diff --git a/kotlin-native/.clang-format b/kotlin-native/.clang-format new file mode 100644 index 00000000000..7102f63f270 --- /dev/null +++ b/kotlin-native/.clang-format @@ -0,0 +1,194 @@ +# Also see codestyle/cpp/README.md +# For documentation on options see: https://releases.llvm.org/8.0.0/tools/clang/docs/ClangFormatStyleOptions.html +# "Kt N/A" means that this C/C++/ObjC construct have no corresponding Kotlin construct to refer to +# "Kt U" means that formatting is unspecified in Kotlin formatting guide +# "Kt " means that this is specified in Kotlin formatting guide with url pointing to it +--- +DisableFormat: false +Standard: Cpp11 + +# Kt N/A. Different from 0 to make modifiers stand out. An alternative is -2, but it introduces another level of indentation. +AccessModifierOffset: -4 +# Kt https://kotlinlang.org/docs/reference/coding-conventions.html#method-call-formatting +AlignAfterOpenBracket: AlwaysBreak +# Kt U. Not touching +AlignConsecutiveAssignments: false +# Kt U. Not touching +AlignConsecutiveDeclarations: false +# Kt N/A. Not touching +AlignEscapedNewlines: DontAlign +# Kt U. Not touching +AlignOperands: false +# Kt U. Not touching +AlignTrailingComments: false +# Kt https://kotlinlang.org/docs/reference/coding-conventions.html#function-formatting +AllowAllParametersOfDeclarationOnNextLine: true +# Kt https://kotlinlang.org/docs/reference/coding-conventions.html#formatting-control-flow-statements +AllowShortBlocksOnASingleLine: false +# Kt U. The closest is https://kotlinlang.org/docs/reference/coding-conventions.html#formatting-control-flow-statements +# Using false, because case statements usually contain at least 2 statements: doing something + break, which makes them multiline +AllowShortCaseLabelsOnASingleLine: false +# Kt https://kotlinlang.org/docs/reference/coding-conventions.html#function-formatting Inline is somewhat close to "single expression" functions +AllowShortFunctionsOnASingleLine: Inline +# Kt U. The closest is https://kotlinlang.org/docs/reference/coding-conventions.html#using-conditional-statements however it mostly refers to the ternary operator. +AllowShortIfStatementsOnASingleLine: true +# Kt U. Same as previous +AllowShortLoopsOnASingleLine: true +# Kt N/A. In Kotlin return type is in a trailing position. +AlwaysBreakAfterReturnType: None +# Kt U. Not touching. +AlwaysBreakBeforeMultilineStrings: false +# Kt N/A. In Kotlin type parameters are declared inline in a much more compact way. +# Using Yes to make it easy to detect function name +AlwaysBreakTemplateDeclarations: Yes +# Kt https://kotlinlang.org/docs/reference/coding-conventions.html#method-call-formatting +BinPackArguments: true +# Kt https://kotlinlang.org/docs/reference/coding-conventions.html#function-formatting +BinPackParameters: false +BraceWrapping: + # Kt https://kotlinlang.org/docs/reference/coding-conventions.html#formatting + AfterClass: false + # Kt https://kotlinlang.org/docs/reference/coding-conventions.html#formatting + AfterControlStatement: false + # Kt https://kotlinlang.org/docs/reference/coding-conventions.html#formatting + AfterEnum: false + # Kt https://kotlinlang.org/docs/reference/coding-conventions.html#formatting + AfterFunction: false + # Kt https://kotlinlang.org/docs/reference/coding-conventions.html#formatting + AfterNamespace: false + # Kt https://kotlinlang.org/docs/reference/coding-conventions.html#formatting + AfterObjCDeclaration: false + # Kt https://kotlinlang.org/docs/reference/coding-conventions.html#formatting + AfterStruct: false + # Kt https://kotlinlang.org/docs/reference/coding-conventions.html#formatting + AfterUnion: false + # Kt https://kotlinlang.org/docs/reference/coding-conventions.html#formatting + AfterExternBlock: false + # Kt https://kotlinlang.org/docs/reference/coding-conventions.html#formatting-control-flow-statements + BeforeCatch: false + # Kt https://kotlinlang.org/docs/reference/coding-conventions.html#formatting-control-flow-statements + BeforeElse: false + # Kt https://kotlinlang.org/docs/reference/coding-conventions.html#formatting + IndentBraces: false + # Only used when AfterFunction is true + SplitEmptyFunction: true + # Only used when AfterRecord is true + SplitEmptyRecord: true + # Only used if AfterNamespace is true + SplitEmptyNamespace: true +# Kt U. Break after operators +BreakBeforeBinaryOperators: None +# Configured by BraceWrapping +BreakBeforeBraces: Custom +# Kt U. Using true because it looks more like an if-expression with "then" and "else" branches marked "?" and ":" +BreakBeforeTernaryOperators: true +# Kt N/A. The closest is https://kotlinlang.org/docs/reference/coding-conventions.html#class-header-formatting AfterColon looks the most consistent +BreakConstructorInitializers: AfterColon +# Kt https://kotlinlang.org/docs/reference/coding-conventions.html#class-header-formatting +BreakInheritanceList: AfterColon +# Kt U. Choosing to break long strings to fit into line length +BreakStringLiterals: true +# Kt U. IDEA displays a vertical guide at 120. Choosing it to avoid very long lines. +ColumnLimit: 140 +# Kt N/A. Probably should use nested namespaces instead. +CompactNamespaces: false +# Kt N/A. The closest is https://kotlinlang.org/docs/reference/coding-conventions.html#class-header-formatting +ConstructorInitializerAllOnOneLineOrOnePerLine: true +# Kt https://kotlinlang.org/docs/reference/coding-conventions.html#formatting +ConstructorInitializerIndentWidth: 4 +# Kt https://kotlinlang.org/docs/reference/coding-conventions.html#formatting IDEA seems to indent continuations with 8 +ContinuationIndentWidth: 8 +# Kt N/A. The closest is https://kotlinlang.org/docs/reference/coding-conventions.html#horizontal-whitespace +# Braced initalizer braces are close to parens in function call or to brackets in array initialier. And styleguide asks not to put spaces in them. +Cpp11BracedListStyle: true +# Configured by PointerAlignment +DerivePointerAlignment: false +# Confgured by BinPack* +ExperimentalAutoDetectBinPacking: false +# Kt N/A. Setting to true because it helps to see when anonymous namespace ends +FixNamespaceComments: true +# Kt U. Not touching manually created including blocks +IncludeBlocks: Preserve +# Kt U. Sorting: main header (priority 0) > system headers > project headers +IncludeCategories: + - Regex: '^<.*' + Priority: 1 + - Regex: '.*' + Priority: 2 +# Kt N/A. Main header must match current filename (modulo extension) exactly. +IncludeIsMainRegex: '$' +# Kt https://kotlinlang.org/docs/reference/coding-conventions.html#formatting-control-flow-statements +IndentCaseLabels: true +# Kt N/A. Do not indent macro code +IndentPPDirectives: None +# Kt https://kotlinlang.org/docs/reference/coding-conventions.html#formatting +IndentWidth: 4 +# Kt U. IDEA seems to indent +IndentWrappedFunctionNames: true +# Kt U. Do not touch. +KeepEmptyLinesAtTheStartOfBlocks: false +# Kt U. IDEA keeps 1 empty line by default. +MaxEmptyLinesToKeep: 1 +# Kt N/A. +NamespaceIndentation: None +# Kt N/A. The closest is https://kotlinlang.org/docs/reference/coding-conventions.html#class-header-formatting +ObjCBinPackProtocolList: Never +# Kt https://kotlinlang.org/docs/reference/coding-conventions.html#formatting +ObjCBlockIndentWidth: 4 +# Kt N/A. Following Google and LLVM styleguides. +ObjCSpaceAfterProperty: false +# Kt N/A. The closest is class inheritance list. Following Google and LLVM styleguides. +ObjCSpaceBeforeProtocolList: true +# Kt N/A. +PointerAlignment: Left +# Kt U. Reflow comments to fit into line width +ReflowComments: true +# Kt U. IDEA does not sort by default, but allows this option. Do not touch. +SortIncludes: false +# Kt U. Like SortIncludes. +SortUsingDeclarations: false +# Kt N/A. +SpaceAfterCStyleCast: false +# Kt N/A. IDEA puts space in `fun ` +SpaceAfterTemplateKeyword: true +# Kt U. https://kotlinlang.org/docs/reference/coding-conventions.html puts spaces +SpaceBeforeAssignmentOperators: true +# Kt N/A. The closest is https://kotlinlang.org/docs/reference/coding-conventions.html#horizontal-whitespace which does not put space before parens and brackets. +SpaceBeforeCpp11BracedList: false +# Kt N/A. The closest is https://kotlinlang.org/docs/reference/coding-conventions.html#colon +SpaceBeforeCtorInitializerColon: true +# Kt https://kotlinlang.org/docs/reference/coding-conventions.html#colon +SpaceBeforeInheritanceColon: true +# Kt https://kotlinlang.org/docs/reference/coding-conventions.html#horizontal-whitespace +SpaceBeforeParens: ControlStatements +# Kt https://kotlinlang.org/docs/reference/coding-conventions.html#horizontal-whitespace +SpaceBeforeRangeBasedForLoopColon: true +# Kt https://kotlinlang.org/docs/reference/coding-conventions.html#horizontal-whitespace +SpaceInEmptyParentheses: false +# Kt U. https://kotlinlang.org/docs/reference/coding-conventions.html uses 1 +SpacesBeforeTrailingComments: 1 +# Kt https://kotlinlang.org/docs/reference/coding-conventions.html#horizontal-whitespace +SpacesInAngles: false +# Kt https://kotlinlang.org/docs/reference/coding-conventions.html#horizontal-whitespace +SpacesInContainerLiterals: false +# Kt N/A. +SpacesInCStyleCastParentheses: false +# Kt https://kotlinlang.org/docs/reference/coding-conventions.html#horizontal-whitespace +SpacesInParentheses: false +# Kt https://kotlinlang.org/docs/reference/coding-conventions.html#horizontal-whitespace +SpacesInSquareBrackets: false +# Kt https://kotlinlang.org/docs/reference/coding-conventions.html#formatting +TabWidth: 4 +# Kt https://kotlinlang.org/docs/reference/coding-conventions.html#formatting +UseTab: Never + +PenaltyBreakAssignment: 2 +PenaltyBreakBeforeFirstCallParameter: 1 +PenaltyBreakComment: 300 +PenaltyBreakFirstLessLess: 120 +PenaltyBreakString: 1000 +PenaltyBreakTemplateDeclaration: 10 +PenaltyExcessCharacter: 1000000 +PenaltyReturnTypeOnItsOwnLine: 200 +... + diff --git a/kotlin-native/.gitignore b/kotlin-native/.gitignore new file mode 100644 index 00000000000..2903a0401ea --- /dev/null +++ b/kotlin-native/.gitignore @@ -0,0 +1,74 @@ +.DS_Store +.idea/shelf +*.iml +/dependencies/all +dist +kotlin-native-*.tar.gz +kotlin-native-*.zip +translator/src/test/kotlin/tests/*/linked +out +tmp +workspace.xml +*.versionsBackup + +local.properties +.gradle +build +translator/.gradle/2.9/taskArtifacts + +kotstd/kotstd.iml + +# test suit products. +*.bc +*.bc.o +*.kt.S +*.kt.exe +*.log +test.output +*.kexe + +# Ignore Gradle GUI config +gradle-app.setting + +# Avoid ignoring Gradle wrapper jar file (.jar files are usually ignored) +!gradle-wrapper.jar + +# Cache of project +.gradletasknamecache + +# local project files +lib/ +.idea/ +proto/compiler/protoc-artifacts +proto/compiler/tests + +proto/compiler/google/src/google/protobuf/compiler/kotlin/bin +proto/compiler/google/src/google/protobuf/compiler/kotlin/protoc + +peformance/build + +# translator auto generated artifacts +kotstd/ll + +# test teamcity property: commitable only with -f +backend.native/tests/teamcity-test.property + +# Sample output +samples/**/*.kt.bc-build +samples/androidNativeActivity/Polyhedron + +# CMake +llvmCoverageMappingC/CMakeLists.txt +tools/performance-server/node_modules +tools/performance-server/server +tools/performance-server/ui/js +runtime/cmake-build-debug/ + +# compilation database +compile_commands.json + +# clangd caches +.clangd/ + +# googletest framework used by runtime tests +runtime/googletest/ \ No newline at end of file diff --git a/kotlin-native/BUILDING_LLVM.md b/kotlin-native/BUILDING_LLVM.md new file mode 100644 index 00000000000..f91b5087727 --- /dev/null +++ b/kotlin-native/BUILDING_LLVM.md @@ -0,0 +1,65 @@ +# Building Apple LLVM for Kotlin/Native + +This document describes how to compile LLVM distribution and use it to build Kotlin/Native on macOS. +Usually, you don't need to compile LLVM by yourself: +* If you use Kotlin/Native compiler it will download LLVM on the first run. +* If you contribute to kotlin-native repository then use `:dependencies:update` Gradle task. + +But if you don't want to download prebuilt LLVM or want to experiment with your own distribution, +you came to the right place. + +## Part 1. Building the right LLVM version for macOS. + +For macOS host we use LLVM from [Apple downstream](https://github.com/apple/llvm-project). +Branch is [**apple/stable/20190104**](https://github.com/apple/llvm-project/tree/apple/stable/20190104) +because it is similar (or even the same) to what Apple ships with Xcode 11.*. +After cloning the repo and changing the branch we perform the following steps to build LLVM toolchain: + +```bash +mkdir build + +cd build + +cmake -DLLVM_ENABLE_PROJECTS="clang;lld;libcxx;libcxxabi" \ + -DCMAKE_BUILD_TYPE=Release \ + -DLLVM_ENABLE_ASSERTIONS=Off \ + -G Ninja \ + -DCMAKE_INSTALL_PREFIX=clang-llvm-apple-8.0.0-darwin-macos \ + ../llvm + +ninja install +``` + +After these steps `clang-llvm-apple-8.0.0-darwin-macos` directory will contain LLVM distribution that is suitable for building Kotlin/Native. + +## Part 2. Building Kotlin/Native against given LLVM distribution. + +By default, Kotlin/Native will try to download LLVM distribution from CDN if it is not present in `$HOME/.konan/dependencies` folder. +There are two ways to bypass this behaviour. + +#### Option A. Substitute prebuilt distribution. +This option doesn't require you to edit compiler sources, but a bit harder. + +The compiler checks dependency presence by reading contents of `$HOME/.konan/dependencies/.extracted` file. +So to avoid LLVM downloading, we should manually add a record to the `.extracted` file: +1. Create `$HOME/.konan/dependencies/.extracted` file if it is not created. +2. Add `clang-llvm-apple-8.0.0-darwin-macos` line. + +and put `clang-llvm-apple-8.0.0-darwin-macos` directory from the Part 1 to `$HOME/.konan/dependencies/`. + +#### Option B. Provide an absolute path to the distribution. +This option requires user to edit [konan.properties file](konan/konan.properties). +Set `llvmHome.` to an absolute path to your LLVM distribution and +set `llvmVersion.` to its version. +For example, provide a path to `clang-llvm-apple-8.0.0-darwin-macos` from the Part 1 and set version to 8.0.0. + +Now we are ready to build Kotlin/Native itself. The process is described in [README.md](README.md). +Please note that we still need to run `./gradlew dependencies:update` to download other dependencies (e.g. libffi). + +## Q&A + +— Can I override `.konan` location? +— Yes, by setting `$KONAN_DATA_DIR` environment variable. See [HACKING.md](HACKING.md#compiler-environment-variables). + +- Can I use another LLVM distribution without rebuilding Kotlin/Native? +- Yes, see [HACKING.md](HACKING.md#using-different-llvm-distributions-as-part-of-kotlinnative-compilation-pipeline). \ No newline at end of file diff --git a/kotlin-native/CHANGELOG.md b/kotlin-native/CHANGELOG.md new file mode 100644 index 00000000000..90c926bd0a6 --- /dev/null +++ b/kotlin-native/CHANGELOG.md @@ -0,0 +1,295 @@ +# 1.4.10 (Sep 2020) + * Fixed a newline handling in @Deprecated annotation in ObjCExport ([KT-39206](https://youtrack.jetbrains.com/issue/KT-39206)) + * Fixed suspend function types in ObjCExport ([KT-40976](https://youtrack.jetbrains.com/issue/KT-40976)) + * Fixed support for unsupported C declarations in cinterop ([KT-39762](https://youtrack.jetbrains.com/issue/KT-39762)) + +# v1.4.0 (Aug 2020) + * Objective-C/Swift interop: + * Reworked exception handling ([GH-3822](https://github.com/JetBrains/kotlin-native/pull/3822), [GH-3842](https://github.com/JetBrains/kotlin-native/pull/3842)) + * Enabled support for Objective-C generics by default ([GH-3778](https://github.com/JetBrains/kotlin-native/pull/3778)) + * Support for Kotlin’s suspending functions ([GH-3915](https://github.com/JetBrains/kotlin-native/pull/3915)) + * Handle variadic block types in ObjC interop ([`KT-36766`](https://youtrack.jetbrains.com/issue/KT-36766)) + * Added native-specific frontend checkers (implemented in the main Kotlin repository: [GH-3293](https://github.com/JetBrains/kotlin/pull/3293), [GH-3091](https://github.com/JetBrains/kotlin/pull/3091), [GH-3172](https://github.com/JetBrains/kotlin/pull/3172)) + * .dSYMs for release binaries on Apple platforms ([GH-4085](https://github.com/JetBrains/kotlin-native/pull/4085)) + * Improved compilation time of builds with interop libraries by reworking cinterop under the hood. + * Experimental mimalloc allocator support (-Xallocator=mimalloc) to improve execution time performance. ([GH-3704](https://github.com/JetBrains/kotlin-native/pull/3704)) + * Tune GC to improve execution time performance + * Various fixes to compiler caches and Gradle daemon usage + +# v1.3.72 (April 2020) + * Fix ios_x64 platform libs cache for iOS 11 and 12 (GH-4071) + +# v1.3.71 (March 2020) + * Fix `lazy {}` memory leak regression ([`KT-37232`](https://youtrack.jetbrains.com/issue/KT-37232), GH-3944) + * Fix using cached Kotlin subclasses of Objective-C classes (GH-3986) + +# v1.3.70 (Dec 2019) + * Support compiler caches for debug mode (GH-3650) + * Support running Kotlin/Native compiler from Gradle daemon (GH-3442) + * Support multiple independent Kotlin frameworks in the same application (GH-3457) + * Compile-time allocation for some singleton objects (GH-3645) + * Native support for SIMD vector types in compiler and interop (GH-3498) + * API for runtime detector of cyclic garbage (GH-3616) + * Commonized StringBuilder (GH-3593) and Float.rangeTo (KT-35299) + * Fix interop with localized strings (GH-3562) + * Provide utility for user-side generation of platform libraries (GH-3538) + * On-stack allocation using local escape analysis (GH-3625) + * Code coverage support on Linux and Windows (GH-3403) + * Debugging experience improvements (GH-3561, GH-3638, GH-3606) + +# v1.3.60 (Oct 2019) + * Support XCode 11 + * Switch to LLVM 8.0 + * New compiler targets: + * watchOS targets, watchos_x86, watchos_arm64 and watchos_arm32 (GH-3323, GH-3404, GH-3344) + * tvOS targets tvos_x64 and tvos_arm64 (GH-3303, GH-3363) + * native Android targets android_x86 and android_x64 (GH-3306, GH-3314) + * Standard CLI library kotlinx.cli is shipped with the compiler distribution (GH-3215) + * Improved debug information for inline functions (KT-28929, GH-3292) + * Improved runtime performance of interface calls, up to 5x faster (GH-3377) + * Improved runtime performance of type checks, up to 50x faster (GH-3291) + * Produce native binaries directly from klibs, speeds up large project compilation (GH-3246) + * Supported arbitrary (up to 255 inclusive) function arity (GH-3253) + * Supported callable references to suspend functions (GH-3197) + * Implemented experimental -Xg0 switch, symbolication of release binaries for iOS (GH-3233, GH-3367) + * Interop: + * Allow passing untyped null as variadic function's parameter (GH-3312, KT-33525) + * Standard library: + * Allow scheduling jobs in arbitrary K/N context, not only Worker (GH-3316) + * Important bug fixes: + * Boxed negative values can lead to crashes on ios_arm64 (GH-3296) + * Implemented thread-safe tracking of Objective-C references to Kotlin objects (GH-3267) + +# v1.3.50 (Aug 2019) + * Kotlin/Native versioning now aligned with Kotlin versioning + * Exhaustive platform libraries on macOS (GH-3141) + * Update to Gradle 5.5 (GH-3166) + * Improved debug information correctness (GH-3130) + * Major memory manager refactoring (GH-3129) + * Embed actual bitcode in produced frameworks (GH-2974) + * Compilation speed improvements + * Interop: + * Support kotlin.Deprecated when producing framework (GH-3114) + * Ensure produced Objective-C header does not have warnings (GH-3101) + * Speed up interop stub generator (GH-3082, GH-3050) + * getOriginalKotlinClass() to get KClass for Kotlin classes in Objective-C (GH-3036) + * Supported nullable primitive types in reverse C interop (GH-3198) + * Standard library + * API for delayed job execution on worker (GH-2971) + * API for running via worker's job queue (GH-3078) + * MonoClock and Duration support (GH-3028) + * Support typeOf (KT-29917, KT-28625) + * New zero-terminated utf8 to String conversion API (GH-3116) + * Optimize StringBuilder for certain cases (GH-3202) + * Implemented Array.fill API (GH-3244) + +# v1.3.0 (Jun 2019) + * CoreLocation platform library on macOS (GH-3041) + * Converting Unit type to Void during producing framework for Objective-C/Swift (GH-2549, GH-1271) + * Support linux/arm64 targets (GH-2917) + * Performance improvements of memory manager (GH-2813) + * FreezableAtomicReference prototype (GH-2776) + * Logging and error messages enhancements + * Interop: + * Support nullable String return type in reverse C interop (GH-2956) + * Support setting custom exception hook in reverse C interop (GH-2941) + * Experimental generics support for produced frameworks for Objective-C/Swift implemented by Kevin Galligan (GH-2850) + * Improve support for Objective-C methods clashing with methods of Any (GH-2914) + * Support variadic Objective-C functions (GH-2896) + +# v1.2.1 (Apr 2019) + * Fix Objective-C interop with React (GH-2872) + * Fix “not in vtable” compiler crash when generating frameworks (GH-2865) + * Implement some optimizations (GH-2854) + * Fix release build for 32-bit Windows (GH-2848) + * Fix casts to type parameters with multiple bounds (GH-2888) + * Fix “could not get descriptor uniq id for deserialized class FlagEnum” compiler crash when generating framework (GH-2874) + +# v1.2.0 (Apr 2019) + * New intermediate representation based library format allowing global optimizations + * Exception backtraces in debug mode on macOS and iOS targets contains symbolic information + * Support for 32-bit Windows targets (target mingw_x86) + * Support for cross-compilation to Linux (x86-64 and arm32) from macOS and Windows hosts + * Static Apple frameworks can be produced + * Support Gradle 5.1 + * Fix alignment-related issues on ARM32 and MIPS platforms + * Write unhandled exceptions stacktrace on device to iOS crash log + * Fix undefined behavior in some arithmetic operations + * Interop: + * Get rid of libffi dependency + * Support returning struct from C callbacks + * Support passing Kotlin strings to C interop functions accepting UTF-32 arguments + * Fix bool conversion + * Support variable length arrays + * Provide Kotlin access to C compiler intrinsics via platform.builtins package + * Support clang modules (for Objective-C only) + * Experimental integration with CocoaPods + * IDE + * Kotlin/Native plugin is supported in CLion 2018.3 and AppCode/CLion 2019.1 + * Basic highlighting support for .def files + * Navigation to source files from exception backtrace + +## v1.1.0 (Dec 2018) + * Performance optimizations: + * runtime: optimization of queue of finalization + * compiler: loop generation optimization + * compiler: reduce RTTI size + * runtime: reduce size of the object header + * Contracts support + * Regex engine: fix quantifier processing + +## v0.9.3 (Sep 2018) + * Bugfixes + +## v0.9.2 (Sep 2018) + * Support Xcode 10.0 + * iOS 9.0 is the minimal supported version for all targets + * Swift interop improvements + * Support shared top level values of some immutable types (i.e. String and atomic references) + * Support release Kotlin 1.3.0 + +## v0.9.1 (Sep 2018) + * Improve naming in produced Objective-C frameworks. Use ‘Kotlin’ prefix instead of ‘Stdlib’ prefix. + * Improvements in KLIB: Library versioning, IDEA-friendly internal format. + +# v0.9 (Sep 2018) + * Support Kotlin 1.3M2 + * Note: Common modules of multiplatform projects also should use Kotlin 1.3 + * Major standard library (native parts) rework and rename + * New Gradle plugin with multiplatform integration and reworked DSL + * Support unsigned types in Kotlin and interop + * Support non-experimental coroutines API (kotlin.coroutines) + * Top level object var/val can only be accessed from the main thread + * Support lazy properties in singleton objects + * Update LLVM to 6.0.1 + +## v0.8 (Jul 2018) + * Singleton objects are frozen after creation, and shared between threads + * String and primitives types are frozen by default + * Common stdlib with Kotlin/JVM and Kotlin/JS + * Implemented `kotlin.random.*` and `Collection.shuffle` + * Implemented atomic integers and atomic references + * Multiple bugfixes in compiler (coroutines, inliner) + * Support 32-bit iOS (target `ios_arm32`) + * New experimental Gradle plugin + * Support Xcode 9.4.1 + * Optimizations (switch by enum, memory management) + +## v0.7.1 (Jun 2018) + * Bugfixes in the runtime (indexOf, GC for kotlin.Array, enum equality) and the compiler + * Fix NSBlock problem, preventing upload of binaries to the AppStore + * Create primitive type boxes and kotlin.String as frozen by default + * Support Gradle 4.7, provide separate run task for each executable + * Support Xcode 9.4 and CoreML and ClassKit frameworks on Apple platforms + * Improved runtime Kotlin variable examination + * Minor performance optimizations in compiled code and runtime + * Add `disableDesignatedInitializerChecks` definition file support + +## v0.7 (May 2018) + * Interop with Objective-C/Swift changes: + * Uniform direct and reverse interops (values could be passed in both directions now) + * Interop by exceptions + * Type conversion and checks (`as`, `is`) for interop types + * Seamless interop on numbers, strings, lists, maps and sets + * Better interop on constructors and initializers + * Switched to Xcode 9.3 on Apple platforms + * Introduced object freezing API, frozen object could be used from multiple threads + * Kotlin enums are frozen by default + * Switch to Gradle 4.6 + * Use Gradle native dependency model, allowing to use `.klib` as Maven artifacts + * Introduced typed arrays API + * Introduced weak references API + * Activated global devirtualization analysis + * Performance improvements (box caching, bridge inlining, others) + +## v0.6.2 (Mar 2018) + * Support several `expectedBy`-dependencies in Gradle plugin. + * Improved interaction between Gradle plugin and IDE. + * Various bugfixes + +## v0.6.1 (Mar 2018) + * Various bugfixes + * Support total ordering in FP comparisons + * Interop generates string constants from string macrodefinitions + * STM32 blinky demo in pure Kotlin/Native + * Top level variables initialization redesign (proper dependency order) + * Support kotlin.math on WebAssembly targets + * Support embedded targets on Windows hosts + +## v0.6 (Feb 2018) + * Support multiplatform projects (expect/actual) in compiler and Gradle plugin + * Support first embedded target (STM32 board) + * Support Kotlin 1.2.20 + * Support Java 9 + * Support Gradle 4.5 + * Transparent Objective-C/Kotlin container classes interoperability + * Produce optimized WebAssembly binaries (10x smaller than it used to be) + * Improved APIs for object transfer between threads and workers + * Allow exporting top level C function in reverse interop with @CName annotation + * Supported debugging of code with inline functions + * Multiple bugfixes and performance optimizations + +## v0.5 (Dec 2017) + * Reverse interop allowing to call Kotlin/Native code compiled as framework from Objective-C/Swift programs + * Reverse interop allowing to call Kotlin/Native code compiled as shared object from C/C++ programs + * Support generation of shared objects and DLLs by the compiler + * Migration to LLVM 5.0 + * Support WebAssembly target on Linux and Windows hosts + * Make string conversions more robust + * Support kotlin.math package + * Refine workers and string conversion APIs + +## v0.4 (Nov 2017) ## + * Objective-C frameworks interop for iOS and macOS targets + * Platform API libraries for Linux, iOS, macOS and Windows + * Kotlin 1.2 supported + * `val` and function parameters can be inspected in debugger + * Experimental support for WebAssembly (wasm32 target) + * Linux MIPS support (little and big endian, mips and mipsel targets) + * Gradle plugin DSL fully reworked + * Support for unit testing annotations and automatic test runner generation + * Final executable size reduced + * Various interop improvements (forward declaration, better handling of unsupported types) + * Workers object subgraph transfer checks implemented + * Optimized low level memory management using more efficient cycle tracing algorithm + +## v0.3.4 (Oct 2017) ## + * Intermediate release + +## v0.3.2 (Sep 2017) ## + * Bug fixes + +## v0.3.1 (Aug 2017) ## + * Improvements in C interop tools (function pointers, bitfields, bugfixes) + * Improvements to Gradle plugin and dependency downloader + * Support for immutable data linked into an executable via ImmutableDataBlob class + * Kotlin 1.1.4 supported + * Basic variable inspection support in the debugger + * Some performance improvements ("for" loops, memory management) + * .klib improvements (keep options from .def file, faster inline handling) + * experimental workers API added (see [`sample`](https://github.com/JetBrains/kotlin-native/blob/master/samples/workers)) + +## v0.3 (Jun 2017) ## + * Preliminary support for x86-64 Windows hosts and targets + * Support for producing native activities on 32- and 64-bit Android targets + * Extended standard library (bitsets, character classification, regular expression) + * Preliminary support for Kotlin/Native library format (.klib) + * Preliminary source-level debugging support (stepping only, no variable inspection) + * Compiler switch `-entry` to select entry point + * Symbolic backtrace in runtime for unstripped binaries, for all supported targets + +## v0.2 (May 2017) ## + * Added support for coroutines + * Fixed most stdlib incompatibilities + * Improved memory management performance + * Cross-module inline function support + * Unicode support independent from installed system locales + * Interoperability improvements + * file-based filtering in definition file + * stateless lambdas could be used as C callbacks + * any Unicode string could be passed to C function + * Very basic debugging support + * Improve compilation and linking performance + +## v0.1 (Mar 2017) ## +Initial technical preview of Kotlin/Native diff --git a/kotlin-native/COCOAPODS.md b/kotlin-native/COCOAPODS.md new file mode 100644 index 00000000000..4b84d581754 --- /dev/null +++ b/kotlin-native/COCOAPODS.md @@ -0,0 +1,310 @@ +# CocoaPods integration + +Kotlin/Native provides integration with the [CocoaPods dependency manager](https://cocoapods.org/). You can add +dependencies on Pod libraries stored in the CocoaPods repository or locally as well as use a multiplatform project with +native targets as a CocoaPods dependency (Kotlin Pod). + +You can manage Pod dependencies directly in IntelliJ IDEA and enjoy all the additional features such as code highlighting +and completion. You can build the whole Kotlin project with Gradle and not ever have to switch to Xcode. +Use Xcode only when you need to write Swift/Objective-C code or run your application on a simulator or device. + +Depending on your project and purposes, you can add dependencies between: +* [A Kotlin project and a Pod library from the CocoaPods repository](#add-a-dependency-on-a-pod-library-from-the-cocoapods-repository) +* [A Kotlin project and a Pod library stored locally](#add-a-dependency-on-a-pod-library-stored-locally) +* [A Kotlin Pod and an Xcode project with one target](#add-a-dependency-between-a-kotlin-pod-and-xcode-project-with-one-target) +or [several targets](#add-a-dependency-between-a-kotlin-pod-with-an-xcode-project-with-several-targets) + +>You can also add dependencies between a Kotlin Pod and multiple Xcode projects. However, in this case you need to add a +>dependency by calling `pod install` manually for each Xcode project. In other cases, it's done automatically. +{:.note} + +## Install the CocoaPods dependency manager and plugin + +1. Install the [CocoaPods dependency manager](https://cocoapods.org/). + +
+ + ```ruby + $ sudo gem install cocoapods + ``` + +
+ +2. Install the [`cocoapods-generate`](https://github.com/square/cocoapods-generate) plugin. + +
+ + ```ruby + $ sudo gem install cocoapods-generate + ``` + +
+ +3. In `build.gradle.kts` (or `build.gradle`) of your IDEA project, apply the CocoaPods plugin as well as the Kotlin + Multiplatform plugin. + +
+ + ```kotlin + plugins { + kotlin("multiplatform") version "{{ site.data.releases.latest.version }}" + kotlin("native.cocoapods") version "{{ site.data.releases.latest.version }}" + } + ``` + +
+ +4. Configure `summary`, `homepage`, and `frameworkName`of the `Podspec` file in the `cocoapods` block. +`version` is a version of the Gradle project. + +
+ + ```kotlin + plugins { + kotlin("multiplatform") version "{{ site.data.releases.latest.version }}" + kotlin("native.cocoapods") version "{{ site.data.releases.latest.version }}" + } + + // CocoaPods requires the podspec to have a version. + version = "1.0" + + kotlin { + cocoapods { + // Configure fields required by CocoaPods. + summary = "Some description for a Kotlin/Native module" + homepage = "Link to a Kotlin/Native module homepage" + + // You can change the name of the produced framework. + // By default, it is the name of the Gradle project. + frameworkName = "my_framework" + } + } + ``` + +
+ +5. Re-import the project. + +When applied, the CocoaPods plugin does the following: + +* Adds both `debug` and `release` frameworks as output binaries for all macOS, iOS, tvOS, and watchOS targets. +* Creates a `podspec` task which generates a [Podspec](https://guides.cocoapods.org/syntax/podspec.html) +file for the project. + +The `Podspec` file includes a path to an output framework and script phases that automate building this framework during +the build process of an Xcode project. + +## Add dependencies on Pod libraries + +You can add dependencies between a Kotlin project and Pod libraries [stored in the CocoaPods repository](#add-a-dependency-on-a-pod-library-from-the-cocoapods-repository) +and [stored locally](#add-a-dependency-on-a-pod-library-stored-locally). + +[Complete the initial configuration](#install-the-cocoapods-dependency-manager-and-plugin), and when you add a new +dependency and re-import the project in IntelliJ IDEA; the new dependency will be added automatically. There are no +additional steps required. + +### Add a dependency on a Pod library from the CocoaPods repository + +1. Add dependencies on a Pod library that you want to use from the CocoaPods repository with `pod()` to `build.gradle.kts` +(`build.gradle`) of your project. + > You can also add dependencies on subspecs. + {:.note} > + +
+ + ```kotlin + kotlin { + ios() + + cocoapods { + summary = "CocoaPods test library" + homepage = "https://github.com/JetBrains/kotlin" + pod("AFNetworking", "~> 4.0.0") + + pod("SDWebImage/MapKit") + } + } + ``` + +
+ +2. Re-import the project. + +To use these dependencies from the Kotlin code, import the packages `cocoapods.`. + +
+ +```kotlin +import cocoapods.AFNetworking.* +import cocoapods.SDWebImage.* +``` + +
+ +You can find a sample project [here](https://github.com/Kotlin/kotlin-with-cocoapods-sample). + +### Add a dependency on a Pod library stored locally + +1. Add a dependency on a Pod library stored locally with `pod()` to `build.gradle.kts` (`build.gradle`) of your + project. +As the third parameter, specify the path to `Podspec` of the local Pod using `project.file(..)`. + > You can add local dependencies on subspecs as well. + > The `cocoapods` block can include dependencies to Pods stored locally and Pods from the CocoaPods repository at + > the same time. + {:.note} + +
+ + ```kotlin + kotlin { + ios() + + cocoapods { + summary = "CocoaPods test library" + homepage = "https://github.com/JetBrains/kotlin" + pod("pod_dependency", "1.0", project.file("../pod_dependency/pod_dependency.podspec")) + pod("subspec_dependency/Core", "1.0", project.file("../subspec_dependency/subspec_dependency.podspec")) + + pod("AFNetworking", "~> 4.0.0") + pod("SDWebImage/MapKit") + } + } + ``` + +
+ +2. Re-import the project. + +If you want to use dependencies on local pods from Kotlin code, import the corresponding packages. + +
+ +```kotlin +import cocoapods.pod_dependency.* +import cocoapods.subspec_dependency.* +``` + +
+ +You can find a sample project [here](https://github.com/Kotlin/kotlin-with-cocoapods-sample). + +## Use a Kotlin Gradle project as a CocoaPods dependency + +You can use a Kotlin Multiplatform project with native targets as a CocoaPods dependency (Kotlin Pod). You can include such a dependency +in the Podfile of the Xcode project by its name and path to the project directory containing the generated Podspec. +This dependency will be automatically built (and rebuilt) along with this project. +Such an approach simplifies importing to Xcode by removing a need to write the corresponding Gradle tasks and Xcode build steps manually. + + +You can add dependencies between: +* [A Kotlin Pod and an Xcode project with one target](#add-a-dependency-between-a-kotlin-pod-and-xcode-project-with-one-target) +* [A Kotlin Pod and an Xcode project with several targets](#add-a-dependency-between-a-kotlin-pod-with-an-xcode-project-with-several-targets) + +> To correctly import the dependencies into the Kotlin/Native module, the +`Podfile` must contain either [`use_modular_headers!`](https://guides.cocoapods.org/syntax/podfile.html#use_modular_headers_bang) +or [`use_frameworks!`](https://guides.cocoapods.org/syntax/podfile.html#use_frameworks_bang) +directive. +{:.note} + +### Add a dependency between a Kotlin Pod and Xcode project with one target + +1. Create an Xcode project with a `Podfile` if you haven’t done so yet. +2. Add the path to your Xcode project `Podfile` with `podfile = project.file(..)` to `build.gradle.kts` (`build.gradle`) +of your Kotlin project. + This step helps synchronize your Xcode project with Kotlin Pod dependencies by calling `pod install` for your `Podfile`. +3. Specify the minimum target version for the Pod library. + > If you don't specify the minimum target version and a dependency Pod requires a higher deployment target, you may get an error. + {:.note} + +
+ + ```kotlin + kotlin { + ios() + + cocoapods { + summary = "CocoaPods test library" + homepage = "https://github.com/JetBrains/kotlin" + ios.deploymentTarget = "13.5" + pod("AFNetworking", "~> 4.0.0") + podfile = project.file("../ios-app/Podfile") + } + } + ``` + +
+ +4. Add the name and path of the Kotlin Pod you want to include in the Xcode project to `Podfile`. + +
+ + ```ruby + use_frameworks! + + platform :ios, '9.0' + + target 'ios-app' do + pod 'kotlin_library', :path => '../kotlin-library' + end + ``` + +
+ +5. Re-import the project. + +### Add a dependency between a Kotlin Pod with an Xcode project with several targets + +1. Create an Xcode project with a `Podfile` if you haven’t done so yet. +2. Add the path to your Xcode project `Podfile` with `podfile = project.file(..)` to `build.gradle.kts` (`build.gradle`) of + your Kotlin project. + This step helps synchronize your Xcode project with Kotlin Pod dependencies by calling `pod install` for your `Podfile`. +3. Add dependencies to the Pod libraries that you want to use in your project with `pod()`. +4. For each target, specify the minimum target version for the Pod library. + +
+ + ```kotlin + kotlin { + ios() + tvos() + + cocoapods { + summary = "CocoaPods test library" + homepage = "https://github.com/JetBrains/kotlin" + ios.deploymentTarget = "13.5" + tvos.deploymentTarget = "13.4" + + pod("AFNetworking", "~> 4.0.0") + podfile = project.file("../severalTargetsXcodeProject/Podfile") // specify the path to Podfile + } + } + ``` + +
+ +5. Add the name and path of the Kotlin Pod you want to include in the Xcode project to the `Podfile`. + +
+ + ```ruby + target 'iosApp' do + use_frameworks! + platform :ios, '13.5' + # Pods for iosApp + pod 'kotlin_library', :path => '../kotlin-library' + end + + target 'TVosApp' do + use_frameworks! + platform :tvos, '13.4' + + # Pods for TVosApp + pod 'kotlin_library', :path => '../kotlin-library' + end + ``` + +
+ +6. Re-import the project. + +You can find a sample project [here](https://github.com/Kotlin/multitarget-xcode-with-kotlin-cocoapods-sample). \ No newline at end of file diff --git a/kotlin-native/CODE_COVERAGE.md b/kotlin-native/CODE_COVERAGE.md new file mode 100644 index 00000000000..2f7b5e0bff4 --- /dev/null +++ b/kotlin-native/CODE_COVERAGE.md @@ -0,0 +1,67 @@ +# Code Coverage +Kotlin/Native has a code coverage support that is based on Clang's +[Source-based Code Coverage](https://clang.llvm.org/docs/SourceBasedCodeCoverage.html). + +**Please note**: +1. Coverage support is in it's very early days and is in active development. Known issues are: + * Coverage information may be inaccurate. + * Line execution counts may be wrong. + +2. Most of described functionality will be incorporated into Gradle plugin. + +### Usage + +#### TL;DR +```bash +kotlinc-native main.kt -Xcoverage +./program.kexe +llvm-profdata merge program.kexe.profraw -o program.profdata +llvm-cov report program.kexe -instr-profile program.profdata +``` + +#### Compiling with coverage enabled + +There are 2 compiler flags that allows to generate coverage information: +* `-Xcoverage`. Generate coverage for immediate sources. +* `-Xlibrary-to-cover=`. Generate coverage for specified `klib`. +Note that library also should be either linked via `-library/-l` compiler option or be a transitive dependency. + +#### Running covered executable + +After the execution of the compiled binary (ex. `program.kexe`) `program.kexe.profraw` will be generated. +By default it will be generated in the same location where binary was created. The are two ways to override this behavior: + * `-Xcoverage-file=` compiler flag. + * `LLVM_PROFILE_FILE` environment variable. So if you run your program like this: +``` +LLVM_PROFILE_FILE=build/program.profraw ./program.kexe +``` +Then the coverage information will be stored to the `build` dir as `program.profraw`. + +#### Parsing `*.profraw` + +Generated file can be parsed with `llvm-profdata` utility. Basic usage: +``` +llvm-profdata merge default.profraw -o program.profdata +``` +See [command guide](http://llvm.org/docs/CommandGuide/llvm-profdata.html) for more options. + +#### Creating reports + +The last step is to create a report from the `program.profdata` file. +It can be done with `llvm-cov` utility (refer to [command guide](http://llvm.org/docs/CommandGuide/llvm-cov.html) for detailed usage). +For example, we can see a basic report using: +``` +llvm-cov report program.kexe -instr-profile program.profdata +``` +Or show a line-by-line coverage information in html: +``` +llvm-cov show program.kexe -instr-profile program.profdata -format=html > report.html +``` + +### Sample +Usually coverage information is collected during running of the tests. +Please refer to `samples/coverage` to see how it can be done. + + +### Useful links +* [LLVM Code Coverage Mapping Format](https://llvm.org/docs/CoverageMappingFormat.html) \ No newline at end of file diff --git a/kotlin-native/CONCURRENCY.md b/kotlin-native/CONCURRENCY.md new file mode 100644 index 00000000000..21b340cb9fb --- /dev/null +++ b/kotlin-native/CONCURRENCY.md @@ -0,0 +1,222 @@ +## Concurrency in Kotlin/Native + + Kotlin/Native runtime doesn't encourage a classical thread-oriented concurrency + model with mutually exclusive code blocks and conditional variables, as this model is + known to be error-prone and unreliable. Instead, we suggest a collection of + alternative approaches, allowing you to use hardware concurrency and implement blocking IO. + Those approaches are as follows, and they will be elaborated on in further sections: + * Workers with message passing + * Object subgraph ownership transfer + * Object subgraph freezing + * Object subgraph detachment + * Raw shared memory using C globals + * Atomic primitives and references + * Coroutines for blocking operations (not covered in this document) + +### Workers + + Instead of threads Kotlin/Native runtime offers the concept of workers: concurrently executed + control flow streams with an associated request queue. Workers are very similar to the actors + in the Actor Model. A worker can exchange Kotlin objects with another worker, so that at any moment + each mutable object is owned by a single worker, but ownership can be transferred. + See section [Object transfer and freezing](#transfer). + + Once a worker is started with the `Worker.start` function call, it can be addressed with its own unique integer + worker id. Other workers, or non-worker concurrency primitives, such as OS threads, can send a message + to the worker with the `execute` call. + +
+ + ```kotlin +val future = execute(TransferMode.SAFE, { SomeDataForWorker() }) { + // data returned by the second function argument comes to the + // worker routine as 'input' parameter. + input -> + // Here we create an instance to be returned when someone consumes result future. + WorkerResult(input.stringParam + " result") +} + +future.consume { + // Here we see result returned from routine above. Note that future object or + // id could be transferred to another worker, so we don't have to consume future + // in same execution context it was obtained. + result -> println("result is $result") +} +``` + +
+ + The call to `execute` uses a function passed as its second parameter to produce an object subgraph + (i.e. set of mutually referring objects) which is then passed as a whole to that worker, it is then no longer + available to the thread that initiated the request. This property is checked if the first parameter + is `TransferMode.SAFE` by graph traversal and is just assumed to be true, if it is `TransferMode.UNSAFE`. + The last parameter to `execute` is a special Kotlin lambda, which is not allowed to capture any state, + and is actually invoked in the target worker's context. Once processed, the result is transferred to whatever consumes + it in the future, and it is attached to the object graph of that worker/thread. + + If an object is transferred in `UNSAFE` mode and is still accessible from multiple concurrent executors, + program will likely crash unexpectedly, so consider that last resort in optimizing, not a general purpose + mechanism. + + For a more complete example please refer to the [workers example](https://github.com/JetBrains/kotlin-native/tree/master/samples/workers) + in the Kotlin/Native repository. + + +### Object transfer and freezing + + An important invariant that Kotlin/Native runtime maintains is that the object is either owned by a single + thread/worker, or it is immutable (_shared XOR mutable_). This ensures that the same data has a single mutator, + and so there is no need for locking to exist. To achieve such an invariant, we use the concept of not externally + referred object subgraphs. + This is a subgraph which has no external references from outside of the subgraph, which could be checked + algorithmically with O(N) complexity (in ARC systems), where N is the number of elements in such a subgraph. + Such subgraphs are usually produced as a result of a lambda expression, for example some builder, and may not + contain objects, referred to externally. + + Freezing is a runtime operation making a given object subgraph immutable, by modifying the object header + so that future mutation attempts throw an `InvalidMutabilityException`. It is deep, so + if an object has a pointer to other objects - transitive closure of such objects will be frozen. + Freezing is a one way transformation, frozen objects cannot be unfrozen. Frozen objects have a nice + property that due to their immutability, they can be freely shared between multiple workers/threads + without breaking the "mutable XOR shared" invariant. + + If an object is frozen it can be checked with an extension property `isFrozen`, and if it is, object sharing + is allowed. Currently, Kotlin/Native runtime only freezes the enum objects after creation, although additional + autofreezing of certain provably immutable objects could be implemented in the future. + + +### Object subgraph detachment + + An object subgraph without external references can be disconnected using `DetachedObjectGraph` to + a `COpaquePointer` value, which could be stored in `void*` data, so the disconnected object subgraphs + can be stored in a C data structure, and later attached back with `DetachedObjectGraph.attach()` in an arbitrary thread + or a worker. Combining it with [raw memory sharing](#shared) it allows side channel object transfer between + concurrent threads, if the worker mechanisms are insufficient for a particular task. Note, that object detachment + may require explicit leaving function holding object references and then performing cyclic garbage collection. + For example, code like: + +
+ +```kotlin +val graph = DetachedObjectGraph { + val map = mutableMapOf() + for (entry in map.entries) { + // ... + } + map +} +``` + +
+ + will not work as expected and will throw runtime exception, as there are uncollected cycles in the detached graph, while: + +
+ +```kotlin +val graph = DetachedObjectGraph { + { + val map = mutableMapOf() + for (entry in map.entries) { + // ... + } + map + }().also { + kotlin.native.internal.GC.collect() + } + } +``` + +
+ + will work properly, as holding references will be released, and then cyclic garbage affecting reference counter is + collected. + + +### Raw shared memory + + Considering the strong ties between Kotlin/Native and C via interoperability, in conjunction with the other mechanisms + mentioned above it is possible to build popular data structures, like concurrent hashmap or shared cache with + Kotlin/Native. It is possible to rely upon shared C data, and store in it references to detached object subgraphs. + Consider the following .def file: + +
+ +```c +package = global + +--- +typedef struct { + int version; + void* kotlinObject; +} SharedData; + +SharedData sharedData; +``` + +
+ +After running the cinterop tool it can share Kotlin data in a versionized global structure, +and interact with it from Kotlin transparently via autogenerated Kotlin like this: + +
+ +```kotlin +class SharedData(rawPtr: NativePtr) : CStructVar(rawPtr) { + var version: Int + var kotlinObject: COpaquePointer? +} +``` + +
+ +So in combination with the top level variable declared above, it can allow looking at the same memory from different +threads and building traditional concurrent structures with platform-specific synchronization primitives. + + +### Global variables and singletons + + Frequently, global variables are a source of unintended concurrency issues, so _Kotlin/Native_ implements +the following mechanisms to prevent the unintended sharing of state via global objects: + + * global variables, unless specially marked, can be only accessed from the main thread (that is, the thread + _Kotlin/Native_ runtime was first initialized), if other thread access such a global, `IncorrectDereferenceException` is thrown + * for global variables marked with the `@kotlin.native.ThreadLocal` annotation each threads keeps thread-local copy, + so changes are not visible between threads + * for global variables marked with the `@kotlin.native.SharedImmutable` annotation value is shared, but frozen + before publishing, so each threads sees the same value + * singleton objects unless marked with `@kotlin.native.ThreadLocal` are frozen and shared, lazy values allowed, + unless cyclic frozen structures were attempted to be created + * enums are always frozen + + Combined, these mechanisms allow natural race-free programming with code reuse across platforms in MPP projects. + + +### Atomic primitives and references + + Kotlin/Native standard library provides primitives for safe working with concurrently mutable data, namely +`AtomicInt`, `AtomicLong`, `AtomicNativePtr`, `AtomicReference` and `FreezableAtomicReference` in the package +`kotlin.native.concurrent`. +Atomic primitives allows concurrency-safe update operations, such as increment, decrement and compare-and-swap, +along with value setters and getters. Atomic primitives are considered always frozen by the runtime, and +while their fields can be updated with the regular `field.value += 1`, it is not concurrency safe. +Value must be be changed using dedicated operations, so it is possible to perform concurrent-safe +global counters and similar data structures. + + Some algorithms require shared mutable references across the multiple workers, for example global mutable +configuration could be implemented as an immutable instance of properties list atomically replaced with the +new version on configuration update as the whole in a single transaction. This way no inconsistent configuration +could be seen, and at the same time configuration could be updated as needed. +To achieve such functionality Kotlin/Native runtime provides two related classes: +`kotlin.native.concurrent.AtomicReference` and `kotlin.native.concurrent.FreezableAtomicReference`. +Atomic reference holds reference to a frozen or immutable object, and its value could be updated by set +or compare-and-swap operation. Thus, dedicated set of objects could be used to create mutable shared object graphs +(of immutable objects). Cycles in the shared memory could be created using atomic references. +Kotlin/Native runtime doesn't support garbage collecting cyclic data when reference cycle goes through +`AtomicReference` or frozen `FreezableAtomicReference`. So to avoid memory leaks atomic references +that are potentially parts of shared cyclic data should be zeroed out once no longer needed. + + If atomic reference value is attempted to be set to non-frozen value runtime exception is thrown. + + Freezable atomic reference is similar to the regular atomic reference, but until frozen behaves like regular box +for a reference. After freezing it behaves like an atomic reference, and can only hold a reference to a frozen object. \ No newline at end of file diff --git a/kotlin-native/DEBUGGING.md b/kotlin-native/DEBUGGING.md new file mode 100644 index 00000000000..a5c2d59c803 --- /dev/null +++ b/kotlin-native/DEBUGGING.md @@ -0,0 +1,261 @@ +## Debugging + +Currently the Kotlin/Native compiler produces debug info compatible with the DWARF 2 specification, so modern debugger tools can +perform the following operations: +- breakpoints +- stepping +- inspection of type information +- variable inspection + +### Producing binaries with debug info with Kotlin/Native compiler + +To produce binaries with the Kotlin/Native compiler it's sufficient to use the ``-g`` option on the command line.
+_Example:_ + +
+ +```bash +0:b-debugger-fixes:minamoto@unit-703(0)# cat - > hello.kt +fun main(args: Array) { + println("Hello world") + println("I need your clothes, your boots and your motocycle") +} +0:b-debugger-fixes:minamoto@unit-703(0)# dist/bin/konanc -g hello.kt -o terminator +KtFile: hello.kt +0:b-debugger-fixes:minamoto@unit-703(0)# lldb terminator.kexe +(lldb) target create "terminator.kexe" +Current executable set to 'terminator.kexe' (x86_64). +(lldb) b kfun:main(kotlin.Array) +Breakpoint 1: where = terminator.kexe`kfun:main(kotlin.Array) + 4 at hello.kt:2, address = 0x00000001000012e4 +(lldb) r +Process 28473 launched: '/Users/minamoto/ws/.git-trees/debugger-fixes/terminator.kexe' (x86_64) +Process 28473 stopped +* thread #1, queue = 'com.apple.main-thread', stop reason = breakpoint 1.1 + frame #0: 0x00000001000012e4 terminator.kexe`kfun:main(kotlin.Array) at hello.kt:2 + 1 fun main(args: Array) { +-> 2 println("Hello world") + 3 println("I need your clothes, your boots and your motocycle") + 4 } +(lldb) n +Hello world +Process 28473 stopped +* thread #1, queue = 'com.apple.main-thread', stop reason = step over + frame #0: 0x00000001000012f0 terminator.kexe`kfun:main(kotlin.Array) at hello.kt:3 + 1 fun main(args: Array) { + 2 println("Hello world") +-> 3 println("I need your clothes, your boots and your motocycle") + 4 } +(lldb) +``` + +
+ +### Breakpoints +Modern debuggers provide several ways to set a breakpoint, see below for a tool-by-tool breakdown: + +#### lldb +- by name + +
+ +```bash +(lldb) b -n kfun:main(kotlin.Array) +Breakpoint 4: where = terminator.kexe`kfun:main(kotlin.Array) + 4 at hello.kt:2, address = 0x00000001000012e4 +``` + +
+ + _``-n`` is optional, this flag is applied by default_ +- by location (filename, line number) + +
+ +```bash +(lldb) b -f hello.kt -l 1 +Breakpoint 1: where = terminator.kexe`kfun:main(kotlin.Array) + 4 at hello.kt:2, address = 0x00000001000012e4 +``` + +
+ +- by address + +
+ +```bash +(lldb) b -a 0x00000001000012e4 +Breakpoint 2: address = 0x00000001000012e4 +``` + +
+ +- by regex, you might find it useful for debugging generated artifacts, like lambda etc. (where used ``#`` symbol in name). + +
+ +```bash +3: regex = 'main\(', locations = 1 + 3.1: where = terminator.kexe`kfun:main(kotlin.Array) + 4 at hello.kt:2, address = terminator.kexe[0x00000001000012e4], unresolved, hit count = 0 +``` + +
+ +#### gdb +- by regex + +
+ +```bash +(gdb) rbreak main( +Breakpoint 1 at 0x1000109b4 +struct ktype:kotlin.Unit &kfun:main(kotlin.Array); +``` + +
+ +- by name __unusable__, because ``:`` is a separator for the breakpoint by location + +
+ +```bash +(gdb) b kfun:main(kotlin.Array) +No source file named kfun. +Make breakpoint pending on future shared library load? (y or [n]) y +Breakpoint 1 (kfun:main(kotlin.Array)) pending +``` + +
+ +- by location + +
+ +```bash +(gdb) b hello.kt:1 +Breakpoint 2 at 0x100001704: file /Users/minamoto/ws/.git-trees/hello.kt, line 1. +``` + +
+ +- by address + +
+ +```bash +(gdb) b *0x100001704 +Note: breakpoint 2 also set at pc 0x100001704. +Breakpoint 3 at 0x100001704: file /Users/minamoto/ws/.git-trees/hello.kt, line 2. +``` + +
+ + +### Stepping +Stepping functions works mostly the same way as for C/C++ programs + +### Variable inspection + +Variable inspections for var variables works out of the box for primitive types. +For non-primitive types there are custom pretty printers for lldb in +`konan_lldb.py`: + +
+ +```bash +λ cat main.kt | nl + 1 fun main(args: Array) { + 2 var x = 1 + 3 var y = 2 + 4 var p = Point(x, y) + 5 println("p = $p") + 6 } + + 7 data class Point(val x: Int, val y: Int) + +λ lldb ./program.kexe -o 'b main.kt:5' -o +(lldb) target create "./program.kexe" +Current executable set to './program.kexe' (x86_64). +(lldb) b main.kt:5 +Breakpoint 1: where = program.kexe`kfun:main(kotlin.Array) + 289 at main.kt:5, address = 0x000000000040af11 +(lldb) r +Process 4985 stopped +* thread #1, name = 'program.kexe', stop reason = breakpoint 1.1 + frame #0: program.kexe`kfun:main(kotlin.Array) at main.kt:5 + 2 var x = 1 + 3 var y = 2 + 4 var p = Point(x, y) +-> 5 println("p = $p") + 6 } + 7 + 8 data class Point(val x: Int, val y: Int) + +Process 4985 launched: './program.kexe' (x86_64) +(lldb) fr var +(int) x = 1 +(int) y = 2 +(ObjHeader *) p = 0x00000000007643d8 +(lldb) command script import dist/tools/konan_lldb.py +(lldb) fr var +(int) x = 1 +(int) y = 2 +(ObjHeader *) p = Point(x=1, y=2) +(lldb) p p +(ObjHeader *) $2 = Point(x=1, y=2) +(lldb) +``` + +
+ + +Getting representation of the object variable (var) could also be done using the +built-in runtime function `Konan_DebugPrint` (this approach also works for gdb, +using a module of command syntax): + +
+ +```bash +0:b-debugger-fixes:minamoto@unit-703(0)# cat ../debugger-plugin/1.kt | nl -p + 1 fun foo(a:String, b:Int) = a + b + 2 fun one() = 1 + 3 fun main(arg:Array) { + 4 var a_variable = foo("(a_variable) one is ", 1) + 5 var b_variable = foo("(b_variable) two is ", 2) + 6 var c_variable = foo("(c_variable) two is ", 3) + 7 var d_variable = foo("(d_variable) two is ", 4) + 8 println(a_variable) + 9 println(b_variable) + 10 println(c_variable) + 11 println(d_variable) + 12 } +0:b-debugger-fixes:minamoto@unit-703(0)# lldb ./program.kexe -o 'b -f 1.kt -l 9' -o r +(lldb) target create "./program.kexe" +Current executable set to './program.kexe' (x86_64). +(lldb) b -f 1.kt -l 9 +Breakpoint 1: where = program.kexe`kfun:main(kotlin.Array) + 463 at 1.kt:9, address = 0x0000000100000dbf +(lldb) r +(a_variable) one is 1 +Process 80496 stopped +* thread #1, queue = 'com.apple.main-thread', stop reason = breakpoint 1.1 + frame #0: 0x0000000100000dbf program.kexe`kfun:main(kotlin.Array) at 1.kt:9 + 6 var c_variable = foo("(c_variable) two is ", 3) + 7 var d_variable = foo("(d_variable) two is ", 4) + 8 println(a_variable) +-> 9 println(b_variable) + 10 println(c_variable) + 11 println(d_variable) + 12 } + +Process 80496 launched: './program.kexe' (x86_64) +(lldb) expression -- Konan_DebugPrint(a_variable) +(a_variable) one is 1(KInt) $0 = 0 +(lldb) + +``` + +
+ + +### Known issues +- performance of Python bindings. + +_Note:_ Supporting the DWARF 2 specification means that the debugger tool recognizes Kotlin as C89, because before the DWARF 5 specification, there is no identifier for the Kotlin language type in specification. + diff --git a/kotlin-native/DISTRO_README.md b/kotlin-native/DISTRO_README.md new file mode 100644 index 00000000000..05397fad5d1 --- /dev/null +++ b/kotlin-native/DISTRO_README.md @@ -0,0 +1,33 @@ +# Kotlin/Native # + +_Kotlin/Native_ is a LLVM backend for the Kotlin compiler, runtime +implementation and native code generation facility using LLVM toolchain. + + _Kotlin/Native_ is primarily designed to allow compilation for platforms where +virtual machines are not desirable or possible (such as iOS, embedded targets), +or where developer is willing to produce reasonably-sized self-contained program +without need to ship an additional execution runtime. + + _Kotlin/Native_ could be used either as standalone compiler toolchain or as Gradle +plugin. See [documentation](https://kotlinlang.org/docs/reference/native/gradle_plugin.html) +for more details on how to use this plugin. + +Compile your programs like that: + + export PATH=kotlin-native--/bin:$PATH + kotlinc hello.kt -o hello + +For an optimized compilation use -opt: + + kotlinc hello.kt -o hello -opt + +To generate interoperability stubs create library definition file +(take a look on [Tetris sample](samples/tetris)) +and run `cinterop` tool like this: + + cinterop -def lib.def + +See [C interop documentation](https://kotlinlang.org/docs/reference/native/c_interop.html) +for more information on how to use C libraries from _Kotlin/Native_. + +See [`RELEASE_NOTES.md`](https://github.com/JetBrains/kotlin-native/blob/master/RELEASE_NOTES.md) for information on supported platforms and current limitations. diff --git a/kotlin-native/FAQ.md b/kotlin-native/FAQ.md new file mode 100644 index 00000000000..37a45224f8a --- /dev/null +++ b/kotlin-native/FAQ.md @@ -0,0 +1,206 @@ +### Q: How do I run my program? + +A: Define a top level function `fun main(args: Array)` or just `fun main()` if you are not interested +in passed arguments, please ensure it's not in a package. +Also compiler switch `-entry` could be used to make any function taking `Array` or no arguments +and return `Unit` as an entry point. + + +### Q: What is Kotlin/Native memory management model? + +A: Kotlin/Native provides an automated memory management scheme, similar to what Java or Swift provides. +The current implementation includes an automated reference counter with a cycle collector to collect cyclical +garbage. + + +### Q: How do I create a shared library? + +A: Use the `-produce dynamic` compiler switch, or `binaries.sharedLib()` in Gradle, i.e. + +
+ +```kotlin +kotlin { + iosArm64("mylib") { + binaries.sharedLib() + } +} +``` + +
+ +It will produce a platform-specific shared object (.so on Linux, .dylib on macOS, and .dll on Windows targets) and a +C language header, allowing the use of all public APIs available in your Kotlin/Native program from C/C++ code. +See `samples/python_extension` for an example of using such a shared object to provide a bridge between Python and +Kotlin/Native. + + +### Q: How do I create a static library or an object file? + +A: Use the `-produce static` compiler switch, or `binaries.staticLib()` in Gradle, i.e. + +
+ +```kotlin +kotlin { + iosArm64("mylib") { + binaries.staticLib() + } +} +``` + +
+ +It will produce a platform-specific static object (.a library format) and a C language header, allowing you to +use all the public APIs available in your Kotlin/Native program from C/C++ code. + + +### Q: How do I run Kotlin/Native behind a corporate proxy? + +A: As Kotlin/Native needs to download a platform specific toolchain, you need to specify +`-Dhttp.proxyHost=xxx -Dhttp.proxyPort=xxx` as the compiler's or `gradlew` arguments, +or set it via the `JAVA_OPTS` environment variable. + + +### Q: How do I specify a custom Objective-C prefix/name for my Kotlin framework? + +A: Use the `-module-name` compiler option or matching Gradle DSL statement, i.e. + +
+
+ +```kotlin +kotlin { + iosArm64("myapp") { + binaries.framework { + freeCompilerArgs += listOf("-module-name", "TheName") + } + } +} +``` + +
+
+ +
+
+ +```groovy +kotlin { + iosArm64("myapp") { + binaries.framework { + freeCompilerArgs += ["-module-name", "TheName"] + } + } +} +``` + +
+
+ +### Q: How do I rename the iOS framework? (default name is _\_.framework) + +A: Use the `baseName` option. This will also set the module name. + +
+ +```kotlin +kotlin { + iosArm64("myapp") { + binaries { + framework { + baseName = "TheName" + } + } + } +} +``` + +
+ +### Q: How do I enable bitcode for my Kotlin framework? + +A: By default gradle plugin adds it on iOS target. + * For debug build it embeds placeholder LLVM IR data as a marker. + * For release build it embeds bitcode as data. + +Or commandline arguments: `-Xembed-bitcode` (for release) and `-Xembed-bitcode-marker` (debug) + +Setting this in a Gradle DSL: +
+ +```kotlin +kotlin { + iosArm64("myapp") { + binaries { + framework { + // Use "marker" to embed the bitcode marker (for debug builds). + // Use "disable" to disable embedding. + embedBitcode("bitcode") // for release binaries. + } + } + } +} +``` + +
+ +These options have nearly the same effect as clang's `-fembed-bitcode`/`-fembed-bitcode-marker` +and swiftc's `-embed-bitcode`/`-embed-bitcode-marker`. + +### Q: Why do I see `InvalidMutabilityException`? + +A: It likely happens, because you are trying to mutate a frozen object. An object can transfer to the +frozen state either explicitly, as objects reachable from objects on which the `kotlin.native.concurrent.freeze` is called, +or implicitly (i.e. reachable from `enum` or global singleton object - see the next question). + + +### Q: How do I make a singleton object mutable? + +A: Currently, singleton objects are immutable (i.e. frozen after creation), and it's generally considered +good practise to have the global state immutable. If for some reason you need a mutable state inside such an +object, use the `@konan.ThreadLocal` annotation on the object. Also the `kotlin.native.concurrent.AtomicReference` class could be +used to store different pointers to frozen objects in a frozen object and automatically update them. + +### Q: How can I compile my project against the Kotlin/Native master? + +A: One of the following should be done: + +
+ +For the CLI, you can compile using gradle as stated in the README (and if you get errors, you can try to do a ./gradlew clean): + +
+ +```bash +./gradlew dependencies:update +./gradlew dist distPlatformLibs +``` + +
+ + +You can then set the `KONAN_HOME` env variable to the generated `dist` folder in the git repository. + +
+ +
+For Gradle, you can use Gradle composite builds like this: + +
+ + +```bash +# Set with the path of your kotlin-native clone +export KONAN_REPO=$PWD/../kotlin-native + +# Run this once since it is costly, you can remove the `clean` task if not big changes were made from the last time you did this +pushd $KONAN_REPO && git pull && ./gradlew clean dependencies:update dist distPlatformLibs && popd + +# In your project, you set have to the org.jetbrains.kotlin.native.home property, and include as composite the shared and gradle-plugin builds +./gradlew check -Porg.jetbrains.kotlin.native.home=$KONAN_REPO/dist --include-build $KONAN_REPO/shared --include-build $KONAN_REPO/tools/kotlin-native-gradle-plugin +``` + +
+ +
diff --git a/kotlin-native/GRADLE_PLUGIN.md b/kotlin-native/GRADLE_PLUGIN.md new file mode 100644 index 00000000000..55f61364383 --- /dev/null +++ b/kotlin-native/GRADLE_PLUGIN.md @@ -0,0 +1,729 @@ +# Kotlin/Native Gradle plugin + +Since 1.3.40, a separate Gradle plugin for Kotlin/Native is deprecated in favor of the `kotlin-multiplatform` plugin. +This plugin provides an IDE support along with support of the new multiplatform project model introduced in Kotlin 1.3.0. +Below you can find a short list of differences between `kotlin-platform-native` and `kotlin-muliplatform` plugins. +For more information see the `kotlin-muliplatform` [documentation page](https://kotlinlang.org/docs/reference/building-mpp-with-gradle.html). +For `kotlin-platform-native` reference see the [corresponding section](#kotlin-platform-native-reference). + +### Applying the multiplatform plugin + +To apply the `kotlin-multiplatform` plugin, just add the following snippet into your build script: + +
+ +```groovy +plugins { + id("org.jetbrains.kotlin.multiplatform") version '1.3.40' +} +``` + +
+ + +### Managing targets + +With the `kotlin-platform-native` plugin a set of target platforms is specified as a list in properties of the main component: + +
+ +```groovy +components.main { + targets = ['macos_x64', 'linux_x64', 'mingw_x64'] +} +``` + +
+ +With the `kotlin-multiplatform` plugin target platforms can be added into a project using special methods available in the `kotlin` extension. +Each method adds into a project one __target__ which can be accessed using the `targets` property. Each target can be configured independently +including output kinds, additional compiler options etc. See details about targets at the [corresponding page](https://kotlinlang.org/docs/reference/building-mpp-with-gradle.html#setting-up-targets). + +
+ +```groovy +import org.jetbrains.kotlin.gradle.plugin.mpp.KotlinNativeTarget + +kotlin { + // These targets are declared without any target-specific settings. + macosX64() + linuxX64() + + // You can specify a custom name used to access the target. + mingwX64("windows") + + iosArm64 { + // Additional settings for ios_arm64. + } + + // You can access declared targets using the `targets` property. + println(targets.macosX64) + println(targets.windows) + + // You also can configure all native targets in a single block. + targets.withType(KotlinNativeTarget) { + // Native target configuration. + } +} +``` + +
+ +Each target includes two __compilations__: `main` and `test` compiling product and test sources respectively. A compilation is an abstraction +over a compiler invocation and described at the [corresponding page](https://kotlinlang.org/docs/reference/building-mpp-with-gradle.html#configuring-compilations). + +### Managing sources + +With the `kotlin-platform-native` plugin source sets are used to separate test and product sources. Also you can specify different sources +for different platforms in the same source set: + +
+ +```groovy +sourceSets { + // Adding target-independent sources. + main.kotlin.srcDirs += 'src/main/mySources' + + // Adding Linux-specific code. + main.target('linux_x64').srcDirs += 'src/main/linux' +} +``` + +
+ +With the `kotlin-multiplatform` plugin __source__ __sets__ are also used to group sources but source files for different platforms are located in different source sets. +For each declared target two source sets are created: `Main` and `Test` containing product and test sources for this platform. Common for all +platforms sources are located in `commonMain` and `commonTest` source sets created by default. More information about source sets can be found +[here](https://kotlinlang.org/docs/reference/building-mpp-with-gradle.html#configuring-source-sets). + +
+ +```groovy +kotlin { + sourceSets { + // Adding target-independent sources. + commonMain.kotlin.srcDirs += file("src/main/mySources") + + // Adding Linux-specific code. + linuxX64Main.kotlin.srcDirs += file("src/main/linux") + } +} +``` + +
+ +### Managing dependencies + +With the `kotlin-platform-native` plugin dependencies are configured in a traditional for Gradle way by grouping them into configurations +using the project `dependencies` block: + +
+ +```groovy +dependencies { + implementation 'org.sample.test:mylibrary:1.0' + testImplementation 'org.sample.test:testlibrary:1.0' +} +``` + +
+ +The `kotlin-multiplatform` plugin also uses configurations under the hood but it also provides a `dependencies` block for each source set +allowing configuring dependencies of this sources set: + +
+ +```groovy +kotlin.sourceSets { + commonMain { + dependencies { + implementation("org.sample.test:mylibrary:1.0") + } + } + + commonTest { + dependencies { + implementation("org.sample.test:testlibrary:1.0") + } + } +} +``` + +
+ +Note that a module referenced by a dependency declared for `commonMain` or `commonTest` source set must be published using the `kotlin-multiplatform` plugin. +If you want to use libraries published by the `kotlin-platform-native` plugin, you need to declare a separate source set for common native sources. + +
+ +```groovy +kotlin.sourceSets { + // Create a common source set used by native targets only. + nativeMain { + dependsOn(commonMain) + dependencies { + // Depend on a library published by the kotlin-platform-naive plugin. + implementation("org.sample.test:mylibrary:1.0") + } + } + + // Configure all native platform sources sets to use it as a common one. + linuxX64Main.dependsOn(nativeMain) + macosX64Main.dependsOn(nativeMain) + //... +} +``` + +
+ +See more info about dependencies at the [corresponding page](https://kotlinlang.org/docs/reference/building-mpp-with-gradle.html#adding-dependencies). + +### Output kinds + +With the `kotlin-platform-native` plugin output kinds are specified as a list in properties of a component: + +
+ +```groovy +components.main { + // Compile the component into an executable and a Kotlin/Native library. + outputKinds = [EXECUTABLE, KLIBRARY] +} +``` + +
+ +With the `kotlin-multiplatform` plugin a compilation always produces a `*.klib` file. A separate `binaries` block is used to configure what +final native binaries should be produced by each target. Each binary can be configured independently including linker options, executable entry point etc. + +
+ +```groovy +kotlin { + macosX64 { + binaries { + executable { + // Binary configuration: linker options, name, etc. + } + framework { + // ... + } + + } + } +} +``` + +
+ +See more about native binaries declaration at the [corresponding page](https://kotlinlang.org/docs/reference/building-mpp-with-gradle.html#building-final-native-binaries). + + +### Publishing + +Both `kotlin-platform-native` and `kotlin-multiplatform` plugins automatically set up artifact publication when the +`maven-publish` plugin is applied. See details about publication at the [corresponding page](https://kotlinlang.org/docs/reference/building-mpp-with-gradle.html#publishing-a-multiplatform-library). +Note that currently only Kotlin/Native libraries (`*.klib`) can be published for native targets. + +### Cinterop support + +With the `kotlin-platform-native` plugin interop with a native library can be declared in component dependencies: + +
+ +```groovy +components.main { + dependencies { + cinterop('mystdio') { + // Cinterop configuration. + } + } +} +``` + +
+ +With the `kotlin-multiplatform` plugin interops are configured as a part of a compilation (see details [here](https://kotlinlang.org/docs/reference/building-mpp-with-gradle.html#cinterop-support)). +The rest of an interop configuration is the same as for the `kotlin-platform-native` plugin. + +
+ +```groovy +kotlin { + macosX64 { + compilations.main.cinterops { + mystdio { + // Cinterop configuration. + } + } + } +} +``` + +
+ +## `kotlin-platform-native` reference + +### Overview + +You may use the Gradle plugin to build _Kotlin/Native_ projects. Builds of the plugin are +[available](https://plugins.gradle.org/plugin/org.jetbrains.kotlin.platform.native) at the Gradle plugin portal, so you can apply it +using Gradle plugin DSL: + +
+ +```groovy +plugins { + id "org.jetbrains.kotlin.platform.native" version "1.3.0-rc-146" +} +``` + +
+ +You also can get the plugin from a Bintray repository. In addition to releases, this repo contains old and development +versions of the plugin which are not available at the plugin portal. To get the plugin from the Bintray repo, include +the following snippet in your build script: + +
+ +```groovy +buildscript { + repositories { + mavenCentral() + maven { + url "https://dl.bintray.com/jetbrains/kotlin-native-dependencies" + } + } + + dependencies { + classpath "org.jetbrains.kotlin:kotlin-native-gradle-plugin:1.3.0-rc-146" + } +} + +apply plugin: 'org.jetbrains.kotlin.platform.native' +``` + +
+ +By default the plugin downloads the Kotlin/Native compiler during the first run. If you have already downloaded the compiler +manually you can specify the path to its root directory using `org.jetbrains.kotlin.native.home` project property (e.g. in `gradle.properties`). + +
+ +```groovy +org.jetbrains.kotlin.native.home=/home/user/kotlin-native-0.8 +``` + +
+ +In this case the compiler will not be downloaded by the plugin. + +### Source management + +Source management in the `kotlin.platform.native` plugin is uniform with other Kotlin plugins and is based on source sets. +A source set is a group of Kotlin/Native source which may contain both common and platform-specific code. The plugin +provides a top-level script block `sourceSets` allowing you to configure source sets. Also it creates the default +source sets `main` and `test` (for production and test code respectively). + +By default the production sources are located in `src/main/kotlin` and the test sources - in `src/test/kotlin`. + +
+ +```groovy +sourceSets { + // Adding target-independent sources. + main.kotlin.srcDirs += 'src/main/mySources' + + // Adding Linux-specific code. It will be compiled in Linux binaries only. + main.target('linux_x64').srcDirs += 'src/main/linux' +} +``` + +
+ +### Targets and output kinds + +By default the plugin creates software components for the main and test source sets. You can access them via the +`components` container provided by Gradle or via the `component` property of a corresponding source set: + +
+ +```groovy +// Main component. +components.main +sourceSets.main.component + +// Test component. +components.test +sourceSets.test.component +``` + +
+ +Components allow you to specify: + +* Targets (e.g. Linux/x64 or iOS/arm64 etc) +* Output kinds (e.g. executable, library, framework etc) +* Dependencies (including interop ones) + +Targets can be specified by setting a corresponding component property: + +
+ +```groovy +components.main { + // Compile this component for 64-bit MacOS, Linux and Windows. + targets = ['macos_x64', 'linux_x64', 'mingw_x64'] +} +``` + +
+ +The plugin uses the same notation as the compiler. By default, test component uses the same targets as specified for the main one. + +Output kinds can also be specified using a special property: + +
+ +```groovy +components.main { + // Compile the component into an executable and a Kotlin/Native library. + outputKinds = [EXECUTABLE, KLIBRARY] +} +``` + +
+ +All constants used here are available inside a component configuration script block. +The plugin supports producing binaries of the following kinds: + +* `EXECUTABLE` - an executable file; +* `KLIBRARY` - a Kotlin/Native library (*.klib); +* `FRAMEWORK` - an Objective-C framework; +* `DYNAMIC` - shared native library; +* `STATIC` - static native library. + +Also each native binary is built in two variants (build types): `debug` (debuggable, not optimized) and `release` (not debuggable, optimized). +Note that Kotlin/Native libraries have only `debug` variant because optimizations are preformed only during compilation +of a final binary (executable, static lib etc) and affect all libraries used to build it. + +### Compile tasks + +The plugin creates a compilation task for each combination of the target, output kind, and build type. The tasks have the following naming convention: + + compileKotlinNative + +For example `compileDebugKlibraryMacos_x64KotlinNative`, `compileTestDebugKotlinNative`. + +The name contains the following parts (some of them may be empty): + +* `` - name of a component. Empty for the main component. +* `` - `Debug` or `Release`. +* `` - output kind name, e.g. `Executabe` or `Dynamic`. Empty if the component has only one output kind. +* `` - target the component is built for, e.g. `Macos_x64` or `Wasm32`. Empty if the component is built only for one target. + +Also the plugin creates a number of aggregate tasks allowing you to build all the binaries for a build type (e.g. +`assembleAllDebug`) or all the binaries for a particular target (e.g. `assembleAllWasm32`). + +Basic lifecycle tasks like `assemble`, `build`, and `clean` are also available. + +### Running tests + +The plugin builds a test executable for all the targets specified for the `test` component. If the current host platform is +included in this list the test running tasks are also created. To run tests, execute the standard lifecycle `check` task: + +
+ +```bash +./gradlew check +``` + +
+ +### Dependencies + +The plugin allows you to declare dependencies on files and other projects using traditional Gradle's mechanism of +configurations. The plugin supports Kotlin multiplatform projects allowing you to declare the `expectedBy` dependencies + +
+ +```groovy +dependencies { + implementation files('path/to/file/dependencies') + implementation project('library') + testImplementation project('testLibrary') + expectedBy project('common') +} +``` + +
+ +It's possible to depend on a Kotlin/Native library published earlier in a maven repo. The plugin relies on Gradle's +[metadata](https://github.com/gradle/gradle/blob/master/subprojects/docs/src/docs/design/gradle-module-metadata-specification.md) +support so the corresponding feature must be enabled. Add the following line in your `settings.gradle`: + +
+ +```groovy +enableFeaturePreview('GRADLE_METADATA') +``` + +
+ + +Now you can declare a dependency on a Kotlin/Native library in the traditional `group:artifact:version` notation: + +
+ +```groovy +dependencies { + implementation 'org.sample.test:mylibrary:1.0' + testImplementation 'org.sample.test:testlibrary:1.0' +} +``` + +
+ +Dependency declaration is also possible in the component block: + +
+ +```groovy +components.main { + dependencies { + implementation 'org.sample.test:mylibrary:1.0' + } +} + +components.test { + dependencies { + implementation 'org.sample.test:testlibrary:1.0' + } +} +``` + +
+ + +### Using cinterop + +It's possible to declare a cinterop dependency for a component: + +
+ +```groovy +components.main { + dependencies { + cinterop('mystdio') { + // src/main/c_interop/mystdio.def is used as a def file. + + // Set up compiler options + compilerOpts '-I/my/include/path' + + // It's possible to set up different options for different targets + target('linux') { + compilerOpts '-I/linux/include/path' + } + } + } +} +``` + +
+ +Here an interop library will be built and added in the component dependencies. + +Often it's necessary to specify target-specific linker options for a Kotlin/Native binary using an interop. It can be +done using the `target` script block: + +
+ +```groovy +components.main { + target('linux') { + linkerOpts '-L/path/to/linux/libs' + } +} +``` + +
+ +Also the `allTargets` block is available. + +
+ +```groovy +components.main { + // Configure all targets. + allTargets { + linkerOpts '-L/path/to/libs' + } +} +``` + +
+ + +### Publishing + +In the presence of `maven-publish` plugin the publications for all the binaries built are created. The plugin uses Gradle +metadata to publish the artifacts so this feature must be enabled (see the [dependencies](#dependencies) section). + +Now you can publish the artifacts with the standard Gradle `publish` task: + +
+ +```bash +./gradlew publish +``` + +
+ +Only `EXECUTABLE` and `KLIBRARY` binaries are published currently. + +The plugin allows you to customize the pom generated for the publication with the `pom` code block available for every component: + +
+ +```groovy +components.main { + pom { + withXml { + def root = asNode() + root.appendNode('name', 'My library') + root.appendNode('description', 'A Kotlin/Native library') + } + } +} +``` + +
+ +### Serialization plugin + +The plugin is shipped with a customized version of the `kotlinx.serialization` plugin. To use it you don't have to +add new buildscript dependencies, just apply the plugins and add a dependency on the serialization library: + +
+ +```groovy +apply plugin: 'org.jetbrains.kotlin.platform.native' +apply plugin: 'kotlinx-serialization-native' + +dependencies { + implementation 'org.jetbrains.kotlinx:kotlinx-serialization-runtime-native' +} +``` + +
+ +The [example project](https://github.com/ilmat192/kotlin-native-serialization-sample) for details. + +### DSL example + +In this section a commented DSL is shown. +See also the example projects that use this plugin, e.g. +[Kotlinx.coroutines](https://github.com/Kotlin/kotlinx.coroutines), +[MPP http client](https://github.com/e5l/http-client-common/tree/master/samples/ios-test-application) + +
+ +```groovy +plugins { + id "org.jetbrains.kotlin.platform.native" version "1.3.0-rc-146" +} + +sourceSets.main { + // Plugin uses Gradle's source directory sets here, + // so all the DSL methods available in SourceDirectorySet can be called here. + // Platform independent sources. + kotlin.srcDirs += 'src/main/customDir' + + // Linux-specific sources + target('linux').srcDirs += 'src/main/linux' +} + +components.main { + + // Set up targets + targets = ['linux_x64', 'macos_x64', 'mingw_x64'] + + // Set up output kinds + outputKinds = [EXECUTABLE, KLIBRARY, FRAMEWORK, DYNAMIC, STATIC] + + // Specify custom entry point for executables + entryPoint = "org.test.myMain" + + // Target-specific options + target('linux_x64') { + linkerOpts '-L/linux/lib/path' + } + + // Targets independent options + allTargets { + linkerOpts '-L/common/lib/path' + } + + dependencies { + + // Dependency on a published Kotlin/Native library. + implementation 'org.test:mylib:1.0' + + // Dependency on a project + implementation project('library') + + // Cinterop dependency + cinterop('interop-name') { + // Def-file describing the native API. + // The default path is src/main/c_interop/.def + defFile project.file("deffile.def") + + // Package to place the Kotlin API generated. + packageName 'org.sample' + + // Options to be passed to compiler and linker by cinterop tool. + compilerOpts 'Options for native stubs compilation' + linkerOpts 'Options for native stubs' + + // Additional headers to parse. + headers project.files('header1.h', 'header2.h') + + // Directories to look for headers. + includeDirs { + // All objects accepted by the Project.file method may be used with both options. + + // Directories for header search (an analogue of the -I compiler option). + allHeaders 'path1', 'path2' + + // Additional directories to search headers listed in the 'headerFilter' def-file option. + // -headerFilterAdditionalSearchPrefix command line option analogue. + headerFilterOnly 'path1', 'path2' + } + // A shortcut for includeDirs.allHeaders. + includeDirs "include/directory" "another/directory" + + // Pass additional command line options to the cinterop tool. + extraOpts '-verbose' + + // Additional configuration for Linux. + target('linux') { + compilerOpts 'Linux-specific options' + } + } + } + + // Additional pom settings for publication. + pom { + withXml { + def root = asNode() + root.appendNode('name', 'My library') + root.appendNode('description', 'A Kotlin/Native library') + } + } + + // Additional options passed to the compiler. + extraOpts '--time' +} +``` + +
diff --git a/kotlin-native/HACKING.md b/kotlin-native/HACKING.md new file mode 100644 index 00000000000..68a466eb72c --- /dev/null +++ b/kotlin-native/HACKING.md @@ -0,0 +1,324 @@ +## Profiling the compiler + +### Profiling with Async profiler + + IDEA Ultimate contains an Async sampling profiler. + As of IDEA 2018.3 Async sampling profiler is still an experimental feature, so use Ctrl-Alt-Shift-/ on Linux, +Cmd-Alt-Shift-/ on macOS to activate it. Then start compilation in CLI with `--no-daemon` and +`-Porg.gradle.workers.max=1` flags (running Gradle task with the profiler doesn't seem to work properly) and attach +to the running process using "Run/Attach Profiler to Local Process" menu item. + + Select "K2NativeKt" or "org.jetbrains.kotlin.cli.utilities.MainKt" process. +On completion profiler will produce flame diagram which could be navigated with the mouse +(click-drag moves, wheel scales). More RAM in IDE (>4G) could be helpful when analyzing longer runs. +As Async is a sampling profiler, to get sensible coverage longer runs are important. + +### Profiling with YourKit + +Unlike Async profiler in IDEA, YourKit can work as an exact profiler and provide complete coverage +of all methods along with exact invocation counters. + +Install the YourKit profiler for your platform from https://www.yourkit.com/java/profiler. +Set AGENT variable to the JVMTI agent provided by YourKit, like + + export AGENT=/Applications/YourKit-Java-Profiler-2018.04.app/Contents/Resources/bin/mac/libyjpagent.jnilib + +To profile standard library compilation: + + ./gradlew -PstdLibJvmArgs="-agentpath:$AGENT=probe_disable=*,listen=all,tracing" dist + +To profile platform libraries start build of proper target like this: + + ./gradlew -PplatformLibsJvmArgs="-agentpath:$AGENT=probe_disable=*,listen=all,tracing" ios_arm64PlatformLibs + +To profile standalone code compilation use: + + JAVA_OPTS="-agentpath:$AGENT=probe_disable=*,listen=all,tracing" ./dist/bin/konanc file.kt + +Then attach to the desired application in YourKit GUI and use CPU tab to inspect CPU consuming methods. +Saving the trace may be needed for more analysis. Adjusting `-Xmx` in `$HOME/.yjp/ui.ini` could help +with the big traces. + +To perform memory profiling follow the steps above, and after attachment to the running process +use "Start Object Allocation Recording" button. See https://www.yourkit.com/docs/java/help/allocations.jsp for more details. + +## Compiler Gradle options + +There are several gradle flags one can use for Konan build. + +* **-Pbuild_flags** passes flags to the compiler used to build stdlib + + ./gradlew -Pbuild_flags="--disable lower_inline --print_ir" stdlib + +* **-Pshims** compiles LLVM interface with tracing "shims". Allowing one + to trace the LLVM calls from the compiler. + Make sure to rebuild the project. + + ./gradlew -Pshims=true dist + + ## Compiler environment variables + +* **KONAN_DATA_DIR** changes `.konan` local data directory location (`$HOME/.konan` by default). Works both with cli compiler and gradle plugin + + ## Testing + + ### Compiler integration tests + +To run blackbox compiler tests from JVM Kotlin use (takes time): + + ./gradlew run_external + +To update the blackbox compiler tests set TeamCity build number in `gradle.properties`: + + testKotlinVersion= + +* **-Pfilter** allows one to choose test files to run. + + ./gradlew -Pfilter=overflowLong.kt run_external + +* **-Pprefix** allows one to choose external test directories to run. Only tests from directories with given prefix will be executed. + + ./gradlew -Pprefix=build_external_compiler_codegen_box_cast run_external + +* **-Ptest_flags** passes flags to the compiler used to compile tests + + ./gradlew -Ptest_flags="--time" backend.native:tests:array0 + +* **-Ptest_target** specifies cross target for a test run. + + ./gradlew -Ptest_target=raspberrypi backend.native:tests:array0 + +* **-Premote=user@host** sets remote test execution login/hostname. Good for cross compiled tests. + + ./gradlew -Premote=kotlin@111.22.33.444 backend.native:tests:run + +* **-Ptest_verbose** enables printing compiler args and other helpful information during a test execution. + + ./gradlew -Ptest_verbose :backend.native:tests:mpp_optional_expectation + +* **-Ptest_two_stage** enables two-stage compilation of tests. If two-stage compilation is enabled, test sources are compiled into a klibrary +and then a final native binary is produced from this klibrary using the -Xinclude compiler flag. + + ./gradlew -Ptest_two_stage backend.native:tests:array0 + + ### Runtime unit tests + +To run runtime unit tests on the host machine for both mimalloc and the standard allocator: + + ./gradlew hostRuntimeTests + +To run tests for only one of these two allocators, run `hostStdAllocRuntimeTests` or `hostMimallocRuntimeTests`. + +We use [Google Test](https://github.com/google/googletest) to execute the runtime unit tests. The build automatically fetches +the specified Google Test revision to `runtime/googletest`. It is possible to manually modify the downloaded GTest sources for debug +purposes; the build will not overwrite them by default. + +To forcibly redownload Google Test when running tests, use the corresponding project property: + + ./gradlew hostRuntimeTests -Prefresh-gtest + +or run the `downloadGTest` task directly with the `--refresh` CLI key: + + ./gradlew downloadGTest --refresh + +To use a local GTest copy instead of the downloaded one, add the following line to `runtime/build.gradle.kts`: + + googletest.useLocalSources("") + + ## Performance measurement + + Firstly, it's necessary to build analyzer tool to have opportunity to compare different performance results: + + cd tools/benchmarksAnalyzer + ../../gradlew build + + To measure performance of Kotlin/Native compiler on existing benchmarks: + + ./gradlew :performance:konanRun + + **NOTE**: **konanRun** task needs built compiler and libs. To test against working tree make sure to run + + ./gradlew dist distPlatformLibs + + before **konanRun** + + **konanRun** task can be run separately for one/several benchmark applications: + + ./gradlew :performance:cinterop:konanRun + + **konanRun** task has parameter `filter` which allows to run only some subset of benchmarks: + + ./gradlew :performance:cinterop:konanRun --filter=struct,macros + + Or you can use `filterRegex` if you want to specify the filter as regexes: + + ./gradlew :performance:ring:konanRun --filterRegex=String.*,Loop.* + + There us also verbose mode to follow progress of running benchmarks + + ./gradlew :performance:cinterop:konanRun --verbose + + > Task :performance:cinterop:konanRun + [DEBUG] Warm up iterations for benchmark macros + [DEBUG] Running benchmark macros + ... + + There are also tasks for running benchmarks on JVM (pay attention, some benchmarks e.g. cinterop benchmarks can't be run on JVM) + + ./gradlew :performance:jvmRun + + Files with results of benchmarks run are saved in `performance/build/nativeReport.json` for konanRun and `jvmReport.json` for jvmRun. + You can change the output filename by setting the `nativeJson` property for konanRun and `jvmJson` for jvmRun: + + ./gradlew :performance:ring:konanRun --filter=String.*,Loop.* -PnativeJson=stringsAndLoops.json + + You can use the `compilerArgs` property to pass flags to the compiler used to compile the benchmarks: + + ./gradlew :performance:konanRun -PcompilerArgs="--time -g" + + To compare different results run benchmarksAnalyzer tool: + + cd tools/benchmarksAnalyzer/build/bin//benchmarksAnalyzerReleaseExecutable/ + ./benchmarksAnalyzer.kexe + + Tool has several renders which allow produce output report in different forms (text, html, etc.). To set up render use flag `--render/-r`. + Output can be redirected to file with flag `--output/-o`. + To get detailed information about supported options, please use `--help/-h`. + + Analyzer tool can compare both local files and files placed on Artifactory/TeamCity. + + File description stored on Artifactory + + artifactory::: + + Example + + artifactory:1.2-dev-7942:Windows10:nativeReport.json + + File description stored on TeamCity + + teamcity:: + + Example + + teamcity:id:42491947:nativeReport.json + + Pay attention, user and password information(with flag `-u :`) should be provided to get data from TeamCity. + +## Composite build and testing + +If you have a fix spanning both Kotlin and Kotlin/native workspaces you need to be able to test Kotlin/Native composite build. Here's how to do it manually: + +### Have a composite build with the proper Kotlin tag. + +Find the version of Kotlin the current native is guaranteed to build with. +The version is specified in `kotlin-native/gradle.properties`. For example: +``` +kotlinVersion=1.3.70-dev-1526 +``` +Checkout `kotlin` workspace to tag `build-1.3.70-dev-1526`. Make sure its path ends with `.../kotlin`. +Otherwise issues will arise. +Direct `kotlin-native` build to the kotlin with `kotlinProjectPath` in native's `gradle.properties`. + +Now you have the kotlin + kotlin-native combination that is known to build. +Apply your fix on top of both workspaces and run +``` +$ ./gradlew dist +``` + +in `kotlin-native` to check the buildability. + +### Testing native + +For a quick check use: +``` +$ ./gradlew sanity 2>&1 | tee log +``` + +For a longer, more thorough testing build the complete build. Make sure you are running it on a macOS. + + +Have a complete build: + +``` +$ ./gradlew bundle # includes dist as its part +``` + +then run two test sets: + +``` +$ ./gradlew backend.native:tests:run 2>&1 | tee log + +$ ./gradlew backend.native:tests:runExternal -Ptest_two_stage=true 2>&1 | tee log + +``` + +## LLVM + +See [BUILDING_LLVM.md](BUILDING_LLVM.md) if you want to build and use your own LLVM distribution +instead of provided one. + +### Using different LLVM distributions as part of Kotlin/Native compilation pipeline. + +`llvmHome.` variable in `/konan/konan.properties` controls +which LLVM distribution Kotlin/Native will use in its compilation pipeline. +You can replace its value with either `$llvm..{dev, user}` to use one of predefined distributions +or pass an absolute to your own distribution. +Don't forget to set `llvmVersion.` to the version of your LLVM distribution. + +### Playing with compilation pipeline. + +Following compiler phases control different parts of LLVM pipeline: +1. `LinkBitcodeDependencies`. Linkage of produced bitcode with runtime and some other dependencies. +2. `BitcodeOptimization`. Running LLVM optimization pipeline. +3. `ObjectFiles`. Compilation of bitcode with Clang. + +For example, pass `-Xdisable-phases=BitcodeOptimization` to skip optimization pipeline. +Note that disabling `LinkBitcodeDependencies` or `ObjectFiles` will break compilation pipeline. + +By default, compiler takes options for Clang from [konan.properties](konan/konan.properties) file +by combining `clangFlags.` and `clangFlags.` properties. +To override this behaviour, one can specify flag `-Xoverride-clang-options=`. + +Please note: +1. Kotlin Native passes bitcode files to Clang instead of C or C++, so many flags won't work. +2. `-c` should be passed because Kotlin/Native calls linker by itself. + +Another useful compiler option is `-Xtemporary-files-dir=` which allows +to specify a directory for intermediate compiler artifacts like bitcode and object files. + + +#### Example 1. Bitcode right after IR to Bitcode translation. +```shell script +konanc main.kt -produce bitcode -o bitcode.bc +``` + +#### Example 2. Bitcode after LLVM optimizations. +```shell script +konanc main.kt -Xtemporary-files-dir= -o +``` +`/.kt.bc` will contain bitcode after LLVM optimization pipeline. + +#### Example 3. Replace predefined LLVM pipeline with Clang options. +```shell script +konanc main.kt -Xdisable-phases=BitcodeOptimization -Xoverride-clang-options=-c,-O2 +``` + +## Running Clang the same way Kotlin/Native compiler does + +Kotlin/Native compiler (including `cinterop` tool) has machinery that manages LLVM, Clang and native SDKs for supported targets +and runs bundled Clang with proper arguments. +To utilize this machinery, use `$dist/bin/run_konan clang $tool $target $arguments`, e.g. +``` +$dist/bin/run_konan clang clang ios_arm64 1.c +``` +will print and run the following command: +``` +~/.konan/dependencies/clang-llvm-apple-8.0.0-darwin-macos/bin/clang \ + -B/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin \ + -fno-stack-protector -stdlib=libc++ -arch arm64 \ + -isysroot /Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS13.5.sdk \ + -miphoneos-version-min=9.0 1.c +``` + +The similar helper is available for LLVM tools, `$dist/bin/run_konan llvm $tool $arguments`. diff --git a/kotlin-native/IMMUTABILITY.md b/kotlin-native/IMMUTABILITY.md new file mode 100644 index 00000000000..746610d084a --- /dev/null +++ b/kotlin-native/IMMUTABILITY.md @@ -0,0 +1,31 @@ +# Immutability in Kotlin/Native + + Kotlin/Native implements strict mutability checks, ensuring +the important invariant that the object is either immutable or +accessible from the single thread at that moment in time (`mutable XOR global`). + + Immutability is a runtime property in Kotlin/Native, and can be applied +to an arbitrary object subgraph using the `kotlin.native.concurrent.freeze` function. +It makes all the objects reachable from the given one immutable, +such a transition is a one-way operation (i.e., objects cannot be unfrozen later). +Some naturally immutable objects such as `kotlin.String`, `kotlin.Int`, and +other primitive types, along with `AtomicInt` and `AtomicReference` are frozen +by default. If a mutating operation is applied to a frozen object, +an `InvalidMutabilityException` is thrown. + + To achieve `mutable XOR global` invariant, all globally visible state (currently, +`object` singletons and enums) are automatically frozen. If object freezing +is not desired, a `kotlin.native.ThreadLocal` annotation can be used, which will make +the object state thread local, and so, mutable (but the changed state is not visible to +other threads). + + Top level/global variables of non-primitive types are by default accessible in the +main thread (i.e., the thread which initialized _Kotlin/Native_ runtime first) only. +Access from another thread will lead to an `IncorrectDereferenceException` being thrown. +To make such variables accessible in other threads, you can use either the `@ThreadLocal` annotation, +and mark the value thread local or `@SharedImmutable`, which will make the value frozen and accessible +from other threads. + + Class `AtomicReference` can be used to publish the changed frozen state to +other threads, and so build patterns like shared caches. + diff --git a/kotlin-native/INTEROP.md b/kotlin-native/INTEROP.md new file mode 100644 index 00000000000..585b12087a9 --- /dev/null +++ b/kotlin-native/INTEROP.md @@ -0,0 +1,722 @@ +# _Kotlin/Native_ interoperability # + +## Introduction ## + + _Kotlin/Native_ follows the general tradition of Kotlin to provide excellent +existing platform software interoperability. In the case of a native platform, +the most important interoperability target is a C library. So _Kotlin/Native_ +comes with a `cinterop` tool, which can be used to quickly generate +everything needed to interact with an external library. + + The following workflow is expected when interacting with the native library. + * create a `.def` file describing what to include into bindings + * use the `cinterop` tool to produce Kotlin bindings + * run _Kotlin/Native_ compiler on an application to produce the final executable + + The interoperability tool analyses C headers and produces a "natural" mapping of +the types, functions, and constants into the Kotlin world. The generated stubs can be +imported into an IDE for the purpose of code completion and navigation. + + Interoperability with Swift/Objective-C is provided too and covered in a +separate document [OBJC_INTEROP.md](OBJC_INTEROP.md). + +## Platform libraries ## + + Note that in many cases there's no need to use custom interoperability library creation mechanisms described below, +as for APIs available on the platform standardized bindings called [platform libraries](PLATFORM_LIBS.md) +could be used. For example, POSIX on Linux/macOS platforms, Win32 on Windows platform, or Apple frameworks +on macOS/iOS are available this way. + +## Simple example ## + +Install libgit2 and prepare stubs for the git library: + +
+ +```bash + +cd samples/gitchurn +../../dist/bin/cinterop -def src/main/c_interop/libgit2.def \ + -compiler-option -I/usr/local/include -o libgit2 +``` + +
+ +Compile the client: + +
+ +```bash +../../dist/bin/kotlinc src/main/kotlin \ + -library libgit2 -o GitChurn +``` + +
+ +Run the client: + +
+ +```bash +./GitChurn.kexe ../.. +``` + +
+ + +## Creating bindings for a new library ## + + To create bindings for a new library, start by creating a `.def` file. +Structurally it's a simple property file, which looks like this: + +
+ +```c +headers = png.h +headerFilter = png.h +package = png +``` + +
+ + +Then run the `cinterop` tool with something like this (note that for host libraries that are not included +in the sysroot search paths, headers may be needed): + +
+ +```bash +cinterop -def png.def -compiler-option -I/usr/local/include -o png +``` + +
+ + +This command will produce a `png.klib` compiled library and +`png-build/kotlin` directory containing Kotlin source code for the library. + +If the behavior for a certain platform needs to be modified, you can use a format like +`compilerOpts.osx` or `compilerOpts.linux` to provide platform-specific values +to the options. + +Note, that the generated bindings are generally platform-specific, so if you are developing for +multiple targets, the bindings need to be regenerated. + +After the generation of bindings, they can be used by the IDE as a proxy view of the +native library. + +For a typical Unix library with a config script, the `compilerOpts` will likely contain +the output of a config script with the `--cflags` flag (maybe without exact paths). + +The output of a config script with `--libs` will be passed as a `-linkedArgs` `kotlinc` +flag value (quoted) when compiling. + +### Selecting library headers + +When library headers are imported to a C program with the `#include` directive, +all of the headers included by these headers are also included in the program. +So all header dependencies are included in generated stubs as well. + +This behavior is correct but it can be very inconvenient for some libraries. So +it is possible to specify in the `.def` file which of the included headers are to +be imported. The separate declarations from other headers can also be imported +in case of direct dependencies. + +#### Filtering headers by globs + +It is possible to filter headers by globs. The `headerFilter` property value +from the `.def` file is treated as a space-separated list of globs. If the +included header matches any of the globs, then the declarations from this header +are included into the bindings. + +The globs are applied to the header paths relative to the appropriate include +path elements, e.g. `time.h` or `curl/curl.h`. So if the library is usually +included with `#include `, then it would probably be +correct to filter headers with + +
+ +```c +headerFilter = SomeLibrary/** +``` + +
+ +If a `headerFilter` is not specified, then all headers are included. + +#### Filtering by module maps + +Some libraries have proper `module.modulemap` or `module.map` files in its +headers. For example, macOS and iOS system libraries and frameworks do. +The [module map file](https://clang.llvm.org/docs/Modules.html#module-map-language) +describes the correspondence between header files and modules. When the module +maps are available, the headers from the modules that are not included directly +can be filtered out using the experimental `excludeDependentModules` option of the +`.def` file: + +
+ +```c +headers = OpenGL/gl.h OpenGL/glu.h GLUT/glut.h +compilerOpts = -framework OpenGL -framework GLUT +excludeDependentModules = true +``` + +
+ + +When both `excludeDependentModules` and `headerFilter` are used, they are +applied as an intersection. + +### C compiler and linker options ### + + Options passed to the C compiler (used to analyze headers, such as preprocessor definitions) and the linker +(used to link final executables) can be passed in the definition file as `compilerOpts` and `linkerOpts` +respectively. For example + +
+ +```c +compilerOpts = -DFOO=bar +linkerOpts = -lpng +``` + +
+ +Target-specific options, only applicable to the certain target can be specified as well, such as + +
+ + ```c + compilerOpts = -DBAR=bar + compilerOpts.linux_x64 = -DFOO=foo1 + compilerOpts.mac_x64 = -DFOO=foo2 + ``` + +
+ +and so, C headers on Linux will be analyzed with `-DBAR=bar -DFOO=foo1` and on macOS with `-DBAR=bar -DFOO=foo2`. +Note that any definition file option can have both common and the platform-specific part. + +### Adding custom declarations ### + + Sometimes it is required to add custom C declarations to the library before +generating bindings (e.g., for [macros](#macros)). Instead of creating an +additional header file with these declarations, you can include them directly +to the end of the `.def` file, after a separating line, containing only the +separator sequence `---`: + +
+ +```c +headers = errno.h + +--- + +static inline int getErrno() { + return errno; +} +``` + +
+ +Note that this part of the `.def` file is treated as part of the header file, so +functions with the body should be declared as `static`. +The declarations are parsed after including the files from the `headers` list. + +### Including static library in your klib + +Sometimes it is more convenient to ship a static library with your product, +rather than assume it is available within the user's environment. +To include a static library into `.klib` use `staticLibrary` and `libraryPaths` +clauses. For example: + +
+ +```c +headers = foo.h +staticLibraries = libfoo.a +libraryPaths = /opt/local/lib /usr/local/opt/curl/lib +``` + +
+ +When given the above snippet the `cinterop` tool will search `libfoo.a` in +`/opt/local/lib` and `/usr/local/opt/curl/lib`, and if it is found include the +library binary into `klib`. + +When using such `klib` in your program, the library is linked automatically. + +## Using bindings ## + +### Basic interop types ### + +All the supported C types have corresponding representations in Kotlin: + +* Signed, unsigned integral, and floating point types are mapped to their + Kotlin counterpart with the same width. +* Pointers and arrays are mapped to `CPointer?`. +* Enums can be mapped to either Kotlin enum or integral values, depending on + heuristics and the [definition file hints](#definition-file-hints). +* Structs / unions are mapped to types having fields available via the dot notation, + i.e. `someStructInstance.field1`. +* `typedef` are represented as `typealias`. + +Also, any C type has the Kotlin type representing the lvalue of this type, +i.e., the value located in memory rather than a simple immutable self-contained +value. Think C++ references, as a similar concept. +For structs (and `typedef`s to structs) this representation is the main one +and has the same name as the struct itself, for Kotlin enums it is named +`${type}Var`, for `CPointer` it is `CPointerVar`, and for most other +types it is `${type}Var`. + +For types that have both representations, the one with a "lvalue" has a mutable +`.value` property for accessing the value. + +#### Pointer types #### + +The type argument `T` of `CPointer` must be one of the "lvalue" types +described above, e.g., the C type `struct S*` is mapped to `CPointer`, +`int8_t*` is mapped to `CPointer`, and `char**` is mapped to +`CPointer>`. + +C null pointer is represented as Kotlin's `null`, and the pointer type +`CPointer` is not nullable, but the `CPointer?` is. The values of this +type support all the Kotlin operations related to handling `null`, e.g. `?:`, `?.`, +`!!` etc.: + +
+ +```kotlin +val path = getenv("PATH")?.toKString() ?: "" +``` + +
+ +Since the arrays are also mapped to `CPointer`, it supports the `[]` operator +for accessing values by index: + +
+ +```kotlin +fun shift(ptr: CPointer, length: Int) { + for (index in 0 .. length - 2) { + ptr[index] = ptr[index + 1] + } +} +``` + +
+ +The `.pointed` property for `CPointer` returns the lvalue of type `T`, +pointed by this pointer. The reverse operation is `.ptr`: it takes the lvalue +and returns the pointer to it. + +`void*` is mapped to `COpaquePointer` – the special pointer type which is the +supertype for any other pointer type. So if the C function takes `void*`, then +the Kotlin binding accepts any `CPointer`. + +Casting a pointer (including `COpaquePointer`) can be done with +`.reinterpret`, e.g.: + +
+ +```kotlin +val intPtr = bytePtr.reinterpret() +``` + +
+ +or + +
+ +```kotlin +val intPtr: CPointer = bytePtr.reinterpret() +``` + +
+ +As is with C, these reinterpret casts are unsafe and can potentially lead to +subtle memory problems in the application. + +Also there are unsafe casts between `CPointer?` and `Long` available, +provided by the `.toLong()` and `.toCPointer()` extension methods: + +
+ +```kotlin +val longValue = ptr.toLong() +val originalPtr = longValue.toCPointer() +``` + +
+ +Note that if the type of the result is known from the context, the type argument +can be omitted as usual due to the type inference. + +### Memory allocation ### + +The native memory can be allocated using the `NativePlacement` interface, e.g. + +
+ +```kotlin +val byteVar = placement.alloc() +``` + +
+ +or + +
+ +```kotlin +val bytePtr = placement.allocArray(5) +``` + +
+ +The most "natural" placement is in the object `nativeHeap`. +It corresponds to allocating native memory with `malloc` and provides an additional +`.free()` operation to free allocated memory: + +
+ +```kotlin +val buffer = nativeHeap.allocArray(size) + +nativeHeap.free(buffer) +``` + +
+ +However, the lifetime of allocated memory is often bound to the lexical scope. +It is possible to define such scope with `memScoped { ... }`. +Inside the braces, the temporary placement is available as an implicit receiver, +so it is possible to allocate native memory with `alloc` and `allocArray`, +and the allocated memory will be automatically freed after leaving the scope. + +For example, the C function returning values through pointer parameters can be +used like + +
+ +```kotlin +val fileSize = memScoped { + val statBuf = alloc() + val error = stat("/", statBuf.ptr) + statBuf.st_size +} +``` + +
+ +### Passing pointers to bindings ### + +Although C pointers are mapped to the `CPointer` type, the C function +pointer-typed parameters are mapped to `CValuesRef`. When passing +`CPointer` as the value of such a parameter, it is passed to the C function as is. +However, the sequence of values can be passed instead of a pointer. In this case +the sequence is passed "by value", i.e., the C function receives the pointer to +the temporary copy of that sequence, which is valid only until the function returns. + +The `CValuesRef` representation of pointer parameters is designed to support +C array literals without explicit native memory allocation. +To construct the immutable self-contained sequence of C values, the following +methods are provided: + +* `${type}Array.toCValues()`, where `type` is the Kotlin primitive type +* `Array?>.toCValues()`, `List?>.toCValues()` +* `cValuesOf(vararg elements: ${type})`, where `type` is a primitive or pointer + +For example: + +C: + +
+ +```c +void foo(int* elements, int count); +... +int elements[] = {1, 2, 3}; +foo(elements, 3); +``` + +
+ +Kotlin: + +
+ +```kotlin +foo(cValuesOf(1, 2, 3), 3) +``` + +
+ +### Working with the strings ### + +Unlike other pointers, the parameters of type `const char*` are represented as +a Kotlin `String`. So it is possible to pass any Kotlin string to a binding +expecting a C string. + +There are also some tools available to convert between Kotlin and C strings +manually: + +* `fun CPointer.toKString(): String` +* `val String.cstr: CValuesRef`. + + To get the pointer, `.cstr` should be allocated in native memory, e.g. + +
+ + ``` + val cString = kotlinString.cstr.getPointer(nativeHeap) + ``` + +
+ +In all cases, the C string is supposed to be encoded as UTF-8. + +To skip automatic conversion and ensure raw pointers are used in the bindings, a `noStringConversion` +statement in the `.def` file could be used, i.e. + +
+ +```c +noStringConversion = LoadCursorA LoadCursorW +``` + +
+ +This way any value of type `CPointer` can be passed as an argument of `const char*` type. +If a Kotlin string should be passed, code like this could be used: + +
+ +```kotlin +memScoped { + LoadCursorA(null, "cursor.bmp".cstr.ptr) // for ASCII version + LoadCursorW(null, "cursor.bmp".wcstr.ptr) // for Unicode version +} +``` + +
+ +### Scope-local pointers ### + +It is possible to create a scope-stable pointer of C representation of `CValues` +instance using the `CValues.ptr` extension property, available under `memScoped { ... }`. +It allows using the APIs which require C pointers with a lifetime bound to a certain `MemScope`. For example: + +
+ +```kotlin +memScoped { + items = arrayOfNulls?>(6) + arrayOf("one", "two").forEachIndexed { index, value -> items[index] = value.cstr.ptr } + menu = new_menu("Menu".cstr.ptr, items.toCValues().ptr) + ... +} +``` + +
+ +In this example, all values passed to the C API `new_menu()` have a lifetime of the innermost `memScope` +it belongs to. Once the control flow leaves the `memScoped` scope the C pointers become invalid. + +### Passing and receiving structs by value ### + +When a C function takes or returns a struct / union `T` by value, the corresponding +argument type or return type is represented as `CValue`. + +`CValue` is an opaque type, so the structure fields cannot be accessed with +the appropriate Kotlin properties. It should be possible, if an API uses structures +as handles, but if field access is required, there are the following conversion +methods available: + +* `fun T.readValue(): CValue`. Converts (the lvalue) `T` to a `CValue`. + So to construct the `CValue`, `T` can be allocated, filled, and then + converted to `CValue`. + +* `CValue.useContents(block: T.() -> R): R`. Temporarily places the + `CValue` to memory, and then runs the passed lambda with this placed + value `T` as receiver. So to read a single field, the following code can be + used: + +
+ + ```kotlin + val fieldValue = structValue.useContents { field } + ``` + +
+ + +### Callbacks ### + +To convert a Kotlin function to a pointer to a C function, +`staticCFunction(::kotlinFunction)` can be used. It is also able to provide +the lambda instead of a function reference. The function or lambda must not +capture any values. + +If the callback doesn't run in the main thread, it is mandatory to init the _Kotlin/Native_ +runtime by calling `kotlin.native.initRuntimeIfNeeded()`. + +#### Passing user data to callbacks #### + +Often C APIs allow passing some user data to callbacks. Such data is usually +provided by the user when configuring the callback. It is passed to some C function +(or written to the struct) as e.g. `void*`. +However, references to Kotlin objects can't be directly passed to C. +So they require wrapping before configuring the callback and then unwrapping in +the callback itself, to safely swim from Kotlin to Kotlin through the C world. +Such wrapping is possible with `StableRef` class. + +To wrap the reference: + +
+ +```kotlin +val stableRef = StableRef.create(kotlinReference) +val voidPtr = stableRef.asCPointer() +``` + +
+ +where the `voidPtr` is a `COpaquePointer` and can be passed to the C function. + +To unwrap the reference: + +
+ +```kotlin +val stableRef = voidPtr.asStableRef() +val kotlinReference = stableRef.get() +``` + +
+ +where `kotlinReference` is the original wrapped reference. + +The created `StableRef` should eventually be manually disposed using +the `.dispose()` method to prevent memory leaks: + +
+ +```kotlin +stableRef.dispose() +``` + +
+ +After that it becomes invalid, so `voidPtr` can't be unwrapped anymore. + +See the `samples/libcurl` for more details. + +### Macros ### + +Every C macro that expands to a constant is represented as a Kotlin property. +Other macros are not supported. However, they can be exposed manually by +wrapping them with supported declarations. E.g. function-like macro `FOO` can be +exposed as function `foo` by +[adding the custom declaration](#adding-custom-declarations) to the library: + +
+ +```c +headers = library/base.h + +--- + +static inline int foo(int arg) { + return FOO(arg); +} +``` + +
+ +### Definition file hints ### + +The `.def` file supports several options for adjusting the generated bindings. + +* `excludedFunctions` property value specifies a space-separated list of the names + of functions that should be ignored. This may be required because a function + declared in the C header is not generally guaranteed to be really callable, and + it is often hard or impossible to figure this out automatically. This option + can also be used to workaround a bug in the interop itself. + +* `strictEnums` and `nonStrictEnums` properties values are space-separated + lists of the enums that should be generated as a Kotlin enum or as integral + values correspondingly. If the enum is not included into any of these lists, + then it is generated according to the heuristics. + +* `noStringConversion` property value is space-separated lists of the functions whose + `const char*` parameters shall not be autoconverted as Kotlin string + +### Portability ### + + Sometimes the C libraries have function parameters or struct fields of a +platform-dependent type, e.g. `long` or `size_t`. Kotlin itself doesn't provide +neither implicit integer casts nor C-style integer casts (e.g. +`(size_t) intValue`), so to make writing portable code in such cases easier, +the `convert` method is provided: + +
+ +```kotlin +fun ${type1}.convert<${type2}>(): ${type2} +``` +
+ +where each of `type1` and `type2` must be an integral type, either signed or unsigned. + +`.convert<${type}>` has the same semantics as one of the +`.toByte`, `.toShort`, `.toInt`, `.toLong`, +`.toUByte`, `.toUShort`, `.toUInt` or `.toULong` +methods, depending on `type`. + +The example of using `convert`: + +
+ +```kotlin +fun zeroMemory(buffer: COpaquePointer, size: Int) { + memset(buffer, 0, size.convert()) +} +``` + +
+ +Also, the type parameter can be inferred automatically and so may be omitted +in some cases. + + +### Object pinning ### + + Kotlin objects could be pinned, i.e. their position in memory is guaranteed to be stable +until unpinned, and pointers to such objects inner data could be passed to the C functions. For example + +
+ +```kotlin +fun readData(fd: Int): String { + val buffer = ByteArray(1024) + buffer.usePinned { pinned -> + while (true) { + val length = recv(fd, pinned.addressOf(0), buffer.size.convert(), 0).toInt() + + if (length <= 0) { + break + } + // Now `buffer` has raw data obtained from the `recv()` call. + } + } +} +``` + +
+ +Here we use service function `usePinned`, which pins an object, executes block and unpins it on normal and +exception paths. diff --git a/kotlin-native/IOS_SYMBOLICATION.md b/kotlin-native/IOS_SYMBOLICATION.md new file mode 100644 index 00000000000..c7d58ec0cc1 --- /dev/null +++ b/kotlin-native/IOS_SYMBOLICATION.md @@ -0,0 +1,74 @@ +# Symbolicating iOS crash reports + +Debugging an iOS application crash sometimes involves analyzing crash reports. +More info about crash reports can be found +[in the official documentation](https://developer.apple.com/library/archive/technotes/tn2151/_index.html). + +Crash reports generally require symbolication to become properly readable: +symbolication turns machine code addresses into human-readable source locations. +The document below describes some specific details of symbolicating crash reports +from iOS applications using Kotlin. + +## Producing .dSYM for release Kotlin binaries + +To symbolicate addresses in Kotlin code (e.g. for stack trace elements +corresponding to Kotlin code) `.dSYM` bundle for Kotlin code is required. + +By default Kotlin/Native compiler produces `.dSYM` for release +(i.e. optimized) binaries on Darwin platforms. This can be disabled with `-Xadd-light-debug=disable` +compiler flag. At the same time this option is disabled by default for other platforms, to enable it use `-Xadd-light-debug=enable`. +To control option in Gradle, use + +```kotlin +kotlin { + targets.withType { + binaries.all { + freeCompilerArgs += "-Xadd-light-debug={enable|disable}" + } + } +} +``` + +(in Kotlin DSL). + +In projects created from IntelliJ IDEA or AppCode templates these `.dSYM` bundles +are then discovered by Xcode automatically. + +## Make frameworks static when using rebuild from bitcode + +Rebuilding Kotlin-produced framework from bitcode invalidates the original `.dSYM`. +If it is performed locally, make sure the updated `.dSYM` is used when symbolicating +crash reports. + +If rebuilding is performed on App Store side, then `.dSYM` of rebuilt *dynamic* framework +seems discarded and not downloadable from App Store Connect. +So in this case it may be required to make the framework static, e.g. with + +```kotlin +kotlin { + targets.withType { + binaries.withType { + isStatic = true + } + } +} +``` + +(in Kotlin DSL). + +## Decode inlined stack frames + +Xcode doesn't seem to properly decode stack trace elements of inlined function +calls (these aren't only Kotlin `inline` functions but also functions that are +inlined when optimizing machine code). So some stack trace elements may be +missing. If this is the case, consider using `lldb` to process crash report +that is already symbolicated by Xcode, for example: + +```bash +$ lldb -b -o "script import lldb.macosx" -o "crashlog file.crash" +``` + +This command should output crash report that is additionally processed and +includes inlined stack trace elements. + +More details can be found in [LLDB documentation](https://lldb.llvm.org/use/symbolication.html). diff --git a/kotlin-native/Interop/.idea/compiler.xml b/kotlin-native/Interop/.idea/compiler.xml new file mode 100644 index 00000000000..96cc43efa6a --- /dev/null +++ b/kotlin-native/Interop/.idea/compiler.xml @@ -0,0 +1,22 @@ + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/kotlin-native/Interop/.idea/gradle.xml b/kotlin-native/Interop/.idea/gradle.xml new file mode 100644 index 00000000000..712ec676d10 --- /dev/null +++ b/kotlin-native/Interop/.idea/gradle.xml @@ -0,0 +1,23 @@ + + + + + + \ No newline at end of file diff --git a/kotlin-native/Interop/.idea/libraries/Gradle__org_jetbrains_kotlin_kotlin_runtime_1_0_3.xml b/kotlin-native/Interop/.idea/libraries/Gradle__org_jetbrains_kotlin_kotlin_runtime_1_0_3.xml new file mode 100644 index 00000000000..0eb057374b0 --- /dev/null +++ b/kotlin-native/Interop/.idea/libraries/Gradle__org_jetbrains_kotlin_kotlin_runtime_1_0_3.xml @@ -0,0 +1,11 @@ + + + + + + + + + + + \ No newline at end of file diff --git a/kotlin-native/Interop/.idea/libraries/Gradle__org_jetbrains_kotlin_kotlin_stdlib_1_0_3.xml b/kotlin-native/Interop/.idea/libraries/Gradle__org_jetbrains_kotlin_kotlin_stdlib_1_0_3.xml new file mode 100644 index 00000000000..ae3ca477567 --- /dev/null +++ b/kotlin-native/Interop/.idea/libraries/Gradle__org_jetbrains_kotlin_kotlin_stdlib_1_0_3.xml @@ -0,0 +1,11 @@ + + + + + + + + + + + \ No newline at end of file diff --git a/kotlin-native/Interop/.idea/modules.xml b/kotlin-native/Interop/.idea/modules.xml new file mode 100644 index 00000000000..9013d797b60 --- /dev/null +++ b/kotlin-native/Interop/.idea/modules.xml @@ -0,0 +1,10 @@ + + + + + + + + + + \ No newline at end of file diff --git a/kotlin-native/Interop/.idea/modules/Indexer/Indexer.iml b/kotlin-native/Interop/.idea/modules/Indexer/Indexer.iml new file mode 100644 index 00000000000..556176b4b39 --- /dev/null +++ b/kotlin-native/Interop/.idea/modules/Indexer/Indexer.iml @@ -0,0 +1,24 @@ + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/kotlin-native/Interop/.idea/modules/Runtime/Runtime.iml b/kotlin-native/Interop/.idea/modules/Runtime/Runtime.iml new file mode 100644 index 00000000000..91162e21499 --- /dev/null +++ b/kotlin-native/Interop/.idea/modules/Runtime/Runtime.iml @@ -0,0 +1,22 @@ + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/kotlin-native/Interop/.idea/modules/StubGenerator/StubGenerator.iml b/kotlin-native/Interop/.idea/modules/StubGenerator/StubGenerator.iml new file mode 100644 index 00000000000..79b649856d6 --- /dev/null +++ b/kotlin-native/Interop/.idea/modules/StubGenerator/StubGenerator.iml @@ -0,0 +1,24 @@ + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/kotlin-native/Interop/Indexer/build.gradle b/kotlin-native/Interop/Indexer/build.gradle new file mode 100644 index 00000000000..93d3ae019fd --- /dev/null +++ b/kotlin-native/Interop/Indexer/build.gradle @@ -0,0 +1,173 @@ +/* + * Copyright 2010-2017 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +buildscript { + ext.rootBuildDirectory = file('../..') + + apply from: "$rootBuildDirectory/gradle/kotlinGradlePlugin.gradle" + + dependencies { + classpath "org.jetbrains.kotlin:kotlin-stdlib:$kotlinVersion" + classpath "org.jetbrains.kotlin:kotlin-native-shared:$konanVersion" + } +} +apply plugin: 'kotlin' +apply plugin: org.jetbrains.kotlin.NativeInteropPlugin + +apply plugin: 'c' +apply plugin: 'cpp' + +import org.jetbrains.kotlin.konan.target.ClangArgs + +final Project libclangextProject = project(":libclangext") +final String libclangextTask = libclangextProject.path + ":build" +File libclangextDir = new File(libclangextProject.buildDir, "libs/clangext/static") +final boolean libclangextIsEnabled = libclangextProject.isEnabled + +final String libclang +if (isWindows()) { + libclang = "bin/libclang.dll" +} else { + libclang = "lib/${System.mapLibraryName("clang")}" +} + +List cflags = [ + "-I$llvmDir/include", + "-I${project(":libclangext").projectDir.absolutePath + "/src/main/include"}" +]*.toString() + +List ldflags = ["$llvmDir/$libclang", "-L$libclangextDir.absolutePath", "-lclangext"]*.toString() + +if (libclangextIsEnabled) { + assert(isMac()) + ldflags.addAll(['-Wl,--no-demangle', '-Wl,-search_paths_first', '-Wl,-headerpad_max_install_names', '-Wl,-U,_futimens', + '-Wl,-U,__ZN4llvm7remarks11parseFormatENS_9StringRefE', + '-Wl,-U,__ZN4llvm7remarks22createRemarkSerializerENS0_6FormatENS0_14SerializerModeERNS_11raw_ostreamE', + '-Wl,-U,__ZN4llvm7remarks14YAMLSerializerC1ERNS_11raw_ostreamENS0_14UseStringTableE']) + + List llvmLibs = [ + "clangAST", "clangASTMatchers", "clangAnalysis", "clangBasic", "clangDriver", "clangEdit", + "clangFrontend", "clangFrontendTool", "clangLex", "clangParse", "clangSema", "clangEdit", + "clangRewrite", "clangRewriteFrontend", "clangStaticAnalyzerFrontend", + "clangStaticAnalyzerCheckers", "clangStaticAnalyzerCore", "clangSerialization", + "clangToolingCore", + "clangTooling", "clangFormat", "LLVMTarget", "LLVMMC", "LLVMLinker", "LLVMTransformUtils", + "LLVMBitWriter", "LLVMBitReader", "LLVMAnalysis", "LLVMProfileData", "LLVMCore", + "LLVMSupport", "LLVMBinaryFormat", "LLVMDemangle" + ].collect { "$llvmDir/lib/lib${it}.a".toString() } + + ldflags.addAll(llvmLibs) + ldflags.addAll(['-lpthread', '-lz', '-lm', '-lcurses']) +} + + +model { + components { + clangstubs(NativeLibrarySpec) { + sources { + c.source.srcDir 'prebuilt/nativeInteropStubs/c' + cpp.source.srcDir 'src/nativeInteropStubs/cpp' + } + + binaries.all { + cCompiler.args hostPlatform.clang.hostCompilerArgsForJni + cCompiler.args.addAll(cflags) + } + + binaries.withType(SharedLibraryBinarySpec) { + linker.args.addAll(ldflags) + } + } + } + + toolChains { + clang(Clang) { + eachPlatform { + cppCompiler.withArguments(ClangArgs.&filterGradleNativeSoftwareFlags) + cCompiler.withArguments(ClangArgs.&filterGradleNativeSoftwareFlags) + } + } + } +} + +sourceSets { + main { + kotlin { + srcDirs 'prebuilt/nativeInteropStubs/kotlin' + } + } +} + +repositories { + maven { + url buildKotlinCompilerRepo + } +} + +dependencies { + compile "org.jetbrains.kotlin:kotlin-stdlib:$kotlinVersion" + compile project(':Interop:Runtime') +} + +task nativelibs(type: Copy) { + dependsOn 'clangstubsSharedLibrary' + + from "$buildDir/libs/clangstubs/shared/" + into "$buildDir/nativelibs/" +} + +classes.dependsOn nativelibs + +kotlinNativeInterop { + clang { + defFile 'clang.def' + compilerOpts cflags + linkerOpts ldflags + genTask.dependsOn libclangextTask + genTask.inputs.dir libclangextDir + } +} + +compileKotlin { + kotlinOptions { + allWarningsAsErrors=true + } +} + +tasks.matching { it.name == 'linkClangstubsSharedLibrary' }.all { + it.dependsOn libclangextTask + it.inputs.dir libclangextDir +} + +task updatePrebuilt { + dependsOn genClangInteropStubs + + doLast { + copy { + from("$buildDir/nativeInteropStubs/clang/kotlin") { + include 'clang/clang.kt' + } + into 'prebuilt/nativeInteropStubs/kotlin' + } + + copy { + from("$buildDir/interopTemp") { + include 'clangstubs.c' + } + into 'prebuilt/nativeInteropStubs/c' + } + } +} diff --git a/kotlin-native/Interop/Indexer/clang.def b/kotlin-native/Interop/Indexer/clang.def new file mode 100644 index 00000000000..9bbd52a7b1d --- /dev/null +++ b/kotlin-native/Interop/Indexer/clang.def @@ -0,0 +1,16 @@ +headers = clang-c/Index.h clang-c/ext.h clang-c/ExtVector.h + +headerFilter = clang-c/** + +compiler = clang + +compilerOpts = -std=c99 -fPIC +linkerOpts.linux = -Wl,-z,noexecstack + +linker = clang++ + +linkerOpts = -fPIC + +strictEnums = CXErrorCode CXCursorKind CXTypeKind CXDiagnosticSeverity CXLoadDiag_Error CXSaveError \ + CXTUResourceUsageKind CXLinkageKind CXVisibilityKind CXLanguageKind CXCallingConv CXChildVisitResult \ + CXTokenKind CXEvalResultKind CXVisitorResult CXResult CXIdxEntityKind diff --git a/kotlin-native/Interop/Indexer/prebuilt/nativeInteropStubs/c/clangstubs.c b/kotlin-native/Interop/Indexer/prebuilt/nativeInteropStubs/c/clangstubs.c new file mode 100644 index 00000000000..6930a9792c3 --- /dev/null +++ b/kotlin-native/Interop/Indexer/prebuilt/nativeInteropStubs/c/clangstubs.c @@ -0,0 +1,1124 @@ +#include +#include +#include +#include +#include + +// NOTE THIS FILE IS AUTO-GENERATED + +JNIEXPORT jlong JNICALL Java_clang_clang_kniBridge0 (JNIEnv* jniEnv, jclass jclss, jlong p0) { + return (jlong)clang_getCString(*(CXString*)p0); +} +JNIEXPORT void JNICALL Java_clang_clang_kniBridge1 (JNIEnv* jniEnv, jclass jclss, jlong p0) { + clang_disposeString(*(CXString*)p0); +} +JNIEXPORT void JNICALL Java_clang_clang_kniBridge2 (JNIEnv* jniEnv, jclass jclss, jlong p0) { + clang_disposeStringSet((CXStringSet*)p0); +} +JNIEXPORT jlong JNICALL Java_clang_clang_kniBridge3 (JNIEnv* jniEnv, jclass jclss) { + return (jlong)clang_getBuildSessionTimestamp(); +} +JNIEXPORT jlong JNICALL Java_clang_clang_kniBridge4 (JNIEnv* jniEnv, jclass jclss, jint p0) { + return (jlong)clang_VirtualFileOverlay_create(p0); +} +JNIEXPORT jint JNICALL Java_clang_clang_kniBridge5 (JNIEnv* jniEnv, jclass jclss, jlong p0, jlong p1, jlong p2) { + return (jint)clang_VirtualFileOverlay_addFileMapping((struct CXVirtualFileOverlayImpl*)p0, (char*)p1, (char*)p2); +} +JNIEXPORT jint JNICALL Java_clang_clang_kniBridge6 (JNIEnv* jniEnv, jclass jclss, jlong p0, jint p1) { + return (jint)clang_VirtualFileOverlay_setCaseSensitivity((struct CXVirtualFileOverlayImpl*)p0, p1); +} +JNIEXPORT jint JNICALL Java_clang_clang_kniBridge7 (JNIEnv* jniEnv, jclass jclss, jlong p0, jint p1, jlong p2, jlong p3) { + return (jint)clang_VirtualFileOverlay_writeToBuffer((struct CXVirtualFileOverlayImpl*)p0, p1, (char**)p2, (unsigned int*)p3); +} +JNIEXPORT void JNICALL Java_clang_clang_kniBridge8 (JNIEnv* jniEnv, jclass jclss, jlong p0) { + clang_free((void*)p0); +} +JNIEXPORT void JNICALL Java_clang_clang_kniBridge9 (JNIEnv* jniEnv, jclass jclss, jlong p0) { + clang_VirtualFileOverlay_dispose((struct CXVirtualFileOverlayImpl*)p0); +} +JNIEXPORT jlong JNICALL Java_clang_clang_kniBridge10 (JNIEnv* jniEnv, jclass jclss, jint p0) { + return (jlong)clang_ModuleMapDescriptor_create(p0); +} +JNIEXPORT jint JNICALL Java_clang_clang_kniBridge11 (JNIEnv* jniEnv, jclass jclss, jlong p0, jlong p1) { + return (jint)clang_ModuleMapDescriptor_setFrameworkModuleName((struct CXModuleMapDescriptorImpl*)p0, (char*)p1); +} +JNIEXPORT jint JNICALL Java_clang_clang_kniBridge12 (JNIEnv* jniEnv, jclass jclss, jlong p0, jlong p1) { + return (jint)clang_ModuleMapDescriptor_setUmbrellaHeader((struct CXModuleMapDescriptorImpl*)p0, (char*)p1); +} +JNIEXPORT jint JNICALL Java_clang_clang_kniBridge13 (JNIEnv* jniEnv, jclass jclss, jlong p0, jint p1, jlong p2, jlong p3) { + return (jint)clang_ModuleMapDescriptor_writeToBuffer((struct CXModuleMapDescriptorImpl*)p0, p1, (char**)p2, (unsigned int*)p3); +} +JNIEXPORT void JNICALL Java_clang_clang_kniBridge14 (JNIEnv* jniEnv, jclass jclss, jlong p0) { + clang_ModuleMapDescriptor_dispose((struct CXModuleMapDescriptorImpl*)p0); +} +JNIEXPORT jlong JNICALL Java_clang_clang_kniBridge15 (JNIEnv* jniEnv, jclass jclss, jint p0, jint p1) { + return (jlong)clang_createIndex(p0, p1); +} +JNIEXPORT void JNICALL Java_clang_clang_kniBridge16 (JNIEnv* jniEnv, jclass jclss, jlong p0) { + clang_disposeIndex((void*)p0); +} +JNIEXPORT void JNICALL Java_clang_clang_kniBridge17 (JNIEnv* jniEnv, jclass jclss, jlong p0, jint p1) { + clang_CXIndex_setGlobalOptions((void*)p0, p1); +} +JNIEXPORT jint JNICALL Java_clang_clang_kniBridge18 (JNIEnv* jniEnv, jclass jclss, jlong p0) { + return (jint)clang_CXIndex_getGlobalOptions((void*)p0); +} +JNIEXPORT void JNICALL Java_clang_clang_kniBridge19 (JNIEnv* jniEnv, jclass jclss, jlong p0, jlong p1) { + clang_CXIndex_setInvocationEmissionPathOption((void*)p0, (char*)p1); +} +JNIEXPORT void JNICALL Java_clang_clang_kniBridge20 (JNIEnv* jniEnv, jclass jclss, jlong p0, jlong p1) { + CXString kniStructResult = clang_getFileName((void*)p0); + memcpy(p1, &kniStructResult, sizeof(kniStructResult)); +} +JNIEXPORT jlong JNICALL Java_clang_clang_kniBridge21 (JNIEnv* jniEnv, jclass jclss, jlong p0) { + return (jlong)clang_getFileTime((void*)p0); +} +JNIEXPORT jint JNICALL Java_clang_clang_kniBridge22 (JNIEnv* jniEnv, jclass jclss, jlong p0, jlong p1) { + return (jint)clang_getFileUniqueID((void*)p0, (CXFileUniqueID*)p1); +} +JNIEXPORT jint JNICALL Java_clang_clang_kniBridge23 (JNIEnv* jniEnv, jclass jclss, jlong p0, jlong p1) { + return (jint)clang_isFileMultipleIncludeGuarded((struct CXTranslationUnitImpl*)p0, (void*)p1); +} +JNIEXPORT jlong JNICALL Java_clang_clang_kniBridge24 (JNIEnv* jniEnv, jclass jclss, jlong p0, jlong p1) { + return (jlong)clang_getFile((struct CXTranslationUnitImpl*)p0, (char*)p1); +} +JNIEXPORT jlong JNICALL Java_clang_clang_kniBridge25 (JNIEnv* jniEnv, jclass jclss, jlong p0, jlong p1, jlong p2) { + return (jlong)clang_getFileContents((struct CXTranslationUnitImpl*)p0, (void*)p1, (unsigned long*)p2); +} +JNIEXPORT jint JNICALL Java_clang_clang_kniBridge26 (JNIEnv* jniEnv, jclass jclss, jlong p0, jlong p1) { + return (jint)clang_File_isEqual((void*)p0, (void*)p1); +} +JNIEXPORT void JNICALL Java_clang_clang_kniBridge27 (JNIEnv* jniEnv, jclass jclss, jlong p0, jlong p1) { + CXString kniStructResult = clang_File_tryGetRealPathName((void*)p0); + memcpy(p1, &kniStructResult, sizeof(kniStructResult)); +} +JNIEXPORT void JNICALL Java_clang_clang_kniBridge28 (JNIEnv* jniEnv, jclass jclss, jlong p0) { + CXSourceLocation kniStructResult = clang_getNullLocation(); + memcpy(p0, &kniStructResult, sizeof(kniStructResult)); +} +JNIEXPORT jint JNICALL Java_clang_clang_kniBridge29 (JNIEnv* jniEnv, jclass jclss, jlong p0, jlong p1) { + return (jint)clang_equalLocations(*(CXSourceLocation*)p0, *(CXSourceLocation*)p1); +} +JNIEXPORT void JNICALL Java_clang_clang_kniBridge30 (JNIEnv* jniEnv, jclass jclss, jlong p0, jlong p1, jint p2, jint p3, jlong p4) { + CXSourceLocation kniStructResult = clang_getLocation((struct CXTranslationUnitImpl*)p0, (void*)p1, p2, p3); + memcpy(p4, &kniStructResult, sizeof(kniStructResult)); +} +JNIEXPORT void JNICALL Java_clang_clang_kniBridge31 (JNIEnv* jniEnv, jclass jclss, jlong p0, jlong p1, jint p2, jlong p3) { + CXSourceLocation kniStructResult = clang_getLocationForOffset((struct CXTranslationUnitImpl*)p0, (void*)p1, p2); + memcpy(p3, &kniStructResult, sizeof(kniStructResult)); +} +JNIEXPORT jint JNICALL Java_clang_clang_kniBridge32 (JNIEnv* jniEnv, jclass jclss, jlong p0) { + return (jint)clang_Location_isInSystemHeader(*(CXSourceLocation*)p0); +} +JNIEXPORT jint JNICALL Java_clang_clang_kniBridge33 (JNIEnv* jniEnv, jclass jclss, jlong p0) { + return (jint)clang_Location_isFromMainFile(*(CXSourceLocation*)p0); +} +JNIEXPORT void JNICALL Java_clang_clang_kniBridge34 (JNIEnv* jniEnv, jclass jclss, jlong p0) { + CXSourceRange kniStructResult = clang_getNullRange(); + memcpy(p0, &kniStructResult, sizeof(kniStructResult)); +} +JNIEXPORT void JNICALL Java_clang_clang_kniBridge35 (JNIEnv* jniEnv, jclass jclss, jlong p0, jlong p1, jlong p2) { + CXSourceRange kniStructResult = clang_getRange(*(CXSourceLocation*)p0, *(CXSourceLocation*)p1); + memcpy(p2, &kniStructResult, sizeof(kniStructResult)); +} +JNIEXPORT jint JNICALL Java_clang_clang_kniBridge36 (JNIEnv* jniEnv, jclass jclss, jlong p0, jlong p1) { + return (jint)clang_equalRanges(*(CXSourceRange*)p0, *(CXSourceRange*)p1); +} +JNIEXPORT jint JNICALL Java_clang_clang_kniBridge37 (JNIEnv* jniEnv, jclass jclss, jlong p0) { + return (jint)clang_Range_isNull(*(CXSourceRange*)p0); +} +JNIEXPORT void JNICALL Java_clang_clang_kniBridge38 (JNIEnv* jniEnv, jclass jclss, jlong p0, jlong p1, jlong p2, jlong p3, jlong p4) { + clang_getExpansionLocation(*(CXSourceLocation*)p0, (void*)p1, (unsigned int*)p2, (unsigned int*)p3, (unsigned int*)p4); +} +JNIEXPORT void JNICALL Java_clang_clang_kniBridge39 (JNIEnv* jniEnv, jclass jclss, jlong p0, jlong p1, jlong p2, jlong p3) { + clang_getPresumedLocation(*(CXSourceLocation*)p0, (CXString*)p1, (unsigned int*)p2, (unsigned int*)p3); +} +JNIEXPORT void JNICALL Java_clang_clang_kniBridge40 (JNIEnv* jniEnv, jclass jclss, jlong p0, jlong p1, jlong p2, jlong p3, jlong p4) { + clang_getInstantiationLocation(*(CXSourceLocation*)p0, (void*)p1, (unsigned int*)p2, (unsigned int*)p3, (unsigned int*)p4); +} +JNIEXPORT void JNICALL Java_clang_clang_kniBridge41 (JNIEnv* jniEnv, jclass jclss, jlong p0, jlong p1, jlong p2, jlong p3, jlong p4) { + clang_getSpellingLocation(*(CXSourceLocation*)p0, (void*)p1, (unsigned int*)p2, (unsigned int*)p3, (unsigned int*)p4); +} +JNIEXPORT void JNICALL Java_clang_clang_kniBridge42 (JNIEnv* jniEnv, jclass jclss, jlong p0, jlong p1, jlong p2, jlong p3, jlong p4) { + clang_getFileLocation(*(CXSourceLocation*)p0, (void*)p1, (unsigned int*)p2, (unsigned int*)p3, (unsigned int*)p4); +} +JNIEXPORT void JNICALL Java_clang_clang_kniBridge43 (JNIEnv* jniEnv, jclass jclss, jlong p0, jlong p1) { + CXSourceLocation kniStructResult = clang_getRangeStart(*(CXSourceRange*)p0); + memcpy(p1, &kniStructResult, sizeof(kniStructResult)); +} +JNIEXPORT void JNICALL Java_clang_clang_kniBridge44 (JNIEnv* jniEnv, jclass jclss, jlong p0, jlong p1) { + CXSourceLocation kniStructResult = clang_getRangeEnd(*(CXSourceRange*)p0); + memcpy(p1, &kniStructResult, sizeof(kniStructResult)); +} +JNIEXPORT jlong JNICALL Java_clang_clang_kniBridge45 (JNIEnv* jniEnv, jclass jclss, jlong p0, jlong p1) { + return (jlong)clang_getSkippedRanges((struct CXTranslationUnitImpl*)p0, (void*)p1); +} +JNIEXPORT jlong JNICALL Java_clang_clang_kniBridge46 (JNIEnv* jniEnv, jclass jclss, jlong p0) { + return (jlong)clang_getAllSkippedRanges((struct CXTranslationUnitImpl*)p0); +} +JNIEXPORT void JNICALL Java_clang_clang_kniBridge47 (JNIEnv* jniEnv, jclass jclss, jlong p0) { + clang_disposeSourceRangeList((CXSourceRangeList*)p0); +} +JNIEXPORT jint JNICALL Java_clang_clang_kniBridge48 (JNIEnv* jniEnv, jclass jclss, jlong p0) { + return (jint)clang_getNumDiagnosticsInSet((void*)p0); +} +JNIEXPORT jlong JNICALL Java_clang_clang_kniBridge49 (JNIEnv* jniEnv, jclass jclss, jlong p0, jint p1) { + return (jlong)clang_getDiagnosticInSet((void*)p0, p1); +} +JNIEXPORT jlong JNICALL Java_clang_clang_kniBridge50 (JNIEnv* jniEnv, jclass jclss, jlong p0, jlong p1, jlong p2) { + return (jlong)clang_loadDiagnostics((char*)p0, (void*)p1, (CXString*)p2); +} +JNIEXPORT void JNICALL Java_clang_clang_kniBridge51 (JNIEnv* jniEnv, jclass jclss, jlong p0) { + clang_disposeDiagnosticSet((void*)p0); +} +JNIEXPORT jlong JNICALL Java_clang_clang_kniBridge52 (JNIEnv* jniEnv, jclass jclss, jlong p0) { + return (jlong)clang_getChildDiagnostics((void*)p0); +} +JNIEXPORT jint JNICALL Java_clang_clang_kniBridge53 (JNIEnv* jniEnv, jclass jclss, jlong p0) { + return (jint)clang_getNumDiagnostics((struct CXTranslationUnitImpl*)p0); +} +JNIEXPORT jlong JNICALL Java_clang_clang_kniBridge54 (JNIEnv* jniEnv, jclass jclss, jlong p0, jint p1) { + return (jlong)clang_getDiagnostic((struct CXTranslationUnitImpl*)p0, p1); +} +JNIEXPORT jlong JNICALL Java_clang_clang_kniBridge55 (JNIEnv* jniEnv, jclass jclss, jlong p0) { + return (jlong)clang_getDiagnosticSetFromTU((struct CXTranslationUnitImpl*)p0); +} +JNIEXPORT void JNICALL Java_clang_clang_kniBridge56 (JNIEnv* jniEnv, jclass jclss, jlong p0) { + clang_disposeDiagnostic((void*)p0); +} +JNIEXPORT void JNICALL Java_clang_clang_kniBridge57 (JNIEnv* jniEnv, jclass jclss, jlong p0, jint p1, jlong p2) { + CXString kniStructResult = clang_formatDiagnostic((void*)p0, p1); + memcpy(p2, &kniStructResult, sizeof(kniStructResult)); +} +JNIEXPORT jint JNICALL Java_clang_clang_kniBridge58 (JNIEnv* jniEnv, jclass jclss) { + return (jint)clang_defaultDiagnosticDisplayOptions(); +} +JNIEXPORT jint JNICALL Java_clang_clang_kniBridge59 (JNIEnv* jniEnv, jclass jclss, jlong p0) { + return (jint)clang_getDiagnosticSeverity((void*)p0); +} +JNIEXPORT void JNICALL Java_clang_clang_kniBridge60 (JNIEnv* jniEnv, jclass jclss, jlong p0, jlong p1) { + CXSourceLocation kniStructResult = clang_getDiagnosticLocation((void*)p0); + memcpy(p1, &kniStructResult, sizeof(kniStructResult)); +} +JNIEXPORT void JNICALL Java_clang_clang_kniBridge61 (JNIEnv* jniEnv, jclass jclss, jlong p0, jlong p1) { + CXString kniStructResult = clang_getDiagnosticSpelling((void*)p0); + memcpy(p1, &kniStructResult, sizeof(kniStructResult)); +} +JNIEXPORT void JNICALL Java_clang_clang_kniBridge62 (JNIEnv* jniEnv, jclass jclss, jlong p0, jlong p1, jlong p2) { + CXString kniStructResult = clang_getDiagnosticOption((void*)p0, (CXString*)p1); + memcpy(p2, &kniStructResult, sizeof(kniStructResult)); +} +JNIEXPORT jint JNICALL Java_clang_clang_kniBridge63 (JNIEnv* jniEnv, jclass jclss, jlong p0) { + return (jint)clang_getDiagnosticCategory((void*)p0); +} +JNIEXPORT void JNICALL Java_clang_clang_kniBridge64 (JNIEnv* jniEnv, jclass jclss, jint p0, jlong p1) { + CXString kniStructResult = clang_getDiagnosticCategoryName(p0); + memcpy(p1, &kniStructResult, sizeof(kniStructResult)); +} +JNIEXPORT void JNICALL Java_clang_clang_kniBridge65 (JNIEnv* jniEnv, jclass jclss, jlong p0, jlong p1) { + CXString kniStructResult = clang_getDiagnosticCategoryText((void*)p0); + memcpy(p1, &kniStructResult, sizeof(kniStructResult)); +} +JNIEXPORT jint JNICALL Java_clang_clang_kniBridge66 (JNIEnv* jniEnv, jclass jclss, jlong p0) { + return (jint)clang_getDiagnosticNumRanges((void*)p0); +} +JNIEXPORT void JNICALL Java_clang_clang_kniBridge67 (JNIEnv* jniEnv, jclass jclss, jlong p0, jint p1, jlong p2) { + CXSourceRange kniStructResult = clang_getDiagnosticRange((void*)p0, p1); + memcpy(p2, &kniStructResult, sizeof(kniStructResult)); +} +JNIEXPORT jint JNICALL Java_clang_clang_kniBridge68 (JNIEnv* jniEnv, jclass jclss, jlong p0) { + return (jint)clang_getDiagnosticNumFixIts((void*)p0); +} +JNIEXPORT void JNICALL Java_clang_clang_kniBridge69 (JNIEnv* jniEnv, jclass jclss, jlong p0, jint p1, jlong p2, jlong p3) { + CXString kniStructResult = clang_getDiagnosticFixIt((void*)p0, p1, (CXSourceRange*)p2); + memcpy(p3, &kniStructResult, sizeof(kniStructResult)); +} +JNIEXPORT void JNICALL Java_clang_clang_kniBridge70 (JNIEnv* jniEnv, jclass jclss, jlong p0, jlong p1) { + CXString kniStructResult = clang_getTranslationUnitSpelling((struct CXTranslationUnitImpl*)p0); + memcpy(p1, &kniStructResult, sizeof(kniStructResult)); +} +JNIEXPORT jlong JNICALL Java_clang_clang_kniBridge71 (JNIEnv* jniEnv, jclass jclss, jlong p0, jlong p1, jint p2, jlong p3, jint p4, jlong p5) { + return (jlong)clang_createTranslationUnitFromSourceFile((void*)p0, (char*)p1, p2, (char**)p3, p4, (struct CXUnsavedFile*)p5); +} +JNIEXPORT jlong JNICALL Java_clang_clang_kniBridge72 (JNIEnv* jniEnv, jclass jclss, jlong p0, jlong p1) { + return (jlong)clang_createTranslationUnit((void*)p0, (char*)p1); +} +JNIEXPORT jint JNICALL Java_clang_clang_kniBridge73 (JNIEnv* jniEnv, jclass jclss, jlong p0, jlong p1, jlong p2) { + return (jint)clang_createTranslationUnit2((void*)p0, (char*)p1, (struct CXTranslationUnitImpl**)p2); +} +JNIEXPORT jint JNICALL Java_clang_clang_kniBridge74 (JNIEnv* jniEnv, jclass jclss) { + return (jint)clang_defaultEditingTranslationUnitOptions(); +} +JNIEXPORT jlong JNICALL Java_clang_clang_kniBridge75 (JNIEnv* jniEnv, jclass jclss, jlong p0, jlong p1, jlong p2, jint p3, jlong p4, jint p5, jint p6) { + return (jlong)clang_parseTranslationUnit((void*)p0, (char*)p1, (char**)p2, p3, (struct CXUnsavedFile*)p4, p5, p6); +} +JNIEXPORT jint JNICALL Java_clang_clang_kniBridge76 (JNIEnv* jniEnv, jclass jclss, jlong p0, jlong p1, jlong p2, jint p3, jlong p4, jint p5, jint p6, jlong p7) { + return (jint)clang_parseTranslationUnit2((void*)p0, (char*)p1, (char**)p2, p3, (struct CXUnsavedFile*)p4, p5, p6, (struct CXTranslationUnitImpl**)p7); +} +JNIEXPORT jint JNICALL Java_clang_clang_kniBridge77 (JNIEnv* jniEnv, jclass jclss, jlong p0, jlong p1, jlong p2, jint p3, jlong p4, jint p5, jint p6, jlong p7) { + return (jint)clang_parseTranslationUnit2FullArgv((void*)p0, (char*)p1, (char**)p2, p3, (struct CXUnsavedFile*)p4, p5, p6, (struct CXTranslationUnitImpl**)p7); +} +JNIEXPORT jint JNICALL Java_clang_clang_kniBridge78 (JNIEnv* jniEnv, jclass jclss, jlong p0) { + return (jint)clang_defaultSaveOptions((struct CXTranslationUnitImpl*)p0); +} +JNIEXPORT jint JNICALL Java_clang_clang_kniBridge79 (JNIEnv* jniEnv, jclass jclss, jlong p0, jlong p1, jint p2) { + return (jint)clang_saveTranslationUnit((struct CXTranslationUnitImpl*)p0, (char*)p1, p2); +} +JNIEXPORT jint JNICALL Java_clang_clang_kniBridge80 (JNIEnv* jniEnv, jclass jclss, jlong p0) { + return (jint)clang_suspendTranslationUnit((struct CXTranslationUnitImpl*)p0); +} +JNIEXPORT void JNICALL Java_clang_clang_kniBridge81 (JNIEnv* jniEnv, jclass jclss, jlong p0) { + clang_disposeTranslationUnit((struct CXTranslationUnitImpl*)p0); +} +JNIEXPORT jint JNICALL Java_clang_clang_kniBridge82 (JNIEnv* jniEnv, jclass jclss, jlong p0) { + return (jint)clang_defaultReparseOptions((struct CXTranslationUnitImpl*)p0); +} +JNIEXPORT jint JNICALL Java_clang_clang_kniBridge83 (JNIEnv* jniEnv, jclass jclss, jlong p0, jint p1, jlong p2, jint p3) { + return (jint)clang_reparseTranslationUnit((struct CXTranslationUnitImpl*)p0, p1, (struct CXUnsavedFile*)p2, p3); +} +JNIEXPORT jlong JNICALL Java_clang_clang_kniBridge84 (JNIEnv* jniEnv, jclass jclss, jint p0) { + return (jlong)clang_getTUResourceUsageName(p0); +} +JNIEXPORT void JNICALL Java_clang_clang_kniBridge85 (JNIEnv* jniEnv, jclass jclss, jlong p0, jlong p1) { + struct CXTUResourceUsage kniStructResult = clang_getCXTUResourceUsage((struct CXTranslationUnitImpl*)p0); + memcpy(p1, &kniStructResult, sizeof(kniStructResult)); +} +JNIEXPORT void JNICALL Java_clang_clang_kniBridge86 (JNIEnv* jniEnv, jclass jclss, jlong p0) { + clang_disposeCXTUResourceUsage(*(struct CXTUResourceUsage*)p0); +} +JNIEXPORT jlong JNICALL Java_clang_clang_kniBridge87 (JNIEnv* jniEnv, jclass jclss, jlong p0) { + return (jlong)clang_getTranslationUnitTargetInfo((struct CXTranslationUnitImpl*)p0); +} +JNIEXPORT void JNICALL Java_clang_clang_kniBridge88 (JNIEnv* jniEnv, jclass jclss, jlong p0) { + clang_TargetInfo_dispose((struct CXTargetInfoImpl*)p0); +} +JNIEXPORT void JNICALL Java_clang_clang_kniBridge89 (JNIEnv* jniEnv, jclass jclss, jlong p0, jlong p1) { + CXString kniStructResult = clang_TargetInfo_getTriple((struct CXTargetInfoImpl*)p0); + memcpy(p1, &kniStructResult, sizeof(kniStructResult)); +} +JNIEXPORT jint JNICALL Java_clang_clang_kniBridge90 (JNIEnv* jniEnv, jclass jclss, jlong p0) { + return (jint)clang_TargetInfo_getPointerWidth((struct CXTargetInfoImpl*)p0); +} +JNIEXPORT void JNICALL Java_clang_clang_kniBridge91 (JNIEnv* jniEnv, jclass jclss, jlong p0) { + CXCursor kniStructResult = clang_getNullCursor(); + memcpy(p0, &kniStructResult, sizeof(kniStructResult)); +} +JNIEXPORT void JNICALL Java_clang_clang_kniBridge92 (JNIEnv* jniEnv, jclass jclss, jlong p0, jlong p1) { + CXCursor kniStructResult = clang_getTranslationUnitCursor((struct CXTranslationUnitImpl*)p0); + memcpy(p1, &kniStructResult, sizeof(kniStructResult)); +} +JNIEXPORT jint JNICALL Java_clang_clang_kniBridge93 (JNIEnv* jniEnv, jclass jclss, jlong p0, jlong p1) { + return (jint)clang_equalCursors(*(CXCursor*)p0, *(CXCursor*)p1); +} +JNIEXPORT jint JNICALL Java_clang_clang_kniBridge94 (JNIEnv* jniEnv, jclass jclss, jlong p0) { + return (jint)clang_Cursor_isNull(*(CXCursor*)p0); +} +JNIEXPORT jint JNICALL Java_clang_clang_kniBridge95 (JNIEnv* jniEnv, jclass jclss, jlong p0) { + return (jint)clang_hashCursor(*(CXCursor*)p0); +} +JNIEXPORT jint JNICALL Java_clang_clang_kniBridge96 (JNIEnv* jniEnv, jclass jclss, jlong p0) { + return (jint)clang_getCursorKind(*(CXCursor*)p0); +} +JNIEXPORT jint JNICALL Java_clang_clang_kniBridge97 (JNIEnv* jniEnv, jclass jclss, jint p0) { + return (jint)clang_isDeclaration(p0); +} +JNIEXPORT jint JNICALL Java_clang_clang_kniBridge98 (JNIEnv* jniEnv, jclass jclss, jlong p0) { + return (jint)clang_isInvalidDeclaration(*(CXCursor*)p0); +} +JNIEXPORT jint JNICALL Java_clang_clang_kniBridge99 (JNIEnv* jniEnv, jclass jclss, jint p0) { + return (jint)clang_isReference(p0); +} +JNIEXPORT jint JNICALL Java_clang_clang_kniBridge100 (JNIEnv* jniEnv, jclass jclss, jint p0) { + return (jint)clang_isExpression(p0); +} +JNIEXPORT jint JNICALL Java_clang_clang_kniBridge101 (JNIEnv* jniEnv, jclass jclss, jint p0) { + return (jint)clang_isStatement(p0); +} +JNIEXPORT jint JNICALL Java_clang_clang_kniBridge102 (JNIEnv* jniEnv, jclass jclss, jint p0) { + return (jint)clang_isAttribute(p0); +} +JNIEXPORT jint JNICALL Java_clang_clang_kniBridge103 (JNIEnv* jniEnv, jclass jclss, jlong p0) { + return (jint)clang_Cursor_hasAttrs(*(CXCursor*)p0); +} +JNIEXPORT jint JNICALL Java_clang_clang_kniBridge104 (JNIEnv* jniEnv, jclass jclss, jint p0) { + return (jint)clang_isInvalid(p0); +} +JNIEXPORT jint JNICALL Java_clang_clang_kniBridge105 (JNIEnv* jniEnv, jclass jclss, jint p0) { + return (jint)clang_isTranslationUnit(p0); +} +JNIEXPORT jint JNICALL Java_clang_clang_kniBridge106 (JNIEnv* jniEnv, jclass jclss, jint p0) { + return (jint)clang_isPreprocessing(p0); +} +JNIEXPORT jint JNICALL Java_clang_clang_kniBridge107 (JNIEnv* jniEnv, jclass jclss, jint p0) { + return (jint)clang_isUnexposed(p0); +} +JNIEXPORT jint JNICALL Java_clang_clang_kniBridge108 (JNIEnv* jniEnv, jclass jclss, jlong p0) { + return (jint)clang_getCursorLinkage(*(CXCursor*)p0); +} +JNIEXPORT jint JNICALL Java_clang_clang_kniBridge109 (JNIEnv* jniEnv, jclass jclss, jlong p0) { + return (jint)clang_getCursorVisibility(*(CXCursor*)p0); +} +JNIEXPORT jint JNICALL Java_clang_clang_kniBridge110 (JNIEnv* jniEnv, jclass jclss, jlong p0) { + return (jint)clang_getCursorAvailability(*(CXCursor*)p0); +} +JNIEXPORT jint JNICALL Java_clang_clang_kniBridge111 (JNIEnv* jniEnv, jclass jclss, jlong p0, jlong p1, jlong p2, jlong p3, jlong p4, jlong p5, jint p6) { + return (jint)clang_getCursorPlatformAvailability(*(CXCursor*)p0, (int*)p1, (CXString*)p2, (int*)p3, (CXString*)p4, (struct CXPlatformAvailability*)p5, p6); +} +JNIEXPORT void JNICALL Java_clang_clang_kniBridge112 (JNIEnv* jniEnv, jclass jclss, jlong p0) { + clang_disposeCXPlatformAvailability((struct CXPlatformAvailability*)p0); +} +JNIEXPORT jint JNICALL Java_clang_clang_kniBridge113 (JNIEnv* jniEnv, jclass jclss, jlong p0) { + return (jint)clang_getCursorLanguage(*(CXCursor*)p0); +} +JNIEXPORT jint JNICALL Java_clang_clang_kniBridge114 (JNIEnv* jniEnv, jclass jclss, jlong p0) { + return (jint)clang_getCursorTLSKind(*(CXCursor*)p0); +} +JNIEXPORT jlong JNICALL Java_clang_clang_kniBridge115 (JNIEnv* jniEnv, jclass jclss, jlong p0) { + return (jlong)clang_Cursor_getTranslationUnit(*(CXCursor*)p0); +} +JNIEXPORT jlong JNICALL Java_clang_clang_kniBridge116 (JNIEnv* jniEnv, jclass jclss) { + return (jlong)clang_createCXCursorSet(); +} +JNIEXPORT void JNICALL Java_clang_clang_kniBridge117 (JNIEnv* jniEnv, jclass jclss, jlong p0) { + clang_disposeCXCursorSet((struct CXCursorSetImpl*)p0); +} +JNIEXPORT jint JNICALL Java_clang_clang_kniBridge118 (JNIEnv* jniEnv, jclass jclss, jlong p0, jlong p1) { + return (jint)clang_CXCursorSet_contains((struct CXCursorSetImpl*)p0, *(CXCursor*)p1); +} +JNIEXPORT jint JNICALL Java_clang_clang_kniBridge119 (JNIEnv* jniEnv, jclass jclss, jlong p0, jlong p1) { + return (jint)clang_CXCursorSet_insert((struct CXCursorSetImpl*)p0, *(CXCursor*)p1); +} +JNIEXPORT void JNICALL Java_clang_clang_kniBridge120 (JNIEnv* jniEnv, jclass jclss, jlong p0, jlong p1) { + CXCursor kniStructResult = clang_getCursorSemanticParent(*(CXCursor*)p0); + memcpy(p1, &kniStructResult, sizeof(kniStructResult)); +} +JNIEXPORT void JNICALL Java_clang_clang_kniBridge121 (JNIEnv* jniEnv, jclass jclss, jlong p0, jlong p1) { + CXCursor kniStructResult = clang_getCursorLexicalParent(*(CXCursor*)p0); + memcpy(p1, &kniStructResult, sizeof(kniStructResult)); +} +JNIEXPORT void JNICALL Java_clang_clang_kniBridge122 (JNIEnv* jniEnv, jclass jclss, jlong p0, jlong p1, jlong p2) { + clang_getOverriddenCursors(*(CXCursor*)p0, (CXCursor**)p1, (unsigned int*)p2); +} +JNIEXPORT void JNICALL Java_clang_clang_kniBridge123 (JNIEnv* jniEnv, jclass jclss, jlong p0) { + clang_disposeOverriddenCursors((CXCursor*)p0); +} +JNIEXPORT jlong JNICALL Java_clang_clang_kniBridge124 (JNIEnv* jniEnv, jclass jclss, jlong p0) { + return (jlong)clang_getIncludedFile(*(CXCursor*)p0); +} +JNIEXPORT void JNICALL Java_clang_clang_kniBridge125 (JNIEnv* jniEnv, jclass jclss, jlong p0, jlong p1, jlong p2) { + CXCursor kniStructResult = clang_getCursor((struct CXTranslationUnitImpl*)p0, *(CXSourceLocation*)p1); + memcpy(p2, &kniStructResult, sizeof(kniStructResult)); +} +JNIEXPORT void JNICALL Java_clang_clang_kniBridge126 (JNIEnv* jniEnv, jclass jclss, jlong p0, jlong p1) { + CXSourceLocation kniStructResult = clang_getCursorLocation(*(CXCursor*)p0); + memcpy(p1, &kniStructResult, sizeof(kniStructResult)); +} +JNIEXPORT void JNICALL Java_clang_clang_kniBridge127 (JNIEnv* jniEnv, jclass jclss, jlong p0, jlong p1) { + CXSourceRange kniStructResult = clang_getCursorExtent(*(CXCursor*)p0); + memcpy(p1, &kniStructResult, sizeof(kniStructResult)); +} +JNIEXPORT void JNICALL Java_clang_clang_kniBridge128 (JNIEnv* jniEnv, jclass jclss, jlong p0, jlong p1) { + CXType kniStructResult = clang_getCursorType(*(CXCursor*)p0); + memcpy(p1, &kniStructResult, sizeof(kniStructResult)); +} +JNIEXPORT void JNICALL Java_clang_clang_kniBridge129 (JNIEnv* jniEnv, jclass jclss, jlong p0, jlong p1) { + CXString kniStructResult = clang_getTypeSpelling(*(CXType*)p0); + memcpy(p1, &kniStructResult, sizeof(kniStructResult)); +} +JNIEXPORT void JNICALL Java_clang_clang_kniBridge130 (JNIEnv* jniEnv, jclass jclss, jlong p0, jlong p1) { + CXType kniStructResult = clang_getTypedefDeclUnderlyingType(*(CXCursor*)p0); + memcpy(p1, &kniStructResult, sizeof(kniStructResult)); +} +JNIEXPORT void JNICALL Java_clang_clang_kniBridge131 (JNIEnv* jniEnv, jclass jclss, jlong p0, jlong p1) { + CXType kniStructResult = clang_getEnumDeclIntegerType(*(CXCursor*)p0); + memcpy(p1, &kniStructResult, sizeof(kniStructResult)); +} +JNIEXPORT jlong JNICALL Java_clang_clang_kniBridge132 (JNIEnv* jniEnv, jclass jclss, jlong p0) { + return (jlong)clang_getEnumConstantDeclValue(*(CXCursor*)p0); +} +JNIEXPORT jlong JNICALL Java_clang_clang_kniBridge133 (JNIEnv* jniEnv, jclass jclss, jlong p0) { + return (jlong)clang_getEnumConstantDeclUnsignedValue(*(CXCursor*)p0); +} +JNIEXPORT jint JNICALL Java_clang_clang_kniBridge134 (JNIEnv* jniEnv, jclass jclss, jlong p0) { + return (jint)clang_getFieldDeclBitWidth(*(CXCursor*)p0); +} +JNIEXPORT jint JNICALL Java_clang_clang_kniBridge135 (JNIEnv* jniEnv, jclass jclss, jlong p0) { + return (jint)clang_Cursor_getNumArguments(*(CXCursor*)p0); +} +JNIEXPORT void JNICALL Java_clang_clang_kniBridge136 (JNIEnv* jniEnv, jclass jclss, jlong p0, jint p1, jlong p2) { + CXCursor kniStructResult = clang_Cursor_getArgument(*(CXCursor*)p0, p1); + memcpy(p2, &kniStructResult, sizeof(kniStructResult)); +} +JNIEXPORT jint JNICALL Java_clang_clang_kniBridge137 (JNIEnv* jniEnv, jclass jclss, jlong p0) { + return (jint)clang_Cursor_getNumTemplateArguments(*(CXCursor*)p0); +} +JNIEXPORT jint JNICALL Java_clang_clang_kniBridge138 (JNIEnv* jniEnv, jclass jclss, jlong p0, jint p1) { + return (jint)clang_Cursor_getTemplateArgumentKind(*(CXCursor*)p0, p1); +} +JNIEXPORT void JNICALL Java_clang_clang_kniBridge139 (JNIEnv* jniEnv, jclass jclss, jlong p0, jint p1, jlong p2) { + CXType kniStructResult = clang_Cursor_getTemplateArgumentType(*(CXCursor*)p0, p1); + memcpy(p2, &kniStructResult, sizeof(kniStructResult)); +} +JNIEXPORT jlong JNICALL Java_clang_clang_kniBridge140 (JNIEnv* jniEnv, jclass jclss, jlong p0, jint p1) { + return (jlong)clang_Cursor_getTemplateArgumentValue(*(CXCursor*)p0, p1); +} +JNIEXPORT jlong JNICALL Java_clang_clang_kniBridge141 (JNIEnv* jniEnv, jclass jclss, jlong p0, jint p1) { + return (jlong)clang_Cursor_getTemplateArgumentUnsignedValue(*(CXCursor*)p0, p1); +} +JNIEXPORT jint JNICALL Java_clang_clang_kniBridge142 (JNIEnv* jniEnv, jclass jclss, jlong p0, jlong p1) { + return (jint)clang_equalTypes(*(CXType*)p0, *(CXType*)p1); +} +JNIEXPORT void JNICALL Java_clang_clang_kniBridge143 (JNIEnv* jniEnv, jclass jclss, jlong p0, jlong p1) { + CXType kniStructResult = clang_getCanonicalType(*(CXType*)p0); + memcpy(p1, &kniStructResult, sizeof(kniStructResult)); +} +JNIEXPORT jint JNICALL Java_clang_clang_kniBridge144 (JNIEnv* jniEnv, jclass jclss, jlong p0) { + return (jint)clang_isConstQualifiedType(*(CXType*)p0); +} +JNIEXPORT jint JNICALL Java_clang_clang_kniBridge145 (JNIEnv* jniEnv, jclass jclss, jlong p0) { + return (jint)clang_Cursor_isMacroFunctionLike(*(CXCursor*)p0); +} +JNIEXPORT jint JNICALL Java_clang_clang_kniBridge146 (JNIEnv* jniEnv, jclass jclss, jlong p0) { + return (jint)clang_Cursor_isMacroBuiltin(*(CXCursor*)p0); +} +JNIEXPORT jint JNICALL Java_clang_clang_kniBridge147 (JNIEnv* jniEnv, jclass jclss, jlong p0) { + return (jint)clang_Cursor_isFunctionInlined(*(CXCursor*)p0); +} +JNIEXPORT jint JNICALL Java_clang_clang_kniBridge148 (JNIEnv* jniEnv, jclass jclss, jlong p0) { + return (jint)clang_isVolatileQualifiedType(*(CXType*)p0); +} +JNIEXPORT jint JNICALL Java_clang_clang_kniBridge149 (JNIEnv* jniEnv, jclass jclss, jlong p0) { + return (jint)clang_isRestrictQualifiedType(*(CXType*)p0); +} +JNIEXPORT jint JNICALL Java_clang_clang_kniBridge150 (JNIEnv* jniEnv, jclass jclss, jlong p0) { + return (jint)clang_getAddressSpace(*(CXType*)p0); +} +JNIEXPORT void JNICALL Java_clang_clang_kniBridge151 (JNIEnv* jniEnv, jclass jclss, jlong p0, jlong p1) { + CXString kniStructResult = clang_getTypedefName(*(CXType*)p0); + memcpy(p1, &kniStructResult, sizeof(kniStructResult)); +} +JNIEXPORT void JNICALL Java_clang_clang_kniBridge152 (JNIEnv* jniEnv, jclass jclss, jlong p0, jlong p1) { + CXType kniStructResult = clang_getPointeeType(*(CXType*)p0); + memcpy(p1, &kniStructResult, sizeof(kniStructResult)); +} +JNIEXPORT void JNICALL Java_clang_clang_kniBridge153 (JNIEnv* jniEnv, jclass jclss, jlong p0, jlong p1) { + CXCursor kniStructResult = clang_getTypeDeclaration(*(CXType*)p0); + memcpy(p1, &kniStructResult, sizeof(kniStructResult)); +} +JNIEXPORT void JNICALL Java_clang_clang_kniBridge154 (JNIEnv* jniEnv, jclass jclss, jlong p0, jlong p1) { + CXString kniStructResult = clang_getDeclObjCTypeEncoding(*(CXCursor*)p0); + memcpy(p1, &kniStructResult, sizeof(kniStructResult)); +} +JNIEXPORT void JNICALL Java_clang_clang_kniBridge155 (JNIEnv* jniEnv, jclass jclss, jlong p0, jlong p1) { + CXString kniStructResult = clang_Type_getObjCEncoding(*(CXType*)p0); + memcpy(p1, &kniStructResult, sizeof(kniStructResult)); +} +JNIEXPORT void JNICALL Java_clang_clang_kniBridge156 (JNIEnv* jniEnv, jclass jclss, jint p0, jlong p1) { + CXString kniStructResult = clang_getTypeKindSpelling(p0); + memcpy(p1, &kniStructResult, sizeof(kniStructResult)); +} +JNIEXPORT jint JNICALL Java_clang_clang_kniBridge157 (JNIEnv* jniEnv, jclass jclss, jlong p0) { + return (jint)clang_getFunctionTypeCallingConv(*(CXType*)p0); +} +JNIEXPORT void JNICALL Java_clang_clang_kniBridge158 (JNIEnv* jniEnv, jclass jclss, jlong p0, jlong p1) { + CXType kniStructResult = clang_getResultType(*(CXType*)p0); + memcpy(p1, &kniStructResult, sizeof(kniStructResult)); +} +JNIEXPORT jint JNICALL Java_clang_clang_kniBridge159 (JNIEnv* jniEnv, jclass jclss, jlong p0) { + return (jint)clang_getExceptionSpecificationType(*(CXType*)p0); +} +JNIEXPORT jint JNICALL Java_clang_clang_kniBridge160 (JNIEnv* jniEnv, jclass jclss, jlong p0) { + return (jint)clang_getNumArgTypes(*(CXType*)p0); +} +JNIEXPORT void JNICALL Java_clang_clang_kniBridge161 (JNIEnv* jniEnv, jclass jclss, jlong p0, jint p1, jlong p2) { + CXType kniStructResult = clang_getArgType(*(CXType*)p0, p1); + memcpy(p2, &kniStructResult, sizeof(kniStructResult)); +} +JNIEXPORT void JNICALL Java_clang_clang_kniBridge162 (JNIEnv* jniEnv, jclass jclss, jlong p0, jlong p1) { + CXType kniStructResult = clang_Type_getObjCObjectBaseType(*(CXType*)p0); + memcpy(p1, &kniStructResult, sizeof(kniStructResult)); +} +JNIEXPORT jint JNICALL Java_clang_clang_kniBridge163 (JNIEnv* jniEnv, jclass jclss, jlong p0) { + return (jint)clang_Type_getNumObjCProtocolRefs(*(CXType*)p0); +} +JNIEXPORT void JNICALL Java_clang_clang_kniBridge164 (JNIEnv* jniEnv, jclass jclss, jlong p0, jint p1, jlong p2) { + CXCursor kniStructResult = clang_Type_getObjCProtocolDecl(*(CXType*)p0, p1); + memcpy(p2, &kniStructResult, sizeof(kniStructResult)); +} +JNIEXPORT jint JNICALL Java_clang_clang_kniBridge165 (JNIEnv* jniEnv, jclass jclss, jlong p0) { + return (jint)clang_Type_getNumObjCTypeArgs(*(CXType*)p0); +} +JNIEXPORT void JNICALL Java_clang_clang_kniBridge166 (JNIEnv* jniEnv, jclass jclss, jlong p0, jint p1, jlong p2) { + CXType kniStructResult = clang_Type_getObjCTypeArg(*(CXType*)p0, p1); + memcpy(p2, &kniStructResult, sizeof(kniStructResult)); +} +JNIEXPORT jint JNICALL Java_clang_clang_kniBridge167 (JNIEnv* jniEnv, jclass jclss, jlong p0) { + return (jint)clang_isFunctionTypeVariadic(*(CXType*)p0); +} +JNIEXPORT void JNICALL Java_clang_clang_kniBridge168 (JNIEnv* jniEnv, jclass jclss, jlong p0, jlong p1) { + CXType kniStructResult = clang_getCursorResultType(*(CXCursor*)p0); + memcpy(p1, &kniStructResult, sizeof(kniStructResult)); +} +JNIEXPORT jint JNICALL Java_clang_clang_kniBridge169 (JNIEnv* jniEnv, jclass jclss, jlong p0) { + return (jint)clang_getCursorExceptionSpecificationType(*(CXCursor*)p0); +} +JNIEXPORT jint JNICALL Java_clang_clang_kniBridge170 (JNIEnv* jniEnv, jclass jclss, jlong p0) { + return (jint)clang_isPODType(*(CXType*)p0); +} +JNIEXPORT void JNICALL Java_clang_clang_kniBridge171 (JNIEnv* jniEnv, jclass jclss, jlong p0, jlong p1) { + CXType kniStructResult = clang_getElementType(*(CXType*)p0); + memcpy(p1, &kniStructResult, sizeof(kniStructResult)); +} +JNIEXPORT jlong JNICALL Java_clang_clang_kniBridge172 (JNIEnv* jniEnv, jclass jclss, jlong p0) { + return (jlong)clang_getNumElements(*(CXType*)p0); +} +JNIEXPORT void JNICALL Java_clang_clang_kniBridge173 (JNIEnv* jniEnv, jclass jclss, jlong p0, jlong p1) { + CXType kniStructResult = clang_getArrayElementType(*(CXType*)p0); + memcpy(p1, &kniStructResult, sizeof(kniStructResult)); +} +JNIEXPORT jlong JNICALL Java_clang_clang_kniBridge174 (JNIEnv* jniEnv, jclass jclss, jlong p0) { + return (jlong)clang_getArraySize(*(CXType*)p0); +} +JNIEXPORT void JNICALL Java_clang_clang_kniBridge175 (JNIEnv* jniEnv, jclass jclss, jlong p0, jlong p1) { + CXType kniStructResult = clang_Type_getNamedType(*(CXType*)p0); + memcpy(p1, &kniStructResult, sizeof(kniStructResult)); +} +JNIEXPORT jint JNICALL Java_clang_clang_kniBridge176 (JNIEnv* jniEnv, jclass jclss, jlong p0) { + return (jint)clang_Type_isTransparentTagTypedef(*(CXType*)p0); +} +JNIEXPORT jint JNICALL Java_clang_clang_kniBridge177 (JNIEnv* jniEnv, jclass jclss, jlong p0) { + return (jint)clang_Type_getNullability(*(CXType*)p0); +} +JNIEXPORT jlong JNICALL Java_clang_clang_kniBridge178 (JNIEnv* jniEnv, jclass jclss, jlong p0) { + return (jlong)clang_Type_getAlignOf(*(CXType*)p0); +} +JNIEXPORT void JNICALL Java_clang_clang_kniBridge179 (JNIEnv* jniEnv, jclass jclss, jlong p0, jlong p1) { + CXType kniStructResult = clang_Type_getClassType(*(CXType*)p0); + memcpy(p1, &kniStructResult, sizeof(kniStructResult)); +} +JNIEXPORT jlong JNICALL Java_clang_clang_kniBridge180 (JNIEnv* jniEnv, jclass jclss, jlong p0) { + return (jlong)clang_Type_getSizeOf(*(CXType*)p0); +} +JNIEXPORT jlong JNICALL Java_clang_clang_kniBridge181 (JNIEnv* jniEnv, jclass jclss, jlong p0, jlong p1) { + return (jlong)clang_Type_getOffsetOf(*(CXType*)p0, (char*)p1); +} +JNIEXPORT void JNICALL Java_clang_clang_kniBridge182 (JNIEnv* jniEnv, jclass jclss, jlong p0, jlong p1) { + CXType kniStructResult = clang_Type_getModifiedType(*(CXType*)p0); + memcpy(p1, &kniStructResult, sizeof(kniStructResult)); +} +JNIEXPORT jlong JNICALL Java_clang_clang_kniBridge183 (JNIEnv* jniEnv, jclass jclss, jlong p0) { + return (jlong)clang_Cursor_getOffsetOfField(*(CXCursor*)p0); +} +JNIEXPORT jint JNICALL Java_clang_clang_kniBridge184 (JNIEnv* jniEnv, jclass jclss, jlong p0) { + return (jint)clang_Cursor_isAnonymous(*(CXCursor*)p0); +} +JNIEXPORT jint JNICALL Java_clang_clang_kniBridge185 (JNIEnv* jniEnv, jclass jclss, jlong p0) { + return (jint)clang_Type_getNumTemplateArguments(*(CXType*)p0); +} +JNIEXPORT void JNICALL Java_clang_clang_kniBridge186 (JNIEnv* jniEnv, jclass jclss, jlong p0, jint p1, jlong p2) { + CXType kniStructResult = clang_Type_getTemplateArgumentAsType(*(CXType*)p0, p1); + memcpy(p2, &kniStructResult, sizeof(kniStructResult)); +} +JNIEXPORT jint JNICALL Java_clang_clang_kniBridge187 (JNIEnv* jniEnv, jclass jclss, jlong p0) { + return (jint)clang_Type_getCXXRefQualifier(*(CXType*)p0); +} +JNIEXPORT jint JNICALL Java_clang_clang_kniBridge188 (JNIEnv* jniEnv, jclass jclss, jlong p0) { + return (jint)clang_Cursor_isBitField(*(CXCursor*)p0); +} +JNIEXPORT jint JNICALL Java_clang_clang_kniBridge189 (JNIEnv* jniEnv, jclass jclss, jlong p0) { + return (jint)clang_isVirtualBase(*(CXCursor*)p0); +} +JNIEXPORT jint JNICALL Java_clang_clang_kniBridge190 (JNIEnv* jniEnv, jclass jclss, jlong p0) { + return (jint)clang_getCXXAccessSpecifier(*(CXCursor*)p0); +} +JNIEXPORT jint JNICALL Java_clang_clang_kniBridge191 (JNIEnv* jniEnv, jclass jclss, jlong p0) { + return (jint)clang_Cursor_getStorageClass(*(CXCursor*)p0); +} +JNIEXPORT jint JNICALL Java_clang_clang_kniBridge192 (JNIEnv* jniEnv, jclass jclss, jlong p0) { + return (jint)clang_getNumOverloadedDecls(*(CXCursor*)p0); +} +JNIEXPORT void JNICALL Java_clang_clang_kniBridge193 (JNIEnv* jniEnv, jclass jclss, jlong p0, jint p1, jlong p2) { + CXCursor kniStructResult = clang_getOverloadedDecl(*(CXCursor*)p0, p1); + memcpy(p2, &kniStructResult, sizeof(kniStructResult)); +} +JNIEXPORT void JNICALL Java_clang_clang_kniBridge194 (JNIEnv* jniEnv, jclass jclss, jlong p0, jlong p1) { + CXType kniStructResult = clang_getIBOutletCollectionType(*(CXCursor*)p0); + memcpy(p1, &kniStructResult, sizeof(kniStructResult)); +} +JNIEXPORT jint JNICALL Java_clang_clang_kniBridge195 (JNIEnv* jniEnv, jclass jclss, jlong p0, jlong p1, jlong p2) { + return (jint)clang_visitChildren(*(CXCursor*)p0, (void*)p1, (void*)p2); +} +JNIEXPORT void JNICALL Java_clang_clang_kniBridge196 (JNIEnv* jniEnv, jclass jclss, jlong p0, jlong p1) { + CXString kniStructResult = clang_getCursorUSR(*(CXCursor*)p0); + memcpy(p1, &kniStructResult, sizeof(kniStructResult)); +} +JNIEXPORT void JNICALL Java_clang_clang_kniBridge197 (JNIEnv* jniEnv, jclass jclss, jlong p0, jlong p1) { + CXString kniStructResult = clang_constructUSR_ObjCClass((char*)p0); + memcpy(p1, &kniStructResult, sizeof(kniStructResult)); +} +JNIEXPORT void JNICALL Java_clang_clang_kniBridge198 (JNIEnv* jniEnv, jclass jclss, jlong p0, jlong p1, jlong p2) { + CXString kniStructResult = clang_constructUSR_ObjCCategory((char*)p0, (char*)p1); + memcpy(p2, &kniStructResult, sizeof(kniStructResult)); +} +JNIEXPORT void JNICALL Java_clang_clang_kniBridge199 (JNIEnv* jniEnv, jclass jclss, jlong p0, jlong p1) { + CXString kniStructResult = clang_constructUSR_ObjCProtocol((char*)p0); + memcpy(p1, &kniStructResult, sizeof(kniStructResult)); +} +JNIEXPORT void JNICALL Java_clang_clang_kniBridge200 (JNIEnv* jniEnv, jclass jclss, jlong p0, jlong p1, jlong p2) { + CXString kniStructResult = clang_constructUSR_ObjCIvar((char*)p0, *(CXString*)p1); + memcpy(p2, &kniStructResult, sizeof(kniStructResult)); +} +JNIEXPORT void JNICALL Java_clang_clang_kniBridge201 (JNIEnv* jniEnv, jclass jclss, jlong p0, jint p1, jlong p2, jlong p3) { + CXString kniStructResult = clang_constructUSR_ObjCMethod((char*)p0, p1, *(CXString*)p2); + memcpy(p3, &kniStructResult, sizeof(kniStructResult)); +} +JNIEXPORT void JNICALL Java_clang_clang_kniBridge202 (JNIEnv* jniEnv, jclass jclss, jlong p0, jlong p1, jlong p2) { + CXString kniStructResult = clang_constructUSR_ObjCProperty((char*)p0, *(CXString*)p1); + memcpy(p2, &kniStructResult, sizeof(kniStructResult)); +} +JNIEXPORT void JNICALL Java_clang_clang_kniBridge203 (JNIEnv* jniEnv, jclass jclss, jlong p0, jlong p1) { + CXString kniStructResult = clang_getCursorSpelling(*(CXCursor*)p0); + memcpy(p1, &kniStructResult, sizeof(kniStructResult)); +} +JNIEXPORT void JNICALL Java_clang_clang_kniBridge204 (JNIEnv* jniEnv, jclass jclss, jlong p0, jint p1, jint p2, jlong p3) { + CXSourceRange kniStructResult = clang_Cursor_getSpellingNameRange(*(CXCursor*)p0, p1, p2); + memcpy(p3, &kniStructResult, sizeof(kniStructResult)); +} +JNIEXPORT jint JNICALL Java_clang_clang_kniBridge205 (JNIEnv* jniEnv, jclass jclss, jlong p0, jint p1) { + return (jint)clang_PrintingPolicy_getProperty((void*)p0, p1); +} +JNIEXPORT void JNICALL Java_clang_clang_kniBridge206 (JNIEnv* jniEnv, jclass jclss, jlong p0, jint p1, jint p2) { + clang_PrintingPolicy_setProperty((void*)p0, p1, p2); +} +JNIEXPORT jlong JNICALL Java_clang_clang_kniBridge207 (JNIEnv* jniEnv, jclass jclss, jlong p0) { + return (jlong)clang_getCursorPrintingPolicy(*(CXCursor*)p0); +} +JNIEXPORT void JNICALL Java_clang_clang_kniBridge208 (JNIEnv* jniEnv, jclass jclss, jlong p0) { + clang_PrintingPolicy_dispose((void*)p0); +} +JNIEXPORT void JNICALL Java_clang_clang_kniBridge209 (JNIEnv* jniEnv, jclass jclss, jlong p0, jlong p1, jlong p2) { + CXString kniStructResult = clang_getCursorPrettyPrinted(*(CXCursor*)p0, (void*)p1); + memcpy(p2, &kniStructResult, sizeof(kniStructResult)); +} +JNIEXPORT void JNICALL Java_clang_clang_kniBridge210 (JNIEnv* jniEnv, jclass jclss, jlong p0, jlong p1) { + CXString kniStructResult = clang_getCursorDisplayName(*(CXCursor*)p0); + memcpy(p1, &kniStructResult, sizeof(kniStructResult)); +} +JNIEXPORT void JNICALL Java_clang_clang_kniBridge211 (JNIEnv* jniEnv, jclass jclss, jlong p0, jlong p1) { + CXCursor kniStructResult = clang_getCursorReferenced(*(CXCursor*)p0); + memcpy(p1, &kniStructResult, sizeof(kniStructResult)); +} +JNIEXPORT void JNICALL Java_clang_clang_kniBridge212 (JNIEnv* jniEnv, jclass jclss, jlong p0, jlong p1) { + CXCursor kniStructResult = clang_getCursorDefinition(*(CXCursor*)p0); + memcpy(p1, &kniStructResult, sizeof(kniStructResult)); +} +JNIEXPORT jint JNICALL Java_clang_clang_kniBridge213 (JNIEnv* jniEnv, jclass jclss, jlong p0) { + return (jint)clang_isCursorDefinition(*(CXCursor*)p0); +} +JNIEXPORT void JNICALL Java_clang_clang_kniBridge214 (JNIEnv* jniEnv, jclass jclss, jlong p0, jlong p1) { + CXCursor kniStructResult = clang_getCanonicalCursor(*(CXCursor*)p0); + memcpy(p1, &kniStructResult, sizeof(kniStructResult)); +} +JNIEXPORT jint JNICALL Java_clang_clang_kniBridge215 (JNIEnv* jniEnv, jclass jclss, jlong p0) { + return (jint)clang_Cursor_getObjCSelectorIndex(*(CXCursor*)p0); +} +JNIEXPORT jint JNICALL Java_clang_clang_kniBridge216 (JNIEnv* jniEnv, jclass jclss, jlong p0) { + return (jint)clang_Cursor_isDynamicCall(*(CXCursor*)p0); +} +JNIEXPORT void JNICALL Java_clang_clang_kniBridge217 (JNIEnv* jniEnv, jclass jclss, jlong p0, jlong p1) { + CXType kniStructResult = clang_Cursor_getReceiverType(*(CXCursor*)p0); + memcpy(p1, &kniStructResult, sizeof(kniStructResult)); +} +JNIEXPORT jint JNICALL Java_clang_clang_kniBridge218 (JNIEnv* jniEnv, jclass jclss, jlong p0, jint p1) { + return (jint)clang_Cursor_getObjCPropertyAttributes(*(CXCursor*)p0, p1); +} +JNIEXPORT void JNICALL Java_clang_clang_kniBridge219 (JNIEnv* jniEnv, jclass jclss, jlong p0, jlong p1) { + CXString kniStructResult = clang_Cursor_getObjCPropertyGetterName(*(CXCursor*)p0); + memcpy(p1, &kniStructResult, sizeof(kniStructResult)); +} +JNIEXPORT void JNICALL Java_clang_clang_kniBridge220 (JNIEnv* jniEnv, jclass jclss, jlong p0, jlong p1) { + CXString kniStructResult = clang_Cursor_getObjCPropertySetterName(*(CXCursor*)p0); + memcpy(p1, &kniStructResult, sizeof(kniStructResult)); +} +JNIEXPORT jint JNICALL Java_clang_clang_kniBridge221 (JNIEnv* jniEnv, jclass jclss, jlong p0) { + return (jint)clang_Cursor_getObjCDeclQualifiers(*(CXCursor*)p0); +} +JNIEXPORT jint JNICALL Java_clang_clang_kniBridge222 (JNIEnv* jniEnv, jclass jclss, jlong p0) { + return (jint)clang_Cursor_isObjCOptional(*(CXCursor*)p0); +} +JNIEXPORT jint JNICALL Java_clang_clang_kniBridge223 (JNIEnv* jniEnv, jclass jclss, jlong p0) { + return (jint)clang_Cursor_isVariadic(*(CXCursor*)p0); +} +JNIEXPORT jint JNICALL Java_clang_clang_kniBridge224 (JNIEnv* jniEnv, jclass jclss, jlong p0, jlong p1, jlong p2, jlong p3) { + return (jint)clang_Cursor_isExternalSymbol(*(CXCursor*)p0, (CXString*)p1, (CXString*)p2, (unsigned int*)p3); +} +JNIEXPORT void JNICALL Java_clang_clang_kniBridge225 (JNIEnv* jniEnv, jclass jclss, jlong p0, jlong p1) { + CXSourceRange kniStructResult = clang_Cursor_getCommentRange(*(CXCursor*)p0); + memcpy(p1, &kniStructResult, sizeof(kniStructResult)); +} +JNIEXPORT void JNICALL Java_clang_clang_kniBridge226 (JNIEnv* jniEnv, jclass jclss, jlong p0, jlong p1) { + CXString kniStructResult = clang_Cursor_getRawCommentText(*(CXCursor*)p0); + memcpy(p1, &kniStructResult, sizeof(kniStructResult)); +} +JNIEXPORT void JNICALL Java_clang_clang_kniBridge227 (JNIEnv* jniEnv, jclass jclss, jlong p0, jlong p1) { + CXString kniStructResult = clang_Cursor_getBriefCommentText(*(CXCursor*)p0); + memcpy(p1, &kniStructResult, sizeof(kniStructResult)); +} +JNIEXPORT void JNICALL Java_clang_clang_kniBridge228 (JNIEnv* jniEnv, jclass jclss, jlong p0, jlong p1) { + CXString kniStructResult = clang_Cursor_getMangling(*(CXCursor*)p0); + memcpy(p1, &kniStructResult, sizeof(kniStructResult)); +} +JNIEXPORT jlong JNICALL Java_clang_clang_kniBridge229 (JNIEnv* jniEnv, jclass jclss, jlong p0) { + return (jlong)clang_Cursor_getCXXManglings(*(CXCursor*)p0); +} +JNIEXPORT jlong JNICALL Java_clang_clang_kniBridge230 (JNIEnv* jniEnv, jclass jclss, jlong p0) { + return (jlong)clang_Cursor_getObjCManglings(*(CXCursor*)p0); +} +JNIEXPORT jlong JNICALL Java_clang_clang_kniBridge231 (JNIEnv* jniEnv, jclass jclss, jlong p0) { + return (jlong)clang_Cursor_getModule(*(CXCursor*)p0); +} +JNIEXPORT jlong JNICALL Java_clang_clang_kniBridge232 (JNIEnv* jniEnv, jclass jclss, jlong p0, jlong p1) { + return (jlong)clang_getModuleForFile((struct CXTranslationUnitImpl*)p0, (void*)p1); +} +JNIEXPORT jlong JNICALL Java_clang_clang_kniBridge233 (JNIEnv* jniEnv, jclass jclss, jlong p0) { + return (jlong)clang_Module_getASTFile((void*)p0); +} +JNIEXPORT jlong JNICALL Java_clang_clang_kniBridge234 (JNIEnv* jniEnv, jclass jclss, jlong p0) { + return (jlong)clang_Module_getParent((void*)p0); +} +JNIEXPORT void JNICALL Java_clang_clang_kniBridge235 (JNIEnv* jniEnv, jclass jclss, jlong p0, jlong p1) { + CXString kniStructResult = clang_Module_getName((void*)p0); + memcpy(p1, &kniStructResult, sizeof(kniStructResult)); +} +JNIEXPORT void JNICALL Java_clang_clang_kniBridge236 (JNIEnv* jniEnv, jclass jclss, jlong p0, jlong p1) { + CXString kniStructResult = clang_Module_getFullName((void*)p0); + memcpy(p1, &kniStructResult, sizeof(kniStructResult)); +} +JNIEXPORT jint JNICALL Java_clang_clang_kniBridge237 (JNIEnv* jniEnv, jclass jclss, jlong p0) { + return (jint)clang_Module_isSystem((void*)p0); +} +JNIEXPORT jint JNICALL Java_clang_clang_kniBridge238 (JNIEnv* jniEnv, jclass jclss, jlong p0, jlong p1) { + return (jint)clang_Module_getNumTopLevelHeaders((struct CXTranslationUnitImpl*)p0, (void*)p1); +} +JNIEXPORT jlong JNICALL Java_clang_clang_kniBridge239 (JNIEnv* jniEnv, jclass jclss, jlong p0, jlong p1, jint p2) { + return (jlong)clang_Module_getTopLevelHeader((struct CXTranslationUnitImpl*)p0, (void*)p1, p2); +} +JNIEXPORT jint JNICALL Java_clang_clang_kniBridge240 (JNIEnv* jniEnv, jclass jclss, jlong p0) { + return (jint)clang_CXXConstructor_isConvertingConstructor(*(CXCursor*)p0); +} +JNIEXPORT jint JNICALL Java_clang_clang_kniBridge241 (JNIEnv* jniEnv, jclass jclss, jlong p0) { + return (jint)clang_CXXConstructor_isCopyConstructor(*(CXCursor*)p0); +} +JNIEXPORT jint JNICALL Java_clang_clang_kniBridge242 (JNIEnv* jniEnv, jclass jclss, jlong p0) { + return (jint)clang_CXXConstructor_isDefaultConstructor(*(CXCursor*)p0); +} +JNIEXPORT jint JNICALL Java_clang_clang_kniBridge243 (JNIEnv* jniEnv, jclass jclss, jlong p0) { + return (jint)clang_CXXConstructor_isMoveConstructor(*(CXCursor*)p0); +} +JNIEXPORT jint JNICALL Java_clang_clang_kniBridge244 (JNIEnv* jniEnv, jclass jclss, jlong p0) { + return (jint)clang_CXXField_isMutable(*(CXCursor*)p0); +} +JNIEXPORT jint JNICALL Java_clang_clang_kniBridge245 (JNIEnv* jniEnv, jclass jclss, jlong p0) { + return (jint)clang_CXXMethod_isDefaulted(*(CXCursor*)p0); +} +JNIEXPORT jint JNICALL Java_clang_clang_kniBridge246 (JNIEnv* jniEnv, jclass jclss, jlong p0) { + return (jint)clang_CXXMethod_isPureVirtual(*(CXCursor*)p0); +} +JNIEXPORT jint JNICALL Java_clang_clang_kniBridge247 (JNIEnv* jniEnv, jclass jclss, jlong p0) { + return (jint)clang_CXXMethod_isStatic(*(CXCursor*)p0); +} +JNIEXPORT jint JNICALL Java_clang_clang_kniBridge248 (JNIEnv* jniEnv, jclass jclss, jlong p0) { + return (jint)clang_CXXMethod_isVirtual(*(CXCursor*)p0); +} +JNIEXPORT jint JNICALL Java_clang_clang_kniBridge249 (JNIEnv* jniEnv, jclass jclss, jlong p0) { + return (jint)clang_CXXRecord_isAbstract(*(CXCursor*)p0); +} +JNIEXPORT jint JNICALL Java_clang_clang_kniBridge250 (JNIEnv* jniEnv, jclass jclss, jlong p0) { + return (jint)clang_EnumDecl_isScoped(*(CXCursor*)p0); +} +JNIEXPORT jint JNICALL Java_clang_clang_kniBridge251 (JNIEnv* jniEnv, jclass jclss, jlong p0) { + return (jint)clang_CXXMethod_isConst(*(CXCursor*)p0); +} +JNIEXPORT jint JNICALL Java_clang_clang_kniBridge252 (JNIEnv* jniEnv, jclass jclss, jlong p0) { + return (jint)clang_getTemplateCursorKind(*(CXCursor*)p0); +} +JNIEXPORT void JNICALL Java_clang_clang_kniBridge253 (JNIEnv* jniEnv, jclass jclss, jlong p0, jlong p1) { + CXCursor kniStructResult = clang_getSpecializedCursorTemplate(*(CXCursor*)p0); + memcpy(p1, &kniStructResult, sizeof(kniStructResult)); +} +JNIEXPORT void JNICALL Java_clang_clang_kniBridge254 (JNIEnv* jniEnv, jclass jclss, jlong p0, jint p1, jint p2, jlong p3) { + CXSourceRange kniStructResult = clang_getCursorReferenceNameRange(*(CXCursor*)p0, p1, p2); + memcpy(p3, &kniStructResult, sizeof(kniStructResult)); +} +JNIEXPORT jlong JNICALL Java_clang_clang_kniBridge255 (JNIEnv* jniEnv, jclass jclss, jlong p0, jlong p1) { + return (jlong)clang_getToken((struct CXTranslationUnitImpl*)p0, *(CXSourceLocation*)p1); +} +JNIEXPORT jint JNICALL Java_clang_clang_kniBridge256 (JNIEnv* jniEnv, jclass jclss, jlong p0) { + return (jint)clang_getTokenKind(*(CXToken*)p0); +} +JNIEXPORT void JNICALL Java_clang_clang_kniBridge257 (JNIEnv* jniEnv, jclass jclss, jlong p0, jlong p1, jlong p2) { + CXString kniStructResult = clang_getTokenSpelling((struct CXTranslationUnitImpl*)p0, *(CXToken*)p1); + memcpy(p2, &kniStructResult, sizeof(kniStructResult)); +} +JNIEXPORT void JNICALL Java_clang_clang_kniBridge258 (JNIEnv* jniEnv, jclass jclss, jlong p0, jlong p1, jlong p2) { + CXSourceLocation kniStructResult = clang_getTokenLocation((struct CXTranslationUnitImpl*)p0, *(CXToken*)p1); + memcpy(p2, &kniStructResult, sizeof(kniStructResult)); +} +JNIEXPORT void JNICALL Java_clang_clang_kniBridge259 (JNIEnv* jniEnv, jclass jclss, jlong p0, jlong p1, jlong p2) { + CXSourceRange kniStructResult = clang_getTokenExtent((struct CXTranslationUnitImpl*)p0, *(CXToken*)p1); + memcpy(p2, &kniStructResult, sizeof(kniStructResult)); +} +JNIEXPORT void JNICALL Java_clang_clang_kniBridge260 (JNIEnv* jniEnv, jclass jclss, jlong p0, jlong p1, jlong p2, jlong p3) { + clang_tokenize((struct CXTranslationUnitImpl*)p0, *(CXSourceRange*)p1, (CXToken**)p2, (unsigned int*)p3); +} +JNIEXPORT void JNICALL Java_clang_clang_kniBridge261 (JNIEnv* jniEnv, jclass jclss, jlong p0, jlong p1, jint p2, jlong p3) { + clang_annotateTokens((struct CXTranslationUnitImpl*)p0, (CXToken*)p1, p2, (CXCursor*)p3); +} +JNIEXPORT void JNICALL Java_clang_clang_kniBridge262 (JNIEnv* jniEnv, jclass jclss, jlong p0, jlong p1, jint p2) { + clang_disposeTokens((struct CXTranslationUnitImpl*)p0, (CXToken*)p1, p2); +} +JNIEXPORT void JNICALL Java_clang_clang_kniBridge263 (JNIEnv* jniEnv, jclass jclss, jint p0, jlong p1) { + CXString kniStructResult = clang_getCursorKindSpelling(p0); + memcpy(p1, &kniStructResult, sizeof(kniStructResult)); +} +JNIEXPORT void JNICALL Java_clang_clang_kniBridge264 (JNIEnv* jniEnv, jclass jclss, jlong p0, jlong p1, jlong p2, jlong p3, jlong p4, jlong p5, jlong p6) { + clang_getDefinitionSpellingAndExtent(*(CXCursor*)p0, (char**)p1, (char**)p2, (unsigned int*)p3, (unsigned int*)p4, (unsigned int*)p5, (unsigned int*)p6); +} +JNIEXPORT void JNICALL Java_clang_clang_kniBridge265 (JNIEnv* jniEnv, jclass jclss) { + clang_enableStackTraces(); +} +JNIEXPORT void JNICALL Java_clang_clang_kniBridge266 (JNIEnv* jniEnv, jclass jclss, jlong p0, jlong p1, jint p2) { + clang_executeOnThread((void*)p0, (void*)p1, p2); +} +JNIEXPORT jint JNICALL Java_clang_clang_kniBridge267 (JNIEnv* jniEnv, jclass jclss, jlong p0, jint p1) { + return (jint)clang_getCompletionChunkKind((void*)p0, p1); +} +JNIEXPORT void JNICALL Java_clang_clang_kniBridge268 (JNIEnv* jniEnv, jclass jclss, jlong p0, jint p1, jlong p2) { + CXString kniStructResult = clang_getCompletionChunkText((void*)p0, p1); + memcpy(p2, &kniStructResult, sizeof(kniStructResult)); +} +JNIEXPORT jlong JNICALL Java_clang_clang_kniBridge269 (JNIEnv* jniEnv, jclass jclss, jlong p0, jint p1) { + return (jlong)clang_getCompletionChunkCompletionString((void*)p0, p1); +} +JNIEXPORT jint JNICALL Java_clang_clang_kniBridge270 (JNIEnv* jniEnv, jclass jclss, jlong p0) { + return (jint)clang_getNumCompletionChunks((void*)p0); +} +JNIEXPORT jint JNICALL Java_clang_clang_kniBridge271 (JNIEnv* jniEnv, jclass jclss, jlong p0) { + return (jint)clang_getCompletionPriority((void*)p0); +} +JNIEXPORT jint JNICALL Java_clang_clang_kniBridge272 (JNIEnv* jniEnv, jclass jclss, jlong p0) { + return (jint)clang_getCompletionAvailability((void*)p0); +} +JNIEXPORT jint JNICALL Java_clang_clang_kniBridge273 (JNIEnv* jniEnv, jclass jclss, jlong p0) { + return (jint)clang_getCompletionNumAnnotations((void*)p0); +} +JNIEXPORT void JNICALL Java_clang_clang_kniBridge274 (JNIEnv* jniEnv, jclass jclss, jlong p0, jint p1, jlong p2) { + CXString kniStructResult = clang_getCompletionAnnotation((void*)p0, p1); + memcpy(p2, &kniStructResult, sizeof(kniStructResult)); +} +JNIEXPORT void JNICALL Java_clang_clang_kniBridge275 (JNIEnv* jniEnv, jclass jclss, jlong p0, jlong p1, jlong p2) { + CXString kniStructResult = clang_getCompletionParent((void*)p0, (void*)p1); + memcpy(p2, &kniStructResult, sizeof(kniStructResult)); +} +JNIEXPORT void JNICALL Java_clang_clang_kniBridge276 (JNIEnv* jniEnv, jclass jclss, jlong p0, jlong p1) { + CXString kniStructResult = clang_getCompletionBriefComment((void*)p0); + memcpy(p1, &kniStructResult, sizeof(kniStructResult)); +} +JNIEXPORT jlong JNICALL Java_clang_clang_kniBridge277 (JNIEnv* jniEnv, jclass jclss, jlong p0) { + return (jlong)clang_getCursorCompletionString(*(CXCursor*)p0); +} +JNIEXPORT jint JNICALL Java_clang_clang_kniBridge278 (JNIEnv* jniEnv, jclass jclss, jlong p0, jint p1) { + return (jint)clang_getCompletionNumFixIts((CXCodeCompleteResults*)p0, p1); +} +JNIEXPORT void JNICALL Java_clang_clang_kniBridge279 (JNIEnv* jniEnv, jclass jclss, jlong p0, jint p1, jint p2, jlong p3, jlong p4) { + CXString kniStructResult = clang_getCompletionFixIt((CXCodeCompleteResults*)p0, p1, p2, (CXSourceRange*)p3); + memcpy(p4, &kniStructResult, sizeof(kniStructResult)); +} +JNIEXPORT jint JNICALL Java_clang_clang_kniBridge280 (JNIEnv* jniEnv, jclass jclss) { + return (jint)clang_defaultCodeCompleteOptions(); +} +JNIEXPORT jlong JNICALL Java_clang_clang_kniBridge281 (JNIEnv* jniEnv, jclass jclss, jlong p0, jlong p1, jint p2, jint p3, jlong p4, jint p5, jint p6) { + return (jlong)clang_codeCompleteAt((struct CXTranslationUnitImpl*)p0, (char*)p1, p2, p3, (struct CXUnsavedFile*)p4, p5, p6); +} +JNIEXPORT void JNICALL Java_clang_clang_kniBridge282 (JNIEnv* jniEnv, jclass jclss, jlong p0, jint p1) { + clang_sortCodeCompletionResults((CXCompletionResult*)p0, p1); +} +JNIEXPORT void JNICALL Java_clang_clang_kniBridge283 (JNIEnv* jniEnv, jclass jclss, jlong p0) { + clang_disposeCodeCompleteResults((CXCodeCompleteResults*)p0); +} +JNIEXPORT jint JNICALL Java_clang_clang_kniBridge284 (JNIEnv* jniEnv, jclass jclss, jlong p0) { + return (jint)clang_codeCompleteGetNumDiagnostics((CXCodeCompleteResults*)p0); +} +JNIEXPORT jlong JNICALL Java_clang_clang_kniBridge285 (JNIEnv* jniEnv, jclass jclss, jlong p0, jint p1) { + return (jlong)clang_codeCompleteGetDiagnostic((CXCodeCompleteResults*)p0, p1); +} +JNIEXPORT jlong JNICALL Java_clang_clang_kniBridge286 (JNIEnv* jniEnv, jclass jclss, jlong p0) { + return (jlong)clang_codeCompleteGetContexts((CXCodeCompleteResults*)p0); +} +JNIEXPORT jint JNICALL Java_clang_clang_kniBridge287 (JNIEnv* jniEnv, jclass jclss, jlong p0, jlong p1) { + return (jint)clang_codeCompleteGetContainerKind((CXCodeCompleteResults*)p0, (unsigned int*)p1); +} +JNIEXPORT void JNICALL Java_clang_clang_kniBridge288 (JNIEnv* jniEnv, jclass jclss, jlong p0, jlong p1) { + CXString kniStructResult = clang_codeCompleteGetContainerUSR((CXCodeCompleteResults*)p0); + memcpy(p1, &kniStructResult, sizeof(kniStructResult)); +} +JNIEXPORT void JNICALL Java_clang_clang_kniBridge289 (JNIEnv* jniEnv, jclass jclss, jlong p0, jlong p1) { + CXString kniStructResult = clang_codeCompleteGetObjCSelector((CXCodeCompleteResults*)p0); + memcpy(p1, &kniStructResult, sizeof(kniStructResult)); +} +JNIEXPORT void JNICALL Java_clang_clang_kniBridge290 (JNIEnv* jniEnv, jclass jclss, jlong p0) { + CXString kniStructResult = clang_getClangVersion(); + memcpy(p0, &kniStructResult, sizeof(kniStructResult)); +} +JNIEXPORT void JNICALL Java_clang_clang_kniBridge291 (JNIEnv* jniEnv, jclass jclss, jint p0) { + clang_toggleCrashRecovery(p0); +} +JNIEXPORT void JNICALL Java_clang_clang_kniBridge292 (JNIEnv* jniEnv, jclass jclss, jlong p0, jlong p1, jlong p2) { + clang_getInclusions((struct CXTranslationUnitImpl*)p0, (void*)p1, (void*)p2); +} +JNIEXPORT jlong JNICALL Java_clang_clang_kniBridge293 (JNIEnv* jniEnv, jclass jclss, jlong p0) { + return (jlong)clang_Cursor_Evaluate(*(CXCursor*)p0); +} +JNIEXPORT jint JNICALL Java_clang_clang_kniBridge294 (JNIEnv* jniEnv, jclass jclss, jlong p0) { + return (jint)clang_EvalResult_getKind((void*)p0); +} +JNIEXPORT jint JNICALL Java_clang_clang_kniBridge295 (JNIEnv* jniEnv, jclass jclss, jlong p0) { + return (jint)clang_EvalResult_getAsInt((void*)p0); +} +JNIEXPORT jlong JNICALL Java_clang_clang_kniBridge296 (JNIEnv* jniEnv, jclass jclss, jlong p0) { + return (jlong)clang_EvalResult_getAsLongLong((void*)p0); +} +JNIEXPORT jint JNICALL Java_clang_clang_kniBridge297 (JNIEnv* jniEnv, jclass jclss, jlong p0) { + return (jint)clang_EvalResult_isUnsignedInt((void*)p0); +} +JNIEXPORT jlong JNICALL Java_clang_clang_kniBridge298 (JNIEnv* jniEnv, jclass jclss, jlong p0) { + return (jlong)clang_EvalResult_getAsUnsigned((void*)p0); +} +JNIEXPORT jdouble JNICALL Java_clang_clang_kniBridge299 (JNIEnv* jniEnv, jclass jclss, jlong p0) { + return (jdouble)clang_EvalResult_getAsDouble((void*)p0); +} +JNIEXPORT jlong JNICALL Java_clang_clang_kniBridge300 (JNIEnv* jniEnv, jclass jclss, jlong p0) { + return (jlong)clang_EvalResult_getAsStr((void*)p0); +} +JNIEXPORT void JNICALL Java_clang_clang_kniBridge301 (JNIEnv* jniEnv, jclass jclss, jlong p0) { + clang_EvalResult_dispose((void*)p0); +} +JNIEXPORT jlong JNICALL Java_clang_clang_kniBridge302 (JNIEnv* jniEnv, jclass jclss, jlong p0) { + return (jlong)clang_getRemappings((char*)p0); +} +JNIEXPORT jlong JNICALL Java_clang_clang_kniBridge303 (JNIEnv* jniEnv, jclass jclss, jlong p0, jint p1) { + return (jlong)clang_getRemappingsFromFileList((char**)p0, p1); +} +JNIEXPORT jint JNICALL Java_clang_clang_kniBridge304 (JNIEnv* jniEnv, jclass jclss, jlong p0) { + return (jint)clang_remap_getNumFiles((void*)p0); +} +JNIEXPORT void JNICALL Java_clang_clang_kniBridge305 (JNIEnv* jniEnv, jclass jclss, jlong p0, jint p1, jlong p2, jlong p3) { + clang_remap_getFilenames((void*)p0, p1, (CXString*)p2, (CXString*)p3); +} +JNIEXPORT void JNICALL Java_clang_clang_kniBridge306 (JNIEnv* jniEnv, jclass jclss, jlong p0) { + clang_remap_dispose((void*)p0); +} +JNIEXPORT jint JNICALL Java_clang_clang_kniBridge307 (JNIEnv* jniEnv, jclass jclss, jlong p0, jlong p1, jlong p2) { + return (jint)clang_findReferencesInFile(*(CXCursor*)p0, (void*)p1, *(struct CXCursorAndRangeVisitor*)p2); +} +JNIEXPORT jint JNICALL Java_clang_clang_kniBridge308 (JNIEnv* jniEnv, jclass jclss, jlong p0, jlong p1, jlong p2) { + return (jint)clang_findIncludesInFile((struct CXTranslationUnitImpl*)p0, (void*)p1, *(struct CXCursorAndRangeVisitor*)p2); +} +JNIEXPORT jint JNICALL Java_clang_clang_kniBridge309 (JNIEnv* jniEnv, jclass jclss, jint p0) { + return (jint)clang_index_isEntityObjCContainerKind(p0); +} +JNIEXPORT jlong JNICALL Java_clang_clang_kniBridge310 (JNIEnv* jniEnv, jclass jclss, jlong p0) { + return (jlong)clang_index_getObjCContainerDeclInfo((CXIdxDeclInfo*)p0); +} +JNIEXPORT jlong JNICALL Java_clang_clang_kniBridge311 (JNIEnv* jniEnv, jclass jclss, jlong p0) { + return (jlong)clang_index_getObjCInterfaceDeclInfo((CXIdxDeclInfo*)p0); +} +JNIEXPORT jlong JNICALL Java_clang_clang_kniBridge312 (JNIEnv* jniEnv, jclass jclss, jlong p0) { + return (jlong)clang_index_getObjCCategoryDeclInfo((CXIdxDeclInfo*)p0); +} +JNIEXPORT jlong JNICALL Java_clang_clang_kniBridge313 (JNIEnv* jniEnv, jclass jclss, jlong p0) { + return (jlong)clang_index_getObjCProtocolRefListInfo((CXIdxDeclInfo*)p0); +} +JNIEXPORT jlong JNICALL Java_clang_clang_kniBridge314 (JNIEnv* jniEnv, jclass jclss, jlong p0) { + return (jlong)clang_index_getObjCPropertyDeclInfo((CXIdxDeclInfo*)p0); +} +JNIEXPORT jlong JNICALL Java_clang_clang_kniBridge315 (JNIEnv* jniEnv, jclass jclss, jlong p0) { + return (jlong)clang_index_getIBOutletCollectionAttrInfo((CXIdxAttrInfo*)p0); +} +JNIEXPORT jlong JNICALL Java_clang_clang_kniBridge316 (JNIEnv* jniEnv, jclass jclss, jlong p0) { + return (jlong)clang_index_getCXXClassDeclInfo((CXIdxDeclInfo*)p0); +} +JNIEXPORT jlong JNICALL Java_clang_clang_kniBridge317 (JNIEnv* jniEnv, jclass jclss, jlong p0) { + return (jlong)clang_index_getClientContainer((CXIdxContainerInfo*)p0); +} +JNIEXPORT void JNICALL Java_clang_clang_kniBridge318 (JNIEnv* jniEnv, jclass jclss, jlong p0, jlong p1) { + clang_index_setClientContainer((CXIdxContainerInfo*)p0, (void*)p1); +} +JNIEXPORT jlong JNICALL Java_clang_clang_kniBridge319 (JNIEnv* jniEnv, jclass jclss, jlong p0) { + return (jlong)clang_index_getClientEntity((CXIdxEntityInfo*)p0); +} +JNIEXPORT void JNICALL Java_clang_clang_kniBridge320 (JNIEnv* jniEnv, jclass jclss, jlong p0, jlong p1) { + clang_index_setClientEntity((CXIdxEntityInfo*)p0, (void*)p1); +} +JNIEXPORT jlong JNICALL Java_clang_clang_kniBridge321 (JNIEnv* jniEnv, jclass jclss, jlong p0) { + return (jlong)clang_IndexAction_create((void*)p0); +} +JNIEXPORT void JNICALL Java_clang_clang_kniBridge322 (JNIEnv* jniEnv, jclass jclss, jlong p0) { + clang_IndexAction_dispose((void*)p0); +} +JNIEXPORT jint JNICALL Java_clang_clang_kniBridge323 (JNIEnv* jniEnv, jclass jclss, jlong p0, jlong p1, jlong p2, jint p3, jint p4, jlong p5, jlong p6, jint p7, jlong p8, jint p9, jlong p10, jint p11) { + return (jint)clang_indexSourceFile((void*)p0, (void*)p1, (IndexerCallbacks*)p2, p3, p4, (char*)p5, (char**)p6, p7, (struct CXUnsavedFile*)p8, p9, (struct CXTranslationUnitImpl**)p10, p11); +} +JNIEXPORT jint JNICALL Java_clang_clang_kniBridge324 (JNIEnv* jniEnv, jclass jclss, jlong p0, jlong p1, jlong p2, jint p3, jint p4, jlong p5, jlong p6, jint p7, jlong p8, jint p9, jlong p10, jint p11) { + return (jint)clang_indexSourceFileFullArgv((void*)p0, (void*)p1, (IndexerCallbacks*)p2, p3, p4, (char*)p5, (char**)p6, p7, (struct CXUnsavedFile*)p8, p9, (struct CXTranslationUnitImpl**)p10, p11); +} +JNIEXPORT jint JNICALL Java_clang_clang_kniBridge325 (JNIEnv* jniEnv, jclass jclss, jlong p0, jlong p1, jlong p2, jint p3, jint p4, jlong p5) { + return (jint)clang_indexTranslationUnit((void*)p0, (void*)p1, (IndexerCallbacks*)p2, p3, p4, (struct CXTranslationUnitImpl*)p5); +} +JNIEXPORT void JNICALL Java_clang_clang_kniBridge326 (JNIEnv* jniEnv, jclass jclss, jlong p0, jlong p1, jlong p2, jlong p3, jlong p4, jlong p5) { + clang_indexLoc_getFileLocation(*(CXIdxLoc*)p0, (void*)p1, (void*)p2, (unsigned int*)p3, (unsigned int*)p4, (unsigned int*)p5); +} +JNIEXPORT void JNICALL Java_clang_clang_kniBridge327 (JNIEnv* jniEnv, jclass jclss, jlong p0, jlong p1) { + CXSourceLocation kniStructResult = clang_indexLoc_getCXSourceLocation(*(CXIdxLoc*)p0); + memcpy(p1, &kniStructResult, sizeof(kniStructResult)); +} +JNIEXPORT jint JNICALL Java_clang_clang_kniBridge328 (JNIEnv* jniEnv, jclass jclss, jlong p0, jlong p1, jlong p2) { + return (jint)clang_Type_visitFields(*(CXType*)p0, (void*)p1, (void*)p2); +} +JNIEXPORT jlong JNICALL Java_clang_clang_kniBridge329 (JNIEnv* jniEnv, jclass jclss, jlong p0) { + return (jlong)clang_Cursor_getAttributeSpelling(*(CXCursor*)p0); +} +JNIEXPORT void JNICALL Java_clang_clang_kniBridge330 (JNIEnv* jniEnv, jclass jclss, jlong p0, jlong p1) { + CXTypeAttributes kniStructResult = clang_getDeclTypeAttributes(*(CXCursor*)p0); + memcpy(p1, &kniStructResult, sizeof(kniStructResult)); +} +JNIEXPORT void JNICALL Java_clang_clang_kniBridge331 (JNIEnv* jniEnv, jclass jclss, jlong p0, jlong p1) { + CXTypeAttributes kniStructResult = clang_getResultTypeAttributes(*(CXTypeAttributes*)p0); + memcpy(p1, &kniStructResult, sizeof(kniStructResult)); +} +JNIEXPORT void JNICALL Java_clang_clang_kniBridge332 (JNIEnv* jniEnv, jclass jclss, jlong p0, jlong p1) { + CXTypeAttributes kniStructResult = clang_getCursorResultTypeAttributes(*(CXCursor*)p0); + memcpy(p1, &kniStructResult, sizeof(kniStructResult)); +} +JNIEXPORT jint JNICALL Java_clang_clang_kniBridge333 (JNIEnv* jniEnv, jclass jclss, jlong p0, jlong p1) { + return (jint)clang_Type_getNullabilityKind(*(CXType*)p0, *(CXTypeAttributes*)p1); +} +JNIEXPORT jint JNICALL Java_clang_clang_kniBridge334 (JNIEnv* jniEnv, jclass jclss, jlong p0) { + return (jint)clang_Type_getNumProtocols(*(CXType*)p0); +} +JNIEXPORT void JNICALL Java_clang_clang_kniBridge335 (JNIEnv* jniEnv, jclass jclss, jlong p0, jint p1, jlong p2) { + CXCursor kniStructResult = clang_Type_getProtocol(*(CXType*)p0, p1); + memcpy(p2, &kniStructResult, sizeof(kniStructResult)); +} +JNIEXPORT jint JNICALL Java_clang_clang_kniBridge336 (JNIEnv* jniEnv, jclass jclss, jlong p0) { + return (jint)clang_Cursor_isObjCInitMethod(*(CXCursor*)p0); +} +JNIEXPORT jint JNICALL Java_clang_clang_kniBridge337 (JNIEnv* jniEnv, jclass jclss, jlong p0) { + return (jint)clang_Cursor_isObjCReturningRetainedMethod(*(CXCursor*)p0); +} +JNIEXPORT jint JNICALL Java_clang_clang_kniBridge338 (JNIEnv* jniEnv, jclass jclss, jlong p0) { + return (jint)clang_Cursor_isObjCConsumingSelfMethod(*(CXCursor*)p0); +} +JNIEXPORT jint JNICALL Java_clang_clang_kniBridge339 (JNIEnv* jniEnv, jclass jclss, jlong p0) { + return (jint)clang_isExtVectorType(*(CXType*)p0); +} diff --git a/kotlin-native/Interop/Indexer/prebuilt/nativeInteropStubs/kotlin/clang/clang.kt b/kotlin-native/Interop/Indexer/prebuilt/nativeInteropStubs/kotlin/clang/clang.kt new file mode 100644 index 00000000000..f98d9bf03fa --- /dev/null +++ b/kotlin-native/Interop/Indexer/prebuilt/nativeInteropStubs/kotlin/clang/clang.kt @@ -0,0 +1,4733 @@ +@file:JvmName("clang") +@file:Suppress("UNUSED_VARIABLE", "UNUSED_EXPRESSION", "DEPRECATION") +package clang + +import kotlinx.cinterop.* + +// NOTE THIS FILE IS AUTO-GENERATED + +@CNaturalStruct("data", "private_flags") +class CXString(rawPtr: NativePtr) : CStructVar(rawPtr) { + + companion object : CStructVar.Type(16, 8) + + var data: COpaquePointer? + get() = memberAt(0).value + set(value) { memberAt(0).value = value } + + var private_flags: Int + get() = memberAt(8).value + set(value) { memberAt(8).value = value } +} + +@CNaturalStruct("Strings", "Count") +class CXStringSet(rawPtr: NativePtr) : CStructVar(rawPtr) { + + companion object : CStructVar.Type(16, 8) + + var Strings: CPointer? + get() = memberAt>(0).value + set(value) { memberAt>(0).value = value } + + var Count: Int + get() = memberAt(8).value + set(value) { memberAt(8).value = value } +} + +class CXVirtualFileOverlayImpl(rawPtr: NativePtr) : COpaque(rawPtr) + +class CXModuleMapDescriptorImpl(rawPtr: NativePtr) : COpaque(rawPtr) + +class CXTargetInfoImpl(rawPtr: NativePtr) : COpaque(rawPtr) + +class CXTranslationUnitImpl(rawPtr: NativePtr) : COpaque(rawPtr) + +@CNaturalStruct("Filename", "Contents", "Length") +class CXUnsavedFile(rawPtr: NativePtr) : CStructVar(rawPtr) { + + companion object : CStructVar.Type(24, 8) + + var Filename: CPointer? + get() = memberAt>(0).value + set(value) { memberAt>(0).value = value } + + var Contents: CPointer? + get() = memberAt>(8).value + set(value) { memberAt>(8).value = value } + + var Length: Long + get() = memberAt(16).value + set(value) { memberAt(16).value = value } +} + +@CNaturalStruct("Major", "Minor", "Subminor") +class CXVersion(rawPtr: NativePtr) : CStructVar(rawPtr) { + + companion object : CStructVar.Type(12, 4) + + var Major: Int + get() = memberAt(0).value + set(value) { memberAt(0).value = value } + + var Minor: Int + get() = memberAt(4).value + set(value) { memberAt(4).value = value } + + var Subminor: Int + get() = memberAt(8).value + set(value) { memberAt(8).value = value } +} + +@CNaturalStruct("data") +class CXFileUniqueID(rawPtr: NativePtr) : CStructVar(rawPtr) { + + companion object : CStructVar.Type(24, 8) + + @CLength(3) + val data: CArrayPointer + get() = arrayMemberAt(0) +} + +@CNaturalStruct("ptr_data", "int_data") +class CXSourceLocation(rawPtr: NativePtr) : CStructVar(rawPtr) { + + companion object : CStructVar.Type(24, 8) + + @CLength(2) + val ptr_data: CArrayPointer + get() = arrayMemberAt(0) + + var int_data: Int + get() = memberAt(16).value + set(value) { memberAt(16).value = value } +} + +@CNaturalStruct("ptr_data", "begin_int_data", "end_int_data") +class CXSourceRange(rawPtr: NativePtr) : CStructVar(rawPtr) { + + companion object : CStructVar.Type(24, 8) + + @CLength(2) + val ptr_data: CArrayPointer + get() = arrayMemberAt(0) + + var begin_int_data: Int + get() = memberAt(16).value + set(value) { memberAt(16).value = value } + + var end_int_data: Int + get() = memberAt(20).value + set(value) { memberAt(20).value = value } +} + +@CNaturalStruct("count", "ranges") +class CXSourceRangeList(rawPtr: NativePtr) : CStructVar(rawPtr) { + + companion object : CStructVar.Type(16, 8) + + var count: Int + get() = memberAt(0).value + set(value) { memberAt(0).value = value } + + var ranges: CPointer? + get() = memberAt>(8).value + set(value) { memberAt>(8).value = value } +} + +@CNaturalStruct("kind", "amount") +class CXTUResourceUsageEntry(rawPtr: NativePtr) : CStructVar(rawPtr) { + + companion object : CStructVar.Type(16, 8) + + var kind: CXTUResourceUsageKind + get() = memberAt(0).value + set(value) { memberAt(0).value = value } + + var amount: Long + get() = memberAt(8).value + set(value) { memberAt(8).value = value } +} + +@CNaturalStruct("data", "numEntries", "entries") +class CXTUResourceUsage(rawPtr: NativePtr) : CStructVar(rawPtr) { + + companion object : CStructVar.Type(24, 8) + + var data: COpaquePointer? + get() = memberAt(0).value + set(value) { memberAt(0).value = value } + + var numEntries: Int + get() = memberAt(8).value + set(value) { memberAt(8).value = value } + + var entries: CPointer? + get() = memberAt>(16).value + set(value) { memberAt>(16).value = value } +} + +@CNaturalStruct("kind", "xdata", "data") +class CXCursor(rawPtr: NativePtr) : CStructVar(rawPtr) { + + companion object : CStructVar.Type(32, 8) + + var kind: CXCursorKind + get() = memberAt(0).value + set(value) { memberAt(0).value = value } + + var xdata: Int + get() = memberAt(4).value + set(value) { memberAt(4).value = value } + + @CLength(3) + val data: CArrayPointer + get() = arrayMemberAt(8) +} + +@CNaturalStruct("Platform", "Introduced", "Deprecated", "Obsoleted", "Unavailable", "Message") +class CXPlatformAvailability(rawPtr: NativePtr) : CStructVar(rawPtr) { + + companion object : CStructVar.Type(72, 8) + + val Platform: CXString + get() = memberAt(0) + + val Introduced: CXVersion + get() = memberAt(16) + + val Deprecated: CXVersion + get() = memberAt(28) + + val Obsoleted: CXVersion + get() = memberAt(40) + + var Unavailable: Int + get() = memberAt(52).value + set(value) { memberAt(52).value = value } + + val Message: CXString + get() = memberAt(56) +} + +class CXCursorSetImpl(rawPtr: NativePtr) : COpaque(rawPtr) + +@CNaturalStruct("kind", "data") +class CXType(rawPtr: NativePtr) : CStructVar(rawPtr) { + + companion object : CStructVar.Type(24, 8) + + var kind: CXTypeKind + get() = memberAt(0).value + set(value) { memberAt(0).value = value } + + @CLength(2) + val data: CArrayPointer + get() = arrayMemberAt(8) +} + +@CNaturalStruct("int_data", "ptr_data") +class CXToken(rawPtr: NativePtr) : CStructVar(rawPtr) { + + companion object : CStructVar.Type(24, 8) + + @CLength(4) + val int_data: CArrayPointer + get() = arrayMemberAt(0) + + var ptr_data: COpaquePointer? + get() = memberAt(16).value + set(value) { memberAt(16).value = value } +} + +@CNaturalStruct("CursorKind", "CompletionString") +class CXCompletionResult(rawPtr: NativePtr) : CStructVar(rawPtr) { + + companion object : CStructVar.Type(16, 8) + + var CursorKind: CXCursorKind + get() = memberAt(0).value + set(value) { memberAt(0).value = value } + + var CompletionString: CXCompletionString? + get() = memberAt(8).value + set(value) { memberAt(8).value = value } +} + +@CNaturalStruct("Results", "NumResults") +class CXCodeCompleteResults(rawPtr: NativePtr) : CStructVar(rawPtr) { + + companion object : CStructVar.Type(16, 8) + + var Results: CPointer? + get() = memberAt>(0).value + set(value) { memberAt>(0).value = value } + + var NumResults: Int + get() = memberAt(8).value + set(value) { memberAt(8).value = value } +} + +@CNaturalStruct("context", "visit") +class CXCursorAndRangeVisitor(rawPtr: NativePtr) : CStructVar(rawPtr) { + + companion object : CStructVar.Type(16, 8) + + var context: COpaquePointer? + get() = memberAt(0).value + set(value) { memberAt(0).value = value } + + var visit: CPointer, CValue) -> CXVisitorResult>>? + get() = memberAt, CValue) -> CXVisitorResult>>>(8).value + set(value) { memberAt, CValue) -> CXVisitorResult>>>(8).value = value } +} + +@CNaturalStruct("ptr_data", "int_data") +class CXIdxLoc(rawPtr: NativePtr) : CStructVar(rawPtr) { + + companion object : CStructVar.Type(24, 8) + + @CLength(2) + val ptr_data: CArrayPointer + get() = arrayMemberAt(0) + + var int_data: Int + get() = memberAt(16).value + set(value) { memberAt(16).value = value } +} + +@CNaturalStruct("hashLoc", "filename", "file", "isImport", "isAngled", "isModuleImport") +class CXIdxIncludedFileInfo(rawPtr: NativePtr) : CStructVar(rawPtr) { + + companion object : CStructVar.Type(56, 8) + + val hashLoc: CXIdxLoc + get() = memberAt(0) + + var filename: CPointer? + get() = memberAt>(24).value + set(value) { memberAt>(24).value = value } + + var file: CXFile? + get() = memberAt(32).value + set(value) { memberAt(32).value = value } + + var isImport: Int + get() = memberAt(40).value + set(value) { memberAt(40).value = value } + + var isAngled: Int + get() = memberAt(44).value + set(value) { memberAt(44).value = value } + + var isModuleImport: Int + get() = memberAt(48).value + set(value) { memberAt(48).value = value } +} + +@CNaturalStruct("file", "module", "loc", "isImplicit") +class CXIdxImportedASTFileInfo(rawPtr: NativePtr) : CStructVar(rawPtr) { + + companion object : CStructVar.Type(48, 8) + + var file: CXFile? + get() = memberAt(0).value + set(value) { memberAt(0).value = value } + + var module: CXModule? + get() = memberAt(8).value + set(value) { memberAt(8).value = value } + + val loc: CXIdxLoc + get() = memberAt(16) + + var isImplicit: Int + get() = memberAt(40).value + set(value) { memberAt(40).value = value } +} + +@CNaturalStruct("kind", "cursor", "loc") +class CXIdxAttrInfo(rawPtr: NativePtr) : CStructVar(rawPtr) { + + companion object : CStructVar.Type(64, 8) + + var kind: CXIdxAttrKind + get() = memberAt(0).value + set(value) { memberAt(0).value = value } + + val cursor: CXCursor + get() = memberAt(8) + + val loc: CXIdxLoc + get() = memberAt(40) +} + +@CNaturalStruct("kind", "templateKind", "lang", "name", "USR", "cursor", "attributes", "numAttributes") +class CXIdxEntityInfo(rawPtr: NativePtr) : CStructVar(rawPtr) { + + companion object : CStructVar.Type(80, 8) + + var kind: CXIdxEntityKind + get() = memberAt(0).value + set(value) { memberAt(0).value = value } + + var templateKind: CXIdxEntityCXXTemplateKind + get() = memberAt(4).value + set(value) { memberAt(4).value = value } + + var lang: CXIdxEntityLanguage + get() = memberAt(8).value + set(value) { memberAt(8).value = value } + + var name: CPointer? + get() = memberAt>(16).value + set(value) { memberAt>(16).value = value } + + var USR: CPointer? + get() = memberAt>(24).value + set(value) { memberAt>(24).value = value } + + val cursor: CXCursor + get() = memberAt(32) + + var attributes: CPointer>? + get() = memberAt>>(64).value + set(value) { memberAt>>(64).value = value } + + var numAttributes: Int + get() = memberAt(72).value + set(value) { memberAt(72).value = value } +} + +@CNaturalStruct("cursor") +class CXIdxContainerInfo(rawPtr: NativePtr) : CStructVar(rawPtr) { + + companion object : CStructVar.Type(32, 8) + + val cursor: CXCursor + get() = memberAt(0) +} + +@CNaturalStruct("attrInfo", "objcClass", "classCursor", "classLoc") +class CXIdxIBOutletCollectionAttrInfo(rawPtr: NativePtr) : CStructVar(rawPtr) { + + companion object : CStructVar.Type(72, 8) + + var attrInfo: CPointer? + get() = memberAt>(0).value + set(value) { memberAt>(0).value = value } + + var objcClass: CPointer? + get() = memberAt>(8).value + set(value) { memberAt>(8).value = value } + + val classCursor: CXCursor + get() = memberAt(16) + + val classLoc: CXIdxLoc + get() = memberAt(48) +} + +@CNaturalStruct("entityInfo", "cursor", "loc", "semanticContainer", "lexicalContainer", "isRedeclaration", "isDefinition", "isContainer", "declAsContainer", "isImplicit", "attributes", "numAttributes", "flags") +class CXIdxDeclInfo(rawPtr: NativePtr) : CStructVar(rawPtr) { + + companion object : CStructVar.Type(128, 8) + + var entityInfo: CPointer? + get() = memberAt>(0).value + set(value) { memberAt>(0).value = value } + + val cursor: CXCursor + get() = memberAt(8) + + val loc: CXIdxLoc + get() = memberAt(40) + + var semanticContainer: CPointer? + get() = memberAt>(64).value + set(value) { memberAt>(64).value = value } + + var lexicalContainer: CPointer? + get() = memberAt>(72).value + set(value) { memberAt>(72).value = value } + + var isRedeclaration: Int + get() = memberAt(80).value + set(value) { memberAt(80).value = value } + + var isDefinition: Int + get() = memberAt(84).value + set(value) { memberAt(84).value = value } + + var isContainer: Int + get() = memberAt(88).value + set(value) { memberAt(88).value = value } + + var declAsContainer: CPointer? + get() = memberAt>(96).value + set(value) { memberAt>(96).value = value } + + var isImplicit: Int + get() = memberAt(104).value + set(value) { memberAt(104).value = value } + + var attributes: CPointer>? + get() = memberAt>>(112).value + set(value) { memberAt>>(112).value = value } + + var numAttributes: Int + get() = memberAt(120).value + set(value) { memberAt(120).value = value } + + var flags: Int + get() = memberAt(124).value + set(value) { memberAt(124).value = value } +} + +@CNaturalStruct("declInfo", "kind") +class CXIdxObjCContainerDeclInfo(rawPtr: NativePtr) : CStructVar(rawPtr) { + + companion object : CStructVar.Type(16, 8) + + var declInfo: CPointer? + get() = memberAt>(0).value + set(value) { memberAt>(0).value = value } + + var kind: CXIdxObjCContainerKind + get() = memberAt(8).value + set(value) { memberAt(8).value = value } +} + +@CNaturalStruct("base", "cursor", "loc") +class CXIdxBaseClassInfo(rawPtr: NativePtr) : CStructVar(rawPtr) { + + companion object : CStructVar.Type(64, 8) + + var base: CPointer? + get() = memberAt>(0).value + set(value) { memberAt>(0).value = value } + + val cursor: CXCursor + get() = memberAt(8) + + val loc: CXIdxLoc + get() = memberAt(40) +} + +@CNaturalStruct("protocol", "cursor", "loc") +class CXIdxObjCProtocolRefInfo(rawPtr: NativePtr) : CStructVar(rawPtr) { + + companion object : CStructVar.Type(64, 8) + + var protocol: CPointer? + get() = memberAt>(0).value + set(value) { memberAt>(0).value = value } + + val cursor: CXCursor + get() = memberAt(8) + + val loc: CXIdxLoc + get() = memberAt(40) +} + +@CNaturalStruct("protocols", "numProtocols") +class CXIdxObjCProtocolRefListInfo(rawPtr: NativePtr) : CStructVar(rawPtr) { + + companion object : CStructVar.Type(16, 8) + + var protocols: CPointer>? + get() = memberAt>>(0).value + set(value) { memberAt>>(0).value = value } + + var numProtocols: Int + get() = memberAt(8).value + set(value) { memberAt(8).value = value } +} + +@CNaturalStruct("containerInfo", "superInfo", "protocols") +class CXIdxObjCInterfaceDeclInfo(rawPtr: NativePtr) : CStructVar(rawPtr) { + + companion object : CStructVar.Type(24, 8) + + var containerInfo: CPointer? + get() = memberAt>(0).value + set(value) { memberAt>(0).value = value } + + var superInfo: CPointer? + get() = memberAt>(8).value + set(value) { memberAt>(8).value = value } + + var protocols: CPointer? + get() = memberAt>(16).value + set(value) { memberAt>(16).value = value } +} + +@CNaturalStruct("containerInfo", "objcClass", "classCursor", "classLoc", "protocols") +class CXIdxObjCCategoryDeclInfo(rawPtr: NativePtr) : CStructVar(rawPtr) { + + companion object : CStructVar.Type(80, 8) + + var containerInfo: CPointer? + get() = memberAt>(0).value + set(value) { memberAt>(0).value = value } + + var objcClass: CPointer? + get() = memberAt>(8).value + set(value) { memberAt>(8).value = value } + + val classCursor: CXCursor + get() = memberAt(16) + + val classLoc: CXIdxLoc + get() = memberAt(48) + + var protocols: CPointer? + get() = memberAt>(72).value + set(value) { memberAt>(72).value = value } +} + +@CNaturalStruct("declInfo", "getter", "setter") +class CXIdxObjCPropertyDeclInfo(rawPtr: NativePtr) : CStructVar(rawPtr) { + + companion object : CStructVar.Type(24, 8) + + var declInfo: CPointer? + get() = memberAt>(0).value + set(value) { memberAt>(0).value = value } + + var getter: CPointer? + get() = memberAt>(8).value + set(value) { memberAt>(8).value = value } + + var setter: CPointer? + get() = memberAt>(16).value + set(value) { memberAt>(16).value = value } +} + +@CNaturalStruct("declInfo", "bases", "numBases") +class CXIdxCXXClassDeclInfo(rawPtr: NativePtr) : CStructVar(rawPtr) { + + companion object : CStructVar.Type(24, 8) + + var declInfo: CPointer? + get() = memberAt>(0).value + set(value) { memberAt>(0).value = value } + + var bases: CPointer>? + get() = memberAt>>(8).value + set(value) { memberAt>>(8).value = value } + + var numBases: Int + get() = memberAt(16).value + set(value) { memberAt(16).value = value } +} + +@CNaturalStruct("kind", "cursor", "loc", "referencedEntity", "parentEntity", "container", "role") +class CXIdxEntityRefInfo(rawPtr: NativePtr) : CStructVar(rawPtr) { + + companion object : CStructVar.Type(96, 8) + + var kind: CXIdxEntityRefKind + get() = memberAt(0).value + set(value) { memberAt(0).value = value } + + val cursor: CXCursor + get() = memberAt(8) + + val loc: CXIdxLoc + get() = memberAt(40) + + var referencedEntity: CPointer? + get() = memberAt>(64).value + set(value) { memberAt>(64).value = value } + + var parentEntity: CPointer? + get() = memberAt>(72).value + set(value) { memberAt>(72).value = value } + + var container: CPointer? + get() = memberAt>(80).value + set(value) { memberAt>(80).value = value } + + var role: CXSymbolRole + get() = memberAt(88).value + set(value) { memberAt(88).value = value } +} + +@CNaturalStruct("abortQuery", "diagnostic", "enteredMainFile", "ppIncludedFile", "importedASTFile", "startedTranslationUnit", "indexDeclaration", "indexEntityReference") +class IndexerCallbacks(rawPtr: NativePtr) : CStructVar(rawPtr) { + + companion object : CStructVar.Type(64, 8) + + var abortQuery: CPointer Int>>? + get() = memberAt Int>>>(0).value + set(value) { memberAt Int>>>(0).value = value } + + var diagnostic: CPointer Unit>>? + get() = memberAt Unit>>>(8).value + set(value) { memberAt Unit>>>(8).value = value } + + var enteredMainFile: CPointer CXIdxClientFile?>>? + get() = memberAt CXIdxClientFile?>>>(16).value + set(value) { memberAt CXIdxClientFile?>>>(16).value = value } + + var ppIncludedFile: CPointer?) -> CXIdxClientFile?>>? + get() = memberAt?) -> CXIdxClientFile?>>>(24).value + set(value) { memberAt?) -> CXIdxClientFile?>>>(24).value = value } + + var importedASTFile: CPointer?) -> CXIdxClientASTFile?>>? + get() = memberAt?) -> CXIdxClientASTFile?>>>(32).value + set(value) { memberAt?) -> CXIdxClientASTFile?>>>(32).value = value } + + var startedTranslationUnit: CPointer CXIdxClientContainer?>>? + get() = memberAt CXIdxClientContainer?>>>(40).value + set(value) { memberAt CXIdxClientContainer?>>>(40).value = value } + + var indexDeclaration: CPointer?) -> Unit>>? + get() = memberAt?) -> Unit>>>(48).value + set(value) { memberAt?) -> Unit>>>(48).value = value } + + var indexEntityReference: CPointer?) -> Unit>>? + get() = memberAt?) -> Unit>>>(56).value + set(value) { memberAt?) -> Unit>>>(56).value = value } +} + +@CNaturalStruct("typeOpaquePtr") +class CXTypeAttributes(rawPtr: NativePtr) : CStructVar(rawPtr) { + + companion object : CStructVar.Type(8, 8) + + var typeOpaquePtr: COpaquePointer? + get() = memberAt(0).value + set(value) { memberAt(0).value = value } +} + +enum class CXErrorCode(override val value: Int) : CEnum { + CXError_Success(0), + CXError_Failure(1), + CXError_Crashed(2), + CXError_InvalidArguments(3), + CXError_ASTReadError(4), + CXError_RefactoringActionUnavailable(5), + CXError_RefactoringNameSizeMismatch(6), + CXError_RefactoringNameInvalid(7), + ; + + companion object { + + fun byValue(value: Int) = CXErrorCode.values().find { it.value == value }!! + } + + class Var(rawPtr: NativePtr) : CEnumVar(rawPtr) { + companion object : Type(IntVar.size.toInt()) + var value: CXErrorCode + get() = byValue(this.reinterpret().value) + set(value) { this.reinterpret().value = value.value } + } +} + +enum class CXAvailabilityKind(override val value: Int) : CEnum { + CXAvailability_Available(0), + CXAvailability_Deprecated(1), + CXAvailability_NotAvailable(2), + CXAvailability_NotAccessible(3), + ; + + companion object { + + fun byValue(value: Int) = CXAvailabilityKind.values().find { it.value == value }!! + } + + class Var(rawPtr: NativePtr) : CEnumVar(rawPtr) { + companion object : Type(IntVar.size.toInt()) + var value: CXAvailabilityKind + get() = byValue(this.reinterpret().value) + set(value) { this.reinterpret().value = value.value } + } +} + +enum class CXCursor_ExceptionSpecificationKind(override val value: Int) : CEnum { + CXCursor_ExceptionSpecificationKind_None(0), + CXCursor_ExceptionSpecificationKind_DynamicNone(1), + CXCursor_ExceptionSpecificationKind_Dynamic(2), + CXCursor_ExceptionSpecificationKind_MSAny(3), + CXCursor_ExceptionSpecificationKind_BasicNoexcept(4), + CXCursor_ExceptionSpecificationKind_ComputedNoexcept(5), + CXCursor_ExceptionSpecificationKind_Unevaluated(6), + CXCursor_ExceptionSpecificationKind_Uninstantiated(7), + CXCursor_ExceptionSpecificationKind_Unparsed(8), + ; + + companion object { + + fun byValue(value: Int) = CXCursor_ExceptionSpecificationKind.values().find { it.value == value }!! + } + + class Var(rawPtr: NativePtr) : CEnumVar(rawPtr) { + companion object : Type(IntVar.size.toInt()) + var value: CXCursor_ExceptionSpecificationKind + get() = byValue(this.reinterpret().value) + set(value) { this.reinterpret().value = value.value } + } +} + +enum class CXDiagnosticSeverity(override val value: Int) : CEnum { + CXDiagnostic_Ignored(0), + CXDiagnostic_Note(1), + CXDiagnostic_Warning(2), + CXDiagnostic_Error(3), + CXDiagnostic_Fatal(4), + ; + + companion object { + + fun byValue(value: Int) = CXDiagnosticSeverity.values().find { it.value == value }!! + } + + class Var(rawPtr: NativePtr) : CEnumVar(rawPtr) { + companion object : Type(IntVar.size.toInt()) + var value: CXDiagnosticSeverity + get() = byValue(this.reinterpret().value) + set(value) { this.reinterpret().value = value.value } + } +} + +enum class CXLoadDiag_Error(override val value: Int) : CEnum { + CXLoadDiag_None(0), + CXLoadDiag_Unknown(1), + CXLoadDiag_CannotLoad(2), + CXLoadDiag_InvalidFile(3), + ; + + companion object { + + fun byValue(value: Int) = CXLoadDiag_Error.values().find { it.value == value }!! + } + + class Var(rawPtr: NativePtr) : CEnumVar(rawPtr) { + companion object : Type(IntVar.size.toInt()) + var value: CXLoadDiag_Error + get() = byValue(this.reinterpret().value) + set(value) { this.reinterpret().value = value.value } + } +} + +enum class CXSaveError(override val value: Int) : CEnum { + CXSaveError_None(0), + CXSaveError_Unknown(1), + CXSaveError_TranslationErrors(2), + CXSaveError_InvalidTU(3), + ; + + companion object { + + fun byValue(value: Int) = CXSaveError.values().find { it.value == value }!! + } + + class Var(rawPtr: NativePtr) : CEnumVar(rawPtr) { + companion object : Type(IntVar.size.toInt()) + var value: CXSaveError + get() = byValue(this.reinterpret().value) + set(value) { this.reinterpret().value = value.value } + } +} + +enum class CXTUResourceUsageKind(override val value: Int) : CEnum { + CXTUResourceUsage_AST(1), + CXTUResourceUsage_Identifiers(2), + CXTUResourceUsage_Selectors(3), + CXTUResourceUsage_GlobalCompletionResults(4), + CXTUResourceUsage_SourceManagerContentCache(5), + CXTUResourceUsage_AST_SideTables(6), + CXTUResourceUsage_SourceManager_Membuffer_Malloc(7), + CXTUResourceUsage_SourceManager_Membuffer_MMap(8), + CXTUResourceUsage_ExternalASTSource_Membuffer_Malloc(9), + CXTUResourceUsage_ExternalASTSource_Membuffer_MMap(10), + CXTUResourceUsage_Preprocessor(11), + CXTUResourceUsage_PreprocessingRecord(12), + CXTUResourceUsage_SourceManager_DataStructures(13), + CXTUResourceUsage_Preprocessor_HeaderSearch(14), + ; + + companion object { + val CXTUResourceUsage_MEMORY_IN_BYTES_BEGIN = CXTUResourceUsage_AST + val CXTUResourceUsage_First = CXTUResourceUsage_AST + val CXTUResourceUsage_MEMORY_IN_BYTES_END = CXTUResourceUsage_Preprocessor_HeaderSearch + val CXTUResourceUsage_Last = CXTUResourceUsage_Preprocessor_HeaderSearch + + fun byValue(value: Int) = CXTUResourceUsageKind.values().find { it.value == value }!! + } + + class Var(rawPtr: NativePtr) : CEnumVar(rawPtr) { + companion object : Type(IntVar.size.toInt()) + var value: CXTUResourceUsageKind + get() = byValue(this.reinterpret().value) + set(value) { this.reinterpret().value = value.value } + } +} + +enum class CXCursorKind(override val value: Int) : CEnum { + CXCursor_UnexposedDecl(1), + CXCursor_StructDecl(2), + CXCursor_UnionDecl(3), + CXCursor_ClassDecl(4), + CXCursor_EnumDecl(5), + CXCursor_FieldDecl(6), + CXCursor_EnumConstantDecl(7), + CXCursor_FunctionDecl(8), + CXCursor_VarDecl(9), + CXCursor_ParmDecl(10), + CXCursor_ObjCInterfaceDecl(11), + CXCursor_ObjCCategoryDecl(12), + CXCursor_ObjCProtocolDecl(13), + CXCursor_ObjCPropertyDecl(14), + CXCursor_ObjCIvarDecl(15), + CXCursor_ObjCInstanceMethodDecl(16), + CXCursor_ObjCClassMethodDecl(17), + CXCursor_ObjCImplementationDecl(18), + CXCursor_ObjCCategoryImplDecl(19), + CXCursor_TypedefDecl(20), + CXCursor_CXXMethod(21), + CXCursor_Namespace(22), + CXCursor_LinkageSpec(23), + CXCursor_Constructor(24), + CXCursor_Destructor(25), + CXCursor_ConversionFunction(26), + CXCursor_TemplateTypeParameter(27), + CXCursor_NonTypeTemplateParameter(28), + CXCursor_TemplateTemplateParameter(29), + CXCursor_FunctionTemplate(30), + CXCursor_ClassTemplate(31), + CXCursor_ClassTemplatePartialSpecialization(32), + CXCursor_NamespaceAlias(33), + CXCursor_UsingDirective(34), + CXCursor_UsingDeclaration(35), + CXCursor_TypeAliasDecl(36), + CXCursor_ObjCSynthesizeDecl(37), + CXCursor_ObjCDynamicDecl(38), + CXCursor_CXXAccessSpecifier(39), + CXCursor_ObjCSuperClassRef(40), + CXCursor_ObjCProtocolRef(41), + CXCursor_ObjCClassRef(42), + CXCursor_TypeRef(43), + CXCursor_CXXBaseSpecifier(44), + CXCursor_TemplateRef(45), + CXCursor_NamespaceRef(46), + CXCursor_MemberRef(47), + CXCursor_LabelRef(48), + CXCursor_OverloadedDeclRef(49), + CXCursor_VariableRef(50), + CXCursor_InvalidFile(70), + CXCursor_NoDeclFound(71), + CXCursor_NotImplemented(72), + CXCursor_InvalidCode(73), + CXCursor_UnexposedExpr(100), + CXCursor_DeclRefExpr(101), + CXCursor_MemberRefExpr(102), + CXCursor_CallExpr(103), + CXCursor_ObjCMessageExpr(104), + CXCursor_BlockExpr(105), + CXCursor_IntegerLiteral(106), + CXCursor_FloatingLiteral(107), + CXCursor_ImaginaryLiteral(108), + CXCursor_StringLiteral(109), + CXCursor_CharacterLiteral(110), + CXCursor_ParenExpr(111), + CXCursor_UnaryOperator(112), + CXCursor_ArraySubscriptExpr(113), + CXCursor_BinaryOperator(114), + CXCursor_CompoundAssignOperator(115), + CXCursor_ConditionalOperator(116), + CXCursor_CStyleCastExpr(117), + CXCursor_CompoundLiteralExpr(118), + CXCursor_InitListExpr(119), + CXCursor_AddrLabelExpr(120), + CXCursor_StmtExpr(121), + CXCursor_GenericSelectionExpr(122), + CXCursor_GNUNullExpr(123), + CXCursor_CXXStaticCastExpr(124), + CXCursor_CXXDynamicCastExpr(125), + CXCursor_CXXReinterpretCastExpr(126), + CXCursor_CXXConstCastExpr(127), + CXCursor_CXXFunctionalCastExpr(128), + CXCursor_CXXTypeidExpr(129), + CXCursor_CXXBoolLiteralExpr(130), + CXCursor_CXXNullPtrLiteralExpr(131), + CXCursor_CXXThisExpr(132), + CXCursor_CXXThrowExpr(133), + CXCursor_CXXNewExpr(134), + CXCursor_CXXDeleteExpr(135), + CXCursor_UnaryExpr(136), + CXCursor_ObjCStringLiteral(137), + CXCursor_ObjCEncodeExpr(138), + CXCursor_ObjCSelectorExpr(139), + CXCursor_ObjCProtocolExpr(140), + CXCursor_ObjCBridgedCastExpr(141), + CXCursor_PackExpansionExpr(142), + CXCursor_SizeOfPackExpr(143), + CXCursor_LambdaExpr(144), + CXCursor_ObjCBoolLiteralExpr(145), + CXCursor_ObjCSelfExpr(146), + CXCursor_OMPArraySectionExpr(147), + CXCursor_ObjCAvailabilityCheckExpr(148), + CXCursor_FixedPointLiteral(149), + CXCursor_UnexposedStmt(200), + CXCursor_LabelStmt(201), + CXCursor_CompoundStmt(202), + CXCursor_CaseStmt(203), + CXCursor_DefaultStmt(204), + CXCursor_IfStmt(205), + CXCursor_SwitchStmt(206), + CXCursor_WhileStmt(207), + CXCursor_DoStmt(208), + CXCursor_ForStmt(209), + CXCursor_GotoStmt(210), + CXCursor_IndirectGotoStmt(211), + CXCursor_ContinueStmt(212), + CXCursor_BreakStmt(213), + CXCursor_ReturnStmt(214), + CXCursor_GCCAsmStmt(215), + CXCursor_ObjCAtTryStmt(216), + CXCursor_ObjCAtCatchStmt(217), + CXCursor_ObjCAtFinallyStmt(218), + CXCursor_ObjCAtThrowStmt(219), + CXCursor_ObjCAtSynchronizedStmt(220), + CXCursor_ObjCAutoreleasePoolStmt(221), + CXCursor_ObjCForCollectionStmt(222), + CXCursor_CXXCatchStmt(223), + CXCursor_CXXTryStmt(224), + CXCursor_CXXForRangeStmt(225), + CXCursor_SEHTryStmt(226), + CXCursor_SEHExceptStmt(227), + CXCursor_SEHFinallyStmt(228), + CXCursor_MSAsmStmt(229), + CXCursor_NullStmt(230), + CXCursor_DeclStmt(231), + CXCursor_OMPParallelDirective(232), + CXCursor_OMPSimdDirective(233), + CXCursor_OMPForDirective(234), + CXCursor_OMPSectionsDirective(235), + CXCursor_OMPSectionDirective(236), + CXCursor_OMPSingleDirective(237), + CXCursor_OMPParallelForDirective(238), + CXCursor_OMPParallelSectionsDirective(239), + CXCursor_OMPTaskDirective(240), + CXCursor_OMPMasterDirective(241), + CXCursor_OMPCriticalDirective(242), + CXCursor_OMPTaskyieldDirective(243), + CXCursor_OMPBarrierDirective(244), + CXCursor_OMPTaskwaitDirective(245), + CXCursor_OMPFlushDirective(246), + CXCursor_SEHLeaveStmt(247), + CXCursor_OMPOrderedDirective(248), + CXCursor_OMPAtomicDirective(249), + CXCursor_OMPForSimdDirective(250), + CXCursor_OMPParallelForSimdDirective(251), + CXCursor_OMPTargetDirective(252), + CXCursor_OMPTeamsDirective(253), + CXCursor_OMPTaskgroupDirective(254), + CXCursor_OMPCancellationPointDirective(255), + CXCursor_OMPCancelDirective(256), + CXCursor_OMPTargetDataDirective(257), + CXCursor_OMPTaskLoopDirective(258), + CXCursor_OMPTaskLoopSimdDirective(259), + CXCursor_OMPDistributeDirective(260), + CXCursor_OMPTargetEnterDataDirective(261), + CXCursor_OMPTargetExitDataDirective(262), + CXCursor_OMPTargetParallelDirective(263), + CXCursor_OMPTargetParallelForDirective(264), + CXCursor_OMPTargetUpdateDirective(265), + CXCursor_OMPDistributeParallelForDirective(266), + CXCursor_OMPDistributeParallelForSimdDirective(267), + CXCursor_OMPDistributeSimdDirective(268), + CXCursor_OMPTargetParallelForSimdDirective(269), + CXCursor_OMPTargetSimdDirective(270), + CXCursor_OMPTeamsDistributeDirective(271), + CXCursor_OMPTeamsDistributeSimdDirective(272), + CXCursor_OMPTeamsDistributeParallelForSimdDirective(273), + CXCursor_OMPTeamsDistributeParallelForDirective(274), + CXCursor_OMPTargetTeamsDirective(275), + CXCursor_OMPTargetTeamsDistributeDirective(276), + CXCursor_OMPTargetTeamsDistributeParallelForDirective(277), + CXCursor_OMPTargetTeamsDistributeParallelForSimdDirective(278), + CXCursor_OMPTargetTeamsDistributeSimdDirective(279), + CXCursor_TranslationUnit(300), + CXCursor_UnexposedAttr(400), + CXCursor_IBActionAttr(401), + CXCursor_IBOutletAttr(402), + CXCursor_IBOutletCollectionAttr(403), + CXCursor_CXXFinalAttr(404), + CXCursor_CXXOverrideAttr(405), + CXCursor_AnnotateAttr(406), + CXCursor_AsmLabelAttr(407), + CXCursor_PackedAttr(408), + CXCursor_PureAttr(409), + CXCursor_ConstAttr(410), + CXCursor_NoDuplicateAttr(411), + CXCursor_CUDAConstantAttr(412), + CXCursor_CUDADeviceAttr(413), + CXCursor_CUDAGlobalAttr(414), + CXCursor_CUDAHostAttr(415), + CXCursor_CUDASharedAttr(416), + CXCursor_VisibilityAttr(417), + CXCursor_DLLExport(418), + CXCursor_DLLImport(419), + CXCursor_NSReturnsRetained(420), + CXCursor_NSReturnsNotRetained(421), + CXCursor_NSReturnsAutoreleased(422), + CXCursor_NSConsumesSelf(423), + CXCursor_NSConsumed(424), + CXCursor_ObjCException(425), + CXCursor_ObjCNSObject(426), + CXCursor_ObjCIndependentClass(427), + CXCursor_ObjCPreciseLifetime(428), + CXCursor_ObjCReturnsInnerPointer(429), + CXCursor_ObjCRequiresSuper(430), + CXCursor_ObjCRootClass(431), + CXCursor_ObjCSubclassingRestricted(432), + CXCursor_ObjCExplicitProtocolImpl(433), + CXCursor_ObjCDesignatedInitializer(434), + CXCursor_ObjCRuntimeVisible(435), + CXCursor_ObjCBoxable(436), + CXCursor_FlagEnum(437), + CXCursor_PreprocessingDirective(500), + CXCursor_MacroDefinition(501), + CXCursor_MacroExpansion(502), + CXCursor_InclusionDirective(503), + CXCursor_ModuleImportDecl(600), + CXCursor_TypeAliasTemplateDecl(601), + CXCursor_StaticAssert(602), + CXCursor_LastExtraDecl(603), + CXCursor_OverloadCandidate(700), + ; + + companion object { + val CXCursor_FirstDecl = CXCursor_UnexposedDecl + val CXCursor_LastDecl = CXCursor_CXXAccessSpecifier + val CXCursor_FirstRef = CXCursor_ObjCSuperClassRef + val CXCursor_LastRef = CXCursor_VariableRef + val CXCursor_FirstInvalid = CXCursor_InvalidFile + val CXCursor_LastInvalid = CXCursor_InvalidCode + val CXCursor_FirstExpr = CXCursor_UnexposedExpr + val CXCursor_LastExpr = CXCursor_FixedPointLiteral + val CXCursor_FirstStmt = CXCursor_UnexposedStmt + val CXCursor_AsmStmt = CXCursor_GCCAsmStmt + val CXCursor_LastStmt = CXCursor_OMPTargetTeamsDistributeSimdDirective + val CXCursor_FirstAttr = CXCursor_UnexposedAttr + val CXCursor_LastAttr = CXCursor_FlagEnum + val CXCursor_FirstPreprocessing = CXCursor_PreprocessingDirective + val CXCursor_MacroInstantiation = CXCursor_MacroExpansion + val CXCursor_LastPreprocessing = CXCursor_InclusionDirective + val CXCursor_FirstExtraDecl = CXCursor_ModuleImportDecl + val CXCursor_FriendDecl = CXCursor_LastExtraDecl + + fun byValue(value: Int) = CXCursorKind.values().find { it.value == value }!! + } + + class Var(rawPtr: NativePtr) : CEnumVar(rawPtr) { + companion object : Type(IntVar.size.toInt()) + var value: CXCursorKind + get() = byValue(this.reinterpret().value) + set(value) { this.reinterpret().value = value.value } + } +} + +enum class CXLinkageKind(override val value: Int) : CEnum { + CXLinkage_Invalid(0), + CXLinkage_NoLinkage(1), + CXLinkage_Internal(2), + CXLinkage_UniqueExternal(3), + CXLinkage_External(4), + ; + + companion object { + + fun byValue(value: Int) = CXLinkageKind.values().find { it.value == value }!! + } + + class Var(rawPtr: NativePtr) : CEnumVar(rawPtr) { + companion object : Type(IntVar.size.toInt()) + var value: CXLinkageKind + get() = byValue(this.reinterpret().value) + set(value) { this.reinterpret().value = value.value } + } +} + +enum class CXVisibilityKind(override val value: Int) : CEnum { + CXVisibility_Invalid(0), + CXVisibility_Hidden(1), + CXVisibility_Protected(2), + CXVisibility_Default(3), + ; + + companion object { + + fun byValue(value: Int) = CXVisibilityKind.values().find { it.value == value }!! + } + + class Var(rawPtr: NativePtr) : CEnumVar(rawPtr) { + companion object : Type(IntVar.size.toInt()) + var value: CXVisibilityKind + get() = byValue(this.reinterpret().value) + set(value) { this.reinterpret().value = value.value } + } +} + +enum class CXLanguageKind(override val value: Int) : CEnum { + CXLanguage_Invalid(0), + CXLanguage_C(1), + CXLanguage_ObjC(2), + CXLanguage_CPlusPlus(3), + ; + + companion object { + + fun byValue(value: Int) = CXLanguageKind.values().find { it.value == value }!! + } + + class Var(rawPtr: NativePtr) : CEnumVar(rawPtr) { + companion object : Type(IntVar.size.toInt()) + var value: CXLanguageKind + get() = byValue(this.reinterpret().value) + set(value) { this.reinterpret().value = value.value } + } +} + +enum class CXTypeKind(override val value: Int) : CEnum { + CXType_Invalid(0), + CXType_Unexposed(1), + CXType_Void(2), + CXType_Bool(3), + CXType_Char_U(4), + CXType_UChar(5), + CXType_Char16(6), + CXType_Char32(7), + CXType_UShort(8), + CXType_UInt(9), + CXType_ULong(10), + CXType_ULongLong(11), + CXType_UInt128(12), + CXType_Char_S(13), + CXType_SChar(14), + CXType_WChar(15), + CXType_Short(16), + CXType_Int(17), + CXType_Long(18), + CXType_LongLong(19), + CXType_Int128(20), + CXType_Float(21), + CXType_Double(22), + CXType_LongDouble(23), + CXType_NullPtr(24), + CXType_Overload(25), + CXType_Dependent(26), + CXType_ObjCId(27), + CXType_ObjCClass(28), + CXType_ObjCSel(29), + CXType_Float128(30), + CXType_Half(31), + CXType_Float16(32), + CXType_ShortAccum(33), + CXType_Accum(34), + CXType_LongAccum(35), + CXType_UShortAccum(36), + CXType_UAccum(37), + CXType_ULongAccum(38), + CXType_Complex(100), + CXType_Pointer(101), + CXType_BlockPointer(102), + CXType_LValueReference(103), + CXType_RValueReference(104), + CXType_Record(105), + CXType_Enum(106), + CXType_Typedef(107), + CXType_ObjCInterface(108), + CXType_ObjCObjectPointer(109), + CXType_FunctionNoProto(110), + CXType_FunctionProto(111), + CXType_ConstantArray(112), + CXType_Vector(113), + CXType_IncompleteArray(114), + CXType_VariableArray(115), + CXType_DependentSizedArray(116), + CXType_MemberPointer(117), + CXType_Auto(118), + CXType_Elaborated(119), + CXType_Pipe(120), + CXType_OCLImage1dRO(121), + CXType_OCLImage1dArrayRO(122), + CXType_OCLImage1dBufferRO(123), + CXType_OCLImage2dRO(124), + CXType_OCLImage2dArrayRO(125), + CXType_OCLImage2dDepthRO(126), + CXType_OCLImage2dArrayDepthRO(127), + CXType_OCLImage2dMSAARO(128), + CXType_OCLImage2dArrayMSAARO(129), + CXType_OCLImage2dMSAADepthRO(130), + CXType_OCLImage2dArrayMSAADepthRO(131), + CXType_OCLImage3dRO(132), + CXType_OCLImage1dWO(133), + CXType_OCLImage1dArrayWO(134), + CXType_OCLImage1dBufferWO(135), + CXType_OCLImage2dWO(136), + CXType_OCLImage2dArrayWO(137), + CXType_OCLImage2dDepthWO(138), + CXType_OCLImage2dArrayDepthWO(139), + CXType_OCLImage2dMSAAWO(140), + CXType_OCLImage2dArrayMSAAWO(141), + CXType_OCLImage2dMSAADepthWO(142), + CXType_OCLImage2dArrayMSAADepthWO(143), + CXType_OCLImage3dWO(144), + CXType_OCLImage1dRW(145), + CXType_OCLImage1dArrayRW(146), + CXType_OCLImage1dBufferRW(147), + CXType_OCLImage2dRW(148), + CXType_OCLImage2dArrayRW(149), + CXType_OCLImage2dDepthRW(150), + CXType_OCLImage2dArrayDepthRW(151), + CXType_OCLImage2dMSAARW(152), + CXType_OCLImage2dArrayMSAARW(153), + CXType_OCLImage2dMSAADepthRW(154), + CXType_OCLImage2dArrayMSAADepthRW(155), + CXType_OCLImage3dRW(156), + CXType_OCLSampler(157), + CXType_OCLEvent(158), + CXType_OCLQueue(159), + CXType_OCLReserveID(160), + CXType_ObjCObject(161), + CXType_ObjCTypeParam(162), + CXType_Attributed(163), + CXType_OCLIntelSubgroupAVCMcePayload(164), + CXType_OCLIntelSubgroupAVCImePayload(165), + CXType_OCLIntelSubgroupAVCRefPayload(166), + CXType_OCLIntelSubgroupAVCSicPayload(167), + CXType_OCLIntelSubgroupAVCMceResult(168), + CXType_OCLIntelSubgroupAVCImeResult(169), + CXType_OCLIntelSubgroupAVCRefResult(170), + CXType_OCLIntelSubgroupAVCSicResult(171), + CXType_OCLIntelSubgroupAVCImeResultSingleRefStreamout(172), + CXType_OCLIntelSubgroupAVCImeResultDualRefStreamout(173), + CXType_OCLIntelSubgroupAVCImeSingleRefStreamin(174), + CXType_OCLIntelSubgroupAVCImeDualRefStreamin(175), + ; + + companion object { + val CXType_FirstBuiltin = CXType_Void + val CXType_LastBuiltin = CXType_ULongAccum + + fun byValue(value: Int) = CXTypeKind.values().find { it.value == value }!! + } + + class Var(rawPtr: NativePtr) : CEnumVar(rawPtr) { + companion object : Type(IntVar.size.toInt()) + var value: CXTypeKind + get() = byValue(this.reinterpret().value) + set(value) { this.reinterpret().value = value.value } + } +} + +enum class CXCallingConv(override val value: Int) : CEnum { + CXCallingConv_Default(0), + CXCallingConv_C(1), + CXCallingConv_X86StdCall(2), + CXCallingConv_X86FastCall(3), + CXCallingConv_X86ThisCall(4), + CXCallingConv_X86Pascal(5), + CXCallingConv_AAPCS(6), + CXCallingConv_AAPCS_VFP(7), + CXCallingConv_X86RegCall(8), + CXCallingConv_IntelOclBicc(9), + CXCallingConv_Win64(10), + CXCallingConv_X86_64SysV(11), + CXCallingConv_X86VectorCall(12), + CXCallingConv_Swift(13), + CXCallingConv_PreserveMost(14), + CXCallingConv_PreserveAll(15), + CXCallingConv_AArch64VectorCall(16), + CXCallingConv_Invalid(100), + CXCallingConv_Unexposed(200), + ; + + companion object { + val CXCallingConv_X86_64Win64 = CXCallingConv_Win64 + + fun byValue(value: Int) = CXCallingConv.values().find { it.value == value }!! + } + + class Var(rawPtr: NativePtr) : CEnumVar(rawPtr) { + companion object : Type(IntVar.size.toInt()) + var value: CXCallingConv + get() = byValue(this.reinterpret().value) + set(value) { this.reinterpret().value = value.value } + } +} + +enum class CXTemplateArgumentKind(override val value: Int) : CEnum { + CXTemplateArgumentKind_Null(0), + CXTemplateArgumentKind_Type(1), + CXTemplateArgumentKind_Declaration(2), + CXTemplateArgumentKind_NullPtr(3), + CXTemplateArgumentKind_Integral(4), + CXTemplateArgumentKind_Template(5), + CXTemplateArgumentKind_TemplateExpansion(6), + CXTemplateArgumentKind_Expression(7), + CXTemplateArgumentKind_Pack(8), + CXTemplateArgumentKind_Invalid(9), + ; + + companion object { + + fun byValue(value: Int) = CXTemplateArgumentKind.values().find { it.value == value }!! + } + + class Var(rawPtr: NativePtr) : CEnumVar(rawPtr) { + companion object : Type(IntVar.size.toInt()) + var value: CXTemplateArgumentKind + get() = byValue(this.reinterpret().value) + set(value) { this.reinterpret().value = value.value } + } +} + +enum class CX_CXXAccessSpecifier(override val value: Int) : CEnum { + CX_CXXInvalidAccessSpecifier(0), + CX_CXXPublic(1), + CX_CXXProtected(2), + CX_CXXPrivate(3), + ; + + companion object { + + fun byValue(value: Int) = CX_CXXAccessSpecifier.values().find { it.value == value }!! + } + + class Var(rawPtr: NativePtr) : CEnumVar(rawPtr) { + companion object : Type(IntVar.size.toInt()) + var value: CX_CXXAccessSpecifier + get() = byValue(this.reinterpret().value) + set(value) { this.reinterpret().value = value.value } + } +} + +enum class CX_StorageClass(override val value: Int) : CEnum { + CX_SC_Invalid(0), + CX_SC_None(1), + CX_SC_Extern(2), + CX_SC_Static(3), + CX_SC_PrivateExtern(4), + CX_SC_OpenCLWorkGroupLocal(5), + CX_SC_Auto(6), + CX_SC_Register(7), + ; + + companion object { + + fun byValue(value: Int) = CX_StorageClass.values().find { it.value == value }!! + } + + class Var(rawPtr: NativePtr) : CEnumVar(rawPtr) { + companion object : Type(IntVar.size.toInt()) + var value: CX_StorageClass + get() = byValue(this.reinterpret().value) + set(value) { this.reinterpret().value = value.value } + } +} + +enum class CXChildVisitResult(override val value: Int) : CEnum { + CXChildVisit_Break(0), + CXChildVisit_Continue(1), + CXChildVisit_Recurse(2), + ; + + companion object { + + fun byValue(value: Int) = CXChildVisitResult.values().find { it.value == value }!! + } + + class Var(rawPtr: NativePtr) : CEnumVar(rawPtr) { + companion object : Type(IntVar.size.toInt()) + var value: CXChildVisitResult + get() = byValue(this.reinterpret().value) + set(value) { this.reinterpret().value = value.value } + } +} + +enum class CXTokenKind(override val value: Int) : CEnum { + CXToken_Punctuation(0), + CXToken_Keyword(1), + CXToken_Identifier(2), + CXToken_Literal(3), + CXToken_Comment(4), + ; + + companion object { + + fun byValue(value: Int) = CXTokenKind.values().find { it.value == value }!! + } + + class Var(rawPtr: NativePtr) : CEnumVar(rawPtr) { + companion object : Type(IntVar.size.toInt()) + var value: CXTokenKind + get() = byValue(this.reinterpret().value) + set(value) { this.reinterpret().value = value.value } + } +} + +enum class CXCompletionChunkKind(override val value: Int) : CEnum { + CXCompletionChunk_Optional(0), + CXCompletionChunk_TypedText(1), + CXCompletionChunk_Text(2), + CXCompletionChunk_Placeholder(3), + CXCompletionChunk_Informative(4), + CXCompletionChunk_CurrentParameter(5), + CXCompletionChunk_LeftParen(6), + CXCompletionChunk_RightParen(7), + CXCompletionChunk_LeftBracket(8), + CXCompletionChunk_RightBracket(9), + CXCompletionChunk_LeftBrace(10), + CXCompletionChunk_RightBrace(11), + CXCompletionChunk_LeftAngle(12), + CXCompletionChunk_RightAngle(13), + CXCompletionChunk_Comma(14), + CXCompletionChunk_ResultType(15), + CXCompletionChunk_Colon(16), + CXCompletionChunk_SemiColon(17), + CXCompletionChunk_Equal(18), + CXCompletionChunk_HorizontalSpace(19), + CXCompletionChunk_VerticalSpace(20), + ; + + companion object { + + fun byValue(value: Int) = CXCompletionChunkKind.values().find { it.value == value }!! + } + + class Var(rawPtr: NativePtr) : CEnumVar(rawPtr) { + companion object : Type(IntVar.size.toInt()) + var value: CXCompletionChunkKind + get() = byValue(this.reinterpret().value) + set(value) { this.reinterpret().value = value.value } + } +} + +enum class CXEvalResultKind(override val value: Int) : CEnum { + CXEval_Int(1), + CXEval_Float(2), + CXEval_ObjCStrLiteral(3), + CXEval_StrLiteral(4), + CXEval_CFStr(5), + CXEval_Other(6), + CXEval_UnExposed(0), + ; + + companion object { + + fun byValue(value: Int) = CXEvalResultKind.values().find { it.value == value }!! + } + + class Var(rawPtr: NativePtr) : CEnumVar(rawPtr) { + companion object : Type(IntVar.size.toInt()) + var value: CXEvalResultKind + get() = byValue(this.reinterpret().value) + set(value) { this.reinterpret().value = value.value } + } +} + +enum class CXVisitorResult(override val value: Int) : CEnum { + CXVisit_Break(0), + CXVisit_Continue(1), + ; + + companion object { + + fun byValue(value: Int) = CXVisitorResult.values().find { it.value == value }!! + } + + class Var(rawPtr: NativePtr) : CEnumVar(rawPtr) { + companion object : Type(IntVar.size.toInt()) + var value: CXVisitorResult + get() = byValue(this.reinterpret().value) + set(value) { this.reinterpret().value = value.value } + } +} + +enum class CXResult(override val value: Int) : CEnum { + CXResult_Success(0), + CXResult_Invalid(1), + CXResult_VisitBreak(2), + ; + + companion object { + + fun byValue(value: Int) = CXResult.values().find { it.value == value }!! + } + + class Var(rawPtr: NativePtr) : CEnumVar(rawPtr) { + companion object : Type(IntVar.size.toInt()) + var value: CXResult + get() = byValue(this.reinterpret().value) + set(value) { this.reinterpret().value = value.value } + } +} + +enum class CXIdxEntityKind(override val value: Int) : CEnum { + CXIdxEntity_Unexposed(0), + CXIdxEntity_Typedef(1), + CXIdxEntity_Function(2), + CXIdxEntity_Variable(3), + CXIdxEntity_Field(4), + CXIdxEntity_EnumConstant(5), + CXIdxEntity_ObjCClass(6), + CXIdxEntity_ObjCProtocol(7), + CXIdxEntity_ObjCCategory(8), + CXIdxEntity_ObjCInstanceMethod(9), + CXIdxEntity_ObjCClassMethod(10), + CXIdxEntity_ObjCProperty(11), + CXIdxEntity_ObjCIvar(12), + CXIdxEntity_Enum(13), + CXIdxEntity_Struct(14), + CXIdxEntity_Union(15), + CXIdxEntity_CXXClass(16), + CXIdxEntity_CXXNamespace(17), + CXIdxEntity_CXXNamespaceAlias(18), + CXIdxEntity_CXXStaticVariable(19), + CXIdxEntity_CXXStaticMethod(20), + CXIdxEntity_CXXInstanceMethod(21), + CXIdxEntity_CXXConstructor(22), + CXIdxEntity_CXXDestructor(23), + CXIdxEntity_CXXConversionFunction(24), + CXIdxEntity_CXXTypeAlias(25), + CXIdxEntity_CXXInterface(26), + ; + + companion object { + + fun byValue(value: Int) = CXIdxEntityKind.values().find { it.value == value }!! + } + + class Var(rawPtr: NativePtr) : CEnumVar(rawPtr) { + companion object : Type(IntVar.size.toInt()) + var value: CXIdxEntityKind + get() = byValue(this.reinterpret().value) + set(value) { this.reinterpret().value = value.value } + } +} + +enum class CXNullabilityKind(override val value: Int) : CEnum { + CXNullabilityKind_Nullable(0), + CXNullabilityKind_NonNull(1), + CXNullabilityKind_Unspecified(2), + ; + + companion object { + + fun byValue(value: Int) = CXNullabilityKind.values().find { it.value == value }!! + } + + class Var(rawPtr: NativePtr) : CEnumVar(rawPtr) { + companion object : Type(IntVar.size.toInt()) + var value: CXNullabilityKind + get() = byValue(this.reinterpret().value) + set(value) { this.reinterpret().value = value.value } + } +} + +fun clang_getCString(string: CValue): CPointer? { + memScoped { + return interpretCPointer(kniBridge0(string.getPointer(memScope).rawValue)) + } +} + +fun clang_disposeString(string: CValue): Unit { + memScoped { + return kniBridge1(string.getPointer(memScope).rawValue) + } +} + +fun clang_disposeStringSet(set: CValuesRef?): Unit { + memScoped { + return kniBridge2(set?.getPointer(memScope).rawValue) + } +} + +fun clang_getBuildSessionTimestamp(): Long { + return kniBridge3() +} + +fun clang_VirtualFileOverlay_create(options: Int): CXVirtualFileOverlay? { + return interpretCPointer(kniBridge4(options)) +} + +fun clang_VirtualFileOverlay_addFileMapping(arg0: CXVirtualFileOverlay?, virtualPath: String?, realPath: String?): CXErrorCode { + memScoped { + return CXErrorCode.byValue(kniBridge5(arg0.rawValue, virtualPath?.cstr?.getPointer(memScope).rawValue, realPath?.cstr?.getPointer(memScope).rawValue)) + } +} + +fun clang_VirtualFileOverlay_setCaseSensitivity(arg0: CXVirtualFileOverlay?, caseSensitive: Int): CXErrorCode { + return CXErrorCode.byValue(kniBridge6(arg0.rawValue, caseSensitive)) +} + +fun clang_VirtualFileOverlay_writeToBuffer(arg0: CXVirtualFileOverlay?, options: Int, out_buffer_ptr: CValuesRef>?, out_buffer_size: CValuesRef?): CXErrorCode { + memScoped { + return CXErrorCode.byValue(kniBridge7(arg0.rawValue, options, out_buffer_ptr?.getPointer(memScope).rawValue, out_buffer_size?.getPointer(memScope).rawValue)) + } +} + +fun clang_free(buffer: CValuesRef<*>?): Unit { + memScoped { + return kniBridge8(buffer?.getPointer(memScope).rawValue) + } +} + +fun clang_VirtualFileOverlay_dispose(arg0: CXVirtualFileOverlay?): Unit { + return kniBridge9(arg0.rawValue) +} + +fun clang_ModuleMapDescriptor_create(options: Int): CXModuleMapDescriptor? { + return interpretCPointer(kniBridge10(options)) +} + +fun clang_ModuleMapDescriptor_setFrameworkModuleName(arg0: CXModuleMapDescriptor?, name: String?): CXErrorCode { + memScoped { + return CXErrorCode.byValue(kniBridge11(arg0.rawValue, name?.cstr?.getPointer(memScope).rawValue)) + } +} + +fun clang_ModuleMapDescriptor_setUmbrellaHeader(arg0: CXModuleMapDescriptor?, name: String?): CXErrorCode { + memScoped { + return CXErrorCode.byValue(kniBridge12(arg0.rawValue, name?.cstr?.getPointer(memScope).rawValue)) + } +} + +fun clang_ModuleMapDescriptor_writeToBuffer(arg0: CXModuleMapDescriptor?, options: Int, out_buffer_ptr: CValuesRef>?, out_buffer_size: CValuesRef?): CXErrorCode { + memScoped { + return CXErrorCode.byValue(kniBridge13(arg0.rawValue, options, out_buffer_ptr?.getPointer(memScope).rawValue, out_buffer_size?.getPointer(memScope).rawValue)) + } +} + +fun clang_ModuleMapDescriptor_dispose(arg0: CXModuleMapDescriptor?): Unit { + return kniBridge14(arg0.rawValue) +} + +fun clang_createIndex(excludeDeclarationsFromPCH: Int, displayDiagnostics: Int): CXIndex? { + return interpretCPointer(kniBridge15(excludeDeclarationsFromPCH, displayDiagnostics)) +} + +fun clang_disposeIndex(index: CXIndex?): Unit { + return kniBridge16(index.rawValue) +} + +fun clang_CXIndex_setGlobalOptions(arg0: CXIndex?, options: Int): Unit { + return kniBridge17(arg0.rawValue, options) +} + +fun clang_CXIndex_getGlobalOptions(arg0: CXIndex?): Int { + return kniBridge18(arg0.rawValue) +} + +fun clang_CXIndex_setInvocationEmissionPathOption(arg0: CXIndex?, Path: String?): Unit { + memScoped { + return kniBridge19(arg0.rawValue, Path?.cstr?.getPointer(memScope).rawValue) + } +} + +fun clang_getFileName(SFile: CXFile?): CValue { + val kniRetVal = nativeHeap.alloc() + try { + kniBridge20(SFile.rawValue, kniRetVal.rawPtr) + return kniRetVal.readValue() + } finally { nativeHeap.free(kniRetVal) } +} + +fun clang_getFileTime(SFile: CXFile?): time_t { + return kniBridge21(SFile.rawValue) +} + +fun clang_getFileUniqueID(file: CXFile?, outID: CValuesRef?): Int { + memScoped { + return kniBridge22(file.rawValue, outID?.getPointer(memScope).rawValue) + } +} + +fun clang_isFileMultipleIncludeGuarded(tu: CXTranslationUnit?, file: CXFile?): Int { + return kniBridge23(tu.rawValue, file.rawValue) +} + +fun clang_getFile(tu: CXTranslationUnit?, file_name: String?): CXFile? { + memScoped { + return interpretCPointer(kniBridge24(tu.rawValue, file_name?.cstr?.getPointer(memScope).rawValue)) + } +} + +fun clang_getFileContents(tu: CXTranslationUnit?, file: CXFile?, size: CValuesRef?): CPointer? { + memScoped { + return interpretCPointer(kniBridge25(tu.rawValue, file.rawValue, size?.getPointer(memScope).rawValue)) + } +} + +fun clang_File_isEqual(file1: CXFile?, file2: CXFile?): Int { + return kniBridge26(file1.rawValue, file2.rawValue) +} + +fun clang_File_tryGetRealPathName(file: CXFile?): CValue { + val kniRetVal = nativeHeap.alloc() + try { + kniBridge27(file.rawValue, kniRetVal.rawPtr) + return kniRetVal.readValue() + } finally { nativeHeap.free(kniRetVal) } +} + +fun clang_getNullLocation(): CValue { + val kniRetVal = nativeHeap.alloc() + try { + kniBridge28(kniRetVal.rawPtr) + return kniRetVal.readValue() + } finally { nativeHeap.free(kniRetVal) } +} + +fun clang_equalLocations(loc1: CValue, loc2: CValue): Int { + memScoped { + return kniBridge29(loc1.getPointer(memScope).rawValue, loc2.getPointer(memScope).rawValue) + } +} + +fun clang_getLocation(tu: CXTranslationUnit?, file: CXFile?, line: Int, column: Int): CValue { + val kniRetVal = nativeHeap.alloc() + try { + kniBridge30(tu.rawValue, file.rawValue, line, column, kniRetVal.rawPtr) + return kniRetVal.readValue() + } finally { nativeHeap.free(kniRetVal) } +} + +fun clang_getLocationForOffset(tu: CXTranslationUnit?, file: CXFile?, offset: Int): CValue { + val kniRetVal = nativeHeap.alloc() + try { + kniBridge31(tu.rawValue, file.rawValue, offset, kniRetVal.rawPtr) + return kniRetVal.readValue() + } finally { nativeHeap.free(kniRetVal) } +} + +fun clang_Location_isInSystemHeader(location: CValue): Int { + memScoped { + return kniBridge32(location.getPointer(memScope).rawValue) + } +} + +fun clang_Location_isFromMainFile(location: CValue): Int { + memScoped { + return kniBridge33(location.getPointer(memScope).rawValue) + } +} + +fun clang_getNullRange(): CValue { + val kniRetVal = nativeHeap.alloc() + try { + kniBridge34(kniRetVal.rawPtr) + return kniRetVal.readValue() + } finally { nativeHeap.free(kniRetVal) } +} + +fun clang_getRange(begin: CValue, end: CValue): CValue { + memScoped { + val kniRetVal = nativeHeap.alloc() + try { + kniBridge35(begin.getPointer(memScope).rawValue, end.getPointer(memScope).rawValue, kniRetVal.rawPtr) + return kniRetVal.readValue() + } finally { nativeHeap.free(kniRetVal) } + } +} + +fun clang_equalRanges(range1: CValue, range2: CValue): Int { + memScoped { + return kniBridge36(range1.getPointer(memScope).rawValue, range2.getPointer(memScope).rawValue) + } +} + +fun clang_Range_isNull(range: CValue): Int { + memScoped { + return kniBridge37(range.getPointer(memScope).rawValue) + } +} + +fun clang_getExpansionLocation(location: CValue, file: CValuesRef?, line: CValuesRef?, column: CValuesRef?, offset: CValuesRef?): Unit { + memScoped { + return kniBridge38(location.getPointer(memScope).rawValue, file?.getPointer(memScope).rawValue, line?.getPointer(memScope).rawValue, column?.getPointer(memScope).rawValue, offset?.getPointer(memScope).rawValue) + } +} + +fun clang_getPresumedLocation(location: CValue, filename: CValuesRef?, line: CValuesRef?, column: CValuesRef?): Unit { + memScoped { + return kniBridge39(location.getPointer(memScope).rawValue, filename?.getPointer(memScope).rawValue, line?.getPointer(memScope).rawValue, column?.getPointer(memScope).rawValue) + } +} + +fun clang_getInstantiationLocation(location: CValue, file: CValuesRef?, line: CValuesRef?, column: CValuesRef?, offset: CValuesRef?): Unit { + memScoped { + return kniBridge40(location.getPointer(memScope).rawValue, file?.getPointer(memScope).rawValue, line?.getPointer(memScope).rawValue, column?.getPointer(memScope).rawValue, offset?.getPointer(memScope).rawValue) + } +} + +fun clang_getSpellingLocation(location: CValue, file: CValuesRef?, line: CValuesRef?, column: CValuesRef?, offset: CValuesRef?): Unit { + memScoped { + return kniBridge41(location.getPointer(memScope).rawValue, file?.getPointer(memScope).rawValue, line?.getPointer(memScope).rawValue, column?.getPointer(memScope).rawValue, offset?.getPointer(memScope).rawValue) + } +} + +fun clang_getFileLocation(location: CValue, file: CValuesRef?, line: CValuesRef?, column: CValuesRef?, offset: CValuesRef?): Unit { + memScoped { + return kniBridge42(location.getPointer(memScope).rawValue, file?.getPointer(memScope).rawValue, line?.getPointer(memScope).rawValue, column?.getPointer(memScope).rawValue, offset?.getPointer(memScope).rawValue) + } +} + +fun clang_getRangeStart(range: CValue): CValue { + memScoped { + val kniRetVal = nativeHeap.alloc() + try { + kniBridge43(range.getPointer(memScope).rawValue, kniRetVal.rawPtr) + return kniRetVal.readValue() + } finally { nativeHeap.free(kniRetVal) } + } +} + +fun clang_getRangeEnd(range: CValue): CValue { + memScoped { + val kniRetVal = nativeHeap.alloc() + try { + kniBridge44(range.getPointer(memScope).rawValue, kniRetVal.rawPtr) + return kniRetVal.readValue() + } finally { nativeHeap.free(kniRetVal) } + } +} + +fun clang_getSkippedRanges(tu: CXTranslationUnit?, file: CXFile?): CPointer? { + return interpretCPointer(kniBridge45(tu.rawValue, file.rawValue)) +} + +fun clang_getAllSkippedRanges(tu: CXTranslationUnit?): CPointer? { + return interpretCPointer(kniBridge46(tu.rawValue)) +} + +fun clang_disposeSourceRangeList(ranges: CValuesRef?): Unit { + memScoped { + return kniBridge47(ranges?.getPointer(memScope).rawValue) + } +} + +fun clang_getNumDiagnosticsInSet(Diags: CXDiagnosticSet?): Int { + return kniBridge48(Diags.rawValue) +} + +fun clang_getDiagnosticInSet(Diags: CXDiagnosticSet?, Index: Int): CXDiagnostic? { + return interpretCPointer(kniBridge49(Diags.rawValue, Index)) +} + +fun clang_loadDiagnostics(file: String?, error: CValuesRef?, errorString: CValuesRef?): CXDiagnosticSet? { + memScoped { + return interpretCPointer(kniBridge50(file?.cstr?.getPointer(memScope).rawValue, error?.getPointer(memScope).rawValue, errorString?.getPointer(memScope).rawValue)) + } +} + +fun clang_disposeDiagnosticSet(Diags: CXDiagnosticSet?): Unit { + return kniBridge51(Diags.rawValue) +} + +fun clang_getChildDiagnostics(D: CXDiagnostic?): CXDiagnosticSet? { + return interpretCPointer(kniBridge52(D.rawValue)) +} + +fun clang_getNumDiagnostics(Unit: CXTranslationUnit?): Int { + return kniBridge53(Unit.rawValue) +} + +fun clang_getDiagnostic(Unit: CXTranslationUnit?, Index: Int): CXDiagnostic? { + return interpretCPointer(kniBridge54(Unit.rawValue, Index)) +} + +fun clang_getDiagnosticSetFromTU(Unit: CXTranslationUnit?): CXDiagnosticSet? { + return interpretCPointer(kniBridge55(Unit.rawValue)) +} + +fun clang_disposeDiagnostic(Diagnostic: CXDiagnostic?): Unit { + return kniBridge56(Diagnostic.rawValue) +} + +fun clang_formatDiagnostic(Diagnostic: CXDiagnostic?, Options: Int): CValue { + val kniRetVal = nativeHeap.alloc() + try { + kniBridge57(Diagnostic.rawValue, Options, kniRetVal.rawPtr) + return kniRetVal.readValue() + } finally { nativeHeap.free(kniRetVal) } +} + +fun clang_defaultDiagnosticDisplayOptions(): Int { + return kniBridge58() +} + +fun clang_getDiagnosticSeverity(arg0: CXDiagnostic?): CXDiagnosticSeverity { + return CXDiagnosticSeverity.byValue(kniBridge59(arg0.rawValue)) +} + +fun clang_getDiagnosticLocation(arg0: CXDiagnostic?): CValue { + val kniRetVal = nativeHeap.alloc() + try { + kniBridge60(arg0.rawValue, kniRetVal.rawPtr) + return kniRetVal.readValue() + } finally { nativeHeap.free(kniRetVal) } +} + +fun clang_getDiagnosticSpelling(arg0: CXDiagnostic?): CValue { + val kniRetVal = nativeHeap.alloc() + try { + kniBridge61(arg0.rawValue, kniRetVal.rawPtr) + return kniRetVal.readValue() + } finally { nativeHeap.free(kniRetVal) } +} + +fun clang_getDiagnosticOption(Diag: CXDiagnostic?, Disable: CValuesRef?): CValue { + memScoped { + val kniRetVal = nativeHeap.alloc() + try { + kniBridge62(Diag.rawValue, Disable?.getPointer(memScope).rawValue, kniRetVal.rawPtr) + return kniRetVal.readValue() + } finally { nativeHeap.free(kniRetVal) } + } +} + +fun clang_getDiagnosticCategory(arg0: CXDiagnostic?): Int { + return kniBridge63(arg0.rawValue) +} + +fun clang_getDiagnosticCategoryName(Category: Int): CValue { + val kniRetVal = nativeHeap.alloc() + try { + kniBridge64(Category, kniRetVal.rawPtr) + return kniRetVal.readValue() + } finally { nativeHeap.free(kniRetVal) } +} + +fun clang_getDiagnosticCategoryText(arg0: CXDiagnostic?): CValue { + val kniRetVal = nativeHeap.alloc() + try { + kniBridge65(arg0.rawValue, kniRetVal.rawPtr) + return kniRetVal.readValue() + } finally { nativeHeap.free(kniRetVal) } +} + +fun clang_getDiagnosticNumRanges(arg0: CXDiagnostic?): Int { + return kniBridge66(arg0.rawValue) +} + +fun clang_getDiagnosticRange(Diagnostic: CXDiagnostic?, Range: Int): CValue { + val kniRetVal = nativeHeap.alloc() + try { + kniBridge67(Diagnostic.rawValue, Range, kniRetVal.rawPtr) + return kniRetVal.readValue() + } finally { nativeHeap.free(kniRetVal) } +} + +fun clang_getDiagnosticNumFixIts(Diagnostic: CXDiagnostic?): Int { + return kniBridge68(Diagnostic.rawValue) +} + +fun clang_getDiagnosticFixIt(Diagnostic: CXDiagnostic?, FixIt: Int, ReplacementRange: CValuesRef?): CValue { + memScoped { + val kniRetVal = nativeHeap.alloc() + try { + kniBridge69(Diagnostic.rawValue, FixIt, ReplacementRange?.getPointer(memScope).rawValue, kniRetVal.rawPtr) + return kniRetVal.readValue() + } finally { nativeHeap.free(kniRetVal) } + } +} + +fun clang_getTranslationUnitSpelling(CTUnit: CXTranslationUnit?): CValue { + val kniRetVal = nativeHeap.alloc() + try { + kniBridge70(CTUnit.rawValue, kniRetVal.rawPtr) + return kniRetVal.readValue() + } finally { nativeHeap.free(kniRetVal) } +} + +fun clang_createTranslationUnitFromSourceFile(CIdx: CXIndex?, source_filename: String?, num_clang_command_line_args: Int, clang_command_line_args: CValuesRef>?, num_unsaved_files: Int, unsaved_files: CValuesRef?): CXTranslationUnit? { + memScoped { + return interpretCPointer(kniBridge71(CIdx.rawValue, source_filename?.cstr?.getPointer(memScope).rawValue, num_clang_command_line_args, clang_command_line_args?.getPointer(memScope).rawValue, num_unsaved_files, unsaved_files?.getPointer(memScope).rawValue)) + } +} + +fun clang_createTranslationUnit(CIdx: CXIndex?, ast_filename: String?): CXTranslationUnit? { + memScoped { + return interpretCPointer(kniBridge72(CIdx.rawValue, ast_filename?.cstr?.getPointer(memScope).rawValue)) + } +} + +fun clang_createTranslationUnit2(CIdx: CXIndex?, ast_filename: String?, out_TU: CValuesRef?): CXErrorCode { + memScoped { + return CXErrorCode.byValue(kniBridge73(CIdx.rawValue, ast_filename?.cstr?.getPointer(memScope).rawValue, out_TU?.getPointer(memScope).rawValue)) + } +} + +fun clang_defaultEditingTranslationUnitOptions(): Int { + return kniBridge74() +} + +fun clang_parseTranslationUnit(CIdx: CXIndex?, source_filename: String?, command_line_args: CValuesRef>?, num_command_line_args: Int, unsaved_files: CValuesRef?, num_unsaved_files: Int, options: Int): CXTranslationUnit? { + memScoped { + return interpretCPointer(kniBridge75(CIdx.rawValue, source_filename?.cstr?.getPointer(memScope).rawValue, command_line_args?.getPointer(memScope).rawValue, num_command_line_args, unsaved_files?.getPointer(memScope).rawValue, num_unsaved_files, options)) + } +} + +fun clang_parseTranslationUnit2(CIdx: CXIndex?, source_filename: String?, command_line_args: CValuesRef>?, num_command_line_args: Int, unsaved_files: CValuesRef?, num_unsaved_files: Int, options: Int, out_TU: CValuesRef?): CXErrorCode { + memScoped { + return CXErrorCode.byValue(kniBridge76(CIdx.rawValue, source_filename?.cstr?.getPointer(memScope).rawValue, command_line_args?.getPointer(memScope).rawValue, num_command_line_args, unsaved_files?.getPointer(memScope).rawValue, num_unsaved_files, options, out_TU?.getPointer(memScope).rawValue)) + } +} + +fun clang_parseTranslationUnit2FullArgv(CIdx: CXIndex?, source_filename: String?, command_line_args: CValuesRef>?, num_command_line_args: Int, unsaved_files: CValuesRef?, num_unsaved_files: Int, options: Int, out_TU: CValuesRef?): CXErrorCode { + memScoped { + return CXErrorCode.byValue(kniBridge77(CIdx.rawValue, source_filename?.cstr?.getPointer(memScope).rawValue, command_line_args?.getPointer(memScope).rawValue, num_command_line_args, unsaved_files?.getPointer(memScope).rawValue, num_unsaved_files, options, out_TU?.getPointer(memScope).rawValue)) + } +} + +fun clang_defaultSaveOptions(TU: CXTranslationUnit?): Int { + return kniBridge78(TU.rawValue) +} + +fun clang_saveTranslationUnit(TU: CXTranslationUnit?, FileName: String?, options: Int): Int { + memScoped { + return kniBridge79(TU.rawValue, FileName?.cstr?.getPointer(memScope).rawValue, options) + } +} + +fun clang_suspendTranslationUnit(arg0: CXTranslationUnit?): Int { + return kniBridge80(arg0.rawValue) +} + +fun clang_disposeTranslationUnit(arg0: CXTranslationUnit?): Unit { + return kniBridge81(arg0.rawValue) +} + +fun clang_defaultReparseOptions(TU: CXTranslationUnit?): Int { + return kniBridge82(TU.rawValue) +} + +fun clang_reparseTranslationUnit(TU: CXTranslationUnit?, num_unsaved_files: Int, unsaved_files: CValuesRef?, options: Int): Int { + memScoped { + return kniBridge83(TU.rawValue, num_unsaved_files, unsaved_files?.getPointer(memScope).rawValue, options) + } +} + +fun clang_getTUResourceUsageName(kind: CXTUResourceUsageKind): CPointer? { + return interpretCPointer(kniBridge84(kind.value)) +} + +fun clang_getCXTUResourceUsage(TU: CXTranslationUnit?): CValue { + val kniRetVal = nativeHeap.alloc() + try { + kniBridge85(TU.rawValue, kniRetVal.rawPtr) + return kniRetVal.readValue() + } finally { nativeHeap.free(kniRetVal) } +} + +fun clang_disposeCXTUResourceUsage(usage: CValue): Unit { + memScoped { + return kniBridge86(usage.getPointer(memScope).rawValue) + } +} + +fun clang_getTranslationUnitTargetInfo(CTUnit: CXTranslationUnit?): CXTargetInfo? { + return interpretCPointer(kniBridge87(CTUnit.rawValue)) +} + +fun clang_TargetInfo_dispose(Info: CXTargetInfo?): Unit { + return kniBridge88(Info.rawValue) +} + +fun clang_TargetInfo_getTriple(Info: CXTargetInfo?): CValue { + val kniRetVal = nativeHeap.alloc() + try { + kniBridge89(Info.rawValue, kniRetVal.rawPtr) + return kniRetVal.readValue() + } finally { nativeHeap.free(kniRetVal) } +} + +fun clang_TargetInfo_getPointerWidth(Info: CXTargetInfo?): Int { + return kniBridge90(Info.rawValue) +} + +fun clang_getNullCursor(): CValue { + val kniRetVal = nativeHeap.alloc() + try { + kniBridge91(kniRetVal.rawPtr) + return kniRetVal.readValue() + } finally { nativeHeap.free(kniRetVal) } +} + +fun clang_getTranslationUnitCursor(arg0: CXTranslationUnit?): CValue { + val kniRetVal = nativeHeap.alloc() + try { + kniBridge92(arg0.rawValue, kniRetVal.rawPtr) + return kniRetVal.readValue() + } finally { nativeHeap.free(kniRetVal) } +} + +fun clang_equalCursors(arg0: CValue, arg1: CValue): Int { + memScoped { + return kniBridge93(arg0.getPointer(memScope).rawValue, arg1.getPointer(memScope).rawValue) + } +} + +fun clang_Cursor_isNull(cursor: CValue): Int { + memScoped { + return kniBridge94(cursor.getPointer(memScope).rawValue) + } +} + +fun clang_hashCursor(arg0: CValue): Int { + memScoped { + return kniBridge95(arg0.getPointer(memScope).rawValue) + } +} + +fun clang_getCursorKind(arg0: CValue): CXCursorKind { + memScoped { + return CXCursorKind.byValue(kniBridge96(arg0.getPointer(memScope).rawValue)) + } +} + +fun clang_isDeclaration(arg0: CXCursorKind): Int { + return kniBridge97(arg0.value) +} + +fun clang_isInvalidDeclaration(arg0: CValue): Int { + memScoped { + return kniBridge98(arg0.getPointer(memScope).rawValue) + } +} + +fun clang_isReference(arg0: CXCursorKind): Int { + return kniBridge99(arg0.value) +} + +fun clang_isExpression(arg0: CXCursorKind): Int { + return kniBridge100(arg0.value) +} + +fun clang_isStatement(arg0: CXCursorKind): Int { + return kniBridge101(arg0.value) +} + +fun clang_isAttribute(arg0: CXCursorKind): Int { + return kniBridge102(arg0.value) +} + +fun clang_Cursor_hasAttrs(C: CValue): Int { + memScoped { + return kniBridge103(C.getPointer(memScope).rawValue) + } +} + +fun clang_isInvalid(arg0: CXCursorKind): Int { + return kniBridge104(arg0.value) +} + +fun clang_isTranslationUnit(arg0: CXCursorKind): Int { + return kniBridge105(arg0.value) +} + +fun clang_isPreprocessing(arg0: CXCursorKind): Int { + return kniBridge106(arg0.value) +} + +fun clang_isUnexposed(arg0: CXCursorKind): Int { + return kniBridge107(arg0.value) +} + +fun clang_getCursorLinkage(cursor: CValue): CXLinkageKind { + memScoped { + return CXLinkageKind.byValue(kniBridge108(cursor.getPointer(memScope).rawValue)) + } +} + +fun clang_getCursorVisibility(cursor: CValue): CXVisibilityKind { + memScoped { + return CXVisibilityKind.byValue(kniBridge109(cursor.getPointer(memScope).rawValue)) + } +} + +fun clang_getCursorAvailability(cursor: CValue): CXAvailabilityKind { + memScoped { + return CXAvailabilityKind.byValue(kniBridge110(cursor.getPointer(memScope).rawValue)) + } +} + +fun clang_getCursorPlatformAvailability(cursor: CValue, always_deprecated: CValuesRef?, deprecated_message: CValuesRef?, always_unavailable: CValuesRef?, unavailable_message: CValuesRef?, availability: CValuesRef?, availability_size: Int): Int { + memScoped { + return kniBridge111(cursor.getPointer(memScope).rawValue, always_deprecated?.getPointer(memScope).rawValue, deprecated_message?.getPointer(memScope).rawValue, always_unavailable?.getPointer(memScope).rawValue, unavailable_message?.getPointer(memScope).rawValue, availability?.getPointer(memScope).rawValue, availability_size) + } +} + +fun clang_disposeCXPlatformAvailability(availability: CValuesRef?): Unit { + memScoped { + return kniBridge112(availability?.getPointer(memScope).rawValue) + } +} + +fun clang_getCursorLanguage(cursor: CValue): CXLanguageKind { + memScoped { + return CXLanguageKind.byValue(kniBridge113(cursor.getPointer(memScope).rawValue)) + } +} + +fun clang_getCursorTLSKind(cursor: CValue): CXTLSKind { + memScoped { + return kniBridge114(cursor.getPointer(memScope).rawValue) + } +} + +fun clang_Cursor_getTranslationUnit(arg0: CValue): CXTranslationUnit? { + memScoped { + return interpretCPointer(kniBridge115(arg0.getPointer(memScope).rawValue)) + } +} + +fun clang_createCXCursorSet(): CXCursorSet? { + return interpretCPointer(kniBridge116()) +} + +fun clang_disposeCXCursorSet(cset: CXCursorSet?): Unit { + return kniBridge117(cset.rawValue) +} + +fun clang_CXCursorSet_contains(cset: CXCursorSet?, cursor: CValue): Int { + memScoped { + return kniBridge118(cset.rawValue, cursor.getPointer(memScope).rawValue) + } +} + +fun clang_CXCursorSet_insert(cset: CXCursorSet?, cursor: CValue): Int { + memScoped { + return kniBridge119(cset.rawValue, cursor.getPointer(memScope).rawValue) + } +} + +fun clang_getCursorSemanticParent(cursor: CValue): CValue { + memScoped { + val kniRetVal = nativeHeap.alloc() + try { + kniBridge120(cursor.getPointer(memScope).rawValue, kniRetVal.rawPtr) + return kniRetVal.readValue() + } finally { nativeHeap.free(kniRetVal) } + } +} + +fun clang_getCursorLexicalParent(cursor: CValue): CValue { + memScoped { + val kniRetVal = nativeHeap.alloc() + try { + kniBridge121(cursor.getPointer(memScope).rawValue, kniRetVal.rawPtr) + return kniRetVal.readValue() + } finally { nativeHeap.free(kniRetVal) } + } +} + +fun clang_getOverriddenCursors(cursor: CValue, overridden: CValuesRef>?, num_overridden: CValuesRef?): Unit { + memScoped { + return kniBridge122(cursor.getPointer(memScope).rawValue, overridden?.getPointer(memScope).rawValue, num_overridden?.getPointer(memScope).rawValue) + } +} + +fun clang_disposeOverriddenCursors(overridden: CValuesRef?): Unit { + memScoped { + return kniBridge123(overridden?.getPointer(memScope).rawValue) + } +} + +fun clang_getIncludedFile(cursor: CValue): CXFile? { + memScoped { + return interpretCPointer(kniBridge124(cursor.getPointer(memScope).rawValue)) + } +} + +fun clang_getCursor(arg0: CXTranslationUnit?, arg1: CValue): CValue { + memScoped { + val kniRetVal = nativeHeap.alloc() + try { + kniBridge125(arg0.rawValue, arg1.getPointer(memScope).rawValue, kniRetVal.rawPtr) + return kniRetVal.readValue() + } finally { nativeHeap.free(kniRetVal) } + } +} + +fun clang_getCursorLocation(arg0: CValue): CValue { + memScoped { + val kniRetVal = nativeHeap.alloc() + try { + kniBridge126(arg0.getPointer(memScope).rawValue, kniRetVal.rawPtr) + return kniRetVal.readValue() + } finally { nativeHeap.free(kniRetVal) } + } +} + +fun clang_getCursorExtent(arg0: CValue): CValue { + memScoped { + val kniRetVal = nativeHeap.alloc() + try { + kniBridge127(arg0.getPointer(memScope).rawValue, kniRetVal.rawPtr) + return kniRetVal.readValue() + } finally { nativeHeap.free(kniRetVal) } + } +} + +fun clang_getCursorType(C: CValue): CValue { + memScoped { + val kniRetVal = nativeHeap.alloc() + try { + kniBridge128(C.getPointer(memScope).rawValue, kniRetVal.rawPtr) + return kniRetVal.readValue() + } finally { nativeHeap.free(kniRetVal) } + } +} + +fun clang_getTypeSpelling(CT: CValue): CValue { + memScoped { + val kniRetVal = nativeHeap.alloc() + try { + kniBridge129(CT.getPointer(memScope).rawValue, kniRetVal.rawPtr) + return kniRetVal.readValue() + } finally { nativeHeap.free(kniRetVal) } + } +} + +fun clang_getTypedefDeclUnderlyingType(C: CValue): CValue { + memScoped { + val kniRetVal = nativeHeap.alloc() + try { + kniBridge130(C.getPointer(memScope).rawValue, kniRetVal.rawPtr) + return kniRetVal.readValue() + } finally { nativeHeap.free(kniRetVal) } + } +} + +fun clang_getEnumDeclIntegerType(C: CValue): CValue { + memScoped { + val kniRetVal = nativeHeap.alloc() + try { + kniBridge131(C.getPointer(memScope).rawValue, kniRetVal.rawPtr) + return kniRetVal.readValue() + } finally { nativeHeap.free(kniRetVal) } + } +} + +fun clang_getEnumConstantDeclValue(C: CValue): Long { + memScoped { + return kniBridge132(C.getPointer(memScope).rawValue) + } +} + +fun clang_getEnumConstantDeclUnsignedValue(C: CValue): Long { + memScoped { + return kniBridge133(C.getPointer(memScope).rawValue) + } +} + +fun clang_getFieldDeclBitWidth(C: CValue): Int { + memScoped { + return kniBridge134(C.getPointer(memScope).rawValue) + } +} + +fun clang_Cursor_getNumArguments(C: CValue): Int { + memScoped { + return kniBridge135(C.getPointer(memScope).rawValue) + } +} + +fun clang_Cursor_getArgument(C: CValue, i: Int): CValue { + memScoped { + val kniRetVal = nativeHeap.alloc() + try { + kniBridge136(C.getPointer(memScope).rawValue, i, kniRetVal.rawPtr) + return kniRetVal.readValue() + } finally { nativeHeap.free(kniRetVal) } + } +} + +fun clang_Cursor_getNumTemplateArguments(C: CValue): Int { + memScoped { + return kniBridge137(C.getPointer(memScope).rawValue) + } +} + +fun clang_Cursor_getTemplateArgumentKind(C: CValue, I: Int): CXTemplateArgumentKind { + memScoped { + return CXTemplateArgumentKind.byValue(kniBridge138(C.getPointer(memScope).rawValue, I)) + } +} + +fun clang_Cursor_getTemplateArgumentType(C: CValue, I: Int): CValue { + memScoped { + val kniRetVal = nativeHeap.alloc() + try { + kniBridge139(C.getPointer(memScope).rawValue, I, kniRetVal.rawPtr) + return kniRetVal.readValue() + } finally { nativeHeap.free(kniRetVal) } + } +} + +fun clang_Cursor_getTemplateArgumentValue(C: CValue, I: Int): Long { + memScoped { + return kniBridge140(C.getPointer(memScope).rawValue, I) + } +} + +fun clang_Cursor_getTemplateArgumentUnsignedValue(C: CValue, I: Int): Long { + memScoped { + return kniBridge141(C.getPointer(memScope).rawValue, I) + } +} + +fun clang_equalTypes(A: CValue, B: CValue): Int { + memScoped { + return kniBridge142(A.getPointer(memScope).rawValue, B.getPointer(memScope).rawValue) + } +} + +fun clang_getCanonicalType(T: CValue): CValue { + memScoped { + val kniRetVal = nativeHeap.alloc() + try { + kniBridge143(T.getPointer(memScope).rawValue, kniRetVal.rawPtr) + return kniRetVal.readValue() + } finally { nativeHeap.free(kniRetVal) } + } +} + +fun clang_isConstQualifiedType(T: CValue): Int { + memScoped { + return kniBridge144(T.getPointer(memScope).rawValue) + } +} + +fun clang_Cursor_isMacroFunctionLike(C: CValue): Int { + memScoped { + return kniBridge145(C.getPointer(memScope).rawValue) + } +} + +fun clang_Cursor_isMacroBuiltin(C: CValue): Int { + memScoped { + return kniBridge146(C.getPointer(memScope).rawValue) + } +} + +fun clang_Cursor_isFunctionInlined(C: CValue): Int { + memScoped { + return kniBridge147(C.getPointer(memScope).rawValue) + } +} + +fun clang_isVolatileQualifiedType(T: CValue): Int { + memScoped { + return kniBridge148(T.getPointer(memScope).rawValue) + } +} + +fun clang_isRestrictQualifiedType(T: CValue): Int { + memScoped { + return kniBridge149(T.getPointer(memScope).rawValue) + } +} + +fun clang_getAddressSpace(T: CValue): Int { + memScoped { + return kniBridge150(T.getPointer(memScope).rawValue) + } +} + +fun clang_getTypedefName(CT: CValue): CValue { + memScoped { + val kniRetVal = nativeHeap.alloc() + try { + kniBridge151(CT.getPointer(memScope).rawValue, kniRetVal.rawPtr) + return kniRetVal.readValue() + } finally { nativeHeap.free(kniRetVal) } + } +} + +fun clang_getPointeeType(T: CValue): CValue { + memScoped { + val kniRetVal = nativeHeap.alloc() + try { + kniBridge152(T.getPointer(memScope).rawValue, kniRetVal.rawPtr) + return kniRetVal.readValue() + } finally { nativeHeap.free(kniRetVal) } + } +} + +fun clang_getTypeDeclaration(T: CValue): CValue { + memScoped { + val kniRetVal = nativeHeap.alloc() + try { + kniBridge153(T.getPointer(memScope).rawValue, kniRetVal.rawPtr) + return kniRetVal.readValue() + } finally { nativeHeap.free(kniRetVal) } + } +} + +fun clang_getDeclObjCTypeEncoding(C: CValue): CValue { + memScoped { + val kniRetVal = nativeHeap.alloc() + try { + kniBridge154(C.getPointer(memScope).rawValue, kniRetVal.rawPtr) + return kniRetVal.readValue() + } finally { nativeHeap.free(kniRetVal) } + } +} + +fun clang_Type_getObjCEncoding(type: CValue): CValue { + memScoped { + val kniRetVal = nativeHeap.alloc() + try { + kniBridge155(type.getPointer(memScope).rawValue, kniRetVal.rawPtr) + return kniRetVal.readValue() + } finally { nativeHeap.free(kniRetVal) } + } +} + +fun clang_getTypeKindSpelling(K: CXTypeKind): CValue { + val kniRetVal = nativeHeap.alloc() + try { + kniBridge156(K.value, kniRetVal.rawPtr) + return kniRetVal.readValue() + } finally { nativeHeap.free(kniRetVal) } +} + +fun clang_getFunctionTypeCallingConv(T: CValue): CXCallingConv { + memScoped { + return CXCallingConv.byValue(kniBridge157(T.getPointer(memScope).rawValue)) + } +} + +fun clang_getResultType(T: CValue): CValue { + memScoped { + val kniRetVal = nativeHeap.alloc() + try { + kniBridge158(T.getPointer(memScope).rawValue, kniRetVal.rawPtr) + return kniRetVal.readValue() + } finally { nativeHeap.free(kniRetVal) } + } +} + +fun clang_getExceptionSpecificationType(T: CValue): Int { + memScoped { + return kniBridge159(T.getPointer(memScope).rawValue) + } +} + +fun clang_getNumArgTypes(T: CValue): Int { + memScoped { + return kniBridge160(T.getPointer(memScope).rawValue) + } +} + +fun clang_getArgType(T: CValue, i: Int): CValue { + memScoped { + val kniRetVal = nativeHeap.alloc() + try { + kniBridge161(T.getPointer(memScope).rawValue, i, kniRetVal.rawPtr) + return kniRetVal.readValue() + } finally { nativeHeap.free(kniRetVal) } + } +} + +fun clang_Type_getObjCObjectBaseType(T: CValue): CValue { + memScoped { + val kniRetVal = nativeHeap.alloc() + try { + kniBridge162(T.getPointer(memScope).rawValue, kniRetVal.rawPtr) + return kniRetVal.readValue() + } finally { nativeHeap.free(kniRetVal) } + } +} + +fun clang_Type_getNumObjCProtocolRefs(T: CValue): Int { + memScoped { + return kniBridge163(T.getPointer(memScope).rawValue) + } +} + +fun clang_Type_getObjCProtocolDecl(T: CValue, i: Int): CValue { + memScoped { + val kniRetVal = nativeHeap.alloc() + try { + kniBridge164(T.getPointer(memScope).rawValue, i, kniRetVal.rawPtr) + return kniRetVal.readValue() + } finally { nativeHeap.free(kniRetVal) } + } +} + +fun clang_Type_getNumObjCTypeArgs(T: CValue): Int { + memScoped { + return kniBridge165(T.getPointer(memScope).rawValue) + } +} + +fun clang_Type_getObjCTypeArg(T: CValue, i: Int): CValue { + memScoped { + val kniRetVal = nativeHeap.alloc() + try { + kniBridge166(T.getPointer(memScope).rawValue, i, kniRetVal.rawPtr) + return kniRetVal.readValue() + } finally { nativeHeap.free(kniRetVal) } + } +} + +fun clang_isFunctionTypeVariadic(T: CValue): Int { + memScoped { + return kniBridge167(T.getPointer(memScope).rawValue) + } +} + +fun clang_getCursorResultType(C: CValue): CValue { + memScoped { + val kniRetVal = nativeHeap.alloc() + try { + kniBridge168(C.getPointer(memScope).rawValue, kniRetVal.rawPtr) + return kniRetVal.readValue() + } finally { nativeHeap.free(kniRetVal) } + } +} + +fun clang_getCursorExceptionSpecificationType(C: CValue): Int { + memScoped { + return kniBridge169(C.getPointer(memScope).rawValue) + } +} + +fun clang_isPODType(T: CValue): Int { + memScoped { + return kniBridge170(T.getPointer(memScope).rawValue) + } +} + +fun clang_getElementType(T: CValue): CValue { + memScoped { + val kniRetVal = nativeHeap.alloc() + try { + kniBridge171(T.getPointer(memScope).rawValue, kniRetVal.rawPtr) + return kniRetVal.readValue() + } finally { nativeHeap.free(kniRetVal) } + } +} + +fun clang_getNumElements(T: CValue): Long { + memScoped { + return kniBridge172(T.getPointer(memScope).rawValue) + } +} + +fun clang_getArrayElementType(T: CValue): CValue { + memScoped { + val kniRetVal = nativeHeap.alloc() + try { + kniBridge173(T.getPointer(memScope).rawValue, kniRetVal.rawPtr) + return kniRetVal.readValue() + } finally { nativeHeap.free(kniRetVal) } + } +} + +fun clang_getArraySize(T: CValue): Long { + memScoped { + return kniBridge174(T.getPointer(memScope).rawValue) + } +} + +fun clang_Type_getNamedType(T: CValue): CValue { + memScoped { + val kniRetVal = nativeHeap.alloc() + try { + kniBridge175(T.getPointer(memScope).rawValue, kniRetVal.rawPtr) + return kniRetVal.readValue() + } finally { nativeHeap.free(kniRetVal) } + } +} + +fun clang_Type_isTransparentTagTypedef(T: CValue): Int { + memScoped { + return kniBridge176(T.getPointer(memScope).rawValue) + } +} + +fun clang_Type_getNullability(T: CValue): CXTypeNullabilityKind { + memScoped { + return kniBridge177(T.getPointer(memScope).rawValue) + } +} + +fun clang_Type_getAlignOf(T: CValue): Long { + memScoped { + return kniBridge178(T.getPointer(memScope).rawValue) + } +} + +fun clang_Type_getClassType(T: CValue): CValue { + memScoped { + val kniRetVal = nativeHeap.alloc() + try { + kniBridge179(T.getPointer(memScope).rawValue, kniRetVal.rawPtr) + return kniRetVal.readValue() + } finally { nativeHeap.free(kniRetVal) } + } +} + +fun clang_Type_getSizeOf(T: CValue): Long { + memScoped { + return kniBridge180(T.getPointer(memScope).rawValue) + } +} + +fun clang_Type_getOffsetOf(T: CValue, S: String?): Long { + memScoped { + return kniBridge181(T.getPointer(memScope).rawValue, S?.cstr?.getPointer(memScope).rawValue) + } +} + +fun clang_Type_getModifiedType(T: CValue): CValue { + memScoped { + val kniRetVal = nativeHeap.alloc() + try { + kniBridge182(T.getPointer(memScope).rawValue, kniRetVal.rawPtr) + return kniRetVal.readValue() + } finally { nativeHeap.free(kniRetVal) } + } +} + +fun clang_Cursor_getOffsetOfField(C: CValue): Long { + memScoped { + return kniBridge183(C.getPointer(memScope).rawValue) + } +} + +fun clang_Cursor_isAnonymous(C: CValue): Int { + memScoped { + return kniBridge184(C.getPointer(memScope).rawValue) + } +} + +fun clang_Type_getNumTemplateArguments(T: CValue): Int { + memScoped { + return kniBridge185(T.getPointer(memScope).rawValue) + } +} + +fun clang_Type_getTemplateArgumentAsType(T: CValue, i: Int): CValue { + memScoped { + val kniRetVal = nativeHeap.alloc() + try { + kniBridge186(T.getPointer(memScope).rawValue, i, kniRetVal.rawPtr) + return kniRetVal.readValue() + } finally { nativeHeap.free(kniRetVal) } + } +} + +fun clang_Type_getCXXRefQualifier(T: CValue): CXRefQualifierKind { + memScoped { + return kniBridge187(T.getPointer(memScope).rawValue) + } +} + +fun clang_Cursor_isBitField(C: CValue): Int { + memScoped { + return kniBridge188(C.getPointer(memScope).rawValue) + } +} + +fun clang_isVirtualBase(arg0: CValue): Int { + memScoped { + return kniBridge189(arg0.getPointer(memScope).rawValue) + } +} + +fun clang_getCXXAccessSpecifier(arg0: CValue): CX_CXXAccessSpecifier { + memScoped { + return CX_CXXAccessSpecifier.byValue(kniBridge190(arg0.getPointer(memScope).rawValue)) + } +} + +fun clang_Cursor_getStorageClass(arg0: CValue): CX_StorageClass { + memScoped { + return CX_StorageClass.byValue(kniBridge191(arg0.getPointer(memScope).rawValue)) + } +} + +fun clang_getNumOverloadedDecls(cursor: CValue): Int { + memScoped { + return kniBridge192(cursor.getPointer(memScope).rawValue) + } +} + +fun clang_getOverloadedDecl(cursor: CValue, index: Int): CValue { + memScoped { + val kniRetVal = nativeHeap.alloc() + try { + kniBridge193(cursor.getPointer(memScope).rawValue, index, kniRetVal.rawPtr) + return kniRetVal.readValue() + } finally { nativeHeap.free(kniRetVal) } + } +} + +fun clang_getIBOutletCollectionType(arg0: CValue): CValue { + memScoped { + val kniRetVal = nativeHeap.alloc() + try { + kniBridge194(arg0.getPointer(memScope).rawValue, kniRetVal.rawPtr) + return kniRetVal.readValue() + } finally { nativeHeap.free(kniRetVal) } + } +} + +fun clang_visitChildren(parent: CValue, visitor: CXCursorVisitor?, client_data: CXClientData?): Int { + memScoped { + return kniBridge195(parent.getPointer(memScope).rawValue, visitor.rawValue, client_data.rawValue) + } +} + +fun clang_getCursorUSR(arg0: CValue): CValue { + memScoped { + val kniRetVal = nativeHeap.alloc() + try { + kniBridge196(arg0.getPointer(memScope).rawValue, kniRetVal.rawPtr) + return kniRetVal.readValue() + } finally { nativeHeap.free(kniRetVal) } + } +} + +fun clang_constructUSR_ObjCClass(class_name: String?): CValue { + memScoped { + val kniRetVal = nativeHeap.alloc() + try { + kniBridge197(class_name?.cstr?.getPointer(memScope).rawValue, kniRetVal.rawPtr) + return kniRetVal.readValue() + } finally { nativeHeap.free(kniRetVal) } + } +} + +fun clang_constructUSR_ObjCCategory(class_name: String?, category_name: String?): CValue { + memScoped { + val kniRetVal = nativeHeap.alloc() + try { + kniBridge198(class_name?.cstr?.getPointer(memScope).rawValue, category_name?.cstr?.getPointer(memScope).rawValue, kniRetVal.rawPtr) + return kniRetVal.readValue() + } finally { nativeHeap.free(kniRetVal) } + } +} + +fun clang_constructUSR_ObjCProtocol(protocol_name: String?): CValue { + memScoped { + val kniRetVal = nativeHeap.alloc() + try { + kniBridge199(protocol_name?.cstr?.getPointer(memScope).rawValue, kniRetVal.rawPtr) + return kniRetVal.readValue() + } finally { nativeHeap.free(kniRetVal) } + } +} + +fun clang_constructUSR_ObjCIvar(name: String?, classUSR: CValue): CValue { + memScoped { + val kniRetVal = nativeHeap.alloc() + try { + kniBridge200(name?.cstr?.getPointer(memScope).rawValue, classUSR.getPointer(memScope).rawValue, kniRetVal.rawPtr) + return kniRetVal.readValue() + } finally { nativeHeap.free(kniRetVal) } + } +} + +fun clang_constructUSR_ObjCMethod(name: String?, isInstanceMethod: Int, classUSR: CValue): CValue { + memScoped { + val kniRetVal = nativeHeap.alloc() + try { + kniBridge201(name?.cstr?.getPointer(memScope).rawValue, isInstanceMethod, classUSR.getPointer(memScope).rawValue, kniRetVal.rawPtr) + return kniRetVal.readValue() + } finally { nativeHeap.free(kniRetVal) } + } +} + +fun clang_constructUSR_ObjCProperty(property: String?, classUSR: CValue): CValue { + memScoped { + val kniRetVal = nativeHeap.alloc() + try { + kniBridge202(property?.cstr?.getPointer(memScope).rawValue, classUSR.getPointer(memScope).rawValue, kniRetVal.rawPtr) + return kniRetVal.readValue() + } finally { nativeHeap.free(kniRetVal) } + } +} + +fun clang_getCursorSpelling(arg0: CValue): CValue { + memScoped { + val kniRetVal = nativeHeap.alloc() + try { + kniBridge203(arg0.getPointer(memScope).rawValue, kniRetVal.rawPtr) + return kniRetVal.readValue() + } finally { nativeHeap.free(kniRetVal) } + } +} + +fun clang_Cursor_getSpellingNameRange(arg0: CValue, pieceIndex: Int, options: Int): CValue { + memScoped { + val kniRetVal = nativeHeap.alloc() + try { + kniBridge204(arg0.getPointer(memScope).rawValue, pieceIndex, options, kniRetVal.rawPtr) + return kniRetVal.readValue() + } finally { nativeHeap.free(kniRetVal) } + } +} + +fun clang_PrintingPolicy_getProperty(Policy: CXPrintingPolicy?, Property: CXPrintingPolicyProperty): Int { + return kniBridge205(Policy.rawValue, Property) +} + +fun clang_PrintingPolicy_setProperty(Policy: CXPrintingPolicy?, Property: CXPrintingPolicyProperty, Value: Int): Unit { + return kniBridge206(Policy.rawValue, Property, Value) +} + +fun clang_getCursorPrintingPolicy(arg0: CValue): CXPrintingPolicy? { + memScoped { + return interpretCPointer(kniBridge207(arg0.getPointer(memScope).rawValue)) + } +} + +fun clang_PrintingPolicy_dispose(Policy: CXPrintingPolicy?): Unit { + return kniBridge208(Policy.rawValue) +} + +fun clang_getCursorPrettyPrinted(Cursor: CValue, Policy: CXPrintingPolicy?): CValue { + memScoped { + val kniRetVal = nativeHeap.alloc() + try { + kniBridge209(Cursor.getPointer(memScope).rawValue, Policy.rawValue, kniRetVal.rawPtr) + return kniRetVal.readValue() + } finally { nativeHeap.free(kniRetVal) } + } +} + +fun clang_getCursorDisplayName(arg0: CValue): CValue { + memScoped { + val kniRetVal = nativeHeap.alloc() + try { + kniBridge210(arg0.getPointer(memScope).rawValue, kniRetVal.rawPtr) + return kniRetVal.readValue() + } finally { nativeHeap.free(kniRetVal) } + } +} + +fun clang_getCursorReferenced(arg0: CValue): CValue { + memScoped { + val kniRetVal = nativeHeap.alloc() + try { + kniBridge211(arg0.getPointer(memScope).rawValue, kniRetVal.rawPtr) + return kniRetVal.readValue() + } finally { nativeHeap.free(kniRetVal) } + } +} + +fun clang_getCursorDefinition(arg0: CValue): CValue { + memScoped { + val kniRetVal = nativeHeap.alloc() + try { + kniBridge212(arg0.getPointer(memScope).rawValue, kniRetVal.rawPtr) + return kniRetVal.readValue() + } finally { nativeHeap.free(kniRetVal) } + } +} + +fun clang_isCursorDefinition(arg0: CValue): Int { + memScoped { + return kniBridge213(arg0.getPointer(memScope).rawValue) + } +} + +fun clang_getCanonicalCursor(arg0: CValue): CValue { + memScoped { + val kniRetVal = nativeHeap.alloc() + try { + kniBridge214(arg0.getPointer(memScope).rawValue, kniRetVal.rawPtr) + return kniRetVal.readValue() + } finally { nativeHeap.free(kniRetVal) } + } +} + +fun clang_Cursor_getObjCSelectorIndex(arg0: CValue): Int { + memScoped { + return kniBridge215(arg0.getPointer(memScope).rawValue) + } +} + +fun clang_Cursor_isDynamicCall(C: CValue): Int { + memScoped { + return kniBridge216(C.getPointer(memScope).rawValue) + } +} + +fun clang_Cursor_getReceiverType(C: CValue): CValue { + memScoped { + val kniRetVal = nativeHeap.alloc() + try { + kniBridge217(C.getPointer(memScope).rawValue, kniRetVal.rawPtr) + return kniRetVal.readValue() + } finally { nativeHeap.free(kniRetVal) } + } +} + +fun clang_Cursor_getObjCPropertyAttributes(C: CValue, reserved: Int): Int { + memScoped { + return kniBridge218(C.getPointer(memScope).rawValue, reserved) + } +} + +fun clang_Cursor_getObjCPropertyGetterName(C: CValue): CValue { + memScoped { + val kniRetVal = nativeHeap.alloc() + try { + kniBridge219(C.getPointer(memScope).rawValue, kniRetVal.rawPtr) + return kniRetVal.readValue() + } finally { nativeHeap.free(kniRetVal) } + } +} + +fun clang_Cursor_getObjCPropertySetterName(C: CValue): CValue { + memScoped { + val kniRetVal = nativeHeap.alloc() + try { + kniBridge220(C.getPointer(memScope).rawValue, kniRetVal.rawPtr) + return kniRetVal.readValue() + } finally { nativeHeap.free(kniRetVal) } + } +} + +fun clang_Cursor_getObjCDeclQualifiers(C: CValue): Int { + memScoped { + return kniBridge221(C.getPointer(memScope).rawValue) + } +} + +fun clang_Cursor_isObjCOptional(C: CValue): Int { + memScoped { + return kniBridge222(C.getPointer(memScope).rawValue) + } +} + +fun clang_Cursor_isVariadic(C: CValue): Int { + memScoped { + return kniBridge223(C.getPointer(memScope).rawValue) + } +} + +fun clang_Cursor_isExternalSymbol(C: CValue, language: CValuesRef?, definedIn: CValuesRef?, isGenerated: CValuesRef?): Int { + memScoped { + return kniBridge224(C.getPointer(memScope).rawValue, language?.getPointer(memScope).rawValue, definedIn?.getPointer(memScope).rawValue, isGenerated?.getPointer(memScope).rawValue) + } +} + +fun clang_Cursor_getCommentRange(C: CValue): CValue { + memScoped { + val kniRetVal = nativeHeap.alloc() + try { + kniBridge225(C.getPointer(memScope).rawValue, kniRetVal.rawPtr) + return kniRetVal.readValue() + } finally { nativeHeap.free(kniRetVal) } + } +} + +fun clang_Cursor_getRawCommentText(C: CValue): CValue { + memScoped { + val kniRetVal = nativeHeap.alloc() + try { + kniBridge226(C.getPointer(memScope).rawValue, kniRetVal.rawPtr) + return kniRetVal.readValue() + } finally { nativeHeap.free(kniRetVal) } + } +} + +fun clang_Cursor_getBriefCommentText(C: CValue): CValue { + memScoped { + val kniRetVal = nativeHeap.alloc() + try { + kniBridge227(C.getPointer(memScope).rawValue, kniRetVal.rawPtr) + return kniRetVal.readValue() + } finally { nativeHeap.free(kniRetVal) } + } +} + +fun clang_Cursor_getMangling(arg0: CValue): CValue { + memScoped { + val kniRetVal = nativeHeap.alloc() + try { + kniBridge228(arg0.getPointer(memScope).rawValue, kniRetVal.rawPtr) + return kniRetVal.readValue() + } finally { nativeHeap.free(kniRetVal) } + } +} + +fun clang_Cursor_getCXXManglings(arg0: CValue): CPointer? { + memScoped { + return interpretCPointer(kniBridge229(arg0.getPointer(memScope).rawValue)) + } +} + +fun clang_Cursor_getObjCManglings(arg0: CValue): CPointer? { + memScoped { + return interpretCPointer(kniBridge230(arg0.getPointer(memScope).rawValue)) + } +} + +fun clang_Cursor_getModule(C: CValue): CXModule? { + memScoped { + return interpretCPointer(kniBridge231(C.getPointer(memScope).rawValue)) + } +} + +fun clang_getModuleForFile(arg0: CXTranslationUnit?, arg1: CXFile?): CXModule? { + return interpretCPointer(kniBridge232(arg0.rawValue, arg1.rawValue)) +} + +fun clang_Module_getASTFile(Module: CXModule?): CXFile? { + return interpretCPointer(kniBridge233(Module.rawValue)) +} + +fun clang_Module_getParent(Module: CXModule?): CXModule? { + return interpretCPointer(kniBridge234(Module.rawValue)) +} + +fun clang_Module_getName(Module: CXModule?): CValue { + val kniRetVal = nativeHeap.alloc() + try { + kniBridge235(Module.rawValue, kniRetVal.rawPtr) + return kniRetVal.readValue() + } finally { nativeHeap.free(kniRetVal) } +} + +fun clang_Module_getFullName(Module: CXModule?): CValue { + val kniRetVal = nativeHeap.alloc() + try { + kniBridge236(Module.rawValue, kniRetVal.rawPtr) + return kniRetVal.readValue() + } finally { nativeHeap.free(kniRetVal) } +} + +fun clang_Module_isSystem(Module: CXModule?): Int { + return kniBridge237(Module.rawValue) +} + +fun clang_Module_getNumTopLevelHeaders(arg0: CXTranslationUnit?, Module: CXModule?): Int { + return kniBridge238(arg0.rawValue, Module.rawValue) +} + +fun clang_Module_getTopLevelHeader(arg0: CXTranslationUnit?, Module: CXModule?, Index: Int): CXFile? { + return interpretCPointer(kniBridge239(arg0.rawValue, Module.rawValue, Index)) +} + +fun clang_CXXConstructor_isConvertingConstructor(C: CValue): Int { + memScoped { + return kniBridge240(C.getPointer(memScope).rawValue) + } +} + +fun clang_CXXConstructor_isCopyConstructor(C: CValue): Int { + memScoped { + return kniBridge241(C.getPointer(memScope).rawValue) + } +} + +fun clang_CXXConstructor_isDefaultConstructor(C: CValue): Int { + memScoped { + return kniBridge242(C.getPointer(memScope).rawValue) + } +} + +fun clang_CXXConstructor_isMoveConstructor(C: CValue): Int { + memScoped { + return kniBridge243(C.getPointer(memScope).rawValue) + } +} + +fun clang_CXXField_isMutable(C: CValue): Int { + memScoped { + return kniBridge244(C.getPointer(memScope).rawValue) + } +} + +fun clang_CXXMethod_isDefaulted(C: CValue): Int { + memScoped { + return kniBridge245(C.getPointer(memScope).rawValue) + } +} + +fun clang_CXXMethod_isPureVirtual(C: CValue): Int { + memScoped { + return kniBridge246(C.getPointer(memScope).rawValue) + } +} + +fun clang_CXXMethod_isStatic(C: CValue): Int { + memScoped { + return kniBridge247(C.getPointer(memScope).rawValue) + } +} + +fun clang_CXXMethod_isVirtual(C: CValue): Int { + memScoped { + return kniBridge248(C.getPointer(memScope).rawValue) + } +} + +fun clang_CXXRecord_isAbstract(C: CValue): Int { + memScoped { + return kniBridge249(C.getPointer(memScope).rawValue) + } +} + +fun clang_EnumDecl_isScoped(C: CValue): Int { + memScoped { + return kniBridge250(C.getPointer(memScope).rawValue) + } +} + +fun clang_CXXMethod_isConst(C: CValue): Int { + memScoped { + return kniBridge251(C.getPointer(memScope).rawValue) + } +} + +fun clang_getTemplateCursorKind(C: CValue): CXCursorKind { + memScoped { + return CXCursorKind.byValue(kniBridge252(C.getPointer(memScope).rawValue)) + } +} + +fun clang_getSpecializedCursorTemplate(C: CValue): CValue { + memScoped { + val kniRetVal = nativeHeap.alloc() + try { + kniBridge253(C.getPointer(memScope).rawValue, kniRetVal.rawPtr) + return kniRetVal.readValue() + } finally { nativeHeap.free(kniRetVal) } + } +} + +fun clang_getCursorReferenceNameRange(C: CValue, NameFlags: Int, PieceIndex: Int): CValue { + memScoped { + val kniRetVal = nativeHeap.alloc() + try { + kniBridge254(C.getPointer(memScope).rawValue, NameFlags, PieceIndex, kniRetVal.rawPtr) + return kniRetVal.readValue() + } finally { nativeHeap.free(kniRetVal) } + } +} + +fun clang_getToken(TU: CXTranslationUnit?, Location: CValue): CPointer? { + memScoped { + return interpretCPointer(kniBridge255(TU.rawValue, Location.getPointer(memScope).rawValue)) + } +} + +fun clang_getTokenKind(arg0: CValue): CXTokenKind { + memScoped { + return CXTokenKind.byValue(kniBridge256(arg0.getPointer(memScope).rawValue)) + } +} + +fun clang_getTokenSpelling(arg0: CXTranslationUnit?, arg1: CValue): CValue { + memScoped { + val kniRetVal = nativeHeap.alloc() + try { + kniBridge257(arg0.rawValue, arg1.getPointer(memScope).rawValue, kniRetVal.rawPtr) + return kniRetVal.readValue() + } finally { nativeHeap.free(kniRetVal) } + } +} + +fun clang_getTokenLocation(arg0: CXTranslationUnit?, arg1: CValue): CValue { + memScoped { + val kniRetVal = nativeHeap.alloc() + try { + kniBridge258(arg0.rawValue, arg1.getPointer(memScope).rawValue, kniRetVal.rawPtr) + return kniRetVal.readValue() + } finally { nativeHeap.free(kniRetVal) } + } +} + +fun clang_getTokenExtent(arg0: CXTranslationUnit?, arg1: CValue): CValue { + memScoped { + val kniRetVal = nativeHeap.alloc() + try { + kniBridge259(arg0.rawValue, arg1.getPointer(memScope).rawValue, kniRetVal.rawPtr) + return kniRetVal.readValue() + } finally { nativeHeap.free(kniRetVal) } + } +} + +fun clang_tokenize(TU: CXTranslationUnit?, Range: CValue, Tokens: CValuesRef>?, NumTokens: CValuesRef?): Unit { + memScoped { + return kniBridge260(TU.rawValue, Range.getPointer(memScope).rawValue, Tokens?.getPointer(memScope).rawValue, NumTokens?.getPointer(memScope).rawValue) + } +} + +fun clang_annotateTokens(TU: CXTranslationUnit?, Tokens: CValuesRef?, NumTokens: Int, Cursors: CValuesRef?): Unit { + memScoped { + return kniBridge261(TU.rawValue, Tokens?.getPointer(memScope).rawValue, NumTokens, Cursors?.getPointer(memScope).rawValue) + } +} + +fun clang_disposeTokens(TU: CXTranslationUnit?, Tokens: CValuesRef?, NumTokens: Int): Unit { + memScoped { + return kniBridge262(TU.rawValue, Tokens?.getPointer(memScope).rawValue, NumTokens) + } +} + +fun clang_getCursorKindSpelling(Kind: CXCursorKind): CValue { + val kniRetVal = nativeHeap.alloc() + try { + kniBridge263(Kind.value, kniRetVal.rawPtr) + return kniRetVal.readValue() + } finally { nativeHeap.free(kniRetVal) } +} + +fun clang_getDefinitionSpellingAndExtent(arg0: CValue, startBuf: CValuesRef>?, endBuf: CValuesRef>?, startLine: CValuesRef?, startColumn: CValuesRef?, endLine: CValuesRef?, endColumn: CValuesRef?): Unit { + memScoped { + return kniBridge264(arg0.getPointer(memScope).rawValue, startBuf?.getPointer(memScope).rawValue, endBuf?.getPointer(memScope).rawValue, startLine?.getPointer(memScope).rawValue, startColumn?.getPointer(memScope).rawValue, endLine?.getPointer(memScope).rawValue, endColumn?.getPointer(memScope).rawValue) + } +} + +fun clang_enableStackTraces(): Unit { + return kniBridge265() +} + +fun clang_executeOnThread(fn: CPointer Unit>>?, user_data: CValuesRef<*>?, stack_size: Int): Unit { + memScoped { + return kniBridge266(fn.rawValue, user_data?.getPointer(memScope).rawValue, stack_size) + } +} + +fun clang_getCompletionChunkKind(completion_string: CXCompletionString?, chunk_number: Int): CXCompletionChunkKind { + return CXCompletionChunkKind.byValue(kniBridge267(completion_string.rawValue, chunk_number)) +} + +fun clang_getCompletionChunkText(completion_string: CXCompletionString?, chunk_number: Int): CValue { + val kniRetVal = nativeHeap.alloc() + try { + kniBridge268(completion_string.rawValue, chunk_number, kniRetVal.rawPtr) + return kniRetVal.readValue() + } finally { nativeHeap.free(kniRetVal) } +} + +fun clang_getCompletionChunkCompletionString(completion_string: CXCompletionString?, chunk_number: Int): CXCompletionString? { + return interpretCPointer(kniBridge269(completion_string.rawValue, chunk_number)) +} + +fun clang_getNumCompletionChunks(completion_string: CXCompletionString?): Int { + return kniBridge270(completion_string.rawValue) +} + +fun clang_getCompletionPriority(completion_string: CXCompletionString?): Int { + return kniBridge271(completion_string.rawValue) +} + +fun clang_getCompletionAvailability(completion_string: CXCompletionString?): CXAvailabilityKind { + return CXAvailabilityKind.byValue(kniBridge272(completion_string.rawValue)) +} + +fun clang_getCompletionNumAnnotations(completion_string: CXCompletionString?): Int { + return kniBridge273(completion_string.rawValue) +} + +fun clang_getCompletionAnnotation(completion_string: CXCompletionString?, annotation_number: Int): CValue { + val kniRetVal = nativeHeap.alloc() + try { + kniBridge274(completion_string.rawValue, annotation_number, kniRetVal.rawPtr) + return kniRetVal.readValue() + } finally { nativeHeap.free(kniRetVal) } +} + +fun clang_getCompletionParent(completion_string: CXCompletionString?, kind: CValuesRef?): CValue { + memScoped { + val kniRetVal = nativeHeap.alloc() + try { + kniBridge275(completion_string.rawValue, kind?.getPointer(memScope).rawValue, kniRetVal.rawPtr) + return kniRetVal.readValue() + } finally { nativeHeap.free(kniRetVal) } + } +} + +fun clang_getCompletionBriefComment(completion_string: CXCompletionString?): CValue { + val kniRetVal = nativeHeap.alloc() + try { + kniBridge276(completion_string.rawValue, kniRetVal.rawPtr) + return kniRetVal.readValue() + } finally { nativeHeap.free(kniRetVal) } +} + +fun clang_getCursorCompletionString(cursor: CValue): CXCompletionString? { + memScoped { + return interpretCPointer(kniBridge277(cursor.getPointer(memScope).rawValue)) + } +} + +fun clang_getCompletionNumFixIts(results: CValuesRef?, completion_index: Int): Int { + memScoped { + return kniBridge278(results?.getPointer(memScope).rawValue, completion_index) + } +} + +fun clang_getCompletionFixIt(results: CValuesRef?, completion_index: Int, fixit_index: Int, replacement_range: CValuesRef?): CValue { + memScoped { + val kniRetVal = nativeHeap.alloc() + try { + kniBridge279(results?.getPointer(memScope).rawValue, completion_index, fixit_index, replacement_range?.getPointer(memScope).rawValue, kniRetVal.rawPtr) + return kniRetVal.readValue() + } finally { nativeHeap.free(kniRetVal) } + } +} + +fun clang_defaultCodeCompleteOptions(): Int { + return kniBridge280() +} + +fun clang_codeCompleteAt(TU: CXTranslationUnit?, complete_filename: String?, complete_line: Int, complete_column: Int, unsaved_files: CValuesRef?, num_unsaved_files: Int, options: Int): CPointer? { + memScoped { + return interpretCPointer(kniBridge281(TU.rawValue, complete_filename?.cstr?.getPointer(memScope).rawValue, complete_line, complete_column, unsaved_files?.getPointer(memScope).rawValue, num_unsaved_files, options)) + } +} + +fun clang_sortCodeCompletionResults(Results: CValuesRef?, NumResults: Int): Unit { + memScoped { + return kniBridge282(Results?.getPointer(memScope).rawValue, NumResults) + } +} + +fun clang_disposeCodeCompleteResults(Results: CValuesRef?): Unit { + memScoped { + return kniBridge283(Results?.getPointer(memScope).rawValue) + } +} + +fun clang_codeCompleteGetNumDiagnostics(Results: CValuesRef?): Int { + memScoped { + return kniBridge284(Results?.getPointer(memScope).rawValue) + } +} + +fun clang_codeCompleteGetDiagnostic(Results: CValuesRef?, Index: Int): CXDiagnostic? { + memScoped { + return interpretCPointer(kniBridge285(Results?.getPointer(memScope).rawValue, Index)) + } +} + +fun clang_codeCompleteGetContexts(Results: CValuesRef?): Long { + memScoped { + return kniBridge286(Results?.getPointer(memScope).rawValue) + } +} + +fun clang_codeCompleteGetContainerKind(Results: CValuesRef?, IsIncomplete: CValuesRef?): CXCursorKind { + memScoped { + return CXCursorKind.byValue(kniBridge287(Results?.getPointer(memScope).rawValue, IsIncomplete?.getPointer(memScope).rawValue)) + } +} + +fun clang_codeCompleteGetContainerUSR(Results: CValuesRef?): CValue { + memScoped { + val kniRetVal = nativeHeap.alloc() + try { + kniBridge288(Results?.getPointer(memScope).rawValue, kniRetVal.rawPtr) + return kniRetVal.readValue() + } finally { nativeHeap.free(kniRetVal) } + } +} + +fun clang_codeCompleteGetObjCSelector(Results: CValuesRef?): CValue { + memScoped { + val kniRetVal = nativeHeap.alloc() + try { + kniBridge289(Results?.getPointer(memScope).rawValue, kniRetVal.rawPtr) + return kniRetVal.readValue() + } finally { nativeHeap.free(kniRetVal) } + } +} + +fun clang_getClangVersion(): CValue { + val kniRetVal = nativeHeap.alloc() + try { + kniBridge290(kniRetVal.rawPtr) + return kniRetVal.readValue() + } finally { nativeHeap.free(kniRetVal) } +} + +fun clang_toggleCrashRecovery(isEnabled: Int): Unit { + return kniBridge291(isEnabled) +} + +fun clang_getInclusions(tu: CXTranslationUnit?, visitor: CXInclusionVisitor?, client_data: CXClientData?): Unit { + return kniBridge292(tu.rawValue, visitor.rawValue, client_data.rawValue) +} + +fun clang_Cursor_Evaluate(C: CValue): CXEvalResult? { + memScoped { + return interpretCPointer(kniBridge293(C.getPointer(memScope).rawValue)) + } +} + +fun clang_EvalResult_getKind(E: CXEvalResult?): CXEvalResultKind { + return CXEvalResultKind.byValue(kniBridge294(E.rawValue)) +} + +fun clang_EvalResult_getAsInt(E: CXEvalResult?): Int { + return kniBridge295(E.rawValue) +} + +fun clang_EvalResult_getAsLongLong(E: CXEvalResult?): Long { + return kniBridge296(E.rawValue) +} + +fun clang_EvalResult_isUnsignedInt(E: CXEvalResult?): Int { + return kniBridge297(E.rawValue) +} + +fun clang_EvalResult_getAsUnsigned(E: CXEvalResult?): Long { + return kniBridge298(E.rawValue) +} + +fun clang_EvalResult_getAsDouble(E: CXEvalResult?): Double { + return kniBridge299(E.rawValue) +} + +fun clang_EvalResult_getAsStr(E: CXEvalResult?): CPointer? { + return interpretCPointer(kniBridge300(E.rawValue)) +} + +fun clang_EvalResult_dispose(E: CXEvalResult?): Unit { + return kniBridge301(E.rawValue) +} + +fun clang_getRemappings(path: String?): CXRemapping? { + memScoped { + return interpretCPointer(kniBridge302(path?.cstr?.getPointer(memScope).rawValue)) + } +} + +fun clang_getRemappingsFromFileList(filePaths: CValuesRef>?, numFiles: Int): CXRemapping? { + memScoped { + return interpretCPointer(kniBridge303(filePaths?.getPointer(memScope).rawValue, numFiles)) + } +} + +fun clang_remap_getNumFiles(arg0: CXRemapping?): Int { + return kniBridge304(arg0.rawValue) +} + +fun clang_remap_getFilenames(arg0: CXRemapping?, index: Int, original: CValuesRef?, transformed: CValuesRef?): Unit { + memScoped { + return kniBridge305(arg0.rawValue, index, original?.getPointer(memScope).rawValue, transformed?.getPointer(memScope).rawValue) + } +} + +fun clang_remap_dispose(arg0: CXRemapping?): Unit { + return kniBridge306(arg0.rawValue) +} + +fun clang_findReferencesInFile(cursor: CValue, file: CXFile?, visitor: CValue): CXResult { + memScoped { + return CXResult.byValue(kniBridge307(cursor.getPointer(memScope).rawValue, file.rawValue, visitor.getPointer(memScope).rawValue)) + } +} + +fun clang_findIncludesInFile(TU: CXTranslationUnit?, file: CXFile?, visitor: CValue): CXResult { + memScoped { + return CXResult.byValue(kniBridge308(TU.rawValue, file.rawValue, visitor.getPointer(memScope).rawValue)) + } +} + +fun clang_index_isEntityObjCContainerKind(arg0: CXIdxEntityKind): Int { + return kniBridge309(arg0.value) +} + +fun clang_index_getObjCContainerDeclInfo(arg0: CValuesRef?): CPointer? { + memScoped { + return interpretCPointer(kniBridge310(arg0?.getPointer(memScope).rawValue)) + } +} + +fun clang_index_getObjCInterfaceDeclInfo(arg0: CValuesRef?): CPointer? { + memScoped { + return interpretCPointer(kniBridge311(arg0?.getPointer(memScope).rawValue)) + } +} + +fun clang_index_getObjCCategoryDeclInfo(arg0: CValuesRef?): CPointer? { + memScoped { + return interpretCPointer(kniBridge312(arg0?.getPointer(memScope).rawValue)) + } +} + +fun clang_index_getObjCProtocolRefListInfo(arg0: CValuesRef?): CPointer? { + memScoped { + return interpretCPointer(kniBridge313(arg0?.getPointer(memScope).rawValue)) + } +} + +fun clang_index_getObjCPropertyDeclInfo(arg0: CValuesRef?): CPointer? { + memScoped { + return interpretCPointer(kniBridge314(arg0?.getPointer(memScope).rawValue)) + } +} + +fun clang_index_getIBOutletCollectionAttrInfo(arg0: CValuesRef?): CPointer? { + memScoped { + return interpretCPointer(kniBridge315(arg0?.getPointer(memScope).rawValue)) + } +} + +fun clang_index_getCXXClassDeclInfo(arg0: CValuesRef?): CPointer? { + memScoped { + return interpretCPointer(kniBridge316(arg0?.getPointer(memScope).rawValue)) + } +} + +fun clang_index_getClientContainer(arg0: CValuesRef?): CXIdxClientContainer? { + memScoped { + return interpretCPointer(kniBridge317(arg0?.getPointer(memScope).rawValue)) + } +} + +fun clang_index_setClientContainer(arg0: CValuesRef?, arg1: CXIdxClientContainer?): Unit { + memScoped { + return kniBridge318(arg0?.getPointer(memScope).rawValue, arg1.rawValue) + } +} + +fun clang_index_getClientEntity(arg0: CValuesRef?): CXIdxClientEntity? { + memScoped { + return interpretCPointer(kniBridge319(arg0?.getPointer(memScope).rawValue)) + } +} + +fun clang_index_setClientEntity(arg0: CValuesRef?, arg1: CXIdxClientEntity?): Unit { + memScoped { + return kniBridge320(arg0?.getPointer(memScope).rawValue, arg1.rawValue) + } +} + +fun clang_IndexAction_create(CIdx: CXIndex?): CXIndexAction? { + return interpretCPointer(kniBridge321(CIdx.rawValue)) +} + +fun clang_IndexAction_dispose(arg0: CXIndexAction?): Unit { + return kniBridge322(arg0.rawValue) +} + +fun clang_indexSourceFile(arg0: CXIndexAction?, client_data: CXClientData?, index_callbacks: CValuesRef?, index_callbacks_size: Int, index_options: Int, source_filename: String?, command_line_args: CValuesRef>?, num_command_line_args: Int, unsaved_files: CValuesRef?, num_unsaved_files: Int, out_TU: CValuesRef?, TU_options: Int): Int { + memScoped { + return kniBridge323(arg0.rawValue, client_data.rawValue, index_callbacks?.getPointer(memScope).rawValue, index_callbacks_size, index_options, source_filename?.cstr?.getPointer(memScope).rawValue, command_line_args?.getPointer(memScope).rawValue, num_command_line_args, unsaved_files?.getPointer(memScope).rawValue, num_unsaved_files, out_TU?.getPointer(memScope).rawValue, TU_options) + } +} + +fun clang_indexSourceFileFullArgv(arg0: CXIndexAction?, client_data: CXClientData?, index_callbacks: CValuesRef?, index_callbacks_size: Int, index_options: Int, source_filename: String?, command_line_args: CValuesRef>?, num_command_line_args: Int, unsaved_files: CValuesRef?, num_unsaved_files: Int, out_TU: CValuesRef?, TU_options: Int): Int { + memScoped { + return kniBridge324(arg0.rawValue, client_data.rawValue, index_callbacks?.getPointer(memScope).rawValue, index_callbacks_size, index_options, source_filename?.cstr?.getPointer(memScope).rawValue, command_line_args?.getPointer(memScope).rawValue, num_command_line_args, unsaved_files?.getPointer(memScope).rawValue, num_unsaved_files, out_TU?.getPointer(memScope).rawValue, TU_options) + } +} + +fun clang_indexTranslationUnit(arg0: CXIndexAction?, client_data: CXClientData?, index_callbacks: CValuesRef?, index_callbacks_size: Int, index_options: Int, arg5: CXTranslationUnit?): Int { + memScoped { + return kniBridge325(arg0.rawValue, client_data.rawValue, index_callbacks?.getPointer(memScope).rawValue, index_callbacks_size, index_options, arg5.rawValue) + } +} + +fun clang_indexLoc_getFileLocation(loc: CValue, indexFile: CValuesRef?, file: CValuesRef?, line: CValuesRef?, column: CValuesRef?, offset: CValuesRef?): Unit { + memScoped { + return kniBridge326(loc.getPointer(memScope).rawValue, indexFile?.getPointer(memScope).rawValue, file?.getPointer(memScope).rawValue, line?.getPointer(memScope).rawValue, column?.getPointer(memScope).rawValue, offset?.getPointer(memScope).rawValue) + } +} + +fun clang_indexLoc_getCXSourceLocation(loc: CValue): CValue { + memScoped { + val kniRetVal = nativeHeap.alloc() + try { + kniBridge327(loc.getPointer(memScope).rawValue, kniRetVal.rawPtr) + return kniRetVal.readValue() + } finally { nativeHeap.free(kniRetVal) } + } +} + +fun clang_Type_visitFields(T: CValue, visitor: CXFieldVisitor?, client_data: CXClientData?): Int { + memScoped { + return kniBridge328(T.getPointer(memScope).rawValue, visitor.rawValue, client_data.rawValue) + } +} + +fun clang_Cursor_getAttributeSpelling(cursor: CValue): CPointer? { + memScoped { + return interpretCPointer(kniBridge329(cursor.getPointer(memScope).rawValue)) + } +} + +fun clang_getDeclTypeAttributes(cursor: CValue): CValue { + memScoped { + val kniRetVal = nativeHeap.alloc() + try { + kniBridge330(cursor.getPointer(memScope).rawValue, kniRetVal.rawPtr) + return kniRetVal.readValue() + } finally { nativeHeap.free(kniRetVal) } + } +} + +fun clang_getResultTypeAttributes(typeAttributes: CValue): CValue { + memScoped { + val kniRetVal = nativeHeap.alloc() + try { + kniBridge331(typeAttributes.getPointer(memScope).rawValue, kniRetVal.rawPtr) + return kniRetVal.readValue() + } finally { nativeHeap.free(kniRetVal) } + } +} + +fun clang_getCursorResultTypeAttributes(cursor: CValue): CValue { + memScoped { + val kniRetVal = nativeHeap.alloc() + try { + kniBridge332(cursor.getPointer(memScope).rawValue, kniRetVal.rawPtr) + return kniRetVal.readValue() + } finally { nativeHeap.free(kniRetVal) } + } +} + +fun clang_Type_getNullabilityKind(type: CValue, attributes: CValue): CXNullabilityKind { + memScoped { + return CXNullabilityKind.byValue(kniBridge333(type.getPointer(memScope).rawValue, attributes.getPointer(memScope).rawValue)) + } +} + +fun clang_Type_getNumProtocols(type: CValue): Int { + memScoped { + return kniBridge334(type.getPointer(memScope).rawValue) + } +} + +fun clang_Type_getProtocol(type: CValue, index: Int): CValue { + memScoped { + val kniRetVal = nativeHeap.alloc() + try { + kniBridge335(type.getPointer(memScope).rawValue, index, kniRetVal.rawPtr) + return kniRetVal.readValue() + } finally { nativeHeap.free(kniRetVal) } + } +} + +fun clang_Cursor_isObjCInitMethod(cursor: CValue): Int { + memScoped { + return kniBridge336(cursor.getPointer(memScope).rawValue) + } +} + +fun clang_Cursor_isObjCReturningRetainedMethod(cursor: CValue): Int { + memScoped { + return kniBridge337(cursor.getPointer(memScope).rawValue) + } +} + +fun clang_Cursor_isObjCConsumingSelfMethod(cursor: CValue): Int { + memScoped { + return kniBridge338(cursor.getPointer(memScope).rawValue) + } +} + +fun clang_isExtVectorType(type: CValue): Int { + memScoped { + return kniBridge339(type.getPointer(memScope).rawValue) + } +} + +val CINDEX_VERSION_MAJOR: Int get() = 0 + +val CINDEX_VERSION_MINOR: Int get() = 50 + +val CINDEX_VERSION: Int get() = 50 + +val CINDEX_VERSION_STRING: String get() = "0.50" + +typealias CXVirtualFileOverlayVar = CPointerVarOf + +typealias CXVirtualFileOverlay = CPointer + +typealias CXModuleMapDescriptorVar = CPointerVarOf + +typealias CXModuleMapDescriptor = CPointer + +typealias CXIndexVar = CPointerVarOf + +typealias CXIndex = COpaquePointer + +typealias CXTargetInfoVar = CPointerVarOf + +typealias CXTargetInfo = CPointer + +typealias CXTranslationUnitVar = CPointerVarOf + +typealias CXTranslationUnit = CPointer + +typealias CXClientDataVar = CPointerVarOf + +typealias CXClientData = COpaquePointer + +typealias CXFileVar = CPointerVarOf + +typealias CXFile = COpaquePointer + +typealias __darwin_time_tVar = LongVarOf<__darwin_time_t> + +typealias __darwin_time_t = Long + +typealias time_tVar = LongVarOf + +typealias time_t = __darwin_time_t + +typealias __darwin_size_tVar = LongVarOf<__darwin_size_t> + +typealias __darwin_size_t = Long + +typealias size_tVar = LongVarOf + +typealias size_t = __darwin_size_t + +typealias CXDiagnosticVar = CPointerVarOf + +typealias CXDiagnostic = COpaquePointer + +typealias CXDiagnosticSetVar = CPointerVarOf + +typealias CXDiagnosticSet = COpaquePointer + +typealias CXCursorSetVar = CPointerVarOf + +typealias CXCursorSet = CPointer + +typealias CXCursorVisitorVar = CPointerVarOf + +typealias CXCursorVisitor = CPointer, CValue, CXClientData?) -> CXChildVisitResult>> + +typealias CXPrintingPolicyVar = CPointerVarOf + +typealias CXPrintingPolicy = COpaquePointer + +typealias CXModuleVar = CPointerVarOf + +typealias CXModule = COpaquePointer + +typealias CXCompletionStringVar = CPointerVarOf + +typealias CXCompletionString = COpaquePointer + +typealias CXInclusionVisitorVar = CPointerVarOf + +typealias CXInclusionVisitor = CPointer?, Int, CXClientData?) -> Unit>> + +typealias CXEvalResultVar = CPointerVarOf + +typealias CXEvalResult = COpaquePointer + +typealias CXRemappingVar = CPointerVarOf + +typealias CXRemapping = COpaquePointer + +typealias CXIdxClientFileVar = CPointerVarOf + +typealias CXIdxClientFile = COpaquePointer + +typealias CXIdxClientEntityVar = CPointerVarOf + +typealias CXIdxClientEntity = COpaquePointer + +typealias CXIdxClientContainerVar = CPointerVarOf + +typealias CXIdxClientContainer = COpaquePointer + +typealias CXIdxClientASTFileVar = CPointerVarOf + +typealias CXIdxClientASTFile = COpaquePointer + +typealias CXIndexActionVar = CPointerVarOf + +typealias CXIndexAction = COpaquePointer + +typealias CXFieldVisitorVar = CPointerVarOf + +typealias CXFieldVisitor = CPointer, CXClientData?) -> CXVisitorResult>> + + +val CXGlobalOpt_None: CXGlobalOptFlags get() = 0 + +val CXGlobalOpt_ThreadBackgroundPriorityForIndexing: CXGlobalOptFlags get() = 1 + +val CXGlobalOpt_ThreadBackgroundPriorityForEditing: CXGlobalOptFlags get() = 2 + +val CXGlobalOpt_ThreadBackgroundPriorityForAll: CXGlobalOptFlags get() = 3 + +typealias CXGlobalOptFlagsVar = IntVarOf + +typealias CXGlobalOptFlags = Int + + +val CXDiagnostic_DisplaySourceLocation: CXDiagnosticDisplayOptions get() = 1 + +val CXDiagnostic_DisplayColumn: CXDiagnosticDisplayOptions get() = 2 + +val CXDiagnostic_DisplaySourceRanges: CXDiagnosticDisplayOptions get() = 4 + +val CXDiagnostic_DisplayOption: CXDiagnosticDisplayOptions get() = 8 + +val CXDiagnostic_DisplayCategoryId: CXDiagnosticDisplayOptions get() = 16 + +val CXDiagnostic_DisplayCategoryName: CXDiagnosticDisplayOptions get() = 32 + +typealias CXDiagnosticDisplayOptionsVar = IntVarOf + +typealias CXDiagnosticDisplayOptions = Int + + +val CXTranslationUnit_None: CXTranslationUnit_Flags get() = 0 + +val CXTranslationUnit_DetailedPreprocessingRecord: CXTranslationUnit_Flags get() = 1 + +val CXTranslationUnit_Incomplete: CXTranslationUnit_Flags get() = 2 + +val CXTranslationUnit_PrecompiledPreamble: CXTranslationUnit_Flags get() = 4 + +val CXTranslationUnit_CacheCompletionResults: CXTranslationUnit_Flags get() = 8 + +val CXTranslationUnit_ForSerialization: CXTranslationUnit_Flags get() = 16 + +val CXTranslationUnit_CXXChainedPCH: CXTranslationUnit_Flags get() = 32 + +val CXTranslationUnit_SkipFunctionBodies: CXTranslationUnit_Flags get() = 64 + +val CXTranslationUnit_IncludeBriefCommentsInCodeCompletion: CXTranslationUnit_Flags get() = 128 + +val CXTranslationUnit_CreatePreambleOnFirstParse: CXTranslationUnit_Flags get() = 256 + +val CXTranslationUnit_KeepGoing: CXTranslationUnit_Flags get() = 512 + +val CXTranslationUnit_SingleFileParse: CXTranslationUnit_Flags get() = 1024 + +val CXTranslationUnit_LimitSkipFunctionBodiesToPreamble: CXTranslationUnit_Flags get() = 2048 + +val CXTranslationUnit_IncludeAttributedTypes: CXTranslationUnit_Flags get() = 4096 + +val CXTranslationUnit_VisitImplicitAttributes: CXTranslationUnit_Flags get() = 8192 + +typealias CXTranslationUnit_FlagsVar = IntVarOf + +typealias CXTranslationUnit_Flags = Int + + +val CXSaveTranslationUnit_None: CXSaveTranslationUnit_Flags get() = 0 + +typealias CXSaveTranslationUnit_FlagsVar = IntVarOf + +typealias CXSaveTranslationUnit_Flags = Int + + +val CXReparse_None: CXReparse_Flags get() = 0 + +typealias CXReparse_FlagsVar = IntVarOf + +typealias CXReparse_Flags = Int + + +val CXTLS_None: CXTLSKind get() = 0 + +val CXTLS_Dynamic: CXTLSKind get() = 1 + +val CXTLS_Static: CXTLSKind get() = 2 + +typealias CXTLSKindVar = IntVarOf + +typealias CXTLSKind = Int + + +val CXTypeNullability_NonNull: CXTypeNullabilityKind get() = 0 + +val CXTypeNullability_Nullable: CXTypeNullabilityKind get() = 1 + +val CXTypeNullability_Unspecified: CXTypeNullabilityKind get() = 2 + +val CXTypeNullability_Invalid: CXTypeNullabilityKind get() = 3 + +typealias CXTypeNullabilityKindVar = IntVarOf + +typealias CXTypeNullabilityKind = Int + + +val CXTypeLayoutError_Invalid: CXTypeLayoutError get() = -1 + +val CXTypeLayoutError_Incomplete: CXTypeLayoutError get() = -2 + +val CXTypeLayoutError_Dependent: CXTypeLayoutError get() = -3 + +val CXTypeLayoutError_NotConstantSize: CXTypeLayoutError get() = -4 + +val CXTypeLayoutError_InvalidFieldName: CXTypeLayoutError get() = -5 + +typealias CXTypeLayoutErrorVar = IntVarOf + +typealias CXTypeLayoutError = Int + + +val CXRefQualifier_None: CXRefQualifierKind get() = 0 + +val CXRefQualifier_LValue: CXRefQualifierKind get() = 1 + +val CXRefQualifier_RValue: CXRefQualifierKind get() = 2 + +typealias CXRefQualifierKindVar = IntVarOf + +typealias CXRefQualifierKind = Int + + +val CXPrintingPolicy_Indentation: CXPrintingPolicyProperty get() = 0 + +val CXPrintingPolicy_SuppressSpecifiers: CXPrintingPolicyProperty get() = 1 + +val CXPrintingPolicy_SuppressTagKeyword: CXPrintingPolicyProperty get() = 2 + +val CXPrintingPolicy_IncludeTagDefinition: CXPrintingPolicyProperty get() = 3 + +val CXPrintingPolicy_SuppressScope: CXPrintingPolicyProperty get() = 4 + +val CXPrintingPolicy_SuppressUnwrittenScope: CXPrintingPolicyProperty get() = 5 + +val CXPrintingPolicy_SuppressInitializers: CXPrintingPolicyProperty get() = 6 + +val CXPrintingPolicy_ConstantArraySizeAsWritten: CXPrintingPolicyProperty get() = 7 + +val CXPrintingPolicy_AnonymousTagLocations: CXPrintingPolicyProperty get() = 8 + +val CXPrintingPolicy_SuppressStrongLifetime: CXPrintingPolicyProperty get() = 9 + +val CXPrintingPolicy_SuppressLifetimeQualifiers: CXPrintingPolicyProperty get() = 10 + +val CXPrintingPolicy_SuppressTemplateArgsInCXXConstructors: CXPrintingPolicyProperty get() = 11 + +val CXPrintingPolicy_Bool: CXPrintingPolicyProperty get() = 12 + +val CXPrintingPolicy_Restrict: CXPrintingPolicyProperty get() = 13 + +val CXPrintingPolicy_Alignof: CXPrintingPolicyProperty get() = 14 + +val CXPrintingPolicy_UnderscoreAlignof: CXPrintingPolicyProperty get() = 15 + +val CXPrintingPolicy_UseVoidForZeroParams: CXPrintingPolicyProperty get() = 16 + +val CXPrintingPolicy_TerseOutput: CXPrintingPolicyProperty get() = 17 + +val CXPrintingPolicy_PolishForDeclaration: CXPrintingPolicyProperty get() = 18 + +val CXPrintingPolicy_Half: CXPrintingPolicyProperty get() = 19 + +val CXPrintingPolicy_MSWChar: CXPrintingPolicyProperty get() = 20 + +val CXPrintingPolicy_IncludeNewlines: CXPrintingPolicyProperty get() = 21 + +val CXPrintingPolicy_MSVCFormatting: CXPrintingPolicyProperty get() = 22 + +val CXPrintingPolicy_ConstantsAsWritten: CXPrintingPolicyProperty get() = 23 + +val CXPrintingPolicy_SuppressImplicitBase: CXPrintingPolicyProperty get() = 24 + +val CXPrintingPolicy_FullyQualifiedName: CXPrintingPolicyProperty get() = 25 + +val CXPrintingPolicy_LastProperty: CXPrintingPolicyProperty get() = 25 + +typealias CXPrintingPolicyPropertyVar = IntVarOf + +typealias CXPrintingPolicyProperty = Int + + +val CXObjCPropertyAttr_noattr: CXObjCPropertyAttrKind get() = 0 + +val CXObjCPropertyAttr_readonly: CXObjCPropertyAttrKind get() = 1 + +val CXObjCPropertyAttr_getter: CXObjCPropertyAttrKind get() = 2 + +val CXObjCPropertyAttr_assign: CXObjCPropertyAttrKind get() = 4 + +val CXObjCPropertyAttr_readwrite: CXObjCPropertyAttrKind get() = 8 + +val CXObjCPropertyAttr_retain: CXObjCPropertyAttrKind get() = 16 + +val CXObjCPropertyAttr_copy: CXObjCPropertyAttrKind get() = 32 + +val CXObjCPropertyAttr_nonatomic: CXObjCPropertyAttrKind get() = 64 + +val CXObjCPropertyAttr_setter: CXObjCPropertyAttrKind get() = 128 + +val CXObjCPropertyAttr_atomic: CXObjCPropertyAttrKind get() = 256 + +val CXObjCPropertyAttr_weak: CXObjCPropertyAttrKind get() = 512 + +val CXObjCPropertyAttr_strong: CXObjCPropertyAttrKind get() = 1024 + +val CXObjCPropertyAttr_unsafe_unretained: CXObjCPropertyAttrKind get() = 2048 + +val CXObjCPropertyAttr_class: CXObjCPropertyAttrKind get() = 4096 + +typealias CXObjCPropertyAttrKindVar = IntVarOf + +typealias CXObjCPropertyAttrKind = Int + + +val CXObjCDeclQualifier_None: CXObjCDeclQualifierKind get() = 0 + +val CXObjCDeclQualifier_In: CXObjCDeclQualifierKind get() = 1 + +val CXObjCDeclQualifier_Inout: CXObjCDeclQualifierKind get() = 2 + +val CXObjCDeclQualifier_Out: CXObjCDeclQualifierKind get() = 4 + +val CXObjCDeclQualifier_Bycopy: CXObjCDeclQualifierKind get() = 8 + +val CXObjCDeclQualifier_Byref: CXObjCDeclQualifierKind get() = 16 + +val CXObjCDeclQualifier_Oneway: CXObjCDeclQualifierKind get() = 32 + +typealias CXObjCDeclQualifierKindVar = IntVarOf + +typealias CXObjCDeclQualifierKind = Int + + +val CXNameRange_WantQualifier: CXNameRefFlags get() = 1 + +val CXNameRange_WantTemplateArgs: CXNameRefFlags get() = 2 + +val CXNameRange_WantSinglePiece: CXNameRefFlags get() = 4 + +typealias CXNameRefFlagsVar = IntVarOf + +typealias CXNameRefFlags = Int + + +val CXCodeComplete_IncludeMacros: CXCodeComplete_Flags get() = 1 + +val CXCodeComplete_IncludeCodePatterns: CXCodeComplete_Flags get() = 2 + +val CXCodeComplete_IncludeBriefComments: CXCodeComplete_Flags get() = 4 + +val CXCodeComplete_SkipPreamble: CXCodeComplete_Flags get() = 8 + +val CXCodeComplete_IncludeCompletionsWithFixIts: CXCodeComplete_Flags get() = 16 + +typealias CXCodeComplete_FlagsVar = IntVarOf + +typealias CXCodeComplete_Flags = Int + + +val CXCompletionContext_Unexposed: CXCompletionContext get() = 0 + +val CXCompletionContext_AnyType: CXCompletionContext get() = 1 + +val CXCompletionContext_AnyValue: CXCompletionContext get() = 2 + +val CXCompletionContext_ObjCObjectValue: CXCompletionContext get() = 4 + +val CXCompletionContext_ObjCSelectorValue: CXCompletionContext get() = 8 + +val CXCompletionContext_CXXClassTypeValue: CXCompletionContext get() = 16 + +val CXCompletionContext_DotMemberAccess: CXCompletionContext get() = 32 + +val CXCompletionContext_ArrowMemberAccess: CXCompletionContext get() = 64 + +val CXCompletionContext_ObjCPropertyAccess: CXCompletionContext get() = 128 + +val CXCompletionContext_EnumTag: CXCompletionContext get() = 256 + +val CXCompletionContext_UnionTag: CXCompletionContext get() = 512 + +val CXCompletionContext_StructTag: CXCompletionContext get() = 1024 + +val CXCompletionContext_ClassTag: CXCompletionContext get() = 2048 + +val CXCompletionContext_Namespace: CXCompletionContext get() = 4096 + +val CXCompletionContext_NestedNameSpecifier: CXCompletionContext get() = 8192 + +val CXCompletionContext_ObjCInterface: CXCompletionContext get() = 16384 + +val CXCompletionContext_ObjCProtocol: CXCompletionContext get() = 32768 + +val CXCompletionContext_ObjCCategory: CXCompletionContext get() = 65536 + +val CXCompletionContext_ObjCInstanceMessage: CXCompletionContext get() = 131072 + +val CXCompletionContext_ObjCClassMessage: CXCompletionContext get() = 262144 + +val CXCompletionContext_ObjCSelectorName: CXCompletionContext get() = 524288 + +val CXCompletionContext_MacroName: CXCompletionContext get() = 1048576 + +val CXCompletionContext_NaturalLanguage: CXCompletionContext get() = 2097152 + +val CXCompletionContext_IncludedFile: CXCompletionContext get() = 4194304 + +val CXCompletionContext_Unknown: CXCompletionContext get() = 8388607 + +typealias CXCompletionContextVar = IntVarOf + +typealias CXCompletionContext = Int + + +val CXIdxEntityLang_None: CXIdxEntityLanguage get() = 0 + +val CXIdxEntityLang_C: CXIdxEntityLanguage get() = 1 + +val CXIdxEntityLang_ObjC: CXIdxEntityLanguage get() = 2 + +val CXIdxEntityLang_CXX: CXIdxEntityLanguage get() = 3 + +val CXIdxEntityLang_Swift: CXIdxEntityLanguage get() = 4 + +typealias CXIdxEntityLanguageVar = IntVarOf + +typealias CXIdxEntityLanguage = Int + + +val CXIdxEntity_NonTemplate: CXIdxEntityCXXTemplateKind get() = 0 + +val CXIdxEntity_Template: CXIdxEntityCXXTemplateKind get() = 1 + +val CXIdxEntity_TemplatePartialSpecialization: CXIdxEntityCXXTemplateKind get() = 2 + +val CXIdxEntity_TemplateSpecialization: CXIdxEntityCXXTemplateKind get() = 3 + +typealias CXIdxEntityCXXTemplateKindVar = IntVarOf + +typealias CXIdxEntityCXXTemplateKind = Int + + +val CXIdxAttr_Unexposed: CXIdxAttrKind get() = 0 + +val CXIdxAttr_IBAction: CXIdxAttrKind get() = 1 + +val CXIdxAttr_IBOutlet: CXIdxAttrKind get() = 2 + +val CXIdxAttr_IBOutletCollection: CXIdxAttrKind get() = 3 + +typealias CXIdxAttrKindVar = IntVarOf + +typealias CXIdxAttrKind = Int + + +val CXIdxDeclFlag_Skipped: CXIdxDeclInfoFlags get() = 1 + +typealias CXIdxDeclInfoFlagsVar = IntVarOf + +typealias CXIdxDeclInfoFlags = Int + + +val CXIdxObjCContainer_ForwardRef: CXIdxObjCContainerKind get() = 0 + +val CXIdxObjCContainer_Interface: CXIdxObjCContainerKind get() = 1 + +val CXIdxObjCContainer_Implementation: CXIdxObjCContainerKind get() = 2 + +typealias CXIdxObjCContainerKindVar = IntVarOf + +typealias CXIdxObjCContainerKind = Int + + +val CXIdxEntityRef_Direct: CXIdxEntityRefKind get() = 1 + +val CXIdxEntityRef_Implicit: CXIdxEntityRefKind get() = 2 + +typealias CXIdxEntityRefKindVar = IntVarOf + +typealias CXIdxEntityRefKind = Int + + +val CXSymbolRole_None: CXSymbolRole get() = 0 + +val CXSymbolRole_Declaration: CXSymbolRole get() = 1 + +val CXSymbolRole_Definition: CXSymbolRole get() = 2 + +val CXSymbolRole_Reference: CXSymbolRole get() = 4 + +val CXSymbolRole_Read: CXSymbolRole get() = 8 + +val CXSymbolRole_Write: CXSymbolRole get() = 16 + +val CXSymbolRole_Call: CXSymbolRole get() = 32 + +val CXSymbolRole_Dynamic: CXSymbolRole get() = 64 + +val CXSymbolRole_AddressOf: CXSymbolRole get() = 128 + +val CXSymbolRole_Implicit: CXSymbolRole get() = 256 + +typealias CXSymbolRoleVar = IntVarOf + +typealias CXSymbolRole = Int + + +val CXIndexOpt_None: CXIndexOptFlags get() = 0 + +val CXIndexOpt_SuppressRedundantRefs: CXIndexOptFlags get() = 1 + +val CXIndexOpt_IndexFunctionLocalSymbols: CXIndexOptFlags get() = 2 + +val CXIndexOpt_IndexImplicitTemplateInstantiations: CXIndexOptFlags get() = 4 + +val CXIndexOpt_SuppressWarnings: CXIndexOptFlags get() = 8 + +val CXIndexOpt_SkipParsedBodiesInSession: CXIndexOptFlags get() = 16 + +typealias CXIndexOptFlagsVar = IntVarOf + +typealias CXIndexOptFlags = Int +private external fun kniBridge0(p0: NativePtr): NativePtr +private external fun kniBridge1(p0: NativePtr): Unit +private external fun kniBridge2(p0: NativePtr): Unit +private external fun kniBridge3(): Long +private external fun kniBridge4(p0: Int): NativePtr +private external fun kniBridge5(p0: NativePtr, p1: NativePtr, p2: NativePtr): Int +private external fun kniBridge6(p0: NativePtr, p1: Int): Int +private external fun kniBridge7(p0: NativePtr, p1: Int, p2: NativePtr, p3: NativePtr): Int +private external fun kniBridge8(p0: NativePtr): Unit +private external fun kniBridge9(p0: NativePtr): Unit +private external fun kniBridge10(p0: Int): NativePtr +private external fun kniBridge11(p0: NativePtr, p1: NativePtr): Int +private external fun kniBridge12(p0: NativePtr, p1: NativePtr): Int +private external fun kniBridge13(p0: NativePtr, p1: Int, p2: NativePtr, p3: NativePtr): Int +private external fun kniBridge14(p0: NativePtr): Unit +private external fun kniBridge15(p0: Int, p1: Int): NativePtr +private external fun kniBridge16(p0: NativePtr): Unit +private external fun kniBridge17(p0: NativePtr, p1: Int): Unit +private external fun kniBridge18(p0: NativePtr): Int +private external fun kniBridge19(p0: NativePtr, p1: NativePtr): Unit +private external fun kniBridge20(p0: NativePtr, p1: NativePtr): Unit +private external fun kniBridge21(p0: NativePtr): Long +private external fun kniBridge22(p0: NativePtr, p1: NativePtr): Int +private external fun kniBridge23(p0: NativePtr, p1: NativePtr): Int +private external fun kniBridge24(p0: NativePtr, p1: NativePtr): NativePtr +private external fun kniBridge25(p0: NativePtr, p1: NativePtr, p2: NativePtr): NativePtr +private external fun kniBridge26(p0: NativePtr, p1: NativePtr): Int +private external fun kniBridge27(p0: NativePtr, p1: NativePtr): Unit +private external fun kniBridge28(p0: NativePtr): Unit +private external fun kniBridge29(p0: NativePtr, p1: NativePtr): Int +private external fun kniBridge30(p0: NativePtr, p1: NativePtr, p2: Int, p3: Int, p4: NativePtr): Unit +private external fun kniBridge31(p0: NativePtr, p1: NativePtr, p2: Int, p3: NativePtr): Unit +private external fun kniBridge32(p0: NativePtr): Int +private external fun kniBridge33(p0: NativePtr): Int +private external fun kniBridge34(p0: NativePtr): Unit +private external fun kniBridge35(p0: NativePtr, p1: NativePtr, p2: NativePtr): Unit +private external fun kniBridge36(p0: NativePtr, p1: NativePtr): Int +private external fun kniBridge37(p0: NativePtr): Int +private external fun kniBridge38(p0: NativePtr, p1: NativePtr, p2: NativePtr, p3: NativePtr, p4: NativePtr): Unit +private external fun kniBridge39(p0: NativePtr, p1: NativePtr, p2: NativePtr, p3: NativePtr): Unit +private external fun kniBridge40(p0: NativePtr, p1: NativePtr, p2: NativePtr, p3: NativePtr, p4: NativePtr): Unit +private external fun kniBridge41(p0: NativePtr, p1: NativePtr, p2: NativePtr, p3: NativePtr, p4: NativePtr): Unit +private external fun kniBridge42(p0: NativePtr, p1: NativePtr, p2: NativePtr, p3: NativePtr, p4: NativePtr): Unit +private external fun kniBridge43(p0: NativePtr, p1: NativePtr): Unit +private external fun kniBridge44(p0: NativePtr, p1: NativePtr): Unit +private external fun kniBridge45(p0: NativePtr, p1: NativePtr): NativePtr +private external fun kniBridge46(p0: NativePtr): NativePtr +private external fun kniBridge47(p0: NativePtr): Unit +private external fun kniBridge48(p0: NativePtr): Int +private external fun kniBridge49(p0: NativePtr, p1: Int): NativePtr +private external fun kniBridge50(p0: NativePtr, p1: NativePtr, p2: NativePtr): NativePtr +private external fun kniBridge51(p0: NativePtr): Unit +private external fun kniBridge52(p0: NativePtr): NativePtr +private external fun kniBridge53(p0: NativePtr): Int +private external fun kniBridge54(p0: NativePtr, p1: Int): NativePtr +private external fun kniBridge55(p0: NativePtr): NativePtr +private external fun kniBridge56(p0: NativePtr): Unit +private external fun kniBridge57(p0: NativePtr, p1: Int, p2: NativePtr): Unit +private external fun kniBridge58(): Int +private external fun kniBridge59(p0: NativePtr): Int +private external fun kniBridge60(p0: NativePtr, p1: NativePtr): Unit +private external fun kniBridge61(p0: NativePtr, p1: NativePtr): Unit +private external fun kniBridge62(p0: NativePtr, p1: NativePtr, p2: NativePtr): Unit +private external fun kniBridge63(p0: NativePtr): Int +private external fun kniBridge64(p0: Int, p1: NativePtr): Unit +private external fun kniBridge65(p0: NativePtr, p1: NativePtr): Unit +private external fun kniBridge66(p0: NativePtr): Int +private external fun kniBridge67(p0: NativePtr, p1: Int, p2: NativePtr): Unit +private external fun kniBridge68(p0: NativePtr): Int +private external fun kniBridge69(p0: NativePtr, p1: Int, p2: NativePtr, p3: NativePtr): Unit +private external fun kniBridge70(p0: NativePtr, p1: NativePtr): Unit +private external fun kniBridge71(p0: NativePtr, p1: NativePtr, p2: Int, p3: NativePtr, p4: Int, p5: NativePtr): NativePtr +private external fun kniBridge72(p0: NativePtr, p1: NativePtr): NativePtr +private external fun kniBridge73(p0: NativePtr, p1: NativePtr, p2: NativePtr): Int +private external fun kniBridge74(): Int +private external fun kniBridge75(p0: NativePtr, p1: NativePtr, p2: NativePtr, p3: Int, p4: NativePtr, p5: Int, p6: Int): NativePtr +private external fun kniBridge76(p0: NativePtr, p1: NativePtr, p2: NativePtr, p3: Int, p4: NativePtr, p5: Int, p6: Int, p7: NativePtr): Int +private external fun kniBridge77(p0: NativePtr, p1: NativePtr, p2: NativePtr, p3: Int, p4: NativePtr, p5: Int, p6: Int, p7: NativePtr): Int +private external fun kniBridge78(p0: NativePtr): Int +private external fun kniBridge79(p0: NativePtr, p1: NativePtr, p2: Int): Int +private external fun kniBridge80(p0: NativePtr): Int +private external fun kniBridge81(p0: NativePtr): Unit +private external fun kniBridge82(p0: NativePtr): Int +private external fun kniBridge83(p0: NativePtr, p1: Int, p2: NativePtr, p3: Int): Int +private external fun kniBridge84(p0: Int): NativePtr +private external fun kniBridge85(p0: NativePtr, p1: NativePtr): Unit +private external fun kniBridge86(p0: NativePtr): Unit +private external fun kniBridge87(p0: NativePtr): NativePtr +private external fun kniBridge88(p0: NativePtr): Unit +private external fun kniBridge89(p0: NativePtr, p1: NativePtr): Unit +private external fun kniBridge90(p0: NativePtr): Int +private external fun kniBridge91(p0: NativePtr): Unit +private external fun kniBridge92(p0: NativePtr, p1: NativePtr): Unit +private external fun kniBridge93(p0: NativePtr, p1: NativePtr): Int +private external fun kniBridge94(p0: NativePtr): Int +private external fun kniBridge95(p0: NativePtr): Int +private external fun kniBridge96(p0: NativePtr): Int +private external fun kniBridge97(p0: Int): Int +private external fun kniBridge98(p0: NativePtr): Int +private external fun kniBridge99(p0: Int): Int +private external fun kniBridge100(p0: Int): Int +private external fun kniBridge101(p0: Int): Int +private external fun kniBridge102(p0: Int): Int +private external fun kniBridge103(p0: NativePtr): Int +private external fun kniBridge104(p0: Int): Int +private external fun kniBridge105(p0: Int): Int +private external fun kniBridge106(p0: Int): Int +private external fun kniBridge107(p0: Int): Int +private external fun kniBridge108(p0: NativePtr): Int +private external fun kniBridge109(p0: NativePtr): Int +private external fun kniBridge110(p0: NativePtr): Int +private external fun kniBridge111(p0: NativePtr, p1: NativePtr, p2: NativePtr, p3: NativePtr, p4: NativePtr, p5: NativePtr, p6: Int): Int +private external fun kniBridge112(p0: NativePtr): Unit +private external fun kniBridge113(p0: NativePtr): Int +private external fun kniBridge114(p0: NativePtr): Int +private external fun kniBridge115(p0: NativePtr): NativePtr +private external fun kniBridge116(): NativePtr +private external fun kniBridge117(p0: NativePtr): Unit +private external fun kniBridge118(p0: NativePtr, p1: NativePtr): Int +private external fun kniBridge119(p0: NativePtr, p1: NativePtr): Int +private external fun kniBridge120(p0: NativePtr, p1: NativePtr): Unit +private external fun kniBridge121(p0: NativePtr, p1: NativePtr): Unit +private external fun kniBridge122(p0: NativePtr, p1: NativePtr, p2: NativePtr): Unit +private external fun kniBridge123(p0: NativePtr): Unit +private external fun kniBridge124(p0: NativePtr): NativePtr +private external fun kniBridge125(p0: NativePtr, p1: NativePtr, p2: NativePtr): Unit +private external fun kniBridge126(p0: NativePtr, p1: NativePtr): Unit +private external fun kniBridge127(p0: NativePtr, p1: NativePtr): Unit +private external fun kniBridge128(p0: NativePtr, p1: NativePtr): Unit +private external fun kniBridge129(p0: NativePtr, p1: NativePtr): Unit +private external fun kniBridge130(p0: NativePtr, p1: NativePtr): Unit +private external fun kniBridge131(p0: NativePtr, p1: NativePtr): Unit +private external fun kniBridge132(p0: NativePtr): Long +private external fun kniBridge133(p0: NativePtr): Long +private external fun kniBridge134(p0: NativePtr): Int +private external fun kniBridge135(p0: NativePtr): Int +private external fun kniBridge136(p0: NativePtr, p1: Int, p2: NativePtr): Unit +private external fun kniBridge137(p0: NativePtr): Int +private external fun kniBridge138(p0: NativePtr, p1: Int): Int +private external fun kniBridge139(p0: NativePtr, p1: Int, p2: NativePtr): Unit +private external fun kniBridge140(p0: NativePtr, p1: Int): Long +private external fun kniBridge141(p0: NativePtr, p1: Int): Long +private external fun kniBridge142(p0: NativePtr, p1: NativePtr): Int +private external fun kniBridge143(p0: NativePtr, p1: NativePtr): Unit +private external fun kniBridge144(p0: NativePtr): Int +private external fun kniBridge145(p0: NativePtr): Int +private external fun kniBridge146(p0: NativePtr): Int +private external fun kniBridge147(p0: NativePtr): Int +private external fun kniBridge148(p0: NativePtr): Int +private external fun kniBridge149(p0: NativePtr): Int +private external fun kniBridge150(p0: NativePtr): Int +private external fun kniBridge151(p0: NativePtr, p1: NativePtr): Unit +private external fun kniBridge152(p0: NativePtr, p1: NativePtr): Unit +private external fun kniBridge153(p0: NativePtr, p1: NativePtr): Unit +private external fun kniBridge154(p0: NativePtr, p1: NativePtr): Unit +private external fun kniBridge155(p0: NativePtr, p1: NativePtr): Unit +private external fun kniBridge156(p0: Int, p1: NativePtr): Unit +private external fun kniBridge157(p0: NativePtr): Int +private external fun kniBridge158(p0: NativePtr, p1: NativePtr): Unit +private external fun kniBridge159(p0: NativePtr): Int +private external fun kniBridge160(p0: NativePtr): Int +private external fun kniBridge161(p0: NativePtr, p1: Int, p2: NativePtr): Unit +private external fun kniBridge162(p0: NativePtr, p1: NativePtr): Unit +private external fun kniBridge163(p0: NativePtr): Int +private external fun kniBridge164(p0: NativePtr, p1: Int, p2: NativePtr): Unit +private external fun kniBridge165(p0: NativePtr): Int +private external fun kniBridge166(p0: NativePtr, p1: Int, p2: NativePtr): Unit +private external fun kniBridge167(p0: NativePtr): Int +private external fun kniBridge168(p0: NativePtr, p1: NativePtr): Unit +private external fun kniBridge169(p0: NativePtr): Int +private external fun kniBridge170(p0: NativePtr): Int +private external fun kniBridge171(p0: NativePtr, p1: NativePtr): Unit +private external fun kniBridge172(p0: NativePtr): Long +private external fun kniBridge173(p0: NativePtr, p1: NativePtr): Unit +private external fun kniBridge174(p0: NativePtr): Long +private external fun kniBridge175(p0: NativePtr, p1: NativePtr): Unit +private external fun kniBridge176(p0: NativePtr): Int +private external fun kniBridge177(p0: NativePtr): Int +private external fun kniBridge178(p0: NativePtr): Long +private external fun kniBridge179(p0: NativePtr, p1: NativePtr): Unit +private external fun kniBridge180(p0: NativePtr): Long +private external fun kniBridge181(p0: NativePtr, p1: NativePtr): Long +private external fun kniBridge182(p0: NativePtr, p1: NativePtr): Unit +private external fun kniBridge183(p0: NativePtr): Long +private external fun kniBridge184(p0: NativePtr): Int +private external fun kniBridge185(p0: NativePtr): Int +private external fun kniBridge186(p0: NativePtr, p1: Int, p2: NativePtr): Unit +private external fun kniBridge187(p0: NativePtr): Int +private external fun kniBridge188(p0: NativePtr): Int +private external fun kniBridge189(p0: NativePtr): Int +private external fun kniBridge190(p0: NativePtr): Int +private external fun kniBridge191(p0: NativePtr): Int +private external fun kniBridge192(p0: NativePtr): Int +private external fun kniBridge193(p0: NativePtr, p1: Int, p2: NativePtr): Unit +private external fun kniBridge194(p0: NativePtr, p1: NativePtr): Unit +private external fun kniBridge195(p0: NativePtr, p1: NativePtr, p2: NativePtr): Int +private external fun kniBridge196(p0: NativePtr, p1: NativePtr): Unit +private external fun kniBridge197(p0: NativePtr, p1: NativePtr): Unit +private external fun kniBridge198(p0: NativePtr, p1: NativePtr, p2: NativePtr): Unit +private external fun kniBridge199(p0: NativePtr, p1: NativePtr): Unit +private external fun kniBridge200(p0: NativePtr, p1: NativePtr, p2: NativePtr): Unit +private external fun kniBridge201(p0: NativePtr, p1: Int, p2: NativePtr, p3: NativePtr): Unit +private external fun kniBridge202(p0: NativePtr, p1: NativePtr, p2: NativePtr): Unit +private external fun kniBridge203(p0: NativePtr, p1: NativePtr): Unit +private external fun kniBridge204(p0: NativePtr, p1: Int, p2: Int, p3: NativePtr): Unit +private external fun kniBridge205(p0: NativePtr, p1: Int): Int +private external fun kniBridge206(p0: NativePtr, p1: Int, p2: Int): Unit +private external fun kniBridge207(p0: NativePtr): NativePtr +private external fun kniBridge208(p0: NativePtr): Unit +private external fun kniBridge209(p0: NativePtr, p1: NativePtr, p2: NativePtr): Unit +private external fun kniBridge210(p0: NativePtr, p1: NativePtr): Unit +private external fun kniBridge211(p0: NativePtr, p1: NativePtr): Unit +private external fun kniBridge212(p0: NativePtr, p1: NativePtr): Unit +private external fun kniBridge213(p0: NativePtr): Int +private external fun kniBridge214(p0: NativePtr, p1: NativePtr): Unit +private external fun kniBridge215(p0: NativePtr): Int +private external fun kniBridge216(p0: NativePtr): Int +private external fun kniBridge217(p0: NativePtr, p1: NativePtr): Unit +private external fun kniBridge218(p0: NativePtr, p1: Int): Int +private external fun kniBridge219(p0: NativePtr, p1: NativePtr): Unit +private external fun kniBridge220(p0: NativePtr, p1: NativePtr): Unit +private external fun kniBridge221(p0: NativePtr): Int +private external fun kniBridge222(p0: NativePtr): Int +private external fun kniBridge223(p0: NativePtr): Int +private external fun kniBridge224(p0: NativePtr, p1: NativePtr, p2: NativePtr, p3: NativePtr): Int +private external fun kniBridge225(p0: NativePtr, p1: NativePtr): Unit +private external fun kniBridge226(p0: NativePtr, p1: NativePtr): Unit +private external fun kniBridge227(p0: NativePtr, p1: NativePtr): Unit +private external fun kniBridge228(p0: NativePtr, p1: NativePtr): Unit +private external fun kniBridge229(p0: NativePtr): NativePtr +private external fun kniBridge230(p0: NativePtr): NativePtr +private external fun kniBridge231(p0: NativePtr): NativePtr +private external fun kniBridge232(p0: NativePtr, p1: NativePtr): NativePtr +private external fun kniBridge233(p0: NativePtr): NativePtr +private external fun kniBridge234(p0: NativePtr): NativePtr +private external fun kniBridge235(p0: NativePtr, p1: NativePtr): Unit +private external fun kniBridge236(p0: NativePtr, p1: NativePtr): Unit +private external fun kniBridge237(p0: NativePtr): Int +private external fun kniBridge238(p0: NativePtr, p1: NativePtr): Int +private external fun kniBridge239(p0: NativePtr, p1: NativePtr, p2: Int): NativePtr +private external fun kniBridge240(p0: NativePtr): Int +private external fun kniBridge241(p0: NativePtr): Int +private external fun kniBridge242(p0: NativePtr): Int +private external fun kniBridge243(p0: NativePtr): Int +private external fun kniBridge244(p0: NativePtr): Int +private external fun kniBridge245(p0: NativePtr): Int +private external fun kniBridge246(p0: NativePtr): Int +private external fun kniBridge247(p0: NativePtr): Int +private external fun kniBridge248(p0: NativePtr): Int +private external fun kniBridge249(p0: NativePtr): Int +private external fun kniBridge250(p0: NativePtr): Int +private external fun kniBridge251(p0: NativePtr): Int +private external fun kniBridge252(p0: NativePtr): Int +private external fun kniBridge253(p0: NativePtr, p1: NativePtr): Unit +private external fun kniBridge254(p0: NativePtr, p1: Int, p2: Int, p3: NativePtr): Unit +private external fun kniBridge255(p0: NativePtr, p1: NativePtr): NativePtr +private external fun kniBridge256(p0: NativePtr): Int +private external fun kniBridge257(p0: NativePtr, p1: NativePtr, p2: NativePtr): Unit +private external fun kniBridge258(p0: NativePtr, p1: NativePtr, p2: NativePtr): Unit +private external fun kniBridge259(p0: NativePtr, p1: NativePtr, p2: NativePtr): Unit +private external fun kniBridge260(p0: NativePtr, p1: NativePtr, p2: NativePtr, p3: NativePtr): Unit +private external fun kniBridge261(p0: NativePtr, p1: NativePtr, p2: Int, p3: NativePtr): Unit +private external fun kniBridge262(p0: NativePtr, p1: NativePtr, p2: Int): Unit +private external fun kniBridge263(p0: Int, p1: NativePtr): Unit +private external fun kniBridge264(p0: NativePtr, p1: NativePtr, p2: NativePtr, p3: NativePtr, p4: NativePtr, p5: NativePtr, p6: NativePtr): Unit +private external fun kniBridge265(): Unit +private external fun kniBridge266(p0: NativePtr, p1: NativePtr, p2: Int): Unit +private external fun kniBridge267(p0: NativePtr, p1: Int): Int +private external fun kniBridge268(p0: NativePtr, p1: Int, p2: NativePtr): Unit +private external fun kniBridge269(p0: NativePtr, p1: Int): NativePtr +private external fun kniBridge270(p0: NativePtr): Int +private external fun kniBridge271(p0: NativePtr): Int +private external fun kniBridge272(p0: NativePtr): Int +private external fun kniBridge273(p0: NativePtr): Int +private external fun kniBridge274(p0: NativePtr, p1: Int, p2: NativePtr): Unit +private external fun kniBridge275(p0: NativePtr, p1: NativePtr, p2: NativePtr): Unit +private external fun kniBridge276(p0: NativePtr, p1: NativePtr): Unit +private external fun kniBridge277(p0: NativePtr): NativePtr +private external fun kniBridge278(p0: NativePtr, p1: Int): Int +private external fun kniBridge279(p0: NativePtr, p1: Int, p2: Int, p3: NativePtr, p4: NativePtr): Unit +private external fun kniBridge280(): Int +private external fun kniBridge281(p0: NativePtr, p1: NativePtr, p2: Int, p3: Int, p4: NativePtr, p5: Int, p6: Int): NativePtr +private external fun kniBridge282(p0: NativePtr, p1: Int): Unit +private external fun kniBridge283(p0: NativePtr): Unit +private external fun kniBridge284(p0: NativePtr): Int +private external fun kniBridge285(p0: NativePtr, p1: Int): NativePtr +private external fun kniBridge286(p0: NativePtr): Long +private external fun kniBridge287(p0: NativePtr, p1: NativePtr): Int +private external fun kniBridge288(p0: NativePtr, p1: NativePtr): Unit +private external fun kniBridge289(p0: NativePtr, p1: NativePtr): Unit +private external fun kniBridge290(p0: NativePtr): Unit +private external fun kniBridge291(p0: Int): Unit +private external fun kniBridge292(p0: NativePtr, p1: NativePtr, p2: NativePtr): Unit +private external fun kniBridge293(p0: NativePtr): NativePtr +private external fun kniBridge294(p0: NativePtr): Int +private external fun kniBridge295(p0: NativePtr): Int +private external fun kniBridge296(p0: NativePtr): Long +private external fun kniBridge297(p0: NativePtr): Int +private external fun kniBridge298(p0: NativePtr): Long +private external fun kniBridge299(p0: NativePtr): Double +private external fun kniBridge300(p0: NativePtr): NativePtr +private external fun kniBridge301(p0: NativePtr): Unit +private external fun kniBridge302(p0: NativePtr): NativePtr +private external fun kniBridge303(p0: NativePtr, p1: Int): NativePtr +private external fun kniBridge304(p0: NativePtr): Int +private external fun kniBridge305(p0: NativePtr, p1: Int, p2: NativePtr, p3: NativePtr): Unit +private external fun kniBridge306(p0: NativePtr): Unit +private external fun kniBridge307(p0: NativePtr, p1: NativePtr, p2: NativePtr): Int +private external fun kniBridge308(p0: NativePtr, p1: NativePtr, p2: NativePtr): Int +private external fun kniBridge309(p0: Int): Int +private external fun kniBridge310(p0: NativePtr): NativePtr +private external fun kniBridge311(p0: NativePtr): NativePtr +private external fun kniBridge312(p0: NativePtr): NativePtr +private external fun kniBridge313(p0: NativePtr): NativePtr +private external fun kniBridge314(p0: NativePtr): NativePtr +private external fun kniBridge315(p0: NativePtr): NativePtr +private external fun kniBridge316(p0: NativePtr): NativePtr +private external fun kniBridge317(p0: NativePtr): NativePtr +private external fun kniBridge318(p0: NativePtr, p1: NativePtr): Unit +private external fun kniBridge319(p0: NativePtr): NativePtr +private external fun kniBridge320(p0: NativePtr, p1: NativePtr): Unit +private external fun kniBridge321(p0: NativePtr): NativePtr +private external fun kniBridge322(p0: NativePtr): Unit +private external fun kniBridge323(p0: NativePtr, p1: NativePtr, p2: NativePtr, p3: Int, p4: Int, p5: NativePtr, p6: NativePtr, p7: Int, p8: NativePtr, p9: Int, p10: NativePtr, p11: Int): Int +private external fun kniBridge324(p0: NativePtr, p1: NativePtr, p2: NativePtr, p3: Int, p4: Int, p5: NativePtr, p6: NativePtr, p7: Int, p8: NativePtr, p9: Int, p10: NativePtr, p11: Int): Int +private external fun kniBridge325(p0: NativePtr, p1: NativePtr, p2: NativePtr, p3: Int, p4: Int, p5: NativePtr): Int +private external fun kniBridge326(p0: NativePtr, p1: NativePtr, p2: NativePtr, p3: NativePtr, p4: NativePtr, p5: NativePtr): Unit +private external fun kniBridge327(p0: NativePtr, p1: NativePtr): Unit +private external fun kniBridge328(p0: NativePtr, p1: NativePtr, p2: NativePtr): Int +private external fun kniBridge329(p0: NativePtr): NativePtr +private external fun kniBridge330(p0: NativePtr, p1: NativePtr): Unit +private external fun kniBridge331(p0: NativePtr, p1: NativePtr): Unit +private external fun kniBridge332(p0: NativePtr, p1: NativePtr): Unit +private external fun kniBridge333(p0: NativePtr, p1: NativePtr): Int +private external fun kniBridge334(p0: NativePtr): Int +private external fun kniBridge335(p0: NativePtr, p1: Int, p2: NativePtr): Unit +private external fun kniBridge336(p0: NativePtr): Int +private external fun kniBridge337(p0: NativePtr): Int +private external fun kniBridge338(p0: NativePtr): Int +private external fun kniBridge339(p0: NativePtr): Int +private val loadLibrary = loadKonanLibrary("clangstubs") diff --git a/kotlin-native/Interop/Indexer/src/main/kotlin/org/jetbrains/kotlin/native/interop/indexer/HeaderToIdMapper.kt b/kotlin-native/Interop/Indexer/src/main/kotlin/org/jetbrains/kotlin/native/interop/indexer/HeaderToIdMapper.kt new file mode 100644 index 00000000000..ec33ec9dc08 --- /dev/null +++ b/kotlin-native/Interop/Indexer/src/main/kotlin/org/jetbrains/kotlin/native/interop/indexer/HeaderToIdMapper.kt @@ -0,0 +1,35 @@ +/* + * Copyright 2010-2017 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.jetbrains.kotlin.native.interop.indexer + +import java.io.File + +class HeaderToIdMapper(sysRoot: String) { + private val headerPathToId = mutableMapOf() + private val sysRoot = File(sysRoot).canonicalFile.toPath() + + internal fun getHeaderId(filePath: String) = headerPathToId.getOrPut(filePath) { + val path = File(filePath).canonicalFile.toPath() + val headerIdValue = if (path.startsWith(sysRoot)) { + val relative = sysRoot.relativize(path) + relative.toString() + } else { + headerContentsHash(filePath) + } + HeaderId(headerIdValue) + } +} diff --git a/kotlin-native/Interop/Indexer/src/main/kotlin/org/jetbrains/kotlin/native/interop/indexer/Indexer.kt b/kotlin-native/Interop/Indexer/src/main/kotlin/org/jetbrains/kotlin/native/interop/indexer/Indexer.kt new file mode 100644 index 00000000000..6171596b049 --- /dev/null +++ b/kotlin-native/Interop/Indexer/src/main/kotlin/org/jetbrains/kotlin/native/interop/indexer/Indexer.kt @@ -0,0 +1,1046 @@ +/* + * Copyright 2010-2017 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.jetbrains.kotlin.native.interop.indexer + +import clang.* +import clang.CXIdxEntityKind.* +import clang.CXTypeKind.* +import kotlinx.cinterop.* + +private class StructDeclImpl(spelling: String, override val location: Location) : StructDecl(spelling) { + override var def: StructDefImpl? = null +} + +private class StructDefImpl( + size: Long, align: Int, decl: StructDecl, + override val kind: Kind +) : StructDef( + size, align, decl +) { + override val members = mutableListOf() +} + +private class EnumDefImpl(spelling: String, type: Type, override val location: Location) : EnumDef(spelling, type) { + override val constants = mutableListOf() +} + +private interface ObjCContainerImpl { + val protocols: MutableList + val methods: MutableList + val properties: MutableList +} + +private class ObjCProtocolImpl( + name: String, + override val location: Location, + override val isForwardDeclaration: Boolean +) : ObjCProtocol(name), ObjCContainerImpl { + override val protocols = mutableListOf() + override val methods = mutableListOf() + override val properties = mutableListOf() +} + +private class ObjCClassImpl( + name: String, + override val location: Location, + override val isForwardDeclaration: Boolean, + override val binaryName: String? +) : ObjCClass(name), ObjCContainerImpl { + override val protocols = mutableListOf() + override val methods = mutableListOf() + override val properties = mutableListOf() + override var baseClass: ObjCClass? = null +} + +private class ObjCCategoryImpl( + name: String, clazz: ObjCClass +) : ObjCCategory(name, clazz), ObjCContainerImpl { + override val protocols = mutableListOf() + override val methods = mutableListOf() + override val properties = mutableListOf() +} + +internal class NativeIndexImpl(val library: NativeLibrary, val verbose: Boolean = false) : NativeIndex() { + + private sealed class DeclarationID { + data class USR(val usr: String) : DeclarationID() + object VaList : DeclarationID() + object VaListTag : DeclarationID() + object BuiltinVaList : DeclarationID() + object Protocol : DeclarationID() + } + + private inner class TypeDeclarationRegistry { + private val all = mutableMapOf() + + val included = mutableListOf() + + inline fun getOrPut(cursor: CValue, create: () -> D) = getOrPut(cursor, create, configure = {}) + + inline fun getOrPut(cursor: CValue, create: () -> D, configure: (D) -> Unit): D { + val key = getDeclarationId(cursor) + return all.getOrElse(key) { + + val value = create() + all[key] = value + + val headerId = getHeaderId(getContainingFile(cursor)) + if (!library.headerExclusionPolicy.excludeAll(headerId)) { + // This declaration is used, and thus should be included: + included.add(value) + } + + configure(value) + value + } + } + + } + + internal fun getHeaderId(file: CXFile?): HeaderId = getHeaderId(this.library, file) + + private fun getLocation(cursor: CValue): Location { + val headerId = getHeaderId(getContainingFile(cursor)) + return Location(headerId) + } + + override val structs: List get() = structRegistry.included + private val structRegistry = TypeDeclarationRegistry() + + override val enums: List get() = enumRegistry.included + private val enumRegistry = TypeDeclarationRegistry() + + override val objCClasses: List get() = objCClassRegistry.included + private val objCClassRegistry = TypeDeclarationRegistry() + + override val objCProtocols: List get() = objCProtocolRegistry.included + private val objCProtocolRegistry = TypeDeclarationRegistry() + + override val objCCategories: Collection get() = objCCategoryById.values + private val objCCategoryById = mutableMapOf() + + override val typedefs get() = typedefRegistry.included + private val typedefRegistry = TypeDeclarationRegistry() + + private val functionById = mutableMapOf() + + override val functions: Collection + get() = functionById.values + + override val macroConstants = mutableListOf() + override val wrappedMacros = mutableListOf() + + private val globalById = mutableMapOf() + + override val globals: Collection + get() = globalById.values + + override lateinit var includedHeaders: List + + private fun log(message: String) { + if (verbose) { + println(message) + } + } + + private fun getDeclarationId(cursor: CValue): DeclarationID { + val usr = clang_getCursorUSR(cursor).convertAndDispose() + if (usr == "") { + val kind = cursor.kind + val spelling = getCursorSpelling(cursor) + return when (kind to spelling) { + CXCursorKind.CXCursor_StructDecl to "__va_list_tag" -> DeclarationID.VaListTag + CXCursorKind.CXCursor_StructDecl to "__va_list" -> DeclarationID.VaList + CXCursorKind.CXCursor_TypedefDecl to "__builtin_va_list" -> DeclarationID.BuiltinVaList + CXCursorKind.CXCursor_ObjCInterfaceDecl to "Protocol" -> DeclarationID.Protocol + else -> error(kind to spelling) + } + } + + return DeclarationID.USR(usr) + } + + private fun getStructDeclAt( + cursor: CValue + ): StructDeclImpl = structRegistry.getOrPut(cursor, { createStructDecl(cursor) }) { decl -> + val definitionCursor = clang_getCursorDefinition(cursor) + if (clang_Cursor_isNull(definitionCursor) == 0) { + assert(clang_isCursorDefinition(definitionCursor) != 0) + createStructDef(decl, cursor) + } + } + + private fun createStructDecl(cursor: CValue): StructDeclImpl { + val cursorType = clang_getCursorType(cursor) + val typeSpelling = clang_getTypeSpelling(cursorType).convertAndDispose() + + return StructDeclImpl(typeSpelling, getLocation(cursor)) + } + + private fun createStructDef(structDecl: StructDeclImpl, cursor: CValue) { + val type = clang_getCursorType(cursor) + + val fields = mutableListOf() + addDeclaredFields(fields, type, type) + + val size = clang_Type_getSizeOf(type) + val align = clang_Type_getAlignOf(type).toInt() + + val structDef = StructDefImpl( + size, align, structDecl, + when (cursor.kind) { + CXCursorKind.CXCursor_UnionDecl -> StructDef.Kind.UNION + CXCursorKind.CXCursor_StructDecl -> StructDef.Kind.STRUCT + else -> error(cursor.kind) + } + ) + + structDef.members += fields + + structDecl.def = structDef + } + + private fun addDeclaredFields(result: MutableList, structType: CValue, containerType: CValue) { + getFields(containerType).forEach { fieldCursor -> + val name = getCursorSpelling(fieldCursor) + if (name.isNotEmpty()) { + val fieldType = convertCursorType(fieldCursor) + val offset = clang_Type_getOffsetOf(structType, name) + val member = if (offset < 0) { + IncompleteField(name, fieldType) + } else if (clang_Cursor_isBitField(fieldCursor) == 0) { + val canonicalFieldType = clang_getCanonicalType(clang_getCursorType(fieldCursor)) + Field( + name, + fieldType, + offset, + clang_Type_getSizeOf(canonicalFieldType), + clang_Type_getAlignOf(canonicalFieldType) + ) + } else { + val size = clang_getFieldDeclBitWidth(fieldCursor) + BitField(name, fieldType, offset, size) + } + result.add(member) + } else { + // Unnamed field. + val fieldType = clang_getCursorType(fieldCursor) + when (fieldType.kind) { + CXTypeKind.CXType_Record -> { + // Unnamed struct fields also contribute their fields: + addDeclaredFields(result, structType, fieldType) + } + else -> { + // Nothing. + } + } + } + } + } + + private fun getEnumDefAt(cursor: CValue): EnumDefImpl { + if (clang_isCursorDefinition(cursor) == 0) { + val definitionCursor = clang_getCursorDefinition(cursor) + if (clang_isCursorDefinition(definitionCursor) != 0) { + return getEnumDefAt(definitionCursor) + } else { + TODO("support enum forward declarations: " + + clang_getTypeSpelling(clang_getCursorType(cursor)).convertAndDispose()) + } + } + + return enumRegistry.getOrPut(cursor) { + val cursorType = clang_getCursorType(cursor) + val typeSpelling = clang_getTypeSpelling(cursorType).convertAndDispose() + + val baseType = convertType(clang_getEnumDeclIntegerType(cursor)) + + val enumDef = EnumDefImpl(typeSpelling, baseType, getLocation(cursor)) + + visitChildren(cursor) { childCursor, _ -> + if (clang_getCursorKind(childCursor) == CXCursorKind.CXCursor_EnumConstantDecl) { + val name = clang_getCursorSpelling(childCursor).convertAndDispose() + val value = clang_getEnumConstantDeclValue(childCursor) + + val constant = EnumConstant(name, value, isExplicitlyDefined = childCursor.hasExpressionChild()) + enumDef.constants.add(constant) + } + + CXChildVisitResult.CXChildVisit_Continue + } + + enumDef + } + } + + private fun getObjCCategoryClassCursor(cursor: CValue): CValue { + assert(cursor.kind == CXCursorKind.CXCursor_ObjCCategoryDecl) + var classRef: CValue? = null + visitChildren(cursor) { child, _ -> + if (child.kind == CXCursorKind.CXCursor_ObjCClassRef) { + classRef = child + CXChildVisitResult.CXChildVisit_Break + } else { + CXChildVisitResult.CXChildVisit_Continue + } + } + + return clang_getCursorReferenced(classRef!!).apply { + assert(this.kind == CXCursorKind.CXCursor_ObjCInterfaceDecl) + } + } + + private fun isObjCInterfaceDeclForward(cursor: CValue): Boolean { + assert(cursor.kind == CXCursorKind.CXCursor_ObjCInterfaceDecl) { cursor.kind } + + // It is forward declaration <=> the first child is reference to it: + var result = false + visitChildren(cursor) { child, _ -> + result = (child.kind == CXCursorKind.CXCursor_ObjCClassRef && clang_getCursorReferenced(child) == cursor) + CXChildVisitResult.CXChildVisit_Break + } + return result + } + + private fun getObjCClassAt(cursor: CValue): ObjCClassImpl { + assert(cursor.kind == CXCursorKind.CXCursor_ObjCInterfaceDecl) { cursor.kind } + + val name = clang_getCursorDisplayName(cursor).convertAndDispose() + + if (isObjCInterfaceDeclForward(cursor)) { + return objCClassRegistry.getOrPut(cursor) { + ObjCClassImpl(name, getLocation(cursor), isForwardDeclaration = true, binaryName = null) + } + } + + return objCClassRegistry.getOrPut(cursor, { + ObjCClassImpl(name, getLocation(cursor), isForwardDeclaration = false, + binaryName = getObjCBinaryName(cursor).takeIf { it != name }) + }) { + addChildrenToObjCContainer(cursor, it) + } + + } + + private fun getObjCProtocolAt(cursor: CValue): ObjCProtocolImpl { + assert(cursor.kind == CXCursorKind.CXCursor_ObjCProtocolDecl) { cursor.kind } + val name = clang_getCursorDisplayName(cursor).convertAndDispose() + + if (clang_isCursorDefinition(cursor) == 0) { + val definition = clang_getCursorDefinition(cursor) + return if (clang_isCursorDefinition(definition) != 0) { + getObjCProtocolAt(definition) + } else { + objCProtocolRegistry.getOrPut(cursor) { + ObjCProtocolImpl(name, getLocation(cursor), isForwardDeclaration = true) + } + } + } + + return objCProtocolRegistry.getOrPut(cursor, { + ObjCProtocolImpl(name, getLocation(cursor), isForwardDeclaration = false) + }) { + addChildrenToObjCContainer(cursor, it) + } + } + + private fun getObjCBinaryName(cursor: CValue): String { + val prefix = "_OBJC_CLASS_\$_" + val symbolName = clang_Cursor_getObjCManglings(cursor)!!.convertAndDispose() + .single { it.startsWith(prefix) } + + return symbolName.substring(prefix.length) + } + + private fun getObjCCategoryAt(cursor: CValue): ObjCCategoryImpl? { + assert(cursor.kind == CXCursorKind.CXCursor_ObjCCategoryDecl) { cursor.kind } + + val classCursor = getObjCCategoryClassCursor(cursor) + if (!isAvailable(classCursor)) return null + + val name = clang_getCursorDisplayName(cursor).convertAndDispose() + val declarationId = getDeclarationId(cursor) + + return objCCategoryById.getOrPut(declarationId) { + val clazz = getObjCClassAt(classCursor) + val category = ObjCCategoryImpl(name, clazz) + addChildrenToObjCContainer(cursor, category) + category + } + + } + + private fun addChildrenToObjCContainer(cursor: CValue, result: ObjCContainerImpl) { + visitChildren(cursor) { child, _ -> + when (child.kind) { + CXCursorKind.CXCursor_ObjCSuperClassRef -> { + assert(cursor.kind == CXCursorKind.CXCursor_ObjCInterfaceDecl) + result as ObjCClassImpl + + assert(result.baseClass == null) + result.baseClass = getObjCClassAt(clang_getCursorReferenced(child)) + } + CXCursorKind.CXCursor_ObjCProtocolRef -> { + val protocol = getObjCProtocolAt(clang_getCursorReferenced(child)) + if (protocol !in result.protocols) { + result.protocols.add(protocol) + } + } + CXCursorKind.CXCursor_ObjCClassMethodDecl, CXCursorKind.CXCursor_ObjCInstanceMethodDecl -> { + getObjCMethod(child)?.let { method -> + result.methods.removeAll { method.replaces(it) } + result.methods.add(method) + } + } + else -> { + } + } + CXChildVisitResult.CXChildVisit_Continue + } + } + + fun getTypedef(type: CValue): Type { + val declCursor = clang_getTypeDeclaration(type) + val name = getCursorSpelling(declCursor) + + val underlying = convertType(clang_getTypedefDeclUnderlyingType(declCursor)) + + if (underlying == UnsupportedType) return underlying + + if (clang_getCursorLexicalParent(declCursor).kind != CXCursorKind.CXCursor_TranslationUnit) { + // Objective-C type parameters are represented as non-top-level typedefs. + // Erase for now: + return underlying + } + + if (library.language == Language.OBJECTIVE_C) { + if (name == "BOOL" || name == "Boolean") { + assert(clang_Type_getSizeOf(type) == 1L) + return ObjCBoolType + } + + if (underlying is ObjCPointer && (name == "Class" || name == "id") || + underlying is PointerType && name == "SEL") { + + // Ignore implicit Objective-C typedefs: + return underlying + } + } + + + + if ((underlying is RecordType && underlying.decl.spelling.split(' ').last() == name) || + (underlying is EnumType && underlying.def.spelling.split(' ').last() == name)) { + + // special handling for: + // typedef struct { ... } name; + // typedef enum { ... } name; + // FIXME: implement better solution + return underlying + } + + val typedefDef = typedefRegistry.getOrPut(declCursor) { + + TypedefDef(underlying, name, getLocation(declCursor)) + } + + return Typedef(typedefDef) + } + + private fun convertCursorType(cursor: CValue) = + convertType(clang_getCursorType(cursor), clang_getDeclTypeAttributes(cursor)) + + private inline fun objCType(supplier: () -> ObjCPointer) = when (library.language) { + Language.C -> UnsupportedType + Language.OBJECTIVE_C -> supplier() + } + + // We omit `const` qualifier for IntegerType and FloatingType to make `CBridgeGen` simpler. + // See KT-28102. + private fun String.dropConstQualifier() = + substringAfterLast("const ") + + private fun convertUnqualifiedPrimitiveType(type: CValue): Type = when (type.kind) { + CXTypeKind.CXType_Char_U, CXTypeKind.CXType_Char_S -> { + assert(type.getSize() == 1L) + CharType + } + + CXTypeKind.CXType_UChar, CXTypeKind.CXType_UShort, + CXTypeKind.CXType_UInt, CXTypeKind.CXType_ULong, CXTypeKind.CXType_ULongLong -> IntegerType( + size = type.getSize().toInt(), + isSigned = false, + spelling = clang_getTypeSpelling(type).convertAndDispose().dropConstQualifier() + ) + + CXTypeKind.CXType_SChar, CXTypeKind.CXType_Short, + CXTypeKind.CXType_Int, CXTypeKind.CXType_Long, CXTypeKind.CXType_LongLong -> IntegerType( + size = type.getSize().toInt(), + isSigned = true, + spelling = clang_getTypeSpelling(type).convertAndDispose().dropConstQualifier() + ) + + CXTypeKind.CXType_Float, CXTypeKind.CXType_Double -> FloatingType( + size = type.getSize().toInt(), + spelling = clang_getTypeSpelling(type).convertAndDispose().dropConstQualifier() + ) + + CXType_Unexposed -> { + // FIXME Remove this cludge for libclang version >= 9 (CINDEX_VERSION > 55) + if (clang_isExtVectorType(type) != 0) { + val size = clang_Type_getSizeOf(type) + if (size == 16L) { + // ExtVector elementType and elementCount are ignored for now but stubs are still needed for + // CXType_Vector compatibility. Incoming clang v9 provide CXType_ExtVector compatible with CXType_Vector + val spelling = "__attribute__((__vector_size__($size))) float" + VectorType(FloatingType(4, "float"), 4, spelling) + } else { + UnsupportedType + } + } else { + UnsupportedType + } + } + + CXType_Vector -> { + val elementCXType = clang_getElementType(type) + val elementType = convertType(elementCXType) + val size = clang_Type_getSizeOf(type) + val elemSize = clang_Type_getSizeOf(elementCXType) + val elementCount = clang_getNumElements(type) + assert(size >= elemSize * elementCount && size % elemSize == 0L) + + // Spelling example: `__attribute__((__vector_size__(4 * sizeof(float)))) const float` + // Re-generate spelling removing constness and typedefs to limit number of variants for bridge generator + // Supposed to be the same (i.e. natively compatible) as clang_getTypeSpelling(type) aka type.name + val spelling = "__attribute__((__vector_size__($size))) ${clang_getCanonicalType(elementCXType).name}" + + if (size == 16L) { + VectorType(elementType, elementCount.toInt(), spelling) + } else { + UnsupportedType + } + } + + CXTypeKind.CXType_Bool -> CBoolType + + else -> UnsupportedType + } + + fun convertType(type: CValue, typeAttributes: CValue? = null): Type { + val primitiveType = convertUnqualifiedPrimitiveType(type) + if (primitiveType != UnsupportedType) { + return primitiveType + } + + val kind = type.kind + + return when (kind) { + CXType_Elaborated -> convertType(clang_Type_getNamedType(type)) + + CXType_Unexposed -> { + if (clang_getResultType(type).kind != CXTypeKind.CXType_Invalid) { + convertFunctionType(type) + } else { + val canonicalType = clang_getCanonicalType(type) + if (canonicalType.kind != CXType_Unexposed) { + convertType(canonicalType) + } else { + UnsupportedType + } + } + } + + CXType_Void -> VoidType + + CXType_Typedef -> { + val declCursor = clang_getTypeDeclaration(type) + val declSpelling = getCursorSpelling(declCursor) + val underlying = convertType(clang_getTypedefDeclUnderlyingType(declCursor)) + when { + declSpelling == "instancetype" && underlying is ObjCPointer -> + ObjCInstanceType(getNullability(type, typeAttributes)) + + else -> getTypedef(type) + } + } + + CXType_Record -> RecordType(getStructDeclAt(clang_getTypeDeclaration(type))) + CXType_Enum -> EnumType(getEnumDefAt(clang_getTypeDeclaration(type))) + + CXType_Pointer -> { + val pointeeType = clang_getPointeeType(type) + val pointeeIsConst = + (clang_isConstQualifiedType(clang_getCanonicalType(pointeeType)) != 0) + + val convertedPointeeType = convertType(pointeeType) + PointerType( + if (convertedPointeeType == UnsupportedType) VoidType else convertedPointeeType, + pointeeIsConst = pointeeIsConst + ) + } + + CXType_ConstantArray -> { + val elementType = convertType(clang_getArrayElementType(type)) + val length = clang_getArraySize(type) + ConstArrayType(elementType, length) + } + + CXType_IncompleteArray -> { + val elementType = convertType(clang_getArrayElementType(type)) + IncompleteArrayType(elementType) + } + + CXType_VariableArray -> { + val elementType = convertType(clang_getArrayElementType(type)) + VariableArrayType(elementType) + } + + CXType_FunctionProto -> { + convertFunctionType(type) + } + + CXType_ObjCObjectPointer -> objCType { + val declaration = clang_getTypeDeclaration(clang_getPointeeType(type)) + val declarationKind = declaration.kind + val nullability = getNullability(type, typeAttributes) + when (declarationKind) { + CXCursorKind.CXCursor_NoDeclFound -> ObjCIdType(nullability, getProtocols(type)) + + CXCursorKind.CXCursor_ObjCInterfaceDecl -> + ObjCObjectPointer(getObjCClassAt(declaration), nullability, getProtocols(type)) + + CXCursorKind.CXCursor_TypedefDecl -> + // typedef to Objective-C class itself, e.g. `typedef NSObject Object;`, + // (as opposed to `typedef NSObject* Object;`). + // Note: it is not yet represented as Kotlin `typealias`. + ObjCObjectPointer( + getObjCClassAt(getTypedefUnderlyingObjCClass(declaration)), + nullability, + getProtocols(type) + ) + + else -> TODO("${declarationKind.toString()} ${clang_getTypeSpelling(type).convertAndDispose()}") + } + } + + CXType_ObjCId -> objCType { ObjCIdType(getNullability(type, typeAttributes), getProtocols(type)) } + + CXType_ObjCClass -> objCType { ObjCClassPointer(getNullability(type, typeAttributes), getProtocols(type)) } + + CXType_ObjCSel -> PointerType(VoidType) + + CXType_BlockPointer -> objCType { convertBlockPointerType(type, typeAttributes) } + + else -> UnsupportedType + } + } + + private tailrec fun getTypedefUnderlyingObjCClass(typedefDecl: CValue): CValue { + assert(typedefDecl.kind == CXCursorKind.CXCursor_TypedefDecl) + val underlyingType = clang_getTypedefDeclUnderlyingType(typedefDecl) + val underlyingTypeDecl = clang_getTypeDeclaration(underlyingType) + + return when (underlyingTypeDecl.kind) { + CXCursorKind.CXCursor_TypedefDecl -> getTypedefUnderlyingObjCClass(underlyingTypeDecl) + CXCursorKind.CXCursor_ObjCInterfaceDecl -> underlyingTypeDecl + else -> TODO( + """typedef = ${getCursorSpelling(typedefDecl)} + |underlying decl kind = ${underlyingTypeDecl.kind} + |underlying = ${clang_getTypeSpelling(underlyingType).convertAndDispose()}""".trimMargin() + ) + } + } + + private fun getNullability( + type: CValue, typeAttributes: CValue? + ): ObjCPointer.Nullability { + + if (typeAttributes == null) return ObjCPointer.Nullability.Unspecified + + return when (clang_Type_getNullabilityKind(type, typeAttributes)) { + CXNullabilityKind.CXNullabilityKind_Nullable -> ObjCPointer.Nullability.Nullable + CXNullabilityKind.CXNullabilityKind_NonNull -> ObjCPointer.Nullability.NonNull + CXNullabilityKind.CXNullabilityKind_Unspecified -> ObjCPointer.Nullability.Unspecified + } + } + + private fun getProtocols(type: CValue): List { + val num = clang_Type_getNumProtocols(type) + return (0 until num).map { index -> + getObjCProtocolAt(clang_Type_getProtocol(type, index)) + } + } + + private fun convertFunctionType(type: CValue): Type { + val kind = type.kind + assert(kind == CXType_Unexposed || kind == CXType_FunctionProto || kind == CXType_FunctionNoProto) { kind } + + if (clang_isFunctionTypeVariadic(type) != 0) { + return VoidType // make this function pointer opaque. + } else { + val returnType = convertType(clang_getResultType(type)) + val numArgs = clang_getNumArgTypes(type) + + // Ignore functions with long signatures since we have no basic class for such functional types in the stdlib. + // TODO: Remove this limitation when functional types with long signatures are supported. + if (numArgs > 22) { + log("Warning: cannot generate a Kotlin functional type for a pointer to a function with more than 22 parameters. " + + "An opaque pointer will be used instead.") + return VoidType + } + + val paramTypes = (0..numArgs - 1).map { + convertType(clang_getArgType(type, it)) + } + + return if (returnType == UnsupportedType || paramTypes.any { it == UnsupportedType }) { + VoidType + } else { + FunctionType(paramTypes, returnType) + } + } + } + + private fun convertBlockPointerType(type: CValue, typeAttributes: CValue?): ObjCPointer { + val kind = type.kind + assert(kind == CXType_BlockPointer) + + val pointee = clang_getPointeeType(type) + val nullability = getNullability(type, typeAttributes) + + // TODO: also use nullability attributes of parameters and return value. + + val functionType = convertFunctionType(pointee) as? FunctionType + ?: return ObjCIdType(nullability, protocols = emptyList()) + + return ObjCBlockPointer(nullability, functionType.parameterTypes, functionType.returnType) + } + + private val TARGET_ATTRIBUTE = "__target__" + + private fun isSuitableFunction(cursor: CValue): Boolean { + if (!isAvailable(cursor)) return false + + // If function is specific for certain target, ignore that, as we may be + // unable to generate machine code for bridge from the bitcode. + return !functionHasTargetAttribute(cursor) + } + + private fun functionHasTargetAttribute(cursor: CValue): Boolean { + // TODO: this must be implemented with hasAttribute(), but hasAttribute() + // works for Mac hosts only so far. + + var result = false + visitChildren(cursor) { child, _ -> + if (isTargetAttribute(child)) { + result = true + CXChildVisitResult.CXChildVisit_Break + } else { + CXChildVisitResult.CXChildVisit_Continue + } + } + return result + } + + private fun isTargetAttribute(cursor: CValue): Boolean = clang_isAttribute(cursor.kind) != 0 && + getExtentFirstToken(cursor) == TARGET_ATTRIBUTE + + private fun getExtentFirstToken(cursor: CValue) = + getToken(clang_Cursor_getTranslationUnit(cursor)!!, clang_getRangeStart(clang_getCursorExtent(cursor))) + + // TODO: implement with clang_getToken after updating libclang. + private fun getToken(translationUnit: CXTranslationUnit, location: CValue): String? = memScoped { + val range = clang_getRange(location, location) // Seems to work. + + val tokensVar = alloc>() + val numTokensVar = alloc() + clang_tokenize(translationUnit, range, tokensVar.ptr, numTokensVar.ptr) + val numTokens = numTokensVar.value + val tokens = tokensVar.value ?: return null + + try { + when (numTokens) { + 0 -> null + 1 -> clang_getTokenSpelling(translationUnit, tokens[0].readValue()).convertAndDispose() + else -> error("Unexpected number of tokens: $numTokens") + } + } finally { + clang_disposeTokens(translationUnit, tokens, numTokens) + } + } + + fun indexDeclaration(info: CXIdxDeclInfo): Unit { + val cursor = info.cursor.readValue() + val entityInfo = info.entityInfo!!.pointed + val entityName = entityInfo.name?.toKString() + val kind = entityInfo.kind + + if (!this.library.includesDeclaration(cursor)) { + return + } + + when (kind) { + CXIdxEntity_Struct, CXIdxEntity_Union -> { + if (entityName == null) { + // Skip anonymous struct. + // (It gets included anyway if used as a named field type). + } else { + getStructDeclAt(cursor) + } + } + + CXIdxEntity_Typedef -> { + val type = clang_getCursorType(cursor) + getTypedef(type) + } + + CXIdxEntity_Function -> { + if (isSuitableFunction(cursor)) { + functionById.getOrPut(getDeclarationId(cursor)) { + getFunction(cursor) + } + } + } + + CXIdxEntity_Enum -> { + getEnumDefAt(cursor) + } + + CXIdxEntity_Variable -> { + if (info.semanticContainer!!.pointed.cursor.kind == CXCursorKind.CXCursor_TranslationUnit) { + // Top-level variable. + globalById.getOrPut(getDeclarationId(cursor)) { + GlobalDecl( + name = entityName!!, + type = convertCursorType(cursor), + isConst = clang_isConstQualifiedType(clang_getCursorType(cursor)) != 0 + ) + } + } + } + + CXIdxEntity_ObjCClass -> if (cursor.kind != CXCursorKind.CXCursor_ObjCClassRef /* not a forward declaration */) { + indexObjCClass(cursor) + } + + CXIdxEntity_ObjCCategory -> { + if (isAvailable(cursor)) { + getObjCCategoryAt(cursor) + } + } + + CXIdxEntity_ObjCProtocol -> if (cursor.kind != CXCursorKind.CXCursor_ObjCProtocolRef /* not a forward declaration */) { + indexObjCProtocol(cursor) + } + + CXIdxEntity_ObjCProperty -> { + val container = clang_getCursorSemanticParent(cursor) + if (isAvailable(cursor) && isAvailable(container)) { + val propertyInfo = clang_index_getObjCPropertyDeclInfo(info.ptr)!!.pointed + val getter = getObjCMethod(propertyInfo.getter!!.pointed.cursor.readValue()) + val setter = propertyInfo.setter?.let { + getObjCMethod(it.pointed.cursor.readValue()) + } + + if (getter != null) { + val property = ObjCProperty(entityName!!, getter, setter) + val objCContainer: ObjCContainerImpl? = when (container.kind) { + CXCursorKind.CXCursor_ObjCCategoryDecl -> getObjCCategoryAt(container) + CXCursorKind.CXCursor_ObjCInterfaceDecl -> getObjCClassAt(container) + CXCursorKind.CXCursor_ObjCProtocolDecl -> getObjCProtocolAt(container) + else -> error(container.kind) + } + + if (objCContainer != null) { + objCContainer.properties.removeAll { property.replaces(it) } + objCContainer.properties.add(property) + } + } + } + } + + else -> { + // Ignore declaration. + } + } + } + + fun indexObjCClass(cursor: CValue) { + if (isAvailable(cursor)) { + getObjCClassAt(cursor) + } + } + + fun indexObjCProtocol(cursor: CValue) { + if (isAvailable(cursor)) { + getObjCProtocolAt(cursor) + } + } + + private fun getFunction(cursor: CValue): FunctionDecl { + val name = clang_getCursorSpelling(cursor).convertAndDispose() + val returnType = convertType(clang_getCursorResultType(cursor), clang_getCursorResultTypeAttributes(cursor)) + + val parameters = getFunctionParameters(cursor) + + val binaryName = when (library.language) { + Language.C, Language.OBJECTIVE_C -> clang_Cursor_getMangling(cursor).convertAndDispose() + } + + val definitionCursor = clang_getCursorDefinition(cursor) + val isDefined = (clang_Cursor_isNull(definitionCursor) == 0) + + val isVararg = clang_Cursor_isVariadic(cursor) != 0 + + return FunctionDecl(name, parameters, returnType, binaryName, isDefined, isVararg) + } + + private fun getObjCMethod(cursor: CValue): ObjCMethod? { + if (!isAvailable(cursor)) { + return null + } + + val selector = clang_getCursorDisplayName(cursor).convertAndDispose() + + // Ignore some very special methods: + when (selector) { + "dealloc", "retain", "release", "autorelease", "retainCount", "self" -> return null + } + + val encoding = clang_getDeclObjCTypeEncoding(cursor).convertAndDispose() + val returnType = convertType(clang_getCursorResultType(cursor), clang_getCursorResultTypeAttributes(cursor)) + val parameters = getFunctionParameters(cursor) + + if (returnType == UnsupportedType || parameters.any { it.type == UnsupportedType }) { + return null // TODO: make a more universal fix. + } + + val isClass = when (cursor.kind) { + CXCursorKind.CXCursor_ObjCClassMethodDecl -> true + CXCursorKind.CXCursor_ObjCInstanceMethodDecl -> false + else -> error(cursor.kind) + } + + return ObjCMethod( + selector, encoding, parameters, returnType, + isVariadic = clang_Cursor_isVariadic(cursor) != 0, + isClass = isClass, + nsConsumesSelf = clang_Cursor_isObjCConsumingSelfMethod(cursor) != 0, + nsReturnsRetained = clang_Cursor_isObjCReturningRetainedMethod(cursor) != 0, + isOptional = (clang_Cursor_isObjCOptional(cursor) != 0), + isInit = (clang_Cursor_isObjCInitMethod(cursor) != 0), + isExplicitlyDesignatedInitializer = hasAttribute(cursor, OBJC_DESGINATED_INITIALIZER) + ) + } + + // TODO: unavailable declarations should be imported as deprecated. + private fun isAvailable(cursor: CValue): Boolean = when (clang_getCursorAvailability(cursor)) { + CXAvailabilityKind.CXAvailability_Available, + CXAvailabilityKind.CXAvailability_Deprecated -> true + + CXAvailabilityKind.CXAvailability_NotAvailable, + CXAvailabilityKind.CXAvailability_NotAccessible -> false + } + + private fun getFunctionParameters(cursor: CValue): List { + val argNum = clang_Cursor_getNumArguments(cursor) + val args = (0..argNum - 1).map { + val argCursor = clang_Cursor_getArgument(cursor, it) + val argName = getCursorSpelling(argCursor) + val type = convertCursorType(argCursor) + Parameter(argName, type, + nsConsumed = hasAttribute(argCursor, NS_CONSUMED)) + } + return args + } + + private val NS_CONSUMED = "ns_consumed" + private val OBJC_DESGINATED_INITIALIZER = "objc_designated_initializer" + + private fun hasAttribute(cursor: CValue, name: String): Boolean { + var result = false + visitChildren(cursor) { child, _ -> + if (clang_isAttribute(child.kind) != 0 && clang_Cursor_getAttributeSpelling(child)?.toKString() == name) { + result = true + CXChildVisitResult.CXChildVisit_Break + } else { + CXChildVisitResult.CXChildVisit_Continue + } + } + return result + } + +} + +fun buildNativeIndexImpl(library: NativeLibrary, verbose: Boolean): IndexerResult { + val result = NativeIndexImpl(library, verbose) + val compilation = indexDeclarations(result) + return IndexerResult(result, compilation) +} + +private fun indexDeclarations(nativeIndex: NativeIndexImpl): CompilationWithPCH { + withIndex { index -> + val translationUnit = nativeIndex.library.copyWithArgsForPCH().parse( + index, + options = CXTranslationUnit_DetailedPreprocessingRecord or CXTranslationUnit_ForSerialization + ) + try { + translationUnit.ensureNoCompileErrors() + + val compilation = nativeIndex.library.withPrecompiledHeader(translationUnit) + + val headers = getFilteredHeaders(nativeIndex, index, translationUnit) + + nativeIndex.includedHeaders = headers.map { + nativeIndex.getHeaderId(it) + } + + indexTranslationUnit(index, translationUnit, 0, object : Indexer { + override fun indexDeclaration(info: CXIdxDeclInfo) { + val file = memScoped { + val fileVar = alloc() + clang_indexLoc_getFileLocation(info.loc.readValue(), null, fileVar.ptr, null, null, null) + fileVar.value + } + + if (file in headers) { + nativeIndex.indexDeclaration(info) + } + } + }) + + visitChildren(clang_getTranslationUnitCursor(translationUnit)) { cursor, _ -> + val file = getContainingFile(cursor) + if (file in headers && nativeIndex.library.includesDeclaration(cursor)) { + when (cursor.kind) { + CXCursorKind.CXCursor_ObjCInterfaceDecl -> nativeIndex.indexObjCClass(cursor) + CXCursorKind.CXCursor_ObjCProtocolDecl -> nativeIndex.indexObjCProtocol(cursor) + else -> {} + } + } + CXChildVisitResult.CXChildVisit_Continue + } + + findMacros(nativeIndex, compilation, translationUnit, headers) + + return compilation + } finally { + clang_disposeTranslationUnit(translationUnit) + } + } +} diff --git a/kotlin-native/Interop/Indexer/src/main/kotlin/org/jetbrains/kotlin/native/interop/indexer/MacroConstants.kt b/kotlin-native/Interop/Indexer/src/main/kotlin/org/jetbrains/kotlin/native/interop/indexer/MacroConstants.kt new file mode 100644 index 00000000000..225e4b7b024 --- /dev/null +++ b/kotlin-native/Interop/Indexer/src/main/kotlin/org/jetbrains/kotlin/native/interop/indexer/MacroConstants.kt @@ -0,0 +1,322 @@ +/* + * Copyright 2010-2017 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.jetbrains.kotlin.native.interop.indexer + +import clang.* +import kotlinx.cinterop.* +import java.io.File + +/** + * Finds all "macro constants" and registers them as [NativeIndex.constants] in given index. + */ +internal fun findMacros( + nativeIndex: NativeIndexImpl, + compilation: CompilationWithPCH, + translationUnit: CXTranslationUnit, + headers: Set +) { + val names = collectMacroNames(nativeIndex, translationUnit, headers) + // TODO: apply user-defined filters. + val macros = expandMacros(compilation, names, typeConverter = { nativeIndex.convertType(it) }) + + macros.filterIsInstanceTo(nativeIndex.macroConstants) + macros.filterIsInstanceTo(nativeIndex.wrappedMacros) +} + +private typealias TypeConverter = (CValue) -> Type + +/** + * For each name expands the macro with this name declared in the library, + * checking if it gets expanded to a constant expression. + * + * Note: in the worst case this method parses the code against the library a lot of times, + * so it requires library headers precompiled to significantly speed up the parsing and avoid visiting headers' AST. + * + * @return the list of constants. + */ +private fun expandMacros( + library: CompilationWithPCH, + names: List, + typeConverter: TypeConverter +): List { + withIndex(excludeDeclarationsFromPCH = true) { index -> + val sourceFile = library.createTempSource() + val compilerArgs = library.compilerArgs.toMutableList() + // We disable implicit function declaration to filter out cases when a macro is expanded as a function + // or function-like construction (e.g. #define FOO throw()) but such a function is undeclared. + compilerArgs += "-Werror=implicit-function-declaration" + + // Ensure libclang reports all errors: + compilerArgs += "-ferror-limit=0" + + val translationUnit = parseTranslationUnit(index, sourceFile, compilerArgs, options = 0) + try { + val nameToMacroDef = mutableMapOf() + val unprocessedMacros = names.toMutableList() + + // Note: will be slow for a library with a lot of macros having unbalanced '{'. TODO: Optimize this case too. + + while (unprocessedMacros.isNotEmpty()) { + val processedMacros = + tryExpandMacros(library, translationUnit, sourceFile, unprocessedMacros, typeConverter) + + unprocessedMacros -= (processedMacros.keys + unprocessedMacros.first()) + // Note: removing first macro should not have any effect, doing this to ensure the loop is finite. + + processedMacros.forEach { (name, macroDef) -> + if (macroDef != null) nameToMacroDef[name] = macroDef + } + } + + return names.mapNotNull { nameToMacroDef[it] } + } finally { + clang_disposeTranslationUnit(translationUnit) + } + } +} + +/** + * Tries to expand macros [names] defined in [library]. + * Returns the map of successfully processed macros with resulting constant as a value + * or `null` if the result is not a constant (expression). + * + * As a side effect, modifies the [sourceFile] and reparses the [translationUnit]. + */ +private fun tryExpandMacros( + library: CompilationWithPCH, + translationUnit: CXTranslationUnit, + sourceFile: File, + names: List, + typeConverter: TypeConverter +): Map { + + reparseWithCodeSnippets(library, translationUnit, sourceFile, names) + + val macrosWithErrorsInSnippetFunctionHeader = mutableSetOf() + val macrosWithErrorsInSnippetFunctionBody = mutableSetOf() + + val preambleSize = library.preambleLines.size + + translationUnit.getErrorLineNumbers().map { it - preambleSize - 1 }.forEach { lineNumber -> + val index = lineNumber / CODE_SNIPPET_LINES_NUMBER + if (index >= 0 && index < names.size) { + when (lineNumber % CODE_SNIPPET_LINES_NUMBER) { + 0 -> macrosWithErrorsInSnippetFunctionHeader += names[index] + 1 -> macrosWithErrorsInSnippetFunctionBody += names[index] + else -> {} + } + } + } + + val result = mutableMapOf() + + visitChildren(translationUnit) { cursor, _ -> + if (cursor.kind == CXCursorKind.CXCursor_FunctionDecl) { + val functionName = getCursorSpelling(cursor) + if (functionName.startsWith(CODE_SNIPPET_FUNCTION_NAME_PREFIX)) { + val macroName = functionName.removePrefix(CODE_SNIPPET_FUNCTION_NAME_PREFIX) + if (macroName in macrosWithErrorsInSnippetFunctionHeader) { + // Code snippet is likely affected by previous macros' snippets, skip it for now. + } else { + result[macroName] = if (macroName in macrosWithErrorsInSnippetFunctionBody) { + // Code snippet is likely unaffected by previous ones but parsed with its own errors, + // so suppose macro is processed successfully as non-expression: + null + } else { + processCodeSnippet(cursor, macroName, typeConverter) + } + } + } + } + CXChildVisitResult.CXChildVisit_Continue + } + + return result +} + +private const val CODE_SNIPPET_LINES_NUMBER = 3 +private const val CODE_SNIPPET_FUNCTION_NAME_PREFIX = "kni_indexer_function_" + +/** + * Adds code snippets to be then processed with [processCodeSnippet] to the [sourceFile] + * and reparses the [translationUnit]. + * + * - If a code snippet allows extracting the constant value using libclang API, we'll add a [ConstantDef] in the + * native index and generate a Kotlin constant for it. + * - If the expression type can be inferred by libclang, we'll add a [WrappedMacroDef] in the native index and + * generate a bridge for this macro. + * - Otherwise the macro is skipped. + */ +private fun reparseWithCodeSnippets(library: CompilationWithPCH, + translationUnit: CXTranslationUnit, sourceFile: File, + names: List) { + + // TODO: consider using CXUnsavedFile instead of writing the modified file to OS file system. + sourceFile.bufferedWriter().use { writer -> + writer.appendPreamble(library) + + names.forEach { name -> + val codeSnippetLines = when (library.language) { + Language.C, Language.OBJECTIVE_C -> + listOf("void $CODE_SNIPPET_FUNCTION_NAME_PREFIX$name() {", + " __auto_type KNI_INDEXER_VARIABLE_$name = $name;", + "}") + } + + assert(codeSnippetLines.size == CODE_SNIPPET_LINES_NUMBER) + codeSnippetLines.forEach { writer.appendLine(it) } + } + } + clang_reparseTranslationUnit(translationUnit, 0, null, 0) +} + +/** + * Checks that [functionCursor] is parsed exactly as expected for the code appended by [reparseWithCodeSnippets], + * and returns the constant on success. + */ +private fun processCodeSnippet( + functionCursor: CValue, + name: String, + typeConverter: TypeConverter +): MacroDef? { + + val kindsToSkip = setOf(CXCursorKind.CXCursor_CompoundStmt) + var state = VisitorState.EXPECT_NODES_TO_SKIP + var evalResultOrNull: CXEvalResult? = null + var typeOrNull: Type? = null + + val visitor: CursorVisitor = { cursor, _ -> + val kind = cursor.kind + when { + state == VisitorState.EXPECT_VARIABLE && kind == CXCursorKind.CXCursor_VarDecl -> { + evalResultOrNull = clang_Cursor_Evaluate(cursor) + state = VisitorState.EXPECT_VARIABLE_VALUE + CXChildVisitResult.CXChildVisit_Recurse + } + + state == VisitorState.EXPECT_VARIABLE_VALUE && clang_isExpression(kind) != 0 -> { + typeOrNull = typeConverter(clang_getCursorType(cursor)) + state = VisitorState.EXPECT_END + CXChildVisitResult.CXChildVisit_Continue + } + + // Skip auxiliary elements. + state == VisitorState.EXPECT_NODES_TO_SKIP && kind in kindsToSkip -> + CXChildVisitResult.CXChildVisit_Recurse + + state == VisitorState.EXPECT_NODES_TO_SKIP && kind == CXCursorKind.CXCursor_DeclStmt -> { + state = VisitorState.EXPECT_VARIABLE + CXChildVisitResult.CXChildVisit_Recurse + } + + else -> { + state = VisitorState.INVALID + CXChildVisitResult.CXChildVisit_Break + } + } + } + + try { + visitChildren(functionCursor, visitor) + + if (state != VisitorState.EXPECT_END) { + return null + } + + val type = typeOrNull!! + return if (evalResultOrNull == null) { + // The macro cannot be evaluated as a constant so we will wrap it in a bridge. + when(type.unwrapTypedefs()) { + is PrimitiveType, + is PointerType, + is ObjCPointer -> WrappedMacroDef(name, type) + else -> null + } + } else { + // Otherwise we can evaluate the expression and create a Kotlin constant for it. + val evalResult = evalResultOrNull!! + val evalResultKind = clang_EvalResult_getKind(evalResult) + when (evalResultKind) { + CXEvalResultKind.CXEval_Int -> + IntegerConstantDef(name, type, clang_EvalResult_getAsLongLong(evalResult)) + + CXEvalResultKind.CXEval_Float -> + FloatingConstantDef(name, type, clang_EvalResult_getAsDouble(evalResult)) + + CXEvalResultKind.CXEval_CFStr, + CXEvalResultKind.CXEval_ObjCStrLiteral, + CXEvalResultKind.CXEval_StrLiteral -> + if (evalResultKind == CXEvalResultKind.CXEval_StrLiteral && !type.canonicalIsPointerToChar()) { + // libclang doesn't seem to support wide string literals properly in this API; + // thus disable wide literals here: + null + } else { + StringConstantDef(name, type, clang_EvalResult_getAsStr(evalResult)!!.toKString()) + } + + CXEvalResultKind.CXEval_Other, + CXEvalResultKind.CXEval_UnExposed -> null + } + } + + } finally { + evalResultOrNull?.let { clang_EvalResult_dispose(it) } + } +} + +enum class VisitorState { + EXPECT_NODES_TO_SKIP, + EXPECT_VARIABLE, EXPECT_VARIABLE_VALUE, + EXPECT_END, INVALID +} + +private fun collectMacroNames(nativeIndex: NativeIndexImpl, translationUnit: CXTranslationUnit, headers: Set): List { + val result = mutableSetOf() + + visitChildren(translationUnit) { cursor, _ -> + val file = memScoped { + val fileVar = alloc() + clang_getFileLocation(clang_getCursorLocation(cursor), fileVar.ptr, null, null, null) + fileVar.value + } + + if (cursor.kind == CXCursorKind.CXCursor_MacroDefinition && + nativeIndex.library.includesDeclaration(cursor) && + file != null && // Builtin macros mostly seem to be useless. + file in headers && + canMacroBeConstant(cursor)) + { + val spelling = getCursorSpelling(cursor) + result.add(spelling) + } + CXChildVisitResult.CXChildVisit_Continue + } + + return result.toList() +} + +private fun canMacroBeConstant(cursor: CValue): Boolean { + + if (clang_Cursor_isMacroFunctionLike(cursor) != 0) { + return false + } + + // TODO: check number of tokens and filter out empty definitions; + // Requires updating to 3.9.1 due to https://bugs.llvm.org//show_bug.cgi?id=9069 + + return true +} \ No newline at end of file diff --git a/kotlin-native/Interop/Indexer/src/main/kotlin/org/jetbrains/kotlin/native/interop/indexer/ModuleSupport.kt b/kotlin-native/Interop/Indexer/src/main/kotlin/org/jetbrains/kotlin/native/interop/indexer/ModuleSupport.kt new file mode 100644 index 00000000000..b603ae69c2e --- /dev/null +++ b/kotlin-native/Interop/Indexer/src/main/kotlin/org/jetbrains/kotlin/native/interop/indexer/ModuleSupport.kt @@ -0,0 +1,138 @@ +package org.jetbrains.kotlin.native.interop.indexer + +import clang.* +import kotlinx.cinterop.* + +data class ModulesInfo(val topLevelHeaders: List, val ownHeaders: Set) + +fun getModulesInfo(compilation: Compilation, modules: List): ModulesInfo { + if (modules.isEmpty()) return ModulesInfo(emptyList(), emptySet()) + + withIndex { index -> + ModularCompilation(compilation).use { + val modulesASTFiles = getModulesASTFiles(index, it, modules) + return buildModulesInfo(index, modules, modulesASTFiles) + } + } +} + +private fun buildModulesInfo(index: CXIndex, modules: List, modulesASTFiles: List): ModulesInfo { + val ownHeaders = mutableSetOf() + val topLevelHeaders = linkedSetOf() + modulesASTFiles.forEach { + val moduleTranslationUnit = clang_createTranslationUnit(index, it)!! + try { + val modulesHeaders = getModulesHeaders(index, moduleTranslationUnit, modules.toSet(), topLevelHeaders) + modulesHeaders.mapTo(ownHeaders) { it.canonicalPath } + } finally { + clang_disposeTranslationUnit(moduleTranslationUnit) + } + } + + return ModulesInfo(topLevelHeaders.toList(), ownHeaders) +} + +internal open class ModularCompilation(compilation: Compilation): Compilation by compilation, Disposable { + + companion object { + private const val moduleCacheFlag = "-fmodules-cache-path=" + } + + private val moduleCacheDirectory = if (compilation.compilerArgs.none { it.startsWith(moduleCacheFlag) }) { + createTempDir("ModuleCache") + } else { + null + } + + override val compilerArgs: List = compilation.compilerArgs + + listOfNotNull("-fmodules", moduleCacheDirectory?.let { "$moduleCacheFlag${it.absolutePath}" }) + + override fun dispose() { + moduleCacheDirectory?.deleteRecursively() + } +} + +private fun getModulesASTFiles(index: CXIndex, compilation: ModularCompilation, modules: List): List { + val compilationWithImports = compilation.copy( + additionalPreambleLines = modules.map { "@import $it;" } + compilation.additionalPreambleLines + ) + + val result = linkedSetOf() + + val translationUnit = compilationWithImports.parse( + index, + options = CXTranslationUnit_DetailedPreprocessingRecord + ) + try { + translationUnit.ensureNoCompileErrors() + + indexTranslationUnit(index, translationUnit, 0, object : Indexer { + override fun importedASTFile(info: CXIdxImportedASTFileInfo) { + result += info.file!!.canonicalPath + } + }) + } finally { + clang_disposeTranslationUnit(translationUnit) + } + return result.toList() +} + +private fun getModulesHeaders( + index: CXIndex, + translationUnit: CXTranslationUnit, + modules: Set, + topLevelHeaders: LinkedHashSet +): Set { + val nonModularIncludes = mutableMapOf>() + val result = mutableSetOf() + + indexTranslationUnit(index, translationUnit, 0, object : Indexer { + override fun ppIncludedFile(info: CXIdxIncludedFileInfo) { + val file = info.file!! + val includer = clang_indexLoc_getCXSourceLocation(info.hashLoc.readValue()).getContainingFile() + + if (includer == null) { + // i.e. the header is included by the module itself. + topLevelHeaders += file.path + } + + val module = clang_getModuleForFile(translationUnit, file) + + if (module != null) { + val moduleWithParents = generateSequence(module, { clang_Module_getParent(it) }).map { + clang_Module_getFullName(it).convertAndDispose() + } + + if (moduleWithParents.any { it in modules }) { + result += file + } + } else if (includer != null) { + nonModularIncludes.getOrPut(includer, { mutableSetOf() }) += file + } + } + }) + + + // There are cases when non-modular includes should also be considered as a part of module. For example: + // 1. Some module maps are broken, + // e.g. system header `IOKit/hid/IOHIDProperties.h` isn't included to framework module map at all. + // 2. Textual headers are reported as non-modular by libclang. + // + // Find and include non-modular headers too: + result += findReachable(roots = result, arcs = nonModularIncludes) + + return result +} + +private fun findReachable(roots: Set, arcs: Map>): Set { + val visited = mutableSetOf() + + fun dfs(vertex: T) { + if (!visited.add(vertex)) return + arcs[vertex].orEmpty().forEach { dfs(it) } + } + + roots.forEach { dfs(it) } + + return visited +} diff --git a/kotlin-native/Interop/Indexer/src/main/kotlin/org/jetbrains/kotlin/native/interop/indexer/NativeIndex.kt b/kotlin-native/Interop/Indexer/src/main/kotlin/org/jetbrains/kotlin/native/interop/indexer/NativeIndex.kt new file mode 100644 index 00000000000..a6eca10eeea --- /dev/null +++ b/kotlin-native/Interop/Indexer/src/main/kotlin/org/jetbrains/kotlin/native/interop/indexer/NativeIndex.kt @@ -0,0 +1,331 @@ +/* + * Copyright 2010-2017 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.jetbrains.kotlin.native.interop.indexer + +enum class Language(val sourceFileExtension: String) { + C("c"), + OBJECTIVE_C("m") +} + +interface HeaderInclusionPolicy { + /** + * Whether unused declarations from given header should be excluded. + * + * @param headerName header path relative to the appropriate include path element (e.g. `time.h` or `curl/curl.h`), + * or `null` for builtin declarations. + */ + fun excludeUnused(headerName: String?): Boolean +} + +interface HeaderExclusionPolicy { + /** + * Whether all declarations from this header should be excluded. + * + * Note: the declarations from such headers can be actually present in the internal representation, + * but not included into the root collections. + */ + fun excludeAll(headerId: HeaderId): Boolean +} + +sealed class NativeLibraryHeaderFilter { + class NameBased( + val policy: HeaderInclusionPolicy, + val excludeDepdendentModules: Boolean + ) : NativeLibraryHeaderFilter() + + class Predefined(val headers: Set) : NativeLibraryHeaderFilter() +} + +interface Compilation { + val includes: List + val additionalPreambleLines: List + val compilerArgs: List + val language: Language +} + +data class CompilationWithPCH( + override val compilerArgs: List, + override val language: Language +) : Compilation { + + constructor(compilerArgs: List, precompiledHeader: String, language: Language) + : this(compilerArgs + listOf("-include-pch", precompiledHeader), language) + + override val includes: List + get() = emptyList() + + override val additionalPreambleLines: List + get() = emptyList() +} + +// TODO: Compilation hierarchy seems to require some refactoring. + +data class NativeLibrary(override val includes: List, + override val additionalPreambleLines: List, + override val compilerArgs: List, + val headerToIdMapper: HeaderToIdMapper, + override val language: Language, + val excludeSystemLibs: Boolean, // TODO: drop? + val headerExclusionPolicy: HeaderExclusionPolicy, + val headerFilter: NativeLibraryHeaderFilter) : Compilation + +data class IndexerResult(val index: NativeIndex, val compilation: CompilationWithPCH) + +/** + * Retrieves the definitions from given C header file using given compiler arguments (e.g. defines). + */ +fun buildNativeIndex(library: NativeLibrary, verbose: Boolean): IndexerResult = buildNativeIndexImpl(library, verbose) + +/** + * This class describes the IR of definitions from C header file(s). + */ +abstract class NativeIndex { + abstract val structs: Collection + abstract val enums: Collection + abstract val objCClasses: Collection + abstract val objCProtocols: Collection + abstract val objCCategories: Collection + abstract val typedefs: Collection + abstract val functions: Collection + abstract val macroConstants: Collection + abstract val wrappedMacros: Collection + abstract val globals: Collection + abstract val includedHeaders: Collection +} + +/** + * The (contents-based) header id. + * Its [value] remains valid across different runs of the indexer and the process, + * and thus can be used to 'serialize' the id. + */ +data class HeaderId(val value: String) + +data class Location(val headerId: HeaderId) + +interface TypeDeclaration { + val location: Location +} + +sealed class StructMember(val name: String, val type: Type) { + abstract val offset: Long? +} + +/** + * C struct field. + */ +class Field(name: String, type: Type, override val offset: Long, val typeSize: Long, val typeAlign: Long) + : StructMember(name, type) + +val Field.isAligned: Boolean + get() = offset % (typeAlign * 8) == 0L + +class BitField(name: String, type: Type, override val offset: Long, val size: Int) : StructMember(name, type) + +class IncompleteField(name: String, type: Type) : StructMember(name, type) { + override val offset: Long? get() = null +} + +/** + * C struct declaration. + */ +abstract class StructDecl(val spelling: String) : TypeDeclaration { + + abstract val def: StructDef? +} + +/** + * C struct definition. + * + * @param hasNaturalLayout must be `false` if the struct has unnatural layout, e.g. it is `packed`. + * May be `false` even if the struct has natural layout. + */ +abstract class StructDef(val size: Long, val align: Int, val decl: StructDecl) { + + enum class Kind { + STRUCT, UNION + } + + abstract val members: List + abstract val kind: Kind + + val fields: List get() = members.filterIsInstance() + val bitFields: List get() = members.filterIsInstance() +} + +/** + * C enum value. + */ +class EnumConstant(val name: String, val value: Long, val isExplicitlyDefined: Boolean) + +/** + * C enum definition. + */ +abstract class EnumDef(val spelling: String, val baseType: Type) : TypeDeclaration { + + abstract val constants: List +} + +sealed class ObjCContainer { + abstract val protocols: List + abstract val methods: List + abstract val properties: List +} + +sealed class ObjCClassOrProtocol(val name: String) : ObjCContainer(), TypeDeclaration { + abstract val isForwardDeclaration: Boolean +} + +data class ObjCMethod( + val selector: String, val encoding: String, val parameters: List, private val returnType: Type, + val isVariadic: Boolean, val isClass: Boolean, val nsConsumesSelf: Boolean, val nsReturnsRetained: Boolean, + val isOptional: Boolean, val isInit: Boolean, val isExplicitlyDesignatedInitializer: Boolean +) { + + fun returnsInstancetype(): Boolean = returnType is ObjCInstanceType + + fun getReturnType(container: ObjCClassOrProtocol): Type = if (returnType is ObjCInstanceType) { + when (container) { + is ObjCClass -> ObjCObjectPointer(container, returnType.nullability, protocols = emptyList()) + is ObjCProtocol -> ObjCIdType(returnType.nullability, protocols = listOf(container)) + } + } else { + returnType + } +} + +data class ObjCProperty(val name: String, val getter: ObjCMethod, val setter: ObjCMethod?) { + fun getType(container: ObjCClassOrProtocol): Type = getter.getReturnType(container) +} + +abstract class ObjCClass(name: String) : ObjCClassOrProtocol(name) { + abstract val binaryName: String? + abstract val baseClass: ObjCClass? +} +abstract class ObjCProtocol(name: String) : ObjCClassOrProtocol(name) + +abstract class ObjCCategory(val name: String, val clazz: ObjCClass) : ObjCContainer() + +/** + * C function parameter. + */ +data class Parameter(val name: String?, val type: Type, val nsConsumed: Boolean) + +/** + * C function declaration. + */ +class FunctionDecl(val name: String, val parameters: List, val returnType: Type, val binaryName: String, + val isDefined: Boolean, val isVararg: Boolean) + +/** + * C typedef definition. + * + * ``` + * typedef $aliased $name; + * ``` + */ +class TypedefDef(val aliased: Type, val name: String, override val location: Location) : TypeDeclaration + +abstract class MacroDef(val name: String) + +abstract class ConstantDef(name: String, val type: Type): MacroDef(name) +class IntegerConstantDef(name: String, type: Type, val value: Long) : ConstantDef(name, type) +class FloatingConstantDef(name: String, type: Type, val value: Double) : ConstantDef(name, type) +class StringConstantDef(name: String, type: Type, val value: String) : ConstantDef(name, type) + +class WrappedMacroDef(name: String, val type: Type) : MacroDef(name) + +class GlobalDecl(val name: String, val type: Type, val isConst: Boolean) + +/** + * C type. + */ +interface Type + +interface PrimitiveType : Type + +object CharType : PrimitiveType + +open class BoolType: PrimitiveType + +object CBoolType : BoolType() + +object ObjCBoolType : BoolType() +// We omit `const` qualifier for IntegerType and FloatingType to make `CBridgeGen` simpler. +// See KT-28102. +data class IntegerType(val size: Int, val isSigned: Boolean, val spelling: String) : PrimitiveType + +// TODO: floating type is not actually defined entirely by its size. +data class FloatingType(val size: Int, val spelling: String) : PrimitiveType + +data class VectorType(val elementType: Type, val elementCount: Int, val spelling: String) : PrimitiveType + +object VoidType : Type + +data class RecordType(val decl: StructDecl) : Type + +data class EnumType(val def: EnumDef) : Type + +data class PointerType(val pointeeType: Type, val pointeeIsConst: Boolean = false) : Type +// TODO: refactor type representation and support type modifiers more generally. + +data class FunctionType(val parameterTypes: List, val returnType: Type) : Type + +interface ArrayType : Type { + val elemType: Type +} + +data class ConstArrayType(override val elemType: Type, val length: Long) : ArrayType +data class IncompleteArrayType(override val elemType: Type) : ArrayType +data class VariableArrayType(override val elemType: Type) : ArrayType + +data class Typedef(val def: TypedefDef) : Type + +sealed class ObjCPointer : Type { + enum class Nullability { + Nullable, NonNull, Unspecified + } + + abstract val nullability: Nullability +} + +sealed class ObjCQualifiedPointer : ObjCPointer() { + abstract val protocols: List +} + +data class ObjCObjectPointer( + val def: ObjCClass, + override val nullability: Nullability, + override val protocols: List +) : ObjCQualifiedPointer() + +data class ObjCClassPointer( + override val nullability: Nullability, + override val protocols: List +) : ObjCQualifiedPointer() + +data class ObjCIdType( + override val nullability: Nullability, + override val protocols: List +) : ObjCQualifiedPointer() + +data class ObjCInstanceType(override val nullability: Nullability) : ObjCPointer() +data class ObjCBlockPointer( + override val nullability: Nullability, + val parameterTypes: List, val returnType: Type +) : ObjCPointer() + +object UnsupportedType : Type diff --git a/kotlin-native/Interop/Indexer/src/main/kotlin/org/jetbrains/kotlin/native/interop/indexer/Utils.kt b/kotlin-native/Interop/Indexer/src/main/kotlin/org/jetbrains/kotlin/native/interop/indexer/Utils.kt new file mode 100644 index 00000000000..371bc3c6b63 --- /dev/null +++ b/kotlin-native/Interop/Indexer/src/main/kotlin/org/jetbrains/kotlin/native/interop/indexer/Utils.kt @@ -0,0 +1,770 @@ +/* + * Copyright 2010-2017 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.jetbrains.kotlin.native.interop.indexer + +import clang.* +import kotlinx.cinterop.* +import java.io.Closeable +import java.io.File +import java.nio.file.Files +import java.nio.file.Path +import java.nio.file.Paths +import java.security.DigestInputStream +import java.security.MessageDigest + +internal val CValue.kind: CXTypeKind get() = this.useContents { kind } + +internal val CValue.kind: CXCursorKind get() = this.useContents { kind } + +internal val CValue.type: CValue get() = clang_getCursorType(this) +internal val CValue.spelling: String get() = clang_getCursorSpelling(this).convertAndDispose() +internal val CValue.name: String get() = clang_getTypeSpelling(this).convertAndDispose() +internal val CXTypeKind.spelling: String get() = clang_getTypeKindSpelling(this).convertAndDispose() +internal val CXCursorKind.spelling: String get() = clang_getCursorKindSpelling(this).convertAndDispose() + +internal fun CValue.convertAndDispose(): String { + try { + return clang_getCString(this)!!.toKString() + } finally { + clang_disposeString(this) + } +} + +internal fun CPointer.convertAndDispose(): Set = try { + (0 until this.pointed.Count).mapTo(mutableSetOf()) { + clang_getCString(this.pointed.Strings!![it].readValue())!!.toKString() + } +} finally { + clang_disposeStringSet(this) +} + +internal fun getCursorSpelling(cursor: CValue) = + clang_getCursorSpelling(cursor).convertAndDispose() + +internal fun CValue.getSize(): Long { + val size = clang_Type_getSizeOf(this) + if (size < 0) { + throw Error(size.toString()) + } + return size +} + +internal inline fun withIndex( + excludeDeclarationsFromPCH: Boolean = false, + displayDiagnostics: Boolean = false, + block: (index: CXIndex) -> R +): R { + val index = clang_createIndex( + excludeDeclarationsFromPCH = if (excludeDeclarationsFromPCH) 1 else 0, + displayDiagnostics = if (displayDiagnostics) 1 else 0 + )!! + + return try { + block(index) + } finally { + clang_disposeIndex(index) + } +} + +internal fun parseTranslationUnit( + index: CXIndex, + sourceFile: File, + compilerArgs: List, + options: Int +): CXTranslationUnit { + + memScoped { + val resultVar = alloc() + + val errorCode = clang_parseTranslationUnit2( + index, + sourceFile.absolutePath, + compilerArgs.toNativeStringArray(memScope), compilerArgs.size, + null, 0, + options, + resultVar.ptr + ) + + if (errorCode != CXErrorCode.CXError_Success) { + val copiedSourceFile = sourceFile.copyTo(createTempFile(suffix = sourceFile.name), overwrite = true) + + error(""" + clang_parseTranslationUnit2 failed with $errorCode; + sourceFile = ${copiedSourceFile.absolutePath} + arguments = ${compilerArgs.joinToString(" ")} + """.trimIndent()) + } + + return resultVar.value!! + } +} + +internal fun Compilation.parse(index: CXIndex, options: Int = 0): CXTranslationUnit = + parseTranslationUnit(index, this.createTempSource(), this.compilerArgs, options) + +internal data class Diagnostic(val severity: CXDiagnosticSeverity, val format: String, + val location: CValue) + +internal fun CXTranslationUnit.getDiagnostics(): Sequence { + val numDiagnostics = clang_getNumDiagnostics(this) + return (0 until numDiagnostics).asSequence() + .map { index -> + val diagnostic = clang_getDiagnostic(this, index) + try { + val severity = clang_getDiagnosticSeverity(diagnostic) + + val format = clang_formatDiagnostic(diagnostic, clang_defaultDiagnosticDisplayOptions()) + .convertAndDispose() + + val location = clang_getDiagnosticLocation(diagnostic) + + Diagnostic(severity, format, location) + } finally { + clang_disposeDiagnostic(diagnostic) + } + } +} + +internal fun CXTranslationUnit.getCompileErrors(): Sequence = + getDiagnostics().filter { it.isError() }.map { it.format } + +private fun Diagnostic.isError() = (severity == CXDiagnosticSeverity.CXDiagnostic_Error) || + (severity == CXDiagnosticSeverity.CXDiagnostic_Fatal) + +internal fun CXTranslationUnit.hasCompileErrors() = (this.getCompileErrors().firstOrNull() != null) + +internal fun CXTranslationUnit.ensureNoCompileErrors(): CXTranslationUnit { + val firstError = this.getCompileErrors().firstOrNull() ?: return this + throw Error(firstError) +} + +internal typealias CursorVisitor = (cursor: CValue, parent: CValue) -> CXChildVisitResult + +internal fun visitChildren(parent: CValue, visitor: CursorVisitor) { + val visitorStableRef = StableRef.create(visitor) + try { + val clientData = visitorStableRef.asCPointer() + clang_visitChildren(parent, staticCFunction { cursorIt, parentIt, clientDataIt -> + val visitorIt = clientDataIt!!.asStableRef().get() + visitorIt(cursorIt, parentIt) + }, clientData) + } finally { + visitorStableRef.dispose() + } +} + +internal fun visitChildren(translationUnit: CXTranslationUnit, visitor: CursorVisitor) = + visitChildren(clang_getTranslationUnitCursor(translationUnit), visitor) + +internal fun getFields(type: CValue): List> { + val result = mutableListOf>() + val resultStableRef = StableRef.create(result) + try { + val clientData = resultStableRef.asCPointer() + + @Suppress("NAME_SHADOWING") + clang_Type_visitFields(type, staticCFunction { cursor, clientData -> + val result = clientData!!.asStableRef>>().get() + result.add(cursor) + CXVisitorResult.CXVisit_Continue + }, clientData) + + } finally { + resultStableRef.dispose() + } + + return result +} + +fun StructDef.fieldsHaveDefaultAlignment(): Boolean { + fun alignUp(x: Long, alignment: Long): Long = (x + alignment - 1) and (alignment - 1).inv() + + var offset = 0L + this.members.forEach { + when (it) { + is Field -> { + if (alignUp(offset, it.typeAlign) * 8 != it.offset) return false + offset = it.offset / 8 + it.typeSize + } + is BitField -> return false + } + } + + return true +} + +internal fun CValue.hasExpressionChild(): Boolean { + var result = false + + visitChildren(this) { cursor, _ -> + if (clang_isExpression(cursor.kind) != 0) { + result = true + CXChildVisitResult.CXChildVisit_Break + } else { + CXChildVisitResult.CXChildVisit_Continue + } + } + + return result +} + +internal fun List.toNativeStringArray(scope: AutofreeScope): CArrayPointer> { + return scope.allocArray(this.size) { index -> + this.value = this@toNativeStringArray[index].cstr.getPointer(scope) + } +} + +val Compilation.preambleLines: List + get() = this.includes.map { "#include <$it>" } + this.additionalPreambleLines + +internal fun Appendable.appendPreamble(compilation: Compilation) = this.apply { + compilation.preambleLines.forEach { + this.appendLine(it) + } +} + +/** + * Creates temporary source file which includes the library. + */ +internal fun Compilation.createTempSource(): File { + val result = createTempFile(suffix = ".${language.sourceFileExtension}") + result.deleteOnExit() + + result.bufferedWriter().use { writer -> + writer.appendPreamble(this) + } + + return result +} + +fun Compilation.copy( + includes: List = this.includes, + additionalPreambleLines: List = this.additionalPreambleLines, + compilerArgs: List = this.compilerArgs, + language: Language = this.language +): Compilation = CompilationImpl( + includes = includes, + additionalPreambleLines = additionalPreambleLines, + compilerArgs = compilerArgs, + language = language +) + +// Clang-8 crashes when consuming a precompiled header built with -fmodule-map-file argument (see KT-34467). +// We ignore this argument when building a pch to workaround this crash. +fun Compilation.copyWithArgsForPCH(): Compilation = + copy(compilerArgs = compilerArgs.filterNot { it.startsWith("-fmodule-map-file") }) + +data class CompilationImpl( + override val includes: List, + override val additionalPreambleLines: List, + override val compilerArgs: List, + override val language: Language +) : Compilation + +/** + * Precompiles the headers of this library. + * + * @return the library which includes the precompiled header instead of original ones. + */ +fun Compilation.precompileHeaders(): CompilationWithPCH = withIndex { index -> + val options = CXTranslationUnit_ForSerialization + val translationUnit = copyWithArgsForPCH().parse(index, options) + try { + translationUnit.ensureNoCompileErrors() + withPrecompiledHeader(translationUnit) + } finally { + clang_disposeTranslationUnit(translationUnit) + } +} + +internal fun Compilation.withPrecompiledHeader(translationUnit: CXTranslationUnit): CompilationWithPCH { + val precompiledHeader = createTempFile(suffix = ".pch").apply { this.deleteOnExit() } + clang_saveTranslationUnit(translationUnit, precompiledHeader.absolutePath, 0) + + return CompilationWithPCH(this.compilerArgs, precompiledHeader.absolutePath, this.language) +} + +internal fun NativeLibrary.includesDeclaration(cursor: CValue): Boolean { + return if (this.excludeSystemLibs) { + clang_Location_isInSystemHeader(clang_getCursorLocation(cursor)) == 0 + } else { + true + } +} + +internal fun CXTranslationUnit.getErrorLineNumbers(): Sequence = + getDiagnostics().filter { + it.isError() + }.map { + memScoped { + val lineNumberVar = alloc() + clang_getFileLocation(it.location, null, lineNumberVar.ptr, null, null) + lineNumberVar.value + } + } + +/** + * For each list of lines, checks if the code fragment composed from these lines is compilable against given library. + */ +fun List>.mapFragmentIsCompilable(originalLibrary: CompilationWithPCH): List { + val library: CompilationWithPCH = originalLibrary + .copy(compilerArgs = originalLibrary.compilerArgs + "-ferror-limit=0") + + val indicesOfNonCompilable = mutableSetOf() + + val fragmentsToCheck = this.withIndex().toMutableList() + + withIndex(excludeDeclarationsFromPCH = true) { index -> + val sourceFile = library.createTempSource() + val translationUnit = parseTranslationUnit(index, sourceFile, library.compilerArgs, options = 0) + try { + translationUnit.ensureNoCompileErrors() + while (fragmentsToCheck.isNotEmpty()) { + // Combine all fragments to be checked in a single file: + sourceFile.bufferedWriter().use { writer -> + writer.appendPreamble(library) + fragmentsToCheck.forEach { + it.value.forEach { + assert(!it.contains('\n')) + writer.appendLine(it) + } + } + } + + clang_reparseTranslationUnit(translationUnit, 0, null, 0) + val errorLineNumbers = translationUnit.getErrorLineNumbers().toSet() + + // Retain only those fragments that contain compilation error locations: + var lastLineNumber = library.preambleLines.size + fragmentsToCheck.retainAll { + val firstLineNumber = lastLineNumber + 1 + lastLineNumber += it.value.size + (firstLineNumber .. lastLineNumber).any { it in errorLineNumbers } + } + + if (fragmentsToCheck.isNotEmpty()) { + // The first fragment is now known to be non-compilable. + val firstFragment = fragmentsToCheck.removeAt(0) + indicesOfNonCompilable.add(firstFragment.index) + } + + // The remaining fragments was potentially influenced by the first one, + // and thus require to be checked again. + } + } finally { + clang_disposeTranslationUnit(translationUnit) + } + } + + return this.indices.map { it !in indicesOfNonCompilable } +} + +internal interface Indexer { + /** + * Called when entered main file. + */ + fun enteredMainFile(file: CXFile) {} + + /** + * Called when a file gets #included/#imported. + */ + fun ppIncludedFile(info: CXIdxIncludedFileInfo) {} + + /** + * Called when a AST file (PCH or module) gets imported. + */ + fun importedASTFile(info: CXIdxImportedASTFileInfo) {} + + /** + * Called to index a declaration. + */ + fun indexDeclaration(info: CXIdxDeclInfo) {} +} + +internal fun indexTranslationUnit(index: CXIndex, translationUnit: CXTranslationUnit, options: Int, indexer: Indexer) { + val indexerStableRef = StableRef.create(indexer) + try { + val clientData = indexerStableRef.asCPointer() + memScoped { + val indexerCallbacks = alloc().apply { + abortQuery = null + diagnostic = null + enteredMainFile = staticCFunction { clientData, mainFile, _ -> + @Suppress("NAME_SHADOWING") + val indexer = clientData!!.asStableRef().get() + indexer.enteredMainFile(mainFile!!) + // We must ensure only interop types exist in function signature. + @Suppress("USELESS_CAST") + null as CXIdxClientFile? + } + ppIncludedFile = staticCFunction { clientData, info -> + @Suppress("NAME_SHADOWING") + val indexer = clientData!!.asStableRef().get() + indexer.ppIncludedFile(info!!.pointed) + // We must ensure only interop types exist in function signature. + @Suppress("USELESS_CAST") + null as CXIdxClientFile? + } + importedASTFile = staticCFunction { clientData, info -> + @Suppress("NAME_SHADOWING") + val indexer = clientData!!.asStableRef().get() + indexer.importedASTFile(info!!.pointed) + // We must ensure only interop types exist in function signature. + @Suppress("USELESS_CAST") + null as CXIdxClientFile? + } + startedTranslationUnit = null + indexDeclaration = staticCFunction { clientData, info -> + @Suppress("NAME_SHADOWING") + val nativeIndex = clientData!!.asStableRef().get() + nativeIndex.indexDeclaration(info!!.pointed) + } + indexEntityReference = null + } + + val indexAction = clang_IndexAction_create(index) + try { + val result = clang_indexTranslationUnit(indexAction, clientData, + indexerCallbacks.ptr, sizeOf().toInt(), options, translationUnit) + + if (result != 0) { + throw Error("clang_indexTranslationUnit returned $result") + } + } finally { + clang_IndexAction_dispose(indexAction) + } + } + } finally { + indexerStableRef.dispose() + } +} + +internal class ModulesMap( + val compilation: Compilation, + val translationUnit: CXTranslationUnit +) : Closeable { + + private val modularCompilation: ModularCompilation + private val index: CXIndex + private val translationUnitWithModules: CXTranslationUnit + + private val arena = Arena() + + private inline fun T.toBeDisposedWith(crossinline block: (T) -> Unit): T = apply { + arena.defer { block(this) } + } + + override fun close() { + arena.clear() + } + + init { + try { + modularCompilation = ModularCompilation(compilation) + .toBeDisposedWith { it.dispose() } + + index = clang_createIndex(0, 0)!! + .toBeDisposedWith { clang_disposeIndex(it) } + + translationUnitWithModules = modularCompilation.parse(index) + .toBeDisposedWith { clang_disposeTranslationUnit(it) } + + translationUnitWithModules.ensureNoCompileErrors() + + } catch (e: Throwable) { + this.close() + throw e + } + } + + data class Module(private val cxModule: CXModule) + + fun getModule(file: CXFile): Module? { + // `file` is bound to `translationUnit`, however `translationUnitWithModules` is used to access modules. + // Find the corresponding file in `translationUnitWithModules`: + val fileInTuWithModules = + clang_getFile(translationUnitWithModules, clang_getFileName(file).convertAndDispose())!! + + return clang_getModuleForFile(translationUnitWithModules, fileInTuWithModules)?.let { Module(it) } + } +} + +internal fun getHeaderId(library: NativeLibrary, header: CXFile?): HeaderId { + if (header == null) { + return HeaderId("builtins") + } + + val filePath = header.path + return library.headerToIdMapper.getHeaderId(filePath) +} + +internal fun getFilteredHeaders( + nativeIndex: NativeIndexImpl, + index: CXIndex, + translationUnit: CXTranslationUnit +): Set = getHeaders(nativeIndex.library, index, translationUnit).ownHeaders + +class NativeLibraryHeaders
(val ownHeaders: Set
, val importedHeaders: Set
) + +internal fun getHeaders( + library: NativeLibrary, + index: CXIndex, + translationUnit: CXTranslationUnit +): NativeLibraryHeaders { + val ownHeaders = mutableSetOf() + val allHeaders = mutableSetOf(null) + + val filter = library.headerFilter + + when (filter) { + is NativeLibraryHeaderFilter.NameBased -> + filterHeadersByName(library, filter, index, translationUnit, ownHeaders, allHeaders) + + is NativeLibraryHeaderFilter.Predefined -> + filterHeadersByPredefined(filter, index, translationUnit, ownHeaders, allHeaders) + } + + ownHeaders.removeAll { library.headerExclusionPolicy.excludeAll(getHeaderId(library, it)) } + + return NativeLibraryHeaders(ownHeaders, allHeaders - ownHeaders) +} + +private fun filterHeadersByName( + compilation: Compilation, + filter: NativeLibraryHeaderFilter.NameBased, + index: CXIndex, + translationUnit: CXTranslationUnit, + ownHeaders: MutableSet, + allHeaders: MutableSet +) { + val topLevelFiles = mutableListOf() + var mainFile: CXFile? = null + + indexTranslationUnit(index, translationUnit, 0, object : Indexer { + val headerToName = mutableMapOf() + // The *name* of the header here is the path relative to the include path element., e.g. `curl/curl.h`. + + override fun enteredMainFile(file: CXFile) { + mainFile = file + allHeaders += file + } + + override fun ppIncludedFile(info: CXIdxIncludedFileInfo) { + val includeLocation = clang_indexLoc_getCXSourceLocation(info.hashLoc.readValue()) + val file = info.file!! + + allHeaders += file + + if (clang_Location_isFromMainFile(includeLocation) != 0) { + topLevelFiles.add(file) + } + + val name = info.filename!!.toKString() + val headerName = if (info.isAngled != 0) { + // If the header is included with `#include <$name>`, then `name` is probably + // the path relative to the include path element. + name + } else { + // If it is included with `#include "$name"`, then `name` can also be the path relative to the includer. + val includerFile = includeLocation.getContainingFile()!! + val includerName = headerToName[includerFile] ?: "" + val includerPath = includerFile.path + + if (clang_getFile(translationUnit, Paths.get(includerPath).resolveSibling(name).toString()) == file) { + // included file is accessible from the includer by `name` used as relative path, so + // `name` seems to be relative to the includer: + Paths.get(includerName).resolveSibling(name).normalize().toString() + } else { + name + } + } + + headerToName[file] = headerName + if (!filter.policy.excludeUnused(headerName)) { + ownHeaders.add(file) + } + } + }) + + if (filter.excludeDepdendentModules) { + ModulesMap(compilation, translationUnit).use { modulesMap -> + val topLevelModules = topLevelFiles.map { modulesMap.getModule(it) }.toSet() + ownHeaders.removeAll { + val module = modulesMap.getModule(it!!) + module !in topLevelModules + } + // Note: if some of the top-level headers don't belong to modules, + // then all non-modular headers are included. + } + } else { + if (!filter.policy.excludeUnused(headerName = null)) { + // Builtins. + ownHeaders.add(null) + } + } + + ownHeaders.add(mainFile!!) +} + +private fun filterHeadersByPredefined( + filter: NativeLibraryHeaderFilter.Predefined, + index: CXIndex, + translationUnit: CXTranslationUnit, + ownHeaders: MutableSet, + allHeaders: MutableSet +) { + // Note: suboptimal but simple. + indexTranslationUnit(index, translationUnit, 0, object : Indexer { + override fun ppIncludedFile(info: CXIdxIncludedFileInfo) { + val file = info.file + allHeaders += file + if (file?.canonicalPath in filter.headers) { + ownHeaders += file + } + } + }) +} + +fun NativeLibrary.getHeaderPaths(): NativeLibraryHeaders { + withIndex { index -> + val translationUnit = + this.parse(index, options = CXTranslationUnit_DetailedPreprocessingRecord).ensureNoCompileErrors() + try { + + fun getPath(file: CXFile?) = if (file == null) "" else file.canonicalPath + + val headers = getHeaders(this, index, translationUnit) + return NativeLibraryHeaders( + headers.ownHeaders.map(::getPath).toSet(), + headers.importedHeaders.map(::getPath).toSet() + ) + } finally { + clang_disposeTranslationUnit(translationUnit) + } + } +} + +fun ObjCMethod.replaces(other: ObjCMethod): Boolean = + this.isClass == other.isClass && this.selector == other.selector + +fun ObjCProperty.replaces(other: ObjCProperty): Boolean = + this.getter.replaces(other.getter) + +fun File.sha256(): String { + val digest = MessageDigest.getInstance("SHA-256") + DigestInputStream(this.inputStream(), digest).use { dis -> + val buffer = ByteArray(8192) + // Read all bytes: + while (dis.read(buffer, 0, buffer.size) != -1) {} + } + // Convert to hex: + return digest.digest().joinToString("") { + Integer.toHexString((it.toInt() and 0xff) + 0x100).substring(1) + } +} + +fun headerContentsHash(filePath: String) = File(filePath).sha256() + +internal fun CValue.getContainingFile(): CXFile? = memScoped { + val fileVar = alloc() + clang_getFileLocation(this@getContainingFile, fileVar.ptr, null, null, null) + fileVar.value +} + +@JvmName("getFileContainingCursor") +internal fun getContainingFile(cursor: CValue): CXFile? { + return clang_getCursorLocation(cursor).getContainingFile() +} + +internal val CXFile.path: String get() = clang_getFileName(this).convertAndDispose() +internal val CXFile.canonicalPath: String get() = File(this.path).canonicalPath + +private fun createVfsOverlayFileContents(virtualPathToReal: Map): ByteArray { + val overlay = clang_VirtualFileOverlay_create(0) + + try { + fun addFileMapping(realPath: Path, virtualPath: Path) { + clang_VirtualFileOverlay_addFileMapping( + overlay, + virtualPath = virtualPath.toAbsolutePath().toString(), + realPath = realPath.toAbsolutePath().toString() + ) + } + + virtualPathToReal.forEach { virtualPath, realPath -> + if (Files.isDirectory(realPath)) { + realPath.toFile().walkTopDown().forEach { + if (!it.isDirectory) { + addFileMapping( + realPath = it.toPath(), + virtualPath = virtualPath.resolve(realPath.relativize(it.toPath())) + ) + } + } + } else { + addFileMapping(realPath = realPath, virtualPath = virtualPath) + } + } + + memScoped { + val bufferVar = alloc>().apply { value = null } + val bufferSizeVar = alloc() + + val res = clang_VirtualFileOverlay_writeToBuffer(overlay, 0, bufferVar.ptr, bufferSizeVar.ptr) + if (res != CXErrorCode.CXError_Success) { + // TODO: shall we free the buffer in this case? + error(res) + } + + return bufferVar.value!!.readBytes(bufferSizeVar.value) + } + } finally { + clang_VirtualFileOverlay_dispose(overlay) + } +} + +fun createVfsOverlayFile(virtualPathToReal: Map): Path { + val bytes = createVfsOverlayFileContents(virtualPathToReal) + + return createTempFile(prefix = "konan", suffix = ".vfsoverlay").apply { + bufferedWriter().use { + writeBytes(bytes) + } + deleteOnExit() + }.toPath() +} + +tailrec fun Type.unwrapTypedefs(): Type = if (this is Typedef) { + this.def.aliased.unwrapTypedefs() +} else { + this +} + +fun Type.canonicalIsPointerToChar(): Boolean { + val unwrappedType = this.unwrapTypedefs() + return unwrappedType is PointerType && unwrappedType.pointeeType.unwrapTypedefs() == CharType +} + +internal interface Disposable { + fun dispose() +} + +internal inline fun T.use(block: (T) -> R): R = try { + block(this) +} finally { + this.dispose() +} diff --git a/kotlin-native/Interop/Indexer/src/nativeInteropStubs/cpp/disable-abi-checks.cpp b/kotlin-native/Interop/Indexer/src/nativeInteropStubs/cpp/disable-abi-checks.cpp new file mode 100644 index 00000000000..89e4142b16d --- /dev/null +++ b/kotlin-native/Interop/Indexer/src/nativeInteropStubs/cpp/disable-abi-checks.cpp @@ -0,0 +1,9 @@ +#ifdef __linux__ +namespace llvm { +/** + * http://lists.llvm.org/pipermail/llvm-dev/2017-January/109621.html + * We can't rebuild llvm, but we can define symbol missed in llvm build. + */ +int DisableABIBreakingChecks = 1; +} +#endif diff --git a/kotlin-native/Interop/Indexer/src/nativeInteropStubs/cpp/signalChaining.cpp b/kotlin-native/Interop/Indexer/src/nativeInteropStubs/cpp/signalChaining.cpp new file mode 100644 index 00000000000..5e5a10ac0d5 --- /dev/null +++ b/kotlin-native/Interop/Indexer/src/nativeInteropStubs/cpp/signalChaining.cpp @@ -0,0 +1,110 @@ +#if defined(__linux__) || defined(__APPLE__) +#include +#if defined(__linux__) +#include +#endif +#include +#include + +extern "C" void clang_toggleCrashRecovery(unsigned isEnabled); + +constexpr int signalsToCover[] = { + SIGILL, SIGFPE, SIGSEGV, SIGBUS, SIGUSR1, SIGUSR2 +}; + +struct { + void* handler; + bool isSigaction; +} oldSignalHandlers[sizeof(signalsToCover)/sizeof(signalsToCover[0])] = { 0 }; + +static int mySigaction(int sig, const struct sigaction *act, struct sigaction * oact) { + for (int i = 0; i < sizeof(signalsToCover)/sizeof(signalsToCover[0]); i++) { + if (sig == signalsToCover[i]) return 0; + } + return sigaction(sig, act, oact); +} + +static void checkSignalChaining() { + struct sigaction oact; + clang_toggleCrashRecovery(1); + for (int i = 0; i < sizeof(signalsToCover)/sizeof(signalsToCover[0]); i++) { + int sig = signalsToCover[i]; + if (sigaction(sig, nullptr, &oact) != 0) continue; + if ((oact.sa_flags & SA_SIGINFO) == 0) { + if (oldSignalHandlers[i].isSigaction) { + fprintf(stderr, "ERROR: improperly changed signal flag for %d\n", sig); + continue; + } + if (oldSignalHandlers[i].handler != (void*)oact.sa_handler) { + fprintf(stderr, "ERROR: improperly changed signal handler for %d\n", sig); + continue; + } + } else { + if (!oldSignalHandlers[i].isSigaction) { + fprintf(stderr, "ERROR: improperly changed signal flag for %d\n", sig); + continue; + } + void* action = (void*)oact.sa_sigaction; + if (oldSignalHandlers[i].handler != action) { + Dl_info info; + const char* soname = ""; + if (dladdr(action, &info) != 0) { + soname = info.dli_fname; + } + fprintf(stderr, "ERROR: changed signal handler for %d from %p to %p: coming from %s\n", + sig, oldSignalHandlers[i].handler, action, soname); + } + } + } + clang_toggleCrashRecovery(0); +} + +__attribute__((constructor)) +static void initSignalChaining() { + void** base = 0; + Dl_info info; + + for (int i = 0; i < sizeof(signalsToCover)/sizeof(signalsToCover[0]); i++) { + struct sigaction oact; + int sig = signalsToCover[i]; + if (sigaction(signalsToCover[i], nullptr, &oact) == 0) { + if ((oact.sa_flags & SA_SIGINFO) == 0) { + oldSignalHandlers[i] = {(void*)oact.sa_handler, false}; + } else { + oldSignalHandlers[i] = {(void*)oact.sa_sigaction, true}; + } + } + } + + + if (dladdr((void*)&clang_toggleCrashRecovery, &info) == 0) return; + base = (void**)info.dli_fbase; + + // Force resolving of lazy symbols. + clang_toggleCrashRecovery(1); + clang_toggleCrashRecovery(0); + + // And then patch GOT. +#if defined(__linux__) + { + // On Linux we have to be a bit tricky, as there's unmapped gap between code and GOT. + struct link_map* linkmap = 0; + if (dladdr1((void*)&clang_toggleCrashRecovery, &info, (void**)&linkmap, RTLD_DL_LINKMAP) == 0) return; + base = (void**)linkmap->l_ld; + } +#endif + for (int index = 0, patched = 0; patched < 1; index++) { + void* value = base[index]; + if (value == &sigaction) { + base[index] = (void*)mySigaction; + patched++; + } + if (value == mySigaction) { + patched++; + } + } + + checkSignalChaining(); +} + +#endif // defined(__linux__) || defined(__APPLE__) diff --git a/kotlin-native/Interop/JsRuntime/build.gradle b/kotlin-native/Interop/JsRuntime/build.gradle new file mode 100644 index 00000000000..08397f3d8ee --- /dev/null +++ b/kotlin-native/Interop/JsRuntime/build.gradle @@ -0,0 +1,20 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +buildscript { + apply from: "$rootDir/gradle/kotlinGradlePlugin.gradle" +} + diff --git a/kotlin-native/Interop/JsRuntime/src/main/js/jsinterop.js b/kotlin-native/Interop/JsRuntime/src/main/js/jsinterop.js new file mode 100644 index 00000000000..050b4a7bcf7 --- /dev/null +++ b/kotlin-native/Interop/JsRuntime/src/main/js/jsinterop.js @@ -0,0 +1,97 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +konan.libraries.push ({ + arenas: new Map(), + nextArena: 0, + Konan_js_allocateArena: function (array) { + var index = konan_dependencies.env.nextArena++; + konan_dependencies.env.arenas.set(index, array || []); + return index; + + }, + Konan_js_freeArena: function(arenaIndex) { + var arena = konan_dependencies.env.arenas.get(arenaIndex); + arena.forEach(function(element, index) { + arena[index] = null; + }); + konan_dependencies.env.arenas.delete(arenaIndex); + }, + Konan_js_pushIntToArena: function (arenaIndex, value) { + var arena = konan_dependencies.env.arenas.get(arenaIndex); + arena.push(value); + return arena.length - 1; + }, + Konan_js_addObjectToArena: function (arenaIndex, object) { + var arena = konan_dependencies.env.arenas.get(arenaIndex); + arena.push(object); + return arena.length - 1; + }, + Konan_js_wrapLambda: function (functionArenaIndex, index) { + return (function () { + var functionArena = konan_dependencies.env.arenas.get(functionArenaIndex); + + // convert Arguments to an array + // to be provided by launcher.js + var argumentArenaIndex = konan_dependencies.env.Konan_js_allocateArena(Array.prototype.slice.call(arguments)); + + var resultIndex = instance.exports.Konan_js_runLambda(index, argumentArenaIndex, arguments.length); + var result = kotlinObject(argumentArenaIndex, resultIndex); + konan_dependencies.env.Konan_js_freeArena(argumentArenaIndex); + + return result; + }); + }, + Konan_js_getInt: function(arenaIndex, objIndex, propertyNamePtr, propertyNameLength) { + // TODO: The toUTF16String() is to be resolved by launcher.js runtime. + var property = toUTF16String(propertyNamePtr, propertyNameLength); + var value = kotlinObject(arenaIndex, objIndex)[property]; + return value; + }, + Konan_js_getProperty: function(arenaIndex, objIndex, propertyNamePtr, propertyNameLength) { + // TODO: The toUTF16String() is to be resolved by launcher.js runtime. + var property = toUTF16String(propertyNamePtr, propertyNameLength); + var arena = konan_dependencies.env.arenas.get(arenaIndex); + var value = arena[objIndex][property]; + arena.push(value); + return arena.length - 1; + }, + Konan_js_setFunction: function (arena, obj, propertyName, propertyNameLength, func) { + var name = toUTF16String(propertyName, propertyNameLength); + kotlinObject(arena, obj)[name] = konan_dependencies.env.Konan_js_wrapLambda(arena, func); + }, + + Konan_js_setString: function (arena, obj, propertyName, propertyNameLength, stringPtr, stringLength) { + var name = toUTF16String(propertyName, propertyNameLength); + var string = toUTF16String(stringPtr, stringLength); + kotlinObject(arena, obj)[name] = string; + }, +}); + +// TODO: This is just a shorthand notation. +function kotlinObject(arenaIndex, objectIndex) { + var arena = konan_dependencies.env.arenas.get(arenaIndex); + if (typeof arena == "undefined") { + console.log("No arena index " + arenaIndex + "for object" + objectIndex); + console.trace() + } + return arena[objectIndex] +} + +function toArena(arenaIndex, object) { + return konan_dependencies.env.Konan_js_addObjectToArena(arenaIndex, object); +} + diff --git a/kotlin-native/Interop/JsRuntime/src/main/kotlin/jsinterop.kt b/kotlin-native/Interop/JsRuntime/src/main/kotlin/jsinterop.kt new file mode 100644 index 00000000000..3c271ef4793 --- /dev/null +++ b/kotlin-native/Interop/JsRuntime/src/main/kotlin/jsinterop.kt @@ -0,0 +1,143 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package kotlinx.wasm.jsinterop + +import kotlin.native.* +import kotlin.native.internal.ExportForCppRuntime +import kotlinx.cinterop.* + +typealias Arena = Int +typealias Object = Int +typealias Pointer = Int + +/** + * @Retain annotation is required to preserve functions from internalization and DCE. + */ +@RetainForTarget("wasm32") +@SymbolName("Konan_js_allocateArena") +external public fun allocateArena(): Arena + +@RetainForTarget("wasm32") +@SymbolName("Konan_js_freeArena") +external public fun freeArena(arena: Arena) + +@RetainForTarget("wasm32") +@SymbolName("Konan_js_pushIntToArena") +external public fun pushIntToArena(arena: Arena, value: Int) + +const val upperWord = 0xffffffff.toLong() shl 32 + +@ExportForCppRuntime +fun doubleUpper(value: Double): Int = + ((value.toBits() and upperWord) ushr 32) .toInt() + +@ExportForCppRuntime +fun doubleLower(value: Double): Int = + (value.toBits() and 0x00000000ffffffff) .toInt() + +@RetainForTarget("wasm32") +@SymbolName("ReturnSlot_getDouble") +external public fun ReturnSlot_getDouble(): Double + +@RetainForTarget("wasm32") +@SymbolName("Kotlin_String_utf16pointer") +external public fun stringPointer(message: String): Pointer + +@RetainForTarget("wasm32") +@SymbolName("Kotlin_String_utf16length") +external public fun stringLengthBytes(message: String): Int + +typealias KtFunction = ((ArrayList)->R) + +fun wrapFunction(func: KtFunction): Int { + val ptr: Long = StableRef.create(func).asCPointer().toLong() + return ptr.toInt() // TODO: LP64 unsafe. +} + +@RetainForTarget("wasm32") +@ExportForCppRuntime("Konan_js_runLambda") +fun runLambda(pointer: Int, argumentsArena: Arena, argumentsArenaSize: Int): Int { + val arguments = arrayListOf() + for (i in 0 until argumentsArenaSize) { + arguments.add(JsValue(argumentsArena, i)); + } + val previousArena = ArenaManager.currentArena + ArenaManager.currentArena = argumentsArena + // TODO: LP64 unsafe: wasm32 passes Int, not Long. + val func = pointer.toLong().toCPointer()!!.asStableRef>().get() + val result = func(arguments) + + ArenaManager.currentArena = previousArena + return result.index +} + +open class JsValue(val arena: Arena, val index: Object) { + fun getInt(property: String): Int { + return getInt(ArenaManager.currentArena, index, stringPointer(property), stringLengthBytes(property)) + } + fun getProperty(property: String): JsValue { + return JsValue(ArenaManager.currentArena, Konan_js_getProperty(ArenaManager.currentArena, index, stringPointer(property), stringLengthBytes(property))) + } +} + +open class JsArray(arena: Arena, index: Object): JsValue(arena, index) { + constructor(jsValue: JsValue): this(jsValue.arena, jsValue.index) + operator fun get(index: Int): JsValue { + // TODO: we could pass an integer index to index arrays. + return getProperty(index.toString()) + } + val size: Int + get() = this.getInt("length") +} + +@RetainForTarget("wasm32") +@SymbolName("Konan_js_getInt") +external public fun getInt(arena: Arena, obj: Object, propertyPtr: Pointer, propertyLen: Int): Int; + +@RetainForTarget("wasm32") +@SymbolName("Konan_js_getProperty") +external public fun Konan_js_getProperty(arena: Arena, obj: Object, propertyPtr: Pointer, propertyLen: Int): Int; + +@RetainForTarget("wasm32") +@SymbolName("Konan_js_setFunction") +external public fun setFunction(arena: Arena, obj: Object, propertyName: Pointer, propertyLength: Int , function: Int) + +@RetainForTarget("wasm32") +@SymbolName("Konan_js_setString") +external public fun setString(arena: Arena, obj: Object, propertyName: Pointer, propertyLength: Int, stringPtr: Pointer, stringLength: Int ) + +fun setter(obj: JsValue, property: String, string: String) { + setString(obj.arena, obj.index, stringPointer(property), stringLengthBytes(property), stringPointer(string), stringLengthBytes(string)) +} + +fun setter(obj: JsValue, property: String, lambda: KtFunction) { + val pointer = wrapFunction(lambda); + setFunction(obj.arena, obj.index, stringPointer(property), stringLengthBytes(property), pointer) +} + +fun JsValue.setter(property: String, lambda: KtFunction) { + setter(this, property, lambda) +} + +fun JsValue.setter(property: String, string: String) { + setter(this, property, string) +} + +object ArenaManager { + val globalArena = allocateArena() + var currentArena = globalArena +} \ No newline at end of file diff --git a/kotlin-native/Interop/README.md b/kotlin-native/Interop/README.md new file mode 100644 index 00000000000..085a0bc1015 --- /dev/null +++ b/kotlin-native/Interop/README.md @@ -0,0 +1,18 @@ +# Kotlin-native interop + +## Usage + +Create file `../gradle.properties` with contents: + + llvmInstallPath=/path/to/llvm + +Create a Gradle subproject somewhere under `../`, using `../InteropExample` as a template. + +To generate the interop stubs and libraries and build all sources you can run +the following command from `../`: + + ./gradlew InteropExample:build + +To run the example (if 'application' plugin is enabled): + + ./gradlew InteropExample:run diff --git a/kotlin-native/Interop/Runtime/build.gradle b/kotlin-native/Interop/Runtime/build.gradle new file mode 100644 index 00000000000..273e3b2e962 --- /dev/null +++ b/kotlin-native/Interop/Runtime/build.gradle @@ -0,0 +1,92 @@ +/* + * Copyright 2010-2017 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +apply plugin: 'kotlin' +apply plugin: 'c' + +buildscript { + ext.rootBuildDirectory = file('../..') + + apply from: "$rootBuildDirectory/gradle/kotlinGradlePlugin.gradle" + + dependencies { + classpath "org.jetbrains.kotlin:kotlin-stdlib:$kotlinVersion" + classpath "org.jetbrains.kotlin:kotlin-native-shared:$konanVersion" + } +} +import org.jetbrains.kotlin.konan.target.ClangArgs + + +model { + components { + callbacks(NativeLibrarySpec) { + sources.c.source { + srcDir 'src/callbacks/c' + include '**/*.c' + } + binaries.all { + def host = rootProject.ext.hostName + + def hostLibffiDir = rootProject.ext.get("${host}LibffiDir") + + cCompiler.args hostPlatform.clang.hostCompilerArgsForJni + cCompiler.args "-I$hostLibffiDir/include" + + linker.args "$hostLibffiDir/lib/libffi.a" + } + } + } + + toolChains { + clang(Clang) { + eachPlatform { + cCompiler.withArguments(ClangArgs.&filterGradleNativeSoftwareFlags) + } + } + } +} + +repositories { + maven { + url buildKotlinCompilerRepo + } +} + +dependencies { + compile project(":utilities:basic-utils") + compile "org.jetbrains.kotlin:kotlin-stdlib:$kotlinVersion" + compile "org.jetbrains.kotlin:kotlin-reflect:$kotlinVersion" +} + +sourceSets.main.kotlin.srcDirs += "src/jvm/kotlin" + +compileKotlin { + kotlinOptions { + freeCompilerArgs = ['-Xuse-experimental=kotlin.ExperimentalUnsignedTypes', '-Xuse-experimental=kotlin.Experimental', + '-Xopt-in=kotlin.RequiresOptIn', "-XXLanguage:+InlineClasses"] + allWarningsAsErrors=true + } +} + + +task nativelibs(type: Copy) { + dependsOn 'callbacksSharedLibrary' + + from "$buildDir/libs/callbacks/shared/" + into "$buildDir/nativelibs/" +} + +classes.dependsOn nativelibs diff --git a/kotlin-native/Interop/Runtime/src/callbacks/c/callbacks.c b/kotlin-native/Interop/Runtime/src/callbacks/c/callbacks.c new file mode 100644 index 00000000000..d187d71a426 --- /dev/null +++ b/kotlin-native/Interop/Runtime/src/callbacks/c/callbacks.c @@ -0,0 +1,243 @@ +#include +#include +#include +#include +#include + +/* + * Class: kotlinx_cinterop_JvmCallbacksKt + * Method: ffiTypeVoid + * Signature: ()J + */ +JNIEXPORT jlong JNICALL Java_kotlinx_cinterop_JvmCallbacksKt_ffiTypeVoid(JNIEnv *env, jclass cls) { + return (jlong) &ffi_type_void; +} + +/* + * Class: kotlinx_cinterop_JvmCallbacksKt + * Method: ffiTypeUInt8 + * Signature: ()J + */ +JNIEXPORT jlong JNICALL Java_kotlinx_cinterop_JvmCallbacksKt_ffiTypeUInt8(JNIEnv *env, jclass cls) { + return (jlong) &ffi_type_uint8; +} + +/* + * Class: kotlinx_cinterop_JvmCallbacksKt + * Method: ffiTypeSInt8 + * Signature: ()J + */ +JNIEXPORT jlong JNICALL Java_kotlinx_cinterop_JvmCallbacksKt_ffiTypeSInt8(JNIEnv *env, jclass cls) { + return (jlong) &ffi_type_sint8; +} + +/* + * Class: kotlinx_cinterop_JvmCallbacksKt + * Method: ffiTypeUInt16 + * Signature: ()J + */ +JNIEXPORT jlong JNICALL Java_kotlinx_cinterop_JvmCallbacksKt_ffiTypeUInt16(JNIEnv *env, jclass cls) { + return (jlong) &ffi_type_uint16; +} + +/* + * Class: kotlinx_cinterop_JvmCallbacksKt + * Method: ffiTypeSInt16 + * Signature: ()J + */ +JNIEXPORT jlong JNICALL Java_kotlinx_cinterop_JvmCallbacksKt_ffiTypeSInt16(JNIEnv *env, jclass cls) { + return (jlong) &ffi_type_sint16; +} + +/* + * Class: kotlinx_cinterop_JvmCallbacksKt + * Method: ffiTypeUInt32 + * Signature: ()J + */ +JNIEXPORT jlong JNICALL Java_kotlinx_cinterop_JvmCallbacksKt_ffiTypeUInt32(JNIEnv *env, jclass cls) { + return (jlong) &ffi_type_uint32; +} + +/* + * Class: kotlinx_cinterop_JvmCallbacksKt + * Method: ffiTypeSInt32 + * Signature: ()J + */ +JNIEXPORT jlong JNICALL Java_kotlinx_cinterop_JvmCallbacksKt_ffiTypeSInt32(JNIEnv *env, jclass cls) { + return (jlong) &ffi_type_sint32; +} + +/* + * Class: kotlinx_cinterop_JvmCallbacksKt + * Method: ffiTypeUInt64 + * Signature: ()J + */ +JNIEXPORT jlong JNICALL Java_kotlinx_cinterop_JvmCallbacksKt_ffiTypeUInt64(JNIEnv *env, jclass cls) { + return (jlong) &ffi_type_uint64; +} + +/* + * Class: kotlinx_cinterop_JvmCallbacksKt + * Method: ffiTypeSInt64 + * Signature: ()J + */ +JNIEXPORT jlong JNICALL Java_kotlinx_cinterop_JvmCallbacksKt_ffiTypeSInt64(JNIEnv *env, jclass cls) { + return (jlong) &ffi_type_sint64; +} + +/* + * Class: kotlinx_cinterop_JvmCallbacksKt + * Method: ffiTypePointer + * Signature: ()J + */ +JNIEXPORT jlong JNICALL Java_kotlinx_cinterop_JvmCallbacksKt_ffiTypePointer(JNIEnv *env, jclass cls) { + return (jlong) &ffi_type_pointer; +} + +/* + * Class: kotlinx_cinterop_JvmCallbacksKt + * Method: ffiTypeStruct0 + * Signature: (J)J + */ +JNIEXPORT jlong JNICALL Java_kotlinx_cinterop_JvmCallbacksKt_ffiTypeStruct0(JNIEnv *env, jclass cls, jlong elements) { + ffi_type* res = malloc(sizeof(ffi_type)); + if (res != NULL) { + res->size = 0; + res->alignment = 0; + res->elements = (ffi_type**) elements; + res->type = FFI_TYPE_STRUCT; + } + return (jlong) res; +} + +/* + * Class: kotlinx_cinterop_JvmCallbacksKt + * Method: ffiCreateCif0 + * Signature: (IJJ)J + */ +JNIEXPORT jlong JNICALL Java_kotlinx_cinterop_JvmCallbacksKt_ffiCreateCif0(JNIEnv *env, jclass cls, jint nArgs, jlong rType, jlong argTypes) { + ffi_cif* res = malloc(sizeof(ffi_cif)); + if (res != NULL) { + ffi_status status = ffi_prep_cif(res, FFI_DEFAULT_ABI, nArgs, (ffi_type*)rType, (ffi_type**)argTypes); + if (status != FFI_OK) { + if (status == FFI_BAD_TYPEDEF) { + return -(jlong)1; + } else if (status == FFI_BAD_ABI) { + return -(jlong)2; + } else { + return -(jlong)3; + } + } + } + return (jlong) res; +} + +static JavaVM *vm = NULL; + +// Returns the JNI env which can be used by the caller. +// If current thread is not attached to JVM, then it gets attached as daemon. +static JNIEnv* getCurrentEnv() { + JNIEnv* env; + assert(vm != NULL); + jint res = (*vm)->GetEnv(vm, (void**)&env, JNI_VERSION_1_1); + if (res != JNI_OK) { + assert(res == JNI_EDETACHED); + res = (*vm)->AttachCurrentThreadAsDaemon(vm, (void**)&env, NULL); + assert(res == JNI_OK); + } + return env; +} + +JNIEXPORT jint JNICALL JNI_OnLoad(JavaVM *vm_, void *reserved) { + vm = vm_; + return JNI_VERSION_1_1; +} + +// Checks for pending exception. If there is one, describes it and terminates the process. +static void checkException(JNIEnv *env) { + if ((*env)->ExceptionCheck(env)) { + (*env)->ExceptionDescribe(env); + abort(); + } +} + +static void ffi_fun(ffi_cif *cif, void *ret, void **args, void *user_data) { + JNIEnv* env = getCurrentEnv(); + + static jmethodID acceptFun = NULL; + static jclass cls = NULL; + if (acceptFun == NULL) { + // Note: in some cases [FindClass] below may use a classloader different from the one loaded interop classes, + // so stick to JVM-provided class: + jclass clsLocal = (*env)->FindClass(env, "java/util/function/LongConsumer"); + checkException(env); + assert(clsLocal != NULL); + + cls = (jclass) (*env)->NewGlobalRef(env, clsLocal); + checkException(env); + assert(cls != NULL); + + acceptFun = (*env)->GetMethodID(env, cls, "accept", "(J)V"); + checkException(env); + assert(acceptFun != NULL); + } + + jlong retAndArgs[2] = { (jlong)ret, (jlong)args }; // Unpacked in [ffiClosureImpl]. + (*env)->CallVoidMethod(env, (jobject) user_data, acceptFun, (jlong)(intptr_t)&retAndArgs[0]); + checkException(env); +} + +/* + * Class: kotlinx_cinterop_JvmCallbacksKt + * Method: ffiCreateClosure0 + * Signature: (JLjava/lang/Object;)J + */ +JNIEXPORT jlong JNICALL Java_kotlinx_cinterop_JvmCallbacksKt_ffiCreateClosure0(JNIEnv *env, jclass cls, jlong ffiCif, jobject userData) { + jobject userDataGlobalRef = (*env)->NewGlobalRef(env, userData); + if (userDataGlobalRef == NULL) { + return (jlong)0; + } + + assert(sizeof(jobject) == sizeof(void*)); // TODO: check statically + void* userDataPtr = (void*) userDataGlobalRef; + + void* res; + ffi_closure *closure = ffi_closure_alloc(sizeof(ffi_closure), &res); + if (closure == NULL) { + return (jlong)0; + } + ffi_status status = ffi_prep_closure_loc(closure, (ffi_cif*)ffiCif, ffi_fun, userDataPtr, res); + if (status != FFI_OK) { + return -(jlong)1; + } + + return (jlong) res; +} + +/* + * Class: kotlinx_cinterop_JvmCallbacksKt + * Method: newGlobalRef + * Signature: (Ljava/lang/Object;)J + */ +JNIEXPORT jlong JNICALL Java_kotlinx_cinterop_JvmCallbacksKt_newGlobalRef(JNIEnv *env, jclass cls, jobject obj) { + jobject res = (*env)->NewGlobalRef(env, obj); + return (jlong) res; +} + +/* + * Class: kotlinx_cinterop_JvmCallbacksKt + * Method: derefGlobalRef + * Signature: (J)Ljava/lang/Object; + */ +JNIEXPORT jobject JNICALL Java_kotlinx_cinterop_JvmCallbacksKt_derefGlobalRef(JNIEnv *env, jclass cls, jlong ref) { + return (jobject) ref; +} + +/* + * Class: kotlinx_cinterop_JvmCallbacksKt + * Method: deleteGlobalRef + * Signature: (J)V + */ +JNIEXPORT void JNICALL Java_kotlinx_cinterop_JvmCallbacksKt_deleteGlobalRef(JNIEnv *env, jclass cls, jlong ref) { + (*env)->DeleteGlobalRef(env, (jobject) ref); +} diff --git a/kotlin-native/Interop/Runtime/src/jvm/kotlin/kotlinx/cinterop/JvmCallbacks.kt b/kotlin-native/Interop/Runtime/src/jvm/kotlin/kotlinx/cinterop/JvmCallbacks.kt new file mode 100644 index 00000000000..fd01e1fedee --- /dev/null +++ b/kotlin-native/Interop/Runtime/src/jvm/kotlin/kotlinx/cinterop/JvmCallbacks.kt @@ -0,0 +1,461 @@ +/* + * Copyright 2010-2017 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package kotlinx.cinterop + +import java.util.concurrent.ConcurrentHashMap +import java.util.function.LongConsumer +import kotlin.reflect.KClass +import kotlin.reflect.KFunction +import kotlin.reflect.KType +import kotlin.reflect.full.companionObjectInstance +import kotlin.reflect.full.declaredMemberProperties +import kotlin.reflect.full.isSubclassOf +import kotlin.reflect.jvm.reflect + +internal fun createStablePointer(any: Any): COpaquePointer = newGlobalRef(any).toCPointer()!! + +internal fun disposeStablePointer(pointer: COpaquePointer) = deleteGlobalRef(pointer.toLong()) + +@PublishedApi +internal fun derefStablePointer(pointer: COpaquePointer): Any = derefGlobalRef(pointer.toLong()) + +private fun getFieldCType(type: KType): CType<*> { + val classifier = type.classifier + if (classifier is KClass<*> && classifier.isSubclassOf(CStructVar::class)) { + return getStructCType(classifier) + } + + return getArgOrRetValCType(type) +} + +private fun getVariableCType(type: KType): CType<*>? { + val classifier = type.classifier + return when (classifier) { + !is KClass<*> -> null + ByteVarOf::class -> SInt8 + ShortVarOf::class -> SInt16 + IntVarOf::class -> SInt32 + LongVarOf::class -> SInt64 + CPointerVarOf::class -> Pointer + // TODO: floats, enums. + else -> if (classifier.isSubclassOf(CStructVar::class)) { + getStructCType(classifier) + } else { + null + } + } +} + +private val structTypeCache = ConcurrentHashMap, CType<*>>() + +private fun getStructCType(structClass: KClass<*>): CType<*> = structTypeCache.computeIfAbsent(structClass.java) { + // Note that struct classes are not supposed to be user-defined, + // so they don't require to be checked strictly. + + val annotations = structClass.annotations + val cNaturalStruct = annotations.filterIsInstance().firstOrNull() ?: + error("struct ${structClass.simpleName} has custom layout") + + val propertiesByName = structClass.declaredMemberProperties.groupBy { it.name } + + val fields = cNaturalStruct.fieldNames.map { + propertiesByName[it]!!.single() + } + + val fieldCTypes = mutableListOf>() + + for (field in fields) { + val lengthAnnotation = field.annotations.filterIsInstance().firstOrNull() + if (lengthAnnotation == null) { + val fieldType = getFieldCType(field.returnType) + fieldCTypes.add(fieldType) + } else { + assert(field.returnType.classifier == CPointer::class) + val length = lengthAnnotation.value + if (length != 0) { + val pointed = field.returnType.arguments.single().type!! + val pointedCType = getVariableCType(pointed) ?: TODO("array element type '$pointed'") + + // Represent array field as repeated element-typed fields: + repeat(length) { + fieldCTypes.add(pointedCType) + } + } + } + } + + @Suppress("DEPRECATION") + val structType = structClass.companionObjectInstance as CVariable.Type + + Struct(structType.size, structType.align, fieldCTypes) +} + +private fun getStructValueCType(type: KType): CType<*> { + val structClass = type.arguments.singleOrNull()?.type?.classifier as? KClass<*> ?: + error("'$type' type is incomplete") + + return getStructCType(structClass) +} + +private fun getEnumCType(classifier: KClass<*>): CEnumType? { + val rawValueType = classifier.declaredMemberProperties.single().returnType + + val rawValueCType = when (rawValueType.classifier) { + Byte::class -> SInt8 + Short::class -> SInt16 + Int::class -> SInt32 + Long::class -> SInt64 + else -> error("'${classifier.simpleName}' has unexpected value type '$rawValueType'") + } + + @Suppress("UNCHECKED_CAST") + return CEnumType(rawValueCType as CType) +} + +private fun getArgOrRetValCType(type: KType): CType<*> { + val classifier = type.classifier + + val result = when (classifier) { + !is KClass<*> -> null + Unit::class -> Void + Byte::class -> SInt8 + Short::class -> SInt16 + Int::class -> SInt32 + Long::class -> SInt64 + CPointer::class -> Pointer + // TODO: floats + CValue::class -> getStructValueCType(type) + else -> if (classifier.isSubclassOf(@Suppress("DEPRECATION") CEnum::class)) { + getEnumCType(classifier) + } else { + null + } + } ?: error("$type is not supported in callback signature") + + if (type.isMarkedNullable != (classifier == CPointer::class)) { + if (type.isMarkedNullable) { + error("$type must not be nullable when used in callback signature") + } else { + error("$type must be nullable when used in callback signature") + } + } + + return result +} + +private fun createStaticCFunction(function: Function<*>): CPointer> { + val errorMessage = "staticCFunction must take an unbound, non-capturing function" + + if (!isStatic(function)) { + throw IllegalArgumentException(errorMessage) + } + + val kFunction = function as? KFunction<*> ?: function.reflect() ?: + throw IllegalArgumentException(errorMessage) + + val returnType = getArgOrRetValCType(kFunction.returnType) + val paramTypes = kFunction.parameters.map { getArgOrRetValCType(it.type) } + + @Suppress("UNCHECKED_CAST") + return interpretCPointer(createStaticCFunctionImpl(returnType as CType, paramTypes, function))!! +} + +/** + * Returns `true` if given function is *static* as defined in [staticCFunction]. + */ +private fun isStatic(function: Function<*>): Boolean { + // TODO: revise + try { + with(function.javaClass.getDeclaredField("INSTANCE")) { + if (!java.lang.reflect.Modifier.isStatic(modifiers) || !java.lang.reflect.Modifier.isFinal(modifiers)) { + return false + } + + isAccessible = true // TODO: undo + + return get(null) == function + + // If the class has static final "INSTANCE" field, and only the value of this field is accepted, + // then each class is handled at most once, so these checks prevent memory leaks. + } + } catch (e: NoSuchFieldException) { + return false + } +} + +private val createdStaticFunctions = ConcurrentHashMap, CPointer>>() + +@Suppress("UNCHECKED_CAST") +internal fun > staticCFunctionImpl(function: F) = + createdStaticFunctions.computeIfAbsent(function.javaClass) { + createStaticCFunction(function) + } as CPointer> + +private val invokeMethods = (0 .. 22).map { arity -> + Class.forName("kotlin.jvm.functions.Function$arity").getMethod("invoke", + *Array>(arity) { java.lang.Object::class.java }) +} + +private fun createStaticCFunctionImpl( + returnType: CType, + paramTypes: List>, + function: Function<*> +): NativePtr { + val ffiCif = ffiCreateCif(returnType.ffiType, paramTypes.map { it.ffiType }) + + val arity = paramTypes.size + val pt = paramTypes.toTypedArray() + + @Suppress("UNCHECKED_CAST") + val impl: FfiClosureImpl = when (arity) { + 0 -> { + val f = function as () -> Any? + ffiClosureImpl(returnType) { _ -> + f() + } + } + 1 -> { + val f = function as (Any?) -> Any? + ffiClosureImpl(returnType) { args -> + f(pt.read(args, 0)) + } + } + 2 -> { + val f = function as (Any?, Any?) -> Any? + ffiClosureImpl(returnType) { args -> + f(pt.read(args, 0), pt.read(args, 1)) + } + } + 3 -> { + val f = function as (Any?, Any?, Any?) -> Any? + ffiClosureImpl(returnType) { args -> + f(pt.read(args, 0), pt.read(args, 1), pt.read(args, 2)) + } + } + 4 -> { + val f = function as (Any?, Any?, Any?, Any?) -> Any? + ffiClosureImpl(returnType) { args -> + f(pt.read(args, 0), pt.read(args, 1), pt.read(args, 2), pt.read(args, 3)) + } + } + 5 -> { + val f = function as (Any?, Any?, Any?, Any?, Any?) -> Any? + ffiClosureImpl(returnType) { args -> + f(pt.read(args, 0), pt.read(args, 1), pt.read(args, 2), pt.read(args, 3), pt.read(args, 4)) + } + } + else -> { + val invokeMethod = invokeMethods[arity] + ffiClosureImpl(returnType) { args -> + val arguments = Array(arity) { pt.read(args, it) } + invokeMethod.invoke(function, *arguments) + } + } + } + return ffiCreateClosure(ffiCif, impl) +} + +@Suppress("NOTHING_TO_INLINE") +private inline fun Array>.read(args: CArrayPointer, index: Int) = + this[index].read(args[index].rawValue) + +private inline fun ffiClosureImpl( + returnType: CType, + crossinline invoke: (args: CArrayPointer) -> Any? +): FfiClosureImpl { + // Called through [ffi_fun] when a native function created with [ffiCreateClosure] is invoked. + return LongConsumer { retAndArgsRaw -> + val retAndArgs = retAndArgsRaw.toCPointer>()!! + + // Pointer to memory to be filled with return value of the invoked native function: + val ret = retAndArgs[0]!! + + // Pointer to array of pointers to arguments passed to the invoked native function: + val args = retAndArgs[1]!!.reinterpret() + + val result = invoke(args) + + returnType.write(ret.rawValue, result) + } +} + +/** + * Describes the bridge between Kotlin type `T` and the corresponding C type of a function's parameter or return value. + * It is supposed to be constructed using the primitive types (such as [SInt32]), the [Struct] combinator + * and the [CEnumType] wrapper. + * + * This description omits the details that are irrelevant for the ABI. + */ +private abstract class CType internal constructor(val ffiType: ffi_type) { + internal constructor(ffiTypePtr: Long) : this(interpretPointed(ffiTypePtr)) + abstract fun read(location: NativePtr): T + abstract fun write(location: NativePtr, value: T): Unit +} + +private object Void : CType(ffiTypeVoid()) { + override fun read(location: NativePtr) = throw UnsupportedOperationException() + + override fun write(location: NativePtr, value: Any?) { + // nothing to do. + } +} + +private object SInt8 : CType(ffiTypeSInt8()) { + override fun read(location: NativePtr) = interpretPointed(location).value + override fun write(location: NativePtr, value: Byte) { + interpretPointed(location).value = value + } +} + +private object SInt16 : CType(ffiTypeSInt16()) { + override fun read(location: NativePtr) = interpretPointed(location).value + override fun write(location: NativePtr, value: Short) { + interpretPointed(location).value = value + } +} + +private object SInt32 : CType(ffiTypeSInt32()) { + override fun read(location: NativePtr) = interpretPointed(location).value + override fun write(location: NativePtr, value: Int) { + interpretPointed(location).value = value + } +} + +private object SInt64 : CType(ffiTypeSInt64()) { + override fun read(location: NativePtr) = interpretPointed(location).value + override fun write(location: NativePtr, value: Long) { + interpretPointed(location).value = value + } +} +private object Pointer : CType?>(ffiTypePointer()) { + override fun read(location: NativePtr) = interpretPointed>(location).value + override fun write(location: NativePtr, value: CPointer<*>?) { + interpretPointed>(location).value = value + } +} + +private class Struct(val size: Long, val align: Int, elementTypes: List>) : CType>( + ffiTypeStruct( + elementTypes.map { it.ffiType } + ) +) { + override fun read(location: NativePtr) = interpretPointed(location).readValue(size, align) + + override fun write(location: NativePtr, value: CValue<*>) = value.write(location) +} + +@Suppress("DEPRECATION") +private class CEnumType(private val rawValueCType: CType) : CType(rawValueCType.ffiType) { + + override fun read(location: NativePtr): CEnum { + TODO("enum-typed callback parameters") + } + + override fun write(location: NativePtr, value: CEnum) { + rawValueCType.write(location, value.value) + } +} + +private typealias FfiClosureImpl = LongConsumer +private typealias UserData = FfiClosureImpl + +private val topLevelInitializer = loadKonanLibrary("callbacks") + + +/** + * Reference to `ffi_type` struct instance. + */ +internal class ffi_type(rawPtr: NativePtr) : COpaque(rawPtr) + +/** + * Reference to `ffi_cif` struct instance. + */ +internal class ffi_cif(rawPtr: NativePtr) : COpaque(rawPtr) + +private external fun ffiTypeVoid(): Long +private external fun ffiTypeUInt8(): Long +private external fun ffiTypeSInt8(): Long +private external fun ffiTypeUInt16(): Long +private external fun ffiTypeSInt16(): Long +private external fun ffiTypeUInt32(): Long +private external fun ffiTypeSInt32(): Long +private external fun ffiTypeUInt64(): Long +private external fun ffiTypeSInt64(): Long +private external fun ffiTypePointer(): Long + +private external fun ffiTypeStruct0(elements: Long): Long + +/** + * Allocates and initializes `ffi_type` describing the struct. + * + * @param elements types of the struct elements + */ +private fun ffiTypeStruct(elementTypes: List): ffi_type { + val elements = nativeHeap.allocArrayOfPointersTo(*elementTypes.toTypedArray(), null) + val res = ffiTypeStruct0(elements.rawValue) + if (res == 0L) { + throw OutOfMemoryError() + } + return interpretPointed(res) +} + +private external fun ffiCreateCif0(nArgs: Int, rType: Long, argTypes: Long): Long + +/** + * Creates and prepares an `ffi_cif`. + * + * @param returnType native function return value type + * @param paramTypes native function parameter types + * + * @return the initialized `ffi_cif` + */ +private fun ffiCreateCif(returnType: ffi_type, paramTypes: List): ffi_cif { + val nArgs = paramTypes.size + val argTypes = nativeHeap.allocArrayOfPointersTo(*paramTypes.toTypedArray(), null) + val res = ffiCreateCif0(nArgs, returnType.rawPtr, argTypes.rawValue) + + when (res) { + 0L -> throw OutOfMemoryError() + -1L -> throw Error("FFI_BAD_TYPEDEF") + -2L -> throw Error("FFI_BAD_ABI") + -3L -> throw Error("libffi error occurred") + } + + return interpretPointed(res) +} + +private external fun ffiCreateClosure0(ffiCif: Long, userData: Any): Long + +/** + * Uses libffi to allocate a native function which will call [impl] when invoked. + * + * @param ffiCif describes the type of the function to create + */ +private fun ffiCreateClosure(ffiCif: ffi_cif, impl: FfiClosureImpl): NativePtr { + val res = ffiCreateClosure0(ffiCif.rawPtr, userData = impl) + + when (res) { + 0L -> throw OutOfMemoryError() + -1L -> throw Error("libffi error occurred") + } + + return res +} + +private external fun newGlobalRef(any: Any): Long +private external fun derefGlobalRef(ref: Long): Any +private external fun deleteGlobalRef(ref: Long) \ No newline at end of file diff --git a/kotlin-native/Interop/Runtime/src/jvm/kotlin/kotlinx/cinterop/JvmNativeMem.kt b/kotlin-native/Interop/Runtime/src/jvm/kotlin/kotlinx/cinterop/JvmNativeMem.kt new file mode 100644 index 00000000000..ceae51a34c4 --- /dev/null +++ b/kotlin-native/Interop/Runtime/src/jvm/kotlin/kotlinx/cinterop/JvmNativeMem.kt @@ -0,0 +1,118 @@ +/* + * Copyright 2010-2017 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package kotlinx.cinterop + +import sun.misc.Unsafe + +private val NativePointed.address: Long + get() = this.rawPtr + +private enum class DataModel(val pointerSize: Long) { + _32BIT(4), + _64BIT(8) +} + +private val dataModel: DataModel = when (System.getProperty("sun.arch.data.model")) { + null -> TODO() + "32" -> DataModel._32BIT + "64" -> DataModel._64BIT + else -> throw IllegalStateException() +} + +// Must be only used in interop, contains host pointer size, not target! +@PublishedApi +internal val pointerSize: Int = dataModel.pointerSize.toInt() + +@PublishedApi +internal object nativeMemUtils { + fun getByte(mem: NativePointed) = unsafe.getByte(mem.address) + fun putByte(mem: NativePointed, value: Byte) = unsafe.putByte(mem.address, value) + + fun getShort(mem: NativePointed) = unsafe.getShort(mem.address) + fun putShort(mem: NativePointed, value: Short) = unsafe.putShort(mem.address, value) + + fun getInt(mem: NativePointed) = unsafe.getInt(mem.address) + fun putInt(mem: NativePointed, value: Int) = unsafe.putInt(mem.address, value) + + fun getLong(mem: NativePointed) = unsafe.getLong(mem.address) + fun putLong(mem: NativePointed, value: Long) = unsafe.putLong(mem.address, value) + + fun getFloat(mem: NativePointed) = unsafe.getFloat(mem.address) + fun putFloat(mem: NativePointed, value: Float) = unsafe.putFloat(mem.address, value) + + fun getDouble(mem: NativePointed) = unsafe.getDouble(mem.address) + fun putDouble(mem: NativePointed, value: Double) = unsafe.putDouble(mem.address, value) + + fun getNativePtr(mem: NativePointed): NativePtr = when (dataModel) { + DataModel._32BIT -> getInt(mem).toLong() + DataModel._64BIT -> getLong(mem) + } + + fun putNativePtr(mem: NativePointed, value: NativePtr) = when (dataModel) { + DataModel._32BIT -> putInt(mem, value.toInt()) + DataModel._64BIT -> putLong(mem, value) + } + + fun getByteArray(source: NativePointed, dest: ByteArray, length: Int) { + unsafe.copyMemory(null, source.address, dest, byteArrayBaseOffset, length.toLong()) + } + + fun putByteArray(source: ByteArray, dest: NativePointed, length: Int) { + unsafe.copyMemory(source, byteArrayBaseOffset, null, dest.address, length.toLong()) + } + + fun getCharArray(source: NativePointed, dest: CharArray, length: Int) { + unsafe.copyMemory(null, source.address, dest, charArrayBaseOffset, length.toLong() * 2) + } + + fun putCharArray(source: CharArray, dest: NativePointed, length: Int) { + unsafe.copyMemory(source, charArrayBaseOffset, null, dest.address, length.toLong() * 2) + } + + fun zeroMemory(dest: NativePointed, length: Int): Unit = + unsafe.setMemory(dest.address, length.toLong(), 0) + + fun copyMemory(dest: NativePointed, length: Int, src: NativePointed) = + unsafe.copyMemory(src.address, dest.address, length.toLong()) + + + @Suppress("NON_PUBLIC_CALL_FROM_PUBLIC_INLINE") + inline fun allocateInstance(): T { + return unsafe.allocateInstance(T::class.java) as T + } + + fun alloc(size: Long, align: Int): NativePointed { + val address = unsafe.allocateMemory( + if (size == 0L) 1L else size // It is a hack: `sun.misc.Unsafe` can't allocate zero bytes + ) + + if (address % align != 0L) TODO(align.toString()) + return interpretOpaquePointed(address) + } + + fun free(mem: NativePtr) { + unsafe.freeMemory(mem) + } + + private val unsafe = with(Unsafe::class.java.getDeclaredField("theUnsafe")) { + isAccessible = true + return@with this.get(null) as Unsafe + } + + private val byteArrayBaseOffset = unsafe.arrayBaseOffset(ByteArray::class.java).toLong() + private val charArrayBaseOffset = unsafe.arrayBaseOffset(CharArray::class.java).toLong() +} diff --git a/kotlin-native/Interop/Runtime/src/jvm/kotlin/kotlinx/cinterop/JvmTypes.kt b/kotlin-native/Interop/Runtime/src/jvm/kotlin/kotlinx/cinterop/JvmTypes.kt new file mode 100644 index 00000000000..49b16c4231e --- /dev/null +++ b/kotlin-native/Interop/Runtime/src/jvm/kotlin/kotlinx/cinterop/JvmTypes.kt @@ -0,0 +1,145 @@ +/* + * Copyright 2010-2017 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package kotlinx.cinterop + +import java.util.concurrent.ConcurrentHashMap +import kotlin.reflect.full.companionObjectInstance + +typealias NativePtr = Long +internal typealias NonNullNativePtr = NativePtr +@PublishedApi internal fun NonNullNativePtr.toNativePtr() = this +internal fun NativePtr.toNonNull(): NonNullNativePtr = this + +public val nativeNullPtr: NativePtr = 0L + +// TODO: the functions below should eventually be intrinsified + +@Suppress("DEPRECATION") +private val typeOfCache = ConcurrentHashMap, CVariable.Type>() + +@Deprecated("Use sizeOf() or alignOf() instead.") +@Suppress("NON_PUBLIC_CALL_FROM_PUBLIC_INLINE") +inline fun typeOf() = + @Suppress("DEPRECATION") + typeOfCache.computeIfAbsent(T::class.java) { T::class.companionObjectInstance as CVariable.Type } + +/** + * Returns interpretation of entity with given pointer, or `null` if it is null. + * + * @param T must not be abstract + */ +@Suppress("NON_PUBLIC_CALL_FROM_PUBLIC_INLINE") +inline fun interpretNullablePointed(ptr: NativePtr): T? { + if (ptr == nativeNullPtr) { + return null + } else { + val result = nativeMemUtils.allocateInstance() + result.rawPtr = ptr + return result + } +} + +/** + * Creates a [CPointer] from the raw pointer of [NativePtr]. + * + * @return a [CPointer] representation, or `null` if the [rawValue] represents native `nullptr`. + */ +fun interpretCPointer(rawValue: NativePtr) = + if (rawValue == nativeNullPtr) { + null + } else { + CPointer(rawValue) + } + +internal fun CPointer<*>.cPointerToString() = "CPointer(raw=0x%x)".format(rawValue) + +@Target(AnnotationTarget.PROPERTY) +@Retention(AnnotationRetention.RUNTIME) +annotation class CLength(val value: Int) + +@Target(AnnotationTarget.CLASS) +@Retention(AnnotationRetention.RUNTIME) +annotation class CNaturalStruct(vararg val fieldNames: String) + +fun staticCFunction(function: () -> R): CPointer R>> = + staticCFunctionImpl(function) + +fun staticCFunction(function: (P1) -> R): CPointer R>> = + staticCFunctionImpl(function) + +fun staticCFunction(function: (P1, P2) -> R): CPointer R>> = + staticCFunctionImpl(function) + +fun staticCFunction(function: (P1, P2, P3) -> R): CPointer R>> = + staticCFunctionImpl(function) + +fun staticCFunction(function: (P1, P2, P3, P4) -> R): CPointer R>> = + staticCFunctionImpl(function) + +fun staticCFunction(function: (P1, P2, P3, P4, P5) -> R): CPointer R>> = + staticCFunctionImpl(function) + +fun staticCFunction(function: (P1, P2, P3, P4, P5, P6) -> R): CPointer R>> = + staticCFunctionImpl(function) + +fun staticCFunction(function: (P1, P2, P3, P4, P5, P6, P7) -> R): CPointer R>> = + staticCFunctionImpl(function) + +fun staticCFunction(function: (P1, P2, P3, P4, P5, P6, P7, P8) -> R): CPointer R>> = + staticCFunctionImpl(function) + +fun staticCFunction(function: (P1, P2, P3, P4, P5, P6, P7, P8, P9) -> R): CPointer R>> = + staticCFunctionImpl(function) + +fun staticCFunction(function: (P1, P2, P3, P4, P5, P6, P7, P8, P9, P10) -> R): CPointer R>> = + staticCFunctionImpl(function) + +fun staticCFunction(function: (P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11) -> R): CPointer R>> = + staticCFunctionImpl(function) + +fun staticCFunction(function: (P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12) -> R): CPointer R>> = + staticCFunctionImpl(function) + +fun staticCFunction(function: (P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13) -> R): CPointer R>> = + staticCFunctionImpl(function) + +fun staticCFunction(function: (P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14) -> R): CPointer R>> = + staticCFunctionImpl(function) + +fun staticCFunction(function: (P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15) -> R): CPointer R>> = + staticCFunctionImpl(function) + +fun staticCFunction(function: (P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16) -> R): CPointer R>> = + staticCFunctionImpl(function) + +fun staticCFunction(function: (P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17) -> R): CPointer R>> = + staticCFunctionImpl(function) + +fun staticCFunction(function: (P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18) -> R): CPointer R>> = + staticCFunctionImpl(function) + +fun staticCFunction(function: (P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19) -> R): CPointer R>> = + staticCFunctionImpl(function) + +fun staticCFunction(function: (P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20) -> R): CPointer R>> = + staticCFunctionImpl(function) + +fun staticCFunction(function: (P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21) -> R): CPointer R>> = + staticCFunctionImpl(function) + +fun staticCFunction(function: (P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22) -> R): CPointer R>> = + staticCFunctionImpl(function) diff --git a/kotlin-native/Interop/Runtime/src/jvm/kotlin/kotlinx/cinterop/JvmUtils.kt b/kotlin-native/Interop/Runtime/src/jvm/kotlin/kotlinx/cinterop/JvmUtils.kt new file mode 100644 index 00000000000..d1943be26b7 --- /dev/null +++ b/kotlin-native/Interop/Runtime/src/jvm/kotlin/kotlinx/cinterop/JvmUtils.kt @@ -0,0 +1,109 @@ +/* + * Copyright 2010-2017 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package kotlinx.cinterop + +import org.jetbrains.kotlin.konan.util.KonanHomeProvider +import java.io.File +import java.nio.file.Files +import java.nio.file.Paths + +internal fun decodeFromUtf8(bytes: ByteArray) = String(bytes) +internal fun encodeToUtf8(str: String) = str.toByteArray() + +fun bitsToFloat(bits: Int): Float = java.lang.Float.intBitsToFloat(bits) +fun bitsToDouble(bits: Long): Double = java.lang.Double.longBitsToDouble(bits) + +// TODO: the functions below should eventually be intrinsified + +inline fun Byte.signExtend(): R = when (R::class.java) { + java.lang.Byte::class.java -> this.toByte() as R + java.lang.Short::class.java -> this.toShort() as R + java.lang.Integer::class.java -> this.toInt() as R + java.lang.Long::class.java -> this.toLong() as R + else -> this.invalidSignExtension() +} + +inline fun Short.signExtend(): R = when (R::class.java) { + java.lang.Short::class.java -> this.toShort() as R + java.lang.Integer::class.java -> this.toInt() as R + java.lang.Long::class.java -> this.toLong() as R + else -> this.invalidSignExtension() +} + +inline fun Int.signExtend(): R = when (R::class.java) { + java.lang.Integer::class.java -> this.toInt() as R + java.lang.Long::class.java -> this.toLong() as R + else -> this.invalidSignExtension() +} + +inline fun Long.signExtend(): R = when (R::class.java) { + java.lang.Long::class.java -> this.toLong() as R + else -> this.invalidSignExtension() +} + +inline fun Number.invalidSignExtension(): R { + throw Error("unable to sign extend ${this.javaClass.simpleName} \"${this}\" to ${R::class.java.simpleName}") +} + +inline fun Byte.narrow(): R = when (R::class.java) { + java.lang.Byte::class.java -> this.toByte() as R + else -> this.invalidNarrowing() +} + +inline fun Short.narrow(): R = when (R::class.java) { + java.lang.Byte::class.java -> this.toByte() as R + java.lang.Short::class.java -> this.toShort() as R + else -> this.invalidNarrowing() +} + +inline fun Int.narrow(): R = when (R::class.java) { + java.lang.Byte::class.java -> this.toByte() as R + java.lang.Short::class.java -> this.toShort() as R + java.lang.Integer::class.java -> this.toInt() as R + else -> this.invalidNarrowing() +} + +inline fun Long.narrow(): R = when (R::class.java) { + java.lang.Byte::class.java -> this.toByte() as R + java.lang.Short::class.java -> this.toShort() as R + java.lang.Integer::class.java -> this.toInt() as R + java.lang.Long::class.java -> this.toLong() as R + else -> this.invalidNarrowing() +} + +inline fun Number.invalidNarrowing(): R { + throw Error("unable to narrow ${this.javaClass.simpleName} \"${this}\" to ${R::class.java.simpleName}") +} + +fun loadKonanLibrary(name: String) { + try { + System.loadLibrary(name) + } catch (e: UnsatisfiedLinkError) { + val fullLibraryName = System.mapLibraryName(name) + val dir = "${KonanHomeProvider.determineKonanHome()}/konan/nativelib" + try { + System.load("$dir/$fullLibraryName") + } catch (e: UnsatisfiedLinkError) { + val tempDir = createTempDir(directory = File(dir)).absolutePath + Files.createLink(Paths.get(tempDir, fullLibraryName), Paths.get(dir, fullLibraryName)) + // TODO: Does not work on Windows. May be use FILE_FLAG_DELETE_ON_CLOSE? + File(tempDir).deleteOnExit() + File("$tempDir/$fullLibraryName").deleteOnExit() + System.load("$tempDir/$fullLibraryName") + } + } +} \ No newline at end of file diff --git a/kotlin-native/Interop/Runtime/src/main/kotlin/kotlinx/cinterop/Generated.kt b/kotlin-native/Interop/Runtime/src/main/kotlin/kotlinx/cinterop/Generated.kt new file mode 100644 index 00000000000..323811d4e53 --- /dev/null +++ b/kotlin-native/Interop/Runtime/src/main/kotlin/kotlinx/cinterop/Generated.kt @@ -0,0 +1,316 @@ +/* + * Copyright 2010-2017 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +@file:Suppress("FINAL_UPPER_BOUND", "NOTHING_TO_INLINE") + +package kotlinx.cinterop + +@JvmName("plus\$Byte") +inline operator fun > CPointer?.plus(index: Long): CPointer? = + interpretCPointer(this.rawValue + index * 1) + +@JvmName("plus\$Byte") +inline operator fun > CPointer?.plus(index: Int): CPointer? = + this + index.toLong() + +@JvmName("get\$Byte") +inline operator fun CPointer>.get(index: Int): T = + (this + index)!!.pointed.value + +@JvmName("set\$Byte") +inline operator fun CPointer>.set(index: Int, value: T) { + (this + index)!!.pointed.value = value +} + +@JvmName("get\$Byte") +inline operator fun CPointer>.get(index: Long): T = + (this + index)!!.pointed.value + +@JvmName("set\$Byte") +inline operator fun CPointer>.set(index: Long, value: T) { + (this + index)!!.pointed.value = value +} + +@JvmName("plus\$Short") +inline operator fun > CPointer?.plus(index: Long): CPointer? = + interpretCPointer(this.rawValue + index * 2) + +@JvmName("plus\$Short") +inline operator fun > CPointer?.plus(index: Int): CPointer? = + this + index.toLong() + +@JvmName("get\$Short") +inline operator fun CPointer>.get(index: Int): T = + (this + index)!!.pointed.value + +@JvmName("set\$Short") +inline operator fun CPointer>.set(index: Int, value: T) { + (this + index)!!.pointed.value = value +} + +@JvmName("get\$Short") +inline operator fun CPointer>.get(index: Long): T = + (this + index)!!.pointed.value + +@JvmName("set\$Short") +inline operator fun CPointer>.set(index: Long, value: T) { + (this + index)!!.pointed.value = value +} + +@JvmName("plus\$Int") +inline operator fun > CPointer?.plus(index: Long): CPointer? = + interpretCPointer(this.rawValue + index * 4) + +@JvmName("plus\$Int") +inline operator fun > CPointer?.plus(index: Int): CPointer? = + this + index.toLong() + +@JvmName("get\$Int") +inline operator fun CPointer>.get(index: Int): T = + (this + index)!!.pointed.value + +@JvmName("set\$Int") +inline operator fun CPointer>.set(index: Int, value: T) { + (this + index)!!.pointed.value = value +} + +@JvmName("get\$Int") +inline operator fun CPointer>.get(index: Long): T = + (this + index)!!.pointed.value + +@JvmName("set\$Int") +inline operator fun CPointer>.set(index: Long, value: T) { + (this + index)!!.pointed.value = value +} + +@JvmName("plus\$Long") +inline operator fun > CPointer?.plus(index: Long): CPointer? = + interpretCPointer(this.rawValue + index * 8) + +@JvmName("plus\$Long") +inline operator fun > CPointer?.plus(index: Int): CPointer? = + this + index.toLong() + +@JvmName("get\$Long") +inline operator fun CPointer>.get(index: Int): T = + (this + index)!!.pointed.value + +@JvmName("set\$Long") +inline operator fun CPointer>.set(index: Int, value: T) { + (this + index)!!.pointed.value = value +} + +@JvmName("get\$Long") +inline operator fun CPointer>.get(index: Long): T = + (this + index)!!.pointed.value + +@JvmName("set\$Long") +inline operator fun CPointer>.set(index: Long, value: T) { + (this + index)!!.pointed.value = value +} + +@JvmName("plus\$UByte") +inline operator fun > CPointer?.plus(index: Long): CPointer? = + interpretCPointer(this.rawValue + index * 1) + +@JvmName("plus\$UByte") +inline operator fun > CPointer?.plus(index: Int): CPointer? = + this + index.toLong() + +@JvmName("get\$UByte") +inline operator fun CPointer>.get(index: Int): T = + (this + index)!!.pointed.value + +inline operator fun CPointer>.set(index: Int, value: T) { + (this + index)!!.pointed.value = value +} + +inline operator fun CPointer>.get(index: Long): T = + (this + index)!!.pointed.value + +inline operator fun CPointer>.set(index: Long, value: T) { + (this + index)!!.pointed.value = value +} + +@JvmName("plus\$UShort") +inline operator fun > CPointer?.plus(index: Long): CPointer? = + interpretCPointer(this.rawValue + index * 2) + +@JvmName("plus\$UShort") +inline operator fun > CPointer?.plus(index: Int): CPointer? = + this + index.toLong() + +@JvmName("get\$UShort") +inline operator fun CPointer>.get(index: Int): T = + (this + index)!!.pointed.value + +inline operator fun CPointer>.set(index: Int, value: T) { + (this + index)!!.pointed.value = value +} + +@JvmName("get\$UShort") +inline operator fun CPointer>.get(index: Long): T = + (this + index)!!.pointed.value + +inline operator fun CPointer>.set(index: Long, value: T) { + (this + index)!!.pointed.value = value +} + +@JvmName("plus\$UInt") +inline operator fun > CPointer?.plus(index: Long): CPointer? = + interpretCPointer(this.rawValue + index * 4) + +@JvmName("plus\$UInt") +inline operator fun > CPointer?.plus(index: Int): CPointer? = + this + index.toLong() + +@JvmName("get\$UInt") +inline operator fun CPointer>.get(index: Int): T = + (this + index)!!.pointed.value + +inline operator fun CPointer>.set(index: Int, value: T) { + (this + index)!!.pointed.value = value +} + +@JvmName("get\$UInt") +inline operator fun CPointer>.get(index: Long): T = + (this + index)!!.pointed.value + +inline operator fun CPointer>.set(index: Long, value: T) { + (this + index)!!.pointed.value = value +} + +@JvmName("plus\$ULong") +inline operator fun > CPointer?.plus(index: Long): CPointer? = + interpretCPointer(this.rawValue + index * 8) + +@JvmName("plus\$ULong") +inline operator fun > CPointer?.plus(index: Int): CPointer? = + this + index.toLong() + +@JvmName("get\$ULong") +inline operator fun CPointer>.get(index: Int): T = + (this + index)!!.pointed.value + +inline operator fun CPointer>.set(index: Int, value: T) { + (this + index)!!.pointed.value = value +} + +@JvmName("get\$ULong") +inline operator fun CPointer>.get(index: Long): T = + (this + index)!!.pointed.value + +inline operator fun CPointer>.set(index: Long, value: T) { + (this + index)!!.pointed.value = value +} + +@JvmName("plus\$Float") +inline operator fun > CPointer?.plus(index: Long): CPointer? = + interpretCPointer(this.rawValue + index * 4) + +@JvmName("plus\$Float") +inline operator fun > CPointer?.plus(index: Int): CPointer? = + this + index.toLong() + +@JvmName("get\$Float") +inline operator fun CPointer>.get(index: Int): T = + (this + index)!!.pointed.value + +@JvmName("set\$Float") +inline operator fun CPointer>.set(index: Int, value: T) { + (this + index)!!.pointed.value = value +} + +@JvmName("get\$Float") +inline operator fun CPointer>.get(index: Long): T = + (this + index)!!.pointed.value + +@JvmName("set\$Float") +inline operator fun CPointer>.set(index: Long, value: T) { + (this + index)!!.pointed.value = value +} + +@JvmName("plus\$Double") +inline operator fun > CPointer?.plus(index: Long): CPointer? = + interpretCPointer(this.rawValue + index * 8) + +@JvmName("plus\$Double") +inline operator fun > CPointer?.plus(index: Int): CPointer? = + this + index.toLong() + +@JvmName("get\$Double") +inline operator fun CPointer>.get(index: Int): T = + (this + index)!!.pointed.value + +@JvmName("set\$Double") +inline operator fun CPointer>.set(index: Int, value: T) { + (this + index)!!.pointed.value = value +} + +@JvmName("get\$Double") +inline operator fun CPointer>.get(index: Long): T = + (this + index)!!.pointed.value + +@JvmName("set\$Double") +inline operator fun CPointer>.set(index: Long, value: T) { + (this + index)!!.pointed.value = value +} + +/* Generated by: + +#!/bin/bash + +function gen { +echo "@JvmName(\"plus\\\$$1\")" +echo "inline operator fun > CPointer?.plus(index: Long): CPointer? =" +echo " interpretCPointer(this.rawValue + index * ${2})" +echo +echo "@JvmName(\"plus\\\$$1\")" +echo "inline operator fun > CPointer?.plus(index: Int): CPointer? =" +echo " this + index.toLong()" +echo +echo "@JvmName(\"get\\\$$1\")" +echo "inline operator fun CPointer<${1}VarOf>.get(index: Int): T =" +echo " (this + index)!!.pointed.value" +echo +echo "@JvmName(\"set\\\$$1\")" +echo "inline operator fun CPointer<${1}VarOf>.set(index: Int, value: T) {" +echo " (this + index)!!.pointed.value = value" +echo '}' +echo +echo "@JvmName(\"get\\\$$1\")" +echo "inline operator fun CPointer<${1}VarOf>.get(index: Long): T =" +echo " (this + index)!!.pointed.value" +echo +echo "@JvmName(\"set\\\$$1\")" +echo "inline operator fun CPointer<${1}VarOf>.set(index: Long, value: T) {" +echo " (this + index)!!.pointed.value = value" +echo '}' +echo +} + +gen Byte 1 +gen Short 2 +gen Int 4 +gen Long 8 +gen UByte 1 +gen UShort 2 +gen UInt 4 +gen ULong 8 +gen Float 4 +gen Double 8 + + */ diff --git a/kotlin-native/Interop/Runtime/src/main/kotlin/kotlinx/cinterop/StableRef.kt b/kotlin-native/Interop/Runtime/src/main/kotlin/kotlinx/cinterop/StableRef.kt new file mode 100644 index 00000000000..060aa818c66 --- /dev/null +++ b/kotlin-native/Interop/Runtime/src/main/kotlin/kotlinx/cinterop/StableRef.kt @@ -0,0 +1,77 @@ +/* + * Copyright 2010-2017 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package kotlinx.cinterop + +@Deprecated("Use StableRef instead", ReplaceWith("StableRef"), DeprecationLevel.ERROR) +typealias StableObjPtr = StableRef<*> + +/** + * This class provides a way to create a stable handle to any Kotlin object. + * After [converting to CPointer][asCPointer] it can be safely passed to native code e.g. to be received + * in a Kotlin callback. + * + * Any [StableRef] should be manually [disposed][dispose] + */ +@Suppress("NON_PUBLIC_PRIMARY_CONSTRUCTOR_OF_INLINE_CLASS") +public inline class StableRef @PublishedApi internal constructor( + private val stablePtr: COpaquePointer +) { + + companion object { + + /** + * Creates a handle for given object. + */ + fun create(any: T) = StableRef(createStablePointer(any)) + + /** + * Creates [StableRef] from given raw value. + * + * @param value must be a [value] of some [StableRef] + */ + @Deprecated("Use CPointer<*>.asStableRef() instead", ReplaceWith("ptr.asStableRef()"), + DeprecationLevel.ERROR) + fun fromValue(value: COpaquePointer) = value.asStableRef() + } + @Deprecated("Use .asCPointer() instead", ReplaceWith("this.asCPointer()"), DeprecationLevel.ERROR) + val value: COpaquePointer get() = this.asCPointer() + + /** + * Converts the handle to C pointer. + * @see [asStableRef] + */ + fun asCPointer(): COpaquePointer = this.stablePtr + + /** + * Disposes the handle. It must not be used after that. + */ + fun dispose() { + disposeStablePointer(this.stablePtr) + } + + /** + * Returns the object this handle was [created][StableRef.create] for. + */ + @Suppress("UNCHECKED_CAST") + fun get() = derefStablePointer(this.stablePtr) as T + +} + +/** + * Converts to [StableRef] this opaque pointer produced by [StableRef.asCPointer]. + */ +inline fun CPointer<*>.asStableRef(): StableRef = StableRef(this).also { it.get() } diff --git a/kotlin-native/Interop/Runtime/src/main/kotlin/kotlinx/cinterop/Types.kt b/kotlin-native/Interop/Runtime/src/main/kotlin/kotlinx/cinterop/Types.kt new file mode 100644 index 00000000000..e338c4928f9 --- /dev/null +++ b/kotlin-native/Interop/Runtime/src/main/kotlin/kotlinx/cinterop/Types.kt @@ -0,0 +1,506 @@ +/* + * Copyright 2010-2019 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package kotlinx.cinterop + +/** + * The entity which has an associated native pointer. + * Subtypes are supposed to represent interpretations of the pointed data or code. + * + * This interface is likely to be handled by compiler magic and shouldn't be subtyped by arbitrary classes. + * + * TODO: the behavior of [equals], [hashCode] and [toString] differs on Native and JVM backends. + */ +public open class NativePointed internal constructor(rawPtr: NonNullNativePtr) { + var rawPtr = rawPtr.toNativePtr() + internal set +} + +// `null` value of `NativePointed?` is mapped to `nativeNullPtr`. +public val NativePointed?.rawPtr: NativePtr + get() = if (this != null) this.rawPtr else nativeNullPtr + +/** + * Returns interpretation of entity with given pointer. + * + * @param T must not be abstract + */ +public inline fun interpretPointed(ptr: NativePtr): T = interpretNullablePointed(ptr)!! + +private class OpaqueNativePointed(rawPtr: NativePtr) : NativePointed(rawPtr.toNonNull()) + +public fun interpretOpaquePointed(ptr: NativePtr): NativePointed = interpretPointed(ptr) +public fun interpretNullableOpaquePointed(ptr: NativePtr): NativePointed? = interpretNullablePointed(ptr) + +/** + * Changes the interpretation of the pointed data or code. + */ +public inline fun NativePointed.reinterpret(): T = interpretPointed(this.rawPtr) + +/** + * C data or code. + */ +public abstract class CPointed(rawPtr: NativePtr) : NativePointed(rawPtr.toNonNull()) + +/** + * Represents a reference to (possibly empty) sequence of C values. + * It can be either a stable pointer [CPointer] or a sequence of immutable values [CValues]. + * + * [CValuesRef] is designed to be used as Kotlin representation of pointer-typed parameters of C functions. + * When passing [CPointer] as [CValuesRef] to the Kotlin binding method, the C function receives exactly this pointer. + * Passing [CValues] has nearly the same semantics as passing by value: the C function receives + * the pointer to the temporary copy of these values, and the caller can't observe the modifications to this copy. + * The copy is valid until the C function returns. + * There are also other implementations of [CValuesRef] that provide temporary pointer, + * e.g. Kotlin Native specific [refTo] functions to pass primitive arrays directly to native. + */ +public abstract class CValuesRef { + /** + * If this reference is [CPointer], returns this pointer, otherwise + * allocate storage value in the scope and return it. + */ + public abstract fun getPointer(scope: AutofreeScope): CPointer +} + +/** + * The (possibly empty) sequence of immutable C values. + * It is self-contained and doesn't depend on native memory. + */ +public abstract class CValues : CValuesRef() { + /** + * Copies the values to [placement] and returns the pointer to the copy. + */ + public override fun getPointer(scope: AutofreeScope): CPointer { + return place(interpretCPointer(scope.alloc(size, align).rawPtr)!!) + } + + // TODO: optimize + public override fun equals(other: Any?): Boolean { + if (this === other) return true + if (other !is CValues<*>) return false + + val thisBytes = this.getBytes() + val otherBytes = other.getBytes() + + if (thisBytes.size != otherBytes.size) { + return false + } + + for (index in 0 .. thisBytes.size - 1) { + if (thisBytes[index] != otherBytes[index]) { + return false + } + } + + return true + } + + public override fun hashCode(): Int { + var result = 0 + for (byte in this.getBytes()) { + result = result * 31 + byte + } + return result + } + + public abstract val size: Int + + public abstract val align: Int + + /** + * Copy the referenced values to [placement] and return placement pointer. + */ + public abstract fun place(placement: CPointer): CPointer +} + +public fun CValues.placeTo(scope: AutofreeScope) = this.getPointer(scope) + +/** + * The single immutable C value. + * It is self-contained and doesn't depend on native memory. + * + * TODO: consider providing an adapter instead of subtyping [CValues]. + */ +public abstract class CValue : CValues() + +/** + * C pointer. + */ +public class CPointer internal constructor(@PublishedApi internal val value: NonNullNativePtr) : CValuesRef() { + + // TODO: replace by [value]. + @Suppress("NOTHING_TO_INLINE") + public inline val rawValue: NativePtr get() = value.toNativePtr() + + public override fun equals(other: Any?): Boolean { + if (this === other) { + return true // fast path + } + + return (other is CPointer<*>) && (rawValue == other.rawValue) + } + + public override fun hashCode(): Int { + return rawValue.hashCode() + } + + public override fun toString() = this.cPointerToString() + + public override fun getPointer(scope: AutofreeScope) = this +} + +/** + * Returns the pointer to this data or code. + */ +public val T.ptr: CPointer + get() = interpretCPointer(this.rawPtr)!! + +/** + * Returns the corresponding [CPointed]. + * + * @param T must not be abstract + */ +public inline val CPointer.pointed: T + get() = interpretPointed(this.rawValue) + +// `null` value of `CPointer?` is mapped to `nativeNullPtr` +public val CPointer<*>?.rawValue: NativePtr + get() = if (this != null) this.rawValue else nativeNullPtr + +public fun CPointer<*>.reinterpret(): CPointer = interpretCPointer(this.rawValue)!! + +public fun CPointer?.toLong() = this.rawValue.toLong() + +public fun Long.toCPointer(): CPointer? = interpretCPointer(nativeNullPtr + this) + +/** + * The [CPointed] without any specified interpretation. + */ +public abstract class COpaque(rawPtr: NativePtr) : CPointed(rawPtr) // TODO: should it correspond to COpaquePointer? + +/** + * The pointer with an opaque type. + */ +public typealias COpaquePointer = CPointer // FIXME + +/** + * The variable containing a [COpaquePointer]. + */ +public typealias COpaquePointerVar = CPointerVarOf + +/** + * The C data variable located in memory. + * + * The non-abstract subclasses should represent the (complete) C data type and thus specify size and alignment. + * Each such subclass must have a companion object which is a [Type]. + */ +public abstract class CVariable(rawPtr: NativePtr) : CPointed(rawPtr) { + + /** + * The (complete) C data type. + * + * @param size the size in bytes of data of this type + * @param align the alignments in bytes that is enough for this data type. + * It may be greater than actually required for simplicity. + */ + @Deprecated("Use sizeOf() or alignOf() instead.") + public open class Type(val size: Long, val align: Int) { + + init { + require(size % align == 0L) + } + + } +} + +@Suppress("DEPRECATION") +public inline fun sizeOf() = typeOf().size + +@Suppress("DEPRECATION") +public inline fun alignOf() = typeOf().align + +/** + * Returns the member of this [CStructVar] which is located by given offset in bytes. + */ +public inline fun CStructVar.memberAt(offset: Long): T { + return interpretPointed(this.rawPtr + offset) +} + +public inline fun CStructVar.arrayMemberAt(offset: Long): CArrayPointer { + return interpretCPointer(this.rawPtr + offset)!! +} + +/** + * The C struct-typed variable located in memory. + */ +public abstract class CStructVar(rawPtr: NativePtr) : CVariable(rawPtr) { + @Deprecated("Use sizeOf() or alignOf() instead.") + @Suppress("DEPRECATION") + open class Type(size: Long, align: Int) : CVariable.Type(size, align) +} + +/** + * The C primitive-typed variable located in memory. + */ +sealed class CPrimitiveVar(rawPtr: NativePtr) : CVariable(rawPtr) { + // aligning by size is obviously enough + @Deprecated("Use sizeOf() or alignOf() instead.") + @Suppress("DEPRECATION") + open class Type(size: Int) : CVariable.Type(size.toLong(), align = size) +} + +@Deprecated("Will be removed.") +public interface CEnum { + public val value: Any +} + +public abstract class CEnumVar(rawPtr: NativePtr) : CPrimitiveVar(rawPtr) + +// generics below are used for typedef support +// these classes are not supposed to be used directly, instead the typealiases are provided. + +@Suppress("FINAL_UPPER_BOUND") +public class BooleanVarOf(rawPtr: NativePtr) : CPrimitiveVar(rawPtr) { + @Deprecated("Use sizeOf() or alignOf() instead.") + @Suppress("DEPRECATION") + companion object : Type(1) +} + +@Suppress("FINAL_UPPER_BOUND") +public class ByteVarOf(rawPtr: NativePtr) : CPrimitiveVar(rawPtr) { + @Deprecated("Use sizeOf() or alignOf() instead.") + @Suppress("DEPRECATION") + companion object : Type(1) +} + +@Suppress("FINAL_UPPER_BOUND") +public class ShortVarOf(rawPtr: NativePtr) : CPrimitiveVar(rawPtr) { + @Deprecated("Use sizeOf() or alignOf() instead.") + @Suppress("DEPRECATION") + companion object : Type(2) +} + +@Suppress("FINAL_UPPER_BOUND") +public class IntVarOf(rawPtr: NativePtr) : CPrimitiveVar(rawPtr) { + @Deprecated("Use sizeOf() or alignOf() instead.") + @Suppress("DEPRECATION") + companion object : Type(4) +} + +@Suppress("FINAL_UPPER_BOUND") +public class LongVarOf(rawPtr: NativePtr) : CPrimitiveVar(rawPtr) { + @Deprecated("Use sizeOf() or alignOf() instead.") + @Suppress("DEPRECATION") + companion object : Type(8) +} + +@Suppress("FINAL_UPPER_BOUND") +public class UByteVarOf(rawPtr: NativePtr) : CPrimitiveVar(rawPtr) { + @Deprecated("Use sizeOf() or alignOf() instead.") + @Suppress("DEPRECATION") + companion object : Type(1) +} + +@Suppress("FINAL_UPPER_BOUND") +public class UShortVarOf(rawPtr: NativePtr) : CPrimitiveVar(rawPtr) { + @Deprecated("Use sizeOf() or alignOf() instead.") + @Suppress("DEPRECATION") + companion object : Type(2) +} + +@Suppress("FINAL_UPPER_BOUND") +public class UIntVarOf(rawPtr: NativePtr) : CPrimitiveVar(rawPtr) { + @Deprecated("Use sizeOf() or alignOf() instead.") + @Suppress("DEPRECATION") + companion object : Type(4) +} + +@Suppress("FINAL_UPPER_BOUND") +public class ULongVarOf(rawPtr: NativePtr) : CPrimitiveVar(rawPtr) { + @Deprecated("Use sizeOf() or alignOf() instead.") + @Suppress("DEPRECATION") + companion object : Type(8) +} + +@Suppress("FINAL_UPPER_BOUND") +public class FloatVarOf(rawPtr: NativePtr) : CPrimitiveVar(rawPtr) { + @Deprecated("Use sizeOf() or alignOf() instead.") + @Suppress("DEPRECATION") + companion object : Type(4) +} + +@Suppress("FINAL_UPPER_BOUND") +public class DoubleVarOf(rawPtr: NativePtr) : CPrimitiveVar(rawPtr) { + @Deprecated("Use sizeOf() or alignOf() instead.") + @Suppress("DEPRECATION") + companion object : Type(8) +} + +public typealias BooleanVar = BooleanVarOf +public typealias ByteVar = ByteVarOf +public typealias ShortVar = ShortVarOf +public typealias IntVar = IntVarOf +public typealias LongVar = LongVarOf +public typealias UByteVar = UByteVarOf +public typealias UShortVar = UShortVarOf +public typealias UIntVar = UIntVarOf +public typealias ULongVar = ULongVarOf +public typealias FloatVar = FloatVarOf +public typealias DoubleVar = DoubleVarOf + +@Suppress("FINAL_UPPER_BOUND", "UNCHECKED_CAST") +public var BooleanVarOf.value: T + get() { + val byte = nativeMemUtils.getByte(this) + return byte.toBoolean() as T + } + set(value) = nativeMemUtils.putByte(this, value.toByte()) + +@Suppress("NOTHING_TO_INLINE") +public inline fun Boolean.toByte(): Byte = if (this) 1 else 0 + +@Suppress("NOTHING_TO_INLINE") +public inline fun Byte.toBoolean() = (this.toInt() != 0) + +@Suppress("FINAL_UPPER_BOUND", "UNCHECKED_CAST") +public var ByteVarOf.value: T + get() = nativeMemUtils.getByte(this) as T + set(value) = nativeMemUtils.putByte(this, value) + +@Suppress("FINAL_UPPER_BOUND", "UNCHECKED_CAST") +public var ShortVarOf.value: T + get() = nativeMemUtils.getShort(this) as T + set(value) = nativeMemUtils.putShort(this, value) + +@Suppress("FINAL_UPPER_BOUND", "UNCHECKED_CAST") +public var IntVarOf.value: T + get() = nativeMemUtils.getInt(this) as T + set(value) = nativeMemUtils.putInt(this, value) + +@Suppress("FINAL_UPPER_BOUND", "UNCHECKED_CAST") +public var LongVarOf.value: T + get() = nativeMemUtils.getLong(this) as T + set(value) = nativeMemUtils.putLong(this, value) + +@Suppress("FINAL_UPPER_BOUND", "UNCHECKED_CAST") +public var UByteVarOf.value: T + get() = nativeMemUtils.getByte(this).toUByte() as T + set(value) = nativeMemUtils.putByte(this, value.toByte()) + +@Suppress("FINAL_UPPER_BOUND", "UNCHECKED_CAST") +public var UShortVarOf.value: T + get() = nativeMemUtils.getShort(this).toUShort() as T + set(value) = nativeMemUtils.putShort(this, value.toShort()) + +@Suppress("FINAL_UPPER_BOUND", "UNCHECKED_CAST") +public var UIntVarOf.value: T + get() = nativeMemUtils.getInt(this).toUInt() as T + set(value) = nativeMemUtils.putInt(this, value.toInt()) + +@Suppress("FINAL_UPPER_BOUND", "UNCHECKED_CAST") +public var ULongVarOf.value: T + get() = nativeMemUtils.getLong(this).toULong() as T + set(value) = nativeMemUtils.putLong(this, value.toLong()) + +// TODO: ensure native floats have the appropriate binary representation + +@Suppress("FINAL_UPPER_BOUND", "UNCHECKED_CAST") +public var FloatVarOf.value: T + get() = nativeMemUtils.getFloat(this) as T + set(value) = nativeMemUtils.putFloat(this, value) + +@Suppress("FINAL_UPPER_BOUND", "UNCHECKED_CAST") +public var DoubleVarOf.value: T + get() = nativeMemUtils.getDouble(this) as T + set(value) = nativeMemUtils.putDouble(this, value) + + +public class CPointerVarOf>(rawPtr: NativePtr) : CVariable(rawPtr) { + @Deprecated("Use sizeOf() or alignOf() instead.") + @Suppress("DEPRECATION") + companion object : CVariable.Type(pointerSize.toLong(), pointerSize) +} + +/** + * The C data variable containing the pointer to `T`. + */ +public typealias CPointerVar = CPointerVarOf> + +/** + * The value of this variable. + */ +@Suppress("UNCHECKED_CAST") +public inline var

> CPointerVarOf

.value: P? + get() = interpretCPointer(nativeMemUtils.getNativePtr(this)) as P? + set(value) = nativeMemUtils.putNativePtr(this, value.rawValue) + +/** + * The code or data pointed by the value of this variable. + * + * @param T must not be abstract + */ +public inline var > CPointerVarOf

.pointed: T? + get() = this.value?.pointed + set(value) { + this.value = value?.ptr as P? + } + +public inline operator fun CPointer.get(index: Long): T { + val offset = if (index == 0L) { + 0L // optimization for JVM impl which uses reflection for now. + } else { + index * sizeOf() + } + return interpretPointed(this.rawValue + offset) +} + +public inline operator fun CPointer.get(index: Int): T = this.get(index.toLong()) + +@Suppress("NOTHING_TO_INLINE") +@JvmName("plus\$CPointer") +public inline operator fun > CPointer?.plus(index: Long): CPointer? = + interpretCPointer(this.rawValue + index * pointerSize) + +@Suppress("NOTHING_TO_INLINE") +@JvmName("plus\$CPointer") +public inline operator fun > CPointer?.plus(index: Int): CPointer? = + this + index.toLong() + +@Suppress("NOTHING_TO_INLINE") +public inline operator fun > CPointer>.get(index: Int): T? = + (this + index)!!.pointed.value + +@Suppress("NOTHING_TO_INLINE") +public inline operator fun > CPointer>.set(index: Int, value: T?) { + (this + index)!!.pointed.value = value +} + +@Suppress("NOTHING_TO_INLINE") +public inline operator fun > CPointer>.get(index: Long): T? = + (this + index)!!.pointed.value + +@Suppress("NOTHING_TO_INLINE") +public inline operator fun > CPointer>.set(index: Long, value: T?) { + (this + index)!!.pointed.value = value +} + +public typealias CArrayPointer = CPointer +public typealias CArrayPointerVar = CPointerVar + +/** + * The C function. + */ +public class CFunction>(rawPtr: NativePtr) : CPointed(rawPtr) diff --git a/kotlin-native/Interop/Runtime/src/main/kotlin/kotlinx/cinterop/Utils.kt b/kotlin-native/Interop/Runtime/src/main/kotlin/kotlinx/cinterop/Utils.kt new file mode 100644 index 00000000000..1c6c9c2443f --- /dev/null +++ b/kotlin-native/Interop/Runtime/src/main/kotlin/kotlinx/cinterop/Utils.kt @@ -0,0 +1,643 @@ +/* + * Copyright 2010-2017 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package kotlinx.cinterop + +public interface NativePlacement { + + public fun alloc(size: Long, align: Int): NativePointed + + public fun alloc(size: Int, align: Int): NativePointed = alloc(size.toLong(), align) +} + +public interface NativeFreeablePlacement : NativePlacement { + public fun free(mem: NativePtr) +} + +public fun NativeFreeablePlacement.free(pointer: CPointer<*>) = this.free(pointer.rawValue) +public fun NativeFreeablePlacement.free(pointed: NativePointed) = this.free(pointed.rawPtr) + +public object nativeHeap : NativeFreeablePlacement { + override fun alloc(size: Long, align: Int) = nativeMemUtils.alloc(size, align) + + override fun free(mem: NativePtr) = nativeMemUtils.free(mem) +} + +private typealias Deferred = () -> Unit + +public open class DeferScope { + + @PublishedApi + internal var topDeferred: Deferred? = null + + internal fun executeAllDeferred() { + topDeferred?.let { + it.invoke() + topDeferred = null + } + } + + inline fun defer(crossinline block: () -> Unit) { + val currentTop = topDeferred + topDeferred = { + try { + block() + } finally { + // TODO: it is possible to implement chaining without recursion, + // but it would require using an anonymous object here + // which is not yet supported in Kotlin Native inliner. + currentTop?.invoke() + } + } + } +} + +public abstract class AutofreeScope : DeferScope(), NativePlacement { + abstract override fun alloc(size: Long, align: Int): NativePointed +} + +public open class ArenaBase(private val parent: NativeFreeablePlacement = nativeHeap) : AutofreeScope() { + + private var lastChunk: NativePointed? = null + + final override fun alloc(size: Long, align: Int): NativePointed { + // Reserve space for a pointer: + val gapForPointer = maxOf(pointerSize, align) + + val chunk = parent.alloc(size = gapForPointer + size, align = gapForPointer) + nativeMemUtils.putNativePtr(chunk, lastChunk.rawPtr) + lastChunk = chunk + return interpretOpaquePointed(chunk.rawPtr + gapForPointer.toLong()) + } + + @PublishedApi + internal fun clearImpl() { + this.executeAllDeferred() + + var chunk = lastChunk + while (chunk != null) { + val nextChunk = nativeMemUtils.getNativePtr(chunk) + parent.free(chunk) + chunk = interpretNullableOpaquePointed(nextChunk) + } + } + +} + +public class Arena(parent: NativeFreeablePlacement = nativeHeap) : ArenaBase(parent) { + fun clear() = this.clearImpl() +} + +/** + * Allocates variable of given type. + * + * @param T must not be abstract + */ +public inline fun NativePlacement.alloc(): T = + @Suppress("DEPRECATION") + alloc(typeOf()).reinterpret() + +@PublishedApi +@Suppress("DEPRECATION") +internal fun NativePlacement.alloc(type: CVariable.Type): NativePointed = + alloc(type.size, type.align) + +/** + * Allocates variable of given type and initializes it applying given block. + * + * @param T must not be abstract + */ +public inline fun NativePlacement.alloc(initialize: T.() -> Unit): T = + alloc().also { it.initialize() } + +/** + * Allocates C array of given elements type and length. + * + * @param T must not be abstract + */ +public inline fun NativePlacement.allocArray(length: Long): CArrayPointer = + alloc(sizeOf() * length, alignOf()).reinterpret().ptr + +/** + * Allocates C array of given elements type and length. + * + * @param T must not be abstract + */ +public inline fun NativePlacement.allocArray(length: Int): CArrayPointer = + allocArray(length.toLong()) + +/** + * Allocates C array of given elements type and length, and initializes its elements applying given block. + * + * @param T must not be abstract + */ +public inline fun NativePlacement.allocArray(length: Long, + initializer: T.(index: Long)->Unit): CArrayPointer { + val res = allocArray(length) + + (0 .. length - 1).forEach { index -> + res[index].initializer(index) + } + + return res +} + +/** + * Allocates C array of given elements type and length, and initializes its elements applying given block. + * + * @param T must not be abstract + */ +public inline fun NativePlacement.allocArray( + length: Int, initializer: T.(index: Int)->Unit): CArrayPointer = allocArray(length.toLong()) { index -> + this.initializer(index.toInt()) + } + + +/** + * Allocates C array of pointers to given elements. + */ +public fun NativePlacement.allocArrayOfPointersTo(elements: List): CArrayPointer> { + val res = allocArray>(elements.size) + elements.forEachIndexed { index, value -> + res[index] = value?.ptr + } + return res +} + +/** + * Allocates C array of pointers to given elements. + */ +public fun NativePlacement.allocArrayOfPointersTo(vararg elements: T?) = + allocArrayOfPointersTo(listOf(*elements)) + +/** + * Allocates C array of given values. + */ +public inline fun > + NativePlacement.allocArrayOf(vararg elements: T?): CArrayPointer> { + return allocArrayOf(listOf(*elements)) +} + +/** + * Allocates C array of given values. + */ +public inline fun > + NativePlacement.allocArrayOf(elements: List): CArrayPointer> { + + val res = allocArray>(elements.size) + var index = 0 + while (index < elements.size) { + res[index] = elements[index] + ++index + } + return res +} + +public fun NativePlacement.allocArrayOf(elements: ByteArray): CArrayPointer { + val result = allocArray(elements.size) + nativeMemUtils.putByteArray(elements, result.pointed, elements.size) + return result +} + +public fun NativePlacement.allocArrayOf(vararg elements: Float): CArrayPointer { + val res = allocArray(elements.size) + var index = 0 + while (index < elements.size) { + res[index] = elements[index] + ++index + } + return res +} + +public fun NativePlacement.allocPointerTo() = alloc>() + +@PublishedApi +internal class ZeroValue(private val sizeBytes: Int, private val alignBytes: Int): CValue() { + // Optimization to avoid unneeded virtual calls in base class implementation. + override fun getPointer(scope: AutofreeScope): CPointer { + return place(interpretCPointer(scope.alloc(size, align).rawPtr)!!) + } + + override fun place(placement: CPointer): CPointer { + nativeMemUtils.zeroMemory(interpretPointed(placement.rawValue), sizeBytes) + return placement + } + override val size get() = sizeBytes + + override val align get() = alignBytes + +} +@Suppress("NOTHING_TO_INLINE") +public inline fun zeroValue(size: Int, align: Int): CValue = ZeroValue(size, align) + +public inline fun zeroValue(): CValue = zeroValue(sizeOf().toInt(), alignOf()) + +public inline fun cValue(): CValue = zeroValue() + +public fun CPointed.readValues(size: Int, align: Int): CValues { + val bytes = ByteArray(size) + nativeMemUtils.getByteArray(this, bytes, size) + + return object : CValue() { + // Optimization to avoid unneeded virtual calls in base class implementation. + override fun getPointer(scope: AutofreeScope): CPointer { + return place(interpretCPointer(scope.alloc(size, align).rawPtr)!!) + } + override fun place(placement: CPointer): CPointer { + nativeMemUtils.putByteArray(bytes, interpretPointed(placement.rawValue), bytes.size) + return placement + } + override val size get() = size + override val align get() = align + } +} + +public inline fun T.readValues(count: Int): CValues = + this.readValues(size = count * sizeOf().toInt(), align = alignOf()) + +public fun CPointed.readValue(size: Long, align: Int): CValue { + val bytes = ByteArray(size.toInt()) + nativeMemUtils.getByteArray(this, bytes, size.toInt()) + + return object : CValue() { + override fun place(placement: CPointer): CPointer { + nativeMemUtils.putByteArray(bytes, interpretPointed(placement.rawValue), bytes.size) + return placement + } + // Optimization to avoid unneeded virtual calls in base class implementation. + public override fun getPointer(scope: AutofreeScope): CPointer { + return place(interpretCPointer(scope.alloc(size, align).rawPtr)!!) + } + override val size get() = size.toInt() + override val align get() = align + } +} + +@Suppress("DEPRECATION") +@PublishedApi internal fun CPointed.readValue(type: CVariable.Type): CValue = + readValue(type.size, type.align) + +// Note: can't be declared as property due to possible clash with a struct field. +// TODO: find better name. +@Suppress("DEPRECATION") +public inline fun T.readValue(): CValue = this.readValue(typeOf()) + +public fun CValue.write(location: NativePtr) { + this.place(interpretCPointer(location)!!) +} + +// TODO: optimize +public fun CValues.getBytes(): ByteArray = memScoped { + val result = ByteArray(size) + nativeMemUtils.getByteArray( + source = this@getBytes.placeTo(memScope).reinterpret().pointed, + dest = result, + length = result.size + ) + result +} + +/** + * Calls the [block] with temporary copy of this value as receiver. + */ +public inline fun CValue.useContents(block: T.() -> R): R = memScoped { + this@useContents.placeTo(memScope).pointed.block() +} + +public inline fun CValue.copy(modify: T.() -> Unit): CValue = useContents { + this.modify() + this.readValue() +} + +public inline fun cValue(initialize: T.() -> Unit): CValue = + zeroValue().copy(modify = initialize) + +public inline fun createValues(count: Int, initializer: T.(index: Int) -> Unit) = memScoped { + val array = allocArray(count, initializer) + array[0].readValues(count) +} + +// TODO: optimize other [cValuesOf] methods: +/** + * Returns sequence of immutable values [CValues] to pass them to C code. + */ +fun cValuesOf(vararg elements: Byte): CValues = object : CValues() { + // Optimization to avoid unneeded virtual calls in base class implementation. + override fun getPointer(scope: AutofreeScope): CPointer { + return place(interpretCPointer(scope.alloc(size, align).rawPtr)!!) + } + override fun place(placement: CPointer): CPointer { + nativeMemUtils.putByteArray(elements, interpretPointed(placement.rawValue), elements.size) + return placement + } + + override val size get() = 1 * elements.size + override val align get() = 1 +} + +public fun cValuesOf(vararg elements: Short): CValues = + createValues(elements.size) { index -> this.value = elements[index] } + +public fun cValuesOf(vararg elements: Int): CValues = + createValues(elements.size) { index -> this.value = elements[index] } + +public fun cValuesOf(vararg elements: Long): CValues = + createValues(elements.size) { index -> this.value = elements[index] } + +public fun cValuesOf(vararg elements: Float): CValues = + createValues(elements.size) { index -> this.value = elements[index] } + +public fun cValuesOf(vararg elements: Double): CValues = + createValues(elements.size) { index -> this.value = elements[index] } + +public fun cValuesOf(vararg elements: CPointer?): CValues> = + createValues(elements.size) { index -> this.value = elements[index] } + +public fun ByteArray.toCValues() = cValuesOf(*this) +public fun ShortArray.toCValues() = cValuesOf(*this) +public fun IntArray.toCValues() = cValuesOf(*this) +public fun LongArray.toCValues() = cValuesOf(*this) +public fun FloatArray.toCValues() = cValuesOf(*this) +public fun DoubleArray.toCValues() = cValuesOf(*this) +public fun Array?>.toCValues() = cValuesOf(*this) +public fun List?>.toCValues() = this.toTypedArray().toCValues() + +private class CString(val bytes: ByteArray): CValues() { + override val size get() = bytes.size + 1 + override val align get() = 1 + + // Optimization to avoid unneeded virtual calls in base class implementation. + override fun getPointer(scope: AutofreeScope): CPointer { + return place(interpretCPointer(scope.alloc(size, align).rawPtr)!!) + } + override fun place(placement: CPointer): CPointer { + nativeMemUtils.putByteArray(bytes, placement.pointed, bytes.size) + placement[bytes.size] = 0.toByte() + return placement + } +} + +/** + * @return the value of zero-terminated UTF-8-encoded C string constructed from given [kotlin.String]. + */ +public val String.cstr: CValues + get() = CString(encodeToUtf8(this)) + +/** + * @return the value of zero-terminated UTF-8-encoded C string constructed from given [kotlin.String]. + */ +public val String.utf8: CValues + get() = CString(encodeToUtf8(this)) + +/** + * Convert this list of Kotlin strings to C array of C strings, + * allocating memory for the array and C strings with given [AutofreeScope]. + */ +public fun List.toCStringArray(autofreeScope: AutofreeScope): CPointer> = + autofreeScope.allocArrayOf(this.map { it.cstr.getPointer(autofreeScope) }) + +/** + * Convert this array of Kotlin strings to C array of C strings, + * allocating memory for the array and C strings with given [AutofreeScope]. + */ +public fun Array.toCStringArray(autofreeScope: AutofreeScope): CPointer> = + autofreeScope.allocArrayOf(this.map { it.cstr.getPointer(autofreeScope) }) + + +private class U16CString(val chars: CharArray): CValues() { + override val size get() = 2 * (chars.size + 1) + + override val align get() = 2 + + // Optimization to avoid unneeded virtual calls in base class implementation. + override fun getPointer(scope: AutofreeScope): CPointer { + return place(interpretCPointer(scope.alloc(size, align).rawPtr)!!) + } + + override fun place(placement: CPointer): CPointer { + nativeMemUtils.putCharArray(chars, placement.pointed, chars.size) + // TODO: fix, after KT-29627 is fixed. + nativeMemUtils.putShort((placement + chars.size)!!.pointed, 0) + return placement + } +} + +/** + * @return the value of zero-terminated UTF-16-encoded C string constructed from given [kotlin.String]. + */ +public val String.wcstr: CValues + get() = U16CString(this.toCharArray()) + +/** + * @return the value of zero-terminated UTF-16-encoded C string constructed from given [kotlin.String]. + */ +public val String.utf16: CValues + get() = U16CString(this.toCharArray()) + +private class U32CString(val chars: CharArray): CValues() { + override val size get() = 4 * (chars.size + 1) + + override val align get() = 4 + + // Optimization to avoid unneeded virtual calls in base class implementation. + override fun getPointer(scope: AutofreeScope): CPointer { + return place(interpretCPointer(scope.alloc(size, align).rawPtr)!!) + } + + override fun place(placement: CPointer): CPointer { + var indexIn = 0 + var indexOut = 0 + while (indexIn < chars.size) { + var value = chars[indexIn++].toInt() + if (value >= 0xd800 && value < 0xdc00) { + // Surrogate pair. + if (indexIn >= chars.size - 1) throw IllegalArgumentException() + indexIn++ + val next = chars[indexIn].toInt() + if (next < 0xdc00 || next >= 0xe000) throw IllegalArgumentException() + value = 0x10000 + ((value and 0x3ff) shl 10) + (next and 0x3ff) + } + nativeMemUtils.putInt((placement + indexOut)!!.pointed, value) + indexOut++ + } + nativeMemUtils.putInt((placement + indexOut)!!.pointed, 0) + return placement + } +} + +/** + * @return the value of zero-terminated UTF-32-encoded C string constructed from given [kotlin.String]. + */ +public val String.utf32: CValues + get() = U32CString(this.toCharArray()) + + +// TODO: optimize +/** + * @return the [kotlin.String] decoded from given zero-terminated UTF-8-encoded C string. + */ +public fun CPointer.toKStringFromUtf8(): String { + val nativeBytes = this + + var length = 0 + while (nativeBytes[length] != 0.toByte()) { + ++length + } + + val bytes = ByteArray(length) + nativeMemUtils.getByteArray(nativeBytes.pointed, bytes, length) + return decodeFromUtf8(bytes) +} + +/** + * @return the [kotlin.String] decoded from given zero-terminated UTF-8-encoded C string. + */ +public fun CPointer.toKString(): String = this.toKStringFromUtf8() + +/** + * @return the [kotlin.String] decoded from given zero-terminated UTF-16-encoded C string. + */ +public fun CPointer.toKStringFromUtf16(): String { + val nativeBytes = this + + var length = 0 + while (nativeBytes[length] != 0.toShort()) { + ++length + } + val chars = CharArray(length) + var index = 0 + while (index < length) { + chars[index] = nativeBytes[index].toChar() + ++index + } + return String(chars) +} + +/** + * @return the [kotlin.String] decoded from given zero-terminated UTF-32-encoded C string. + */ +public fun CPointer.toKStringFromUtf32(): String { + val nativeBytes = this + + var fromIndex = 0 + var toIndex = 0 + while (true) { + val value = nativeBytes[fromIndex++] + if (value == 0) break + toIndex++ + if (value >= 0x10000 && value <= 0x10ffff) { + toIndex++ + } + } + val length = toIndex + val chars = CharArray(length) + fromIndex = 0 + toIndex = 0 + while (toIndex < length) { + var value = nativeBytes[fromIndex++] + if (value >= 0x10000 && value <= 0x10ffff) { + chars[toIndex++] = (((value - 0x10000) shr 10) or 0xd800).toChar() + chars[toIndex++] = (((value - 0x10000) and 0x3ff) or 0xdc00).toChar() + } else { + chars[toIndex++] = value.toChar() + } + } + return String(chars) +} + +/** + * Decodes a string from the bytes in UTF-8 encoding in this array. + * Bytes following the first occurrence of `0` byte, if it occurs, are not decoded. + * + * Malformed byte sequences are replaced by the replacement char `\uFFFD`. + */ +@OptIn(ExperimentalStdlibApi::class) +@SinceKotlin("1.3") +public fun ByteArray.toKString() : String { + val realEndIndex = realEndIndex(this, 0, this.size) + return decodeToString(0, realEndIndex) +} + +/** + * Decodes a string from the bytes in UTF-8 encoding in this array or its subrange. + * Bytes following the first occurrence of `0` byte, if it occurs, are not decoded. + * + * @param startIndex the beginning (inclusive) of the subrange to decode, 0 by default. + * @param endIndex the end (exclusive) of the subrange to decode, size of this array by default. + * @param throwOnInvalidSequence specifies whether to throw an exception on malformed byte sequence or replace it by the replacement char `\uFFFD`. + * + * @throws IndexOutOfBoundsException if [startIndex] is less than zero or [endIndex] is greater than the size of this array. + * @throws IllegalArgumentException if [startIndex] is greater than [endIndex]. + * @throws CharacterCodingException if the byte array contains malformed UTF-8 byte sequence and [throwOnInvalidSequence] is true. + */ +@OptIn(ExperimentalStdlibApi::class) +@SinceKotlin("1.3") +public fun ByteArray.toKString( + startIndex: Int = 0, + endIndex: Int = this.size, + throwOnInvalidSequence: Boolean = false +) : String { + checkBoundsIndexes(startIndex, endIndex, this.size) + val realEndIndex = realEndIndex(this, startIndex, endIndex) + return decodeToString(startIndex, realEndIndex, throwOnInvalidSequence) +} + +private fun realEndIndex(byteArray: ByteArray, startIndex: Int, endIndex: Int): Int { + var index = startIndex + while (index < endIndex && byteArray[index] != 0.toByte()) { + index++ + } + return index +} + +private fun checkBoundsIndexes(startIndex: Int, endIndex: Int, size: Int) { + if (startIndex < 0 || endIndex > size) { + throw IndexOutOfBoundsException("startIndex: $startIndex, endIndex: $endIndex, size: $size") + } + if (startIndex > endIndex) { + throw IllegalArgumentException("startIndex: $startIndex > endIndex: $endIndex") + } +} + +public class MemScope : ArenaBase() { + + val memScope: MemScope + get() = this + + val CValues.ptr: CPointer + get() = this@ptr.getPointer(this@MemScope) +} + +// TODO: consider renaming `memScoped` because it now supports `defer`. + +/** + * Runs given [block] providing allocation of memory + * which will be automatically disposed at the end of this scope. + */ +public inline fun memScoped(block: MemScope.()->R): R { + val memScope = MemScope() + try { + return memScope.block() + } finally { + memScope.clearImpl() + } +} + +public fun COpaquePointer.readBytes(count: Int): ByteArray { + val result = ByteArray(count) + nativeMemUtils.getByteArray(this.reinterpret().pointed, result, count) + return result +} diff --git a/kotlin-native/Interop/Runtime/src/main/kotlin/kotlinx/cinterop/package-info.java b/kotlin-native/Interop/Runtime/src/main/kotlin/kotlinx/cinterop/package-info.java new file mode 100644 index 00000000000..9e737b69fe9 --- /dev/null +++ b/kotlin-native/Interop/Runtime/src/main/kotlin/kotlinx/cinterop/package-info.java @@ -0,0 +1,22 @@ +/* + * Copyright 2010-2017 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/** + * This package contains API and runtime support for calling C code from Kotlin (aka Kotlin C interop). + * + * TODO: decide about package location. + */ +package kotlinx.cinterop; \ No newline at end of file diff --git a/kotlin-native/Interop/Runtime/src/native/kotlin/kotlinx/cinterop/ForeignException.kt b/kotlin-native/Interop/Runtime/src/native/kotlin/kotlinx/cinterop/ForeignException.kt new file mode 100644 index 00000000000..9872a71a2b6 --- /dev/null +++ b/kotlin-native/Interop/Runtime/src/native/kotlin/kotlinx/cinterop/ForeignException.kt @@ -0,0 +1,21 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ +package kotlinx.cinterop + +import kotlin.native.internal.ExportForCppRuntime + +public class ForeignException internal constructor(val nativeException: Any?): Exception() { + override val message: String = nativeException?.let { + kotlin_ObjCExport_ExceptionDetails(nativeException) + }?: "" + + // Current implementation expects NSException type only, which is ensured by CodeGenerator. + @SymbolName("Kotlin_ObjCExport_ExceptionDetails") + private external fun kotlin_ObjCExport_ExceptionDetails(nativeException: Any): String? +} + +@ExportForCppRuntime +internal fun CreateForeignException(payload: NativePtr): Throwable + = ForeignException(interpretObjCPointerOrNull(payload)) diff --git a/kotlin-native/Interop/Runtime/src/native/kotlin/kotlinx/cinterop/FunctionPointers.kt b/kotlin-native/Interop/Runtime/src/native/kotlin/kotlinx/cinterop/FunctionPointers.kt new file mode 100644 index 00000000000..b59df85afcc --- /dev/null +++ b/kotlin-native/Interop/Runtime/src/native/kotlin/kotlinx/cinterop/FunctionPointers.kt @@ -0,0 +1,67 @@ +/* + * Copyright 2010-2017 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package kotlinx.cinterop + +import kotlin.native.internal.TypedIntrinsic +import kotlin.native.internal.IntrinsicType +import kotlin.native.internal.ExportForCompiler + +@TypedIntrinsic(IntrinsicType.INTEROP_FUNPTR_INVOKE) external operator fun CPointer R>>.invoke(): R + +@TypedIntrinsic(IntrinsicType.INTEROP_FUNPTR_INVOKE) external operator fun CPointer R>>.invoke(p1: P1): R + +@TypedIntrinsic(IntrinsicType.INTEROP_FUNPTR_INVOKE) external operator fun CPointer R>>.invoke(p1: P1, p2: P2): R + +@TypedIntrinsic(IntrinsicType.INTEROP_FUNPTR_INVOKE) external operator fun CPointer R>>.invoke(p1: P1, p2: P2, p3: P3): R + +@TypedIntrinsic(IntrinsicType.INTEROP_FUNPTR_INVOKE) external operator fun CPointer R>>.invoke(p1: P1, p2: P2, p3: P3, p4: P4): R + +@TypedIntrinsic(IntrinsicType.INTEROP_FUNPTR_INVOKE) external operator fun CPointer R>>.invoke(p1: P1, p2: P2, p3: P3, p4: P4, p5: P5): R + +@TypedIntrinsic(IntrinsicType.INTEROP_FUNPTR_INVOKE) external operator fun CPointer R>>.invoke(p1: P1, p2: P2, p3: P3, p4: P4, p5: P5, p6: P6): R + +@TypedIntrinsic(IntrinsicType.INTEROP_FUNPTR_INVOKE) external operator fun CPointer R>>.invoke(p1: P1, p2: P2, p3: P3, p4: P4, p5: P5, p6: P6, p7: P7): R + +@TypedIntrinsic(IntrinsicType.INTEROP_FUNPTR_INVOKE) external operator fun CPointer R>>.invoke(p1: P1, p2: P2, p3: P3, p4: P4, p5: P5, p6: P6, p7: P7, p8: P8): R + +@TypedIntrinsic(IntrinsicType.INTEROP_FUNPTR_INVOKE) external operator fun CPointer R>>.invoke(p1: P1, p2: P2, p3: P3, p4: P4, p5: P5, p6: P6, p7: P7, p8: P8, p9: P9): R + +@TypedIntrinsic(IntrinsicType.INTEROP_FUNPTR_INVOKE) external operator fun CPointer R>>.invoke(p1: P1, p2: P2, p3: P3, p4: P4, p5: P5, p6: P6, p7: P7, p8: P8, p9: P9, p10: P10): R + +@TypedIntrinsic(IntrinsicType.INTEROP_FUNPTR_INVOKE) external operator fun CPointer R>>.invoke(p1: P1, p2: P2, p3: P3, p4: P4, p5: P5, p6: P6, p7: P7, p8: P8, p9: P9, p10: P10, p11: P11): R + +@TypedIntrinsic(IntrinsicType.INTEROP_FUNPTR_INVOKE) external operator fun CPointer R>>.invoke(p1: P1, p2: P2, p3: P3, p4: P4, p5: P5, p6: P6, p7: P7, p8: P8, p9: P9, p10: P10, p11: P11, p12: P12): R + +@TypedIntrinsic(IntrinsicType.INTEROP_FUNPTR_INVOKE) external operator fun CPointer R>>.invoke(p1: P1, p2: P2, p3: P3, p4: P4, p5: P5, p6: P6, p7: P7, p8: P8, p9: P9, p10: P10, p11: P11, p12: P12, p13: P13): R + +@TypedIntrinsic(IntrinsicType.INTEROP_FUNPTR_INVOKE) external operator fun CPointer R>>.invoke(p1: P1, p2: P2, p3: P3, p4: P4, p5: P5, p6: P6, p7: P7, p8: P8, p9: P9, p10: P10, p11: P11, p12: P12, p13: P13, p14: P14): R + +@TypedIntrinsic(IntrinsicType.INTEROP_FUNPTR_INVOKE) external operator fun CPointer R>>.invoke(p1: P1, p2: P2, p3: P3, p4: P4, p5: P5, p6: P6, p7: P7, p8: P8, p9: P9, p10: P10, p11: P11, p12: P12, p13: P13, p14: P14, p15: P15): R + +@TypedIntrinsic(IntrinsicType.INTEROP_FUNPTR_INVOKE) external operator fun CPointer R>>.invoke(p1: P1, p2: P2, p3: P3, p4: P4, p5: P5, p6: P6, p7: P7, p8: P8, p9: P9, p10: P10, p11: P11, p12: P12, p13: P13, p14: P14, p15: P15, p16: P16): R + +@TypedIntrinsic(IntrinsicType.INTEROP_FUNPTR_INVOKE) external operator fun CPointer R>>.invoke(p1: P1, p2: P2, p3: P3, p4: P4, p5: P5, p6: P6, p7: P7, p8: P8, p9: P9, p10: P10, p11: P11, p12: P12, p13: P13, p14: P14, p15: P15, p16: P16, p17: P17): R + +@TypedIntrinsic(IntrinsicType.INTEROP_FUNPTR_INVOKE) external operator fun CPointer R>>.invoke(p1: P1, p2: P2, p3: P3, p4: P4, p5: P5, p6: P6, p7: P7, p8: P8, p9: P9, p10: P10, p11: P11, p12: P12, p13: P13, p14: P14, p15: P15, p16: P16, p17: P17, p18: P18): R + +@TypedIntrinsic(IntrinsicType.INTEROP_FUNPTR_INVOKE) external operator fun CPointer R>>.invoke(p1: P1, p2: P2, p3: P3, p4: P4, p5: P5, p6: P6, p7: P7, p8: P8, p9: P9, p10: P10, p11: P11, p12: P12, p13: P13, p14: P14, p15: P15, p16: P16, p17: P17, p18: P18, p19: P19): R + +@TypedIntrinsic(IntrinsicType.INTEROP_FUNPTR_INVOKE) external operator fun CPointer R>>.invoke(p1: P1, p2: P2, p3: P3, p4: P4, p5: P5, p6: P6, p7: P7, p8: P8, p9: P9, p10: P10, p11: P11, p12: P12, p13: P13, p14: P14, p15: P15, p16: P16, p17: P17, p18: P18, p19: P19, p20: P20): R + +@TypedIntrinsic(IntrinsicType.INTEROP_FUNPTR_INVOKE) external operator fun CPointer R>>.invoke(p1: P1, p2: P2, p3: P3, p4: P4, p5: P5, p6: P6, p7: P7, p8: P8, p9: P9, p10: P10, p11: P11, p12: P12, p13: P13, p14: P14, p15: P15, p16: P16, p17: P17, p18: P18, p19: P19, p20: P20, p21: P21): R + +@TypedIntrinsic(IntrinsicType.INTEROP_FUNPTR_INVOKE) external operator fun CPointer R>>.invoke(p1: P1, p2: P2, p3: P3, p4: P4, p5: P5, p6: P6, p7: P7, p8: P8, p9: P9, p10: P10, p11: P11, p12: P12, p13: P13, p14: P14, p15: P15, p16: P16, p17: P17, p18: P18, p19: P19, p20: P20, p21: P21, p22: P22): R diff --git a/kotlin-native/Interop/Runtime/src/native/kotlin/kotlinx/cinterop/NativeMem.kt b/kotlin-native/Interop/Runtime/src/native/kotlin/kotlinx/cinterop/NativeMem.kt new file mode 100644 index 00000000000..88e69256436 --- /dev/null +++ b/kotlin-native/Interop/Runtime/src/native/kotlin/kotlinx/cinterop/NativeMem.kt @@ -0,0 +1,162 @@ +/* + * Copyright 2010-2017 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package kotlinx.cinterop + +import kotlin.native.* +import kotlin.native.internal.Intrinsic +import kotlin.native.internal.TypedIntrinsic +import kotlin.native.internal.IntrinsicType + +@PublishedApi +internal inline val pointerSize: Int + get() = getPointerSize() + +@PublishedApi +@TypedIntrinsic(IntrinsicType.INTEROP_GET_POINTER_SIZE) +internal external fun getPointerSize(): Int + +// TODO: do not use singleton because it leads to init-check on any access. +@PublishedApi +internal object nativeMemUtils { + @TypedIntrinsic(IntrinsicType.INTEROP_READ_PRIMITIVE) external fun getByte(mem: NativePointed): Byte + @TypedIntrinsic(IntrinsicType.INTEROP_WRITE_PRIMITIVE) external fun putByte(mem: NativePointed, value: Byte) + + @TypedIntrinsic(IntrinsicType.INTEROP_READ_PRIMITIVE) external fun getShort(mem: NativePointed): Short + @TypedIntrinsic(IntrinsicType.INTEROP_WRITE_PRIMITIVE) external fun putShort(mem: NativePointed, value: Short) + + @TypedIntrinsic(IntrinsicType.INTEROP_READ_PRIMITIVE) external fun getInt(mem: NativePointed): Int + @TypedIntrinsic(IntrinsicType.INTEROP_WRITE_PRIMITIVE) external fun putInt(mem: NativePointed, value: Int) + + @TypedIntrinsic(IntrinsicType.INTEROP_READ_PRIMITIVE) external fun getLong(mem: NativePointed): Long + @TypedIntrinsic(IntrinsicType.INTEROP_WRITE_PRIMITIVE) external fun putLong(mem: NativePointed, value: Long) + + @TypedIntrinsic(IntrinsicType.INTEROP_READ_PRIMITIVE) external fun getFloat(mem: NativePointed): Float + @TypedIntrinsic(IntrinsicType.INTEROP_WRITE_PRIMITIVE) external fun putFloat(mem: NativePointed, value: Float) + + @TypedIntrinsic(IntrinsicType.INTEROP_READ_PRIMITIVE) external fun getDouble(mem: NativePointed): Double + @TypedIntrinsic(IntrinsicType.INTEROP_WRITE_PRIMITIVE) external fun putDouble(mem: NativePointed, value: Double) + + @TypedIntrinsic(IntrinsicType.INTEROP_READ_PRIMITIVE) external fun getNativePtr(mem: NativePointed): NativePtr + @TypedIntrinsic(IntrinsicType.INTEROP_WRITE_PRIMITIVE) external fun putNativePtr(mem: NativePointed, value: NativePtr) + + @TypedIntrinsic(IntrinsicType.INTEROP_READ_PRIMITIVE) external fun getVector(mem: NativePointed): Vector128 + @TypedIntrinsic(IntrinsicType.INTEROP_WRITE_PRIMITIVE) external fun putVector(mem: NativePointed, value: Vector128) + + // TODO: optimize + fun getByteArray(source: NativePointed, dest: ByteArray, length: Int) { + val sourceArray = source.reinterpret().ptr + var index = 0 + while (index < length) { + dest[index] = sourceArray[index] + ++index + } + } + + // TODO: optimize + fun putByteArray(source: ByteArray, dest: NativePointed, length: Int) { + val destArray = dest.reinterpret().ptr + var index = 0 + while (index < length) { + destArray[index] = source[index] + ++index + } + } + + // TODO: optimize + fun getCharArray(source: NativePointed, dest: CharArray, length: Int) { + val sourceArray = source.reinterpret().ptr + var index = 0 + while (index < length) { + dest[index] = sourceArray[index].toChar() + ++index + } + } + + // TODO: optimize + fun putCharArray(source: CharArray, dest: NativePointed, length: Int) { + val destArray = dest.reinterpret().ptr + var index = 0 + while (index < length) { + destArray[index] = source[index].toShort() + ++index + } + } + + // TODO: optimize + fun zeroMemory(dest: NativePointed, length: Int): Unit { + val destArray = dest.reinterpret().ptr + var index = 0 + while (index < length) { + destArray[index] = 0 + ++index + } + } + + // TODO: optimize + fun copyMemory(dest: NativePointed, length: Int, src: NativePointed): Unit { + val destArray = dest.reinterpret().ptr + val srcArray = src.reinterpret().ptr + var index = 0 + while (index < length) { + destArray[index] = srcArray[index] + ++index + } + } + + fun alloc(size: Long, align: Int): NativePointed { + val ptr = malloc(size, align) + if (ptr == nativeNullPtr) { + throw OutOfMemoryError("unable to allocate native memory") + } + return interpretOpaquePointed(ptr) + } + + fun free(mem: NativePtr) { + cfree(mem) + } +} + +public fun CPointer.toKStringFromUtf16(): String { + val nativeBytes = this + + var length = 0 + while (nativeBytes[length] != 0.toUShort()) { + ++length + } + val chars = kotlin.CharArray(length) + var index = 0 + while (index < length) { + chars[index] = nativeBytes[index].toShort().toChar() + ++index + } + return String(chars) +} + +public fun CPointer.toKString(): String = this.toKStringFromUtf16() + +public fun CPointer.toKString(): String = this.toKStringFromUtf16() + +@SymbolName("Kotlin_interop_malloc") +private external fun malloc(size: Long, align: Int): NativePtr + +@SymbolName("Kotlin_interop_free") +private external fun cfree(ptr: NativePtr) + +@TypedIntrinsic(IntrinsicType.INTEROP_READ_BITS) +external fun readBits(ptr: NativePtr, offset: Long, size: Int, signed: Boolean): Long +@TypedIntrinsic(IntrinsicType.INTEROP_WRITE_BITS) +external fun writeBits(ptr: NativePtr, offset: Long, size: Int, value: Long) diff --git a/kotlin-native/Interop/Runtime/src/native/kotlin/kotlinx/cinterop/NativeStableRef.kt b/kotlin-native/Interop/Runtime/src/native/kotlin/kotlinx/cinterop/NativeStableRef.kt new file mode 100644 index 00000000000..872427ebd41 --- /dev/null +++ b/kotlin-native/Interop/Runtime/src/native/kotlin/kotlinx/cinterop/NativeStableRef.kt @@ -0,0 +1,28 @@ +/* + * Copyright 2010-2017 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package kotlinx.cinterop +import kotlin.native.* + +@SymbolName("Kotlin_Interop_createStablePointer") +internal external fun createStablePointer(any: Any): COpaquePointer + +@SymbolName("Kotlin_Interop_disposeStablePointer") +internal external fun disposeStablePointer(pointer: COpaquePointer) + +@PublishedApi +@SymbolName("Kotlin_Interop_derefStablePointer") +internal external fun derefStablePointer(pointer: COpaquePointer): Any diff --git a/kotlin-native/Interop/Runtime/src/native/kotlin/kotlinx/cinterop/NativeTypes.kt b/kotlin-native/Interop/Runtime/src/native/kotlin/kotlinx/cinterop/NativeTypes.kt new file mode 100644 index 00000000000..b7feb4f7359 --- /dev/null +++ b/kotlin-native/Interop/Runtime/src/native/kotlin/kotlinx/cinterop/NativeTypes.kt @@ -0,0 +1,123 @@ +/* + * Copyright 2010-2017 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package kotlinx.cinterop + +import kotlin.native.internal.getNativeNullPtr +import kotlin.native.internal.reinterpret +import kotlin.native.internal.Intrinsic +import kotlin.native.internal.VolatileLambda +import kotlin.native.internal.TypedIntrinsic +import kotlin.native.internal.IntrinsicType + +typealias NativePtr = kotlin.native.internal.NativePtr +internal typealias NonNullNativePtr = kotlin.native.internal.NonNullNativePtr + +@Suppress("NOTHING_TO_INLINE") +internal inline fun NativePtr.toNonNull() = this.reinterpret() + +inline val nativeNullPtr: NativePtr + get() = getNativeNullPtr() + +@Deprecated("Use sizeOf() or alignOf() instead.") +@Suppress("DEPRECATION") +fun typeOf(): CVariable.Type = throw Error("typeOf() is called with erased argument") + +/** + * Performs type cast of the native pointer to given interop type, including null values. + * + * @param T must not be abstract + */ +@TypedIntrinsic(IntrinsicType.IDENTITY) +external fun interpretNullablePointed(ptr: NativePtr): T? + +/** + * Performs type cast of the [CPointer] from the given raw pointer. + */ +@TypedIntrinsic(IntrinsicType.IDENTITY) +external fun interpretCPointer(rawValue: NativePtr): CPointer? + +@TypedIntrinsic(IntrinsicType.IDENTITY) +external fun NativePointed.getRawPointer(): NativePtr + +@TypedIntrinsic(IntrinsicType.IDENTITY) +external fun CPointer<*>.getRawValue(): NativePtr + +internal fun CPointer<*>.cPointerToString() = "CPointer(raw=$rawValue)" + +public class Vector128VarOf(rawPtr: NativePtr) : CVariable(rawPtr) { + @Deprecated("Use sizeOf() or alignOf() instead.") + @Suppress("DEPRECATION") + companion object : Type(size = 16, align = 16) +} + +public typealias Vector128Var = Vector128VarOf + +public var Vector128VarOf.value: T + get() = nativeMemUtils.getVector(this) as T + set(value) = nativeMemUtils.putVector(this, value) + +/** + * Returns a pointer to C function which calls given Kotlin *static* function. + * + * @param function must be *static*, i.e. an (unbound) reference to a Kotlin function or + * a closure which doesn't capture any variable + */ +@TypedIntrinsic(IntrinsicType.INTEROP_STATIC_C_FUNCTION) external fun staticCFunction(@VolatileLambda function: () -> R): CPointer R>> + +@TypedIntrinsic(IntrinsicType.INTEROP_STATIC_C_FUNCTION) external fun staticCFunction(@VolatileLambda function: (P1) -> R): CPointer R>> + +@TypedIntrinsic(IntrinsicType.INTEROP_STATIC_C_FUNCTION) external fun staticCFunction(@VolatileLambda function: (P1, P2) -> R): CPointer R>> + +@TypedIntrinsic(IntrinsicType.INTEROP_STATIC_C_FUNCTION) external fun staticCFunction(@VolatileLambda function: (P1, P2, P3) -> R): CPointer R>> + +@TypedIntrinsic(IntrinsicType.INTEROP_STATIC_C_FUNCTION) external fun staticCFunction(@VolatileLambda function: (P1, P2, P3, P4) -> R): CPointer R>> + +@TypedIntrinsic(IntrinsicType.INTEROP_STATIC_C_FUNCTION) external fun staticCFunction(@VolatileLambda function: (P1, P2, P3, P4, P5) -> R): CPointer R>> + +@TypedIntrinsic(IntrinsicType.INTEROP_STATIC_C_FUNCTION) external fun staticCFunction(@VolatileLambda function: (P1, P2, P3, P4, P5, P6) -> R): CPointer R>> + +@TypedIntrinsic(IntrinsicType.INTEROP_STATIC_C_FUNCTION) external fun staticCFunction(@VolatileLambda function: (P1, P2, P3, P4, P5, P6, P7) -> R): CPointer R>> + +@TypedIntrinsic(IntrinsicType.INTEROP_STATIC_C_FUNCTION) external fun staticCFunction(@VolatileLambda function: (P1, P2, P3, P4, P5, P6, P7, P8) -> R): CPointer R>> + +@TypedIntrinsic(IntrinsicType.INTEROP_STATIC_C_FUNCTION) external fun staticCFunction(@VolatileLambda function: (P1, P2, P3, P4, P5, P6, P7, P8, P9) -> R): CPointer R>> + +@TypedIntrinsic(IntrinsicType.INTEROP_STATIC_C_FUNCTION) external fun staticCFunction(@VolatileLambda function: (P1, P2, P3, P4, P5, P6, P7, P8, P9, P10) -> R): CPointer R>> + +@TypedIntrinsic(IntrinsicType.INTEROP_STATIC_C_FUNCTION) external fun staticCFunction(@VolatileLambda function: (P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11) -> R): CPointer R>> + +@TypedIntrinsic(IntrinsicType.INTEROP_STATIC_C_FUNCTION) external fun staticCFunction(@VolatileLambda function: (P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12) -> R): CPointer R>> + +@TypedIntrinsic(IntrinsicType.INTEROP_STATIC_C_FUNCTION) external fun staticCFunction(@VolatileLambda function: (P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13) -> R): CPointer R>> + +@TypedIntrinsic(IntrinsicType.INTEROP_STATIC_C_FUNCTION) external fun staticCFunction(@VolatileLambda function: (P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14) -> R): CPointer R>> + +@TypedIntrinsic(IntrinsicType.INTEROP_STATIC_C_FUNCTION) external fun staticCFunction(@VolatileLambda function: (P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15) -> R): CPointer R>> + +@TypedIntrinsic(IntrinsicType.INTEROP_STATIC_C_FUNCTION) external fun staticCFunction(@VolatileLambda function: (P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16) -> R): CPointer R>> + +@TypedIntrinsic(IntrinsicType.INTEROP_STATIC_C_FUNCTION) external fun staticCFunction(@VolatileLambda function: (P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17) -> R): CPointer R>> + +@TypedIntrinsic(IntrinsicType.INTEROP_STATIC_C_FUNCTION) external fun staticCFunction(@VolatileLambda function: (P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18) -> R): CPointer R>> + +@TypedIntrinsic(IntrinsicType.INTEROP_STATIC_C_FUNCTION) external fun staticCFunction(@VolatileLambda function: (P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19) -> R): CPointer R>> + +@TypedIntrinsic(IntrinsicType.INTEROP_STATIC_C_FUNCTION) external fun staticCFunction(@VolatileLambda function: (P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20) -> R): CPointer R>> + +@TypedIntrinsic(IntrinsicType.INTEROP_STATIC_C_FUNCTION) external fun staticCFunction(@VolatileLambda function: (P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21) -> R): CPointer R>> + +@TypedIntrinsic(IntrinsicType.INTEROP_STATIC_C_FUNCTION) external fun staticCFunction(@VolatileLambda function: (P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22) -> R): CPointer R>> diff --git a/kotlin-native/Interop/Runtime/src/native/kotlin/kotlinx/cinterop/NativeUtils.kt b/kotlin-native/Interop/Runtime/src/native/kotlin/kotlinx/cinterop/NativeUtils.kt new file mode 100644 index 00000000000..846bd3650f4 --- /dev/null +++ b/kotlin-native/Interop/Runtime/src/native/kotlin/kotlinx/cinterop/NativeUtils.kt @@ -0,0 +1,68 @@ +/* + * Copyright 2010-2017 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package kotlinx.cinterop + +import kotlin.native.internal.Intrinsic +import kotlin.native.internal.TypedIntrinsic +import kotlin.native.internal.IntrinsicType + +internal fun decodeFromUtf8(bytes: ByteArray): String = bytes.decodeToString() +internal fun encodeToUtf8(str: String): ByteArray = str.encodeToByteArray() + +@TypedIntrinsic(IntrinsicType.INTEROP_BITS_TO_FLOAT) +external fun bitsToFloat(bits: Int): Float + +@TypedIntrinsic(IntrinsicType.INTEROP_BITS_TO_DOUBLE) +external fun bitsToDouble(bits: Long): Double + +// TODO: deprecate. +@TypedIntrinsic(IntrinsicType.INTEROP_SIGN_EXTEND) +external inline fun Number.signExtend(): R + +// TODO: deprecate. +@TypedIntrinsic(IntrinsicType.INTEROP_NARROW) +external inline fun Number.narrow(): R + +@TypedIntrinsic(IntrinsicType.INTEROP_CONVERT) external inline fun Byte.convert(): R +@TypedIntrinsic(IntrinsicType.INTEROP_CONVERT) external inline fun Short.convert(): R +@TypedIntrinsic(IntrinsicType.INTEROP_CONVERT) external inline fun Int.convert(): R +@TypedIntrinsic(IntrinsicType.INTEROP_CONVERT) external inline fun Long.convert(): R +@TypedIntrinsic(IntrinsicType.INTEROP_CONVERT) external inline fun UByte.convert(): R +@TypedIntrinsic(IntrinsicType.INTEROP_CONVERT) external inline fun UShort.convert(): R +@TypedIntrinsic(IntrinsicType.INTEROP_CONVERT) external inline fun UInt.convert(): R +@TypedIntrinsic(IntrinsicType.INTEROP_CONVERT) external inline fun ULong.convert(): R + +@Target(AnnotationTarget.FUNCTION, AnnotationTarget.PROPERTY_GETTER, AnnotationTarget.PROPERTY_SETTER, AnnotationTarget.FILE) +@Retention(AnnotationRetention.SOURCE) +internal annotation class JvmName(val name: String) + +fun cValuesOf(vararg elements: UByte): CValues = + createValues(elements.size) { index -> this.value = elements[index] } + +fun cValuesOf(vararg elements: UShort): CValues = + createValues(elements.size) { index -> this.value = elements[index] } + +fun cValuesOf(vararg elements: UInt): CValues = + createValues(elements.size) { index -> this.value = elements[index] } + +fun cValuesOf(vararg elements: ULong): CValues = + createValues(elements.size) { index -> this.value = elements[index] } + +fun UByteArray.toCValues() = cValuesOf(*this) +fun UShortArray.toCValues() = cValuesOf(*this) +fun UIntArray.toCValues() = cValuesOf(*this) +fun ULongArray.toCValues() = cValuesOf(*this) \ No newline at end of file diff --git a/kotlin-native/Interop/Runtime/src/native/kotlin/kotlinx/cinterop/ObjectiveCImpl.kt b/kotlin-native/Interop/Runtime/src/native/kotlin/kotlinx/cinterop/ObjectiveCImpl.kt new file mode 100644 index 00000000000..8b1d65f5ffd --- /dev/null +++ b/kotlin-native/Interop/Runtime/src/native/kotlin/kotlinx/cinterop/ObjectiveCImpl.kt @@ -0,0 +1,227 @@ +/* + * Copyright 2010-2017 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +@file:Suppress("NOTHING_TO_INLINE") + +package kotlinx.cinterop +import kotlin.native.* +import kotlin.native.internal.ExportTypeInfo +import kotlin.native.internal.ExportForCppRuntime +import kotlin.native.internal.TypedIntrinsic +import kotlin.native.internal.IntrinsicType +import kotlin.native.internal.FilterExceptions + +interface ObjCObject +interface ObjCClass : ObjCObject +interface ObjCClassOf : ObjCClass // TODO: T should be added to ObjCClass and all meta-classes instead. +typealias ObjCObjectMeta = ObjCClass + +interface ObjCProtocol : ObjCObject + +@ExportTypeInfo("theForeignObjCObjectTypeInfo") +@kotlin.native.internal.Frozen +internal open class ForeignObjCObject : kotlin.native.internal.ObjCObjectWrapper + +abstract class ObjCObjectBase protected constructor() : ObjCObject { + @Target(AnnotationTarget.CONSTRUCTOR) + @Retention(AnnotationRetention.SOURCE) + annotation class OverrideInit +} +abstract class ObjCObjectBaseMeta protected constructor() : ObjCObjectBase(), ObjCObjectMeta {} + +fun optional(): Nothing = throw RuntimeException("Do not call me!!!") + +@Deprecated( + "Add @OverrideInit to constructor to make it override Objective-C initializer", + level = DeprecationLevel.ERROR +) +@TypedIntrinsic(IntrinsicType.OBJC_INIT_BY) +external fun T.initBy(constructorCall: T): T + +@kotlin.native.internal.ExportForCompiler +private fun ObjCObjectBase.superInitCheck(superInitCallResult: ObjCObject?) { + if (superInitCallResult == null) + throw RuntimeException("Super initialization failed") + + if (superInitCallResult.objcPtr() != this.objcPtr()) + throw UnsupportedOperationException("Super initializer has replaced object") +} + +internal fun Any?.uncheckedCast(): T = @Suppress("UNCHECKED_CAST") (this as T) + +// Note: if this is called for non-frozen object on a wrong worker, the program will terminate. +@SymbolName("Kotlin_Interop_refFromObjC") +external fun interpretObjCPointerOrNull(objcPtr: NativePtr): T? + +@ExportForCppRuntime +inline fun interpretObjCPointer(objcPtr: NativePtr): T = interpretObjCPointerOrNull(objcPtr)!! + +@SymbolName("Kotlin_Interop_refToObjC") +external fun Any?.objcPtr(): NativePtr + +@SymbolName("Kotlin_Interop_createKotlinObjectHolder") +external fun createKotlinObjectHolder(any: Any?): NativePtr + +// Note: if this is called for non-frozen underlying ref on a wrong worker, the program will terminate. +inline fun unwrapKotlinObjectHolder(holder: Any?): T { + return unwrapKotlinObjectHolderImpl(holder!!.objcPtr()) as T +} + +@PublishedApi +@SymbolName("Kotlin_Interop_unwrapKotlinObjectHolder") +external internal fun unwrapKotlinObjectHolderImpl(ptr: NativePtr): Any + +class ObjCObjectVar(rawPtr: NativePtr) : CVariable(rawPtr) { + @Deprecated("Use sizeOf() or alignOf() instead.") + @Suppress("DEPRECATION") + companion object : CVariable.Type(pointerSize.toLong(), pointerSize) +} + +class ObjCNotImplementedVar(rawPtr: NativePtr) : CVariable(rawPtr) { + @Deprecated("Use sizeOf() or alignOf() instead.") + @Suppress("DEPRECATION") + companion object : CVariable.Type(pointerSize.toLong(), pointerSize) +} + +var ObjCNotImplementedVar.value: T + get() = TODO() + set(value) = TODO() + +typealias ObjCStringVarOf = ObjCNotImplementedVar +typealias ObjCBlockVar = ObjCNotImplementedVar + +@TypedIntrinsic(IntrinsicType.OBJC_CREATE_SUPER_STRUCT) +@PublishedApi +internal external fun createObjCSuperStruct(receiver: NativePtr, superClass: NativePtr): NativePtr + +@Target(AnnotationTarget.CLASS) +@Retention(AnnotationRetention.BINARY) +annotation class ExternalObjCClass(val protocolGetter: String = "", val binaryName: String = "") + +@Target(AnnotationTarget.FUNCTION, AnnotationTarget.PROPERTY_GETTER, AnnotationTarget.PROPERTY_SETTER) +@Retention(AnnotationRetention.BINARY) +annotation class ObjCMethod(val selector: String, val encoding: String, val isStret: Boolean = false) + +@Target(AnnotationTarget.CONSTRUCTOR) +@Retention(AnnotationRetention.BINARY) +annotation class ObjCConstructor(val initSelector: String, val designated: Boolean) + +@Target(AnnotationTarget.FUNCTION) +@Retention(AnnotationRetention.BINARY) +annotation class ObjCFactory(val selector: String, val encoding: String, val isStret: Boolean = false) + +@Target(AnnotationTarget.FILE) +@Retention(AnnotationRetention.BINARY) +annotation class InteropStubs() + +@PublishedApi +@Target(AnnotationTarget.FUNCTION) +@Retention(AnnotationRetention.SOURCE) +internal annotation class ObjCMethodImp(val selector: String, val encoding: String) + +@PublishedApi +@TypedIntrinsic(IntrinsicType.OBJC_GET_SELECTOR) +internal external fun objCGetSelector(selector: String): COpaquePointer + +@kotlin.native.internal.ExportForCppRuntime("Kotlin_Interop_getObjCClass") +private fun getObjCClassByName(name: NativePtr): NativePtr { + val result = objc_lookUpClass(name) + if (result == nativeNullPtr) { + val className = interpretCPointer(name)!!.toKString() + val message = """Objective-C class '$className' not found. + |Ensure that the containing framework or library was linked.""".trimMargin() + + throw RuntimeException(message) + } + return result +} + +@kotlin.native.internal.ExportForCompiler +private fun allocObjCObject(clazz: NativePtr): NativePtr { + val rawResult = objc_allocWithZone(clazz) + if (rawResult == nativeNullPtr) { + throw OutOfMemoryError("Unable to allocate Objective-C object") + } + + // Note: `objc_allocWithZone` returns retained pointer, and thus it must be balanced by the caller. + + return rawResult +} + +@TypedIntrinsic(IntrinsicType.OBJC_GET_OBJC_CLASS) +@kotlin.native.internal.ExportForCompiler +private external fun getObjCClass(): NativePtr + +@PublishedApi +@TypedIntrinsic(IntrinsicType.OBJC_GET_MESSENGER) +internal external fun getMessenger(superClass: NativePtr): COpaquePointer? + +@PublishedApi +@TypedIntrinsic(IntrinsicType.OBJC_GET_MESSENGER_STRET) +internal external fun getMessengerStret(superClass: NativePtr): COpaquePointer? + + +internal class ObjCWeakReferenceImpl : kotlin.native.ref.WeakReferenceImpl() { + @SymbolName("Konan_ObjCInterop_getWeakReference") + external override fun get(): Any? +} + +@SymbolName("Konan_ObjCInterop_initWeakReference") +private external fun ObjCWeakReferenceImpl.init(objcPtr: NativePtr) + +@kotlin.native.internal.ExportForCppRuntime internal fun makeObjCWeakReferenceImpl(objcPtr: NativePtr): ObjCWeakReferenceImpl { + val result = ObjCWeakReferenceImpl() + result.init(objcPtr) + return result +} + +// Konan runtme: + +@Deprecated("Use plain Kotlin cast of String to NSString", level = DeprecationLevel.ERROR) +@SymbolName("Kotlin_Interop_CreateNSStringFromKString") +external fun CreateNSStringFromKString(str: String?): NativePtr + +@Deprecated("Use plain Kotlin cast of NSString to String", level = DeprecationLevel.ERROR) +@SymbolName("Kotlin_Interop_CreateKStringFromNSString") +external fun CreateKStringFromNSString(ptr: NativePtr): String? + +@PublishedApi +@SymbolName("Kotlin_Interop_CreateObjCObjectHolder") +internal external fun createObjCObjectHolder(ptr: NativePtr): Any? + +// Objective-C runtime: + +@SymbolName("objc_retainAutoreleaseReturnValue") +external fun objc_retainAutoreleaseReturnValue(ptr: NativePtr): NativePtr + +@SymbolName("Kotlin_objc_autoreleasePoolPush") +external fun objc_autoreleasePoolPush(): NativePtr + +@SymbolName("Kotlin_objc_autoreleasePoolPop") +external fun objc_autoreleasePoolPop(ptr: NativePtr) + +@SymbolName("Kotlin_objc_allocWithZone") +@FilterExceptions +private external fun objc_allocWithZone(clazz: NativePtr): NativePtr + +@SymbolName("Kotlin_objc_retain") +external fun objc_retain(ptr: NativePtr): NativePtr + +@SymbolName("Kotlin_objc_release") +external fun objc_release(ptr: NativePtr) + +@SymbolName("Kotlin_objc_lookUpClass") +external fun objc_lookUpClass(name: NativePtr): NativePtr diff --git a/kotlin-native/Interop/Runtime/src/native/kotlin/kotlinx/cinterop/ObjectiveCKClassSupport.kt b/kotlin-native/Interop/Runtime/src/native/kotlin/kotlinx/cinterop/ObjectiveCKClassSupport.kt new file mode 100644 index 00000000000..cf0f94290e0 --- /dev/null +++ b/kotlin-native/Interop/Runtime/src/native/kotlin/kotlinx/cinterop/ObjectiveCKClassSupport.kt @@ -0,0 +1,41 @@ +/* + * Copyright 2010-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +package kotlinx.cinterop + +import kotlin.native.internal.KClassImpl +import kotlin.reflect.KClass + +/** + * If [objCClass] is a class generated to Objective-C header for Kotlin class, + * returns [KClass] for that original Kotlin class. + * + * Otherwise returns `null`. + */ +fun getOriginalKotlinClass(objCClass: ObjCClass): KClass<*>? { + val typeInfo = getTypeInfoForClass(objCClass.objcPtr()) + if (typeInfo.isNull()) return null + + return KClassImpl(typeInfo) +} + +/** + * If [objCProtocol] is a protocol generated to Objective-C header for Kotlin class, + * returns [KClass] for that original Kotlin class. + * + * Otherwise returns `null`. + */ +fun getOriginalKotlinClass(objCProtocol: ObjCProtocol): KClass<*>? { + val typeInfo = getTypeInfoForProtocol(objCProtocol.objcPtr()) + if (typeInfo.isNull()) return null + + return KClassImpl(typeInfo) +} + +@SymbolName("Kotlin_ObjCInterop_getTypeInfoForClass") +private external fun getTypeInfoForClass(ptr: NativePtr): NativePtr + +@SymbolName("Kotlin_ObjCInterop_getTypeInfoForProtocol") +private external fun getTypeInfoForProtocol(ptr: NativePtr): NativePtr \ No newline at end of file diff --git a/kotlin-native/Interop/Runtime/src/native/kotlin/kotlinx/cinterop/ObjectiveCUtils.kt b/kotlin-native/Interop/Runtime/src/native/kotlin/kotlinx/cinterop/ObjectiveCUtils.kt new file mode 100644 index 00000000000..b3b76ea1672 --- /dev/null +++ b/kotlin-native/Interop/Runtime/src/native/kotlin/kotlinx/cinterop/ObjectiveCUtils.kt @@ -0,0 +1,63 @@ +/* + * Copyright 2010-2017 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package kotlinx.cinterop + +inline fun autoreleasepool(block: () -> R): R { + val pool = objc_autoreleasePoolPush() + return try { + block() + } finally { + objc_autoreleasePoolPop(pool) + } +} + +@Deprecated("Use plain Kotlin cast", ReplaceWith("this as T"), DeprecationLevel.ERROR) +fun ObjCObject.reinterpret() = @Suppress("DEPRECATION") this.uncheckedCast() + +// TODO: null checks +var ObjCObjectVar.value: T + @Suppress("DEPRECATION") get() = + interpretObjCPointerOrNull(nativeMemUtils.getNativePtr(this)).uncheckedCast() + + set(value) = nativeMemUtils.putNativePtr(this, value.objcPtr()) + +/** + * Makes Kotlin method in Objective-C class accessible through Objective-C dispatch + * to be used as action sent by control in UIKit or AppKit. + */ +@Target(AnnotationTarget.FUNCTION) +@Retention(AnnotationRetention.SOURCE) +annotation class ObjCAction + +/** + * Makes Kotlin property in Objective-C class settable through Objective-C dispatch + * to be used as IB outlet. + */ +@Target(AnnotationTarget.PROPERTY) +@Retention(AnnotationRetention.SOURCE) +annotation class ObjCOutlet + +/** + * Makes Kotlin subclass of Objective-C class visible for runtime lookup + * after Kotlin `main` function gets invoked. + * + * Note: runtime lookup can be forced even when the class is referenced statically from + * Objective-C source code by adding `__attribute__((objc_runtime_visible))` to its `@interface`. + */ +@Target(AnnotationTarget.CLASS) +@Retention(AnnotationRetention.SOURCE) +annotation class ExportObjCClass(val name: String = "") diff --git a/kotlin-native/Interop/Runtime/src/native/kotlin/kotlinx/cinterop/Pinning.kt b/kotlin-native/Interop/Runtime/src/native/kotlin/kotlinx/cinterop/Pinning.kt new file mode 100644 index 00000000000..2b69bbabf05 --- /dev/null +++ b/kotlin-native/Interop/Runtime/src/native/kotlin/kotlinx/cinterop/Pinning.kt @@ -0,0 +1,129 @@ +/* + * Copyright 2010-2017 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package kotlinx.cinterop +import kotlin.native.* + +data class Pinned internal constructor(private val stablePtr: COpaquePointer) { + + /** + * Disposes the handle. It must not be [used][get] after that. + */ + fun unpin() { + disposeStablePointer(this.stablePtr) + } + + /** + * Returns the underlying pinned object. + */ + fun get(): T = @Suppress("UNCHECKED_CAST") (derefStablePointer(stablePtr) as T) + +} + +fun T.pin() = Pinned(createStablePointer(this)) + +inline fun T.usePinned(block: (Pinned) -> R): R { + val pinned = this.pin() + return try { + block(pinned) + } finally { + pinned.unpin() + } +} + +fun Pinned.addressOf(index: Int): CPointer = this.get().addressOfElement(index) +fun ByteArray.refTo(index: Int): CValuesRef = this.usingPinned { addressOf(index) } + +fun Pinned.addressOf(index: Int): CPointer = this.get().addressOfElement(index) +fun String.refTo(index: Int): CValuesRef = this.usingPinned { addressOf(index) } + +fun Pinned.addressOf(index: Int): CPointer = this.get().addressOfElement(index) +fun CharArray.refTo(index: Int): CValuesRef = this.usingPinned { addressOf(index) } + +fun Pinned.addressOf(index: Int): CPointer = this.get().addressOfElement(index) +fun ShortArray.refTo(index: Int): CValuesRef = this.usingPinned { addressOf(index) } + +fun Pinned.addressOf(index: Int): CPointer = this.get().addressOfElement(index) +fun IntArray.refTo(index: Int): CValuesRef = this.usingPinned { addressOf(index) } + +fun Pinned.addressOf(index: Int): CPointer = this.get().addressOfElement(index) +fun LongArray.refTo(index: Int): CValuesRef = this.usingPinned { addressOf(index) } + +// TODO: pinning of unsigned arrays involves boxing as they are inline classes wrapping signed arrays. +fun Pinned.addressOf(index: Int): CPointer = this.get().addressOfElement(index) +fun UByteArray.refTo(index: Int): CValuesRef = this.usingPinned { addressOf(index) } + +fun Pinned.addressOf(index: Int): CPointer = this.get().addressOfElement(index) +fun UShortArray.refTo(index: Int): CValuesRef = this.usingPinned { addressOf(index) } + +fun Pinned.addressOf(index: Int): CPointer = this.get().addressOfElement(index) +fun UIntArray.refTo(index: Int): CValuesRef = this.usingPinned { addressOf(index) } + +fun Pinned.addressOf(index: Int): CPointer = this.get().addressOfElement(index) +fun ULongArray.refTo(index: Int): CValuesRef = this.usingPinned { addressOf(index) } + +fun Pinned.addressOf(index: Int): CPointer = this.get().addressOfElement(index) +fun FloatArray.refTo(index: Int): CValuesRef = this.usingPinned { addressOf(index) } + +fun Pinned.addressOf(index: Int): CPointer = this.get().addressOfElement(index) +fun DoubleArray.refTo(index: Int): CValuesRef = this.usingPinned { addressOf(index) } + +private inline fun T.usingPinned( + crossinline block: Pinned.() -> CPointer

+) = object : CValuesRef

() { + + override fun getPointer(scope: AutofreeScope): CPointer

{ + val pinned = this@usingPinned.pin() + scope.defer { pinned.unpin() } + return pinned.block() + } +} + +@SymbolName("Kotlin_Arrays_getByteArrayAddressOfElement") +private external fun ByteArray.addressOfElement(index: Int): CPointer + +@SymbolName("Kotlin_Arrays_getStringAddressOfElement") +private external fun String.addressOfElement(index: Int): CPointer + +@SymbolName("Kotlin_Arrays_getCharArrayAddressOfElement") +private external fun CharArray.addressOfElement(index: Int): CPointer + +@SymbolName("Kotlin_Arrays_getShortArrayAddressOfElement") +private external fun ShortArray.addressOfElement(index: Int): CPointer + +@SymbolName("Kotlin_Arrays_getIntArrayAddressOfElement") +private external fun IntArray.addressOfElement(index: Int): CPointer + +@SymbolName("Kotlin_Arrays_getLongArrayAddressOfElement") +private external fun LongArray.addressOfElement(index: Int): CPointer + +@SymbolName("Kotlin_Arrays_getByteArrayAddressOfElement") +private external fun UByteArray.addressOfElement(index: Int): CPointer + +@SymbolName("Kotlin_Arrays_getShortArrayAddressOfElement") +private external fun UShortArray.addressOfElement(index: Int): CPointer + +@SymbolName("Kotlin_Arrays_getIntArrayAddressOfElement") +private external fun UIntArray.addressOfElement(index: Int): CPointer + +@SymbolName("Kotlin_Arrays_getLongArrayAddressOfElement") +private external fun ULongArray.addressOfElement(index: Int): CPointer + +@SymbolName("Kotlin_Arrays_getFloatArrayAddressOfElement") +private external fun FloatArray.addressOfElement(index: Int): CPointer + +@SymbolName("Kotlin_Arrays_getDoubleArrayAddressOfElement") +private external fun DoubleArray.addressOfElement(index: Int): CPointer diff --git a/kotlin-native/Interop/Runtime/src/native/kotlin/kotlinx/cinterop/internal/Annotations.kt b/kotlin-native/Interop/Runtime/src/native/kotlin/kotlinx/cinterop/internal/Annotations.kt new file mode 100644 index 00000000000..29e47e06afc --- /dev/null +++ b/kotlin-native/Interop/Runtime/src/native/kotlin/kotlinx/cinterop/internal/Annotations.kt @@ -0,0 +1,97 @@ +package kotlinx.cinterop.internal + +@Target(AnnotationTarget.CLASS) +@Retention(AnnotationRetention.BINARY) +annotation class CStruct(val spelling: String) { + @Retention(AnnotationRetention.BINARY) + @Target( + AnnotationTarget.PROPERTY_GETTER, + AnnotationTarget.PROPERTY_SETTER + ) + annotation class MemberAt(val offset: Long) + + @Retention(AnnotationRetention.BINARY) + @Target(AnnotationTarget.PROPERTY_GETTER) + annotation class ArrayMemberAt(val offset: Long) + + @Retention(AnnotationRetention.BINARY) + @Target( + AnnotationTarget.PROPERTY_GETTER, + AnnotationTarget.PROPERTY_SETTER + ) + annotation class BitField(val offset: Long, val size: Int) + + @Retention(AnnotationRetention.BINARY) + annotation class VarType(val size: Long, val align: Int) +} + +@Target( + AnnotationTarget.FUNCTION, + AnnotationTarget.PROPERTY_GETTER, + AnnotationTarget.PROPERTY_SETTER +) +@Retention(AnnotationRetention.BINARY) +public annotation class CCall(val id: String) { + @Target(AnnotationTarget.VALUE_PARAMETER) + @Retention(AnnotationRetention.BINARY) + annotation class CString + + @Target(AnnotationTarget.VALUE_PARAMETER) + @Retention(AnnotationRetention.BINARY) + annotation class WCString + + @Target(AnnotationTarget.FUNCTION) + @Retention(AnnotationRetention.BINARY) + annotation class ReturnsRetained + + @Target(AnnotationTarget.FUNCTION) + @Retention(AnnotationRetention.BINARY) + annotation class ConsumesReceiver + + @Target(AnnotationTarget.VALUE_PARAMETER) + @Retention(AnnotationRetention.BINARY) + annotation class Consumed +} + +/** + * Collection of annotations that allow to store + * constant values. + */ +public object ConstantValue { + @Retention(AnnotationRetention.BINARY) + annotation class Byte(val value: kotlin.Byte) + @Retention(AnnotationRetention.BINARY) + annotation class Short(val value: kotlin.Short) + @Retention(AnnotationRetention.BINARY) + annotation class Int(val value: kotlin.Int) + @Retention(AnnotationRetention.BINARY) + annotation class Long(val value: kotlin.Long) + @Retention(AnnotationRetention.BINARY) + annotation class UByte(val value: kotlin.UByte) + @Retention(AnnotationRetention.BINARY) + annotation class UShort(val value: kotlin.UShort) + @Retention(AnnotationRetention.BINARY) + annotation class UInt(val value: kotlin.UInt) + @Retention(AnnotationRetention.BINARY) + annotation class ULong(val value: kotlin.ULong) + @Retention(AnnotationRetention.BINARY) + annotation class Float(val value: kotlin.Float) + @Retention(AnnotationRetention.BINARY) + annotation class Double(val value: kotlin.Double) + @Retention(AnnotationRetention.BINARY) + annotation class String(val value: kotlin.String) +} + +/** + * Denotes property that is an alias to some enum entry. + */ +@Target(AnnotationTarget.CLASS) +@Retention(AnnotationRetention.BINARY) +public annotation class CEnumEntryAlias(val entryName: String) + +/** + * Stores instance size of the type T: CEnumVar. + */ +@Target(AnnotationTarget.CLASS) +@Retention(AnnotationRetention.BINARY) +public annotation class CEnumVarTypeSize(val size: Int) \ No newline at end of file diff --git a/kotlin-native/Interop/StubGenerator/build.gradle b/kotlin-native/Interop/StubGenerator/build.gradle new file mode 100644 index 00000000000..d4b8b3e9d08 --- /dev/null +++ b/kotlin-native/Interop/StubGenerator/build.gradle @@ -0,0 +1,52 @@ +/* + * Copyright 2010-2017 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +buildscript { + apply from: "$rootDir/gradle/kotlinGradlePlugin.gradle" +} + +apply plugin: 'kotlin' +apply plugin: 'application' + +mainClassName = "org.jetbrains.kotlin.native.interop.gen.jvm.MainKt" + +repositories { + maven { + url buildKotlinCompilerRepo + } +} + +dependencies { + implementation project(":Interop:Indexer") + implementation project(":utilities:basic-utils") + api project(path: ":endorsedLibraries:kotlinx.cli", configuration: "jvmRuntimeElements") + + api "org.jetbrains.kotlin:kotlin-stdlib:$kotlinVersion" + api "org.jetbrains.kotlin:kotlin-compiler:$kotlinVersion" + api "org.jetbrains.kotlin:kotlin-native-shared:$konanVersion" + api "org.jetbrains.kotlinx:kotlinx-metadata-klib:$metadataVersion" + + testImplementation "junit:junit:4.12" + testImplementation "org.jetbrains.kotlin:kotlin-test-junit:$buildKotlinVersion" + testImplementation "org.jetbrains.kotlin:kotlin-test:$buildKotlinVersion" +} + +compileKotlin { + kotlinOptions { + freeCompilerArgs = ['-Xopt-in=kotlin.ExperimentalUnsignedTypes', '-Xskip-metadata-version-check'] + allWarningsAsErrors=true + } +} diff --git a/kotlin-native/Interop/StubGenerator/src/main/kotlin/org/jetbrains/kotlin/native/interop/gen/AbiSpecific.kt b/kotlin-native/Interop/StubGenerator/src/main/kotlin/org/jetbrains/kotlin/native/interop/gen/AbiSpecific.kt new file mode 100644 index 00000000000..d1661642c45 --- /dev/null +++ b/kotlin-native/Interop/StubGenerator/src/main/kotlin/org/jetbrains/kotlin/native/interop/gen/AbiSpecific.kt @@ -0,0 +1,134 @@ +/* + * Copyright 2010-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +package org.jetbrains.kotlin.native.interop.gen + +import org.jetbrains.kotlin.konan.target.KonanTarget +import org.jetbrains.kotlin.native.interop.indexer.* + +/** + * objc_msgSend*_stret functions must be used when return value is returned through memory + * pointed by implicit argument, which is passed on the register that would otherwise be used for receiver. + * + * The entire implementation is just the real ABI approximation which is enough for practical cases. + */ +internal fun Type.isStret(target: KonanTarget): Boolean { + val unwrappedType = this.unwrapTypedefs() + val abiInfo: ObjCAbiInfo = when (target) { + KonanTarget.IOS_ARM64, + KonanTarget.TVOS_ARM64 -> DarwinArm64AbiInfo() + + KonanTarget.IOS_X64, + KonanTarget.MACOS_X64, + KonanTarget.WATCHOS_X64, + KonanTarget.TVOS_X64 -> DarwinX64AbiInfo() + + KonanTarget.WATCHOS_X86 -> DarwinX86AbiInfo() + + KonanTarget.IOS_ARM32, + KonanTarget.WATCHOS_ARM32 -> DarwinArm32AbiInfo(target) + + else -> error("Cannot generate ObjC stubs for $target.") + } + return abiInfo.shouldUseStret(unwrappedType) +} + +/** + * Provides ABI-specific information about target for Objective C interop. + */ +interface ObjCAbiInfo { + fun shouldUseStret(returnType: Type): Boolean +} + +class DarwinX64AbiInfo : ObjCAbiInfo { + override fun shouldUseStret(returnType: Type): Boolean { + return when (returnType) { + is RecordType -> returnType.decl.def!!.size > 16 || returnType.hasUnalignedMembers() + else -> false + } + } +} + +class DarwinX86AbiInfo : ObjCAbiInfo { + override fun shouldUseStret(returnType: Type): Boolean { + // https://github.com/llvm/llvm-project/blob/6c8a34ed9b49704bdd60838143047c62ba9f2502/clang/lib/CodeGen/TargetInfo.cpp#L1243 + return when (returnType) { + is RecordType -> { + val size = returnType.decl.def!!.size + val canBePassedInRegisters = (size == 1L || size == 2L || size == 4L || size == 8L) + return !canBePassedInRegisters + } + else -> false + } + } +} + +class DarwinArm32AbiInfo(private val target: KonanTarget) : ObjCAbiInfo { + override fun shouldUseStret(returnType: Type): Boolean = when (target) { + KonanTarget.IOS_ARM32 -> when (returnType) { + is RecordType -> !returnType.isIntegerLikeType() + else -> false + } + // 32-bit watchOS uses armv7k which is effectively Cortex-A7 and + // uses AAPCS16 VPF. + KonanTarget.WATCHOS_ARM32 -> when (returnType) { + is RecordType -> { + // https://github.com/llvm/llvm-project/blob/6c8a34ed9b49704bdd60838143047c62ba9f2502/clang/lib/CodeGen/TargetInfo.cpp#L6165 + when { + returnType.decl.def!!.size <= 16 -> false + else -> true + } + } + else -> false + } + else -> error("Unexpected target") + } +} + +class DarwinArm64AbiInfo : ObjCAbiInfo { + override fun shouldUseStret(returnType: Type): Boolean { + // On aarch64 stret is never the case, since an implicit argument gets passed on x8. + return false + } +} + +private fun Type.isIntegerLikeType(): Boolean = when (this) { + is RecordType -> { + val def = this.decl.def + if (def == null) { + false + } else { + def.size <= 4 && + def.members.all { + when (it) { + is BitField -> it.type.isIntegerLikeType() + is Field -> it.offset == 0L && it.type.isIntegerLikeType() + is IncompleteField -> false + } + } + } + } + is ObjCPointer, is PointerType, CharType, is BoolType -> true + is IntegerType -> this.size <= 4 + is Typedef -> this.def.aliased.isIntegerLikeType() + is EnumType -> this.def.baseType.isIntegerLikeType() + + else -> false +} + +private fun Type.hasUnalignedMembers(): Boolean = when (this) { + is Typedef -> this.def.aliased.hasUnalignedMembers() + is RecordType -> this.decl.def!!.let { def -> + def.fields.any { + !it.isAligned || + // Check members of fields too: + it.type.hasUnalignedMembers() + } + } + is ArrayType -> this.elemType.hasUnalignedMembers() + else -> false + +// TODO: should the recursive checks be made in indexer when computing `hasUnalignedFields`? +} \ No newline at end of file diff --git a/kotlin-native/Interop/StubGenerator/src/main/kotlin/org/jetbrains/kotlin/native/interop/gen/CWrapperGenerator.kt b/kotlin-native/Interop/StubGenerator/src/main/kotlin/org/jetbrains/kotlin/native/interop/gen/CWrapperGenerator.kt new file mode 100644 index 00000000000..8de4751a46d --- /dev/null +++ b/kotlin-native/Interop/StubGenerator/src/main/kotlin/org/jetbrains/kotlin/native/interop/gen/CWrapperGenerator.kt @@ -0,0 +1,94 @@ +/* + * Copyright 2010-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ +package org.jetbrains.kotlin.native.interop.gen + +import org.jetbrains.kotlin.native.interop.indexer.FunctionDecl +import org.jetbrains.kotlin.native.interop.indexer.GlobalDecl +import org.jetbrains.kotlin.native.interop.indexer.VoidType +import org.jetbrains.kotlin.native.interop.indexer.unwrapTypedefs + +internal data class CCalleeWrapper(val lines: List) + +/** + * Some functions don't have an address (e.g. macros-based or builtins). + * To solve this problem we generate a wrapper function. + */ +internal class CWrappersGenerator(private val context: StubIrContext) { + + private var currentFunctionWrapperId = 0 + + private val packageName = + context.configuration.pkgName.replace(INVALID_CLANG_IDENTIFIER_REGEX, "_") + + private fun generateFunctionWrapperName(functionName: String): String { + return "${packageName}_${functionName}_wrapper${currentFunctionWrapperId++}" + } + + private fun bindSymbolToFunction(symbol: String, function: String): List = listOf( + "const void* $symbol __asm(${symbol.quoteAsKotlinLiteral()});", + "const void* $symbol = &$function;" + ) + + private data class Parameter(val type: String, val name: String) + + private fun createWrapper( + symbolName: String, + wrapperName: String, + returnType: String, + parameters: List, + body: String + ): List = listOf( + "__attribute__((always_inline))", + "$returnType $wrapperName(${parameters.joinToString { "${it.type} ${it.name}" }}) {", + body, + "}", + *bindSymbolToFunction(symbolName, wrapperName).toTypedArray() + ) + + fun generateCCalleeWrapper(function: FunctionDecl, symbolName: String): CCalleeWrapper = + if (function.isVararg) { + CCalleeWrapper(bindSymbolToFunction(symbolName, function.name)) + } else { + val wrapperName = generateFunctionWrapperName(function.name) + + val returnType = function.returnType.getStringRepresentation() + val parameters = function.parameters.mapIndexed { index, parameter -> + Parameter(parameter.type.getStringRepresentation(), "p$index") + } + val callExpression = "${function.name}(${parameters.joinToString { it.name }});" + val wrapperBody = if (function.returnType.unwrapTypedefs() is VoidType) { + callExpression + } else { + "return $callExpression" + } + val wrapper = createWrapper(symbolName, wrapperName, returnType, parameters, wrapperBody) + CCalleeWrapper(wrapper) + } + + fun generateCGlobalGetter(globalDecl: GlobalDecl, symbolName: String): CCalleeWrapper { + val wrapperName = generateFunctionWrapperName("${globalDecl.name}_getter") + val returnType = globalDecl.type.getStringRepresentation() + val wrapperBody = "return ${globalDecl.name};" + val wrapper = createWrapper(symbolName, wrapperName, returnType, emptyList(), wrapperBody) + return CCalleeWrapper(wrapper) + } + + fun generateCGlobalByPointerGetter(globalDecl: GlobalDecl, symbolName: String): CCalleeWrapper { + val wrapperName = generateFunctionWrapperName("${globalDecl.name}_getter") + val returnType = "void*" + val wrapperBody = "return &${globalDecl.name};" + val wrapper = createWrapper(symbolName, wrapperName, returnType, emptyList(), wrapperBody) + return CCalleeWrapper(wrapper) + } + + fun generateCGlobalSetter(globalDecl: GlobalDecl, symbolName: String): CCalleeWrapper { + val wrapperName = generateFunctionWrapperName("${globalDecl.name}_setter") + val globalType = globalDecl.type.getStringRepresentation() + val parameter = Parameter(globalType, "p1") + val wrapperBody = "${globalDecl.name} = ${parameter.name};" + val wrapper = createWrapper(symbolName, wrapperName, "void", listOf(parameter), wrapperBody) + return CCalleeWrapper(wrapper) + } +} diff --git a/kotlin-native/Interop/StubGenerator/src/main/kotlin/org/jetbrains/kotlin/native/interop/gen/CodeBuilders.kt b/kotlin-native/Interop/StubGenerator/src/main/kotlin/org/jetbrains/kotlin/native/interop/gen/CodeBuilders.kt new file mode 100644 index 00000000000..886ded7033b --- /dev/null +++ b/kotlin-native/Interop/StubGenerator/src/main/kotlin/org/jetbrains/kotlin/native/interop/gen/CodeBuilders.kt @@ -0,0 +1,103 @@ +/* + * Copyright 2010-2017 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.jetbrains.kotlin.native.interop.gen + +interface NativeScope { + val mappingBridgeGenerator: MappingBridgeGenerator +} + +class NativeCodeBuilder(val scope: NativeScope) { + val lines = mutableListOf() + + fun out(line: String): Unit { + lines.add(line) + } +} + +inline fun buildNativeCodeLines(scope: NativeScope, block: NativeCodeBuilder.() -> Unit): List { + val builder = NativeCodeBuilder(scope) + builder.block() + return builder.lines +} + +private class Block(val nesting: Int, val start: String, val end: String) { + val prologue = mutableListOf() + val body = mutableListOf() + val epilogue = mutableListOf() + + fun indent(line: String) = " ".repeat(nesting) + line + fun indentBraces(line: String) = " ".repeat(nesting - 1) + line +} + +class KotlinCodeBuilder(val scope: KotlinScope) { + + private val blocks = mutableListOf() + + init { + pushBlock("", "") + } + + fun out(line: String) { + currentBlock().body += line + } + + private var memScoped = false + fun pushMemScoped() { + if (!memScoped) { + memScoped = true + pushBlock("memScoped {") + } + } + + fun getNativePointer(name: String): String { + return "$name?.getPointer(memScope)" + } + + fun returnResult(result: String) { + currentBlock().body += "return $result" + } + + private fun currentBlock() = blocks.last() + + fun pushBlock(start: String, end: String = "}") { + val block = Block(blocks.size, start = start, end = end) + blocks += block + } + + private fun emitBlockAndNested(position: Int, lines: MutableList) { + if (position >= blocks.size) return + val block = blocks[position] + if (block.start.isNotEmpty()) lines += block.indentBraces(block.start) + lines += block.prologue.map { block.indent(it) } + lines += block.body.map { block.indent(it) } + emitBlockAndNested(position + 1, lines) + lines += block.epilogue.map { block.indent(it) } + if (block.end.isNotEmpty()) lines += block.indentBraces(block.end) + } + + fun build(): List { + val lines = mutableListOf() + emitBlockAndNested(0, lines) + return lines.toList() + } +} + +inline fun buildKotlinCodeLines(scope: KotlinScope, block: KotlinCodeBuilder.() -> Unit): List { + val builder = KotlinCodeBuilder(scope) + builder.block() + return builder.build() +} \ No newline at end of file diff --git a/kotlin-native/Interop/StubGenerator/src/main/kotlin/org/jetbrains/kotlin/native/interop/gen/CodeUtils.kt b/kotlin-native/Interop/StubGenerator/src/main/kotlin/org/jetbrains/kotlin/native/interop/gen/CodeUtils.kt new file mode 100644 index 00000000000..6ad1baf79d9 --- /dev/null +++ b/kotlin-native/Interop/StubGenerator/src/main/kotlin/org/jetbrains/kotlin/native/interop/gen/CodeUtils.kt @@ -0,0 +1,91 @@ +/* + * Copyright 2010-2017 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.jetbrains.kotlin.native.interop.gen + +val kotlinKeywords = setOf( + "as", "break", "class", "continue", "do", "dynamic", "else", "false", "for", "fun", "if", "in", + "interface", "is", "null", "object", "package", "return", "super", "this", "throw", + "true", "try", "typealias", "val", "var", "when", "while", + // While not technically keywords, those shall be escaped as well. + "_", "__", "___" +) + +/** + * The expression written in native language. + */ +typealias NativeExpression = String + +/** + * The expression written in Kotlin. + */ +typealias KotlinExpression = String + +/** + * For this identifier constructs the string to be parsed by Kotlin as `SimpleName` + * defined [here](https://kotlinlang.org/docs/reference/grammar.html#SimpleName). + */ +fun String.asSimpleName(): String = if (this in kotlinKeywords || this.contains("$")) { + "`$this`" +} else { + this +} + +/** + * Yet another mangler, particularly to avoid secondary clash, e.g. when a property + * in prototype (interface) is mangled and that will cause another clash in the class + * which implements this interface. + * Rationale: keep algorithm simple but use the mangling characters which are rare + * in normal code, and keep mangling easy readable. + */ +internal fun mangleSimple(name: String): String { + val reserved = setOf("Companion") + val postfix = "\$" + return if (name in reserved) + "$name$postfix" + else + name +} + +/** + * Returns the expression to be parsed by Kotlin as string literal with given contents, + * i.e. transforms `foo$bar` to `"foo\$bar"`. + */ +fun String.quoteAsKotlinLiteral(): KotlinExpression = buildString { + append('"') + + this@quoteAsKotlinLiteral.forEach { c -> + when (c) { + in charactersAllowedInKotlinStringLiterals -> append(c) + '$' -> append("\\$") + else -> append("\\u" + "%04X".format(c.toInt())) + } + } + + append('"') +} + +// TODO: improve literal readability by preserving more characters. + +private val charactersAllowedInKotlinStringLiterals: Set = mutableSetOf().apply { + addAll('a' .. 'z') + addAll('A' .. 'Z') + addAll('0' .. '9') + addAll(listOf('_', '@', ':', ';', '.', ',', '{', '}', '=', '[', ']', '^', '#', '*', ' ', '(', ')')) +} + +val annotationForUnableToImport + get() = "@Deprecated(${"Unable to import this declaration".quoteAsKotlinLiteral()}, level = DeprecationLevel.ERROR)" diff --git a/kotlin-native/Interop/StubGenerator/src/main/kotlin/org/jetbrains/kotlin/native/interop/gen/Imports.kt b/kotlin-native/Interop/StubGenerator/src/main/kotlin/org/jetbrains/kotlin/native/interop/gen/Imports.kt new file mode 100644 index 00000000000..a3f65856d15 --- /dev/null +++ b/kotlin-native/Interop/StubGenerator/src/main/kotlin/org/jetbrains/kotlin/native/interop/gen/Imports.kt @@ -0,0 +1,72 @@ +/* + * Copyright 2010-2017 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.jetbrains.kotlin.native.interop.gen + +import org.jetbrains.kotlin.konan.library.KonanLibrary +import org.jetbrains.kotlin.native.interop.indexer.* + +interface Imports { + fun getPackage(location: Location): String? +} + + +class PackageInfo(val name: String, val library: KonanLibrary) + +class ImportsImpl(internal val headerIdToPackage: Map) : Imports { + + override fun getPackage(location: Location): String? { + val packageInfo = headerIdToPackage[location.headerId] + ?: return null + accessedLibraries += packageInfo.library + return packageInfo.name + } + + private val accessedLibraries = mutableSetOf() + + val requiredLibraries: Set + get() = accessedLibraries.toSet() +} + +class HeaderInclusionPolicyImpl(private val nameGlobs: List) : HeaderInclusionPolicy { + + override fun excludeUnused(headerName: String?): Boolean { + if (nameGlobs.isEmpty()) { + return false + } + + if (headerName == null) { + // Builtins; included only if no globs are specified: + return true + } + + return nameGlobs.all { !headerName.matchesToGlob(it) } + } +} + +class HeaderExclusionPolicyImpl( + private val importsImpl: ImportsImpl +) : HeaderExclusionPolicy { + + override fun excludeAll(headerId: HeaderId): Boolean { + return headerId in importsImpl.headerIdToPackage + } + +} + +private fun String.matchesToGlob(glob: String): Boolean = + java.nio.file.FileSystems.getDefault() + .getPathMatcher("glob:$glob").matches(java.nio.file.Paths.get(this)) diff --git a/kotlin-native/Interop/StubGenerator/src/main/kotlin/org/jetbrains/kotlin/native/interop/gen/KotlinCodeModel.kt b/kotlin-native/Interop/StubGenerator/src/main/kotlin/org/jetbrains/kotlin/native/interop/gen/KotlinCodeModel.kt new file mode 100644 index 00000000000..2b2b8fbba41 --- /dev/null +++ b/kotlin-native/Interop/StubGenerator/src/main/kotlin/org/jetbrains/kotlin/native/interop/gen/KotlinCodeModel.kt @@ -0,0 +1,346 @@ +/* + * Copyright 2010-2017 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.jetbrains.kotlin.native.interop.gen + +import kotlin.reflect.KProperty + +interface KotlinScope { + /** + * @return the string to be used to reference the classifier in current scope. + */ + fun reference(classifier: Classifier): String + + /** + * @return the string to be used as a name in the declaration of the classifier in current scope. + */ + fun declare(classifier: Classifier): String + + /** + * @return the string to be used as a name in the declaration of the property in current scope, + * or `null` if the property with given name can't be declared. + */ + fun declareProperty(receiver: String?, name: String): String? + + val mappingBridgeGenerator: MappingBridgeGenerator +} + +data class Classifier( + val pkg: String, + val topLevelName: String, + private val nestedNames: List = emptyList() +) { + + companion object { + fun topLevel(pkg: String, name: String): Classifier { + assert(!name.contains('.')) + assert(!name.contains('`')) + return Classifier(pkg, name) + } + } + + val isTopLevel: Boolean get() = this.nestedNames.isEmpty() + + fun nested(name: String): Classifier { + assert(!name.contains('.')) + assert(!name.contains('`')) + return this.copy(nestedNames = nestedNames + name) + } + + fun getRelativeFqName(asSimpleName: Boolean = true): String = buildString { + append(topLevelName.run { if (asSimpleName) asSimpleName() else this }) + nestedNames.forEach { + append('.') + append(it.run { if (asSimpleName) asSimpleName() else this }) + } + } + + val fqName: String get() = buildString { + if (pkg.isNotEmpty()) { + append(pkg) + append('.') + } + append(getRelativeFqName()) + } +} + +val Classifier.type + get() = KotlinClassifierType(this, arguments = emptyList(), nullable = false, underlyingType = null) + +fun Classifier.typeWith(vararg arguments: KotlinTypeArgument) = + KotlinClassifierType(this, arguments.toList(), nullable = false, underlyingType = null) + +fun Classifier.typeAbbreviation(expandedType: KotlinType) = + KotlinClassifierType(this, arguments = emptyList(), nullable = false, underlyingType = expandedType) + +interface KotlinTypeArgument { + /** + * @return the string to be used in the given scope to denote this. + */ + fun render(scope: KotlinScope): String +} + +object StarProjection : KotlinTypeArgument { + override fun render(scope: KotlinScope) = "*" +} + +interface KotlinType : KotlinTypeArgument { + val classifier: Classifier + fun makeNullableAsSpecified(nullable: Boolean): KotlinType +} + +/** + * @property underlyingType is non-null if this type is an alias to another type. + */ +data class KotlinClassifierType( + override val classifier: Classifier, + val arguments: List, + val nullable: Boolean, + val underlyingType: KotlinType? +) : KotlinType { + + override fun makeNullableAsSpecified(nullable: Boolean) = if (this.nullable == nullable) { + this + } else { + this.copy(nullable = nullable) + } + + override fun render(scope: KotlinScope): String = buildString { + append(scope.reference(classifier)) + if (arguments.isNotEmpty()) { + append('<') + arguments.joinTo(this) { it.render(scope) } + append('>') + } + if (nullable) { + append('?') + } + } +} + +fun KotlinType.makeNullable() = this.makeNullableAsSpecified(true) + +data class KotlinFunctionType( + val parameterTypes: List, + val returnType: KotlinType, + val nullable: Boolean = false +) : KotlinType { + + override fun makeNullableAsSpecified(nullable: Boolean) = if (this.nullable == nullable) { + this + } else { + this.copy(nullable = nullable) + } + + override val classifier by lazy { + Classifier.topLevel("kotlin", "Function${parameterTypes.size}") + } + + override fun render(scope: KotlinScope) = buildString { + if (nullable) append("(") + + append('(') + parameterTypes.joinTo(this) { it.render(scope) } + append(") -> ") + append(returnType.render(scope)) + + if (nullable) append(")?") + } +} + +internal val cnamesStructsPackageName = "cnames.structs" + +object KotlinTypes { + val independent = Classifier.topLevel("kotlin.native.internal", "Independent") + + val boolean by BuiltInType + val byte by BuiltInType + val short by BuiltInType + val int by BuiltInType + val long by BuiltInType + val uByte by BuiltInType + val uShort by BuiltInType + val uInt by BuiltInType + val uLong by BuiltInType + val float by BuiltInType + val double by BuiltInType + val unit by BuiltInType + val string by BuiltInType + val any by BuiltInType + + val list by CollectionClassifier + val mutableList by CollectionClassifier + val set by CollectionClassifier + val map by CollectionClassifier + + val nativePtr by InteropType + val vector128 by KotlinNativeType + + val cOpaque by InteropType + val cOpaquePointer by InteropType + val cOpaquePointerVar by InteropType + + val booleanVarOf by InteropClassifier + + val objCObject by InteropClassifier + val objCObjectMeta by InteropClassifier + val objCClass by InteropClassifier + val objCClassOf by InteropClassifier + val objCProtocol by InteropClassifier + + val cValuesRef by InteropClassifier + + val cPointed by InteropClassifier + val cPointer by InteropClassifier + val cPointerVar by InteropClassifier + val cArrayPointer by InteropClassifier + val cArrayPointerVar by InteropClassifier + val cPointerVarOf by InteropClassifier + + val cFunction by InteropClassifier + + val objCObjectVar by InteropClassifier + + val objCObjectBase by InteropClassifier + val objCObjectBaseMeta by InteropClassifier + + val objCBlockVar by InteropClassifier + val objCNotImplementedVar by InteropClassifier + + val cValue by InteropClassifier + + private open class ClassifierAtPackage(val pkg: String) { + operator fun getValue(thisRef: KotlinTypes, property: KProperty<*>): Classifier = + Classifier.topLevel(pkg, property.name.capitalize()) + } + + private open class TypeAtPackage(val pkg: String) { + operator fun getValue(thisRef: KotlinTypes, property: KProperty<*>): KotlinClassifierType = + Classifier.topLevel(pkg, property.name.capitalize()).type + } + + private object BuiltInType : TypeAtPackage("kotlin") + private object CollectionClassifier : ClassifierAtPackage("kotlin.collections") + + private object InteropClassifier : ClassifierAtPackage("kotlinx.cinterop") + private object InteropType : TypeAtPackage("kotlinx.cinterop") + private object KotlinNativeType : TypeAtPackage("kotlin.native") +} + +abstract class KotlinFile( + val pkg: String, + namesToBeDeclared: List +) : KotlinScope { + + // Note: all names are related to classifiers currently. + + private val namesToBeDeclared: Set + + init { + this.namesToBeDeclared = mutableSetOf() + + namesToBeDeclared.forEach { + if (it in this.namesToBeDeclared) { + throw IllegalArgumentException("'$it' is going to be declared twice") + } else { + this.namesToBeDeclared.add(it) + } + } + } + + private val importedNameToPkg = mutableMapOf() + private val declaredProperties = mutableSetOf() + + override fun reference(classifier: Classifier): String = if (classifier.topLevelName in namesToBeDeclared) { + if (classifier.pkg == this.pkg) { + classifier.getRelativeFqName() + } else { + // Don't import if would clash with own declaration: + classifier.fqName + } + } else if (classifier.pkg == this.pkg) { + throw IllegalArgumentException( + "'${classifier.topLevelName}' from the file package was not reserved for declaration" + ) + } else { + if (tryImport(classifier)) { + // Is successfully imported: + classifier.getRelativeFqName() + } else { + classifier.fqName + } + } + + private fun tryImport(classifier: Classifier): Boolean { + if (classifier.topLevelName in declaredProperties) { + return false + } + + return importedNameToPkg.getOrPut(classifier.topLevelName) { classifier.pkg } == classifier.pkg + } + + private val alreadyDeclared = mutableSetOf() + + override fun declare(classifier: Classifier): String { + if (classifier.pkg != this.pkg) { + throw IllegalArgumentException("wrong package for classifier ${classifier.fqName}; expected '$pkg', got '${classifier.pkg}'") + } + + if (!classifier.isTopLevel) { + throw IllegalArgumentException( + "'${classifier.getRelativeFqName()}' is not top-level thus can't be declared at file scope" + ) + } + + val topLevelName = classifier.topLevelName + if (topLevelName in alreadyDeclared) { + throw IllegalStateException("'$topLevelName' is already declared") + } + alreadyDeclared.add(topLevelName) + + return topLevelName + } + + override fun declareProperty(receiver: String?, name: String): String? { + val fullName = receiver?.let { "$it.${name}" } ?: name + return if (fullName in declaredProperties || name in namesToBeDeclared || name in importedNameToPkg) { + null + // TODO: using original global name should be preferred to importing the clashed name. + } else { + declaredProperties.add(fullName) + name + } + } + + fun buildImports(): List = importedNameToPkg.mapNotNull { (name, pkg) -> + if (pkg == "kotlin" || pkg == "kotlinx.cinterop") { + // Is already imported either by default or with '*': + null + } else { + "import $pkg.${name.asSimpleName()}" + } + }.sorted() + +} + +internal fun getTopLevelPropertyDeclarationName(scope: KotlinScope, property: PropertyStub): String { + val receiverName = property.receiverType?.underlyingTypeFqName + return getTopLevelPropertyDeclarationName(scope, receiverName, property.name) +} + +// Try to use the provided name. If failed, mangle it with underscore and try again: +private tailrec fun getTopLevelPropertyDeclarationName(scope: KotlinScope, receiver: String?, name: String): String = + scope.declareProperty(receiver, name) ?: getTopLevelPropertyDeclarationName(scope, receiver, name + "_") \ No newline at end of file diff --git a/kotlin-native/Interop/StubGenerator/src/main/kotlin/org/jetbrains/kotlin/native/interop/gen/LibraryUtils.kt b/kotlin-native/Interop/StubGenerator/src/main/kotlin/org/jetbrains/kotlin/native/interop/gen/LibraryUtils.kt new file mode 100644 index 00000000000..37141b919e6 --- /dev/null +++ b/kotlin-native/Interop/StubGenerator/src/main/kotlin/org/jetbrains/kotlin/native/interop/gen/LibraryUtils.kt @@ -0,0 +1,44 @@ +/* + * Copyright 2010-2017 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.jetbrains.kotlin.native.interop.gen + +import org.jetbrains.kotlin.konan.file.File + +internal fun resolveLibraries(staticLibraries: List, libraryPaths: List): List { + val result = mutableListOf() + staticLibraries.forEach { library -> + + val resolution = libraryPaths.map { "$it/$library" } + .find { File(it).exists } + + if (resolution != null) { + result.add(resolution) + } else { + error("Could not find '$library' binary in neither of $libraryPaths") + } + } + return result +} + +internal fun argsToCompiler(staticLibraries: Array, libraryPaths: Array) = argsToCompiler(staticLibraries.toList(), libraryPaths.toList()) + +internal fun argsToCompiler(staticLibraries: List, libraryPaths: List) = + resolveLibraries(staticLibraries, libraryPaths) + .map { it -> listOf("-include-binary", it) } + .flatten() + .toTypedArray() + diff --git a/kotlin-native/Interop/StubGenerator/src/main/kotlin/org/jetbrains/kotlin/native/interop/gen/MappingBridgeGenerator.kt b/kotlin-native/Interop/StubGenerator/src/main/kotlin/org/jetbrains/kotlin/native/interop/gen/MappingBridgeGenerator.kt new file mode 100644 index 00000000000..68068bba5a4 --- /dev/null +++ b/kotlin-native/Interop/StubGenerator/src/main/kotlin/org/jetbrains/kotlin/native/interop/gen/MappingBridgeGenerator.kt @@ -0,0 +1,46 @@ +/* + * Copyright 2010-2017 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.jetbrains.kotlin.native.interop.gen + +import org.jetbrains.kotlin.native.interop.indexer.Type + +data class TypedKotlinValue(val type: Type, val value: KotlinExpression) +data class TypedNativeValue(val type: Type, val value: NativeExpression) + +/** + * Generates bridges between Kotlin and native, passing arbitrary native-typed values. + * + * It does the same as [SimpleBridgeGenerator] except that it supports any native types, e.g. struct values. + */ +interface MappingBridgeGenerator { + fun kotlinToNative( + builder: KotlinCodeBuilder, + nativeBacked: NativeBacked, + returnType: Type, + kotlinValues: List, + independent: Boolean, + block: NativeCodeBuilder.(nativeValues: List) -> NativeExpression + ): KotlinExpression + + fun nativeToKotlin( + builder: NativeCodeBuilder, + nativeBacked: NativeBacked, + returnType: Type, + nativeValues: List, + block: KotlinCodeBuilder.(kotlinValues: List) -> KotlinExpression + ): NativeExpression +} diff --git a/kotlin-native/Interop/StubGenerator/src/main/kotlin/org/jetbrains/kotlin/native/interop/gen/MappingBridgeGeneratorImpl.kt b/kotlin-native/Interop/StubGenerator/src/main/kotlin/org/jetbrains/kotlin/native/interop/gen/MappingBridgeGeneratorImpl.kt new file mode 100644 index 00000000000..cfda59df17d --- /dev/null +++ b/kotlin-native/Interop/StubGenerator/src/main/kotlin/org/jetbrains/kotlin/native/interop/gen/MappingBridgeGeneratorImpl.kt @@ -0,0 +1,207 @@ +/* + * Copyright 2010-2017 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.jetbrains.kotlin.native.interop.gen + +import org.jetbrains.kotlin.native.interop.indexer.RecordType +import org.jetbrains.kotlin.native.interop.indexer.Type +import org.jetbrains.kotlin.native.interop.indexer.VoidType +import org.jetbrains.kotlin.native.interop.indexer.unwrapTypedefs + +/** + * The [MappingBridgeGenerator] implementation which uses [SimpleBridgeGenerator] as the backend and + * maps the type using [mirror]. + */ +class MappingBridgeGeneratorImpl( + val declarationMapper: DeclarationMapper, + val simpleBridgeGenerator: SimpleBridgeGenerator +) : MappingBridgeGenerator { + + override fun kotlinToNative( + builder: KotlinCodeBuilder, + nativeBacked: NativeBacked, + returnType: Type, + kotlinValues: List, + independent: Boolean, + block: NativeCodeBuilder.(nativeValues: List) -> NativeExpression + ): KotlinExpression { + val bridgeArguments = mutableListOf() + + kotlinValues.forEach { (type, value) -> + if (type.unwrapTypedefs() is RecordType) { + builder.pushMemScoped() + val bridgeArgument = "$value.getPointer(memScope).rawValue" + bridgeArguments.add(BridgeTypedKotlinValue(BridgedType.NATIVE_PTR, bridgeArgument)) + } else { + val info = mirror(declarationMapper, type).info + bridgeArguments.add(BridgeTypedKotlinValue(info.bridgedType, info.argToBridged(value))) + } + } + + val unwrappedReturnType = returnType.unwrapTypedefs() + val kniRetVal = "kniRetVal" + val bridgeReturnType = when (unwrappedReturnType) { + VoidType -> BridgedType.VOID + is RecordType -> { + val mirror = mirror(declarationMapper, returnType) + val tmpVarName = kniRetVal + // We clear in the finally block. + builder.out("val $tmpVarName = nativeHeap.alloc<${mirror.pointedType.render(builder.scope)}>()") + builder.pushBlock(start = "try {", end = "} finally { nativeHeap.free($tmpVarName) }") + bridgeArguments.add(BridgeTypedKotlinValue(BridgedType.NATIVE_PTR, "$tmpVarName.rawPtr")) + BridgedType.VOID + } + else -> { + val mirror = mirror(declarationMapper, returnType) + mirror.info.bridgedType + } + } + + val callExpr = simpleBridgeGenerator.kotlinToNative( + nativeBacked, bridgeReturnType, bridgeArguments, independent + ) { bridgeNativeValues -> + + val nativeValues = mutableListOf() + kotlinValues.forEachIndexed { index, (type, _) -> + val unwrappedType = type.unwrapTypedefs() + if (unwrappedType is RecordType) { + nativeValues.add("*(${unwrappedType.decl.spelling}*)${bridgeNativeValues[index]}") + } else { + nativeValues.add( + mirror(declarationMapper, type).info.cFromBridged( + bridgeNativeValues[index], scope, nativeBacked + ) + ) + } + } + + val nativeResult = block(nativeValues) + + when (unwrappedReturnType) { + is VoidType -> { + out(nativeResult + ";") + "" + } + is RecordType -> { + val kniStructResult = "kniStructResult" + + out("${unwrappedReturnType.decl.spelling} $kniStructResult = $nativeResult;") + out("memcpy(${bridgeNativeValues.last()}, &$kniStructResult, sizeof($kniStructResult));") + "" + } + else -> { + nativeResult + } + } + } + + val result = when (unwrappedReturnType) { + is VoidType -> callExpr + is RecordType -> { + builder.out(callExpr) + "$kniRetVal.readValue()" + } + else -> { + val mirror = mirror(declarationMapper, returnType) + mirror.info.argFromBridged(callExpr, builder.scope, nativeBacked) + } + } + + return result + } + + override fun nativeToKotlin( + builder: NativeCodeBuilder, + nativeBacked: NativeBacked, + returnType: Type, + nativeValues: List, + block: KotlinCodeBuilder.(kotlinValues: List) -> KotlinExpression + ): NativeExpression { + + val bridgeArguments = mutableListOf() + + nativeValues.forEachIndexed { _, (type, value) -> + val bridgeArgument = if (type.unwrapTypedefs() is RecordType) { + BridgeTypedNativeValue(BridgedType.NATIVE_PTR, "&$value") + } else { + val info = mirror(declarationMapper, type).info + BridgeTypedNativeValue(info.bridgedType, value) + } + bridgeArguments.add(bridgeArgument) + } + + val unwrappedReturnType = returnType.unwrapTypedefs() + val kniRetVal = "kniRetVal" + val bridgeReturnType = when (unwrappedReturnType) { + VoidType -> BridgedType.VOID + is RecordType -> { + val tmpVarName = kniRetVal + builder.out("${unwrappedReturnType.decl.spelling} $tmpVarName;") + bridgeArguments.add(BridgeTypedNativeValue(BridgedType.NATIVE_PTR, "&$tmpVarName")) + BridgedType.VOID + } + else -> { + val mirror = mirror(declarationMapper, returnType) + mirror.info.bridgedType + } + } + + val callExpr = simpleBridgeGenerator.nativeToKotlin( + nativeBacked, + bridgeReturnType, + bridgeArguments + ) { bridgeKotlinValues -> + val kotlinValues = mutableListOf() + nativeValues.forEachIndexed { index, (type, _) -> + val mirror = mirror(declarationMapper, type) + if (type.unwrapTypedefs() is RecordType) { + val pointedTypeName = mirror.pointedType.render(this.scope) + kotlinValues.add( + "interpretPointed<$pointedTypeName>(${bridgeKotlinValues[index]}).readValue()" + ) + } else { + kotlinValues.add(mirror.info.argFromBridged(bridgeKotlinValues[index], this.scope, nativeBacked)) + } + } + + val kotlinResult = block(kotlinValues) + when (unwrappedReturnType) { + is RecordType -> { + "$kotlinResult.write(${bridgeKotlinValues.last()})" + } + is VoidType -> { + kotlinResult + } + else -> { + mirror(declarationMapper, returnType).info.argToBridged(kotlinResult) + } + } + } + + val result = when (unwrappedReturnType) { + is VoidType -> callExpr + is RecordType -> { + builder.out("$callExpr;") + kniRetVal + } + else -> { + mirror(declarationMapper, returnType).info.cFromBridged(callExpr, builder.scope, nativeBacked) + } + } + + return result + } +} \ No newline at end of file diff --git a/kotlin-native/Interop/StubGenerator/src/main/kotlin/org/jetbrains/kotlin/native/interop/gen/Mappings.kt b/kotlin-native/Interop/StubGenerator/src/main/kotlin/org/jetbrains/kotlin/native/interop/gen/Mappings.kt new file mode 100644 index 00000000000..80b9beada07 --- /dev/null +++ b/kotlin-native/Interop/StubGenerator/src/main/kotlin/org/jetbrains/kotlin/native/interop/gen/Mappings.kt @@ -0,0 +1,578 @@ +/* + * Copyright 2010-2017 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.jetbrains.kotlin.native.interop.gen + +import org.jetbrains.kotlin.native.interop.indexer.* + +interface DeclarationMapper { + fun getKotlinClassForPointed(structDecl: StructDecl): Classifier + fun isMappedToStrict(enumDef: EnumDef): Boolean + fun getKotlinNameForValue(enumDef: EnumDef): String + fun getPackageFor(declaration: TypeDeclaration): String + + val useUnsignedTypes: Boolean +} + +fun DeclarationMapper.isMappedToSigned(integerType: IntegerType): Boolean = integerType.isSigned || !useUnsignedTypes + +fun DeclarationMapper.getKotlinClassFor( + objCClassOrProtocol: ObjCClassOrProtocol, + isMeta: Boolean = false +): Classifier { + val pkg = if (objCClassOrProtocol.isForwardDeclaration) { + when (objCClassOrProtocol) { + is ObjCClass -> "objcnames.classes" + is ObjCProtocol -> "objcnames.protocols" + } + } else { + this.getPackageFor(objCClassOrProtocol) + } + val className = objCClassOrProtocol.kotlinClassName(isMeta) + return Classifier.topLevel(pkg, className) +} + +fun PrimitiveType.getKotlinType(declarationMapper: DeclarationMapper): KotlinClassifierType = when (this) { + is CharType -> KotlinTypes.byte + + is BoolType -> KotlinTypes.boolean + +// TODO: C primitive types should probably be generated as type aliases for Kotlin types. + is IntegerType -> if (declarationMapper.isMappedToSigned(this)) { + when (this.size) { + 1 -> KotlinTypes.byte + 2 -> KotlinTypes.short + 4 -> KotlinTypes.int + 8 -> KotlinTypes.long + else -> TODO(this.toString()) + } + } else { + when (this.size) { + 1 -> KotlinTypes.uByte + 2 -> KotlinTypes.uShort + 4 -> KotlinTypes.uInt + 8 -> KotlinTypes.uLong + else -> TODO(this.toString()) + } + } + + is FloatingType -> when (this.size) { + 4 -> KotlinTypes.float + 8 -> KotlinTypes.double + else -> TODO(this.toString()) + } + + is VectorType -> { + /// @todo assert elementType and size here + KotlinTypes.vector128 + } + else -> throw NotImplementedError() +} + +private fun PrimitiveType.getBridgedType(declarationMapper: DeclarationMapper): BridgedType { + val kotlinType = this.getKotlinType(declarationMapper) + return BridgedType.values().single { + it.kotlinType == kotlinType + } +} + +internal val ObjCPointer.isNullable: Boolean + get() = this.nullability != ObjCPointer.Nullability.NonNull + +/** + * Describes the Kotlin types used to represent some C type. + */ +sealed class TypeMirror(val pointedType: KotlinClassifierType, val info: TypeInfo) { + /** + * Type to be used in bindings for argument or return value. + */ + abstract val argType: KotlinType + + /** + * Mirror for C type to be represented in Kotlin as by-value type. + */ + class ByValue( + pointedType: KotlinClassifierType, + info: TypeInfo, + val valueType: KotlinType, + val nullable: Boolean = (info is TypeInfo.Pointer) + ) : TypeMirror(pointedType, info) { + + override val argType: KotlinType + get() = valueType.makeNullableAsSpecified(nullable) + } + + /** + * Mirror for C type to be represented in Kotlin as by-ref type. + */ + class ByRef(pointedType: KotlinClassifierType, info: TypeInfo) : TypeMirror(pointedType, info) { + override val argType: KotlinType get() = KotlinTypes.cValue.typeWith(pointedType) + } +} + +/** + * Describes various type conversions for [TypeMirror]. + */ +sealed class TypeInfo { + /** + * The conversion from [TypeMirror.argType] to [bridgedType]. + */ + abstract fun argToBridged(expr: KotlinExpression): KotlinExpression + + /** + * The conversion from [bridgedType] to [TypeMirror.argType]. + */ + abstract fun argFromBridged( + expr: KotlinExpression, + scope: KotlinScope, + nativeBacked: NativeBacked + ): KotlinExpression + + abstract val bridgedType: BridgedType + + open fun cFromBridged( + expr: NativeExpression, + scope: NativeScope, + nativeBacked: NativeBacked + ): NativeExpression = expr + + open fun cToBridged(expr: NativeExpression): NativeExpression = expr + + /** + * If this info is for [TypeMirror.ByValue], then this method describes how to + * construct pointed-type from value type. + */ + abstract fun constructPointedType(valueType: KotlinType): KotlinClassifierType + + class Primitive(override val bridgedType: BridgedType, val varClass: Classifier) : TypeInfo() { + + override fun argToBridged(expr: KotlinExpression) = expr + override fun argFromBridged(expr: KotlinExpression, scope: KotlinScope, nativeBacked: NativeBacked) = expr + + override fun constructPointedType(valueType: KotlinType) = varClass.typeWith(valueType) + } + + class Boolean : TypeInfo() { + override fun argToBridged(expr: KotlinExpression) = "$expr.toByte()" + + override fun argFromBridged(expr: KotlinExpression, scope: KotlinScope, nativeBacked: NativeBacked) = + "$expr.toBoolean()" + + override val bridgedType: BridgedType get() = BridgedType.BYTE + + override fun cFromBridged(expr: NativeExpression, scope: NativeScope, nativeBacked: NativeBacked) = + "($expr) ? 1 : 0" + + override fun cToBridged(expr: NativeExpression) = "($expr) ? 1 : 0" + + override fun constructPointedType(valueType: KotlinType) = KotlinTypes.booleanVarOf.typeWith(valueType) + } + + class Enum(val clazz: Classifier, override val bridgedType: BridgedType) : TypeInfo() { + override fun argToBridged(expr: KotlinExpression) = "$expr.value" + + override fun argFromBridged(expr: KotlinExpression, scope: KotlinScope, nativeBacked: NativeBacked) = + scope.reference(clazz) + ".byValue($expr)" + + override fun constructPointedType(valueType: KotlinType) = + clazz.nested("Var").type // TODO: improve + + } + + class Pointer(val pointee: KotlinType, val cPointee: Type) : TypeInfo() { + override fun argToBridged(expr: String) = "$expr.rawValue" + + override fun argFromBridged(expr: KotlinExpression, scope: KotlinScope, nativeBacked: NativeBacked) = + "interpretCPointer<${pointee.render(scope)}>($expr)" + + override val bridgedType: BridgedType + get() = BridgedType.NATIVE_PTR + + override fun cFromBridged(expr: NativeExpression, scope: NativeScope, nativeBacked: NativeBacked) = + "(${getPointerTypeStringRepresentation(cPointee)})$expr" + + override fun constructPointedType(valueType: KotlinType) = KotlinTypes.cPointerVarOf.typeWith(valueType) + } + + class ObjCPointerInfo(val kotlinType: KotlinType, val type: ObjCPointer) : TypeInfo() { + override fun argToBridged(expr: String) = "$expr.objcPtr()" + + override fun argFromBridged(expr: KotlinExpression, scope: KotlinScope, nativeBacked: NativeBacked) = + "interpretObjCPointerOrNull<${kotlinType.render(scope)}>($expr)" + + if (type.isNullable) "" else "!!" + + override val bridgedType: BridgedType + get() = BridgedType.OBJC_POINTER + + override fun constructPointedType(valueType: KotlinType) = KotlinTypes.objCObjectVar.typeWith(valueType) + } + + class ObjCBlockPointerInfo(val kotlinType: KotlinFunctionType, val type: ObjCBlockPointer) : TypeInfo() { + + override val bridgedType: BridgedType + get() = BridgedType.OBJC_POINTER + + // When passing Kotlin function as block pointer from Kotlin to native, + // it first gets wrapped by a holder in [argToBridged], + // and then converted to block in [cFromBridged]. + + override fun argToBridged(expr: KotlinExpression): KotlinExpression = "createKotlinObjectHolder($expr)" + + override fun cFromBridged( + expr: NativeExpression, + scope: NativeScope, + nativeBacked: NativeBacked + ): NativeExpression { + val mappingBridgeGenerator = scope.mappingBridgeGenerator + + val blockParameters = type.parameterTypes.mapIndexed { index, it -> + "p$index" to it.getStringRepresentation() + }.joinToString { "${it.second} ${it.first}" } + + val blockReturnType = type.returnType.getStringRepresentation() + + val kniFunction = "kniFunction" + + val codeBuilder = NativeCodeBuilder(scope) + + return buildString { + append("({ ") // Statement expression begins. + append("id $kniFunction = $expr; ") // Note: it gets captured below. + append("($kniFunction == nil) ? nil : ") + append("(id)") // Cast the block to `id`. + append("^$blockReturnType($blockParameters) {") // Block begins. + + // As block body, generate the code which simply bridges to Kotlin and calls the Kotlin function: + mappingBridgeGenerator.nativeToKotlin( + codeBuilder, + nativeBacked, + type.returnType, + type.parameterTypes.mapIndexed { index, it -> + TypedNativeValue(it, "p$index") + } + TypedNativeValue(ObjCIdType(ObjCPointer.Nullability.Nullable, emptyList()), kniFunction) + ) { kotlinValues -> + val kotlinFunctionType = kotlinType.render(this.scope) + val kotlinFunction = "unwrapKotlinObjectHolder<$kotlinFunctionType>(${kotlinValues.last()})" + "$kotlinFunction(${kotlinValues.dropLast(1).joinToString()})" + }.let { + codeBuilder.out("return $it;") + } + + codeBuilder.lines.joinTo(this, separator = " ") + + append(" };") // Block ends. + append(" })") // Statement expression ends. + } + } + + // When passing block pointer as Kotlin function from native to Kotlin, + // it is converted to Kotlin function in [cFromBridged]. + + override fun cToBridged(expr: NativeExpression): NativeExpression = expr + + override fun argFromBridged( + expr: KotlinExpression, + scope: KotlinScope, + nativeBacked: NativeBacked + ): KotlinExpression { + val mappingBridgeGenerator = scope.mappingBridgeGenerator + + val funParameters = type.parameterTypes.mapIndexed { index, _ -> + "p$index" to kotlinType.parameterTypes[index] + }.joinToString { "${it.first}: ${it.second.render(scope)}" } + + val funReturnType = kotlinType.returnType.render(scope) + + val codeBuilder = KotlinCodeBuilder(scope) + val kniBlockPtr = "kniBlockPtr" + + + // Build the anonymous function expression: + val anonymousFun = buildString { + append("fun($funParameters): $funReturnType {\n") // Anonymous function begins. + + // As function body, generate the code which simply bridges to native and calls the block: + mappingBridgeGenerator.kotlinToNative( + codeBuilder, + nativeBacked, + type.returnType, + type.parameterTypes.mapIndexed { index, it -> + TypedKotlinValue(it, "p$index") + } + TypedKotlinValue(PointerType(VoidType), "interpretCPointer($kniBlockPtr)"), + independent = true + + ) { nativeValues -> + val type = type + val blockType = blockTypeStringRepresentation(type) + val objCBlock = "((__bridge $blockType)${nativeValues.last()})" + "$objCBlock(${nativeValues.dropLast(1).joinToString()})" + }.let { + codeBuilder.returnResult(it) + } + + codeBuilder.build().joinTo(this, separator = "\n") + append("}") // Anonymous function ends. + } + + val nullOutput = if (type.isNullable) "null" else "throw NullPointerException()" + + return "$expr.let { $kniBlockPtr -> if (kniBlockPtr == nativeNullPtr) $nullOutput else $anonymousFun }" + } + + override fun constructPointedType(valueType: KotlinType): KotlinClassifierType { + return Classifier.topLevel("kotlinx.cinterop", "ObjCBlockVar").typeWith(valueType) + } + } + + class ByRef(val pointed: KotlinType) : TypeInfo() { + override fun argToBridged(expr: String) = error(pointed) + override fun argFromBridged(expr: KotlinExpression, scope: KotlinScope, nativeBacked: NativeBacked) = + error(pointed) + override val bridgedType: BridgedType get() = error(pointed) + override fun cFromBridged(expr: NativeExpression, scope: NativeScope, nativeBacked: NativeBacked) = + error(pointed) + override fun cToBridged(expr: String) = error(pointed) + + // TODO: this method must not exist. + override fun constructPointedType(valueType: KotlinType): KotlinClassifierType = error(pointed) + } +} + +fun mirrorPrimitiveType(type: PrimitiveType, declarationMapper: DeclarationMapper): TypeMirror.ByValue { + val varClassName = when (type) { + is CharType -> "ByteVar" + is BoolType -> "BooleanVar" + is IntegerType -> if (declarationMapper.isMappedToSigned(type)) { + when (type.size) { + 1 -> "ByteVar" + 2 -> "ShortVar" + 4 -> "IntVar" + 8 -> "LongVar" + else -> TODO(type.toString()) + } + } else { + when (type.size) { + 1 -> "UByteVar" + 2 -> "UShortVar" + 4 -> "UIntVar" + 8 -> "ULongVar" + else -> TODO(type.toString()) + } + } + is FloatingType -> when (type.size) { + 4 -> "FloatVar" + 8 -> "DoubleVar" + else -> TODO(type.toString()) + } + is VectorType -> { + "Vector128Var" + } + else -> TODO(type.toString()) + } + + val varClass = Classifier.topLevel("kotlinx.cinterop", varClassName) + val varClassOf = Classifier.topLevel("kotlinx.cinterop", "${varClassName}Of") + + val info = if (type is BoolType) { + TypeInfo.Boolean() + } else { + TypeInfo.Primitive(type.getBridgedType(declarationMapper), varClassOf) + } + return TypeMirror.ByValue(varClass.type, info, type.getKotlinType(declarationMapper)) +} + +private fun byRefTypeMirror(pointedType: KotlinClassifierType) : TypeMirror.ByRef { + val info = TypeInfo.ByRef(pointedType) + return TypeMirror.ByRef(pointedType, info) +} + +fun mirror(declarationMapper: DeclarationMapper, type: Type): TypeMirror = when (type) { + is PrimitiveType -> mirrorPrimitiveType(type, declarationMapper) + + is RecordType -> byRefTypeMirror(declarationMapper.getKotlinClassForPointed(type.decl).type) + + is EnumType -> { + val pkg = declarationMapper.getPackageFor(type.def) + val kotlinName = declarationMapper.getKotlinNameForValue(type.def) + .let { mangleSimple(it) } // enum class requires additional mangling + + when { + declarationMapper.isMappedToStrict(type.def) -> { + val bridgedType = (type.def.baseType.unwrapTypedefs() as PrimitiveType).getBridgedType(declarationMapper) + val clazz = Classifier.topLevel(pkg, kotlinName) + val info = TypeInfo.Enum(clazz, bridgedType) + TypeMirror.ByValue(clazz.nested("Var").type, info, clazz.type) + } + !type.def.isAnonymous -> { + val baseTypeMirror = mirror(declarationMapper, type.def.baseType) + TypeMirror.ByValue( + Classifier.topLevel(pkg, kotlinName + "Var").typeAbbreviation(baseTypeMirror.pointedType), + baseTypeMirror.info, + Classifier.topLevel(pkg, kotlinName).typeAbbreviation(baseTypeMirror.argType) + ) + } + else -> mirror(declarationMapper, type.def.baseType) + } + } + + is PointerType -> { + val pointeeType = type.pointeeType + val unwrappedPointeeType = pointeeType.unwrapTypedefs() + if (unwrappedPointeeType is VoidType) { + val info = TypeInfo.Pointer(KotlinTypes.cOpaque, pointeeType) + TypeMirror.ByValue(KotlinTypes.cOpaquePointerVar, info, KotlinTypes.cOpaquePointer) + } else if (unwrappedPointeeType is ArrayType) { + mirror(declarationMapper, pointeeType) + } else { + val pointeeMirror = mirror(declarationMapper, pointeeType) + val info = TypeInfo.Pointer(pointeeMirror.pointedType, pointeeType) + TypeMirror.ByValue( + KotlinTypes.cPointerVar.typeWith(pointeeMirror.pointedType), + info, + KotlinTypes.cPointer.typeWith(pointeeMirror.pointedType) + ) + } + } + + is ArrayType -> { + // TODO: array type doesn't exactly correspond neither to pointer nor to value. + val elemTypeMirror = mirror(declarationMapper, type.elemType) + if (type.elemType.unwrapTypedefs() is ArrayType) { + elemTypeMirror + } else { + val info = TypeInfo.Pointer(elemTypeMirror.pointedType, type.elemType) + TypeMirror.ByValue( + KotlinTypes.cArrayPointerVar.typeWith(elemTypeMirror.pointedType), + info, + KotlinTypes.cArrayPointer.typeWith(elemTypeMirror.pointedType) + ) + } + } + + is FunctionType -> byRefTypeMirror(KotlinTypes.cFunction.typeWith(getKotlinFunctionType(declarationMapper, type))) + + is Typedef -> { + val baseType = mirror(declarationMapper, type.def.aliased) + val pkg = declarationMapper.getPackageFor(type.def) + + val name = type.def.name + when (baseType) { + is TypeMirror.ByValue -> { + val valueType = Classifier.topLevel(pkg, name).typeAbbreviation(baseType.valueType) + val underlyingPointedType = if (baseType.info is TypeInfo.Pointer) { + KotlinTypes.cPointerVarOf.typeWith(valueType) + } else { + baseType.pointedType + } + val pointedType = Classifier.topLevel(pkg, "${name}Var").typeAbbreviation(underlyingPointedType) + TypeMirror.ByValue( + pointedType, + baseType.info, + valueType, + nullable = baseType.nullable) + } + + is TypeMirror.ByRef -> TypeMirror.ByRef( + Classifier.topLevel(pkg, name).typeAbbreviation(baseType.pointedType), + baseType.info + ) + } + + } + + is ObjCPointer -> objCPointerMirror(declarationMapper, type) + + else -> TODO(type.toString()) +} + +internal tailrec fun ObjCClass.isNSStringOrSubclass(): Boolean = when (this.name) { + "NSMutableString", // fast path and handling for forward declarations. + "NSString" -> true + else -> { + val baseClass = this.baseClass + if (baseClass != null) { + baseClass.isNSStringOrSubclass() + } else { + false + } + } +} + +internal fun ObjCClass.isNSStringSubclass(): Boolean = this.baseClass?.isNSStringOrSubclass() == true + +private fun objCPointerMirror(declarationMapper: DeclarationMapper, type: ObjCPointer): TypeMirror.ByValue { + if (type is ObjCObjectPointer && type.def.isNSStringOrSubclass()) { + val valueType = KotlinTypes.string + return objCMirror(valueType, TypeInfo.ObjCPointerInfo(valueType, type), type.isNullable) + } + + val valueType = when (type) { + is ObjCIdType -> { + type.protocols.firstOrNull()?.let { declarationMapper.getKotlinClassFor(it) }?.type + ?: KotlinTypes.any + } + is ObjCClassPointer -> KotlinTypes.objCClass.type + is ObjCObjectPointer -> { + when (type.def.name) { + "NSArray" -> KotlinTypes.list.typeWith(StarProjection) + "NSMutableArray" -> KotlinTypes.mutableList.typeWith(KotlinTypes.any.makeNullable()) + "NSSet" -> KotlinTypes.set.typeWith(StarProjection) + "NSDictionary" -> KotlinTypes.map.typeWith(KotlinTypes.any.makeNullable(), StarProjection) + else -> declarationMapper.getKotlinClassFor(type.def).type + } + } + is ObjCInstanceType -> TODO(type.toString()) // Must have already been handled. + is ObjCBlockPointer -> return objCBlockPointerMirror(declarationMapper, type) + } + + return objCMirror(valueType, TypeInfo.ObjCPointerInfo(valueType, type), type.isNullable) +} + +private fun objCBlockPointerMirror(declarationMapper: DeclarationMapper, type: ObjCBlockPointer): TypeMirror.ByValue { + val returnType = if (type.returnType.unwrapTypedefs() is VoidType) { + KotlinTypes.unit + } else { + mirror(declarationMapper, type.returnType).argType + } + val kotlinType = KotlinFunctionType( + type.parameterTypes.map { mirror(declarationMapper, it).argType }, + returnType + ) + + val info = TypeInfo.ObjCBlockPointerInfo(kotlinType, type) + return objCMirror(kotlinType, info, type.isNullable) +} + +private fun objCMirror(valueType: KotlinType, info: TypeInfo, nullable: Boolean) = TypeMirror.ByValue( + info.constructPointedType(valueType.makeNullableAsSpecified(nullable)), + info, + valueType.makeNullable(), // All typedefs to Objective-C pointers would be nullable for simplicity + nullable +) + +fun getKotlinFunctionType(declarationMapper: DeclarationMapper, type: FunctionType): KotlinFunctionType { + val returnType = if (type.returnType.unwrapTypedefs() is VoidType) { + KotlinTypes.unit + } else { + mirror(declarationMapper, type.returnType).argType + } + return KotlinFunctionType( + type.parameterTypes.map { mirror(declarationMapper, it).argType }, + returnType, + nullable = false + ) +} + diff --git a/kotlin-native/Interop/StubGenerator/src/main/kotlin/org/jetbrains/kotlin/native/interop/gen/ObjCStubs.kt b/kotlin-native/Interop/StubGenerator/src/main/kotlin/org/jetbrains/kotlin/native/interop/gen/ObjCStubs.kt new file mode 100644 index 00000000000..d327e946d4b --- /dev/null +++ b/kotlin-native/Interop/StubGenerator/src/main/kotlin/org/jetbrains/kotlin/native/interop/gen/ObjCStubs.kt @@ -0,0 +1,602 @@ +/* + * Copyright 2010-2017 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.jetbrains.kotlin.native.interop.gen + +import org.jetbrains.kotlin.native.interop.indexer.* + +internal fun ObjCMethod.getKotlinParameterNames(forConstructorOrFactory: Boolean = false): List { + val selectorParts = this.selector.split(":") + + val result = mutableListOf() + + fun String.mangled(): String { + var mangled = this + while (mangled in result) { + mangled = "_$mangled" + } + return mangled + } + + // The names of all parameters except first must depend only on the selector: + this.parameters.forEachIndexed { index, _ -> + if (index > 0) { + val name = selectorParts[index].takeIf { it.isNotEmpty() } ?: "_$index" + result.add(name.mangled()) + } + } + + this.parameters.firstOrNull()?.let { + val name = this.getFirstKotlinParameterNameCandidate(forConstructorOrFactory) + result.add(0, name.mangled()) + } + + if (this.isVariadic) { + result.add("args".mangled()) + } + + return result +} + +private fun ObjCMethod.getFirstKotlinParameterNameCandidate(forConstructorOrFactory: Boolean): String { + if (forConstructorOrFactory) { + val selectorPart = this.selector.takeWhile { it != ':' }.trimStart('_') + if (selectorPart.startsWith("init")) { + selectorPart.removePrefix("init").removePrefix("With") + .takeIf { it.isNotEmpty() }?.let { return it.decapitalize() } + } + } + + return this.parameters.first().name?.takeIf { it.isNotEmpty() } ?: "_0" +} + +private fun ObjCMethod.getKotlinParameters( + stubIrBuilder: StubsBuildingContext, + forConstructorOrFactory: Boolean +): List { + if (this.isInit && this.parameters.isEmpty() && this.selector != "init") { + // Create synthetic Unit parameter, just like Swift does in this case: + val parameterName = this.selector.removePrefix("init").removePrefix("With").decapitalize() + return listOf(FunctionParameterStub(parameterName, KotlinTypes.unit.toStubIrType())) + // Note: this parameter is explicitly handled in compiler. + } + + val names = getKotlinParameterNames(forConstructorOrFactory) // TODO: consider refactoring. + val result = mutableListOf() + + this.parameters.mapIndexedTo(result) { index, it -> + val kotlinType = stubIrBuilder.mirror(it.type).argType + val name = names[index] + val annotations = if (it.nsConsumed) listOf(AnnotationStub.ObjC.Consumed) else emptyList() + FunctionParameterStub(name, kotlinType.toStubIrType(), isVararg = false, annotations = annotations) + } + if (this.isVariadic) { + result += FunctionParameterStub( + names.last(), + KotlinTypes.any.makeNullable().toStubIrType(), + isVararg = true, + annotations = emptyList() + ) + } + return result +} + +private class ObjCMethodStubBuilder( + private val method: ObjCMethod, + private val container: ObjCContainer, + private val isDesignatedInitializer: Boolean, + override val context: StubsBuildingContext +) : StubElementBuilder { + private val isStret: Boolean + private val stubReturnType: StubType + val annotations = mutableListOf() + private val kotlinMethodParameters: List + private val external: Boolean + private val receiver: ReceiverParameterStub? + private val name: String = method.kotlinName + private val origin = StubOrigin.ObjCMethod(method, container) + private val modality: MemberStubModality + private val isOverride: Boolean = + container is ObjCClassOrProtocol && method.isOverride(container) + + init { + val returnType = method.getReturnType(container.classOrProtocol) + isStret = returnType.isStret(context.configuration.target) + stubReturnType = if (returnType.unwrapTypedefs() is VoidType) { + KotlinTypes.unit + } else { + context.mirror(returnType).argType + }.toStubIrType() + val methodAnnotation = AnnotationStub.ObjC.Method( + method.selector, + method.encoding, + isStret + ) + annotations += buildObjCMethodAnnotations(methodAnnotation) + kotlinMethodParameters = method.getKotlinParameters(context, forConstructorOrFactory = false) + external = (container !is ObjCProtocol) + modality = when (container) { + is ObjCClass -> MemberStubModality.OPEN + is ObjCProtocol -> if (method.isOptional) MemberStubModality.OPEN else MemberStubModality.ABSTRACT + is ObjCCategory -> MemberStubModality.FINAL + } + receiver = if (container is ObjCCategory) { + val receiverType = ClassifierStubType(context.getKotlinClassFor(container.clazz, isMeta = method.isClass)) + ReceiverParameterStub(receiverType) + } else null + } + + private fun buildObjCMethodAnnotations(main: AnnotationStub): List = listOfNotNull( + main, + AnnotationStub.ObjC.ConsumesReceiver.takeIf { method.nsConsumesSelf }, + AnnotationStub.ObjC.ReturnsRetained.takeIf { method.nsReturnsRetained } + ) + + fun isDefaultConstructor(): Boolean = + method.isInit && method.parameters.isEmpty() + + override fun build(): List { + val replacement = if (method.isInit) { + val parameters = method.getKotlinParameters(context, forConstructorOrFactory = true) + when (container) { + is ObjCClass -> { + annotations.add(0, deprecatedInit( + container.kotlinClassName(method.isClass), + kotlinMethodParameters.map { it.name }, + factory = false + )) + val designated = isDesignatedInitializer || + context.configuration.disableDesignatedInitializerChecks + + val annotations = listOf(AnnotationStub.ObjC.Constructor(method.selector, designated)) + val constructor = ConstructorStub(parameters, annotations, isPrimary = false, origin = origin) + constructor + } + is ObjCCategory -> { + assert(!method.isClass) + + + val clazz = context.getKotlinClassFor(container.clazz, isMeta = false).type + + annotations.add(0, deprecatedInit( + clazz.classifier.getRelativeFqName(), + kotlinMethodParameters.map { it.name }, + factory = true + )) + + val factoryAnnotation = AnnotationStub.ObjC.Factory( + method.selector, + method.encoding, + isStret + ) + val annotations = buildObjCMethodAnnotations(factoryAnnotation) + + val originalReturnType = method.getReturnType(container.clazz) + val typeParameter = TypeParameterStub("T", clazz.toStubIrType()) + val returnType = if (originalReturnType is ObjCPointer) { + typeParameter.getStubType(originalReturnType.isNullable) + } else { + // This shouldn't happen actually. + this.stubReturnType + } + val typeArgument = TypeArgumentStub(typeParameter.getStubType(false)) + val receiverType = ClassifierStubType(KotlinTypes.objCClassOf, listOf(typeArgument)) + val receiver = ReceiverParameterStub(receiverType) + val createMethod = FunctionStub( + "create", + returnType, + parameters, + receiver = receiver, + typeParameters = listOf(typeParameter), + external = true, + origin = StubOrigin.ObjCCategoryInitMethod(method), + annotations = annotations, + modality = MemberStubModality.FINAL + ) + createMethod + } + is ObjCProtocol -> null + } + } else { + null + } + return listOfNotNull( + FunctionStub( + name, + stubReturnType, + kotlinMethodParameters.toList(), + origin, + annotations.toList(), + external, + receiver, + modality, + emptyList(), + isOverride), + replacement + ) + } +} + +internal val ObjCContainer.classOrProtocol: ObjCClassOrProtocol + get() = when (this) { + is ObjCClassOrProtocol -> this + is ObjCCategory -> this.clazz + } + +private fun deprecatedInit(className: String, initParameterNames: List, factory: Boolean): AnnotationStub { + val replacement = if (factory) "$className.create" else className + val replacementKind = if (factory) "factory method" else "constructor" + val replaceWith = "$replacement(${initParameterNames.joinToString { it.asSimpleName() }})" + return AnnotationStub.Deprecated("Use $replacementKind instead", replaceWith, DeprecationLevel.ERROR) +} + +internal val ObjCMethod.kotlinName: String + get() { + val candidate = selector.split(":").first() + val trimmed = candidate.trimEnd('_') + return if (trimmed == "equals" && parameters.size == 1 + || (trimmed == "hashCode" || trimmed == "toString") && parameters.size == 0) { + candidate + "_" + } else { + candidate + } + } + +internal val ObjCClassOrProtocol.protocolsWithSupers: Sequence + get() = this.protocols.asSequence().flatMap { sequenceOf(it) + it.protocolsWithSupers } + +internal val ObjCClassOrProtocol.immediateSuperTypes: Sequence + get() { + val baseClass = (this as? ObjCClass)?.baseClass + if (baseClass != null) { + return sequenceOf(baseClass) + this.protocols.asSequence() + } + + return this.protocols.asSequence() + } + +internal val ObjCClassOrProtocol.selfAndSuperTypes: Sequence + get() = sequenceOf(this) + this.superTypes + +internal val ObjCClassOrProtocol.superTypes: Sequence + get() = this.immediateSuperTypes.flatMap { it.selfAndSuperTypes }.distinct() + +internal fun ObjCClassOrProtocol.declaredMethods(isClass: Boolean): Sequence = + this.methods.asSequence().filter { it.isClass == isClass } + +@Suppress("UNUSED_PARAMETER") +internal fun Sequence.inheritedTo(container: ObjCClassOrProtocol, isMeta: Boolean): Sequence = + this // TODO: exclude methods that are marked as unavailable in [container]. + +internal fun ObjCClassOrProtocol.inheritedMethods(isClass: Boolean): Sequence = + this.immediateSuperTypes.flatMap { it.methodsWithInherited(isClass) } + .distinctBy { it.selector } + .inheritedTo(this, isClass) + +internal fun ObjCClassOrProtocol.methodsWithInherited(isClass: Boolean): Sequence = + (this.declaredMethods(isClass) + this.inheritedMethods(isClass)).distinctBy { it.selector } + +internal fun ObjCClass.getDesignatedInitializerSelectors(result: MutableSet): Set { + // Note: Objective-C initializers act as usual methods and thus are inherited by subclasses. + // Swift considers all super initializers to be available (unless otherwise specified explicitly), + // but seems to consider them as non-designated if class declares its own ones explicitly. + // Simulate the similar behaviour: + val explicitlyDesignatedInitializers = this.methods.filter { it.isExplicitlyDesignatedInitializer && !it.isClass } + + if (explicitlyDesignatedInitializers.isNotEmpty()) { + explicitlyDesignatedInitializers.mapTo(result) { it.selector } + } else { + this.declaredMethods(isClass = false).filter { it.isInit }.mapTo(result) { it.selector } + this.baseClass?.getDesignatedInitializerSelectors(result) + } + + this.superTypes.filterIsInstance() + .flatMap { it.declaredMethods(isClass = false) }.filter { it.isInit } + .mapTo(result) { it.selector } + + return result +} + +internal fun ObjCMethod.isOverride(container: ObjCClassOrProtocol): Boolean = + container.superTypes.any { superType -> superType.methods.any(this::replaces) } + +internal abstract class ObjCContainerStubBuilder( + final override val context: StubsBuildingContext, + private val container: ObjCClassOrProtocol, + protected val metaContainerStub: ObjCContainerStubBuilder? +) : StubElementBuilder { + private val isMeta: Boolean get() = metaContainerStub == null + + private val designatedInitializerSelectors = if (container is ObjCClass && !isMeta) { + container.getDesignatedInitializerSelectors(mutableSetOf()) + } else { + emptySet() + } + + private val methods: List + private val properties: List + + private val protocolGetter: String? + + init { + val superMethods = container.inheritedMethods(isMeta) + + // Add all methods declared in the class or protocol: + var methods = container.declaredMethods(isMeta) + + // Exclude those which are identically declared in super types: + methods -= superMethods + + // Add some special methods from super types: + methods += superMethods.filter { it.returnsInstancetype() || it.isInit } + + // Add methods from adopted protocols that must be implemented according to Kotlin rules: + if (container is ObjCClass) { + methods += container.protocolsWithSupers.flatMap { it.declaredMethods(isMeta) }.filter { !it.isOptional } + } + + // Add methods inherited from multiple supertypes that must be defined according to Kotlin rules: + methods += container.immediateSuperTypes + .flatMap { superType -> + val methodsWithInherited = superType.methodsWithInherited(isMeta).inheritedTo(container, isMeta) + // Select only those which are represented as non-abstract in Kotlin: + when (superType) { + is ObjCClass -> methodsWithInherited + is ObjCProtocol -> methodsWithInherited.filter { it.isOptional } + } + } + .groupBy { it.selector } + .mapNotNull { (_, inheritedMethods) -> if (inheritedMethods.size > 1) inheritedMethods.first() else null } + + this.methods = methods.distinctBy { it.selector }.toList() + + this.properties = container.properties.filter { property -> + property.getter.isClass == isMeta && + // Select only properties that don't override anything: + superMethods.none { property.getter.replaces(it) || property.setter?.replaces(it) ?: false } + } + } + + private val methodToStub = methods.map { + it to ObjCMethodStubBuilder(it, container, it.selector in designatedInitializerSelectors, context) + }.toMap() + + private val propertyBuilders = properties.mapNotNull { + createObjCPropertyBuilder(context, it, container, this.methodToStub) + } + + private val modality = when (container) { + is ObjCClass -> ClassStubModality.OPEN + is ObjCProtocol -> ClassStubModality.INTERFACE + } + + private val classifier = context.getKotlinClassFor(container, isMeta) + + private val externalObjCAnnotation = when (container) { + is ObjCProtocol -> { + protocolGetter = if (metaContainerStub != null) { + metaContainerStub.protocolGetter!! + } else { + // TODO: handle the case when protocol getter stub can't be compiled. + context.generateNextUniqueId("kniprot_") + } + AnnotationStub.ObjC.ExternalClass(protocolGetter) + } + is ObjCClass -> { + protocolGetter = null + val binaryName = container.binaryName + AnnotationStub.ObjC.ExternalClass("", binaryName ?: "") + } + } + + private val interfaces: List by lazy { + val interfaces = mutableListOf() + if (container is ObjCClass) { + val baseClass = container.baseClass + val baseClassifier = if (baseClass != null) { + context.getKotlinClassFor(baseClass, isMeta) + } else { + if (isMeta) KotlinTypes.objCObjectBaseMeta else KotlinTypes.objCObjectBase + } + interfaces += baseClassifier.type.toStubIrType() + } + container.protocols.forEach { + interfaces += context.getKotlinClassFor(it, isMeta).type.toStubIrType() + } + if (interfaces.isEmpty()) { + assert(container is ObjCProtocol) + val classifier = if (isMeta) KotlinTypes.objCObjectMeta else KotlinTypes.objCObject + interfaces += classifier.type.toStubIrType() + } + if (!isMeta && container.isProtocolClass()) { + // TODO: map Protocol type to ObjCProtocol instead. + interfaces += KotlinTypes.objCProtocol.type.toStubIrType() + } + interfaces + } + + private fun buildBody(): Pair, List> { + val defaultConstructor = if (container is ObjCClass && methodToStub.values.none { it.isDefaultConstructor() }) { + // Always generate default constructor. + // If it is not produced for an init method, then include it manually: + ConstructorStub( + isPrimary = false, + visibility = VisibilityModifier.PROTECTED, + origin = StubOrigin.Synthetic.DefaultConstructor) + } else null + + return Pair( + propertyBuilders.flatMap { it.build() }, + methodToStub.values.flatMap { it.build() } + listOfNotNull(defaultConstructor) + ) + } + + protected fun buildClassStub(origin: StubOrigin, companion: ClassStub.Companion? = null): ClassStub { + val (properties, methods) = buildBody() + return ClassStub.Simple( + classifier, + properties = properties, + methods = methods.filterIsInstance(), + constructors = methods.filterIsInstance(), + origin = origin, + modality = modality, + annotations = listOf(externalObjCAnnotation), + interfaces = interfaces, + companion = companion + ) + } +} + +internal sealed class ObjCClassOrProtocolStubBuilder( + context: StubsBuildingContext, + private val container: ObjCClassOrProtocol +) : ObjCContainerStubBuilder( + context, + container, + metaContainerStub = object : ObjCContainerStubBuilder(context, container, metaContainerStub = null) { + + override fun build(): List { + val origin = when (container) { + is ObjCProtocol -> StubOrigin.ObjCProtocol(container, isMeta = true) + is ObjCClass -> StubOrigin.ObjCClass(container, isMeta = true) + } + return listOf(buildClassStub(origin)) + } + } +) + +internal class ObjCProtocolStubBuilder( + context: StubsBuildingContext, + private val protocol: ObjCProtocol +) : ObjCClassOrProtocolStubBuilder(context, protocol), StubElementBuilder { + override fun build(): List { + val classStub = buildClassStub(StubOrigin.ObjCProtocol(protocol, isMeta = false)) + return listOf(*metaContainerStub!!.build().toTypedArray(), classStub) + } +} + +internal class ObjCClassStubBuilder( + context: StubsBuildingContext, + private val clazz: ObjCClass +) : ObjCClassOrProtocolStubBuilder(context, clazz), StubElementBuilder { + override fun build(): List { + val companionSuper = ClassifierStubType(context.getKotlinClassFor(clazz, isMeta = true)) + + val objCClassType = KotlinTypes.objCClassOf.typeWith( + context.getKotlinClassFor(clazz, isMeta = false).type + ).toStubIrType() + + val superClassInit = SuperClassInit(companionSuper) + val companionClassifier = context.getKotlinClassFor(clazz, isMeta = false).nested("Companion") + val companion = ClassStub.Companion(companionClassifier, emptyList(), superClassInit, listOf(objCClassType)) + val classStub = buildClassStub(StubOrigin.ObjCClass(clazz, isMeta = false), companion) + return listOf(*metaContainerStub!!.build().toTypedArray(), classStub) + } +} + +class GeneratedObjCCategoriesMembers { + private val propertyNames = mutableSetOf() + private val instanceMethodSelectors = mutableSetOf() + private val classMethodSelectors = mutableSetOf() + + fun register(method: ObjCMethod): Boolean = + (if (method.isClass) classMethodSelectors else instanceMethodSelectors).add(method.selector) + + fun register(property: ObjCProperty): Boolean = propertyNames.add(property.name) + +} + +internal class ObjCCategoryStubBuilder( + override val context: StubsBuildingContext, + private val category: ObjCCategory +) : StubElementBuilder { + private val generatedMembers = context.generatedObjCCategoriesMembers + .getOrPut(category.clazz, { GeneratedObjCCategoriesMembers() }) + + private val methodToBuilder = category.methods.filter { generatedMembers.register(it) }.map { + it to ObjCMethodStubBuilder(it, category, isDesignatedInitializer = false, context = context) + }.toMap() + + private val methodBuilders get() = methodToBuilder.values + + private val propertyBuilders = category.properties.filter { generatedMembers.register(it) }.mapNotNull { + createObjCPropertyBuilder(context, it, category, methodToBuilder) + } + + override fun build(): List { + val description = "${category.clazz.name} (${category.name})" + val meta = StubContainerMeta( + "// @interface $description", + "// @end; // $description" + ) + val container = SimpleStubContainer( + meta = meta, + functions = methodBuilders.flatMap { it.build() }, + properties = propertyBuilders.flatMap { it.build() } + ) + return listOf(container) + } +} + +private fun createObjCPropertyBuilder( + context: StubsBuildingContext, + property: ObjCProperty, + container: ObjCContainer, + methodToStub: Map +): ObjCPropertyStubBuilder? { + // Note: the code below assumes that if the property is generated, + // then its accessors are also generated as explicit methods. + val getterStub = methodToStub[property.getter] ?: return null + val setterStub = property.setter?.let { methodToStub[it] ?: return null } + return ObjCPropertyStubBuilder(context, property, container, getterStub, setterStub) +} + +private class ObjCPropertyStubBuilder( + override val context: StubsBuildingContext, + private val property: ObjCProperty, + private val container: ObjCContainer, + private val getterBuilder: ObjCMethodStubBuilder, + private val setterMethod: ObjCMethodStubBuilder? +) : StubElementBuilder { + override fun build(): List { + val type = property.getType(container.classOrProtocol) + val kotlinType = context.mirror(type).argType + val getter = PropertyAccessor.Getter.ExternalGetter(annotations = getterBuilder.annotations) + val setter = property.setter?.let { PropertyAccessor.Setter.ExternalSetter(annotations = setterMethod!!.annotations) } + val kind = setter?.let { PropertyStub.Kind.Var(getter, it) } ?: PropertyStub.Kind.Val(getter) + val modality = MemberStubModality.FINAL + val receiver = when (container) { + is ObjCClassOrProtocol -> null + is ObjCCategory -> ClassifierStubType(context.getKotlinClassFor(container.clazz, isMeta = property.getter.isClass)) + } + val origin = StubOrigin.ObjCProperty(property, container) + return listOf(PropertyStub(mangleSimple(property.name), kotlinType.toStubIrType(), kind, modality, receiver, origin = origin)) + } +} + +fun ObjCClassOrProtocol.kotlinClassName(isMeta: Boolean): String { + val baseClassName = when (this) { + is ObjCClass -> this.name + is ObjCProtocol -> "${this.name}Protocol" + } + + return if (isMeta) "${baseClassName}Meta" else baseClassName +} + +internal fun ObjCClassOrProtocol.isProtocolClass(): Boolean = when (this) { + is ObjCClass -> (name == "Protocol" || binaryName == "Protocol") + is ObjCProtocol -> false +} diff --git a/kotlin-native/Interop/StubGenerator/src/main/kotlin/org/jetbrains/kotlin/native/interop/gen/SimpleBridgeGenerator.kt b/kotlin-native/Interop/StubGenerator/src/main/kotlin/org/jetbrains/kotlin/native/interop/gen/SimpleBridgeGenerator.kt new file mode 100644 index 00000000000..1a27ba4e24e --- /dev/null +++ b/kotlin-native/Interop/StubGenerator/src/main/kotlin/org/jetbrains/kotlin/native/interop/gen/SimpleBridgeGenerator.kt @@ -0,0 +1,101 @@ +/* + * Copyright 2010-2017 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.jetbrains.kotlin.native.interop.gen + +/** + * The type which has exact counterparts on both Kotlin and native side and can be directly passed through bridges. + */ +enum class BridgedType(val kotlinType: KotlinClassifierType, val convertor: String? = null) { + BYTE(KotlinTypes.byte, "toByte"), + SHORT(KotlinTypes.short, "toShort"), + INT(KotlinTypes.int, "toInt"), + LONG(KotlinTypes.long, "toLong"), + UBYTE(KotlinTypes.uByte, "toUByte"), + USHORT(KotlinTypes.uShort, "toUShort"), + UINT(KotlinTypes.uInt, "toUInt"), + ULONG(KotlinTypes.uLong, "toULong"), + FLOAT(KotlinTypes.float, "toFloat"), + DOUBLE(KotlinTypes.double, "toDouble"), + VECTOR128(KotlinTypes.vector128), + NATIVE_PTR(KotlinTypes.nativePtr), + OBJC_POINTER(KotlinTypes.nativePtr), + VOID(KotlinTypes.unit) +} + +data class BridgeTypedKotlinValue(val type: BridgedType, val value: KotlinExpression) +data class BridgeTypedNativeValue(val type: BridgedType, val value: NativeExpression) + +/** + * The entity which depends on native bridges. + */ +interface NativeBacked + +/** + * Generates simple bridges between Kotlin and native, passing [BridgedType] values. + */ +interface SimpleBridgeGenerator { + + val topLevelNativeScope: NativeScope + + /** + * Generates the expression to convert given Kotlin values to native counterparts, pass through the bridge, + * use inside the native code produced by [block] and then return the result back. + * + * @param block produces native code lines into the builder and returns the expression to be used as the result. + */ + fun kotlinToNative( + nativeBacked: NativeBacked, + returnType: BridgedType, + kotlinValues: List, + independent: Boolean, + block: NativeCodeBuilder.(nativeValues: List) -> NativeExpression + ): KotlinExpression + + /** + * Generates the expression to convert given native values to Kotlin counterparts, pass through the bridge, + * use inside the Kotlin code produced by [block] and then return the result back. + */ + fun nativeToKotlin( + nativeBacked: NativeBacked, + returnType: BridgedType, + nativeValues: List, + block: KotlinCodeBuilder.(kotlinValues: List) -> KotlinExpression + ): NativeExpression + + fun insertNativeBridge( + nativeBacked: NativeBacked, + kotlinLines: List, + nativeLines: List + ) + + /** + * Prepares all requested native bridges. + */ + fun prepare(): NativeBridges +} + +interface NativeBridges { + /** + * @return `true` iff given entity is supported by these bridges, + * i.e. all bridges it depends on can be successfully generated. + */ + fun isSupported(nativeBacked: NativeBacked): Boolean + + val kotlinLines: Sequence + val nativeLines: Sequence +} + diff --git a/kotlin-native/Interop/StubGenerator/src/main/kotlin/org/jetbrains/kotlin/native/interop/gen/SimpleBridgeGeneratorImpl.kt b/kotlin-native/Interop/StubGenerator/src/main/kotlin/org/jetbrains/kotlin/native/interop/gen/SimpleBridgeGeneratorImpl.kt new file mode 100644 index 00000000000..b6517d140bf --- /dev/null +++ b/kotlin-native/Interop/StubGenerator/src/main/kotlin/org/jetbrains/kotlin/native/interop/gen/SimpleBridgeGeneratorImpl.kt @@ -0,0 +1,253 @@ +/* + * Copyright 2010-2017 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.jetbrains.kotlin.native.interop.gen + +import org.jetbrains.kotlin.native.interop.gen.jvm.KotlinPlatform +import org.jetbrains.kotlin.native.interop.indexer.CompilationWithPCH +import org.jetbrains.kotlin.native.interop.indexer.Language +import org.jetbrains.kotlin.native.interop.indexer.mapFragmentIsCompilable + +internal val INVALID_CLANG_IDENTIFIER_REGEX = "[^a-zA-Z1-9_]".toRegex() + +class SimpleBridgeGeneratorImpl( + private val platform: KotlinPlatform, + private val pkgName: String, + private val jvmFileClassName: String, + private val libraryForCStubs: CompilationWithPCH, + override val topLevelNativeScope: NativeScope, + private val topLevelKotlinScope: KotlinScope +) : SimpleBridgeGenerator { + + private var nextUniqueId = 0 + + private val BridgedType.nativeType: String get() = when (platform) { + KotlinPlatform.JVM -> when (this) { + BridgedType.BYTE -> "jbyte" + BridgedType.SHORT -> "jshort" + BridgedType.INT -> "jint" + BridgedType.LONG -> "jlong" + BridgedType.UBYTE -> "jbyte" + BridgedType.USHORT -> "jshort" + BridgedType.UINT -> "jint" + BridgedType.ULONG -> "jlong" + BridgedType.FLOAT -> "jfloat" + BridgedType.DOUBLE -> "jdouble" + BridgedType.VECTOR128 -> TODO() + BridgedType.NATIVE_PTR -> "jlong" + BridgedType.OBJC_POINTER -> TODO() + BridgedType.VOID -> "void" + } + KotlinPlatform.NATIVE -> when (this) { + BridgedType.BYTE -> "int8_t" + BridgedType.SHORT -> "int16_t" + BridgedType.INT -> "int32_t" + BridgedType.LONG -> "int64_t" + BridgedType.UBYTE -> "uint8_t" + BridgedType.USHORT -> "uint16_t" + BridgedType.UINT -> "uint32_t" + BridgedType.ULONG -> "uint64_t" + BridgedType.FLOAT -> "float" + BridgedType.DOUBLE -> "double" + BridgedType.VECTOR128 -> TODO() // "float __attribute__ ((__vector_size__ (16)))" + BridgedType.NATIVE_PTR -> "void*" + BridgedType.OBJC_POINTER -> "id" + BridgedType.VOID -> "void" + } + } + + private inner class NativeBridge(val kotlinLines: List, val nativeLines: List) + + override fun kotlinToNative( + nativeBacked: NativeBacked, + returnType: BridgedType, + kotlinValues: List, + independent: Boolean, + block: NativeCodeBuilder.(nativeValues: List) -> NativeExpression + ): KotlinExpression { + + val kotlinLines = mutableListOf() + val nativeLines = mutableListOf() + + val kotlinFunctionName = "kniBridge${nextUniqueId++}" + val kotlinParameters = kotlinValues.withIndex().joinToString { + "p${it.index}: ${it.value.type.kotlinType.render(topLevelKotlinScope)}" + } + + val callExpr = "$kotlinFunctionName(${kotlinValues.joinToString { it.value }})" + + val cFunctionParameters = when (platform) { + KotlinPlatform.JVM -> mutableListOf( + "jniEnv" to "JNIEnv*", + "jclss" to "jclass" + ) + KotlinPlatform.NATIVE -> mutableListOf() + } + + kotlinValues.withIndex().mapTo(cFunctionParameters) { + "p${it.index}" to it.value.type.nativeType + } + + val joinedCParameters = cFunctionParameters.joinToString { (name, type) -> "$type $name" } + val cReturnType = returnType.nativeType + + val cFunctionHeader = when (platform) { + KotlinPlatform.JVM -> { + val funcFullName = buildString { + if (pkgName.isNotEmpty()) { + append(pkgName) + append('.') + } + append(jvmFileClassName) + append('.') + append(kotlinFunctionName) + } + + val functionName = "Java_" + funcFullName.replace("_", "_1").replace('.', '_').replace("$", "_00024") + "JNIEXPORT $cReturnType JNICALL $functionName ($joinedCParameters)" + } + KotlinPlatform.NATIVE -> { + val functionName = pkgName.replace(INVALID_CLANG_IDENTIFIER_REGEX, "_") + "_$kotlinFunctionName" + if (independent) kotlinLines.add("@" + topLevelKotlinScope.reference(KotlinTypes.independent)) + kotlinLines.add("@SymbolName(${functionName.quoteAsKotlinLiteral()})") + "$cReturnType $functionName ($joinedCParameters)" + } + } + nativeLines.add(cFunctionHeader + " {") + + buildNativeCodeLines(topLevelNativeScope) { + val cExpr = block(cFunctionParameters.takeLast(kotlinValues.size).map { (name, _) -> name }) + if (returnType != BridgedType.VOID) { + out("return ($cReturnType)$cExpr;") + } + }.forEach { + nativeLines.add(" $it") + } + + if (libraryForCStubs.language == Language.OBJECTIVE_C) { + // Prevent Objective-C exceptions from passing to Kotlin: + nativeLines.add(1, "@try {") + nativeLines.add("} @catch (id e) { objc_terminate(); }") + // 'objc_terminate' will report the exception. + // TODO: consider implementing this in bitcode generator. + } + + nativeLines.add("}") + val kotlinReturnType = returnType.kotlinType.render(topLevelKotlinScope) + kotlinLines.add("private external fun $kotlinFunctionName($kotlinParameters): $kotlinReturnType") + + val nativeBridge = NativeBridge(kotlinLines, nativeLines) + nativeBridges.add(nativeBacked to nativeBridge) + + return callExpr + } + + override fun nativeToKotlin( + nativeBacked: NativeBacked, + returnType: BridgedType, + nativeValues: List, + block: KotlinCodeBuilder.(arguments: List) -> KotlinExpression + ): NativeExpression { + + if (platform != KotlinPlatform.NATIVE) TODO() + + val kotlinLines = mutableListOf() + val nativeLines = mutableListOf() + + val kotlinFunctionName = "kniBridge${nextUniqueId++}" + val kotlinParameters = nativeValues.withIndex().map { + "p${it.index}" to it.value.type.kotlinType + } + val joinedKotlinParameters = kotlinParameters.joinToString { + "${it.first}: ${it.second.render(topLevelKotlinScope)}" + } + + val cFunctionParameters = nativeValues.withIndex().map { + "p${it.index}" to it.value.type.nativeType + } + val joinedCParameters = cFunctionParameters.joinToString { (name, type) -> "$type $name" } + val cReturnType = returnType.nativeType + + val symbolName = pkgName.replace(INVALID_CLANG_IDENTIFIER_REGEX, "_") + "_$kotlinFunctionName" + kotlinLines.add("@kotlin.native.internal.ExportForCppRuntime(${symbolName.quoteAsKotlinLiteral()})") + val cFunctionHeader = "$cReturnType $symbolName($joinedCParameters)" + + nativeLines.add("$cFunctionHeader;") + val kotlinReturnType = returnType.kotlinType.render(topLevelKotlinScope) + kotlinLines.add("private fun $kotlinFunctionName($joinedKotlinParameters): $kotlinReturnType {") + + buildKotlinCodeLines(topLevelKotlinScope) { + var kotlinExpr = block(kotlinParameters.map { (name, _) -> name }) + if (returnType == BridgedType.OBJC_POINTER) { + // The Kotlin code may lose the ownership on this pointer after returning from the bridge, + // so retain the pointer and autorelease it: + kotlinExpr = "objc_retainAutoreleaseReturnValue($kotlinExpr)" + // (Objective-C does the same for returned pointers). + } + returnResult(kotlinExpr) + }.forEach { + kotlinLines.add(" $it") + } + + kotlinLines.add("}") + + insertNativeBridge(nativeBacked, kotlinLines, nativeLines) + + return "$symbolName(${nativeValues.joinToString { it.value }})" + + } + + override fun insertNativeBridge(nativeBacked: NativeBacked, kotlinLines: List, nativeLines: List) { + val nativeBridge = NativeBridge(kotlinLines, nativeLines) + nativeBridges.add(nativeBacked to nativeBridge) + } + + private val nativeBridges = mutableListOf>() + + override fun prepare(): NativeBridges { + val includedBridges = mutableListOf() + val excludedClients = mutableSetOf() + + nativeBridges.map { it.second.nativeLines } + .mapFragmentIsCompilable(libraryForCStubs) + .forEachIndexed { index, isCompilable -> + if (!isCompilable) { + excludedClients.add(nativeBridges[index].first) + } + } + + nativeBridges.mapNotNullTo(includedBridges) { (nativeBacked, nativeBridge) -> + if (nativeBacked in excludedClients) { + null + } else { + nativeBridge + } + } + + // TODO: exclude unused bridges. + return object : NativeBridges { + + override val kotlinLines: Sequence + get() = includedBridges.asSequence().flatMap { it.kotlinLines.asSequence() } + + override val nativeLines: Sequence + get() = includedBridges.asSequence().flatMap { it.nativeLines.asSequence() } + + override fun isSupported(nativeBacked: NativeBacked): Boolean = + nativeBacked !in excludedClients + } + } +} diff --git a/kotlin-native/Interop/StubGenerator/src/main/kotlin/org/jetbrains/kotlin/native/interop/gen/StructRendering.kt b/kotlin-native/Interop/StubGenerator/src/main/kotlin/org/jetbrains/kotlin/native/interop/gen/StructRendering.kt new file mode 100644 index 00000000000..ae9f31f7c7e --- /dev/null +++ b/kotlin-native/Interop/StubGenerator/src/main/kotlin/org/jetbrains/kotlin/native/interop/gen/StructRendering.kt @@ -0,0 +1,83 @@ +package org.jetbrains.kotlin.native.interop.gen + +import org.jetbrains.kotlin.native.interop.indexer.* + +fun tryRenderStructOrUnion(def: StructDef): String? = when (def.kind) { + StructDef.Kind.STRUCT -> tryRenderStruct(def) + StructDef.Kind.UNION -> tryRenderUnion(def) +} + +private fun tryRenderStruct(def: StructDef): String? { + val isPackedStruct = def.fields.any { !it.isAligned } + + var offset = 0L + + return buildString { + append("struct") + if (isPackedStruct) append(" __attribute__((packed))") + append(" { ") + + def.members.forEachIndexed { index, it -> + val name = "p$index" + val decl = when (it) { + is Field -> { + val defaultAlignment = if (isPackedStruct) 1L else it.typeAlign + val alignment = guessAlignment(offset, it.offsetBytes, defaultAlignment) ?: return null + + offset = it.offsetBytes + it.typeSize + + tryRenderVar(it.type, name) + ?.plus(if (alignment == defaultAlignment) "" else "__attribute__((aligned($alignment)))") + } + + is BitField, // TODO: tryRenderVar(it.type, name)?.plus(" : ${it.size}") + is IncompleteField -> null // e.g. flexible array member. + } ?: return null + append("$decl; ") + } + + append("}") + } +} + +private fun guessAlignment(offset: Long, paddedOffset: Long, defaultAlignment: Long): Long? = + longArrayOf(defaultAlignment, 1L, 2L, 4L, 8L, 16L, 32L).firstOrNull { + alignUp(offset, it) == paddedOffset + } + +private fun alignUp(x: Long, alignment: Long): Long = (x + alignment - 1) and ((alignment - 1).inv()) + +private fun tryRenderUnion(def: StructDef): String? = + if (def.members.any { it.offset != 0L }) null else buildString { + append("union { ") + def.members.forEachIndexed { index, it -> + val decl = when (it) { + is Field -> tryRenderVar(it.type, "p$index") + is BitField, is IncompleteField -> null + } ?: return null + + append("$decl; ") + } + append("}") + + } + +private fun tryRenderVar(type: Type, name: String): String? = when (type) { + CharType, is BoolType -> "char $name" + is IntegerType -> "${type.spelling} $name" + is FloatingType -> "${type.spelling} $name" + is VectorType -> "${type.spelling} $name" + is RecordType -> "${tryRenderStructOrUnion(type.decl.def!!)} $name" + is EnumType -> tryRenderVar(type.def.baseType, name) + is PointerType -> "void* $name" + is ConstArrayType -> tryRenderVar(type.elemType, "$name[${type.length}]") + is IncompleteArrayType -> tryRenderVar(type.elemType, "$name[]") + is Typedef -> tryRenderVar(type.def.aliased, name) + is ObjCPointer -> "void* $name" + else -> null +} + +private val Field.offsetBytes: Long get() { + require(this.offset % 8 == 0L) + return this.offset / 8 +} \ No newline at end of file diff --git a/kotlin-native/Interop/StubGenerator/src/main/kotlin/org/jetbrains/kotlin/native/interop/gen/StubIr.kt b/kotlin-native/Interop/StubGenerator/src/main/kotlin/org/jetbrains/kotlin/native/interop/gen/StubIr.kt new file mode 100644 index 00000000000..27be99cbac5 --- /dev/null +++ b/kotlin-native/Interop/StubGenerator/src/main/kotlin/org/jetbrains/kotlin/native/interop/gen/StubIr.kt @@ -0,0 +1,529 @@ +/* + * Copyright 2010-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ +package org.jetbrains.kotlin.native.interop.gen + +import org.jetbrains.kotlin.native.interop.indexer.* + +// TODO: Replace all usages of these strings with constants. +const val cinteropPackage = "kotlinx.cinterop" +const val cinteropInternalPackage = "$cinteropPackage.internal" + +interface StubIrElement { + fun accept(visitor: StubIrVisitor, data: T): R +} + +sealed class StubContainer : StubIrElement { + abstract val meta: StubContainerMeta + abstract val classes: List + abstract val functions: List + abstract val properties: List + abstract val typealiases: List + abstract val simpleContainers: List +} + +/** + * Meta information about [StubContainer]. + * For example, can be used for comments in textual representation. + */ +class StubContainerMeta( + val textAtStart: String = "", + val textAtEnd: String = "" +) + +class SimpleStubContainer( + override val meta: StubContainerMeta = StubContainerMeta(), + override val classes: List = emptyList(), + override val functions: List = emptyList(), + override val properties: List = emptyList(), + override val typealiases: List = emptyList(), + override val simpleContainers: List = emptyList() +) : StubContainer() { + + override fun accept(visitor: StubIrVisitor, data: T): R { + return visitor.visitSimpleStubContainer(this, data) + } +} + +val StubContainer.children: List + get() = (classes as List) + properties + functions + typealiases + +/** + * Marks that abstract value of such type can be passed as value. + */ +sealed class ValueStub + +class TypeParameterStub( + val name: String, + val upperBound: StubType? = null +) { + fun getStubType(nullable: Boolean) = + TypeParameterType(name, nullable = nullable, typeParameterDeclaration = this) + +} + +interface TypeArgument { + object StarProjection : TypeArgument { + override fun toString(): String = + "*" + } + + enum class Variance { + INVARIANT, + IN, + OUT + } +} + +class TypeArgumentStub( + val type: StubType, + val variance: TypeArgument.Variance = TypeArgument.Variance.INVARIANT +) : TypeArgument { + override fun toString(): String = + type.toString() +} + +/** + * Represents a source of StubIr element. + */ +sealed class StubOrigin { + /** + * Special case when element of IR was generated. + */ + sealed class Synthetic : StubOrigin() { + object CompanionObject : Synthetic() + + /** + * Denotes default constructor that was generated and has no real origin. + */ + object DefaultConstructor : Synthetic() + + /** + * CEnum.Companion.byValue. + */ + class EnumByValue(val enum: EnumDef) : Synthetic() + + /** + * CEnum.value. + */ + class EnumValueField(val enum: EnumDef) : Synthetic() + + /** + * E.CEnumVar.value. + */ + class EnumVarValueField(val enum: EnumDef) : Synthetic() + } + + class ObjCCategoryInitMethod( + val method: org.jetbrains.kotlin.native.interop.indexer.ObjCMethod + ) : StubOrigin() + + class ObjCMethod( + val method: org.jetbrains.kotlin.native.interop.indexer.ObjCMethod, + val container: ObjCContainer + ) : StubOrigin() + + class ObjCProperty( + val property: org.jetbrains.kotlin.native.interop.indexer.ObjCProperty, + val container: ObjCContainer + ) : StubOrigin() + + class ObjCClass( + val clazz: org.jetbrains.kotlin.native.interop.indexer.ObjCClass, + val isMeta: Boolean + ) : StubOrigin() + + class ObjCProtocol( + val protocol: org.jetbrains.kotlin.native.interop.indexer.ObjCProtocol, + val isMeta: Boolean + ) : StubOrigin() + + class Enum(val enum: EnumDef) : StubOrigin() + + class EnumEntry(val constant: EnumConstant) : StubOrigin() + + class Function(val function: FunctionDecl) : StubOrigin() + + class Struct(val struct: StructDecl) : StubOrigin() + + class StructMember( + val member: org.jetbrains.kotlin.native.interop.indexer.StructMember + ) : StubOrigin() + + class Constant(val constantDef: ConstantDef): StubOrigin() + + class Global(val global: GlobalDecl) : StubOrigin() + + class TypeDef(val typedefDef: TypedefDef) : StubOrigin() + + class VarOf(val typeOrigin: StubOrigin) : StubOrigin() +} + +interface StubElementWithOrigin : StubIrElement { + val origin: StubOrigin +} + +interface AnnotationHolder { + val annotations: List +} + +sealed class AnnotationStub(val classifier: Classifier) { + + sealed class ObjC(classifier: Classifier) : AnnotationStub(classifier) { + object ConsumesReceiver : + ObjC(cCallClassifier.nested("ConsumesReceiver")) + + object ReturnsRetained : + ObjC(cCallClassifier.nested("ReturnsRetained")) + + class Method(val selector: String, val encoding: String, val isStret: Boolean = false) : + ObjC(Classifier.topLevel(cinteropPackage, "ObjCMethod")) + + class Factory(val selector: String, val encoding: String, val isStret: Boolean = false) : + ObjC(Classifier.topLevel(cinteropPackage, "ObjCFactory")) + + object Consumed : + ObjC(cCallClassifier.nested("Consumed")) + + class Constructor(val selector: String, val designated: Boolean) : + ObjC(Classifier.topLevel(cinteropPackage, "ObjCConstructor")) + + class ExternalClass(val protocolGetter: String = "", val binaryName: String = "") : + ObjC(Classifier.topLevel(cinteropPackage, "ExternalObjCClass")) + } + + sealed class CCall(classifier: Classifier) : AnnotationStub(classifier) { + object CString : CCall(cCallClassifier.nested("CString")) + object WCString : CCall(cCallClassifier.nested("WCString")) + class Symbol(val symbolName: String) : CCall(cCallClassifier) + } + + class CStruct(val struct: String) : AnnotationStub(cStructClassifier) { + class MemberAt(val offset: Long) : AnnotationStub(cStructClassifier.nested("MemberAt")) + + class ArrayMemberAt(val offset: Long) : AnnotationStub(cStructClassifier.nested("ArrayMemberAt")) + + class BitField(val offset: Long, val size: Int) : AnnotationStub(cStructClassifier.nested("BitField")) + + class VarType(val size: Long, val align: Int) : AnnotationStub(cStructClassifier.nested("VarType")) + } + + class CNaturalStruct(val members: List) : + AnnotationStub(Classifier.topLevel(cinteropPackage, "CNaturalStruct")) + + class CLength(val length: Long) : + AnnotationStub(Classifier.topLevel(cinteropPackage, "CLength")) + + class Deprecated(val message: String, val replaceWith: String, val level: DeprecationLevel) : + AnnotationStub(Classifier.topLevel("kotlin", "Deprecated")) { + companion object { + val unableToImport = Deprecated( + "Unable to import this declaration", + "", + DeprecationLevel.ERROR + ) + + val deprecatedCVariableCompanion = Deprecated( + "Use sizeOf() or alignOf() instead.", + "", + DeprecationLevel.WARNING + ) + + val deprecatedCEnumByValue = Deprecated( + "Will be removed.", + "", + DeprecationLevel.WARNING + ) + } + } + + + class CEnumEntryAlias(val entryName: String) : + AnnotationStub(Classifier.topLevel(cinteropInternalPackage, "CEnumEntryAlias")) + + class CEnumVarTypeSize(val size: Int) : + AnnotationStub(Classifier.topLevel(cinteropInternalPackage, "CEnumVarTypeSize")) + + private companion object { + val cCallClassifier = Classifier.topLevel(cinteropInternalPackage, "CCall") + + val cStructClassifier = Classifier.topLevel(cinteropInternalPackage, "CStruct") + } +} + +/** + * Compile-time known values. + */ +sealed class ConstantStub : ValueStub() +class StringConstantStub(val value: String) : ConstantStub() +data class IntegralConstantStub(val value: Long, val size: Int, val isSigned: Boolean) : ConstantStub() +data class DoubleConstantStub(val value: Double, val size: Int) : ConstantStub() + + +data class PropertyStub( + val name: String, + val type: StubType, + val kind: Kind, + val modality: MemberStubModality = MemberStubModality.FINAL, + val receiverType: StubType? = null, + override val annotations: List = emptyList(), + val origin: StubOrigin, + val isOverride: Boolean = false +) : StubIrElement, AnnotationHolder { + sealed class Kind { + class Val( + val getter: PropertyAccessor.Getter + ) : Kind() + + class Var( + val getter: PropertyAccessor.Getter, + val setter: PropertyAccessor.Setter + ) : Kind() + + class Constant(val constant: ConstantStub) : Kind() + } + + override fun accept(visitor: StubIrVisitor, data: T): R { + return visitor.visitProperty(this, data) + } +} + +enum class ClassStubModality { + INTERFACE, OPEN, ABSTRACT, NONE +} + +enum class VisibilityModifier { + PRIVATE, PROTECTED, INTERNAL, PUBLIC +} + +class GetConstructorParameter( + val constructorParameterStub: FunctionParameterStub +) : ValueStub() + +class SuperClassInit( + val type: StubType, + val arguments: List = listOf() +) + +// TODO: Consider unifying these classes. +sealed class ClassStub : StubContainer(), StubElementWithOrigin, AnnotationHolder { + + abstract val superClassInit: SuperClassInit? + abstract val interfaces: List + abstract val childrenClasses: List + abstract val companion : Companion? + abstract val classifier: Classifier + + class Simple( + override val classifier: Classifier, + val modality: ClassStubModality, + constructors: List = emptyList(), + methods: List = emptyList(), + override val superClassInit: SuperClassInit? = null, + override val interfaces: List = emptyList(), + override val properties: List = emptyList(), + override val origin: StubOrigin, + override val annotations: List = emptyList(), + override val childrenClasses: List = emptyList(), + override val companion: Companion? = null, + override val simpleContainers: List = emptyList() + ) : ClassStub() { + override val functions: List = constructors + methods + } + + class Companion( + override val classifier: Classifier, + methods: List = emptyList(), + override val superClassInit: SuperClassInit? = null, + override val interfaces: List = emptyList(), + override val properties: List = emptyList(), + override val origin: StubOrigin = StubOrigin.Synthetic.CompanionObject, + override val annotations: List = emptyList(), + override val childrenClasses: List = emptyList(), + override val simpleContainers: List = emptyList() + ) : ClassStub() { + override val companion: Companion? = null + + override val functions: List = methods + } + + class Enum( + override val classifier: Classifier, + val entries: List, + constructors: List, + override val superClassInit: SuperClassInit? = null, + override val interfaces: List = emptyList(), + override val properties: List = emptyList(), + override val origin: StubOrigin, + override val annotations: List = emptyList(), + override val childrenClasses: List = emptyList(), + override val companion: Companion?= null, + override val simpleContainers: List = emptyList() + ) : ClassStub() { + override val functions: List = constructors + } + + override val meta: StubContainerMeta = StubContainerMeta() + + override val classes: List + get() = childrenClasses + listOfNotNull(companion) + + override fun accept(visitor: StubIrVisitor, data: T) = + visitor.visitClass(this, data) + + override val typealiases: List = emptyList() +} + +class ReceiverParameterStub( + val type: StubType +) + +class FunctionParameterStub( + val name: String, + val type: StubType, + override val annotations: List = emptyList(), + val isVararg: Boolean = false +) : AnnotationHolder + +enum class MemberStubModality { + OPEN, + FINAL, + ABSTRACT +} + +interface FunctionalStub : AnnotationHolder, StubIrElement, NativeBacked { + val parameters: List +} + +sealed class PropertyAccessor : FunctionalStub { + + sealed class Getter : PropertyAccessor() { + + override val parameters: List = emptyList() + + class SimpleGetter( + override val annotations: List = emptyList(), + val constant: ConstantStub? = null + ) : Getter() + + class GetConstructorParameter( + val constructorParameter: FunctionParameterStub, + override val annotations: List = emptyList() + ) : Getter() + + class ExternalGetter( + override val annotations: List = emptyList() + ) : Getter() + + class ArrayMemberAt( + val offset: Long + ) : Getter() { + override val parameters: List = emptyList() + override val annotations: List = emptyList() + } + + class MemberAt( + val offset: Long, + val typeArguments: List = emptyList(), + val hasValueAccessor: Boolean + ) : Getter() { + override val annotations: List = emptyList() + } + + class ReadBits( + val offset: Long, + val size: Int, + val signed: Boolean + ) : Getter() { + override val annotations: List = emptyList() + } + + class InterpretPointed(val cGlobalName:String, pointedType: StubType) : Getter() { + override val annotations: List = emptyList() + val typeParameters: List = listOf(pointedType) + } + + class GetEnumEntry( + val enumEntryStub: EnumEntryStub, + override val annotations: List = emptyList() + ) : Getter() + } + + sealed class Setter : PropertyAccessor() { + + override val parameters: List = emptyList() + + class SimpleSetter( + override val annotations: List = emptyList() + ) : Setter() + + class ExternalSetter( + override val annotations: List = emptyList() + ) : Setter() + + class MemberAt( + val offset: Long, + override val annotations: List = emptyList(), + val typeArguments: List = emptyList() + ) : Setter() + + class WriteBits( + val offset: Long, + val size: Int, + override val annotations: List = emptyList() + ) : Setter() + } + + override fun accept(visitor: StubIrVisitor, data: T) = + visitor.visitPropertyAccessor(this, data) + +} + +data class FunctionStub( + val name: String, + val returnType: StubType, + override val parameters: List, + override val origin: StubOrigin, + override val annotations: List, + val external: Boolean = false, + val receiver: ReceiverParameterStub?, + val modality: MemberStubModality, + val typeParameters: List = emptyList(), + val isOverride: Boolean = false, + val hasStableParameterNames: Boolean = true +) : StubElementWithOrigin, FunctionalStub { + + override fun accept(visitor: StubIrVisitor, data: T) = + visitor.visitFunction(this, data) +} + +// TODO: should we support non-trivial constructors? +class ConstructorStub( + override val parameters: List = emptyList(), + override val annotations: List = emptyList(), + val isPrimary: Boolean, + val visibility: VisibilityModifier = VisibilityModifier.PUBLIC, + val origin: StubOrigin +) : FunctionalStub { + + override fun accept(visitor: StubIrVisitor, data: T) = + visitor.visitConstructor(this, data) +} + +class EnumEntryStub( + val name: String, + val constant: IntegralConstantStub, + val origin: StubOrigin.EnumEntry, + val ordinal: Int +) + +class TypealiasStub( + val alias: Classifier, + val aliasee: StubType, + val origin: StubOrigin +) : StubIrElement { + + override fun accept(visitor: StubIrVisitor, data: T) = + visitor.visitTypealias(this, data) +} \ No newline at end of file diff --git a/kotlin-native/Interop/StubGenerator/src/main/kotlin/org/jetbrains/kotlin/native/interop/gen/StubIrBridgeBuilder.kt b/kotlin-native/Interop/StubGenerator/src/main/kotlin/org/jetbrains/kotlin/native/interop/gen/StubIrBridgeBuilder.kt new file mode 100644 index 00000000000..e30ad7ad7a1 --- /dev/null +++ b/kotlin-native/Interop/StubGenerator/src/main/kotlin/org/jetbrains/kotlin/native/interop/gen/StubIrBridgeBuilder.kt @@ -0,0 +1,319 @@ +/* + * Copyright 2010-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ +package org.jetbrains.kotlin.native.interop.gen + +import org.jetbrains.kotlin.native.interop.gen.jvm.KotlinPlatform +import org.jetbrains.kotlin.native.interop.indexer.* +import org.jetbrains.kotlin.utils.addToStdlib.firstIsInstanceOrNull + +class BridgeBuilderResult( + val kotlinFile: KotlinFile, + val nativeBridges: NativeBridges, + val propertyAccessorBridgeBodies: Map, + val functionBridgeBodies: Map>, + val excludedStubs: Set +) + +/** + * Generates [NativeBridges] and corresponding function bodies and property accessors. + */ +class StubIrBridgeBuilder( + private val context: StubIrContext, + private val builderResult: StubIrBuilderResult) { + + private val globalAddressExpressions = mutableMapOf, KotlinExpression>() + + private val wrapperGenerator = CWrappersGenerator(context) + + private fun getGlobalAddressExpression(cGlobalName: String, accessor: PropertyAccessor) = + globalAddressExpressions.getOrPut(Pair(cGlobalName, accessor)) { + simpleBridgeGenerator.kotlinToNative( + nativeBacked = accessor, + returnType = BridgedType.NATIVE_PTR, + kotlinValues = emptyList(), + independent = false + ) { + "&$cGlobalName" + } + } + + private val declarationMapper = builderResult.declarationMapper + + private val kotlinFile = object : KotlinFile( + context.configuration.pkgName, + namesToBeDeclared = builderResult.stubs.computeNamesToBeDeclared(context.configuration.pkgName) + ) { + override val mappingBridgeGenerator: MappingBridgeGenerator + get() = this@StubIrBridgeBuilder.mappingBridgeGenerator + } + + private val simpleBridgeGenerator: SimpleBridgeGenerator = + SimpleBridgeGeneratorImpl( + context.platform, + context.configuration.pkgName, + context.jvmFileClassName, + context.libraryForCStubs, + topLevelNativeScope = object : NativeScope { + override val mappingBridgeGenerator: MappingBridgeGenerator + get() = this@StubIrBridgeBuilder.mappingBridgeGenerator + }, + topLevelKotlinScope = kotlinFile + ) + + private val mappingBridgeGenerator: MappingBridgeGenerator = + MappingBridgeGeneratorImpl(declarationMapper, simpleBridgeGenerator) + + private val propertyAccessorBridgeBodies = mutableMapOf() + private val functionBridgeBodies = mutableMapOf>() + private val excludedStubs = mutableSetOf() + + private val bridgeGeneratingVisitor = object : StubIrVisitor { + + override fun visitClass(element: ClassStub, data: StubContainer?) { + element.annotations.filterIsInstance().firstOrNull()?.let { + val origin = element.origin + if (it.protocolGetter.isNotEmpty() && origin is StubOrigin.ObjCProtocol && !origin.isMeta) { + val protocol = (element.origin as StubOrigin.ObjCProtocol).protocol + // TODO: handle the case when protocol getter stub can't be compiled. + generateProtocolGetter(it.protocolGetter, protocol) + } + } + element.children.forEach { + it.accept(this, element) + } + } + + override fun visitTypealias(element: TypealiasStub, data: StubContainer?) { + } + + override fun visitFunction(element: FunctionStub, data: StubContainer?) { + try { + when { + element.external -> tryProcessCCallAnnotation(element) + element.isOptionalObjCMethod() -> { } + element.origin is StubOrigin.Synthetic.EnumByValue -> { } + data != null && data.isInterface -> { } + else -> generateBridgeBody(element) + } + } catch (e: Throwable) { + context.log("Warning: cannot generate bridge for ${element.name}.") + excludedStubs += element + } + } + + private fun tryProcessCCallAnnotation(function: FunctionStub) { + val origin = function.origin as? StubOrigin.Function + ?: return + val cCallAnnotation = function.annotations.firstIsInstanceOrNull() + ?: return + val wrapper = wrapperGenerator.generateCCalleeWrapper(origin.function, cCallAnnotation.symbolName) + simpleBridgeGenerator.insertNativeBridge(function, emptyList(), wrapper.lines) + } + + override fun visitProperty(element: PropertyStub, data: StubContainer?) { + try { + when (val kind = element.kind) { + is PropertyStub.Kind.Constant -> { + } + is PropertyStub.Kind.Val -> { + visitPropertyAccessor(kind.getter, data) + } + is PropertyStub.Kind.Var -> { + visitPropertyAccessor(kind.getter, data) + visitPropertyAccessor(kind.setter, data) + } + } + } catch (e: Throwable) { + context.log("Warning: cannot generate bridge for ${element.name}.") + excludedStubs += element + } + } + + override fun visitConstructor(constructorStub: ConstructorStub, data: StubContainer?) { + } + + override fun visitPropertyAccessor(propertyAccessor: PropertyAccessor, data: StubContainer?) { + when (propertyAccessor) { + is PropertyAccessor.Getter.SimpleGetter -> { + when (propertyAccessor) { + in builderResult.bridgeGenerationComponents.getterToBridgeInfo -> { + val extra = builderResult.bridgeGenerationComponents.getterToBridgeInfo.getValue(propertyAccessor) + val typeInfo = extra.typeInfo + propertyAccessorBridgeBodies[propertyAccessor] = typeInfo.argFromBridged(simpleBridgeGenerator.kotlinToNative( + nativeBacked = propertyAccessor, + returnType = typeInfo.bridgedType, + kotlinValues = emptyList(), + independent = false + ) { + typeInfo.cToBridged(expr = extra.cGlobalName) + }, kotlinFile, nativeBacked = propertyAccessor) + } + in builderResult.bridgeGenerationComponents.arrayGetterInfo -> { + val extra = builderResult.bridgeGenerationComponents.arrayGetterInfo.getValue(propertyAccessor) + val typeInfo = extra.typeInfo + val getAddressExpression = getGlobalAddressExpression(extra.cGlobalName, propertyAccessor) + propertyAccessorBridgeBodies[propertyAccessor] = typeInfo.argFromBridged(getAddressExpression, kotlinFile, nativeBacked = propertyAccessor) + "!!" + } + } + } + + is PropertyAccessor.Getter.ReadBits -> { + val extra = builderResult.bridgeGenerationComponents.getterToBridgeInfo.getValue(propertyAccessor) + val rawType = extra.typeInfo.bridgedType + val readBits = "readBits(this.rawPtr, ${propertyAccessor.offset}, ${propertyAccessor.size}, ${propertyAccessor.signed}).${rawType.convertor!!}()" + val getExpr = extra.typeInfo.argFromBridged(readBits, kotlinFile, object : NativeBacked {}) + propertyAccessorBridgeBodies[propertyAccessor] = getExpr + } + + is PropertyAccessor.Setter.SimpleSetter -> when (propertyAccessor) { + in builderResult.bridgeGenerationComponents.setterToBridgeInfo -> { + val extra = builderResult.bridgeGenerationComponents.setterToBridgeInfo.getValue(propertyAccessor) + val typeInfo = extra.typeInfo + val bridgedValue = BridgeTypedKotlinValue(typeInfo.bridgedType, typeInfo.argToBridged("value")) + val setter = simpleBridgeGenerator.kotlinToNative( + nativeBacked = propertyAccessor, + returnType = BridgedType.VOID, + kotlinValues = listOf(bridgedValue), + independent = false + ) { nativeValues -> + out("${extra.cGlobalName} = ${typeInfo.cFromBridged( + nativeValues.single(), + scope, + nativeBacked = propertyAccessor + )};") + "" + } + propertyAccessorBridgeBodies[propertyAccessor] = setter + } + } + + is PropertyAccessor.Setter.WriteBits -> { + val extra = builderResult.bridgeGenerationComponents.setterToBridgeInfo.getValue(propertyAccessor) + val rawValue = extra.typeInfo.argToBridged("value") + propertyAccessorBridgeBodies[propertyAccessor] = "writeBits(this.rawPtr, ${propertyAccessor.offset}, ${propertyAccessor.size}, $rawValue.toLong())" + } + + is PropertyAccessor.Getter.InterpretPointed -> { + val getAddressExpression = getGlobalAddressExpression(propertyAccessor.cGlobalName, propertyAccessor) + propertyAccessorBridgeBodies[propertyAccessor] = getAddressExpression + } + + is PropertyAccessor.Getter.ExternalGetter -> { + if (propertyAccessor in builderResult.wrapperGenerationComponents.getterToWrapperInfo) { + val extra = builderResult.wrapperGenerationComponents.getterToWrapperInfo.getValue(propertyAccessor) + val cCallAnnotation = propertyAccessor.annotations.firstIsInstanceOrNull() + ?: error("external getter for ${extra.global.name} wasn't marked with @CCall") + val wrapper = if (extra.passViaPointer) { + wrapperGenerator.generateCGlobalByPointerGetter(extra.global, cCallAnnotation.symbolName) + } else { + wrapperGenerator.generateCGlobalGetter(extra.global, cCallAnnotation.symbolName) + } + simpleBridgeGenerator.insertNativeBridge(propertyAccessor, emptyList(), wrapper.lines) + } + } + + is PropertyAccessor.Setter.ExternalSetter -> { + if (propertyAccessor in builderResult.wrapperGenerationComponents.setterToWrapperInfo) { + val extra = builderResult.wrapperGenerationComponents.setterToWrapperInfo.getValue(propertyAccessor) + val cCallAnnotation = propertyAccessor.annotations.firstIsInstanceOrNull() + ?: error("external setter for ${extra.global.name} wasn't marked with @CCall") + val wrapper = wrapperGenerator.generateCGlobalSetter(extra.global, cCallAnnotation.symbolName) + simpleBridgeGenerator.insertNativeBridge(propertyAccessor, emptyList(), wrapper.lines) + } + } + } + } + + override fun visitSimpleStubContainer(simpleStubContainer: SimpleStubContainer, data: StubContainer?) { + simpleStubContainer.classes.forEach { + it.accept(this, simpleStubContainer) + } + simpleStubContainer.functions.forEach { + it.accept(this, simpleStubContainer) + } + simpleStubContainer.properties.forEach { + it.accept(this, simpleStubContainer) + } + simpleStubContainer.typealiases.forEach { + it.accept(this, simpleStubContainer) + } + simpleStubContainer.simpleContainers.forEach { + it.accept(this, simpleStubContainer) + } + } + } + + private fun isCValuesRef(type: StubType): Boolean = + (type as? ClassifierStubType)?.let { it.classifier == KotlinTypes.cValuesRef } + ?: false + + private fun generateBridgeBody(function: FunctionStub) { + assert(context.platform == KotlinPlatform.JVM) { "Function ${function.name} was not marked as external." } + assert(function.origin is StubOrigin.Function) { "Can't create bridge for ${function.name}" } + val origin = function.origin as StubOrigin.Function + val bodyGenerator = KotlinCodeBuilder(scope = kotlinFile) + val bridgeArguments = mutableListOf() + var isVararg = false + function.parameters.forEachIndexed { index, parameter -> + isVararg = isVararg or parameter.isVararg + val parameterName = parameter.name.asSimpleName() + val bridgeArgument = when { + parameter in builderResult.bridgeGenerationComponents.cStringParameters -> { + bodyGenerator.pushMemScoped() + "$parameterName?.cstr?.getPointer(memScope)" + } + parameter in builderResult.bridgeGenerationComponents.wCStringParameters -> { + bodyGenerator.pushMemScoped() + "$parameterName?.wcstr?.getPointer(memScope)" + } + isCValuesRef(parameter.type) -> { + bodyGenerator.pushMemScoped() + bodyGenerator.getNativePointer(parameterName) + } + else -> { + parameterName + } + } + bridgeArguments += TypedKotlinValue(origin.function.parameters[index].type, bridgeArgument) + } + // TODO: Improve assertion message. + assert(!isVararg || context.platform != KotlinPlatform.NATIVE) { + "Function ${function.name} was processed incorrectly." + } + val result = mappingBridgeGenerator.kotlinToNative( + bodyGenerator, + function, + origin.function.returnType, + bridgeArguments, + independent = false + ) { nativeValues -> + "${origin.function.name}(${nativeValues.joinToString()})" + } + bodyGenerator.returnResult(result) + functionBridgeBodies[function] = bodyGenerator.build() + } + + private fun generateProtocolGetter(protocolGetterName: String, protocol: ObjCProtocol) { + val builder = NativeCodeBuilder(simpleBridgeGenerator.topLevelNativeScope) + val nativeBacked = object : NativeBacked {} + with(builder) { + out("Protocol* $protocolGetterName() {") + out(" return @protocol(${protocol.name});") + out("}") + } + simpleBridgeGenerator.insertNativeBridge(nativeBacked, emptyList(), builder.lines) + } + + fun build(): BridgeBuilderResult { + bridgeGeneratingVisitor.visitSimpleStubContainer(builderResult.stubs, null) + return BridgeBuilderResult( + kotlinFile, + simpleBridgeGenerator.prepare(), + propertyAccessorBridgeBodies.toMap(), + functionBridgeBodies.toMap(), + excludedStubs.toSet() + ) + } +} diff --git a/kotlin-native/Interop/StubGenerator/src/main/kotlin/org/jetbrains/kotlin/native/interop/gen/StubIrBuilder.kt b/kotlin-native/Interop/StubGenerator/src/main/kotlin/org/jetbrains/kotlin/native/interop/gen/StubIrBuilder.kt new file mode 100644 index 00000000000..f8c6a29d40c --- /dev/null +++ b/kotlin-native/Interop/StubGenerator/src/main/kotlin/org/jetbrains/kotlin/native/interop/gen/StubIrBuilder.kt @@ -0,0 +1,407 @@ +/* + * Copyright 2010-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ +package org.jetbrains.kotlin.native.interop.gen + +import org.jetbrains.kotlin.native.interop.gen.jvm.GenerationMode +import org.jetbrains.kotlin.native.interop.gen.jvm.InteropConfiguration +import org.jetbrains.kotlin.native.interop.gen.jvm.KotlinPlatform +import org.jetbrains.kotlin.native.interop.indexer.* + +/** + * Components that are not passed via StubIr but required for bridge generation. + */ +class BridgeGenerationInfo(val cGlobalName: String, val typeInfo: TypeInfo) + +/** + * Additional components that are required to generate bridges. + * TODO: Metadata-based interop should not depend on these components. + */ +interface BridgeGenerationComponents { + + val setterToBridgeInfo: Map + + val getterToBridgeInfo: Map + + val arrayGetterInfo: Map + + val enumToTypeMirror: Map + + val wCStringParameters: Set + + val cStringParameters: Set +} + +class BridgeGenerationComponentsBuilder { + + val getterToBridgeInfo = mutableMapOf() + val setterToBridgeInfo = mutableMapOf() + val arrayGetterBridgeInfo = mutableMapOf() + val enumToTypeMirror = mutableMapOf() + val wCStringParameters = mutableSetOf() + val cStringParameters = mutableSetOf() + + fun build(): BridgeGenerationComponents = object : BridgeGenerationComponents { + override val getterToBridgeInfo = + this@BridgeGenerationComponentsBuilder.getterToBridgeInfo.toMap() + + override val setterToBridgeInfo = + this@BridgeGenerationComponentsBuilder.setterToBridgeInfo.toMap() + + override val enumToTypeMirror = + this@BridgeGenerationComponentsBuilder.enumToTypeMirror.toMap() + + override val wCStringParameters: Set = + this@BridgeGenerationComponentsBuilder.wCStringParameters.toSet() + + override val cStringParameters: Set = + this@BridgeGenerationComponentsBuilder.cStringParameters.toSet() + + override val arrayGetterInfo: Map = + this@BridgeGenerationComponentsBuilder.arrayGetterBridgeInfo.toMap() + } +} + +/** + * Components that are not passed via StubIr but required for generation of wrappers. + */ +class WrapperGenerationInfo(val global: GlobalDecl, val passViaPointer: Boolean = false) + +interface WrapperGenerationComponents { + val getterToWrapperInfo: Map + val setterToWrapperInfo: Map +} + +class WrapperGenerationComponentsBuilder { + + val getterToWrapperInfo = mutableMapOf() + val setterToWrapperInfo = mutableMapOf() + + fun build(): WrapperGenerationComponents = object : WrapperGenerationComponents { + override val getterToWrapperInfo = this@WrapperGenerationComponentsBuilder.getterToWrapperInfo.toMap() + + override val setterToWrapperInfo = this@WrapperGenerationComponentsBuilder.setterToWrapperInfo.toMap() + } +} + +/** + * Common part of all [StubIrBuilder] implementations. + */ +interface StubsBuildingContext { + val configuration: InteropConfiguration + + fun mirror(type: Type): TypeMirror + + val declarationMapper: DeclarationMapper + + fun generateNextUniqueId(prefix: String): String + + val generatedObjCCategoriesMembers: MutableMap + + val platform: KotlinPlatform + + /** + * In some cases StubIr should be different for metadata and sourcecode modes. + * For example, it is impossible to represent call to superclass constructor in + * metadata directly and arguments should be passed via annotations instead. + */ + val generationMode: GenerationMode + + fun isStrictEnum(enumDef: EnumDef): Boolean + + val macroConstantsByName: Map + + fun tryCreateIntegralStub(type: Type, value: Long): IntegralConstantStub? + + fun tryCreateDoubleStub(type: Type, value: Double): DoubleConstantStub? + + val bridgeComponentsBuilder: BridgeGenerationComponentsBuilder + + val wrapperComponentsBuilder: WrapperGenerationComponentsBuilder + + fun getKotlinClassFor(objCClassOrProtocol: ObjCClassOrProtocol, isMeta: Boolean = false): Classifier + + fun getKotlinClassForPointed(structDecl: StructDecl): Classifier + + fun isOverloading(func: FunctionDecl): Boolean +} + +/** + * + */ +internal interface StubElementBuilder { + val context: StubsBuildingContext + + fun build(): List +} + +class StubsBuildingContextImpl( + private val stubIrContext: StubIrContext +) : StubsBuildingContext { + + override val configuration: InteropConfiguration = stubIrContext.configuration + override val platform: KotlinPlatform = stubIrContext.platform + override val generationMode: GenerationMode = stubIrContext.generationMode + val imports: Imports = stubIrContext.imports + private val nativeIndex: NativeIndex = stubIrContext.nativeIndex + + private var theCounter = 0 + + private val uniqFunctions = mutableSetOf() + override fun isOverloading(func: FunctionDecl) = !uniqFunctions.add(func.name) // TODO: params & return type. + + override fun generateNextUniqueId(prefix: String) = + prefix + pkgName.replace('.', '_') + theCounter++ + + override fun mirror(type: Type): TypeMirror = mirror(declarationMapper, type) + + /** + * Indicates whether this enum should be represented as Kotlin enum. + */ + + override fun isStrictEnum(enumDef: EnumDef): Boolean = with(enumDef) { + if (this.isAnonymous) { + return false + } + + val name = this.kotlinName + + if (name in configuration.strictEnums) { + return true + } + + if (name in configuration.nonStrictEnums) { + return false + } + + // Let the simple heuristic decide: + return !this.constants.any { it.isExplicitlyDefined } + } + + override val generatedObjCCategoriesMembers = mutableMapOf() + + override val declarationMapper = object : DeclarationMapper { + override fun getKotlinClassForPointed(structDecl: StructDecl): Classifier { + val baseName = structDecl.kotlinName + val pkg = when (platform) { + KotlinPlatform.JVM -> pkgName + KotlinPlatform.NATIVE -> if (structDecl.def == null) { + cnamesStructsPackageName // to be imported as forward declaration. + } else { + getPackageFor(structDecl) + } + } + return Classifier.topLevel(pkg, baseName) + } + + override fun isMappedToStrict(enumDef: EnumDef): Boolean = isStrictEnum(enumDef) + + override fun getKotlinNameForValue(enumDef: EnumDef): String = enumDef.kotlinName + + override fun getPackageFor(declaration: TypeDeclaration): String { + return imports.getPackage(declaration.location) ?: pkgName + } + + override val useUnsignedTypes: Boolean + get() = when (platform) { + KotlinPlatform.JVM -> false + KotlinPlatform.NATIVE -> true + } + } + + override val macroConstantsByName: Map = + (nativeIndex.macroConstants + nativeIndex.wrappedMacros).associateBy { it.name } + + /** + * The name to be used for this enum in Kotlin + */ + val EnumDef.kotlinName: String + get() = if (spelling.startsWith("enum ")) { + spelling.substringAfter(' ') + } else { + assert (!isAnonymous) + spelling + } + + + private val pkgName: String + get() = configuration.pkgName + + /** + * The name to be used for this struct in Kotlin + */ + val StructDecl.kotlinName: String + get() = stubIrContext.getKotlinName(this) + + override fun tryCreateIntegralStub(type: Type, value: Long): IntegralConstantStub? { + val integerType = when (val unwrappedType = type.unwrapTypedefs()) { + is IntegerType -> unwrappedType + CharType -> IntegerType(1, true, "char") + else -> return null + } + val size = integerType.size + if (size != 1 && size != 2 && size != 4 && size != 8) return null + return IntegralConstantStub(value, size, declarationMapper.isMappedToSigned(integerType)) + } + + override fun tryCreateDoubleStub(type: Type, value: Double): DoubleConstantStub? { + val unwrappedType = type.unwrapTypedefs() as? FloatingType ?: return null + val size = unwrappedType.size + if (size != 4 && size != 8) return null + return DoubleConstantStub(value, size) + } + + override val bridgeComponentsBuilder = BridgeGenerationComponentsBuilder() + + override val wrapperComponentsBuilder = WrapperGenerationComponentsBuilder() + + override fun getKotlinClassFor(objCClassOrProtocol: ObjCClassOrProtocol, isMeta: Boolean): Classifier { + return declarationMapper.getKotlinClassFor(objCClassOrProtocol, isMeta) + } + + override fun getKotlinClassForPointed(structDecl: StructDecl): Classifier { + val classifier = declarationMapper.getKotlinClassForPointed(structDecl) + return classifier + } +} + +data class StubIrBuilderResult( + val stubs: SimpleStubContainer, + val declarationMapper: DeclarationMapper, + val bridgeGenerationComponents: BridgeGenerationComponents, + val wrapperGenerationComponents: WrapperGenerationComponents +) + +/** + * Produces [StubIrBuilderResult] for given [KotlinPlatform] using [InteropConfiguration]. + */ +class StubIrBuilder(private val context: StubIrContext) { + + private val configuration = context.configuration + private val nativeIndex: NativeIndex = context.nativeIndex + + private val classes = mutableListOf() + private val functions = mutableListOf() + private val globals = mutableListOf() + private val typealiases = mutableListOf() + private val containers = mutableListOf() + + private fun addStubs(stubs: List) = stubs.forEach(this::addStub) + + private fun addStub(stub: StubIrElement) { + when(stub) { + is ClassStub -> classes += stub + is FunctionStub -> functions += stub + is PropertyStub -> globals += stub + is TypealiasStub -> typealiases += stub + is SimpleStubContainer -> containers += stub + else -> error("Unexpected stub: $stub") + } + } + + private val excludedFunctions: Set + get() = configuration.excludedFunctions + + private val excludedMacros: Set + get() = configuration.excludedMacros + + private val buildingContext = StubsBuildingContextImpl(context) + + fun build(): StubIrBuilderResult { + nativeIndex.objCProtocols.filter { !it.isForwardDeclaration }.forEach { generateStubsForObjCProtocol(it) } + nativeIndex.objCClasses.filter { !it.isForwardDeclaration && !it.isNSStringSubclass()} .forEach { generateStubsForObjCClass(it) } + nativeIndex.objCCategories.filter { !it.clazz.isNSStringSubclass() }.forEach { generateStubsForObjCCategory(it) } + nativeIndex.structs.forEach { generateStubsForStruct(it) } + nativeIndex.enums.forEach { generateStubsForEnum(it) } + nativeIndex.functions.filter { it.name !in excludedFunctions }.forEach { generateStubsForFunction(it) } + nativeIndex.typedefs.forEach { generateStubsForTypedef(it) } + nativeIndex.globals.filter { it.name !in excludedFunctions }.forEach { generateStubsForGlobal(it) } + nativeIndex.macroConstants.filter { it.name !in excludedMacros }.forEach { generateStubsForMacroConstant(it) } + nativeIndex.wrappedMacros.filter { it.name !in excludedMacros }.forEach { generateStubsForWrappedMacro(it) } + + val meta = StubContainerMeta() + val stubs = SimpleStubContainer( + meta, + classes.toList(), + functions.toList(), + globals.toList(), + typealiases.toList(), + containers.toList() + ) + return StubIrBuilderResult( + stubs, + buildingContext.declarationMapper, + buildingContext.bridgeComponentsBuilder.build(), + buildingContext.wrapperComponentsBuilder.build() + ) + } + + private fun generateStubsForWrappedMacro(macro: WrappedMacroDef) { + try { + generateStubsForGlobal(GlobalDecl(macro.name, macro.type, isConst = true)) + } catch (e: Throwable) { + context.log("Warning: cannot generate stubs for macro ${macro.name}") + } + } + + private fun generateStubsForMacroConstant(constant: ConstantDef) { + try { + addStubs(MacroConstantStubBuilder(buildingContext, constant).build()) + } catch (e: Throwable) { + context.log("Warning: cannot generate stubs for constant ${constant.name}") + } + } + + private fun generateStubsForEnum(enumDef: EnumDef) { + try { + addStubs(EnumStubBuilder(buildingContext, enumDef).build()) + } catch (e: Throwable) { + context.log("Warning: cannot generate definition for enum ${enumDef.spelling}") + } + } + + private fun generateStubsForFunction(func: FunctionDecl) { + try { + addStubs(FunctionStubBuilder(buildingContext, func, skipOverloads = true).build()) + } catch (e: Throwable) { + context.log("Warning: cannot generate stubs for function ${func.name}") + } + } + + private fun generateStubsForStruct(decl: StructDecl) { + try { + addStubs(StructStubBuilder(buildingContext, decl).build()) + } catch (e: Throwable) { + context.log("Warning: cannot generate definition for struct ${decl.spelling}") + } + } + + private fun generateStubsForTypedef(typedefDef: TypedefDef) { + try { + addStubs(TypedefStubBuilder(buildingContext, typedefDef).build()) + } catch (e: Throwable) { + context.log("Warning: cannot generate typedef ${typedefDef.name}") + } + } + + private fun generateStubsForGlobal(global: GlobalDecl) { + try { + addStubs(GlobalStubBuilder(buildingContext, global).build()) + } catch (e: Throwable) { + context.log("Warning: cannot generate stubs for global ${global.name}") + } + } + + private fun generateStubsForObjCProtocol(objCProtocol: ObjCProtocol) { + addStubs(ObjCProtocolStubBuilder(buildingContext, objCProtocol).build()) + } + + private fun generateStubsForObjCClass(objCClass: ObjCClass) { + addStubs(ObjCClassStubBuilder(buildingContext, objCClass).build()) + } + + private fun generateStubsForObjCCategory(objCCategory: ObjCCategory) { + addStubs(ObjCCategoryStubBuilder(buildingContext, objCCategory).build()) + } +} diff --git a/kotlin-native/Interop/StubGenerator/src/main/kotlin/org/jetbrains/kotlin/native/interop/gen/StubIrDriver.kt b/kotlin-native/Interop/StubGenerator/src/main/kotlin/org/jetbrains/kotlin/native/interop/gen/StubIrDriver.kt new file mode 100644 index 00000000000..4b30749529c --- /dev/null +++ b/kotlin-native/Interop/StubGenerator/src/main/kotlin/org/jetbrains/kotlin/native/interop/gen/StubIrDriver.kt @@ -0,0 +1,171 @@ +/* + * Copyright 2010-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ +package org.jetbrains.kotlin.native.interop.gen + +import kotlinx.metadata.klib.KlibModuleMetadata +import org.jetbrains.kotlin.native.interop.gen.jvm.GenerationMode +import org.jetbrains.kotlin.native.interop.gen.jvm.InteropConfiguration +import org.jetbrains.kotlin.native.interop.gen.jvm.KotlinPlatform +import org.jetbrains.kotlin.native.interop.indexer.* +import java.io.File +import java.util.* + +class StubIrContext( + val log: (String) -> Unit, + val configuration: InteropConfiguration, + val nativeIndex: NativeIndex, + val imports: Imports, + val platform: KotlinPlatform, + val generationMode: GenerationMode, + val libName: String +) { + val libraryForCStubs = configuration.library.copy( + includes = mutableListOf().apply { + add("stdint.h") + add("string.h") + if (platform == KotlinPlatform.JVM) { + add("jni.h") + } + addAll(configuration.library.includes) + }, + compilerArgs = configuration.library.compilerArgs, + additionalPreambleLines = configuration.library.additionalPreambleLines + + when (configuration.library.language) { + Language.C -> emptyList() + Language.OBJECTIVE_C -> listOf("void objc_terminate();") + } + ).precompileHeaders() + + // TODO: Used only for JVM. + val jvmFileClassName = if (configuration.pkgName.isEmpty()) { + libName + } else { + configuration.pkgName.substringAfterLast('.') + } + + val validPackageName = configuration.pkgName.split(".").joinToString(".") { + if (it.matches(VALID_PACKAGE_NAME_REGEX)) it else "`$it`" + } + + private val anonymousStructKotlinNames = mutableMapOf() + + private val forbiddenStructNames = run { + val typedefNames = nativeIndex.typedefs.map { it.name } + typedefNames.toSet() + } + + /** + * The name to be used for this struct in Kotlin + */ + fun getKotlinName(decl: StructDecl): String { + val spelling = decl.spelling + if (decl.isAnonymous) { + val names = anonymousStructKotlinNames + return names.getOrPut(decl) { + "anonymousStruct${names.size + 1}" + } + } + + val strippedCName = if (spelling.startsWith("struct ") || spelling.startsWith("union ")) { + spelling.substringAfter(' ') + } else { + spelling + } + + // TODO: don't mangle struct names because it wouldn't work if the struct + // is imported into another interop library. + return if (strippedCName !in forbiddenStructNames) strippedCName else (strippedCName + "Struct") + } + + fun addManifestProperties(properties: Properties) { + val exportForwardDeclarations = configuration.exportForwardDeclarations.toMutableList() + + nativeIndex.structs + .filter { it.def == null } + .mapTo(exportForwardDeclarations) { + "$cnamesStructsPackageName.${getKotlinName(it)}" + } + + properties["exportForwardDeclarations"] = exportForwardDeclarations.joinToString(" ") + + // TODO: consider exporting Objective-C class and protocol forward refs. + } + + companion object { + private val VALID_PACKAGE_NAME_REGEX = "[a-zA-Z0-9_.]+".toRegex() + } +} + +class StubIrDriver( + private val context: StubIrContext, + private val options: DriverOptions +) { + data class DriverOptions( + val entryPoint: String?, + val moduleName: String, + val outCFile: File, + val outKtFileCreator: () -> File + ) + + sealed class Result { + object SourceCode : Result() + + class Metadata(val metadata: KlibModuleMetadata): Result() + } + + fun run(): Result { + val (entryPoint, moduleName, outCFile, outKtFile) = options + + val builderResult = StubIrBuilder(context).build() + val bridgeBuilderResult = StubIrBridgeBuilder(context, builderResult).build() + + outCFile.bufferedWriter().use { + emitCFile(context, it, entryPoint, bridgeBuilderResult.nativeBridges) + } + + return when (context.generationMode) { + GenerationMode.SOURCE_CODE -> { + emitSourceCode(outKtFile(), builderResult, bridgeBuilderResult) + } + GenerationMode.METADATA -> emitMetadata(builderResult, moduleName, bridgeBuilderResult) + } + } + + private fun emitSourceCode( + outKtFile: File, builderResult: StubIrBuilderResult, bridgeBuilderResult: BridgeBuilderResult + ): Result.SourceCode { + outKtFile.bufferedWriter().use { ktFile -> + StubIrTextEmitter(context, builderResult, bridgeBuilderResult).emit(ktFile) + } + return Result.SourceCode + } + + private fun emitMetadata( + builderResult: StubIrBuilderResult, moduleName: String, bridgeBuilderResult: BridgeBuilderResult + ) = Result.Metadata(StubIrMetadataEmitter(context, builderResult, moduleName, bridgeBuilderResult).emit()) + + private fun emitCFile(context: StubIrContext, cFile: Appendable, entryPoint: String?, nativeBridges: NativeBridges) { + val out = { it: String -> cFile.appendLine(it) } + + context.libraryForCStubs.preambleLines.forEach { + out(it) + } + out("") + + out("// NOTE THIS FILE IS AUTO-GENERATED") + out("") + + nativeBridges.nativeLines.forEach { out(it) } + + if (entryPoint != null) { + out("extern int Konan_main(int argc, char** argv);") + out("") + out("__attribute__((__used__))") + out("int $entryPoint(int argc, char** argv) {") + out(" return Konan_main(argc, argv);") + out("}") + } + } +} \ No newline at end of file diff --git a/kotlin-native/Interop/StubGenerator/src/main/kotlin/org/jetbrains/kotlin/native/interop/gen/StubIrElementBuilders.kt b/kotlin-native/Interop/StubGenerator/src/main/kotlin/org/jetbrains/kotlin/native/interop/gen/StubIrElementBuilders.kt new file mode 100644 index 00000000000..9bba73f3e3e --- /dev/null +++ b/kotlin-native/Interop/StubGenerator/src/main/kotlin/org/jetbrains/kotlin/native/interop/gen/StubIrElementBuilders.kt @@ -0,0 +1,727 @@ +/* + * Copyright 2010-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ +package org.jetbrains.kotlin.native.interop.gen + +import org.jetbrains.kotlin.native.interop.gen.jvm.GenerationMode +import org.jetbrains.kotlin.native.interop.gen.jvm.KotlinPlatform +import org.jetbrains.kotlin.native.interop.indexer.* + +internal class MacroConstantStubBuilder( + override val context: StubsBuildingContext, + private val constant: ConstantDef +) : StubElementBuilder { + override fun build(): List { + val kotlinName = constant.name + val origin = StubOrigin.Constant(constant) + val declaration = when (constant) { + is IntegerConstantDef -> { + val literal = context.tryCreateIntegralStub(constant.type, constant.value) ?: return emptyList() + val kotlinType = context.mirror(constant.type).argType.toStubIrType() + when (context.platform) { + KotlinPlatform.NATIVE -> PropertyStub(kotlinName, kotlinType, PropertyStub.Kind.Constant(literal), origin = origin) + // No reason to make it const val with backing field on Kotlin/JVM yet: + KotlinPlatform.JVM -> { + val getter = PropertyAccessor.Getter.SimpleGetter(constant = literal) + PropertyStub(kotlinName, kotlinType, PropertyStub.Kind.Val(getter), origin = origin) + } + } + } + is FloatingConstantDef -> { + val literal = context.tryCreateDoubleStub(constant.type, constant.value) ?: return emptyList() + val kind = when (context.generationMode) { + GenerationMode.SOURCE_CODE -> { + PropertyStub.Kind.Val(PropertyAccessor.Getter.SimpleGetter(constant = literal)) + } + GenerationMode.METADATA -> { + PropertyStub.Kind.Constant(literal) + } + } + val kotlinType = context.mirror(constant.type).argType.toStubIrType() + PropertyStub(kotlinName, kotlinType, kind, origin = origin) + } + is StringConstantDef -> { + val literal = StringConstantStub(constant.value) + val kind = when (context.generationMode) { + GenerationMode.SOURCE_CODE -> { + PropertyStub.Kind.Val(PropertyAccessor.Getter.SimpleGetter(constant = literal)) + } + GenerationMode.METADATA -> { + PropertyStub.Kind.Constant(literal) + } + } + PropertyStub(kotlinName, KotlinTypes.string.toStubIrType(), kind, origin = origin) + } + else -> return emptyList() + } + return listOf(declaration) + } +} + +internal class StructStubBuilder( + override val context: StubsBuildingContext, + private val decl: StructDecl +) : StubElementBuilder { + override fun build(): List { + val platform = context.platform + val def = decl.def ?: return generateForwardStruct(decl) + + val structAnnotation: AnnotationStub? = if (platform == KotlinPlatform.JVM) { + if (def.kind == StructDef.Kind.STRUCT && def.fieldsHaveDefaultAlignment()) { + AnnotationStub.CNaturalStruct(def.members) + } else { + null + } + } else { + tryRenderStructOrUnion(def)?.let { + AnnotationStub.CStruct(it) + } + } + val classifier = context.getKotlinClassForPointed(decl) + + val fields: List = def.fields.map { field -> + try { + assert(field.name.isNotEmpty()) + assert(field.offset % 8 == 0L) + val offset = field.offset / 8 + val fieldRefType = context.mirror(field.type) + val unwrappedFieldType = field.type.unwrapTypedefs() + val origin = StubOrigin.StructMember(field) + val fieldName = mangleSimple(field.name) + if (unwrappedFieldType is ArrayType) { + val type = (fieldRefType as TypeMirror.ByValue).valueType + val annotations = if (platform == KotlinPlatform.JVM) { + val length = getArrayLength(unwrappedFieldType) + // TODO: @CLength should probably be used on types instead of properties. + listOf(AnnotationStub.CLength(length)) + } else { + emptyList() + } + val getter = when (context.generationMode) { + GenerationMode.SOURCE_CODE -> PropertyAccessor.Getter.ArrayMemberAt(offset) + GenerationMode.METADATA -> PropertyAccessor.Getter.ExternalGetter(listOf(AnnotationStub.CStruct.ArrayMemberAt(offset))) + } + val kind = PropertyStub.Kind.Val(getter) + // TODO: Should receiver be added? + PropertyStub(fieldName, type.toStubIrType(), kind, annotations = annotations, origin = origin) + } else { + val pointedType = fieldRefType.pointedType.toStubIrType() + val pointedTypeArgument = TypeArgumentStub(pointedType) + if (fieldRefType is TypeMirror.ByValue) { + val getter: PropertyAccessor.Getter + val setter: PropertyAccessor.Setter + when (context.generationMode) { + GenerationMode.SOURCE_CODE -> { + getter = PropertyAccessor.Getter.MemberAt(offset, typeArguments = listOf(pointedTypeArgument), hasValueAccessor = true) + setter = PropertyAccessor.Setter.MemberAt(offset, typeArguments = listOf(pointedTypeArgument)) + } + GenerationMode.METADATA -> { + getter = PropertyAccessor.Getter.ExternalGetter(listOf(AnnotationStub.CStruct.MemberAt(offset))) + setter = PropertyAccessor.Setter.ExternalSetter(listOf(AnnotationStub.CStruct.MemberAt(offset))) + } + } + val kind = PropertyStub.Kind.Var(getter, setter) + PropertyStub(fieldName, fieldRefType.argType.toStubIrType(), kind, origin = origin) + } else { + val accessor = when (context.generationMode) { + GenerationMode.SOURCE_CODE -> PropertyAccessor.Getter.MemberAt(offset, hasValueAccessor = false) + GenerationMode.METADATA -> PropertyAccessor.Getter.ExternalGetter(listOf(AnnotationStub.CStruct.MemberAt(offset))) + } + val kind = PropertyStub.Kind.Val(accessor) + PropertyStub(fieldName, pointedType, kind, origin = origin) + } + } + } catch (e: Throwable) { + null + } + } + + val bitFields: List = def.bitFields.map { field -> + val typeMirror = context.mirror(field.type) + val typeInfo = typeMirror.info + val kotlinType = typeMirror.argType + val signed = field.type.isIntegerTypeSigned() + val fieldName = mangleSimple(field.name) + val kind = when (context.generationMode) { + GenerationMode.SOURCE_CODE -> { + val readBits = PropertyAccessor.Getter.ReadBits(field.offset, field.size, signed) + val writeBits = PropertyAccessor.Setter.WriteBits(field.offset, field.size) + context.bridgeComponentsBuilder.getterToBridgeInfo[readBits] = BridgeGenerationInfo("", typeInfo) + context.bridgeComponentsBuilder.setterToBridgeInfo[writeBits] = BridgeGenerationInfo("", typeInfo) + PropertyStub.Kind.Var(readBits, writeBits) + } + GenerationMode.METADATA -> { + val readBits = PropertyAccessor.Getter.ExternalGetter(listOf(AnnotationStub.CStruct.BitField(field.offset, field.size))) + val writeBits = PropertyAccessor.Setter.ExternalSetter(listOf(AnnotationStub.CStruct.BitField(field.offset, field.size))) + PropertyStub.Kind.Var(readBits, writeBits) + } + } + PropertyStub(fieldName, kotlinType.toStubIrType(), kind, origin = StubOrigin.StructMember(field)) + } + + val superClass = context.platform.getRuntimeType("CStructVar") + require(superClass is ClassifierStubType) + val rawPtrConstructorParam = FunctionParameterStub("rawPtr", context.platform.getRuntimeType("NativePtr")) + val origin = StubOrigin.Struct(decl) + val primaryConstructor = ConstructorStub( + parameters = listOf(rawPtrConstructorParam), + isPrimary = true, + annotations = emptyList(), + origin = origin + ) + val superClassInit = SuperClassInit(superClass, listOf(GetConstructorParameter(rawPtrConstructorParam))) + + val companionSuper = superClass.nested("Type") + val typeSize = listOf(IntegralConstantStub(def.size, 4, true), IntegralConstantStub(def.align.toLong(), 4, true)) + val companionSuperInit = SuperClassInit(companionSuper, typeSize) + val companionClassifier = classifier.nested("Companion") + val annotation = AnnotationStub.CStruct.VarType(def.size, def.align).takeIf { + context.generationMode == GenerationMode.METADATA + } + val companion = ClassStub.Companion( + companionClassifier, + superClassInit = companionSuperInit, + annotations = listOfNotNull(annotation, AnnotationStub.Deprecated.deprecatedCVariableCompanion) + ) + + return listOf(ClassStub.Simple( + classifier, + origin = origin, + properties = fields.filterNotNull() + if (platform == KotlinPlatform.NATIVE) bitFields else emptyList(), + constructors = listOf(primaryConstructor), + methods = emptyList(), + modality = ClassStubModality.NONE, + annotations = listOfNotNull(structAnnotation), + superClassInit = superClassInit, + companion = companion + )) + } + + private fun getArrayLength(type: ArrayType): Long { + val unwrappedElementType = type.elemType.unwrapTypedefs() + val elementLength = if (unwrappedElementType is ArrayType) { + getArrayLength(unwrappedElementType) + } else { + 1L + } + + val elementCount = when (type) { + is ConstArrayType -> type.length + is IncompleteArrayType -> 0L + else -> TODO(type.toString()) + } + + return elementLength * elementCount + } + + private tailrec fun Type.isIntegerTypeSigned(): Boolean = when (this) { + is IntegerType -> this.isSigned + is BoolType -> false + is EnumType -> this.def.baseType.isIntegerTypeSigned() + is Typedef -> this.def.aliased.isIntegerTypeSigned() + else -> error(this) + } + + /** + * Produces to [out] the definition of Kotlin class representing the reference to given forward (incomplete) struct. + */ + private fun generateForwardStruct(s: StructDecl): List = when (context.platform) { + KotlinPlatform.JVM -> { + val classifier = context.getKotlinClassForPointed(s) + val superClass = context.platform.getRuntimeType("COpaque") + val rawPtrConstructorParam = FunctionParameterStub("rawPtr", context.platform.getRuntimeType("NativePtr")) + val superClassInit = SuperClassInit(superClass, listOf(GetConstructorParameter(rawPtrConstructorParam))) + val origin = StubOrigin.Struct(s) + val primaryConstructor = ConstructorStub(listOf(rawPtrConstructorParam), emptyList(), isPrimary = true, origin = origin) + listOf(ClassStub.Simple( + classifier, + ClassStubModality.NONE, + constructors = listOf(primaryConstructor), + superClassInit = superClassInit, + origin = origin)) + } + KotlinPlatform.NATIVE -> emptyList() + } +} + +internal class EnumStubBuilder( + override val context: StubsBuildingContext, + private val enumDef: EnumDef +) : StubElementBuilder { + + private val classifier = (context.mirror(EnumType(enumDef)) as TypeMirror.ByValue).valueType.classifier + private val baseTypeMirror = context.mirror(enumDef.baseType) + private val baseType = baseTypeMirror.argType.toStubIrType() + + override fun build(): List { + if (!context.isStrictEnum(enumDef)) { + return generateEnumAsConstants(enumDef) + } + val constructorParameter = FunctionParameterStub("value", baseType) + val valueProperty = PropertyStub( + name = "value", + type = baseType, + kind = PropertyStub.Kind.Val(PropertyAccessor.Getter.GetConstructorParameter(constructorParameter)), + modality = MemberStubModality.OPEN, + origin = StubOrigin.Synthetic.EnumValueField(enumDef), + isOverride = true) + + val canonicalsByValue = enumDef.constants + .groupingBy { it.value } + .reduce { _, accumulator, element -> + if (element.isMoreCanonicalThan(accumulator)) { + element + } else { + accumulator + } + } + val (canonicalConstants, aliasConstants) = enumDef.constants.partition { canonicalsByValue[it.value] == it } + + val canonicalEntriesWithAliases = canonicalConstants + .sortedBy { it.value } // TODO: Is it stable enough? + .mapIndexed { index, constant -> + val literal = context.tryCreateIntegralStub(enumDef.baseType, constant.value) + ?: error("Cannot create enum value ${constant.value} of type ${enumDef.baseType}") + val entry = EnumEntryStub(mangleSimple(constant.name), literal, StubOrigin.EnumEntry(constant), index) + val aliases = aliasConstants + .filter { it.value == constant.value } + .map { constructAliasProperty(it, entry) } + entry to aliases + } + val origin = StubOrigin.Enum(enumDef) + val primaryConstructor = ConstructorStub( + parameters = listOf(constructorParameter), + annotations = emptyList(), + isPrimary = true, + origin = origin, + visibility = VisibilityModifier.PRIVATE + ) + + val byValueFunction = FunctionStub( + name = "byValue", + returnType = ClassifierStubType(classifier), + parameters = listOf(FunctionParameterStub("value", baseType)), + origin = StubOrigin.Synthetic.EnumByValue(enumDef), + receiver = null, + modality = MemberStubModality.FINAL, + annotations = listOf(AnnotationStub.Deprecated.deprecatedCEnumByValue) + ) + + val companion = ClassStub.Companion( + classifier = classifier.nested("Companion"), + properties = canonicalEntriesWithAliases.flatMap { it.second }, + methods = listOf(byValueFunction) + ) + val enumVarClass = constructEnumVarClass().takeIf { context.generationMode == GenerationMode.METADATA } + val kotlinEnumType = ClassifierStubType(Classifier.topLevel("kotlin", "Enum"), + listOf(TypeArgumentStub(ClassifierStubType(classifier)))) + val enum = ClassStub.Enum( + classifier = classifier, + superClassInit = SuperClassInit(kotlinEnumType), + entries = canonicalEntriesWithAliases.map { it.first }, + companion = companion, + constructors = listOf(primaryConstructor), + properties = listOf(valueProperty), + origin = origin, + interfaces = listOf(context.platform.getRuntimeType("CEnum")), + childrenClasses = listOfNotNull(enumVarClass) + ) + context.bridgeComponentsBuilder.enumToTypeMirror[enum] = baseTypeMirror + return listOf(enum) + } + + private fun constructAliasProperty(enumConstant: EnumConstant, entry: EnumEntryStub): PropertyStub { + val aliasAnnotation = AnnotationStub.CEnumEntryAlias(entry.name) + .takeIf { context.generationMode == GenerationMode.METADATA } + return PropertyStub( + enumConstant.name, + ClassifierStubType(classifier), + kind = PropertyStub.Kind.Val(PropertyAccessor.Getter.GetEnumEntry(entry)), + origin = StubOrigin.EnumEntry(enumConstant), + annotations = listOfNotNull(aliasAnnotation) + ) + } + + private fun constructEnumVarClass(): ClassStub.Simple { + + val enumVarClassifier = classifier.nested("Var") + + val rawPtrConstructorParam = FunctionParameterStub("rawPtr", context.platform.getRuntimeType("NativePtr")) + val superClass = context.platform.getRuntimeType("CEnumVar") + require(superClass is ClassifierStubType) + val primaryConstructor = ConstructorStub( + parameters = listOf(rawPtrConstructorParam), + isPrimary = true, + annotations = emptyList(), + origin = StubOrigin.Synthetic.DefaultConstructor + ) + val superClassInit = SuperClassInit(superClass, listOf(GetConstructorParameter(rawPtrConstructorParam))) + + val baseIntegerTypeSize = when (val unwrappedType = enumDef.baseType.unwrapTypedefs()) { + is IntegerType -> unwrappedType.size.toLong() + CharType -> 1L + else -> error("Incorrect base type for enum ${classifier.fqName}") + } + val typeSize = IntegralConstantStub(baseIntegerTypeSize, 4, true) + val companionSuper = (context.platform.getRuntimeType("CPrimitiveVar") as ClassifierStubType).nested("Type") + val varSizeAnnotation = AnnotationStub.CEnumVarTypeSize(baseIntegerTypeSize.toInt()) + .takeIf { context.generationMode == GenerationMode.METADATA } + val companion = ClassStub.Companion( + classifier = enumVarClassifier.nested("Companion"), + superClassInit = SuperClassInit(companionSuper, listOf(typeSize)), + annotations = listOfNotNull(varSizeAnnotation, AnnotationStub.Deprecated.deprecatedCVariableCompanion) + ) + val valueProperty = PropertyStub( + name = "value", + type = ClassifierStubType(classifier), + kind = PropertyStub.Kind.Var( + PropertyAccessor.Getter.ExternalGetter(), + PropertyAccessor.Setter.ExternalSetter() + ), + origin = StubOrigin.Synthetic.EnumVarValueField(enumDef) + ) + return ClassStub.Simple( + classifier = enumVarClassifier, + constructors = listOf(primaryConstructor), + superClassInit = superClassInit, + companion = companion, + modality = ClassStubModality.NONE, + origin = StubOrigin.VarOf(StubOrigin.Enum(enumDef)), + properties = listOf(valueProperty) + ) + } + + private fun EnumConstant.isMoreCanonicalThan(other: EnumConstant): Boolean = with(other.name.toLowerCase()) { + contains("min") || contains("max") || + contains("first") || contains("last") || + contains("begin") || contains("end") + } + + /** + * Produces to [out] the Kotlin definitions for given enum which shouldn't be represented as Kotlin enum. + */ + private fun generateEnumAsConstants(enumDef: EnumDef): List { + // TODO: if this enum defines e.g. a type of struct field, then it should be generated inside the struct class + // to prevent name clashing + + val entries = mutableListOf() + val typealiases = mutableListOf() + + val constants = enumDef.constants.filter { + // Macro "overrides" the original enum constant. + it.name !in context.macroConstantsByName + } + + val kotlinType: KotlinType + + val baseKotlinType = context.mirror(enumDef.baseType).argType + val meta = if (enumDef.isAnonymous) { + kotlinType = baseKotlinType + StubContainerMeta(textAtStart = if (constants.isNotEmpty()) "// ${enumDef.spelling}:" else "") + } else { + val typeMirror = context.mirror(EnumType(enumDef)) + if (typeMirror !is TypeMirror.ByValue) { + error("unexpected enum type mirror: $typeMirror") + } + + val varTypeName = typeMirror.info.constructPointedType(typeMirror.valueType) + val varTypeClassifier = typeMirror.pointedType.classifier + val valueTypeClassifier = typeMirror.valueType.classifier + val origin = StubOrigin.Enum(enumDef) + typealiases += TypealiasStub(varTypeClassifier, varTypeName.toStubIrType(), StubOrigin.VarOf(origin)) + typealiases += TypealiasStub(valueTypeClassifier, baseKotlinType.toStubIrType(), origin) + + kotlinType = typeMirror.valueType + StubContainerMeta() + } + + for (constant in constants) { + val literal = context.tryCreateIntegralStub(enumDef.baseType, constant.value) ?: continue + val kind = when (context.generationMode) { + GenerationMode.SOURCE_CODE -> { + val getter = PropertyAccessor.Getter.SimpleGetter(constant = literal) + PropertyStub.Kind.Val(getter) + } + GenerationMode.METADATA -> { + PropertyStub.Kind.Constant(literal) + } + } + entries += PropertyStub( + constant.name, + kotlinType.toStubIrType(), + kind, + MemberStubModality.FINAL, + null, + origin = StubOrigin.EnumEntry(constant) + ) + } + val container = SimpleStubContainer( + meta, + properties = entries.toList(), + typealiases = typealiases.toList() + ) + return listOf(container) + } +} + +internal class FunctionStubBuilder( + override val context: StubsBuildingContext, + private val func: FunctionDecl, + private val skipOverloads: Boolean = false +) : StubElementBuilder { + + override fun build(): List { + val platform = context.platform + val parameters = mutableListOf() + + var hasStableParameterNames = true + func.parameters.forEachIndexed { index, parameter -> + val parameterName = parameter.name.let { + if (it == null || it.isEmpty()) { + hasStableParameterNames = false + "arg$index" + } else { + it + } + } + + val representAsValuesRef = representCFunctionParameterAsValuesRef(parameter.type) + parameters += when { + representCFunctionParameterAsString(func, parameter.type) -> { + val annotations = when (platform) { + KotlinPlatform.JVM -> emptyList() + KotlinPlatform.NATIVE -> listOf(AnnotationStub.CCall.CString) + } + val type = KotlinTypes.string.makeNullable().toStubIrType() + val functionParameterStub = FunctionParameterStub(parameterName, type, annotations) + context.bridgeComponentsBuilder.cStringParameters += functionParameterStub + functionParameterStub + } + representCFunctionParameterAsWString(func, parameter.type) -> { + val annotations = when (platform) { + KotlinPlatform.JVM -> emptyList() + KotlinPlatform.NATIVE -> listOf(AnnotationStub.CCall.WCString) + } + val type = KotlinTypes.string.makeNullable().toStubIrType() + val functionParameterStub = FunctionParameterStub(parameterName, type, annotations) + context.bridgeComponentsBuilder.wCStringParameters += functionParameterStub + functionParameterStub + } + representAsValuesRef != null -> { + FunctionParameterStub(parameterName, representAsValuesRef.toStubIrType()) + } + else -> { + val mirror = context.mirror(parameter.type) + val type = mirror.argType.toStubIrType() + FunctionParameterStub(parameterName, type) + } + } + } + + val returnType = if (func.returnsVoid()) { + KotlinTypes.unit + } else { + context.mirror(func.returnType).argType + }.toStubIrType() + + if (skipOverloads && context.isOverloading(func)) + return emptyList() + + val annotations: List + val mustBeExternal: Boolean + if (platform == KotlinPlatform.JVM) { + annotations = emptyList() + mustBeExternal = false + } else { + if (func.isVararg) { + val type = KotlinTypes.any.makeNullable().toStubIrType() + parameters += FunctionParameterStub("variadicArguments", type, isVararg = true) + } + annotations = listOf(AnnotationStub.CCall.Symbol("${context.generateNextUniqueId("knifunptr_")}_${func.name}")) + mustBeExternal = true + } + val functionStub = FunctionStub( + func.name, + returnType, + parameters.toList(), + StubOrigin.Function(func), + annotations, + mustBeExternal, + null, + MemberStubModality.FINAL, + hasStableParameterNames = hasStableParameterNames + ) + return listOf(functionStub) + } + + + private fun FunctionDecl.returnsVoid(): Boolean = this.returnType.unwrapTypedefs() is VoidType + + private fun representCFunctionParameterAsValuesRef(type: Type): KotlinType? { + val pointeeType = when (type) { + is PointerType -> type.pointeeType + is ArrayType -> type.elemType + else -> return null + } + + val unwrappedPointeeType = pointeeType.unwrapTypedefs() + + if (unwrappedPointeeType is VoidType) { + // Represent `void*` as `CValuesRef<*>?`: + return KotlinTypes.cValuesRef.typeWith(StarProjection).makeNullable() + } + + if (unwrappedPointeeType is FunctionType) { + // Don't represent function pointer as `CValuesRef?` currently: + return null + } + + if (unwrappedPointeeType is ArrayType) { + return representCFunctionParameterAsValuesRef(pointeeType) + } + + + return KotlinTypes.cValuesRef.typeWith(context.mirror(pointeeType).pointedType).makeNullable() + } + + + private val platformWStringTypes = setOf("LPCWSTR") + + private val noStringConversion: Set + get() = context.configuration.noStringConversion + + private fun Type.isAliasOf(names: Set): Boolean { + var type = this + while (type is Typedef) { + if (names.contains(type.def.name)) return true + type = type.def.aliased + } + return false + } + + private fun representCFunctionParameterAsString(function: FunctionDecl, type: Type): Boolean { + val unwrappedType = type.unwrapTypedefs() + return unwrappedType is PointerType && unwrappedType.pointeeIsConst && + unwrappedType.pointeeType.unwrapTypedefs() == CharType && + !noStringConversion.contains(function.name) + } + + // We take this approach as generic 'const short*' shall not be used as String. + private fun representCFunctionParameterAsWString(function: FunctionDecl, type: Type) = type.isAliasOf(platformWStringTypes) + && !noStringConversion.contains(function.name) +} + +internal class GlobalStubBuilder( + override val context: StubsBuildingContext, + private val global: GlobalDecl +) : StubElementBuilder { + override fun build(): List { + val mirror = context.mirror(global.type) + val unwrappedType = global.type.unwrapTypedefs() + val origin = StubOrigin.Global(global) + + val kotlinType: KotlinType + val kind: PropertyStub.Kind + if (unwrappedType is ArrayType) { + kotlinType = (mirror as TypeMirror.ByValue).valueType + val getter = when (context.platform) { + KotlinPlatform.JVM -> { + PropertyAccessor.Getter.SimpleGetter().also { + val extra = BridgeGenerationInfo(global.name, mirror.info) + context.bridgeComponentsBuilder.arrayGetterBridgeInfo[it] = extra + } + } + KotlinPlatform.NATIVE -> { + val cCallAnnotation = AnnotationStub.CCall.Symbol("${context.generateNextUniqueId("knifunptr_")}_${global.name}_getter") + PropertyAccessor.Getter.ExternalGetter(listOf(cCallAnnotation)).also { + context.wrapperComponentsBuilder.getterToWrapperInfo[it] = WrapperGenerationInfo(global) + } + } + } + kind = PropertyStub.Kind.Val(getter) + } else { + when (mirror) { + is TypeMirror.ByValue -> { + kotlinType = mirror.argType + val getter = when (context.platform) { + KotlinPlatform.JVM -> { + PropertyAccessor.Getter.SimpleGetter().also { + val getterExtra = BridgeGenerationInfo(global.name, mirror.info) + context.bridgeComponentsBuilder.getterToBridgeInfo[it] = getterExtra + } + } + KotlinPlatform.NATIVE -> { + val cCallAnnotation = AnnotationStub.CCall.Symbol("${context.generateNextUniqueId("knifunptr_")}_${global.name}_getter") + PropertyAccessor.Getter.ExternalGetter(listOf(cCallAnnotation)).also { + context.wrapperComponentsBuilder.getterToWrapperInfo[it] = WrapperGenerationInfo(global) + } + } + } + kind = if (global.isConst) { + PropertyStub.Kind.Val(getter) + } else { + val setter = when (context.platform) { + KotlinPlatform.JVM -> { + PropertyAccessor.Setter.SimpleSetter().also { + val setterExtra = BridgeGenerationInfo(global.name, mirror.info) + context.bridgeComponentsBuilder.setterToBridgeInfo[it] = setterExtra + } + } + KotlinPlatform.NATIVE -> { + val cCallAnnotation = AnnotationStub.CCall.Symbol("${context.generateNextUniqueId("knifunptr_")}_${global.name}_setter") + PropertyAccessor.Setter.ExternalSetter(listOf(cCallAnnotation)).also { + context.wrapperComponentsBuilder.setterToWrapperInfo[it] = WrapperGenerationInfo(global) + } + } + } + PropertyStub.Kind.Var(getter, setter) + } + } + is TypeMirror.ByRef -> { + kotlinType = mirror.pointedType + val getter = when (context.generationMode) { + GenerationMode.SOURCE_CODE -> { + PropertyAccessor.Getter.InterpretPointed(global.name, kotlinType.toStubIrType()) + } + GenerationMode.METADATA -> { + val cCallAnnotation = AnnotationStub.CCall.Symbol("${context.generateNextUniqueId("knifunptr_")}_${global.name}_getter") + PropertyAccessor.Getter.ExternalGetter(listOf(cCallAnnotation)).also { + context.wrapperComponentsBuilder.getterToWrapperInfo[it] = WrapperGenerationInfo(global, passViaPointer = true) + } + } + } + kind = PropertyStub.Kind.Val(getter) + } + } + } + return listOf(PropertyStub(global.name, kotlinType.toStubIrType(), kind, origin = origin)) + } +} + +internal class TypedefStubBuilder( + override val context: StubsBuildingContext, + private val typedefDef: TypedefDef +) : StubElementBuilder { + override fun build(): List { + val mirror = context.mirror(Typedef(typedefDef)) + val baseMirror = context.mirror(typedefDef.aliased) + val varType = mirror.pointedType.classifier + val origin = StubOrigin.TypeDef(typedefDef) + return when (baseMirror) { + is TypeMirror.ByValue -> { + val valueType = (mirror as TypeMirror.ByValue).valueType + val varTypeAliasee = mirror.info.constructPointedType(valueType) + val valueTypeAliasee = baseMirror.valueType + listOf( + TypealiasStub(varType, varTypeAliasee.toStubIrType(), StubOrigin.VarOf(origin)), + TypealiasStub(valueType.classifier, valueTypeAliasee.toStubIrType(), origin) + ) + } + is TypeMirror.ByRef -> { + val varTypeAliasee = baseMirror.pointedType + listOf(TypealiasStub(varType, varTypeAliasee.toStubIrType(), origin)) + } + } + } +} diff --git a/kotlin-native/Interop/StubGenerator/src/main/kotlin/org/jetbrains/kotlin/native/interop/gen/StubIrExtensions.kt b/kotlin-native/Interop/StubGenerator/src/main/kotlin/org/jetbrains/kotlin/native/interop/gen/StubIrExtensions.kt new file mode 100644 index 00000000000..d48a60046c7 --- /dev/null +++ b/kotlin-native/Interop/StubGenerator/src/main/kotlin/org/jetbrains/kotlin/native/interop/gen/StubIrExtensions.kt @@ -0,0 +1,100 @@ +/* + * Copyright 2010-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ +package org.jetbrains.kotlin.native.interop.gen + +import org.jetbrains.kotlin.native.interop.indexer.ObjCProtocol + +private val StubOrigin.ObjCMethod.isOptional: Boolean + get() = container is ObjCProtocol && method.isOptional + +fun FunctionStub.isOptionalObjCMethod(): Boolean = this.origin is StubOrigin.ObjCMethod && + this.origin.isOptional + +val StubContainer.isInterface: Boolean + get() = if (this is ClassStub.Simple) { + modality == ClassStubModality.INTERFACE + } else { + false + } + +/** + * Compute which names will be declared by [StubContainer] in the given [pkgName] + */ +fun StubContainer.computeNamesToBeDeclared(pkgName: String): List { + + fun checkPackageCorrectness(classifier: Classifier) { + assert(classifier.pkg == pkgName) { + """Wrong classifier package. + |Expected: $pkgName + |Got: ${classifier.pkg} + |""".trimMargin() + } + } + + val classNames = classes.mapNotNull { + when (it) { + is ClassStub.Simple -> it.classifier + is ClassStub.Companion -> null + is ClassStub.Enum -> it.classifier + } + }.onEach { checkPackageCorrectness(it) }.map { it.topLevelName } + + val typealiasNames = typealiases + .onEach { checkPackageCorrectness(it.alias) } + .map { it.alias.topLevelName } + + val namesFromNestedContainers = simpleContainers + .flatMap { it.computeNamesToBeDeclared(pkgName) } + + return classNames + typealiasNames + namesFromNestedContainers +} + +val StubContainer.defaultMemberModality: MemberStubModality + get() = when (this) { + is SimpleStubContainer -> MemberStubModality.FINAL + is ClassStub.Simple -> if (this.modality == ClassStubModality.INTERFACE) { + MemberStubModality.ABSTRACT + } else { + MemberStubModality.FINAL + } + is ClassStub.Companion -> MemberStubModality.FINAL + is ClassStub.Enum -> MemberStubModality.FINAL + } + +/** + * Returns constructor that should be rendered in class header. + */ +val ClassStub.explicitPrimaryConstructor: ConstructorStub? + get() = functions.filterIsInstance().firstOrNull(ConstructorStub::isPrimary) + +fun ClassStub.nestedName(): String = + classifier.getRelativeFqName().substringAfterLast('.') + +fun ConstantStub.determineConstantAnnotationClassifier(): Classifier = when (this) { + is StringConstantStub -> "String" + is IntegralConstantStub -> when (size) { + 1 -> if (isSigned) "Byte" else "UByte" + 2 -> if (isSigned) "Short" else "UShort" + 4 -> if (isSigned) "Int" else "UInt" + 8 -> if (isSigned) "Long" else "ULong" + else -> error("Integral constant with unexpected size of $size.") + } + is DoubleConstantStub -> when (size) { + 4 -> "Float" + 8 -> "Double" + else -> error("Real constant with unexpected size of $size.") + } +}.let { Classifier.topLevel(cinteropInternalPackage, "ConstantValue").nested(it) } + +/** + * Returns the original name of the given type. + */ +val StubType.underlyingTypeFqName: String + get() = when (this) { + is ClassifierStubType -> classifier.fqName + is AbbreviatedType -> underlyingType.underlyingTypeFqName + is FunctionalType -> classifier.fqName + is TypeParameterType -> name + } \ No newline at end of file diff --git a/kotlin-native/Interop/StubGenerator/src/main/kotlin/org/jetbrains/kotlin/native/interop/gen/StubIrMetadataEmitter.kt b/kotlin-native/Interop/StubGenerator/src/main/kotlin/org/jetbrains/kotlin/native/interop/gen/StubIrMetadataEmitter.kt new file mode 100644 index 00000000000..8f5aa9e76cb --- /dev/null +++ b/kotlin-native/Interop/StubGenerator/src/main/kotlin/org/jetbrains/kotlin/native/interop/gen/StubIrMetadataEmitter.kt @@ -0,0 +1,600 @@ +/* + * Copyright 2010-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ +package org.jetbrains.kotlin.native.interop.gen + +import kotlinx.metadata.* +import kotlinx.metadata.klib.* +import org.jetbrains.kotlin.metadata.serialization.Interner +import org.jetbrains.kotlin.utils.addIfNotNull + +class StubIrMetadataEmitter( + private val context: StubIrContext, + private val builderResult: StubIrBuilderResult, + private val moduleName: String, + private val bridgeBuilderResult: BridgeBuilderResult +) { + fun emit(): KlibModuleMetadata { + val annotations = emptyList() + val fragments = emitModuleFragments() + return KlibModuleMetadata(moduleName, fragments, annotations) + } + + private fun emitModuleFragments(): List = + ModuleMetadataEmitter( + context.configuration.pkgName, + builderResult.stubs, + bridgeBuilderResult + ).emit().let { kmModuleFragment -> + // We need to create module fragment for each part of package name. + val pkgName = context.configuration.pkgName + val fakePackages = pkgName.mapIndexedNotNull { idx, char -> + if (char == '.') idx else null + }.map { dotPosition -> + KmModuleFragment().also { + it.fqName = pkgName.substring(0, dotPosition) + } + } + fakePackages + kmModuleFragment + } +} + +/** + * Translates single [StubContainer] to [KmModuleFragment]. + */ +internal class ModuleMetadataEmitter( + private val packageFqName: String, + private val module: SimpleStubContainer, + private val bridgeBuilderResult: BridgeBuilderResult +) { + + fun emit(): KmModuleFragment { + val context = VisitingContext(bridgeBuilderResult = bridgeBuilderResult) + val elements = KmElements(visitor.visitSimpleStubContainer(module, context)) + return writeModule(elements) + } + + private fun writeModule(elements: KmElements) = KmModuleFragment().also { km -> + km.fqName = packageFqName + km.classes += elements.classes.toList() + km.className += elements.classes.map(KmClass::name) + km.pkg = writePackage(elements) + } + + private fun writePackage(elements: KmElements) = KmPackage().also { km -> + km.fqName = packageFqName + km.typeAliases += elements.typeAliases.toList() + km.properties += elements.properties.toList() + km.functions += elements.functions.toList() + } + + /** + * StubIr translation result. Since Km* classes don't have common hierarchy we need + * to use list of Any. + */ + private class KmElements(result: List) { + val classes: List = result.filterIsInstance>().flatten() + val properties: List = result.filterIsInstance() + val typeAliases: List = result.filterIsInstance() + val functions: List = result.filterIsInstance() + val constructors: List = result.filterIsInstance() + } + + /** + * Used to pass data between parents and children when visiting StubIr elements. + */ + private data class VisitingContext( + val container: StubContainer? = null, + val typeParametersInterner: Interner = Interner(), + val bridgeBuilderResult: BridgeBuilderResult + ) { + inline fun withMappingExtensions(block: MappingExtensions.() -> R) = + with (MappingExtensions(typeParametersInterner, bridgeBuilderResult), block) + } + + private fun isTopLevelContainer(container: StubContainer?): Boolean = + container == null + + private fun getPropertyNameInScope(property: PropertyStub, container: StubContainer?): String = + if (isTopLevelContainer(container)) { + getTopLevelPropertyDeclarationName(bridgeBuilderResult.kotlinFile, property) + } else { + property.name + } + + private val visitor = object : StubIrVisitor { + + override fun visitClass(element: ClassStub, data: VisitingContext): List { + val classVisitingContext = VisitingContext( + container = element, + typeParametersInterner = Interner(data.typeParametersInterner), + bridgeBuilderResult = data.bridgeBuilderResult + ) + val children = element.children + if (element is ClassStub.Companion) { + listOf(ConstructorStub(isPrimary = true, visibility = VisibilityModifier.PRIVATE, origin = StubOrigin.Synthetic.DefaultConstructor)) + } else emptyList() + val elements = KmElements(children.mapNotNull { it.accept(this, classVisitingContext) }) + val kmClass = data.withMappingExtensions { + KmClass().also { km -> + element.annotations.mapTo(km.annotations) { it.map() } + km.flags = element.flags + km.name = element.classifier.fqNameSerialized + element.superClassInit?.let { km.supertypes += it.type.map() } + element.interfaces.mapTo(km.supertypes) { it.map() } + element.classes.mapTo(km.nestedClasses) { it.nestedName() } + km.typeAliases += elements.typeAliases.toList() + km.properties += elements.properties.toList() + km.functions += elements.functions.toList() + km.constructors += elements.constructors.toList() + km.companionObject = element.companion?.nestedName() + if (element is ClassStub.Enum) { + element.entries.mapTo(km.klibEnumEntries) { mapEnumEntry(it, classVisitingContext) } + } + } + } + // Metadata stores classes as flat list. + return listOf(kmClass) + elements.classes + } + + override fun visitTypealias(element: TypealiasStub, data: VisitingContext): KmTypeAlias = + data.withMappingExtensions { + KmTypeAlias(element.flags, element.alias.topLevelName).also { km -> + km.underlyingType = element.aliasee.map(shouldExpandTypeAliases = false) + km.expandedType = element.aliasee.map() + } + } + + override fun visitFunction(element: FunctionStub, data: VisitingContext) = + data.withMappingExtensions { + val function = if (bridgeBuilderResult.nativeBridges.isSupported(element)) { + element + } else { + element.copy( + external = false, + annotations = listOf(AnnotationStub.Deprecated.unableToImport) + ) + } + KmFunction(function.flags, function.name).also { km -> + km.receiverParameterType = function.receiver?.type?.map() + function.typeParameters.mapTo(km.typeParameters) { it.map() } + function.parameters.mapTo(km.valueParameters) { it.map() } + function.annotations.mapTo(km.annotations) { it.map() } + km.returnType = function.returnType.map() + } + } + + override fun visitProperty(element: PropertyStub, data: VisitingContext) = + data.withMappingExtensions { + val property = when (val bridgeSupportedKind = element.bridgeSupportedKind) { + null -> element.copy( + kind = PropertyStub.Kind.Val(PropertyAccessor.Getter.SimpleGetter()), + annotations = listOf(AnnotationStub.Deprecated.unableToImport) + ) + element.kind -> element + else -> element.copy(kind = bridgeSupportedKind) + } + val name = getPropertyNameInScope(property, data.container) + KmProperty(property.flags, name, property.getterFlags, property.setterFlags).also { km -> + property.annotations.mapTo(km.annotations) { it.map() } + km.receiverParameterType = property.receiverType?.map() + km.returnType = property.type.map() + val kind = property.kind + if (kind is PropertyStub.Kind.Var) { + kind.setter.annotations.mapTo(km.setterAnnotations) { it.map() } + // TODO: Maybe it's better to explicitly add setter parameter in stub. + km.setterParameter = FunctionParameterStub("value", property.type).map() + } + km.getterAnnotations += when (kind) { + is PropertyStub.Kind.Val -> kind.getter.annotations.map { it.map() } + is PropertyStub.Kind.Var -> kind.getter.annotations.map { it.map() } + is PropertyStub.Kind.Constant -> emptyList() + } + if (kind is PropertyStub.Kind.Constant) { + km.compileTimeValue = kind.constant.mapToAnnotationArgument() + } + } + } + + override fun visitConstructor(constructorStub: ConstructorStub, data: VisitingContext) = + data.withMappingExtensions { + KmConstructor(constructorStub.flags).apply { + constructorStub.parameters.mapTo(valueParameters, { it.map() }) + constructorStub.annotations.mapTo(annotations, { it.map() }) + } + } + + override fun visitPropertyAccessor(propertyAccessor: PropertyAccessor, data: VisitingContext) { + // TODO("not implemented") + } + + override fun visitSimpleStubContainer(simpleStubContainer: SimpleStubContainer, data: VisitingContext): List = + simpleStubContainer.children.mapNotNull { it.accept(this, data) } + + simpleStubContainer.simpleContainers.flatMap { visitSimpleStubContainer(it, data) } + + private fun mapEnumEntry(enumEntry: EnumEntryStub, data: VisitingContext): KlibEnumEntry = + data.withMappingExtensions { + KlibEnumEntry( + name = enumEntry.name, + ordinal = enumEntry.ordinal, + annotations = mutableListOf(enumEntry.constant.mapToConstantAnnotation()) + ) + } + } +} + +/** + * Collection of extension functions that simplify translation of + * StubIr elements to Kotlin Metadata. + */ +private class MappingExtensions( + private val typeParametersInterner: Interner, + private val bridgeBuilderResult: BridgeBuilderResult +) { + + private fun flagsOfNotNull(vararg flags: Flag?): Flags = + flagsOf(*listOfNotNull(*flags).toTypedArray()) + + private fun mapOfNotNull(vararg entries: Pair?): Map = + listOfNotNull(*entries).toMap() + + private val VisibilityModifier.flags: Flags + get() = flagsOfNotNull( + Flag.IS_PUBLIC.takeIf { this == VisibilityModifier.PUBLIC }, + Flag.IS_PROTECTED.takeIf { this == VisibilityModifier.PROTECTED }, + Flag.IS_INTERNAL.takeIf { this == VisibilityModifier.INTERNAL }, + Flag.IS_PRIVATE.takeIf { this == VisibilityModifier.PRIVATE } + ) + + private val MemberStubModality.flags: Flags + get() = flagsOfNotNull( + Flag.IS_FINAL.takeIf { this == MemberStubModality.FINAL }, + Flag.IS_OPEN.takeIf { this == MemberStubModality.OPEN }, + Flag.IS_ABSTRACT.takeIf { this == MemberStubModality.ABSTRACT } + ) + + val FunctionStub.flags: Flags + get() = flagsOfNotNull( + Flag.IS_PUBLIC, + Flag.Function.IS_EXTERNAL.takeIf { this.external }, + Flag.HAS_ANNOTATIONS.takeIf { annotations.isNotEmpty() }, + Flag.Function.HAS_NON_STABLE_PARAMETER_NAMES.takeIf { !this.hasStableParameterNames } + ) or modality.flags + + val Classifier.fqNameSerialized: String + get() = buildString { + if (pkg.isNotEmpty()) { + append(pkg.replace('.', '/')) + append('/') + } + // Nested classes should dot-separated. + append(getRelativeFqName(asSimpleName = false)) + } + + val PropertyStub.flags: Flags + get() = flagsOfNotNull( + Flag.IS_PUBLIC, + Flag.Property.IS_DECLARATION, + Flag.HAS_ANNOTATIONS.takeIf { annotations.isNotEmpty() }, + Flag.Property.HAS_CONSTANT.takeIf { kind is PropertyStub.Kind.Constant }, + Flag.Property.HAS_GETTER, + Flag.Property.HAS_SETTER.takeIf { kind is PropertyStub.Kind.Var }, + when (kind) { + is PropertyStub.Kind.Val -> null + is PropertyStub.Kind.Var -> Flag.Property.IS_VAR + is PropertyStub.Kind.Constant -> Flag.Property.IS_CONST + } + ) or modality.flags + + val PropertyStub.getterFlags: Flags + get() = when (val kind = kind) { + is PropertyStub.Kind.Val -> kind.getter.flags(modality) + is PropertyStub.Kind.Var -> kind.getter.flags(modality) + is PropertyStub.Kind.Constant -> kind.flags + } + + val PropertyStub.Kind.Constant.flags: Flags + get() = flagsOfNotNull( + Flag.IS_PUBLIC, + Flag.IS_FINAL + ) + + private fun PropertyAccessor.Getter.flags(propertyModality: MemberStubModality): Flags = + flagsOfNotNull( + Flag.HAS_ANNOTATIONS.takeIf { annotations.isNotEmpty() }, + Flag.IS_PUBLIC, + Flag.PropertyAccessor.IS_NOT_DEFAULT, + Flag.PropertyAccessor.IS_EXTERNAL.takeIf { this is PropertyAccessor.Getter.ExternalGetter } + ) or propertyModality.flags + + val PropertyStub.setterFlags: Flags + get() = when (val kind = kind) { + is PropertyStub.Kind.Var -> kind.setter.flags(modality) + else -> flagsOf() + } + + private fun PropertyAccessor.Setter.flags(propertyModality: MemberStubModality): Flags = + flagsOfNotNull( + Flag.HAS_ANNOTATIONS.takeIf { annotations.isNotEmpty() }, + Flag.IS_PUBLIC, + Flag.PropertyAccessor.IS_NOT_DEFAULT, + Flag.PropertyAccessor.IS_EXTERNAL.takeIf { this is PropertyAccessor.Setter.ExternalSetter } + ) or propertyModality.flags + + val StubType.flags: Flags + get() = flagsOfNotNull( + Flag.Type.IS_NULLABLE.takeIf { nullable } + ) + + val TypealiasStub.flags: Flags + get() = flagsOfNotNull( + Flag.IS_PUBLIC + ) + + val FunctionParameterStub.flags: Flags + get() = flagsOfNotNull( + Flag.HAS_ANNOTATIONS.takeIf { annotations.isNotEmpty() } + ) + + val ClassStub.flags: Flags + get() = flagsOfNotNull( + Flag.HAS_ANNOTATIONS.takeIf { annotations.isNotEmpty() }, + Flag.IS_PUBLIC, + Flag.IS_OPEN.takeIf { this is ClassStub.Simple && modality == ClassStubModality.OPEN }, + Flag.IS_FINAL.takeIf { this is ClassStub.Simple && modality == ClassStubModality.NONE }, + Flag.IS_ABSTRACT.takeIf { this is ClassStub.Simple + && (modality == ClassStubModality.ABSTRACT || modality == ClassStubModality.INTERFACE) }, + Flag.Class.IS_INTERFACE.takeIf { this is ClassStub.Simple && modality == ClassStubModality.INTERFACE }, + Flag.Class.IS_COMPANION_OBJECT.takeIf { this is ClassStub.Companion }, + Flag.Class.IS_CLASS.takeIf { this is ClassStub.Simple && modality != ClassStubModality.INTERFACE }, + Flag.Class.IS_ENUM_CLASS.takeIf { this is ClassStub.Enum } + ) + + + val ConstructorStub.flags: Flags + get() = flagsOfNotNull( + Flag.Constructor.IS_SECONDARY.takeIf { !isPrimary }, + Flag.HAS_ANNOTATIONS.takeIf { annotations.isNotEmpty() } + ) or visibility.flags + + fun AnnotationStub.map(): KmAnnotation { + fun Pair.asAnnotationArgument() = + (first to KmAnnotationArgument.StringValue(second)).takeIf { second.isNotEmpty() } + + fun replaceWith(replaceWith: String) = KmAnnotationArgument.AnnotationValue(KmAnnotation( + Classifier.topLevel("kotlin", "ReplaceWith").fqNameSerialized, + mapOfNotNull( + "imports" to KmAnnotationArgument.ArrayValue(emptyList()), + ("expression" to replaceWith).asAnnotationArgument() + ) + )) + + fun deprecationLevel(level: DeprecationLevel) = KmAnnotationArgument.EnumValue( + Classifier.topLevel("kotlin", "DeprecationLevel").fqNameSerialized, + level.name + ) + + val args = when (this) { + AnnotationStub.ObjC.ConsumesReceiver -> emptyMap() + AnnotationStub.ObjC.ReturnsRetained -> emptyMap() + is AnnotationStub.ObjC.Method -> mapOfNotNull( + ("selector" to selector).asAnnotationArgument(), + ("encoding" to encoding).asAnnotationArgument(), + ("isStret" to KmAnnotationArgument.BooleanValue(isStret)) + ) + is AnnotationStub.ObjC.Factory -> mapOfNotNull( + ("selector" to selector).asAnnotationArgument(), + ("encoding" to encoding).asAnnotationArgument(), + ("isStret" to KmAnnotationArgument.BooleanValue(isStret)) + ) + AnnotationStub.ObjC.Consumed -> emptyMap() + is AnnotationStub.ObjC.Constructor -> mapOfNotNull( + ("designated" to KmAnnotationArgument.BooleanValue(designated)), + ("initSelector" to selector).asAnnotationArgument() + ) + is AnnotationStub.ObjC.ExternalClass -> mapOfNotNull( + ("protocolGetter" to protocolGetter).asAnnotationArgument(), + ("binaryName" to binaryName).asAnnotationArgument() + ) + AnnotationStub.CCall.CString -> emptyMap() + AnnotationStub.CCall.WCString -> emptyMap() + is AnnotationStub.CCall.Symbol -> mapOfNotNull( + ("id" to symbolName).asAnnotationArgument() + ) + is AnnotationStub.CStruct -> mapOfNotNull( + ("spelling" to struct).asAnnotationArgument() + ) + is AnnotationStub.CNaturalStruct -> + error("@CNaturalStruct should not be used for Kotlin/Native interop") + is AnnotationStub.CLength -> mapOfNotNull( + "value" to KmAnnotationArgument.LongValue(length) + ) + is AnnotationStub.Deprecated -> mapOfNotNull( + ("message" to message).asAnnotationArgument(), + ("replaceWith" to replaceWith(replaceWith)), + ("level" to deprecationLevel(level)) + ) + is AnnotationStub.CEnumEntryAlias -> mapOfNotNull( + ("entryName" to entryName).asAnnotationArgument() + ) + is AnnotationStub.CEnumVarTypeSize -> mapOfNotNull( + ("size" to KmAnnotationArgument.IntValue(size)) + ) + is AnnotationStub.CStruct.MemberAt -> mapOfNotNull( + ("offset" to KmAnnotationArgument.LongValue(offset)) + ) + is AnnotationStub.CStruct.ArrayMemberAt -> mapOfNotNull( + ("offset" to KmAnnotationArgument.LongValue(offset)) + ) + is AnnotationStub.CStruct.BitField -> mapOfNotNull( + ("offset" to KmAnnotationArgument.LongValue(offset)), + ("size" to KmAnnotationArgument.IntValue(size)) + ) + is AnnotationStub.CStruct.VarType -> mapOfNotNull( + ("size" to KmAnnotationArgument.LongValue(size)), + ("align" to KmAnnotationArgument.IntValue(align)) + ) + } + return KmAnnotation(classifier.fqNameSerialized, args) + } + + /** + * @param shouldExpandTypeAliases describes how should we write type aliases. + * If [shouldExpandTypeAliases] is true then type alias-based types are written as + * ``` + * Type { + * abbreviatedType = AbbreviatedType.abbreviatedClassifier + * classifier = AbbreviatedType.underlyingType + * arguments = AbbreviatedType.underlyingType.typeArguments + * } + * ``` + * So we basically replacing type alias with underlying class. + * Otherwise: + * ``` + * Type { + * classifier = AbbreviatedType.abbreviatedClassifier + * } + * ``` + * As of 25 Nov 2019, the latter form is used only for KmTypeAlias.underlyingType. + */ + // TODO: Add caching if needed. + fun StubType.map(shouldExpandTypeAliases: Boolean = true): KmType = when (this) { + is AbbreviatedType -> { + val typeAliasClassifier = KmClassifier.TypeAlias(abbreviatedClassifier.fqNameSerialized) + val typeArguments = typeArguments.map { it.map(shouldExpandTypeAliases) } + val abbreviatedType = KmType(flags).also { km -> + km.classifier = typeAliasClassifier + km.arguments += typeArguments + } + if (shouldExpandTypeAliases) { + // Abbreviated and expanded types have the same nullability. + KmType(flags).also { km -> + km.abbreviatedType = abbreviatedType + val kmUnderlyingType = underlyingType.map(true) + km.arguments += kmUnderlyingType.arguments + km.classifier = kmUnderlyingType.classifier + } + } else { + abbreviatedType + } + } + is ClassifierStubType -> KmType(flags).also { km -> + typeArguments.mapTo(km.arguments) { it.map(shouldExpandTypeAliases) } + km.classifier = KmClassifier.Class(classifier.fqNameSerialized) + } + is FunctionalType -> KmType(flags).also { km -> + typeArguments.mapTo(km.arguments) { it.map(shouldExpandTypeAliases) } + km.classifier = KmClassifier.Class(classifier.fqNameSerialized) + } + is TypeParameterType -> KmType(flags).also { km -> + km.classifier = KmClassifier.TypeParameter(id) + } + } + + fun FunctionParameterStub.map(): KmValueParameter = + KmValueParameter(flags, name).also { km -> + val kmType = type.map() + if (isVararg) { + km.varargElementType = kmType + km.type = ClassifierStubType( + Classifier.topLevel("kotlin", "Array"), + listOf(TypeArgumentStub(type)) + ).map() + } else { + km.type = kmType + } + annotations.mapTo(km.annotations, { it.map() }) + } + + fun TypeParameterStub.map(): KmTypeParameter = + KmTypeParameter(flagsOf(), name, id, KmVariance.INVARIANT).also { km -> + km.upperBounds.addIfNotNull(upperBound?.map()) + } + + private fun TypeArgument.map(expanded: Boolean = true): KmTypeProjection = when (this) { + TypeArgument.StarProjection -> KmTypeProjection.STAR + is TypeArgumentStub -> KmTypeProjection(variance.map(), type.map(expanded)) + else -> error("Unexpected TypeArgument: $this") + } + + private fun TypeArgument.Variance.map(): KmVariance = when (this) { + TypeArgument.Variance.INVARIANT -> KmVariance.INVARIANT + TypeArgument.Variance.IN -> KmVariance.IN + TypeArgument.Variance.OUT -> KmVariance.OUT + } + + fun ConstantStub.mapToAnnotationArgument(): KmAnnotationArgument<*> = when (this) { + is StringConstantStub -> KmAnnotationArgument.StringValue(value) + is IntegralConstantStub -> when (size) { + 1 -> if (isSigned) { + KmAnnotationArgument.ByteValue(value.toByte()) + } else { + KmAnnotationArgument.UByteValue(value.toByte()) + } + 2 -> if (isSigned) { + KmAnnotationArgument.ShortValue(value.toShort()) + } else { + KmAnnotationArgument.UShortValue(value.toShort()) + } + 4 -> if (isSigned) { + KmAnnotationArgument.IntValue(value.toInt()) + } else { + KmAnnotationArgument.UIntValue(value.toInt()) + } + 8 -> if (isSigned) { + KmAnnotationArgument.LongValue(value) + } else { + KmAnnotationArgument.ULongValue(value) + } + + else -> error("Integral constant of value $value with unexpected size of $size.") + } + is DoubleConstantStub -> when (size) { + 4 -> KmAnnotationArgument.FloatValue(value.toFloat()) + 8 -> KmAnnotationArgument.DoubleValue(value) + else -> error("Floating-point constant of value $value with unexpected size of $size.") + } + } + + fun ConstantStub.mapToConstantAnnotation(): KmAnnotation = + KmAnnotation( + determineConstantAnnotationClassifier().fqNameSerialized, + mapOf("value" to mapToAnnotationArgument()) + ) + + private val TypeParameterType.id: Int + get() = typeParameterDeclaration.id + + private val TypeParameterStub.id: Int + get() = typeParametersInterner.intern(this) + + /** + * Sometimes we can't generate bridge for getter or setter. + * For example, it may happen due to bug in libclang which may + * erroneously skip `const` qualifier of global variable. + * + * In this case we should change effective property's kind to either `val` + * or even omit the declaration at all. + */ + val PropertyStub.bridgeSupportedKind: PropertyStub.Kind? + get() = when (kind) { + is PropertyStub.Kind.Var -> { + val isGetterSupported = bridgeBuilderResult.nativeBridges.isSupported(kind.getter) + val isSetterSupported = bridgeBuilderResult.nativeBridges.isSupported(kind.setter) + when { + isGetterSupported && isSetterSupported -> kind + !isGetterSupported -> null + else -> PropertyStub.Kind.Val(kind.getter) + } + } + is PropertyStub.Kind.Val -> { + val isGetterSupported = bridgeBuilderResult.nativeBridges.isSupported(kind.getter) + if (isGetterSupported) { + kind + } else { + null + } + } + is PropertyStub.Kind.Constant -> kind + } +} \ No newline at end of file diff --git a/kotlin-native/Interop/StubGenerator/src/main/kotlin/org/jetbrains/kotlin/native/interop/gen/StubIrTextEmitter.kt b/kotlin-native/Interop/StubGenerator/src/main/kotlin/org/jetbrains/kotlin/native/interop/gen/StubIrTextEmitter.kt new file mode 100644 index 00000000000..42fc8e06397 --- /dev/null +++ b/kotlin-native/Interop/StubGenerator/src/main/kotlin/org/jetbrains/kotlin/native/interop/gen/StubIrTextEmitter.kt @@ -0,0 +1,663 @@ +/* + * Copyright 2010-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ +package org.jetbrains.kotlin.native.interop.gen + +import org.jetbrains.kotlin.native.interop.gen.jvm.KotlinPlatform +import org.jetbrains.kotlin.native.interop.indexer.* +import org.jetbrains.kotlin.utils.addIfNotNull +import java.lang.IllegalStateException + +/** + * Emits stubs and bridge functions as *.kt and *.c files. + * Many unintuitive printings are made for compatability with previous version of stub generator. + * + * [omitEmptyLines] is useful for testing output (e.g. diff calculating). + */ +class StubIrTextEmitter( + private val context: StubIrContext, + private val builderResult: StubIrBuilderResult, + private val bridgeBuilderResult: BridgeBuilderResult, + private val omitEmptyLines: Boolean = false +) { + private val kotlinFile = bridgeBuilderResult.kotlinFile + private val nativeBridges = bridgeBuilderResult.nativeBridges + private val propertyAccessorBridgeBodies = bridgeBuilderResult.propertyAccessorBridgeBodies + private val functionBridgeBodies = bridgeBuilderResult.functionBridgeBodies + + private val pkgName: String + get() = context.configuration.pkgName + + private val StubContainer.isTopLevelContainer: Boolean + get() = this == builderResult.stubs || this in builderResult.stubs.simpleContainers + + /** + * The output currently used by the generator. + * Should append line separator after any usage. + */ + private var out: (String) -> Unit = { + throw IllegalStateException() + } + + private fun emitEmptyLine() { + if (!omitEmptyLines) { + out("") + } + } + + private fun withOutput(output: (String) -> Unit, action: () -> R): R { + val oldOut = out + out = output + try { + return action() + } finally { + out = oldOut + } + } + + private fun withOutput(appendable: Appendable, action: () -> R): R { + return withOutput({ appendable.appendLine(it) }, action) + } + + private fun generateLinesBy(action: () -> Unit): List { + val result = mutableListOf() + withOutput({ result.add(it) }, action) + return result + } + + private fun generateKotlinFragmentBy(block: () -> Unit): Sequence { + val lines = generateLinesBy(block) + return lines.asSequence() + } + + private fun indent(action: () -> R): R { + val oldOut = out + return withOutput({ oldOut(" $it") }, action) + } + + private fun block(header: String, body: () -> R): R { + out("$header {") + val res = indent { + body() + } + out("}") + return res + } + + private fun emitKotlinFileHeader() { + if (context.platform == KotlinPlatform.JVM) { + out("@file:JvmName(${context.jvmFileClassName.quoteAsKotlinLiteral()})") + } + if (context.platform == KotlinPlatform.NATIVE) { + out("@file:kotlinx.cinterop.InteropStubs") + } + + val suppress = mutableListOf("UNUSED_VARIABLE", "UNUSED_EXPRESSION").apply { + add("DEPRECATION") // CVariable.Type and CEnum companion deprecations. + if (context.configuration.library.language == Language.OBJECTIVE_C) { + add("CONFLICTING_OVERLOADS") + add("RETURN_TYPE_MISMATCH_ON_INHERITANCE") + add("PROPERTY_TYPE_MISMATCH_ON_INHERITANCE") // Multiple-inheriting property with conflicting types + add("VAR_TYPE_MISMATCH_ON_INHERITANCE") // Multiple-inheriting mutable property with conflicting types + add("RETURN_TYPE_MISMATCH_ON_OVERRIDE") + add("WRONG_MODIFIER_CONTAINING_DECLARATION") // For `final val` in interface. + add("PARAMETER_NAME_CHANGED_ON_OVERRIDE") + add("UNUSED_PARAMETER") // For constructors. + add("MANY_IMPL_MEMBER_NOT_IMPLEMENTED") // Workaround for multiple-inherited properties. + add("MANY_INTERFACES_MEMBER_NOT_IMPLEMENTED") // Workaround for multiple-inherited properties. + add("EXTENSION_SHADOWED_BY_MEMBER") // For Objective-C categories represented as extensions. + add("REDUNDANT_NULLABLE") // This warning appears due to Obj-C typedef nullability incomplete support. + add("DEPRECATION") // For uncheckedCast. + add("DEPRECATION_ERROR") // For initializers. + } + } + + out("@file:Suppress(${suppress.joinToString { it.quoteAsKotlinLiteral() }})") + if (pkgName != "") { + out("package ${context.validPackageName}") + out("") + } + if (context.platform == KotlinPlatform.NATIVE) { + out("import kotlin.native.SymbolName") + out("import kotlinx.cinterop.internal.*") + } + out("import kotlinx.cinterop.*") + + kotlinFile.buildImports().forEach { + out(it) + } + + out("") + + out("// NOTE THIS FILE IS AUTO-GENERATED") + } + fun emit(ktFile: Appendable) { + + // Stubs generation may affect imports list so do it before header generation. + val stubLines = generateKotlinFragmentBy { + printer.visitSimpleStubContainer(builderResult.stubs, null) + } + + withOutput(ktFile) { + emitKotlinFileHeader() + stubLines.forEach(out) + nativeBridges.kotlinLines.forEach(out) + if (context.platform == KotlinPlatform.JVM) + out("private val loadLibrary = loadKonanLibrary(\"${context.libName}\")") + } + } + private val printer = object : StubIrVisitor { + + override fun visitClass(element: ClassStub, data: StubContainer?) { + element.annotations.forEach { + out(renderAnnotation(it)) + } + val header = renderClassHeader(element) + when { + element.children.isEmpty() -> out(header) + else -> block(header) { + if (element is ClassStub.Enum) { + emitEnumEntries(element) + } + element.children + // We render a primary constructor as part of a header. + .filterNot { it is ConstructorStub && it.isPrimary } + .forEach { + emitEmptyLine() + it.accept(this, element) + } + if (element is ClassStub.Enum) { + emitEnumVarClass(element) + } + } + } + } + + override fun visitTypealias(element: TypealiasStub, data: StubContainer?) { + val alias = renderClassifierDeclaration(element.alias) + val aliasee = renderStubType(element.aliasee) + out("typealias $alias = $aliasee") + } + + override fun visitFunction(element: FunctionStub, data: StubContainer?) { + if (element in bridgeBuilderResult.excludedStubs) return + + val header = run { + val parameters = element.parameters.joinToString(prefix = "(", postfix = ")") { renderFunctionParameter(it) } + val receiver = element.receiver?.let { renderFunctionReceiver(it) + "." } ?: "" + val typeParameters = renderTypeParameters(element.typeParameters) + val override = if (element.isOverride) "override " else "" + val modality = renderMemberModality(element.modality, data) + "$override${modality}fun$typeParameters $receiver${element.name.asSimpleName()}$parameters: ${renderStubType(element.returnType)}" + } + if (!nativeBridges.isSupported(element)) { + sequenceOf( + annotationForUnableToImport, + "$header = throw UnsupportedOperationException()" + ).forEach(out) + return + } + element.annotations.forEach { + out(renderAnnotation(it)) + } + when { + element.external -> out("external $header") + element.isOptionalObjCMethod() -> out("$header = optional()") + element.origin is StubOrigin.Synthetic.EnumByValue -> + out("$header = values().find { it.value == value }!!") + data != null && data.isInterface -> out(header) + else -> block(header) { + functionBridgeBodies.getValue(element).forEach(out) + } + } + } + + override fun visitProperty(element: PropertyStub, data: StubContainer?) = + emitProperty(element, data) + + override fun visitConstructor(constructorStub: ConstructorStub, data: StubContainer?) { + constructorStub.annotations.forEach { + out(renderAnnotation(it)) + } + val visibility = renderVisibilityModifier(constructorStub.visibility) + out("${visibility}constructor(${constructorStub.parameters.joinToString { renderFunctionParameter(it) }}) {}") + } + + override fun visitPropertyAccessor(propertyAccessor: PropertyAccessor, data: StubContainer?) { + + } + + override fun visitSimpleStubContainer(simpleStubContainer: SimpleStubContainer, data: StubContainer?) { + if (simpleStubContainer.meta.textAtStart.isNotEmpty()) { + out(simpleStubContainer.meta.textAtStart) + } + simpleStubContainer.classes.forEach { + emitEmptyLine() + it.accept(this, simpleStubContainer) + } + simpleStubContainer.functions.forEach { + emitEmptyLine() + it.accept(this, simpleStubContainer) + } + simpleStubContainer.properties.forEach { + emitEmptyLine() + it.accept(this, simpleStubContainer) + } + simpleStubContainer.typealiases.forEach { + emitEmptyLine() + it.accept(this, simpleStubContainer) + } + simpleStubContainer.simpleContainers.forEach { + emitEmptyLine() + it.accept(this, simpleStubContainer) + } + if (simpleStubContainer.meta.textAtEnd.isNotEmpty()) { + out(simpleStubContainer.meta.textAtEnd) + } + } + } + + // About method naming convention: + // - "emit" prefix means that method will call `out` by itself. + // - "render" prefix means that method returns string that should be emitted by caller. + private fun emitEnumEntries(enum: ClassStub.Enum) { + enum.entries.forEach { + out(renderEnumEntry(it) + ",") + } + out(";") + } + + private fun emitEnumVarClass(enum: ClassStub.Enum) { + val simpleKotlinName = enum.classifier.topLevelName.asSimpleName() + val typeMirror = builderResult.bridgeGenerationComponents.enumToTypeMirror.getValue(enum) + val basePointedTypeName = typeMirror.pointedType.render(kotlinFile) + block("class Var(rawPtr: NativePtr) : CEnumVar(rawPtr)") { + out("@Deprecated(\"Use sizeOf() or alignOf() instead.\")") + out("companion object : Type(sizeOf<$basePointedTypeName>().toInt())") + out("var value: $simpleKotlinName") + out(" get() = byValue(this.reinterpret<$basePointedTypeName>().value)") + out(" set(value) { this.reinterpret<$basePointedTypeName>().value = value.value }") + } + } + + private fun emitProperty(element: PropertyStub, owner: StubContainer?) { + if (element in bridgeBuilderResult.excludedStubs) return + + val override = if (element.isOverride) "override " else "" + val modality = "$override${renderMemberModality(element.modality, owner)}" + val receiver = if (element.receiverType != null) "${renderStubType(element.receiverType)}." else "" + val name = if (owner?.isTopLevelContainer == true) { + getTopLevelPropertyDeclarationName(kotlinFile, element).asSimpleName() + } else { + element.name.asSimpleName() + } + val header = "$receiver$name: ${renderStubType(element.type)}" + + if (element.kind is PropertyStub.Kind.Val && !nativeBridges.isSupported(element.kind.getter) + || element.kind is PropertyStub.Kind.Var && !nativeBridges.isSupported(element.kind.getter)) { + out(annotationForUnableToImport) + out("val $header") + out(" get() = TODO()") + } else { + element.annotations.forEach { + out(renderAnnotation(it)) + } + when (val kind = element.kind) { + is PropertyStub.Kind.Constant -> { + out("${modality}const val $header = ${renderValueUsage(kind.constant)}") + } + is PropertyStub.Kind.Val -> { + val shouldWriteInline = kind.getter.let { + (it is PropertyAccessor.Getter.SimpleGetter && it.constant != null) + // We should render access to constructor parameter inline. + // Otherwise, it may be access to the property itself. (val f: Any get() = f) + || it is PropertyAccessor.Getter.GetConstructorParameter + } + if (shouldWriteInline) { + out("${modality}val $header ${renderGetter(kind.getter)}") + } else { + out("${modality}val $header") + indent { + out(renderGetter(kind.getter)) + } + } + } + is PropertyStub.Kind.Var -> { + val isSupported = nativeBridges.isSupported(kind.setter) + val variableKind = if (isSupported) "var" else "val" + + out("$modality$variableKind $header") + indent { + out(renderGetter(kind.getter)) + if (isSupported) { + out(renderSetter(kind.setter)) + } + } + } + } + } + } + + private fun renderFunctionReceiver(receiver: ReceiverParameterStub): String { + return renderStubType(receiver.type) + } + + private fun renderFunctionParameter(parameter: FunctionParameterStub): String { + val annotations = if (parameter.annotations.isEmpty()) + "" + else + parameter.annotations.joinToString(separator = " ") { renderAnnotation(it) } + " " + val vararg = if (parameter.isVararg) "vararg " else "" + return "$annotations$vararg${parameter.name.asSimpleName()}: ${renderStubType(parameter.type)}" + } + + private fun renderMemberModality(modality: MemberStubModality, container: StubContainer?): String = + if (container?.defaultMemberModality == modality) { + "" + } else + when (modality) { + MemberStubModality.OPEN -> "open " + MemberStubModality.FINAL -> "final " + MemberStubModality.ABSTRACT -> "abstract " + } + + private fun renderVisibilityModifier(visibilityModifier: VisibilityModifier) = when (visibilityModifier) { + VisibilityModifier.PRIVATE -> "private " + VisibilityModifier.PROTECTED -> "protected " + VisibilityModifier.INTERNAL -> "internal " + VisibilityModifier.PUBLIC -> "" + } + + private fun renderClassHeader(classStub: ClassStub): String { + val modality = when (classStub) { + is ClassStub.Simple -> renderClassStubModality(classStub.modality) + is ClassStub.Companion -> "" + is ClassStub.Enum -> "enum class " + } + val className = when (classStub) { + is ClassStub.Simple -> renderClassifierDeclaration(classStub.classifier) + is ClassStub.Companion -> "companion object" + is ClassStub.Enum -> renderClassifierDeclaration(classStub.classifier) + } + val constructorParams = classStub.explicitPrimaryConstructor?.parameters?.let(this::renderConstructorParams) ?: "" + val inheritance = mutableListOf().apply { + // Enum inheritance is implicit. + if (classStub !is ClassStub.Enum) { + addIfNotNull(classStub.superClassInit?.let { renderSuperInit(it) }) + } + addAll(classStub.interfaces.map { renderStubType(it) }) + }.let { if (it.isNotEmpty()) " : ${it.joinToString()}" else "" } + + return "$modality$className$constructorParams$inheritance" + } + + private fun renderClassifierDeclaration(classifier: Classifier): String = + kotlinFile.declare(classifier).asSimpleName() + + private fun renderClassStubModality(classStubModality: ClassStubModality): String = when (classStubModality) { + ClassStubModality.INTERFACE -> "interface " + ClassStubModality.OPEN -> "open class " + ClassStubModality.ABSTRACT -> "abstract class " + ClassStubModality.NONE -> "class " + } + + private fun renderConstructorParams(parameters: List): String = + if (parameters.isEmpty()) { + "" + } else { + parameters.joinToString(prefix = "(", postfix = ")") { renderFunctionParameter(it) } + } + + private fun renderSuperInit(superClassInit: SuperClassInit): String { + val parameters = superClassInit.arguments.joinToString(prefix = "(", postfix = ")") { renderValueUsage(it) } + return "${renderStubType(superClassInit.type)}$parameters" + } + + private fun renderStubType(stubType: StubType): String { + val nullable = if (stubType.nullable) "?" else "" + + return when (stubType) { + is ClassifierStubType -> { + val classifier = kotlinFile.reference(stubType.classifier) + val typeArguments = renderTypeArguments(stubType.typeArguments) + "$classifier$typeArguments$nullable" + } + is FunctionalType -> buildString { + if (stubType.nullable) append("(") + + append('(') + stubType.parameterTypes.joinTo(this) { renderStubType(it) } + append(") -> ") + append(renderStubType(stubType.returnType)) + + if (stubType.nullable) append(")?") + } + is TypeParameterType -> "${stubType.name}$nullable" + is AbbreviatedType -> { + val classifier = kotlinFile.reference(stubType.abbreviatedClassifier) + val typeArguments = renderTypeArguments(stubType.typeArguments) + "$classifier$typeArguments$nullable" + } + } + } + + private fun renderValueUsage(value: ValueStub): String = when (value) { + is StringConstantStub -> value.value.quoteAsKotlinLiteral() + is IntegralConstantStub -> renderIntegralConstant(value)!! + is DoubleConstantStub -> renderDoubleConstant(value)!! + is GetConstructorParameter -> value.constructorParameterStub.name + } + + private fun renderAnnotation(annotationStub: AnnotationStub): String = when (annotationStub) { + AnnotationStub.ObjC.ConsumesReceiver -> "@CCall.ConsumesReceiver" + AnnotationStub.ObjC.ReturnsRetained -> "@CCall.ReturnsRetained" + is AnnotationStub.ObjC.Method -> { + val stret = if (annotationStub.isStret) ", true" else "" + val selector = annotationStub.selector.quoteAsKotlinLiteral() + val encoding = annotationStub.encoding.quoteAsKotlinLiteral() + "@ObjCMethod($selector, $encoding$stret)" + } + is AnnotationStub.ObjC.Factory -> { + val stret = if (annotationStub.isStret) ", true" else "" + val selector = annotationStub.selector.quoteAsKotlinLiteral() + val encoding = annotationStub.encoding.quoteAsKotlinLiteral() + "@ObjCFactory($selector, $encoding$stret)" + } + AnnotationStub.ObjC.Consumed -> + "@CCall.Consumed" + is AnnotationStub.ObjC.Constructor -> + "@ObjCConstructor(${annotationStub.selector.quoteAsKotlinLiteral()}, ${annotationStub.designated})" + is AnnotationStub.ObjC.ExternalClass -> { + val protocolGetter = annotationStub.protocolGetter.quoteAsKotlinLiteral() + val binaryName = annotationStub.binaryName.quoteAsKotlinLiteral() + "@ExternalObjCClass" + when { + annotationStub.protocolGetter.isEmpty() && annotationStub.binaryName.isEmpty() -> "" + annotationStub.protocolGetter.isEmpty() -> "(\"\", $binaryName)" + annotationStub.binaryName.isEmpty() -> "($protocolGetter)" + else -> "($protocolGetter, $binaryName)" + } + } + AnnotationStub.CCall.CString -> + "@CCall.CString" + AnnotationStub.CCall.WCString -> + "@CCall.WCString" + is AnnotationStub.CCall.Symbol -> + "@CCall(${annotationStub.symbolName.quoteAsKotlinLiteral()})" + is AnnotationStub.CStruct -> + "@CStruct(${annotationStub.struct.quoteAsKotlinLiteral()})" + is AnnotationStub.CNaturalStruct -> + "@CNaturalStruct(${annotationStub.members.joinToString { it.name.quoteAsKotlinLiteral() }})" + is AnnotationStub.CLength -> + "@CLength(${annotationStub.length})" + is AnnotationStub.Deprecated -> + "@Deprecated(${annotationStub.message.quoteAsKotlinLiteral()}, " + + "ReplaceWith(${annotationStub.replaceWith.quoteAsKotlinLiteral()}), " + + "DeprecationLevel.${annotationStub.level.name})" + is AnnotationStub.CEnumEntryAlias, + is AnnotationStub.CEnumVarTypeSize, + is AnnotationStub.CStruct.MemberAt, + is AnnotationStub.CStruct.ArrayMemberAt, + is AnnotationStub.CStruct.BitField, + is AnnotationStub.CStruct.VarType -> + error("${annotationStub.classifier.fqName} annotation is unsupported in textual mode") + } + + private fun renderEnumEntry(enumEntryStub: EnumEntryStub): String = + "${enumEntryStub.name.asSimpleName()}(${renderValueUsage(enumEntryStub.constant)})" + + private fun renderGetter(accessor: PropertyAccessor.Getter): String { + val annotations = accessor.annotations.joinToString(separator = "") { renderAnnotation(it) + " " } + + return annotations + when (accessor) { + is PropertyAccessor.Getter.ExternalGetter -> { + "external get" + } + is PropertyAccessor.Getter.GetConstructorParameter -> "= ${renderPropertyAccessorBody(accessor)}" + else -> { + "get() = ${renderPropertyAccessorBody(accessor)}" + } + } + } + + private fun renderSetter(accessor: PropertyAccessor.Setter): String { + val annotations = accessor.annotations.joinToString(separator = "") { renderAnnotation(it) + " " } + return annotations + if (accessor is PropertyAccessor.Setter.ExternalSetter) { + "external set" + } else { + "set(value) { ${renderPropertyAccessorBody(accessor)} }" + } + } + + private fun renderPropertyAccessorBody(accessor: PropertyAccessor): String = when (accessor) { + is PropertyAccessor.Getter.SimpleGetter -> { + when { + accessor in propertyAccessorBridgeBodies -> propertyAccessorBridgeBodies.getValue(accessor) + accessor.constant != null -> renderValueUsage(accessor.constant) + else -> error("Bridge body for getter was not generated") + } + } + + is PropertyAccessor.Getter.GetConstructorParameter -> accessor.constructorParameter.name + + is PropertyAccessor.Getter.ArrayMemberAt -> "arrayMemberAt(${accessor.offset})" + + is PropertyAccessor.Getter.MemberAt -> { + val typeArguments = renderTypeArguments(accessor.typeArguments) + val valueAccess = if (accessor.hasValueAccessor) ".value" else "" + "memberAt$typeArguments(${accessor.offset})$valueAccess" + } + + is PropertyAccessor.Getter.ReadBits -> { + propertyAccessorBridgeBodies.getValue(accessor) + } + + is PropertyAccessor.Getter.GetEnumEntry -> accessor.enumEntryStub.name + + is PropertyAccessor.Setter.SimpleSetter -> when { + accessor in propertyAccessorBridgeBodies -> propertyAccessorBridgeBodies.getValue(accessor) + else -> error("Bridge body for setter was not generated") + } + + is PropertyAccessor.Setter.MemberAt -> { + if (accessor.typeArguments.isEmpty()) { + error("Unexpected memberAt setter without type parameters!") + } else { + val typeArguments = renderTypeArguments(accessor.typeArguments) + "memberAt$typeArguments(${accessor.offset}).value = value" + } + } + + is PropertyAccessor.Setter.WriteBits -> { + propertyAccessorBridgeBodies.getValue(accessor) + } + + is PropertyAccessor.Getter.InterpretPointed -> { + val typeParameters = accessor.typeParameters.joinToString(prefix = "<", postfix = ">") { renderStubType(it) } + val getAddressExpression = propertyAccessorBridgeBodies.getValue(accessor) + "interpretPointed$typeParameters($getAddressExpression)" + } + is PropertyAccessor.Getter.ExternalGetter, + is PropertyAccessor.Setter.ExternalSetter -> error("External property accessor shouldn't have a body!") + } + + private fun renderIntegralConstant(integralValue: IntegralConstantStub): String? { + val (value, size, isSigned) = integralValue + return if (isSigned) { + if (value == Long.MIN_VALUE) { + return "${value + 1} - 1" // Workaround for "The value is out of range" compile error. + } + + val narrowedValue: Number = when (size) { + 1 -> value.toByte() + 2 -> value.toShort() + 4 -> value.toInt() + 8 -> value + else -> return null + } + + narrowedValue.toString() + } else { + // Note: stub generator is built and run with different ABI versions, + // so Kotlin unsigned types can't be used here currently. + + val narrowedValue: String = when (size) { + 1 -> (value and 0xFF).toString() + 2 -> (value and 0xFFFF).toString() + 4 -> (value and 0xFFFFFFFF).toString() + 8 -> java.lang.Long.toUnsignedString(value) + else -> return null + } + + "${narrowedValue}u" + } + } + + private fun renderDoubleConstant(doubleValue: DoubleConstantStub): String? { + val (value, size) = doubleValue + return when (size) { + 4 -> { + val floatValue = value.toFloat() + val bits = java.lang.Float.floatToRawIntBits(floatValue) + "bitsToFloat($bits) /* == $floatValue */" + } + 8 -> { + val bits = java.lang.Double.doubleToRawLongBits(value) + "bitsToDouble($bits) /* == $value */" + } + else -> null + } + } + + private fun renderTypeArguments(typeArguments: List) = if (typeArguments.isNotEmpty()) { + typeArguments.joinToString(", ", "<", ">") { renderTypeArgument(it) } + } else { + "" + } + + private fun renderTypeArgument(typeArgument: TypeArgument) = when (typeArgument) { + is TypeArgumentStub -> { + val variance = when (typeArgument.variance) { + TypeArgument.Variance.INVARIANT -> "" + TypeArgument.Variance.IN -> "in " + TypeArgument.Variance.OUT -> "out " + } + "$variance${renderStubType(typeArgument.type)}" + } + TypeArgument.StarProjection -> "*" + else -> error("Unexpected type argument: $typeArgument") + } + + private fun renderTypeParameters(typeParameters: List) = if (typeParameters.isNotEmpty()) { + typeParameters.joinToString(", ", " <", ">") { renderTypeParameter(it) } + } else { + "" + } + + private fun renderTypeParameter(typeParameterStub: TypeParameterStub): String { + val name = typeParameterStub.name + return typeParameterStub.upperBound?.let { + "$name : ${renderStubType(it)}" + } ?: name + } +} \ No newline at end of file diff --git a/kotlin-native/Interop/StubGenerator/src/main/kotlin/org/jetbrains/kotlin/native/interop/gen/StubIrType.kt b/kotlin-native/Interop/StubGenerator/src/main/kotlin/org/jetbrains/kotlin/native/interop/gen/StubIrType.kt new file mode 100644 index 00000000000..1e87c70bbae --- /dev/null +++ b/kotlin-native/Interop/StubGenerator/src/main/kotlin/org/jetbrains/kotlin/native/interop/gen/StubIrType.kt @@ -0,0 +1,223 @@ +/* + * Copyright 2010-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ +package org.jetbrains.kotlin.native.interop.gen + +import org.jetbrains.kotlin.native.interop.gen.jvm.KotlinPlatform +import org.jetbrains.kotlin.utils.addToStdlib.ifNotEmpty + +sealed class StubType { + abstract val nullable: Boolean + abstract val typeArguments: List +} + +/** + * Wrapper over [Classifier]. + */ +class ClassifierStubType( + val classifier: Classifier, + override val typeArguments: List = emptyList(), + override val nullable: Boolean = false +) : StubType() { + + fun nested(name: String): ClassifierStubType = + ClassifierStubType(classifier.nested(name)) + + override fun toString(): String = + "${classifier.topLevelName}${typeArguments.ifNotEmpty { joinToString(prefix = "<", postfix = ">") } ?: ""}" +} + +class AbbreviatedType( + val underlyingType: StubType, + val abbreviatedClassifier: Classifier, + override val typeArguments: List, + override val nullable: Boolean = false +) : StubType() { + override fun toString(): String = + "${abbreviatedClassifier.topLevelName}${typeArguments.ifNotEmpty { joinToString(prefix = "<", postfix = ">") } ?: ""}" +} + +/** + * @return type from kotlinx.cinterop package + */ +fun KotlinPlatform.getRuntimeType(name: String, nullable: Boolean = false): StubType { + val classifier = Classifier.topLevel(cinteropPackage, name) + PredefinedTypesHandler.tryExpandPlatformDependentTypealias(classifier, this, nullable)?.let { return it } + return ClassifierStubType(classifier, nullable = nullable) +} + +/** + * Functional type from kotlin package: ([parameterTypes]) -> [returnType] + */ +class FunctionalType( + val parameterTypes: List, // TODO: Use TypeArguments. + val returnType: StubType, + override val nullable: Boolean = false +) : StubType() { + val classifier: Classifier = + Classifier.topLevel("kotlin", "Function${parameterTypes.size}") + + override val typeArguments: List by lazy { + listOf(*parameterTypes.toTypedArray(), returnType).map { TypeArgumentStub(it) } + } +} + +class TypeParameterType( + val name: String, + override val nullable: Boolean, + val typeParameterDeclaration: TypeParameterStub +) : StubType() { + override val typeArguments: List = emptyList() +} + +fun KotlinType.toStubIrType(): StubType = when (this) { + is KotlinFunctionType -> this.toStubIrType() + is KotlinClassifierType -> this.toStubIrType() + else -> error("Unexpected KotlinType: $this") +} + +private fun KotlinFunctionType.toStubIrType(): StubType = + FunctionalType(parameterTypes.map(KotlinType::toStubIrType), returnType.toStubIrType(), nullable) + +private fun KotlinClassifierType.toStubIrType(): StubType { + val typeArguments = arguments.map(KotlinTypeArgument::toStubIrType) + PredefinedTypesHandler.tryExpandPredefinedTypealias(classifier, nullable, typeArguments)?.let { return it } + return if (underlyingType == null) { + ClassifierStubType(classifier, typeArguments, nullable) + } else { + AbbreviatedType(underlyingType.toStubIrType(), classifier, typeArguments, nullable) + } +} + +private fun KotlinTypeArgument.toStubIrType(): TypeArgument = when (this) { + is KotlinType -> TypeArgumentStub(this.toStubIrType()) + StarProjection -> TypeArgument.StarProjection + else -> error("Unexpected KotlinTypeArgument: $this") +} + +/** + * Types that come from kotlinx.cinterop require special handling because we + * don't have explicit information about their structure. + * For example, to be able to produce metadata-based interop library we need to know + * that ByteVar is a typealias to ByteVarOf. + */ +private object PredefinedTypesHandler { + private const val cInteropPackage = "kotlinx.cinterop" + + private val nativePtrClassifier = Classifier.topLevel(cInteropPackage, "NativePtr") + + private val primitives = setOf( + KotlinTypes.boolean, + KotlinTypes.byte, KotlinTypes.short, KotlinTypes.int, KotlinTypes.long, + KotlinTypes.uByte, KotlinTypes.uShort, KotlinTypes.uInt, KotlinTypes.uLong, + KotlinTypes.float, KotlinTypes.double, + KotlinTypes.vector128 + ) + + /** + * kotlinx.cinterop.{primitive}Var -> kotlin.{primitive} + */ + private val primitiveVarClassifierToPrimitiveType: Map = + primitives.associateBy { + val typeVar = "${it.classifier.topLevelName}Var" + Classifier.topLevel(cInteropPackage, typeVar) + } + + /** + * @param primitiveType primitive type from kotlin package. + * @return kotlinx.cinterop.[primitiveType]VarOf<[primitiveType]> + */ + private fun getVarOfTypeFor(primitiveType: KotlinClassifierType, nullable: Boolean): ClassifierStubType { + val typeVarOf = "${primitiveType.classifier.topLevelName}VarOf" + val classifier = Classifier.topLevel(cInteropPackage, typeVarOf) + return ClassifierStubType(classifier, listOf(TypeArgumentStub(primitiveType.toStubIrType())), nullable = nullable) + } + + private fun expandCOpaquePointerVar(nullable: Boolean): AbbreviatedType { + val typeArgument = TypeArgumentStub(expandCOpaquePointer(nullable=false)) + val underlyingType = ClassifierStubType( + KotlinTypes.cPointerVarOf, listOf(typeArgument), nullable = nullable + ) + return AbbreviatedType(underlyingType, KotlinTypes.cOpaquePointerVar.classifier, emptyList(), nullable) + } + + private fun expandCOpaquePointer(nullable: Boolean): AbbreviatedType { + val typeArgument = TypeArgumentStub(ClassifierStubType(KotlinTypes.cPointed), TypeArgument.Variance.OUT) + val underlyingType = ClassifierStubType( + KotlinTypes.cPointer, listOf(typeArgument), nullable = nullable + ) + return AbbreviatedType(underlyingType, KotlinTypes.cOpaquePointer.classifier, emptyList(), nullable) + } + + private fun expandCPointerVar(typeArguments: List, nullable: Boolean): AbbreviatedType { + require(typeArguments.size == 1) { "CPointerVar has only one type argument." } + val cPointer = ClassifierStubType(KotlinTypes.cPointer, typeArguments) + val cPointerVarOfTypeArgument = TypeArgumentStub(cPointer) + val underlyingType = ClassifierStubType( + KotlinTypes.cPointerVarOf, listOf(cPointerVarOfTypeArgument), nullable = nullable + ) + return AbbreviatedType(underlyingType, KotlinTypes.cPointerVar, typeArguments, nullable) + } + + /** + * @param primitiveVarType one of kotlinx.cinterop.{primitive}Var types. + * @return typealias in terms of StubIR types. + */ + private fun expandPrimitiveVarType(primitiveVarClassifier: Classifier, nullable: Boolean): AbbreviatedType { + val primitiveType = primitiveVarClassifierToPrimitiveType.getValue(primitiveVarClassifier) + val underlyingType = getVarOfTypeFor(primitiveType, nullable) + return AbbreviatedType(underlyingType, primitiveVarClassifier, listOf(), nullable) + } + + private fun expandNativePtr(platform: KotlinPlatform, nullable: Boolean): StubType { + val underlyingTypeClassifier = when (platform) { + KotlinPlatform.JVM -> KotlinTypes.long.classifier + KotlinPlatform.NATIVE -> Classifier.topLevel("kotlin.native.internal", "NativePtr") + } + val underlyingType = ClassifierStubType(underlyingTypeClassifier, nullable = nullable) + return AbbreviatedType(underlyingType, nativePtrClassifier, listOf(), nullable) + } + + private fun expandObjCObjectMeta(typeArguments: List, nullable: Boolean): AbbreviatedType { + require(typeArguments.isEmpty()) + val objCClass = ClassifierStubType(KotlinTypes.objCClass, emptyList(), nullable) + return AbbreviatedType(objCClass, KotlinTypes.objCObjectMeta, emptyList(), nullable) + } + + private fun expandCArrayPointer(typeArguments: List, nullable: Boolean): AbbreviatedType { + val cPointer = ClassifierStubType(KotlinTypes.cPointer, typeArguments) + return AbbreviatedType(cPointer, KotlinTypes.cArrayPointer, typeArguments, nullable) + } + + private fun expandObjCBlockVar(typeArguments: List, nullable: Boolean): AbbreviatedType { + val underlyingType = ClassifierStubType(KotlinTypes.objCNotImplementedVar, typeArguments, nullable) + return AbbreviatedType(underlyingType, KotlinTypes.objCBlockVar, typeArguments, nullable) + } + + /** + * @return [ClassifierStubType] if [classifier] is a typealias from [kotlinx.cinterop] package. + */ + fun tryExpandPredefinedTypealias(classifier: Classifier, nullable: Boolean, typeArguments: List): AbbreviatedType? = + when (classifier) { + in primitiveVarClassifierToPrimitiveType.keys -> expandPrimitiveVarType(classifier, nullable) + KotlinTypes.cOpaquePointer.classifier -> expandCOpaquePointer(nullable) + KotlinTypes.cOpaquePointerVar.classifier -> expandCOpaquePointerVar(nullable) + KotlinTypes.cPointerVar -> expandCPointerVar(typeArguments, nullable) + KotlinTypes.objCObjectMeta -> expandObjCObjectMeta(typeArguments, nullable) + KotlinTypes.cArrayPointer -> expandCArrayPointer(typeArguments, nullable) + KotlinTypes.objCBlockVar -> expandObjCBlockVar(typeArguments, nullable) + else -> null + } + + /** + * Variant of [tryExpandPredefinedTypealias] with [platform]-dependent result. + */ + fun tryExpandPlatformDependentTypealias( + classifier: Classifier, platform: KotlinPlatform, nullable: Boolean + ): StubType? = + when (classifier) { + nativePtrClassifier -> expandNativePtr(platform, nullable) + else -> null + } +} \ No newline at end of file diff --git a/kotlin-native/Interop/StubGenerator/src/main/kotlin/org/jetbrains/kotlin/native/interop/gen/StubIrVisitor.kt b/kotlin-native/Interop/StubGenerator/src/main/kotlin/org/jetbrains/kotlin/native/interop/gen/StubIrVisitor.kt new file mode 100644 index 00000000000..12c33e7d811 --- /dev/null +++ b/kotlin-native/Interop/StubGenerator/src/main/kotlin/org/jetbrains/kotlin/native/interop/gen/StubIrVisitor.kt @@ -0,0 +1,22 @@ +/* + * Copyright 2010-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ +package org.jetbrains.kotlin.native.interop.gen + +interface StubIrVisitor { + + fun visitClass(element: ClassStub, data: T): R + + fun visitTypealias(element: TypealiasStub, data: T): R + + fun visitFunction(element: FunctionStub, data: T): R + + fun visitProperty(element: PropertyStub, data: T): R + + fun visitConstructor(constructorStub: ConstructorStub, data: T): R + + fun visitPropertyAccessor(propertyAccessor: PropertyAccessor, data: T): R + + fun visitSimpleStubContainer(simpleStubContainer: SimpleStubContainer, data: T): R +} \ No newline at end of file diff --git a/kotlin-native/Interop/StubGenerator/src/main/kotlin/org/jetbrains/kotlin/native/interop/gen/TypeUtils.kt b/kotlin-native/Interop/StubGenerator/src/main/kotlin/org/jetbrains/kotlin/native/interop/gen/TypeUtils.kt new file mode 100644 index 00000000000..8bc3a60255f --- /dev/null +++ b/kotlin-native/Interop/StubGenerator/src/main/kotlin/org/jetbrains/kotlin/native/interop/gen/TypeUtils.kt @@ -0,0 +1,100 @@ +/* + * Copyright 2010-2017 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.jetbrains.kotlin.native.interop.gen + +import org.jetbrains.kotlin.native.interop.indexer.* + +val EnumDef.isAnonymous: Boolean + get() = spelling.contains("(anonymous ") // TODO: it is a hack + +val StructDecl.isAnonymous: Boolean + get() = spelling.contains("(anonymous ") // TODO: it is a hack + +/** + * Returns the expression which could be used for this type in C code. + * Note: the resulting string doesn't exactly represent this type, but it is enough for current purposes. + * + * TODO: use libclang to implement? + */ +fun Type.getStringRepresentation(): String = when (this) { + VoidType -> "void" + CharType -> "char" + CBoolType -> "_Bool" + ObjCBoolType -> "BOOL" + is IntegerType -> this.spelling + is FloatingType -> this.spelling + + is VectorType -> this.spelling + is PointerType -> getPointerTypeStringRepresentation(this.pointeeType) + is ArrayType -> getPointerTypeStringRepresentation(this.elemType) + + is RecordType -> this.decl.spelling + + is EnumType -> if (this.def.isAnonymous) { + this.def.baseType.getStringRepresentation() + } else { + this.def.spelling + } + + is Typedef -> this.def.aliased.getStringRepresentation() + + is ObjCPointer -> when (this) { + is ObjCIdType -> "id$protocolQualifier" + is ObjCClassPointer -> "Class$protocolQualifier" + is ObjCObjectPointer -> "${def.name}$protocolQualifier*" + is ObjCInstanceType -> TODO(this.toString()) // Must have already been handled. + is ObjCBlockPointer -> "id" + } + + else -> throw NotImplementedError() +} + +fun getPointerTypeStringRepresentation(pointee: Type): String = + (getStringRepresentationOfPointee(pointee) ?: "void") + "*" + +private fun getStringRepresentationOfPointee(type: Type): String? { + val unwrapped = type.unwrapTypedefs() + + return when (unwrapped) { + is PrimitiveType -> unwrapped.getStringRepresentation() + is PointerType -> getStringRepresentationOfPointee(unwrapped.pointeeType)?.plus("*") + is RecordType -> if (unwrapped.decl.isAnonymous || unwrapped.decl.spelling == "struct __va_list_tag") { + null + } else { + unwrapped.decl.spelling + } + else -> null + } +} + +private val ObjCQualifiedPointer.protocolQualifier: String + get() = if (this.protocols.isEmpty()) "" else " <${protocols.joinToString { it.name }}>" + +fun blockTypeStringRepresentation(type: ObjCBlockPointer): String { + return buildString { + append(type.returnType.getStringRepresentation()) + append("(^)") + append("(") + val blockParameters = if (type.parameterTypes.isEmpty()) { + "void" + } else { + type.parameterTypes.joinToString { it.getStringRepresentation() } + } + append(blockParameters) + append(")") + } +} diff --git a/kotlin-native/Interop/StubGenerator/src/main/kotlin/org/jetbrains/kotlin/native/interop/gen/defFileDependencies.kt b/kotlin-native/Interop/StubGenerator/src/main/kotlin/org/jetbrains/kotlin/native/interop/gen/defFileDependencies.kt new file mode 100644 index 00000000000..3badf996c6b --- /dev/null +++ b/kotlin-native/Interop/StubGenerator/src/main/kotlin/org/jetbrains/kotlin/native/interop/gen/defFileDependencies.kt @@ -0,0 +1,164 @@ +package org.jetbrains.kotlin.native.interop.gen + +import org.jetbrains.kotlin.konan.util.DefFile +import org.jetbrains.kotlin.native.interop.gen.jvm.KotlinPlatform +import org.jetbrains.kotlin.native.interop.gen.jvm.buildNativeLibrary +import org.jetbrains.kotlin.native.interop.gen.jvm.prepareTool +import org.jetbrains.kotlin.native.interop.indexer.NativeLibraryHeaders +import org.jetbrains.kotlin.native.interop.indexer.getHeaderPaths +import org.jetbrains.kotlin.native.interop.tool.CInteropArguments +import java.io.File + +fun defFileDependencies(args: Array) { + val defFiles = mutableListOf() + val targets = mutableListOf() + + var index = 0 + while (index < args.size) { + val arg = args[index] + + ++index + + when (arg) { + "-target" -> { + targets += args[index] + ++index + } + else -> { + defFiles.add(File(arg)) + } + } + } + + defFileDependencies(makeDependencyAssigner(targets, defFiles)) +} + +private fun makeDependencyAssigner(targets: List, defFiles: List) = + CompositeDependencyAssigner(targets.map { makeDependencyAssignerForTarget(it, defFiles) }) + +private fun makeDependencyAssignerForTarget(target: String, defFiles: List): SingleTargetDependencyAssigner { + val tool = prepareTool(target, KotlinPlatform.NATIVE) + val cinteropArguments = CInteropArguments() + cinteropArguments.argParser.parse(arrayOf()) + val libraries = defFiles.associateWith { + buildNativeLibrary( + tool, + DefFile(it, tool.substitutions), + cinteropArguments, + ImportsImpl(emptyMap()) + ).getHeaderPaths() + } + return SingleTargetDependencyAssigner(libraries) +} + +private fun defFileDependencies(dependencyAssigner: DependencyAssigner) { + while (!dependencyAssigner.isDone()) { + val (file, depends) = dependencyAssigner.getReady().entries.sortedBy { it.key }.first() + dependencyAssigner.markDone(file) + patchDepends(file, depends.sorted()) + println("${file.name} done.") + } +} + +private fun patchDepends(file: File, newDepends: List) { + val defFileLines = file.readLines() + val dependsLine = buildString { + append("depends =") + newDepends.forEach { + append(" ") + append(it) + } + } + val newDefFileLines = listOf(dependsLine) + defFileLines.filter { !it.startsWith("depends =") } + + file.bufferedWriter().use { writer -> + newDefFileLines.forEach { writer.appendLine(it) } + } +} + +private interface DependencyAssigner { + fun isDone(): Boolean + fun getReady(): Map> + fun markDone(file: File) +} + +private class CompositeDependencyAssigner(val dependencyAssigners: List) : DependencyAssigner { + override fun isDone(): Boolean = dependencyAssigners.all { it.isDone() } + + override fun getReady(): Map> { + return dependencyAssigners.map { it.getReady() }.reduce { left, right -> + (left.keys intersect right.keys) + .associateWith { left.getValue(it) union right.getValue(it) } + }.also { + require(it.isNotEmpty()) { "incompatible dependencies" } // TODO: add more info. + } + } + + override fun markDone(file: File) { + dependencyAssigners.forEach { it.markDone(file) } + } +} + +private class SingleTargetDependencyAssigner( + defFilesToHeaders: Map> +) : DependencyAssigner { + private val pendingDefFilesToHeaders = defFilesToHeaders.toMutableMap() + + private val processedHeadersToDefFiles = mutableMapOf() + + init { + val ownedHeaders = pendingDefFilesToHeaders.values.flatMap { it.ownHeaders } + val unownedHeadersToDefFiles = mutableMapOf() + + pendingDefFilesToHeaders.forEach { (def, lib) -> + (lib.importedHeaders - ownedHeaders).forEach { + unownedHeadersToDefFiles.putIfAbsent(it, def) + } + } + + if (unownedHeadersToDefFiles.isNotEmpty()) { + error("Unowned headers:\n" + + unownedHeadersToDefFiles.entries.joinToString("\n") { "${it.key}\n imported by: ${it.value.name}" }) + } + } + + override fun isDone(): Boolean = pendingDefFilesToHeaders.isEmpty() + + override fun getReady(): Map> { + val result = mutableMapOf>() + + defFiles@for ((defFile, headers) in pendingDefFilesToHeaders) { + val depends = mutableSetOf() + + headers@for (header in (headers.ownHeaders + headers.importedHeaders)) { + val dependency = processedHeadersToDefFiles[header] + ?: if (header in headers.ownHeaders) continue@headers else continue@defFiles + + depends.add(dependency.nameWithoutExtension) + } + result[defFile] = depends + } + + if (result.isEmpty()) { + pendingDefFilesToHeaders.entries.forEach { (def, headers) -> + println(def.name) + println("Own headers:") + headers.ownHeaders.forEach { println(it) } + println("Unowned imported headers:") + headers.importedHeaders.forEach { if (it !in processedHeadersToDefFiles) println(it) } + println() + } + error("Cyclic dependency? Remaining libs:\n" + pendingDefFilesToHeaders.keys.joinToString("\n") { it.name }) + } + + return result + } + + override fun markDone(file: File) { + val headers = pendingDefFilesToHeaders.remove(file)!! + + headers.ownHeaders.forEach { + processedHeadersToDefFiles.putIfAbsent(it, file) + } + } +} \ No newline at end of file diff --git a/kotlin-native/Interop/StubGenerator/src/main/kotlin/org/jetbrains/kotlin/native/interop/gen/jvm/CommandLine.kt b/kotlin-native/Interop/StubGenerator/src/main/kotlin/org/jetbrains/kotlin/native/interop/gen/jvm/CommandLine.kt new file mode 100644 index 00000000000..e4a9a1bb23b --- /dev/null +++ b/kotlin-native/Interop/StubGenerator/src/main/kotlin/org/jetbrains/kotlin/native/interop/gen/jvm/CommandLine.kt @@ -0,0 +1,136 @@ +/* + * Copyright 2010-2017 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.jetbrains.kotlin.native.interop.tool + +import kotlinx.cli.ArgParser +import kotlinx.cli.ArgType +import kotlinx.cli.* + +const val HEADER_FILTER_ADDITIONAL_SEARCH_PREFIX = "headerFilterAdditionalSearchPrefix" +const val NODEFAULTLIBS_DEPRECATED = "nodefaultlibs" +const val NODEFAULTLIBS = "no-default-libs" +const val NOENDORSEDLIBS = "no-endorsed-libs" +const val PURGE_USER_LIBS = "Xpurge-user-libs" +const val TEMP_DIR = "Xtemporary-files-dir" +const val NOPACK = "nopack" +const val COMPILE_SOURCES = "Xcompile-source" +const val SHORT_MODULE_NAME = "Xshort-module-name" +const val FOREIGN_EXCEPTION_MODE = "Xforeign-exception-mode" + +// TODO: unify camel and snake cases. +// Possible solution is to accept both cases +open class CommonInteropArguments(val argParser: ArgParser) { + val verbose by argParser.option(ArgType.Boolean, description = "Enable verbose logging output").default(false) + val pkg by argParser.option(ArgType.String, description = "place generated bindings to the package") + val output by argParser.option(ArgType.String, shortName = "o", description = "specifies the resulting library file") + .default("nativelib") + val libraryPath by argParser.option(ArgType.String, description = "add a library search path") + .multiple().delimiter(",") + val staticLibrary by argParser.option(ArgType.String, description = "embed static library to the result") + .multiple().delimiter(",") + val library by argParser.option(ArgType.String, shortName = "l", description = "library to use for building") + .multiple() + val repo by argParser.option(ArgType.String, shortName = "r", description = "repository to resolve dependencies") + .multiple() + val mode by argParser.option(ArgType.Choice(listOf(MODE_METADATA, MODE_SOURCECODE)), description = "the way interop library is generated") + .default(DEFAULT_MODE) + val nodefaultlibs by argParser.option(ArgType.Boolean, NODEFAULTLIBS, + description = "don't link the libraries from dist/klib automatically").default(false) + val nodefaultlibsDeprecated by argParser.option(ArgType.Boolean, NODEFAULTLIBS_DEPRECATED, + description = "don't link the libraries from dist/klib automatically", + deprecatedWarning = "Old form of flag. Please, use $NODEFAULTLIBS.").default(false) + val noendorsedlibs by argParser.option(ArgType.Boolean, NOENDORSEDLIBS, + description = "don't link the endorsed libraries from dist automatically").default(false) + val purgeUserLibs by argParser.option(ArgType.Boolean, PURGE_USER_LIBS, + description = "don't link unused libraries even explicitly specified").default(false) + val nopack by argParser.option(ArgType.Boolean, fullName = NOPACK, + description = "Don't pack the produced library into a klib file").default(false) + val tempDir by argParser.option(ArgType.String, TEMP_DIR, + description = "save temporary files to the given directory") + val kotlincOption by argParser.option(ArgType.String, "Xkotlinc-option", + description = "additional kotlinc compiler option").multiple() + + companion object { + const val MODE_SOURCECODE = "sourcecode" + const val MODE_METADATA = "metadata" + + const val DEFAULT_MODE = MODE_METADATA + } +} + +open class CInteropArguments(argParser: ArgParser = + ArgParser("cinterop", + prefixStyle = ArgParser.OptionPrefixStyle.JVM)): CommonInteropArguments(argParser) { + val target by argParser.option(ArgType.String, description = "native target to compile to").default("host") + val def by argParser.option(ArgType.String, description = "the library definition file") + val header by argParser.option(ArgType.String, description = "header file to produce kotlin bindings for") + .multiple().delimiter(",") + val headerFilterPrefix by argParser.option(ArgType.String, HEADER_FILTER_ADDITIONAL_SEARCH_PREFIX, "hfasp", + "header file to produce kotlin bindings for").multiple().delimiter(",") + val compilerOpts by argParser.option(ArgType.String, + description = "additional compiler options (allows to add several options separated by spaces)", + deprecatedWarning = "-compilerOpts is deprecated. Please use -compiler-options.") + .multiple().delimiter(" ") + val compilerOptions by argParser.option(ArgType.String, "compiler-options", + description = "additional compiler options (allows to add several options separated by spaces)") + .multiple().delimiter(" ") + val linkerOpts = argParser.option(ArgType.String, "linkerOpts", + description = "additional linker options (allows to add several options separated by spaces)", + deprecatedWarning = "-linkerOpts is deprecated. Please use -linker-options.") + .multiple().delimiter(" ") + val linkerOptions = argParser.option(ArgType.String, "linker-options", + description = "additional linker options (allows to add several options separated by spaces)") + .multiple().delimiter(" ") + val compilerOption by argParser.option(ArgType.String, "compiler-option", + description = "additional compiler option").multiple() + val linkerOption = argParser.option(ArgType.String, "linker-option", + description = "additional linker option").multiple() + val linker by argParser.option(ArgType.String, description = "use specified linker") + + val compileSource by argParser.option(ArgType.String, + fullName = COMPILE_SOURCES, + description = "additional C/C++ sources to be compiled into resulting library" + ).multiple() + + val sourceCompileOptions by argParser.option(ArgType.String, + fullName = "Xsource-compiler-option", + description = "compiler options for sources provided via -$COMPILE_SOURCES" + ).multiple() + + val shortModuleName by argParser.option(ArgType.String, + fullName = SHORT_MODULE_NAME, + description = "A short name used to denote this library in the IDE" + ) + + val moduleName by argParser.option(ArgType.String, + fullName = "Xmodule-name", + description = "A full name of the library used for dependency resolution" + ) + + val foreignExceptionMode by argParser.option(ArgType.String, FOREIGN_EXCEPTION_MODE, + description = "Handle native exception in Kotlin: ") +} + +class JSInteropArguments(argParser: ArgParser = ArgParser("jsinterop", + prefixStyle = ArgParser.OptionPrefixStyle.JVM)): CommonInteropArguments(argParser) { + val target by argParser.option(ArgType.Choice(listOf("wasm32")), + description = "wasm target to compile to").default("wasm32") +} + +internal fun warn(msg: String) { + println("warning: $msg") +} diff --git a/kotlin-native/Interop/StubGenerator/src/main/kotlin/org/jetbrains/kotlin/native/interop/gen/jvm/GenerationMode.kt b/kotlin-native/Interop/StubGenerator/src/main/kotlin/org/jetbrains/kotlin/native/interop/gen/jvm/GenerationMode.kt new file mode 100644 index 00000000000..6174374932d --- /dev/null +++ b/kotlin-native/Interop/StubGenerator/src/main/kotlin/org/jetbrains/kotlin/native/interop/gen/jvm/GenerationMode.kt @@ -0,0 +1,13 @@ +package org.jetbrains.kotlin.native.interop.gen.jvm + +import org.jetbrains.kotlin.native.interop.tool.CommonInteropArguments + +enum class GenerationMode { + SOURCE_CODE, METADATA +} + +fun parseGenerationMode(mode: String): GenerationMode? = when(mode) { + CommonInteropArguments.MODE_METADATA -> GenerationMode.METADATA + CommonInteropArguments.MODE_SOURCECODE -> GenerationMode.SOURCE_CODE + else -> null +} \ No newline at end of file diff --git a/kotlin-native/Interop/StubGenerator/src/main/kotlin/org/jetbrains/kotlin/native/interop/gen/jvm/InteropConfiguration.kt b/kotlin-native/Interop/StubGenerator/src/main/kotlin/org/jetbrains/kotlin/native/interop/gen/jvm/InteropConfiguration.kt new file mode 100644 index 00000000000..e82e37083a2 --- /dev/null +++ b/kotlin-native/Interop/StubGenerator/src/main/kotlin/org/jetbrains/kotlin/native/interop/gen/jvm/InteropConfiguration.kt @@ -0,0 +1,41 @@ +/* + * Copyright 2010-2017 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.jetbrains.kotlin.native.interop.gen.jvm + +import org.jetbrains.kotlin.konan.target.KonanTarget +import org.jetbrains.kotlin.native.interop.indexer.CompilationWithPCH + +/** + * Describes the native library and the options for adjusting the Kotlin API to be generated for this library. + */ +class InteropConfiguration( + val library: CompilationWithPCH, + val pkgName: String, + val excludedFunctions: Set, + val excludedMacros: Set, + val strictEnums: Set, + val nonStrictEnums: Set, + val noStringConversion: Set, + val exportForwardDeclarations: List, + val disableDesignatedInitializerChecks: Boolean, + val target: KonanTarget +) + +enum class KotlinPlatform { + JVM, + NATIVE +} \ No newline at end of file diff --git a/kotlin-native/Interop/StubGenerator/src/main/kotlin/org/jetbrains/kotlin/native/interop/gen/jvm/InteropLibraryCreation.kt b/kotlin-native/Interop/StubGenerator/src/main/kotlin/org/jetbrains/kotlin/native/interop/gen/jvm/InteropLibraryCreation.kt new file mode 100644 index 00000000000..9aab4724226 --- /dev/null +++ b/kotlin-native/Interop/StubGenerator/src/main/kotlin/org/jetbrains/kotlin/native/interop/gen/jvm/InteropLibraryCreation.kt @@ -0,0 +1,108 @@ +/* + * Copyright 2010-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ +package org.jetbrains.kotlin.native.interop.gen.jvm + +import kotlinx.metadata.* +import kotlinx.metadata.klib.KlibModuleFragmentWriteStrategy +import kotlinx.metadata.klib.KlibModuleMetadata +import kotlinx.metadata.klib.className +import kotlinx.metadata.klib.fqName +import org.jetbrains.kotlin.backend.common.serialization.KlibIrVersion +import org.jetbrains.kotlin.backend.common.serialization.metadata.KlibMetadataVersion +import org.jetbrains.kotlin.konan.CURRENT +import org.jetbrains.kotlin.konan.CompilerVersion +import org.jetbrains.kotlin.konan.file.File +import org.jetbrains.kotlin.konan.library.impl.KonanLibraryWriterImpl +import org.jetbrains.kotlin.konan.target.KonanTarget +import org.jetbrains.kotlin.library.KotlinLibraryVersioning +import org.jetbrains.kotlin.library.KotlinAbiVersion +import org.jetbrains.kotlin.library.KotlinLibrary +import org.jetbrains.kotlin.library.SerializedMetadata +import org.jetbrains.kotlin.library.impl.BuiltInsPlatform +import org.jetbrains.kotlin.util.removeSuffixIfPresent +import java.util.* + +fun createInteropLibrary( + metadata: KlibModuleMetadata, + outputPath: String, + moduleName: String, + nativeBitcodeFiles: List, + target: KonanTarget, + manifest: Properties, + dependencies: List, + nopack: Boolean, + shortName: String?, + staticLibraries: List +) { + val version = KotlinLibraryVersioning( + libraryVersion = null, + abiVersion = KotlinAbiVersion.CURRENT, + compilerVersion = CompilerVersion.CURRENT.toString(), + metadataVersion = KlibMetadataVersion.INSTANCE.toString(), + irVersion = KlibIrVersion.INSTANCE.toString() + ) + val outputPathWithoutExtension = outputPath.removeSuffixIfPresent(".klib") + KonanLibraryWriterImpl( + File(outputPathWithoutExtension), + moduleName, + version, + target, + + BuiltInsPlatform.NATIVE, + nopack = nopack, + shortName = shortName + ).apply { + val serializedMetadata = metadata.write(ChunkingWriteStrategy()) + addMetadata(SerializedMetadata(serializedMetadata.header, serializedMetadata.fragments, serializedMetadata.fragmentNames)) + nativeBitcodeFiles.forEach(this::addNativeBitcode) + addManifestAddend(manifest) + addLinkDependencies(dependencies) + staticLibraries.forEach(this::addIncludedBinary) + commit() + } +} + +// TODO: Consider adding it to kotlinx-metadata-klib. +class ChunkingWriteStrategy( + private val classesChunkSize: Int = 128, + private val packagesChunkSize: Int = 128 +) : KlibModuleFragmentWriteStrategy { + + override fun processPackageParts(parts: List): List { + if (parts.isEmpty()) return emptyList() + val fqName = parts.first().fqName + ?: error("KmModuleFragment should have a not-null fqName!") + val classFragments = parts.flatMap(KmModuleFragment::classes) + .chunked(classesChunkSize) { chunk -> + KmModuleFragment().also { fragment -> + fragment.fqName = fqName + fragment.classes += chunk + chunk.mapTo(fragment.className, KmClass::name) + } + } + val packageFragments = parts.mapNotNull(KmModuleFragment::pkg) + .flatMap { it.functions + it.typeAliases + it.properties } + .chunked(packagesChunkSize) { chunk -> + KmModuleFragment().also { fragment -> + fragment.fqName = fqName + fragment.pkg = KmPackage().also { pkg -> + pkg.fqName = fqName + pkg.properties += chunk.filterIsInstance() + pkg.functions += chunk.filterIsInstance() + pkg.typeAliases += chunk.filterIsInstance() + } + } + } + val result = classFragments + packageFragments + return if (result.isEmpty()) { + // We still need to emit empty packages because they may + // represent parts of package declaration (e.g. platform.[]). + // Tooling (e.g. `klib contents`) expects this kind of behavior. + parts + } else { + result + } + } +} \ No newline at end of file diff --git a/kotlin-native/Interop/StubGenerator/src/main/kotlin/org/jetbrains/kotlin/native/interop/gen/jvm/ToolConfig.kt b/kotlin-native/Interop/StubGenerator/src/main/kotlin/org/jetbrains/kotlin/native/interop/gen/jvm/ToolConfig.kt new file mode 100644 index 00000000000..fa38a9a686a --- /dev/null +++ b/kotlin-native/Interop/StubGenerator/src/main/kotlin/org/jetbrains/kotlin/native/interop/gen/jvm/ToolConfig.kt @@ -0,0 +1,57 @@ +/* + * Copyright 2010-2017 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.jetbrains.kotlin.native.interop.tool + +import org.jetbrains.kotlin.konan.target.HostManager +import org.jetbrains.kotlin.konan.target.KonanTarget +import org.jetbrains.kotlin.konan.target.PlatformManager +import org.jetbrains.kotlin.konan.target.customerDistribution +import org.jetbrains.kotlin.konan.util.KonanHomeProvider +import org.jetbrains.kotlin.konan.util.defaultTargetSubstitutions +import org.jetbrains.kotlin.native.interop.gen.jvm.KotlinPlatform + +class ToolConfig(userProvidedTargetName: String?, flavor: KotlinPlatform) { + + private val konanHome = KonanHomeProvider.determineKonanHome() + private val distribution = customerDistribution(konanHome) + private val platformManager = PlatformManager(distribution) + private val targetManager = platformManager.targetManager(userProvidedTargetName) + private val host = HostManager.host + val target = targetManager.target + + private val platform = platformManager.platform(target) + + val clang = platform.clang + + val substitutions = defaultTargetSubstitutions(target) + + fun downloadDependencies() = platform.downloadDependencies() + + val defaultCompilerOpts = + platform.clang.targetLibclangArgs.toList() + + val platformCompilerOpts = if (flavor == KotlinPlatform.JVM) + platform.clang.hostCompilerArgsForJni.toList() else emptyList() + + val llvmHome = platform.absoluteLlvmHome + val sysRoot = platform.absoluteTargetSysRoot + + val libclang = when (host) { + KonanTarget.MINGW_X64 -> "$llvmHome/bin/libclang.dll" + else -> "$llvmHome/lib/${System.mapLibraryName("clang")}" + } +} diff --git a/kotlin-native/Interop/StubGenerator/src/main/kotlin/org/jetbrains/kotlin/native/interop/gen/jvm/main.kt b/kotlin-native/Interop/StubGenerator/src/main/kotlin/org/jetbrains/kotlin/native/interop/gen/jvm/main.kt new file mode 100644 index 00000000000..7fdcf966774 --- /dev/null +++ b/kotlin-native/Interop/StubGenerator/src/main/kotlin/org/jetbrains/kotlin/native/interop/gen/jvm/main.kt @@ -0,0 +1,527 @@ +/* + * Copyright 2010-2017 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.jetbrains.kotlin.native.interop.gen.jvm + +import org.jetbrains.kotlin.konan.TempFiles +import org.jetbrains.kotlin.konan.exec.Command +import org.jetbrains.kotlin.konan.util.DefFile +import org.jetbrains.kotlin.native.interop.gen.* +import org.jetbrains.kotlin.native.interop.gen.wasm.processIdlLib +import org.jetbrains.kotlin.native.interop.indexer.* +import org.jetbrains.kotlin.native.interop.tool.* +import kotlinx.cli.ArgParser +import kotlinx.cli.ArgType +import kotlinx.cli.default +import kotlinx.cli.required +import org.jetbrains.kotlin.konan.ForeignExceptionMode +import org.jetbrains.kotlin.konan.library.* +import org.jetbrains.kotlin.konan.target.CompilerOutputKind +import org.jetbrains.kotlin.konan.target.Distribution +import org.jetbrains.kotlin.konan.target.KonanTarget +import org.jetbrains.kotlin.konan.util.KonanHomeProvider +import org.jetbrains.kotlin.library.KotlinLibrary +import org.jetbrains.kotlin.library.packageFqName +import org.jetbrains.kotlin.library.resolver.impl.KotlinLibraryResolverImpl +import org.jetbrains.kotlin.library.resolver.impl.libraryResolver +import org.jetbrains.kotlin.library.toUnresolvedLibraries +import org.jetbrains.kotlin.util.removeSuffixIfPresent +import java.io.File +import java.lang.IllegalArgumentException +import java.nio.file.* +import java.util.* + +data class InternalInteropOptions(val generated: String, val natives: String, val manifest: String? = null, + val cstubsName: String? = null) + +fun main(args: Array) { + // Adding flavor option for interop plugin. + class FullCInteropArguments: CInteropArguments() { + val flavor by argParser.option(ArgType.Choice(listOf("jvm", "native", "wasm")), description = "Interop target") + .default("jvm") + val generated by argParser.option(ArgType.String, description = "place generated bindings to the directory") + .required() + val natives by argParser.option(ArgType.String, description = "where to put the built native files") + .required() + } + val arguments = FullCInteropArguments() + arguments.argParser.parse(args) + val flavorName = arguments.flavor + processCLib(flavorName, arguments, InternalInteropOptions(arguments.generated, arguments.natives)) +} + +fun interop( + flavor: String, args: Array, + additionalArgs: InternalInteropOptions +): Array? = when(flavor) { + "jvm", "native" -> { + val cinteropArguments = CInteropArguments() + cinteropArguments.argParser.parse(args) + processCLib(flavor, cinteropArguments, additionalArgs) + } + "wasm" -> processIdlLib(args, additionalArgs) + else -> error("Unexpected flavor") + } + +// Options, whose values are space-separated and can be escaped. +val escapedOptions = setOf("-compilerOpts", "-linkerOpts", "-compiler-options", "-linker-options") + +private fun String.asArgList(key: String) = + if (escapedOptions.contains(key)) + this.split(Regex("(? Collection.atMostOne(): T? { + return when (this.size) { + 0 -> null + 1 -> this.iterator().next() + else -> throw IllegalArgumentException("Collection has more than one element.") + } +} + +private fun List?.isTrue(): Boolean { + // The rightmost wins, null != "true". + return this?.last() == "true" +} + +private fun runCmd(command: Array, verbose: Boolean = false) { + Command(*command).getOutputLines(true).let { lines -> + if (verbose) lines.forEach(::println) + } +} + +private fun Properties.storeProperties(file: File) { + file.outputStream().use { + this.store(it, null) + } +} + +private fun Properties.putAndRunOnReplace(key: Any, newValue: Any, beforeReplace: (Any, Any, Any) -> Unit) { + val oldValue = this[key] + if (oldValue != null && oldValue != newValue) { + beforeReplace(key, oldValue, newValue) + } + this[key] = newValue +} + +private fun selectNativeLanguage(config: DefFile.DefFileConfig): Language { + val languages = mapOf( + "C" to Language.C, + "Objective-C" to Language.OBJECTIVE_C + ) + + val language = config.language ?: return Language.C + + return languages[language] ?: + error("Unexpected language '$language'. Possible values are: ${languages.keys.joinToString { "'$it'" }}") +} + +private fun parseImports(dependencies: List): ImportsImpl = + dependencies.filterIsInstance().mapNotNull { library -> + // TODO: handle missing properties? + library.packageFqName?.let { packageFqName -> + val headerIds = library.includedHeaders + headerIds.map { HeaderId(it) to PackageInfo(packageFqName, library) } + } + }.reversed().flatten().toMap().let(::ImportsImpl) + +fun getCompilerFlagsForVfsOverlay(headerFilterPrefix: Array, def: DefFile): List { + val relativeToRoot = mutableMapOf() // TODO: handle clashes + + val filteredIncludeDirs = headerFilterPrefix .map { Paths.get(it) } + if (filteredIncludeDirs.isNotEmpty()) { + val headerFilterGlobs = def.config.headerFilter + if (headerFilterGlobs.isEmpty()) { + error("'$HEADER_FILTER_ADDITIONAL_SEARCH_PREFIX' option requires " + + "'headerFilter' to be specified in .def file") + } + + relativeToRoot += findFilesByGlobs(roots = filteredIncludeDirs, globs = headerFilterGlobs) + } + + if (relativeToRoot.isEmpty()) { + return emptyList() + } + + val virtualRoot = Paths.get(System.getProperty("java.io.tmpdir")).resolve("konanSystemInclude") + + val virtualPathToReal = relativeToRoot.map { (relativePath, realRoot) -> + virtualRoot.resolve(relativePath) to realRoot.resolve(relativePath) + }.toMap() + + val vfsOverlayFile = createVfsOverlayFile(virtualPathToReal) + + return listOf("-I${virtualRoot.toAbsolutePath()}", "-ivfsoverlay", vfsOverlayFile.toAbsolutePath().toString()) +} + +private fun findFilesByGlobs(roots: List, globs: List): Map { + val relativeToRoot = mutableMapOf() + + val pathMatchers = globs.map { FileSystems.getDefault().getPathMatcher("glob:$it") } + + roots.reversed() + .filter { path -> + return@filter when { + path.toFile().exists() -> true + else -> { warn("$path doesn't exist"); false } + } + } + .forEach { root -> + // TODO: don't scan the entire tree, skip subdirectories according to globs. + Files.walk(root, FileVisitOption.FOLLOW_LINKS).forEach { path -> + val relativePath = root.relativize(path) + if (!Files.isDirectory(path) && pathMatchers.any { it.matches(relativePath) }) { + relativeToRoot[relativePath] = root + } + } + } + return relativeToRoot +} + +private fun processCLib(flavorName: String, cinteropArguments: CInteropArguments, + additionalArgs: InternalInteropOptions): Array? { + val ktGenRoot = additionalArgs.generated + val nativeLibsDir = additionalArgs.natives + val flavor = KotlinPlatform.values().single { it.name.equals(flavorName, ignoreCase = true) } + val defFile = cinteropArguments.def?.let { File(it) } + val manifestAddend = additionalArgs.manifest?.let { File(it) } + + if (defFile == null && cinteropArguments.pkg == null) { + cinteropArguments.argParser.printError("-def or -pkg should be provided!") + } + + val tool = prepareTool(cinteropArguments.target, flavor) + + val def = DefFile(defFile, tool.substitutions) + val isLinkerOptsSetByUser = (cinteropArguments.linkerOpts.valueOrigin == ArgParser.ValueOrigin.SET_BY_USER) || + (cinteropArguments.linkerOptions.valueOrigin == ArgParser.ValueOrigin.SET_BY_USER) || + (cinteropArguments.linkerOption.valueOrigin == ArgParser.ValueOrigin.SET_BY_USER) + if (flavorName == "native" && isLinkerOptsSetByUser) { + warn("-linker-option(s)/-linkerOpts option is not supported by cinterop. Please add linker options to .def file or binary compilation instead.") + } + + val additionalLinkerOpts = cinteropArguments.linkerOpts.value.toTypedArray() + cinteropArguments.linkerOption.value.toTypedArray() + + cinteropArguments.linkerOptions.value.toTypedArray() + val verbose = cinteropArguments.verbose + + val language = selectNativeLanguage(def.config) + + val entryPoint = def.config.entryPoints.atMostOne() + val linkerOpts = + def.config.linkerOpts.toTypedArray() + + tool.defaultCompilerOpts + + additionalLinkerOpts + val linkerName = cinteropArguments.linker ?: def.config.linker + val linker = "${tool.llvmHome}/bin/$linkerName" + val compiler = "${tool.llvmHome}/bin/clang" + val excludedFunctions = def.config.excludedFunctions.toSet() + val excludedMacros = def.config.excludedMacros.toSet() + val staticLibraries = def.config.staticLibraries + cinteropArguments.staticLibrary.toTypedArray() + val libraryPaths = def.config.libraryPaths + cinteropArguments.libraryPath.toTypedArray() + val fqParts = (cinteropArguments.pkg ?: def.config.packageName)?.split('.') + ?: defFile!!.name.split('.').reversed().drop(1) + + val outKtPkg = fqParts.joinToString(".") + + val mode = run { + val providedMode = parseGenerationMode(cinteropArguments.mode) + ?: error ("Unexpected interop generation mode: ${cinteropArguments.mode}") + + if (providedMode == GenerationMode.METADATA && flavor == KotlinPlatform.JVM) { + warn("Metadata mode isn't supported for Kotlin/JVM! Falling back to sourcecode.") + GenerationMode.SOURCE_CODE + } else { + providedMode + } + } + + val resolver = getLibraryResolver(cinteropArguments, tool.target) + + val allLibraryDependencies = when (flavor) { + KotlinPlatform.NATIVE -> resolveDependencies(resolver, cinteropArguments) + else -> listOf() + } + + val libName = additionalArgs.cstubsName ?: fqParts.joinToString("") + "stubs" + + val tempFiles = TempFiles(libName, cinteropArguments.tempDir) + + val imports = parseImports(allLibraryDependencies) + + val library = buildNativeLibrary(tool, def, cinteropArguments, imports) + + val (nativeIndex, compilation) = buildNativeIndex(library, verbose) + + // Our current approach to arm64_32 support is to compile armv7k version of bitcode + // for arm64_32. That's the reason for this substitution. + // TODO: Add proper support with the next LLVM update. + val target = when (tool.target) { + KonanTarget.WATCHOS_ARM64 -> KonanTarget.WATCHOS_ARM32 + else -> tool.target + } + + val klibSuffix = CompilerOutputKind.LIBRARY.suffix(target) + val moduleName = cinteropArguments.moduleName + ?: File(cinteropArguments.output).name.removeSuffixIfPresent(klibSuffix) + + val configuration = InteropConfiguration( + library = compilation, + pkgName = outKtPkg, + excludedFunctions = excludedFunctions, + excludedMacros = excludedMacros, + strictEnums = def.config.strictEnums.toSet(), + nonStrictEnums = def.config.nonStrictEnums.toSet(), + noStringConversion = def.config.noStringConversion.toSet(), + exportForwardDeclarations = def.config.exportForwardDeclarations, + disableDesignatedInitializerChecks = def.config.disableDesignatedInitializerChecks, + target = target + ) + + + File(nativeLibsDir).mkdirs() + val outCFile = tempFiles.create(libName, ".${language.sourceFileExtension}") + + val logger = if (verbose) { + { message: String -> println(message) } + } else { + {} + } + + val stubIrContext = StubIrContext(logger, configuration, nativeIndex, imports, flavor, mode, libName) + val stubIrOutput = run { + val outKtFileCreator = { + val outKtFileName = fqParts.last() + ".kt" + val outKtFileRelative = (fqParts + outKtFileName).joinToString("/") + val file = File(ktGenRoot, outKtFileRelative) + file.parentFile.mkdirs() + file + } + val driverOptions = StubIrDriver.DriverOptions(entryPoint, moduleName, File(outCFile.absolutePath), outKtFileCreator) + val stubIrDriver = StubIrDriver(stubIrContext, driverOptions) + stubIrDriver.run() + } + + // TODO: if a library has partially included headers, then it shouldn't be used as a dependency. + def.manifestAddendProperties["includedHeaders"] = nativeIndex.includedHeaders.joinToString(" ") { it.value } + + def.manifestAddendProperties.putAndRunOnReplace("package", outKtPkg) { + _, oldValue, newValue -> + warn("The package value `$oldValue` specified in .def file is overridden with explicit $newValue") + } + def.manifestAddendProperties["interop"] = "true" + if (stubIrOutput is StubIrDriver.Result.Metadata) { + def.manifestAddendProperties["ir_provider"] = KLIB_INTEROP_IR_PROVIDER_IDENTIFIER + } + stubIrContext.addManifestProperties(def.manifestAddendProperties) + + // cinterop command line option overrides def file property + val foreignExceptionMode = cinteropArguments.foreignExceptionMode?: def.config.foreignExceptionMode + foreignExceptionMode?.let { + def.manifestAddendProperties[ForeignExceptionMode.manifestKey] = + ForeignExceptionMode.byValue(it).value // may throw IllegalArgumentException + } + + manifestAddend?.parentFile?.mkdirs() + manifestAddend?.let { def.manifestAddendProperties.storeProperties(it) } + + val compilerArgs = stubIrContext.libraryForCStubs.compilerArgs.toTypedArray() + val nativeOutputPath: String = when (flavor) { + KotlinPlatform.JVM -> { + val outOFile = tempFiles.create(libName,".o") + val compilerCmd = arrayOf(compiler, *compilerArgs, + "-c", outCFile.absolutePath, "-o", outOFile.absolutePath) + runCmd(compilerCmd, verbose) + + val outLib = File(nativeLibsDir, System.mapLibraryName(libName)) + val linkerCmd = arrayOf(linker, + outOFile.absolutePath, "-shared", "-o", outLib.absolutePath, + *linkerOpts) + runCmd(linkerCmd, verbose) + outOFile.absolutePath + } + KotlinPlatform.NATIVE -> { + val outLib = File(nativeLibsDir, "$libName.bc") + val compilerCmd = arrayOf(compiler, *compilerArgs, + "-emit-llvm", "-c", outCFile.absolutePath, "-o", outLib.absolutePath) + + runCmd(compilerCmd, verbose) + outLib.absolutePath + } + } + + val compiledFiles = compileSources(nativeLibsDir, tool, cinteropArguments) + + return when (stubIrOutput) { + is StubIrDriver.Result.SourceCode -> { + val bitcodePaths = compiledFiles.map { listOf("-native-library", it) }.flatten() + argsToCompiler(staticLibraries, libraryPaths) + bitcodePaths + } + is StubIrDriver.Result.Metadata -> { + val stdlibDependency = resolver.resolveWithDependencies( + emptyList(), + noDefaultLibs = true, + noEndorsedLibs = true + ).getFullList() + createInteropLibrary( + metadata = stubIrOutput.metadata, + nativeBitcodeFiles = compiledFiles + nativeOutputPath, + target = tool.target, + moduleName = moduleName, + outputPath = cinteropArguments.output, + manifest = def.manifestAddendProperties, + dependencies = stdlibDependency + imports.requiredLibraries.toList(), + nopack = cinteropArguments.nopack, + shortName = cinteropArguments.shortModuleName, + staticLibraries = resolveLibraries(staticLibraries, libraryPaths) + ) + return null + } + } +} + +private fun compileSources( + nativeLibsDir: String, + toolConfig: ToolConfig, + cinteropArguments: CInteropArguments +): List = cinteropArguments.compileSource.mapIndexed { index, source -> + // Mangle file name to avoid collisions. + val mangledFileName = "${index}_${File(source).nameWithoutExtension}" + val outputFileName = "$nativeLibsDir/${mangledFileName}.bc" + val compilerArgs = cinteropArguments.sourceCompileOptions.toTypedArray() + val compilerCmd = toolConfig.clang.clangCXX(*compilerArgs, source, "-emit-llvm", "-c", "-o", outputFileName) + runCmd(compilerCmd.toTypedArray(), verbose = cinteropArguments.verbose) + outputFileName +} + +private fun getLibraryResolver( + cinteropArguments: CInteropArguments, target: KonanTarget +): KotlinLibraryResolverImpl { + val libraries = cinteropArguments.library + val repos = cinteropArguments.repo + return defaultResolver( + repos, + libraries.filter { it.contains(org.jetbrains.kotlin.konan.file.File.separator) }, + target, + Distribution(KonanHomeProvider.determineKonanHome()) + ).libraryResolver() +} + +private fun resolveDependencies( + resolver: KotlinLibraryResolverImpl, cinteropArguments: CInteropArguments +): List { + val libraries = cinteropArguments.library + val noDefaultLibs = cinteropArguments.nodefaultlibs || cinteropArguments.nodefaultlibsDeprecated + val noEndorsedLibs = cinteropArguments.noendorsedlibs + return resolver.resolveWithDependencies( + libraries.toUnresolvedLibraries, + noStdLib = false, + noDefaultLibs = noDefaultLibs, + noEndorsedLibs = noEndorsedLibs + ).getFullList() +} + +internal fun prepareTool(target: String?, flavor: KotlinPlatform): ToolConfig { + val tool = ToolConfig(target, flavor) + tool.downloadDependencies() + + System.load(tool.libclang) + + return tool +} + +internal fun buildNativeLibrary( + tool: ToolConfig, + def: DefFile, + arguments: CInteropArguments, + imports: ImportsImpl +): NativeLibrary { + val additionalHeaders = (arguments.header).toTypedArray() + val additionalCompilerOpts = (arguments.compilerOpts + + arguments.compilerOptions + arguments.compilerOption).toTypedArray() + + val headerFiles = def.config.headers + additionalHeaders + val language = selectNativeLanguage(def.config) + val compilerOpts: List = mutableListOf().apply { + addAll(def.config.compilerOpts) + addAll(tool.defaultCompilerOpts) + // We compile with -O2 because Clang may insert inline asm in bitcode at -O0. + // It is undesirable in case of watchos_arm64 since we target armv7k + // for this target instead of arm64_32 because it is not supported in LLVM 8. + // + // Note that PCH and the *.c file should be compiled with the same optimization level. + add("-O2") + addAll(additionalCompilerOpts) + addAll(getCompilerFlagsForVfsOverlay(arguments.headerFilterPrefix.toTypedArray(), def)) + addAll(when (language) { + Language.C -> emptyList() + Language.OBJECTIVE_C -> { + // "Objective-C" within interop means "Objective-C with ARC": + listOf("-fobjc-arc") + // Using this flag here has two effects: + // 1. The headers are parsed with ARC enabled, thus the API is visible correctly. + // 2. The generated Objective-C stubs are compiled with ARC enabled, so reference counting + // calls are inserted automatically. + } + }) + } + + val compilation = CompilationImpl( + includes = headerFiles, + additionalPreambleLines = def.defHeaderLines, + compilerArgs = compilerOpts + tool.platformCompilerOpts, + language = language + ) + + val headerFilter: NativeLibraryHeaderFilter + val includes: List + + val modules = def.config.modules + + if (modules.isEmpty()) { + val excludeDependentModules = def.config.excludeDependentModules + + val headerFilterGlobs = def.config.headerFilter + val headerInclusionPolicy = HeaderInclusionPolicyImpl(headerFilterGlobs) + + headerFilter = NativeLibraryHeaderFilter.NameBased(headerInclusionPolicy, excludeDependentModules) + includes = headerFiles + } else { + require(language == Language.OBJECTIVE_C) { "cinterop supports 'modules' only when 'language = Objective-C'" } + require(headerFiles.isEmpty()) { "cinterop doesn't support having headers and modules specified at the same time" } + require(def.config.headerFilter.isEmpty()) { "cinterop doesn't support 'headerFilter' with 'modules'" } + + val modulesInfo = getModulesInfo(compilation, modules) + + headerFilter = NativeLibraryHeaderFilter.Predefined(modulesInfo.ownHeaders) + includes = modulesInfo.topLevelHeaders + } + + val excludeSystemLibs = def.config.excludeSystemLibs + + val headerExclusionPolicy = HeaderExclusionPolicyImpl(imports) + + return NativeLibrary( + includes = includes, + additionalPreambleLines = compilation.additionalPreambleLines, + compilerArgs = compilation.compilerArgs, + headerToIdMapper = HeaderToIdMapper(sysRoot = tool.sysRoot), + language = compilation.language, + excludeSystemLibs = excludeSystemLibs, + headerExclusionPolicy = headerExclusionPolicy, + headerFilter = headerFilter + ) +} diff --git a/kotlin-native/Interop/StubGenerator/src/main/kotlin/org/jetbrains/kotlin/native/interop/gen/wasm/StubGenerator.kt b/kotlin-native/Interop/StubGenerator/src/main/kotlin/org/jetbrains/kotlin/native/interop/gen/wasm/StubGenerator.kt new file mode 100644 index 00000000000..908f445c100 --- /dev/null +++ b/kotlin-native/Interop/StubGenerator/src/main/kotlin/org/jetbrains/kotlin/native/interop/gen/wasm/StubGenerator.kt @@ -0,0 +1,410 @@ +package org.jetbrains.kotlin.native.interop.gen.wasm + +import org.jetbrains.kotlin.konan.file.File +import org.jetbrains.kotlin.native.interop.gen.argsToCompiler +import org.jetbrains.kotlin.native.interop.gen.wasm.idl.* +import org.jetbrains.kotlin.native.interop.gen.jvm.InternalInteropOptions +import org.jetbrains.kotlin.native.interop.tool.JSInteropArguments + +fun kotlinHeader(packageName: String): String { + return "package $packageName\n" + + "import kotlinx.wasm.jsinterop.*\n" +} + +fun Type.toKotlinType(argName: String? = null): String = when (this) { + is idlVoid -> "Unit" + is idlInt -> "Int" + is idlFloat -> "Float" + is idlDouble -> "Double" + is idlString -> "String" + is idlObject -> "JsValue" + is idlFunction -> "KtFunction" + is idlInterfaceRef -> name + else -> error("Unexpected type") +} + +fun Arg.wasmMapping(): String = when (type) { + is idlVoid -> error("An arg can not be idlVoid") + is idlInt -> name + is idlFloat -> name + is idlDouble -> "doubleUpper($name), doubleLower($name)" + is idlString -> "stringPointer($name), stringLengthBytes($name)" + is idlObject -> TODO("implement me") + is idlFunction -> "wrapFunction($name), ArenaManager.currentArena" + is idlInterfaceRef -> TODO("Implement me") + else -> error("Unexpected type") +} + +fun Type.wasmReturnArg(): String = + when (this) { + is idlVoid -> "ArenaManager.currentArena" // TODO: optimize. + is idlInt -> "ArenaManager.currentArena" + is idlFloat -> "ArenaManager.currentArena" + is idlDouble -> "ArenaManager.currentArena" + is idlString -> "ArenaManager.currentArena" + is idlObject -> "ArenaManager.currentArena" + is idlFunction -> "ArenaManager.currentArena" + is idlInterfaceRef -> "ArenaManager.currentArena" + else -> error("Unexpected type") + } +val Operation.wasmReturnArg: String get() = returnType.wasmReturnArg() +val Attribute.wasmReturnArg: String get() = type.wasmReturnArg() + +fun Arg.wasmArgNames(): List = when (type) { + is idlVoid -> error("An arg can not be idlVoid") + is idlInt -> listOf(name) + is idlFloat -> listOf(name) + is idlDouble -> listOf("${name}Upper", "${name}Lower") + is idlString -> listOf("${name}Ptr", "${name}Len") + is idlObject -> TODO("implement me (idlObject)") + is idlFunction -> listOf("${name}Index", "${name}ResultArena") + is idlInterfaceRef -> TODO("Implement me (idlInterfaceRef)") + else -> error("Unexpected type") +} + +fun Type.wasmReturnMapping(value: String): String = when (this) { + is idlVoid -> "" + is idlInt -> value + is idlFloat -> value + is idlDouble -> value + is idlString -> "TODO(\"Implement me\")" + is idlObject -> "JsValue(ArenaManager.currentArena, $value)" + is idlFunction -> "TODO(\"Implement me\")" + is idlInterfaceRef -> "$name(ArenaManager.currentArena, $value)" + else -> error("Unexpected type") +} + +fun wasmFunctionName(functionName: String, interfaceName: String) + = "knjs__${interfaceName}_$functionName" + +fun wasmSetterName(propertyName: String, interfaceName: String) + = "knjs_set__${interfaceName}_$propertyName" + +fun wasmGetterName(propertyName: String, interfaceName: String) + = "knjs_get__${interfaceName}_$propertyName" + +val Operation.kotlinTypeParameters: String get() { + val lambdaRetTypes = args.filter { it.type is idlFunction } + .map { "R${it.name}" }. joinToString(", ") + return if (lambdaRetTypes == "") "" else "<$lambdaRetTypes>" +} + +val Interface.wasmReceiverArgs get() = + if (isGlobal) emptyList() + else listOf("this.arena", "this.index") + +fun Member.wasmReceiverArgs(parent: Interface) = + if (isStatic) emptyList() + else parent.wasmReceiverArgs + +fun Type.generateKotlinCall(name: String, wasmArgList: String) = + "$name($wasmArgList)" + +fun Type.generateKotlinCallWithReturn(name: String, wasmArgList: String) = + when(this) { + is idlVoid -> " ${generateKotlinCall(name, wasmArgList)}\n" + is idlDouble -> " ${generateKotlinCall(name, wasmArgList)}\n" + + " val wasmRetVal = ReturnSlot_getDouble()\n" + + else -> " val wasmRetVal = ${generateKotlinCall(name, wasmArgList)}\n" + } + +fun Operation.generateKotlinCallWithReturn(parent_name: String, wasmArgList: String) = + returnType.generateKotlinCallWithReturn( + wasmFunctionName(name, parent_name), + wasmArgList) + +fun Attribute.generateKotlinGetterCallWithReturn(parent_name: String, wasmArgList: String) = + type.generateKotlinCallWithReturn( + wasmGetterName(name, parent_name), + wasmArgList) + +fun Operation.generateKotlin(parent: Interface): String { + val argList = args.map { + "${it.name}: ${it.type.toKotlinType(it.name)}" + }.joinToString(", ") + + val wasmArgList = (wasmReceiverArgs(parent) + args.map(Arg::wasmMapping) + wasmReturnArg).joinToString(", ") + + // TODO: there can be multiple Rs. + return " fun $kotlinTypeParameters $name(" + + argList + + "): ${returnType.toKotlinType()} {\n" + + generateKotlinCallWithReturn(parent.name, wasmArgList) + + " return ${returnType.wasmReturnMapping("wasmRetVal")}\n"+ + " }\n\n" +} + +fun Attribute.generateKotlinSetter(parent: Interface): String { + val kotlinType = type.toKotlinType(name) + return " set(value: $kotlinType) {\n" + + " ${wasmSetterName(name, parent.name)}(" + + (wasmReceiverArgs(parent) + Arg("value", type).wasmMapping()).joinToString(", ") + + ")\n" + + " }\n\n" +} + +fun Attribute.generateKotlinGetter(parent: Interface): String { + val wasmArgList = (wasmReceiverArgs(parent) + wasmReturnArg).joinToString(", ") + return " get() {\n" + + generateKotlinGetterCallWithReturn(parent.name, wasmArgList) + + " return ${type.wasmReturnMapping("wasmRetVal")}\n"+ + " }\n\n" +} + +fun Attribute.generateKotlin(parent: Interface): String { + val kotlinType = type.toKotlinType(name) + val varOrVal = if (readOnly) "val" else "var" + return " $varOrVal $name: $kotlinType\n" + + generateKotlinGetter(parent) + + if (!readOnly) generateKotlinSetter(parent) else "" +} + +val Interface.wasmTypedReceiverArgs get() = + if (isGlobal) emptyList() + else listOf("arena: Int", "index: Int") + +fun Member.wasmTypedReceiverArgs(parent: Interface) = + if (isStatic) emptyList() else parent.wasmTypedReceiverArgs + +fun Operation.generateWasmStub(parent: Interface): String { + val wasmName = wasmFunctionName(this.name, parent.name) + val allArgs = (wasmTypedReceiverArgs(parent) + args.toList().wasmTypedMapping() + wasmTypedReturnMapping).joinToString(", ") + return "@SymbolName(\"$wasmName\")\n" + + "external public fun $wasmName($allArgs): ${returnType.wasmReturnTypeMapping()}\n\n" +} +fun Attribute.generateWasmSetterStub(parent: Interface): String { + val wasmSetter = wasmSetterName(this.name, parent.name) + val allArgs = (wasmTypedReceiverArgs(parent) + Arg("value", this.type).wasmTypedMapping()).joinToString(", ") + return "@SymbolName(\"$wasmSetter\")\n" + + "external public fun $wasmSetter($allArgs): Unit\n\n" +} +fun Attribute.generateWasmGetterStub(parent: Interface): String { + val wasmGetter = wasmGetterName(this.name, parent.name) + val allArgs = (wasmTypedReceiverArgs(parent) + wasmTypedReturnMapping).joinToString(", ") + return "@SymbolName(\"$wasmGetter\")\n" + + "external public fun $wasmGetter($allArgs): Int\n\n" +} +fun Attribute.generateWasmStubs(parent: Interface) = + generateWasmGetterStub(parent) + + if (!readOnly) generateWasmSetterStub(parent) else "" + +// TODO: consider using virtual methods +fun Member.generateKotlin(parent: Interface): String = when (this) { + is Operation -> this.generateKotlin(parent) + is Attribute -> this.generateKotlin(parent) + else -> error("Unexpected member") +} + +// TODO: consider using virtual methods +fun Member.generateWasmStub(parent: Interface) = + when (this) { + is Operation -> this.generateWasmStub(parent) + is Attribute -> this.generateWasmStubs(parent) + else -> error("Unexpected member") + + } + +fun Arg.wasmTypedMapping() + = this.wasmArgNames().map { "$it: Int" } .joinToString(", ") + +// TODO: Optimize for simple types. +fun Type.wasmTypedReturnMapping(): String = "resultArena: Int" + +val Operation.wasmTypedReturnMapping get() = returnType.wasmTypedReturnMapping() + +val Attribute.wasmTypedReturnMapping get() = type.wasmTypedReturnMapping() + +fun List.wasmTypedMapping():List + = this.map(Arg::wasmTypedMapping) + +// TODO: more complex return types, such as returning a pair of Ints +// will require a more complex approach. +fun Type.wasmReturnTypeMapping() + = if (this == idlVoid) "Unit" else "Int" + +fun Interface.generateMemberWasmStubs() = + members.map { + it.generateWasmStub(this) + }.joinToString("") + +fun Interface.generateKotlinMembers() = + members.filterNot { it.isStatic } .map { + it.generateKotlin(this) + }.joinToString("") + +fun Interface.generateKotlinCompanion() = + " companion object {\n" + + members.filter { it.isStatic } .map { + it.generateKotlin(this) + }.joinToString("") + + " }\n" + +fun Interface.generateKotlinClassHeader() = + "open class $name(arena: Int, index: Int): JsValue(arena, index) {\n" + + " constructor(jsValue: JsValue): this(jsValue.arena, jsValue.index)\n" + +fun Interface.generateKotlinClassFooter() = + "}\n" + +fun Interface.generateKotlinClassConverter() = + "val JsValue.as$name: $name\n" + + " get() {\n" + + " return $name(this.arena, this.index)\n"+ + " }\n" + +fun Interface.generateKotlin(): String { + fun unlessGlobal(value: () -> String): String { + return if (this.isGlobal) "" else value() + } + + return generateMemberWasmStubs() + + unlessGlobal { generateKotlinClassHeader() } + + generateKotlinMembers() + + unlessGlobal { + generateKotlinCompanion() + + generateKotlinClassFooter() + + generateKotlinClassConverter() + } +} + +fun generateKotlin(pkg: String, interfaces: List) = + kotlinHeader(pkg) + + interfaces.map { + it.generateKotlin() + }.joinToString("\n") + + if (pkg == "kotlinx.interop.wasm.dom") // TODO: make it a general solution. + "fun setInterval(interval: Int, lambda: KtFunction) = setInterval(lambda, interval)\n" + else "" + +///////////////////////////////////////////////////////// + +fun Arg.composeWasmArgs(): String = when (type) { + is idlVoid -> error("An arg can not be idlVoid") + is idlInt -> "" + is idlFloat -> "" + is idlDouble -> + " var $name = twoIntsToDouble(${name}Upper, ${name}Lower);\n" + is idlString -> + " var $name = toUTF16String(${name}Ptr, ${name}Len);\n" + is idlObject -> TODO("implement me") + is idlFunction -> + " var $name = konan_dependencies.env.Konan_js_wrapLambda(lambdaResultArena, ${name}Index);\n" + + is idlInterfaceRef -> TODO("Implement me") + else -> error("Unexpected type") +} + +val Interface.receiver get() = + if (isGlobal) "" else "kotlinObject(arena, obj)." + +fun Member.receiver(parent: Interface) = + if (isStatic) "${parent.name}." else parent.receiver + +val Interface.wasmReceiverArgName get() = + if (isGlobal) emptyList() else listOf("arena", "obj") + +fun Member.wasmReceiverArgName(parent: Interface) = + if (isStatic) emptyList() else parent.wasmReceiverArgName + +val Operation.wasmReturnArgName get() = + returnType.wasmReturnArgName + +val Attribute.wasmReturnArgName get() = + type.wasmReturnArgName + +val Type.wasmReturnArgName get() = + when (this) { + is idlVoid -> emptyList() + is idlInt -> emptyList() + is idlFloat -> emptyList() + is idlDouble -> emptyList() + is idlString -> listOf("resultArena") + is idlObject -> listOf("resultArena") + is idlInterfaceRef -> listOf("resultArena") + else -> error("Unexpected type: $this") + } + +val Type.wasmReturnExpression get() = + when(this) { + is idlVoid -> "" + is idlInt -> "result" + is idlFloat -> "result" // TODO: can we really pass floats as is? + is idlDouble -> "doubleToReturnSlot(result)" + is idlString -> "toArena(resultArena, result)" + is idlObject -> "toArena(resultArena, result)" + is idlInterfaceRef -> "toArena(resultArena, result)" + else -> error("Unexpected type: $this") + } + +fun Operation.generateJs(parent: Interface): String { + val allArgs = wasmReceiverArgName(parent) + args.map { it.wasmArgNames() }.flatten() + wasmReturnArgName + val wasmMapping = allArgs.joinToString(", ") + val argList = args.map { it.name }. joinToString(", ") + val composedArgsList = args.map { it.composeWasmArgs() }. joinToString("") + + return "\n ${wasmFunctionName(this.name, parent.name)}: function($wasmMapping) {\n" + + composedArgsList + + " var result = ${receiver(parent)}$name($argList);\n" + + " return ${returnType.wasmReturnExpression};\n" + + " }" +} + +fun Attribute.generateJsSetter(parent: Interface): String { + val valueArg = Arg("value", type) + val allArgs = wasmReceiverArgName(parent) + valueArg.wasmArgNames() + val wasmMapping = allArgs.joinToString(", ") + return "\n ${wasmSetterName(name, parent.name)}: function($wasmMapping) {\n" + + valueArg.composeWasmArgs() + + " ${receiver(parent)}$name = value;\n" + + " }" +} + +fun Attribute.generateJsGetter(parent: Interface): String { + val allArgs = wasmReceiverArgName(parent) + wasmReturnArgName + val wasmMapping = allArgs.joinToString(", ") + return "\n ${wasmGetterName(name, parent.name)}: function($wasmMapping) {\n" + + " var result = ${receiver(parent)}$name;\n" + + " return ${type.wasmReturnExpression};\n" + + " }" +} + +fun Attribute.generateJs(parent: Interface) = + generateJsGetter(parent) + + if (!readOnly) ",\n${generateJsSetter(parent)}" else "" + +fun Member.generateJs(parent: Interface): String = when (this) { + is Operation -> this.generateJs(parent) + is Attribute -> this.generateJs(parent) + else -> error("Unexpected member") +} + +fun generateJs(interfaces: List): String = + "konan.libraries.push ({\n" + + interfaces.map { interf -> + interf.members.map { member -> + member.generateJs(interf) + } + }.flatten() .joinToString(",\n") + + "\n})\n" + +const val idlMathPackage = "kotlinx.interop.wasm.math" +const val idlDomPackage = "kotlinx.interop.wasm.dom" + +fun processIdlLib(args: Array, additionalArgs: InternalInteropOptions): Array { + val jsInteropArguments = JSInteropArguments() + jsInteropArguments.argParser.parse(args) + // TODO: Refactor me. + val ktGenRoot = File(additionalArgs.generated).mkdirs() + val nativeLibsDir = File(additionalArgs.natives).mkdirs() + + val idl = when (jsInteropArguments.pkg) { + idlMathPackage -> idlMath + idlDomPackage -> idlDom + else -> throw IllegalArgumentException("Please choose either $idlMathPackage or $idlDomPackage for -pkg argument") + } + File(ktGenRoot, "kotlin_stubs.kt").writeText(generateKotlin(jsInteropArguments.pkg!!, idl)) + File(nativeLibsDir, "js_stubs.js").writeText(generateJs(idl)) + File((additionalArgs.manifest)!!).writeText("") // The manifest is currently unused for wasm. + return argsToCompiler(jsInteropArguments.staticLibrary.toTypedArray(), jsInteropArguments.libraryPath.toTypedArray()) +} diff --git a/kotlin-native/Interop/StubGenerator/src/main/kotlin/org/jetbrains/kotlin/native/interop/gen/wasm/idl/dom.kt b/kotlin-native/Interop/StubGenerator/src/main/kotlin/org/jetbrains/kotlin/native/interop/gen/wasm/idl/dom.kt new file mode 100644 index 00000000000..0d799ce7671 --- /dev/null +++ b/kotlin-native/Interop/StubGenerator/src/main/kotlin/org/jetbrains/kotlin/native/interop/gen/wasm/idl/dom.kt @@ -0,0 +1,50 @@ +package org.jetbrains.kotlin.native.interop.gen.wasm.idl + +// This shall be an output of Web IDL parser. +val idlDom = listOf( + Interface("Context", + Attribute("lineWidth", idlInt), + Attribute("fillStyle", idlString), + Attribute("strokeStyle", idlString), + + Operation("lineTo", idlVoid, Arg("x", idlInt), Arg("y", idlInt)), + Operation("moveTo", idlVoid, Arg("x", idlInt), Arg("y", idlInt)), + Operation("beginPath", idlVoid), + Operation("stroke", idlVoid), + Operation("fillRect", idlVoid, Arg("x", idlInt), Arg("y", idlInt), Arg("width", idlInt), Arg("height", idlInt)), + Operation("fillText", idlVoid, Arg("test", idlString), Arg("x", idlInt), Arg("y", idlInt), Arg("maxWidth", idlInt)), + Operation("fill", idlVoid), + Operation("closePath", idlVoid) + ), + Interface("DOMRect", + Attribute("left", idlInt), + Attribute("right", idlInt), + Attribute("top", idlInt), + Attribute("bottom", idlInt) + ), + Interface("Canvas", + Operation("getContext", idlInterfaceRef("Context"), Arg("context", idlString)), + Operation("getBoundingClientRect", idlInterfaceRef("DOMRect")) + ), + Interface("Document", + Operation("getElementById", idlObject, Arg("id", idlString)) + ), + Interface("MouseEvent", + Attribute("clientX", idlInt, readOnly = true), + Attribute("clientY", idlInt, readOnly = true) + ), + Interface("Response", + Operation("json", idlObject) + ), + Interface("Promise", + Operation("then", idlInterfaceRef("Promise"), Arg("lambda", idlFunction)) + ), + Interface("__Global", + Attribute("document", idlInterfaceRef("Document"), readOnly = true), + + Operation("fetch", idlInterfaceRef("Promise"), Arg("url", idlString)), + Operation("setInterval", idlVoid, Arg("lambda", idlFunction), Arg("interval", idlInt)) + ) +) + + diff --git a/kotlin-native/Interop/StubGenerator/src/main/kotlin/org/jetbrains/kotlin/native/interop/gen/wasm/idl/idl.kt b/kotlin-native/Interop/StubGenerator/src/main/kotlin/org/jetbrains/kotlin/native/interop/gen/wasm/idl/idl.kt new file mode 100644 index 00000000000..0ccbd8e8fca --- /dev/null +++ b/kotlin-native/Interop/StubGenerator/src/main/kotlin/org/jetbrains/kotlin/native/interop/gen/wasm/idl/idl.kt @@ -0,0 +1,37 @@ +package org.jetbrains.kotlin.native.interop.gen.wasm.idl + +// This is (as of now) a poor man's IDL representation. + +interface Type +interface Member { + val isStatic: Boolean get() = false +} + +object idlVoid: Type +object idlInt: Type +object idlFloat: Type +object idlDouble: Type +object idlString: Type +object idlObject: Type +object idlFunction: Type + +data class Attribute(val name: String, val type: Type, + val readOnly: Boolean = false, + override val isStatic: Boolean = false): Member + +data class Arg(val name: String, val type: Type) + +class Operation(val name: String, val returnType: Type, + override val isStatic: Boolean = false, + vararg val args: Arg): Member { + + constructor(name: String, returnType: Type, vararg args: Arg) : + this(name, returnType, false, *args) +} + +data class idlInterfaceRef(val name: String): Type +class Interface(val name: String, vararg val members: Member) { + val isGlobal = (name == "__Global") +} + + diff --git a/kotlin-native/Interop/StubGenerator/src/main/kotlin/org/jetbrains/kotlin/native/interop/gen/wasm/idl/idlMath.kt b/kotlin-native/Interop/StubGenerator/src/main/kotlin/org/jetbrains/kotlin/native/interop/gen/wasm/idl/idlMath.kt new file mode 100644 index 00000000000..4b6bc871eb0 --- /dev/null +++ b/kotlin-native/Interop/StubGenerator/src/main/kotlin/org/jetbrains/kotlin/native/interop/gen/wasm/idl/idlMath.kt @@ -0,0 +1,73 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.jetbrains.kotlin.native.interop.gen.wasm.idl + +// There are no WebIDL descriptions of Math, +// so in any case this one will be a part of the project. +// Although, may be in the form of our own WebIDL source. + +val idlMath = listOf( + Interface("Math", + Attribute("E", idlDouble, readOnly = true, isStatic = true), + Attribute("LN2", idlDouble, readOnly = true, isStatic = true), + Attribute("LN10", idlDouble, readOnly = true, isStatic = true), + Attribute("LOG2E", idlDouble, readOnly = true, isStatic = true), + Attribute("LOG10E", idlDouble, readOnly = true, isStatic = true), + Attribute("PI", idlDouble, readOnly = true, isStatic = true), + Attribute("SQRT1_2", idlDouble, readOnly = true, isStatic = true), + Attribute("SQRT2", idlDouble, readOnly = true, isStatic = true), + + Operation("abs", idlDouble, true, Arg("x", idlDouble)), + Operation("acos", idlDouble, true, Arg("x", idlDouble)), + Operation("acosh", idlDouble, true, Arg("x", idlDouble)), + Operation("asin", idlDouble, true, Arg("x", idlDouble)), + Operation("asinh", idlDouble, true, Arg("x", idlDouble)), + Operation("atan", idlDouble, true, Arg("x", idlDouble)), + Operation("atanh", idlDouble, true, Arg("x", idlDouble)), + Operation("atan2", idlDouble, true, Arg("y", idlDouble), Arg("x", idlDouble)), + Operation("cbrt", idlDouble, true, Arg("x", idlDouble)), + Operation("ceil", idlDouble, true, Arg("x", idlDouble)), + Operation("clz32", idlDouble, true, Arg("x", idlDouble)), + Operation("cos", idlDouble, true, Arg("x", idlDouble)), + Operation("cosh", idlDouble, true, Arg("x", idlDouble)), + Operation("exp", idlDouble, true, Arg("x", idlDouble)), + Operation("expm1", idlDouble, true, Arg("x", idlDouble)), + Operation("floor", idlDouble, true, Arg("x", idlDouble)), + Operation("fround", idlDouble, true, Arg("x", idlDouble)), + //Operation("imul(x, y), + Operation("log", idlDouble, true, Arg("x", idlDouble)), + Operation("log1p", idlDouble, true, Arg("x", idlDouble)), + Operation("log10", idlDouble, true, Arg("x", idlDouble)), + Operation("log2", idlDouble, true, Arg("x", idlDouble)), + Operation("pow", idlDouble, true, Arg("x", idlDouble), Arg("y", idlDouble)), + Operation("random", idlDouble, true), + Operation("round", idlDouble, true, Arg("x", idlDouble)), + Operation("sign", idlDouble, true, Arg("x", idlDouble)), + Operation("sin", idlDouble, true, Arg("x", idlDouble)), + Operation("sinh", idlDouble, true, Arg("x", idlDouble)), + Operation("sqrt", idlDouble, true, Arg("x", idlDouble)), + Operation("tan", idlDouble, true, Arg("x", idlDouble)), + Operation("tanh", idlDouble, true, Arg("x", idlDouble)), + Operation("trunc", idlDouble, true, Arg("x", idlDouble)), + + // Actually these functions have vararg parameter. + // But their kotlin analogs have only 2 parameters so we don't need to support varargs here. + Operation("hypot", idlDouble, true, Arg("x", idlDouble), Arg("y", idlDouble)), + Operation("max", idlDouble, true, Arg("x", idlDouble), Arg("y", idlDouble)), + Operation("min", idlDouble, true, Arg("x", idlDouble), Arg("y", idlDouble)) + ) +) diff --git a/kotlin-native/Interop/StubGenerator/src/test/kotlin/org/jetbrains/kotlin/native/interop/gen/StubIrToMetadataTests.kt b/kotlin-native/Interop/StubGenerator/src/test/kotlin/org/jetbrains/kotlin/native/interop/gen/StubIrToMetadataTests.kt new file mode 100644 index 00000000000..d9ce4d66188 --- /dev/null +++ b/kotlin-native/Interop/StubGenerator/src/test/kotlin/org/jetbrains/kotlin/native/interop/gen/StubIrToMetadataTests.kt @@ -0,0 +1,102 @@ +package org.jetbrains.kotlin.native.interop.gen + +import kotlinx.metadata.KmAnnotationArgument +import kotlinx.metadata.KmClassifier +import kotlinx.metadata.KmModuleFragment +import kotlinx.metadata.klib.compileTimeValue +import kotlinx.metadata.klib.uniqId +import org.jetbrains.kotlin.native.interop.indexer.FunctionDecl +import org.jetbrains.kotlin.native.interop.indexer.IntegerConstantDef +import org.jetbrains.kotlin.native.interop.indexer.IntegerType +import org.junit.Test +import kotlin.test.assertEquals +import kotlin.test.assertNotNull +import kotlin.test.assertTrue + +class StubIrToMetadataTests { + + companion object { + val intStubType = ClassifierStubType(Classifier.topLevel("kotlin", "Int")) + val intType = IntegerType(4, true, "int") + } + + private fun createTrivialFunction(name: String): FunctionStub { + val cDeclaration = FunctionDecl(name, emptyList(), intType, "", false, false) + val origin = StubOrigin.Function(cDeclaration) + return FunctionStub( + name = cDeclaration.name, + returnType = intStubType, + parameters = listOf(), + origin = origin, + annotations = emptyList(), + external = true, + receiver = null, + modality = MemberStubModality.FINAL + ) + } + + private fun createTrivialIntegerConstantProperty(name: String, value: Long): PropertyStub { + val origin = StubOrigin.Constant(IntegerConstantDef(name, intType, value)) + return PropertyStub( + name = name, + type = intStubType, + kind = PropertyStub.Kind.Constant(IntegralConstantStub(value, intType.size, true)), + origin = origin + ) + } + + private fun createMetadata( + fqName: String, + functions: List = emptyList(), + properties: List = emptyList() + ) = SimpleStubContainer(functions = functions, properties = properties) + .let { ModuleMetadataEmitter(fqName, it).emit() } + .also(this::checkUniqIdPresence) + + private fun checkUniqIdPresence(metadata: KmModuleFragment) { + metadata.classes.forEach { assertNotNull(it.uniqId) } + metadata.pkg?.let { pkg -> + pkg.functions.forEach { assertNotNull(it.uniqId) } + pkg.properties.forEach { assertNotNull(it.uniqId) } + pkg.typeAliases.forEach { assertNotNull(it.uniqId) } + } + } + + @Test + fun `single simple function`() { + val packageName = "single_function" + val function = createTrivialFunction("hello") + val metadata = createMetadata(packageName, functions = listOf(function)) + with (metadata) { + assertEquals(packageName, packageName) + assertTrue(classes.isEmpty()) + assertNotNull(pkg) + assertTrue(pkg!!.functions.size == 1) + + val kmFunction = pkg!!.functions[0] + assertEquals(kmFunction.name, function.name) + assertEquals(0, kmFunction.valueParameters.size) + val returnTypeClassifier = kmFunction.returnType.classifier + assertTrue(returnTypeClassifier is KmClassifier.Class) + assertEquals("kotlin/Int", returnTypeClassifier.name) + } + } + + @Test + fun `single constant`() { + val property = createTrivialIntegerConstantProperty("meaning", 42) + val metadata = createMetadata("single_property", properties = listOf(property)) + with (metadata) { + assertNotNull(pkg) + assertTrue(pkg!!.properties.size == 1) + + val kmProperty = pkg!!.properties[0] + assertEquals(kmProperty.name, property.name) + + val compileTimeValue = kmProperty.compileTimeValue + assertNotNull(compileTimeValue) + assertTrue(compileTimeValue is KmAnnotationArgument.IntValue) + assertEquals(42, compileTimeValue.value) + } + } +} \ No newline at end of file diff --git a/kotlin-native/LIBRARIES.md b/kotlin-native/LIBRARIES.md new file mode 100644 index 00000000000..72d9c005776 --- /dev/null +++ b/kotlin-native/LIBRARIES.md @@ -0,0 +1,245 @@ +# Kotlin/Native libraries + +## Kotlin compiler specifics + +To produce a library with the Kotlin/Native compiler use the `-produce library` or `-p library` flag. For example: + +

+ +```bash +$ kotlinc foo.kt -p library -o bar +``` + +
+ +the above command will produce a `bar.klib` with the compiled contents of `foo.kt`. + +To link to a library use the `-library ` or `-l ` flag. For example: + +
+ +```bash +$ kotlinc qux.kt -l bar +``` + +
+ + +the above command will produce a `program.kexe` out of `qux.kt` and `bar.klib` + + +## cinterop tool specifics + +The **cinterop** tool produces `.klib` wrappers for native libraries as its main output. +For example, using the simple `libgit2.def` native library definition file provided in your Kotlin/Native distribution + +
+ +```bash +$ cinterop -def samples/gitchurn/src/nativeInterop/cinterop/libgit2.def -compiler-option -I/usr/local/include -o libgit2 +``` + +
+ +we will obtain `libgit2.klib`. + +See more details in [INTEROP.md](INTEROP.md) + + +## klib utility + +The **klib** library management utility allows you to inspect and install the libraries. + +The following commands are available. + +To list library contents: + +
+ +```bash +$ klib contents +``` + +
+ +To inspect the bookkeeping details of the library + +
+ +```bash +$ klib info +``` + +
+ +To install the library to the default location use + +
+ +```bash +$ klib install +``` + +
+ +To remove the library from the default repository use + +
+ +```bash +$ klib remove +``` + +
+ +All of the above commands accept an additional `-repository ` argument for specifying a repository different to the default one. + +
+ +```bash +$ klib -repository +``` + +
+ + +## Several examples + +First let's create a library. +Place the tiny library source code into `kotlinizer.kt`: + +
+ +```kotlin +package kotlinizer +val String.kotlinized + get() = "Kotlin $this" +``` + +```bash +$ kotlinc kotlinizer.kt -p library -o kotlinizer +``` + +
+ +The library has been created in the current directory: + +
+ +```bash +$ ls kotlinizer.klib +kotlinizer.klib +``` + +
+ +Now let's check out the contents of the library: + +
+ +```bash +$ klib contents kotlinizer +``` + +
+ +We can install `kotlinizer` to the default repository: + +
+ +```bash +$ klib install kotlinizer +``` + +
+ +Remove any traces of it from the current directory: + +
+ +```bash +$ rm kotlinizer.klib +``` + +
+ +Create a very short program and place it into a `use.kt` : + +
+ +```kotlin +import kotlinizer.* + +fun main(args: Array) { + println("Hello, ${"world".kotlinized}!") +} +``` + +
+ +Now compile the program linking with the library we have just created: + +
+ +```bash +$ kotlinc use.kt -l kotlinizer -o kohello +``` + +
+ +And run the program: + +
+ +```bash +$ ./kohello.kexe +Hello, Kotlin world! +``` + +
+ +Have fun! + +# Advanced topics + +## Library search sequence + +When given a `-library foo` flag, the compiler searches the `foo` library in the following order: + + * Current compilation directory or an absolute path. + + * All repositories specified with `-repo` flag. + + * Libraries installed in the default repository (For now the default is `~/.konan`, however it could be changed by setting **KONAN_DATA_DIR** environment variable). + + * Libraries installed in `$installation/klib` directory. + +## The library format + +Kotlin/Native libraries are zip files containing a predefined +directory structure, with the following layout: + +**foo.klib** when unpacked as **foo/** gives us: + +```yaml + - foo/ + - $component_name/ + - ir/ + - Seriaized Kotlin IR. + - targets/ + - $platform/ + - kotlin/ + - Kotlin compiled to LLVM bitcode. + - native/ + - Bitcode files of additional native objects. + - $another_platform/ + - There can be several platform specific kotlin and native pairs. + - linkdata/ + - A set of ProtoBuf files with serialized linkage metadata. + - resources/ + - General resources such as images. (Not used yet). + - manifest - A file in *java property* format describing the library. +``` + +An example layout can be found in `klib/stdlib` directory of your installation. + diff --git a/kotlin-native/LICENSE b/kotlin-native/LICENSE new file mode 100644 index 00000000000..9e385b9d099 --- /dev/null +++ b/kotlin-native/LICENSE @@ -0,0 +1,202 @@ + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright 2000-2020 JetBrains s.r.o. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. diff --git a/kotlin-native/MULTIPLATFORM.md b/kotlin-native/MULTIPLATFORM.md new file mode 100644 index 00000000000..343067047bb --- /dev/null +++ b/kotlin-native/MULTIPLATFORM.md @@ -0,0 +1 @@ +Please refer to the tutorial at https://kotlinlang.org/docs/reference/multiplatform.html for documentation on how to create multiplatform project. diff --git a/kotlin-native/OBJC_INTEROP.md b/kotlin-native/OBJC_INTEROP.md new file mode 100644 index 00000000000..6c49cd061a2 --- /dev/null +++ b/kotlin-native/OBJC_INTEROP.md @@ -0,0 +1,426 @@ +# _Kotlin/Native_ interoperability with Swift/Objective-C + +This document covers some details of Kotlin/Native interoperability with +Swift/Objective-C. + +## Usage + +Kotlin/Native provides bidirectional interoperability with Objective-C. +Objective-C frameworks and libraries can be used in Kotlin code if +properly imported to the build (system frameworks are imported by default). +See e.g. "Using cinterop" in +[Gradle plugin documentation](GRADLE_PLUGIN.md#using-cinterop). +A Swift library can be used in Kotlin code if its API is exported to Objective-C +with `@objc`. Pure Swift modules are not yet supported. + +Kotlin modules can be used in Swift/Objective-C code if compiled into a +framework (see "Targets and output kinds" section in [Gradle plugin documentation](GRADLE_PLUGIN.md#targets-and-output-kinds)). +See [calculator sample](https://github.com/JetBrains/kotlin-native/tree/master/samples/calculator) for an example. + +## Mappings + +The table below shows how Kotlin concepts are mapped to Swift/Objective-C and vice versa. + +"->" and "<-" indicate that mapping only goes one way. + +| Kotlin | Swift | Objective-C | Notes | +| ------ | ----- |------------ | ----- | +| `class` | `class` | `@interface` | [note](#name-translation) | +| `interface` | `protocol` | `@protocol` | | +| `constructor`/`create` | Initializer | Initializer | [note](#initializers) | +| Property | Property | Property | [note](#top-level-functions-and-properties) [note](#setters)| +| Method | Method | Method | [note](#top-level-functions-and-properties) [note](#method-names-translation) | +| `suspend` -> | `completionHandler:` | | [note](#errors-and-exceptions) | +| `@Throws fun` | `throws` | `error:(NSError**)error` | [note](#errors-and-exceptions) | +| Extension | Extension | Category member | [note](#extensions-and-category-members) | +| `companion` member <- | Class method or property | Class method or property | | +| `null` | `nil` | `nil` | | +| `Singleton` | `Singleton()` | `[Singleton singleton]` | [note](#kotlin-singletons) | +| Primitive type | Primitive type / `NSNumber` | | [note](#nsnumber) | +| `Unit` return type | `Void` | `void` | | +| `String` | `String` | `NSString` | | +| `String` | `NSMutableString` | `NSMutableString` | [note](#nsmutablestring) | +| `List` | `Array` | `NSArray` | | +| `MutableList` | `NSMutableArray` | `NSMutableArray` | | +| `Set` | `Set` | `NSSet` | | +| `MutableSet` | `NSMutableSet` | `NSMutableSet` | [note](#collections) | +| `Map` | `Dictionary` | `NSDictionary` | | +| `MutableMap` | `NSMutableDictionary` | `NSMutableDictionary` | [note](#collections) | +| Function type | Function type | Block pointer type | [note](#function-types) | +| Inline classes | Unsupported| Unsupported| [note](#unsupported) | + + +### Name translation + +Objective-C classes are imported into Kotlin with their original names. +Protocols are imported as interfaces with `Protocol` name suffix, +i.e. `@protocol Foo` -> `interface FooProtocol`. +These classes and interfaces are placed into a package [specified in build configuration](#usage) +(`platform.*` packages for preconfigured system frameworks). + +The names of Kotlin classes and interfaces are prefixed when imported to Objective-C. +The prefix is derived from the framework name. + +### Initializers + +Swift/Objective-C initializers are imported to Kotlin as constructors and factory methods +named `create`. The latter happens with initializers declared in the Objective-C category or +as a Swift extension, because Kotlin has no concept of extension constructors. + +Kotlin constructors are imported as initializers to Swift/Objective-C. + +### Setters + +Writeable Objective-C properties overriding read-only properties of the superclass are represented as `setFoo()` method for the property `foo`. Same goes for a protocol's read-only properties that are implemented as mutable. + +### Top-level functions and properties + +Top-level Kotlin functions and properties are accessible as members of special classes. +Each Kotlin file is translated into such a class. E.g. + +
+ +```kotlin +// MyLibraryUtils.kt +package my.library + +fun foo() {} +``` + +
+ +can be called from Swift like + +
+ +```swift +MyLibraryUtilsKt.foo() +``` + +
+ +### Method names translation + +Generally Swift argument labels and Objective-C selector pieces are mapped to Kotlin +parameter names. Anyway these two concepts have different semantics, so sometimes +Swift/Objective-C methods can be imported with a clashing Kotlin signature. In this case +the clashing methods can be called from Kotlin using named arguments, e.g.: + +
+ +```swift +[player moveTo:LEFT byMeters:17] +[player moveTo:UP byInches:42] +``` + +
+ +in Kotlin it would be: + +
+ +```kotlin +player.moveTo(LEFT, byMeters = 17) +player.moveTo(UP, byInches = 42) +``` + +
+ +### Errors and exceptions + +Kotlin has no concept of checked exceptions, all Kotlin exceptions are unchecked. +Swift has only checked errors. So if Swift or Objective-C code calls a Kotlin method +which throws an exception to be handled, then the Kotlin method should be marked +with a `@Throws` annotation specifying a list of "expected" exception classes. + +When compiling to Objective-C/Swift framework, non-`suspend` functions having or inheriting +`@Throws` annotation are represented as `NSError*`-producing methods in Objective-C +and as `throws` methods in Swift. Representations for `suspend` functions always have +`NSError*`/`Error` parameter in completion handler. + +When Kotlin function called from Swift/Objective-C code throws an exception +which is an instance of one of the `@Throws`-specified classes or their subclasses, +it is propagated as `NSError`. Other Kotlin exceptions reaching Swift/Objective-C +are considered unhandled and cause program termination. + +`suspend` functions without `@Throws` propagate only +`CancellationException` as `NSError`. Non-`suspend` functions without `@Throws` +don't propagate Kotlin exceptions at all. + +Note that the opposite reversed translation is not implemented yet: +Swift/Objective-C error-throwing methods aren't imported to Kotlin as +exception-throwing. + +### Extensions and category members + +Members of Objective-C categories and Swift extensions are imported to Kotlin +as extensions. That's why these declarations can't be overridden in Kotlin. +And the extension initializers aren't available as Kotlin constructors. + +Kotlin extensions to "regular" Kotlin classes are imported to Swift and Objective-C as extensions and category members respectively. +Kotlin extensions to other types are treated as [top-level declarations](#top-level-functions-and-properties) +with an additional receiver parameter. These types include: + +* Kotlin `String` type +* Kotlin collection types and subtypes +* Kotlin `interface` types +* Kotlin primitive types +* Kotlin `inline` classes +* Kotlin `Any` type +* Kotlin function types and subtypes +* Objective-C classes and protocols + +### Kotlin singletons + +Kotlin singleton (made with an `object` declaration, including `companion object`) +is imported to Swift/Objective-C as a class with a single instance. +The instance is available through the factory method, i.e. as +`[MySingleton mySingleton]` in Objective-C and `MySingleton()` in Swift. + +### NSNumber + +Kotlin primitive type boxes are mapped to special Swift/Objective-C classes. +For example, `kotlin.Int` box is represented as `KotlinInt` class instance in Swift +(or `${prefix}Int` instance in Objective-C, where `prefix` is the framework names prefix). +These classes are derived from `NSNumber`, so the instances are proper `NSNumber`s +supporting all corresponding operations. + +`NSNumber` type is not automatically translated to Kotlin primitive types +when used as a Swift/Objective-C parameter type or return value. +The reason is that `NSNumber` type doesn't provide enough information +about a wrapped primitive value type, i.e. `NSNumber` is statically not known +to be a e.g. `Byte`, `Boolean`, or `Double`. So Kotlin primitive values +should be cast to/from `NSNumber` manually (see [below](#casting-between-mapped-types)). + +### NSMutableString + +`NSMutableString` Objective-C class is not available from Kotlin. +All instances of `NSMutableString` are copied when passed to Kotlin. + +### Collections + +Kotlin collections are converted to Swift/Objective-C collections as described +in the table above. Swift/Objective-C collections are mapped to Kotlin in the same way, +except for `NSMutableSet` and `NSMutableDictionary`. `NSMutableSet` isn't converted to +a Kotlin `MutableSet`. To pass an object for Kotlin `MutableSet`, +you can create this kind of Kotlin collection explicitly by either creating it +in Kotlin with e.g. `mutableSetOf()`, or using the `KotlinMutableSet` class in Swift +(or `${prefix}MutableSet` in Objective-C, where `prefix` is the framework names prefix). +The same holds for `MutableMap`. + +### Function types + +Kotlin function-typed objects (e.g. lambdas) are converted to +Swift functions / Objective-C blocks. However there is a difference in how +types of parameters and return values are mapped when translating a function +and a function type. In the latter case primitive types are mapped to their +boxed representation. Kotlin `Unit` return value is represented +as a corresponding `Unit` singleton in Swift/Objective-C. The value of this singleton +can be retrieved in the same way as it is for any other Kotlin `object` +(see singletons in the table above). +To sum the things up: + +
+ +```kotlin +fun foo(block: (Int) -> Unit) { ... } +``` + +
+ +would be represented in Swift as + +
+ +```swift +func foo(block: (KotlinInt) -> KotlinUnit) +``` + +
+ +and can be called like + +
+ +```kotlin +foo { + bar($0 as! Int32) + return KotlinUnit() +} +``` + +
+ +### Generics + +Objective-C supports "lightweight generics" defined on classes, with a relatively limited feature set. Swift can import +generics defined on classes to help provide additional type information to the compiler. + +Generic feature support for Objective-C and Swift differ from Kotlin, so the translation will inevitably lose some information, +but the features supported retain meaningful information. + +#### Limitations + +Objective-C generics do not support all features of either Kotlin or Swift, so there will be some information lost +in the translation. + +Generics can only be defined on classes, not on interfaces (protocols in Objective-C and Swift) or functions. + +#### Nullability + +Kotlin and Swift both define nullability as part of the type specification, while Objective-C defines nullability on methods +and properties of a type. As such, the following: + +
+ +```kotlin +class Sample() { + fun myVal(): T +} +``` + +
+ +will (logically) look like this: + +
+ +```swift +class Sample() { + fun myVal(): T? +} +``` + +
+ +In order to support a potentially nullable type, the Objective-C header needs to define `myVal` with a nullable return value. + +To mitigate this, when defining your generic classes, if the generic type should *never* be null, provide a non-null +type constraint: + +
+ +```kotlin +class Sample() { + fun myVal(): T +} +``` + +
+ +That will force the Objective-C header to mark `myVal` as non-null. + +#### Variance + +Objective-C allows generics to be declared covariant or contravariant. Swift has no support for variance. Generic classes coming +from Objective-C can be force-cast as needed. + +
+ +```kotlin +data class SomeData(val num: Int = 42) : BaseData() +class GenVarOut(val arg: T) +``` + +
+ +
+ +```swift +let variOut = GenVarOut(arg: sd) +let variOutAny : GenVarOut = variOut as! GenVarOut +``` + +
+ +#### Constraints + +In Kotlin you can provide upper bounds for a generic type. Objective-C also supports this, but that support is unavailable +in more complex cases, and is currently not supported in the Kotlin - Objective-C interop. The exception here being a non-null +upper bound will make Objective-C methods/properties non-null. + +### To disable + +To have the framework header written without generics, add the flag to the compiler config: + +
+ +```kotlin +binaries.framework { + freeCompilerArgs += "-Xno-objc-generics" +} +``` + +
+ +## Casting between mapped types + +When writing Kotlin code, an object may need to be converted from a Kotlin type +to the equivalent Swift/Objective-C type (or vice versa). In this case a plain old +Kotlin cast can be used, e.g. + +
+ +```kotlin +val nsArray = listOf(1, 2, 3) as NSArray +val string = nsString as String +val nsNumber = 42 as NSNumber +``` + +
+ +## Subclassing + +### Subclassing Kotlin classes and interfaces from Swift/Objective-C + +Kotlin classes and interfaces can be subclassed by Swift/Objective-C classes +and protocols. + +### Subclassing Swift/Objective-C classes and protocols from Kotlin + +Swift/Objective-C classes and protocols can be subclassed with a Kotlin `final` class. +Non-`final` Kotlin classes inheriting Swift/Objective-C types aren't supported yet, so it is +not possible to declare a complex class hierarchy inheriting Swift/Objective-C types. + +Normal methods can be overridden using the `override` Kotlin keyword. In this case +the overriding method must have the same parameter names as the overridden one. + +Sometimes it is required to override initializers, e.g. when subclassing `UIViewController`. +Initializers imported as Kotlin constructors can be overridden by Kotlin constructors +marked with the `@OverrideInit` annotation: + +
+ +```swift +class ViewController : UIViewController { + @OverrideInit constructor(coder: NSCoder) : super(coder) + + ... +} +``` + +
+ +The overriding constructor must have the same parameter names and types as the overridden one. + +To override different methods with clashing Kotlin signatures, you can add a +`@Suppress("CONFLICTING_OVERLOADS")` annotation to the class. + +By default the Kotlin/Native compiler doesn't allow calling a non-designated +Objective-C initializer as a `super(...)` constructor. This behaviour can be +inconvenient if the designated initializers aren't marked properly in the Objective-C +library. Adding a `disableDesignatedInitializerChecks = true` to the `.def` file for +this library would disable these compiler checks. + +## C features + +See [INTEROP.md](INTEROP.md) for an example case where the library uses some plain C features +(e.g. unsafe pointers, structs etc.). + +## Unsupported + +Some features of Kotlin programming language are not yet mapped into respective features of Objective-C or Swift. +Currently, following features are not properly exposed in generated framework headers: + * inline classes (arguments are mapped as either underlying primitive type or `id`) + * custom classes implementing standard Kotlin collection interfaces (`List`, `Map`, `Set`) and other special classes + * Kotlin subclasses of Objective-C classes diff --git a/kotlin-native/PLATFORM_LIBS.md b/kotlin-native/PLATFORM_LIBS.md new file mode 100644 index 00000000000..b62f59f2205 --- /dev/null +++ b/kotlin-native/PLATFORM_LIBS.md @@ -0,0 +1,61 @@ +# Platform libraries + +## Overview + +To provide access to user's native operating system services, +`Kotlin/Native` distribution includes a set of prebuilt libraries specific to +each target. We call them **Platform Libraries**. + +### POSIX bindings + +For all `Unix` or `Windows` based targets (including `Android` and +`iOS`) we provide the `posix` platform lib. It contains bindings +to platform's implementation of `POSIX` standard. + +To use the library just + +
+ +```kotlin +import platform.posix.* +``` + +
+ +The only target for which it is not available is [WebAssembly](https://en.wikipedia.org/wiki/WebAssembly). + +Note that the content of `platform.posix` is NOT identical on +different platforms, in the same way as different `POSIX` implementations +are a little different. + + +### Popular native libraries + +There are many more platform libraries available for host and +cross-compilation targets. `Kotlin/Native` distribution provides access to +`OpenGL`, `zlib` and other popular native libraries on +applicable platforms. + +On Apple platforms `objc` library is provided for interoperability with [Objective-C](https://en.wikipedia.org/wiki/Objective-C). + +Inspect the contents of `dist/klib/platform/$target` of the distribution for the details. + +## Availability by default + +The packages from platform libraries are available by default. No +special link flags need to be specified to use them. `Kotlin/Native` +compiler automatically detects which of the platform libraries have +been accessed and automatically links the needed libraries. + +On the other hand, the platform libs in the distribution are merely +just wrappers and bindings to the native libraries. That means the +native libraries themselves (`.so`, `.a`, `.dylib`, `.dll` etc) +should be installed on the machine. + +## Examples + +`Kotlin/Native` installation provides a wide spectrum of examples +demonstrating the use of platform libraries. +See [samples](https://github.com/JetBrains/kotlin-native/tree/master/samples) for details. + + diff --git a/kotlin-native/README.md b/kotlin-native/README.md new file mode 100644 index 00000000000..3134a538e5a --- /dev/null +++ b/kotlin-native/README.md @@ -0,0 +1,64 @@ +[![official project](http://jb.gg/badges/official.svg)](https://confluence.jetbrains.com/display/ALL/JetBrains+on+GitHub) +[![version](https://img.shields.io/badge/dynamic/json.svg?color=orange&label=latest%20version&query=%24.tag_name&url=https%3A%2F%2Fgithub.com%2FJetBrains%2Fkotlin-native%2Freleases%2Flatest)](https://github.com/JetBrains/kotlin-native/releases/latest) +# Kotlin/Native # + +_Kotlin/Native_ is an LLVM backend for the Kotlin compiler, runtime +implementation, and native code generation facility using the LLVM toolchain. + + _Kotlin/Native_ is primarily designed to allow compilation for platforms where +virtual machines are not desirable or possible (such as iOS or embedded targets), +or where a developer is willing to produce a reasonably-sized self-contained program +without the need to ship an additional execution runtime. + +Prerequisites: +* install JDK for your platform, instead of JRE. The build requires ```tools.jar```, which is not included in JRE; +* on macOS install Xcode 11 (Xcode 12.0 is required to compile Kotlin/Native from sources) +* on Fedora 26+ ```yum install ncurses-compat-libs``` may be needed +* on recent Ubuntu ```apt install libncurses5``` is needed + +To compile from sources use following steps: + +First, download dependencies: + + ./gradlew dependencies:update + +Then, build the compiler and libraries: + + ./gradlew bundle + +To build with experimental targets support compile with `-Porg.jetbrains.kotlin.native.experimentalTargets`. + +The build can take about an hour on a Macbook Pro. +To run a shorter build with only the host compiler and libraries, run: + + ./gradlew dist distPlatformLibs + +To include Kotlin compiler in [composite build](https://docs.gradle.org/current/userguide/composite_builds.html) and build +against it, use the `kotlinProjectPath` project property: + + ./gradlew dist -PkotlinProjectPath=path/to/kotlin/project + +It's possible to include in a composite build both Kotlin compiler and Kotlin/Native Shared simultaneously. + +After that, you should be able to compile your programs like this: + + export PATH=./dist/bin:$PATH + kotlinc hello.kt -o hello + +For an optimized compilation, use `-opt`: + + kotlinc hello.kt -o hello -opt + +For tests, use: + + ./gradlew backend.native:tests:run + +To generate interoperability stubs, create a library definition file +(refer to [`samples/tetris/.../sdl.def`](https://github.com/JetBrains/kotlin-native/blob/master/samples/tetris/src/nativeInterop/cinterop/sdl.def)), and run the `cinterop` tool like this: + + cinterop -def lib.def + +See the provided [samples](https://github.com/JetBrains/kotlin-native/tree/master/samples) and [`INTEROP.md`](https://github.com/JetBrains/kotlin-native/blob/master/INTEROP.md) for more details. + +The Interop tool generates a library in the `.klib` library format. See [`LIBRARIES.md`](https://github.com/JetBrains/kotlin-native/blob/master/LIBRARIES.md) +for more details on this file format. diff --git a/kotlin-native/RELEASE_NOTES.md b/kotlin-native/RELEASE_NOTES.md new file mode 100644 index 00000000000..eeb564ff106 --- /dev/null +++ b/kotlin-native/RELEASE_NOTES.md @@ -0,0 +1,113 @@ +# Kotlin/Native backend, Beta version # + +## Introduction ## + + _Kotlin/Native_ is an LLVM backend for the Kotlin compiler. +It consists of a machine code generation facility using the LLVM toolchain +and a native runtime implementation. + + _Kotlin/Native_ is primarily designed to allow compilation for platforms where +virtual machines are not desirable or possible (such as iOS or embedded targets), +or where the developer needs to produce a reasonably-sized self-contained binary +that doesn't require an additional execution runtime. + +## Supported platforms ## + +The _Kotlin/Native_ compiler produces mostly portable (modulo pointer size and target +triplet) LLVM bitcode, and as such can easily support any platform, as long as there's an LLVM +code generator for the platform. + However, as actually producing native code requires a platform linker and some +basic runtime shipped along with the translator, we only support a subset of all possible +target platforms. Currently _Kotlin/Native_ is being shipped and tested with support for +the following platforms: + + * Mac OS X 10.11 and later (x86-64), host and target (`-target macos_x64`, default on macOS hosts) + * Ubuntu Linux x86-64 (14.04, 16.04 and later), other Linux flavours may work as well, host and target + (`-target linux_x64`, default on Linux hosts, hosted on Linux, Windows and macOS). + * Microsoft Windows x86-64 (tested on Windows 7 and Windows 10), host and target (`-target mingw_x64`, + default on Windows hosts). Experimental support is available on Linux and macOS hosts (requires Wine). + * Microsoft Windows x86-32 cross-compiled target (`-target mingw_x86`), hosted on Windows. + Experimental support is available on Linux and macOS hosts (requires Wine). + * Apple iOS (armv7 and arm64 devices, x86 simulator), cross-compiled target + (`-target ios_arm32|ios_arm64|ios_x64`), hosted on macOS. + * Apple tvOS (arm64 devices, x86 simulator), cross-compiled target + (`-target tvos_arm64|tvos_x64`), hosted on macOS. + * Apple watchOS (arm32/arm64 devices, x86 simulator), cross-compiled target + (`-target watchos_arm32|watchos_arm64|watchos_x86`), hosted on macOS. + * Linux arm32 hardfp, Raspberry Pi, cross-compiled target (`-target raspberrypi`), hosted on Linux, Windows and macOS + * Linux MIPS big endian, cross-compiled target (`-target mips`), hosted on Linux. + * Linux MIPS little endian, cross-compiled target (`-target mipsel`), hosted on Linux. + * Android x86 (32 and 64 bit), arm32 and arm64 (`-target android_x86|android_x64|android_arm32|android_arm64`) targets, + hosted on Linux, macOS and Windows. + * WebAssembly (`-target wasm32`) target, hosted on Linux, Windows or macOS. Webassembly support is experimental + and could be discontinued in further releases. + * Experimental support for Zephyr RTOS (`-target zephyr_stm32f4_disco`) is available on macOS, Linux + and Windows hosts. + + To enable experimental targets Kotlin/Native must be recompiled with `org.jetbrains.kotlin.native.experimentalTargets` Gradle property set. + + Adding support for other target platforms shouldn't be too hard, if LLVM support is available. + + ## Compatibility and features ## + +To run _Kotlin/Native_ compiler JDK 8 or later (JDK) for the host platform has to be installed. +Produced programs are fully self-sufficient and do not need JVM or other runtime. + +On macOS it also requires Xcode 11.0 or newer to be installed. + +The language and library version supported by this EAP release match Kotlin 1.3. +However, there are certain limitations, see section [Known Limitations](#limitations). + + Currently _Kotlin/Native_ uses reference counting based memory management scheme with a cycle +collection algorithm. Multiple threads could be used, but objects must be explicitly transferred +between threads, and same object couldn't be accessed by two threads concurrently. + +_Kotlin/Native_ provides efficient interoperability with libraries written in C or Objective-C, and supports +automatic generation of Kotlin bindings from a C/Objective-C header file. +See the samples coming with the distribution. + + ## Getting Started ## + + Download _Kotlin/Native_ distribution and unpack it. You can run command line compiler with + + bin/kotlinc .kt -o + + During the first run it will download all the external dependencies, such as LLVM. + +To see the list of available flags, run `kotlinc -h`. + +For documentation on C interoperability stubs see [INTEROP.md](https://github.com/JetBrains/kotlin-native/blob/master/INTEROP.md). + + ## Known limitations ## + + ### Performance ### + + *** DO NOT USE THIS PREVIEW RELEASE FOR ANY PERFORMANCE ANALYSIS *** + + This beta version of _Kotlin/Native_ technology is not yet tuned +for benchmarking and competitive analysis of any kind. + +### Standard Library ### + + The standard library in _Kotlin/Native_ is known match common standard library in other Kotlin variants. + Note, that standard Java APIs, such as `java.math.BigDecimal` or `java.io` +is not available in current _Kotlin_ standard library, but using C interoperability, one could +call similar APIs from the POSIX library, see this [`sample`](https://github.com/JetBrains/kotlin-native/blob/master/samples/csvparser). + Also Kotlin/Native standard library contains certain native-specific extensions, mostly around +memory management and concurrency. + +### Reflection ### + +Full reflection is not implemented, but class can be referenced and its name could be retrieved. +Notice that property delegation (including lazy properties) *does* work. + +### Microsoft Windows support ### + + Only 64-bit Windows is currently supported as compilation host, both 32-bit and 64-bit Windows could +be targets. + +### Debugging ### + + _Kotlin/Native_ supports source-level debugging on produced executables with `lldb` debugger. + Produce your binary with debugging information by specifying `-g` _Kotlin/Native_ compiler switch. +See [`DEBUGGING.md`](https://github.com/JetBrains/kotlin-native/blob/master/DEBUGGING.md) for further information. diff --git a/kotlin-native/_nav_reference.yml b/kotlin-native/_nav_reference.yml new file mode 100644 index 00000000000..223933adfea --- /dev/null +++ b/kotlin-native/_nav_reference.yml @@ -0,0 +1,44 @@ +- md: CONCURRENCY.md + url: concurrency.html + title: "Concurrency" + +- md: IMMUTABILITY.md + url: immutability.html + title: "Immutability" + +- md: LIBRARIES.md + url: libraries.html + title: "Kotlin Libraries" + +- md: PLATFORM_LIBS.md + url: platform_libs.html + title: "Platform Libraries" + +- md: INTEROP.md + url: c_interop.html + title: "C Interop" + +- md: OBJC_INTEROP.md + url: objc_interop.html + title: "Objective-C and Swift Interop" + +- md: IOS_SYMBOLICATION.md + url: ios_symbolication.html + title: "Symbolicating iOS crash reports" + +- md: COCOAPODS.md + url: cocoapods.html + title: "CocoaPods Integration" + +- md: GRADLE_PLUGIN.md + url: gradle_plugin.html + title: "Gradle Plugin" + +- md: DEBUGGING.md + url: debugging.html + title: "Debugging" + +- md: FAQ.md + url: faq.html + title: "FAQ" + diff --git a/kotlin-native/backend.native/backend.native.iml b/kotlin-native/backend.native/backend.native.iml new file mode 100644 index 00000000000..5bab15c4427 --- /dev/null +++ b/kotlin-native/backend.native/backend.native.iml @@ -0,0 +1,14 @@ + + + + + + + + + + + + + + \ No newline at end of file diff --git a/kotlin-native/backend.native/bc.frontend/bc.frontend.iml b/kotlin-native/backend.native/bc.frontend/bc.frontend.iml new file mode 100644 index 00000000000..a8bfb8f9d08 --- /dev/null +++ b/kotlin-native/backend.native/bc.frontend/bc.frontend.iml @@ -0,0 +1,13 @@ + + + + + + + + + + + + + \ No newline at end of file diff --git a/kotlin-native/backend.native/build.gradle b/kotlin-native/backend.native/build.gradle new file mode 100644 index 00000000000..e5da6cc46e9 --- /dev/null +++ b/kotlin-native/backend.native/build.gradle @@ -0,0 +1,322 @@ +import org.jetbrains.kotlin.CopyCommonSources +import org.jetbrains.kotlin.konan.target.HostManager + +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ +buildscript { + apply from: "$rootDir/gradle/kotlinGradlePlugin.gradle" + apply plugin: 'project-report' + + dependencies { + classpath "com.google.protobuf:protobuf-gradle-plugin:0.8.8" + } +} + +String protobufVersion = '2.6.1' +apply plugin: "com.google.protobuf" +apply plugin: 'java' +apply plugin: 'kotlin' +apply plugin: org.jetbrains.kotlin.NativeInteropPlugin +apply plugin: "maven-publish" + +// (gets applied to this project and all its subprojects) +allprojects { + repositories { + maven { url buildKotlinCompilerRepo } + } +} + +sourceSets { + compiler { + proto.srcDir 'compiler/ir/backend.native/src/' + java { + srcDir 'compiler/ir/backend.native/src/' + srcDir 'build/renamed/source/proto/compiler/java' + } + kotlin { + srcDir 'compiler/ir/backend.native/src/' + } + resources.srcDir 'compiler/ir/backend.native/resources/' + } + cli_bc { + java.srcDir 'cli.bc/src' + kotlin.srcDir 'cli.bc/src' + } + bc_frontend { + java.srcDir 'bc.frontend/src' + kotlin.srcDir 'bc.frontend/src' + } +} + +compileCompilerKotlin { + dependsOn('renamePackage') + // The protobuf plugin specifies this dependency for java by itself, + // but not for Kotlin. + dependsOn('generateCompilerProto') + kotlinOptions.jvmTarget = "1.8" + kotlinOptions.allWarningsAsErrors=true + kotlinOptions.freeCompilerArgs += ['-Xopt-in=kotlin.RequiresOptIn', '-Xopt-in=org.jetbrains.kotlin.ir.ObsoleteDescriptorBasedAPI'] +} + +compileCompilerJava { + dependsOn('renamePackage') +} + +task copyGenerated(type: Copy) { + dependsOn('generateCompilerProto') + from 'build/generated/source/proto/compiler/java' + into 'build/renamed/source/proto/compiler/java' + filter { line -> line.replaceAll("com.google.protobuf", "org.jetbrains.kotlin.protobuf") } + outputs.dir('build/renamed') +} + +task deleteGenerated(type: Delete) { + dependsOn('copyGenerated') + delete 'build/generated/source/proto/compiler/java' +} + +task renamePackage { + dependsOn('copyGenerated', 'deleteGenerated') +} + +kotlinNativeInterop { + llvm { + dependsOn ":llvmDebugInfoC:debugInfoStaticLibrary" + dependsOn ":llvmCoverageMappingC:coverageMappingStaticLibrary" + defFile 'llvm.def' + if (!project.parent.convention.plugins.platformInfo.isWindows()) + compilerOpts "-fPIC" + compilerOpts "-I$llvmDir/include", "-I${project(':llvmDebugInfoC').projectDir}/src/main/include", "-I${project(':llvmCoverageMappingC').projectDir}/src/main/include" + linkerOpts "-L$llvmDir/lib", "-L${project(':llvmDebugInfoC').buildDir}/libs/debugInfo/static", "-L${project(':llvmCoverageMappingC').buildDir}/libs/coverageMapping/static" + } + + hash { // TODO: copy-pasted from ':common:compileHash' + if (!project.parent.convention.plugins.platformInfo.isWindows()) { + compilerOpts '-fPIC' + linkerOpts '-fPIC' + } + linker 'clang++' + linkOutputs ":common:${hostName}Hash" + + headers fileTree('../common/src/hash/headers') { + include '**/*.h' + include '**/*.hpp' + } + + pkg 'org.jetbrains.kotlin.backend.konan.hash' + } + + files { + if (!project.parent.convention.plugins.platformInfo.isWindows()) { + compilerOpts '-fPIC' + linkerOpts '-fPIC' + } + linker 'clang++' + linkOutputs ":common:${hostName}Files" + + headers fileTree('../common/src/files/headers') { + include '**/*.h' + include '**/*.hpp' + } + + pkg 'org.jetbrains.kotlin.backend.konan.files' + } +} + + +configurations { + kotlin_compiler_jar + kotlin_stdlib_jar + kotlin_reflect_jar + kotlin_script_runtime_jar + trove4j_jar + kotlinCommonSources + + cli_bcRuntime { + extendsFrom compilerRuntime + extendsFrom kotlin_script_runtime_jar + } + + cli_bc { + extendsFrom cli_bcRuntime + } +} + +dependencies { + trove4j_jar "org.jetbrains.intellij.deps:trove4j:1.0.20181211@jar" + kotlin_compiler_jar "$kotlinCompilerModule@jar" + kotlin_stdlib_jar "$kotlinStdLibModule@jar" + kotlin_reflect_jar "$kotlinReflectModule@jar" + kotlin_script_runtime_jar "$kotlinScriptRuntimeModule@jar" + + [kotlinCommonStdlibModule, kotlinTestCommonModule, kotlinTestAnnotationsCommonModule].each { + kotlinCommonSources(it) { transitive = false } + } + + compilerCompile project(":utilities:basic-utils") + + compilerCompile "com.google.protobuf:protobuf-java:${protobufVersion}" + + compilerCompile kotlinCompilerModule + compilerCompile kotlinNativeInterop['llvm'].configuration + compilerCompile kotlinNativeInterop['hash'].configuration + compilerCompile kotlinNativeInterop['files'].configuration + compilerCompile "org.jetbrains.kotlin:kotlin-native-shared:$konanVersion" + + cli_bcCompile kotlinCompilerModule + cli_bcCompile "org.jetbrains.kotlin:kotlin-native-shared:$konanVersion" + cli_bcCompile sourceSets.compiler.output + + bc_frontendCompile kotlinCompilerModule + + cli_bc sourceSets.cli_bc.output +} + + +classes.dependsOn 'compilerClasses', 'cli_bcClasses', 'bc_frontendClasses' + + +// These are just a couple of aliases +task stdlib(dependsOn: "${hostName}Stdlib") + +def commonSrc = file('build/stdlib') + +task unzipStdlibSources(type: CopyCommonSources) { + outputDir commonSrc + sourcePaths configurations.kotlinCommonSources +} + +final List stdLibSrc = [ + project(':Interop:Runtime').file('src/main/kotlin'), + project(':Interop:Runtime').file('src/native/kotlin'), + project(':Interop:JsRuntime').file('src/main/kotlin'), + project(':runtime').file('src/main/kotlin') +] + +// These files are built before the 'dist' is complete, +// so we provide a custom value for --runtime + +targetList.each { target -> + def konanJvmArgs = [*HostManager.regularJvmArgs] + + def defaultArgs = ['-nopack', '-nostdlib', '-no-default-libs', '-no-endorsed-libs', + //Uncomment this '-Werror' when common stdlib will be ready + ] + if (target != "wasm32") defaultArgs += '-g' + def konanArgs = [*defaultArgs, + '-target', target, + "-Xruntime=${project(':runtime').file('build/bitcode/main/' + target + '/runtime.bc')}", + *project.globalBuildArgs] + + task("${target}Stdlib", type: JavaExec) { + main = 'org.jetbrains.kotlin.cli.bc.K2NativeKt' + // This task depends on distCompiler, so the compiler jar is already in the dist directory. + classpath = fileTree("${rootProject.projectDir}/dist/konan/lib") { + include "*.jar" + } + jvmArgs = konanJvmArgs + args = [*konanArgs, + '-output', project(':runtime').file("build/${target}Stdlib"), + '-produce', 'library', '-module-name', 'stdlib', '-XXLanguage:+AllowContractsForCustomFunctions', + '-Xmulti-platform', '-Xopt-in=kotlin.RequiresOptIn', '-Xinline-classes', + '-Xopt-in=kotlin.contracts.ExperimentalContracts', + '-Xopt-in=kotlin.ExperimentalMultiplatform', + '-Xallow-result-return-type', + commonSrc.absolutePath, + "-Xcommon-sources=${commonSrc.absolutePath}", + *stdLibSrc] + stdLibSrc.forEach { inputs.dir(it) } + inputs.dir(commonSrc) + outputs.dir(project(':runtime').file("build/${target}Stdlib")) + + dependsOn 'unzipStdlibSources' + dependsOn ":runtime:${target}Runtime" + dependsOn ":distCompiler" + } +} + +task run { + doLast { + logger.quiet("Run the outer project 'demo' target to compile the test source.") + } +} + +jar { + from sourceSets.cli_bc.output, + sourceSets.compiler.output, + sourceSets.hashInteropStubs.output, + sourceSets.filesInteropStubs.output, + sourceSets.llvmInteropStubs.output + + dependsOn ':runtime:hostRuntime', 'external_jars' +} + +def externalJars = ['compiler', 'stdlib', 'reflect', 'script_runtime'] + +task trove4jCopy(type: Copy) { + from configurations.getByName("trove4j_jar") { + include "trove4j*.jar" + rename "trove4j(.*).jar", "trove4j.jar" + + into 'build/external_jars' + } +} + +externalJars.each { arg -> + def jar = arg.replace('_', '-') // :( + task("${arg}Copy", type: Copy) { + from configurations.getByName("kotlin_${arg}_jar") { + include "kotlin-${jar}*.jar" + rename "kotlin-${jar}(.*).jar", "kotlin-${jar}.jar" + + into 'build/external_jars' + } + } +} + +task external_jars(type: Copy) { + dependsOn externalJars.collect { "${it}Copy" } + dependsOn trove4jCopy + + from configurations.compilerCompile { + + include "protobuf-java-${protobufVersion}.jar" + + into 'build/external_jars' + } +} + +protobuf { + protoc { + artifact = "com.google.protobuf:protoc:${protobufVersion}" + } +} + +task debugCompiler(type: JavaExec) { + dependsOn ':dist' + main = 'org.jetbrains.kotlin.cli.bc.K2NativeKt' + classpath = project.fileTree("${distDir.canonicalPath}/konan/lib/") { + include '*.jar' + } + jvmArgs "-Dorg.jetbrains.kotlin.native.home=${distDir.canonicalPath}" + enableAssertions = true + args = findProperty("konan.debug.args").toString().tokenize() ?: [] +} + +publishing { + repositories { + maven { url = "$buildDir/repo" } + } + + publications { + maven(MavenPublication) { + groupId = 'org.jetbrains.kotlin' + artifactId = 'backend.native' + version = konanVersionFull + + from components.java + } + } +} \ No newline at end of file diff --git a/kotlin-native/backend.native/cli.bc/cli.bc.iml b/kotlin-native/backend.native/cli.bc/cli.bc.iml new file mode 100644 index 00000000000..507103972c1 --- /dev/null +++ b/kotlin-native/backend.native/cli.bc/cli.bc.iml @@ -0,0 +1,18 @@ + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/kotlin-native/backend.native/cli.bc/src/org/jetbrains/kotlin/cli/bc/K2Native.kt b/kotlin-native/backend.native/cli.bc/src/org/jetbrains/kotlin/cli/bc/K2Native.kt new file mode 100644 index 00000000000..d5f0d29c9b6 --- /dev/null +++ b/kotlin-native/backend.native/cli.bc/src/org/jetbrains/kotlin/cli/bc/K2Native.kt @@ -0,0 +1,460 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +package org.jetbrains.kotlin.cli.bc + +import com.intellij.openapi.Disposable +import org.jetbrains.annotations.NotNull +import org.jetbrains.annotations.Nullable +import org.jetbrains.kotlin.backend.common.serialization.metadata.KlibMetadataVersion +import org.jetbrains.kotlin.backend.konan.* +import org.jetbrains.kotlin.cli.common.* +import org.jetbrains.kotlin.cli.common.config.addKotlinSourceRoot +import org.jetbrains.kotlin.cli.common.config.kotlinSourceRoots +import org.jetbrains.kotlin.cli.common.messages.CompilerMessageSeverity.* +import org.jetbrains.kotlin.cli.common.messages.MessageCollector +import org.jetbrains.kotlin.cli.common.messages.MessageRenderer +import org.jetbrains.kotlin.cli.jvm.compiler.EnvironmentConfigFiles +import org.jetbrains.kotlin.cli.jvm.compiler.KotlinCoreEnvironment +import org.jetbrains.kotlin.cli.jvm.plugins.PluginCliParser +import org.jetbrains.kotlin.config.CommonConfigurationKeys +import org.jetbrains.kotlin.config.CompilerConfiguration +import org.jetbrains.kotlin.config.Services +import org.jetbrains.kotlin.konan.CURRENT +import org.jetbrains.kotlin.konan.CompilerVersion +import org.jetbrains.kotlin.konan.file.File +import org.jetbrains.kotlin.konan.target.CompilerOutputKind +import org.jetbrains.kotlin.metadata.deserialization.BinaryVersion +import org.jetbrains.kotlin.psi.KtFile +import org.jetbrains.kotlin.util.profile +import org.jetbrains.kotlin.utils.KotlinPaths + +private class K2NativeCompilerPerformanceManager: CommonCompilerPerformanceManager("Kotlin to Native Compiler") +class K2Native : CLICompiler() { + + override fun MutableList.addPlatformOptions(arguments: K2NativeCompilerArguments) {} + + override fun createMetadataVersion(versionArray: IntArray): BinaryVersion = KlibMetadataVersion(*versionArray) + + override val performanceManager:CommonCompilerPerformanceManager by lazy { + K2NativeCompilerPerformanceManager() + } + + override fun doExecute(@NotNull arguments: K2NativeCompilerArguments, + @NotNull configuration: CompilerConfiguration, + @NotNull rootDisposable: Disposable, + @Nullable paths: KotlinPaths?): ExitCode { + + if (arguments.version) { + println("Kotlin/Native: ${CompilerVersion.CURRENT}") + return ExitCode.OK + } + + val pluginLoadResult = + PluginCliParser.loadPluginsSafe(arguments.pluginClasspaths, arguments.pluginOptions, configuration) + if (pluginLoadResult != ExitCode.OK) return pluginLoadResult + + val environment = KotlinCoreEnvironment.createForProduction(rootDisposable, + configuration, EnvironmentConfigFiles.NATIVE_CONFIG_FILES) + val project = environment.project + val messageCollector = configuration.get(CLIConfigurationKeys.MESSAGE_COLLECTOR_KEY) ?: MessageCollector.NONE + configuration.put(CLIConfigurationKeys.PHASE_CONFIG, createPhaseConfig(toplevelPhase, arguments, messageCollector)) + val konanConfig = KonanConfig(project, configuration) + + val enoughArguments = arguments.freeArgs.isNotEmpty() || arguments.isUsefulWithoutFreeArgs + if (!enoughArguments) { + configuration.report(ERROR, "You have not specified any compilation arguments. No output has been produced.") + } + + /* Set default version of metadata version */ + val metadataVersionString = arguments.metadataVersion + if (metadataVersionString == null) { + configuration.put(CommonConfigurationKeys.METADATA_VERSION, KlibMetadataVersion.INSTANCE) + } + + try { + runTopLevelPhases(konanConfig, environment) + } catch (e: KonanCompilationException) { + return ExitCode.COMPILATION_ERROR + } catch (e: Throwable) { + configuration.report(ERROR, """ + |Compilation failed: ${e.message} + + | * Source files: ${environment.getSourceFiles().joinToString(transform = KtFile::getName)} + | * Compiler version info: Konan: ${CompilerVersion.CURRENT} / Kotlin: ${KotlinVersion.CURRENT} + | * Output kind: ${configuration.get(KonanConfigKeys.PRODUCE)} + + """.trimMargin()) + throw e + } + + return ExitCode.OK + } + + val K2NativeCompilerArguments.isUsefulWithoutFreeArgs: Boolean + get() = listTargets || listPhases || checkDependencies || !includes.isNullOrEmpty() || + !librariesToCache.isNullOrEmpty() || libraryToAddToCache != null + + fun Array?.toNonNullList(): List { + return this?.asList() ?: listOf() + } + + // It is executed before doExecute(). + override fun setupPlatformSpecificArgumentsAndServices( + configuration: CompilerConfiguration, + arguments : K2NativeCompilerArguments, + services : Services) { + + val commonSources = arguments.commonSources?.toSet().orEmpty() + arguments.freeArgs.forEach { + configuration.addKotlinSourceRoot(it, it in commonSources) + } + + with(KonanConfigKeys) { + with(configuration) { + arguments.kotlinHome?.let { put(KONAN_HOME, it) } + + put(NODEFAULTLIBS, arguments.nodefaultlibs || !arguments.libraryToAddToCache.isNullOrEmpty()) + put(NOENDORSEDLIBS, arguments.noendorsedlibs || !arguments.libraryToAddToCache.isNullOrEmpty()) + put(NOSTDLIB, arguments.nostdlib || !arguments.libraryToAddToCache.isNullOrEmpty()) + put(NOPACK, arguments.nopack) + put(NOMAIN, arguments.nomain) + put(LIBRARY_FILES, + arguments.libraries.toNonNullList()) + put(LINKER_ARGS, arguments.linkerArguments.toNonNullList() + + arguments.singleLinkerArguments.toNonNullList()) + arguments.moduleName?.let{ put(MODULE_NAME, it) } + arguments.target?.let{ put(TARGET, it) } + + put(INCLUDED_BINARY_FILES, + arguments.includeBinaries.toNonNullList()) + put(NATIVE_LIBRARY_FILES, + arguments.nativeLibraries.toNonNullList()) + put(REPOSITORIES, + arguments.repositories.toNonNullList()) + + // TODO: Collect all the explicit file names into an object + // and teach the compiler to work with temporaries and -save-temps. + + arguments.outputName ?.let { put(OUTPUT, it) } + val outputKind = CompilerOutputKind.valueOf( + (arguments.produce ?: "program").toUpperCase()) + put(PRODUCE, outputKind) + put(METADATA_KLIB, arguments.metadataKlib) + + arguments.libraryVersion ?. let { put(LIBRARY_VERSION, it) } + + arguments.mainPackage ?.let{ put(ENTRY, it) } + arguments.manifestFile ?.let{ put(MANIFEST_FILE, it) } + arguments.runtimeFile ?.let{ put(RUNTIME_FILE, it) } + arguments.temporaryFilesDir?.let { put(TEMPORARY_FILES_DIR, it) } + + put(LIST_TARGETS, arguments.listTargets) + put(OPTIMIZATION, arguments.optimization) + put(DEBUG, arguments.debug) + // TODO: remove after 1.4 release. + if (arguments.lightDebugDeprecated) { + configuration.report(WARNING, + "-Xg0 is now deprecated and skipped by compiler. Light debug information is enabled by default for Darwin platforms." + + " For other targets, please, use `-Xadd-light-debug=enable` instead.") + } + putIfNotNull(LIGHT_DEBUG, when (val it = arguments.lightDebugString) { + "enable" -> true + "disable" -> false + null -> null + else -> { + configuration.report(ERROR, "Unsupported -Xadd-light-debug= value: $it. Possible values are 'enable'/'disable'") + null + } + }) + put(STATIC_FRAMEWORK, selectFrameworkType(configuration, arguments, outputKind)) + put(OVERRIDE_CLANG_OPTIONS, arguments.clangOptions.toNonNullList()) + put(ALLOCATION_MODE, arguments.allocator) + + put(PRINT_IR, arguments.printIr) + put(PRINT_IR_WITH_DESCRIPTORS, arguments.printIrWithDescriptors) + put(PRINT_DESCRIPTORS, arguments.printDescriptors) + put(PRINT_LOCATIONS, arguments.printLocations) + put(PRINT_BITCODE, arguments.printBitCode) + + put(PURGE_USER_LIBS, arguments.purgeUserLibs) + + if (arguments.verifyCompiler != null) + put(VERIFY_COMPILER, arguments.verifyCompiler == "true") + put(VERIFY_BITCODE, arguments.verifyBitCode) + + put(ENABLED_PHASES, + arguments.enablePhases.toNonNullList()) + put(DISABLED_PHASES, + arguments.disablePhases.toNonNullList()) + put(LIST_PHASES, arguments.listPhases) + + put(COMPATIBLE_COMPILER_VERSIONS, + arguments.compatibleCompilerVersions.toNonNullList()) + + put(ENABLE_ASSERTIONS, arguments.enableAssertions) + + put(MEMORY_MODEL, when (arguments.memoryModel) { + "relaxed" -> { + configuration.report(STRONG_WARNING, "Relaxed memory model is not yet fully functional") + MemoryModel.RELAXED + } + "strict" -> MemoryModel.STRICT + "experimental" -> MemoryModel.EXPERIMENTAL + else -> { + configuration.report(ERROR, "Unsupported memory model ${arguments.memoryModel}") + MemoryModel.STRICT + } + }) + + when { + arguments.generateWorkerTestRunner -> put(GENERATE_TEST_RUNNER, TestRunnerKind.WORKER) + arguments.generateTestRunner -> put(GENERATE_TEST_RUNNER, TestRunnerKind.MAIN_THREAD) + arguments.generateNoExitTestRunner -> put(GENERATE_TEST_RUNNER, TestRunnerKind.MAIN_THREAD_NO_EXIT) + else -> put(GENERATE_TEST_RUNNER, TestRunnerKind.NONE) + } + // We need to download dependencies only if we use them ( = there are files to compile). + put( + CHECK_DEPENDENCIES, + configuration.kotlinSourceRoots.isNotEmpty() + || !arguments.includes.isNullOrEmpty() + || arguments.checkDependencies + ) + if (arguments.friendModules != null) + put(FRIEND_MODULES, arguments.friendModules!!.split(File.pathSeparator).filterNot(String::isEmpty)) + + put(EXPORTED_LIBRARIES, selectExportedLibraries(configuration, arguments, outputKind)) + put(INCLUDED_LIBRARIES, selectIncludes(configuration, arguments, outputKind)) + put(FRAMEWORK_IMPORT_HEADERS, arguments.frameworkImportHeaders.toNonNullList()) + arguments.emitLazyObjCHeader?.let { put(EMIT_LAZY_OBJC_HEADER_FILE, it) } + + put(BITCODE_EMBEDDING_MODE, selectBitcodeEmbeddingMode(this, arguments)) + put(DEBUG_INFO_VERSION, arguments.debugInfoFormatVersion.toInt()) + put(COVERAGE, arguments.coverage) + put(LIBRARIES_TO_COVER, arguments.coveredLibraries.toNonNullList()) + arguments.coverageFile?.let { put(PROFRAW_PATH, it) } + put(OBJC_GENERICS, !arguments.noObjcGenerics) + put(DEBUG_PREFIX_MAP, parseDebugPrefixMap(arguments, configuration)) + + put(LIBRARIES_TO_CACHE, parseLibrariesToCache(arguments, configuration, outputKind)) + val libraryToAddToCache = parseLibraryToAddToCache(arguments, configuration, outputKind) + if (libraryToAddToCache != null && !arguments.outputName.isNullOrEmpty()) + configuration.report(ERROR, "$ADD_CACHE already implicitly sets output file name") + val cacheDirectories = arguments.cacheDirectories.toNonNullList() + libraryToAddToCache?.let { put(LIBRARY_TO_ADD_TO_CACHE, it) } + put(CACHE_DIRECTORIES, cacheDirectories) + put(CACHED_LIBRARIES, parseCachedLibraries(arguments, configuration)) + + parseShortModuleName(arguments, configuration, outputKind)?.let { + put(SHORT_MODULE_NAME, it) + } + put(DISABLE_FAKE_OVERRIDE_VALIDATOR, arguments.disableFakeOverrideValidator) + putIfNotNull(PRE_LINK_CACHES, parsePreLinkCachesValue(configuration, arguments.preLinkCaches)) + } + } + } + + override fun createArguments() = K2NativeCompilerArguments() + + override fun executableScriptFileName() = "kotlinc-native" + + companion object { + @JvmStatic fun main(args: Array) { + profile("Total compiler main()") { + doMain(K2Native(), args) + } + } + @JvmStatic fun mainNoExit(args: Array) { + profile("Total compiler main()") { + if (doMainNoExit(K2Native(), args) != ExitCode.OK) { + throw KonanCompilationException("Compilation finished with errors") + } + } + } + + @JvmStatic fun mainNoExitWithGradleRenderer(args: Array) { + profile("Total compiler main()") { + if (doMainNoExit(K2Native(), args, MessageRenderer.GRADLE_STYLE) != ExitCode.OK) { + throw KonanCompilationException("Compilation finished with errors") + } + } + } + } +} + +private fun selectFrameworkType( + configuration: CompilerConfiguration, + arguments: K2NativeCompilerArguments, + outputKind: CompilerOutputKind +): Boolean { + return if (outputKind != CompilerOutputKind.FRAMEWORK && arguments.staticFramework) { + configuration.report( + STRONG_WARNING, + "'$STATIC_FRAMEWORK_FLAG' is only supported when producing frameworks, " + + "but the compiler is producing ${outputKind.name.toLowerCase()}" + ) + false + } else { + arguments.staticFramework + } +} + +private fun parsePreLinkCachesValue( + configuration: CompilerConfiguration, + value: String? +): Boolean? = when (value) { + "enable" -> true + "disable" -> false + null -> null + else -> { + configuration.report(ERROR, "Unsupported `-Xpre-link-caches` value: $value. Possible values are 'enable'/'disable'") + null + } + } + +private fun selectBitcodeEmbeddingMode( + configuration: CompilerConfiguration, + arguments: K2NativeCompilerArguments +): BitcodeEmbedding.Mode = when { + arguments.embedBitcodeMarker -> { + if (arguments.embedBitcode) { + configuration.report( + STRONG_WARNING, + "'$EMBED_BITCODE_FLAG' is ignored because '$EMBED_BITCODE_MARKER_FLAG' is specified" + ) + } + BitcodeEmbedding.Mode.MARKER + } + arguments.embedBitcode -> { + BitcodeEmbedding.Mode.FULL + } + else -> BitcodeEmbedding.Mode.NONE +} + +private fun selectExportedLibraries( + configuration: CompilerConfiguration, + arguments: K2NativeCompilerArguments, + outputKind: CompilerOutputKind +): List { + val exportedLibraries = arguments.exportedLibraries?.toList().orEmpty() + + return if (exportedLibraries.isNotEmpty() && outputKind != CompilerOutputKind.FRAMEWORK && + outputKind != CompilerOutputKind.STATIC && outputKind != CompilerOutputKind.DYNAMIC) { + configuration.report(STRONG_WARNING, + "-Xexport-library is only supported when producing frameworks or native libraries, " + + "but the compiler is producing ${outputKind.name.toLowerCase()}") + + emptyList() + } else { + exportedLibraries + } +} + +private fun selectIncludes( + configuration: CompilerConfiguration, + arguments: K2NativeCompilerArguments, + outputKind: CompilerOutputKind +): List { + val includes = arguments.includes?.toList().orEmpty() + + return if (includes.isNotEmpty() && outputKind == CompilerOutputKind.LIBRARY) { + configuration.report( + ERROR, + "The $INCLUDE_ARG flag is not supported when producing ${outputKind.name.toLowerCase()}" + ) + emptyList() + } else { + includes + } +} + +private fun parseCachedLibraries( + arguments: K2NativeCompilerArguments, + configuration: CompilerConfiguration +): Map = arguments.cachedLibraries?.asList().orEmpty().mapNotNull { + val libraryAndCache = it.split(",") + if (libraryAndCache.size != 2) { + configuration.report( + ERROR, + "incorrect $CACHED_LIBRARY format: expected ',', got '$it'" + ) + null + } else { + libraryAndCache[0] to libraryAndCache[1] + } +}.toMap() + +private fun parseLibrariesToCache( + arguments: K2NativeCompilerArguments, + configuration: CompilerConfiguration, + outputKind: CompilerOutputKind +): List { + val input = arguments.librariesToCache?.asList().orEmpty() + + return if (input.isNotEmpty() && !outputKind.isCache) { + configuration.report(ERROR, "$MAKE_CACHE can't be used when not producing cache") + emptyList() + } else if (input.isNotEmpty() && !arguments.libraryToAddToCache.isNullOrEmpty()) { + configuration.report(ERROR, "supplied both $MAKE_CACHE and $ADD_CACHE options") + emptyList() + } else { + input + } +} + +private fun parseLibraryToAddToCache( + arguments: K2NativeCompilerArguments, + configuration: CompilerConfiguration, + outputKind: CompilerOutputKind +): String? { + val input = arguments.libraryToAddToCache + + return if (input != null && !outputKind.isCache) { + configuration.report(ERROR, "$ADD_CACHE can't be used when not producing cache") + null + } else { + input + } +} + +// TODO: Support short names for current module in ObjC export and lift this limitation. +private fun parseShortModuleName( + arguments: K2NativeCompilerArguments, + configuration: CompilerConfiguration, + outputKind: CompilerOutputKind +): String? { + val input = arguments.shortModuleName + + return if (input != null && outputKind != CompilerOutputKind.LIBRARY) { + configuration.report( + STRONG_WARNING, + "$SHORT_MODULE_NAME_ARG is only supported when producing a Kotlin library, " + + "but the compiler is producing ${outputKind.name.toLowerCase()}" + ) + null + } else { + input + } +} + +private fun parseDebugPrefixMap( + arguments: K2NativeCompilerArguments, + configuration: CompilerConfiguration +): Map = arguments.debugPrefixMap?.asList().orEmpty().mapNotNull { + val libraryAndCache = it.split("=") + if (libraryAndCache.size != 2) { + configuration.report( + ERROR, + "incorrect debug prefix map format: expected '=', got '$it'" + ) + null + } else { + libraryAndCache[0] to libraryAndCache[1] + } +}.toMap() + + +fun main(args: Array) = K2Native.main(args) +fun mainNoExitWithGradleRenderer(args: Array) = K2Native.mainNoExitWithGradleRenderer(args) diff --git a/kotlin-native/backend.native/cli.bc/src/org/jetbrains/kotlin/cli/bc/K2NativeCompilerArguments.kt b/kotlin-native/backend.native/cli.bc/src/org/jetbrains/kotlin/cli/bc/K2NativeCompilerArguments.kt new file mode 100644 index 00000000000..942d8ebe913 --- /dev/null +++ b/kotlin-native/backend.native/cli.bc/src/org/jetbrains/kotlin/cli/bc/K2NativeCompilerArguments.kt @@ -0,0 +1,308 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +package org.jetbrains.kotlin.cli.bc + +import org.jetbrains.kotlin.cli.common.arguments.CommonCompilerArguments +import org.jetbrains.kotlin.cli.common.arguments.Argument +import org.jetbrains.kotlin.cli.common.messages.CompilerMessageSeverity +import org.jetbrains.kotlin.cli.common.messages.MessageCollector +import org.jetbrains.kotlin.config.* + +class K2NativeCompilerArguments : CommonCompilerArguments() { + // First go the options interesting to the general public. + // Prepend them with a single dash. + // Keep the list lexically sorted. + + @Argument(value = "-enable-assertions", deprecatedName = "-enable_assertions", shortName = "-ea", description = "Enable runtime assertions in generated code") + var enableAssertions: Boolean = false + + @Argument(value = "-g", description = "Enable emitting debug information") + var debug: Boolean = false + + @Argument(value = "-generate-test-runner", deprecatedName = "-generate_test_runner", + shortName = "-tr", description = "Produce a runner for unit tests") + var generateTestRunner = false + @Argument(value = "-generate-worker-test-runner", + shortName = "-trw", description = "Produce a worker runner for unit tests") + var generateWorkerTestRunner = false + @Argument(value = "-generate-no-exit-test-runner", + shortName = "-trn", description = "Produce a runner for unit tests not forcing exit") + var generateNoExitTestRunner = false + + @Argument(value="-include-binary", deprecatedName = "-includeBinary", shortName = "-ib", valueDescription = "", description = "Pack external binary within the klib") + var includeBinaries: Array? = null + + @Argument(value = "-library", shortName = "-l", valueDescription = "", description = "Link with the library", delimiter = "") + var libraries: Array? = null + + @Argument(value = "-library-version", shortName = "-lv", valueDescription = "", description = "Set library version") + var libraryVersion: String? = null + + @Argument(value = "-list-targets", deprecatedName = "-list_targets", description = "List available hardware targets") + var listTargets: Boolean = false + + @Argument(value = "-manifest", valueDescription = "", description = "Provide a maniferst addend file") + var manifestFile: String? = null + + @Argument(value="-memory-model", valueDescription = "", description = "Memory model to use, 'strict', 'relaxed' and 'experimental' are currently supported") + var memoryModel: String? = "strict" + + @Argument(value="-module-name", deprecatedName = "-module_name", valueDescription = "", description = "Specify a name for the compilation module") + var moduleName: String? = null + + @Argument(value = "-native-library", deprecatedName = "-nativelibrary", shortName = "-nl", + valueDescription = "", description = "Include the native bitcode library", delimiter = "") + var nativeLibraries: Array? = null + + @Argument(value = "-no-default-libs", deprecatedName = "-nodefaultlibs", description = "Don't link the libraries from dist/klib automatically") + var nodefaultlibs: Boolean = false + + @Argument(value = "-no-endorsed-libs", description = "Don't link the endorsed libraries from dist automatically") + var noendorsedlibs: Boolean = false + + @Argument(value = "-nomain", description = "Assume 'main' entry point to be provided by external libraries") + var nomain: Boolean = false + + @Argument(value = "-nopack", description = "Don't pack the library into a klib file") + var nopack: Boolean = false + + @Argument(value="-linker-options", deprecatedName = "-linkerOpts", valueDescription = "", description = "Pass arguments to linker", delimiter = " ") + var linkerArguments: Array? = null + + @Argument(value="-linker-option", valueDescription = "", description = "Pass argument to linker", delimiter = "") + var singleLinkerArguments: Array? = null + + @Argument(value = "-nostdlib", description = "Don't link with stdlib") + var nostdlib: Boolean = false + + @Argument(value = "-opt", description = "Enable optimizations during compilation") + var optimization: Boolean = false + + @Argument(value = "-output", shortName = "-o", valueDescription = "", description = "Output name") + var outputName: String? = null + + @Argument(value = "-entry", shortName = "-e", valueDescription = "", description = "Qualified entry point name") + var mainPackage: String? = null + + @Argument(value = "-produce", shortName = "-p", + valueDescription = "{program|static|dynamic|framework|library|bitcode}", + description = "Specify output file kind") + var produce: String? = null + + @Argument(value = "-repo", shortName = "-r", valueDescription = "", description = "Library search path") + var repositories: Array? = null + + @Argument(value = "-target", valueDescription = "", description = "Set hardware target") + var target: String? = null + + // The rest of the options are only interesting to the developers. + // Make sure to prepend them with -X. + // Keep the list lexically sorted. + + @Argument( + value = "-Xcache-directory", + valueDescription = "", + description = "Path to the directory containing caches", + delimiter = "" + ) + var cacheDirectories: Array? = null + + @Argument( + value = CACHED_LIBRARY, + valueDescription = ",", + description = "Comma-separated paths of a library and its cache", + delimiter = "" + ) + var cachedLibraries: Array? = null + + @Argument(value="-Xcheck-dependencies", deprecatedName = "--check_dependencies", description = "Check dependencies and download the missing ones") + var checkDependencies: Boolean = false + + @Argument(value="-Xcompatible-compiler-version", valueDescription = "", description = "Assume the given compiler version to be binary compatible") + var compatibleCompilerVersions: Array? = null + + @Argument(value = EMBED_BITCODE_FLAG, description = "Embed LLVM IR bitcode as data") + var embedBitcode: Boolean = false + + @Argument(value = EMBED_BITCODE_MARKER_FLAG, description = "Embed placeholder LLVM IR data as a marker") + var embedBitcodeMarker: Boolean = false + + @Argument(value = "-Xemit-lazy-objc-header", description = "") + var emitLazyObjCHeader: String? = null + + @Argument(value = "-Xenable", deprecatedName = "--enable", valueDescription = "", description = "Enable backend phase") + var enablePhases: Array? = null + + @Argument( + value = "-Xexport-library", + valueDescription = "", + description = "A library to be included into produced framework API.\n" + + "Must be one of libraries passed with '-library'", + delimiter = "" + ) + var exportedLibraries: Array? = null + + @Argument(value="-Xdisable-fake-override-validator", description = "Disable IR fake override validator") + var disableFakeOverrideValidator: Boolean = false + + @Argument( + value = "-Xframework-import-header", + valueDescription = "
", + description = "Add additional header import to framework header" + ) + var frameworkImportHeaders: Array? = null + + @Argument( + value = "-Xadd-light-debug", + valueDescription = "{disable|enable}", + description = "Add light debug information for optimized builds. This option is skipped in debug builds.\n" + + "It's enabled by default on Darwin platforms where collected debug information is stored in .dSYM file.\n" + + "Currently option is disabled by default on other platforms." + ) + var lightDebugString: String? = null + + // TODO: remove after 1.4 release. + @Argument(value = "-Xg0", description = "Add light debug information. Deprecated option. Please use instead -Xadd-light-debug=enable") + var lightDebugDeprecated: Boolean = false + + @Argument( + value = MAKE_CACHE, + valueDescription = "", + description = "Path of the library to be compiled to cache", + delimiter = "" + ) + var librariesToCache: Array? = null + + @Argument( + value = ADD_CACHE, + valueDescription = "", + description = "Path to the library to be added to cache", + delimiter = "" + ) + var libraryToAddToCache: String? = null + + @Argument(value = "-Xprint-bitcode", deprecatedName = "--print_bitcode", description = "Print llvm bitcode") + var printBitCode: Boolean = false + + @Argument(value = "-Xprint-descriptors", deprecatedName = "--print_descriptors", description = "Print descriptor tree") + var printDescriptors: Boolean = false + + @Argument(value = "-Xprint-ir", deprecatedName = "--print_ir", description = "Print IR") + var printIr: Boolean = false + + @Argument(value = "-Xprint-ir-with-descriptors", deprecatedName = "--print_ir_with_descriptors", description = "Print IR with descriptors") + var printIrWithDescriptors: Boolean = false + + @Argument(value = "-Xprint-locations", deprecatedName = "--print_locations", description = "Print locations") + var printLocations: Boolean = false + + @Argument(value="-Xpurge-user-libs", deprecatedName = "--purge_user_libs", description = "Don't link unused libraries even explicitly specified") + var purgeUserLibs: Boolean = false + + @Argument(value = "-Xruntime", deprecatedName = "--runtime", valueDescription = "", description = "Override standard 'runtime.bc' location") + var runtimeFile: String? = null + + @Argument( + value = INCLUDE_ARG, + valueDescription = "", + description = "A path to an intermediate library that should be processed in the same manner as source files" + ) + var includes: Array? = null + + @Argument( + value = SHORT_MODULE_NAME_ARG, + valueDescription = "", + description = "A short name used to denote this library in the IDE and in a generated Objective-C header" + ) + var shortModuleName: String? = null + + @Argument(value = STATIC_FRAMEWORK_FLAG, description = "Create a framework with a static library instead of a dynamic one") + var staticFramework: Boolean = false + + @Argument(value = "-Xtemporary-files-dir", deprecatedName = "--temporary_files_dir", valueDescription = "", description = "Save temporary files to the given directory") + var temporaryFilesDir: String? = null + + @Argument(value = "-Xverify-bitcode", deprecatedName = "--verify_bitcode", description = "Verify llvm bitcode after each method") + var verifyBitCode: Boolean = false + + @Argument(value = "-Xverify-compiler", description = "Verify compiler") + var verifyCompiler: String? = null + + @Argument( + value = "-friend-modules", + valueDescription = "", + description = "Paths to friend modules" + ) + var friendModules: String? = null + + @Argument(value = "-Xdebug-info-version", description = "generate debug info of given version (1, 2)") + var debugInfoFormatVersion: String = "1" /* command line parser doesn't accept kotlin.Int type */ + + @Argument(value = "-Xcoverage", description = "emit coverage") + var coverage: Boolean = false + + @Argument( + value = "-Xlibrary-to-cover", + valueDescription = "", + description = "Provide code coverage for the given library.\n" + + "Must be one of libraries passed with '-library'", + delimiter = "" + ) + var coveredLibraries: Array? = null + + @Argument(value = "-Xcoverage-file", valueDescription = "", description = "Save coverage information to the given file") + var coverageFile: String? = null + + @Argument(value = "-Xno-objc-generics", description = "Disable generics support for framework header") + var noObjcGenerics: Boolean = false + + @Argument(value="-Xoverride-clang-options", valueDescription = "", description = "Explicit list of Clang options") + var clangOptions: Array? = null + + @Argument(value="-Xallocator", valueDescription = "std | mimalloc", description = "Allocator used in runtime") + var allocator: String = "std" + + @Argument(value = "-Xmetadata-klib", description = "Produce a klib that only contains the declarations metadata") + var metadataKlib: Boolean = false + + @Argument(value = "-Xdebug-prefix-map", valueDescription = "", description = "Remap file source directory paths in debug info") + var debugPrefixMap: Array? = null + + @Argument( + value = "-Xpre-link-caches", + valueDescription = "{disable|enable}", + description = "Perform caches pre-link" + ) + var preLinkCaches: String? = null + + override fun configureAnalysisFlags(collector: MessageCollector): MutableMap, Any> = + super.configureAnalysisFlags(collector).also { + val useExperimental = it[AnalysisFlags.useExperimental] as List<*> + it[AnalysisFlags.useExperimental] = useExperimental + listOf("kotlin.ExperimentalUnsignedTypes") + if (printIr) + phasesToDumpAfter = arrayOf("ALL") + } + + override fun checkIrSupport(languageVersionSettings: LanguageVersionSettings, collector: MessageCollector) { + if (languageVersionSettings.languageVersion < LanguageVersion.KOTLIN_1_4 + || languageVersionSettings.apiVersion < ApiVersion.KOTLIN_1_4 + ) { + collector.report( + severity = CompilerMessageSeverity.ERROR, + message = "Native backend cannot be used with language or API version below 1.4" + ) + } + } +} + +const val EMBED_BITCODE_FLAG = "-Xembed-bitcode" +const val EMBED_BITCODE_MARKER_FLAG = "-Xembed-bitcode-marker" +const val STATIC_FRAMEWORK_FLAG = "-Xstatic-framework" +const val INCLUDE_ARG = "-Xinclude" +const val CACHED_LIBRARY = "-Xcached-library" +const val MAKE_CACHE = "-Xmake-cache" +const val ADD_CACHE = "-Xadd-cache" +const val SHORT_MODULE_NAME_ARG = "-Xshort-module-name" diff --git a/kotlin-native/backend.native/compiler/ir/backend.native/resources/META-INF/services/org.jetbrains.kotlin.resolve.ExternalOverridabilityCondition b/kotlin-native/backend.native/compiler/ir/backend.native/resources/META-INF/services/org.jetbrains.kotlin.resolve.ExternalOverridabilityCondition new file mode 100644 index 00000000000..d558692ac29 --- /dev/null +++ b/kotlin-native/backend.native/compiler/ir/backend.native/resources/META-INF/services/org.jetbrains.kotlin.resolve.ExternalOverridabilityCondition @@ -0,0 +1 @@ +org.jetbrains.kotlin.backend.konan.ObjCOverridabilityCondition diff --git a/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/common/AbstractValueUsageTransformer.kt b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/common/AbstractValueUsageTransformer.kt new file mode 100644 index 00000000000..86a39a7f153 --- /dev/null +++ b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/common/AbstractValueUsageTransformer.kt @@ -0,0 +1,272 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +package org.jetbrains.kotlin.backend.common + +import org.jetbrains.kotlin.backend.konan.ir.KonanSymbols +import org.jetbrains.kotlin.builtins.KotlinBuiltIns +import org.jetbrains.kotlin.ir.IrStatement +import org.jetbrains.kotlin.ir.declarations.* +import org.jetbrains.kotlin.ir.descriptors.IrBuiltIns +import org.jetbrains.kotlin.ir.expressions.* +import org.jetbrains.kotlin.ir.symbols.* +import org.jetbrains.kotlin.ir.types.IrType +import org.jetbrains.kotlin.ir.util.defaultType +import org.jetbrains.kotlin.ir.visitors.IrElementTransformerVoid +import org.jetbrains.kotlin.ir.visitors.transformChildrenVoid + + +/** + * Transforms expressions depending on the context they are used in. + * + * The transformations are defined with `IrExpression.use*` methods in this class, + * the most common are [useAs], [useAsStatement], [useInTypeOperator]. + * + * TODO: the implementation is originally based on [org.jetbrains.kotlin.psi2ir.transformations.InsertImplicitCasts] + * and should probably be used as its base. + * + * TODO: consider making this visitor non-recursive to make it more general. + */ +internal abstract class AbstractValueUsageTransformer( + val builtIns: KotlinBuiltIns, + val symbols: KonanSymbols, + val irBuiltIns: IrBuiltIns +): IrElementTransformerVoid() { + + protected open fun IrExpression.useAs(type: IrType): IrExpression = this + + protected open fun IrExpression.useAsStatement(): IrExpression = this + + protected open fun IrExpression.useInTypeOperator(operator: IrTypeOperator, typeOperand: IrType): IrExpression = + this + + protected open fun IrExpression.useAsValue(value: IrValueDeclaration): IrExpression = this.useAs(value.type) + + protected open fun IrExpression.useAsArgument(parameter: IrValueParameter): IrExpression = + this.useAsValue(parameter) + + protected open fun IrExpression.useAsDispatchReceiver(expression: IrFunctionAccessExpression): IrExpression = + this.useAsArgument(expression.symbol.owner.dispatchReceiverParameter!!) + + protected open fun IrExpression.useAsExtensionReceiver(expression: IrFunctionAccessExpression): IrExpression = + this.useAsArgument(expression.symbol.owner.extensionReceiverParameter!!) + + protected open fun IrExpression.useAsValueArgument(expression: IrFunctionAccessExpression, + parameter: IrValueParameter + ): IrExpression = + this.useAsArgument(parameter) + + private fun IrExpression.useForVariable(variable: IrVariable): IrExpression = + this.useAsValue(variable) + + private fun IrExpression.useForValue(value: IrValueDeclaration) = + this.useAsValue(value) + + private fun IrExpression.useForField(field: IrField): IrExpression = + this.useAs(field.type) + + protected open fun IrExpression.useAsReturnValue(returnTarget: IrReturnTargetSymbol): IrExpression = + when (returnTarget) { + is IrSimpleFunctionSymbol -> this.useAs(returnTarget.owner.returnType) + is IrConstructorSymbol -> this.useAs(irBuiltIns.unitType) + is IrReturnableBlockSymbol -> this.useAs(returnTarget.owner.type) + else -> error(returnTarget) + } + + protected open fun IrExpression.useAsResult(enclosing: IrExpression): IrExpression = + this.useAs(enclosing.type) + + override fun visitPropertyReference(expression: IrPropertyReference): IrExpression { + TODO() + } + + override fun visitLocalDelegatedPropertyReference(expression: IrLocalDelegatedPropertyReference): IrExpression { + TODO() + } + + override fun visitFunctionReference(expression: IrFunctionReference): IrExpression { + TODO() + } + + override fun visitFunctionAccess(expression: IrFunctionAccessExpression): IrExpression { + expression.transformChildrenVoid(this) + + with(expression) { + dispatchReceiver = dispatchReceiver?.useAsDispatchReceiver(expression) + extensionReceiver = extensionReceiver?.useAsExtensionReceiver(expression) + for (index in symbol.owner.valueParameters.indices) { + val argument = getValueArgument(index) ?: continue + val parameter = symbol.owner.valueParameters[index] + putValueArgument(index, argument.useAsValueArgument(expression, parameter)) + } + } + + return expression + } + + override fun visitBlockBody(body: IrBlockBody): IrBody { + body.transformChildrenVoid(this) + + body.statements.forEachIndexed { i, irStatement -> + if (irStatement is IrExpression) { + body.statements[i] = irStatement.useAsStatement() + } + } + + return body + } + + override fun visitContainerExpression(expression: IrContainerExpression): IrExpression { + expression.transformChildrenVoid(this) + + if (expression.statements.isEmpty()) { + return expression + } + + val lastIndex = expression.statements.lastIndex + expression.statements.forEachIndexed { i, irStatement -> + if (irStatement is IrExpression) { + expression.statements[i] = + if (i == lastIndex) + irStatement.useAsResult(expression) + else + irStatement.useAsStatement() + } + } + + return expression + } + + override fun visitReturn(expression: IrReturn): IrExpression { + expression.transformChildrenVoid(this) + + expression.value = expression.value.useAsReturnValue(expression.returnTargetSymbol) + + return expression + } + + override fun visitSetValue(expression: IrSetValue): IrExpression { + expression.transformChildrenVoid(this) + + expression.value = expression.value.useForValue(expression.symbol.owner) + + return expression + } + + override fun visitSetField(expression: IrSetField): IrExpression { + expression.transformChildrenVoid(this) + + expression.value = expression.value.useForField(expression.symbol.owner) + + return expression + } + + override fun visitField(declaration: IrField): IrStatement { + declaration.transformChildrenVoid(this) + + declaration.initializer?.let { + it.expression = it.expression.useForField(declaration) + } + + return declaration + } + + override fun visitVariable(declaration: IrVariable): IrVariable { + declaration.transformChildrenVoid(this) + + declaration.initializer = declaration.initializer?.useForVariable(declaration) + + return declaration + } + + override fun visitWhen(expression: IrWhen): IrExpression { + expression.transformChildrenVoid(this) + + for (irBranch in expression.branches) { + irBranch.condition = irBranch.condition.useAs(irBuiltIns.booleanType) + irBranch.result = irBranch.result.useAsResult(expression) + } + + return expression + } + + override fun visitLoop(loop: IrLoop): IrExpression { + loop.transformChildrenVoid(this) + + loop.condition = loop.condition.useAs(irBuiltIns.booleanType) + + loop.body = loop.body?.useAsStatement() + + return loop + } + + override fun visitThrow(expression: IrThrow): IrExpression { + expression.transformChildrenVoid(this) + + expression.value = expression.value.useAs(symbols.throwable.owner.defaultType) + + return expression + } + + override fun visitTry(aTry: IrTry): IrExpression { + aTry.transformChildrenVoid(this) + + aTry.tryResult = aTry.tryResult.useAsResult(aTry) + + for (aCatch in aTry.catches) { + aCatch.result = aCatch.result.useAsResult(aTry) + } + + aTry.finallyExpression = aTry.finallyExpression?.useAsStatement() + + return aTry + } + + override fun visitVararg(expression: IrVararg): IrExpression { + expression.transformChildrenVoid(this) + + expression.elements.forEachIndexed { i, element -> + when (element) { + is IrSpreadElement -> + element.expression = element.expression.useAs(expression.type) + is IrExpression -> + expression.putElement(i, element.useAs(expression.varargElementType)) + } + } + + return expression + } + + override fun visitTypeOperator(expression: IrTypeOperatorCall): IrExpression { + expression.transformChildrenVoid(this) + + expression.argument = expression.argument.useInTypeOperator(expression.operator, expression.typeOperand) + + return expression + } + + override fun visitFunction(declaration: IrFunction): IrStatement { + declaration.transformChildrenVoid(this) + + declaration.valueParameters.forEach { parameter -> + val defaultValue = parameter.defaultValue + if (defaultValue is IrExpressionBody) { + defaultValue.expression = defaultValue.expression.useAsArgument(parameter) + } + } + + declaration.body?.let { + if (it is IrExpressionBody) { + it.expression = it.expression.useAsReturnValue(declaration.symbol) + } + } + + return declaration + } + + // TODO: IrStringConcatenation, IrEnumEntry? + +} + diff --git a/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/BinaryType.kt b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/BinaryType.kt new file mode 100644 index 00000000000..b71b206c3d9 --- /dev/null +++ b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/BinaryType.kt @@ -0,0 +1,20 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +package org.jetbrains.kotlin.backend.konan + +sealed class BinaryType { + class Primitive(val type: PrimitiveBinaryType) : BinaryType() + class Reference(val types: Sequence, val nullable: Boolean) : BinaryType() +} + +fun BinaryType<*>.primitiveBinaryTypeOrNull(): PrimitiveBinaryType? = when (this) { + is BinaryType.Primitive -> this.type + is BinaryType.Reference -> null +} + +enum class PrimitiveBinaryType { + BOOLEAN, BYTE, SHORT, INT, LONG, FLOAT, DOUBLE, POINTER, VECTOR128 +} diff --git a/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/BitcodeCompiler.kt b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/BitcodeCompiler.kt new file mode 100644 index 00000000000..eb6a75dfe22 --- /dev/null +++ b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/BitcodeCompiler.kt @@ -0,0 +1,106 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +package org.jetbrains.kotlin.backend.konan + +import org.jetbrains.kotlin.konan.exec.Command +import org.jetbrains.kotlin.konan.target.* + +typealias BitcodeFile = String +typealias ObjectFile = String +typealias ExecutableFile = String + +internal class BitcodeCompiler(val context: Context) { + + private val platform = context.config.platform + private val optimize = context.shouldOptimize() + private val debug = context.config.debug + + private val overrideClangOptions = + context.configuration.getList(KonanConfigKeys.OVERRIDE_CLANG_OPTIONS) + + private fun MutableList.addNonEmpty(elements: List) { + addAll(elements.filter { it.isNotEmpty() }) + } + + private fun runTool(vararg command: String) = + Command(*command) + .logWith(context::log) + .execute() + + private fun temporary(name: String, suffix: String): String = + context.config.tempFiles.create(name, suffix).absolutePath + + private fun targetTool(tool: String, vararg arg: String) { + val absoluteToolName = if (platform.configurables is AppleConfigurables) { + "${platform.absoluteTargetToolchain}/usr/bin/$tool" + } else { + "${platform.absoluteTargetToolchain}/bin/$tool" + } + runTool(absoluteToolName, *arg) + } + + private fun hostLlvmTool(tool: String, vararg arg: String) { + val absoluteToolName = "${platform.absoluteLlvmHome}/bin/$tool" + runTool(absoluteToolName, *arg) + } + + private fun clang(configurables: ClangFlags, file: BitcodeFile): ObjectFile { + val objectFile = temporary("result", ".o") + + val profilingFlags = llvmProfilingFlags().map { listOf("-mllvm", it) }.flatten() + + // LLVM we use does not have support for arm64_32. + // TODO: fix with LLVM update. + val targetTriple = when (context.config.target) { + KonanTarget.WATCHOS_ARM64 -> { + require(configurables is AppleConfigurables) + "arm64_32-apple-watchos${configurables.osVersionMin}" + } + else -> context.llvm.targetTriple + } + val flags = overrideClangOptions.takeIf(List::isNotEmpty) + ?: mutableListOf().apply { + addNonEmpty(configurables.clangFlags) + addNonEmpty(listOf("-triple", targetTriple)) + if (configurables is ZephyrConfigurables) { + addNonEmpty(configurables.constructClangCC1Args()) + } + addNonEmpty(when { + optimize -> configurables.clangOptFlags + debug -> configurables.clangDebugFlags + else -> configurables.clangNooptFlags + }) + addNonEmpty(BitcodeEmbedding.getClangOptions(context.config)) + if (determineLinkerOutput(context) == LinkerOutputKind.DYNAMIC_LIBRARY) { + addNonEmpty(configurables.clangDynamicFlags) + } + addNonEmpty(profilingFlags) + } + if (configurables is AppleConfigurables) { + targetTool("clang++", *flags.toTypedArray(), file, "-o", objectFile) + } else { + hostLlvmTool("clang++", *flags.toTypedArray(), file, "-o", objectFile) + } + return objectFile + } + + private fun llvmProfilingFlags(): List { + val flags = mutableListOf() + if (context.shouldProfilePhases()) { + flags += "-time-passes" + } + if (context.inVerbosePhase) { + flags += "-debug-pass=Structure" + } + return flags + } + + fun makeObjectFiles(bitcodeFile: BitcodeFile): List = + listOf(when (val configurables = platform.configurables) { + is ClangFlags -> clang(configurables, bitcodeFile) + else -> error("Unsupported configurables kind: ${configurables::class.simpleName}!") + }) +} \ No newline at end of file diff --git a/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/BitcodeEmbedding.kt b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/BitcodeEmbedding.kt new file mode 100644 index 00000000000..8f71776b589 --- /dev/null +++ b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/BitcodeEmbedding.kt @@ -0,0 +1,22 @@ +package org.jetbrains.kotlin.backend.konan + +object BitcodeEmbedding { + + enum class Mode { + NONE, MARKER, FULL + } + + internal fun getLinkerOptions(config: KonanConfig): List = when (config.bitcodeEmbeddingMode) { + Mode.NONE -> emptyList() + Mode.MARKER -> listOf("-bitcode_bundle", "-bitcode_process_mode", "marker") + Mode.FULL -> listOf("-bitcode_bundle") + } + + internal fun getClangOptions(config: KonanConfig): List = when (config.bitcodeEmbeddingMode) { + Mode.NONE -> listOf("-fembed-bitcode=off") + Mode.MARKER -> listOf("-fembed-bitcode=marker") + Mode.FULL -> listOf("-fembed-bitcode=all") + } + + private val KonanConfig.bitcodeEmbeddingMode get() = configuration.get(KonanConfigKeys.BITCODE_EMBEDDING_MODE)!! +} \ No newline at end of file diff --git a/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/Boxing.kt b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/Boxing.kt new file mode 100644 index 00000000000..a6b01056bde --- /dev/null +++ b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/Boxing.kt @@ -0,0 +1,227 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +package org.jetbrains.kotlin.backend.konan + +import llvm.* +import org.jetbrains.kotlin.backend.konan.ir.KonanSymbols +import org.jetbrains.kotlin.backend.konan.llvm.* +import org.jetbrains.kotlin.descriptors.Modality +import org.jetbrains.kotlin.descriptors.DescriptorVisibilities +import org.jetbrains.kotlin.ir.declarations.* +import org.jetbrains.kotlin.ir.declarations.impl.IrFunctionImpl +import org.jetbrains.kotlin.ir.declarations.impl.IrValueParameterImpl +import org.jetbrains.kotlin.ir.descriptors.IrBuiltIns +import org.jetbrains.kotlin.ir.descriptors.WrappedSimpleFunctionDescriptor +import org.jetbrains.kotlin.ir.descriptors.WrappedValueParameterDescriptor +import org.jetbrains.kotlin.ir.symbols.IrSimpleFunctionSymbol +import org.jetbrains.kotlin.ir.symbols.impl.IrSimpleFunctionSymbolImpl +import org.jetbrains.kotlin.ir.symbols.impl.IrValueParameterSymbolImpl +import org.jetbrains.kotlin.ir.types.IrType +import org.jetbrains.kotlin.ir.util.* +import org.jetbrains.kotlin.konan.target.KonanTarget +import org.jetbrains.kotlin.name.Name + +internal fun KonanSymbols.getTypeConversion(actualType: IrType, expectedType: IrType): IrSimpleFunctionSymbol? = + getTypeConversionImpl(actualType.getInlinedClassNative(), expectedType.getInlinedClassNative()) + +private fun KonanSymbols.getTypeConversionImpl( + actualInlinedClass: IrClass?, + expectedInlinedClass: IrClass? +): IrSimpleFunctionSymbol? { + if (actualInlinedClass == expectedInlinedClass) return null + + return when { + actualInlinedClass == null && expectedInlinedClass == null -> null + actualInlinedClass != null && expectedInlinedClass == null -> context.getBoxFunction(actualInlinedClass) + actualInlinedClass == null && expectedInlinedClass != null -> context.getUnboxFunction(expectedInlinedClass) + else -> error("actual type is ${actualInlinedClass?.fqNameForIrSerialization}, expected ${expectedInlinedClass?.fqNameForIrSerialization}") + }?.symbol +} + +internal object DECLARATION_ORIGIN_INLINE_CLASS_SPECIAL_FUNCTION : IrDeclarationOriginImpl("INLINE_CLASS_SPECIAL_FUNCTION") + +internal val Context.getBoxFunction: (IrClass) -> IrSimpleFunction by Context.lazyMapMember { inlinedClass -> + assert(inlinedClass.isUsedAsBoxClass()) + assert(inlinedClass.parent is IrFile) { "Expected top level inline class" } + + val symbols = ir.symbols + + val isNullable = inlinedClass.inlinedClassIsNullable() + val unboxedType = inlinedClass.defaultOrNullableType(isNullable) + val boxedType = symbols.any.owner.defaultOrNullableType(isNullable) + + val parameterType = unboxedType + val returnType = boxedType + + val startOffset = inlinedClass.startOffset + val endOffset = inlinedClass.endOffset + + val descriptor = WrappedSimpleFunctionDescriptor() + IrFunctionImpl( + startOffset, endOffset, + DECLARATION_ORIGIN_INLINE_CLASS_SPECIAL_FUNCTION, + IrSimpleFunctionSymbolImpl(descriptor), + Name.special("<${inlinedClass.name}-box>"), + DescriptorVisibilities.PUBLIC, + Modality.FINAL, + returnType, + isInline = false, + isExternal = false, + isTailrec = false, + isSuspend = false, + isExpect = false, + isFakeOverride = false, + isOperator = false, + isInfix = false + ).also { function -> + function.valueParameters = listOf(WrappedValueParameterDescriptor().let { + IrValueParameterImpl( + startOffset, endOffset, + IrDeclarationOrigin.DEFINED, + IrValueParameterSymbolImpl(it), + Name.identifier("value"), + index = 0, + varargElementType = null, + isCrossinline = false, + type = parameterType, + isNoinline = false + ).apply { + it.bind(this) + parent = function + } + }) + descriptor.bind(function) + function.parent = inlinedClass.getContainingFile()!! + } +} + +internal val Context.getUnboxFunction: (IrClass) -> IrSimpleFunction by Context.lazyMapMember { inlinedClass -> + assert(inlinedClass.isUsedAsBoxClass()) + assert(inlinedClass.parent is IrFile) { "Expected top level inline class" } + + val symbols = ir.symbols + + val isNullable = inlinedClass.inlinedClassIsNullable() + val unboxedType = inlinedClass.defaultOrNullableType(isNullable) + val boxedType = symbols.any.owner.defaultOrNullableType(isNullable) + + val parameterType = boxedType + val returnType = unboxedType + + val startOffset = inlinedClass.startOffset + val endOffset = inlinedClass.endOffset + + val descriptor = WrappedSimpleFunctionDescriptor() + IrFunctionImpl( + startOffset, endOffset, + DECLARATION_ORIGIN_INLINE_CLASS_SPECIAL_FUNCTION, + IrSimpleFunctionSymbolImpl(descriptor), + Name.special("<${inlinedClass.name}-unbox>"), + DescriptorVisibilities.PUBLIC, + Modality.FINAL, + returnType, + isInline = false, + isExternal = false, + isTailrec = false, + isSuspend = false, + isExpect = false, + isFakeOverride = false, + isOperator = false, + isInfix = false + ).also { function -> + function.valueParameters = listOf(WrappedValueParameterDescriptor().let { + IrValueParameterImpl( + startOffset, endOffset, + IrDeclarationOrigin.DEFINED, + IrValueParameterSymbolImpl(it), + Name.identifier("value"), + index = 0, + varargElementType = null, + isCrossinline = false, + type = parameterType, + isNoinline = false + ).apply { + it.bind(this) + parent = function + } + }) + descriptor.bind(function) + function.parent = inlinedClass.getContainingFile()!! + } +} + +/** + * Initialize static boxing. + * If output target is native binary then the cache is created. + */ +internal fun initializeCachedBoxes(context: Context) { + if (context.producedLlvmModuleContainsStdlib) { + BoxCache.values().forEach { cache -> + val cacheName = "${cache.name}_CACHE" + val rangeStart = "${cache.name}_RANGE_FROM" + val rangeEnd = "${cache.name}_RANGE_TO" + initCache(cache, context, cacheName, rangeStart, rangeEnd) + } + } +} + +/** + * Adds global that refers to the cache. + */ +private fun initCache(cache: BoxCache, context: Context, cacheName: String, + rangeStartName: String, rangeEndName: String) { + + val kotlinType = context.irBuiltIns.getKotlinClass(cache) + val staticData = context.llvm.staticData + val llvmType = staticData.getLLVMType(kotlinType.defaultType) + + val (start, end) = context.config.target.getBoxCacheRange(cache) + // Constancy of these globals allows LLVM's constant propagation and DCE + // to remove fast path of boxing function in case of empty range. + staticData.placeGlobal(rangeStartName, createConstant(llvmType, start), true) + .setConstant(true) + staticData.placeGlobal(rangeEndName, createConstant(llvmType, end), true) + .setConstant(true) + val values = (start..end).map { staticData.createInitializer(kotlinType, createConstant(llvmType, it)) } + val llvmBoxType = structType(context.llvm.runtime.objHeaderType, llvmType) + staticData.placeGlobalConstArray(cacheName, llvmBoxType, values, true).llvm +} + +private fun createConstant(llvmType: LLVMTypeRef, value: Int): ConstValue = + constValue(LLVMConstInt(llvmType, value.toLong(), 1)!!) + +// When start is greater than end then `inRange` check is always false +// and can be eliminated by LLVM. +private val emptyRange = 1 to 0 + +// Memory usage is around 20kb. +private val BoxCache.defaultRange get() = when (this) { + BoxCache.BOOLEAN -> (0 to 1) + BoxCache.BYTE -> (-128 to 127) + BoxCache.SHORT -> (-128 to 127) + BoxCache.CHAR -> (0 to 255) + BoxCache.INT -> (-128 to 127) + BoxCache.LONG -> (-128 to 127) +} + +private fun KonanTarget.getBoxCacheRange(cache: BoxCache): Pair = when (this) { + is KonanTarget.ZEPHYR -> emptyRange + else -> cache.defaultRange +} + +internal fun IrBuiltIns.getKotlinClass(cache: BoxCache): IrClass = when (cache) { + BoxCache.BOOLEAN -> booleanClass + BoxCache.BYTE -> byteClass + BoxCache.SHORT -> shortClass + BoxCache.CHAR -> charClass + BoxCache.INT -> intClass + BoxCache.LONG -> longClass +}.owner + +// TODO: consider adding box caches for unsigned types. +enum class BoxCache { + BOOLEAN, BYTE, SHORT, CHAR, INT, LONG +} diff --git a/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/BuiltInFictitiousFunctionIrClassFactory.kt b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/BuiltInFictitiousFunctionIrClassFactory.kt new file mode 100644 index 00000000000..a3afe3410a3 --- /dev/null +++ b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/BuiltInFictitiousFunctionIrClassFactory.kt @@ -0,0 +1,351 @@ +/* + * Copyright 2010-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +package org.jetbrains.kotlin.backend.konan + +import org.jetbrains.kotlin.backend.common.ir.copyTo +import org.jetbrains.kotlin.backend.common.ir.createDispatchReceiverParameter +import org.jetbrains.kotlin.backend.common.ir.createParameterDeclarations +import org.jetbrains.kotlin.backend.common.ir.simpleFunctions +import org.jetbrains.kotlin.backend.konan.descriptors.findPackage +import org.jetbrains.kotlin.builtins.functions.FunctionClassDescriptor +import org.jetbrains.kotlin.builtins.functions.FunctionClassKind +import org.jetbrains.kotlin.descriptors.* +import org.jetbrains.kotlin.incremental.components.NoLookupLocation +import org.jetbrains.kotlin.ir.declarations.* +import org.jetbrains.kotlin.ir.declarations.impl.* +import org.jetbrains.kotlin.ir.descriptors.IrAbstractFunctionFactory +import org.jetbrains.kotlin.ir.descriptors.IrBuiltIns +import org.jetbrains.kotlin.ir.linkage.IrProvider +import org.jetbrains.kotlin.ir.symbols.IrClassSymbol +import org.jetbrains.kotlin.ir.symbols.IrPropertySymbol +import org.jetbrains.kotlin.ir.symbols.IrSimpleFunctionSymbol +import org.jetbrains.kotlin.ir.symbols.IrSymbol +import org.jetbrains.kotlin.ir.symbols.impl.* +import org.jetbrains.kotlin.ir.types.IrType +import org.jetbrains.kotlin.ir.types.classOrNull +import org.jetbrains.kotlin.ir.types.defaultType +import org.jetbrains.kotlin.ir.types.impl.* +import org.jetbrains.kotlin.ir.util.* +import org.jetbrains.kotlin.name.ClassId +import org.jetbrains.kotlin.resolve.scopes.DescriptorKindFilter +import org.jetbrains.kotlin.types.KotlinType +import org.jetbrains.kotlin.util.OperatorNameConventions + +internal object DECLARATION_ORIGIN_FUNCTION_CLASS : IrDeclarationOriginImpl("DECLARATION_ORIGIN_FUNCTION_CLASS") + +internal class BuiltInFictitiousFunctionIrClassFactory( + var symbolTable: SymbolTable?, + private val irBuiltIns: IrBuiltIns, + private val reflectionTypes: KonanReflectionTypes +) : IrAbstractFunctionFactory(), IrProvider { + + override fun getDeclaration(symbol: IrSymbol) = + (symbol.descriptor as? FunctionClassDescriptor)?.let { descriptor -> + buildClass(descriptor) { + declareClass(descriptor) { + createIrClass(it, descriptor) + } + } + } + + var module: IrModuleFragment? = null + set(value) { + if (value == null) + error("Provide a valid non-null module") + if (field != null) + error("Module has already been set") + field = value + value.files += filesMap.values +// builtClasses.forEach { it.addFakeOverrides() } + } + + class FunctionalInterface(val irClass: IrClass, val arity: Int) + + fun buildAllClasses() { + val maxArity = 255 // See [BuiltInFictitiousFunctionClassFactory]. + (0 .. maxArity).forEach { arity -> + functionN(arity) + kFunctionN(arity) + suspendFunctionN(arity) + kSuspendFunctionN(arity) + } + } + + override fun functionClassDescriptor(arity: Int): FunctionClassDescriptor = + irBuiltIns.builtIns.getFunction(arity) as FunctionClassDescriptor + + override fun kFunctionClassDescriptor(arity: Int): FunctionClassDescriptor = + reflectionTypes.getKFunction(arity) as FunctionClassDescriptor + + override fun suspendFunctionClassDescriptor(arity: Int): FunctionClassDescriptor = + irBuiltIns.builtIns.getSuspendFunction(arity) as FunctionClassDescriptor + + override fun kSuspendFunctionClassDescriptor(arity: Int): FunctionClassDescriptor = + reflectionTypes.getKSuspendFunction(arity) as FunctionClassDescriptor + + override fun functionN(arity: Int, declarator: SymbolTable.((IrClassSymbol) -> IrClass) -> IrClass): IrClass = + buildClass(irBuiltIns.builtIns.getFunction(arity) as FunctionClassDescriptor, declarator) + + override fun kFunctionN(arity: Int, declarator: SymbolTable.((IrClassSymbol) -> IrClass) -> IrClass): IrClass = + buildClass(reflectionTypes.getKFunction(arity) as FunctionClassDescriptor, declarator) + + override fun suspendFunctionN(arity: Int, declarator: SymbolTable.((IrClassSymbol) -> IrClass) -> IrClass): IrClass = + buildClass(irBuiltIns.builtIns.getSuspendFunction(arity) as FunctionClassDescriptor, declarator) + + override fun kSuspendFunctionN(arity: Int, declarator: SymbolTable.((IrClassSymbol) -> IrClass) -> IrClass): IrClass = + buildClass(reflectionTypes.getKSuspendFunction(arity) as FunctionClassDescriptor, declarator) + + private val functionSymbol = symbolTable!!.referenceClass( + irBuiltIns.builtIns.builtInsModule.findClassAcrossModuleDependencies( + ClassId.topLevel(KonanFqNames.function))!!) + + private val kFunctionSymbol = symbolTable!!.referenceClass( + irBuiltIns.builtIns.builtInsModule.findClassAcrossModuleDependencies( + ClassId.topLevel(KonanFqNames.kFunction))!!) + + private val filesMap = mutableMapOf() + + private val builtClassesMap = mutableMapOf() + + val builtClasses get() = builtClassesMap.values + + val builtFunctionNClasses get() = builtClassesMap.values.mapNotNull { + with(it.descriptor as FunctionClassDescriptor) { + if (functionKind == FunctionClassKind.Function) + FunctionalInterface(it, arity) + else null + } + } + + private fun createTypeParameter(descriptor: TypeParameterDescriptor): IrTypeParameter = + symbolTable?.declareGlobalTypeParameter( + SYNTHETIC_OFFSET, SYNTHETIC_OFFSET, DECLARATION_ORIGIN_FUNCTION_CLASS, + descriptor + ) + ?: IrTypeParameterImpl( + SYNTHETIC_OFFSET, + SYNTHETIC_OFFSET, + DECLARATION_ORIGIN_FUNCTION_CLASS, + IrTypeParameterSymbolImpl(descriptor), + descriptor.name, + descriptor.index, + descriptor.isReified, + descriptor.variance + ) + + private fun createSimpleFunction( + descriptor: FunctionDescriptor, + origin: IrDeclarationOrigin, + returnType: IrType + ): IrSimpleFunction { + val functionFactory: (IrSimpleFunctionSymbol) -> IrSimpleFunction = { + with(descriptor) { + IrFunctionImpl( + SYNTHETIC_OFFSET, SYNTHETIC_OFFSET, origin, it, name, visibility, modality, returnType, + isInline, isExternal, isTailrec, isSuspend, isOperator, isInfix, isExpect + ) + } + } + return symbolTable?.declareSimpleFunction(descriptor, functionFactory) + ?: functionFactory(IrSimpleFunctionSymbolImpl(descriptor)) + } + + private fun createIrClass(symbol: IrClassSymbol, descriptor: ClassDescriptor): IrClass = + IrFactoryImpl.createIrClassFromDescriptor(offset, offset, DECLARATION_ORIGIN_FUNCTION_CLASS, symbol, descriptor) + + private fun createClass(descriptor: FunctionClassDescriptor, declarator: SymbolTable.((IrClassSymbol) -> IrClass) -> IrClass): IrClass = + symbolTable?.declarator { createIrClass(it, descriptor) } + ?: createIrClass(IrClassSymbolImpl(descriptor), descriptor) + + private fun buildClass(descriptor: FunctionClassDescriptor, declarator: SymbolTable.((IrClassSymbol) -> IrClass) -> IrClass): IrClass = + builtClassesMap.getOrPut(descriptor) { + createClass(descriptor, declarator).apply { + val functionClass = this + typeParameters += descriptor.declaredTypeParameters.map { typeParameterDescriptor -> + createTypeParameter(typeParameterDescriptor).also { + it.parent = this + it.superTypes += irBuiltIns.anyNType + } + } + + val descriptorToIrParametersMap = typeParameters.map { it.descriptor to it }.toMap() + superTypes += descriptor.typeConstructor.supertypes.map { superType -> + val arguments = superType.arguments.map { argument -> + val argumentClassifierDescriptor = argument.type.constructor.declarationDescriptor + val argumentClassifierSymbol = argumentClassifierDescriptor?.let { descriptorToIrParametersMap[it] } + ?: error("Unexpected super type argument: $argumentClassifierDescriptor") + makeTypeProjection(argumentClassifierSymbol.defaultType, argument.projectionKind) + } + val superTypeSymbol = when (val superTypeDescriptor = superType.constructor.declarationDescriptor) { + is FunctionClassDescriptor -> buildClass(superTypeDescriptor) { + declareClass(superTypeDescriptor) { + createIrClass(it, superTypeDescriptor) + } + }.symbol + functionSymbol.descriptor -> functionSymbol + kFunctionSymbol.descriptor -> kFunctionSymbol + else -> error("Unexpected super type: $superTypeDescriptor") + } + IrSimpleTypeImpl(superTypeSymbol, superType.isMarkedNullable, arguments, emptyList()) + } + + createParameterDeclarations() + + val invokeFunctionDescriptor = descriptor.unsubstitutedMemberScope.getContributedFunctions( + OperatorNameConventions.INVOKE, NoLookupLocation.FROM_BACKEND).single() + val isFakeOverride = invokeFunctionDescriptor.kind == CallableMemberDescriptor.Kind.FAKE_OVERRIDE + if (!isFakeOverride) { + val invokeFunctionOrigin = + if (isFakeOverride) + IrDeclarationOrigin.FAKE_OVERRIDE + else + DECLARATION_ORIGIN_FUNCTION_CLASS + declarations += createSimpleFunction( + invokeFunctionDescriptor, invokeFunctionOrigin, + typeParameters.last().defaultType + ).apply { + parent = functionClass + valueParameters += invokeFunctionDescriptor.valueParameters.map { + IrValueParameterImpl( + SYNTHETIC_OFFSET, SYNTHETIC_OFFSET, invokeFunctionOrigin, + IrValueParameterSymbolImpl(it), it.name, it.index, + functionClass.typeParameters[it.index].defaultType, null, + it.isCrossinline, it.isNoinline + ).also { it.parent = this } + } + if (!isFakeOverride) + createDispatchReceiverParameter(invokeFunctionOrigin) + else { + val overriddenFunction = superTypes + .mapNotNull { it.classOrNull?.owner } + .single { it.descriptor is FunctionClassDescriptor } + .simpleFunctions() + .single { it.name == OperatorNameConventions.INVOKE } + overriddenSymbols += overriddenFunction.symbol + dispatchReceiverParameter = overriddenFunction.dispatchReceiverParameter?.copyTo(this) + } + } + } + // Unfortunately, addFakeOverrides() uses some parents but they are only set after PsiToIr phase. + // So we add all the fake overrides only when we're supplied with the module (this is done after PsiToIr). +// if (this@BuiltInFictitiousFunctionIrClassFactory.module != null) + addFakeOverrides() + + val packageFragmentDescriptor = descriptor.findPackage() + val file = filesMap.getOrPut(packageFragmentDescriptor) { + IrFileImpl(NaiveSourceBasedFileEntryImpl("[K][Suspend]Functions"), packageFragmentDescriptor).also { + this@BuiltInFictitiousFunctionIrClassFactory.module?.files?.add(it) + } + } + parent = file + file.declarations += this + } + } + + private fun toIrType(wrapped: KotlinType): IrType { + val kotlinType = wrapped.unwrap() + return with(IrSimpleTypeBuilder()) { + classifier = + symbolTable?.referenceClassifier(kotlinType.constructor.declarationDescriptor ?: error("No classifier for type $kotlinType")) + hasQuestionMark = kotlinType.isMarkedNullable + arguments = kotlinType.arguments.map { + if (it.isStarProjection) IrStarProjectionImpl + else makeTypeProjection(toIrType(it.type), it.projectionKind) + } + buildSimpleType() + } + } + + private fun IrFunction.createValueParameter(descriptor: ParameterDescriptor): IrValueParameter { + val varargType = if (descriptor is ValueParameterDescriptor) descriptor.varargElementType else null + return IrValueParameterImpl( + offset, + offset, + memberOrigin, + IrValueParameterSymbolImpl(descriptor), + descriptor.name, + descriptor.indexOrMinusOne, + toIrType(descriptor.type), + varargType?.let { toIrType(it) }, + descriptor.isCrossinline, + descriptor.isNoinline + ).also { + it.parent = this + } + } + + private fun IrClass.addFakeOverrides() { + + val fakeOverrideDescriptors = descriptor.unsubstitutedMemberScope.getContributedDescriptors(DescriptorKindFilter.CALLABLES) + .filterIsInstance().filter { it.kind === CallableMemberDescriptor.Kind.FAKE_OVERRIDE } + + fun createFakeOverrideFunction(descriptor: FunctionDescriptor, property: IrPropertySymbol?): IrSimpleFunction { + val returnType = descriptor.returnType?.let { toIrType(it) } ?: error("No return type for $descriptor") + + + val functionDeclare = { s: IrSimpleFunctionSymbol -> + descriptor.run { + IrFunctionImpl( + offset, offset, memberOrigin, s, name, visibility, modality, returnType, + isInline, isExternal, isTailrec, isSuspend, isOperator, isInfix, isExpect, + isFakeOverride = true + ) + } + } + + val newFunction = symbolTable?.declareSimpleFunction(descriptor, functionDeclare) + ?: functionDeclare(IrSimpleFunctionSymbolImpl(descriptor)) + + newFunction.parent = this + newFunction.overriddenSymbols = descriptor.overriddenDescriptors.mapNotNull { symbolTable?.referenceSimpleFunction(it.original) } + newFunction.dispatchReceiverParameter = descriptor.dispatchReceiverParameter?.let { newFunction.createValueParameter(it) } + newFunction.extensionReceiverParameter = descriptor.extensionReceiverParameter?.let { newFunction.createValueParameter(it) } + newFunction.valueParameters = descriptor.valueParameters.map { newFunction.createValueParameter(it) } + newFunction.correspondingPropertySymbol = property + + return newFunction + } + + fun createFakeOverrideProperty(descriptor: PropertyDescriptor): IrProperty { + val propertyDeclare = { s: IrPropertySymbol -> + IrPropertyImpl( + startOffset = offset, + endOffset = offset, + origin = memberOrigin, + symbol = s, + name = descriptor.name, + visibility = descriptor.visibility, + modality = descriptor.modality, + isVar = descriptor.isVar, + isConst = descriptor.isConst, + isLateinit = descriptor.isLateInit, + isDelegated = descriptor.isDelegated, + isExternal = descriptor.isExternal, + isExpect = descriptor.isExpect, + isFakeOverride = memberOrigin == IrDeclarationOrigin.FAKE_OVERRIDE) + } + val property = symbolTable?.declareProperty(offset, offset, memberOrigin, descriptor, propertyFactory = propertyDeclare) + ?: propertyDeclare(IrPropertySymbolImpl(descriptor)) + + property.parent = this + property.getter = descriptor.getter?.let { g -> createFakeOverrideFunction(g, property.symbol) } + property.setter = descriptor.setter?.let { s -> createFakeOverrideFunction(s, property.symbol) } + + return property + } + + + fun createFakeOverride(descriptor: CallableMemberDescriptor): IrDeclaration { + return when (descriptor) { + is FunctionDescriptor -> createFakeOverrideFunction(descriptor, null) + is PropertyDescriptor -> createFakeOverrideProperty(descriptor) + else -> error("Unexpected member $descriptor") + } + } + + declarations += fakeOverrideDescriptors.map { createFakeOverride(it) } + } +} diff --git a/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/CAdapterCompile.kt b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/CAdapterCompile.kt new file mode 100644 index 00000000000..a9090f656af --- /dev/null +++ b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/CAdapterCompile.kt @@ -0,0 +1,15 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +package org.jetbrains.kotlin.backend.konan + +import org.jetbrains.kotlin.konan.exec.* +import org.jetbrains.kotlin.konan.target.* +import org.jetbrains.kotlin.konan.file.* + +fun produceCAdapterBitcode(clang: ClangArgs, cppFileName: String, bitcodeFileName: String) { + val clangCommand = clang.clangCXX("-std=c++14", cppFileName, "-emit-llvm", "-c", "-o", bitcodeFileName) + Command(clangCommand).execute() +} diff --git a/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/CAdapterGenerator.kt b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/CAdapterGenerator.kt new file mode 100644 index 00000000000..1c2a88efdb8 --- /dev/null +++ b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/CAdapterGenerator.kt @@ -0,0 +1,1129 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +package org.jetbrains.kotlin.backend.konan + +import kotlinx.cinterop.cValuesOf +import java.io.PrintWriter +import llvm.* +import org.jetbrains.kotlin.backend.common.descriptors.allParameters +import org.jetbrains.kotlin.backend.common.descriptors.explicitParameters +import org.jetbrains.kotlin.backend.common.pop +import org.jetbrains.kotlin.backend.common.push +import org.jetbrains.kotlin.backend.konan.ir.isOverridable +import org.jetbrains.kotlin.backend.konan.llvm.* +import org.jetbrains.kotlin.builtins.UnsignedType +import org.jetbrains.kotlin.descriptors.* +import org.jetbrains.kotlin.descriptors.annotations.AnnotationDescriptor +import org.jetbrains.kotlin.ir.declarations.IrClass +import org.jetbrains.kotlin.ir.declarations.IrEnumEntry +import org.jetbrains.kotlin.ir.declarations.IrFunction +import org.jetbrains.kotlin.ir.util.SymbolTable +import org.jetbrains.kotlin.ir.util.isEnumClass +import org.jetbrains.kotlin.ir.util.isEnumEntry +import org.jetbrains.kotlin.ir.util.referenceFunction +import org.jetbrains.kotlin.konan.target.* +import org.jetbrains.kotlin.name.isChildOf +import org.jetbrains.kotlin.name.FqName +import org.jetbrains.kotlin.resolve.annotations.* +import org.jetbrains.kotlin.resolve.DescriptorUtils +import org.jetbrains.kotlin.resolve.descriptorUtil.* +import org.jetbrains.kotlin.types.KotlinType +import org.jetbrains.kotlin.types.TypeUtils +import org.jetbrains.kotlin.types.typeUtil.isNothing +import org.jetbrains.kotlin.types.typeUtil.isUnit +import org.jetbrains.kotlin.types.typeUtil.makeNullable + +private enum class ScopeKind { + TOP, + CLASS, + PACKAGE +} + +private enum class ElementKind { + FUNCTION, + PROPERTY, + TYPE +} + +private enum class DefinitionKind { + C_HEADER_DECLARATION, + C_HEADER_STRUCT, + C_SOURCE_DECLARATION, + C_SOURCE_STRUCT +} + +private enum class Direction { + KOTLIN_TO_C, + C_TO_KOTLIN +} + +private operator fun String.times(count: Int): String { + val builder = StringBuilder() + repeat(count, { builder.append(this) }) + return builder.toString() +} + +private val KotlinType.shortNameForPredefinedType + get() = this.toString().split('.').last() + + +private val KotlinType.createNullableNameForPredefinedType + get() = "createNullable${this.shortNameForPredefinedType}" + +internal val cKeywords = setOf( + // Actual C keywords. + "auto", "break", "case", + "char", "const", "continue", + "default", "do", "double", + "else", "enum", "extern", + "float", "for", "goto", + "if", "int", "long", + "register", "return", + "short", "signed", "sizeof", "static", "struct", "switch", + "typedef", "union", "unsigned", + "void", "volatile", "while", + // C99-specific. + "_Bool", "_Complex", "_Imaginary", "inline", "restrict", + // C11-specific. + "_Alignas", "_Alignof", "_Atomic", "_Generic", "_Noreturn", "_Static_assert", "_Thread_local", + // Not exactly keywords, but reserved or standard-defined. + "and", "not", "or", "xor", + "bool", "complex", "imaginary", + + // C++ keywords not listed above. + "alignas", "alignof", "and_eq", "asm", + "bitand", "bitor", "bool", + "catch", "char16_t", "char32_t", "class", "compl", "constexpr", "const_cast", + "decltype", "delete", "dynamic_cast", + "explicit", "export", + "false", "friend", + "inline", + "mutable", + "namespace", "new", "noexcept", "not_eq", "nullptr", + "operator", "or_eq", + "private", "protected", "public", + "reinterpret_cast", + "static_assert", + "template", "this", "thread_local", "throw", "true", "try", "typeid", "typename", + "using", + "virtual", + "wchar_t", + "xor_eq" +) + +private fun isExportedFunction(descriptor: FunctionDescriptor): Boolean { + if (!descriptor.isEffectivelyPublicApi || !descriptor.kind.isReal || descriptor.isExpect) + return false + if (descriptor.isSuspend) + return false + return !descriptor.typeParameters.any() +} + +private fun isExportedClass(descriptor: ClassDescriptor): Boolean { + if (!descriptor.isEffectivelyPublicApi) return false + // No sense to export annotations. + if (DescriptorUtils.isAnnotationClass(descriptor)) return false + // Do not export expect classes. + if (descriptor.isExpect) return false + // Do not export types with type parameters. + // TODO: is it correct? + if (!descriptor.declaredTypeParameters.isEmpty()) return false + // Do not export inline classes for now. TODO: add proper support. + if (descriptor.isInlined()) return false + + return true +} + +internal fun AnnotationDescriptor.properValue(key: String) = + this.argumentValue(key)?.toString()?.removeSurrounding("\"") + +private fun functionImplName(descriptor: DeclarationDescriptor, default: String, shortName: Boolean): String { + assert(descriptor is FunctionDescriptor) + val annotation = descriptor.annotations.findAnnotation(RuntimeNames.cnameAnnotation) ?: return default + val key = if (shortName) "shortName" else "externName" + val value = annotation.properValue(key) + return value.takeIf { value != null && value.isNotEmpty() } ?: default +} + +internal data class SignatureElement(val name: String, val type: KotlinType) + +private class ExportedElementScope(val kind: ScopeKind, val name: String) { + val elements = mutableListOf() + val scopes = mutableListOf() + private val scopeNames = mutableSetOf() + private val scopeNamesMap = mutableMapOf, String>() + + override fun toString(): String { + return "$kind: $name ${elements.joinToString(", ")} ${scopes.joinToString("\n")}" + } + + fun generateCAdapters() { + elements.forEach { + it.generateCAdapter() + } + scopes.forEach { + it.generateCAdapters() + } + } + + fun scopeUniqueName(descriptor: DeclarationDescriptor, shortName: Boolean): String { + scopeNamesMap[descriptor to shortName]?.apply { return this } + var computedName = when (descriptor) { + is ConstructorDescriptor -> "${descriptor.constructedClass.fqNameSafe.shortName().asString()}" + is PropertyGetterDescriptor -> "get_${descriptor.correspondingProperty.name.asString()}" + is PropertySetterDescriptor -> "set_${descriptor.correspondingProperty.name.asString()}" + is FunctionDescriptor -> functionImplName(descriptor, descriptor.fqNameSafe.shortName().asString(), shortName) + else -> descriptor.fqNameSafe.shortName().asString() + } + while (scopeNames.contains(computedName) || cKeywords.contains(computedName)) { + computedName += "_" + } + scopeNames += computedName + scopeNamesMap[descriptor to shortName] = computedName + return computedName + } +} + +private class ExportedElement(val kind: ElementKind, + val scope: ExportedElementScope, + val declaration: DeclarationDescriptor, + val owner: CAdapterGenerator) : ContextUtils { + init { + scope.elements.add(this) + } + + val name: String + get() = declaration.fqNameSafe.shortName().asString() + + lateinit var cname: String + + override fun toString(): String { + return "$kind: $name (aliased to ${if (::cname.isInitialized) cname.toString() else ""})" + } + + override val context = owner.context + + fun generateCAdapter() { + when { + isFunction -> { + val function = declaration as FunctionDescriptor + val irFunction = irSymbol.owner as IrFunction + cname = "_konan_function_${owner.nextFunctionIndex()}" + val llvmFunction = owner.codegen.llvmFunction(irFunction) + // If function is virtual, we need to resolve receiver properly. + val bridge = if (!DescriptorUtils.isTopLevelDeclaration(function) && !function.isExtension && + irFunction.isOverridable) { + // We need LLVMGetElementType() as otherwise type is function pointer. + generateFunction(owner.codegen, LLVMGetElementType(llvmFunction.type)!!, cname) { + val receiver = param(0) + val numParams = LLVMCountParams(llvmFunction) + val args = (0 .. numParams - 1).map { index -> param(index) } + val callee = lookupVirtualImpl(receiver, irFunction) + val result = call(callee, args, exceptionHandler = ExceptionHandler.Caller, verbatim = true) + ret(result) + } + } else { + LLVMAddAlias(context.llvmModule, llvmFunction.type, llvmFunction, cname)!! + } + LLVMSetLinkage(bridge, LLVMLinkage.LLVMExternalLinkage) + } + isClass -> { + val irClass = irSymbol.owner as IrClass + cname = "_konan_function_${owner.nextFunctionIndex()}" + // Produce type getter. + val getTypeFunction = LLVMAddFunction(context.llvmModule, "${cname}_type", owner.kGetTypeFuncType)!! + val builder = LLVMCreateBuilderInContext(llvmContext)!! + val bb = LLVMAppendBasicBlockInContext(llvmContext, getTypeFunction, "")!! + LLVMPositionBuilderAtEnd(builder, bb) + LLVMBuildRet(builder, irClass.typeInfoPtr.llvm) + LLVMDisposeBuilder(builder) + // Produce instance getter if needed. + if (isSingletonObject) { + generateFunction(owner.codegen, owner.kGetObjectFuncType, "${cname}_instance") { + val value = getObjectValue(irClass, ExceptionHandler.Caller, null) + ret(value) + } + } + } + isEnumEntry -> { + // Produce entry getter. + cname = "_konan_function_${owner.nextFunctionIndex()}" + generateFunction(owner.codegen, owner.kGetObjectFuncType, cname) { + val irEnumEntry = irSymbol.owner as IrEnumEntry + val value = getEnumEntry(irEnumEntry, ExceptionHandler.Caller) + ret(value) + } + } + } + } + + fun uniqueName(descriptor: DeclarationDescriptor, shortName: Boolean) = + scope.scopeUniqueName(descriptor, shortName) + + val isFunction = declaration is FunctionDescriptor + val isTopLevelFunction: Boolean + get() { + if (declaration !is FunctionDescriptor || + !declaration.annotations.hasAnnotation(RuntimeNames.cnameAnnotation)) + return false + val annotation = declaration.annotations.findAnnotation(RuntimeNames.cnameAnnotation)!! + val externName = annotation.properValue("externName") + return externName != null && externName.isNotEmpty() + } + val isClass = declaration is ClassDescriptor && declaration.kind != ClassKind.ENUM_ENTRY + val isEnumEntry = declaration is ClassDescriptor && declaration.kind == ClassKind.ENUM_ENTRY + val isSingletonObject = declaration is ClassDescriptor && DescriptorUtils.isObject(declaration) + + private val irSymbol = when { + isFunction -> owner.symbolTable.referenceFunction(declaration as FunctionDescriptor) + isClass -> owner.symbolTable.referenceClass(declaration as ClassDescriptor) + isEnumEntry -> owner.symbolTable.referenceEnumEntry(declaration as ClassDescriptor) + else -> error("unexpected $kind element: $declaration") + } + + fun KotlinType.includeToSignature() = !this.isUnit() + + fun makeCFunctionSignature(shortName: Boolean): List { + if (!isFunction) { + throw Error("only for functions") + } + val descriptor = declaration + val original = descriptor.original as FunctionDescriptor + val returned = when { + original is ConstructorDescriptor -> + SignatureElement(uniqueName(original, shortName), original.constructedClass.defaultType) + else -> + SignatureElement(uniqueName(original, shortName), original.returnType!!) + } + val uniqueNames = owner.paramsToUniqueNames(original.explicitParameters) + val params = ArrayList(original.explicitParameters + .filter { it.type.includeToSignature() } + .map { SignatureElement(uniqueNames[it]!!, it.type) }) + return listOf(returned) + params + } + + fun makeBridgeSignature(): List { + if (!isFunction) { + throw Error("only for functions") + } + val descriptor = declaration + val original = descriptor.original as FunctionDescriptor + val returnedType = when { + original is ConstructorDescriptor -> owner.context.builtIns.unitType + else -> original.returnType!! + } + val params = ArrayList(original.allParameters + .filter { it.type.includeToSignature() } + .map { + owner.translateTypeBridge(it.type) + }) + if (owner.isMappedToReference(returnedType) || owner.isMappedToString(returnedType)) { + params += "KObjHeader**" + } + return listOf(owner.translateTypeBridge(returnedType)) + params + } + + + fun makeFunctionPointerString(): String { + val signature = makeCFunctionSignature(true) + return "${owner.translateType(signature[0])} (*${signature[0].name})(${signature.drop(1).map { it -> "${owner.translateType(it)} ${it.name}" }.joinToString(", ")});" + } + + fun makeTopLevelFunctionString(): Pair { + val signature = makeCFunctionSignature(false) + val name = signature[0].name + return (name to + "extern ${owner.translateType(signature[0])} $name(${signature.drop(1).map { it -> "${owner.translateType(it)} ${it.name}" }.joinToString(", ")});") + } + + fun makeFunctionDeclaration(): String { + assert(isFunction) + val bridge = makeBridgeSignature() + + val builder = StringBuilder() + builder.append("extern \"C\" ${bridge[0]} $cname") + builder.append("(${bridge.drop(1).joinToString(", ")});\n") + + // Now the C function body. + builder.append(translateBody(makeCFunctionSignature(false))) + return builder.toString() + } + + fun makeClassDeclaration(): String { + assert(isClass) + val typeGetter = "extern \"C\" ${owner.prefix}_KType* ${cname}_type(void);" + val instanceGetter = if (isSingletonObject) { + val objectClassC = owner.translateType((declaration as ClassDescriptor).defaultType) + """ + | + |extern "C" KObjHeader* ${cname}_instance(KObjHeader**); + |static $objectClassC ${cname}_instance_impl(void) { + | KObjHolder result_holder; + | Kotlin_initRuntimeIfNeeded(); + | KObjHeader* result = ${cname}_instance(result_holder.slot()); + | return $objectClassC { .pinned = CreateStablePointer(result)}; + |} + """.trimMargin() + } else "" + return "$typeGetter$instanceGetter" + } + + fun makeEnumEntryDeclaration(): String { + assert(isEnumEntry) + val enumClass = declaration.containingDeclaration as ClassDescriptor + val enumClassC = owner.translateType(enumClass.defaultType) + + return """ + |extern "C" KObjHeader* $cname(KObjHeader**); + |static $enumClassC ${cname}_impl(void) { + | KObjHolder result_holder; + | Kotlin_initRuntimeIfNeeded(); + | KObjHeader* result = $cname(result_holder.slot()); + | return $enumClassC { .pinned = CreateStablePointer(result)}; + |} + """.trimMargin() + } + + private fun translateArgument(name: String, signatureElement: SignatureElement, + direction: Direction, builder: StringBuilder): String { + return when { + owner.isMappedToString(signatureElement.type) -> + if (direction == Direction.C_TO_KOTLIN) { + builder.append(" KObjHolder ${name}_holder;\n") + "CreateStringFromCString($name, ${name}_holder.slot())" + } else { + "CreateCStringFromString($name)" + } + owner.isMappedToReference(signatureElement.type) -> + if (direction == Direction.C_TO_KOTLIN) { + builder.append(" KObjHolder ${name}_holder2;\n") + "DerefStablePointer(${name}.pinned, ${name}_holder2.slot())" + } else { + "((${owner.translateType(signatureElement.type)}){ .pinned = CreateStablePointer(${name})})" + } + else -> { + assert(!signatureElement.type.binaryTypeIsReference()) { + println(signatureElement.toString()) + } + name + } + } + } + + val cnameImpl: String + get() = if (isTopLevelFunction) + functionImplName(declaration, "******" /* Default value must never be used. */, false) + else + "${cname}_impl" + + private fun translateBody(cfunction: List): String { + val visibility = if (isTopLevelFunction) "RUNTIME_USED extern \"C\"" else "static" + val builder = StringBuilder() + builder.append("$visibility ${owner.translateType(cfunction[0])} ${cnameImpl}(${cfunction.drop(1). + mapIndexed { index, it -> "${owner.translateType(it)} arg${index}" }.joinToString(", ")}) {\n") + val args = ArrayList(cfunction.drop(1).mapIndexed { index, pair -> + translateArgument("arg$index", pair, Direction.C_TO_KOTLIN, builder) + }) + val isVoidReturned = owner.isMappedToVoid(cfunction[0].type) + val isConstructor = declaration is ConstructorDescriptor + val isObjectReturned = !isConstructor && owner.isMappedToReference(cfunction[0].type) + val isStringReturned = owner.isMappedToString(cfunction[0].type) + // TODO: do we really need that in every function? + builder.append(" Kotlin_initRuntimeIfNeeded();\n") + builder.append(" try {\n") + if (isObjectReturned || isStringReturned) { + builder.append(" KObjHolder result_holder;\n") + args += "result_holder.slot()" + } + if (isConstructor) { + builder.append(" KObjHolder result_holder;\n") + val clazz = scope.elements[0] + assert(clazz.kind == ElementKind.TYPE) + builder.append(" KObjHeader* result = AllocInstance((const KTypeInfo*)${clazz.cname}_type(), result_holder.slot());\n") + args.add(0, "result") + } + if (!isVoidReturned && !isConstructor) { + builder.append(" auto result = ") + } + builder.append(" $cname(") + builder.append(args.joinToString(", ")) + builder.append(");\n") + + if (!isVoidReturned) { + val result = translateArgument( + "result", cfunction[0], Direction.KOTLIN_TO_C, builder) + builder.append(" return $result;\n") + } + builder.append(" } catch (ExceptionObjHolder& e) { TerminateWithUnhandledException(e.obj()); } \n") + + builder.append("}\n") + + return builder.toString() + } + + private fun addUsedType(type: KotlinType, set: MutableSet) { + if (type.constructor.declarationDescriptor is TypeParameterDescriptor) return + val clazz = TypeUtils.getClassDescriptor(type) + if (clazz == null) { + context.reportCompilationWarning("cannot get class for $type") + } else { + set += clazz + } + } + + fun addUsedTypes(set: MutableSet) { + val descriptor = declaration + when (descriptor) { + is FunctionDescriptor -> { + val original = descriptor.original + original.allParameters.forEach { addUsedType(it.type, set) } + original.returnType?.let { addUsedType(it, set) } + } + is PropertyAccessorDescriptor -> { + val original = descriptor.original + addUsedType(original.correspondingProperty.type, set) + } + is ClassDescriptor -> { + set += descriptor + } + } + } +} + +private fun getPackagesFqNames(module: ModuleDescriptor): Set { + val result = mutableSetOf() + + fun getSubPackages(fqName: FqName) { + result.add(fqName) + module.getSubPackagesOf(fqName) { true }.forEach { getSubPackages(it) } + } + + getSubPackages(FqName.ROOT) + return result +} + +private fun ModuleDescriptor.getPackageFragments(): List = + getPackagesFqNames(this).flatMap { + getPackage(it).fragments.filter { it.module == this } + } + +internal class CAdapterGenerator(val context: Context) : DeclarationDescriptorVisitor { + + private val scopes = mutableListOf() + internal val prefix = context.config.moduleId + private lateinit var outputStreamWriter: PrintWriter + private val paramNamesRecorded = mutableMapOf() + + private var codegenOrNull: CodeGenerator? = null + internal val codegen get() = codegenOrNull!! + + private var symbolTableOrNull: SymbolTable? = null + internal val symbolTable get() = symbolTableOrNull!! + + private val predefinedTypes = listOf( + context.builtIns.byteType, context.builtIns.shortType, + context.builtIns.intType, context.builtIns.longType, + context.builtIns.floatType, context.builtIns.doubleType, + context.builtIns.charType, context.builtIns.booleanType, + context.builtIns.unitType) + + internal fun paramsToUniqueNames(params: List): Map { + paramNamesRecorded.clear() + return params.associate { + val name = translateName(it.name.asString()) + val count = paramNamesRecorded.getOrDefault(name, 0) + paramNamesRecorded[name] = count + 1 + if (count == 0) { + it to name + } else { + it to "$name${count.toString()}" + } + } + } + + private fun visitChildren(descriptors: Collection) { + for (descriptor in descriptors) { + descriptor.accept(this, null) + } + } + + private fun visitChildren(descriptor: DeclarationDescriptor) { + descriptor.accept(this, null) + } + + override fun visitConstructorDescriptor(descriptor: ConstructorDescriptor, ignored: Void?): Boolean { + if (!isExportedFunction(descriptor)) return true + ExportedElement(ElementKind.FUNCTION, scopes.last(), descriptor, this) + return true + } + + override fun visitFunctionDescriptor(descriptor: FunctionDescriptor, ignored: Void?): Boolean { + if (!isExportedFunction(descriptor)) return true + ExportedElement(ElementKind.FUNCTION, scopes.last(), descriptor, this) + return true + } + + override fun visitClassDescriptor(descriptor: ClassDescriptor, ignored: Void?): Boolean { + if (!isExportedClass(descriptor)) return true + // TODO: fix me! + val shortName = descriptor.fqNameSafe.shortName() + if (shortName.isSpecial || shortName.asString().contains("")) + return true + val classScope = ExportedElementScope(ScopeKind.CLASS, shortName.asString()) + scopes.last().scopes += classScope + scopes.push(classScope) + // Add type getter. + ExportedElement(ElementKind.TYPE, scopes.last(), descriptor, this) + visitChildren(descriptor.getConstructors()) + visitChildren(DescriptorUtils.getAllDescriptors(descriptor.getDefaultType().memberScope)) + scopes.pop() + return true + } + + override fun visitPropertyDescriptor(descriptor: PropertyDescriptor, ignored: Void?): Boolean { + if (descriptor.isExpect) return true + descriptor.getter?.let { visitChildren(it) } + descriptor.setter?.let { visitChildren(it) } + return true + } + + override fun visitPropertyGetterDescriptor(descriptor: PropertyGetterDescriptor, ignored: Void?): Boolean { + if (!isExportedFunction(descriptor)) return true + ExportedElement(ElementKind.FUNCTION, scopes.last(), descriptor, this) + return true + } + + override fun visitPropertySetterDescriptor(descriptor: PropertySetterDescriptor, ignored: Void?): Boolean { + if (!isExportedFunction(descriptor)) return true + ExportedElement(ElementKind.FUNCTION, scopes.last(), descriptor, this) + return true + } + + override fun visitScriptDescriptor(descriptor: ScriptDescriptor, ignored: Void?): Boolean { + context.reportCompilationWarning("visitScriptDescriptor() is ignored") + return true + } + + override fun visitPackageViewDescriptor(descriptor: PackageViewDescriptor, ignored: Void?): Boolean { + if (descriptor.module !in moduleDescriptors) return true + val fragments = descriptor.module.getPackage(FqName.ROOT).fragments.filter { + it.module in moduleDescriptors } + visitChildren(fragments) + return true + } + + override fun visitValueParameterDescriptor(descriptor: ValueParameterDescriptor, ignored: Void?): Boolean { + TODO("visitValueParameterDescriptor() shall not be seen") + } + + override fun visitReceiverParameterDescriptor(descriptor: ReceiverParameterDescriptor?, ignored: Void?): Boolean { + TODO("visitReceiverParameterDescriptor() shall not be seen") + } + + override fun visitVariableDescriptor(descriptor: VariableDescriptor, ignored: Void?): Boolean { + context.reportCompilationWarning("visitVariableDescriptor() is ignored for now") + return true + } + + override fun visitTypeParameterDescriptor(descriptor: TypeParameterDescriptor, ignored: Void?): Boolean { + context.reportCompilationWarning("visitTypeParameterDescriptor() is ignored for now") + return true + } + + private val seenPackageFragments = mutableSetOf() + private var currentPackageFragments: List = emptyList() + private val packageScopes = mutableMapOf() + + override fun visitModuleDeclaration(descriptor: ModuleDescriptor, ignored: Void?): Boolean { + TODO("Shall not be called directly") + } + + override fun visitTypeAliasDescriptor(descriptor: TypeAliasDescriptor, ignored: Void?): Boolean { + context.reportCompilationWarning("visitTypeAliasDescriptor() is ignored for now") + return true + } + + override fun visitPackageFragmentDescriptor(descriptor: PackageFragmentDescriptor, ignored: Void?): Boolean { + val fqName = descriptor.fqName + val packageScope = packageScopes.getOrPut(fqName) { + val name = if (fqName.isRoot) "root" else translateName(fqName.shortName().asString()) + val scope = ExportedElementScope(ScopeKind.PACKAGE, name) + scopes.last().scopes += scope + scope + } + scopes.push(packageScope) + visitChildren(DescriptorUtils.getAllDescriptors(descriptor.getMemberScope())) + for (currentPackageFragment in currentPackageFragments) { + if (!seenPackageFragments.contains(currentPackageFragment) && + currentPackageFragment.fqName.isChildOf(descriptor.fqName)) { + seenPackageFragments += currentPackageFragment + visitChildren(currentPackageFragment) + } + } + scopes.pop() + return true + } + + + private val moduleDescriptors = mutableSetOf() + + fun buildExports(symbolTable: SymbolTable) { + this.symbolTableOrNull = symbolTable + try { + buildExports() + } finally { + this.symbolTableOrNull = null + } + } + + fun generateBindings(codegen: CodeGenerator) { + this.codegenOrNull = codegen + try { + generateBindings() + } finally { + this.codegenOrNull = null + } + } + + private fun buildExports() { + scopes.push(ExportedElementScope(ScopeKind.TOP, "kotlin")) + moduleDescriptors += context.moduleDescriptor + moduleDescriptors += context.getExportedDependencies() + + currentPackageFragments = moduleDescriptors.flatMap { it.getPackageFragments() }.toSet().sortedWith( + Comparator { o1, o2 -> + o1.fqName.toString().compareTo(o2.fqName.toString()) + }) + + context.moduleDescriptor.getPackage(FqName.ROOT).accept(this, null) + } + + private fun generateBindings() { + val top = scopes.pop() + assert(scopes.isEmpty() && top.kind == ScopeKind.TOP) + + // Now, let's generate C world adapters for all functions. + top.generateCAdapters() + + // Then generate data structure, describing generated adapters. + makeGlobalStruct(top) + } + + private fun output(string: String, indent: Int = 0) { + if (indent != 0) outputStreamWriter.print(" " * indent) + outputStreamWriter.println(string) + } + + private fun makeElementDefinition(element: ExportedElement, kind: DefinitionKind, indent: Int) { + when (kind) { + DefinitionKind.C_HEADER_DECLARATION -> { + when { + element.isTopLevelFunction -> { + val (name, declaration) = element.makeTopLevelFunctionString() + exportedSymbols += name + output(declaration, 0) + } + } + } + + DefinitionKind.C_HEADER_STRUCT -> { + when { + element.isFunction -> + output(element.makeFunctionPointerString(), indent) + element.isClass -> { + output("${prefix}_KType* (*_type)(void);", indent) + if (element.isSingletonObject) { + output("${translateType((element.declaration as ClassDescriptor).defaultType)} (*_instance)();", indent) + } + } + element.isEnumEntry -> { + val enumClass = element.declaration.containingDeclaration as ClassDescriptor + output("${translateType(enumClass.defaultType)} (*get)(); /* enum entry for ${element.name}. */", indent) + } + // TODO: handle properties. + } + } + + DefinitionKind.C_SOURCE_DECLARATION -> { + when { + element.isFunction -> + output(element.makeFunctionDeclaration(), 0) + element.isClass -> + output(element.makeClassDeclaration(), 0) + element.isEnumEntry -> + output(element.makeEnumEntryDeclaration(), 0) + // TODO: handle properties. + } + } + + DefinitionKind.C_SOURCE_STRUCT -> { + when { + element.isFunction -> + output("/* ${element.name} = */ ${element.cnameImpl}, ", indent) + element.isClass -> { + output("/* Type for ${element.name} = */ ${element.cname}_type, ", indent) + if (element.isSingletonObject) + output("/* Instance for ${element.name} = */ ${element.cname}_instance_impl, ", indent) + } + element.isEnumEntry -> + output("/* enum entry getter ${element.name} = */ ${element.cname}_impl,", indent) + // TODO: handle properties. + } + } + } + } + + private fun makeScopeDefinitions(scope: ExportedElementScope, kind: DefinitionKind, indent: Int) { + if (kind == DefinitionKind.C_HEADER_STRUCT) output("struct {", indent) + if (kind == DefinitionKind.C_SOURCE_STRUCT) output(".${scope.name} = {", indent) + scope.elements.forEach { makeElementDefinition(it, kind, indent + 1) } + scope.scopes.forEach { makeScopeDefinitions(it, kind, indent + 1) } + if (kind == DefinitionKind.C_HEADER_STRUCT) output("} ${scope.name};", indent) + if (kind == DefinitionKind.C_SOURCE_STRUCT) output("},", indent) + } + + private fun defineUsedTypesImpl(scope: ExportedElementScope, set: MutableSet) { + scope.elements.forEach { + it.addUsedTypes(set) + } + scope.scopes.forEach { + defineUsedTypesImpl(it, set) + } + } + + private fun defineUsedTypes(scope: ExportedElementScope, indent: Int) { + val set = mutableSetOf() + defineUsedTypesImpl(scope, set) + // Add nullable primitives. + predefinedTypes.forEach { + val nullableIt = it.makeNullable() + output("typedef struct {", indent) + output("${prefix}_KNativePtr pinned;", indent + 1) + output("} ${translateType(nullableIt)};", indent) + } + set.forEach { + val type = it.defaultType + if (isMappedToReference(type) && !it.isInlined()) { + output("typedef struct {", indent) + output("${prefix}_KNativePtr pinned;", indent + 1) + output("} ${translateType(type)};", indent) + } + } + } + + val exportedSymbols = mutableListOf() + + private fun makeGlobalStruct(top: ExportedElementScope) { + val headerFile = context.config.outputFiles.cAdapterHeader + outputStreamWriter = headerFile.printWriter() + + val exportedSymbol = "${prefix}_symbols" + exportedSymbols += exportedSymbol + + output("#ifndef KONAN_${prefix.toUpperCase()}_H") + output("#define KONAN_${prefix.toUpperCase()}_H") + // TODO: use namespace for C++ case? + output(""" + #ifdef __cplusplus + extern "C" { + #endif""".trimIndent()) + output(""" + #ifdef __cplusplus + typedef bool ${prefix}_KBoolean; + #else + typedef _Bool ${prefix}_KBoolean; + #endif + """.trimIndent()) + output("typedef unsigned short ${prefix}_KChar;") + output("typedef signed char ${prefix}_KByte;") + output("typedef short ${prefix}_KShort;") + output("typedef int ${prefix}_KInt;") + output("typedef long long ${prefix}_KLong;") + output("typedef unsigned char ${prefix}_KUByte;") + output("typedef unsigned short ${prefix}_KUShort;") + output("typedef unsigned int ${prefix}_KUInt;") + output("typedef unsigned long long ${prefix}_KULong;") + output("typedef float ${prefix}_KFloat;") + output("typedef double ${prefix}_KDouble;") + + val typedef_KVector128 = "typedef float __attribute__ ((__vector_size__ (16))) ${prefix}_KVector128;" + if (context.config.target.family == Family.MINGW) { + // Separate `output` for each line to ensure Windows EOL (LFCR), otherwise generated file will have inconsistent line ending. + output("#ifndef _MSC_VER") + output(typedef_KVector128) + output("#else") + output("#include ") + output("typedef __m128 ${prefix}_KVector128;") + output("#endif") + } else { + output(typedef_KVector128) + } + + output("typedef void* ${prefix}_KNativePtr;") + output("struct ${prefix}_KType;") + output("typedef struct ${prefix}_KType ${prefix}_KType;") + + output("") + defineUsedTypes(top, 0) + + output("") + makeScopeDefinitions(top, DefinitionKind.C_HEADER_DECLARATION, 0) + + output("") + output("typedef struct {") + output("/* Service functions. */", 1) + output("void (*DisposeStablePointer)(${prefix}_KNativePtr ptr);", 1) + output("void (*DisposeString)(const char* string);", 1) + output("${prefix}_KBoolean (*IsInstance)(${prefix}_KNativePtr ref, const ${prefix}_KType* type);", 1) + predefinedTypes.forEach { + val nullableIt = it.makeNullable() + val argument = if (!it.isUnit()) translateType(it) else "void" + output("${translateType(nullableIt)} (*${it.createNullableNameForPredefinedType})($argument);", 1) + } + + output("") + output("/* User functions. */", 1) + makeScopeDefinitions(top, DefinitionKind.C_HEADER_STRUCT, 1) + output("} ${prefix}_ExportedSymbols;") + + output("extern ${prefix}_ExportedSymbols* $exportedSymbol(void);") + output(""" + #ifdef __cplusplus + } /* extern "C" */ + #endif""".trimIndent()) + + output("#endif /* KONAN_${prefix.toUpperCase()}_H */") + + outputStreamWriter.close() + println("Produced library API in ${prefix}_api.h") + + outputStreamWriter = context.config.tempFiles + .cAdapterCpp + .printWriter() + + // Include header into C++ source. + headerFile.forEachLine { it -> output(it) } + + output(""" + |struct KObjHeader; + |typedef struct KObjHeader KObjHeader; + |struct KTypeInfo; + |typedef struct KTypeInfo KTypeInfo; + | + |#define RUNTIME_NOTHROW __attribute__((nothrow)) + |#define RUNTIME_USED __attribute__((used)) + |#define RUNTIME_NORETURN __attribute__((noreturn)) + | + |extern "C" { + |void UpdateHeapRef(KObjHeader**, const KObjHeader*) RUNTIME_NOTHROW; + |void UpdateStackRef(KObjHeader**, const KObjHeader*) RUNTIME_NOTHROW; + |KObjHeader* AllocInstance(const KTypeInfo*, KObjHeader**) RUNTIME_NOTHROW; + |KObjHeader* DerefStablePointer(void*, KObjHeader**) RUNTIME_NOTHROW; + |void* CreateStablePointer(KObjHeader*) RUNTIME_NOTHROW; + |void DisposeStablePointer(void*) RUNTIME_NOTHROW; + |${prefix}_KBoolean IsInstance(const KObjHeader*, const KTypeInfo*) RUNTIME_NOTHROW; + |void EnterFrame(KObjHeader** start, int parameters, int count) RUNTIME_NOTHROW; + |void LeaveFrame(KObjHeader** start, int parameters, int count) RUNTIME_NOTHROW; + |void Kotlin_initRuntimeIfNeeded(); + |void TerminateWithUnhandledException(KObjHeader*) RUNTIME_NORETURN; + | + |KObjHeader* CreateStringFromCString(const char*, KObjHeader**); + |char* CreateCStringFromString(const KObjHeader*); + |void DisposeCString(char* cstring); + |} // extern "C" + | + |struct ${prefix}_FrameOverlay { + | void* arena; + | ${prefix}_FrameOverlay* previous; + | ${prefix}_KInt parameters; + | ${prefix}_KInt count; + |}; + | + |class KObjHolder { + |public: + | KObjHolder() : obj_(nullptr) { + | EnterFrame(frame(), 0, sizeof(*this)/sizeof(void*)); + | } + | explicit KObjHolder(const KObjHeader* obj) : obj_(nullptr) { + | EnterFrame(frame(), 0, sizeof(*this)/sizeof(void*)); + | UpdateStackRef(&obj_, obj); + | } + | ~KObjHolder() { + | LeaveFrame(frame(), 0, sizeof(*this)/sizeof(void*)); + | } + | KObjHeader* obj() { return obj_; } + | KObjHeader** slot() { return &obj_; } + | private: + | ${prefix}_FrameOverlay frame_; + | KObjHeader* obj_; + | + | KObjHeader** frame() { return reinterpret_cast(&frame_); } + |}; + | + |class ExceptionObjHolder { + | public: + | explicit ExceptionObjHolder(const KObjHeader* obj): obj_(nullptr) { + | ::UpdateHeapRef(&obj_, obj); + | } + | ~ExceptionObjHolder() { + | UpdateHeapRef(&obj_, nullptr); + | } + | KObjHeader* obj() { return obj_; } + | private: + | KObjHeader* obj_; + |}; + | + |static void DisposeStablePointerImpl(${prefix}_KNativePtr ptr) { + | DisposeStablePointer(ptr); + |} + |static void DisposeStringImpl(const char* ptr) { + | DisposeCString((char*)ptr); + |} + |static ${prefix}_KBoolean IsInstanceImpl(${prefix}_KNativePtr ref, const ${prefix}_KType* type) { + | KObjHolder holder; + | return IsInstance(DerefStablePointer(ref, holder.slot()), (const KTypeInfo*)type); + |} + """.trimMargin()) + predefinedTypes.forEach { + assert(!it.isNothing()) + val nullableIt = it.makeNullable() + val needArgument = !it.isUnit() + val (parameter, maybeComma) = if (needArgument) + ("${translateType(it)} value" to ",") else ("" to "") + val argument = if (needArgument) "value, " else "" + output("extern \"C\" KObjHeader* Kotlin_box${it.shortNameForPredefinedType}($parameter$maybeComma KObjHeader**);") + output("static ${translateType(nullableIt)} ${it.createNullableNameForPredefinedType}Impl($parameter) {") + output("KObjHolder result_holder;", 1) + output("Kotlin_initRuntimeIfNeeded();", 1) + output("KObjHeader* result = Kotlin_box${it.shortNameForPredefinedType}($argument result_holder.slot());", 1) + output("return ${translateType(nullableIt)} { .pinned = CreateStablePointer(result) };", 1) + output("}") + } + makeScopeDefinitions(top, DefinitionKind.C_SOURCE_DECLARATION, 0) + output("static ${prefix}_ExportedSymbols __konan_symbols = {") + output(".DisposeStablePointer = DisposeStablePointerImpl,", 1) + output(".DisposeString = DisposeStringImpl,", 1) + output(".IsInstance = IsInstanceImpl,", 1) + predefinedTypes.forEach { + output(".${it.createNullableNameForPredefinedType} = ${it.createNullableNameForPredefinedType}Impl,", 1) + } + + makeScopeDefinitions(top, DefinitionKind.C_SOURCE_STRUCT, 1) + output("};") + output("RUNTIME_USED ${prefix}_ExportedSymbols* $exportedSymbol(void) { return &__konan_symbols;}") + outputStreamWriter.close() + + if (context.config.target.family == Family.MINGW) { + outputStreamWriter = context.config.outputFiles + .cAdapterDef + .printWriter() + output("EXPORTS") + exportedSymbols.forEach { output(it) } + outputStreamWriter.close() + } + } + + private val simpleNameMapping = mapOf( + "" to "thiz", + "" to "set" + ) + + private val primitiveTypeMapping = KonanPrimitiveType.values().associate { + it to when (it) { + KonanPrimitiveType.BOOLEAN -> "${prefix}_KBoolean" + KonanPrimitiveType.CHAR -> "${prefix}_KChar" + KonanPrimitiveType.BYTE -> "${prefix}_KByte" + KonanPrimitiveType.SHORT -> "${prefix}_KShort" + KonanPrimitiveType.INT -> "${prefix}_KInt" + KonanPrimitiveType.LONG -> "${prefix}_KLong" + KonanPrimitiveType.FLOAT -> "${prefix}_KFloat" + KonanPrimitiveType.DOUBLE -> "${prefix}_KDouble" + KonanPrimitiveType.NON_NULL_NATIVE_PTR -> "void*" + KonanPrimitiveType.VECTOR128 -> "${prefix}_KVector128" + } + } + + private val unsignedTypeMapping = UnsignedType.values().associate { + it.classId to when (it) { + UnsignedType.UBYTE -> "${prefix}_KUByte" + UnsignedType.USHORT -> "${prefix}_KUShort" + UnsignedType.UINT -> "${prefix}_KUInt" + UnsignedType.ULONG -> "${prefix}_KULong" + } + } + + internal fun isMappedToString(type: KotlinType): Boolean = + isMappedToString(type.computeBinaryType()) + + private fun isMappedToString(binaryType: BinaryType): Boolean = + when (binaryType) { + is BinaryType.Primitive -> false + is BinaryType.Reference -> binaryType.types.first() == context.builtIns.string + } + + internal fun isMappedToReference(type: KotlinType) = + !isMappedToVoid(type) && !isMappedToString(type) && + type.binaryTypeIsReference() + + internal fun isMappedToVoid(type: KotlinType): Boolean { + return type.isUnit() || type.isNothing() + } + + fun translateName(name: String): String { + return when { + simpleNameMapping.contains(name) -> simpleNameMapping[name]!! + cKeywords.contains(name) -> "${name}_" + else -> name + } + } + + private fun translateTypeFull(type: KotlinType): Pair = + if (isMappedToVoid(type)) { + "void" to "void" + } else { + translateNonVoidTypeFull(type) + } + + private fun translateNonVoidTypeFull(type: KotlinType): Pair = type.unwrapToPrimitiveOrReference( + eachInlinedClass = { inlinedClass, _ -> + unsignedTypeMapping[inlinedClass.classId]?.let { + return it to it + } + }, + ifPrimitive = { primitiveType, _ -> + primitiveTypeMapping[primitiveType]!!.let { it to it } + }, + ifReference = { + val clazz = (it.computeBinaryType() as BinaryType.Reference).types.first() + if (clazz == context.builtIns.string) { + "const char*" to "KObjHeader*" + } else { + "${prefix}_kref_${translateTypeFqName(clazz.fqNameSafe.asString())}" to "KObjHeader*" + } + } + ) + + fun translateType(element: SignatureElement): String = + translateTypeFull(element.type).first + + fun translateType(type: KotlinType): String + = translateTypeFull(type).first + + fun translateTypeBridge(type: KotlinType): String = translateTypeFull(type).second + + fun translateTypeFqName(name: String): String { + return name.replace('.', '_') + } + + private var functionIndex = 0 + fun nextFunctionIndex() = functionIndex++ + + internal val kGetTypeFuncType get() = + LLVMFunctionType(codegen.kTypeInfoPtr, null, 0, 0)!! + // Abstraction leak for slot :(. + internal val kGetObjectFuncType get() = + LLVMFunctionType(codegen.kObjHeaderPtr, cValuesOf(codegen.kObjHeaderPtrPtr), 1, 0)!! +} diff --git a/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/CStubsManager.kt b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/CStubsManager.kt new file mode 100644 index 00000000000..589fd0ff31f --- /dev/null +++ b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/CStubsManager.kt @@ -0,0 +1,94 @@ +package org.jetbrains.kotlin.backend.konan + +import org.jetbrains.kotlin.cli.common.messages.CompilerMessageLocation +import org.jetbrains.kotlin.cli.common.messages.CompilerMessageSeverity +import org.jetbrains.kotlin.cli.common.messages.MessageCollector +import org.jetbrains.kotlin.konan.exec.Command +import org.jetbrains.kotlin.konan.file.* +import org.jetbrains.kotlin.konan.target.ClangArgs +import org.jetbrains.kotlin.konan.target.Family +import org.jetbrains.kotlin.konan.target.KonanTarget + +class CStubsManager(private val target: KonanTarget) { + + fun getUniqueName(prefix: String) = "$prefix${counter++}" + + fun addStub(kotlinLocation: CompilerMessageLocation?, lines: List) { + stubs += Stub(kotlinLocation, lines) + } + + fun compile(clang: ClangArgs, messageCollector: MessageCollector, verbose: Boolean): File? { + if (stubs.isEmpty()) return null + + val compilerOptions = mutableListOf() + val sourceFileExtension = when { + target.family.isAppleFamily -> { + compilerOptions += "-fobjc-arc" + ".m" // TODO: consider managing C and Objective-C stubs separately. + } + else -> ".c" + } + val cSource = createTempFile("cstubs", sourceFileExtension).deleteOnExit() + cSource.writeLines(stubs.flatMap { it.lines }) + + val bitcode = createTempFile("cstubs", ".bc").deleteOnExit() + + val cSourcePath = cSource.absolutePath + + val clangCommand = clang.clangC(*compilerOptions.toTypedArray(), "-O2", + cSourcePath, "-emit-llvm", "-c", "-o", bitcode.absolutePath) + + val result = Command(clangCommand).getResult(withErrors = true) + if (result.exitCode != 0) { + reportCompilationErrors(cSourcePath, result, messageCollector, verbose) + } + + return bitcode + } + + private fun reportCompilationErrors( + cSourcePath: String, + result: Command.Result, + messageCollector: MessageCollector, + verbose: Boolean + ): Nothing { + val regex = Regex("${Regex.escape(cSourcePath)}:([0-9]+):[0-9]+: error: .*") + val errorLines = result.outputLines.mapNotNull { line -> + regex.matchEntire(line)?.let { matchResult -> + matchResult.groupValues[1].toInt() + } + } + + val lineToStub = ArrayList() + stubs.forEach { stub -> + repeat(stub.lines.size) { lineToStub.add(stub) } + } + + val cSourceCopyPath = "cstubs.c" + if (verbose) { + File(cSourcePath).copyTo(File(cSourceCopyPath)) + } + + if (errorLines.isNotEmpty()) { + errorLines.forEach { + messageCollector.report( + CompilerMessageSeverity.ERROR, + "Unable to compile C bridge" + if (verbose) " at $cSourceCopyPath:$it" else "", + lineToStub[it - 1].kotlinLocation + ) + } + } else { + messageCollector.report( + CompilerMessageSeverity.ERROR, + "Unable to compile C bridges", + null + ) + } + + throw KonanCompilationException() + } + + private val stubs = mutableListOf() + private class Stub(val kotlinLocation: CompilerMessageLocation?, val lines: List) + private var counter = 0 +} \ No newline at end of file diff --git a/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/CacheSupport.kt b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/CacheSupport.kt new file mode 100644 index 00000000000..d91bbe46f64 --- /dev/null +++ b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/CacheSupport.kt @@ -0,0 +1,131 @@ +/* + * Copyright 2010-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +package org.jetbrains.kotlin.backend.konan + +import org.jetbrains.kotlin.cli.common.messages.CompilerMessageSeverity +import org.jetbrains.kotlin.config.CompilerConfiguration +import org.jetbrains.kotlin.konan.file.File +import org.jetbrains.kotlin.konan.target.CompilerOutputKind +import org.jetbrains.kotlin.konan.target.KonanTarget +import org.jetbrains.kotlin.library.KotlinLibrary +import org.jetbrains.kotlin.library.resolver.KotlinLibraryResolveResult + +class CacheSupport( + val configuration: CompilerConfiguration, + resolvedLibraries: KotlinLibraryResolveResult, + target: KonanTarget, + produce: CompilerOutputKind +) { + private val allLibraries = resolvedLibraries.getFullList() + + // TODO: consider using [FeaturedLibraries.kt]. + private val fileToLibrary = allLibraries.associateBy { it.libraryFile } + + private val implicitCacheDirectories = configuration.get(KonanConfigKeys.CACHE_DIRECTORIES)!! + .map { + File(it).takeIf { it.isDirectory } + ?: configuration.reportCompilationError("cache directory $it is not found or not a directory") + } + + internal fun tryGetImplicitOutput(): String? { + val libraryToAddToCache = configuration.get(KonanConfigKeys.LIBRARY_TO_ADD_TO_CACHE) ?: return null + // Put the resulting library in the first cache directory. + val cacheDirectory = implicitCacheDirectories.firstOrNull() ?: return null + val libraryToAddToCacheFile = File(libraryToAddToCache) + val library = allLibraries.single { it.libraryFile == libraryToAddToCacheFile } + return cacheDirectory.child(CachedLibraries.getCachedLibraryName(library)).absolutePath + } + + + internal val cachedLibraries: CachedLibraries = run { + val explicitCacheFiles = configuration.get(KonanConfigKeys.CACHED_LIBRARIES)!! + + val explicitCaches = explicitCacheFiles.entries.associate { (libraryPath, cachePath) -> + val library = fileToLibrary[File(libraryPath)] + ?: configuration.reportCompilationError("cache not applied: library $libraryPath in $cachePath") + + library to cachePath + } + + val optimized = configuration.getBoolean(KonanConfigKeys.OPTIMIZATION) + if (optimized && (explicitCacheFiles.isNotEmpty() || implicitCacheDirectories.isNotEmpty())) + configuration.report(CompilerMessageSeverity.WARNING, "Cached libraries will not be used for optimized compilation") + + CachedLibraries( + target = target, + allLibraries = allLibraries, + explicitCaches = if (optimized) emptyMap() else explicitCaches, + implicitCacheDirectories = if (optimized) emptyList() else implicitCacheDirectories + ) + } + + private fun getLibrary(file: File) = + fileToLibrary[file] ?: error("library to cache\n" + + " ${file.absolutePath}\n" + + "not found among resolved libraries:\n " + + allLibraries.joinToString("\n ") { it.libraryFile.absolutePath }) + + internal val librariesToCache: Set = run { + val libraryToAddToCachePath = configuration.get(KonanConfigKeys.LIBRARY_TO_ADD_TO_CACHE) + if (libraryToAddToCachePath.isNullOrEmpty()) { + configuration.get(KonanConfigKeys.LIBRARIES_TO_CACHE)!! + .map { getLibrary(File(it)) } + .toSet() + .also { if (!produce.isCache) check(it.isEmpty()) } + } else { + val libraryToAddToCacheFile = File(libraryToAddToCachePath) + val libraryToAddToCache = getLibrary(libraryToAddToCacheFile) + val libraryCache = cachedLibraries.getLibraryCache(libraryToAddToCache) + if (libraryCache == null) + setOf(libraryToAddToCache) + else + emptySet() + } + } + + internal val preLinkCaches: Boolean = + configuration.get(KonanConfigKeys.PRE_LINK_CACHES, false) + + init { + // Ensure dependencies of every cached library are cached too: + resolvedLibraries.getFullList { libraries -> + libraries.map { library -> + val cache = cachedLibraries.getLibraryCache(library.library) + if (cache != null || library.library in librariesToCache) { + library.resolvedDependencies.forEach { + if (!cachedLibraries.isLibraryCached(it.library) && it.library !in librariesToCache) { + val description = if (cache != null) { + "cached (in ${cache.path})" + } else { + "going to be cached" + } + configuration.reportCompilationError( + "${library.library.libraryName} is $description, " + + "but its dependency isn't: ${it.library.libraryName}" + ) + } + } + } + + library + } + } + + // Ensure not making cache for libraries that are already cached: + librariesToCache.forEach { + val cache = cachedLibraries.getLibraryCache(it) + if (cache != null) { + configuration.reportCompilationError("Can't cache library '${it.libraryName}' " + + "that is already cached in '${cache.path}'") + } + } + + if ((librariesToCache.isNotEmpty() || cachedLibraries.hasDynamicCaches || cachedLibraries.hasStaticCaches) + && configuration.getBoolean(KonanConfigKeys.OPTIMIZATION)) { + configuration.reportCompilationError("Cache cannot be used in optimized compilation") + } + } +} \ No newline at end of file diff --git a/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/CachedLibraries.kt b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/CachedLibraries.kt new file mode 100644 index 00000000000..ebfe168967a --- /dev/null +++ b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/CachedLibraries.kt @@ -0,0 +1,91 @@ +/* + * Copyright 2010-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +package org.jetbrains.kotlin.backend.konan + +import org.jetbrains.kotlin.konan.file.File +import org.jetbrains.kotlin.konan.target.CompilerOutputKind +import org.jetbrains.kotlin.konan.target.KonanTarget +import org.jetbrains.kotlin.library.KotlinLibrary +import org.jetbrains.kotlin.library.uniqueName +import org.jetbrains.kotlin.utils.addToStdlib.firstNotNullResult + +class CachedLibraries( + private val target: KonanTarget, + allLibraries: List, + explicitCaches: Map, + implicitCacheDirectories: List +) { + + class Cache(val kind: Kind, val path: String) { + enum class Kind { DYNAMIC, STATIC } + + val bitcodeDependencies by lazy { + val directory = File(path).absoluteFile.parent + File(directory, BITCODE_DEPENDENCIES_FILE_NAME).readStrings() + } + } + + private fun selectCache(library: KotlinLibrary, cacheDir: File): Cache? { + // See Linker.renameOutput why is it ok to have an empty cache directory. + if (cacheDir.listFilesOrEmpty.isEmpty()) return null + val baseName = getCachedLibraryName(library) + val dynamicFile = cacheDir.child(getArtifactName(baseName, CompilerOutputKind.DYNAMIC_CACHE)) + val staticFile = cacheDir.child(getArtifactName(baseName, CompilerOutputKind.STATIC_CACHE)) + + if (dynamicFile.exists && staticFile.exists) + error("Both dynamic and static caches files cannot be in the same directory." + + " Library: ${library.libraryName}, path to cache: ${cacheDir.absolutePath}") + return when { + dynamicFile.exists -> Cache(Cache.Kind.DYNAMIC, dynamicFile.absolutePath) + staticFile.exists -> Cache(Cache.Kind.STATIC, staticFile.absolutePath) + else -> error("No cache found for library ${library.libraryName} at ${cacheDir.absolutePath}") + } + } + + private val allCaches: Map = allLibraries.mapNotNull { library -> + val explicitPath = explicitCaches[library] + + val cache = if (explicitPath != null) { + selectCache(library, File(explicitPath)) + ?: error("No cache found for library ${library.libraryName} at $explicitPath") + } else { + implicitCacheDirectories.firstNotNullResult { dir -> + selectCache(library, dir.child(getCachedLibraryName(library))) + } + } + + cache?.let { library to it } + }.toMap() + + private fun getArtifactName(baseName: String, kind: CompilerOutputKind) = + "${kind.prefix(target)}$baseName${kind.suffix(target)}" + + fun isLibraryCached(library: KotlinLibrary): Boolean = + getLibraryCache(library) != null + + fun getLibraryCache(library: KotlinLibrary): Cache? = + allCaches[library] + + val hasStaticCaches = allCaches.values.any { + when (it.kind) { + Cache.Kind.STATIC -> true + Cache.Kind.DYNAMIC -> false + } + } + + val hasDynamicCaches = allCaches.values.any { + when (it.kind) { + Cache.Kind.STATIC -> false + Cache.Kind.DYNAMIC -> true + } + } + + companion object { + fun getCachedLibraryName(library: KotlinLibrary): String = getCachedLibraryName(library.uniqueName) + fun getCachedLibraryName(libraryName: String): String = "$libraryName-cache" + const val BITCODE_DEPENDENCIES_FILE_NAME = "bitcode_deps" + } +} \ No newline at end of file diff --git a/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/CodeGenerationInfo.kt b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/CodeGenerationInfo.kt new file mode 100644 index 00000000000..309bdb56628 --- /dev/null +++ b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/CodeGenerationInfo.kt @@ -0,0 +1,34 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +package org.jetbrains.kotlin.backend.konan + +import org.jetbrains.kotlin.descriptors.ClassKind +import org.jetbrains.kotlin.ir.declarations.IrClass +import org.jetbrains.kotlin.ir.util.hasAnnotation +import org.jetbrains.kotlin.name.FqName + +internal fun IrClass.isNonGeneratedAnnotation(): Boolean = + this.kind == ClassKind.ANNOTATION_CLASS && + !this.annotations.hasAnnotation(serialInfoAnnotationFqName) + +private val serialInfoAnnotationFqName = FqName("kotlinx.serialization.SerialInfo") + +/** + * We don't need to generate RTTI in some cases, e.g. Objective-C external classes. + */ +internal fun IrClass.requiresRtti(): Boolean = when { + // TODO: Support more cases + // Sadly, we still need to emit RTTI for Kotlin inheritors of Obj-C classes. + // The reason for it is that we need to know a layout of the object to correctly + // deinitialize it. + this.isExternalObjCClass() -> false + else -> true +} + +internal fun IrClass.requiresCodeGeneration(): Boolean = + // For now these two sets (classes that require RTTI and classes that require codegen) + // are the same, but they might diverge later. + requiresRtti() \ No newline at end of file diff --git a/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/CompilerOutput.kt b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/CompilerOutput.kt new file mode 100644 index 00000000000..7b286069937 --- /dev/null +++ b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/CompilerOutput.kt @@ -0,0 +1,204 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ +package org.jetbrains.kotlin.backend.konan + +import llvm.* +import org.jetbrains.kotlin.backend.common.serialization.KlibIrVersion +import org.jetbrains.kotlin.backend.common.serialization.metadata.KlibMetadataVersion +import org.jetbrains.kotlin.backend.konan.llvm.* +import org.jetbrains.kotlin.backend.konan.llvm.Llvm +import org.jetbrains.kotlin.backend.konan.llvm.objc.linkObjC +import org.jetbrains.kotlin.konan.CURRENT +import org.jetbrains.kotlin.library.KotlinAbiVersion +import org.jetbrains.kotlin.konan.CompilerVersion +import org.jetbrains.kotlin.konan.file.isBitcode +import org.jetbrains.kotlin.library.* +import org.jetbrains.kotlin.konan.target.CompilerOutputKind +import org.jetbrains.kotlin.konan.target.Family +import org.jetbrains.kotlin.konan.library.impl.buildLibrary + +/** + * Supposed to be true for a single LLVM module within final binary. + */ +val CompilerOutputKind.isFinalBinary: Boolean get() = when (this) { + CompilerOutputKind.PROGRAM, CompilerOutputKind.DYNAMIC, + CompilerOutputKind.STATIC, CompilerOutputKind.FRAMEWORK -> true + CompilerOutputKind.DYNAMIC_CACHE, CompilerOutputKind.STATIC_CACHE, + CompilerOutputKind.LIBRARY, CompilerOutputKind.BITCODE -> false +} + +val CompilerOutputKind.involvesBitcodeGeneration: Boolean + get() = this != CompilerOutputKind.LIBRARY + +internal val Context.producedLlvmModuleContainsStdlib: Boolean + get() = this.llvmModuleSpecification.containsModule(this.stdlibModule) + +val CompilerOutputKind.involvesLinkStage: Boolean + get() = when (this) { + CompilerOutputKind.PROGRAM, CompilerOutputKind.DYNAMIC, + CompilerOutputKind.DYNAMIC_CACHE, CompilerOutputKind.STATIC_CACHE, + CompilerOutputKind.STATIC, CompilerOutputKind.FRAMEWORK -> true + CompilerOutputKind.LIBRARY, CompilerOutputKind.BITCODE -> false + } + +val CompilerOutputKind.isCache: Boolean + get() = (this == CompilerOutputKind.STATIC_CACHE || this == CompilerOutputKind.DYNAMIC_CACHE) + +internal fun produceCStubs(context: Context) { + val llvmModule = context.llvmModule!! + context.cStubsManager.compile(context.config.clang, context.messageCollector, context.inVerbosePhase)?.let { + parseAndLinkBitcodeFile(llvmModule, it.absolutePath) + } +} + +private fun linkAllDependencies(context: Context, generatedBitcodeFiles: List) { + val config = context.config + + val runtimeNativeLibraries = config.runtimeNativeLibraries + .takeIf { context.producedLlvmModuleContainsStdlib }.orEmpty() + + val launcherNativeLibraries = config.launcherNativeLibraries + .takeIf { config.produce == CompilerOutputKind.PROGRAM }.orEmpty() + + linkObjC(context) + + val nativeLibraries = config.nativeLibraries + runtimeNativeLibraries + launcherNativeLibraries + + val bitcodeLibraries = context.llvm.bitcodeToLink.map { it.bitcodePaths }.flatten().filter { it.isBitcode } + val additionalBitcodeFilesToLink = context.llvm.additionalProducedBitcodeFiles + val exceptionsSupportNativeLibrary = config.exceptionsSupportNativeLibrary + val bitcodeFiles = (nativeLibraries + generatedBitcodeFiles + additionalBitcodeFilesToLink + bitcodeLibraries).toMutableSet() + if (config.produce == CompilerOutputKind.DYNAMIC_CACHE) + bitcodeFiles += exceptionsSupportNativeLibrary + + val llvmModule = context.llvmModule!! + bitcodeFiles.forEach { + parseAndLinkBitcodeFile(llvmModule, it) + } +} + +private fun insertAliasToEntryPoint(context: Context) { + val nomain = context.config.configuration.get(KonanConfigKeys.NOMAIN) ?: false + if (context.config.produce != CompilerOutputKind.PROGRAM || nomain) + return + val module = context.llvmModule + val entryPoint = LLVMGetNamedFunction(module, "Konan_main") + ?: error("Module doesn't contain `Konan_main`") + LLVMAddAlias(module, LLVMTypeOf(entryPoint)!!, entryPoint, "main") +} + +internal fun linkBitcodeDependencies(context: Context) { + val config = context.config.configuration + val tempFiles = context.config.tempFiles + val produce = config.get(KonanConfigKeys.PRODUCE) + + val generatedBitcodeFiles = + if (produce == CompilerOutputKind.DYNAMIC || produce == CompilerOutputKind.STATIC) { + produceCAdapterBitcode( + context.config.clang, + tempFiles.cAdapterCppName, + tempFiles.cAdapterBitcodeName) + listOf(tempFiles.cAdapterBitcodeName) + } else emptyList() + if (produce == CompilerOutputKind.FRAMEWORK && context.config.produceStaticFramework) { + embedAppleLinkerOptionsToBitcode(context.llvm, context.config) + } + linkAllDependencies(context, generatedBitcodeFiles) +} + +internal fun produceOutput(context: Context) { + + val config = context.config.configuration + val tempFiles = context.config.tempFiles + val produce = config.get(KonanConfigKeys.PRODUCE) + + when (produce) { + CompilerOutputKind.STATIC, + CompilerOutputKind.DYNAMIC, + CompilerOutputKind.FRAMEWORK, + CompilerOutputKind.DYNAMIC_CACHE, + CompilerOutputKind.STATIC_CACHE, + CompilerOutputKind.PROGRAM -> { + val output = tempFiles.nativeBinaryFileName + context.bitcodeFileName = output + // Insert `_main` after pipeline so we won't worry about optimizations + // corrupting entry point. + insertAliasToEntryPoint(context) + LLVMWriteBitcodeToFile(context.llvmModule!!, output) + } + CompilerOutputKind.LIBRARY -> { + val output = context.config.outputFiles.outputName + val libraryName = context.config.moduleId + val shortLibraryName = context.config.shortModuleName + val neededLibraries = context.librariesWithDependencies + val abiVersion = KotlinAbiVersion.CURRENT + val compilerVersion = CompilerVersion.CURRENT.toString() + val libraryVersion = config.get(KonanConfigKeys.LIBRARY_VERSION) + val metadataVersion = KlibMetadataVersion.INSTANCE.toString() + val irVersion = KlibIrVersion.INSTANCE.toString() + val versions = KotlinLibraryVersioning( + abiVersion = abiVersion, + libraryVersion = libraryVersion, + compilerVersion = compilerVersion, + metadataVersion = metadataVersion, + irVersion = irVersion + ) + val target = context.config.target + val nopack = config.getBoolean(KonanConfigKeys.NOPACK) + val manifestProperties = context.config.manifestProperties + + val library = buildLibrary( + context.config.nativeLibraries, + context.config.includeBinaries, + neededLibraries, + context.serializedMetadata!!, + context.serializedIr, + versions, + target, + output, + libraryName, + nopack, + shortLibraryName, + manifestProperties, + context.dataFlowGraph) + + context.bitcodeFileName = library.mainBitcodeFileName + } + CompilerOutputKind.BITCODE -> { + val output = context.config.outputFile + context.bitcodeFileName = output + LLVMWriteBitcodeToFile(context.llvmModule!!, output) + } + } +} + +private fun parseAndLinkBitcodeFile(llvmModule: LLVMModuleRef, path: String) { + val parsedModule = parseBitcodeFile(path) + val failed = LLVMLinkModules2(llvmModule, parsedModule) + if (failed != 0) { + throw Error("failed to link $path") // TODO: retrieve error message from LLVM. + } +} + +private fun embedAppleLinkerOptionsToBitcode(llvm: Llvm, config: KonanConfig) { + fun findEmbeddableOptions(options: List): List> { + val result = mutableListOf>() + val iterator = options.iterator() + loop@while (iterator.hasNext()) { + val option = iterator.next() + result += when { + option.startsWith("-l") -> listOf(option) + option == "-framework" && iterator.hasNext() -> listOf(option, iterator.next()) + else -> break@loop // Ignore the rest. + } + } + return result + } + + val optionsToEmbed = findEmbeddableOptions(config.platform.configurables.linkerKonanFlags) + + llvm.allNativeDependencies.flatMap { findEmbeddableOptions(it.linkerOpts) } + + embedLlvmLinkOptions(llvm.llvmModule, optionsToEmbed) +} diff --git a/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/Context.kt b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/Context.kt new file mode 100644 index 00000000000..9d8cae222b5 --- /dev/null +++ b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/Context.kt @@ -0,0 +1,457 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +package org.jetbrains.kotlin.backend.konan + +import llvm.* +import org.jetbrains.kotlin.backend.konan.descriptors.* +import org.jetbrains.kotlin.backend.konan.ir.KonanIr +import org.jetbrains.kotlin.library.SerializedMetadata +import org.jetbrains.kotlin.backend.konan.llvm.* +import org.jetbrains.kotlin.backend.konan.lower.DECLARATION_ORIGIN_BRIDGE_METHOD +import org.jetbrains.kotlin.backend.konan.optimizations.Devirtualization +import org.jetbrains.kotlin.backend.konan.optimizations.ExternalModulesDFG +import org.jetbrains.kotlin.backend.konan.optimizations.ModuleDFG +import org.jetbrains.kotlin.descriptors.* +import org.jetbrains.kotlin.descriptors.annotations.Annotations +import org.jetbrains.kotlin.descriptors.impl.PropertyDescriptorImpl +import org.jetbrains.kotlin.descriptors.impl.ReceiverParameterDescriptorImpl +import org.jetbrains.kotlin.incremental.components.NoLookupLocation +import org.jetbrains.kotlin.ir.IrElement +import org.jetbrains.kotlin.ir.declarations.* +import org.jetbrains.kotlin.ir.declarations.impl.IrFieldImpl +import org.jetbrains.kotlin.ir.declarations.impl.IrFunctionImpl +import org.jetbrains.kotlin.ir.util.* +import org.jetbrains.kotlin.builtins.konan.KonanBuiltIns +import org.jetbrains.kotlin.cli.jvm.compiler.KotlinCoreEnvironment +import org.jetbrains.kotlin.ir.symbols.impl.IrSimpleFunctionSymbolImpl +import org.jetbrains.kotlin.konan.target.CompilerOutputKind +import org.jetbrains.kotlin.name.Name +import org.jetbrains.kotlin.resolve.BindingContext +import org.jetbrains.kotlin.resolve.descriptorUtil.module +import org.jetbrains.kotlin.resolve.scopes.MemberScope +import org.jetbrains.kotlin.resolve.scopes.receivers.ImplicitClassReceiver +import java.lang.System.out +import kotlin.LazyThreadSafetyMode.PUBLICATION +import kotlin.reflect.KProperty +import org.jetbrains.kotlin.backend.common.ir.copyTo +import org.jetbrains.kotlin.backend.common.ir.copyToWithoutSuperTypes +import org.jetbrains.kotlin.backend.konan.objcexport.ObjCExport +import org.jetbrains.kotlin.backend.konan.llvm.coverage.CoverageManager +import org.jetbrains.kotlin.ir.descriptors.WrappedSimpleFunctionDescriptor +import org.jetbrains.kotlin.ir.symbols.IrSymbol +import org.jetbrains.kotlin.ir.symbols.impl.IrFieldSymbolImpl +import org.jetbrains.kotlin.name.FqName +import org.jetbrains.kotlin.konan.library.KonanLibraryLayout +import org.jetbrains.kotlin.library.SerializedIrModule +import org.jetbrains.kotlin.resolve.descriptorUtil.isEffectivelyExternal + +/** + * Offset for synthetic elements created by lowerings and not attributable to other places in the source code. + */ + +internal class SpecialDeclarationsFactory(val context: Context) { + private val enumSpecialDeclarationsFactory by lazy { EnumSpecialDeclarationsFactory(context) } + private val outerThisFields = mutableMapOf() + private val internalLoweredEnums = mutableMapOf() + private val externalLoweredEnums = mutableMapOf() + + private data class BridgeKey(val target: IrSimpleFunction, val bridgeDirections: BridgeDirections) + + private val bridges = mutableMapOf() + + val loweredInlineFunctions = mutableSetOf() + + object DECLARATION_ORIGIN_FIELD_FOR_OUTER_THIS : + IrDeclarationOriginImpl("FIELD_FOR_OUTER_THIS") + + fun getOuterThisField(innerClass: IrClass): IrField = + if (!innerClass.isInner) throw AssertionError("Class is not inner: ${innerClass.descriptor}") + else outerThisFields.getOrPut(innerClass) { + val outerClass = innerClass.parent as? IrClass + ?: throw AssertionError("No containing class for inner class ${innerClass.descriptor}") + + val receiver = ReceiverParameterDescriptorImpl( + innerClass.descriptor, + ImplicitClassReceiver(innerClass.descriptor, null), + Annotations.EMPTY + ) + val descriptor = PropertyDescriptorImpl.create( + innerClass.descriptor, Annotations.EMPTY, Modality.FINAL, + DescriptorVisibilities.PRIVATE, false, "this$0".synthesizedName, CallableMemberDescriptor.Kind.SYNTHESIZED, + SourceElement.NO_SOURCE, false, false, false, false, false, false + ).apply { + this.setType(outerClass.descriptor.defaultType, emptyList(), receiver, null) + initialize(null, null) + } + + IrFieldImpl( + startOffset = innerClass.startOffset, + endOffset = innerClass.endOffset, + origin = DECLARATION_ORIGIN_FIELD_FOR_OUTER_THIS, + symbol = IrFieldSymbolImpl(descriptor), + name = descriptor.name, + type = outerClass.defaultType, + visibility = descriptor.visibility, + isFinal = !descriptor.isVar, + isExternal = descriptor.isEffectivelyExternal(), + isStatic = descriptor.dispatchReceiverParameter == null + ).apply { + parent = innerClass + } + } + + fun getLoweredEnum(enumClass: IrClass): LoweredEnumAccess { + assert(enumClass.kind == ClassKind.ENUM_CLASS) { "Expected enum class but was: ${enumClass.descriptor}" } + return if (!context.llvmModuleSpecification.containsDeclaration(enumClass)) { + externalLoweredEnums.getOrPut(enumClass) { + enumSpecialDeclarationsFactory.createExternalLoweredEnum(enumClass) + } + } else { + internalLoweredEnums.getOrPut(enumClass) { + enumSpecialDeclarationsFactory.createInternalLoweredEnum(enumClass) + } + } + } + + fun getInternalLoweredEnum(enumClass: IrClass): InternalLoweredEnum { + assert(enumClass.kind == ClassKind.ENUM_CLASS) { "Expected enum class but was: ${enumClass.descriptor}" } + assert(context.llvmModuleSpecification.containsDeclaration(enumClass)) { "Expected enum class from current module." } + return internalLoweredEnums.getOrPut(enumClass) { + enumSpecialDeclarationsFactory.createInternalLoweredEnum(enumClass) + } + } + + fun getEnumEntryOrdinal(enumEntry: IrEnumEntry) = + enumEntry.parentAsClass.declarations.filterIsInstance().indexOf(enumEntry) + + fun getBridge(overriddenFunction: OverriddenFunctionInfo): IrSimpleFunction { + val irFunction = overriddenFunction.function + assert(overriddenFunction.needBridge) { + "Function ${irFunction.descriptor} is not needed in a bridge to call overridden function ${overriddenFunction.overriddenFunction.descriptor}" + } + val key = BridgeKey(irFunction, overriddenFunction.bridgeDirections) + return bridges.getOrPut(key) { createBridge(key) } + } + + private fun createBridge(key: BridgeKey): IrSimpleFunction = WrappedSimpleFunctionDescriptor().let { descriptor -> + val (function, bridgeDirections) = key + val startOffset = function.startOffset + val endOffset = function.endOffset + + fun BridgeDirection.type() = + if (this.kind == BridgeDirectionKind.NONE) + null + else this.irClass?.defaultType ?: context.irBuiltIns.anyNType + + IrFunctionImpl( + startOffset, endOffset, + DECLARATION_ORIGIN_BRIDGE_METHOD(function), + IrSimpleFunctionSymbolImpl(descriptor), + "${function.functionName}".synthesizedName, + function.visibility, + function.modality, + isInline = false, + isExternal = false, + isTailrec = false, + isSuspend = function.isSuspend, + returnType = bridgeDirections.returnDirection.type() ?: function.returnType, + isExpect = false, + isFakeOverride = false, + isOperator = false, + isInfix = false + ).apply { + val bridge = this + descriptor.bind(bridge) + parent = function.parent + + dispatchReceiverParameter = function.dispatchReceiverParameter?.let { + it.copyTo(bridge, type = bridgeDirections.dispatchReceiverDirection.type() ?: it.type) + } + extensionReceiverParameter = function.extensionReceiverParameter?.let { + it.copyTo(bridge, type = bridgeDirections.extensionReceiverDirection.type() ?: it.type) + } + valueParameters += function.valueParameters.map { + it.copyTo(bridge, type = bridgeDirections.parameterDirectionAt(it.index).type() ?: it.type) + } + + typeParameters += function.typeParameters.map { parameter -> + parameter.copyToWithoutSuperTypes(bridge).also { it.superTypes += parameter.superTypes } + } + } + } +} + +internal class Context(config: KonanConfig) : KonanBackendContext(config) { + override val lateinitNullableFields = mutableMapOf() + lateinit var frontendServices: FrontendServices + lateinit var environment: KotlinCoreEnvironment + lateinit var bindingContext: BindingContext + + lateinit var moduleDescriptor: ModuleDescriptor + + lateinit var objCExport: ObjCExport + + lateinit var cAdapterGenerator: CAdapterGenerator + + lateinit var expectDescriptorToSymbol: MutableMap + + override val builtIns: KonanBuiltIns by lazy(PUBLICATION) { + moduleDescriptor.builtIns as KonanBuiltIns + } + + override val configuration get() = config.configuration + + override val internalPackageFqn: FqName = RuntimeNames.kotlinNativeInternalPackageName + + val phaseConfig = config.phaseConfig + + private val packageScope by lazy { builtIns.builtInsModule.getPackage(KonanFqNames.internalPackageName).memberScope } + + val nativePtr by lazy { packageScope.getContributedClassifier(NATIVE_PTR_NAME) as ClassDescriptor } + val nonNullNativePtr by lazy { packageScope.getContributedClassifier(NON_NULL_NATIVE_PTR_NAME) as ClassDescriptor } + val getNativeNullPtr by lazy { packageScope.getContributedFunctions("getNativeNullPtr").single() } + val immutableBlobOf by lazy { + builtIns.builtInsModule.getPackage(KonanFqNames.packageName).memberScope.getContributedFunctions("immutableBlobOf").single() + } + + val specialDeclarationsFactory = SpecialDeclarationsFactory(this) + + open class LazyMember(val initializer: Context.() -> T) { + operator fun getValue(thisRef: Context, property: KProperty<*>): T = thisRef.getValue(this) + } + + class LazyVarMember(initializer: Context.() -> T) : LazyMember(initializer) { + operator fun setValue(thisRef: Context, property: KProperty<*>, newValue: T) = thisRef.setValue(this, newValue) + } + + companion object { + fun lazyMember(initializer: Context.() -> T) = LazyMember(initializer) + + fun lazyMapMember(initializer: Context.(K) -> V): LazyMember<(K) -> V> = lazyMember { + val storage = mutableMapOf() + val result: (K) -> V = { + storage.getOrPut(it, { initializer(it) }) + } + result + } + + fun nullValue() = LazyVarMember({ null }) + } + + private val lazyValues = mutableMapOf, Any?>() + + fun getValue(member: LazyMember): T = + @Suppress("UNCHECKED_CAST") (lazyValues.getOrPut(member, { member.initializer(this) }) as T) + + fun setValue(member: LazyVarMember, newValue: T) { + lazyValues[member] = newValue + } + + val reflectionTypes: KonanReflectionTypes by lazy(PUBLICATION) { + KonanReflectionTypes(moduleDescriptor, KonanFqNames.internalPackageName) + } + + val layoutBuilders = mutableMapOf() + + fun getLayoutBuilder(irClass: IrClass) = layoutBuilders.getOrPut(irClass) { + ClassLayoutBuilder(irClass, this, isLowered = shouldLower(this, irClass)) + } + + lateinit var globalHierarchyAnalysisResult: GlobalHierarchyAnalysisResult + + // We serialize untouched descriptor tree and IR. + // But we have to wait until the code generation phase, + // to dump this information into generated file. + var serializedMetadata: SerializedMetadata? = null + var serializedIr: SerializedIrModule? = null + var dataFlowGraph: ByteArray? = null + + val librariesWithDependencies by lazy { + config.librariesWithDependencies(moduleDescriptor) + } + + var functionReferenceCount = 0 + var coroutineCount = 0 + + fun needGlobalInit(field: IrField): Boolean { + if (field.descriptor.containingDeclaration !is PackageFragmentDescriptor) return false + // TODO: add some smartness here. Maybe if package of the field is in never accessed + // assume its global init can be actually omitted. + return true + } + + lateinit var irModules: Map + + // TODO: make lateinit? + var irModule: IrModuleFragment? = null + set(module) { + if (field != null) { + throw Error("Another IrModule in the context.") + } + field = module!! + ir = KonanIr(this, module) + } + + override lateinit var ir: KonanIr + + override val irBuiltIns + get() = ir.irModule.irBuiltins + + val interopBuiltIns by lazy { + InteropBuiltIns(this.builtIns) + } + + var llvmModule: LLVMModuleRef? = null + set(module) { + if (field != null) { + throw Error("Another LLVMModule in the context.") + } + field = module!! + + llvm = Llvm(this, module) + debugInfo = DebugInfo(this) + } + + lateinit var llvm: Llvm + val llvmImports: LlvmImports = Llvm.ImportsImpl(this) + lateinit var llvmDeclarations: LlvmDeclarations + lateinit var bitcodeFileName: String + lateinit var library: KonanLibraryLayout + + private var llvmDisposed = false + + fun disposeLlvm() { + if (llvmDisposed) return + if (::debugInfo.isInitialized) + LLVMDisposeDIBuilder(debugInfo.builder) + if (llvmModule != null) + LLVMDisposeModule(llvmModule) + if (::llvm.isInitialized) + LLVMDisposeModule(llvm.runtime.llvmModule) + tryDisposeLLVMContext() + llvmDisposed = true + } + + val cStubsManager = CStubsManager(config.target) + + val coverage = CoverageManager(this) + + protected fun separator(title: String) { + println("\n\n--- ${title} ----------------------\n") + } + + fun verifyDescriptors() { + // TODO: Nothing here for now. + } + + fun printDescriptors() { + if (!::moduleDescriptor.isInitialized) + return + + separator("Descriptors:") + moduleDescriptor.deepPrint() + } + + fun printIr() { + if (irModule == null) return + separator("IR:") + irModule!!.accept(DumpIrTreeVisitor(out), "") + } + + fun verifyBitCode() { + if (llvmModule == null) return + verifyModule(llvmModule!!) + } + + fun printBitCode() { + if (llvmModule == null) return + separator("BitCode:") + LLVMDumpModule(llvmModule!!) + } + + fun verify() { + verifyDescriptors() + verifyBitCode() + } + + fun print() { + printDescriptors() + printIr() + printBitCode() + } + fun shouldVerifyBitCode() = config.configuration.getBoolean(KonanConfigKeys.VERIFY_BITCODE) + + fun shouldPrintBitCode() = config.configuration.getBoolean(KonanConfigKeys.PRINT_BITCODE) + + fun shouldPrintLocations() = config.configuration.getBoolean(KonanConfigKeys.PRINT_LOCATIONS) + + fun shouldProfilePhases() = config.phaseConfig.needProfiling + + fun shouldContainDebugInfo() = config.debug + fun shouldContainLocationDebugInfo() = shouldContainDebugInfo() || config.lightDebug + fun shouldContainAnyDebugInfo() = shouldContainDebugInfo() || shouldContainLocationDebugInfo() + + fun shouldOptimize() = config.configuration.getBoolean(KonanConfigKeys.OPTIMIZATION) + fun ghaEnabled() = ::globalHierarchyAnalysisResult.isInitialized + + val memoryModel = config.memoryModel + + override var inVerbosePhase = false + override fun log(message: () -> String) { + if (inVerbosePhase) { + println(message()) + } + } + + lateinit var debugInfo: DebugInfo + var moduleDFG: ModuleDFG? = null + var externalModulesDFG: ExternalModulesDFG? = null + lateinit var lifetimes: MutableMap + lateinit var codegenVisitor: CodeGeneratorVisitor + var devirtualizationAnalysisResult: Devirtualization.AnalysisResult? = null + + var referencedFunctions: Set? = null + + val isNativeLibrary: Boolean by lazy { + val kind = config.configuration.get(KonanConfigKeys.PRODUCE) + kind == CompilerOutputKind.DYNAMIC || kind == CompilerOutputKind.STATIC + } + + internal val stdlibModule + get() = this.builtIns.any.module + + lateinit var compilerOutput: List + + val llvmModuleSpecification: LlvmModuleSpecification by lazy { + when { + config.produce.isCache -> + CacheLlvmModuleSpecification(config.cachedLibraries, config.librariesToCache) + else -> DefaultLlvmModuleSpecification(config.cachedLibraries) + } + } + + val declaredLocalArrays: MutableMap = HashMap() + + /** + * Manages internal ABI references and declarations. + */ + val internalAbi = InternalAbi(this) +} + +private fun MemberScope.getContributedClassifier(name: String) = + this.getContributedClassifier(Name.identifier(name), NoLookupLocation.FROM_BUILTINS) + +private fun MemberScope.getContributedFunctions(name: String) = + this.getContributedFunctions(Name.identifier(name), NoLookupLocation.FROM_BUILTINS) + +internal class ContextLogger(val context: Context) { + operator fun String.unaryPlus() = context.log { this } +} + +internal fun Context.logMultiple(messageBuilder: ContextLogger.() -> Unit) { + if (!inVerbosePhase) return + with(ContextLogger(this)) { messageBuilder() } +} \ No newline at end of file diff --git a/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/EntryPoint.kt b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/EntryPoint.kt new file mode 100644 index 00000000000..282ee96fecf --- /dev/null +++ b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/EntryPoint.kt @@ -0,0 +1,96 @@ +/* + * Copyright 2010-2019 JetBrains s.r.o. and Kotlin Programming Language contributors. + * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. + */ + +package org.jetbrains.kotlin.backend.konan + +import org.jetbrains.kotlin.backend.common.lower.createIrBuilder +import org.jetbrains.kotlin.backend.common.lower.irBlockBody +import org.jetbrains.kotlin.backend.konan.ir.buildSimpleAnnotation +import org.jetbrains.kotlin.descriptors.Modality +import org.jetbrains.kotlin.descriptors.DescriptorVisibilities +import org.jetbrains.kotlin.ir.builders.* +import org.jetbrains.kotlin.ir.declarations.IrDeclarationOrigin +import org.jetbrains.kotlin.ir.declarations.IrFunction +import org.jetbrains.kotlin.ir.declarations.impl.IrFunctionImpl +import org.jetbrains.kotlin.ir.declarations.impl.IrValueParameterImpl +import org.jetbrains.kotlin.ir.descriptors.WrappedSimpleFunctionDescriptor +import org.jetbrains.kotlin.ir.descriptors.WrappedValueParameterDescriptor +import org.jetbrains.kotlin.ir.expressions.impl.IrTryImpl +import org.jetbrains.kotlin.ir.symbols.impl.IrSimpleFunctionSymbolImpl +import org.jetbrains.kotlin.ir.symbols.impl.IrValueParameterSymbolImpl +import org.jetbrains.kotlin.ir.types.typeWith +import org.jetbrains.kotlin.ir.util.irCatch +import org.jetbrains.kotlin.name.Name + +internal fun makeEntryPoint(context: Context): IrFunction { + val entryPointDescriptor = WrappedSimpleFunctionDescriptor() + val actualMain = context.ir.symbols.entryPoint!!.owner + val entryPoint = IrFunctionImpl( + actualMain.startOffset, + actualMain.startOffset, + IrDeclarationOrigin.DEFINED, + IrSimpleFunctionSymbolImpl(entryPointDescriptor), + Name.identifier("Konan_start"), + DescriptorVisibilities.PRIVATE, + Modality.FINAL, + context.irBuiltIns.intType, + isInline = false, + isExternal = false, + isTailrec = false, + isSuspend = false, + isExpect = false, + isFakeOverride = false, + isOperator = false, + isInfix = false + ).also { function -> + function.valueParameters = listOf(WrappedValueParameterDescriptor().let { + IrValueParameterImpl( + actualMain.startOffset, actualMain.startOffset, + IrDeclarationOrigin.DEFINED, + IrValueParameterSymbolImpl(it), + Name.identifier("args"), + index = 0, + varargElementType = null, + isCrossinline = false, + type = context.irBuiltIns.arrayClass.typeWith(context.irBuiltIns.stringType), + isNoinline = false + ).apply { + it.bind(this) + parent = function + } + }) + } + entryPointDescriptor.bind(entryPoint) + entryPoint.annotations += buildSimpleAnnotation(context.irBuiltIns, + actualMain.startOffset, actualMain.startOffset, + context.ir.symbols.exportForCppRuntime.owner, "Konan_start") + + val builder = context.createIrBuilder(entryPoint.symbol) + entryPoint.body = builder.irBlockBody(entryPoint) { + +IrTryImpl( + startOffset = actualMain.startOffset, + endOffset = actualMain.startOffset, + type = context.irBuiltIns.nothingType + ).apply { + tryResult = irBlock { + +irCall(actualMain).apply { + if (actualMain.valueParameters.size != 0) + putValueArgument(0, irGet(entryPoint.valueParameters[0])) + } + +irReturn(irInt(0)) + } + catches += irCatch(context.irBuiltIns.throwableType).apply { + result = irBlock { + +irCall(context.ir.symbols.onUnhandledException).apply { + putValueArgument(0, irGet(catchParameter)) + } + +irReturn(irInt(1)) + } + } + } + } + + return entryPoint +} diff --git a/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/EnumSpecialDescriptorsFactory.kt b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/EnumSpecialDescriptorsFactory.kt new file mode 100644 index 00000000000..afb5f15770b --- /dev/null +++ b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/EnumSpecialDescriptorsFactory.kt @@ -0,0 +1,228 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +package org.jetbrains.kotlin.backend.konan + +import org.jetbrains.kotlin.backend.common.ir.addFakeOverrides +import org.jetbrains.kotlin.backend.common.ir.addSimpleDelegatingConstructor +import org.jetbrains.kotlin.backend.common.ir.createParameterDeclarations +import org.jetbrains.kotlin.backend.common.lower.createIrBuilder +import org.jetbrains.kotlin.backend.konan.descriptors.synthesizedName +import org.jetbrains.kotlin.descriptors.ClassKind +import org.jetbrains.kotlin.descriptors.DescriptorVisibilities +import org.jetbrains.kotlin.descriptors.Modality +import org.jetbrains.kotlin.ir.UNDEFINED_OFFSET +import org.jetbrains.kotlin.ir.builders.declarations.buildFun +import org.jetbrains.kotlin.ir.builders.irBlockBody +import org.jetbrains.kotlin.ir.builders.irCall +import org.jetbrains.kotlin.ir.builders.irReturn +import org.jetbrains.kotlin.ir.declarations.* +import org.jetbrains.kotlin.ir.declarations.impl.IrClassImpl +import org.jetbrains.kotlin.ir.declarations.impl.IrFieldImpl +import org.jetbrains.kotlin.ir.declarations.impl.IrFunctionImpl +import org.jetbrains.kotlin.ir.descriptors.WrappedClassDescriptor +import org.jetbrains.kotlin.ir.descriptors.WrappedFieldDescriptor +import org.jetbrains.kotlin.ir.descriptors.WrappedSimpleFunctionDescriptor +import org.jetbrains.kotlin.ir.expressions.IrExpression +import org.jetbrains.kotlin.ir.expressions.impl.IrCallImpl +import org.jetbrains.kotlin.ir.expressions.impl.IrGetFieldImpl +import org.jetbrains.kotlin.ir.expressions.impl.IrGetObjectValueImpl +import org.jetbrains.kotlin.ir.symbols.IrSimpleFunctionSymbol +import org.jetbrains.kotlin.ir.symbols.impl.IrClassSymbolImpl +import org.jetbrains.kotlin.ir.symbols.impl.IrFieldSymbolImpl +import org.jetbrains.kotlin.ir.symbols.impl.IrSimpleFunctionSymbolImpl +import org.jetbrains.kotlin.ir.types.IrType +import org.jetbrains.kotlin.ir.types.typeWith +import org.jetbrains.kotlin.ir.util.* +import org.jetbrains.kotlin.name.Name +import org.jetbrains.kotlin.resolve.descriptorUtil.module + + +internal object DECLARATION_ORIGIN_ENUM : IrDeclarationOriginImpl("ENUM") + +/** + * Common interface for both [InternalLoweredEnum] and [ExternalLoweredEnum] + * that allows to work with lowered enum regardless of its location. + */ +internal interface LoweredEnumAccess { + val valuesGetter: IrSimpleFunction + val itemGetterSymbol: IrSimpleFunctionSymbol + val entriesMap: Map + fun getValuesField(startOffset: Int, endOffset: Int): IrExpression +} + +/** + * Represents lowered enum from current module. + */ +internal data class InternalLoweredEnum( + val implObject: IrClass, + val valuesField: IrField, + val valuesGetterWrapper: IrSimpleFunction, + override val valuesGetter: IrSimpleFunction, + override val itemGetterSymbol: IrSimpleFunctionSymbol, + override val entriesMap: Map +) : LoweredEnumAccess { + private fun internalObjectGetter(startOffset: Int, endOffset: Int) = + IrGetObjectValueImpl(startOffset, endOffset, + implObject.defaultType, + implObject.symbol + ) + + override fun getValuesField(startOffset: Int, endOffset: Int): IrExpression = IrGetFieldImpl( + startOffset, + endOffset, + valuesField.symbol, + valuesField.type, + internalObjectGetter(startOffset, endOffset) + ) +} + +/** + * Represents lowered enum that's located in external module. + */ +internal data class ExternalLoweredEnum( + override val valuesGetter: IrSimpleFunction, + override val itemGetterSymbol: IrSimpleFunctionSymbol, + override val entriesMap: Map +) : LoweredEnumAccess { + override fun getValuesField(startOffset: Int, endOffset: Int): IrExpression = + IrCallImpl(startOffset, endOffset, valuesGetter.returnType, valuesGetter.symbol, valuesGetter.typeParameters.size, valuesGetter.valueParameters.size) +} + +internal class EnumSpecialDeclarationsFactory(val context: Context) { + private val symbols = context.ir.symbols + + private fun enumEntriesMap(enumClass: IrClass): Map = + enumClass.declarations + .filterIsInstance() + .sortedBy { it.name } + .withIndex() + .associate { it.value.name to it.index } + .toMap() + + private fun findItemGetterSymbol(): IrSimpleFunctionSymbol = + symbols.array.functions.single { it.descriptor.name == Name.identifier("get") } + + private fun valuesArrayType(enumClass: IrClass): IrType = + symbols.array.typeWith(enumClass.defaultType) + + // We can't move property getter to the top-level scope. + // So add a wrapper instead. + private fun createValuesGetterWrapper(enumClass: IrClass, isExternal: Boolean): IrSimpleFunction = + context.irFactory.buildFun { + name = InternalAbi.getEnumValuesAccessorName(enumClass) + returnType = valuesArrayType(enumClass) + origin = InternalAbi.INTERNAL_ABI_ORIGIN + this.isExternal = isExternal + }.also { + if (isExternal) { + context.internalAbi.reference(it, enumClass.module) + } else { + context.internalAbi.declare(it, enumClass.module) + } + } + + fun createExternalLoweredEnum(enumClass: IrClass): ExternalLoweredEnum { + val enumEntriesMap = enumEntriesMap(enumClass) + val itemGetterSymbol = findItemGetterSymbol() + val valuesGetterWrapper = createValuesGetterWrapper(enumClass, isExternal = true) + return ExternalLoweredEnum(valuesGetterWrapper, itemGetterSymbol, enumEntriesMap) + } + + fun createInternalLoweredEnum(enumClass: IrClass): InternalLoweredEnum { + val startOffset = enumClass.startOffset + val endOffset = enumClass.endOffset + + val implObject = WrappedClassDescriptor().let { + IrClassImpl( + startOffset, endOffset, + DECLARATION_ORIGIN_ENUM, + IrClassSymbolImpl(it), + "OBJECT".synthesizedName, + ClassKind.OBJECT, + DescriptorVisibilities.PUBLIC, + Modality.FINAL, + isCompanion = false, + isInner = false, + isData = false, + isExternal = false, + isInline = false, + isExpect = false, + isFun = false + ).apply { + it.bind(this) + parent = enumClass + createParameterDeclarations() + } + } + + val valuesType = valuesArrayType(enumClass) + val valuesField = WrappedFieldDescriptor().let { + IrFieldImpl( + startOffset, endOffset, + DECLARATION_ORIGIN_ENUM, + IrFieldSymbolImpl(it), + "VALUES".synthesizedName, + valuesType, + DescriptorVisibilities.PRIVATE, + isFinal = true, + isExternal = false, + isStatic = false, + ).apply { + it.bind(this) + parent = implObject + } + } + + val valuesGetter = WrappedSimpleFunctionDescriptor().let { + IrFunctionImpl( + startOffset, endOffset, + DECLARATION_ORIGIN_ENUM, + IrSimpleFunctionSymbolImpl(it), + "get-VALUES".synthesizedName, + DescriptorVisibilities.PUBLIC, + Modality.FINAL, + valuesType, + isInline = false, + isExternal = false, + isTailrec = false, + isSuspend = false, + isExpect = false, + isFakeOverride = false, + isOperator = false, + isInfix = false + ).apply { + it.bind(this) + parent = implObject + } + } + + val constructorOfAny = context.irBuiltIns.anyClass.owner.constructors.first() + implObject.addSimpleDelegatingConstructor( + constructorOfAny, + context.irBuiltIns, + true // TODO: why primary? + ) + + implObject.superTypes += context.irBuiltIns.anyType + implObject.addFakeOverrides(context.irBuiltIns) + + val itemGetterSymbol = findItemGetterSymbol() + val enumEntriesMap = enumEntriesMap(enumClass) + val valuesGetterWrapper = createValuesGetterWrapper(enumClass, isExternal = false) + context.createIrBuilder(valuesGetterWrapper.symbol).run { + valuesGetterWrapper.body = irBlockBody { + +irReturn(irCall(valuesGetter)) + } + } + return InternalLoweredEnum( + implObject, + valuesField, + valuesGetterWrapper, + valuesGetter, + itemGetterSymbol, + enumEntriesMap) + } +} diff --git a/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/Exceptions.kt b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/Exceptions.kt new file mode 100644 index 00000000000..be0feda4785 --- /dev/null +++ b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/Exceptions.kt @@ -0,0 +1,23 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +package org.jetbrains.kotlin.backend.konan + +import org.jetbrains.kotlin.konan.KonanException +import org.jetbrains.kotlin.utils.KotlinExceptionWithAttachments + +/** + * Represents a compilation error caused by mistakes in an input file, e.g. undefined reference. + */ +class KonanCompilationException( + message: String = "", + cause: Throwable? = null +) : KotlinExceptionWithAttachments(message, cause) + +/** + * Internal compiler error: could not deserialize IR for inline function body. + */ +class KonanIrDeserializationException(message: String = "", cause: Throwable? = null) : KonanException(message, cause) + diff --git a/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/FeaturedLibraries.kt b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/FeaturedLibraries.kt new file mode 100644 index 00000000000..9138796d0a4 --- /dev/null +++ b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/FeaturedLibraries.kt @@ -0,0 +1,187 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +package org.jetbrains.kotlin.backend.konan + +import org.jetbrains.kotlin.library.resolver.KotlinLibraryResolveResult +import org.jetbrains.kotlin.cli.common.messages.CompilerMessageSeverity +import org.jetbrains.kotlin.config.CompilerConfiguration +import org.jetbrains.kotlin.descriptors.ModuleDescriptor +import org.jetbrains.kotlin.descriptors.konan.* +import org.jetbrains.kotlin.konan.file.File +import org.jetbrains.kotlin.konan.library.KonanLibrary +import org.jetbrains.kotlin.library.SearchPathResolver +import org.jetbrains.kotlin.library.isInterop +import org.jetbrains.kotlin.library.toUnresolvedLibraries +import org.jetbrains.kotlin.utils.addToStdlib.cast + +internal fun Context.getExportedDependencies(): List = getDescriptorsFromLibraries((config.resolve.exportedLibraries + config.resolve.includedLibraries).toSet()) +internal fun Context.getIncludedLibraryDescriptors(): List = getDescriptorsFromLibraries(config.resolve.includedLibraries.toSet()) + +private fun Context.getDescriptorsFromLibraries(libraries: Set) = + moduleDescriptor.allDependencyModules.filter { + when (val origin = it.klibModuleOrigin) { + CurrentKlibModuleOrigin, SyntheticModulesOrigin -> false + is DeserializedKlibModuleOrigin -> origin.library in libraries + } + } + +internal fun getExportedLibraries( + configuration: CompilerConfiguration, + resolvedLibraries: KotlinLibraryResolveResult, + resolver: SearchPathResolver, + report: Boolean +): List = getFeaturedLibraries( + configuration.getList(KonanConfigKeys.EXPORTED_LIBRARIES), + resolvedLibraries, + resolver, + if (report) FeaturedLibrariesReporter.forExportedLibraries(configuration) else FeaturedLibrariesReporter.Silent, + allowDefaultLibs = false +) + +internal fun getIncludedLibraries( + includedLibraryFiles: List, + configuration: CompilerConfiguration, + resolvedLibraries: KotlinLibraryResolveResult +): List = getFeaturedLibraries( + includedLibraryFiles.toSet(), + resolvedLibraries, + FeaturedLibrariesReporter.forIncludedLibraries(configuration), + allowDefaultLibs = false +) + +internal fun getCoveredLibraries( + configuration: CompilerConfiguration, + resolvedLibraries: KotlinLibraryResolveResult, + resolver: SearchPathResolver +): List = getFeaturedLibraries( + configuration.getList(KonanConfigKeys.LIBRARIES_TO_COVER), + resolvedLibraries, + resolver, + FeaturedLibrariesReporter.forCoveredLibraries(configuration), + allowDefaultLibs = true +) + +private sealed class FeaturedLibrariesReporter { + + abstract fun reportIllegalKind(library: KonanLibrary) + abstract fun reportNotIncludedLibraries(includedLibraries: List, remainingFeaturedLibraries: Set) + + protected val KonanLibrary.reportedKind: String + get() = when { + isInterop -> "Interop" + isDefault -> "Default" + else -> "Unknown kind" + } + + object Silent: FeaturedLibrariesReporter() { + override fun reportIllegalKind(library: KonanLibrary) {} + override fun reportNotIncludedLibraries(includedLibraries: List, remainingFeaturedLibraries: Set) {} + } + + abstract class BaseReporter(val configuration: CompilerConfiguration) : FeaturedLibrariesReporter() { + protected abstract fun illegalKindMessage(kind: String, libraryName: String): String + protected abstract fun notIncludedLibraryMessageTitle(): String + + override fun reportIllegalKind(library: KonanLibrary) { + configuration.report( + CompilerMessageSeverity.STRONG_WARNING, + illegalKindMessage(library.reportedKind, library.libraryName) + ) + } + + override fun reportNotIncludedLibraries(includedLibraries: List, remainingFeaturedLibraries: Set) { + val message = buildString { + appendLine(notIncludedLibraryMessageTitle()) + remainingFeaturedLibraries.forEach { appendLine(it) } + appendLine() + appendLine("Included libraries:") + includedLibraries.forEach { appendLine(it.libraryFile) } + } + + configuration.report(CompilerMessageSeverity.STRONG_WARNING, message) + } + } + + private class IncludedLibrariesReporter(val configuration: CompilerConfiguration) : FeaturedLibrariesReporter() { + override fun reportIllegalKind(library: KonanLibrary) = with(library) { + val message = "$reportedKind library $libraryName cannot be passed with -Xinclude " + + "(library path: ${libraryFile.absolutePath})" + configuration.report(CompilerMessageSeverity.STRONG_WARNING, message) + } + + override fun reportNotIncludedLibraries(includedLibraries: List, remainingFeaturedLibraries: Set) { + error("An included library is not found among resolved libraries") + } + } + + private class ExportedLibrariesReporter(configuration: CompilerConfiguration) : BaseReporter(configuration) { + override fun illegalKindMessage(kind: String, libraryName: String): String = + "$kind library $libraryName can't be exported with -Xexport-library" + + override fun notIncludedLibraryMessageTitle(): String = + "Following libraries are specified to be exported with -Xexport-library, but not included to the build:" + } + + private class CoveredLibraryReporter(configuration: CompilerConfiguration): BaseReporter(configuration) { + override fun illegalKindMessage(kind: String, libraryName: String): String = + "Cannot provide the code coverage for the $kind library $libraryName." + + override fun notIncludedLibraryMessageTitle(): String = + "The code coverage is enabled for the following libraries, but they are not included to the build:" + } + + companion object { + fun forExportedLibraries(configuration: CompilerConfiguration): FeaturedLibrariesReporter = + ExportedLibrariesReporter(configuration) + fun forCoveredLibraries(configuration: CompilerConfiguration): FeaturedLibrariesReporter = + CoveredLibraryReporter(configuration) + fun forIncludedLibraries(configuration: CompilerConfiguration): FeaturedLibrariesReporter = + IncludedLibrariesReporter(configuration) + } +} + +private fun getFeaturedLibraries( + featuredLibraries: List, + resolvedLibraries: KotlinLibraryResolveResult, + resolver: SearchPathResolver, + reporter: FeaturedLibrariesReporter, + allowDefaultLibs: Boolean +) = getFeaturedLibraries( + featuredLibraries.toUnresolvedLibraries.map { resolver.resolve(it).libraryFile }.toSet(), + resolvedLibraries, + reporter, + allowDefaultLibs +) + +private fun getFeaturedLibraries( + featuredLibraryFiles: Set, + resolvedLibraries: KotlinLibraryResolveResult, + reporter: FeaturedLibrariesReporter, + allowDefaultLibs: Boolean +) : List { + val remainingFeaturedLibraries = featuredLibraryFiles.toMutableSet() + val result = mutableListOf() + //TODO: please add type checks before cast. + val libraries = resolvedLibraries.getFullList(null).cast>() + + for (library in libraries) { + val libraryFile = library.libraryFile + if (libraryFile in featuredLibraryFiles) { + remainingFeaturedLibraries -= libraryFile + if (library.isInterop || (!allowDefaultLibs && library.isDefault)) { + reporter.reportIllegalKind(library) + } else { + result += library + } + } + } + + if (remainingFeaturedLibraries.isNotEmpty()) { + reporter.reportNotIncludedLibraries(libraries, remainingFeaturedLibraries) + } + + return result +} \ No newline at end of file diff --git a/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/GraphAlgorithms.kt b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/GraphAlgorithms.kt new file mode 100644 index 00000000000..8e08a573852 --- /dev/null +++ b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/GraphAlgorithms.kt @@ -0,0 +1,89 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +package org.jetbrains.kotlin.backend.konan + +internal interface DirectedGraphNode { + val key: K + val directEdges: List? + val reversedEdges: List? +} + +internal interface DirectedGraph> { + val nodes: Collection + fun get(key: K): N +} + +internal class DirectedGraphMultiNode(val nodes: Set) + +internal class DirectedGraphCondensation(val topologicalOrder: List>) + +// The Kosoraju-Sharir algorithm. +internal class DirectedGraphCondensationBuilder>(private val graph: DirectedGraph) { + private val visited = mutableSetOf() + private val order = mutableListOf() + private val nodeToMultiNodeMap = mutableMapOf>() + private val multiNodesOrder = mutableListOf>() + + fun build(): DirectedGraphCondensation { + // First phase. + graph.nodes.forEach { + if (!visited.contains(it.key)) + findOrder(it) + } + + // Second phase. + visited.clear() + val multiNodes = mutableListOf>() + order.reversed().forEach { + if (!visited.contains(it.key)) { + val nodes = mutableSetOf() + paint(it, nodes) + multiNodes += DirectedGraphMultiNode(nodes) + } + } + + // Topsort of built condensation. + multiNodes.forEach { multiNode -> + multiNode.nodes.forEach { nodeToMultiNodeMap.put(graph.get(it), multiNode) } + } + visited.clear() + multiNodes.forEach { + if (!visited.contains(it.nodes.first())) + findMultiNodesOrder(it) + } + + return DirectedGraphCondensation(multiNodesOrder.reversed()) + } + + private fun findOrder(node: N) { + visited += node.key + node.directEdges?.forEach { + if (!visited.contains(it)) + findOrder(graph.get(it)) + } + order += node + } + + private fun paint(node: N, multiNode: MutableSet) { + visited += node.key + multiNode += node.key + node.reversedEdges?.forEach { + if (!visited.contains(it)) + paint(graph.get(it), multiNode) + } + } + + private fun findMultiNodesOrder(node: DirectedGraphMultiNode) { + visited.addAll(node.nodes) + node.nodes.forEach { + graph.get(it).directEdges?.forEach { + if (!visited.contains(it)) + findMultiNodesOrder(nodeToMultiNodeMap[graph.get(it)]!!) + } + } + multiNodesOrder += node + } +} diff --git a/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/InlineClasses.kt b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/InlineClasses.kt new file mode 100644 index 00000000000..af230bc662e --- /dev/null +++ b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/InlineClasses.kt @@ -0,0 +1,318 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +package org.jetbrains.kotlin.backend.konan + +import org.jetbrains.kotlin.backend.common.ir.isTopLevel +import org.jetbrains.kotlin.backend.konan.descriptors.findPackage +import org.jetbrains.kotlin.backend.konan.ir.containsNull +import org.jetbrains.kotlin.backend.konan.ir.getSuperClassNotAny +import org.jetbrains.kotlin.builtins.PrimitiveType +import org.jetbrains.kotlin.descriptors.ClassDescriptor +import org.jetbrains.kotlin.descriptors.PackageFragmentDescriptor +import org.jetbrains.kotlin.ir.declarations.IrClass +import org.jetbrains.kotlin.ir.declarations.IrProperty +import org.jetbrains.kotlin.ir.symbols.IrClassSymbol +import org.jetbrains.kotlin.ir.symbols.IrTypeParameterSymbol +import org.jetbrains.kotlin.ir.symbols.isPublicApi +import org.jetbrains.kotlin.ir.types.IrType +import org.jetbrains.kotlin.ir.types.classifierOrFail +import org.jetbrains.kotlin.ir.types.makeNullable +import org.jetbrains.kotlin.ir.util.constructors +import org.jetbrains.kotlin.ir.util.defaultType +import org.jetbrains.kotlin.ir.util.packageFqName +import org.jetbrains.kotlin.name.ClassId +import org.jetbrains.kotlin.name.FqName +import org.jetbrains.kotlin.name.FqNameUnsafe +import org.jetbrains.kotlin.name.Name +import org.jetbrains.kotlin.resolve.descriptorUtil.fqNameUnsafe +import org.jetbrains.kotlin.resolve.descriptorUtil.getAllSuperClassifiers +import org.jetbrains.kotlin.types.KotlinType +import org.jetbrains.kotlin.types.isNullable +import org.jetbrains.kotlin.types.typeUtil.makeNullable + +/** + * TODO: there is [IrType::getInlinedClass] in [org.jetbrains.kotlin.ir.util] which isn't compatible with + * Native's implementation. Please take a look while commonization. + */ +fun IrType.getInlinedClassNative(): IrClass? = IrTypeInlineClassesSupport.getInlinedClass(this) + +/** + * TODO: there is [IrType::isInlined] in [org.jetbrains.kotlin.ir.util] which isn't compatible with + * Native's implementation. Please take a look while commonization. + */ +fun IrType.isInlinedNative(): Boolean = IrTypeInlineClassesSupport.isInlined(this) +fun IrClass.isInlined(): Boolean = IrTypeInlineClassesSupport.isInlined(this) +fun IrClass.isNativePrimitiveType() = IrTypeInlineClassesSupport.isTopLevelClass(this) && + KonanPrimitiveType.byFqNameParts[packageFqName]?.get(name) != null + +fun KotlinType.getInlinedClass(): ClassDescriptor? = KotlinTypeInlineClassesSupport.getInlinedClass(this) + +fun ClassDescriptor.isInlined(): Boolean = KotlinTypeInlineClassesSupport.isInlined(this) + +fun KotlinType.binaryRepresentationIsNullable() = KotlinTypeInlineClassesSupport.representationIsNullable(this) + +internal inline fun KotlinType.unwrapToPrimitiveOrReference( + eachInlinedClass: (inlinedClass: ClassDescriptor, nullable: Boolean) -> Unit, + ifPrimitive: (primitiveType: KonanPrimitiveType, nullable: Boolean) -> R, + ifReference: (type: KotlinType) -> R +): R = KotlinTypeInlineClassesSupport.unwrapToPrimitiveOrReference(this, eachInlinedClass, ifPrimitive, ifReference) + +// TODO: consider renaming to `isReference`. +fun KotlinType.binaryTypeIsReference(): Boolean = this.computePrimitiveBinaryTypeOrNull() == null +fun IrType.binaryTypeIsReference(): Boolean = this.computePrimitiveBinaryTypeOrNull() == null + +fun KotlinType.computePrimitiveBinaryTypeOrNull(): PrimitiveBinaryType? = + this.computeBinaryType().primitiveBinaryTypeOrNull() + +fun KotlinType.computeBinaryType(): BinaryType = KotlinTypeInlineClassesSupport.computeBinaryType(this) + +fun IrType.computePrimitiveBinaryTypeOrNull(): PrimitiveBinaryType? = + this.computeBinaryType().primitiveBinaryTypeOrNull() + +fun IrType.computeBinaryType(): BinaryType = IrTypeInlineClassesSupport.computeBinaryType(this) + +fun IrClass.inlinedClassIsNullable(): Boolean = this.defaultType.makeNullable().getInlinedClassNative() == this // TODO: optimize +fun IrClass.isUsedAsBoxClass(): Boolean = IrTypeInlineClassesSupport.isUsedAsBoxClass(this) + +/** + * Most "underlying" user-visible non-reference type. + * It is visible as inlined to compiler for simplicity. + */ +enum class KonanPrimitiveType(val classId: ClassId, val binaryType: BinaryType.Primitive) { + BOOLEAN(PrimitiveType.BOOLEAN, PrimitiveBinaryType.BOOLEAN), + CHAR(PrimitiveType.CHAR, PrimitiveBinaryType.SHORT), + BYTE(PrimitiveType.BYTE, PrimitiveBinaryType.BYTE), + SHORT(PrimitiveType.SHORT, PrimitiveBinaryType.SHORT), + INT(PrimitiveType.INT, PrimitiveBinaryType.INT), + LONG(PrimitiveType.LONG, PrimitiveBinaryType.LONG), + FLOAT(PrimitiveType.FLOAT, PrimitiveBinaryType.FLOAT), + DOUBLE(PrimitiveType.DOUBLE, PrimitiveBinaryType.DOUBLE), + NON_NULL_NATIVE_PTR(ClassId.topLevel(KonanFqNames.nonNullNativePtr.toSafe()), PrimitiveBinaryType.POINTER), + VECTOR128(ClassId.topLevel(KonanFqNames.Vector128), PrimitiveBinaryType.VECTOR128) + + ; + + constructor(primitiveType: PrimitiveType, primitiveBinaryType: PrimitiveBinaryType) + : this(ClassId.topLevel(primitiveType.typeFqName), primitiveBinaryType) + + constructor(classId: ClassId, primitiveBinaryType: PrimitiveBinaryType) + : this(classId, BinaryType.Primitive(primitiveBinaryType)) + + val fqName: FqNameUnsafe get() = this.classId.asSingleFqName().toUnsafe() + + companion object { + val byFqNameParts = KonanPrimitiveType.values().groupingBy { + assert(!it.classId.isNestedClass) + it.classId.packageFqName + }.fold({ _, _ -> mutableMapOf() }, + { _, accumulator, element -> + accumulator.also { it[element.classId.shortClassName] = element } + }) + } +} + +internal abstract class InlineClassesSupport { + protected abstract fun isNullable(type: Type): Boolean + protected abstract fun makeNullable(type: Type): Type + protected abstract fun erase(type: Type): Class + protected abstract fun computeFullErasure(type: Type): Sequence + protected abstract fun hasInlineModifier(clazz: Class): Boolean + protected abstract fun getNativePointedSuperclass(clazz: Class): Class? + protected abstract fun getInlinedClassUnderlyingType(clazz: Class): Type + protected abstract fun getPackageFqName(clazz: Class): FqName? + protected abstract fun getName(clazz: Class): Name? + abstract fun isTopLevelClass(clazz: Class): Boolean + + @JvmName("classIsInlined") + fun isInlined(clazz: Class): Boolean = getInlinedClass(clazz) != null + fun isInlined(type: Type): Boolean = getInlinedClass(type) != null + + fun isUsedAsBoxClass(clazz: Class) = getInlinedClass(clazz) == clazz // To handle NativePointed subclasses. + + fun getInlinedClass(type: Type): Class? = + getInlinedClass(erase(type), isNullable(type)) + + protected fun getKonanPrimitiveType(clazz: Class): KonanPrimitiveType? = + if (isTopLevelClass(clazz)) + KonanPrimitiveType.byFqNameParts[getPackageFqName(clazz)]?.get(getName(clazz)) + else null + + protected fun isImplicitInlineClass(clazz: Class): Boolean = + isTopLevelClass(clazz) && (getKonanPrimitiveType(clazz) != null || + getName(clazz) == KonanFqNames.nativePtr.shortName() && getPackageFqName(clazz) == KonanFqNames.internalPackageName || + getName(clazz) == InteropFqNames.cPointer.shortName() && getPackageFqName(clazz) == InteropFqNames.cPointer.parent().toSafe()) + + private fun getInlinedClass(erased: Class, isNullable: Boolean): Class? { + val inlinedClass = getInlinedClass(erased) ?: return null + return if (!isNullable || representationIsNonNullReferenceOrPointer(inlinedClass)) { + inlinedClass + } else { + null + } + } + + tailrec fun representationIsNonNullReferenceOrPointer(clazz: Class): Boolean { + val konanPrimitiveType = getKonanPrimitiveType(clazz) + if (konanPrimitiveType != null) { + return konanPrimitiveType == KonanPrimitiveType.NON_NULL_NATIVE_PTR + } + + val inlinedClass = getInlinedClass(clazz) ?: return true + + val underlyingType = getInlinedClassUnderlyingType(inlinedClass) + return if (isNullable(underlyingType)) { + false + } else { + representationIsNonNullReferenceOrPointer(erase(underlyingType)) + } + } + + @JvmName("classGetInlinedClass") + private fun getInlinedClass(clazz: Class): Class? = + if (hasInlineModifier(clazz) || isImplicitInlineClass(clazz)) { + clazz + } else { + getNativePointedSuperclass(clazz) + } + + inline fun unwrapToPrimitiveOrReference( + type: Type, + eachInlinedClass: (inlinedClass: Class, nullable: Boolean) -> Unit, + ifPrimitive: (primitiveType: KonanPrimitiveType, nullable: Boolean) -> R, + ifReference: (type: Type) -> R + ): R { + var currentType: Type = type + + while (true) { + val inlinedClass = getInlinedClass(currentType) + if (inlinedClass == null) { + return ifReference(currentType) + } + + val nullable = isNullable(currentType) + + getKonanPrimitiveType(inlinedClass)?.let { primitiveType -> + return ifPrimitive(primitiveType, nullable) + } + + eachInlinedClass(inlinedClass, nullable) + + val underlyingType = getInlinedClassUnderlyingType(inlinedClass) + currentType = if (nullable) makeNullable(underlyingType) else underlyingType + } + } + + fun representationIsNullable(type: Type): Boolean { + unwrapToPrimitiveOrReference( + type, + eachInlinedClass = { _, nullable -> if (nullable) return true }, + ifPrimitive = { _, nullable -> return nullable }, + ifReference = { return isNullable(it) } + ) + } + + // TODO: optimize. + fun computeBinaryType(type: Type): BinaryType { + val erased = erase(type) + val inlinedClass = getInlinedClass(erased, isNullable(type)) ?: return createReferenceBinaryType(type) + + getKonanPrimitiveType(inlinedClass)?.let { + return it.binaryType + } + + val underlyingBinaryType = computeBinaryType(getInlinedClassUnderlyingType(inlinedClass)) + return if (isNullable(type) && underlyingBinaryType is BinaryType.Reference) { + BinaryType.Reference(underlyingBinaryType.types, true) + } else { + underlyingBinaryType + } + } + + private fun createReferenceBinaryType(type: Type): BinaryType.Reference = + BinaryType.Reference(computeFullErasure(type), true) +} + +internal object KotlinTypeInlineClassesSupport : InlineClassesSupport() { + + override fun isNullable(type: KotlinType): Boolean = type.isNullable() + override fun makeNullable(type: KotlinType): KotlinType = type.makeNullable() + override tailrec fun erase(type: KotlinType): ClassDescriptor { + val descriptor = type.constructor.declarationDescriptor + return if (descriptor is ClassDescriptor) { + descriptor + } else { + erase(type.constructor.supertypes.first()) + } + } + + override fun computeFullErasure(type: KotlinType): Sequence { + val classifier = type.constructor.declarationDescriptor + return if (classifier is ClassDescriptor) sequenceOf(classifier) + else type.constructor.supertypes.asSequence().flatMap { computeFullErasure(it) } + } + + override fun hasInlineModifier(clazz: ClassDescriptor): Boolean = clazz.isInline + + override fun getNativePointedSuperclass(clazz: ClassDescriptor): ClassDescriptor? = clazz.getAllSuperClassifiers() + .firstOrNull { it.fqNameUnsafe == InteropFqNames.nativePointed } as ClassDescriptor? + + override fun getInlinedClassUnderlyingType(clazz: ClassDescriptor): KotlinType = + clazz.unsubstitutedPrimaryConstructor!!.valueParameters.single().type + + override fun getPackageFqName(clazz: ClassDescriptor) = + clazz.findPackage().fqName + + override fun getName(clazz: ClassDescriptor) = + clazz.name + + override fun isTopLevelClass(clazz: ClassDescriptor): Boolean = clazz.containingDeclaration is PackageFragmentDescriptor +} + +private object IrTypeInlineClassesSupport : InlineClassesSupport() { + + override fun isNullable(type: IrType): Boolean = type.containsNull() + + override fun makeNullable(type: IrType): IrType = type.makeNullable() + + override tailrec fun erase(type: IrType): IrClass { + val classifier = type.classifierOrFail + return when (classifier) { + is IrClassSymbol -> classifier.owner + is IrTypeParameterSymbol -> erase(classifier.owner.superTypes.first()) + else -> error(classifier) + } + } + + override fun computeFullErasure(type: IrType): Sequence { + val classifier = type.classifierOrFail + return when (classifier) { + is IrClassSymbol -> sequenceOf(classifier.owner) + is IrTypeParameterSymbol -> classifier.owner.superTypes.asSequence().flatMap { computeFullErasure(it) } + else -> error(classifier) + } + } + + override fun hasInlineModifier(clazz: IrClass): Boolean = clazz.descriptor.isInline + + override fun getNativePointedSuperclass(clazz: IrClass): IrClass? { + var superClass: IrClass? = clazz + while (superClass != null && (!superClass.symbol.isPublicApi || InteropIdSignatures.nativePointed != superClass.symbol.signature)) + superClass = superClass.getSuperClassNotAny() + return superClass + } + + override fun getInlinedClassUnderlyingType(clazz: IrClass): IrType = + clazz.constructors.firstOrNull { it.isPrimary }?.valueParameters?.single()?.type + ?: clazz.declarations.filterIsInstance().single { it.backingField != null }.backingField!!.type + + override fun getPackageFqName(clazz: IrClass) = + clazz.packageFqName + + override fun getName(clazz: IrClass): Name? = + clazz.name + + override fun isTopLevelClass(clazz: IrClass): Boolean = clazz.isTopLevel +} diff --git a/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/InternalAbi.kt b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/InternalAbi.kt new file mode 100644 index 00000000000..d38aaed178d --- /dev/null +++ b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/InternalAbi.kt @@ -0,0 +1,88 @@ +/* + * Copyright 2010-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ +package org.jetbrains.kotlin.backend.konan + +import org.jetbrains.kotlin.backend.common.ir.addChild +import org.jetbrains.kotlin.backend.konan.descriptors.synthesizedName +import org.jetbrains.kotlin.backend.konan.llvm.llvmSymbolOrigin +import org.jetbrains.kotlin.descriptors.ModuleDescriptor +import org.jetbrains.kotlin.ir.declarations.* +import org.jetbrains.kotlin.ir.declarations.impl.IrModuleFragmentImpl +import org.jetbrains.kotlin.ir.util.NaiveSourceBasedFileEntryImpl +import org.jetbrains.kotlin.ir.util.addFile +import org.jetbrains.kotlin.ir.util.fqNameForIrSerialization +import org.jetbrains.kotlin.name.FqName +import org.jetbrains.kotlin.name.Name + +/** + * Sometimes we need to reference symbols that are not declared in metadata. + * For example, symbol might be declared during lowering. + * In case of compiler caches, this means that it is not accessible as Lazy IR + * and we have to explicitly add an external declaration. + */ +internal class InternalAbi(private val context: Context) { + /** + * Files that stores all internal ABI declarations. + * We use per-module files so that global initializer will be stored + * in the appropriate modules. + * + * We have to store such declarations in top-level to avoid mangling that + * makes referencing harder. + * A bit better solution is to add files with proper packages, but it is impossible + * during FileLowering (hello, ConcurrentModificationException). + */ + private lateinit var internalAbiFiles: Map + + /** + * Representation of ABI files from external modules. + */ + private val externalAbiFiles = mutableMapOf() + + fun init(modules: List) { + internalAbiFiles = modules.associate { it.descriptor to createAbiFile(it) } + } + + private fun createAbiFile(module: IrModuleFragment): IrFile = + module.addFile(NaiveSourceBasedFileEntryImpl("internal"), FqName("kotlin.native.caches.abi")) + + /** + * Adds external [function] from [module] to a list of external references. + */ + fun reference(function: IrFunction, module: ModuleDescriptor) { + assert(function.isExternal) { "Function that represents external ABI should be marked as external" } + context.llvmImports.add(module.llvmSymbolOrigin) + externalAbiFiles.getOrPut(module) { + createAbiFile(IrModuleFragmentImpl(module, context.irBuiltIns)) + }.addChild(function) + } + + /** + * Adds [function] to a list of [module]'s publicly available symbols. + */ + fun declare(function: IrFunction, module: ModuleDescriptor) { + internalAbiFiles.getValue(module).addChild(function) + } + + companion object { + /** + * Allows to distinguish external declarations to internal ABI. + */ + val INTERNAL_ABI_ORIGIN = object : IrDeclarationOriginImpl("INTERNAL_ABI") {} + + fun getCompanionObjectAccessorName(companion: IrClass): Name = + getMangledNameFor("globalAccessor", companion) + + fun getEnumValuesAccessorName(enum: IrClass): Name = + getMangledNameFor("getValues", enum) + + /** + * Generate name for declaration that will be a part of internal ABI. + */ + private fun getMangledNameFor(declarationName: String, parent: IrDeclarationParent): Name { + val prefix = parent.fqNameForIrSerialization + return "$prefix.$declarationName".synthesizedName + } + } +} \ No newline at end of file diff --git a/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/InteropUtils.kt b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/InteropUtils.kt new file mode 100644 index 00000000000..e7af77b2aca --- /dev/null +++ b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/InteropUtils.kt @@ -0,0 +1,129 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +package org.jetbrains.kotlin.backend.konan + +import org.jetbrains.kotlin.builtins.UnsignedType +import org.jetbrains.kotlin.builtins.konan.KonanBuiltIns +import org.jetbrains.kotlin.descriptors.ClassDescriptor +import org.jetbrains.kotlin.descriptors.findClassAcrossModuleDependencies +import org.jetbrains.kotlin.incremental.components.NoLookupLocation +import org.jetbrains.kotlin.ir.types.getPublicSignature +import org.jetbrains.kotlin.name.FqName +import org.jetbrains.kotlin.name.Name +import org.jetbrains.kotlin.resolve.scopes.MemberScope +import org.jetbrains.kotlin.types.TypeUtils + +object InteropFqNames { + + const val cPointerName = "CPointer" + const val nativePointedName = "NativePointed" + + val packageName = FqName("kotlinx.cinterop") + + val cPointer = packageName.child(Name.identifier(cPointerName)).toUnsafe() + val nativePointed = packageName.child(Name.identifier(nativePointedName)).toUnsafe() +} + +object InteropIdSignatures { + val nativePointed = getPublicSignature(InteropFqNames.packageName, InteropFqNames.nativePointedName) +} + +internal class InteropBuiltIns(builtIns: KonanBuiltIns) { + + val packageScope = builtIns.builtInsModule.getPackage(InteropFqNames.packageName).memberScope + + val nativePointed = packageScope.getContributedClass(InteropFqNames.nativePointedName) + + val cValuesRef = this.packageScope.getContributedClass("CValuesRef") + val cValues = this.packageScope.getContributedClass("CValues") + val cValue = this.packageScope.getContributedClass("CValue") + val cOpaque = this.packageScope.getContributedClass("COpaque") + val cValueWrite = this.packageScope.getContributedFunctions("write") + .single { it.extensionReceiverParameter?.type?.constructor?.declarationDescriptor == cValue } + val cValueRead = this.packageScope.getContributedFunctions("readValue") + .single { it.valueParameters.size == 1 } + + val cEnum = this.packageScope.getContributedClass("CEnum") + val cEnumVar = this.packageScope.getContributedClass("CEnumVar") + val cStructVar = this.packageScope.getContributedClass("CStructVar") + val cStructVarType = cStructVar.defaultType.memberScope.getContributedClass("Type") + val cPrimitiveVar = this.packageScope.getContributedClass("CPrimitiveVar") + val cPrimitiveVarType = cPrimitiveVar.defaultType.memberScope.getContributedClass("Type") + + val nativeMemUtils = this.packageScope.getContributedClass("nativeMemUtils") + + val allocType = this.packageScope.getContributedFunctions("alloc") + .single { it.extensionReceiverParameter != null + && it.valueParameters.singleOrNull()?.name?.toString() == "type" } + + val cPointer = this.packageScope.getContributedClass(InteropFqNames.cPointerName) + + val cPointerRawValue = cPointer.unsubstitutedMemberScope.getContributedVariables("rawValue").single() + + val cPointerGetRawValue = packageScope.getContributedFunctions("getRawValue").single { + val extensionReceiverParameter = it.extensionReceiverParameter + extensionReceiverParameter != null && + TypeUtils.getClassDescriptor(extensionReceiverParameter.type) == cPointer + } + + val cstr = packageScope.getContributedVariables("cstr").single() + val wcstr = packageScope.getContributedVariables("wcstr").single() + val memScope = packageScope.getContributedClass("MemScope") + + val nativePointedRawPtrGetter = + nativePointed.unsubstitutedMemberScope.getContributedVariables("rawPtr").single().getter!! + + val nativePointedGetRawPointer = packageScope.getContributedFunctions("getRawPointer").single { + val extensionReceiverParameter = it.extensionReceiverParameter + extensionReceiverParameter != null && + TypeUtils.getClassDescriptor(extensionReceiverParameter.type) == nativePointed + } + + val typeOf = packageScope.getContributedFunctions("typeOf").single() + + private fun KonanBuiltIns.getUnsignedClass(unsignedType: UnsignedType): ClassDescriptor = + this.builtInsModule.findClassAcrossModuleDependencies(unsignedType.classId)!! + + val objCObject = packageScope.getContributedClass("ObjCObject") + + val objCObjectBase = packageScope.getContributedClass("ObjCObjectBase") + + val allocObjCObject = packageScope.getContributedFunctions("allocObjCObject").single() + + val getObjCClass = packageScope.getContributedFunctions("getObjCClass").single() + + val objCObjectRawPtr = packageScope.getContributedFunctions("objcPtr").single() + + val interpretObjCPointerOrNull = packageScope.getContributedFunctions("interpretObjCPointerOrNull").single() + val interpretObjCPointer = packageScope.getContributedFunctions("interpretObjCPointer").single() + val interpretNullablePointed = packageScope.getContributedFunctions("interpretNullablePointed").single() + val interpretCPointer = packageScope.getContributedFunctions("interpretCPointer").single() + + val objCObjectSuperInitCheck = packageScope.getContributedFunctions("superInitCheck").single() + val objCObjectInitBy = packageScope.getContributedFunctions("initBy").single() + + val objCAction = packageScope.getContributedClass("ObjCAction") + + val objCOutlet = packageScope.getContributedClass("ObjCOutlet") + + val objCOverrideInit = objCObjectBase.unsubstitutedMemberScope.getContributedClass("OverrideInit") + + val objCMethodImp = packageScope.getContributedClass("ObjCMethodImp") + + val exportObjCClass = packageScope.getContributedClass("ExportObjCClass") + + val CreateNSStringFromKString = packageScope.getContributedFunctions("CreateNSStringFromKString").single() + +} + +private fun MemberScope.getContributedVariables(name: String) = + this.getContributedVariables(Name.identifier(name), NoLookupLocation.FROM_BUILTINS) + +private fun MemberScope.getContributedClass(name: String): ClassDescriptor = + this.getContributedClassifier(Name.identifier(name), NoLookupLocation.FROM_BUILTINS) as ClassDescriptor + +private fun MemberScope.getContributedFunctions(name: String) = + this.getContributedFunctions(Name.identifier(name), NoLookupLocation.FROM_BUILTINS) diff --git a/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/KonanBackendContext.kt b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/KonanBackendContext.kt new file mode 100644 index 00000000000..56c000f2e2f --- /dev/null +++ b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/KonanBackendContext.kt @@ -0,0 +1,92 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +package org.jetbrains.kotlin.backend.konan + +import org.jetbrains.kotlin.backend.common.CommonBackendContext +import org.jetbrains.kotlin.backend.common.DefaultMapping +import org.jetbrains.kotlin.backend.common.Mapping +import org.jetbrains.kotlin.backend.konan.descriptors.KonanSharedVariablesManager +import org.jetbrains.kotlin.backend.konan.descriptors.findPackage +import org.jetbrains.kotlin.backend.konan.descriptors.kotlinNativeInternal +import org.jetbrains.kotlin.backend.konan.ir.KonanIr +import org.jetbrains.kotlin.builtins.konan.KonanBuiltIns +import org.jetbrains.kotlin.cli.common.CLIConfigurationKeys +import org.jetbrains.kotlin.cli.common.messages.CompilerMessageLocation +import org.jetbrains.kotlin.cli.common.messages.CompilerMessageSeverity +import org.jetbrains.kotlin.cli.common.messages.MessageCollector +import org.jetbrains.kotlin.descriptors.ClassDescriptor +import org.jetbrains.kotlin.descriptors.FunctionDescriptor +import org.jetbrains.kotlin.incremental.components.NoLookupLocation +import org.jetbrains.kotlin.ir.IrElement +import org.jetbrains.kotlin.ir.builders.IrBuilderWithScope +import org.jetbrains.kotlin.ir.declarations.IrClass +import org.jetbrains.kotlin.ir.declarations.IrDeclaration +import org.jetbrains.kotlin.ir.declarations.IrFactory +import org.jetbrains.kotlin.ir.declarations.IrFile +import org.jetbrains.kotlin.ir.declarations.impl.IrFactoryImpl +import org.jetbrains.kotlin.ir.symbols.IrFunctionSymbol +import org.jetbrains.kotlin.ir.symbols.IrSimpleFunctionSymbol +import org.jetbrains.kotlin.name.Name + +internal abstract class KonanBackendContext(val config: KonanConfig) : CommonBackendContext { + abstract override val builtIns: KonanBuiltIns + + abstract override val ir: KonanIr + + override val transformedFunction: MutableMap + get() = TODO("not implemented") + override val scriptMode: Boolean = false + + override val sharedVariablesManager by lazy { + // Creating lazily because builtIns module seems to be incomplete during `link` test; + // TODO: investigate this. + KonanSharedVariablesManager(this) + } + + fun getKonanInternalClass(name: String): ClassDescriptor = + builtIns.kotlinNativeInternal.getContributedClassifier(Name.identifier(name), NoLookupLocation.FROM_BACKEND) as ClassDescriptor + + fun getKonanInternalFunctions(name: String): List = + builtIns.kotlinNativeInternal.getContributedFunctions(Name.identifier(name), NoLookupLocation.FROM_BACKEND).toList() + + val messageCollector: MessageCollector + get() = config.configuration.getNotNull(CLIConfigurationKeys.MESSAGE_COLLECTOR_KEY) + + override fun report(element: IrElement?, irFile: IrFile?, message: String, isError: Boolean) { + val location = element?.getCompilerMessageLocation(irFile ?: error("irFile should be not null for $element")) + this.messageCollector.report( + if (isError) CompilerMessageSeverity.ERROR else CompilerMessageSeverity.WARNING, + message, location + ) + } + + override val internalPackageFqn = KonanFqNames.internalPackageName + + override val mapping: Mapping = DefaultMapping() + + override val extractedLocalClasses: MutableSet = mutableSetOf() + + override val irFactory: IrFactory = IrFactoryImpl +} + +internal fun IrElement.getCompilerMessageLocation(containingFile: IrFile): CompilerMessageLocation? = + createCompilerMessageLocation(containingFile, this.startOffset, this.endOffset) + +internal fun IrBuilderWithScope.getCompilerMessageLocation(): CompilerMessageLocation? { + val declaration = this.scope.scopeOwnerSymbol.owner as? IrDeclaration ?: return null + val file = declaration.findPackage() as? IrFile ?: return null + return createCompilerMessageLocation(file, startOffset, endOffset) +} + +private fun createCompilerMessageLocation(containingFile: IrFile, startOffset: Int, endOffset: Int): CompilerMessageLocation? { + val sourceRangeInfo = containingFile.fileEntry.getSourceRangeInfo(startOffset, endOffset) + return CompilerMessageLocation.create( + path = sourceRangeInfo.filePath, + line = sourceRangeInfo.startLineNumber + 1, + column = sourceRangeInfo.startColumnNumber + 1, + lineContent = null // TODO: retrieve the line content. + ) +} diff --git a/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/KonanCompilerFrontendServices.kt b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/KonanCompilerFrontendServices.kt new file mode 100644 index 00000000000..5ef2399e257 --- /dev/null +++ b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/KonanCompilerFrontendServices.kt @@ -0,0 +1,48 @@ +/* + * Copyright 2010-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +package org.jetbrains.kotlin.backend.konan + +import org.jetbrains.kotlin.analyzer.ModuleInfo +import org.jetbrains.kotlin.backend.konan.objcexport.ObjCExportLazy +import org.jetbrains.kotlin.backend.konan.objcexport.ObjCExportLazyImpl +import org.jetbrains.kotlin.backend.konan.objcexport.ObjCExportWarningCollector +import org.jetbrains.kotlin.backend.konan.objcexport.dumpObjCHeader +import org.jetbrains.kotlin.container.* +import org.jetbrains.kotlin.psi.KtFile +import org.jetbrains.kotlin.resolve.deprecation.DeprecationResolver + +internal fun StorageComponentContainer.initContainer(config: KonanConfig) { + this.useImpl() + + if (config.configuration.get(KonanConfigKeys.EMIT_LAZY_OBJC_HEADER_FILE) != null) { + this.useImpl() + this.useInstance(ObjCExportWarningCollector.SILENT) + + useInstance(object : ObjCExportLazy.Configuration { + override val frameworkName: String + get() = config.moduleId + + override fun isIncluded(moduleInfo: ModuleInfo): Boolean = true + + override fun getCompilerModuleName(moduleInfo: ModuleInfo): String { + TODO() + } + + override val objcGenerics: Boolean + get() = config.configuration.getBoolean(KonanConfigKeys.OBJC_GENERICS) + }) + } +} + +internal fun ComponentProvider.postprocessComponents(context: Context, files: Collection) { + context.frontendServices = this.get() + + context.config.configuration.get(KonanConfigKeys.EMIT_LAZY_OBJC_HEADER_FILE)?.let { + this.get().dumpObjCHeader(files, it) + } +} + +class FrontendServices(val deprecationResolver: DeprecationResolver) \ No newline at end of file diff --git a/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/KonanConfig.kt b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/KonanConfig.kt new file mode 100644 index 00000000000..54e22cefe0e --- /dev/null +++ b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/KonanConfig.kt @@ -0,0 +1,202 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +package org.jetbrains.kotlin.backend.konan + +import com.intellij.openapi.project.Project +import org.jetbrains.kotlin.cli.common.CLIConfigurationKeys +import org.jetbrains.kotlin.cli.common.config.kotlinSourceRoots +import org.jetbrains.kotlin.cli.common.messages.CompilerMessageSeverity +import org.jetbrains.kotlin.config.CommonConfigurationKeys +import org.jetbrains.kotlin.config.CompilerConfiguration +import org.jetbrains.kotlin.descriptors.ModuleDescriptor +import org.jetbrains.kotlin.konan.CURRENT +import org.jetbrains.kotlin.konan.CompilerVersion +import org.jetbrains.kotlin.konan.MetaVersion +import org.jetbrains.kotlin.konan.TempFiles +import org.jetbrains.kotlin.konan.file.File +import org.jetbrains.kotlin.konan.library.KonanLibrary +import org.jetbrains.kotlin.konan.properties.loadProperties +import org.jetbrains.kotlin.konan.target.* +import org.jetbrains.kotlin.konan.util.KonanHomeProvider +import org.jetbrains.kotlin.library.KotlinLibrary +import org.jetbrains.kotlin.library.resolver.TopologicalLibraryOrder +import org.jetbrains.kotlin.utils.addToStdlib.cast + +class KonanConfig(val project: Project, val configuration: CompilerConfiguration) { + + internal val distribution = Distribution( + configuration.get(KonanConfigKeys.KONAN_HOME) ?: KonanHomeProvider.determineKonanHome(), + false, + configuration.get(KonanConfigKeys.RUNTIME_FILE) + ) + + private val platformManager = PlatformManager(distribution) + internal val targetManager = platformManager.targetManager(configuration.get(KonanConfigKeys.TARGET)) + internal val target = targetManager.target + internal val phaseConfig = configuration.get(CLIConfigurationKeys.PHASE_CONFIG)!! + + // TODO: debug info generation mode and debug/release variant selection probably requires some refactoring. + val debug: Boolean get() = configuration.getBoolean(KonanConfigKeys.DEBUG) + val lightDebug: Boolean = configuration.get(KonanConfigKeys.LIGHT_DEBUG) + ?: target.family.isAppleFamily // Default is true for Apple targets. + + val memoryModel: MemoryModel get() = configuration.get(KonanConfigKeys.MEMORY_MODEL)!! + + val needCompilerVerification: Boolean + get() = configuration.get(KonanConfigKeys.VERIFY_COMPILER) ?: + (configuration.getBoolean(KonanConfigKeys.OPTIMIZATION) || + CompilerVersion.CURRENT.meta != MetaVersion.RELEASE) + + init { + if (!platformManager.isEnabled(target)) { + error("Target ${target.visibleName} is not available on the ${HostManager.hostName} host") + } + } + + val platform = platformManager.platform(target).apply { + if (configuration.getBoolean(KonanConfigKeys.CHECK_DEPENDENCIES)) { + downloadDependencies() + } + } + + internal val clang = platform.clang + val indirectBranchesAreAllowed = target != KonanTarget.WASM32 + val threadsAreAllowed = (target != KonanTarget.WASM32) && (target !is KonanTarget.ZEPHYR) + + internal val produce get() = configuration.get(KonanConfigKeys.PRODUCE)!! + + internal val metadataKlib get() = configuration.get(KonanConfigKeys.METADATA_KLIB)!! + + internal val produceStaticFramework get() = configuration.getBoolean(KonanConfigKeys.STATIC_FRAMEWORK) + + internal val purgeUserLibs: Boolean + get() = configuration.getBoolean(KonanConfigKeys.PURGE_USER_LIBS) + + internal val resolve = KonanLibrariesResolveSupport(configuration, target, distribution) + + internal val resolvedLibraries get() = resolve.resolvedLibraries + + internal val cacheSupport = CacheSupport(configuration, resolvedLibraries, target, produce) + + internal val cachedLibraries: CachedLibraries + get() = cacheSupport.cachedLibraries + + internal val librariesToCache: Set + get() = cacheSupport.librariesToCache + + val outputFiles = + OutputFiles(configuration.get(KonanConfigKeys.OUTPUT) ?: cacheSupport.tryGetImplicitOutput(), + target, produce) + + val tempFiles = TempFiles(outputFiles.outputName, configuration.get(KonanConfigKeys.TEMPORARY_FILES_DIR)) + + val outputFile get() = outputFiles.mainFile + + val moduleId: String + get() = configuration.get(KonanConfigKeys.MODULE_NAME) ?: File(outputFiles.outputName).name + + val shortModuleName: String? + get() = configuration.get(KonanConfigKeys.SHORT_MODULE_NAME) + + val infoArgsOnly = configuration.kotlinSourceRoots.isEmpty() + && configuration[KonanConfigKeys.INCLUDED_LIBRARIES].isNullOrEmpty() + && librariesToCache.isEmpty() + + fun librariesWithDependencies(moduleDescriptor: ModuleDescriptor?): List { + if (moduleDescriptor == null) error("purgeUnneeded() only works correctly after resolve is over, and we have successfully marked package files as needed or not needed.") + return resolvedLibraries.filterRoots { (!it.isDefault && !this.purgeUserLibs) || it.isNeededForLink }.getFullList(TopologicalLibraryOrder).cast() + } + + val shouldCoverSources = configuration.getBoolean(KonanConfigKeys.COVERAGE) + private val shouldCoverLibraries = !configuration.getList(KonanConfigKeys.LIBRARIES_TO_COVER).isNullOrEmpty() + + internal val runtimeNativeLibraries: List = mutableListOf().apply { + add(if (debug) "debug.bc" else "release.bc") + val effectiveMemoryModel = when (memoryModel) { + MemoryModel.STRICT -> MemoryModel.STRICT + MemoryModel.RELAXED -> MemoryModel.RELAXED + MemoryModel.EXPERIMENTAL -> { + if (!target.supportsMimallocAllocator()) { + configuration.report(CompilerMessageSeverity.STRONG_WARNING, + "Experimental memory model requires mimalloc allocator. Used strict memory model.") + MemoryModel.STRICT + } else if (!target.supportsThreads()) { + configuration.report(CompilerMessageSeverity.STRONG_WARNING, + "Experimental memory model requires threads, which are not supported on target ${target.name}. Used strict memory model.") + MemoryModel.STRICT + } else { + MemoryModel.EXPERIMENTAL + } + } + } + val useMimalloc = if (effectiveMemoryModel == MemoryModel.EXPERIMENTAL) { + true // we already checked that target supports mimalloc. + } else if (configuration.get(KonanConfigKeys.ALLOCATION_MODE) == "mimalloc") { + if (target.supportsMimallocAllocator()) { + true + } else { + configuration.report(CompilerMessageSeverity.STRONG_WARNING, + "Mimalloc allocator isn't supported on target ${target.name}. Used standard mode.") + false + } + } else { + false + } + when (effectiveMemoryModel) { + MemoryModel.STRICT -> { + add("strict.bc") + add("legacy_memory_manager.bc") + } + MemoryModel.RELAXED -> { + add("relaxed.bc") + add("legacy_memory_manager.bc") + } + MemoryModel.EXPERIMENTAL -> { + add("experimental_memory_manager.bc") + } + } + if (shouldCoverLibraries || shouldCoverSources) add("profileRuntime.bc") + if (useMimalloc) { + add("opt_alloc.bc") + add("mimalloc.bc") + } else { + add("std_alloc.bc") + } + }.map { + File(distribution.defaultNatives(target)).child(it).absolutePath + } + + internal val launcherNativeLibraries: List = distribution.launcherFiles.map { + File(distribution.defaultNatives(target)).child(it).absolutePath + } + + internal val objCNativeLibrary: String = + File(distribution.defaultNatives(target)).child("objc.bc").absolutePath + + internal val exceptionsSupportNativeLibrary: String = + File(distribution.defaultNatives(target)).child("exceptionsSupport.bc").absolutePath + + internal val nativeLibraries: List = + configuration.getList(KonanConfigKeys.NATIVE_LIBRARY_FILES) + + internal val includeBinaries: List = + configuration.getList(KonanConfigKeys.INCLUDED_BINARY_FILES) + + internal val languageVersionSettings = + configuration.get(CommonConfigurationKeys.LANGUAGE_VERSION_SETTINGS)!! + + internal val friendModuleFiles: Set = + configuration.get(KonanConfigKeys.FRIEND_MODULES)?.map { File(it) }?.toSet() ?: emptySet() + + internal val manifestProperties = configuration.get(KonanConfigKeys.MANIFEST_FILE)?.let { + File(it).loadProperties() + } + + internal val isInteropStubs: Boolean get() = manifestProperties?.getProperty("interop") == "true" +} + +fun CompilerConfiguration.report(priority: CompilerMessageSeverity, message: String) + = this.getNotNull(CLIConfigurationKeys.MESSAGE_COLLECTOR_KEY).report(priority, message) diff --git a/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/KonanConfigurationKeys.kt b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/KonanConfigurationKeys.kt new file mode 100644 index 00000000000..c4e68b64aaf --- /dev/null +++ b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/KonanConfigurationKeys.kt @@ -0,0 +1,149 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +package org.jetbrains.kotlin.backend.konan + +import org.jetbrains.kotlin.config.CompilerConfigurationKey +import org.jetbrains.kotlin.serialization.js.ModuleKind +import org.jetbrains.kotlin.konan.target.CompilerOutputKind + +class KonanConfigKeys { + companion object { + // Keep the list lexically sorted. + val CHECK_DEPENDENCIES: CompilerConfigurationKey + = CompilerConfigurationKey.create("check dependencies and download the missing ones") + val COMPATIBLE_COMPILER_VERSIONS: CompilerConfigurationKey> + = CompilerConfigurationKey.create("compatible compiler versions") + val DEBUG: CompilerConfigurationKey + = CompilerConfigurationKey.create("add debug information") + val DISABLE_FAKE_OVERRIDE_VALIDATOR: CompilerConfigurationKey + = CompilerConfigurationKey.create("disable fake override validator") + val DISABLED_PHASES: CompilerConfigurationKey> + = CompilerConfigurationKey.create("disable backend phases") + val BITCODE_EMBEDDING_MODE: CompilerConfigurationKey + = CompilerConfigurationKey.create("bitcode embedding mode") + val EMIT_LAZY_OBJC_HEADER_FILE: CompilerConfigurationKey = + CompilerConfigurationKey.create("output file to emit lazy Obj-C header") + val ENABLE_ASSERTIONS: CompilerConfigurationKey + = CompilerConfigurationKey.create("enable runtime assertions in generated code") + val ENABLED_PHASES: CompilerConfigurationKey> + = CompilerConfigurationKey.create("enable backend phases") + val ENTRY: CompilerConfigurationKey + = CompilerConfigurationKey.create("fully qualified main() name") + val EXPORTED_LIBRARIES: CompilerConfigurationKey> + = CompilerConfigurationKey.create>("libraries included into produced framework API") + val LIBRARIES_TO_CACHE: CompilerConfigurationKey> + = CompilerConfigurationKey.create>("paths to libraries that to be compiled to cache") + val LIBRARY_TO_ADD_TO_CACHE: CompilerConfigurationKey + = CompilerConfigurationKey.create("path to library that to be added to cache") + val CACHE_DIRECTORIES: CompilerConfigurationKey> + = CompilerConfigurationKey.create>("paths to directories containing caches") + val CACHED_LIBRARIES: CompilerConfigurationKey> + = CompilerConfigurationKey.create>("mapping from library paths to cache paths") + val FRAMEWORK_IMPORT_HEADERS: CompilerConfigurationKey> + = CompilerConfigurationKey.create>("headers imported to framework header") + val FRIEND_MODULES: CompilerConfigurationKey> + = CompilerConfigurationKey.create>("friend module paths") + val GENERATE_TEST_RUNNER: CompilerConfigurationKey + = CompilerConfigurationKey.create("generate test runner") + val INCLUDED_BINARY_FILES: CompilerConfigurationKey> + = CompilerConfigurationKey.create("included binary file paths") + val KONAN_HOME: CompilerConfigurationKey + = CompilerConfigurationKey.create("overridden compiler distribution path") + val LIBRARY_FILES: CompilerConfigurationKey> + = CompilerConfigurationKey.create("library file paths") + val LIBRARY_VERSION: CompilerConfigurationKey + = CompilerConfigurationKey.create("library version") + val LIGHT_DEBUG: CompilerConfigurationKey + = CompilerConfigurationKey.create("add light debug information") + val LINKER_ARGS: CompilerConfigurationKey> + = CompilerConfigurationKey.create("additional linker arguments") + val LIST_PHASES: CompilerConfigurationKey + = CompilerConfigurationKey.create("list backend phases") + val LIST_TARGETS: CompilerConfigurationKey + = CompilerConfigurationKey.create("list available targets") + val MANIFEST_FILE: CompilerConfigurationKey + = CompilerConfigurationKey.create("provide manifest addend file") + val MEMORY_MODEL: CompilerConfigurationKey + = CompilerConfigurationKey.create("memory model") + val META_INFO: CompilerConfigurationKey> + = CompilerConfigurationKey.create("generate metadata") + val METADATA_KLIB: CompilerConfigurationKey + = CompilerConfigurationKey.create("metadata klib") + val MODULE_KIND: CompilerConfigurationKey + = CompilerConfigurationKey.create("module kind") + val MODULE_NAME: CompilerConfigurationKey + = CompilerConfigurationKey.create("module name") + val NATIVE_LIBRARY_FILES: CompilerConfigurationKey> + = CompilerConfigurationKey.create("native library file paths") + val NODEFAULTLIBS: CompilerConfigurationKey + = CompilerConfigurationKey.create("don't link with the default libraries") + val NOENDORSEDLIBS: CompilerConfigurationKey + = CompilerConfigurationKey.create("don't link with the endorsed libraries") + val NOMAIN: CompilerConfigurationKey + = CompilerConfigurationKey.create("assume 'main' entry point to be provided by external libraries") + val NOSTDLIB: CompilerConfigurationKey + = CompilerConfigurationKey.create("don't link with stdlib") + val NOPACK: CompilerConfigurationKey + = CompilerConfigurationKey.create("don't the library into a klib file") + val OPTIMIZATION: CompilerConfigurationKey + = CompilerConfigurationKey.create("optimized compilation") + val OUTPUT: CompilerConfigurationKey + = CompilerConfigurationKey.create("program or library name") + val OVERRIDE_CLANG_OPTIONS: CompilerConfigurationKey> + = CompilerConfigurationKey.create("arguments for clang") + val ALLOCATION_MODE: CompilerConfigurationKey + = CompilerConfigurationKey.create("allocation mode") + val PRINT_BITCODE: CompilerConfigurationKey + = CompilerConfigurationKey.create("print bitcode") + val PRINT_DESCRIPTORS: CompilerConfigurationKey + = CompilerConfigurationKey.create("print descriptors") + val PRINT_IR: CompilerConfigurationKey + = CompilerConfigurationKey.create("print ir") + val PRINT_IR_WITH_DESCRIPTORS: CompilerConfigurationKey + = CompilerConfigurationKey.create("print ir with descriptors") + val PRINT_LOCATIONS: CompilerConfigurationKey + = CompilerConfigurationKey.create("print locations") + val PRODUCE: CompilerConfigurationKey + = CompilerConfigurationKey.create("compiler output kind") + val PURGE_USER_LIBS: CompilerConfigurationKey + = CompilerConfigurationKey.create("purge user-specified libs too") + val REPOSITORIES: CompilerConfigurationKey> + = CompilerConfigurationKey.create("library search path repositories") + val RUNTIME_FILE: CompilerConfigurationKey + = CompilerConfigurationKey.create("override default runtime file path") + val INCLUDED_LIBRARIES: CompilerConfigurationKey> + = CompilerConfigurationKey("klibs processed in the same manner as source files") + val SOURCE_MAP: CompilerConfigurationKey> + = CompilerConfigurationKey.create("generate source map") + val SHORT_MODULE_NAME: CompilerConfigurationKey + = CompilerConfigurationKey("short module name for IDE and export") + val STATIC_FRAMEWORK: CompilerConfigurationKey + = CompilerConfigurationKey.create("produce a static library for a framework") + val TARGET: CompilerConfigurationKey + = CompilerConfigurationKey.create("target we compile for") + val TEMPORARY_FILES_DIR: CompilerConfigurationKey + = CompilerConfigurationKey.create("directory for temporary files") + val VERIFY_BITCODE: CompilerConfigurationKey + = CompilerConfigurationKey.create("verify bitcode") + val VERIFY_COMPILER: CompilerConfigurationKey + = CompilerConfigurationKey.create("verify compiler") + val DEBUG_INFO_VERSION: CompilerConfigurationKey + = CompilerConfigurationKey.create("debug info format version") + val COVERAGE: CompilerConfigurationKey + = CompilerConfigurationKey.create("emit coverage info for sources") + val LIBRARIES_TO_COVER: CompilerConfigurationKey> + = CompilerConfigurationKey.create("libraries that should be covered") + val PROFRAW_PATH: CompilerConfigurationKey + = CompilerConfigurationKey.create("path to *.profraw coverage output") + val OBJC_GENERICS: CompilerConfigurationKey + = CompilerConfigurationKey.create("write objc header with generics support") + val DEBUG_PREFIX_MAP: CompilerConfigurationKey> + = CompilerConfigurationKey.create("remap file source paths in debug info") + val PRE_LINK_CACHES: CompilerConfigurationKey + = CompilerConfigurationKey.create("perform compiler caches pre-link") + } +} + diff --git a/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/KonanDriver.kt b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/KonanDriver.kt new file mode 100644 index 00000000000..aab93ee9f87 --- /dev/null +++ b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/KonanDriver.kt @@ -0,0 +1,34 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +package org.jetbrains.kotlin.backend.konan + +import org.jetbrains.kotlin.backend.common.phaser.CompilerPhase +import org.jetbrains.kotlin.backend.common.phaser.invokeToplevel +import org.jetbrains.kotlin.cli.jvm.compiler.KotlinCoreEnvironment +import org.jetbrains.kotlin.utils.addToStdlib.cast + +fun runTopLevelPhases(konanConfig: KonanConfig, environment: KotlinCoreEnvironment) { + + val config = konanConfig.configuration + + val targets = konanConfig.targetManager + if (config.get(KonanConfigKeys.LIST_TARGETS) ?: false) { + targets.list() + } + + val context = Context(konanConfig) + context.environment = environment + context.phaseConfig.konanPhasesConfig(konanConfig) // TODO: Wrong place to call it + + if (konanConfig.infoArgsOnly) return + + try { + toplevelPhase.cast>().invokeToplevel(context.phaseConfig, context, Unit) + } finally { + context.disposeLlvm() + } +} + diff --git a/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/KonanFqNames.kt b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/KonanFqNames.kt new file mode 100644 index 00000000000..0ec960f9c12 --- /dev/null +++ b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/KonanFqNames.kt @@ -0,0 +1,34 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +package org.jetbrains.kotlin.backend.konan + +import org.jetbrains.kotlin.name.FqName +import org.jetbrains.kotlin.name.FqNameUnsafe +import org.jetbrains.kotlin.name.Name + +internal const val NATIVE_PTR_NAME = "NativePtr" +internal const val NON_NULL_NATIVE_PTR_NAME = "NonNullNativePtr" +internal const val VECTOR128 = "Vector128" + +object KonanFqNames { + val function = FqName("kotlin.Function") + val kFunction = FqName("kotlin.reflect.KFunction") + val packageName = FqName("kotlin.native") + val internalPackageName = FqName("kotlin.native.internal") + val nativePtr = internalPackageName.child(Name.identifier(NATIVE_PTR_NAME)).toUnsafe() + val nonNullNativePtr = internalPackageName.child(Name.identifier(NON_NULL_NATIVE_PTR_NAME)).toUnsafe() + val Vector128 = packageName.child(Name.identifier(VECTOR128)) + val throws = FqName("kotlin.Throws") + val cancellationException = FqName("kotlin.coroutines.cancellation.CancellationException") + val threadLocal = FqName("kotlin.native.concurrent.ThreadLocal") + val sharedImmutable = FqName("kotlin.native.concurrent.SharedImmutable") + val frozen = FqName("kotlin.native.internal.Frozen") + val leakDetectorCandidate = FqName("kotlin.native.internal.LeakDetectorCandidate") + val canBePrecreated = FqName("kotlin.native.internal.CanBePrecreated") + val typedIntrinsic = FqName("kotlin.native.internal.TypedIntrinsic") + val objCMethod = FqName("kotlinx.cinterop.ObjCMethod") + val hasFinalizer = FqName("kotlin.native.internal.HasFinalizer") +} diff --git a/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/KonanLibrariesResolveSupport.kt b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/KonanLibrariesResolveSupport.kt new file mode 100644 index 00000000000..d2f62892442 --- /dev/null +++ b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/KonanLibrariesResolveSupport.kt @@ -0,0 +1,90 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +package org.jetbrains.kotlin.backend.konan + +import org.jetbrains.kotlin.cli.common.CLIConfigurationKeys +import org.jetbrains.kotlin.cli.common.messages.CompilerMessageSeverity +import org.jetbrains.kotlin.cli.common.messages.GroupingMessageCollector +import org.jetbrains.kotlin.config.CompilerConfiguration +import org.jetbrains.kotlin.konan.CompilerVersion +import org.jetbrains.kotlin.konan.file.File +import org.jetbrains.kotlin.konan.library.defaultResolver +import org.jetbrains.kotlin.konan.parseCompilerVersion +import org.jetbrains.kotlin.konan.target.Distribution +import org.jetbrains.kotlin.konan.target.KonanTarget +import org.jetbrains.kotlin.library.UnresolvedLibrary +import org.jetbrains.kotlin.library.resolver.impl.libraryResolver +import org.jetbrains.kotlin.library.toUnresolvedLibraries +import org.jetbrains.kotlin.util.Logger +import kotlin.system.exitProcess + +class KonanLibrariesResolveSupport( + configuration: CompilerConfiguration, + target: KonanTarget, + distribution: Distribution +) { + private val includedLibraryFiles = + configuration.getList(KonanConfigKeys.INCLUDED_LIBRARIES).map { File(it) } + + private val librariesToCacheFiles = + configuration.getList(KonanConfigKeys.LIBRARIES_TO_CACHE).map { File(it) } + + configuration.get(KonanConfigKeys.LIBRARY_TO_ADD_TO_CACHE).let { + if (it.isNullOrEmpty()) emptyList() else listOf(File(it)) + } + + private val libraryNames = configuration.getList(KonanConfigKeys.LIBRARY_FILES) + + private val unresolvedLibraries = libraryNames.toUnresolvedLibraries + + private val repositories = configuration.getList(KonanConfigKeys.REPOSITORIES) + private val resolverLogger = + object : Logger { + private val collector = configuration.getNotNull(CLIConfigurationKeys.MESSAGE_COLLECTOR_KEY) + override fun warning(message: String)= collector.report(CompilerMessageSeverity.STRONG_WARNING, message) + override fun error(message: String) = collector.report(CompilerMessageSeverity.ERROR, message) + override fun log(message: String) = collector.report(CompilerMessageSeverity.LOGGING, message) + override fun fatal(message: String): Nothing { + collector.report(CompilerMessageSeverity.ERROR, message) + (collector as? GroupingMessageCollector)?.flush() + exitProcess(1) + } + } + + private val compatibleCompilerVersions: List = + configuration.getList(KonanConfigKeys.COMPATIBLE_COMPILER_VERSIONS).map { it.parseCompilerVersion() } + + private val resolver = defaultResolver( + repositories, + libraryNames.filter { it.contains(File.separator) }, + target, + distribution, + compatibleCompilerVersions, + resolverLogger + ).libraryResolver() + + // We pass included libraries by absolute paths to avoid repository-based resolution for them. + // Strictly speaking such "direct" libraries should be specially handled by the resolver, not by KonanConfig. + // But currently the resolver is in the middle of a complex refactoring so it was decided to avoid changes in its logic. + // TODO: Handle included libraries in KonanLibraryResolver when it's refactored and moved into the big Kotlin repo. + internal val resolvedLibraries = run { + val additionalLibraryFiles = includedLibraryFiles + librariesToCacheFiles + resolver.resolveWithDependencies( + unresolvedLibraries + additionalLibraryFiles.map { UnresolvedLibrary(it.absolutePath, null) }, + noStdLib = configuration.getBoolean(KonanConfigKeys.NOSTDLIB), + noDefaultLibs = configuration.getBoolean(KonanConfigKeys.NODEFAULTLIBS), + noEndorsedLibs = configuration.getBoolean(KonanConfigKeys.NOENDORSEDLIBS) + ) + } + + internal val exportedLibraries = + getExportedLibraries(configuration, resolvedLibraries, resolver.searchPathResolver, report = true) + + internal val coveredLibraries = + getCoveredLibraries(configuration, resolvedLibraries, resolver.searchPathResolver) + + internal val includedLibraries = + getIncludedLibraries(includedLibraryFiles, configuration, resolvedLibraries) +} \ No newline at end of file diff --git a/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/KonanLoweringPhases.kt b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/KonanLoweringPhases.kt new file mode 100644 index 00000000000..455663de5a4 --- /dev/null +++ b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/KonanLoweringPhases.kt @@ -0,0 +1,375 @@ +package org.jetbrains.kotlin.backend.konan + +import org.jetbrains.kotlin.backend.common.* +import org.jetbrains.kotlin.backend.common.lower.* +import org.jetbrains.kotlin.backend.common.lower.inline.FunctionInlining +import org.jetbrains.kotlin.backend.common.lower.inline.LocalClassesExtractionFromInlineFunctionsLowering +import org.jetbrains.kotlin.backend.common.lower.inline.LocalClassesInInlineFunctionsLowering +import org.jetbrains.kotlin.backend.common.lower.inline.LocalClassesInInlineLambdasLowering +import org.jetbrains.kotlin.backend.common.lower.loops.ForLoopsLowering +import org.jetbrains.kotlin.backend.common.lower.optimizations.FoldConstantLowering +import org.jetbrains.kotlin.backend.common.phaser.* +import org.jetbrains.kotlin.backend.konan.lower.* +import org.jetbrains.kotlin.backend.konan.lower.FinallyBlocksLowering +import org.jetbrains.kotlin.backend.konan.lower.InitializersLowering +import org.jetbrains.kotlin.backend.konan.lower.StringConcatenationLowering +import org.jetbrains.kotlin.ir.declarations.IrFile +import org.jetbrains.kotlin.ir.declarations.IrModuleFragment + +private val validateAll = false +private val filePhaseActions = if (validateAll) setOf(defaultDumper, ::fileValidationCallback) else setOf(defaultDumper) +private val modulePhaseActions = if (validateAll) setOf(defaultDumper, ::moduleValidationCallback) else setOf(defaultDumper) + +private fun makeKonanFileLoweringPhase( + lowering: (Context) -> FileLoweringPass, + name: String, + description: String, + prerequisite: Set> = emptySet() +) = makeIrFilePhase(lowering, name, description, prerequisite, actions = filePhaseActions) + +private fun makeKonanModuleLoweringPhase( + lowering: (Context) -> FileLoweringPass, + name: String, + description: String, + prerequisite: Set> = emptySet() +) = makeIrModulePhase(lowering, name, description, prerequisite, actions = modulePhaseActions) + +internal fun makeKonanFileOpPhase( + op: (Context, IrFile) -> Unit, + name: String, + description: String, + prerequisite: Set> = emptySet() +) = NamedCompilerPhase( + name, description, prerequisite, nlevels = 0, + lower = object : SameTypeCompilerPhase { + override fun invoke(phaseConfig: PhaseConfig, phaserState: PhaserState, context: Context, input: IrFile): IrFile { + op(context, input) + return input + } + }, + actions = filePhaseActions +) + +internal fun makeKonanModuleOpPhase( + op: (Context, IrModuleFragment) -> Unit, + name: String, + description: String, + prerequisite: Set> = emptySet() +) = NamedCompilerPhase( + name, description, prerequisite, nlevels = 0, + lower = object : SameTypeCompilerPhase { + override fun invoke(phaseConfig: PhaseConfig, phaserState: PhaserState, context: Context, input: IrModuleFragment): IrModuleFragment { + op(context, input) + return input + } + }, + actions = modulePhaseActions +) + +internal val specialBackendChecksPhase = konanUnitPhase( + op = { irModule!!.files.forEach { SpecialBackendChecksTraversal(this).lower(it) } }, + name = "SpecialBackendChecks", + description = "Special backend checks" +) + +internal val removeExpectDeclarationsPhase = makeKonanModuleLoweringPhase( + ::ExpectDeclarationsRemoving, + name = "RemoveExpectDeclarations", + description = "Expect declarations removing" +) + +internal val stripTypeAliasDeclarationsPhase = makeKonanModuleLoweringPhase( + { StripTypeAliasDeclarationsLowering() }, + name = "StripTypeAliasDeclarations", + description = "Strip typealias declarations" +) + +internal val lowerBeforeInlinePhase = makeKonanModuleLoweringPhase( + ::PreInlineLowering, + name = "LowerBeforeInline", + description = "Special operations processing before inlining" +) + +internal val arrayConstructorPhase = makeKonanModuleLoweringPhase( + ::ArrayConstructorLowering, + name = "ArrayConstructor", + description = "Transform `Array(size) { index -> value }` into a loop" +) + +internal val lateinitPhase = makeKonanModuleOpPhase( + { context, irModule -> + NullableFieldsForLateinitCreationLowering(context).lower(irModule) + NullableFieldsDeclarationLowering(context).lower(irModule) + LateinitUsageLowering(context).lower(irModule) + }, + name = "Lateinit", + description = "Lateinit properties lowering" +) + +internal val sharedVariablesPhase = makeKonanModuleLoweringPhase( + ::SharedVariablesLowering, + name = "SharedVariables", + description = "Shared variable lowering", + prerequisite = setOf(lateinitPhase) +) + +internal val extractLocalClassesFromInlineBodies = NamedCompilerPhase( + lower = object : SameTypeCompilerPhase { + override fun invoke(phaseConfig: PhaseConfig, phaserState: PhaserState, context: Context, input: IrModuleFragment): IrModuleFragment { + LocalClassesInInlineLambdasLowering(context).run { + input.files.forEach { lower(it) } + } + LocalClassesInInlineFunctionsLowering(context).run { + input.files.forEach { lower(it) } + } + LocalClassesExtractionFromInlineFunctionsLowering(context).run { + input.files.forEach { lower(it) } + } + return input + } + }, + name = "ExtractLocalClassesFromInlineBodies", + description = "Extraction of local classes from inline bodies", + prerequisite = setOf(sharedVariablesPhase), + nlevels = 0, + actions = modulePhaseActions +) + +internal val inlinePhase = NamedCompilerPhase( + lower = object : SameTypeCompilerPhase { + override fun invoke(phaseConfig: PhaseConfig, phaserState: PhaserState, context: Context, input: IrModuleFragment): IrModuleFragment { + FunctionInlining(context, NativeInlineFunctionResolver(context)).run { + input.files.forEach { lower(it) } + } + return input + } + }, + name = "Inline", + description = "Functions inlining", + prerequisite = setOf(lowerBeforeInlinePhase, arrayConstructorPhase, extractLocalClassesFromInlineBodies), + nlevels = 0, + actions = modulePhaseActions +) + +internal val lowerAfterInlinePhase = makeKonanModuleOpPhase( + { context, irModule -> + irModule.files.forEach(PostInlineLowering(context)::lower) + // TODO: Seems like this should be deleted in PsiToIR. + irModule.files.forEach(ContractsDslRemover(context)::lower) + }, + name = "LowerAfterInline", + description = "Special operations processing after inlining" +) + +/* IrFile phases */ + +// TODO make all lambda-related stuff work with IrFunctionExpression and drop this phase (see kotlin: dd3f8ecaacd) +internal val provisionalFunctionExpressionPhase = makeKonanModuleLoweringPhase( + { ProvisionalFunctionExpressionLowering() }, + name = "FunctionExpression-before-inliner", + description = "Transform IrFunctionExpression to a local function reference" +) + +internal val flattenStringConcatenationPhase = makeKonanFileLoweringPhase( + ::FlattenStringConcatenationLowering, + name = "FlattenStringConcatenationLowering", + description = "Flatten nested string concatenation expressions into a single IrStringConcatenation" +) + +internal val stringConcatenationPhase = makeKonanFileLoweringPhase( + ::StringConcatenationLowering, + name = "StringConcatenation", + description = "String concatenation lowering" +) + +internal val kotlinNothingValueExceptionPhase = makeKonanFileLoweringPhase( + ::KotlinNothingValueExceptionLowering, + name = "KotlinNothingValueException", + description = "Throw proper exception for calls returning value of type 'kotlin.Nothing'" +) + +internal val enumConstructorsPhase = makeKonanFileLoweringPhase( + ::EnumConstructorsLowering, + name = "EnumConstructors", + description = "Enum constructors lowering" +) + +internal val initializersPhase = makeKonanFileLoweringPhase( + ::InitializersLowering, + name = "Initializers", + description = "Initializers lowering", + prerequisite = setOf(enumConstructorsPhase) +) + +internal val localFunctionsPhase = makeKonanFileOpPhase( + op = { context, irFile -> + LocalDelegatedPropertiesLowering().lower(irFile) + LocalDeclarationsLowering(context).lower(irFile) + LocalClassPopupLowering(context).lower(irFile) + }, + name = "LocalFunctions", + description = "Local function lowering", + prerequisite = setOf(sharedVariablesPhase) +) + +internal val tailrecPhase = makeKonanFileLoweringPhase( + ::TailrecLowering, + name = "Tailrec", + description = "Tailrec lowering", + prerequisite = setOf(localFunctionsPhase) +) + +internal val defaultParameterExtentPhase = makeKonanFileOpPhase( + { context, irFile -> + KonanDefaultArgumentStubGenerator(context).lower(irFile) + DefaultParameterCleaner(context, replaceDefaultValuesWithStubs = true).lower(irFile) + KonanDefaultParameterInjector(context).lower(irFile) + }, + name = "DefaultParameterExtent", + description = "Default parameter extent lowering", + prerequisite = setOf(tailrecPhase, enumConstructorsPhase) +) + +internal val innerClassPhase = makeKonanFileLoweringPhase( + ::InnerClassLowering, + name = "InnerClasses", + description = "Inner classes lowering", + prerequisite = setOf(defaultParameterExtentPhase) +) + +internal val rangeContainsLoweringPhase = makeKonanFileLoweringPhase( + ::RangeContainsLowering, + name = "RangeContains", + description = "Optimizes calls to contains() for ClosedRanges" +) + +internal val forLoopsPhase = makeKonanFileLoweringPhase( + ::ForLoopsLowering, + name = "ForLoops", + description = "For loops lowering" +) + +internal val dataClassesPhase = makeKonanFileLoweringPhase( + ::DataClassOperatorsLowering, + name = "DataClasses", + description = "Data classes lowering" +) + +internal val finallyBlocksPhase = makeKonanFileLoweringPhase( + ::FinallyBlocksLowering, + name = "FinallyBlocks", + description = "Finally blocks lowering", + prerequisite = setOf(initializersPhase, localFunctionsPhase, tailrecPhase) +) + +internal val testProcessorPhase = makeKonanFileOpPhase( + { context, irFile -> TestProcessor(context).process(irFile) }, + name = "TestProcessor", + description = "Unit test processor" +) + +internal val delegationPhase = makeKonanFileLoweringPhase( + ::PropertyDelegationLowering, + name = "Delegation", + description = "Delegation lowering" +) + +internal val functionReferencePhase = makeKonanFileLoweringPhase( + ::FunctionReferenceLowering, + name = "FunctionReference", + description = "Function references lowering", + prerequisite = setOf(delegationPhase, localFunctionsPhase) // TODO: make weak dependency on `testProcessorPhase` +) + +internal val enumClassPhase = makeKonanFileOpPhase( + { context, irFile -> EnumClassLowering(context).run(irFile) }, + name = "Enums", + description = "Enum classes lowering", + prerequisite = setOf(enumConstructorsPhase, functionReferencePhase) // TODO: make weak dependency on `testProcessorPhase` +) + +internal val singleAbstractMethodPhase = makeKonanFileLoweringPhase( + ::NativeSingleAbstractMethodLowering, + name = "SingleAbstractMethod", + description = "Replace SAM conversions with instances of interface-implementing classes", + prerequisite = setOf(functionReferencePhase) +) + +internal val builtinOperatorPhase = makeKonanFileLoweringPhase( + ::BuiltinOperatorLowering, + name = "BuiltinOperators", + description = "BuiltIn operators lowering", + prerequisite = setOf(defaultParameterExtentPhase, singleAbstractMethodPhase) +) + +internal val interopPhase = makeKonanFileLoweringPhase( + ::InteropLowering, + name = "Interop", + description = "Interop lowering", + prerequisite = setOf(inlinePhase, localFunctionsPhase, functionReferencePhase) +) + +internal val varargPhase = makeKonanFileLoweringPhase( + ::VarargInjectionLowering, + name = "Vararg", + description = "Vararg lowering", + prerequisite = setOf(functionReferencePhase, defaultParameterExtentPhase, interopPhase) +) + +internal val compileTimeEvaluatePhase = makeKonanFileLoweringPhase( + ::CompileTimeEvaluateLowering, + name = "CompileTimeEvaluate", + description = "Compile time evaluation lowering", + prerequisite = setOf(varargPhase) +) + +internal val coroutinesPhase = makeKonanFileLoweringPhase( + ::NativeSuspendFunctionsLowering, + name = "Coroutines", + description = "Coroutines lowering", + prerequisite = setOf(localFunctionsPhase, finallyBlocksPhase, kotlinNothingValueExceptionPhase) +) + +internal val typeOperatorPhase = makeKonanFileLoweringPhase( + ::TypeOperatorLowering, + name = "TypeOperators", + description = "Type operators lowering", + prerequisite = setOf(coroutinesPhase) +) + +internal val bridgesPhase = makeKonanFileOpPhase( + { context, irFile -> + BridgesBuilding(context).runOnFilePostfix(irFile) + WorkersBridgesBuilding(context).lower(irFile) + }, + name = "Bridges", + description = "Bridges building", + prerequisite = setOf(coroutinesPhase) +) + +internal val autoboxPhase = makeKonanFileLoweringPhase( + ::Autoboxing, + name = "Autobox", + description = "Autoboxing of primitive types", + prerequisite = setOf(bridgesPhase, coroutinesPhase) +) + +internal val returnsInsertionPhase = makeKonanFileLoweringPhase( + ::ReturnsInsertionLowering, + name = "ReturnsInsertion", + description = "Returns insertion for Unit functions", + prerequisite = setOf(autoboxPhase, coroutinesPhase, enumClassPhase) +) + +internal val ifNullExpressionsFusionPhase = makeKonanFileLoweringPhase( + ::IfNullExpressionsFusionLowering, + name = "IfNullExpressionsFusionLowering", + description = "Simplify '?.' and '?:' operator chains" +) + +internal val foldConstantLoweringPhase = makeKonanFileOpPhase( + { context, irFile -> FoldConstantLowering(context).lower(irFile) }, + name = "FoldConstantLowering", + description = "Constant Folding", + prerequisite = setOf(flattenStringConcatenationPhase) +) \ No newline at end of file diff --git a/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/KonanReflectionTypes.kt b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/KonanReflectionTypes.kt new file mode 100644 index 00000000000..18de0410495 --- /dev/null +++ b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/KonanReflectionTypes.kt @@ -0,0 +1,63 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +package org.jetbrains.kotlin.backend.konan + + +import org.jetbrains.kotlin.builtins.StandardNames.KOTLIN_REFLECT_FQ_NAME +import org.jetbrains.kotlin.descriptors.ClassDescriptor +import org.jetbrains.kotlin.descriptors.ModuleDescriptor +import org.jetbrains.kotlin.incremental.components.NoLookupLocation +import org.jetbrains.kotlin.name.FqName +import org.jetbrains.kotlin.name.Name +import org.jetbrains.kotlin.resolve.scopes.MemberScope +import kotlin.reflect.KProperty + +class KonanReflectionTypes(module: ModuleDescriptor, internalPackage: FqName) { + + private val kotlinReflectScope: MemberScope by lazy(LazyThreadSafetyMode.PUBLICATION) { + module.getPackage(KOTLIN_REFLECT_FQ_NAME).memberScope + } + + private val internalScope: MemberScope by lazy(LazyThreadSafetyMode.PUBLICATION) { + module.getPackage(internalPackage).memberScope + } + + private fun find(memberScope: MemberScope, className: String): ClassDescriptor { + val name = Name.identifier(className) + return memberScope.getContributedClassifier(name, NoLookupLocation.FROM_REFLECTION) as ClassDescriptor + } + + private class ClassLookup(val memberScope: MemberScope) { + operator fun getValue(types: KonanReflectionTypes, property: KProperty<*>): ClassDescriptor { + return types.find(memberScope, property.name.capitalize()) + } + } + + fun getKFunction(n: Int): ClassDescriptor = find(kotlinReflectScope, "KFunction$n") + + fun getKSuspendFunction(n: Int): ClassDescriptor = find(kotlinReflectScope, "KSuspendFunction$n") + + val kProperty0: ClassDescriptor by ClassLookup(kotlinReflectScope) + val kMutableProperty0: ClassDescriptor by ClassLookup(kotlinReflectScope) + val kMutableProperty1: ClassDescriptor by ClassLookup(kotlinReflectScope) + val kMutableProperty2: ClassDescriptor by ClassLookup(kotlinReflectScope) + val kTypeProjection: ClassDescriptor by ClassLookup(kotlinReflectScope) + val kType: ClassDescriptor by ClassLookup(kotlinReflectScope) + val kVariance: ClassDescriptor by ClassLookup(kotlinReflectScope) + + val kFunctionImpl: ClassDescriptor by ClassLookup(internalScope) + val kSuspendFunctionImpl: ClassDescriptor by ClassLookup(internalScope) + val kProperty0Impl: ClassDescriptor by ClassLookup(internalScope) + val kProperty1Impl: ClassDescriptor by ClassLookup(internalScope) + val kProperty2Impl: ClassDescriptor by ClassLookup(internalScope) + val kMutableProperty0Impl: ClassDescriptor by ClassLookup(internalScope) + val kMutableProperty1Impl: ClassDescriptor by ClassLookup(internalScope) + val kMutableProperty2Impl: ClassDescriptor by ClassLookup(internalScope) + val kLocalDelegatedPropertyImpl: ClassDescriptor by ClassLookup(internalScope) + val kLocalDelegatedMutablePropertyImpl: ClassDescriptor by ClassLookup(internalScope) + + val typeOf = kotlinReflectScope.getContributedFunctions(Name.identifier("typeOf"), NoLookupLocation.FROM_REFLECTION).single() +} diff --git a/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/Linker.kt b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/Linker.kt new file mode 100644 index 00000000000..1f379002591 --- /dev/null +++ b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/Linker.kt @@ -0,0 +1,241 @@ +package org.jetbrains.kotlin.backend.konan + +import org.jetbrains.kotlin.konan.KonanExternalToolFailure +import org.jetbrains.kotlin.konan.exec.Command +import org.jetbrains.kotlin.konan.file.File +import org.jetbrains.kotlin.konan.target.CompilerOutputKind +import org.jetbrains.kotlin.konan.target.Family +import org.jetbrains.kotlin.konan.target.LinkerOutputKind +import org.jetbrains.kotlin.konan.library.KonanLibrary +import org.jetbrains.kotlin.konan.target.supportsMimallocAllocator +import org.jetbrains.kotlin.library.resolver.TopologicalLibraryOrder +import org.jetbrains.kotlin.library.uniqueName +import org.jetbrains.kotlin.utils.addToStdlib.cast + +internal fun determineLinkerOutput(context: Context): LinkerOutputKind = + when (context.config.produce) { + CompilerOutputKind.FRAMEWORK -> { + val staticFramework = context.config.produceStaticFramework + if (staticFramework) LinkerOutputKind.STATIC_LIBRARY else LinkerOutputKind.DYNAMIC_LIBRARY + } + CompilerOutputKind.DYNAMIC_CACHE, + CompilerOutputKind.DYNAMIC -> LinkerOutputKind.DYNAMIC_LIBRARY + CompilerOutputKind.STATIC_CACHE, + CompilerOutputKind.STATIC -> LinkerOutputKind.STATIC_LIBRARY + CompilerOutputKind.PROGRAM -> LinkerOutputKind.EXECUTABLE + else -> TODO("${context.config.produce} should not reach native linker stage") + } + +// TODO: We have a Linker.kt file in the shared module. +internal class Linker(val context: Context) { + + private val platform = context.config.platform + private val config = context.config.configuration + private val linkerOutput = determineLinkerOutput(context) + private val linker = platform.linker + private val target = context.config.target + private val optimize = context.shouldOptimize() + private val debug = context.config.debug || context.config.lightDebug + + fun link(objectFiles: List) { + val nativeDependencies = context.llvm.nativeDependenciesToLink + + val includedBinariesLibraries = if (context.config.produce.isCache) { + context.config.librariesToCache + } else { + nativeDependencies.filterNot { context.config.cachedLibraries.isLibraryCached(it) } + } + val includedBinaries = includedBinariesLibraries.map { (it as? KonanLibrary)?.includedPaths.orEmpty() }.flatten() + + val libraryProvidedLinkerFlags = context.llvm.allNativeDependencies.map { it.linkerOpts }.flatten() + + if (context.config.produce.isCache) { + context.config.outputFiles.tempCacheDirectory!!.mkdirs() + saveAdditionalInfoForCache() + } + + runLinker(objectFiles, includedBinaries, libraryProvidedLinkerFlags) + + renameOutput() + } + + private fun saveAdditionalInfoForCache() { + saveCacheBitcodeDependencies() + } + + private fun saveCacheBitcodeDependencies() { + val outputFiles = context.config.outputFiles + val bitcodeDependenciesFile = File(outputFiles.bitcodeDependenciesFile!!) + val bitcodeDependencies = context.config.resolvedLibraries + .getFullList(TopologicalLibraryOrder) + .filter { + require(it is KonanLibrary) + context.llvmImports.bitcodeIsUsed(it) + && it !in context.config.cacheSupport.librariesToCache // Skip loops. + }.cast>() + bitcodeDependenciesFile.writeLines(bitcodeDependencies.map { it.uniqueName }) + } + + private fun renameOutput() { + if (context.config.produce.isCache) { + val outputFiles = context.config.outputFiles + // For caches the output file is a directory. It might be created by someone else, + // We have to delete it in order to the next renaming operation to succeed. + java.io.File(outputFiles.mainFile).delete() + if (!java.io.File(outputFiles.tempCacheDirectory!!.absolutePath).renameTo(java.io.File(outputFiles.mainFile))) + outputFiles.tempCacheDirectory.deleteRecursively() + } + } + + private fun asLinkerArgs(args: List): List { + if (linker.useCompilerDriverAsLinker) { + return args + } + + val result = mutableListOf() + for (arg in args) { + // If user passes compiler arguments to us - transform them to linker ones. + if (arg.startsWith("-Wl,")) { + result.addAll(arg.substring(4).split(',')) + } else { + result.add(arg) + } + } + return result + } + + private fun runLinker(objectFiles: List, + includedBinaries: List, + libraryProvidedLinkerFlags: List): ExecutableFile? { + val additionalLinkerArgs: List + val executable: String + + if (context.config.produce != CompilerOutputKind.FRAMEWORK) { + additionalLinkerArgs = if (target.family.isAppleFamily) { + when (context.config.produce) { + CompilerOutputKind.DYNAMIC_CACHE -> + listOf("-install_name", context.config.outputFiles.mainFile) + else -> listOf("-dead_strip") + } + } else { + emptyList() + } + executable = context.config.outputFiles.nativeBinaryFile + } else { + val framework = File(context.config.outputFile) + val dylibName = framework.name.removeSuffix(".framework") + val dylibRelativePath = when (target.family) { + Family.IOS, + Family.TVOS, + Family.WATCHOS -> dylibName + Family.OSX -> "Versions/A/$dylibName" + else -> error(target) + } + additionalLinkerArgs = listOf("-dead_strip", "-install_name", "@rpath/${framework.name}/$dylibRelativePath") + val dylibPath = framework.child(dylibRelativePath) + dylibPath.parentFile.mkdirs() + executable = dylibPath.absolutePath + } + + val needsProfileLibrary = context.coverage.enabled + val mimallocEnabled = config.get(KonanConfigKeys.ALLOCATION_MODE) == "mimalloc" && + target.supportsMimallocAllocator() + + val linkerInput = determineLinkerInput(objectFiles, linkerOutput) + try { + File(executable).delete() + val linkerArgs = asLinkerArgs(config.getNotNull(KonanConfigKeys.LINKER_ARGS)) + + BitcodeEmbedding.getLinkerOptions(context.config) + + linkerInput.caches.dynamic + + libraryProvidedLinkerFlags + additionalLinkerArgs + val finalOutputCommands = linker.finalLinkCommands( + objectFiles = linkerInput.objectFiles, + executable = executable, + libraries = linker.linkStaticLibraries(includedBinaries) + linkerInput.caches.static, + linkerArgs = linkerArgs, + optimize = optimize, + debug = debug, + kind = linkerOutput, + outputDsymBundle = context.config.outputFiles.symbolicInfoFile, + needsProfileLibrary = needsProfileLibrary, + mimallocEnabled = mimallocEnabled) + (linkerInput.preLinkCommands + finalOutputCommands).forEach { + it.logWith(context::log) + it.execute() + } + } catch (e: KonanExternalToolFailure) { + val extraUserInfo = + if (linkerInput.cachingInvolved) + """ + Please try to disable compiler caches and rerun the build. To disable compiler caches, add the following line to the gradle.properties file in the project's root directory: + + kotlin.native.cacheKind=none + + Also, consider filing an issue with full Gradle log here: https://kotl.in/issue + """.trimIndent() + else "" + context.reportCompilationError("${e.toolName} invocation reported errors\n$extraUserInfo\n${e.message}") + } + return executable + } + + private fun shouldPerformPreLink(caches: CachesToLink, linkerOutputKind: LinkerOutputKind): Boolean { + // Pre-link is only useful when producing static library. Otherwise its just a waste of time. + val isStaticLibrary = linkerOutputKind == LinkerOutputKind.STATIC_LIBRARY && + context.config.produce.isFinalBinary + val enabled = context.config.cacheSupport.preLinkCaches + val nonEmptyCaches = caches.static.isNotEmpty() + return isStaticLibrary && enabled && nonEmptyCaches + } + + private fun determineLinkerInput(objectFiles: List, linkerOutputKind: LinkerOutputKind): LinkerInput { + val caches = determineCachesToLink(context) + // Since we have several linker stages that involve caching, + // we should detect cache usage early to report errors correctly. + val cachingInvolved = caches.static.isNotEmpty() || caches.dynamic.isNotEmpty() + return when { + context.config.produce == CompilerOutputKind.STATIC_CACHE -> { + // Do not link static cache dependencies. + LinkerInput(objectFiles, CachesToLink(emptyList(), caches.dynamic), emptyList(), cachingInvolved) + } + shouldPerformPreLink(caches, linkerOutputKind) -> { + val preLinkResult = context.config.tempFiles.create("withStaticCaches", ".o").absolutePath + val preLinkCommands = linker.preLinkCommands(objectFiles + caches.static, preLinkResult) + LinkerInput(listOf(preLinkResult), CachesToLink(emptyList(), caches.dynamic), preLinkCommands, cachingInvolved) + } + else -> LinkerInput(objectFiles, caches, emptyList(), cachingInvolved) + } + } +} + +private class LinkerInput( + val objectFiles: List, + val caches: CachesToLink, + val preLinkCommands: List, + val cachingInvolved: Boolean +) + +private class CachesToLink(val static: List, val dynamic: List) + +private fun determineCachesToLink(context: Context): CachesToLink { + val staticCaches = mutableListOf() + val dynamicCaches = mutableListOf() + + context.llvm.allCachedBitcodeDependencies.forEach { library -> + val currentBinaryContainsLibrary = context.llvmModuleSpecification.containsLibrary(library) + val cache = context.config.cachedLibraries.getLibraryCache(library) + ?: error("Library $library is expected to be cached") + + // Consistency check. Generally guaranteed by implementation. + if (currentBinaryContainsLibrary) + error("Library ${library.libraryName} is found in both cache and current binary") + + val list = when (cache.kind) { + CachedLibraries.Cache.Kind.DYNAMIC -> dynamicCaches + CachedLibraries.Cache.Kind.STATIC -> staticCaches + } + + list += cache.path + } + return CachesToLink(static = staticCaches, dynamic = dynamicCaches) +} diff --git a/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/LlvmModuleSpecification.kt b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/LlvmModuleSpecification.kt new file mode 100644 index 00000000000..1aaf71d5176 --- /dev/null +++ b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/LlvmModuleSpecification.kt @@ -0,0 +1,24 @@ +/* + * Copyright 2010-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +package org.jetbrains.kotlin.backend.konan + +import org.jetbrains.kotlin.descriptors.ModuleDescriptor +import org.jetbrains.kotlin.ir.declarations.IrDeclaration +import org.jetbrains.kotlin.ir.declarations.IrModuleFragment +import org.jetbrains.kotlin.library.KotlinLibrary + +/** + * Defines what LLVM module should consist of. + */ +interface LlvmModuleSpecification { + val isFinal: Boolean + fun importsKotlinDeclarationsFromOtherObjectFiles(): Boolean + fun importsKotlinDeclarationsFromOtherSharedLibraries(): Boolean + fun containsLibrary(library: KotlinLibrary): Boolean + fun containsModule(module: ModuleDescriptor): Boolean + fun containsModule(module: IrModuleFragment): Boolean + fun containsDeclaration(declaration: IrDeclaration): Boolean +} diff --git a/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/LlvmModuleSpecificationImpl.kt b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/LlvmModuleSpecificationImpl.kt new file mode 100644 index 00000000000..5e3ce5256ca --- /dev/null +++ b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/LlvmModuleSpecificationImpl.kt @@ -0,0 +1,46 @@ +/* + * Copyright 2010-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +package org.jetbrains.kotlin.backend.konan + +import org.jetbrains.kotlin.backend.konan.descriptors.konanLibrary +import org.jetbrains.kotlin.descriptors.ModuleDescriptor +import org.jetbrains.kotlin.ir.declarations.IrDeclaration +import org.jetbrains.kotlin.ir.declarations.IrModuleFragment +import org.jetbrains.kotlin.ir.util.module +import org.jetbrains.kotlin.library.KotlinLibrary + +internal abstract class LlvmModuleSpecificationBase(protected val cachedLibraries: CachedLibraries) : LlvmModuleSpecification { + override fun importsKotlinDeclarationsFromOtherObjectFiles(): Boolean = + cachedLibraries.hasStaticCaches // A bit conservative but still valid. + + override fun importsKotlinDeclarationsFromOtherSharedLibraries(): Boolean = + cachedLibraries.hasDynamicCaches // A bit conservative but still valid. + + override fun containsModule(module: IrModuleFragment): Boolean = + containsModule(module.descriptor) + + override fun containsModule(module: ModuleDescriptor): Boolean = + module.konanLibrary.let { it == null || containsLibrary(it) } + + override fun containsDeclaration(declaration: IrDeclaration): Boolean = + declaration.module.konanLibrary.let { it == null || containsLibrary(it) } +} + +internal class DefaultLlvmModuleSpecification(cachedLibraries: CachedLibraries) + : LlvmModuleSpecificationBase(cachedLibraries) { + override val isFinal = true + + override fun containsLibrary(library: KotlinLibrary): Boolean = !cachedLibraries.isLibraryCached(library) +} + +internal class CacheLlvmModuleSpecification( + cachedLibraries: CachedLibraries, + private val librariesToCache: Set +) : LlvmModuleSpecificationBase(cachedLibraries) { + override val isFinal = false + + override fun containsLibrary(library: KotlinLibrary): Boolean = library in librariesToCache +} diff --git a/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/MemoryModel.kt b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/MemoryModel.kt new file mode 100644 index 00000000000..954d151037c --- /dev/null +++ b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/MemoryModel.kt @@ -0,0 +1,11 @@ +/* + * Copyright 2010-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ +package org.jetbrains.kotlin.backend.konan + +enum class MemoryModel { + STRICT, + RELAXED, + EXPERIMENTAL, +} diff --git a/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/ObjCInterop.kt b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/ObjCInterop.kt new file mode 100644 index 00000000000..8b069430730 --- /dev/null +++ b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/ObjCInterop.kt @@ -0,0 +1,335 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +package org.jetbrains.kotlin.backend.konan + +import org.jetbrains.kotlin.backend.konan.descriptors.findPackage +import org.jetbrains.kotlin.backend.konan.descriptors.getArgumentValueOrNull +import org.jetbrains.kotlin.backend.konan.descriptors.getAnnotationValueOrNull +import org.jetbrains.kotlin.backend.konan.descriptors.getStringValue +import org.jetbrains.kotlin.backend.konan.descriptors.getAnnotationStringValue +import org.jetbrains.kotlin.backend.konan.descriptors.getStringValueOrNull +import org.jetbrains.kotlin.backend.konan.ir.* +import org.jetbrains.kotlin.descriptors.* +import org.jetbrains.kotlin.descriptors.annotations.AnnotationDescriptor +import org.jetbrains.kotlin.incremental.components.NoLookupLocation +import org.jetbrains.kotlin.ir.declarations.* +import org.jetbrains.kotlin.ir.expressions.IrConstructorCall +import org.jetbrains.kotlin.ir.symbols.isPublicApi +import org.jetbrains.kotlin.ir.types.classOrNull +import org.jetbrains.kotlin.ir.types.getPublicSignature +import org.jetbrains.kotlin.ir.util.* +import org.jetbrains.kotlin.name.FqName +import org.jetbrains.kotlin.name.Name +import org.jetbrains.kotlin.resolve.ExternalOverridabilityCondition +import org.jetbrains.kotlin.resolve.constants.BooleanValue +import org.jetbrains.kotlin.resolve.descriptorUtil.fqNameSafe +import org.jetbrains.kotlin.resolve.descriptorUtil.getAllSuperClassifiers +import org.jetbrains.kotlin.resolve.descriptorUtil.parentsWithSelf +import org.jetbrains.kotlin.types.KotlinType +import org.jetbrains.kotlin.types.TypeUtils +import org.jetbrains.kotlin.types.typeUtil.supertypes +import org.jetbrains.kotlin.utils.addToStdlib.firstNotNullResult + +internal val interopPackageName = InteropFqNames.packageName +internal val objCObjectFqName = interopPackageName.child(Name.identifier("ObjCObject")) +internal val objCObjectIdSignature = getTopLevelPublicSignature(objCObjectFqName) +private val objCClassFqName = interopPackageName.child(Name.identifier("ObjCClass")) +private val objCClassIdSignature = getTopLevelPublicSignature(objCClassFqName) +private val objCProtocolFqName = interopPackageName.child(Name.identifier("ObjCProtocol")) +private val objCProtocolIdSignature = getTopLevelPublicSignature(objCProtocolFqName) +internal val externalObjCClassFqName = interopPackageName.child(Name.identifier("ExternalObjCClass")) +private val objCMethodFqName = interopPackageName.child(Name.identifier("ObjCMethod")) +private val objCConstructorFqName = FqName("kotlinx.cinterop.ObjCConstructor") +private val objCFactoryFqName = interopPackageName.child(Name.identifier("ObjCFactory")) +private val objcnamesForwardDeclarationsPackageName = Name.identifier("objcnames") + +private fun getTopLevelPublicSignature(fqName: FqName): IdSignature.PublicSignature = + getPublicSignature(fqName.parent(), fqName.shortName().asString()) + +fun ClassDescriptor.isObjCClass(): Boolean = + this.containingDeclaration.fqNameSafe != interopPackageName && + this.getAllSuperClassifiers().any { it.fqNameSafe == objCObjectFqName } // TODO: this is not cheap. Cache me! + +fun KotlinType.isObjCObjectType(): Boolean = + (this.supertypes() + this).any { TypeUtils.getClassDescriptor(it)?.fqNameSafe == objCObjectFqName } + +private fun IrClass.selfOrAnySuperClass(pred: (IrClass) -> Boolean): Boolean { + if (pred(this)) return true + + return superTypes.any { it.classOrNull!!.owner.selfOrAnySuperClass(pred) } +} + +internal fun IrClass.isObjCClass() = this.packageFqName != interopPackageName && + selfOrAnySuperClass { it.symbol.isPublicApi && objCObjectIdSignature == it.symbol.signature } + +fun ClassDescriptor.isExternalObjCClass(): Boolean = this.isObjCClass() && + this.parentsWithSelf.filterIsInstance().any { + it.annotations.findAnnotation(externalObjCClassFqName) != null + } +fun IrClass.isExternalObjCClass(): Boolean = this.isObjCClass() && + (this as IrDeclaration).parentDeclarationsWithSelf.filterIsInstance().any { + it.annotations.hasAnnotation(externalObjCClassFqName) + } + +fun ClassDescriptor.isObjCForwardDeclaration(): Boolean = + this.findPackage().fqName.startsWith(objcnamesForwardDeclarationsPackageName) + +fun ClassDescriptor.isObjCMetaClass(): Boolean = this.getAllSuperClassifiers().any { + it.fqNameSafe == objCClassFqName +} + +fun IrClass.isObjCMetaClass(): Boolean = selfOrAnySuperClass { + it.symbol.isPublicApi && objCClassIdSignature == it.symbol.signature +} + +fun IrClass.isObjCProtocolClass(): Boolean = + symbol.isPublicApi && objCProtocolIdSignature == symbol.signature + +fun ClassDescriptor.isObjCProtocolClass(): Boolean = + this.fqNameSafe == objCProtocolFqName + +fun FunctionDescriptor.isObjCClassMethod() = + this.containingDeclaration.let { it is ClassDescriptor && it.isObjCClass() } + +fun IrFunction.isObjCClassMethod() = + this.parent.let { it is IrClass && it.isObjCClass() } + +fun FunctionDescriptor.isExternalObjCClassMethod() = + this.containingDeclaration.let { it is ClassDescriptor && it.isExternalObjCClass() } + +internal fun IrFunction.isExternalObjCClassMethod() = + this.parent.let {it is IrClass && it.isExternalObjCClass()} + +// Special case: methods from Kotlin Objective-C classes can be called virtually from bridges. +fun FunctionDescriptor.canObjCClassMethodBeCalledVirtually(overriddenDescriptor: FunctionDescriptor) = + overriddenDescriptor.isOverridable && this.kind.isReal && !this.isExternalObjCClassMethod() + +internal fun IrFunction.canObjCClassMethodBeCalledVirtually(overridden: IrFunction) = + overridden.isOverridable && this.origin != IrDeclarationOrigin.FAKE_OVERRIDE && !this.isExternalObjCClassMethod() + +fun ClassDescriptor.isKotlinObjCClass(): Boolean = this.isObjCClass() && !this.isExternalObjCClass() + +fun IrClass.isKotlinObjCClass(): Boolean = this.isObjCClass() && !this.isExternalObjCClass() + + +data class ObjCMethodInfo(val selector: String, + val encoding: String, + val isStret: Boolean) + +private fun FunctionDescriptor.decodeObjCMethodAnnotation(): ObjCMethodInfo? { + assert (this.kind.isReal) + val methodAnnotation = this.annotations.findAnnotation(objCMethodFqName) ?: return null + return objCMethodInfo(methodAnnotation) +} + +private fun IrFunction.decodeObjCMethodAnnotation(): ObjCMethodInfo? { + assert (this.isReal) + val methodAnnotation = this.annotations.findAnnotation(objCMethodFqName) ?: return null + return objCMethodInfo(methodAnnotation) +} + +private fun objCMethodInfo(annotation: AnnotationDescriptor) = ObjCMethodInfo( + selector = annotation.getStringValue("selector"), + encoding = annotation.getStringValue("encoding"), + isStret = annotation.getArgumentValueOrNull("isStret") ?: false +) + +private fun objCMethodInfo(annotation: IrConstructorCall) = ObjCMethodInfo( + selector = annotation.getAnnotationStringValue("selector"), + encoding = annotation.getAnnotationStringValue("encoding"), + isStret = annotation.getAnnotationValueOrNull("isStret") ?: false +) + +/** + * @param onlyExternal indicates whether to accept overriding methods from Kotlin classes + */ +private fun FunctionDescriptor.getObjCMethodInfo(onlyExternal: Boolean): ObjCMethodInfo? { + if (this.kind.isReal) { + this.decodeObjCMethodAnnotation()?.let { return it } + + if (onlyExternal) { + return null + } + } + + return overriddenDescriptors.firstNotNullResult { it.getObjCMethodInfo(onlyExternal) } +} + +/** + * @param onlyExternal indicates whether to accept overriding methods from Kotlin classes + */ +private fun IrSimpleFunction.getObjCMethodInfo(onlyExternal: Boolean): ObjCMethodInfo? { + if (this.isReal) { + this.decodeObjCMethodAnnotation()?.let { return it } + + if (onlyExternal) { + return null + } + } + + return overriddenSymbols.firstNotNullResult { it.owner.getObjCMethodInfo(onlyExternal) } +} + +fun FunctionDescriptor.getExternalObjCMethodInfo(): ObjCMethodInfo? = this.getObjCMethodInfo(onlyExternal = true) + +fun IrFunction.getExternalObjCMethodInfo(): ObjCMethodInfo? = (this as? IrSimpleFunction)?.getObjCMethodInfo(onlyExternal = true) + +fun FunctionDescriptor.getObjCMethodInfo(): ObjCMethodInfo? = this.getObjCMethodInfo(onlyExternal = false) + +fun IrFunction.getObjCMethodInfo(): ObjCMethodInfo? = (this as? IrSimpleFunction)?.getObjCMethodInfo(onlyExternal = false) + +fun IrFunction.isObjCBridgeBased(): Boolean { + assert(this.isReal) + + return this.annotations.hasAnnotation(objCMethodFqName) || + this.annotations.hasAnnotation(objCFactoryFqName) || + this.annotations.hasAnnotation(objCConstructorFqName) +} + +/** + * Describes method overriding rules for Objective-C methods. + * + * This class is applied at [org.jetbrains.kotlin.resolve.OverridingUtil] as configured with + * `META-INF/services/org.jetbrains.kotlin.resolve.ExternalOverridabilityCondition` resource. + */ +class ObjCOverridabilityCondition : ExternalOverridabilityCondition { + + override fun getContract() = ExternalOverridabilityCondition.Contract.BOTH + + override fun isOverridable( + superDescriptor: CallableDescriptor, + subDescriptor: CallableDescriptor, + subClassDescriptor: ClassDescriptor? + ): ExternalOverridabilityCondition.Result { + if (superDescriptor.name == subDescriptor.name) { // Slow path: + if (superDescriptor is FunctionDescriptor && subDescriptor is FunctionDescriptor) { + superDescriptor.getExternalObjCMethodInfo()?.let { superInfo -> + val subInfo = subDescriptor.getExternalObjCMethodInfo() + if (subInfo != null) { + // Overriding Objective-C method by Objective-C method in interop stubs. + // Don't even check method signatures: + return if (superInfo.selector == subInfo.selector) { + ExternalOverridabilityCondition.Result.OVERRIDABLE + } else { + ExternalOverridabilityCondition.Result.INCOMPATIBLE + } + } else { + // Overriding Objective-C method by Kotlin method. + if (!parameterNamesMatch(superDescriptor, subDescriptor)) { + return ExternalOverridabilityCondition.Result.INCOMPATIBLE + } + } + } + } else if (superDescriptor.isExternalObjCClassProperty() && subDescriptor.isExternalObjCClassProperty()) { + return ExternalOverridabilityCondition.Result.OVERRIDABLE + } + } + + return ExternalOverridabilityCondition.Result.UNKNOWN + } + + private fun CallableDescriptor.isExternalObjCClassProperty() = this is PropertyDescriptor && + (this.containingDeclaration as? ClassDescriptor)?.isExternalObjCClass() == true + + private fun parameterNamesMatch(first: FunctionDescriptor, second: FunctionDescriptor): Boolean { + // The original Objective-C method selector is represented as + // function name and parameter names (except first). + + if (first.valueParameters.size != second.valueParameters.size) { + return false + } + + first.valueParameters.forEachIndexed { index, parameter -> + if (index > 0 && parameter.name != second.valueParameters[index].name) { + return false + } + } + + return true + } + +} + +fun IrConstructor.objCConstructorIsDesignated(): Boolean = + this.getAnnotationArgumentValue(objCConstructorFqName, "designated") + ?: error("Could not find 'designated' argument") + +fun ConstructorDescriptor.objCConstructorIsDesignated(): Boolean { + val annotation = this.annotations.findAnnotation(objCConstructorFqName)!! + val value = annotation.allValueArguments[Name.identifier("designated")]!! + + return (value as BooleanValue).value +} + + +val IrConstructor.isObjCConstructor get() = this.annotations.hasAnnotation(objCConstructorFqName) +val ConstructorDescriptor.isObjCConstructor get() = this.annotations.hasAnnotation(objCConstructorFqName) + +// TODO-DCE-OBJC-INIT: Selector should be preserved by DCE. +fun IrConstructor.getObjCInitMethod(): IrSimpleFunction? { + return this.annotations.findAnnotation(objCConstructorFqName)?.let { + val initSelector = it.getAnnotationStringValue("initSelector") + this.constructedClass.declarations.asSequence() + .filterIsInstance() + .single { it.getExternalObjCMethodInfo()?.selector == initSelector } + } +} + +fun ConstructorDescriptor.getObjCInitMethod(): FunctionDescriptor? { + return this.annotations.findAnnotation(objCConstructorFqName)?.let { + val initSelector = it.getAnnotationStringValue("initSelector") + val memberScope = constructedClass.unsubstitutedMemberScope + val functionNames = memberScope.getFunctionNames() + for (name in functionNames) { + val functions = memberScope.getContributedFunctions(name, NoLookupLocation.FROM_BACKEND) + for (function in functions) { + val objectInfo = function.getExternalObjCMethodInfo() ?: continue + if (objectInfo.selector == initSelector) return function + } + } + error("Cannot find ObjInitMethod for $this") + } +} + +val IrFunction.hasObjCFactoryAnnotation get() = this.annotations.hasAnnotation(objCFactoryFqName) +val FunctionDescriptor.hasObjCFactoryAnnotation get() = this.annotations.hasAnnotation(objCFactoryFqName) + +val IrFunction.hasObjCMethodAnnotation get() = this.annotations.hasAnnotation(objCMethodFqName) +val FunctionDescriptor.hasObjCMethodAnnotation get() = this.annotations.hasAnnotation(objCMethodFqName) + +fun FunctionDescriptor.getObjCFactoryInitMethodInfo(): ObjCMethodInfo? { + val factoryAnnotation = this.annotations.findAnnotation(objCFactoryFqName) ?: return null + return objCMethodInfo(factoryAnnotation) +} + +fun IrFunction.getObjCFactoryInitMethodInfo(): ObjCMethodInfo? { + val factoryAnnotation = this.annotations.findAnnotation(objCFactoryFqName) ?: return null + return objCMethodInfo(factoryAnnotation) +} + +fun inferObjCSelector(descriptor: FunctionDescriptor): String = if (descriptor.valueParameters.isEmpty()) { + descriptor.name.asString() +} else { + buildString { + append(descriptor.name) + append(':') + descriptor.valueParameters.drop(1).forEach { + append(it.name) + append(':') + } + } +} + +fun ClassDescriptor.getExternalObjCClassBinaryName(): String = + this.getExplicitExternalObjCClassBinaryName() + ?: this.name.asString() + +fun ClassDescriptor.getExternalObjCMetaClassBinaryName(): String = + this.getExplicitExternalObjCClassBinaryName() + ?: this.name.asString().removeSuffix("Meta") + +private fun ClassDescriptor.getExplicitExternalObjCClassBinaryName() = + this.annotations.findAnnotation(externalObjCClassFqName)!!.getStringValueOrNull("binaryName") \ No newline at end of file diff --git a/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/OptimizationPipeline.kt b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/OptimizationPipeline.kt new file mode 100644 index 00000000000..ca4546c47b7 --- /dev/null +++ b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/OptimizationPipeline.kt @@ -0,0 +1,205 @@ +package org.jetbrains.kotlin.backend.konan + +import kotlinx.cinterop.alloc +import kotlinx.cinterop.memScoped +import kotlinx.cinterop.ptr +import kotlinx.cinterop.value +import llvm.* +import org.jetbrains.kotlin.backend.konan.llvm.makeVisibilityHiddenLikeLlvmInternalizePass +import org.jetbrains.kotlin.konan.target.CompilerOutputKind +import org.jetbrains.kotlin.konan.target.Configurables +import org.jetbrains.kotlin.konan.target.KonanTarget +import org.jetbrains.kotlin.konan.target.ZephyrConfigurables + +private fun initializeLlvmGlobalPassRegistry() { + val passRegistry = LLVMGetGlobalPassRegistry() + + LLVMInitializeCore(passRegistry) + LLVMInitializeTransformUtils(passRegistry) + LLVMInitializeScalarOpts(passRegistry) + LLVMInitializeVectorization(passRegistry) + LLVMInitializeInstCombine(passRegistry) + LLVMInitializeIPO(passRegistry) + LLVMInitializeInstrumentation(passRegistry) + LLVMInitializeAnalysis(passRegistry) + LLVMInitializeIPA(passRegistry) + LLVMInitializeCodeGen(passRegistry) + LLVMInitializeTarget(passRegistry) +} + +internal fun shouldRunLateBitcodePasses(context: Context): Boolean { + return context.coverage.enabled +} + +internal fun runLateBitcodePasses(context: Context, llvmModule: LLVMModuleRef) { + val passManager = LLVMCreatePassManager()!! + LLVMKotlinAddTargetLibraryInfoWrapperPass(passManager, context.llvm.targetTriple) + context.coverage.addLateLlvmPasses(passManager) + LLVMRunPassManager(passManager, llvmModule) + LLVMDisposePassManager(passManager) +} + +private class LlvmPipelineConfiguration(context: Context) { + + private val target = context.config.target + private val configurables: Configurables = context.config.platform.configurables + + val targetTriple: String = context.llvm.targetTriple + + // Some of these values are copied from corresponding runtime.bc + // which is using "generic" target CPU for many case. + // This approach is suboptimal because target-cpu="generic" limits + // the set of used cpu features. + // TODO: refactor KonanTarget so that we can explicitly specify + // target cpu or arch+features combination in a single place. + val cpuModel: String = when (target) { + KonanTarget.IOS_ARM32 -> "generic" + KonanTarget.IOS_ARM64 -> "cyclone" + KonanTarget.IOS_X64 -> "core2" + KonanTarget.TVOS_ARM64 -> "cyclone" + KonanTarget.TVOS_X64 -> "core2" + KonanTarget.WATCHOS_X86 -> "i386" + KonanTarget.WATCHOS_X64 -> "core2" + KonanTarget.WATCHOS_ARM64, + KonanTarget.WATCHOS_ARM32 -> "cortex-a7" + KonanTarget.LINUX_X64 -> "x86-64" + KonanTarget.MINGW_X86 -> "pentium4" + KonanTarget.MINGW_X64 -> "x86-64" + KonanTarget.MACOS_X64 -> "core2" + KonanTarget.LINUX_ARM32_HFP -> "arm1136jf-s" + KonanTarget.LINUX_ARM64 -> "generic" + KonanTarget.ANDROID_ARM32 -> "arm7tdmi" + KonanTarget.ANDROID_ARM64 -> "cortex-a57" + KonanTarget.ANDROID_X64 -> "x86-64" + KonanTarget.ANDROID_X86 -> "i686" + KonanTarget.LINUX_MIPS32 -> "mips32r2" + KonanTarget.LINUX_MIPSEL32 -> "mips32r2" + KonanTarget.WASM32 -> "generic" + is KonanTarget.ZEPHYR -> (configurables as ZephyrConfigurables).targetCpu ?: run { + context.reportCompilationWarning("targetCpu for target $target was not set. Targeting `generic` cpu.") + "generic" + } + } + + val cpuFeatures: String = when (target) { + KonanTarget.LINUX_ARM32_HFP -> "+dsp,+strict-align,+vfp2,-crypto,-d16,-fp-armv8,-fp-only-sp,-fp16,-neon,-thumb-mode,-vfp3,-vfp4" + KonanTarget.ANDROID_ARM32 -> "+soft-float,+strict-align,-crypto,-neon,-thumb-mode" + else -> "" + } + + /** + * Null value means that LLVM should use default inliner params + * for the provided optimization and size level. + */ + val customInlineThreshold: Int? = when { + context.shouldOptimize() -> INLINE_THRESHOLD_OPT + context.shouldContainDebugInfo() -> null + else -> null + } + + val optimizationLevel: LlvmOptimizationLevel = when { + context.shouldOptimize() -> LlvmOptimizationLevel.AGGRESSIVE + context.shouldContainDebugInfo() -> LlvmOptimizationLevel.NONE + else -> LlvmOptimizationLevel.DEFAULT + } + + val sizeLevel: LlvmSizeLevel = when { + // We try to optimize code as much as possible on embedded targets. + target is KonanTarget.ZEPHYR || + target == KonanTarget.WASM32 -> LlvmSizeLevel.AGGRESSIVE + context.shouldOptimize() -> LlvmSizeLevel.NONE + context.shouldContainDebugInfo() -> LlvmSizeLevel.NONE + else -> LlvmSizeLevel.NONE + } + + val codegenOptimizationLevel: LLVMCodeGenOptLevel = when { + context.shouldOptimize() -> LLVMCodeGenOptLevel.LLVMCodeGenLevelAggressive + context.shouldContainDebugInfo() -> LLVMCodeGenOptLevel.LLVMCodeGenLevelNone + else -> LLVMCodeGenOptLevel.LLVMCodeGenLevelDefault + } + + val relocMode: LLVMRelocMode = LLVMRelocMode.LLVMRelocDefault + + val codeModel: LLVMCodeModel = LLVMCodeModel.LLVMCodeModelDefault + + companion object { + // By default LLVM uses 250 for -03 builds. + // We use a smaller value since default value leads to + // unreasonably bloated runtime code without any measurable + // performance benefits. + // This value still has to be tuned for different targets, though. + private const val INLINE_THRESHOLD_OPT = 100 + } + + enum class LlvmOptimizationLevel(val value: Int) { + NONE(0), + DEFAULT(1), + AGGRESSIVE(3) + } + + enum class LlvmSizeLevel(val value: Int) { + NONE(0), + DEFAULT(1), + AGGRESSIVE(2) + } +} + +internal fun runLlvmOptimizationPipeline(context: Context) { + val llvmModule = context.llvmModule!! + val config = LlvmPipelineConfiguration(context) + + memScoped { + LLVMKotlinInitializeTargets() + + initializeLlvmGlobalPassRegistry() + val passBuilder = LLVMPassManagerBuilderCreate() + val modulePasses = LLVMCreatePassManager() + LLVMPassManagerBuilderSetOptLevel(passBuilder, config.optimizationLevel.value) + LLVMPassManagerBuilderSetSizeLevel(passBuilder, config.sizeLevel.value) + // TODO: use LLVMGetTargetFromName instead. + val target = alloc() + val foundLlvmTarget = LLVMGetTargetFromTriple(config.targetTriple, target.ptr, null) == 0 + check(foundLlvmTarget) { "Cannot get target from triple ${config.targetTriple}." } + + val targetMachine = LLVMCreateTargetMachine( + target.value, + config.targetTriple, + config.cpuModel, + config.cpuFeatures, + config.codegenOptimizationLevel, + config.relocMode, + config.codeModel) + + LLVMKotlinAddTargetLibraryInfoWrapperPass(modulePasses, config.targetTriple) + // TargetTransformInfo pass. + LLVMAddAnalysisPasses(targetMachine, modulePasses) + if (context.llvmModuleSpecification.isFinal) { + // Since we are in a "closed world" internalization can be safely used + // to reduce size of a bitcode with global dce. + LLVMAddInternalizePass(modulePasses, 0) + } else if (context.config.produce == CompilerOutputKind.STATIC_CACHE) { + // Hidden visibility makes symbols internal when linking the binary. + // When producing dynamic library, this enables stripping unused symbols from binary with -dead_strip flag, + // similar to DCE enabled by internalize but later: + makeVisibilityHiddenLikeLlvmInternalizePass(llvmModule) + // Important for binary size, workarounds references to undefined symbols from interop libraries. + } + LLVMAddGlobalDCEPass(modulePasses) + + config.customInlineThreshold?.let { threshold -> + LLVMPassManagerBuilderUseInlinerWithThreshold(passBuilder, threshold) + } + // Pipeline that is similar to `llvm-lto`. + // TODO: Add ObjC optimization passes. + LLVMPassManagerBuilderPopulateLTOPassManager(passBuilder, modulePasses, Internalize = 0, RunInliner = 1) + + LLVMRunPassManager(modulePasses, llvmModule) + + LLVMPassManagerBuilderDispose(passBuilder) + LLVMDisposeTargetMachine(targetMachine) + LLVMDisposePassManager(modulePasses) + } + if (shouldRunLateBitcodePasses(context)) { + runLateBitcodePasses(context, llvmModule) + } +} \ No newline at end of file diff --git a/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/OutputFiles.kt b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/OutputFiles.kt new file mode 100644 index 00000000000..e592ffbf9a5 --- /dev/null +++ b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/OutputFiles.kt @@ -0,0 +1,79 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ +package org.jetbrains.kotlin.backend.konan + +import org.jetbrains.kotlin.util.prefixBaseNameIfNot +import org.jetbrains.kotlin.util.removeSuffixIfPresent +import org.jetbrains.kotlin.util.suffixIfNot +import org.jetbrains.kotlin.konan.file.File +import org.jetbrains.kotlin.konan.target.CompilerOutputKind +import org.jetbrains.kotlin.konan.target.KonanTarget +import org.jetbrains.kotlin.konan.util.visibleName +import kotlin.random.Random + + +/** + * Creates and stores terminal compiler outputs. + */ +class OutputFiles(outputPath: String?, target: KonanTarget, val produce: CompilerOutputKind) { + + private val prefix = produce.prefix(target) + private val suffix = produce.suffix(target) + + val outputName = outputPath?.removeSuffixIfPresent(suffix) ?: produce.visibleName + + /** + * Header file for dynamic library. + */ + val cAdapterHeader by lazy { File("${outputName}_api.h") } + val cAdapterDef by lazy { File("${outputName}.def") } + + /** + * Main compiler's output file. + */ + val mainFile = + if (produce.isCache) + outputName + else + outputName.fullOutputName() + + val tempCacheDirectory = + if (produce.isCache) + File(outputName + Random.nextLong().toString()) + else null + + val nativeBinaryFile = + if (produce.isCache) + tempCacheDirectory!!.child(File(outputName.fullOutputName()).absoluteFile.name).absolutePath + else mainFile + + val symbolicInfoFile = "$nativeBinaryFile.dSYM" + + val bitcodeDependenciesFile = + if (produce.isCache) + tempCacheDirectory!!.child(CachedLibraries.BITCODE_DEPENDENCIES_FILE_NAME).absolutePath + else null + + private fun String.fullOutputName() = prefixBaseNameIfNeeded(prefix).suffixIfNeeded(suffix) + + private fun String.prefixBaseNameIfNeeded(prefix: String) = + if (produce.isCache) + prefixBaseNameAlways(prefix) + else prefixBaseNameIfNot(prefix) + + private fun String.suffixIfNeeded(prefix: String) = + if (produce.isCache) + suffixAlways(prefix) + else suffixIfNot(prefix) + + private fun String.prefixBaseNameAlways(prefix: String): String { + val file = File(this).absoluteFile + val name = file.name + val directory = file.parent + return "$directory/$prefix$name" + } + + private fun String.suffixAlways(suffix: String) = "$this$suffix" +} \ No newline at end of file diff --git a/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/PsiToIr.kt b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/PsiToIr.kt new file mode 100644 index 00000000000..49abcccc74b --- /dev/null +++ b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/PsiToIr.kt @@ -0,0 +1,197 @@ +package org.jetbrains.kotlin.backend.konan + +import org.jetbrains.kotlin.backend.common.LoggingContext +import org.jetbrains.kotlin.backend.common.extensions.IrGenerationExtension +import org.jetbrains.kotlin.backend.common.extensions.IrPluginContextImpl +import org.jetbrains.kotlin.backend.common.overrides.FakeOverrideChecker +import org.jetbrains.kotlin.backend.common.serialization.mangle.ManglerChecker +import org.jetbrains.kotlin.backend.common.serialization.mangle.descriptor.Ir2DescriptorManglerAdapter +import org.jetbrains.kotlin.backend.konan.descriptors.isForwardDeclarationModule +import org.jetbrains.kotlin.backend.konan.descriptors.isFromInteropLibrary +import org.jetbrains.kotlin.backend.konan.descriptors.konanLibrary +import org.jetbrains.kotlin.backend.konan.ir.KonanSymbols +import org.jetbrains.kotlin.backend.konan.ir.interop.IrProviderForCEnumAndCStructStubs +import org.jetbrains.kotlin.backend.konan.serialization.KonanIrLinker +import org.jetbrains.kotlin.backend.konan.serialization.KonanManglerDesc +import org.jetbrains.kotlin.backend.konan.serialization.KonanManglerIr +import org.jetbrains.kotlin.config.CommonConfigurationKeys +import org.jetbrains.kotlin.config.languageVersionSettings +import org.jetbrains.kotlin.descriptors.ModuleDescriptor +import org.jetbrains.kotlin.descriptors.konan.DeserializedKlibModuleOrigin +import org.jetbrains.kotlin.descriptors.konan.KlibModuleOrigin +import org.jetbrains.kotlin.descriptors.konan.isNativeStdlib +import org.jetbrains.kotlin.ir.builders.TranslationPluginContext +import org.jetbrains.kotlin.ir.descriptors.IrBuiltIns +import org.jetbrains.kotlin.ir.linkage.IrDeserializer +import org.jetbrains.kotlin.ir.symbols.IrSymbol +import org.jetbrains.kotlin.ir.util.* +import org.jetbrains.kotlin.ir.visitors.acceptVoid +import org.jetbrains.kotlin.psi2ir.Psi2IrConfiguration +import org.jetbrains.kotlin.psi2ir.Psi2IrTranslator +import org.jetbrains.kotlin.resolve.BindingContext +import org.jetbrains.kotlin.utils.DFS + +internal fun Context.psiToIr( + symbolTable: SymbolTable, + isProducingLibrary: Boolean, + useLinkerWhenProducingLibrary: Boolean +) { + // Translate AST to high level IR. + val expectActualLinker = config.configuration.get(CommonConfigurationKeys.EXPECT_ACTUAL_LINKER)?:false + + val translator = Psi2IrTranslator(config.configuration.languageVersionSettings, Psi2IrConfiguration(false)) + val generatorContext = translator.createGeneratorContext(moduleDescriptor, bindingContext, symbolTable) + + val pluginExtensions = IrGenerationExtension.getInstances(config.project) + + val forwardDeclarationsModuleDescriptor = moduleDescriptor.allDependencyModules.firstOrNull { it.isForwardDeclarationModule } + + val modulesWithoutDCE = moduleDescriptor.allDependencyModules + .filter { !llvmModuleSpecification.isFinal && llvmModuleSpecification.containsModule(it) } + + // Note: using [llvmModuleSpecification] since this phase produces IR for generating single LLVM module. + + val exportedDependencies = (getExportedDependencies() + modulesWithoutDCE).distinct() + val functionIrClassFactory = BuiltInFictitiousFunctionIrClassFactory( + symbolTable, generatorContext.irBuiltIns, reflectionTypes) + generatorContext.irBuiltIns.functionFactory = functionIrClassFactory + val stubGenerator = DeclarationStubGenerator( + moduleDescriptor, symbolTable, + config.configuration.languageVersionSettings + ) + val symbols = KonanSymbols(this, generatorContext.irBuiltIns, symbolTable, symbolTable.lazyWrapper, functionIrClassFactory) + + val irDeserializer = if (isProducingLibrary && !useLinkerWhenProducingLibrary) { + // Enable lazy IR generation for newly-created symbols inside BE + stubGenerator.unboundSymbolGeneration = true + + object : IrDeserializer { + override fun getDeclaration(symbol: IrSymbol) = stubGenerator.getDeclaration(symbol) + } + } else { + val irProviderForCEnumsAndCStructs = + IrProviderForCEnumAndCStructStubs(generatorContext, interopBuiltIns, symbols) + + val deserializeFakeOverrides = config.configuration.getBoolean(CommonConfigurationKeys.DESERIALIZE_FAKE_OVERRIDES) + + val translationContext = object : TranslationPluginContext { + override val moduleDescriptor: ModuleDescriptor + get() = generatorContext.moduleDescriptor + override val bindingContext: BindingContext + get() = generatorContext.bindingContext + override val symbolTable: ReferenceSymbolTable + get() = symbolTable + override val typeTranslator: TypeTranslator + get() = generatorContext.typeTranslator + override val irBuiltIns: IrBuiltIns + get() = generatorContext.irBuiltIns + } + + KonanIrLinker( + moduleDescriptor, + functionIrClassFactory, + translationContext, + this as LoggingContext, + generatorContext.irBuiltIns, + symbolTable, + forwardDeclarationsModuleDescriptor, + stubGenerator, + irProviderForCEnumsAndCStructs, + exportedDependencies, + deserializeFakeOverrides, + config.cachedLibraries + ).also { linker -> + + // context.config.librariesWithDependencies could change at each iteration. + var dependenciesCount = 0 + while (true) { + // context.config.librariesWithDependencies could change at each iteration. + val dependencies = moduleDescriptor.allDependencyModules.filter { + config.librariesWithDependencies(moduleDescriptor).contains(it.konanLibrary) + } + + fun sortDependencies(dependencies: List): Collection { + return DFS.topologicalOrder(dependencies) { + it.allDependencyModules + }.reversed() + } + + for (dependency in sortDependencies(dependencies).filter { it != moduleDescriptor }) { + val kotlinLibrary = dependency.getCapability(KlibModuleOrigin.CAPABILITY)?.let { + (it as? DeserializedKlibModuleOrigin)?.library + } + if (isProducingLibrary) + linker.deserializeOnlyHeaderModule(dependency, kotlinLibrary) + else + linker.deserializeIrModuleHeader(dependency, kotlinLibrary) + } + if (dependencies.size == dependenciesCount) break + dependenciesCount = dependencies.size + } + + // We need to run `buildAllEnumsAndStructsFrom` before `generateModuleFragment` because it adds references to symbolTable + // that should be bound. + modulesWithoutDCE + .filter(ModuleDescriptor::isFromInteropLibrary) + .forEach(irProviderForCEnumsAndCStructs::referenceAllEnumsAndStructsFrom) + } + } + + translator.addPostprocessingStep { module -> + val pluginContext = IrPluginContextImpl( + generatorContext.moduleDescriptor, + generatorContext.bindingContext, + generatorContext.languageVersionSettings, + generatorContext.symbolTable, + generatorContext.typeTranslator, + generatorContext.irBuiltIns, + linker = irDeserializer + ) + pluginExtensions.forEach { extension -> + extension.generate(module, pluginContext) + } + } + + expectDescriptorToSymbol = mutableMapOf() + val module = translator.generateModuleFragment( + generatorContext, + environment.getSourceFiles(), + irProviders = listOf(irDeserializer), + linkerExtensions = pluginExtensions, + // TODO: This is a hack to allow platform libs to build in reasonable time. + // referenceExpectsForUsedActuals() appears to be quadratic in time because of + // how ExpectedActualResolver is implemented. + // Need to fix ExpectActualResolver to either cache expects or somehow reduce the member scope searches. + expectDescriptorToSymbol = if (expectActualLinker) expectDescriptorToSymbol else null + ) + + irDeserializer.postProcess() + + // Enable lazy IR genration for newly-created symbols inside BE + stubGenerator.unboundSymbolGeneration = true + + symbolTable.noUnboundLeft("Unbound symbols left after linker") + + module.acceptVoid(ManglerChecker(KonanManglerIr, Ir2DescriptorManglerAdapter(KonanManglerDesc))) + + val modules = if (isProducingLibrary) emptyMap() else (irDeserializer as KonanIrLinker).modules + + if (!config.configuration.getBoolean(KonanConfigKeys.DISABLE_FAKE_OVERRIDE_VALIDATOR)) { + val fakeOverrideChecker = FakeOverrideChecker(KonanManglerIr, KonanManglerDesc) + modules.values.forEach { fakeOverrideChecker.check(it) } + } + + irModule = module + + // Note: coupled with [shouldLower] below. + irModules = modules.filterValues { llvmModuleSpecification.containsModule(it) } + + ir.symbols = symbols + + if (!isProducingLibrary) { + if (this.stdlibModule in modulesWithoutDCE) + functionIrClassFactory.buildAllClasses() + internalAbi.init(irModules.values + irModule!!) + functionIrClassFactory.module = (modules.values + irModule!!).single { it.descriptor.isNativeStdlib() } + } +} \ No newline at end of file diff --git a/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/Reporting.kt b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/Reporting.kt new file mode 100644 index 00000000000..f41fe630c3e --- /dev/null +++ b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/Reporting.kt @@ -0,0 +1,56 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +package org.jetbrains.kotlin.backend.konan + +import org.jetbrains.kotlin.backend.common.CommonBackendContext +import org.jetbrains.kotlin.cli.common.messages.CompilerMessageSeverity +import org.jetbrains.kotlin.config.CompilerConfiguration +import org.jetbrains.kotlin.ir.IrElement +import org.jetbrains.kotlin.ir.declarations.IrFile +import org.jetbrains.kotlin.ir.util.render + +internal fun CommonBackendContext.reportCompilationError(message: String, irFile: IrFile, irElement: IrElement): Nothing { + report(irElement, irFile, message, true) + throw KonanCompilationException() +} + +internal fun CommonBackendContext.reportCompilationError(message: String): Nothing { + report(null, null, message, true) + throw KonanCompilationException() +} + +internal fun CompilerConfiguration.reportCompilationError(message: String): Nothing { + report(CompilerMessageSeverity.ERROR, message) + throw KonanCompilationException() +} + +internal fun CommonBackendContext.reportCompilationWarning(message: String) { + report(null, null, message, false) +} + +internal fun error(irFile: IrFile?, element: IrElement?, message: String): Nothing { + error(renderCompilerError(irFile, element, message)) +} + +internal fun renderCompilerError(irFile: IrFile?, element: IrElement?, message: String) = + buildString { + append("Internal compiler error: $message\n") + if (element == null) { + append("(IR element is null)") + } else { + if (irFile != null) { + val location = element.getCompilerMessageLocation(irFile) + append("at $location\n") + } + + val renderedElement = try { + element.render() + } catch (e: Throwable) { + "(unable to render IR element)" + } + append(renderedElement) + } + } \ No newline at end of file diff --git a/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/RuntimeNames.kt b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/RuntimeNames.kt new file mode 100644 index 00000000000..c4f3f7caf33 --- /dev/null +++ b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/RuntimeNames.kt @@ -0,0 +1,23 @@ +package org.jetbrains.kotlin.backend.konan + +import org.jetbrains.kotlin.name.FqName + +object RuntimeNames { + val symbolNameAnnotation = FqName("kotlin.native.SymbolName") + val cnameAnnotation = FqName("kotlin.native.CName") + val frozenAnnotation = FqName("kotlin.native.internal.Frozen") + val exportForCppRuntime = FqName("kotlin.native.internal.ExportForCppRuntime") + val exportForCompilerAnnotation = FqName("kotlin.native.internal.ExportForCompiler") + val exportTypeInfoAnnotation = FqName("kotlin.native.internal.ExportTypeInfo") + val cCall = FqName("kotlinx.cinterop.internal.CCall") + val cStructMemberAt = FqName("kotlinx.cinterop.internal.CStruct.MemberAt") + val cStructArrayMemberAt = FqName("kotlinx.cinterop.internal.CStruct.ArrayMemberAt") + val cStructBitField = FqName("kotlinx.cinterop.internal.CStruct.BitField") + val objCMethodAnnotation = FqName("kotlinx.cinterop.ObjCMethod") + val objCMethodImp = FqName("kotlinx.cinterop.ObjCMethodImp") + val independent = FqName("kotlin.native.internal.Independent") + val filterExceptions = FqName("kotlin.native.internal.FilterExceptions") + val kotlinNativeInternalPackageName = FqName.fromSegments(listOf("kotlin", "native", "internal")) + val associatedObjectKey = FqName("kotlin.reflect.AssociatedObjectKey") + val typedIntrinsicAnnotation = FqName("kotlin.native.internal.TypedIntrinsic") +} diff --git a/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/TestRunnerKind.kt b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/TestRunnerKind.kt new file mode 100644 index 00000000000..1f364540966 --- /dev/null +++ b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/TestRunnerKind.kt @@ -0,0 +1,12 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ +package org.jetbrains.kotlin.backend.konan + +enum class TestRunnerKind { + NONE, + MAIN_THREAD, + WORKER, + MAIN_THREAD_NO_EXIT +} \ No newline at end of file diff --git a/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/TopDownAnalyzerFacadeForKonan.kt b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/TopDownAnalyzerFacadeForKonan.kt new file mode 100644 index 00000000000..46027d9fbde --- /dev/null +++ b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/TopDownAnalyzerFacadeForKonan.kt @@ -0,0 +1,135 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +package org.jetbrains.kotlin.backend.konan + +import org.jetbrains.kotlin.library.resolver.KotlinLibraryResolveResult +import org.jetbrains.kotlin.analyzer.AnalysisResult +import org.jetbrains.kotlin.builtins.KotlinBuiltIns +import org.jetbrains.kotlin.builtins.functions.functionInterfacePackageFragmentProvider +import org.jetbrains.kotlin.builtins.konan.KonanBuiltIns +import org.jetbrains.kotlin.config.CommonConfigurationKeys +import org.jetbrains.kotlin.config.LanguageVersionSettings +import org.jetbrains.kotlin.container.get +import org.jetbrains.kotlin.context.ModuleContext +import org.jetbrains.kotlin.context.MutableModuleContextImpl +import org.jetbrains.kotlin.context.ProjectContext +import org.jetbrains.kotlin.descriptors.PackageFragmentProvider +import org.jetbrains.kotlin.descriptors.impl.ModuleDescriptorImpl +import org.jetbrains.kotlin.descriptors.konan.CurrentKlibModuleOrigin +import org.jetbrains.kotlin.descriptors.konan.isNativeStdlib +import org.jetbrains.kotlin.konan.file.File +import org.jetbrains.kotlin.konan.util.KlibMetadataFactories +import org.jetbrains.kotlin.library.KotlinLibrary +import org.jetbrains.kotlin.library.metadata.NativeTypeTransformer +import org.jetbrains.kotlin.library.metadata.NullFlexibleTypeDeserializer +import org.jetbrains.kotlin.name.Name +import org.jetbrains.kotlin.psi.KtFile +import org.jetbrains.kotlin.resolve.* +import org.jetbrains.kotlin.resolve.lazy.declarations.FileBasedDeclarationProviderFactory +import org.jetbrains.kotlin.serialization.konan.KotlinResolvedModuleDescriptors +import org.jetbrains.kotlin.storage.StorageManager + +internal object TopDownAnalyzerFacadeForKonan { + + fun analyzeFiles(files: Collection, context: Context): AnalysisResult { + val config = context.config + val moduleName = Name.special("<${config.moduleId}>") + + val projectContext = ProjectContext(config.project, "TopDownAnalyzer for Konan") + + val module = NativeFactories.DefaultDescriptorFactory.createDescriptorAndNewBuiltIns( + moduleName, projectContext.storageManager, origin = CurrentKlibModuleOrigin) + val moduleContext = MutableModuleContextImpl(module, projectContext) + + val resolvedDependencies = ResolvedDependencies( + config.resolvedLibraries, + projectContext.storageManager, + module.builtIns, + config.languageVersionSettings, + config.friendModuleFiles, + module + ) + + val additionalPackages = mutableListOf() + if (!module.isNativeStdlib()) { + val dependencies = listOf(module) + resolvedDependencies.moduleDescriptors.resolvedDescriptors + resolvedDependencies.moduleDescriptors.forwardDeclarationsModule + module.setDependencies(dependencies, resolvedDependencies.friends) + } else { + assert (resolvedDependencies.moduleDescriptors.resolvedDescriptors.isEmpty()) + moduleContext.setDependencies(module) + // [K][Suspend]FunctionN belong to stdlib. + additionalPackages += functionInterfacePackageFragmentProvider(projectContext.storageManager, module) + } + + return analyzeFilesWithGivenTrace(files, BindingTraceContext(), moduleContext, context, additionalPackages) + } + + fun analyzeFilesWithGivenTrace( + files: Collection, + trace: BindingTrace, + moduleContext: ModuleContext, + context: Context, + additionalPackages: List = emptyList() + ): AnalysisResult { + + // we print out each file we compile if frontend phase is verbose + files.takeIf { + frontendPhase in context.phaseConfig.verbose + } ?.forEach(::println) + + val analyzerForKonan = createTopDownAnalyzerProviderForKonan( + moduleContext, trace, + FileBasedDeclarationProviderFactory(moduleContext.storageManager, files), + context.config.configuration.get(CommonConfigurationKeys.LANGUAGE_VERSION_SETTINGS)!!, + additionalPackages + ) { + initContainer(context.config) + }.apply { + postprocessComponents(context, files) + }.get() + + analyzerForKonan.analyzeDeclarations(TopDownAnalysisMode.TopLevelDeclarations, files) + return AnalysisResult.success(trace.bindingContext, moduleContext.module) + } + + fun checkForErrors(files: Collection, bindingContext: BindingContext) { + AnalyzingUtils.throwExceptionOnErrors(bindingContext) + for (file in files) { + AnalyzingUtils.checkForSyntacticErrors(file) + } + } +} + +private class ResolvedDependencies( + resolvedLibraries: KotlinLibraryResolveResult, + storageManager: StorageManager, + builtIns: KotlinBuiltIns, + specifics: LanguageVersionSettings, + friendModuleFiles: Set, + currentModuleDescriptor: ModuleDescriptorImpl +) { + + val moduleDescriptors: KotlinResolvedModuleDescriptors + val friends: Set + + init { + + val collectedFriends = mutableListOf() + + val customAction: (KotlinLibrary, ModuleDescriptorImpl) -> Unit = { library, moduleDescriptor -> + if (friendModuleFiles.contains(library.libraryFile)) { + collectedFriends.add(moduleDescriptor) + } + } + + this.moduleDescriptors = NativeFactories.DefaultResolvedDescriptorsFactory.createResolved( + resolvedLibraries, storageManager, builtIns, specifics, customAction, listOf(currentModuleDescriptor)) + + this.friends = collectedFriends.toSet() + } +} + +val NativeFactories = KlibMetadataFactories(::KonanBuiltIns, NullFlexibleTypeDeserializer, NativeTypeTransformer()) diff --git a/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/ToplevelPhases.kt b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/ToplevelPhases.kt new file mode 100644 index 00000000000..b92344bd15d --- /dev/null +++ b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/ToplevelPhases.kt @@ -0,0 +1,479 @@ +package org.jetbrains.kotlin.backend.konan + +import org.jetbrains.kotlin.backend.common.CheckDeclarationParentsVisitor +import org.jetbrains.kotlin.backend.common.IrValidator +import org.jetbrains.kotlin.backend.common.IrValidatorConfig +import org.jetbrains.kotlin.backend.common.lower.createIrBuilder +import org.jetbrains.kotlin.backend.common.phaser.* +import org.jetbrains.kotlin.backend.common.serialization.metadata.KlibMetadataMonolithicSerializer +import org.jetbrains.kotlin.backend.konan.llvm.* +import org.jetbrains.kotlin.backend.konan.lower.ExpectToActualDefaultValueCopier +import org.jetbrains.kotlin.backend.konan.objcexport.ObjCExport +import org.jetbrains.kotlin.backend.konan.serialization.* +import org.jetbrains.kotlin.cli.common.messages.AnalyzerWithCompilerReport +import org.jetbrains.kotlin.config.CommonConfigurationKeys +import org.jetbrains.kotlin.config.languageVersionSettings +import org.jetbrains.kotlin.ir.IrElement +import org.jetbrains.kotlin.ir.builders.declarations.buildFun +import org.jetbrains.kotlin.ir.builders.irBlockBody +import org.jetbrains.kotlin.ir.builders.irGetObjectValue +import org.jetbrains.kotlin.ir.builders.irReturn +import org.jetbrains.kotlin.ir.declarations.* +import org.jetbrains.kotlin.ir.declarations.impl.IrFactoryImpl +import org.jetbrains.kotlin.ir.expressions.IrExpression +import org.jetbrains.kotlin.ir.expressions.IrGetObjectValue +import org.jetbrains.kotlin.ir.expressions.impl.IrCallImpl +import org.jetbrains.kotlin.ir.util.* +import org.jetbrains.kotlin.ir.visitors.IrElementTransformerVoid +import org.jetbrains.kotlin.ir.visitors.IrElementVisitorVoid +import org.jetbrains.kotlin.ir.visitors.acceptChildrenVoid +import org.jetbrains.kotlin.ir.visitors.transformChildrenVoid +import org.jetbrains.kotlin.konan.target.CompilerOutputKind + +internal fun moduleValidationCallback(state: ActionState, module: IrModuleFragment, context: Context) { + if (!context.config.needCompilerVerification) return + + val validatorConfig = IrValidatorConfig( + abortOnError = false, + ensureAllNodesAreDifferent = true, + checkTypes = true, + checkDescriptors = false + ) + try { + module.accept(IrValidator(context, validatorConfig), null) + module.accept(CheckDeclarationParentsVisitor, null) + } catch (t: Throwable) { + // TODO: Add reference to source. + if (validatorConfig.abortOnError) + throw IllegalStateException("Failed IR validation ${state.beforeOrAfter} ${state.phase}", t) + else context.reportCompilationWarning("[IR VALIDATION] ${state.beforeOrAfter} ${state.phase}: ${t.message}") + } +} + +internal fun fileValidationCallback(state: ActionState, irFile: IrFile, context: Context) { + val validatorConfig = IrValidatorConfig( + abortOnError = false, + ensureAllNodesAreDifferent = true, + checkTypes = true, + checkDescriptors = false + ) + try { + irFile.accept(IrValidator(context, validatorConfig), null) + irFile.accept(CheckDeclarationParentsVisitor, null) + } catch (t: Throwable) { + // TODO: Add reference to source. + if (validatorConfig.abortOnError) + throw IllegalStateException("Failed IR validation ${state.beforeOrAfter} ${state.phase}", t) + else context.reportCompilationWarning("[IR VALIDATION] ${state.beforeOrAfter} ${state.phase}: ${t.message}") + } +} + +internal fun konanUnitPhase( + name: String, + description: String, + prerequisite: Set = emptySet(), + op: Context.() -> Unit +) = namedOpUnitPhase(name, description, prerequisite, op) + +internal val frontendPhase = konanUnitPhase( + op = { + val environment = environment + val analyzerWithCompilerReport = AnalyzerWithCompilerReport(messageCollector, + environment.configuration.languageVersionSettings) + + // Build AST and binding info. + analyzerWithCompilerReport.analyzeAndReport(environment.getSourceFiles()) { + TopDownAnalyzerFacadeForKonan.analyzeFiles(environment.getSourceFiles(), this) + } + if (analyzerWithCompilerReport.hasErrors()) { + throw KonanCompilationException() + } + moduleDescriptor = analyzerWithCompilerReport.analysisResult.moduleDescriptor + bindingContext = analyzerWithCompilerReport.analysisResult.bindingContext + }, + name = "Frontend", + description = "Frontend builds AST" +) + +/** + * Valid from [createSymbolTablePhase] until [destroySymbolTablePhase]. + */ +private var Context.symbolTable: SymbolTable? by Context.nullValue() + +internal val createSymbolTablePhase = konanUnitPhase( + op = { + this.symbolTable = SymbolTable(KonanIdSignaturer(KonanManglerDesc), IrFactoryImpl) + }, + name = "CreateSymbolTable", + description = "Create SymbolTable" +) + +internal val objCExportPhase = konanUnitPhase( + op = { + objCExport = ObjCExport(this, symbolTable!!) + }, + name = "ObjCExport", + description = "Objective-C header generation", + prerequisite = setOf(createSymbolTablePhase) +) + +internal val buildCExportsPhase = konanUnitPhase( + op = { + if (this.isNativeLibrary) { + this.cAdapterGenerator = CAdapterGenerator(this).also { + it.buildExports(this.symbolTable!!) + } + } + }, + name = "BuildCExports", + description = "Build C exports", + prerequisite = setOf(createSymbolTablePhase) +) + +internal val psiToIrPhase = konanUnitPhase( + op = { + this.psiToIr(symbolTable!!, + isProducingLibrary = config.produce == CompilerOutputKind.LIBRARY, + useLinkerWhenProducingLibrary = false) + }, + name = "Psi2Ir", + description = "Psi to IR conversion and klib linkage", + prerequisite = setOf(createSymbolTablePhase) +) + +// Coupled with [psiToIrPhase] logic above. +internal fun shouldLower(context: Context, declaration: IrDeclaration): Boolean { + return context.llvmModuleSpecification.containsDeclaration(declaration) +} + +internal val destroySymbolTablePhase = konanUnitPhase( + op = { + this.symbolTable = null // TODO: invalidate symbolTable itself. + }, + name = "DestroySymbolTable", + description = "Destroy SymbolTable", + prerequisite = setOf(createSymbolTablePhase) +) + +// TODO: We copy default value expressions from expects to actuals before IR serialization, +// because the current infrastructure doesn't allow us to get them at deserialization stage. +// That requires some design and implementation work. +internal val copyDefaultValuesToActualPhase = konanUnitPhase( + op = { + ExpectToActualDefaultValueCopier(irModule!!).process() + }, + name = "CopyDefaultValuesToActual", + description = "Copy default values from expect to actual declarations" +) + +internal val serializerPhase = konanUnitPhase( + op = { + val expectActualLinker = config.configuration.get(CommonConfigurationKeys.EXPECT_ACTUAL_LINKER) ?: false + + serializedIr = irModule?.let { ir -> + KonanIrModuleSerializer( + this, ir.irBuiltins, expectDescriptorToSymbol, skipExpects = !expectActualLinker + ).serializedIrModule(ir) + } + + val serializer = KlibMetadataMonolithicSerializer( + this.config.configuration.languageVersionSettings, + config.configuration.get(CommonConfigurationKeys.METADATA_VERSION)!!, + config.project, + !expectActualLinker) + serializedMetadata = serializer.serializeModule(moduleDescriptor) + }, + name = "Serializer", + description = "Serialize descriptor tree and inline IR bodies" +) + +internal val objectFilesPhase = konanUnitPhase( + op = { compilerOutput = BitcodeCompiler(this).makeObjectFiles(bitcodeFileName) }, + name = "ObjectFiles", + description = "Bitcode to object file" +) + +internal val linkerPhase = konanUnitPhase( + op = { Linker(this).link(compilerOutput) }, + name = "Linker", + description = "Linker" +) + +internal val allLoweringsPhase = NamedCompilerPhase( + name = "IrLowering", + description = "IR Lowering", + // TODO: The lowerings before inlinePhase should be aligned with [NativeInlineFunctionResolver.kt] + lower = removeExpectDeclarationsPhase then + stripTypeAliasDeclarationsPhase then + lowerBeforeInlinePhase then + arrayConstructorPhase then + lateinitPhase then + sharedVariablesPhase then + extractLocalClassesFromInlineBodies then + inlinePhase then + provisionalFunctionExpressionPhase then + lowerAfterInlinePhase then + performByIrFile( + name = "IrLowerByFile", + description = "IR Lowering by file", + lower = listOf( + rangeContainsLoweringPhase, + forLoopsPhase, + flattenStringConcatenationPhase, + foldConstantLoweringPhase, + stringConcatenationPhase, + enumConstructorsPhase, + initializersPhase, + localFunctionsPhase, + tailrecPhase, + defaultParameterExtentPhase, + innerClassPhase, + dataClassesPhase, + ifNullExpressionsFusionPhase, + testProcessorPhase, + delegationPhase, + functionReferencePhase, + singleAbstractMethodPhase, + builtinOperatorPhase, + finallyBlocksPhase, + enumClassPhase, + interopPhase, + varargPhase, + compileTimeEvaluatePhase, + kotlinNothingValueExceptionPhase, + coroutinesPhase, + typeOperatorPhase, + bridgesPhase, + autoboxPhase, + returnsInsertionPhase, + ) + ), + actions = setOf(defaultDumper, ::moduleValidationCallback) +) + +internal val dependenciesLowerPhase = NamedCompilerPhase( + name = "LowerLibIR", + description = "Lower library's IR", + prerequisite = emptySet(), + lower = object : CompilerPhase { + override fun invoke(phaseConfig: PhaseConfig, phaserState: PhaserState, context: Context, input: IrModuleFragment): IrModuleFragment { + val files = mutableListOf() + files += input.files + input.files.clear() + + // TODO: KonanLibraryResolver.TopologicalLibraryOrder actually returns libraries in the reverse topological order. + context.librariesWithDependencies + .reversed() + .forEach { + val libModule = context.irModules[it.libraryName] + ?: return@forEach + + input.files += libModule.files + allLoweringsPhase.invoke(phaseConfig, phaserState, context, input) + + input.files.clear() + } + + // Save all files for codegen in reverse topological order. + // This guarantees that libraries initializers are emitted in correct order. + context.librariesWithDependencies + .forEach { + val libModule = context.irModules[it.libraryName] + ?: return@forEach + input.files += libModule.files + } + + input.files += files + + return input + } + }) + +internal val entryPointPhase = makeCustomPhase( + name = "addEntryPoint", + description = "Add entry point for program", + prerequisite = emptySet(), + op = { context, _ -> + assert(context.config.produce == CompilerOutputKind.PROGRAM) + + val originalFile = context.ir.symbols.entryPoint!!.owner.file + val originalModule = originalFile.packageFragmentDescriptor.containingDeclaration + val file = if (context.llvmModuleSpecification.containsModule(originalModule)) { + originalFile + } else { + // `main` function is compiled to other LLVM module. + // For example, test running support uses `main` defined in stdlib. + context.irModule!!.addFile(originalFile.fileEntry, originalFile.fqName) + } + + require(context.llvmModuleSpecification.containsModule( + file.packageFragmentDescriptor.containingDeclaration)) + + file.addChild(makeEntryPoint(context)) + } +) + +internal val exportInternalAbiPhase = makeKonanModuleOpPhase( + name = "exportInternalAbi", + description = "Add accessors to private entities", + prerequisite = emptySet(), + op = { context, module -> + val visitor = object : IrElementVisitorVoid { + override fun visitElement(element: IrElement) { + element.acceptChildrenVoid(this) + } + + override fun visitClass(declaration: IrClass) { + declaration.acceptChildrenVoid(this) + if (declaration.isCompanion) { + val function = context.irFactory.buildFun { + name = InternalAbi.getCompanionObjectAccessorName(declaration) + origin = InternalAbi.INTERNAL_ABI_ORIGIN + returnType = declaration.defaultType + } + context.createIrBuilder(function.symbol).apply { + function.body = irBlockBody { + +irReturn(irGetObjectValue(declaration.defaultType, declaration.symbol)) + } + } + context.internalAbi.declare(function, declaration.module) + } + + } + } + module.acceptChildrenVoid(visitor) + } +) + +internal val useInternalAbiPhase = makeKonanModuleOpPhase( + name = "useInternalAbi", + description = "Use internal ABI functions to access private entities", + prerequisite = emptySet(), + op = { context, module -> + val accessors = mutableMapOf() + val transformer = object : IrElementTransformerVoid() { + override fun visitGetObjectValue(expression: IrGetObjectValue): IrExpression { + val irClass = expression.symbol.owner + if (!irClass.isCompanion || context.llvmModuleSpecification.containsDeclaration(irClass)) { + return expression + } + val parent = irClass.parentAsClass + if (parent.isObjCClass()) { + // Access to Obj-C metaclass is done via intrinsic. + return expression + } + val accessor = accessors.getOrPut(irClass) { + context.irFactory.buildFun { + name = InternalAbi.getCompanionObjectAccessorName(irClass) + returnType = irClass.defaultType + origin = InternalAbi.INTERNAL_ABI_ORIGIN + isExternal = true + }.also { + context.internalAbi.reference(it, irClass.module) + } + } + return IrCallImpl(expression.startOffset, expression.endOffset, expression.type, accessor.symbol, accessor.typeParameters.size, accessor.valueParameters.size) + } + } + module.transformChildrenVoid(transformer) + } +) + +internal val bitcodePhase = NamedCompilerPhase( + name = "Bitcode", + description = "LLVM Bitcode generation", + lower = contextLLVMSetupPhase then + buildDFGPhase then + devirtualizationPhase then + redundantCoercionsCleaningPhase then + dcePhase then + createLLVMDeclarationsPhase then + ghaPhase then + RTTIPhase then + generateDebugInfoHeaderPhase then + escapeAnalysisPhase then + localEscapeAnalysisPhase then + codegenPhase then + finalizeDebugInfoPhase then + cStubsPhase +) + +private val backendCodegen = namedUnitPhase( + name = "Backend codegen", + description = "Backend code generation", + lower = takeFromContext { it.irModule!! } then + allLoweringsPhase then // Lower current module first. + dependenciesLowerPhase then // Then lower all libraries in topological order. + // With that we guarantee that inline functions are unlowered while being inlined. + entryPointPhase then + exportInternalAbiPhase then + useInternalAbiPhase then + bitcodePhase then + verifyBitcodePhase then + printBitcodePhase then + linkBitcodeDependenciesPhase then + bitcodeOptimizationPhase then + unitSink() +) + +// Have to hide Context as type parameter in order to expose toplevelPhase outside of this module. +val toplevelPhase: CompilerPhase<*, Unit, Unit> = namedUnitPhase( + name = "Compiler", + description = "The whole compilation process", + lower = frontendPhase then + createSymbolTablePhase then + objCExportPhase then + buildCExportsPhase then + psiToIrPhase then + destroySymbolTablePhase then + copyDefaultValuesToActualPhase then + serializerPhase then + specialBackendChecksPhase then + namedUnitPhase( + name = "Backend", + description = "All backend", + lower = backendCodegen then + produceOutputPhase then + disposeLLVMPhase then + unitSink() + ) then + objectFilesPhase then + linkerPhase +) + +internal fun PhaseConfig.disableIf(phase: AnyNamedPhase, condition: Boolean) { + if (condition) disable(phase) +} + +internal fun PhaseConfig.disableUnless(phase: AnyNamedPhase, condition: Boolean) { + if (!condition) disable(phase) +} + +internal fun PhaseConfig.konanPhasesConfig(config: KonanConfig) { + with(config.configuration) { + disable(compileTimeEvaluatePhase) + disable(localEscapeAnalysisPhase) + + // Don't serialize anything to a final executable. + disableUnless(serializerPhase, config.produce == CompilerOutputKind.LIBRARY) + disableUnless(entryPointPhase, config.produce == CompilerOutputKind.PROGRAM) + disableUnless(exportInternalAbiPhase, config.produce.isCache) + disableIf(backendCodegen, config.produce == CompilerOutputKind.LIBRARY) + disableUnless(bitcodeOptimizationPhase, config.produce.involvesLinkStage) + disableUnless(linkBitcodeDependenciesPhase, config.produce.involvesLinkStage) + disableUnless(objectFilesPhase, config.produce.involvesLinkStage) + disableUnless(linkerPhase, config.produce.involvesLinkStage) + disableIf(testProcessorPhase, getNotNull(KonanConfigKeys.GENERATE_TEST_RUNNER) == TestRunnerKind.NONE) + disableUnless(buildDFGPhase, getBoolean(KonanConfigKeys.OPTIMIZATION)) + disableUnless(devirtualizationPhase, getBoolean(KonanConfigKeys.OPTIMIZATION)) + disableUnless(escapeAnalysisPhase, getBoolean(KonanConfigKeys.OPTIMIZATION)) + disableUnless(dcePhase, getBoolean(KonanConfigKeys.OPTIMIZATION)) + disableUnless(ghaPhase, getBoolean(KonanConfigKeys.OPTIMIZATION)) + disableUnless(verifyBitcodePhase, config.needCompilerVerification || getBoolean(KonanConfigKeys.VERIFY_BITCODE)) + + val isDescriptorsOnlyLibrary = config.metadataKlib == true + disableIf(psiToIrPhase, isDescriptorsOnlyLibrary) + disableIf(destroySymbolTablePhase, isDescriptorsOnlyLibrary) + disableIf(copyDefaultValuesToActualPhase, isDescriptorsOnlyLibrary) + } +} diff --git a/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/cgen/CBridgeGen.kt b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/cgen/CBridgeGen.kt new file mode 100644 index 00000000000..a39fefa269f --- /dev/null +++ b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/cgen/CBridgeGen.kt @@ -0,0 +1,1395 @@ +package org.jetbrains.kotlin.backend.konan.cgen + +import org.jetbrains.kotlin.backend.common.ir.addFakeOverrides +import org.jetbrains.kotlin.backend.common.ir.createDispatchReceiverParameter +import org.jetbrains.kotlin.backend.common.ir.createParameterDeclarations +import org.jetbrains.kotlin.backend.common.ir.simpleFunctions +import org.jetbrains.kotlin.backend.common.lower.at +import org.jetbrains.kotlin.backend.common.lower.irNot +import org.jetbrains.kotlin.backend.konan.PrimitiveBinaryType +import org.jetbrains.kotlin.backend.konan.RuntimeNames +import org.jetbrains.kotlin.backend.konan.descriptors.konanLibrary +import org.jetbrains.kotlin.backend.konan.getObjCMethodInfo +import org.jetbrains.kotlin.backend.konan.ir.KonanSymbols +import org.jetbrains.kotlin.backend.konan.ir.buildSimpleAnnotation +import org.jetbrains.kotlin.backend.konan.ir.getAnnotationArgumentValue +import org.jetbrains.kotlin.backend.konan.ir.typeWithStarProjections +import org.jetbrains.kotlin.backend.konan.isObjCMetaClass +import org.jetbrains.kotlin.backend.konan.lower.FunctionReferenceLowering +import org.jetbrains.kotlin.descriptors.ClassKind +import org.jetbrains.kotlin.descriptors.DescriptorVisibilities +import org.jetbrains.kotlin.descriptors.Modality +import org.jetbrains.kotlin.ir.IrElement +import org.jetbrains.kotlin.ir.IrStatement +import org.jetbrains.kotlin.ir.UNDEFINED_OFFSET +import org.jetbrains.kotlin.ir.builders.* +import org.jetbrains.kotlin.ir.declarations.* +import org.jetbrains.kotlin.ir.declarations.impl.IrClassImpl +import org.jetbrains.kotlin.ir.declarations.impl.IrConstructorImpl +import org.jetbrains.kotlin.ir.declarations.impl.IrFunctionImpl +import org.jetbrains.kotlin.ir.declarations.impl.IrValueParameterImpl +import org.jetbrains.kotlin.ir.descriptors.* +import org.jetbrains.kotlin.ir.expressions.* +import org.jetbrains.kotlin.ir.expressions.impl.IrConstImpl +import org.jetbrains.kotlin.ir.expressions.impl.IrFunctionReferenceImpl +import org.jetbrains.kotlin.ir.symbols.IrClassSymbol +import org.jetbrains.kotlin.ir.symbols.impl.IrClassSymbolImpl +import org.jetbrains.kotlin.ir.symbols.impl.IrConstructorSymbolImpl +import org.jetbrains.kotlin.ir.symbols.impl.IrSimpleFunctionSymbolImpl +import org.jetbrains.kotlin.ir.symbols.impl.IrValueParameterSymbolImpl +import org.jetbrains.kotlin.ir.types.* +import org.jetbrains.kotlin.ir.util.* +import org.jetbrains.kotlin.konan.ForeignExceptionMode +import org.jetbrains.kotlin.konan.target.Family +import org.jetbrains.kotlin.konan.target.KonanTarget +import org.jetbrains.kotlin.name.Name +import org.jetbrains.kotlin.types.Variance +import org.jetbrains.kotlin.util.OperatorNameConventions + +internal interface KotlinStubs { + val irBuiltIns: IrBuiltIns + val symbols: KonanSymbols + val target: KonanTarget + fun addKotlin(declaration: IrDeclaration) + fun addC(lines: List) + fun getUniqueCName(prefix: String): String + fun getUniqueKotlinFunctionReferenceClassName(prefix: String): String + + fun throwCompilerError(element: IrElement?, message: String): Nothing + fun renderCompilerError(element: IrElement?, message: String = "Failed requirement."): String +} + +private class KotlinToCCallBuilder( + val irBuilder: IrBuilderWithScope, + val stubs: KotlinStubs, + val isObjCMethod: Boolean, + foreignExceptionMode: ForeignExceptionMode.Mode +) { + + val cBridgeName = stubs.getUniqueCName("knbridge") + + val symbols: KonanSymbols get() = stubs.symbols + + val bridgeCallBuilder = KotlinCallBuilder(irBuilder, symbols) + val bridgeBuilder = KotlinCBridgeBuilder(irBuilder.startOffset, irBuilder.endOffset, cBridgeName, stubs, isKotlinToC = true, foreignExceptionMode) + val cBridgeBodyLines = mutableListOf() + val cCallBuilder = CCallBuilder() + val cFunctionBuilder = CFunctionBuilder() + +} + +private fun KotlinToCCallBuilder.passThroughBridge(argument: IrExpression, kotlinType: IrType, cType: CType): CVariable { + bridgeCallBuilder.arguments += argument + return bridgeBuilder.addParameter(kotlinType, cType).second +} + +private fun KotlinToCCallBuilder.addArgument( + argument: IrExpression, + type: IrType, + variadic: Boolean, + parameter: IrValueParameter? +) { + val argumentPassing = mapCalleeFunctionParameter(type, variadic, parameter, argument) + addArgument(argument, argumentPassing, variadic) +} + +private fun KotlinToCCallBuilder.addArgument( + argument: IrExpression, + argumentPassing: KotlinToCArgumentPassing, + variadic: Boolean +) { + val cArgument = with(argumentPassing) { passValue(argument) } ?: return + cCallBuilder.arguments += cArgument.expression + if (!variadic) cFunctionBuilder.addParameter(cArgument.type) +} + +private fun KotlinToCCallBuilder.buildKotlinBridgeCall(transformCall: (IrMemberAccessExpression<*>) -> IrExpression = { it }): IrExpression = + bridgeCallBuilder.build( + bridgeBuilder.buildKotlinBridge().also { + this.stubs.addKotlin(it) + }, + transformCall + ) + +internal fun KotlinStubs.generateCCall(expression: IrCall, builder: IrBuilderWithScope, isInvoke: Boolean, + foreignExceptionMode: ForeignExceptionMode.Mode = ForeignExceptionMode.default): IrExpression { + require(expression.dispatchReceiver == null) { renderCompilerError(expression) } + + val callBuilder = KotlinToCCallBuilder(builder, this, isObjCMethod = false, foreignExceptionMode) + + val callee = expression.symbol.owner + + // TODO: consider computing all arguments before converting. + + val targetPtrParameter: String? + val targetFunctionName: String + + if (isInvoke) { + targetPtrParameter = callBuilder.passThroughBridge( + expression.extensionReceiver!!, + symbols.interopCPointer.typeWithStarProjections, + CTypes.voidPtr + ).name + targetFunctionName = "targetPtr" + + (0 until expression.valueArgumentsCount).forEach { + callBuilder.addArgument( + expression.getValueArgument(it)!!, + type = expression.getTypeArgument(it)!!, + variadic = false, + parameter = null + ) + } + } else { + require(expression.extensionReceiver == null) { renderCompilerError(expression) } + targetPtrParameter = null + targetFunctionName = this.getUniqueCName("target") + + val arguments = (0 until expression.valueArgumentsCount).map { + expression.getValueArgument(it) + } + callBuilder.addArguments(arguments, callee) + } + + val returnValuePassing = if (isInvoke) { + val returnType = expression.getTypeArgument(expression.typeArgumentsCount - 1)!! + mapReturnType(returnType, expression, signature = null) + } else { + mapReturnType(callee.returnType, expression, signature = callee) + } + + val result = callBuilder.buildCall(targetFunctionName, returnValuePassing) + + val targetFunctionVariable = CVariable(CTypes.pointer(callBuilder.cFunctionBuilder.getType()), targetFunctionName) + + if (isInvoke) { + callBuilder.cBridgeBodyLines.add(0, "$targetFunctionVariable = ${targetPtrParameter!!};") + } else { + val cCallSymbolName = callee.getAnnotationArgumentValue(RuntimeNames.cCall, "id")!! + this.addC(listOf("extern const $targetFunctionVariable __asm(\"$cCallSymbolName\");")) // Exported from cinterop stubs. + } + + callBuilder.emitCBridge() + + return result +} + +private fun KotlinToCCallBuilder.addArguments(arguments: List, callee: IrFunction) { + arguments.forEachIndexed { index, argument -> + val parameter = callee.valueParameters[index] + if (parameter.isVararg) { + require(index == arguments.lastIndex) { stubs.renderCompilerError(argument) } + addVariadicArguments(argument) + cFunctionBuilder.variadic = true + } else { + addArgument(argument!!, parameter.type, variadic = false, parameter = parameter) + } + } +} + +private fun KotlinToCCallBuilder.addVariadicArguments( + argumentForVarargParameter: IrExpression? +) = handleArgumentForVarargParameter(argumentForVarargParameter) { variable, elements -> + if (variable == null) { + unwrapVariadicArguments(elements).forEach { + addArgument(it, it.type, variadic = true, parameter = null) + } + } else { + // See comment in [handleArgumentForVarargParameter]. + // Array for this vararg parameter is already computed before the call, + // so query statically known typed arguments from this array. + + with(irBuilder) { + val argumentTypes = unwrapVariadicArguments(elements).map { it.type } + argumentTypes.forEachIndexed { index, type -> + val untypedArgument = irCall(symbols.arrayGet[symbols.array]!!.owner).apply { + dispatchReceiver = irGet(variable) + putValueArgument(0, irInt(index)) + } + val argument = irAs(untypedArgument, type) // Note: this cast always succeeds. + addArgument(argument, type, variadic = true, parameter = null) + } + } + } +} + +private fun KotlinToCCallBuilder.unwrapVariadicArguments( + elements: List +): List = elements.flatMap { + when (it) { + is IrExpression -> listOf(it) + is IrSpreadElement -> { + val expression = it.expression + require(expression is IrCall && expression.symbol == symbols.arrayOf) { stubs.renderCompilerError(it) } + handleArgumentForVarargParameter(expression.getValueArgument(0)) { _, elements -> + unwrapVariadicArguments(elements) + } + } + else -> stubs.throwCompilerError(it, "unexpected IrVarargElement") + } +} + +private fun KotlinToCCallBuilder.handleArgumentForVarargParameter( + argument: IrExpression?, + block: (variable: IrVariable?, elements: List) -> R +): R = when (argument) { + + null -> block(null, emptyList()) + + is IrVararg -> block(null, argument.elements) + + is IrGetValue -> { + /* This is possible when using named arguments with reordering, i.e. + * + * foo(second = *arrayOf(...), first = ...) + * + * psi2ir generates as + * + * val secondTmp = *arrayOf(...) + * val firstTmp = ... + * foo(firstTmp, secondTmp) + * + * + **/ + + val variable = argument.symbol.owner + if (variable is IrVariable && variable.origin == IrDeclarationOrigin.IR_TEMPORARY_VARIABLE && !variable.isVar) { + val initializer = variable.initializer + require(initializer is IrVararg) { stubs.renderCompilerError(initializer) } + block(variable, initializer.elements) + } else if (variable is IrValueParameter && FunctionReferenceLowering.isLoweredFunctionReference(variable)) { + val location = variable.parent // Parameter itself has incorrect location. + val kind = if (this.isObjCMethod) "Objective-C methods" else "C functions" + stubs.throwCompilerError(location, "callable references to variadic $kind are not supported") + } else { + stubs.throwCompilerError(variable, "unexpected value declaration") + } + } + + else -> stubs.throwCompilerError(argument, "unexpected vararg") +} + +private fun KotlinToCCallBuilder.emitCBridge() { + val cLines = mutableListOf() + + cLines += "${bridgeBuilder.buildCSignature(cBridgeName)} {" + cLines += cBridgeBodyLines + cLines += "}" + + stubs.addC(cLines) +} + +private fun KotlinToCCallBuilder.buildCall( + targetFunctionName: String, + returnValuePassing: ValueReturning +): IrExpression = with(returnValuePassing) { + returnValue(cCallBuilder.build(targetFunctionName)) +} + +internal sealed class ObjCCallReceiver { + class Regular(val rawPtr: IrExpression) : ObjCCallReceiver() + class Retained(val rawPtr: IrExpression) : ObjCCallReceiver() +} + +internal fun KotlinStubs.generateObjCCall( + builder: IrBuilderWithScope, + method: IrSimpleFunction, + isStret: Boolean, + selector: String, + call: IrFunctionAccessExpression, + superQualifier: IrClassSymbol?, + receiver: ObjCCallReceiver, + arguments: List +) = builder.irBlock { + val resolved = method.resolveFakeOverride(allowAbstract = true)?: method + val exceptionMode = ForeignExceptionMode.byValue( + resolved.module.konanLibrary?.manifestProperties + ?.getProperty(ForeignExceptionMode.manifestKey) + ) + + val callBuilder = KotlinToCCallBuilder(builder, this@generateObjCCall, isObjCMethod = true, exceptionMode) + + val superClass = irTemporary( + superQualifier?.let { getObjCClass(symbols, it) } ?: irNullNativePtr(symbols), + isMutable = true + ) + + val messenger = irCall(if (isStret) { + symbols.interopGetMessengerStret + } else { + symbols.interopGetMessenger + }.owner).apply { + putValueArgument(0, irGet(superClass)) // TODO: check superClass statically. + } + + val targetPtrParameter = callBuilder.passThroughBridge( + messenger, + symbols.interopCPointer.typeWithStarProjections, + CTypes.voidPtr + ).name + val targetFunctionName = "targetPtr" + + val preparedReceiver = if (method.objCConsumesReceiver()) { + when (receiver) { + is ObjCCallReceiver.Regular -> irCall(symbols.interopObjCRetain.owner).apply { + putValueArgument(0, receiver.rawPtr) + } + + is ObjCCallReceiver.Retained -> receiver.rawPtr + } + } else { + when (receiver) { + is ObjCCallReceiver.Regular -> receiver.rawPtr + + is ObjCCallReceiver.Retained -> { + // Note: shall not happen: Retained is used only for alloc result currently, + // which is used only as receiver for init methods, which are always receiver-consuming. + // Can't even add a test for the code below. + val rawPtrVar = scope.createTemporaryVariable(receiver.rawPtr) + callBuilder.bridgeCallBuilder.prepare += rawPtrVar + callBuilder.bridgeCallBuilder.cleanup += { + irCall(symbols.interopObjCRelease).apply { + putValueArgument(0, irGet(rawPtrVar)) // Balance retained pointer. + } + } + irGet(rawPtrVar) + } + } + } + + val receiverOrSuper = if (superQualifier != null) { + irCall(symbols.interopCreateObjCSuperStruct.owner).apply { + putValueArgument(0, preparedReceiver) + putValueArgument(1, irGet(superClass)) + } + } else { + preparedReceiver + } + + callBuilder.cCallBuilder.arguments += callBuilder.passThroughBridge( + receiverOrSuper, symbols.nativePtrType, CTypes.voidPtr).name + callBuilder.cFunctionBuilder.addParameter(CTypes.voidPtr) + + callBuilder.cCallBuilder.arguments += "@selector($selector)" + callBuilder.cFunctionBuilder.addParameter(CTypes.voidPtr) + + callBuilder.addArguments(arguments, method) + + val returnValuePassing = mapReturnType(method.returnType, call, signature = method) + + val result = callBuilder.buildCall(targetFunctionName, returnValuePassing) + + val targetFunctionVariable = CVariable(CTypes.pointer(callBuilder.cFunctionBuilder.getType()), targetFunctionName) + callBuilder.cBridgeBodyLines.add(0, "$targetFunctionVariable = $targetPtrParameter;") + + callBuilder.emitCBridge() + + +result +} + +internal fun IrBuilderWithScope.getObjCClass(symbols: KonanSymbols, symbol: IrClassSymbol): IrExpression { + val classDescriptor = symbol.descriptor + require(!classDescriptor.isObjCMetaClass()) + return irCall(symbols.interopGetObjCClass, symbols.nativePtrType, listOf(symbol.typeWithStarProjections)) +} + +private fun IrBuilderWithScope.irNullNativePtr(symbols: KonanSymbols) = irCall(symbols.getNativeNullPtr.owner) + +private class CCallbackBuilder( + val stubs: KotlinStubs, + val location: IrElement, + val isObjCMethod: Boolean +) { + + val irBuiltIns: IrBuiltIns get() = stubs.irBuiltIns + val symbols: KonanSymbols get() = stubs.symbols + + private val cBridgeName = stubs.getUniqueCName("knbridge") + + fun buildCBridgeCall(): String = cBridgeCallBuilder.build(cBridgeName) + fun buildCBridge(): String = bridgeBuilder.buildCSignature(cBridgeName) + + val bridgeBuilder = KotlinCBridgeBuilder(location.startOffset, location.endOffset, cBridgeName, stubs, isKotlinToC = false) + val kotlinCallBuilder = KotlinCallBuilder(bridgeBuilder.kotlinIrBuilder, symbols) + val kotlinBridgeStatements = mutableListOf() + val cBridgeCallBuilder = CCallBuilder() + val cBodyLines = mutableListOf() + val cFunctionBuilder = CFunctionBuilder() + +} + +private fun CCallbackBuilder.passThroughBridge( + cBridgeArgument: String, + cBridgeParameterType: CType, + kotlinBridgeParameterType: IrType +): IrValueParameter { + cBridgeCallBuilder.arguments += cBridgeArgument + return bridgeBuilder.addParameter(kotlinBridgeParameterType, cBridgeParameterType).first +} + +private fun CCallbackBuilder.addParameter(it: IrValueParameter, functionParameter: IrValueParameter) { + val location = if (isObjCMethod) functionParameter else location + require(!functionParameter.isVararg) { stubs.renderCompilerError(location) } + + val valuePassing = stubs.mapFunctionParameterType( + it.type, + retained = it.isObjCConsumed(), + variadic = false, + location = location + ) + + val kotlinArgument = with(valuePassing) { receiveValue() } + kotlinCallBuilder.arguments += kotlinArgument +} + +private fun CCallbackBuilder.build(function: IrSimpleFunction, signature: IrSimpleFunction): String { + val valueReturning = stubs.mapReturnType( + signature.returnType, + location = if (isObjCMethod) function else location, + signature = signature + ) + buildValueReturn(function, valueReturning) + return buildCFunction() +} + +private fun CCallbackBuilder.buildValueReturn(function: IrSimpleFunction, valueReturning: ValueReturning) { + val kotlinCall = kotlinCallBuilder.build(function) + with(valueReturning) { + returnValue(kotlinCall) + } + + val kotlinBridge = bridgeBuilder.buildKotlinBridge() + kotlinBridge.body = bridgeBuilder.kotlinIrBuilder.irBlockBody { + kotlinBridgeStatements.forEach { +it } + } + stubs.addKotlin(kotlinBridge) + + stubs.addC(listOf("${buildCBridge()};")) +} + +private fun CCallbackBuilder.buildCFunction(): String { + val result = stubs.getUniqueCName("kncfun") + + val cLines = mutableListOf() + + cLines += "${cFunctionBuilder.buildSignature(result)} {" + cLines += cBodyLines + cLines += "}" + + stubs.addC(cLines) + + return result +} + +private fun KotlinStubs.generateCFunction( + function: IrSimpleFunction, + signature: IrSimpleFunction, + isObjCMethod: Boolean, + location: IrElement +): String { + val callbackBuilder = CCallbackBuilder(this, location, isObjCMethod) + + if (isObjCMethod) { + val receiver = signature.dispatchReceiverParameter!! + require(receiver.type.isObjCReferenceType(target, irBuiltIns)) { renderCompilerError(signature) } + val valuePassing = ObjCReferenceValuePassing(symbols, receiver.type, retained = signature.objCConsumesReceiver()) + val kotlinArgument = with(valuePassing) { callbackBuilder.receiveValue() } + callbackBuilder.kotlinCallBuilder.arguments += kotlinArgument + + // Selector is ignored: + with(TrivialValuePassing(symbols.nativePtrType, CTypes.voidPtr)) { callbackBuilder.receiveValue() } + } else { + require(signature.dispatchReceiverParameter == null) { renderCompilerError(signature) } + } + + signature.extensionReceiverParameter?.let { callbackBuilder.addParameter(it, function.extensionReceiverParameter!!) } + + signature.valueParameters.forEach { + callbackBuilder.addParameter(it, function.valueParameters[it.index]) + } + + return callbackBuilder.build(function, signature) +} + +internal fun KotlinStubs.generateCFunctionPointer( + function: IrSimpleFunction, + signature: IrSimpleFunction, + expression: IrExpression +): IrExpression { + val fakeFunction = generateCFunctionAndFakeKotlinExternalFunction( + function, + signature, + isObjCMethod = false, + location = expression + ) + addKotlin(fakeFunction) + + return IrFunctionReferenceImpl.fromSymbolDescriptor( + expression.startOffset, + expression.endOffset, + expression.type, + fakeFunction.symbol, + typeArgumentsCount = 0, + reflectionTarget = null + ) +} + +internal fun KotlinStubs.generateCFunctionAndFakeKotlinExternalFunction( + function: IrSimpleFunction, + signature: IrSimpleFunction, + isObjCMethod: Boolean, + location: IrElement +): IrSimpleFunction { + val cFunction = generateCFunction(function, signature, isObjCMethod, location) + return createFakeKotlinExternalFunction(signature, cFunction, isObjCMethod) +} + +private fun KotlinStubs.createFakeKotlinExternalFunction( + signature: IrSimpleFunction, + cFunctionName: String, + isObjCMethod: Boolean +): IrSimpleFunction { + val bridgeDescriptor = WrappedSimpleFunctionDescriptor() + val bridge = IrFunctionImpl( + UNDEFINED_OFFSET, + UNDEFINED_OFFSET, + IrDeclarationOrigin.DEFINED, + IrSimpleFunctionSymbolImpl(bridgeDescriptor), + Name.identifier(cFunctionName), + DescriptorVisibilities.PRIVATE, + Modality.FINAL, + signature.returnType, + isInline = false, + isExternal = true, + isTailrec = false, + isSuspend = false, + isExpect = false, + isFakeOverride = false, + isOperator = false, + isInfix = false + ) + bridgeDescriptor.bind(bridge) + + bridge.annotations += buildSimpleAnnotation(irBuiltIns, UNDEFINED_OFFSET, UNDEFINED_OFFSET, + symbols.symbolName.owner, cFunctionName) + + if (isObjCMethod) { + val methodInfo = signature.getObjCMethodInfo()!! + bridge.annotations += buildSimpleAnnotation(irBuiltIns, UNDEFINED_OFFSET, UNDEFINED_OFFSET, + symbols.objCMethodImp.owner, methodInfo.selector, methodInfo.encoding) + } + + return bridge +} + +private fun getCStructType(kotlinClass: IrClass): CType? = + kotlinClass.getCStructSpelling()?.let { CTypes.simple(it) } + +private fun KotlinStubs.getNamedCStructType(kotlinClass: IrClass): CType? { + val cStructType = getCStructType(kotlinClass) ?: return null + val name = getUniqueCName("struct") + addC(listOf("typedef ${cStructType.render(name)};")) + return CTypes.simple(name) +} + +// TODO: rework Boolean support. +// TODO: What should be used on watchOS? +internal fun cBoolType(target: KonanTarget): CType? = when (target.family) { + Family.IOS, Family.TVOS, Family.WATCHOS -> CTypes.C99Bool + else -> CTypes.signedChar +} + +private fun KotlinToCCallBuilder.mapCalleeFunctionParameter( + type: IrType, + variadic: Boolean, + parameter: IrValueParameter?, + argument: IrExpression +): KotlinToCArgumentPassing { + val classifier = type.classifierOrNull + return when { + classifier == symbols.interopCValues || // Note: this should not be accepted, but is required for compatibility + classifier == symbols.interopCValuesRef -> CValuesRefArgumentPassing + + classifier == symbols.string && (variadic || parameter?.isCStringParameter() == true) -> { + require(!variadic || !isObjCMethod) { stubs.renderCompilerError(argument) } + CStringArgumentPassing() + } + + classifier == symbols.string && parameter?.isWCStringParameter() == true -> + WCStringArgumentPassing() + + else -> stubs.mapFunctionParameterType( + type, + retained = parameter?.isObjCConsumed() ?: false, + variadic = variadic, + location = argument + ) + } +} + +private fun KotlinStubs.mapFunctionParameterType( + type: IrType, + retained: Boolean, + variadic: Boolean, + location: IrElement +): ArgumentPassing = when { + type.isUnit() && !variadic -> IgnoredUnitArgumentPassing + else -> mapType(type, retained = retained, variadic = variadic, location = location) +} + +private fun KotlinStubs.mapReturnType( + type: IrType, + location: IrElement, + signature: IrSimpleFunction? +): ValueReturning = when { + type.isUnit() -> VoidReturning + else -> mapType(type, retained = signature?.objCReturnsRetained() ?: false, variadic = false, location = location) +} + +private fun KotlinStubs.mapBlockType( + type: IrType, + retained: Boolean, + location: IrElement +): ObjCBlockPointerValuePassing { + require(type is IrSimpleType) { renderCompilerError(location) } + require(type.classifier == symbols.functionN(type.arguments.size - 1)) { renderCompilerError(location) } + + val returnTypeArgument = type.arguments.last() + require(returnTypeArgument is IrTypeProjection) { renderCompilerError(location) } + require(returnTypeArgument.variance == Variance.INVARIANT) { renderCompilerError(location) } + val valueReturning = mapReturnType(returnTypeArgument.type, location, null) + + val parameterValuePassings = type.arguments.dropLast(1).map { argument -> + require(argument is IrTypeProjection) { renderCompilerError(location) } + require(argument.variance == Variance.INVARIANT) { renderCompilerError(location) } + mapType( + argument.type, + retained = false, + variadic = false, + location = location + ) + } + return ObjCBlockPointerValuePassing( + this, + location, + type, + valueReturning, + parameterValuePassings, + retained + ) +} + +private fun KotlinStubs.mapType( + type: IrType, + retained: Boolean, + variadic: Boolean, + location: IrElement +): ValuePassing = when { + type.isBoolean() -> { + val cBoolType = cBoolType(target) + require(cBoolType != null) { renderCompilerError(location) } + BooleanValuePassing(cBoolType, irBuiltIns) + } + + type.isByte() -> TrivialValuePassing(irBuiltIns.byteType, CTypes.signedChar) + type.isShort() -> TrivialValuePassing(irBuiltIns.shortType, CTypes.short) + type.isInt() -> TrivialValuePassing(irBuiltIns.intType, CTypes.int) + type.isLong() -> TrivialValuePassing(irBuiltIns.longType, CTypes.longLong) + type.isFloat() -> TrivialValuePassing(irBuiltIns.floatType, CTypes.float) + type.isDouble() -> TrivialValuePassing(irBuiltIns.doubleType, CTypes.double) + type.isCPointer(symbols) -> TrivialValuePassing(type, CTypes.voidPtr) + type.isTypeOfNullLiteral() && variadic -> TrivialValuePassing(symbols.interopCPointer.typeWithStarProjections.makeNullable(), CTypes.voidPtr) + type.isUByte() -> UnsignedValuePassing(type, CTypes.signedChar, CTypes.unsignedChar) + type.isUShort() -> UnsignedValuePassing(type, CTypes.short, CTypes.unsignedShort) + type.isUInt() -> UnsignedValuePassing(type, CTypes.int, CTypes.unsignedInt) + type.isULong() -> UnsignedValuePassing(type, CTypes.longLong, CTypes.unsignedLongLong) + + type.isVector() -> TrivialValuePassing(type, CTypes.vector128) + + type.isCEnumType() -> { + val enumClass = type.getClass()!! + val value = enumClass.declarations + .filterIsInstance() + .single { it.name.asString() == "value" } + + CEnumValuePassing( + enumClass, + value, + mapType(value.getter!!.returnType, retained, variadic, location) as SimpleValuePassing + ) + } + + type.isCValue(symbols) -> { + require(!type.isNullable()) { renderCompilerError(location) } + val kotlinClass = (type as IrSimpleType).arguments.singleOrNull()?.typeOrNull?.getClass() + require(kotlinClass != null) { renderCompilerError(location) } + val cStructType = getNamedCStructType(kotlinClass) + require(cStructType != null) { renderCompilerError(location) } + + StructValuePassing(kotlinClass, cStructType) + } + + type.classOrNull?.isSubtypeOfClass(symbols.nativePointed) == true -> { + TrivialValuePassing(type, CTypes.voidPtr) + } + + type.isFunction() -> { + require(!variadic) { renderCompilerError(location) } + mapBlockType(type, retained = retained, location = location) + } + + type.isObjCReferenceType(target, irBuiltIns) -> ObjCReferenceValuePassing(symbols, type, retained = retained) + + else -> throwCompilerError(location, "doesn't correspond to any C type") +} + +private class CExpression(val expression: String, val type: CType) + +private interface KotlinToCArgumentPassing { + fun KotlinToCCallBuilder.passValue(expression: IrExpression): CExpression? +} + +private interface ValueReturning { + val cType: CType + + fun KotlinToCCallBuilder.returnValue(expression: String): IrExpression + fun CCallbackBuilder.returnValue(expression: IrExpression) +} + +private interface ArgumentPassing : KotlinToCArgumentPassing { + fun CCallbackBuilder.receiveValue(): IrExpression +} + +private interface ValuePassing : ArgumentPassing, ValueReturning + +private abstract class SimpleValuePassing : ValuePassing { + abstract val kotlinBridgeType: IrType + abstract val cBridgeType: CType + override abstract val cType: CType + open val callbackParameterCType get() = cType + + abstract fun IrBuilderWithScope.kotlinToBridged(expression: IrExpression): IrExpression + open fun IrBuilderWithScope.kotlinCallbackResultToBridged(expression: IrExpression): IrExpression = + kotlinToBridged(expression) + + abstract fun IrBuilderWithScope.bridgedToKotlin(expression: IrExpression, symbols: KonanSymbols): IrExpression + abstract fun bridgedToC(expression: String): String + abstract fun cToBridged(expression: String): String + + override fun KotlinToCCallBuilder.passValue(expression: IrExpression): CExpression { + val bridgeArgument = irBuilder.kotlinToBridged(expression) + val cBridgeValue = passThroughBridge(bridgeArgument, kotlinBridgeType, cBridgeType).name + return CExpression(bridgedToC(cBridgeValue), cType) + } + + override fun KotlinToCCallBuilder.returnValue(expression: String): IrExpression { + cFunctionBuilder.setReturnType(cType) + bridgeBuilder.setReturnType(kotlinBridgeType, cBridgeType) + cBridgeBodyLines.add("return ${cToBridged(expression)};") + val kotlinBridgeCall = buildKotlinBridgeCall() + return irBuilder.bridgedToKotlin(kotlinBridgeCall, symbols) + } + + override fun CCallbackBuilder.receiveValue(): IrExpression { + val cParameter = cFunctionBuilder.addParameter(callbackParameterCType) + val cBridgeArgument = cToBridged(cParameter.name) + val kotlinParameter = passThroughBridge(cBridgeArgument, cBridgeType, kotlinBridgeType) + return with(bridgeBuilder.kotlinIrBuilder) { + bridgedToKotlin(irGet(kotlinParameter), symbols) + } + } + + override fun CCallbackBuilder.returnValue(expression: IrExpression) { + cFunctionBuilder.setReturnType(cType) + bridgeBuilder.setReturnType(kotlinBridgeType, cBridgeType) + + kotlinBridgeStatements += with(bridgeBuilder.kotlinIrBuilder) { + irReturn(kotlinCallbackResultToBridged(expression)) + } + val cBridgeCall = buildCBridgeCall() + cBodyLines += "return ${bridgedToC(cBridgeCall)};" + } +} + +private class TrivialValuePassing(val kotlinType: IrType, override val cType: CType) : SimpleValuePassing() { + override val kotlinBridgeType: IrType + get() = kotlinType + override val cBridgeType: CType + get() = cType + + override fun IrBuilderWithScope.kotlinToBridged(expression: IrExpression): IrExpression = expression + override fun IrBuilderWithScope.bridgedToKotlin(expression: IrExpression, symbols: KonanSymbols): IrExpression = expression + override fun bridgedToC(expression: String): String = expression + override fun cToBridged(expression: String): String = expression +} + +private class UnsignedValuePassing(val kotlinType: IrType, val cSignedType: CType, override val cType: CType) : SimpleValuePassing() { + override val kotlinBridgeType: IrType + get() = kotlinType + override val cBridgeType: CType + get() = cSignedType + + override fun IrBuilderWithScope.kotlinToBridged(expression: IrExpression): IrExpression = expression + + override fun IrBuilderWithScope.bridgedToKotlin(expression: IrExpression, symbols: KonanSymbols): IrExpression = expression + + override fun bridgedToC(expression: String): String = cType.cast(expression) + + override fun cToBridged(expression: String): String = cBridgeType.cast(expression) +} + +private class BooleanValuePassing(override val cType: CType, private val irBuiltIns: IrBuiltIns) : SimpleValuePassing() { + override val cBridgeType: CType get() = CTypes.signedChar + override val kotlinBridgeType: IrType get() = irBuiltIns.byteType + + override fun IrBuilderWithScope.kotlinToBridged(expression: IrExpression): IrExpression = irIfThenElse( + irBuiltIns.byteType, + condition = expression, + thenPart = IrConstImpl.byte(startOffset, endOffset, irBuiltIns.byteType, 1), + elsePart = IrConstImpl.byte(startOffset, endOffset, irBuiltIns.byteType, 0) + ) + + override fun IrBuilderWithScope.bridgedToKotlin( + expression: IrExpression, + symbols: KonanSymbols + ): IrExpression = irNot(irCall(symbols.areEqualByValue[PrimitiveBinaryType.BYTE]!!.owner).apply { + putValueArgument(0, expression) + putValueArgument(1, IrConstImpl.byte(startOffset, endOffset, irBuiltIns.byteType, 0)) + }) + + override fun bridgedToC(expression: String): String = cType.cast(expression) + + override fun cToBridged(expression: String): String = cBridgeType.cast(expression) +} + +private class StructValuePassing(private val kotlinClass: IrClass, override val cType: CType) : ValuePassing { + override fun KotlinToCCallBuilder.passValue(expression: IrExpression): CExpression { + val cBridgeValue = passThroughBridge( + cValuesRefToPointer(expression), + symbols.interopCPointer.typeWithStarProjections, + CTypes.pointer(cType) + ).name + + return CExpression("*$cBridgeValue", cType) + } + + override fun KotlinToCCallBuilder.returnValue(expression: String): IrExpression = with(irBuilder) { + cFunctionBuilder.setReturnType(cType) + bridgeBuilder.setReturnType(context.irBuiltIns.unitType, CTypes.void) + + val kotlinPointed = scope.createTemporaryVariable(irCall(symbols.interopAllocType.owner).apply { + extensionReceiver = bridgeCallBuilder.getMemScope() + putValueArgument(0, getTypeObject()) + }) + + bridgeCallBuilder.prepare += kotlinPointed + + val cPointer = passThroughBridge(irGet(kotlinPointed), kotlinPointedType, CTypes.pointer(cType)) + cBridgeBodyLines += "*${cPointer.name} = $expression;" + + buildKotlinBridgeCall { + irBlock { + at(it) + +it + +readCValue(irGet(kotlinPointed), symbols) + } + } + } + + override fun CCallbackBuilder.receiveValue(): IrExpression = with(bridgeBuilder.kotlinIrBuilder) { + val cParameter = cFunctionBuilder.addParameter(cType) + val kotlinPointed = passThroughBridge("&${cParameter.name}", CTypes.voidPtr, kotlinPointedType) + + readCValue(irGet(kotlinPointed), symbols) + } + + private fun IrBuilderWithScope.readCValue(kotlinPointed: IrExpression, symbols: KonanSymbols): IrExpression = + irCall(symbols.interopCValueRead.owner).apply { + extensionReceiver = kotlinPointed + putValueArgument(0, getTypeObject()) + } + + override fun CCallbackBuilder.returnValue(expression: IrExpression) = with(bridgeBuilder.kotlinIrBuilder) { + bridgeBuilder.setReturnType(irBuiltIns.unitType, CTypes.void) + cFunctionBuilder.setReturnType(cType) + + val result = "callbackResult" + val cReturnValue = CVariable(cType, result) + cBodyLines += "$cReturnValue;" + val kotlinPtr = passThroughBridge("&$result", CTypes.voidPtr, symbols.nativePtrType) + + kotlinBridgeStatements += irCall(symbols.interopCValueWrite.owner).apply { + extensionReceiver = expression + putValueArgument(0, irGet(kotlinPtr)) + } + val cBridgeCall = buildCBridgeCall() + cBodyLines += "$cBridgeCall;" + cBodyLines += "return $result;" + } + + private val kotlinPointedType: IrType get() = kotlinClass.defaultType + + private fun IrBuilderWithScope.getTypeObject() = + irGetObject( + kotlinClass.declarations.filterIsInstance() + .single { it.isCompanion }.symbol + ) + +} + +private class CEnumValuePassing( + val enumClass: IrClass, + val value: IrProperty, + val baseValuePassing: SimpleValuePassing +) : SimpleValuePassing() { + override val kotlinBridgeType: IrType + get() = baseValuePassing.kotlinBridgeType + override val cBridgeType: CType + get() = baseValuePassing.cBridgeType + override val cType: CType + get() = baseValuePassing.cType + + override fun IrBuilderWithScope.kotlinToBridged(expression: IrExpression): IrExpression { + val value = irCall(value.getter!!).apply { + dispatchReceiver = expression + } + + return with(baseValuePassing) { kotlinToBridged(value) } + } + + override fun IrBuilderWithScope.bridgedToKotlin(expression: IrExpression, symbols: KonanSymbols): IrExpression { + val companionClass = enumClass.declarations.filterIsInstance().single { it.isCompanion } + val byValue = companionClass.simpleFunctions().single { it.name.asString() == "byValue" } + + return irCall(byValue).apply { + dispatchReceiver = irGetObject(companionClass.symbol) + putValueArgument(0, expression) + } + } + + override fun bridgedToC(expression: String): String = with(baseValuePassing) { bridgedToC(expression) } + override fun cToBridged(expression: String): String = with(baseValuePassing) { cToBridged(expression) } +} + +private class ObjCReferenceValuePassing( + private val symbols: KonanSymbols, + private val type: IrType, + private val retained: Boolean +) : SimpleValuePassing() { + override val kotlinBridgeType: IrType + get() = symbols.nativePtrType + override val cBridgeType: CType + get() = CTypes.voidPtr + override val cType: CType + get() = CTypes.voidPtr + + override fun IrBuilderWithScope.kotlinToBridged(expression: IrExpression): IrExpression { + val ptr = irCall(symbols.interopObjCObjectRawValueGetter.owner).apply { + extensionReceiver = expression + } + return if (retained) { + irCall(symbols.interopObjCRetain).apply { + putValueArgument(0, ptr) + } + } else { + ptr + } + } + + override fun IrBuilderWithScope.kotlinCallbackResultToBridged(expression: IrExpression): IrExpression { + if (retained) return kotlinToBridged(expression) // Optimization. + // Kotlin code may loose the ownership on this pointer after returning from the bridge, + // so retain the pointer and autorelease it: + return irCall(symbols.interopObjcRetainAutoreleaseReturnValue.owner).apply { + putValueArgument(0, kotlinToBridged(expression)) + } + // TODO: optimize by using specialized Kotlin-to-ObjC converter. + } + + override fun IrBuilderWithScope.bridgedToKotlin(expression: IrExpression, symbols: KonanSymbols): IrExpression = + convertPossiblyRetainedObjCPointer(symbols, retained, expression) { + irCall(symbols.interopInterpretObjCPointerOrNull, listOf(type)).apply { + putValueArgument(0, it) + } + } + + override fun bridgedToC(expression: String): String = expression + override fun cToBridged(expression: String): String = expression + +} + +private fun IrBuilderWithScope.convertPossiblyRetainedObjCPointer( + symbols: KonanSymbols, + retained: Boolean, + pointer: IrExpression, + convert: (IrExpression) -> IrExpression +): IrExpression = if (retained) { + irBlock(startOffset, endOffset) { + val ptrVar = irTemporary(pointer) + val resultVar = irTemporary(convert(irGet(ptrVar))) + +irCall(symbols.interopObjCRelease.owner).apply { + putValueArgument(0, irGet(ptrVar)) + } + +irGet(resultVar) + } +} else { + convert(pointer) +} + +private class ObjCBlockPointerValuePassing( + val stubs: KotlinStubs, + private val location: IrElement, + private val functionType: IrSimpleType, + private val valueReturning: ValueReturning, + private val parameterValuePassings: List, + private val retained: Boolean +) : SimpleValuePassing() { + val symbols get() = stubs.symbols + + override val kotlinBridgeType: IrType + get() = symbols.nativePtrType + override val cBridgeType: CType + get() = CTypes.id + override val cType: CType + get() = CTypes.id + + /** + * Callback can receive stack-allocated block. Using block type for parameter and passing it as `id` to the bridge + * makes Objective-C compiler generate proper copying to heap. + */ + override val callbackParameterCType: CType + get() = CTypes.blockPointer( + CTypes.function( + valueReturning.cType, + parameterValuePassings.map { it.cType }, + variadic = false + )) + + override fun IrBuilderWithScope.kotlinToBridged(expression: IrExpression): IrExpression = + irCall(symbols.interopCreateKotlinObjectHolder.owner).apply { + putValueArgument(0, expression) + } + + override fun IrBuilderWithScope.bridgedToKotlin(expression: IrExpression, symbols: KonanSymbols): IrExpression = + irLetS(expression) { blockPointerVarSymbol -> + val blockPointerVar = blockPointerVarSymbol.owner + irIfThenElse( + functionType.makeNullable(), + condition = irCall(symbols.areEqualByValue.getValue(PrimitiveBinaryType.POINTER).owner).apply { + putValueArgument(0, irGet(blockPointerVar)) + putValueArgument(1, irNullNativePtr(symbols)) + }, + thenPart = irNull(), + elsePart = convertPossiblyRetainedObjCPointer(symbols, retained, irGet(blockPointerVar)) { + createKotlinFunctionObject(it) + } + ) + } + + private object OBJC_BLOCK_FUNCTION_IMPL : IrDeclarationOriginImpl("OBJC_BLOCK_FUNCTION_IMPL") + + private fun IrBuilderWithScope.createKotlinFunctionObject(blockPointer: IrExpression): IrExpression { + val constructor = generateKotlinFunctionClass() + return irCall(constructor).apply { + putValueArgument(0, blockPointer) + } + } + + private fun IrBuilderWithScope.generateKotlinFunctionClass(): IrConstructor { + val symbols = stubs.symbols + + val classDescriptor = WrappedClassDescriptor() + val irClass = IrClassImpl( + startOffset, endOffset, + OBJC_BLOCK_FUNCTION_IMPL, IrClassSymbolImpl(classDescriptor), + Name.identifier(stubs.getUniqueKotlinFunctionReferenceClassName("BlockFunctionImpl")), + ClassKind.CLASS, DescriptorVisibilities.PRIVATE, Modality.FINAL, + isCompanion = false, isInner = false, isData = false, isExternal = false, + isInline = false, isExpect = false, isFun = false + ) + classDescriptor.bind(irClass) + irClass.createParameterDeclarations() + + irClass.superTypes += stubs.irBuiltIns.anyType + irClass.superTypes += functionType.makeNotNull() + + val blockHolderField = createField( + startOffset, endOffset, + OBJC_BLOCK_FUNCTION_IMPL, + stubs.irBuiltIns.anyType, + Name.identifier("blockHolder"), + isMutable = false, owner = irClass + ) + + val constructorDescriptor = WrappedClassConstructorDescriptor() + val constructor = IrConstructorImpl( + startOffset, endOffset, + OBJC_BLOCK_FUNCTION_IMPL, + IrConstructorSymbolImpl(constructorDescriptor), + Name.special(""), + DescriptorVisibilities.PUBLIC, + irClass.defaultType, + isInline = false, isExternal = false, isPrimary = true, isExpect = false + ) + constructorDescriptor.bind(constructor) + irClass.addChild(constructor) + + val constructorParameterDescriptor = WrappedValueParameterDescriptor() + val constructorParameter = IrValueParameterImpl( + startOffset, endOffset, + OBJC_BLOCK_FUNCTION_IMPL, + IrValueParameterSymbolImpl(constructorParameterDescriptor), + Name.identifier("blockPointer"), + 0, + symbols.nativePtrType, + varargElementType = null, isCrossinline = false, isNoinline = false + ) + constructorParameterDescriptor.bind(constructorParameter) + constructor.valueParameters += constructorParameter + constructorParameter.parent = constructor + + constructor.body = irBuilder(stubs.irBuiltIns, constructor.symbol).irBlockBody(startOffset, endOffset) { + +irDelegatingConstructorCall(symbols.any.owner.constructors.single()) + +irSetField(irGet(irClass.thisReceiver!!), blockHolderField, + irCall(symbols.interopCreateObjCObjectHolder.owner).apply { + putValueArgument(0, irGet(constructorParameter)) + }) + } + + val parameterCount = parameterValuePassings.size + require(functionType.arguments.size == parameterCount + 1) { stubs.renderCompilerError(location) } + + val overriddenInvokeMethod = (functionType.classifier.owner as IrClass).simpleFunctions() + .single { it.name == OperatorNameConventions.INVOKE } + + val invokeMethodDescriptor = WrappedSimpleFunctionDescriptor() + val invokeMethod = IrFunctionImpl( + startOffset, endOffset, + OBJC_BLOCK_FUNCTION_IMPL, + IrSimpleFunctionSymbolImpl(invokeMethodDescriptor), + overriddenInvokeMethod.name, + DescriptorVisibilities.PUBLIC, Modality.FINAL, + returnType = functionType.arguments.last().typeOrNull!!, + isInline = false, isExternal = false, isTailrec = false, isSuspend = false, isExpect = false, + isFakeOverride = false, isOperator = false, isInfix = false + ) + invokeMethodDescriptor.bind(invokeMethod) + invokeMethod.overriddenSymbols += overriddenInvokeMethod.symbol + irClass.addChild(invokeMethod) + invokeMethod.createDispatchReceiverParameter() + + invokeMethod.valueParameters += (0 until parameterCount).map { index -> + val parameterDescriptor = WrappedValueParameterDescriptor() + val parameter = IrValueParameterImpl( + startOffset, endOffset, + OBJC_BLOCK_FUNCTION_IMPL, + IrValueParameterSymbolImpl(parameterDescriptor), + Name.identifier("p$index"), + index, + functionType.arguments[index].typeOrNull!!, + varargElementType = null, isCrossinline = false, isNoinline = false + ) + parameterDescriptor.bind(parameter) + parameter.parent = invokeMethod + parameter + } + + invokeMethod.body = irBuilder(stubs.irBuiltIns, invokeMethod.symbol).irBlockBody(startOffset, endOffset) { + val blockPointer = irCall(symbols.interopObjCObjectRawValueGetter.owner).apply { + extensionReceiver = irGetField(irGet(invokeMethod.dispatchReceiverParameter!!), blockHolderField) + } + + val arguments = (0 until parameterCount).map { index -> + irGet(invokeMethod.valueParameters[index]) + } + + +irReturn(callBlock(blockPointer, arguments)) + } + + irClass.addFakeOverrides(stubs.irBuiltIns) + + stubs.addKotlin(irClass) + return constructor + } + + private fun IrBuilderWithScope.callBlock(blockPtr: IrExpression, arguments: List): IrExpression { + val callBuilder = KotlinToCCallBuilder(this, stubs, isObjCMethod = false, ForeignExceptionMode.default) + + val rawBlockPointerParameter = callBuilder.passThroughBridge(blockPtr, blockPtr.type, CTypes.id) + val blockVariableName = "block" + + arguments.forEachIndexed { index, argument -> + callBuilder.addArgument(argument, parameterValuePassings[index], variadic = false) + } + + val result = callBuilder.buildCall(blockVariableName, valueReturning) + + val blockVariableType = CTypes.blockPointer(callBuilder.cFunctionBuilder.getType()) + val blockVariable = CVariable(blockVariableType, blockVariableName) + callBuilder.cBridgeBodyLines.add(0, "$blockVariable = ${rawBlockPointerParameter.name};") + + callBuilder.emitCBridge() + + return result + } + + override fun bridgedToC(expression: String): String { + val callbackBuilder = CCallbackBuilder(stubs, location, isObjCMethod = false) + val kotlinFunctionHolder = "kotlinFunctionHolder" + + callbackBuilder.cBridgeCallBuilder.arguments += kotlinFunctionHolder + val (kotlinFunctionHolderParameter, _) = + callbackBuilder.bridgeBuilder.addParameter(symbols.nativePtrType, CTypes.id) + + callbackBuilder.kotlinCallBuilder.arguments += with(callbackBuilder.bridgeBuilder.kotlinIrBuilder) { + // TODO: consider casting to [functionType]. + irCall(symbols.interopUnwrapKotlinObjectHolderImpl.owner).apply { + putValueArgument(0, irGet(kotlinFunctionHolderParameter) ) + } + } + + parameterValuePassings.forEach { + callbackBuilder.kotlinCallBuilder.arguments += with(it) { + callbackBuilder.receiveValue() + } + } + + require(functionType.isFunction()) { stubs.renderCompilerError(location) } + val invokeFunction = (functionType.classifier.owner as IrClass) + .simpleFunctions().single { it.name == OperatorNameConventions.INVOKE } + + callbackBuilder.buildValueReturn(invokeFunction, valueReturning) + + val block = buildString { + append('^') + append(callbackBuilder.cFunctionBuilder.buildSignature("")) + append(" { ") + callbackBuilder.cBodyLines.forEach { + append(it) + append(' ') + } + append(" }") + } + val blockAsId = if (retained) { + "(__bridge id)(__bridge_retained void*)$block" // Retain and convert to id. + } else { + "(id)$block" + } + + return "({ id $kotlinFunctionHolder = $expression; $kotlinFunctionHolder ? $blockAsId : (id)0; })" + } + + override fun cToBridged(expression: String) = expression + +} + +private class WCStringArgumentPassing : KotlinToCArgumentPassing { + + override fun KotlinToCCallBuilder.passValue(expression: IrExpression): CExpression { + val wcstr = irBuilder.irSafeTransform(expression) { + irCall(symbols.interopWcstr.owner).apply { + extensionReceiver = it + } + } + return with(CValuesRefArgumentPassing) { passValue(wcstr) } + } + +} + +private class CStringArgumentPassing : KotlinToCArgumentPassing { + + override fun KotlinToCCallBuilder.passValue(expression: IrExpression): CExpression { + val cstr = irBuilder.irSafeTransform(expression) { + irCall(symbols.interopCstr.owner).apply { + extensionReceiver = it + } + } + return with(CValuesRefArgumentPassing) { passValue(cstr) } + } + +} + +private object CValuesRefArgumentPassing : KotlinToCArgumentPassing { + override fun KotlinToCCallBuilder.passValue(expression: IrExpression): CExpression { + val bridgeArgument = cValuesRefToPointer(expression) + val cBridgeValue = passThroughBridge( + bridgeArgument, + symbols.interopCPointer.typeWithStarProjections.makeNullable(), + CTypes.voidPtr + ) + return CExpression(cBridgeValue.name, cBridgeValue.type) + } +} + +private fun KotlinToCCallBuilder.cValuesRefToPointer( + value: IrExpression +): IrExpression = if (value.type.classifierOrNull == symbols.interopCPointer) { + value // Optimization +} else { + val getPointerFunction = symbols.interopCValuesRef.owner + .simpleFunctions() + .single { it.name.asString() == "getPointer" } + + irBuilder.irSafeTransform(value) { + irCall(getPointerFunction).apply { + dispatchReceiver = it + putValueArgument(0, bridgeCallBuilder.getMemScope()) + } + } +} + +private fun IrBuilderWithScope.irSafeTransform( + value: IrExpression, + block: IrBuilderWithScope.(IrExpression) -> IrExpression +): IrExpression = if (!value.type.isNullable()) { + block(value) // Optimization +} else { + irLetS(value) { valueVarSymbol -> + val valueVar = valueVarSymbol.owner + val transformed = block(irGet(valueVar)) + irIfThenElse( + type = transformed.type.makeNullable(), + condition = irEqeqeq(irGet(valueVar), irNull()), + thenPart = irNull(), + elsePart = transformed + ) + } +} + +private object VoidReturning : ValueReturning { + override val cType: CType + get() = CTypes.void + + override fun KotlinToCCallBuilder.returnValue(expression: String): IrExpression { + bridgeBuilder.setReturnType(irBuilder.context.irBuiltIns.unitType, CTypes.void) + cFunctionBuilder.setReturnType(CTypes.void) + cBridgeBodyLines += "$expression;" + return buildKotlinBridgeCall() + } + + override fun CCallbackBuilder.returnValue(expression: IrExpression) { + bridgeBuilder.setReturnType(irBuiltIns.unitType, CTypes.void) + cFunctionBuilder.setReturnType(CTypes.void) + kotlinBridgeStatements += bridgeBuilder.kotlinIrBuilder.irReturn(expression) + cBodyLines += "${buildCBridgeCall()};" + } +} + +private object IgnoredUnitArgumentPassing : ArgumentPassing { + override fun KotlinToCCallBuilder.passValue(expression: IrExpression): CExpression? { + // Note: it is not correct to just drop the expression (due to possible side effects), + // so (in lack of other options) evaluate the expression and pass ignored value to the bridge: + val bridgeArgument = irBuilder.irBlock { + +expression + +irInt(0) + } + passThroughBridge(bridgeArgument, irBuilder.context.irBuiltIns.intType, CTypes.int).name + return null + } + + override fun CCallbackBuilder.receiveValue(): IrExpression { + return bridgeBuilder.kotlinIrBuilder.irGetObject(irBuiltIns.unitClass) + } +} + +internal fun CType.cast(expression: String): String = "((${this.render("")})$expression)" diff --git a/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/cgen/CBridgeGenUtils.kt b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/cgen/CBridgeGenUtils.kt new file mode 100644 index 00000000000..dee663372ef --- /dev/null +++ b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/cgen/CBridgeGenUtils.kt @@ -0,0 +1,253 @@ +package org.jetbrains.kotlin.backend.konan.cgen + +import org.jetbrains.kotlin.backend.common.ir.simpleFunctions +import org.jetbrains.kotlin.backend.common.lower.irBlock +import org.jetbrains.kotlin.backend.common.lower.irThrow +import org.jetbrains.kotlin.backend.konan.ir.KonanSymbols +import org.jetbrains.kotlin.backend.konan.ir.buildSimpleAnnotation +import org.jetbrains.kotlin.descriptors.Modality +import org.jetbrains.kotlin.descriptors.DescriptorVisibilities +import org.jetbrains.kotlin.ir.IrStatement +import org.jetbrains.kotlin.ir.builders.* +import org.jetbrains.kotlin.ir.declarations.IrDeclarationOrigin +import org.jetbrains.kotlin.ir.declarations.IrFunction +import org.jetbrains.kotlin.ir.declarations.IrValueParameter +import org.jetbrains.kotlin.ir.declarations.IrVariable +import org.jetbrains.kotlin.ir.declarations.impl.IrFunctionImpl +import org.jetbrains.kotlin.ir.declarations.impl.IrValueParameterImpl +import org.jetbrains.kotlin.ir.descriptors.WrappedSimpleFunctionDescriptor +import org.jetbrains.kotlin.ir.descriptors.WrappedValueParameterDescriptor +import org.jetbrains.kotlin.ir.expressions.IrExpression +import org.jetbrains.kotlin.ir.expressions.IrMemberAccessExpression +import org.jetbrains.kotlin.ir.expressions.impl.IrTryImpl +import org.jetbrains.kotlin.ir.symbols.impl.IrSimpleFunctionSymbolImpl +import org.jetbrains.kotlin.ir.symbols.impl.IrValueParameterSymbolImpl +import org.jetbrains.kotlin.ir.types.IrType +import org.jetbrains.kotlin.ir.types.impl.IrUninitializedType +import org.jetbrains.kotlin.ir.util.constructors +import org.jetbrains.kotlin.ir.util.irBuilder +import org.jetbrains.kotlin.ir.util.irCatch +import org.jetbrains.kotlin.konan.ForeignExceptionMode +import org.jetbrains.kotlin.name.Name + +internal class CFunctionBuilder { + private val parameters = mutableListOf() + private lateinit var returnType: CType + + var variadic: Boolean = false + + fun setReturnType(type: CType) { + require(!::returnType.isInitialized) + returnType = type + } + + fun addParameter(type: CType): CVariable { + val result = CVariable(type, "p${counter++}") + parameters += result + return result + } + + val numberOfParameters: Int get() = parameters.size + + private var counter = 1 + + fun getType(): CType = CTypes.function(returnType, parameters.map { it.type }, variadic) + + fun buildSignature(name: String): String = returnType.render(buildString { + append(name) + append('(') + parameters.joinTo(this) + if (parameters.isEmpty()) { + if (!variadic) append("void") + } else { + if (variadic) append(", ...") + } + append(')') + }) + +} + +internal class KotlinBridgeBuilder( + startOffset: Int, + endOffset: Int, + cName: String, + stubs: KotlinStubs, + isExternal: Boolean, + foreignExceptionMode: ForeignExceptionMode.Mode +) { + private var counter = 0 + private val bridge: IrFunction = createKotlinBridge(startOffset, endOffset, cName, stubs, isExternal, foreignExceptionMode) + val irBuilder: IrBuilderWithScope = irBuilder(stubs.irBuiltIns, bridge.symbol).at(startOffset, endOffset) + + fun addParameter(type: IrType): IrValueParameter { + val index = counter++ + val descriptor = WrappedValueParameterDescriptor() + + return IrValueParameterImpl( + bridge.startOffset, bridge.endOffset, bridge.origin, + IrValueParameterSymbolImpl(descriptor), + Name.identifier("p$index"), index, type, + null, false, false + ).apply { + descriptor.bind(this) + parent = bridge + bridge.valueParameters += this + } + } + + fun setReturnType(type: IrType) { + bridge.returnType = type + } + + fun build(): IrFunction = bridge +} + +private fun createKotlinBridge( + startOffset: Int, + endOffset: Int, + cBridgeName: String, + stubs: KotlinStubs, + isExternal: Boolean, + foreignExceptionMode: ForeignExceptionMode.Mode +): IrFunction { + val bridgeDescriptor = WrappedSimpleFunctionDescriptor() + val bridge = IrFunctionImpl( + startOffset, + endOffset, + IrDeclarationOrigin.DEFINED, + IrSimpleFunctionSymbolImpl(bridgeDescriptor), + Name.identifier(cBridgeName), + DescriptorVisibilities.PRIVATE, + Modality.FINAL, + IrUninitializedType, + isInline = false, + isExternal = isExternal, + isTailrec = false, + isSuspend = false, + isExpect = false, + isFakeOverride = false, + isOperator = false, + isInfix = false + ) + bridgeDescriptor.bind(bridge) + if (isExternal) { + bridge.annotations += buildSimpleAnnotation(stubs.irBuiltIns, startOffset, endOffset, + stubs.symbols.symbolName.owner, cBridgeName) + bridge.annotations += buildSimpleAnnotation(stubs.irBuiltIns, startOffset, endOffset, + stubs.symbols.filterExceptions.owner, + foreignExceptionMode.value) + } else { + bridge.annotations += buildSimpleAnnotation(stubs.irBuiltIns, startOffset, endOffset, + stubs.symbols.exportForCppRuntime.owner, cBridgeName) + } + return bridge +} + +internal class KotlinCBridgeBuilder( + startOffset: Int, + endOffset: Int, + cName: String, + stubs: KotlinStubs, + isKotlinToC: Boolean, + foreignExceptionMode: ForeignExceptionMode.Mode = ForeignExceptionMode.default +) { + private val kotlinBridgeBuilder = KotlinBridgeBuilder(startOffset, endOffset, cName, stubs, isExternal = isKotlinToC, foreignExceptionMode) + private val cBridgeBuilder = CFunctionBuilder() + + val kotlinIrBuilder: IrBuilderWithScope get() = kotlinBridgeBuilder.irBuilder + + fun addParameter(kotlinType: IrType, cType: CType): Pair { + return kotlinBridgeBuilder.addParameter(kotlinType) to cBridgeBuilder.addParameter(cType) + } + + fun setReturnType(kotlinReturnType: IrType, cReturnType: CType) { + kotlinBridgeBuilder.setReturnType(kotlinReturnType) + cBridgeBuilder.setReturnType(cReturnType) + } + + fun buildCSignature(name: String): String = cBridgeBuilder.buildSignature(name) + + fun buildKotlinBridge() = kotlinBridgeBuilder.build() +} + +internal class KotlinCallBuilder(private val irBuilder: IrBuilderWithScope, private val symbols: KonanSymbols) { + val prepare = mutableListOf() + val arguments = mutableListOf() + val cleanup = mutableListOf IrStatement>() + + private var memScope: IrVariable? = null + + fun getMemScope(): IrExpression = with(irBuilder) { + memScope?.let { return irGet(it) } + + val newMemScope = scope.createTemporaryVariable(irCall(symbols.interopMemScope.owner.constructors.single())) + memScope = newMemScope + + prepare += newMemScope + + val clearImpl = symbols.interopMemScope.owner.simpleFunctions().single { it.name.asString() == "clearImpl" } + cleanup += { + irCall(clearImpl).apply { + dispatchReceiver = irGet(memScope!!) + } + } + + irGet(newMemScope) + } + + fun build( + function: IrFunction, + transformCall: (IrMemberAccessExpression<*>) -> IrExpression = { it } + ): IrExpression { + val arguments = this.arguments.toMutableList() + + val kotlinCall = irBuilder.irCall(function).run { + if (function.dispatchReceiverParameter != null) { + dispatchReceiver = arguments.removeAt(0) + } + if (function.extensionReceiverParameter != null) { + extensionReceiver = arguments.removeAt(0) + } + assert(arguments.size == function.valueParameters.size) + arguments.forEachIndexed { index, it -> putValueArgument(index, it) } + + transformCall(this) + } + + return if (prepare.isEmpty() && cleanup.isEmpty()) { + kotlinCall + } else { + irBuilder.irBlock(kotlinCall) { + prepare.forEach { +it } + if (cleanup.isEmpty()) { + +kotlinCall + } else { + // Note: generating try-catch as finally blocks are already lowered. + val result = irTemporary(IrTryImpl(startOffset, endOffset, kotlinCall.type).apply { + tryResult = kotlinCall + catches += irCatch(context.irBuiltIns.throwableType).apply { + result = irBlock(kotlinCall) { + cleanup.forEach { +it() } + +irThrow(irGet(catchParameter)) + } + } + }) + // TODO: consider handling a cleanup failure properly. + cleanup.forEach { +it() } + +irGet(result) + } + } + } + } +} + +internal class CCallBuilder { + val arguments = mutableListOf() + + fun build(function: String) = buildString { + append(function) + append('(') + arguments.joinTo(this) + append(')') + } +} diff --git a/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/cgen/CSyntaxSupport.kt b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/cgen/CSyntaxSupport.kt new file mode 100644 index 00000000000..4141abc18c0 --- /dev/null +++ b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/cgen/CSyntaxSupport.kt @@ -0,0 +1,66 @@ +package org.jetbrains.kotlin.backend.konan.cgen + +internal interface CType { + fun render(name: String): String +} + +internal class CVariable(val type: CType, val name: String) { + override fun toString() = type.render(name) +} + +internal object CTypes { + fun simple(type: String): CType = SimpleCType(type) + fun pointer(pointee: CType): CType = PointerCType(pointee) + fun function(returnType: CType, parameterTypes: List, variadic: Boolean): CType = + FunctionCType(returnType, parameterTypes, variadic) + + fun blockPointer(pointee: CType): CType = object : CType { + override fun render(name: String): String = pointee.render("^$name") + } + + val void = simple("void") + val voidPtr = pointer(void) + val signedChar = simple("signed char") + val unsignedChar = simple("unsigned char") + val short = simple("short") + val unsignedShort = simple("unsigned short") + val int = simple("int") + val unsignedInt = simple("unsigned int") + val longLong = simple("long long") + val unsignedLongLong = simple("unsigned long long") + val float = simple("float") + val double = simple("double") + val C99Bool = simple("_Bool") + val char = simple("char") + + val vector128 = simple("float __attribute__ ((__vector_size__ (16)))") + + val id = simple("id") +} + +private class SimpleCType(private val type: String) : CType { + override fun render(name: String): String = if (name.isEmpty()) type else "$type $name" +} + +private class PointerCType(private val pointee: CType) : CType { + override fun render(name: String): String = pointee.render("*$name") +} + +private class FunctionCType( + private val returnType: CType, + private val parameterTypes: List, + private val variadic: Boolean +) : CType { + override fun render(name: String): String = returnType.render(buildString { + append("(") + append(name) + append(")(") + parameterTypes.joinTo(this) { it.render("") } + if (parameterTypes.isEmpty()) { + if (!variadic) append("void") + } else { + if (variadic) append(", ...") + } + append(')') + }) +} diff --git a/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/cgen/InteropIrUtils.kt b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/cgen/InteropIrUtils.kt new file mode 100644 index 00000000000..f25cc253fa6 --- /dev/null +++ b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/cgen/InteropIrUtils.kt @@ -0,0 +1,118 @@ +/* + * Copyright 2010-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +package org.jetbrains.kotlin.backend.konan.cgen + +import org.jetbrains.kotlin.backend.jvm.ir.propertyIfAccessor +import org.jetbrains.kotlin.backend.konan.KonanFqNames +import org.jetbrains.kotlin.backend.konan.RuntimeNames +import org.jetbrains.kotlin.backend.konan.ir.* +import org.jetbrains.kotlin.backend.konan.ir.KonanSymbols +import org.jetbrains.kotlin.backend.konan.ir.isObjCObjectType +import org.jetbrains.kotlin.builtins.StandardNames +import org.jetbrains.kotlin.ir.declarations.* +import org.jetbrains.kotlin.ir.descriptors.IrBuiltIns +import org.jetbrains.kotlin.ir.types.* +import org.jetbrains.kotlin.ir.util.* +import org.jetbrains.kotlin.konan.target.KonanTarget +import org.jetbrains.kotlin.name.FqName +import org.jetbrains.kotlin.name.Name + +internal fun IrType.isCEnumType(): Boolean { + val simpleType = this as? IrSimpleType ?: return false + if (simpleType.hasQuestionMark) return false + val enumClass = simpleType.classifier.owner as? IrClass ?: return false + if (!enumClass.isEnumClass) return false + + return enumClass.superTypes + .any { (it.classifierOrNull?.owner as? IrClass)?.fqNameForIrSerialization == FqName("kotlinx.cinterop.CEnum") } +} + +private val cCall = RuntimeNames.cCall + +// Make sure external stubs always get proper annotaions. +private fun IrDeclaration.hasCCallAnnotation(name: String): Boolean = + this.annotations.hasAnnotation(cCall.child(Name.identifier(name))) + // LazyIr doesn't pass annotations from descriptor to IrValueParameter. + || this.descriptor.annotations.hasAnnotation(cCall.child(Name.identifier(name))) + +internal fun IrValueParameter.isWCStringParameter() = hasCCallAnnotation("WCString") + +internal fun IrValueParameter.isCStringParameter() = hasCCallAnnotation("CString") + +internal fun IrValueParameter.isObjCConsumed() = hasCCallAnnotation("Consumed") + +internal fun IrSimpleFunction.objCConsumesReceiver() = hasCCallAnnotation("ConsumesReceiver") + +internal fun IrSimpleFunction.objCReturnsRetained() = hasCCallAnnotation("ReturnsRetained") + +internal fun IrClass.getCStructSpelling(): String? = + getAnnotationArgumentValue(FqName("kotlinx.cinterop.internal.CStruct"), "spelling") + +internal fun IrType.isTypeOfNullLiteral(): Boolean = this is IrSimpleType && hasQuestionMark + && classifier.isClassWithFqName(StandardNames.FqNames.nothing) + +internal fun IrType.isVector(): Boolean { + if (this is IrSimpleType && !this.hasQuestionMark) { + return classifier.isClassWithFqName(KonanFqNames.Vector128.toUnsafe()) + } + return false +} + +internal fun IrType.isObjCReferenceType(target: KonanTarget, irBuiltIns: IrBuiltIns): Boolean { + if (!target.family.isAppleFamily) return false + + // Handle the same types as produced by [objCPointerMirror] in Interop/StubGenerator/.../Mappings.kt. + + if (isObjCObjectType()) return true + + val descriptor = classifierOrNull?.descriptor ?: return false + val builtIns = irBuiltIns.builtIns + + return when (descriptor) { + builtIns.any, + builtIns.string, + builtIns.list, builtIns.mutableList, + builtIns.set, + builtIns.map -> true + else -> false + } +} + +internal fun IrType.isCPointer(symbols: KonanSymbols): Boolean = this.classOrNull == symbols.interopCPointer +internal fun IrType.isCValue(symbols: KonanSymbols): Boolean = this.classOrNull == symbols.interopCValue + +internal fun IrType.isNativePointed(symbols: KonanSymbols): Boolean = isSubtypeOfClass(symbols.nativePointed) + +internal fun IrType.isCStructFieldTypeStoredInMemoryDirectly(): Boolean = isPrimitiveType() || isUnsigned() || isVector() + +internal fun IrType.isCStructFieldSupportedReferenceType(symbols: KonanSymbols): Boolean = + isObjCObjectType() + || getClass()?.isAny() == true + || isStringClassType() + || classOrNull == symbols.list + || classOrNull == symbols.mutableList + || classOrNull == symbols.set + || classOrNull == symbols.map + +/** + * Check given function is a getter or setter + * for `value` property of CEnumVar subclass. + */ +internal fun IrFunction.isCEnumVarValueAccessor(symbols: KonanSymbols): Boolean { + val parent = parent as? IrClass ?: return false + return if (symbols.interopCEnumVar in parent.superClasses && isPropertyAccessor) { + (propertyIfAccessor as IrProperty).name.asString() == "value" + } else { + false + } +} + +internal fun IrFunction.isCStructMemberAtAccessor() = hasAnnotation(RuntimeNames.cStructMemberAt) + +internal fun IrFunction.isCStructArrayMemberAtAccessor() = hasAnnotation(RuntimeNames.cStructArrayMemberAt) + +internal fun IrFunction.isCStructBitFieldAccessor() = hasAnnotation(RuntimeNames.cStructBitField) + diff --git a/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/descriptors/ClassLayoutBuilder.kt b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/descriptors/ClassLayoutBuilder.kt new file mode 100644 index 00000000000..7431e56aae7 --- /dev/null +++ b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/descriptors/ClassLayoutBuilder.kt @@ -0,0 +1,466 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +package org.jetbrains.kotlin.backend.konan.descriptors + +import llvm.LLVMStoreSizeOfType +import org.jetbrains.kotlin.backend.common.ir.simpleFunctions +import org.jetbrains.kotlin.backend.konan.* +import org.jetbrains.kotlin.backend.konan.ir.* +import org.jetbrains.kotlin.backend.konan.llvm.functionName +import org.jetbrains.kotlin.backend.konan.llvm.llvmType +import org.jetbrains.kotlin.backend.konan.llvm.localHash +import org.jetbrains.kotlin.backend.konan.lower.InnerClassLowering +import org.jetbrains.kotlin.backend.konan.lower.bridgeTarget +import org.jetbrains.kotlin.descriptors.Modality +import org.jetbrains.kotlin.ir.IrElement +import org.jetbrains.kotlin.ir.declarations.* +import org.jetbrains.kotlin.ir.expressions.IrClassReference +import org.jetbrains.kotlin.ir.util.* +import org.jetbrains.kotlin.ir.visitors.IrElementVisitorVoid +import org.jetbrains.kotlin.ir.visitors.acceptChildrenVoid +import org.jetbrains.kotlin.ir.visitors.acceptVoid +import org.jetbrains.kotlin.name.FqName + +internal class OverriddenFunctionInfo( + val function: IrSimpleFunction, + val overriddenFunction: IrSimpleFunction +) { + val needBridge: Boolean + get() = function.target.needBridgeTo(overriddenFunction) + + val bridgeDirections: BridgeDirections + get() = function.target.bridgeDirectionsTo(overriddenFunction) + + val canBeCalledVirtually: Boolean + get() { + if (overriddenFunction.isObjCClassMethod()) { + return function.canObjCClassMethodBeCalledVirtually(overriddenFunction) + } + + return overriddenFunction.isOverridable + } + + val inheritsBridge: Boolean + get() = !function.isReal + && function.target.overrides(overriddenFunction) + && function.bridgeDirectionsTo(overriddenFunction).allNotNeeded() + + fun getImplementation(context: Context): IrSimpleFunction? { + + val target = function.target + val implementation = if (!needBridge) + target + else { + val bridgeOwner = if (inheritsBridge) { + target // Bridge is inherited from superclass. + } else { + function + } + context.specialDeclarationsFactory.getBridge(OverriddenFunctionInfo(bridgeOwner, overriddenFunction)) + } + return if (implementation.modality == Modality.ABSTRACT) null else implementation + } + + override fun toString(): String { + return "(descriptor=$function, overriddenDescriptor=$overriddenFunction)" + } + + override fun equals(other: Any?): Boolean { + if (this === other) return true + if (other !is OverriddenFunctionInfo) return false + + if (function != other.function) return false + if (overriddenFunction != other.overriddenFunction) return false + + return true + } + + override fun hashCode(): Int { + var result = function.hashCode() + result = 31 * result + overriddenFunction.hashCode() + return result + } +} + +internal class ClassGlobalHierarchyInfo(val classIdLo: Int, val classIdHi: Int, + val interfaceId: Int, val interfaceColor: Int) { + companion object { + val DUMMY = ClassGlobalHierarchyInfo(0, 0, 0, 0) + + // 32-items table seems like a good threshold. + val MAX_BITS_PER_COLOR = 5 + } +} + +internal class GlobalHierarchyAnalysisResult(val bitsPerColor: Int) + +internal class GlobalHierarchyAnalysis(val context: Context, val irModule: IrModuleFragment) { + fun run() { + /* + * The algorithm for fast interface call and check: + * Consider the following graph: the vertices are interfaces and two interfaces are + * connected with an edge if there exists a class which inherits both of them. + * Now find a proper vertex-coloring of that graph (such that no edge connects vertices of same color). + * Assign to each interface a unique id in such a way that its color is stored in the lower bits of its id. + * Assuming the number of colors used is reasonably small build then a perfect hash table for each class: + * for each interfaceId inherited: itable[interfaceId % size] == interfaceId + * Since we store the color in the lower bits the division can be replaced with (interfaceId & (size - 1)). + * This is indeed a perfect hash table by construction of the coloring of the interface graph. + * Now to perform an interface call store in all itables pointers to vtables of that particular interface. + * Interface call: *(itable[interfaceId & (size - 1)].vtable[methodIndex])(...) + * Interface check: itable[interfaceId & (size - 1)].id == interfaceId + * + * Note that we have a fallback to a more conservative version if the size of an itable is too large: + * just save all interface ids and vtables in sorted order and find the needed one with the binary search. + * We can signal that using the sign bit of the type info's size field: + * if (size >= 0) { .. fast path .. } + * else binary_search(0, -size) + */ + val interfaceColors = assignColorsToInterfaces() + val maxColor = interfaceColors.values.maxOrNull() ?: 0 + var bitsPerColor = 0 + var x = maxColor + while (x > 0) { + ++bitsPerColor + x /= 2 + } + + val maxInterfaceId = Int.MAX_VALUE shr bitsPerColor + val colorCounts = IntArray(maxColor + 1) + + /* + * Here's the explanation of what's happening here: + * Given a tree we can traverse it with the DFS and save for each vertex two times: + * the enter time (the first time we saw this vertex) and the exit time (the last time we saw it). + * It turns out that if we assign then for each vertex the interval (enterTime, exitTime), + * then the following claim holds for any two vertices v and w: + * ----- v is ancestor of w iff interval(v) contains interval(w) ------ + * Now apply this idea to the classes hierarchy tree and we'll get a fast type check. + * + * And one more observation: for each pair of intervals they either don't intersect or + * one contains the other. With that in mind, we can save in a type info only one end of an interval. + */ + val root = context.irBuiltIns.anyClass.owner + val immediateInheritors = mutableMapOf>() + val allClasses = mutableListOf() + irModule.acceptVoid(object: IrElementVisitorVoid { + override fun visitElement(element: IrElement) { + element.acceptChildrenVoid(this) + } + + override fun visitClass(declaration: IrClass) { + if (declaration.isInterface) { + val color = interfaceColors[declaration]!! + // Numerate from 1 (reserve 0 for invalid value). + val interfaceId = ++colorCounts[color] + assert (interfaceId <= maxInterfaceId) { + "Unable to assign interface id to ${declaration.name}" + } + context.getLayoutBuilder(declaration).hierarchyInfo = + ClassGlobalHierarchyInfo(0, 0, + color or (interfaceId shl bitsPerColor), color) + } else { + allClasses += declaration + if (declaration != root) { + val superClass = declaration.getSuperClassNotAny() ?: root + val inheritors = immediateInheritors.getOrPut(superClass) { mutableListOf() } + inheritors.add(declaration) + } + } + super.visitClass(declaration) + } + }) + var time = 0 + + fun dfs(irClass: IrClass) { + ++time + // Make the Any's interval's left border -1 in order to correctly generate classes for ObjC blocks. + val enterTime = if (irClass == root) -1 else time + immediateInheritors[irClass]?.forEach { dfs(it) } + val exitTime = time + context.getLayoutBuilder(irClass).hierarchyInfo = ClassGlobalHierarchyInfo(enterTime, exitTime, 0, 0) + } + + dfs(root) + + context.globalHierarchyAnalysisResult = GlobalHierarchyAnalysisResult(bitsPerColor) + } + + class InterfacesForbiddennessGraph(val nodes: List, val forbidden: List>) { + + fun computeColoringGreedy(): IntArray { + val colors = IntArray(nodes.size) { -1 } + var numberOfColors = 0 + val usedColors = BooleanArray(nodes.size) + for (v in nodes.indices) { + for (c in 0 until numberOfColors) + usedColors[c] = false + for (u in forbidden[v]) + if (colors[u] >= 0) + usedColors[colors[u]] = true + var found = false + for (c in 0 until numberOfColors) + if (!usedColors[c]) { + colors[v] = c + found = true + break + } + if (!found) + colors[v] = numberOfColors++ + } + return colors + } + + companion object { + fun build(irModuleFragment: IrModuleFragment): InterfacesForbiddennessGraph { + val interfaceIndices = mutableMapOf() + val interfaces = mutableListOf() + val forbidden = mutableListOf>() + irModuleFragment.acceptVoid(object : IrElementVisitorVoid { + override fun visitElement(element: IrElement) { + element.acceptChildrenVoid(this) + } + + fun registerInterface(iface: IrClass) { + interfaceIndices.getOrPut(iface) { + forbidden.add(mutableListOf()) + interfaces.add(iface) + interfaces.size - 1 + } + } + + override fun visitClass(declaration: IrClass) { + if (declaration.isInterface) + registerInterface(declaration) + else { + val implementedInterfaces = declaration.implementedInterfaces + implementedInterfaces.forEach { registerInterface(it) } + for (i in 0 until implementedInterfaces.size) + for (j in i + 1 until implementedInterfaces.size) { + val v = interfaceIndices[implementedInterfaces[i]]!! + val u = interfaceIndices[implementedInterfaces[j]]!! + forbidden[v].add(u) + forbidden[u].add(v) + } + } + super.visitClass(declaration) + } + }) + return InterfacesForbiddennessGraph(interfaces, forbidden) + } + } + } + + private fun assignColorsToInterfaces(): Map { + val graph = InterfacesForbiddennessGraph.build(irModule) + val coloring = graph.computeColoringGreedy() + return graph.nodes.mapIndexed { v, irClass -> irClass to coloring[v] }.toMap() + } +} + +internal class ClassLayoutBuilder(val irClass: IrClass, val context: Context, val isLowered: Boolean) { + val vtableEntries: List by lazy { + assert(!irClass.isInterface) + + context.logMultiple { + +"" + +"BUILDING vTable for ${irClass.render()}" + } + + val superVtableEntries = if (irClass.isSpecialClassWithNoSupertypes()) { + emptyList() + } else { + val superClass = irClass.getSuperClassNotAny() ?: context.ir.symbols.any.owner + context.getLayoutBuilder(superClass).vtableEntries + } + + val methods = irClass.sortedOverridableOrOverridingMethods + val newVtableSlots = mutableListOf() + val overridenVtableSlots = mutableMapOf() + + context.logMultiple { + +"" + +"SUPER vTable:" + superVtableEntries.forEach { +" ${it.overriddenFunction.render()} -> ${it.function.render()}" } + + +"" + +"METHODS:" + methods.forEach { +" ${it.render()}" } + + +"" + +"BUILDING INHERITED vTable" + } + + val superVtableMap = superVtableEntries.groupBy { it.function } + methods.forEach { overridingMethod -> + overridingMethod.allOverriddenFunctions.forEach { + val superMethods = superVtableMap[it] + if (superMethods?.isNotEmpty() == true) { + newVtableSlots.add(OverriddenFunctionInfo(overridingMethod, it)) + superMethods.forEach { superMethod -> + overridenVtableSlots[superMethod.overriddenFunction] = + OverriddenFunctionInfo(overridingMethod, superMethod.overriddenFunction) + } + } + } + } + val inheritedVtableSlots = superVtableEntries.map { superMethod -> + overridenVtableSlots[superMethod.overriddenFunction]?.also { + context.log { "Taking overridden ${superMethod.overriddenFunction.render()} -> ${it.function.render()}" } + } ?: superMethod.also { + context.log { "Taking super ${superMethod.overriddenFunction.render()} -> ${superMethod.function.render()}" } + } + } + + // Add all possible (descriptor, overriddenDescriptor) edges for now, redundant will be removed later. + methods.mapTo(newVtableSlots) { OverriddenFunctionInfo(it, it) } + + val inheritedVtableSlotsSet = inheritedVtableSlots.map { it.function to it.bridgeDirections }.toSet() + + val filteredNewVtableSlots = newVtableSlots + .filterNot { inheritedVtableSlotsSet.contains(it.function to it.bridgeDirections) } + .distinctBy { it.function to it.bridgeDirections } + .filter { it.function.isOverridable } + + context.logMultiple { + +"" + +"INHERITED vTable slots:" + inheritedVtableSlots.forEach { +" ${it.overriddenFunction.render()} -> ${it.function.render()}" } + + +"" + +"MY OWN vTable slots:" + filteredNewVtableSlots.forEach { +" ${it.overriddenFunction.render()} -> ${it.function.render()} ${it.function}" } + +"DONE vTable for ${irClass.render()}" + } + + inheritedVtableSlots + filteredNewVtableSlots.sortedBy { it.overriddenFunction.uniqueId } + } + + fun vtableIndex(function: IrSimpleFunction): Int { + val bridgeDirections = function.target.bridgeDirectionsTo(function) + val index = vtableEntries.indexOfFirst { it.function == function && it.bridgeDirections == bridgeDirections } + if (index < 0) throw Error(function.render() + " $function " + " (${function.symbol.descriptor}) not in vtable of " + irClass.render()) + return index + } + + val methodTableEntries: List by lazy { + irClass.sortedOverridableOrOverridingMethods + .flatMap { method -> method.allOverriddenFunctions.map { OverriddenFunctionInfo(method, it) } } + .filter { it.canBeCalledVirtually } + .distinctBy { it.overriddenFunction.uniqueId } + .sortedBy { it.overriddenFunction.uniqueId } + // TODO: probably method table should contain all accessible methods to improve binary compatibility + } + + val interfaceTableEntries: List by lazy { + irClass.sortedOverridableOrOverridingMethods + .filter { f -> + f.isReal || f.overriddenSymbols.any { OverriddenFunctionInfo(f, it.owner).needBridge } + } + .toList() + } + + data class InterfaceTablePlace(val interfaceId: Int, val methodIndex: Int) { + companion object { + val INVALID = InterfaceTablePlace(0, -1) + } + } + + fun itablePlace(function: IrSimpleFunction): InterfaceTablePlace { + assert (irClass.isInterface) { "An interface expected but was ${irClass.name}" } + val itable = interfaceTableEntries + val index = itable.indexOf(function) + if (index >= 0) + return InterfaceTablePlace(hierarchyInfo.interfaceId, index) + val superFunction = function.overriddenSymbols.first().owner + return context.getLayoutBuilder(superFunction.parentAsClass).itablePlace(superFunction) + } + + /** + * All fields of the class instance. + * The order respects the class hierarchy, i.e. a class [fields] contains superclass [fields] as a prefix. + */ + val fields: List by lazy { + val superClass = irClass.getSuperClassNotAny() // TODO: what if Any has fields? + val superFields = if (superClass != null) context.getLayoutBuilder(superClass).fields else emptyList() + + superFields + getDeclaredFields() + } + + val associatedObjects by lazy { + val result = mutableMapOf() + + irClass.annotations.forEach { + val irFile = irClass.getContainingFile() + + val annotationClass = (it.symbol.owner as? IrConstructor)?.constructedClass + ?: error(irFile, it, "unexpected annotation") + + if (annotationClass.hasAnnotation(RuntimeNames.associatedObjectKey)) { + val argument = it.getValueArgument(0) + + val irClassReference = argument as? IrClassReference + ?: error(irFile, argument, "unexpected annotation argument") + + val associatedObject = irClassReference.symbol.owner + + if (associatedObject !is IrClass || !associatedObject.isObject) { + error(irFile, irClassReference, "argument is not a singleton") + } + + if (annotationClass in result) { + error( + irFile, + it, + "duplicate value for ${annotationClass.name}, previous was ${result[annotationClass]?.name}" + ) + } + + result[annotationClass] = associatedObject + } + } + + result + } + + lateinit var hierarchyInfo: ClassGlobalHierarchyInfo + + /** + * Fields declared in the class. + */ + private fun getDeclaredFields(): List { + val declarations: List = if (irClass.isInner && !isLowered) { + // Note: copying to avoid mutation of the original class. + irClass.declarations.toMutableList() + .also { InnerClassLowering.addOuterThisField(it, irClass, context) } + } else { + irClass.declarations + } + + val fields = declarations.mapNotNull { + when (it) { + is IrField -> it.takeIf { it.isReal } + is IrProperty -> it.takeIf { it.isReal }?.backingField + else -> null + } + } + + if (irClass.hasAnnotation(FqName.fromSegments(listOf("kotlin", "native", "internal", "NoReorderFields")))) + return fields + + return fields.sortedByDescending{ LLVMStoreSizeOfType(context.llvm.runtime.targetData, it.type.llvmType(context)) } + } + + private val IrClass.sortedOverridableOrOverridingMethods: List + get() = + this.simpleFunctions() + .filter { it.isOverridableOrOverrides && it.bridgeTarget == null } + .sortedBy { it.uniqueId } + + private val functionIds = mutableMapOf() + + private val IrFunction.uniqueId get() = functionIds.getOrPut(this) { functionName.localHash.value } +} diff --git a/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/descriptors/DeepPrintVisitor.kt b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/descriptors/DeepPrintVisitor.kt new file mode 100644 index 00000000000..abe7c90c7e2 --- /dev/null +++ b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/descriptors/DeepPrintVisitor.kt @@ -0,0 +1,75 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +package org.jetbrains.kotlin.backend.konan.descriptors + +import org.jetbrains.kotlin.util.nTabs +import org.jetbrains.kotlin.descriptors.* + +class DeepPrintVisitor(worker: DeclarationDescriptorVisitor): DeepVisitor(worker) { + + override fun visitChildren(descriptor: DeclarationDescriptor?, data: Int): Boolean { + return super.visitChildren(descriptor, data+1) + } + + override fun visitChildren(descriptors: Collection, data: Int): Boolean { + return super.visitChildren(descriptors, data+1) + } +} + +class PrintVisitor: DeclarationDescriptorVisitor { + + fun printDescriptor(descriptor: DeclarationDescriptor, amount: Int): Boolean { + println("${nTabs(amount)} ${descriptor.toString()}") + return true; + } + + override fun visitPackageFragmentDescriptor(descriptor: PackageFragmentDescriptor, data: Int): Boolean + = printDescriptor(descriptor, data) + + override fun visitPackageViewDescriptor(descriptor: PackageViewDescriptor, data: Int): Boolean + = printDescriptor(descriptor, data) + + override fun visitVariableDescriptor(descriptor: VariableDescriptor, data: Int): Boolean + = printDescriptor(descriptor, data) + + override fun visitFunctionDescriptor(descriptor: FunctionDescriptor, data: Int): Boolean + = printDescriptor(descriptor, data) + + override fun visitTypeParameterDescriptor(descriptor: TypeParameterDescriptor, data: Int): Boolean + = printDescriptor(descriptor, data) + + override fun visitClassDescriptor(descriptor: ClassDescriptor, data: Int): Boolean + = printDescriptor(descriptor, data) + + override fun visitTypeAliasDescriptor(descriptor: TypeAliasDescriptor, data: Int): Boolean + = printDescriptor(descriptor, data) + + override fun visitModuleDeclaration(descriptor: ModuleDescriptor, data: Int): Boolean + = printDescriptor(descriptor, data) + + override fun visitConstructorDescriptor(descriptor: ConstructorDescriptor, data: Int): Boolean + = printDescriptor(descriptor, data) + + override fun visitScriptDescriptor(descriptor: ScriptDescriptor, data: Int): Boolean + = printDescriptor(descriptor, data) + + override fun visitPropertyDescriptor(descriptor: PropertyDescriptor, data: Int): Boolean + = printDescriptor(descriptor, data) + + override fun visitValueParameterDescriptor(descriptor: ValueParameterDescriptor, data: Int): Boolean + = printDescriptor(descriptor, data) + + override fun visitPropertyGetterDescriptor(descriptor: PropertyGetterDescriptor, data: Int): Boolean + = printDescriptor(descriptor, data) + + override fun visitPropertySetterDescriptor(descriptor: PropertySetterDescriptor, data: Int): Boolean + = printDescriptor(descriptor, data) + + override fun visitReceiverParameterDescriptor(descriptor: ReceiverParameterDescriptor, data: Int): Boolean + = printDescriptor(descriptor, data) +} + + diff --git a/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/descriptors/DeepVisitor.kt b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/descriptors/DeepVisitor.kt new file mode 100644 index 00000000000..02a3a5456db --- /dev/null +++ b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/descriptors/DeepVisitor.kt @@ -0,0 +1,123 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +package org.jetbrains.kotlin.backend.konan.descriptors + +import org.jetbrains.kotlin.descriptors.* +import org.jetbrains.kotlin.name.FqName +import org.jetbrains.kotlin.resolve.DescriptorUtils + + +open class DeepVisitor(val worker: DeclarationDescriptorVisitor) : DeclarationDescriptorVisitor { + + open fun visitChildren(descriptors: Collection, data: D): Boolean { + for (descriptor in descriptors) { + if (!descriptor.accept(this, data)) return false + } + return true + } + + open fun visitChildren(descriptor: DeclarationDescriptor?, data: D): Boolean { + if (descriptor == null) return true + + return descriptor.accept(this, data) + } + + fun applyWorker(descriptor: DeclarationDescriptor, data: D): Boolean { + return descriptor.accept(worker, data) + } + + fun processCallable(descriptor: CallableDescriptor, data: D): Boolean { + return applyWorker(descriptor, data) + && visitChildren(descriptor.getTypeParameters(), data) + && visitChildren(descriptor.getExtensionReceiverParameter(), data) + && visitChildren(descriptor.getValueParameters(), data) + } + + override fun visitPackageFragmentDescriptor(descriptor: PackageFragmentDescriptor, data: D): Boolean? { + return applyWorker(descriptor, data) && visitChildren(DescriptorUtils.getAllDescriptors(descriptor.getMemberScope()), data) + } + + override fun visitPackageViewDescriptor(descriptor: PackageViewDescriptor, data: D): Boolean? { + return applyWorker(descriptor, data) && visitChildren(DescriptorUtils.getAllDescriptors(descriptor.memberScope), data) + } + + override fun visitVariableDescriptor(descriptor: VariableDescriptor, data: D): Boolean? { + return processCallable(descriptor, data) + } + + override fun visitPropertyDescriptor(descriptor: PropertyDescriptor, data: D): Boolean? { + return processCallable(descriptor, data) + && visitChildren(descriptor.getter, data) + && visitChildren(descriptor.setter, data) + } + + override fun visitFunctionDescriptor(descriptor: FunctionDescriptor, data: D): Boolean? { + return processCallable(descriptor, data) + } + + override fun visitTypeParameterDescriptor(descriptor: TypeParameterDescriptor, data: D): Boolean? { + return applyWorker(descriptor, data) + } + + override fun visitClassDescriptor(descriptor: ClassDescriptor, data: D): Boolean? { + return applyWorker(descriptor, data) + && visitChildren(descriptor.getThisAsReceiverParameter(), data) + && visitChildren(descriptor.getConstructors(), data) + && visitChildren(descriptor.getTypeConstructor().getParameters(), data) + && visitChildren(DescriptorUtils.getAllDescriptors(descriptor.getDefaultType().memberScope), data) + } + + override fun visitTypeAliasDescriptor(descriptor: TypeAliasDescriptor, data: D): Boolean? { + return applyWorker(descriptor, data) && visitChildren(descriptor.getDeclaredTypeParameters(), data) + } + + override fun visitModuleDeclaration(descriptor: ModuleDescriptor, data: D): Boolean? { + return applyWorker(descriptor, data) && visitChildren(descriptor.getPackage(FqName.ROOT), data) + } + + override fun visitConstructorDescriptor(constructorDescriptor: ConstructorDescriptor, data: D): Boolean? { + return visitFunctionDescriptor(constructorDescriptor, data) + } + + override fun visitScriptDescriptor(scriptDescriptor: ScriptDescriptor, data: D): Boolean? { + return visitClassDescriptor(scriptDescriptor, data) + } + + override fun visitValueParameterDescriptor(descriptor: ValueParameterDescriptor, data: D): Boolean? { + return visitVariableDescriptor(descriptor, data) + } + + override fun visitPropertyGetterDescriptor(descriptor: PropertyGetterDescriptor, data: D): Boolean? { + return visitFunctionDescriptor(descriptor, data) + } + + override fun visitPropertySetterDescriptor(descriptor: PropertySetterDescriptor, data: D): Boolean? { + return visitFunctionDescriptor(descriptor, data) + } + + override fun visitReceiverParameterDescriptor(descriptor: ReceiverParameterDescriptor, data: D): Boolean? { + return applyWorker(descriptor, data) + } +} + +open public class EmptyDescriptorVisitorVoid: DeclarationDescriptorVisitor { + override fun visitPackageFragmentDescriptor(descriptor: PackageFragmentDescriptor, data: Unit) = true + override fun visitPackageViewDescriptor(descriptor: PackageViewDescriptor, data: Unit) = true + override fun visitVariableDescriptor(descriptor: VariableDescriptor, data: Unit) = true + override fun visitFunctionDescriptor(descriptor: FunctionDescriptor, data: Unit) = true + override fun visitTypeParameterDescriptor(descriptor: TypeParameterDescriptor, data: Unit) = true + override fun visitClassDescriptor(descriptor: ClassDescriptor, data: Unit) = true + override fun visitTypeAliasDescriptor(descriptor: TypeAliasDescriptor, data: Unit) = true + override fun visitModuleDeclaration(descriptor: ModuleDescriptor, data: Unit) = true + override fun visitConstructorDescriptor(descriptor: ConstructorDescriptor, data: Unit) = true + override fun visitScriptDescriptor(descriptor: ScriptDescriptor, data: Unit) = true + override fun visitPropertyDescriptor(descriptor: PropertyDescriptor, data: Unit) = true + override fun visitValueParameterDescriptor(descriptor: ValueParameterDescriptor, data: Unit) = true + override fun visitPropertyGetterDescriptor(descriptor: PropertyGetterDescriptor, data: Unit) = true + override fun visitPropertySetterDescriptor(descriptor: PropertySetterDescriptor, data: Unit) = true + override fun visitReceiverParameterDescriptor(descriptor: ReceiverParameterDescriptor, data: Unit) = true +} + diff --git a/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/descriptors/DescriptorUtils.kt b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/descriptors/DescriptorUtils.kt new file mode 100644 index 00000000000..3b5f13a5cb7 --- /dev/null +++ b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/descriptors/DescriptorUtils.kt @@ -0,0 +1,308 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +package org.jetbrains.kotlin.backend.konan.descriptors + +import org.jetbrains.kotlin.backend.common.atMostOne +import org.jetbrains.kotlin.backend.konan.* +import org.jetbrains.kotlin.backend.konan.ir.* +import org.jetbrains.kotlin.backend.konan.llvm.isVoidAsReturnType +import org.jetbrains.kotlin.backend.konan.llvm.longName +import org.jetbrains.kotlin.descriptors.Modality +import org.jetbrains.kotlin.descriptors.annotations.AnnotationDescriptor +import org.jetbrains.kotlin.ir.declarations.* +import org.jetbrains.kotlin.ir.descriptors.IrBuiltIns +import org.jetbrains.kotlin.ir.expressions.IrConst +import org.jetbrains.kotlin.ir.expressions.IrConstructorCall +import org.jetbrains.kotlin.ir.symbols.* +import org.jetbrains.kotlin.ir.types.* +import org.jetbrains.kotlin.ir.util.* +import org.jetbrains.kotlin.resolve.annotations.argumentValue +import org.jetbrains.kotlin.resolve.constants.StringValue +import org.jetbrains.kotlin.resolve.descriptorUtil.module +import org.jetbrains.kotlin.utils.addToStdlib.cast +import org.jetbrains.kotlin.utils.addToStdlib.safeAs + +/** + * List of all implemented interfaces (including those which implemented by a super class) + */ +internal val IrClass.implementedInterfaces: List + get() { + val superClassImplementedInterfaces = this.getSuperClassNotAny()?.implementedInterfaces ?: emptyList() + val superInterfaces = this.getSuperInterfaces() + val superInterfacesImplementedInterfaces = superInterfaces.flatMap { it.implementedInterfaces } + return (superClassImplementedInterfaces + + superInterfacesImplementedInterfaces + + superInterfaces).distinct() + } + +internal val IrFunction.isTypedIntrinsic: Boolean + get() = annotations.hasAnnotation(KonanFqNames.typedIntrinsic) + +internal val arrayTypes = setOf( + "kotlin.Array", + "kotlin.ByteArray", + "kotlin.CharArray", + "kotlin.ShortArray", + "kotlin.IntArray", + "kotlin.LongArray", + "kotlin.FloatArray", + "kotlin.DoubleArray", + "kotlin.BooleanArray", + "kotlin.native.ImmutableBlob", + "kotlin.native.internal.NativePtrArray" +) + +internal val arraysWithFixedSizeItems = setOf( + "kotlin.ByteArray", + "kotlin.CharArray", + "kotlin.ShortArray", + "kotlin.IntArray", + "kotlin.LongArray", + "kotlin.FloatArray", + "kotlin.DoubleArray", + "kotlin.BooleanArray" +) + +internal val IrClass.isArray: Boolean + get() = this.fqNameForIrSerialization.asString() in arrayTypes + +internal val IrClass.isArrayWithFixedSizeItems: Boolean + get() = this.fqNameForIrSerialization.asString() in arraysWithFixedSizeItems + +fun IrClass.isAbstract() = this.modality == Modality.SEALED || this.modality == Modality.ABSTRACT + +private enum class TypeKind { + ABSENT, + VOID, + VALUE_TYPE, + REFERENCE +} + +private data class TypeWithKind(val irType: IrType?, val kind: TypeKind) { + companion object { + fun fromType(irType: IrType?) = when { + irType == null -> TypeWithKind(null, TypeKind.ABSENT) + irType.isInlinedNative() -> TypeWithKind(irType, TypeKind.VALUE_TYPE) + else -> TypeWithKind(irType, TypeKind.REFERENCE) + } + } +} + +private fun IrFunction.typeWithKindAt(index: ParameterIndex) = when (index) { + ParameterIndex.RETURN_INDEX -> when { + isSuspend -> TypeWithKind(null, TypeKind.REFERENCE) + returnType.isVoidAsReturnType() -> TypeWithKind(returnType, TypeKind.VOID) + else -> TypeWithKind.fromType(returnType) + } + ParameterIndex.DISPATCH_RECEIVER_INDEX -> TypeWithKind.fromType(dispatchReceiverParameter?.type) + ParameterIndex.EXTENSION_RECEIVER_INDEX -> TypeWithKind.fromType(extensionReceiverParameter?.type) + else -> TypeWithKind.fromType(this.valueParameters[index.unmap()].type) +} + +private fun IrFunction.needBridgeToAt(target: IrFunction, index: ParameterIndex) + = bridgeDirectionToAt(target, index).kind != BridgeDirectionKind.NONE + +@Suppress("EXPERIMENTAL_FEATURE_WARNING") +private inline class ParameterIndex(val index: Int) { + companion object { + val RETURN_INDEX = ParameterIndex(0) + val DISPATCH_RECEIVER_INDEX = ParameterIndex(1) + val EXTENSION_RECEIVER_INDEX = ParameterIndex(2) + + fun map(index: Int) = ParameterIndex(index + 3) + + fun allParametersCount(irFunction: IrFunction) = irFunction.valueParameters.size + 3 + + inline fun forEachIndex(irFunction: IrFunction, block: (ParameterIndex) -> Unit) = + (0 until allParametersCount(irFunction)).forEach { block(ParameterIndex(it)) } + } + + fun unmap() = index - 3 +} + +internal fun IrFunction.needBridgeTo(target: IrFunction): Boolean { + ParameterIndex.forEachIndex(this) { + if (needBridgeToAt(target, it)) return true + } + return false +} + +internal enum class BridgeDirectionKind { + NONE, + BOX, + UNBOX +} + +internal data class BridgeDirection(val irClass: IrClass?, val kind: BridgeDirectionKind) { + companion object { + val NONE = BridgeDirection(null, BridgeDirectionKind.NONE) + } +} + +private fun IrFunction.bridgeDirectionToAt(overriddenFunction: IrFunction, index: ParameterIndex): BridgeDirection { + val kind = typeWithKindAt(index).kind + val (irClass, otherKind) = overriddenFunction.typeWithKindAt(index) + return if (otherKind == kind) + BridgeDirection.NONE + else when (kind) { + TypeKind.VOID, TypeKind.REFERENCE -> BridgeDirection(irClass?.erasure(), BridgeDirectionKind.UNBOX) + TypeKind.VALUE_TYPE -> BridgeDirection( + irClass?.erasure().takeIf { otherKind == TypeKind.VOID } /* Otherwise erase to [Any?] */, + BridgeDirectionKind.BOX) + TypeKind.ABSENT -> error("TypeKind.ABSENT should be on both sides") + } +} + +private tailrec fun IrType.erasure(): IrClass = + when (val classifier = classifierOrFail) { + is IrClassSymbol -> classifier.owner + is IrTypeParameterSymbol -> classifier.owner.superTypes.first().erasure() + else -> error(classifier) + } + +internal class BridgeDirections(private val array: Array) { + constructor(irFunction: IrSimpleFunction, overriddenFunction: IrSimpleFunction) + : this(Array(ParameterIndex.allParametersCount(irFunction)) { + irFunction.bridgeDirectionToAt(overriddenFunction, ParameterIndex(it)) + }) + + fun allNotNeeded(): Boolean = array.all { it.kind == BridgeDirectionKind.NONE } + + private fun getDirectionAt(index: ParameterIndex) = array[index.index] + + val returnDirection get() = getDirectionAt(ParameterIndex.RETURN_INDEX) + val dispatchReceiverDirection get() = getDirectionAt(ParameterIndex.DISPATCH_RECEIVER_INDEX) + val extensionReceiverDirection get() = getDirectionAt(ParameterIndex.EXTENSION_RECEIVER_INDEX) + fun parameterDirectionAt(index: Int) = getDirectionAt(ParameterIndex.map(index)) + + override fun toString(): String { + val result = StringBuilder() + array.forEach { + result.append(when (it.kind) { + BridgeDirectionKind.BOX -> 'B' + BridgeDirectionKind.UNBOX -> 'U' + BridgeDirectionKind.NONE -> 'N' + }) + } + return result.toString() + } + + override fun equals(other: Any?): Boolean { + if (this === other) return true + if (other !is BridgeDirections) return false + + return array.size == other.array.size + && array.indices.all { array[it] == other.array[it] } + } + + override fun hashCode(): Int { + var result = 0 + array.forEach { result = result * 31 + it.hashCode() } + return result + } + + companion object { + fun none(irFunction: IrSimpleFunction) = BridgeDirections(irFunction, irFunction) + } +} + +val IrSimpleFunction.allOverriddenFunctions: Set + get() { + val result = mutableSetOf() + + fun traverse(function: IrSimpleFunction) { + if (function in result) return + result += function + function.overriddenSymbols.forEach { traverse(it.owner) } + } + + traverse(this) + + return result + } + +internal fun IrSimpleFunction.bridgeDirectionsTo(overriddenFunction: IrSimpleFunction): BridgeDirections { + val ourDirections = BridgeDirections(this, overriddenFunction) + + val target = this.target + if (!this.isReal && modality != Modality.ABSTRACT + && target.overrides(overriddenFunction) + && ourDirections == target.bridgeDirectionsTo(overriddenFunction)) { + // Bridge is inherited from superclass. + return BridgeDirections.none(this) + } + + return ourDirections +} + +internal tailrec fun IrDeclaration.findPackage(): IrPackageFragment { + val parent = this.parent + return parent as? IrPackageFragment + ?: (parent as IrDeclaration).findPackage() +} + +fun IrFunctionSymbol.isComparisonFunction(map: Map): Boolean = + this in map.values + +val IrDeclaration.isPropertyAccessor get() = + this is IrSimpleFunction && this.correspondingPropertySymbol != null + +val IrDeclaration.isPropertyField get() = + this is IrField && this.correspondingPropertySymbol != null + +val IrDeclaration.isTopLevelDeclaration get() = + parent !is IrDeclaration && !this.isPropertyAccessor && !this.isPropertyField + +fun IrDeclaration.findTopLevelDeclaration(): IrDeclaration = when { + this.isTopLevelDeclaration -> + this + this.isPropertyAccessor -> + (this as IrSimpleFunction).correspondingPropertySymbol!!.owner.findTopLevelDeclaration() + this.isPropertyField -> + (this as IrField).correspondingPropertySymbol!!.owner.findTopLevelDeclaration() + else -> + (this.parent as IrDeclaration).findTopLevelDeclaration() +} + +internal val IrClass.isFrozen: Boolean + get() = annotations.hasAnnotation(KonanFqNames.frozen) || + // RTTI is used for non-reference type box: + !this.defaultType.binaryTypeIsReference() + +fun IrConstructorCall.getAnnotationStringValue() = getValueArgument(0).safeAs>()?.value + +fun IrConstructorCall.getAnnotationStringValue(name: String): String { + val parameter = symbol.owner.valueParameters.single { it.name.asString() == name } + return getValueArgument(parameter.index).cast>().value +} + +fun AnnotationDescriptor.getAnnotationStringValue(name: String): String { + return argumentValue(name)?.safeAs()?.value ?: error("Expected value $name at annotation $this") +} + +fun IrConstructorCall.getAnnotationValueOrNull(name: String): T? { + val parameter = symbol.owner.valueParameters.atMostOne { it.name.asString() == name } + return parameter?.let { getValueArgument(it.index)?.let { (it.cast>()).value } } +} + +fun IrFunction.externalSymbolOrThrow(): String? { + annotations.findAnnotation(RuntimeNames.symbolNameAnnotation)?.let { return it.getAnnotationStringValue() } + + if (annotations.hasAnnotation(KonanFqNames.objCMethod)) return null + + if (annotations.hasAnnotation(KonanFqNames.typedIntrinsic)) return null + + if (annotations.hasAnnotation(RuntimeNames.cCall)) return null + + if (origin == InternalAbi.INTERNAL_ABI_ORIGIN) return null + + throw Error("external function ${this.longName} must have @TypedIntrinsic, @SymbolName or @ObjCMethod annotation") +} + +val IrFunction.isBuiltInOperator get() = origin == IrBuiltIns.BUILTIN_OPERATOR + +fun IrDeclaration.isFromMetadataInteropLibrary() = + descriptor.module.isFromInteropLibrary() \ No newline at end of file diff --git a/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/descriptors/KonanSharedVariablesManager.kt b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/descriptors/KonanSharedVariablesManager.kt new file mode 100644 index 00000000000..89702ad81fb --- /dev/null +++ b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/descriptors/KonanSharedVariablesManager.kt @@ -0,0 +1,102 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +package org.jetbrains.kotlin.backend.konan.descriptors + + +import org.jetbrains.kotlin.backend.common.ir.SharedVariablesManager +import org.jetbrains.kotlin.backend.konan.KonanBackendContext +import org.jetbrains.kotlin.ir.IrStatement +import org.jetbrains.kotlin.ir.declarations.IrProperty +import org.jetbrains.kotlin.ir.declarations.IrVariable +import org.jetbrains.kotlin.ir.declarations.impl.IrVariableImpl +import org.jetbrains.kotlin.ir.descriptors.WrappedVariableDescriptor +import org.jetbrains.kotlin.ir.expressions.IrGetValue +import org.jetbrains.kotlin.ir.expressions.IrSetValue +import org.jetbrains.kotlin.ir.expressions.impl.IrCallImpl +import org.jetbrains.kotlin.ir.expressions.impl.IrCompositeImpl +import org.jetbrains.kotlin.ir.expressions.impl.IrConstructorCallImpl +import org.jetbrains.kotlin.ir.expressions.impl.IrGetValueImpl +import org.jetbrains.kotlin.ir.symbols.IrVariableSymbol +import org.jetbrains.kotlin.ir.symbols.impl.IrVariableSymbolImpl +import org.jetbrains.kotlin.ir.types.typeWith +import org.jetbrains.kotlin.ir.util.constructors + +internal class KonanSharedVariablesManager(val context: KonanBackendContext) : SharedVariablesManager { + + private val refClass = context.ir.symbols.refClass + + private val refClassConstructor = refClass.constructors.single() + + private val elementProperty = refClass.owner.declarations.filterIsInstance().single() + + override fun declareSharedVariable(originalDeclaration: IrVariable): IrVariable { + val valueType = originalDeclaration.type + + val refConstructorCall = IrConstructorCallImpl.fromSymbolOwner( + originalDeclaration.startOffset, originalDeclaration.endOffset, + refClass.typeWith(valueType), + refClassConstructor + ).apply { + putTypeArgument(0, valueType) + } + + return with(originalDeclaration) { + WrappedVariableDescriptor().let { + IrVariableImpl( + startOffset, endOffset, origin, + IrVariableSymbolImpl(it), name, refConstructorCall.type, + isVar = false, + isConst = false, + isLateinit = false + ).apply { + it.bind(this) + initializer = refConstructorCall + } + } + } + } + + override fun defineSharedValue(originalDeclaration: IrVariable, sharedVariableDeclaration: IrVariable): IrStatement { + val initializer = originalDeclaration.initializer ?: return sharedVariableDeclaration + + val sharedVariableInitialization = + IrCallImpl(initializer.startOffset, initializer.endOffset, + context.irBuiltIns.unitType, elementProperty.setter!!.symbol, + elementProperty.setter!!.typeParameters.size, elementProperty.setter!!.valueParameters.size) + sharedVariableInitialization.dispatchReceiver = + IrGetValueImpl(initializer.startOffset, initializer.endOffset, + sharedVariableDeclaration.type, sharedVariableDeclaration.symbol) + + sharedVariableInitialization.putValueArgument(0, initializer) + + return IrCompositeImpl( + originalDeclaration.startOffset, originalDeclaration.endOffset, context.irBuiltIns.unitType, null, + listOf(sharedVariableDeclaration, sharedVariableInitialization) + ) + } + + override fun getSharedValue(sharedVariableSymbol: IrVariableSymbol, originalGet: IrGetValue) = + IrCallImpl(originalGet.startOffset, originalGet.endOffset, + originalGet.type, elementProperty.getter!!.symbol, + elementProperty.getter!!.typeParameters.size, elementProperty.getter!!.valueParameters.size).apply { + dispatchReceiver = IrGetValueImpl( + originalGet.startOffset, originalGet.endOffset, + sharedVariableSymbol.owner.type, sharedVariableSymbol + ) + } + + override fun setSharedValue(sharedVariableSymbol: IrVariableSymbol, originalSet: IrSetValue) = + IrCallImpl(originalSet.startOffset, originalSet.endOffset, context.irBuiltIns.unitType, + elementProperty.setter!!.symbol, elementProperty.setter!!.typeParameters.size, + elementProperty.setter!!.valueParameters.size).apply { + dispatchReceiver = IrGetValueImpl( + originalSet.startOffset, originalSet.endOffset, + sharedVariableSymbol.owner.type, sharedVariableSymbol + ) + putValueArgument(0, originalSet.value) + } + +} diff --git a/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/descriptors/LegacyDescriptorUtils.kt b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/descriptors/LegacyDescriptorUtils.kt new file mode 100644 index 00000000000..51b8249f9a9 --- /dev/null +++ b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/descriptors/LegacyDescriptorUtils.kt @@ -0,0 +1,160 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +package org.jetbrains.kotlin.backend.konan.descriptors + +import org.jetbrains.kotlin.backend.common.atMostOne +import org.jetbrains.kotlin.backend.konan.RuntimeNames +import org.jetbrains.kotlin.builtins.konan.KonanBuiltIns +import org.jetbrains.kotlin.descriptors.* +import org.jetbrains.kotlin.descriptors.annotations.AnnotationDescriptor +import org.jetbrains.kotlin.descriptors.konan.DeserializedKlibModuleOrigin +import org.jetbrains.kotlin.descriptors.konan.klibModuleOrigin +import org.jetbrains.kotlin.name.FqName +import org.jetbrains.kotlin.resolve.OverridingUtil +import org.jetbrains.kotlin.resolve.checkers.ExpectedActualDeclarationChecker +import org.jetbrains.kotlin.resolve.descriptorUtil.fqNameSafe +import org.jetbrains.kotlin.resolve.descriptorUtil.module +import org.jetbrains.kotlin.resolve.scopes.MemberScope +import org.jetbrains.kotlin.types.typeUtil.isNothing +import org.jetbrains.kotlin.types.typeUtil.isUnit + +/** + * Implementation of given method. + * + * TODO: this method is actually a part of resolve and probably duplicates another one + */ +internal fun T.resolveFakeOverride(allowAbstract: Boolean = false): T { + if (this.kind.isReal) { + return this + } else { + val overridden = OverridingUtil.getOverriddenDeclarations(this) + val filtered = OverridingUtil.filterOutOverridden(overridden) + // TODO: is it correct to take first? + @Suppress("UNCHECKED_CAST") + return filtered.first { allowAbstract || it.modality != Modality.ABSTRACT } as T + } +} + +internal val ClassDescriptor.isArray: Boolean + get() = this.fqNameSafe.asString() in arrayTypes + + +internal val ClassDescriptor.isInterface: Boolean + get() = (this.kind == ClassKind.INTERFACE) + +/** + * @return `konan.internal` member scope + */ +internal val KonanBuiltIns.kotlinNativeInternal: MemberScope + get() = this.builtInsModule.getPackage(RuntimeNames.kotlinNativeInternalPackageName).memberScope + +internal fun ClassDescriptor.isUnit() = this.defaultType.isUnit() + +internal fun ClassDescriptor.isNothing() = this.defaultType.isNothing() + + +internal val T.allOverriddenDescriptors: List + get() { + val result = mutableListOf() + fun traverse(descriptor: T) { + result.add(descriptor) + @Suppress("UNCHECKED_CAST") + descriptor.overriddenDescriptors.forEach { traverse(it as T) } + } + traverse(this) + return result + } + +internal val ClassDescriptor.contributedMethods: List + get () = unsubstitutedMemberScope.contributedMethods + +internal val MemberScope.contributedMethods: List + get () { + val contributedDescriptors = this.getContributedDescriptors() + + val functions = contributedDescriptors.filterIsInstance() + + val properties = contributedDescriptors.filterIsInstance() + val getters = properties.mapNotNull { it.getter } + val setters = properties.mapNotNull { it.setter } + + return functions + getters + setters + } + +fun ClassDescriptor.isAbstract() = this.modality == Modality.SEALED || this.modality == Modality.ABSTRACT + +internal val FunctionDescriptor.target: FunctionDescriptor + get() = (if (modality == Modality.ABSTRACT) this else resolveFakeOverride()).original + +tailrec internal fun DeclarationDescriptor.findPackage(): PackageFragmentDescriptor { + return if (this is PackageFragmentDescriptor) this + else this.containingDeclaration!!.findPackage() +} + +internal fun DeclarationDescriptor.findPackageView(): PackageViewDescriptor { + val packageFragment = this.findPackage() + return packageFragment.module.getPackage(packageFragment.fqName) +} + +internal fun DeclarationDescriptor.allContainingDeclarations(): List { + var list = mutableListOf() + var current = this.containingDeclaration + while (current != null) { + list.add(current) + current = current.containingDeclaration + } + return list +} + +fun AnnotationDescriptor.getStringValueOrNull(name: String): String? { + val constantValue = this.allValueArguments.entries.atMostOne { + it.key.asString() == name + }?.value + return constantValue?.value as String? +} + +inline fun AnnotationDescriptor.getArgumentValueOrNull(name: String): T? { + val constantValue = this.allValueArguments.entries.atMostOne { + it.key.asString() == name + }?.value + return constantValue?.value as T? +} + + +fun AnnotationDescriptor.getStringValue(name: String): String = this.getStringValueOrNull(name)!! + +private fun getPackagesFqNames(module: ModuleDescriptor): Set { + val result = mutableSetOf() + + fun getSubPackages(fqName: FqName) { + result.add(fqName) + module.getSubPackagesOf(fqName) { true }.forEach { getSubPackages(it) } + } + + getSubPackages(FqName.ROOT) + return result +} + +fun ModuleDescriptor.getPackageFragments(): List = + getPackagesFqNames(this).flatMap { + getPackage(it).fragments.filter { it.module == this }.toSet() + } + +val ClassDescriptor.enumEntries: List + get() { + assert(this.kind == ClassKind.ENUM_CLASS) + return this.unsubstitutedMemberScope.getContributedDescriptors() + .filterIsInstance() + .filter { it.kind == ClassKind.ENUM_ENTRY } + } + +internal val DeclarationDescriptor.isExpectMember: Boolean + get() = this is MemberDescriptor && this.isExpect + +internal val DeclarationDescriptor.isSerializableExpectClass: Boolean + get() = this is ClassDescriptor && ExpectedActualDeclarationChecker.shouldGenerateExpectClass(this) + +val ModuleDescriptor.konanLibrary get() = (this.klibModuleOrigin as? DeserializedKlibModuleOrigin)?.library diff --git a/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/descriptors/utils.kt b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/descriptors/utils.kt new file mode 100644 index 00000000000..ea14c29580f --- /dev/null +++ b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/descriptors/utils.kt @@ -0,0 +1,65 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +package org.jetbrains.kotlin.backend.konan.descriptors + +import org.jetbrains.kotlin.descriptors.* +import org.jetbrains.kotlin.descriptors.konan.DeserializedKlibModuleOrigin +import org.jetbrains.kotlin.descriptors.konan.klibModuleOrigin +import org.jetbrains.kotlin.descriptors.konan.kotlinLibrary +import org.jetbrains.kotlin.konan.library.KLIB_INTEROP_IR_PROVIDER_IDENTIFIER +import org.jetbrains.kotlin.library.BaseKotlinLibrary +import org.jetbrains.kotlin.name.Name +import org.jetbrains.kotlin.serialization.deserialization.descriptors.* + +fun DeclarationDescriptor.deepPrint() { + this.accept(DeepPrintVisitor(PrintVisitor()), 0) +} + +internal val String.synthesizedName get() = Name.identifier(this.synthesizedString) + +internal val String.synthesizedString get() = "\$$this" + + +internal val DeclarationDescriptor.propertyIfAccessor + get() = if (this is PropertyAccessorDescriptor) + this.correspondingProperty + else this + +internal val CallableMemberDescriptor.propertyIfAccessor + get() = if (this is PropertyAccessorDescriptor) + this.correspondingProperty + else this + +internal val FunctionDescriptor.deserializedPropertyIfAccessor: DeserializedCallableMemberDescriptor + get() { + val member = this.propertyIfAccessor + if (member is DeserializedCallableMemberDescriptor) + return member + else + error("Unexpected deserializable callable descriptor") + } + +internal val CallableMemberDescriptor.isDeserializableCallable + get () = (this.propertyIfAccessor is DeserializedCallableMemberDescriptor) + +fun DeclarationDescriptor.findTopLevelDescriptor(): DeclarationDescriptor { + return if (this.containingDeclaration is org.jetbrains.kotlin.descriptors.PackageFragmentDescriptor) this.propertyIfAccessor + else this.containingDeclaration!!.findTopLevelDescriptor() +} + +val ModuleDescriptor.isForwardDeclarationModule: Boolean + get() { + // TODO: use KlibResolvedModuleDescriptorsFactoryImpl.FORWARD_DECLARATIONS_MODULE_NAME instead of + // manually created Name instance + return name == Name.special("") + } + +fun BaseKotlinLibrary.isInteropLibrary() = + manifestProperties["ir_provider"] == KLIB_INTEROP_IR_PROVIDER_IDENTIFIER + +fun ModuleDescriptor.isFromInteropLibrary() = + if (klibModuleOrigin !is DeserializedKlibModuleOrigin) false + else kotlinLibrary.isInteropLibrary() diff --git a/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/injection.kt b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/injection.kt new file mode 100644 index 00000000000..34df652f166 --- /dev/null +++ b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/injection.kt @@ -0,0 +1,48 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ +package org.jetbrains.kotlin.backend.konan + +import org.jetbrains.kotlin.config.LanguageVersionSettings +import org.jetbrains.kotlin.container.* +import org.jetbrains.kotlin.context.ModuleContext +import org.jetbrains.kotlin.descriptors.PackageFragmentProvider +import org.jetbrains.kotlin.descriptors.impl.CompositePackageFragmentProvider +import org.jetbrains.kotlin.descriptors.impl.ModuleDescriptorImpl +import org.jetbrains.kotlin.frontend.di.configureModule +import org.jetbrains.kotlin.platform.konan.NativePlatforms +import org.jetbrains.kotlin.resolve.* +import org.jetbrains.kotlin.resolve.konan.platform.NativePlatformAnalyzerServices +import org.jetbrains.kotlin.resolve.lazy.KotlinCodeAnalyzer +import org.jetbrains.kotlin.resolve.lazy.ResolveSession +import org.jetbrains.kotlin.resolve.lazy.declarations.DeclarationProviderFactory + + +fun createTopDownAnalyzerProviderForKonan( + moduleContext: ModuleContext, + bindingTrace: BindingTrace, + declarationProviderFactory: DeclarationProviderFactory, + languageVersionSettings: LanguageVersionSettings, + additionalPackages: List, + initContainer: StorageComponentContainer.() -> Unit +): ComponentProvider { + return createContainer("TopDownAnalyzerForKonan", NativePlatformAnalyzerServices) { + configureModule(moduleContext, NativePlatforms.unspecifiedNativePlatform, NativePlatformAnalyzerServices, bindingTrace, languageVersionSettings) + + useInstance(declarationProviderFactory) + useImpl() + + CompilerEnvironment.configure(this) + + useImpl() + useImpl() + + initContainer() + }.apply { + val packagePartProviders = mutableListOf(get().packageFragmentProvider) + val moduleDescriptor = get() + packagePartProviders += additionalPackages + moduleDescriptor.initialize(CompositePackageFragmentProvider(packagePartProviders)) + } +} diff --git a/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/ir/FakeIrUtils.kt b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/ir/FakeIrUtils.kt new file mode 100644 index 00000000000..5dd514db789 --- /dev/null +++ b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/ir/FakeIrUtils.kt @@ -0,0 +1,25 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +package org.jetbrains.kotlin.backend.konan.ir + +import org.jetbrains.kotlin.backend.konan.* +import org.jetbrains.kotlin.backend.konan.llvm.llvmSymbolOrigin +import org.jetbrains.kotlin.ir.declarations.* +import org.jetbrains.kotlin.ir.declarations.lazy.IrLazyDeclarationBase +import org.jetbrains.kotlin.ir.types.IrType +import org.jetbrains.kotlin.ir.types.toKotlinType +import org.jetbrains.kotlin.ir.util.file + +// This file contains some IR utilities which actually use descriptors. +// TODO: port this code to IR. + +internal val IrDeclaration.llvmSymbolOrigin get() = when (this) { + is IrLazyDeclarationBase -> descriptor.llvmSymbolOrigin + else -> file.packageFragmentDescriptor.llvmSymbolOrigin +} + +internal fun IrType.isObjCObjectType() = this.toKotlinType().isObjCObjectType() + diff --git a/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/ir/Ir.kt b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/ir/Ir.kt new file mode 100644 index 00000000000..a4b38853084 --- /dev/null +++ b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/ir/Ir.kt @@ -0,0 +1,576 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +package org.jetbrains.kotlin.backend.konan.ir + +import org.jetbrains.kotlin.backend.common.COROUTINE_SUSPENDED_NAME +import org.jetbrains.kotlin.backend.common.ir.Ir +import org.jetbrains.kotlin.backend.common.ir.Symbols +import org.jetbrains.kotlin.backend.konan.* +import org.jetbrains.kotlin.backend.konan.descriptors.kotlinNativeInternal +import org.jetbrains.kotlin.backend.konan.llvm.findMainEntryPoint +import org.jetbrains.kotlin.backend.konan.lower.TestProcessor +import org.jetbrains.kotlin.builtins.KotlinBuiltIns +import org.jetbrains.kotlin.builtins.StandardNames +import org.jetbrains.kotlin.builtins.UnsignedType +import org.jetbrains.kotlin.config.coroutinesIntrinsicsPackageFqName +import org.jetbrains.kotlin.config.coroutinesPackageFqName +import org.jetbrains.kotlin.config.languageVersionSettings +import org.jetbrains.kotlin.descriptors.* +import org.jetbrains.kotlin.incremental.components.NoLookupLocation +import org.jetbrains.kotlin.ir.declarations.IrModuleFragment +import org.jetbrains.kotlin.ir.descriptors.IrBuiltIns +import org.jetbrains.kotlin.ir.symbols.IrClassSymbol +import org.jetbrains.kotlin.ir.symbols.IrFunctionSymbol +import org.jetbrains.kotlin.ir.symbols.IrSimpleFunctionSymbol +import org.jetbrains.kotlin.ir.types.IrType +import org.jetbrains.kotlin.ir.types.typeWith +import org.jetbrains.kotlin.ir.util.* +import org.jetbrains.kotlin.name.ClassId +import org.jetbrains.kotlin.name.FqName +import org.jetbrains.kotlin.name.Name +import org.jetbrains.kotlin.resolve.calls.components.isVararg +import org.jetbrains.kotlin.resolve.scopes.MemberScope +import org.jetbrains.kotlin.types.KotlinType +import org.jetbrains.kotlin.types.Variance +import kotlin.properties.Delegates + +// This is what Context collects about IR. +internal class KonanIr(context: Context, irModule: IrModuleFragment): Ir(context, irModule) { + override var symbols: KonanSymbols by Delegates.notNull() +} + +internal class KonanSymbols( + context: Context, + irBuiltIns: IrBuiltIns, + private val symbolTable: SymbolTable, + lazySymbolTable: ReferenceSymbolTable, + val functionIrClassFactory: BuiltInFictitiousFunctionIrClassFactory +): Symbols(context, irBuiltIns, symbolTable) { + + val entryPoint = findMainEntryPoint(context)?.let { symbolTable.referenceSimpleFunction(it) } + + override val externalSymbolTable = lazySymbolTable + + val nothing = symbolTable.referenceClass(builtIns.nothing) + val throwable = symbolTable.referenceClass(builtIns.throwable) + val enum = symbolTable.referenceClass(builtIns.enum) + val nativePtr = symbolTable.referenceClass(context.nativePtr) + val nativePointed = symbolTable.referenceClass(context.interopBuiltIns.nativePointed) + val nativePtrType = nativePtr.typeWith(arguments = emptyList()) + val nonNullNativePtr = symbolTable.referenceClass(context.nonNullNativePtr) + + val immutableBlobOf = symbolTable.referenceSimpleFunction(context.immutableBlobOf) + + private fun unsignedClass(unsignedType: UnsignedType): IrClassSymbol = classById(unsignedType.classId) + + override val uByte = unsignedClass(UnsignedType.UBYTE) + override val uShort = unsignedClass(UnsignedType.USHORT) + override val uInt = unsignedClass(UnsignedType.UINT) + override val uLong = unsignedClass(UnsignedType.ULONG) + + val signedIntegerClasses = setOf(byte, short, int, long) + val unsignedIntegerClasses = setOf(uByte, uShort, uInt, uLong) + + val allIntegerClasses = signedIntegerClasses + unsignedIntegerClasses + + val unsignedToSignedOfSameBitWidth = unsignedIntegerClasses.associate { + it to when (it) { + uByte -> byte + uShort -> short + uInt -> int + uLong -> long + else -> error(it.descriptor) + } + } + + val integerConversions = allIntegerClasses.flatMap { fromClass -> + allIntegerClasses.map { toClass -> + val name = Name.identifier("to${toClass.descriptor.name.asString().capitalize()}") + val descriptor = if (fromClass in signedIntegerClasses && toClass in unsignedIntegerClasses) { + builtInsPackage("kotlin") + .getContributedFunctions(name, NoLookupLocation.FROM_BACKEND) + .single { + it.dispatchReceiverParameter == null && + it.extensionReceiverParameter?.type == fromClass.descriptor.defaultType && + it.valueParameters.isEmpty() + } + } else { + fromClass.descriptor.unsubstitutedMemberScope + .getContributedFunctions(name, NoLookupLocation.FROM_BACKEND) + .single { + it.extensionReceiverParameter == null && it.valueParameters.isEmpty() + } + } + val symbol = symbolTable.referenceSimpleFunction(descriptor) + + (fromClass to toClass) to symbol + } + }.toMap() + + val arrayList = symbolTable.referenceClass(getArrayListClassDescriptor(context)) + + val symbolName = topLevelClass(RuntimeNames.symbolNameAnnotation) + val filterExceptions = topLevelClass(RuntimeNames.filterExceptions) + val exportForCppRuntime = topLevelClass(RuntimeNames.exportForCppRuntime) + + val objCMethodImp = symbolTable.referenceClass(context.interopBuiltIns.objCMethodImp) + + val onUnhandledException = internalFunction("OnUnhandledException") + + val interopNativePointedGetRawPointer = + symbolTable.referenceSimpleFunction(context.interopBuiltIns.nativePointedGetRawPointer) + + val interopCPointer = symbolTable.referenceClass(context.interopBuiltIns.cPointer) + val interopCstr = symbolTable.referenceSimpleFunction(context.interopBuiltIns.cstr.getter!!) + val interopWcstr = symbolTable.referenceSimpleFunction(context.interopBuiltIns.wcstr.getter!!) + val interopMemScope = symbolTable.referenceClass(context.interopBuiltIns.memScope) + val interopCValue = symbolTable.referenceClass(context.interopBuiltIns.cValue) + val interopCValues = symbolTable.referenceClass(context.interopBuiltIns.cValues) + val interopCValuesRef = symbolTable.referenceClass(context.interopBuiltIns.cValuesRef) + val interopCValueWrite = symbolTable.referenceSimpleFunction(context.interopBuiltIns.cValueWrite) + val interopCValueRead = symbolTable.referenceSimpleFunction(context.interopBuiltIns.cValueRead) + val interopAllocType = symbolTable.referenceSimpleFunction(context.interopBuiltIns.allocType) + + val interopTypeOf = symbolTable.referenceSimpleFunction(context.interopBuiltIns.typeOf) + + val interopCPointerGetRawValue = symbolTable.referenceSimpleFunction(context.interopBuiltIns.cPointerGetRawValue) + + val interopAllocObjCObject = symbolTable.referenceSimpleFunction(context.interopBuiltIns.allocObjCObject) + + val interopForeignObjCObject = interopClass("ForeignObjCObject") + + // These are possible supertypes of forward declarations - we need to reference them explicitly to force their deserialization. + // TODO: Do it lazily. + val interopCOpaque = symbolTable.referenceClass(context.interopBuiltIns.cOpaque) + val interopObjCObject = symbolTable.referenceClass(context.interopBuiltIns.objCObject) + val interopObjCObjectBase = symbolTable.referenceClass(context.interopBuiltIns.objCObjectBase) + + val interopObjCRelease = interopFunction("objc_release") + + val interopObjCRetain = interopFunction("objc_retain") + + val interopObjcRetainAutoreleaseReturnValue = interopFunction("objc_retainAutoreleaseReturnValue") + + val interopCreateObjCObjectHolder = interopFunction("createObjCObjectHolder") + + val interopCreateKotlinObjectHolder = interopFunction("createKotlinObjectHolder") + val interopUnwrapKotlinObjectHolderImpl = interopFunction("unwrapKotlinObjectHolderImpl") + + val interopCreateObjCSuperStruct = interopFunction("createObjCSuperStruct") + + val interopGetMessenger = interopFunction("getMessenger") + val interopGetMessengerStret = interopFunction("getMessengerStret") + + val interopGetObjCClass = symbolTable.referenceSimpleFunction(context.interopBuiltIns.getObjCClass) + + val interopObjCObjectSuperInitCheck = + symbolTable.referenceSimpleFunction(context.interopBuiltIns.objCObjectSuperInitCheck) + + val interopObjCObjectInitBy = symbolTable.referenceSimpleFunction(context.interopBuiltIns.objCObjectInitBy) + + val interopObjCObjectRawValueGetter = + symbolTable.referenceSimpleFunction(context.interopBuiltIns.objCObjectRawPtr) + + val interopNativePointedRawPtrGetter = + symbolTable.referenceSimpleFunction(context.interopBuiltIns.nativePointedRawPtrGetter) + + val interopCPointerRawValue = + symbolTable.referenceProperty(context.interopBuiltIns.cPointerRawValue) + + val interopInterpretObjCPointer = + symbolTable.referenceSimpleFunction(context.interopBuiltIns.interpretObjCPointer) + + val interopInterpretObjCPointerOrNull = + symbolTable.referenceSimpleFunction(context.interopBuiltIns.interpretObjCPointerOrNull) + + val interopInterpretNullablePointed = + symbolTable.referenceSimpleFunction(context.interopBuiltIns.interpretNullablePointed) + + val interopInterpretCPointer = + symbolTable.referenceSimpleFunction(context.interopBuiltIns.interpretCPointer) + + val interopCreateNSStringFromKString = + symbolTable.referenceSimpleFunction(context.interopBuiltIns.CreateNSStringFromKString) + + val createForeignException = interopFunction("CreateForeignException") + + val interopObjCGetSelector = interopFunction("objCGetSelector") + + val interopCEnumVar = interopClass("CEnumVar") + + val nativeMemUtils = symbolTable.referenceClass(context.interopBuiltIns.nativeMemUtils) + + val readBits = interopFunction("readBits") + val writeBits = interopFunction("writeBits") + + val objCExportTrapOnUndeclaredException = + symbolTable.referenceSimpleFunction(context.builtIns.kotlinNativeInternal.getContributedFunctions( + Name.identifier("trapOnUndeclaredException"), + NoLookupLocation.FROM_BACKEND + ).single()) + + val objCExportResumeContinuation = internalFunction("resumeContinuation") + val objCExportResumeContinuationWithException = internalFunction("resumeContinuationWithException") + val objCExportGetCoroutineSuspended = internalFunction("getCoroutineSuspended") + val objCExportInterceptedContinuation = internalFunction("interceptedContinuation") + + val getNativeNullPtr = symbolTable.referenceSimpleFunction(context.getNativeNullPtr) + + val boxCachePredicates = BoxCache.values().associate { + it to internalFunction("in${it.name.toLowerCase().capitalize()}BoxCache") + } + + val boxCacheGetters = BoxCache.values().associate { + it to internalFunction("getCached${it.name.toLowerCase().capitalize()}Box") + } + + val immutableBlob = symbolTable.referenceClass( + builtInsPackage("kotlin", "native").getContributedClassifier( + Name.identifier("ImmutableBlob"), NoLookupLocation.FROM_BACKEND + ) as ClassDescriptor + ) + + val executeImpl = symbolTable.referenceSimpleFunction( + builtIns.builtInsModule.getPackage(FqName("kotlin.native.concurrent")).memberScope + .getContributedFunctions(Name.identifier("executeImpl"), NoLookupLocation.FROM_BACKEND) + .single() + ) + + val createCleaner = symbolTable.referenceSimpleFunction( + builtIns.builtInsModule.getPackage(FqName("kotlin.native.internal")).memberScope + .getContributedFunctions(Name.identifier("createCleaner"), NoLookupLocation.FROM_BACKEND) + .single() + ) + + val areEqualByValue = context.getKonanInternalFunctions("areEqualByValue").map { + symbolTable.referenceSimpleFunction(it) + }.associateBy { it.descriptor.valueParameters[0].type.computePrimitiveBinaryTypeOrNull()!! } + + val reinterpret = internalFunction("reinterpret") + + val ieee754Equals = context.getKonanInternalFunctions("ieee754Equals").map { + symbolTable.referenceSimpleFunction(it) + } + + val equals = context.builtIns.any.unsubstitutedMemberScope + .getContributedFunctions(Name.identifier("equals"), NoLookupLocation.FROM_BACKEND) + .single().let { symbolTable.referenceSimpleFunction(it) } + + val throwArithmeticException = internalFunction("ThrowArithmeticException") + + val throwIndexOutOfBoundsException = internalFunction("ThrowIndexOutOfBoundsException") + + override val throwNullPointerException = internalFunction("ThrowNullPointerException") + + override val throwNoWhenBranchMatchedException = internalFunction("ThrowNoWhenBranchMatchedException") + + override val throwTypeCastException = internalFunction("ThrowTypeCastException") + + override val throwKotlinNothingValueException = internalFunction("ThrowKotlinNothingValueException") + + val throwClassCastException = internalFunction("ThrowClassCastException") + + val throwInvalidReceiverTypeException = internalFunction("ThrowInvalidReceiverTypeException") + val throwIllegalStateException = internalFunction("ThrowIllegalStateException") + val throwIllegalStateExceptionWithMessage = internalFunction("ThrowIllegalStateExceptionWithMessage") + val throwIllegalArgumentException = internalFunction("ThrowIllegalArgumentException") + val throwIllegalArgumentExceptionWithMessage = internalFunction("ThrowIllegalArgumentExceptionWithMessage") + + + override val throwUninitializedPropertyAccessException = internalFunction("ThrowUninitializedPropertyAccessException") + + override val stringBuilder = symbolTable.referenceClass( + builtInsPackage("kotlin", "text").getContributedClassifier( + Name.identifier("StringBuilder"), NoLookupLocation.FROM_BACKEND + ) as ClassDescriptor + ) + + override val defaultConstructorMarker = symbolTable.referenceClass( + context.getKonanInternalClass("DefaultConstructorMarker") + ) + + val checkProgressionStep = context.getKonanInternalFunctions("checkProgressionStep") + .map { Pair(it.returnType, symbolTable.referenceSimpleFunction(it)) }.toMap() + val getProgressionLast = context.getKonanInternalFunctions("getProgressionLast") + .map { Pair(it.returnType, symbolTable.referenceSimpleFunction(it)) }.toMap() + + val arrayContentToString = arrays.associateBy( + { it }, + { findArrayExtension(it.descriptor, "contentToString") } + ) + val arrayContentHashCode = arrays.associateBy( + { it }, + { findArrayExtension(it.descriptor, "contentHashCode") } + ) + + private val kotlinCollectionsPackageScope: MemberScope + get() = builtInsPackage("kotlin", "collections") + + private fun findArrayExtension(descriptor: ClassDescriptor, name: String): IrSimpleFunctionSymbol { + val functionDescriptor = kotlinCollectionsPackageScope + .getContributedFunctions(Name.identifier(name), NoLookupLocation.FROM_BACKEND) + .singleOrNull { + it.valueParameters.isEmpty() + && it.extensionReceiverParameter?.type?.constructor?.declarationDescriptor == descriptor + && it.extensionReceiverParameter?.type?.isMarkedNullable == false + && !it.isExpect + } ?: error(descriptor.toString()) + return symbolTable.referenceSimpleFunction(functionDescriptor) + } + override val copyRangeTo get() = TODO() + + fun getNoParamFunction(name: Name, receiverType: KotlinType): IrFunctionSymbol { + val descriptor = receiverType.memberScope.getContributedFunctions(name, NoLookupLocation.FROM_BACKEND) + .first { it.valueParameters.isEmpty() } + return symbolTable.referenceFunction(descriptor) + } + + val copyInto = arrays.map { symbol -> + val packageViewDescriptor = builtIns.builtInsModule.getPackage(StandardNames.COLLECTIONS_PACKAGE_FQ_NAME) + val functionDescriptor = packageViewDescriptor.memberScope + .getContributedFunctions(Name.identifier("copyInto"), NoLookupLocation.FROM_BACKEND) + .single { + !it.isExpect && + it.extensionReceiverParameter?.type?.constructor?.declarationDescriptor == symbol.descriptor + } + symbol.descriptor to symbolTable.referenceSimpleFunction(functionDescriptor) + }.toMap() + + val arrayGet = arrays.associateWith { it.descriptor.unsubstitutedMemberScope + .getContributedFunctions(Name.identifier("get"), NoLookupLocation.FROM_BACKEND) + .single().let { symbolTable.referenceSimpleFunction(it) } } + + val arraySet = arrays.associateWith { it.descriptor.unsubstitutedMemberScope + .getContributedFunctions(Name.identifier("set"), NoLookupLocation.FROM_BACKEND) + .single().let { symbolTable.referenceSimpleFunction(it) } } + + + val arraySize = arrays.associateWith { it.descriptor.unsubstitutedMemberScope + .getContributedVariables(Name.identifier("size"), NoLookupLocation.FROM_BACKEND) + .single().let { symbolTable.referenceSimpleFunction(it.getter!!) } } + + + val valuesForEnum = internalFunction("valuesForEnum") + + val valueOfForEnum = internalFunction("valueOfForEnum") + + val createUninitializedInstance = internalFunction("createUninitializedInstance") + + val initInstance = internalFunction("initInstance") + + val freeze = symbolTable.referenceSimpleFunction( + builtInsPackage("kotlin", "native", "concurrent").getContributedFunctions( + Name.identifier("freeze"), NoLookupLocation.FROM_BACKEND).single()) + + val println = symbolTable.referenceSimpleFunction( + builtInsPackage("kotlin", "io").getContributedFunctions( + Name.identifier("println"), NoLookupLocation.FROM_BACKEND) + .single { it.valueParameters.singleOrNull()?.type == builtIns.stringType }) + + val anyNToString = symbolTable.referenceSimpleFunction( + builtInsPackage("kotlin").getContributedFunctions( + Name.identifier("toString"), NoLookupLocation.FROM_BACKEND) + .single { it.extensionReceiverParameter?.type == builtIns.nullableAnyType}) + + override val getContinuation = internalFunction("getContinuation") + + override val returnIfSuspended = internalFunction("returnIfSuspended") + + val coroutineLaunchpad = internalFunction("coroutineLaunchpad") + + override val suspendCoroutineUninterceptedOrReturn = internalFunction("suspendCoroutineUninterceptedOrReturn") + + private val coroutinesIntrinsicsPackage = context.builtIns.builtInsModule.getPackage( + context.config.configuration.languageVersionSettings.coroutinesIntrinsicsPackageFqName()).memberScope + + private val coroutinesPackage = context.builtIns.builtInsModule.getPackage( + context.config.configuration.languageVersionSettings.coroutinesPackageFqName()).memberScope + + override val coroutineContextGetter = symbolTable.referenceSimpleFunction( + coroutinesPackage + .getContributedVariables(Name.identifier("coroutineContext"), NoLookupLocation.FROM_BACKEND) + .single() + .getter!!) + + override val coroutineGetContext = internalFunction("getCoroutineContext") + + override val coroutineImpl get() = TODO() + + val baseContinuationImpl = topLevelClass("kotlin.coroutines.native.internal.BaseContinuationImpl") + + val restrictedContinuationImpl = topLevelClass("kotlin.coroutines.native.internal.RestrictedContinuationImpl") + + val continuationImpl = topLevelClass("kotlin.coroutines.native.internal.ContinuationImpl") + + val invokeSuspendFunction = + symbolTable.referenceSimpleFunction( + baseContinuationImpl.descriptor.unsubstitutedMemberScope + .getContributedFunctions(Name.identifier("invokeSuspend"), NoLookupLocation.FROM_BACKEND) + .single() + ) + + override val coroutineSuspendedGetter = symbolTable.referenceSimpleFunction( + coroutinesIntrinsicsPackage + .getContributedVariables(COROUTINE_SUSPENDED_NAME, NoLookupLocation.FROM_BACKEND) + .filterNot { it.isExpect }.single().getter!! + ) + + val cancellationException = topLevelClass(KonanFqNames.cancellationException) + + val kotlinResult = topLevelClass("kotlin.Result") + + val kotlinResultGetOrThrow = symbolTable.referenceSimpleFunction( + builtInsPackage("kotlin") + .getContributedFunctions(Name.identifier("getOrThrow"), NoLookupLocation.FROM_BACKEND) + .single { + it.extensionReceiverParameter?.type?.constructor?.declarationDescriptor == kotlinResult.descriptor + } + ) + + override val functionAdapter = symbolTable.referenceClass(context.getKonanInternalClass("FunctionAdapter")) + + val refClass = symbolTable.referenceClass(context.getKonanInternalClass("Ref")) + + val kFunctionImpl = symbolTable.referenceClass(context.reflectionTypes.kFunctionImpl) + val kSuspendFunctionImpl = symbolTable.referenceClass(context.reflectionTypes.kSuspendFunctionImpl) + + val kMutableProperty0 = symbolTable.referenceClass(context.reflectionTypes.kMutableProperty0) + val kMutableProperty1 = symbolTable.referenceClass(context.reflectionTypes.kMutableProperty1) + val kMutableProperty2 = symbolTable.referenceClass(context.reflectionTypes.kMutableProperty2) + + val kProperty0Impl = symbolTable.referenceClass(context.reflectionTypes.kProperty0Impl) + val kProperty1Impl = symbolTable.referenceClass(context.reflectionTypes.kProperty1Impl) + val kProperty2Impl = symbolTable.referenceClass(context.reflectionTypes.kProperty2Impl) + val kMutableProperty0Impl = symbolTable.referenceClass(context.reflectionTypes.kMutableProperty0Impl) + val kMutableProperty1Impl = symbolTable.referenceClass(context.reflectionTypes.kMutableProperty1Impl) + val kMutableProperty2Impl = symbolTable.referenceClass(context.reflectionTypes.kMutableProperty2Impl) + + val kLocalDelegatedPropertyImpl = symbolTable.referenceClass(context.reflectionTypes.kLocalDelegatedPropertyImpl) + val kLocalDelegatedMutablePropertyImpl = symbolTable.referenceClass(context.reflectionTypes.kLocalDelegatedMutablePropertyImpl) + + val typeOf = symbolTable.referenceSimpleFunction(context.reflectionTypes.typeOf) + + val kType = symbolTable.referenceClass(context.reflectionTypes.kType) + val kVariance = symbolTable.referenceClass(context.reflectionTypes.kVariance) + + val getClassTypeInfo = internalFunction("getClassTypeInfo") + val getObjectTypeInfo = internalFunction("getObjectTypeInfo") + val kClassImpl = internalClass("KClassImpl") + val kClassImplConstructor by lazy { kClassImpl.constructors.single() } + val kClassUnsupportedImpl = internalClass("KClassUnsupportedImpl") + val kClassUnsupportedImplConstructor by lazy { kClassUnsupportedImpl.constructors.single() } + val kTypeParameterImpl = internalClass("KTypeParameterImpl") + val kTypeImpl = internalClass("KTypeImpl") + val kTypeImplForTypeParametersWithRecursiveBounds = internalClass("KTypeImplForTypeParametersWithRecursiveBounds") + + val kTypeProjection = symbolTable.referenceClass(context.reflectionTypes.kTypeProjection) + + private val kTypeProjectionCompanionDescriptor = context.reflectionTypes.kTypeProjection.companionObjectDescriptor!! + + val kTypeProjectionCompanion = symbolTable.referenceClass(kTypeProjectionCompanionDescriptor) + + val kTypeProjectionStar = symbolTable.referenceProperty( + kTypeProjectionCompanionDescriptor.unsubstitutedMemberScope + .getContributedVariables(Name.identifier("STAR"), NoLookupLocation.FROM_BACKEND).single() + ) + + val kTypeProjectionFactories: Map = Variance.values().toList().associateWith { + val factoryName = when (it) { + Variance.INVARIANT -> "invariant" + Variance.IN_VARIANCE -> "contravariant" + Variance.OUT_VARIANCE -> "covariant" + } + + symbolTable.referenceSimpleFunction( + kTypeProjectionCompanionDescriptor.unsubstitutedMemberScope + .getContributedFunctions(Name.identifier(factoryName), NoLookupLocation.FROM_BACKEND).single() + ) + } + + val emptyList = symbolTable.referenceSimpleFunction( + kotlinCollectionsPackageScope + .getContributedFunctions(Name.identifier("emptyList"), NoLookupLocation.FROM_BACKEND) + .single { it.valueParameters.isEmpty() } + ) + + val listOf = symbolTable.referenceSimpleFunction( + kotlinCollectionsPackageScope + .getContributedFunctions(Name.identifier("listOf"), NoLookupLocation.FROM_BACKEND) + .single { it.valueParameters.size == 1 && it.valueParameters[0].isVararg } + ) + val listOfInternal = internalFunction("listOfInternal") + + val threadLocal = symbolTable.referenceClass( + context.builtIns.builtInsModule.findClassAcrossModuleDependencies( + ClassId.topLevel(KonanFqNames.threadLocal))!!) + + val sharedImmutable = symbolTable.referenceClass( + context.builtIns.builtInsModule.findClassAcrossModuleDependencies( + ClassId.topLevel(KonanFqNames.sharedImmutable))!!) + + private fun topLevelClass(fqName: String): IrClassSymbol = topLevelClass(FqName(fqName)) + private fun topLevelClass(fqName: FqName): IrClassSymbol = classById(ClassId.topLevel(fqName)) + private fun classById(classId: ClassId): IrClassSymbol = + symbolTable.referenceClass(builtIns.builtInsModule.findClassAcrossModuleDependencies(classId)!!) + + private fun internalFunction(name: String): IrSimpleFunctionSymbol = + symbolTable.referenceSimpleFunction(context.getKonanInternalFunctions(name).single()) + + private fun internalClass(name: String): IrClassSymbol = + symbolTable.referenceClass(context.getKonanInternalClass(name)) + + private fun getKonanTestClass(className: String) = symbolTable.referenceClass( + builtInsPackage("kotlin", "native", "internal", "test").getContributedClassifier( + Name.identifier(className), NoLookupLocation.FROM_BACKEND + ) as ClassDescriptor) + + private fun interopFunction(name: String) = symbolTable.referenceSimpleFunction( + context.interopBuiltIns.packageScope + .getContributedFunctions(Name.identifier(name), NoLookupLocation.FROM_BACKEND) + .single() + ) + + private fun interopClass(name: String) = symbolTable.referenceClass( + context.interopBuiltIns.packageScope + .getContributedClassifier(Name.identifier(name), NoLookupLocation.FROM_BACKEND) as ClassDescriptor + ) + + override fun functionN(n: Int) = functionIrClassFactory.functionN(n).symbol + + override fun suspendFunctionN(n: Int) = functionIrClassFactory.suspendFunctionN(n).symbol + + fun kFunctionN(n: Int) = functionIrClassFactory.kFunctionN(n).symbol + + fun kSuspendFunctionN(n: Int) = functionIrClassFactory.kSuspendFunctionN(n).symbol + + fun getKFunctionType(returnType: IrType, parameterTypes: List) = + kFunctionN(parameterTypes.size).typeWith(parameterTypes + returnType) + + val baseClassSuite = getKonanTestClass("BaseClassSuite") + val topLevelSuite = getKonanTestClass("TopLevelSuite") + val testFunctionKind = getKonanTestClass("TestFunctionKind") + + private val testFunctionKindCache = TestProcessor.FunctionKind.values().associate { + val symbol = if (it.runtimeKindString.isEmpty()) + null + else + symbolTable.referenceEnumEntry(testFunctionKind.descriptor.unsubstitutedMemberScope.getContributedClassifier( + Name.identifier(it.runtimeKindString), NoLookupLocation.FROM_BACKEND + ) as ClassDescriptor) + it to symbol + } + + fun getTestFunctionKind(kind: TestProcessor.FunctionKind) = testFunctionKindCache[kind]!! +} + +private fun getArrayListClassDescriptor(context: Context): ClassDescriptor { + val module = context.builtIns.builtInsModule + val pkg = module.getPackage(FqName.fromSegments(listOf("kotlin", "collections"))) + val classifier = pkg.memberScope.getContributedClassifier(Name.identifier("ArrayList"), + NoLookupLocation.FROM_BACKEND) + + return classifier as ClassDescriptor +} diff --git a/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/ir/IrTypeAsKotlinType.kt b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/ir/IrTypeAsKotlinType.kt new file mode 100644 index 00000000000..a52a178338f --- /dev/null +++ b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/ir/IrTypeAsKotlinType.kt @@ -0,0 +1,64 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +package org.jetbrains.kotlin.backend.konan.ir + +import org.jetbrains.kotlin.ir.declarations.IrClass +import org.jetbrains.kotlin.ir.symbols.IrClassSymbol +import org.jetbrains.kotlin.ir.symbols.IrClassifierSymbol +import org.jetbrains.kotlin.ir.symbols.IrTypeParameterSymbol +import org.jetbrains.kotlin.ir.types.* +import org.jetbrains.kotlin.ir.types.impl.IrSimpleTypeImpl +import org.jetbrains.kotlin.ir.types.impl.IrStarProjectionImpl +import org.jetbrains.kotlin.types.KotlinType +import org.jetbrains.kotlin.types.typeUtil.isSubtypeOf + +val IrClassifierSymbol.typeWithoutArguments: IrType + get() = when (this) { + is IrClassSymbol -> { + require(this.descriptor.declaredTypeParameters.isEmpty()) + this.typeWith(arguments = emptyList()) + } + is IrTypeParameterSymbol -> this.defaultType + else -> error(this) + } + +val IrClassifierSymbol.typeWithStarProjections + get() = when (this) { + is IrClassSymbol -> createType( + hasQuestionMark = false, + arguments = this.descriptor.declaredTypeParameters.map { IrStarProjectionImpl } + ) + is IrTypeParameterSymbol -> this.defaultType + else -> error(this) + } + +val IrTypeParameterSymbol.defaultType: IrType get() = IrSimpleTypeImpl( + this, + false, + emptyList(), + emptyList() +) + +fun IrClass.typeWith(arguments: List) = this.symbol.typeWith(arguments) + +fun IrType.containsNull(): Boolean = if (this is IrSimpleType) { + if (this.hasQuestionMark) { + true + } else { + val classifier = this.classifier + when (classifier) { + is IrClassSymbol -> false + is IrTypeParameterSymbol -> classifier.owner.superTypes.any { it.containsNull() } + else -> error(classifier) + } + } +} else { + true +} + +// TODO: get rid of these: +fun IrType.isSubtypeOf(other: KotlinType): Boolean = this.toKotlinType().isSubtypeOf(other) +fun IrType.isSubtypeOf(other: IrType): Boolean = this.isSubtypeOf(other.toKotlinType()) diff --git a/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/ir/ModuleIndex.kt b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/ir/ModuleIndex.kt new file mode 100644 index 00000000000..b07d70a5412 --- /dev/null +++ b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/ir/ModuleIndex.kt @@ -0,0 +1,49 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +package org.jetbrains.kotlin.backend.konan.ir + +import org.jetbrains.kotlin.descriptors.ClassDescriptor +import org.jetbrains.kotlin.descriptors.FunctionDescriptor +import org.jetbrains.kotlin.ir.IrElement +import org.jetbrains.kotlin.ir.declarations.* +import org.jetbrains.kotlin.ir.visitors.IrElementVisitorVoid +import org.jetbrains.kotlin.ir.visitors.acceptChildrenVoid +import org.jetbrains.kotlin.ir.visitors.acceptVoid + +class ModuleIndex(val module: IrModuleFragment) { + + /** + * Contains all classes declared in [module] + */ + val classes: Map + + /** + * Contains all functions declared in [module] + */ + val functions: Map + + init { + classes = mutableMapOf() + functions = mutableMapOf() + + module.acceptVoid(object : IrElementVisitorVoid { + override fun visitElement(element: IrElement) { + element.acceptChildrenVoid(this) + } + + override fun visitClass(declaration: IrClass) { + super.visitClass(declaration) + + classes[declaration.descriptor] = declaration + } + + override fun visitFunction(declaration: IrFunction) { + super.visitFunction(declaration) + functions[declaration.descriptor] = declaration + } + }) + } +} diff --git a/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/ir/NewIrUtils.kt b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/ir/NewIrUtils.kt new file mode 100644 index 00000000000..606317321b0 --- /dev/null +++ b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/ir/NewIrUtils.kt @@ -0,0 +1,103 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +package org.jetbrains.kotlin.backend.konan.ir + +import org.jetbrains.kotlin.backend.common.atMostOne +import org.jetbrains.kotlin.backend.konan.DECLARATION_ORIGIN_INLINE_CLASS_SPECIAL_FUNCTION +import org.jetbrains.kotlin.descriptors.Modality +import org.jetbrains.kotlin.descriptors.DescriptorVisibilities +import org.jetbrains.kotlin.ir.declarations.* +import org.jetbrains.kotlin.ir.descriptors.IrBuiltIns +import org.jetbrains.kotlin.ir.expressions.IrCall +import org.jetbrains.kotlin.ir.expressions.IrConst +import org.jetbrains.kotlin.ir.expressions.IrConstructorCall +import org.jetbrains.kotlin.ir.expressions.IrExpression +import org.jetbrains.kotlin.ir.expressions.impl.IrConstImpl +import org.jetbrains.kotlin.ir.expressions.impl.IrConstructorCallImpl +import org.jetbrains.kotlin.ir.symbols.IrClassSymbol +import org.jetbrains.kotlin.ir.symbols.isPublicApi +import org.jetbrains.kotlin.ir.types.IdSignatureValues +import org.jetbrains.kotlin.ir.types.classifierOrFail +import org.jetbrains.kotlin.ir.types.isMarkedNullable +import org.jetbrains.kotlin.ir.util.* +import org.jetbrains.kotlin.name.FqName +import org.jetbrains.kotlin.name.Name +import org.jetbrains.kotlin.utils.addToStdlib.safeAs + +private fun IrClass.isClassTypeWithSignature(signature: IdSignature.PublicSignature): Boolean { + if (!symbol.isPublicApi) return false + return signature == symbol.signature +} + +fun IrClass.isUnit() = this.isClassTypeWithSignature(IdSignatureValues.unit) + +fun IrClass.isKotlinArray() = this.isClassTypeWithSignature(IdSignatureValues.array) + +val IrClass.superClasses get() = this.superTypes.map { it.classifierOrFail as IrClassSymbol } +fun IrClass.getSuperClassNotAny() = this.superClasses.map { it.owner }.atMostOne { !it.isInterface && !it.isAny() } + +fun IrClass.isAny() = this.isClassTypeWithSignature(IdSignatureValues.any) + +fun IrClass.isNothing() = this.isClassTypeWithSignature(IdSignatureValues.nothing) + +fun IrClass.getSuperInterfaces() = this.superClasses.map { it.owner }.filter { it.isInterface } + +// Note: psi2ir doesn't set `origin = FAKE_OVERRIDE` for fields and properties yet. +val IrProperty.isReal: Boolean get() = this.descriptor.kind.isReal +val IrField.isReal: Boolean get() = this.descriptor.kind.isReal + +val IrSimpleFunction.isOverridable: Boolean + get() = visibility != DescriptorVisibilities.PRIVATE + && modality != Modality.FINAL + && (parent as? IrClass)?.isFinalClass != true + +val IrFunction.isOverridable get() = this is IrSimpleFunction && this.isOverridable + +val IrFunction.isOverridableOrOverrides + get() = this is IrSimpleFunction && (this.isOverridable || this.overriddenSymbols.isNotEmpty()) + +val IrClass.isFinalClass: Boolean + get() = modality == Modality.FINAL + +fun IrClass.isSpecialClassWithNoSupertypes() = this.isAny() || this.isNothing() + +inline fun IrDeclaration.getAnnotationArgumentValue(fqName: FqName, argumentName: String): T? { + val annotation = this.annotations.findAnnotation(fqName) ?: return null + for (index in 0 until annotation.valueArgumentsCount) { + val parameter = annotation.symbol.owner.valueParameters[index] + if (parameter.name == Name.identifier(argumentName)) { + val actual = annotation.getValueArgument(index).safeAs>() + return actual?.value + } + } + return null +} + +fun IrValueParameter.isInlineParameter(): Boolean = + !this.isNoinline && (this.type.isFunction() || this.type.isSuspendFunction()) && !this.type.isMarkedNullable() + +val IrDeclaration.parentDeclarationsWithSelf: Sequence + get() = generateSequence(this, { it.parent as? IrDeclaration }) + +fun IrClass.companionObject() = this.declarations.filterIsInstance().atMostOne { it.isCompanion } + +fun buildSimpleAnnotation(irBuiltIns: IrBuiltIns, startOffset: Int, endOffset: Int, + annotationClass: IrClass, vararg args: String): IrConstructorCall { + val constructor = annotationClass.constructors.let { + it.singleOrNull() ?: it.single { ctor -> ctor.valueParameters.size == args.size } + } + return IrConstructorCallImpl.fromSymbolOwner(startOffset, endOffset, constructor.returnType, constructor.symbol).apply { + args.forEachIndexed { index, arg -> + assert(constructor.valueParameters[index].type == irBuiltIns.stringType) { + "String type expected but was ${constructor.valueParameters[index].type}" + } + putValueArgument(index, IrConstImpl.string(startOffset, endOffset, irBuiltIns.stringType, arg)) + } + } +} + +internal fun IrExpression.isBoxOrUnboxCall() = + (this is IrCall && symbol.owner.origin == DECLARATION_ORIGIN_INLINE_CLASS_SPECIAL_FUNCTION) diff --git a/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/ir/interop/DescriptorToIrTranslationUtils.kt b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/ir/interop/DescriptorToIrTranslationUtils.kt new file mode 100644 index 00000000000..f9391b4cda4 --- /dev/null +++ b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/ir/interop/DescriptorToIrTranslationUtils.kt @@ -0,0 +1,183 @@ +/* + * Copyright 2010-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ +package org.jetbrains.kotlin.backend.konan.ir.interop + +import org.jetbrains.kotlin.backend.common.ir.createParameterDeclarations +import org.jetbrains.kotlin.backend.konan.InteropBuiltIns +import org.jetbrains.kotlin.descriptors.* +import org.jetbrains.kotlin.ir.builders.IrBuilder +import org.jetbrains.kotlin.ir.declarations.* +import org.jetbrains.kotlin.ir.declarations.impl.IrConstructorImpl +import org.jetbrains.kotlin.ir.descriptors.IrBuiltIns +import org.jetbrains.kotlin.ir.expressions.IrExpression +import org.jetbrains.kotlin.ir.expressions.impl.IrInstanceInitializerCallImpl +import org.jetbrains.kotlin.ir.symbols.IrClassSymbol +import org.jetbrains.kotlin.ir.symbols.IrSymbol +import org.jetbrains.kotlin.ir.types.impl.IrUninitializedType +import org.jetbrains.kotlin.ir.util.* +import org.jetbrains.kotlin.resolve.descriptorUtil.getSuperClassNotAny +import org.jetbrains.kotlin.resolve.descriptorUtil.getSuperInterfaces +import org.jetbrains.kotlin.resolve.descriptorUtil.isEffectivelyExternal +import org.jetbrains.kotlin.resolve.descriptorUtil.parentsWithSelf +import org.jetbrains.kotlin.types.KotlinType + +internal inline fun ClassDescriptor.findDeclarationByName(name: String): T? = + unsubstitutedMemberScope + .getContributedDescriptors() + .filterIsInstance() + .firstOrNull { it.name.identifier == name } + +/** + * Provides a set of functions and properties that helps + * to translate descriptor declarations to corresponding IR. + */ +internal interface DescriptorToIrTranslationMixin { + + val symbolTable: SymbolTable + + val irBuiltIns: IrBuiltIns + + val typeTranslator: TypeTranslator + + fun KotlinType.toIrType() = typeTranslator.translateType(this) + + /** + * Declares [IrClass] instance from [descriptor] and populates it with + * supertypes, parameter declaration and fake overrides. + * Additional elements are passed via [builder] callback. + */ + fun createClass(descriptor: ClassDescriptor, builder: (IrClass) -> Unit): IrClass = + symbolTable.declareClass(descriptor) { + symbolTable.irFactory.createIrClassFromDescriptor( + SYNTHETIC_OFFSET, SYNTHETIC_OFFSET, IrDeclarationOrigin.IR_EXTERNAL_DECLARATION_STUB, it, descriptor + ) + }.also { irClass -> + symbolTable.withScope(descriptor) { + irClass.superTypes += descriptor.typeConstructor.supertypes.map { + it.toIrType() + } + irClass.generateAnnotations() + irClass.createParameterDeclarations() + builder(irClass) + createFakeOverrides(descriptor).forEach(irClass::addMember) + } + } + + private fun createFakeOverrides(classDescriptor: ClassDescriptor): List { + val fakeOverrides = classDescriptor.unsubstitutedMemberScope + .getContributedDescriptors() + .filterIsInstance() + .filter { it.kind == CallableMemberDescriptor.Kind.FAKE_OVERRIDE } + return fakeOverrides.map { + when (it) { + is PropertyDescriptor -> createProperty(it) + is FunctionDescriptor -> createFunction(it, IrDeclarationOrigin.FAKE_OVERRIDE) + else -> error("Unexpected fake override descriptor: $it") + } + } + } + + fun createConstructor(constructorDescriptor: ClassConstructorDescriptor): IrConstructor { + val irConstructor = symbolTable.declareConstructor(constructorDescriptor) { + with(constructorDescriptor) { + IrConstructorImpl( + SYNTHETIC_OFFSET, SYNTHETIC_OFFSET, IrDeclarationOrigin.IR_EXTERNAL_DECLARATION_STUB, it, name, visibility, + IrUninitializedType, isInline, isEffectivelyExternal(), isPrimary, isExpect + ) + } + } + irConstructor.valueParameters += constructorDescriptor.valueParameters.map { valueParameterDescriptor -> + symbolTable.declareValueParameter( + SYNTHETIC_OFFSET, SYNTHETIC_OFFSET, IrDeclarationOrigin.DEFINED, + valueParameterDescriptor, + valueParameterDescriptor.type.toIrType()).also { + it.parent = irConstructor + } + } + irConstructor.returnType = constructorDescriptor.returnType.toIrType() + irConstructor.generateAnnotations() + return irConstructor + } + + fun createProperty(propertyDescriptor: PropertyDescriptor): IrProperty { + val origin = if (propertyDescriptor.kind == CallableMemberDescriptor.Kind.FAKE_OVERRIDE) { + IrDeclarationOrigin.FAKE_OVERRIDE + } else { + IrDeclarationOrigin.IR_EXTERNAL_DECLARATION_STUB + } + val irProperty = symbolTable.declareProperty(SYNTHETIC_OFFSET, SYNTHETIC_OFFSET, origin, propertyDescriptor) + irProperty.getter = propertyDescriptor.getter?.let { + val irGetter = createFunction(it, origin) + irGetter.correspondingPropertySymbol = irProperty.symbol + irGetter + } + irProperty.setter = propertyDescriptor.setter?.let { + val irSetter = createFunction(it, origin) + irSetter.correspondingPropertySymbol = irProperty.symbol + irSetter + } + irProperty.generateAnnotations() + return irProperty + } + + fun createFunction( + functionDescriptor: FunctionDescriptor, + origin: IrDeclarationOrigin = IrDeclarationOrigin.IR_EXTERNAL_DECLARATION_STUB + ): IrSimpleFunction { + val irFunction = symbolTable.declareSimpleFunctionWithOverrides(SYNTHETIC_OFFSET, SYNTHETIC_OFFSET, origin, functionDescriptor) + symbolTable.withScope(functionDescriptor) { + irFunction.returnType = functionDescriptor.returnType!!.toIrType() + irFunction.valueParameters += functionDescriptor.valueParameters.map { + symbolTable.declareValueParameter(SYNTHETIC_OFFSET, SYNTHETIC_OFFSET, IrDeclarationOrigin.DEFINED, it, it.type.toIrType()) + } + irFunction.dispatchReceiverParameter = functionDescriptor.dispatchReceiverParameter?.let { + symbolTable.declareValueParameter(SYNTHETIC_OFFSET, SYNTHETIC_OFFSET, IrDeclarationOrigin.DEFINED, it, it.type.toIrType()) + } + irFunction.generateAnnotations() + } + return irFunction + } + + private fun IrDeclaration.generateAnnotations() { + annotations += descriptor.annotations.map { + typeTranslator.constantValueGenerator.generateAnnotationConstructorCall(it)!! + } + } +} + +internal fun IrBuilder.irInstanceInitializer(classSymbol: IrClassSymbol): IrExpression = + IrInstanceInitializerCallImpl( + startOffset, endOffset, + classSymbol, + context.irBuiltIns.unitType + ) + +internal fun ClassDescriptor.implementsCEnum(interopBuiltIns: InteropBuiltIns): Boolean = + interopBuiltIns.cEnum in this.getSuperInterfaces() + +internal fun ClassDescriptor.inheritsFromCStructVar(interopBuiltIns: InteropBuiltIns): Boolean = + interopBuiltIns.cStructVar == this.getSuperClassNotAny() + +/** + * All enums that come from interop library implement CEnum interface. + * This function checks that given symbol located in subtree of + * CEnum inheritor. + */ +internal fun IrSymbol.findCEnumDescriptor(interopBuiltIns: InteropBuiltIns): ClassDescriptor? = + descriptor.findCEnumDescriptor(interopBuiltIns) + +internal fun DeclarationDescriptor.findCEnumDescriptor(interopBuiltIns: InteropBuiltIns): ClassDescriptor? = + parentsWithSelf.filterIsInstance().firstOrNull { it.implementsCEnum(interopBuiltIns) } + +/** + * All structs that come from interop library inherit from CStructVar class. + * This function checks that given symbol located in subtree of + * CStructVar inheritor. + */ +internal fun IrSymbol.findCStructDescriptor(interopBuiltIns: InteropBuiltIns): ClassDescriptor? = + descriptor.findCStructDescriptor(interopBuiltIns) + +internal fun DeclarationDescriptor.findCStructDescriptor(interopBuiltIns: InteropBuiltIns): ClassDescriptor? = + parentsWithSelf.filterIsInstance().firstOrNull { it.inheritsFromCStructVar(interopBuiltIns) } \ No newline at end of file diff --git a/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/ir/interop/IrProviderForCEnumAndCStructStubs.kt b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/ir/interop/IrProviderForCEnumAndCStructStubs.kt new file mode 100644 index 00000000000..3b24ca60afc --- /dev/null +++ b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/ir/interop/IrProviderForCEnumAndCStructStubs.kt @@ -0,0 +1,103 @@ +/* + * Copyright 2010-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ +package org.jetbrains.kotlin.backend.konan.ir.interop + +import org.jetbrains.kotlin.backend.common.serialization.encodings.BinarySymbolData +import org.jetbrains.kotlin.backend.konan.InteropBuiltIns +import org.jetbrains.kotlin.backend.konan.descriptors.getPackageFragments +import org.jetbrains.kotlin.backend.konan.ir.KonanSymbols +import org.jetbrains.kotlin.backend.konan.ir.interop.cenum.CEnumByValueFunctionGenerator +import org.jetbrains.kotlin.backend.konan.ir.interop.cenum.CEnumClassGenerator +import org.jetbrains.kotlin.backend.konan.ir.interop.cenum.CEnumCompanionGenerator +import org.jetbrains.kotlin.backend.konan.ir.interop.cenum.CEnumVarClassGenerator +import org.jetbrains.kotlin.backend.konan.ir.interop.cstruct.CStructVarClassGenerator +import org.jetbrains.kotlin.descriptors.* +import org.jetbrains.kotlin.ir.declarations.* +import org.jetbrains.kotlin.ir.symbols.* +import org.jetbrains.kotlin.ir.util.* +import org.jetbrains.kotlin.psi2ir.generators.GeneratorContext +import org.jetbrains.kotlin.resolve.scopes.DescriptorKindFilter + +/** + * For the most of descriptors that come from metadata-based interop libraries + * we generate a lazy IR. + * We use a different approach for CEnums and CStructVars and generate IR eagerly. Motivation: + * 1. CEnums are "real" Kotlin enums. Thus, we need apply the same compilation approach + * as we use for usual Kotlin enums. + * Eager generation allows to reuse [EnumClassLowering], [EnumConstructorsLowering] and other + * compiler phases. + * 2. It is an easier and more obvious approach. Since implementation of metadata-based + * libraries generation already took too much time we take an easier approach here. + */ +internal class IrProviderForCEnumAndCStructStubs( + context: GeneratorContext, + private val interopBuiltIns: InteropBuiltIns, + symbols: KonanSymbols +) { + + /** + * TODO: integrate this provider into [KonanIrLinker.KonanInteropModuleDeserializer] + */ + private val symbolTable: SymbolTable = context.symbolTable + + private val cEnumByValueFunctionGenerator = + CEnumByValueFunctionGenerator(context, symbols) + private val cEnumCompanionGenerator = + CEnumCompanionGenerator(context, cEnumByValueFunctionGenerator) + private val cEnumVarClassGenerator = + CEnumVarClassGenerator(context, interopBuiltIns) + private val cEnumClassGenerator = + CEnumClassGenerator(context, cEnumCompanionGenerator, cEnumVarClassGenerator) + private val cStructClassGenerator = + CStructVarClassGenerator(context, interopBuiltIns) + + fun isCEnumOrCStruct(declarationDescriptor: DeclarationDescriptor): Boolean = + declarationDescriptor.run { findCEnumDescriptor(interopBuiltIns) ?: findCStructDescriptor(interopBuiltIns) } != null + + fun referenceAllEnumsAndStructsFrom(interopModule: ModuleDescriptor) = interopModule.getPackageFragments() + .flatMap { it.getMemberScope().getContributedDescriptors(DescriptorKindFilter.CLASSIFIERS) } + .filterIsInstance() + .filter { it.implementsCEnum(interopBuiltIns) || it.inheritsFromCStructVar(interopBuiltIns) } + .forEach { symbolTable.referenceClass(it) } + + private fun generateIrIfNeeded(symbol: IrSymbol, file: IrFile) { + // TODO: These `findOrGenerate` calls generate a whole subtree. + // This a simple but clearly suboptimal solution. + symbol.findCEnumDescriptor(interopBuiltIns)?.let { enumDescriptor -> + cEnumClassGenerator.findOrGenerateCEnum(enumDescriptor, file) + } + symbol.findCStructDescriptor(interopBuiltIns)?.let { structDescriptor -> + cStructClassGenerator.findOrGenerateCStruct(structDescriptor, file) + } + } + + fun getDeclaration(descriptor: DeclarationDescriptor, idSignature: IdSignature, file: IrFile, symbolKind: BinarySymbolData.SymbolKind): IrSymbolOwner { + return symbolTable.run { + when (symbolKind) { + BinarySymbolData.SymbolKind.CLASS_SYMBOL -> declareClassFromLinker(descriptor as ClassDescriptor, idSignature) { s -> + generateIrIfNeeded(s, file) + s.owner + } + BinarySymbolData.SymbolKind.ENUM_ENTRY_SYMBOL -> declareEnumEntryFromLinker(descriptor as ClassDescriptor, idSignature) { s -> + generateIrIfNeeded(s, file) + s.owner + } + BinarySymbolData.SymbolKind.FUNCTION_SYMBOL -> declareSimpleFunctionFromLinker(descriptor as FunctionDescriptor, idSignature) { s -> + generateIrIfNeeded(s, file) + s.owner + } + BinarySymbolData.SymbolKind.PROPERTY_SYMBOL -> declarePropertyFromLinker(descriptor as PropertyDescriptor, idSignature) { s -> + generateIrIfNeeded(s, file) + s.owner + } + else -> error("Unexpected symbol kind $symbolKind for sig $idSignature") + } + } + } + + companion object { + const val cTypeDefinitionsFileName = "CTypeDefinitions" + } +} \ No newline at end of file diff --git a/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/ir/interop/cenum/CEnumByValueFunctionGenerator.kt b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/ir/interop/cenum/CEnumByValueFunctionGenerator.kt new file mode 100644 index 00000000000..eab5171e6c0 --- /dev/null +++ b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/ir/interop/cenum/CEnumByValueFunctionGenerator.kt @@ -0,0 +1,95 @@ +/* + * Copyright 2010-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ +package org.jetbrains.kotlin.backend.konan.ir.interop.cenum + +import org.jetbrains.kotlin.backend.konan.ir.KonanSymbols +import org.jetbrains.kotlin.backend.konan.ir.interop.DescriptorToIrTranslationMixin +import org.jetbrains.kotlin.backend.konan.ir.interop.findDeclarationByName +import org.jetbrains.kotlin.descriptors.FunctionDescriptor +import org.jetbrains.kotlin.ir.builders.* +import org.jetbrains.kotlin.ir.declarations.IrClass +import org.jetbrains.kotlin.ir.declarations.IrFunction +import org.jetbrains.kotlin.ir.descriptors.IrBuiltIns +import org.jetbrains.kotlin.ir.symbols.IrSimpleFunctionSymbol +import org.jetbrains.kotlin.ir.types.classOrNull +import org.jetbrains.kotlin.ir.types.getClass +import org.jetbrains.kotlin.ir.util.* +import org.jetbrains.kotlin.ir.util.irCall +import org.jetbrains.kotlin.psi2ir.generators.GeneratorContext +import org.jetbrains.kotlin.util.OperatorNameConventions + +/** + * Generate IR for function that returns appropriate enum entry for the provided integral value. + */ +internal class CEnumByValueFunctionGenerator( + context: GeneratorContext, + private val symbols: KonanSymbols +) : DescriptorToIrTranslationMixin { + + override val irBuiltIns: IrBuiltIns = context.irBuiltIns + override val symbolTable: SymbolTable = context.symbolTable + override val typeTranslator: TypeTranslator = context.typeTranslator + + fun generateByValueFunction( + companionIrClass: IrClass, + valuesIrFunctionSymbol: IrSimpleFunctionSymbol + ): IrFunction { + val byValueFunctionDescriptor = companionIrClass.descriptor.findDeclarationByName("byValue")!! + val byValueIrFunction = createFunction(byValueFunctionDescriptor) + val irValueParameter = byValueIrFunction.valueParameters.first() + // val values: Array = values() + // var i: Int = 0 + // val size: Int = values.size + // while (i < size) { + // val entry: E = values[i] + // if (entry.value == arg) { + // return entry + // } + // i++ + // } + // throw NPE + byValueIrFunction.body = irBuilder(irBuiltIns, byValueIrFunction.symbol, SYNTHETIC_OFFSET, SYNTHETIC_OFFSET).irBlockBody { + +irReturn(irBlock { + val values = irTemporary(irCall(valuesIrFunctionSymbol), isMutable = true) + val inductionVariable = irTemporary(irInt(0), isMutable = true) + val arrayClass = values.type.classOrNull!! + val valuesSize = irCall(symbols.arraySize.getValue(arrayClass), irBuiltIns.intType).also { irCall -> + irCall.dispatchReceiver = irGet(values) + } + val getElementFn = symbols.arrayGet.getValue(arrayClass) + val plusFun = symbols.getBinaryOperator(OperatorNameConventions.PLUS, irBuiltIns.intType, irBuiltIns.intType) + val lessFunctionSymbol = irBuiltIns.lessFunByOperandType.getValue(irBuiltIns.intClass) + +irWhile().also { loop -> + loop.condition = irCall(lessFunctionSymbol, irBuiltIns.booleanType).also { irCall -> + irCall.putValueArgument(0, irGet(inductionVariable)) + irCall.putValueArgument(1, valuesSize) + } + loop.body = irBlock { + val entry = irTemporary(irCall(getElementFn, byValueIrFunction.returnType).also { irCall -> + irCall.dispatchReceiver = irGet(values) + irCall.putValueArgument(0, irGet(inductionVariable)) + }, isMutable = true) + val valueGetter = entry.type.getClass()!!.getPropertyGetter("value")!! + val entryValue = irGet(irValueParameter.type, irGet(entry), valueGetter) + +irIfThenElse( + type = irBuiltIns.unitType, + condition = irEquals(entryValue, irGet(irValueParameter)), + thenPart = irReturn(irGet(entry)), + elsePart = irSetVar( + inductionVariable, + irCallOp(plusFun, irBuiltIns.intType, + irGet(inductionVariable), + irInt(1) + ) + ) + ) + } + } + +irCall(symbols.throwNullPointerException, irBuiltIns.nothingType) + }) + } + return byValueIrFunction + } +} \ No newline at end of file diff --git a/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/ir/interop/cenum/CEnumClassGenerator.kt b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/ir/interop/cenum/CEnumClassGenerator.kt new file mode 100644 index 00000000000..bc2da7010e0 --- /dev/null +++ b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/ir/interop/cenum/CEnumClassGenerator.kt @@ -0,0 +1,162 @@ +/* + * Copyright 2010-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ +package org.jetbrains.kotlin.backend.konan.ir.interop.cenum + +import org.jetbrains.kotlin.backend.konan.descriptors.enumEntries +import org.jetbrains.kotlin.backend.konan.ir.interop.DescriptorToIrTranslationMixin +import org.jetbrains.kotlin.backend.konan.ir.interop.findDeclarationByName +import org.jetbrains.kotlin.backend.konan.ir.interop.irInstanceInitializer +import org.jetbrains.kotlin.descriptors.ClassDescriptor +import org.jetbrains.kotlin.descriptors.DeclarationDescriptor +import org.jetbrains.kotlin.descriptors.PropertyDescriptor +import org.jetbrains.kotlin.descriptors.DescriptorVisibilities +import org.jetbrains.kotlin.ir.builders.* +import org.jetbrains.kotlin.ir.declarations.* +import org.jetbrains.kotlin.ir.descriptors.IrBuiltIns +import org.jetbrains.kotlin.ir.expressions.IrExpression +import org.jetbrains.kotlin.ir.expressions.impl.IrEnumConstructorCallImpl +import org.jetbrains.kotlin.ir.expressions.impl.IrExpressionBodyImpl +import org.jetbrains.kotlin.ir.util.* +import org.jetbrains.kotlin.name.FqName +import org.jetbrains.kotlin.name.Name +import org.jetbrains.kotlin.psi2ir.generators.DeclarationGenerator +import org.jetbrains.kotlin.psi2ir.generators.EnumClassMembersGenerator +import org.jetbrains.kotlin.psi2ir.generators.GeneratorContext +import org.jetbrains.kotlin.resolve.constants.ConstantValue +import org.jetbrains.kotlin.utils.addToStdlib.firstNotNullResult + +private fun extractConstantValue(descriptor: DeclarationDescriptor, type: String): ConstantValue<*>? = + descriptor.annotations + .findAnnotation(cEnumEntryValueAnnotationName.child(Name.identifier(type))) + ?.allValueArguments + ?.getValue(Name.identifier("value")) + +private val cEnumEntryValueAnnotationName = FqName("kotlinx.cinterop.internal.ConstantValue") + +private val cEnumEntryValueTypes = setOf( + "Byte", "Short", "Int", "Long", + "UByte", "UShort", "UInt", "ULong" +) + +internal class CEnumClassGenerator( + val context: GeneratorContext, + private val cEnumCompanionGenerator: CEnumCompanionGenerator, + private val cEnumVarClassGenerator: CEnumVarClassGenerator +) : DescriptorToIrTranslationMixin { + + override val irBuiltIns: IrBuiltIns = context.irBuiltIns + override val symbolTable: SymbolTable = context.symbolTable + override val typeTranslator: TypeTranslator = context.typeTranslator + + private val enumClassMembersGenerator = EnumClassMembersGenerator(DeclarationGenerator(context)) + + /** + * Searches for an IR class for [classDescriptor] in symbol table. + * Generates one if absent. + */ + fun findOrGenerateCEnum(classDescriptor: ClassDescriptor, parent: IrDeclarationContainer): IrClass { + val irClassSymbol = symbolTable.referenceClass(classDescriptor) + return if (!irClassSymbol.isBound) { + provideIrClassForCEnum(classDescriptor).also { + it.patchDeclarationParents(parent) + parent.declarations += it + } + } else { + irClassSymbol.owner + } + } + + /** + * The main function that for given [descriptor] of the enum generates the whole + * IR tree including entries, CEnumVar class, and companion objects. + */ + private fun provideIrClassForCEnum(descriptor: ClassDescriptor): IrClass = + createClass(descriptor) { enumIrClass -> + enumIrClass.addMember(createEnumPrimaryConstructor(descriptor)) + enumIrClass.addMember(createValueProperty(enumIrClass)) + descriptor.enumEntries.mapTo(enumIrClass.declarations) { entryDescriptor -> + createEnumEntry(descriptor, entryDescriptor) + } + enumClassMembersGenerator.generateSpecialMembers(enumIrClass) + enumIrClass.addChild(cEnumCompanionGenerator.generate(enumIrClass)) + enumIrClass.addChild(cEnumVarClassGenerator.generate(enumIrClass)) + } + + /** + * Creates `value` property that stores integral value of the enum. + */ + private fun createValueProperty(irClass: IrClass): IrProperty { + val propertyDescriptor = irClass.descriptor + .findDeclarationByName("value") + ?: error("No `value` property in ${irClass.name}") + val irProperty = createProperty(propertyDescriptor) + symbolTable.withScope(propertyDescriptor) { + irProperty.backingField = symbolTable.declareField( + SYNTHETIC_OFFSET, SYNTHETIC_OFFSET, IrDeclarationOrigin.PROPERTY_BACKING_FIELD, + propertyDescriptor, propertyDescriptor.type.toIrType(), DescriptorVisibilities.PRIVATE + ).also { + it.initializer = irBuilder(irBuiltIns, it.symbol, SYNTHETIC_OFFSET, SYNTHETIC_OFFSET).run { + irExprBody(irGet(irClass.primaryConstructor!!.valueParameters[0])) + } + } + } + val getter = irProperty.getter!! + getter.correspondingPropertySymbol = irProperty.symbol + getter.body = irBuilder(irBuiltIns, getter.symbol, SYNTHETIC_OFFSET, SYNTHETIC_OFFSET).irBlockBody { + +irReturn( + irGetField( + irGet(getter.dispatchReceiverParameter!!), + irProperty.backingField!! + ) + ) + } + return irProperty + } + + private fun createEnumEntry(enumDescriptor: ClassDescriptor, entryDescriptor: ClassDescriptor): IrEnumEntry { + return symbolTable.declareEnumEntry( + SYNTHETIC_OFFSET, SYNTHETIC_OFFSET, + IrDeclarationOrigin.IR_EXTERNAL_DECLARATION_STUB, entryDescriptor + ).also { enumEntry -> + enumEntry.initializerExpression = IrExpressionBodyImpl(IrEnumConstructorCallImpl.fromSymbolDescriptor( + SYNTHETIC_OFFSET, SYNTHETIC_OFFSET, + type = irBuiltIns.unitType, + symbol = symbolTable.referenceConstructor(enumDescriptor.unsubstitutedPrimaryConstructor!!), + typeArgumentsCount = 0 // enums can't be generic + ).also { + it.putValueArgument(0, extractEnumEntryValue(entryDescriptor)) + }) + } + } + + /** + * Every enum entry that came from metadata-based interop library is annotated with + * [kotlinx.cinterop.internal.ConstantValue] annotation that holds internal constant value of the + * corresponding entry. + * + * This function extracts value from the annotation. + */ + private fun extractEnumEntryValue(entryDescriptor: ClassDescriptor): IrExpression = + cEnumEntryValueTypes.firstNotNullResult { extractConstantValue(entryDescriptor, it) } ?.let { + context.constantValueGenerator.generateConstantValueAsExpression(SYNTHETIC_OFFSET, SYNTHETIC_OFFSET, it) + } ?: error("Enum entry $entryDescriptor has no appropriate @$cEnumEntryValueAnnotationName annotation!") + + private fun createEnumPrimaryConstructor(descriptor: ClassDescriptor): IrConstructor { + val irConstructor = createConstructor(descriptor.unsubstitutedPrimaryConstructor!!) + val enumConstructor = context.builtIns.enum.constructors.single() + irConstructor.body = irBuilder(irBuiltIns, irConstructor.symbol, SYNTHETIC_OFFSET, SYNTHETIC_OFFSET).irBlockBody { + +IrEnumConstructorCallImpl.fromSymbolDescriptor( + startOffset, endOffset, + context.irBuiltIns.unitType, + symbolTable.referenceConstructor(enumConstructor), + typeArgumentsCount = 1 // kotlin.Enum has a single type parameter. + ).apply { + putTypeArgument(0, descriptor.defaultType.toIrType()) + } + +irInstanceInitializer(symbolTable.referenceClass(descriptor)) + } + return irConstructor + } +} diff --git a/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/ir/interop/cenum/CEnumCompanionGenerator.kt b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/ir/interop/cenum/CEnumCompanionGenerator.kt new file mode 100644 index 00000000000..eafb782eda2 --- /dev/null +++ b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/ir/interop/cenum/CEnumCompanionGenerator.kt @@ -0,0 +1,96 @@ +/* + * Copyright 2010-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ +package org.jetbrains.kotlin.backend.konan.ir.interop.cenum + +import org.jetbrains.kotlin.backend.konan.descriptors.getArgumentValueOrNull +import org.jetbrains.kotlin.backend.konan.ir.interop.DescriptorToIrTranslationMixin +import org.jetbrains.kotlin.backend.konan.ir.interop.irInstanceInitializer +import org.jetbrains.kotlin.descriptors.ClassDescriptor +import org.jetbrains.kotlin.descriptors.PropertyDescriptor +import org.jetbrains.kotlin.ir.builders.irBlockBody +import org.jetbrains.kotlin.ir.builders.irReturn +import org.jetbrains.kotlin.ir.declarations.* +import org.jetbrains.kotlin.ir.descriptors.IrBuiltIns +import org.jetbrains.kotlin.ir.expressions.IrBody +import org.jetbrains.kotlin.ir.expressions.impl.IrDelegatingConstructorCallImpl +import org.jetbrains.kotlin.ir.expressions.impl.IrGetEnumValueImpl +import org.jetbrains.kotlin.ir.symbols.IrEnumEntrySymbol +import org.jetbrains.kotlin.ir.util.* +import org.jetbrains.kotlin.name.FqName +import org.jetbrains.kotlin.psi2ir.generators.GeneratorContext +import org.jetbrains.kotlin.resolve.descriptorUtil.builtIns + +private val cEnumEntryAliasAnnonation = FqName("kotlinx.cinterop.internal.CEnumEntryAlias") + +internal class CEnumCompanionGenerator( + context: GeneratorContext, + private val cEnumByValueFunctionGenerator: CEnumByValueFunctionGenerator +) : DescriptorToIrTranslationMixin { + + override val irBuiltIns: IrBuiltIns = context.irBuiltIns + override val symbolTable: SymbolTable = context.symbolTable + override val typeTranslator: TypeTranslator = context.typeTranslator + + // Depends on already generated `.values()` irFunction. + fun generate(enumClass: IrClass): IrClass = + createClass(enumClass.descriptor.companionObjectDescriptor!!) { companionIrClass -> + companionIrClass.superTypes += irBuiltIns.anyType + companionIrClass.addMember(createCompanionConstructor(companionIrClass.descriptor)) + val valuesFunction = enumClass.functions.single { it.name.identifier == "values" }.symbol + val byValueIrFunction = cEnumByValueFunctionGenerator + .generateByValueFunction(companionIrClass, valuesFunction) + companionIrClass.addMember(byValueIrFunction) + findEntryAliases(companionIrClass.descriptor) + .map { declareEntryAliasProperty(it, enumClass) } + .forEach(companionIrClass::addMember) + } + + private fun createCompanionConstructor(companionObjectDescriptor: ClassDescriptor): IrConstructor { + val anyPrimaryConstructor = companionObjectDescriptor.builtIns.any.unsubstitutedPrimaryConstructor!! + val superConstructorSymbol = symbolTable.referenceConstructor(anyPrimaryConstructor) + return createConstructor(companionObjectDescriptor.unsubstitutedPrimaryConstructor!!).also { + it.body = irBuilder(irBuiltIns, it.symbol, SYNTHETIC_OFFSET, SYNTHETIC_OFFSET).irBlockBody { + +IrDelegatingConstructorCallImpl.fromSymbolDescriptor( + startOffset, endOffset, context.irBuiltIns.unitType, + superConstructorSymbol, + superConstructorSymbol.owner.typeParameters.size, + superConstructorSymbol.owner.valueParameters.size + ) + +irInstanceInitializer(symbolTable.referenceClass(companionObjectDescriptor)) + } + } + } + + /** + * Returns all properties in companion object that represent aliases to + * enum entries. + */ + private fun findEntryAliases(companionDescriptor: ClassDescriptor) = + companionDescriptor.defaultType.memberScope.getContributedDescriptors() + .filterIsInstance() + .filter { it.annotations.hasAnnotation(cEnumEntryAliasAnnonation) } + + private fun fundCorrespondingEnumEntrySymbol(aliasDescriptor: PropertyDescriptor, irClass: IrClass): IrEnumEntrySymbol { + val enumEntryName = aliasDescriptor.annotations + .findAnnotation(cEnumEntryAliasAnnonation)!! + .getArgumentValueOrNull("entryName") + return irClass.declarations.filterIsInstance() + .single { it.name.identifier == enumEntryName }.symbol + } + + private fun generateAliasGetterBody(getter: IrSimpleFunction, entrySymbol: IrEnumEntrySymbol): IrBody = + irBuilder(irBuiltIns, getter.symbol, SYNTHETIC_OFFSET, SYNTHETIC_OFFSET).irBlockBody { + +irReturn( + IrGetEnumValueImpl(startOffset, endOffset, entrySymbol.owner.parentAsClass.defaultType, entrySymbol) + ) + } + + private fun declareEntryAliasProperty(propertyDescriptor: PropertyDescriptor, enumClass: IrClass): IrProperty { + val entrySymbol = fundCorrespondingEnumEntrySymbol(propertyDescriptor, enumClass) + return createProperty(propertyDescriptor).also { + it.getter!!.body = generateAliasGetterBody(it.getter!!, entrySymbol) + } + } +} \ No newline at end of file diff --git a/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/ir/interop/cenum/CEnumVarClassGenerator.kt b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/ir/interop/cenum/CEnumVarClassGenerator.kt new file mode 100644 index 00000000000..aa0a04c6abf --- /dev/null +++ b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/ir/interop/cenum/CEnumVarClassGenerator.kt @@ -0,0 +1,96 @@ +/* + * Copyright 2010-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ +package org.jetbrains.kotlin.backend.konan.ir.interop.cenum + +import org.jetbrains.kotlin.backend.konan.InteropBuiltIns +import org.jetbrains.kotlin.backend.konan.descriptors.getArgumentValueOrNull +import org.jetbrains.kotlin.backend.konan.ir.interop.DescriptorToIrTranslationMixin +import org.jetbrains.kotlin.backend.konan.ir.interop.irInstanceInitializer +import org.jetbrains.kotlin.descriptors.ClassDescriptor +import org.jetbrains.kotlin.incremental.components.NoLookupLocation +import org.jetbrains.kotlin.ir.builders.irBlockBody +import org.jetbrains.kotlin.ir.builders.irGet +import org.jetbrains.kotlin.ir.builders.irInt +import org.jetbrains.kotlin.ir.declarations.IrClass +import org.jetbrains.kotlin.ir.declarations.IrConstructor +import org.jetbrains.kotlin.ir.declarations.IrProperty +import org.jetbrains.kotlin.ir.declarations.addMember +import org.jetbrains.kotlin.ir.descriptors.IrBuiltIns +import org.jetbrains.kotlin.ir.expressions.impl.IrDelegatingConstructorCallImpl +import org.jetbrains.kotlin.ir.util.* +import org.jetbrains.kotlin.name.FqName +import org.jetbrains.kotlin.name.Name +import org.jetbrains.kotlin.psi2ir.generators.GeneratorContext + +private val typeSizeAnnotation = FqName("kotlinx.cinterop.internal.CEnumVarTypeSize") + +internal class CEnumVarClassGenerator( + context: GeneratorContext, + private val interopBuiltIns: InteropBuiltIns +) : DescriptorToIrTranslationMixin { + + override val irBuiltIns: IrBuiltIns = context.irBuiltIns + override val symbolTable: SymbolTable = context.symbolTable + override val typeTranslator: TypeTranslator = context.typeTranslator + + fun generate(enumIrClass: IrClass): IrClass { + val enumVarClassDescriptor = enumIrClass.descriptor.unsubstitutedMemberScope + .getContributedClassifier(Name.identifier("Var"), NoLookupLocation.FROM_BACKEND)!! as ClassDescriptor + return createClass(enumVarClassDescriptor) { enumVarClass -> + enumVarClass.addMember(createPrimaryConstructor(enumVarClass)) + enumVarClass.addMember(createCompanionObject(enumVarClass)) + enumVarClass.addMember(createValueProperty(enumVarClass)) + } + } + + private fun createValueProperty(enumVarClass: IrClass): IrProperty { + val valuePropertyDescriptor = enumVarClass.descriptor.unsubstitutedMemberScope + .getContributedVariables(Name.identifier("value"), NoLookupLocation.FROM_BACKEND).single() + return createProperty(valuePropertyDescriptor) + } + + private fun createPrimaryConstructor(enumVarClass: IrClass): IrConstructor { + val irConstructor = createConstructor(enumVarClass.descriptor.unsubstitutedPrimaryConstructor!!) + val enumVarConstructorSymbol = symbolTable.referenceConstructor( + interopBuiltIns.cEnumVar.unsubstitutedPrimaryConstructor!! + ) + irConstructor.body = irBuilder(irBuiltIns, irConstructor.symbol, SYNTHETIC_OFFSET, SYNTHETIC_OFFSET).irBlockBody { + +IrDelegatingConstructorCallImpl( + startOffset, endOffset, context.irBuiltIns.unitType, enumVarConstructorSymbol, + enumVarConstructorSymbol.owner.typeParameters.size, + enumVarConstructorSymbol.owner.valueParameters.size + ).also { + it.putValueArgument(0, irGet(irConstructor.valueParameters[0])) + } + +irInstanceInitializer(symbolTable.referenceClass(enumVarClass.descriptor)) + } + return irConstructor + } + + private fun createCompanionObject(enumVarClass: IrClass): IrClass = + createClass(enumVarClass.descriptor.companionObjectDescriptor!!) { companionIrClass -> + val typeSize = companionIrClass.descriptor.annotations + .findAnnotation(typeSizeAnnotation)!! + .getArgumentValueOrNull("size")!! + companionIrClass.addMember(createCompanionConstructor(companionIrClass.descriptor, typeSize)) + } + + private fun createCompanionConstructor(companionObjectDescriptor: ClassDescriptor, typeSize: Int): IrConstructor { + val superConstructorSymbol = symbolTable.referenceConstructor(interopBuiltIns.cPrimitiveVarType.unsubstitutedPrimaryConstructor!!) + return createConstructor(companionObjectDescriptor.unsubstitutedPrimaryConstructor!!).also { + it.body = irBuilder(irBuiltIns, it.symbol, SYNTHETIC_OFFSET, SYNTHETIC_OFFSET).irBlockBody { + +IrDelegatingConstructorCallImpl.fromSymbolDescriptor( + startOffset, endOffset, context.irBuiltIns.unitType, + superConstructorSymbol, + superConstructorSymbol.owner.typeParameters.size, + superConstructorSymbol.owner.valueParameters.size + ).also { + it.putValueArgument(0, irInt(typeSize)) + } + +irInstanceInitializer(symbolTable.referenceClass(companionObjectDescriptor)) + } + } + } +} diff --git a/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/ir/interop/cstruct/CStructVarClassGenerator.kt b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/ir/interop/cstruct/CStructVarClassGenerator.kt new file mode 100644 index 00000000000..8ab3200b262 --- /dev/null +++ b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/ir/interop/cstruct/CStructVarClassGenerator.kt @@ -0,0 +1,77 @@ +/* + * Copyright 2010-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ +package org.jetbrains.kotlin.backend.konan.ir.interop.cstruct + +import org.jetbrains.kotlin.backend.konan.InteropBuiltIns +import org.jetbrains.kotlin.backend.konan.ir.interop.DescriptorToIrTranslationMixin +import org.jetbrains.kotlin.backend.konan.ir.interop.irInstanceInitializer +import org.jetbrains.kotlin.descriptors.CallableMemberDescriptor +import org.jetbrains.kotlin.descriptors.ClassDescriptor +import org.jetbrains.kotlin.descriptors.PropertyDescriptor +import org.jetbrains.kotlin.ir.builders.irBlockBody +import org.jetbrains.kotlin.ir.builders.irGet +import org.jetbrains.kotlin.ir.declarations.IrClass +import org.jetbrains.kotlin.ir.declarations.IrConstructor +import org.jetbrains.kotlin.ir.declarations.IrDeclarationContainer +import org.jetbrains.kotlin.ir.declarations.addMember +import org.jetbrains.kotlin.ir.descriptors.IrBuiltIns +import org.jetbrains.kotlin.ir.expressions.impl.IrDelegatingConstructorCallImpl +import org.jetbrains.kotlin.ir.util.* +import org.jetbrains.kotlin.psi2ir.generators.GeneratorContext + +internal class CStructVarClassGenerator( + context: GeneratorContext, + private val interopBuiltIns: InteropBuiltIns +) : DescriptorToIrTranslationMixin { + + override val irBuiltIns: IrBuiltIns = context.irBuiltIns + override val symbolTable: SymbolTable = context.symbolTable + override val typeTranslator: TypeTranslator = context.typeTranslator + + private val companionGenerator = CStructVarCompanionGenerator(context, interopBuiltIns) + + fun findOrGenerateCStruct(classDescriptor: ClassDescriptor, parent: IrDeclarationContainer): IrClass { + val irClassSymbol = symbolTable.referenceClass(classDescriptor) + return if (!irClassSymbol.isBound) { + provideIrClassForCStruct(classDescriptor).also { + it.patchDeclarationParents(parent) + parent.declarations += it + } + } else { + irClassSymbol.owner + } + } + + private fun provideIrClassForCStruct(descriptor: ClassDescriptor): IrClass = + createClass(descriptor) { irClass -> + irClass.addMember(createPrimaryConstructor(irClass)) + irClass.addMember(companionGenerator.generate(descriptor)) + descriptor.unsubstitutedMemberScope + .getContributedDescriptors() + .filterIsInstance() + .filter { it.kind != CallableMemberDescriptor.Kind.FAKE_OVERRIDE } + .map(this::createProperty) + .forEach(irClass::addMember) + } + + private fun createPrimaryConstructor(irClass: IrClass): IrConstructor { + val enumVarConstructorSymbol = symbolTable.referenceConstructor( + interopBuiltIns.cStructVar.unsubstitutedPrimaryConstructor!! + ) + return createConstructor(irClass.descriptor.unsubstitutedPrimaryConstructor!!).also { irConstructor -> + irConstructor.body = irBuilder(irBuiltIns, irConstructor.symbol, SYNTHETIC_OFFSET, SYNTHETIC_OFFSET).irBlockBody { + +IrDelegatingConstructorCallImpl.fromSymbolDescriptor( + startOffset, endOffset, + context.irBuiltIns.unitType, enumVarConstructorSymbol, + irConstructor.typeParameters.size, + 1 + ).also { + it.putValueArgument(0, irGet(irConstructor.valueParameters[0])) + } + +irInstanceInitializer(symbolTable.referenceClass(irClass.descriptor)) + } + } + } +} \ No newline at end of file diff --git a/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/ir/interop/cstruct/CStructVarCompanionGenerator.kt b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/ir/interop/cstruct/CStructVarCompanionGenerator.kt new file mode 100644 index 00000000000..2277c7b704d --- /dev/null +++ b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/ir/interop/cstruct/CStructVarCompanionGenerator.kt @@ -0,0 +1,62 @@ +/* + * Copyright 2010-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ +package org.jetbrains.kotlin.backend.konan.ir.interop.cstruct + +import org.jetbrains.kotlin.backend.konan.InteropBuiltIns +import org.jetbrains.kotlin.backend.konan.descriptors.getArgumentValueOrNull +import org.jetbrains.kotlin.backend.konan.ir.interop.DescriptorToIrTranslationMixin +import org.jetbrains.kotlin.backend.konan.ir.interop.irInstanceInitializer +import org.jetbrains.kotlin.descriptors.ClassDescriptor +import org.jetbrains.kotlin.ir.builders.irBlockBody +import org.jetbrains.kotlin.ir.builders.irInt +import org.jetbrains.kotlin.ir.builders.irLong +import org.jetbrains.kotlin.ir.declarations.IrClass +import org.jetbrains.kotlin.ir.declarations.IrConstructor +import org.jetbrains.kotlin.ir.declarations.addMember +import org.jetbrains.kotlin.ir.descriptors.IrBuiltIns +import org.jetbrains.kotlin.ir.expressions.impl.IrDelegatingConstructorCallImpl +import org.jetbrains.kotlin.ir.util.* +import org.jetbrains.kotlin.ir.util.irBuilder +import org.jetbrains.kotlin.name.FqName +import org.jetbrains.kotlin.psi2ir.generators.GeneratorContext + +private val varTypeAnnotationFqName = FqName("kotlinx.cinterop.internal.CStruct.VarType") + +internal class CStructVarCompanionGenerator( + context: GeneratorContext, + private val interopBuiltIns: InteropBuiltIns +) : DescriptorToIrTranslationMixin { + + override val irBuiltIns: IrBuiltIns = context.irBuiltIns + override val symbolTable: SymbolTable = context.symbolTable + override val typeTranslator: TypeTranslator = context.typeTranslator + + fun generate(structDescriptor: ClassDescriptor): IrClass = + createClass(structDescriptor.companionObjectDescriptor!!) { companionIrClass -> + val annotation = companionIrClass.descriptor.annotations + .findAnnotation(varTypeAnnotationFqName)!! + val size = annotation.getArgumentValueOrNull("size")!! + val align = annotation.getArgumentValueOrNull("align")!! + companionIrClass.addMember(createCompanionConstructor(companionIrClass.descriptor, size, align)) + } + + private fun createCompanionConstructor(companionObjectDescriptor: ClassDescriptor, size: Long, align: Int): IrConstructor { + val superConstructorSymbol = symbolTable.referenceConstructor(interopBuiltIns.cStructVarType.unsubstitutedPrimaryConstructor!!) + return createConstructor(companionObjectDescriptor.unsubstitutedPrimaryConstructor!!).also { irConstructor -> + irConstructor.body = irBuilder(irBuiltIns, irConstructor.symbol, SYNTHETIC_OFFSET, SYNTHETIC_OFFSET).irBlockBody { + +IrDelegatingConstructorCallImpl.fromSymbolDescriptor( + startOffset, endOffset, context.irBuiltIns.unitType, + superConstructorSymbol, + irConstructor.typeParameters.size, + 2 + ).also { + it.putValueArgument(0, irLong(size)) + it.putValueArgument(1, irInt(align)) + } + +irInstanceInitializer(symbolTable.referenceClass(companionObjectDescriptor)) + } + } + } +} \ No newline at end of file diff --git a/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/BinaryInterface.kt b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/BinaryInterface.kt new file mode 100644 index 00000000000..3cc6ea68d6f --- /dev/null +++ b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/BinaryInterface.kt @@ -0,0 +1,148 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +package org.jetbrains.kotlin.backend.konan.llvm + +import llvm.LLVMTypeRef +import org.jetbrains.kotlin.backend.common.ir.allParameters +import org.jetbrains.kotlin.backend.common.serialization.mangle.MangleConstant +import org.jetbrains.kotlin.backend.common.serialization.mangle.SpecialDeclarationType +import org.jetbrains.kotlin.backend.konan.RuntimeNames +import org.jetbrains.kotlin.backend.konan.descriptors.externalSymbolOrThrow +import org.jetbrains.kotlin.backend.konan.descriptors.getAnnotationStringValue +import org.jetbrains.kotlin.backend.konan.descriptors.isAbstract +import org.jetbrains.kotlin.backend.konan.ir.isUnit +import org.jetbrains.kotlin.backend.konan.isExternalObjCClass +import org.jetbrains.kotlin.backend.konan.isKotlinObjCClass +import org.jetbrains.kotlin.backend.konan.serialization.AbstractKonanIrMangler +import org.jetbrains.kotlin.ir.declarations.* +import org.jetbrains.kotlin.ir.util.findAnnotation +import org.jetbrains.kotlin.ir.util.fqNameForIrSerialization +import org.jetbrains.kotlin.ir.util.isSuspend +import org.jetbrains.kotlin.ir.util.render +import org.jetbrains.kotlin.konan.library.KonanLibrary +import org.jetbrains.kotlin.library.uniqueName +import org.jetbrains.kotlin.name.Name + + +// This file describes the ABI for Kotlin descriptors of exported declarations. +// TODO: revise the naming scheme to ensure it produces unique names. +// TODO: do not serialize descriptors of non-exported declarations. + +object KonanBinaryInterface { + private val mangler = object : AbstractKonanIrMangler(true) {} + + private val exportChecker = mangler.getExportChecker() + + val IrFunction.functionName: String get() = mangler.run { signatureString } + + val IrFunction.symbolName: String get() = funSymbolNameImpl() + val IrField.symbolName: String get() = + withPrefix(MangleConstant.FIELD_PREFIX, fieldSymbolNameImpl()) + val IrClass.typeInfoSymbolName: String get() = + withPrefix(MangleConstant.CLASS_PREFIX, typeInfoSymbolNameImpl()) + fun isExported(declaration: IrDeclaration) = exportChecker.run { + check(declaration, SpecialDeclarationType.REGULAR) || declaration.isPlatformSpecificExported() + } + + private fun withPrefix(prefix: String, mangle: String) = "$prefix:$mangle" + + private fun IrFunction.funSymbolNameImpl(): String { + if (!isExported(this)) { + throw AssertionError(render()) + } + + if (isExternal) { + this.externalSymbolOrThrow()?.let { + return it + } + } + + this.annotations.findAnnotation(RuntimeNames.exportForCppRuntime)?.let { + val name = it.getAnnotationStringValue() ?: this.name.asString() + return name // no wrapping currently required + } + + return withPrefix(MangleConstant.FUN_PREFIX, mangler.run { mangleString }) + } + + private fun IrField.fieldSymbolNameImpl(): String { + val containingDeclarationPart = parent.fqNameForIrSerialization.let { + if (it.isRoot) "" else "$it." + } + return "$containingDeclarationPart$name" + } + + private fun IrClass.typeInfoSymbolNameImpl(): String { + return this.fqNameForIrSerialization.toString() + } +} + +internal val IrClass.writableTypeInfoSymbolName: String + get() { + assert (this.isExported()) + return "ktypew:" + this.fqNameForIrSerialization.toString() + } + +internal val IrClass.globalObjectStorageSymbolName: String + get() { + assert (this.isExported()) + assert (this.kind.isSingleton) + assert (!this.isUnit()) + + return "kobjref:$fqNameForIrSerialization" + } + +internal val IrClass.threadLocalObjectStorageGetterSymbolName: String + get() { + assert (this.isExported()) + assert (this.kind.isSingleton) + assert (!this.isUnit()) + + return "kobjget:$fqNameForIrSerialization" + } + +internal val IrClass.kotlinObjCClassInfoSymbolName: String + get() { + assert (this.isExported()) + assert (this.isKotlinObjCClass()) + + return "kobjcclassinfo:$fqNameForIrSerialization" + } + +val IrFunction.functionName get() = with(KonanBinaryInterface) { functionName } +val IrFunction.fullName get() = parent.fqNameForIrSerialization.child(Name.identifier(functionName)).asString() + +val IrFunction.symbolName get() = with(KonanBinaryInterface) { symbolName } + +val IrField.symbolName get() = with(KonanBinaryInterface) { symbolName } + +val IrClass.typeInfoSymbolName get() = with(KonanBinaryInterface) { typeInfoSymbolName } + +fun IrDeclaration.isExported() = KonanBinaryInterface.isExported(this) + +// TODO: bring here dependencies of this method? +internal fun RuntimeAware.getLlvmFunctionType(function: IrFunction): LLVMTypeRef { + val returnType = when { + function is IrConstructor -> voidType + function.isSuspend -> kObjHeaderPtr // Suspend functions return Any?. + else -> getLLVMReturnType(function.returnType) + } + val paramTypes = ArrayList(function.allParameters.map { getLLVMType(it.type) }) + if (function.isSuspend) + paramTypes.add(kObjHeaderPtr) // Suspend functions have implicit parameter of type Continuation<>. + if (isObjectType(returnType)) paramTypes.add(kObjHeaderPtrPtr) + + return functionType(returnType, isVarArg = false, paramTypes = paramTypes.toTypedArray()) +} + +internal val IrClass.typeInfoHasVtableAttached: Boolean + get() = !this.isAbstract() && !this.isExternalObjCClass() + +internal val String.moduleConstructorName + get() = "_Konan_init_${this}" + +internal val KonanLibrary.moduleConstructorName + get() = uniqueName.moduleConstructorName diff --git a/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/BitcodePhases.kt b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/BitcodePhases.kt new file mode 100644 index 00000000000..b040bbc5c94 --- /dev/null +++ b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/BitcodePhases.kt @@ -0,0 +1,315 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +package org.jetbrains.kotlin.backend.konan.llvm + +import llvm.* +import org.jetbrains.kotlin.backend.common.phaser.CompilerPhase +import org.jetbrains.kotlin.backend.common.phaser.PhaseConfig +import org.jetbrains.kotlin.backend.common.phaser.PhaserState +import org.jetbrains.kotlin.backend.common.phaser.namedUnitPhase +import org.jetbrains.kotlin.backend.konan.* +import org.jetbrains.kotlin.backend.konan.descriptors.GlobalHierarchyAnalysis +import org.jetbrains.kotlin.backend.konan.lower.RedundantCoercionsCleaner +import org.jetbrains.kotlin.backend.konan.optimizations.* +import org.jetbrains.kotlin.ir.IrElement +import org.jetbrains.kotlin.ir.IrStatement +import org.jetbrains.kotlin.ir.declarations.* +import org.jetbrains.kotlin.ir.util.* +import org.jetbrains.kotlin.ir.visitors.* +import org.jetbrains.kotlin.util.OperatorNameConventions +import org.jetbrains.kotlin.utils.addToStdlib.cast + +internal val contextLLVMSetupPhase = makeKonanModuleOpPhase( + name = "ContextLLVMSetup", + description = "Set up Context for LLVM Bitcode generation", + op = { context, _ -> + // Note that we don't set module target explicitly. + // It is determined by the target of runtime.bc + // (see Llvm class in ContextUtils) + // Which in turn is determined by the clang flags + // used to compile runtime.bc. + llvmContext = LLVMContextCreate()!! + val llvmModule = LLVMModuleCreateWithNameInContext("out", llvmContext)!! + context.llvmModule = llvmModule + context.debugInfo.builder = LLVMCreateDIBuilder(llvmModule) + + // we don't split path to filename and directory to provide enough level uniquely for dsymutil to avoid symbol + // clashing, which happens on linking with libraries produced from intercepting sources. + val filePath = context.config.outputFile.toFileAndFolder(context).path() + + context.debugInfo.compilationUnit = if (context.shouldContainLocationDebugInfo()) DICreateCompilationUnit( + builder = context.debugInfo.builder, + lang = DWARF.language(context.config), + File = filePath, + dir = "", + producer = DWARF.producer, + isOptimized = 0, + flags = "", + rv = DWARF.runtimeVersion(context.config)).cast() + else null + } +) + +internal val createLLVMDeclarationsPhase = makeKonanModuleOpPhase( + name = "CreateLLVMDeclarations", + description = "Map IR declarations to LLVM", + prerequisite = setOf(contextLLVMSetupPhase), + op = { context, _ -> + context.llvmDeclarations = createLlvmDeclarations(context) + context.lifetimes = mutableMapOf() + context.codegenVisitor = CodeGeneratorVisitor(context, context.lifetimes) + } +) + +internal val disposeLLVMPhase = namedUnitPhase( + name = "DisposeLLVM", + description = "Dispose LLVM", + lower = object : CompilerPhase { + override fun invoke(phaseConfig: PhaseConfig, phaserState: PhaserState, context: Context, input: Unit) { + context.disposeLlvm() + } + } +) + +internal val RTTIPhase = makeKonanModuleOpPhase( + name = "RTTI", + description = "RTTI generation", + op = { context, irModule -> + val visitor = RTTIGeneratorVisitor(context) + irModule.acceptVoid(visitor) + visitor.dispose() + } +) + +internal val generateDebugInfoHeaderPhase = makeKonanModuleOpPhase( + name = "GenerateDebugInfoHeader", + description = "Generate debug info header", + op = { context, _ -> generateDebugInfoHeader(context) } +) + +internal val buildDFGPhase = makeKonanModuleOpPhase( + name = "BuildDFG", + description = "Data flow graph building", + op = { context, irModule -> + context.moduleDFG = ModuleDFGBuilder(context, irModule).build() + } +) + +internal val devirtualizationPhase = makeKonanModuleOpPhase( + name = "Devirtualization", + description = "Devirtualization", + prerequisite = setOf(buildDFGPhase), + op = { context, irModule -> + context.devirtualizationAnalysisResult = Devirtualization.run( + irModule, context, context.moduleDFG!!, ExternalModulesDFG(emptyList(), emptyMap(), emptyMap(), emptyMap()) + ) + } +) + +internal val redundantCoercionsCleaningPhase = makeKonanModuleOpPhase( + name = "RedundantCoercionsCleaning", + description = "Redundant coercions cleaning", + op = { context, irModule -> irModule.files.forEach { RedundantCoercionsCleaner(context).lower(it) } } +) + +internal val ghaPhase = makeKonanModuleOpPhase( + name = "GHAPhase", + description = "Global hierarchy analysis", + op = { context, irModule -> GlobalHierarchyAnalysis(context, irModule).run() } +) + +internal val IrFunction.longName: String + get() = "${(parent as? IrClass)?.name?.asString() ?: ""}.${(this as? IrSimpleFunction)?.name ?: ""}" + +internal val dcePhase = makeKonanModuleOpPhase( + name = "DCEPhase", + description = "Dead code elimination", + prerequisite = setOf(devirtualizationPhase), + op = { context, _ -> + val externalModulesDFG = ExternalModulesDFG(emptyList(), emptyMap(), emptyMap(), emptyMap()) + + val callGraph = CallGraphBuilder( + context, context.moduleDFG!!, + externalModulesDFG, + context.devirtualizationAnalysisResult!!, + // For DCE we don't wanna miss any potentially reachable function. + nonDevirtualizedCallSitesUnfoldFactor = Int.MAX_VALUE + ).build() + + val referencedFunctions = mutableSetOf() + callGraph.rootExternalFunctions.forEach { + if (!it.isGlobalInitializer) + referencedFunctions.add(it.irFunction ?: error("No IR for: $it")) + } + for (node in callGraph.directEdges.values) { + if (!node.symbol.isGlobalInitializer) + referencedFunctions.add(node.symbol.irFunction ?: error("No IR for: ${node.symbol}")) + node.callSites.forEach { + assert (!it.isVirtual) { "There should be no virtual calls in the call graph, but was: ${it.actualCallee}" } + referencedFunctions.add(it.actualCallee.irFunction ?: error("No IR for: ${it.actualCallee}")) + } + } + + context.irModule!!.acceptChildrenVoid(object: IrElementVisitorVoid { + override fun visitElement(element: IrElement) { + element.acceptChildrenVoid(this) + } + + override fun visitFunction(declaration: IrFunction) { + // TODO: Generalize somehow, not that graceful. + if (declaration.name == OperatorNameConventions.INVOKE + && declaration.parent.let { it is IrClass && it.defaultType.isFunction() }) { + referencedFunctions.add(declaration) + } + super.visitFunction(declaration) + } + + override fun visitConstructor(declaration: IrConstructor) { + // TODO: NativePointed is the only inline class for which the field's type and + // the constructor parameter's type are different. + // Thus we need to conserve the constructor no matter if it was actually referenced somehow or not. + // See [IrTypeInlineClassesSupport.getInlinedClassUnderlyingType] why. + if (declaration.parentAsClass.name.asString() == InteropFqNames.nativePointedName && declaration.isPrimary) + referencedFunctions.add(declaration) + super.visitConstructor(declaration) + } + }) + + context.irModule!!.transformChildrenVoid(object: IrElementTransformerVoid() { + override fun visitFile(declaration: IrFile): IrFile { + declaration.declarations.removeAll { + (it is IrFunction && !referencedFunctions.contains(it)) + } + return super.visitFile(declaration) + } + + override fun visitClass(declaration: IrClass): IrStatement { + if (declaration == context.ir.symbols.nativePointed) + return super.visitClass(declaration) + declaration.declarations.removeAll { + (it is IrFunction && it.isReal && !referencedFunctions.contains(it)) + } + return super.visitClass(declaration) + } + + override fun visitProperty(declaration: IrProperty): IrStatement { + if (declaration.getter.let { it != null && it.isReal && !referencedFunctions.contains(it) }) { + declaration.getter = null + } + if (declaration.setter.let { it != null && it.isReal && !referencedFunctions.contains(it) }) { + declaration.setter = null + } + return super.visitProperty(declaration) + } + }) + + context.referencedFunctions = referencedFunctions + } +) + +internal val escapeAnalysisPhase = makeKonanModuleOpPhase( + name = "EscapeAnalysis", + description = "Escape analysis", + prerequisite = setOf(buildDFGPhase, devirtualizationPhase), + op = { context, _ -> + val entryPoint = context.ir.symbols.entryPoint?.owner + val externalModulesDFG = ExternalModulesDFG(emptyList(), emptyMap(), emptyMap(), emptyMap()) + val nonDevirtualizedCallSitesUnfoldFactor = + if (entryPoint != null) { + // For a final program it can be safely assumed that what classes we see is what we got, + // so can take those. In theory we can always unfold call sites using type hierarchy, but + // the analysis might converge much, much slower, so take only reasonably small for now. + 5 + } + else { + // Can't tolerate any non-devirtualized call site for a library. + // TODO: What about private virtual functions? + // Note: 0 is also bad - this means that there're no inheritors in the current source set, + // but there might be some provided by the users of the library being produced. + -1 + } + val callGraph = CallGraphBuilder( + context, context.moduleDFG!!, + externalModulesDFG, + context.devirtualizationAnalysisResult!!, + nonDevirtualizedCallSitesUnfoldFactor + ).build() + EscapeAnalysis.computeLifetimes( + context, context.moduleDFG!!, externalModulesDFG, callGraph, context.lifetimes + ) + } +) + +internal val localEscapeAnalysisPhase = makeKonanModuleOpPhase( + name = "LocalEscapeAnalysis", + description = "Local escape analysis", + prerequisite = setOf(buildDFGPhase, devirtualizationPhase), + op = { context, _ -> + LocalEscapeAnalysis.computeLifetimes(context, context.moduleDFG!!, context.lifetimes) + } +) + +internal val codegenPhase = makeKonanModuleOpPhase( + name = "Codegen", + description = "Code generation", + op = { context, irModule -> + irModule.acceptVoid(context.codegenVisitor) + } +) + +internal val finalizeDebugInfoPhase = makeKonanModuleOpPhase( + name = "FinalizeDebugInfo", + description = "Finalize debug info", + op = { context, _ -> + if (context.shouldContainAnyDebugInfo()) { + DIFinalize(context.debugInfo.builder) + } + } +) + +internal val cStubsPhase = makeKonanModuleOpPhase( + name = "CStubs", + description = "C stubs compilation", + op = { context, _ -> produceCStubs(context) } +) + +internal val linkBitcodeDependenciesPhase = makeKonanModuleOpPhase( + name = "LinkBitcodeDependencies", + description = "Link bitcode dependencies", + op = { context, _ -> linkBitcodeDependencies(context) } +) + +internal val bitcodeOptimizationPhase = makeKonanModuleOpPhase( + name = "BitcodeOptimization", + description = "Optimize bitcode", + op = { context, _ -> runLlvmOptimizationPipeline(context) } +) + +internal val produceOutputPhase = namedUnitPhase( + name = "ProduceOutput", + description = "Produce output", + lower = object : CompilerPhase { + override fun invoke(phaseConfig: PhaseConfig, phaserState: PhaserState, context: Context, input: Unit) { + produceOutput(context) + } + } +) + +internal val verifyBitcodePhase = makeKonanModuleOpPhase( + name = "VerifyBitcode", + description = "Verify bitcode", + op = { context, _ -> context.verifyBitCode() } +) + +internal val printBitcodePhase = makeKonanModuleOpPhase( + name = "PrintBitcode", + description = "Print bitcode", + op = { context, _ -> + if (context.shouldPrintBitCode()) { + context.printBitCode() + } + } +) \ No newline at end of file diff --git a/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/CodeGenerator.kt b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/CodeGenerator.kt new file mode 100644 index 00000000000..c326d70c176 --- /dev/null +++ b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/CodeGenerator.kt @@ -0,0 +1,1441 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +package org.jetbrains.kotlin.backend.konan.llvm + + +import kotlinx.cinterop.* +import llvm.* +import org.jetbrains.kotlin.backend.konan.* +import org.jetbrains.kotlin.backend.konan.descriptors.ClassGlobalHierarchyInfo +import org.jetbrains.kotlin.backend.konan.llvm.objc.* +import org.jetbrains.kotlin.konan.target.CompilerOutputKind +import org.jetbrains.kotlin.descriptors.* +import org.jetbrains.kotlin.ir.declarations.* +import org.jetbrains.kotlin.ir.util.* +import org.jetbrains.kotlin.backend.konan.ir.* +import org.jetbrains.kotlin.descriptors.konan.CompiledKlibModuleOrigin +import org.jetbrains.kotlin.ir.expressions.IrDelegatingConstructorCall +import org.jetbrains.kotlin.ir.expressions.IrGetObjectValue +import org.jetbrains.kotlin.ir.expressions.IrReturn +import org.jetbrains.kotlin.konan.ForeignExceptionMode + +private fun IrConstructor.isAnyConstructorDelegation(context: Context): Boolean { + val statements = this.body?.statements ?: return false + if (statements.size != 2) return false + val lastStatement = statements[1] + if (lastStatement !is IrReturn || + (lastStatement.value as? IrGetObjectValue)?.symbol != context.irBuiltIns.unitClass) return false + val constructorCall = statements[0] as? IrDelegatingConstructorCall ?: return false + val constructor = constructorCall.symbol.owner as? IrConstructor ?: return false + return constructor.constructedClass.isAny() + } + +// TODO: shall we memoize that property? +internal fun IrClass.hasConstStateAndNoSideEffects(context: Context): Boolean { + if (!context.shouldOptimize()) return false + if (this.hasAnnotation(KonanFqNames.canBePrecreated)) return true + val fields = context.getLayoutBuilder(this).fields + return fields.isEmpty() && this.constructors.all { it.isAnyConstructorDelegation(context) } +} + +internal class CodeGenerator(override val context: Context) : ContextUtils { + + fun llvmFunction(function: IrFunction): LLVMValueRef = llvmFunctionOrNull(function) ?: error("no function ${function.name} in ${function.file.fqName}") + fun llvmFunctionOrNull(function: IrFunction): LLVMValueRef? = function.llvmFunctionOrNull + val intPtrType = LLVMIntPtrTypeInContext(llvmContext, llvmTargetData)!! + internal val immOneIntPtrType = LLVMConstInt(intPtrType, 1, 1)!! + internal val immThreeIntPtrType = LLVMConstInt(intPtrType, 3, 1)!! + // Keep in sync with OBJECT_TAG_MASK in C++. + internal val immTypeInfoMask = LLVMConstNot(LLVMConstInt(intPtrType, 3, 0)!!)!! + + //-------------------------------------------------------------------------// + + fun typeInfoValue(irClass: IrClass): LLVMValueRef = irClass.llvmTypeInfoPtr + + fun param(fn: IrFunction, i: Int): LLVMValueRef { + assert(i >= 0 && i < countParams(fn)) + return LLVMGetParam(fn.llvmFunction, i)!! + } + + private fun countParams(fn: IrFunction) = LLVMCountParams(fn.llvmFunction) + + fun functionEntryPointAddress(function: IrFunction) = function.entryPointAddress.llvm + fun functionHash(function: IrFunction): LLVMValueRef = function.functionName.localHash.llvm + + fun typeInfoForAllocation(constructedClass: IrClass): LLVMValueRef { + assert(!constructedClass.isObjCClass()) + return typeInfoValue(constructedClass) + } + + fun generateLocationInfo(locationInfo: LocationInfo): DILocationRef? = if (locationInfo.inlinedAt != null) + LLVMCreateLocationInlinedAt(LLVMGetModuleContext(context.llvmModule), locationInfo.line, locationInfo.column, + locationInfo.scope, generateLocationInfo(locationInfo.inlinedAt)) + else + LLVMCreateLocation(LLVMGetModuleContext(context.llvmModule), locationInfo.line, locationInfo.column, locationInfo.scope) + + val objCDataGenerator = when { + context.config.target.family.isAppleFamily -> ObjCDataGenerator(this) + else -> null + } + +} + +internal sealed class ExceptionHandler { + object None : ExceptionHandler() + object Caller : ExceptionHandler() + abstract class Local : ExceptionHandler() { + abstract val unwind: LLVMBasicBlockRef + } +} + +val LLVMValueRef.name:String? + get() = LLVMGetValueName(this)?.toKString() + +val LLVMValueRef.isConst:Boolean + get() = (LLVMIsConstant(this) == 1) + + +internal inline fun generateFunction(codegen: CodeGenerator, + function: IrFunction, + startLocation: LocationInfo? = null, + endLocation: LocationInfo? = null, + code: FunctionGenerationContext.(FunctionGenerationContext) -> R) { + val llvmFunction = codegen.llvmFunction(function) + + val functionGenerationContext = FunctionGenerationContext( + llvmFunction, + codegen, + startLocation, + endLocation, + function) + try { + generateFunctionBody(functionGenerationContext, code) + } finally { + functionGenerationContext.dispose() + } + + // To perform per-function validation. + if (false) + LLVMVerifyFunction(llvmFunction, LLVMVerifierFailureAction.LLVMAbortProcessAction) +} + + +internal inline fun generateFunction(codegen: CodeGenerator, function: LLVMValueRef, + startLocation: LocationInfo? = null, endLocation: LocationInfo? = null, + code:FunctionGenerationContext.(FunctionGenerationContext) -> R) { + val functionGenerationContext = FunctionGenerationContext(function, codegen, startLocation, endLocation) + try { + generateFunctionBody(functionGenerationContext, code) + } finally { + functionGenerationContext.dispose() + } +} + +internal inline fun generateFunction( + codegen: CodeGenerator, + functionType: LLVMTypeRef, + name: String, + block: FunctionGenerationContext.(FunctionGenerationContext) -> Unit +): LLVMValueRef { + val function = LLVMAddFunction(codegen.context.llvmModule, name, functionType)!! + generateFunction(codegen, function, startLocation = null, endLocation = null, code = block) + return function +} + +private inline fun generateFunctionBody( + functionGenerationContext: FunctionGenerationContext, + code: FunctionGenerationContext.(FunctionGenerationContext) -> R) { + functionGenerationContext.prologue() + functionGenerationContext.code(functionGenerationContext) + if (!functionGenerationContext.isAfterTerminator()) + functionGenerationContext.unreachable() + functionGenerationContext.epilogue() + functionGenerationContext.resetDebugLocation() +} + +/** + * There're cases when we don't need end position or it is meaningless. + */ +internal data class LocationInfoRange(var start: LocationInfo, var end: LocationInfo?) + +internal interface StackLocalsManager { + fun alloc(irClass: IrClass, cleanFieldsExplicitly: Boolean): LLVMValueRef + + fun allocArray(irClass: IrClass, count: LLVMValueRef): LLVMValueRef + + fun clean(refsOnly: Boolean) +} + +internal class StackLocalsManagerImpl( + val functionGenerationContext: FunctionGenerationContext, + val bbInitStackLocals: LLVMBasicBlockRef +) : StackLocalsManager { + private class StackLocal(val isArray: Boolean, val irClass: IrClass, + val bodyPtr: LLVMValueRef, val objHeaderPtr: LLVMValueRef) + + private val stackLocals = mutableListOf() + + override fun alloc(irClass: IrClass, cleanFieldsExplicitly: Boolean): LLVMValueRef = with(functionGenerationContext) { + val type = context.llvmDeclarations.forClass(irClass).bodyType + val stackLocal = appendingTo(bbInitStackLocals) { + val stackSlot = LLVMBuildAlloca(builder, type, "")!! + + call(context.llvm.memsetFunction, + listOf(bitcast(kInt8Ptr, stackSlot), + Int8(0).llvm, + Int32(LLVMSizeOfTypeInBits(codegen.llvmTargetData, type).toInt() / 8).llvm, + Int1(0).llvm)) + + val objectHeader = structGep(stackSlot, 0, "objHeader") + val typeInfo = codegen.typeInfoForAllocation(irClass) + setTypeInfoForLocalObject(objectHeader, typeInfo) + StackLocal(false, irClass, stackSlot, objectHeader) + } + + stackLocals += stackLocal + if (cleanFieldsExplicitly) + clean(stackLocal, false) + stackLocal.objHeaderPtr + } + + // Returns generated special type for local array. + // It's needed to prevent changing variables order on stack. + private fun localArrayType(irClass: IrClass, count: Int) = with(functionGenerationContext) { + val name = "local#${irClass.name}${count}#internal" + // Create new type or get already created. + context.declaredLocalArrays.getOrPut(name) { + val fieldTypes = listOf(kArrayHeader, LLVMArrayType(arrayToElementType[irClass.symbol]!!, count)) + val classType = LLVMStructCreateNamed(LLVMGetModuleContext(context.llvmModule), name)!! + LLVMStructSetBody(classType, fieldTypes.toCValues(), fieldTypes.size, 1) + classType + } + } + + private val symbols = functionGenerationContext.context.ir.symbols + // TODO: find better place? + private val arrayToElementType = mapOf( + symbols.array to functionGenerationContext.kObjHeaderPtr, + symbols.byteArray to int8Type, + symbols.charArray to int16Type, + symbols.shortArray to int16Type, + symbols.intArray to int32Type, + symbols.longArray to int64Type, + symbols.floatArray to floatType, + symbols.doubleArray to doubleType, + symbols.booleanArray to int8Type + ) + + override fun allocArray(irClass: IrClass, count: LLVMValueRef) = with(functionGenerationContext) { + val stackLocal = appendingTo(bbInitStackLocals) { + val constCount = extractConstUnsignedInt(count).toInt() + val arrayType = localArrayType(irClass, constCount) + val typeInfo = codegen.typeInfoValue(irClass) + val arraySlot = LLVMBuildAlloca(builder, arrayType, "")!! + // Set array size in ArrayHeader. + val arrayHeaderSlot = structGep(arraySlot, 0, "arrayHeader") + setTypeInfoForLocalObject(arrayHeaderSlot, typeInfo) + val sizeField = structGep(arrayHeaderSlot, 1, "count_") + store(count, sizeField) + + call(context.llvm.memsetFunction, + listOf(bitcast(kInt8Ptr, structGep(arraySlot, 1, "arrayBody")), + Int8(0).llvm, + Int32(constCount * LLVMSizeOfTypeInBits(codegen.llvmTargetData, + arrayToElementType[irClass.symbol]).toInt() / 8).llvm, + Int1(0).llvm)) + StackLocal(true, irClass, arraySlot, arrayHeaderSlot) + } + + stackLocals += stackLocal + bitcast(kObjHeaderPtr, stackLocal.objHeaderPtr) + } + + override fun clean(refsOnly: Boolean) = stackLocals.forEach { clean(it, refsOnly) } + + private fun clean(stackLocal: StackLocal, refsOnly: Boolean) = with(functionGenerationContext) { + if (stackLocal.isArray) { + if (stackLocal.irClass.symbol == context.ir.symbols.array) + call(context.llvm.zeroArrayRefsFunction, listOf(stackLocal.objHeaderPtr)) + } else { + val type = context.llvmDeclarations.forClass(stackLocal.irClass).bodyType + for (field in context.getLayoutBuilder(stackLocal.irClass).fields) { + val fieldIndex = context.llvmDeclarations.forField(field).index + val fieldType = LLVMStructGetTypeAtIndex(type, fieldIndex)!! + + if (isObjectType(fieldType)) { + val fieldPtr = LLVMBuildStructGEP(builder, stackLocal.bodyPtr, fieldIndex, "")!! + if (refsOnly) + storeHeapRef(kNullObjHeaderPtr, fieldPtr) + else + call(context.llvm.zeroHeapRefFunction, listOf(fieldPtr)) + } + } + + if (!refsOnly) { + val bodyPtr = ptrToInt(stackLocal.bodyPtr, codegen.intPtrType) + val bodySize = LLVMSizeOfTypeInBits(codegen.llvmTargetData, type).toInt() / 8 + val serviceInfoSize = runtime.pointerSize + val serviceInfoSizeLlvm = LLVMConstInt(codegen.intPtrType, serviceInfoSize.toLong(), 1)!! + val bodyWithSkippedServiceInfoPtr = intToPtr(add(bodyPtr, serviceInfoSizeLlvm), kInt8Ptr) + call(context.llvm.memsetFunction, + listOf(bodyWithSkippedServiceInfoPtr, + Int8(0).llvm, + Int32(bodySize - serviceInfoSize).llvm, + Int1(0).llvm)) + } + } + } + + private fun setTypeInfoForLocalObject(objectHeader: LLVMValueRef, typeInfoPointer: LLVMValueRef) = with(functionGenerationContext) { + val typeInfo = structGep(objectHeader, 0, "typeInfoOrMeta_") + // Set tag OBJECT_TAG_PERMANENT_CONTAINER | OBJECT_TAG_NONTRIVIAL_CONTAINER. + val typeInfoValue = intToPtr(or(ptrToInt(typeInfoPointer, codegen.intPtrType), + codegen.immThreeIntPtrType), kTypeInfoPtr) + store(typeInfoValue, typeInfo) + } +} + +internal class FunctionGenerationContext(val function: LLVMValueRef, + val codegen: CodeGenerator, + startLocation: LocationInfo?, + endLocation: LocationInfo?, + internal val irFunction: IrFunction? = null): ContextUtils { + + override val context = codegen.context + val vars = VariableManager(this) + private val basicBlockToLastLocation = mutableMapOf() + + private fun update(block: LLVMBasicBlockRef, startLocationInfo: LocationInfo?, endLocation: LocationInfo? = startLocationInfo) { + startLocationInfo ?: return + basicBlockToLastLocation.put(block, LocationInfoRange(startLocationInfo, endLocation)) + } + + var returnType: LLVMTypeRef? = LLVMGetReturnType(getFunctionType(function)) + private val returns: MutableMap = mutableMapOf() + val constructedClass: IrClass? + get() = (irFunction as? IrConstructor)?.constructedClass + private var returnSlot: LLVMValueRef? = null + private var slotsPhi: LLVMValueRef? = null + private val frameOverlaySlotCount = + (LLVMStoreSizeOfType(llvmTargetData, runtime.frameOverlayType) / runtime.pointerSize).toInt() + private var slotCount = frameOverlaySlotCount + private var localAllocs = 0 + // TODO: remove if exactly unused. + //private var arenaSlot: LLVMValueRef? = null + private val slotToVariableLocation = mutableMapOf() + + private val prologueBb = basicBlockInFunction("prologue", startLocation) + private val localsInitBb = basicBlockInFunction("locals_init", startLocation) + private val stackLocalsInitBb = basicBlockInFunction("stack_locals_init", startLocation) + private val entryBb = basicBlockInFunction("entry", startLocation) + private val epilogueBb = basicBlockInFunction("epilogue", endLocation) + private val cleanupLandingpad = basicBlockInFunction("cleanup_landingpad", endLocation) + + val stackLocalsManager = StackLocalsManagerImpl(this, stackLocalsInitBb) + + /** + * TODO: consider merging this with [ExceptionHandler]. + */ + var forwardingForeignExceptionsTerminatedWith: LLVMValueRef? = null + + init { + irFunction?.let { + if (!irFunction.isExported()) { + LLVMSetLinkage(function, LLVMLinkage.LLVMInternalLinkage) + // (Cannot do this before the function body is created). + } + } + } + + fun dispose() { + currentPositionHolder.dispose() + } + + private fun basicBlockInFunction(name: String, locationInfo: LocationInfo?): LLVMBasicBlockRef { + val bb = LLVMAppendBasicBlockInContext(llvmContext, function, name)!! + update(bb, locationInfo) + return bb + } + + fun basicBlock(name: String = "label_", startLocationInfo: LocationInfo?, endLocationInfo: LocationInfo? = startLocationInfo): LLVMBasicBlockRef { + val result = LLVMInsertBasicBlockInContext(llvmContext, this.currentBlock, name)!! + update(result, startLocationInfo, endLocationInfo) + LLVMMoveBasicBlockAfter(result, this.currentBlock) + return result + } + + fun alloca(type: LLVMTypeRef?, name: String = "", variableLocation: VariableDebugLocation? = null): LLVMValueRef { + if (isObjectType(type!!)) { + appendingTo(localsInitBb) { + val slotAddress = gep(slotsPhi!!, Int32(slotCount).llvm, name) + variableLocation?.let { + slotToVariableLocation[slotCount] = it + } + slotCount++ + return slotAddress + } + } + + appendingTo(prologueBb) { + val slotAddress = LLVMBuildAlloca(builder, type, name)!! + variableLocation?.let { + DIInsertDeclaration( + builder = codegen.context.debugInfo.builder, + value = slotAddress, + localVariable = it.localVariable, + location = it.location, + bb = prologueBb, + expr = null, + exprCount = 0) + } + return slotAddress + } + } + + + fun ret(value: LLVMValueRef?): LLVMValueRef { + val res = LLVMBuildBr(builder, epilogueBb)!! + if (returns.containsKey(currentBlock)) { + // TODO: enable error throwing. + throw Error("ret() in the same basic block twice! in ${function.name}") + } + + if (value != null) + returns[currentBlock] = value + + currentPositionHolder.setAfterTerminator() + return res + } + + fun param(index: Int): LLVMValueRef = LLVMGetParam(this.function, index)!! + + fun load(value: LLVMValueRef, name: String = ""): LLVMValueRef { + val result = LLVMBuildLoad(builder, value, name)!! + // Use loadSlot() API for that. + assert(!isObjectRef(value)) + return result + } + + fun loadSlot(address: LLVMValueRef, isVar: Boolean, name: String = ""): LLVMValueRef { + val value = LLVMBuildLoad(builder, address, name)!! + if (isObjectRef(value) && isVar) { + val slot = alloca(LLVMTypeOf(value), variableLocation = null) + storeStackRef(value, slot) + } + return value + } + + fun store(value: LLVMValueRef, ptr: LLVMValueRef) { + LLVMBuildStore(builder, value, ptr) + } + + fun storeHeapRef(value: LLVMValueRef, ptr: LLVMValueRef) { + updateRef(value, ptr, onStack = false) + } + + fun storeStackRef(value: LLVMValueRef, ptr: LLVMValueRef) { + updateRef(value, ptr, onStack = true) + } + + fun storeAny(value: LLVMValueRef, ptr: LLVMValueRef, onStack: Boolean) = if (isObjectRef(value)) { + if (onStack) storeStackRef(value, ptr) else storeHeapRef(value, ptr) + null + } else { + LLVMBuildStore(builder, value, ptr) + } + + fun freeze(value: LLVMValueRef, exceptionHandler: ExceptionHandler) { + if (isObjectRef(value)) + call(context.llvm.freezeSubgraph, listOf(value), Lifetime.IRRELEVANT, exceptionHandler) + } + + fun checkMainThread(exceptionHandler: ExceptionHandler) { + if (context.memoryModel == MemoryModel.STRICT) + call(context.llvm.checkMainThread, emptyList(), Lifetime.IRRELEVANT, exceptionHandler) + } + + private fun updateReturnRef(value: LLVMValueRef, address: LLVMValueRef) { + if (context.memoryModel == MemoryModel.STRICT) + store(value, address) + else + call(context.llvm.updateReturnRefFunction, listOf(address, value)) + } + + private fun updateRef(value: LLVMValueRef, address: LLVMValueRef, onStack: Boolean) { + if (onStack) { + if (context.memoryModel == MemoryModel.STRICT) + store(value, address) + else + call(context.llvm.updateStackRefFunction, listOf(address, value)) + } else { + call(context.llvm.updateHeapRefFunction, listOf(address, value)) + } + } + + //-------------------------------------------------------------------------// + + fun call(llvmFunction: LLVMValueRef, args: List, + resultLifetime: Lifetime = Lifetime.IRRELEVANT, + exceptionHandler: ExceptionHandler = ExceptionHandler.None, + verbatim: Boolean = false): LLVMValueRef { + val callArgs = if (verbatim || !isObjectReturn(llvmFunction.type)) { + args + } else { + // If function returns an object - create slot for the returned value or give local arena. + // This allows appropriate rootset accounting by just looking at the stack slots, + // along with ability to allocate in appropriate arena. + val resultSlot = when (resultLifetime.slotType) { + SlotType.STACK -> { + localAllocs++ + // Case of local call. Use memory allocated on stack. + val type = LLVMGetReturnType(LLVMGetElementType(llvmFunction.type))!! + val stackPointer = alloca(type) + //val objectHeader = structGep(stackPointer, 0) + //setTypeInfoForLocalObject(objectHeader) + stackPointer + //arenaSlot!! + } + + SlotType.RETURN -> returnSlot!! + + SlotType.ANONYMOUS -> vars.createAnonymousSlot() + + else -> throw Error("Incorrect slot type: ${resultLifetime.slotType}") + } + args + resultSlot + } + return callRaw(llvmFunction, callArgs, exceptionHandler) + } + + private fun callRaw(llvmFunction: LLVMValueRef, args: List, + exceptionHandler: ExceptionHandler): LLVMValueRef { + val rargs = args.toCValues() + if (LLVMIsAFunction(llvmFunction) != null /* the function declaration */ && + isFunctionNoUnwind(llvmFunction)) { + return LLVMBuildCall(builder, llvmFunction, rargs, args.size, "")!! + } else { + val unwind = when (exceptionHandler) { + ExceptionHandler.Caller -> cleanupLandingpad + is ExceptionHandler.Local -> exceptionHandler.unwind + + ExceptionHandler.None -> { + // When calling a function that is not marked as nounwind (can throw an exception), + // it is required to specify an unwind label to handle exceptions properly. + // Runtime C++ function can be marked as non-throwing using `RUNTIME_NOTHROW`. + val functionName = llvmFunction.name + val message = + "no exception handler specified when calling function $functionName without nounwind attr" + throw IllegalArgumentException(message) + } + } + + val position = position() + val endLocation = position?.end + val success = basicBlock("call_success", endLocation) + val result = LLVMBuildInvoke(builder, llvmFunction, rargs, args.size, success, unwind, "")!! + update(success, endLocation) + positionAtEnd(success) + return result + } + } + + //-------------------------------------------------------------------------// + + fun phi(type: LLVMTypeRef, name: String = ""): LLVMValueRef { + return LLVMBuildPhi(builder, type, name)!! + } + + fun addPhiIncoming(phi: LLVMValueRef, vararg incoming: Pair) { + memScoped { + val incomingValues = incoming.map { it.second }.toCValues() + val incomingBlocks = incoming.map { it.first }.toCValues() + + LLVMAddIncoming(phi, incomingValues, incomingBlocks, incoming.size) + } + } + + fun assignPhis(vararg phiToValue: Pair) { + phiToValue.forEach { + addPhiIncoming(it.first, currentBlock to it.second) + } + } + + fun allocInstance(typeInfo: LLVMValueRef, lifetime: Lifetime): LLVMValueRef = + call(context.llvm.allocInstanceFunction, listOf(typeInfo), lifetime) + + fun allocInstance(irClass: IrClass, lifetime: Lifetime, stackLocalsManager: StackLocalsManager) = + if (lifetime == Lifetime.STACK) + stackLocalsManager.alloc(irClass, + // In case the allocation is not from the root scope, fields must be cleaned up explicitly, + // as the object might be being reused. + cleanFieldsExplicitly = stackLocalsManager != this.stackLocalsManager) + else + allocInstance(codegen.typeInfoForAllocation(irClass), lifetime) + + fun allocArray( + irClass: IrClass, + count: LLVMValueRef, + lifetime: Lifetime, + exceptionHandler: ExceptionHandler + ): LLVMValueRef { + val typeInfo = codegen.typeInfoValue(irClass) + return if (lifetime == Lifetime.STACK) { + stackLocalsManager.allocArray(irClass, count) + } else { + call(context.llvm.allocArrayFunction, listOf(typeInfo, count), lifetime, exceptionHandler) + } + } + + fun unreachable(): LLVMValueRef? { + if (context.config.debug) { + call(context.llvm.llvmTrap, emptyList()) + } + val res = LLVMBuildUnreachable(builder) + currentPositionHolder.setAfterTerminator() + return res + } + + fun br(bbLabel: LLVMBasicBlockRef): LLVMValueRef { + val res = LLVMBuildBr(builder, bbLabel)!! + currentPositionHolder.setAfterTerminator() + return res + } + + fun condBr(condition: LLVMValueRef?, bbTrue: LLVMBasicBlockRef?, bbFalse: LLVMBasicBlockRef?): LLVMValueRef? { + val res = LLVMBuildCondBr(builder, condition, bbTrue, bbFalse) + currentPositionHolder.setAfterTerminator() + return res + } + + fun blockAddress(bbLabel: LLVMBasicBlockRef): LLVMValueRef { + return LLVMBlockAddress(function, bbLabel)!! + } + + fun not(arg: LLVMValueRef, name: String = ""): LLVMValueRef = LLVMBuildNot(builder, arg, name)!! + fun and(arg0: LLVMValueRef, arg1: LLVMValueRef, name: String = ""): LLVMValueRef = LLVMBuildAnd(builder, arg0, arg1, name)!! + fun or(arg0: LLVMValueRef, arg1: LLVMValueRef, name: String = ""): LLVMValueRef = LLVMBuildOr(builder, arg0, arg1, name)!! + fun xor(arg0: LLVMValueRef, arg1: LLVMValueRef, name: String = ""): LLVMValueRef = LLVMBuildXor(builder, arg0, arg1, name)!! + + fun zext(arg: LLVMValueRef, type: LLVMTypeRef): LLVMValueRef = + LLVMBuildZExt(builder, arg, type, "")!! + + fun sext(arg: LLVMValueRef, type: LLVMTypeRef): LLVMValueRef = + LLVMBuildSExt(builder, arg, type, "")!! + + fun ext(arg: LLVMValueRef, type: LLVMTypeRef, signed: Boolean): LLVMValueRef = + if (signed) { + sext(arg, type) + } else { + zext(arg, type) + } + + fun trunc(arg: LLVMValueRef, type: LLVMTypeRef): LLVMValueRef = + LLVMBuildTrunc(builder, arg, type, "")!! + + private fun shift(op: LLVMOpcode, arg: LLVMValueRef, amount: Int) = + if (amount == 0) { + arg + } else { + LLVMBuildBinOp(builder, op, arg, LLVMConstInt(arg.type, amount.toLong(), 0), "")!! + } + + fun shl(arg: LLVMValueRef, amount: Int) = shift(LLVMOpcode.LLVMShl, arg, amount) + + fun shr(arg: LLVMValueRef, amount: Int, signed: Boolean) = + shift(if (signed) LLVMOpcode.LLVMAShr else LLVMOpcode.LLVMLShr, + arg, amount) + + /* integers comparisons */ + fun icmpEq(arg0: LLVMValueRef, arg1: LLVMValueRef, name: String = ""): LLVMValueRef = LLVMBuildICmp(builder, LLVMIntPredicate.LLVMIntEQ, arg0, arg1, name)!! + + fun icmpGt(arg0: LLVMValueRef, arg1: LLVMValueRef, name: String = ""): LLVMValueRef = LLVMBuildICmp(builder, LLVMIntPredicate.LLVMIntSGT, arg0, arg1, name)!! + fun icmpGe(arg0: LLVMValueRef, arg1: LLVMValueRef, name: String = ""): LLVMValueRef = LLVMBuildICmp(builder, LLVMIntPredicate.LLVMIntSGE, arg0, arg1, name)!! + fun icmpLt(arg0: LLVMValueRef, arg1: LLVMValueRef, name: String = ""): LLVMValueRef = LLVMBuildICmp(builder, LLVMIntPredicate.LLVMIntSLT, arg0, arg1, name)!! + fun icmpLe(arg0: LLVMValueRef, arg1: LLVMValueRef, name: String = ""): LLVMValueRef = LLVMBuildICmp(builder, LLVMIntPredicate.LLVMIntSLE, arg0, arg1, name)!! + fun icmpNe(arg0: LLVMValueRef, arg1: LLVMValueRef, name: String = ""): LLVMValueRef = LLVMBuildICmp(builder, LLVMIntPredicate.LLVMIntNE, arg0, arg1, name)!! + fun icmpULt(arg0: LLVMValueRef, arg1: LLVMValueRef, name: String = ""): LLVMValueRef = LLVMBuildICmp(builder, LLVMIntPredicate.LLVMIntULT, arg0, arg1, name)!! + fun icmpULe(arg0: LLVMValueRef, arg1: LLVMValueRef, name: String = ""): LLVMValueRef = LLVMBuildICmp(builder, LLVMIntPredicate.LLVMIntULE, arg0, arg1, name)!! + fun icmpUGt(arg0: LLVMValueRef, arg1: LLVMValueRef, name: String = ""): LLVMValueRef = LLVMBuildICmp(builder, LLVMIntPredicate.LLVMIntUGT, arg0, arg1, name)!! + fun icmpUGe(arg0: LLVMValueRef, arg1: LLVMValueRef, name: String = ""): LLVMValueRef = LLVMBuildICmp(builder, LLVMIntPredicate.LLVMIntUGE, arg0, arg1, name)!! + + /* floating-point comparisons */ + fun fcmpEq(arg0: LLVMValueRef, arg1: LLVMValueRef, name: String = ""): LLVMValueRef = LLVMBuildFCmp(builder, LLVMRealPredicate.LLVMRealOEQ, arg0, arg1, name)!! + fun fcmpGt(arg0: LLVMValueRef, arg1: LLVMValueRef, name: String = ""): LLVMValueRef = LLVMBuildFCmp(builder, LLVMRealPredicate.LLVMRealOGT, arg0, arg1, name)!! + fun fcmpGe(arg0: LLVMValueRef, arg1: LLVMValueRef, name: String = ""): LLVMValueRef = LLVMBuildFCmp(builder, LLVMRealPredicate.LLVMRealOGE, arg0, arg1, name)!! + fun fcmpLt(arg0: LLVMValueRef, arg1: LLVMValueRef, name: String = ""): LLVMValueRef = LLVMBuildFCmp(builder, LLVMRealPredicate.LLVMRealOLT, arg0, arg1, name)!! + fun fcmpLe(arg0: LLVMValueRef, arg1: LLVMValueRef, name: String = ""): LLVMValueRef = LLVMBuildFCmp(builder, LLVMRealPredicate.LLVMRealOLE, arg0, arg1, name)!! + + fun sub(arg0: LLVMValueRef, arg1: LLVMValueRef, name: String = ""): LLVMValueRef = LLVMBuildSub(builder, arg0, arg1, name)!! + fun add(arg0: LLVMValueRef, arg1: LLVMValueRef, name: String = ""): LLVMValueRef = LLVMBuildAdd(builder, arg0, arg1, name)!! + + fun fsub(arg0: LLVMValueRef, arg1: LLVMValueRef, name: String = ""): LLVMValueRef = LLVMBuildFSub(builder, arg0, arg1, name)!! + fun fadd(arg0: LLVMValueRef, arg1: LLVMValueRef, name: String = ""): LLVMValueRef = LLVMBuildFAdd(builder, arg0, arg1, name)!! + fun fneg(arg: LLVMValueRef, name: String = ""): LLVMValueRef = LLVMBuildFNeg(builder, arg, name)!! + + fun select(ifValue: LLVMValueRef, thenValue: LLVMValueRef, elseValue: LLVMValueRef, name: String = ""): LLVMValueRef = + LLVMBuildSelect(builder, ifValue, thenValue, elseValue, name)!! + + fun bitcast(type: LLVMTypeRef?, value: LLVMValueRef, name: String = "") = LLVMBuildBitCast(builder, value, type, name)!! + + fun intToPtr(value: LLVMValueRef?, DestTy: LLVMTypeRef, Name: String = "") = LLVMBuildIntToPtr(builder, value, DestTy, Name)!! + fun ptrToInt(value: LLVMValueRef?, DestTy: LLVMTypeRef, Name: String = "") = LLVMBuildPtrToInt(builder, value, DestTy, Name)!! + fun gep(base: LLVMValueRef, index: LLVMValueRef, name: String = ""): LLVMValueRef { + return LLVMBuildGEP(builder, base, cValuesOf(index), 1, name)!! + } + fun structGep(base: LLVMValueRef, index: Int, name: String = ""): LLVMValueRef = + LLVMBuildStructGEP(builder, base, index, name)!! + + fun extractValue(aggregate: LLVMValueRef, index: Int, name: String = ""): LLVMValueRef = + LLVMBuildExtractValue(builder, aggregate, index, name)!! + + fun gxxLandingpad(numClauses: Int, name: String = ""): LLVMValueRef { + val personalityFunction = context.llvm.gxxPersonalityFunction + + // Type of `landingpad` instruction result (depends on personality function): + val landingpadType = structType(int8TypePtr, int32Type) + + return LLVMBuildLandingPad(builder, landingpadType, personalityFunction, numClauses, name)!! + } + + fun extractElement(vector: LLVMValueRef, index: LLVMValueRef, name: String = ""): LLVMValueRef { + return LLVMBuildExtractElement(builder, vector, index, name)!! + } + + fun filteringExceptionHandler(codeContext: CodeContext, foreignExceptionMode: ForeignExceptionMode.Mode): ExceptionHandler { + val lpBlock = basicBlockInFunction("filteringExceptionHandler", position()?.start) + + val wrapExceptionMode = context.config.target.family.isAppleFamily && + foreignExceptionMode == ForeignExceptionMode.Mode.OBJC_WRAP + + appendingTo(lpBlock) { + val landingpad = gxxLandingpad(2) + LLVMAddClause(landingpad, kotlinExceptionRtti.llvm) + if (wrapExceptionMode) { + LLVMAddClause(landingpad, objcNSExceptionRtti.llvm) + } + LLVMAddClause(landingpad, LLVMConstNull(kInt8Ptr)) + + val fatalForeignExceptionBlock = basicBlock("fatalForeignException", position()?.start) + val forwardKotlinExceptionBlock = basicBlock("forwardKotlinException", position()?.start) + + val typeId = extractValue(landingpad, 1) + val isKotlinException = icmpEq( + typeId, + call(context.llvm.llvmEhTypeidFor, listOf(kotlinExceptionRtti.llvm)) + ) + + if (wrapExceptionMode) { + val foreignExceptionBlock = basicBlock("foreignException", position()?.start) + val forwardNativeExceptionBlock = basicBlock("forwardNativeException", position()?.start) + + condBr(isKotlinException, forwardKotlinExceptionBlock, foreignExceptionBlock) + appendingTo(foreignExceptionBlock) { + val isObjCException = icmpEq( + typeId, + call(context.llvm.llvmEhTypeidFor, listOf(objcNSExceptionRtti.llvm)) + ) + condBr(isObjCException, forwardNativeExceptionBlock, fatalForeignExceptionBlock) + + appendingTo(forwardNativeExceptionBlock) { + val exception = createForeignException(landingpad, codeContext.exceptionHandler) + codeContext.genThrow(exception) + } + } + } else { + condBr(isKotlinException, forwardKotlinExceptionBlock, fatalForeignExceptionBlock) + } + + appendingTo(forwardKotlinExceptionBlock) { + // Rethrow Kotlin exception to real handler. + codeContext.genThrow(extractKotlinException(landingpad)) + } + + appendingTo(fatalForeignExceptionBlock) { + val exceptionRecord = extractValue(landingpad, 0) + call(context.llvm.cxaBeginCatchFunction, listOf(exceptionRecord)) + terminate() + } + + } + + return object : ExceptionHandler.Local() { + override val unwind: LLVMBasicBlockRef + get() = lpBlock + } + } + + fun terminate() { + call(context.llvm.cxxStdTerminate, emptyList()) + + // Note: unreachable instruction to be generated here, but debug information is improper in this case. + val loopBlock = basicBlock("loop", position()?.start) + br(loopBlock) + appendingTo(loopBlock) { + br(loopBlock) + } + } + + fun kotlinExceptionHandler( + block: FunctionGenerationContext.(exception: LLVMValueRef) -> Unit + ): ExceptionHandler { + val lpBlock = basicBlock("kotlinExceptionHandler", position()?.end) + + appendingTo(lpBlock) { + val exception = catchKotlinException() + block(exception) + } + + return object : ExceptionHandler.Local() { + override val unwind: LLVMBasicBlockRef get() = lpBlock + } + } + + fun catchKotlinException(): LLVMValueRef { + val landingpadResult = gxxLandingpad(numClauses = 1, name = "lp") + + LLVMAddClause(landingpadResult, LLVMConstNull(kInt8Ptr)) + + // TODO: properly handle C++ exceptions: currently C++ exception can be thrown out from try-finally + // bypassing the finally block. + + return extractKotlinException(landingpadResult) + } + + private fun extractKotlinException(landingpadResult: LLVMValueRef): LLVMValueRef { + val exceptionRecord = extractValue(landingpadResult, 0, "er") + + // __cxa_begin_catch returns pointer to C++ exception object. + val beginCatch = context.llvm.cxaBeginCatchFunction + val exceptionRawPtr = call(beginCatch, listOf(exceptionRecord)) + + // Pointer to KotlinException instance: + val exceptionPtrPtr = bitcast(codegen.kObjHeaderPtrPtr, exceptionRawPtr, "") + + // Pointer to Kotlin exception object: + // We do need a slot here, as otherwise exception instance could be freed by _cxa_end_catch. + val exceptionPtr = loadSlot(exceptionPtrPtr, true, "exception") + + // __cxa_end_catch performs some C++ cleanup, including calling `KotlinException` class destructor. + val endCatch = context.llvm.cxaEndCatchFunction + call(endCatch, listOf()) + + return exceptionPtr + } + + private fun createForeignException(landingpadResult: LLVMValueRef, exceptionHandler: ExceptionHandler): LLVMValueRef { + val exceptionRecord = extractValue(landingpadResult, 0, "er") + + // __cxa_begin_catch returns pointer to C++ exception object. + val exceptionRawPtr = call(context.llvm.cxaBeginCatchFunction, listOf(exceptionRecord)) + + // This will take care of ARC - need to be done in the catching scope, i.e. before __cxa_end_catch + val exception = call(context.ir.symbols.createForeignException.owner.llvmFunction, + listOf(exceptionRawPtr), + Lifetime.GLOBAL, exceptionHandler) + + call(context.llvm.cxaEndCatchFunction, listOf()) + return exception + } + + inline fun ifThenElse( + condition: LLVMValueRef, + thenValue: LLVMValueRef, + elseBlock: () -> LLVMValueRef + ): LLVMValueRef { + val resultType = thenValue.type + + val position = position() + val endPosition = position()?.end + val bbExit = basicBlock(startLocationInfo = endPosition) + val resultPhi = appendingTo(bbExit) { + phi(resultType) + } + + val bbElse = basicBlock(startLocationInfo = position?.start, endLocationInfo = endPosition) + + condBr(condition, bbExit, bbElse) + assignPhis(resultPhi to thenValue) + + appendingTo(bbElse) { + val elseValue = elseBlock() + br(bbExit) + assignPhis(resultPhi to elseValue) + } + + positionAtEnd(bbExit) + return resultPhi + } + + inline fun ifThen(condition: LLVMValueRef, thenBlock: () -> Unit) { + val endPosition = position()?.end + val bbExit = basicBlock(startLocationInfo = endPosition) + val bbThen = basicBlock(startLocationInfo = endPosition) + + condBr(condition, bbThen, bbExit) + + appendingTo(bbThen) { + thenBlock() + if (!isAfterTerminator()) br(bbExit) + } + + positionAtEnd(bbExit) + } + + internal fun debugLocation(startLocationInfo: LocationInfo, endLocation: LocationInfo?): DILocationRef? { + if (!context.shouldContainLocationDebugInfo()) return null + update(currentBlock, startLocationInfo, endLocation) + val debugLocation = codegen.generateLocationInfo(startLocationInfo) + currentPositionHolder.setBuilderDebugLocation(debugLocation) + return debugLocation + } + + fun indirectBr(address: LLVMValueRef, destinations: Collection): LLVMValueRef? { + val indirectBr = LLVMBuildIndirectBr(builder, address, destinations.size) + destinations.forEach { LLVMAddDestination(indirectBr, it) } + currentPositionHolder.setAfterTerminator() + return indirectBr + } + + fun switch(value: LLVMValueRef, cases: Collection>, elseBB: LLVMBasicBlockRef): LLVMValueRef? { + val switch = LLVMBuildSwitch(builder, value, elseBB, cases.size) + cases.forEach { LLVMAddCase(switch, it.first, it.second) } + currentPositionHolder.setAfterTerminator() + return switch + } + + fun loadTypeInfo(objPtr: LLVMValueRef): LLVMValueRef { + val typeInfoOrMetaPtr = structGep(objPtr, 0 /* typeInfoOrMeta_ */) + val typeInfoOrMetaWithFlags = load(typeInfoOrMetaPtr) + // Clear two lower bits. + val typeInfoOrMetaWithFlagsRaw = ptrToInt(typeInfoOrMetaWithFlags, codegen.intPtrType) + val typeInfoOrMetaRaw = and(typeInfoOrMetaWithFlagsRaw, codegen.immTypeInfoMask) + val typeInfoOrMeta = intToPtr(typeInfoOrMetaRaw, kTypeInfoPtr) + val typeInfoPtrPtr = structGep(typeInfoOrMeta, 0 /* typeInfo */) + return load(typeInfoPtrPtr) + } + + fun lookupInterfaceTableRecord(typeInfo: LLVMValueRef, interfaceId: Int): LLVMValueRef { + val interfaceTableSize = load(structGep(typeInfo, 11 /* interfaceTableSize_ */)) + val interfaceTable = load(structGep(typeInfo, 12 /* interfaceTable_ */)) + + fun fastPath(): LLVMValueRef { + // The fastest optimistic version. + val interfaceTableIndex = and(interfaceTableSize, Int32(interfaceId).llvm) + return gep(interfaceTable, interfaceTableIndex) + } + + // See details in ClassLayoutBuilder. + return if (context.globalHierarchyAnalysisResult.bitsPerColor <= ClassGlobalHierarchyInfo.MAX_BITS_PER_COLOR + && context.config.produce != CompilerOutputKind.FRAMEWORK) { + // All interface tables are small and no unknown interface inheritance. + fastPath() + } else { + val startLocationInfo = position()?.start + val fastPathBB = basicBlock("fast_path", startLocationInfo) + val slowPathBB = basicBlock("slow_path", startLocationInfo) + val takeResBB = basicBlock("take_res", startLocationInfo) + condBr(icmpGe(interfaceTableSize, kImmInt32Zero), fastPathBB, slowPathBB) + positionAtEnd(takeResBB) + val resultPhi = phi(pointerType(runtime.interfaceTableRecordType)) + appendingTo(fastPathBB) { + val fastValue = fastPath() + br(takeResBB) + addPhiIncoming(resultPhi, currentBlock to fastValue) + } + appendingTo(slowPathBB) { + val actualInterfaceTableSize = sub(kImmInt32Zero, interfaceTableSize) // -interfaceTableSize + val slowValue = call(context.llvm.lookupInterfaceTableRecord, + listOf(interfaceTable, actualInterfaceTableSize, Int32(interfaceId).llvm)) + br(takeResBB) + addPhiIncoming(resultPhi, currentBlock to slowValue) + } + resultPhi + } + } + + fun lookupVirtualImpl(receiver: LLVMValueRef, irFunction: IrFunction): LLVMValueRef { + assert(LLVMTypeOf(receiver) == codegen.kObjHeaderPtr) + + val typeInfoPtr: LLVMValueRef = if (irFunction.getObjCMethodInfo() != null) + call(context.llvm.getObjCKotlinTypeInfo, listOf(receiver)) + else + loadTypeInfo(receiver) + + assert(typeInfoPtr.type == codegen.kTypeInfoPtr) { LLVMPrintTypeToString(typeInfoPtr.type)!!.toKString() } + + /* + * Resolve owner of the call with special handling of Any methods: + * if toString/eq/hc is invoked on an interface instance, we resolve + * owner as Any and dispatch it via vtable. + */ + val anyMethod = (irFunction as IrSimpleFunction).findOverriddenMethodOfAny() + val owner = (anyMethod ?: irFunction).parentAsClass + val methodHash = codegen.functionHash(irFunction) + + val llvmMethod = when { + !owner.isInterface -> { + // If this is a virtual method of the class - we can call via vtable. + val index = context.getLayoutBuilder(owner).vtableIndex(anyMethod ?: irFunction) + val vtablePlace = gep(typeInfoPtr, Int32(1).llvm) // typeInfoPtr + 1 + val vtable = bitcast(kInt8PtrPtr, vtablePlace) + val slot = gep(vtable, Int32(index).llvm) + load(slot) + } + + !context.ghaEnabled() -> call(context.llvm.lookupOpenMethodFunction, listOf(typeInfoPtr, methodHash)) + + else -> { + // Essentially: typeInfo.itable[place(interfaceId)].vtable[method] + val itablePlace = context.getLayoutBuilder(owner).itablePlace(irFunction) + val interfaceTableRecord = lookupInterfaceTableRecord(typeInfoPtr, itablePlace.interfaceId) + load(gep(load(structGep(interfaceTableRecord, 2 /* vtable */)), Int32(itablePlace.methodIndex).llvm)) + } + } + val functionPtrType = pointerType(codegen.getLlvmFunctionType(irFunction)) + return bitcast(functionPtrType, llvmMethod) + } + + private fun IrSimpleFunction.findOverriddenMethodOfAny(): IrSimpleFunction? { + if (modality == Modality.ABSTRACT) return null + val resolved = resolveFakeOverride()!! + if ((resolved.parent as IrClass).isAny()) { + return resolved + } + + return null + } + + fun getObjectValue(irClass: IrClass, exceptionHandler: ExceptionHandler, + startLocationInfo: LocationInfo?, endLocationInfo: LocationInfo? = null + ): LLVMValueRef { + // TODO: could be processed the same way as other stateless objects. + if (irClass.isUnit()) { + return codegen.theUnitInstanceRef.llvm + } + + if (irClass.isCompanion) { + val parent = irClass.parent as IrClass + if (parent.isObjCClass()) { + // TODO: cache it too. + return call( + codegen.llvmFunction(context.ir.symbols.interopInterpretObjCPointer.owner), + listOf(getObjCClass(parent, exceptionHandler)), + Lifetime.GLOBAL, + exceptionHandler + ) + } + } + + val storageKind = irClass.storageKind(context) + + val objectPtr = if (isExternal(irClass)) { + when (storageKind) { + // If thread local object is imported - access it via getter function. + ObjectStorageKind.THREAD_LOCAL -> { + val valueGetterName = irClass.threadLocalObjectStorageGetterSymbolName + val valueGetterFunction = LLVMGetNamedFunction(context.llvmModule, valueGetterName) + ?: LLVMAddFunction(context.llvmModule, valueGetterName, + functionType(kObjHeaderPtrPtr, false)) + call(valueGetterFunction!!, + listOf(), + resultLifetime = Lifetime.GLOBAL, + exceptionHandler = exceptionHandler) + } + + // If global object is imported - import it's storage directly. + ObjectStorageKind.PERMANENT, ObjectStorageKind.SHARED -> { + val llvmType = getLLVMType(irClass.defaultType) + importGlobal( + irClass.globalObjectStorageSymbolName, + llvmType, + origin = irClass.llvmSymbolOrigin + ) + } + } + } else { + // Local globals and thread locals storage info is stored in our map. + val singleton = context.llvmDeclarations.forSingleton(irClass) + val instanceAddress = singleton.instanceStorage + instanceAddress.getAddress(this) + } + + when (storageKind) { + ObjectStorageKind.SHARED -> + // If current file used a shared object, make file's (de)initializer function deinit it. + context.llvm.globalSharedObjects += objectPtr + ObjectStorageKind.THREAD_LOCAL -> + // If current file used locally defined TLS objects, make file's (de)initializer function + // init and deinit TLS. + // Note: for exported TLS objects a getter is generated in a file they're defined in. Which + // adds TLS init and deinit to that file's (de)initializer function. + if (!isExternal(irClass)) + context.llvm.fileUsesThreadLocalObjects = true + ObjectStorageKind.PERMANENT -> { /* Do nothing, no need to free such an instance. */ } + } + + if (storageKind == ObjectStorageKind.PERMANENT) { + return loadSlot(objectPtr, false) + } + val bbInit = basicBlock("label_init", startLocationInfo, endLocationInfo) + val bbExit = basicBlock("label_continue", startLocationInfo, endLocationInfo) + val objectVal = loadSlot(objectPtr, false) + val objectInitialized = icmpUGt(ptrToInt(objectVal, codegen.intPtrType), codegen.immOneIntPtrType) + val bbCurrent = currentBlock + condBr(objectInitialized, bbExit, bbInit) + + positionAtEnd(bbInit) + val typeInfo = codegen.typeInfoForAllocation(irClass) + val defaultConstructor = irClass.constructors.single { it.valueParameters.size == 0 } + val ctor = codegen.llvmFunction(defaultConstructor) + val initFunction = + if (storageKind == ObjectStorageKind.SHARED && context.config.threadsAreAllowed) { + context.llvm.initSharedInstanceFunction + } else { + context.llvm.initInstanceFunction + } + val args = listOf(objectPtr, typeInfo, ctor) + val newValue = call(initFunction, args, Lifetime.GLOBAL, exceptionHandler) + val bbInitResult = currentBlock + br(bbExit) + + positionAtEnd(bbExit) + val valuePhi = phi(codegen.getLLVMType(irClass.defaultType)) + addPhiIncoming(valuePhi, bbCurrent to objectVal, bbInitResult to newValue) + + return valuePhi + } + + /** + * Note: the same code is generated as IR in [org.jetbrains.kotlin.backend.konan.lower.EnumUsageLowering]. + */ + fun getEnumEntry(enumEntry: IrEnumEntry, exceptionHandler: ExceptionHandler): LLVMValueRef { + val enumClass = enumEntry.parentAsClass + val loweredEnum = context.specialDeclarationsFactory.getLoweredEnum(enumClass) + + val ordinal = loweredEnum.entriesMap[enumEntry.name]!! + val values = call( + loweredEnum.valuesGetter.llvmFunction, + emptyList(), + Lifetime.ARGUMENT, + exceptionHandler + ) + + return call( + loweredEnum.itemGetterSymbol.owner.llvmFunction, + listOf(values, Int32(ordinal).llvm), + Lifetime.GLOBAL, + exceptionHandler + ) + } + + // TODO: get rid of exceptionHandler argument by ensuring that all called functions are non-throwing. + fun getObjCClass(irClass: IrClass, exceptionHandler: ExceptionHandler): LLVMValueRef { + assert(!irClass.isInterface) + + return if (irClass.isExternalObjCClass()) { + val llvmSymbolOrigin = irClass.llvmSymbolOrigin + + if (irClass.isObjCMetaClass()) { + val name = irClass.descriptor.getExternalObjCMetaClassBinaryName() + val objCClass = getObjCClass(name, llvmSymbolOrigin) + + val getClass = context.llvm.externalFunction( + "object_getClass", + functionType(int8TypePtr, false, int8TypePtr), + origin = context.standardLlvmSymbolsOrigin + ) + + call(getClass, listOf(objCClass), exceptionHandler = exceptionHandler) + } else { + getObjCClass(irClass.descriptor.getExternalObjCClassBinaryName(), llvmSymbolOrigin) + } + } else { + if (irClass.isObjCMetaClass()) { + error("type-checking against Kotlin classes inheriting Objective-C meta-classes isn't supported yet") + } + + val classInfo = codegen.kotlinObjCClassInfo(irClass) + val classPointerGlobal = load(structGep(classInfo, KotlinObjCClassInfoGenerator.createdClassFieldIndex)) + + val storedClass = this.load(classPointerGlobal) + + val storedClassIsNotNull = this.icmpNe(storedClass, kNullInt8Ptr) + + return this.ifThenElse(storedClassIsNotNull, storedClass) { + call( + context.llvm.createKotlinObjCClass, + listOf(classInfo), + exceptionHandler = exceptionHandler + ) + } + } + } + + fun getObjCClass(binaryName: String, llvmSymbolOrigin: CompiledKlibModuleOrigin): LLVMValueRef { + context.llvm.imports.add(llvmSymbolOrigin) + return load(codegen.objCDataGenerator!!.genClassRef(binaryName).llvm) + } + + fun resetDebugLocation() { + if (!context.shouldContainLocationDebugInfo()) return + currentPositionHolder.resetBuilderDebugLocation() + } + + private fun position() = basicBlockToLastLocation[currentBlock] + + internal fun mapParameterForDebug(index: Int, value: LLVMValueRef) { + appendingTo(localsInitBb) { + LLVMBuildStore(builder, value, vars.addressOf(index)) + } + } + + internal fun prologue() { + assert(returns.isEmpty()) + if (isObjectType(returnType!!)) { + returnSlot = LLVMGetParam(function, numParameters(function.type) - 1) + } + positionAtEnd(localsInitBb) + slotsPhi = phi(kObjHeaderPtrPtr) + // Is removed by DCE trivially, if not needed. + /*arenaSlot = intToPtr( + or(ptrToInt(slotsPhi, codegen.intPtrType), codegen.immOneIntPtrType), kObjHeaderPtrPtr)*/ + positionAtEnd(entryBb) + } + + internal fun epilogue() { + appendingTo(prologueBb) { + val slots = if (needSlotsPhi) + LLVMBuildArrayAlloca(builder, kObjHeaderPtr, Int32(slotCount).llvm, "")!! + else + kNullObjHeaderPtrPtr + if (needSlots) { + // Zero-init slots. + val slotsMem = bitcast(kInt8Ptr, slots) + call(context.llvm.memsetFunction, + listOf(slotsMem, Int8(0).llvm, + Int32(slotCount * codegen.runtime.pointerSize).llvm, + Int1(0).llvm)) + call(context.llvm.enterFrameFunction, listOf(slots, Int32(vars.skipSlots).llvm, Int32(slotCount).llvm)) + } + addPhiIncoming(slotsPhi!!, prologueBb to slots) + memScoped { + slotToVariableLocation.forEach { slot, variable -> + val expr = longArrayOf(DwarfOp.DW_OP_plus_uconst.value, + runtime.pointerSize * slot.toLong()).toCValues() + DIInsertDeclaration( + builder = codegen.context.debugInfo.builder, + value = slots, + localVariable = variable.localVariable, + location = variable.location, + bb = prologueBb, + expr = expr, + exprCount = 2) + } + } + br(localsInitBb) + } + + appendingTo(localsInitBb) { + br(stackLocalsInitBb) + } + + appendingTo(stackLocalsInitBb) { + br(entryBb) + } + + appendingTo(epilogueBb) { + when { + returnType == voidType -> { + releaseVars() + assert(returnSlot == null) + LLVMBuildRetVoid(builder) + } + returns.isNotEmpty() -> { + val returnPhi = phi(returnType!!) + addPhiIncoming(returnPhi, *returns.toList().toTypedArray()) + if (returnSlot != null) { + updateReturnRef(returnPhi, returnSlot!!) + } + releaseVars() + LLVMBuildRet(builder, returnPhi) + } + // Do nothing, all paths throw. + else -> LLVMBuildUnreachable(builder) + } + } + + appendingTo(cleanupLandingpad) { + val landingpad = gxxLandingpad(numClauses = 0) + LLVMSetCleanup(landingpad, 1) + + forwardingForeignExceptionsTerminatedWith?.let { terminator -> + // Catch all but Kotlin exceptions. + val clause = ConstArray(int8TypePtr, listOf(kotlinExceptionRtti)) + LLVMAddClause(landingpad, clause.llvm) + + val bbCleanup = basicBlock("forwardException", position()?.end) + val bbUnexpected = basicBlock("unexpectedException", position()?.end) + + val selector = extractValue(landingpad, 1) + condBr( + icmpLt(selector, Int32(0).llvm), + bbUnexpected, + bbCleanup + ) + + appendingTo(bbUnexpected) { + val exceptionRecord = extractValue(landingpad, 0) + + val beginCatch = context.llvm.cxaBeginCatchFunction + // So `terminator` is called from C++ catch block: + call(beginCatch, listOf(exceptionRecord)) + call(terminator, emptyList()) + unreachable() + } + + positionAtEnd(bbCleanup) + } + + releaseVars() + LLVMBuildResume(builder, landingpad) + } + + returns.clear() + vars.clear() + returnSlot = null + slotsPhi = null + } + + private val kotlinExceptionRtti: ConstPointer + get() = constPointer(importGlobal( + "_ZTI18ExceptionObjHolder", // typeinfo for ObjHolder + int8TypePtr, + origin = context.stdlibModule.llvmSymbolOrigin + )).bitcast(int8TypePtr) + + private val objcNSExceptionRtti: ConstPointer by lazy { + constPointer(importGlobal( + "OBJC_EHTYPE_\$_NSException", // typeinfo for NSException* + int8TypePtr, + origin = context.stdlibModule.llvmSymbolOrigin + )).bitcast(int8TypePtr) + } + + //-------------------------------------------------------------------------// + + /** + * Represents the mutable position of instructions being inserted. + * + * This class is introduced to workaround unreachable code handling. + */ + inner class PositionHolder { + private val builder: LLVMBuilderRef = LLVMCreateBuilderInContext(llvmContext)!! + + + fun getBuilder(): LLVMBuilderRef { + if (isAfterTerminator) { + val position = position() + positionAtEnd(basicBlock("unreachable", position?.start, position?.end)) + } + + return builder + } + + /** + * Should be `true` iff the position is located after terminator instruction. + */ + var isAfterTerminator: Boolean = false + private set + + fun setAfterTerminator() { + isAfterTerminator = true + } + + val currentBlock: LLVMBasicBlockRef + get() = LLVMGetInsertBlock(builder)!! + + fun positionAtEnd(block: LLVMBasicBlockRef) { + LLVMPositionBuilderAtEnd(builder, block) + basicBlockToLastLocation[block]?.let{ debugLocation(it.start, it.end) } + val lastInstr = LLVMGetLastInstruction(block) + isAfterTerminator = lastInstr != null && (LLVMIsATerminatorInst(lastInstr) != null) + } + + fun dispose() { + LLVMDisposeBuilder(builder) + } + + fun resetBuilderDebugLocation() { + if (!context.shouldContainLocationDebugInfo()) return + LLVMBuilderResetDebugLocation(builder) + } + + fun setBuilderDebugLocation(debugLocation: DILocationRef?) { + if (!context.shouldContainLocationDebugInfo()) return + LLVMBuilderSetDebugLocation(builder, debugLocation) + } + } + + private var currentPositionHolder: PositionHolder = PositionHolder() + + /** + * Returns `true` iff the current code generation position is located after terminator instruction. + */ + fun isAfterTerminator() = currentPositionHolder.isAfterTerminator + + val currentBlock: LLVMBasicBlockRef + get() = currentPositionHolder.currentBlock + + /** + * The builder representing the current code generation position. + * + * Note that it shouldn't be positioned directly using LLVM API due to some hacks. + * Use e.g. [positionAtEnd] instead. See [PositionHolder] for details. + */ + val builder: LLVMBuilderRef + get() = currentPositionHolder.getBuilder() + + fun positionAtEnd(bbLabel: LLVMBasicBlockRef) = currentPositionHolder.positionAtEnd(bbLabel) + + inline private fun preservingPosition(code: () -> R): R { + val oldPositionHolder = currentPositionHolder + val newPositionHolder = PositionHolder() + currentPositionHolder = newPositionHolder + try { + return code() + } finally { + currentPositionHolder = oldPositionHolder + newPositionHolder.dispose() + } + } + + inline fun appendingTo(block: LLVMBasicBlockRef, code: FunctionGenerationContext.() -> R) = preservingPosition { + positionAtEnd(block) + code() + } + + private val needSlots: Boolean + get() { + return slotCount - vars.skipSlots > frameOverlaySlotCount + } + + private val needSlotsPhi: Boolean + get() { + return slotCount > frameOverlaySlotCount || localAllocs > 0 + } + + + private fun releaseVars() { + if (needSlots) { + call(context.llvm.leaveFrameFunction, + listOf(slotsPhi!!, Int32(vars.skipSlots).llvm, Int32(slotCount).llvm)) + } + stackLocalsManager.clean(refsOnly = true) // Only bother about not leaving any dangling references. + } +} + + + diff --git a/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/ContextUtils.kt b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/ContextUtils.kt new file mode 100644 index 00000000000..894c2b97c2d --- /dev/null +++ b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/ContextUtils.kt @@ -0,0 +1,639 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +package org.jetbrains.kotlin.backend.konan.llvm + +import kotlinx.cinterop.allocArray +import kotlinx.cinterop.get +import kotlinx.cinterop.memScoped +import kotlinx.cinterop.toKString +import llvm.* +import org.jetbrains.kotlin.backend.konan.CachedLibraries +import org.jetbrains.kotlin.library.resolver.TopologicalLibraryOrder +import org.jetbrains.kotlin.backend.konan.Context +import org.jetbrains.kotlin.backend.konan.hash.GlobalHash +import org.jetbrains.kotlin.backend.konan.ir.llvmSymbolOrigin +import org.jetbrains.kotlin.descriptors.ModuleDescriptor +import org.jetbrains.kotlin.descriptors.konan.CompiledKlibModuleOrigin +import org.jetbrains.kotlin.descriptors.konan.CurrentKlibModuleOrigin +import org.jetbrains.kotlin.descriptors.konan.DeserializedKlibModuleOrigin +import org.jetbrains.kotlin.ir.declarations.* +import org.jetbrains.kotlin.ir.util.file +import org.jetbrains.kotlin.ir.util.fqNameForIrSerialization +import org.jetbrains.kotlin.ir.util.isReal +import org.jetbrains.kotlin.konan.library.KonanLibrary +import org.jetbrains.kotlin.konan.target.KonanTarget +import org.jetbrains.kotlin.library.KotlinLibrary +import org.jetbrains.kotlin.library.resolver.TopologicalLibraryOrder +import org.jetbrains.kotlin.library.uniqueName +import org.jetbrains.kotlin.name.FqName +import org.jetbrains.kotlin.name.Name +import org.jetbrains.kotlin.utils.addToStdlib.cast +import kotlin.properties.ReadOnlyProperty +import kotlin.reflect.KProperty + +internal sealed class SlotType { + // An object is statically allocated on stack. + object STACK : SlotType() + + // Frame local arena slot can be used. + object ARENA : SlotType() + + // Return slot can be used. + object RETURN : SlotType() + + // Return slot, if it is an arena, can be used. + object RETURN_IF_ARENA : SlotType() + + // Param slot, if it is an arena, can be used. + class PARAM_IF_ARENA(val parameter: Int) : SlotType() + + // Params slot, if it is an arena, can be used. + class PARAMS_IF_ARENA(val parameters: IntArray, val useReturnSlot: Boolean) : SlotType() + + // Anonymous slot. + object ANONYMOUS : SlotType() + + // Unknown slot type. + object UNKNOWN : SlotType() +} + +// Lifetimes class of reference, computed by escape analysis. +internal sealed class Lifetime(val slotType: SlotType) { + object STACK : Lifetime(SlotType.STACK) { + override fun toString(): String { + return "STACK" + } + } + + // If reference is frame-local (only obtained from some call and never leaves). + object LOCAL : Lifetime(SlotType.ARENA) { + override fun toString(): String { + return "LOCAL" + } + } + + // If reference is only returned. + object RETURN_VALUE : Lifetime(SlotType.ANONYMOUS) { + override fun toString(): String { + return "RETURN_VALUE" + } + } + + // If reference is set as field of references of class RETURN_VALUE or INDIRECT_RETURN_VALUE. + object INDIRECT_RETURN_VALUE : Lifetime(SlotType.RETURN_IF_ARENA) { + override fun toString(): String { + return "INDIRECT_RETURN_VALUE" + } + } + + // If reference is stored to the field of an incoming parameters. + class PARAMETER_FIELD(val parameter: Int) : Lifetime(SlotType.PARAM_IF_ARENA(parameter)) { + override fun toString(): String { + return "PARAMETER_FIELD($parameter)" + } + } + + // If reference is stored to the field of an incoming parameters. + class PARAMETERS_FIELD(val parameters: IntArray, val useReturnSlot: Boolean) + : Lifetime(SlotType.PARAMS_IF_ARENA(parameters, useReturnSlot)) { + override fun toString(): String { + return "PARAMETERS_FIELD(${parameters.contentToString()}, useReturnSlot='$useReturnSlot')" + } + } + + // If reference refers to the global (either global object or global variable). + object GLOBAL : Lifetime(SlotType.ANONYMOUS) { + override fun toString(): String { + return "GLOBAL" + } + } + + // If reference used to throw. + object THROW : Lifetime(SlotType.ANONYMOUS) { + override fun toString(): String { + return "THROW" + } + } + + // If reference used as an argument of outgoing function. Class can be improved by escape analysis + // of called function. + object ARGUMENT : Lifetime(SlotType.ANONYMOUS) { + override fun toString(): String { + return "ARGUMENT" + } + } + + // If reference class is unknown. + object UNKNOWN : Lifetime(SlotType.UNKNOWN) { + override fun toString(): String { + return "UNKNOWN" + } + } + + // If reference class is irrelevant. + object IRRELEVANT : Lifetime(SlotType.UNKNOWN) { + override fun toString(): String { + return "IRRELEVANT" + } + } +} + +/** + * Provides utility methods to the implementer. + */ +internal interface ContextUtils : RuntimeAware { + val context: Context + + override val runtime: Runtime + get() = context.llvm.runtime + + /** + * Describes the target platform. + * + * TODO: using [llvmTargetData] usually results in generating non-portable bitcode. + */ + val llvmTargetData: LLVMTargetDataRef + get() = runtime.targetData + + val staticData: StaticData + get() = context.llvm.staticData + + /** + * TODO: maybe it'd be better to replace with [IrDeclaration::isEffectivelyExternal()], + * or just drop all [else] branches of corresponding conditionals. + */ + fun isExternal(declaration: IrDeclaration): Boolean { + return !context.llvmModuleSpecification.containsDeclaration(declaration) + } + + /** + * LLVM function generated from the Kotlin function. + * It may be declared as external function prototype. + */ + val IrFunction.llvmFunction: LLVMValueRef + get() = llvmFunctionOrNull + ?: error("$name in $file/${parent.fqNameForIrSerialization}") + + val IrFunction.llvmFunctionOrNull: LLVMValueRef? + get() { + assert(this.isReal) + return if (isExternal(this)) { + runtime.addedLLVMExternalFunctions.getOrPut(this) { context.llvm.externalFunction(this.symbolName, getLlvmFunctionType(this), + origin = this.llvmSymbolOrigin) } + + } else { + context.llvmDeclarations.forFunctionOrNull(this)?.llvmFunction + } + } + + /** + * Address of entry point of [llvmFunction]. + */ + val IrFunction.entryPointAddress: ConstPointer + get() { + val result = LLVMConstBitCast(this.llvmFunction, int8TypePtr)!! + return constPointer(result) + } + + val IrClass.typeInfoPtr: ConstPointer + get() { + return if (isExternal(this)) { + constPointer(importGlobal(this.typeInfoSymbolName, runtime.typeInfoType, + origin = this.llvmSymbolOrigin)) + } else { + context.llvmDeclarations.forClass(this).typeInfo + } + } + + /** + * Pointer to type info for given class. + * It may be declared as pointer to external variable. + */ + val IrClass.llvmTypeInfoPtr: LLVMValueRef + get() = typeInfoPtr.llvm + + /** + * Returns contents of this [GlobalHash]. + * + * It must be declared identically with [Runtime.globalHashType]. + */ + fun GlobalHash.getBytes(): ByteArray { + @Suppress("DEPRECATION") + val size = GlobalHash.size + assert(size == LLVMStoreSizeOfType(llvmTargetData, runtime.globalHashType)) + + return this.bits.getBytes(size) + } + + /** + * Returns global hash of this string contents. + */ + val String.globalHashBytes: ByteArray + get() = memScoped { + val hash = globalHash(stringAsBytes(this@globalHashBytes), memScope) + hash.getBytes() + } + + /** + * Return base64 representation for global hash of this string contents. + */ + val String.globalHashBase64: String + get() { + return base64Encode(globalHashBytes) + } + + val String.globalHash: ConstValue + get() = memScoped { + val hashBytes = this@globalHash.globalHashBytes + return Struct(runtime.globalHashType, ConstArray(int8Type, hashBytes.map { Int8(it) })) + } + + val FqName.globalHash: ConstValue + get() = this.toString().globalHash + +} + +/** + * Converts this string to the sequence of bytes to be used for hashing/storing to binary/etc. + */ +internal fun stringAsBytes(str: String) = str.toByteArray(Charsets.UTF_8) + +internal val String.localHash: LocalHash + get() = LocalHash(localHash(stringAsBytes(this))) + +internal val Name.localHash: LocalHash + get() = this.toString().localHash + +internal val FqName.localHash: LocalHash + get() = this.toString().localHash + + +internal class Llvm(val context: Context, val llvmModule: LLVMModuleRef) { + + private fun importFunction(name: String, otherModule: LLVMModuleRef): LLVMValueRef { + if (LLVMGetNamedFunction(llvmModule, name) != null) { + throw IllegalArgumentException("function $name already exists") + } + + val externalFunction = LLVMGetNamedFunction(otherModule, name) ?: throw Error("function $name not found") + + val functionType = getFunctionType(externalFunction) + val function = LLVMAddFunction(llvmModule, name, functionType)!! + + copyFunctionAttributes(externalFunction, function) + + return function + } + + private fun importGlobal(name: String, otherModule: LLVMModuleRef): LLVMValueRef { + if (LLVMGetNamedGlobal(llvmModule, name) != null) { + throw IllegalArgumentException("global $name already exists") + } + + val externalGlobal = LLVMGetNamedGlobal(otherModule, name)!! + val globalType = getGlobalType(externalGlobal) + val global = LLVMAddGlobal(llvmModule, globalType, name)!! + + return global + } + + private fun copyFunctionAttributes(source: LLVMValueRef, destination: LLVMValueRef) { + // TODO: consider parameter attributes + val attributeIndex = LLVMAttributeFunctionIndex + val count = LLVMGetAttributeCountAtIndex(source, attributeIndex) + memScoped { + val attributes = allocArray(count) + LLVMGetAttributesAtIndex(source, attributeIndex, attributes) + (0 until count).forEach { + LLVMAddAttributeAtIndex(destination, attributeIndex, attributes[it]) + } + } + } + + private fun importMemset(): LLVMValueRef { + val functionType = functionType(voidType, false, int8TypePtr, int8Type, int32Type, int1Type) + return LLVMAddFunction(llvmModule, "llvm.memset.p0i8.i32", functionType)!! + } + + private fun importMemcpy(): LLVMValueRef { + val functionType = functionType(voidType, false, int8TypePtr, int8TypePtr, int32Type, int1Type) + return LLVMAddFunction(llvmModule, "llvm.memcpy.p0i8.p0i8.i32", functionType)!! + } + + private fun llvmIntrinsic(name: String, type: LLVMTypeRef, vararg attributes: String): LLVMValueRef { + val result = LLVMAddFunction(llvmModule, name, type)!! + attributes.forEach { + val kindId = getLlvmAttributeKindId(it) + addLlvmFunctionEnumAttribute(result, kindId) + } + return result + } + + internal fun externalFunction( + name: String, + type: LLVMTypeRef, + origin: CompiledKlibModuleOrigin, + independent: Boolean = false + ): LLVMValueRef { + this.imports.add(origin, onlyBitcode = independent) + + val found = LLVMGetNamedFunction(llvmModule, name) + if (found != null) { + assert(getFunctionType(found) == type) { + "Expected: ${LLVMPrintTypeToString(type)!!.toKString()} " + + "found: ${LLVMPrintTypeToString(getFunctionType(found))!!.toKString()}" + } + assert(LLVMGetLinkage(found) == LLVMLinkage.LLVMExternalLinkage) + return found + } else { + // As exported functions are written in C++ they assume sign extension for promoted types - + // mention that in attributes. + val function = LLVMAddFunction(llvmModule, name, type)!! + return memScoped { + val paramCount = LLVMCountParamTypes(type) + val paramTypes = allocArray(paramCount) + LLVMGetParamTypes(type, paramTypes) + (0 until paramCount).forEach { index -> + val paramType = paramTypes[index] + addFunctionSignext(function, index + 1, paramType) + } + val returnType = LLVMGetReturnType(type) + addFunctionSignext(function, 0, returnType) + function + } + } + } + + private fun externalNounwindFunction(name: String, type: LLVMTypeRef, origin: CompiledKlibModuleOrigin): LLVMValueRef { + val function = externalFunction(name, type, origin) + setFunctionNoUnwind(function) + return function + } + + val imports get() = context.llvmImports + + class ImportsImpl(private val context: Context) : LlvmImports { + + private val usedBitcode = mutableSetOf() + private val usedNativeDependencies = mutableSetOf() + + private val allLibraries by lazy { context.librariesWithDependencies.toSet() } + + override fun add(origin: CompiledKlibModuleOrigin, onlyBitcode: Boolean) { + val library = when (origin) { + CurrentKlibModuleOrigin -> return + is DeserializedKlibModuleOrigin -> origin.library + } + + if (library !in allLibraries) { + error("Library (${library.libraryName}) is used but not requested.\nRequested libraries: ${allLibraries.joinToString { it.libraryName }}") + } + + usedBitcode.add(library) + if (!onlyBitcode) { + usedNativeDependencies.add(library) + } + } + + override fun bitcodeIsUsed(library: KonanLibrary) = library in usedBitcode + + override fun nativeDependenciesAreUsed(library: KonanLibrary) = library in usedNativeDependencies + } + + val nativeDependenciesToLink: List by lazy { + context.config.resolvedLibraries + .getFullList(TopologicalLibraryOrder) + .filter { + require(it is KonanLibrary) + (!it.isDefault && !context.config.purgeUserLibs) || imports.nativeDependenciesAreUsed(it) + }.cast>() + } + + private val immediateBitcodeDependencies: List by lazy { + context.config.resolvedLibraries.getFullList(TopologicalLibraryOrder).cast>() + .filter { (!it.isDefault && !context.config.purgeUserLibs) || imports.bitcodeIsUsed(it) } + } + + val allCachedBitcodeDependencies: List by lazy { + val allLibraries = context.config.resolvedLibraries.getFullList().associateBy { it.uniqueName } + val result = mutableSetOf() + + fun addDependencies(cachedLibrary: CachedLibraries.Cache) { + cachedLibrary.bitcodeDependencies.forEach { + val library = allLibraries[it] ?: error("Bitcode dependency to an unknown library: $it") + result.add(library as KonanLibrary) + addDependencies(context.config.cachedLibraries.getLibraryCache(library) + ?: error("Library $it is expected to be cached")) + } + } + + for (library in immediateBitcodeDependencies) { + val cache = context.config.cachedLibraries.getLibraryCache(library) + if (cache != null) { + result += library + addDependencies(cache) + } + } + + result.toList() + } + + val allNativeDependencies: List by lazy { + (nativeDependenciesToLink + allCachedBitcodeDependencies).distinct() + } + + val allBitcodeDependencies: List by lazy { + val allNonCachedDependencies = context.librariesWithDependencies.filter { + context.config.cachedLibraries.getLibraryCache(it) == null + } + val set = (allNonCachedDependencies + allCachedBitcodeDependencies).toSet() + // This list is used in particular to build the libraries' initializers chain. + // The initializers must be called in the topological order, so make sure that the + // libraries list being returned is also toposorted. + context.config.resolvedLibraries + .getFullList(TopologicalLibraryOrder) + .cast>() + .filter { it in set } + } + + val bitcodeToLink: List by lazy { + (context.config.resolvedLibraries.getFullList(TopologicalLibraryOrder).cast>()) + .filter { shouldContainBitcode(it) } + } + + private fun shouldContainBitcode(library: KonanLibrary): Boolean { + if (!context.llvmModuleSpecification.containsLibrary(library)) { + return false + } + + if (!context.llvmModuleSpecification.isFinal) { + return true + } + + // Apply some DCE: + return (!library.isDefault && !context.config.purgeUserLibs) || imports.bitcodeIsUsed(library) + } + + val additionalProducedBitcodeFiles = mutableListOf() + + val staticData = StaticData(context) + + private val target = context.config.target + + val runtimeFile = context.config.distribution.runtime(target) + val runtime = Runtime(runtimeFile) // TODO: dispose + + val targetTriple = runtime.target + + init { + LLVMSetDataLayout(llvmModule, runtime.dataLayout) + LLVMSetTarget(llvmModule, targetTriple) + } + + private fun importRtFunction(name: String) = importFunction(name, runtime.llvmModule) + + private fun importRtGlobal(name: String) = importGlobal(name, runtime.llvmModule) + + val allocInstanceFunction = importRtFunction("AllocInstance") + val allocArrayFunction = importRtFunction("AllocArrayInstance") + val initInstanceFunction = importRtFunction("InitInstance") + val initSharedInstanceFunction = importRtFunction("InitSharedInstance") + val updateHeapRefFunction = importRtFunction("UpdateHeapRef") + val updateStackRefFunction = importRtFunction("UpdateStackRef") + val updateReturnRefFunction = importRtFunction("UpdateReturnRef") + val zeroHeapRefFunction = importRtFunction("ZeroHeapRef") + val zeroArrayRefsFunction = importRtFunction("ZeroArrayRefs") + val enterFrameFunction = importRtFunction("EnterFrame") + val leaveFrameFunction = importRtFunction("LeaveFrame") + val lookupOpenMethodFunction = importRtFunction("LookupOpenMethod") + val lookupInterfaceTableRecord = importRtFunction("LookupInterfaceTableRecord") + val isInstanceFunction = importRtFunction("IsInstance") + val isInstanceOfClassFastFunction = importRtFunction("IsInstanceOfClassFast") + val throwExceptionFunction = importRtFunction("ThrowException") + val appendToInitalizersTail = importRtFunction("AppendToInitializersTail") + val addTLSRecord = importRtFunction("AddTLSRecord") + val clearTLSRecord = importRtFunction("ClearTLSRecord") + val lookupTLS = importRtFunction("LookupTLS") + val initRuntimeIfNeeded = importRtFunction("Kotlin_initRuntimeIfNeeded") + val mutationCheck = importRtFunction("MutationCheck") + val checkLifetimesConstraint = importRtFunction("CheckLifetimesConstraint") + val freezeSubgraph = importRtFunction("FreezeSubgraph") + val checkMainThread = importRtFunction("CheckIsMainThread") + + val kRefSharedHolderInitLocal = importRtFunction("KRefSharedHolder_initLocal") + val kRefSharedHolderInit = importRtFunction("KRefSharedHolder_init") + val kRefSharedHolderDispose = importRtFunction("KRefSharedHolder_dispose") + val kRefSharedHolderRef = importRtFunction("KRefSharedHolder_ref") + + val createKotlinObjCClass by lazy { importRtFunction("CreateKotlinObjCClass") } + val getObjCKotlinTypeInfo by lazy { importRtFunction("GetObjCKotlinTypeInfo") } + val missingInitImp by lazy { importRtFunction("MissingInitImp") } + + val Kotlin_Interop_DoesObjectConformToProtocol by lazyRtFunction + val Kotlin_Interop_IsObjectKindOfClass by lazyRtFunction + + val Kotlin_ObjCExport_refToObjC by lazyRtFunction + val Kotlin_ObjCExport_refFromObjC by lazyRtFunction + val Kotlin_ObjCExport_CreateNSStringFromKString by lazyRtFunction + val Kotlin_ObjCExport_convertUnit by lazyRtFunction + val Kotlin_ObjCExport_GetAssociatedObject by lazyRtFunction + val Kotlin_ObjCExport_AbstractMethodCalled by lazyRtFunction + val Kotlin_ObjCExport_RethrowExceptionAsNSError by lazyRtFunction + val Kotlin_ObjCExport_RethrowNSErrorAsException by lazyRtFunction + val Kotlin_ObjCExport_AllocInstanceWithAssociatedObject by lazyRtFunction + val Kotlin_ObjCExport_createContinuationArgument by lazyRtFunction + val Kotlin_ObjCExport_resumeContinuation by lazyRtFunction + + val tlsMode by lazy { + when (target) { + KonanTarget.WASM32, + is KonanTarget.ZEPHYR -> LLVMThreadLocalMode.LLVMNotThreadLocal + else -> LLVMThreadLocalMode.LLVMGeneralDynamicTLSModel + } + } + + var tlsCount = 0 + + val tlsKey by lazy { + val global = LLVMAddGlobal(llvmModule, kInt8Ptr, "__KonanTlsKey")!! + LLVMSetLinkage(global, LLVMLinkage.LLVMInternalLinkage) + LLVMSetInitializer(global, LLVMConstNull(kInt8Ptr)) + global + } + + private val personalityFunctionName = when (target) { + KonanTarget.IOS_ARM32 -> "__gxx_personality_sj0" + KonanTarget.MINGW_X64 -> "__gxx_personality_seh0" + else -> "__gxx_personality_v0" + } + + val cxxStdTerminate = externalNounwindFunction( + "_ZSt9terminatev", // mangled C++ 'std::terminate' + functionType(voidType, false), + origin = context.standardLlvmSymbolsOrigin + ) + + val gxxPersonalityFunction = externalNounwindFunction( + personalityFunctionName, + functionType(int32Type, true), + origin = context.standardLlvmSymbolsOrigin + ) + val cxaBeginCatchFunction = externalNounwindFunction( + "__cxa_begin_catch", + functionType(int8TypePtr, false, int8TypePtr), + origin = context.standardLlvmSymbolsOrigin + ) + val cxaEndCatchFunction = externalNounwindFunction( + "__cxa_end_catch", + functionType(voidType, false), + origin = context.standardLlvmSymbolsOrigin + ) + + val memsetFunction = importMemset() + //val memcpyFunction = importMemcpy() + + val llvmTrap = llvmIntrinsic( + "llvm.trap", + functionType(voidType, false), + "cold", "noreturn", "nounwind" + ) + + val llvmEhTypeidFor = llvmIntrinsic( + "llvm.eh.typeid.for", + functionType(int32Type, false, int8TypePtr), + "nounwind", "readnone" + ) + + val usedFunctions = mutableListOf() + val usedGlobals = mutableListOf() + val compilerUsedGlobals = mutableListOf() + val irStaticInitializers = mutableListOf() + val otherStaticInitializers = mutableListOf() + val fileInitializers = mutableListOf() + var fileUsesThreadLocalObjects = false + val globalSharedObjects = mutableSetOf() + + private object lazyRtFunction { + operator fun provideDelegate( + thisRef: Llvm, property: KProperty<*> + ) = object : ReadOnlyProperty { + + val value by lazy { thisRef.importRtFunction(property.name) } + + override fun getValue(thisRef: Llvm, property: KProperty<*>): LLVMValueRef = value + } + } + + val llvmInt8 = int8Type + val llvmInt16 = int16Type + val llvmInt32 = int32Type + val llvmInt64 = int64Type + val llvmFloat = floatType + val llvmDouble = doubleType + val llvmVector128 = vector128Type +} + +class IrStaticInitializer(val module: ModuleDescriptor, val initializer: LLVMValueRef) diff --git a/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/DataLayout.kt b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/DataLayout.kt new file mode 100644 index 00000000000..0481efd64b0 --- /dev/null +++ b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/DataLayout.kt @@ -0,0 +1,43 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +package org.jetbrains.kotlin.backend.konan.llvm + +import llvm.* +import org.jetbrains.kotlin.backend.konan.* +import org.jetbrains.kotlin.backend.konan.optimizations.DataFlowIR +import org.jetbrains.kotlin.ir.types.IrType +import org.jetbrains.kotlin.ir.types.isNothing +import org.jetbrains.kotlin.ir.types.isUnit + +private fun RuntimeAware.getLlvmType(primitiveBinaryType: PrimitiveBinaryType?) = when (primitiveBinaryType) { + null -> this.kObjHeaderPtr + + PrimitiveBinaryType.BOOLEAN -> int1Type + PrimitiveBinaryType.BYTE -> int8Type + PrimitiveBinaryType.SHORT -> int16Type + PrimitiveBinaryType.INT -> int32Type + PrimitiveBinaryType.LONG -> int64Type + PrimitiveBinaryType.FLOAT -> floatType + PrimitiveBinaryType.DOUBLE -> doubleType + + PrimitiveBinaryType.VECTOR128 -> vector128Type + PrimitiveBinaryType.POINTER -> int8TypePtr +} + +internal fun RuntimeAware.getLLVMType(type: IrType): LLVMTypeRef = + runtime.calculatedLLVMTypes.getOrPut(type) { getLlvmType(type.computePrimitiveBinaryTypeOrNull()) } + +internal fun RuntimeAware.getLLVMType(type: DataFlowIR.Type) = + getLlvmType(type.primitiveBinaryType) + +internal fun IrType.isVoidAsReturnType() = isUnit() || isNothing() + +internal fun RuntimeAware.getLLVMReturnType(type: IrType): LLVMTypeRef { + return when { + type.isVoidAsReturnType() -> voidType + else -> getLLVMType(type) + } +} diff --git a/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/DebugUtils.kt b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/DebugUtils.kt new file mode 100644 index 00000000000..11c96bee67b --- /dev/null +++ b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/DebugUtils.kt @@ -0,0 +1,292 @@ +/* + * Copyright 2010-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +package org.jetbrains.kotlin.backend.konan.llvm + +import kotlinx.cinterop.allocArrayOf +import kotlinx.cinterop.memScoped +import kotlinx.cinterop.reinterpret +import llvm.* +import org.jetbrains.kotlin.backend.konan.* +import org.jetbrains.kotlin.ir.SourceManager.FileEntry +import org.jetbrains.kotlin.ir.UNDEFINED_OFFSET +import org.jetbrains.kotlin.ir.declarations.IrFunction +import org.jetbrains.kotlin.ir.types.IrType +import org.jetbrains.kotlin.ir.types.classOrNull +import org.jetbrains.kotlin.ir.util.SYNTHETIC_OFFSET +import org.jetbrains.kotlin.ir.util.isTypeParameter +import org.jetbrains.kotlin.ir.util.isUnsigned +import org.jetbrains.kotlin.ir.util.render +import org.jetbrains.kotlin.konan.CURRENT +import org.jetbrains.kotlin.konan.CompilerVersion +import org.jetbrains.kotlin.konan.file.File +import org.jetbrains.kotlin.utils.addToStdlib.cast + +internal object DWARF { + val producer = "konanc ${CompilerVersion.CURRENT} / kotlin-compiler: ${KotlinVersion.CURRENT}" + /* TODO: from LLVM sources is unclear what runtimeVersion corresponds to term in terms of dwarf specification. */ + val dwarfVersionMetaDataNodeName get() = "Dwarf Version".mdString() + val dwarfDebugInfoMetaDataNodeName get() = "Debug Info Version".mdString() + const val debugInfoVersion = 3 /* TODO: configurable? */ + /** + * This is the value taken from [DIFlags.FlagFwdDecl], to mark type declaration as + * forward one. + */ + const val flagsForwardDeclaration = 4 + + fun runtimeVersion(config: KonanConfig) = when (config.debugInfoVersion()) { + 2 -> 0 + 1 -> 2 /* legacy :/ */ + else -> TODO("unsupported debug info format version") + } + + /** + * Note: Kotlin language constant appears in DWARF v6, while modern linker fails to links DWARF other then [2;4], + * that why we emit version 4 actually. + */ + fun dwarfVersion(config : KonanConfig) = when (config.debugInfoVersion()) { + 1 -> 2 + 2 -> 4 /* likely the most of the future kotlin native debug info format versions will emit DWARF v4 */ + else -> TODO("unsupported debug info format version") + } + + fun language(config: KonanConfig) = when (config.debugInfoVersion()) { + 1 -> DwarfLanguage.DW_LANG_C89.value + else -> DwarfLanguage.DW_LANG_Kotlin.value + } +} + +fun KonanConfig.debugInfoVersion():Int = configuration[KonanConfigKeys.DEBUG_INFO_VERSION] ?: 1 + +internal class DebugInfo internal constructor(override val context: Context):ContextUtils { + val files = mutableMapOf() + val subprograms = mutableMapOf() + /* Some functions are inlined on all callsites and body is eliminated by DCE, so there's no LLVM value */ + val inlinedSubprograms = mutableMapOf() + var builder: DIBuilderRef? = null + var module: DIModuleRef? = null + var compilationUnit: DIScopeOpaqueRef? = null + var objHeaderPointerType: DITypeOpaqueRef? = null + var types = mutableMapOf() + + val llvmTypes = mapOf( + context.irBuiltIns.booleanType to context.llvm.llvmInt8, + context.irBuiltIns.byteType to context.llvm.llvmInt8, + context.irBuiltIns.charType to context.llvm.llvmInt16, + context.irBuiltIns.shortType to context.llvm.llvmInt16, + context.irBuiltIns.intType to context.llvm.llvmInt32, + context.irBuiltIns.longType to context.llvm.llvmInt64, + context.irBuiltIns.floatType to context.llvm.llvmFloat, + context.irBuiltIns.doubleType to context.llvm.llvmDouble) + val llvmTypeSizes = llvmTypes.map { it.key to LLVMSizeOfTypeInBits(llvmTargetData, it.value) }.toMap() + val llvmTypeAlignments = llvmTypes.map {it.key to LLVMPreferredAlignmentOfType(llvmTargetData, it.value)}.toMap() + val otherLlvmType = LLVMPointerType(int64Type, 0)!! + val otherTypeSize = LLVMSizeOfTypeInBits(llvmTargetData, otherLlvmType) + val otherTypeAlignment = LLVMPreferredAlignmentOfType(llvmTargetData, otherLlvmType) + + val compilerGeneratedFile by lazy { + DICreateFile(builder, "", "")!! + } +} + +/** + * File entry starts offsets from zero while dwarf number lines/column starting from 1. + */ +private val NO_SOURCE_FILE = "no source file" +private fun FileEntry.location(offset: Int, offsetToNumber: (Int) -> Int): Int { + assert(offset != UNDEFINED_OFFSET) + // Part "name.isEmpty() || name == NO_SOURCE_FILE" is an awful hack, @minamoto, please fix properly. + if (offset == SYNTHETIC_OFFSET || name.isEmpty() || name == NO_SOURCE_FILE) return 1 + // lldb uses 1-based unsigned integers, so 0 is "no-info". + val result = offsetToNumber(offset) + 1 + assert(result != 0) + return result +} + +internal fun FileEntry.line(offset: Int) = location(offset, this::getLineNumber) + +internal fun FileEntry.column(offset: Int) = location(offset, this::getColumnNumber) + +internal data class FileAndFolder(val file: String, val folder: String) { + companion object { + val NOFILE = FileAndFolder("-", "") + } + + fun path() = if (this == NOFILE) file else "$folder/$file" +} + +internal fun String?.toFileAndFolder(context: Context):FileAndFolder { + this ?: return FileAndFolder.NOFILE + val file = File(this).absoluteFile + var parent = file.parent + context.configuration.get(KonanConfigKeys.DEBUG_PREFIX_MAP)?.let { debugPrefixMap -> + for ((key, value) in debugPrefixMap) { + if (parent.startsWith(key)) { + parent = value + parent.removePrefix(key) + } + } + } + return FileAndFolder(file.name, parent) +} + +internal fun generateDebugInfoHeader(context: Context) { + if (context.shouldContainAnyDebugInfo()) { + val path = context.config.outputFile + .toFileAndFolder(context) + @Suppress("UNCHECKED_CAST") + context.debugInfo.module = DICreateModule( + builder = context.debugInfo.builder, + scope = null, + name = path.path(), + configurationMacro = "", + includePath = "", + iSysRoot = "") + /* TODO: figure out what here 2 means: + * + * 0:b-backend-dwarf:minamoto@minamoto-osx(0)# cat /dev/null | clang -xc -S -emit-llvm -g -o - - + * ; ModuleID = '-' + * source_filename = "-" + * target datalayout = "e-m:o-i64:64-f80:128-n8:16:32:64-S128" + * target triple = "x86_64-apple-macosx10.12.0" + * + * !llvm.dbg.cu = !{!0} + * !llvm.module.flags = !{!3, !4, !5} + * !llvm.ident = !{!6} + * + * !0 = distinct !DICompileUnit(language: DW_LANG_C99, file: !1, producer: "Apple LLVM version 8.0.0 (clang-800.0.38)", isOptimized: false, runtimeVersion: 0, emissionKind: FullDebug, enums: !2) + * !1 = !DIFile(filename: "-", directory: "/Users/minamoto/ws/.git-trees/backend-dwarf") + * !2 = !{} + * !3 = !{i32 2, !"Dwarf Version", i32 2} ; <- + * !4 = !{i32 2, !"Debug Info Version", i32 700000003} ; <- + * !5 = !{i32 1, !"PIC Level", i32 2} + * !6 = !{!"Apple LLVM version 8.0.0 (clang-800.0.38)"} + */ + val llvmTwo = Int32(2).llvm + val dwarfVersion = node(llvmTwo, DWARF.dwarfVersionMetaDataNodeName, Int32(DWARF.dwarfVersion(context.config)).llvm) + val nodeDebugInfoVersion = node(llvmTwo, DWARF.dwarfDebugInfoMetaDataNodeName, Int32(DWARF.debugInfoVersion).llvm) + val llvmModuleFlags = "llvm.module.flags" + LLVMAddNamedMetadataOperand(context.llvmModule, llvmModuleFlags, dwarfVersion) + LLVMAddNamedMetadataOperand(context.llvmModule, llvmModuleFlags, nodeDebugInfoVersion) + val objHeaderType = DICreateStructType( + refBuilder = context.debugInfo.builder, + // TODO: here should be DIFile as scope. + scope = null, + name = "ObjHeader", + file = null, + lineNumber = 0, + sizeInBits = 0, + alignInBits = 0, + flags = DWARF.flagsForwardDeclaration, + derivedFrom = null, + elements = null, + elementsCount = 0, + refPlace = null).cast() + context.debugInfo.objHeaderPointerType = dwarfPointerType(context, objHeaderType) + } +} + +@Suppress("UNCHECKED_CAST") +internal fun IrType.dwarfType(context: Context, targetData: LLVMTargetDataRef): DITypeOpaqueRef { + when { + this.computePrimitiveBinaryTypeOrNull() != null -> return debugInfoBaseType(context, targetData, this.render(), llvmType(context), encoding().value.toInt()) + else -> { + return when { + classOrNull != null || this.isTypeParameter() -> context.debugInfo.objHeaderPointerType!! + else -> TODO("$this: Does this case really exist?") + } + } + } +} + +internal fun IrType.diType(context: Context, llvmTargetData: LLVMTargetDataRef): DITypeOpaqueRef = + context.debugInfo.types.getOrPut(this) { + dwarfType(context, llvmTargetData) + } + +@Suppress("UNCHECKED_CAST") +private fun debugInfoBaseType(context:Context, targetData:LLVMTargetDataRef, typeName:String, type:LLVMTypeRef, encoding:Int) = DICreateBasicType( + context.debugInfo.builder, typeName, + LLVMSizeOfTypeInBits(targetData, type), + LLVMPreferredAlignmentOfType(targetData, type).toLong(), encoding) as DITypeOpaqueRef + +internal val IrFunction.types:List + get() { + val parameters = valueParameters.map { it.type } + return listOf(returnType, *parameters.toTypedArray()) + } + +internal fun IrType.size(context:Context) = context.debugInfo.llvmTypeSizes.getOrDefault(this, context.debugInfo.otherTypeSize) + +internal fun IrType.alignment(context:Context) = context.debugInfo.llvmTypeAlignments.getOrDefault(this, context.debugInfo.otherTypeAlignment).toLong() + +internal fun IrType.llvmType(context:Context): LLVMTypeRef = context.debugInfo.llvmTypes.getOrElse(this) { + when(computePrimitiveBinaryTypeOrNull()) { + PrimitiveBinaryType.BYTE -> context.llvm.llvmInt8 + PrimitiveBinaryType.SHORT -> context.llvm.llvmInt16 + PrimitiveBinaryType.INT -> context.llvm.llvmInt32 + PrimitiveBinaryType.LONG -> context.llvm.llvmInt64 + PrimitiveBinaryType.FLOAT -> context.llvm.llvmFloat + PrimitiveBinaryType.DOUBLE -> context.llvm.llvmDouble + PrimitiveBinaryType.VECTOR128 -> context.llvm.llvmVector128 + else -> context.debugInfo.otherLlvmType + } +} + +internal fun IrType.encoding(): DwarfTypeKind = when(computePrimitiveBinaryTypeOrNull()) { + PrimitiveBinaryType.FLOAT -> DwarfTypeKind.DW_ATE_float + PrimitiveBinaryType.DOUBLE -> DwarfTypeKind.DW_ATE_float + PrimitiveBinaryType.BOOLEAN -> DwarfTypeKind.DW_ATE_boolean + PrimitiveBinaryType.POINTER -> DwarfTypeKind.DW_ATE_address + else -> { + //TODO: not recursive. + if (this.isUnsigned()) DwarfTypeKind.DW_ATE_unsigned + else DwarfTypeKind.DW_ATE_signed + } +} + +internal fun alignTo(value:Long, align:Long):Long = (value + align - 1) / align * align + +internal fun IrFunction.subroutineType(context: Context, llvmTargetData: LLVMTargetDataRef): DISubroutineTypeRef { + val types = this@subroutineType.types + return subroutineType(context, llvmTargetData, types) +} + +internal fun subroutineType(context: Context, llvmTargetData: LLVMTargetDataRef, types: List): DISubroutineTypeRef { + return memScoped { + DICreateSubroutineType(context.debugInfo.builder, allocArrayOf( + types.map { it.diType(context, llvmTargetData) }), + types.size)!! + } +} + +@Suppress("UNCHECKED_CAST") +private fun dwarfPointerType(context: Context, type: DITypeOpaqueRef) = + DICreatePointerType(context.debugInfo.builder, type) as DITypeOpaqueRef + +internal fun setupBridgeDebugInfo(context: Context, function: LLVMValueRef): LocationInfo? { + if (!context.shouldContainLocationDebugInfo()) { + return null + } + + val file = context.debugInfo.compilerGeneratedFile + + // TODO: can we share the scope among all bridges? + val scope: DIScopeOpaqueRef = DICreateFunction( + builder = context.debugInfo.builder, + scope = file.reinterpret(), + name = function.name, + linkageName = function.name, + file = file, + lineNo = 0, + type = subroutineType(context, context.llvm.runtime.targetData, emptyList()), // TODO: use proper type. + isLocal = 0, + isDefinition = 1, + scopeLine = 0 + )!!.also { + DIFunctionAddSubprogram(function, it) + }.reinterpret() + + return LocationInfo(scope, 1, 0) +} diff --git a/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/Dwarf.kt b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/Dwarf.kt new file mode 100644 index 00000000000..15be2027d97 --- /dev/null +++ b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/Dwarf.kt @@ -0,0 +1,309 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ +package org.jetbrains.kotlin.backend.konan.llvm +/** + * This code was generated with following command: + * $ clang -xc -E -Idist/dependencies/clang-llvm-3.9.0-darwin-macos/include/ llvmDebugInfoC/src/dwarf/include/dwarf_util.kt.pp -Wp,-P -Wp,-CC -o - | sed -e '/^$/d' -e '/^\ *\/\/.*$/d' > backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/Dwarf.kt + * + */ +internal enum class DwarfTag(val value:Int) { + DW_TAG_array_type(0x0001), + DW_TAG_class_type(0x0002), + DW_TAG_entry_point(0x0003), + DW_TAG_enumeration_type(0x0004), + DW_TAG_formal_parameter(0x0005), + DW_TAG_imported_declaration(0x0008), + DW_TAG_label(0x000a), + DW_TAG_lexical_block(0x000b), + DW_TAG_member(0x000d), + DW_TAG_pointer_type(0x000f), + DW_TAG_reference_type(0x0010), + DW_TAG_compile_unit(0x0011), + DW_TAG_string_type(0x0012), + DW_TAG_structure_type(0x0013), + DW_TAG_subroutine_type(0x0015), + DW_TAG_typedef(0x0016), + DW_TAG_union_type(0x0017), + DW_TAG_unspecified_parameters(0x0018), + DW_TAG_variant(0x0019), + DW_TAG_common_block(0x001a), + DW_TAG_common_inclusion(0x001b), + DW_TAG_inheritance(0x001c), + DW_TAG_inlined_subroutine(0x001d), + DW_TAG_module(0x001e), + DW_TAG_ptr_to_member_type(0x001f), + DW_TAG_set_type(0x0020), + DW_TAG_subrange_type(0x0021), + DW_TAG_with_stmt(0x0022), + DW_TAG_access_declaration(0x0023), + DW_TAG_base_type(0x0024), + DW_TAG_catch_block(0x0025), + DW_TAG_const_type(0x0026), + DW_TAG_constant(0x0027), + DW_TAG_enumerator(0x0028), + DW_TAG_file_type(0x0029), + DW_TAG_friend(0x002a), + DW_TAG_namelist(0x002b), + DW_TAG_namelist_item(0x002c), + DW_TAG_packed_type(0x002d), + DW_TAG_subprogram(0x002e), + DW_TAG_template_type_parameter(0x002f), + DW_TAG_template_value_parameter(0x0030), + DW_TAG_thrown_type(0x0031), + DW_TAG_try_block(0x0032), + DW_TAG_variant_part(0x0033), + DW_TAG_variable(0x0034), + DW_TAG_volatile_type(0x0035), + DW_TAG_dwarf_procedure(0x0036), + DW_TAG_restrict_type(0x0037), + DW_TAG_interface_type(0x0038), + DW_TAG_namespace(0x0039), + DW_TAG_imported_module(0x003a), + DW_TAG_unspecified_type(0x003b), + DW_TAG_partial_unit(0x003c), + DW_TAG_imported_unit(0x003d), + DW_TAG_condition(0x003f), + DW_TAG_shared_type(0x0040), + DW_TAG_type_unit(0x0041), + DW_TAG_rvalue_reference_type(0x0042), + DW_TAG_template_alias(0x0043), + DW_TAG_coarray_type(0x0044), + DW_TAG_generic_subrange(0x0045), + DW_TAG_dynamic_type(0x0046), + DW_TAG_MIPS_loop(0x4081), + DW_TAG_format_label(0x4101), + DW_TAG_function_template(0x4102), + DW_TAG_class_template(0x4103), + DW_TAG_GNU_template_template_param(0x4106), + DW_TAG_GNU_template_parameter_pack(0x4107), + DW_TAG_GNU_formal_parameter_pack(0x4108), + DW_TAG_APPLE_property(0x4200), + DW_TAG_BORLAND_property(0xb000), + DW_TAG_BORLAND_Delphi_string(0xb001), + DW_TAG_BORLAND_Delphi_dynamic_array(0xb002), + DW_TAG_BORLAND_Delphi_set(0xb003), + DW_TAG_BORLAND_Delphi_variant(0xb004), +} + +internal enum class DwarfTypeKind(val value:Byte) { + DW_ATE_address(0x01), + DW_ATE_boolean(0x02), + DW_ATE_complex_float(0x03), + DW_ATE_float(0x04), + DW_ATE_signed(0x05), + DW_ATE_signed_char(0x06), + DW_ATE_unsigned(0x07), + DW_ATE_unsigned_char(0x08), + DW_ATE_imaginary_float(0x09), + DW_ATE_packed_decimal(0x0a), + DW_ATE_numeric_string(0x0b), + DW_ATE_edited(0x0c), + DW_ATE_signed_fixed(0x0d), + DW_ATE_unsigned_fixed(0x0e), + DW_ATE_decimal_float(0x0f), + DW_ATE_UTF(0x10), +} + +internal enum class DwarfOp(val value:Long) { + DW_OP_addr(0x03), + DW_OP_deref(0x06), + DW_OP_const1u(0x08), + DW_OP_const1s(0x09), + DW_OP_const2u(0x0a), + DW_OP_const2s(0x0b), + DW_OP_const4u(0x0c), + DW_OP_const4s(0x0d), + DW_OP_const8u(0x0e), + DW_OP_const8s(0x0f), + DW_OP_constu(0x10), + DW_OP_consts(0x11), + DW_OP_dup(0x12), + DW_OP_drop(0x13), + DW_OP_over(0x14), + DW_OP_pick(0x15), + DW_OP_swap(0x16), + DW_OP_rot(0x17), + DW_OP_xderef(0x18), + DW_OP_abs(0x19), + DW_OP_and(0x1a), + DW_OP_div(0x1b), + DW_OP_minus(0x1c), + DW_OP_mod(0x1d), + DW_OP_mul(0x1e), + DW_OP_neg(0x1f), + DW_OP_not(0x20), + DW_OP_or(0x21), + DW_OP_plus(0x22), + DW_OP_plus_uconst(0x23), + DW_OP_shl(0x24), + DW_OP_shr(0x25), + DW_OP_shra(0x26), + DW_OP_xor(0x27), + DW_OP_skip(0x2f), + DW_OP_bra(0x28), + DW_OP_eq(0x29), + DW_OP_ge(0x2a), + DW_OP_gt(0x2b), + DW_OP_le(0x2c), + DW_OP_lt(0x2d), + DW_OP_ne(0x2e), + DW_OP_lit0(0x30), + DW_OP_lit1(0x31), + DW_OP_lit2(0x32), + DW_OP_lit3(0x33), + DW_OP_lit4(0x34), + DW_OP_lit5(0x35), + DW_OP_lit6(0x36), + DW_OP_lit7(0x37), + DW_OP_lit8(0x38), + DW_OP_lit9(0x39), + DW_OP_lit10(0x3a), + DW_OP_lit11(0x3b), + DW_OP_lit12(0x3c), + DW_OP_lit13(0x3d), + DW_OP_lit14(0x3e), + DW_OP_lit15(0x3f), + DW_OP_lit16(0x40), + DW_OP_lit17(0x41), + DW_OP_lit18(0x42), + DW_OP_lit19(0x43), + DW_OP_lit20(0x44), + DW_OP_lit21(0x45), + DW_OP_lit22(0x46), + DW_OP_lit23(0x47), + DW_OP_lit24(0x48), + DW_OP_lit25(0x49), + DW_OP_lit26(0x4a), + DW_OP_lit27(0x4b), + DW_OP_lit28(0x4c), + DW_OP_lit29(0x4d), + DW_OP_lit30(0x4e), + DW_OP_lit31(0x4f), + DW_OP_reg0(0x50), + DW_OP_reg1(0x51), + DW_OP_reg2(0x52), + DW_OP_reg3(0x53), + DW_OP_reg4(0x54), + DW_OP_reg5(0x55), + DW_OP_reg6(0x56), + DW_OP_reg7(0x57), + DW_OP_reg8(0x58), + DW_OP_reg9(0x59), + DW_OP_reg10(0x5a), + DW_OP_reg11(0x5b), + DW_OP_reg12(0x5c), + DW_OP_reg13(0x5d), + DW_OP_reg14(0x5e), + DW_OP_reg15(0x5f), + DW_OP_reg16(0x60), + DW_OP_reg17(0x61), + DW_OP_reg18(0x62), + DW_OP_reg19(0x63), + DW_OP_reg20(0x64), + DW_OP_reg21(0x65), + DW_OP_reg22(0x66), + DW_OP_reg23(0x67), + DW_OP_reg24(0x68), + DW_OP_reg25(0x69), + DW_OP_reg26(0x6a), + DW_OP_reg27(0x6b), + DW_OP_reg28(0x6c), + DW_OP_reg29(0x6d), + DW_OP_reg30(0x6e), + DW_OP_reg31(0x6f), + DW_OP_breg0(0x70), + DW_OP_breg1(0x71), + DW_OP_breg2(0x72), + DW_OP_breg3(0x73), + DW_OP_breg4(0x74), + DW_OP_breg5(0x75), + DW_OP_breg6(0x76), + DW_OP_breg7(0x77), + DW_OP_breg8(0x78), + DW_OP_breg9(0x79), + DW_OP_breg10(0x7a), + DW_OP_breg11(0x7b), + DW_OP_breg12(0x7c), + DW_OP_breg13(0x7d), + DW_OP_breg14(0x7e), + DW_OP_breg15(0x7f), + DW_OP_breg16(0x80), + DW_OP_breg17(0x81), + DW_OP_breg18(0x82), + DW_OP_breg19(0x83), + DW_OP_breg20(0x84), + DW_OP_breg21(0x85), + DW_OP_breg22(0x86), + DW_OP_breg23(0x87), + DW_OP_breg24(0x88), + DW_OP_breg25(0x89), + DW_OP_breg26(0x8a), + DW_OP_breg27(0x8b), + DW_OP_breg28(0x8c), + DW_OP_breg29(0x8d), + DW_OP_breg30(0x8e), + DW_OP_breg31(0x8f), + DW_OP_regx(0x90), + DW_OP_fbreg(0x91), + DW_OP_bregx(0x92), + DW_OP_piece(0x93), + DW_OP_deref_size(0x94), + DW_OP_xderef_size(0x95), + DW_OP_nop(0x96), + DW_OP_push_object_address(0x97), + DW_OP_call2(0x98), + DW_OP_call4(0x99), + DW_OP_call_ref(0x9a), + DW_OP_form_tls_address(0x9b), + DW_OP_call_frame_cfa(0x9c), + DW_OP_bit_piece(0x9d), + DW_OP_implicit_value(0x9e), + DW_OP_stack_value(0x9f), + DW_OP_GNU_push_tls_address(0xe0), + DW_OP_GNU_addr_index(0xfb), + DW_OP_GNU_const_index(0xfc), +} + +internal enum class DwarfLanguage(val value:Int) { + DW_LANG_C89(0x0001), + DW_LANG_C(0x0002), + DW_LANG_Ada83(0x0003), + DW_LANG_C_plus_plus(0x0004), + DW_LANG_Cobol74(0x0005), + DW_LANG_Cobol85(0x0006), + DW_LANG_Fortran77(0x0007), + DW_LANG_Fortran90(0x0008), + DW_LANG_Pascal83(0x0009), + DW_LANG_Modula2(0x000a), + DW_LANG_Java(0x000b), + DW_LANG_C99(0x000c), + DW_LANG_Ada95(0x000d), + DW_LANG_Fortran95(0x000e), + DW_LANG_PLI(0x000f), + DW_LANG_ObjC(0x0010), + DW_LANG_ObjC_plus_plus(0x0011), + DW_LANG_UPC(0x0012), + DW_LANG_D(0x0013), + DW_LANG_Python(0x0014), + DW_LANG_OpenCL(0x0015), + DW_LANG_Go(0x0016), + DW_LANG_Modula3(0x0017), + DW_LANG_Haskell(0x0018), + DW_LANG_C_plus_plus_03(0x0019), + DW_LANG_C_plus_plus_11(0x001a), + DW_LANG_OCaml(0x001b), + DW_LANG_Rust(0x001c), + DW_LANG_C11(0x001d), + DW_LANG_Swift(0x001e), + DW_LANG_Julia(0x001f), + DW_LANG_Dylan(0x0020), + DW_LANG_C_plus_plus_14(0x0021), + DW_LANG_Fortran03(0x0022), + DW_LANG_Fortran08(0x0023), + DW_LANG_Mips_Assembler(0x8001), + DW_LANG_GOOGLE_RenderScript(0x8e57), + DW_LANG_BORLAND_Delphi(0xb000), + DW_LANG_Kotlin(0x0026) +} diff --git a/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/EntryPoint.kt b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/EntryPoint.kt new file mode 100644 index 00000000000..8370ff23a62 --- /dev/null +++ b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/EntryPoint.kt @@ -0,0 +1,78 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +package org.jetbrains.kotlin.backend.konan.llvm + +import org.jetbrains.kotlin.backend.konan.* +import org.jetbrains.kotlin.backend.konan.descriptors.isArray +import org.jetbrains.kotlin.config.CompilerConfiguration +import org.jetbrains.kotlin.descriptors.ClassDescriptor +import org.jetbrains.kotlin.descriptors.FunctionDescriptor +import org.jetbrains.kotlin.incremental.components.NoLookupLocation +import org.jetbrains.kotlin.konan.target.CompilerOutputKind.* +import org.jetbrains.kotlin.name.FqName +import org.jetbrains.kotlin.resolve.descriptorUtil.fqNameSafe +import org.jetbrains.kotlin.types.KotlinType +import org.jetbrains.kotlin.types.typeUtil.isUnit + +internal fun findMainEntryPoint(context: Context): FunctionDescriptor? { + + val config = context.config.configuration + if (config.get(KonanConfigKeys.PRODUCE) != PROGRAM) return null + + val entryPoint = FqName(config.get(KonanConfigKeys.ENTRY) ?: defaultEntryName(config)) + + val entryName = entryPoint.shortName() + val packageName = entryPoint.parent() + + val packageScope = context.builtIns.builtInsModule.getPackage(packageName).memberScope + + val candidates = packageScope.getContributedFunctions(entryName, + NoLookupLocation.FROM_BACKEND).filter { + it.returnType?.isUnit() == true && + it.typeParameters.isEmpty() && + it.visibility.isPublicAPI + } + + val main = + candidates.singleOrNull { it.hasSingleArrayOfStringParameter } ?: + candidates.singleOrNull { it.hasNoParameters } ?: + context.reportCompilationError("Could not find '$entryName' in '$packageName' package.") + + if (main.isSuspend) + context.reportCompilationError("Entry point can not be a suspend function.") + + return main +} + +private fun defaultEntryName(config: CompilerConfiguration): String = + when (config.get(KonanConfigKeys.GENERATE_TEST_RUNNER)) { + TestRunnerKind.MAIN_THREAD -> "kotlin.native.internal.test.main" + TestRunnerKind.WORKER -> "kotlin.native.internal.test.worker" + TestRunnerKind.MAIN_THREAD_NO_EXIT -> "kotlin.native.internal.test.mainNoExit" + else -> "main" + } + +private val KotlinType.filterClass: ClassDescriptor? + get() { + val constr = constructor.declarationDescriptor + return constr as? ClassDescriptor + } + +private val ClassDescriptor.isString + get() = fqNameSafe.asString() == "kotlin.String" + +private val KotlinType.isString + get() = filterClass?.isString ?: false + +private val KotlinType.isArrayOfString: Boolean + get() = (filterClass?.isArray ?: false) && + (arguments.singleOrNull()?.type?.isString ?: false) + +private val FunctionDescriptor.hasSingleArrayOfStringParameter: Boolean + get() = valueParameters.singleOrNull()?.type?.isArrayOfString ?: false + +private val FunctionDescriptor.hasNoParameters: Boolean + get() = valueParameters.isEmpty() diff --git a/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/HashUtils.kt b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/HashUtils.kt new file mode 100644 index 00000000000..1f3f4aa0fca --- /dev/null +++ b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/HashUtils.kt @@ -0,0 +1,53 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +package org.jetbrains.kotlin.backend.konan.llvm + +import kotlinx.cinterop.* +import org.jetbrains.kotlin.backend.konan.hash.* + +internal fun localHash(data: ByteArray): Long { + memScoped { + val res = alloc() + val bytes = allocArrayOf(data) + MakeLocalHash(bytes, data.size, res.ptr) + return res.value + } +} + +internal fun globalHash(data: ByteArray, retValPlacement: NativePlacement): GlobalHash { + val res = retValPlacement.alloc() + memScoped { + val bytes = allocArrayOf(data) + MakeGlobalHash(bytes, data.size, res.ptr) + } + return res +} + +public fun base64Encode(data: ByteArray): String { + memScoped { + val resultSize = 4 * data.size / 3 + 3 + 1 + val result = allocArray(resultSize) + val bytes = allocArrayOf(data) + EncodeBase64(bytes, data.size, result, resultSize) + // TODO: any better way to do that without two copies? + return result.toKString() + } +} + +public fun base64Decode(encoded: String): ByteArray { + memScoped { + val bufferSize: Int = 3 * encoded.length / 4 + val result = allocArray(bufferSize) + val resultSize = allocArray(1) + resultSize[0] = bufferSize + val errorCode = DecodeBase64(encoded, encoded.length, result, resultSize) + if (errorCode != 0) throw Error("Non-zero exit code of DecodeBase64: ${errorCode}") + val realSize = resultSize[0] + return result.readBytes(realSize) + } +} + +internal class LocalHash(val value: Long) : ConstValue by Int64(value) diff --git a/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/Imports.kt b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/Imports.kt new file mode 100644 index 00000000000..4116a4260f6 --- /dev/null +++ b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/Imports.kt @@ -0,0 +1,35 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +package org.jetbrains.kotlin.backend.konan.llvm + +import org.jetbrains.kotlin.backend.konan.Context +import org.jetbrains.kotlin.backend.konan.descriptors.isExpectMember +import org.jetbrains.kotlin.descriptors.DeclarationDescriptor +import org.jetbrains.kotlin.descriptors.konan.CompiledKlibModuleOrigin +import org.jetbrains.kotlin.descriptors.konan.SyntheticModulesOrigin +import org.jetbrains.kotlin.descriptors.konan.klibModuleOrigin +import org.jetbrains.kotlin.konan.library.KonanLibrary +import org.jetbrains.kotlin.resolve.descriptorUtil.module + +internal interface LlvmImports { + fun add(origin: CompiledKlibModuleOrigin, onlyBitcode: Boolean = false) + fun bitcodeIsUsed(library: KonanLibrary): Boolean + fun nativeDependenciesAreUsed(library: KonanLibrary): Boolean +} + +internal val DeclarationDescriptor.llvmSymbolOrigin: CompiledKlibModuleOrigin + get() { + assert(!this.isExpectMember) { this } + + val module = this.module + val moduleOrigin = module.klibModuleOrigin + when (moduleOrigin) { + is CompiledKlibModuleOrigin -> return moduleOrigin + SyntheticModulesOrigin -> error("Declaration is synthetic and can't be an origin of LLVM symbol:\n${this}") + } + } + +internal val Context.standardLlvmSymbolsOrigin: CompiledKlibModuleOrigin get() = this.stdlibModule.llvmSymbolOrigin diff --git a/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/IntrinsicGenerator.kt b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/IntrinsicGenerator.kt new file mode 100644 index 00000000000..c3613e4438a --- /dev/null +++ b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/IntrinsicGenerator.kt @@ -0,0 +1,725 @@ +package org.jetbrains.kotlin.backend.konan.llvm + +import kotlinx.cinterop.cValuesOf +import llvm.* +import org.jetbrains.kotlin.backend.konan.RuntimeNames +import org.jetbrains.kotlin.backend.konan.descriptors.getAnnotationStringValue +import org.jetbrains.kotlin.backend.konan.descriptors.isTypedIntrinsic +import org.jetbrains.kotlin.backend.konan.llvm.objc.genObjCSelector +import org.jetbrains.kotlin.backend.konan.reportCompilationError +import org.jetbrains.kotlin.ir.IrElement +import org.jetbrains.kotlin.ir.declarations.IrClass +import org.jetbrains.kotlin.ir.declarations.IrFunction +import org.jetbrains.kotlin.ir.expressions.* +import org.jetbrains.kotlin.ir.types.getClass +import org.jetbrains.kotlin.ir.util.dump +import org.jetbrains.kotlin.ir.util.findAnnotation +import org.jetbrains.kotlin.ir.util.isSuspend + +internal enum class IntrinsicType { + PLUS, + MINUS, + TIMES, + SIGNED_DIV, + SIGNED_REM, + UNSIGNED_DIV, + UNSIGNED_REM, + INC, + DEC, + UNARY_PLUS, + UNARY_MINUS, + SHL, + SHR, + USHR, + AND, + OR, + XOR, + INV, + SIGN_EXTEND, + ZERO_EXTEND, + INT_TRUNCATE, + FLOAT_TRUNCATE, + FLOAT_EXTEND, + SIGNED_TO_FLOAT, + UNSIGNED_TO_FLOAT, + FLOAT_TO_SIGNED, + SIGNED_COMPARE_TO, + UNSIGNED_COMPARE_TO, + NOT, + REINTERPRET, + EXTRACT_ELEMENT, + ARE_EQUAL_BY_VALUE, + IEEE_754_EQUALS, + // OBJC + OBJC_GET_MESSENGER, + OBJC_GET_MESSENGER_STRET, + OBJC_GET_OBJC_CLASS, + OBJC_CREATE_SUPER_STRUCT, + OBJC_INIT_BY, + OBJC_GET_SELECTOR, + // Other + GET_CLASS_TYPE_INFO, + CREATE_UNINITIALIZED_INSTANCE, + LIST_OF_INTERNAL, + IDENTITY, + IMMUTABLE_BLOB, + INIT_INSTANCE, + // Enums + ENUM_VALUES, + ENUM_VALUE_OF, + // Coroutines + GET_CONTINUATION, + RETURN_IF_SUSPENDED, + COROUTINE_LAUNCHPAD, + // Interop + INTEROP_READ_BITS, + INTEROP_WRITE_BITS, + INTEROP_READ_PRIMITIVE, + INTEROP_WRITE_PRIMITIVE, + INTEROP_GET_POINTER_SIZE, + INTEROP_NATIVE_PTR_TO_LONG, + INTEROP_NATIVE_PTR_PLUS_LONG, + INTEROP_GET_NATIVE_NULL_PTR, + INTEROP_CONVERT, + INTEROP_BITS_TO_FLOAT, + INTEROP_BITS_TO_DOUBLE, + INTEROP_SIGN_EXTEND, + INTEROP_NARROW, + INTEROP_STATIC_C_FUNCTION, + INTEROP_FUNPTR_INVOKE, + INTEROP_MEMORY_COPY, + // Worker + WORKER_EXECUTE +} + +// Explicit and single interface between Intrinsic Generator and IrToBitcode. +internal interface IntrinsicGeneratorEnvironment { + + val codegen: CodeGenerator + + val functionGenerationContext: FunctionGenerationContext + + val continuation: LLVMValueRef + + val exceptionHandler: ExceptionHandler + + val stackLocalsManager: StackLocalsManager + + fun calculateLifetime(element: IrElement): Lifetime + + fun evaluateCall(function: IrFunction, args: List, resultLifetime: Lifetime, superClass: IrClass? = null): LLVMValueRef + + fun evaluateExplicitArgs(expression: IrFunctionAccessExpression): List + + fun evaluateExpression(value: IrExpression): LLVMValueRef +} + +internal fun tryGetIntrinsicType(callSite: IrFunctionAccessExpression): IntrinsicType? = + if (callSite.symbol.owner.isTypedIntrinsic) getIntrinsicType(callSite) else null + +private fun getIntrinsicType(callSite: IrFunctionAccessExpression): IntrinsicType { + val function = callSite.symbol.owner + val annotation = function.annotations.findAnnotation(RuntimeNames.typedIntrinsicAnnotation)!! + val value = annotation.getAnnotationStringValue()!! + return IntrinsicType.valueOf(value) +} + +internal class IntrinsicGenerator(private val environment: IntrinsicGeneratorEnvironment) { + + private val codegen = environment.codegen + + private val context = codegen.context + + private val IrCall.llvmReturnType: LLVMTypeRef + get() = LLVMGetReturnType(codegen.getLlvmFunctionType(symbol.owner))!! + + + private fun LLVMTypeRef.sizeInBits() = LLVMSizeOfTypeInBits(codegen.llvmTargetData, this).toInt() + + /** + * Some intrinsics have to be processed before evaluation of their arguments. + * So this method looks at [callSite] and if it is call to "special" intrinsic + * processes it. Otherwise it returns null. + */ + fun tryEvaluateSpecialCall(callSite: IrFunctionAccessExpression): LLVMValueRef? { + val function = callSite.symbol.owner + if (!function.isTypedIntrinsic) { + return null + } + return when (getIntrinsicType(callSite)) { + IntrinsicType.IMMUTABLE_BLOB -> { + @Suppress("UNCHECKED_CAST") + val arg = callSite.getValueArgument(0) as IrConst + context.llvm.staticData.createImmutableBlob(arg) + } + IntrinsicType.OBJC_GET_SELECTOR -> { + val selector = (callSite.getValueArgument(0) as IrConst<*>).value as String + environment.functionGenerationContext.genObjCSelector(selector) + } + IntrinsicType.INIT_INSTANCE -> { + val initializer = callSite.getValueArgument(1) as IrConstructorCall + val thiz = environment.evaluateExpression(callSite.getValueArgument(0)!!) + environment.evaluateCall( + initializer.symbol.owner, + listOf(thiz) + environment.evaluateExplicitArgs(initializer), + environment.calculateLifetime(initializer) + ) + codegen.theUnitInstanceRef.llvm + } + IntrinsicType.COROUTINE_LAUNCHPAD -> { + val suspendFunctionCall = callSite.getValueArgument(0) as IrCall + val continuation = environment.evaluateExpression(callSite.getValueArgument(1)!!) + val suspendFunction = suspendFunctionCall.symbol.owner + assert(suspendFunction.isSuspend) { "Call to a suspend function expected but was ${suspendFunction.dump()}" } + environment.evaluateCall(suspendFunction, + environment.evaluateExplicitArgs(suspendFunctionCall) + listOf(continuation), + environment.calculateLifetime(suspendFunctionCall), + suspendFunction.parent as? IrClass // Call non-virtually. + ) + } + else -> null + } + } + + fun evaluateCall(callSite: IrCall, args: List): LLVMValueRef = + environment.functionGenerationContext.evaluateCall(callSite, args) + + // Assuming that we checked for `TypedIntrinsic` annotation presence. + private fun FunctionGenerationContext.evaluateCall(callSite: IrCall, args: List): LLVMValueRef = + when (val intrinsicType = getIntrinsicType(callSite)) { + IntrinsicType.PLUS -> emitPlus(args) + IntrinsicType.MINUS -> emitMinus(args) + IntrinsicType.TIMES -> emitTimes(args) + IntrinsicType.SIGNED_DIV -> emitSignedDiv(args) + IntrinsicType.SIGNED_REM -> emitSignedRem(args) + IntrinsicType.UNSIGNED_DIV -> emitUnsignedDiv(args) + IntrinsicType.UNSIGNED_REM -> emitUnsignedRem(args) + IntrinsicType.INC -> emitInc(args) + IntrinsicType.DEC -> emitDec(args) + IntrinsicType.UNARY_PLUS -> emitUnaryPlus(args) + IntrinsicType.UNARY_MINUS -> emitUnaryMinus(args) + IntrinsicType.SHL -> emitShl(args) + IntrinsicType.SHR -> emitShr(args) + IntrinsicType.USHR -> emitUshr(args) + IntrinsicType.AND -> emitAnd(args) + IntrinsicType.OR -> emitOr(args) + IntrinsicType.XOR -> emitXor(args) + IntrinsicType.INV -> emitInv(args) + IntrinsicType.SIGNED_COMPARE_TO -> emitSignedCompareTo(args) + IntrinsicType.UNSIGNED_COMPARE_TO -> emitUnsignedCompareTo(args) + IntrinsicType.NOT -> emitNot(args) + IntrinsicType.REINTERPRET -> emitReinterpret(callSite, args) + IntrinsicType.EXTRACT_ELEMENT -> emitExtractElement(callSite, args) + IntrinsicType.SIGN_EXTEND -> emitSignExtend(callSite, args) + IntrinsicType.ZERO_EXTEND -> emitZeroExtend(callSite, args) + IntrinsicType.INT_TRUNCATE -> emitIntTruncate(callSite, args) + IntrinsicType.SIGNED_TO_FLOAT -> emitSignedToFloat(callSite, args) + IntrinsicType.UNSIGNED_TO_FLOAT -> emitUnsignedToFloat(callSite, args) + IntrinsicType.FLOAT_TO_SIGNED -> emitFloatToSigned(callSite, args) + IntrinsicType.FLOAT_EXTEND -> emitFloatExtend(callSite, args) + IntrinsicType.FLOAT_TRUNCATE -> emitFloatTruncate(callSite, args) + IntrinsicType.ARE_EQUAL_BY_VALUE -> emitAreEqualByValue(args) + IntrinsicType.IEEE_754_EQUALS -> emitIeee754Equals(args) + IntrinsicType.OBJC_GET_MESSENGER -> emitObjCGetMessenger(args, isStret = false) + IntrinsicType.OBJC_GET_MESSENGER_STRET -> emitObjCGetMessenger(args, isStret = true) + IntrinsicType.OBJC_GET_OBJC_CLASS -> emitGetObjCClass(callSite) + IntrinsicType.OBJC_CREATE_SUPER_STRUCT -> emitObjCCreateSuperStruct(args) + IntrinsicType.GET_CLASS_TYPE_INFO -> emitGetClassTypeInfo(callSite) + IntrinsicType.INTEROP_READ_BITS -> emitReadBits(args) + IntrinsicType.INTEROP_WRITE_BITS -> emitWriteBits(args) + IntrinsicType.INTEROP_READ_PRIMITIVE -> emitReadPrimitive(callSite, args) + IntrinsicType.INTEROP_WRITE_PRIMITIVE -> emitWritePrimitive(callSite, args) + IntrinsicType.INTEROP_GET_POINTER_SIZE -> emitGetPointerSize() + IntrinsicType.CREATE_UNINITIALIZED_INSTANCE -> emitCreateUninitializedInstance(callSite) + IntrinsicType.INTEROP_NATIVE_PTR_TO_LONG -> emitNativePtrToLong(callSite, args) + IntrinsicType.INTEROP_NATIVE_PTR_PLUS_LONG -> emitNativePtrPlusLong(args) + IntrinsicType.INTEROP_GET_NATIVE_NULL_PTR -> emitGetNativeNullPtr() + IntrinsicType.LIST_OF_INTERNAL -> emitListOfInternal(callSite, args) + IntrinsicType.IDENTITY -> emitIdentity(args) + IntrinsicType.GET_CONTINUATION -> emitGetContinuation() + IntrinsicType.INTEROP_MEMORY_COPY -> emitMemoryCopy(callSite, args) + IntrinsicType.RETURN_IF_SUSPENDED, + IntrinsicType.INTEROP_BITS_TO_FLOAT, + IntrinsicType.INTEROP_BITS_TO_DOUBLE, + IntrinsicType.INTEROP_SIGN_EXTEND, + IntrinsicType.INTEROP_NARROW, + IntrinsicType.INTEROP_STATIC_C_FUNCTION, + IntrinsicType.INTEROP_FUNPTR_INVOKE, + IntrinsicType.INTEROP_CONVERT, + IntrinsicType.ENUM_VALUES, + IntrinsicType.ENUM_VALUE_OF, + IntrinsicType.WORKER_EXECUTE -> + reportNonLoweredIntrinsic(intrinsicType) + IntrinsicType.INIT_INSTANCE, + IntrinsicType.OBJC_INIT_BY, + IntrinsicType.COROUTINE_LAUNCHPAD, + IntrinsicType.OBJC_GET_SELECTOR, + IntrinsicType.IMMUTABLE_BLOB -> + reportSpecialIntrinsic(intrinsicType) + } + + private fun reportSpecialIntrinsic(intrinsicType: IntrinsicType): Nothing = + context.reportCompilationError("$intrinsicType should be handled by `tryEvaluateSpecialCall`") + + private fun reportNonLoweredIntrinsic(intrinsicType: IntrinsicType): Nothing = + context.reportCompilationError("Intrinsic of type $intrinsicType should be handled by previos lowering phase") + + private fun FunctionGenerationContext.emitGetContinuation(): LLVMValueRef = + environment.continuation + + private fun FunctionGenerationContext.emitIdentity(args: List): LLVMValueRef = + args.single() + + private fun FunctionGenerationContext.emitListOfInternal(callSite: IrCall, args: List): LLVMValueRef { + val varargExpression = callSite.getValueArgument(0) as IrVararg + val vararg = args.single() + + val length = varargExpression.elements.size + // TODO: store length in `vararg` itself when more abstract types will be used for values. + + val array = constPointer(vararg) + // Note: dirty hack here: `vararg` has type `Array`, but `createConstArrayList` expects `Array`; + // however `vararg` is immutable, and in current implementation it has type `Array`, + // so let's ignore this mismatch currently for simplicity. + + return context.llvm.staticData.createConstArrayList(array, length).llvm + } + + private fun FunctionGenerationContext.emitGetNativeNullPtr(): LLVMValueRef = + kNullInt8Ptr + + private fun FunctionGenerationContext.emitNativePtrPlusLong(args: List): LLVMValueRef = + gep(args[0], args[1]) + + private fun FunctionGenerationContext.emitNativePtrToLong(callSite: IrCall, args: List): LLVMValueRef { + val intPtrValue = ptrToInt(args.single(), codegen.intPtrType) + val resultType = callSite.llvmReturnType + return if (resultType == intPtrValue.type) { + intPtrValue + } else { + LLVMBuildSExt(builder, intPtrValue, resultType, "")!! + } + } + + private fun FunctionGenerationContext.emitCreateUninitializedInstance(callSite: IrCall): LLVMValueRef { + val typeParameterT = context.ir.symbols.createUninitializedInstance.descriptor.typeParameters[0] + val enumClass = callSite.getTypeArgument(typeParameterT)!! + val enumIrClass = enumClass.getClass()!! + return allocInstance(enumIrClass, environment.calculateLifetime(callSite), environment.stackLocalsManager) + } + + private fun FunctionGenerationContext.emitGetPointerSize(): LLVMValueRef = + Int32(LLVMPointerSize(codegen.llvmTargetData)).llvm + + private fun FunctionGenerationContext.emitReadPrimitive(callSite: IrCall, args: List): LLVMValueRef { + val pointerType = pointerType(callSite.llvmReturnType) + val rawPointer = args.last() + val pointer = bitcast(pointerType, rawPointer) + return load(pointer) + } + + private fun FunctionGenerationContext.emitWritePrimitive(callSite: IrCall, args: List): LLVMValueRef { + val function = callSite.symbol.owner + val pointerType = pointerType(codegen.getLLVMType(function.valueParameters.last().type)) + val rawPointer = args[1] + val pointer = bitcast(pointerType, rawPointer) + store(args[2], pointer) + return codegen.theUnitInstanceRef.llvm + } + + private fun FunctionGenerationContext.emitReadBits(args: List): LLVMValueRef { + val ptr = args[0] + assert(ptr.type == int8TypePtr) + + val offset = extractConstUnsignedInt(args[1]) + val size = extractConstUnsignedInt(args[2]).toInt() + val signed = extractConstUnsignedInt(args[3]) != 0L + + val prefixBitsNum = (offset % 8).toInt() + val suffixBitsNum = (8 - ((size + offset) % 8).toInt()) % 8 + + // Note: LLVM allows to read without padding tail up to byte boundary, but the result seems to be incorrect. + + val bitsWithPaddingNum = prefixBitsNum + size + suffixBitsNum + val bitsWithPaddingType = LLVMIntTypeInContext(llvmContext, bitsWithPaddingNum)!! + + val bitsWithPaddingPtr = bitcast(org.jetbrains.kotlin.backend.konan.llvm.pointerType(bitsWithPaddingType), gep(ptr, org.jetbrains.kotlin.backend.konan.llvm.Int64(offset / 8).llvm)) + val bitsWithPadding = load(bitsWithPaddingPtr).setUnaligned() + + val bits = shr( + shl(bitsWithPadding, suffixBitsNum), + prefixBitsNum + suffixBitsNum, signed + ) + return when { + bitsWithPaddingNum == 64 -> bits + bitsWithPaddingNum > 64 -> trunc(bits, org.jetbrains.kotlin.backend.konan.llvm.int64Type) + else -> ext(bits, org.jetbrains.kotlin.backend.konan.llvm.int64Type, signed) + } + } + + private fun FunctionGenerationContext.emitWriteBits(args: List): LLVMValueRef { + val ptr = args[0] + assert(ptr.type == int8TypePtr) + + val offset = extractConstUnsignedInt(args[1]) + val size = extractConstUnsignedInt(args[2]).toInt() + + val value = args[3] + assert(value.type == int64Type) + + val bitsType = LLVMIntTypeInContext(llvmContext, size)!! + + val prefixBitsNum = (offset % 8).toInt() + val suffixBitsNum = (8 - ((size + offset) % 8).toInt()) % 8 + + val bitsWithPaddingNum = prefixBitsNum + size + suffixBitsNum + val bitsWithPaddingType = LLVMIntTypeInContext(llvmContext, bitsWithPaddingNum)!! + + // 0011111000: + val discardBitsMask = LLVMConstShl( + LLVMConstZExt( + LLVMConstAllOnes(bitsType), // 11111 + bitsWithPaddingType + ), // 1111100000 + LLVMConstInt(bitsWithPaddingType, prefixBitsNum.toLong(), 0) + ) + + val preservedBitsMask = LLVMConstNot(discardBitsMask)!! + + val bitsWithPaddingPtr = bitcast(pointerType(bitsWithPaddingType), gep(ptr, Int64(offset / 8).llvm)) + + val bits = trunc(value, bitsType) + + val bitsToStore = if (prefixBitsNum == 0 && suffixBitsNum == 0) { + bits + } else { + val previousValue = load(bitsWithPaddingPtr).setUnaligned() + val preservedBits = and(previousValue, preservedBitsMask) + val bitsWithPadding = shl(zext(bits, bitsWithPaddingType), prefixBitsNum) + + or(bitsWithPadding, preservedBits) + } + llvm.LLVMBuildStore(builder, bitsToStore, bitsWithPaddingPtr)!!.setUnaligned() + return codegen.theUnitInstanceRef.llvm + } + + private fun FunctionGenerationContext.emitMemoryCopy(callSite: IrCall, args: List): LLVMValueRef { + println("memcpy at ${callSite}") + args.map { println(llvm2string(it)) } + TODO("Implement me") + } + + private fun FunctionGenerationContext.emitGetClassTypeInfo(callSite: IrCall): LLVMValueRef { + val typeArgument = callSite.getTypeArgument(0)!! + val typeArgumentClass = typeArgument.getClass() + return if (typeArgumentClass == null) { + // Should not happen anymore, but it is safer to handle this case. + unreachable() + kNullInt8Ptr + } else { + val typeInfo = codegen.typeInfoValue(typeArgumentClass) + LLVMConstBitCast(typeInfo, kInt8Ptr)!! + } + } + + private fun FunctionGenerationContext.emitObjCCreateSuperStruct(args: List): LLVMValueRef { + assert(args.size == 2) + val receiver = args[0] + val superClass = args[1] + + val structType = structType(kInt8Ptr, kInt8Ptr) + val ptr = alloca(structType) + store(receiver, LLVMBuildGEP(builder, ptr, cValuesOf(kImmZero, kImmZero), 2, "")!!) + store(superClass, LLVMBuildGEP(builder, ptr, cValuesOf(kImmZero, kImmOne), 2, "")!!) + return bitcast(int8TypePtr, ptr) + } + + // TODO: Find better place for these guys. + private val kImmZero = LLVMConstInt(int32Type, 0, 1)!! + private val kImmOne = LLVMConstInt(int32Type, 1, 1)!! + + private fun FunctionGenerationContext.emitGetObjCClass(callSite: IrCall): LLVMValueRef { + val typeArgument = callSite.getTypeArgument(0) + return getObjCClass(typeArgument!!.getClass()!!, environment.exceptionHandler) + } + + private fun FunctionGenerationContext.emitObjCGetMessenger(args: List, isStret: Boolean): LLVMValueRef { + val messengerNameSuffix = if (isStret) "_stret" else "" + + val functionType = functionType(int8TypePtr, true, int8TypePtr, int8TypePtr) + + val libobjc = context.standardLlvmSymbolsOrigin + val normalMessenger = context.llvm.externalFunction( + "objc_msgSend$messengerNameSuffix", + functionType, + origin = libobjc + ) + val superMessenger = context.llvm.externalFunction( + "objc_msgSendSuper$messengerNameSuffix", + functionType, + origin = libobjc + ) + + val superClass = args.single() + val messenger = LLVMBuildSelect(builder, + If = icmpEq(superClass, kNullInt8Ptr), + Then = normalMessenger, + Else = superMessenger, + Name = "" + )!! + + return bitcast(int8TypePtr, messenger) + } + + private fun FunctionGenerationContext.emitAreEqualByValue(args: List): LLVMValueRef { + val (first, second) = args + assert (first.type == second.type) { "Types are different: '${llvmtype2string(first.type)}' and '${llvmtype2string(second.type)}'" } + + return when (val typeKind = LLVMGetTypeKind(first.type)) { + llvm.LLVMTypeKind.LLVMFloatTypeKind, llvm.LLVMTypeKind.LLVMDoubleTypeKind, + LLVMTypeKind.LLVMVectorTypeKind -> { + // TODO LLVM API does not provide guarantee for LLVMIntTypeInContext availability for longer types; consider meaningful diag message instead of NPE + val integerType = LLVMIntTypeInContext(llvmContext, first.type.sizeInBits())!! + icmpEq(bitcast(integerType, first), bitcast(integerType, second)) + } + llvm.LLVMTypeKind.LLVMIntegerTypeKind, llvm.LLVMTypeKind.LLVMPointerTypeKind -> icmpEq(first, second) + else -> error(typeKind) + } + } + + private fun FunctionGenerationContext.emitIeee754Equals(args: List): LLVMValueRef { + val (first, second) = args + assert (first.type == second.type) + { "Types are different: '${llvmtype2string(first.type)}' and '${llvmtype2string(second.type)}'" } + val type = LLVMGetTypeKind(first.type) + assert (type == LLVMTypeKind.LLVMFloatTypeKind || type == LLVMTypeKind.LLVMDoubleTypeKind) + { "Should be of floating point kind, not: '${llvmtype2string(first.type)}'"} + return fcmpEq(first, second) + } + + private fun FunctionGenerationContext.emitReinterpret(callSite: IrCall, args: List) = + bitcast(callSite.llvmReturnType, args[0]) + + private fun FunctionGenerationContext.emitExtractElement(callSite: IrCall, args: List): LLVMValueRef { + val (vector, index) = args + val elementSize = LLVMSizeOfTypeInBits(codegen.llvmTargetData, callSite.llvmReturnType).toInt() + val vectorSize = LLVMSizeOfTypeInBits(codegen.llvmTargetData, vector.type).toInt() + + assert(callSite.llvmReturnType.isVectorElementType() + && vectorSize % elementSize == 0 + ) { "Invalid vector element type ${LLVMGetTypeKind(callSite.llvmReturnType)}"} + + val elementCount = vectorSize / elementSize + emitThrowIfOOB(index, Int32((elementCount)).llvm) + + val targetType = LLVMVectorType(callSite.llvmReturnType, elementCount)!! + return extractElement( + (if (targetType == vector.type) vector else bitcast(targetType, vector)), + index) + } + + private fun FunctionGenerationContext.emitNot(args: List) = + not(args[0]) + + private fun FunctionGenerationContext.emitPlus(args: List): LLVMValueRef { + val (first, second) = args + return if (first.type.isFloatingPoint()) { + fadd(first, second) + } else { + add(first, second) + } + } + + private fun FunctionGenerationContext.emitSignExtend(callSite: IrCall, args: List) = + sext(args[0], callSite.llvmReturnType) + + private fun FunctionGenerationContext.emitZeroExtend(callSite: IrCall, args: List) = + zext(args[0], callSite.llvmReturnType) + + private fun FunctionGenerationContext.emitIntTruncate(callSite: IrCall, args: List) = + trunc(args[0], callSite.llvmReturnType) + + private fun FunctionGenerationContext.emitSignedToFloat(callSite: IrCall, args: List) = + LLVMBuildSIToFP(builder, args[0], callSite.llvmReturnType, "")!! + + private fun FunctionGenerationContext.emitUnsignedToFloat(callSite: IrCall, args: List) = + LLVMBuildUIToFP(builder, args[0], callSite.llvmReturnType, "")!! + + private fun FunctionGenerationContext.emitFloatToSigned(callSite: IrCall, args: List) = + LLVMBuildFPToSI(builder, args[0], callSite.llvmReturnType, "")!! + + private fun FunctionGenerationContext.emitFloatExtend(callSite: IrCall, args: List) = + LLVMBuildFPExt(builder, args[0], callSite.llvmReturnType, "")!! + + private fun FunctionGenerationContext.emitFloatTruncate(callSite: IrCall, args: List) = + LLVMBuildFPTrunc(builder, args[0], callSite.llvmReturnType, "")!! + + private fun FunctionGenerationContext.emitShift(op: LLVMOpcode, args: List): LLVMValueRef { + val (first, second) = args + val shift = if (first.type == int64Type) { + val tmp = and(second, Int32(63).llvm) + zext(tmp, int64Type) + } else { + and(second, Int32(31).llvm) + } + return LLVMBuildBinOp(builder, op, first, shift, "")!! + } + + private fun FunctionGenerationContext.emitShl(args: List) = + emitShift(LLVMOpcode.LLVMShl, args) + + private fun FunctionGenerationContext.emitShr(args: List) = + emitShift(LLVMOpcode.LLVMAShr, args) + + private fun FunctionGenerationContext.emitUshr(args: List) = + emitShift(LLVMOpcode.LLVMLShr, args) + + private fun FunctionGenerationContext.emitAnd(args: List): LLVMValueRef { + val (first, second) = args + return and(first, second) + } + + private fun FunctionGenerationContext.emitOr(args: List): LLVMValueRef { + val (first, second) = args + return or(first, second) + } + + private fun FunctionGenerationContext.emitXor(args: List): LLVMValueRef { + val (first, second) = args + return xor(first, second) + } + + private fun FunctionGenerationContext.emitInv(args: List): LLVMValueRef { + val first = args[0] + val mask = makeConstOfType(first.type, -1) + return xor(first, mask) + } + + private fun FunctionGenerationContext.emitMinus(args: List): LLVMValueRef { + val (first, second) = args + return if (first.type.isFloatingPoint()) { + fsub(first, second) + } else { + sub(first, second) + } + } + + private fun FunctionGenerationContext.emitTimes(args: List): LLVMValueRef { + val (first, second) = args + return if (first.type.isFloatingPoint()) { + LLVMBuildFMul(builder, first, second, "") + } else { + LLVMBuildMul(builder, first, second, "") + }!! + } + + private fun FunctionGenerationContext.emitThrowIfZero(divider: LLVMValueRef) { + ifThen(icmpEq(divider, Zero(divider.type).llvm)) { + val throwArithExc = codegen.llvmFunction(context.ir.symbols.throwArithmeticException.owner) + call(throwArithExc, emptyList(), Lifetime.GLOBAL, environment.exceptionHandler) + unreachable() + } + } + + private fun FunctionGenerationContext.emitThrowIfOOB(index: LLVMValueRef, size: LLVMValueRef) { + ifThen(icmpUGe(index, size)) { + val throwIndexOutOfBoundsException = codegen.llvmFunction(context.ir.symbols.throwIndexOutOfBoundsException.owner) + call(throwIndexOutOfBoundsException, emptyList(), Lifetime.GLOBAL, environment.exceptionHandler) + unreachable() + } + } + + private fun FunctionGenerationContext.emitSignedDiv(args: List): LLVMValueRef { + val (first, second) = args + if (!second.type.isFloatingPoint()) { + emitThrowIfZero(second) + } + return if (first.type.isFloatingPoint()) { + LLVMBuildFDiv(builder, first, second, "") + } else { + LLVMBuildSDiv(builder, first, second, "") + }!! + } + + private fun FunctionGenerationContext.emitSignedRem(args: List): LLVMValueRef { + val (first, second) = args + if (!second.type.isFloatingPoint()) { + emitThrowIfZero(second) + } + return if (first.type.isFloatingPoint()) { + LLVMBuildFRem(builder, first, second, "") + } else { + LLVMBuildSRem(builder, first, second, "") + }!! + } + + private fun FunctionGenerationContext.emitUnsignedDiv(args: List): LLVMValueRef { + val (first, second) = args + emitThrowIfZero(second) + return LLVMBuildUDiv(builder, first, second, "")!! + } + + private fun FunctionGenerationContext.emitUnsignedRem(args: List): LLVMValueRef { + val (first, second) = args + emitThrowIfZero(second) + return LLVMBuildURem(builder, first, second, "")!! + } + + private fun FunctionGenerationContext.emitInc(args: List): LLVMValueRef { + val first = args[0] + val const1 = makeConstOfType(first.type, 1) + return if (first.type.isFloatingPoint()) { + fadd(first, const1) + } else { + add(first, const1) + } + } + + private fun FunctionGenerationContext.emitDec(args: List): LLVMValueRef { + val first = args[0] + val const1 = makeConstOfType(first.type, 1) + return if (first.type.isFloatingPoint()) { + fsub(first, const1) + } else { + sub(first, const1) + } + } + + private fun FunctionGenerationContext.emitUnaryPlus(args: List) = + args[0] + + private fun FunctionGenerationContext.emitUnaryMinus(args: List): LLVMValueRef { + val first = args[0] + val destTy = first.type + return if (destTy.isFloatingPoint()) { + fneg(first) + } else { + val const0 = makeConstOfType(destTy, 0) + sub(const0, first) + } + } + + private fun FunctionGenerationContext.emitCompareTo(args: List, signed: Boolean): LLVMValueRef { + val (first, second) = args + val equal = icmpEq(first, second) + val less = if (signed) icmpLt(first, second) else icmpULt(first, second) + val tmp = select(less, Int32(-1).llvm, Int32(1).llvm) + return select(equal, Int32(0).llvm, tmp) + } + + private fun FunctionGenerationContext.emitSignedCompareTo(args: List) = + emitCompareTo(args, signed = true) + + private fun FunctionGenerationContext.emitUnsignedCompareTo(args: List) = + emitCompareTo(args, signed = false) + + private fun makeConstOfType(type: LLVMTypeRef, value: Int): LLVMValueRef = when (type) { + int8Type -> Int8(value.toByte()).llvm + int16Type -> Char16(value.toChar()).llvm + int32Type -> Int32(value).llvm + int64Type -> Int64(value.toLong()).llvm + floatType -> Float32(value.toFloat()).llvm + doubleType -> Float64(value.toDouble()).llvm + else -> context.reportCompilationError("Unexpected primitive type: $type") + } +} \ No newline at end of file diff --git a/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/IrToBitcode.kt b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/IrToBitcode.kt new file mode 100644 index 00000000000..8925ef0adef --- /dev/null +++ b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/IrToBitcode.kt @@ -0,0 +1,2553 @@ +/* + * Copyright 2010-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +package org.jetbrains.kotlin.backend.konan.llvm + +import kotlinx.cinterop.* +import llvm.* +import org.jetbrains.kotlin.backend.common.ir.ir2string +import org.jetbrains.kotlin.backend.common.ir.allParameters +import org.jetbrains.kotlin.backend.common.ir.allParametersCount +import org.jetbrains.kotlin.backend.common.lower.inline.InlinerExpressionLocationHint +import org.jetbrains.kotlin.backend.konan.* +import org.jetbrains.kotlin.backend.konan.descriptors.* +import org.jetbrains.kotlin.backend.konan.ir.* +import org.jetbrains.kotlin.backend.konan.llvm.coverage.LLVMCoverageInstrumentation +import org.jetbrains.kotlin.builtins.UnsignedType +import org.jetbrains.kotlin.descriptors.Modality +import org.jetbrains.kotlin.descriptors.ModuleDescriptor +import org.jetbrains.kotlin.ir.IrElement +import org.jetbrains.kotlin.ir.IrStatement +import org.jetbrains.kotlin.ir.UNDEFINED_OFFSET +import org.jetbrains.kotlin.ir.declarations.* +import org.jetbrains.kotlin.ir.expressions.* +import org.jetbrains.kotlin.ir.symbols.IrFunctionSymbol +import org.jetbrains.kotlin.ir.types.* +import org.jetbrains.kotlin.ir.util.* +import org.jetbrains.kotlin.ir.visitors.IrElementVisitorVoid +import org.jetbrains.kotlin.ir.visitors.acceptChildrenVoid +import org.jetbrains.kotlin.ir.visitors.acceptVoid +import org.jetbrains.kotlin.konan.ForeignExceptionMode +import org.jetbrains.kotlin.konan.target.CompilerOutputKind +import org.jetbrains.kotlin.konan.target.Family +import org.jetbrains.kotlin.name.FqName +import org.jetbrains.kotlin.name.Name +import org.jetbrains.kotlin.resolve.descriptorUtil.classId +import org.jetbrains.kotlin.resolve.descriptorUtil.module + +internal enum class FieldStorageKind { + MAIN_THREAD, + SHARED, + THREAD_LOCAL +} + +internal enum class ObjectStorageKind { + PERMANENT, + THREAD_LOCAL, + SHARED +} + +// TODO: maybe unannotated singleton objects shall be accessed from main thread only as well? +internal val IrField.storageKind: FieldStorageKind get() { + // TODO: Is this correct? + val annotations = correspondingPropertySymbol?.owner?.annotations ?: annotations + return when { + annotations.hasAnnotation(KonanFqNames.threadLocal) -> FieldStorageKind.THREAD_LOCAL + !isFinal -> FieldStorageKind.MAIN_THREAD + annotations.hasAnnotation(KonanFqNames.sharedImmutable) -> FieldStorageKind.SHARED + // TODO: simplify, once IR types are fully there. + (type.classifierOrNull?.owner as? IrAnnotationContainer) + ?.annotations?.hasAnnotation(KonanFqNames.frozen) == true -> FieldStorageKind.SHARED + else -> FieldStorageKind.MAIN_THREAD + } +} + +internal fun IrClass.storageKind(context: Context): ObjectStorageKind = when { + this.annotations.hasAnnotation(KonanFqNames.threadLocal) && + context.config.threadsAreAllowed -> ObjectStorageKind.THREAD_LOCAL + this.hasConstStateAndNoSideEffects(context) -> ObjectStorageKind.PERMANENT + else -> ObjectStorageKind.SHARED +} + +val IrField.isMainOnlyNonPrimitive get() = when { + type.computePrimitiveBinaryTypeOrNull() != null -> false + else -> storageKind == FieldStorageKind.MAIN_THREAD + } + +internal class RTTIGeneratorVisitor(context: Context) : IrElementVisitorVoid { + val generator = RTTIGenerator(context) + + val kotlinObjCClassInfoGenerator = KotlinObjCClassInfoGenerator(context) + + override fun visitElement(element: IrElement) { + element.acceptChildrenVoid(this) + } + + override fun visitClass(declaration: IrClass) { + super.visitClass(declaration) + if (declaration.requiresRtti()) { + generator.generate(declaration) + } + if (declaration.isKotlinObjCClass()) { + kotlinObjCClassInfoGenerator.generate(declaration) + } + } + + fun dispose() { + generator.dispose() + } +} + +//-------------------------------------------------------------------------// + + +/** + * Defines how to generate context-dependent operations. + */ +internal interface CodeContext { + + /** + * Generates `return` [value] operation. + * + * @param value may be null iff target type is `Unit`. + */ + fun genReturn(target: IrSymbolOwner, value: LLVMValueRef?) + + fun genBreak(destination: IrBreak) + + fun genContinue(destination: IrContinue) + + val exceptionHandler: ExceptionHandler + + fun genThrow(exception: LLVMValueRef) + + val stackLocalsManager: StackLocalsManager + + /** + * Declares the variable. + * @return index of declared variable. + */ + fun genDeclareVariable(variable: IrVariable, value: LLVMValueRef?, variableLocation: VariableDebugLocation?): Int + + /** + * @return index of value declared before, or -1 if no such variable has been declared yet. + */ + fun getDeclaredValue(value: IrValueDeclaration): Int + + /** + * Generates the code to obtain a value available in this context. + * + * @return the requested value + */ + fun genGetValue(value: IrValueDeclaration): LLVMValueRef + + /** + * Returns owning function scope. + * + * @return the requested value + */ + fun functionScope(): CodeContext? + + /** + * Returns owning file scope. + * + * @return the requested value if in the file scope or null. + */ + fun fileScope(): CodeContext? + + /** + * Returns owning class scope [ClassScope]. + * + * @returns the requested value if in the class scope or null. + */ + fun classScope(): CodeContext? + + fun addResumePoint(bbLabel: LLVMBasicBlockRef): Int + + /** + * Returns owning returnable block scope [ReturnableBlockScope]. + * + * @returns the requested value if in the returnableBlockScope scope or null. + */ + fun returnableBlockScope(): CodeContext? + + /** + * Returns location information for given source location [LocationInfo]. + */ + fun location(offset: Int): LocationInfo? + + /** + * Returns [DIScopeOpaqueRef] instance for corresponding scope. + */ + fun scope(): DIScopeOpaqueRef? +} + +//-------------------------------------------------------------------------// + +internal class CodeGeneratorVisitor(val context: Context, val lifetimes: Map) : IrElementVisitorVoid { + + val codegen = CodeGenerator(context) + + // TODO: consider eliminating mutable state + private var currentCodeContext: CodeContext = TopLevelCodeContext + + private val intrinsicGeneratorEnvironment = object : IntrinsicGeneratorEnvironment { + override val codegen: CodeGenerator + get() = this@CodeGeneratorVisitor.codegen + + override val functionGenerationContext: FunctionGenerationContext + get() = this@CodeGeneratorVisitor.functionGenerationContext + + override fun calculateLifetime(element: IrElement): Lifetime = + resultLifetime(element) + + override val continuation: LLVMValueRef + get() = getContinuation() + + override val exceptionHandler: ExceptionHandler + get() = currentCodeContext.exceptionHandler + + override val stackLocalsManager: StackLocalsManager + get() = currentCodeContext.stackLocalsManager + + override fun evaluateCall(function: IrFunction, args: List, resultLifetime: Lifetime, superClass: IrClass?) = + evaluateSimpleFunctionCall(function, args, resultLifetime, superClass) + + override fun evaluateExplicitArgs(expression: IrFunctionAccessExpression): List = + this@CodeGeneratorVisitor.evaluateExplicitArgs(expression) + + override fun evaluateExpression(value: IrExpression): LLVMValueRef = + this@CodeGeneratorVisitor.evaluateExpression(value) + } + + private val intrinsicGenerator = IntrinsicGenerator(intrinsicGeneratorEnvironment) + + /** + * Fake [CodeContext] that doesn't support any operation. + * + * During function code generation [FunctionScope] should be set up. + */ + private object TopLevelCodeContext : CodeContext { + private fun unsupported(any: Any? = null): Nothing = throw UnsupportedOperationException(any?.toString() ?: "") + + override fun genReturn(target: IrSymbolOwner, value: LLVMValueRef?) = unsupported(target) + + override fun genBreak(destination: IrBreak) = unsupported() + + override fun genContinue(destination: IrContinue) = unsupported() + + override val exceptionHandler get() = unsupported() + + override fun genThrow(exception: LLVMValueRef) = unsupported() + + override val stackLocalsManager: StackLocalsManager get() = unsupported() + + override fun genDeclareVariable(variable: IrVariable, value: LLVMValueRef?, variableLocation: VariableDebugLocation?) = unsupported(variable) + + override fun getDeclaredValue(value: IrValueDeclaration) = -1 + + override fun genGetValue(value: IrValueDeclaration) = unsupported(value) + + override fun functionScope(): CodeContext? = null + + override fun fileScope(): CodeContext? = null + + override fun classScope(): CodeContext? = null + + override fun addResumePoint(bbLabel: LLVMBasicBlockRef) = unsupported(bbLabel) + + override fun returnableBlockScope(): CodeContext? = null + + override fun location(offset: Int): LocationInfo? = unsupported() + + override fun scope(): DIScopeOpaqueRef? = unsupported() + } + + /** + * The [CodeContext] which can define some operations and delegate other ones to [outerContext] + */ + private abstract class InnerScope(val outerContext: CodeContext) : CodeContext by outerContext + + /** + * Convenient [InnerScope] implementation that is bound to the [currentCodeContext]. + */ + private abstract inner class InnerScopeImpl : InnerScope(currentCodeContext) + /** + * Executes [block] with [codeContext] substituted as [currentCodeContext]. + */ + private inline fun using(codeContext: CodeContext?, block: () -> R): R { + val oldCodeContext = currentCodeContext + if (codeContext != null) { + currentCodeContext = codeContext + } + try { + return block() + } finally { + currentCodeContext = oldCodeContext + } + } + + private fun findCodeContext(entry: T, context:CodeContext?, predicate: CodeContext.(T) -> Boolean): CodeContext? { + if(context == null) + //TODO: replace `return null` with `throw NoContextFound()` ASAP. + return null + if (context.predicate(entry)) + return context + return findCodeContext(entry, (context as? InnerScope)?.outerContext, predicate) + } + + + private inline fun switchSymbolizationContextTo(symbol: IrFunctionSymbol, block: () -> R): R? { + val functionContext = findCodeContext(symbol.owner, currentCodeContext) { + val declaration = (this as? FunctionScope)?.declaration + val returnableBlock = (this as? ReturnableBlockScope)?.returnableBlock + val inlinedFunction = returnableBlock?.inlineFunctionSymbol?.owner + declaration == it || inlinedFunction == it + } ?: return null + + /** + * We can't switch context safely, only for symbolzation needs: location, scope detection. + */ + using(object: InnerScopeImpl() { + override fun location(offset: Int): LocationInfo? = functionContext.location(offset) + + override fun scope(): DIScopeOpaqueRef? = functionContext.scope() + + }) { + return block() + } + } + private fun appendCAdapters() { + context.cAdapterGenerator.generateBindings(codegen) + } + + private fun runAndProcessInitializers(module: ModuleDescriptor, f: () -> Unit) { + // TODO: collect those two in one place. + context.llvm.fileInitializers.clear() + context.llvm.fileUsesThreadLocalObjects = false + context.llvm.globalSharedObjects.clear() + + f() + + if (context.llvm.fileInitializers.isEmpty() && !context.llvm.fileUsesThreadLocalObjects && context.llvm.globalSharedObjects.isEmpty()) { + return + } + + // Create global initialization records. + val initNode = createInitNode(createInitBody()) + context.llvm.irStaticInitializers.add(IrStaticInitializer(module, createInitCtor(initNode))) + } + + //-------------------------------------------------------------------------// + + override fun visitElement(element: IrElement) { + TODO(ir2string(element)) + } + + //-------------------------------------------------------------------------// + override fun visitModuleFragment(declaration: IrModuleFragment) { + context.log{"visitModule : ${ir2string(declaration)}"} + + context.coverage.collectRegions(declaration) + + initializeCachedBoxes(context) + declaration.acceptChildrenVoid(this) + + runAndProcessInitializers(declaration.descriptor) { + // Note: it is here because it also generates some bitcode. + context.objCExport.generate(codegen) + + codegen.objCDataGenerator?.finishModule() + + context.coverage.writeRegionInfo() + appendDebugSelector() + appendLlvmUsed("llvm.used", context.llvm.usedFunctions + context.llvm.usedGlobals) + appendLlvmUsed("llvm.compiler.used", context.llvm.compilerUsedGlobals) + if (context.isNativeLibrary) { + appendCAdapters() + } + } + + appendStaticInitializers() + } + + //-------------------------------------------------------------------------// + + val kVoidFuncType = functionType(voidType) + val kNodeInitType = LLVMGetTypeByName(context.llvmModule, "struct.InitNode")!! + val kMemoryStateType = LLVMGetTypeByName(context.llvmModule, "struct.MemoryState")!! + val kInitFuncType = functionType(voidType, false, int32Type, pointerType(kMemoryStateType)) + + //-------------------------------------------------------------------------// + + val INIT_GLOBALS = 0 + val INIT_THREAD_LOCAL_GLOBALS = 1 + val DEINIT_THREAD_LOCAL_GLOBALS = 2 + val DEINIT_GLOBALS = 3 + + private fun createInitBody(): LLVMValueRef { + val initFunction = LLVMAddFunction(context.llvmModule, "", kInitFuncType)!! + LLVMSetLinkage(initFunction, LLVMLinkage.LLVMPrivateLinkage) + generateFunction(codegen, initFunction) { + using(FunctionScope(initFunction, "init_body", it)) { + val bbInit = basicBlock("init", null) + val bbLocalInit = basicBlock("local_init", null) + val bbLocalDeinit = basicBlock("local_deinit", null) + val bbGlobalDeinit = basicBlock("global_deinit", null) + val bbDefault = basicBlock("default", null) { + unreachable() + } + + switch(LLVMGetParam(initFunction, 0)!!, + listOf(Int32(INIT_GLOBALS).llvm to bbInit, + Int32(INIT_THREAD_LOCAL_GLOBALS).llvm to bbLocalInit, + Int32(DEINIT_THREAD_LOCAL_GLOBALS).llvm to bbLocalDeinit, + Int32(DEINIT_GLOBALS).llvm to bbGlobalDeinit), + bbDefault) + + // Globals initalizers may contain accesses to objects, so visit them first. + appendingTo(bbInit) { + // Bit clumsy, global init may need access to TLS, thus it has to be ready to that point. + if (context.llvm.tlsCount > 0) { + val memory = LLVMGetParam(initFunction, 1)!! + call(context.llvm.addTLSRecord, listOf(memory, context.llvm.tlsKey, + Int32(context.llvm.tlsCount).llvm)) + } + context.llvm.fileInitializers + .forEach { irField -> + if (irField.initializer?.expression !is IrConst<*>?) { + if (irField.storageKind != FieldStorageKind.THREAD_LOCAL) { + val initialization = evaluateExpression(irField.initializer!!.expression) + val address = context.llvmDeclarations.forStaticField(irField).storageAddressAccess.getAddress( + functionGenerationContext + ) + if (irField.storageKind == FieldStorageKind.SHARED) + freeze(initialization, currentCodeContext.exceptionHandler) + storeAny(initialization, address, false) + } + } + } + ret(null) + } + + appendingTo(bbLocalInit) { + if (context.llvm.tlsCount > 0) { + val memory = LLVMGetParam(initFunction, 1)!! + call(context.llvm.addTLSRecord, listOf(memory, context.llvm.tlsKey, + Int32(context.llvm.tlsCount).llvm)) + } + context.llvm.fileInitializers + .forEach { irField -> + if (irField.initializer != null && irField.storageKind == FieldStorageKind.THREAD_LOCAL) { + val initialization = evaluateExpression(irField.initializer!!.expression) + val address = context.llvmDeclarations.forStaticField(irField).storageAddressAccess.getAddress( + functionGenerationContext + ) + storeAny(initialization, address, false) + } + } + ret(null) + } + + appendingTo(bbLocalDeinit) { + if (context.llvm.tlsCount > 0) { + val memory = LLVMGetParam(initFunction, 1)!! + call(context.llvm.clearTLSRecord, listOf(memory, context.llvm.tlsKey)) + } + ret(null) + } + + appendingTo(bbGlobalDeinit) { + context.llvm.fileInitializers + // Only if a subject for memory management. + .forEach {irField -> + if (irField.type.binaryTypeIsReference() && irField.storageKind != FieldStorageKind.THREAD_LOCAL) { + val address = context.llvmDeclarations.forStaticField(irField).storageAddressAccess.getAddress( + functionGenerationContext + ) + storeHeapRef(codegen.kNullObjHeaderPtr, address) + } + } + context.llvm.globalSharedObjects.forEach { address -> + storeHeapRef(codegen.kNullObjHeaderPtr, address) + } + ret(null) + } + } + } + return initFunction + } + + //-------------------------------------------------------------------------// + // Creates static struct InitNode $nodeName = {$initName, NULL}; + + private fun createInitNode(initFunction: LLVMValueRef): LLVMValueRef { + val nextInitNode = LLVMConstNull(pointerType(kNodeInitType)) + val argList = cValuesOf(initFunction, nextInitNode) + // Create static object of class InitNode. + val initNode = LLVMConstNamedStruct(kNodeInitType, argList, 2)!! + // Create global variable with init record data. + return context.llvm.staticData.placeGlobal( + "init_node", constPointer(initNode), isExported = false).llvmGlobal + } + + //-------------------------------------------------------------------------// + + private fun createInitCtor(initNodePtr: LLVMValueRef): LLVMValueRef { + val ctorFunction = LLVMAddFunction(context.llvmModule, "", kVoidFuncType)!! + LLVMSetLinkage(ctorFunction, LLVMLinkage.LLVMPrivateLinkage) + generateFunction(codegen, ctorFunction) { + call(context.llvm.appendToInitalizersTail, listOf(initNodePtr)) + ret(null) + } + return ctorFunction + } + + //-------------------------------------------------------------------------// + + override fun visitFile(declaration: IrFile) { + @Suppress("UNCHECKED_CAST") + using(FileScope(declaration)) { + runAndProcessInitializers(declaration.packageFragmentDescriptor.module) { + declaration.acceptChildrenVoid(this) + } + } + } + + //-------------------------------------------------------------------------// + + private inner class LoopScope(val loop: IrLoop) : InnerScopeImpl() { + val loopExit = functionGenerationContext.basicBlock("loop_exit", loop.endLocation) + val loopCheck = functionGenerationContext.basicBlock("loop_check", loop.condition.startLocation) + + override fun genBreak(destination: IrBreak) { + if (destination.loop == loop) + functionGenerationContext.br(loopExit) + else + super.genBreak(destination) + } + + override fun genContinue(destination: IrContinue) { + if (destination.loop == loop) + functionGenerationContext.br(loopCheck) + else + super.genContinue(destination) + } + + override val stackLocalsManager: StackLocalsManager = + object : StackLocalsManager by functionGenerationContext.stackLocalsManager { } + } + + //-------------------------------------------------------------------------// + + fun evaluateBreak(destination: IrBreak): LLVMValueRef { + currentCodeContext.genBreak(destination) + return codegen.kNothingFakeValue + } + + //-------------------------------------------------------------------------// + + fun evaluateContinue(destination: IrContinue): LLVMValueRef { + currentCodeContext.genContinue(destination) + return codegen.kNothingFakeValue + } + + //-------------------------------------------------------------------------// + + override fun visitConstructor(declaration: IrConstructor) { + context.log{"visitConstructor : ${ir2string(declaration)}"} + if (declaration.constructedClass.isInlined()) { + // Do not generate any ctors for value types. + return + } + + if (declaration.isObjCConstructor) { + // Do not generate any ctors for external Objective-C classes. + return + } + + visitFunction(declaration) + } + + //-------------------------------------------------------------------------// + + override fun visitAnonymousInitializer(declaration: IrAnonymousInitializer) { + context.log{"visitAnonymousInitializer : ${ir2string(declaration)}"} + } + + //-------------------------------------------------------------------------// + + /** + * The scope of variable visibility. + */ + private inner class VariableScope : InnerScopeImpl() { + + override fun genDeclareVariable(variable: IrVariable, value: LLVMValueRef?, variableLocation: VariableDebugLocation?): Int { + return functionGenerationContext.vars.createVariable(variable, value, variableLocation) + } + + override fun getDeclaredValue(value: IrValueDeclaration): Int { + val index = functionGenerationContext.vars.indexOf(value) + return if (index < 0) super.getDeclaredValue(value) else index + } + + override fun genGetValue(value: IrValueDeclaration): LLVMValueRef { + val index = functionGenerationContext.vars.indexOf(value) + if (index < 0) { + return super.genGetValue(value) + } else { + return functionGenerationContext.vars.load(index) + } + } + } + + /** + * The scope of parameter visibility. + */ + private open inner class ParameterScope( + function: IrFunction?, + private val functionGenerationContext: FunctionGenerationContext): InnerScopeImpl() { + + val parameters = bindParameters(function) + + init { + if (function != null) { + parameters.forEach{ + val parameter = it.key + val local = functionGenerationContext.vars.createParameter( + parameter, debugInfoIfNeeded(function, parameter)) + functionGenerationContext.mapParameterForDebug(local, it.value) + } + } + } + + override fun genGetValue(value: IrValueDeclaration): LLVMValueRef { + val index = functionGenerationContext.vars.indexOf(value) + if (index < 0) { + return super.genGetValue(value) + } else { + return functionGenerationContext.vars.load(index) + } + } + } + + /** + * The [CodeContext] enclosing the entire function body. + */ + private inner class FunctionScope(val declaration: IrFunction?, val functionGenerationContext: FunctionGenerationContext) : InnerScopeImpl() { + + constructor(llvmFunction:LLVMValueRef, name:String, functionGenerationContext: FunctionGenerationContext): + this(null, functionGenerationContext) { + this.llvmFunction = llvmFunction + this.name = name + } + + var llvmFunction: LLVMValueRef? = declaration?.let{ + codegen.llvmFunction(it) + } + + val coverageInstrumentation: LLVMCoverageInstrumentation? = + context.coverage.tryGetInstrumentation(declaration) { function, args -> functionGenerationContext.call(function, args) } + + private var name:String? = declaration?.name?.asString() + + override fun genReturn(target: IrSymbolOwner, value: LLVMValueRef?) { + if (declaration == null || target == declaration) { + if ((target as IrFunction).returnsUnit()) { + functionGenerationContext.ret(null) + } else { + functionGenerationContext.ret(value!!) + } + } else { + super.genReturn(target, value) + } + } + + override val exceptionHandler get() = ExceptionHandler.Caller + + override fun genThrow(exception: LLVMValueRef) { + val objHeaderPtr = functionGenerationContext.bitcast(codegen.kObjHeaderPtr, exception) + val args = listOf(objHeaderPtr) + + functionGenerationContext.call( + context.llvm.throwExceptionFunction, args, Lifetime.IRRELEVANT, this.exceptionHandler + ) + functionGenerationContext.unreachable() + } + + override val stackLocalsManager get() = functionGenerationContext.stackLocalsManager + + override fun functionScope(): CodeContext = this + + + private val scope by lazy { + if (!context.shouldContainLocationDebugInfo()) + return@lazy null + declaration?.scope() ?: llvmFunction!!.scope(0, subroutineType(context, codegen.llvmTargetData, listOf(context.irBuiltIns.intType))) + } + + private val fileScope = (fileScope() as? FileScope) + override fun location(offset: Int) = scope?.let { scope -> fileScope?.let{LocationInfo(scope, it.file.fileEntry.line(offset), it.file.fileEntry.column(offset)) } } + + override fun scope() = scope + } + + private val functionGenerationContext + get() = (currentCodeContext.functionScope() as FunctionScope).functionGenerationContext + /** + * Binds LLVM function parameters to IR parameter descriptors. + */ + private fun bindParameters(function: IrFunction?): Map { + if (function == null) return emptyMap() + return function.allParameters.mapIndexed { i, irParameter -> + val parameter = codegen.param(function, i) + assert(codegen.getLLVMType(irParameter.type) == parameter.type) + irParameter to parameter + }.toMap() + } + + override fun visitFunction(declaration: IrFunction) { + context.log{"visitFunction : ${ir2string(declaration)}"} + + val body = declaration.body + + if ((declaration as? IrSimpleFunction)?.modality == Modality.ABSTRACT + || declaration.isExternal + || body == null) + return + val isNotInlinedLambda = declaration.origin == IrDeclarationOrigin.LOCAL_FUNCTION_FOR_LAMBDA + val file = ((declaration as? IrSimpleFunction)?.attributeOwnerId as? IrSimpleFunction)?.file.takeIf { + it ?: return@takeIf false + (currentCodeContext.fileScope() as FileScope).file != it && isNotInlinedLambda + } + val scope = file?.let { + FileScope(it) + } + using(scope) { + generateFunction(codegen, declaration, + declaration.location(start = true), + declaration.location(start = false)) { + using(FunctionScope(declaration, it)) { + val parameterScope = ParameterScope(declaration, functionGenerationContext) + using(parameterScope) usingParameterScope@{ + using(VariableScope()) usingVariableScope@{ + recordCoverage(body) + if (declaration.isReifiedInline) { + callDirect(context.ir.symbols.throwIllegalStateExceptionWithMessage.owner, + listOf(context.llvm.staticData.kotlinStringLiteral( + "unsupported call of reified inlined function `${declaration.fqNameForIrSerialization}`").llvm), + Lifetime.IRRELEVANT) + return@usingVariableScope + } + when (body) { + is IrBlockBody -> body.statements.forEach { generateStatement(it) } + is IrExpressionBody -> error("IrExpressionBody should've been lowered") + is IrSyntheticBody -> throw AssertionError("Synthetic body ${body.kind} has not been lowered") + else -> TODO(ir2string(body)) + } + } + } + } + } + } + + + if (declaration.retainAnnotation(context.config.target)) { + context.llvm.usedFunctions.add(codegen.llvmFunction(declaration)) + } + + if (context.shouldVerifyBitCode()) + verifyModule(context.llvmModule!!, + "${declaration.descriptor.containingDeclaration}::${ir2string(declaration)}") + } + + private fun IrFunction.location(start: Boolean) = + if (context.shouldContainLocationDebugInfo() && startOffset != UNDEFINED_OFFSET) LocationInfo( + scope = scope()!!, + line = if (start) startLine() else endLine(), + column = if (start) startColumn() else endColumn()) + else null + + //-------------------------------------------------------------------------// + + override fun visitClass(declaration: IrClass) { + context.log{"visitClass : ${ir2string(declaration)}"} + + if (declaration.isNonGeneratedAnnotation() || !declaration.requiresCodeGeneration()) { + // For non-generated annotation classes generate only nested classes. + declaration.declarations + .filterIsInstance() + .forEach { it.acceptVoid(this) } + return + } + using(ClassScope(declaration)) { + declaration.declarations.forEach { + it.acceptVoid(this) + } + } + + if (declaration.kind.isSingleton && !declaration.isUnit()) { + val singleton = context.llvmDeclarations.forSingleton(declaration) + val access = singleton.instanceStorage + if (access is GlobalAddressAccess) { + // Global objects are kept in a data segment and can be accessed by any module (if exported) and also + // they need to be initialized statically. + LLVMSetInitializer(access.getAddress(null), if (declaration.storageKind(context) == ObjectStorageKind.PERMANENT) + context.llvm.staticData.createConstKotlinObject(declaration, + *computeFields(declaration)).llvm else codegen.kNullObjHeaderPtr) + } else { + // Thread local objects are kept in a special map, so they need a getter function to be accessible + // by other modules. + val isObjCCompanion = declaration.isCompanion && declaration.parentAsClass.isObjCClass() + // If can be exported and can be instantiated. + if (declaration.isExported() && !isObjCCompanion && + declaration.constructors.singleOrNull() { it.valueParameters.size == 0 } != null) { + val valueGetterName = declaration.threadLocalObjectStorageGetterSymbolName + generateFunction(codegen, + functionType(codegen.kObjHeaderPtrPtr, false), + valueGetterName) { + val value = access.getAddress(this) + ret(value) + } + // Getter uses TLS object, so need to ensure that this file's (de)initializer function + // inits and deinits TLS. + context.llvm.fileUsesThreadLocalObjects = true + } + } + } + } + + private fun computeFields(declaration: IrClass): Array { + val fields = context.getLayoutBuilder(declaration).fields + return Array(fields.size) { index -> + val initializer = fields[index].initializer!!.expression as IrConst<*> + constValue(evaluateConst(initializer)) + } + } + + override fun visitProperty(declaration: IrProperty) { + declaration.getter?.acceptVoid(this) + declaration.setter?.acceptVoid(this) + declaration.backingField?.acceptVoid(this) + } + + //-------------------------------------------------------------------------// + + override fun visitField(declaration: IrField) { + context.log{"visitField : ${ir2string(declaration)}"} + debugFieldDeclaration(declaration) + if (context.needGlobalInit(declaration)) { + val type = codegen.getLLVMType(declaration.type) + val globalPropertyAccess = context.llvmDeclarations.forStaticField(declaration).storageAddressAccess + val initializer = declaration.initializer?.expression as? IrConst<*> + val globalProperty = (globalPropertyAccess as? GlobalAddressAccess)?.getAddress(null) + if (globalProperty != null) { + LLVMSetInitializer(globalProperty, if (initializer != null) + evaluateExpression(initializer) else LLVMConstNull(type)) + // (Cannot do this before the global is initialized). + LLVMSetLinkage(globalProperty, LLVMLinkage.LLVMInternalLinkage) + } + context.llvm.fileInitializers.add(declaration) + } + } + + private fun recordCoverage(irElement: IrElement) { + val scope = currentCodeContext.functionScope() + if (scope is FunctionScope) { + scope.coverageInstrumentation?.instrumentIrElement(irElement) + } + } + + //-------------------------------------------------------------------------// + + private fun evaluateExpression(value: IrExpression): LLVMValueRef { + updateBuilderDebugLocation(value) + recordCoverage(value) + when (value) { + is IrTypeOperatorCall -> return evaluateTypeOperator (value) + is IrCall -> return evaluateCall (value) + is IrDelegatingConstructorCall -> + return evaluateCall (value) + is IrConstructorCall -> return evaluateCall (value) + is IrInstanceInitializerCall -> + return evaluateInstanceInitializerCall(value) + is IrGetValue -> return evaluateGetValue (value) + is IrSetValue -> return evaluateSetValue (value) + is IrGetField -> return evaluateGetField (value) + is IrSetField -> return evaluateSetField (value) + is IrConst<*> -> return evaluateConst (value) + is IrReturn -> return evaluateReturn (value) + is IrWhen -> return evaluateWhen (value) + is IrThrow -> return evaluateThrow (value) + is IrTry -> return evaluateTry (value) + is IrReturnableBlock -> return evaluateReturnableBlock (value) + is IrContainerExpression -> return evaluateContainerExpression (value) + is IrWhileLoop -> return evaluateWhileLoop (value) + is IrDoWhileLoop -> return evaluateDoWhileLoop (value) + is IrVararg -> return evaluateVararg (value) + is IrBreak -> return evaluateBreak (value) + is IrContinue -> return evaluateContinue (value) + is IrGetObjectValue -> return evaluateGetObjectValue (value) + is IrFunctionReference -> return evaluateFunctionReference (value) + is IrSuspendableExpression -> + return evaluateSuspendableExpression (value) + is IrSuspensionPoint -> return evaluateSuspensionPoint (value) + is IrClassReference -> return evaluateClassReference (value) + else -> { + TODO(ir2string(value)) + } + } + } + + private fun generateStatement(statement: IrStatement) { + when (statement) { + is IrExpression -> evaluateExpression(statement) + is IrVariable -> generateVariable(statement) + else -> TODO(ir2string(statement)) + } + } + + private fun IrStatement.generate() = generateStatement(this) + + //-------------------------------------------------------------------------// + + private fun evaluateGetObjectValue(value: IrGetObjectValue): LLVMValueRef = + functionGenerationContext.getObjectValue( + value.symbol.owner, + currentCodeContext.exceptionHandler, + value.startLocation, + value.endLocation + ) + + + //-------------------------------------------------------------------------// + + private fun evaluateExpressionAndJump(expression: IrExpression, destination: ContinuationBlock) { + val result = evaluateExpression(expression) + + // It is possible to check here whether the generated code has the normal continuation path + // and do not generate any jump if not; + // however such optimization can lead to phi functions with zero entries, which is not allowed by LLVM; + // TODO: find the better solution. + + jump(destination, result) + } + + //-------------------------------------------------------------------------// + + /** + * Represents the basic block which may expect a value: + * when generating a [jump] to this block, one should provide the value. + * Inside the block that value is accessible as [valuePhi]. + * + * This class is designed to be used to generate Kotlin expressions that have a value and require branching. + * + * [valuePhi] may be `null`, which would mean `Unit` value is passed. + */ + private data class ContinuationBlock(val block: LLVMBasicBlockRef, val valuePhi: LLVMValueRef?) + + private val ContinuationBlock.value: LLVMValueRef + get() = this.valuePhi ?: codegen.theUnitInstanceRef.llvm + + /** + * Jumps to [target] passing [value]. + */ + private fun jump(target: ContinuationBlock, value: LLVMValueRef?) { + val entry = target.block + functionGenerationContext.br(entry) + if (target.valuePhi != null) { + functionGenerationContext.assignPhis(target.valuePhi to value!!) + } + } + + /** + * Creates new [ContinuationBlock] that receives the value of given Kotlin type + * and generates [code] starting from its beginning. + */ + private fun continuationBlock( + type: IrType, locationInfo: LocationInfo?, code: (ContinuationBlock) -> Unit = {}): ContinuationBlock { + + val entry = functionGenerationContext.basicBlock("continuation_block", locationInfo) + + functionGenerationContext.appendingTo(entry) { + val valuePhi = if (type.isUnit()) { + null + } else { + functionGenerationContext.phi(codegen.getLLVMType(type)) + } + + val result = ContinuationBlock(entry, valuePhi) + code(result) + return result + } + } + + //-------------------------------------------------------------------------// + + private fun evaluateVararg(value: IrVararg): LLVMValueRef { + val elements = value.elements.map { + if (it is IrExpression) { + val mapped = evaluateExpression(it) + if (mapped.isConst) { + return@map mapped + } + } + + throw IllegalStateException("IrVararg neither was lowered nor can be statically evaluated") + } + + val arrayClass = value.type.getClass()!! + + // Note: even if all elements are const, they aren't guaranteed to be statically initialized. + // E.g. an element may be a pointer to lazy-initialized object (aka singleton). + // However it is guaranteed that all elements are already initialized at this point. + return codegen.staticData.createConstKotlinArray(arrayClass, elements) + } + + //-------------------------------------------------------------------------// + + private fun evaluateThrow(expression: IrThrow): LLVMValueRef { + val exception = evaluateExpression(expression.value) + currentCodeContext.genThrow(exception) + return codegen.kNothingFakeValue + } + + //-------------------------------------------------------------------------// + + /** + * The [CodeContext] that catches exceptions. + */ + private inner abstract class CatchingScope : InnerScopeImpl() { + + /** + * The LLVM `landingpad` such that if invoked function throws an exception, + * then this exception is passed to [handler]. + */ + private val landingpad: LLVMBasicBlockRef by lazy { + using(outerContext) { + functionGenerationContext.basicBlock("landingpad", endLocationInfoFromScope()) { + genLandingpad() + } + } + } + + /** + * The Kotlin exception handler, i.e. the [ContinuationBlock] which gets started + * when the exception is caught, receiving this exception as its value. + */ + private val handler by lazy { + using(outerContext) { + continuationBlock(context.ir.symbols.throwable.owner.defaultType, endLocationInfoFromScope()) { + genHandler(it.value) + } + } + } + + private fun endLocationInfoFromScope(): LocationInfo? { + val functionScope = currentCodeContext.functionScope() + val irFunction = functionScope?.let { + (functionScope as FunctionScope).declaration + } + return irFunction?.endLocation + } + + private fun jumpToHandler(exception: LLVMValueRef) { + jump(this.handler, exception) + } + + /** + * Generates the LLVM `landingpad` that catches C++ exception with type `KotlinException`, + * unwraps the Kotlin exception object and jumps to [handler]. + * + * This method generates nearly the same code as `clang++` does for the following: + * ``` + * catch (KotlinException& e) { + * KRef exception = e.exception_; + * return exception; + * } + * ``` + * except that our code doesn't check exception `typeid`. + * + * TODO: why does `clang++` check `typeid` even if there is only one catch clause? + */ + private fun genLandingpad() { + with(functionGenerationContext) { + val exceptionPtr = catchKotlinException() + jumpToHandler(exceptionPtr) + } + } + + override val exceptionHandler: ExceptionHandler get() = object : ExceptionHandler.Local() { + override val unwind get() = landingpad + } + + override fun genThrow(exception: LLVMValueRef) { + jumpToHandler(exception) + } + + protected abstract fun genHandler(exception: LLVMValueRef) + } + + /** + * The [CatchingScope] that handles exceptions using Kotlin `catch` clauses. + * + * @param success the block to be used when the exception is successfully handled; + * expects `catch` expression result as its value. + */ + private inner class CatchScope(private val catches: List, + private val success: ContinuationBlock) : CatchingScope() { + + override fun genHandler(exception: LLVMValueRef) { + + for (catch in catches) { + fun genCatchBlock() { + using(VariableScope()) { + currentCodeContext.genDeclareVariable(catch.catchParameter, exception, null) + evaluateExpressionAndJump(catch.result, success) + } + } + + if (catch.catchParameter.descriptor.type == context.builtIns.throwable.defaultType) { + genCatchBlock() + return // Remaining catch clauses are unreachable. + } else { + val isInstance = genInstanceOf(exception, catch.catchParameter.type.getClass()!!) + val body = functionGenerationContext.basicBlock("catch", catch.startLocation) + val nextCheck = functionGenerationContext.basicBlock("catchCheck", catch.endLocation) + functionGenerationContext.condBr(isInstance, body, nextCheck) + + functionGenerationContext.appendingTo(body) { + genCatchBlock() + } + + functionGenerationContext.positionAtEnd(nextCheck) + } + } + // rethrow the exception if no clause can handle it. + outerContext.genThrow(exception) + } + } + + private fun evaluateTry(expression: IrTry): LLVMValueRef { + // TODO: does basic block order influence machine code order? + // If so, consider reordering blocks to reduce exception tables size. + + assert (expression.finallyExpression == null, { "All finally blocks should've been lowered" }) + + val continuation = continuationBlock(expression.type, expression.endLocation) + + val catchScope = if (expression.catches.isEmpty()) + null + else + CatchScope(expression.catches, continuation) + using(catchScope) { + evaluateExpressionAndJump(expression.tryResult, continuation) + } + functionGenerationContext.positionAtEnd(continuation.block) + + return continuation.value + } + + //-------------------------------------------------------------------------// + /* FIXME. Fix "when" type in frontend. + * For the following code: + * fun foo(x: Int) { + * when (x) { + * 0 -> 0 + * } + * } + * we cannot determine if the result of when is assigned or not. + */ + private inner class WhenEmittingContext(val expression: IrWhen) { + val needsPhi = isUnconditional(expression.branches.last()) && !expression.type.isUnit() + val llvmType = codegen.getLLVMType(expression.type) + + val bbExit = lazy { functionGenerationContext.basicBlock("when_exit", expression.endLocation) } + + val resultPhi = lazy { + functionGenerationContext.appendingTo(bbExit.value) { + functionGenerationContext.phi(llvmType) + } + } + } + + private fun evaluateWhen(expression: IrWhen): LLVMValueRef { + context.log{"evaluateWhen : ${ir2string(expression)}"} + + val whenEmittingContext = WhenEmittingContext(expression) + + expression.branches.forEach { + val bbNext = if (it == expression.branches.last()) + null + else + functionGenerationContext.basicBlock("when_next", it.startLocation, it.endLocation) + generateWhenCase(whenEmittingContext, it, bbNext) + } + + if (whenEmittingContext.bbExit.isInitialized()) + functionGenerationContext.positionAtEnd(whenEmittingContext.bbExit.value) + + return when { + expression.type.isUnit() -> functionGenerationContext.theUnitInstanceRef.llvm + expression.type.isNothing() -> functionGenerationContext.kNothingFakeValue + whenEmittingContext.resultPhi.isInitialized() -> whenEmittingContext.resultPhi.value + else -> LLVMGetUndef(whenEmittingContext.llvmType)!! + } + } + + private fun generateWhenCase(whenEmittingContext: WhenEmittingContext, branch: IrBranch, bbNext: LLVMBasicBlockRef?) { + val brResult = if (isUnconditional(branch)) + evaluateExpression(branch.result) + else { + val bbCase = functionGenerationContext.basicBlock("when_case", branch.startLocation, branch.endLocation) + val condition = evaluateExpression(branch.condition) + functionGenerationContext.condBr(condition, bbCase, bbNext ?: whenEmittingContext.bbExit.value) + functionGenerationContext.positionAtEnd(bbCase) + evaluateExpression(branch.result) + } + if (!functionGenerationContext.isAfterTerminator()) { + if (whenEmittingContext.needsPhi) + functionGenerationContext.assignPhis(whenEmittingContext.resultPhi.value to brResult) + functionGenerationContext.br(whenEmittingContext.bbExit.value) + } + if (bbNext != null) + functionGenerationContext.positionAtEnd(bbNext) + } + + //-------------------------------------------------------------------------// + // Checks if the branch is unconditional + + private fun isUnconditional(branch: IrBranch): Boolean = + branch.condition is IrConst<*> // If branch condition is constant. + && (branch.condition as IrConst<*>).value as Boolean // If condition is "true" + + //-------------------------------------------------------------------------// + + private fun evaluateWhileLoop(loop: IrWhileLoop): LLVMValueRef { + val loopScope = LoopScope(loop) + using(loopScope) { + val loopBody = functionGenerationContext.basicBlock("while_loop", loop.startLocation) + functionGenerationContext.br(loopScope.loopCheck) + + functionGenerationContext.positionAtEnd(loopScope.loopCheck) + val condition = evaluateExpression(loop.condition) + functionGenerationContext.condBr(condition, loopBody, loopScope.loopExit) + + functionGenerationContext.positionAtEnd(loopBody) + loop.body?.generate() + + functionGenerationContext.br(loopScope.loopCheck) + functionGenerationContext.positionAtEnd(loopScope.loopExit) + + } + + assert(loop.type.isUnit()) + return functionGenerationContext.theUnitInstanceRef.llvm + } + + //-------------------------------------------------------------------------// + + private fun evaluateDoWhileLoop(loop: IrDoWhileLoop): LLVMValueRef { + val loopScope = LoopScope(loop) + using(loopScope) { + val loopBody = functionGenerationContext.basicBlock("do_while_loop", loop.body?.startLocation ?: loop.startLocation) + functionGenerationContext.br(loopBody) + + functionGenerationContext.positionAtEnd(loopBody) + loop.body?.generate() + functionGenerationContext.br(loopScope.loopCheck) + + functionGenerationContext.positionAtEnd(loopScope.loopCheck) + val condition = evaluateExpression(loop.condition) + functionGenerationContext.condBr(condition, loopBody, loopScope.loopExit) + + functionGenerationContext.positionAtEnd(loopScope.loopExit) + } + + assert(loop.type.isUnit()) + return functionGenerationContext.theUnitInstanceRef.llvm + } + + //-------------------------------------------------------------------------// + + private fun evaluateGetValue(value: IrGetValue): LLVMValueRef { + context.log{"evaluateGetValue : ${ir2string(value)}"} + return currentCodeContext.genGetValue(value.symbol.owner) + } + + //-------------------------------------------------------------------------// + + private fun evaluateSetValue(value: IrSetValue): LLVMValueRef { + context.log{"evaluateSetValue : ${ir2string(value)}"} + val result = evaluateExpression(value.value) + val variable = currentCodeContext.getDeclaredValue(value.symbol.owner) + functionGenerationContext.vars.store(result, variable) + assert(value.type.isUnit()) + return functionGenerationContext.theUnitInstanceRef.llvm + } + + //-------------------------------------------------------------------------// + private fun debugInfoIfNeeded(function: IrFunction?, element: IrElement): VariableDebugLocation? { + if (function == null || !element.needDebugInfo(context) || currentCodeContext.scope() == null) return null + val locationInfo = element.startLocation ?: return null + val location = codegen.generateLocationInfo(locationInfo) + val file = (currentCodeContext.fileScope() as FileScope).file.file() + return when (element) { + is IrVariable -> if (shouldGenerateDebugInfo(element)) debugInfoLocalVariableLocation( + builder = context.debugInfo.builder, + functionScope = locationInfo.scope, + diType = element.type.diType(context, codegen.llvmTargetData), + name = element.debugNameConversion(), + file = file, + line = locationInfo.line, + location = location) + else null + is IrValueParameter -> debugInfoParameterLocation( + builder = context.debugInfo.builder, + functionScope = locationInfo.scope, + diType = element.type.diType(context, codegen.llvmTargetData), + name = element.debugNameConversion(), + argNo = function.allParameters.indexOf(element) + 1, + file = file, + line = locationInfo.line, + location = location) + else -> throw Error("Unsupported element type: ${ir2string(element)}") + } + } + + private fun shouldGenerateDebugInfo(variable: IrVariable) = when(variable.origin) { + IrDeclarationOrigin.FOR_LOOP_IMPLICIT_VARIABLE, + IrDeclarationOrigin.FOR_LOOP_ITERATOR, + IrDeclarationOrigin.IR_TEMPORARY_VARIABLE -> false + else -> true + } + + private fun generateVariable(variable: IrVariable) { + context.log{"generateVariable : ${ir2string(variable)}"} + val value = variable.initializer?.let { + val callSiteOrigin = (it as? IrBlock)?.origin as? InlinerExpressionLocationHint + val inlineAtFunctionSymbol = callSiteOrigin?.inlineAtSymbol as? IrFunctionSymbol + inlineAtFunctionSymbol?.run { + switchSymbolizationContextTo(inlineAtFunctionSymbol) { + evaluateExpression(it) + } + } ?: evaluateExpression(it) + } + currentCodeContext.genDeclareVariable( + variable, value, debugInfoIfNeeded( + (currentCodeContext.functionScope() as FunctionScope).declaration, variable)) + } + + //-------------------------------------------------------------------------// + + private fun evaluateTypeOperator(value: IrTypeOperatorCall): LLVMValueRef { + return when (value.operator) { + IrTypeOperator.CAST -> evaluateCast(value) + IrTypeOperator.IMPLICIT_INTEGER_COERCION -> evaluateIntegerCoercion(value) + IrTypeOperator.IMPLICIT_CAST -> evaluateExpression(value.argument) + IrTypeOperator.IMPLICIT_NOTNULL -> TODO(ir2string(value)) + IrTypeOperator.IMPLICIT_COERCION_TO_UNIT -> { + evaluateExpression(value.argument) + functionGenerationContext.theUnitInstanceRef.llvm + } + IrTypeOperator.SAFE_CAST -> throw IllegalStateException("safe cast wasn't lowered") + IrTypeOperator.INSTANCEOF -> evaluateInstanceOf(value) + IrTypeOperator.NOT_INSTANCEOF -> evaluateNotInstanceOf(value) + IrTypeOperator.SAM_CONVERSION -> TODO(ir2string(value)) + IrTypeOperator.IMPLICIT_DYNAMIC_CAST -> TODO(ir2string(value)) + IrTypeOperator.REINTERPRET_CAST -> TODO(ir2string(value)) + } + } + + //-------------------------------------------------------------------------// + + private fun IrType.isPrimitiveInteger(): Boolean { + return this.isPrimitiveType() && + !this.isBoolean() && + !this.isFloat() && + !this.isDouble() && + !this.isChar() + } + + private fun IrType.isUnsignedInteger(): Boolean = + this is IrSimpleType && !this.hasQuestionMark && + UnsignedType.values().any { it.classId == this.getClass()?.descriptor?.classId } + + private fun evaluateIntegerCoercion(value: IrTypeOperatorCall): LLVMValueRef { + context.log{"evaluateIntegerCoercion : ${ir2string(value)}"} + val type = value.typeOperand + assert(type.isPrimitiveInteger() || type.isUnsignedInteger()) + val result = evaluateExpression(value.argument) + assert(value.argument.type.isInt()) + val llvmSrcType = codegen.getLLVMType(value.argument.type) + val llvmDstType = codegen.getLLVMType(type) + val srcWidth = LLVMGetIntTypeWidth(llvmSrcType) + val dstWidth = LLVMGetIntTypeWidth(llvmDstType) + return when { + srcWidth == dstWidth -> result + srcWidth > dstWidth -> LLVMBuildTrunc(functionGenerationContext.builder, result, llvmDstType, "")!! + else /* srcWidth < dstWidth */ -> LLVMBuildSExt(functionGenerationContext.builder, result, llvmDstType, "")!! + } + } + + //-------------------------------------------------------------------------// + // table of conversion with llvm for primitive types + // to be used in replacement fo primitive.toX() calls with + // translator intrinsics. + // | byte short int long float double + //------------|---------------------------------------------------- + // byte | x sext sext sext sitofp sitofp + // short | trunc x sext sext sitofp sitofp + // int | trunc trunc x sext sitofp sitofp + // long | trunc trunc trunc x sitofp sitofp + // float | fptosi fptosi fptosi fptosi x fpext + // double | fptosi fptosi fptosi fptosi fptrunc x + + private fun evaluateCast(value: IrTypeOperatorCall): LLVMValueRef { + context.log{"evaluateCast : ${ir2string(value)}"} + val dstClass = value.typeOperand.getClass()!! + + val srcArg = evaluateExpression(value.argument) + assert(srcArg.type == codegen.kObjHeaderPtr) + + with(functionGenerationContext) { + ifThen(not(genInstanceOf(srcArg, dstClass))) { + if (dstClass.defaultType.isObjCObjectType()) { + callDirect( + context.ir.symbols.throwTypeCastException.owner, + emptyList(), + Lifetime.GLOBAL + ) + } else { + val dstTypeInfo = functionGenerationContext.bitcast(kInt8Ptr, codegen.typeInfoValue(dstClass)) + callDirect( + context.ir.symbols.throwClassCastException.owner, + listOf(srcArg, dstTypeInfo), + Lifetime.GLOBAL + ) + } + } + } + return srcArg + } + + //-------------------------------------------------------------------------// + + private fun evaluateInstanceOf(value: IrTypeOperatorCall): LLVMValueRef { + context.log{"evaluateInstanceOf : ${ir2string(value)}"} + + val type = value.typeOperand + val srcArg = evaluateExpression(value.argument) // Evaluate src expression. + + val bbExit = functionGenerationContext.basicBlock("instance_of_exit", value.startLocation) + val bbInstanceOf = functionGenerationContext.basicBlock("instance_of_notnull", value.startLocation) + val bbNull = functionGenerationContext.basicBlock("instance_of_null", value.startLocation) + + val condition = functionGenerationContext.icmpEq(srcArg, codegen.kNullObjHeaderPtr) + functionGenerationContext.condBr(condition, bbNull, bbInstanceOf) + + functionGenerationContext.positionAtEnd(bbNull) + val resultNull = if (type.containsNull()) kTrue else kFalse + functionGenerationContext.br(bbExit) + + functionGenerationContext.positionAtEnd(bbInstanceOf) + val typeOperandClass = value.typeOperand.getClass() + val resultInstanceOf = if (typeOperandClass != null) { + genInstanceOf(srcArg, typeOperandClass) + } else { + // E.g. when generating type operation with reified type parameter in the original body of inline function. + kTrue + // TODO: this code should be unreachable, however [BridgesBuilding] generates IR with such type checks. + } + functionGenerationContext.br(bbExit) + val bbInstanceOfResult = functionGenerationContext.currentBlock + + functionGenerationContext.positionAtEnd(bbExit) + val result = functionGenerationContext.phi(kBoolean) + functionGenerationContext.addPhiIncoming(result, bbNull to resultNull, bbInstanceOfResult to resultInstanceOf) + return result + } + + //-------------------------------------------------------------------------// + + private fun genInstanceOf(obj: LLVMValueRef, dstClass: IrClass): LLVMValueRef { + if (dstClass.defaultType.isObjCObjectType()) { + return genInstanceOfObjC(obj, dstClass) + } + + val srcObjInfoPtr = functionGenerationContext.bitcast(codegen.kObjHeaderPtr, obj) + + return if (!context.ghaEnabled()) { + call(context.llvm.isInstanceFunction, listOf(srcObjInfoPtr, codegen.typeInfoValue(dstClass))) + } else { + val dstHierarchyInfo = context.getLayoutBuilder(dstClass).hierarchyInfo + if (!dstClass.isInterface) { + call(context.llvm.isInstanceOfClassFastFunction, + listOf(srcObjInfoPtr, Int32(dstHierarchyInfo.classIdLo).llvm, Int32(dstHierarchyInfo.classIdHi).llvm)) + } else { + // Essentially: typeInfo.itable[place(interfaceId)].id == interfaceId + val interfaceId = dstHierarchyInfo.interfaceId + val typeInfo = functionGenerationContext.loadTypeInfo(srcObjInfoPtr) + with(functionGenerationContext) { + val interfaceTableRecord = lookupInterfaceTableRecord(typeInfo, interfaceId) + icmpEq(load(structGep(interfaceTableRecord, 0 /* id */)), Int32(interfaceId).llvm) + } + } + } + } + + private fun genInstanceOfObjC(obj: LLVMValueRef, dstClass: IrClass): LLVMValueRef { + val objCObject = callDirect( + context.ir.symbols.interopObjCObjectRawValueGetter.owner, + listOf(obj), + Lifetime.IRRELEVANT + ) + + return if (dstClass.isObjCClass()) { + if (dstClass.isInterface) { + val isMeta = if (dstClass.isObjCMetaClass()) kTrue else kFalse + call( + context.llvm.Kotlin_Interop_DoesObjectConformToProtocol, + listOf( + objCObject, + genGetObjCProtocol(dstClass), + isMeta + ) + ) + } else { + call( + context.llvm.Kotlin_Interop_IsObjectKindOfClass, + listOf(objCObject, genGetObjCClass(dstClass)) + ) + }.let { + functionGenerationContext.icmpNe(it, kFalse) + } + + + } else { + // e.g. ObjCObject, ObjCObjectBase etc. + if (dstClass.isObjCMetaClass()) { + val isClass = context.llvm.externalFunction( + "object_isClass", + functionType(int8Type, false, int8TypePtr), + context.standardLlvmSymbolsOrigin + ) + + call(isClass, listOf(objCObject)).let { + functionGenerationContext.icmpNe(it, Int8(0).llvm) + } + } else if (dstClass.isObjCProtocolClass()) { + // Note: it is not clear whether this class should be looked up this way. + // clang does the same, however swiftc uses dynamic lookup. + val protocolClass = + functionGenerationContext.getObjCClass("Protocol", context.standardLlvmSymbolsOrigin) + call( + context.llvm.Kotlin_Interop_IsObjectKindOfClass, + listOf(objCObject, protocolClass) + ) + } else { + kTrue + } + } + } + + //-------------------------------------------------------------------------// + + private fun evaluateNotInstanceOf(value: IrTypeOperatorCall): LLVMValueRef { + val instanceOfResult = evaluateInstanceOf(value) + return functionGenerationContext.not(instanceOfResult) + } + + //-------------------------------------------------------------------------// + + private fun evaluateGetField(value: IrGetField): LLVMValueRef { + context.log { "evaluateGetField : ${ir2string(value)}" } + return if (!value.symbol.owner.isStatic) { + val thisPtr = evaluateExpression(value.receiver!!) + functionGenerationContext.loadSlot( + fieldPtrOfClass(thisPtr, value.symbol.owner), !value.symbol.owner.isFinal) + } else { + assert(value.receiver == null) + if (value.symbol.owner.correspondingPropertySymbol?.owner?.isConst == true) { + evaluateConst(value.symbol.owner.initializer?.expression as IrConst<*>) + } else { + if (context.config.threadsAreAllowed && value.symbol.owner.isMainOnlyNonPrimitive) { + functionGenerationContext.checkMainThread(currentCodeContext.exceptionHandler) + } + val ptr = context.llvmDeclarations.forStaticField(value.symbol.owner).storageAddressAccess.getAddress( + functionGenerationContext + ) + functionGenerationContext.loadSlot(ptr, !value.symbol.owner.isFinal) + } + }.also { + if (value.type.classifierOrNull?.isClassWithFqName(vectorType) == true) + LLVMSetAlignment(it, 8) + + } + } + + //-------------------------------------------------------------------------// + private fun needMutationCheck(irClass: IrClass): Boolean { + // For now we omit mutation checks on immutable types, as this allows initialization in constructor + // and it is assumed that API doesn't allow to change them. + return !irClass.isFrozen + } + + private fun isZeroConstValue(value: IrExpression): Boolean { + if (value !is IrConst<*>) return false + return when (value.kind) { + IrConstKind.Null -> true + IrConstKind.Boolean -> (value.value as Boolean) == false + IrConstKind.Byte -> (value.value as Byte) == 0.toByte() + IrConstKind.Char -> (value.value as Char) == 0.toChar() + IrConstKind.Short -> (value.value as Short) == 0.toShort() + IrConstKind.Int -> (value.value as Int) == 0 + IrConstKind.Long -> (value.value as Long) == 0L + IrConstKind.Float -> (value.value as Float).toRawBits() == 0 + IrConstKind.Double -> (value.value as Double).toRawBits() == 0L + IrConstKind.String -> false + } + } + + private fun evaluateSetField(value: IrSetField): LLVMValueRef { + context.log{"evaluateSetField : ${ir2string(value)}"} + if (value.origin == IrStatementOrigin.INITIALIZE_FIELD + && isZeroConstValue(value.value)) { + check(value.receiver is IrGetValue) { "Only IrGetValue expected for receiver of a field initializer" } + // All newly allocated objects are zeroed out, so it is redundant to initialize their + // fields with the default values. This is also aligned with the Kotlin/JVM behavior. + // See https://youtrack.jetbrains.com/issue/KT-39100 for details. + return codegen.theUnitInstanceRef.llvm + } + + val valueToAssign = evaluateExpression(value.value) + val store = if (!value.symbol.owner.isStatic) { + val thisPtr = evaluateExpression(value.receiver!!) + assert(thisPtr.type == codegen.kObjHeaderPtr) { + LLVMPrintTypeToString(thisPtr.type)?.toKString().toString() + } + if (needMutationCheck(value.symbol.owner.parentAsClass)) { + functionGenerationContext.call(context.llvm.mutationCheck, + listOf(functionGenerationContext.bitcast(codegen.kObjHeaderPtr, thisPtr)), + Lifetime.IRRELEVANT, ExceptionHandler.Caller) + + if (functionGenerationContext.isObjectType(valueToAssign.type)) + functionGenerationContext.call(context.llvm.checkLifetimesConstraint, listOf(thisPtr, valueToAssign)) + } + functionGenerationContext.storeAny(valueToAssign, fieldPtrOfClass(thisPtr, value.symbol.owner), false) + } else { + assert(value.receiver == null) + val globalAddress = context.llvmDeclarations.forStaticField(value.symbol.owner).storageAddressAccess.getAddress( + functionGenerationContext + ) + if (context.config.threadsAreAllowed && value.symbol.owner.storageKind == FieldStorageKind.MAIN_THREAD) + functionGenerationContext.checkMainThread(currentCodeContext.exceptionHandler) + if (value.symbol.owner.storageKind == FieldStorageKind.SHARED) + functionGenerationContext.freeze(valueToAssign, currentCodeContext.exceptionHandler) + functionGenerationContext.storeAny(valueToAssign, globalAddress, false) + } + if (store != null && value.value.type.classifierOrNull?.isClassWithFqName(vectorType) == true) { + LLVMSetAlignment(store, 8) + } + + assert (value.type.isUnit()) + return codegen.theUnitInstanceRef.llvm + } + + private val vectorType = FqName("kotlin.native.Vector128").toUnsafe() + + //-------------------------------------------------------------------------// + private fun fieldPtrOfClass(thisPtr: LLVMValueRef, value: IrField): LLVMValueRef { + val fieldInfo = context.llvmDeclarations.forField(value) + + val typePtr = pointerType(fieldInfo.classBodyType) + + val typedBodyPtr = functionGenerationContext.bitcast(typePtr, thisPtr) + val fieldPtr = LLVMBuildStructGEP(functionGenerationContext.builder, typedBodyPtr, fieldInfo.index, "") + return fieldPtr!! + } + + //-------------------------------------------------------------------------// + private fun evaluateStringConst(value: IrConst) = + context.llvm.staticData.kotlinStringLiteral(value.value).llvm + + private fun evaluateConst(value: IrConst<*>): LLVMValueRef { + context.log{"evaluateConst : ${ir2string(value)}"} + /* This suppression against IrConst */ + @Suppress("UNCHECKED_CAST") + when (value.kind) { + IrConstKind.Null -> return codegen.kNullObjHeaderPtr + IrConstKind.Boolean -> when (value.value) { + true -> return kTrue + false -> return kFalse + } + IrConstKind.Char -> return Char16(value.value as Char).llvm + IrConstKind.Byte -> return Int8(value.value as Byte).llvm + IrConstKind.Short -> return Int16(value.value as Short).llvm + IrConstKind.Int -> return Int32(value.value as Int).llvm + IrConstKind.Long -> return Int64(value.value as Long).llvm + IrConstKind.String -> return evaluateStringConst(value as IrConst) + IrConstKind.Float -> return Float32(value.value as Float).llvm + IrConstKind.Double -> return Float64(value.value as Double).llvm + } + TODO(ir2string(value)) + } + + //-------------------------------------------------------------------------// + + private fun evaluateReturn(expression: IrReturn): LLVMValueRef { + context.log{"evaluateReturn : ${ir2string(expression)}"} + val value = expression.value + + val evaluated = evaluateExpression(value) + + val target = expression.returnTargetSymbol.owner + + currentCodeContext.genReturn(target, evaluated) + return codegen.kNothingFakeValue + } + + //-------------------------------------------------------------------------// + private inner class ReturnableBlockScope(val returnableBlock: IrReturnableBlock) : + FileScope(returnableBlock.sourceFileSymbol?.owner ?: (currentCodeContext.fileScope() as? FileScope)?.file ?: error("returnable block should belong to current file at least") ) { + + var bbExit : LLVMBasicBlockRef? = null + var resultPhi : LLVMValueRef? = null + private val functionScope by lazy { returnableBlock.inlineFunctionSymbol?.owner?.scope() } + + private fun getExit(): LLVMBasicBlockRef { + val location = returnableBlock.inlineFunctionSymbol?.let { + location(it.owner.endOffset) + } ?: returnableBlock.statements.lastOrNull()?.let { + location(it.endOffset) + } + if (bbExit == null) bbExit = functionGenerationContext.basicBlock("returnable_block_exit", location) + return bbExit!! + } + + private fun getResult(): LLVMValueRef { + if (resultPhi == null) { + val bbCurrent = functionGenerationContext.currentBlock + functionGenerationContext.positionAtEnd(getExit()) + resultPhi = functionGenerationContext.phi(codegen.getLLVMType(returnableBlock.type)) + functionGenerationContext.positionAtEnd(bbCurrent) + } + return resultPhi!! + } + + override fun genReturn(target: IrSymbolOwner, value: LLVMValueRef?) { + if (target != returnableBlock) { // It is not our "local return". + super.genReturn(target, value) + return + } + // It is local return from current function. + functionGenerationContext.br(getExit()) // Generate branch on exit block. + + if (!returnableBlock.type.isUnit()) { // If function returns more then "unit" + functionGenerationContext.assignPhis(getResult() to value!!) // Assign return value to result PHI node. + } + } + + override fun returnableBlockScope(): CodeContext? = this + + override fun location(offset: Int): LocationInfo? { + return if (returnableBlock.inlineFunctionSymbol != null) { + val diScope = functionScope ?: return null + val inlinedAt = outerContext.location(returnableBlock.startOffset) + ?: error("no location for inlinedAt:\n" + + "${returnableBlock.startOffset} ${returnableBlock.endOffset}\n" + + returnableBlock.render()) + LocationInfo(diScope, file.fileEntry.line(offset), file.fileEntry.column(offset), inlinedAt) + } else { + outerContext.location(offset) + } + } + + /** + * Note: DILexicalBlocks aren't nested, they should be scoped with the parent function. + */ + private val scope by lazy { + if (!context.shouldContainLocationDebugInfo() || returnableBlock.startOffset == UNDEFINED_OFFSET) + return@lazy null + val lexicalBlockFile = DICreateLexicalBlockFile(context.debugInfo.builder, functionScope()!!.scope(), super.file.file()) + DICreateLexicalBlock(context.debugInfo.builder, lexicalBlockFile, super.file.file(), returnableBlock.startLine(), returnableBlock.startColumn())!! + } + + override fun scope() = scope + + } + + //-------------------------------------------------------------------------// + + private open inner class FileScope(val file: IrFile) : InnerScopeImpl() { + override fun fileScope(): CodeContext? = this + + override fun location(offset: Int) = scope()?.let { LocationInfo(it, file.fileEntry.line(offset), file.fileEntry.column(offset)) } + + @Suppress("UNCHECKED_CAST") + private val scope by lazy { + if (!context.shouldContainLocationDebugInfo()) + return@lazy null + file.file() as DIScopeOpaqueRef? + } + + override fun scope() = scope + } + + //-------------------------------------------------------------------------// + + private inner class ClassScope(val clazz:IrClass) : InnerScopeImpl() { + val isExported + get() = clazz.isExported() + var offsetInBits = 0L + val members = mutableListOf() + @Suppress("UNCHECKED_CAST") + val scope = if (isExported && context.shouldContainDebugInfo()) + context.debugInfo.objHeaderPointerType + else null + override fun classScope(): CodeContext? = this + } + + //-------------------------------------------------------------------------// + + private fun evaluateReturnableBlock(value: IrReturnableBlock): LLVMValueRef { + context.log{"evaluateReturnableBlock : ${value.statements.forEach { ir2string(it) }}"} + + val returnableBlockScope = ReturnableBlockScope(value) + using(returnableBlockScope) { + using(VariableScope()) { + value.statements.forEach { + generateStatement(it) + } + } + } + + val bbExit = returnableBlockScope.bbExit + if (bbExit != null) { + if (!functionGenerationContext.isAfterTerminator()) { // TODO should we solve this problem once and for all + functionGenerationContext.unreachable() + } + functionGenerationContext.positionAtEnd(bbExit) + } + + return returnableBlockScope.resultPhi ?: if (value.type.isUnit()) { + codegen.theUnitInstanceRef.llvm + } else { + LLVMGetUndef(codegen.getLLVMType(value.type))!! + } + } + + //-------------------------------------------------------------------------// + + private fun evaluateContainerExpression(value: IrContainerExpression): LLVMValueRef { + context.log{"evaluateContainerExpression : ${value.statements.forEach { ir2string(it) }}"} + + val scope = if (value.isTransparentScope) { + null + } else { + VariableScope() + } + + using(scope) { + value.statements.dropLast(1).forEach { + generateStatement(it) + } + value.statements.lastOrNull()?.let { + if (it is IrExpression) { + return evaluateExpression(it) + } else { + generateStatement(it) + } + } + + assert(value.type.isUnit()) + return codegen.theUnitInstanceRef.llvm + } + } + + private fun evaluateInstanceInitializerCall(expression: IrInstanceInitializerCall): LLVMValueRef { + assert (expression.type.isUnit()) + return codegen.theUnitInstanceRef.llvm + } + + //-------------------------------------------------------------------------// + private fun evaluateCall(value: IrFunctionAccessExpression): LLVMValueRef { + context.log{"evaluateCall : ${ir2string(value)}"} + + intrinsicGenerator.tryEvaluateSpecialCall(value)?.let { return it } + + val args = evaluateExplicitArgs(value) + + updateBuilderDebugLocation(value) + return when (value) { + is IrDelegatingConstructorCall -> delegatingConstructorCall(value.symbol.owner, args) + is IrConstructorCall -> evaluateConstructorCall(value, args) + else -> evaluateFunctionCall(value as IrCall, args, resultLifetime(value)) + } + } + + //-------------------------------------------------------------------------// + private fun file() = (currentCodeContext.fileScope() as FileScope).file + + //-------------------------------------------------------------------------// + private fun updateBuilderDebugLocation(element: IrElement) { + if (!context.shouldContainLocationDebugInfo() || currentCodeContext.functionScope() == null || element.startLocation == null) return + functionGenerationContext.debugLocation(element.startLocation!!, element.endLocation!!) + } + + private val IrElement.startLocation: LocationInfo? + get() = if (!context.shouldContainLocationDebugInfo() || startOffset == UNDEFINED_OFFSET) null + else currentCodeContext.location(startOffset) + + private val IrElement.endLocation: LocationInfo? + get() = if (!context.shouldContainLocationDebugInfo() || startOffset == UNDEFINED_OFFSET) null + else currentCodeContext.location(endOffset) + + //-------------------------------------------------------------------------// + private fun IrElement.startLine() = file().fileEntry.line(this.startOffset) + + //-------------------------------------------------------------------------// + private fun IrElement.startColumn() = file().fileEntry.column(this.startOffset) + + //-------------------------------------------------------------------------// + private fun IrElement.endLine() = file().fileEntry.line(this.endOffset) + + //-------------------------------------------------------------------------// + private fun IrElement.endColumn() = file().fileEntry.column(this.endOffset) + + //-------------------------------------------------------------------------// + private fun debugFieldDeclaration(expression: IrField) { + val scope = currentCodeContext.classScope() as? ClassScope ?: return + if (!scope.isExported || !context.shouldContainDebugInfo()) return + val irFile = (currentCodeContext.fileScope() as FileScope).file + val sizeInBits = expression.type.size(context) + scope.offsetInBits += sizeInBits + val alignInBits = expression.type.alignment(context) + scope.offsetInBits = alignTo(scope.offsetInBits, alignInBits) + @Suppress("UNCHECKED_CAST") + scope.members.add(DICreateMemberType( + refBuilder = context.debugInfo.builder, + refScope = scope.scope as DIScopeOpaqueRef, + name = expression.symbolName, + file = irFile.file(), + lineNum = expression.startLine(), + sizeInBits = sizeInBits, + alignInBits = alignInBits, + offsetInBits = scope.offsetInBits, + flags = 0, + type = expression.type.diType(context, codegen.llvmTargetData) + )!!) + } + + + //-------------------------------------------------------------------------// + private fun IrFile.file(): DIFileRef { + return context.debugInfo.files.getOrPut(this.fileEntry.name) { + val path = this.fileEntry.name.toFileAndFolder(context) + DICreateFile(context.debugInfo.builder, path.file, path.folder)!! + } + } + + //-------------------------------------------------------------------------// + + // Saved calculated IrFunction scope which is used several time for getting locations and generating debug info. + private var irFunctionSavedScope: Pair? = null + + private fun IrFunction.scope(): DIScopeOpaqueRef? = if (startOffset != UNDEFINED_OFFSET) ( + if (irFunctionSavedScope != null && this == irFunctionSavedScope!!.first) + irFunctionSavedScope!!.second + else + this.scope(startLine()).also { irFunctionSavedScope = Pair(this, it) } + ) else null + + private val IrFunction.isReifiedInline:Boolean + get() = isInline && typeParameters.any { it.isReified } + + @Suppress("UNCHECKED_CAST") + private fun IrFunction.scope(startLine:Int): DIScopeOpaqueRef? { + if (!context.shouldContainLocationDebugInfo()) + return null + val functionLlvmValue = + // TODO: May be tie up inline lambdas to their outer function? + if (codegen.isExternal(this) && !KonanBinaryInterface.isExported(this)) + null + else + codegen.llvmFunctionOrNull(this) + return if (!isReifiedInline && functionLlvmValue != null) { + context.debugInfo.subprograms.getOrPut(functionLlvmValue) { + memScoped { + val subroutineType = subroutineType(context, codegen.llvmTargetData) + val llvmFunnction = codegen.llvmFunction(this@scope) + diFunctionScope(name.asString(), llvmFunnction.name!!, startLine, subroutineType).also { + if (!this@scope.isInline) + DIFunctionAddSubprogram(llvmFunnction, it) + } + } + } as DIScopeOpaqueRef + } else { + context.debugInfo.inlinedSubprograms.getOrPut(this) { + memScoped { + val subroutineType = subroutineType(context, codegen.llvmTargetData) + diFunctionScope(name.asString(), "", startLine, subroutineType) + } + } as DIScopeOpaqueRef + } + + } + + @Suppress("UNCHECKED_CAST") + private fun LLVMValueRef.scope(startLine:Int, subroutineType: DISubroutineTypeRef): DIScopeOpaqueRef? { + return context.debugInfo.subprograms.getOrPut(this) { + diFunctionScope(name!!, name!!, startLine, subroutineType).also { + DIFunctionAddSubprogram(this@scope, it) + } + } as DIScopeOpaqueRef + } + + @Suppress("UNCHECKED_CAST") + private fun diFunctionScope(name: String, linkageName: String, startLine: Int, subroutineType: DISubroutineTypeRef) = DICreateFunction( + builder = context.debugInfo.builder, + scope = context.debugInfo.compilationUnit, + name = name, + linkageName = linkageName, + file = file().file(), + lineNo = startLine, + type = subroutineType, + //TODO: need more investigations. + isLocal = 0, + isDefinition = 1, + scopeLine = 0)!! + + //-------------------------------------------------------------------------// + + private fun getContinuation(): LLVMValueRef { + val caller = functionGenerationContext.irFunction!! + return if (caller.isSuspend) + codegen.param(caller, caller.allParametersCount) // The last argument. + else { + // Suspend call from non-suspend function - must be [invokeSuspend]. + assert ((caller as IrSimpleFunction).overrides(context.ir.symbols.invokeSuspendFunction.owner), + { "Expected 'BaseContinuationImpl.invokeSuspend' but was '$caller'" }) + currentCodeContext.genGetValue(caller.dispatchReceiverParameter!!) + } + } + + private fun IrFunction.returnsUnit() = returnType.isUnit() && !isSuspend + + /** + * Evaluates all arguments of [expression] that are explicitly represented in the IR. + * Returns results in the same order as LLVM function expects, assuming that all explicit arguments + * exactly correspond to a tail of LLVM parameters. + */ + private fun evaluateExplicitArgs(expression: IrFunctionAccessExpression): List { + val result = expression.getArgumentsWithIr().map { (_, argExpr) -> + evaluateExpression(argExpr) + } + val explicitParametersCount = expression.symbol.owner.explicitParametersCount + if (result.size != explicitParametersCount) { + error("Number of arguments explicitly represented in the IR ${result.size} differs from expected " + + "$explicitParametersCount in ${ir2string(expression)}") + } + return result + } + + //-------------------------------------------------------------------------// + + private fun evaluateFunctionReference(expression: IrFunctionReference): LLVMValueRef { + // TODO: consider creating separate IR element for pointer to function. + assert (expression.type.getClass()?.descriptor == context.interopBuiltIns.cPointer) { + "assert: ${expression.type.getClass()?.descriptor} == ${context.interopBuiltIns.cPointer}" + } + + assert (expression.getArguments().isEmpty()) + + val function = expression.symbol.owner + assert (function.dispatchReceiverParameter == null) + + return codegen.functionEntryPointAddress(function) + } + + //-------------------------------------------------------------------------// + + private inner class SuspendableExpressionScope(val resumePoints: MutableList) : InnerScopeImpl() { + override fun addResumePoint(bbLabel: LLVMBasicBlockRef): Int { + val result = resumePoints.size + resumePoints.add(bbLabel) + return result + } + } + + private fun evaluateSuspendableExpression(expression: IrSuspendableExpression): LLVMValueRef { + val suspensionPointId = evaluateExpression(expression.suspensionPointId) + val bbStart = functionGenerationContext.basicBlock("start", expression.result.startLocation) + val bbDispatch = functionGenerationContext.basicBlock("dispatch", expression.suspensionPointId.startLocation) + + val resumePoints = mutableListOf() + using (SuspendableExpressionScope(resumePoints)) { + functionGenerationContext.condBr(functionGenerationContext.icmpEq(suspensionPointId, kNullInt8Ptr), bbStart, bbDispatch) + + functionGenerationContext.positionAtEnd(bbStart) + val result = evaluateExpression(expression.result) + + functionGenerationContext.appendingTo(bbDispatch) { + if (context.config.indirectBranchesAreAllowed) + functionGenerationContext.indirectBr(suspensionPointId, resumePoints) + else { + val bbElse = functionGenerationContext.basicBlock("else", null) { + functionGenerationContext.unreachable() + } + + val cases = resumePoints.withIndex().map { Int32(it.index + 1).llvm to it.value } + functionGenerationContext.switch(functionGenerationContext.ptrToInt(suspensionPointId, int32Type), cases, bbElse) + } + } + return result + } + } + + private inner class SuspensionPointScope(val suspensionPointId: IrVariable, + val bbResume: LLVMBasicBlockRef, + val bbResumeId: Int): InnerScopeImpl() { + override fun genGetValue(value: IrValueDeclaration): LLVMValueRef { + if (value == suspensionPointId) { + return if (context.config.indirectBranchesAreAllowed) + functionGenerationContext.blockAddress(bbResume) + else + functionGenerationContext.intToPtr(Int32(bbResumeId + 1).llvm, int8TypePtr) + } + return super.genGetValue(value) + } + } + + private fun evaluateSuspensionPoint(expression: IrSuspensionPoint): LLVMValueRef { + val bbResume = functionGenerationContext.basicBlock("resume", expression.resumeResult.startLocation) + val id = currentCodeContext.addResumePoint(bbResume) + + using (SuspensionPointScope(expression.suspensionPointIdParameter, bbResume, id)) { + continuationBlock(expression.type, expression.result.startLocation).run { + val normalResult = evaluateExpression(expression.result) + jump(this, normalResult) + + functionGenerationContext.positionAtEnd(bbResume) + val resumeResult = evaluateExpression(expression.resumeResult) + jump(this, resumeResult) + + functionGenerationContext.positionAtEnd(this.block) + return this.value + } + } + } + + //-------------------------------------------------------------------------// + + private fun evaluateFunctionCall(callee: IrCall, args: List, + resultLifetime: Lifetime): LLVMValueRef { + val function = callee.symbol.owner + + val argsWithContinuationIfNeeded = if (function.isSuspend) + args + getContinuation() + else args + return when { + function.isTypedIntrinsic -> intrinsicGenerator.evaluateCall(callee, args) + function.isBuiltInOperator -> evaluateOperatorCall(callee, argsWithContinuationIfNeeded) + else -> evaluateSimpleFunctionCall(function, argsWithContinuationIfNeeded, resultLifetime, callee.superQualifierSymbol?.owner) + } + } + + //-------------------------------------------------------------------------// + + private fun evaluateClassReference(classReference: IrClassReference): LLVMValueRef { + val typeInfoPtr = codegen.typeInfoValue(classReference.symbol.owner as IrClass) + return functionGenerationContext.bitcast(int8TypePtr, typeInfoPtr) + } + + //-------------------------------------------------------------------------// + + private fun evaluateSimpleFunctionCall( + function: IrFunction, args: List, + resultLifetime: Lifetime, superClass: IrClass? = null): LLVMValueRef { + //context.log{"evaluateSimpleFunctionCall : $tmpVariableName = ${ir2string(value)}"} + if (superClass == null && function is IrSimpleFunction && function.isOverridable) + return callVirtual(function, args, resultLifetime) + else + return callDirect(function, args, resultLifetime) + } + + //-------------------------------------------------------------------------// + private fun resultLifetime(callee: IrElement): Lifetime { + return lifetimes.getOrElse(callee) { /* TODO: make IRRELEVANT */ Lifetime.GLOBAL } + } + + private fun evaluateConstructorCall(callee: IrConstructorCall, args: List): LLVMValueRef { + context.log{"evaluateConstructorCall : ${ir2string(callee)}"} + return memScoped { + val constructedClass = callee.symbol.owner.constructedClass + val thisValue = when { + constructedClass.isArray -> { + assert(args.isNotEmpty() && args[0].type == int32Type) + functionGenerationContext.allocArray(constructedClass, args[0], + resultLifetime(callee), currentCodeContext.exceptionHandler) + } + constructedClass == context.ir.symbols.string.owner -> { + // TODO: consider returning the empty string literal instead. + assert(args.isEmpty()) + functionGenerationContext.allocArray(constructedClass, count = kImmZero, + lifetime = resultLifetime(callee), exceptionHandler = currentCodeContext.exceptionHandler) + } + + constructedClass.isObjCClass() -> error("Call should've been lowered: ${callee.dump()}") + + else -> functionGenerationContext.allocInstance(constructedClass, resultLifetime(callee), + currentCodeContext.stackLocalsManager) + } + evaluateSimpleFunctionCall(callee.symbol.owner, + listOf(thisValue) + args, Lifetime.IRRELEVANT /* constructor doesn't return anything */) + thisValue + } + } + + private fun genGetObjCClass(irClass: IrClass): LLVMValueRef { + return functionGenerationContext.getObjCClass(irClass, currentCodeContext.exceptionHandler) + } + + private fun genGetObjCProtocol(irClass: IrClass): LLVMValueRef { + // Note: this function will return the same result for Obj-C protocol and corresponding meta-class. + + assert(irClass.isInterface) + assert(irClass.isExternalObjCClass()) + + val annotation = irClass.annotations.findAnnotation(externalObjCClassFqName)!! + val protocolGetterName = annotation.getAnnotationStringValue("protocolGetter") + val protocolGetter = context.llvm.externalFunction( + protocolGetterName, + functionType(int8TypePtr, false), + irClass.llvmSymbolOrigin, + independent = true // Protocol is header-only declaration. + ) + + return call(protocolGetter, emptyList()) + } + + //-------------------------------------------------------------------------// + private val kImmZero = Int32(0).llvm + private val kImmOne = Int32(1).llvm + private val kTrue = Int1(1).llvm + private val kFalse = Int1(0).llvm + + // TODO: Intrinsify? + private fun evaluateOperatorCall(callee: IrCall, args: List): LLVMValueRef { + context.log{"evaluateOperatorCall : origin:${ir2string(callee)}"} + val function = callee.symbol.owner + val ib = context.irModule!!.irBuiltins + + with(functionGenerationContext) { + val functionSymbol = function.symbol + return when (functionSymbol) { + ib.eqeqeqSymbol -> icmpEq(args[0], args[1]) + ib.booleanNotSymbol -> icmpNe(args[0], kTrue) + else -> { + val isFloatingPoint = args[0].type.isFloatingPoint() + // LLVM does not distinguish between signed/unsigned integers, so we must check + // the parameter type. + val shouldUseUnsignedComparison = function.valueParameters[0].type.isChar() + when { + functionSymbol.isComparisonFunction(ib.greaterFunByOperandType) -> { + when { + isFloatingPoint -> fcmpGt(args[0], args[1]) + shouldUseUnsignedComparison -> icmpUGt(args[0], args[1]) + else -> icmpGt(args[0], args[1]) + } + } + functionSymbol.isComparisonFunction(ib.greaterOrEqualFunByOperandType) -> { + when { + isFloatingPoint -> fcmpGe(args[0], args[1]) + shouldUseUnsignedComparison -> icmpUGe(args[0], args[1]) + else -> icmpGe(args[0], args[1]) + } + } + functionSymbol.isComparisonFunction(ib.lessFunByOperandType) -> { + when { + isFloatingPoint -> fcmpLt(args[0], args[1]) + shouldUseUnsignedComparison -> icmpULt(args[0], args[1]) + else -> icmpLt(args[0], args[1]) + } + } + functionSymbol.isComparisonFunction(ib.lessOrEqualFunByOperandType) -> { + when { + isFloatingPoint -> fcmpLe(args[0], args[1]) + shouldUseUnsignedComparison -> icmpULe(args[0], args[1]) + else -> icmpLe(args[0], args[1]) + } + } + functionSymbol == context.irBuiltIns.illegalArgumentExceptionSymbol -> { + callDirect( + context.ir.symbols.throwIllegalArgumentExceptionWithMessage.owner, + args, + Lifetime.GLOBAL + ) + } + else -> TODO(function.name.toString()) + } + } + } + } + } + + //-------------------------------------------------------------------------// + + fun callDirect(function: IrFunction, args: List, + resultLifetime: Lifetime): LLVMValueRef { + val llvmFunction = codegen.llvmFunction(function.target) + return call(function, llvmFunction, args, resultLifetime) + } + + //-------------------------------------------------------------------------// + + fun callVirtual(function: IrFunction, args: List, + resultLifetime: Lifetime): LLVMValueRef { + + val llvmFunction = functionGenerationContext.lookupVirtualImpl(args.first(), function) + + return call(function, llvmFunction, args, resultLifetime) // Invoke the method + } + + //-------------------------------------------------------------------------// + + private fun call(function: IrFunction, llvmFunction: LLVMValueRef, args: List, + resultLifetime: Lifetime): LLVMValueRef { + + val exceptionHandler = function.annotations.findAnnotation(RuntimeNames.filterExceptions)?.let { + val foreignExceptionMode = ForeignExceptionMode.byValue(it.getAnnotationValueOrNull("mode")) + functionGenerationContext.filteringExceptionHandler(currentCodeContext, foreignExceptionMode) + } ?: currentCodeContext.exceptionHandler + + val result = call(llvmFunction, args, resultLifetime, exceptionHandler) + if (!function.isSuspend && function.returnType.isNothing()) { + functionGenerationContext.unreachable() + } + + if (LLVMGetReturnType(getFunctionType(llvmFunction)) == voidType) { + return codegen.theUnitInstanceRef.llvm + } + + return result + } + + private fun call(function: LLVMValueRef, args: List, + resultLifetime: Lifetime = Lifetime.IRRELEVANT, + exceptionHandler: ExceptionHandler = currentCodeContext.exceptionHandler): LLVMValueRef { + return functionGenerationContext.call(function, args, resultLifetime, exceptionHandler) + } + + //-------------------------------------------------------------------------// + + private fun delegatingConstructorCall(constructor: IrConstructor, args: List): LLVMValueRef { + + val constructedClass = functionGenerationContext.constructedClass!! + val thisPtr = currentCodeContext.genGetValue(constructedClass.thisReceiver!!) + + if (constructor.constructedClass.isExternalObjCClass() || constructor.constructedClass.isAny()) { + assert(args.isEmpty()) + return codegen.theUnitInstanceRef.llvm + } + + val thisPtrArgType = codegen.getLLVMType(constructor.allParameters[0].type) + val thisPtrArg = if (thisPtr.type == thisPtrArgType) { + thisPtr + } else { + // e.g. when array constructor calls super (i.e. Any) constructor. + functionGenerationContext.bitcast(thisPtrArgType, thisPtr) + } + + return callDirect(constructor, listOf(thisPtrArg) + args, + Lifetime.IRRELEVANT /* no value returned */) + } + + //-------------------------------------------------------------------------// + + private fun appendLlvmUsed(name: String, args: List) { + if (args.isEmpty()) return + + val argsCasted = args.map { it -> constPointer(it).bitcast(int8TypePtr) } + val llvmUsedGlobal = + context.llvm.staticData.placeGlobalArray(name, int8TypePtr, argsCasted) + + LLVMSetLinkage(llvmUsedGlobal.llvmGlobal, LLVMLinkage.LLVMAppendingLinkage) + LLVMSetSection(llvmUsedGlobal.llvmGlobal, "llvm.metadata") + } + + private fun appendDebugSelector() { + if (!context.producedLlvmModuleContainsStdlib) return + val llvmDebugSelector = + context.llvm.staticData.placeGlobal("KonanNeedDebugInfo", + Int32(if (context.shouldContainDebugInfo()) 1 else 0)) + llvmDebugSelector.setConstant(true) + llvmDebugSelector.setLinkage(LLVMLinkage.LLVMExternalLinkage) + } + + //-------------------------------------------------------------------------// + // Create type { i32, void ()*, i8* } + + val kCtorType = structType(int32Type, pointerType(kVoidFuncType), kInt8Ptr) + + //-------------------------------------------------------------------------// + // Create object { i32, void ()*, i8* } { i32 1, void ()* @ctorFunction, i8* null } + + fun createGlobalCtor(ctorFunction: LLVMValueRef): ConstPointer { + val priority = if (context.config.target.family == Family.MINGW) { + // Workaround MinGW bug. Using this value makes the compiler generate + // '.ctors' section instead of '.ctors.XXXXX', which can't be recognized by ld + // when string table is too long. + // More details: https://youtrack.jetbrains.com/issue/KT-39548 + Int32(65535).llvm + // Note: this difference in priorities doesn't actually make initializers + // platform-dependent, because handling priorities for initializers + // from different object files is platform-dependent anyway. + } else { + kImmInt32One + } + val data = kNullInt8Ptr + val argList = cValuesOf(priority, ctorFunction, data) + val ctorItem = LLVMConstNamedStruct(kCtorType, argList, 3)!! + return constPointer(ctorItem) + } + + //-------------------------------------------------------------------------// + fun appendStaticInitializers() { + // Note: the list of libraries is topologically sorted (in order for initializers to be called correctly). + val libraries = (context.llvm.allBitcodeDependencies + listOf(null)/* Null for "current" non-library module */) + + val libraryToInitializers = libraries.associateWith { + mutableListOf() + } + + context.llvm.irStaticInitializers.forEach { + val library = it.module.konanLibrary + val initializers = libraryToInitializers[library] + ?: error("initializer for not included library ${library?.libraryFile}") + + initializers.add(it.initializer) + } + + val ctorFunctions = libraries.map { library -> + val ctorName = if (library != null) { + library.moduleConstructorName + } else { + context.config.moduleId.moduleConstructorName + } + + val ctorFunction = LLVMAddFunction(context.llvmModule, ctorName, kVoidFuncType)!! + LLVMSetLinkage(ctorFunction, LLVMLinkage.LLVMExternalLinkage) + + val initializers = libraryToInitializers.getValue(library) + + if (library == null || context.llvmModuleSpecification.containsLibrary(library)) { + val otherInitializers = + context.llvm.otherStaticInitializers.takeIf { library == null }.orEmpty() + + appendStaticInitializers(ctorFunction, initializers + otherInitializers) + } else { + check(initializers.isEmpty()) { + "found initializer from ${library.libraryFile}, which is not included into compilation" + } + } + + ctorFunction + } + + appendGlobalCtors(ctorFunctions) + } + + private fun appendStaticInitializers(ctorFunction: LLVMValueRef, initializers: List) { + generateFunction(codegen, ctorFunction) { + val initGuardName = ctorFunction.name.orEmpty() + "_guard" + val initGuard = LLVMAddGlobal(context.llvmModule, int32Type, initGuardName) + LLVMSetInitializer(initGuard, kImmZero) + LLVMSetLinkage(initGuard, LLVMLinkage.LLVMPrivateLinkage) + val bbInited = basicBlock("inited", null) + val bbNeedInit = basicBlock("need_init", null) + + + val value = LLVMBuildLoad(builder, initGuard, "")!! + condBr(icmpEq(value, kImmZero), bbNeedInit, bbInited) + + appendingTo(bbInited) { + ret(null) + } + + appendingTo(bbNeedInit) { + LLVMBuildStore(builder, kImmOne, initGuard) + + // TODO: shall we put that into the try block? + initializers.forEach { + call(it, emptyList(), Lifetime.IRRELEVANT, + exceptionHandler = ExceptionHandler.Caller, verbatim = true) + } + ret(null) + } + } + } + + private fun appendGlobalCtors(ctorFunctions: List) { + if (context.config.produce.isFinalBinary) { + // Generate function calling all [ctorFunctions]. + val globalCtorFunction = LLVMAddFunction(context.llvmModule, "_Konan_constructors", kVoidFuncType)!! + LLVMSetLinkage(globalCtorFunction, LLVMLinkage.LLVMPrivateLinkage) + generateFunction(codegen, globalCtorFunction) { + ctorFunctions.forEach { + call(it, emptyList(), Lifetime.IRRELEVANT, + exceptionHandler = ExceptionHandler.Caller, verbatim = true) + } + ret(null) + } + + // Append initializers of global variables in "llvm.global_ctors" array. + val globalCtors = context.llvm.staticData.placeGlobalArray("llvm.global_ctors", kCtorType, + listOf(createGlobalCtor(globalCtorFunction))) + LLVMSetLinkage(globalCtors.llvmGlobal, LLVMLinkage.LLVMAppendingLinkage) + if (context.config.produce == CompilerOutputKind.PROGRAM) { + // Provide an optional handle for calling .ctors, if standard constructors mechanism + // is not available on the platform (i.e. WASM, embedded). + LLVMSetLinkage(globalCtorFunction, LLVMLinkage.LLVMExternalLinkage) + appendLlvmUsed("llvm.used", listOf(globalCtorFunction)) + } + } + } + + //-------------------------------------------------------------------------// + + fun FunctionGenerationContext.basicBlock(name: String, locationInfo: LocationInfo?, code: () -> Unit) = functionGenerationContext.basicBlock(name, locationInfo).apply { + appendingTo(this) { + code() + } + } +} + +private fun IrValueParameter.debugNameConversion() = descriptor.name.debugNameConversion() + +private fun IrVariable.debugNameConversion() = descriptor.name.debugNameConversion() + +private val thisName = Name.special("") +private val underscoreThisName = Name.identifier("_this") +/** + * HACK: this is workaround for GH-2316, to let IDE some how operate with this. + * We're experiencing issue with libclang which is used as compiler of expression in lldb + * for current state support Kotlin in lldb: + * 1. isn't accepted by libclang as valid variable name. + * 2. this is reserved name and compiled in special way. + */ +private fun Name.debugNameConversion(): Name = when(this) { + thisName -> underscoreThisName + else -> this +} + +internal class LocationInfo(val scope: DIScopeOpaqueRef, + val line: Int, + val column: Int, + val inlinedAt: LocationInfo? = null) { + init { + assert(line != 0) + } +} diff --git a/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/KotlinObjCClassInfoGenerator.kt b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/KotlinObjCClassInfoGenerator.kt new file mode 100644 index 00000000000..ba7270dfdd0 --- /dev/null +++ b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/KotlinObjCClassInfoGenerator.kt @@ -0,0 +1,150 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +package org.jetbrains.kotlin.backend.konan.llvm + +import llvm.LLVMStoreSizeOfType +import llvm.LLVMValueRef +import org.jetbrains.kotlin.backend.common.atMostOne +import org.jetbrains.kotlin.backend.konan.* +import org.jetbrains.kotlin.backend.konan.descriptors.getAnnotationStringValue +import org.jetbrains.kotlin.backend.konan.ir.* +import org.jetbrains.kotlin.ir.declarations.IrClass +import org.jetbrains.kotlin.ir.declarations.IrSimpleFunction +import org.jetbrains.kotlin.ir.util.constructors +import org.jetbrains.kotlin.ir.util.findAnnotation +import org.jetbrains.kotlin.ir.util.fqNameForIrSerialization +import org.jetbrains.kotlin.ir.util.hasAnnotation +import org.jetbrains.kotlin.resolve.descriptorUtil.fqNameSafe + +internal class KotlinObjCClassInfoGenerator(override val context: Context) : ContextUtils { + fun generate(irClass: IrClass) { + assert(irClass.isFinalClass) + + val objCLLvmDeclarations = context.llvmDeclarations.forClass(irClass).objCDeclarations!! + + val instanceMethods = generateInstanceMethodDescs(irClass) + + val companionObject = irClass.companionObject() + val classMethods = companionObject?.generateMethodDescs().orEmpty() + + val superclassName = irClass.getSuperClassNotAny()!!.let { + context.llvm.imports.add(it.llvmSymbolOrigin) + it.descriptor.getExternalObjCClassBinaryName() + } + val protocolNames = irClass.getSuperInterfaces().map { + context.llvm.imports.add(it.llvmSymbolOrigin) + it.name.asString().removeSuffix("Protocol") + } + + val exportedClassName = selectExportedClassName(irClass) + val className = exportedClassName ?: selectInternalClassName(irClass) + + val classNameLiteral = className?.let { staticData.cStringLiteral(it) } ?: NullPointer(int8Type) + val info = Struct(runtime.kotlinObjCClassInfo, + classNameLiteral, + Int32(if (exportedClassName != null) 1 else 0), + + staticData.cStringLiteral(superclassName), + staticData.placeGlobalConstArray("", int8TypePtr, + protocolNames.map { staticData.cStringLiteral(it) } + NullPointer(int8Type)), + + staticData.placeGlobalConstArray("", runtime.objCMethodDescription, instanceMethods), + Int32(instanceMethods.size), + + staticData.placeGlobalConstArray("", runtime.objCMethodDescription, classMethods), + Int32(classMethods.size), + + objCLLvmDeclarations.bodyOffsetGlobal.pointer, + + irClass.typeInfoPtr, + companionObject?.typeInfoPtr ?: NullPointer(runtime.typeInfoType), + + staticData.placeGlobal( + "kobjcclassptr:${irClass.fqNameForIrSerialization}#internal", + NullPointer(int8Type) + ).pointer + ) + + objCLLvmDeclarations.classInfoGlobal.setInitializer(info) + + objCLLvmDeclarations.bodyOffsetGlobal.setInitializer(Int32(0)) + } + + private fun IrClass.generateMethodDescs(): List = this.generateImpMethodDescs() + + private fun generateInstanceMethodDescs( + irClass: IrClass + ): List = mutableListOf().apply { + addAll(irClass.generateMethodDescs()) + val allImplementedSelectors = this.map { it.selector }.toSet() + + assert(irClass.getSuperClassNotAny()!!.isExternalObjCClass()) + val allInitMethodsInfo = irClass.getSuperClassNotAny()!!.constructors + .mapNotNull { it.getObjCInitMethod()?.getExternalObjCMethodInfo() } + .filter { it.selector !in allImplementedSelectors } + .distinctBy { it.selector } + + allInitMethodsInfo.mapTo(this) { + ObjCMethodDesc(it.selector, it.encoding, context.llvm.missingInitImp) + } + } + + private fun selectExportedClassName(irClass: IrClass): String? { + val exportObjCClassAnnotation = context.interopBuiltIns.exportObjCClass.fqNameSafe + val explicitName = irClass.getAnnotationArgumentValue(exportObjCClassAnnotation, "name") + if (explicitName != null) return explicitName + + return if (irClass.annotations.hasAnnotation(exportObjCClassAnnotation)) irClass.name.asString() else null + } + + private fun selectInternalClassName(irClass: IrClass): String? = if (irClass.isExported()) { + irClass.fqNameForIrSerialization.asString() + } else { + null // Generate as anonymous. + } + + private val impType = pointerType(functionType(int8TypePtr, true, int8TypePtr, int8TypePtr)) + + private inner class ObjCMethodDesc( + val selector: String, val encoding: String, val impFunction: LLVMValueRef + ) : Struct( + runtime.objCMethodDescription, + constPointer(impFunction).bitcast(impType), + staticData.cStringLiteral(selector), + staticData.cStringLiteral(encoding) + ) + + private fun IrClass.generateImpMethodDescs(): List = this.declarations + .filterIsInstance() + .mapNotNull { + val annotation = + it.annotations.findAnnotation(context.interopBuiltIns.objCMethodImp.fqNameSafe) ?: + return@mapNotNull null + + ObjCMethodDesc( + annotation.getAnnotationStringValue("selector"), + annotation.getAnnotationStringValue("encoding"), + it.llvmFunction + ) + } + + companion object { + const val createdClassFieldIndex = 11 + } +} + +internal fun CodeGenerator.kotlinObjCClassInfo(irClass: IrClass): LLVMValueRef { + require(irClass.isKotlinObjCClass()) + return if (isExternal(irClass)) { + importGlobal( + irClass.kotlinObjCClassInfoSymbolName, + runtime.kotlinObjCClassInfo, + origin = irClass.llvmSymbolOrigin + ) + } else { + context.llvmDeclarations.forClass(irClass).objCDeclarations!!.classInfoGlobal.llvmGlobal + } +} diff --git a/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/LlvmAttributes.kt b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/LlvmAttributes.kt new file mode 100644 index 00000000000..e1d35a12afd --- /dev/null +++ b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/LlvmAttributes.kt @@ -0,0 +1,58 @@ +/* + * Copyright 2010-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +package org.jetbrains.kotlin.backend.konan.llvm + +import llvm.LLVMAddTargetDependentFunctionAttr +import llvm.LLVMValueRef +import org.jetbrains.kotlin.backend.konan.Context +import org.jetbrains.kotlin.ir.declarations.IrConstructor +import org.jetbrains.kotlin.ir.declarations.IrFunction +import org.jetbrains.kotlin.ir.types.isNothing +import org.jetbrains.kotlin.ir.util.isThrowable +import org.jetbrains.kotlin.konan.target.Family + +internal fun addLlvmAttributes(context: Context, irFunction: IrFunction, llvmFunction: LLVMValueRef) { + if (irFunction.returnType.isNothing()) { + setFunctionNoReturn(llvmFunction) + } + + if (shouldEnforceFramePointer(context)) { + // Note: this is default for clang on at least on iOS and macOS. + enforceFramePointer(llvmFunction) + } + + if (mustNotInline(context, irFunction)) { + setFunctionNoInline(llvmFunction) + } +} + +private fun mustNotInline(context: Context, irFunction: IrFunction): Boolean { + if (context.shouldContainLocationDebugInfo()) { + if (irFunction is IrConstructor && irFunction.isPrimary && irFunction.returnType.isThrowable()) { + // To simplify skipping this constructor when scanning call stack in Kotlin_getCurrentStackTrace. + return true + } + } + + return false +} + +private fun shouldEnforceFramePointer(context: Context): Boolean { + // TODO: do we still need it? + if (!context.shouldOptimize()) { + return true + } + + return when (context.config.target.family) { + Family.OSX, Family.IOS, Family.WATCHOS, Family.TVOS -> context.shouldContainLocationDebugInfo() + Family.LINUX, Family.MINGW, Family.ANDROID, Family.WASM, Family.ZEPHYR -> false + } +} + +private fun enforceFramePointer(llvmFunction: LLVMValueRef) { + LLVMAddTargetDependentFunctionAttr(llvmFunction, "no-frame-pointer-elim", "true") + LLVMAddTargetDependentFunctionAttr(llvmFunction, "no-frame-pointer-elim-non-leaf", "") +} diff --git a/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/LlvmDeclarations.kt b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/LlvmDeclarations.kt new file mode 100644 index 00000000000..03f9722ec87 --- /dev/null +++ b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/LlvmDeclarations.kt @@ -0,0 +1,379 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +package org.jetbrains.kotlin.backend.konan.llvm + +import kotlinx.cinterop.* +import llvm.* +import org.jetbrains.kotlin.backend.konan.* +import org.jetbrains.kotlin.backend.konan.descriptors.* +import org.jetbrains.kotlin.backend.konan.ir.* +import org.jetbrains.kotlin.ir.IrElement +import org.jetbrains.kotlin.ir.declarations.* +import org.jetbrains.kotlin.ir.util.* +import org.jetbrains.kotlin.ir.visitors.IrElementVisitorVoid +import org.jetbrains.kotlin.ir.visitors.acceptChildrenVoid +import org.jetbrains.kotlin.name.FqName +import org.jetbrains.kotlin.name.Name + +internal fun createLlvmDeclarations(context: Context): LlvmDeclarations { + val generator = DeclarationsGeneratorVisitor(context) + context.ir.irModule.acceptChildrenVoid(generator) + return with(generator) { + LlvmDeclarations( + functions, classes, fields, staticFields, uniques + ) + } +} + +// Please note, that llvmName is part of the ABI, and cannot be liberally changed. +enum class UniqueKind(val llvmName: String) { + UNIT("theUnitInstance"), + EMPTY_ARRAY("theEmptyArray") +} + +internal class LlvmDeclarations( + private val functions: Map, + private val classes: Map, + private val fields: Map, + private val staticFields: Map, + private val unique: Map) { + fun forFunction(function: IrFunction) = forFunctionOrNull(function) ?: with(function){error("$name in $file/${parent.fqNameForIrSerialization}")} + fun forFunctionOrNull(function: IrFunction) = functions[function] + + fun forClass(irClass: IrClass) = classes[irClass] ?: + error(irClass.descriptor.toString()) + + fun forField(field: IrField) = fields[field] ?: + error(field.descriptor.toString()) + + fun forStaticField(field: IrField) = staticFields[field] ?: + error(field.descriptor.toString()) + + fun forSingleton(irClass: IrClass) = forClass(irClass).singletonDeclarations ?: + error(irClass.descriptor.toString()) + + fun forUnique(kind: UniqueKind) = unique[kind] ?: error("No unique $kind") + +} + +internal class ClassLlvmDeclarations( + val bodyType: LLVMTypeRef, + val typeInfoGlobal: StaticData.Global, + val writableTypeInfoGlobal: StaticData.Global?, + val typeInfo: ConstPointer, + val singletonDeclarations: SingletonLlvmDeclarations?, + val objCDeclarations: KotlinObjCClassLlvmDeclarations?) + +internal class SingletonLlvmDeclarations(val instanceStorage: AddressAccess) + +internal class KotlinObjCClassLlvmDeclarations( + val classInfoGlobal: StaticData.Global, + val bodyOffsetGlobal: StaticData.Global +) + +internal class FunctionLlvmDeclarations(val llvmFunction: LLVMValueRef) + +internal class FieldLlvmDeclarations(val index: Int, val classBodyType: LLVMTypeRef) + +internal class StaticFieldLlvmDeclarations(val storageAddressAccess: AddressAccess) + +internal class UniqueLlvmDeclarations(val pointer: ConstPointer) + +private fun ContextUtils.createClassBodyType(name: String, fields: List): LLVMTypeRef { + val fieldTypes = listOf(runtime.objHeaderType) + fields.map { getLLVMType(it.type) } + // TODO: consider adding synthetic ObjHeader field to Any. + + val classType = LLVMStructCreateNamed(LLVMGetModuleContext(context.llvmModule), name)!! + + // LLVMStructSetBody expects the struct to be properly aligned and will insert padding accordingly. In our case + // `allocInstance` returns 16x + 8 address, i.e. always misaligned for vector types. Workaround is to use packed struct. + val hasBigAlignment = fields.any { LLVMABIAlignmentOfType(context.llvm.runtime.targetData, getLLVMType(it.type)) > 8 } + val packed = if (hasBigAlignment) 1 else 0 + LLVMStructSetBody(classType, fieldTypes.toCValues(), fieldTypes.size, packed) + + return classType +} + +private class DeclarationsGeneratorVisitor(override val context: Context) : + IrElementVisitorVoid, ContextUtils { + + val functions = mutableMapOf() + val classes = mutableMapOf() + val fields = mutableMapOf() + val staticFields = mutableMapOf() + val uniques = mutableMapOf() + + private class Namer(val prefix: String) { + private val names = mutableMapOf() + private val counts = mutableMapOf() + + fun getName(parent: FqName, declaration: IrDeclaration): Name { + return names.getOrPut(declaration) { + val count = counts.getOrDefault(parent, 0) + 1 + counts[parent] = count + Name.identifier(prefix + count) + } + } + } + + val objectNamer = Namer("object-") + + private fun getLocalName(parent: FqName, declaration: IrDeclaration): Name { + if (declaration.isAnonymousObject) { + return objectNamer.getName(parent, declaration) + } + + return declaration.nameForIrSerialization + } + + private fun getFqName(declaration: IrDeclaration): FqName { + val parent = declaration.parent + val parentFqName = when (parent) { + is IrPackageFragment -> parent.fqName + is IrDeclaration -> getFqName(parent) + else -> error(parent) + } + + val localName = getLocalName(parentFqName, declaration) + return parentFqName.child(localName) + } + + /** + * Produces the name to be used for non-exported LLVM declarations corresponding to [declaration]. + * + * Note: since these declarations are going to be private, the name is only required not to clash with any + * exported declarations. + */ + private fun qualifyInternalName(declaration: IrDeclaration): String { + return getFqName(declaration).asString() + "#internal" + } + + override fun visitElement(element: IrElement) { + element.acceptChildrenVoid(this) + } + + override fun visitClass(declaration: IrClass) { + if (declaration.requiresRtti()) { + this.classes[declaration] = createClassDeclarations(declaration) + } + super.visitClass(declaration) + } + + private fun createClassDeclarations(declaration: IrClass): ClassLlvmDeclarations { + val internalName = qualifyInternalName(declaration) + + val fields = context.getLayoutBuilder(declaration).fields + val bodyType = createClassBodyType("kclassbody:$internalName", fields) + + val typeInfoPtr: ConstPointer + val typeInfoGlobal: StaticData.Global + + val typeInfoSymbolName = if (declaration.isExported()) { + declaration.typeInfoSymbolName + } else { + "ktype:$internalName" + } + + if (declaration.typeInfoHasVtableAttached) { + // Create the special global consisting of TypeInfo and vtable. + + val typeInfoGlobalName = "ktypeglobal:$internalName" + + val typeInfoWithVtableType = structType( + runtime.typeInfoType, + LLVMArrayType(int8TypePtr, context.getLayoutBuilder(declaration).vtableEntries.size)!! + ) + + typeInfoGlobal = staticData.createGlobal(typeInfoWithVtableType, typeInfoGlobalName, isExported = false) + + val llvmTypeInfoPtr = LLVMAddAlias(context.llvmModule, + kTypeInfoPtr, + typeInfoGlobal.pointer.getElementPtr(0).llvm, + typeInfoSymbolName)!! + + if (declaration.isExported()) { + if (llvmTypeInfoPtr.name != typeInfoSymbolName) { + // So alias name has been mangled by LLVM to avoid name clash. + throw IllegalArgumentException("Global '$typeInfoSymbolName' already exists") + } + } else { + LLVMSetLinkage(llvmTypeInfoPtr, LLVMLinkage.LLVMInternalLinkage) + } + + typeInfoPtr = constPointer(llvmTypeInfoPtr) + + } else { + typeInfoGlobal = staticData.createGlobal(runtime.typeInfoType, + typeInfoSymbolName, + isExported = declaration.isExported()) + + typeInfoPtr = typeInfoGlobal.pointer + } + + if (declaration.isUnit() || declaration.isKotlinArray()) + createUniqueDeclarations(declaration, typeInfoPtr, bodyType) + + val singletonDeclarations = if (declaration.kind.isSingleton) { + createSingletonDeclarations(declaration) + } else { + null + } + + val objCDeclarations = if (declaration.isKotlinObjCClass()) { + createKotlinObjCClassDeclarations(declaration) + } else { + null + } + + val writableTypeInfoType = runtime.writableTypeInfoType + val writableTypeInfoGlobal = if (writableTypeInfoType == null) { + null + } else if (declaration.isExported()) { + val name = declaration.writableTypeInfoSymbolName + staticData.createGlobal(writableTypeInfoType, name, isExported = true).also { + it.setLinkage(LLVMLinkage.LLVMCommonLinkage) // Allows to be replaced by other bitcode module. + } + } else { + staticData.createGlobal(writableTypeInfoType, "") + }.also { + it.setZeroInitializer() + } + + return ClassLlvmDeclarations(bodyType, typeInfoGlobal, writableTypeInfoGlobal, typeInfoPtr, + singletonDeclarations, objCDeclarations) + } + + private fun createUniqueDeclarations( + irClass: IrClass, typeInfoPtr: ConstPointer, bodyType: LLVMTypeRef) { + when { + irClass.isUnit() -> { + uniques[UniqueKind.UNIT] = + UniqueLlvmDeclarations(staticData.createUniqueInstance(UniqueKind.UNIT, bodyType, typeInfoPtr)) + } + irClass.isKotlinArray() -> { + uniques[UniqueKind.EMPTY_ARRAY] = + UniqueLlvmDeclarations(staticData.createUniqueInstance(UniqueKind.EMPTY_ARRAY, bodyType, typeInfoPtr)) + } + else -> TODO("Unsupported unique $irClass") + } + } + + private fun createSingletonDeclarations(irClass: IrClass): SingletonLlvmDeclarations? { + if (irClass.isUnit()) { + return null + } + + val storageKind = irClass.storageKind(context) + val threadLocal = storageKind == ObjectStorageKind.THREAD_LOCAL + val isExported = irClass.isExported() + val symbolName = if (isExported) { + irClass.globalObjectStorageSymbolName + } else { + "kobjref:" + qualifyInternalName(irClass) + } + val instanceAddress = if (threadLocal) { + addKotlinThreadLocal(symbolName, getLLVMType(irClass.defaultType)) + } else { + addKotlinGlobal(symbolName, getLLVMType(irClass.defaultType), isExported) + } + + return SingletonLlvmDeclarations(instanceAddress) + } + + private fun createKotlinObjCClassDeclarations(irClass: IrClass): KotlinObjCClassLlvmDeclarations { + val internalName = qualifyInternalName(irClass) + + val isExported = irClass.isExported() + val classInfoSymbolName = if (isExported) { + irClass.kotlinObjCClassInfoSymbolName + } else { + "kobjcclassinfo:$internalName" + } + val classInfoGlobal = staticData.createGlobal( + context.llvm.runtime.kotlinObjCClassInfo, + classInfoSymbolName, + isExported = isExported + ).apply { + setConstant(true) + } + + val bodyOffsetGlobal = staticData.createGlobal(int32Type, "kobjcbodyoffs:$internalName") + + return KotlinObjCClassLlvmDeclarations(classInfoGlobal, bodyOffsetGlobal) + } + + override fun visitField(declaration: IrField) { + super.visitField(declaration) + + val containingClass = declaration.parent as? IrClass + if (containingClass != null) { + if (!containingClass.requiresRtti()) return + val classDeclarations = this.classes[containingClass] ?: + error(containingClass.descriptor.toString()) + val allFields = context.getLayoutBuilder(containingClass).fields + this.fields[declaration] = FieldLlvmDeclarations( + allFields.indexOf(declaration) + 1, // First field is ObjHeader. + classDeclarations.bodyType + ) + } else { + // Fields are module-private, so we use internal name: + val name = "kvar:" + qualifyInternalName(declaration) + val storage = if (declaration.storageKind == FieldStorageKind.THREAD_LOCAL) { + addKotlinThreadLocal(name, getLLVMType(declaration.type)) + } else { + addKotlinGlobal(name, getLLVMType(declaration.type), isExported = false) + } + + this.staticFields[declaration] = StaticFieldLlvmDeclarations(storage) + } + } + + override fun visitFunction(declaration: IrFunction) { + super.visitFunction(declaration) + + if (!declaration.isReal) return + + val llvmFunctionType = getLlvmFunctionType(declaration) + + if ((declaration is IrConstructor && declaration.isObjCConstructor)) { + return + } + + val llvmFunction = if (declaration.isExternal) { + if (declaration.isTypedIntrinsic || declaration.isObjCBridgeBased() + // All call-sites to external accessors to interop properties + // are lowered by InteropLowering. + || (declaration.isAccessor && declaration.isFromMetadataInteropLibrary()) + || declaration.annotations.hasAnnotation(RuntimeNames.cCall)) return + + context.llvm.externalFunction(declaration.symbolName, llvmFunctionType, + // Assume that `external fun` is defined in native libs attached to this module: + origin = declaration.llvmSymbolOrigin, + independent = declaration.hasAnnotation(RuntimeNames.independent) + ) + } else { + val symbolName = if (declaration.isExported()) { + declaration.symbolName.also { + if (declaration.name.asString() != "main") { + assert(LLVMGetNamedFunction(context.llvm.llvmModule, it) == null) { it } + } else { + // As a workaround, allow `main` functions to clash because frontend accepts this. + // See [OverloadResolver.isTopLevelMainInDifferentFiles] usage. + } + } + } else { + "kfun:" + qualifyInternalName(declaration) + } + val function = LLVMAddFunction(context.llvmModule, symbolName, llvmFunctionType)!! + + addLlvmAttributes(context, declaration, function) + + function + } + + this.functions[declaration] = FunctionLlvmDeclarations(llvmFunction) + } +} diff --git a/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/LlvmLinkOptions.kt b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/LlvmLinkOptions.kt new file mode 100644 index 00000000000..d3e78578e91 --- /dev/null +++ b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/LlvmLinkOptions.kt @@ -0,0 +1,16 @@ +/* + * Copyright 2010-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +package org.jetbrains.kotlin.backend.konan.llvm + +import llvm.LLVMAddNamedMetadataOperand +import llvm.LLVMModuleRef + +fun embedLlvmLinkOptions(module: LLVMModuleRef, options: List>) { + options.forEach { + val node = node(*it.map { it.mdString() }.toTypedArray()) + LLVMAddNamedMetadataOperand(module, "llvm.linker.options", node) + } +} \ No newline at end of file diff --git a/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/LlvmUtils.kt b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/LlvmUtils.kt new file mode 100644 index 00000000000..480dff89f48 --- /dev/null +++ b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/LlvmUtils.kt @@ -0,0 +1,440 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +package org.jetbrains.kotlin.backend.konan.llvm + +import kotlinx.cinterop.* +import llvm.* +import org.jetbrains.kotlin.backend.konan.Context +import org.jetbrains.kotlin.descriptors.konan.CompiledKlibModuleOrigin + +private val llvmContextHolder = ThreadLocal() +internal var llvmContext: LLVMContextRef + get() = llvmContextHolder.get() + set(value) { llvmContextHolder.set(value) } + +internal fun tryDisposeLLVMContext() { + val llvmContext = llvmContextHolder.get() + if (llvmContext != null) + LLVMContextDispose(llvmContext) + llvmContextHolder.remove() +} + +internal val LLVMTypeRef.context: LLVMContextRef + get() = LLVMGetTypeContext(this)!! + +internal val List.context: LLVMContextRef + get() { + val context = this[0].context + for (i in 1 until this.size) + assert(this[i].context == context) { + "Expected the same context for all types in a list" + } + return context + } + +internal val LLVMValueRef.type: LLVMTypeRef + get() = LLVMTypeOf(this)!! + +/** + * Represents the value which can be emitted as bitcode const value + */ +internal interface ConstValue { + val llvm: LLVMValueRef +} + +internal val ConstValue.llvmType: LLVMTypeRef + get() = this.llvm.type + +internal interface ConstPointer : ConstValue { + fun getElementPtr(index: Int): ConstPointer = ConstGetElementPtr(this, index) +} + +internal fun constPointer(value: LLVMValueRef) = object : ConstPointer { + init { + assert(LLVMIsConstant(value) == 1) + } + + override val llvm = value +} + +private class ConstGetElementPtr(val pointer: ConstPointer, val index: Int) : ConstPointer { + override val llvm = LLVMConstInBoundsGEP(pointer.llvm, cValuesOf(Int32(0).llvm, Int32(index).llvm), 2)!! + // TODO: squash multiple GEPs +} + +internal fun ConstPointer.bitcast(toType: LLVMTypeRef) = constPointer(LLVMConstBitCast(this.llvm, toType)!!) + +internal class ConstArray(elementType: LLVMTypeRef?, val elements: List) : ConstValue { + init { + elements.forEach { + assert(it.llvmType == elementType) { + "Expected element type: ${llvmtype2string(elementType)}, actual: ${llvmtype2string(it.llvmType)}" + } + } + } + override val llvm = LLVMConstArray(elementType, elements.map { it.llvm }.toCValues(), elements.size)!! +} + +internal open class Struct(val type: LLVMTypeRef?, val elements: List) : ConstValue { + + constructor(type: LLVMTypeRef?, vararg elements: ConstValue?) : this(type, elements.toList()) + + constructor(vararg elements: ConstValue) : this(structType(elements.map { it.llvmType }), *elements) + + override val llvm = LLVMConstNamedStruct(type, elements.mapIndexed { index, element -> + val expectedType = LLVMStructGetTypeAtIndex(type, index) + if (element == null) { + LLVMConstNull(expectedType)!! + } else { + element.llvm.also { + assert(it.type == expectedType) { + "Unexpected type at $index: expected ${LLVMPrintTypeToString(expectedType)!!.toKString()} " + + "got ${LLVMPrintTypeToString(it.type)!!.toKString()}" + } + } + } + }.toCValues(), elements.size)!! + + init { + assert(elements.size == LLVMCountStructElementTypes(type)) + } +} + +internal val int1Type get() = LLVMInt1TypeInContext(llvmContext)!! +internal val int8Type get() = LLVMInt8TypeInContext(llvmContext)!! +internal val int16Type get() = LLVMInt16TypeInContext(llvmContext)!! +internal val int32Type get() = LLVMInt32TypeInContext(llvmContext)!! +internal val int64Type get() = LLVMInt64TypeInContext(llvmContext)!! +internal val int8TypePtr get() = pointerType(int8Type) +internal val floatType get() = LLVMFloatTypeInContext(llvmContext)!! +internal val doubleType get() = LLVMDoubleTypeInContext(llvmContext)!! +internal val vector128Type get() = LLVMVectorType(floatType, 4)!! + +internal val voidType get() = LLVMVoidTypeInContext(llvmContext)!! + +internal class Int1(val value: Byte) : ConstValue { + override val llvm = LLVMConstInt(int1Type, value.toLong(), 1)!! +} + +internal class Int8(val value: Byte) : ConstValue { + override val llvm = LLVMConstInt(int8Type, value.toLong(), 1)!! +} + +internal class Int16(val value: Short) : ConstValue { + override val llvm = LLVMConstInt(int16Type, value.toLong(), 1)!! +} + +internal class Char16(val value: Char) : ConstValue { + override val llvm = LLVMConstInt(int16Type, value.toLong(), 1)!! +} + +internal class Int32(val value: Int) : ConstValue { + override val llvm = LLVMConstInt(int32Type, value.toLong(), 1)!! +} + +internal class Int64(val value: Long) : ConstValue { + override val llvm = LLVMConstInt(int64Type, value, 1)!! +} + +internal class Float32(val value: Float) : ConstValue { + override val llvm = LLVMConstReal(floatType, value.toDouble())!! +} + +internal class Float64(val value: Double) : ConstValue { + override val llvm = LLVMConstReal(doubleType, value)!! +} + +internal class Zero(val type: LLVMTypeRef) : ConstValue { + override val llvm = LLVMConstNull(type)!! +} + +internal class NullPointer(pointeeType: LLVMTypeRef): ConstPointer { + override val llvm = LLVMConstNull(pointerType(pointeeType))!! +} + +internal fun constValue(value: LLVMValueRef) = object : ConstValue { + init { + assert (LLVMIsConstant(value) == 1) + } + + override val llvm = value +} + +internal val RuntimeAware.kTypeInfo: LLVMTypeRef + get() = runtime.typeInfoType +internal val RuntimeAware.kObjHeader: LLVMTypeRef + get() = runtime.objHeaderType +internal val RuntimeAware.kObjHeaderPtr: LLVMTypeRef + get() = pointerType(kObjHeader) +internal val RuntimeAware.kObjHeaderPtrPtr: LLVMTypeRef + get() = pointerType(kObjHeaderPtr) +internal val RuntimeAware.kArrayHeader: LLVMTypeRef + get() = runtime.arrayHeaderType +internal val RuntimeAware.kArrayHeaderPtr: LLVMTypeRef + get() = pointerType(kArrayHeader) +internal val RuntimeAware.kTypeInfoPtr: LLVMTypeRef + get() = pointerType(kTypeInfo) +internal val kInt1 get() = int1Type +internal val kBoolean get() = kInt1 +internal val kInt8Ptr get() = pointerType(int8Type) +internal val kInt8PtrPtr get() = pointerType(kInt8Ptr) +internal val kNullInt8Ptr get() = LLVMConstNull(kInt8Ptr)!! +internal val kImmInt32Zero get() = Int32(0).llvm +internal val kImmInt32One get() = Int32(1).llvm +internal val ContextUtils.kNullObjHeaderPtr: LLVMValueRef + get() = LLVMConstNull(this.kObjHeaderPtr)!! +internal val ContextUtils.kNullObjHeaderPtrPtr: LLVMValueRef + get() = LLVMConstNull(this.kObjHeaderPtrPtr)!! + +// Nothing type has no values, but we do generate unreachable code and thus need some fake value: +internal val ContextUtils.kNothingFakeValue: LLVMValueRef + get() = LLVMGetUndef(kObjHeaderPtr)!! + +internal fun pointerType(pointeeType: LLVMTypeRef) = LLVMPointerType(pointeeType, 0)!! + +internal fun structType(vararg types: LLVMTypeRef): LLVMTypeRef = structType(types.toList()) + +internal fun structType(types: List): LLVMTypeRef = + LLVMStructTypeInContext(llvmContext, types.toCValues(), types.size, 0)!! + +internal fun ContextUtils.numParameters(functionType: LLVMTypeRef) : Int { + // Note that type is usually function pointer, so we have to dereference it. + return LLVMCountParamTypes(LLVMGetElementType(functionType)) +} + +fun extractConstUnsignedInt(value: LLVMValueRef): Long { + assert(LLVMIsConstant(value) != 0) + return LLVMConstIntGetZExtValue(value) +} + +internal fun ContextUtils.isObjectReturn(functionType: LLVMTypeRef) : Boolean { + // Note that type is usually function pointer, so we have to dereference it. + val returnType = LLVMGetReturnType(LLVMGetElementType(functionType))!! + return isObjectType(returnType) +} + +internal fun ContextUtils.isObjectRef(value: LLVMValueRef): Boolean { + return isObjectType(value.type) +} + +internal fun RuntimeAware.isObjectType(type: LLVMTypeRef): Boolean { + return type == kObjHeaderPtr || type == kArrayHeaderPtr +} + +/** + * Reads [size] bytes contained in this array. + */ +internal fun CArrayPointer.getBytes(size: Long) = + (0 .. size-1).map { this[it] }.toByteArray() + +internal fun getFunctionType(ptrToFunction: LLVMValueRef): LLVMTypeRef { + return getGlobalType(ptrToFunction) +} + +internal fun getGlobalType(ptrToGlobal: LLVMValueRef): LLVMTypeRef { + return LLVMGetElementType(ptrToGlobal.type)!! +} + +internal fun ContextUtils.addGlobal(name: String, type: LLVMTypeRef, isExported: Boolean): LLVMValueRef { + if (isExported) + assert(LLVMGetNamedGlobal(context.llvmModule, name) == null) + return LLVMAddGlobal(context.llvmModule, type, name)!! +} + +internal fun ContextUtils.importGlobal(name: String, type: LLVMTypeRef, origin: CompiledKlibModuleOrigin): LLVMValueRef { + + context.llvm.imports.add(origin) + + val found = LLVMGetNamedGlobal(context.llvmModule, name) + return if (found != null) { + assert (getGlobalType(found) == type) + assert (LLVMGetInitializer(found) == null) { "$name is already declared in the current module" } + found + } else { + addGlobal(name, type, isExported = false) + } +} + +internal abstract class AddressAccess { + abstract fun getAddress(generationContext: FunctionGenerationContext?): LLVMValueRef +} + +internal class GlobalAddressAccess(private val address: LLVMValueRef): AddressAccess() { + override fun getAddress(generationContext: FunctionGenerationContext?): LLVMValueRef = address +} + +internal class TLSAddressAccess( + private val context: Context, private val index: Int): AddressAccess() { + + override fun getAddress(generationContext: FunctionGenerationContext?): LLVMValueRef { + return generationContext!!.call(context.llvm.lookupTLS, + listOf(context.llvm.tlsKey, Int32(index).llvm)) + } +} + +internal fun ContextUtils.addKotlinThreadLocal(name: String, type: LLVMTypeRef): AddressAccess { + return if (isObjectType(type)) { + val index = context.llvm.tlsCount++ + TLSAddressAccess(context, index) + } else { + // TODO: This will break if Workers get decoupled from host threads. + GlobalAddressAccess(LLVMAddGlobal(context.llvmModule, type, name)!!.also { + LLVMSetThreadLocalMode(it, context.llvm.tlsMode) + LLVMSetLinkage(it, LLVMLinkage.LLVMInternalLinkage) + }) + } +} + +internal fun ContextUtils.addKotlinGlobal(name: String, type: LLVMTypeRef, isExported: Boolean): AddressAccess { + return GlobalAddressAccess(LLVMAddGlobal(context.llvmModule, type, name)!!.also { + if (!isExported) + LLVMSetLinkage(it, LLVMLinkage.LLVMInternalLinkage) + }) +} + +internal fun functionType(returnType: LLVMTypeRef, isVarArg: Boolean = false, vararg paramTypes: LLVMTypeRef) = + LLVMFunctionType( + returnType, + cValuesOf(*paramTypes), paramTypes.size, + if (isVarArg) 1 else 0 + )!! + +internal fun functionType(returnType: LLVMTypeRef, isVarArg: Boolean = false, paramTypes: List) = + functionType(returnType, isVarArg, *paramTypes.toTypedArray()) + + +fun llvm2string(value: LLVMValueRef?): String { + if (value == null) return "" + return LLVMPrintValueToString(value)!!.toKString() +} + +fun llvmtype2string(type: LLVMTypeRef?): String { + if (type == null) return "" + return LLVMPrintTypeToString(type)!!.toKString() +} + +fun getStructElements(type: LLVMTypeRef): List { + val count = LLVMCountStructElementTypes(type) + return (0 until count).map { + LLVMStructGetTypeAtIndex(type, it)!! + } +} + +fun parseBitcodeFile(path: String): LLVMModuleRef = memScoped { + val bufRef = alloc() + val errorRef = allocPointerTo() + + val res = LLVMCreateMemoryBufferWithContentsOfFile(path, bufRef.ptr, errorRef.ptr) + if (res != 0) { + throw Error(errorRef.value?.toKString()) + } + + val memoryBuffer = bufRef.value + try { + + val moduleRef = alloc() + val parseRes = LLVMParseBitcodeInContext2(llvmContext, memoryBuffer, moduleRef.ptr) + if (parseRes != 0) { + throw Error(parseRes.toString()) + } + + moduleRef.value!! + } finally { + LLVMDisposeMemoryBuffer(memoryBuffer) + } +} + +private val nounwindAttrKindId by lazy { + getLlvmAttributeKindId("nounwind") +} + +private val noreturnAttrKindId by lazy { + getLlvmAttributeKindId("noreturn") +} + +private val noinlineAttrKindId by lazy { + getLlvmAttributeKindId("noinline") +} + +private val signextAttrKindId by lazy { + getLlvmAttributeKindId("signext") +} + + +fun isFunctionNoUnwind(function: LLVMValueRef): Boolean { + val attribute = LLVMGetEnumAttributeAtIndex(function, LLVMAttributeFunctionIndex, nounwindAttrKindId.value) + return attribute != null +} + +internal fun getLlvmAttributeKindId(attributeName: String): LLVMAttributeKindId { + val attrKindId = LLVMGetEnumAttributeKindForName(attributeName, attributeName.length.signExtend()) + if (attrKindId == 0) { + throw Error("Unable to find '$attributeName' attribute kind id") + } + return LLVMAttributeKindId(attrKindId) +} + +data class LLVMAttributeKindId(val value: Int) + +fun setFunctionNoUnwind(function: LLVMValueRef) { + addLlvmFunctionEnumAttribute(function, nounwindAttrKindId) +} + +fun setFunctionNoReturn(function: LLVMValueRef) { + addLlvmFunctionEnumAttribute(function, noreturnAttrKindId) +} + +fun setFunctionNoInline(function: LLVMValueRef) { + addLlvmFunctionEnumAttribute(function, noinlineAttrKindId) +} + +internal fun addLlvmFunctionEnumAttribute(function: LLVMValueRef, attrKindId: LLVMAttributeKindId, value: Long = 0) { + val attribute = createLlvmEnumAttribute(LLVMGetTypeContext(function.type)!!, attrKindId, value) + addLlvmFunctionAttribute(function, attribute) +} + +internal fun createLlvmEnumAttribute(llvmContext: LLVMContextRef, attrKindId: LLVMAttributeKindId, value: Long = 0) = + LLVMCreateEnumAttribute(llvmContext, attrKindId.value, value)!! + +internal fun addLlvmFunctionAttribute(function: LLVMValueRef, attribute: LLVMAttributeRef) { + LLVMAddAttributeAtIndex(function, LLVMAttributeFunctionIndex, attribute) +} + +fun addFunctionSignext(function: LLVMValueRef, index: Int, type: LLVMTypeRef?) { + if (type == int1Type || type == int8Type || type == int16Type) { + val attribute = createLlvmEnumAttribute(LLVMGetTypeContext(function.type)!!, signextAttrKindId) + LLVMAddAttributeAtIndex(function, index, attribute) + } +} + +internal fun String.mdString() = LLVMMDStringInContext(llvmContext, this, this.length)!! +internal fun node(vararg it:LLVMValueRef) = LLVMMDNodeInContext(llvmContext, it.toList().toCValues(), it.size) + +internal fun LLVMValueRef.setUnaligned() = apply { LLVMSetAlignment(this, 1) } + +internal fun getOperands(value: LLVMValueRef) = + (0 until LLVMGetNumOperands(value)).map { LLVMGetOperand(value, it)!! } + +internal fun getGlobalAliases(module: LLVMModuleRef) = + generateSequence(LLVMGetFirstGlobalAlias(module), { LLVMGetNextGlobalAlias(it) }) + +internal fun getFunctions(module: LLVMModuleRef) = + generateSequence(LLVMGetFirstFunction(module), { LLVMGetNextFunction(it) }) + +internal fun getGlobals(module: LLVMModuleRef) = + generateSequence(LLVMGetFirstGlobal(module), { LLVMGetNextGlobal(it) }) + +fun LLVMTypeRef.isFloatingPoint(): Boolean = when (llvm.LLVMGetTypeKind(this)) { + LLVMTypeKind.LLVMFloatTypeKind, LLVMTypeKind.LLVMDoubleTypeKind -> true + else -> false +} + +fun LLVMTypeRef.isVectorElementType(): Boolean = when (llvm.LLVMGetTypeKind(this)) { + LLVMTypeKind.LLVMIntegerTypeKind, + LLVMTypeKind.LLVMFloatTypeKind, + LLVMTypeKind.LLVMDoubleTypeKind -> true + else -> false +} diff --git a/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/RTTIGenerator.kt b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/RTTIGenerator.kt new file mode 100644 index 00000000000..e3741cacc77 --- /dev/null +++ b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/RTTIGenerator.kt @@ -0,0 +1,643 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +package org.jetbrains.kotlin.backend.konan.llvm + +import llvm.* +import org.jetbrains.kotlin.backend.konan.* +import org.jetbrains.kotlin.backend.konan.Context +import org.jetbrains.kotlin.backend.konan.descriptors.* +import org.jetbrains.kotlin.backend.konan.ir.* +import org.jetbrains.kotlin.backend.konan.isExternalObjCClassMethod +import org.jetbrains.kotlin.builtins.PrimitiveType +import org.jetbrains.kotlin.builtins.StandardNames +import org.jetbrains.kotlin.ir.declarations.* +import org.jetbrains.kotlin.ir.symbols.isPublicApi +import org.jetbrains.kotlin.ir.types.* +import org.jetbrains.kotlin.ir.util.* +import org.jetbrains.kotlin.ir.util.isAnnotationClass +import org.jetbrains.kotlin.ir.util.isInterface +import org.jetbrains.kotlin.library.KotlinAbiVersion +import org.jetbrains.kotlin.name.FqName + +internal class RTTIGenerator(override val context: Context) : ContextUtils { + + private val acyclicCache = mutableMapOf() + private val safeAcyclicFieldTypes = setOf( + context.irBuiltIns.stringClass, + context.irBuiltIns.booleanClass, context.irBuiltIns.charClass, + context.irBuiltIns.byteClass, context.irBuiltIns.shortClass, context.irBuiltIns.intClass, + context.irBuiltIns.longClass, + context.irBuiltIns.floatClass,context.irBuiltIns.doubleClass) + + context.ir.symbols.primitiveArrays.values + + context.ir.symbols.unsignedArrays.values + + // TODO: extend logic here by taking into account final acyclic classes. + private fun checkAcyclicFieldType(type: IrType): Boolean = acyclicCache.getOrPut(type) { + when { + type.isInterface() -> false + type.computePrimitiveBinaryTypeOrNull() != null -> true + else -> { + val classifier = type.classifierOrNull + (classifier != null && classifier in safeAcyclicFieldTypes) + } + } + } + + private fun checkAcyclicClass(irClass: IrClass): Boolean = when { + irClass.symbol == context.ir.symbols.array -> false + irClass.isArray -> true + context.getLayoutBuilder(irClass).fields.all { checkAcyclicFieldType(it.type) } -> true + else -> false + } + + private fun flagsFromClass(irClass: IrClass): Int { + var result = 0 + if (irClass.isFrozen) + result = result or TF_IMMUTABLE + // TODO: maybe perform deeper analysis to find surely acyclic types. + if (!irClass.isInterface && !irClass.isAbstract() && !irClass.isAnnotationClass) { + if (checkAcyclicClass(irClass)) { + result = result or TF_ACYCLIC + } + } + if (irClass.hasAnnotation(KonanFqNames.leakDetectorCandidate)) { + result = result or TF_LEAK_DETECTOR_CANDIDATE + } + if (irClass.isInterface) + result = result or TF_INTERFACE + + if (irClass.defaultType.isSuspendFunction()) { + result = result or TF_SUSPEND_FUNCTION + } + + if (irClass.hasAnnotation(KonanFqNames.hasFinalizer)) { + result = result or TF_HAS_FINALIZER + } + + return result + } + + inner class MethodTableRecord(val nameSignature: LocalHash, methodEntryPoint: ConstPointer?) : + Struct(runtime.methodTableRecordType, nameSignature, methodEntryPoint) + + inner class InterfaceTableRecord(id: Int32, vtableSize: Int32, vtable: ConstPointer?) : + Struct(runtime.interfaceTableRecordType, id, vtableSize, vtable) + + private inner class TypeInfo( + selfPtr: ConstPointer, + extendedInfo: ConstPointer, + size: Int, + superType: ConstValue, + objOffsets: ConstValue, + objOffsetsCount: Int, + interfaces: ConstValue, + interfacesCount: Int, + methods: ConstValue, + methodsCount: Int, + interfaceTableSize: Int, + interfaceTable: ConstValue, + packageName: String?, + relativeName: String?, + flags: Int, + classId: Int, + writableTypeInfo: ConstPointer?, + associatedObjects: ConstPointer?) : + + Struct( + runtime.typeInfoType, + + selfPtr, + + extendedInfo, + + // TODO: it used to be a single int32 ABI version, + // but klib abi version is not an int anymore. + // So now this field is just reserved to preserve the layout. + Int32(0), + + Int32(size), + + superType, + + objOffsets, + Int32(objOffsetsCount), + + interfaces, + Int32(interfacesCount), + + methods, + Int32(methodsCount), + + Int32(interfaceTableSize), + interfaceTable, + + kotlinStringLiteral(packageName), + kotlinStringLiteral(relativeName), + + Int32(flags), + + Int32(classId), + + *listOfNotNull(writableTypeInfo).toTypedArray(), + + associatedObjects + ) + + private fun kotlinStringLiteral(string: String?): ConstPointer = if (string == null) { + NullPointer(runtime.objHeaderType) + } else { + staticData.kotlinStringLiteral(string) + } + + private val EXPORT_TYPE_INFO_FQ_NAME = FqName.fromSegments(listOf("kotlin", "native", "internal", "ExportTypeInfo")) + + private fun exportTypeInfoIfRequired(irClass: IrClass, typeInfoGlobal: LLVMValueRef?) { + val annotation = irClass.annotations.findAnnotation(EXPORT_TYPE_INFO_FQ_NAME) + if (annotation != null) { + val name = annotation.getAnnotationStringValue()!! + // TODO: use LLVMAddAlias. + val global = addGlobal(name, pointerType(runtime.typeInfoType), isExported = true) + LLVMSetInitializer(global, typeInfoGlobal) + } + } + + private val arrayClasses = mapOf( + IdSignatureValues.array to kObjHeaderPtr, + primitiveArrayTypesSignatures[PrimitiveType.BYTE] to int8Type, + primitiveArrayTypesSignatures[PrimitiveType.CHAR] to int16Type, + primitiveArrayTypesSignatures[PrimitiveType.SHORT] to int16Type, + primitiveArrayTypesSignatures[PrimitiveType.INT] to int32Type, + primitiveArrayTypesSignatures[PrimitiveType.LONG] to int64Type, + primitiveArrayTypesSignatures[PrimitiveType.FLOAT] to floatType, + primitiveArrayTypesSignatures[PrimitiveType.DOUBLE] to doubleType, + primitiveArrayTypesSignatures[PrimitiveType.BOOLEAN] to int8Type, + IdSignatureValues.string to int16Type, + getPublicSignature(KonanFqNames.packageName, "ImmutableBlob") to int8Type, + getPublicSignature(KonanFqNames.internalPackageName, "NativePtrArray") to kInt8Ptr + ) + + // Keep in sync with Konan_RuntimeType. + private val runtimeTypeMap = mapOf( + kObjHeaderPtr to 1, + int8Type to 2, + int16Type to 3, + int32Type to 4, + int64Type to 5, + floatType to 6, + doubleType to 7, + kInt8Ptr to 8, + int1Type to 9, + vector128Type to 10 + ) + + private fun getElementType(irClass: IrClass): LLVMTypeRef? = + if (irClass.symbol.isPublicApi) arrayClasses[irClass.symbol.signature as IdSignature.PublicSignature] else null + + private fun getInstanceSize(classType: LLVMTypeRef?, irClass: IrClass) : Int { + val elementType = getElementType(irClass) + // Check if it is an array. + if (elementType != null) return -LLVMABISizeOfType(llvmTargetData, elementType).toInt() + return LLVMStoreSizeOfType(llvmTargetData, classType).toInt() + } + + private fun getClassId(irClass: IrClass): Int { + if (irClass.isKotlinObjCClass()) return 0 + val hierarchyInfo = if (context.ghaEnabled()) { + context.getLayoutBuilder(irClass).hierarchyInfo + } else { + ClassGlobalHierarchyInfo.DUMMY + } + return if (irClass.isInterface) { + hierarchyInfo.interfaceId + } else { + hierarchyInfo.classIdLo + } + } + + fun generate(irClass: IrClass) { + + val className = irClass.fqNameForIrSerialization + + val llvmDeclarations = context.llvmDeclarations.forClass(irClass) + + val bodyType = llvmDeclarations.bodyType + + val instanceSize = getInstanceSize(bodyType, irClass) + + val superType = when { + irClass.isAny() -> NullPointer(runtime.typeInfoType) + irClass.isKotlinObjCClass() -> context.ir.symbols.any.owner.typeInfoPtr + else -> { + val superTypeOrAny = irClass.getSuperClassNotAny() ?: context.ir.symbols.any.owner + superTypeOrAny.typeInfoPtr + } + } + + val implementedInterfaces = irClass.implementedInterfaces.filter { it.requiresRtti() } + + val interfaces = implementedInterfaces.map { it.typeInfoPtr } + val interfacesPtr = staticData.placeGlobalConstArray("kintf:$className", + pointerType(runtime.typeInfoType), interfaces) + + val objOffsets = getObjOffsets(bodyType) + + val objOffsetsPtr = staticData.placeGlobalConstArray("krefs:$className", int32Type, objOffsets) + + val objOffsetsCount = if (irClass.descriptor == context.builtIns.array) { + 1 // To mark it as non-leaf. + } else { + objOffsets.size + } + + val methods = if (irClass.isAbstract()) { + emptyList() + } else { + methodTableRecords(irClass) + } + val methodsPtr = staticData.placeGlobalConstArray("kmethods:$className", + runtime.methodTableRecordType, methods) + + val needInterfaceTable = context.ghaEnabled() && !irClass.isInterface + && !irClass.isAbstract() && !irClass.isObjCClass() + val (interfaceTable, interfaceTableSize) = if (needInterfaceTable) { + interfaceTableRecords(irClass) + } else { + Pair(emptyList(), -1) + } + val interfaceTablePtr = staticData.placeGlobalConstArray("kifacetable:$className", + runtime.interfaceTableRecordType, interfaceTable) + + val reflectionInfo = getReflectionInfo(irClass) + val typeInfoGlobal = llvmDeclarations.typeInfoGlobal + val typeInfo = TypeInfo( + irClass.typeInfoPtr, + makeExtendedInfo(irClass), + instanceSize, + superType, + objOffsetsPtr, objOffsetsCount, + interfacesPtr, interfaces.size, + methodsPtr, methods.size, + interfaceTableSize, interfaceTablePtr, + reflectionInfo.packageName, + reflectionInfo.relativeName, + flagsFromClass(irClass), + getClassId(irClass), + llvmDeclarations.writableTypeInfoGlobal?.pointer, + associatedObjects = genAssociatedObjects(irClass) + ) + + val typeInfoGlobalValue = if (!irClass.typeInfoHasVtableAttached) { + typeInfo + } else { + val vtable = vtable(irClass) + Struct(typeInfo, vtable) + } + + typeInfoGlobal.setInitializer(typeInfoGlobalValue) + typeInfoGlobal.setConstant(true) + + exportTypeInfoIfRequired(irClass, irClass.llvmTypeInfoPtr) + } + + private fun getObjOffsets(bodyType: LLVMTypeRef): List = + getStructElements(bodyType).mapIndexedNotNull { index, type -> + if (isObjectType(type)) { + LLVMOffsetOfElement(llvmTargetData, bodyType, index) + } else { + null + } + }.map { Int32(it.toInt()) } + + fun vtable(irClass: IrClass): ConstArray { + // TODO: compile-time resolution limits binary compatibility. + val vtableEntries = context.getLayoutBuilder(irClass).vtableEntries.map { + val implementation = it.implementation + if (implementation == null || implementation.isExternalObjCClassMethod() || context.referencedFunctions?.contains(implementation) == false) { + NullPointer(int8Type) + } else { + implementation.entryPointAddress + } + } + return ConstArray(int8TypePtr, vtableEntries) + } + + fun methodTableRecords(irClass: IrClass): List { + val functionNames = mutableMapOf() + return context.getLayoutBuilder(irClass).methodTableEntries.map { + val functionName = it.overriddenFunction.functionName + val nameSignature = functionName.localHash + val previous = functionNames.putIfAbsent(nameSignature.value, it) + if (previous != null) + throw AssertionError("Duplicate method table entry: functionName = '$functionName', hash = '${nameSignature.value}', entry1 = $previous, entry2 = $it") + + // TODO: compile-time resolution limits binary compatibility. + val implementation = it.implementation + val methodEntryPoint = + if (implementation == null || context.referencedFunctions?.contains(implementation) == false) + null + else implementation.entryPointAddress + MethodTableRecord(nameSignature, methodEntryPoint) + }.sortedBy { it.nameSignature.value } + } + + fun interfaceTableRecords(irClass: IrClass): Pair, Int> { + // The details are in ClassLayoutBuilder. + val interfaces = irClass.implementedInterfaces + val (interfaceTableSkeleton, interfaceTableSize) = interfaceTableSkeleton(interfaces) + + val interfaceTableEntries = interfaceTableRecords(irClass, interfaceTableSkeleton) + return Pair(interfaceTableEntries, interfaceTableSize) + } + + private fun interfaceTableSkeleton(interfaces: List): Pair, Int> { + val interfaceLayouts = interfaces.map { context.getLayoutBuilder(it) } + val interfaceColors = interfaceLayouts.map { it.hierarchyInfo.interfaceColor } + + // Find the optimal size. It must be a power of 2. + var size = 1 + val maxSize = 1 shl ClassGlobalHierarchyInfo.MAX_BITS_PER_COLOR + val used = BooleanArray(maxSize) + while (size <= maxSize) { + for (i in 0 until size) + used[i] = false + // Check for collisions. + var ok = true + for (color in interfaceColors) { + val index = color % size + if (used[index]) { + ok = false + break + } + used[index] = true + } + if (ok) break + size *= 2 + } + val conservative = size > maxSize + + val interfaceTableSkeleton = if (conservative) { + size = interfaceLayouts.size + interfaceLayouts.sortedBy { it.hierarchyInfo.interfaceId }.toTypedArray() + } else arrayOfNulls(size).also { + for (interfaceLayout in interfaceLayouts) + it[interfaceLayout.hierarchyInfo.interfaceId % size] = interfaceLayout + } + + val interfaceTableSize = if (conservative) -size else (size - 1) + return Pair(interfaceTableSkeleton, interfaceTableSize) + } + + private fun interfaceTableRecords( + irClass: IrClass, + interfaceTableSkeleton: Array + ): List { + val methodTableEntries = context.getLayoutBuilder(irClass).methodTableEntries + val className = irClass.fqNameForIrSerialization + + return interfaceTableSkeleton.map { iface -> + val interfaceId = iface?.hierarchyInfo?.interfaceId ?: 0 + InterfaceTableRecord( + Int32(interfaceId), + Int32(iface?.interfaceTableEntries?.size ?: 0), + if (iface == null) + NullPointer(kInt8Ptr) + else { + val vtableEntries = iface.interfaceTableEntries.map { ifaceFunction -> + val impl = OverriddenFunctionInfo( + methodTableEntries.first { ifaceFunction in it.function.allOverriddenFunctions }.function, + ifaceFunction + ).implementation + if (impl == null || context.referencedFunctions?.contains(impl) == false) + NullPointer(int8Type) + else impl.entryPointAddress + } + + staticData.placeGlobalConstArray("kifacevtable:${className}_$interfaceId", + kInt8Ptr, vtableEntries + ) + } + ) + } + } + + private fun mapRuntimeType(type: LLVMTypeRef): Int = + runtimeTypeMap[type] ?: throw Error("Unmapped type: ${llvmtype2string(type)}") + + private val debugRuntimeOrNull: LLVMModuleRef? by lazy { + context.config.runtimeNativeLibraries.singleOrNull { it.endsWith("debug.bc")}?.let { + parseBitcodeFile(it) + } + } + + private val debugOperations: ConstValue by lazy { + if (debugRuntimeOrNull != null) { + val external = LLVMGetNamedGlobal(debugRuntimeOrNull, "Konan_debugOperationsList")!! + val local = LLVMAddGlobal(context.llvmModule, LLVMGetElementType(LLVMTypeOf(external)),"Konan_debugOperationsList")!! + constPointer(LLVMConstBitCast(local, kInt8PtrPtr)!!) + } else { + Zero(kInt8PtrPtr) + } + } + + val debugOperationsSize: ConstValue by lazy { + if (debugRuntimeOrNull != null) { + val external = LLVMGetNamedGlobal(debugRuntimeOrNull, "Konan_debugOperationsList")!! + Int32(LLVMGetArrayLength(LLVMGetElementType(LLVMTypeOf(external)))) + } else + Int32(0) + } + + private fun makeExtendedInfo(irClass: IrClass): ConstPointer { + // TODO: shall we actually do that? + if (context.shouldOptimize()) + return NullPointer(runtime.extendedTypeInfoType) + + val className = irClass.fqNameForIrSerialization.toString() + val llvmDeclarations = context.llvmDeclarations.forClass(irClass) + val bodyType = llvmDeclarations.bodyType + val elementType = getElementType(irClass) + + val value = if (elementType != null) { + // An array type. + val runtimeElementType = mapRuntimeType(elementType) + Struct(runtime.extendedTypeInfoType, + Int32(-runtimeElementType), + NullPointer(int32Type), NullPointer(int8Type), NullPointer(kInt8Ptr), + debugOperationsSize, debugOperations) + } else { + data class FieldRecord(val offset: Int, val type: Int, val name: String) + val fields = getStructElements(bodyType).drop(1).mapIndexed { index, type -> + FieldRecord( + LLVMOffsetOfElement(llvmTargetData, bodyType, index + 1).toInt(), + mapRuntimeType(type), + context.getLayoutBuilder(irClass).fields[index].name.asString()) + } + val offsetsPtr = staticData.placeGlobalConstArray("kextoff:$className", int32Type, + fields.map { Int32(it.offset) }) + val typesPtr = staticData.placeGlobalConstArray("kexttype:$className", int8Type, + fields.map { Int8(it.type.toByte()) }) + val namesPtr = staticData.placeGlobalConstArray("kextname:$className", kInt8Ptr, + fields.map { staticData.placeCStringLiteral(it.name) }) + + Struct(runtime.extendedTypeInfoType, Int32(fields.size), offsetsPtr, typesPtr, namesPtr, + debugOperationsSize, debugOperations) + + } + val result = staticData.placeGlobal("", value) + result.setConstant(true) + return result.pointer + } + + private fun genAssociatedObjects(irClass: IrClass): ConstPointer? { + val associatedObjects = context.getLayoutBuilder(irClass).associatedObjects + if (associatedObjects.isEmpty()) { + return null + } + + val associatedObjectTableRecords = associatedObjects.map { (key, value) -> + val associatedObjectGetter = generateFunction( + CodeGenerator(context), + functionType(kObjHeaderPtr, false, kObjHeaderPtrPtr), + "" + ) { + ret(getObjectValue(value, ExceptionHandler.Caller, startLocationInfo = null)) + } + + Struct(runtime.associatedObjectTableRecordType, key.typeInfoPtr, constPointer(associatedObjectGetter)) + } + + return staticData.placeGlobalConstArray( + name = "kassociatedobjects:${irClass.fqNameForIrSerialization}", + elemType = runtime.associatedObjectTableRecordType, + elements = associatedObjectTableRecords + Struct(runtime.associatedObjectTableRecordType, null, null) + ) + } + + // TODO: extract more code common with generate(). + fun generateSyntheticInterfaceImpl( + irClass: IrClass, + methodImpls: Map, + bodyType: LLVMTypeRef, + immutable: Boolean = false + ): ConstPointer { + assert(irClass.isInterface) + + val size = LLVMStoreSizeOfType(llvmTargetData, bodyType).toInt() + + val superClass = context.ir.symbols.any.owner + + assert(superClass.implementedInterfaces.isEmpty()) + val interfaces = (listOf(irClass) + irClass.implementedInterfaces) + val interfacesPtr = staticData.placeGlobalConstArray("", + pointerType(runtime.typeInfoType), interfaces.map { it.typeInfoPtr }) + + assert(superClass.declarations.all { it !is IrProperty && it !is IrField }) + + val objOffsets = getObjOffsets(bodyType) + val objOffsetsPtr = staticData.placeGlobalConstArray("", int32Type, objOffsets) + val objOffsetsCount = objOffsets.size + + val methods = (methodTableRecords(superClass) + methodImpls.map { (method, impl) -> + assert(method.parent == irClass) + MethodTableRecord(method.functionName.localHash, impl.bitcast(int8TypePtr)) + }).sortedBy { it.nameSignature.value }.also { + assert(it.distinctBy { it.nameSignature.value } == it) + } + + val methodsPtr = staticData.placeGlobalConstArray("", runtime.methodTableRecordType, methods) + + val reflectionInfo = ReflectionInfo(null, null) + + val writableTypeInfoType = runtime.writableTypeInfoType + val writableTypeInfo = if (writableTypeInfoType == null) { + null + } else { + staticData.createGlobal(writableTypeInfoType, "") + .also { it.setZeroInitializer() } + .pointer + } + val vtable = vtable(superClass) + val typeInfoWithVtableType = structType(runtime.typeInfoType, vtable.llvmType) + val typeInfoWithVtableGlobal = staticData.createGlobal(typeInfoWithVtableType, "", isExported = false) + val result = typeInfoWithVtableGlobal.pointer.getElementPtr(0) + val typeHierarchyInfo = if (!context.ghaEnabled()) + ClassGlobalHierarchyInfo.DUMMY + else + ClassGlobalHierarchyInfo(-1, -1, 0, 0) + + // TODO: interfaces (e.g. FunctionN and Function) should have different colors. + val (interfaceTableSkeleton, interfaceTableSize) = + if (context.ghaEnabled()) interfaceTableSkeleton(interfaces) else Pair(emptyArray(), -1) + + val interfaceTable = interfaceTableSkeleton.map { layoutBuilder -> + if (layoutBuilder == null) { + InterfaceTableRecord(Int32(0), Int32(0), null) + } else { + val vtableEntries = layoutBuilder.interfaceTableEntries.map { methodImpls[it]!!.bitcast(int8TypePtr) } + val interfaceVTable = staticData.placeGlobalArray("", kInt8Ptr, vtableEntries) + InterfaceTableRecord( + Int32(layoutBuilder.hierarchyInfo.interfaceId), + Int32(layoutBuilder.interfaceTableEntries.size), + interfaceVTable.pointer.getElementPtr(0) + ) + } + } + val interfaceTablePtr = staticData.placeGlobalConstArray("", runtime.interfaceTableRecordType, interfaceTable) + + val typeInfoWithVtable = Struct(TypeInfo( + selfPtr = result, + extendedInfo = NullPointer(runtime.extendedTypeInfoType), + size = size, + superType = superClass.typeInfoPtr, + objOffsets = objOffsetsPtr, objOffsetsCount = objOffsetsCount, + interfaces = interfacesPtr, interfacesCount = interfaces.size, + methods = methodsPtr, methodsCount = methods.size, + interfaceTableSize = interfaceTableSize, interfaceTable = interfaceTablePtr, + packageName = reflectionInfo.packageName, + relativeName = reflectionInfo.relativeName, + flags = flagsFromClass(irClass) or (if (immutable) TF_IMMUTABLE else 0), + classId = typeHierarchyInfo.classIdLo, + writableTypeInfo = writableTypeInfo, + associatedObjects = null + ), vtable) + + typeInfoWithVtableGlobal.setInitializer(typeInfoWithVtable) + typeInfoWithVtableGlobal.setConstant(true) + + return result + } + + private val OverriddenFunctionInfo.implementation get() = getImplementation(context) + + data class ReflectionInfo(val packageName: String?, val relativeName: String?) + + private fun getReflectionInfo(irClass: IrClass): ReflectionInfo = when { + irClass.isAnonymousObject -> ReflectionInfo(packageName = null, relativeName = null) + + irClass.isLocal -> ReflectionInfo(packageName = null, relativeName = irClass.name.asString()) + + else -> ReflectionInfo( + packageName = irClass.findPackage().fqNameForIrSerialization.asString(), + relativeName = generateSequence(irClass) { it.parent as? IrClass } + .toList().reversed() + .joinToString(".") { it.name.asString() } + ) + } + + fun dispose() { + debugRuntimeOrNull?.let { LLVMDisposeModule(it) } + } +} + +// Keep in sync with Konan_TypeFlags in TypeInfo.h. +private const val TF_IMMUTABLE = 1 +private const val TF_ACYCLIC = 2 +private const val TF_INTERFACE = 4 +private const val TF_OBJC_DYNAMIC = 8 +private const val TF_LEAK_DETECTOR_CANDIDATE = 16 +private const val TF_SUSPEND_FUNCTION = 32 +private const val TF_HAS_FINALIZER = 64 + diff --git a/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/RetainAnnotation.kt b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/RetainAnnotation.kt new file mode 100644 index 00000000000..87594ecc93f --- /dev/null +++ b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/RetainAnnotation.kt @@ -0,0 +1,22 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +package org.jetbrains.kotlin.backend.konan.llvm + +import org.jetbrains.kotlin.backend.konan.descriptors.getAnnotationStringValue +import org.jetbrains.kotlin.ir.declarations.IrFunction +import org.jetbrains.kotlin.ir.util.findAnnotation +import org.jetbrains.kotlin.konan.target.KonanTarget +import org.jetbrains.kotlin.name.FqName + +private val retainAnnotationName = FqName("kotlin.native.Retain") +private val retainForTargetAnnotationName = FqName("kotlin.native.RetainForTarget") + +internal fun IrFunction.retainAnnotation(target: KonanTarget): Boolean { + if (this.annotations.findAnnotation(retainAnnotationName) != null) return true + val forTarget = this.annotations.findAnnotation(retainForTargetAnnotationName) + if (forTarget != null && forTarget.getAnnotationStringValue() == target.name) return true + return false +} diff --git a/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/Runtime.kt b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/Runtime.kt new file mode 100644 index 00000000000..15b890aa1da --- /dev/null +++ b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/Runtime.kt @@ -0,0 +1,61 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +package org.jetbrains.kotlin.backend.konan.llvm + +import kotlinx.cinterop.* +import llvm.* +import org.jetbrains.kotlin.ir.types.IrType +import org.jetbrains.kotlin.ir.declarations.IrFunction + +interface RuntimeAware { + val runtime: Runtime +} + +class Runtime(bitcodeFile: String) { + val llvmModule: LLVMModuleRef = parseBitcodeFile(bitcodeFile) + val calculatedLLVMTypes: MutableMap = HashMap() + val addedLLVMExternalFunctions: MutableMap = HashMap() + + internal fun getStructTypeOrNull(name: String) = LLVMGetTypeByName(llvmModule, "struct.$name") + internal fun getStructType(name: String) = getStructTypeOrNull(name) + ?: throw Error("struct.$name is not found in the Runtime module.") + + val typeInfoType = getStructType("TypeInfo") + val extendedTypeInfoType = getStructType("ExtendedTypeInfo") + val writableTypeInfoType = getStructTypeOrNull("WritableTypeInfo") + val methodTableRecordType = getStructType("MethodTableRecord") + val interfaceTableRecordType = getStructType("InterfaceTableRecord") + val globalHashType = getStructType("GlobalHash") + val associatedObjectTableRecordType = getStructType("AssociatedObjectTableRecord") + + val objHeaderType = getStructType("ObjHeader") + val objHeaderPtrType = pointerType(objHeaderType) + val objHeaderPtrPtrType = pointerType(objHeaderType) + val arrayHeaderType = getStructType("ArrayHeader") + + val frameOverlayType = getStructType("FrameOverlay") + + val target = LLVMGetTarget(llvmModule)!!.toKString() + + val dataLayout = LLVMGetDataLayout(llvmModule)!!.toKString() + + val targetData = LLVMCreateTargetData(dataLayout)!! + + val kotlinObjCClassInfo by lazy { getStructType("KotlinObjCClassInfo") } + val objCMethodDescription by lazy { getStructType("ObjCMethodDescription") } + val objCTypeAdapter by lazy { getStructType("ObjCTypeAdapter") } + val objCToKotlinMethodAdapter by lazy { getStructType("ObjCToKotlinMethodAdapter") } + val kotlinToObjCMethodAdapter by lazy { getStructType("KotlinToObjCMethodAdapter") } + val typeInfoObjCExportAddition by lazy { getStructType("TypeInfoObjCExportAddition") } + + val pointerSize: Int by lazy { + LLVMABISizeOfType(targetData, objHeaderPtrType).toInt() + } + + val pointerAlignment: Int by lazy { + LLVMABIAlignmentOfType(targetData, objHeaderPtrType) + } +} diff --git a/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/StaticData.kt b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/StaticData.kt new file mode 100644 index 00000000000..8b27ff9bebc --- /dev/null +++ b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/StaticData.kt @@ -0,0 +1,178 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +package org.jetbrains.kotlin.backend.konan.llvm + +import llvm.* +import org.jetbrains.kotlin.backend.konan.Context +import org.jetbrains.kotlin.ir.expressions.IrConst + +/** + * Provides utilities to create static data. + */ +internal class StaticData(override val context: Context): ContextUtils { + + /** + * Represents the LLVM global variable. + */ + class Global private constructor(val staticData: StaticData, val llvmGlobal: LLVMValueRef) { + companion object { + + private fun createLlvmGlobal(module: LLVMModuleRef, + type: LLVMTypeRef, + name: String, + isExported: Boolean + ): LLVMValueRef { + + if (isExported && LLVMGetNamedGlobal(module, name) != null) { + throw IllegalArgumentException("Global '$name' already exists") + } + + // Globals created with this API are *not* thread local. + val llvmGlobal = LLVMAddGlobal(module, type, name)!! + + if (!isExported) { + LLVMSetLinkage(llvmGlobal, LLVMLinkage.LLVMInternalLinkage) + } + + return llvmGlobal + } + + fun create(staticData: StaticData, type: LLVMTypeRef, name: String, isExported: Boolean): Global { + val module = staticData.context.llvmModule + + val isUnnamed = (name == "") // LLVM will select the unique index and represent the global as `@idx`. + if (isUnnamed && isExported) { + throw IllegalArgumentException("unnamed global can't be exported") + } + + val llvmGlobal = createLlvmGlobal(module!!, type, name, isExported) + return Global(staticData, llvmGlobal) + } + } + + val type get() = getGlobalType(this.llvmGlobal) + + fun setInitializer(value: ConstValue) { + LLVMSetInitializer(llvmGlobal, value.llvm) + } + + fun setZeroInitializer() { + LLVMSetInitializer(llvmGlobal, LLVMConstNull(this.type)!!) + } + + fun setConstant(value: Boolean) { + LLVMSetGlobalConstant(llvmGlobal, if (value) 1 else 0) + } + + fun setLinkage(value: LLVMLinkage) { + LLVMSetLinkage(llvmGlobal, value) + } + + fun setAlignment(value: Int) { + LLVMSetAlignment(llvmGlobal, value) + } + + fun setSection(name: String) { + LLVMSetSection(llvmGlobal, name) + } + + val pointer = Pointer.to(this) + } + + /** + * Represents the pointer to static data. + * It can be a pointer to either a global or any its element. + * + * TODO: this class is probably should be implemented more optimally + */ + class Pointer private constructor(val global: Global, + private val delegate: ConstPointer, + val offsetInGlobal: Long) : ConstPointer by delegate { + + companion object { + fun to(global: Global) = Pointer(global, constPointer(global.llvmGlobal), 0L) + } + + private fun getElementOffset(index: Int): Long { + val llvmTargetData = global.staticData.llvmTargetData + val type = LLVMGetElementType(delegate.llvmType) + return when (LLVMGetTypeKind(type)) { + LLVMTypeKind.LLVMStructTypeKind -> LLVMOffsetOfElement(llvmTargetData, type, index) + LLVMTypeKind.LLVMArrayTypeKind -> LLVMABISizeOfType(llvmTargetData, LLVMGetElementType(type)) * index + else -> TODO() + } + } + + override fun getElementPtr(index: Int): Pointer { + return Pointer(global, delegate.getElementPtr(index), offsetInGlobal + this.getElementOffset(index)) + } + + /** + * @return the distance from other pointer to this. + * + * @throws UnsupportedOperationException if it is not possible to represent the distance as [Int] value + */ + fun sub(other: Pointer): Int { + if (this.global != other.global) { + throw UnsupportedOperationException("pointers must belong to the same global") + } + + val res = this.offsetInGlobal - other.offsetInGlobal + if (res.toInt().toLong() != res) { + throw UnsupportedOperationException("result doesn't fit into Int") + } + + return res.toInt() + } + } + + /** + * Creates [Global] with given type and name. + * + * It is external until explicitly initialized with [Global.setInitializer]. + */ + fun createGlobal(type: LLVMTypeRef, name: String, isExported: Boolean = false): Global { + return Global.create(this, type, name, isExported) + } + + /** + * Creates [Global] with given name and value. + */ + fun placeGlobal(name: String, initializer: ConstValue, isExported: Boolean = false): Global { + val global = createGlobal(initializer.llvmType, name, isExported) + global.setInitializer(initializer) + return global + } + + /** + * Creates array-typed global with given name and value. + */ + fun placeGlobalArray(name: String, elemType: LLVMTypeRef?, elements: List, isExported: Boolean = false): Global { + val initializer = ConstArray(elemType, elements) + val global = placeGlobal(name, initializer, isExported) + + return global + } + + private val stringLiterals = mutableMapOf() + private val cStringLiterals = mutableMapOf() + + fun cStringLiteral(value: String) = + cStringLiterals.getOrPut(value) { placeCStringLiteral(value) } + + fun kotlinStringLiteral(value: String) = + stringLiterals.getOrPut(value) { createKotlinStringLiteral(value) } +} + +/** + * Creates static instance of `konan.ImmutableByteArray` with given values of elements. + * + * @param args data for constant creation. + */ +internal fun StaticData.createImmutableBlob(value: IrConst): LLVMValueRef { + val args = value.value.map { Int8(it.toByte()).llvm } + return createConstKotlinArray(context.ir.symbols.immutableBlob.owner, args) +} \ No newline at end of file diff --git a/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/StaticDataUtils.kt b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/StaticDataUtils.kt new file mode 100644 index 00000000000..978dda08df6 --- /dev/null +++ b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/StaticDataUtils.kt @@ -0,0 +1,38 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +package org.jetbrains.kotlin.backend.konan.llvm + +import llvm.* + +/** + * Creates const array-typed global with given name and value. + * Returns pointer to the first element of the array. + * + * If [elements] is empty, then null pointer is returned. + */ +internal fun StaticData.placeGlobalConstArray(name: String, + elemType: LLVMTypeRef, + elements: List, + isExported: Boolean = false): ConstPointer { + if (elements.isNotEmpty() || isExported) { + val global = this.placeGlobalArray(name, elemType, elements, isExported) + global.setConstant(true) + return global.pointer.getElementPtr(0) + } else { + return NullPointer(elemType) + } +} + +internal fun StaticData.createAlias(name: String, aliasee: ConstPointer): ConstPointer { + val alias = LLVMAddAlias(context.llvmModule, aliasee.llvmType, aliasee.llvm, name)!! + return constPointer(alias) +} + +internal fun StaticData.placeCStringLiteral(value: String): ConstPointer { + val chars = value.toByteArray(Charsets.UTF_8).map { Int8(it) } + Int8(0) + + return placeGlobalConstArray("", int8Type, chars) +} \ No newline at end of file diff --git a/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/StaticObjects.kt b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/StaticObjects.kt new file mode 100644 index 00000000000..052543a1b73 --- /dev/null +++ b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/StaticObjects.kt @@ -0,0 +1,131 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +package org.jetbrains.kotlin.backend.konan.llvm + +import kotlinx.cinterop.cValuesOf +import llvm.* +import org.jetbrains.kotlin.backend.konan.ir.llvmSymbolOrigin +import org.jetbrains.kotlin.ir.declarations.IrClass + +private fun ConstPointer.add(index: Int): ConstPointer { + return constPointer(LLVMConstGEP(llvm, cValuesOf(Int32(index).llvm), 1)!!) +} + +// Must match OBJECT_TAG_PERMANENT_CONTAINER in C++. +private fun StaticData.permanentTag(typeInfo: ConstPointer): ConstPointer { + // Only pointer arithmetic via GEP works on constant pointers in LLVM. + return typeInfo.bitcast(int8TypePtr).add(1).bitcast(kTypeInfoPtr) +} + +private fun StaticData.objHeader(typeInfo: ConstPointer): Struct { + return Struct(runtime.objHeaderType, permanentTag(typeInfo)) +} + +private fun StaticData.arrayHeader(typeInfo: ConstPointer, length: Int): Struct { + assert (length >= 0) + return Struct(runtime.arrayHeaderType, permanentTag(typeInfo), Int32(length)) +} + +internal fun StaticData.createKotlinStringLiteral(value: String): ConstPointer { + val elements = value.toCharArray().map(::Char16) + val objRef = createConstKotlinArray(context.ir.symbols.string.owner, elements) + return objRef +} + +private fun StaticData.createRef(objHeaderPtr: ConstPointer) = objHeaderPtr.bitcast(kObjHeaderPtr) + +internal fun StaticData.createConstKotlinArray(arrayClass: IrClass, elements: List) = + createConstKotlinArray(arrayClass, elements.map { constValue(it) }).llvm + +internal fun StaticData.createConstKotlinArray(arrayClass: IrClass, elements: List): ConstPointer { + val typeInfo = arrayClass.typeInfoPtr + + val bodyElementType: LLVMTypeRef = elements.firstOrNull()?.llvmType ?: int8Type + // (use [0 x i8] as body if there are no elements) + val arrayBody = ConstArray(bodyElementType, elements) + + val compositeType = structType(runtime.arrayHeaderType, arrayBody.llvmType) + + val global = this.createGlobal(compositeType, "") + + val objHeaderPtr = global.pointer.getElementPtr(0) + val arrayHeader = arrayHeader(typeInfo, elements.size) + + global.setInitializer(Struct(compositeType, arrayHeader, arrayBody)) + global.setConstant(true) + + return createRef(objHeaderPtr) +} + +internal fun StaticData.createConstKotlinObject(type: IrClass, vararg fields: ConstValue): ConstPointer { + val typeInfo = type.typeInfoPtr + val objHeader = objHeader(typeInfo) + + val global = this.placeGlobal("", Struct(objHeader, *fields)) + global.setConstant(true) + + val objHeaderPtr = global.pointer.getElementPtr(0) + + return createRef(objHeaderPtr) +} + +internal fun StaticData.createInitializer(type: IrClass, vararg fields: ConstValue): ConstValue = + Struct(objHeader(type.typeInfoPtr), *fields) + +/** + * Creates static instance of `kotlin.collections.ArrayList` with given values of fields. + * + * @param array value for `array: Array` field. + * @param length value for `length: Int` field. + */ +internal fun StaticData.createConstArrayList(array: ConstPointer, length: Int): ConstPointer { + val arrayListClass = context.ir.symbols.arrayList.owner + + val arrayListFields = mapOf( + "array" to array, + "offset" to Int32(0), + "length" to Int32(length), + "backing" to NullPointer(kObjHeader)) + + // Now sort these values according to the order of fields returned by getFields() + // to match the sorting order of the real ArrayList(). + val sorted = mutableListOf() + context.getLayoutBuilder(arrayListClass).fields.forEach { + require (it.parent == arrayListClass) + sorted.add(arrayListFields[it.name.asString()]!!) + } + + return createConstKotlinObject(arrayListClass, *sorted.toTypedArray()) +} + +internal fun StaticData.createUniqueInstance( + kind: UniqueKind, bodyType: LLVMTypeRef, typeInfo: ConstPointer): ConstPointer { + assert (getStructElements(bodyType).size == 1) // ObjHeader only. + val objHeader = when (kind) { + UniqueKind.UNIT -> objHeader(typeInfo) + UniqueKind.EMPTY_ARRAY -> arrayHeader(typeInfo, 0) + } + val global = this.placeGlobal(kind.llvmName, objHeader, isExported = true) + global.setConstant(true) + return global.pointer +} + +internal fun ContextUtils.unique(kind: UniqueKind): ConstPointer { + val descriptor = when (kind) { + UniqueKind.UNIT -> context.ir.symbols.unit.owner + UniqueKind.EMPTY_ARRAY -> context.ir.symbols.array.owner + } + return if (isExternal(descriptor)) { + constPointer(importGlobal( + kind.llvmName, context.llvm.runtime.objHeaderType, origin = descriptor.llvmSymbolOrigin + )) + } else { + context.llvmDeclarations.forUnique(kind).pointer + } +} + +internal val ContextUtils.theUnitInstanceRef: ConstPointer + get() = this.unique(UniqueKind.UNIT) \ No newline at end of file diff --git a/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/VariableManager.kt b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/VariableManager.kt new file mode 100644 index 00000000000..74c27b5fdcb --- /dev/null +++ b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/VariableManager.kt @@ -0,0 +1,171 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +package org.jetbrains.kotlin.backend.konan.llvm + +import llvm.* +import org.jetbrains.kotlin.backend.common.ir.ir2string +import org.jetbrains.kotlin.backend.konan.Context +import org.jetbrains.kotlin.ir.IrElement +import org.jetbrains.kotlin.ir.declarations.IrValueDeclaration +import org.jetbrains.kotlin.ir.declarations.IrVariable +import org.jetbrains.kotlin.name.Name + +internal fun IrElement.needDebugInfo(context: Context) = context.shouldContainDebugInfo() || (this is IrVariable && this.isVar) + +internal class VariableManager(val functionGenerationContext: FunctionGenerationContext) { + internal interface Record { + fun load() : LLVMValueRef + fun store(value: LLVMValueRef) + fun address() : LLVMValueRef + } + + inner class SlotRecord(val address: LLVMValueRef, val refSlot: Boolean, val isVar: Boolean) : Record { + override fun load() : LLVMValueRef = functionGenerationContext.loadSlot(address, isVar) + override fun store(value: LLVMValueRef) { + functionGenerationContext.storeAny(value, address, true) + } + override fun address() : LLVMValueRef = this.address + override fun toString() = (if (refSlot) "refslot" else "slot") + " for ${address}" + } + + inner class ParameterRecord(val address: LLVMValueRef, val refSlot: Boolean) : Record { + override fun load() : LLVMValueRef = functionGenerationContext.loadSlot(address, false) + override fun store(value: LLVMValueRef) = functionGenerationContext.store(value, address) + override fun address() : LLVMValueRef = this.address + override fun toString() = (if (refSlot) "refslot" else "slot") + " for ${address}" + } + + class ValueRecord(val value: LLVMValueRef, val name: Name) : Record { + override fun load() : LLVMValueRef = value + override fun store(value: LLVMValueRef) = throw Error("writing to immutable: ${name}") + override fun address() : LLVMValueRef = throw Error("no address for: ${name}") + override fun toString() = "value of ${value} from ${name}" + } + + val variables: ArrayList = arrayListOf() + val contextVariablesToIndex: HashMap = hashMapOf() + + // Clears inner state of variable manager. + fun clear() { + skipSlots = 0 + variables.clear() + contextVariablesToIndex.clear() + } + + fun createVariable(valueDeclaration: IrValueDeclaration, value: LLVMValueRef? = null, variableLocation: VariableDebugLocation?) : Int { + val isVar = valueDeclaration is IrVariable && valueDeclaration.isVar + // Note that we always create slot for object references for memory management. + if (!functionGenerationContext.context.shouldContainDebugInfo() && !isVar && value != null) + return createImmutable(valueDeclaration, value) + else + // Unfortunately, we have to create mutable slots here, + // as even vals can be assigned on multiple paths. However, we use varness + // knowledge, as anonymous slots are created only for true vars (for vals + // their single assigner already have slot). + return createMutable(valueDeclaration, isVar, value, variableLocation) + } + + internal fun createMutable(valueDeclaration: IrValueDeclaration, + isVar: Boolean, value: LLVMValueRef? = null, variableLocation: VariableDebugLocation?) : Int { + assert(!contextVariablesToIndex.contains(valueDeclaration)) + val index = variables.size + val type = functionGenerationContext.getLLVMType(valueDeclaration.type) + val slot = functionGenerationContext.alloca(type, valueDeclaration.name.asString(), variableLocation) + if (value != null) + functionGenerationContext.storeAny(value, slot, true) + variables.add(SlotRecord(slot, functionGenerationContext.isObjectType(type), isVar)) + contextVariablesToIndex[valueDeclaration] = index + return index + } + + internal var skipSlots = 0 + internal fun createParameter(valueDeclaration: IrValueDeclaration, variableLocation: VariableDebugLocation?) : Int { + assert(!contextVariablesToIndex.contains(valueDeclaration)) + val index = variables.size + val type = functionGenerationContext.getLLVMType(valueDeclaration.type) + val slot = functionGenerationContext.alloca( + type, "p-${valueDeclaration.name.asString()}", variableLocation) + val isObject = functionGenerationContext.isObjectType(type) + variables.add(ParameterRecord(slot, isObject)) + contextVariablesToIndex[valueDeclaration] = index + if (isObject) + skipSlots++ + return index + } + + // Creates anonymous mutable variable. + // Think of slot reuse. + fun createAnonymousSlot(value: LLVMValueRef? = null) : LLVMValueRef { + val index = createAnonymousMutable(functionGenerationContext.kObjHeaderPtr, value) + return addressOf(index) + } + + private fun createAnonymousMutable(type: LLVMTypeRef, value: LLVMValueRef? = null) : Int { + val index = variables.size + val slot = functionGenerationContext.alloca(type, variableLocation = null) + if (value != null) + functionGenerationContext.storeAny(value, slot, true) + variables.add(SlotRecord(slot, functionGenerationContext.isObjectType(type), true)) + return index + } + + internal fun createImmutable(valueDeclaration: IrValueDeclaration, value: LLVMValueRef) : Int { + if (contextVariablesToIndex.containsKey(valueDeclaration)) + throw Error("${ir2string(valueDeclaration)} is already defined") + val index = variables.size + variables.add(ValueRecord(value, valueDeclaration.name)) + contextVariablesToIndex[valueDeclaration] = index + return index + } + + fun indexOf(valueDeclaration: IrValueDeclaration) : Int { + return contextVariablesToIndex.getOrElse(valueDeclaration) { -1 } + } + + fun addressOf(index: Int): LLVMValueRef { + return variables[index].address() + } + + fun load(index: Int): LLVMValueRef { + return variables[index].load() + } + + fun store(value: LLVMValueRef, index: Int) { + variables[index].store(value) + } +} + +internal data class VariableDebugLocation(val localVariable: DILocalVariableRef, val location:DILocationRef?, val file:DIFileRef, val line:Int) + +internal fun debugInfoLocalVariableLocation(builder: DIBuilderRef?, + functionScope: DIScopeOpaqueRef, diType: DITypeOpaqueRef, name:Name, file: DIFileRef, line: Int, + location: DILocationRef?): VariableDebugLocation { + val variableDeclaration = DICreateAutoVariable( + builder = builder, + scope = functionScope, + name = name.asString(), + file = file, + line = line, + type = diType) + + return VariableDebugLocation(localVariable = variableDeclaration!!, location = location, file = file, line = line) +} + +internal fun debugInfoParameterLocation(builder: DIBuilderRef?, + functionScope: DIScopeOpaqueRef, diType: DITypeOpaqueRef, + name:Name, argNo: Int, file: DIFileRef, line: Int, + location: DILocationRef?): VariableDebugLocation { + val variableDeclaration = DICreateParameterVariable( + builder = builder, + scope = functionScope, + name = name.asString(), + argNo = argNo, + file = file, + line = line, + type = diType) + + return VariableDebugLocation(localVariable = variableDeclaration!!, location = location, file = file, line = line) +} diff --git a/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/VerifyModule.kt b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/VerifyModule.kt new file mode 100644 index 00000000000..b67b3bfd674 --- /dev/null +++ b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/VerifyModule.kt @@ -0,0 +1,95 @@ +package org.jetbrains.kotlin.backend.konan.llvm + +import kotlinx.cinterop.* +import llvm.* +import java.io.File + +internal fun verifyModule(llvmModule: LLVMModuleRef, current: String = "") = memScoped { + val errorRef = allocPointerTo() + errorRef.value = null + + val verificationResult = LLVMVerifyModule( + llvmModule, + LLVMVerifierFailureAction.LLVMReturnStatusAction, + errorRef.ptr + ) + + val verificationError = convertAndDisposeLlvmMessage(errorRef.value) + + if (verificationResult != 0) { + throwModuleVerificationError(llvmModule, current, verificationError) + } +} + +private fun throwModuleVerificationError( + llvmModule: LLVMModuleRef, + current: String, + verificationError: String? +): Nothing { + val exceptionMessage = buildString { + try { + appendModuleVerificationFailureDetails(llvmModule, current, verificationError) + } catch (e: Throwable) { + appendLine("Failed to make full error message: ${e.message}") + } + } + + throw Error(exceptionMessage) +} + +private fun StringBuilder.appendModuleVerificationFailureDetails( + llvmModule: LLVMModuleRef, + current: String, + verificationError: String? +) { + appendLine("Invalid LLVM module") + + if (current.isNotEmpty()) + appendLine("Error in $current") + + appendVerificationError(verificationError) + + val moduleDumpFile = createTempFile("kotlin_native_llvm_module_dump", ".ll") + + dumpModuleAndAppendDetails(llvmModule, moduleDumpFile) + + moduleDumpFile.appendText(verificationError.orEmpty()) +} + +private fun StringBuilder.appendVerificationError(error: String?) { + if (error == null) return + + val lines = error.lines() + appendLine("Verification errors:") + + val maxLines = 12 + + lines.take(maxLines).forEach { + appendLine(" $it") + } + + if (lines.size > maxLines) { + appendLine(" ... (full error is available at the LLVM module dump file)") + } +} + +private fun StringBuilder.dumpModuleAndAppendDetails(llvmModule: LLVMModuleRef, moduleDumpFile: File) = memScoped { + val errorRef = allocPointerTo() + errorRef.value = null + val printedWithErrors = LLVMPrintModuleToFile(llvmModule, moduleDumpFile.absolutePath, errorRef.ptr) + + appendLine() + appendLine("LLVM module dump: ${moduleDumpFile.absolutePath}") + + val modulePrintError = convertAndDisposeLlvmMessage(errorRef.value) + if (printedWithErrors != 0) { + appendLine(" (printed with errors: $modulePrintError)") + } +} + +private fun convertAndDisposeLlvmMessage(message: CPointer?): String? = + try { + message?.toKString() + } finally { + LLVMDisposeMessage(message) + } diff --git a/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/coverage/CoverageInformation.kt b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/coverage/CoverageInformation.kt new file mode 100644 index 00000000000..c318cdebaaa --- /dev/null +++ b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/coverage/CoverageInformation.kt @@ -0,0 +1,102 @@ +/* + * Copyright 2010-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ +package org.jetbrains.kotlin.backend.konan.llvm.coverage + +import org.jetbrains.kotlin.backend.common.ir.ir2string +import org.jetbrains.kotlin.backend.konan.llvm.column +import org.jetbrains.kotlin.backend.konan.llvm.line +import org.jetbrains.kotlin.backend.konan.llvm.symbolName +import org.jetbrains.kotlin.ir.IrElement +import org.jetbrains.kotlin.ir.UNDEFINED_OFFSET +import org.jetbrains.kotlin.ir.declarations.IrFile +import org.jetbrains.kotlin.ir.declarations.IrFunction +import org.jetbrains.kotlin.ir.declarations.name + +/** + * The most important class in the coverage package. + * It describes textual region of the code that is associated with IrElement. + * Besides the obvious [file] and line/column borders, it has [RegionKind] which is described later. + */ +class Region( + val startOffset: Int, + val endOffset: Int, + val file: IrFile, + val kind: RegionKind +) { + val startLine: Int + get() = file.fileEntry.line(startOffset) + + val startColumn: Int + get() = file.fileEntry.column(startOffset) + + val endLine: Int + get() = file.fileEntry.line(endOffset) + + val endColumn: Int + get() = file.fileEntry.column(endOffset) + + companion object { + fun fromIr(irElement: IrElement, irFile: IrFile, kind: RegionKind = RegionKind.Code) = + fromOffset(irElement.startOffset, irElement.endOffset, irFile, kind) + + fun fromOffset(startOffset: Int, endOffset: Int, irFile: IrFile, kind: RegionKind = RegionKind.Code) = + if (startOffset == UNDEFINED_OFFSET || endOffset == UNDEFINED_OFFSET || startOffset == endOffset) null + else Region(startOffset, endOffset, irFile, kind) + } + + override fun toString(): String { + val expansion = (kind as? RegionKind.Expansion)?.let { " expand to " + it.expandedFile.name } ?: "" + return "${file.name}$expansion: ${kind::class.simpleName} $startLine, $startColumn -> $endLine, $endColumn" + } +} + +/** + * Describes what is the given code region. + * Based on llvm::coverage::CounterMappingRegion. + * Currently only [RegionKind.Code] is used. + */ +sealed class RegionKind { + /** + * Regular peace of code. + */ + object Code : RegionKind() + /** + * Empty line. + */ + object Gap : RegionKind() + /** + * Region of code that is an expansion of another source file. + * Used for inline function. + */ + class Expansion(val expandedFile: IrFile) : RegionKind() +} + +/** + * "Regional" description of the [function]. + */ +class FunctionRegions( + val function: IrFunction, + val regions: Map +) { + // Enumeration is required for serialization and instrumentation calls. + val regionEnumeration = regions.values.mapIndexed { index, region -> region to index }.toMap() + // Actually, it should be computed. + // But since we don't support PGO structural hash doesn't really matter for now. + val structuralHash: Long = 0 + + override fun toString(): String = buildString { + appendLine("${function.symbolName} regions:") + regions.forEach { (irElem, region) -> appendLine("${ir2string(irElem)} -> ($region)") } + } +} + +/** + * Since file is the biggest unit in terms of the code coverage + * we aggregate [FunctionRegions] per [file]. + */ +class FileRegionInfo( + val file: IrFile, + val functions: List +) \ No newline at end of file diff --git a/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/coverage/CoverageManager.kt b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/coverage/CoverageManager.kt new file mode 100644 index 00000000000..dc3ac8ca1ad --- /dev/null +++ b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/coverage/CoverageManager.kt @@ -0,0 +1,122 @@ +/* + * Copyright 2010-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ +package org.jetbrains.kotlin.backend.konan.llvm.coverage + +import llvm.* +import org.jetbrains.kotlin.backend.konan.* +import org.jetbrains.kotlin.backend.konan.Context +import org.jetbrains.kotlin.backend.konan.reportCompilationError +import org.jetbrains.kotlin.descriptors.ModuleDescriptor +import org.jetbrains.kotlin.ir.declarations.IrFile +import org.jetbrains.kotlin.ir.declarations.IrFunction +import org.jetbrains.kotlin.ir.declarations.IrModuleFragment +import org.jetbrains.kotlin.konan.file.File +import org.jetbrains.kotlin.konan.target.supportsCodeCoverage +import org.jetbrains.kotlin.resolve.descriptorUtil.module + +/** + * "Umbrella" class of all the of the code coverage related logic. + */ +internal class CoverageManager(val context: Context) { + + private val shouldCoverSources: Boolean = + context.config.shouldCoverSources + + private val librariesToCover: Set = + context.config.resolve.coveredLibraries.map { it.libraryName }.toSet() + + private val llvmProfileFilenameGlobal = "__llvm_profile_filename" + + private val defaultOutputFilePath: String by lazy { + "${context.config.outputFile}.profraw" + } + + private val outputFileName: String = + context.config.configuration.get(KonanConfigKeys.PROFRAW_PATH) + ?.let { File(it).absolutePath } + ?: defaultOutputFilePath + + val enabled: Boolean = + shouldCoverSources || librariesToCover.isNotEmpty() + + init { + if (enabled && !checkRestrictions()) { + context.reportCompilationError("Coverage is not supported for ${context.config.target}.") + } + } + + private fun checkRestrictions(): Boolean { + val isKindAllowed = context.config.produce.involvesBitcodeGeneration + val target = context.config.target + val isTargetAllowed = target.supportsCodeCoverage() + return isKindAllowed && isTargetAllowed + } + + private val filesRegionsInfo = mutableListOf() + + private fun getFunctionRegions(irFunction: IrFunction) = + filesRegionsInfo.flatMap { it.functions }.firstOrNull { it.function == irFunction } + + private val coveredModules: Set by lazy { + val coveredUserCode = if (shouldCoverSources) setOf(context.moduleDescriptor) else emptySet() + val coveredLibs = context.irModules.filter { it.key in librariesToCover }.values + .map { it.descriptor }.toSet() + val coveredIncludedLibs = if (shouldCoverSources) context.getIncludedLibraryDescriptors().toSet() else emptySet() + coveredLibs + coveredUserCode + coveredIncludedLibs + } + + private fun fileCoverageFilter(file: IrFile) = + file.packageFragmentDescriptor.module in coveredModules + + /** + * Walk [irModuleFragment] subtree and collect [FileRegionInfo] for files that are part of [coveredModules]. + */ + fun collectRegions(irModuleFragment: IrModuleFragment) { + if (enabled) { + val regions = CoverageRegionCollector(this::fileCoverageFilter).collectFunctionRegions(irModuleFragment) + filesRegionsInfo += regions + } + } + + /** + * @return [LLVMCoverageInstrumentation] instance if [irFunction] should be covered. + */ + fun tryGetInstrumentation(irFunction: IrFunction?, callSitePlacer: (function: LLVMValueRef, args: List) -> Unit) = + if (enabled && irFunction != null) { + getFunctionRegions(irFunction)?.let { LLVMCoverageInstrumentation(context, it, callSitePlacer) } + } else { + null + } + + /** + * Add __llvm_coverage_mapping to the LLVM module. + */ + fun writeRegionInfo() { + if (enabled) { + LLVMCoverageWriter(context, filesRegionsInfo).write() + } + } + + /** + * Add passes that should be executed after main LLVM optimization pipeline. + */ + fun addLateLlvmPasses(passManager: LLVMPassManagerRef) { + if (enabled) { + // It's a late pass since DCE can kill __llvm_profile_filename global. + LLVMAddInstrProfPass(passManager, outputFileName) + } + } + + /** + * Since we performing instruction profiling before internalization and global dce + * __llvm_profile_filename need to be added to exported symbols. + */ + fun addExportedSymbols(): List = + if (enabled) { + listOf(llvmProfileFilenameGlobal) + } else { + emptyList() + } +} \ No newline at end of file diff --git a/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/coverage/CoverageRegionCollector.kt b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/coverage/CoverageRegionCollector.kt new file mode 100644 index 00000000000..f5466a155c4 --- /dev/null +++ b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/coverage/CoverageRegionCollector.kt @@ -0,0 +1,222 @@ +/* + * Copyright 2010-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ +package org.jetbrains.kotlin.backend.konan.llvm.coverage + +import org.jetbrains.kotlin.backend.common.pop +import org.jetbrains.kotlin.backend.common.push +import org.jetbrains.kotlin.ir.IrElement +import org.jetbrains.kotlin.ir.IrStatement +import org.jetbrains.kotlin.ir.UNDEFINED_OFFSET +import org.jetbrains.kotlin.ir.declarations.* +import org.jetbrains.kotlin.ir.expressions.* +import org.jetbrains.kotlin.ir.util.nameForIrSerialization +import org.jetbrains.kotlin.ir.util.statements +import org.jetbrains.kotlin.ir.visitors.IrElementVisitorVoid +import org.jetbrains.kotlin.ir.visitors.acceptChildrenVoid +import org.jetbrains.kotlin.ir.visitors.acceptVoid + +/** + * Collect all regions in the module. + * @param fileFilter filters files that should be processed. + */ +internal class CoverageRegionCollector(private val fileFilter: (IrFile) -> Boolean) { + + fun collectFunctionRegions(irModuleFragment: IrModuleFragment): List = + irModuleFragment.files + .filter(fileFilter) + .map { file -> + val collector = FunctionsCollector(file) + collector.visitFile(file) + FileRegionInfo(file, collector.functionRegions) + } + + private inner class FunctionsCollector(val file: IrFile) : IrElementVisitorVoid { + + val functionRegions = mutableListOf() + + override fun visitElement(element: IrElement) { + element.acceptChildrenVoid(this) + } + + override fun visitFunction(declaration: IrFunction) { + if (!declaration.isInline && !declaration.isExternal && !declaration.isGeneratedByCompiler) { + val regionsCollector = IrFunctionRegionsCollector(fileFilter, file) + declaration.acceptVoid(regionsCollector) + if (regionsCollector.regions.isNotEmpty()) { + functionRegions += FunctionRegions(declaration, regionsCollector.regions) + } + } + // TODO: Decide how to work with local functions. Should they be process separately? + declaration.acceptChildrenVoid(this) + } + } +} + +// User doesn't bother about compiler-generated declarations. +// So lets filter them. +private val IrDeclaration.isGeneratedByCompiler: Boolean + get() { + return origin != IrDeclarationOrigin.DEFINED || nameForIrSerialization.asString() == "Konan_start" + } + +/** + * Very similar to [org.jetbrains.kotlin.backend.konan.llvm.CodeGeneratorVisitor] but instead of bitcode generation we collect regions. + * [fileFilter]: specify which files should be processed by code coverage. Here it is required + * for checking calls to inline functions from other files. + * TODO: for now it is very inaccurate. + */ +private class IrFunctionRegionsCollector( + val fileFilter: (IrFile) -> Boolean, + val irFile: IrFile +) : IrElementVisitorVoid { + + private data class StatementContext(val current: IrStatement, val next: IrStatement?) + + val regions = mutableMapOf() + + private val irFileStack = mutableListOf(irFile) + + private val regionStack = mutableListOf() + + private val irStatementsStack = mutableListOf() + + private val currentFile: IrFile + get() = irFileStack.last() + + private val currentRegion: Region + get() = regionStack.last() + + override fun visitElement(element: IrElement) { + element.acceptChildrenVoid(this) + } + + override fun visitSimpleFunction(declaration: IrSimpleFunction) { + declaration.body?.let { body -> + visitInRegionContext(recordRegion(body) ?: return) { + body.acceptVoid(this) + } + } + } + + override fun visitConstructor(declaration: IrConstructor) { + val statements = declaration.body?.statements ?: return + visitInStatementContext(statements) { statement -> + if (statement is IrDelegatingConstructorCall && !declaration.isPrimary + || statement !is IrDelegatingConstructorCall && statement !is IrReturn) { + recordRegion(statement) + statement.acceptVoid(this) + } + } + } + + override fun visitBody(body: IrBody) = visitInStatementContext(body.statements) + + override fun visitContainerExpression(expression: IrContainerExpression) { + val statements = expression.statements + when (expression) { + is IrReturnableBlock -> { + val file = expression.sourceFileSymbol?.owner + if (file != null && file != currentFile && fileFilter(file)) { + recordRegion(expression) + visitInFileContext(file) { + visitInStatementContext(statements) + } + } + } + else -> visitInStatementContext(statements) + } + } + + // TODO: The following implementation produces correct region mapping, but something goes wrong later + // override fun visitFieldAccess(expression: IrFieldAccessExpression) { + // expression.receiver?.let { recordRegion(it) } + // expression.acceptChildrenVoid(this) + // } + + override fun visitWhen(expression: IrWhen) { + val branches = expression.branches + branches.forEach { + val condition = it.condition + val result = it.result + + if (condition is IrConst<*> && condition.value == true && condition.endOffset == result.endOffset) { + // Probably an 'else' branch. + // Note: can't rely on [IrElseBranch], because IR deserializer doesn't emit it. + recordRegion(result) + } else { + recordRegion(condition) + recordRegion(result, condition.endOffset, result.endOffset) + condition.acceptVoid(this) + } + result.acceptVoid(this) + } + } + + override fun visitLoop(loop: IrLoop) { + val condition = loop.condition + recordRegion(condition) + condition.acceptVoid(this) + + val body = loop.body ?: return + when (loop) { + is IrWhileLoop -> recordRegion(body, condition.endOffset, body.endOffset) + is IrDoWhileLoop -> recordRegion(body, body.startOffset, condition.startOffset) + } + body.acceptVoid(this) + } + + override fun visitBreakContinue(jump: IrBreakContinue) { + val (current, next) = irStatementsStack.lastOrNull() ?: return + recordRegion(next ?: return, current.endOffset, jump.loop.endOffset) + } + + override fun visitReturn(expression: IrReturn) { + irStatementsStack.subList(0, irStatementsStack.lastIndex) + .filter { (current, next) -> next != null && current.endOffset > expression.endOffset } + .forEach { (current, next) -> recordRegion(next!!, expression.endOffset, current.endOffset) } + val next = irStatementsStack.lastOrNull()?.next ?: return + val nextRegion = recordRegion(next, expression.endOffset, currentRegion.endOffset) ?: return + regionStack.pop() + regionStack.push(nextRegion) + } + + private fun visitInFileContext(file: IrFile, visit: () -> Unit) { + irFileStack.push(file) + visit() + irFileStack.pop() + } + + private fun visitInRegionContext(region: Region, visit: () -> Unit) { + regionStack.push(region) + visit() + regionStack.pop() + } + + private fun visitInStatementContext( + statements: List, + visit: (IrStatement) -> Unit = { statement -> statement.acceptVoid(this) } + ) { + for (i in 0..statements.lastIndex) { + val current = statements[i] + if (!current.hasValidOffsets()) { + continue + } + val nextInContext = irStatementsStack.lastOrNull()?.next + val next = if (i < statements.lastIndex && statements[i + 1].hasValidOffsets()) statements[i + 1] else nextInContext + irStatementsStack.push(StatementContext(current, next)) + visit(current) + irStatementsStack.pop() + } + } + + private fun recordRegion(irElement: IrElement, kind: RegionKind = RegionKind.Code) + = Region.fromIr(irElement, currentFile, kind)?.also { regions[irElement] = it } + + private fun recordRegion(irElement: IrElement, startOffset: Int, endOffset: Int, kind: RegionKind = RegionKind.Code) + = Region.fromOffset(startOffset, endOffset, currentFile, kind)?.also { regions[irElement] = it } + + private fun IrElement.hasValidOffsets() = startOffset != UNDEFINED_OFFSET && endOffset != UNDEFINED_OFFSET + && startOffset != endOffset +} \ No newline at end of file diff --git a/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/coverage/LLVMCoverageInstrumentation.kt b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/coverage/LLVMCoverageInstrumentation.kt new file mode 100644 index 00000000000..28ac78e36ed --- /dev/null +++ b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/coverage/LLVMCoverageInstrumentation.kt @@ -0,0 +1,53 @@ +/* + * Copyright 2010-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ +package org.jetbrains.kotlin.backend.konan.llvm.coverage + +import llvm.LLVMConstBitCast +import llvm.LLVMCreatePGOFunctionNameVar +import llvm.LLVMInstrProfIncrement +import llvm.LLVMValueRef +import org.jetbrains.kotlin.backend.konan.Context +import org.jetbrains.kotlin.backend.konan.llvm.* +import org.jetbrains.kotlin.ir.IrElement +import org.jetbrains.kotlin.ir.declarations.IrFunction + +/** + * Places calls to `llvm.instrprof.increment` in the beginning of the each + * region in [functionRegions]. + */ +internal class LLVMCoverageInstrumentation( + override val context: Context, + private val functionRegions: FunctionRegions, + private val callSitePlacer: (function: LLVMValueRef, args: List) -> Unit +) : ContextUtils { + + private val functionNameGlobal = createFunctionNameGlobal(functionRegions.function) + + private val functionHash = Int64(functionRegions.structuralHash).llvm + + // TODO: It's a great place for some debug output. + fun instrumentIrElement(element: IrElement) { + functionRegions.regions[element]?.let { + placeRegionIncrement(it) + } + } + + /** + * See https://llvm.org/docs/LangRef.html#llvm-instrprof-increment-intrinsic + */ + private fun placeRegionIncrement(region: Region) { + val numberOfRegions = Int32(functionRegions.regions.size).llvm + val regionNumber = Int32(functionRegions.regionEnumeration.getValue(region)).llvm + val args = listOf(functionNameGlobal, functionHash, numberOfRegions, regionNumber) + callSitePlacer(LLVMInstrProfIncrement(context.llvmModule)!!, args) + } + + // Each profiled function should have a global with its name in a specific format. + private fun createFunctionNameGlobal(function: IrFunction): LLVMValueRef { + val name = function.llvmFunction.name + val pgoFunctionName = LLVMCreatePGOFunctionNameVar(function.llvmFunction, name)!! + return LLVMConstBitCast(pgoFunctionName, int8TypePtr)!! + } +} \ No newline at end of file diff --git a/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/coverage/LLVMCoverageWriter.kt b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/coverage/LLVMCoverageWriter.kt new file mode 100644 index 00000000000..4e28b9f5fea --- /dev/null +++ b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/coverage/LLVMCoverageWriter.kt @@ -0,0 +1,77 @@ +/* + * Copyright 2010-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ +package org.jetbrains.kotlin.backend.konan.llvm.coverage + +import kotlinx.cinterop.* +import llvm.* +import org.jetbrains.kotlin.backend.konan.Context +import org.jetbrains.kotlin.backend.konan.llvm.name +import org.jetbrains.kotlin.backend.konan.llvm.symbolName +import org.jetbrains.kotlin.ir.declarations.IrFile +import org.jetbrains.kotlin.ir.declarations.name +import org.jetbrains.kotlin.ir.declarations.path +import org.jetbrains.kotlin.konan.file.File + +private fun RegionKind.toLLVMCoverageRegionKind(): LLVMCoverageRegionKind = when (this) { + RegionKind.Code -> LLVMCoverageRegionKind.CODE + RegionKind.Gap -> LLVMCoverageRegionKind.GAP + is RegionKind.Expansion -> LLVMCoverageRegionKind.EXPANSION +} + +private fun LLVMCoverageRegion.populateFrom(region: Region, regionId: Int, filesIndex: Map) = apply { + fileId = filesIndex.getValue(region.file) + lineStart = region.startLine + columnStart = region.startColumn + lineEnd = region.endLine + columnEnd = region.endColumn + counterId = regionId + kind = region.kind.toLLVMCoverageRegionKind() + expandedFileId = if (region.kind is RegionKind.Expansion) filesIndex.getValue(region.kind.expandedFile) else 0 +} + +/** + * Writes all of the coverage information to the [org.jetbrains.kotlin.backend.konan.Context.llvmModule]. + * See http://llvm.org/docs/CoverageMappingFormat.html for the format description. + */ +internal class LLVMCoverageWriter( + private val context: Context, + private val filesRegionsInfo: List +) { + fun write() { + if (filesRegionsInfo.isEmpty()) return + + val module = context.llvmModule + ?: error("LLVM module should be initialized.") + val filesIndex = filesRegionsInfo.mapIndexed { index, fileRegionInfo -> fileRegionInfo.file to index }.toMap() + + val coverageGlobal = memScoped { + val (functionMappingRecords, functionCoverages) = filesRegionsInfo.flatMap { it.functions }.map { functionRegions -> + val regions = (functionRegions.regions.values).map { region -> + alloc().populateFrom(region, functionRegions.regionEnumeration.getValue(region), filesIndex).ptr + } + val fileIds = functionRegions.regions.map { filesIndex.getValue(it.value.file) }.toSet().toIntArray() + val functionCoverage = LLVMWriteCoverageRegionMapping( + fileIds.toCValues(), fileIds.size.signExtend(), + regions.toCValues(), regions.size.signExtend()) + + val functionName = context.llvmDeclarations.forFunction(functionRegions.function).llvmFunction.name + val functionMappingRecord = LLVMAddFunctionMappingRecord(LLVMGetModuleContext(context.llvmModule), + functionName, functionRegions.structuralHash, functionCoverage)!! + + Pair(functionMappingRecord, functionCoverage) + }.unzip() + val (filenames, fileIds) = filesIndex.entries.toList().map { File(it.key.path).absolutePath to it.value }.unzip() + val retval = LLVMCoverageEmit(module, functionMappingRecords.toCValues(), functionMappingRecords.size.signExtend(), + filenames.toCStringArray(this), fileIds.toIntArray().toCValues(), fileIds.size.signExtend(), + functionCoverages.map { it }.toCValues(), functionCoverages.size.signExtend())!! + + // TODO: Is there a better way to cleanup fields of T* type in `memScoped`? + functionCoverages.forEach { LLVMFunctionCoverageDispose(it) } + + retval + } + context.llvm.usedGlobals.add(coverageGlobal) + } +} diff --git a/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/objc/ObjCCodeGenerator.kt b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/objc/ObjCCodeGenerator.kt new file mode 100644 index 00000000000..9b4ecd0a943 --- /dev/null +++ b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/objc/ObjCCodeGenerator.kt @@ -0,0 +1,47 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +package org.jetbrains.kotlin.backend.konan.llvm.objc + +import llvm.LLVMTypeRef +import llvm.LLVMValueRef +import org.jetbrains.kotlin.backend.konan.llvm.* + +internal open class ObjCCodeGenerator(val codegen: CodeGenerator) { + val context = codegen.context + + val dataGenerator = codegen.objCDataGenerator!! + + fun FunctionGenerationContext.genSelector(selector: String): LLVMValueRef = genObjCSelector(selector) + + fun FunctionGenerationContext.genGetLinkedClass(name: String): LLVMValueRef { + val classRef = dataGenerator.genClassRef(name) + return load(classRef.llvm) + } + + private val objcMsgSend = constPointer( + context.llvm.externalFunction( + "objc_msgSend", + functionType(int8TypePtr, true, int8TypePtr, int8TypePtr), + context.stdlibModule.llvmSymbolOrigin + ) + ) + + val objcRelease = context.llvm.externalFunction( + "objc_release", + functionType(voidType, false, int8TypePtr), + context.stdlibModule.llvmSymbolOrigin + ) + + // TODO: this doesn't support stret. + fun msgSender(functionType: LLVMTypeRef): LLVMValueRef = + objcMsgSend.bitcast(pointerType(functionType)).llvm +} + +internal fun FunctionGenerationContext.genObjCSelector(selector: String): LLVMValueRef { + val selectorRef = codegen.objCDataGenerator!!.genSelectorRef(selector) + // TODO: clang emits it with `invariant.load` metadata. + return load(selectorRef.llvm) +} \ No newline at end of file diff --git a/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/objc/ObjCDataGenerator.kt b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/objc/ObjCDataGenerator.kt new file mode 100644 index 00000000000..c80ac89e36a --- /dev/null +++ b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/objc/ObjCDataGenerator.kt @@ -0,0 +1,293 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +package org.jetbrains.kotlin.backend.konan.llvm.objc + +import llvm.* +import org.jetbrains.kotlin.backend.konan.llvm.* +import org.jetbrains.kotlin.descriptors.konan.CurrentKlibModuleOrigin + +/** + * This class provides methods to generate Objective-C RTTI and other data. + * It is mostly based on `clang/lib/CodeGen/CGObjCMac.cpp`, and supports only subset of operations + * required for our purposes (thus simplified). + * + * [finishModule] must be called exactly once after all required data was generated. + */ +internal class ObjCDataGenerator(val codegen: CodeGenerator) { + + val context = codegen.context + + fun finishModule() { + addModuleClassList( + definedClasses, + "OBJC_LABEL_CLASS_$", + "__DATA,__objc_classlist,regular,no_dead_strip" + ) + } + + private val selectorRefs = mutableMapOf() + private val classRefs = mutableMapOf() + + fun genSelectorRef(selector: String): ConstPointer = selectorRefs.getOrPut(selector) { + val literal = selectors.get(selector) + val global = codegen.staticData.placeGlobal("OBJC_SELECTOR_REFERENCES_", literal) + global.setLinkage(LLVMLinkage.LLVMPrivateLinkage) + LLVMSetExternallyInitialized(global.llvmGlobal, 1) + global.setAlignment(codegen.runtime.pointerAlignment) + global.setSection("__DATA,__objc_selrefs,literal_pointers,no_dead_strip") + + context.llvm.compilerUsedGlobals += global.llvmGlobal + + global.pointer + } + + fun genClassRef(name: String): ConstPointer = classRefs.getOrPut(name) { + val classGlobal = getClassGlobal(name, isMetaclass = false) + val global = codegen.staticData.placeGlobal("OBJC_CLASSLIST_REFERENCES_\$_", classGlobal).also { + it.setLinkage(LLVMLinkage.LLVMPrivateLinkage) + it.setSection("__DATA,__objc_classrefs,regular,no_dead_strip") + it.setAlignment(codegen.runtime.pointerAlignment) + } + + context.llvm.compilerUsedGlobals += global.pointer.llvm + + global.pointer.bitcast(pointerType(int8TypePtr)) + } + + val classObjectType = codegen.runtime.getStructType("_class_t") + + fun exportClass(name: String) { + context.llvm.usedGlobals += getClassGlobal(name, isMetaclass = false).llvm + context.llvm.usedGlobals += getClassGlobal(name, isMetaclass = true).llvm + } + + private fun getClassGlobal(name: String, isMetaclass: Boolean): ConstPointer { + val prefix = if (isMetaclass) { + "OBJC_METACLASS_\$_" + } else { + "OBJC_CLASS_\$_" + } + + val globalName = prefix + name + + // TODO: refactor usages and use [Global] class. + val llvmGlobal = LLVMGetNamedGlobal(context.llvmModule, globalName) ?: + codegen.importGlobal(globalName, classObjectType, CurrentKlibModuleOrigin) + + return constPointer(llvmGlobal) + } + + private val emptyCache = constPointer( + codegen.importGlobal( + "_objc_empty_cache", + codegen.runtime.getStructType("_objc_cache"), + CurrentKlibModuleOrigin + ) + ) + + fun emitEmptyClass(name: String, superName: String) { + emitClass(name, superName, instanceMethods = emptyList()) + } + + class Method(val selector: String, val encoding: String, val imp: ConstPointer) + + fun emitClass(name: String, superName: String, instanceMethods: List) { + val runtime = context.llvm.runtime + fun struct(name: String) = runtime.getStructType(name) + + val classRoType = struct("_class_ro_t") + val methodType = struct("_objc_method") + val methodListType = struct("__method_list_t") + val protocolListType = struct("_objc_protocol_list") + val ivarListType = struct("_ivar_list_t") + val propListType = struct("_prop_list_t") + + val classNameLiteral = classNames.get(name) + + fun emitInstanceMethodList(): ConstPointer { + if (instanceMethods.isEmpty()) return NullPointer(methodListType) + + val methodStructs = instanceMethods.map { + Struct(methodType, selectors.get(it.selector), encodings.get(it.encoding), it.imp.bitcast(int8TypePtr)) + } + + val methodList = Struct( + Int32(LLVMABISizeOfType(codegen.llvmTargetData, methodType).toInt()), + Int32(instanceMethods.size), + ConstArray(methodType, methodStructs) + ) + + val globalName = "\u0001l_OBJC_\$_INSTANCE_METHODS_$name" + val global = context.llvm.staticData.placeGlobal(globalName, methodList).also { + it.setLinkage(LLVMLinkage.LLVMPrivateLinkage) + it.setAlignment(runtime.pointerAlignment) + it.setSection("__DATA, __objc_const") + } + + context.llvm.compilerUsedGlobals += global.llvmGlobal + + return global.pointer.bitcast(pointerType(methodListType)) + } + + fun buildClassRo(isMetaclass: Boolean): ConstPointer { + // TODO: add NonFragileABI_Class_CompiledByARC flag? + + val flags: Int + val start: Int + val size: Int + // TODO: stop using hard-coded values. + if (isMetaclass) { + flags = 1 + start = 40 + size = 40 + } else { + flags = 0 + start = 8 + size = 8 + } + + val fields = mutableListOf() + + fields += Int32(flags) + fields += Int32(start) + fields += Int32(size) + fields += NullPointer(int8Type) // ivar layout name + fields += classNameLiteral + fields += if (isMetaclass) NullPointer(methodListType) else emitInstanceMethodList() + fields += NullPointer(protocolListType) + fields += NullPointer(ivarListType) + fields += NullPointer(int8Type) // ivar layout + fields += NullPointer(propListType) + + val roValue = Struct(classRoType, fields) + + val roLabel = if (isMetaclass) { + "\u0001l_OBJC_METACLASS_RO_\$_" + } else { + "\u0001l_OBJC_CLASS_RO_\$_" + } + name + + val roGlobal = context.llvm.staticData.placeGlobal(roLabel, roValue).also { + it.setLinkage(LLVMLinkage.LLVMPrivateLinkage) + it.setAlignment(runtime.pointerAlignment) + it.setSection("__DATA, __objc_const") + } + + return roGlobal.pointer + } + + fun buildClassObject( + isMetaclass: Boolean, + isa: ConstPointer, + superClass: ConstPointer, + classRo: ConstPointer + ): ConstPointer { + val fields = mutableListOf() + + fields += isa + fields += superClass + fields += emptyCache + val vtableEntryType = pointerType(functionType(int8TypePtr, false, int8TypePtr, int8TypePtr)) + fields += NullPointer(vtableEntryType) // empty vtable + fields += classRo + + val classObjectValue = Struct(classObjectType, fields) + val classGlobal = getClassGlobal(name, isMetaclass = isMetaclass) + + LLVMSetInitializer(classGlobal.llvm, classObjectValue.llvm) + LLVMSetSection(classGlobal.llvm, "__DATA, __objc_data") + LLVMSetAlignment(classGlobal.llvm, LLVMABIAlignmentOfType(runtime.targetData, classObjectType)) + + context.llvm.usedGlobals.add(classGlobal.llvm) + + return classGlobal + } + + val metaclassObject = buildClassObject( + isMetaclass = true, + isa = getClassGlobal("NSObject", isMetaclass = true), + superClass = getClassGlobal(superName, isMetaclass = true), + classRo = buildClassRo(isMetaclass = true) + ) + + val classObject = buildClassObject( + isMetaclass = false, + isa = metaclassObject, + superClass = getClassGlobal(superName, isMetaclass = false), + classRo = buildClassRo(isMetaclass = false) + ) + + definedClasses.add(classObject) + } + + private val definedClasses = mutableListOf() + + private fun addModuleClassList(elements: List, name: String, section: String) { + if (elements.isEmpty()) return + + val global = context.llvm.staticData.placeGlobalArray( + name, + int8TypePtr, + elements.map { it.bitcast(int8TypePtr) } + ) + + global.setAlignment( + LLVMABIAlignmentOfType( + context.llvm.runtime.targetData, + LLVMGetInitializer(global.llvmGlobal)!!.type + ) + ) + + global.setSection(section) + + context.llvm.compilerUsedGlobals += global.llvmGlobal + } + + private val classNames = CStringLiteralsTable(classNameGenerator) + + private val selectors = CStringLiteralsTable(selectorGenerator) + + private val encodings = CStringLiteralsTable(encodingGenerator) + + private inner class CStringLiteralsTable(val generator: CStringLiteralsGenerator) { + + private val literals = mutableMapOf() + + fun get(value: String) = literals.getOrPut(value) { + val globalPointer = generator.generate(context.llvmModule!!, value) + context.llvm.compilerUsedGlobals += globalPointer.llvm + globalPointer.getElementPtr(0) + } + } + + companion object { + val classNameGenerator = + CStringLiteralsGenerator("OBJC_CLASS_NAME_", "__TEXT,__objc_classname,cstring_literals") + + val selectorGenerator = + CStringLiteralsGenerator("OBJC_METH_VAR_NAME_", "__TEXT,__objc_methname,cstring_literals") + + private val encodingGenerator = + CStringLiteralsGenerator("OBJC_METH_VAR_TYPE_", "__TEXT,__objc_methtype,cstring_literals") + } + + class CStringLiteralsGenerator(val label: String, val section: String) { + fun generate(module: LLVMModuleRef, value: String): ConstPointer { + val bytes = value.toByteArray(Charsets.UTF_8).map { Int8(it) } + Int8(0) + val initializer = ConstArray(int8Type, bytes) + val llvmGlobal = LLVMAddGlobal(module, initializer.llvmType, label)!! + LLVMSetInitializer(llvmGlobal, initializer.llvm) + + LLVMSetGlobalConstant(llvmGlobal, 1) + LLVMSetLinkage(llvmGlobal, LLVMLinkage.LLVMPrivateLinkage) + LLVMSetSection(llvmGlobal, section) + LLVMSetUnnamedAddr(llvmGlobal, 1) + LLVMSetAlignment(llvmGlobal, 1) + + return constPointer(llvmGlobal) + } + } +} diff --git a/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/objc/linkObjC.kt b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/objc/linkObjC.kt new file mode 100644 index 00000000000..6240faaa294 --- /dev/null +++ b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/objc/linkObjC.kt @@ -0,0 +1,233 @@ +/* + * Copyright 2010-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +package org.jetbrains.kotlin.backend.konan.llvm.objc + +import kotlinx.cinterop.* +import llvm.* +import org.jetbrains.kotlin.backend.konan.Context +import org.jetbrains.kotlin.backend.konan.isFinalBinary +import org.jetbrains.kotlin.backend.konan.llvm.* +import org.jetbrains.kotlin.backend.konan.objcexport.NSNumberKind +import org.jetbrains.kotlin.backend.konan.objcexport.ObjCExportNamer + +internal fun linkObjC(context: Context) { + val config = context.config + if (!(config.produce.isFinalBinary && config.target.family.isAppleFamily)) return + + val patchBuilder = PatchBuilder(context) + patchBuilder.addObjCPatches() + + val bitcodeFile = config.objCNativeLibrary + val parsedModule = parseBitcodeFile(bitcodeFile) + + patchBuilder.buildAndApply(parsedModule) + + val failed = LLVMLinkModules2(context.llvmModule!!, parsedModule) + if (failed != 0) { + throw Error("failed to link $bitcodeFile") + } +} + +private class PatchBuilder(val context: Context) { + enum class GlobalKind(val prefix: String) { + OBJC_CLASS("OBJC_CLASS_\$_"), + OBJC_METACLASS("OBJC_METACLASS_\$_"), + OBJC_IVAR("OBJC_IVAR_\$_"), + } + + data class GlobalPatch(val kind: GlobalKind, val suffix: String, val newSuffix: String) { + val globalName: String + get() = "${kind.prefix}$suffix" + + val newGlobalName: String + get() = "${kind.prefix}$newSuffix" + } + + data class LiteralPatch( + val generator: ObjCDataGenerator.CStringLiteralsGenerator, + val value: String, + val newValue: String + ) + + val globalPatches = mutableListOf() + val literalPatches = mutableListOf() + + val objCExportNamer = context.objCExport.namer + + // Note: exported classes anyway use the same prefix, + // so using more unique private prefix wouldn't help to prevent any clashes. + private val privatePrefix = objCExportNamer.topLevelNamePrefix + + fun addProtocolImport(name: String) { + literalPatches += LiteralPatch(ObjCDataGenerator.classNameGenerator, name, name) + // So that protocol name literal wouldn't be detected as unhandled class. + } + + fun addExportedClass(publicName: ObjCExportNamer.ClassOrProtocolName, runtimeName: String, vararg ivars: String) { + addRenameClass(runtimeName, publicName.binaryName, ivars) + } + + fun addPrivateClass(name: String, vararg ivars: String) { + addRenameClass(name, "$privatePrefix$name", ivars) + } + + private fun addRenameClass(oldName: String, newName: String, ivars: Array) { + globalPatches += GlobalPatch(GlobalKind.OBJC_CLASS, oldName, newName) + globalPatches += GlobalPatch(GlobalKind.OBJC_METACLASS, oldName, newName) + + ivars.mapTo(globalPatches) { + GlobalPatch(GlobalKind.OBJC_IVAR, "$oldName.$it", "$newName.$it") + } + + literalPatches += LiteralPatch(ObjCDataGenerator.classNameGenerator, oldName, newName) + } + + fun addPrivateCategory(name: String) { + literalPatches += LiteralPatch(ObjCDataGenerator.classNameGenerator, name, "$privatePrefix$name") + } + + fun addPrivateSelector(name: String) { + literalPatches += LiteralPatch(ObjCDataGenerator.selectorGenerator, name, "${privatePrefix}_$name") + } +} + +/** + * Add patches for objc.bc. + */ +private fun PatchBuilder.addObjCPatches() { + addProtocolImport("NSCopying") + + addPrivateSelector("toKotlin:") + addPrivateSelector("releaseAsAssociatedObject") + + addPrivateClass("KIteratorAsNSEnumerator", "iteratorHolder") + addPrivateClass("KListAsNSArray", "listHolder") + addPrivateClass("KMutableListAsNSMutableArray", "listHolder") + addPrivateClass("KSetAsNSSet", "setHolder") + addPrivateClass("KMapAsNSDictionary", "mapHolder") + + addPrivateClass("KotlinObjectHolder", "refHolder") + addPrivateClass("KotlinObjCWeakReference", "referred") + + addPrivateCategory("NSObjectToKotlin") + addPrivateCategory("NSStringToKotlin") + addPrivateCategory("NSNumberToKotlin") + addPrivateCategory("NSDecimalNumberToKotlin") + addPrivateCategory("NSArrayToKotlin") + addPrivateCategory("NSSetToKotlin") + addPrivateCategory("NSDictionaryToKotlin") + addPrivateCategory("NSEnumeratorAsAssociatedObject") + + addExportedClass(objCExportNamer.kotlinAnyName, "KotlinBase", "refHolder", "permanent") + + addExportedClass(objCExportNamer.mutableSetName, "KotlinMutableSet", "setHolder") + addExportedClass(objCExportNamer.mutableMapName, "KotlinMutableDictionary", "mapHolder") + + addExportedClass(objCExportNamer.kotlinNumberName, "KotlinNumber") + NSNumberKind.values().mapNotNull { it.mappedKotlinClassId }.forEach { + addExportedClass(objCExportNamer.numberBoxName(it), "Kotlin${it.shortClassName}", "value_") + } +} + +private fun PatchBuilder.buildAndApply(llvmModule: LLVMModuleRef) { + val nameToGlobalPatch = globalPatches.associateNonRepeatingBy { it.globalName } + + val sectionToValueToLiteralPatch = literalPatches.groupBy { it.generator.section } + .mapValues { (_, patches) -> + patches.associateNonRepeatingBy { it.value } + } + + val unusedPatches = (globalPatches + literalPatches).toMutableSet() + + val globals = generateSequence(LLVMGetFirstGlobal(llvmModule), { LLVMGetNextGlobal(it) }).toList() + for (global in globals) { + val initializer = LLVMGetInitializer(global) ?: continue + val name = LLVMGetValueName(global)?.toKString().orEmpty() + + val globalPatch = nameToGlobalPatch[name] + if (globalPatch != null) { + LLVMSetValueName(global, globalPatch.newGlobalName) + unusedPatches -= globalPatch + } else if (PatchBuilder.GlobalKind.values().any { name.startsWith(it.prefix) }) { + error("Objective-C global '$name' is not patched") + } + + val section = LLVMGetSection(global)?.toKString() + sectionToValueToLiteralPatch[section]?.let { valueToLiteralPatch -> + val value = getStringValue(initializer) + val patch = valueToLiteralPatch[value] + if (patch != null) { + if (patch.newValue != value) patchLiteral(global, patch.generator, patch.newValue) + unusedPatches -= patch + } else if (section == ObjCDataGenerator.classNameGenerator.section) { + error("Objective-C class name literal is not patched: $value") + } + } + } + + unusedPatches.firstOrNull()?.let { + error("Patch is not applied: $it") + } +} + +private fun getStringValue(initializer: LLVMValueRef): String? = when (LLVMGetValueKind(initializer)) { + LLVMValueKind.LLVMConstantDataArrayValueKind -> memScoped { + require(LLVMIsConstantString(initializer) != 0) { "not a constant string: ${llvm2string(initializer)}" } + + val lengthVar = alloc() + val bytePtr = LLVMGetAsString(initializer, lengthVar.ptr)!! + val length = lengthVar.value + + val lastByte = bytePtr[length - 1] + require(lastByte == 0.toByte()) { + "${llvm2string(initializer)}:\n expected zero terminator, found $lastByte" + } + + bytePtr.toKString() + } + + LLVMValueKind.LLVMConstantAggregateZeroValueKind -> "" + + else -> error("Unexpected literal initializer: ${llvm2string(initializer)}") +} + +private fun List.associateNonRepeatingBy(keySelector: (T) -> K): Map = + this.groupBy(keySelector) + .mapValues { (key, values) -> + values.singleOrNull() + ?: error("multiple values found for $key: ${values.joinToString()}") + } + +private fun patchLiteral( + global: LLVMValueRef, + generator: ObjCDataGenerator.CStringLiteralsGenerator, + newValue: String +) { + val module = LLVMGetGlobalParent(global)!! + + val newFirstCharPtr = generator.generate(module, newValue).getElementPtr(0).llvm + + generateSequence(LLVMGetFirstUse(global), { LLVMGetNextUse(it) }).forEach { use -> + val firstCharPtr = LLVMGetUser(use)!!.also { + require(it.isFirstCharPtr(global)) { + "Unexpected literal usage: ${llvm2string(it)}" + } + } + LLVMReplaceAllUsesWith(firstCharPtr, newFirstCharPtr) + } +} + +private fun LLVMValueRef.isFirstCharPtr(global: LLVMValueRef): Boolean = + this.type == int8TypePtr && + LLVMIsConstant(this) != 0 && LLVMGetConstOpcode(this) == LLVMOpcode.LLVMGetElementPtr + && LLVMGetNumOperands(this) == 3 + && LLVMGetOperand(this, 0) == global + && LLVMGetOperand(this, 1).isZeroConst() + && LLVMGetOperand(this, 2).isZeroConst() + +private fun LLVMValueRef?.isZeroConst(): Boolean = + this != null && LLVMGetValueKind(this) == LLVMValueKind.LLVMConstantIntValueKind + && LLVMConstIntGetZExtValue(this) == 0L diff --git a/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/objcexport/BlockPointerSupport.kt b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/objcexport/BlockPointerSupport.kt new file mode 100644 index 00000000000..0ca13e435dc --- /dev/null +++ b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/objcexport/BlockPointerSupport.kt @@ -0,0 +1,344 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +package org.jetbrains.kotlin.backend.konan.llvm.objcexport + +import llvm.* +import org.jetbrains.kotlin.backend.common.ir.simpleFunctions +import org.jetbrains.kotlin.backend.konan.llvm.* +import org.jetbrains.kotlin.backend.konan.objcexport.BlockPointerBridge +import org.jetbrains.kotlin.descriptors.konan.CurrentKlibModuleOrigin +import org.jetbrains.kotlin.ir.declarations.IrSimpleFunction +import org.jetbrains.kotlin.util.OperatorNameConventions + +internal fun ObjCExportCodeGeneratorBase.generateBlockToKotlinFunctionConverter( + bridge: BlockPointerBridge +): LLVMValueRef { + val irInterface = symbols.functionN(bridge.numberOfParameters).owner + val invokeMethod = irInterface.declarations.filterIsInstance() + .single { it.name == OperatorNameConventions.INVOKE } + + // Note: we can store Objective-C block pointer as associated object of Kotlin function object itself, + // but only if it is equivalent to its dynamic translation result. If block returns void, then it's not like that: + val useSeparateHolder = bridge.returnsVoid + + val bodyType = if (useSeparateHolder) { + structType(codegen.kObjHeader, codegen.kObjHeaderPtr) + } else { + structType(codegen.kObjHeader) + } + + val invokeImpl = generateFunction( + codegen, + codegen.getLlvmFunctionType(invokeMethod), + "invokeFunction${bridge.nameSuffix}" + ) { + val args = (0 until bridge.numberOfParameters).map { index -> + kotlinReferenceToObjC(param(index + 1)) + } + + val thisRef = param(0) + val associatedObjectHolder = if (useSeparateHolder) { + val bodyPtr = bitcast(pointerType(bodyType), thisRef) + loadSlot(structGep(bodyPtr, 1), isVar = false) + } else { + thisRef + } + val blockPtr = callFromBridge( + context.llvm.Kotlin_ObjCExport_GetAssociatedObject, + listOf(associatedObjectHolder) + ) + + val invoke = loadBlockInvoke(blockPtr, bridge) + val result = callFromBridge(invoke, listOf(blockPtr) + args) + + val kotlinResult = if (bridge.returnsVoid) { + theUnitInstanceRef.llvm + } else { + objCReferenceToKotlin(result, Lifetime.RETURN_VALUE) + } + ret(kotlinResult) + }.also { + LLVMSetLinkage(it, LLVMLinkage.LLVMInternalLinkage) + } + + val typeInfo = rttiGenerator.generateSyntheticInterfaceImpl( + irInterface, + mapOf(invokeMethod to constPointer(invokeImpl)), + bodyType, + immutable = true + ) + + return generateFunction( + codegen, + functionType(codegen.kObjHeaderPtr, false, int8TypePtr, codegen.kObjHeaderPtrPtr), + "convertBlock${bridge.nameSuffix}" + ) { + val blockPtr = param(0) + ifThen(icmpEq(blockPtr, kNullInt8Ptr)) { + ret(kNullObjHeaderPtr) + } + + val retainedBlockPtr = callFromBridge(retainBlock, listOf(blockPtr)) + + val result = if (useSeparateHolder) { + val result = allocInstance(typeInfo.llvm, Lifetime.RETURN_VALUE) + val bodyPtr = bitcast(pointerType(bodyType), result) + val holder = allocInstanceWithAssociatedObject( + symbols.interopForeignObjCObject.owner.typeInfoPtr, + retainedBlockPtr, + Lifetime.ARGUMENT + ) + storeHeapRef(holder, structGep(bodyPtr, 1)) + result + } else { + allocInstanceWithAssociatedObject(typeInfo, retainedBlockPtr, Lifetime.RETURN_VALUE) + } + + ret(result) + }.also { + LLVMSetLinkage(it, LLVMLinkage.LLVMInternalLinkage) + } +} + +private fun FunctionGenerationContext.loadBlockInvoke( + blockPtr: LLVMValueRef, + bridge: BlockPointerBridge +): LLVMValueRef { + val blockLiteralType = codegen.runtime.getStructType("Block_literal_1") + val invokePtr = structGep(bitcast(pointerType(blockLiteralType), blockPtr), 3) + + return bitcast(pointerType(bridge.blockType.blockInvokeLlvmType), load(invokePtr)) +} + +private fun FunctionGenerationContext.allocInstanceWithAssociatedObject( + typeInfo: ConstPointer, + associatedObject: LLVMValueRef, + resultLifetime: Lifetime +): LLVMValueRef = call( + context.llvm.Kotlin_ObjCExport_AllocInstanceWithAssociatedObject, + listOf(typeInfo.llvm, associatedObject), + resultLifetime +) + +private val BlockPointerBridge.blockType: BlockType + get() = BlockType(numberOfParameters = this.numberOfParameters, returnsVoid = this.returnsVoid) + +/** + * Type of block having [numberOfParameters] reference-typed parameters and reference- or void-typed return value. + */ +internal data class BlockType(val numberOfParameters: Int, val returnsVoid: Boolean) + +private val BlockType.blockInvokeLlvmType: LLVMTypeRef + get() = functionType( + if (returnsVoid) voidType else int8TypePtr, + false, + (0..numberOfParameters).map { int8TypePtr } + ) + +private val BlockPointerBridge.nameSuffix: String + get() = numberOfParameters.toString() + if (returnsVoid) "V" else "" + +internal class BlockGenerator(private val codegen: CodeGenerator) { + private val kRefSharedHolderType = LLVMGetTypeByName(codegen.runtime.llvmModule, "class.KRefSharedHolder")!! + + private val blockLiteralType = structType( + codegen.runtime.getStructType("Block_literal_1"), + kRefSharedHolderType + ) + + private val blockDescriptorType = codegen.runtime.getStructType("Block_descriptor_1") + + val disposeHelper = generateFunction( + codegen, + functionType(voidType, false, int8TypePtr), + "blockDisposeHelper" + ) { + val blockPtr = bitcast(pointerType(blockLiteralType), param(0)) + val refHolder = structGep(blockPtr, 1) + call(context.llvm.kRefSharedHolderDispose, listOf(refHolder)) + + ret(null) + }.also { + LLVMSetLinkage(it, LLVMLinkage.LLVMInternalLinkage) + } + + val copyHelper = generateFunction( + codegen, + functionType(voidType, false, int8TypePtr, int8TypePtr), + "blockCopyHelper" + ) { + val dstBlockPtr = bitcast(pointerType(blockLiteralType), param(0)) + val dstRefHolder = structGep(dstBlockPtr, 1) + + val srcBlockPtr = bitcast(pointerType(blockLiteralType), param(1)) + val srcRefHolder = structGep(srcBlockPtr, 1) + + // Note: in current implementation copy helper is invoked only for stack-allocated blocks from the same thread, + // so it is technically not necessary to check owner. + // However this is not guaranteed by Objective-C runtime, so keep it suboptimal but reliable: + val ref = call( + context.llvm.kRefSharedHolderRef, + listOf(srcRefHolder), + exceptionHandler = ExceptionHandler.Caller, + verbatim = true + ) + + call(context.llvm.kRefSharedHolderInit, listOf(dstRefHolder, ref)) + + ret(null) + }.also { + LLVMSetLinkage(it, LLVMLinkage.LLVMInternalLinkage) + } + + fun org.jetbrains.kotlin.backend.konan.Context.LongInt(value: Long) = + if (is64BitLong()) Int64(value) else Int32(value.toInt()) + + private fun generateDescriptorForBlock(blockType: BlockType): ConstValue { + val numberOfParameters = blockType.numberOfParameters + + val signature = buildString { + append(if (blockType.returnsVoid) 'v' else '@') + val pointerSize = codegen.runtime.pointerSize + append(pointerSize * (numberOfParameters + 1)) + + var paramOffset = 0L + + (0 .. numberOfParameters).forEach { index -> + append('@') + if (index == 0) append('?') + append(paramOffset) + paramOffset += pointerSize + } + } + + return Struct(blockDescriptorType, + codegen.context.LongInt(0L), + codegen.context.LongInt(LLVMStoreSizeOfType(codegen.runtime.targetData, blockLiteralType)), + constPointer(copyHelper), + constPointer(disposeHelper), + codegen.staticData.cStringLiteral(signature), + NullPointer(int8Type) + ) + } + + + private fun ObjCExportCodeGeneratorBase.generateInvoke( + blockType: BlockType, + invokeName: String, + genBody: FunctionGenerationContext.(LLVMValueRef, List) -> Unit + ): ConstPointer { + val result = generateFunction(codegen, blockType.blockInvokeLlvmType, invokeName) { + val blockPtr = bitcast(pointerType(blockLiteralType), param(0)) + val kotlinObject = call( + context.llvm.kRefSharedHolderRef, + listOf(structGep(blockPtr, 1)), + exceptionHandler = ExceptionHandler.Caller, + verbatim = true + ) + + val arguments = (1 .. blockType.numberOfParameters).map { index -> param(index) } + + genBody(kotlinObject, arguments) + }.also { + LLVMSetLinkage(it, LLVMLinkage.LLVMInternalLinkage) + } + + return constPointer(result) + } + + fun ObjCExportCodeGeneratorBase.generateConvertFunctionToBlock( + bridge: BlockPointerBridge + ): LLVMValueRef { + return generateWrapKotlinObjectToBlock( + bridge.blockType, + convertName = "convertFunction${bridge.nameSuffix}", + invokeName = "invokeBlock${bridge.nameSuffix}" + ) { kotlinFunction, arguments -> + val numberOfParameters = bridge.numberOfParameters + + val kotlinArguments = arguments.map { objCReferenceToKotlin(it, Lifetime.ARGUMENT) } + + val invokeMethod = context.ir.symbols.functionN(numberOfParameters).owner.simpleFunctions() + .single { it.name == OperatorNameConventions.INVOKE } + + val callee = lookupVirtualImpl(kotlinFunction, invokeMethod) + + val result = callFromBridge(callee, listOf(kotlinFunction) + kotlinArguments, Lifetime.ARGUMENT) + + if (bridge.returnsVoid) { + ret(null) + } else { + ret(kotlinReferenceToObjC(result)) + } + } + } + + internal fun ObjCExportCodeGeneratorBase.generateWrapKotlinObjectToBlock( + blockType: BlockType, + convertName: String, + invokeName: String, + genBlockBody: FunctionGenerationContext.(LLVMValueRef, List) -> Unit + ): LLVMValueRef { + val blockDescriptor = codegen.staticData.placeGlobal( + "", + generateDescriptorForBlock(blockType) + ) + + return generateFunction( + codegen, + functionType(int8TypePtr, false, codegen.kObjHeaderPtr), + convertName + ) { + val kotlinRef = param(0) + ifThen(icmpEq(kotlinRef, kNullObjHeaderPtr)) { + ret(kNullInt8Ptr) + } + + val isa = codegen.importGlobal( + "_NSConcreteStackBlock", + int8TypePtr, + CurrentKlibModuleOrigin + ) + + val flags = Int32((1 shl 25) or (1 shl 30) or (1 shl 31)).llvm + val reserved = Int32(0).llvm + + val invokeType = pointerType(functionType(voidType, true, int8TypePtr)) + val invoke = generateInvoke(blockType, invokeName, genBlockBody).bitcast(invokeType).llvm + val descriptor = blockDescriptor.llvmGlobal + + val blockOnStack = alloca(blockLiteralType) + val blockOnStackBase = structGep(blockOnStack, 0) + val refHolder = structGep(blockOnStack, 1) + + listOf(bitcast(int8TypePtr, isa), flags, reserved, invoke, descriptor).forEachIndexed { index, value -> + // Although value is actually on the stack, it's not in normal slot area, so we cannot handle it + // as if it was on the stack. + store(value, structGep(blockOnStackBase, index)) + } + + call(context.llvm.kRefSharedHolderInitLocal, listOf(refHolder, kotlinRef)) + + val copiedBlock = callFromBridge(retainBlock, listOf(bitcast(int8TypePtr, blockOnStack))) + + val autoreleaseReturnValue = context.llvm.externalFunction( + "objc_autoreleaseReturnValue", + functionType(int8TypePtr, false, int8TypePtr), + CurrentKlibModuleOrigin + ) + + ret(callFromBridge(autoreleaseReturnValue, listOf(copiedBlock))) + }.also { + LLVMSetLinkage(it, LLVMLinkage.LLVMInternalLinkage) + } + } +} + +private val ObjCExportCodeGeneratorBase.retainBlock get() = context.llvm.externalFunction( + "objc_retainBlock", + functionType(int8TypePtr, false, int8TypePtr), + CurrentKlibModuleOrigin +) \ No newline at end of file diff --git a/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/objcexport/ObjCExportCodeGenerator.kt b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/objcexport/ObjCExportCodeGenerator.kt new file mode 100644 index 00000000000..e6dc602de5f --- /dev/null +++ b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/objcexport/ObjCExportCodeGenerator.kt @@ -0,0 +1,1639 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +package org.jetbrains.kotlin.backend.konan.llvm.objcexport + +import llvm.* +import org.jetbrains.kotlin.backend.common.ir.allParameters +import org.jetbrains.kotlin.backend.common.ir.allParametersCount +import org.jetbrains.kotlin.backend.common.ir.simpleFunctions +import org.jetbrains.kotlin.backend.konan.* +import org.jetbrains.kotlin.backend.konan.descriptors.* +import org.jetbrains.kotlin.backend.konan.ir.* +import org.jetbrains.kotlin.backend.konan.llvm.* +import org.jetbrains.kotlin.backend.konan.llvm.objc.ObjCCodeGenerator +import org.jetbrains.kotlin.backend.konan.llvm.objc.ObjCDataGenerator +import org.jetbrains.kotlin.backend.konan.objcexport.* +import org.jetbrains.kotlin.backend.konan.serialization.resolveFakeOverrideMaybeAbstract +import org.jetbrains.kotlin.descriptors.* +import org.jetbrains.kotlin.descriptors.konan.CompiledKlibModuleOrigin +import org.jetbrains.kotlin.descriptors.konan.CurrentKlibModuleOrigin +import org.jetbrains.kotlin.ir.declarations.* +import org.jetbrains.kotlin.ir.expressions.IrClassReference +import org.jetbrains.kotlin.ir.expressions.IrVararg +import org.jetbrains.kotlin.ir.symbols.IrClassSymbol +import org.jetbrains.kotlin.ir.types.* +import org.jetbrains.kotlin.ir.util.* +import org.jetbrains.kotlin.konan.target.Family +import org.jetbrains.kotlin.konan.target.KonanTarget +import org.jetbrains.kotlin.name.Name + +internal fun TypeBridge.makeNothing() = when (this) { + is ReferenceBridge, is BlockPointerBridge -> kNullInt8Ptr + is ValueTypeBridge -> LLVMConstNull(this.objCValueType.llvmType)!! +} + +internal open class ObjCExportCodeGeneratorBase(codegen: CodeGenerator) : ObjCCodeGenerator(codegen) { + val symbols get() = context.ir.symbols + val runtime get() = codegen.runtime + val staticData get() = codegen.staticData + + val rttiGenerator = RTTIGenerator(context) + + private val objcTerminate: LLVMValueRef by lazy { + context.llvm.externalFunction( + "objc_terminate", + functionType(voidType, false), + CurrentKlibModuleOrigin + ).also { + setFunctionNoUnwind(it) + } + } + + fun dispose() { + rttiGenerator.dispose() + } + + // TODO: currently bridges don't have any custom `landingpad`s, + // so it is correct to use [callAtFunctionScope] here. + // However, exception handling probably should be refactored + // (e.g. moved from `IrToBitcode.kt` to [FunctionGenerationContext]). + fun FunctionGenerationContext.callFromBridge( + function: LLVMValueRef, + args: List, + resultLifetime: Lifetime = Lifetime.IRRELEVANT + ): LLVMValueRef { + + // TODO: it is required only for Kotlin-to-Objective-C bridges. + this.forwardingForeignExceptionsTerminatedWith = objcTerminate + + return call(function, args, resultLifetime, ExceptionHandler.Caller) + } + + fun FunctionGenerationContext.kotlinReferenceToObjC(value: LLVMValueRef) = + callFromBridge(context.llvm.Kotlin_ObjCExport_refToObjC, listOf(value)) + + fun FunctionGenerationContext.objCReferenceToKotlin(value: LLVMValueRef, resultLifetime: Lifetime) = + callFromBridge(context.llvm.Kotlin_ObjCExport_refFromObjC, listOf(value), resultLifetime) + + private val blockToKotlinFunctionConverterCache = mutableMapOf() + + internal fun blockToKotlinFunctionConverter(bridge: BlockPointerBridge): LLVMValueRef = + blockToKotlinFunctionConverterCache.getOrPut(bridge) { + generateBlockToKotlinFunctionConverter(bridge) + } + + protected val blockGenerator = BlockGenerator(this.codegen) + private val functionToBlockConverterCache = mutableMapOf() + + internal fun kotlinFunctionToBlockConverter(bridge: BlockPointerBridge): LLVMValueRef = + functionToBlockConverterCache.getOrPut(bridge) { + blockGenerator.run { + generateConvertFunctionToBlock(bridge) + } + } +} + +internal class ObjCExportBlockCodeGenerator(codegen: CodeGenerator) : ObjCExportCodeGeneratorBase(codegen) { + init { + // Must be generated along with stdlib: + // 1. Enumerates [BuiltInFictitiousFunctionIrClassFactory] built classes, which may be incomplete otherwise. + // 2. Modifies stdlib global initializers. + // 3. Defines runtime-declared globals. + require(context.producedLlvmModuleContainsStdlib) + } + + fun generate() { + emitFunctionConverters() + emitBlockToKotlinFunctionConverters() + dispose() + } +} + +internal class ObjCExportCodeGenerator( + codegen: CodeGenerator, + val namer: ObjCExportNamer, + val mapper: ObjCExportMapper +) : ObjCExportCodeGeneratorBase(codegen) { + + val selectorsToDefine = mutableMapOf() + + val externalGlobalInitializers = mutableMapOf() + + internal val continuationToCompletionConverter: LLVMValueRef by lazy { + generateContinuationToCompletionConverter(blockGenerator) + } + + fun FunctionGenerationContext.genSendMessage( + returnType: LLVMTypeRef, + receiver: LLVMValueRef, + selector: String, + vararg args: LLVMValueRef + ): LLVMValueRef { + + val objcMsgSendType = functionType( + returnType, + false, + listOf(int8TypePtr, int8TypePtr) + args.map { it.type } + ) + + return callFromBridge(msgSender(objcMsgSendType), listOf(receiver, genSelector(selector)) + args) + } + + fun FunctionGenerationContext.kotlinToObjC( + value: LLVMValueRef, + valueType: ObjCValueType + ): LLVMValueRef = when (valueType) { + ObjCValueType.BOOL -> zext(value, int8Type) // TODO: zext behaviour may be strange on bit types. + + ObjCValueType.UNICHAR, + ObjCValueType.CHAR, ObjCValueType.SHORT, ObjCValueType.INT, ObjCValueType.LONG_LONG, + ObjCValueType.UNSIGNED_CHAR, ObjCValueType.UNSIGNED_SHORT, ObjCValueType.UNSIGNED_INT, + ObjCValueType.UNSIGNED_LONG_LONG, + ObjCValueType.FLOAT, ObjCValueType.DOUBLE, ObjCValueType.POINTER -> value + } + + private fun FunctionGenerationContext.objCToKotlin( + value: LLVMValueRef, + valueType: ObjCValueType + ): LLVMValueRef = when (valueType) { + ObjCValueType.BOOL -> icmpNe(value, Int8(0).llvm) + + ObjCValueType.UNICHAR, + ObjCValueType.CHAR, ObjCValueType.SHORT, ObjCValueType.INT, ObjCValueType.LONG_LONG, + ObjCValueType.UNSIGNED_CHAR, ObjCValueType.UNSIGNED_SHORT, ObjCValueType.UNSIGNED_INT, + ObjCValueType.UNSIGNED_LONG_LONG, + ObjCValueType.FLOAT, ObjCValueType.DOUBLE, ObjCValueType.POINTER -> value + } + + private fun FunctionGenerationContext.objCBlockPointerToKotlin( + value: LLVMValueRef, + typeBridge: BlockPointerBridge, + resultLifetime: Lifetime + ) = callFromBridge( + blockToKotlinFunctionConverter(typeBridge), + listOf(value), + resultLifetime + ) + + private fun FunctionGenerationContext.kotlinFunctionToObjCBlockPointer( + typeBridge: BlockPointerBridge, + value: LLVMValueRef + ) = callFromBridge(kotlinFunctionToBlockConverter(typeBridge), listOf(value)) + + fun FunctionGenerationContext.kotlinToObjC( + value: LLVMValueRef, + typeBridge: TypeBridge + ): LLVMValueRef = if (LLVMTypeOf(value) == voidType) { + typeBridge.makeNothing() + } else { + when (typeBridge) { + is ReferenceBridge -> kotlinReferenceToObjC(value) + is BlockPointerBridge -> kotlinFunctionToObjCBlockPointer(typeBridge, value) + is ValueTypeBridge -> kotlinToObjC(value, typeBridge.objCValueType) + } + } + + fun FunctionGenerationContext.objCToKotlin( + value: LLVMValueRef, + typeBridge: TypeBridge, + resultLifetime: Lifetime + ): LLVMValueRef = when (typeBridge) { + is ReferenceBridge -> objCReferenceToKotlin(value, resultLifetime) + is BlockPointerBridge -> objCBlockPointerToKotlin(value, typeBridge, resultLifetime) + is ValueTypeBridge -> objCToKotlin(value, typeBridge.objCValueType) + } + + fun FunctionGenerationContext.initRuntimeIfNeeded() { + callFromBridge(context.llvm.initRuntimeIfNeeded, emptyList()) + } + + inline fun FunctionGenerationContext.convertKotlin( + genValue: (Lifetime) -> LLVMValueRef, + actualType: IrType, + expectedType: IrType, + resultLifetime: Lifetime + ): LLVMValueRef { + + val conversion = symbols.getTypeConversion(actualType, expectedType) + ?: return genValue(resultLifetime) + + val value = genValue(Lifetime.ARGUMENT) + + return callFromBridge(conversion.owner.llvmFunction, listOf(value), resultLifetime) + } + + private val objCTypeAdapters = mutableListOf() + + internal fun generate(spec: ObjCExportCodeSpec) { + spec.types.forEach { + objCTypeAdapters += when (it) { + is ObjCClassForKotlinClass -> { + val superClass = it.superClassNotAny ?: objCClassForAny + + dataGenerator.emitEmptyClass(it.binaryName, superClass.binaryName) + // Note: it is generated only to be visible for linker. + // Methods will be added at runtime. + + createTypeAdapter(it, superClass) + } + + is ObjCProtocolForKotlinInterface -> createTypeAdapter(it, superClass = null) + } + } + + spec.files.forEach { + objCTypeAdapters += createTypeAdapterForFileClass(it) + dataGenerator.emitEmptyClass(it.binaryName, namer.kotlinAnyName.binaryName) + } + } + + internal fun emitRtti() { + NSNumberKind.values().mapNotNull { it.mappedKotlinClassId }.forEach { + dataGenerator.exportClass(namer.numberBoxName(it).binaryName) + } + dataGenerator.exportClass(namer.mutableSetName.binaryName) + dataGenerator.exportClass(namer.mutableMapName.binaryName) + dataGenerator.exportClass(namer.kotlinAnyName.binaryName) + + emitSpecialClassesConvertions() + + objCTypeAdapters += createTypeAdapter(objCClassForAny, superClass = null) + + emitTypeAdapters() + + // Replace runtime global with weak linkage: + replaceExternalWeakOrCommonGlobal( + "Kotlin_ObjCInterop_uniquePrefix", + codegen.staticData.cStringLiteral(namer.topLevelNamePrefix), + context.standardLlvmSymbolsOrigin + ) + + emitSelectorsHolder() + + emitStaticInitializers() + } + + private fun emitTypeAdapters() { + val placedClassAdapters = mutableMapOf() + val placedInterfaceAdapters = mutableMapOf() + + objCTypeAdapters.forEach { adapter -> + val typeAdapter = staticData.placeGlobal("", adapter).pointer + val irClass = adapter.irClass + + val descriptorToAdapter = if (irClass?.isInterface == true) { + placedInterfaceAdapters + } else { + // Objective-C class for Kotlin class or top-level declarations. + placedClassAdapters + } + descriptorToAdapter[adapter.objCName] = typeAdapter + + if (irClass != null) { + if (!context.llvmModuleSpecification.importsKotlinDeclarationsFromOtherSharedLibraries()) { + setObjCExportTypeInfo(irClass, typeAdapter = typeAdapter) + } else { + // Optimization: avoid generating huge initializers; + // handled with "Kotlin_ObjCExport_initTypeAdapters" below. + } + } + } + + fun emitSortedAdapters(nameToAdapter: Map, prefix: String) { + val sortedAdapters = nameToAdapter.toList().sortedBy { it.first }.map { + it.second + } + + if (sortedAdapters.isNotEmpty()) { + val type = sortedAdapters.first().llvmType + val sortedAdaptersPointer = staticData.placeGlobalConstArray("", type, sortedAdapters) + + // Note: this globals replace runtime globals with weak linkage: + val origin = context.standardLlvmSymbolsOrigin + replaceExternalWeakOrCommonGlobal(prefix, sortedAdaptersPointer, origin) + replaceExternalWeakOrCommonGlobal("${prefix}Num", Int32(sortedAdapters.size), origin) + } + } + + emitSortedAdapters(placedClassAdapters, "Kotlin_ObjCExport_sortedClassAdapters") + emitSortedAdapters(placedInterfaceAdapters, "Kotlin_ObjCExport_sortedProtocolAdapters") + + if (context.llvmModuleSpecification.importsKotlinDeclarationsFromOtherSharedLibraries()) { + replaceExternalWeakOrCommonGlobal( + "Kotlin_ObjCExport_initTypeAdapters", + Int1(1), + context.standardLlvmSymbolsOrigin + ) + } + } + + private fun emitStaticInitializers() { + if (externalGlobalInitializers.isEmpty()) return + + val initializer = generateFunction(codegen, functionType(voidType, false), "initObjCExportGlobals") { + externalGlobalInitializers.forEach { (global, value) -> + store(value.llvm, global) + } + ret(null) + } + + LLVMSetLinkage(initializer, LLVMLinkage.LLVMInternalLinkage) + + context.llvm.otherStaticInitializers += initializer + } + + // TODO: consider including this into ObjCExportCodeSpec. + private val objCClassForAny = ObjCClassForKotlinClass( + namer.kotlinAnyName.binaryName, + symbols.any, + methods = listOf("equals", "hashCode", "toString").map { name -> + symbols.any.owner.simpleFunctions().single { it.name == Name.identifier(name) } + }.map { + require(mapper.shouldBeExposed(it.descriptor)) + ObjCMethodForKotlinMethod(it.symbol) + }, + categoryMethods = emptyList(), + superClassNotAny = null + ) + + private fun emitSelectorsHolder() { + val impType = functionType(voidType, false, int8TypePtr, int8TypePtr) + val imp = generateFunction(codegen, impType, "") { + unreachable() + } + + val methods = selectorsToDefine.map { (selector, bridge) -> + ObjCDataGenerator.Method(selector, getEncoding(bridge), constPointer(imp)) + } + + dataGenerator.emitClass( + "${namer.topLevelNamePrefix}KotlinSelectorsHolder", + superName = "NSObject", + instanceMethods = methods + ) + } + + private val impType = pointerType(functionType(voidType, false)) + + internal val directMethodAdapters = mutableMapOf() + + internal val exceptionTypeInfoArrays = mutableMapOf() + internal val typeInfoArrays = mutableMapOf, ConstPointer>() + + inner class ObjCToKotlinMethodAdapter( + selector: String, + encoding: String, + imp: ConstPointer + ) : Struct( + runtime.objCToKotlinMethodAdapter, + staticData.cStringLiteral(selector), + staticData.cStringLiteral(encoding), + imp.bitcast(impType) + ) + + inner class KotlinToObjCMethodAdapter( + selector: String, + nameSignature: Long, + itablePlace: ClassLayoutBuilder.InterfaceTablePlace, + vtableIndex: Int, + kotlinImpl: ConstPointer + ) : Struct( + runtime.kotlinToObjCMethodAdapter, + staticData.cStringLiteral(selector), + Int64(nameSignature), + Int32(itablePlace.interfaceId), + Int32(itablePlace.methodIndex), + Int32(vtableIndex), + kotlinImpl + ) + + inner class ObjCTypeAdapter( + val irClass: IrClass?, + typeInfo: ConstPointer?, + vtable: ConstPointer?, + vtableSize: Int, + methodTable: List, + itable: List, + itableSize: Int, + val objCName: String, + directAdapters: List, + classAdapters: List, + virtualAdapters: List, + reverseAdapters: List + ) : Struct( + runtime.objCTypeAdapter, + typeInfo, + + vtable, + Int32(vtableSize), + + staticData.placeGlobalConstArray("", runtime.methodTableRecordType, methodTable), + Int32(methodTable.size), + + staticData.placeGlobalConstArray("", runtime.interfaceTableRecordType, itable), + Int32(itableSize), + + staticData.cStringLiteral(objCName), + + staticData.placeGlobalConstArray( + "", + runtime.objCToKotlinMethodAdapter, + directAdapters + ), + Int32(directAdapters.size), + + staticData.placeGlobalConstArray( + "", + runtime.objCToKotlinMethodAdapter, + classAdapters + ), + Int32(classAdapters.size), + + staticData.placeGlobalConstArray( + "", + runtime.objCToKotlinMethodAdapter, + virtualAdapters + ), + Int32(virtualAdapters.size), + + staticData.placeGlobalConstArray( + "", + runtime.kotlinToObjCMethodAdapter, + reverseAdapters + ), + Int32(reverseAdapters.size) + ) + +} + +private fun ObjCExportCodeGenerator.replaceExternalWeakOrCommonGlobal( + name: String, + value: ConstValue, + origin: CompiledKlibModuleOrigin +) { + if (context.llvmModuleSpecification.importsKotlinDeclarationsFromOtherSharedLibraries()) { + val global = codegen.importGlobal(name, value.llvmType, origin) + externalGlobalInitializers[global] = value + } else { + context.llvmImports.add(origin) + val global = staticData.placeGlobal(name, value, isExported = true) + + if (context.llvmModuleSpecification.importsKotlinDeclarationsFromOtherObjectFiles()) { + // Note: actually this is required only if global's weak/common definition is in another object file, + // but it is simpler to do this for all globals, considering that all usages can't be removed by DCE anyway. + context.llvm.usedGlobals += global.llvmGlobal + LLVMSetVisibility(global.llvmGlobal, LLVMVisibility.LLVMHiddenVisibility) + } + } +} + +private fun ObjCExportCodeGenerator.setObjCExportTypeInfo( + irClass: IrClass, + converter: ConstPointer? = null, + objCClass: ConstPointer? = null, + typeAdapter: ConstPointer? = null +) { + val writableTypeInfoValue = buildWritableTypeInfoValue( + converter = converter, + objCClass = objCClass, + typeAdapter = typeAdapter + ) + + if (codegen.isExternal(irClass)) { + // Note: this global replaces the external one with common linkage. + replaceExternalWeakOrCommonGlobal( + irClass.writableTypeInfoSymbolName, + writableTypeInfoValue, + irClass.llvmSymbolOrigin + ) + } else { + setOwnWritableTypeInfo(irClass, writableTypeInfoValue) + } +} + +private fun ObjCExportCodeGeneratorBase.setOwnWritableTypeInfo(irClass: IrClass, writableTypeInfoValue: Struct) { + require(!codegen.isExternal(irClass)) + val writeableTypeInfoGlobal = context.llvmDeclarations.forClass(irClass).writableTypeInfoGlobal!! + writeableTypeInfoGlobal.setLinkage(LLVMLinkage.LLVMExternalLinkage) + writeableTypeInfoGlobal.setInitializer(writableTypeInfoValue) +} + +private fun ObjCExportCodeGeneratorBase.buildWritableTypeInfoValue( + converter: ConstPointer? = null, + objCClass: ConstPointer? = null, + typeAdapter: ConstPointer? = null +): Struct { + if (converter != null) { + assert(converter.llvmType == pointerType(functionType(int8TypePtr, false, codegen.kObjHeaderPtr))) + } + + val objCExportAddition = Struct(runtime.typeInfoObjCExportAddition, + converter?.bitcast(int8TypePtr), + objCClass, + typeAdapter + ) + + val writableTypeInfoType = runtime.writableTypeInfoType!! + return Struct(writableTypeInfoType, objCExportAddition) +} + +private val ObjCExportCodeGenerator.kotlinToObjCFunctionType: LLVMTypeRef + get() = functionType(int8TypePtr, false, codegen.kObjHeaderPtr) + +private val ObjCExportCodeGeneratorBase.objCToKotlinFunctionType: LLVMTypeRef + get() = functionType(codegen.kObjHeaderPtr, false, int8TypePtr, codegen.kObjHeaderPtrPtr) + +private fun ObjCExportCodeGenerator.emitBoxConverters() { + val irBuiltIns = context.irBuiltIns + + emitBoxConverter(irBuiltIns.booleanClass, ObjCValueType.BOOL, "numberWithBool:") + emitBoxConverter(irBuiltIns.byteClass, ObjCValueType.CHAR, "numberWithChar:") + emitBoxConverter(irBuiltIns.shortClass, ObjCValueType.SHORT, "numberWithShort:") + emitBoxConverter(irBuiltIns.intClass, ObjCValueType.INT, "numberWithInt:") + emitBoxConverter(irBuiltIns.longClass, ObjCValueType.LONG_LONG, "numberWithLongLong:") + emitBoxConverter(symbols.uByte, ObjCValueType.UNSIGNED_CHAR, "numberWithUnsignedChar:") + emitBoxConverter(symbols.uShort, ObjCValueType.UNSIGNED_SHORT, "numberWithUnsignedShort:") + emitBoxConverter(symbols.uInt, ObjCValueType.UNSIGNED_INT, "numberWithUnsignedInt:") + emitBoxConverter(symbols.uLong, ObjCValueType.UNSIGNED_LONG_LONG, "numberWithUnsignedLongLong:") + emitBoxConverter(irBuiltIns.floatClass, ObjCValueType.FLOAT, "numberWithFloat:") + emitBoxConverter(irBuiltIns.doubleClass, ObjCValueType.DOUBLE, "numberWithDouble:") +} + +private fun ObjCExportCodeGenerator.emitBoxConverter( + boxClassSymbol: IrClassSymbol, + objCValueType: ObjCValueType, + nsNumberFactorySelector: String +) { + val boxClass = boxClassSymbol.owner + val name = "${boxClass.name}ToNSNumber" + + val converter = generateFunction(codegen, kotlinToObjCFunctionType, name) { + val unboxFunction = context.getUnboxFunction(boxClass).llvmFunction + val kotlinValue = callFromBridge( + unboxFunction, + listOf(param(0)), + Lifetime.IRRELEVANT + ) + + val value = kotlinToObjC(kotlinValue, objCValueType) + + val nsNumberSubclass = genGetLinkedClass(namer.numberBoxName(boxClass.classId!!).binaryName) + ret(genSendMessage(int8TypePtr, nsNumberSubclass, nsNumberFactorySelector, value)) + } + + LLVMSetLinkage(converter, LLVMLinkage.LLVMPrivateLinkage) + setObjCExportTypeInfo(boxClass, constPointer(converter)) +} + +private fun ObjCExportCodeGenerator.generateContinuationToCompletionConverter( + blockGenerator: BlockGenerator +): LLVMValueRef = with(blockGenerator) { + generateWrapKotlinObjectToBlock( + BlockType(numberOfParameters = 2, returnsVoid = true), + convertName = "convertContinuation", + invokeName = "invokeCompletion" + ) { continuation, arguments -> + check(arguments.size == 2) + callFromBridge(context.llvm.Kotlin_ObjCExport_resumeContinuation, listOf(continuation) + arguments) + ret(null) + } +} + +private val ObjCExportBlockCodeGenerator.mappedFunctionNClasses get() = + context.ir.symbols.functionIrClassFactory.builtFunctionNClasses + .filter { it.irClass.descriptor.isMappedFunctionClass() } + +private fun ObjCExportBlockCodeGenerator.emitFunctionConverters() { + require(context.producedLlvmModuleContainsStdlib) + mappedFunctionNClasses.forEach { functionClass -> + val converter = kotlinFunctionToBlockConverter(BlockPointerBridge(functionClass.arity, returnsVoid = false)) + + val writableTypeInfoValue = buildWritableTypeInfoValue(converter = constPointer(converter)) + setOwnWritableTypeInfo(functionClass.irClass, writableTypeInfoValue) + } +} + +private fun ObjCExportBlockCodeGenerator.emitBlockToKotlinFunctionConverters() { + require(context.producedLlvmModuleContainsStdlib) + val functionClassesByArity = mappedFunctionNClasses.associateBy { it.arity } + + val arityLimit = (functionClassesByArity.keys.maxOrNull() ?: -1) + 1 + + val converters = (0 until arityLimit).map { arity -> + functionClassesByArity[arity]?.let { + val bridge = BlockPointerBridge(numberOfParameters = arity, returnsVoid = false) + constPointer(blockToKotlinFunctionConverter(bridge)) + } ?: NullPointer(objCToKotlinFunctionType) + } + + val ptr = staticData.placeGlobalArray( + "", + pointerType(objCToKotlinFunctionType), + converters + ).pointer.getElementPtr(0) + + // Note: defining globals declared in runtime. + staticData.placeGlobal("Kotlin_ObjCExport_blockToFunctionConverters", ptr, isExported = true) + staticData.placeGlobal("Kotlin_ObjCExport_blockToFunctionConverters_size", Int32(arityLimit), isExported = true) +} + +private fun ObjCExportCodeGenerator.emitSpecialClassesConvertions() { + setObjCExportTypeInfo( + symbols.string.owner, + constPointer(context.llvm.Kotlin_ObjCExport_CreateNSStringFromKString) + ) + + emitCollectionConverters() + + emitBoxConverters() +} + +private fun ObjCExportCodeGenerator.emitCollectionConverters() { + + fun importConverter(name: String): ConstPointer = constPointer(context.llvm.externalFunction( + name, + kotlinToObjCFunctionType, + CurrentKlibModuleOrigin + )) + + setObjCExportTypeInfo( + symbols.list.owner, + importConverter("Kotlin_Interop_CreateNSArrayFromKList") + ) + + setObjCExportTypeInfo( + symbols.mutableList.owner, + importConverter("Kotlin_Interop_CreateNSMutableArrayFromKList") + ) + + setObjCExportTypeInfo( + symbols.set.owner, + importConverter("Kotlin_Interop_CreateNSSetFromKSet") + ) + + setObjCExportTypeInfo( + symbols.mutableSet.owner, + importConverter("Kotlin_Interop_CreateKotlinMutableSetFromKSet") + ) + + setObjCExportTypeInfo( + symbols.map.owner, + importConverter("Kotlin_Interop_CreateNSDictionaryFromKMap") + ) + + setObjCExportTypeInfo( + symbols.mutableMap.owner, + importConverter("Kotlin_Interop_CreateKotlinMutableDictonaryFromKMap") + ) +} + +private inline fun ObjCExportCodeGenerator.generateObjCImpBy( + methodBridge: MethodBridge, + debugInfo: Boolean = false, + genBody: FunctionGenerationContext.() -> Unit +): LLVMValueRef { + val result = LLVMAddFunction(context.llvmModule, "objc2kotlin", objCFunctionType(context, methodBridge))!! + + val location = if (debugInfo) { + setupBridgeDebugInfo(context, result) + } else { + null + } + + generateFunction(codegen, result, startLocation = location, endLocation = location) { + genBody() + } + + LLVMSetLinkage(result, LLVMLinkage.LLVMInternalLinkage) + return result +} + +private fun ObjCExportCodeGenerator.generateAbstractObjCImp(methodBridge: MethodBridge): LLVMValueRef = + generateObjCImpBy(methodBridge) { + callFromBridge( + context.llvm.Kotlin_ObjCExport_AbstractMethodCalled, + listOf(param(0), param(1)) + ) + unreachable() + } + +private fun ObjCExportCodeGenerator.generateObjCImp( + target: IrFunction?, + baseMethod: IrFunction, + methodBridge: MethodBridge, + isVirtual: Boolean = false +) = if (target == null) { + generateAbstractObjCImp(methodBridge) +} else { + generateObjCImp( + methodBridge, + isDirect = !isVirtual, + baseMethod = baseMethod + ) { args, resultLifetime, exceptionHandler -> + val llvmTarget = if (!isVirtual) { + codegen.llvmFunction(target) + } else { + lookupVirtualImpl(args.first(), target) + } + + call(llvmTarget, args, resultLifetime, exceptionHandler) + } +} + +private fun ObjCExportCodeGenerator.generateObjCImp( + methodBridge: MethodBridge, + isDirect: Boolean, + baseMethod: IrFunction? = null, + callKotlin: FunctionGenerationContext.( + args: List, + resultLifetime: Lifetime, + exceptionHandler: ExceptionHandler + ) -> LLVMValueRef? +): LLVMValueRef = generateObjCImpBy(methodBridge, debugInfo = isDirect /* see below */) { + // Considering direct calls inlinable above. If such a call is inlined into a bridge with no debug information, + // lldb will not decode the inlined frame even if the callee has debug information. + // So generate dummy debug information for bridge in this case. + // TODO: consider adding debug info to other bridges. + + val returnType = methodBridge.returnBridge + + // TODO: call [NSObject init] if it is a constructor? + // TODO: check for abstract class if it is a constructor. + + if (!methodBridge.isInstance) { + initRuntimeIfNeeded() // For instance methods it gets called when allocating. + } + + var errorOutPtr: LLVMValueRef? = null + var continuation: LLVMValueRef? = null + + val kotlinArgs = methodBridge.paramBridges.mapIndexedNotNull { index, paramBridge -> + val parameter = param(index) + when (paramBridge) { + is MethodBridgeValueParameter.Mapped -> + objCToKotlin(parameter, paramBridge.bridge, Lifetime.ARGUMENT) + + MethodBridgeReceiver.Static, MethodBridgeSelector -> null + MethodBridgeReceiver.Instance -> objCReferenceToKotlin(parameter, Lifetime.ARGUMENT) + + MethodBridgeReceiver.Factory -> null // actual value added by [callKotlin]. + + MethodBridgeValueParameter.ErrorOutParameter -> { + assert(errorOutPtr == null) + errorOutPtr = parameter + null + } + + MethodBridgeValueParameter.SuspendCompletion -> { + callFromBridge( + context.llvm.Kotlin_ObjCExport_createContinuationArgument, + listOf(parameter, generateExceptionTypeInfoArray(baseMethod!!)), + Lifetime.ARGUMENT + ).also { + continuation = it + } + } + } + } + + // TODO: consider merging this handler with function cleanup. + val exceptionHandler = when { + errorOutPtr != null -> kotlinExceptionHandler { exception -> + callFromBridge( + context.llvm.Kotlin_ObjCExport_RethrowExceptionAsNSError, + listOf(exception, errorOutPtr!!, generateExceptionTypeInfoArray(baseMethod!!)) + ) + + val returnValue = when (returnType) { + !is MethodBridge.ReturnValue.WithError -> + error("bridge with error parameter has unexpected return type: $returnType") + + MethodBridge.ReturnValue.WithError.Success -> Int8(0).llvm // false + + is MethodBridge.ReturnValue.WithError.ZeroForError -> { + if (returnType.successBridge == MethodBridge.ReturnValue.Instance.InitResult) { + // Release init receiver, as required by convention. + callFromBridge(objcRelease, listOf(param(0))) + } + Zero(returnType.objCType(context)).llvm + } + } + + ret(returnValue) + } + + continuation != null -> kotlinExceptionHandler { exception -> + // Callee haven't suspended, so it isn't going to call the completion. Call it here: + callFromBridge( + context.ir.symbols.objCExportResumeContinuationWithException.owner.llvmFunction, + listOf(continuation!!, exception) + ) + // Note: completion block could be called directly instead, but this implementation is + // simpler and avoids duplication. + ret(null) + } + + else -> kotlinExceptionHandler { exception -> + callFromBridge(symbols.objCExportTrapOnUndeclaredException.owner.llvmFunction, listOf(exception)) + unreachable() + } + } + + val targetResult = callKotlin(kotlinArgs, Lifetime.ARGUMENT, exceptionHandler) + + tailrec fun genReturnValueOnSuccess(returnBridge: MethodBridge.ReturnValue): LLVMValueRef? = when (returnBridge) { + MethodBridge.ReturnValue.Void -> null + MethodBridge.ReturnValue.HashCode -> { + val kotlinHashCode = targetResult!! + if (codegen.context.is64BitNSInteger()) zext(kotlinHashCode, int64Type) else kotlinHashCode + } + is MethodBridge.ReturnValue.Mapped -> kotlinToObjC(targetResult!!, returnBridge.bridge) + MethodBridge.ReturnValue.WithError.Success -> Int8(1).llvm // true + is MethodBridge.ReturnValue.WithError.ZeroForError -> genReturnValueOnSuccess(returnBridge.successBridge) + MethodBridge.ReturnValue.Instance.InitResult -> param(0) + MethodBridge.ReturnValue.Instance.FactoryResult -> kotlinReferenceToObjC(targetResult!!) // provided by [callKotlin] + MethodBridge.ReturnValue.Suspend -> { + val coroutineSuspended = callFromBridge( + codegen.llvmFunction(context.ir.symbols.objCExportGetCoroutineSuspended.owner), + emptyList(), + Lifetime.STACK + ) + ifThen(icmpNe(targetResult!!, coroutineSuspended)) { + // Callee haven't suspended, so it isn't going to call the completion. Call it here: + callFromBridge( + context.ir.symbols.objCExportResumeContinuation.owner.llvmFunction, + listOf(continuation!!, targetResult) + ) + // Note: completion block could be called directly instead, but this implementation is + // simpler and avoids duplication. + } + null + } + } + + ret(genReturnValueOnSuccess(returnType)) +} + +private fun ObjCExportCodeGenerator.generateExceptionTypeInfoArray(baseMethod: IrFunction): LLVMValueRef = + exceptionTypeInfoArrays.getOrPut(baseMethod) { + val types = effectiveThrowsClasses(baseMethod, symbols) + generateTypeInfoArray(types.toSet()) + }.llvm + +private fun ObjCExportCodeGenerator.generateTypeInfoArray(types: Set): ConstPointer = + typeInfoArrays.getOrPut(types) { + val typeInfos = types.map { with(codegen) { it.typeInfoPtr } } + NullPointer(codegen.kTypeInfo) + codegen.staticData.placeGlobalConstArray("", codegen.kTypeInfoPtr, typeInfos) + } + +private fun effectiveThrowsClasses(method: IrFunction, symbols: KonanSymbols): List { + if (method is IrSimpleFunction && method.overriddenSymbols.isNotEmpty()) { + return effectiveThrowsClasses(method.overriddenSymbols.first().owner, symbols) + } + + val throwsAnnotation = method.annotations.findAnnotation(KonanFqNames.throws) + ?: return if (method.isSuspend) { + listOf(symbols.cancellationException.owner) + } else { + // Note: frontend ensures that all topmost overridden methods have (equal) @Throws annotations. + // However due to linking different versions of libraries IR could end up not meeting this condition. + // Handling missing annotation gracefully: + emptyList() + } + + val throwsVararg = throwsAnnotation.getValueArgument(0) + ?: return emptyList() + + if (throwsVararg !is IrVararg) error(method.getContainingFile(), throwsVararg, "unexpected vararg") + + return throwsVararg.elements.map { + (it as? IrClassReference)?.symbol?.owner as? IrClass + ?: error(method.getContainingFile(), it, "unexpected @Throws argument") + } +} + +private fun ObjCExportCodeGenerator.generateObjCImpForArrayConstructor( + target: IrConstructor, + methodBridge: MethodBridge +): LLVMValueRef = generateObjCImp(methodBridge, isDirect = true) { args, resultLifetime, exceptionHandler -> + val arrayInstance = callFromBridge( + context.llvm.allocArrayFunction, + listOf(target.constructedClass.llvmTypeInfoPtr, args.first()), + resultLifetime = Lifetime.ARGUMENT + ) + + call(target.llvmFunction, listOf(arrayInstance) + args, resultLifetime, exceptionHandler) + arrayInstance +} + +// TODO: cache bridges. +private fun ObjCExportCodeGenerator.generateKotlinToObjCBridge( + irFunction: IrFunction, + baseIrFunction: IrFunction +): ConstPointer { + val baseMethod = baseIrFunction.descriptor + + val methodBridge = mapper.bridgeMethod(baseMethod) + + val parameterToBase = irFunction.allParameters.zip(baseIrFunction.allParameters).toMap() + + val objcMsgSend = msgSender(objCFunctionType(context, methodBridge)) + + val functionType = codegen.getLlvmFunctionType(irFunction) + + val result = generateFunction(codegen, functionType, "kotlin2objc") { + var errorOutPtr: LLVMValueRef? = null + + val parameters = irFunction.allParameters.mapIndexed { index, parameterDescriptor -> + parameterDescriptor to param(index) + }.toMap() + + val objCArgs = methodBridge.parametersAssociated(irFunction).map { (bridge, parameter) -> + when (bridge) { + is MethodBridgeValueParameter.Mapped -> { + parameter!! + val kotlinValue = convertKotlin( + { parameters[parameter]!! }, + actualType = parameter.type, + expectedType = parameterToBase[parameter]!!.type, + resultLifetime = Lifetime.ARGUMENT + ) + kotlinToObjC(kotlinValue, bridge.bridge) + } + + MethodBridgeReceiver.Instance -> kotlinReferenceToObjC(parameters[parameter]!!) + MethodBridgeSelector -> { + val selector = namer.getSelector(baseMethod) + // Selector is referenced thus should be defined to avoid false positive non-public API rejection: + selectorsToDefine[selector] = methodBridge + genSelector(selector) + } + + MethodBridgeReceiver.Static, + MethodBridgeReceiver.Factory -> + error("Method is not instance and thus can't have bridge for overriding: $baseMethod") + + MethodBridgeValueParameter.ErrorOutParameter -> + alloca(int8TypePtr).also { + store(kNullInt8Ptr, it) + errorOutPtr = it + } + + MethodBridgeValueParameter.SuspendCompletion -> { + val continuation = param(irFunction.allParametersCount) // The last argument. + // TODO: consider placing interception into the converter to reduce code size. + val intercepted = callFromBridge( + context.ir.symbols.objCExportInterceptedContinuation.owner.llvmFunction, + listOf(continuation), + Lifetime.ARGUMENT + ) + callFromBridge(continuationToCompletionConverter, listOf(intercepted)) + } + } + } + + val targetResult = callFromBridge(objcMsgSend, objCArgs) + + assert(baseMethod !is ConstructorDescriptor) + + fun rethrow() { + val error = load(errorOutPtr!!) + callFromBridge(context.llvm.Kotlin_ObjCExport_RethrowNSErrorAsException, listOf(error)) + unreachable() + } + + fun genKotlinBaseMethodResult( + lifetime: Lifetime, + returnBridge: MethodBridge.ReturnValue + ): LLVMValueRef? = when (returnBridge) { + MethodBridge.ReturnValue.Void -> null + + MethodBridge.ReturnValue.HashCode -> { + if (codegen.context.is64BitNSInteger()) { + val low = trunc(targetResult, int32Type) + val high = trunc(shr(targetResult, 32, signed = false), int32Type) + xor(low, high) + } else { + targetResult + } + } + + is MethodBridge.ReturnValue.Mapped -> { + objCToKotlin(targetResult, returnBridge.bridge, lifetime) + } + + MethodBridge.ReturnValue.WithError.Success -> { + ifThen(icmpEq(targetResult, Int8(0).llvm)) { + rethrow() + } + null + } + + is MethodBridge.ReturnValue.WithError.ZeroForError -> { + if (returnBridge.successMayBeZero) { + val error = load(errorOutPtr!!) + ifThen(icmpNe(error, kNullInt8Ptr)) { + rethrow() + } + } else { + ifThen(icmpEq(targetResult, kNullInt8Ptr)) { + rethrow() + } + } + genKotlinBaseMethodResult(lifetime, returnBridge.successBridge) + } + + MethodBridge.ReturnValue.Instance.InitResult, + MethodBridge.ReturnValue.Instance.FactoryResult -> + error("init or factory method can't have bridge for overriding: $baseMethod") + + MethodBridge.ReturnValue.Suspend -> { + // Objective-C implementation of Kotlin suspend function is always responsible + // for calling the completion, so in Kotlin coroutines machinery terms it suspends, + // which is indicated by the return value: + callFromBridge( + context.ir.symbols.objCExportGetCoroutineSuspended.owner.llvmFunction, + emptyList(), + Lifetime.RETURN_VALUE + ) + } + } + + val baseReturnType = baseIrFunction.returnType + val actualReturnType = irFunction.returnType + + val retVal = when { + baseIrFunction.isSuspend -> genKotlinBaseMethodResult(Lifetime.RETURN_VALUE, methodBridge.returnBridge) + + actualReturnType.isUnit() || actualReturnType.isNothing() -> { + genKotlinBaseMethodResult(Lifetime.ARGUMENT, methodBridge.returnBridge) + null + } + baseReturnType.isUnit() || baseReturnType.isNothing() -> { + genKotlinBaseMethodResult(Lifetime.ARGUMENT, methodBridge.returnBridge) + codegen.theUnitInstanceRef.llvm + } + else -> + convertKotlin( + { lifetime -> genKotlinBaseMethodResult(lifetime, methodBridge.returnBridge)!! }, + actualType = baseReturnType, + expectedType = actualReturnType, + resultLifetime = Lifetime.RETURN_VALUE + ) + } + + ret(retVal) + } + + LLVMSetLinkage(result, LLVMLinkage.LLVMPrivateLinkage) + + return constPointer(result) +} + +private fun ObjCExportCodeGenerator.createReverseAdapter( + irFunction: IrFunction, + baseMethod: IrFunction, + functionName: String, + vtableIndex: Int?, + itablePlace: ClassLayoutBuilder.InterfaceTablePlace? +): ObjCExportCodeGenerator.KotlinToObjCMethodAdapter { + + val nameSignature = functionName.localHash.value + val selector = namer.getSelector(baseMethod.descriptor) + + val kotlinToObjC = generateKotlinToObjCBridge( + irFunction, + baseMethod + ).bitcast(int8TypePtr) + + return KotlinToObjCMethodAdapter(selector, nameSignature, + itablePlace ?: ClassLayoutBuilder.InterfaceTablePlace.INVALID, + vtableIndex ?: -1, + kotlinToObjC) +} + +private fun ObjCExportCodeGenerator.createMethodVirtualAdapter( + baseMethod: IrFunction +): ObjCExportCodeGenerator.ObjCToKotlinMethodAdapter { + assert(mapper.isBaseMethod(baseMethod.descriptor)) + + val selector = namer.getSelector(baseMethod.descriptor) + + val methodBridge = mapper.bridgeMethod(baseMethod.descriptor) + val objCToKotlin = constPointer(generateObjCImp(baseMethod, baseMethod, methodBridge, isVirtual = true)) + + selectorsToDefine[selector] = methodBridge + + return ObjCToKotlinMethodAdapter(selector, getEncoding(methodBridge), objCToKotlin) +} + +private fun ObjCExportCodeGenerator.createMethodAdapter( + implementation: IrFunction?, + baseMethod: IrFunction +) = createMethodAdapter(DirectAdapterRequest(implementation, baseMethod)) + +private fun ObjCExportCodeGenerator.createFinalMethodAdapter( + irFunction: IrSimpleFunction +): ObjCExportCodeGenerator.ObjCToKotlinMethodAdapter { + require(irFunction.modality == Modality.FINAL) + return createMethodAdapter(irFunction, irFunction) +} + +private fun ObjCExportCodeGenerator.createMethodAdapter( + request: DirectAdapterRequest +): ObjCExportCodeGenerator.ObjCToKotlinMethodAdapter = this.directMethodAdapters.getOrPut(request) { + + val selectorName = namer.getSelector(request.base.descriptor) + val methodBridge = mapper.bridgeMethod(request.base.descriptor) + val objCEncoding = getEncoding(methodBridge) + val objCToKotlin = constPointer(generateObjCImp(request.implementation, request.base, methodBridge)) + + selectorsToDefine[selectorName] = methodBridge + + ObjCToKotlinMethodAdapter(selectorName, objCEncoding, objCToKotlin) +} + +private fun ObjCExportCodeGenerator.createConstructorAdapter( + irConstructor: IrConstructor +): ObjCExportCodeGenerator.ObjCToKotlinMethodAdapter = createMethodAdapter(irConstructor, irConstructor) + +private fun ObjCExportCodeGenerator.createArrayConstructorAdapter( + irConstructor: IrConstructor +): ObjCExportCodeGenerator.ObjCToKotlinMethodAdapter { + val selectorName = namer.getSelector(irConstructor.descriptor) + val methodBridge = mapper.bridgeMethod(irConstructor.descriptor) + val objCEncoding = getEncoding(methodBridge) + val objCToKotlin = constPointer(generateObjCImpForArrayConstructor(irConstructor, methodBridge)) + + selectorsToDefine[selectorName] = methodBridge + + return ObjCToKotlinMethodAdapter(selectorName, objCEncoding, objCToKotlin) +} + +private fun ObjCExportCodeGenerator.vtableIndex(irFunction: IrSimpleFunction): Int? { + assert(irFunction.isOverridable) + val irClass = irFunction.parentAsClass + return if (irClass.isInterface) { + null + } else { + context.getLayoutBuilder(irClass).vtableIndex(irFunction) + } +} + +private fun ObjCExportCodeGenerator.itablePlace(irFunction: IrSimpleFunction): ClassLayoutBuilder.InterfaceTablePlace? { + assert(irFunction.isOverridable) + val irClass = irFunction.parentAsClass + return if (irClass.isInterface && context.ghaEnabled() + && (irFunction.isReal || irFunction.resolveFakeOverrideMaybeAbstract().parent != context.irBuiltIns.anyClass.owner)) { + context.getLayoutBuilder(irClass).itablePlace(irFunction) + } else { + null + } +} + +private fun ObjCExportCodeGenerator.createTypeAdapterForFileClass( + fileClass: ObjCClassForKotlinFile +): ObjCExportCodeGenerator.ObjCTypeAdapter { + val name = fileClass.binaryName + + val adapters = fileClass.methods.map { createFinalMethodAdapter(it.baseMethod.owner) } + + return ObjCTypeAdapter( + irClass = null, + typeInfo = null, + vtable = null, + vtableSize = -1, + methodTable = emptyList(), + itable = emptyList(), + itableSize = -1, + objCName = name, + directAdapters = emptyList(), + classAdapters = adapters, + virtualAdapters = emptyList(), + reverseAdapters = emptyList() + ) +} + +private fun ObjCExportCodeGenerator.createTypeAdapter( + type: ObjCTypeForKotlinType, + superClass: ObjCClassForKotlinClass? +): ObjCExportCodeGenerator.ObjCTypeAdapter { + val irClass = type.irClassSymbol.owner + val adapters = mutableListOf() + val classAdapters = mutableListOf() + + type.methods.forEach { + when (it) { + is ObjCInitMethodForKotlinConstructor -> { + adapters += createConstructorAdapter(it.irConstructorSymbol.owner) + } + is ObjCFactoryMethodForKotlinArrayConstructor -> { + classAdapters += createArrayConstructorAdapter(it.irConstructorSymbol.owner) + } + is ObjCGetterForKotlinEnumEntry -> { + classAdapters += createEnumEntryAdapter(it.irEnumEntrySymbol.owner) + } + is ObjCMethodForKotlinMethod -> {} // Handled below. + }.let {} // Force exhaustive. + } + + val reverseAdapters = mutableListOf() + + if (type is ObjCClassForKotlinClass) { + + type.categoryMethods.forEach { + val irFunction = it.baseMethod.owner + adapters += createFinalMethodAdapter(irFunction) + reverseAdapters += nonOverridableAdapter(irFunction.descriptor, hasSelectorAmbiguity = false) + } + + adapters += createDirectAdapters(type, superClass) + } + + reverseAdapters += createReverseAdapters(type) + + val virtualAdapters = type.kotlinMethods.map { it.baseMethod.owner } + .filter { it.parentAsClass == irClass && it.isOverridable } + .map { createMethodVirtualAdapter(it) } + + val typeInfo = constPointer(codegen.typeInfoValue(irClass)) + val objCName = type.binaryName + + val vtableSize = if (irClass.kind == ClassKind.INTERFACE) { + -1 + } else { + context.getLayoutBuilder(irClass).vtableEntries.size + } + + val vtable = if (!irClass.isInterface && !irClass.typeInfoHasVtableAttached) { + staticData.placeGlobal("", rttiGenerator.vtable(irClass)).also { + it.setConstant(true) + }.pointer.getElementPtr(0) + } else { + null + } + + val methodTable = if (!irClass.isInterface && irClass.isAbstract()) { + rttiGenerator.methodTableRecords(irClass) + } else { + emptyList() + } + + val (itable, itableSize) = when { + irClass.isInterface -> Pair(emptyList(), context.getLayoutBuilder(irClass).interfaceTableEntries.size) + irClass.isAbstract() && context.ghaEnabled() -> rttiGenerator.interfaceTableRecords(irClass) + else -> Pair(emptyList(), -1) + } + + when (irClass.kind) { + ClassKind.OBJECT -> { + classAdapters += if (irClass.isUnit()) { + createUnitInstanceAdapter() + } else { + createObjectInstanceAdapter(irClass) + } + } + else -> { + // Nothing special. + } + } + + return ObjCTypeAdapter( + irClass, + typeInfo, + vtable, + vtableSize, + methodTable, + itable, + itableSize, + objCName, + adapters, + classAdapters, + virtualAdapters, + reverseAdapters + ) +} + +private fun ObjCExportCodeGenerator.createReverseAdapters( + type: ObjCTypeForKotlinType +): List { + val result = mutableListOf() + val allBaseMethods = type.kotlinMethods.map { it.baseMethod.owner }.toSet() + + for (method in type.irClassSymbol.owner.simpleFunctions()) { + val baseMethods = method.allOverriddenFunctions.filter { it in allBaseMethods } + if (baseMethods.isEmpty()) continue + + val hasSelectorAmbiguity = baseMethods.map { namer.getSelector(it.descriptor) }.distinct().size > 1 + + if (method.isOverridable && !hasSelectorAmbiguity) { + val baseMethod = baseMethods.first() + + val presentVtableBridges = mutableSetOf(null) + val presentMethodTableBridges = mutableSetOf() + val presentItableBridges = mutableSetOf(null) + + val allOverriddenMethods = method.allOverriddenFunctions + + val (inherited, uninherited) = allOverriddenMethods.partition { + it != method && mapper.shouldBeExposed(it.descriptor) + } + + inherited.forEach { + presentVtableBridges += vtableIndex(it) + presentMethodTableBridges += it.functionName + presentItableBridges += itablePlace(it) + } + + uninherited.forEach { + val vtableIndex = vtableIndex(it) + val functionName = it.functionName + val itablePlace = itablePlace(it) + + if (vtableIndex !in presentVtableBridges || functionName !in presentMethodTableBridges + || itablePlace !in presentItableBridges) { + presentVtableBridges += vtableIndex + presentMethodTableBridges += functionName + presentItableBridges += itablePlace + result += createReverseAdapter(it, baseMethod, functionName, vtableIndex, itablePlace) + } + } + + } else { + // Mark it as non-overridable: + baseMethods.distinctBy { namer.getSelector(it.descriptor) }.forEach { baseMethod -> + result += nonOverridableAdapter(baseMethod.descriptor, hasSelectorAmbiguity) + } + } + } + + return result +} + +private fun ObjCExportCodeGenerator.nonOverridableAdapter( + baseMethod: FunctionDescriptor, + hasSelectorAmbiguity: Boolean +): ObjCExportCodeGenerator.KotlinToObjCMethodAdapter = KotlinToObjCMethodAdapter( + namer.getSelector(baseMethod), + -1, + vtableIndex = if (hasSelectorAmbiguity) -2 else -1, // Describes the reason. + kotlinImpl = NullPointer(int8Type), + itablePlace = ClassLayoutBuilder.InterfaceTablePlace.INVALID +) + +private val ObjCTypeForKotlinType.kotlinMethods: List + get() = this.methods.filterIsInstance() + +internal data class DirectAdapterRequest(val implementation: IrFunction?, val base: IrFunction) + +private fun ObjCExportCodeGenerator.createDirectAdapters( + typeDeclaration: ObjCClassForKotlinClass, + superClass: ObjCClassForKotlinClass? +): List { + + fun ObjCClassForKotlinClass.getAllRequiredDirectAdapters() = this.kotlinMethods.map { method -> + DirectAdapterRequest( + findImplementation(irClassSymbol.owner, method.baseMethod.owner, context), + method.baseMethod.owner + ) + } + + val inheritedAdapters = superClass?.getAllRequiredDirectAdapters().orEmpty() + val requiredAdapters = typeDeclaration.getAllRequiredDirectAdapters() - inheritedAdapters + + return requiredAdapters.distinctBy { namer.getSelector(it.base.descriptor) }.map { createMethodAdapter(it) } +} + +private fun findImplementation(irClass: IrClass, method: IrSimpleFunction, context: Context): IrSimpleFunction? { + val override = irClass.simpleFunctions().singleOrNull { + method in it.allOverriddenFunctions + } ?: error("no implementation for ${method.descriptor}\nin ${irClass.descriptor}") + return OverriddenFunctionInfo(override, method).getImplementation(context) +} + +private inline fun ObjCExportCodeGenerator.generateObjCToKotlinSyntheticGetter( + selector: String, + block: FunctionGenerationContext.() -> Unit +): ObjCExportCodeGenerator.ObjCToKotlinMethodAdapter { + + val methodBridge = MethodBridge( + MethodBridge.ReturnValue.Mapped(ReferenceBridge), + MethodBridgeReceiver.Static, valueParameters = emptyList() + ) + + val encoding = getEncoding(methodBridge) + val imp = generateFunction(codegen, objCFunctionType(context, methodBridge), "objc2kotlin") { + block() + } + + LLVMSetLinkage(imp, LLVMLinkage.LLVMPrivateLinkage) + + selectorsToDefine[selector] = methodBridge + + return ObjCToKotlinMethodAdapter(selector, encoding, constPointer(imp)) +} + +private fun ObjCExportCodeGenerator.createUnitInstanceAdapter() = + generateObjCToKotlinSyntheticGetter( + namer.getObjectInstanceSelector(context.builtIns.unit) + ) { + initRuntimeIfNeeded() // For instance methods it gets called when allocating. + + ret(callFromBridge(context.llvm.Kotlin_ObjCExport_convertUnit, listOf(codegen.theUnitInstanceRef.llvm))) + } + +private fun ObjCExportCodeGenerator.createObjectInstanceAdapter( + irClass: IrClass +): ObjCExportCodeGenerator.ObjCToKotlinMethodAdapter { + assert(irClass.kind == ClassKind.OBJECT) + assert(!irClass.isUnit()) + + val selector = namer.getObjectInstanceSelector(irClass.descriptor) + + return generateObjCToKotlinSyntheticGetter(selector) { + initRuntimeIfNeeded() // For instance methods it gets called when allocating. + val value = getObjectValue(irClass, startLocationInfo = null, exceptionHandler = ExceptionHandler.Caller) + ret(kotlinToObjC(value, ReferenceBridge)) + } +} + +private fun ObjCExportCodeGenerator.createEnumEntryAdapter( + irEnumEntry: IrEnumEntry +): ObjCExportCodeGenerator.ObjCToKotlinMethodAdapter { + val selector = namer.getEnumEntrySelector(irEnumEntry.descriptor) + + return generateObjCToKotlinSyntheticGetter(selector) { + initRuntimeIfNeeded() // For instance methods it gets called when allocating. + + val value = getEnumEntry(irEnumEntry, ExceptionHandler.Caller) + ret(kotlinToObjC(value, ReferenceBridge)) + } +} + +private fun List.toMethods(): List = this.flatMap { + when (it) { + is PropertyDescriptor -> listOfNotNull(it.getter, it.setter) + is FunctionDescriptor -> listOf(it) + else -> error(it) + } +} + +private fun objCFunctionType(context: Context, methodBridge: MethodBridge): LLVMTypeRef { + val paramTypes = methodBridge.paramBridges.map { it.objCType } + + val returnType = methodBridge.returnBridge.objCType(context) + + return functionType(returnType, false, *(paramTypes.toTypedArray())) +} + +private val ObjCValueType.llvmType: LLVMTypeRef get() = when (this) { + ObjCValueType.BOOL -> int8Type + ObjCValueType.UNICHAR -> int16Type + ObjCValueType.CHAR -> int8Type + ObjCValueType.SHORT -> int16Type + ObjCValueType.INT -> int32Type + ObjCValueType.LONG_LONG -> int64Type + ObjCValueType.UNSIGNED_CHAR -> int8Type + ObjCValueType.UNSIGNED_SHORT -> int16Type + ObjCValueType.UNSIGNED_INT -> int32Type + ObjCValueType.UNSIGNED_LONG_LONG -> int64Type + ObjCValueType.FLOAT -> floatType + ObjCValueType.DOUBLE -> doubleType + ObjCValueType.POINTER -> kInt8Ptr +} + +private val MethodBridgeParameter.objCType: LLVMTypeRef get() = when (this) { + is MethodBridgeValueParameter.Mapped -> this.bridge.objCType + is MethodBridgeReceiver -> ReferenceBridge.objCType + MethodBridgeSelector -> int8TypePtr + MethodBridgeValueParameter.ErrorOutParameter -> pointerType(ReferenceBridge.objCType) + MethodBridgeValueParameter.SuspendCompletion -> int8TypePtr +} + +private fun MethodBridge.ReturnValue.objCType(context: Context): LLVMTypeRef { + return when (this) { + MethodBridge.ReturnValue.Suspend, + MethodBridge.ReturnValue.Void -> voidType + MethodBridge.ReturnValue.HashCode -> if (context.is64BitNSInteger()) int64Type else int32Type + is MethodBridge.ReturnValue.Mapped -> this.bridge.objCType + MethodBridge.ReturnValue.WithError.Success -> ObjCValueType.BOOL.llvmType + + MethodBridge.ReturnValue.Instance.InitResult, + MethodBridge.ReturnValue.Instance.FactoryResult -> ReferenceBridge.objCType + is MethodBridge.ReturnValue.WithError.ZeroForError -> this.successBridge.objCType(context) + } +} + +private val TypeBridge.objCType: LLVMTypeRef get() = when (this) { + is ReferenceBridge, is BlockPointerBridge -> int8TypePtr + is ValueTypeBridge -> this.objCValueType.llvmType +} + +internal fun ObjCExportCodeGenerator.getEncoding(methodBridge: MethodBridge): String { + var paramOffset = 0 + + val params = buildString { + methodBridge.paramBridges.forEach { + append(it.objCEncoding) + append(paramOffset) + paramOffset += LLVMStoreSizeOfType(runtime.targetData, it.objCType).toInt() + } + } + + val targetFamily = context.config.target.family + val returnTypeEncoding = methodBridge.returnBridge.getObjCEncoding(targetFamily) + + val paramSize = paramOffset + return "$returnTypeEncoding$paramSize$params" +} + +// https://developer.apple.com/documentation/objectivec/nsuinteger?language=objc +// `typedef unsigned long NSUInteger` on iOS, macOS, tvOS. +// `typedef unsigned int NSInteger` on watchOS. +private val Family.nsUIntegerEncoding: String get() = when (this) { + Family.OSX, + Family.IOS, + Family.TVOS -> "L" + Family.WATCHOS -> "I" + else -> error("Unexpected target platform: $this") +} + +private fun MethodBridge.ReturnValue.getObjCEncoding(targetFamily: Family): String = when (this) { + MethodBridge.ReturnValue.Suspend, + MethodBridge.ReturnValue.Void -> "v" + MethodBridge.ReturnValue.HashCode -> targetFamily.nsUIntegerEncoding + is MethodBridge.ReturnValue.Mapped -> this.bridge.objCEncoding + MethodBridge.ReturnValue.WithError.Success -> ObjCValueType.BOOL.encoding + + MethodBridge.ReturnValue.Instance.InitResult, + MethodBridge.ReturnValue.Instance.FactoryResult -> ReferenceBridge.objCEncoding + is MethodBridge.ReturnValue.WithError.ZeroForError -> this.successBridge.getObjCEncoding(targetFamily) +} + +private val MethodBridgeParameter.objCEncoding: String get() = when (this) { + is MethodBridgeValueParameter.Mapped -> this.bridge.objCEncoding + is MethodBridgeReceiver -> ReferenceBridge.objCEncoding + MethodBridgeSelector -> ":" + MethodBridgeValueParameter.ErrorOutParameter -> "^${ReferenceBridge.objCEncoding}" + MethodBridgeValueParameter.SuspendCompletion -> "@" +} + +private val TypeBridge.objCEncoding: String get() = when (this) { + ReferenceBridge, is BlockPointerBridge -> "@" + is ValueTypeBridge -> this.objCValueType.encoding +} + +private fun Context.is64BitNSInteger(): Boolean = when (val target = this.config.target) { + KonanTarget.IOS_X64, + KonanTarget.IOS_ARM64, + KonanTarget.TVOS_ARM64, + KonanTarget.TVOS_X64, + KonanTarget.MACOS_X64 -> true + KonanTarget.WATCHOS_ARM64, + KonanTarget.WATCHOS_ARM32, + KonanTarget.WATCHOS_X86, + KonanTarget.IOS_ARM32 -> false + KonanTarget.ANDROID_X64, + KonanTarget.ANDROID_X86, + KonanTarget.ANDROID_ARM32, + KonanTarget.ANDROID_ARM64, + KonanTarget.LINUX_X64, + KonanTarget.MINGW_X86, + KonanTarget.MINGW_X64, + KonanTarget.LINUX_ARM64, + KonanTarget.LINUX_ARM32_HFP, + KonanTarget.LINUX_MIPS32, + KonanTarget.LINUX_MIPSEL32, + KonanTarget.WASM32, + is KonanTarget.ZEPHYR -> error("Target $target has no support for NSInteger type.") + KonanTarget.WATCHOS_X64 -> error("Target $target is not supported.") +} + +internal fun Context.is64BitLong(): Boolean = when (val target = this.config.target) { + KonanTarget.IOS_X64, + KonanTarget.IOS_ARM64, + KonanTarget.TVOS_ARM64, + KonanTarget.TVOS_X64, + KonanTarget.ANDROID_X64, + KonanTarget.ANDROID_ARM64, + KonanTarget.LINUX_ARM64, + KonanTarget.MINGW_X64, + KonanTarget.LINUX_X64, + KonanTarget.MACOS_X64 -> true + KonanTarget.WATCHOS_ARM64, + KonanTarget.WATCHOS_ARM32, + KonanTarget.ANDROID_X86, + KonanTarget.ANDROID_ARM32, + KonanTarget.WATCHOS_X86, + KonanTarget.MINGW_X86, + KonanTarget.LINUX_ARM32_HFP, + KonanTarget.LINUX_MIPS32, + KonanTarget.LINUX_MIPSEL32, + KonanTarget.WASM32, + is KonanTarget.ZEPHYR, + KonanTarget.IOS_ARM32 -> false + KonanTarget.WATCHOS_X64 -> error("Target $target is not supported.") +} diff --git a/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/visibility.kt b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/visibility.kt new file mode 100644 index 00000000000..9f23ad0cbc1 --- /dev/null +++ b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/visibility.kt @@ -0,0 +1,59 @@ +/* + * Copyright 2010-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +package org.jetbrains.kotlin.backend.konan.llvm + +import llvm.* +import org.jetbrains.kotlin.utils.DFS + +/** + * Applies hidden visibility to symbols similarly to LLVM's internalize pass: + * it makes hidden the symbols that are made internal by internalize. + */ +fun makeVisibilityHiddenLikeLlvmInternalizePass(module: LLVMModuleRef) { + // Note: the implementation below generally follows InternalizePass::internalizeModule, + // but omits some details for simplicity. + + // TODO: LLVM handles some additional cases. + val alwaysPreserved = getLlvmUsed(module) + + (getFunctions(module) + getGlobals(module) + getGlobalAliases(module)) + .filter { + when (LLVMGetLinkage(it)) { + LLVMLinkage.LLVMInternalLinkage, LLVMLinkage.LLVMPrivateLinkage -> false + else -> true + } + } + .filter { LLVMIsDeclaration(it) == 0 } + .minus(alwaysPreserved) + .forEach { + LLVMSetVisibility(it, LLVMVisibility.LLVMHiddenVisibility) + } +} + +private fun getLlvmUsed(module: LLVMModuleRef): Set { + val llvmUsed = LLVMGetNamedGlobal(module, "llvm.used") ?: return emptySet() + val llvmUsedValue = LLVMGetInitializer(llvmUsed) ?: return emptySet() + + // Note: llvm.used value is an array of globals, wrapped into bitcasts, GEPs and other instructions; + // see llvm::collectUsedGlobalVariables. + // Conservatively extract all involved globals for simplicity: + return DFS.dfs( + /* nodes = */ listOf(llvmUsedValue), + /* neighbors = */ { value -> getOperands(value) }, + object : DFS.CollectingNodeHandler>(mutableSetOf()) { + override fun beforeChildren(current: LLVMValueRef): Boolean = when (LLVMGetValueKind(current)) { + LLVMValueKind.LLVMGlobalAliasValueKind, + LLVMValueKind.LLVMGlobalVariableValueKind, + LLVMValueKind.LLVMFunctionValueKind -> { + result.add(current) + false // Skip children. + } + + else -> true + } + } + ) +} diff --git a/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/lower/Autoboxing.kt b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/lower/Autoboxing.kt new file mode 100644 index 00000000000..02bcf832aaa --- /dev/null +++ b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/lower/Autoboxing.kt @@ -0,0 +1,536 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +package org.jetbrains.kotlin.backend.konan.lower + +import org.jetbrains.kotlin.backend.common.AbstractValueUsageTransformer +import org.jetbrains.kotlin.backend.common.FileLoweringPass +import org.jetbrains.kotlin.backend.common.atMostOne +import org.jetbrains.kotlin.backend.common.ir.copyTo +import org.jetbrains.kotlin.backend.common.lower.* +import org.jetbrains.kotlin.backend.konan.* +import org.jetbrains.kotlin.backend.konan.ir.* +import org.jetbrains.kotlin.descriptors.Modality +import org.jetbrains.kotlin.descriptors.DescriptorVisibilities +import org.jetbrains.kotlin.ir.IrStatement +import org.jetbrains.kotlin.ir.builders.* +import org.jetbrains.kotlin.ir.declarations.* +import org.jetbrains.kotlin.ir.declarations.impl.IrFieldImpl +import org.jetbrains.kotlin.ir.declarations.impl.IrFunctionImpl +import org.jetbrains.kotlin.ir.declarations.impl.IrPropertyImpl +import org.jetbrains.kotlin.ir.descriptors.WrappedPropertyDescriptor +import org.jetbrains.kotlin.ir.descriptors.WrappedSimpleFunctionDescriptor +import org.jetbrains.kotlin.ir.expressions.* +import org.jetbrains.kotlin.ir.expressions.impl.IrBlockImpl +import org.jetbrains.kotlin.ir.expressions.impl.IrCallImpl +import org.jetbrains.kotlin.ir.expressions.impl.IrGetObjectValueImpl +import org.jetbrains.kotlin.ir.symbols.* +import org.jetbrains.kotlin.ir.symbols.impl.IrFieldSymbolImpl +import org.jetbrains.kotlin.ir.symbols.impl.IrPropertySymbolImpl +import org.jetbrains.kotlin.ir.symbols.impl.IrSimpleFunctionSymbolImpl +import org.jetbrains.kotlin.ir.transformStatement +import org.jetbrains.kotlin.ir.types.IrType +import org.jetbrains.kotlin.ir.util.* +import org.jetbrains.kotlin.ir.visitors.* +import org.jetbrains.kotlin.name.Name +import org.jetbrains.kotlin.utils.addIfNotNull + +/** + * Boxes and unboxes values of value types when necessary. + */ +internal class Autoboxing(val context: Context) : FileLoweringPass { + + private val transformer = AutoboxingTransformer(context) + + override fun lower(irFile: IrFile) { + irFile.transformChildrenVoid(transformer) + irFile.transform(InlineClassTransformer(context), data = null) + } + +} + +private class AutoboxingTransformer(val context: Context) : AbstractValueUsageTransformer( + context.builtIns, + context.ir.symbols, + context.irBuiltIns +) { + + // TODO: should we handle the cases when expression type + // is not equal to e.g. called function return type? + + override fun IrExpression.useInTypeOperator(operator: IrTypeOperator, typeOperand: IrType): IrExpression { + return if (operator == IrTypeOperator.IMPLICIT_COERCION_TO_UNIT || + operator == IrTypeOperator.IMPLICIT_INTEGER_COERCION) { + this + } else { + // Codegen expects the argument of type-checking operator to be an object reference: + this.useAs(context.irBuiltIns.anyNType) + } + } + + private var currentFunction: IrFunction? = null + + override fun visitFunction(declaration: IrFunction): IrStatement { + currentFunction = declaration + val result = super.visitFunction(declaration) + currentFunction = null + return result + } + + override fun IrExpression.useAsReturnValue(returnTarget: IrReturnTargetSymbol): IrExpression = when (returnTarget) { + is IrSimpleFunctionSymbol -> if (returnTarget.owner.isSuspend && returnTarget == currentFunction?.symbol) { + this.useAs(irBuiltIns.anyNType) + } else { + this.useAs(returnTarget.owner.returnType) + } + is IrConstructorSymbol -> this.useAs(irBuiltIns.unitType) + is IrReturnableBlockSymbol -> this.useAs(returnTarget.owner.type) + else -> error(returnTarget) + } + + override fun IrExpression.useAs(type: IrType): IrExpression { + if (this.isNullConst() && type.isNullablePointer()) { + // TODO: consider using IrConst with proper type. + return IrCallImpl.fromSymbolDescriptor( + startOffset, + endOffset, + symbols.getNativeNullPtr.owner.returnType, + symbols.getNativeNullPtr, + symbols.getNativeNullPtr.owner.typeParameters.size, + symbols.getNativeNullPtr.owner.valueParameters.size + ).uncheckedCast(type) + } + + val actualType = when (this) { + is IrCall -> { + if (this.symbol.owner.isSuspend) irBuiltIns.anyNType + else if (this.symbol == symbols.reinterpret) this.getTypeArgument(1)!! + else this.callTarget.returnType + } + is IrGetField -> this.symbol.owner.type + + is IrTypeOperatorCall -> when (this.operator) { + IrTypeOperator.IMPLICIT_INTEGER_COERCION -> + // TODO: is it a workaround for inconsistent IR? + this.typeOperand + + IrTypeOperator.CAST, IrTypeOperator.IMPLICIT_CAST -> context.irBuiltIns.anyNType + + else -> this.type + } + + else -> this.type + } + return this.adaptIfNecessary(actualType, type) + } + + private fun IrType.isNullablePointer(): Boolean = + this.containsNull() && this.computePrimitiveBinaryTypeOrNull() == PrimitiveBinaryType.POINTER + + private val IrFunctionAccessExpression.target: IrFunction get() = when (this) { + is IrCall -> this.callTarget + is IrDelegatingConstructorCall -> this.symbol.owner + is IrConstructorCall -> this.symbol.owner + else -> TODO(this.render()) + } + + private val IrCall.callTarget: IrFunction + get() = if (superQualifierSymbol == null && symbol.owner.isOverridable) { + // A virtual call. + symbol.owner + } else { + symbol.owner.target + } + + override fun IrExpression.useAsDispatchReceiver(expression: IrFunctionAccessExpression): IrExpression { + return this.useAsArgument(expression.target.dispatchReceiverParameter!!) + } + + override fun IrExpression.useAsExtensionReceiver(expression: IrFunctionAccessExpression): IrExpression { + return this.useAsArgument(expression.target.extensionReceiverParameter!!) + } + + override fun IrExpression.useAsValueArgument(expression: IrFunctionAccessExpression, + parameter: IrValueParameter): IrExpression { + + return this.useAsArgument(expression.target.valueParameters[parameter.index]) + } + + private fun IrExpression.adaptIfNecessary(actualType: IrType, expectedType: IrType): IrExpression { + val conversion = symbols.getTypeConversion(actualType, expectedType) + return if (conversion == null) { + this + } else { + val parameter = conversion.owner.explicitParameters.single() + val argument = this.uncheckedCast(parameter.type) + + IrCallImpl(startOffset, endOffset, conversion.owner.returnType, conversion, + conversion.owner.typeParameters.size, conversion.owner.valueParameters.size).apply { + addArguments(mapOf(parameter to argument)) + }.uncheckedCast(this.type) // Try not to bring new type incompatibilities. + } + } + + override fun visitFunctionReference(expression: IrFunctionReference): IrExpression { + expression.transformChildrenVoid() + assert(expression.getArgumentsWithIr().isEmpty()) + return expression + } + + /** + * Casts this expression to `type` without changing its representation in generated code. + */ + @Suppress("UNUSED_PARAMETER") + private fun IrExpression.uncheckedCast(type: IrType): IrExpression { + // TODO: apply some cast if types are incompatible; not required currently. + return this + } + + override fun visitCall(expression: IrCall): IrExpression { + return when (expression.symbol) { + symbols.reinterpret -> { + expression.transformChildrenVoid() + + // TODO: check types has the same binary representation. + val oldType = expression.getTypeArgument(0)!! + val newType = expression.getTypeArgument(1)!! + + assert(oldType.computePrimitiveBinaryTypeOrNull() == newType.computePrimitiveBinaryTypeOrNull()) + + expression.extensionReceiver = expression.extensionReceiver!!.useAs(oldType) + + expression + } + + else -> super.visitCall(expression) + } + } + +} + +private class InlineClassTransformer(private val context: Context) : IrBuildingTransformer(context) { + + private val symbols = context.ir.symbols + private val irBuiltIns = context.irBuiltIns + + private val builtBoxUnboxFunctions = mutableListOf() + + override fun visitFile(declaration: IrFile): IrFile { + declaration.transformChildrenVoid(this) + declaration.declarations.addAll(builtBoxUnboxFunctions) + builtBoxUnboxFunctions.clear() + return declaration + } + + override fun visitClass(declaration: IrClass): IrStatement { + super.visitClass(declaration) + + if (declaration.isInlined()) { + if (declaration.isUsedAsBoxClass()) { + if (declaration.isNativePrimitiveType()) { + buildBoxField(declaration) + } + + buildBoxFunction(declaration, context.getBoxFunction(declaration)) + buildUnboxFunction(declaration, context.getUnboxFunction(declaration)) + } + + declaration.constructors.filter { !it.isPrimary }.toList().mapTo(declaration.declarations) { + context.getLoweredInlineClassConstructor(it) + } + } + + return declaration + } + + override fun visitGetField(expression: IrGetField): IrExpression { + super.visitGetField(expression) + + val field = expression.symbol.owner + val parentClass = field.parentClassOrNull + return if (parentClass == null || !parentClass.isInlined()) + expression + else { + builder.at(expression) + .irCall(symbols.reinterpret, field.type, + listOf(parentClass.defaultType, field.type) + ).apply { + extensionReceiver = expression.receiver!! + } + } + } + + override fun visitSetField(expression: IrSetField): IrExpression { + super.visitSetField(expression) + + return if (expression.symbol.owner.parentClassOrNull?.isInlined() == true) { + // TODO: it is better to get rid of functions setting such fields. + // Here we're trying to maintain all IR nodes as is, albeit the transformed IR isn't equivalent to the original. + // By far SET_FIELD can only be in the constructor which won't be codegened. + // Box functions use createUninitializedInstance instead of constructor calls + // and are placed separately so they won't be processed here. + val startOffset = expression.startOffset + val endOffset = expression.endOffset + IrBlockImpl(startOffset, endOffset, irBuiltIns.unitType).apply { + statements.addIfNotNull(expression.receiver) + statements += expression.value + statements += IrCallImpl(startOffset, endOffset, irBuiltIns.nothingType, symbols.throwNullPointerException, + symbols.throwNullPointerException.owner.typeParameters.size, + symbols.throwNullPointerException.owner.valueParameters.size) + statements += IrGetObjectValueImpl(startOffset, endOffset, irBuiltIns.unitType, irBuiltIns.unitClass) + } + } else { + expression + } + } + + override fun visitConstructorCall(expression: IrConstructorCall): IrExpression { + super.visitConstructorCall(expression) + + val constructor = expression.symbol.owner + return if (constructor.constructedClass.isInlined()) { + builder.lowerConstructorCallToValue(expression, constructor) + } else { + expression + } + } + + override fun visitConstructor(declaration: IrConstructor): IrStatement { + super.visitConstructor(declaration) + + if (declaration.constructedClass.isInlined()) { + if (!declaration.isPrimary) { + buildLoweredSecondaryConstructor(declaration) + } + // TODO: fix DFG building and nullify the body instead. + (declaration.body as IrBlockBody).statements.clear() + } + + return declaration + } + + private fun IrBuilderWithScope.irIsNull(expression: IrExpression): IrExpression { + val binary = expression.type.computeBinaryType() + return when (binary) { + is BinaryType.Primitive -> { + assert(binary.type == PrimitiveBinaryType.POINTER) + irCall(symbols.areEqualByValue[binary.type]!!.owner).apply { + putValueArgument(0, expression) + putValueArgument(1, irNullPointer()) + } + } + is BinaryType.Reference -> irCall(context.irBuiltIns.eqeqeqSymbol).apply { + putValueArgument(0, expression) + putValueArgument(1, irNull()) + } + } + } + + private fun buildBoxFunction(irClass: IrClass, function: IrFunction) { + val builder = context.createIrBuilder(function.symbol) + val cache = BoxCache.values().toList().atMostOne { context.irBuiltIns.getKotlinClass(it) == irClass } + + function.body = builder.irBlockBody(function) { + val valueToBox = function.valueParameters[0] + if (valueToBox.type.containsNull()) { + +irIfThen( + condition = irIsNull(irGet(valueToBox)), + thenPart = irReturn(irNull()) + ) + } + + if (cache != null) { + +irIfThen( + condition = irCall(symbols.boxCachePredicates[cache]!!.owner).apply { + putValueArgument(0, irGet(valueToBox)) + }, + thenPart = irReturn(irCall(symbols.boxCacheGetters[cache]!!.owner).apply { + putValueArgument(0, irGet(valueToBox)) + }) + ) + } + + // Note: IR variable created below has reference type intentionally. + val box = irTemporary(irCall(symbols.createUninitializedInstance.owner).also { + it.putTypeArgument(0, irClass.defaultType) + }) + +irSetField(irGet(box), getInlineClassBackingField(irClass), irGet(valueToBox)) + +irReturn(irGet(box)) + } + + builtBoxUnboxFunctions += function + } + + private fun IrBuilderWithScope.irNullPointerOrReference(type: IrType): IrExpression = + if (type.binaryTypeIsReference()) { + irNull() + } else { + irNullPointer() + } + + private fun IrBuilderWithScope.irNullPointer(): IrExpression = irCall(symbols.getNativeNullPtr.owner) + + private fun buildUnboxFunction(irClass: IrClass, function: IrFunction) { + val builder = context.createIrBuilder(function.symbol) + + function.body = builder.irBlockBody(function) { + val boxParameter = function.valueParameters.single() + if (boxParameter.type.containsNull()) { + +irIfThen( + condition = irEqeqeq(irGet(boxParameter), irNull()), + thenPart = irReturn(irNullPointerOrReference(function.returnType)) + ) + } + +irReturn(irGetField(irGet(boxParameter), getInlineClassBackingField(irClass))) + } + + builtBoxUnboxFunctions += function + } + + private fun buildBoxField(declaration: IrClass) { + val startOffset = declaration.startOffset + val endOffset = declaration.endOffset + val descriptor = WrappedPropertyDescriptor() + + val irField = IrFieldImpl( + startOffset, + endOffset, + IrDeclarationOrigin.DEFINED, + IrFieldSymbolImpl(descriptor), + Name.identifier("value"), + declaration.defaultType, + DescriptorVisibilities.PRIVATE, + isFinal = true, + isExternal = false, + isStatic = false, + ) + irField.parent = declaration + + val irProperty = IrPropertyImpl( + startOffset, + endOffset, + IrDeclarationOrigin.DEFINED, + IrPropertySymbolImpl(descriptor), + irField.name, + irField.visibility, + Modality.FINAL, + isVar = false, + isConst = false, + isLateinit = false, + isDelegated = false, + isExternal = false + ) + descriptor.bind(irProperty) + irProperty.backingField = irField + + declaration.addChild(irProperty) + } + + private fun IrBuilderWithScope.lowerConstructorCallToValue( + expression: IrMemberAccessExpression<*>, + callee: IrConstructor + ): IrExpression = if (callee.isPrimary) { + expression.getValueArgument(0)!! + } else { + this.at(expression).irCall(this@InlineClassTransformer.context.getLoweredInlineClassConstructor(callee)).apply { + (0 until expression.valueArgumentsCount).forEach { + putValueArgument(it, expression.getValueArgument(it)!!) + } + } + } + + private fun buildLoweredSecondaryConstructor(irConstructor: IrConstructor) { + val result = context.getLoweredInlineClassConstructor(irConstructor) + val irClass = irConstructor.parentAsClass + + result.body = context.createIrBuilder(result.symbol).irBlockBody(result) { + lateinit var thisVar: IrVariable + val parameterMapping = result.valueParameters.associateBy { + irConstructor.valueParameters[it.index].symbol + } + + (irConstructor.body as IrBlockBody).statements.forEach { statement -> + statement.setDeclarationsParent(result) + +statement.transformStatement(object : IrElementTransformerVoid() { + override fun visitDelegatingConstructorCall(expression: IrDelegatingConstructorCall): IrExpression { + expression.transformChildrenVoid() + + val value = lowerConstructorCallToValue(expression, expression.symbol.owner) + return irBlock(expression) { + thisVar = irTemporary(value) + } + } + + override fun visitGetValue(expression: IrGetValue): IrExpression { + expression.transformChildrenVoid() + if (expression.symbol == irClass.thisReceiver?.symbol) { + return irGet(thisVar) + } + + parameterMapping[expression.symbol]?.let { return irGet(it) } + return expression + } + + override fun visitSetValue(expression: IrSetValue): IrExpression { + expression.transformChildrenVoid() + parameterMapping[expression.symbol]?.let { return irSet(it.symbol, expression.value) } + return expression + } + + override fun visitReturn(expression: IrReturn): IrExpression { + expression.transformChildrenVoid() + if (expression.returnTargetSymbol == irConstructor.symbol) { + return irReturn(irBlock(expression.startOffset, expression.endOffset) { + +expression.value + +irGet(thisVar) + }) + } + + return expression + } + }) + } + +irReturn(irGet(thisVar)) + } + } + + private fun getInlineClassBackingField(irClass: IrClass): IrField = + irClass.declarations.filterIsInstance().mapNotNull { it.backingField }.single() +} + +private val Context.getLoweredInlineClassConstructor: (IrConstructor) -> IrSimpleFunction by Context.lazyMapMember { irConstructor -> + require(irConstructor.constructedClass.isInlined()) + require(!irConstructor.isPrimary) + + val descriptor = WrappedSimpleFunctionDescriptor() + IrFunctionImpl( + irConstructor.startOffset, irConstructor.endOffset, + IrDeclarationOrigin.DEFINED, + IrSimpleFunctionSymbolImpl(descriptor), + Name.special(""), + irConstructor.visibility, + Modality.FINAL, + isInline = false, + isExternal = false, + isTailrec = false, + isSuspend = false, + returnType = irConstructor.returnType, + isExpect = false, + isFakeOverride = false, + isOperator = false, + isInfix = false + ).apply { + descriptor.bind(this) + parent = irConstructor.parent + + // Note: technically speaking, this function doesn't have access to class type parameters (since it is "static"). + // But, technically speaking, otherwise we would have to remap types in the entire IR subtree, + // which is an overkill here, because type parameters don't matter at this phase of compilation and later. + // So it is just a trick to make [copyTo] happy: + val remapTypeMap = irConstructor.constructedClass.typeParameters.associateBy { it } + + valueParameters += irConstructor.valueParameters.map { it.copyTo(this, remapTypeMap = remapTypeMap) } + } +} diff --git a/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/lower/BridgesBuilding.kt b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/lower/BridgesBuilding.kt new file mode 100644 index 00000000000..e5caa09c3e7 --- /dev/null +++ b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/lower/BridgesBuilding.kt @@ -0,0 +1,259 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +package org.jetbrains.kotlin.backend.konan.lower + +import org.jetbrains.kotlin.backend.common.ClassLoweringPass +import org.jetbrains.kotlin.backend.common.DeclarationContainerLoweringPass +import org.jetbrains.kotlin.backend.common.ir.simpleFunctions +import org.jetbrains.kotlin.backend.common.lower.createIrBuilder +import org.jetbrains.kotlin.backend.common.lower.irBlockBody +import org.jetbrains.kotlin.backend.common.lower.irIfThen +import org.jetbrains.kotlin.backend.konan.Context +import org.jetbrains.kotlin.backend.konan.descriptors.* +import org.jetbrains.kotlin.descriptors.Modality +import org.jetbrains.kotlin.ir.IrStatement +import org.jetbrains.kotlin.ir.builders.* +import org.jetbrains.kotlin.ir.declarations.* +import org.jetbrains.kotlin.ir.declarations.impl.IrFunctionImpl +import org.jetbrains.kotlin.ir.declarations.impl.IrValueParameterImpl +import org.jetbrains.kotlin.ir.descriptors.WrappedSimpleFunctionDescriptor +import org.jetbrains.kotlin.ir.descriptors.WrappedValueParameterDescriptor +import org.jetbrains.kotlin.ir.expressions.* +import org.jetbrains.kotlin.ir.expressions.impl.* +import org.jetbrains.kotlin.ir.symbols.IrClassSymbol +import org.jetbrains.kotlin.ir.symbols.IrSimpleFunctionSymbol +import org.jetbrains.kotlin.ir.symbols.impl.IrSimpleFunctionSymbolImpl +import org.jetbrains.kotlin.ir.symbols.impl.IrValueParameterSymbolImpl +import org.jetbrains.kotlin.ir.types.IrType +import org.jetbrains.kotlin.ir.types.isNullableAny +import org.jetbrains.kotlin.ir.util.transformFlat +import org.jetbrains.kotlin.ir.visitors.IrElementTransformerVoid +import org.jetbrains.kotlin.ir.visitors.transformChildrenVoid +import org.jetbrains.kotlin.load.java.BuiltinMethodsWithSpecialGenericSignature +import org.jetbrains.kotlin.load.java.SpecialGenericSignatures + +internal class WorkersBridgesBuilding(val context: Context) : DeclarationContainerLoweringPass, IrElementTransformerVoid() { + + val symbols = context.ir.symbols + lateinit var runtimeJobFunction: IrSimpleFunction + + override fun lower(irDeclarationContainer: IrDeclarationContainer) { + irDeclarationContainer.declarations.transformFlat { + listOf(it) + buildWorkerBridges(it).also { bridges -> + // `buildWorkerBridges` builds bridges for all declarations inside `it` and nested declarations, + // so some bridges get incorrect parent. Fix it: + bridges.forEach { bridge -> bridge.parent = irDeclarationContainer } + } + } + } + + private fun buildWorkerBridges(declaration: IrDeclaration): List { + val bridges = mutableListOf() + declaration.transformChildrenVoid(object: IrElementTransformerVoid() { + + override fun visitCall(expression: IrCall): IrExpression { + expression.transformChildrenVoid(this) + + if (expression.symbol != symbols.executeImpl) + return expression + + val job = expression.getValueArgument(3) as IrFunctionReference + val jobFunction = (job.symbol as IrSimpleFunctionSymbol).owner + + if (!::runtimeJobFunction.isInitialized) { + val arg = jobFunction.valueParameters[0] + val startOffset = jobFunction.startOffset + val endOffset = jobFunction.endOffset + runtimeJobFunction = WrappedSimpleFunctionDescriptor().let { + IrFunctionImpl( + startOffset, endOffset, + IrDeclarationOrigin.DEFINED, + IrSimpleFunctionSymbolImpl(it), + jobFunction.name, + jobFunction.visibility, + jobFunction.modality, + isInline = false, + isExternal = false, + isTailrec = false, + isSuspend = false, + returnType = context.irBuiltIns.anyNType, + isExpect = false, + isFakeOverride = false, + isOperator = false, + isInfix = false + ).apply { + it.bind(this) + } + } + + runtimeJobFunction.valueParameters += WrappedValueParameterDescriptor().let { + IrValueParameterImpl( + startOffset, endOffset, + IrDeclarationOrigin.DEFINED, + IrValueParameterSymbolImpl(it), + arg.name, + arg.index, + type = context.irBuiltIns.anyNType, + varargElementType = null, + isCrossinline = arg.isCrossinline, + isNoinline = arg.isNoinline, + isAssignable = arg.isAssignable + ).apply { it.bind(this) } + } + } + val overriddenJobDescriptor = OverriddenFunctionInfo(jobFunction, runtimeJobFunction) + if (!overriddenJobDescriptor.needBridge) return expression + + val bridge = context.buildBridge( + startOffset = job.startOffset, + endOffset = job.endOffset, + overriddenFunction = overriddenJobDescriptor, + targetSymbol = jobFunction.symbol) + bridges += bridge + expression.putValueArgument(3, IrFunctionReferenceImpl.fromSymbolDescriptor( + startOffset = job.startOffset, + endOffset = job.endOffset, + type = job.type, + symbol = bridge.symbol, + typeArgumentsCount = 0, + reflectionTarget = null) + ) + return expression + } + }) + return bridges + } +} + +internal class BridgesBuilding(val context: Context) : ClassLoweringPass { + + override fun lower(irClass: IrClass) { + val builtBridges = mutableSetOf() + + irClass.simpleFunctions() + .forEach { function -> + function.allOverriddenFunctions + .map { OverriddenFunctionInfo(function, it) } + .filter { !it.bridgeDirections.allNotNeeded() } + .filter { it.canBeCalledVirtually } + .filter { !it.inheritsBridge } + .distinctBy { it.bridgeDirections } + .forEach { + buildBridge(it, irClass) + builtBridges += it.function + } + } + irClass.transformChildrenVoid(object: IrElementTransformerVoid() { + override fun visitFunction(declaration: IrFunction): IrStatement { + declaration.transformChildrenVoid(this) + + val body = declaration.body ?: return declaration + + val descriptor = declaration.descriptor + val typeSafeBarrierDescription = BuiltinMethodsWithSpecialGenericSignature.getDefaultValueForOverriddenBuiltinFunction(descriptor) + if (typeSafeBarrierDescription == null || builtBridges.contains(declaration)) + return declaration + + val irBuilder = context.createIrBuilder(declaration.symbol, declaration.startOffset, declaration.endOffset) + declaration.body = irBuilder.irBlockBody(declaration) { + buildTypeSafeBarrier(declaration, declaration, typeSafeBarrierDescription) + (body as IrBlockBody).statements.forEach { +it } + } + return declaration + } + }) + } + + private fun buildBridge(overriddenFunction: OverriddenFunctionInfo, irClass: IrClass) { + irClass.declarations.add(context.buildBridge( + startOffset = irClass.startOffset, + endOffset = irClass.endOffset, + overriddenFunction = overriddenFunction, + targetSymbol = overriddenFunction.function.symbol, + superQualifierSymbol = irClass.symbol) + ) + } +} + +internal class DECLARATION_ORIGIN_BRIDGE_METHOD(val bridgeTarget: IrFunction) : IrDeclarationOrigin { + override fun toString(): String { + return "BRIDGE_METHOD(target=${bridgeTarget.descriptor})" + } +} + +internal val IrFunction.bridgeTarget: IrFunction? + get() = (origin as? DECLARATION_ORIGIN_BRIDGE_METHOD)?.bridgeTarget + +private fun IrBuilderWithScope.returnIfBadType(value: IrExpression, + type: IrType, + returnValueOnFail: IrExpression) + = irIfThen(irNotIs(value, type), irReturn(returnValueOnFail)) + +private fun IrBuilderWithScope.irConst(value: Any?) = when (value) { + null -> irNull() + is Int -> irInt(value) + is Boolean -> if (value) irTrue() else irFalse() + else -> TODO() +} + +private fun IrBlockBodyBuilder.buildTypeSafeBarrier(function: IrFunction, + originalFunction: IrFunction, + typeSafeBarrierDescription: SpecialGenericSignatures.TypeSafeBarrierDescription) { + val valueParameters = function.valueParameters + val originalValueParameters = originalFunction.valueParameters + for (i in valueParameters.indices) { + if (!typeSafeBarrierDescription.checkParameter(i)) + continue + val type = originalValueParameters[i].type + if (!type.isNullableAny()) { + +returnIfBadType(irGet(valueParameters[i]), type, + if (typeSafeBarrierDescription == SpecialGenericSignatures.TypeSafeBarrierDescription.MAP_GET_OR_DEFAULT) + irGet(valueParameters[2]) + else irConst(typeSafeBarrierDescription.defaultValue) + ) + } + } +} + +private fun Context.buildBridge(startOffset: Int, endOffset: Int, + overriddenFunction: OverriddenFunctionInfo, targetSymbol: IrSimpleFunctionSymbol, + superQualifierSymbol: IrClassSymbol? = null): IrFunction { + + val bridge = specialDeclarationsFactory.getBridge(overriddenFunction) + + if (bridge.modality == Modality.ABSTRACT) { + return bridge + } + + val irBuilder = createIrBuilder(bridge.symbol, startOffset, endOffset) + bridge.body = irBuilder.irBlockBody(bridge) { + val typeSafeBarrierDescription = BuiltinMethodsWithSpecialGenericSignature.getDefaultValueForOverriddenBuiltinFunction(overriddenFunction.overriddenFunction.descriptor) + typeSafeBarrierDescription?.let { buildTypeSafeBarrier(bridge, overriddenFunction.function, it) } + + val delegatingCall = IrCallImpl.fromSymbolDescriptor( + startOffset, + endOffset, + targetSymbol.owner.returnType, + targetSymbol, + typeArgumentsCount = targetSymbol.owner.typeParameters.size, + valueArgumentsCount = targetSymbol.owner.valueParameters.size, + superQualifierSymbol = superQualifierSymbol /* Call non-virtually */ + ).apply { + bridge.dispatchReceiverParameter?.let { + dispatchReceiver = irGet(it) + } + bridge.extensionReceiverParameter?.let { + extensionReceiver = irGet(it) + } + bridge.valueParameters.forEachIndexed { index, parameter -> + this.putValueArgument(index, irGet(parameter)) + } + } + + +irReturn(delegatingCall) + } + return bridge +} \ No newline at end of file diff --git a/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/lower/BuiltinOperatorLowering.kt b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/lower/BuiltinOperatorLowering.kt new file mode 100644 index 00000000000..082f34c8240 --- /dev/null +++ b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/lower/BuiltinOperatorLowering.kt @@ -0,0 +1,262 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +package org.jetbrains.kotlin.backend.konan.lower + +import org.jetbrains.kotlin.backend.common.FileLoweringPass +import org.jetbrains.kotlin.backend.common.atMostOne +import org.jetbrains.kotlin.backend.common.ir.simpleFunctions +import org.jetbrains.kotlin.backend.common.lower.IrBuildingTransformer +import org.jetbrains.kotlin.backend.common.lower.at +import org.jetbrains.kotlin.backend.common.lower.irNot +import org.jetbrains.kotlin.backend.konan.* +import org.jetbrains.kotlin.backend.konan.ir.containsNull +import org.jetbrains.kotlin.backend.konan.ir.isSubtypeOf +import org.jetbrains.kotlin.ir.builders.* +import org.jetbrains.kotlin.ir.declarations.IrFile +import org.jetbrains.kotlin.ir.descriptors.IrBuiltinOperatorDescriptor +import org.jetbrains.kotlin.ir.expressions.IrCall +import org.jetbrains.kotlin.ir.expressions.IrExpression +import org.jetbrains.kotlin.ir.expressions.IrTypeOperatorCall +import org.jetbrains.kotlin.ir.expressions.impl.IrCallImpl +import org.jetbrains.kotlin.ir.symbols.IrSimpleFunctionSymbol +import org.jetbrains.kotlin.ir.types.makeNullable +import org.jetbrains.kotlin.ir.builders.irGet +import org.jetbrains.kotlin.ir.declarations.IrClass +import org.jetbrains.kotlin.ir.declarations.IrDeclarationOrigin +import org.jetbrains.kotlin.ir.symbols.IrFunctionSymbol +import org.jetbrains.kotlin.ir.types.IrType +import org.jetbrains.kotlin.ir.types.isNothing +import org.jetbrains.kotlin.ir.util.* +import org.jetbrains.kotlin.ir.util.defaultOrNullableType +import org.jetbrains.kotlin.ir.util.isNullConst +import org.jetbrains.kotlin.ir.visitors.transformChildrenVoid + +/** + * This lowering pass lowers some calls to [IrBuiltinOperatorDescriptor]s. + */ +internal class BuiltinOperatorLowering(val context: Context) : FileLoweringPass, IrBuildingTransformer(context) { + + private val irBuiltins = context.irModule!!.irBuiltins + private val symbols = context.ir.symbols + + override fun lower(irFile: IrFile) { + irFile.transformChildrenVoid(this) + } + + override fun visitCall(expression: IrCall): IrExpression { + expression.transformChildrenVoid(this) + + return when (expression.symbol) { + irBuiltins.eqeqSymbol, in ieee754EqualsSymbols() -> lowerEqeq(expression) + + irBuiltins.eqeqeqSymbol -> lowerEqeqeq(expression) + + irBuiltins.checkNotNullSymbol -> lowerCheckNotNull(expression) + + irBuiltins.noWhenBranchMatchedExceptionSymbol -> IrCallImpl.fromSymbolDescriptor( + expression.startOffset, expression.endOffset, + context.ir.symbols.throwNoWhenBranchMatchedException.owner.returnType, + context.ir.symbols.throwNoWhenBranchMatchedException, + context.ir.symbols.throwNoWhenBranchMatchedException.owner.typeParameters.size, + context.ir.symbols.throwNoWhenBranchMatchedException.owner.valueParameters.size) + + else -> expression + } + } + + override fun visitTypeOperator(expression: IrTypeOperatorCall): IrExpression { + expression.transformChildrenVoid(this) + if (expression.argument.type.isNothing()) { + return expression.argument + } + return expression + } + + private fun ieee754EqualsSymbols(): List = + irBuiltins.ieee754equalsFunByOperandType.values.toList() + + private fun lowerEqeqeq(expression: IrCall): IrExpression { + val lhs = expression.getValueArgument(0)!! + val rhs = expression.getValueArgument(1)!! + + return if (lhs.type.isInlinedNative() && rhs.type.isInlinedNative()) { + // Achieve the same behavior as with JVM BE: if both sides of `===` are values, then compare by value: + lowerEqeq(expression) + // Note: such comparisons are deprecated. + } else { + expression + } + } + + private fun IrBuilderWithScope.reinterpret(expression: IrExpression, toType: IrType) = + reinterpret(expression, expression.type, toType) + + private fun IrBuilderWithScope.reinterpret(expression: IrExpression, fromType: IrType, toType: IrType) = + irCall(symbols.reinterpret.owner, listOf(fromType, toType)).apply { + extensionReceiver = expression + } + + private val anyEquals = irBuiltins.anyClass.owner.simpleFunctions().single { it.name.asString() == "equals" } + + private fun lowerEqeq(expression: IrCall): IrExpression { + // TODO: optimize boxing? + + builder.at(expression).run { + val lhs = expression.getValueArgument(0)!! + val rhs = expression.getValueArgument(1)!! + + if (rhs.isNullConst()) { + return irEqeqNull(lhs) + } + + if (lhs.isNullConst()) { + return irEqeqNull(rhs) + } + + if (expression.symbol == irBuiltins.eqeqSymbol) { + lhs.type.getInlinedClassNative()?.let { + if (it == rhs.type.getInlinedClassNative() && inlinedClassHasDefaultEquals(it)) { + return genInlineClassEquals(expression.symbol, rhs, lhs) + } + } + } + + return genFloatingOrReferenceEquals(expression.symbol, lhs, rhs) + } + } + + private fun inlinedClassHasDefaultEquals(irClass: IrClass): Boolean { + if (!irClass.descriptor.isInline) { + // Implicitly-inlined class, e.g. primitive one. + return true + } + + val equals = irClass.simpleFunctions() + .single { it.name.asString() == "equals" && it.valueParameters.size == 1 && it.overrides(anyEquals) } + + return equals.origin == IrDeclarationOrigin.GENERATED_INLINE_CLASS_MEMBER + } + + fun IrBuilderWithScope.genInlineClassEquals( + symbol: IrFunctionSymbol, + rhs: IrExpression, + lhs: IrExpression + ): IrExpression { + val lhsBinaryType = lhs.type.computeBinaryType() + return when (lhsBinaryType) { + is BinaryType.Primitive -> { + val areEqualByValue = symbols.areEqualByValue[lhsBinaryType.type]!!.owner + irCall(areEqualByValue).apply { + putValueArgument(0, reinterpret(lhs, areEqualByValue.valueParameters[0].type)) + putValueArgument(1, reinterpret(rhs, areEqualByValue.valueParameters[1].type)) + } + } + + is BinaryType.Reference -> { + // TODO: don't use binaryType.nullable. + val lhsRawType = irBuiltins.anyClass.owner.defaultOrNullableType(lhsBinaryType.nullable) + val rhsBinaryType = rhs.type.computeBinaryType() as BinaryType.Reference<*> + val rhsRawType = irBuiltins.anyClass.owner.defaultOrNullableType(rhsBinaryType.nullable) + + genFloatingOrReferenceEquals( + symbol, + reinterpret(lhs, lhsRawType), + reinterpret(rhs, rhsRawType) + ) + } + } + } + + private fun IrBuilderWithScope.irEqeqNull(expression: IrExpression): IrExpression { + val type = expression.type.makeNullable() + return when (val primitiveBinaryTypeOrNull = type.computePrimitiveBinaryTypeOrNull()) { + null -> irEqeqeq(reinterpret(expression, type, irBuiltins.anyNType), irNull()) + PrimitiveBinaryType.POINTER -> irCall(symbols.areEqualByValue[PrimitiveBinaryType.POINTER]!!.owner).apply { + putValueArgument(0, reinterpret(expression, type, symbols.nativePtrType)) + putValueArgument(1, reinterpret(irNull(), type, symbols.nativePtrType)) + } + else -> error("Nullable type ${type.render()} is $primitiveBinaryTypeOrNull") + } + } + + private fun lowerCheckNotNull(expression: IrCall) = builder.at(expression).irBlock(resultType = expression.type) { + val temp = irTemporary(expression.getValueArgument(0)!!) + +irIfThen(context.irBuiltIns.unitType, irEqeqNull(irGet(temp)), irCall(symbols.throwNullPointerException)) + +irGet(temp) + } + + private fun IrBuilderWithScope.irLogicalAnd(lhs: IrExpression, rhs: IrExpression) = context.andand(lhs, rhs) + private fun IrBuilderWithScope.irIsNull(exp: IrExpression) = irEqeqeq(exp, irNull()) + private fun IrBuilderWithScope.irIsNotNull(exp: IrExpression) = irNot(irEqeqeq(exp, irNull())) + + private fun IrBuilderWithScope.genFloatingOrReferenceEquals(symbol: IrFunctionSymbol, lhs: IrExpression, rhs: IrExpression): IrExpression { + // TODO: areEqualByValue and ieee754Equals intrinsics are specially treated by code generator + // and thus can be declared synthetically in the compiler instead of explicitly in the runtime. + fun callEquals(lhs: IrExpression, rhs: IrExpression) = + if (symbol in ieee754EqualsSymbols()) + // Find a type-compatible `konan.internal.ieee754Equals` intrinsic: + irCall(selectIntrinsic(symbols.ieee754Equals, lhs.type, rhs.type, true)!!).apply { + putValueArgument(0, lhs) + putValueArgument(1, rhs) + } + else + irCall(symbols.equals).apply { + dispatchReceiver = lhs + putValueArgument(0, rhs) + } + + val lhsIsNotNullable = !lhs.type.containsNull() + val rhsIsNotNullable = !rhs.type.containsNull() + + return if (symbol in ieee754EqualsSymbols()) { + if (lhsIsNotNullable && rhsIsNotNullable) + callEquals(lhs, rhs) + else irBlock { + val lhsTemp = irTemporary(lhs) + val rhsTemp = irTemporary(rhs) + if (lhsIsNotNullable xor rhsIsNotNullable) { // Exactly one nullable. + +irLogicalAnd( + irIsNotNull(irGet(if (lhsIsNotNullable) rhsTemp else lhsTemp)), + callEquals(irGet(lhsTemp), irGet(rhsTemp)) + ) + } else { // Both are nullable. + +irIfThenElse(context.irBuiltIns.booleanType, irIsNull(irGet(lhsTemp)), + irIsNull(irGet(rhsTemp)), + irLogicalAnd( + irIsNotNull(irGet(rhsTemp)), + callEquals(irGet(lhsTemp), irGet(rhsTemp)) + ) + ) + } + } + } else { + if (lhsIsNotNullable) + callEquals(lhs, rhs) + else { + irBlock { + val lhsTemp = irTemporary(lhs) + if (rhsIsNotNullable) + +irLogicalAnd(irIsNotNull(irGet(lhsTemp)), callEquals(irGet(lhsTemp), rhs)) + else { + val rhsTemp = irTemporary(rhs) + +irIfThenElse(irBuiltins.booleanType, irIsNull(irGet(lhsTemp)), + irIsNull(irGet(rhsTemp)), + callEquals(irGet(lhsTemp), irGet(rhsTemp)) + ) + } + } + } + } + } + + private fun selectIntrinsic(from: List, lhsType: IrType, rhsType: IrType, allowNullable: Boolean) = + from.atMostOne { + val leftParamType = it.owner.valueParameters[0].type + val rightParamType = it.owner.valueParameters[1].type + (lhsType.isSubtypeOf(leftParamType) || (allowNullable && lhsType.isSubtypeOf(leftParamType.makeNullable()))) + && (rhsType.isSubtypeOf(rightParamType) || (allowNullable && rhsType.isSubtypeOf(rightParamType.makeNullable()))) + } +} diff --git a/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/lower/CompileTimeEvaluateLowering.kt b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/lower/CompileTimeEvaluateLowering.kt new file mode 100644 index 00000000000..a4648eb2f1e --- /dev/null +++ b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/lower/CompileTimeEvaluateLowering.kt @@ -0,0 +1,50 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +package org.jetbrains.kotlin.backend.konan.lower + +import org.jetbrains.kotlin.backend.common.FileLoweringPass +import org.jetbrains.kotlin.backend.common.lower.IrBuildingTransformer +import org.jetbrains.kotlin.backend.common.lower.at +import org.jetbrains.kotlin.backend.konan.Context +import org.jetbrains.kotlin.ir.declarations.IrFile +import org.jetbrains.kotlin.ir.expressions.* +import org.jetbrains.kotlin.ir.types.isString +import org.jetbrains.kotlin.ir.util.fqNameForIrSerialization +import org.jetbrains.kotlin.ir.util.irCall +import org.jetbrains.kotlin.ir.visitors.transformChildrenVoid + +internal class CompileTimeEvaluateLowering(val context: Context): FileLoweringPass { + + override fun lower(irFile: IrFile) { + irFile.transformChildrenVoid(object: IrBuildingTransformer(context) { + override fun visitCall(expression: IrCall): IrExpression { + expression.transformChildrenVoid(this) + + val callee = expression.symbol.owner + // TODO + if (callee.fqNameForIrSerialization.asString() != "kotlin.collections.listOf" || callee.valueParameters.size != 1) + return expression + val elementsArr = expression.getValueArgument(0) as? IrVararg + ?: return expression + + // The function is kotlin.collections.listOf(vararg args: T). + // TODO: refer functions more reliably. + + if (elementsArr.elements.any { it is IrSpreadElement } + || !elementsArr.elements.all { it is IrConst<*> && it.type.isString() }) + return expression + + + builder.at(expression) + + val typeArgument = expression.getTypeArgument(0)!! + return builder.irCall(context.ir.symbols.listOfInternal.owner, listOf(typeArgument)).apply { + putValueArgument(0, elementsArr) + } + } + }) + } +} \ No newline at end of file diff --git a/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/lower/ContractsDslRemover.kt b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/lower/ContractsDslRemover.kt new file mode 100644 index 00000000000..79876d8f4be --- /dev/null +++ b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/lower/ContractsDslRemover.kt @@ -0,0 +1,25 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +package org.jetbrains.kotlin.backend.konan.lower + +import org.jetbrains.kotlin.backend.common.DeclarationContainerLoweringPass +import org.jetbrains.kotlin.backend.konan.Context +import org.jetbrains.kotlin.contracts.parsing.ContractsDslNames +import org.jetbrains.kotlin.ir.declarations.IrClass +import org.jetbrains.kotlin.ir.declarations.IrDeclarationContainer +import org.jetbrains.kotlin.ir.util.hasAnnotation +import org.jetbrains.kotlin.ir.util.transformFlat + +internal class ContractsDslRemover(val context: Context) : DeclarationContainerLoweringPass { + override fun lower(irDeclarationContainer: IrDeclarationContainer) { + irDeclarationContainer.declarations.transformFlat { + if (it is IrClass && it.annotations.hasAnnotation(ContractsDslNames.CONTRACTS_DSL_ANNOTATION_FQN)) + null + else + listOf(it) + } + } +} \ No newline at end of file diff --git a/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/lower/DataClassOperatorsLowering.kt b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/lower/DataClassOperatorsLowering.kt new file mode 100644 index 00000000000..a7811d311e3 --- /dev/null +++ b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/lower/DataClassOperatorsLowering.kt @@ -0,0 +1,80 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +package org.jetbrains.kotlin.backend.konan.lower + +import org.jetbrains.kotlin.backend.common.FileLoweringPass +import org.jetbrains.kotlin.backend.common.lower.createIrBuilder +import org.jetbrains.kotlin.backend.common.lower.irBlock +import org.jetbrains.kotlin.backend.konan.Context +import org.jetbrains.kotlin.ir.IrStatement +import org.jetbrains.kotlin.ir.builders.* +import org.jetbrains.kotlin.ir.declarations.IrFile +import org.jetbrains.kotlin.ir.declarations.IrFunction +import org.jetbrains.kotlin.ir.expressions.IrCall +import org.jetbrains.kotlin.ir.expressions.IrExpression +import org.jetbrains.kotlin.ir.types.classifierOrFail +import org.jetbrains.kotlin.ir.util.irCall +import org.jetbrains.kotlin.ir.util.isSimpleTypeWithQuestionMark +import org.jetbrains.kotlin.ir.visitors.IrElementTransformer + +internal class DataClassOperatorsLowering(val context: Context) : FileLoweringPass, IrElementTransformer { + private val irBuiltins = context.irModule!!.irBuiltins + + override fun lower(irFile: IrFile) { + irFile.transformChildren(this, null) + } + + override fun visitFunction(declaration: IrFunction, data: IrFunction?): IrStatement = + super.visitFunction(declaration, declaration) + + override fun visitCall(expression: IrCall, data: IrFunction?): IrExpression { + expression.transformChildren(this, data) + + if (expression.symbol != irBuiltins.dataClassArrayMemberToStringSymbol + && expression.symbol != irBuiltins.dataClassArrayMemberHashCodeSymbol) + return expression + + val argument = expression.getValueArgument(0)!! + val argumentClassifier = argument.type.classifierOrFail + + val isToString = expression.symbol == irBuiltins.dataClassArrayMemberToStringSymbol + val newCalleeSymbol = if (isToString) + context.ir.symbols.arrayContentToString[argumentClassifier]!! + else + context.ir.symbols.arrayContentHashCode[argumentClassifier]!! + + val newCallee = newCalleeSymbol.owner + + val startOffset = expression.startOffset + val endOffset = expression.endOffset + val irBuilder = context.createIrBuilder(data!!.symbol, startOffset, endOffset) + + return irBuilder.run { + // TODO: use more precise type arguments. + val typeArguments = (0 until newCallee.typeParameters.size).map { irBuiltins.anyNType } + + if (!argument.type.isSimpleTypeWithQuestionMark) { + irCall(newCallee, typeArguments).apply { + extensionReceiver = argument + } + } else { + irBlock(argument) { + val tmp = irTemporary(argument) + val call = irCall(newCallee, typeArguments).apply { + extensionReceiver = irGet(tmp) + } + +irIfThenElse(call.type, + irEqeqeq(irGet(tmp), irNull()), + if (isToString) + irString("null") + else + irInt(0), + call) + } + } + } + } +} diff --git a/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/lower/DelegationLowering.kt b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/lower/DelegationLowering.kt new file mode 100644 index 00000000000..ccfde9d4e9b --- /dev/null +++ b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/lower/DelegationLowering.kt @@ -0,0 +1,300 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +package org.jetbrains.kotlin.backend.konan.lower + +import org.jetbrains.kotlin.backend.common.FileLoweringPass +import org.jetbrains.kotlin.backend.common.IrElementTransformerVoidWithContext +import org.jetbrains.kotlin.backend.common.lower.createIrBuilder +import org.jetbrains.kotlin.backend.common.lower.irBlock +import org.jetbrains.kotlin.backend.konan.Context +import org.jetbrains.kotlin.backend.konan.descriptors.synthesizedName +import org.jetbrains.kotlin.backend.konan.ir.buildSimpleAnnotation +import org.jetbrains.kotlin.descriptors.* +import org.jetbrains.kotlin.ir.builders.* +import org.jetbrains.kotlin.ir.declarations.* +import org.jetbrains.kotlin.ir.declarations.impl.IrFieldImpl +import org.jetbrains.kotlin.ir.descriptors.WrappedFieldDescriptor +import org.jetbrains.kotlin.ir.expressions.IrExpression +import org.jetbrains.kotlin.ir.expressions.IrLocalDelegatedPropertyReference +import org.jetbrains.kotlin.ir.expressions.IrPropertyReference +import org.jetbrains.kotlin.ir.expressions.impl.* +import org.jetbrains.kotlin.ir.symbols.IrConstructorSymbol +import org.jetbrains.kotlin.ir.symbols.impl.IrFieldSymbolImpl +import org.jetbrains.kotlin.ir.types.* +import org.jetbrains.kotlin.ir.types.IrType +import org.jetbrains.kotlin.ir.types.typeWith +import org.jetbrains.kotlin.ir.util.* +import org.jetbrains.kotlin.ir.visitors.transformChildrenVoid +import org.jetbrains.kotlin.name.Name + +internal class PropertyDelegationLowering(val context: Context) : FileLoweringPass { + private var tempIndex = 0 + + private fun getKPropertyImplConstructor(receiverTypes: List, + returnType: IrType, + isLocal: Boolean, + isMutable: Boolean) : Pair> { + + val symbols = context.ir.symbols + + val classSymbol = + if (isLocal) { + assert(receiverTypes.isEmpty()) { "Local delegated property cannot have explicit receiver" } + when { + isMutable -> symbols.kLocalDelegatedMutablePropertyImpl + else -> symbols.kLocalDelegatedPropertyImpl + } + } else { + when (receiverTypes.size) { + 0 -> when { + isMutable -> symbols.kMutableProperty0Impl + else -> symbols.kProperty0Impl + } + 1 -> when { + isMutable -> symbols.kMutableProperty1Impl + else -> symbols.kProperty1Impl + } + 2 -> when { + isMutable -> symbols.kMutableProperty2Impl + else -> symbols.kProperty2Impl + } + else -> throw AssertionError("More than 2 receivers is not allowed") + } + } + + val arguments = (receiverTypes + listOf(returnType)) + + return classSymbol.constructors.single() to arguments + } + + override fun lower(irFile: IrFile) { + // Somehow there is no reasonable common ancestor for IrProperty and IrLocalDelegatedProperty, + // so index by IrDeclaration. + val kProperties = mutableMapOf>() + + val arrayClass = context.ir.symbols.array.owner + + val arrayItemGetter = arrayClass.functions.single { it.name == Name.identifier("get") } + + val anyType = context.irBuiltIns.anyType + val kPropertyImplType = context.ir.symbols.kProperty1Impl.typeWith(anyType, anyType) + + val kPropertiesFieldType: IrType = context.ir.symbols.array.typeWith(kPropertyImplType) + + val kPropertiesField = WrappedFieldDescriptor().let { + IrFieldImpl( + SYNTHETIC_OFFSET, SYNTHETIC_OFFSET, + DECLARATION_ORIGIN_KPROPERTIES_FOR_DELEGATION, + IrFieldSymbolImpl(it), + "KPROPERTIES".synthesizedName, + kPropertiesFieldType, + DescriptorVisibilities.PRIVATE, + isFinal = true, + isExternal = false, + isStatic = true, + ).apply { + it.bind(this) + parent = irFile + annotations += buildSimpleAnnotation(context.irBuiltIns, startOffset, endOffset, context.ir.symbols.sharedImmutable.owner) + } + } + + irFile.transformChildrenVoid(object : IrElementTransformerVoidWithContext() { + + override fun visitPropertyReference(expression: IrPropertyReference): IrExpression { + expression.transformChildrenVoid(this) + + val kTypeGenerator = KTypeGenerator(context, irFile, expression) + val startOffset = expression.startOffset + val endOffset = expression.endOffset + val irBuilder = context.createIrBuilder(currentScope!!.scope.scopeOwnerSymbol, startOffset, endOffset) + irBuilder.run { + val receiversCount = listOf(expression.dispatchReceiver, expression.extensionReceiver).count { it != null } + return when (receiversCount) { + 1 -> createKProperty(expression, kTypeGenerator, this) // Has receiver. + + 2 -> error("Callable reference to properties with two receivers is not allowed: ${expression.symbol.owner.name}") + + else -> { // Cache KProperties with no arguments. + val field = kProperties.getOrPut(expression.symbol.owner) { + createKProperty(expression, kTypeGenerator, this) to kProperties.size + } + + irCall(arrayItemGetter).apply { + dispatchReceiver = irGetField(null, kPropertiesField) + putValueArgument(0, irInt(field.second)) + } + } + } + } + } + + override fun visitLocalDelegatedPropertyReference(expression: IrLocalDelegatedPropertyReference): IrExpression { + expression.transformChildrenVoid(this) + + val startOffset = expression.startOffset + val endOffset = expression.endOffset + val irBuilder = context.createIrBuilder(currentScope!!.scope.scopeOwnerSymbol, startOffset, endOffset) + irBuilder.run { + val receiversCount = listOf(expression.dispatchReceiver, expression.extensionReceiver).count { it != null } + if (receiversCount == 2) + throw AssertionError("Callable reference to properties with two receivers is not allowed: ${expression}") + else { // Cache KProperties with no arguments. + // TODO: what about `receiversCount == 1` case? + val field = kProperties.getOrPut(expression.symbol.owner) { + createLocalKProperty( + expression.symbol.owner.name.asString(), + expression.getter.owner.returnType, + KTypeGenerator(this@PropertyDelegationLowering.context, irFile, expression), + this + ) to kProperties.size + } + + return irCall(arrayItemGetter).apply { + dispatchReceiver = irGetField(null, kPropertiesField) + putValueArgument(0, irInt(field.second)) + } + } + } + } + }) + + if (kProperties.isNotEmpty()) { + val initializers = kProperties.values.sortedBy { it.second }.map { it.first } + // TODO: move to object for lazy initialization. + irFile.declarations.add(0, kPropertiesField.apply { + initializer = IrExpressionBodyImpl(startOffset, endOffset, + context.createArrayOfExpression(startOffset, endOffset, kPropertyImplType, initializers)) + }) + } + } + + private fun createKProperty( + expression: IrPropertyReference, + kTypeGenerator: KTypeGenerator, + irBuilder: IrBuilderWithScope + ): IrExpression { + val startOffset = expression.startOffset + val endOffset = expression.endOffset + return irBuilder.irBlock(expression) { + val receiverTypes = mutableListOf() + val dispatchReceiver = expression.dispatchReceiver.let { + if (it == null) + null + else + irTemporary(value = it, nameHint = "\$dispatchReceiver${tempIndex++}") + } + val extensionReceiver = expression.extensionReceiver.let { + if (it == null) + null + else + irTemporary(value = it, nameHint = "\$extensionReceiver${tempIndex++}") + } + val returnType = expression.getter?.owner?.returnType ?: expression.field!!.owner.type + + val getterCallableReference = expression.getter?.owner?.let { getter -> + getter.extensionReceiverParameter.let { + if (it != null && expression.extensionReceiver == null) + receiverTypes.add(it.type) + } + getter.dispatchReceiverParameter.let { + if (it != null && expression.dispatchReceiver == null) + receiverTypes.add(it.type) + } + val getterKFunctionType = this@PropertyDelegationLowering.context.ir.symbols.getKFunctionType( + returnType, + receiverTypes + ) + IrFunctionReferenceImpl( + startOffset = startOffset, + endOffset = endOffset, + type = getterKFunctionType, + symbol = expression.getter!!, + typeArgumentsCount = getter.typeParameters.size, + valueArgumentsCount = getter.valueParameters.size, + reflectionTarget = expression.getter!! + ).apply { + this.dispatchReceiver = dispatchReceiver?.let { irGet(it) } + this.extensionReceiver = extensionReceiver?.let { irGet(it) } + for (index in 0 until expression.typeArgumentsCount) + putTypeArgument(index, expression.getTypeArgument(index)) + } + } + + val setterCallableReference = expression.setter?.owner?.let { setter -> + if (!isKMutablePropertyType(expression.type)) null + else { + val setterKFunctionType = this@PropertyDelegationLowering.context.ir.symbols.getKFunctionType( + context.irBuiltIns.unitType, + receiverTypes + returnType + ) + IrFunctionReferenceImpl( + startOffset = startOffset, + endOffset = endOffset, + type = setterKFunctionType, + symbol = expression.setter!!, + typeArgumentsCount = setter.typeParameters.size, + valueArgumentsCount = setter.valueParameters.size, + reflectionTarget = expression.setter!! + ).apply { + this.dispatchReceiver = dispatchReceiver?.let { irGet(it) } + this.extensionReceiver = extensionReceiver?.let { irGet(it) } + for (index in 0 until expression.typeArgumentsCount) + putTypeArgument(index, expression.getTypeArgument(index)) + } + } + } + + val (symbol, constructorTypeArguments) = getKPropertyImplConstructor( + receiverTypes = receiverTypes, + returnType = returnType, + isLocal = false, + isMutable = setterCallableReference != null) + val initializer = irCall(symbol.owner, constructorTypeArguments).apply { + putValueArgument(0, irString(expression.symbol.owner.name.asString())) + putValueArgument(1, with(kTypeGenerator) { irKType(returnType) }) + if (getterCallableReference != null) + putValueArgument(2, getterCallableReference) + if (setterCallableReference != null) + putValueArgument(3, setterCallableReference) + } + +initializer + } + } + + private fun createLocalKProperty(propertyName: String, + propertyType: IrType, + kTypeGenerator: KTypeGenerator, + irBuilder: IrBuilderWithScope): IrExpression { + irBuilder.run { + val (symbol, constructorTypeArguments) = getKPropertyImplConstructor( + receiverTypes = emptyList(), + returnType = propertyType, + isLocal = true, + isMutable = false) + val initializer = irCall(symbol.owner, constructorTypeArguments).apply { + putValueArgument(0, irString(propertyName)) + putValueArgument(1, with(kTypeGenerator) { irKType(propertyType) }) + } + return initializer + } + } + + private fun isKMutablePropertyType(type: IrType): Boolean { + if (type !is IrSimpleType) return false + val expectedClass = when (type.arguments.size) { + 0 -> return false + 1 -> context.ir.symbols.kMutableProperty0 + 2 -> context.ir.symbols.kMutableProperty1 + 3 -> context.ir.symbols.kMutableProperty2 + else -> throw AssertionError("More than 2 receivers is not allowed") + } + return type.classifier == expectedClass + } + + private object DECLARATION_ORIGIN_KPROPERTIES_FOR_DELEGATION : + IrDeclarationOriginImpl("KPROPERTIES_FOR_DELEGATION") +} diff --git a/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/lower/EnumClassLowering.kt b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/lower/EnumClassLowering.kt new file mode 100644 index 00000000000..ad89024f187 --- /dev/null +++ b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/lower/EnumClassLowering.kt @@ -0,0 +1,343 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +package org.jetbrains.kotlin.backend.konan.lower + +import org.jetbrains.kotlin.backend.common.ClassLoweringPass +import org.jetbrains.kotlin.backend.common.FileLoweringPass +import org.jetbrains.kotlin.backend.common.lower.EnumWhenLowering +import org.jetbrains.kotlin.backend.common.lower.createIrBuilder +import org.jetbrains.kotlin.backend.common.lower.irBlockBody +import org.jetbrains.kotlin.backend.common.runOnFilePostfix +import org.jetbrains.kotlin.backend.konan.Context +import org.jetbrains.kotlin.backend.konan.DECLARATION_ORIGIN_ENUM +import org.jetbrains.kotlin.backend.konan.llvm.IntrinsicType +import org.jetbrains.kotlin.backend.konan.llvm.tryGetIntrinsicType +import org.jetbrains.kotlin.descriptors.ClassKind +import org.jetbrains.kotlin.ir.builders.* +import org.jetbrains.kotlin.ir.declarations.* +import org.jetbrains.kotlin.ir.declarations.impl.IrPropertyImpl +import org.jetbrains.kotlin.ir.expressions.* +import org.jetbrains.kotlin.ir.expressions.IrStatementOrigin.ARGUMENTS_REORDERING_FOR_CALL +import org.jetbrains.kotlin.ir.expressions.impl.* +import org.jetbrains.kotlin.ir.symbols.IrClassSymbol +import org.jetbrains.kotlin.ir.symbols.impl.IrPropertySymbolImpl +import org.jetbrains.kotlin.ir.types.classifierOrNull +import org.jetbrains.kotlin.ir.types.typeWith +import org.jetbrains.kotlin.ir.util.* +import org.jetbrains.kotlin.ir.visitors.IrElementTransformerVoid +import org.jetbrains.kotlin.ir.visitors.transformChildrenVoid +import org.jetbrains.kotlin.name.Name + +private class EnumSyntheticFunctionsBuilder(val context: Context) { + fun buildValuesExpression(startOffset: Int, endOffset: Int, + enumClass: IrClass): IrExpression { + + val loweredEnum = context.specialDeclarationsFactory.getLoweredEnum(enumClass) + + return irCall(startOffset, endOffset, genericValuesSymbol.owner, listOf(enumClass.defaultType)) + .apply { + putValueArgument(0, loweredEnum.getValuesField(startOffset, endOffset)) + } + } + + fun buildValueOfExpression(startOffset: Int, endOffset: Int, + enumClass: IrClass, + value: IrExpression): IrExpression { + val loweredEnum = context.specialDeclarationsFactory.getLoweredEnum(enumClass) + + return irCall(startOffset, endOffset, genericValueOfSymbol.owner, listOf(enumClass.defaultType)) + .apply { + putValueArgument(0, value) + putValueArgument(1, loweredEnum.getValuesField(startOffset, endOffset)) + } + } + + private val genericValueOfSymbol = context.ir.symbols.valueOfForEnum + + private val genericValuesSymbol = context.ir.symbols.valuesForEnum +} + +internal class EnumUsageLowering(val context: Context) + : IrElementTransformerVoid(), FileLoweringPass { + + private val enumSyntheticFunctionsBuilder = EnumSyntheticFunctionsBuilder(context) + + override fun lower(irFile: IrFile) { + visitFile(irFile) + } + + override fun visitGetEnumValue(expression: IrGetEnumValue): IrExpression { + val entry = expression.symbol.owner + return loadEnumEntry( + expression.startOffset, + expression.endOffset, + entry.parentAsClass, + entry.name + ) + } + + override fun visitCall(expression: IrCall): IrExpression { + expression.transformChildrenVoid(this) + + val intrinsicType = tryGetIntrinsicType(expression) + if (intrinsicType != IntrinsicType.ENUM_VALUES && intrinsicType != IntrinsicType.ENUM_VALUE_OF) + return expression + + val startOffset = expression.startOffset + val endOffset = expression.endOffset + val irClassSymbol = expression.getTypeArgument(0)!!.classifierOrNull as? IrClassSymbol + + if (irClassSymbol == null || irClassSymbol == context.ir.symbols.enum) { + // Either a type parameter or a type parameter erased to 'Enum'. + return irCall(startOffset, endOffset, context.ir.symbols.throwIllegalStateException.owner, emptyList()) + } + + val irClass = irClassSymbol.owner + + assert (irClass.kind == ClassKind.ENUM_CLASS) + + return if (intrinsicType == IntrinsicType.ENUM_VALUES) { + enumSyntheticFunctionsBuilder.buildValuesExpression(startOffset, endOffset, irClass) + } else { + val value = expression.getValueArgument(0)!! + enumSyntheticFunctionsBuilder.buildValueOfExpression(startOffset, endOffset, irClass, value) + } + } + + private fun loadEnumEntry(startOffset: Int, endOffset: Int, enumClass: IrClass, name: Name): IrExpression { + val loweredEnum = context.specialDeclarationsFactory.getLoweredEnum(enumClass) + val ordinal = loweredEnum.entriesMap.getValue(name) + return IrCallImpl.fromSymbolDescriptor( + startOffset, endOffset, enumClass.defaultType, + loweredEnum.itemGetterSymbol.owner.symbol, + typeArgumentsCount = 0, + loweredEnum.itemGetterSymbol.owner.valueParameters.size + ).apply { + dispatchReceiver = IrCallImpl(startOffset, endOffset, loweredEnum.valuesGetter.returnType, + loweredEnum.valuesGetter.symbol, loweredEnum.valuesGetter.typeParameters.size, + loweredEnum.valuesGetter.valueParameters.size) + putValueArgument(0, IrConstImpl.int(startOffset, endOffset, context.irBuiltIns.intType, ordinal)) + } + } +} + +internal class EnumClassLowering(val context: Context) : ClassLoweringPass { + + fun run(irFile: IrFile) { + // EnumWhenLowering should be performed before EnumUsageLowering because + // the latter performs lowering of IrGetEnumValue + EnumWhenLowering(context).lower(irFile) + runOnFilePostfix(irFile) + EnumUsageLowering(context).lower(irFile) + } + + override fun lower(irClass: IrClass) { + if (irClass.kind != ClassKind.ENUM_CLASS) return + EnumClassTransformer(irClass).run() + } + + private inner class EnumClassTransformer(val irClass: IrClass) { + private val loweredEnum = context.specialDeclarationsFactory.getInternalLoweredEnum(irClass) + private val enumSyntheticFunctionsBuilder = EnumSyntheticFunctionsBuilder(context) + + fun run() { + pullUpEnumEntriesClasses() + createImplObject() + } + + private fun pullUpEnumEntriesClasses() { + irClass.declarations.transformFlat { declaration -> + if (declaration is IrEnumEntry) { + val correspondingClass = declaration.correspondingClass + declaration.correspondingClass = null + listOfNotNull(declaration, correspondingClass) + } else null + } + } + + private fun createImplObject() { + val implObject = loweredEnum.implObject + + val enumEntries = mutableListOf() + var i = 0 + while (i < irClass.declarations.size) { + val declaration = irClass.declarations[i] + var delete = false + when (declaration) { + is IrEnumEntry -> { + enumEntries.add(declaration) + delete = true + } + is IrFunction -> { + val body = declaration.body + if (body is IrSyntheticBody) { + when (body.kind) { + IrSyntheticBodyKind.ENUM_VALUEOF -> + declaration.body = createSyntheticValueOfMethodBody(declaration) + IrSyntheticBodyKind.ENUM_VALUES -> + declaration.body = createSyntheticValuesMethodBody(declaration) + } + } + } + } + if (delete) + irClass.declarations.removeAt(i) + else + ++i + } + + implObject.declarations += createSyntheticValuesPropertyDeclaration(enumEntries) + + + irClass.declarations += implObject + } + + private val createUninitializedInstance = context.ir.symbols.createUninitializedInstance.owner + + private fun createSyntheticValuesPropertyDeclaration(enumEntries: List): IrProperty { + val startOffset = irClass.startOffset + val endOffset = irClass.endOffset + + val implObject = loweredEnum.implObject + val constructor = implObject.constructors.single() + + val irValuesInitializer = context.createArrayOfExpression( + startOffset, endOffset, + irClass.defaultType, + enumEntries + .sortedBy { it.name } + .map { + val initializer = it.initializerExpression?.expression + val entryConstructorCall = when { + initializer is IrConstructorCall -> initializer + + initializer is IrBlock && initializer.origin == ARGUMENTS_REORDERING_FOR_CALL -> + initializer.statements.last() as IrConstructorCall + + else -> error("Unexpected initializer: $initializer") + } + val entryClass = entryConstructorCall.symbol.owner.constructedClass + + irCall(startOffset, endOffset, + createUninitializedInstance, + listOf(entryClass.defaultType) + ) + + } + ) + val irField = loweredEnum.valuesField + context.createIrBuilder(constructor.symbol).run { + (constructor.body as IrBlockBody).statements += + irSetField(irGet(implObject.thisReceiver!!), irField, irValuesInitializer) + } + + val getter = loweredEnum.valuesGetter + context.createIrBuilder(getter.symbol).run { + getter.body = irBlockBody(irClass) { +irReturn(irGetField(irGetObject(implObject.symbol), irField)) } + } + + createValuesPropertyInitializer(enumEntries) + + return with(loweredEnum.valuesField.descriptor) { + IrPropertyImpl( + startOffset, endOffset, DECLARATION_ORIGIN_ENUM, IrPropertySymbolImpl(this), + name, visibility, modality, isVar, isConst, isLateInit, isDelegated, isExternal + ).apply { + this.backingField = irField + this.getter = getter + this.parent = implObject + } + } + } + + private val initInstanceSymbol = context.ir.symbols.initInstance + + private val arrayGetSymbol = context.ir.symbols.array.functions.single { it.owner.name == Name.identifier("get") } + + private val arrayType = context.ir.symbols.array.typeWith(irClass.defaultType) + + private fun createValuesPropertyInitializer(enumEntries: List) { + val startOffset = irClass.startOffset + val endOffset = irClass.endOffset + + fun IrBlockBuilder.initInstanceCall(instance: IrCall, constructor: IrConstructorCall): IrCall = + irCall(initInstanceSymbol).apply { + putValueArgument(0, instance) + putValueArgument(1, constructor) + } + + val implObject = loweredEnum.implObject + val constructor = implObject.constructors.single() + val irBuilder = context.createIrBuilder(constructor.symbol, startOffset, endOffset) + val valuesInitializer = irBuilder.irBlock(startOffset, endOffset) { + val receiver = implObject.thisReceiver!! + val instances = irTemporary(irGetField(irGet(receiver), loweredEnum.valuesField)) + enumEntries + .sortedBy { it.name } + .withIndex() + .forEach { + val instance = irCall(arrayGetSymbol).apply { + dispatchReceiver = irGet(instances) + putValueArgument(0, irInt(it.index)) + } + val initializer = it.value.initializerExpression!!.expression + initializer.setDeclarationsParent(constructor) + when { + initializer is IrConstructorCall -> +initInstanceCall(instance, initializer) + + initializer is IrBlock && initializer.origin == ARGUMENTS_REORDERING_FOR_CALL -> { + val statements = initializer.statements + val constructorCall = statements.last() as IrConstructorCall + statements[statements.lastIndex] = initInstanceCall(instance, constructorCall) + +initializer + } + + else -> error("Unexpected initializer: $initializer") + } + } + +irCall(this@EnumClassLowering.context.ir.symbols.freeze, listOf(arrayType)).apply { + extensionReceiver = irGet(receiver) + } + } + (constructor.body as IrBlockBody).statements += valuesInitializer + } + + private fun createSyntheticValuesMethodBody(declaration: IrFunction): IrBody { + val startOffset = irClass.startOffset + val endOffset = irClass.endOffset + val valuesExpression = enumSyntheticFunctionsBuilder.buildValuesExpression(startOffset, endOffset, irClass) + + return IrBlockBodyImpl(startOffset, endOffset).apply { + statements += IrReturnImpl( + startOffset, + endOffset, + context.irBuiltIns.nothingType, + declaration.symbol, + valuesExpression + ) + } + } + + private fun createSyntheticValueOfMethodBody(declaration: IrFunction): IrBody { + val startOffset = irClass.startOffset + val endOffset = irClass.endOffset + val parameter = declaration.valueParameters[0] + val value = IrGetValueImpl(startOffset, endOffset, parameter.type, parameter.symbol) + val valueOfExpression = enumSyntheticFunctionsBuilder.buildValueOfExpression(startOffset, endOffset, irClass, value) + + return IrBlockBodyImpl(startOffset, endOffset).apply { + statements += IrReturnImpl( + startOffset, + endOffset, + context.irBuiltIns.nothingType, + declaration.symbol, + valueOfExpression + ) + } + } + + } +} diff --git a/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/lower/EnumConstructorsLowering.kt b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/lower/EnumConstructorsLowering.kt new file mode 100644 index 00000000000..cf85928b404 --- /dev/null +++ b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/lower/EnumConstructorsLowering.kt @@ -0,0 +1,407 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +package org.jetbrains.kotlin.backend.konan.lower + +import org.jetbrains.kotlin.backend.common.ClassLoweringPass +import org.jetbrains.kotlin.backend.common.ir.copyTo +import org.jetbrains.kotlin.backend.common.runOnFilePostfix +import org.jetbrains.kotlin.backend.konan.Context +import org.jetbrains.kotlin.backend.konan.DECLARATION_ORIGIN_ENUM +import org.jetbrains.kotlin.descriptors.ClassKind +import org.jetbrains.kotlin.descriptors.DescriptorVisibilities +import org.jetbrains.kotlin.ir.IrStatement +import org.jetbrains.kotlin.ir.declarations.* +import org.jetbrains.kotlin.ir.declarations.impl.IrConstructorImpl +import org.jetbrains.kotlin.ir.declarations.impl.IrValueParameterImpl +import org.jetbrains.kotlin.ir.descriptors.WrappedClassConstructorDescriptor +import org.jetbrains.kotlin.ir.descriptors.WrappedValueParameterDescriptor +import org.jetbrains.kotlin.ir.expressions.* +import org.jetbrains.kotlin.ir.expressions.impl.* +import org.jetbrains.kotlin.ir.symbols.IrConstructorSymbol +import org.jetbrains.kotlin.ir.symbols.impl.IrConstructorSymbolImpl +import org.jetbrains.kotlin.ir.symbols.impl.IrValueParameterSymbolImpl +import org.jetbrains.kotlin.ir.types.IrType +import org.jetbrains.kotlin.ir.util.* +import org.jetbrains.kotlin.ir.visitors.IrElementTransformerVoid +import org.jetbrains.kotlin.ir.visitors.transformChildrenVoid +import org.jetbrains.kotlin.name.Name + +internal class EnumConstructorsLowering(val context: Context) : ClassLoweringPass { + + fun run(irFile: IrFile) { + runOnFilePostfix(irFile) + } + + override fun lower(irClass: IrClass) { + if (irClass.kind != ClassKind.ENUM_CLASS) return + EnumClassTransformer(irClass).run() + } + + private interface EnumConstructorCallTransformer { + fun transform(enumConstructorCall: IrEnumConstructorCall): IrExpression + fun transform(delegatingConstructorCall: IrDelegatingConstructorCall): IrExpression + } + + private inner class EnumClassTransformer(val irClass: IrClass) { + private val loweredEnumConstructors = mutableMapOf() + private val loweredEnumConstructorParameters = mutableMapOf() + + fun run() { + insertInstanceInitializerCall() + lowerEnumConstructors(irClass) + lowerEnumEntriesClasses() + lowerEnumClassBody() + } + + private fun insertInstanceInitializerCall() { + irClass.transformChildrenVoid(object: IrElementTransformerVoid() { + override fun visitClass(declaration: IrClass): IrStatement { + // Skip nested + return declaration + } + + override fun visitConstructor(declaration: IrConstructor): IrStatement { + declaration.transformChildrenVoid(this) + + val blockBody = declaration.body as? IrBlockBody + ?: throw AssertionError("Unexpected constructor body: ${declaration.body}") + if (blockBody.statements.all { it !is IrInstanceInitializerCall }) { + blockBody.statements.transformFlat { + if (it is IrEnumConstructorCall) + listOf(it, IrInstanceInitializerCallImpl(declaration.startOffset, declaration.startOffset, + irClass.symbol, context.irBuiltIns.unitType)) + else null + } + } + return declaration + } + }) + } + + private fun lowerEnumEntriesClasses() { + for (enumEntry in irClass.declarations.filterIsInstance()) + enumEntry.correspondingClass?.let { lowerEnumConstructors(it) } + } + + private fun lowerEnumConstructors(irClass: IrClass) { + irClass.declarations.forEachIndexed { index, declaration -> + if (declaration is IrConstructor) + irClass.declarations[index] = transformEnumConstructor(declaration) + } + } + + private fun transformEnumConstructor(enumConstructor: IrConstructor): IrConstructor { + val loweredEnumConstructor = lowerEnumConstructor(enumConstructor) + + for (parameter in enumConstructor.valueParameters) { + val defaultValue = parameter.defaultValue ?: continue + defaultValue.transformChildrenVoid(ParameterMapper(enumConstructor, loweredEnumConstructor, true)) + loweredEnumConstructor.valueParameters[parameter.loweredIndex].defaultValue = defaultValue + defaultValue.setDeclarationsParent(loweredEnumConstructor) + } + + return loweredEnumConstructor + } + + private fun lowerEnumConstructor(constructor: IrConstructor): IrConstructor { + val startOffset = constructor.startOffset + val endOffset = constructor.endOffset + val loweredConstructor = WrappedClassConstructorDescriptor().let { + IrConstructorImpl( + startOffset, endOffset, + constructor.origin, + IrConstructorSymbolImpl(it), + constructor.name, + DescriptorVisibilities.PROTECTED, + constructor.returnType, + isInline = false, + isExternal = false, + isPrimary = constructor.isPrimary, + isExpect = false + ).apply { + it.bind(this) + parent = constructor.parent + val body = constructor.body!! + this.body = body // Will be transformed later. + body.setDeclarationsParent(this) + } + } + + fun createSynthesizedValueParameter(index: Int, name: String, type: IrType): IrValueParameter = + WrappedValueParameterDescriptor().let { + IrValueParameterImpl( + startOffset, endOffset, + DECLARATION_ORIGIN_ENUM, + IrValueParameterSymbolImpl(it), + Name.identifier(name), + index, + type, + varargElementType = null, + isCrossinline = false, + isNoinline = false + ).apply { + it.bind(this) + parent = loweredConstructor + } + } + + loweredConstructor.valueParameters += createSynthesizedValueParameter(0, "name", context.irBuiltIns.stringType) + loweredConstructor.valueParameters += createSynthesizedValueParameter(1, "ordinal", context.irBuiltIns.intType) + loweredConstructor.valueParameters += constructor.valueParameters.map { + it.copyTo(loweredConstructor, index = it.loweredIndex).apply { + loweredEnumConstructorParameters[it] = this + } + } + + loweredEnumConstructors[constructor] = loweredConstructor + + return loweredConstructor + } + + private fun lowerEnumClassBody() { + val transformer = EnumClassBodyTransformer() + irClass.transformChildrenVoid(transformer) + irClass.declarations.filterIsInstance().forEach { + it.correspondingClass?.transformChildrenVoid(transformer) + } + } + + private inner class InEnumClassConstructor(val enumClassConstructor: IrConstructor) : + EnumConstructorCallTransformer { + override fun transform(enumConstructorCall: IrEnumConstructorCall): IrExpression { + val startOffset = enumConstructorCall.startOffset + val endOffset = enumConstructorCall.endOffset + val origin = enumConstructorCall.origin + + val result = IrDelegatingConstructorCallImpl.fromSymbolDescriptor( + startOffset, endOffset, + context.irBuiltIns.unitType, + enumConstructorCall.symbol, + enumConstructorCall.symbol.owner.typeParameters.size, + enumConstructorCall.symbol.owner.valueParameters.size) + + assert(result.symbol.owner.valueParameters.size == 2) { + "Enum(String, Int) constructor call expected:\n${result.dump()}" + } + + val nameParameter = enumClassConstructor.valueParameters.getOrElse(0) { + throw AssertionError("No 'name' parameter in enum constructor: $enumClassConstructor") + } + + val ordinalParameter = enumClassConstructor.valueParameters.getOrElse(1) { + throw AssertionError("No 'ordinal' parameter in enum constructor: $enumClassConstructor") + } + + result.putValueArgument(0, + IrGetValueImpl(startOffset, endOffset, nameParameter.type, nameParameter.symbol, origin) + ) + result.putValueArgument(1, + IrGetValueImpl(startOffset, endOffset, ordinalParameter.type, ordinalParameter.symbol, origin) + ) + return result + } + + override fun transform(delegatingConstructorCall: IrDelegatingConstructorCall): IrExpression { + val startOffset = delegatingConstructorCall.startOffset + val endOffset = delegatingConstructorCall.endOffset + + val delegatingConstructor = delegatingConstructorCall.symbol.owner + val loweredDelegatingConstructor = loweredEnumConstructors.getOrElse(delegatingConstructor) { + throw AssertionError("Constructor called in enum entry initializer should've been lowered: $delegatingConstructor") + } + + val result = IrDelegatingConstructorCallImpl.fromSymbolDescriptor( + startOffset, endOffset, + context.irBuiltIns.unitType, + loweredDelegatingConstructor.symbol, + loweredDelegatingConstructor.symbol.owner.typeParameters.size, + loweredDelegatingConstructor.symbol.owner.valueParameters.size) + + val firstParameter = enumClassConstructor.valueParameters[0] + result.putValueArgument(0, + IrGetValueImpl(startOffset, endOffset, firstParameter.type, firstParameter.symbol)) + val secondParameter = enumClassConstructor.valueParameters[1] + result.putValueArgument(1, + IrGetValueImpl(startOffset, endOffset, secondParameter.type, secondParameter.symbol)) + + delegatingConstructor.valueParameters.forEach { + result.putValueArgument(it.loweredIndex, delegatingConstructorCall.getValueArgument(it.index)) + } + + return result + } + } + + private abstract inner class InEnumEntry(private val enumEntry: IrEnumEntry) : EnumConstructorCallTransformer { + + override fun transform(enumConstructorCall: IrEnumConstructorCall): IrExpression { + val name = enumEntry.name.asString() + val ordinal = context.specialDeclarationsFactory.getEnumEntryOrdinal(enumEntry) + + val startOffset = enumConstructorCall.startOffset + val endOffset = enumConstructorCall.endOffset + + val enumConstructor = enumConstructorCall.symbol.owner + val loweredConstructor = loweredEnumConstructors.getOrElse(enumConstructor) { + throw AssertionError("Constructor called in enum entry initializer should've been lowered: $enumConstructor") + } + + val result = createConstructorCall(startOffset, endOffset, loweredConstructor.symbol) + + result.putValueArgument(0, + IrConstImpl.string(startOffset, endOffset, context.irBuiltIns.stringType, name)) + result.putValueArgument(1, + IrConstImpl.int(startOffset, endOffset, context.irBuiltIns.intType, ordinal)) + + enumConstructor.valueParameters.forEach { + result.putValueArgument(it.loweredIndex, enumConstructorCall.getValueArgument(it.index)) + } + + return result + } + + override fun transform(delegatingConstructorCall: IrDelegatingConstructorCall): IrExpression { + throw AssertionError("Unexpected delegating constructor call within enum entry: $enumEntry") + } + + abstract fun createConstructorCall(startOffset: Int, endOffset: Int, loweredConstructor: IrConstructorSymbol): IrMemberAccessExpression<*> + } + + private inner class InEnumEntryClassConstructor(enumEntry: IrEnumEntry) : InEnumEntry(enumEntry) { + override fun createConstructorCall(startOffset: Int, endOffset: Int, loweredConstructor: IrConstructorSymbol) = + IrDelegatingConstructorCallImpl(startOffset, endOffset, context.irBuiltIns.unitType, loweredConstructor, + loweredConstructor.owner.typeParameters.size, loweredConstructor.owner.valueParameters.size) + } + + private inner class InEnumEntryInitializer(enumEntry: IrEnumEntry) : InEnumEntry(enumEntry) { + override fun createConstructorCall(startOffset: Int, endOffset: Int, loweredConstructor: IrConstructorSymbol) = + IrConstructorCallImpl.fromSymbolOwner(startOffset, endOffset, loweredConstructor.owner.returnType, loweredConstructor) + } + + private inner class EnumClassBodyTransformer : IrElementTransformerVoid() { + private var enumConstructorCallTransformer: EnumConstructorCallTransformer? = null + + override fun visitClass(declaration: IrClass): IrStatement { + if (declaration.kind == ClassKind.ENUM_CLASS) + return declaration + return super.visitClass(declaration) + } + + override fun visitEnumEntry(declaration: IrEnumEntry): IrStatement { + assert(enumConstructorCallTransformer == null) { "Nested enum entry initialization:\n${declaration.dump()}" } + + enumConstructorCallTransformer = InEnumEntryInitializer(declaration) + + declaration.initializerExpression = declaration.initializerExpression?.transform(this, data = null) + + enumConstructorCallTransformer = null + + return declaration + } + + override fun visitConstructor(declaration: IrConstructor): IrStatement { + val containingClass = declaration.parentAsClass + + // TODO local (non-enum) class in enum class constructor? + val previous = enumConstructorCallTransformer + + if (containingClass.kind == ClassKind.ENUM_ENTRY) { + assert(enumConstructorCallTransformer == null) { "Nested enum entry initialization:\n${declaration.dump()}" } + val entry = irClass.declarations.filterIsInstance().single { it.correspondingClass == containingClass } + enumConstructorCallTransformer = InEnumEntryClassConstructor(entry) + } else if (containingClass.kind == ClassKind.ENUM_CLASS) { + assert(enumConstructorCallTransformer == null) { "Nested enum entry initialization:\n${declaration.dump()}" } + enumConstructorCallTransformer = InEnumClassConstructor(declaration) + } + + val result = super.visitConstructor(declaration) + + enumConstructorCallTransformer = previous + + return result + } + + override fun visitEnumConstructorCall(expression: IrEnumConstructorCall): IrExpression { + expression.transformChildrenVoid(this) + + val callTransformer = enumConstructorCallTransformer ?: + throw AssertionError("Enum constructor call outside of enum entry initialization or enum class constructor:\n" + irClass.dump()) + + + return callTransformer.transform(expression) + } + + override fun visitDelegatingConstructorCall(expression: IrDelegatingConstructorCall): IrExpression { + expression.transformChildrenVoid(this) + + if (expression.symbol.owner.parentAsClass.kind == ClassKind.ENUM_CLASS) { + val callTransformer = enumConstructorCallTransformer ?: + throw AssertionError("Enum constructor call outside of enum entry initialization or enum class constructor:\n" + irClass.dump()) + + return callTransformer.transform(expression) + } + return expression + } + + override fun visitGetValue(expression: IrGetValue): IrExpression { + val parameter = expression.symbol.owner + val loweredParameter = loweredEnumConstructorParameters[parameter] + return if (loweredParameter == null) { + expression + } else { + IrGetValueImpl(expression.startOffset, expression.endOffset, loweredParameter.type, + loweredParameter.symbol, expression.origin) + } + } + + override fun visitSetValue(expression: IrSetValue): IrExpression { + expression.transformChildrenVoid() + return loweredEnumConstructorParameters[expression.symbol.owner]?.let { + IrSetValueImpl(expression.startOffset, expression.endOffset, it.type, + it.symbol, expression.value, expression.origin) + } ?: expression + } + } + } +} + +private val IrValueParameter.loweredIndex: Int get() = index + 2 + +private class ParameterMapper(superConstructor: IrConstructor, + val constructor: IrConstructor, + val useLoweredIndex: Boolean) : IrElementTransformerVoid() { + private val valueParameters = superConstructor.valueParameters.toSet() + + override fun visitGetValue(expression: IrGetValue): IrExpression { + + val superParameter = expression.symbol.owner as? IrValueParameter ?: return expression + if (valueParameters.contains(superParameter)) { + val index = if (useLoweredIndex) superParameter.loweredIndex else superParameter.index + val parameter = constructor.valueParameters[index] + return IrGetValueImpl( + expression.startOffset, expression.endOffset, + parameter.type, + parameter.symbol) + } + return expression + } + + override fun visitSetValue(expression: IrSetValue): IrExpression { + expression.transformChildrenVoid() + val superParameter = expression.symbol.owner as? IrValueParameter ?: return expression + if (valueParameters.contains(superParameter)) { + val index = if (useLoweredIndex) superParameter.loweredIndex else superParameter.index + val parameter = constructor.valueParameters[index] + return IrSetValueImpl( + expression.startOffset, expression.endOffset, + parameter.type, + parameter.symbol, + expression.value, + expression.origin) + } + return expression + } +} diff --git a/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/lower/ExpectDeclarationsRemoving.kt b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/lower/ExpectDeclarationsRemoving.kt new file mode 100644 index 00000000000..bb29eaa07d4 --- /dev/null +++ b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/lower/ExpectDeclarationsRemoving.kt @@ -0,0 +1,210 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +package org.jetbrains.kotlin.backend.konan.lower + +import org.jetbrains.kotlin.backend.common.FileLoweringPass +import org.jetbrains.kotlin.backend.konan.Context +import org.jetbrains.kotlin.backend.konan.descriptors.isExpectMember +import org.jetbrains.kotlin.backend.konan.descriptors.propertyIfAccessor +import org.jetbrains.kotlin.backend.konan.ir.ModuleIndex +import org.jetbrains.kotlin.descriptors.MemberDescriptor +import org.jetbrains.kotlin.ir.IrElement +import org.jetbrains.kotlin.ir.declarations.* +import org.jetbrains.kotlin.ir.expressions.IrExpression +import org.jetbrains.kotlin.ir.expressions.impl.IrExpressionBodyImpl +import org.jetbrains.kotlin.ir.symbols.* +import org.jetbrains.kotlin.ir.util.DeepCopyIrTreeWithSymbols +import org.jetbrains.kotlin.ir.util.DeepCopySymbolRemapper +import org.jetbrains.kotlin.ir.util.DeepCopyTypeRemapper +import org.jetbrains.kotlin.ir.util.patchDeclarationParents +import org.jetbrains.kotlin.ir.visitors.IrElementVisitorVoid +import org.jetbrains.kotlin.ir.visitors.acceptChildrenVoid +import org.jetbrains.kotlin.ir.visitors.acceptVoid +import org.jetbrains.kotlin.resolve.checkers.ExpectedActualDeclarationChecker +import org.jetbrains.kotlin.resolve.descriptorUtil.module +import org.jetbrains.kotlin.resolve.multiplatform.ExpectedActualResolver + +/** + * This pass removes all declarations with `isExpect == true`. + * Note: org.jetbrains.kotlin.backend.common.lower.ExpectDeclarationsRemoving is copy of this lower. + */ +internal class ExpectDeclarationsRemoving(val context: Context) : FileLoweringPass { + override fun lower(irFile: IrFile) { + // All declarations with `isExpect == true` are nested into a top-level declaration with `isExpect == true`. + irFile.declarations.removeAll { it.descriptor.isExpectMember } + } +} + +internal class ExpectToActualDefaultValueCopier(private val irModule: IrModuleFragment) { + + // Note: local declarations aren't required here; TODO: use more lightweight index. + private val moduleIndex = ModuleIndex(irModule) + + fun process() { + irModule.files.forEach { this.process(it) } + } + + private fun process(irFile: IrFile) { + // All declarations with `isExpect == true` are nested into a top-level declaration with `isExpect == true`. + irFile.declarations.forEach { + if (it.descriptor.isExpectMember) { + copyDefaultArgumentsFromExpectToActual(it) + } + } + } + + private fun copyDefaultArgumentsFromExpectToActual(declaration: IrDeclaration) { + declaration.acceptVoid(object : IrElementVisitorVoid { + override fun visitElement(element: IrElement) { + element.acceptChildrenVoid(this) + } + + override fun visitValueParameter(declaration: IrValueParameter) { + super.visitValueParameter(declaration) + + val defaultValue = declaration.defaultValue ?: return + val function = declaration.parent as IrFunction + + val index = declaration.index + assert(function.valueParameters[index] == declaration) + + if (function is IrConstructor && + ExpectedActualDeclarationChecker.isOptionalAnnotationClass( + function.descriptor.constructedClass + ) + ) { + return + } + + val actualForExpected = function.findActualForExpected() + actualForExpected.valueParameters[index].defaultValue = + IrExpressionBodyImpl( + defaultValue.startOffset, defaultValue.endOffset, + defaultValue.expression.remapExpectValueSymbols().patchDeclarationParents(actualForExpected) + ) + } + }) + } + + private inline fun T.findActualForExpected(): T = + moduleIndex.functions[descriptor.findActualForExpect()] as T + + private fun IrClass.findActualForExpected(): IrClass = + moduleIndex.classes[descriptor.findActualForExpect()]!! + + private inline fun T.findActualForExpect() = with(ExpectedActualResolver) { + val descriptor = this@findActualForExpect + + if (!descriptor.isExpect) error(this) + + findCompatibleActualForExpected(descriptor.module).singleOrNull() ?: error(descriptor) + } as T + + private fun IrExpression.remapExpectValueSymbols(): IrExpression { + class SymbolRemapper : DeepCopySymbolRemapper() { + override fun getReferencedClass(symbol: IrClassSymbol) = + if (symbol.descriptor.isExpect) + symbol.owner.findActualForExpected().symbol + else super.getReferencedClass(symbol) + + override fun getReferencedClassOrNull(symbol: IrClassSymbol?) = + symbol?.let { getReferencedClass(it) } + + override fun getReferencedClassifier(symbol: IrClassifierSymbol): IrClassifierSymbol = when (symbol) { + is IrClassSymbol -> getReferencedClass(symbol) + is IrTypeParameterSymbol -> remapExpectTypeParameter(symbol).symbol + else -> error("Unexpected symbol $symbol ${symbol.descriptor}") + } + + override fun getReferencedConstructor(symbol: IrConstructorSymbol) = + if (symbol.descriptor.isExpect) + symbol.owner.findActualForExpected().symbol + else super.getReferencedConstructor(symbol) + + override fun getReferencedFunction(symbol: IrFunctionSymbol): IrFunctionSymbol = when (symbol) { + is IrSimpleFunctionSymbol -> getReferencedSimpleFunction(symbol) + is IrConstructorSymbol -> getReferencedConstructor(symbol) + else -> error("Unexpected symbol $symbol ${symbol.descriptor}") + } + + override fun getReferencedSimpleFunction(symbol: IrSimpleFunctionSymbol) = when { + symbol.descriptor.isExpect -> symbol.owner.findActualForExpected().symbol + + symbol.descriptor.propertyIfAccessor.isExpect -> { + val property = symbol.owner.correspondingPropertySymbol!!.owner + val actualPropertyDescriptor = property.descriptor.findActualForExpect() + val accessorDescriptor = when (symbol.owner) { + property.getter -> actualPropertyDescriptor.getter!! + property.setter -> actualPropertyDescriptor.setter!! + else -> error("Unexpected accessor of $symbol ${symbol.descriptor}") + } + moduleIndex.functions[accessorDescriptor]!!.symbol as IrSimpleFunctionSymbol + } + + else -> super.getReferencedSimpleFunction(symbol) + } + + override fun getReferencedValue(symbol: IrValueSymbol) = + remapExpectValue(symbol)?.symbol ?: super.getReferencedValue(symbol) + } + + val symbolRemapper = SymbolRemapper() + acceptVoid(symbolRemapper) + return transform(DeepCopyIrTreeWithSymbols(symbolRemapper, DeepCopyTypeRemapper(symbolRemapper)), data = null) + } + + private fun remapExpectTypeParameter(symbol: IrTypeParameterSymbol): IrTypeParameter { + val parameter = symbol.owner + val parent = parameter.parent + + return when (parent) { + is IrClass -> + if (!parent.descriptor.isExpect) + parameter + else parent.findActualForExpected().typeParameters[parameter.index] + + is IrFunction -> + if (!parent.descriptor.isExpect) + parameter + else parent.findActualForExpected().typeParameters[parameter.index] + + else -> error(parent) + } + } + + private fun remapExpectValue(symbol: IrValueSymbol): IrValueParameter? { + if (symbol !is IrValueParameterSymbol) { + return null + } + + val parameter = symbol.owner + val parent = parameter.parent + + return when (parent) { + is IrClass -> + if (!parent.descriptor.isExpect) + null + else { + assert(parameter == parent.thisReceiver) + parent.findActualForExpected().thisReceiver!! + } + + is IrFunction -> + if (!parent.descriptor.isExpect) + null + else when (parameter) { + parent.dispatchReceiverParameter -> parent.findActualForExpected().dispatchReceiverParameter!! + parent.extensionReceiverParameter -> parent.findActualForExpected().extensionReceiverParameter!! + else -> { + assert(parent.valueParameters[parameter.index] == parameter) + parent.findActualForExpected().valueParameters[parameter.index] + } + } + + else -> error(parent) + } + } +} diff --git a/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/lower/FinallyBlocksLowering.kt b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/lower/FinallyBlocksLowering.kt new file mode 100644 index 00000000000..3672d2e5b99 --- /dev/null +++ b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/lower/FinallyBlocksLowering.kt @@ -0,0 +1,324 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +package org.jetbrains.kotlin.backend.konan.lower + +import org.jetbrains.kotlin.backend.common.lower.* +import org.jetbrains.kotlin.backend.common.* +import org.jetbrains.kotlin.backend.konan.Context +import org.jetbrains.kotlin.descriptors.Modality +import org.jetbrains.kotlin.descriptors.SimpleFunctionDescriptor +import org.jetbrains.kotlin.descriptors.DescriptorVisibilities +import org.jetbrains.kotlin.ir.IrElement +import org.jetbrains.kotlin.ir.IrStatement +import org.jetbrains.kotlin.ir.builders.* +import org.jetbrains.kotlin.ir.declarations.impl.IrVariableImpl +import org.jetbrains.kotlin.ir.expressions.* +import org.jetbrains.kotlin.ir.expressions.impl.* +import org.jetbrains.kotlin.ir.symbols.IrReturnTargetSymbol +import org.jetbrains.kotlin.ir.symbols.IrReturnableBlockSymbol +import org.jetbrains.kotlin.ir.symbols.impl.IrReturnableBlockSymbolImpl +import org.jetbrains.kotlin.ir.types.IrType +import org.jetbrains.kotlin.ir.builders.irGet +import org.jetbrains.kotlin.ir.declarations.* +import org.jetbrains.kotlin.ir.declarations.impl.IrFunctionImpl +import org.jetbrains.kotlin.ir.descriptors.WrappedSimpleFunctionDescriptor +import org.jetbrains.kotlin.ir.descriptors.WrappedVariableDescriptor +import org.jetbrains.kotlin.ir.symbols.impl.IrSimpleFunctionSymbolImpl +import org.jetbrains.kotlin.ir.symbols.impl.IrVariableSymbolImpl +import org.jetbrains.kotlin.ir.types.IrSimpleType +import org.jetbrains.kotlin.ir.util.SYNTHETIC_OFFSET +import org.jetbrains.kotlin.ir.util.defaultType +import org.jetbrains.kotlin.ir.util.setDeclarationsParent +import org.jetbrains.kotlin.ir.visitors.transformChildrenVoid +import org.jetbrains.kotlin.name.Name + +internal class FinallyBlocksLowering(val context: Context): FileLoweringPass, IrElementTransformerVoidWithContext() { + private val symbols = context.ir.symbols + + private interface HighLevelJump { + fun toIr(context: Context, startOffset: Int, endOffset: Int, value: IrExpression): IrExpression + } + + private data class Return(val target: IrReturnTargetSymbol): HighLevelJump { + override fun toIr(context: Context, startOffset: Int, endOffset: Int, value: IrExpression) + = IrReturnImpl(startOffset, endOffset, context.irBuiltIns.nothingType, target, value) + } + + private data class Break(val loop: IrLoop): HighLevelJump { + override fun toIr(context: Context, startOffset: Int, endOffset: Int, value: IrExpression) + = IrBlockImpl(startOffset, endOffset, context.irBuiltIns.nothingType, null, + statements = listOf( + value, + IrBreakImpl(startOffset, endOffset, context.irBuiltIns.nothingType, loop) + )) + } + + private data class Continue(val loop: IrLoop): HighLevelJump { + override fun toIr(context: Context, startOffset: Int, endOffset: Int, value: IrExpression) + = IrBlockImpl(startOffset, endOffset, context.irBuiltIns.nothingType, null, + statements = listOf( + value, + IrContinueImpl(startOffset, endOffset, context.irBuiltIns.nothingType, loop) + )) + } + + private abstract class Scope + + private class ReturnableScope(val symbol: IrReturnTargetSymbol): Scope() + + private class LoopScope(val loop: IrLoop): Scope() + + private class TryScope(var expression: IrExpression, + val finallyExpression: IrExpression, + val irBuilder: IrBuilderWithScope): Scope() { + val jumps = mutableMapOf() + } + + private val scopeStack = mutableListOf() + + private inline fun using(scope: S, block: (S) -> R): R { + scopeStack.push(scope) + try { + return block(scope) + } finally { + scopeStack.pop() + } + } + + override fun lower(irFile: IrFile) { + irFile.transformChildrenVoid(this) + } + + override fun visitFunctionNew(declaration: IrFunction): IrStatement { + using(ReturnableScope(declaration.symbol)) { + return super.visitFunctionNew(declaration) + } + } + + override fun visitContainerExpression(expression: IrContainerExpression): IrExpression { + if (expression !is IrReturnableBlock) + return super.visitContainerExpression(expression) + + using(ReturnableScope(expression.symbol)) { + return super.visitContainerExpression(expression) + } + } + + override fun visitLoop(loop: IrLoop): IrExpression { + using(LoopScope(loop)) { + return super.visitLoop(loop) + } + } + + override fun visitBreak(jump: IrBreak): IrExpression { + val startOffset = jump.startOffset + val endOffset = jump.endOffset + val irBuilder = context.createIrBuilder(currentScope!!.scope.scopeOwnerSymbol, startOffset, endOffset) + return performHighLevelJump( + targetScopePredicate = { it is LoopScope && it.loop == jump.loop }, + jump = Break(jump.loop), + startOffset = startOffset, + endOffset = endOffset, + value = irBuilder.irGetObject(context.ir.symbols.unit) + ) ?: jump + } + + override fun visitContinue(jump: IrContinue): IrExpression { + val startOffset = jump.startOffset + val endOffset = jump.endOffset + val irBuilder = context.createIrBuilder(currentScope!!.scope.scopeOwnerSymbol, startOffset, endOffset) + return performHighLevelJump( + targetScopePredicate = { it is LoopScope && it.loop == jump.loop }, + jump = Continue(jump.loop), + startOffset = startOffset, + endOffset = endOffset, + value = irBuilder.irGetObject(context.ir.symbols.unit) + ) ?: jump + } + + override fun visitReturn(expression: IrReturn): IrExpression { + expression.transformChildrenVoid(this) + + return performHighLevelJump( + targetScopePredicate = { it is ReturnableScope && it.symbol == expression.returnTargetSymbol }, + jump = Return(expression.returnTargetSymbol), + startOffset = expression.startOffset, + endOffset = expression.endOffset, + value = expression.value + ) ?: expression + } + + private fun performHighLevelJump(targetScopePredicate: (Scope) -> Boolean, + jump: HighLevelJump, + startOffset: Int, + endOffset: Int, + value: IrExpression): IrExpression? { + val tryScopes = scopeStack.reversed() + .takeWhile { !targetScopePredicate(it) } + .filterIsInstance() + .toList() + if (tryScopes.isEmpty()) + return null + return performHighLevelJump(tryScopes, 0, jump, startOffset, endOffset, value) + } + + private val IrReturnTarget.returnType: IrType + get() = when (this) { + is IrConstructor -> context.irBuiltIns.unitType + is IrFunction -> returnType + is IrReturnableBlock -> type + else -> error("Unknown ReturnTarget: $this") + } + + private fun createSyntheticFunctionDescriptor(name: String): SimpleFunctionDescriptor { + val descriptor = WrappedSimpleFunctionDescriptor() + descriptor.bind(IrFunctionImpl( + SYNTHETIC_OFFSET, SYNTHETIC_OFFSET, + IrDeclarationOrigin.DEFINED, + IrSimpleFunctionSymbolImpl(descriptor), + Name.identifier(name), + DescriptorVisibilities.PUBLIC, + Modality.FINAL, + context.irBuiltIns.unitType, + false, + false, + false, + false, + false, + false, + false) + ) + return descriptor + } + + private fun performHighLevelJump(tryScopes: List, + index: Int, + jump: HighLevelJump, + startOffset: Int, + endOffset: Int, + value: IrExpression): IrExpression { + if (index == tryScopes.size) + return jump.toIr(context, startOffset, endOffset, value) + + val currentTryScope = tryScopes[index] + currentTryScope.jumps.getOrPut(jump) { + val type = (jump as? Return)?.target?.owner?.returnType ?: value.type + val symbol = IrReturnableBlockSymbolImpl(createSyntheticFunctionDescriptor("\$Finally$index")) + with(currentTryScope) { + irBuilder.run { + val inlinedFinally = irInlineFinally(symbol, type, expression, finallyExpression) + expression = performHighLevelJump( + tryScopes = tryScopes, + index = index + 1, + jump = jump, + startOffset = startOffset, + endOffset = endOffset, + value = inlinedFinally) + } + } + symbol + }.let { + return IrReturnImpl( + startOffset = startOffset, + endOffset = endOffset, + type = context.irBuiltIns.nothingType, + returnTargetSymbol = it, + value = value) + } + } + + override fun visitTry(aTry: IrTry): IrExpression { + val finallyExpression = aTry.finallyExpression + ?: return super.visitTry(aTry) + + val startOffset = aTry.startOffset + val endOffset = aTry.endOffset + val irBuilder = context.createIrBuilder(currentScope!!.scope.scopeOwnerSymbol, startOffset, endOffset) + val transformer = this + irBuilder.run { + val transformedTry = IrTryImpl( + startOffset = startOffset, + endOffset = endOffset, + type = context.irBuiltIns.nothingType + ) + val transformedFinallyExpression = finallyExpression.transform(transformer, null) + val catchParameter = WrappedVariableDescriptor().let { + IrVariableImpl( + startOffset, endOffset, + IrDeclarationOrigin.CATCH_PARAMETER, + IrVariableSymbolImpl(it), + Name.identifier("t"), + symbols.throwable.owner.defaultType, + isVar = false, + isConst = false, + isLateinit = false + ).apply { + it.bind(this) + parent = this@run.parent + } + } + + val syntheticTry = IrTryImpl( + startOffset = startOffset, + endOffset = endOffset, + type = context.irBuiltIns.nothingType, + tryResult = transformedTry, + catches = listOf( + irCatch(catchParameter, irBlock { + +copy(finallyExpression) + +irThrow(irGet(catchParameter)) + }) + ), + finallyExpression = null + ) + using(TryScope(syntheticTry, transformedFinallyExpression, this)) { + val fallThroughType = aTry.type + val fallThroughSymbol = IrReturnableBlockSymbolImpl(createSyntheticFunctionDescriptor("\$Fallthrough")) + val transformedResult = aTry.tryResult.transform(transformer, null) + transformedTry.tryResult = irReturn(fallThroughSymbol, transformedResult) + for (aCatch in aTry.catches) { + val transformedCatch = aCatch.transform(transformer, null) + transformedCatch.result = irReturn(fallThroughSymbol, transformedCatch.result) + transformedTry.catches.add(transformedCatch) + } + return irInlineFinally(fallThroughSymbol, fallThroughType, it.expression, it.finallyExpression) + } + } + } + + private fun IrBuilderWithScope.irInlineFinally(symbol: IrReturnableBlockSymbol, type: IrType, + value: IrExpression, + finallyExpression: IrExpression): IrExpression { + val returnTypeClassifier = (type as? IrSimpleType)?.classifier + return when (returnTypeClassifier) { + symbols.unit, symbols.nothing -> irBlock(value, null, type) { + +irReturnableBlock(finallyExpression.startOffset, finallyExpression.endOffset, symbol, type) { + +value + } + +copy(finallyExpression) + } + else -> irBlock(value, null, type) { + val tmp = irTemporary(irReturnableBlock(finallyExpression.startOffset, finallyExpression.endOffset, symbol, type) { + +irReturn(symbol, value) + }) + +copy(finallyExpression) + +irGet(tmp) + } + } + } + + private inline fun IrBuilderWithScope.copy(element: T) = + element.deepCopyWithVariables().setDeclarationsParent(parent) + + fun IrBuilderWithScope.irReturn(target: IrReturnTargetSymbol, value: IrExpression) = + IrReturnImpl(startOffset, endOffset, context.irBuiltIns.nothingType, target, value) + + private inline fun IrBuilderWithScope.irReturnableBlock(startOffset: Int, endOffset: Int, symbol: IrReturnableBlockSymbol, + type: IrType, body: IrBlockBuilder.() -> Unit) = + IrReturnableBlockImpl(startOffset, endOffset, type, symbol, null, + IrBlockBuilder(context, scope, startOffset, endOffset, null, type) + .block(body).statements) +} diff --git a/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/lower/FunctionReferenceLowering.kt b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/lower/FunctionReferenceLowering.kt new file mode 100644 index 00000000000..51ec2a03f98 --- /dev/null +++ b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/lower/FunctionReferenceLowering.kt @@ -0,0 +1,491 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +package org.jetbrains.kotlin.backend.konan.lower + +import org.jetbrains.kotlin.backend.common.FileLoweringPass +import org.jetbrains.kotlin.backend.common.IrElementTransformerVoidWithContext +import org.jetbrains.kotlin.backend.common.ir.* +import org.jetbrains.kotlin.backend.common.lower.createIrBuilder +import org.jetbrains.kotlin.backend.common.pop +import org.jetbrains.kotlin.backend.common.push +import org.jetbrains.kotlin.backend.konan.Context +import org.jetbrains.kotlin.backend.konan.descriptors.synthesizedName +import org.jetbrains.kotlin.backend.konan.llvm.fullName +import org.jetbrains.kotlin.descriptors.ClassKind +import org.jetbrains.kotlin.descriptors.Modality +import org.jetbrains.kotlin.descriptors.ReceiverParameterDescriptor +import org.jetbrains.kotlin.descriptors.DescriptorVisibilities +import org.jetbrains.kotlin.ir.IrElement +import org.jetbrains.kotlin.ir.IrStatement +import org.jetbrains.kotlin.ir.builders.* +import org.jetbrains.kotlin.ir.declarations.* +import org.jetbrains.kotlin.ir.declarations.impl.IrClassImpl +import org.jetbrains.kotlin.ir.declarations.impl.IrConstructorImpl +import org.jetbrains.kotlin.ir.declarations.impl.IrFunctionImpl +import org.jetbrains.kotlin.ir.descriptors.WrappedClassConstructorDescriptor +import org.jetbrains.kotlin.ir.descriptors.WrappedClassDescriptor +import org.jetbrains.kotlin.ir.descriptors.WrappedSimpleFunctionDescriptor +import org.jetbrains.kotlin.ir.expressions.* +import org.jetbrains.kotlin.ir.expressions.impl.IrInstanceInitializerCallImpl +import org.jetbrains.kotlin.ir.symbols.IrClassSymbol +import org.jetbrains.kotlin.ir.symbols.impl.IrClassSymbolImpl +import org.jetbrains.kotlin.ir.symbols.impl.IrConstructorSymbolImpl +import org.jetbrains.kotlin.ir.symbols.impl.IrSimpleFunctionSymbolImpl +import org.jetbrains.kotlin.ir.types.* +import org.jetbrains.kotlin.ir.util.* +import org.jetbrains.kotlin.ir.visitors.transformChildrenVoid +import org.jetbrains.kotlin.name.FqName +import org.jetbrains.kotlin.name.Name + +internal class FunctionReferenceLowering(val context: Context): FileLoweringPass { + + private object DECLARATION_ORIGIN_FUNCTION_REFERENCE_IMPL : IrDeclarationOriginImpl("FUNCTION_REFERENCE_IMPL") + + companion object { + fun isLoweredFunctionReference(declaration: IrDeclaration): Boolean = + declaration.origin == DECLARATION_ORIGIN_FUNCTION_REFERENCE_IMPL + } + + override fun lower(irFile: IrFile) { + var generatedClasses = mutableListOf() + irFile.transform(object: IrElementTransformerVoidWithContext() { + + private val stack = mutableListOf() + + override fun visitElement(element: IrElement): IrElement { + stack.push(element) + val result = super.visitElement(element) + stack.pop() + return result + } + + override fun visitExpression(expression: IrExpression): IrExpression { + stack.push(expression) + val result = super.visitExpression(expression) + stack.pop() + return result + } + + override fun visitDeclaration(declaration: IrDeclarationBase): IrStatement { + lateinit var tempGeneratedClasses: MutableList + if (declaration is IrClass) { + tempGeneratedClasses = generatedClasses + generatedClasses = mutableListOf() + } + stack.push(declaration) + val result = super.visitDeclaration(declaration) + stack.pop() + if (declaration is IrClass) { + declaration.declarations += generatedClasses + generatedClasses = tempGeneratedClasses + } + return result + } + + override fun visitSpreadElement(spread: IrSpreadElement): IrSpreadElement { + stack.push(spread) + val result = super.visitSpreadElement(spread) + stack.pop() + return result + } + + // Handle SAM conversions which wrap a function reference: + // class sam$n(private val receiver: R) : Interface { override fun method(...) = receiver.target(...) } + // + // This avoids materializing an invokable KFunction representing, thus producing one less class. + // This is actually very common, as `Interface { something }` is a local function + a SAM-conversion + // of a reference to it into an implementation. + override fun visitTypeOperator(expression: IrTypeOperatorCall): IrExpression { + if (expression.operator == IrTypeOperator.SAM_CONVERSION) { + val invokable = expression.argument + val reference = if (invokable is IrFunctionReference) { + invokable + } else if (invokable is IrBlock && (invokable.origin.isLambda) + && invokable.statements.last() is IrFunctionReference) { + // By this point the lambda's function has been replaced with empty IrComposite by LocalDeclarationsLowering. + val statements = invokable.statements + require(statements.size == 2) + require((statements[0] as? IrComposite)?.statements?.isEmpty() == true) + statements[1] as IrFunctionReference + } else { + return super.visitTypeOperator(expression) + } + reference.transformChildrenVoid() + return transformFunctionReference(reference, expression.typeOperand) + } + return super.visitTypeOperator(expression) + } + + override fun visitFunctionReference(expression: IrFunctionReference): IrExpression { + expression.transformChildrenVoid(this) + + for (i in stack.size - 1 downTo 0) { + val cur = stack[i] + if (cur is IrBlock) + continue + if (cur !is IrCall) + break + val argument = if (i < stack.size - 1) stack[i + 1] else expression + val parameter = cur.symbol.owner.valueParameters.singleOrNull { + cur.getValueArgument(it.index) == argument + } + if (parameter?.annotations?.findAnnotation(VOLATILE_LAMBDA_FQ_NAME) != null) { + return expression + } + break + } + + if (!expression.type.isFunction() && !expression.type.isKFunction() + && !expression.type.isKSuspendFunction()) { + // Not a subject of this lowering. + return expression + } + + return transformFunctionReference(expression) + } + + fun transformFunctionReference(expression: IrFunctionReference, samSuperType: IrType? = null): IrExpression { + val parent: IrDeclarationContainer = (currentClass?.irElement as? IrClass) ?: irFile + val loweredFunctionReference = FunctionReferenceBuilder(irFile, parent, expression, samSuperType).build() + generatedClasses.add(loweredFunctionReference.functionReferenceClass) + val irBuilder = context.createIrBuilder(currentScope!!.scope.scopeOwnerSymbol, + expression.startOffset, expression.endOffset) + return irBuilder.irCall(loweredFunctionReference.functionReferenceConstructor.symbol).apply { + expression.getArguments().forEachIndexed { index, argument -> + putValueArgument(index, argument.second) + } + } + } + }, data = null) + + irFile.declarations += generatedClasses + } + + private class BuiltFunctionReference(val functionReferenceClass: IrClass, + val functionReferenceConstructor: IrConstructor) + + private val VOLATILE_LAMBDA_FQ_NAME = FqName.fromSegments(listOf("kotlin", "native", "internal", "VolatileLambda")) + + private val symbols = context.ir.symbols + private val irBuiltIns = context.irBuiltIns + + private val getContinuationSymbol = symbols.getContinuation + private val continuationClassSymbol = getContinuationSymbol.owner.returnType.classifierOrFail as IrClassSymbol + + private inner class FunctionReferenceBuilder( + val irFile: IrFile, + val parent: IrDeclarationParent, + val functionReference: IrFunctionReference, + val samSuperType: IrType? + ) { + private val startOffset = functionReference.startOffset + private val endOffset = functionReference.endOffset + private val referencedFunction = functionReference.symbol.owner + private val functionParameters = referencedFunction.explicitParameters + private val boundFunctionParameters = functionReference.getArgumentsWithIr().map { it.first } + private val unboundFunctionParameters = functionParameters - boundFunctionParameters + + private val typeArgumentsMap = referencedFunction.typeParameters.associate { typeParam -> + typeParam.symbol to functionReference.getTypeArgument(typeParam.index)!! + } + + private val isLambda = functionReference.origin.isLambda + private val isKFunction = functionReference.type.isKFunction() + private val isKSuspendFunction = functionReference.type.isKSuspendFunction() + + private val samSuperClass = samSuperType?.let { it.classOrNull ?: error("Expected a class but was: ${it.render()}") } + + private val adapteeCall: IrFunctionAccessExpression? = + // TODO: Copied from JVM. + if (referencedFunction.origin == IrDeclarationOrigin.ADAPTER_FOR_CALLABLE_REFERENCE) { + // The body of a callable reference adapter contains either only a call, or an IMPLICIT_COERCION_TO_UNIT type operator + // applied to a call. That call's target is the original function which we need to get owner/name/signature. + val call = when (val statement = referencedFunction.body!!.statements.single()) { + is IrTypeOperatorCall -> { + assert(statement.operator == IrTypeOperator.IMPLICIT_COERCION_TO_UNIT) { + "Unexpected type operator in ADAPTER_FOR_CALLABLE_REFERENCE: ${referencedFunction.render()}" + } + statement.argument + } + is IrReturn -> statement.value + else -> statement + } + if (call !is IrFunctionAccessExpression) { + throw UnsupportedOperationException("Unknown structure of ADAPTER_FOR_CALLABLE_REFERENCE: ${referencedFunction.render()}") + } + call + } else { + null + } + + private val adaptedReferenceOriginalTarget: IrFunction? = adapteeCall?.symbol?.owner + private val functionReferenceTarget = adaptedReferenceOriginalTarget ?: referencedFunction + + private val functionReferenceClass: IrClass = WrappedClassDescriptor().let { + IrClassImpl( + startOffset,endOffset, + DECLARATION_ORIGIN_FUNCTION_REFERENCE_IMPL, + IrClassSymbolImpl(it), + "${functionReferenceTarget.name}\$FUNCTION_REFERENCE\$${context.functionReferenceCount++}".synthesizedName, + ClassKind.CLASS, + DescriptorVisibilities.PRIVATE, + Modality.FINAL, + isCompanion = false, + isInner = false, + isData = false, + isExternal = false, + isInline = false, + isExpect = false, + isFun = false + ).apply { + it.bind(this) + parent = this@FunctionReferenceBuilder.parent + createParameterDeclarations() + } + } + + private val functionReferenceThis = functionReferenceClass.thisReceiver!! + + private val argumentToPropertiesMap = boundFunctionParameters.associate { + it to createField( + startOffset, endOffset, + DECLARATION_ORIGIN_FUNCTION_REFERENCE_IMPL, + it.type, + it.name, + isMutable = false, + owner = functionReferenceClass + ) + } + + private fun IrClass.getInvokeFunction() = simpleFunctions().single { it.name.asString() == "invoke" } + + private val kFunctionImplSymbol = symbols.kFunctionImpl + private val kFunctionImplConstructorSymbol = kFunctionImplSymbol.constructors.single() + private val kSuspendFunctionImplSymbol = symbols.kSuspendFunctionImpl + private val kSuspendFunctionImplConstructorSymbol = kSuspendFunctionImplSymbol.constructors.single() + + fun build(): BuiltFunctionReference { + val numberOfParameters = unboundFunctionParameters.size + val functionParameterTypes = unboundFunctionParameters.map { it.type } + val superTypes = mutableListOf() + val functionClass: IrClass + val suspendFunctionClass: IrClass? + if (isKSuspendFunction) { + superTypes += kSuspendFunctionImplSymbol.typeWith(referencedFunction.returnType) + functionClass = symbols.functionN(numberOfParameters + 1).owner + val continuationType = continuationClassSymbol.typeWith(referencedFunction.returnType) + superTypes += functionClass.typeWith(functionParameterTypes + continuationType + irBuiltIns.anyNType) + suspendFunctionClass = symbols.kSuspendFunctionN(numberOfParameters).owner + superTypes += suspendFunctionClass.typeWith(functionParameterTypes + referencedFunction.returnType) + } + else { + superTypes += if (isLambda) + irBuiltIns.anyType + else + kFunctionImplSymbol.typeWith(referencedFunction.returnType) + functionClass = (if (isKFunction) symbols.kFunctionN(numberOfParameters) else symbols.functionN(numberOfParameters)).owner + superTypes += functionClass.typeWith(functionParameterTypes + referencedFunction.returnType) + val lastParameterType = unboundFunctionParameters.lastOrNull()?.type + if (lastParameterType?.classifierOrNull != continuationClassSymbol) + suspendFunctionClass = null + else { + lastParameterType as IrSimpleType + // If the last parameter is Continuation<> inherit from SuspendFunction. + suspendFunctionClass = symbols.suspendFunctionN(numberOfParameters - 1).owner + val suspendFunctionClassTypeParameters = functionParameterTypes.dropLast(1) + + (lastParameterType.arguments.single().typeOrNull ?: irBuiltIns.anyNType) + superTypes += suspendFunctionClass.symbol.typeWith(suspendFunctionClassTypeParameters) + } + } + + val constructor = buildConstructor() + val functionInvoke = if (isKSuspendFunction) + null + else + buildInvokeMethod(functionClass.getInvokeFunction()) + val suspendFunctionInvoke = if (suspendFunctionClass == null) + null + else { + buildInvokeMethod(suspendFunctionClass.getInvokeFunction()).also { + if (isKSuspendFunction) + it.overriddenSymbols += functionClass.getInvokeFunction().symbol + } + } + samSuperType?.let { superTypes += it } + val sam = samSuperClass?.functions?.single { it.owner.modality == Modality.ABSTRACT } + if (sam != null) { + if (sam.owner.extensionReceiverParameter != null) + buildInvokeMethod(sam.owner) + else { + // The signatures of SAM and [invoke] coincide - no need to build additional function. + val properInvoke = if (sam.isSuspend) + suspendFunctionInvoke + else + functionInvoke + if (properInvoke != null) + properInvoke.overriddenSymbols += sam + } + } + + functionReferenceClass.superTypes += superTypes + + functionReferenceClass.addFakeOverrides(context.irBuiltIns) + + return BuiltFunctionReference(functionReferenceClass, constructor) + } + + private fun buildConstructor(): IrConstructor = WrappedClassConstructorDescriptor().let { + IrConstructorImpl( + startOffset, endOffset, + DECLARATION_ORIGIN_FUNCTION_REFERENCE_IMPL, + IrConstructorSymbolImpl(it), + Name.special(""), + DescriptorVisibilities.PUBLIC, + functionReferenceClass.defaultType, + isInline = false, + isExternal = false, + isPrimary = true, + isExpect = false + ).apply { + it.bind(this) + parent = functionReferenceClass + functionReferenceClass.declarations += this + + valueParameters += boundFunctionParameters.mapIndexed { index, parameter -> + parameter.copyTo(this, DECLARATION_ORIGIN_FUNCTION_REFERENCE_IMPL, index, + type = parameter.type.substitute(typeArgumentsMap)) + } + + val kTypeGenerator = KTypeGenerator(context, irFile, functionReference) + body = context.createIrBuilder(symbol, startOffset, endOffset).irBlockBody { + val superConstructor = when { + isKSuspendFunction -> kSuspendFunctionImplConstructorSymbol.owner + isLambda -> irBuiltIns.anyClass.owner.constructors.single() + else -> kFunctionImplConstructorSymbol.owner + } + +irDelegatingConstructorCall(superConstructor).apply applyIrDelegationConstructorCall@ { + if (isLambda) return@applyIrDelegationConstructorCall + val name = ((functionReferenceTarget as? IrSimpleFunction)?.attributeOwnerId as? IrSimpleFunction)?.name + ?: functionReferenceTarget.name + val needReceiver = boundFunctionParameters.singleOrNull()?.descriptor is ReceiverParameterDescriptor + val receiver = if (needReceiver) irGet(valueParameters.single()) else irNull() + val arity = unboundFunctionParameters.size + if (functionReferenceTarget.isSuspend) 1 else 0 + putValueArgument(0, irString(name.asString())) + putValueArgument(1, irString(functionReferenceTarget.fullName)) + putValueArgument(2, receiver) + putValueArgument(3, irInt(arity)) + putValueArgument(4, irInt(getFlags())) + putValueArgument(5, with(kTypeGenerator) { irKType(referencedFunction.returnType) }) + } + +IrInstanceInitializerCallImpl(startOffset, endOffset, functionReferenceClass.symbol, irBuiltIns.unitType) + // Save all arguments to fields. + boundFunctionParameters.forEachIndexed { index, parameter -> + +irSetField(irGet(functionReferenceThis), argumentToPropertiesMap[parameter]!!, irGet(valueParameters[index])) + } + } + } + } + + private fun getFlags() = + (if (referencedFunction.isSuspend) 1 else 0) + getAdaptedCallableReferenceFlags() shl 1 + + private fun getAdaptedCallableReferenceFlags(): Int { + if (adaptedReferenceOriginalTarget == null) return 0 + + val isVarargMappedToElementBit = if (hasVarargMappedToElement()) 1 else 0 + val isSuspendConvertedBit = + if (!adaptedReferenceOriginalTarget.isSuspend && referencedFunction.isSuspend) 1 else 0 + val isCoercedToUnitBit = + if (!adaptedReferenceOriginalTarget.returnType.isUnit() && referencedFunction.returnType.isUnit()) 1 else 0 + + return isVarargMappedToElementBit + + (isSuspendConvertedBit shl 1) + + (isCoercedToUnitBit shl 2) + } + + private fun hasVarargMappedToElement(): Boolean { + if (adapteeCall == null) return false + for (i in 0 until adapteeCall.valueArgumentsCount) { + val arg = adapteeCall.getValueArgument(i) ?: continue + if (arg !is IrVararg) continue + for (varargElement in arg.elements) { + if (varargElement is IrGetValue) return true + } + } + return false + } + + private fun buildInvokeMethod(superFunction: IrSimpleFunction): IrSimpleFunction = WrappedSimpleFunctionDescriptor().let { + IrFunctionImpl( + startOffset, endOffset, + DECLARATION_ORIGIN_FUNCTION_REFERENCE_IMPL, + IrSimpleFunctionSymbolImpl(it), + superFunction.name, + DescriptorVisibilities.PRIVATE, + Modality.FINAL, + referencedFunction.returnType, + isInline = false, + isExternal = false, + isTailrec = false, + isSuspend = superFunction.isSuspend, + isExpect = false, + isFakeOverride = false, + isOperator = false, + isInfix = false + ).apply { + it.bind(this) + val function = this + parent = functionReferenceClass + functionReferenceClass.declarations += function + + this.createDispatchReceiverParameter() + + extensionReceiverParameter = superFunction.extensionReceiverParameter?.copyTo(function) + + valueParameters += superFunction.valueParameters.mapIndexed { index, parameter -> + parameter.copyTo(function, DECLARATION_ORIGIN_FUNCTION_REFERENCE_IMPL, index, + type = parameter.type.substitute(typeArgumentsMap)) + } + + overriddenSymbols += superFunction.symbol + + body = context.createIrBuilder(function.symbol, startOffset, endOffset).irBlockBody(startOffset, endOffset) { + +irReturn( + irCall(functionReference.symbol).apply { + var unboundIndex = 0 + val unboundArgsSet = unboundFunctionParameters.toSet() + for (parameter in functionParameters) { + val argument = + if (!unboundArgsSet.contains(parameter)) + // Bound parameter - read from field. + irGetField( + irGet(function.dispatchReceiverParameter!!), + argumentToPropertiesMap[parameter]!! + ) + else { + if (parameter == referencedFunction.extensionReceiverParameter + && extensionReceiverParameter != null) + irGet(extensionReceiverParameter!!) + else if (function.isSuspend && unboundIndex == valueParameters.size) + // For suspend functions the last argument is continuation and it is implicit. + irCall(getContinuationSymbol.owner, listOf(returnType)) + else + irGet(valueParameters[unboundIndex++]) + } + when (parameter) { + referencedFunction.dispatchReceiverParameter -> dispatchReceiver = argument + referencedFunction.extensionReceiverParameter -> extensionReceiver = argument + else -> putValueArgument(parameter.index, argument) + } + } + assert(unboundIndex == valueParameters.size) { "Not all arguments of are used" } + } + ) + } + } + } + } +} diff --git a/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/lower/InitializersLowering.kt b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/lower/InitializersLowering.kt new file mode 100644 index 00000000000..fbfd584ad21 --- /dev/null +++ b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/lower/InitializersLowering.kt @@ -0,0 +1,226 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +package org.jetbrains.kotlin.backend.konan.lower + +import org.jetbrains.kotlin.backend.common.ClassLoweringPass +import org.jetbrains.kotlin.backend.common.CommonBackendContext +import org.jetbrains.kotlin.backend.common.ir.createDispatchReceiverParameter +import org.jetbrains.kotlin.backend.common.lower.createIrBuilder +import org.jetbrains.kotlin.backend.common.lower.irBlockBody +import org.jetbrains.kotlin.backend.konan.descriptors.synthesizedName +import org.jetbrains.kotlin.backend.konan.isNonGeneratedAnnotation +import org.jetbrains.kotlin.descriptors.* +import org.jetbrains.kotlin.ir.IrStatement +import org.jetbrains.kotlin.ir.builders.irDelegatingConstructorCall +import org.jetbrains.kotlin.ir.declarations.* +import org.jetbrains.kotlin.ir.declarations.impl.IrFunctionImpl +import org.jetbrains.kotlin.ir.descriptors.WrappedSimpleFunctionDescriptor +import org.jetbrains.kotlin.ir.expressions.* +import org.jetbrains.kotlin.ir.expressions.impl.* +import org.jetbrains.kotlin.ir.symbols.IrSimpleFunctionSymbol +import org.jetbrains.kotlin.ir.symbols.impl.IrSimpleFunctionSymbolImpl +import org.jetbrains.kotlin.ir.types.isPrimitiveType +import org.jetbrains.kotlin.ir.types.isString +import org.jetbrains.kotlin.ir.util.* +import org.jetbrains.kotlin.ir.visitors.IrElementTransformerVoid +import org.jetbrains.kotlin.ir.visitors.transformChildrenVoid + +internal class InitializersLowering(val context: CommonBackendContext) : ClassLoweringPass { + + object STATEMENT_ORIGIN_ANONYMOUS_INITIALIZER : IrStatementOriginImpl("ANONYMOUS_INITIALIZER") + + object DECLARATION_ORIGIN_ANONYMOUS_INITIALIZER : IrDeclarationOriginImpl("ANONYMOUS_INITIALIZER") + + override fun lower(irClass: IrClass) { + if (irClass.isInterface) return + InitializersTransformer(irClass).lowerInitializers() + } + + private inner class InitializersTransformer(val irClass: IrClass) { + val initializers = mutableListOf() + + fun lowerInitializers() { + collectAndRemoveInitializers() + val initializeMethodSymbol = createInitializerMethod() + lowerConstructors(initializeMethodSymbol) + } + + private fun collectAndRemoveInitializers() { + // Do with one traversal in order to preserve initializers order. + irClass.transformChildrenVoid(object : IrElementTransformerVoid() { + override fun visitClass(declaration: IrClass): IrStatement { + // Skip nested. + return declaration + } + + override fun visitAnonymousInitializer(declaration: IrAnonymousInitializer): IrStatement { + initializers.add(IrBlockImpl(declaration.startOffset, declaration.endOffset, + context.irBuiltIns.unitType, STATEMENT_ORIGIN_ANONYMOUS_INITIALIZER, declaration.body.statements)) + return declaration + } + + override fun visitField(declaration: IrField): IrStatement { + val initializer = declaration.initializer ?: return declaration + val startOffset = initializer.startOffset + val endOffset = initializer.endOffset + val initExpression = initializer.expression + initializers.add(IrBlockImpl(startOffset, endOffset, + context.irBuiltIns.unitType, + IrStatementOrigin.INITIALIZE_FIELD, + listOf( + IrSetFieldImpl(startOffset, endOffset, declaration.symbol, + IrGetValueImpl( + startOffset, endOffset, + irClass.thisReceiver!!.type, irClass.thisReceiver!!.symbol + ), + initExpression, + context.irBuiltIns.unitType, + IrStatementOrigin.INITIALIZE_FIELD))) + ) + + // We shall keep initializer for constants for compile-time instantiation. + declaration.initializer = + if (initExpression is IrConst<*> && + (initExpression.type.isPrimitiveType() || initExpression.type.isString())) { + IrExpressionBodyImpl(initExpression.copy()) + } else { + null + } + return declaration + } + }) + + irClass.declarations.transformFlat { + if (it !is IrAnonymousInitializer) + null + else listOf() + } + } + + private fun createInitializerMethod(): IrSimpleFunctionSymbol? { + if (irClass.declarations.any { it is IrConstructor && it.isPrimary }) + return null // Place initializers in the primary constructor. + + val startOffset = irClass.startOffset + val endOffset = irClass.endOffset + val initializeFun = WrappedSimpleFunctionDescriptor().let { + IrFunctionImpl( + startOffset, endOffset, + DECLARATION_ORIGIN_ANONYMOUS_INITIALIZER, + IrSimpleFunctionSymbolImpl(it), + "INITIALIZER".synthesizedName, + DescriptorVisibilities.PRIVATE, + Modality.FINAL, + context.irBuiltIns.unitType, + isInline = false, + isSuspend = false, + isExternal = false, + isTailrec = false, + isExpect = false, + isFakeOverride = false, + isOperator = false, + isInfix = false + ).apply { + it.bind(this) + parent = irClass + irClass.declarations.add(this) + + createDispatchReceiverParameter() + + body = IrBlockBodyImpl(startOffset, endOffset, initializers) + } + } + + for (initializer in initializers) { + initializer.transformChildrenVoid(object : IrElementTransformerVoid() { + override fun visitGetValue(expression: IrGetValue): IrExpression { + if (expression.symbol == irClass.thisReceiver!!.symbol) { + return IrGetValueImpl( + expression.startOffset, + expression.endOffset, + initializeFun.dispatchReceiverParameter!!.type, + initializeFun.dispatchReceiverParameter!!.symbol + ) + } + return expression + } + }) + initializer.setDeclarationsParent(initializeFun) + } + + return initializeFun.symbol + } + + private fun lowerConstructors(initializeMethodSymbol: IrSimpleFunctionSymbol?) { + if (irClass.kind == ClassKind.ANNOTATION_CLASS) { + if (irClass.isNonGeneratedAnnotation()) return + + val irConstructor = irClass.declarations.filterIsInstance().single() + assert(irConstructor.body == null) + irConstructor.body = context.createIrBuilder(irConstructor.symbol).irBlockBody(irConstructor) { + +irDelegatingConstructorCall(context.irBuiltIns.anyClass.owner.constructors.single()) + +IrInstanceInitializerCallImpl(startOffset, endOffset, irClass.symbol, context.irBuiltIns.unitType) + } + } + irClass.transformChildrenVoid(object : IrElementTransformerVoid() { + + override fun visitClass(declaration: IrClass): IrStatement { + // Skip nested. + return declaration + } + + override fun visitConstructor(declaration: IrConstructor): IrStatement { + val blockBody = declaration.body as? IrBlockBody + ?: throw AssertionError("Unexpected constructor body: ${declaration.body}") + + blockBody.statements.transformFlat { + when { + it is IrInstanceInitializerCall -> { + if (initializeMethodSymbol == null) { + assert(declaration.isPrimary) + for (initializer in initializers) + initializer.setDeclarationsParent(declaration) + initializers + } else { + val startOffset = it.startOffset + val endOffset = it.endOffset + listOf(IrCallImpl(startOffset, endOffset, + context.irBuiltIns.unitType, initializeMethodSymbol, + initializeMethodSymbol.owner.typeParameters.size, + initializeMethodSymbol.owner.valueParameters.size + ).apply { + dispatchReceiver = IrGetValueImpl( + startOffset, endOffset, + irClass.thisReceiver!!.type, irClass.thisReceiver!!.symbol + ) + }) + } + } + + /** + * IR for kotlin.Any is: + * BLOCK_BODY + * DELEGATING_CONSTRUCTOR_CALL 'constructor Any()' + * INSTANCE_INITIALIZER_CALL classDescriptor='Any' + * + * to avoid possible recursion we manually reject body generation for Any. + */ + it is IrDelegatingConstructorCall + && irClass.symbol == context.irBuiltIns.anyClass + && it.symbol == declaration.symbol -> { + listOf() + } + + else -> null + } + } + + return declaration + } + }) + } + } +} diff --git a/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/lower/InnerClassLowering.kt b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/lower/InnerClassLowering.kt new file mode 100644 index 00000000000..ff1022f50d5 --- /dev/null +++ b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/lower/InnerClassLowering.kt @@ -0,0 +1,151 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +package org.jetbrains.kotlin.backend.konan.lower + +import org.jetbrains.kotlin.backend.common.ClassLoweringPass +import org.jetbrains.kotlin.backend.common.IrElementTransformerVoidWithContext +import org.jetbrains.kotlin.backend.common.lower.callsSuper +import org.jetbrains.kotlin.backend.konan.Context +import org.jetbrains.kotlin.ir.declarations.* +import org.jetbrains.kotlin.ir.expressions.IrBlockBody +import org.jetbrains.kotlin.ir.expressions.IrExpression +import org.jetbrains.kotlin.ir.expressions.IrGetValue +import org.jetbrains.kotlin.ir.expressions.impl.IrGetFieldImpl +import org.jetbrains.kotlin.ir.expressions.impl.IrGetValueImpl +import org.jetbrains.kotlin.ir.expressions.impl.IrSetFieldImpl +import org.jetbrains.kotlin.ir.symbols.IrConstructorSymbol +import org.jetbrains.kotlin.ir.symbols.IrFieldSymbol +import org.jetbrains.kotlin.ir.types.classifierOrNull +import org.jetbrains.kotlin.ir.util.dump +import org.jetbrains.kotlin.ir.util.parentAsClass +import org.jetbrains.kotlin.ir.util.transformFlat +import org.jetbrains.kotlin.ir.visitors.transformChildrenVoid + +internal class InnerClassLowering(val context: Context) : ClassLoweringPass { + override fun lower(irClass: IrClass) { + InnerClassTransformer(irClass).lowerInnerClass() + } + + companion object { + fun addOuterThisField(declarations: MutableList, irClass: IrClass, context: Context): IrField { + val outerThisField = context.specialDeclarationsFactory.getOuterThisField(irClass) + declarations += outerThisField + return outerThisField + } + } + + private inner class InnerClassTransformer(val irClass: IrClass) { + lateinit var outerThisFieldSymbol: IrFieldSymbol + + fun lowerInnerClass() { + if (!irClass.isInner) return + + createOuterThisField() + lowerOuterThisReferences() + lowerConstructors() + } + + private fun createOuterThisField() { + val outerThisField = addOuterThisField(irClass.declarations, irClass, context) + outerThisFieldSymbol = outerThisField.symbol + } + + private fun lowerConstructors() { + irClass.declarations.transformFlat { irMember -> + if (irMember is IrConstructor) + listOf(lowerConstructor(irMember)) + else + null + } + } + + private fun lowerConstructor(irConstructor: IrConstructor): IrConstructor { + if (irConstructor.callsSuper(context.irBuiltIns)) { + // Initializing constructor: initialize 'this.this$0' with '$outer'. + val blockBody = irConstructor.body as? IrBlockBody + ?: throw AssertionError("Unexpected constructor body: ${irConstructor.body}") + val startOffset = irConstructor.startOffset + val endOffset = irConstructor.endOffset + val thisReceiver = irClass.thisReceiver!! + val outerReceiver = irConstructor.dispatchReceiverParameter!! + blockBody.statements.add( + 0, + IrSetFieldImpl( + startOffset, endOffset, outerThisFieldSymbol, + IrGetValueImpl(startOffset, endOffset, thisReceiver.type, thisReceiver.symbol), + IrGetValueImpl(startOffset, endOffset, outerReceiver.type, outerReceiver.symbol), + context.irBuiltIns.unitType + ) + ) + } + + return irConstructor + } + + private fun lowerOuterThisReferences() { + irClass.transformChildrenVoid(object : IrElementTransformerVoidWithContext() { + override fun visitGetValue(expression: IrGetValue): IrExpression { + expression.transformChildrenVoid(this) + + val implicitThisClass = (expression.symbol.owner.parent as? IrClass) ?: return expression + + if (implicitThisClass == irClass) return expression + + val constructorSymbol = currentFunction!!.scope.scopeOwnerSymbol as? IrConstructorSymbol + + val startOffset = expression.startOffset + val endOffset = expression.endOffset + val origin = expression.origin + + var irThis: IrExpression + var innerClass: IrClass + if (constructorSymbol == null || constructorSymbol.owner.parentAsClass != irClass) { + innerClass = irClass + val currentIrFunction = currentFunction!!.scope.scopeOwnerSymbol.owner as IrFunction + + val currentFunctionReceiver = currentIrFunction.dispatchReceiverParameter + val thisParameter = + if (currentFunctionReceiver?.type?.classifierOrNull == irClass.symbol) + currentFunctionReceiver + else + irClass.thisReceiver!! + + irThis = IrGetValueImpl(startOffset, endOffset, thisParameter.type, thisParameter.symbol, origin) + } else { + // For constructor we have outer class as dispatchReceiverParameter. + innerClass = irClass.parent as? IrClass ?: + throw AssertionError("No containing class for inner class ${irClass.dump()}") + val thisParameter = constructorSymbol.owner.dispatchReceiverParameter!! + irThis = IrGetValueImpl(startOffset, endOffset, thisParameter.type, thisParameter.symbol, origin) + } + + while (innerClass != implicitThisClass) { + if (!innerClass.isInner) { + // Captured 'this' unrelated to inner classes nesting hierarchy, leave it as is - + // should be transformed by closures conversion. + return expression + } + + val outerThisField = context.specialDeclarationsFactory.getOuterThisField(innerClass) + irThis = IrGetFieldImpl( + startOffset, endOffset, + outerThisField.symbol, outerThisField.type, + irThis, + origin + ) + + val outer = innerClass.parent + innerClass = outer as? IrClass ?: + throw AssertionError("Unexpected containing declaration for inner class ${innerClass.dump()}: $outer") + } + + return irThis + } + }) + } + } +} + diff --git a/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/lower/InteropCallConvertors.kt b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/lower/InteropCallConvertors.kt new file mode 100644 index 00000000000..d0564de3bce --- /dev/null +++ b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/lower/InteropCallConvertors.kt @@ -0,0 +1,441 @@ +/* + * Copyright 2010-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ +package org.jetbrains.kotlin.backend.konan.lower + +import org.jetbrains.kotlin.backend.common.ir.simpleFunctions +import org.jetbrains.kotlin.backend.konan.PrimitiveBinaryType +import org.jetbrains.kotlin.backend.konan.RuntimeNames +import org.jetbrains.kotlin.backend.konan.cgen.* +import org.jetbrains.kotlin.backend.konan.descriptors.getAnnotationStringValue +import org.jetbrains.kotlin.backend.konan.ir.KonanSymbols +import org.jetbrains.kotlin.backend.konan.llvm.IntrinsicType +import org.jetbrains.kotlin.ir.builders.* +import org.jetbrains.kotlin.ir.declarations.IrFunction +import org.jetbrains.kotlin.ir.descriptors.IrBuiltIns +import org.jetbrains.kotlin.ir.expressions.IrCall +import org.jetbrains.kotlin.ir.expressions.IrConst +import org.jetbrains.kotlin.ir.expressions.IrExpression +import org.jetbrains.kotlin.ir.symbols.IrClassSymbol +import org.jetbrains.kotlin.ir.types.IrType +import org.jetbrains.kotlin.ir.types.classOrNull +import org.jetbrains.kotlin.ir.types.defaultType +import org.jetbrains.kotlin.ir.types.getClass +import org.jetbrains.kotlin.ir.util.* +import org.jetbrains.kotlin.utils.addToStdlib.cast + +private class InteropCallContext( + val symbols: KonanSymbols, + val builder: IrBuilderWithScope, + val failCompilation: (String) -> Nothing +) { + fun IrType.isCPointer() = this.isCPointer(symbols) + + fun IrType.isNativePointed() = this.isNativePointed(symbols) + + fun IrType.isSupportedReference() = this.isCStructFieldSupportedReferenceType(symbols) + + val irBuiltIns: IrBuiltIns = builder.context.irBuiltIns +} + +private inline fun generateInteropCall( + symbols: KonanSymbols, + builder: IrBuilderWithScope, + noinline failCompilation: (String) -> Nothing, + block: InteropCallContext.() -> T +) = InteropCallContext(symbols, builder, failCompilation).block() + +/** + * Search for memory read/write function in [kotlinx.cinterop.nativeMemUtils] of a given [valueType]. + */ +private fun InteropCallContext.findMemoryAccessFunction(isRead: Boolean, valueType: IrType): IrFunction { + val requiredType = if (isRead) { + IntrinsicType.INTEROP_READ_PRIMITIVE + } else { + IntrinsicType.INTEROP_WRITE_PRIMITIVE + } + val nativeMemUtilsClass = symbols.nativeMemUtils.owner + return nativeMemUtilsClass.functions.filter { + val annotationArgument = it.annotations + .findAnnotation(RuntimeNames.typedIntrinsicAnnotation) + ?.getAnnotationStringValue() + annotationArgument == requiredType.name + }.firstOrNull { + if (isRead) { + it.returnType.classOrNull == valueType.classOrNull + } else { + it.valueParameters.last().type.classOrNull == valueType.classOrNull + } + } ?: error("No memory access function for ${valueType.classOrNull?.owner?.name}") +} + +private fun InteropCallContext.readValueFromMemory( + nativePtr: IrExpression, + returnType: IrType +): IrExpression { + val memoryValueType = determineInMemoryType(returnType) + val memReadFn = findMemoryAccessFunction(isRead = true, valueType = memoryValueType) + val memRead = builder.irCall(memReadFn).also { memRead -> + memRead.dispatchReceiver = builder.irGetObject(symbols.nativeMemUtils) + memRead.putValueArgument(0, builder.irCall(symbols.interopInterpretNullablePointed).also { + it.putValueArgument(0, nativePtr) + }) + } + return castPrimitiveIfNeeded(memRead, memoryValueType, returnType) +} + +private fun InteropCallContext.writeValueToMemory( + nativePtr: IrExpression, + value: IrExpression, + targetType: IrType +): IrExpression { + val memoryValueType = determineInMemoryType(targetType) + val memWriteFn = findMemoryAccessFunction(isRead = false, valueType = memoryValueType) + val valueToWrite = castPrimitiveIfNeeded(value, targetType, memoryValueType) + return with(builder) { + irCall(memWriteFn).also { memWrite -> + memWrite.dispatchReceiver = irGetObject(symbols.nativeMemUtils) + memWrite.putValueArgument(0, irCall(symbols.interopInterpretNullablePointed).also { + it.putValueArgument(0, nativePtr) + }) + memWrite.putValueArgument(1, valueToWrite) + } + } +} + +private fun InteropCallContext.determineInMemoryType(type: IrType): IrType { + val classifier = type.classOrNull!! + return when (classifier) { + in symbols.unsignedIntegerClasses -> { + symbols.unsignedToSignedOfSameBitWidth.getValue(classifier).owner.defaultType + } + // Assuming that _Bool is stored as single byte. + irBuiltIns.booleanClass -> symbols.byte.defaultType + else -> type + } +} + +private fun InteropCallContext.castPrimitiveIfNeeded( + value: IrExpression, + fromType: IrType, + toType: IrType +): IrExpression { + val sourceClass = fromType.classOrNull!! + val targetClass = toType.classOrNull!! + return if (sourceClass != targetClass) { + when { + targetClass == irBuiltIns.booleanClass -> castToBoolean(sourceClass, value) + sourceClass == irBuiltIns.booleanClass -> castFromBoolean(targetClass, value) + else -> { + val conversion = symbols.integerConversions[sourceClass to targetClass] + ?: error("There is no conversion from ${sourceClass.owner.name} to ${targetClass.owner.name}") + builder.irCall(conversion.owner).apply { + if (conversion.owner.dispatchReceiverParameter != null) { + dispatchReceiver = value + } else { + extensionReceiver = value + } + } + } + } + } else { + value + } +} + +/** + * Perform (value != 0) + */ +private fun InteropCallContext.castToBoolean(sourceClass: IrClassSymbol, value: IrExpression): IrExpression { + val (primitiveBinaryType, immZero) = when (sourceClass) { + // Case of regular struct field. + symbols.byte -> PrimitiveBinaryType.BYTE to builder.irByte(0) + // Case of bitfield. + symbols.long -> PrimitiveBinaryType.LONG to builder.irLong(0) + else -> error("Unsupported cast to boolean from ${sourceClass.owner.name}") + } + val areEqualByValuesBytes = symbols.areEqualByValue.getValue(primitiveBinaryType) + val compareToZero = builder.irCall(areEqualByValuesBytes).apply { + putValueArgument(0, value) + putValueArgument(1, immZero) + } + return builder.irCall(irBuiltIns.booleanNotSymbol).apply { + dispatchReceiver = compareToZero + } +} + +/** + * Perform if (value) 1 else 0 + */ +private fun InteropCallContext.castFromBoolean(targetClass: IrClassSymbol, value: IrExpression): IrExpression { + val (thenPart, elsePart) = when (targetClass) { + // Case of regular struct field. + symbols.byte -> builder.irByte(1) to builder.irByte(0) + // Case of bitfield. + symbols.long -> builder.irLong(1) to builder.irLong(0) + else -> error("Unsupported cast from boolean to ${targetClass.owner.name}") + } + return builder.irIfThenElse(targetClass.defaultType, value, thenPart, elsePart) +} + +private fun InteropCallContext.convertEnumToIntegral(enumValue: IrExpression, targetEnumType: IrType): IrExpression { + val enumClass = targetEnumType.getClass()!! + val valueProperty = enumClass.properties.single { it.name.asString() == "value" } + return builder.irCall(valueProperty.getter!!).also { + it.dispatchReceiver = enumValue + } +} + +private fun InteropCallContext.convertIntegralToEnum( + value: IrExpression, + intergralType: IrType, + enumType: IrType +): IrExpression { + val enumClass = enumType.getClass()!! + val companionClass = enumClass.companionObject()!! + val byValue = companionClass.simpleFunctions().single { it.name.asString() == "byValue" } + val byValueArg = castPrimitiveIfNeeded(value, intergralType, byValue.valueParameters.first().type) + return builder.irCall(byValue).apply { + dispatchReceiver = builder.irGetObject(companionClass.symbol) + putValueArgument(0, byValueArg) + } +} + +private fun IrType.getCEnumPrimitiveType(): IrType { + assert(this.isCEnumType()) + val enumClass = this.getClass()!! + return enumClass.properties.single { it.name.asString() == "value" } + .getter!!.returnType +} + +private fun InteropCallContext.readEnumValueFromMemory(nativePtr: IrExpression, enumType: IrType): IrExpression { + val enumPrimitiveType = enumType.getCEnumPrimitiveType() + val readMemory = readValueFromMemory(nativePtr, enumPrimitiveType) + return convertIntegralToEnum(readMemory, readMemory.type, enumType) +} + +private fun InteropCallContext.writeEnumValueToMemory( + nativePtr: IrExpression, + value: IrExpression, + targetEnumType: IrType +): IrExpression { + val valueToWrite = convertEnumToIntegral(value, targetEnumType) + return writeValueToMemory(nativePtr, valueToWrite, targetEnumType.getCEnumPrimitiveType()) +} + +private fun InteropCallContext.convertCPointerToNativePtr(cPointer: IrExpression): IrExpression { + return builder.irCall(symbols.interopCPointerGetRawValue).also { + it.extensionReceiver = cPointer + } +} + + +private fun InteropCallContext.writePointerToMemory( + nativePtr: IrExpression, + value: IrExpression, + pointerType: IrType +): IrExpression { + val valueToWrite = when { + pointerType.isCPointer() -> convertCPointerToNativePtr(value) + else -> error("Unsupported pointer type") + } + return writeValueToMemory(nativePtr, valueToWrite, valueToWrite.type) +} + +private fun InteropCallContext.writeObjCReferenceToMemory( + nativePtr: IrExpression, + value: IrExpression +): IrExpression { + val valueToWrite = builder.irCall(symbols.interopObjCObjectRawValueGetter).also { + it.extensionReceiver = value + } + return writeValueToMemory(nativePtr, valueToWrite, valueToWrite.type) +} + +private fun InteropCallContext.calculateFieldPointer(receiver: IrExpression, offset: Long): IrExpression { + val base = builder.irCall(symbols.interopNativePointedRawPtrGetter).also { + it.dispatchReceiver = receiver + } + val nativePtrPlusLong = symbols.nativePtrType.getClass()!! + .functions.single { it.name.identifier == "plus" } + return with (builder) { + irCall(nativePtrPlusLong).also { + it.dispatchReceiver = base + it.putValueArgument(0, irLong(offset)) + } + } +} + +private fun InteropCallContext.readPointerFromMemory(nativePtr: IrExpression): IrExpression { + val readMemory = readValueFromMemory(nativePtr, symbols.nativePtrType) + return builder.irCall(symbols.interopInterpretCPointer).also { + it.putValueArgument(0, readMemory) + } +} + +private fun InteropCallContext.readPointed(nativePtr: IrExpression): IrExpression { + return builder.irCall(symbols.interopInterpretNullablePointed).also { + it.putValueArgument(0, nativePtr) + } +} + +private fun InteropCallContext.readObjectiveCReferenceFromMemory( + nativePtr: IrExpression, + type: IrType +): IrExpression { + val readMemory = readValueFromMemory(nativePtr, symbols.nativePtrType) + return builder.irCall(symbols.interopInterpretObjCPointerOrNull, listOf(type)).apply { + putValueArgument(0, readMemory) + } +} + +/** Returns non-null result if [callSite] is accessor to: + * 1. T.value, T : CEnumVar + * 2. T., T : CStructVar and accessor is annotated with + * [kotlinx.cinterop.internal.CStruct.MemberAt] or [kotlinx.cinterop.internal.CStruct.BitField] + */ +internal fun tryGenerateInteropMemberAccess( + callSite: IrCall, + symbols: KonanSymbols, + builder: IrBuilderWithScope, + failCompilation: (String) -> Nothing +): IrExpression? = when { + callSite.symbol.owner.isCEnumVarValueAccessor(symbols) -> + generateInteropCall(symbols, builder, failCompilation) { generateEnumVarValueAccess(callSite) } + callSite.symbol.owner.isCStructMemberAtAccessor() -> + generateInteropCall(symbols, builder, failCompilation) { generateMemberAtAccess(callSite) } + callSite.symbol.owner.isCStructBitFieldAccessor() -> + generateInteropCall(symbols, builder, failCompilation) { generateBitFieldAccess(callSite) } + callSite.symbol.owner.isCStructArrayMemberAtAccessor() -> + generateInteropCall(symbols, builder, failCompilation) { generateArrayMemberAtAccess(callSite) } + else -> null +} + +private fun InteropCallContext.generateEnumVarValueAccess(callSite: IrCall): IrExpression { + val accessor = callSite.symbol.owner + val nativePtr = builder.irCall(symbols.interopNativePointedRawPtrGetter).also { + it.dispatchReceiver = callSite.dispatchReceiver!! + } + return when { + accessor.isGetter -> readEnumValueFromMemory(nativePtr, accessor.returnType) + accessor.isSetter -> { + val type = accessor.valueParameters[0].type + writeEnumValueToMemory(nativePtr, callSite.getValueArgument(0)!!, type) + } + else -> error("") + } +} + +private fun InteropCallContext.generateMemberAtAccess(callSite: IrCall): IrExpression { + val accessor = callSite.symbol.owner + val memberAt = accessor.getAnnotation(RuntimeNames.cStructMemberAt)!! + val offset = memberAt.getValueArgument(0).cast>().value + val fieldPointer = calculateFieldPointer(callSite.dispatchReceiver!!, offset) + return when { + accessor.isGetter -> { + val type = accessor.returnType + when { + type.isCEnumType() -> readEnumValueFromMemory(fieldPointer, type) + type.isCStructFieldTypeStoredInMemoryDirectly() -> readValueFromMemory(fieldPointer, type) + type.isCPointer() -> readPointerFromMemory(fieldPointer) + type.isNativePointed() -> readPointed(fieldPointer) + type.isSupportedReference() -> readObjectiveCReferenceFromMemory(fieldPointer, type) + else -> failCompilation("Unsupported struct field type: ${type.getClass()?.name}") + } + } + accessor.isSetter -> { + val value = callSite.getValueArgument(0)!! + val type = accessor.valueParameters[0].type + when { + type.isCEnumType() -> writeEnumValueToMemory(fieldPointer, value, type) + type.isCStructFieldTypeStoredInMemoryDirectly() -> writeValueToMemory(fieldPointer, value, type) + type.isCPointer() -> writePointerToMemory(fieldPointer, value, type) + type.isSupportedReference() -> writeObjCReferenceToMemory(fieldPointer, value) + else -> failCompilation("Unsupported struct field type: ${type.getClass()?.name}") + } + } + else -> failCompilation("Unexpected accessor function: ${accessor.name}") + } +} + +private fun InteropCallContext.generateArrayMemberAtAccess(callSite: IrCall): IrExpression { + val accessor = callSite.symbol.owner + val memberAt = accessor.getAnnotation(RuntimeNames.cStructArrayMemberAt)!! + val offset = memberAt.getValueArgument(0).cast>().value + val fieldPointer = calculateFieldPointer(callSite.dispatchReceiver!!, offset) + return builder.irCall(symbols.interopInterpretCPointer).also { + it.putValueArgument(0, fieldPointer) + } +} + +private fun InteropCallContext.writeBits( + base: IrExpression, + offset: Long, + size: Int, + value: IrExpression, + type: IrType +): IrExpression { + val (integralValue, fromType) = when { + type.isCEnumType() -> convertEnumToIntegral(value, type) to type.getCEnumPrimitiveType() + else -> value to type + } + val targetType = symbols.writeBits.owner.valueParameters.last().type + val valueToWrite = castPrimitiveIfNeeded(integralValue, fromType, targetType) + return with(builder) { + irCall(symbols.writeBits).also { + it.putValueArgument(0, base) + it.putValueArgument(1, irLong(offset)) + it.putValueArgument(2, irInt(size)) + it.putValueArgument(3, valueToWrite) + } + } +} + +private fun InteropCallContext.readBits( + base: IrExpression, + offset: Long, + size: Int, + type: IrType +): IrExpression { + val isSigned = when { + type.isCEnumType() -> + !type.getCEnumPrimitiveType().isUnsigned() + else -> + !type.isUnsigned() + } + val integralValue = with (builder) { + irCall(symbols.readBits).also { + it.putValueArgument(0, base) + it.putValueArgument(1, irLong(offset)) + it.putValueArgument(2, irInt(size)) + it.putValueArgument(3, irBoolean(isSigned)) + } + } + return when { + type.isCEnumType() -> convertIntegralToEnum(integralValue, integralValue.type, type) + else -> castPrimitiveIfNeeded(integralValue, integralValue.type, type) + } +} + +private fun InteropCallContext.generateBitFieldAccess(callSite: IrCall): IrExpression { + val accessor = callSite.symbol.owner + val bitField = accessor.getAnnotation(RuntimeNames.cStructBitField)!! + val offset = bitField.getValueArgument(0).cast>().value + val size = bitField.getValueArgument(1).cast>().value + val base = builder.irCall(symbols.interopNativePointedRawPtrGetter).also { + it.dispatchReceiver = callSite.dispatchReceiver!! + } + return when { + accessor.isSetter -> { + val argument = callSite.getValueArgument(0)!! + val type = accessor.valueParameters[0].type + writeBits(base, offset, size, argument, type) + } + accessor.isGetter -> { + val type = accessor.returnType + readBits(base, offset, size, type) + } + else -> error("Unexpected accessor function: ${accessor.name}") + } +} diff --git a/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/lower/InteropLowering.kt b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/lower/InteropLowering.kt new file mode 100644 index 00000000000..3d640b3af4b --- /dev/null +++ b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/lower/InteropLowering.kt @@ -0,0 +1,1090 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +package org.jetbrains.kotlin.backend.konan.lower + +import org.jetbrains.kotlin.backend.common.* +import org.jetbrains.kotlin.backend.common.ir.allParameters +import org.jetbrains.kotlin.backend.common.ir.copyTo +import org.jetbrains.kotlin.backend.common.ir.createDispatchReceiverParameter +import org.jetbrains.kotlin.backend.common.ir.simpleFunctions +import org.jetbrains.kotlin.backend.common.lower.* +import org.jetbrains.kotlin.backend.konan.* +import org.jetbrains.kotlin.backend.konan.cgen.* +import org.jetbrains.kotlin.backend.konan.descriptors.allOverriddenFunctions +import org.jetbrains.kotlin.backend.konan.descriptors.isFromInteropLibrary +import org.jetbrains.kotlin.backend.konan.descriptors.konanLibrary +import org.jetbrains.kotlin.backend.konan.descriptors.synthesizedName +import org.jetbrains.kotlin.backend.konan.ir.* +import org.jetbrains.kotlin.backend.konan.ir.companionObject +import org.jetbrains.kotlin.backend.konan.llvm.IntrinsicType +import org.jetbrains.kotlin.backend.konan.llvm.tryGetIntrinsicType +import org.jetbrains.kotlin.backend.konan.serialization.resolveFakeOverrideMaybeAbstract +import org.jetbrains.kotlin.descriptors.* +import org.jetbrains.kotlin.ir.IrElement +import org.jetbrains.kotlin.ir.IrStatement +import org.jetbrains.kotlin.ir.builders.* +import org.jetbrains.kotlin.ir.declarations.* +import org.jetbrains.kotlin.ir.declarations.impl.IrFunctionImpl +import org.jetbrains.kotlin.ir.declarations.impl.IrValueParameterImpl +import org.jetbrains.kotlin.ir.descriptors.WrappedSimpleFunctionDescriptor +import org.jetbrains.kotlin.ir.descriptors.WrappedValueParameterDescriptor +import org.jetbrains.kotlin.ir.expressions.* +import org.jetbrains.kotlin.ir.expressions.impl.IrConstImpl +import org.jetbrains.kotlin.ir.expressions.impl.IrDelegatingConstructorCallImpl +import org.jetbrains.kotlin.ir.expressions.impl.IrFunctionReferenceImpl +import org.jetbrains.kotlin.ir.expressions.impl.IrReturnImpl +import org.jetbrains.kotlin.ir.symbols.IrClassSymbol +import org.jetbrains.kotlin.ir.symbols.IrFunctionSymbol +import org.jetbrains.kotlin.ir.symbols.IrSimpleFunctionSymbol +import org.jetbrains.kotlin.ir.symbols.impl.IrSimpleFunctionSymbolImpl +import org.jetbrains.kotlin.ir.symbols.impl.IrValueParameterSymbolImpl +import org.jetbrains.kotlin.ir.types.* +import org.jetbrains.kotlin.ir.util.* +import org.jetbrains.kotlin.ir.visitors.transformChildrenVoid +import org.jetbrains.kotlin.name.FqName +import org.jetbrains.kotlin.name.Name +import org.jetbrains.kotlin.resolve.descriptorUtil.fqNameSafe +import org.jetbrains.kotlin.resolve.descriptorUtil.module +import org.jetbrains.kotlin.konan.ForeignExceptionMode + +internal class InteropLowering(context: Context) : FileLoweringPass { + // TODO: merge these lowerings. + private val part1 = InteropLoweringPart1(context) + private val part2 = InteropLoweringPart2(context) + + override fun lower(irFile: IrFile) { + part1.lower(irFile) + part2.lower(irFile) + } +} + +private abstract class BaseInteropIrTransformer(private val context: Context) : IrBuildingTransformer(context) { + + protected inline fun generateWithStubs(element: IrElement? = null, block: KotlinStubs.() -> T): T = + createKotlinStubs(element).block() + + protected fun createKotlinStubs(element: IrElement?): KotlinStubs { + val location = if (element != null) { + element.getCompilerMessageLocation(irFile) + } else { + builder.getCompilerMessageLocation() + } + + val uniqueModuleName = irFile.packageFragmentDescriptor.module.name.asString() + .let { it.substring(1, it.lastIndex) } + val uniquePrefix = buildString { + append('_') + uniqueModuleName.toByteArray().joinTo(this, "") { + (0xFF and it.toInt()).toString(16).padStart(2, '0') + } + append('_') + } + + return object : KotlinStubs { + override val irBuiltIns get() = context.irBuiltIns + override val symbols get() = context.ir.symbols + + override fun addKotlin(declaration: IrDeclaration) { + addTopLevel(declaration) + } + + override fun addC(lines: List) { + context.cStubsManager.addStub(location, lines) + } + + override fun getUniqueCName(prefix: String) = + "$uniquePrefix${context.cStubsManager.getUniqueName(prefix)}" + + override fun getUniqueKotlinFunctionReferenceClassName(prefix: String) = + "$prefix${context.functionReferenceCount++}" + + override val target get() = context.config.target + + override fun throwCompilerError(element: IrElement?, message: String): Nothing { + error(irFile, element, message) + } + + override fun renderCompilerError(element: IrElement?, message: String) = + renderCompilerError(irFile, element, message) + } + } + + protected fun renderCompilerError(element: IrElement?, message: String = "Failed requirement") = + renderCompilerError(irFile, element, message) + + protected abstract val irFile: IrFile + protected abstract fun addTopLevel(declaration: IrDeclaration) +} + +private class InteropLoweringPart1(val context: Context) : BaseInteropIrTransformer(context), FileLoweringPass { + + private val symbols get() = context.ir.symbols + + lateinit var currentFile: IrFile + + private val topLevelInitializers = mutableListOf() + private val newTopLevelDeclarations = mutableListOf() + + override val irFile: IrFile + get() = currentFile + + override fun addTopLevel(declaration: IrDeclaration) { + declaration.parent = currentFile + newTopLevelDeclarations += declaration + } + + override fun lower(irFile: IrFile) { + currentFile = irFile + irFile.transformChildrenVoid(this) + + topLevelInitializers.forEach { irFile.addTopLevelInitializer(it, context, false) } + topLevelInitializers.clear() + + irFile.addChildren(newTopLevelDeclarations) + newTopLevelDeclarations.clear() + } + + private fun IrBuilderWithScope.callAlloc(classPtr: IrExpression): IrExpression = + irCall(symbols.interopAllocObjCObject).apply { + putValueArgument(0, classPtr) + } + + private val outerClasses = mutableListOf() + + override fun visitClass(declaration: IrClass): IrStatement { + if (declaration.isKotlinObjCClass()) { + lowerKotlinObjCClass(declaration) + } + + outerClasses.push(declaration) + try { + return super.visitClass(declaration) + } finally { + outerClasses.pop() + } + } + + private fun lowerKotlinObjCClass(irClass: IrClass) { + checkKotlinObjCClass(irClass) + + val interop = context.interopBuiltIns + + irClass.declarations.toList().mapNotNull { + when { + it is IrSimpleFunction && it.annotations.hasAnnotation(interop.objCAction.fqNameSafe) -> + generateActionImp(it) + + it is IrProperty && it.annotations.hasAnnotation(interop.objCOutlet.fqNameSafe) -> + generateOutletSetterImp(it) + + it is IrConstructor && it.isOverrideInit() -> + generateOverrideInit(irClass, it) + + else -> null + } + }.let { irClass.addChildren(it) } + + if (irClass.annotations.hasAnnotation(interop.exportObjCClass.fqNameSafe)) { + val irBuilder = context.createIrBuilder(currentFile.symbol).at(irClass) + topLevelInitializers.add(irBuilder.getObjCClass(symbols, irClass.symbol)) + } + } + + private fun IrConstructor.isOverrideInit(): Boolean { + if (this.origin != IrDeclarationOrigin.DEFINED) { + // Make best efforts to skip generated stubs that might have got annotations + // copied from original declarations. + // For example, default argument stubs (https://youtrack.jetbrains.com/issue/KT-41910). + return false + } + + return this.annotations.hasAnnotation(context.interopBuiltIns.objCOverrideInit.fqNameSafe) + } + + private fun generateOverrideInit(irClass: IrClass, constructor: IrConstructor): IrSimpleFunction { + val superClass = irClass.getSuperClassNotAny()!! + val superConstructors = superClass.constructors.filter { + constructor.overridesConstructor(it) + }.toList() + + val superConstructor = superConstructors.singleOrNull() + require(superConstructor != null) { renderCompilerError(constructor) } + + val initMethod = superConstructor.getObjCInitMethod()!! + + // Remove fake overrides of this init method, also check for explicit overriding: + irClass.declarations.removeAll { + if (it is IrSimpleFunction && initMethod.symbol in it.overriddenSymbols) { + require(it.isFakeOverride) { renderCompilerError(constructor) } + true + } else { + false + } + } + + // Generate `override fun init...(...) = this.initBy(...)`: + + val resultDescriptor = WrappedSimpleFunctionDescriptor() + return IrFunctionImpl( + constructor.startOffset, constructor.endOffset, + OVERRIDING_INITIALIZER_BY_CONSTRUCTOR, + IrSimpleFunctionSymbolImpl(resultDescriptor), + initMethod.name, + DescriptorVisibilities.PUBLIC, + Modality.OPEN, + irClass.defaultType, + isInline = false, + isExternal = false, + isTailrec = false, + isSuspend = false, + isExpect = false, + isFakeOverride = false, + isOperator = false, + isInfix = false + ).also { result -> + resultDescriptor.bind(result) + result.parent = irClass + result.createDispatchReceiverParameter() + result.valueParameters += constructor.valueParameters.map { it.copyTo(result) } + + result.overriddenSymbols += initMethod.symbol + + result.body = context.createIrBuilder(result.symbol).irBlockBody(result) { + +irReturn( + irCall(symbols.interopObjCObjectInitBy, listOf(irClass.defaultType)).apply { + extensionReceiver = irGet(result.dispatchReceiverParameter!!) + putValueArgument(0, irCall(constructor).also { + result.valueParameters.forEach { parameter -> + it.putValueArgument(parameter.index, irGet(parameter)) + } + }) + } + ) + } + + // Ensure it gets correctly recognized by the compiler. + require(result.getObjCMethodInfo() != null) { renderCompilerError(constructor) } + } + } + + private object OVERRIDING_INITIALIZER_BY_CONSTRUCTOR : + IrDeclarationOriginImpl("OVERRIDING_INITIALIZER_BY_CONSTRUCTOR") + + private fun IrConstructor.overridesConstructor(other: IrConstructor): Boolean { + return this.descriptor.valueParameters.size == other.descriptor.valueParameters.size && + this.descriptor.valueParameters.all { + val otherParameter = other.descriptor.valueParameters[it.index] + it.name == otherParameter.name && it.type == otherParameter.type + } + } + + private fun generateActionImp(function: IrSimpleFunction): IrSimpleFunction { + require(function.extensionReceiverParameter == null) { renderCompilerError(function) } + require(function.valueParameters.all { it.type.isObjCObjectType() }) { renderCompilerError(function) } + require(function.returnType.isUnit()) { renderCompilerError(function) } + + return generateFunctionImp(inferObjCSelector(function.descriptor), function) + } + + private fun generateOutletSetterImp(property: IrProperty): IrSimpleFunction { + require(property.isVar) { renderCompilerError(property) } + require(property.getter?.extensionReceiverParameter == null) { renderCompilerError(property) } + require(property.descriptor.type.isObjCObjectType()) { renderCompilerError(property) } + + val name = property.name.asString() + val selector = "set${name.capitalize()}:" + + return generateFunctionImp(selector, property.setter!!) + } + + private fun getMethodSignatureEncoding(function: IrFunction): String { + require(function.extensionReceiverParameter == null) { renderCompilerError(function) } + require(function.valueParameters.all { it.type.isObjCObjectType() }) { renderCompilerError(function) } + require(function.returnType.isUnit()) { renderCompilerError(function) } + + // Note: these values are valid for x86_64 and arm64. + return when (function.valueParameters.size) { + 0 -> "v16@0:8" + 1 -> "v24@0:8@16" + 2 -> "v32@0:8@16@24" + else -> error(irFile, function, "Only 0, 1 or 2 parameters are supported here") + } + } + + private fun generateFunctionImp(selector: String, function: IrFunction): IrSimpleFunction { + val signatureEncoding = getMethodSignatureEncoding(function) + + val nativePtrType = context.ir.symbols.nativePtrType + + val parameterTypes = mutableListOf(nativePtrType) // id self + + parameterTypes.add(nativePtrType) // SEL _cmd + + function.valueParameters.mapTo(parameterTypes) { nativePtrType } + + val newFunction = WrappedSimpleFunctionDescriptor().let { + IrFunctionImpl( + function.startOffset, function.endOffset, + IrDeclarationOrigin.DEFINED, + IrSimpleFunctionSymbolImpl(it), + ("imp:$selector").synthesizedName, + DescriptorVisibilities.PRIVATE, + Modality.FINAL, + function.returnType, + isInline = false, + isExternal = false, + isTailrec = false, + isSuspend = false, + isExpect = false, + isFakeOverride = false, + isOperator = false, + isInfix = false + ).apply { + it.bind(this) + } + } + + newFunction.valueParameters += parameterTypes.mapIndexed { index, type -> + WrappedValueParameterDescriptor().let { + IrValueParameterImpl( + function.startOffset, function.endOffset, + IrDeclarationOrigin.DEFINED, + IrValueParameterSymbolImpl(it), + Name.identifier("p$index"), + index, + type, + varargElementType = null, + isCrossinline = false, + isNoinline = false + ).apply { + it.bind(this) + parent = newFunction + } + } + } + + // Annotations to be detected in KotlinObjCClassInfoGenerator: + + newFunction.annotations += buildSimpleAnnotation(context.irBuiltIns, function.startOffset, function.endOffset, + symbols.objCMethodImp.owner, selector, signatureEncoding) + + val builder = context.createIrBuilder(newFunction.symbol) + newFunction.body = builder.irBlockBody(newFunction) { + +irCall(function).apply { + dispatchReceiver = interpretObjCPointer( + irGet(newFunction.valueParameters[0]), + function.dispatchReceiverParameter!!.type + ) + + function.valueParameters.forEachIndexed { index, parameter -> + putValueArgument(index, + interpretObjCPointer( + irGet(newFunction.valueParameters[index + 2]), + parameter.type + ) + ) + } + } + } + + return newFunction + } + + private fun IrBuilderWithScope.interpretObjCPointer(expression: IrExpression, type: IrType): IrExpression { + val callee: IrFunctionSymbol = if (type.containsNull()) { + symbols.interopInterpretObjCPointerOrNull + } else { + symbols.interopInterpretObjCPointer + } + + return irCall(callee, listOf(type)).apply { + putValueArgument(0, expression) + } + } + + private fun IrClass.hasFields() = + this.declarations.any { + when (it) { + is IrField -> it.isReal + is IrProperty -> it.isReal && it.backingField != null + else -> false + } + } + + private fun checkKotlinObjCClass(irClass: IrClass) { + val kind = irClass.kind + require(kind == ClassKind.CLASS || kind == ClassKind.OBJECT) { renderCompilerError(irClass) } + require(irClass.isFinalClass) { renderCompilerError(irClass) } + require(irClass.companionObject()?.hasFields() != true) { renderCompilerError(irClass) } + require(irClass.companionObject()?.getSuperClassNotAny()?.hasFields() != true) { renderCompilerError(irClass) } + + var hasObjCClassSupertype = false + irClass.descriptor.defaultType.constructor.supertypes.forEach { + val descriptor = it.constructor.declarationDescriptor as ClassDescriptor + require(descriptor.isObjCClass()) { renderCompilerError(irClass) } + + if (descriptor.kind == ClassKind.CLASS) { + hasObjCClassSupertype = true + } + } + + require(hasObjCClassSupertype) { renderCompilerError(irClass) } + + val methodsOfAny = + context.ir.symbols.any.owner.declarations.filterIsInstance().toSet() + + irClass.declarations.filterIsInstance().filter { it.isReal }.forEach { method -> + val overriddenMethodOfAny = method.allOverriddenFunctions.firstOrNull { + it in methodsOfAny + } + + require(overriddenMethodOfAny == null) { renderCompilerError(method) } + } + } + + override fun visitDelegatingConstructorCall(expression: IrDelegatingConstructorCall): IrExpression { + expression.transformChildrenVoid() + + builder.at(expression) + + val constructedClass = outerClasses.peek()!! + + if (!constructedClass.isObjCClass()) { + return expression + } + + constructedClass.parent.let { parent -> + if (parent is IrClass && parent.isObjCClass() && + constructedClass.isCompanion) { + + // Note: it is actually not used; getting values of such objects is handled by code generator + // in [FunctionGenerationContext.getObjectValue]. + + return expression + } + } + + val delegatingCallConstructingClass = expression.symbol.owner.constructedClass + if (!constructedClass.isExternalObjCClass() && + delegatingCallConstructingClass.isExternalObjCClass()) { + + // Calling super constructor from Kotlin Objective-C class. + + require(constructedClass.getSuperClassNotAny() == delegatingCallConstructingClass) { renderCompilerError(expression) } + require(expression.symbol.owner.objCConstructorIsDesignated()) { renderCompilerError(expression) } + require(expression.dispatchReceiver == null) { renderCompilerError(expression) } + require(expression.extensionReceiver == null) { renderCompilerError(expression) } + + val initMethod = expression.symbol.owner.getObjCInitMethod()!! + + val initMethodInfo = initMethod.getExternalObjCMethodInfo()!! + + val initCall = builder.genLoweredObjCMethodCall( + initMethodInfo, + superQualifier = delegatingCallConstructingClass.symbol, + receiver = builder.irGet(constructedClass.thisReceiver!!), + arguments = initMethod.valueParameters.map { expression.getValueArgument(it.index) }, + call = expression, + method = initMethod + ) + + val superConstructor = delegatingCallConstructingClass + .constructors.single { it.valueParameters.size == 0 }.symbol + + return builder.irBlock(expression) { + // Required for the IR to be valid, will be ignored in codegen: + +IrDelegatingConstructorCallImpl.fromSymbolDescriptor( + startOffset, + endOffset, + context.irBuiltIns.unitType, + superConstructor, + 0, + superConstructor.owner.valueParameters.size + ) + + +irCall(symbols.interopObjCObjectSuperInitCheck).apply { + extensionReceiver = irGet(constructedClass.thisReceiver!!) + putValueArgument(0, initCall) + } + } + } + + return expression + } + + private fun IrBuilderWithScope.genLoweredObjCMethodCall( + info: ObjCMethodInfo, + superQualifier: IrClassSymbol?, + receiver: IrExpression, + arguments: List, + call: IrFunctionAccessExpression, + method: IrSimpleFunction + ): IrExpression = genLoweredObjCMethodCall( + info = info, + superQualifier = superQualifier, + receiver = ObjCCallReceiver.Regular(rawPtr = getRawPtr(receiver)), + arguments = arguments, + call = call, + method = method + ) + + private fun IrBuilderWithScope.genLoweredObjCMethodCall( + info: ObjCMethodInfo, + superQualifier: IrClassSymbol?, + receiver: ObjCCallReceiver, + arguments: List, + call: IrFunctionAccessExpression, + method: IrSimpleFunction + ): IrExpression = generateWithStubs(call) { + if (method.parent !is IrClass) { + // Category-provided. + this@InteropLoweringPart1.context.llvmImports.add(method.llvmSymbolOrigin) + } + + this.generateObjCCall( + this@genLoweredObjCMethodCall, + method, + info.isStret, + info.selector, + call, + superQualifier, + receiver, + arguments + ) + } + + override fun visitConstructorCall(expression: IrConstructorCall): IrExpression { + expression.transformChildrenVoid() + + val callee = expression.symbol.owner + val initMethod = callee.getObjCInitMethod() + if (initMethod != null) { + val arguments = callee.valueParameters.map { expression.getValueArgument(it.index) } + require(expression.extensionReceiver == null) { renderCompilerError(expression) } + require(expression.dispatchReceiver == null) { renderCompilerError(expression) } + + val constructedClass = callee.constructedClass + val initMethodInfo = initMethod.getExternalObjCMethodInfo()!! + return builder.at(expression).run { + val classPtr = getObjCClass(symbols, constructedClass.symbol) + ensureObjCReferenceNotNull(callAllocAndInit(classPtr, initMethodInfo, arguments, expression, initMethod)) + } + } + + return expression + } + + private fun IrBuilderWithScope.ensureObjCReferenceNotNull(expression: IrExpression): IrExpression = + if (!expression.type.containsNull()) { + expression + } else { + irBlock(resultType = expression.type) { + val temp = irTemporary(expression) + +irIfThen( + context.irBuiltIns.unitType, + irEqeqeq(irGet(temp), irNull()), + irCall(symbols.throwNullPointerException) + ) + +irGet(temp) + } + } + + override fun visitCall(expression: IrCall): IrExpression { + expression.transformChildrenVoid() + + val callee = expression.symbol.owner + + callee.getObjCFactoryInitMethodInfo()?.let { initMethodInfo -> + val arguments = (0 until expression.valueArgumentsCount) + .map { index -> expression.getValueArgument(index) } + + return builder.at(expression).run { + val classPtr = getRawPtr(expression.extensionReceiver!!) + callAllocAndInit(classPtr, initMethodInfo, arguments, expression, callee) + } + } + + callee.getExternalObjCMethodInfo()?.let { methodInfo -> + val isInteropStubsFile = + currentFile.annotations.hasAnnotation(FqName("kotlinx.cinterop.InteropStubs")) + + // Special case: bridge from Objective-C method implementation template to Kotlin method; + // handled in CodeGeneratorVisitor.callVirtual. + val useKotlinDispatch = isInteropStubsFile && + (builder.scope.scopeOwnerSymbol.owner as? IrAnnotationContainer) + ?.hasAnnotation(FqName("kotlin.native.internal.ExportForCppRuntime")) == true + + if (!useKotlinDispatch) { + val arguments = callee.valueParameters.map { expression.getValueArgument(it.index) } + require(expression.dispatchReceiver == null || expression.extensionReceiver == null) { renderCompilerError(expression) } + require(expression.superQualifierSymbol?.owner?.isObjCMetaClass() != true) { renderCompilerError(expression) } + require(expression.superQualifierSymbol?.owner?.isInterface != true) { renderCompilerError(expression) } + + builder.at(expression) + return builder.genLoweredObjCMethodCall( + methodInfo, + superQualifier = expression.superQualifierSymbol, + receiver = expression.dispatchReceiver ?: expression.extensionReceiver!!, + arguments = arguments, + call = expression, + method = callee + ) + } + } + + return when (callee.symbol) { + symbols.interopTypeOf -> { + val typeArgument = expression.getSingleTypeArgument() + val classSymbol = typeArgument.classifierOrNull as? IrClassSymbol + + if (classSymbol == null) { + expression + } else { + val irClass = classSymbol.owner + + val companionObject = irClass.companionObject() ?: + error(irFile, expression, "native variable class ${irClass.descriptor} must have the companion object") + + builder.at(expression).irGetObject(companionObject.symbol) + } + } + else -> expression + } + } + + override fun visitProperty(declaration: IrProperty): IrStatement { + val backingField = declaration.backingField + return if (declaration.isConst && backingField?.isStatic == true && context.config.isInteropStubs) { + // Transform top-level `const val x = 42` to `val x get() = 42`. + // Generally this transformation is just an optimization to ensure that interop constants + // don't require any storage and/or initialization at program startup. + // Also it is useful due to uncertain design of top-level stored properties in Kotlin/Native. + val initializer = backingField.initializer!!.expression + declaration.backingField = null + + val getter = declaration.getter!! + val getterBody = getter.body!! as IrBlockBody + getterBody.statements.clear() + getterBody.statements += IrReturnImpl( + declaration.startOffset, + declaration.endOffset, + context.irBuiltIns.nothingType, + getter.symbol, + initializer + ) + // Note: in interop stubs const val initializer is either `IrConst` or quite simple expression, + // so it is ok to compute it every time. + + require(declaration.setter == null) { renderCompilerError(declaration) } + require(!declaration.isVar) { renderCompilerError(declaration) } + + declaration.transformChildrenVoid() + declaration + } else { + super.visitProperty(declaration) + } + } + + private fun IrBuilderWithScope.callAllocAndInit( + classPtr: IrExpression, + initMethodInfo: ObjCMethodInfo, + arguments: List, + call: IrFunctionAccessExpression, + initMethod: IrSimpleFunction + ): IrExpression = genLoweredObjCMethodCall( + initMethodInfo, + superQualifier = null, + receiver = ObjCCallReceiver.Retained(rawPtr = callAlloc(classPtr)), + arguments = arguments, + call = call, + method = initMethod + ) + + private fun IrBuilderWithScope.getRawPtr(receiver: IrExpression) = + irCall(symbols.interopObjCObjectRawValueGetter).apply { + extensionReceiver = receiver + } +} + +/** + * Lowers some interop intrinsic calls. + */ +private class InteropLoweringPart2(val context: Context) : FileLoweringPass { + override fun lower(irFile: IrFile) { + val transformer = InteropTransformer(context, irFile) + irFile.transformChildrenVoid(transformer) + + while (transformer.newTopLevelDeclarations.isNotEmpty()) { + val newTopLevelDeclarations = transformer.newTopLevelDeclarations.toList() + transformer.newTopLevelDeclarations.clear() + + // Assuming these declarations contain only new IR (i.e. existing lowered IR has not been moved there). + // TODO: make this more reliable. + val loweredNewTopLevelDeclarations = + newTopLevelDeclarations.map { it.transform(transformer, null) as IrDeclaration } + + irFile.addChildren(loweredNewTopLevelDeclarations) + } + } +} + +private class InteropTransformer(val context: Context, override val irFile: IrFile) : BaseInteropIrTransformer(context) { + + val newTopLevelDeclarations = mutableListOf() + + val interop = context.interopBuiltIns + val symbols = context.ir.symbols + + override fun addTopLevel(declaration: IrDeclaration) { + declaration.parent = irFile + newTopLevelDeclarations += declaration + } + + override fun visitClass(declaration: IrClass): IrStatement { + super.visitClass(declaration) + if (declaration.isKotlinObjCClass()) { + val uniq = mutableSetOf() // remove duplicates [KT-38234] + val imps = declaration.simpleFunctions().filter { it.isReal }.flatMap { function -> + function.overriddenSymbols.mapNotNull { + val selector = it.owner.getExternalObjCMethodInfo()?.selector + if (selector == null || selector in uniq) { + null + } else { + uniq += selector + generateWithStubs(it.owner) { + generateCFunctionAndFakeKotlinExternalFunction( + function, + it.owner, + isObjCMethod = true, + location = function + ) + } + } + } + } + declaration.addChildren(imps) + } + return declaration + } + + private fun generateCFunctionPointer(function: IrSimpleFunction, expression: IrExpression): IrExpression = + generateWithStubs { generateCFunctionPointer(function, function, expression) } + + override fun visitConstructorCall(expression: IrConstructorCall): IrExpression { + expression.transformChildrenVoid(this) + + val callee = expression.symbol.owner + val inlinedClass = callee.returnType.getInlinedClassNative() + require(inlinedClass?.descriptor != interop.cPointer) { renderCompilerError(expression) } + require(inlinedClass?.descriptor != interop.nativePointed) { renderCompilerError(expression) } + + val constructedClass = callee.constructedClass + if (!constructedClass.isObjCClass()) + return expression + + // Calls to other ObjC class constructors must be lowered. + require(constructedClass.isKotlinObjCClass()) { renderCompilerError(expression) } + return builder.at(expression).irBlock { + val rawPtr = irTemporary(irCall(symbols.interopAllocObjCObject.owner).apply { + putValueArgument(0, getObjCClass(symbols, constructedClass.symbol)) + }) + val instance = irTemporary(irCall(symbols.interopInterpretObjCPointer.owner).apply { + putValueArgument(0, irGet(rawPtr)) + }) + // Balance pointer retained by alloc: + +irCall(symbols.interopObjCRelease.owner).apply { + putValueArgument(0, irGet(rawPtr)) + } + +irCall(symbols.initInstance).apply { + putValueArgument(0, irGet(instance)) + putValueArgument(1, expression) + } + +irGet(instance) + } + } + + /** + * Handle `const val`s that come from interop libraries. + * + * We extract constant value from the backing field, and replace getter invocation with it. + */ + private fun tryGenerateInteropConstantRead(expression: IrCall): IrExpression? { + val function = expression.symbol.owner + + if (!function.descriptor.module.isFromInteropLibrary()) return null + if (!function.isGetter) return null + + val constantProperty = (function as? IrSimpleFunction) + ?.correspondingPropertySymbol + ?.owner + ?.takeIf { it.isConst } + ?: return null + + val initializer = constantProperty.backingField?.initializer?.expression + require(initializer is IrConst<*>) { renderCompilerError(expression) } + + // Avoid node duplication + return initializer.copy() + } + + override fun visitCall(expression: IrCall): IrExpression { + val intrinsicType = tryGetIntrinsicType(expression) + if (intrinsicType == IntrinsicType.OBJC_INIT_BY) { + // Need to do this separately as otherwise [expression.transformChildrenVoid(this)] would be called + // and the [IrConstructorCall] would be transformed which is not what we want. + + val argument = expression.getValueArgument(0)!! + require(argument is IrConstructorCall) { renderCompilerError(argument) } + + val constructedClass = argument.symbol.owner.constructedClass + + val extensionReceiver = expression.extensionReceiver!! + require(extensionReceiver is IrGetValue && + extensionReceiver.symbol.owner.isDispatchReceiverFor(constructedClass)) { renderCompilerError(extensionReceiver) } + + argument.transformChildrenVoid(this) + + return builder.at(expression).irBlock { + val instance = extensionReceiver.symbol.owner + +irCall(symbols.initInstance).apply { + putValueArgument(0, irGet(instance)) + putValueArgument(1, argument) + } + +irGet(instance) + } + } + + expression.transformChildrenVoid(this) + builder.at(expression) + val function = expression.symbol.owner + + if ((function as? IrSimpleFunction)?.resolveFakeOverrideMaybeAbstract()?.symbol + == symbols.interopNativePointedRawPtrGetter) { + + // Replace by the intrinsic call to be handled by code generator: + return builder.irCall(symbols.interopNativePointedGetRawPointer).apply { + extensionReceiver = expression.dispatchReceiver + } + } + + if (function.annotations.hasAnnotation(RuntimeNames.cCall)) { + context.llvmImports.add(function.llvmSymbolOrigin) + val exceptionMode = ForeignExceptionMode.byValue( + function.module.konanLibrary?.manifestProperties?.getProperty(ForeignExceptionMode.manifestKey) + ) + return generateWithStubs { generateCCall(expression, builder, isInvoke = false, exceptionMode) } + } + + val failCompilation = { msg: String -> error(irFile, expression, msg) } + tryGenerateInteropMemberAccess(expression, symbols, builder, failCompilation)?.let { return it } + + tryGenerateInteropConstantRead(expression)?.let { return it } + + if (intrinsicType != null) { + return when (intrinsicType) { + IntrinsicType.INTEROP_BITS_TO_FLOAT -> { + val argument = expression.getValueArgument(0) + if (argument is IrConst<*> && argument.kind == IrConstKind.Int) { + val floatValue = kotlinx.cinterop.bitsToFloat(argument.value as Int) + builder.irFloat(floatValue) + } else { + expression + } + } + IntrinsicType.INTEROP_BITS_TO_DOUBLE -> { + val argument = expression.getValueArgument(0) + if (argument is IrConst<*> && argument.kind == IrConstKind.Long) { + val doubleValue = kotlinx.cinterop.bitsToDouble(argument.value as Long) + builder.irDouble(doubleValue) + } else { + expression + } + } + IntrinsicType.INTEROP_STATIC_C_FUNCTION -> { + val irCallableReference = unwrapStaticFunctionArgument(expression.getValueArgument(0)!!) + + require(irCallableReference != null && irCallableReference.getArguments().isEmpty() + && irCallableReference.symbol is IrSimpleFunctionSymbol) { renderCompilerError(expression) } + + val targetSymbol = irCallableReference.symbol + val target = targetSymbol.owner + val signatureTypes = target.allParameters.map { it.type } + target.returnType + + function.typeParameters.indices.forEach { index -> + val typeArgument = expression.getTypeArgument(index)!!.toKotlinType() + val signatureType = signatureTypes[index].toKotlinType() + + require(typeArgument.constructor == signatureType.constructor && + typeArgument.isMarkedNullable == signatureType.isMarkedNullable) { renderCompilerError(expression) } + } + + generateCFunctionPointer(target as IrSimpleFunction, expression) + } + IntrinsicType.INTEROP_FUNPTR_INVOKE -> { + generateWithStubs { generateCCall(expression, builder, isInvoke = true) } + } + IntrinsicType.INTEROP_SIGN_EXTEND, IntrinsicType.INTEROP_NARROW -> { + + val integerTypePredicates = arrayOf( + IrType::isByte, IrType::isShort, IrType::isInt, IrType::isLong + ) + + val receiver = expression.extensionReceiver!! + val typeOperand = expression.getSingleTypeArgument() + + val receiverTypeIndex = integerTypePredicates.indexOfFirst { it(receiver.type) } + val typeOperandIndex = integerTypePredicates.indexOfFirst { it(typeOperand) } + + require(receiverTypeIndex >= 0) { renderCompilerError(receiver) } + require(typeOperandIndex >= 0) { renderCompilerError(expression) } + + when (intrinsicType) { + IntrinsicType.INTEROP_SIGN_EXTEND -> + require(receiverTypeIndex <= typeOperandIndex) { renderCompilerError(expression) } + IntrinsicType.INTEROP_NARROW -> + require(receiverTypeIndex >= typeOperandIndex) { renderCompilerError(expression) } + else -> error(intrinsicType) + } + + val receiverClass = symbols.integerClasses.single { + receiver.type.isSubtypeOf(it.owner.defaultType) + } + val targetClass = symbols.integerClasses.single { + typeOperand.isSubtypeOf(it.owner.defaultType) + } + + val conversionSymbol = receiverClass.functions.single { + it.owner.name == Name.identifier("to${targetClass.owner.name}") + } + + builder.irCall(conversionSymbol).apply { + dispatchReceiver = receiver + } + } + IntrinsicType.INTEROP_CONVERT -> { + val integerClasses = symbols.allIntegerClasses + val typeOperand = expression.getTypeArgument(0)!! + val receiverType = expression.symbol.owner.extensionReceiverParameter!!.type + val source = receiverType.classifierOrFail as IrClassSymbol + require(source in integerClasses) { renderCompilerError(expression) } + require(typeOperand is IrSimpleType && typeOperand.classifier in integerClasses + && !typeOperand.hasQuestionMark) { renderCompilerError(expression) } + + val target = typeOperand.classifier as IrClassSymbol + val valueToConvert = expression.extensionReceiver!! + + if (source in symbols.signedIntegerClasses && target in symbols.unsignedIntegerClasses) { + // Default Kotlin signed-to-unsigned widening integer conversions don't follow C rules. + val signedTarget = symbols.unsignedToSignedOfSameBitWidth[target]!! + val widened = builder.irConvertInteger(source, signedTarget, valueToConvert) + builder.irConvertInteger(signedTarget, target, widened) + } else { + builder.irConvertInteger(source, target, valueToConvert) + } + } + IntrinsicType.INTEROP_MEMORY_COPY -> { + TODO("So far unsupported") + } + IntrinsicType.WORKER_EXECUTE -> { + val irCallableReference = unwrapStaticFunctionArgument(expression.getValueArgument(2)!!) + + require(irCallableReference != null + && irCallableReference.getArguments().isEmpty()) { renderCompilerError(expression) } + + val targetSymbol = irCallableReference.symbol + val jobPointer = IrFunctionReferenceImpl.fromSymbolDescriptor( + builder.startOffset, builder.endOffset, + symbols.executeImpl.owner.valueParameters[3].type, + targetSymbol, + typeArgumentsCount = 0, + reflectionTarget = null) + + builder.irCall(symbols.executeImpl).apply { + putValueArgument(0, expression.dispatchReceiver) + putValueArgument(1, expression.getValueArgument(0)) + putValueArgument(2, expression.getValueArgument(1)) + putValueArgument(3, jobPointer) + } + } + else -> expression + } + } + return when (function) { + symbols.interopCPointerRawValue.owner.getter -> + // Replace by the intrinsic call to be handled by code generator: + builder.irCall(symbols.interopCPointerGetRawValue).apply { + extensionReceiver = expression.dispatchReceiver + } + else -> expression + } + } + + private fun IrBuilderWithScope.irConvertInteger( + source: IrClassSymbol, + target: IrClassSymbol, + value: IrExpression + ): IrExpression { + val conversion = symbols.integerConversions[source to target]!! + return irCall(conversion.owner).apply { + if (conversion.owner.dispatchReceiverParameter != null) { + dispatchReceiver = value + } else { + extensionReceiver = value + } + } + } + + private fun unwrapStaticFunctionArgument(argument: IrExpression): IrFunctionReference? { + if (argument is IrFunctionReference) { + return argument + } + + // Otherwise check whether it is a lambda: + + // 1. It is a container with two statements and expected origin: + + if (argument !is IrContainerExpression || argument.statements.size != 2) { + return null + } + if (argument.origin != IrStatementOrigin.LAMBDA && argument.origin != IrStatementOrigin.ANONYMOUS_FUNCTION) { + return null + } + + // 2. First statement is an empty container (created during local functions lowering): + + val firstStatement = argument.statements.first() + + if (firstStatement !is IrContainerExpression || firstStatement.statements.size != 0) { + return null + } + + // 3. Second statement is IrCallableReference: + + return argument.statements.last() as? IrFunctionReference + } + + val IrValueParameter.isDispatchReceiver: Boolean + get() = when(val parent = this.parent) { + is IrClass -> true + is IrFunction -> parent.dispatchReceiverParameter == this + else -> false + } + + private fun IrValueDeclaration.isDispatchReceiverFor(irClass: IrClass): Boolean = + this is IrValueParameter && isDispatchReceiver && type.getClass() == irClass + +} + +private fun IrCall.getSingleTypeArgument(): IrType { + val typeParameter = symbol.owner.typeParameters.single() + return getTypeArgument(typeParameter.index)!! +} + +private fun IrBuilder.irFloat(value: Float) = + IrConstImpl.float(startOffset, endOffset, context.irBuiltIns.floatType, value) + +private fun IrBuilder.irDouble(value: Double) = + IrConstImpl.double(startOffset, endOffset, context.irBuiltIns.doubleType, value) diff --git a/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/lower/KonanDefaultArgumentStubGenerator.kt b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/lower/KonanDefaultArgumentStubGenerator.kt new file mode 100644 index 00000000000..de2b529727e --- /dev/null +++ b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/lower/KonanDefaultArgumentStubGenerator.kt @@ -0,0 +1,26 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +package org.jetbrains.kotlin.backend.konan.lower + +import org.jetbrains.kotlin.backend.common.lower.DefaultArgumentStubGenerator +import org.jetbrains.kotlin.backend.konan.Context +import org.jetbrains.kotlin.ir.builders.* +import org.jetbrains.kotlin.ir.declarations.IrValueDeclaration +import org.jetbrains.kotlin.ir.declarations.IrValueParameter +import org.jetbrains.kotlin.ir.expressions.IrExpression + +internal class KonanDefaultArgumentStubGenerator(override val context: Context) + : DefaultArgumentStubGenerator(context, skipInlineMethods = false) +{ + override fun IrBlockBodyBuilder.selectArgumentOrDefault( + defaultFlag: IrExpression, + parameter: IrValueParameter, + default: IrExpression + ): IrValueDeclaration { + val value = irIfThenElse(parameter.type, irNotEquals(defaultFlag, irInt(0)), default, irGet(parameter)) + return createTmpVariable(value, nameHint = parameter.name.asString()) + } +} \ No newline at end of file diff --git a/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/lower/KonanDefaultParameterInjector.kt b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/lower/KonanDefaultParameterInjector.kt new file mode 100644 index 00000000000..d6cb01af9a7 --- /dev/null +++ b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/lower/KonanDefaultParameterInjector.kt @@ -0,0 +1,46 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +package org.jetbrains.kotlin.backend.konan.lower + +import org.jetbrains.kotlin.backend.common.lower.DefaultParameterInjector +import org.jetbrains.kotlin.backend.konan.* +import org.jetbrains.kotlin.ir.expressions.IrExpression +import org.jetbrains.kotlin.ir.expressions.impl.IrConstImpl +import org.jetbrains.kotlin.ir.types.IrType +import org.jetbrains.kotlin.ir.util.irCall + +internal class KonanDefaultParameterInjector(private val konanContext: KonanBackendContext) + : DefaultParameterInjector(konanContext, skipInline = false) { + + override fun nullConst(startOffset: Int, endOffset: Int, type: IrType): IrExpression { + val symbols = konanContext.ir.symbols + + val nullConstOfEquivalentType = when (type.computePrimitiveBinaryTypeOrNull()) { + null -> IrConstImpl.constNull(startOffset, endOffset, context.irBuiltIns.nothingNType) + PrimitiveBinaryType.BOOLEAN -> IrConstImpl.boolean(startOffset, endOffset, type, false) + PrimitiveBinaryType.BYTE -> IrConstImpl.byte(startOffset, endOffset, type, 0) + PrimitiveBinaryType.SHORT -> when (type.getInlinedClassNative()) { + context.irBuiltIns.char -> IrConstImpl.char(startOffset, endOffset, type, 0.toChar()) + else -> IrConstImpl.short(startOffset, endOffset, type, 0) + } + PrimitiveBinaryType.INT -> IrConstImpl.int(startOffset, endOffset, type, 0) + PrimitiveBinaryType.LONG -> IrConstImpl.long(startOffset, endOffset, type, 0) + PrimitiveBinaryType.FLOAT -> IrConstImpl.float(startOffset, endOffset, type, 0.0F) + PrimitiveBinaryType.DOUBLE -> IrConstImpl.double(startOffset, endOffset, type, 0.0) + PrimitiveBinaryType.POINTER -> irCall(startOffset, endOffset, symbols.getNativeNullPtr.owner, emptyList()) + PrimitiveBinaryType.VECTOR128 -> TODO() + } + + return irCall( + startOffset, + endOffset, + symbols.reinterpret.owner, + listOf(nullConstOfEquivalentType.type, type) + ).apply { + extensionReceiver = nullConstOfEquivalentType + } + } +} diff --git a/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/lower/NativeInlineFunctionResolver.kt b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/lower/NativeInlineFunctionResolver.kt new file mode 100644 index 00000000000..622a8cfe2c9 --- /dev/null +++ b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/lower/NativeInlineFunctionResolver.kt @@ -0,0 +1,55 @@ +/* + * Copyright 2010-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +package org.jetbrains.kotlin.backend.konan.lower + +import org.jetbrains.kotlin.backend.common.DeclarationTransformer +import org.jetbrains.kotlin.backend.common.lower.* +import org.jetbrains.kotlin.backend.common.lower.inline.DefaultInlineFunctionResolver +import org.jetbrains.kotlin.backend.common.lower.inline.LocalClassesExtractionFromInlineFunctionsLowering +import org.jetbrains.kotlin.backend.common.lower.inline.LocalClassesInInlineFunctionsLowering +import org.jetbrains.kotlin.backend.common.lower.inline.LocalClassesInInlineLambdasLowering +import org.jetbrains.kotlin.backend.konan.Context +import org.jetbrains.kotlin.ir.declarations.IrFunction +import org.jetbrains.kotlin.ir.symbols.IrFunctionSymbol +import org.jetbrains.kotlin.ir.util.dump + +// TODO: This is a bit hacky. Think about adopting persistent IR ideas. +internal class NativeInlineFunctionResolver(override val context: Context) : DefaultInlineFunctionResolver(context) { + override fun getFunctionDeclaration(symbol: IrFunctionSymbol): IrFunction { + val function = super.getFunctionDeclaration(symbol) + val body = function.body ?: return function + + if (function in context.specialDeclarationsFactory.loweredInlineFunctions) + return function + + context.specialDeclarationsFactory.loweredInlineFunctions.add(function) + + PreInlineLowering(context).lower(body, function) + + ArrayConstructorLowering(context).lower(body, function) + + NullableFieldsForLateinitCreationLowering(context).lowerWithLocalDeclarations(function) + NullableFieldsDeclarationLowering(context).lowerWithLocalDeclarations(function) + LateinitUsageLowering(context).lower(body, function) + + SharedVariablesLowering(context).lower(body, function) + + LocalClassesInInlineLambdasLowering(context).lower(body, function) + + if (context.llvmModuleSpecification.containsDeclaration(function)) { + // Do not extract local classes off of inline functions from cached libraries. + LocalClassesInInlineFunctionsLowering(context).lower(body, function) + LocalClassesExtractionFromInlineFunctionsLowering(context).lower(body, function) + } + + return function + } + + private fun DeclarationTransformer.lowerWithLocalDeclarations(function: IrFunction) { + if (transformFlat(function) != null) + error("Unexpected transformation of function ${function.dump()}") + } +} diff --git a/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/lower/NativeSingleAbstractMethodLowering.kt b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/lower/NativeSingleAbstractMethodLowering.kt new file mode 100644 index 00000000000..c7566a194eb --- /dev/null +++ b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/lower/NativeSingleAbstractMethodLowering.kt @@ -0,0 +1,27 @@ +/* + * Copyright 2010-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +package org.jetbrains.kotlin.backend.konan.lower + +import org.jetbrains.kotlin.backend.common.ScopeWithIr +import org.jetbrains.kotlin.backend.common.lower.SingleAbstractMethodLowering +import org.jetbrains.kotlin.backend.konan.Context +import org.jetbrains.kotlin.descriptors.DescriptorVisibilities +import org.jetbrains.kotlin.ir.expressions.IrTypeOperatorCall +import org.jetbrains.kotlin.ir.types.IrType +import org.jetbrains.kotlin.ir.types.classOrNull +import org.jetbrains.kotlin.ir.types.defaultType +import org.jetbrains.kotlin.ir.util.render + +internal class NativeSingleAbstractMethodLowering(context: Context) : SingleAbstractMethodLowering(context) { + override fun getWrapperVisibility(expression: IrTypeOperatorCall, scopes: List) = + DescriptorVisibilities.PRIVATE + + override fun getSuperTypeForWrapper(typeOperand: IrType): IrType { + return typeOperand.classOrNull?.defaultType ?: error("Unsupported SAM conversion: ${typeOperand.render()}") + } + + override val IrType.needEqualsHashCodeMethods get() = true +} \ No newline at end of file diff --git a/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/lower/NativeSuspendFunctionLowering.kt b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/lower/NativeSuspendFunctionLowering.kt new file mode 100644 index 00000000000..0e352602ff5 --- /dev/null +++ b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/lower/NativeSuspendFunctionLowering.kt @@ -0,0 +1,563 @@ +package org.jetbrains.kotlin.backend.konan.lower + +import org.jetbrains.kotlin.backend.common.descriptors.synthesizedName +import org.jetbrains.kotlin.backend.common.ir.isSuspend +import org.jetbrains.kotlin.backend.common.ir.simpleFunctions +import org.jetbrains.kotlin.backend.common.lower.* +import org.jetbrains.kotlin.backend.konan.Context +import org.jetbrains.kotlin.descriptors.Modality +import org.jetbrains.kotlin.descriptors.DescriptorVisibilities +import org.jetbrains.kotlin.ir.IrElement +import org.jetbrains.kotlin.ir.IrStatement +import org.jetbrains.kotlin.ir.builders.* +import org.jetbrains.kotlin.ir.builders.irCall +import org.jetbrains.kotlin.ir.declarations.* +import org.jetbrains.kotlin.ir.declarations.impl.IrFunctionImpl +import org.jetbrains.kotlin.ir.declarations.impl.IrVariableImpl +import org.jetbrains.kotlin.ir.descriptors.WrappedSimpleFunctionDescriptor +import org.jetbrains.kotlin.ir.descriptors.WrappedVariableDescriptor +import org.jetbrains.kotlin.ir.expressions.* +import org.jetbrains.kotlin.ir.expressions.impl.IrGetValueImpl +import org.jetbrains.kotlin.ir.expressions.impl.IrSetValueImpl +import org.jetbrains.kotlin.ir.expressions.impl.IrSuspendableExpressionImpl +import org.jetbrains.kotlin.ir.expressions.impl.IrSuspensionPointImpl +import org.jetbrains.kotlin.ir.symbols.IrClassSymbol +import org.jetbrains.kotlin.ir.symbols.IrVariableSymbol +import org.jetbrains.kotlin.ir.symbols.impl.IrSimpleFunctionSymbolImpl +import org.jetbrains.kotlin.ir.symbols.impl.IrVariableSymbolImpl +import org.jetbrains.kotlin.ir.types.IrType +import org.jetbrains.kotlin.ir.types.isUnit +import org.jetbrains.kotlin.ir.types.makeNotNull +import org.jetbrains.kotlin.ir.util.* +import org.jetbrains.kotlin.ir.visitors.* +import org.jetbrains.kotlin.name.Name + +internal class NativeSuspendFunctionsLowering(ctx: Context): AbstractSuspendFunctionsLowering(ctx) { + private val symbols = context.ir.symbols + + override val stateMachineMethodName = Name.identifier("invokeSuspend") + + override fun getCoroutineBaseClass(function: IrFunction): IrClassSymbol = + (if (function.isRestrictedSuspendFunction(context.irBuiltIns.languageVersionSettings)) { + symbols.restrictedContinuationImpl + } else { + symbols.continuationImpl + }) + + override fun nameForCoroutineClass(function: IrFunction) = + "${function.name}COROUTINE\$${context.coroutineCount++}".synthesizedName + + override fun initializeStateMachine(coroutineConstructors: List, coroutineClassThis: IrValueDeclaration) { + // Nothing to do: it's redundant to initialize the "label" field with null + // since all freshly allocated objects are zeroed out. + } + + override fun IrBlockBodyBuilder.generateCoroutineStart(invokeSuspendFunction: IrFunction, receiver: IrExpression) { + +irReturn( + irCall(invokeSuspendFunction).apply { + dispatchReceiver = receiver + putValueArgument(0, irSuccess(irGetObject(symbols.unit))) + } + ) + } + + override fun buildStateMachine(stateMachineFunction: IrFunction, + transformingFunction: IrFunction, + argumentToPropertiesMap: Map) { + val originalBody = transformingFunction.body!! + val resultArgument = stateMachineFunction.valueParameters.single() + + val coroutineClass = stateMachineFunction.parentAsClass + + val labelField = coroutineClass.addField(Name.identifier("label"), symbols.nativePtrType, true) + + val startOffset = transformingFunction.startOffset + val endOffset = transformingFunction.endOffset + + val irBuilder = context.createIrBuilder(stateMachineFunction.symbol, startOffset, endOffset) + stateMachineFunction.body = irBuilder.irBlockBody(startOffset, endOffset) { + + val suspendResult = irVar("suspendResult".synthesizedName, context.irBuiltIns.anyNType, true) + + // Extract all suspend calls to temporaries in order to make correct jumps to them. + originalBody.transformChildrenVoid(ExpressionSlicer(labelField.type, transformingFunction, saveState, restoreState, suspendResult, resultArgument)) + + val liveLocals = computeLivenessAtSuspensionPoints(originalBody) + + val immutableLiveLocals = liveLocals.values.flatten().filterNot { it.isVar }.toSet() + val localsMap = immutableLiveLocals.associate { it to irVar(it.name, it.type, true) } + + if (localsMap.isNotEmpty()) + transformVariables(originalBody, localsMap) // Make variables mutable in order to save/restore them. + + val localToPropertyMap = mutableMapOf() + // TODO: optimize by using the same property for different locals. + liveLocals.values.forEach { scope -> + scope.forEach { + localToPropertyMap.getOrPut(it.symbol) { + coroutineClass.addField(it.name, it.type, true) + } + } + } + + originalBody.transformChildrenVoid(object : IrElementTransformerVoid() { + + private val thisReceiver = stateMachineFunction.dispatchReceiverParameter!! + + // Replace returns to refer to the new function. + override fun visitReturn(expression: IrReturn): IrExpression { + expression.transformChildrenVoid(this) + + return if (expression.returnTargetSymbol != transformingFunction.symbol) + expression + else + irReturn(expression.value) + } + + // Replace function arguments loading with properties reading. + override fun visitGetValue(expression: IrGetValue): IrExpression { + expression.transformChildrenVoid(this) + + val capturedValue = argumentToPropertiesMap[expression.symbol.owner] + ?: return expression + return irGetField(irGet(thisReceiver), capturedValue) + } + + override fun visitSetValue(expression: IrSetValue): IrExpression { + expression.transformChildrenVoid(this) + val capturedValue = argumentToPropertiesMap[expression.symbol.owner] + ?: return expression + return irSetField(irGet(thisReceiver), capturedValue, expression.value) + } + + // Save/restore state at suspension points. + override fun visitExpression(expression: IrExpression): IrExpression { + expression.transformChildrenVoid(this) + + val suspensionPoint = expression as? IrSuspensionPoint + ?: return expression + + suspensionPoint.transformChildrenVoid(object : IrElementTransformerVoid() { + override fun visitCall(expression: IrCall): IrExpression { + expression.transformChildrenVoid(this) + + when (expression.symbol) { + saveState.symbol -> { + val scope = liveLocals[suspensionPoint]!! + return irBlock(expression) { + scope.forEach { + val variable = localsMap[it] ?: it + +irSetField(irGet(thisReceiver), localToPropertyMap[it.symbol]!!, irGet(variable)) + } + +irSetField( + irGet(thisReceiver), + labelField, + irGet(suspensionPoint.suspensionPointIdParameter) + ) + } + } + restoreState.symbol -> { + val scope = liveLocals[suspensionPoint]!! + return irBlock(expression) { + scope.forEach { + +irSetVar(localsMap[it] + ?: it, irGetField(irGet(thisReceiver), localToPropertyMap[it.symbol]!!)) + } + } + } + } + return expression + } + }) + + return suspensionPoint + } + }) + originalBody.setDeclarationsParent(stateMachineFunction) + val statements = (originalBody as IrBlockBody).statements + +suspendResult + +IrSuspendableExpressionImpl( + startOffset, endOffset, + context.irBuiltIns.unitType, + suspensionPointId = irGetField(irGet(stateMachineFunction.dispatchReceiverParameter!!), labelField), + result = irBlock(startOffset, endOffset) { + +irThrowIfNotNull(irExceptionOrNull(irGet(resultArgument))) // Coroutine might start with an exception. + statements.forEach { +it } + }) + if (transformingFunction.returnType.isUnit()) + +irReturn(irGetObject(symbols.unit)) // Insert explicit return for Unit functions. + } + } + + private var tempIndex = 0 + private var suspensionPointIdIndex = 0 + + private fun transformVariables(element: IrElement, variablesMap: Map) { + element.transformChildrenVoid(object: IrElementTransformerVoid() { + + override fun visitGetValue(expression: IrGetValue): IrExpression { + expression.transformChildrenVoid(this) + + val newVariable = variablesMap[expression.symbol.owner] + ?: return expression + + return IrGetValueImpl( + startOffset = expression.startOffset, + endOffset = expression.endOffset, + type = newVariable.type, + symbol = newVariable.symbol, + origin = expression.origin) + } + + override fun visitSetValue(expression: IrSetValue): IrExpression { + expression.transformChildrenVoid(this) + + val newVariable = variablesMap[expression.symbol.owner] + ?: return expression + + return IrSetValueImpl( + startOffset = expression.startOffset, + endOffset = expression.endOffset, + type = context.irBuiltIns.unitType, + symbol = newVariable.symbol, + value = expression.value, + origin = expression.origin) + } + + override fun visitVariable(declaration: IrVariable): IrStatement { + declaration.transformChildrenVoid(this) + + val newVariable = variablesMap[declaration] + ?: return declaration + + newVariable.initializer = declaration.initializer + + return newVariable + } + }) + } + + private fun computeLivenessAtSuspensionPoints(body: IrBody): Map> { + // TODO: data flow analysis. + // Just save all visible for now. + val result = mutableMapOf>() + body.acceptChildrenVoid(object: VariablesScopeTracker() { + + override fun visitExpression(expression: IrExpression) { + val suspensionPoint = expression as? IrSuspensionPoint + if (suspensionPoint == null) { + super.visitExpression(expression) + return + } + + suspensionPoint.result.acceptChildrenVoid(this) + suspensionPoint.resumeResult.acceptChildrenVoid(this) + + val visibleVariables = mutableListOf() + scopeStack.forEach { visibleVariables += it } + result[suspensionPoint] = visibleVariables + } + }) + + return result + } + + private inner class ExpressionSlicer(val suspensionPointIdType: IrType, val irFunction: IrFunction, + val saveState: IrFunction, val restoreState: IrFunction, + val suspendResult: IrVariable, val resultArgument: IrValueParameter): IrElementTransformerVoid() { + // TODO: optimize - it has square complexity. + + override fun visitSetField(expression: IrSetField): IrExpression { + expression.transformChildrenVoid(this) + + return sliceExpression(expression) + } + + override fun visitMemberAccess(expression: IrMemberAccessExpression<*>): IrExpression { + expression.transformChildrenVoid(this) + + return sliceExpression(expression) + } + + private fun sliceExpression(expression: IrExpression): IrExpression { + val irBuilder = context.createIrBuilder(irFunction.symbol, expression.startOffset, expression.endOffset) + irBuilder.run { + val children = when (expression) { + is IrSetField -> listOf(expression.receiver, expression.value) + is IrMemberAccessExpression<*> -> ( + listOf(expression.dispatchReceiver, expression.extensionReceiver) + + (0 until expression.valueArgumentsCount).map { expression.getValueArgument(it) } + ) + else -> throw Error("Unexpected expression: $expression") + } + + val numberOfChildren = children.size + + val hasSuspendCallInTail = BooleanArray(numberOfChildren + 1) + for (i in numberOfChildren - 1 downTo 0) + hasSuspendCallInTail[i] = hasSuspendCallInTail[i + 1] || children[i].let { it != null && it.hasSuspendCalls() } + + val newChildren = arrayOfNulls(numberOfChildren) + val tempStatements = mutableListOf() + var first = true + for ((index, child) in children.withIndex()) { + if (child == null) continue + val transformedChild = + if (!child.isSpecialBlock()) + child + else { + val statements = (child as IrBlock).statements + tempStatements += statements.take(statements.size - 1) + statements.last() as IrExpression + } + if (first && !hasSuspendCallInTail[index + 1]) { + // Don't extract suspend call to a temporary if it is the first argument and is the only suspend call. + newChildren[index] = transformedChild + first = false + continue + } + first = false + if (transformedChild.isPure() || !hasSuspendCallInTail[index]) + newChildren[index] = transformedChild + else { + // Save to temporary in order to save execution order. + val tmp = irVar(transformedChild) + + tempStatements += tmp + newChildren[index] = irGet(tmp) + } + } + + var calledSaveState = false + var suspendCall: IrExpression? = null + when { + expression.isReturnIfSuspendedCall -> { + calledSaveState = true + val firstArgument = newChildren[2]!! + newChildren[2] = irBlock(firstArgument) { + +irCall(saveState) + +firstArgument + } + suspendCall = newChildren[2] + } + expression.isSuspendCall -> { + val lastChildIndex = newChildren.indexOfLast { it != null } + if (lastChildIndex != -1) { + // Save state as late as possible. + val lastChild = newChildren[lastChildIndex]!! + calledSaveState = true + newChildren[lastChildIndex] = + irBlock(lastChild) { + if (lastChild.isPure()) { + +irCall(saveState) + +lastChild + } else { + val tmp = irVar(lastChild) + +tmp + +irCall(saveState) + +irGet(tmp) + } + } + } + suspendCall = expression + } + } + + when (expression) { + is IrSetField -> { + expression.receiver = newChildren[0] + expression.value = newChildren[1]!! + } + is IrMemberAccessExpression<*> -> { + expression.dispatchReceiver = newChildren[0] + expression.extensionReceiver = newChildren[1] + newChildren.drop(2).forEachIndexed { index, newChild -> + expression.putValueArgument(index, newChild) + } + } + } + + if (suspendCall == null) + return irWrap(expression, tempStatements) + + val suspensionPoint = IrSuspensionPointImpl( + startOffset = startOffset, + endOffset = endOffset, + type = context.irBuiltIns.anyNType, + suspensionPointIdParameter = irVar( + "suspensionPointId${suspensionPointIdIndex++}".synthesizedName, + suspensionPointIdType + ), + result = irBlock(startOffset, endOffset) { + if (!calledSaveState) + +irCall(saveState) + +irSet(suspendResult.symbol, suspendCall) + +irReturnIfSuspended(suspendResult) + +irGet(suspendResult) + }, + resumeResult = irBlock(startOffset, endOffset) { + +irCall(restoreState) + +irGetOrThrow(irGet(resultArgument)) + }) + val expressionResult = when { + suspendCall.type.isUnit() -> irImplicitCoercionToUnit(suspensionPoint) + else -> irAs(suspensionPoint, suspendCall.type) + } + return irBlock(expression) { + tempStatements.forEach { +it } + +expressionResult + } + } + + } + } + + private fun IrBuilderWithScope.irWrap(expression: IrExpression, tempStatements: List) + = if (tempStatements.isEmpty()) + expression + else irBlock(expression, STATEMENT_ORIGIN_COROUTINE_IMPL) { + tempStatements.forEach { +it } + +expression + } + + + private fun IrBuilderWithScope.irThrowIfNotNull(exception: IrExpression) = irLetS(exception) { + irThrowIfNotNull(it.owner) + } + + fun IrBuilderWithScope.irThrowIfNotNull(exception: IrValueDeclaration) = + irIfThen(irNot(irEqeqeq(irGet(exception), irNull())), + irThrow(irImplicitCast(irGet(exception), exception.type.makeNotNull()))) + + private val IrExpression.isSuspendCall: Boolean + get() = this is IrCall && this.isSuspend + + private fun IrElement.isSpecialBlock() + = this is IrBlock && this.origin == STATEMENT_ORIGIN_COROUTINE_IMPL + + private fun IrElement.hasSuspendCalls(): Boolean { + var hasSuspendCalls = false + acceptVoid(object : IrElementVisitorVoid { + override fun visitElement(element: IrElement) { + element.acceptChildrenVoid(this) + } + + override fun visitCall(expression: IrCall) { + expression.acceptChildrenVoid(this) + hasSuspendCalls = hasSuspendCalls || expression.isSuspendCall + } + + override fun visitExpression(expression: IrExpression) { + expression.acceptChildrenVoid(this) + hasSuspendCalls = hasSuspendCalls || expression is IrSuspensionPointImpl + } + }) + + return hasSuspendCalls + } + + private val IrExpression.isReturnIfSuspendedCall: Boolean + get() = this is IrCall && isReturnIfSuspendedCall() + + private fun IrBuilderWithScope.irVar(initializer: IrExpression) = + irVar("tmp${tempIndex++}".synthesizedName, initializer.type, false, initializer) + + + private fun IrBuilderWithScope.irReturnIfSuspended(value: IrValueDeclaration) = + irIfThen(irEqeqeq(irGet(value), irCall(symbols.coroutineSuspendedGetter)), + irReturn(irGet(value))) + + private fun IrExpression.isPure(): Boolean { + return when (this) { + is IrConst<*> -> true + is IrCall -> false // TODO: skip builtin operators. + is IrTypeOperatorCall -> this.argument.isPure() && this.operator != IrTypeOperator.CAST + is IrGetValue -> !this.symbol.owner.let { it is IrVariable && it.isVar } + else -> false + } + } + + // These are marker functions to split up the lowering on two parts. + private val saveState = WrappedSimpleFunctionDescriptor().let { + IrFunctionImpl( + SYNTHETIC_OFFSET, SYNTHETIC_OFFSET, + IrDeclarationOrigin.DEFINED, + IrSimpleFunctionSymbolImpl(it), + "saveState".synthesizedName, + DescriptorVisibilities.PRIVATE, + Modality.ABSTRACT, + context.irBuiltIns.unitType, + isInline = false, + isExternal = false, + isTailrec = false, + isSuspend = false, + isExpect = false, + isFakeOverride = false, + isOperator = false, + isInfix = false + ).apply { + it.bind(this) + } + } + + private val restoreState = WrappedSimpleFunctionDescriptor().let { + IrFunctionImpl( + SYNTHETIC_OFFSET, SYNTHETIC_OFFSET, + IrDeclarationOrigin.DEFINED, + IrSimpleFunctionSymbolImpl(it), + "restoreState".synthesizedName, + DescriptorVisibilities.PRIVATE, + Modality.ABSTRACT, + context.irBuiltIns.unitType, + isInline = false, + isExternal = false, + isTailrec = false, + isSuspend = false, + isExpect = false, + isFakeOverride = false, + isOperator = false, + isInfix = false + ).apply { + it.bind(this) + } + } + + private fun IrBuilderWithScope.irVar(name: Name, type: IrType, + isMutable: Boolean = false, + initializer: IrExpression? = null) = WrappedVariableDescriptor().let { + IrVariableImpl( + startOffset, endOffset, + DECLARATION_ORIGIN_COROUTINE_IMPL, + IrVariableSymbolImpl(it), + name, + type, + isMutable, + isConst = false, + isLateinit = false + ).apply { + it.bind(this) + this.initializer = initializer + this.parent = this@irVar.parent + } + } + + private fun IrBuilderWithScope.irGetOrThrow(result: IrExpression): IrExpression = + irCall(symbols.kotlinResultGetOrThrow.owner).apply { + extensionReceiver = result + } // TODO: consider inlining getOrThrow function body here. + + private fun IrBuilderWithScope.irExceptionOrNull(result: IrExpression): IrExpression { + val resultClass = symbols.kotlinResult.owner + val exceptionOrNull = resultClass.simpleFunctions().single { it.name.asString() == "exceptionOrNull" } + return irCall(exceptionOrNull).apply { + dispatchReceiver = result + } + } + + fun IrBlockBodyBuilder.irSuccess(value: IrExpression): IrMemberAccessExpression<*> { + val createResult = symbols.kotlinResult.owner.constructors.single { it.isPrimary } + return irCall(createResult).apply { + putValueArgument(0, value) + } + } +} diff --git a/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/lower/PostInlineLowering.kt b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/lower/PostInlineLowering.kt new file mode 100644 index 00000000000..c20174f7938 --- /dev/null +++ b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/lower/PostInlineLowering.kt @@ -0,0 +1,95 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +package org.jetbrains.kotlin.backend.konan.lower + +import org.jetbrains.kotlin.backend.common.FileLoweringPass +import org.jetbrains.kotlin.backend.common.ir.Symbols +import org.jetbrains.kotlin.backend.common.lower.IrBuildingTransformer +import org.jetbrains.kotlin.backend.common.lower.at +import org.jetbrains.kotlin.backend.konan.Context +import org.jetbrains.kotlin.backend.konan.renderCompilerError +import org.jetbrains.kotlin.ir.declarations.IrFile +import org.jetbrains.kotlin.ir.expressions.* +import org.jetbrains.kotlin.ir.expressions.impl.IrConstImpl +import org.jetbrains.kotlin.ir.symbols.IrClassSymbol +import org.jetbrains.kotlin.ir.util.irCall +import org.jetbrains.kotlin.ir.visitors.transformChildrenVoid + +/** + * This pass runs after inlining and performs the following additional transformations over some operations: + * - Convert immutableBlobOf() arguments to special IrConst. + * - Convert `obj::class` and `Class::class` to calls. + */ +internal class PostInlineLowering(val context: Context) : FileLoweringPass { + + private val symbols get() = context.ir.symbols + + override fun lower(irFile: IrFile) { + irFile.transformChildrenVoid(object : IrBuildingTransformer(context) { + + override fun visitClassReference(expression: IrClassReference): IrExpression { + expression.transformChildrenVoid() + + return builder.at(expression).run { + (expression.symbol as? IrClassSymbol)?.let { irKClass(this@PostInlineLowering.context, it) } + ?: + // E.g. for `T::class` in a body of an inline function itself. + irCall(symbols.throwNullPointerException.owner) + } + } + + override fun visitGetClass(expression: IrGetClass): IrExpression { + expression.transformChildrenVoid() + + return builder.at(expression).run { + irCall(symbols.kClassImplConstructor, listOf(expression.argument.type)).apply { + val typeInfo = irCall(symbols.getObjectTypeInfo).apply { + putValueArgument(0, expression.argument) + } + + putValueArgument(0, typeInfo) + } + } + } + + override fun visitCall(expression: IrCall): IrExpression { + expression.transformChildrenVoid(this) + + // Function inlining is changing function symbol at callsite + // and unbound symbol replacement is happening later. + // So we compare descriptors for now. + if (expression.symbol == symbols.immutableBlobOf) { + // Convert arguments of the binary blob to special IrConst structure, so that + // vararg lowering will not affect it. + val args = expression.getValueArgument(0) as? IrVararg + ?: error("varargs shall not be lowered yet") + val builder = StringBuilder() + args.elements.forEach { + require(it is IrConst<*>) { renderCompilerError(irFile, it, "expected const") } + val value = (it as? IrConst<*>)?.value + require(value is Short && value >= 0 && value <= 0xff) { + renderCompilerError(irFile, it, "incorrect value for binary data: $value") + } + // Luckily, all values in range 0x00 .. 0xff represent valid UTF-16 symbols, + // block 0 (Basic Latin) and block 1 (Latin-1 Supplement) in + // Basic Multilingual Plane, so we could just append data "as is". + builder.append(value.toChar()) + } + expression.putValueArgument(0, IrConstImpl( + expression.startOffset, expression.endOffset, + context.irBuiltIns.stringType, + IrConstKind.String, builder.toString())) + } else if (Symbols.isTypeOfIntrinsic(expression.symbol)) { + return with (KTypeGenerator(context, irFile, expression, needExactTypeParameters = true)) { + builder.at(expression).irKType(expression.getTypeArgument(0)!!, leaveReifiedForLater = false) + } + } + + return expression + } + }) + } +} \ No newline at end of file diff --git a/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/lower/PreInlineLowering.kt b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/lower/PreInlineLowering.kt new file mode 100644 index 00000000000..2e0b6127443 --- /dev/null +++ b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/lower/PreInlineLowering.kt @@ -0,0 +1,65 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +package org.jetbrains.kotlin.backend.konan.lower + +import org.jetbrains.kotlin.backend.common.BodyLoweringPass +import org.jetbrains.kotlin.backend.common.ir.Symbols +import org.jetbrains.kotlin.backend.common.lower.at +import org.jetbrains.kotlin.backend.common.lower.createIrBuilder +import org.jetbrains.kotlin.backend.konan.Context +import org.jetbrains.kotlin.backend.konan.KonanConfigKeys +import org.jetbrains.kotlin.ir.builders.IrBuilderWithScope +import org.jetbrains.kotlin.ir.declarations.IrDeclaration +import org.jetbrains.kotlin.ir.declarations.IrDeclarationBase +import org.jetbrains.kotlin.ir.declarations.IrSymbolOwner +import org.jetbrains.kotlin.ir.expressions.IrBody +import org.jetbrains.kotlin.ir.expressions.IrCall +import org.jetbrains.kotlin.ir.expressions.IrExpression +import org.jetbrains.kotlin.ir.expressions.impl.IrCompositeImpl +import org.jetbrains.kotlin.ir.types.isUnit +import org.jetbrains.kotlin.ir.util.file +import org.jetbrains.kotlin.ir.visitors.IrElementTransformer + +/** + * This pass runs before inlining and performs the following additional transformations over some operations: + * - Assertion call removal. + * - First phase of typeOf intrinsic lowering. + */ +internal class PreInlineLowering(val context: Context) : BodyLoweringPass { + + private val symbols get() = context.ir.symbols + + private val asserts = symbols.asserts + private val enableAssertions = context.config.configuration.getBoolean(KonanConfigKeys.ENABLE_ASSERTIONS) + + override fun lower(irBody: IrBody, container: IrDeclaration) { + irBody.transformChildren(object : IrElementTransformer { + override fun visitDeclaration(declaration: IrDeclarationBase, data: IrBuilderWithScope) = + super.visitDeclaration(declaration, + data = (declaration as? IrSymbolOwner)?.let { context.createIrBuilder(it.symbol, it.startOffset, it.endOffset) } + ?: data + ) + + override fun visitCall(expression: IrCall, data: IrBuilderWithScope): IrExpression { + expression.transformChildren(this, data) + + return when { + !enableAssertions && expression.symbol in asserts -> { + // Replace assert() call with an empty composite if assertions are not enabled. + require(expression.type.isUnit()) + IrCompositeImpl(expression.startOffset, expression.endOffset, expression.type) + } + Symbols.isTypeOfIntrinsic(expression.symbol) -> { + with (KTypeGenerator(context, container.file, expression, needExactTypeParameters = true)) { + data.at(expression).irKType(expression.getTypeArgument(0)!!, leaveReifiedForLater = true) + } + } + else -> expression + } + } + }, data = context.createIrBuilder((container as IrSymbolOwner).symbol, irBody.startOffset, irBody.endOffset)) + } +} \ No newline at end of file diff --git a/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/lower/RedundantCoercionsCleaner.kt b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/lower/RedundantCoercionsCleaner.kt new file mode 100644 index 00000000000..ddbc37926d0 --- /dev/null +++ b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/lower/RedundantCoercionsCleaner.kt @@ -0,0 +1,259 @@ +/* + * Copyright 2010-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +package org.jetbrains.kotlin.backend.konan.lower + +import org.jetbrains.kotlin.backend.common.FileLoweringPass +import org.jetbrains.kotlin.backend.konan.Context +import org.jetbrains.kotlin.backend.konan.DECLARATION_ORIGIN_INLINE_CLASS_SPECIAL_FUNCTION +import org.jetbrains.kotlin.backend.konan.getInlinedClassNative +import org.jetbrains.kotlin.backend.konan.ir.isBoxOrUnboxCall +import org.jetbrains.kotlin.ir.IrElement +import org.jetbrains.kotlin.ir.declarations.IrClass +import org.jetbrains.kotlin.ir.declarations.IrFile +import org.jetbrains.kotlin.ir.declarations.IrFunction +import org.jetbrains.kotlin.ir.expressions.* +import org.jetbrains.kotlin.ir.expressions.impl.* +import org.jetbrains.kotlin.ir.symbols.impl.IrReturnableBlockSymbolImpl +import org.jetbrains.kotlin.ir.types.classifierOrFail +import org.jetbrains.kotlin.ir.util.dump +import org.jetbrains.kotlin.ir.util.getArguments +import org.jetbrains.kotlin.ir.visitors.IrElementTransformerVoid +import org.jetbrains.kotlin.ir.visitors.IrElementVisitorVoid +import org.jetbrains.kotlin.ir.visitors.acceptChildrenVoid +import org.jetbrains.kotlin.ir.visitors.transformChildrenVoid + +internal class RedundantCoercionsCleaner(val context: Context) : FileLoweringPass, IrElementTransformerVoid() { + + private class PossiblyFoldedExpression(val expression: IrExpression, val folded: Boolean) { + fun getFullExpression(coercion: IrCall, cast: IrTypeOperatorCall?): IrExpression { + if (folded) return expression + require (coercion.dispatchReceiver == null && coercion.extensionReceiver == null) { + "Expected either or function without any receivers" + } + val castedExpression = + if (cast == null) + expression + else with (cast) { + IrTypeOperatorCallImpl(startOffset, endOffset, type, operator, + typeOperand, expression) + } + with (coercion) { + return IrCallImpl(startOffset, endOffset, type, symbol, typeArgumentsCount, symbol.owner.valueParameters.size, origin).apply { + putValueArgument(0, castedExpression) + } + } + } + } + + private val returnableBlockValues = mutableMapOf>() + + private fun computeReturnableBlockValues(irFile: IrFile) { + irFile.acceptChildrenVoid(object: IrElementVisitorVoid { + override fun visitElement(element: IrElement) { + element.acceptChildrenVoid(this) + } + + override fun visitContainerExpression(expression: IrContainerExpression) { + if (expression is IrReturnableBlock) + returnableBlockValues[expression] = mutableListOf() + + super.visitContainerExpression(expression) + } + + override fun visitReturn(expression: IrReturn) { + val returnableBlock = expression.returnTargetSymbol.owner as? IrReturnableBlock + if (returnableBlock != null) + returnableBlockValues[returnableBlock]!!.add(expression.value) + + super.visitReturn(expression) + } + }) + } + + override fun lower(irFile: IrFile) { + computeReturnableBlockValues(irFile) + irFile.transformChildrenVoid(this) + } + + override fun visitCall(expression: IrCall): IrExpression { + if (!expression.isBoxOrUnboxCall()) + return super.visitCall(expression) + + val argument = expression.getArguments().single().second + val foldedArgument = fold( + expression = argument, + coercion = expression, + cast = null, + transformRecursively = true) + return foldedArgument.getFullExpression(expression, null) + } + + private fun IrFunction.getCoercedClass(): IrClass { + if (name.asString().endsWith("-box>")) + return valueParameters[0].type.classifierOrFail.owner as IrClass + if (name.asString().endsWith("-unbox>")) + return returnType.classifierOrFail.owner as IrClass + error("Unexpected coercion: ${this.dump()}") + } + + private fun IrExpression.unwrapImplicitCasts(): IrExpression { + var expression = this + while (expression is IrTypeOperatorCall && expression.operator == IrTypeOperator.IMPLICIT_CAST) + expression = expression.argument + return expression + } + + /** + * TODO: JVM inliner crashed on attempt inline this function from transform.kt with: + * j.l.IllegalStateException: Couldn't obtain compiled function body for + * public inline fun kotlin.collections.MutableList.transform... + */ + private inline fun MutableList.transform(transformation: (T) -> IrElement) { + forEachIndexed { i, item -> + set(i, transformation(item) as T) + } + } + + private fun fold(expression: IrExpression, coercion: IrCall, + cast: IrTypeOperatorCall?, transformRecursively: Boolean): PossiblyFoldedExpression { + + val transformer = this + + fun IrExpression.transformIfAsked() = + if (transformRecursively) this.transform(transformer, data = null) else this + + fun IrElement.transformIfAsked() = + if (transformRecursively) this.transform(transformer, data = null) else this + + val coercionDeclaringClass = coercion.symbol.owner.getCoercedClass() + expression.unwrapImplicitCasts().let { + if (it.isBoxOrUnboxCall()) { + val result = + if (coercionDeclaringClass == (it as IrCall).symbol.owner.getCoercedClass()) + it.getArguments().single().second + else expression + + return PossiblyFoldedExpression(result.transformIfAsked(), result != expression) + } + } + return when (expression) { + is IrReturnableBlock -> { + val foldedReturnableBlockValues = returnableBlockValues[expression]!!.associate { + it to fold(it, coercion, cast, false) + } + val someoneFolded = foldedReturnableBlockValues.any { it.value.folded } + val transformedReturnableBlock = + if (!someoneFolded) + expression + else { + val oldSymbol = expression.symbol + val newSymbol = IrReturnableBlockSymbolImpl(expression.descriptor) + val transformedReturnableBlock = with(expression) { + IrReturnableBlockImpl( + startOffset = startOffset, + endOffset = endOffset, + type = coercion.type, + symbol = newSymbol, + origin = origin, + statements = statements, + inlineFunctionSymbol = inlineFunctionSymbol) + } + transformedReturnableBlock.transformChildrenVoid(object: IrElementTransformerVoid() { + override fun visitExpression(expression: IrExpression): IrExpression { + foldedReturnableBlockValues[expression]?.let { + return it.getFullExpression(coercion, cast) + } + return super.visitExpression(expression) + } + + override fun visitReturn(expression: IrReturn): IrExpression { + expression.transformChildrenVoid(this) + return if (expression.returnTargetSymbol != oldSymbol) + expression + else with(expression) { + IrReturnImpl( + startOffset = startOffset, + endOffset = endOffset, + type = context.irBuiltIns.nothingType, + returnTargetSymbol = newSymbol, + value = value) + } + } + }) + transformedReturnableBlock + } + if (transformRecursively) + transformedReturnableBlock.transformChildrenVoid(this) + PossiblyFoldedExpression(transformedReturnableBlock, someoneFolded) + } + + is IrBlock -> { + val statements = expression.statements + if (statements.isEmpty()) + PossiblyFoldedExpression(expression, false) + else { + val lastStatement = statements.last() as IrExpression + val foldedLastStatement = fold(lastStatement, coercion, cast, transformRecursively) + statements.transform { + if (it == lastStatement) + foldedLastStatement.expression + else + it.transformIfAsked() + } + val transformedBlock = + if (!foldedLastStatement.folded) + expression + else with(expression) { + IrBlockImpl( + startOffset = startOffset, + endOffset = endOffset, + type = coercion.type, + origin = origin, + statements = statements) + } + PossiblyFoldedExpression(transformedBlock, foldedLastStatement.folded) + } + } + + is IrWhen -> { + val foldedBranches = expression.branches.map { fold(it.result, coercion, cast, transformRecursively) } + val someoneFolded = foldedBranches.any { it.folded } + val transformedWhen = with(expression) { + IrWhenImpl(startOffset, endOffset, if (someoneFolded) coercion.type else type, origin, + branches.asSequence().withIndex().map { (index, branch) -> + IrBranchImpl( + startOffset = branch.startOffset, + endOffset = branch.endOffset, + condition = branch.condition.transformIfAsked(), + result = if (someoneFolded) + foldedBranches[index].getFullExpression(coercion, cast) + else foldedBranches[index].expression) + }.toList()) + } + return PossiblyFoldedExpression(transformedWhen, someoneFolded) + } + + is IrTypeOperatorCall -> + if (expression.operator != IrTypeOperator.CAST + && expression.operator != IrTypeOperator.IMPLICIT_CAST + && expression.operator != IrTypeOperator.SAFE_CAST) + PossiblyFoldedExpression(expression.transformIfAsked(), false) + else { + if (expression.typeOperand.getInlinedClassNative() != coercionDeclaringClass) + PossiblyFoldedExpression(expression.transformIfAsked(), false) + else { + val foldedArgument = fold(expression.argument, coercion, expression, transformRecursively) + if (foldedArgument.folded) + foldedArgument + else + PossiblyFoldedExpression(expression.apply { argument = foldedArgument.expression }, false) + } + } + + else -> PossiblyFoldedExpression(expression.transformIfAsked(), false) + } + } +} diff --git a/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/lower/ReflectionSupport.kt b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/lower/ReflectionSupport.kt new file mode 100644 index 00000000000..088766b8151 --- /dev/null +++ b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/lower/ReflectionSupport.kt @@ -0,0 +1,213 @@ +/* + * Copyright 2010-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +package org.jetbrains.kotlin.backend.konan.lower + +import org.jetbrains.kotlin.backend.konan.InteropFqNames +import org.jetbrains.kotlin.backend.konan.KonanBackendContext +import org.jetbrains.kotlin.backend.konan.ir.typeWithStarProjections +import org.jetbrains.kotlin.backend.konan.ir.typeWithoutArguments +import org.jetbrains.kotlin.backend.konan.isObjCClass +import org.jetbrains.kotlin.backend.konan.llvm.fullName +import org.jetbrains.kotlin.backend.konan.reportCompilationError +import org.jetbrains.kotlin.descriptors.ClassDescriptor +import org.jetbrains.kotlin.ir.IrElement +import org.jetbrains.kotlin.ir.builders.* +import org.jetbrains.kotlin.ir.declarations.IrEnumEntry +import org.jetbrains.kotlin.ir.declarations.IrFile +import org.jetbrains.kotlin.ir.declarations.IrFunction +import org.jetbrains.kotlin.ir.declarations.IrTypeParameter +import org.jetbrains.kotlin.ir.expressions.IrExpression +import org.jetbrains.kotlin.ir.expressions.IrMemberAccessExpression +import org.jetbrains.kotlin.ir.expressions.impl.IrGetEnumValueImpl +import org.jetbrains.kotlin.ir.expressions.impl.IrVarargImpl +import org.jetbrains.kotlin.ir.symbols.IrClassSymbol +import org.jetbrains.kotlin.ir.symbols.IrTypeParameterSymbol +import org.jetbrains.kotlin.ir.types.* +import org.jetbrains.kotlin.ir.util.* +import org.jetbrains.kotlin.ir.util.irCall +import org.jetbrains.kotlin.resolve.descriptorUtil.fqNameUnsafe +import org.jetbrains.kotlin.resolve.descriptorUtil.getAllSuperClassifiers +import org.jetbrains.kotlin.types.Variance + +internal class KTypeGenerator( + val context: KonanBackendContext, + val irFile: IrFile, + val irElement: IrElement, + val needExactTypeParameters: Boolean = false +) { + private val symbols = context.ir.symbols + + fun IrBuilderWithScope.irKType(type: IrType, leaveReifiedForLater: Boolean = false) = + irKType(type, leaveReifiedForLater, mutableSetOf()) + + private class RecursiveBoundsException(message: String) : Throwable(message) + + private fun IrBuilderWithScope.irKType( + type: IrType, + leaveReifiedForLater: Boolean, + seenTypeParameters: MutableSet + ): IrExpression { + if (type !is IrSimpleType) { + // Represent as non-denotable type: + return irKTypeImpl( + kClassifier = irNull(), + irTypeArguments = emptyList(), + isMarkedNullable = false, + leaveReifiedForLater = leaveReifiedForLater, + seenTypeParameters = seenTypeParameters + ) + } + try { + val kClassifier = when (val classifier = type.classifier) { + is IrClassSymbol -> irKClass(classifier) + is IrTypeParameterSymbol -> { + if (classifier.owner.isReified && leaveReifiedForLater) { + // Leave as is for reification. + return irCall(symbols.typeOf).apply { putTypeArgument(0, type) } + } + + // Leave upper bounds of non-reified type parameters as is, even if they are reified themselves. + irKTypeParameter(classifier.owner, leaveReifiedForLater = false, seenTypeParameters = seenTypeParameters) + } + else -> TODO("Unexpected classifier: $classifier") + } + + return irKTypeImpl( + kClassifier = kClassifier, + irTypeArguments = type.arguments, + isMarkedNullable = type.hasQuestionMark, + leaveReifiedForLater = leaveReifiedForLater, + seenTypeParameters = seenTypeParameters + ) + } catch (t: RecursiveBoundsException) { + if (needExactTypeParameters) + this@KTypeGenerator.context.reportCompilationError(t.message!!, irFile, irElement) + return irCall(symbols.kTypeImplForTypeParametersWithRecursiveBounds.constructors.single()) + } + } + + private fun IrBuilderWithScope.irKTypeImpl( + kClassifier: IrExpression, + irTypeArguments: List, + isMarkedNullable: Boolean, + leaveReifiedForLater: Boolean, + seenTypeParameters: MutableSet + ): IrExpression = irCall(symbols.kTypeImpl.constructors.single()).apply { + putValueArgument(0, kClassifier) + putValueArgument(1, irKTypeProjectionsList(irTypeArguments, leaveReifiedForLater, seenTypeParameters)) + putValueArgument(2, irBoolean(isMarkedNullable)) + } + + private fun IrBuilderWithScope.irKClass(symbol: IrClassSymbol) = irKClass(this@KTypeGenerator.context, symbol) + + private fun IrBuilderWithScope.irKTypeParameter( + typeParameter: IrTypeParameter, + leaveReifiedForLater: Boolean, + seenTypeParameters: MutableSet + ): IrMemberAccessExpression<*> { + if (!seenTypeParameters.add(typeParameter)) + throw RecursiveBoundsException("Non-reified type parameters with recursive bounds are not supported yet: ${typeParameter.render()}") + val result = irCall(symbols.kTypeParameterImpl.constructors.single()).apply { + putValueArgument(0, irString(typeParameter.name.asString())) + putValueArgument(1, irString(typeParameter.parentUniqueName)) + putValueArgument(2, irKTypeList(typeParameter.superTypes, leaveReifiedForLater, seenTypeParameters)) + putValueArgument(3, irKVariance(typeParameter.variance)) + putValueArgument(4, irBoolean(typeParameter.isReified)) + } + seenTypeParameters.remove(typeParameter) + return result + } + + private val IrTypeParameter.parentUniqueName get() = when (val parent = parent) { + is IrFunction -> parent.fullName + else -> parent.fqNameForIrSerialization.asString() + } + + private val Variance.kVarianceName: String + get() = when (this) { + Variance.INVARIANT -> "INVARIANT" + Variance.IN_VARIANCE -> "IN" + Variance.OUT_VARIANCE -> "OUT" + } + + private fun IrBuilderWithScope.irKVariance(variance: Variance) = + IrGetEnumValueImpl( + startOffset, endOffset, + symbols.kVariance.defaultType, + symbols.kVariance.owner.declarations + .filterIsInstance() + .single { it.name.asString() == variance.kVarianceName }.symbol + ) + + private fun IrBuilderWithScope.irKTypeLikeList( + types: List, + itemType: IrType, + itemBuilder: (T) -> IrExpression + ) = if (types.isEmpty()) { + irCall(symbols.emptyList, listOf(itemType)) + } else { + irCall(symbols.listOf, listOf(itemType)).apply { + putValueArgument(0, IrVarargImpl( + startOffset, endOffset, + type = symbols.array.typeWith(itemType), + varargElementType = itemType, + elements = types.map { itemBuilder(it) } + )) + } + } + + private fun IrBuilderWithScope.irKTypeList( + types: List, + leaveReifiedForLater: Boolean, + seenTypeParameters: MutableSet + ) = irKTypeLikeList(types, symbols.kType.defaultType) { irKType(it, leaveReifiedForLater, seenTypeParameters) } + + private fun IrBuilderWithScope.irKTypeProjectionsList( + irTypeArguments: List, + leaveReifiedForLater: Boolean, + seenTypeParameters: MutableSet + ) = irKTypeLikeList(irTypeArguments, symbols.kTypeProjection.typeWithoutArguments) { + irKTypeProjection(it, leaveReifiedForLater, seenTypeParameters) + } + + private fun IrBuilderWithScope.irKTypeProjection( + argument: IrTypeArgument, + leaveReifiedForLater: Boolean, + seenTypeParameters: MutableSet + ) = when (argument) { + is IrTypeProjection -> irCall(symbols.kTypeProjectionFactories.getValue(argument.variance)).apply { + dispatchReceiver = irGetObject(symbols.kTypeProjectionCompanion) + putValueArgument(0, irKType(argument.type, leaveReifiedForLater, seenTypeParameters)) + } + + is IrStarProjection -> irCall(symbols.kTypeProjectionStar.owner.getter!!).apply { + dispatchReceiver = irGetObject(symbols.kTypeProjectionCompanion) + } + + else -> error("Unexpected IrTypeArgument: $argument (${argument::class})") + } +} + +internal fun IrBuilderWithScope.irKClass(context: KonanBackendContext, symbol: IrClassSymbol): IrExpression { + val symbols = context.ir.symbols + return when { + symbol.descriptor.isObjCClass() -> + irKClassUnsupported(context, "KClass for Objective-C classes is not supported yet") + + symbol.descriptor.getAllSuperClassifiers().any { + it is ClassDescriptor && it.fqNameUnsafe == InteropFqNames.nativePointed + } -> irKClassUnsupported(context, "KClass for interop types is not supported yet") + + else -> irCall(symbols.kClassImplConstructor.owner).apply { + putValueArgument(0, irCall(symbols.getClassTypeInfo, listOf(symbol.typeWithStarProjections))) + } + } +} + +private fun IrBuilderWithScope.irKClassUnsupported(context: KonanBackendContext, message: String) = + irCall(context.ir.symbols.kClassUnsupportedImplConstructor.owner).apply { + putValueArgument(0, irString(message)) + } diff --git a/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/lower/ReturnsInsertionLowering.kt b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/lower/ReturnsInsertionLowering.kt new file mode 100644 index 00000000000..35d443b3576 --- /dev/null +++ b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/lower/ReturnsInsertionLowering.kt @@ -0,0 +1,62 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +package org.jetbrains.kotlin.backend.konan.lower + +import org.jetbrains.kotlin.backend.common.FileLoweringPass +import org.jetbrains.kotlin.backend.common.lower.createIrBuilder +import org.jetbrains.kotlin.backend.konan.Context +import org.jetbrains.kotlin.ir.IrElement +import org.jetbrains.kotlin.ir.builders.irGetObject +import org.jetbrains.kotlin.ir.builders.irReturn +import org.jetbrains.kotlin.ir.declarations.IrConstructor +import org.jetbrains.kotlin.ir.declarations.IrFile +import org.jetbrains.kotlin.ir.declarations.IrFunction +import org.jetbrains.kotlin.ir.expressions.* +import org.jetbrains.kotlin.ir.expressions.impl.IrBlockBodyImpl +import org.jetbrains.kotlin.ir.visitors.IrElementVisitorVoid +import org.jetbrains.kotlin.ir.visitors.acceptChildrenVoid +import org.jetbrains.kotlin.ir.visitors.acceptVoid + +internal class ReturnsInsertionLowering(val context: Context) : FileLoweringPass { + private val symbols = context.ir.symbols + + override fun lower(irFile: IrFile) { + irFile.acceptVoid(object : IrElementVisitorVoid { + override fun visitElement(element: IrElement) { + element.acceptChildrenVoid(this) + } + + override fun visitFunction(declaration: IrFunction) { + declaration.acceptChildrenVoid(this) + + context.createIrBuilder(declaration.symbol, declaration.endOffset, declaration.endOffset).run { + when (val body = declaration.body) { + is IrExpressionBody -> { + declaration.body = IrBlockBodyImpl(body.startOffset, body.endOffset) { + statements += irReturn(body.expression) + } + } + is IrBlockBody -> { + if (declaration is IrConstructor || declaration.returnType == context.irBuiltIns.unitType) + body.statements += irReturn(irGetObject(symbols.unit)) + } + } + } + } + + override fun visitBlock(expression: IrBlock) { + expression.acceptChildrenVoid(this) + if (expression !is IrReturnableBlock) return + if (expression.inlineFunctionSymbol?.owner?.returnType == context.irBuiltIns.unitType) { + val irBuilder = context.createIrBuilder(expression.symbol, expression.endOffset, expression.endOffset) + irBuilder.run { + expression.statements += irReturn(irGetObject(symbols.unit)) + } + } + } + }) + } +} \ No newline at end of file diff --git a/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/lower/SpecialBackendChecksTraversal.kt b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/lower/SpecialBackendChecksTraversal.kt new file mode 100644 index 00000000000..ec64e94faf8 --- /dev/null +++ b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/lower/SpecialBackendChecksTraversal.kt @@ -0,0 +1,790 @@ +/* + * Copyright 2010-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +package org.jetbrains.kotlin.backend.konan.lower + +import org.jetbrains.kotlin.backend.common.* +import org.jetbrains.kotlin.backend.common.ir.Symbols +import org.jetbrains.kotlin.backend.common.ir.allParameters +import org.jetbrains.kotlin.backend.common.lower.Closure +import org.jetbrains.kotlin.backend.common.lower.ClosureAnnotator +import org.jetbrains.kotlin.backend.konan.* +import org.jetbrains.kotlin.backend.konan.cgen.* +import org.jetbrains.kotlin.backend.konan.descriptors.allOverriddenFunctions +import org.jetbrains.kotlin.backend.konan.ir.* +import org.jetbrains.kotlin.backend.konan.ir.companionObject +import org.jetbrains.kotlin.backend.konan.llvm.IntrinsicType +import org.jetbrains.kotlin.backend.konan.llvm.tryGetIntrinsicType +import org.jetbrains.kotlin.descriptors.ClassDescriptor +import org.jetbrains.kotlin.descriptors.ClassKind +import org.jetbrains.kotlin.descriptors.DescriptorVisibilities +import org.jetbrains.kotlin.descriptors.isFinalClass +import org.jetbrains.kotlin.ir.IrElement +import org.jetbrains.kotlin.ir.builders.* +import org.jetbrains.kotlin.ir.declarations.* +import org.jetbrains.kotlin.ir.expressions.* +import org.jetbrains.kotlin.ir.symbols.IrSimpleFunctionSymbol +import org.jetbrains.kotlin.ir.symbols.IrTypeParameterSymbol +import org.jetbrains.kotlin.ir.types.* +import org.jetbrains.kotlin.ir.util.* +import org.jetbrains.kotlin.ir.visitors.IrElementVisitorVoid +import org.jetbrains.kotlin.ir.visitors.acceptChildrenVoid +import org.jetbrains.kotlin.name.FqName +import org.jetbrains.kotlin.resolve.descriptorUtil.fqNameSafe +import org.jetbrains.kotlin.types.Variance + +internal class SpecialBackendChecksTraversal(val context: Context) : FileLoweringPass { + override fun lower(irFile: IrFile) = irFile.acceptChildrenVoid(BackendChecker(context, irFile)) +} + +private class BackendChecker(val context: Context, val irFile: IrFile) : IrElementVisitorVoid { + val interop = context.interopBuiltIns + val symbols = context.ir.symbols + val irBuiltIns = context.irBuiltIns + val target = context.config.target + + fun reportError(location: IrElement, message: String): Nothing = + context.reportCompilationError(message, irFile, location) + + private val outerDeclarations = mutableListOf() + + private val outerClass: IrClass? get() = outerDeclarations.last { it is IrClass } as? IrClass + private val outerFunction: IrFunction? get() = outerDeclarations.last { it is IrFunction } as? IrFunction + + private val outerAnnotators = mutableListOf>() + private val functionAnnotators = mutableMapOf>() + private val functionClosures = mutableMapOf() + + private fun capturesAnything(function: IrFunction): Boolean { + if (function.visibility != DescriptorVisibilities.LOCAL) return false + val closure = functionClosures.getOrPut(function) { + functionAnnotators[function]!!.value.getFunctionClosure(function) + } + return closure.capturedValues.isNotEmpty() + } + + override fun visitElement(element: IrElement) { + element.acceptChildrenVoid(this) + } + + override fun visitDeclaration(declaration: IrDeclarationBase) { + if (declaration is IrClass && declaration.isKotlinObjCClass()) { + checkKotlinObjCClass(declaration) + } + + outerDeclarations.push(declaration) + try { + super.visitDeclaration(declaration) + } finally { + outerDeclarations.pop() + } + } + + override fun visitBody(body: IrBody) { + val declaration = outerDeclarations.peek()!! + if ((declaration as? IrFunction)?.visibility == DescriptorVisibilities.LOCAL) { + functionAnnotators[declaration] = outerAnnotators.peek()!! + super.visitBody(body) + return + } + + outerAnnotators.push(lazy { ClosureAnnotator(body, declaration) }) + try { + super.visitBody(body) + } finally { + outerAnnotators.pop() + } + } + + private fun IrConstructor.isOverrideInit() = + this.annotations.hasAnnotation(context.interopBuiltIns.objCOverrideInit.fqNameSafe) + + private fun checkCanGenerateOverrideInit(irClass: IrClass, constructor: IrConstructor) { + val superClass = irClass.getSuperClassNotAny()!! + val superConstructors = superClass.constructors.filter { + constructor.overridesConstructor(it) + }.toList() + + val superConstructor = superConstructors.singleOrNull() ?: run { + val annotation = context.interopBuiltIns.objCOverrideInit.name + if (superConstructors.isEmpty()) + reportError(constructor, + """ + constructor with @$annotation doesn't override any super class constructor. + It must completely match by parameter names and types.""".trimIndent() + ) + else + reportError(constructor, + "constructor with @$annotation matches more than one of super constructors" + ) + } + + val initMethod = superConstructor.getObjCInitMethod()!! + + // Remove fake overrides of this init method, also check for explicit overriding: + irClass.declarations.forEach { + if (it is IrSimpleFunction && initMethod.symbol in it.overriddenSymbols && it.isReal) { + val annotation = context.interopBuiltIns.objCOverrideInit.name + reportError(constructor, + "constructor with @$annotation overrides initializer that is already overridden explicitly" + ) + } + } + } + + private fun IrConstructor.overridesConstructor(other: IrConstructor) = + this.descriptor.valueParameters.size == other.descriptor.valueParameters.size && + this.descriptor.valueParameters.all { + val otherParameter = other.descriptor.valueParameters[it.index] + it.name == otherParameter.name && it.type == otherParameter.type + } + + private fun checkCanGenerateActionImp(function: IrSimpleFunction) { + val action = "@${context.interopBuiltIns.objCAction.name}" + + function.extensionReceiverParameter?.let { + reportError(it, "$action method must not have extension receiver") + } + + function.valueParameters.forEach { + val kotlinType = it.descriptor.type + if (!kotlinType.isObjCObjectType()) + reportError(it, "Unexpected $action method parameter type: $kotlinType\n" + + "Only Objective-C object types are supported here") + } + + val returnType = function.returnType + if (!returnType.isUnit()) + reportError(function, "Unexpected $action method return type: ${returnType.toKotlinType()}\n" + + "Only 'Unit' is supported here") + + checkCanGenerateFunctionImp(function) + } + + private fun checkCanGenerateOutletSetterImp(property: IrProperty) { + val descriptor = property.descriptor + + val outlet = "@${context.interopBuiltIns.objCOutlet.name}" + + if (!descriptor.isVar) + reportError(property, "$outlet property must be var") + + property.getter?.extensionReceiverParameter?.let { + reportError(it, "$outlet must not have extension receiver") + } + + val type = descriptor.type + if (!type.isObjCObjectType()) + reportError(property, "Unexpected $outlet type: $type\n" + + "Only Objective-C object types are supported here") + + checkCanGenerateFunctionImp(property.setter!!) + } + + private fun checkCanGenerateFunctionImp(function: IrFunction) { + if (function.valueParameters.size > 2) + reportError(function, "Only 0, 1 or 2 parameters are supported here") + } + + private fun IrClass.hasFields() = + this.declarations.any { + when (it) { + is IrField -> it.isReal + is IrProperty -> it.isReal && it.backingField != null + else -> false + } + } + + private fun checkKotlinObjCClass(irClass: IrClass) { + for (declaration in irClass.declarations) { + if (declaration is IrSimpleFunction && declaration.annotations.hasAnnotation(interop.objCAction.fqNameSafe)) + checkCanGenerateActionImp(declaration) + if (declaration is IrProperty && declaration.annotations.hasAnnotation(interop.objCOutlet.fqNameSafe)) + checkCanGenerateOutletSetterImp(declaration) + if (declaration is IrConstructor && declaration.isOverrideInit()) + checkCanGenerateOverrideInit(irClass, declaration) + if (declaration is IrSimpleFunction && declaration.isReal) { + for (overriddenSymbol in declaration.overriddenSymbols) + overriddenSymbol.owner.getExternalObjCMethodInfo()?.selector?.let { + checkCanGenerateCFunction( + function = declaration, + signature = overriddenSymbol.owner, + isObjCMethod = true, + location = declaration + ) + } + } + } + + val kind = irClass.descriptor.kind + if (kind != ClassKind.CLASS && kind != ClassKind.OBJECT) + reportError(irClass, "Only classes are supported as subtypes of Objective-C types") + + if (!irClass.descriptor.isFinalClass) + reportError(irClass, "Non-final Kotlin subclasses of Objective-C classes are not yet supported") + + irClass.companionObject()?.let { + if (it.hasFields() || it.getSuperClassNotAny()?.hasFields() == true) + reportError(irClass, "Fields are not supported for Companion of subclass of ObjC type") + } + + var hasObjCClassSupertype = false + irClass.descriptor.defaultType.constructor.supertypes.forEach { + val descriptor = it.constructor.declarationDescriptor as ClassDescriptor + if (!descriptor.isObjCClass()) + reportError(irClass, "Mixing Kotlin and Objective-C supertypes is not supported") + + if (descriptor.kind == ClassKind.CLASS) + hasObjCClassSupertype = true + } + + if (!hasObjCClassSupertype) + reportError(irClass, "Kotlin implementation of Objective-C protocol must have Objective-C superclass (e.g. NSObject)") + + val methodsOfAny = context.ir.symbols.any.owner.declarations.filterIsInstance().toSet() + + irClass.declarations.filterIsInstance().filter { it.isReal }.forEach { method -> + val overriddenMethodOfAny = method.allOverriddenFunctions.firstOrNull { + it in methodsOfAny + } + + if (overriddenMethodOfAny != null) { + val correspondingObjCMethod = when (method.name.asString()) { + "toString" -> "'description'" + "hashCode" -> "'hash'" + "equals" -> "'isEqual:'" + else -> "corresponding Objective-C method" + } + + context.report( + method, + "can't override '${method.name}', override $correspondingObjCMethod instead", + isError = true + ) + } + } + } + + override fun visitDelegatingConstructorCall(expression: IrDelegatingConstructorCall) { + expression.acceptChildrenVoid(this) + + val constructedClass = outerClass!! + + if (!constructedClass.isObjCClass()) + return + + constructedClass.parent.let { parent -> + if (parent is IrClass && parent.isObjCClass() && constructedClass.isCompanion) { + // Note: it is actually not used; getting values of such objects is handled by code generator + // in [FunctionGenerationContext.getObjectValue]. + + return + } + } + + val delegatingCallConstructingClass = expression.symbol.owner.constructedClass + if (!constructedClass.isExternalObjCClass() && + delegatingCallConstructingClass.isExternalObjCClass()) { + // Calling super constructor from Kotlin Objective-C class. + + val initMethod = expression.symbol.owner.getObjCInitMethod()!! + + if (!expression.symbol.owner.objCConstructorIsDesignated()) + reportError(expression, "Unable to call non-designated initializer as super constructor") + + checkCanGenerateObjCCall( + method = initMethod, + call = expression, + arguments = initMethod.valueParameters.map { expression.getValueArgument(it.index) } + ) + } + } + + override fun visitConstructorCall(expression: IrConstructorCall) { + expression.acceptChildrenVoid(this) + + val callee = expression.symbol.owner + val initMethod = callee.getObjCInitMethod() + if (initMethod != null) { + val arguments = callee.valueParameters.map { expression.getValueArgument(it.index) } + + checkCanGenerateObjCCall( + method = initMethod, + call = expression, + arguments = arguments + ) + } + + if (callee.returnType.getInlinedClassNative()?.descriptor == interop.nativePointed) + reportError(expression, "Native interop types constructors must not be called directly") + } + + override fun visitCall(expression: IrCall) { + expression.acceptChildrenVoid(this) + + val callee = expression.symbol.owner + + callee.getObjCFactoryInitMethodInfo()?.let { _ -> + val arguments = (0 until expression.valueArgumentsCount).map(expression::getValueArgument) + + checkCanGenerateObjCCall( + method = callee, + call = expression, + arguments = arguments + ) + } + + callee.getExternalObjCMethodInfo()?.let { _ -> + val isInteropStubsFile = irFile.annotations.hasAnnotation(FqName("kotlinx.cinterop.InteropStubs")) + + // Special case: bridge from Objective-C method implementation template to Kotlin method; + // handled in CodeGeneratorVisitor.callVirtual. + val useKotlinDispatch = isInteropStubsFile && + outerFunction!!.annotations.hasAnnotation(FqName("kotlin.native.internal.ExportForCppRuntime")) + + if (!useKotlinDispatch) { + val arguments = callee.valueParameters.map { expression.getValueArgument(it.index) } + + if (expression.superQualifierSymbol?.owner?.isObjCMetaClass() == true) + reportError(expression, "Super calls to Objective-C meta classes are not supported yet") + + if (expression.superQualifierSymbol?.owner?.isInterface == true) + reportError(expression, "Super calls to Objective-C protocols are not allowed") + + checkCanGenerateObjCCall( + method = callee, + call = expression, + arguments = arguments + ) + } + } + + if (callee.annotations.hasAnnotation(RuntimeNames.cCall)) + checkCanGenerateCCall(expression, isInvoke = false) + + when (val intrinsicType = tryGetIntrinsicType(expression)) { + IntrinsicType.INTEROP_STATIC_C_FUNCTION -> { + val target = getUnboundReferencedFunction(expression.getValueArgument(0)!!) + + if (target == null || target.symbol !is IrSimpleFunctionSymbol) + reportError(expression, "${callee.fqNameForIrSerialization} must take an unbound, non-capturing function or lambda") + + val signatureTypes = target.allParameters.map { it.type } + target.returnType + + callee.typeParameters.indices.forEach { index -> + val typeArgument = expression.getTypeArgument(index)!!.toKotlinType() + val signatureType = signatureTypes[index].toKotlinType() + if (typeArgument.constructor != signatureType.constructor || + typeArgument.isMarkedNullable != signatureType.isMarkedNullable + ) { + reportError(expression, "C function signature element mismatch: expected '$signatureType', got '$typeArgument'") + } + } + + checkCanGenerateCFunctionPointer(target as IrSimpleFunction, expression) + } + IntrinsicType.INTEROP_FUNPTR_INVOKE -> { + checkCanGenerateCCall(expression, isInvoke = true) + } + IntrinsicType.INTEROP_SIGN_EXTEND, IntrinsicType.INTEROP_NARROW -> { + + val integerTypePredicates = arrayOf( + IrType::isByte, IrType::isShort, IrType::isInt, IrType::isLong + ) + + val receiver = expression.extensionReceiver!! + val typeOperand = expression.getSingleTypeArgument() + val kotlinTypeOperand = typeOperand.toKotlinType() + + val receiverTypeIndex = integerTypePredicates.indexOfFirst { it(receiver.type) } + val typeOperandIndex = integerTypePredicates.indexOfFirst { it(typeOperand) } + + val receiverKotlinType = receiver.type.toKotlinType() + + if (receiverTypeIndex == -1) + reportError(receiver, "Receiver's type $receiverKotlinType is not an integer type") + + if (typeOperandIndex == -1) + reportError(expression, "Type argument $kotlinTypeOperand is not an integer type") + + when (intrinsicType) { + IntrinsicType.INTEROP_SIGN_EXTEND -> if (receiverTypeIndex > typeOperandIndex) + reportError(expression, "unable to sign extend $receiverKotlinType to $kotlinTypeOperand") + + IntrinsicType.INTEROP_NARROW -> if (receiverTypeIndex < typeOperandIndex) + reportError(expression, "unable to narrow $receiverKotlinType to $kotlinTypeOperand") + + else -> error(intrinsicType) + } + } + IntrinsicType.INTEROP_CONVERT -> { + val integerClasses = symbols.allIntegerClasses + val typeOperand = expression.getTypeArgument(0)!! + val receiverType = expression.symbol.owner.extensionReceiverParameter!!.type + + if (typeOperand !is IrSimpleType || typeOperand.classifier !in integerClasses || typeOperand.hasQuestionMark) + reportError(expression, "unable to convert ${receiverType.toKotlinType()} to ${typeOperand.toKotlinType()}") + } + IntrinsicType.WORKER_EXECUTE -> { + getUnboundReferencedFunction(expression.getValueArgument(2)!!) + ?: reportError(expression, "${callee.fqNameForIrSerialization} must take an unbound, non-capturing function or lambda") + } + else -> when { + callee.symbol == symbols.createCleaner -> + getUnboundReferencedFunction(expression.getValueArgument(1)!!) + ?: reportError(expression, "${callee.fqNameForIrSerialization} must take an unbound, non-capturing function or lambda") + callee.symbol == symbols.immutableBlobOf -> { + val args = expression.getValueArgument(0) + ?: reportError(expression, "expected at least one element") + val elements = (args as IrVararg).elements + if (elements.any { it is IrSpreadElement }) + reportError(args, "no spread elements allowed here") + elements.forEach { + if (it !is IrConst<*>) + reportError(args, "all elements of binary blob must be constants") + val value = it.value as Short + if (value < 0 || value > 0xff) + reportError(it, "incorrect value for binary data: $value") + } + } + Symbols.isTypeOfIntrinsic(callee.symbol) -> + checkIrKType(expression, expression.getTypeArgument(0)!!) + } + } + } + + override fun visitFunctionExpression(expression: IrFunctionExpression) { + expression.acceptChildrenVoid(this) + + checkCanReferenceFunction(expression.function, expression) + } + + override fun visitFunctionReference(expression: IrFunctionReference) { + expression.acceptChildrenVoid(this) + + checkCanReferenceFunction(expression.symbol.owner, expression) + } + + private fun checkCanReferenceFunction(callee: IrFunction, expression: IrExpression) { + // Corresponds to the check in [KotlinToCCallBuilder.handleArgumentForVarargParameter]. + if (callee.valueParameters.any { it.isVararg }) { + if (callee.annotations.hasAnnotation(RuntimeNames.cCall)) + reportError(expression, "callable references to variadic C functions are not supported") + if (callee is IrConstructor && callee.getObjCInitMethod() != null + || callee.getObjCFactoryInitMethodInfo() != null + || callee.getExternalObjCMethodInfo() != null + ) { + reportError(expression, "callable references to variadic Objective-C methods are not supported") + } + } + } + + private fun getUnboundReferencedFunction(expression: IrExpression) = when (expression) { + is IrFunctionReference -> expression.symbol.owner.takeIf { expression.getArguments().isEmpty() && !capturesAnything(it) } + is IrFunctionExpression -> expression.function.takeIf { !capturesAnything(it) } + else -> null + } + + private fun IrCall.getSingleTypeArgument(): IrType { + val typeParameter = symbol.owner.typeParameters.single() + return getTypeArgument(typeParameter.index)!! + } + + private fun checkIrKType( + irElement: IrElement, + type: IrType, + seenTypeParameters: MutableSet = mutableSetOf() + ) { + if (type !is IrSimpleType) + return + val classifier = type.classifier + if (classifier is IrTypeParameterSymbol) + checkIrKTypeParameter(irElement, classifier.owner, seenTypeParameters) + + type.arguments.forEach { + if (it is IrTypeProjection) + checkIrKType(irElement, it.type, seenTypeParameters) + } + } + + private fun checkIrKTypeParameter( + irElement: IrElement, + typeParameter: IrTypeParameter, + seenTypeParameters: MutableSet + ) { + if (!seenTypeParameters.add(typeParameter)) + reportError(irElement, "Non-reified type parameters with recursive bounds are not supported yet: ${typeParameter.render()}") + typeParameter.superTypes.forEach { checkIrKType(irElement, it, seenTypeParameters) } + seenTypeParameters.remove(typeParameter) + } +} + +private fun BackendChecker.checkCanGenerateCCall(expression: IrCall, isInvoke: Boolean) { + val callee = expression.symbol.owner + + if (isInvoke) { + (0 until expression.valueArgumentsCount).forEach { + checkCanMapCalleeFunctionParameter( + type = expression.getTypeArgument(it)!!, + isObjCMethod = false, + variadic = false, + parameter = null, + argument = expression.getValueArgument(it)!!) + } + + val returnType = expression.getTypeArgument(expression.typeArgumentsCount - 1)!! + checkCanMapReturnType(returnType, TypeLocation.FunctionCallResult(expression)) + } else { + val arguments = (0 until expression.valueArgumentsCount).map(expression::getValueArgument) + checkCanAddArguments(arguments, callee, isObjCMethod = false) + + checkCanMapReturnType(callee.returnType, TypeLocation.FunctionCallResult(expression)) + } +} + +private fun BackendChecker.checkCanAddArguments(arguments: List, callee: IrFunction, isObjCMethod: Boolean) { + arguments.forEachIndexed { index, argument -> + val parameter = callee.valueParameters[index] + if (parameter.isVararg) + checkCanHandleArgumentForVarargParameter(argument, isObjCMethod) + else + checkCanMapCalleeFunctionParameter(parameter.type, isObjCMethod, variadic = false, parameter = parameter, argument = argument!!) + } +} + +private fun BackendChecker.checkCanUnwrapVariadicArguments(elements: List, isObjCMethod: Boolean) { + for (element in elements) when (element) { + is IrExpression -> + checkCanMapCalleeFunctionParameter(element.type, isObjCMethod, variadic = true, parameter = null, argument = element) + is IrSpreadElement -> { + val expression = element.expression + if (expression is IrCall && expression.symbol == symbols.arrayOf) + checkCanHandleArgumentForVarargParameter(expression.getValueArgument(0), isObjCMethod) + else + reportError(element, "When calling variadic " + + (if (isObjCMethod) "Objective-C methods " else "C functions ") + + "spread operator is supported only for *arrayOf(...)") + } + } +} + +private fun BackendChecker.checkCanHandleArgumentForVarargParameter(argument: IrExpression?, isObjCMethod: Boolean) { + when (argument) { + is IrVararg -> checkCanUnwrapVariadicArguments(argument.elements, isObjCMethod) + + is IrGetValue -> { + /* This is possible when using named arguments with reordering, i.e. + * + * foo(second = *arrayOf(...), first = ...) + * + * psi2ir generates as + * + * val secondTmp = *arrayOf(...) + * val firstTmp = ... + * foo(firstTmp, secondTmp) + * + * + **/ + + val variable = argument.symbol.owner + if (variable is IrVariable && variable.origin == IrDeclarationOrigin.IR_TEMPORARY_VARIABLE && !variable.isVar) + checkCanUnwrapVariadicArguments((variable.initializer as IrVararg).elements, isObjCMethod) + } + } +} + +private fun BackendChecker.checkCanGenerateObjCCall( + method: IrSimpleFunction, + call: IrFunctionAccessExpression, + arguments: List +) { + checkCanAddArguments(arguments, method, isObjCMethod = true) + + checkCanMapReturnType(method.returnType, TypeLocation.FunctionCallResult(call)) +} + +private fun BackendChecker.checkParameter(it: IrValueParameter, functionParameter: IrValueParameter, + isObjCMethod: Boolean, location: IrElement) { + val typeLocation = if (isObjCMethod) + TypeLocation.ObjCMethodParameter(it.index, functionParameter) + else + TypeLocation.FunctionPointerParameter(it.index, location) + + if (functionParameter.isVararg) + reportError(typeLocation.element, if (isObjCMethod) { + "overriding variadic Objective-C methods is not supported" + } else { + "variadic function pointers are not supported" + }) + + checkCanMapFunctionParameterType(it.type, variadic = false, location = typeLocation) +} + +private fun BackendChecker.checkCanGenerateCFunction( + function: IrSimpleFunction, + signature: IrSimpleFunction, + isObjCMethod: Boolean, + location: IrElement +) { + signature.extensionReceiverParameter?.let { + checkParameter(it, function.extensionReceiverParameter!!, isObjCMethod, location) + } + + signature.valueParameters.forEach { + checkParameter(it, function.valueParameters[it.index], isObjCMethod, location) + } +} + +private fun BackendChecker.checkCanGenerateCFunctionPointer(function: IrSimpleFunction, expression: IrExpression) = + checkCanGenerateCFunction( + function = function, + signature = function, + isObjCMethod = false, + location = expression + ) + +private fun BackendChecker.checkCanMapCalleeFunctionParameter( + type: IrType, + isObjCMethod: Boolean, + variadic: Boolean, + parameter: IrValueParameter?, + argument: IrExpression +) { + val classifier = type.classifierOrNull + when { + classifier == symbols.interopCValues || // Note: this should not be accepted, but is required for compatibility + classifier == symbols.interopCValuesRef -> return + + classifier == symbols.string && (variadic || parameter?.isCStringParameter() == true) -> { + if (variadic && isObjCMethod) { + reportError(argument, "Passing String as variadic Objective-C argument is ambiguous; " + + "cast it to NSString or pass with '.cstr' as C string") + // TODO: consider reporting a warning for C functions. + } + } + + classifier == symbols.string && parameter?.isWCStringParameter() == true -> return + + else -> checkCanMapFunctionParameterType(type, variadic = variadic, location = TypeLocation.FunctionArgument(argument)) + } +} + +private sealed class TypeLocation(val element: IrElement) { + class FunctionArgument(val argument: IrExpression) : TypeLocation(argument) + class FunctionCallResult(val call: IrFunctionAccessExpression) : TypeLocation(call) + + class FunctionPointerParameter(val index: Int, element: IrElement) : TypeLocation(element) + class FunctionPointerReturnValue(element: IrElement) : TypeLocation(element) + + class ObjCMethodParameter(val index: Int, element: IrElement) : TypeLocation(element) + class ObjCMethodReturnValue(element: IrElement) : TypeLocation(element) + + class BlockParameter(val index: Int, val blockLocation: TypeLocation) : TypeLocation(blockLocation.element) + class BlockReturnValue(val blockLocation: TypeLocation) : TypeLocation(blockLocation.element) +} + +private fun BackendChecker.checkCanMapFunctionParameterType(type: IrType, variadic: Boolean, location: TypeLocation) { + if (!type.isUnit() || variadic) + checkCanMapType(type, variadic = variadic, location = location) +} + +private fun BackendChecker.checkCanMapReturnType(type: IrType, location: TypeLocation) { + if (!type.isUnit()) + checkCanMapType(type, variadic = false, location = location) +} + +private fun BackendChecker.checkCanMapBlockType(type: IrType, location: TypeLocation) { + when (val returnTypeArgument = (type as IrSimpleType).arguments.last()) { + is IrTypeProjection -> if (returnTypeArgument.variance == Variance.INVARIANT) + checkCanMapReturnType(returnTypeArgument.type, TypeLocation.BlockReturnValue(location)) + else + reportUnsupportedType("${returnTypeArgument.variance.label}-variance of return type", type, location) + + is IrStarProjection -> reportUnsupportedType("* as return type", type, location) + } + type.arguments.dropLast(1).forEachIndexed { index, argument -> + when (argument) { + is IrTypeProjection -> if (argument.variance == Variance.INVARIANT) + checkCanMapType(argument.type, variadic = false, location = TypeLocation.BlockParameter(index, location)) + else + reportUnsupportedType("${argument.variance.label}-variance of ${index + 1} parameter type", type, location) + + is IrStarProjection -> reportUnsupportedType("* as ${index + 1} parameter type", type, location) + } + } +} + +private fun BackendChecker.checkCanMapType(type: IrType, variadic: Boolean, location: TypeLocation) = + checkCanMapType(type, variadic, location) { reportUnsupportedType(it, type, location) } + +private fun BackendChecker.checkCanMapType( + type: IrType, + variadic: Boolean, + typeLocation: TypeLocation, + reportUnsupportedType: (String) -> Nothing +) { + when { + type.isBoolean() -> { + if (cBoolType(target) == null) + reportUnsupportedType("unavailable on target platform") + } + + type.isByte() -> return + type.isShort() -> return + type.isInt() -> return + type.isLong() -> return + type.isFloat() -> return + type.isDouble() -> return + type.isCPointer(symbols) -> return + type.isTypeOfNullLiteral() && variadic -> return + type.isUByte() -> return + type.isUShort() -> return + type.isUInt() -> return + type.isULong() -> return + type.isVector() -> return + + type.isCEnumType() -> return + + type.isCValue(symbols) -> if (type.isNullable()) + reportUnsupportedType("must not be nullable") + else { + val kotlinClass = (type as IrSimpleType).arguments.singleOrNull()?.typeOrNull?.getClass() + ?: reportUnsupportedType("must be parameterized with concrete class") + + kotlinClass.getCStructSpelling() + ?: reportUnsupportedType("not a structure or too complex") + } + + type.isNativePointed(symbols) -> return + + type.isFunction() -> if (variadic) + reportUnsupportedType("not supported as variadic argument") + else + checkCanMapBlockType(type, location = typeLocation) + + type.isObjCReferenceType(target, irBuiltIns) -> return + + else -> reportUnsupportedType("doesn't correspond to any C type") + } +} + +private fun BackendChecker.reportUnsupportedType(reason: String, type: IrType, location: TypeLocation): Nothing { + // TODO: report errors in frontend instead. + fun TypeLocation.render(): String = when (this) { + is TypeLocation.FunctionArgument -> "" + is TypeLocation.FunctionCallResult -> " of return value" + is TypeLocation.FunctionPointerParameter -> " of callback parameter ${index + 1}" + is TypeLocation.FunctionPointerReturnValue -> " of callback return value" + is TypeLocation.ObjCMethodParameter -> " of overridden Objective-C method parameter" + is TypeLocation.ObjCMethodReturnValue -> " of overridden Objective-C method return value" + is TypeLocation.BlockParameter -> " of ${index + 1} parameter in Objective-C block type${blockLocation.render()}" + is TypeLocation.BlockReturnValue -> " of return value of Objective-C block type${blockLocation.render()}" + } + + val typeLocation: String = location.render() + + reportError(location.element, "type ${type.render()} $typeLocation is not supported here" + + if (reason.isNotEmpty()) ": $reason" else "") +} diff --git a/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/lower/StringConcatenationLowering.kt b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/lower/StringConcatenationLowering.kt new file mode 100644 index 00000000000..c6a3380952e --- /dev/null +++ b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/lower/StringConcatenationLowering.kt @@ -0,0 +1,114 @@ +package org.jetbrains.kotlin.backend.konan.lower + +import org.jetbrains.kotlin.backend.common.FileLoweringPass +import org.jetbrains.kotlin.backend.common.atMostOne +import org.jetbrains.kotlin.backend.common.lower.IrBuildingTransformer +import org.jetbrains.kotlin.backend.common.lower.at +import org.jetbrains.kotlin.backend.common.lower.irBlock +import org.jetbrains.kotlin.backend.konan.Context +import org.jetbrains.kotlin.ir.builders.* +import org.jetbrains.kotlin.ir.declarations.IrFile +import org.jetbrains.kotlin.ir.declarations.IrSimpleFunction +import org.jetbrains.kotlin.ir.expressions.IrExpression +import org.jetbrains.kotlin.ir.expressions.IrStringConcatenation +import org.jetbrains.kotlin.ir.types.* +import org.jetbrains.kotlin.ir.util.constructors +import org.jetbrains.kotlin.ir.util.functions +import org.jetbrains.kotlin.ir.visitors.transformChildrenVoid +import org.jetbrains.kotlin.name.Name +import org.jetbrains.kotlin.util.OperatorNameConventions + +/** + * This lowering pass replaces [IrStringConcatenation]s with StringBuilder appends. + */ +internal class StringConcatenationLowering(context: Context) : FileLoweringPass, IrBuildingTransformer(context) { + override fun lower(irFile: IrFile) { + irFile.transformChildrenVoid(this) + } + + private val irBuiltIns = context.irBuiltIns + private val symbols = context.ir.symbols + + private val typesWithSpecialAppendFunction = irBuiltIns.primitiveIrTypes + irBuiltIns.stringType + + private val nameToString = Name.identifier("toString") + private val nameAppend = Name.identifier("append") + + private val stringBuilder = context.ir.symbols.stringBuilder.owner + + //TODO: calculate and pass string length to the constructor. + private val constructor = stringBuilder.constructors.single { + it.valueParameters.isEmpty() + } + + private val toStringFunction = stringBuilder.functions.single { + it.valueParameters.isEmpty() && it.name == nameToString + } + + private val defaultAppendFunction = stringBuilder.functions.single { + it.name == nameAppend && + it.valueParameters.size == 1 && + it.valueParameters.single().type.isNullableAny() + } + + private val appendFunctions: Map = + typesWithSpecialAppendFunction.map { type -> + type to stringBuilder.functions.toList().atMostOne { + it.name == nameAppend && it.valueParameters.singleOrNull()?.type == type + } + }.toMap() + + private fun typeToAppendFunction(type: IrType): IrSimpleFunction { + return appendFunctions[type] ?: defaultAppendFunction + } + + override fun visitStringConcatenation(expression: IrStringConcatenation): IrExpression { + expression.transformChildrenVoid(this) + + builder.at(expression) + val arguments = expression.arguments + return when { + arguments.isEmpty() -> builder.irString("") + + arguments.size == 1 -> { + val argument = arguments[0] + if (argument.type.isNullable()) + builder.irCall(symbols.extensionToString).apply { + extensionReceiver = argument + } + else builder.irCall( + irBuiltIns.anyClass.functions + .single { it.owner.name.asString() == "toString" }).apply { + dispatchReceiver = argument + } + } + + arguments.size == 2 && arguments[0].type.isStringClassType() -> + if (arguments[0].type.isNullable()) + builder.irCall(symbols.stringPlus).apply { + extensionReceiver = arguments[0] + putValueArgument(0, arguments[1]) + } + else + builder.irCall(symbols.string.functions + .single { it.owner.name == OperatorNameConventions.PLUS }).apply { + dispatchReceiver = arguments[0] + putValueArgument(0, arguments[1]) + } + + else -> builder.irBlock(expression) { + val stringBuilderImpl = createTmpVariable(irCall(constructor)) + expression.arguments.forEach { arg -> + val appendFunction = typeToAppendFunction(arg.type) + +irCall(appendFunction).apply { + dispatchReceiver = irGet(stringBuilderImpl) + putValueArgument(0, arg) + } + } + +irCall(toStringFunction).apply { + dispatchReceiver = irGet(stringBuilderImpl) + } + } + } + } +} diff --git a/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/lower/TestProcessor.kt b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/lower/TestProcessor.kt new file mode 100644 index 00000000000..baa2034e8c2 --- /dev/null +++ b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/lower/TestProcessor.kt @@ -0,0 +1,628 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +package org.jetbrains.kotlin.backend.konan.lower + +import org.jetbrains.kotlin.backend.common.ir.* +import org.jetbrains.kotlin.backend.common.lower.createIrBuilder +import org.jetbrains.kotlin.backend.common.reportWarning +import org.jetbrains.kotlin.backend.konan.Context +import org.jetbrains.kotlin.backend.konan.descriptors.isAbstract +import org.jetbrains.kotlin.backend.konan.descriptors.synthesizedName +import org.jetbrains.kotlin.backend.konan.getIncludedLibraryDescriptors +import org.jetbrains.kotlin.backend.konan.ir.typeWithStarProjections +import org.jetbrains.kotlin.backend.konan.ir.typeWithoutArguments +import org.jetbrains.kotlin.backend.konan.reportCompilationError +import org.jetbrains.kotlin.descriptors.* +import org.jetbrains.kotlin.ir.IrElement +import org.jetbrains.kotlin.ir.builders.* +import org.jetbrains.kotlin.ir.declarations.* +import org.jetbrains.kotlin.ir.declarations.impl.IrClassImpl +import org.jetbrains.kotlin.ir.declarations.impl.IrConstructorImpl +import org.jetbrains.kotlin.ir.declarations.impl.IrFunctionImpl +import org.jetbrains.kotlin.ir.descriptors.WrappedClassConstructorDescriptor +import org.jetbrains.kotlin.ir.descriptors.WrappedClassDescriptor +import org.jetbrains.kotlin.ir.descriptors.WrappedSimpleFunctionDescriptor +import org.jetbrains.kotlin.ir.expressions.impl.* +import org.jetbrains.kotlin.ir.symbols.* +import org.jetbrains.kotlin.ir.symbols.impl.IrClassSymbolImpl +import org.jetbrains.kotlin.ir.symbols.impl.IrConstructorSymbolImpl +import org.jetbrains.kotlin.ir.symbols.impl.IrSimpleFunctionSymbolImpl +import org.jetbrains.kotlin.ir.types.* +import org.jetbrains.kotlin.ir.util.* +import org.jetbrains.kotlin.ir.util.addChild +import org.jetbrains.kotlin.ir.visitors.IrElementVisitorVoid +import org.jetbrains.kotlin.ir.visitors.acceptChildrenVoid +import org.jetbrains.kotlin.load.kotlin.PackagePartClassUtils +import org.jetbrains.kotlin.name.FqName +import org.jetbrains.kotlin.name.Name +import org.jetbrains.kotlin.resolve.descriptorUtil.module +import org.jetbrains.kotlin.utils.addToStdlib.firstNotNullResult + +internal class TestProcessor (val context: Context) { + + object TEST_SUITE_CLASS: IrDeclarationOriginImpl("TEST_SUITE_CLASS") + object TEST_SUITE_GENERATED_MEMBER: IrDeclarationOriginImpl("TEST_SUITE_GENERATED_MEMBER") + + companion object { + val COMPANION_GETTER_NAME = Name.identifier("getCompanion") + val INSTANCE_GETTER_NAME = Name.identifier("createInstance") + + val IGNORE_FQ_NAME = FqName.fromSegments(listOf("kotlin", "test" , "Ignore")) + } + + private val symbols = context.ir.symbols + + private val baseClassSuite = symbols.baseClassSuite.owner + + private val topLevelSuiteNames = mutableSetOf() + + // region Useful extensions. + private var testSuiteCnt = 0 + private fun Name.synthesizeSuiteClassName() = identifier.synthesizeSuiteClassName() + private fun String.synthesizeSuiteClassName() = "$this\$test\$${testSuiteCnt++}".synthesizedName + + // IrFile always uses a forward slash as a directory separator. + private val IrFile.fileName + get() = name.substringAfterLast('/') + + private val IrFile.topLevelSuiteName: String + get() { + val packageFqName = fqName + val shortFileName = PackagePartClassUtils.getFilePartShortName(fileName) + return if (packageFqName.isRoot) shortFileName else "$packageFqName.$shortFileName" + } + + private fun MutableList.registerFunction( + function: IrFunction, + kinds: Collection>) = + kinds.forEach { (kind, ignored) -> + add(TestFunction(function, kind, ignored)) + } + + private fun MutableList.registerFunction( + function: IrFunction, + kind: FunctionKind, + ignored: Boolean + ) = add(TestFunction(function, kind, ignored)) + + private fun IrStatementsBuilder.generateFunctionRegistration( + receiver: IrValueDeclaration, + registerTestCase: IrFunction, + registerFunction: IrFunction, + functions: Collection) { + functions.forEach { + if (it.kind == FunctionKind.TEST) { + // Call registerTestCase(name: String, testFunction: () -> Unit) method. + +irCall(registerTestCase).apply { + dispatchReceiver = irGet(receiver) + putValueArgument(0, irString(it.function.name.identifier)) + putValueArgument(1, IrFunctionReferenceImpl( + it.function.startOffset, + it.function.endOffset, + registerTestCase.valueParameters[1].type, + it.function.symbol, + typeArgumentsCount = 0, + valueArgumentsCount = 0, + reflectionTarget = null)) + putValueArgument(2, irBoolean(it.ignored)) + } + } else { + // Call registerFunction(kind: TestFunctionKind, () -> Unit) method. + +irCall(registerFunction).apply { + dispatchReceiver = irGet(receiver) + val testKindEntry = it.kind.runtimeKind + putValueArgument(0, IrGetEnumValueImpl( + it.function.startOffset, + it.function.endOffset, + symbols.testFunctionKind.typeWithoutArguments, + testKindEntry) + ) + putValueArgument(1, IrFunctionReferenceImpl( + it.function.startOffset, + it.function.endOffset, + registerFunction.valueParameters[1].type, + it.function.symbol, + typeArgumentsCount = 0, + valueArgumentsCount = 0, + reflectionTarget = null)) + } + } + } + } + // endregion + + // region Classes for annotation collection. + internal enum class FunctionKind(annotationNameString: String, val runtimeKindString: String) { + TEST("kotlin.test.Test", ""), + BEFORE_TEST("kotlin.test.BeforeTest", "BEFORE_TEST"), + AFTER_TEST("kotlin.test.AfterTest", "AFTER_TEST"), + BEFORE_CLASS("kotlin.test.BeforeClass", "BEFORE_CLASS"), + AFTER_CLASS("kotlin.test.AfterClass", "AFTER_CLASS"); + + val annotationFqName = FqName(annotationNameString) + + companion object { + val INSTANCE_KINDS = listOf(TEST, BEFORE_TEST, AFTER_TEST) + val COMPANION_KINDS = listOf(BEFORE_CLASS, AFTER_CLASS) + } + } + + private val FunctionKind.runtimeKind: IrEnumEntrySymbol + get() = symbols.getTestFunctionKind(this) + + private fun IrType.isTestFunctionKind() = classifierOrNull == symbols.testFunctionKind + + private data class TestFunction( + val function: IrFunction, + val kind: FunctionKind, + val ignored: Boolean + ) + + private inner class TestClass(val ownerClass: IrClass) { + var companion: IrClass? = null + val functions = mutableListOf() + + fun registerFunction( + function: IrFunction, + kinds: Collection> + ) = functions.registerFunction(function, kinds) + + fun registerFunction(function: IrFunction, kind: FunctionKind, ignored: Boolean) = + functions.registerFunction(function, kind, ignored) + } + + private inner class AnnotationCollector(val irFile: IrFile) : IrElementVisitorVoid { + val testClasses = mutableMapOf() + val topLevelFunctions = mutableListOf() + + private fun MutableMap.getTestClass(key: IrClass) = + getOrPut(key) { TestClass(key) } + + override fun visitElement(element: IrElement) { + element.acceptChildrenVoid(this) + } + + fun IrFunctionSymbol.hasAnnotation(fqName: FqName) = descriptor.annotations.any { it.fqName == fqName } + + /** + * Checks if [this] or any of its parent functions has the annotation with the given [testAnnotation]. + * If [this] contains the given annotation, returns [this]. + * If one of the parent functions contains the given annotation, returns the [IrFunctionSymbol] for it. + * If the annotation isn't found or found only in interface methods, returns null. + */ + fun IrFunctionSymbol.findAnnotatedFunction(testAnnotation: FqName): IrFunctionSymbol? { + val owner = this.owner + val parent = owner.parent + if (parent is IrClass && parent.isInterface) { + return null + } + + if (hasAnnotation(testAnnotation)) { + return this + } + + return (owner as? IrSimpleFunction) + ?.overriddenSymbols + ?.firstNotNullResult { + it.findAnnotatedFunction(testAnnotation) + } + } + + fun registerClassFunction(irClass: IrClass, + function: IrFunction, + kinds: Collection>) { + + fun warn(msg: String) = context.reportWarning(msg, irFile, function) + + kinds.forEach { (kind, ignored) -> + val annotation = kind.annotationFqName + when (kind) { + in FunctionKind.INSTANCE_KINDS -> with(irClass) { + when { + isInner -> + warn("Annotation $annotation is not allowed for methods of an inner class") + + isAbstract() -> { + // We cannot create an abstract test class but it's allowed to mark its methods as + // tests because the class can be extended. So skip this case without warnings. + } + + isCompanion -> + warn("Annotation $annotation is not allowed for methods of a companion object") + + constructors.none { it.valueParameters.size == 0 } -> + warn("Test class has no default constructor: $fqNameForIrSerialization") + + else -> + testClasses.getTestClass(irClass).registerFunction(function, kind, ignored) + } + } + in FunctionKind.COMPANION_KINDS -> + when { + irClass.isCompanion -> { + val containingClass = irClass.parentAsClass + val testClass = testClasses.getTestClass(containingClass) + testClass.companion = irClass + testClass.registerFunction(function, kind, ignored) + } + + irClass.kind == ClassKind.OBJECT -> { + testClasses.getTestClass(irClass).registerFunction(function, kind, ignored) + } + + else -> warn("Annotation $annotation is only allowed for methods of an object " + + "(named or companion) or top level functions") + } + else -> throw IllegalStateException("Unreachable") + } + } + } + + fun IrFunction.checkFunctionSignature() { + // Test runner requires test functions to have the following signature: () -> Unit. + if (!returnType.isUnit()) { + context.reportCompilationError( + "Test function must return Unit: $fqNameForIrSerialization", irFile, this + ) + } + if (valueParameters.isNotEmpty()) { + context.reportCompilationError( + "Test function must have no arguments: $fqNameForIrSerialization", irFile, this + ) + } + } + + private fun warnAboutInheritedAnnotations( + kind: FunctionKind, + function: IrFunctionSymbol, + annotatedFunction: IrFunctionSymbol + ) { + if (function.owner != annotatedFunction.owner) { + context.reportWarning( + "Super method has a test annotation ${kind.annotationFqName} but the overriding method doesn't. " + + "Note that the overriding method will still be executed.", + irFile, + function.owner + ) + } + } + + private fun warnAboutLoneIgnore(functionSymbol: IrFunctionSymbol): Unit = with(functionSymbol) { + if (hasAnnotation(IGNORE_FQ_NAME) && !hasAnnotation(FunctionKind.TEST.annotationFqName)) { + context.reportWarning( + "Unused $IGNORE_FQ_NAME annotation (not paired with ${FunctionKind.TEST.annotationFqName}).", + irFile, + owner + ) + } + } + + // TODO: Use symbols instead of containingDeclaration when such information is available. + override fun visitFunction(declaration: IrFunction) { + val symbol = declaration.symbol + val parent = declaration.parent + + warnAboutLoneIgnore(symbol) + val kinds = FunctionKind.values().mapNotNull { kind -> + symbol.findAnnotatedFunction(kind.annotationFqName)?.let { annotatedFunction -> + warnAboutInheritedAnnotations(kind, symbol, annotatedFunction) + kind to (kind == FunctionKind.TEST && annotatedFunction.hasAnnotation(IGNORE_FQ_NAME)) + } + } + + if (kinds.isEmpty()) { + return + } + declaration.checkFunctionSignature() + + when (parent) { + is IrPackageFragment -> topLevelFunctions.registerFunction(declaration, kinds) + is IrClass -> registerClassFunction(parent, declaration, kinds) + else -> UnsupportedOperationException("Cannot create test function $declaration (defined in $parent") + } + } + } + // endregion + + //region Symbol and IR builders + + /** + * Builds a method in `[owner]` class with name `[getterName]` + * returning a reference to an object represented by `[objectSymbol]`. + */ + private fun buildObjectGetter(objectSymbol: IrClassSymbol, + owner: IrClass, + getterName: Name): IrSimpleFunction = WrappedSimpleFunctionDescriptor().let { descriptor -> + IrFunctionImpl( + owner.startOffset, owner.endOffset, + TEST_SUITE_GENERATED_MEMBER, + IrSimpleFunctionSymbolImpl(descriptor), + getterName, + DescriptorVisibilities.PROTECTED, + Modality.FINAL, + objectSymbol.typeWithStarProjections, + isInline = false, + isExternal = false, + isTailrec = false, + isSuspend = false, + isExpect = false, + isFakeOverride = false, + isOperator = false, + isInfix = false + ).apply { + descriptor.bind(this) + parent = owner + + val superFunction = baseClassSuite.simpleFunctions() + .single { it.name == getterName && it.valueParameters.isEmpty() } + + createDispatchReceiverParameter() + overriddenSymbols += superFunction.symbol + + body = context.createIrBuilder(symbol, symbol.owner.startOffset, symbol.owner.endOffset).irBlockBody { + +irReturn(irGetObjectValue(objectSymbol.typeWithoutArguments, objectSymbol) + ) + } + } + } + + /** + * Builds a method in `[testSuite]` class with name `[getterName]` + * returning a new instance of class referenced by [classSymbol]. + */ + private fun buildInstanceGetter(classSymbol: IrClassSymbol, + owner: IrClass, + getterName: Name): IrSimpleFunction = WrappedSimpleFunctionDescriptor().let { descriptor -> + IrFunctionImpl( + owner.startOffset, owner.endOffset, + TEST_SUITE_GENERATED_MEMBER, + IrSimpleFunctionSymbolImpl(descriptor), + getterName, + DescriptorVisibilities.PROTECTED, + Modality.FINAL, + classSymbol.typeWithStarProjections, + isInline = false, + isExternal = false, + isTailrec = false, + isSuspend = false, + isExpect = false, + isFakeOverride = false, + isOperator = false, + isInfix = false + ).apply { + descriptor.bind(this) + parent = owner + + val superFunction = baseClassSuite.simpleFunctions() + .single { it.name == getterName && it.valueParameters.isEmpty() } + + createDispatchReceiverParameter() + overriddenSymbols += superFunction.symbol + + body = context.createIrBuilder(symbol, symbol.owner.startOffset, symbol.owner.endOffset).irBlockBody { + val constructor = classSymbol.owner.constructors.single { it.valueParameters.isEmpty() } + +irReturn(irCall(constructor)) + } + } + } + + private val baseClassSuiteConstructor = baseClassSuite.constructors.single { + it.valueParameters.size == 2 + && it.valueParameters[0].type.isString() // name: String + && it.valueParameters[1].type.isBoolean() // ignored: Boolean + } + + /** + * Builds a constructor for a test suite class representing a test class (any class in the original IrFile with + * method(s) annotated with @Test). The test suite class is a subclass of ClassTestSuite + * where T is the test class. + */ + private fun buildClassSuiteConstructor(suiteName: String, + testClassType: IrType, + testCompanionType: IrType, + testSuite: IrClassSymbol, + owner: IrClass, + functions: Collection, + ignored: Boolean): IrConstructor = WrappedClassConstructorDescriptor().let { descriptor -> + IrConstructorImpl( + testSuite.owner.startOffset, testSuite.owner.endOffset, + TEST_SUITE_GENERATED_MEMBER, + IrConstructorSymbolImpl(descriptor), + Name.special(""), + DescriptorVisibilities.PUBLIC, + testSuite.typeWithStarProjections, + isInline = false, + isExternal = false, + isPrimary = true, + isExpect = false + ).apply { + descriptor.bind(this) + parent = owner + + fun IrClass.getFunction(name: String, predicate: (IrSimpleFunction) -> Boolean) = + simpleFunctions().single { it.name.asString() == name && predicate(it) } + + val registerTestCase = baseClassSuite.getFunction("registerTestCase") { + it.valueParameters.size == 3 + && it.valueParameters[0].type.isString() // name: String + && it.valueParameters[1].type.isFunction() // function: testClassType.() -> Unit + && it.valueParameters[2].type.isBoolean() // ignored: Boolean + } + val registerFunction = baseClassSuite.getFunction("registerFunction") { + it.valueParameters.size == 2 + && it.valueParameters[0].type.isTestFunctionKind() // kind: TestFunctionKind + && it.valueParameters[1].type.isFunction() // function: () -> Unit + } + + body = context.createIrBuilder(symbol, symbol.owner.startOffset, symbol.owner.endOffset).irBlockBody { + +irDelegatingConstructorCall(baseClassSuiteConstructor).apply { + putTypeArgument(0, testClassType) + putTypeArgument(1, testCompanionType) + + putValueArgument(0, irString(suiteName)) + putValueArgument(1, irBoolean(ignored)) + } + generateFunctionRegistration(testSuite.owner.thisReceiver!!, + registerTestCase, registerFunction, functions) + } + } + } + + private val IrClass.ignored: Boolean get() = annotations.hasAnnotation(IGNORE_FQ_NAME) + + /** + * Builds a test suite class representing a test class (any class in the original IrFile with method(s) + * annotated with @Test). The test suite class is a subclass of ClassTestSuite where T is the test class. + */ + private fun buildClassSuite(testClass: IrClass, + testCompanion: IrClass?, + functions: Collection): IrClass = WrappedClassDescriptor().let { descriptor -> + IrClassImpl( + testClass.startOffset, testClass.endOffset, + TEST_SUITE_CLASS, + IrClassSymbolImpl(descriptor), + testClass.name.synthesizeSuiteClassName(), + ClassKind.CLASS, + DescriptorVisibilities.PRIVATE, + Modality.FINAL, + isCompanion = false, + isInner = false, + isData = false, + isExternal = false, + isInline = false, + isExpect = false, + isFun = false + ).apply { + descriptor.bind(this) + createParameterDeclarations() + + val testClassType = testClass.defaultType + val testCompanionType = if (testClass.kind == ClassKind.OBJECT) { + testClassType + } else { + testCompanion?.defaultType ?: context.irBuiltIns.nothingType + } + + val constructor = buildClassSuiteConstructor( + testClass.fqNameForIrSerialization.toString(), testClassType, testCompanionType, + symbol, this, functions, testClass.ignored + ) + + val instanceGetter: IrFunction + val companionGetter: IrFunction? + + if (testClass.kind == ClassKind.OBJECT) { + instanceGetter = buildObjectGetter(testClass.symbol, this, INSTANCE_GETTER_NAME) + companionGetter = buildObjectGetter(testClass.symbol, this, COMPANION_GETTER_NAME) + } else { + instanceGetter = buildInstanceGetter(testClass.symbol, this, INSTANCE_GETTER_NAME) + companionGetter = testCompanion?.let { + buildObjectGetter(it.symbol, this, COMPANION_GETTER_NAME) + } + } + + declarations += constructor + declarations += instanceGetter + companionGetter?.let { declarations += it } + + superTypes += symbols.baseClassSuite.typeWith(listOf(testClassType, testCompanionType)) + addFakeOverrides(context.irBuiltIns) + } + } + //endregion + + // region IR generation methods + private fun generateClassSuite(irFile: IrFile, testClass: TestClass) = + with(buildClassSuite(testClass.ownerClass, testClass.companion,testClass.functions)) { + irFile.addChild(this) + val irConstructor = constructors.single() + context.createIrBuilder(irFile.symbol, testClass.ownerClass.startOffset, testClass.ownerClass.endOffset).run { + irFile.addTopLevelInitializer( + irCall(irConstructor), + this@TestProcessor.context, + threadLocal = true) + } + } + + /** Check if this fqName already used or not. */ + private fun checkSuiteName(irFile: IrFile, name: String): Boolean { + if (topLevelSuiteNames.contains(name)) { + context.reportCompilationError("Package '${irFile.fqName}' has top-level test " + + "functions in several files with the same name: '${irFile.fileName}'") + } + topLevelSuiteNames.add(name) + return true + } + + private val topLevelSuite = symbols.topLevelSuite.owner + private val topLevelSuiteConstructor = topLevelSuite.constructors.single { + it.valueParameters.size == 1 + && it.valueParameters[0].type.isString() + } + private val topLevelSuiteRegisterFunction = topLevelSuite.simpleFunctions().single { + it.name.asString() == "registerFunction" + && it.valueParameters.size == 2 + && it.valueParameters[0].type.isTestFunctionKind() + && it.valueParameters[1].type.isFunction() + } + private val topLevelSuiteRegisterTestCase = topLevelSuite.simpleFunctions().single { + it.name.asString() == "registerTestCase" + && it.valueParameters.size == 3 + && it.valueParameters[0].type.isString() + && it.valueParameters[1].type.isFunction() + && it.valueParameters[2].type.isBoolean() + } + + private fun generateTopLevelSuite(irFile: IrFile, functions: Collection) { + val builder = context.createIrBuilder(irFile.symbol) + val suiteName = irFile.topLevelSuiteName + if (!checkSuiteName(irFile, suiteName)) { + return + } + + // TODO: an awful hack, we make this initializer thread local, so that it doesn't freeze suite, + // and later on we could modify some suite's properties. This shall be redesigned. + irFile.addTopLevelInitializer(builder.irBlock { + val constructorCall = irCall(topLevelSuiteConstructor).apply { + putValueArgument(0, IrConstImpl.string(SYNTHETIC_OFFSET, SYNTHETIC_OFFSET, + context.irBuiltIns.stringType, suiteName)) + } + val testSuiteVal = irTemporary(constructorCall, "topLevelTestSuite") + generateFunctionRegistration(testSuiteVal, + topLevelSuiteRegisterTestCase, + topLevelSuiteRegisterFunction, + functions) + }, context, threadLocal = true) + } + + private fun createTestSuites(irFile: IrFile, annotationCollector: AnnotationCollector) { + annotationCollector.testClasses.filter { + it.value.functions.any { it.kind == FunctionKind.TEST } + }.forEach { _, testClass -> + generateClassSuite(irFile, testClass) + } + if (annotationCollector.topLevelFunctions.isNotEmpty()) { + generateTopLevelSuite(irFile, annotationCollector.topLevelFunctions) + } + } + // endregion + + private fun shouldProcessFile(irFile: IrFile): Boolean = irFile.packageFragmentDescriptor.module.let { + // Process test annotations in source libraries too. + it == context.moduleDescriptor || it in context.getIncludedLibraryDescriptors() + } + + fun process(irFile: IrFile) { + // TODO: uses descriptors. + if (!shouldProcessFile(irFile)) { + return + } + + val annotationCollector = AnnotationCollector(irFile) + irFile.acceptChildrenVoid(annotationCollector) + createTestSuites(irFile, annotationCollector) + } +} \ No newline at end of file diff --git a/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/lower/TypeOperatorLowering.kt b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/lower/TypeOperatorLowering.kt new file mode 100644 index 00000000000..f33aad224d5 --- /dev/null +++ b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/lower/TypeOperatorLowering.kt @@ -0,0 +1,112 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +package org.jetbrains.kotlin.backend.konan.lower + +import org.jetbrains.kotlin.backend.common.CommonBackendContext +import org.jetbrains.kotlin.backend.common.FileLoweringPass +import org.jetbrains.kotlin.backend.common.lower.* +import org.jetbrains.kotlin.backend.konan.ir.containsNull +import org.jetbrains.kotlin.backend.konan.ir.isSubtypeOf +import org.jetbrains.kotlin.ir.builders.* +import org.jetbrains.kotlin.ir.declarations.IrFile +import org.jetbrains.kotlin.ir.expressions.IrExpression +import org.jetbrains.kotlin.ir.expressions.IrTypeOperator +import org.jetbrains.kotlin.ir.expressions.IrTypeOperatorCall +import org.jetbrains.kotlin.ir.symbols.IrClassSymbol +import org.jetbrains.kotlin.ir.symbols.IrTypeParameterSymbol +import org.jetbrains.kotlin.ir.types.IrSimpleType +import org.jetbrains.kotlin.ir.types.IrType +import org.jetbrains.kotlin.ir.types.makeNotNull +import org.jetbrains.kotlin.ir.types.makeNullable +import org.jetbrains.kotlin.ir.util.irCall +import org.jetbrains.kotlin.ir.util.isSimpleTypeWithQuestionMark +import org.jetbrains.kotlin.ir.visitors.transformChildrenVoid + +internal class TypeOperatorLowering(val context: CommonBackendContext) : FileLoweringPass, IrBuildingTransformer(context) { + override fun lower(irFile: IrFile) { + irFile.transformChildren(this, null) + } + + private fun IrType.erasure(): IrType { + if (this !is IrSimpleType) return this + + return when (val classifier = classifier) { + is IrClassSymbol -> this + is IrTypeParameterSymbol -> { + val upperBound = classifier.owner.superTypes.firstOrNull() ?: + TODO("${classifier.descriptor} : ${classifier.descriptor.upperBounds}") + + if (this.hasQuestionMark) { + // `T?` + upperBound.erasure().makeNullable() + } else { + upperBound.erasure() + } + } + else -> TODO(classifier.toString()) + } + } + + private fun lowerCast(expression: IrTypeOperatorCall): IrExpression { + builder.at(expression) + val typeOperand = expression.typeOperand.erasure() + +// assert (!TypeUtils.hasNullableSuperType(typeOperand)) // So that `isNullable()` <=> `isMarkedNullable`. + + // TODO: consider the case when expression type is wrong e.g. due to generics-related unchecked casts. + + return when { + expression.argument.type.isSubtypeOf(typeOperand) -> expression.argument + + expression.argument.type.containsNull() -> { + with(builder) { + irLetS(expression.argument) { argument -> + irIfThenElse( + type = expression.type, + condition = irEqeqeq(irGet(argument.owner), irNull()), + + thenPart = if (typeOperand.isSimpleTypeWithQuestionMark) + irNull() + else + irCall(this@TypeOperatorLowering.context.ir.symbols.throwNullPointerException.owner), + + elsePart = irAs(irGet(argument.owner), typeOperand.makeNotNull()) + ) + } + } + } + + typeOperand.isSimpleTypeWithQuestionMark -> builder.irAs(expression.argument, typeOperand.makeNotNull()) + + typeOperand == expression.typeOperand -> expression + + else -> builder.irAs(expression.argument, typeOperand) + } + } + + private fun lowerSafeCast(expression: IrTypeOperatorCall): IrExpression { + val typeOperand = expression.typeOperand.erasure() + + return builder.irBlock(expression) { + +irLetS(expression.argument) { variable -> + irIfThenElse(expression.type, + condition = irIs(irGet(variable.owner), typeOperand), + thenPart = irImplicitCast(irGet(variable.owner), typeOperand), + elsePart = irNull()) + } + } + } + + override fun visitTypeOperator(expression: IrTypeOperatorCall): IrExpression { + expression.transformChildrenVoid(this) + + return when (expression.operator) { + IrTypeOperator.SAFE_CAST -> lowerSafeCast(expression) + IrTypeOperator.CAST -> lowerCast(expression) + else -> expression + } + } +} diff --git a/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/lower/VarargLowering.kt b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/lower/VarargLowering.kt new file mode 100644 index 00000000000..0652aea9149 --- /dev/null +++ b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/lower/VarargLowering.kt @@ -0,0 +1,265 @@ +/* + * Copyright 2010-2017 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.jetbrains.kotlin.backend.konan.lower + +import org.jetbrains.kotlin.backend.common.DeclarationContainerLoweringPass +import org.jetbrains.kotlin.backend.common.descriptors.synthesizedString +import org.jetbrains.kotlin.backend.common.ir.ir2string +import org.jetbrains.kotlin.backend.common.lower.createIrBuilder +import org.jetbrains.kotlin.backend.common.lower.irBlock +import org.jetbrains.kotlin.backend.konan.KonanBackendContext +import org.jetbrains.kotlin.builtins.PrimitiveType +import org.jetbrains.kotlin.builtins.UnsignedType +import org.jetbrains.kotlin.ir.IrElement +import org.jetbrains.kotlin.ir.builders.* +import org.jetbrains.kotlin.ir.declarations.* +import org.jetbrains.kotlin.ir.expressions.* +import org.jetbrains.kotlin.ir.expressions.impl.IrConstImpl +import org.jetbrains.kotlin.ir.expressions.impl.IrVarargImpl +import org.jetbrains.kotlin.ir.symbols.IrClassSymbol +import org.jetbrains.kotlin.ir.symbols.IrSymbol +import org.jetbrains.kotlin.ir.types.* +import org.jetbrains.kotlin.ir.util.* +import org.jetbrains.kotlin.ir.visitors.IrElementTransformerVoid +import org.jetbrains.kotlin.ir.visitors.transformChildrenVoid +import org.jetbrains.kotlin.util.OperatorNameConventions + +internal class VarargInjectionLowering constructor(val context: KonanBackendContext): DeclarationContainerLoweringPass { + override fun lower(irDeclarationContainer: IrDeclarationContainer) { + irDeclarationContainer.declarations.forEach{ + when (it) { + is IrField -> lower(it.symbol, it.initializer) + is IrFunction -> lower(it.symbol, it.body) + is IrProperty -> { + it.backingField?.let { field -> + lower(field.symbol, field) + } + it.getter?.let { getter -> + lower(getter.symbol, getter) + } + it.setter?.let { setter -> + lower(setter.symbol, setter) + } + } + } + } + } + + private fun lower(owner: IrSymbol, element: IrElement?) { + element?.transformChildrenVoid(object: IrElementTransformerVoid() { + val transformer = this + + private fun replaceEmptyParameterWithEmptyArray(expression: IrFunctionAccessExpression) { + val callee = expression.symbol.owner + log { "call of: ${callee.fqNameForIrSerialization}" } + context.createIrBuilder(owner, expression.startOffset, expression.endOffset).apply { + callee.valueParameters.forEach { + log { "varargElementType: ${it.varargElementType} expr: ${ir2string(expression.getValueArgument(it.index))}" } + } + callee.valueParameters + .filter { it.varargElementType != null && expression.getValueArgument(it.index) == null } + .forEach { + expression.putValueArgument( + it.index, + IrVarargImpl( + startOffset = startOffset, + endOffset = endOffset, + type = it.type, + varargElementType = it.varargElementType!! + ) + ) + } + } + expression.transformChildrenVoid(this) + } + + override fun visitFunctionAccess(expression: IrFunctionAccessExpression): IrExpression { + replaceEmptyParameterWithEmptyArray(expression) + return expression + } + + override fun visitVararg(expression: IrVararg): IrExpression { + expression.transformChildrenVoid(transformer) + + val hasSpreadElement = hasSpreadElement(expression) + val irBuilder = context.createIrBuilder(owner, expression.startOffset, expression.endOffset) + return irBuilder.irBlock(expression, null, expression.type) { + val type = expression.varargElementType + log { "$expression: array type:$type, is array of primitives ${!expression.type.isArray()}" } + val arrayHandle = arrayType(expression.type) + + val vars = expression.elements.map { + it to irTemporary( + (it as? IrSpreadElement)?.expression ?: it as IrExpression, + "elem".synthesizedString, + isMutable = true + ) + }.toMap() + val arraySize = calculateArraySize(arrayHandle, hasSpreadElement, scope, expression, vars) + val array = arrayHandle.createArray(this, expression.varargElementType, arraySize) + + val arrayTmpVariable = irTemporary(array, "array".synthesizedString, isMutable = true) + lateinit var indexTmpVariable: IrVariable + if (hasSpreadElement) + indexTmpVariable = irTemporary(kIntZero, "index".synthesizedString, isMutable = true) + expression.elements.forEachIndexed { i, element -> + irBuilder.at(element.startOffset, element.endOffset) + log { "element:$i> ${ir2string(element)}" } + val dst = vars[element]!! + if (element !is IrSpreadElement) { + +irCall(arrayHandle.setMethodSymbol.owner).apply { + dispatchReceiver = irGet(arrayTmpVariable) + putValueArgument(0, if (hasSpreadElement) irGet(indexTmpVariable) else irConstInt(i)) + putValueArgument(1, irGet(dst)) + } + if (hasSpreadElement) + +incrementVariable(indexTmpVariable, kIntOne) + } else { + val arraySizeVariable = irTemporary(irArraySize(arrayHandle, irGet(dst)), "length".synthesizedString) + +irCall(arrayHandle.copyIntoSymbol.owner).apply { + extensionReceiver = irGet(dst) + putValueArgument(0, irGet(arrayTmpVariable)) /* destination */ + putValueArgument(1, irGet(indexTmpVariable)) /* destinationOffset */ + putValueArgument(2, kIntZero) /* startIndex */ + putValueArgument(3, irGet(arraySizeVariable)) /* endIndex */ + } + +incrementVariable(indexTmpVariable, irGet(arraySizeVariable)) + log { "element:$i:spread element> ${ir2string(element.expression)}" } + } + } + +irGet(arrayTmpVariable) + } + } + }) + } + + private val symbols = context.ir.symbols + private val intPlusInt = symbols.getBinaryOperator( + OperatorNameConventions.PLUS, context.irBuiltIns.intType, context.irBuiltIns.intType + ).owner + + private fun arrayType(type: IrType): ArrayHandle { + val arrayClass = type.classifierOrFail + return arrayToHandle[arrayClass] ?: error(arrayClass.descriptor) + } + + private fun IrBuilderWithScope.intPlus() = irCall(intPlusInt) + private fun IrBuilderWithScope.increment(expression: IrExpression, value: IrExpression): IrExpression { + return intPlus().apply { + dispatchReceiver = expression + putValueArgument(0, value) + } + } + + private fun IrBuilderWithScope.incrementVariable(variable: IrVariable, value: IrExpression): IrExpression { + return irSet(variable.symbol, intPlus().apply { + dispatchReceiver = irGet(variable) + putValueArgument(0, value) + }) + } + private fun calculateArraySize(arrayHandle: ArrayHandle, hasSpreadElement: Boolean, scope:Scope, expression: IrVararg, vars: Map): IrExpression { + context.createIrBuilder(scope.scopeOwnerSymbol, expression.startOffset, expression.endOffset).run { + if (!hasSpreadElement) + return irConstInt(expression.elements.size) + val notSpreadElementCount = expression.elements.filter { it !is IrSpreadElement}.size + val initialValue = irConstInt(notSpreadElementCount) as IrExpression + return vars.filter{it.key is IrSpreadElement}.toList().fold( initial = initialValue) { result, it -> + val arraySize = irArraySize(arrayHandle, irGet(it.second)) + increment(result, arraySize) + } + } + } + + private fun IrBuilderWithScope.irArraySize(arrayHandle: ArrayHandle, expression: IrExpression): IrExpression { + val arraySize = irCall(arrayHandle.sizeGetterSymbol.owner).apply { + dispatchReceiver = expression + } + return arraySize + } + + + private fun hasSpreadElement(expression: IrVararg?) = expression?.elements?.any { it is IrSpreadElement }?:false + + private fun log(msg:() -> String) { + context.log { "VARARG-INJECTOR: ${msg()}" } + } + + abstract inner class ArrayHandle(val arraySymbol: IrClassSymbol) { + val setMethodSymbol = arraySymbol.functions.single { it.descriptor.name == OperatorNameConventions.SET } + val sizeGetterSymbol = arraySymbol.getPropertyGetter("size")!! + val copyIntoSymbol = symbols.copyInto[arraySymbol.descriptor]!! + protected val singleParameterConstructor = + arraySymbol.owner.constructors.find { it.valueParameters.size == 1 }!! + + abstract fun createArray(builder: IrBuilderWithScope, elementType: IrType, size: IrExpression): IrExpression + } + + inner class ReferenceArrayHandle : ArrayHandle(symbols.array) { + override fun createArray(builder: IrBuilderWithScope, elementType: IrType, size: IrExpression): IrExpression { + return builder.irCall(singleParameterConstructor).apply { + putTypeArgument(0, elementType) + putValueArgument(0, size) + } + } + } + + inner class PrimitiveArrayHandle(primitiveType: PrimitiveType) + : ArrayHandle(symbols.primitiveArrays[primitiveType]!!) { + + override fun createArray(builder: IrBuilderWithScope, elementType: IrType, size: IrExpression): IrExpression { + return builder.irCall(singleParameterConstructor).apply { + putValueArgument(0, size) + } + } + } + + inner class UnsignedArrayHandle( + arraySymbol: IrClassSymbol, + private val wrappedArrayHandle: PrimitiveArrayHandle + ) : ArrayHandle(arraySymbol) { + + override fun createArray(builder: IrBuilderWithScope, elementType: IrType, size: IrExpression): IrExpression { + val wrappedArray = wrappedArrayHandle.createArray(builder, elementType, size) + return builder.irCall(singleParameterConstructor).apply { + putValueArgument(0, wrappedArray) + } + } + } + + private val primitiveArrayHandles = PrimitiveType.values().associate { it to PrimitiveArrayHandle(it) } + + private val unsignedArrayHandles = UnsignedType.values().mapNotNull { unsignedType -> + symbols.unsignedArrays[unsignedType]?.let { + val primitiveType = when (unsignedType) { + UnsignedType.UBYTE -> PrimitiveType.BYTE + UnsignedType.USHORT -> PrimitiveType.SHORT + UnsignedType.UINT -> PrimitiveType.INT + UnsignedType.ULONG -> PrimitiveType.LONG + } + UnsignedArrayHandle(it, primitiveArrayHandles[primitiveType]!!) + } + } + + val arrayToHandle = + (primitiveArrayHandles.values + unsignedArrayHandles + ReferenceArrayHandle()).associateBy { it.arraySymbol } + +} + +private fun IrBuilderWithScope.irConstInt(value: Int): IrConst = + IrConstImpl.int(startOffset, endOffset, context.irBuiltIns.intType, value) +private val IrBuilderWithScope.kIntZero get() = irConstInt(0) +private val IrBuilderWithScope.kIntOne get() = irConstInt(1) diff --git a/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/lower/matchers/IrCallMatcher.kt b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/lower/matchers/IrCallMatcher.kt new file mode 100644 index 00000000000..fd72223ee9c --- /dev/null +++ b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/lower/matchers/IrCallMatcher.kt @@ -0,0 +1,66 @@ +package org.jetbrains.kotlin.backend.konan.lower.matchers + +import org.jetbrains.kotlin.ir.expressions.IrCall +import org.jetbrains.kotlin.ir.expressions.IrExpression +import org.jetbrains.kotlin.ir.expressions.IrStatementOrigin + + +internal interface IrCallMatcher : (IrCall) -> Boolean + +/** + * IrCallMatcher that puts restrictions only on its callee. + */ +internal class SimpleCalleeMatcher( + restrictions: IrFunctionMatcherContainer.() -> Unit +) : IrCallMatcher { + + private val calleeRestriction: IrFunctionMatcher + = createIrFunctionRestrictions(restrictions) + + override fun invoke(call: IrCall) = calleeRestriction(call.symbol.owner) +} + +internal class IrCallExtensionReceiverMatcher( + val restriction: (IrExpression?) -> Boolean +) : IrCallMatcher { + override fun invoke(call: IrCall) = restriction(call.extensionReceiver) +} + +internal class IrCallDispatchReceiverMatcher( + val restriction: (IrExpression?) -> Boolean +) : IrCallMatcher { + override fun invoke(call: IrCall) = restriction(call.dispatchReceiver) +} + +internal class IrCallOriginMatcher( + val restriction: (IrStatementOrigin?) -> Boolean +) : IrCallMatcher { + override fun invoke(call: IrCall) = restriction(call.origin) +} + +internal open class IrCallMatcherContainer : IrCallMatcher { + + private val matchers = mutableListOf() + + fun add(matcher: IrCallMatcher) { + matchers += matcher + } + + fun extensionReceiver(restriction: (IrExpression?) -> Boolean) = + add(IrCallExtensionReceiverMatcher(restriction)) + + fun origin(restriction: (IrStatementOrigin?) -> Boolean) = + add(IrCallOriginMatcher(restriction)) + + fun callee(restrictions: IrFunctionMatcherContainer.() -> Unit) { + add(SimpleCalleeMatcher(restrictions)) + } + + fun dispatchReceiver(restriction: (IrExpression?) -> Boolean) = + add(IrCallDispatchReceiverMatcher(restriction)) + + override fun invoke(call: IrCall) = matchers.all { it(call) } +} + +internal fun createIrCallMatcher(restrictions: IrCallMatcherContainer.() -> Unit) = + IrCallMatcherContainer().apply(restrictions) \ No newline at end of file diff --git a/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/lower/matchers/IrFunctionMatcher.kt b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/lower/matchers/IrFunctionMatcher.kt new file mode 100644 index 00000000000..764feeb3332 --- /dev/null +++ b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/lower/matchers/IrFunctionMatcher.kt @@ -0,0 +1,96 @@ +package org.jetbrains.kotlin.backend.konan.lower.matchers + +import org.jetbrains.kotlin.ir.declarations.IrFunction +import org.jetbrains.kotlin.ir.declarations.IrValueParameter +import org.jetbrains.kotlin.ir.symbols.IrClassSymbol +import org.jetbrains.kotlin.ir.types.classifierOrNull +import org.jetbrains.kotlin.ir.util.fqNameForIrSerialization +import org.jetbrains.kotlin.name.FqName + +internal interface IrFunctionMatcher : (IrFunction) -> Boolean + +internal class ParameterMatcher( + val index: Int, + val restriction: (IrValueParameter) -> Boolean +) : IrFunctionMatcher { + + override fun invoke(function: IrFunction): Boolean { + val params = function.valueParameters + return params.size > index && restriction(params[index]) + } +} + +internal class DispatchReceiverMatcher( + val restriction: (IrValueParameter?) -> Boolean +) : IrFunctionMatcher { + + override fun invoke(function: IrFunction): Boolean { + return restriction(function.dispatchReceiverParameter) + } +} + +internal class ExtensionReceiverMatcher( + val restriction: (IrValueParameter?) -> Boolean +) : IrFunctionMatcher { + + override fun invoke(function: IrFunction): Boolean { + return restriction(function.extensionReceiverParameter) + } +} + +internal class ParameterCountMatcher( + val restriction: (Int) -> Boolean +) : IrFunctionMatcher { + + override fun invoke(function: IrFunction): Boolean { + return restriction(function.valueParameters.size) + } +} + +internal class FqNameMatcher( + val restriction: (FqName) -> Boolean +) : IrFunctionMatcher { + + override fun invoke(function: IrFunction): Boolean { + return restriction(function.fqNameForIrSerialization) + } +} + +internal open class IrFunctionMatcherContainer : IrFunctionMatcher { + private val restrictions = mutableListOf() + + fun add(restriction: IrFunctionMatcher) { + restrictions += restriction + } + + fun fqName(restriction: (FqName) -> Boolean) = + add(FqNameMatcher(restriction)) + + fun parameterCount(restriction: (Int) -> Boolean) = + add(ParameterCountMatcher(restriction)) + + fun extensionReceiver(restriction: (IrValueParameter?) -> Boolean) = + add(ExtensionReceiverMatcher(restriction)) + + fun dispatchReceiver(restriction: (IrValueParameter?) -> Boolean) = + add(DispatchReceiverMatcher(restriction)) + + fun parameter(index: Int, restriction: (IrValueParameter) -> Boolean) = + add(ParameterMatcher(index, restriction)) + + override fun invoke(function: IrFunction) = restrictions.all { it(function) } +} + +internal fun createIrFunctionRestrictions(restrictions: IrFunctionMatcherContainer.() -> Unit) = + IrFunctionMatcherContainer().apply(restrictions) + +internal fun IrFunctionMatcherContainer.singleArgumentExtension( + fqName: FqName, + classes: Collection +): IrFunctionMatcherContainer { + extensionReceiver { it != null && it.type.classifierOrNull in classes } + parameterCount { it == 1 } + fqName { it == fqName } + return this +} + diff --git a/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/objcexport/CustomTypeMapper.kt b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/objcexport/CustomTypeMapper.kt new file mode 100644 index 00000000000..dab24ccc86a --- /dev/null +++ b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/objcexport/CustomTypeMapper.kt @@ -0,0 +1,151 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +package org.jetbrains.kotlin.backend.konan.objcexport + +import org.jetbrains.kotlin.builtins.KotlinBuiltIns +import org.jetbrains.kotlin.builtins.StandardNames +import org.jetbrains.kotlin.builtins.functions.FunctionClassDescriptor +import org.jetbrains.kotlin.builtins.functions.FunctionClassKind +import org.jetbrains.kotlin.builtins.getFunctionalClassKind +import org.jetbrains.kotlin.descriptors.ClassDescriptor +import org.jetbrains.kotlin.name.ClassId +import org.jetbrains.kotlin.name.FqName +import org.jetbrains.kotlin.resolve.descriptorUtil.classId +import org.jetbrains.kotlin.types.KotlinType +import org.jetbrains.kotlin.types.TypeUtils + +internal fun ClassDescriptor.isMappedFunctionClass() = + this.getFunctionalClassKind() == FunctionClassKind.Function && + // Type parameters include return type. + declaredTypeParameters.size - 1 < CustomTypeMappers.functionTypeMappersArityLimit + +internal interface CustomTypeMapper { + val mappedClassId: ClassId + fun mapType(mappedSuperType: KotlinType, translator: ObjCExportTranslatorImpl, objCExportScope: ObjCExportScope): ObjCNonNullReferenceType +} + +internal object CustomTypeMappers { + /** + * Custom type mappers. + * + * Don't forget to update [hiddenTypes] after adding new one. + */ + private val predefined: Map = with(StandardNames.FqNames) { + val result = mutableListOf() + + result += Collection(list, "NSArray") + result += Collection(mutableList, "NSMutableArray") + result += Collection(set, "NSSet") + result += Collection(mutableSet, { namer.mutableSetName.objCName }) + result += Collection(map, "NSDictionary") + result += Collection(mutableMap, { namer.mutableMapName.objCName }) + + NSNumberKind.values().forEach { + // TODO: NSNumber seem to have different equality semantics. + val classId = it.mappedKotlinClassId + if (classId != null) { + result += Simple(classId, { namer.numberBoxName(classId).objCName }) + } + + } + + result += Simple(ClassId.topLevel(string.toSafe()), "NSString") + + result.associateBy { it.mappedClassId } + } + + internal val functionTypeMappersArityLimit = 33 // not including, i.e. [0..33) + + fun hasMapper(descriptor: ClassDescriptor): Boolean { + // Should be equivalent to `getMapper(descriptor) != null`. + if (descriptor.classId in predefined) return true + if (descriptor.isMappedFunctionClass()) return true + return false + } + + fun getMapper(descriptor: ClassDescriptor): CustomTypeMapper? { + val classId = descriptor.classId + + predefined[classId]?.let { return it } + + if (descriptor.isMappedFunctionClass()) { + // TODO: somewhat hacky, consider using FunctionClassDescriptor.arity later. + val arity = descriptor.declaredTypeParameters.size - 1 // Type parameters include return type. + assert(classId == StandardNames.getFunctionClassId(arity)) + return Function(arity) + } + + return null + } + + /** + * Types to be "hidden" during mapping, i.e. represented as `id`. + * + * Currently contains super types of classes handled by custom type mappers. + * Note: can be generated programmatically, but requires stdlib in this case. + */ + val hiddenTypes: Set = listOf( + "kotlin.Any", + "kotlin.CharSequence", + "kotlin.Comparable", + "kotlin.Function", + "kotlin.Number", + "kotlin.collections.Collection", + "kotlin.collections.Iterable", + "kotlin.collections.MutableCollection", + "kotlin.collections.MutableIterable" + ).map { ClassId.topLevel(FqName(it)) }.toSet() + + private class Simple( + override val mappedClassId: ClassId, + private val getObjCClassName: ObjCExportTranslatorImpl.() -> String + ) : CustomTypeMapper { + + constructor( + mappedClassId: ClassId, + objCClassName: String + ) : this(mappedClassId, { objCClassName }) + + override fun mapType(mappedSuperType: KotlinType, translator: ObjCExportTranslatorImpl, objCExportScope: ObjCExportScope): ObjCNonNullReferenceType = + ObjCClassType(translator.getObjCClassName()) + } + + private class Collection( + mappedClassFqName: FqName, + private val getObjCClassName: ObjCExportTranslatorImpl.() -> String + ) : CustomTypeMapper { + + constructor( + mappedClassFqName: FqName, + objCClassName: String + ) : this(mappedClassFqName, { objCClassName }) + + override val mappedClassId = ClassId.topLevel(mappedClassFqName) + + override fun mapType(mappedSuperType: KotlinType, translator: ObjCExportTranslatorImpl, objCExportScope: ObjCExportScope): ObjCNonNullReferenceType { + val typeArguments = mappedSuperType.arguments.map { + val argument = it.type + if (TypeUtils.isNullableType(argument)) { + // Kotlin `null` keys and values are represented as `NSNull` singleton. + ObjCIdType + } else { + translator.mapReferenceTypeIgnoringNullability(argument, objCExportScope) + } + } + + return ObjCClassType(translator.getObjCClassName(), typeArguments) + } + } + + private class Function(private val parameterCount: Int) : CustomTypeMapper { + override val mappedClassId: ClassId + get() = StandardNames.getFunctionClassId(parameterCount) + + override fun mapType(mappedSuperType: KotlinType, translator: ObjCExportTranslatorImpl, objCExportScope: ObjCExportScope): ObjCNonNullReferenceType { + return translator.mapFunctionTypeIgnoringNullability(mappedSuperType, objCExportScope, returnsVoid = false) + } + } +} diff --git a/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/objcexport/MethodBridge.kt b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/objcexport/MethodBridge.kt new file mode 100644 index 00000000000..b4e3e82a097 --- /dev/null +++ b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/objcexport/MethodBridge.kt @@ -0,0 +1,121 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +package org.jetbrains.kotlin.backend.konan.objcexport + +import org.jetbrains.kotlin.backend.common.descriptors.allParameters +import org.jetbrains.kotlin.backend.common.ir.allParameters +import org.jetbrains.kotlin.descriptors.FunctionDescriptor +import org.jetbrains.kotlin.descriptors.ParameterDescriptor +import org.jetbrains.kotlin.ir.declarations.IrFunction +import org.jetbrains.kotlin.ir.declarations.IrValueParameter + +internal sealed class TypeBridge +internal object ReferenceBridge : TypeBridge() + +internal data class BlockPointerBridge( + val numberOfParameters: Int, + val returnsVoid: Boolean +) : TypeBridge() + +internal data class ValueTypeBridge(val objCValueType: ObjCValueType) : TypeBridge() + +internal sealed class MethodBridgeParameter + +internal sealed class MethodBridgeReceiver : MethodBridgeParameter() { + object Static : MethodBridgeReceiver() + object Factory : MethodBridgeReceiver() + object Instance : MethodBridgeReceiver() +} + +internal object MethodBridgeSelector : MethodBridgeParameter() + +internal sealed class MethodBridgeValueParameter : MethodBridgeParameter() { + data class Mapped(val bridge: TypeBridge) : MethodBridgeValueParameter() + object ErrorOutParameter : MethodBridgeValueParameter() + object SuspendCompletion : MethodBridgeValueParameter() +} + +internal data class MethodBridge( + val returnBridge: ReturnValue, + val receiver: MethodBridgeReceiver, + val valueParameters: List +) { + + sealed class ReturnValue { + object Void : ReturnValue() + object HashCode : ReturnValue() + data class Mapped(val bridge: TypeBridge) : ReturnValue() + sealed class Instance : ReturnValue() { + object InitResult : Instance() + object FactoryResult : Instance() + } + + sealed class WithError : ReturnValue() { + object Success : WithError() + data class ZeroForError(val successBridge: ReturnValue, val successMayBeZero: Boolean) : WithError() + } + + object Suspend : ReturnValue() + } + + val paramBridges: List = + listOf(receiver) + MethodBridgeSelector + valueParameters + + // TODO: it is not exactly true in potential future cases. + val isInstance: Boolean get() = when (receiver) { + MethodBridgeReceiver.Static, + MethodBridgeReceiver.Factory -> false + + MethodBridgeReceiver.Instance -> true + } + + val returnsError: Boolean + get() = returnBridge is ReturnValue.WithError +} + +internal fun MethodBridge.valueParametersAssociated( + descriptor: FunctionDescriptor +): List> { + val kotlinParameters = descriptor.allParameters.iterator() + val skipFirstKotlinParameter = when (this.receiver) { + MethodBridgeReceiver.Static -> false + MethodBridgeReceiver.Factory, MethodBridgeReceiver.Instance -> true + } + if (skipFirstKotlinParameter) { + kotlinParameters.next() + } + + return this.valueParameters.map { + when (it) { + is MethodBridgeValueParameter.Mapped -> it to kotlinParameters.next() + + MethodBridgeValueParameter.SuspendCompletion, + is MethodBridgeValueParameter.ErrorOutParameter -> it to null + } + }.also { assert(!kotlinParameters.hasNext()) } +} + +internal fun MethodBridge.parametersAssociated( + irFunction: IrFunction +): List> { + val kotlinParameters = irFunction.allParameters.iterator() + + return this.paramBridges.map { + when (it) { + is MethodBridgeValueParameter.Mapped, MethodBridgeReceiver.Instance -> + it to kotlinParameters.next() + + MethodBridgeValueParameter.SuspendCompletion, + MethodBridgeReceiver.Static, MethodBridgeSelector, MethodBridgeValueParameter.ErrorOutParameter -> + it to null + + MethodBridgeReceiver.Factory -> { + kotlinParameters.next() + it to null + } + } + }.also { assert(!kotlinParameters.hasNext()) } +} diff --git a/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/objcexport/ObjCExport.kt b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/objcexport/ObjCExport.kt new file mode 100644 index 00000000000..0a852dd8a67 --- /dev/null +++ b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/objcexport/ObjCExport.kt @@ -0,0 +1,318 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +package org.jetbrains.kotlin.backend.konan.objcexport + +import org.jetbrains.kotlin.backend.konan.* +import org.jetbrains.kotlin.backend.konan.Context +import org.jetbrains.kotlin.backend.konan.descriptors.getPackageFragments +import org.jetbrains.kotlin.backend.konan.descriptors.isInterface +import org.jetbrains.kotlin.backend.konan.getExportedDependencies +import org.jetbrains.kotlin.backend.konan.llvm.CodeGenerator +import org.jetbrains.kotlin.backend.konan.llvm.objcexport.ObjCExportBlockCodeGenerator +import org.jetbrains.kotlin.backend.konan.llvm.objcexport.ObjCExportCodeGenerator +import org.jetbrains.kotlin.descriptors.CallableMemberDescriptor +import org.jetbrains.kotlin.descriptors.ClassDescriptor +import org.jetbrains.kotlin.descriptors.SourceFile +import org.jetbrains.kotlin.ir.util.SymbolTable +import org.jetbrains.kotlin.konan.exec.Command +import org.jetbrains.kotlin.konan.file.File +import org.jetbrains.kotlin.konan.file.createTempFile +import org.jetbrains.kotlin.konan.target.* +import org.jetbrains.kotlin.name.FqName +import org.jetbrains.kotlin.name.Name +import org.jetbrains.kotlin.name.isSubpackageOf + +internal class ObjCExportedInterface( + val generatedClasses: Set, + val categoryMembers: Map>, + val topLevel: Map>, + val headerLines: List, + val namer: ObjCExportNamer, + val mapper: ObjCExportMapper +) + +internal class ObjCExport(val context: Context, symbolTable: SymbolTable) { + private val target get() = context.config.target + + private val exportedInterface = produceInterface() + private val codeSpec = exportedInterface?.createCodeSpec(symbolTable) + + private fun produceInterface(): ObjCExportedInterface? { + if (!target.family.isAppleFamily) return null + + if (!context.config.produce.isFinalBinary) return null + + // TODO: emit RTTI to the same modules as classes belong to. + // Not possible yet, since ObjCExport translates the entire "world" API at once + // and can't do this per-module, e.g. due to global name conflict resolution. + + val produceFramework = context.config.produce == CompilerOutputKind.FRAMEWORK + + return if (produceFramework) { + val mapper = ObjCExportMapper(context.frontendServices.deprecationResolver) + val moduleDescriptors = listOf(context.moduleDescriptor) + context.getExportedDependencies() + val objcGenerics = context.configuration.getBoolean(KonanConfigKeys.OBJC_GENERICS) + val namer = ObjCExportNamerImpl( + moduleDescriptors.toSet(), + context.moduleDescriptor.builtIns, + mapper, + context.moduleDescriptor.namePrefix, + local = false, + objcGenerics = objcGenerics + ) + val headerGenerator = ObjCExportHeaderGeneratorImpl(context, moduleDescriptors, mapper, namer, objcGenerics) + headerGenerator.translateModule() + headerGenerator.buildInterface() + } else { + null + } + } + + lateinit var namer: ObjCExportNamer + + internal fun generate(codegen: CodeGenerator) { + if (!target.family.isAppleFamily) return + + if (context.producedLlvmModuleContainsStdlib) { + ObjCExportBlockCodeGenerator(codegen).generate() + } + + if (!context.config.produce.isFinalBinary) return // TODO: emit RTTI to the same modules as classes belong to. + + val mapper = exportedInterface?.mapper ?: ObjCExportMapper() + namer = exportedInterface?.namer ?: ObjCExportNamerImpl( + setOf(codegen.context.moduleDescriptor), + context.moduleDescriptor.builtIns, + mapper, + context.moduleDescriptor.namePrefix, + local = false + ) + + val objCCodeGenerator = ObjCExportCodeGenerator(codegen, namer, mapper) + + if (exportedInterface != null) { + produceFrameworkSpecific(exportedInterface.headerLines) + + objCCodeGenerator.generate(codeSpec!!) + + exportedInterface.generateWorkaroundForSwiftSR10177() + } + + objCCodeGenerator.emitRtti() + objCCodeGenerator.dispose() + } + + private fun produceFrameworkSpecific(headerLines: List) { + val framework = File(context.config.outputFile) + val frameworkContents = when(target.family) { + Family.IOS, + Family.WATCHOS, + Family.TVOS -> framework + Family.OSX -> framework.child("Versions/A") + else -> error(target) + } + + val headers = frameworkContents.child("Headers") + + val frameworkName = framework.name.removeSuffix(".framework") + val headerName = frameworkName + ".h" + val header = headers.child(headerName) + headers.mkdirs() + header.writeLines(headerLines) + + val modules = frameworkContents.child("Modules") + modules.mkdirs() + + val moduleMap = """ + |framework module $frameworkName { + | umbrella header "$headerName" + | + | export * + | module * { export * } + |} + """.trimMargin() + + modules.child("module.modulemap").writeBytes(moduleMap.toByteArray()) + + emitInfoPlist(frameworkContents, frameworkName) + + if (target == KonanTarget.MACOS_X64) { + framework.child("Versions/Current").createAsSymlink("A") + for (child in listOf(frameworkName, "Headers", "Modules", "Resources")) { + framework.child(child).createAsSymlink("Versions/Current/$child") + } + } + } + + private fun emitInfoPlist(frameworkContents: File, name: String) { + val directory = when (target.family) { + Family.IOS, + Family.WATCHOS, + Family.TVOS -> frameworkContents + Family.OSX -> frameworkContents.child("Resources").also { it.mkdirs() } + else -> error(target) + } + + val file = directory.child("Info.plist") + val pkg = guessMainPackage() // TODO: consider showing warning if it is root. + val bundleId = pkg.child(Name.identifier(name)).asString() + + val platform = when (target) { + KonanTarget.IOS_ARM32, KonanTarget.IOS_ARM64 -> "iPhoneOS" + KonanTarget.IOS_X64 -> "iPhoneSimulator" + KonanTarget.TVOS_ARM64 -> "AppleTVOS" + KonanTarget.TVOS_X64 -> "AppleTVSimulator" + KonanTarget.MACOS_X64 -> "MacOSX" + KonanTarget.WATCHOS_ARM32, KonanTarget.WATCHOS_ARM64 -> "WatchOS" + KonanTarget.WATCHOS_X86, KonanTarget.WATCHOS_X64 -> "WatchSimulator" + else -> error(target) + } + val properties = context.config.platform.configurables as AppleConfigurables + val minimumOsVersion = properties.osVersionMin + + val contents = StringBuilder() + contents.append(""" + + + + + CFBundleExecutable + $name + CFBundleIdentifier + $bundleId + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + $name + CFBundlePackageType + FMWK + CFBundleShortVersionString + 1.0 + CFBundleSupportedPlatforms + + $platform + + CFBundleVersion + 1 + + """.trimIndent()) + + fun addUiDeviceFamilies(vararg values: Int) { + val xmlValues = values.joinToString(separator = "\n") { + " $it" + } + contents.append(""" + | MinimumOSVersion + | $minimumOsVersion + | UIDeviceFamily + | + |$xmlValues + | + + """.trimMargin()) + } + + // UIDeviceFamily mapping: + // 1 - iPhone + // 2 - iPad + // 3 - AppleTV + // 4 - Apple Watch + when (target.family) { + Family.IOS -> addUiDeviceFamilies(1, 2) + Family.TVOS -> addUiDeviceFamilies(3) + Family.WATCHOS -> addUiDeviceFamilies(4) + else -> {} + } + + if (target == KonanTarget.IOS_ARM64) { + contents.append(""" + | UIRequiredDeviceCapabilities + | + | arm64 + | + + """.trimMargin() + ) + } + + if (target == KonanTarget.IOS_ARM32) { + contents.append(""" + | UIRequiredDeviceCapabilities + | + | armv7 + | + + """.trimMargin() + ) + } + + contents.append(""" + + + """.trimIndent()) + + // TODO: Xcode also add some number of DT* keys. + + file.writeBytes(contents.toString().toByteArray()) + } + + // See https://bugs.swift.org/browse/SR-10177 + private fun ObjCExportedInterface.generateWorkaroundForSwiftSR10177() { + // Code for all protocols from the header should get into the binary. + // Objective-C protocols ABI is complicated (consider e.g. undocumented extended type encoding), + // so the easiest way to achieve this (quickly) is to compile a stub by clang. + + val protocolsStub = listOf( + "__attribute__((used)) static void __workaroundSwiftSR10177() {", + buildString { + append(" ") + generatedClasses.forEach { + if (it.isInterface) { + val protocolName = namer.getClassOrProtocolName(it).objCName + append("@protocol($protocolName); ") + } + } + }, + "}" + ) + + val source = createTempFile("protocols", ".m").deleteOnExit() + source.writeLines(headerLines + protocolsStub) + + val bitcode = createTempFile("protocols", ".bc").deleteOnExit() + + val clangCommand = context.config.clang.clangC( + source.absolutePath, + "-O2", + "-emit-llvm", + "-c", "-o", bitcode.absolutePath + ) + + val result = Command(clangCommand).getResult(withErrors = true) + + if (result.exitCode == 0) { + context.llvm.additionalProducedBitcodeFiles += bitcode.absolutePath + } else { + // Note: ignoring compile errors intentionally. + // In this case resulting framework will likely be unusable due to compile errors when importing it. + } + } + + private fun guessMainPackage(): FqName { + val allPackages = (context.getIncludedLibraryDescriptors() + context.moduleDescriptor).flatMap { + it.getPackageFragments() // Includes also all parent packages, e.g. the root one. + } + + val nonEmptyPackages = allPackages + .filter { it.getMemberScope().getContributedDescriptors().isNotEmpty() } + .map { it.fqName }.distinct() + + return allPackages.map { it.fqName }.distinct() + .filter { candidate -> nonEmptyPackages.all { it.isSubpackageOf(candidate) } } + // Now there are all common ancestors of non-empty packages. Longest of them is the least common accessor: + .maxByOrNull { it.asString().length }!! + } +} diff --git a/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/objcexport/ObjCExportCodeSpec.kt b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/objcexport/ObjCExportCodeSpec.kt new file mode 100644 index 00000000000..376bc9e7c3e --- /dev/null +++ b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/objcexport/ObjCExportCodeSpec.kt @@ -0,0 +1,128 @@ +/* + * Copyright 2010-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +package org.jetbrains.kotlin.backend.konan.objcexport + +import org.jetbrains.kotlin.backend.konan.descriptors.contributedMethods +import org.jetbrains.kotlin.backend.konan.descriptors.enumEntries +import org.jetbrains.kotlin.backend.konan.descriptors.isArray +import org.jetbrains.kotlin.backend.konan.descriptors.isInterface +import org.jetbrains.kotlin.descriptors.* +import org.jetbrains.kotlin.ir.symbols.IrClassSymbol +import org.jetbrains.kotlin.ir.symbols.IrConstructorSymbol +import org.jetbrains.kotlin.ir.symbols.IrEnumEntrySymbol +import org.jetbrains.kotlin.ir.symbols.IrSimpleFunctionSymbol +import org.jetbrains.kotlin.ir.util.SymbolTable +import org.jetbrains.kotlin.resolve.descriptorUtil.getSuperClassNotAny + +internal fun ObjCExportedInterface.createCodeSpec(symbolTable: SymbolTable): ObjCExportCodeSpec { + + fun createObjCMethods(methods: List) = methods.map { + ObjCMethodForKotlinMethod(symbolTable.referenceSimpleFunction(it)) + } + + fun List.toObjCMethods() = createObjCMethods(this.flatMap { + when (it) { + is PropertyDescriptor -> listOfNotNull(it.getter, it.setter) + is FunctionDescriptor -> listOf(it) + else -> error(it) + } + }) + + val files = topLevel.map { (sourceFile, declarations) -> + val binaryName = namer.getFileClassName(sourceFile).binaryName + val methods = declarations.toObjCMethods() + ObjCClassForKotlinFile(binaryName, methods) + } + + val classToType = mutableMapOf() + fun getType(descriptor: ClassDescriptor): ObjCTypeForKotlinType = classToType.getOrPut(descriptor) { + val methods = mutableListOf() + + // Note: contributedMethods includes fake overrides too. + val allBaseMethods = descriptor.contributedMethods.filter { mapper.shouldBeExposed(it) } + .flatMap { mapper.getBaseMethods(it) }.distinct() + + methods += createObjCMethods(allBaseMethods) + + val binaryName = namer.getClassOrProtocolName(descriptor).binaryName + val irClassSymbol = symbolTable.referenceClass(descriptor) + + if (descriptor.isInterface) { + ObjCProtocolForKotlinInterface(binaryName, irClassSymbol, methods) + } else { + descriptor.constructors.filter { mapper.shouldBeExposed(it) }.mapTo(methods) { + val irConstructorSymbol = symbolTable.referenceConstructor(it) + + if (descriptor.isArray) { + ObjCFactoryMethodForKotlinArrayConstructor(irConstructorSymbol) + } else { + ObjCInitMethodForKotlinConstructor(irConstructorSymbol) + } + } + + if (descriptor.kind == ClassKind.ENUM_CLASS) { + descriptor.enumEntries.mapTo(methods) { + ObjCGetterForKotlinEnumEntry(symbolTable.referenceEnumEntry(it)) + } + } + + val categoryMethods = categoryMembers[descriptor].orEmpty().toObjCMethods() + + val superClassNotAny = descriptor.getSuperClassNotAny() + ?.let { getType(it) as ObjCClassForKotlinClass } + + ObjCClassForKotlinClass(binaryName, irClassSymbol, methods, categoryMethods, superClassNotAny) + } + } + + val types = generatedClasses.map { getType(it) } + + return ObjCExportCodeSpec(files, types) +} + +internal class ObjCExportCodeSpec( + val files: List, + val types: List +) + +internal sealed class ObjCMethodSpec + +internal class ObjCMethodForKotlinMethod(val baseMethod: IrSimpleFunctionSymbol) : ObjCMethodSpec() + +internal class ObjCInitMethodForKotlinConstructor(val irConstructorSymbol: IrConstructorSymbol) : ObjCMethodSpec() + +internal class ObjCFactoryMethodForKotlinArrayConstructor( + val irConstructorSymbol: IrConstructorSymbol +) : ObjCMethodSpec() + +internal class ObjCGetterForKotlinEnumEntry(val irEnumEntrySymbol: IrEnumEntrySymbol) : ObjCMethodSpec() + +internal sealed class ObjCTypeSpec(val binaryName: String) + +internal sealed class ObjCTypeForKotlinType( + binaryName: String, + val irClassSymbol: IrClassSymbol, + val methods: List +) : ObjCTypeSpec(binaryName) + +internal class ObjCClassForKotlinClass( + binaryName: String, + irClassSymbol: IrClassSymbol, + methods: List, + val categoryMethods: List, + val superClassNotAny: ObjCClassForKotlinClass? +) : ObjCTypeForKotlinType(binaryName, irClassSymbol, methods) + +internal class ObjCProtocolForKotlinInterface( + binaryName: String, + irClassSymbol: IrClassSymbol, + methods: List +) : ObjCTypeForKotlinType(binaryName, irClassSymbol, methods) + +internal class ObjCClassForKotlinFile( + binaryName: String, + val methods: List +) : ObjCTypeSpec(binaryName) \ No newline at end of file diff --git a/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/objcexport/ObjCExportHeaderGenerator.kt b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/objcexport/ObjCExportHeaderGenerator.kt new file mode 100644 index 00000000000..bf1bdb44f2b --- /dev/null +++ b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/objcexport/ObjCExportHeaderGenerator.kt @@ -0,0 +1,1256 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +package org.jetbrains.kotlin.backend.konan.objcexport + +import org.jetbrains.kotlin.backend.common.serialization.findSourceFile +import org.jetbrains.kotlin.backend.konan.* +import org.jetbrains.kotlin.backend.konan.descriptors.* +import org.jetbrains.kotlin.builtins.* +import org.jetbrains.kotlin.builtins.KotlinBuiltIns.isAny +import org.jetbrains.kotlin.descriptors.* +import org.jetbrains.kotlin.name.ClassId +import org.jetbrains.kotlin.resolve.constants.ArrayValue +import org.jetbrains.kotlin.resolve.constants.KClassValue +import org.jetbrains.kotlin.resolve.deprecation.Deprecation +import org.jetbrains.kotlin.resolve.deprecation.DeprecationLevelValue +import org.jetbrains.kotlin.resolve.descriptorUtil.* +import org.jetbrains.kotlin.resolve.scopes.MemberScope +import org.jetbrains.kotlin.types.ErrorUtils +import org.jetbrains.kotlin.types.KotlinType +import org.jetbrains.kotlin.types.TypeUtils +import org.jetbrains.kotlin.types.Variance +import org.jetbrains.kotlin.types.typeUtil.builtIns +import org.jetbrains.kotlin.types.typeUtil.isInterface +import org.jetbrains.kotlin.types.typeUtil.isTypeParameter +import org.jetbrains.kotlin.types.typeUtil.supertypes +import org.jetbrains.kotlin.utils.addIfNotNull + +interface ObjCExportTranslator { + fun generateBaseDeclarations(): List> + fun getClassIfExtension(receiverType: KotlinType): ClassDescriptor? + fun translateFile(file: SourceFile, declarations: List): ObjCInterface + fun translateClass(descriptor: ClassDescriptor): ObjCInterface + fun translateInterface(descriptor: ClassDescriptor): ObjCProtocol + fun translateExtensions(classDescriptor: ClassDescriptor, declarations: List): ObjCInterface +} + +interface ObjCExportWarningCollector { + fun reportWarning(text: String) + fun reportWarning(method: FunctionDescriptor, text: String) + + object SILENT : ObjCExportWarningCollector { + override fun reportWarning(text: String) {} + override fun reportWarning(method: FunctionDescriptor, text: String) {} + } +} + +internal class ObjCExportTranslatorImpl( + private val generator: ObjCExportHeaderGenerator?, + val mapper: ObjCExportMapper, + val namer: ObjCExportNamer, + val warningCollector: ObjCExportWarningCollector, + val objcGenerics: Boolean +) : ObjCExportTranslator { + + private val kotlinAnyName = namer.kotlinAnyName + + override fun generateBaseDeclarations(): List> { + val stubs = mutableListOf>() + + stubs.add(objCInterface(namer.kotlinAnyName, superClass = "NSObject", members = buildMembers { + +ObjCMethod(null, true, ObjCInstanceType, listOf("init"), emptyList(), listOf("unavailable")) + +ObjCMethod(null, false, ObjCInstanceType, listOf("new"), emptyList(), listOf("unavailable")) + +ObjCMethod(null, false, ObjCVoidType, listOf("initialize"), emptyList(), listOf("objc_requires_super")) + })) + + // TODO: add comment to the header. + stubs.add(ObjCInterfaceImpl( + namer.kotlinAnyName.objCName, + superProtocols = listOf("NSCopying"), + categoryName = "${namer.kotlinAnyName.objCName}Copying" + )) + + // TODO: only if appears + stubs.add(objCInterface( + namer.mutableSetName, + generics = listOf("ObjectType"), + superClass = "NSMutableSet" + )) + + // TODO: only if appears + stubs.add(objCInterface( + namer.mutableMapName, + generics = listOf("KeyType", "ObjectType"), + superClass = "NSMutableDictionary" + )) + + val nsErrorCategoryName = "NSError${namer.topLevelNamePrefix}KotlinException" + stubs.add(ObjCInterfaceImpl("NSError", categoryName = nsErrorCategoryName, members = buildMembers { + +ObjCProperty("kotlinException", null, ObjCNullableReferenceType(ObjCIdType), listOf("readonly")) + })) + + genKotlinNumbers(stubs) + + return stubs + } + + private fun genKotlinNumbers(stubs: MutableList>) { + val members = buildMembers { + NSNumberKind.values().forEach { + +nsNumberFactory(it, listOf("unavailable")) + } + NSNumberKind.values().forEach { + +nsNumberInit(it, listOf("unavailable")) + } + } + stubs.add(objCInterface( + namer.kotlinNumberName, + superClass = "NSNumber", + members = members + )) + + NSNumberKind.values().forEach { + if (it.mappedKotlinClassId != null) { + stubs += genKotlinNumber(it.mappedKotlinClassId, it) + } + } + } + + private fun genKotlinNumber(kotlinClassId: ClassId, kind: NSNumberKind): ObjCInterface { + val name = namer.numberBoxName(kotlinClassId) + + val members = buildMembers { + +nsNumberFactory(kind) + +nsNumberInit(kind) + } + return objCInterface( + name, + superClass = namer.kotlinNumberName.objCName, + members = members + ) + } + + private fun nsNumberInit(kind: NSNumberKind, attributes: List = emptyList()): ObjCMethod { + return ObjCMethod( + null, + false, + ObjCInstanceType, + listOf(kind.factorySelector), + listOf(ObjCParameter("value", null, kind.objCType)), + attributes + ) + } + + private fun nsNumberFactory(kind: NSNumberKind, attributes: List = emptyList()): ObjCMethod { + return ObjCMethod( + null, + true, + ObjCInstanceType, + listOf(kind.initSelector), + listOf(ObjCParameter("value", null, kind.objCType)), + attributes + ) + } + + override fun getClassIfExtension(receiverType: KotlinType): ClassDescriptor? = + mapper.getClassIfCategory(receiverType) + + internal fun translateUnexposedClassAsUnavailableStub(descriptor: ClassDescriptor): ObjCInterface = objCInterface( + namer.getClassOrProtocolName(descriptor), + descriptor = descriptor, + superClass = "NSObject", + attributes = attributesForUnexposed(descriptor) + ) + + internal fun translateUnexposedInterfaceAsUnavailableStub(descriptor: ClassDescriptor): ObjCProtocol = objCProtocol( + namer.getClassOrProtocolName(descriptor), + descriptor = descriptor, + superProtocols = emptyList(), + members = emptyList(), + attributes = attributesForUnexposed(descriptor) + ) + + private fun attributesForUnexposed(descriptor: ClassDescriptor): List { + val message = when { + descriptor.isKotlinObjCClass() -> "Kotlin subclass of Objective-C class " + else -> "" + } + "can't be imported" + return listOf("unavailable(\"$message\")") + } + + private fun referenceClass(descriptor: ClassDescriptor): ObjCExportNamer.ClassOrProtocolName { + fun forwardDeclarationObjcClassName(objcGenerics: Boolean, descriptor: ClassDescriptor, namer:ObjCExportNamer): String { + val className = translateClassOrInterfaceName(descriptor) + val builder = StringBuilder(className.objCName) + if (objcGenerics) + formatGenerics(builder, descriptor.typeConstructor.parameters.map { typeParameterDescriptor -> + "${typeParameterDescriptor.variance.objcDeclaration()}${namer.getTypeParameterName(typeParameterDescriptor)}" + }) + return builder.toString() + } + + assert(mapper.shouldBeExposed(descriptor)) { "Shouldn't be exposed: $descriptor" } + assert(!descriptor.isInterface) + generator?.requireClassOrInterface(descriptor) + + return translateClassOrInterfaceName(descriptor).also { + val objcName = forwardDeclarationObjcClassName(objcGenerics, descriptor, namer) + generator?.referenceClass(objcName) + } + } + + private fun referenceProtocol(descriptor: ClassDescriptor): ObjCExportNamer.ClassOrProtocolName { + assert(mapper.shouldBeExposed(descriptor)) { "Shouldn't be exposed: $descriptor" } + assert(descriptor.isInterface) + generator?.requireClassOrInterface(descriptor) + + return translateClassOrInterfaceName(descriptor).also { + generator?.referenceProtocol(it.objCName) + } + } + + private fun translateClassOrInterfaceName(descriptor: ClassDescriptor): ObjCExportNamer.ClassOrProtocolName { + assert(mapper.shouldBeExposed(descriptor)) { "Shouldn't be exposed: $descriptor" } + if (ErrorUtils.isError(descriptor)) { + return ObjCExportNamer.ClassOrProtocolName("ERROR", "ERROR") + } + + return namer.getClassOrProtocolName(descriptor) + } + + override fun translateInterface(descriptor: ClassDescriptor): ObjCProtocol { + require(descriptor.isInterface) + if (!mapper.shouldBeExposed(descriptor)) { + return translateUnexposedInterfaceAsUnavailableStub(descriptor) + } + + val name = translateClassOrInterfaceName(descriptor) + val members: List> = buildMembers { translateInterfaceMembers(descriptor) } + val superProtocols: List = descriptor.superProtocols + + return objCProtocol(name, descriptor, superProtocols, members) + } + + private val ClassDescriptor.superProtocols: List + get() = + getSuperInterfaces() + .asSequence() + .filter { mapper.shouldBeExposed(it) } + .map { + generator?.generateInterface(it) + referenceProtocol(it).objCName + } + .toList() + + override fun translateExtensions( + classDescriptor: ClassDescriptor, + declarations: List + ): ObjCInterface { + generator?.generateClass(classDescriptor) + + val name = referenceClass(classDescriptor).objCName + val members = buildMembers { + translatePlainMembers(declarations, ObjCNoneExportScope) + } + return ObjCInterfaceImpl(name, categoryName = "Extensions", members = members) + } + + override fun translateFile(file: SourceFile, declarations: List): ObjCInterface { + val name = namer.getFileClassName(file) + + // TODO: stop inheriting KotlinBase. + val members = buildMembers { + translatePlainMembers(declarations, ObjCNoneExportScope) + } + return objCInterface( + name, + superClass = namer.kotlinAnyName.objCName, + members = members, + attributes = listOf(OBJC_SUBCLASSING_RESTRICTED) + ) + } + + override fun translateClass(descriptor: ClassDescriptor): ObjCInterface { + require(!descriptor.isInterface) + if (!mapper.shouldBeExposed(descriptor)) { + return translateUnexposedClassAsUnavailableStub(descriptor) + } + + val genericExportScope = if (objcGenerics) { + ObjCClassExportScope(descriptor, namer) + } else { + ObjCNoneExportScope + } + + fun superClassGenerics(genericExportScope: ObjCExportScope): List { + val parentType = computeSuperClassType(descriptor) + return if(parentType != null) { + parentType.arguments.map { typeProjection -> + mapReferenceTypeIgnoringNullability(typeProjection.type, genericExportScope) + } + } else { + emptyList() + } + } + + val superClass = descriptor.getSuperClassNotAny() + + val superName = if (superClass == null) { + kotlinAnyName + } else { + generator?.generateClass(superClass) + referenceClass(superClass) + } + + val superProtocols: List = descriptor.superProtocols + val members: List> = buildMembers { + val presentConstructors = mutableSetOf() + + descriptor.constructors + .asSequence() + .filter { mapper.shouldBeExposed(it) } + .forEach { + val selector = getSelector(it) + if (!descriptor.isArray) presentConstructors += selector + + +buildMethod(it, it, genericExportScope) + exportThrown(it) + if (selector == "init") { + +ObjCMethod(it, false, ObjCInstanceType, listOf("new"), emptyList(), + listOf("availability(swift, unavailable, message=\"use object initializers instead\")")) + } + } + + if (descriptor.isArray || descriptor.kind == ClassKind.OBJECT || descriptor.kind == ClassKind.ENUM_CLASS) { + +ObjCMethod(null, false, ObjCInstanceType, listOf("alloc"), emptyList(), listOf("unavailable")) + + val parameter = ObjCParameter("zone", null, ObjCRawType("struct _NSZone *")) + +ObjCMethod(descriptor, false, ObjCInstanceType, listOf("allocWithZone:"), listOf(parameter), listOf("unavailable")) + } + + // Hide "unimplemented" super constructors: + superClass?.constructors + ?.asSequence() + ?.filter { mapper.shouldBeExposed(it) } + ?.forEach { + val selector = getSelector(it) + if (selector !in presentConstructors) { + +buildMethod(it, it, ObjCNoneExportScope, unavailable = true) + + if (selector == "init") { + +ObjCMethod(null, false, ObjCInstanceType, listOf("new"), emptyList(), listOf("unavailable")) + } + + // TODO: consider adding exception-throwing impls for these. + } + } + + // TODO: consider adding exception-throwing impls for these. + when (descriptor.kind) { + ClassKind.OBJECT -> { + +ObjCMethod( + null, false, ObjCInstanceType, + listOf(namer.getObjectInstanceSelector(descriptor)), emptyList(), + listOf(swiftNameAttribute("init()")) + ) + } + ClassKind.ENUM_CLASS -> { + val type = mapType(descriptor.defaultType, ReferenceBridge, ObjCNoneExportScope) + + descriptor.enumEntries.forEach { + val entryName = namer.getEnumEntrySelector(it) + +ObjCProperty(entryName, it, type, listOf("class", "readonly"), + declarationAttributes = listOf(swiftNameAttribute(entryName))) + } + } + else -> { + // Nothing special. + } + } + + translateClassMembers(descriptor, genericExportScope) + } + + val attributes = if (descriptor.isFinalOrEnum) listOf(OBJC_SUBCLASSING_RESTRICTED) else emptyList() + + val name = translateClassOrInterfaceName(descriptor) + + val generics = if (objcGenerics) { + descriptor.typeConstructor.parameters.map { + "${it.variance.objcDeclaration()}${namer.getTypeParameterName(it)}" + } + } else { + emptyList() + } + + val superClassGenerics = if (objcGenerics) { + superClassGenerics(genericExportScope) + } else { + emptyList() + } + + return objCInterface( + name, + generics = generics, + descriptor = descriptor, + superClass = superName.objCName, + superClassGenerics = superClassGenerics, + superProtocols = superProtocols, + members = members, + attributes = attributes + ) + } + + private fun ClassDescriptor.getExposedMembers(): List = + this.unsubstitutedMemberScope.getContributedDescriptors() + .asSequence() + .filterIsInstance() + .filter { mapper.shouldBeExposed(it) } + .toList() + + private fun StubBuilder.translateClassMembers(descriptor: ClassDescriptor, objCExportScope: ObjCExportScope) { + require(!descriptor.isInterface) + translateClassMembers(descriptor.getExposedMembers(), objCExportScope) + } + + private fun StubBuilder.translateInterfaceMembers(descriptor: ClassDescriptor) { + require(descriptor.isInterface) + translateBaseMembers(descriptor.getExposedMembers()) + } + + private fun List.toObjCMembers( + methodsBuffer: MutableList, + propertiesBuffer: MutableList + ) = this.forEach { + when (it) { + is FunctionDescriptor -> methodsBuffer += it + is PropertyDescriptor -> if (mapper.isObjCProperty(it)) { + propertiesBuffer += it + } else { + methodsBuffer.addIfNotNull(it.getter) + methodsBuffer.addIfNotNull(it.setter) + } + else -> error(it) + } + } + + private fun StubBuilder.translateClassMembers( + members: List, + objCExportScope: ObjCExportScope + ) { + // TODO: add some marks about modality. + + val methods = mutableListOf() + val properties = mutableListOf() + + members.toObjCMembers(methods, properties) + + methods.forEach { exportThrown(it) } + + methods.retainAll { it.kind.isReal } + properties.retainAll { it.kind.isReal } + + methods.forEach { method -> + mapper.getBaseMethods(method) + .asSequence() + .distinctBy { namer.getSelector(it) } + .forEach { base -> +buildMethod(method, base, objCExportScope) } + } + + properties.forEach { property -> + mapper.getBaseProperties(property) + .asSequence() + .distinctBy { namer.getPropertyName(it) } + .forEach { base -> +buildProperty(property, base, objCExportScope) } + } + } + + private fun StubBuilder.translateBaseMembers(members: List) { + // TODO: add some marks about modality. + + val methods = mutableListOf() + val properties = mutableListOf() + + members.toObjCMembers(methods, properties) + + methods.forEach { exportThrown(it) } + + methods.retainAll { mapper.isBaseMethod(it) } + + properties.retainAll { + if (mapper.isBaseProperty(it)) { + true + } else { + methods.addIfNotNull(it.setter?.takeIf(mapper::isBaseMethod)) + false + } + } + + translatePlainMembers(methods, properties, ObjCNoneExportScope) + } + + private fun StubBuilder.translatePlainMembers(members: List, objCExportScope: ObjCExportScope) { + val methods = mutableListOf() + val properties = mutableListOf() + + members.toObjCMembers(methods, properties) + + methods.forEach { exportThrown(it) } + + translatePlainMembers(methods, properties, objCExportScope) + } + + private fun StubBuilder.translatePlainMembers(methods: List, properties: List, objCExportScope: ObjCExportScope) { + methods.forEach { +buildMethod(it, it, objCExportScope) } + properties.forEach { +buildProperty(it, it, objCExportScope) } + } + // TODO: consider checking that signatures for bases with same selector/name are equal. + + private fun getSelector(method: FunctionDescriptor): String { + return namer.getSelector(method) + } + + private fun buildProperty(property: PropertyDescriptor, baseProperty: PropertyDescriptor, objCExportScope: ObjCExportScope): ObjCProperty { + assert(mapper.isBaseProperty(baseProperty)) + assert(mapper.isObjCProperty(baseProperty)) + + val getterBridge = mapper.bridgeMethod(baseProperty.getter!!) + val type = mapReturnType(getterBridge.returnBridge, property.getter!!, objCExportScope) + val name = namer.getPropertyName(baseProperty) + + val attributes = mutableListOf() + + if (!getterBridge.isInstance) { + attributes += "class" + } + + val setterName: String? + val propertySetter = property.setter + if (propertySetter != null && mapper.shouldBeExposed(propertySetter)) { + val setterSelector = mapper.getBaseMethods(propertySetter).map { namer.getSelector(it) }.distinct().single() + setterName = if (setterSelector != "set" + name.capitalize() + ":") setterSelector else null + } else { + attributes += "readonly" + setterName = null + } + + val getterSelector = getSelector(baseProperty.getter!!) + val getterName: String? = if (getterSelector != name) getterSelector else null + + val declarationAttributes = mutableListOf(swiftNameAttribute(name)) + declarationAttributes.addIfNotNull(mapper.getDeprecation(property)?.toDeprecationAttribute()) + + return ObjCProperty(name, property, type, attributes, setterName, getterName, declarationAttributes) + } + + private fun buildMethod( + method: FunctionDescriptor, + baseMethod: FunctionDescriptor, + objCExportScope: ObjCExportScope, + unavailable: Boolean = false + ): ObjCMethod { + fun collectParameters(baseMethodBridge: MethodBridge, method: FunctionDescriptor): List { + fun unifyName(initialName: String, usedNames: Set): String { + var unique = initialName.toValidObjCSwiftIdentifier() + while (unique in usedNames || unique in cKeywords) { + unique += "_" + } + return unique + } + + val valueParametersAssociated = baseMethodBridge.valueParametersAssociated(method) + + val parameters = mutableListOf() + + val usedNames = mutableSetOf() + + valueParametersAssociated.forEach { (bridge: MethodBridgeValueParameter, p: ParameterDescriptor?) -> + val candidateName: String = when (bridge) { + is MethodBridgeValueParameter.Mapped -> { + p!! + when { + p is ReceiverParameterDescriptor -> "receiver" + method is PropertySetterDescriptor -> "value" + else -> p.name.asString() + } + } + MethodBridgeValueParameter.ErrorOutParameter -> "error" + MethodBridgeValueParameter.SuspendCompletion -> "completionHandler" + } + + val uniqueName = unifyName(candidateName, usedNames) + usedNames += uniqueName + + val type = when (bridge) { + is MethodBridgeValueParameter.Mapped -> mapType(p!!.type, bridge.bridge, objCExportScope) + MethodBridgeValueParameter.ErrorOutParameter -> + ObjCPointerType(ObjCNullableReferenceType(ObjCClassType("NSError")), nullable = true) + + MethodBridgeValueParameter.SuspendCompletion -> { + ObjCBlockPointerType( + returnType = ObjCVoidType, + parameterTypes = listOf( + mapReferenceType(method.returnType!!, objCExportScope).makeNullable(), + ObjCNullableReferenceType(ObjCClassType("NSError")) + ) + ) + } + } + + parameters += ObjCParameter(uniqueName, p, type) + } + return parameters + } + + assert(mapper.isBaseMethod(baseMethod)) + + val baseMethodBridge = mapper.bridgeMethod(baseMethod) + + val isInstanceMethod: Boolean = baseMethodBridge.isInstance + val returnType: ObjCType = mapReturnType(baseMethodBridge.returnBridge, method, objCExportScope) + val parameters = collectParameters(baseMethodBridge, method) + val selector = getSelector(baseMethod) + val selectorParts: List = splitSelector(selector) + val swiftName = namer.getSwiftName(baseMethod) + val attributes = mutableListOf() + + attributes += swiftNameAttribute(swiftName) + if (baseMethodBridge.returnBridge is MethodBridge.ReturnValue.WithError.ZeroForError + && baseMethodBridge.returnBridge.successMayBeZero) { + + // Method may return zero on success, but + // standard Objective-C convention doesn't suppose this happening. + // Add non-standard convention hint for Swift: + attributes += "swift_error(nonnull_error)" // Means "failure <=> (error != nil)". + } + + if (method is ConstructorDescriptor && !method.constructedClass.isArray) { // TODO: check methodBridge instead. + attributes += "objc_designated_initializer" + } + + if (unavailable) { + attributes += "unavailable" + } else { + attributes.addIfNotNull(mapper.getDeprecation(method)?.toDeprecationAttribute()) + } + + val comment = buildComment(method, baseMethodBridge) + + return ObjCMethod(method, isInstanceMethod, returnType, selectorParts, parameters, attributes, comment) + } + + private fun splitSelector(selector: String): List { + return if (!selector.endsWith(":")) { + listOf(selector) + } else { + selector.trimEnd(':').split(':').map { "$it:" } + } + } + + private fun buildComment(method: FunctionDescriptor, bridge: MethodBridge): ObjCComment? { + if (method.isSuspend || bridge.returnsError) { + val effectiveThrows = getEffectiveThrows(method).toSet() + return when { + effectiveThrows.contains(throwableClassId) -> { + ObjCComment("@note This method converts all Kotlin exceptions to errors.") + } + + effectiveThrows.isNotEmpty() -> { + ObjCComment( + buildString { + append("@note This method converts instances of ") + effectiveThrows.joinTo(this) { it.relativeClassName.asString() } + append(" to errors.") + }, + "Other uncaught Kotlin exceptions are fatal." + ) + } + + else -> { + // Shouldn't happen though. + ObjCComment("@warning All uncaught Kotlin exceptions are fatal.") + } + } + } + + return null + } + + private val throwableClassId = ClassId.topLevel(StandardNames.FqNames.throwable) + + private fun getEffectiveThrows(method: FunctionDescriptor): Sequence { + method.overriddenDescriptors.firstOrNull()?.let { return getEffectiveThrows(it) } + return getDefinedThrows(method).orEmpty() + } + + private fun exportThrown(method: FunctionDescriptor) { + getDefinedThrows(method) + ?.mapNotNull { method.module.findClassAcrossModuleDependencies(it) } + ?.forEach { generator?.requireClassOrInterface(it) } + } + + private fun getDefinedThrows(method: FunctionDescriptor): Sequence? { + if (!method.kind.isReal) return null + + val throwsAnnotation = method.annotations.findAnnotation(KonanFqNames.throws) + + if (throwsAnnotation != null) { + val argumentsArrayValue = throwsAnnotation.firstArgument() as? ArrayValue + return argumentsArrayValue?.value?.asSequence().orEmpty() + .filterIsInstance() + .mapNotNull { + when (val value = it.value) { + is KClassValue.Value.NormalClass -> value.classId + is KClassValue.Value.LocalClass -> null + } + } + } + + if (method.isSuspend && method.overriddenDescriptors.isEmpty()) { + return implicitSuspendThrows + } + + return null + } + + private val implicitSuspendThrows = sequenceOf(ClassId.topLevel(KonanFqNames.cancellationException)) + + private fun mapReturnType(returnBridge: MethodBridge.ReturnValue, method: FunctionDescriptor, objCExportScope: ObjCExportScope): ObjCType = when (returnBridge) { + MethodBridge.ReturnValue.Suspend, + MethodBridge.ReturnValue.Void -> ObjCVoidType + MethodBridge.ReturnValue.HashCode -> ObjCPrimitiveType.NSUInteger + is MethodBridge.ReturnValue.Mapped -> mapType(method.returnType!!, returnBridge.bridge, objCExportScope) + MethodBridge.ReturnValue.WithError.Success -> ObjCPrimitiveType.BOOL + is MethodBridge.ReturnValue.WithError.ZeroForError -> { + val successReturnType = mapReturnType(returnBridge.successBridge, method, objCExportScope) + + if (!returnBridge.successMayBeZero) { + check(successReturnType is ObjCNonNullReferenceType + || (successReturnType is ObjCPointerType && !successReturnType.nullable)) { + "Unexpected return type: $successReturnType in $method" + } + } + + successReturnType.makeNullableIfReferenceOrPointer() + } + + MethodBridge.ReturnValue.Instance.InitResult, + MethodBridge.ReturnValue.Instance.FactoryResult -> ObjCInstanceType + } + + internal fun mapReferenceType(kotlinType: KotlinType, objCExportScope: ObjCExportScope): ObjCReferenceType = + mapReferenceTypeIgnoringNullability(kotlinType, objCExportScope).withNullabilityOf(kotlinType) + + private fun ObjCNonNullReferenceType.withNullabilityOf(kotlinType: KotlinType): ObjCReferenceType = + if (kotlinType.binaryRepresentationIsNullable()) { + ObjCNullableReferenceType(this) + } else { + this + } + + internal fun mapReferenceTypeIgnoringNullability(kotlinType: KotlinType, objCExportScope: ObjCExportScope): ObjCNonNullReferenceType { + class TypeMappingMatch(val type: KotlinType, val descriptor: ClassDescriptor, val mapper: CustomTypeMapper) + + val typeMappingMatches = (listOf(kotlinType) + kotlinType.supertypes()).mapNotNull { type -> + (type.constructor.declarationDescriptor as? ClassDescriptor)?.let { descriptor -> + mapper.getCustomTypeMapper(descriptor)?.let { mapper -> + TypeMappingMatch(type, descriptor, mapper) + } + } + } + + val mostSpecificMatches = typeMappingMatches.filter { match -> + typeMappingMatches.all { otherMatch -> + otherMatch.descriptor == match.descriptor || + !otherMatch.descriptor.isSubclassOf(match.descriptor) + } + } + + if (mostSpecificMatches.size > 1) { + val types = mostSpecificMatches.map { it.type } + val firstType = types[0] + val secondType = types[1] + + warningCollector.reportWarning( + "Exposed type '$kotlinType' is '$firstType' and '$secondType' at the same time. " + + "This most likely wouldn't work as expected.") + + // TODO: the same warning for such classes. + } + + mostSpecificMatches.firstOrNull()?.let { + return it.mapper.mapType(it.type, this, objCExportScope) + } + + if(objcGenerics && kotlinType.isTypeParameter()){ + val genericTypeDeclaration = objCExportScope.getGenericDeclaration(TypeUtils.getTypeParameterDescriptorOrNull(kotlinType)) + if(genericTypeDeclaration != null) + return genericTypeDeclaration + } + + val classDescriptor = kotlinType.getErasedTypeClass() + + // TODO: translate `where T : BaseClass, T : SomeInterface` to `BaseClass* ` + + // TODO: expose custom inline class boxes properly. + if (isAny(classDescriptor) || classDescriptor.classId in mapper.hiddenTypes || classDescriptor.isInlined()) { + return ObjCIdType + } + + if (classDescriptor.defaultType.isObjCObjectType()) { + return mapObjCObjectReferenceTypeIgnoringNullability(classDescriptor) + } + + if (!mapper.shouldBeExposed(classDescriptor)) { + // There are number of tricky corner cases getting here. + return ObjCIdType + } + + return if (classDescriptor.isInterface) { + ObjCProtocolType(referenceProtocol(classDescriptor).objCName) + } else { + val typeArgs = if (objcGenerics) { + kotlinType.arguments.map { typeProjection -> + if (typeProjection.isStarProjection) { + ObjCIdType // TODO: use Kotlin upper bound. + } else { + mapReferenceTypeIgnoringNullability(typeProjection.type, objCExportScope) + } + } + } else { + emptyList() + } + ObjCClassType(referenceClass(classDescriptor).objCName, typeArgs) + } + } + + private tailrec fun mapObjCObjectReferenceTypeIgnoringNullability(descriptor: ClassDescriptor): ObjCNonNullReferenceType { + // TODO: more precise types can be used. + + if (descriptor.isObjCMetaClass()) return ObjCMetaClassType + if (descriptor.isObjCProtocolClass()) return foreignClassType("Protocol") + + if (descriptor.isExternalObjCClass() || descriptor.isObjCForwardDeclaration()) { + return if (descriptor.isInterface) { + val name = descriptor.name.asString().removeSuffix("Protocol") + foreignProtocolType(name) + } else { + val name = descriptor.name.asString() + foreignClassType(name) + } + } + + if (descriptor.isKotlinObjCClass()) { + return mapObjCObjectReferenceTypeIgnoringNullability(descriptor.getSuperClassOrAny()) + } + + return ObjCIdType + } + + private fun foreignProtocolType(name: String): ObjCProtocolType { + generator?.referenceProtocol(name) + return ObjCProtocolType(name) + } + + private fun foreignClassType(name: String): ObjCClassType { + generator?.referenceClass(name) + return ObjCClassType(name) + } + + internal fun mapFunctionTypeIgnoringNullability( + functionType: KotlinType, + objCExportScope: ObjCExportScope, + returnsVoid: Boolean + ): ObjCBlockPointerType { + val parameterTypes = listOfNotNull(functionType.getReceiverTypeFromFunctionType()) + + functionType.getValueParameterTypesFromFunctionType().map { it.type } + + return ObjCBlockPointerType( + if (returnsVoid) { + ObjCVoidType + } else { + mapReferenceType(functionType.getReturnTypeFromFunctionType(), objCExportScope) + }, + parameterTypes.map { mapReferenceType(it, objCExportScope) } + ) + } + + private fun mapFunctionType( + kotlinType: KotlinType, + objCExportScope: ObjCExportScope, + typeBridge: BlockPointerBridge + ): ObjCReferenceType { + val expectedDescriptor = kotlinType.builtIns.getFunction(typeBridge.numberOfParameters) + + // Somewhat similar to mapType: + val functionType = if (TypeUtils.getClassDescriptor(kotlinType) == expectedDescriptor) { + kotlinType + } else { + kotlinType.supertypes().singleOrNull { TypeUtils.getClassDescriptor(it) == expectedDescriptor } + ?: expectedDescriptor.defaultType // Should not happen though. + } + + return mapFunctionTypeIgnoringNullability(functionType, objCExportScope, typeBridge.returnsVoid) + .withNullabilityOf(kotlinType) + } + + private fun mapType(kotlinType: KotlinType, typeBridge: TypeBridge, objCExportScope: ObjCExportScope): ObjCType = when (typeBridge) { + ReferenceBridge -> mapReferenceType(kotlinType, objCExportScope) + is BlockPointerBridge -> mapFunctionType(kotlinType, objCExportScope, typeBridge) + is ValueTypeBridge -> { + when (typeBridge.objCValueType) { + ObjCValueType.BOOL -> ObjCPrimitiveType.BOOL + ObjCValueType.UNICHAR -> ObjCPrimitiveType.unichar + ObjCValueType.CHAR -> ObjCPrimitiveType.int8_t + ObjCValueType.SHORT -> ObjCPrimitiveType.int16_t + ObjCValueType.INT -> ObjCPrimitiveType.int32_t + ObjCValueType.LONG_LONG -> ObjCPrimitiveType.int64_t + ObjCValueType.UNSIGNED_CHAR -> ObjCPrimitiveType.uint8_t + ObjCValueType.UNSIGNED_SHORT -> ObjCPrimitiveType.uint16_t + ObjCValueType.UNSIGNED_INT -> ObjCPrimitiveType.uint32_t + ObjCValueType.UNSIGNED_LONG_LONG -> ObjCPrimitiveType.uint64_t + ObjCValueType.FLOAT -> ObjCPrimitiveType.float + ObjCValueType.DOUBLE -> ObjCPrimitiveType.double + ObjCValueType.POINTER -> ObjCPointerType(ObjCVoidType, kotlinType.binaryRepresentationIsNullable()) + } + // TODO: consider other namings. + } + } +} + +abstract class ObjCExportHeaderGenerator internal constructor( + val moduleDescriptors: List, + internal val mapper: ObjCExportMapper, + val namer: ObjCExportNamer, + val objcGenerics:Boolean = false +) { + + constructor( + moduleDescriptors: List, + builtIns: KotlinBuiltIns, + topLevelNamePrefix: String + ) : this(moduleDescriptors, builtIns, topLevelNamePrefix, ObjCExportMapper()) + + private constructor( + moduleDescriptors: List, + builtIns: KotlinBuiltIns, + topLevelNamePrefix: String, + mapper: ObjCExportMapper + ) : this( + moduleDescriptors, + mapper, + ObjCExportNamerImpl(moduleDescriptors.toSet(), builtIns, mapper, topLevelNamePrefix, local = false) + ) + + constructor( + moduleDescriptor: ModuleDescriptor, + builtIns: KotlinBuiltIns, + topLevelNamePrefix: String = moduleDescriptor.namePrefix + ) : this(moduleDescriptor, emptyList(), builtIns, topLevelNamePrefix) + + constructor( + moduleDescriptor: ModuleDescriptor, + exportedDependencies: List, + builtIns: KotlinBuiltIns, + topLevelNamePrefix: String = moduleDescriptor.namePrefix + ) : this(listOf(moduleDescriptor) + exportedDependencies, builtIns, topLevelNamePrefix) + + private val stubs = mutableListOf>() + + private val classForwardDeclarations = linkedSetOf() + private val protocolForwardDeclarations = linkedSetOf() + private val extraClassesToTranslate = mutableSetOf() + + private val translator = ObjCExportTranslatorImpl(this, mapper, namer, + object : ObjCExportWarningCollector { + override fun reportWarning(text: String) = + this@ObjCExportHeaderGenerator.reportWarning(text) + + override fun reportWarning(method: FunctionDescriptor, text: String) = + this@ObjCExportHeaderGenerator.reportWarning(method, text) + }, + objcGenerics) + + private val generatedClasses = mutableSetOf() + private val extensions = mutableMapOf>() + private val topLevel = mutableMapOf>() + + fun build(): List = mutableListOf().apply { + add("#import ") + add("#import ") + add("#import ") + add("#import ") + add("#import ") + add("#import ") + add("#import ") + getAdditionalImports().forEach { + add("#import <$it>") + } + add("") + + if (classForwardDeclarations.isNotEmpty()) { + add("@class ${classForwardDeclarations.joinToString()};") + add("") + } + + if (protocolForwardDeclarations.isNotEmpty()) { + add("@protocol ${protocolForwardDeclarations.joinToString()};") + add("") + } + + add("NS_ASSUME_NONNULL_BEGIN") + add("#pragma clang diagnostic push") + listOf( + "-Wunknown-warning-option", + + // Protocols don't have generics, classes do. So generated header may contain + // overriding property with "incompatible" type, e.g. `Generic`-typed property + // overriding `Generic`. Suppress these warnings: + "-Wincompatible-property-type", + + "-Wnullability" + ).forEach { + add("#pragma clang diagnostic ignored \"$it\"") + } + add("") + + stubs.forEach { + addAll(StubRenderer.render(it)) + add("") + } + + add("#pragma clang diagnostic pop") + add("NS_ASSUME_NONNULL_END") + } + + internal fun buildInterface(): ObjCExportedInterface { + val headerLines = build() + return ObjCExportedInterface(generatedClasses, extensions, topLevel, headerLines, namer, mapper) + } + + protected abstract fun reportWarning(text: String) + + protected abstract fun reportWarning(method: FunctionDescriptor, text: String) + + protected open fun getAdditionalImports(): List = emptyList() + + + fun translateModule(): List> { + // TODO: make the translation order stable + // to stabilize name mangling. + + stubs += translator.generateBaseDeclarations() + + val packageFragments = moduleDescriptors.flatMap { it.getPackageFragments() } + + packageFragments.forEach { packageFragment -> + packageFragment.getMemberScope().getContributedDescriptors() + .asSequence() + .filterIsInstance() + .filter { mapper.shouldBeExposed(it) } + .forEach { + val classDescriptor = mapper.getClassIfCategory(it) + if (classDescriptor != null) { + extensions.getOrPut(classDescriptor, { mutableListOf() }) += it + } else { + topLevel.getOrPut(it.findSourceFile(), { mutableListOf() }) += it + } + } + + } + + fun MemberScope.translateClasses() { + getContributedDescriptors() + .asSequence() + .filterIsInstance() + .forEach { + if (mapper.shouldBeExposed(it)) { + if (it.isInterface) { + generateInterface(it) + } else { + generateClass(it) + } + + it.unsubstitutedMemberScope.translateClasses() + } else if (mapper.shouldBeVisible(it)) { + stubs += if (it.isInterface) { + translator.translateUnexposedInterfaceAsUnavailableStub(it) + } else { + translator.translateUnexposedClassAsUnavailableStub(it) + } + } + } + } + + packageFragments.forEach { packageFragment -> + packageFragment.getMemberScope().translateClasses() + } + + extensions.forEach { classDescriptor, declarations -> + generateExtensions(classDescriptor, declarations) + } + + topLevel.forEach { sourceFile, declarations -> + generateFile(sourceFile, declarations) + } + + while (extraClassesToTranslate.isNotEmpty()) { + val descriptor = extraClassesToTranslate.first() + extraClassesToTranslate -= descriptor + if (descriptor.isInterface) { + generateInterface(descriptor) + } else { + generateClass(descriptor) + } + } + + return stubs + } + + private fun generateFile(sourceFile: SourceFile, declarations: List) { + stubs.add(translator.translateFile(sourceFile, declarations)) + } + + private fun generateExtensions(classDescriptor: ClassDescriptor, declarations: List) { + stubs.add(translator.translateExtensions(classDescriptor, declarations)) + } + + internal fun generateClass(descriptor: ClassDescriptor) { + if (!generatedClasses.add(descriptor)) return + stubs.add(translator.translateClass(descriptor)) + } + + internal fun generateInterface(descriptor: ClassDescriptor) { + if (!generatedClasses.add(descriptor)) return + stubs.add(translator.translateInterface(descriptor)) + } + + internal fun requireClassOrInterface(descriptor: ClassDescriptor) { + if (descriptor !in generatedClasses) { + extraClassesToTranslate += descriptor + } + } + + internal fun referenceClass(objCName: String) { + classForwardDeclarations += objCName + } + + internal fun referenceProtocol(objCName: String) { + protocolForwardDeclarations += objCName + } +} + +private fun objCInterface( + name: ObjCExportNamer.ClassOrProtocolName, + generics: List = emptyList(), + descriptor: ClassDescriptor? = null, + superClass: String? = null, + superClassGenerics: List = emptyList(), + superProtocols: List = emptyList(), + members: List> = emptyList(), + attributes: List = emptyList() +): ObjCInterface = ObjCInterfaceImpl( + name.objCName, + generics, + descriptor, + superClass, + superClassGenerics, + superProtocols, + null, + members, + attributes + name.toNameAttributes() +) + +private fun objCProtocol( + name: ObjCExportNamer.ClassOrProtocolName, + descriptor: ClassDescriptor, + superProtocols: List, + members: List>, + attributes: List = emptyList() +): ObjCProtocol = ObjCProtocolImpl( + name.objCName, + descriptor, + superProtocols, + members, + attributes + name.toNameAttributes() +) + +internal fun ObjCExportNamer.ClassOrProtocolName.toNameAttributes(): List = listOfNotNull( + binaryName.takeIf { it != objCName }?.let { objcRuntimeNameAttribute(it) }, + swiftName.takeIf { it != objCName }?.let { swiftNameAttribute(it) } +) + +private fun swiftNameAttribute(swiftName: String) = "swift_name(\"$swiftName\")" +private fun objcRuntimeNameAttribute(name: String) = "objc_runtime_name(\"$name\")" + +interface ObjCExportScope{ + fun getGenericDeclaration(typeParameterDescriptor: TypeParameterDescriptor?): ObjCGenericTypeDeclaration? +} + +internal class ObjCClassExportScope constructor(container:DeclarationDescriptor, val namer: ObjCExportNamer): ObjCExportScope { + private val typeNames = if(container is ClassDescriptor && !container.isInterface) { + container.typeConstructor.parameters + } else { + emptyList() + } + + override fun getGenericDeclaration(typeParameterDescriptor: TypeParameterDescriptor?): ObjCGenericTypeDeclaration? { + val localTypeParam = typeNames.firstOrNull { + typeParameterDescriptor != null && + (it == typeParameterDescriptor || (it.isCapturedFromOuterDeclaration && it.original == typeParameterDescriptor)) + } + + return if(localTypeParam == null) { + null + } else { + ObjCGenericTypeDeclaration(localTypeParam, namer) + } + } +} + +internal object ObjCNoneExportScope: ObjCExportScope{ + override fun getGenericDeclaration(typeParameterDescriptor: TypeParameterDescriptor?): ObjCGenericTypeDeclaration? = null +} + +internal fun Variance.objcDeclaration():String = when(this){ + Variance.OUT_VARIANCE -> "__covariant " + Variance.IN_VARIANCE -> "__contravariant " + else -> "" +} + +private fun computeSuperClassType(descriptor: ClassDescriptor): KotlinType? = descriptor.typeConstructor.supertypes.filter { !it.isInterface() }.firstOrNull() + +internal const val OBJC_SUBCLASSING_RESTRICTED = "objc_subclassing_restricted" + +private fun Deprecation.toDeprecationAttribute(): String { + val attribute = when (deprecationLevel) { + DeprecationLevelValue.WARNING -> "deprecated" + DeprecationLevelValue.ERROR, DeprecationLevelValue.HIDDEN -> "unavailable" + } + + // TODO: consider avoiding code generation for unavailable. + + val message = this.message.orEmpty() + + return "$attribute(${quoteAsCStringLiteral(message)})" +} + +private fun quoteAsCStringLiteral(str: String): String = buildString { + append('"') + for (c in str) { + when (c) { + '\n' -> append("\\n") + + '\r' -> append("\\r") + + '"', '\\' -> append('\\').append(c) + + // TODO: handle more special cases. + else -> append(c) + } + } + append('"') +} diff --git a/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/objcexport/ObjCExportHeaderGeneratorImpl.kt b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/objcexport/ObjCExportHeaderGeneratorImpl.kt new file mode 100644 index 00000000000..11b05b3f0ca --- /dev/null +++ b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/objcexport/ObjCExportHeaderGeneratorImpl.kt @@ -0,0 +1,44 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +package org.jetbrains.kotlin.backend.konan.objcexport + +import org.jetbrains.kotlin.backend.konan.Context +import org.jetbrains.kotlin.backend.konan.KonanConfigKeys +import org.jetbrains.kotlin.backend.konan.reportCompilationWarning +import org.jetbrains.kotlin.cli.common.messages.CompilerMessageSeverity +import org.jetbrains.kotlin.cli.common.messages.MessageUtil +import org.jetbrains.kotlin.descriptors.DeclarationDescriptorWithSource +import org.jetbrains.kotlin.descriptors.FunctionDescriptor +import org.jetbrains.kotlin.descriptors.ModuleDescriptor +import org.jetbrains.kotlin.renderer.DescriptorRenderer +import org.jetbrains.kotlin.resolve.source.getPsi + +internal class ObjCExportHeaderGeneratorImpl( + val context: Context, + moduleDescriptors: List, + mapper: ObjCExportMapper, + namer: ObjCExportNamer, + objcGenerics: Boolean +) : ObjCExportHeaderGenerator(moduleDescriptors, mapper, namer, objcGenerics) { + + override fun reportWarning(text: String) { + context.reportCompilationWarning(text) + } + + override fun reportWarning(method: FunctionDescriptor, text: String) { + val psi = (method as? DeclarationDescriptorWithSource)?.source?.getPsi() + ?: return reportWarning( + "$text\n (at ${DescriptorRenderer.COMPACT_WITH_SHORT_TYPES.render(method)})" + ) + + val location = MessageUtil.psiElementToMessageLocation(psi) + + context.messageCollector.report(CompilerMessageSeverity.WARNING, text, location) + } + + override fun getAdditionalImports(): List = + context.config.configuration.getNotNull(KonanConfigKeys.FRAMEWORK_IMPORT_HEADERS) +} diff --git a/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/objcexport/ObjCExportLazy.kt b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/objcexport/ObjCExportLazy.kt new file mode 100644 index 00000000000..60efb291d24 --- /dev/null +++ b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/objcexport/ObjCExportLazy.kt @@ -0,0 +1,464 @@ +/* + * Copyright 2010-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +package org.jetbrains.kotlin.backend.konan.objcexport + +import com.intellij.psi.PsiElement +import org.jetbrains.kotlin.analyzer.ModuleInfo +import org.jetbrains.kotlin.descriptors.konan.isNativeStdlib +import org.jetbrains.kotlin.builtins.KotlinBuiltIns +import org.jetbrains.kotlin.descriptors.* +import org.jetbrains.kotlin.descriptors.annotations.Annotations +import org.jetbrains.kotlin.descriptors.impl.PropertyDescriptorImpl +import org.jetbrains.kotlin.descriptors.impl.SimpleFunctionDescriptorImpl +import org.jetbrains.kotlin.lexer.KtTokens +import org.jetbrains.kotlin.name.ClassId +import org.jetbrains.kotlin.name.FqName +import org.jetbrains.kotlin.name.Name +import org.jetbrains.kotlin.psi.* +import org.jetbrains.kotlin.psi.psiUtil.containingClassOrObject +import org.jetbrains.kotlin.psi.psiUtil.hasExpectModifier +import org.jetbrains.kotlin.psi.psiUtil.modalityModifier +import org.jetbrains.kotlin.psi.psiUtil.visibilityModifierTypeOrDefault +import org.jetbrains.kotlin.resolve.BindingTrace +import org.jetbrains.kotlin.resolve.BindingTraceContext +import org.jetbrains.kotlin.resolve.DescriptorResolver +import org.jetbrains.kotlin.resolve.TypeResolver +import org.jetbrains.kotlin.resolve.deprecation.DeprecationResolver +import org.jetbrains.kotlin.resolve.descriptorUtil.module +import org.jetbrains.kotlin.resolve.lazy.FileScopeProvider +import org.jetbrains.kotlin.resolve.lazy.KotlinCodeAnalyzer +import org.jetbrains.kotlin.resolve.scopes.LexicalScope +import org.jetbrains.kotlin.resolve.scopes.LexicalScopeKind +import org.jetbrains.kotlin.resolve.scopes.LexicalWritableScope +import org.jetbrains.kotlin.resolve.scopes.LocalRedeclarationChecker +import org.jetbrains.kotlin.resolve.source.PsiSourceFile +import org.jetbrains.kotlin.types.ErrorUtils + +interface ObjCExportLazy { + interface Configuration { + val frameworkName: String + fun isIncluded(moduleInfo: ModuleInfo): Boolean + fun getCompilerModuleName(moduleInfo: ModuleInfo): String + val objcGenerics: Boolean + } + + fun generateBase(): List> + + fun translate(file: KtFile): List> +} + +@JvmOverloads +fun createObjCExportLazy( + configuration: ObjCExportLazy.Configuration, + warningCollector: ObjCExportWarningCollector, + codeAnalyzer: KotlinCodeAnalyzer, + typeResolver: TypeResolver, + descriptorResolver: DescriptorResolver, + fileScopeProvider: FileScopeProvider, + builtIns: KotlinBuiltIns, + deprecationResolver: DeprecationResolver? = null +): ObjCExportLazy = ObjCExportLazyImpl( + configuration, + warningCollector, + codeAnalyzer, + typeResolver, + descriptorResolver, + fileScopeProvider, + builtIns, + deprecationResolver +) + +internal class ObjCExportLazyImpl( + private val configuration: ObjCExportLazy.Configuration, + warningCollector: ObjCExportWarningCollector, + private val codeAnalyzer: KotlinCodeAnalyzer, + private val typeResolver: TypeResolver, + private val descriptorResolver: DescriptorResolver, + private val fileScopeProvider: FileScopeProvider, + builtIns: KotlinBuiltIns, + deprecationResolver: DeprecationResolver? +) : ObjCExportLazy { + + private val namerConfiguration = createNamerConfiguration(configuration) + + private val nameTranslator: ObjCExportNameTranslator = ObjCExportNameTranslatorImpl(namerConfiguration) + + private val mapper = ObjCExportMapper(deprecationResolver, local = true) + + private val namer = ObjCExportNamerImpl(namerConfiguration, builtIns, mapper, local = true) + + private val translator: ObjCExportTranslator = ObjCExportTranslatorImpl( + null, + mapper, + namer, + warningCollector, + objcGenerics = configuration.objcGenerics + ) + + private val isValid: Boolean + get() = codeAnalyzer.moduleDescriptor.isValid + + override fun generateBase() = translator.generateBaseDeclarations() + + override fun translate(file: KtFile): List> = + translateClasses(file) + translateTopLevels(file) + + private fun translateClasses(container: KtDeclarationContainer): List> { + val result = mutableListOf>() + container.declarations.forEach { declaration -> + // Supposed to be true if ObjCExportMapper.shouldBeVisible is true. + if (declaration is KtClassOrObject && declaration.isPublic && declaration !is KtEnumEntry + && !declaration.hasExpectModifier()) { + + if (!declaration.isAnnotation() && !declaration.hasModifier(KtTokens.INLINE_KEYWORD)) { + result += translateClass(declaration) + } + + declaration.body?.let { + result += translateClasses(it) + } + } + } + return result + } + + private fun translateClass(ktClassOrObject: KtClassOrObject): ObjCClass<*> { + val name = nameTranslator.getClassOrProtocolName(ktClassOrObject) + + // Note: some attributes may be missing (e.g. "unavailable" for unexposed classes). + + return if (ktClassOrObject.isInterface) { + LazyObjCProtocolImpl(name, ktClassOrObject, this) + } else { + val isFinal = ktClassOrObject.modalityModifier() == null || + ktClassOrObject.hasModifier(KtTokens.FINAL_KEYWORD) + + val attributes = if (isFinal) { + listOf(OBJC_SUBCLASSING_RESTRICTED) + } else { + emptyList() + } + + LazyObjCInterfaceImpl(name, + attributes, + generics = translateGenerics(ktClassOrObject), + psi = ktClassOrObject, + lazy = this) + } + } + + private fun translateGenerics(ktClassOrObject: KtClassOrObject): List = if (configuration.objcGenerics) { + ktClassOrObject.typeParametersWithOuter + .map { nameTranslator.getTypeParameterName(it) } + .toList() + } else { + emptyList() + } + + private fun translateTopLevels(file: KtFile): List { + val extensions = + mutableMapOf>() + + val topLevel = mutableListOf() + + file.children.filterIsInstance().forEach { + // Supposed to be similar to ObjCExportMapper.shouldBeVisible. + if ((it is KtFunction || it is KtProperty) && it.isPublic && !it.hasExpectModifier()) { + val classDescriptor = getClassIfExtension(it) + if (classDescriptor != null) { + extensions.getOrPut(classDescriptor, { mutableListOf() }) += it + } else { + topLevel += it + } + } + } + + val result = mutableListOf() + + extensions.mapTo(result) { (classDescriptor, declarations) -> + translateExtensions(file, classDescriptor, declarations) + } + + if (topLevel.isNotEmpty()) result += translateFileClass(file, topLevel) + + return result + } + + private fun translateFileClass(file: KtFile, declarations: List): ObjCInterface { + val name = nameTranslator.getFileClassName(file) + return LazyObjCFileInterface(name, file, declarations, this) + } + + private fun translateExtensions( + file: KtFile, + classDescriptor: ClassDescriptor, + declarations: List + ): ObjCInterface { + // TODO: consider using file-based categories in compiler too. + + val name = if (ErrorUtils.isError(classDescriptor)) { + ObjCExportNamer.ClassOrProtocolName("ERROR", "ERROR") + } else { + namer.getClassOrProtocolName(classDescriptor) + } + + return LazyObjCExtensionInterface(name, nameTranslator.getCategoryName(file), classDescriptor, declarations, this) + } + + private fun resolveDeclaration(ktDeclaration: KtDeclaration): DeclarationDescriptor = + codeAnalyzer.resolveToDescriptor(ktDeclaration) + + private fun resolve(ktClassOrObject: KtClassOrObject) = + resolveDeclaration(ktClassOrObject) as ClassDescriptor + + private fun resolve(ktCallableDeclaration: KtCallableDeclaration) = + resolveDeclaration(ktCallableDeclaration) as CallableMemberDescriptor + + private fun getClassIfExtension(topLevelDeclaration: KtCallableDeclaration): ClassDescriptor? { + val receiverType = topLevelDeclaration.receiverTypeReference ?: return null + val fileScope = fileScopeProvider.getFileResolutionScope(topLevelDeclaration.containingKtFile) + + val trace = BindingTraceContext() // TODO: revise. + + val kotlinReceiverType = typeResolver.resolveType( + createHeaderScope(topLevelDeclaration, fileScope, trace), + receiverType, + trace, + checkBounds = false + ) + + return translator.getClassIfExtension(kotlinReceiverType) + } + + private fun createHeaderScope( + declaration: KtCallableDeclaration, + parent: LexicalScope, + trace: BindingTrace + ): LexicalScope { + if (declaration.typeParameters.isEmpty()) return parent + + val fakeName = Name.special("") + val sourceElement = SourceElement.NO_SOURCE + + val descriptor: CallableMemberDescriptor + val scopeKind: LexicalScopeKind + + when (declaration) { + is KtFunction -> { + descriptor = SimpleFunctionDescriptorImpl.create( + parent.ownerDescriptor, + Annotations.EMPTY, + fakeName, + CallableMemberDescriptor.Kind.DECLARATION, + sourceElement + ) + scopeKind = LexicalScopeKind.FUNCTION_HEADER + } + is KtProperty -> { + descriptor = PropertyDescriptorImpl.create( + parent.ownerDescriptor, + Annotations.EMPTY, + Modality.FINAL, + DescriptorVisibilities.PUBLIC, + declaration.isVar, + fakeName, + CallableMemberDescriptor.Kind.DECLARATION, + sourceElement, + false, + false, + false, + false, + false, + false + ) + scopeKind = LexicalScopeKind.PROPERTY_HEADER + } + else -> TODO("${declaration::class}") + } + + val result = LexicalWritableScope( + parent, + descriptor, + false, + LocalRedeclarationChecker.DO_NOTHING, + scopeKind + ) + + val typeParameters = descriptorResolver.resolveTypeParametersForDescriptor( + descriptor, + result, + result, + declaration.typeParameters, + trace + ) + + descriptorResolver.resolveGenericBounds(declaration, descriptor, result, typeParameters, trace) + + return result + } + + private class LazyObjCProtocolImpl( + name: ObjCExportNamer.ClassOrProtocolName, + override val psi: KtClassOrObject, + private val lazy: ObjCExportLazyImpl + ) : LazyObjCProtocol(name) { + override val descriptor: ClassDescriptor by lazy { lazy.resolve(psi) } + + override val isValid: Boolean + get() = lazy.isValid + + override fun computeRealStub(): ObjCProtocol = lazy.translator.translateInterface(descriptor) + } + + private class LazyObjCInterfaceImpl( + name: ObjCExportNamer.ClassOrProtocolName, + attributes: List, + generics: List, + override val psi: KtClassOrObject, + private val lazy: ObjCExportLazyImpl + ) : LazyObjCInterface(name = name, generics = generics, categoryName = null, attributes = attributes) { + override val descriptor: ClassDescriptor by lazy { lazy.resolve(psi) } + + override val isValid: Boolean + get() = lazy.isValid + + override fun computeRealStub(): ObjCInterface = lazy.translator.translateClass(descriptor) + } + + private class LazyObjCFileInterface( + name: ObjCExportNamer.ClassOrProtocolName, + private val file: KtFile, + private val declarations: List, + private val lazy: ObjCExportLazyImpl + ) : LazyObjCInterface(name = name, generics = emptyList(), categoryName = null, attributes = listOf(OBJC_SUBCLASSING_RESTRICTED)) { + override val descriptor: ClassDescriptor? + get() = null + + override val isValid: Boolean + get() = lazy.isValid + + override val psi: PsiElement? + get() = null + + override fun computeRealStub(): ObjCInterface = lazy.translator.translateFile( + PsiSourceFile(file), + declarations.mapNotNull { declaration -> + lazy.resolve(declaration).takeIf { descriptor -> + lazy.mapper.shouldBeExposed(descriptor) + } + } + ) + } + + private class LazyObjCExtensionInterface( + name: ObjCExportNamer.ClassOrProtocolName, + categoryName: String, + private val classDescriptor: ClassDescriptor, + private val declarations: List, + private val lazy: ObjCExportLazyImpl + ) : LazyObjCInterface(name = name.objCName, generics = emptyList(), categoryName = categoryName, attributes = emptyList()) { + override val descriptor: ClassDescriptor? + get() = null + + override val isValid: Boolean + get() = lazy.isValid + + override val psi: PsiElement? + get() = null + + override fun computeRealStub(): ObjCInterface = lazy.translator.translateExtensions( + classDescriptor, + declarations.mapNotNull { declaration -> + lazy.resolve(declaration).takeIf { lazy.mapper.shouldBeExposed(it) } + } + ) + } +} + +private abstract class LazyObjCInterface : ObjCInterface { + + constructor( + name: ObjCExportNamer.ClassOrProtocolName, + generics: List, + categoryName: String?, + attributes: List + ) : super(name.objCName, generics, categoryName, attributes + name.toNameAttributes()) + + constructor( + name: String, + generics: List, + categoryName: String, + attributes: List + ) : super(name, generics, categoryName, attributes) + + protected abstract fun computeRealStub(): ObjCInterface + + private val realStub by lazy { computeRealStub() } + + override val members: List> + get() = realStub.members + + override val superProtocols: List + get() = realStub.superProtocols + + override val superClass: String? + get() = realStub.superClass + + override val superClassGenerics: List + get() = realStub.superClassGenerics +} + +private abstract class LazyObjCProtocol( + name: ObjCExportNamer.ClassOrProtocolName +) : ObjCProtocol(name.objCName, name.toNameAttributes()) { + + protected abstract fun computeRealStub(): ObjCProtocol + + private val realStub by lazy { computeRealStub() } + + override val members: List> + get() = realStub.members + + override val superProtocols: List + get() = realStub.superProtocols +} + +internal fun createNamerConfiguration(configuration: ObjCExportLazy.Configuration): ObjCExportNamer.Configuration { + return object : ObjCExportNamer.Configuration { + override val topLevelNamePrefix = abbreviate(configuration.frameworkName) + + override fun getAdditionalPrefix(module: ModuleDescriptor): String? { + if (module.isStdlib()) return "Kotlin" + + // Note: incorrect for compiler since it doesn't store ModuleInfo to ModuleDescriptor. + val moduleInfo = module.getCapability(ModuleInfo.Capability) ?: return null + if (configuration.isIncluded(moduleInfo)) return null + return abbreviate(configuration.getCompilerModuleName(moduleInfo)) + } + + override val objcGenerics = configuration.objcGenerics + } +} + +// TODO: find proper solution. +private fun ModuleDescriptor.isStdlib(): Boolean = + this.builtIns == this || this.isCommonStdlib() || this.isNativeStdlib() + +private val kotlinSequenceClassId = ClassId.topLevel(FqName("kotlin.sequences.Sequence")) + +private fun ModuleDescriptor.isCommonStdlib() = + this.findClassAcrossModuleDependencies(kotlinSequenceClassId)?.module == this + + +private val KtModifierListOwner.isPublic: Boolean + get() = this.visibilityModifierTypeOrDefault() == KtTokens.PUBLIC_KEYWORD + +internal val KtPureClassOrObject.isInterface: Boolean + get() = this is KtClass && this.isInterface() + +internal val KtClassOrObject.typeParametersWithOuter + get() = generateSequence(this, { if (it is KtClass && it.isInner()) it.containingClassOrObject else null }) + .flatMap { it.typeParameters.asSequence() } diff --git a/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/objcexport/ObjCExportLazyUtils.kt b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/objcexport/ObjCExportLazyUtils.kt new file mode 100644 index 00000000000..bdea63ee33e --- /dev/null +++ b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/objcexport/ObjCExportLazyUtils.kt @@ -0,0 +1,16 @@ +/* + * Copyright 2010-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +package org.jetbrains.kotlin.backend.konan.objcexport + +import org.jetbrains.kotlin.konan.file.File +import org.jetbrains.kotlin.psi.KtFile + +internal fun ObjCExportLazy.dumpObjCHeader(files: Collection, outputFile: String) { + val lines = (this.generateBase() + files.flatMap { this.translate(it) }) + .flatMap { StubRenderer.render(it) + listOf("") } + + File(outputFile).writeLines(lines) +} \ No newline at end of file diff --git a/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/objcexport/ObjCExportMapper.kt b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/objcexport/ObjCExportMapper.kt new file mode 100644 index 00000000000..0b5991c0dce --- /dev/null +++ b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/objcexport/ObjCExportMapper.kt @@ -0,0 +1,388 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +package org.jetbrains.kotlin.backend.konan.objcexport + +import org.jetbrains.kotlin.backend.common.descriptors.allParameters +import org.jetbrains.kotlin.backend.common.descriptors.isSuspend +import org.jetbrains.kotlin.backend.konan.* +import org.jetbrains.kotlin.backend.konan.descriptors.allOverriddenDescriptors +import org.jetbrains.kotlin.backend.konan.descriptors.isArray +import org.jetbrains.kotlin.backend.konan.descriptors.isInterface +import org.jetbrains.kotlin.builtins.* +import org.jetbrains.kotlin.descriptors.* +import org.jetbrains.kotlin.name.ClassId +import org.jetbrains.kotlin.resolve.deprecation.Deprecation +import org.jetbrains.kotlin.resolve.deprecation.DeprecationLevelValue +import org.jetbrains.kotlin.resolve.deprecation.DeprecationResolver +import org.jetbrains.kotlin.resolve.descriptorUtil.* +import org.jetbrains.kotlin.types.KotlinType +import org.jetbrains.kotlin.types.TypeUtils +import org.jetbrains.kotlin.types.typeUtil.isNothing +import org.jetbrains.kotlin.types.typeUtil.isUnit + +internal class ObjCExportMapper( + internal val deprecationResolver: DeprecationResolver? = null, + private val local: Boolean = false +) { + fun getCustomTypeMapper(descriptor: ClassDescriptor): CustomTypeMapper? = CustomTypeMappers.getMapper(descriptor) + + val hiddenTypes: Set get() = CustomTypeMappers.hiddenTypes + + fun isSpecialMapped(descriptor: ClassDescriptor): Boolean { + // TODO: this method duplicates some of the [ObjCExportTranslatorImpl.mapReferenceType] logic. + return KotlinBuiltIns.isAny(descriptor) || + descriptor.getAllSuperClassifiers().any { it is ClassDescriptor && CustomTypeMappers.hasMapper(it) } + } + + private val methodBridgeCache = mutableMapOf() + + fun bridgeMethod(descriptor: FunctionDescriptor): MethodBridge = if (local) { + bridgeMethodImpl(descriptor) + } else { + methodBridgeCache.getOrPut(descriptor) { + bridgeMethodImpl(descriptor) + } + } +} + +internal fun ObjCExportMapper.getClassIfCategory(descriptor: CallableMemberDescriptor): ClassDescriptor? { + if (descriptor.dispatchReceiverParameter != null) return null + + val extensionReceiverType = descriptor.extensionReceiverParameter?.type ?: return null + + return getClassIfCategory(extensionReceiverType) +} + +internal fun ObjCExportMapper.getClassIfCategory(extensionReceiverType: KotlinType): ClassDescriptor? { + // FIXME: this code must rely on type mapping instead of copying its logic. + + if (extensionReceiverType.isObjCObjectType()) return null + + val erasedClass = extensionReceiverType.getErasedTypeClass() + return if (!erasedClass.isInterface && !erasedClass.isInlined() && !this.isSpecialMapped(erasedClass)) { + erasedClass + } else { + // E.g. receiver is protocol, or some type with custom mapping. + null + } +} + +// Note: partially duplicated in ObjCExportLazyImpl.translateTopLevels. +internal fun ObjCExportMapper.shouldBeExposed(descriptor: CallableMemberDescriptor): Boolean = + descriptor.isEffectivelyPublicApi && !descriptor.isExpect && + !isHiddenByDeprecation(descriptor) + +internal fun ObjCExportMapper.shouldBeExposed(descriptor: ClassDescriptor): Boolean = + shouldBeVisible(descriptor) && !isSpecialMapped(descriptor) && !descriptor.defaultType.isObjCObjectType() + +private fun ObjCExportMapper.isHiddenByDeprecation(descriptor: CallableMemberDescriptor): Boolean { + // Note: ObjCExport generally expect overrides of exposed methods to be exposed. + // So don't hide a "deprecated hidden" method which overrides non-hidden one: + if (deprecationResolver != null && deprecationResolver.isDeprecatedHidden(descriptor) && + descriptor.overriddenDescriptors.all { isHiddenByDeprecation(it) }) { + return true + } + + // Note: ObjCExport expects members of unexposed classes to be unexposed too. + // So hide a declaration if it is from a hidden class: + val containingDeclaration = descriptor.containingDeclaration + if (containingDeclaration is ClassDescriptor && isHiddenByDeprecation(containingDeclaration)) { + return true + } + + return false +} + +internal fun ObjCExportMapper.getDeprecation(descriptor: DeclarationDescriptor): Deprecation? { + deprecationResolver?.getDeprecations(descriptor).orEmpty().maxByOrNull { + when (it.deprecationLevel) { + DeprecationLevelValue.WARNING -> 1 + DeprecationLevelValue.ERROR -> 2 + DeprecationLevelValue.HIDDEN -> 3 + } + }?.let { return it } + + (descriptor as? ConstructorDescriptor)?.let { + // Note: a deprecation can't be applied to a class itself when generating header + // since the class can be referred from the header. + // Apply class deprecations to its constructors instead: + return getDeprecation(it.constructedClass) + } + + return null +} + +private fun ObjCExportMapper.isHiddenByDeprecation(descriptor: ClassDescriptor): Boolean { + if (deprecationResolver == null) return false + if (deprecationResolver.isDeprecatedHidden(descriptor)) return true + + // Note: ObjCExport requires super class of exposed class to be exposed. + // So hide a class if its super class is hidden: + val superClass = descriptor.getSuperClassNotAny() + if (superClass != null && isHiddenByDeprecation(superClass)) { + return true + } + + // Note: ObjCExport requires enclosing class of exposed class to be exposed. + // Also in Kotlin hidden class members (including other classes) aren't directly accessible. + // So hide a class if its enclosing class is hidden: + val containingDeclaration = descriptor.containingDeclaration + if (containingDeclaration is ClassDescriptor && isHiddenByDeprecation(containingDeclaration)) { + return true + } + + return false +} + +// Note: the logic is partially duplicated in ObjCExportLazyImpl.translateClasses. +internal fun ObjCExportMapper.shouldBeVisible(descriptor: ClassDescriptor): Boolean = + descriptor.isEffectivelyPublicApi && when (descriptor.kind) { + ClassKind.CLASS, ClassKind.INTERFACE, ClassKind.ENUM_CLASS, ClassKind.OBJECT -> true + ClassKind.ENUM_ENTRY, ClassKind.ANNOTATION_CLASS -> false + } && !descriptor.isExpect && !descriptor.isInlined() && !isHiddenByDeprecation(descriptor) + +private fun ObjCExportMapper.isBase(descriptor: CallableMemberDescriptor): Boolean = + descriptor.overriddenDescriptors.all { !shouldBeExposed(it) } + // e.g. it is not `override`, or overrides only unexposed methods. + +internal fun ObjCExportMapper.isBaseMethod(descriptor: FunctionDescriptor) = + this.isBase(descriptor) + +internal fun ObjCExportMapper.getBaseMethods(descriptor: FunctionDescriptor): List = + if (isBaseMethod(descriptor)) { + listOf(descriptor) + } else { + descriptor.overriddenDescriptors.filter { shouldBeExposed(it) } + .flatMap { getBaseMethods(it.original)} + .distinct() + } + +internal fun ObjCExportMapper.isBaseProperty(descriptor: PropertyDescriptor) = + isBase(descriptor) + +internal fun ObjCExportMapper.getBaseProperties(descriptor: PropertyDescriptor): List = + if (isBaseProperty(descriptor)) { + listOf(descriptor) + } else { + descriptor.overriddenDescriptors + .flatMap { getBaseProperties(it.original) } + .distinct() + } + +internal tailrec fun KotlinType.getErasedTypeClass(): ClassDescriptor = + TypeUtils.getClassDescriptor(this) ?: this.constructor.supertypes.first().getErasedTypeClass() + +internal fun ObjCExportMapper.isTopLevel(descriptor: CallableMemberDescriptor): Boolean = + descriptor.containingDeclaration !is ClassDescriptor && this.getClassIfCategory(descriptor) == null + +internal fun ObjCExportMapper.isObjCProperty(property: PropertyDescriptor): Boolean = + property.extensionReceiverParameter == null || getClassIfCategory(property) != null + +internal fun ObjCExportMapper.doesThrow(method: FunctionDescriptor): Boolean = method.allOverriddenDescriptors.any { + it.overriddenDescriptors.isEmpty() && it.annotations.hasAnnotation(KonanFqNames.throws) +} + +private fun ObjCExportMapper.bridgeType( + kotlinType: KotlinType +): TypeBridge = kotlinType.unwrapToPrimitiveOrReference( + eachInlinedClass = { inlinedClass, _ -> + when (inlinedClass.classId) { + UnsignedType.UBYTE.classId -> return ValueTypeBridge(ObjCValueType.UNSIGNED_CHAR) + UnsignedType.USHORT.classId -> return ValueTypeBridge(ObjCValueType.UNSIGNED_SHORT) + UnsignedType.UINT.classId -> return ValueTypeBridge(ObjCValueType.UNSIGNED_INT) + UnsignedType.ULONG.classId -> return ValueTypeBridge(ObjCValueType.UNSIGNED_LONG_LONG) + } + }, + ifPrimitive = { primitiveType, _ -> + val objCValueType = when (primitiveType) { + KonanPrimitiveType.BOOLEAN -> ObjCValueType.BOOL + KonanPrimitiveType.CHAR -> ObjCValueType.UNICHAR + KonanPrimitiveType.BYTE -> ObjCValueType.CHAR + KonanPrimitiveType.SHORT -> ObjCValueType.SHORT + KonanPrimitiveType.INT -> ObjCValueType.INT + KonanPrimitiveType.LONG -> ObjCValueType.LONG_LONG + KonanPrimitiveType.FLOAT -> ObjCValueType.FLOAT + KonanPrimitiveType.DOUBLE -> ObjCValueType.DOUBLE + KonanPrimitiveType.NON_NULL_NATIVE_PTR -> ObjCValueType.POINTER + KonanPrimitiveType.VECTOR128 -> TODO() + } + ValueTypeBridge(objCValueType) + }, + ifReference = { + if (kotlinType.isFunctionType) { + bridgeFunctionType(kotlinType) + } else { + ReferenceBridge + } + } +) + +private fun ObjCExportMapper.bridgeFunctionType(kotlinType: KotlinType): TypeBridge { + // kotlinType.arguments include return type: + val numberOfParameters = kotlinType.arguments.size - 1 + + val returnType = kotlinType.getReturnTypeFromFunctionType() + val returnsVoid = returnType.isUnit() || returnType.isNothing() + // Note: this is correct because overriding method can't turn this into false + // neither for a parameter nor for a return type. + + return BlockPointerBridge(numberOfParameters, returnsVoid) +} + +private fun ObjCExportMapper.bridgeParameter(parameter: ParameterDescriptor): MethodBridgeValueParameter = + MethodBridgeValueParameter.Mapped(bridgeType(parameter.type)) + +private fun ObjCExportMapper.bridgeReturnType( + descriptor: FunctionDescriptor, + convertExceptionsToErrors: Boolean +): MethodBridge.ReturnValue { + val returnType = descriptor.returnType!! + return when { + descriptor.isSuspend -> MethodBridge.ReturnValue.Suspend + + descriptor is ConstructorDescriptor -> if (descriptor.constructedClass.isArray) { + MethodBridge.ReturnValue.Instance.FactoryResult + } else { + MethodBridge.ReturnValue.Instance.InitResult + }.let { + if (convertExceptionsToErrors) { + MethodBridge.ReturnValue.WithError.ZeroForError(it, successMayBeZero = false) + } else { + it + } + } + + descriptor.containingDeclaration == descriptor.builtIns.any && descriptor.name.asString() == "hashCode" -> { + assert(!convertExceptionsToErrors) + MethodBridge.ReturnValue.HashCode + } + + descriptor is PropertyGetterDescriptor -> { + assert(!convertExceptionsToErrors) + MethodBridge.ReturnValue.Mapped(bridgePropertyType(descriptor.correspondingProperty)) + } + + returnType.isUnit() || returnType.isNothing() -> if (convertExceptionsToErrors) { + MethodBridge.ReturnValue.WithError.Success + } else { + MethodBridge.ReturnValue.Void + } + + else -> { + val returnTypeBridge = bridgeType(returnType) + val successReturnValueBridge = MethodBridge.ReturnValue.Mapped(returnTypeBridge) + if (convertExceptionsToErrors) { + val canReturnZero = !returnTypeBridge.isReferenceOrPointer() || TypeUtils.isNullableType(returnType) + MethodBridge.ReturnValue.WithError.ZeroForError( + successReturnValueBridge, + successMayBeZero = canReturnZero + ) + } else { + successReturnValueBridge + } + } + } +} + +private fun TypeBridge.isReferenceOrPointer(): Boolean = when (this) { + ReferenceBridge, is BlockPointerBridge -> true + is ValueTypeBridge -> this.objCValueType == ObjCValueType.POINTER +} + +private fun ObjCExportMapper.bridgeMethodImpl(descriptor: FunctionDescriptor): MethodBridge { + assert(isBaseMethod(descriptor)) + + val convertExceptionsToErrors = this.doesThrow(descriptor) + + val kotlinParameters = descriptor.allParameters.iterator() + + val isTopLevel = isTopLevel(descriptor) + + val receiver = if (descriptor is ConstructorDescriptor && descriptor.constructedClass.isArray) { + kotlinParameters.next() + MethodBridgeReceiver.Factory + } else if (isTopLevel) { + MethodBridgeReceiver.Static + } else { + kotlinParameters.next() + MethodBridgeReceiver.Instance + } + + val valueParameters = mutableListOf() + kotlinParameters.forEach { + valueParameters += bridgeParameter(it) + } + + val returnBridge = bridgeReturnType(descriptor, convertExceptionsToErrors) + + if (descriptor.isSuspend) { + valueParameters += MethodBridgeValueParameter.SuspendCompletion + } else if (convertExceptionsToErrors) { + // Add error out parameter before tail block parameters. The convention allows this. + // Placing it after would trigger https://bugs.swift.org/browse/SR-12201 + // (see also https://github.com/JetBrains/kotlin-native/issues/3825). + val tailBlocksCount = valueParameters.reversed().takeWhile { it.isBlockPointer() }.count() + valueParameters.add(valueParameters.size - tailBlocksCount, MethodBridgeValueParameter.ErrorOutParameter) + } + + return MethodBridge(returnBridge, receiver, valueParameters) +} + +private fun MethodBridgeValueParameter.isBlockPointer(): Boolean = when (this) { + is MethodBridgeValueParameter.Mapped -> when (this.bridge) { + ReferenceBridge, is ValueTypeBridge -> false + is BlockPointerBridge -> true + } + MethodBridgeValueParameter.ErrorOutParameter -> false + MethodBridgeValueParameter.SuspendCompletion -> true +} + +internal fun ObjCExportMapper.bridgePropertyType(descriptor: PropertyDescriptor): TypeBridge { + assert(isBaseProperty(descriptor)) + + return bridgeType(descriptor.type) +} + +internal enum class NSNumberKind(val mappedKotlinClassId: ClassId?, val objCType: ObjCType) { + CHAR(PrimitiveType.BYTE, ObjCPrimitiveType.char), + UNSIGNED_CHAR(UnsignedType.UBYTE, ObjCPrimitiveType.unsigned_char), + SHORT(PrimitiveType.SHORT, ObjCPrimitiveType.short), + UNSIGNED_SHORT(UnsignedType.USHORT, ObjCPrimitiveType.unsigned_short), + INT(PrimitiveType.INT, ObjCPrimitiveType.int), + UNSIGNED_INT(UnsignedType.UINT, ObjCPrimitiveType.unsigned_int), + LONG(ObjCPrimitiveType.long), + UNSIGNED_LONG(ObjCPrimitiveType.unsigned_long), + LONG_LONG(PrimitiveType.LONG, ObjCPrimitiveType.long_long), + UNSIGNED_LONG_LONG(UnsignedType.ULONG, ObjCPrimitiveType.unsigned_long_long), + FLOAT(PrimitiveType.FLOAT, ObjCPrimitiveType.float), + DOUBLE(PrimitiveType.DOUBLE, ObjCPrimitiveType.double), + BOOL(PrimitiveType.BOOLEAN, ObjCPrimitiveType.BOOL), + INTEGER(ObjCPrimitiveType.NSInteger), + UNSIGNED_INTEGER(ObjCPrimitiveType.NSUInteger) + + ; + + // UNSIGNED_SHORT -> unsignedShort + private val kindName = this.name.split('_') + .joinToString("") { it.toLowerCase().capitalize() }.decapitalize() + + + val valueSelector = kindName // unsignedShort + val initSelector = "initWith${kindName.capitalize()}:" // initWithUnsignedShort: + val factorySelector = "numberWith${kindName.capitalize()}:" // numberWithUnsignedShort: + + constructor( + primitiveType: PrimitiveType, + objCPrimitiveType: ObjCPrimitiveType + ) : this(ClassId.topLevel(primitiveType.typeFqName), objCPrimitiveType) + + constructor( + unsignedType: UnsignedType, + objCPrimitiveType: ObjCPrimitiveType + ) : this(unsignedType.classId, objCPrimitiveType) + + constructor(objCPrimitiveType: ObjCPrimitiveType) : this(null, objCPrimitiveType) +} diff --git a/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/objcexport/ObjCExportNamer.kt b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/objcexport/ObjCExportNamer.kt new file mode 100644 index 00000000000..3e06c627ed5 --- /dev/null +++ b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/objcexport/ObjCExportNamer.kt @@ -0,0 +1,903 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +package org.jetbrains.kotlin.backend.konan.objcexport + +import org.jetbrains.kotlin.backend.common.serialization.findSourceFile +import org.jetbrains.kotlin.backend.konan.cKeywords +import org.jetbrains.kotlin.backend.konan.descriptors.isArray +import org.jetbrains.kotlin.backend.konan.descriptors.isInterface +import org.jetbrains.kotlin.descriptors.konan.isNativeStdlib +import org.jetbrains.kotlin.builtins.KotlinBuiltIns +import org.jetbrains.kotlin.descriptors.* +import org.jetbrains.kotlin.descriptors.konan.* +import org.jetbrains.kotlin.incremental.components.NoLookupLocation +import org.jetbrains.kotlin.library.shortName +import org.jetbrains.kotlin.library.uniqueName +import org.jetbrains.kotlin.load.kotlin.PackagePartClassUtils +import org.jetbrains.kotlin.name.ClassId +import org.jetbrains.kotlin.name.Name +import org.jetbrains.kotlin.psi.* +import org.jetbrains.kotlin.psi.psiUtil.getStrictParentOfType +import org.jetbrains.kotlin.resolve.descriptorUtil.isSubclassOf +import org.jetbrains.kotlin.resolve.descriptorUtil.module +import org.jetbrains.kotlin.resolve.descriptorUtil.propertyIfAccessor +import org.jetbrains.kotlin.resolve.source.PsiSourceFile + +internal interface ObjCExportNameTranslator { + fun getFileClassName(file: KtFile): ObjCExportNamer.ClassOrProtocolName + + fun getCategoryName(file: KtFile): String + + fun getClassOrProtocolName( + ktClassOrObject: KtClassOrObject + ): ObjCExportNamer.ClassOrProtocolName + + fun getTypeParameterName(ktTypeParameter: KtTypeParameter): String +} + +interface ObjCExportNamer { + data class ClassOrProtocolName(val swiftName: String, val objCName: String, val binaryName: String = objCName) + + interface Configuration { + val topLevelNamePrefix: String + fun getAdditionalPrefix(module: ModuleDescriptor): String? + val objcGenerics: Boolean + } + + val topLevelNamePrefix: String + + fun getFileClassName(file: SourceFile): ClassOrProtocolName + fun getClassOrProtocolName(descriptor: ClassDescriptor): ClassOrProtocolName + fun getSelector(method: FunctionDescriptor): String + fun getSwiftName(method: FunctionDescriptor): String + fun getPropertyName(property: PropertyDescriptor): String + fun getObjectInstanceSelector(descriptor: ClassDescriptor): String + fun getEnumEntrySelector(descriptor: ClassDescriptor): String + fun getTypeParameterName(typeParameterDescriptor: TypeParameterDescriptor): String + + fun numberBoxName(classId: ClassId): ClassOrProtocolName + + val kotlinAnyName: ClassOrProtocolName + val mutableSetName: ClassOrProtocolName + val mutableMapName: ClassOrProtocolName + val kotlinNumberName: ClassOrProtocolName +} + +fun createNamer(moduleDescriptor: ModuleDescriptor, + topLevelNamePrefix: String = moduleDescriptor.namePrefix): ObjCExportNamer = + createNamer(moduleDescriptor, emptyList(), topLevelNamePrefix) + +fun createNamer( + moduleDescriptor: ModuleDescriptor, + exportedDependencies: List, + topLevelNamePrefix: String = moduleDescriptor.namePrefix +): ObjCExportNamer = ObjCExportNamerImpl( + (exportedDependencies + moduleDescriptor).toSet(), + moduleDescriptor.builtIns, + ObjCExportMapper(local = true), + topLevelNamePrefix, + local = true +) + +// Note: this class duplicates some of ObjCExportNamerImpl logic, +// but operates on different representation. +internal open class ObjCExportNameTranslatorImpl( + configuration: ObjCExportNamer.Configuration +) : ObjCExportNameTranslator { + + private val helper = ObjCExportNamingHelper(configuration.topLevelNamePrefix, configuration.objcGenerics) + + override fun getFileClassName(file: KtFile): ObjCExportNamer.ClassOrProtocolName = + helper.getFileClassName(file) + + override fun getCategoryName(file: KtFile): String = + helper.translateFileName(file) + + override fun getClassOrProtocolName( + ktClassOrObject: KtClassOrObject + ): ObjCExportNamer.ClassOrProtocolName = helper.swiftClassNameToObjC( + getClassOrProtocolSwiftName(ktClassOrObject) + ) + + private fun getClassOrProtocolSwiftName( + ktClassOrObject: KtClassOrObject + ): String = buildString { + val outerClass = ktClassOrObject.getStrictParentOfType() + if (outerClass != null) { + appendNameWithContainer(ktClassOrObject, outerClass) + } else { + append(ktClassOrObject.name!!.toIdentifier()) + } + } + + private fun StringBuilder.appendNameWithContainer( + ktClassOrObject: KtClassOrObject, + outerClass: KtClassOrObject + ) = helper.appendNameWithContainer( + this, + ktClassOrObject, ktClassOrObject.name!!.toIdentifier(), + outerClass, getClassOrProtocolSwiftName(outerClass), + object : ObjCExportNamingHelper.ClassInfoProvider { + override fun hasGenerics(clazz: KtClassOrObject): Boolean = + clazz.typeParametersWithOuter.count() != 0 + + override fun isInterface(clazz: KtClassOrObject): Boolean = ktClassOrObject.isInterface + } + ) + + override fun getTypeParameterName(ktTypeParameter: KtTypeParameter): String = buildString { + append(ktTypeParameter.name!!.toIdentifier()) + while (helper.isTypeParameterNameReserved(this.toString())) append('_') + } +} + +private class ObjCExportNamingHelper( + private val topLevelNamePrefix: String, + private val objcGenerics: Boolean +) { + + fun translateFileName(fileName: String): String = + PackagePartClassUtils.getFilePartShortName(fileName).toIdentifier() + + fun translateFileName(file: KtFile): String = translateFileName(file.name) + + fun getFileClassName(fileName: String): ObjCExportNamer.ClassOrProtocolName { + val baseName = translateFileName(fileName) + return ObjCExportNamer.ClassOrProtocolName(swiftName = baseName, objCName = "$topLevelNamePrefix$baseName") + } + + fun swiftClassNameToObjC(swiftName: String): ObjCExportNamer.ClassOrProtocolName = + ObjCExportNamer.ClassOrProtocolName(swiftName, buildString { + append(topLevelNamePrefix) + swiftName.split('.').forEachIndexed { index, part -> + append(if (index == 0) part else part.capitalize()) + } + }) + + fun getFileClassName(file: KtFile): ObjCExportNamer.ClassOrProtocolName = + getFileClassName(file.name) + + fun appendNameWithContainer( + builder: StringBuilder, + clazz: T, + ownName: String, + containingClass: T, + containerName: String, + provider: ClassInfoProvider + ) = builder.apply { + if (clazz.canBeSwiftInner(provider)) { + append(containerName) + if (!this.contains('.') && containingClass.canBeSwiftOuter(provider)) { + // AB -> AB.C + append('.') + append(mangleSwiftNestedClassName(ownName)) + } else { + // AB -> ABC + // A.B -> A.BC + append(ownName.capitalize()) + } + } else { + // AB, A.B -> ABC + val dotIndex = containerName.indexOf('.') + if (dotIndex == -1) { + append(containerName) + } else { + append(containerName.substring(0, dotIndex)) + append(containerName.substring(dotIndex + 1).capitalize()) + } + append(ownName.capitalize()) + } + } + + interface ClassInfoProvider { + fun hasGenerics(clazz: T): Boolean + fun isInterface(clazz: T): Boolean + } + + private fun T.canBeSwiftOuter(provider: ClassInfoProvider): Boolean = when { + objcGenerics && provider.hasGenerics(this) -> { + // Swift nested classes are static but capture outer's generics. + false + } + + provider.isInterface(this) -> { + // Swift doesn't support outer protocols. + false + } + + else -> true + } + + private fun T.canBeSwiftInner(provider: ClassInfoProvider): Boolean = when { + objcGenerics && provider.hasGenerics(this) -> { + // Swift compiler doesn't seem to handle this case properly. + false + } + + provider.isInterface(this) -> { + // Swift doesn't support nested protocols. + false + } + + else -> true + } + + fun mangleSwiftNestedClassName(name: String): String = when (name) { + "Type" -> "${name}_" // See https://github.com/JetBrains/kotlin-native/issues/3167 + else -> name + } + + fun isTypeParameterNameReserved(name: String): Boolean = name in reservedTypeParameterNames + + private val reservedTypeParameterNames = setOf("id", "NSObject", "NSArray", "NSCopying", "NSNumber", "NSInteger", + "NSUInteger", "NSString", "NSSet", "NSDictionary", "NSMutableArray", "int", "unsigned", "short", + "char", "long", "float", "double", "int32_t", "int64_t", "int16_t", "int8_t", "unichar") +} + +internal class ObjCExportNamerImpl( + private val configuration: ObjCExportNamer.Configuration, + builtIns: KotlinBuiltIns, + private val mapper: ObjCExportMapper, + private val local: Boolean +) : ObjCExportNamer { + + constructor( + moduleDescriptors: Set, + builtIns: KotlinBuiltIns, + mapper: ObjCExportMapper, + topLevelNamePrefix: String, + local: Boolean, + objcGenerics: Boolean = false + ) : this( + object : ObjCExportNamer.Configuration { + override val topLevelNamePrefix: String + get() = topLevelNamePrefix + + override fun getAdditionalPrefix(module: ModuleDescriptor): String? = + if (module in moduleDescriptors) null else module.namePrefix + + override val objcGenerics: Boolean + get() = objcGenerics + + }, + builtIns, + mapper, + local + ) + + private val objcGenerics get() = configuration.objcGenerics + override val topLevelNamePrefix get() = configuration.topLevelNamePrefix + private val helper = ObjCExportNamingHelper(configuration.topLevelNamePrefix, objcGenerics) + + private fun String.toSpecialStandardClassOrProtocolName() = ObjCExportNamer.ClassOrProtocolName( + swiftName = "Kotlin$this", + objCName = "${topLevelNamePrefix}$this" + ) + + override val kotlinAnyName = "Base".toSpecialStandardClassOrProtocolName() + + override val mutableSetName = "MutableSet".toSpecialStandardClassOrProtocolName() + override val mutableMapName = "MutableDictionary".toSpecialStandardClassOrProtocolName() + + override fun numberBoxName(classId: ClassId): ObjCExportNamer.ClassOrProtocolName = + classId.shortClassName.asString().toSpecialStandardClassOrProtocolName() + + override val kotlinNumberName = "Number".toSpecialStandardClassOrProtocolName() + + private val methodSelectors = object : Mapping() { + + // Try to avoid clashing with critical NSObject instance methods: + + private val reserved = setOf( + "retain", "release", "autorelease", + "class", "superclass", + "hash" + ) + + override fun reserved(name: String) = name in reserved + + override fun conflict(first: FunctionDescriptor, second: FunctionDescriptor): Boolean = + !mapper.canHaveSameSelector(first, second) + } + + private val methodSwiftNames = object : Mapping() { + override fun conflict(first: FunctionDescriptor, second: FunctionDescriptor): Boolean = + !mapper.canHaveSameSelector(first, second) + // Note: this condition is correct but can be too strict. + } + + private val propertyNames = object : Mapping() { + override fun reserved(name: String) = name in Reserved.propertyNames + + override fun conflict(first: PropertyDescriptor, second: PropertyDescriptor): Boolean = + !mapper.canHaveSameName(first, second) + } + + private open inner class GlobalNameMapping : Mapping() { + final override fun conflict(first: T, second: T): Boolean = true + } + + private val objCClassNames = GlobalNameMapping() + private val objCProtocolNames = GlobalNameMapping() + + // Classes and protocols share the same namespace in Swift. + private val swiftClassAndProtocolNames = GlobalNameMapping() + + private val genericTypeParameterNameMapping = GenericTypeParameterNameMapping() + + private abstract inner class ClassPropertyNameMapping : Mapping() { + + // Try to avoid clashing with NSObject class methods: + + private val reserved = setOf( + "retain", "release", "autorelease", + "initialize", "load", "alloc", "new", "class", "superclass", + "classFallbacksForKeyedArchiver", "classForKeyedUnarchiver", + "description", "debugDescription", "version", "hash", + "useStoredAccessor" + ) + + override fun reserved(name: String) = (name in reserved) || (name in cKeywords) + } + + private val objectInstanceSelectors = object : ClassPropertyNameMapping() { + override fun conflict(first: ClassDescriptor, second: ClassDescriptor) = false + } + + private val enumEntrySelectors = object : ClassPropertyNameMapping() { + override fun conflict(first: ClassDescriptor, second: ClassDescriptor) = + first.containingDeclaration == second.containingDeclaration + } + + override fun getFileClassName(file: SourceFile): ObjCExportNamer.ClassOrProtocolName { + val candidate by lazy { + val fileName = when (file) { + is PsiSourceFile -> { + val psiFile = file.psiFile + val ktFile = psiFile as? KtFile ?: error("PsiFile '$psiFile' is not KtFile") + ktFile.name + } + else -> file.name ?: error("$file has no name") + } + helper.getFileClassName(fileName) + } + + val objCName = objCClassNames.getOrPut(file) { + StringBuilder(candidate.objCName).mangledBySuffixUnderscores() + } + + val swiftName = swiftClassAndProtocolNames.getOrPut(file) { + StringBuilder(candidate.swiftName).mangledBySuffixUnderscores() + } + + return ObjCExportNamer.ClassOrProtocolName(swiftName = swiftName, objCName = objCName) + } + + override fun getClassOrProtocolName(descriptor: ClassDescriptor): ObjCExportNamer.ClassOrProtocolName = + ObjCExportNamer.ClassOrProtocolName( + swiftName = getClassOrProtocolSwiftName(descriptor), + objCName = getClassOrProtocolObjCName(descriptor) + ) + + private fun getClassOrProtocolSwiftName( + descriptor: ClassDescriptor + ): String = swiftClassAndProtocolNames.getOrPut(descriptor) { + StringBuilder().apply { + val containingDeclaration = descriptor.containingDeclaration + if (containingDeclaration is ClassDescriptor) { + appendNameWithContainer(descriptor, containingDeclaration) + } else if (containingDeclaration is PackageFragmentDescriptor) { + appendTopLevelClassBaseName(descriptor) + } else { + error("unexpected class parent: $containingDeclaration") + } + }.mangledBySuffixUnderscores() + } + + private fun StringBuilder.appendNameWithContainer( + clazz: ClassDescriptor, + containingClass: ClassDescriptor + ) = helper.appendNameWithContainer( + this, + clazz, clazz.name.asString().toIdentifier(), + containingClass, getClassOrProtocolSwiftName(containingClass), + object : ObjCExportNamingHelper.ClassInfoProvider { + override fun hasGenerics(clazz: ClassDescriptor): Boolean = + clazz.typeConstructor.parameters.isNotEmpty() + + override fun isInterface(clazz: ClassDescriptor): Boolean = clazz.isInterface + } + ) + + private fun getClassOrProtocolObjCName(descriptor: ClassDescriptor): String { + val objCMapping = if (descriptor.isInterface) objCProtocolNames else objCClassNames + return objCMapping.getOrPut(descriptor) { + StringBuilder().apply { + val containingDeclaration = descriptor.containingDeclaration + if (containingDeclaration is ClassDescriptor) { + append(getClassOrProtocolObjCName(containingDeclaration)) + .append(descriptor.name.asString().toIdentifier().capitalize()) + + } else if (containingDeclaration is PackageFragmentDescriptor) { + append(topLevelNamePrefix).appendTopLevelClassBaseName(descriptor) + } else { + error("unexpected class parent: $containingDeclaration") + } + }.mangledBySuffixUnderscores() + } + } + + private fun StringBuilder.appendTopLevelClassBaseName(descriptor: ClassDescriptor) = apply { + configuration.getAdditionalPrefix(descriptor.module)?.let { + append(it) + } + append(descriptor.name.asString().toIdentifier()) + } + + override fun getSelector(method: FunctionDescriptor): String = methodSelectors.getOrPut(method) { + assert(mapper.isBaseMethod(method)) + + getPredefined(method, Predefined.anyMethodSelectors)?.let { return it } + + val parameters = mapper.bridgeMethod(method).valueParametersAssociated(method) + + StringBuilder().apply { + append(method.getMangledName(forSwift = false)) + + parameters.forEachIndexed { index, (bridge, it) -> + val name = when (bridge) { + is MethodBridgeValueParameter.Mapped -> when { + it is ReceiverParameterDescriptor -> "" + method is PropertySetterDescriptor -> when (parameters.size) { + 1 -> "" + else -> "value" + } + else -> it!!.name.asString().toIdentifier() + } + MethodBridgeValueParameter.ErrorOutParameter -> "error" + MethodBridgeValueParameter.SuspendCompletion -> "completionHandler" + } + + if (index == 0) { + append(when { + bridge is MethodBridgeValueParameter.ErrorOutParameter -> "AndReturn" + + bridge is MethodBridgeValueParameter.SuspendCompletion -> "With" + + method is ConstructorDescriptor -> "With" + + else -> "" + }) + append(name.capitalize()) + } else { + append(name) + } + + append(':') + } + }.mangledSequence { + if (parameters.isNotEmpty()) { + // "foo:" -> "foo_:" + insert(lastIndex, '_') + } else { + // "foo" -> "foo_" + append("_") + } + } + } + + override fun getSwiftName(method: FunctionDescriptor): String = methodSwiftNames.getOrPut(method) { + assert(mapper.isBaseMethod(method)) + + getPredefined(method, Predefined.anyMethodSwiftNames)?.let { return it } + + val parameters = mapper.bridgeMethod(method).valueParametersAssociated(method) + + StringBuilder().apply { + append(method.getMangledName(forSwift = true)) + append("(") + + parameters@ for ((bridge, it) in parameters) { + val label = when (bridge) { + is MethodBridgeValueParameter.Mapped -> when { + it is ReceiverParameterDescriptor -> "_" + method is PropertySetterDescriptor -> when (parameters.size) { + 1 -> "_" + else -> "value" + } + else -> it!!.name.asString().toIdentifier() + } + MethodBridgeValueParameter.ErrorOutParameter -> continue@parameters + MethodBridgeValueParameter.SuspendCompletion -> "completionHandler" + } + + append(label) + append(":") + } + + append(")") + }.mangledSequence { + // "foo(label:)" -> "foo(label_:)" + // "foo()" -> "foo_()" + insert(lastIndex - 1, '_') + } + } + + private fun getPredefined(method: FunctionDescriptor, predefinedForAny: Map): T? { + return if (method.containingDeclaration.let { it is ClassDescriptor && KotlinBuiltIns.isAny(it) }) { + predefinedForAny.getValue(method.name) + } else { + null + } + } + + override fun getPropertyName(property: PropertyDescriptor): String = propertyNames.getOrPut(property) { + assert(mapper.isBaseProperty(property)) + assert(mapper.isObjCProperty(property)) + + StringBuilder().apply { + append(property.name.asString().toIdentifier()) + }.mangledSequence { + append('_') + } + } + + override fun getObjectInstanceSelector(descriptor: ClassDescriptor): String { + assert(descriptor.kind == ClassKind.OBJECT) + + return objectInstanceSelectors.getOrPut(descriptor) { + val name = descriptor.name.asString().decapitalize().toIdentifier().mangleIfSpecialFamily("get") + + StringBuilder(name).mangledBySuffixUnderscores() + } + } + + override fun getEnumEntrySelector(descriptor: ClassDescriptor): String { + assert(descriptor.kind == ClassKind.ENUM_ENTRY) + + return enumEntrySelectors.getOrPut(descriptor) { + // FOO_BAR_BAZ -> fooBarBaz: + val name = descriptor.name.asString().split('_').mapIndexed { index, s -> + val lower = s.toLowerCase() + if (index == 0) lower else lower.capitalize() + }.joinToString("").toIdentifier().mangleIfSpecialFamily("the") + + StringBuilder(name).mangledBySuffixUnderscores() + } + } + + override fun getTypeParameterName(typeParameterDescriptor: TypeParameterDescriptor): String { + return genericTypeParameterNameMapping.getOrPut(typeParameterDescriptor) { + StringBuilder().apply { + append(typeParameterDescriptor.name.asString().toIdentifier()) + }.mangledSequence { + append('_') + } + } + } + + init { + if (!local) { + forceAssignPredefined(builtIns) + } + } + + private fun forceAssignPredefined(builtIns: KotlinBuiltIns) { + val any = builtIns.any + + val predefinedClassNames = mapOf( + builtIns.any to kotlinAnyName, + builtIns.mutableSet to mutableSetName, + builtIns.mutableMap to mutableMapName + ) + + predefinedClassNames.forEach { descriptor, name -> + objCClassNames.forceAssign(descriptor, name.objCName) + swiftClassAndProtocolNames.forceAssign(descriptor, name.swiftName) + } + + fun ClassDescriptor.method(name: Name) = + this.unsubstitutedMemberScope.getContributedFunctions( + name, + NoLookupLocation.FROM_BACKEND + ).single() + + Predefined.anyMethodSelectors.forEach { name, selector -> + methodSelectors.forceAssign(any.method(name), selector) + } + + Predefined.anyMethodSwiftNames.forEach { name, swiftName -> + methodSwiftNames.forceAssign(any.method(name), swiftName) + } + } + + private object Predefined { + val anyMethodSelectors = mapOf( + "hashCode" to "hash", + "toString" to "description", + "equals" to "isEqual:" + ).mapKeys { Name.identifier(it.key) } + + val anyMethodSwiftNames = mapOf( + "hashCode" to "hash()", + "toString" to "description()", + "equals" to "isEqual(_:)" + ).mapKeys { Name.identifier(it.key) } + } + + private object Reserved { + val propertyNames = cKeywords + + setOf("description") // https://youtrack.jetbrains.com/issue/KT-38641 + } + + private fun FunctionDescriptor.getMangledName(forSwift: Boolean): String { + if (this is ConstructorDescriptor) { + return if (this.constructedClass.isArray && !forSwift) "array" else "init" + } + + val candidate = when (this) { + is PropertyGetterDescriptor -> this.correspondingProperty.name.asString() + is PropertySetterDescriptor -> "set${this.correspondingProperty.name.asString().capitalize()}" + else -> this.name.asString() + }.toIdentifier() + + return candidate.mangleIfSpecialFamily("do") + } + + private fun String.mangleIfSpecialFamily(prefix: String): String { + val trimmed = this.dropWhile { it == '_' } + for (family in listOf("alloc", "copy", "mutableCopy", "new", "init")) { + if (trimmed.startsWithWords(family)) { + // Then method can be detected as having special family by Objective-C compiler. + // mangle the name: + return prefix + this.capitalize() + } + } + + // TODO: handle clashes with NSObject methods etc. + + return this + } + + private fun String.startsWithWords(words: String) = this.startsWith(words) && + (this.length == words.length || !this[words.length].isLowerCase()) + + private inner class GenericTypeParameterNameMapping { + private val elementToName = mutableMapOf() + private val typeParameterNameClassOverrides = mutableMapOf>() + + fun getOrPut(element: TypeParameterDescriptor, nameCandidates: () -> Sequence): String { + getIfAssigned(element)?.let { return it } + + nameCandidates().forEach { + if (tryAssign(element, it)) { + return it + } + } + + error("name candidates run out") + } + + private fun tryAssign(element: TypeParameterDescriptor, name: String): Boolean { + if (element in elementToName) error(element) + + if (helper.isTypeParameterNameReserved(name)) return false + + if (!validName(element, name)) return false + + assignName(element, name) + + return true + } + + private fun assignName(element: TypeParameterDescriptor, name: String) { + if (!local) { + elementToName[element] = name + classNameSet(element).add(name) + } + } + + private fun validName(element: TypeParameterDescriptor, name: String): Boolean { + assert(element.containingDeclaration is ClassDescriptor) + + return !objCClassNames.nameExists(name) && !objCProtocolNames.nameExists(name) && + (local || name !in classNameSet(element)) + } + + private fun classNameSet(element: TypeParameterDescriptor): MutableSet { + require(!local) + return typeParameterNameClassOverrides.getOrPut(element.containingDeclaration as ClassDescriptor) { + mutableSetOf() + } + } + + private fun getIfAssigned(element: TypeParameterDescriptor): String? = elementToName[element] + } + + private abstract inner class Mapping() { + private val elementToName = mutableMapOf() + private val nameToElements = mutableMapOf>() + + abstract fun conflict(first: T, second: T): Boolean + open fun reserved(name: N) = false + inline fun getOrPut(element: T, nameCandidates: () -> Sequence): N { + getIfAssigned(element)?.let { return it } + + nameCandidates().forEach { + if (tryAssign(element, it)) { + return it + } + } + + error("name candidates run out") + } + + fun nameExists(name: N) = nameToElements.containsKey(name) + + private fun getIfAssigned(element: T): N? = elementToName[element] + + private fun tryAssign(element: T, name: N): Boolean { + if (element in elementToName) error(element) + + if (reserved(name)) return false + + if (nameToElements[name].orEmpty().any { conflict(element, it) }) { + return false + } + + if (!local) { + nameToElements.getOrPut(name) { mutableListOf() } += element + + elementToName[element] = name + } + + return true + } + + fun forceAssign(element: T, name: N) { + if (name in nameToElements || element in elementToName) error(element) + + nameToElements[name] = mutableListOf(element) + elementToName[element] = name + } + } + +} + +private inline fun StringBuilder.mangledSequence(crossinline mangle: StringBuilder.() -> Unit) = + generateSequence(this.toString()) { + this@mangledSequence.mangle() + this@mangledSequence.toString() + } + +private fun StringBuilder.mangledBySuffixUnderscores() = this.mangledSequence { append("_") } + +private fun ObjCExportMapper.canHaveCommonSubtype(first: ClassDescriptor, second: ClassDescriptor): Boolean { + if (first.isSubclassOf(second) || second.isSubclassOf(first)) { + return true + } + + if (first.isFinalClass || second.isFinalClass) { + return false + } + + return first.isInterface || second.isInterface +} + +private fun ObjCExportMapper.canBeInheritedBySameClass( + first: CallableMemberDescriptor, + second: CallableMemberDescriptor +): Boolean { + if (this.isTopLevel(first) || this.isTopLevel(second)) { + return this.isTopLevel(first) && this.isTopLevel(second) && + first.propertyIfAccessor.findSourceFile() == second.propertyIfAccessor.findSourceFile() + } + + val firstClass = this.getClassIfCategory(first) ?: first.containingDeclaration as ClassDescriptor + val secondClass = this.getClassIfCategory(second) ?: second.containingDeclaration as ClassDescriptor + + if (first is ConstructorDescriptor) { + return firstClass == secondClass || second !is ConstructorDescriptor && firstClass.isSubclassOf(secondClass) + } + + if (second is ConstructorDescriptor) { + return secondClass == firstClass || first !is ConstructorDescriptor && secondClass.isSubclassOf(firstClass) + } + + return canHaveCommonSubtype(firstClass, secondClass) +} + +private fun ObjCExportMapper.canHaveSameSelector(first: FunctionDescriptor, second: FunctionDescriptor): Boolean { + assert(isBaseMethod(first)) + assert(isBaseMethod(second)) + + if (!canBeInheritedBySameClass(first, second)) { + return true + } + + if (first.dispatchReceiverParameter == null || second.dispatchReceiverParameter == null) { + // I.e. any is category method. + return false + } + + if (first.name != second.name) { + return false + } + if (first.extensionReceiverParameter?.type != second.extensionReceiverParameter?.type) { + return false + } + + if (first is PropertySetterDescriptor && second is PropertySetterDescriptor) { + // Methods should merge in any common subclass as it can't have two properties with same name. + } else if (first.valueParameters.map { it.type } == second.valueParameters.map { it.type }) { + // Methods should merge in any common subclasses since they have the same signature. + } else { + return false + } + + // Check if methods have the same bridge (and thus the same ABI): + return bridgeMethod(first) == bridgeMethod(second) +} + +private fun ObjCExportMapper.canHaveSameName(first: PropertyDescriptor, second: PropertyDescriptor): Boolean { + assert(isBaseProperty(first)) + assert(isObjCProperty(first)) + assert(isBaseProperty(second)) + assert(isObjCProperty(second)) + + if (!canBeInheritedBySameClass(first, second)) { + return true + } + + if (first.dispatchReceiverParameter == null || second.dispatchReceiverParameter == null) { + // I.e. any is category property. + return false + } + + if (first.name != second.name) { + return false + } + + return bridgePropertyType(first) == bridgePropertyType(second) +} + +internal val ModuleDescriptor.namePrefix: String get() { + if (this.isNativeStdlib()) return "Kotlin" + + val fullPrefix = when(val module = this.klibModuleOrigin) { + CurrentKlibModuleOrigin, SyntheticModulesOrigin -> + this.name.asString().let { it.substring(1, it.lastIndex) } + is DeserializedKlibModuleOrigin -> + module.library.let { it.shortName ?: it.uniqueName } + } + + return abbreviate(fullPrefix) +} + +fun abbreviate(name: String): String { + val normalizedName = name + .capitalize() + .replace("-|\\.".toRegex(), "_") + + val uppers = normalizedName.filterIndexed { index, character -> index == 0 || character.isUpperCase() } + if (uppers.length >= 3) return uppers + + return normalizedName +} + +// Note: most usages of this method rely on the fact that concatenation of valid identifiers is valid identifier. +// This may sometimes be a bit conservative (since it requires mangling non-first character as if it was first); +// ignore this for simplicity as having Kotlin identifiers starting from digits is supposed to be rare case. +internal fun String.toValidObjCSwiftIdentifier(): String { + if (this.isEmpty()) return "__" + + return this.replace('$', '_') // TODO: handle more special characters. + .let { if (it.first().isDigit()) "_$it" else it } + .let { if (it == "_") "__" else it } +} + +// Private shortcut. +private fun String.toIdentifier(): String = this.toValidObjCSwiftIdentifier() diff --git a/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/objcexport/ObjcExportHeaderGeneratorMobile.kt b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/objcexport/ObjcExportHeaderGeneratorMobile.kt new file mode 100644 index 00000000000..a7f9ac33c18 --- /dev/null +++ b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/objcexport/ObjcExportHeaderGeneratorMobile.kt @@ -0,0 +1,46 @@ +package org.jetbrains.kotlin.backend.konan.objcexport + +import org.jetbrains.kotlin.builtins.KotlinBuiltIns +import org.jetbrains.kotlin.descriptors.FunctionDescriptor +import org.jetbrains.kotlin.descriptors.ModuleDescriptor +import org.jetbrains.kotlin.resolve.deprecation.DeprecationResolver + +class ObjcExportHeaderGeneratorMobile internal constructor( + moduleDescriptors: List, + mapper: ObjCExportMapper, + namer: ObjCExportNamer, + private val warningCollector: ObjCExportWarningCollector, + objcGenerics: Boolean +) : ObjCExportHeaderGenerator(moduleDescriptors, mapper, namer, objcGenerics) { + + companion object { + fun createInstance( + configuration: ObjCExportLazy.Configuration, + warningCollector: ObjCExportWarningCollector, + builtIns: KotlinBuiltIns, + moduleDescriptors: List, + deprecationResolver: DeprecationResolver? = null, + local: Boolean = false): ObjCExportHeaderGenerator { + + val mapper = ObjCExportMapper(deprecationResolver, local) + val namerConfiguration = createNamerConfiguration(configuration) + val namer = ObjCExportNamerImpl(namerConfiguration, builtIns, mapper, local) + + return ObjcExportHeaderGeneratorMobile( + moduleDescriptors, + mapper, + namer, + warningCollector, + configuration.objcGenerics) + } + } + + override fun reportWarning(text: String) { + warningCollector.reportWarning(text) + } + + override fun reportWarning(method: FunctionDescriptor, text: String) { + warningCollector.reportWarning(method, text) + } + +} diff --git a/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/objcexport/StubBuilder.kt b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/objcexport/StubBuilder.kt new file mode 100644 index 00000000000..b2c89c2821e --- /dev/null +++ b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/objcexport/StubBuilder.kt @@ -0,0 +1,25 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +package org.jetbrains.kotlin.backend.konan.objcexport + +internal class StubBuilder { + private val children = mutableListOf>() + + operator fun Stub<*>.unaryPlus() { + children.add(this) + } + + operator fun plusAssign(set: Collection>) { + children += set + } + + fun build() = children +} + +internal inline fun buildMembers(block: StubBuilder.() -> Unit): List> = StubBuilder().let { + it.block() + it.build() +} diff --git a/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/objcexport/StubRenderer.kt b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/objcexport/StubRenderer.kt new file mode 100644 index 00000000000..76605186c7c --- /dev/null +++ b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/objcexport/StubRenderer.kt @@ -0,0 +1,204 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +package org.jetbrains.kotlin.backend.konan.objcexport + +import org.jetbrains.kotlin.descriptors.ClassDescriptor + +object StubRenderer { + fun render(stub: Stub<*>): List = collect { + stub.run { + this.comment?.let { comment -> + +"" // Probably makes the output more readable. + +"/**" + comment.contentLines.forEach { + +" $it" + } + +"*/" + } + when (this) { + is ObjCProtocol -> { + attributes.forEach { + +renderAttribute(it) + } + +renderProtocolHeader() + +"@required" + renderMembers(this) + +"@end;" + } + is ObjCInterface -> { + attributes.forEach { + +renderAttribute(it) + } + +renderInterfaceHeader() + renderMembers(this) + +"@end;" + } + is ObjCMethod -> { + +renderMethod(this) + } + is ObjCProperty -> { + +renderProperty(this) + } + else -> throw IllegalArgumentException("unsupported stub: " + stub::class) + } + } + } + + private fun renderProperty(property: ObjCProperty): String = buildString { + fun StringBuilder.appendTypeAndName() { + append(' ') + append(property.type.render(property.name)) + } + + fun ObjCProperty.getAllAttributes(): List { + if (getterName == null && setterName == null) return propertyAttributes + + val allAttributes = propertyAttributes.toMutableList() + getterName?.let { allAttributes += "getter=$it" } + setterName?.let { allAttributes += "setter=$it" } + return allAttributes + } + + fun StringBuilder.appendAttributes() { + val attributes = property.getAllAttributes() + if (attributes.isNotEmpty()) { + append(' ') + attributes.joinTo(this, prefix = "(", postfix = ")") + } + } + + append("@property") + appendAttributes() + appendTypeAndName() + appendPostfixDeclarationAttributes(property.declarationAttributes) + append(';') + } + + private fun renderMethod(method: ObjCMethod): String = buildString { + fun appendStaticness() { + if (method.isInstanceMethod) { + append('-') + } else { + append('+') + } + } + + fun appendReturnType() { + append(" (") + append(method.returnType.render()) + append(')') + } + + fun appendParameters() { + assert(method.selectors.size == method.parameters.size || + method.selectors.size == 1 && method.parameters.size == 0) + + if (method.selectors.size == 1 && method.parameters.size == 0) { + append(method.selectors[0]) + } else { + for (i in 0 until method.selectors.size) { + if (i > 0) append(' ') + + val parameter = method.parameters[i] + val selector = method.selectors[i] + append(selector) + append("(") + append(parameter.type.render()) + append(")") + append(parameter.name) + } + } + } + + fun appendAttributes() { + appendPostfixDeclarationAttributes(method.attributes) + } + + appendStaticness() + appendReturnType() + appendParameters() + appendAttributes() + append(';') + } + + private fun Appendable.appendPostfixDeclarationAttributes(attributes: List) { + if (attributes.isNotEmpty()) this.append(' ') + attributes.joinTo(this, separator = " ", transform = this@StubRenderer::renderAttribute) + } + + private fun ObjCProtocol.renderProtocolHeader() = buildString { + append("@protocol ") + append(name) + appendSuperProtocols(this@renderProtocolHeader) + } + + private fun StringBuilder.appendSuperProtocols(clazz: ObjCClass) { + val protocols = clazz.superProtocols + if (protocols.isNotEmpty()) { + protocols.joinTo(this, separator = ", ", prefix = " <", postfix = ">") + } + } + + private fun ObjCInterface.renderInterfaceHeader() = buildString { + fun appendSuperClass() { + if (superClass != null) append(" : $superClass") + formatGenerics(this, superClassGenerics.map { it.render() }) + } + + fun appendGenerics() { + formatGenerics(this, generics) + } + + fun appendCategoryName() { + if (categoryName != null) { + append(" (") + append(categoryName) + append(')') + } + } + + append("@interface ") + append(name) + appendGenerics() + appendCategoryName() + appendSuperClass() + appendSuperProtocols(this@renderInterfaceHeader) + } + + private fun Collector.renderMembers(clazz: ObjCClass<*>) { + clazz.members.forEach { + +render(it) + } + } + + private fun renderAttribute(attribute: String) = "__attribute__(($attribute))" + + private fun collect(p: Collector.() -> Unit): List { + val collector = Collector() + collector.p() + return collector.build() + } + + private class Collector { + private val collection: MutableList = mutableListOf() + fun build(): List = collection + + operator fun String.unaryPlus() { + collection += this + } + + operator fun List.unaryPlus() { + collection += this + } + } +} + +internal fun formatGenerics(buffer: Appendable, generics:List) { + if (generics.isNotEmpty()) { + generics.joinTo(buffer, separator = ", ", prefix = "<", postfix = ">") + } +} + diff --git a/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/objcexport/objcTypes.kt b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/objcexport/objcTypes.kt new file mode 100644 index 00000000000..ef06ee6ecdc --- /dev/null +++ b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/objcexport/objcTypes.kt @@ -0,0 +1,170 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +package org.jetbrains.kotlin.backend.konan.objcexport + +import org.jetbrains.kotlin.descriptors.TypeParameterDescriptor + +sealed class ObjCType { + final override fun toString(): String = this.render() + + abstract fun render(attrsAndName: String): String + + fun render() = render("") + + protected fun String.withAttrsAndName(attrsAndName: String) = + if (attrsAndName.isEmpty()) this else "$this ${attrsAndName.trimStart()}" +} + +class ObjCRawType( + val rawText: String +) : ObjCType() { + override fun render(attrsAndName: String): String = rawText.withAttrsAndName(attrsAndName) +} + +sealed class ObjCReferenceType : ObjCType() + +sealed class ObjCNonNullReferenceType : ObjCReferenceType() + +data class ObjCNullableReferenceType( + val nonNullType: ObjCNonNullReferenceType +) : ObjCReferenceType() { + override fun render(attrsAndName: String) = nonNullType.render(" _Nullable".withAttrsAndName(attrsAndName)) +} + +class ObjCClassType( + val className: String, + val typeArguments: List = emptyList() +) : ObjCNonNullReferenceType() { + + override fun render(attrsAndName: String) = buildString { + append(className) + if (typeArguments.isNotEmpty()) { + append("<") + typeArguments.joinTo(this) { it.render() } + append(">") + } + append(" *") + append(attrsAndName) + } +} + +class ObjCGenericTypeDeclaration( + val typeParameterDescriptor: TypeParameterDescriptor, + val namer: ObjCExportNamer +) : ObjCNonNullReferenceType() { + override fun render(attrsAndName: String): String { + return namer.getTypeParameterName(typeParameterDescriptor).withAttrsAndName(attrsAndName) + } +} + +class ObjCProtocolType( + val protocolName: String +) : ObjCNonNullReferenceType() { + override fun render(attrsAndName: String) = "id<$protocolName>".withAttrsAndName(attrsAndName) +} + +object ObjCIdType : ObjCNonNullReferenceType() { + override fun render(attrsAndName: String) = "id".withAttrsAndName(attrsAndName) +} + +object ObjCInstanceType : ObjCNonNullReferenceType() { + override fun render(attrsAndName: String): String = "instancetype".withAttrsAndName(attrsAndName) +} + +class ObjCBlockPointerType( + val returnType: ObjCType, + val parameterTypes: List +) : ObjCNonNullReferenceType() { + + override fun render(attrsAndName: String) = returnType.render(buildString { + append("(^") + append(attrsAndName) + append(")(") + if (parameterTypes.isEmpty()) append("void") + parameterTypes.joinTo(this) { it.render() } + append(')') + }) +} + +object ObjCMetaClassType : ObjCNonNullReferenceType() { + override fun render(attrsAndName: String): String = "Class".withAttrsAndName(attrsAndName) +} + +sealed class ObjCPrimitiveType( + val cName: String +) : ObjCType() { + object NSUInteger : ObjCPrimitiveType("NSUInteger") + object BOOL : ObjCPrimitiveType("BOOL") + object unichar : ObjCPrimitiveType("unichar") + object int8_t : ObjCPrimitiveType("int8_t") + object int16_t : ObjCPrimitiveType("int16_t") + object int32_t : ObjCPrimitiveType("int32_t") + object int64_t : ObjCPrimitiveType("int64_t") + object uint8_t : ObjCPrimitiveType("uint8_t") + object uint16_t : ObjCPrimitiveType("uint16_t") + object uint32_t : ObjCPrimitiveType("uint32_t") + object uint64_t : ObjCPrimitiveType("uint64_t") + object float : ObjCPrimitiveType("float") + object double : ObjCPrimitiveType("double") + object NSInteger : ObjCPrimitiveType("NSInteger") + object char : ObjCPrimitiveType("char") + object unsigned_char: ObjCPrimitiveType("unsigned char") + object unsigned_short: ObjCPrimitiveType("unsigned short") + object int: ObjCPrimitiveType("int") + object unsigned_int: ObjCPrimitiveType("unsigned int") + object long: ObjCPrimitiveType("long") + object unsigned_long: ObjCPrimitiveType("unsigned long") + object long_long: ObjCPrimitiveType("long long") + object unsigned_long_long: ObjCPrimitiveType("unsigned long long") + object short: ObjCPrimitiveType("short") + + override fun render(attrsAndName: String) = cName.withAttrsAndName(attrsAndName) +} + +class ObjCPointerType( + val pointee: ObjCType, + val nullable: Boolean = false +) : ObjCType() { + override fun render(attrsAndName: String) = + pointee.render("*${if (nullable) { + " _Nullable".withAttrsAndName(attrsAndName) + } else { + attrsAndName + }}") +} + +object ObjCVoidType : ObjCType() { + override fun render(attrsAndName: String) = "void".withAttrsAndName(attrsAndName) +} + +internal enum class ObjCValueType(val encoding: String) { + BOOL("c"), + UNICHAR("S"), + CHAR("c"), + SHORT("s"), + INT("i"), + LONG_LONG("q"), + UNSIGNED_CHAR("C"), + UNSIGNED_SHORT("S"), + UNSIGNED_INT("I"), + UNSIGNED_LONG_LONG("Q"), + FLOAT("f"), + DOUBLE("d"), + POINTER("^v") +} + +internal fun ObjCType.makeNullableIfReferenceOrPointer(): ObjCType = when (this) { + is ObjCPointerType -> ObjCPointerType(this.pointee, nullable = true) + + is ObjCNonNullReferenceType -> ObjCNullableReferenceType(this) + + is ObjCNullableReferenceType, is ObjCRawType, is ObjCPrimitiveType, ObjCVoidType -> this +} + +internal fun ObjCReferenceType.makeNullable(): ObjCNullableReferenceType = when (this) { + is ObjCNonNullReferenceType -> ObjCNullableReferenceType(this) + is ObjCNullableReferenceType -> this +} diff --git a/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/objcexport/stubs.kt b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/objcexport/stubs.kt new file mode 100644 index 00000000000..bc5bf4a6bef --- /dev/null +++ b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/objcexport/stubs.kt @@ -0,0 +1,95 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +package org.jetbrains.kotlin.backend.konan.objcexport + +import com.intellij.psi.PsiElement +import org.jetbrains.kotlin.descriptors.* +import org.jetbrains.kotlin.resolve.descriptorUtil.module +import org.jetbrains.kotlin.resolve.source.PsiSourceElement + +class ObjCComment(val contentLines: List) { + constructor(vararg contentLines: String) : this(contentLines.toList()) +} + +abstract class Stub(val name: String, val comment: ObjCComment? = null) { + abstract val descriptor: D? + open val psi: PsiElement? + get() = ((descriptor as? DeclarationDescriptorWithSource)?.source as? PsiSourceElement)?.psi + open val isValid: Boolean + get() = descriptor?.module?.isValid ?: true +} + +abstract class ObjCTopLevel(name: String) : Stub(name) + +abstract class ObjCClass(name: String, + val attributes: List) : ObjCTopLevel(name) { + abstract val superProtocols: List + abstract val members: List> +} + +abstract class ObjCProtocol(name: String, + attributes: List) : ObjCClass(name, attributes) + +class ObjCProtocolImpl( + name: String, + override val descriptor: ClassDescriptor, + override val superProtocols: List, + override val members: List>, + attributes: List = emptyList()) : ObjCProtocol(name, attributes) + +abstract class ObjCInterface(name: String, + val generics: List, + val categoryName: String?, + attributes: List) : ObjCClass(name, attributes) { + abstract val superClass: String? + abstract val superClassGenerics: List +} + +class ObjCInterfaceImpl( + name: String, + generics: List = emptyList(), + override val descriptor: ClassDescriptor? = null, + override val superClass: String? = null, + override val superClassGenerics: List = emptyList(), + override val superProtocols: List = emptyList(), + categoryName: String? = null, + override val members: List> = emptyList(), + attributes: List = emptyList() +) : ObjCInterface(name, generics, categoryName, attributes) + +class ObjCMethod( + override val descriptor: DeclarationDescriptor?, + val isInstanceMethod: Boolean, + val returnType: ObjCType, + val selectors: List, + val parameters: List, + val attributes: List, + comment: ObjCComment? = null +) : Stub(buildMethodName(selectors, parameters), comment) + +class ObjCParameter(name: String, + override val descriptor: ParameterDescriptor?, + val type: ObjCType) : Stub(name) + +class ObjCProperty(name: String, + override val descriptor: DeclarationDescriptorWithSource?, + val type: ObjCType, + val propertyAttributes: List, + val setterName: String? = null, + val getterName: String? = null, + val declarationAttributes: List = emptyList()) : Stub(name) { + + @Deprecated("", ReplaceWith("this.propertyAttributes"), DeprecationLevel.WARNING) + val attributes: List get() = propertyAttributes +} + +private fun buildMethodName(selectors: List, parameters: List): String = + if (selectors.size == 1 && parameters.size == 0) { + selectors[0] + } else { + assert(selectors.size == parameters.size) + selectors.joinToString(separator = "") + } diff --git a/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/optimizations/CallGraphBuilder.kt b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/optimizations/CallGraphBuilder.kt new file mode 100644 index 00000000000..2c8485ff1d8 --- /dev/null +++ b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/optimizations/CallGraphBuilder.kt @@ -0,0 +1,201 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +package org.jetbrains.kotlin.backend.konan.optimizations + +import org.jetbrains.kotlin.backend.common.pop +import org.jetbrains.kotlin.backend.common.push +import org.jetbrains.kotlin.backend.konan.DirectedGraph +import org.jetbrains.kotlin.backend.konan.DirectedGraphNode +import org.jetbrains.kotlin.backend.konan.Context + +internal class CallGraphNode(val graph: CallGraph, val symbol: DataFlowIR.FunctionSymbol.Declared) + : DirectedGraphNode { + + override val key get() = symbol + + override val directEdges: List by lazy { + graph.directEdges[symbol]!!.callSites + .filter { !it.isVirtual } + .map { it.actualCallee } + .filterIsInstance() + .filter { graph.directEdges.containsKey(it) } + } + + override val reversedEdges: List by lazy { + graph.reversedEdges[symbol]!! + } + + class CallSite(val call: DataFlowIR.Node.Call, val isVirtual: Boolean, val actualCallee: DataFlowIR.FunctionSymbol) + + val callSites = mutableListOf() +} + +internal class CallGraph(val directEdges: Map, + val reversedEdges: Map>, + val rootExternalFunctions: List) + : DirectedGraph { + + override val nodes get() = directEdges.values + + override fun get(key: DataFlowIR.FunctionSymbol.Declared) = directEdges[key]!! + + fun addEdge(caller: DataFlowIR.FunctionSymbol.Declared, callSite: CallGraphNode.CallSite) { + directEdges[caller]!!.callSites += callSite + } + + fun addReversedEdge(caller: DataFlowIR.FunctionSymbol.Declared, callee: DataFlowIR.FunctionSymbol.Declared) { + reversedEdges[callee]!!.add(caller) + } +} + +internal class CallGraphBuilder( + val context: Context, + val moduleDFG: ModuleDFG, + val externalModulesDFG: ExternalModulesDFG, + val devirtualizationAnalysisResult: Devirtualization.AnalysisResult, + val nonDevirtualizedCallSitesUnfoldFactor: Int +) { + + private val devirtualizedCallSites = devirtualizationAnalysisResult.devirtualizedCallSites + + private fun DataFlowIR.FunctionSymbol.resolved(): DataFlowIR.FunctionSymbol { + if (this is DataFlowIR.FunctionSymbol.External) + return externalModulesDFG.publicFunctions[this.hash] ?: this + return this + } + + private val directEdges = mutableMapOf() + private val reversedEdges = mutableMapOf>() + private val externalRootFunctions = mutableListOf() + private val callGraph = CallGraph(directEdges, reversedEdges, externalRootFunctions) + + private data class HandleFunctionParams(val caller: DataFlowIR.FunctionSymbol.Declared?, + val calleeFunction: DataFlowIR.Function) + private val functionStack = mutableListOf() + + fun build(): CallGraph { + val rootSet = Devirtualization.computeRootSet(context, moduleDFG, externalModulesDFG) + for (symbol in rootSet) { + val function = moduleDFG.functions[symbol] + if (function == null) + externalRootFunctions.add(symbol) + else + functionStack.push(HandleFunctionParams(null, function)) + } + + while (functionStack.isNotEmpty()) { + val (caller, calleeFunction) = functionStack.pop() + val callee = calleeFunction.symbol as DataFlowIR.FunctionSymbol.Declared + val gotoCallee = !directEdges.containsKey(callee) + if (gotoCallee) + addNode(callee) + if (caller != null) + callGraph.addReversedEdge(caller, callee) + if (gotoCallee) + handleFunction(callee, calleeFunction) + } + return callGraph + } + + private fun addNode(symbol: DataFlowIR.FunctionSymbol.Declared) { + directEdges[symbol] = CallGraphNode(callGraph, symbol) + reversedEdges[symbol] = mutableListOf() + } + + private inline fun DataFlowIR.FunctionBody.forEachCallSite(block: (DataFlowIR.Node.Call) -> Unit): Unit = + forEachNonScopeNode { node -> + when (node) { + is DataFlowIR.Node.Call -> block(node) + + is DataFlowIR.Node.Singleton -> + node.constructor?.let { block(DataFlowIR.Node.Call(it, emptyList(), node.type, null)) } + + is DataFlowIR.Node.ArrayRead -> + block(DataFlowIR.Node.Call( + callee = node.callee, + arguments = listOf(node.array, node.index), + returnType = node.type, + irCallSite = null) + ) + + is DataFlowIR.Node.ArrayWrite -> + block(DataFlowIR.Node.Call( + callee = node.callee, + arguments = listOf(node.array, node.index, node.value), + returnType = moduleDFG.symbolTable.mapType(context.irBuiltIns.unitType), + irCallSite = null) + ) + + is DataFlowIR.Node.FunctionReference -> + block(DataFlowIR.Node.Call( + callee = node.symbol, + arguments = emptyList(), + returnType = node.symbol.returnParameter.type, + irCallSite = null + )) + + else -> { } + } + } + + private fun staticCall(caller: DataFlowIR.FunctionSymbol.Declared, call: DataFlowIR.Node.Call, callee: DataFlowIR.FunctionSymbol) { + val resolvedCallee = callee.resolved() + val callSite = CallGraphNode.CallSite(call, false, resolvedCallee) + val function = moduleDFG.functions[resolvedCallee] + callGraph.addEdge(caller, callSite) + if (function != null) + functionStack.push(HandleFunctionParams(caller, function)) + } + + private fun handleFunction(symbol: DataFlowIR.FunctionSymbol.Declared, function: DataFlowIR.Function) { + val body = function.body + body.forEachCallSite { call -> + val devirtualizedCallSite = (call as? DataFlowIR.Node.VirtualCall)?.let { devirtualizedCallSites[it] } + when { + call !is DataFlowIR.Node.VirtualCall -> staticCall(symbol, call, call.callee) + + devirtualizedCallSite != null -> { + devirtualizedCallSite.possibleCallees.forEach { + staticCall(symbol, call, it.callee) + } + } + + call.receiverType == DataFlowIR.Type.Virtual -> { + // Skip callsite. This can only be for invocations Any's methods on instances of ObjC classes. + } + + else -> { + // Callsite has not been devirtualized - conservatively assume the worst: + // any inheritor of the receiver type is possible here. + val typeHierarchy = devirtualizationAnalysisResult.typeHierarchy + val allPossibleCallees = mutableListOf() + typeHierarchy.inheritorsOf(call.receiverType as DataFlowIR.Type.Declared).forEachBit { + val receiverType = typeHierarchy.allTypes[it] + if (receiverType.isAbstract) return@forEachBit + // TODO: Unconservative way - when we can use it? + //.filter { devirtualizationAnalysisResult.instantiatingClasses.contains(it) } + val actualCallee = when (call) { + is DataFlowIR.Node.VtableCall -> + receiverType.vtable[call.calleeVtableIndex] + + is DataFlowIR.Node.ItableCall -> + receiverType.itable[call.calleeHash]!! + + else -> error("Unreachable") + } + allPossibleCallees.add(actualCallee) + } + if (allPossibleCallees.size <= nonDevirtualizedCallSitesUnfoldFactor) + allPossibleCallees.forEach { staticCall(symbol, call, it) } + else { + val callSite = CallGraphNode.CallSite(call, true, call.callee) + callGraph.addEdge(symbol, callSite) + } + } + } + } + } +} \ No newline at end of file diff --git a/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/optimizations/DFGBuilder.kt b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/optimizations/DFGBuilder.kt new file mode 100644 index 00000000000..b906b3ec31a --- /dev/null +++ b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/optimizations/DFGBuilder.kt @@ -0,0 +1,887 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +package org.jetbrains.kotlin.backend.konan.optimizations + +import org.jetbrains.kotlin.backend.common.atMostOne +import org.jetbrains.kotlin.backend.common.ir.allParameters +import org.jetbrains.kotlin.backend.common.ir.ir2stringWhole +import org.jetbrains.kotlin.backend.common.ir.simpleFunctions +import org.jetbrains.kotlin.backend.common.peek +import org.jetbrains.kotlin.backend.common.pop +import org.jetbrains.kotlin.backend.common.push +import org.jetbrains.kotlin.backend.konan.* +import org.jetbrains.kotlin.backend.konan.descriptors.allOverriddenFunctions +import org.jetbrains.kotlin.backend.konan.ir.* +import org.jetbrains.kotlin.backend.konan.llvm.functionName +import org.jetbrains.kotlin.backend.konan.llvm.localHash +import org.jetbrains.kotlin.ir.IrElement +import org.jetbrains.kotlin.ir.UNDEFINED_OFFSET +import org.jetbrains.kotlin.ir.declarations.* +import org.jetbrains.kotlin.ir.declarations.lazy.IrLazyClass +import org.jetbrains.kotlin.ir.expressions.* +import org.jetbrains.kotlin.ir.expressions.impl.* +import org.jetbrains.kotlin.ir.symbols.IrClassSymbol +import org.jetbrains.kotlin.ir.symbols.IrSimpleFunctionSymbol +import org.jetbrains.kotlin.ir.symbols.IrTypeParameterSymbol +import org.jetbrains.kotlin.ir.types.* +import org.jetbrains.kotlin.ir.util.* +import org.jetbrains.kotlin.ir.util.constructors +import org.jetbrains.kotlin.ir.util.getArguments +import org.jetbrains.kotlin.ir.util.parentAsClass +import org.jetbrains.kotlin.ir.visitors.IrElementVisitorVoid +import org.jetbrains.kotlin.ir.visitors.acceptChildrenVoid +import org.jetbrains.kotlin.ir.visitors.acceptVoid +import org.jetbrains.kotlin.resolve.DescriptorUtils +import org.jetbrains.kotlin.util.OperatorNameConventions + +internal class ExternalModulesDFG(val allTypes: List, + val publicTypes: Map, + val publicFunctions: Map, + val functionDFGs: Map) + +private fun IrClass.getOverridingOf(function: IrFunction) = (function as? IrSimpleFunction)?.let { + it.allOverriddenFunctions.atMostOne { it.parent == this } +} + +private fun IrTypeOperator.isCast() = + this == IrTypeOperator.CAST || this == IrTypeOperator.IMPLICIT_CAST || this == IrTypeOperator.SAFE_CAST + +private fun IrTypeOperator.callsInstanceOf() = + this == IrTypeOperator.CAST || this == IrTypeOperator.SAFE_CAST + || this == IrTypeOperator.INSTANCEOF || this == IrTypeOperator.NOT_INSTANCEOF + +private class VariableValues { + data class Variable(val loop: IrLoop?, val values: MutableSet) + + val elementData = HashMap() + + fun addEmpty(variable: IrValueDeclaration, loop: IrLoop?) { + elementData[variable] = Variable(loop, mutableSetOf()) + } + + fun add(variable: IrValueDeclaration, element: IrExpression) = + elementData[variable]?.values?.add(element) + + private fun add(variable: IrValueDeclaration, elements: Set) = + elementData[variable]?.values?.addAll(elements) + + fun computeClosure() { + elementData.forEach { (key, _) -> + add(key, computeValueClosure(key)) + } + } + + // Computes closure of all possible values for given variable. + private fun computeValueClosure(value: IrValueDeclaration): Set { + val result = mutableSetOf() + val seen = mutableSetOf() + dfs(value, seen, result) + return result + } + + private fun dfs(value: IrValueDeclaration, seen: MutableSet, result: MutableSet) { + seen += value + val elements = elementData[value]?.values ?: return + for (element in elements) { + if (element !is IrGetValue) + result += element + else { + val declaration = element.symbol.owner + if (declaration is IrVariable && !seen.contains(declaration)) + dfs(declaration, seen, result) + } + } + } +} + +private class ExpressionValuesExtractor(val context: Context, + val returnableBlockValues: Map>, + val suspendableExpressionValues: Map>) { + + val unit = IrGetObjectValueImpl(UNDEFINED_OFFSET, UNDEFINED_OFFSET, + context.irBuiltIns.unitType, context.ir.symbols.unit) + + val nothing = IrGetObjectValueImpl(UNDEFINED_OFFSET, UNDEFINED_OFFSET, + context.irBuiltIns.nothingType, context.ir.symbols.nothing) + + fun forEachValue(expression: IrExpression, block: (IrExpression) -> Unit) { + when (expression) { + is IrReturnableBlock -> returnableBlockValues[expression]!!.forEach { forEachValue(it, block) } + + is IrSuspendableExpression -> + (suspendableExpressionValues[expression]!! + expression.result).forEach { forEachValue(it, block) } + + is IrSuspensionPoint -> { + forEachValue(expression.result, block) + forEachValue(expression.resumeResult, block) + } + + is IrContainerExpression -> { + if (expression.statements.isNotEmpty()) + forEachValue( + expression = (expression.statements.last() as? IrExpression) ?: unit, + block = block + ) + } + + is IrWhen -> expression.branches.forEach { forEachValue(it.result, block) } + + is IrMemberAccessExpression<*> -> block(expression) + + is IrGetValue -> block(expression) + + is IrGetField -> block(expression) + + is IrVararg -> /* Sometimes, we keep vararg till codegen phase (for constant arrays). */ + block(expression) + + is IrConst<*> -> block(expression) + + is IrTypeOperatorCall -> { + if (!expression.operator.isCast()) + block(expression) + else { // Propagate cast to sub-values. + forEachValue(expression.argument) { value -> + with(expression) { + block(IrTypeOperatorCallImpl(startOffset, endOffset, type, operator, typeOperand, value)) + } + } + } + } + + is IrTry -> { + forEachValue(expression.tryResult, block) + expression.catches.forEach { forEachValue(it.result, block) } + } + + is IrGetObjectValue -> block(expression) + + is IrFunctionReference -> block(expression) + + is IrSetField -> block(expression) + + else -> when { + expression.type.isUnit() -> unit + expression.type.isNothing() -> nothing + else -> TODO(ir2stringWhole(expression)) + } + } + } +} + +internal class ModuleDFG(val functions: Map, + val symbolTable: DataFlowIR.SymbolTable) + +internal class ModuleDFGBuilder(val context: Context, val irModule: IrModuleFragment) { + + private val TAKE_NAMES = true // Take fqNames for all functions and types (for debug purposes). + + private inline fun takeName(block: () -> String) = if (TAKE_NAMES) block() else null + + private val module = DataFlowIR.Module(irModule.descriptor) + private val symbolTable = DataFlowIR.SymbolTable(context, irModule, module) + + // Possible values of a returnable block. + private val returnableBlockValues = mutableMapOf>() + + // All suspension points within specified suspendable expression. + private val suspendableExpressionValues = mutableMapOf>() + + private val expressionValuesExtractor = ExpressionValuesExtractor(context, returnableBlockValues, suspendableExpressionValues) + + fun build(): ModuleDFG { + val functions = mutableMapOf() + irModule.accept(object : IrElementVisitorVoid { + + override fun visitElement(element: IrElement) { + element.acceptChildrenVoid(this) + } + + override fun visitConstructor(declaration: IrConstructor) { + val body = declaration.body + assert (body != null || declaration.constructedClass.isNonGeneratedAnnotation()) { + "Non-annotation class constructor has empty body" + } + context.logMultiple { + +"Analysing function ${declaration.descriptor}" + +"IR: ${ir2stringWhole(declaration)}" + } + analyze(declaration, body) + } + + override fun visitFunction(declaration: IrFunction) { + val body = declaration.body + if (body == null) { + // External function or intrinsic. + symbolTable.mapFunction(declaration) + } else { + context.logMultiple { + +"Analysing function ${declaration.descriptor}" + +"IR: ${ir2stringWhole(declaration)}" + } + analyze(declaration, body) + } + } + + override fun visitField(declaration: IrField) { + if (declaration.parent is IrFile) + declaration.initializer?.let { + context.logMultiple { + +"Analysing global field ${declaration.descriptor}" + +"IR: ${ir2stringWhole(declaration)}" + } + analyze(declaration, IrSetFieldImpl(it.startOffset, it.endOffset, declaration.symbol, null, + it.expression, context.irBuiltIns.unitType)) + } + } + + private fun analyze(declaration: IrDeclaration, body: IrElement?) { + // Find all interesting expressions, variables and functions. + val visitor = ElementFinderVisitor() + body?.acceptVoid(visitor) + + context.logMultiple { + +"FIRST PHASE" + visitor.variableValues.elementData.forEach { (t, u) -> + +"VAR $t [LOOP ${u.loop}]:" + u.values.forEach { +" ${ir2stringWhole(it)}" } + } + visitor.expressions.forEach { t -> + +"EXP [LOOP ${t.value}] ${ir2stringWhole(t.key)}" + } + } + + // Compute transitive closure of possible values for variables. + visitor.variableValues.computeClosure() + + context.logMultiple { + +"SECOND PHASE" + visitor.variableValues.elementData.forEach { (t, u) -> + +"VAR $t [LOOP ${u.loop}]:" + u.values.forEach { +" ${ir2stringWhole(it)}" } + } + } + + val function = FunctionDFGBuilder(expressionValuesExtractor, visitor.variableValues, + declaration, visitor.expressions, visitor.parentLoops, visitor.returnValues, + visitor.thrownValues, visitor.catchParameters).build() + + context.logMultiple { + +function.debugString() + +"" + } + + functions[function.symbol] = function + } + }, data = null) + + context.logMultiple { + +"SYMBOL TABLE:" + symbolTable.classMap.forEach { irClass, type -> + +" DESCRIPTOR: ${irClass.descriptor}" + +" TYPE: $type" + if (type !is DataFlowIR.Type.Declared) + return@forEach + +" SUPER TYPES:" + type.superTypes.forEach { +" $it" } + +" VTABLE:" + type.vtable.forEach { +" $it" } + +" ITABLE:" + type.itable.forEach { +" ${it.key} -> ${it.value}" } + } + } + + return ModuleDFG(functions, symbolTable) + } + + private inner class ElementFinderVisitor : IrElementVisitorVoid { + val expressions = mutableMapOf() + val parentLoops = mutableMapOf() + val variableValues = VariableValues() + val returnValues = mutableListOf() + val thrownValues = mutableListOf() + val catchParameters = mutableSetOf() + + private val suspendableExpressionStack = mutableListOf() + private val loopStack = mutableListOf() + private val currentLoop get() = loopStack.peek() + + override fun visitElement(element: IrElement) { + element.acceptChildrenVoid(this) + } + + private fun assignValue(variable: IrValueDeclaration, value: IrExpression) { + expressionValuesExtractor.forEachValue(value) { + variableValues.add(variable, it) + } + } + + override fun visitExpression(expression: IrExpression) { + when (expression) { + is IrMemberAccessExpression<*>, + is IrGetField, + is IrGetObjectValue, + is IrVararg, + is IrConst<*>, + is IrTypeOperatorCall -> + expressions += expression to currentLoop + } + + if (expression is IrCall && expression.symbol == executeImplSymbol) { + // Producer and job of executeImpl are called externally, we need to reflect this somehow. + val producerInvocation = IrCallImpl.fromSymbolDescriptor(expression.startOffset, expression.endOffset, + executeImplProducerInvoke.returnType, + executeImplProducerInvoke.symbol, + executeImplProducerInvoke.symbol.owner.typeParameters.size, + executeImplProducerInvoke.symbol.owner.valueParameters.size) + producerInvocation.dispatchReceiver = expression.getValueArgument(2) + + expressions += producerInvocation to currentLoop + + val jobFunctionReference = expression.getValueArgument(3) as? IrFunctionReference + ?: error("A function reference expected") + val jobInvocation = IrCallImpl.fromSymbolDescriptor(expression.startOffset, expression.endOffset, + jobFunctionReference.symbol.owner.returnType, + jobFunctionReference.symbol as IrSimpleFunctionSymbol, + jobFunctionReference.symbol.owner.typeParameters.size, + jobFunctionReference.symbol.owner.valueParameters.size) + jobInvocation.putValueArgument(0, producerInvocation) + + expressions += jobInvocation to currentLoop + } + + // TODO: A little bit hacky but it is the simplest solution. + // See ObjC instanceOf code generation for details. + if (expression is IrTypeOperatorCall && expression.operator.callsInstanceOf() + && expression.typeOperand.isObjCObjectType()) { + val objcObjGetter = IrCallImpl.fromSymbolDescriptor(expression.startOffset, expression.endOffset, + objCObjectRawValueGetter.owner.returnType, + objCObjectRawValueGetter, + objCObjectRawValueGetter.owner.typeParameters.size, + objCObjectRawValueGetter.owner.valueParameters.size + ).apply { + extensionReceiver = expression.argument + } + expressions += objcObjGetter to currentLoop + } + + if (expression is IrReturnableBlock) { + returnableBlockValues.put(expression, mutableListOf()) + } + if (expression is IrSuspendableExpression) { + suspendableExpressionStack.push(expression) + suspendableExpressionValues.put(expression, mutableListOf()) + } + if (expression is IrSuspensionPoint) + suspendableExpressionValues[suspendableExpressionStack.peek()!!]!!.add(expression) + if (expression is IrLoop) { + parentLoops[expression] = currentLoop + loopStack.push(expression) + } + + super.visitExpression(expression) + + if (expression is IrLoop) + loopStack.pop() + if (expression is IrSuspendableExpression) + suspendableExpressionStack.pop() + } + + override fun visitSetField(expression: IrSetField) { + expressions += expression to currentLoop + super.visitSetField(expression) + } + + override fun visitReturn(expression: IrReturn) { + val returnableBlock = expression.returnTargetSymbol.owner as? IrReturnableBlock + if (returnableBlock != null) { + returnableBlockValues[returnableBlock]!!.add(expression.value) + } else { // Non-local return. + if (!expression.type.isUnit()) + returnValues += expression.value + } + super.visitReturn(expression) + } + + override fun visitThrow(expression: IrThrow) { + thrownValues += expression.value + super.visitThrow(expression) + } + + override fun visitCatch(aCatch: IrCatch) { + catchParameters.add(aCatch.catchParameter) + super.visitCatch(aCatch) + } + + override fun visitSetValue(expression: IrSetValue) { + super.visitSetValue(expression) + assignValue(expression.symbol.owner, expression.value) + } + + override fun visitVariable(declaration: IrVariable) { + variableValues.addEmpty(declaration, currentLoop) + super.visitVariable(declaration) + declaration.initializer?.let { assignValue(declaration, it) } + } + } + + private val symbols = context.ir.symbols + + private val invokeSuspendFunctionSymbol = + symbols.baseContinuationImpl.owner.declarations + .filterIsInstance().single { it.name.asString() == "invokeSuspend" }.symbol + + private val getContinuationSymbol = symbols.getContinuation + + private val arrayGetSymbols = symbols.arrayGet.values + private val arraySetSymbols = symbols.arraySet.values + private val createUninitializedInstanceSymbol = symbols.createUninitializedInstance + private val initInstanceSymbol = symbols.initInstance + private val executeImplSymbol = symbols.executeImpl + private val executeImplProducerClass = symbols.functionN(0).owner + private val executeImplProducerInvoke = executeImplProducerClass.simpleFunctions() + .single { it.name == OperatorNameConventions.INVOKE } + private val reinterpret = symbols.reinterpret + private val objCObjectRawValueGetter = symbols.interopObjCObjectRawValueGetter + + private class Scoped(val value: T, val scope: DataFlowIR.Node.Scope) + + private inner class FunctionDFGBuilder(val expressionValuesExtractor: ExpressionValuesExtractor, + val variableValues: VariableValues, + val declaration: IrDeclaration, + val expressions: Map, + val parentLoops: Map, + val returnValues: List, + val thrownValues: List, + val catchParameters: Set) { + + private val rootScope = DataFlowIR.Node.Scope(0, emptyList()) + private val allParameters = (declaration as? IrFunction)?.allParameters ?: emptyList() + private val templateParameters = allParameters.withIndex().associateBy({ it.value }, + { Scoped(DataFlowIR.Node.Parameter(it.index), rootScope) } + ) + + private val continuationParameter = when { + declaration !is IrSimpleFunction -> null + + declaration.isSuspend -> Scoped(DataFlowIR.Node.Parameter(allParameters.size), rootScope) + + declaration.overrides(invokeSuspendFunctionSymbol.owner) -> // is a ContinuationImpl inheritor. + templateParameters[declaration.dispatchReceiverParameter!!] // It is its own continuation. + + else -> null + } + + private fun getContinuation() = continuationParameter + ?: error("Function ${declaration.descriptor} has no continuation parameter") + + private val nodes = mutableMapOf>() + private val variables = mutableMapOf>() + private val expressionsScopes = mutableMapOf() + + fun build(): DataFlowIR.Function { + val isSuspend = declaration is IrSimpleFunction && declaration.isSuspend + + val scopes = mutableMapOf() + fun transformLoop(loop: IrLoop, parentLoop: IrLoop?): DataFlowIR.Node.Scope { + scopes[loop]?.let { return it } + val parentScope = + if (parentLoop == null) + rootScope + else transformLoop(parentLoop, parentLoops[parentLoop]) + val scope = DataFlowIR.Node.Scope(parentScope.depth + 1, emptyList()) + parentScope.nodes += scope + scopes[loop] = scope + return scope + } + parentLoops.forEach { (loop, parentLoop) -> transformLoop(loop, parentLoop) } + expressions.forEach { (expression, loop) -> + val scope = if (loop == null) rootScope else scopes[loop]!! + expressionsScopes[expression] = scope + } + expressionsScopes[expressionValuesExtractor.unit] = rootScope + expressionsScopes[expressionValuesExtractor.nothing] = rootScope + + variableValues.elementData.forEach { (irVariable, variable) -> + val loop = variable.loop + val scope = if (loop == null) rootScope else scopes[loop]!! + val node = DataFlowIR.Node.Variable( + values = mutableListOf(), + type = symbolTable.mapType(irVariable.type), + kind = if (catchParameters.contains(irVariable)) + DataFlowIR.VariableKind.CatchParameter + else DataFlowIR.VariableKind.Ordinary + ) + scope.nodes += node + variables[irVariable] = Scoped(node, scope) + } + + expressions.forEach { getNode(it.key) } + + val returnNodeType = when (declaration) { + is IrField -> declaration.type + is IrFunction -> declaration.returnType + else -> error(declaration) + } + + val returnsNode = DataFlowIR.Node.Variable( + values = returnValues.map { expressionToEdge(it) }, + type = symbolTable.mapType(returnNodeType), + kind = DataFlowIR.VariableKind.Temporary + ) + val throwsNode = DataFlowIR.Node.Variable( + values = thrownValues.map { expressionToEdge(it) }, + type = symbolTable.mapClassReferenceType(symbols.throwable.owner), + kind = DataFlowIR.VariableKind.Temporary + ) + variables.forEach { (irVariable, node) -> + val values = variableValues.elementData[irVariable]!!.values + values.forEach { node.value.values += expressionToEdge(it) } + } + + rootScope.nodes += templateParameters.values.map { it.value } + rootScope.nodes += returnsNode + rootScope.nodes += throwsNode + if (isSuspend) + rootScope.nodes += continuationParameter!!.value + + return DataFlowIR.Function( + symbol = symbolTable.mapFunction(declaration), + body = DataFlowIR.FunctionBody( + rootScope, listOf(rootScope) + scopes.values, returnsNode, throwsNode) + ) + } + + private fun IrType.erasure(): IrType { + if (this !is IrSimpleType) return this + + val classifier = this.classifier + return when (classifier) { + is IrClassSymbol -> this + is IrTypeParameterSymbol -> { + val upperBound = classifier.owner.superTypes.singleOrNull() ?: + TODO("${classifier.descriptor} : ${classifier.descriptor.upperBounds}") + + if (this.hasQuestionMark) { + // `T?` + upperBound.erasure().makeNullable() + } else { + upperBound.erasure() + } + } + else -> TODO(classifier.toString()) + } + } + + private fun expressionToEdge(expression: IrExpression) = expressionToScopedEdge(expression).value + + private fun expressionToScopedEdge(expression: IrExpression) = + if (expression is IrTypeOperatorCall && expression.operator.isCast()) + getNode(expression.argument).let { + Scoped( + DataFlowIR.Edge( + it.value, + symbolTable.mapClassReferenceType(expression.typeOperand.erasure().getClass()!!) + ), it.scope) + } + else { + getNode(expression).let { + Scoped( + DataFlowIR.Edge(it.value, null), + it.scope + ) + } + } + + private fun mapReturnType(actualType: IrType, returnType: IrType): DataFlowIR.Type { + val returnedInlinedClass = returnType.getInlinedClassNative() + val actualInlinedClass = actualType.getInlinedClassNative() + + return if (returnedInlinedClass == null) { + if (actualInlinedClass == null) symbolTable.mapType(actualType) else symbolTable.mapClassReferenceType(actualInlinedClass) + } else { + symbolTable.mapType(returnType) + } + } + + private fun getNode(expression: IrExpression): Scoped { + if (expression is IrGetValue) { + val valueDeclaration = expression.symbol.owner + if (valueDeclaration is IrValueParameter) + return templateParameters[valueDeclaration]!! + return variables[valueDeclaration]!! + } + return nodes.getOrPut(expression) { + context.logMultiple { + +"Converting expression" + +ir2stringWhole(expression) + } + val values = mutableListOf() + val edges = mutableListOf() + var highestScope: DataFlowIR.Node.Scope? = null + expressionValuesExtractor.forEachValue(expression) { + values += it + if (it != expression || values.size > 1) { + val edge = expressionToScopedEdge(it) + val scope = edge.scope + if (highestScope == null || highestScope!!.depth > scope.depth) + highestScope = scope + edges += edge.value + } + } + if (values.size == 1 && values[0] == expression) { + highestScope = expressionsScopes[expression] ?: error("Unknown expression: ${expression.dump()}") + } + if (values.size == 0) + highestScope = rootScope + val node = if (values.size != 1) { + DataFlowIR.Node.Variable( + values = edges, + type = symbolTable.mapType(expression.type), + kind = DataFlowIR.VariableKind.Temporary + ) + } else { + val value = values[0] + if (value != expression) { + val edge = edges[0] + if (edge.castToType == null) + edge.node + else + DataFlowIR.Node.Variable( + values = listOf(edge), + type = symbolTable.mapType(expression.type), + kind = DataFlowIR.VariableKind.Temporary + ) + } else { + when (value) { + is IrGetValue -> getNode(value).value + + is IrVararg -> DataFlowIR.Node.Const(symbolTable.mapType(value.type)) + + is IrFunctionReference -> { + val callee = value.symbol.owner + DataFlowIR.Node.FunctionReference( + symbolTable.mapFunction(callee), + symbolTable.mapType(value.type), + /*TODO: substitute*/symbolTable.mapType(callee.returnType)) + } + + is IrConst<*> -> + if (value.value == null) + DataFlowIR.Node.Null + else + DataFlowIR.Node.SimpleConst(symbolTable.mapType(value.type), value.value!!) + + is IrGetObjectValue -> { + val constructor = if (value.type.isNothing()) { + // is not a singleton though its instance is get with operation. + null + } else { + val objectClass = value.symbol.owner + if (objectClass is IrLazyClass) { + // Singleton has a private constructor which is not deserialized. + null + } else { + symbolTable.mapFunction(objectClass.constructors.single()) + } + } + DataFlowIR.Node.Singleton(symbolTable.mapType(value.type), constructor) + } + + is IrConstructorCall -> { + val callee = value.symbol.owner + val arguments = value.getArguments().map { expressionToEdge(it.second) } + DataFlowIR.Node.NewObject( + symbolTable.mapFunction(callee), + arguments, + symbolTable.mapClassReferenceType(callee.constructedClass), + value + ) + } + + is IrCall -> when (value.symbol) { + getContinuationSymbol -> getContinuation().value + + in arrayGetSymbols -> { + val callee = value.symbol.owner + val actualCallee = (value.superQualifierSymbol?.owner?.getOverridingOf(callee) + ?: callee).target + + DataFlowIR.Node.ArrayRead( + symbolTable.mapFunction(actualCallee), + array = expressionToEdge(value.dispatchReceiver!!), + index = expressionToEdge(value.getValueArgument(0)!!), + type = mapReturnType(value.type, context.irBuiltIns.anyType), + irCallSite = value) + } + + in arraySetSymbols -> { + val callee = value.symbol.owner + val actualCallee = (value.superQualifierSymbol?.owner?.getOverridingOf(callee) + ?: callee).target + DataFlowIR.Node.ArrayWrite( + symbolTable.mapFunction(actualCallee), + array = expressionToEdge(value.dispatchReceiver!!), + index = expressionToEdge(value.getValueArgument(0)!!), + value = expressionToEdge(value.getValueArgument(1)!!), + type = mapReturnType(value.getValueArgument(1)!!.type, context.irBuiltIns.anyType)) + } + + createUninitializedInstanceSymbol -> + DataFlowIR.Node.AllocInstance(symbolTable.mapClassReferenceType( + value.getTypeArgument(0)!!.getClass()!! + ), value) + + reinterpret -> getNode(value.extensionReceiver!!).value + + initInstanceSymbol -> { + val thiz = expressionToEdge(value.getValueArgument(0)!!) + val initializer = value.getValueArgument(1) as IrConstructorCall + val arguments = listOf(thiz) + initializer.getArguments().map { expressionToEdge(it.second) } + val callee = initializer.symbol.owner + DataFlowIR.Node.StaticCall( + symbolTable.mapFunction(callee), + arguments, + symbolTable.mapClassReferenceType(callee.constructedClass), + symbolTable.mapClassReferenceType(symbols.unit.owner), + null + ) + } + + else -> { + val callee = value.symbol.owner + val arguments = value.getArguments() + .map { expressionToEdge(it.second) } + .let { + if (callee.isSuspend) + it + DataFlowIR.Edge(getContinuation().value, null) + else + it + } + if (callee is IrConstructor) { + error("Constructor call should be done with IrConstructorCall") + } else { + if (callee.isOverridable && value.superQualifierSymbol == null) { + val owner = callee.parentAsClass + val actualReceiverType = value.dispatchReceiver!!.type + val actualReceiverClassifier = actualReceiverType.classifierOrFail + + val receiverType = + if (actualReceiverClassifier is IrTypeParameterSymbol + || !callee.isReal /* Could be a bridge. */) + symbolTable.mapClassReferenceType(owner) + else { + val actualClassAtCallsite = + (actualReceiverClassifier as IrClassSymbol).descriptor +// assert (DescriptorUtils.isSubclass(actualClassAtCallsite, owner.descriptor)) { +// "Expected an inheritor of ${owner.descriptor}, but was $actualClassAtCallsite" +// } + if (DescriptorUtils.isSubclass(actualClassAtCallsite, owner.descriptor)) { + symbolTable.mapClassReferenceType(actualReceiverClassifier.owner) // Box if inline class. + } else { + symbolTable.mapClassReferenceType(owner) + } + } + if (owner.isInterface) { + val calleeHash = callee.functionName.localHash.value + DataFlowIR.Node.ItableCall( + symbolTable.mapFunction(callee.target), + receiverType, + calleeHash, + arguments, + mapReturnType(value.type, callee.target.returnType), + value + ) + } else { + val vtableIndex = context.getLayoutBuilder(owner).vtableIndex(callee) + DataFlowIR.Node.VtableCall( + symbolTable.mapFunction(callee.target), + receiverType, + vtableIndex, + arguments, + mapReturnType(value.type, callee.target.returnType), + value + ) + } + } else { + val actualCallee = (value.superQualifierSymbol?.owner?.getOverridingOf(callee) ?: callee).target + DataFlowIR.Node.StaticCall( + symbolTable.mapFunction(actualCallee), + arguments, + actualCallee.dispatchReceiverParameter?.let { symbolTable.mapType(it.type) }, + mapReturnType(value.type, actualCallee.returnType), + value + ) + } + } + } + } + + is IrDelegatingConstructorCall -> { + val thisReceiver = (declaration as IrConstructor).constructedClass.thisReceiver!! + val thiz = IrGetValueImpl(SYNTHETIC_OFFSET, SYNTHETIC_OFFSET, thisReceiver.type, + thisReceiver.symbol) + val arguments = listOf(thiz) + value.getArguments().map { it.second } + DataFlowIR.Node.StaticCall( + symbolTable.mapFunction(value.symbol.owner), + arguments.map { expressionToEdge(it) }, + symbolTable.mapType(thiz.type), + symbolTable.mapClassReferenceType(symbols.unit.owner), + value + ) + } + + is IrGetField -> { + val receiver = value.receiver?.let { expressionToEdge(it) } + val receiverType = value.receiver?.let { symbolTable.mapType(it.type) } + val name = value.symbol.owner.name.asString() + DataFlowIR.Node.FieldRead( + receiver, + DataFlowIR.Field( + receiverType, + symbolTable.mapType(value.symbol.owner.type), + name.localHash.value, + takeName { name } + ), + mapReturnType(value.type, value.symbol.owner.type), + value + ) + } + + is IrSetField -> { + val receiver = value.receiver?.let { expressionToEdge(it) } + val receiverType = value.receiver?.let { symbolTable.mapType(it.type) } + val name = value.symbol.owner.name.asString() + DataFlowIR.Node.FieldWrite( + receiver, + DataFlowIR.Field( + receiverType, + symbolTable.mapType(value.symbol.owner.type), + name.localHash.value, + takeName { name } + ), + expressionToEdge(value.value), + mapReturnType(value.value.type, value.symbol.owner.type) + ) + } + + is IrTypeOperatorCall -> { + assert(!value.operator.isCast()) { "Casts should've been handled earlier" } + expressionToEdge(value.argument) // Put argument as a separate vertex. + DataFlowIR.Node.Const(symbolTable.mapType(value.type)) // All operators except casts are basically constants. + } + + else -> TODO("Unknown expression: ${ir2stringWhole(value)}") + } + } + } + + highestScope!!.nodes += node + Scoped(node, highestScope!!) + } + } + } +} \ No newline at end of file diff --git a/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/optimizations/DataFlowIR.kt b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/optimizations/DataFlowIR.kt new file mode 100644 index 00000000000..30644c322b5 --- /dev/null +++ b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/optimizations/DataFlowIR.kt @@ -0,0 +1,651 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +package org.jetbrains.kotlin.backend.konan.optimizations + +import org.jetbrains.kotlin.backend.konan.* +import org.jetbrains.kotlin.backend.konan.descriptors.isAbstract +import org.jetbrains.kotlin.backend.konan.descriptors.isBuiltInOperator +import org.jetbrains.kotlin.backend.common.ir.allParameters +import org.jetbrains.kotlin.backend.konan.ir.isOverridableOrOverrides +import org.jetbrains.kotlin.backend.konan.llvm.functionName +import org.jetbrains.kotlin.backend.konan.llvm.isExported +import org.jetbrains.kotlin.backend.konan.llvm.localHash +import org.jetbrains.kotlin.backend.konan.llvm.symbolName +import org.jetbrains.kotlin.backend.konan.lower.DECLARATION_ORIGIN_BRIDGE_METHOD +import org.jetbrains.kotlin.backend.konan.lower.bridgeTarget +import org.jetbrains.kotlin.backend.konan.optimizations.DataFlowIR.Function.Companion.appendCastTo +import org.jetbrains.kotlin.descriptors.Modality +import org.jetbrains.kotlin.descriptors.ModuleDescriptor +import org.jetbrains.kotlin.ir.IrElement +import org.jetbrains.kotlin.ir.declarations.* +import org.jetbrains.kotlin.ir.expressions.* +import org.jetbrains.kotlin.ir.types.IrType +import org.jetbrains.kotlin.ir.types.getClass +import org.jetbrains.kotlin.ir.types.isNothing +import org.jetbrains.kotlin.ir.types.isUnit +import org.jetbrains.kotlin.ir.util.* +import org.jetbrains.kotlin.ir.visitors.IrElementVisitorVoid +import org.jetbrains.kotlin.ir.visitors.acceptChildrenVoid +import org.jetbrains.kotlin.load.java.BuiltinMethodsWithSpecialGenericSignature +import org.jetbrains.kotlin.name.FqName +import org.jetbrains.kotlin.name.Name + +internal object DataFlowIR { + + abstract class Type(val isFinal: Boolean, val isAbstract: Boolean, + val primitiveBinaryType: PrimitiveBinaryType?, + val name: String?) { + // Special marker type forbidding devirtualization on its instances. + object Virtual : Declared(0, false, true, null, null, -1, null, "\$VIRTUAL") + + class External(val hash: Long, isFinal: Boolean, isAbstract: Boolean, + primitiveBinaryType: PrimitiveBinaryType?, name: String? = null) + : Type(isFinal, isAbstract, primitiveBinaryType, name) { + override fun equals(other: Any?): Boolean { + if (this === other) return true + if (other !is External) return false + + return hash == other.hash + } + + override fun hashCode(): Int { + return hash.hashCode() + } + + override fun toString(): String { + return "ExternalType(hash='$hash', name='$name')" + } + } + + abstract class Declared(val index: Int, isFinal: Boolean, isAbstract: Boolean, primitiveBinaryType: PrimitiveBinaryType?, + val module: Module?, val symbolTableIndex: Int, val irClass: IrClass?, name: String?) + : Type(isFinal, isAbstract, primitiveBinaryType, name) { + val superTypes = mutableListOf() + val vtable = mutableListOf() + val itable = mutableMapOf() + } + + class Public(val hash: Long, index: Int, isFinal: Boolean, isAbstract: Boolean, primitiveBinaryType: PrimitiveBinaryType?, + module: Module, symbolTableIndex: Int, irClass: IrClass?, name: String? = null) + : Declared(index, isFinal, isAbstract, primitiveBinaryType, module, symbolTableIndex, irClass, name) { + override fun equals(other: Any?): Boolean { + if (this === other) return true + if (other !is Public) return false + + return hash == other.hash + } + + override fun hashCode(): Int { + return hash.hashCode() + } + + override fun toString(): String { + return "PublicType(hash='$hash', symbolTableIndex='$symbolTableIndex', name='$name')" + } + } + + class Private(index: Int, isFinal: Boolean, isAbstract: Boolean, primitiveBinaryType: PrimitiveBinaryType?, + module: Module, symbolTableIndex: Int, irClass: IrClass?, name: String? = null) + : Declared(index, isFinal, isAbstract, primitiveBinaryType, module, symbolTableIndex, irClass, name) { + override fun equals(other: Any?): Boolean { + if (this === other) return true + if (other !is Private) return false + + return index == other.index + } + + override fun hashCode(): Int { + return index + } + + override fun toString(): String { + return "PrivateType(index=$index, symbolTableIndex='$symbolTableIndex', name='$name')" + } + } + } + + class Module(val descriptor: ModuleDescriptor) { + var numberOfFunctions = 0 + var numberOfClasses = 0 + } + + object FunctionAttributes { + val IS_GLOBAL_INITIALIZER = 1 + val RETURNS_UNIT = 2 + val RETURNS_NOTHING = 4 + val EXPLICITLY_EXPORTED = 8 + } + + class FunctionParameter(val type: Type, val boxFunction: FunctionSymbol?, val unboxFunction: FunctionSymbol?) + + abstract class FunctionSymbol(val attributes: Int, val irFunction: IrFunction?, val name: String?) { + lateinit var parameters: Array + lateinit var returnParameter: FunctionParameter + + val isGlobalInitializer = attributes.and(FunctionAttributes.IS_GLOBAL_INITIALIZER) != 0 + val returnsUnit = attributes.and(FunctionAttributes.RETURNS_UNIT) != 0 + val returnsNothing = attributes.and(FunctionAttributes.RETURNS_NOTHING) != 0 + val explicitlyExported = attributes.and(FunctionAttributes.EXPLICITLY_EXPORTED) != 0 + + var escapes: Int? = null + var pointsTo: IntArray? = null + + class External(val hash: Long, attributes: Int, irFunction: IrFunction?, name: String? = null, val isExported: Boolean) + : FunctionSymbol(attributes, irFunction, name) { + + override fun equals(other: Any?): Boolean { + if (this === other) return true + if (other !is External) return false + + return hash == other.hash + } + + override fun hashCode(): Int { + return hash.hashCode() + } + + override fun toString(): String { + return "ExternalFunction(hash='$hash', name='$name', escapes='$escapes', pointsTo='${pointsTo?.contentToString()}')" + } + } + + abstract class Declared(val module: Module, val symbolTableIndex: Int, + attributes: Int, irFunction: IrFunction?, var bridgeTarget: FunctionSymbol?, name: String?) + : FunctionSymbol(attributes, irFunction, name) { + + } + + class Public(val hash: Long, module: Module, symbolTableIndex: Int, + attributes: Int, irFunction: IrFunction?, bridgeTarget: FunctionSymbol?, name: String? = null) + : Declared(module, symbolTableIndex, attributes, irFunction, bridgeTarget, name) { + + override fun equals(other: Any?): Boolean { + if (this === other) return true + if (other !is Public) return false + + return hash == other.hash + } + + override fun hashCode(): Int { + return hash.hashCode() + } + + override fun toString(): String { + return "PublicFunction(hash='$hash', name='$name', symbolTableIndex='$symbolTableIndex', escapes='$escapes', pointsTo='${pointsTo?.contentToString()})" + } + } + + class Private(val index: Int, module: Module, symbolTableIndex: Int, + attributes: Int, irFunction: IrFunction?, bridgeTarget: FunctionSymbol?, name: String? = null) + : Declared(module, symbolTableIndex, attributes, irFunction, bridgeTarget, name) { + + override fun equals(other: Any?): Boolean { + if (this === other) return true + if (other !is Private) return false + + return index == other.index + } + + override fun hashCode(): Int { + return index + } + + override fun toString(): String { + return "PrivateFunction(index=$index, symbolTableIndex='$symbolTableIndex', name='$name', escapes='$escapes', pointsTo='${pointsTo?.contentToString()})" + } + } + } + + data class Field(val receiverType: Type?, val type: Type, val hash: Long, val name: String? = null) + + class Edge(val castToType: Type?) { + + lateinit var node: Node + + constructor(node: Node, castToType: Type?) : this(castToType) { + this.node = node + } + } + + enum class VariableKind { + Ordinary, + Temporary, + CatchParameter + } + + sealed class Node { + class Parameter(val index: Int) : Node() + + open class Const(val type: Type) : Node() + + class SimpleConst(type: Type, val value: T) : Const(type) + + object Null : Node() + + open class Call(val callee: FunctionSymbol, val arguments: List, val returnType: Type, + open val irCallSite: IrFunctionAccessExpression?) : Node() + + class StaticCall(callee: FunctionSymbol, arguments: List, + val receiverType: Type?, returnType: Type, irCallSite: IrFunctionAccessExpression?) + : Call(callee, arguments, returnType, irCallSite) + + // TODO: It can be replaced with a pair(AllocInstance, constructor Call), remove. + class NewObject(constructor: FunctionSymbol, arguments: List, + val constructedType: Type, override val irCallSite: IrConstructorCall?) + : Call(constructor, arguments, constructedType, irCallSite) + + open class VirtualCall(callee: FunctionSymbol, arguments: List, + val receiverType: Type, returnType: Type, override val irCallSite: IrCall?) + : Call(callee, arguments, returnType, irCallSite) + + class VtableCall(callee: FunctionSymbol, receiverType: Type, val calleeVtableIndex: Int, + arguments: List, returnType: Type, irCallSite: IrCall?) + : VirtualCall(callee, arguments, receiverType, returnType, irCallSite) + + class ItableCall(callee: FunctionSymbol, receiverType: Type, val calleeHash: Long, + arguments: List, returnType: Type, irCallSite: IrCall?) + : VirtualCall(callee, arguments, receiverType, returnType, irCallSite) + + class Singleton(val type: Type, val constructor: FunctionSymbol?) : Node() + + class AllocInstance(val type: Type, val irCallSite: IrCall?) : Node() + + class FunctionReference(val symbol: FunctionSymbol, val type: Type, val returnType: Type) : Node() + + class FieldRead(val receiver: Edge?, val field: Field, val type: Type, val ir: IrGetField?) : Node() + + class FieldWrite(val receiver: Edge?, val field: Field, val value: Edge, val type: Type) : Node() + + class ArrayRead(val callee: FunctionSymbol, val array: Edge, val index: Edge, val type: Type, val irCallSite: IrCall?) : Node() + + class ArrayWrite(val callee: FunctionSymbol, val array: Edge, val index: Edge, val value: Edge, val type: Type) : Node() + + class Variable(values: List, val type: Type, val kind: VariableKind) : Node() { + val values = mutableListOf().also { it += values } + } + + class Scope(val depth: Int, nodes: List) : Node() { + val nodes = mutableSetOf().also { it += nodes } + } + } + + // Note: scopes form a tree. + class FunctionBody(val rootScope: Node.Scope, val allScopes: List, + val returns: Node.Variable, val throws: Node.Variable) { + inline fun forEachNonScopeNode(block: (Node) -> Unit) { + for (scope in allScopes) + for (node in scope.nodes) + if (node !is Node.Scope) + block(node) + } + } + + class Function(val symbol: FunctionSymbol, val body: FunctionBody) { + + fun debugOutput() = println(debugString()) + + fun debugString() = buildString { + appendLine("FUNCTION $symbol") + appendLine("Params: ${symbol.parameters.contentToString()}") + val nodes = listOf(body.rootScope) + body.allScopes.flatMap { it.nodes } + val ids = nodes.withIndex().associateBy({ it.value }, { it.index }) + nodes.forEach { + appendLine(" NODE #${ids[it]!!}") + appendLine(nodeToString(it, ids)) + } + appendLine(" RETURNS") + append(nodeToString(body.returns, ids)) + } + + companion object { + fun printNode(node: Node, ids: Map) = print(nodeToString(node, ids)) + + fun nodeToString(node: Node, ids: Map) = when (node) { + is Node.Const -> + " CONST ${node.type}" + + Node.Null -> + " NULL" + + is Node.Parameter -> + " PARAM ${node.index}" + + is Node.Singleton -> + " SINGLETON ${node.type}" + + is Node.AllocInstance -> + " ALLOC INSTANCE ${node.type}" + + is Node.FunctionReference -> + " FUNCTION REFERENCE ${node.symbol}" + + is Node.StaticCall -> buildString { + append(" STATIC CALL ${node.callee}. Return type = ${node.returnType}") + appendList(node.arguments) { + append(" ARG #${ids[it.node]!!}") + appendCastTo(it.castToType) + } + } + + is Node.VtableCall -> buildString { + appendLine(" VIRTUAL CALL ${node.callee}. Return type = ${node.returnType}") + appendLine(" RECEIVER: ${node.receiverType}") + append(" VTABLE INDEX: ${node.calleeVtableIndex}") + appendList(node.arguments) { + append(" ARG #${ids[it.node]!!}") + appendCastTo(it.castToType) + } + } + + is Node.ItableCall -> buildString { + appendLine(" INTERFACE CALL ${node.callee}. Return type = ${node.returnType}") + appendLine(" RECEIVER: ${node.receiverType}") + append(" METHOD HASH: ${node.calleeHash}") + appendList(node.arguments) { + append(" ARG #${ids[it.node]!!}") + appendCastTo(it.castToType) + } + } + + is Node.NewObject -> buildString { + appendLine(" NEW OBJECT ${node.callee}") + append(" CONSTRUCTED TYPE ${node.constructedType}") + appendList(node.arguments) { + append(" ARG #${ids[it.node]!!}") + appendCastTo(it.castToType) + } + } + + is Node.FieldRead -> buildString { + appendLine(" FIELD READ ${node.field}") + append(" RECEIVER #${node.receiver?.node?.let { ids[it]!! } ?: "null"}") + appendCastTo(node.receiver?.castToType) + } + + is Node.FieldWrite -> buildString { + appendLine(" FIELD WRITE ${node.field}") + append(" RECEIVER #${node.receiver?.node?.let { ids[it]!! } ?: "null"}") + appendCastTo(node.receiver?.castToType) + appendLine() + append(" VALUE #${ids[node.value.node]!!}") + appendCastTo(node.value.castToType) + } + + is Node.ArrayRead -> buildString { + appendLine(" ARRAY READ") + append(" ARRAY #${ids[node.array.node]}") + appendCastTo(node.array.castToType) + appendLine() + append(" INDEX #${ids[node.index.node]!!}") + appendCastTo(node.index.castToType) + } + + is Node.ArrayWrite -> buildString { + appendLine(" ARRAY WRITE") + append(" ARRAY #${ids[node.array.node]}") + appendCastTo(node.array.castToType) + appendLine() + append(" INDEX #${ids[node.index.node]!!}") + appendCastTo(node.index.castToType) + appendLine() + append(" VALUE #${ids[node.value.node]!!}") + appendCastTo(node.value.castToType) + } + + is Node.Variable -> buildString { + append(" ${node.kind}") + appendList(node.values) { + append(" VAL #${ids[it.node]!!}") + appendCastTo(it.castToType) + } + } + + is Node.Scope -> buildString { + append(" SCOPE ${node.depth}") + appendList(node.nodes.toList()) { + append(" SUBNODE #${ids[it]!!}") + } + } + + else -> " UNKNOWN: ${node::class.java}" + } + + private fun StringBuilder.appendList(list: List, itemPrinter: StringBuilder.(T) -> Unit) { + if (list.isEmpty()) return + for (i in list.indices) { + appendLine() + itemPrinter(list[i]) + } + } + + private fun StringBuilder.appendCastTo(type: Type?) { + if (type != null) + append(" CASTED TO ${type}") + } + } + } + + class SymbolTable(val context: Context, val irModule: IrModuleFragment, val module: Module) { + + private val TAKE_NAMES = true // Take fqNames for all functions and types (for debug purposes). + + private inline fun takeName(block: () -> String) = if (TAKE_NAMES) block() else null + + val classMap = mutableMapOf() + val primitiveMap = mutableMapOf() + val functionMap = mutableMapOf() + + private val NAME_ESCAPES = Name.identifier("Escapes") + private val NAME_POINTS_TO = Name.identifier("PointsTo") + private val FQ_NAME_KONAN = FqName.fromSegments(listOf("kotlin", "native", "internal")) + + private val FQ_NAME_ESCAPES = FQ_NAME_KONAN.child(NAME_ESCAPES) + private val FQ_NAME_POINTS_TO = FQ_NAME_KONAN.child(NAME_POINTS_TO) + + private val konanPackage = context.builtIns.builtInsModule.getPackage(FQ_NAME_KONAN).memberScope + private val getContinuationSymbol = context.ir.symbols.getContinuation + private val continuationType = getContinuationSymbol.owner.returnType + + var privateTypeIndex = 1 // 0 for [Virtual] + var privateFunIndex = 0 + + init { + irModule.accept(object : IrElementVisitorVoid { + override fun visitElement(element: IrElement) { + element.acceptChildrenVoid(this) + } + + override fun visitFunction(declaration: IrFunction) { + declaration.body?.let { mapFunction(declaration) } + } + + override fun visitField(declaration: IrField) { + if (declaration.parent is IrFile) + declaration.initializer?.let { + mapFunction(declaration) + } + } + + override fun visitClass(declaration: IrClass) { + declaration.acceptChildrenVoid(this) + + mapClassReferenceType(declaration) + } + }, data = null) + } + + private fun IrClass.isFinal() = modality == Modality.FINAL + + fun mapClassReferenceType(irClass: IrClass): Type { + // Do not try to devirtualize ObjC classes. + if (irClass.module.name == Name.special("") || irClass.isObjCClass()) + return Type.Virtual + + val isFinal = irClass.isFinal() + val isAbstract = irClass.isAbstract() + val name = irClass.fqNameForIrSerialization.asString() + classMap[irClass]?.let { return it } + + val placeToClassTable = true + val symbolTableIndex = if (placeToClassTable) module.numberOfClasses++ else -1 + val type = if (irClass.isExported()) + Type.Public(name.localHash.value, privateTypeIndex++, isFinal, isAbstract, null, + module, symbolTableIndex, irClass, takeName { name }) + else + Type.Private(privateTypeIndex++, isFinal, isAbstract, null, + module, symbolTableIndex, irClass, takeName { name }) + + classMap[irClass] = type + + type.superTypes += irClass.superTypes.map { mapClassReferenceType(it.getClass()!!) } + if (!isAbstract) { + val layoutBuilder = context.getLayoutBuilder(irClass) + type.vtable += layoutBuilder.vtableEntries.map { + mapFunction(it.getImplementation(context)!!) + } + layoutBuilder.methodTableEntries.forEach { + type.itable[it.overriddenFunction.functionName.localHash.value] = mapFunction(it.getImplementation(context)!!) + } + } else if (irClass.isInterface) { + // Warmup interface table so it is computed before DCE. + context.getLayoutBuilder(irClass).interfaceTableEntries + } + return type + } + + private fun choosePrimary(erasure: List): IrClass { + if (erasure.size == 1) return erasure[0] + // A parameter with constraints - choose class if exists. + return erasure.singleOrNull { !it.isInterface } ?: context.ir.symbols.any.owner + } + + private fun mapPrimitiveBinaryType(primitiveBinaryType: PrimitiveBinaryType): Type = + primitiveMap.getOrPut(primitiveBinaryType) { + Type.Public( + primitiveBinaryType.ordinal.toLong(), + privateTypeIndex++, + true, + false, + primitiveBinaryType, + module, + -1, + null, + takeName { primitiveBinaryType.name } + ) + } + + fun mapType(type: IrType): Type { + val binaryType = type.computeBinaryType() + return when (binaryType) { + is BinaryType.Primitive -> mapPrimitiveBinaryType(binaryType.type) + is BinaryType.Reference -> mapClassReferenceType(choosePrimary(binaryType.types.toList())) + } + } + + private fun mapTypeToFunctionParameter(type: IrType) = + type.getInlinedClassNative().let { inlinedClass -> + FunctionParameter(mapType(type), inlinedClass?.let { mapFunction(context.getBoxFunction(it)) }, + inlinedClass?.let { mapFunction(context.getUnboxFunction(it)) }) + } + + fun mapFunction(declaration: IrDeclaration): FunctionSymbol = when (declaration) { + is IrFunction -> mapFunction(declaration) + is IrField -> mapPropertyInitializer(declaration) + else -> error("Unknown declaration: $declaration") + } + + private fun mapFunction(function: IrFunction): FunctionSymbol = function.target.let { + functionMap[it]?.let { return it } + + val parent = it.parent + + val containingDeclarationPart = parent.fqNameForIrSerialization.let { + if (it.isRoot) "" else "$it." + } + val name = "kfun:$containingDeclarationPart${it.functionName}" + + val returnsUnit = it is IrConstructor || (!it.isSuspend && it.returnType.isUnit()) + val returnsNothing = !it.isSuspend && it.returnType.isNothing() + var attributes = 0 + if (returnsUnit) + attributes = attributes or FunctionAttributes.RETURNS_UNIT + if (returnsNothing) + attributes = attributes or FunctionAttributes.RETURNS_NOTHING + if (it.hasAnnotation(RuntimeNames.exportForCppRuntime) + || it.getExternalObjCMethodInfo() != null // TODO-DCE-OBJC-INIT + || it.hasAnnotation(RuntimeNames.objCMethodImp)) { + attributes = attributes or FunctionAttributes.EXPLICITLY_EXPORTED + } + val symbol = when { + it.isExternal || it.isBuiltInOperator -> { + val escapesAnnotation = it.annotations.findAnnotation(FQ_NAME_ESCAPES) + val pointsToAnnotation = it.annotations.findAnnotation(FQ_NAME_POINTS_TO) + @Suppress("UNCHECKED_CAST") + val escapesBitMask = (escapesAnnotation?.getValueArgument(0) as? IrConst)?.value + @Suppress("UNCHECKED_CAST") + val pointsToBitMask = (pointsToAnnotation?.getValueArgument(0) as? IrVararg)?.elements?.map { (it as IrConst).value } + FunctionSymbol.External(name.localHash.value, attributes, it, takeName { name }, it.isExported()).apply { + escapes = escapesBitMask + pointsTo = pointsToBitMask?.toIntArray() + } + } + + else -> { + val isAbstract = it is IrSimpleFunction && it.modality == Modality.ABSTRACT + val irClass = it.parent as? IrClass + val bridgeTarget = it.bridgeTarget + val isSpecialBridge = bridgeTarget.let { + it != null && BuiltinMethodsWithSpecialGenericSignature.getDefaultValueForOverriddenBuiltinFunction(it.descriptor) != null + } + val bridgeTargetSymbol = if (isSpecialBridge || bridgeTarget == null) null else mapFunction(bridgeTarget) + val placeToFunctionsTable = !isAbstract && it !is IrConstructor && irClass != null + && !irClass.isNonGeneratedAnnotation() + && (it.isOverridableOrOverrides || bridgeTarget != null || function.isSpecial || !irClass.isFinal()) + val symbolTableIndex = if (placeToFunctionsTable) module.numberOfFunctions++ else -1 + val frozen = it is IrConstructor && irClass!!.annotations.findAnnotation(KonanFqNames.frozen) != null + val functionSymbol = if (it.isExported()) + FunctionSymbol.Public(name.localHash.value, module, symbolTableIndex, attributes, it, bridgeTargetSymbol, takeName { name }) + else + FunctionSymbol.Private(privateFunIndex++, module, symbolTableIndex, attributes, it, bridgeTargetSymbol, takeName { name }) + if (frozen) { + functionSymbol.escapes = 0b1 // Assume instances of frozen classes escape. + } + functionSymbol + } + } + functionMap[it] = symbol + + symbol.parameters = + (function.allParameters.map { it.type } + (if (function.isSuspend) listOf(continuationType) else emptyList())) + .map { mapTypeToFunctionParameter(it) } + .toTypedArray() + symbol.returnParameter = mapTypeToFunctionParameter(if (function.isSuspend) + context.irBuiltIns.anyType + else + function.returnType) + + return symbol + } + + private val IrFunction.isSpecial get() = + origin == DECLARATION_ORIGIN_INLINE_CLASS_SPECIAL_FUNCTION + || origin is DECLARATION_ORIGIN_BRIDGE_METHOD + + private fun mapPropertyInitializer(irField: IrField): FunctionSymbol { + functionMap[irField]?.let { return it } + + assert(irField.parent !is IrClass) { "All local properties initializers should've been lowered" } + val attributes = FunctionAttributes.IS_GLOBAL_INITIALIZER or FunctionAttributes.RETURNS_UNIT + val symbol = FunctionSymbol.Private(privateFunIndex++, module, -1, attributes, null, null, takeName { "${irField.symbolName}_init" }) + + functionMap[irField] = symbol + + symbol.parameters = emptyArray() + symbol.returnParameter = mapTypeToFunctionParameter(context.irBuiltIns.unitType) + return symbol + } + } +} \ No newline at end of file diff --git a/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/optimizations/Devirtualization.kt b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/optimizations/Devirtualization.kt new file mode 100644 index 00000000000..3f67829cdf2 --- /dev/null +++ b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/optimizations/Devirtualization.kt @@ -0,0 +1,1547 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +package org.jetbrains.kotlin.backend.konan.optimizations + +import org.jetbrains.kotlin.backend.common.IrElementTransformerVoidWithContext +import org.jetbrains.kotlin.backend.common.descriptors.explicitParameters +import org.jetbrains.kotlin.backend.common.ir.ir2stringWhole +import org.jetbrains.kotlin.backend.common.pop +import org.jetbrains.kotlin.backend.common.push +import org.jetbrains.kotlin.backend.common.lower.createIrBuilder +import org.jetbrains.kotlin.backend.common.lower.irBlock +import org.jetbrains.kotlin.backend.konan.* +import org.jetbrains.kotlin.backend.konan.ir.isBoxOrUnboxCall +import org.jetbrains.kotlin.backend.konan.util.IntArrayList +import org.jetbrains.kotlin.backend.konan.util.LongArrayList +import org.jetbrains.kotlin.descriptors.ClassKind +import org.jetbrains.kotlin.ir.IrElement +import org.jetbrains.kotlin.ir.builders.* +import org.jetbrains.kotlin.ir.declarations.* +import org.jetbrains.kotlin.ir.declarations.impl.IrVariableImpl +import org.jetbrains.kotlin.ir.descriptors.WrappedVariableDescriptor +import org.jetbrains.kotlin.ir.expressions.* +import org.jetbrains.kotlin.ir.expressions.impl.* +import org.jetbrains.kotlin.ir.symbols.IrFunctionSymbol +import org.jetbrains.kotlin.ir.symbols.impl.IrReturnableBlockSymbolImpl +import org.jetbrains.kotlin.ir.symbols.impl.IrVariableSymbolImpl +import org.jetbrains.kotlin.ir.types.IrType +import org.jetbrains.kotlin.ir.types.classifierOrFail +import org.jetbrains.kotlin.ir.types.impl.originalKotlinType +import org.jetbrains.kotlin.ir.types.toKotlinType +import org.jetbrains.kotlin.ir.util.irCall +import org.jetbrains.kotlin.ir.util.explicitParameters +import org.jetbrains.kotlin.ir.util.* +import org.jetbrains.kotlin.ir.visitors.IrElementTransformerVoid +import org.jetbrains.kotlin.ir.visitors.IrElementVisitorVoid +import org.jetbrains.kotlin.ir.visitors.acceptChildrenVoid +import org.jetbrains.kotlin.ir.visitors.transformChildrenVoid +import org.jetbrains.kotlin.name.Name +import java.util.* +import kotlin.collections.ArrayList + +inline fun BitSet.forEachBit(block: (Int) -> Unit) { + var i = -1 + while (true) { + i = nextSetBit(i + 1) + if (i < 0) break + block(i) + } +} + +// Devirtualization analysis is performed using Variable Type Analysis algorithm. +// See http://web.cs.ucla.edu/~palsberg/tba/papers/sundaresan-et-al-oopsla00.pdf for details. +internal object Devirtualization { + + private val TAKE_NAMES = false // Take fqNames for all functions and types (for debug purposes). + + private inline fun takeName(block: () -> String) = if (TAKE_NAMES) block() else null + + fun computeRootSet(context: Context, moduleDFG: ModuleDFG, externalModulesDFG: ExternalModulesDFG) + : List { + + fun DataFlowIR.FunctionSymbol.resolved(): DataFlowIR.FunctionSymbol { + if (this is DataFlowIR.FunctionSymbol.External) + return externalModulesDFG.publicFunctions[this.hash] ?: this + return this + } + + val entryPoint = context.ir.symbols.entryPoint?.owner + val exportedFunctions = + if (entryPoint != null) + listOf(moduleDFG.symbolTable.mapFunction(entryPoint).resolved()) + else { + // In a library every public function and every function accessible via virtual call belongs to the rootset. + moduleDFG.symbolTable.functionMap.values.filter { + it is DataFlowIR.FunctionSymbol.Public + || (it as? DataFlowIR.FunctionSymbol.External)?.isExported == true + } + + moduleDFG.symbolTable.classMap.values + .filterIsInstance() + .flatMap { it.vtable + it.itable.values } + .filterIsInstance() + .filter { moduleDFG.functions.containsKey(it) } + } + // TODO: Are globals initializers always called whether they are actually reachable from roots or not? + val globalInitializers = + moduleDFG.symbolTable.functionMap.values.filter { it.isGlobalInitializer } + + externalModulesDFG.functionDFGs.keys.filter { it.isGlobalInitializer } + + val explicitlyExportedFunctions = + moduleDFG.symbolTable.functionMap.values.filter { it.explicitlyExported } + + externalModulesDFG.functionDFGs.keys.filter { it.explicitlyExported } + + // Conservatively assume each associated object could be called. + // Note: for constructors there is additional parameter () and its type will be added + // to instantiating classes since all objects are final types. + val associatedObjects = mutableListOf() + context.irModule!!.acceptChildrenVoid(object: IrElementVisitorVoid { + override fun visitElement(element: IrElement) { + element.acceptChildrenVoid(this) + } + + override fun visitClass(declaration: IrClass) { + context.getLayoutBuilder(declaration).associatedObjects.values.forEach { + assert (it.kind == ClassKind.OBJECT) { "An object expected but was ${it.dump()}" } + associatedObjects += moduleDFG.symbolTable.mapFunction(it.constructors.single()) + } + super.visitClass(declaration) + } + }) + + return (exportedFunctions + globalInitializers + explicitlyExportedFunctions + associatedObjects).distinct() + } + + fun BitSet.format(allTypes: Array): String { + return allTypes.withIndex().filter { this[it.index] }.joinToString { it.value.toString() } + } + + private val VIRTUAL_TYPE_ID = 0 // Id of [DataFlowIR.Type.Virtual]. + + internal class DevirtualizationAnalysis(val context: Context, + val moduleDFG: ModuleDFG, + val externalModulesDFG: ExternalModulesDFG) { + + private val entryPoint = context.ir.symbols.entryPoint?.owner + + private val symbolTable = moduleDFG.symbolTable + + sealed class Node(val id: Int) { + var directCastEdges: MutableList? = null + var reversedCastEdges: MutableList? = null + + val types = BitSet() + + var priority = -1 + + var multiNodeStart = -1 + var multiNodeEnd = -1 + + val multiNodeSize get() = multiNodeEnd - multiNodeStart + + fun addCastEdge(edge: CastEdge) { + if (directCastEdges == null) directCastEdges = ArrayList(1) + directCastEdges!!.add(edge) + if (edge.node.reversedCastEdges == null) edge.node.reversedCastEdges = ArrayList(1) + edge.node.reversedCastEdges!!.add(CastEdge(this, edge.suitableTypes)) + } + + abstract fun toString(allTypes: Array): String + + class Source(id: Int, typeId: Int, nameBuilder: () -> String): Node(id) { + val name = takeName(nameBuilder) + + init { + types.set(typeId) + } + + override fun toString(allTypes: Array): String { + return "Source(name='$name', types='${types.format(allTypes)}')" + } + } + + class Ordinary(id: Int, nameBuilder: () -> String) : Node(id) { + val name = takeName(nameBuilder) + + override fun toString(allTypes: Array): String { + return "Ordinary(name='$name', types='${types.format(allTypes)}')" + } + } + + class CastEdge(val node: Node, val suitableTypes: BitSet) + } + + class Function(val symbol: DataFlowIR.FunctionSymbol, val parameters: Array, val returns: Node, val throws: Node) + + inner class ConstraintGraph { + + private var nodesCount = 0 + + val nodes = mutableListOf() + + val voidNode = addNode { Node.Ordinary(it, { "Void" }) } + val virtualNode = addNode { Node.Source(it, VIRTUAL_TYPE_ID, { "Virtual" }) } + val arrayItemField = DataFlowIR.Field(null, + symbolTable.mapClassReferenceType(context.irBuiltIns.anyClass.owner), 1, "Array\$Item") + val functions = mutableMapOf() + val externalFunctions = mutableMapOf, Node>() + val fields = mutableMapOf() // Do not distinguish receivers. + val virtualCallSiteReceivers = mutableMapOf() + + private fun nextId(): Int = nodesCount++ + + fun addNode(nodeBuilder: (Int) -> Node) = nodeBuilder(nextId()).also { nodes.add(it) } + } + + private val constraintGraph = ConstraintGraph() + + private fun DataFlowIR.Type.resolved(): DataFlowIR.Type.Declared { + if (this is DataFlowIR.Type.Declared) return this + val hash = (this as DataFlowIR.Type.External).hash + return externalModulesDFG.publicTypes[hash] ?: error("Unable to resolve exported type $this") + } + + private fun DataFlowIR.FunctionSymbol.resolved(): DataFlowIR.FunctionSymbol { + if (this is DataFlowIR.FunctionSymbol.External) + return externalModulesDFG.publicFunctions[this.hash] ?: this + return this + } + + private inline fun forEachBitInBoth(first: BitSet, second: BitSet, block: (Int) -> Unit) { + if (first.cardinality() < second.cardinality()) + first.forEachBit { + if (second[it]) + block(it) + } + else second.forEachBit { + if (first[it]) + block(it) + } + } + + private inline fun IntArray.forEachEdge(v: Int, block: (Int) -> Unit) { + for (i in this[v] until this[v + 1]) + block(this[i]) + } + + inner class TypeHierarchy(val allTypes: Array) { + private val typesSubTypes = Array(allTypes.size) { mutableListOf() } + private val allInheritors = Array(allTypes.size) { BitSet() } + + init { + val visited = BitSet() + + fun processType(type: DataFlowIR.Type.Declared) { + if (visited[type.index]) return + visited.set(type.index) + type.superTypes + .map { it.resolved() } + .forEach { superType -> + val subTypes = typesSubTypes[superType.index] + subTypes += type + processType(superType) + } + } + + allTypes.forEach { processType(it) } + } + + fun inheritorsOf(type: DataFlowIR.Type.Declared): BitSet { + val typeId = type.index + val inheritors = allInheritors[typeId] + if (!inheritors.isEmpty || type == DataFlowIR.Type.Virtual) return inheritors + inheritors.set(typeId) + for (subType in typesSubTypes[typeId]) + inheritors.or(inheritorsOf(subType)) + return inheritors + } + } + + private fun DataFlowIR.Type.Declared.calleeAt(callSite: DataFlowIR.Node.VirtualCall) = when (callSite) { + is DataFlowIR.Node.VtableCall -> + vtable[callSite.calleeVtableIndex] + + is DataFlowIR.Node.ItableCall -> + itable[callSite.calleeHash]!! + + else -> error("Unreachable") + } + + fun BitSet.copy() = BitSet(this.size()).apply { this.or(this@copy) } + + fun logPathToType(reversedEdges: IntArray, node: Node, type: Int) { + val nodes = constraintGraph.nodes + val visited = BitSet() + val prev = mutableMapOf() + var front = mutableListOf() + front.add(node) + visited.set(node.id) + lateinit var source: Node.Source + bfs@while (front.isNotEmpty()) { + val prevFront = front + front = mutableListOf() + for (from in prevFront) { + var endBfs = false + reversedEdges.forEachEdge(from.id) { toId -> + val to = nodes[toId] + if (!visited[toId] && to.types[type]) { + visited.set(toId) + prev[to] = from + front.add(to) + if (to is Node.Source) { + source = to + endBfs = true + return@forEachEdge + } + } + } + if (endBfs) break@bfs + val reversedCastEdges = from.reversedCastEdges + if (reversedCastEdges != null) + for (castEdge in reversedCastEdges) { + val to = castEdge.node + if (!visited[to.id] && castEdge.suitableTypes[type] && to.types[type]) { + visited.set(to.id) + prev[to] = from + front.add(to) + if (to is Node.Source) { + source = to + break@bfs + } + } + } + } + } + try { + var cur: Node = source + do { + context.log { " #${cur.id}" } + cur = prev[cur]!! + } while (cur != node) + } catch (t: Throwable) { + context.log { "Unable to print path" } + } + } + + private inner class Condensation(val multiNodes: IntArray, val topologicalOrder: IntArray) { + inline fun forEachNode(node: Node, block: (Node) -> Unit) { + for (i in node.multiNodeStart until node.multiNodeEnd) + block(constraintGraph.nodes[multiNodes[i]]) + } + } + + private inner class CondensationBuilder(val directEdges: IntArray, val reversedEdges: IntArray) { + val nodes = constraintGraph.nodes + val nodesCount = nodes.size + val visited = BitSet(nodesCount) + var index = 0 + val multiNodes = IntArray(nodesCount) + + fun build(): Condensation { + // First phase. + val order = IntArray(nodesCount) + for (node in nodes) { + if (!visited[node.id]) + findOrder(node, order) + } + + // Second phase. + visited.clear() + index = 0 + var multiNodesCount = 0 + val multiNodesRepresentatives = IntArray(nodesCount) + for (i in order.size - 1 downTo 0) { + val nodeIndex = order[i] + if (visited[nodeIndex]) continue + multiNodesRepresentatives[multiNodesCount++] = nodeIndex + val start = index + paint(nodes[nodeIndex]) + val end = index + for (multiNodeIndex in start until end) { + val node = nodes[multiNodes[multiNodeIndex]] + node.multiNodeStart = start + node.multiNodeEnd = end + } + } + + // Topsort the built condensation. + visited.clear() + index = 0 + val multiNodesOrder = IntArray(multiNodesCount) + for (v in multiNodesRepresentatives) { + if (!visited[v]) + findMultiNodesOrder(nodes[v], multiNodesOrder) + } + multiNodesOrder.reverse() + + return Condensation(multiNodes, multiNodesOrder) + } + + private fun findOrder(node: Node, order: IntArray) { + visited.set(node.id) + directEdges.forEachEdge(node.id) { + if (!visited[it]) + findOrder(nodes[it], order) + } + order[index++] = node.id + } + + private fun paint(node: Node) { + visited.set(node.id) + multiNodes[index++] = node.id + reversedEdges.forEachEdge(node.id) { + if (!visited[it]) + paint(nodes[it]) + } + } + + private fun findMultiNodesOrder(multiNode: Node, order: IntArray) { + visited.set(multiNode.id) + for (v in multiNode.multiNodeStart until multiNode.multiNodeEnd) { + val node = nodes[multiNodes[v]] + directEdges.forEachEdge(node.id) { + val nextMultiNode = multiNodes[nodes[it].multiNodeStart] + if (!visited[nextMultiNode]) + findMultiNodesOrder(nodes[nextMultiNode], order) + } + } + order[index++] = multiNode.id + } + } + + private fun DataFlowIR.Node.VirtualCall.debugString() = + irCallSite?.let { ir2stringWhole(it).trimEnd() } ?: this.toString() + + fun analyze(): AnalysisResult { + val functions = moduleDFG.functions + externalModulesDFG.functionDFGs + assert(DataFlowIR.Type.Virtual !in symbolTable.classMap.values) { + "DataFlowIR.Type.Virtual cannot be in symbolTable.classMap" + } + val allDeclaredTypes = listOf(DataFlowIR.Type.Virtual) + + symbolTable.classMap.values.filterIsInstance() + + symbolTable.primitiveMap.values.filterIsInstance() + + externalModulesDFG.allTypes + val allTypes = Array(allDeclaredTypes.size) { DataFlowIR.Type.Virtual } + for (type in allDeclaredTypes) + allTypes[type.index] = type + val typeHierarchy = TypeHierarchy(allTypes) + val rootSet = computeRootSet(context, moduleDFG, externalModulesDFG) + + val nodesMap = mutableMapOf() + + val (instantiatingClasses, directEdges, reversedEdges) = buildConstraintGraph(nodesMap, functions, typeHierarchy, rootSet) + + context.logMultiple { + +"FULL CONSTRAINT GRAPH" + constraintGraph.nodes.forEach { + +" NODE #${it.id}" + directEdges.forEachEdge(it.id) { +" EDGE: #${it}z" } + it.directCastEdges?.forEach { + +" CAST EDGE: #${it.node.id}z casted to ${it.suitableTypes.format(allTypes)}" + } + allTypes.forEachIndexed { index, type -> + if (it.types[index]) + +" TYPE: $type" + } + } + +"" + } + + constraintGraph.nodes.forEach { + if (it is Node.Source) { + assert(reversedEdges[it.id] == reversedEdges[it.id + 1]) { "A source node #${it.id} has incoming edges" } + assert(it.reversedCastEdges?.isEmpty() ?: true) { "A source node #${it.id} has incoming edges" } + } + } + + context.logMultiple { + val edgesCount = constraintGraph.nodes.sumBy { + (directEdges[it.id + 1] - directEdges[it.id]) + (it.directCastEdges?.size ?: 0) + } + +"CONSTRAINT GRAPH: ${constraintGraph.nodes.size} nodes, $edgesCount edges" + +"" + } + + val condensation = CondensationBuilder(directEdges, reversedEdges).build() + val topologicalOrder = condensation.topologicalOrder.map { constraintGraph.nodes[it] } + + context.logMultiple { + +"CONDENSATION" + topologicalOrder.forEachIndexed { index, multiNode -> + +" MULTI-NODE #$index" + condensation.forEachNode(multiNode) { +" #${it.id}: ${it.toString(allTypes)}" } + } + +"" + } + + topologicalOrder.forEachIndexed { index, multiNode -> + condensation.forEachNode(multiNode) { node -> node.priority = index } + } + + val badEdges = mutableListOf>() + for (node in constraintGraph.nodes) { + node.directCastEdges + ?.filter { it.node.priority < node.priority } // Contradicts topological order. + ?.forEach { badEdges += node to it } + } + badEdges.sortBy { it.second.node.priority } // Heuristic. + + // First phase - greedy phase. + var iterations = 0 + val maxNumberOfIterations = 2 + do { + ++iterations + // Handle all 'right-directed' edges. + // TODO: this is pessimistic handling of [DataFlowIR.Type.Virtual], think how to do it better. + for (multiNode in topologicalOrder) { + if (multiNode.multiNodeSize == 1 && multiNode is Node.Source) + continue // A source has no incoming edges. + val types = BitSet() + condensation.forEachNode(multiNode) { node -> + reversedEdges.forEachEdge(node.id) { + types.or(constraintGraph.nodes[it].types) + } + node.reversedCastEdges + ?.filter { it.node.priority < node.priority } // Doesn't contradict topological order. + ?.forEach { + val sourceTypes = it.node.types.copy() + sourceTypes.and(it.suitableTypes) + types.or(sourceTypes) + } + } + condensation.forEachNode(multiNode) { node -> node.types.or(types) } + } + if (iterations >= maxNumberOfIterations) break + + var end = true + for ((sourceNode, edge) in badEdges) { + val distNode = edge.node + val missingTypes = sourceNode.types.copy().apply { andNot(distNode.types) } + missingTypes.and(edge.suitableTypes) + if (!missingTypes.isEmpty) { + end = false + distNode.types.or(missingTypes) + } + } + } while (!end) + + // Second phase - do BFS. + val nodesCount = constraintGraph.nodes.size + val marked = BitSet(nodesCount) + var front = IntArray(nodesCount) + var prevFront = IntArray(nodesCount) + var frontSize = 0 + val tempBitSet = BitSet() + for ((sourceNode, edge) in badEdges) { + val distNode = edge.node + tempBitSet.clear() + tempBitSet.or(sourceNode.types) + tempBitSet.andNot(distNode.types) + tempBitSet.and(edge.suitableTypes) + distNode.types.or(tempBitSet) + if (!marked[distNode.id] && !tempBitSet.isEmpty) { + marked.set(distNode.id) + front[frontSize++] = distNode.id + } + } + + while (frontSize > 0) { + val prevFrontSize = frontSize + frontSize = 0 + val temp = front + front = prevFront + prevFront = temp + for (i in 0 until prevFrontSize) { + marked[prevFront[i]] = false + val node = constraintGraph.nodes[prevFront[i]] + directEdges.forEachEdge(node.id) { distNodeId -> + val distNode = constraintGraph.nodes[distNodeId] + if (marked[distNode.id]) + distNode.types.or(node.types) + else { + tempBitSet.clear() + tempBitSet.or(node.types) + tempBitSet.andNot(distNode.types) + distNode.types.or(node.types) + if (!marked[distNode.id] && !tempBitSet.isEmpty) { + marked.set(distNode.id) + front[frontSize++] = distNode.id + } + } + } + node.directCastEdges?.forEach { edge -> + val distNode = edge.node + tempBitSet.clear() + tempBitSet.or(node.types) + tempBitSet.andNot(distNode.types) + tempBitSet.and(edge.suitableTypes) + distNode.types.or(tempBitSet) + if (!marked[distNode.id] && !tempBitSet.isEmpty) { + marked.set(distNode.id) + front[frontSize++] = distNode.id + } + } + } + } + + context.logMultiple { + topologicalOrder.forEachIndexed { index, multiNode -> + +"Types of multi-node #$index" + condensation.forEachNode(multiNode) { node -> + +" Node #${node.id}" + allTypes.asSequence() + .withIndex() + .filter { node.types[it.index] }.toList() + .forEach { +" ${it.value}" } + } + } + +"" + } + + val result = mutableMapOf>() + val nothing = symbolTable.classMap[context.ir.symbols.nothing.owner] + for (function in functions.values) { + if (!constraintGraph.functions.containsKey(function.symbol)) continue + function.body.forEachNonScopeNode { node -> + val virtualCall = node as? DataFlowIR.Node.VirtualCall ?: return@forEachNonScopeNode + assert(nodesMap[virtualCall] != null) { "Node for virtual call $virtualCall has not been built" } + val receiverNode = constraintGraph.virtualCallSiteReceivers[virtualCall] + ?: error("virtualCallSiteReceivers were not built for virtual call $virtualCall") + if (receiverNode.types[VIRTUAL_TYPE_ID]) { + context.logMultiple { + +"Unable to devirtualize callsite ${virtualCall.debugString()}" + +" receiver is Virtual" + logPathToType(reversedEdges, receiverNode, VIRTUAL_TYPE_ID) + +"" + } + return@forEachNonScopeNode + } + + context.log { "Devirtualized callsite ${virtualCall.debugString()}" } + val receiverType = virtualCall.receiverType.resolved() + val possibleReceivers = mutableListOf() + forEachBitInBoth(receiverNode.types, typeHierarchy.inheritorsOf(receiverType)) { + val type = allTypes[it] + assert(instantiatingClasses[it]) { "Non-instantiating class $type" } + if (type != nothing) { + context.logMultiple { + +"Path to type $type" + logPathToType(reversedEdges, receiverNode, it) + } + possibleReceivers.add(type) + } + } + context.log { "" } + + result[virtualCall] = DevirtualizedCallSite(virtualCall.callee.resolved(), + possibleReceivers.map { possibleReceiverType -> + val callee = possibleReceiverType.calleeAt(virtualCall) + if (callee is DataFlowIR.FunctionSymbol.Declared && callee.symbolTableIndex < 0) + error("Function ${possibleReceiverType}.$callee cannot be called virtually," + + " but actually is at call site: ${virtualCall.debugString()}") + DevirtualizedCallee(possibleReceiverType, callee) + }) to function.symbol + + } + } + + context.logMultiple { + +"Devirtualized from current module:" + result.forEach { virtualCall, devirtualizedCallSite -> + if (virtualCall.irCallSite != null) { + +"DEVIRTUALIZED" + +"FUNCTION: ${devirtualizedCallSite.second}" + +"CALL SITE: ${virtualCall.debugString()}" + +"POSSIBLE RECEIVERS:" + devirtualizedCallSite.first.possibleCallees.forEach { +" TYPE: ${it.receiverType}" } + devirtualizedCallSite.first.possibleCallees.forEach { +" FUN: ${it.callee}" } + +"" + } + } + +"Devirtualized from external modules:" + result.forEach { virtualCall, devirtualizedCallSite -> + if (virtualCall.irCallSite == null) { + +"DEVIRTUALIZED" + +"FUNCTION: ${devirtualizedCallSite.second}" + +"CALL SITE: ${virtualCall.debugString()}" + +"POSSIBLE RECEIVERS:" + devirtualizedCallSite.first.possibleCallees.forEach { +" TYPE: ${it.receiverType}" } + devirtualizedCallSite.first.possibleCallees.forEach { +" FUN: ${it.callee}" } + +"" + } + } + } + + return AnalysisResult(result.asSequence().associateBy({ it.key }, { it.value.first }), typeHierarchy) + } + + // Both [directEdges] and [reversedEdges] are the array representation of a graph: + // for each node v the edges of that node are stored in edges[edges[v] until edges[v + 1]]. + private data class ConstraintGraphBuildResult(val instantiatingClasses: BitSet, + val directEdges: IntArray, val reversedEdges: IntArray) + + // Here we're dividing the build process onto two phases: + // 1. build bag of edges and direct edges array; + // 2. build reversed edges array from the direct edges array. + // This is to lower memory usage (all of these edges structures are more or less equal by size), + // and by that we're only holding references to two out of three of them. + private fun buildConstraintGraph(nodesMap: MutableMap, + functions: Map, + typeHierarchy: TypeHierarchy, + rootSet: List + ): ConstraintGraphBuildResult { + val precursor = buildConstraintGraphPrecursor(nodesMap, functions, typeHierarchy, rootSet) + return ConstraintGraphBuildResult(precursor.instantiatingClasses, precursor.directEdges, + buildReversedEdges(precursor.directEdges, precursor.reversedEdgesCount)) + } + + private class ConstraintGraphPrecursor(val instantiatingClasses: BitSet, + val directEdges: IntArray, val reversedEdgesCount: IntArrayList) + + private fun buildReversedEdges(directEdges: IntArray, reversedEdgesCount: IntArrayList): IntArray { + val numberOfNodes = constraintGraph.nodes.size + var edgesArraySize = numberOfNodes + 1 + for (v in 0 until numberOfNodes) + edgesArraySize += reversedEdgesCount[v] + val reversedEdges = IntArray(edgesArraySize) + var index = numberOfNodes + 1 + for (v in 0..numberOfNodes) { + reversedEdges[v] = index + index += reversedEdgesCount[v] + reversedEdgesCount[v] = 0 + } + for (from in 0 until numberOfNodes) { + directEdges.forEachEdge(from) { to -> + reversedEdges[reversedEdges[to] + (reversedEdgesCount[to]++)] = from + } + } + return reversedEdges + } + + private fun buildConstraintGraphPrecursor(nodesMap: MutableMap, + functions: Map, + typeHierarchy: TypeHierarchy, + rootSet: List + ): ConstraintGraphPrecursor { + val constraintGraphBuilder = ConstraintGraphBuilder(nodesMap, functions, typeHierarchy, rootSet, true) + constraintGraphBuilder.build() + val bagOfEdges = constraintGraphBuilder.bagOfEdges + val directEdgesCount = constraintGraphBuilder.directEdgesCount + val reversedEdgesCount = constraintGraphBuilder.reversedEdgesCount + val numberOfNodes = constraintGraph.nodes.size + // numberOfNodes + 1 for convenience. + directEdgesCount.reserve(numberOfNodes + 1) + reversedEdgesCount.reserve(numberOfNodes + 1) + var edgesArraySize = numberOfNodes + 1 + for (v in 0 until numberOfNodes) + edgesArraySize += directEdgesCount[v] + val directEdges = IntArray(edgesArraySize) + var index = numberOfNodes + 1 + for (v in 0..numberOfNodes) { + directEdges[v] = index + index += directEdgesCount[v] + directEdgesCount[v] = 0 + } + for (bucket in bagOfEdges) + if (bucket != null) + for (edge in bucket) { + val from = edge.toInt() + val to = (edge shr 32).toInt() + directEdges[directEdges[from] + (directEdgesCount[from]++)] = to + } + return ConstraintGraphPrecursor(constraintGraphBuilder.instantiatingClasses, directEdges, reversedEdgesCount) + } + + private class ConstraintGraphVirtualCall(val caller: Function, val virtualCall: DataFlowIR.Node.VirtualCall, + val arguments: List, val returnsNode: Node) + + private inner class ConstraintGraphBuilder(val functionNodesMap: MutableMap, + val functions: Map, + val typeHierarchy: TypeHierarchy, + val rootSet: List, + val useTypes: Boolean) { + + private val allTypes = typeHierarchy.allTypes + private val variables = mutableMapOf() + private val typesVirtualCallSites = Array(allTypes.size) { mutableListOf() } + private val suitableTypes = arrayOfNulls(allTypes.size) + private val concreteClasses = arrayOfNulls(allTypes.size) + private val virtualTypeFilter = BitSet().apply { set(VIRTUAL_TYPE_ID) } + val instantiatingClasses = BitSet() + + private val preliminaryNumberOfNodes = + allTypes.size + // A possible source node for each type. + functions.size * 2 + // and nodes for each function. + functions.values.sumBy { + it.body.allScopes.sumBy { it.nodes.size } // A node for each DataFlowIR.Node. + } + + functions.values + .sumBy { function -> + function.body.allScopes.sumBy { + it.nodes.count { node -> + // A cast if types are different. + node is DataFlowIR.Node.Call + && node.returnType.resolved() != node.callee.returnParameter.type.resolved() + } + } + } + + private fun isPrime(x: Int): Boolean { + if (x <= 3) return true + if (x % 2 == 0) return false + var r = 3 + while (r * r <= x) { + if (x % r == 0) return false + r += 2 + } + return true + } + + private fun makePrime(p: Int): Int { + var x = p + while (true) { + if (isPrime(x)) return x + ++x + } + } + + // A heuristic: the number of edges in the data flow graph + // for any reasonable program is linear in number of nodes. + val bagOfEdges = arrayOfNulls(makePrime(preliminaryNumberOfNodes * 5)) + val directEdgesCount = IntArrayList() + val reversedEdgesCount = IntArrayList() + + @OptIn(ExperimentalUnsignedTypes::class) + private fun addEdge(from: Node, to: Node) { + val fromId = from.id + val toId = to.id + val value = fromId.toLong() or (toId.toLong() shl 32) + // This is 64-bit extension of a hashing method from Knuth's "The Art of Computer Programming". + // The magic constant is the closest prime to 2^64 * phi, where phi is the golden ratio. + val bucketIdx = ((value.toULong() * 11400714819323198393UL) % bagOfEdges.size.toUInt()).toInt() + val bucket = bagOfEdges[bucketIdx] ?: LongArrayList().also { bagOfEdges[bucketIdx] = it } + for (x in bucket) + if (x == value) return + bucket.add(value) + + directEdgesCount.reserve(fromId + 1) + directEdgesCount[fromId]++ + reversedEdgesCount.reserve(toId + 1) + reversedEdgesCount[toId]++ + } + + private fun concreteType(type: DataFlowIR.Type.Declared): Int { + assert(!(type.isAbstract && type.isFinal)) { "Incorrect type: $type" } + return if (type.isAbstract) + VIRTUAL_TYPE_ID + else { + if (!instantiatingClasses[type.index]) + error("Type $type is not instantiated") + type.index + } + } + + private fun ordinaryNode(nameBuilder: () -> String) = + constraintGraph.addNode { Node.Ordinary(it, nameBuilder) } + + private fun sourceNode(typeId: Int, nameBuilder: () -> String) = + constraintGraph.addNode { Node.Source(it, typeId, nameBuilder) } + + private fun concreteClass(type: DataFlowIR.Type.Declared) = + concreteClasses[type.index] + ?: sourceNode(concreteType(type)) { "Class\$$type" }.also { concreteClasses[type.index] = it} + + private fun fieldNode(field: DataFlowIR.Field) = + constraintGraph.fields.getOrPut(field) { + val fieldNode = ordinaryNode { "Field\$$field" } + if (entryPoint == null) { + // TODO: This is conservative. + val fieldType = field.type.resolved() + // Some user of our library might place some value into the field. + if (fieldType.isFinal) + addEdge(concreteClass(fieldType), fieldNode) + else + addEdge(constraintGraph.virtualNode, fieldNode) + } + fieldNode + } + + private var stack = mutableListOf() + + fun build() { + // Rapid Type Analysis: find all instantiations and conservatively estimate call graph. + + // Add all final parameters of the roots. + for (root in rootSet) { + root.parameters + .map { it.type.resolved() } + .filter { it.isFinal } + .forEach { addInstantiatingClass(it) } + } + if (entryPoint == null) { + // For library assume all public non-abstract classes could be instantiated. + // Note: for constructors there is additional parameter () and for associated objects + // its type will be added to instantiating classes since all objects are final types. + symbolTable.classMap.values + .filterIsInstance() + .filter { !it.isAbstract } + .forEach { addInstantiatingClass(it) } + } else { + // String arguments are implicitly put into the array parameter of
. + addInstantiatingClass(symbolTable.mapType(context.irBuiltIns.stringType).resolved()) + addEdge(concreteClass(symbolTable.mapType(context.irBuiltIns.stringType).resolved()), + fieldNode(constraintGraph.arrayItemField)) + } + rootSet.forEach { createFunctionConstraintGraph(it, true) } + while (stack.isNotEmpty()) { + val symbol = stack.pop() + val function = functions[symbol] ?: continue + val body = function.body + val functionConstraintGraph = constraintGraph.functions[symbol]!! + + body.forEachNonScopeNode { dfgNodeToConstraintNode(functionConstraintGraph, it) } + addEdge(functionNodesMap[body.returns]!!, functionConstraintGraph.returns) + addEdge(functionNodesMap[body.throws]!!, functionConstraintGraph.throws) + + context.logMultiple { + +"CONSTRAINT GRAPH FOR $symbol" + val ids = function.body.allScopes.flatMap { it.nodes }.withIndex().associateBy({ it.value }, { it.index }) + function.body.forEachNonScopeNode { node -> + +"FT NODE #${ids[node]}" + +DataFlowIR.Function.nodeToString(node, ids) + val constraintNode = functionNodesMap[node] ?: variables[node] ?: return@forEachNonScopeNode + +" CG NODE #${constraintNode.id}: ${constraintNode.toString(allTypes)}" + } + +"Returns: #${ids[function.body.returns]}" + +"" + } + } + + suitableTypes.forEach { + it?.and(instantiatingClasses) + it?.set(VIRTUAL_TYPE_ID) + } + + if (entryPoint == null) { + for (list in typesVirtualCallSites) + for (virtualCall in list) { + val returnType = virtualCall.virtualCall.returnType.resolved() + val totalIncomingEdgesToReturnsNode = + if (virtualCall.returnsNode.id >= reversedEdgesCount.size) + 0 + else reversedEdgesCount[virtualCall.returnsNode.id] + if (returnType.isFinal && totalIncomingEdgesToReturnsNode == 0) { + // If we are in a library and facing final return type with no possible callees - + // this type still can be returned by some user of this library, so propagate it explicitly. + addEdge(concreteClass(returnType), virtualCall.returnsNode) + } + } + } + } + + private fun createFunctionConstraintGraph(symbol: DataFlowIR.FunctionSymbol, isRoot: Boolean): Function? { + if (symbol is DataFlowIR.FunctionSymbol.External) return null + constraintGraph.functions[symbol]?.let { return it } + + val parameters = Array(symbol.parameters.size) { ordinaryNode { "Param#$it\$$symbol" } } + if (isRoot) { + // Exported function from the current module. + symbol.parameters.forEachIndexed { index, type -> + val resolvedType = type.type.resolved() + val node = if (!resolvedType.isFinal) + constraintGraph.virtualNode // TODO: OBJC-INTEROP-GENERATED-CLASSES + else + concreteClass(resolvedType) + addEdge(node, parameters[index]) + } + } + + val returnsNode = ordinaryNode { "Returns\$$symbol" } + val throwsNode = ordinaryNode { "Throws\$$symbol" } + val functionConstraintGraph = Function(symbol, parameters, returnsNode, throwsNode) + constraintGraph.functions[symbol] = functionConstraintGraph + + stack.push(symbol) + + return functionConstraintGraph + } + + private fun addInstantiatingClass(type: DataFlowIR.Type.Declared) { + if (instantiatingClasses[type.index]) return + instantiatingClasses.set(type.index) + context.log { "Adding instantiating class: $type" } + checkSupertypes(type, type, BitSet()) + } + + private fun processVirtualCall(virtualCall: ConstraintGraphVirtualCall, + receiverType: DataFlowIR.Type.Declared) { + context.logMultiple { + +"Processing virtual call: ${virtualCall.virtualCall.callee}" + +"Receiver type: $receiverType" + } + val callee = receiverType.calleeAt(virtualCall.virtualCall) + addEdge(doCall(virtualCall.caller, callee, virtualCall.arguments, + callee.returnParameter.type.resolved()), virtualCall.returnsNode) + } + + private fun checkSupertypes(type: DataFlowIR.Type.Declared, + inheritor: DataFlowIR.Type.Declared, + seenTypes: BitSet) { + seenTypes.set(type.index) + + context.logMultiple { + +"Checking supertype $type of $inheritor" + typesVirtualCallSites[type.index].let { + if (it.isEmpty()) + +"None virtual call sites encountered yet" + else { + +"Virtual call sites:" + it.forEach { +" ${it.virtualCall.callee}" } + } + } + +"" + } + + typesVirtualCallSites[type.index].let { virtualCallSites -> + var index = 0 + while (index < virtualCallSites.size) { + processVirtualCall(virtualCallSites[index], inheritor) + ++index + } + } + for (superType in type.superTypes) { + val resolvedSuperType = superType.resolved() + if (!seenTypes[resolvedSuperType.index]) + checkSupertypes(resolvedSuperType, inheritor, seenTypes) + } + } + + private fun createCastEdge(node: Node, type: DataFlowIR.Type.Declared): Node.CastEdge { + if (suitableTypes[type.index] == null) + suitableTypes[type.index] = typeHierarchy.inheritorsOf(type).copy() + return Node.CastEdge(node, suitableTypes[type.index]!!) + } + + private fun doCast(function: Function, node: Node, type: DataFlowIR.Type.Declared): Node { + val castNode = ordinaryNode { "Cast\$${function.symbol}" } + val castEdge = createCastEdge(castNode, type) + node.addCastEdge(castEdge) + return castNode + } + + private fun castIfNeeded(function: Function, node: Node, + nodeType: DataFlowIR.Type.Declared, type: DataFlowIR.Type.Declared) = + if (!useTypes || type == nodeType) + node + else doCast(function, node, type) + + private fun edgeToConstraintNode(function: Function, + edge: DataFlowIR.Edge): Node { + val result = dfgNodeToConstraintNode(function, edge.node) + val castToType = edge.castToType?.resolved() ?: return result + return doCast(function, result, castToType) + } + + fun doCall(caller: Function, callee: Function, arguments: List, returnType: DataFlowIR.Type.Declared): Node { + assert(callee.parameters.size == arguments.size) { + "Function ${callee.symbol} takes ${callee.parameters.size} but caller ${caller.symbol}" + + " provided ${arguments.size}" + } + callee.parameters.forEachIndexed { index, parameter -> + addEdge(arguments[index], parameter) + } + return castIfNeeded(caller, callee.returns, callee.symbol.returnParameter.type.resolved(), returnType) + } + + fun doCall(caller: Function, callee: DataFlowIR.FunctionSymbol, + arguments: List, returnType: DataFlowIR.Type.Declared): Node { + val resolvedCallee = callee.resolved() + val calleeConstraintGraph = createFunctionConstraintGraph(resolvedCallee, false) + return if (calleeConstraintGraph == null) { + constraintGraph.externalFunctions.getOrPut(resolvedCallee to returnType) { + val fictitiousReturnNode = ordinaryNode { "External$resolvedCallee" } + if (returnType.isFinal) { + addInstantiatingClass(returnType) + addEdge(concreteClass(returnType), fictitiousReturnNode) + } else { + addEdge(constraintGraph.virtualNode, fictitiousReturnNode) + // TODO: Unconservative way - when we can use it? + // TODO: OBJC-INTEROP-GENERATED-CLASSES +// typeHierarchy.inheritorsOf(returnType) +// .filterNot { it.isAbstract } +// .filter { instantiatingClasses.containsKey(it) } +// .forEach { concreteClass(it).addEdge(fictitiousReturnNode) } + } + fictitiousReturnNode + } + } else { + addEdge(calleeConstraintGraph.throws, caller.throws) + doCall(caller, calleeConstraintGraph, arguments, returnType) + } + } + + /** + * Takes a function DFG's node and creates a constraint graph node corresponding to it. + * Also creates all necessary edges. + */ + private fun dfgNodeToConstraintNode(function: Function, node: DataFlowIR.Node): Node { + + fun edgeToConstraintNode(edge: DataFlowIR.Edge): Node = + edgeToConstraintNode(function, edge) + + fun doCall(callee: DataFlowIR.FunctionSymbol, arguments: List, + returnType: DataFlowIR.Type.Declared) = + doCall(function, callee, arguments, returnType) + + fun readField(field: DataFlowIR.Field, actualType: DataFlowIR.Type.Declared): Node { + val fieldNode = fieldNode(field) + val expectedType = field.type.resolved() + return if (!useTypes || actualType == expectedType) + fieldNode + else + doCast(function, fieldNode, actualType) + } + + fun writeField(field: DataFlowIR.Field, actualType: DataFlowIR.Type.Declared, value: Node) { + val fieldNode = fieldNode(field) + val expectedType = field.type.resolved() + val castedValue = if (!useTypes || actualType == expectedType) + value + else + doCast(function, value, actualType) + addEdge(castedValue, fieldNode) + } + + if (node is DataFlowIR.Node.Variable && node.kind != DataFlowIR.VariableKind.Temporary) { + var variableNode = variables[node] + if (variableNode == null) { + variableNode = ordinaryNode { "Variable\$${function.symbol}" } + variables[node] = variableNode + for (value in node.values) { + addEdge(edgeToConstraintNode(value), variableNode) + } + if (node.kind == DataFlowIR.VariableKind.CatchParameter) + function.throws.addCastEdge(createCastEdge(variableNode, node.type.resolved())) + } + return variableNode + } + + return functionNodesMap.getOrPut(node) { + when (node) { + is DataFlowIR.Node.Const -> { + val type = node.type.resolved() + addInstantiatingClass(type) + sourceNode(concreteType(type)) { "Const\$${function.symbol}" } + } + + DataFlowIR.Node.Null -> constraintGraph.voidNode + + is DataFlowIR.Node.Parameter -> + function.parameters[node.index] + + is DataFlowIR.Node.StaticCall -> { + val arguments = node.arguments.map(::edgeToConstraintNode) + doCall(node.callee, arguments, node.returnType.resolved()) + } + + is DataFlowIR.Node.NewObject -> { + val returnType = node.constructedType.resolved() + addInstantiatingClass(returnType) + val instanceNode = concreteClass(returnType) + val arguments = listOf(instanceNode) + node.arguments.map(::edgeToConstraintNode) + doCall(node.callee, arguments, returnType) + instanceNode + } + + is DataFlowIR.Node.VirtualCall -> { + val callee = node.callee + val receiverType = node.receiverType.resolved() + + context.logMultiple { + +"Virtual call" + +"Caller: ${function.symbol}" + +"Callee: $callee" + +"Receiver type: $receiverType" + + +"Possible callees:" + forEachBitInBoth(typeHierarchy.inheritorsOf(receiverType), instantiatingClasses) { + +allTypes[it].calleeAt(node).toString() + } + +"" + } + + val returnType = node.returnType.resolved() + val arguments = node.arguments.map(::edgeToConstraintNode) + val receiverNode = arguments[0] + if (receiverType == DataFlowIR.Type.Virtual) + addEdge(constraintGraph.virtualNode, receiverNode) + + if (entryPoint == null && returnType.isFinal) { + // If we are in a library and facing final return type then + // this type can be returned by some user of this library, so propagate it explicitly. + addInstantiatingClass(returnType) + } + + val returnsNode = ordinaryNode { "VirtualCallReturns\$${function.symbol}" } + if (receiverType != DataFlowIR.Type.Virtual) + typesVirtualCallSites[receiverType.index].add( + ConstraintGraphVirtualCall(function, node, arguments, returnsNode)) + forEachBitInBoth(typeHierarchy.inheritorsOf(receiverType), instantiatingClasses) { + val actualCallee = allTypes[it].calleeAt(node) + addEdge(doCall(actualCallee, arguments, actualCallee.returnParameter.type.resolved()), returnsNode) + } + // Add cast to [Virtual] edge from receiver to returns, if return type is not final. + // With this we're reflecting the fact that unknown function can return anything. + if (!returnType.isFinal && entryPoint == null) { + receiverNode.addCastEdge(Node.CastEdge(returnsNode, virtualTypeFilter)) + } + // And throw anything. + receiverNode.addCastEdge(Node.CastEdge(function.throws, virtualTypeFilter)) + + constraintGraph.virtualCallSiteReceivers[node] = receiverNode + castIfNeeded(function, returnsNode, node.callee.returnParameter.type.resolved(), returnType) + } + + is DataFlowIR.Node.Singleton -> { + val type = node.type.resolved() + addInstantiatingClass(type) + val instanceNode = concreteClass(type) + node.constructor?.let { doCall(it, listOf(instanceNode), type) } + instanceNode + } + + is DataFlowIR.Node.AllocInstance -> { + val type = node.type.resolved() + addInstantiatingClass(type) + concreteClass(type) + } + + is DataFlowIR.Node.FunctionReference -> { + concreteClass(node.type.resolved()) + } + + is DataFlowIR.Node.FieldRead -> { + val type = node.field.type.resolved() + if (entryPoint == null && type.isFinal) + addInstantiatingClass(type) + readField(node.field, type) + } + + is DataFlowIR.Node.FieldWrite -> { + val type = node.field.type.resolved() + if (entryPoint == null && type.isFinal) + addInstantiatingClass(type) + writeField(node.field, type, edgeToConstraintNode(node.value)) + constraintGraph.voidNode + } + + is DataFlowIR.Node.ArrayRead -> + readField(constraintGraph.arrayItemField, node.type.resolved()) + + is DataFlowIR.Node.ArrayWrite -> { + writeField(constraintGraph.arrayItemField, node.type.resolved(), edgeToConstraintNode(node.value)) + constraintGraph.voidNode + } + + is DataFlowIR.Node.Variable -> + node.values.map { edgeToConstraintNode(it) }.let { values -> + ordinaryNode { "TempVar\$${function.symbol}" }.also { node -> + values.forEach { addEdge(it, node) } + } + } + + else -> error("Unreachable") + } + } + } + } + + } + + class DevirtualizedCallee(val receiverType: DataFlowIR.Type, val callee: DataFlowIR.FunctionSymbol) + + class DevirtualizedCallSite(val callee: DataFlowIR.FunctionSymbol, val possibleCallees: List) + + class AnalysisResult(val devirtualizedCallSites: Map, + val typeHierarchy: DevirtualizationAnalysis.TypeHierarchy) + + fun run(irModule: IrModuleFragment, context: Context, moduleDFG: ModuleDFG, externalModulesDFG: ExternalModulesDFG) + : AnalysisResult { + val devirtualizationAnalysisResult = DevirtualizationAnalysis(context, moduleDFG, externalModulesDFG).analyze() + val devirtualizedCallSites = + devirtualizationAnalysisResult.devirtualizedCallSites + .asSequence() + .filter { it.key.irCallSite != null } + .associate { it.key.irCallSite!! to it.value } + devirtualize(irModule, context, externalModulesDFG, devirtualizedCallSites) + return devirtualizationAnalysisResult + } + + private fun devirtualize(irModule: IrModuleFragment, context: Context, externalModulesDFG: ExternalModulesDFG, + devirtualizedCallSites: Map) { + val symbols = context.ir.symbols + val nativePtrEqualityOperatorSymbol = symbols.areEqualByValue[PrimitiveBinaryType.POINTER]!! + val optimize = context.shouldOptimize() + + fun DataFlowIR.Type.resolved(): DataFlowIR.Type.Declared { + if (this is DataFlowIR.Type.Declared) return this + val hash = (this as DataFlowIR.Type.External).hash + return externalModulesDFG.publicTypes[hash] ?: error("Unable to resolve exported type $hash") + } + + fun DataFlowIR.FunctionSymbol.resolved(): DataFlowIR.FunctionSymbol { + if (this is DataFlowIR.FunctionSymbol.External) + return externalModulesDFG.publicFunctions[this.hash] ?: this + return this + } + + fun IrBuilderWithScope.irCoerce(value: IrExpression, coercion: IrFunctionSymbol?) = + if (coercion == null) + value + else irCall(coercion).apply { + addArguments(listOf(coercion.descriptor.explicitParameters.single() to value)) + } + + fun IrBuilderWithScope.irCoerce(value: IrExpression, coercion: DataFlowIR.FunctionSymbol.Declared?) = + if (coercion == null) + value + else irCall(coercion.irFunction!!).apply { + putValueArgument(0, value) + } + + class PossiblyCoercedValue(val value: IrVariable, val coercion: IrFunctionSymbol?) { + fun getFullValue(irBuilder: IrBuilderWithScope) = irBuilder.run { + irCoerce(irGet(value), coercion) + } + } + + fun IrStatementsBuilder.irTemporary(value: IrExpression, tempName: String, type: IrType): IrVariable { + val descriptor = WrappedVariableDescriptor() + + val temporary = IrVariableImpl( + value.startOffset, value.endOffset, IrDeclarationOrigin.IR_TEMPORARY_VARIABLE, IrVariableSymbolImpl(descriptor), + Name.identifier(tempName), type, isVar = false, isConst = false, isLateinit = false + ).apply { + descriptor.bind(this) + this.initializer = value + } + + +temporary + return temporary + } + + fun IrStatementsBuilder.irSplitCoercion(expression: IrExpression, tempName: String, actualType: IrType) = + if (!expression.isBoxOrUnboxCall()) + PossiblyCoercedValue(irTemporary(expression, tempName, actualType), null) + else { + val coercion = expression as IrCall + PossiblyCoercedValue( + irTemporary(coercion.getValueArgument(0)!!, tempName, + coercion.symbol.owner.explicitParameters.single().type) + , coercion.symbol) + } + + fun getTypeConversion(actualType: DataFlowIR.FunctionParameter, + targetType: DataFlowIR.FunctionParameter): DataFlowIR.FunctionSymbol.Declared? { + if (actualType.boxFunction == null && targetType.boxFunction == null) return null + if (actualType.boxFunction != null && targetType.boxFunction != null) { + assert (actualType.type.resolved() == targetType.type.resolved()) + { "Inconsistent types: ${actualType.type} and ${targetType.type}" } + return null + } + if (actualType.boxFunction == null) + return targetType.unboxFunction!!.resolved() as DataFlowIR.FunctionSymbol.Declared + return actualType.boxFunction.resolved() as DataFlowIR.FunctionSymbol.Declared + } + + fun IrCallImpl.putArgument(index: Int, value: IrExpression) { + var receiversCount = 0 + val callee = symbol.owner + if (callee.dispatchReceiverParameter != null) + ++receiversCount + if (callee.extensionReceiverParameter != null) + ++receiversCount + if (index >= receiversCount) + putValueArgument(index - receiversCount, value) + else { + if (callee.dispatchReceiverParameter != null && index == 0) + dispatchReceiver = value + else + extensionReceiver = value + } + } + + fun IrBuilderWithScope.irDevirtualizedCall(callSite: IrCall, + actualType: IrType, + devirtualizedCallee: DevirtualizedCallee, + arguments: List): IrCall { + val actualCallee = devirtualizedCallee.callee.irFunction as IrSimpleFunction + val call = IrCallImpl( + callSite.startOffset, callSite.endOffset, + actualType, + actualCallee.symbol, + actualCallee.typeParameters.size, + actualCallee.valueParameters.size, + callSite.origin, + actualCallee.parentAsClass.symbol + ) + if (actualCallee.explicitParametersCount == arguments.size) { + arguments.forEachIndexed { index, argument -> call.putArgument(index, argument) } + return call + } + assert(actualCallee.isSuspend && actualCallee.explicitParametersCount == arguments.size - 1) { + "Incorrect number of arguments: expected [${actualCallee.explicitParametersCount}] but was [${arguments.size - 1}]\n" + + actualCallee.dump() + } + val continuation = arguments.last() + for (index in 0..arguments.size - 2) + call.putArgument(index, arguments[index]) + return irCall(context.ir.symbols.coroutineLaunchpad, actualType).apply { + putValueArgument(0, call) + putValueArgument(1, continuation) + } + } + + fun IrBuilderWithScope.irDevirtualizedCall(callee: IrCall, actualType: IrType, + devirtualizedCallee: DevirtualizedCallee, + arguments: List): IrExpression { + val actualCallee = devirtualizedCallee.callee as DataFlowIR.FunctionSymbol.Declared + return actualCallee.bridgeTarget.let { bridgeTarget -> + if (bridgeTarget == null) + irDevirtualizedCall(callee, actualType, + devirtualizedCallee, + arguments.map { it.getFullValue(this@irDevirtualizedCall) }) + else { + val callResult = irDevirtualizedCall(callee, actualType, + DevirtualizedCallee(devirtualizedCallee.receiverType, bridgeTarget), + arguments.mapIndexed { index, value -> + val coercion = getTypeConversion(actualCallee.parameters[index], bridgeTarget.parameters[index]) + val fullValue = value.getFullValue(this@irDevirtualizedCall) + coercion?.let { irCoerce(fullValue, coercion) } ?: fullValue + }) + val returnCoercion = getTypeConversion(bridgeTarget.returnParameter, actualCallee.returnParameter) + irCoerce(callResult, returnCoercion) + } + } + } + + irModule.transformChildrenVoid(object: IrElementTransformerVoidWithContext() { + override fun visitCall(expression: IrCall): IrExpression { + expression.transformChildrenVoid(this) + + val devirtualizedCallSite = devirtualizedCallSites[expression] + val possibleCallees = devirtualizedCallSite?.possibleCallees + if (possibleCallees == null + || possibleCallees.any { it.callee is DataFlowIR.FunctionSymbol.External } + || possibleCallees.any { it.receiverType is DataFlowIR.Type.External }) + return expression + + val callee = expression.symbol.owner + val owner = callee.parentAsClass + // TODO: Think how to evaluate different unfold factors (in terms of both execution speed and code size). + val classMaxUnfoldFactor = 3 + val interfaceMaxUnfoldFactor = 3 + val maxUnfoldFactor = if (owner.isInterface) interfaceMaxUnfoldFactor else classMaxUnfoldFactor + if (possibleCallees.size > maxUnfoldFactor) { + // Callsite too complicated to devirtualize. + return expression + } + + val startOffset = expression.startOffset + val endOffset = expression.endOffset + val function = expression.symbol.owner + val type = if (callee.isSuspend) + context.irBuiltIns.anyNType + else function.returnType + val irBuilder = context.createIrBuilder(currentScope!!.scope.scopeOwnerSymbol, startOffset, endOffset) + irBuilder.run { + val dispatchReceiver = expression.dispatchReceiver!! + return when { + possibleCallees.isEmpty() -> irBlock(expression) { + val throwExpr = irCall(symbols.throwInvalidReceiverTypeException.owner).apply { + putValueArgument(0, + irCall(symbols.kClassImplConstructor.owner, listOf(dispatchReceiver.type)).apply { + putValueArgument(0, + irCall(symbols.getObjectTypeInfo.owner).apply { + putValueArgument(0, dispatchReceiver) + }) + }) + } + // Insert proper unboxing (unreachable code): + +irCoerce(throwExpr, symbols.getTypeConversion(throwExpr.type, type)) + } + + optimize && possibleCallees.size == 1 -> { // Monomorphic callsite. + irBlock(expression) { + val parameters = expression.getArgumentsWithSymbols().mapIndexed { index, arg -> + irSplitCoercion(arg.second, "arg$index", arg.first.owner.type) + } + +irDevirtualizedCall(expression, type, possibleCallees[0], parameters) + } + } + + else -> irBlock(expression) { + val arguments = expression.getArgumentsWithSymbols().mapIndexed { index, arg -> + irSplitCoercion(arg.second, "arg$index", arg.first.owner.type) + } + val typeInfo = irTemporary(irCall(symbols.getObjectTypeInfo).apply { + putValueArgument(0, arguments[0].getFullValue(this@irBlock)) + }) + + val branches = mutableListOf() + possibleCallees.mapIndexedTo(branches) { index, devirtualizedCallee -> + val actualReceiverType = devirtualizedCallee.receiverType as DataFlowIR.Type.Declared + val expectedTypeInfo = IrClassReferenceImpl( + startOffset, endOffset, + symbols.nativePtrType, + actualReceiverType.irClass!!.symbol, + actualReceiverType.irClass.defaultType + ) + val condition = + if (optimize && index == possibleCallees.size - 1) + irTrue() // Don't check last type in optimize mode. + else + irCall(nativePtrEqualityOperatorSymbol).apply { + putValueArgument(0, irGet(typeInfo)) + putValueArgument(1, expectedTypeInfo) + } + IrBranchImpl( + startOffset = startOffset, + endOffset = endOffset, + condition = condition, + result = irDevirtualizedCall(expression, type, devirtualizedCallee, arguments) + ) + } + if (!optimize) { // Add else branch throwing exception for debug purposes. + branches.add(IrBranchImpl( + startOffset = startOffset, + endOffset = endOffset, + condition = irTrue(), + result = irCall(symbols.throwInvalidReceiverTypeException).apply { + putValueArgument(0, + irCall(symbols.kClassImplConstructor, + listOf(dispatchReceiver.type) + ).apply { + putValueArgument(0, irGet(typeInfo)) + } + ) + }) + ) + } + + +IrWhenImpl( + startOffset = startOffset, + endOffset = endOffset, + type = type, + origin = expression.origin, + branches = branches + ) + } + } + } + } + }) + } +} diff --git a/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/optimizations/EscapeAnalysis.kt b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/optimizations/EscapeAnalysis.kt new file mode 100644 index 00000000000..291f690b7db --- /dev/null +++ b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/optimizations/EscapeAnalysis.kt @@ -0,0 +1,1694 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +package org.jetbrains.kotlin.backend.konan.optimizations + +import org.jetbrains.kotlin.backend.common.atMostOne +import org.jetbrains.kotlin.backend.common.pop +import org.jetbrains.kotlin.backend.common.push +import org.jetbrains.kotlin.backend.konan.* +import org.jetbrains.kotlin.backend.konan.Context +import org.jetbrains.kotlin.backend.konan.DirectedGraphCondensationBuilder +import org.jetbrains.kotlin.backend.konan.DirectedGraphMultiNode +import org.jetbrains.kotlin.backend.konan.llvm.Lifetime +import org.jetbrains.kotlin.backend.konan.logMultiple +import org.jetbrains.kotlin.ir.IrElement +import org.jetbrains.kotlin.ir.declarations.IrClass +import kotlin.math.min + +private val DataFlowIR.Node.isAlloc + get() = this is DataFlowIR.Node.NewObject || this is DataFlowIR.Node.AllocInstance + +private val DataFlowIR.Node.ir + get() = when (this) { + is DataFlowIR.Node.Call -> irCallSite + is DataFlowIR.Node.AllocInstance -> irCallSite + is DataFlowIR.Node.ArrayRead -> irCallSite + is DataFlowIR.Node.FieldRead -> ir + else -> null + } + +internal object EscapeAnalysis { + + /* + * The goal of escape analysis is to estimate lifetimes of all expressions in a program. + * Possible lifetimes are: + * 0. Stack - an object is used only within its visibility scope within a function. + * 1. Local - an object is used only within a function. + * 2. Return value - an object is either returned or set to a field of an object being returned. + * 3. Parameter - an object is set to a field of some parameters of a function. + * 4. Global - otherwise. + * For now only Stack and Global lifetimes are supported by the codegen, so others will be pulled up to Global. + * + * The analysis is performed in two main stages - intraprocedural and interprocedural. + * During intraprocedural analysis we remove all control flow related expressions and compute all possible + * values of all variables within a function. + * The goal of interprocedural analysis is to build points-to graph (object A references object B if and only if + * there is a path from the node A to the node B). This is done by building call graph (using devirtualization + * for more precise result). But in practice holding this condition both ways can be difficult and bad in terms of + * performance, so the algorithm tries to ensure only one part: if object A references object B then there must be + * a path from the node A to the node B, with that none of the constraints from the original program will be lost. + * It is ok to add some additional constraints, as long as there are not too many of those. + * + * How do we exactly build the points-to graph out of the call graph? + * 1. Build condensation of the call graph. + * 2. Handle vertices of the resulting DAG in the reversed topological order (ensuring that all functions being called + * are already handled). + * 3. For a strongly connected component build the points-to graph iteratively starting with empty graph + * (if the process is seemed to not be converging for some function, assume the pessimistic result). + * + * Escape analysis result of a function is not only lifetimes for all allocations of that function + * but also a snippet of its points-to graph (it's a reduced version, basically, subgraph reachable from + * the function's parameters). + * Assuming the function has parameters P0, P1, .., Pn, where the last parameter is the return parameter, + * it turns out that the snippet can be described as an array of relations of form + * v.f0.f1...fk -> w.g0.g1...gl where v, w - either one of the function's parameters or special + * additional nodes called drains which will be introduced later; and f0, f1, .., fk, g0, g1, .., gl - fields. + * + * Building points-to graph: + * 1. Seed it from the function's DataFlowIR. + * There are two kinds of edges: + * 1) field. The subgraph for [a.f]: + * [a] + * | f + * V + * [a.f] + * Notice the label [f] on the edge. + * 2) assignment. The subgraph for [a = b]: + * [a] + * | + * V + * [b] + * No labels on the edge. + * When calling a function, take its points-to graph snippet and embed it at the call site, + * replacing parameters with actual node arguments. + * 2. Build the closure. + * Consider an assignment [a = b], and a usage of [a.f] somewhere. Since there is no order on nodes + * of DataFlowIR (sea of nodes), the conservative assumption has to be made - [b.f] is also being used + * at the same place as [a.f] is. Same applies for usages of [b.f]. + * This reasoning leads to the following algorithm: + * Consider for the time being all assignment edges undirected and build connected components. + * Now, every field usage of any node within a component implies the same usage of any other node + * from that component, so the following transformation will be performed: + * 1) Consider components one by one. Select a node which has no outgoing assignment edges, + * if there is no such a node, create additional node and add assignment edges from every node + * to it. Call this node a drain. Then move all beginnings of field edges from all nodes to + * the drain leaving the ends as is (this reflects the above consideration - any field usage + * can be applied to any node within a component). + * 2) After drains creation and field edges moving there might emerge multi-edges (more than one + * field edge with the same label going to different components). The components these + * multi-edges are pointing at must be coalesced together (this is done either by creating + * a new drain or connecting one component's drain to the other). This operation must be + * performed until there are no more multi-edges. + * After the above transformation has been made, finally, simple lifetime propagation can be performed, + * seeing all edges directed. + */ + + // A special marker field for external types implemented in the runtime (mainly, arrays). + // The types being passed to the constructor are not used in the analysis - just put there anything. + private val intestinesField = DataFlowIR.Field(null, DataFlowIR.Type.Virtual, 1L, "inte\$tines") + + // A special marker field for return values. + // Basically we substitute [return x] with [ret.v@lue = x]. + // This is done in order to not handle return parameter somewhat specially. + private val returnsValueField = DataFlowIR.Field(null, DataFlowIR.Type.Virtual, 2L, "v@lue") + + // Roles in which particular object reference is being used. + private enum class Role { + RETURN_VALUE, + THROW_VALUE, + WRITE_FIELD, + READ_FIELD, + WRITTEN_TO_GLOBAL, + ASSIGNED, + } + + // The less the higher an object escapes. + object Depths { + val INFINITY = 1_000_000 + val ROOT_SCOPE = 0 + val RETURN_VALUE = -1 + val PARAMETER = -2 + } + + private class RoleInfoEntry(val node: DataFlowIR.Node? = null, val field: DataFlowIR.Field?) + + private open class RoleInfo { + val entries = mutableListOf() + + open fun add(entry: RoleInfoEntry) = entries.add(entry) + } + + private class NodeInfo(val depth: Int = Depths.INFINITY) { + val data = HashMap() + + fun add(role: Role, info: RoleInfoEntry?) { + val entry = data.getOrPut(role, { RoleInfo() }) + if (info != null) entry.add(info) + } + + fun has(role: Role): Boolean = data[role] != null + + fun escapes() = has(Role.WRITTEN_TO_GLOBAL) || has(Role.THROW_VALUE) + + override fun toString() = + data.keys.joinToString(separator = "; ", prefix = "Roles: ") { it.toString() } + } + + private class FunctionAnalysisResult(val function: DataFlowIR.Function, + val nodesRoles: Map) + + private class IntraproceduralAnalysis(val context: Context, + val moduleDFG: ModuleDFG, val externalModulesDFG: ExternalModulesDFG, + val callGraph: CallGraph) { + + val functions = moduleDFG.functions + + private fun DataFlowIR.Type.resolved(): DataFlowIR.Type.Declared { + if (this is DataFlowIR.Type.Declared) return this + val hash = (this as DataFlowIR.Type.External).hash + return externalModulesDFG.publicTypes[hash] ?: error("Unable to resolve exported type $hash") + } + + fun analyze(): Map { + val nothing = moduleDFG.symbolTable.mapClassReferenceType(context.ir.symbols.nothing.owner).resolved() + return callGraph.nodes.filter { functions[it.symbol] != null }.associateBy({ it.symbol }) { callGraphNode -> + val function = functions[callGraphNode.symbol]!! + val body = function.body + val nodesRoles = mutableMapOf() + + fun computeDepths(node: DataFlowIR.Node, depth: Int) { + if (node is DataFlowIR.Node.Scope) + node.nodes.forEach { computeDepths(it, depth + 1) } + else + nodesRoles[node] = NodeInfo(depth) + } + computeDepths(body.rootScope, Depths.ROOT_SCOPE - 1) + + fun assignRole(node: DataFlowIR.Node, role: Role, infoEntry: RoleInfoEntry?) { + nodesRoles[node]!!.add(role, infoEntry) + } + + body.returns.values.forEach { assignRole(it.node, Role.RETURN_VALUE, null) } + body.throws.values.forEach { assignRole(it.node, Role.THROW_VALUE, null) } + + body.forEachNonScopeNode { node -> + when (node) { + is DataFlowIR.Node.FieldWrite -> { + val receiver = node.receiver + if (receiver == null) + assignRole(node.value.node, Role.WRITTEN_TO_GLOBAL, null) + else + assignRole(receiver.node, Role.WRITE_FIELD, RoleInfoEntry(node.value.node, node.field)) + } + + is DataFlowIR.Node.Singleton -> { + val type = node.type.resolved() + if (type != nothing) + assignRole(node, Role.WRITTEN_TO_GLOBAL, null) + } + + is DataFlowIR.Node.FieldRead -> { + val receiver = node.receiver + if (receiver == null) + assignRole(node, Role.WRITTEN_TO_GLOBAL, null) + else + assignRole(receiver.node, Role.READ_FIELD, RoleInfoEntry(node, node.field)) + } + + is DataFlowIR.Node.ArrayWrite -> { + assignRole(node.array.node, Role.WRITE_FIELD, RoleInfoEntry(node.value.node, intestinesField)) + } + + is DataFlowIR.Node.ArrayRead -> { + assignRole(node.array.node, Role.READ_FIELD, RoleInfoEntry(node, intestinesField)) + } + + is DataFlowIR.Node.Variable -> { + for (value in node.values) + assignRole(node, Role.ASSIGNED, RoleInfoEntry(value.node, null)) + } + } + } + FunctionAnalysisResult(function, nodesRoles) + } + } + } + + private inline fun > Array.sortedAndDistinct(): Array { + this.sort() + if (this.isEmpty()) return this + val unique = mutableListOf(this[0]) + for (i in 1 until this.size) + if (this[i] != this[i - 1]) + unique.add(this[i]) + return unique.toTypedArray() + } + + private class CompressedPointsToGraph(edges: Array) { + val edges = edges.sortedAndDistinct() + + sealed class NodeKind { + abstract val absoluteIndex: Int + + object Return : NodeKind() { + override val absoluteIndex = 0 + + override fun equals(other: Any?) = other === this + + override fun toString() = "RET" + } + + class Param(val index: Int) : NodeKind() { + override val absoluteIndex: Int + get() = -1_000_000 + index + + override fun equals(other: Any?) = index == (other as? Param)?.index + + override fun toString() = "P$index" + } + + class Drain(val index: Int) : NodeKind() { + override val absoluteIndex: Int + get() = index + 1 + + override fun equals(other: Any?) = index == (other as? Drain)?.index + + override fun toString() = "D$index" + } + + companion object { + fun parameter(index: Int, total: Int) = + if (index == total - 1) + Return + else + Param(index) + } + } + + class Node(val kind: NodeKind, val path: Array) : Comparable { + override fun compareTo(other: Node): Int { + if (kind.absoluteIndex != other.kind.absoluteIndex) + return kind.absoluteIndex.compareTo(other.kind.absoluteIndex) + for (i in path.indices) { + if (i >= other.path.size) + return 1 + if (path[i].hash != other.path[i].hash) + return path[i].hash.compareTo(other.path[i].hash) + } + if (path.size < other.path.size) return -1 + return 0 + } + + override fun equals(other: Any?): Boolean { + if (this === other) return true + if (other !is Node) return false + if (kind != other.kind || path.size != other.path.size) + return false + for (i in path.indices) + if (path[i] != other.path[i]) + return false + return true + } + + override fun toString() = debugString(null) + + fun debugString(root: String?) = buildString { + append(root ?: kind.toString()) + path.forEach { + append('.') + append(it.name ?: "") + } + } + + fun goto(field: DataFlowIR.Field?) = when (field) { + null -> this + else -> Node(kind, Array(path.size + 1) { if (it < path.size) path[it] else field }) + } + + companion object { + fun parameter(index: Int, total: Int) = Node(NodeKind.parameter(index, total), path = emptyArray()) + fun drain(index: Int) = Node(NodeKind.Drain(index), path = emptyArray()) + } + } + + class Edge(val from: Node, val to: Node) : Comparable { + override fun compareTo(other: Edge): Int { + val fromCompareResult = from.compareTo(other.from) + if (fromCompareResult != 0) + return fromCompareResult + return to.compareTo(other.to) + } + + override fun equals(other: Any?): Boolean { + if (other === this) return true + if (other !is Edge) return false + return from == other.from && to == other.to + } + + override fun toString() = "$from -> $to" + + companion object { + fun pointsTo(param1: Int, param2: Int, totalParams: Int, kind: Int): Edge { + /* + * Values extracted from @PointsTo annotation. + * kind edge + * 1 p1 -> p2 + * 2 p1 -> p2.intestines + * 3 p1.intestines -> p2 + * 4 p1.intestines -> p2.intestines + */ + if (kind <= 0 || kind > 4) + error("Invalid pointsTo kind: $kind") + val from = if (kind < 3) + Node.parameter(param1, totalParams) + else + Node(NodeKind.parameter(param1, totalParams), Array(1) { intestinesField }) + val to = if (kind % 2 == 1) + Node.parameter(param2, totalParams) + else + Node(NodeKind.parameter(param2, totalParams), Array(1) { intestinesField }) + return Edge(from, to) + } + } + } + } + + private class FunctionEscapeAnalysisResult( + val numberOfDrains: Int, + val pointsTo: CompressedPointsToGraph, + escapes: Array + ) { + val escapes = escapes.sortedAndDistinct() + + override fun equals(other: Any?): Boolean { + if (this === other) return true + if (other !is FunctionEscapeAnalysisResult) return false + + if (escapes.size != other.escapes.size) return false + for (i in escapes.indices) + if (escapes[i] != other.escapes[i]) return false + + if (pointsTo.edges.size != other.pointsTo.edges.size) + return false + for (i in pointsTo.edges.indices) + if (pointsTo.edges[i] != other.pointsTo.edges[i]) + return false + return true + } + + override fun toString(): String { + val result = StringBuilder() + result.appendLine("PointsTo:") + pointsTo.edges.forEach { result.appendLine(" $it") } + result.append("Escapes:") + escapes.forEach { + result.append(' ') + result.append(it) + } + return result.toString() + } + + companion object { + fun fromBits(escapesMask: Int, pointsToMasks: List): FunctionEscapeAnalysisResult { + val paramCount = pointsToMasks.size + val edges = mutableListOf() + val escapes = mutableListOf() + for (param1 in pointsToMasks.indices) { + if (escapesMask and (1 shl param1) != 0) + escapes.add(CompressedPointsToGraph.Node.parameter(param1, paramCount)) + val curPointsToMask = pointsToMasks[param1] + for (param2 in pointsToMasks.indices) { + // Read a nibble at position [param2]. + val pointsTo = (curPointsToMask shr (4 * param2)) and 15 + if (pointsTo != 0) + edges.add(CompressedPointsToGraph.Edge.pointsTo(param1, param2, paramCount, pointsTo)) + } + } + return FunctionEscapeAnalysisResult( + 0, CompressedPointsToGraph(edges.toTypedArray()), escapes.toTypedArray()) + } + + fun optimistic() = + FunctionEscapeAnalysisResult(0, CompressedPointsToGraph(emptyArray()), emptyArray()) + + fun pessimistic(numberOfParameters: Int) = + FunctionEscapeAnalysisResult(0, CompressedPointsToGraph(emptyArray()), + Array(numberOfParameters + 1) { CompressedPointsToGraph.Node.parameter(it, numberOfParameters + 1) }) + } + } + + private class InterproceduralAnalysis( + val context: Context, + val callGraph: CallGraph, + val intraproceduralAnalysisResults: Map, + val externalModulesDFG: ExternalModulesDFG, + val lifetimes: MutableMap, + val propagateExiledToHeapObjects: Boolean + ) { + + private val symbols = context.ir.symbols + + private fun DataFlowIR.Type.resolved(): DataFlowIR.Type.Declared { + if (this is DataFlowIR.Type.Declared) return this + val hash = (this as DataFlowIR.Type.External).hash + return externalModulesDFG.publicTypes[hash] ?: error("Unable to resolve exported type $hash") + } + + val escapeAnalysisResults = mutableMapOf() + + fun analyze() { + context.logMultiple { + +"CALL GRAPH" + callGraph.directEdges.forEach { (t, u) -> + +" FUN $t" + u.callSites.forEach { + val label = when { + it.isVirtual -> "VIRTUAL" + callGraph.directEdges.containsKey(it.actualCallee) -> "LOCAL" + else -> "EXTERNAL" + } + +" CALLS $label ${it.actualCallee}" + } + callGraph.reversedEdges[t]!!.forEach { +" CALLED BY $it" } + } + +"" + } + + val condensation = DirectedGraphCondensationBuilder(callGraph).build() + + context.logMultiple { + +"CONDENSATION" + condensation.topologicalOrder.forEach { multiNode -> + +" MULTI-NODE" + multiNode.nodes.forEach { +" $it" } + } + +"" + +"CONDENSATION(DETAILED)" + condensation.topologicalOrder.forEach { multiNode -> + +" MULTI-NODE" + multiNode.nodes.forEach { + +" $it" + callGraph.directEdges[it]!!.callSites + .filter { callGraph.directEdges.containsKey(it.actualCallee) } + .forEach { +" CALLS ${it.actualCallee}" } + callGraph.reversedEdges[it]!!.forEach { +" CALLED BY $it" } + } + } + +"" + } + + for (functionSymbol in callGraph.directEdges.keys) { + if (!intraproceduralAnalysisResults.containsKey(functionSymbol)) continue + // Assume trivial result at the beginning - then iteratively specify it. + escapeAnalysisResults[functionSymbol] = FunctionEscapeAnalysisResult.optimistic() + } + + for (multiNode in condensation.topologicalOrder.reversed()) + analyze(callGraph, multiNode) + + context.logMultiple { + +"Managed to alloc on stack: ${stackAllocsCount * 100.0 / (globalAllocsCount + stackAllocsCount)}%" + +"Total graph size: $totalGraphSize" + } + } + + var globalAllocsCount = 0 + var stackAllocsCount = 0 + var totalGraphSize = 0 + + private fun analyze(callGraph: CallGraph, multiNode: DirectedGraphMultiNode) { + val nodes = multiNode.nodes.filter { intraproceduralAnalysisResults.containsKey(it) }.toMutableSet() + + context.logMultiple { + +"Analyzing multiNode:\n ${nodes.joinToString("\n ") { it.toString() }}" + nodes.forEach { from -> + +"DataFlowIR" + intraproceduralAnalysisResults[from]!!.function.debugOutput() + callGraph.directEdges[from]!!.callSites.forEach { to -> + +"CALL" + +" from $from" + +" to ${to.actualCallee}" + } + } + } + + val pointsToGraphs = nodes.associateBy({ it }, { PointsToGraph(it) }) + val toAnalyze = mutableSetOf() + toAnalyze.addAll(nodes) + val numberOfRuns = nodes.associateWith { 0 }.toMutableMap() + while (toAnalyze.isNotEmpty()) { + val function = toAnalyze.first() + toAnalyze.remove(function) + numberOfRuns[function] = numberOfRuns[function]!! + 1 + context.log { "Processing function $function" } + + val startResult = escapeAnalysisResults[function]!! + context.log { "Start escape analysis result:\n$startResult" } + + analyze(callGraph, pointsToGraphs[function]!!, function) + val endResult = escapeAnalysisResults[function]!! + + if (startResult == endResult) { + context.log { "Escape analysis is not changed" } + } else { + context.log { "Escape analysis was refined:\n$endResult" } + if (numberOfRuns[function]!! > 1) { + // TODO: suboptimal. May be it is possible somehow handle the entire component at once? + context.log { + "WARNING: Escape analysis for $function seems not to be converging." + + " Assuming conservative results." + } + escapeAnalysisResults[function] = FunctionEscapeAnalysisResult.pessimistic(function.parameters.size) + nodes.remove(function) + } + + callGraph.reversedEdges[function]?.forEach { + if (nodes.contains(it)) + toAnalyze.add(it) + } + } + } + + pointsToGraphs.forEach { (function, graph) -> + // TODO: suboptimal. + if (function !in nodes) return@forEach + for (node in graph.nodes.keys) { + node.ir?.let { + val lifetime = graph.lifetimeOf(node) + + if (node.isAlloc) { + if (lifetime == Lifetime.GLOBAL) + ++globalAllocsCount + if (lifetime == Lifetime.STACK) + ++stackAllocsCount + + lifetimes[it] = lifetime + } + } + } + } + } + + private fun arrayLengthOf(node: DataFlowIR.Node): Int? = + (node as? DataFlowIR.Node.SimpleConst<*>)?.value as? Int + // In case of several possible values, it's unknown what is used. + // TODO: if all values are constants which are less limit? + ?: (node as? DataFlowIR.Node.Variable) + ?.values?.singleOrNull()?.let { arrayLengthOf(it.node) } + + private val pointerSize = context.llvm.runtime.pointerSize + + private fun arrayItemSizeOf(irClass: IrClass): Int? = when (irClass.symbol) { + symbols.array -> pointerSize + symbols.booleanArray -> 1 + symbols.byteArray -> 1 + symbols.charArray -> 2 + symbols.shortArray -> 2 + symbols.intArray -> 4 + symbols.floatArray -> 4 + symbols.longArray -> 8 + symbols.doubleArray -> 8 + else -> null + } + + private fun arraySize(itemSize: Int, length: Int) = + pointerSize /* typeinfo */ + 4 /* size */ + itemSize * length + + private fun analyze(callGraph: CallGraph, pointsToGraph: PointsToGraph, function: DataFlowIR.FunctionSymbol.Declared) { + context.log {"Before calls analysis" } + pointsToGraph.log() + pointsToGraph.logDigraph(false) + + callGraph.directEdges[function]!!.callSites.forEach { + val callee = it.actualCallee + val calleeEAResult = if (it.isVirtual) + getExternalFunctionEAResult(it) + else + callGraph.directEdges[callee]?.let { escapeAnalysisResults[it.symbol]!! } + ?: getExternalFunctionEAResult(it) + pointsToGraph.processCall(it, calleeEAResult) + } + + context.log { "After calls analysis" } + pointsToGraph.log() + pointsToGraph.logDigraph(false) + + // Build transitive closure. + val eaResult = pointsToGraph.buildClosure() + + context.log { "After closure building" } + pointsToGraph.log() + pointsToGraph.logDigraph(true) + + escapeAnalysisResults[function] = eaResult + + totalGraphSize += eaResult.numberOfDrains + eaResult.escapes.size + eaResult.pointsTo.edges.size + } + + private fun DataFlowIR.FunctionSymbol.resolved(): DataFlowIR.FunctionSymbol { + if (this is DataFlowIR.FunctionSymbol.External) + return externalModulesDFG.publicFunctions[this.hash] ?: this + return this + } + + private fun getExternalFunctionEAResult(callSite: CallGraphNode.CallSite): FunctionEscapeAnalysisResult { + val callee = callSite.actualCallee.resolved() + + val calleeEAResult = if (callSite.isVirtual) { + context.log { "A virtual call: $callee" } + FunctionEscapeAnalysisResult.pessimistic(callee.parameters.size) + } else { + context.log { "An external call: $callee" } + if (callee.name?.startsWith("kfun:kotlin.") == true + // TODO: Is it possible to do it in a more fine-grained fashion? + && !callee.name.startsWith("kfun:kotlin.native.concurrent")) { + context.log { "A function from K/N runtime - can use annotations" } + FunctionEscapeAnalysisResult.fromBits( + callee.escapes ?: 0, + (0..callee.parameters.size).map { callee.pointsTo?.elementAtOrNull(it) ?: 0 } + ) + } else { + context.log { "An unknown function - assume pessimistic result" } + FunctionEscapeAnalysisResult.pessimistic(callee.parameters.size) + } + } + + context.logMultiple { + +"Escape analysis result" + +calleeEAResult.toString() + +"" + } + return calleeEAResult + } + + private enum class PointsToGraphNodeKind { + STACK, + LOCAL, + PARAMETER, + RETURN_VALUE + } + + private sealed class PointsToGraphEdge(val node: PointsToGraphNode) { + class Assignment(node: PointsToGraphNode) : PointsToGraphEdge(node) + + class Field(node: PointsToGraphNode, val field: DataFlowIR.Field) : PointsToGraphEdge(node) + } + + private class PointsToGraphNode(val nodeInfo: NodeInfo, val node: DataFlowIR.Node?) { + val edges = mutableListOf() + val reversedEdges = mutableListOf() + + fun addAssignmentEdge(to: PointsToGraphNode) { + edges += PointsToGraphEdge.Assignment(to) + to.reversedEdges += PointsToGraphEdge.Assignment(this) + } + + private val fields = mutableMapOf() + + fun getFieldNode(field: DataFlowIR.Field, graph: PointsToGraph) = + fields.getOrPut(field) { graph.newNode().also { edges += PointsToGraphEdge.Field(it, field) } } + + var depth = when { + node is DataFlowIR.Node.Parameter -> Depths.PARAMETER + nodeInfo.has(Role.RETURN_VALUE) -> Depths.RETURN_VALUE + else -> nodeInfo.depth + } + + val kind get() = when { + depth == Depths.PARAMETER -> PointsToGraphNodeKind.PARAMETER + depth == Depths.RETURN_VALUE -> PointsToGraphNodeKind.RETURN_VALUE + depth != nodeInfo.depth -> PointsToGraphNodeKind.LOCAL + else -> PointsToGraphNodeKind.STACK + } + + var forcedLifetime: Lifetime? = null + + lateinit var drain: PointsToGraphNode + val isDrain get() = this == drain + + val actualDrain: PointsToGraphNode + get() = drain.let { + if (it.isDrain) it + // Flip to the real drain as it is done in the disjoint sets algorithm, + // to reduce the time spent in this function. + else it.actualDrain.also { drain = it } + } + val isActualDrain get() = this == actualDrain + + val beingReturned get() = nodeInfo.has(Role.RETURN_VALUE) + } + + private data class ArrayStaticAllocation(val node: PointsToGraphNode, val irClass: IrClass, val size: Int) + + private enum class EdgeDirection { + FORWARD, + BACKWARD + } + + private inner class PointsToGraph(val functionSymbol: DataFlowIR.FunctionSymbol) { + + val functionAnalysisResult = intraproceduralAnalysisResults[functionSymbol]!! + val nodes = mutableMapOf() + + val allNodes = mutableListOf() + + fun newNode(nodeInfo: NodeInfo, node: DataFlowIR.Node?) = + PointsToGraphNode(nodeInfo, node).also { allNodes.add(it) } + fun newNode() = newNode(NodeInfo(), null) + fun newDrain() = newNode().also { it.drain = it } + + val returnsNode = newNode(NodeInfo().also { it.data[Role.RETURN_VALUE] = RoleInfo() }, null) + + /* + * Of all escaping nodes there are some "starting" - call them origins. + * Consider a variable [v], which is assigned with two values - [a] and [b]. + * Now assume [a] escapes (written to a global, for instance). This implies that [v] also escapes, + * but [b] doesn't, albeit [v] (an escaping node) references it. It's because [v] is not an escape origin. + */ + // The origins of escaping. + val escapeOrigins = mutableSetOf() + // Nodes reachable from either of escape origins going along all edges (assignment and/or field). + val reachableFromEscapeOrigins = mutableSetOf() + // Nodes referencing any escape origin only by assignment edges. + val referencingEscapeOrigins = mutableSetOf() + + fun escapes(node: PointsToGraphNode) = node in reachableFromEscapeOrigins || node in referencingEscapeOrigins + + val ids = ( + listOf(functionAnalysisResult.function.body.rootScope) + + functionAnalysisResult.function.body.allScopes.flatMap { it.nodes } + ) + .withIndex().associateBy({ it.value }, { it.index }) + + fun lifetimeOf(node: DataFlowIR.Node) = nodes[node]!!.let { it.forcedLifetime ?: lifetimeOf(it) } + + fun lifetimeOf(node: PointsToGraphNode) = + if (escapes(node)) + Lifetime.GLOBAL + else when (node.kind) { + PointsToGraphNodeKind.PARAMETER -> Lifetime.ARGUMENT + + PointsToGraphNodeKind.STACK -> { + // A value doesn't escape from its scope - it can be allocated on the stack. + Lifetime.STACK + } + + PointsToGraphNodeKind.LOCAL -> { + // A value is neither stored into a global nor into any parameter nor into the return value - + // it can be allocated locally. + Lifetime.LOCAL + } + + PointsToGraphNodeKind.RETURN_VALUE -> { + when { + // If a value is explicitly returned. + node.node?.let { it in returnValues } == true -> Lifetime.RETURN_VALUE + + // A value is stored into a field of the return value. + else -> Lifetime.INDIRECT_RETURN_VALUE + } + } + } + + private val returnValues: Set + + init { + context.logMultiple { + +"Building points-to graph for function $functionSymbol" + +"Results of preliminary function analysis" + } + functionAnalysisResult.nodesRoles.forEach { (node, roles) -> + context.log { "NODE ${nodeToString(node)}: $roles" } + nodes[node] = newNode(roles, node) + } + + val returnValues = mutableListOf() + functionAnalysisResult.nodesRoles.forEach { (node, roles) -> + val ptgNode = nodes[node]!! + addEdges(ptgNode, roles) + if (ptgNode.beingReturned) { + returnsNode.getFieldNode(returnsValueField, this).addAssignmentEdge(ptgNode) + returnValues += node + } + if (roles.escapes()) + escapeOrigins += ptgNode + } + + this.returnValues = returnValues.toSet() + + val escapes = functionSymbol.escapes + if (escapes != null) { + // Parameters are declared in the root scope + val parameters = functionAnalysisResult.function.body.rootScope.nodes + .filterIsInstance() + for (parameter in parameters) + if (escapes and (1 shl parameter.index) != 0) + escapeOrigins += nodes[parameter]!! + if (escapes and (1 shl parameters.size) != 0) + escapeOrigins += returnsNode + } + } + + private fun addEdges(from: PointsToGraphNode, roles: NodeInfo) { + val assigned = roles.data[Role.ASSIGNED] + assigned?.entries?.forEach { + val to = nodes[it.node!!]!! + from.addAssignmentEdge(to) + } + roles.data[Role.WRITE_FIELD]?.entries?.forEach { roleInfo -> + val value = nodes[roleInfo.node!!]!! + val field = roleInfo.field!! + from.getFieldNode(field, this).addAssignmentEdge(value) + } + roles.data[Role.READ_FIELD]?.entries?.forEach { roleInfo -> + val result = nodes[roleInfo.node!!]!! + val field = roleInfo.field!! + result.addAssignmentEdge(from.getFieldNode(field, this)) + } + } + + private fun nodeToStringWhole(node: DataFlowIR.Node) = DataFlowIR.Function.nodeToString(node, ids) + + private fun nodeToString(node: DataFlowIR.Node) = ids[node].toString() + + fun log() = context.logMultiple { + +"POINTS-TO GRAPH" + +"NODES" + val tempIds = mutableMapOf() + var tempIndex = 0 + allNodes.forEach { + if (it.node == null) + tempIds[it] = tempIndex++ + } + allNodes.forEach { + val tempId = tempIds[it] + +" ${lifetimeOf(it)} ${it.depth} ${if (it in escapeOrigins) "ESCAPES" else ""} ${it.node?.let { nodeToString(it) } ?: "t$tempId"}" + +(it.node?.let { nodeToStringWhole(it) } ?: " t$tempId") + } + } + + fun logDigraph( + markDrains: Boolean, + nodeFilter: (PointsToGraphNode) -> Boolean = { true }, + nodeLabel: ((PointsToGraphNode) -> String)? = null + ) = context.logMultiple { + +"digraph {" + val tempIds = mutableMapOf() + var tempIndex = 0 + allNodes.forEach { + if (it.node == null) + tempIds[it] = tempIndex++ + } + + fun PointsToGraphNode.format() = + (nodeLabel?.invoke(this) ?: + (if (markDrains && isDrain) "d" else "") + + (node?.let { "n${ids[it]!!}" } ?: "t${tempIds[this]}")) + + "[d=$depth,${if (this in escapeOrigins) "eo" else if (escapes(this)) "e" else ""}]" + + for (from in allNodes) { + if (!nodeFilter(from)) continue + for (it in from.edges) { + val to = it.node + if (!nodeFilter(to)) continue + when (it) { + is PointsToGraphEdge.Assignment -> + +" \"${from.format()}\" -> \"${to.format()}\";" + is PointsToGraphEdge.Field -> + +" \"${from.format()}\" -> \"${to.format()}\" [ label=\"${it.field.name}\"];" + } + } + } + +"}" + } + + fun processCall(callSite: CallGraphNode.CallSite, calleeEscapeAnalysisResult: FunctionEscapeAnalysisResult) { + val call = callSite.call + context.logMultiple { + +"Processing callSite" + +nodeToStringWhole(call) + +"Actual callee: ${callSite.actualCallee}" + +"Callee escape analysis result:" + +calleeEscapeAnalysisResult.toString() + } + + val arguments = if (call is DataFlowIR.Node.NewObject) { + (0..call.arguments.size).map { + if (it == 0) call else call.arguments[it - 1].node + } + } else { + (0..call.arguments.size).map { + if (it < call.arguments.size) call.arguments[it].node else call + } + } + + val calleeDrains = Array(calleeEscapeAnalysisResult.numberOfDrains) { newNode() } + + fun mapNode(compressedNode: CompressedPointsToGraph.Node): Pair { + val (arg, rootNode) = when (val kind = compressedNode.kind) { + CompressedPointsToGraph.NodeKind.Return -> + if (call is DataFlowIR.Node.NewObject) // TODO: This better be an assertion. + DataFlowIR.Node.Null to null + else + arguments.last() to nodes[arguments.last()] + is CompressedPointsToGraph.NodeKind.Param -> arguments[kind.index] to nodes[arguments[kind.index]] + is CompressedPointsToGraph.NodeKind.Drain -> null to calleeDrains[kind.index] + } + if (rootNode == null) + return arg to rootNode + val path = compressedNode.path + var node: PointsToGraphNode = rootNode + for (field in path) { + node = when (field) { + returnsValueField -> node + else -> node.getFieldNode(field, this) + } + } + return arg to node + } + + calleeEscapeAnalysisResult.escapes.forEach { escapingNode -> + val (arg, node) = mapNode(escapingNode) + if (node == null) { + context.log { "WARNING: There is no node ${nodeToString(arg!!)}" } + return@forEach + } + escapeOrigins += node + context.log { "Node ${escapingNode.debugString(arg?.let { nodeToString(it) })} escapes" } + } + + calleeEscapeAnalysisResult.pointsTo.edges.forEach { edge -> + val (fromArg, fromNode) = mapNode(edge.from) + if (fromNode == null) { + context.log { "WARNING: There is no node ${nodeToString(fromArg!!)}" } + return@forEach + } + val (toArg, toNode) = mapNode(edge.to) + if (toNode == null) { + context.log { "WARNING: There is no node ${nodeToString(toArg!!)}" } + return@forEach + } + fromNode.addAssignmentEdge(toNode) + + context.logMultiple { + +"Adding edge" + +" FROM ${edge.from.debugString(fromArg?.let { nodeToString(it) })}" + +" TO ${edge.to.debugString(toArg?.let { nodeToString(it) })}" + } + } + } + + fun buildClosure(): FunctionEscapeAnalysisResult { + context.logMultiple { + +"BUILDING CLOSURE" + +"Return values:" + returnValues.forEach { +" ${nodeToString(it)}" } + } + + buildDrains() + + logDigraph(true) + + computeLifetimes() + + /* + * The next part determines the function's escape analysis result. + * Of course, the simplest way would be to just take the entire graph, but it might be big, + * and during call graph traversal these EA graphs will continue to grow (since they are + * being embedded at each call site). To overcome this, the graph must be reduced. + * Let us call nodes that will be part of the result "interesting", and, obviously, + * "interesting drains" - drains that are going to be in the result. + */ + val (numberOfDrains, nodeIds) = paintInterestingNodes() + + logDigraph(true, { nodeIds[it] != null }, { nodeIds[it].toString() }) + + // TODO: Remove redundant edges. + val compressedEdges = mutableListOf() + val escapingNodes = mutableListOf() + for (from in allNodes) { + val fromCompressedNode = nodeIds[from] ?: continue + if (from in escapeOrigins) + escapingNodes += fromCompressedNode + for (edge in from.edges) { + val toCompressedNode = nodeIds[edge.node] ?: continue + when (edge) { + is PointsToGraphEdge.Assignment -> + compressedEdges += CompressedPointsToGraph.Edge(fromCompressedNode, toCompressedNode) + + is PointsToGraphEdge.Field -> + if (edge.node == from /* A loop */) { + compressedEdges += CompressedPointsToGraph.Edge( + fromCompressedNode.goto(edge.field), toCompressedNode) + } + } + } + } + + return FunctionEscapeAnalysisResult( + numberOfDrains, + CompressedPointsToGraph(compressedEdges.toTypedArray()), + escapingNodes.toTypedArray() + ) + } + + private fun buildDrains() { + // TODO: This is actually conservative. If a field is being read of some node, + // then here it is assumed that it might also be being read from any node reachable + // by assignment edges considering them undirected. But in reality it is enough to just + // merge two sets: reachable by assignment edges and reachable by reversed assignment edges. + // But, there will be a downside - drains will have to be created for each field access, + // thus increasing the graph size significantly. + val visited = mutableSetOf() + val drains = mutableListOf() + val createdDrains = mutableSetOf() + // Create drains. + for (node in allNodes.toTypedArray() /* Copy as [allNodes] might change inside */) { + if (node in visited) continue + val component = mutableListOf() + buildComponent(node, visited, component) + val drain = trySelectDrain(component)?.also { it.drain = it } + ?: newDrain().also { createdDrains += it } + drains += drain + component.forEach { + if (it == drain) return@forEach + it.drain = drain + val assignmentEdges = mutableListOf() + for (edge in it.edges) { + if (edge is PointsToGraphEdge.Assignment) + assignmentEdges += edge + else + drain.edges += edge + } + it.edges.clear() + it.edges += assignmentEdges + } + } + + fun PointsToGraphNode.flipTo(otherDrain: PointsToGraphNode) { + require(isDrain) + require(otherDrain.isDrain) + drain = otherDrain + otherDrain.edges += edges + edges.clear() + } + + // Merge the components multi-edges are pointing at. + // TODO: This looks very similar to the system of disjoint sets algorithm. + while (true) { + val toMerge = mutableListOf>() + for (drain in drains) { + val fields = drain.edges.groupBy { edge -> + (edge as? PointsToGraphEdge.Field)?.field + ?: error("A drain cannot have outgoing assignment edges") + } + for (nodes in fields.values) { + if (nodes.size == 1) continue + for (i in nodes.indices) { + val firstNode = nodes[i].node + val secondNode = if (i == nodes.size - 1) nodes[0].node else nodes[i + 1].node + if (firstNode.actualDrain != secondNode.actualDrain) + toMerge += Pair(firstNode, secondNode) + } + } + } + if (toMerge.isEmpty()) break + val possibleDrains = mutableListOf() + for ((first, second) in toMerge) { + // Merge components: try to flip one drain to the other if possible, + // otherwise just create a new one. + + val firstDrain = first.actualDrain + val secondDrain = second.actualDrain + when { + firstDrain == secondDrain -> continue + + firstDrain in createdDrains -> { + secondDrain.flipTo(firstDrain) + possibleDrains += firstDrain + } + + secondDrain in createdDrains -> { + firstDrain.flipTo(secondDrain) + possibleDrains += secondDrain + } + + else -> { + // Create a new drain in order to not create false constraints. + val newDrain = newDrain().also { createdDrains += it } + firstDrain.flipTo(newDrain) + secondDrain.flipTo(newDrain) + possibleDrains += newDrain + } + } + } + drains.clear() + possibleDrains.filterTo(drains) { it.isDrain } + } + + // Compute current drains. + drains.clear() + allNodes.filterTo(drains) { it.isActualDrain } + + // A validation. + for (drain in drains) { + val fields = mutableMapOf() + for (edge in drain.edges) { + val field = (edge as? PointsToGraphEdge.Field)?.field + ?: error("A drain cannot have outgoing assignment edges") + val node = edge.node.actualDrain + fields.getOrPut(field) { node }.also { + if (it != node) error("Drains have not been built correctly") + } + } + } + + // Coalesce multi-edges. + for (drain in drains) { + val actualDrain = drain.actualDrain + val fields = actualDrain.edges.groupBy { edge -> + (edge as? PointsToGraphEdge.Field)?.field + ?: error("A drain cannot have outgoing assignment edges") + } + actualDrain.edges.clear() + for (nodes in fields.values) { + if (nodes.size == 1) { + actualDrain.edges += nodes[0] + continue + } + // All nodes in [nodes] must be connected to each other, but a drain, by definition, + // cannot have outgoing assignment edges, thus a new drain must be created here. + nodes.atMostOne { it.node.isActualDrain } + ?.node?.actualDrain?.flipTo(newDrain()) + + for (i in nodes.indices) { + val firstNode = nodes[i].node + val secondNode = if (i == nodes.size - 1) nodes[0].node else nodes[i + 1].node + firstNode.addAssignmentEdge(secondNode) + } + // Can pick any. + actualDrain.edges += nodes[0] + } + } + + // Make sure every node within a component points to the component's drain. + for (node in allNodes) { + val drain = node.actualDrain + node.drain = drain + if (node != drain) + node.addAssignmentEdge(drain) + } + } + + // Drains, other than interesting, can be safely omitted from the result. + private fun findInterestingDrains(parameters: Array): Set { + // Starting with all reachable from the parameters. + val interestingDrains = mutableSetOf() + for (param in parameters) { + val drain = param.drain + if (drain !in interestingDrains) + findReachableDrains(drain, interestingDrains) + } + + // Then iteratively remove all drains forming kind of a "cactus" + // (picking a leaf drain with only one incoming edge at a time). + // They can be removed because they don't add any relations between the parameters. + val reversedEdges = interestingDrains.associateWith { + mutableListOf>() + } + val edgesCount = mutableMapOf() + val leaves = mutableListOf() + for (drain in interestingDrains) { + var count = 0 + for (edge in drain.edges) { + val nextDrain = edge.node.drain + reversedEdges[nextDrain]!! += drain to edge + if (nextDrain in interestingDrains) + ++count + } + edgesCount[drain] = count + if (count == 0) + leaves.push(drain) + } + val parameterDrains = parameters.map { it.drain }.toSet() + while (leaves.isNotEmpty()) { + val drain = leaves.pop() + val incomingEdges = reversedEdges[drain]!! + if (incomingEdges.isEmpty()) { + if (drain !in parameterDrains) + error("A drain with no incoming edges") + if (!parameters.any { it.isDrain && escapes(it) }) + interestingDrains.remove(drain) + continue + } + if (drain in parameterDrains) + continue + if (incomingEdges.size == 1 + && incomingEdges[0].let { (node, edge) -> escapes(node) || !escapes(edge.node) } + ) { + interestingDrains.remove(drain) + val prevDrain = incomingEdges[0].first + val count = edgesCount[prevDrain]!! - 1 + edgesCount[prevDrain] = count + if (count == 0) + leaves.push(prevDrain) + } + } + return interestingDrains + } + + private fun getParameterNodes(): Array { + // Put a dummyNode in order to not bother with nullability. Then rewrite it with actual values. + val dummyNode = returnsNode // Anything will do. + val parameters = Array(functionSymbol.parameters.size + 1) { dummyNode } + + // Parameters are declared in the root scope. + functionAnalysisResult.function.body.rootScope.nodes + .filterIsInstance() + .forEach { + if (parameters[it.index] != dummyNode) + error("Two parameters with the same index ${it.index}: $it, ${parameters[it.index].node}") + parameters[it.index] = nodes[it]!! + } + parameters[functionSymbol.parameters.size] = returnsNode + + return parameters + } + + private fun paintInterestingNodes(): Pair> { + var drainsCount = 0 + val drainFactory = { CompressedPointsToGraph.Node.drain(drainsCount++) } + + val parameters = getParameterNodes() + val interestingDrains = findInterestingDrains(parameters) + val nodeIds = paintNodes(parameters, interestingDrains, drainFactory) + buildComponentsClosures(nodeIds) + handleNotTakenEscapeOrigins(nodeIds, drainFactory) + restoreOptimizedAwayDrainsIfNeeded(interestingDrains, nodeIds, drainFactory) + + return Pair(drainsCount, nodeIds) + } + + private fun handleNotTakenEscapeOrigins( + nodeIds: MutableMap, + drainFactory: () -> CompressedPointsToGraph.Node + ) { + // We've marked reachable nodes from the parameters, also taking some of the escape origins. + // But there might be some escape origins that are not taken, yet referencing some of the + // marked nodes. Do the following: find all escaping nodes only taking marked escape origins + // into account, compare the result with all escaping nodes. Now for each non-marked escape origin + // find nodes escaping because of it, take those who aren't escaping through the marked origins, + // and add an additional node, pointing at those and mark it as an escape origin. + val reachableFromTakenEscapeOrigins = mutableSetOf() + val referencingTakenEscapeOrigins = mutableSetOf() + val reachableFromNotTakenEscapeOrigins = mutableSetOf() + val referencingNotTakenEscapeOrigins = mutableSetOf() + val reachableFringeFromNotTakenEscapeOrigins = mutableSetOf() + val fringeReferencingNotTakenEscapeOrigins = mutableSetOf() + for (escapeOrigin in escapeOrigins) { + if (nodeIds[escapeOrigin] == null) { + if (escapeOrigin !in reachableFromNotTakenEscapeOrigins) + findReachableFringe(escapeOrigin, reachableFromNotTakenEscapeOrigins, + reachableFringeFromNotTakenEscapeOrigins, nodeIds) + if (escapeOrigin !in referencingNotTakenEscapeOrigins) + findReferencingFringe(escapeOrigin, referencingNotTakenEscapeOrigins, + fringeReferencingNotTakenEscapeOrigins, nodeIds) + } else { + if (escapeOrigin !in reachableFromTakenEscapeOrigins) + findReachable(escapeOrigin, reachableFromTakenEscapeOrigins, false, null) + if (escapeOrigin !in referencingTakenEscapeOrigins) + findReferencing(escapeOrigin, referencingTakenEscapeOrigins) + } + } + + fun addAdditionalEscapeOrigins(escapingNodes: List, direction: EdgeDirection) { + escapingNodes + .groupBy { it.drain } + .forEach { (drain, nodes) -> + val tempNode = newNode() + nodeIds[tempNode] = drainFactory() + tempNode.drain = drain + tempNode.addAssignmentEdge(drain) + escapeOrigins += tempNode + for (node in nodes) + when (direction) { + EdgeDirection.FORWARD -> tempNode.addAssignmentEdge(node) + EdgeDirection.BACKWARD -> node.addAssignmentEdge(tempNode) + } + } + } + + addAdditionalEscapeOrigins( + reachableFringeFromNotTakenEscapeOrigins + .filterNot { it in reachableFromTakenEscapeOrigins }, + EdgeDirection.FORWARD + ) + addAdditionalEscapeOrigins( + fringeReferencingNotTakenEscapeOrigins + .filterNot { it in referencingTakenEscapeOrigins }, + EdgeDirection.BACKWARD + ) + } + + private fun restoreOptimizedAwayDrainsIfNeeded( + interestingDrains: Set, + nodeIds: MutableMap, + drainFactory: () -> CompressedPointsToGraph.Node + ) { + // Here we try to find this subgraph within one component: [v -> d; w -> d; v !-> w; w !-> v]. + // In most cases such a node [d] is just the drain of the component, + // but it may have been optimized away. + // This is needed because components are built with edges being considered undirected, so + // this implicit connection between [v] and [w] may be needed. Note, however, that the + // opposite subgraph: [d -> v; d -> w; v !-> w; w !-> v] is not interesting, because [d] + // can't hold both values simultaneously, but two references can hold the same value + // at the same time, that's the difference. + // For concrete example see [codegen/escapeAnalysis/test10.kt]. + val connectedNodes = mutableSetOf>() + allNodes.filter { nodeIds[it] != null && nodeIds[it.drain] == null /* The drain has been optimized away */ } + .forEach { node -> + val referencingNodes = findReferencing(node).filter { nodeIds[it] != null } + for (i in referencingNodes.indices) + for (j in i + 1 until referencingNodes.size) { + val firstNode = referencingNodes[i] + val secondNode = referencingNodes[j] + connectedNodes.add(Pair(firstNode, secondNode)) + connectedNodes.add(Pair(secondNode, firstNode)) + } + } + allNodes.filter { nodeIds[it] == null && it.drain in interestingDrains && nodeIds[it.drain] == null } + .forEach { node -> + val referencingNodes = findReferencing(node).filter { nodeIds[it] != null } + for (i in referencingNodes.indices) + for (j in i + 1 until referencingNodes.size) { + val firstNode = referencingNodes[i] + val secondNode = referencingNodes[j] + val pair = Pair(firstNode, secondNode) + if (pair in connectedNodes) continue + + // It is not an actual drain, but a temporary node to reflect the found constraint. + val additionalDrain = newDrain() + // For consistency. + additionalDrain.depth = min(firstNode.depth, secondNode.depth) + + firstNode.addAssignmentEdge(additionalDrain) + secondNode.addAssignmentEdge(additionalDrain) + nodeIds[additionalDrain] = drainFactory() + connectedNodes.add(pair) + connectedNodes.add(Pair(secondNode, firstNode)) + } + } + } + + private fun findReferencing(node: PointsToGraphNode, visited: MutableSet) { + visited += node + for (edge in node.reversedEdges) { + val nextNode = edge.node + if (nextNode !in visited) + findReferencing(nextNode, visited) + } + } + + private fun findReferencing(node: PointsToGraphNode): Set { + val visited = mutableSetOf() + findReferencing(node, visited) + return visited + } + + private fun trySelectDrain(component: MutableList) = + component.firstOrNull { node -> + if (node.edges.any { it is PointsToGraphEdge.Assignment }) + false + else + findReferencing(node).size == component.size + } + + private fun buildComponent( + node: PointsToGraphNode, + visited: MutableSet, + component: MutableList + ) { + visited += node + component += node + for (edge in node.edges) { + if (edge is PointsToGraphEdge.Assignment && edge.node !in visited) + buildComponent(edge.node, visited, component) + } + for (edge in node.reversedEdges) { + if (edge.node !in visited) + buildComponent(edge.node, visited, component) + } + } + + private fun findReachable(node: PointsToGraphNode, visited: MutableSet, + assignmentOnly: Boolean, + nodeIds: MutableMap?) { + visited += node + node.edges.forEach { + val next = it.node + if ((it is PointsToGraphEdge.Assignment || !assignmentOnly) + && next !in visited && nodeIds?.containsKey(next) != false) + findReachable(next, visited, assignmentOnly, nodeIds) + } + } + + private fun findFringe(node: PointsToGraphNode, visited: MutableSet, + fringe: MutableSet, direction: EdgeDirection, + nodeIds: MutableMap) { + visited += node + if (nodeIds[node] != null) { + fringe += node + return + } + val edges = when (direction) { + EdgeDirection.FORWARD -> node.edges + EdgeDirection.BACKWARD -> node.reversedEdges + } + for (edge in edges) { + val next = edge.node + if (next !in visited) + findFringe(next, visited, fringe, direction, nodeIds) + } + } + + private fun findReachableFringe( + node: PointsToGraphNode, visited: MutableSet, + fringe: MutableSet, + nodeIds: MutableMap + ) = findFringe(node, visited, fringe, EdgeDirection.FORWARD, nodeIds) + + private fun findReferencingFringe( + node: PointsToGraphNode, visited: MutableSet, + fringe: MutableSet, + nodeIds: MutableMap + ) = findFringe(node, visited, fringe, EdgeDirection.BACKWARD, nodeIds) + + private fun buildComponentsClosures(nodeIds: MutableMap) { + for (node in allNodes) { + if (node !in nodeIds) continue + val visited = mutableSetOf() + findReachable(node, visited, true, null) + val visitedInInterestingSubgraph = mutableSetOf() + findReachable(node, visitedInInterestingSubgraph, true, nodeIds) + visited.removeAll(visitedInInterestingSubgraph) + for (reachable in visited) + if (reachable in nodeIds) + node.addAssignmentEdge(reachable) + } + } + + private fun propagateLifetimes() { + val visited = mutableSetOf() + + fun propagate(node: PointsToGraphNode) { + visited += node + val depth = node.depth + for (edge in node.edges) { + val nextNode = edge.node + if (nextNode !in visited && nextNode.depth >= depth) { + nextNode.depth = depth + propagate(nextNode) + } + } + } + + for (node in allNodes.sortedBy { it.depth }) { + if (node !in visited) + propagate(node) + } + } + + private fun propagateEscapeOrigin(node: PointsToGraphNode) { + if (node !in reachableFromEscapeOrigins) + findReachable(node, reachableFromEscapeOrigins, false, null) + if (node !in referencingEscapeOrigins) + findReferencing(node, referencingEscapeOrigins) + } + + private fun computeLifetimes() { + propagateLifetimes() + + escapeOrigins.forEach { propagateEscapeOrigin(it) } + + val stackArrayCandidates = mutableListOf() + for ((node, ptgNode) in nodes) { + if (node.ir == null) continue + + val computedLifetime = lifetimeOf(node) + var lifetime = computedLifetime + + if (lifetime != Lifetime.STACK) { + // TODO: Support other lifetimes - requires arenas. + lifetime = Lifetime.GLOBAL + } + + if (lifetime == Lifetime.STACK && node is DataFlowIR.Node.NewObject) { + val constructedType = node.constructedType.resolved() + constructedType.irClass?.let { irClass -> + val itemSize = arrayItemSizeOf(irClass) + if (itemSize != null) { + val sizeArgument = node.arguments.first().node + val arrayLength = arrayLengthOf(sizeArgument) + if (arrayLength != null) { + stackArrayCandidates += + ArrayStaticAllocation(ptgNode, irClass, arraySize(itemSize, arrayLength)) + } else { + // Can be placed into the local arena. + // TODO. Support Lifetime.LOCAL + lifetime = Lifetime.GLOBAL + } + } + } + } + + if (lifetime != computedLifetime) { + if (propagateExiledToHeapObjects && node.isAlloc) { + context.log { "Forcing node ${nodeToString(node)} to escape" } + escapeOrigins += ptgNode + propagateEscapeOrigin(ptgNode) + } else { + ptgNode.forcedLifetime = lifetime + } + } + } + + stackArrayCandidates.sortBy { it.size } + // TODO: To a setting? + var allowedToAlloc = 65536 + for ((ptgNode, irClass, size) in stackArrayCandidates) { + if (lifetimeOf(ptgNode) != Lifetime.STACK) continue + if (size <= allowedToAlloc) + allowedToAlloc -= size + else { + allowedToAlloc = 0 + // Do not exile primitive arrays - they ain't reference no object. + if (irClass.symbol == symbols.array && propagateExiledToHeapObjects) { + context.log { "Forcing node ${nodeToString(ptgNode.node!!)} to escape" } + escapeOrigins += ptgNode + propagateEscapeOrigin(ptgNode) + } else { + ptgNode.forcedLifetime = Lifetime.GLOBAL // TODO: Change to LOCAL when supported. + } + } + } + } + + private fun findReachableDrains(drain: PointsToGraphNode, visitedDrains: MutableSet) { + visitedDrains += drain + for (edge in drain.edges) { + if (edge is PointsToGraphEdge.Assignment) + error("A drain cannot have outgoing assignment edges") + val nextDrain = edge.node.drain + if (nextDrain !in visitedDrains) + findReachableDrains(nextDrain, visitedDrains) + } + } + + private fun paintNodes( + parameters: Array, + interestingDrains: Set, + drainFactory: () -> CompressedPointsToGraph.Node + ): MutableMap { + val nodeIds = mutableMapOf() + + for (index in parameters.indices) + nodeIds[parameters[index]] = CompressedPointsToGraph.Node.parameter(index, parameters.size) + + val standAloneDrains = interestingDrains.toMutableSet() + for (drain in interestingDrains) + for (edge in drain.edges) { + val node = edge.node + if (node.isDrain && node != drain /* Skip loops */) + standAloneDrains.remove(node) + } + for (drain in standAloneDrains) { + if (nodeIds[drain] == null + // A little optimization - skip leaf drains. + && drain.edges.any { it.node.drain in interestingDrains }) + nodeIds[drain] = drainFactory() + } + + var front = nodeIds.keys.toList() + while (front.isNotEmpty()) { + val nextFront = mutableListOf() + for (node in front) { + val nodeId = nodeIds[node]!! + node.edges.filterIsInstance().forEach { edge -> + val field = edge.field + val nextNode = edge.node + if (nextNode.drain in interestingDrains && nextNode != node /* Skip loops */) { + val nextNodeId = nodeId.goto(field) + if (nodeIds[nextNode] != null) + error("Expected only one incoming field edge. ${nodeIds[nextNode]} != $nextNodeId") + nodeIds[nextNode] = nextNodeId + if (nextNode.isDrain) + nextFront += nextNode + } + } + } + front = nextFront + } + for (drain in interestingDrains) { + if (nodeIds[drain] == null && drain.edges.any { it.node.drain in interestingDrains }) + error("Drains have not been painted properly") + } + + return nodeIds + } + } + } + + fun computeLifetimes(context: Context, moduleDFG: ModuleDFG, externalModulesDFG: ExternalModulesDFG, + callGraph: CallGraph, lifetimes: MutableMap) { + assert(lifetimes.isEmpty()) + + try { + val intraproceduralAnalysisResult = + IntraproceduralAnalysis(context, moduleDFG, externalModulesDFG, callGraph).analyze() + InterproceduralAnalysis(context, callGraph, intraproceduralAnalysisResult, externalModulesDFG, lifetimes, + // TODO: This is a bit conservative, but for more aggressive option some support from runtime is + // needed (namely, determining that a pointer is from the stack; this is easy for x86 or x64, + // but what about all other platforms?). + propagateExiledToHeapObjects = true + ).analyze() + } catch (t: Throwable) { + val extraUserInfo = + """ + Please try to disable escape analysis and rerun the build. To do it add the following snippet to the gradle script: + + kotlin.targets.withType { + binaries.all { + freeCompilerArgs += "-Xdisable-phases=EscapeAnalysis" + } + } + + In case of using command line compiler add this option: "-Xdisable-phases=EscapeAnalysis". + Also, consider filing an issue with full Gradle log here: https://kotl.in/issue + """.trimIndent() + context.reportCompilationError("Escape analysis failure:\n$extraUserInfo\n\n${t.message}\n${t.stackTraceToString()}") + } + } +} \ No newline at end of file diff --git a/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/optimizations/LocalEscapeAnalysis.kt b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/optimizations/LocalEscapeAnalysis.kt new file mode 100644 index 00000000000..cace5e8bdd6 --- /dev/null +++ b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/optimizations/LocalEscapeAnalysis.kt @@ -0,0 +1,208 @@ +/* + * Copyright 2010-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +package org.jetbrains.kotlin.backend.konan.optimizations + +import org.jetbrains.kotlin.backend.konan.llvm.Lifetime +import org.jetbrains.kotlin.ir.IrElement +import org.jetbrains.kotlin.backend.konan.Context +import org.jetbrains.kotlin.backend.konan.logMultiple +import org.jetbrains.kotlin.backend.konan.descriptors.isArrayWithFixedSizeItems + +internal object LocalEscapeAnalysis { + private enum class EscapeState { + GLOBAL_ESCAPE, // escape through global reference + ARG_ESCAPE, // escapes through function arguments, return or throw + NO_ESCAPE // object does not escape + } + + class FunctionAnalyzer(val function: DataFlowIR.Function, val context: Context) { + // Escape states of nodes. + private val nodesEscapeStates = mutableMapOf() + // Connected objects map, escape state change of key node influences on all connected nodes states. + private val connectedObjects = mutableMapOf>() + // Maximum size of array which is allowed to allocate on stack. + // TODO: replace into KonanConfigKeys? + private val stackAllocationArraySizeLimit = 64 + + private var DataFlowIR.Node.escapeState: EscapeState + set(value) { + // Write state only if it has more limitations. + val writeState = nodesEscapeStates[this]?.let { + value < it + } ?: true + if (writeState) { + nodesEscapeStates[this] = value + } + } + get() = nodesEscapeStates.getOrDefault(this, EscapeState.NO_ESCAPE) + + private fun connectObjects(node: DataFlowIR.Node, connectedNode: DataFlowIR.Node) { + connectedObjects.getOrPut(node) { mutableSetOf() }.add(connectedNode) + } + + private fun findOutArraySize(node: DataFlowIR.Node): Int? { + if (node is DataFlowIR.Node.SimpleConst<*>) { + return node.value as? Int + } + if (node is DataFlowIR.Node.Variable) { + // In case of several possible values, it's unknown what is used. + // TODO: if all values are constants which are less limit? + if (node.values.size == 1) { + return findOutArraySize(node.values.first().node) + } + } + return null + } + + private fun evaluateEscapeState(node: DataFlowIR.Node) { + node.escapeState = EscapeState.NO_ESCAPE + when (node) { + is DataFlowIR.Node.Call -> { + val pointsToMasks = (0..node.callee.parameters.size) + .map { node.callee.pointsTo?.elementAtOrNull(it) ?: 0 } + val returnPointsToMask = pointsToMasks[node.callee.parameters.size] + node.arguments.forEachIndexed { index, arg -> + // Check information about arguments escaping. + val escapes = node.callee.escapes?.let { + it and (1 shl index) != 0 + } ?: node.callee !is DataFlowIR.FunctionSymbol.External + + // Connect with all arguments that return value points to. + if (returnPointsToMask and (1 shl index) != 0) { + connectObjects(node, arg.node) + } + + // Connect current argument with other it points to. + (0..node.callee.parameters.size).filter { pointsToMasks[index] and (1 shl it) != 0 }.forEach { + if (it == node.callee.parameters.size) { + // Argument points to this. + connectObjects(arg.node, node) + } else { + connectObjects(arg.node, node.arguments[it].node) + } + } + arg.node.escapeState = if (escapes) EscapeState.ARG_ESCAPE else EscapeState.NO_ESCAPE + } + + // Check size for array allocation. + if (node is DataFlowIR.Node.NewObject && node.constructedType is DataFlowIR.Type.Declared) { + node.constructedType.irClass?.let { irClass -> + // Work only with arrays which elements size is known. + if (irClass.isArrayWithFixedSizeItems) { + val sizeArgument = node.arguments.first().node + val arraySize = findOutArraySize(sizeArgument) + if (arraySize == null || arraySize > stackAllocationArraySizeLimit) { + node.escapeState = EscapeState.GLOBAL_ESCAPE + } + } else { + node.escapeState = EscapeState.GLOBAL_ESCAPE + } + } + } + } + is DataFlowIR.Node.Singleton -> { + node.escapeState = EscapeState.GLOBAL_ESCAPE + } + is DataFlowIR.Node.FieldRead -> { + node.receiver?.let { obj -> + connectObjects(node, obj.node) + } ?: run { node.escapeState = EscapeState.GLOBAL_ESCAPE } + } + is DataFlowIR.Node.FieldWrite -> { + node.receiver?.let { obj -> + connectObjects(obj.node, node.value.node) + } ?: run { + node.escapeState = EscapeState.GLOBAL_ESCAPE + node.value.node.escapeState = EscapeState.GLOBAL_ESCAPE + } + } + is DataFlowIR.Node.ArrayWrite -> { + connectObjects(node.array.node, node.value.node) + } + is DataFlowIR.Node.Variable -> { + node.values.forEach { + connectObjects(node, it.node) + } + } + is DataFlowIR.Node.ArrayRead -> { + // If element of array(return value) points to array(this value) and escapes then array also should escape. + if (((node.callee.pointsTo?.elementAtOrNull(node.callee.parameters.size) ?: 0) and (1 shl 0)) != 0) { + connectObjects(node, node.array.node) + } + } + is DataFlowIR.Node.Parameter -> { + node.escapeState = EscapeState.ARG_ESCAPE + } + } + } + + private inner class ConnectedObjectsVisitor { + val visitedObjects = mutableSetOf() + + fun visit(node: DataFlowIR.Node, action: (DataFlowIR.Node) -> Unit) { + action(node) + visitedObjects.add(node) + connectedObjects[node]?.forEach { + if (!visitedObjects.contains(it)) { + visit(it, action) + } + } + } + } + + private fun propagateState(state: EscapeState, visitor: ConnectedObjectsVisitor) { + connectedObjects.filter { it.key.escapeState == state }.forEach { (key, value) -> + value.forEach { obj -> + visitor.visit(obj) { it.escapeState = key.escapeState } + } + } + } + + fun analyze(lifetimes: MutableMap) { + function.body.forEachNonScopeNode { node -> + evaluateEscapeState(node) + } + function.body.returns.escapeState = EscapeState.ARG_ESCAPE + function.body.throws.escapeState = EscapeState.ARG_ESCAPE + + // Change state of connected objects. + val visitor = ConnectedObjectsVisitor() + propagateState(EscapeState.GLOBAL_ESCAPE, visitor) + propagateState(EscapeState.ARG_ESCAPE, visitor) + + nodesEscapeStates.filter { + it.value == EscapeState.NO_ESCAPE + }.forEach { (irNode, _) -> + val ir = when (irNode) { + is DataFlowIR.Node.Call -> irNode.irCallSite + else -> null + } + ir?.let { + lifetimes.put(it, Lifetime.STACK) + context.log { "$ir does not escape" } + } + } + } + } + + fun analyze(context: Context, moduleDFG: ModuleDFG, lifetimes: MutableMap) { + moduleDFG.functions.forEach { (name, function) -> + context.logMultiple { + +"===============================================" + +"Visiting $name" + +"DATA FLOW IR:" + +function.debugString() + } + FunctionAnalyzer(function, context).analyze(lifetimes) + } + } + + fun computeLifetimes(context: Context, moduleDFG: ModuleDFG, lifetimes: MutableMap) { + context.log { "In local EA" } + assert(lifetimes.isEmpty()) + analyze(context, moduleDFG, lifetimes) + } +} \ No newline at end of file diff --git a/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/serialization/IrSerializationUtil.kt b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/serialization/IrSerializationUtil.kt new file mode 100644 index 00000000000..614a67cd9f0 --- /dev/null +++ b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/serialization/IrSerializationUtil.kt @@ -0,0 +1,55 @@ +/* + * Copyright 2010-2017 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.jetbrains.kotlin.backend.konan.serialization + +import org.jetbrains.kotlin.backend.konan.descriptors.resolveFakeOverride +import org.jetbrains.kotlin.descriptors.* +import org.jetbrains.kotlin.ir.declarations.* +import org.jetbrains.kotlin.ir.util.resolveFakeOverride +import org.jetbrains.kotlin.resolve.OverridingUtil + +// TODO: move me somewhere + +/** + * Implementation of given method. + * + * TODO: this method is actually a part of resolve and probably duplicates another one + */ +internal fun IrSimpleFunction.resolveFakeOverrideMaybeAbstract() = this.resolveFakeOverride(allowAbstract = true)!! + +internal fun IrProperty.resolveFakeOverrideMaybeAbstract() = + this.getter!!.resolveFakeOverrideMaybeAbstract().correspondingPropertySymbol!!.owner + +internal fun IrField.resolveFakeOverrideMaybeAbstract() = + this.correspondingPropertySymbol!!.owner.resolveFakeOverrideMaybeAbstract().backingField + +/** + * Implementation of given method. + * + * TODO: this method is actually a part of resolve and probably duplicates another one + */ +internal fun T.resolveFakeOverrideMaybeAbstract(): Set { + if (this.kind.isReal) { + return setOf(this) + } else { + val overridden = OverridingUtil.getOverriddenDeclarations(this) + val filtered = OverridingUtil.filterOutOverridden(overridden) + // TODO: is it correct to take first? + @Suppress("UNCHECKED_CAST") + return filtered as Set + } +} diff --git a/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/serialization/KonanDeclarationTable.kt b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/serialization/KonanDeclarationTable.kt new file mode 100644 index 00000000000..a15fcbf129d --- /dev/null +++ b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/serialization/KonanDeclarationTable.kt @@ -0,0 +1,31 @@ +package org.jetbrains.kotlin.backend.konan.serialization + +import org.jetbrains.kotlin.backend.common.serialization.DeclarationTable +import org.jetbrains.kotlin.backend.common.serialization.GlobalDeclarationTable +import org.jetbrains.kotlin.backend.common.serialization.signature.DescToIrIdSignatureComputer +import org.jetbrains.kotlin.backend.common.serialization.signature.IdSignatureSerializer +import org.jetbrains.kotlin.backend.konan.descriptors.isFromInteropLibrary +import org.jetbrains.kotlin.ir.declarations.IrDeclaration + +import org.jetbrains.kotlin.ir.descriptors.IrBuiltIns +import org.jetbrains.kotlin.ir.util.IdSignature +import org.jetbrains.kotlin.resolve.descriptorUtil.module + +class KonanGlobalDeclarationTable(signatureSerializer: IdSignatureSerializer, builtIns: IrBuiltIns) : GlobalDeclarationTable(signatureSerializer, KonanManglerIr) { + init { + loadKnownBuiltins(builtIns) + } +} + +class KonanDeclarationTable( + globalDeclarationTable: GlobalDeclarationTable +) : DeclarationTable(globalDeclarationTable) { + + private val signatureIdComposer = DescToIrIdSignatureComputer(KonanIdSignaturer(KonanManglerDesc)) + + // TODO: We should get rid of this extension point in favor of proper support in IR-based mangler. + override fun tryComputeBackendSpecificSignature(declaration: IrDeclaration): IdSignature? = + if (declaration.descriptor.module.isFromInteropLibrary()) { + signatureIdComposer.computeSignature(declaration) + } else null +} \ No newline at end of file diff --git a/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/serialization/KonanIdSignaturer.kt b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/serialization/KonanIdSignaturer.kt new file mode 100644 index 00000000000..7833590597f --- /dev/null +++ b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/serialization/KonanIdSignaturer.kt @@ -0,0 +1,62 @@ +package org.jetbrains.kotlin.backend.konan.serialization + +import org.jetbrains.kotlin.backend.common.serialization.signature.IdSignatureDescriptor +import org.jetbrains.kotlin.backend.konan.descriptors.isFromInteropLibrary +import org.jetbrains.kotlin.descriptors.* +import org.jetbrains.kotlin.ir.util.IdSignature +import org.jetbrains.kotlin.ir.util.KotlinMangler +import org.jetbrains.kotlin.resolve.descriptorUtil.module + +class KonanIdSignaturer(private val mangler: KotlinMangler.DescriptorMangler) : IdSignatureDescriptor(mangler) { + + override fun createSignatureBuilder(): DescriptorBasedSignatureBuilder = + KonanDescriptorBasedSignatureBuilder(mangler) + + private class KonanDescriptorBasedSignatureBuilder( + mangler: KotlinMangler.DescriptorMangler + ) : DescriptorBasedSignatureBuilder(mangler) { + + /** + * We need a way to distinguish interop declarations from usual ones + * to be able to link against them. We do it by marking them with + * [IdSignature.Flags.IS_NATIVE_INTEROP_LIBRARY] flag. + */ + private fun markInteropDeclaration(descriptor: DeclarationDescriptor) { + if (descriptor.module.isFromInteropLibrary()) { + mask = mask or IdSignature.Flags.IS_NATIVE_INTEROP_LIBRARY.encode(true) + } + } + + override fun platformSpecificAlias(descriptor: TypeAliasDescriptor) { + markInteropDeclaration(descriptor) + } + + override fun platformSpecificClass(descriptor: ClassDescriptor) { + markInteropDeclaration(descriptor) + } + + override fun platformSpecificConstructor(descriptor: ConstructorDescriptor) { + markInteropDeclaration(descriptor) + } + + override fun platformSpecificFunction(descriptor: FunctionDescriptor) { + markInteropDeclaration(descriptor) + } + + override fun platformSpecificGetter(descriptor: PropertyGetterDescriptor) { + markInteropDeclaration(descriptor) + } + + override fun platformSpecificPackage(descriptor: PackageFragmentDescriptor) { + markInteropDeclaration(descriptor) + } + + override fun platformSpecificProperty(descriptor: PropertyDescriptor) { + markInteropDeclaration(descriptor) + } + + override fun platformSpecificSetter(descriptor: PropertySetterDescriptor) { + markInteropDeclaration(descriptor) + } + } +} \ No newline at end of file diff --git a/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/serialization/KonanIrFileSerializer.kt b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/serialization/KonanIrFileSerializer.kt new file mode 100644 index 00000000000..8e58c5b9e1f --- /dev/null +++ b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/serialization/KonanIrFileSerializer.kt @@ -0,0 +1,33 @@ +package org.jetbrains.kotlin.backend.konan.serialization + +import org.jetbrains.kotlin.backend.common.LoggingContext +import org.jetbrains.kotlin.backend.common.serialization.DeclarationTable +import org.jetbrains.kotlin.backend.common.serialization.IrFileSerializer +import org.jetbrains.kotlin.backend.konan.RuntimeNames +import org.jetbrains.kotlin.descriptors.DeclarationDescriptor +import org.jetbrains.kotlin.ir.declarations.IrAnnotationContainer +import org.jetbrains.kotlin.ir.declarations.IrClass +import org.jetbrains.kotlin.ir.declarations.IrFunction +import org.jetbrains.kotlin.ir.symbols.IrSymbol +import org.jetbrains.kotlin.ir.util.hasAnnotation + +class KonanIrFileSerializer( + logger: LoggingContext, + declarationTable: DeclarationTable, + expectDescriptorToSymbol: MutableMap, + skipExpects: Boolean, + bodiesOnlyForInlines: Boolean = false +): IrFileSerializer(logger, declarationTable, expectDescriptorToSymbol, skipExpects = skipExpects, bodiesOnlyForInlines = bodiesOnlyForInlines) { + + override fun backendSpecificExplicitRoot(node: IrAnnotationContainer): Boolean { + val fqn = when (node) { + is IrFunction -> RuntimeNames.exportForCppRuntime + is IrClass -> RuntimeNames.exportTypeInfoAnnotation + else -> return false + } + + return node.annotations.hasAnnotation(fqn) + } + + override fun backendSpecificSerializeAllMembers(irClass: IrClass) = !KonanFakeOverrideClassFilter.needToConstructFakeOverrides(irClass) +} \ No newline at end of file diff --git a/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/serialization/KonanIrModuleSerializer.kt b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/serialization/KonanIrModuleSerializer.kt new file mode 100644 index 00000000000..de9c7b4522c --- /dev/null +++ b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/serialization/KonanIrModuleSerializer.kt @@ -0,0 +1,33 @@ +package org.jetbrains.kotlin.backend.konan.serialization + +import org.jetbrains.kotlin.backend.common.LoggingContext +import org.jetbrains.kotlin.backend.common.serialization.* +import org.jetbrains.kotlin.backend.common.serialization.signature.IdSignatureSerializer +import org.jetbrains.kotlin.backend.konan.ir.interop.IrProviderForCEnumAndCStructStubs +import org.jetbrains.kotlin.descriptors.DeclarationDescriptor +import org.jetbrains.kotlin.ir.declarations.IrFile +import org.jetbrains.kotlin.ir.descriptors.IrBuiltIns +import org.jetbrains.kotlin.ir.symbols.IrSymbol + +class KonanIrModuleSerializer( + logger: LoggingContext, + irBuiltIns: IrBuiltIns, + private val expectDescriptorToSymbol: MutableMap, + val skipExpects: Boolean +) : IrModuleSerializer(logger) { + + private val signaturer = IdSignatureSerializer(KonanManglerIr) + private val globalDeclarationTable = KonanGlobalDeclarationTable(signaturer, irBuiltIns) + + // We skip files with IR for C structs and enums because they should be + // generated anew. + // + // See [IrProviderForCEnumAndCStructStubs.kt#L31] on why we generate IR. + // We may switch from IR generation to LazyIR later (at least for structs; enums are tricky) + // without changing kotlin libraries that depend on interop libraries. + override fun backendSpecificFileFilter(file: IrFile): Boolean = + file.fileEntry.name != IrProviderForCEnumAndCStructStubs.cTypeDefinitionsFileName + + override fun createSerializerForFile(file: IrFile): KonanIrFileSerializer = + KonanIrFileSerializer(logger, KonanDeclarationTable(globalDeclarationTable), expectDescriptorToSymbol, skipExpects = skipExpects) +} diff --git a/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/serialization/KonanIrlinker.kt b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/serialization/KonanIrlinker.kt new file mode 100644 index 00000000000..803dce00605 --- /dev/null +++ b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/serialization/KonanIrlinker.kt @@ -0,0 +1,228 @@ +/* + * Copyright 2010-2017 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.jetbrains.kotlin.backend.konan.serialization + +import org.jetbrains.kotlin.backend.common.LoggingContext +import org.jetbrains.kotlin.backend.common.overrides.FakeOverrideBuilder +import org.jetbrains.kotlin.backend.common.overrides.FakeOverrideClassFilter +import org.jetbrains.kotlin.backend.common.serialization.* +import org.jetbrains.kotlin.backend.common.serialization.encodings.BinarySymbolData +import org.jetbrains.kotlin.backend.common.serialization.signature.IdSignatureSerializer +import org.jetbrains.kotlin.backend.konan.CachedLibraries +import org.jetbrains.kotlin.backend.konan.descriptors.isInteropLibrary +import org.jetbrains.kotlin.backend.konan.descriptors.konanLibrary +import org.jetbrains.kotlin.backend.konan.ir.interop.IrProviderForCEnumAndCStructStubs +import org.jetbrains.kotlin.descriptors.* +import org.jetbrains.kotlin.descriptors.konan.isNativeStdlib +import org.jetbrains.kotlin.descriptors.konan.kotlinLibrary +import org.jetbrains.kotlin.ir.builders.TranslationPluginContext +import org.jetbrains.kotlin.ir.declarations.* +import org.jetbrains.kotlin.ir.declarations.impl.IrFileImpl +import org.jetbrains.kotlin.ir.declarations.impl.IrModuleFragmentImpl +import org.jetbrains.kotlin.ir.descriptors.IrAbstractFunctionFactory +import org.jetbrains.kotlin.ir.descriptors.IrBuiltIns +import org.jetbrains.kotlin.ir.symbols.IrSymbol +import org.jetbrains.kotlin.ir.symbols.impl.IrFileSymbolImpl +import org.jetbrains.kotlin.ir.symbols.impl.IrPublicSymbolBase +import org.jetbrains.kotlin.ir.types.classOrNull +import org.jetbrains.kotlin.ir.util.* +import org.jetbrains.kotlin.library.IrLibrary +import org.jetbrains.kotlin.library.KotlinLibrary +import org.jetbrains.kotlin.name.ClassId +import org.jetbrains.kotlin.name.FqName +import org.jetbrains.kotlin.name.Name +import org.jetbrains.kotlin.resolve.BindingContext +import org.jetbrains.kotlin.resolve.descriptorUtil.module + +object KonanFakeOverrideClassFilter : FakeOverrideClassFilter { + private fun IdSignature.isInteropSignature(): Boolean = with(this) { + IdSignature.Flags.IS_NATIVE_INTEROP_LIBRARY.test() + } + + // This is an alternative to .isObjCClass that doesn't need to walk up all the class heirarchy, + // rather it only looks at immediate super class symbols. + private fun IrClass.hasInteropSuperClass() = this.superTypes + .mapNotNull { it.classOrNull } + .filter { it is IrPublicSymbolBase<*> } + .any { it.signature?.isInteropSignature() ?: false } + + override fun needToConstructFakeOverrides(clazz: IrClass): Boolean { + return !clazz.hasInteropSuperClass() + } +} + +internal class KonanIrLinker( + private val currentModule: ModuleDescriptor, + override val functionalInterfaceFactory: IrAbstractFunctionFactory, + override val translationPluginContext: TranslationPluginContext?, + logger: LoggingContext, + builtIns: IrBuiltIns, + symbolTable: SymbolTable, + private val forwardModuleDescriptor: ModuleDescriptor?, + private val stubGenerator: DeclarationStubGenerator, + private val cenumsProvider: IrProviderForCEnumAndCStructStubs, + exportedDependencies: List, + deserializeFakeOverrides: Boolean, + private val cachedLibraries: CachedLibraries +) : KotlinIrLinker(currentModule, logger, builtIns, symbolTable, exportedDependencies, deserializeFakeOverrides) { + + companion object { + private val C_NAMES_NAME = Name.identifier("cnames") + private val OBJC_NAMES_NAME = Name.identifier("objcnames") + + val FORWARD_DECLARATION_ORIGIN = object : IrDeclarationOriginImpl("FORWARD_DECLARATION_ORIGIN") {} + + const val offset = SYNTHETIC_OFFSET + } + + override fun isBuiltInModule(moduleDescriptor: ModuleDescriptor): Boolean = moduleDescriptor.isNativeStdlib() + + private val forwardDeclarationDeserializer = forwardModuleDescriptor?.let { KonanForwardDeclarationModuleDeserializer(it) } + override val fakeOverrideBuilder = FakeOverrideBuilder(this, symbolTable, IdSignatureSerializer(KonanManglerIr), builtIns, KonanFakeOverrideClassFilter) + + override fun createModuleDeserializer(moduleDescriptor: ModuleDescriptor, klib: IrLibrary?, strategy: DeserializationStrategy): IrModuleDeserializer { + if (moduleDescriptor === forwardModuleDescriptor) { + return forwardDeclarationDeserializer ?: error("forward declaration deserializer expected") + } + + if (klib is KotlinLibrary && klib.isInteropLibrary()) { + val isCached = cachedLibraries.isLibraryCached(klib) + return KonanInteropModuleDeserializer(moduleDescriptor, isCached) + } + + return KonanModuleDeserializer(moduleDescriptor, klib ?: error("Expecting kotlin library"), strategy) + } + + private inner class KonanModuleDeserializer(moduleDescriptor: ModuleDescriptor, klib: IrLibrary, strategy: DeserializationStrategy): + KotlinIrLinker.BasicIrModuleDeserializer(moduleDescriptor, klib, strategy) + + private inner class KonanInteropModuleDeserializer( + moduleDescriptor: ModuleDescriptor, + private val isLibraryCached: Boolean + ) : IrModuleDeserializer(moduleDescriptor) { + init { + assert(moduleDescriptor.kotlinLibrary.isInteropLibrary()) + } + + private val descriptorByIdSignatureFinder = DescriptorByIdSignatureFinder( + moduleDescriptor, KonanManglerDesc, + DescriptorByIdSignatureFinder.LookupMode.MODULE_ONLY + ) + private fun IdSignature.isInteropSignature(): Boolean = IdSignature.Flags.IS_NATIVE_INTEROP_LIBRARY.test() + + override fun contains(idSig: IdSignature): Boolean { + if (idSig.isPublic) { + if (idSig.isInteropSignature()) { + // TODO: add descriptor cache?? + return descriptorByIdSignatureFinder.findDescriptorBySignature(idSig) != null + } + } + + return false + } + + private fun DeclarationDescriptor.isCEnumsOrCStruct(): Boolean = cenumsProvider.isCEnumOrCStruct(this) + + private val fileMap = mutableMapOf() + + private fun getIrFile(packageFragment: PackageFragmentDescriptor): IrFile = fileMap.getOrPut(packageFragment) { + IrFileImpl(NaiveSourceBasedFileEntryImpl(IrProviderForCEnumAndCStructStubs.cTypeDefinitionsFileName), packageFragment).also { + moduleFragment.files.add(it) + } + } + + private fun resolveCEnumsOrStruct(descriptor: DeclarationDescriptor, idSig: IdSignature, symbolKind: BinarySymbolData.SymbolKind): IrSymbol { + val file = getIrFile(descriptor.findPackage()) + return cenumsProvider.getDeclaration(descriptor, idSig, file, symbolKind).symbol + } + + override fun deserializeIrSymbol(idSig: IdSignature, symbolKind: BinarySymbolData.SymbolKind): IrSymbol { + val descriptor = descriptorByIdSignatureFinder.findDescriptorBySignature(idSig) ?: error("Expecting descriptor for $idSig") + // If library is cached we don't need to create an IrClass for struct or enum. + if (!isLibraryCached && descriptor.isCEnumsOrCStruct()) return resolveCEnumsOrStruct(descriptor, idSig, symbolKind) + + val symbolOwner = stubGenerator.generateMemberStub(descriptor) as IrSymbolOwner + + return symbolOwner.symbol + } + + override val moduleFragment: IrModuleFragment = IrModuleFragmentImpl(moduleDescriptor, builtIns) + override val moduleDependencies: Collection = listOfNotNull(forwardDeclarationDeserializer) + } + + private inner class KonanForwardDeclarationModuleDeserializer(moduleDescriptor: ModuleDescriptor) : IrModuleDeserializer(moduleDescriptor) { + init { + assert(moduleDescriptor.isForwardDeclarationModule) + } + + private val declaredDeclaration = mutableMapOf() + + private fun IdSignature.isForwardDeclarationSignature(): Boolean { + if (isPublic) { + return packageFqName().run { + startsWith(C_NAMES_NAME) || startsWith(OBJC_NAMES_NAME) + } + } + + return false + } + + override fun contains(idSig: IdSignature): Boolean = idSig.isForwardDeclarationSignature() + + private fun resolveDescriptor(idSig: IdSignature): ClassDescriptor = + with(idSig as IdSignature.PublicSignature) { + val classId = ClassId(packageFqName(), FqName(declarationFqName), false) + moduleDescriptor.findClassAcrossModuleDependencies(classId) ?: error("No declaration found with $idSig") + } + + private fun buildForwardDeclarationStub(descriptor: ClassDescriptor): IrClass { + return stubGenerator.generateClassStub(descriptor).also { + it.origin = FORWARD_DECLARATION_ORIGIN + } + } + + override fun deserializeIrSymbol(idSig: IdSignature, symbolKind: BinarySymbolData.SymbolKind): IrSymbol { + assert(symbolKind == BinarySymbolData.SymbolKind.CLASS_SYMBOL) { "Only class could be a Forward declaration $idSig (kind $symbolKind)" } + val descriptor = resolveDescriptor(idSig) + val actualModule = descriptor.module + if (actualModule !== moduleDescriptor) { + val moduleDeserializer = deserializersForModules[actualModule] ?: error("No module deserializer for $actualModule") + moduleDeserializer.addModuleReachableTopLevel(idSig) + return symbolTable.referenceClassFromLinker(descriptor, idSig) + } + + return declaredDeclaration.getOrPut(idSig) { buildForwardDeclarationStub(descriptor) }.symbol + } + + override val moduleFragment: IrModuleFragment = IrModuleFragmentImpl(moduleDescriptor, builtIns) + override val moduleDependencies: Collection = emptyList() + } + + val modules: Map + get() = mutableMapOf().apply { + deserializersForModules + .filter { !it.key.isForwardDeclarationModule && it.value.moduleDescriptor !== currentModule } + .forEach { this.put(it.key.konanLibrary!!.libraryName, it.value.moduleFragment) } + } + class KonanPluginContext( + override val moduleDescriptor: ModuleDescriptor, + override val bindingContext: BindingContext, + override val symbolTable: ReferenceSymbolTable, + override val typeTranslator: TypeTranslator, + override val irBuiltIns: IrBuiltIns + ):TranslationPluginContext +} diff --git a/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/serialization/KonanMangler.kt b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/serialization/KonanMangler.kt new file mode 100644 index 00000000000..bb1c78033e2 --- /dev/null +++ b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/serialization/KonanMangler.kt @@ -0,0 +1,148 @@ +package org.jetbrains.kotlin.backend.konan.serialization + +import org.jetbrains.kotlin.backend.common.serialization.mangle.MangleMode +import org.jetbrains.kotlin.backend.common.serialization.mangle.descriptor.DescriptorBasedKotlinManglerImpl +import org.jetbrains.kotlin.backend.common.serialization.mangle.descriptor.DescriptorExportCheckerVisitor +import org.jetbrains.kotlin.backend.common.serialization.mangle.descriptor.DescriptorMangleComputer +import org.jetbrains.kotlin.backend.common.serialization.mangle.ir.IrBasedKotlinManglerImpl +import org.jetbrains.kotlin.backend.common.serialization.mangle.ir.IrExportCheckerVisitor +import org.jetbrains.kotlin.backend.common.serialization.mangle.ir.IrMangleComputer +import org.jetbrains.kotlin.backend.konan.* +import org.jetbrains.kotlin.descriptors.* +import org.jetbrains.kotlin.ir.declarations.* +import org.jetbrains.kotlin.ir.types.getClass +import org.jetbrains.kotlin.ir.util.hasAnnotation + +abstract class AbstractKonanIrMangler(private val withReturnType: Boolean) : IrBasedKotlinManglerImpl() { + override fun getExportChecker(): IrExportCheckerVisitor = KonanIrExportChecker() + + override fun getMangleComputer(mode: MangleMode): IrMangleComputer = + KonanIrManglerComputer(StringBuilder(256), mode, withReturnType) + + private class KonanIrExportChecker : IrExportCheckerVisitor() { + override fun IrDeclaration.isPlatformSpecificExported(): Boolean { + if (this is IrSimpleFunction) if (isFakeOverride) return false + + // TODO: revise + if (annotations.hasAnnotation(RuntimeNames.symbolNameAnnotation)) { + // Treat any `@SymbolName` declaration as exported. + return true + } + if (annotations.hasAnnotation(RuntimeNames.exportForCppRuntime)) { + // Treat any `@ExportForCppRuntime` declaration as exported. + return true + } + if (annotations.hasAnnotation(RuntimeNames.cnameAnnotation)) { + // Treat `@CName` declaration as exported. + return true + } + if (annotations.hasAnnotation(RuntimeNames.exportForCompilerAnnotation)) { + return true + } + + return false + } + } + + private class KonanIrManglerComputer(builder: StringBuilder, mode: MangleMode, private val withReturnType: Boolean) : IrMangleComputer(builder, mode) { + override fun copy(newMode: MangleMode): IrMangleComputer = KonanIrManglerComputer(builder, newMode, withReturnType) + + override fun addReturnType(): Boolean = withReturnType + + override fun IrFunction.platformSpecificFunctionName(): String? { + (if (this is IrConstructor && this.isObjCConstructor) this.getObjCInitMethod() else this)?.getObjCMethodInfo() + ?.let { + return buildString { + if (extensionReceiverParameter != null) { + append(extensionReceiverParameter!!.type.getClass()!!.name) + append(".") + } + + append("objc:") + append(it.selector) + if (this@platformSpecificFunctionName is IrConstructor && this@platformSpecificFunctionName.isObjCConstructor) append("#Constructor") + + if ((this@platformSpecificFunctionName as? IrSimpleFunction)?.correspondingPropertySymbol != null) { + append("#Accessor") + } + } + } + return null + } + + override fun IrFunction.specialValueParamPrefix(param: IrValueParameter): String { + // TODO: there are clashes originating from ObjectiveC interop. + // kotlinx.cinterop.ObjCClassOf.create(format: kotlin.String): T defined in platform.Foundation in file Foundation.kt + // and + // kotlinx.cinterop.ObjCClassOf.create(string: kotlin.String): T defined in platform.Foundation in file Foundation.kt + + return if (this.hasObjCMethodAnnotation || this.hasObjCFactoryAnnotation || this.isObjCClassMethod()) "${param.name}:" else "" + } + } +} + +object KonanManglerIr : AbstractKonanIrMangler(false) + +abstract class AbstractKonanDescriptorMangler : DescriptorBasedKotlinManglerImpl() { + override fun getExportChecker(): DescriptorExportCheckerVisitor = KonanDescriptorExportChecker() + + override fun getMangleComputer(mode: MangleMode): DescriptorMangleComputer = + KonanDescriptorMangleComputer(StringBuilder(256), mode) + + private class KonanDescriptorExportChecker : DescriptorExportCheckerVisitor() { + override fun DeclarationDescriptor.isPlatformSpecificExported(): Boolean { + if (this is SimpleFunctionDescriptor) { + if (kind == CallableMemberDescriptor.Kind.FAKE_OVERRIDE) return false + } + // TODO: revise + if (annotations.hasAnnotation(RuntimeNames.symbolNameAnnotation)) { + // Treat any `@SymbolName` declaration as exported. + return true + } + if (annotations.hasAnnotation(RuntimeNames.exportForCppRuntime)) { + // Treat any `@ExportForCppRuntime` declaration as exported. + return true + } + if (annotations.hasAnnotation(RuntimeNames.cnameAnnotation)) { + // Treat `@CName` declaration as exported. + return true + } + if (annotations.hasAnnotation(RuntimeNames.exportForCompilerAnnotation)) { + return true + } + + return false + } + } + + private class KonanDescriptorMangleComputer(builder: StringBuilder, mode: MangleMode) : DescriptorMangleComputer(builder, mode) { + override fun copy(newMode: MangleMode): DescriptorMangleComputer = KonanDescriptorMangleComputer(builder, newMode) + + override fun FunctionDescriptor.platformSpecificFunctionName(): String? { + (if (this is ConstructorDescriptor && this.isObjCConstructor) this.getObjCInitMethod() else this)?.getObjCMethodInfo() + ?.let { + return buildString { + if (extensionReceiverParameter != null) { + append(extensionReceiverParameter!!.type.constructor.declarationDescriptor!!.name) + append(".") + } + + append("objc:") + append(it.selector) + if (this@platformSpecificFunctionName is ConstructorDescriptor && this@platformSpecificFunctionName.isObjCConstructor) append("#Constructor") + + if (this@platformSpecificFunctionName is PropertyAccessorDescriptor) { + append("#Accessor") + } + } + } + return null + } + + override fun FunctionDescriptor.specialValueParamPrefix(param: ValueParameterDescriptor): String { + return if (this.hasObjCMethodAnnotation || this.hasObjCFactoryAnnotation || this.isObjCClassMethod()) "${param.name}:" else "" + } + } +} + +object KonanManglerDesc : AbstractKonanDescriptorMangler() \ No newline at end of file diff --git a/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/serialization/StringTableUtil.kt b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/serialization/StringTableUtil.kt new file mode 100644 index 00000000000..1c741d3ede0 --- /dev/null +++ b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/serialization/StringTableUtil.kt @@ -0,0 +1,35 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +package org.jetbrains.kotlin.backend.konan.serialization + +import org.jetbrains.kotlin.descriptors.* +import org.jetbrains.kotlin.name.FqName +import org.jetbrains.kotlin.metadata.ProtoBuf +import org.jetbrains.kotlin.metadata.ProtoBuf.QualifiedNameTable.QualifiedName +import org.jetbrains.kotlin.metadata.deserialization.NameResolverImpl +import org.jetbrains.kotlin.serialization.deserialization.getClassId + +// TODO Come up with a better file name. + +internal fun NameResolverImpl.getDescriptorByFqNameIndex( + module: ModuleDescriptor, + nameTable: ProtoBuf.QualifiedNameTable, + fqNameIndex: Int): DeclarationDescriptor { + + if (fqNameIndex == -1) return module.getPackage(FqName.ROOT) + val packageName = this.getPackageFqName(fqNameIndex) + // TODO: Here we are using internals of NameresolverImpl. + // Consider extending NameResolver. + val proto = nameTable.getQualifiedName(fqNameIndex) + when (proto.kind!!) { + QualifiedName.Kind.CLASS, + QualifiedName.Kind.LOCAL -> + return module.findClassAcrossModuleDependencies(this.getClassId(fqNameIndex))!! + QualifiedName.Kind.PACKAGE -> + return module.getPackage(FqName(packageName)) + } +} + diff --git a/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/serialization/google_descriptor.proto1 b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/serialization/google_descriptor.proto1 new file mode 100644 index 00000000000..8e10c6e69c1 --- /dev/null +++ b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/serialization/google_descriptor.proto1 @@ -0,0 +1,621 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// http://code.google.com/p/protobuf/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +// Author: kenton@google.com (Kenton Varda) +// Based on original Protocol Buffers design by +// Sanjay Ghemawat, Jeff Dean, and others. +// +// The messages in this file describe the definitions found in .proto files. +// A valid .proto file can be translated directly to a FileDescriptorProto +// without any other information (e.g. without reading its imports). + + + +syntax = "proto2"; +package google.protobuf; +option java_package = "com.google.protobuf"; +option java_outer_classname = "DescriptorProtos"; + +// descriptor.proto must be optimized for speed because reflection-based +// algorithms don't work during bootstrapping. +option optimize_for = SPEED; + +// The protocol compiler can output a FileDescriptorSet containing the .proto +// files it parses. +message FileDescriptorSet { + repeated FileDescriptorProto file = 1; +} + +// Describes a complete .proto file. +message FileDescriptorProto { + optional string name = 1; // file name, relative to root of source tree + optional string package = 2; // e.g. "foo", "foo.bar", etc. + + // Names of files imported by this file. + repeated string dependency = 3; + // Indexes of the public imported files in the dependency list above. + repeated int32 public_dependency = 10; + // Indexes of the weak imported files in the dependency list. + // For Google-internal migration only. Do not use. + repeated int32 weak_dependency = 11; + + // All top-level definitions in this file. + repeated DescriptorProto message_type = 4; + repeated EnumDescriptorProto enum_type = 5; + repeated ServiceDescriptorProto service = 6; + repeated FieldDescriptorProto extension = 7; + + optional FileOptions options = 8; + + // This field contains optional information about the original source code. + // You may safely remove this entire field whithout harming runtime + // functionality of the descriptors -- the information is needed only by + // development tools. + optional SourceCodeInfo source_code_info = 9; +} + +// Describes a message type. +message DescriptorProto { + optional string name = 1; + + repeated FieldDescriptorProto field = 2; + repeated FieldDescriptorProto extension = 6; + + repeated DescriptorProto nested_type = 3; + repeated EnumDescriptorProto enum_type = 4; + + message ExtensionRange { + optional int32 start = 1; + optional int32 end = 2; + } + repeated ExtensionRange extension_range = 5; + + optional MessageOptions options = 7; +} + +// Describes a field within a message. +message FieldDescriptorProto { + enum Type { + // 0 is reserved for errors. + // Order is weird for historical reasons. + TYPE_DOUBLE = 1; + TYPE_FLOAT = 2; + // Not ZigZag encoded. Negative numbers take 10 bytes. Use TYPE_SINT64 if + // negative values are likely. + TYPE_INT64 = 3; + TYPE_UINT64 = 4; + // Not ZigZag encoded. Negative numbers take 10 bytes. Use TYPE_SINT32 if + // negative values are likely. + TYPE_INT32 = 5; + TYPE_FIXED64 = 6; + TYPE_FIXED32 = 7; + TYPE_BOOL = 8; + TYPE_STRING = 9; + TYPE_GROUP = 10; // Tag-delimited aggregate. + TYPE_MESSAGE = 11; // Length-delimited aggregate. + + // New in version 2. + TYPE_BYTES = 12; + TYPE_UINT32 = 13; + TYPE_ENUM = 14; + TYPE_SFIXED32 = 15; + TYPE_SFIXED64 = 16; + TYPE_SINT32 = 17; // Uses ZigZag encoding. + TYPE_SINT64 = 18; // Uses ZigZag encoding. + }; + + enum Label { + // 0 is reserved for errors + LABEL_OPTIONAL = 1; + LABEL_REQUIRED = 2; + LABEL_REPEATED = 3; + // TODO(sanjay): Should we add LABEL_MAP? + }; + + optional string name = 1; + optional int32 number = 3; + optional Label label = 4; + + // If type_name is set, this need not be set. If both this and type_name + // are set, this must be either TYPE_ENUM or TYPE_MESSAGE. + optional Type type = 5; + + // For message and enum types, this is the name of the type. If the name + // starts with a '.', it is fully-qualified. Otherwise, C++-like scoping + // rules are used to find the type (i.e. first the nested types within this + // message are searched, then within the parent, on up to the root + // namespace). + optional string type_name = 6; + + // For extensions, this is the name of the type being extended. It is + // resolved in the same manner as type_name. + optional string extendee = 2; + + // For numeric types, contains the original text representation of the value. + // For booleans, "true" or "false". + // For strings, contains the default text contents (not escaped in any way). + // For bytes, contains the C escaped value. All bytes >= 128 are escaped. + // TODO(kenton): Base-64 encode? + optional string default_value = 7; + + optional FieldOptions options = 8; +} + +// Describes an enum type. +message EnumDescriptorProto { + optional string name = 1; + + repeated EnumValueDescriptorProto value = 2; + + optional EnumOptions options = 3; +} + +// Describes a value within an enum. +message EnumValueDescriptorProto { + optional string name = 1; + optional int32 number = 2; + + optional EnumValueOptions options = 3; +} + +// Describes a service. +message ServiceDescriptorProto { + optional string name = 1; + repeated MethodDescriptorProto method = 2; + + optional ServiceOptions options = 3; +} + +// Describes a method of a service. +message MethodDescriptorProto { + optional string name = 1; + + // Input and output type names. These are resolved in the same way as + // FieldDescriptorProto.type_name, but must refer to a message type. + optional string input_type = 2; + optional string output_type = 3; + + optional MethodOptions options = 4; +} + + +// =================================================================== +// Options + +// Each of the definitions above may have "options" attached. These are +// just annotations which may cause code to be generated slightly differently +// or may contain hints for code that manipulates protocol messages. +// +// Clients may define custom options as extensions of the *Options messages. +// These extensions may not yet be known at parsing time, so the parser cannot +// store the values in them. Instead it stores them in a field in the *Options +// message called uninterpreted_option. This field must have the same name +// across all *Options messages. We then use this field to populate the +// extensions when we build a descriptor, at which point all protos have been +// parsed and so all extensions are known. +// +// Extension numbers for custom options may be chosen as follows: +// * For options which will only be used within a single application or +// organization, or for experimental options, use field numbers 50000 +// through 99999. It is up to you to ensure that you do not use the +// same number for multiple options. +// * For options which will be published and used publicly by multiple +// independent entities, e-mail protobuf-global-extension-registry@google.com +// to reserve extension numbers. Simply provide your project name (e.g. +// Object-C plugin) and your porject website (if available) -- there's no need +// to explain how you intend to use them. Usually you only need one extension +// number. You can declare multiple options with only one extension number by +// putting them in a sub-message. See the Custom Options section of the docs +// for examples: +// http://code.google.com/apis/protocolbuffers/docs/proto.html#options +// If this turns out to be popular, a web service will be set up +// to automatically assign option numbers. + + +message FileOptions { + + // Sets the Java package where classes generated from this .proto will be + // placed. By default, the proto package is used, but this is often + // inappropriate because proto packages do not normally start with backwards + // domain names. + optional string java_package = 1; + + + // If set, all the classes from the .proto file are wrapped in a single + // outer class with the given name. This applies to both Proto1 + // (equivalent to the old "--one_java_file" option) and Proto2 (where + // a .proto always translates to a single class, but you may want to + // explicitly choose the class name). + optional string java_outer_classname = 8; + + // If set true, then the Java code generator will generate a separate .java + // file for each top-level message, enum, and service defined in the .proto + // file. Thus, these types will *not* be nested inside the outer class + // named by java_outer_classname. However, the outer class will still be + // generated to contain the file's getDescriptor() method as well as any + // top-level extensions defined in the file. + optional bool java_multiple_files = 10 [default=false]; + + // If set true, then the Java code generator will generate equals() and + // hashCode() methods for all messages defined in the .proto file. This is + // purely a speed optimization, as the AbstractMessage base class includes + // reflection-based implementations of these methods. + optional bool java_generate_equals_and_hash = 20 [default=false]; + + // Generated classes can be optimized for speed or code size. + enum OptimizeMode { + SPEED = 1; // Generate complete code for parsing, serialization, + // etc. + CODE_SIZE = 2; // Use ReflectionOps to implement these methods. + LITE_RUNTIME = 3; // Generate code using MessageLite and the lite runtime. + } + optional OptimizeMode optimize_for = 9 [default=SPEED]; + + // Sets the Go package where structs generated from this .proto will be + // placed. There is no default. + optional string go_package = 11; + + + + // Should generic services be generated in each language? "Generic" services + // are not specific to any particular RPC system. They are generated by the + // main code generators in each language (without additional plugins). + // Generic services were the only kind of service generation supported by + // early versions of proto2. + // + // Generic services are now considered deprecated in favor of using plugins + // that generate code specific to your particular RPC system. Therefore, + // these default to false. Old code which depends on generic services should + // explicitly set them to true. + optional bool cc_generic_services = 16 [default=false]; + optional bool java_generic_services = 17 [default=false]; + optional bool py_generic_services = 18 [default=false]; + + // The parser stores options it doesn't recognize here. See above. + repeated UninterpretedOption uninterpreted_option = 999; + + // Clients can define custom options in extensions of this message. See above. + extensions 1000 to max; +} + +message MessageOptions { + // Set true to use the old proto1 MessageSet wire format for extensions. + // This is provided for backwards-compatibility with the MessageSet wire + // format. You should not use this for any other reason: It's less + // efficient, has fewer features, and is more complicated. + // + // The message must be defined exactly as follows: + // message Foo { + // option message_set_wire_format = true; + // extensions 4 to max; + // } + // Note that the message cannot have any defined fields; MessageSets only + // have extensions. + // + // All extensions of your type must be singular messages; e.g. they cannot + // be int32s, enums, or repeated messages. + // + // Because this is an option, the above two restrictions are not enforced by + // the protocol compiler. + optional bool message_set_wire_format = 1 [default=false]; + + // Disables the generation of the standard "descriptor()" accessor, which can + // conflict with a field of the same name. This is meant to make migration + // from proto1 easier; new code should avoid fields named "descriptor". + optional bool no_standard_descriptor_accessor = 2 [default=false]; + + // The parser stores options it doesn't recognize here. See above. + repeated UninterpretedOption uninterpreted_option = 999; + + // Clients can define custom options in extensions of this message. See above. + extensions 1000 to max; +} + +message FieldOptions { + // The ctype option instructs the C++ code generator to use a different + // representation of the field than it normally would. See the specific + // options below. This option is not yet implemented in the open source + // release -- sorry, we'll try to include it in a future version! + optional CType ctype = 1 [default = STRING]; + enum CType { + // Default mode. + STRING = 0; + + CORD = 1; + + STRING_PIECE = 2; + } + // The packed option can be enabled for repeated primitive fields to enable + // a more efficient representation on the wire. Rather than repeatedly + // writing the tag and type for each element, the entire array is encoded as + // a single length-delimited blob. + optional bool packed = 2; + + + + // Should this field be parsed lazily? Lazy applies only to message-type + // fields. It means that when the outer message is initially parsed, the + // inner message's contents will not be parsed but instead stored in encoded + // form. The inner message will actually be parsed when it is first accessed. + // + // This is only a hint. Implementations are free to choose whether to use + // eager or lazy parsing regardless of the value of this option. However, + // setting this option true suggests that the protocol author believes that + // using lazy parsing on this field is worth the additional bookkeeping + // overhead typically needed to implement it. + // + // This option does not affect the public interface of any generated code; + // all method signatures remain the same. Furthermore, thread-safety of the + // interface is not affected by this option; const methods remain safe to + // call from multiple threads concurrently, while non-const methods continue + // to require exclusive access. + // + // + // Note that implementations may choose not to check required fields within + // a lazy sub-message. That is, calling IsInitialized() on the outher message + // may return true even if the inner message has missing required fields. + // This is necessary because otherwise the inner message would have to be + // parsed in order to perform the check, defeating the purpose of lazy + // parsing. An implementation which chooses not to check required fields + // must be consistent about it. That is, for any particular sub-message, the + // implementation must either *always* check its required fields, or *never* + // check its required fields, regardless of whether or not the message has + // been parsed. + optional bool lazy = 5 [default=false]; + + // Is this field deprecated? + // Depending on the target platform, this can emit Deprecated annotations + // for accessors, or it will be completely ignored; in the very least, this + // is a formalization for deprecating fields. + optional bool deprecated = 3 [default=false]; + + // EXPERIMENTAL. DO NOT USE. + // For "map" fields, the name of the field in the enclosed type that + // is the key for this map. For example, suppose we have: + // message Item { + // required string name = 1; + // required string value = 2; + // } + // message Config { + // repeated Item items = 1 [experimental_map_key="name"]; + // } + // In this situation, the map key for Item will be set to "name". + // TODO: Fully-implement this, then remove the "experimental_" prefix. + optional string experimental_map_key = 9; + + // For Google-internal migration only. Do not use. + optional bool weak = 10 [default=false]; + + // The parser stores options it doesn't recognize here. See above. + repeated UninterpretedOption uninterpreted_option = 999; + + // Clients can define custom options in extensions of this message. See above. + extensions 1000 to max; +} + +message EnumOptions { + + // Set this option to false to disallow mapping different tag names to a same + // value. + optional bool allow_alias = 2 [default=true]; + + // The parser stores options it doesn't recognize here. See above. + repeated UninterpretedOption uninterpreted_option = 999; + + // Clients can define custom options in extensions of this message. See above. + extensions 1000 to max; +} + +message EnumValueOptions { + // The parser stores options it doesn't recognize here. See above. + repeated UninterpretedOption uninterpreted_option = 999; + + // Clients can define custom options in extensions of this message. See above. + extensions 1000 to max; +} + +message ServiceOptions { + + // Note: Field numbers 1 through 32 are reserved for Google's internal RPC + // framework. We apologize for hoarding these numbers to ourselves, but + // we were already using them long before we decided to release Protocol + // Buffers. + + // The parser stores options it doesn't recognize here. See above. + repeated UninterpretedOption uninterpreted_option = 999; + + // Clients can define custom options in extensions of this message. See above. + extensions 1000 to max; +} + +message MethodOptions { + + // Note: Field numbers 1 through 32 are reserved for Google's internal RPC + // framework. We apologize for hoarding these numbers to ourselves, but + // we were already using them long before we decided to release Protocol + // Buffers. + + // The parser stores options it doesn't recognize here. See above. + repeated UninterpretedOption uninterpreted_option = 999; + + // Clients can define custom options in extensions of this message. See above. + extensions 1000 to max; +} + + +// A message representing a option the parser does not recognize. This only +// appears in options protos created by the compiler::Parser class. +// DescriptorPool resolves these when building Descriptor objects. Therefore, +// options protos in descriptor objects (e.g. returned by Descriptor::options(), +// or produced by Descriptor::CopyTo()) will never have UninterpretedOptions +// in them. +message UninterpretedOption { + // The name of the uninterpreted option. Each string represents a segment in + // a dot-separated name. is_extension is true iff a segment represents an + // extension (denoted with parentheses in options specs in .proto files). + // E.g.,{ ["foo", false], ["bar.baz", true], ["qux", false] } represents + // "foo.(bar.baz).qux". + message NamePart { + required string name_part = 1; + required bool is_extension = 2; + } + repeated NamePart name = 2; + + // The value of the uninterpreted option, in whatever type the tokenizer + // identified it as during parsing. Exactly one of these should be set. + optional string identifier_value = 3; + optional uint64 positive_int_value = 4; + optional int64 negative_int_value = 5; + optional double double_value = 6; + optional bytes string_value = 7; + optional string aggregate_value = 8; +} + +// =================================================================== +// Optional source code info + +// Encapsulates information about the original source file from which a +// FileDescriptorProto was generated. +message SourceCodeInfo { + // A Location identifies a piece of source code in a .proto file which + // corresponds to a particular definition. This information is intended + // to be useful to IDEs, code indexers, documentation generators, and similar + // tools. + // + // For example, say we have a file like: + // message Foo { + // optional string foo = 1; + // } + // Let's look at just the field definition: + // optional string foo = 1; + // ^ ^^ ^^ ^ ^^^ + // a bc de f ghi + // We have the following locations: + // span path represents + // [a,i) [ 4, 0, 2, 0 ] The whole field definition. + // [a,b) [ 4, 0, 2, 0, 4 ] The label (optional). + // [c,d) [ 4, 0, 2, 0, 5 ] The type (string). + // [e,f) [ 4, 0, 2, 0, 1 ] The name (foo). + // [g,h) [ 4, 0, 2, 0, 3 ] The number (1). + // + // Notes: + // - A location may refer to a repeated field itself (i.e. not to any + // particular index within it). This is used whenever a set of elements are + // logically enclosed in a single code segment. For example, an entire + // extend block (possibly containing multiple extension definitions) will + // have an outer location whose path refers to the "extensions" repeated + // field without an index. + // - Multiple locations may have the same path. This happens when a single + // logical declaration is spread out across multiple places. The most + // obvious example is the "extend" block again -- there may be multiple + // extend blocks in the same scope, each of which will have the same path. + // - A location's span is not always a subset of its parent's span. For + // example, the "extendee" of an extension declaration appears at the + // beginning of the "extend" block and is shared by all extensions within + // the block. + // - Just because a location's span is a subset of some other location's span + // does not mean that it is a descendent. For example, a "group" defines + // both a type and a field in a single declaration. Thus, the locations + // corresponding to the type and field and their components will overlap. + // - Code which tries to interpret locations should probably be designed to + // ignore those that it doesn't understand, as more types of locations could + // be recorded in the future. + repeated Location location = 1; + message Location { + // Identifies which part of the FileDescriptorProto was defined at this + // location. + // + // Each element is a field number or an index. They form a path from + // the root FileDescriptorProto to the place where the definition. For + // example, this path: + // [ 4, 3, 2, 7, 1 ] + // refers to: + // file.message_type(3) // 4, 3 + // .field(7) // 2, 7 + // .name() // 1 + // This is because FileDescriptorProto.message_type has field number 4: + // repeated DescriptorProto message_type = 4; + // and DescriptorProto.field has field number 2: + // repeated FieldDescriptorProto field = 2; + // and FieldDescriptorProto.name has field number 1: + // optional string name = 1; + // + // Thus, the above path gives the location of a field name. If we removed + // the last element: + // [ 4, 3, 2, 7 ] + // this path refers to the whole field declaration (from the beginning + // of the label to the terminating semicolon). + repeated int32 path = 1 [packed=true]; + + // Always has exactly three or four elements: start line, start column, + // end line (optional, otherwise assumed same as start line), end column. + // These are packed into a single field for efficiency. Note that line + // and column numbers are zero-based -- typically you will want to add + // 1 to each before displaying to a user. + repeated int32 span = 2 [packed=true]; + + // If this SourceCodeInfo represents a complete declaration, these are any + // comments appearing before and after the declaration which appear to be + // attached to the declaration. + // + // A series of line comments appearing on consecutive lines, with no other + // tokens appearing on those lines, will be treated as a single comment. + // + // Only the comment content is provided; comment markers (e.g. //) are + // stripped out. For block comments, leading whitespace and an asterisk + // will be stripped from the beginning of each line other than the first. + // Newlines are included in the output. + // + // Examples: + // + // optional int32 foo = 1; // Comment attached to foo. + // // Comment attached to bar. + // optional int32 bar = 2; + // + // optional string baz = 3; + // // Comment attached to baz. + // // Another line attached to baz. + // + // // Comment attached to qux. + // // + // // Another line attached to qux. + // optional double qux = 4; + // + // optional string corge = 5; + // /* Block comment attached + // * to corge. Leading asterisks + // * will be removed. */ + // /* Block comment attached to + // * grault. */ + // optional int32 grault = 6; + optional string leading_comments = 3; + optional string trailing_comments = 4; + } +} diff --git a/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/util/PrimitiveLists.kt b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/util/PrimitiveLists.kt new file mode 100644 index 00000000000..09c87411b88 --- /dev/null +++ b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/util/PrimitiveLists.kt @@ -0,0 +1,106 @@ +/* + * Copyright 2010-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +package org.jetbrains.kotlin.backend.konan.util + +class IntArrayList : Iterable { + private var array = IntArray(3) + private var length = 0 + + val size get() = length + + fun isEmpty() = size == 0 + + fun add(x: Int) { + length++ + ensureCapacity(length) + set(length - 1, x) + } + + fun reserve(minSize: Int) { + if (length >= minSize) return + length = minSize + ensureCapacity(minSize) + } + + operator fun get(index: Int): Int = when { + index < 0 || index >= length -> throw IndexOutOfBoundsException("Index out of range: $index") + + else -> array[index] + } + + operator fun set(index: Int, x: Int) = when { + index < 0 || index >= length -> throw IndexOutOfBoundsException("Index out of range: $index") + + else -> array[index] = x + } + + override operator fun iterator(): Iterator = Itr() + + private fun ensureCapacity(minCapacity: Int) { + val oldArray = array + if (minCapacity > oldArray.size) { + var newSize = oldArray.size * 3 / 2 + if (minCapacity > newSize) + newSize = minCapacity + array = oldArray.copyOf(newSize) + } + } + + private inner class Itr : Iterator { + private var index = 0 + + override fun hasNext() = index < size + + override fun next() = get(index++) + } +} + +class LongArrayList : Iterable { + private var array = LongArray(3) + private var length = 0 + + val size get() = length + + fun isEmpty() = size == 0 + + fun add(x: Long) { + length++ + ensureCapacity(length) + set(length - 1, x) + } + + fun get(index: Int): Long = when { + index < 0 || index >= length -> throw IndexOutOfBoundsException("Index out of range: $index") + + else -> array[index] + } + + fun set(index: Int, x: Long) = when { + index < 0 || index >= length -> throw IndexOutOfBoundsException("Index out of range: $index") + + else -> array[index] = x + } + + override operator fun iterator(): Iterator = Itr() + + private fun ensureCapacity(minCapacity: Int) { + val oldArray = array + if (minCapacity > oldArray.size) { + var newSize = oldArray.size * 3 / 2 + if (minCapacity > newSize) + newSize = minCapacity + array = oldArray.copyOf(newSize) + } + } + + private inner class Itr : Iterator { + private var index = 0 + + override fun hasNext() = index < size + + override fun next() = get(index++) + } +} \ No newline at end of file diff --git a/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/ir/util/IrUtils2.kt b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/ir/util/IrUtils2.kt new file mode 100644 index 00000000000..6d1c44d3d62 --- /dev/null +++ b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/ir/util/IrUtils2.kt @@ -0,0 +1,391 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +package org.jetbrains.kotlin.ir.util + +import org.jetbrains.kotlin.backend.common.CommonBackendContext +import org.jetbrains.kotlin.backend.konan.KonanBackendContext +import org.jetbrains.kotlin.backend.konan.KonanCompilationException +import org.jetbrains.kotlin.backend.konan.descriptors.synthesizedName +import org.jetbrains.kotlin.backend.konan.ir.buildSimpleAnnotation +import org.jetbrains.kotlin.builtins.StandardNames +import org.jetbrains.kotlin.config.LanguageVersionSettings +import org.jetbrains.kotlin.descriptors.ParameterDescriptor +import org.jetbrains.kotlin.descriptors.DescriptorVisibilities +import org.jetbrains.kotlin.descriptors.impl.PackageFragmentDescriptorImpl +import org.jetbrains.kotlin.ir.IrElement +import org.jetbrains.kotlin.ir.SourceManager +import org.jetbrains.kotlin.ir.UNDEFINED_OFFSET +import org.jetbrains.kotlin.ir.builders.* +import org.jetbrains.kotlin.ir.declarations.* +import org.jetbrains.kotlin.ir.declarations.impl.IrFieldImpl +import org.jetbrains.kotlin.ir.declarations.impl.IrFileImpl +import org.jetbrains.kotlin.ir.declarations.impl.IrValueParameterImpl +import org.jetbrains.kotlin.ir.declarations.impl.IrVariableImpl +import org.jetbrains.kotlin.ir.descriptors.IrBuiltIns +import org.jetbrains.kotlin.ir.descriptors.WrappedFieldDescriptor +import org.jetbrains.kotlin.ir.descriptors.WrappedVariableDescriptor +import org.jetbrains.kotlin.ir.expressions.* +import org.jetbrains.kotlin.ir.expressions.impl.* +import org.jetbrains.kotlin.ir.symbols.IrClassSymbol +import org.jetbrains.kotlin.ir.symbols.IrFunctionSymbol +import org.jetbrains.kotlin.ir.symbols.IrSymbol +import org.jetbrains.kotlin.ir.symbols.IrTypeParameterSymbol +import org.jetbrains.kotlin.ir.symbols.impl.IrFieldSymbolImpl +import org.jetbrains.kotlin.ir.symbols.impl.IrValueParameterSymbolImpl +import org.jetbrains.kotlin.ir.symbols.impl.IrVariableSymbolImpl +import org.jetbrains.kotlin.ir.types.* +import org.jetbrains.kotlin.ir.types.impl.IrSimpleTypeImpl +import org.jetbrains.kotlin.ir.types.impl.IrStarProjectionImpl +import org.jetbrains.kotlin.ir.types.impl.makeTypeProjection +import org.jetbrains.kotlin.ir.visitors.IrElementVisitor +import org.jetbrains.kotlin.name.FqName +import org.jetbrains.kotlin.name.Name +import org.jetbrains.kotlin.resolve.calls.checkers.isRestrictsSuspensionReceiver +import org.jetbrains.kotlin.resolve.scopes.MemberScope +import org.jetbrains.kotlin.types.KotlinType +import org.jetbrains.kotlin.types.TypeUtils +import org.jetbrains.kotlin.types.typeUtil.immediateSupertypes +import java.lang.reflect.Proxy + +internal fun irBuilder( + irBuiltIns: IrBuiltIns, + scopeOwnerSymbol: IrSymbol, + startOffset: Int = UNDEFINED_OFFSET, + endOffset: Int = UNDEFINED_OFFSET +): IrBuilderWithScope = + object : IrBuilderWithScope( + IrGeneratorContextBase(irBuiltIns), + Scope(scopeOwnerSymbol), + startOffset, + endOffset + ) {} + +//TODO: delete file on next kotlin dependency update +internal fun IrExpression.isNullConst() = this is IrConst<*> && this.kind == IrConstKind.Null + +private var topLevelInitializersCounter = 0 + +internal fun IrFile.addTopLevelInitializer(expression: IrExpression, context: KonanBackendContext, threadLocal: Boolean) { + val descriptor = WrappedFieldDescriptor() + val irField = IrFieldImpl( + expression.startOffset, expression.endOffset, + IrDeclarationOrigin.DEFINED, + IrFieldSymbolImpl(descriptor), + "topLevelInitializer${topLevelInitializersCounter++}".synthesizedName, + expression.type, + DescriptorVisibilities.PRIVATE, + isFinal = true, + isExternal = false, + isStatic = true, + ).apply { + descriptor.bind(this) + + expression.setDeclarationsParent(this) + + if (threadLocal) + annotations += buildSimpleAnnotation(context.irBuiltIns, startOffset, endOffset, context.ir.symbols.threadLocal.owner) + + initializer = IrExpressionBodyImpl(startOffset, endOffset, expression) + } + addChild(irField) +} + +fun IrModuleFragment.addFile(fileEntry: SourceManager.FileEntry, packageFqName: FqName): IrFile { + val packageFragmentDescriptor = object : PackageFragmentDescriptorImpl(this.descriptor, packageFqName) { + override fun getMemberScope(): MemberScope = MemberScope.Empty + } + + return IrFileImpl(fileEntry, packageFragmentDescriptor) + .also { this.files += it } +} + +inline fun stub(name: String): T { + return Proxy.newProxyInstance(T::class.java.classLoader, arrayOf(T::class.java)) { + _ /* proxy */, method, _ /* methodArgs */ -> + if (method.name == "toString" && method.parameterCount == 0) { + "${T::class.simpleName} stub for $name" + } else { + error("${T::class.simpleName}.${method.name} is not supported for $name") + } + } as T +} + +fun IrDeclarationContainer.addChildren(declarations: List) { + declarations.forEach { this.addChild(it) } +} + +fun IrDeclarationContainer.addChild(declaration: IrDeclaration) { + this.declarations += declaration + declaration.accept(SetDeclarationsParentVisitor, this) +} + +fun T.setDeclarationsParent(parent: IrDeclarationParent): T { + accept(SetDeclarationsParentVisitor, parent) + return this +} + +object SetDeclarationsParentVisitor : IrElementVisitor { + override fun visitElement(element: IrElement, data: IrDeclarationParent) { + if (element !is IrDeclarationParent) { + element.acceptChildren(this, data) + } + } + + override fun visitDeclaration(declaration: IrDeclarationBase, data: IrDeclarationParent) { + declaration.parent = data + super.visitDeclaration(declaration, data) + } +} + +tailrec fun IrDeclaration.getContainingFile(): IrFile? { + val parent = this.parent + + return when (parent) { + is IrFile -> parent + is IrDeclaration -> parent.getContainingFile() + else -> null + } +} + +internal fun KonanBackendContext.report(declaration: IrDeclaration, message: String, isError: Boolean) { + val irFile = declaration.getContainingFile() + this.report( + declaration, + irFile, + if (irFile != null) { + message + } else { + val renderer = org.jetbrains.kotlin.renderer.DescriptorRenderer.COMPACT_WITH_SHORT_TYPES + "$message\n${renderer.render(declaration.descriptor)}" + }, + isError + ) + if (isError) throw KonanCompilationException() +} + +fun IrFunctionAccessExpression.addArguments(args: Map) { + val unhandledParameters = args.keys.toMutableSet() + fun getArg(parameter: IrValueParameter) = args[parameter]?.also { unhandledParameters -= parameter } + + symbol.owner.dispatchReceiverParameter?.let { + val arg = getArg(it) + if (arg != null) { + this.dispatchReceiver = arg + } + } + + symbol.owner.extensionReceiverParameter?.let { + val arg = getArg(it) + if (arg != null) { + this.extensionReceiver = arg + } + } + + symbol.owner.valueParameters.forEach { + val arg = getArg(it) + if (arg != null) { + this.putValueArgument(it.index, arg) + } + } +} + +fun IrType.substitute(map: Map): IrType { + if (this !is IrSimpleType) return this + + val classifier = this.classifier + return when (classifier) { + is IrTypeParameterSymbol -> + map[classifier]?.let { if (this.hasQuestionMark) it.makeNullable() else it } + ?: this + + is IrClassSymbol -> if (this.arguments.isEmpty()) { + this // Fast path. + } else { + val newArguments = this.arguments.map { + when (it) { + is IrTypeProjection -> makeTypeProjection(it.type.substitute(map), it.variance) + is IrStarProjection -> it + else -> error(it) + } + } + IrSimpleTypeImpl(classifier, hasQuestionMark, newArguments, annotations) + } + else -> error(classifier) + } + +} + +private fun IrFunction.substitutedReturnType(typeArguments: List): IrType { + val unsubstituted = this.returnType + if (typeArguments.isEmpty()) return unsubstituted // Fast path. + if (this is IrConstructor) { + // Workaround for missing type parameters in constructors. TODO: remove. + return this.returnType.classifierOrFail.typeWith(typeArguments) + } + + assert(this.typeParameters.size >= typeArguments.size) // TODO: check equality. + // TODO: receiver type must also be considered. + return unsubstituted.substitute(this.typeParameters.map { it.symbol }.zip(typeArguments).toMap()) +} + +// TODO: this function must be avoided since it takes symbol's owner implicitly. +fun IrBuilderWithScope.irCall(symbol: IrFunctionSymbol, typeArguments: List = emptyList()) = + this.irCall(symbol, symbol.owner.substitutedReturnType(typeArguments), typeArguments) + +fun IrBuilderWithScope.irCall(irFunction: IrFunction, typeArguments: List = emptyList()) = + irCall(irFunction.symbol, typeArguments) + +internal fun irCall(startOffset: Int, endOffset: Int, irFunction: IrSimpleFunction, typeArguments: List): IrCall = + IrCallImpl.fromSymbolDescriptor( + startOffset, endOffset, irFunction.substitutedReturnType(typeArguments), + irFunction.symbol, typeArguments.size, irFunction.valueParameters.size + ).apply { + typeArguments.forEachIndexed { index, irType -> + this.putTypeArgument(index, irType) + } + } + +fun IrBuilderWithScope.irCallOp( + callee: IrFunction, + dispatchReceiver: IrExpression, + argument: IrExpression +) = + irCall(callee).apply { + this.dispatchReceiver = dispatchReceiver + putValueArgument(0, argument) + } + +fun IrBuilderWithScope.irSetVar(variable: IrVariable, value: IrExpression) = + irSet(variable.symbol, value) + +fun IrBuilderWithScope.irCatch(type: IrType) = + IrCatchImpl( + startOffset, endOffset, + WrappedVariableDescriptor().let { descriptor -> + IrVariableImpl( + startOffset, + endOffset, + IrDeclarationOrigin.IR_TEMPORARY_VARIABLE, + IrVariableSymbolImpl(descriptor), + Name.identifier("e"), + type, + false, + false, + false + ).apply { + descriptor.bind(this) + parent = this@irCatch.parent + } + } + ) + +/** + * Binds the arguments explicitly represented in the IR to the parameters of the accessed function. + * The arguments are to be evaluated in the same order as they appear in the resulting list. + */ +fun IrMemberAccessExpression<*>.getArgumentsWithIr(): List> { + val res = mutableListOf>() + val irFunction = when (this) { + is IrFunctionAccessExpression -> this.symbol.owner + is IrFunctionReference -> this.symbol.owner + else -> error(this) + } + + dispatchReceiver?.let { + res += (irFunction.dispatchReceiverParameter!! to it) + } + + extensionReceiver?.let { + res += (irFunction.extensionReceiverParameter!! to it) + } + + irFunction.valueParameters.forEachIndexed { index, it -> + val arg = getValueArgument(index) + if (arg != null) { + res += (it to arg) + } + } + + return res +} + +fun ReferenceSymbolTable.translateErased(type: KotlinType): IrSimpleType { + val descriptor = TypeUtils.getClassDescriptor(type) + if (descriptor == null) return translateErased(type.immediateSupertypes().first()) + val classSymbol = this.referenceClass(descriptor) + + val nullable = type.isMarkedNullable + val arguments = type.arguments.map { IrStarProjectionImpl } + + return classSymbol.createType(nullable, arguments) +} + +fun CommonBackendContext.createArrayOfExpression( + startOffset: Int, endOffset: Int, + arrayElementType: IrType, + arrayElements: List +): IrExpression { + + val arrayType = ir.symbols.array.typeWith(arrayElementType) + val arg0 = IrVarargImpl(startOffset, endOffset, arrayType, arrayElementType, arrayElements) + + return irCall(startOffset, endOffset, ir.symbols.arrayOf.owner, listOf(arrayElementType)).apply { + putValueArgument(0, arg0) + } +} + +fun createField( + startOffset: Int, + endOffset: Int, + origin: IrDeclarationOrigin, + type: IrType, + name: Name, + isMutable: Boolean, + owner: IrClass +) = WrappedFieldDescriptor().let { + IrFieldImpl( + startOffset, endOffset, + origin, + IrFieldSymbolImpl(it), + name, + type, + DescriptorVisibilities.PRIVATE, + !isMutable, + false, + false, + ).apply { + it.bind(this) + owner.declarations += this + parent = owner + } +} + +fun IrValueParameter.copy(newDescriptor: ParameterDescriptor): IrValueParameter { + // Aggressive use of WrappedDescriptors during deserialization + // makes these types different. + // Let's hope they not really used afterwards. + //assert(this.descriptor.type == newDescriptor.type) { + // "type1 = ${this.descriptor.type} != type2 = ${newDescriptor.type}" + //} + + return IrValueParameterImpl( + startOffset, endOffset, IrDeclarationOrigin.DEFINED, IrValueParameterSymbolImpl(newDescriptor), + newDescriptor.name, newDescriptor.indexOrMinusOne, type, varargElementType, + newDescriptor.isCrossinline, newDescriptor.isNoinline + ) +} + +val IrType.isSimpleTypeWithQuestionMark: Boolean + get() = this is IrSimpleType && this.hasQuestionMark + +fun IrClass.defaultOrNullableType(hasQuestionMark: Boolean) = + if (hasQuestionMark) this.defaultType.makeNullable() else this.defaultType + +fun IrFunction.isRestrictedSuspendFunction(languageVersionSettings: LanguageVersionSettings): Boolean = + this.descriptor.extensionReceiverParameter?.type?.isRestrictsSuspensionReceiver(languageVersionSettings) == true + +fun IrBuilderWithScope.irByte(value: Byte) = + IrConstImpl.byte(startOffset, endOffset, context.irBuiltIns.byteType, value) diff --git a/kotlin-native/backend.native/llvm.def b/kotlin-native/backend.native/llvm.def new file mode 100644 index 00000000000..d93bccffb40 --- /dev/null +++ b/kotlin-native/backend.native/llvm.def @@ -0,0 +1,90 @@ +headers = llvm-c/Core.h llvm-c/Target.h llvm-c/Analysis.h llvm-c/BitWriter.h \ + llvm-c/BitReader.h llvm-c/Transforms/PassManagerBuilder.h llvm-c/Transforms/IPO.h \ + llvm-c/TargetMachine.h llvm-c/Target.h llvm-c/Linker.h llvm-c/Initialization.h \ + llvm-c/DebugInfo.h DebugInfoC.h CoverageMappingC.h + +headerFilter = llvm-c/* llvm-c/**/* DebugInfoC.h CoverageMappingC.h + +compilerOpts = -std=c99 \ + -Wall -W -Wno-unused-parameter -Wwrite-strings -Wmissing-field-initializers \ + -pedantic -Wno-long-long -Wcovered-switch-default -Wdelete-non-virtual-dtor \ + -DNDEBUG -D__STDC_CONSTANT_MACROS -D__STDC_FORMAT_MACROS -D__STDC_LIMIT_MACROS + + +linker = clang++ + +linkerOpts = -fvisibility-inlines-hidden \ + -Wall -W -Wno-unused-parameter -Wwrite-strings -Wcast-qual -Wmissing-field-initializers \ + -pedantic -Wno-long-long -Wcovered-switch-default -Wnon-virtual-dtor -Wdelete-non-virtual-dtor \ + -std=c++14 \ + -DNDEBUG -D__STDC_CONSTANT_MACROS -D__STDC_FORMAT_MACROS -D__STDC_LIMIT_MACROS \ + -ldebugInfo -lcoverageMapping + +# ./llvm-config --libs analysis bitreader bitwriter core linker target coverage analysis ipo instrumentation lto objcarcopts arm aarch64 webassembly x86 mips +linkerOpts.osx = -fPIC \ + -Wl,-search_paths_first -Wl,-headerpad_max_install_names \ + -lpthread -lz -lm -lcurses -Wl,-U,_futimens -Wl,-U,_LLVMDumpType \ + -Wl,-exported_symbols_list,llvm.list \ + -lLLVMMipsDisassembler -lLLVMMipsCodeGen -lLLVMMipsAsmParser -lLLVMMipsDesc -lLLVMMipsInfo -lLLVMMipsAsmPrinter \ + -lLLVMX86Disassembler -lLLVMX86AsmParser -lLLVMX86CodeGen -lLLVMX86Desc -lLLVMX86Info -lLLVMX86AsmPrinter \ + -lLLVMX86Utils -lLLVMWebAssemblyDisassembler -lLLVMWebAssemblyCodeGen -lLLVMWebAssemblyDesc \ + -lLLVMWebAssemblyAsmPrinter -lLLVMWebAssemblyAsmParser -lLLVMWebAssemblyInfo -lLLVMAArch64Disassembler \ + -lLLVMAArch64CodeGen -lLLVMAArch64AsmParser -lLLVMAArch64Desc -lLLVMAArch64Info -lLLVMAArch64AsmPrinter \ + -lLLVMAArch64Utils -lLLVMARMDisassembler -lLLVMARMCodeGen -lLLVMGlobalISel -lLLVMSelectionDAG -lLLVMAsmPrinter \ + -lLLVMARMAsmParser -lLLVMARMDesc -lLLVMMCDisassembler -lLLVMARMInfo -lLLVMARMAsmPrinter -lLLVMARMUtils \ + -lLLVMLTO -lLLVMPasses -lLLVMObjCARCOpts -lLLVMCodeGen -lLLVMipo -lLLVMInstrumentation -lLLVMVectorize \ + -lLLVMScalarOpts -lLLVMIRReader -lLLVMAsmParser -lLLVMInstCombine -lLLVMAggressiveInstCombine -lLLVMCoverage \ + -lLLVMTarget -lLLVMLinker -lLLVMTransformUtils -lLLVMBitWriter -lLLVMAnalysis -lLLVMProfileData -lLLVMObject \ + -lLLVMMCParser -lLLVMMC -lLLVMDebugInfoCodeView -lLLVMDebugInfoMSF -lLLVMBitReader -lLLVMCore \ + -lLLVMBinaryFormat -lLLVMSupport -lLLVMDemangle + + + +# ./llvm-config --libs analysis bitreader bitwriter core linker target coverage analysis ipo instrumentation lto arm aarch64 webassembly x86 mips +linkerOpts.linux = -fPIC \ + -Wl,-z,noexecstack \ + -lrt -ldl -lpthread -lz -lm \ +-lLLVMMipsDisassembler -lLLVMMipsCodeGen -lLLVMMipsAsmParser -lLLVMMipsDesc -lLLVMMipsInfo -lLLVMMipsAsmPrinter \ +-lLLVMX86Disassembler -lLLVMX86AsmParser -lLLVMX86CodeGen -lLLVMX86Desc -lLLVMX86Info -lLLVMX86AsmPrinter -lLLVMX86Utils \ +-lLLVMWebAssemblyDisassembler -lLLVMWebAssemblyCodeGen -lLLVMWebAssemblyDesc -lLLVMWebAssemblyAsmPrinter -lLLVMWebAssemblyAsmParser \ +-lLLVMWebAssemblyInfo -lLLVMAArch64Disassembler -lLLVMAArch64CodeGen -lLLVMAArch64AsmParser -lLLVMAArch64Desc -lLLVMAArch64Info \ +-lLLVMAArch64AsmPrinter -lLLVMAArch64Utils -lLLVMARMDisassembler -lLLVMARMCodeGen -lLLVMGlobalISel -lLLVMSelectionDAG \ +-lLLVMAsmPrinter -lLLVMARMAsmParser -lLLVMARMDesc -lLLVMMCDisassembler -lLLVMARMInfo -lLLVMARMAsmPrinter -lLLVMARMUtils -lLLVMLTO \ +-lLLVMPasses -lLLVMObjCARCOpts -lLLVMCodeGen -lLLVMipo -lLLVMInstrumentation -lLLVMVectorize -lLLVMScalarOpts -lLLVMIRReader \ +-lLLVMAsmParser -lLLVMInstCombine -lLLVMAggressiveInstCombine -lLLVMCoverage -lLLVMTarget -lLLVMLinker -lLLVMTransformUtils \ +-lLLVMBitWriter -lLLVMAnalysis -lLLVMProfileData -lLLVMObject -lLLVMMCParser -lLLVMMC -lLLVMDebugInfoCodeView -lLLVMDebugInfoMSF \ +-lLLVMBitReader -lLLVMCore -lLLVMBinaryFormat -lLLVMSupport -lLLVMDemangle + +# ./llvm-config --libs analysis bitreader bitwriter core linker target coverage analysis ipo instrumentation lto arm aarch64 webassembly x86 +linkerOpts.mingw = -lLLVMX86Disassembler -lLLVMX86AsmParser -lLLVMX86CodeGen -lLLVMX86Desc -lLLVMX86Info \ +-lLLVMX86AsmPrinter -lLLVMX86Utils -lLLVMWebAssemblyDisassembler -lLLVMWebAssemblyCodeGen -lLLVMWebAssemblyDesc \ +-lLLVMWebAssemblyAsmPrinter -lLLVMWebAssemblyAsmParser -lLLVMWebAssemblyInfo -lLLVMAArch64Disassembler \ +-lLLVMAArch64CodeGen -lLLVMAArch64AsmParser -lLLVMAArch64Desc -lLLVMAArch64Info -lLLVMAArch64AsmPrinter \ +-lLLVMAArch64Utils -lLLVMARMDisassembler -lLLVMARMCodeGen -lLLVMGlobalISel -lLLVMSelectionDAG -lLLVMAsmPrinter \ +-lLLVMARMAsmParser -lLLVMARMDesc -lLLVMMCDisassembler -lLLVMARMInfo -lLLVMARMAsmPrinter -lLLVMARMUtils -lLLVMLTO \ +-lLLVMPasses -lLLVMObjCARCOpts -lLLVMCodeGen -lLLVMipo -lLLVMInstrumentation -lLLVMVectorize -lLLVMScalarOpts \ +-lLLVMIRReader -lLLVMAsmParser -lLLVMInstCombine -lLLVMAggressiveInstCombine -lLLVMCoverage -lLLVMTarget \ +-lLLVMLinker -lLLVMTransformUtils -lLLVMBitWriter -lLLVMAnalysis -lLLVMProfileData -lLLVMObject -lLLVMMCParser \ +-lLLVMMC -lLLVMDebugInfoCodeView -lLLVMDebugInfoMSF -lLLVMBitReader -lLLVMCore -lLLVMBinaryFormat -lLLVMSupport -lLLVMDemangle \ + -lole32 -luuid -static-libgcc -static-libstdc++ \ + -Wl,-Bstatic -lz \ + -Wl,-Bstatic,--whole-archive -lwinpthread -Wl,--no-whole-archive,-Bdynamic \ + +# It looks like mingw port compiled without LLVM_ENABLE_DUMP +#Note: ld on mingw process -Wl,-U,_LLVMDumpType use different from other platform +# way, using this option cause linkage error: +# ld: -r and -shared may not be used together +excludedFunctions.mingw = LLVMDumpType + +# Functions from LLVMIntPtrType to LLVMModuleCreateWithName are excluded because they work with the GlobalContext. +# This might not be safe if the compiler is called from a daemon process. +excludedFunctions = LLVMInitializeAllAsmParsers LLVMInitializeAllAsmPrinters LLVMInitializeAllDisassemblers \ + LLVMInitializeAllTargetInfos LLVMInitializeAllTargetMCs LLVMInitializeAllTargets LLVMInitializeNativeTarget \ + LLVMInitializeNativeAsmParser LLVMInitializeNativeAsmPrinter LLVMInitializeNativeDisassembler \ + LLVMConstInBoundsGEP2 LLVMConstGEP2 LLVMIntPtrType LLVMIntPtrTypeForAS LLVMGetMDKindID LLVMInt1Type LLVMInt8Type \ + LLVMInt16Type LLVMInt32Type LLVMInt64Type LLVMInt128Type LLVMIntType LLVMHalfType LLVMFloatType LLVMDoubleType \ + LLVMX86FP80Type LLVMFP128Type LLVMPPCFP128Type LLVMX86MMXType LLVMStructType LLVMVoidType LLVMLabelType \ + LLVMMDString LLVMMDNode LLVMConstString LLVMConstStruct LLVMAppendBasicBlock LLVMInsertBasicBlock LLVMCreateBuilder \ + LLVMParseBitcode LLVMParseBitcode2 LLVMGetBitcodeModule LLVMGetBitcodeModule2 LLVMGetGlobalContext LLVMModuleCreateWithName + +strictEnums = LLVMIntPredicate LLVMOpcode LLVMDLLStorageClass LLVMCallConv LLVMThreadLocalMode LLVMAtomicOrdering diff --git a/kotlin-native/backend.native/llvm.list b/kotlin-native/backend.native/llvm.list new file mode 100644 index 00000000000..d04f5428cef --- /dev/null +++ b/kotlin-native/backend.native/llvm.list @@ -0,0 +1 @@ +_Java_* diff --git a/kotlin-native/backend.native/tests/build.gradle b/kotlin-native/backend.native/tests/build.gradle new file mode 100644 index 00000000000..f887c460182 --- /dev/null +++ b/kotlin-native/backend.native/tests/build.gradle @@ -0,0 +1,4918 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +import shadow.org.jetbrains.kotlin.gradle.plugin.tasks.KonanCompileNativeBinary +import org.jetbrains.kotlin.* +import org.jetbrains.kotlin.konan.target.Family +import org.jetbrains.kotlin.konan.target.KonanTarget + +import java.nio.file.Paths + +import static org.jetbrains.kotlin.konan.target.Architecture.* + +buildscript { + repositories { + maven { + url 'https://cache-redirector.jetbrains.com/maven-central' + } + mavenCentral() + maven { + url buildKotlinCompilerRepo + } + maven { + url kotlinCompilerRepo + } + } + + dependencies { + classpath "org.jetbrains.kotlin:kotlin-native-gradle-plugin:$gradlePluginVersion" + } + ext.useCustomDist = project.hasProperty("konan.home") + if (!useCustomDist) { + ext.setProperty("konan.home", distDir.absolutePath) + } +} + +apply plugin: 'konan' +apply plugin: 'kotlin' + +configurations { + cli_bc + update_tests + update_stdlib_tests +} + +repositories { + ivy { + ivyPattern 'https://teamcity.jetbrains.com/guestAuth/repository/download/[module]/[revision]/teamcity-ivy.xml' + artifactPattern 'https://teamcity.jetbrains.com/guestAuth/repository/download/[module]/[revision]/[artifact](.[ext])' + } +} + +dependencies { + compile 'org.jetbrains.kotlinx:kotlinx-coroutines-core:1.3.7' + cli_bc project(path: ':backend.native', configuration: 'cli_bc') + def updateTestData = true + if (project.hasProperty("kotlinProjectPath")) { + def kotlinProj = project.property("kotlinProjectPath").toString() + def testDataZip = Paths.get(kotlinProj, "dist", "kotlin-test-data.zip").toFile() + if (testDataZip.exists()) { + update_tests files(testDataZip) + updateTestData = false + } else { + println("WARN: using tests provided by gradle.properties. Please execute :kotlin:zipTestData") + } + def stdlibTestsZip = Paths.get(kotlinProj, "dist", "kotlin-stdlib-tests.zip").toFile() + if (stdlibTestsZip.exists()) { + update_stdlib_tests files(stdlibTestsZip) + updateTestData = false + } else { + println("WARNING: using stdlib tests provided by gradle.properties. Please execute :kotlin:zipTestData") + } + } + if (updateTestData) { + update_tests(group: 'org', name: 'Kotlin_KotlinPublic_Compiler', version: testKotlinCompilerVersion) { + artifact { + name = 'internal/kotlin-test-data' + type = 'zip' + } + } + update_stdlib_tests (group: 'org', name: 'Kotlin_KotlinPublic_Compiler', version: kotlinStdlibTestsVersion) { + artifact { + name = 'internal/kotlin-stdlib-tests' + type = 'zip' + } + } + } +} +ext.testOutputRoot = rootProject.file("test.output").absolutePath +ext.externalTestsDir = project.file("build/external") +ext.externalStdlibTestsDir = project.file("build/stdlib_external/stdlib") +externalTestsDir.mkdirs() +externalStdlibTestsDir.mkdirs() + +ext.platformManager = project.rootProject.platformManager +ext.target = platformManager.targetManager(project.testTarget).target + +ext.testLibraryDir = "${project.property("konan.home")}/klib/platform/${project.target.name}" + +// Add executor to run tests depending on a target +project.convention.plugins.executor = ExecutorServiceKt.create(project) + + +compileTestKotlin { + kotlinOptions { + freeCompilerArgs += "-Xskip-prerelease-check" + } +} + +// Do not generate run tasks for konan built artifacts +ext.konanNoRun = true + +final CacheTesting cacheTesting = CacheTestingKt.configureCacheTesting(project) +if (cacheTesting != null) { + // Note: can't do this in [CacheTesting.configure] since task classes aren't accessible there. + + tasks.withType(KonanCompileNativeBinary.class).configureEach { + dependsOn cacheTesting.buildCacheTask + extraOpts cacheTesting.compilerArgs + } + + tasks.withType(RunExternalTestGroup.class).configureEach { + dependsOn cacheTesting.buildCacheTask + flags = (flags ?: []) + cacheTesting.compilerArgs + } +} + +// Enable two-stage test compilation if the test_two_stage property is set. +ext.twoStageEnabled = project.hasProperty("test_two_stage") + +tasks.withType(KonanCompileNativeBinary.class).configureEach { + enableTwoStageCompilation = twoStageEnabled +} + +tasks.withType(RunExternalTestGroup.class).configureEach { + enableTwoStageCompilation = twoStageEnabled +} + +allprojects { + // Root directories for test output (logs, compiled files, statistics etc). Only single path must be in each set. + // backend.native/tests + ext.testOutputLocal = rootProject.file("$testOutputRoot/local") + + // backend.native/tests/external + ext.testOutputExternal = rootProject.file("$testOutputRoot/external") + + // backend.native/tests/stdlib_external + ext.testOutputStdlib = rootProject.file("$testOutputRoot/stdlib") + + // backend.native/tests/framework + ext.testOutputFramework = rootProject.file("$testOutputRoot/framework") + + // backent.native/tests/coverage + ext.testOutputCoverage = rootProject.file("$testOutputRoot/coverage") +} +testOutputExternal.mkdirs() +testOutputStdlib.mkdirs() + +ext.dist = project.rootProject.file(project.findProperty("org.jetbrains.kotlin.native.home") ?: + project.findProperty("konan.home") ?: "dist") + +konanArtifacts { + library('testLibrary') { + if (!useCustomDist) { + dependsOn ':dist' + } + srcDir 'testLibrary' + } + def target = project.testTarget ?: 'host' + library('baseTestClass', targets: [target]) { + if (!useCustomDist) { + dependsOn ':dist' + } + srcFiles 'testing/library.kt' + } +} + +task installTestLibrary(type: KlibInstall) { + dependsOn compileKonanTestLibraryHost + klib = konanArtifacts.testLibrary.getArtifactByTarget('host') + repo = rootProject.file(testLibraryDir) + + doLast { + // Remove the version in build/, so that we don't link two copies. + def file = project.file("build/konan/libs/${project.target.name}/testLibrary.klib") + file.delete() + } +} + +// Gets tests from the same Kotlin compiler build +def update_external_tests() { + // Copy only used tests into the test directory. + if (externalTestsDir.exists()) { + delete(externalTestsDir) + } + externalTestsDir.mkdirs() + + def compilerTestsFiles = configurations.update_tests.asFileTree + copy { + compilerTestsFiles.each { + from(zipTree(it)) + into(externalTestsDir) + include 'compiler/codegen/box/**' + include 'compiler/codegen/boxInline/**' + include 'compiler/compileKotlinAgainstKotlin/**' + exclude 'stdlib/**' + } + } + + if (externalStdlibTestsDir.exists()) { + delete(externalStdlibTestsDir) + } + externalStdlibTestsDir.mkdirs() + def stdlibTestsFiles = configurations.update_stdlib_tests.asFileTree + copy { + stdlibTestsFiles.each { + from(zipTree(it)) + into(externalStdlibTestsDir) + include 'common/**' + include 'test/**' + exclude 'test/js/**' + include 'kotlin-test/**' + } + } +} + +void konanc(String[] args) { + def konancScript = isWindows() ? "konanc.bat" : "konanc" + def konanc = "$dist/bin/$konancScript" + def allArgs = args.join(" ") + println("$konanc $allArgs") + "$konanc $allArgs".execute().waitFor() +} + +clean { + doLast { + delete(rootProject.file(testOutputRoot)) + } +} + +TaskCollection tasksOf(Class type, Closure filter = { return true }) { + String prefix = project.findProperty("prefix") + project.tasks.withType(type) + .matching { filter(it) && it.enabled && (prefix != null ? it.name.startsWith(prefix) : true) } +} + +run { + dependsOn(tasksOf(KonanTest)) + // Add framework tests + dependsOn(tasksOf(FrameworkTest)) + dependsOn(tasksOf(MetadataComparisonTest)) + // Add regular gradle test tasks + dependsOn(tasksOf(Test)) + dependsOn(tasksOf(CoverageTest)) +} + +task sanity { + doFirst { + if (!project.hasProperty("test.disable_update")) { + update_external_tests() + } + } + def platformLibsTasks = targetList.collect { ":${it}PlatformLibs" } + ":distPlatformLibs" + dependsOn(tasksOf(KonanTest) { task -> + task.getDependsOn().every { !platformLibsTasks.contains(it) } && + task.name != "library_mismatch" // This test requires the wasm32 stdlib which is unavailable during a sanity run. + }) + dependsOn(tasksOf(FrameworkTest) { task -> + task.getDependsOn().every { !platformLibsTasks.contains(it) } + }) + dependsOn(tasksOf(MetadataComparisonTest)) + // Add regular gradle test tasks + dependsOn(tasksOf(Test)) + dependsOn(tasksOf(CoverageTest)) +} + +// Collect reports in one json. +task resultsTask() { + doLast { + List reports = [] + def statistics = new Statistics() + tasks.withType(RunExternalTestGroup).matching { it.state.executed }.each { + reports += new KonanTestGroupReport(it.name, it.testGroupReporter.suiteReports) + statistics.add(it.testGroupReporter.statistics) + } + + tasks.withType(KonanGTest).matching { it.state.executed }.each { + statistics.add(it.statistics) + } + + ExternalReportUtilsKt.saveReport("$testOutputExternal/reports.json", statistics, reports) + use(KonanTestSuiteReportKt) { + project.logger.quiet("DONE.\n\n" + + "TOTAL: $statistics.total\n" + + "PASSED: $statistics.passed\n" + + "FAILED: $statistics.failed\n" + + (statistics.error != 0 ? "ERROR: $statistics.error\n" : "") + + "SKIPPED: $statistics.skipped") + } + } +} + +boolean isExcluded(String dir) { + // List of tests that fail due to unresolved compiler bugs + def excluded = [ ] + + boolean result = false + excluded.forEach { + if (dir.endsWith(it.replace("/", File.separator))) { + result = true + } + } + return result +} + +def createTestTasks(File testRoot, Class taskType) { + testRoot.eachDirRecurse { + // Skip build directory and directories without *.kt files. + if (it.name == "build" || it.listFiles().count { it.name.endsWith(".kt") && it.isFile() } == 0) { + return + } + + def taskDirectory = project.relativePath(it).substring("build/".length()) + if (!isExcluded(taskDirectory)) { + def taskName = taskDirectory.replaceAll("[-/\\\\]", '_') + project.tasks.register(taskName, taskType) { + it.groupDirectory = taskDirectory + it.finalizedBy resultsTask + } + } else { + println("$taskDirectory is excluded") + } + } +} + +void dependsOnPlatformLibs(Task t) { + if (!useCustomDist) { + def testTarget = project.target + if (testTarget != project.platformManager.Companion.host) { + t.dependsOn(":${testTarget}PlatformLibs") + } else { + t.dependsOn(':distPlatformLibs') + } + } +} + +/** + * Creates a task for a standalone test. Configures runner and adds building task. + */ +Task standaloneTest(String name, Closure configureClosure) { + return KotlinNativeTestKt.createTest(project, name, KonanStandaloneTest) { task -> + task.configure(configureClosure) + if (task.enabled) { + konanArtifacts { + program(name, targets: [target.name]) { + baseDir "$testOutputLocal/$name" + srcFiles task.getSources() + extraOpts task.flags + extraOpts project.globalTestArgs + } + } + } + } +} + +/** + * Creates a task for a linking test. Configures runner and adds library and test build tasks. + */ +Task linkTest(String name, Closure configureClosure) { + return KotlinNativeTestKt.createTest(project, name, KonanLinkTest) { task -> + task.configure(configureClosure) + if (task.enabled) { + konanArtifacts { + def lib = "lib$name" + def targetName = target.name + // build a library from KonanLinkTest::lib property + library(lib, targets: [targetName]) { + srcFiles task.lib + baseDir "$testOutputLocal/$name" + extraOpts task.flags + extraOpts project.globalTestArgs + } + UtilsKt.dependsOnKonanBuildingTask(task, lib, target) + + // Build an executable with library + program(name, targets: [targetName]) { + libraries { + klib lib + } + baseDir "$testOutputLocal/$name" + srcFiles task.getSources() + extraOpts task.flags + extraOpts project.globalTestArgs + } + } + } + } +} + +/** + * Creates a task for a dynamic test. Configures runner and adds library and test build tasks. + */ +Task dynamicTest(String name, Closure configureClosure) { + return KotlinNativeTestKt.createTest(project, name, KonanDynamicTest) { task -> + task.configure(configureClosure) + if (task.enabled) { + konanArtifacts { + def targetName = target.name + dynamic(name, targets: [targetName]) { + srcFiles task.getSources() + baseDir "$testOutputLocal/$name" + extraOpts task.flags + extraOpts project.globalTestArgs + } + } + def buildTask = UtilsKt.findKonanBuildTask(project, name, target) + UtilsKt.dependsOnDist(buildTask) + } + } +} + +task run_external () { + // Set this property to disable auto update tests + if (!project.hasProperty("test.disable_update")) { + update_external_tests() + } + + // Create tasks for external tests. + createTestTasks(externalTestsDir, RunExternalTestGroup) + + // Set up dependencies. + dependsOn(tasksOf(RunExternalTestGroup)) + dependsOn("stdlibTest") +} + +task daily() { + dependsOn(run_external) +} + + +task slackReport(type:Reporter) { + reportHome = rootProject.file("test.output").absoluteFile +} + +task slackReportNightly(type:NightlyReporter) { + externalMacosReport = "external_macos_results/reports.json" + externalLinuxReport = "external_linux_results/reports.json" + externalWindowsReport = "external_windows_results/reports.json" +} + +linkTest("localDelegatedPropertyLink") { + goldValue = "OK\n" + source = "lower/local_delegated_property_link/main.kt" + lib = "lower/local_delegated_property_link/lib.kt" +} + +task sum(type: KonanLocalTest) { + source = "codegen/function/sum.kt" +} + +task method_call(type: KonanLocalTest) { + source = "codegen/object/method_call.kt" +} + +task fields(type: KonanLocalTest) { + source = "codegen/object/fields.kt" +} + + +task fields1(type: KonanLocalTest) { + source = "codegen/object/fields1.kt" +} + +task fields2(type: KonanLocalTest) { + goldValue = + "Set global = 1\n" + + "Set member = 42\n" + + "Get member = 42\n" + + "Set global = 42\n" + + "Get global = 42\n" + + "Set member = 42\n" + + source = "codegen/object/fields2.kt" +} + +// This test checks object layout can't be done in +// KonanLocalTest paradigm +//task constructor(type: UnitKonanTest) { +// source = "codegen/object/constructor.kt" +//} + +task objectInitialization(type: KonanLocalTest) { + source = "codegen/object/initialization.kt" +} + +task objectInitialization1(type: KonanLocalTest) { + goldValue = "init\nfield\nconstructor1\ninit\nfield\nconstructor1\nconstructor2\n" + source = "codegen/object/initialization1.kt" +} + +standaloneTest("object_globalInitializer") { + source = "codegen/object/globalInitializer.kt" +} + +task check_type(type: KonanLocalTest) { + goldValue = "true\nfalse\ntrue\ntrue\ntrue\ntrue\n" + source = "codegen/basics/check_type.kt" +} + +task safe_cast(type: KonanLocalTest) { + goldValue = "safe_cast_positive: true\n" + + "safe_cast_negative: true\n" + source = "codegen/basics/safe_cast.kt" +} + +task typealias1(type: KonanLocalTest) { + goldValue = "42\n" + source = "codegen/basics/typealias1.kt" +} + +task aritmetic(type: KonanLocalTest) { + source = "codegen/function/arithmetic.kt" +} + +task sum1(type: KonanLocalTest) { + source = "codegen/function/sum_foo_bar.kt" +} + +task sum2(type: KonanLocalTest) { + source = "codegen/function/sum_imm.kt" +} + +task sum_func(type: KonanLocalTest) { + source = "codegen/function/sum_func.kt" +} + +task sum_mixed(type: KonanLocalTest) { + source = "codegen/function/sum_mixed.kt" +} + +task sum_illy(type: KonanLocalTest) { + source = "codegen/function/sum_silly.kt" +} + +task function_defaults(type: KonanLocalTest) { + source = "codegen/function/defaults.kt" +} + +task function_defaults1(type: KonanLocalTest) { + source = "codegen/function/defaults1.kt" +} + +task function_defaults2(type: KonanLocalTest) { + source = "codegen/function/defaults2.kt" +} + +task function_defaults3(type: KonanLocalTest) { + source = "codegen/function/defaults3.kt" +} + +task function_defaults4(type: KonanLocalTest) { + goldValue = "43\n" + source = "codegen/function/defaults4.kt" +} + +task function_defaults5(type: KonanLocalTest) { + goldValue = "5\n6\n" + source = "codegen/function/defaults5.kt" +} + +task function_defaults6(type: KonanLocalTest) { + goldValue = "42\n" + source = "codegen/function/defaults6.kt" +} + +task function_defaults7(type: KonanLocalTest) { + goldValue = "42\n" + source = "codegen/function/defaults7.kt" +} + +task function_defaults8(type: KonanLocalTest) { + goldValue = "2\n" + source = "codegen/function/defaults8.kt" +} + +task function_defaults9(type: KonanLocalTest) { + goldValue = "1\n" + source = "codegen/function/defaults9.kt" +} + +task function_defaults10(type: KonanLocalTest) { + goldValue = "42\n" + source = "codegen/function/defaults10.kt" +} + +task function_defaults_from_fake_override(type: KonanLocalTest) { + goldValue = "42\n" + source = "codegen/function/defaultsFromFakeOverride.kt" +} + +task function_defaults_with_vararg1(type: KonanLocalTest) { + goldValue = "Hello , Correct!\nHello World, Correct!\n , Correct!\n" + source = "codegen/function/defaultsWithVarArg1.kt" +} + +task function_defaults_with_vararg2(type: KonanLocalTest) { + goldValue = "1\n2\n42\n" + source = "codegen/function/defaultsWithVarArg2.kt" +} + +task function_defaults_with_inline_classes(type: KonanLocalTest) { + source = "codegen/function/defaultsWithInlineClasses.kt" +} + +task sum_3const(type: KonanLocalTest) { + source = "codegen/function/sum_3const.kt" +} + +task codegen_controlflow_for_loops(type: KonanLocalTest) { + source = "codegen/controlflow/for_loops.kt" + goldValue = "01234\n0123\n43210\n\n024\n02\n420\n\n036\n03\n630\n\n024\n02\n420\n\n" +} + +task codegen_controlflow_for_loops_types(type: KonanLocalTest) { + source = "codegen/controlflow/for_loops_types.kt" + goldValue = "01234\n01234\n01234\n01234\n01234\n01234\n01234\n01234\n01234\n01234\n01234\n01234\n01234\n01234\n" + + "01234\n01234\n0123\n0123\n0123\n0123\n0123\n0123\n0123\n0123\n0123\n0123\n0123\n0123\n0123\n0123\n0123\n" + + "0123\n43210\n43210\n43210\n43210\n43210\n43210\n43210\n43210\n43210\n43210\n43210\n43210\n43210\n43210\n" + + "43210\n43210\nabcd\nabc\ndcba\n024\n024\n024\n024\n024\n024\n024\n024\n024\n024\n024\n024\n024\n024\n" + + "024\n024\n02\n02\n02\n02\n02\n02\n02\n02\n02\n02\n02\n02\n02\n02\n02\n02\n420\n420\n420\n420\n420\n420\n" + + "420\n420\n420\n420\n420\n420\n420\n420\n420\n420\nac\nac\ndb\n" +} + +task codegen_controlflow_for_loops_overflow(type: KonanLocalTest) { + source = "codegen/controlflow/for_loops_overflow.kt" + goldValue = "2147483646 2147483647 \n2147483646 \n-2147483647 -2147483648 \n1073741827 \n" +} + +task codegen_controlflow_for_loops_errors(type: KonanLocalTest) { + enabled = (project.testTarget != 'wasm32') // Uses exceptions. + source = "codegen/controlflow/for_loops_errors.kt" + goldValue = "OK\n" +} + +task codegen_controlflow_for_loops_empty_range(type: KonanLocalTest) { + source = "codegen/controlflow/for_loops_empty_range.kt" + goldValue = "OK\n" +} + +task codegen_controlflow_for_loops_nested(type: KonanLocalTest) { + source = "codegen/controlflow/for_loops_nested.kt" + goldValue = "00 01 02 10 11 12 20 21 22 \n" + + "00 01 10 11 20 21 \n" + + "00 01 10 11 20 21 \n" + + "00 01 \n" + + "00 02 10 12 20 22 \n" + + "00 02 10 12 20 22 \n" + + "00 10 20 \n" +} + +task codegen_controlflow_for_loops_coroutines(type: KonanLocalTest) { + source = "codegen/controlflow/for_loops_coroutines.kt" + goldValue = "before: 0 after: 0\n" + + "before: 2 after: 2\n" + + "before: 4 after: 4\n" + + "before: 6 after: 6\n" + + "Got: 0 2 4 6\n" +} + +task codegen_controlflow_for_loops_let_with_nullable(type: KonanLocalTest) { + source = "codegen/controlflow/for_loops_let_with_nullable.kt" + goldValue = "012345\n012345\n024\n01234\n01234\n024\n543210\n543210\n531\n" + + "012345\n012345\n024\n01234\n01234\n024\n543210\n543210\n531\n" + + "abcdef\nabcdef\nace\nabcde\nabcde\nace\nfedcba\nfedcba\nfdb\n" +} + +task codegen_controlflow_for_loops_call_order(type: KonanLocalTest) { + source = "codegen/controlflow/for_loops_call_order.kt" + goldValue = "1234\n1234\n2134\n" +} + +task codegen_controlflow_for_loops_array_indices(type: KonanLocalTest) { + source = "codegen/controlflow/for_loops_array_indices.kt" + goldValue = "0123\n\n" +} + +task codegen_controlflow_for_loops_array(type: KonanLocalTest) { + source = "codegen/controlflow/for_loops_array.kt" + goldValue = "4035\n\n0\n0\n" +} + +task codegen_controlflow_for_loops_array_nested(type: KonanLocalTest) { + source = "codegen/controlflow/for_loops_array_nested.kt" + goldValue = "123\nHello\n\n12345678910\n" +} + +task codegen_controlflow_for_loops_array_side_effects(type: KonanLocalTest) { + source = "codegen/controlflow/for_loops_array_side_effects.kt" + goldValue = "side-effect\n4035\nside-effect\n\n" +} + +task codegen_controlflow_for_loops_array_break_continue(type: KonanLocalTest) { + source = "codegen/controlflow/for_loops_array_break_continue.kt" + goldValue = "403\n\n" +} + +task codegen_controlflow_for_loops_array_mutation(type: KonanLocalTest) { + source = "codegen/controlflow/for_loops_array_mutation.kt" + goldValue = "4000" +} + +task codegen_controlflow_for_loops_array_nullable(type: KonanLocalTest) { + source = "codegen/controlflow/for_loops_array_nullable.kt" + goldValue = "123" +} + +task local_variable(type: KonanLocalTest) { + source = "codegen/basics/local_variable.kt" +} + +task canonical_name(type: KonanLocalTest) { + goldValue = "A:foo\nA:qux\n" + source = "codegen/basics/canonical_name.kt" +} + +task cast_simple(type: KonanLocalTest) { + source = "codegen/basics/cast_simple.kt" +} + +task cast_null(type: KonanLocalTest) { + expectedFail = (project.testTarget == 'wasm32') // Uses exceptions. + goldValue = "Ok\n" + source = "codegen/basics/cast_null.kt" +} + +task unchecked_cast1(type: KonanLocalTest) { + goldValue = "17\n17\n42\n42\n" + source = "codegen/basics/unchecked_cast1.kt" +} + +task unchecked_cast2(type: KonanLocalTest) { + enabled = false + goldValue = "Ok\n" + source = "codegen/basics/unchecked_cast2.kt" +} + +task unchecked_cast3(type: KonanLocalTest) { + expectedFail = (project.testTarget == 'wasm32') // Uses exceptions. + goldValue = "Ok\n" + source = "codegen/basics/unchecked_cast3.kt" +} + +task unchecked_cast4(type: KonanLocalTest) { + expectedFail = (project.testTarget == 'wasm32') // Uses exceptions. + goldValue = "Ok\n" + source = "codegen/basics/unchecked_cast4.kt" +} + +task null_check(type: KonanLocalTest) { + source = "codegen/basics/null_check.kt" +} + +task array_to_any(type: KonanLocalTest) { + source = "codegen/basics/array_to_any.kt" +} + +standaloneTest("runtime_basic_init") { + disabled = (project.testTarget == 'wasm32') // -g not yet properly works for WASM. + source = "runtime/basic/init.kt" + flags = ['-g'] + expectedExitStatus = 0 +} + +standaloneTest("runtime_basic_exit") { + source = "runtime/basic/exit.kt" + expectedExitStatus = 42 +} + +task runtime_random(type: KonanLocalTest) { + source = "runtime/basic/random.kt" +} + +task runtime_basic_simd(type: KonanLocalTest) { + expectedFail = (project.testTarget == 'wasm32') // Uses exceptions. + source = "runtime/basic/simd.kt" +} + +task runtime_worker_random(type: KonanLocalTest) { + enabled = (project.testTarget != 'wasm32') // Uses workers. + source = "runtime/basic/worker_random.kt" +} + +task hello0(type: KonanLocalTest) { + goldValue = "Hello, world!\n" + source = "runtime/basic/hello0.kt" +} + +standaloneTest("hello1") { + goldValue = "Hello World" + testData = "Hello World\n" + source = "runtime/basic/hello1.kt" +} + +standaloneTest("hello2") { + goldValue = "you entered 'Hello World'" + testData = "Hello World\n" + source = "runtime/basic/hello2.kt" +} + +task hello3(type: KonanLocalTest) { + goldValue = "239\ntrue\n3.14159\nA\n" + source = "runtime/basic/hello3.kt" +} + +task hello4(type: KonanLocalTest) { + goldValue = "Hello\nПока\n" + source = "runtime/basic/hello4.kt" +} + +standaloneTest('enumEquals') { + goldValue = "true\nfalse\nfalse\n" + source = "runtime/basic/enum_equals.kt" + flags = ['-XXLanguage:-ProhibitComparisonOfIncompatibleEnums', '-e', 'runtime.basic.enum_equals.main'] +} + +standaloneTest("entry0") { + goldValue = "Hello.\n" + source = "runtime/basic/entry0.kt" + flags = ["-entry", "runtime.basic.entry0.main"] +} + +standaloneTest("entry1") { + goldValue = "Hello.\n" + source = "runtime/basic/entry1.kt" + flags = ["-entry", "foo"] +} + +linkTest("entry2") { + goldValue = "Hello.\n" + source = "runtime/basic/entry2.kt" + lib = "runtime/basic/libentry2.kt" + flags = ["-entry", "foo"] +} + +standaloneTest("entry3") { + goldValue = "Hello, without args.\n" + source = "runtime/basic/entry1.kt" + flags = ["-entry", "bar"] +} + +standaloneTest("entry4") { + goldValue = "This is main without args\n" + source = "runtime/basic/entry4.kt" +} + +standaloneTest("readline0") { + goldValue = "41" + testData = "41\r\n" + source = "runtime/basic/readline0.kt" +} + +standaloneTest("readline1") { + goldValue = "" + testData = "\n" + source = "runtime/basic/readline1.kt" +} + +task tostring0(type: KonanLocalTest) { + goldValue = "127\n-1\n239\nA\nЁ\nト\n1122334455\n112233445566778899\n3.14159265358\n1.0E27\n1.0E7\n1.0E-300\ntrue\nfalse\n" + source = "runtime/basic/tostring0.kt" +} + +task tostring1(type: KonanLocalTest) { + goldValue = "ello\n" + source = "runtime/basic/tostring1.kt" +} + +task tostring2(type: KonanLocalTest) { + goldValue = "H e l l o \nHello\n" + source = "runtime/basic/tostring2.kt" +} + +task tostring3(type: KonanLocalTest) { + goldValue = "-128\n127\n-32768\n32767\n" + + "-2147483648\n2147483647\n-9223372036854775808\n9223372036854775807\n" + + "1.4E-45\n3.4028235E38\n-Infinity\nInfinity\n" + + "NaN\n" + + "4.9E-324\n1.7976931348623157E308\n-Infinity\nInfinity\n" + + "NaN\n" + source = "runtime/basic/tostring3.kt" +} + +task empty_substring(type: KonanLocalTest) { + goldValue = "\n" + source = "runtime/basic/empty_substring.kt" +} + +standaloneTest("cleaner_basic") { + enabled = (project.testTarget != 'wasm32') // Cleaners need workers + source = "runtime/basic/cleaner_basic.kt" + flags = ['-tr', '-Xopt-in=kotlin.native.internal.InternalForKotlinNative'] +} + +standaloneTest("cleaner_workers") { + enabled = (project.testTarget != 'wasm32') // Cleaners need workers + source = "runtime/basic/cleaner_workers.kt" + flags = ['-tr', '-Xopt-in=kotlin.native.internal.InternalForKotlinNative'] +} + +standaloneTest("cleaner_in_main_with_checker") { + enabled = (project.testTarget != 'wasm32') // Cleaners need workers + source = "runtime/basic/cleaner_in_main_with_checker.kt" + goldValue = "42\n" +} + +standaloneTest("cleaner_in_main_without_checker") { + enabled = (project.testTarget != 'wasm32') // Cleaners need workers + source = "runtime/basic/cleaner_in_main_without_checker.kt" + goldValue = "" +} + +standaloneTest("cleaner_leak_release") { + enabled = !project.globalTestArgs.contains('-g') && (project.testTarget != 'wasm32') // Cleaners need workers + source = "runtime/basic/cleaner_leak.kt" + goldValue = "" +} + +standaloneTest("cleaner_leak_debug") { + enabled = !project.globalTestArgs.contains('-opt') && (project.testTarget != 'wasm32') // Cleaners need workers + source = "runtime/basic/cleaner_leak.kt" + flags = ['-g'] + expectedExitStatusChecker = { it != 0 } + outputChecker = { s -> (s =~ /Cleaner (0x)?[0-9a-fA-F]+ was disposed during program exit/).find() } +} + +standaloneTest("cleaner_leak_without_checker") { + enabled = (project.testTarget != 'wasm32') // Cleaners need workers + source = "runtime/basic/cleaner_leak_without_checker.kt" + goldValue = "" +} + +standaloneTest("cleaner_leak_with_checker") { + enabled = (project.testTarget != 'wasm32') // Cleaners need workers + source = "runtime/basic/cleaner_leak_with_checker.kt" + expectedExitStatusChecker = { it != 0 } + outputChecker = { s -> (s =~ /Cleaner (0x)?[0-9a-fA-F]+ was disposed during program exit/).find() } +} + +standaloneTest("cleaner_in_tls_main_without_checker") { + enabled = (project.testTarget != 'wasm32') // Cleaners need workers + source = "runtime/basic/cleaner_in_tls_main_without_checker.kt" +} + +standaloneTest("cleaner_in_tls_main_with_checker") { + enabled = (project.testTarget != 'wasm32') // Cleaners need workers + source = "runtime/basic/cleaner_in_tls_main_with_checker.kt" + expectedExitStatusChecker = { it != 0 } + outputChecker = { s -> (s =~ /Cleaner (0x)?[0-9a-fA-F]+ was disposed during program exit/).find() } +} + +standaloneTest("cleaner_in_tls_worker") { + enabled = (project.testTarget != 'wasm32') // Cleaners need workers + source = "runtime/basic/cleaner_in_tls_worker.kt" + flags = ['-Xopt-in=kotlin.native.internal.InternalForKotlinNative'] +} + +standaloneTest("worker_bound_reference0") { + enabled = (project.testTarget != 'wasm32') // Workers need pthreads. + source = "runtime/concurrent/worker_bound_reference0.kt" + flags = ['-tr'] +} + +task worker0(type: KonanLocalTest) { + enabled = (project.testTarget != 'wasm32') // Workers need pthreads. + goldValue = "Got Input processed\nOK\n" + source = "runtime/workers/worker0.kt" +} + +task worker1(type: KonanLocalTest) { + enabled = (project.testTarget != 'wasm32') // Workers need pthreads. + goldValue = "OK\n" + source = "runtime/workers/worker1.kt" +} + +task worker2(type: KonanLocalTest) { + enabled = (project.testTarget != 'wasm32') // Workers need pthreads. + goldValue = "OK\n" + source = "runtime/workers/worker2.kt" +} + +task worker3(type: KonanLocalTest) { + enabled = (project.testTarget != 'wasm32') // Workers need pthreads. + goldValue = "OK\n" + source = "runtime/workers/worker3.kt" +} + +task worker4(type: KonanLocalTest) { + enabled = (project.testTarget != 'wasm32') // Workers need pthreads. + goldValue = "Got 42\nOK\n" + source = "runtime/workers/worker4.kt" +} + +// This tests changes main thread worker queue state, so better be executed alone. +standaloneTest("worker5") { + enabled = (project.testTarget != 'wasm32') // Workers need pthreads. + goldValue = "Got 3\nOK\n" + source = "runtime/workers/worker5.kt" +} + +task worker6(type: KonanLocalTest) { + enabled = (project.testTarget != 'wasm32') // Workers need pthreads. + goldValue = "Got 42\nOK\n" + source = "runtime/workers/worker6.kt" +} + +task worker7(type: KonanLocalTest) { + enabled = (project.testTarget != 'wasm32') // Workers need pthreads. + goldValue = "Input\nGot kotlin.Unit\nOK\n" + source = "runtime/workers/worker7.kt" +} + +task worker8(type: KonanLocalTest) { + enabled = (project.testTarget != 'wasm32') // Workers need pthreads. + goldValue = "SharedData(string=Hello, int=10, member=SharedDataMember(double=0.1))\nGot kotlin.Unit\nOK\n" + source = "runtime/workers/worker8.kt" +} + +task worker9(type: KonanLocalTest) { + enabled = (project.testTarget != 'wasm32') // Workers need pthreads. + goldValue = "zzz\n42\nOK\nfirst 2\nsecond 3\nfrozen OK\n" + source = "runtime/workers/worker9.kt" +} + +task worker10(type: KonanLocalTest) { + enabled = (project.testTarget != 'wasm32') // Workers need pthreads. + goldValue = "OK\ntrue\ntrue\n" + source = "runtime/workers/worker10.kt" +} + +task worker11(type: KonanLocalTest) { + enabled = (project.testTarget != 'wasm32') // Workers need pthreads. + goldValue = "OK\n" + source = "runtime/workers/worker11.kt" +} + +task freeze0(type: KonanLocalTest) { + enabled = (project.testTarget != 'wasm32') // No workers on WASM. + goldValue = "frozen bit is true\n" + + "Worker: SharedData(string=Hello, int=10, member=SharedDataMember(double=0.1))\n" + + "Main: SharedData(string=Hello, int=10, member=SharedDataMember(double=0.1))\n" + + "OK\n" + source = "runtime/workers/freeze0.kt" +} + +task freeze1(type: KonanLocalTest) { + enabled = (project.testTarget != 'wasm32') // No exceptions on WASM. + goldValue = "OK, cannot mutate frozen\n" + source = "runtime/workers/freeze1.kt" +} + +task freeze_stress(type: KonanLocalTest) { + enabled = (project.testTarget != 'wasm32') // No exceptions on WASM. + goldValue = "OK\n" + source = "runtime/workers/freeze_stress.kt" +} + +task freeze2(type: KonanLocalTest) { + enabled = (project.testTarget != 'wasm32') // No exceptions on WASM. + goldValue = + "Worker 1: Hello world\n" + "Worker2: 42\n" + + "Worker3: 239.0\n" + "Worker4: a\n" + "OK\n" + source = "runtime/workers/freeze2.kt" +} + +task freeze3(type: KonanLocalTest) { + enabled = (project.testTarget != 'wasm32') // No exceptions on WASM. + goldValue = "OK\n" + source = "runtime/workers/freeze3.kt" +} + +task freeze4(type: KonanLocalTest) { + enabled = (project.testTarget != 'wasm32') // No exceptions on WASM. + goldValue = "OK\n" + source = "runtime/workers/freeze4.kt" +} + +task freeze5(type: KonanLocalTest) { + goldValue = "OK\n" + source = "runtime/workers/freeze5.kt" +} + +task freeze6(type: KonanLocalTest) { + enabled = (project.testTarget != 'wasm32') // No exceptions on WASM. + goldValue = "OK\nOK\n" + source = "runtime/workers/freeze6.kt" +} + +task atomic0(type: KonanLocalTest) { + enabled = (project.testTarget != 'wasm32') // Workers need pthreads. + goldValue = "35\n" + "20\n" + "OK\n" + source = "runtime/workers/atomic0.kt" +} + +standaloneTest("atomic1") { + // Note: This test reproduces a race, so it'll start flaking if problem is reintroduced. + enabled = false // Needs USE_CYCLIC_GC, which is disabled. + source = "runtime/workers/atomic1.kt" +} + +task lazy0(type: KonanLocalTest) { + enabled = (project.testTarget != 'wasm32') // Workers need pthreads. + goldValue = "OK\n" + source = "runtime/workers/lazy0.kt" +} + +task lazy1(type: KonanLocalTest) { + enabled = (project.testTarget != 'wasm32') // Need exceptions. + goldValue = "OK\n" + source = "runtime/workers/lazy1.kt" +} + +standaloneTest("lazy2") { + goldValue = "123\nOK\n" + source = "runtime/workers/lazy2.kt" +} + +standaloneTest("lazy3") { + source = "runtime/workers/lazy3.kt" +} + +task mutableData1(type: KonanLocalTest) { + enabled = (project.testTarget != 'wasm32') // Workers need pthreads. Need exceptions + source = "runtime/workers/mutableData1.kt" +} + +task enumIdentity(type: KonanLocalTest) { + enabled = (project.testTarget != 'wasm32') // Workers need pthreads. + goldValue = "true\n" + source = "runtime/workers/enum_identity.kt" +} + +standaloneTest("leakWorker") { + disabled = project.globalTestArgs.contains('-opt') || (project.testTarget == 'wasm32') // Needs debug build and pthreads. + source = "runtime/workers/leak_worker.kt" + flags = ['-g'] + expectedExitStatusChecker = { it != 0 } + outputChecker = { s -> s.contains("Unfinished workers detected, 1 workers leaked!") } +} + +standaloneTest("leakMemoryWithWorkerTermination") { + disabled = project.globalTestArgs.contains('-opt') || (project.testTarget == 'wasm32') // Needs debug build and pthreads. + source = "runtime/workers/leak_memory_with_worker_termination.kt" + flags = ['-g'] + expectedExitStatusChecker = { it != 0 } + outputChecker = { s -> s.contains("Memory leaks detected, 1 objects leaked!") } +} + +task superFunCall(type: KonanLocalTest) { + goldValue = "\n\n" + source = "codegen/basics/superFunCall.kt" +} + +task superGetterCall(type: KonanLocalTest) { + goldValue = "\n\n" + source = "codegen/basics/superGetterCall.kt" +} + +task superSetterCall(type: KonanLocalTest) { + goldValue = "zzz\nzzz\n" + source = "codegen/basics/superSetterCall.kt" +} + +task enum0(type: KonanLocalTest) { + goldValue = "VALUE\n" + source = "codegen/enum/test0.kt" +} + +task enum1(type: KonanLocalTest) { + goldValue = "z12\n" + source = "codegen/enum/test1.kt" +} + +task enum_valueOf(type: KonanLocalTest) { + goldValue = "E1\nE2\nE3\nE1\nE2\nE3\n" + source = "codegen/enum/valueOf.kt" +} + +task enum_values(type: KonanLocalTest) { + goldValue = "E3\nE1\nE2\nE3\nE1\nE2\n" + source = "codegen/enum/values.kt" +} + +task enum_vCallNoEntryClass(type: KonanLocalTest) { + goldValue = "('z3', 3)\n" + source = "codegen/enum/vCallNoEntryClass.kt" +} + +task enum_vCallWithEntryClass(type: KonanLocalTest) { + goldValue = "z1z2\n" + source = "codegen/enum/vCallWithEntryClass.kt" +} + +task enum_companionObject(type: KonanLocalTest) { + goldValue = "OK\n" + source = "codegen/enum/companionObject.kt" +} + +task enum_interfaceCallNoEntryClass(type: KonanLocalTest) { + goldValue = "('z3', 3)\n('z3', 3)\n" + source = "codegen/enum/interfaceCallNoEntryClass.kt" +} + +task enum_interfaceCallWithEntryClass(type: KonanLocalTest) { + goldValue = "z1z2\nz1z2\n" + source = "codegen/enum/interfaceCallWithEntryClass.kt" +} + +linkTest("enum_linkTest") { + goldValue = "42\n117\n-1\n" + source = "codegen/enum/linkTest_main.kt" + lib = "codegen/enum/linkTest_lib.kt" +} + +task enum_varargParam(type: KonanLocalTest) { + goldValue = "3\n" + source = "codegen/enum/varargParam.kt" +} + +task enum_nested(type: KonanLocalTest) { + goldValue = "A\nC\n" + source = "codegen/enum/nested.kt" +} + +task enum_isFrozen(type: KonanLocalTest) { + goldValue = "true\n" + source = "codegen/enum/isFrozen.kt" +} + +task enum_loop(type: KonanLocalTest) { + goldValue = "Z\nZ\n" + source = "codegen/enum/loop.kt" +} + +task enum_reorderedArguments(type: KonanLocalTest) { + source = "codegen/enum/reorderedArguments.kt" +} + +standaloneTest('switchLowering') { + goldValue = "EnumA.A\nok\nok\nok\nok\nok\n" + source = "codegen/enum/switchLowering.kt" + flags = ['-XXLanguage:-ProhibitComparisonOfIncompatibleEnums', '-e', 'codegen.enum.switchLowering.main'] +} + +task enum_lambdaInDefault(type: KonanLocalTest) { + goldValue = "Q\n" + source = "codegen/enum/lambdaInDefault.kt" +} + +linkTest("mangling") { + goldValue = + "Int direct [1, 2, 3, 4]\n" + + "out Number direct [9, 10, 11, 12]\n" + + "star direct [5, 6, 7, 8]\n" + + "Int param [1, 2, 3, 4]\n" + + "out Number param [9, 10, 11, 12]\n" + + "star param [5, 6, 7, 8]\n" + + "no constructors {}\n" + + "single constructor some string\n" + + "two constructors 17\n" + source = "mangling/mangling.kt" + lib = "mangling/manglinglib.kt" +} + +task innerClass_simple(type: KonanLocalTest) { + goldValue = "OK\n" + source = "codegen/innerClass/simple.kt" +} + +task innerClass_getOuterVal(type: KonanLocalTest) { + goldValue = "OK\n" + source = "codegen/innerClass/getOuterVal.kt" +} + +task innerClass_generic(type: KonanLocalTest) { + goldValue = "OK\n" + source = "codegen/innerClass/generic.kt" +} + +task innerClass_doubleInner(type: KonanLocalTest) { + goldValue = "OK\n" + source = "codegen/innerClass/doubleInner.kt" +} + +task innerClass_qualifiedThis(type: KonanLocalTest) { + goldValue = "OK\n" + source = "codegen/innerClass/qualifiedThis.kt" +} + +task innerClass_superOuter(type: KonanLocalTest) { + goldValue = "OK\n" + source = "codegen/innerClass/superOuter.kt" +} + +task innerClass_noPrimaryConstructor(type: KonanLocalTest) { + goldValue = "OK\nOK\n" + source = "codegen/innerClass/noPrimaryConstructor.kt" +} + +task innerClass_secondaryConstructor(type: KonanLocalTest) { + goldValue = "42\n" + source = "codegen/innerClass/secondaryConstructor.kt" +} + +linkTest("innerClass_linkTest") { + source = "codegen/innerClass/linkTest_main.kt" + lib = "codegen/innerClass/linkTest_lib.kt" +} + +task localClass_localHierarchy(type: KonanLocalTest) { + goldValue = "OK\n" + source = "codegen/localClass/localHierarchy.kt" +} + +task localClass_objectExpressionInProperty(type: KonanLocalTest) { + goldValue = "OK\n" + source = "codegen/localClass/objectExpressionInProperty.kt" +} + +task localClass_objectExpressionInInitializer(type: KonanLocalTest) { + goldValue = "OK\n" + source = "codegen/localClass/objectExpressionInInitializer.kt" +} + +task localClass_innerWithCapture(type: KonanLocalTest) { + goldValue = "OK\n" + source = "codegen/localClass/innerWithCapture.kt" +} + +task localClass_innerTakesCapturedFromOuter(type: KonanLocalTest) { + goldValue = "0\n1\n" + source = "codegen/localClass/innerTakesCapturedFromOuter.kt" +} + +task localClass_virtualCallFromConstructor(type: KonanLocalTest) { + goldValue = "OK\n" + source = "codegen/localClass/virtualCallFromConstructor.kt" +} + +task localClass_noPrimaryConstructor(type: KonanLocalTest) { + goldValue = "OKOK\n" + source = "codegen/localClass/noPrimaryConstructor.kt" +} + +task localClass_localFunctionCallFromLocalClass(type: KonanLocalTest) { + goldValue = "OK\n" + source = "codegen/localClass/localFunctionCallFromLocalClass.kt" +} + +task localClass_localFunctionInLocalClass(type: KonanLocalTest) { + goldValue = "OK\n" + source = "codegen/localClass/localFunctionInLocalClass.kt" +} + +task localClass_tryCatch(type: KonanLocalTest) { + goldValue = "" + source = "codegen/localClass/tryCatch.kt" +} + +task function_localFunction(type : KonanLocalTest) { + goldValue = "OK\n" + source = "codegen/function/localFunction.kt" +} + +task function_localFunction2(type : KonanLocalTest) { + goldValue = "OK\n" + source = "codegen/function/localFunction2.kt" +} + +task function_localFunction3(type : KonanLocalTest) { + goldValue = "OK\n" + source = "codegen/function/localFunction3.kt" +} + +task initializers_correctOrder1(type: KonanLocalTest) { + goldValue = "42\n" + source = "codegen/initializers/correctOrder1.kt" +} + +task initializers_correctOrder2(type: KonanLocalTest) { + goldValue = "42\n" + source = "codegen/initializers/correctOrder2.kt" +} + +linkTest("initializers_linkTest1") { + goldValue = "1200\n" + source = "codegen/initializers/linkTest1_main.kt" + lib = "codegen/initializers/linkTest1_lib.kt" +} + +linkTest("initializers_linkTest2") { + goldValue = "2\n" + source = "codegen/initializers/linkTest2_main.kt" + lib = "codegen/initializers/linkTest2_lib.kt" +} + +linkTest("initializers_sharedVarInInitBlock") { + source = "codegen/initializers/sharedVarInInitBlock_main.kt" + lib = "codegen/initializers/sharedVarInInitBlock_lib.kt" +} + +task arithmetic_basic(type: KonanLocalTest) { + source = "codegen/arithmetic/basic.kt" +} + +task arithmetic_division(type: KonanLocalTest) { + expectedFail = (project.testTarget == 'wasm32') // Uses exceptions. + source = "codegen/arithmetic/division.kt" +} + +task arithmetic_github1856(type: KonanLocalTest) { + source = "codegen/arithmetic/github1856.kt" +} + +task bridges_test0(type: KonanLocalTest) { + goldValue = "42\n42\n" + source = "codegen/bridges/test0.kt" +} + +task bridges_test1(type: KonanLocalTest) { + goldValue = "1042\n" + source = "codegen/bridges/test1.kt" +} + +task bridges_test2(type: KonanLocalTest) { + goldValue = "42\n42\n" + source = "codegen/bridges/test2.kt" +} + +task bridges_test3(type: KonanLocalTest) { + goldValue = "OK\n" + source = "codegen/bridges/test3.kt" +} + +task bridges_test4(type: KonanLocalTest) { + goldValue = "42\n42\n" + source = "codegen/bridges/test4.kt" +} + +task bridges_test5(type: KonanLocalTest) { + goldValue = "OK\n" + source = "codegen/bridges/test5.kt" +} + +task bridges_test6(type: KonanLocalTest) { + goldValue = "42\n42\n42\n42\n42\n" + source = "codegen/bridges/test6.kt" +} + +task bridges_test7(type: KonanLocalTest) { + goldValue = "OK\n" + source = "codegen/bridges/test7.kt" +} + +task bridges_test8(type: KonanLocalTest) { + goldValue = "OK\n" + source = "codegen/bridges/test8.kt" +} + +task bridges_test9(type: KonanLocalTest) { + goldValue = "OK\n" + source = "codegen/bridges/test9.kt" +} + +task bridges_test10(type: KonanLocalTest) { + goldValue = "42\n42\n" + source = "codegen/bridges/test10.kt" +} + +task bridges_test11(type: KonanLocalTest) { + goldValue = "42\n42\n42\n" + source = "codegen/bridges/test11.kt" +} + +task bridges_test12(type: KonanLocalTest) { + goldValue = "B: 42\nC: 42\n" + source = "codegen/bridges/test12.kt" +} + +task bridges_test13(type: KonanLocalTest) { + goldValue = "42\n42\n" + source = "codegen/bridges/test13.kt" +} + +task bridges_test14(type: KonanLocalTest) { + goldValue = "42\n56\n42\n56\n56\n42\n156\n142\n" + source = "codegen/bridges/test14.kt" +} + +task bridges_test15(type: KonanLocalTest) { + goldValue = "OK\n" + source = "codegen/bridges/test15.kt" +} + +task bridges_test16(type: KonanLocalTest) { + goldValue = "OK\nOK\n" + source = "codegen/bridges/test16.kt" +} + +task bridges_test17(type: KonanLocalTest) { + goldValue = "42\n42\n42\n42\n" + source = "codegen/bridges/test17.kt" +} + +task bridges_test18(type: KonanLocalTest) { + goldValue = "kotlin.Unit\n" + source = "codegen/bridges/test18.kt" +} + +linkTest("bridges_linkTest") { + goldValue = "42\n42\n42\n" + source = "codegen/bridges/linkTest_main.kt" + lib = "codegen/bridges/linkTest_lib.kt" +} + +linkTest("bridges_linkTest2") { + goldValue = "true\n" + source = "codegen/bridges/linkTest2_main.kt" + lib = "codegen/bridges/linkTest2_lib.kt" +} + +task bridges_special(type: KonanLocalTest) { + goldValue = "Ok\n" + source = "codegen/bridges/special.kt" +} + +task bridges_nativePointed(type: KonanLocalTest) { + source = "codegen/bridges/nativePointed.kt" +} + +task returnTypeSignature(type: KonanLocalTest) { + source = "codegen/bridges/returnTypeSignature.kt" +} + +task classDelegation_method(type: KonanLocalTest) { + goldValue = "OKOK\n" + source = "codegen/classDelegation/method.kt" +} + +task classDelegation_property(type: KonanLocalTest) { + goldValue = "4242\n" + source = "codegen/classDelegation/property.kt" +} + +task classDelegation_generic(type: KonanLocalTest) { + goldValue = "OK\n" + source = "codegen/classDelegation/generic.kt" +} + +task classDelegation_withBridge(type: KonanLocalTest) { + goldValue = "OK\n" + source = "codegen/classDelegation/withBridge.kt" +} + +linkTest("classDelegation_linkTest") { + goldValue = "qxx\n123\n42\n117\nzzz\n" + source = "codegen/classDelegation/linkTest_main.kt" + lib = "codegen/classDelegation/linkTest_lib.kt" +} + +standaloneTest("contracts") { + flags = [ '-Xopt-in=kotlin.RequiresOptIn', '-tr' ] + source = "codegen/contracts/contracts.kt" +} + +task delegatedProperty_simpleVal(type: KonanLocalTest) { + goldValue = "x\n42\n" + source = "codegen/delegatedProperty/simpleVal.kt" +} + +task delegatedProperty_simpleVar(type: KonanLocalTest) { + goldValue = "get x\n42\nset x\nget x\n117\n" + source = "codegen/delegatedProperty/simpleVar.kt" +} + +task delegatedProperty_packageLevel(type: KonanLocalTest) { + goldValue = "x\n42\n" + source = "codegen/delegatedProperty/packageLevel.kt" +} + +task delegatedProperty_local(type: KonanLocalTest) { + goldValue = "x\n42\n" + source = "codegen/delegatedProperty/local.kt" +} + +linkTest("delegatedProperty_delegatedOverride") { + goldValue = "156\nx\n117\n42\n" + source = "codegen/delegatedProperty/delegatedOverride_main.kt" + lib = "codegen/delegatedProperty/delegatedOverride_lib.kt" +} + +linkTest("delegatedProperty_correctFieldsOrder") { + goldValue = "qxx\n117\nzzz\nqzz\n" + source = "codegen/delegatedProperty/correctFieldsOrder_main.kt" + lib = "codegen/delegatedProperty/correctFieldsOrder_lib.kt" +} + +task delegatedProperty_lazy(type: KonanLocalTest) { + goldValue = "computed!\nHello\nHello\n" + source = "codegen/delegatedProperty/lazy.kt" +} + +task delegatedProperty_observable(type: KonanLocalTest) { + goldValue = " -> first\nfirst -> second\n" + source = "codegen/delegatedProperty/observable.kt" +} + +task delegatedProperty_map(type: KonanLocalTest) { + goldValue = "John Doe\n25\n" + source = "codegen/delegatedProperty/map.kt" +} + +task propertyCallableReference_valClass(type: KonanLocalTest) { + goldValue = "42\n117\n" + source = "codegen/propertyCallableReference/valClass.kt" +} + +task propertyCallableReference_valModule(type: KonanLocalTest) { + goldValue = "42\n" + source = "codegen/propertyCallableReference/valModule.kt" +} + +task propertyCallableReference_varClass(type: KonanLocalTest) { + goldValue = "117\n117\n42\n42\n" + source = "codegen/propertyCallableReference/varClass.kt" +} + +task propertyCallableReference_varModule(type: KonanLocalTest) { + goldValue = "117\n117\n" + source = "codegen/propertyCallableReference/varModule.kt" +} + +task propertyCallableReference_valExtension(type: KonanLocalTest) { + goldValue = "42\n117\n" + source = "codegen/propertyCallableReference/valExtension.kt" +} + +task propertyCallableReference_varExtension(type: KonanLocalTest) { + goldValue = "117\n117\n42\n42\n" + source = "codegen/propertyCallableReference/varExtension.kt" +} + +linkTest("propertyCallableReference_linkTest") { + goldValue = "42\n117\n" + source = "codegen/propertyCallableReference/linkTest_main.kt" + lib = "codegen/propertyCallableReference/linkTest_lib.kt" +} + +task propertyCallableReference_dynamicReceiver(type: KonanLocalTest) { + goldValue = "42\n" + source = "codegen/propertyCallableReference/dynamicReceiver.kt" +} + +task lateinit_initialized(type: KonanLocalTest) { + goldValue = "zzz\n" + source = "codegen/lateinit/initialized.kt" +} + +task lateinit_notInitialized(type: KonanLocalTest) { + expectedFail = (project.testTarget == 'wasm32') // Uses exceptions. + goldValue = "OK\n" + source = "codegen/lateinit/notInitialized.kt" +} + +task lateinit_inBaseClass(type: KonanLocalTest) { + goldValue = "42\n" + source = "codegen/lateinit/inBaseClass.kt" +} + +task lateinit_localInitialized(type: KonanLocalTest) { + goldValue = "zzz\n" + source = "codegen/lateinit/localInitialized.kt" +} + +task lateinit_localNotInitialized(type: KonanLocalTest) { + expectedFail = (project.testTarget == 'wasm32') // Uses exceptions. + goldValue = "OK\n" + source = "codegen/lateinit/localNotInitialized.kt" +} + +task lateinit_localCapturedInitialized(type: KonanLocalTest) { + goldValue = "zzz\n" + source = "codegen/lateinit/localCapturedInitialized.kt" +} + +task lateinit_localCapturedNotInitialized(type: KonanLocalTest) { + expectedFail = (project.testTarget == 'wasm32') // Uses exceptions. + goldValue = "OK\n" + source = "codegen/lateinit/localCapturedNotInitialized.kt" +} + +task lateinit_isInitialized(type: KonanLocalTest) { + goldValue = "false\ntrue\n" + source = "codegen/lateinit/isInitialized.kt" +} + +task lateinit_globalIsInitialized(type: KonanLocalTest) { + goldValue = "false\ntrue\n" + source = "codegen/lateinit/globalIsInitialized.kt" +} + +task lateinit_innerIsInitialized(type: KonanLocalTest) { + goldValue = "OK\n" + source = "codegen/lateinit/innerIsInitialized.kt" +} + +task kclass0(type: KonanLocalTest) { + source = "codegen/kclass/kclass0.kt" +} + +task kclass1(type: KonanLocalTest) { + goldValue = "OK :D\n" + source = "codegen/kclass/kclass1.kt" +} + +task kclassEnumArgument(type: KonanLocalTest) { + goldValue = "String\n" + source = "codegen/kclass/kClassEnumArgument.kt" +} + +task ktype1(type: KonanLocalTest) { + source = "codegen/ktype/ktype1.kt" +} + +task ktype_nonReified(type: KonanLocalTest) { + source = "codegen/ktype/nonReified.kt" +} + +task associatedObjects1(type: KonanLocalTest) { + source = "codegen/associatedObjects/associatedObjects1.kt" +} + +task coroutines_simple(type: KonanLocalTest) { + goldValue = "42\n" + source = "codegen/coroutines/simple.kt" +} + +task coroutines_degenerate1(type: KonanLocalTest) { + goldValue = "s1\n" + source = "codegen/coroutines/degenerate1.kt" +} + +task coroutines_degenerate2(type: KonanLocalTest) { + goldValue = "s2\ns1\n" + source = "codegen/coroutines/degenerate2.kt" +} + +task coroutines_withReceiver(type: KonanLocalTest) { + goldValue = "42\n" + source = "codegen/coroutines/withReceiver.kt" +} + +task coroutines_correctOrder1(type: KonanLocalTest) { + goldValue = "f1\ns1\nf2\n160\n" + source = "codegen/coroutines/correctOrder1.kt" +} + +task coroutines_controlFlow_chain(type: KonanLocalTest) { + source = "codegen/coroutines/controlFlow_chain.kt" +} + +task coroutines_controlFlow_if1(type: KonanLocalTest) { + goldValue = "f1\ns1\nf3\n84\n" + source = "codegen/coroutines/controlFlow_if1.kt" +} + +task coroutines_controlFlow_if2(type: KonanLocalTest) { + goldValue = "f1\ns1\nf2\n43\n" + source = "codegen/coroutines/controlFlow_if2.kt" +} + +task coroutines_controlFlow_finally1(type: KonanLocalTest) { + goldValue = "f1\ns1\n117\n" + source = "codegen/coroutines/controlFlow_finally1.kt" +} + +task coroutines_controlFlow_finally2(type: KonanLocalTest) { + goldValue = "f1\ns1\n117\n" + source = "codegen/coroutines/controlFlow_finally2.kt" +} + +task coroutines_controlFlow_finally3(type: KonanLocalTest) { + goldValue = "f1\ns1\n117\n" + source = "codegen/coroutines/controlFlow_finally3.kt" +} + +task coroutines_controlFlow_finally4(type: KonanLocalTest) { + goldValue = "s1\nfinally\n42\n" + source = "codegen/coroutines/controlFlow_finally4.kt" +} + +task coroutines_controlFlow_finally5(type: KonanLocalTest) { + expectedFail = (project.testTarget == 'wasm32') // Uses exceptions. + goldValue = "s1\nf2\nfinally\n1\n" + source = "codegen/coroutines/controlFlow_finally5.kt" +} + +task coroutines_controlFlow_finally6(type: KonanLocalTest) { + expectedFail = (project.testTarget == 'wasm32') // Uses exceptions. + goldValue = "s1\nfinally\nerror\n0\n" + source = "codegen/coroutines/controlFlow_finally6.kt" +} + +task coroutines_controlFlow_finally7(type: KonanLocalTest) { + expectedFail = (project.testTarget == 'wasm32') // Uses exceptions. + goldValue = "s1\nf2\nfinally1\ns2\nfinally2\n42\n" + source = "codegen/coroutines/controlFlow_finally7.kt" +} + +task coroutines_controlFlow_inline1(type: KonanLocalTest) { + goldValue = "42\n" + source = "codegen/coroutines/controlFlow_inline1.kt" +} + +task coroutines_controlFlow_inline2(type: KonanLocalTest) { + goldValue = "s1\n42\n" + source = "codegen/coroutines/controlFlow_inline2.kt" +} + +task coroutines_controlFlow_inline3(type: KonanLocalTest) { + goldValue = "f1\ns1\n42\n" + source = "codegen/coroutines/controlFlow_inline3.kt" +} + +task coroutines_controlFlow_tryCatch1(type: KonanLocalTest) { + goldValue = "s1\n42\n" + source = "codegen/coroutines/controlFlow_tryCatch1.kt" +} + +task coroutines_controlFlow_tryCatch2(type: KonanLocalTest) { + goldValue = "s1\n42\n" + source = "codegen/coroutines/controlFlow_tryCatch2.kt" +} + +task coroutines_controlFlow_tryCatch3(type: KonanLocalTest) { + expectedFail = (project.testTarget == 'wasm32') // Uses exceptions. + goldValue = "s2\nf2\n1\n" + source = "codegen/coroutines/controlFlow_tryCatch3.kt" +} + +task coroutines_controlFlow_tryCatch4(type: KonanLocalTest) { + expectedFail = (project.testTarget == 'wasm32') // Uses exceptions. + goldValue = "s2\nf2\n1\n" + source = "codegen/coroutines/controlFlow_tryCatch4.kt" +} + +task coroutines_controlFlow_tryCatch5(type: KonanLocalTest) { + expectedFail = (project.testTarget == 'wasm32') // Uses exceptions. + goldValue = "s2\ns1\nError\n42\n" + source = "codegen/coroutines/controlFlow_tryCatch5.kt" +} + +task coroutines_controlFlow_while1(type: KonanLocalTest) { + goldValue = "s3\ns3\ns3\ns3\n3\n" + source = "codegen/coroutines/controlFlow_while1.kt" +} + +task coroutines_controlFlow_while2(type: KonanLocalTest) { + goldValue = "s3\ns3\ns3\n3\n" + source = "codegen/coroutines/controlFlow_while2.kt" +} + +task coroutines_returnsNothing1(type: KonanLocalTest) { + goldValue = "OK\n" + source = "codegen/coroutines/returnsNothing1.kt" +} + +task coroutines_returnsUnit1(type: KonanLocalTest) { + goldValue = "117\ns1\n0\n" + source = "codegen/coroutines/returnsUnit1.kt" +} + +task coroutines_coroutineContext1(type: KonanLocalTest) { + goldValue = "EmptyCoroutineContext\n" + source = "codegen/coroutines/coroutineContext1.kt" +} + +task coroutines_coroutineContext2(type: KonanLocalTest) { + goldValue = "EmptyCoroutineContext\n" + source = "codegen/coroutines/coroutineContext2.kt" +} + +task coroutines_anonymousObject(type: KonanLocalTest) { + goldValue = "zzz\n" + source = "codegen/coroutines/anonymousObject.kt" +} + +task coroutines_functionReference_simple(type: KonanLocalTest) { + goldValue = "42\n" + source = "codegen/coroutines/functionReference_simple.kt" +} + +task coroutines_functionReference_eqeq_name(type: KonanLocalTest) { + goldValue = "" + source = "codegen/coroutines/functionReference_eqeq_name.kt" +} + +task coroutines_functionReference_invokeAsFunction(type: KonanLocalTest) { + goldValue = "159\n" + source = "codegen/coroutines/functionReference_invokeAsFunction.kt" +} + +task coroutines_functionReference_lambdaAsSuspendLambda(type: KonanLocalTest) { + goldValue = "" + source = "codegen/coroutines/functionReference_lambdaAsSuspendLambda.kt" +} + +task coroutines_kt41394(type: KonanLocalTest) { + goldValue = "" + source = "codegen/coroutines/kt41394.kt" +} + +standaloneTest('coroutines_suspendConversion') { + goldValue = "" + source = "codegen/coroutines/suspendConversion.kt" + flags = ['-XXLanguage:+SuspendConversion'] +} + +task AbstractMutableCollection(type: KonanLocalTest) { + expectedExitStatus = 0 + source = "runtime/collections/AbstractMutableCollection.kt" +} + +task BitSet(type: KonanLocalTest) { + expectedFail = (project.testTarget == 'wasm32') // Uses exceptions. + expectedExitStatus = 0 + source = "runtime/collections/BitSet.kt" +} + +task stack_array(type: KonanLocalTest) { + goldValue = "true\n3\n" + source = "runtime/collections/stack_array.kt" +} + +task array0(type: KonanLocalTest) { + goldValue = "5\n6\n7\n8\n9\n10\n11\n12\n13\n" + source = "runtime/collections/array0.kt" +} + +task array1(type: KonanLocalTest) { + goldValue = "4 2\n1-1\n69\n38\n" + source = "runtime/collections/array1.kt" +} + +task array2(type: KonanLocalTest) { + goldValue = "0\n2\n4\n6\n8\n40\n" + source = "runtime/collections/array2.kt" +} + +task array3(type: KonanLocalTest) { + goldValue = "1 2 3 7 8 9 -128 -1 \n1 2 3 7 8 9 -128 -1 \n" + source = "runtime/collections/array3.kt" +} + +task array4(type: KonanLocalTest) { + disabled = (project.testTarget == 'wasm32') // Uses exceptions. + goldValue = "OK\n" + source = "runtime/collections/array4.kt" +} + +task array5(type: KonanLocalTest) { + disabled = (project.testTarget == 'wasm32') // Uses exceptions. + source = "runtime/collections/array5.kt" +} + +task typed_array0(type: KonanLocalTest) { + goldValue = "OK\n" + source = "runtime/collections/typed_array0.kt" +} + +task typed_array1(type: KonanLocalTest) { + enabled = (project.testTarget != 'wasm32') // No exceptions on WASM. + goldValue = "OK\n" + source = "runtime/collections/typed_array1.kt" +} + + +task sort0(type: KonanLocalTest) { + goldValue = "[a, b, x]\n[-1, 0, 42, 239, 100500]\n" + source = "runtime/collections/sort0.kt" +} + +task sort1(type: KonanLocalTest) { + goldValue = "[a, b, x]\n[-1, 0, 42, 239, 100500]\n" + source = "runtime/collections/sort1.kt" +} + +task sortWith(type: KonanLocalTest) { + source = "runtime/collections/SortWith.kt" +} + +task if_else(type: KonanLocalTest) { + source = "codegen/branching/if_else.kt" +} + +task immutable_binary_blob_in_lambda(type: KonanLocalTest) { + source = "lower/immutable_blob_in_lambda.kt" + goldValue = "123\n" +} + +task when2(type: KonanLocalTest) { + source = "codegen/branching/when2.kt" +} + +task when5(type: KonanLocalTest) { + source = "codegen/branching/when5.kt" +} + +task when6(type: KonanLocalTest) { + source = "codegen/branching/when6.kt" +} + +task when7(type: KonanLocalTest) { + source = "codegen/branching/when7.kt" +} + +task when8(type: KonanLocalTest) { + source = "codegen/branching/when8.kt" + goldValue = "true\n" +} + +task when9(type: KonanLocalTest) { + goldValue = "Ok\n" + source = "codegen/branching/when9.kt" +} + +task when_through(type: KonanLocalTest) { + source = "codegen/branching/when_through.kt" +} + +task advanced_when2(type: KonanLocalTest) { + source = "codegen/branching/advanced_when2.kt" +} + +task advanced_when5(type: KonanLocalTest) { + source = "codegen/branching/advanced_when5.kt" +} + +task when_with_try1(type: KonanLocalTest) { + goldValue = "null\nnull\n42\n" + source = "codegen/branching/when_with_try1.kt" +} + +task bool_yes(type: KonanLocalTest) { + source = "codegen/function/boolean.kt" +} + +task named(type: KonanLocalTest) { + source = "codegen/function/named.kt" +} + + +task plus_eq(type: KonanLocalTest) { + source = "codegen/function/plus_eq.kt" +} + +task minus_eq(type: KonanLocalTest) { + source = "codegen/function/minus_eq.kt" +} + +task eqeq(type: KonanLocalTest) { + source = "codegen/function/eqeq.kt" +} + +task function_referenceBigArity(type: KonanLocalTest) { + goldValue = "528\n" + source = "codegen/function/referenceBigArity" +} + +task cycle(type: KonanLocalTest) { + source = "codegen/cycles/cycle.kt" +} + +task cycle_do(type: KonanLocalTest) { + source = "codegen/cycles/cycle_do.kt" +} + +task cycle_for(type: KonanLocalTest) { + source = "codegen/cycles/cycle_for.kt" +} + +task abstract_super(type: KonanLocalTest) { + source = "datagen/rtti/abstract_super.kt" +} + +task vtable1(type: KonanLocalTest) { + source = "datagen/rtti/vtable1.kt" +} + +task vtable_any(type: KonanLocalTest) { + source = "datagen/rtti/vtable_any.kt" + goldValue = "[1]\n[2]\n[3]\n[4]\n" +} + +task strdedup1(type: KonanLocalTest) { + goldValue = "true\ntrue\n" + source = "datagen/literals/strdedup1.kt" +} + +task strdedup2(type: KonanLocalTest) { + // TODO: string deduplication across several components seems to require + // linking them as bitcode modules before translating to machine code. + enabled = false + + goldValue = "true\ntrue\n" + source = "datagen/literals/strdedup2.kt" +} + +task empty_string(type: KonanLocalTest) { + goldValue = "\n" + source = "datagen/literals/empty_string.kt" +} + +task intrinsic(type: KonanLocalTest) { + source = "codegen/function/intrinsic.kt" +} + +/* + Disabled until we extract the classes that should be + always present from stdlib into a separate binary. + +linkTest("link") { + goldValue = "0\n" + source = "link/src/bar.kt" + lib = "link/lib" +}( +*/ + +linkTest("link_omit_unused") { + goldValue = "Hello\n" + source = "link/omit/hello.kt" + lib = "link/omit/lib.kt" +} + +standaloneTest("link_default_libs") { + dependsOnPlatformLibs(it) + enabled = (project.testTarget != 'wasm32') // there will be no posix.klib for wasm + goldValue = "sizet = 0\n" + source = "link/default/default.kt" +} + +standaloneTest("link_testLib_explicitly") { + // there are no testLibrary for cross targets yet. + enabled = project.testTarget == null || project.testTarget == project.hostName + + dependsOn 'installTestLibrary' + goldValue = "This is a side effect of a test library linked into the binary.\nYou should not be seeing this.\n\nHello\n" + source = "link/omit/hello.kt" + // We force library inclusion, so need to see the warning banner. + flags = ['-l', 'testLibrary'] + doLast { + def file = new File("$testLibraryDir/testLibrary") + file.deleteDir() + } +} + +linkTest("no_purge_for_dependencies") { + dependsOnPlatformLibs(it) + enabled = (project.testTarget != 'wasm32') // there will be no posix.klib for wasm + goldValue = "linked library\nand symbols from posix available: 17; 1.0\n" + source = "link/purge1/prog.kt" + lib = "link/purge1/lib.kt" +} + +task for0(type: KonanLocalTest) { + goldValue = "2\n3\n4\n" + source = "runtime/basic/for0.kt" +} + +task throw0(type: KonanLocalTest) { + goldValue = "Done\n" + source = "runtime/basic/throw0.kt" +} + +task statements0(type: KonanLocalTest) { + goldValue = "239\n238\n30\n29\n" + source = "runtime/basic/statements0.kt" +} + +standaloneTest("annotations0") { + source = "codegen/annotations/annotations0.kt" + flags = ['-tr'] +} + +task boxing0(type: KonanLocalTest) { + goldValue = "17\n" + source = "codegen/boxing/boxing0.kt" +} + +task boxing1(type: KonanLocalTest) { + goldValue = "1\nfalse\nHello\n" + source = "codegen/boxing/boxing1.kt" +} + +task boxing2(type: KonanLocalTest) { + goldValue = "1\ntrue\nother\n" + source = "codegen/boxing/boxing2.kt" +} + +task boxing3(type: KonanLocalTest) { + goldValue = "42\n" + source = "codegen/boxing/boxing3.kt" +} + +task boxing4(type: KonanLocalTest) { + goldValue = "16\n" + source = "codegen/boxing/boxing4.kt" +} + +task boxing5(type: KonanLocalTest) { + goldValue = "16\n42\n" + source = "codegen/boxing/boxing5.kt" +} + +task boxing6(type: KonanLocalTest) { + goldValue = "42\n16\n" + source = "codegen/boxing/boxing6.kt" +} + +task boxing7(type: KonanLocalTest) { + expectedFail = (project.testTarget == 'wasm32') // Uses exceptions. + goldValue = "1\n0\n" + source = "codegen/boxing/boxing7.kt" +} + +task boxing8(type: KonanLocalTest) { + goldValue = "1\nnull\ntrue\nHello\n" + source = "codegen/boxing/boxing8.kt" +} + +task boxing9(type: KonanLocalTest) { + goldValue = "1\nnull\ntrue\nHello\n2\nnull\ntrue\nHello\n3\n" + source = "codegen/boxing/boxing9.kt" +} + +task boxing10(type: KonanLocalTest) { + goldValue = "Ok\n" + source = "codegen/boxing/boxing10.kt" +} + +task boxing11(type: KonanLocalTest) { + goldValue = "17\n42\n" + source = "codegen/boxing/boxing11.kt" +} + +task boxing12(type: KonanLocalTest) { + goldValue = "18\n" + source = "codegen/boxing/boxing12.kt" +} + +task boxing13(type: KonanLocalTest) { + goldValue = "false\nfalse\ntrue\ntrue\nfalse\nfalse\n" + source = "codegen/boxing/boxing13.kt" +} + +task boxing14(type: KonanLocalTest) { + goldValue = "42\n" + source = "codegen/boxing/boxing14.kt" +} + +task boxing15(type: KonanLocalTest) { + goldValue = "17\n" + source = "codegen/boxing/boxing15.kt" +} + +task boxCache0(type: KonanLocalTest) { + goldValue = "2\n256\n256\n256\n256\n256\n" + source = "codegen/boxing/box_cache0.kt" +} + +task interface0(type: KonanLocalTest) { + goldValue = "PASSED\n" + source = "runtime/basic/interface0.kt" +} + +task hash0(type: KonanLocalTest) { + goldValue = "239\n0\n97\n1065353216\n1072693248\n1\n0\ntrue\ntrue\n" + source = "runtime/basic/hash0.kt" +} + +task ieee754(type: KonanLocalTest) { + goldValue = "Infinity 2147483647 -1 -1\n" + + "3.4028235E38\n" + + "NAN2SHORT:: 0\n" + + "MAX2SHORT:: -1\n" + + "2147483647 -1\n" + + "FLOAT:: Infinity INT:: 2147483647\n" + + "FLOAT:: 1.7014117E38 INT:: 2147483647\n" + + "FLOAT:: 3.4028235E38 INT:: 2147483647\n" + + "FLOAT:: 3.14 INT:: 3\n" + + "FLOAT:: NaN INT:: 0\n" + + "FLOAT:: -33333.125 INT:: -33333\n" + + "FLOAT:: 1.4E-45 INT:: 0\n" + + "FLOAT:: -Infinity INT:: -2147483648\n" + + "FLOAT:: -1.2 INT:: -1\n" + + "FLOAT:: -12.6 INT:: -12\n" + + "FLOAT:: 2.3 INT:: 2\n" + + "OK\n" + source = "runtime/basic/ieee754.kt" +} + +standaloneTest("hypotenuse") { + source = "runtime/basic/hypot.kt" +} + +task array_list1(type: KonanLocalTest) { + goldValue = "OK\n" + source = "runtime/collections/array_list1.kt" +} + +task array_list2(type: KonanLocalTest) { + enabled = (project.testTarget != 'wasm32') // uses exceptions + goldValue = "OK\n" + source = "runtime/collections/array_list2.kt" +} + +task hash_map0(type: KonanLocalTest) { + goldValue = "OK\n" + source = "runtime/collections/hash_map0.kt" +} + +task hash_set0(type: KonanLocalTest) { + goldValue = "OK\n" + source = "runtime/collections/hash_set0.kt" +} + +task listof0(type: KonanLocalTest) { + goldValue = "abc\n[a, b, c, d]\n[n, s, a]\n" + source = "runtime/collections/listof0.kt" +} + +task listof1(type: KonanLocalTest) { + enabled = false + goldValue = "true\n[a, b, c]\n" + source = "datagen/literals/listof1.kt" +} + + +task moderately_large_array(type: KonanLocalTest) { + goldValue = "0\n" + source = "runtime/collections/moderately_large_array.kt" +} + +task moderately_large_array1(type: KonanLocalTest) { + goldValue = "-45392\n" + source = "runtime/collections/moderately_large_array1.kt" +} + +task string_builder0(type: KonanLocalTest) { + // Cannot be executed in the two-stage mode due to KT-33175. + enabled = !twoStageEnabled + expectedFail = (project.testTarget == 'wasm32') // Uses exceptions. + goldValue = "OK\n" + source = "runtime/text/string_builder0.kt" +} + +task string_builder1(type: KonanLocalTest) { + goldValue = "HelloKotlin\n42\n0.1\ntrue\n\n" + source = "runtime/text/string_builder1.kt" +} + +task string0(type: KonanLocalTest) { + goldValue = "true\ntrue\nПРИВЕТ\nпривет\nПока\ntrue\n" + source = "runtime/text/string0.kt" +} + +task parse0(type: KonanLocalTest) { + goldValue = "false\n" + + "true\n" + + "-1\n" + + "10\n" + + "170\n" + + "30\n" + + "4294967295\n" + + "bad format\n" + + "0.5\n" + + "2.39\n" + source = "runtime/text/parse0.kt" +} + +task to_string0(type: KonanLocalTest) { + goldValue = "OK\n" + source = "runtime/text/to_string0.kt" +} + +task trim(type: KonanLocalTest) { + expectedFail = (project.testTarget == 'wasm32') // Uses exceptions + goldValue = "OK\n" + source = "runtime/text/trim.kt" +} + +task chars0(type: KonanLocalTest) { + expectedFail = (project.testTarget == 'wasm32') // Uses exceptions. + source = "runtime/text/chars0.kt" + expectedExitStatus = 0 +} + +task indexof(type: KonanLocalTest) { + source = "runtime/text/indexof.kt" +} + +task utf8(type: KonanLocalTest) { + // Cannot be executed in the two-stage mode due to KT-33175. + // Uses exceptions so cannot run on wasm. + enabled = !twoStageEnabled && (project.testTarget != 'wasm32') + goldValue = "Hello\nПривет\n\uD800\uDC00\n\n\uFFFD\uFFFD\n\uFFFD12\n\uFFFD12\n12\uFFFD\n\uD83D\uDE25\n\uD83D\uDE25\n" + source = "runtime/text/utf8.kt" +} + +task catch1(type: KonanLocalTest) { + expectedFail = (project.testTarget == 'wasm32') // Uses exceptions. + goldValue = "Before\nCaught Throwable\nDone\n" + source = "runtime/exceptions/catch1.kt" +} + +task catch2(type: KonanLocalTest) { + expectedFail = (project.testTarget == 'wasm32') // Uses exceptions. + goldValue = "Before\nCaught Error\nDone\n" + source = "runtime/exceptions/catch2.kt" +} + +task catch7(type: KonanLocalTest) { + expectedFail = (project.testTarget == 'wasm32') // Uses exceptions. + goldValue = "Error happens\n" + source = "runtime/exceptions/catch7.kt" +} + +task extend_exception(type: KonanLocalTest) { + goldValue = "OK\n" + source = "runtime/exceptions/extend0.kt" +} + +standaloneTest("check_stacktrace_format") { + disabled = !isAppleTarget(project) || project.globalTestArgs.contains('-opt') || (project.testTarget == 'ios_arm64') + flags = ['-g'] + source = "runtime/exceptions/check_stacktrace_format.kt" +} + +standaloneTest("stack_trace_inline") { + disabled = !isAppleTarget(project) || project.globalTestArgs.contains('-opt') || (project.testTarget == 'ios_arm64') + flags = ['-g'] + source = "runtime/exceptions/stack_trace_inline.kt" +} + +standaloneTest("kt-37572") { + disabled = !isAppleTarget(project) || project.globalTestArgs.contains('-opt') || (project.testTarget == 'ios_arm64') + flags = ['-g'] + source = "runtime/exceptions/kt-37572.kt" +} + +standaloneTest("custom_hook") { + enabled = (project.testTarget != 'wasm32') // Uses exceptions. + goldValue = "value 42: Error\n" + expectedExitStatus = 1 + source = "runtime/exceptions/custom_hook.kt" +} + +standaloneTest("runtime_math_exceptions") { + enabled = (project.testTarget != 'wasm32') + source = "stdlib_external/numbers/MathExceptionTest.kt" + flags = ['-tr'] +} + +standaloneTest("runtime_math") { + source = "stdlib_external/numbers/MathTest.kt" + flags = ['-tr'] +} + +standaloneTest("runtime_math_harmony") { + source = "stdlib_external/numbers/HarmonyMathTests.kt" + flags = ['-tr'] +} + +task catch3(type: KonanLocalTest) { + goldValue = "Before\nCaught Throwable\nDone\n" + source = "codegen/try/catch3.kt" +} + +task catch4(type: KonanLocalTest) { + goldValue = "Before\nCaught Error\nDone\n" + source = "codegen/try/catch4.kt" +} + +task catch5(type: KonanLocalTest) { + expectedFail = (project.testTarget == 'wasm32') // Uses exceptions. + goldValue = "Before\nCaught Error\nDone\n" + source = "codegen/try/catch5.kt" +} + +task catch6(type: KonanLocalTest) { + expectedFail = (project.testTarget == 'wasm32') // Uses exceptions. + goldValue = "Before\nCaught Error\nDone\n" + source = "codegen/try/catch6.kt" +} + +task catch8(type: KonanLocalTest) { + goldValue = "Error happens\n" + source = "codegen/try/catch8.kt" +} + +task finally1(type: KonanLocalTest) { + goldValue = "Try\nFinally\nDone\n" + source = "codegen/try/finally1.kt" +} + +task finally2(type: KonanLocalTest) { + goldValue = "Try\nCaught Error\nFinally\nDone\n" + source = "codegen/try/finally2.kt" +} + +task finally3(type: KonanLocalTest) { + goldValue = "Try\nFinally\nCaught Error\nDone\n" + source = "codegen/try/finally3.kt" +} + +task finally4(type: KonanLocalTest) { + goldValue = "Try\nCatch\nFinally\nCaught Exception\nDone\n" + source = "codegen/try/finally4.kt" +} + +task finally5(type: KonanLocalTest) { + goldValue = "Done\nFinally\n0\n" + source = "codegen/try/finally5.kt" +} + +task finally6(type: KonanLocalTest) { + goldValue = "Done\nFinally\n1\n" + source = "codegen/try/finally6.kt" +} + +task finally7(type: KonanLocalTest) { + goldValue = "Done\nFinally\n1\n" + source = "codegen/try/finally7.kt" +} + +task finally8(type: KonanLocalTest) { + goldValue = "Finally 1\nFinally 2\n42\n" + source = "codegen/try/finally8.kt" +} + +task finally9(type: KonanLocalTest) { + goldValue = "Finally 1\nFinally 2\nAfter\n" + source = "codegen/try/finally9.kt" +} + +task finally10(type: KonanLocalTest) { + goldValue = "Finally\nAfter\n" + source = "codegen/try/finally10.kt" +} + +task finally11(type: KonanLocalTest) { + goldValue = "Finally\nCatch 2\nDone\n" + source = "codegen/try/finally11.kt" +} + +task finally_returnsDifferentTypes(type: KonanLocalTest) { + goldValue = "zzz\n42\n" + source = "codegen/try/returnsDifferentTypes.kt" +} + +task scope1(type: KonanLocalTest) { + goldValue = "1\n" + source = "codegen/dataflow/scope1.kt" +} + +task uninitialized_val(type: KonanLocalTest) { + goldValue = "1\n2\n" + source = "codegen/dataflow/uninitialized_val.kt" +} + +task try1(type: KonanLocalTest) { + goldValue = "5\n" + source = "codegen/try/try1.kt" +} + +task try2(type: KonanLocalTest) { + goldValue = "6\n" + source = "codegen/try/try2.kt" +} + +task try3(type: KonanLocalTest) { + goldValue = "6\n" + source = "codegen/try/try3.kt" +} + +task try4(type: KonanLocalTest) { + goldValue = "Try\n5\n" + source = "codegen/try/try4.kt" +} + +task unreachable1(type: KonanLocalTest) { + goldValue = "1\n" + source = "codegen/controlflow/unreachable1.kt" +} + +task break_continue(type: KonanLocalTest) { + goldValue = "foo@l1\nfoo@l2\nfoo@l2\nfoo@l2\nbar@l1\nbar@l2\nbar@l2\nbar@l2\nqux@t1\nqux@l2\nqux@l2\nqux@l2\n" + source = "codegen/controlflow/break.kt" +} + +task break1(type: KonanLocalTest) { + goldValue = "Body\nDone\n" + source = "codegen/controlflow/break1.kt" +} + +task range0(type: KonanLocalTest) { + goldValue = "123\nabcd\n" + source = "runtime/collections/range0.kt" +} + +standaloneTest("args0") { + arguments = ["AAA", "BB", "C"] + goldValue = "AAA\nBB\nC\n" + source = "runtime/basic/args0.kt" +} + +standaloneTest("devirtualization_lateinitInterface") { + disabled = (cacheTesting != null) // Cache is not compatible with -opt. + goldValue = "42\n" + flags = ["-opt"] + source = "codegen/devirtualization/lateinitInterface.kt" +} + +standaloneTest("devirtualization_getter_looking_as_box_function") { + disabled = (cacheTesting != null) // Cache is not compatible with -opt. + goldValue = "box\n" + flags = ["-opt"] + source = "codegen/devirtualization/getter_looking_as_box_function.kt" +} + +standaloneTest("devirtualization_anonymousObject") { + disabled = (cacheTesting != null) // Cache is not compatible with -opt. + goldValue = "zzz\n" + flags = ["-opt"] + source = "codegen/devirtualization/anonymousObject.kt" +} + +task interfaceCallsNCasts_conservativeItable(type: KonanLocalTest) { + goldValue = "539\n5050\n26551140\n" + source = "codegen/interfaceCallsNCasts/conservativeItable.kt" +} + +standaloneTest("multiargs") { + arguments = ["AAA", "BB", "C"] + multiRuns = true + multiArguments = [["1", "2", "3"], ["---"], ["Hello", "world"]] + goldValue = "AAA\nBB\nC\n1\n2\n3\n" + + "AAA\nBB\nC\n---\n" + + "AAA\nBB\nC\nHello\nworld\n" + source = "runtime/basic/args0.kt" +} + +task spread_operator_0(type: KonanLocalTest) { + goldValue = "[K, o, t, l, i, n, , i, s, , c, o, o, l, , l, a, n, g, u, a, g, e]\n" + source = "codegen/basics/spread_operator_0.kt" +} + +task main_exception(type: KonanLocalTest) { + outputChecker = { s -> s.contains("kotlin.Error: Hello!") } + expectedExitStatus = 1 + source = "runtime/basic/main_exception.kt" +} + +task runtime_basic_standard(type: KonanLocalTest) { + source = "runtime/basic/standard.kt" +} + +standaloneTest("runtime_basic_assert_failed") { + expectedExitStatus = 1 + source = "runtime/basic/assert_failed.kt" +} + +standaloneTest("runtime_basic_assert_passed") { + expectedExitStatus = 0 + source = "runtime/basic/assert_passed.kt" +} + +standaloneTest("runtime_basic_assert_disabled") { + expectedExitStatus = 0 + enableKonanAssertions = false + source = "runtime/basic/assert_failed.kt" +} + +task initializers0(type: KonanLocalTest) { + goldValue = "main\n" + + "B::constructor(1)\n" + + "A::companion\n" + + "A::companion::foo\n" + + "A::companion::foo\n" + + "B::constructor(0)\n" + + "B::constructor()\n" + + "A::Obj\n" + + "A::AObj::foo\n" + + "A::AObj::foo\n" + source = "runtime/basic/initializers0.kt" +} + + +task initializers1(type: KonanLocalTest) { + goldValue = "Init Test\n" + + "Done\n" + enabled = false + source = "runtime/basic/initializers1.kt" +} + + +task concatenation(type: KonanLocalTest) { + goldValue = "Hello world 1 2\nHello, a\nHello, b\n" + source = "codegen/basics/concatenation.kt" +} + +task const_infinity(type: KonanLocalTest) { + source = "codegen/basics/const_infinity.kt" +} + +task lambda1(type: KonanLocalTest) { + goldValue = "lambda\n" + source = "codegen/lambda/lambda1.kt" +} + +task lambda2(type: KonanLocalTest) { + arguments = ["arg0"] + goldValue = "arg0\n" + source = "codegen/lambda/lambda2.kt" +} + +task lambda3(type: KonanLocalTest) { + goldValue = "lambda\n" + source = "codegen/lambda/lambda3.kt" +} + +task lambda4(type: KonanLocalTest) { + goldValue = "1\n2\n3\n3\n4\n" + source = "codegen/lambda/lambda4.kt" +} + +task lambda5(type: KonanLocalTest) { + goldValue = "42\n" + source = "codegen/lambda/lambda5.kt" +} + +task lambda6(type: KonanLocalTest) { + goldValue = "42\ncaptured\n" + source = "codegen/lambda/lambda6.kt" +} + +task lambda7(type: KonanLocalTest) { + goldValue = "43\n" + source = "codegen/lambda/lambda7.kt" +} + +task lambda8(type: KonanLocalTest) { + goldValue = "first\n0\nsecond\n0\nfirst\n1\nsecond\n1\n" + source = "codegen/lambda/lambda8.kt" +} + +task lambda9(type: KonanLocalTest) { + goldValue = "0\n0\n1\n0\n0\n1\n1\n1\n" + source = "codegen/lambda/lambda9.kt" +} + +task lambda10(type: KonanLocalTest) { + goldValue = "original\nchanged\n" + source = "codegen/lambda/lambda10.kt" +} + +task lambda11(type: KonanLocalTest) { + goldValue = "first\nsecond\n" + source = "codegen/lambda/lambda11.kt" +} + +task lambda12(type: KonanLocalTest) { + goldValue = "one\ntwo\n" + source = "codegen/lambda/lambda12.kt" +} + +task lambda13(type: KonanLocalTest) { + goldValue = "foo\n" + source = "codegen/lambda/lambda13.kt" +} + +standaloneTest("lambda14") { + source = "codegen/lambda/lambda14.kt" + flags = ['-tr'] +} + +task objectExpression1(type: KonanLocalTest) { + goldValue = "aabb\n" + source = "codegen/objectExpression/expr1.kt" +} + +task objectExpression2(type: KonanLocalTest) { + goldValue = "a\n" + source = "codegen/objectExpression/expr2.kt" +} + +task objectExpression3(type: KonanLocalTest) { + goldValue = "\n1\n2\n" + source = "codegen/objectExpression/expr3.kt" +} + +standaloneTest("initializers2") { + goldValue = "init globalValue2\n" + + "init globalValue3\n" + + "1\n" + + "globalValue2\n" + + "globalValue3\n" + + source = "runtime/basic/initializers2.kt" +} + +task initializers3(type: KonanLocalTest) { + goldValue = "42\n" + source = "runtime/basic/initializers3.kt" +} + +task initializers4(type: KonanLocalTest) { + goldValue = "1073741824\ntrue\n" + source = "runtime/basic/initializers4.kt" +} + +task initializers5(type: KonanLocalTest) { + goldValue = "42\n" + source = "runtime/basic/initializers5.kt" +} + +task initializers6(type: KonanLocalTest) { + disabled = project.testTarget == 'wasm32' // Needs workers. + source = "runtime/basic/initializers6.kt" +} + +task initializers7(type: KonanLocalTest) { + source = "runtime/basic/initializers7.kt" +} + +task expression_as_statement(type: KonanLocalTest) { + expectedFail = (project.testTarget == 'wasm32') // uses exceptions. + goldValue = "Ok\n" + source = "codegen/basics/expression_as_statement.kt" +} + +task codegen_escapeAnalysis_zeroOutObjectOnAlloc(type: KonanLocalTest) { + source = "codegen/escapeAnalysis/zeroOutObjectOnAlloc.kt" +} + +task codegen_escapeAnalysis_recursion(type: KonanLocalTest) { + source = "codegen/escapeAnalysis/recursion.kt" +} + +task memory_var1(type: KonanLocalTest) { + source = "runtime/memory/var1.kt" +} + +task memory_var2(type: KonanLocalTest) { + source = "runtime/memory/var2.kt" +} + +task memory_var3(type: KonanLocalTest) { + source = "runtime/memory/var3.kt" +} + +task memory_var4(type: KonanLocalTest) { + source = "runtime/memory/var4.kt" +} + +task memory_throw_cleanup(type: KonanLocalTest) { + expectedFail = (project.testTarget == 'wasm32') // Uses exceptions. + goldValue = "Ok\n" + source = "runtime/memory/throw_cleanup.kt" +} + +task memory_escape0(type: KonanLocalTest) { + source = "runtime/memory/escape0.kt" +} + +task memory_escape1(type: KonanLocalTest) { + goldValue = "zzz\n" + source = "runtime/memory/escape1.kt" +} + +task memory_cycles0(type: KonanLocalTest) { + goldValue = "42\n" + source = "runtime/memory/cycles0.kt" +} + +task memory_cycles1(type: KonanLocalTest) { + source = "runtime/memory/cycles1.kt" +} + +task memory_basic0(type: KonanLocalTest) { + source = "runtime/memory/basic0.kt" +} + +task memory_escape2(type: KonanLocalTest) { + goldValue = "zzz\n" + source = "runtime/memory/escape2.kt" +} + +task memory_weak0(type: KonanLocalTest) { + goldValue = "Data(s=Hello)\nnull\nOK\n" + source = "runtime/memory/weak0.kt" +} + +task memory_weak1(type: KonanLocalTest) { + goldValue = "OK\n" + source = "runtime/memory/weak1.kt" +} + +standaloneTest("memory_only_gc") { + source = "runtime/memory/only_gc.kt" +} + +task memory_stable_ref_cross_thread_check(type: KonanLocalTest) { + disabled = project.testTarget == 'wasm32' // Needs workers. + source = "runtime/memory/stable_ref_cross_thread_check.kt" +} + +standaloneTest("cycle_detector") { + disabled = project.globalTestArgs.contains('-opt') || // Needs debug build. + (project.testTarget == 'wasm32') // CycleDetector is disabled on WASM. + flags = ['-tr', '-g'] + source = "runtime/memory/cycle_detector.kt" +} + +standaloneTest("cycle_collector") { + disabled = true // Needs USE_CYCLIC_GC, which is disabled. + flags = ['-g'] + source = "runtime/memory/cycle_collector.kt" +} + +standaloneTest("cycle_collector_deadlock1") { + disabled = true // Needs USE_CYCLIC_GC, which is disabled. + source = "runtime/memory/cycle_collector_deadlock1.kt" +} + +standaloneTest("leakMemory") { + disabled = project.globalTestArgs.contains('-opt') || (project.testTarget == 'wasm32') // Needs debug build. + source = "runtime/memory/leak_memory.kt" + flags = ['-g'] + expectedExitStatusChecker = { it != 0 } + outputChecker = { s -> s.contains("Memory leaks detected, 1 objects leaked!") } +} + +standaloneTest("mpp1") { + source = "codegen/mpp/mpp1.kt" + flags = ['-tr', '-Xmulti-platform'] +} + +linkTest("mpp2") { + goldValue = "C(arg=42)\ntrue\n1\nh\n" + source = "codegen/mpp/mpp2.kt" + lib = "codegen/mpp/libmpp2.kt" + flags = ['-Xmulti-platform'] +} + +standaloneTest("mpp_default_args") { + source = "codegen/mpp/mpp_default_args.kt" + flags = ['-tr', '-Xmulti-platform'] +} + +standaloneTest("mpp_optional_expectation") { + source = "codegen/mpp/mpp_optional_expectation.kt" + def outputRoot = project.ext.testOutputLocal.toString() + def srcPath = "$outputRoot/$name/mpp_optional_expectation.kt".with { + isWindows() ? it.replaceAll("/", "\\\\") : it + } + flags = [ + '-Xmulti-platform', + "-Xcommon-sources=$srcPath" + ] +} + +task unit1(type: KonanLocalTest) { + goldValue = "First\nkotlin.Unit\n" + source = "codegen/basics/unit1.kt" +} + +task unit2(type: KonanLocalTest) { + goldValue = "kotlin.Unit\n" + source = "codegen/basics/unit2.kt" +} + +task unit3(type: KonanLocalTest) { + goldValue = "kotlin.Unit\n" + source = "codegen/basics/unit3.kt" +} + +task unit4(type: KonanLocalTest) { + goldValue = "Done\n" + source = "codegen/basics/unit4.kt" +} + +task kt42000_1(type: KonanLocalTest) { + source = "codegen/basics/k42000_1.kt" +} + +task kt42000_2(type: KonanLocalTest) { + source = "codegen/basics/k42000_2.kt" +} + +task inline0(type: KonanLocalTest) { + goldValue = "84\n" + source = "codegen/inline/inline0.kt" +} + +task vararg0(type: KonanLocalTest) { + source = "lower/vararg.kt" +} + +task vararg_of_literals(type: KonanLocalTest) { + enabled = false + goldValue = "a\na\n" + source = "lower/vararg_of_literals.kt" +} + +standaloneTest('tailrec') { + goldValue = "12\n100000000\n" + + "8\n" + + "1\n" + + "3 ...\n2 ...\n1 ...\nready!\n" + + "2\n-1\n" + + "true\nfalse\n" + + "default\n" + + "42\n" + source = "lower/tailrec.kt" + flags = ['-XXLanguage:-ProhibitTailrecOnVirtualMember', '-e', 'lower.tailrec.main'] +} + +task inline1(type: KonanLocalTest) { + goldValue = "Hello world\n" + source = "codegen/inline/inline1.kt" +} + +task inline2(type: KonanLocalTest) { + goldValue = "hello 1 8\n" + source = "codegen/inline/inline2.kt" +} + +task inline3(type: KonanLocalTest) { + goldValue = "5\n" + source = "codegen/inline/inline3.kt" +} + +task inline4(type: KonanLocalTest) { + goldValue = "3\n" + source = "codegen/inline/inline4.kt" +} + +task inline5(type: KonanLocalTest) { + goldValue = "33\n" + source = "codegen/inline/inline5.kt" +} + +task inline6(type: KonanLocalTest) { + goldValue = "hello1\nhello2\nhello3\nhello4\n" + source = "codegen/inline/inline6.kt" +} + +task inline7(type: KonanLocalTest) { + goldValue = "1\n2\n3\n" + source = "codegen/inline/inline7.kt" +} + +task inline8(type: KonanLocalTest) { + goldValue = "8\n" + source = "codegen/inline/inline8.kt" +} + +task inline9(type: KonanLocalTest) { + goldValue = "hello\n6\n" + source = "codegen/inline/inline9.kt" +} + +task inline10(type: KonanLocalTest) { + goldValue = "2\n" + source = "codegen/inline/inline10.kt" +} + +task inline13(type: KonanLocalTest) { + goldValue = "true\n" + source = "codegen/inline/inline13.kt" +} + +task inline14(type: KonanLocalTest) { + goldValue = "9\n" + source = "codegen/inline/inline14.kt" +} + +task inline15(type: KonanLocalTest) { + goldValue = "4\n" + source = "codegen/inline/inline15.kt" +} + +task inline16(type: KonanLocalTest) { + goldValue = "false\n" + source = "codegen/inline/inline16.kt" +} + +task inline17(type: KonanLocalTest) { + goldValue = "[1, 2]\n" + source = "codegen/inline/inline17.kt" +} + +task inline18(type: KonanLocalTest) { + goldValue = "true\n" + source = "codegen/inline/inline18.kt" +} + +task inline19(type: KonanLocalTest) { + goldValue = "6\n" + source = "codegen/inline/inline19.kt" +} + +task inline20(type: KonanLocalTest) { + goldValue = "def\n" + source = "codegen/inline/inline20.kt" +} + +task inline21(type: KonanLocalTest) { + goldValue = "bar\nfoo1\nfoo2\n33\n" + source = "codegen/inline/inline21.kt" +} + +task inline22(type: KonanLocalTest) { + goldValue = "14\n" + source = "codegen/inline/inline22.kt" +} + +task inline23(type: KonanLocalTest) { + goldValue = "33\n" + source = "codegen/inline/inline23.kt" +} + +task inline24(type: KonanLocalTest) { + enabled = false + goldValue = "bar\nfoo\n" + source = "codegen/inline/inline24.kt" +} + +task inline25(type: KonanLocalTest) { + goldValue = "Ok\nOk\n" + source = "codegen/inline/inline25.kt" +} + +task inline26(type: KonanLocalTest) { + goldValue = "5\n" + source = "codegen/inline/inline26.kt" +} + +task inline_type_substitution_in_fake_override(type: KonanLocalTest) { + goldValue = "OK\n" + source = "codegen/inline/typeSubstitutionInFakeOverride.kt" +} + +task inline_localFunctionInInitializerBlock(type: KonanLocalTest) { + goldValue = "Ok\n" + source = "codegen/inline/localFunctionInInitializerBlock.kt" +} + +task inline_lambdaInDefaultValue(type: KonanLocalTest) { + goldValue = "OK\n" + source = "codegen/inline/lambdaInDefaultValue.kt" +} + +task inline_lambdaAsAny(type: KonanLocalTest) { + goldValue = "Ok\n" + source = "codegen/inline/lambdaAsAny.kt" +} + +task inline_getClass(type: KonanLocalTest) { + goldValue = "OK\n" + source = "codegen/inline/getClass.kt" +} + +task inline_statementAsLastExprInBlock(type: KonanLocalTest) { + goldValue = "OK\n" + source = "codegen/inline/statementAsLastExprInBlock.kt" +} + +task inline_returnLocalClassFromBlock(type: KonanLocalTest) { + enabled = false + goldValue = "Zzz\n" + source = "codegen/inline/returnLocalClassFromBlock.kt" +} + +task inline_changingCapturedLocal(type: KonanLocalTest) { + goldValue = "OK\n" + source = "codegen/inline/changingCapturedLocal.kt" +} + +task inline_defaultArgs(type: KonanLocalTest) { + goldValue = "42\n" + source = "codegen/inline/defaultArgs.kt" +} + +task inline_twiceInlinedObject(type: KonanLocalTest) { + goldValue = "Ok\n" + source = "codegen/inline/twiceInlinedObject.kt" +} + +task inline_localObjectReturnedFromWhen(type: KonanLocalTest) { + goldValue = "Ok\n" + source = "codegen/inline/localObjectReturnedFromWhen.kt" +} + +task inline_genericFunctionReference(type: KonanLocalTest) { + goldValue = "0\n" + source = "codegen/inline/genericFunctionReference.kt" +} + +task inline_correctOrderFunctionReference(type: KonanLocalTest) { + goldValue = "OK\n" + source = "codegen/inline/correctOrderFunctionReference.kt" +} + +task inline_coercionToUnit(type: KonanLocalTest) { + goldValue = "kotlin.Unit\n" + source = "codegen/inline/coercionToUnit.kt" +} + +task classDeclarationInsideInline(type: KonanLocalTest) { + source = "codegen/inline/classDeclarationInsideInline.kt" + goldValue = "test1: 1.0\n1\ntest2\n" +} + +task inlineClass0(type: KonanLocalTest) { + source = "codegen/inlineClass/inlineClass0.kt" +} + +task inlineClass_customEquals(type: KonanLocalTest) { + source = "codegen/inlineClass/customEquals.kt" +} + +task inlineClass_defaultEquals(type: KonanLocalTest) { + source = "codegen/inlineClass/defaultEquals.kt" +} + +task inlineClass_secondaryConstructorWithGenerics(type: KonanLocalTest) { + source = "codegen/inlineClass/secondaryConstructorWithGenerics.kt" +} + +task deserialized_inline0(type: KonanLocalTest) { + source = "serialization/deserialized_inline0.kt" +} + +task deserialized_listof0(type: KonanLocalTest) { + source = "serialization/deserialized_listof0.kt" +} + +task genKt39548 { + doFirst { + GenTestKT39548Kt.genTestKT39548(file("$buildDir/kt39548/kt39548.kt")) + } +} + +KotlinNativeTestKt.createTest(project, "kt39548", KonanStandaloneTest) { task -> + // Test infrastructure doesn't support generated source; + // workaround by specifying dummy source: + task.source = "does/not/exist/kt39548.dummy.kt" + task.enabled = isWindowsTarget(project) + + if (task.enabled) { + konanArtifacts { + program(name, targets: [target.name]) { + baseDir "$testOutputLocal/$name" + srcFiles "$buildDir/kt39548/kt39548.kt" // Generated by genKt39548 task. + extraOpts task.flags + extraOpts project.globalTestArgs + } + } + + UtilsKt.findKonanBuildTask(project, name, target).dependsOn(genKt39548) + } +} + +linkTest("deserialized_members") { + goldValue= + "first level\n"+ + "second level\n"+ + "third levelxz\n"+ + "inner first level\n"+ + "inner second level\n"+ + "inner third level\n"+ + "types first level: 13\n"+ + "types second level cha-cha-cha\n"+ + "types third level 1.0\n" + lib = "serialization/serialize_members.kt" + source = "serialization/deserialize_members.kt" +} + +linkTest("serialized_catch") { + source = "serialization/use.kt" + lib = "serialization/catch.kt" + goldValue = "Gotcha1: XXX\nGotcha2: YYY\n" +} + +linkTest("serialized_doWhile") { + source = "serialization/use.kt" + lib = "serialization/do_while.kt" + goldValue = "999\n" +} + +linkTest("serialized_vararg") { + source = "serialization/use.kt" + lib = "serialization/vararg.kt" + goldValue = "17\n19\n23\n29\n31\nsize: 5\n" +} + +linkTest("serialized_default_args") { + source = "serialization/prop.kt" + lib = "serialization/default_args.kt" + goldValue = "SomeDataClass(first=17, second=666, third=23)\n" +} + +standaloneTest("serialized_no_typemap") { + source = "serialization/regression/no_type_map.kt" + goldValue = "OK\n" +} + +linkTest("serialized_enum_ordinal") { + source = "serialization/enum_ordinal/main.kt" + lib = "serialization/enum_ordinal/library.kt" + goldValue = "0\n1\n2\nb\n" +} + +linkTest("serialized_char_constant") { + source = "serialization/use_char_const.kt" + lib = "serialization/char_const.kt" + goldValue = "Ы\n" +} + +standaloneTest("testing_annotations") { + source = "testing/annotations.kt" + flags = ['-tr'] + arguments = ['--ktest_logger=SIMPLE'] + goldValue = 'Starting testing\nStarting iteration: 1\n' + + 'Test suite ignored: kotlin.test.tests.IgnoredClass.IgnoredObject\n' + + 'Test suite ignored: kotlin.test.tests.IgnoredClass\nTest suite ignored: kotlin.test.tests.IgnoredObject\n' + + 'Starting test suite: kotlin.test.tests.A\nbeforeClass (A.companion)\n' + + 'Starting test case: test1 (kotlin.test.tests.A)\nbefore (A)\ntest1 (A)\nafter (A)\n' + + 'Passed: test1 (kotlin.test.tests.A)\nIgnore: ignoredTest (kotlin.test.tests.A)\n' + + 'afterClass (A.companion)\nTest suite finished: kotlin.test.tests.A\n' + + 'Starting test suite: kotlin.test.tests.A.O\nbeforeClass (A.object)\n' + + 'Starting test case: test1 (kotlin.test.tests.A.O)\nbefore (A.object)\n' + + 'test1 (A.object)\nafter (A.object)\nPassed: test1 (kotlin.test.tests.A.O)\n' + + 'Ignore: ignoredTest (kotlin.test.tests.A.O)\nafterClass (A.object)\n' + + 'Test suite finished: kotlin.test.tests.A.O\nStarting test suite: kotlin.test.tests.O\n' + + 'beforeClass (object)\nStarting test case: test1 (kotlin.test.tests.O)\nbefore (object)\n' + + 'test1 (object)\nafter (object)\nPassed: test1 (kotlin.test.tests.O)\n' + + 'Ignore: ignoredTest (kotlin.test.tests.O)\nafterClass (object)\nTest suite finished: kotlin.test.tests.O\n' + + 'Starting test suite: kotlin.test.tests.AnnotationsKt\nbeforeClass (file)\n' + + 'Starting test case: test1 (kotlin.test.tests.AnnotationsKt)\nbefore (file)\n' + + 'test1 (file)\nafter (file)\nPassed: test1 (kotlin.test.tests.AnnotationsKt)\n' + + 'Ignore: ignoredTest (kotlin.test.tests.AnnotationsKt)\nafterClass (file)\n' + + 'Test suite finished: kotlin.test.tests.AnnotationsKt\nIteration finished: 1\nTesting finished\n' +} + +standaloneTest("testing_assertions") { + source = "testing/assertions.kt" + flags = ['-tr'] + expectedFail = (project.testTarget == 'wasm32') // Uses exceptions. + expectedExitStatus = 0 +} + +standaloneTest("testing_custom_main") { + source = "testing/custom_main.kt" + flags = ['-tr', '-e', 'kotlin.test.tests.main'] + arguments = ['--ktest_logger=SIMPLE', '--ktest_repeat=2'] + goldValue = 'Custom main\n' + + 'Starting testing\n' + + 'Starting iteration: 1\n' + + 'Starting test suite: kotlin.test.tests.Custom_mainKt\n' + + 'Starting test case: test (kotlin.test.tests.Custom_mainKt)\n' + + 'test\n' + + 'Passed: test (kotlin.test.tests.Custom_mainKt)\n' + + 'Test suite finished: kotlin.test.tests.Custom_mainKt\n' + + 'Iteration finished: 1\n' + + 'Starting iteration: 2\n' + + 'Starting test suite: kotlin.test.tests.Custom_mainKt\n' + + 'Starting test case: test (kotlin.test.tests.Custom_mainKt)\n' + + 'test\n' + + 'Passed: test (kotlin.test.tests.Custom_mainKt)\n' + + 'Test suite finished: kotlin.test.tests.Custom_mainKt\n' + + 'Iteration finished: 2\n' + + 'Testing finished\n' +} + +standaloneTest("testing_library_usage") { + def target = project.testTarget ?: 'host' + dependsOn konanArtifacts.baseTestClass.getByTarget(target) + def klib = konanArtifacts.baseTestClass.getArtifactByTarget(target) + source = 'testing/library_user.kt' + flags = ['-tr', '-e', 'main', '-l', klib.absolutePath] + arguments = ['--ktest_logger=SILENT'] +} + +class Filter { + List positive + List negative + List expectedTests + + Filter(List positive, List negative, List expectedTests) { + this.positive = positive + this.negative = negative + this.expectedTests = expectedTests + } + + List args() { + List result = [] + if (positive != null && !positive.isEmpty()) { + result += "--ktest_gradle_filter=${asListOfPatterns(positive)}" + } + if (negative != null && !negative.isEmpty()) { + result += "--ktest_negative_gradle_filter=${asListOfPatterns(negative)}" + } + return result + } + + static private String asListOfPatterns(List input) { + return input.collect { "kotlin.test.tests.$it" }.join(",") + } +} + +standaloneTest("testing_filters") { + source = "testing/filters.kt" + flags = ['-tr', '-ea'] + def filters = [ + new Filter(["A.foo1", "B", "FiltersKt.foo1"], [], ["A.foo1", "B.foo1", "B.foo2", "B.bar", "FiltersKt.foo1"]), + new Filter([], ["A.foo1", "B", "FiltersKt.foo1"], ["A.foo2", "A.bar", "FiltersKt.foo2", "FiltersKt.bar"]), + new Filter(["A", "FiltersKt"], ["A.foo1", "FiltersKt.foo1"], ["A.foo2", "A.bar", "FiltersKt.foo2", "FiltersKt.bar"]), + new Filter(["A.foo*", "B.*"], [], ["A.foo1", "A.foo2", "B.foo1", "B.foo2", "B.bar"]), + new Filter([], ["A.foo*", "B.*"], ["A.bar", "FiltersKt.foo1", "FiltersKt.foo2", "FiltersKt.bar"]), + new Filter(["*.foo*"], ["B"], ["A.foo1", "A.foo2", "FiltersKt.foo1", "FiltersKt.foo2"]), + new Filter(["A"], ["*.foo*"], ["A.bar"]) + ] + multiRuns = true + multiArguments = filters.collect { it.args() + '--ktest_logger=SIMPLE' } + outputChecker = { String output -> + // The first chunk is empty - drop it. + def outputs = output.split("Starting testing\n").drop(1) + if (outputs.size() != filters.size()) { + println("Incorrect number of test runs. Expected: ${filters.size()}, actual: ${outputs.size()}") + return false + } + + // Check the correct set of tests was executed in each run. + for (int i = 0; i < outputs.size(); i++) { + def actualMessages = outputs[i].split('\n').findAll { it.startsWith("Passed: ") } + def expectedMessages = filters[i].expectedTests.collect { String test -> + def method = test.substring(test.lastIndexOf('.') + 1) + def suite = test.substring(0, test.lastIndexOf('.')) + "Passed: $method (kotlin.test.tests.$suite)".toString() + } + + if (actualMessages.size() != expectedMessages.size()) { + println("Incorrect number of tests executed for filters[$i]. Expected: ${expectedMessages.size()}. Actual: ${actualMessages.size()}") + return false + } + + for (message in expectedMessages) { + if (!actualMessages.contains(message)) { + println("Test run output for filters[$i] doesn't contain the expected message '$message'") + return false + } + } + } + return true + } +} + +// Check that stacktraces and ignored suite are correctly reported in the TC logger. +standaloneTest("testing_stacktrace") { + source = "testing/stacktrace.kt" + flags = ['-tr', '-ea'] + arguments = ["--ktest_logger=TEAMCITY", "--ktest_no_exit_code"] + expectedFail = (project.testTarget == 'wasm32') // Uses exceptions. + // This test prints TeamCity service messages about failed test causing false negative failure at CI. + // So we need to suppress printing these messages to stdout. +// printOutput = false + outputChecker = { String output -> + def ignoredOutput = """\ + |##teamcity[testSuiteStarted name='kotlin.test.tests.Ignored' locationHint='ktest:suite://kotlin.test.tests.Ignored'] + |##teamcity[testIgnored name='foo'] + |##teamcity[testSuiteFinished name='kotlin.test.tests.Ignored']""".stripMargin() + def failedOutput = """\ + |##teamcity[testSuiteStarted name='kotlin.test.tests.Failed' locationHint='ktest:suite://kotlin.test.tests.Failed'] + |##teamcity[testStarted name='bar' locationHint='ktest:test://kotlin.test.tests.Failed.bar'] + |##teamcity[testFailed name='bar' message='Bar' details='kotlin.Exception: Bar|n""".stripMargin() + + def shownInnerException = output.readLines() + .find { it.startsWith("##teamcity[testFailed name='bar'") } + ?.contains("Caused by: kotlin.Exception: Baz") ?: false + + return output.contains(ignoredOutput) && output.contains(failedOutput) && shownInnerException + } +} + +// Just check that the driver is able to produce runnable binaries. +task driver0(type: KonanDriverTest) { + goldValue = "Hello, world!\n" + source = "runtime/basic/driver0.kt" +} + +task driver_opt(type: KonanDriverTest) { + disabled = (cacheTesting != null) // Cache is not compatible with -opt. + goldValue = "Hello, world!\n" + source = "runtime/basic/driver0.kt" + flags = ["-opt"] +} + +// Enable when deserialization for default arguments is fixed. +linkTest("inline_defaultArgs_linkTest") { + goldValue = "122\n47\n" + source = "codegen/inline/defaultArgs_linkTest_main.kt" + lib = "codegen/inline/defaultArgs_linkTest_lib.kt" +} + +linkTest("inline_sharedVar_linkTest") { + goldValue = "6\n" + source = "codegen/inline/sharedVar_linkTest_main.kt" + lib = "codegen/inline/sharedVar_linkTest_lib.kt" +} + +linkTest("inline_lateinitProperty_linkTest") { + disabled = (project.testTarget == 'wasm32') // Uses exceptions. + goldValue = "OK\n" + source = "codegen/inline/lateinitProperty_linkTest_main.kt" + lib = "codegen/inline/lateinitProperty_linkTest_lib.kt" +} + +linkTest("inline_inlineCtor_linkTest") { + source = "codegen/inline/inlineCtor_linkTest_main.kt" + lib = "codegen/inline/inlineCtor_linkTest_lib.kt" +} + +def generateWithSpaceDefFile() { + def mapOption = "--Map \"${buildDir}/cutom map.map\"" + if (isAppleTarget(project)) { + mapOption = "-map \"${buildDir}/cutom map.map\"" + } else if (isWindowsTarget(project)) { + mapOption = "\"-Wl,--Map,${buildDir}/cutom map.map\"" + } + + def file = new File("${buildDir}/withSpaces.def") + file.write """ +headers = stdio.h "${projectDir}/interop/basics/custom headers/custom.h" +linkerOpts = $mapOption +--- + +int customCompare(const char* str1, const char* str2) { + return custom_strcmp(str1, str2); +} +""" + return file.absolutePath +} + +// A helper method to create interop artifacts +void createInterop(String name, Closure conf) { + konanArtifacts { + interop(name, targets: [target.name]) { + conf(it) + noDefaultLibs(true) + noEndorsedLibs(true) + baseDir "$testOutputLocal/$name" + } + } +} + +createInterop("sysstat") { + // FIXME: creates empty file to workaround konan gradle plugin issue (should be able to have no def file) + def f = File.createTempFile("sysstat.empty", ".def") + it.packageName 'sysstat' + // FIXME: this option doesn't work due to an issue in plugin: it tries to resolve header in project dir. + //it.headers 'sys/stat.h' + f.write("headers = sys/stat.h") + it.defFile f +} + +createInterop("cstdlib") { + def f = File.createTempFile("cstdlib.empty", ".def") + it.packageName 'cstdlib' +// it.headers 'stdlib.h' + f.write("headers = stdlib.h") + it.defFile f +} + +createInterop("cstdio") { + it.defFile 'interop/basics/cstdio.def' +} + +createInterop("sockets") { + it.defFile 'interop/basics/sockets.def' +} + +createInterop("bitfields") { + it.defFile 'interop/basics/bitfields.def' +} + +createInterop("cglobals") { + it.defFile 'interop/basics/cglobals.def' +} + +createInterop("cfunptr") { + it.defFile 'interop/basics/cfunptr.def' +} + +createInterop("cmacros") { + it.defFile 'interop/basics/cmacros.def' +} + +createInterop("cunsupported") { + it.defFile 'interop/basics/cunsupported.def' +} + +createInterop("ctypes") { + it.defFile 'interop/basics/ctypes.def' +} + +createInterop("cvalues") { + it.defFile 'interop/basics/cvalues.def' +} + +createInterop("cvectors") { + it.defFile 'interop/basics/cvectors.def' +} + +createInterop("cstructs") { + it.defFile 'interop/basics/cstructs.def' +} + +createInterop("ccallbacksAndVarargs") { + it.defFile 'interop/basics/ccallbacksAndVarargs.def' +} + +createInterop("cmangling") { + it.defFile 'interop/basics/mangling.def' +} + +createInterop("cmangling2") { + it.defFile 'interop/basics/mangling2.def' +} + +createInterop("cmangling_keywords") { + it.defFile 'interop/basics/mangling_keywords.def' +} + +createInterop("cmangling_keywords2") { + it.defFile 'interop/basics/mangling_keywords2.def' +} + +createInterop("cunion") { + it.defFile 'interop/basics/cunion.def' +} + +createInterop("cenums") { + it.defFile 'interop/basics/cenums.def' +} + +createInterop("carrayPointers") { + it.defFile 'interop/basics/carrayPointers.def' +} + +createInterop("auxiliaryCppSources") { + // We need to provide empty def file to create correct `KonanInteropTask`. + it.defFile 'interop/auxiliary_sources/auxiliaryCppSources.def' + it.headers "$projectDir/interop/auxiliary_sources/name.h" + it.extraOpts "-Xcompile-source", "$projectDir/interop/auxiliary_sources/name.cpp" + it.extraOpts "-Xsource-compiler-option", "-std=c++17" +} + +createInterop("concurrentTerminate") { + it.defFile 'interop/concurrentTerminate/concurrentTerminate.def' + it.headers "$projectDir/interop/concurrentTerminate/async.h" + // TODO: Using `-Xcompile-source` does not imply dependency on that source, so the task will no re-run when the source is updated. + it.extraOpts "-Xcompile-source", "$projectDir/interop/concurrentTerminate/async.cpp" + it.extraOpts "-Xsource-compiler-option", "-std=c++11" +} + +createInterop("incomplete_types") { + it.defFile 'interop/incomplete_types/library.def' + it.headers "$projectDir/interop/incomplete_types/library.h" + it.extraOpts "-Xcompile-source", "$projectDir/interop/incomplete_types/library.cpp" +} + +createInterop("embedStaticLibraries") { + it.defFile 'interop/embedStaticLibraries/embedStaticLibraries.def' + it.headers "$projectDir/interop/embedStaticLibraries/embedStaticLibraries.h" + + // Note: also hardcoded in def file. + final String libDir = "$buildDir/embedStaticLibraries/" + + it.getByTarget(target.name).doFirst { + 1.upto(4) { + UtilsKt.buildStaticLibrary( + project, + [file("$projectDir/interop/embedStaticLibraries/${it}.c")], + file("$libDir/${it}.a"), + file("$libDir/${it}.objs"), + ) + } + } + + it.extraOpts '-staticLibrary', "1.a" + it.extraOpts '-staticLibrary', "2.a" +} + +if (PlatformInfo.isAppleTarget(project)) { + createInterop("objcSmoke") { + it.defFile 'interop/objc/objcSmoke.def' + it.headers "$projectDir/interop/objc/smoke.h" + } + + createInterop("objcTests") { + it.defFile 'interop/objc/objcTests.def' + it.headers fileTree("$projectDir/interop/objc/tests") { include '**/*.h' } + } + + createInterop("objcMisc") { + it.defFile 'interop/objc_with_initializer/objc_misc.def' + it.headers "$projectDir/interop/objc_with_initializer/objc_misc.h" + } + + createInterop("objcMessaging") { + it.defFile 'interop/objc/msg_send/messaging.def' + it.headers "$projectDir/interop/objc/msg_send/messaging.h" + } + + createInterop("foreignException") { + it.defFile 'interop/objc/foreignException/objc_wrap.def' + it.headers "$projectDir/interop/objc/foreignException/objc_wrap.h" + } + + createInterop("foreignExceptionMode_default") { + it.defFile 'interop/objc/foreignException/objcExceptionMode.def' + it.headers "$projectDir/interop/objc/foreignException/objc_wrap.h" + } + + createInterop("foreignExceptionMode_wrap") { + it.defFile 'interop/objc/foreignException/objcExceptionMode.def' + it.headers "$projectDir/interop/objc/foreignException/objc_wrap.h" + it.extraOpts '-Xforeign-exception-mode', "objc-wrap" + } + + createInterop("objcKt34467") { + it.defFile 'interop/objc/kt34467/module_library.def' + def moduleMap = file("interop/objc/kt34467/module_library.modulemap").absolutePath + def includePath = file("interop/objc/kt34467").absolutePath + it.compilerOpts "-fmodule-map-file=$moduleMap", "-I$includePath" + } + createInterop("objcGh3343") { + it.defFile 'framework/gh3343/objclib.def' + it.headers "$projectDir/framework/gh3343/objclib.h" + it.linkerOpts "-lobjcgh3343" + } + createInterop("objc_illegal_sharing_with_weak") { + it.defFile 'interop/objc/illegal_sharing_with_weak/objclib.def' + it.headers "$projectDir/interop/objc/illegal_sharing_with_weak/objclib.h" + } +} + +createInterop("withSpaces") { + it.defFile generateWithSpaceDefFile() +} + +/** + * Creates a task for the interop test. Configures runner and adds library and test build tasks. + */ +Task interopTestBase(String name, boolean multiFile, Closure configureClosure) { + return KotlinNativeTestKt.createTest(project, name, KonanInteropTest) { task -> + task.configure(configureClosure) + if (task.enabled) { + konanArtifacts { + def lib = task.interop + UtilsKt.dependsOnKonanBuildingTask(task, lib, target) + + program(name, targets: [target.name]) { + libraries { + artifact lib + } + srcFiles multiFile ? fileTree(task.source) { include '**/*.kt' } : task.getSources() + baseDir "$testOutputLocal/$name" + linkerOpts "-L$buildDir" + extraOpts task.flags + extraOpts project.globalTestArgs + } + } + } + } +} + +Task interopTest(String name, Closure configureClosure) { + return interopTestBase(name, false, configureClosure) +} + +Task interopTestMultifile(String name, Closure configureClosure) { + return interopTestBase(name, true, configureClosure) +} + +standaloneTest("interop_objc_allocException") { + dependsOnPlatformLibs(it) + disabled = !isAppleTarget(project) + expectedExitStatus = 0 + source = "interop/objc/allocException.kt" +} + +interopTest("interop0") { + disabled = (project.testTarget == 'wasm32') || // No interop for wasm yet. + (project.testTarget == 'linux_mips32') || // st_uid of '/' is not equal to 0 when using qemu + (project.testTarget == 'linux_mipsel32') + goldValue = "0\n0\n" + source = "interop/basics/0.kt" + interop = 'sysstat' +} + +interopTest("interop1") { + disabled = (project.testTarget == 'wasm32') // No interop for wasm yet. + goldValue = "257\n-1\n-2\n" + source = "interop/basics/1.kt" + interop = 'cstdlib' +} + +interopTest("interop2") { + disabled = (project.testTarget == 'wasm32') // No interop for wasm yet. + goldValue = "Hello\n" + source = "interop/basics/2.kt" + interop = 'cstdio' +} + +interopTest("interop3") { + // We disable this test on Raspberry Pi because + // qsort accepts size_t args. So the .kt file + // should be different depending on the bitness of the target. + // There are plans to provide a solution and turn this + // test back on. + disabled = (project.testTarget == 'raspberrypi') || + (project.testTarget == 'linux_mips32') || + (project.testTarget == 'linux_mipsel32') || + (project.testTarget == 'wasm32') // No interop for wasm yet. + goldValue = "8 9 12 13 14 \n" + source = "interop/basics/3.kt" + interop = 'cstdlib' +} + +interopTest("interop4") { + disabled = (project.testTarget == 'wasm32') // No interop for wasm yet. + goldValue = "a b -1 2 3 9223372036854775807 0.1 0.2 1 0\n1 42\n" + source = "interop/basics/4.kt" + interop = 'cstdio' +} + +standaloneTest("interop5") { + dependsOnPlatformLibs(it) + enabled = (project.testTarget != 'wasm32') // No interop for wasm yet. + goldValue = "Hello!\n" + source = "interop/basics/5.kt" +} + +interopTest("interop_bitfields") { + disabled = (project.testTarget == 'wasm32') // No interop for wasm yet. + expectedFail = (project.testTarget == 'linux_mips32') // fails because of big-endiannes + source = "interop/basics/bf.kt" + interop = 'bitfields' +} + +interopTest("interop_funptr") { + disabled = (project.testTarget == 'wasm32') // No interop for wasm yet. + goldValue = "42\n17\n1\n0\n42\n42\n" + source = "interop/basics/funptr.kt" + interop = 'cfunptr' +} + +interopTest("interop_globals") { + disabled = (project.testTarget == 'wasm32') // No interop for wasm yet. + source = "interop/basics/globals.kt" + interop = 'cglobals' +} + +interopTest("interop_macros") { + disabled = (project.testTarget == 'wasm32') // No interop for wasm yet. + source = "interop/basics/macros.kt" + interop = 'cmacros' +} + +interopTest("interop_unsupported") { + disabled = (project.testTarget == 'wasm32') // No interop for wasm yet. + source = "interop/basics/unsupported.kt" + interop = 'cunsupported' +} + +interopTest("interop_types") { + disabled = (project.testTarget == 'wasm32') // No interop for wasm yet. + source = "interop/basics/types.kt" + interop = 'ctypes' +} + +interopTest("interop_vectors") { + disabled = (project.testTarget == 'wasm32') // No interop for wasm yet. + source = "interop/basics/vectors.kt" + interop = 'cvectors' +} + +interopTest("interop_vectors_mimalloc") { + disabled = (project.testTarget == 'wasm32') // No interop for wasm yet. + source = "interop/basics/vectors.kt" + interop = 'cvectors' + flags = [ "-Xallocator=mimalloc" ] + arguments = [ "mimalloc" ] +} + +interopTest("interop_mangling") { + disabled = (project.testTarget == 'wasm32') // No interop for wasm yet. + source = "interop/basics/mangling.kt" + interop = 'cmangling' +} + +interopTest("interop_mangling2") { + disabled = (project.testTarget == 'wasm32') // No interop for wasm yet. + source = "interop/basics/mangling2.kt" + interop = 'cmangling2' +} + +interopTest("interop_mangling_keywords") { + disabled = (project.testTarget == 'wasm32') // No interop for wasm yet. + source = "interop/basics/mangling_keywords.kt" + interop = 'cmangling_keywords' +} + +interopTest("interop_mangling_keywords2") { + disabled = (project.testTarget == 'wasm32') // No interop for wasm yet. + source = "interop/basics/mangling_keywords2.kt" + interop = 'cmangling_keywords2' +} + +interopTest("interop_auxiliarySources") { + disabled = (project.testTarget == 'wasm32') // No interop for wasm yet. + source = "interop/auxiliary_sources/main.kt" + interop = 'auxiliaryCppSources' +} + +interopTest("interop_concurrentTerminate") { + disabled = (project.testTarget == 'wasm32') // No interop for wasm yet. + source = "interop/concurrentTerminate/main.kt" + interop = 'concurrentTerminate' + goldValue = "Reporting error!\n" + outputChecker = { str -> str.endsWith(goldValue) } + expectedExitStatus = 99 +} + +interopTest("interop_incompleteTypes") { + disabled = (project.testTarget == 'wasm32') // No interop for wasm yet. + source = "interop/incomplete_types/main.kt" + interop = 'incomplete_types' +} + +interopTest("interop_embedStaticLibraries") { + disabled = (project.testTarget == 'wasm32') // No interop for wasm yet. + source = "interop/embedStaticLibraries/main.kt" + interop = 'embedStaticLibraries' +} + +interopTest("interop_values") { + disabled = (project.testTarget == 'wasm32') // No interop for wasm yet. + source = "interop/basics/values.kt" + interop = 'cvalues' +} + +interopTest("interop_structs") { + disabled = (project.testTarget == 'wasm32') // No interop for wasm yet. + source = "interop/basics/structs.kt" + interop = 'cstructs' +} + +interopTest("interop_callbacksAndVarargs") { + disabled = (project.testTarget == 'wasm32') // No interop for wasm yet. + source = "interop/basics/callbacksAndVarargs.kt" + interop = 'ccallbacksAndVarargs' +} + +interopTest("interop_withSpaces") { + disabled = (project.testTarget == 'wasm32') // No interop for wasm yet. + interop ='withSpaces' + source = "interop/basics/withSpaces.kt" + + doLast { + assert file("${buildDir}/cutom map.map").exists() + } +} + +interopTest("interop_union") { + disabled = (project.testTarget == 'wasm32') // No interop for wasm yet. + interop = 'cunion' + source = "interop/basics/union.kt" +} + +interopTest("interop_enums") { + disabled = (project.testTarget == 'wasm32') // No interop for wasm yet. + interop = 'cenums' + source = "interop/basics/enums.kt" +} + +interopTest("interop_array_pointers") { + disabled = (project.testTarget == 'wasm32') // No interop for wasm yet. + interop = 'carrayPointers' + source = "interop/basics/arrayPointers.kt" +} + +standaloneTest("interop_pinning") { + disabled = (project.testTarget == 'wasm32') // Uses exceptions. + source = "interop/basics/pinning.kt" + flags = [ "-tr" ] +} + +task interop_convert(type: KonanLocalTest) { + source = "codegen/intrinsics/interop_convert.kt" +} + +/* +TODO: This test isn't run automatically +task interop_echo_server(type: RunInteropKonanTest) { + disabled = isWasmTarget(project) || isWindowsTarget(project) + run = false + source = "interop/basics/echo_server.kt" + interop = 'sockets' +} +*/ + +/* +TODO: This test isn't run automatically +standaloneTest("interop_opengl_teapot") { + enabled = isAppleTarget(project) && project.testTarget != 'ios_x64' // No GLUT in iOS + dependsOnPlatformLibs(it as Task) + run = false + source = "interop/basics/opengl_teapot.kt" +} +*/ + +if (PlatformInfo.isAppleTarget(project)) { + interopTest("interop_objc_smoke") { + goldValue = "84\nFoo\nDeallocated\n" + + "Hello, World!\nKotlin says: Hello, everybody!\nHello from Kotlin\n2, 1\n" + + "true\ntrue\n" + + "Global string\nAnother global string\nnull\nglobal object\n" + + "5\n" + + "String macro\n" + + "CFString macro\n" + + "Deallocated\nDeallocated\n" + + "Class TestExportObjCClass34 has multiple implementations. Which one will be used is undefined.\n" + + source = "interop/objc/smoke.kt" + interop = 'objcSmoke' + + doBeforeBuild { + mkdir(buildDir) + execKonanClang(project.target) { + args "$projectDir/interop/objc/smoke.m" + args "-lobjc", '-fobjc-arc' + args '-fPIC', '-shared', '-o', "$buildDir/libobjcsmoke.dylib" + // Enable ARC optimizations to prevent some objects from leaking in Obj-C code due to exceptions: + args '-O2' + } + if (project.target instanceof KonanTarget.IOS_X64) { + UtilsKt.codesign(project, "$buildDir/libobjcsmoke.dylib") + } + + copy { + from("interop/objc/Localizable.stringsdict") + into("$testOutputLocal/$name/$target/en.lproj/") + } + } + } + + interopTestMultifile("interop_objc_tests") { + source = "interop/objc/tests/" + interop = 'objcTests' + flags = ['-tr', '-e', 'main'] + + doBeforeBuild { + mkdir(buildDir) + execKonanClang(project.target) { + args fileTree("$projectDir/interop/objc/tests/") { include '**/*.m' } + args "-lobjc", '-fobjc-arc' + args '-fPIC', '-shared', '-o', "$buildDir/libobjctests.dylib" + // Enable ARC optimizations to prevent some objects from leaking in Obj-C code due to exceptions: + args '-O2' + } + if (project.target instanceof KonanTarget.IOS_X64) { + UtilsKt.codesign(project, "$buildDir/libobjctests.dylib") + } + } + } + + interopTest("interop_objc_global_initializer") { + goldValue = "OK\n" + source = "interop/objc_with_initializer/objc_test.kt" + interop = 'objcMisc' + flags = ['-g'] + + doBeforeBuild { + mkdir(buildDir) + execKonanClang(project.target) { + args "$projectDir/interop/objc_with_initializer/objc_misc.m" + args "-lobjc", '-fobjc-arc' + args '-fPIC', '-shared', '-o', "$buildDir/libobjcmisc.dylib" + } + if (project.target instanceof KonanTarget.IOS_X64) { + UtilsKt.codesign(project, "$buildDir/libobjcmisc.dylib") + } + } + } + + interopTest("interop_objc_msg_send") { + source = "interop/objc/msg_send/main.kt" + interop = 'objcMessaging' + + doBeforeBuild { + mkdir(buildDir) + execKonanClang(project.target) { + args "$projectDir/interop/objc/msg_send/messaging.m" + args "-lobjc", '-fobjc-arc' + args '-fPIC', '-shared', '-o', "$buildDir/libobjcmessaging.dylib" + } + if (project.target instanceof KonanTarget.IOS_X64) { + UtilsKt.codesign(project, "$buildDir/libobjcmessaging.dylib") + } + } + } + + interopTest("interop_objc_foreignException") { + source = "interop/objc/foreignException/objc_wrap.kt" + interop = 'foreignException' + dependsOnPlatformLibs(it) + + doBeforeBuild { + mkdir(buildDir) + execKonanClang(project.target) { + args "$projectDir/interop/objc/foreignException/objc_wrap.m" + args "-lobjc", '-fobjc-arc' + args '-fPIC', '-shared', '-o', "$buildDir/libobjcexception.dylib" + } + if (project.target instanceof KonanTarget.IOS_X64) { + UtilsKt.codesign(project, "$buildDir/libobjcexception.dylib") + } + } + } + + interopTest("interop_objc_foreignExceptionMode_wrap") { + source = "interop/objc/foreignException/objcExceptionMode.kt" + interop = 'foreignExceptionMode_wrap' + goldValue = "OK: ForeignException\n" + dependsOnPlatformLibs(it) + + doBeforeBuild { + mkdir(buildDir) + execKonanClang(project.target) { + args "$projectDir/interop/objc/foreignException/objc_wrap.m" + args "-lobjc", '-fobjc-arc' + args '-fPIC', '-shared', '-o', "$buildDir/libobjcexception.dylib" + } + if (project.target instanceof KonanTarget.IOS_X64) { + UtilsKt.codesign(project, "$buildDir/libobjcexception.dylib") + } + } + } + + interopTest("interop_objc_foreignExceptionMode_default") { + source = "interop/objc/foreignException/objcExceptionMode.kt" + interop = 'foreignExceptionMode_default' + goldValue = "OK: Ends with uncaught exception handler\n" + dependsOnPlatformLibs(it) + + doBeforeBuild { + mkdir(buildDir) + execKonanClang(project.target) { + args "$projectDir/interop/objc/foreignException/objc_wrap.m" + args "-lobjc", '-fobjc-arc' + args '-fPIC', '-shared', '-o', "$buildDir/libobjcexception.dylib" + } + if (project.target instanceof KonanTarget.IOS_X64) { + UtilsKt.codesign(project, "$buildDir/libobjcexception.dylib") + } + } + } + + interopTest("interop_objc_kt34467") { + source = "interop/objc/kt34467/foo.kt" + interop = 'objcKt34467' + goldValue = "OK\n42\n" + } + + interopTest("interop_objc_illegal_sharing_with_weak") { + source = "interop/objc/illegal_sharing_with_weak/main.kt" + interop = 'objc_illegal_sharing_with_weak' + + expectedExitStatusChecker = { it != 0 } + outputChecker = { + it.startsWith("Before") && // Should crash after "Before" + !it.contains("After") && // But before "After" + it.contains("isObjectAliveShouldCrash") // And should contain stack trace. + } + } +} + +standaloneTest("jsinterop_math") { + doBeforeBuild { + def jsinteropScript = isWindows() ? "jsinterop.bat" : "jsinterop" + def jsinterop = "$dist/bin/$jsinteropScript" + // TODO: We probably need a NativeInteropPlugin for jsinterop? + "$jsinterop -pkg kotlinx.interop.wasm.math -o $buildDir/jsmath -target wasm32".execute().waitFor() + + } + dependsOn ':wasm32PlatformLibs' + enabled = (project.testTarget == 'wasm32') + goldValue = "e = 2.718281828459045, pi = 3.141592653589793, sin(pi) = 1.2246467991473532E-16, sin(pi/2) = 1.0, ln(1) = 0.0, ln(e) = 1.0\n" + source = "jsinterop/math.kt" + flags = ["-r", "$buildDir", "-l", "jsmath"] +} + +standaloneTest("interop_libiconv") { + dependsOnPlatformLibs(it) + enabled = (project.testTarget == null) + source = "interop/libiconv.kt" + goldValue = "72 72\n101 101\n108 108\n108 108\n111 111\n33 33\n" +} + +standaloneTest("interop_zlib") { + dependsOnPlatformLibs(it) + enabled = (project.testTarget == null) + source = "interop/platform_zlib.kt" + goldValue = "Hello!\nHello!\n" +} + +standaloneTest("interop_objc_illegal_sharing") { + dependsOnPlatformLibs(it) + disabled = !isAppleTarget(project) + source = "interop/objc/illegal_sharing.kt" + expectedExitStatusChecker = { it != 0 } + outputChecker = { + it.startsWith("Before") && !it.contains("After") + } +} + +dynamicTest("produce_dynamic") { + disabled = (project.testTarget != null && project.testTarget != project.hostName) + source = "produce_dynamic/simple/hello.kt" + cSource = "$projectDir/produce_dynamic/simple/main.c" + goldValue = "Hello, dynamic!\n" + + "Base.foo\n" + + "Base.fooParam: a 1 q\n" + + "Child.fooParam: b 2 null\n" + + "Child.fooParam: c 3 null\n" + + "Impl1.I: d 4 Impl1\n" + + "Impl2.I: e 5 Impl2\n" + + "String is Kotlin/Native nullable is Hi null is OK\n" + + "RO property is 42\n" + + "RW property is 239\n" + + "enum100 = 100\n" + + "enum42 = 42\n" + + "object = 42\n" + + "singleton = I am single\n" + + "mutable = foo\n" + + "topLevel = 777 3\n" + + "IsInstance1 = PASS\n" + + "IsInstance2 = PASS\n" + + "getVector128 = (1, 2, 3, 4)\n" + + "Error handler: kotlin.Error: Expected error\n" +} + +dynamicTest("interop_concurrentRuntime") { + disabled = (project.testTarget != null && project.testTarget != project.hostName) + source = "interop/concurrentTerminate/reverseInterop.kt" + cSource = "$projectDir/interop/concurrentTerminate/main.cpp" + clangTool = "clang++" + goldValue = "Uncaught Kotlin exception: kotlin.RuntimeException: Example" + outputChecker = { str -> str.startsWith(goldValue) } + expectedExitStatus = 99 +} + +dynamicTest("interop_kt42397") { + disabled = (project.testTarget != null && project.testTarget != project.hostName) || + project.globalTestArgs.contains('-opt') + source = "interop/kt42397/knlibrary.kt" + cSource = "$projectDir/interop/kt42397/test.cpp" + clangTool = "clang++" + flags = ['-g'] +} + +dynamicTest("interop_cleaners_main_thread") { + disabled = (project.testTarget != null && project.testTarget != project.hostName) + source = "interop/cleaners/cleaners.kt" + cSource = "$projectDir/interop/cleaners/main_thread.cpp" + clangTool = "clang++" + goldValue = "42\n" + flags = ['-Xopt-in=kotlin.native.internal.InternalForKotlinNative'] +} + +dynamicTest("interop_cleaners_second_thread") { + disabled = (project.testTarget != null && project.testTarget != project.hostName) + source = "interop/cleaners/cleaners.kt" + cSource = "$projectDir/interop/cleaners/second_thread.cpp" + clangTool = "clang++" + goldValue = "42\n" + flags = ['-Xopt-in=kotlin.native.internal.InternalForKotlinNative'] +} + +dynamicTest("interop_cleaners_leak") { + disabled = (project.testTarget != null && project.testTarget != project.hostName) + source = "interop/cleaners/cleaners.kt" + cSource = "$projectDir/interop/cleaners/leak.cpp" + clangTool = "clang++" + goldValue = "" + flags = ['-Xopt-in=kotlin.native.internal.InternalForKotlinNative'] +} + +task library_mismatch(type: KonanDriverTest) { + // Does not work for cross targets yet. + enabled = !(project.testTarget != null && project.target.name != project.hostName) + + def dir = buildDir.absolutePath + def lib = "$projectDir/link/versioning/empty.kt" + + def currentTarget = project.target.name + def someOtherTarget = (project.testTarget == 'wasm32' ? project.hostName : 'wasm32') + + if (!useCustomDist) { + // we actually need any target other than the current one. + dependsOn ':wasm32CrossDistRuntime' + dependsOn ':wasm32CrossDistEndorsedLibraries' + } + + doBeforeBuild { + konanc("$lib -p library -o $dir/1.2/empty -target $currentTarget -lv 1.2") + konanc("$lib -p library -o $dir/3.4/empty -target $someOtherTarget") + konanc("$lib -p library -o $dir/5.6/empty -target $currentTarget -lv 5.6") + konanc("$lib -p library -o $dir/7.8/empty -target $currentTarget -lv 7.8") + + } + source = "link/versioning/hello.kt" + flags = ['-l', 'empty@5.6', '-r', "$dir/1.2", '-r', "$dir/3.4", '-r', "$dir/5.6"] + compilerMessages = true + def messages = + "warning: skipping $dir/1.2/empty.klib. The library versions don't match. Expected '5.6', found '1.2'\n" + + "warning: skipping $dir/3.4/empty.klib. The target doesn't match. Expected '$currentTarget', found [$someOtherTarget]\n" + + "Hello, versioned world!\n" + goldValue = PlatformInfo.isWindows() ? messages.replaceAll('\\/', '\\\\') : messages + outputChecker = { out -> + goldValue.split("\n") + .collect { line -> out.contains(line) } + .every { it == true } + } +} + +task library_ir_provider_mismatch(type: KonanDriverTest) { + def dir = buildDir.absolutePath + def lib = "$projectDir/link/ir_providers/library/empty.kt" + def invalidManifest = "$projectDir/link/ir_providers/library/manifest.properties" + + def currentTarget = project.target.name + + doBeforeBuild { + konanc("$lib -p library -o $dir/supported_ir_provider/empty -target $currentTarget") + konanc("$lib -p library -o $dir/unsupported_ir_provider/empty -manifest $invalidManifest -target $currentTarget") + + } + source = "link/ir_providers/hello.kt" + flags = ['-target', currentTarget, '-l', 'empty', '-r', "$dir/unsupported_ir_provider", '-r', "$dir/supported_ir_provider"] + compilerMessages = true + def messages = + "warning: skipping $dir/unsupported_ir_provider/empty.klib. The library requires unknown IR provider UNSUPPORTED.\n" + + "hello\n" + goldValue = PlatformInfo.isWindows() ? messages.replaceAll('\\/', '\\\\') : messages + outputChecker = { out -> + goldValue.split("\n") + .collect { line -> out.contains(line) } + .every { it == true } + } +} + +standaloneTest("fake_override_0") { + def sources = "$projectDir/link/fake_overrides" + def dir = buildDir.absolutePath + doBeforeBuild { + konanc("$sources/base.kt -p library -target ${target.name} -o $dir/base") + konanc("$sources/move.kt -p library -target ${target.name} -o $dir/move -r $dir -l base") + konanc("$sources/use.kt -p library -target ${target.name} -o $dir/use -r $dir -l move") + konanc("$sources/move2.kt -p library -target ${target.name} -o $dir/move -r $dir -l base") + } + source = "$sources/main.kt" + flags = ["-l", "use", "-r", "$dir"] + goldValue = "Moved\nMoved\nChild\nSuper\n" +} + +linkTest("private_fake_overrides_0") { + source = "link/private_fake_overrides/inherit_main.kt" + lib = "link/private_fake_overrides/inherit_lib.kt" + goldValue = "PASS\nPASS\nPASS\nPASS\nPASS\nPASS\nPASS\nPASS\nPASS\nPASS\n" +} + +linkTest("private_fake_overrides_1") { + source = "link/private_fake_overrides/override_main.kt" + lib = "link/private_fake_overrides/override_lib.kt" + goldValue = "PASS\nPASS\nPASS\nPASS\nPASS\nPASS\nPASS\nPASS\nPASS\nPASS\nPASS\nPASS\nPASS\nPASS\nPASS\nPASS\nPASS\n" +} + +Task frameworkTest(String name, Closure configurator) { + return KotlinNativeTestKt.createTest(project, name, FrameworkTest) { task -> + configurator.delegate = task + configurator() + if (task.enabled) { + konanArtifacts { + task.frameworks.forEach { fr -> + framework(fr.name, targets: [target.name]) { + fr.sources.forEach { src -> + srcFiles src + } + baseDir "$testOutputFramework/${task.name}" + + if (fr.library != null) { + dependsOn konanArtifacts[fr.library].getByTarget(target.name) + libraries { + file konanArtifacts[fr.library].getArtifactByTarget(target.name) + } + linkerOpts "-L$buildDir" + UtilsKt.dependsOnKonanBuildingTask(task, fr.library, target) + } + + if (!useCustomDist) { + dependsOn ":${target.name}CrossDistRuntime", ':distCompiler' + } + + extraOpts fr.bitcode ? "-Xembed-bitcode" : "-Xembed-bitcode-marker" + if (fr.isStatic) extraOpts "-Xstatic-framework" + extraOpts fr.opts + extraOpts project.globalTestArgs + + artifactName fr.artifact + } + } + } + } + } +} + +if (isAppleTarget(project)) { + frameworkTest('testObjCExport') { + final String frameworkName = 'Kt' + final String dir = "$testOutputFramework/testObjCExport" + final File lazyHeader = file("$dir/$target-lazy.h") + + doLast { + final String expectedLazyHeaderName = "expectedLazy.h" + final String expectedLazyHeaderDir = file("objcexport/") + final File expectedLazyHeader = new File(expectedLazyHeaderDir, expectedLazyHeaderName) + + if (expectedLazyHeader.readLines() != lazyHeader.readLines()) { + exec { + commandLine 'diff', '-u', expectedLazyHeader, lazyHeader + ignoreExitValue = true + } + + copy { + from(lazyHeader) + into(expectedLazyHeaderDir) + rename { expectedLazyHeaderName } + } + + throw new Error("$expectedLazyHeader file patched;\nre-run the test and don't forget to commit the patch") + } + + } + + def libraryName = frameworkName + "Library" + konanArtifacts { + library(libraryName, targets: [target.name]) { + srcDir "objcexport/library" + artifactName "test-library" + + if (!useCustomDist) { + dependsOn ":${target.name}CrossDistRuntime", ':distCompiler' + } + + extraOpts "-Xshort-module-name=MyLibrary" + extraOpts "-module-name", "org.jetbrains.kotlin.native.test-library" + } + } + framework(frameworkName) { + sources = ['objcexport'] + library = libraryName + opts = ["-Xemit-lazy-objc-header=$lazyHeader", "-Xopt-in=kotlin.ExperimentalStdlibApi"] + } + swiftSources = ['objcexport'] + } + + frameworkTest('testObjCExportStatic') { + final String frameworkName = 'KtStatic' + final String frameworkArtifactName = 'Kt' + final String libraryName = frameworkName + "Library" + + konanArtifacts { + library(libraryName, targets: [target.name]) { + srcDir "objcexport/library" + artifactName "test-library" + + if (!useCustomDist) { + dependsOn ":${target.name}CrossDistRuntime", ':distCompiler' + } + + extraOpts "-Xshort-module-name=MyLibrary" + extraOpts "-module-name", "org.jetbrains.kotlin.native.test-library" + } + } + + codesign = false + framework(frameworkName) { + sources = ['objcexport'] + bitcode = false + artifact = frameworkArtifactName + library = libraryName + isStatic = true + opts = ['-Xstatic-framework', "-Xopt-in=kotlin.ExperimentalStdlibApi"] + } + swiftSources = ['objcexport'] + } + + frameworkTest('testValuesGenericsFramework') { + framework('ValuesGenerics') { + sources = ['objcexport/values.kt', 'framework/values_generics'] + } + swiftSources = ['framework/values_generics/'] + } + + frameworkTest("testStdlibFramework") { + framework('Stdlib') { + sources = ['framework/stdlib'] + bitcode = true + } + if (cacheTesting == null) fullBitcode = true + swiftSources = ['framework/stdlib/'] + } + + if (cacheTesting != null && cacheTesting.isDynamic) { + // testMultipleFrameworks disabled until https://youtrack.jetbrains.com/issue/KT-34262 is fixed. + } else frameworkTest("testMultipleFrameworks") { + framework('First') { + sources = ['framework/multiple/framework1', 'framework/multiple/shared'] + bitcode = true + } + framework('Second') { + sources = ['framework/multiple/framework2', 'framework/multiple/shared'] + bitcode = true + } + swiftSources = ['framework/multiple'] + } + + frameworkTest("testMultipleFrameworksStatic") { + if (cacheTesting != null) { + // See https://youtrack.jetbrains.com/issue/KT-34261. + expectedExitStatus = 134 + } + + framework('FirstStatic') { + artifact = 'First' + sources = ['framework/multiple/framework1', 'framework/multiple/shared'] + bitcode = true + isStatic = true + opts = ['-Xstatic-framework', "-Xpre-link-caches=enable"] + } + framework('SecondStatic') { + artifact = 'Second' + sources = ['framework/multiple/framework2', 'framework/multiple/shared'] + bitcode = true + isStatic = true + opts = ['-Xstatic-framework', "-Xpre-link-caches=enable"] + } + codesign = false + swiftSources = ['framework/multiple'] + } + + frameworkTest("testGh3343Framework") { + framework('Gh3343') { + sources = ['framework/gh3343'] + library = 'objcGh3343' + } + swiftSources = ['framework/gh3343/'] + } + + frameworkTest("testKt42397Framework") { + enabled = !project.globalTestArgs.contains('-opt') + framework("Kt42397") { + sources = ['framework/kt42397'] + opts = ['-g'] + } + swiftSources = ['framework/kt42397'] + } +} + +/** + * Creates tasks to build and execute Harmony regex tests with GTEST logger. + */ +KotlinNativeTestKt.createTest(project, 'harmonyRegexTest', KonanGTest) { task -> + task.enabled = (project.testTarget != 'wasm32') // Uses exceptions. + task.useFilter = false + task.testLogger = KonanTest.Logger.GTEST + + if (twoStageEnabled) { + // Exclude tests with lone surrogates/incorrect surrogate pairs failing due to KT-33175. + def excludedTests = [ + "test.text.harmony_regex.PatternTest.testCanonEqFlagWithSupplementaryCharacters", + "test.text.harmony_regex.PatternTest.testRangesWithSurrogatesSupplementary", + "test.text.harmony_regex.PatternTest.testSequencesWithSurrogatesSupplementary", + "test.text.harmony_regex.PatternTest.testPredefinedClassesWithSurrogatesSupplementary", + "test.text.harmony_regex.PatternTest.testDotConstructionWithSurrogatesSupplementary", + "test.text.harmony_regex.PatternTest.testAlternationsWithSurrogatesSupplementary", + "test.text.harmony_regex.PatternTest.testGroupsWithSurrogatesSupplementary" + ] + task.arguments += "--ktest_filter=*-${excludedTests.join(":")}" + } + + def sources = UtilsKt.getFilesToCompile(project, ["harmony_regex"], []) + + konanArtifacts { + program('harmonyRegexTest', targets: [target.name]) { + srcFiles sources + baseDir "$testOutputStdlib/harmonyRegexTest" + extraOpts '-tr' + extraOpts project.globalTestArgs + } + } + + task.finalizedBy("resultsTask") +} + +if (UtilsKt.getTestTargetSupportsCodeCoverage(project)) { + task coverage_basic_program(type: CoverageTest) { + + binaryName = "CoverageBasic" + numberOfCoveredFunctions = 1 + numberOfCoveredLines = 3 + + konanArtifacts { + program(binaryName, targets: [ target ]) { + srcDir 'coverage/basic/program' + baseDir "$testOutputCoverage/$binaryName" + entryPoint "coverage.basic.program.main" + extraOpts "-Xcoverage", "-Xcoverage-file=$profrawFile" + } + } + } + + task coverage_basic_library(type: CoverageTest) { + + binaryName = "CoverageBasicLibrary" + numberOfCoveredFunctions = 1 + numberOfCoveredLines = 1 + + konanArtifacts { + library("lib_to_cover", targets: [target.name]) { + srcFiles 'coverage/basic/library/library.kt' + } + program(binaryName, targets: [ target ]) { + srcFiles 'coverage/basic/library/main.kt' + libraries { + artifact konanArtifacts.lib_to_cover + } + baseDir "$testOutputCoverage/$binaryName" + entryPoint "coverage.basic.library.main" + extraOpts "-Xcoverage-file=$profrawFile", "-Xlibrary-to-cover=${konanArtifacts.lib_to_cover.getArtifactByTarget(target.name)}" + } + } + } + + task coverage_controlflow(type: CoverageTest) { + binaryName = "CoverageControlFlow" + numberOfCoveredFunctions = 1 + numberOfCoveredLines = 102 + + konanArtifacts { + program(binaryName, targets: [ target ]) { + srcDir 'coverage/basic/controlflow' + baseDir "$testOutputCoverage/$binaryName" + entryPoint "coverage.basic.controlflow.main" + extraOpts "-Xcoverage", "-Xcoverage-file=$profrawFile" + } + } + } + + task coverage_jumps(type: CoverageTest) { + binaryName = "CoverageJumps" + numberOfCoveredFunctions = 8 + numberOfCoveredLines = 74 + + konanArtifacts { + program(binaryName, targets: [ target ]) { + srcDir 'coverage/basic/jumps' + baseDir "$testOutputCoverage/$binaryName" + entryPoint "coverage.basic.jumps.main" + extraOpts "-Xcoverage", "-Xcoverage-file=$profrawFile" + } + } + } + + task coverage_smoke0(type: CoverageTest) { + binaryName = "CoverageSmoke0" + numberOfCoveredFunctions = 2 + numberOfCoveredLines = 5 + + konanArtifacts { + program(binaryName, targets: [ target ]) { + srcDir 'coverage/basic/smoke0' + baseDir "$testOutputCoverage/$binaryName" + entryPoint "coverage.basic.smoke0.main" + extraOpts "-Xcoverage", "-Xcoverage-file=$profrawFile" + } + } + } + + task coverage_smoke1(type: CoverageTest) { + binaryName = "CoverageSmoke1" + numberOfCoveredFunctions = 9 + numberOfCoveredLines = 33 + + konanArtifacts { + program(binaryName, targets: [ target ]) { + srcDir 'coverage/basic/smoke1' + baseDir "$testOutputCoverage/$binaryName" + entryPoint "coverage.basic.smoke1.main" + extraOpts "-Xcoverage", "-Xcoverage-file=$profrawFile" + } + } + } +} + +task metadata_compare_typedefs(type: MetadataComparisonTest) { + enabled = (project.testTarget != 'wasm32') + defFile = "interop/basics/typedefs.def" +} + +task metadata_compare_unable_to_import(type: MetadataComparisonTest) { + enabled = (project.testTarget != 'wasm32') + defFile = "interop/basics/unable_to_import.def" +} + +standaloneTest("local_ea_arraysfieldwrite") { + disabled = (cacheTesting != null) // Cache is not compatible with -opt. + goldValue = "Array (constructor init):\nSize: 2\nContents: [1, 2]\n" + + "Array (constructor init):\nSize: 2\nContents: [3, 4]\n" + + "Array (default value init):\nSize: 2\nContents: [1, 2]\n" + + "Array (default value init):\nSize: 2\nContents: [3, 4]\n" + + "Array (init block):\nSize: 2\nContents: [1, 2]\n" + + "Array (init block):\nSize: 2\nContents: [3, 4]\n" + flags = ["-opt"] + source = "codegen/localEscapeAnalysis/arraysFieldWrite.kt" +} + +/** + * Creates tasks to build and execute stdlib tests. + */ +KotlinNativeTestKt.createTest(project, 'stdlibTest', KonanGTest) { task -> + def sources = UtilsKt.getFilesToCompile(project, + [ 'build/stdlib_external/stdlib', 'stdlib_external/utils.kt', + 'stdlib_external/jsCollectionFactoriesActuals.kt', + 'stdlib_external/text/StringEncodingTestNative.kt'], + [ 'build/stdlib_external/stdlib/test/internalAnnotations.kt' ]) + + konanArtifacts { + program('stdlibTest', targets: [target.name]) { + srcFiles sources + baseDir "$testOutputStdlib/stdlibTest" + enableMultiplatform true + extraOpts '-tr', + '-Xopt-in=kotlin.RequiresOptIn,kotlin.ExperimentalStdlibApi', + "-friend-modules", project.rootProject.file("${project.properties['konan.home']}/klib/common/stdlib").absolutePath + extraOpts project.globalTestArgs + } + } + // Exclude test providing args to the test executable + task.arguments = [ "--ktest_negative_regex_filter=test.collections.CollectionTest.abstractCollectionToArray" ] + task.useFilter = false + task.testLogger = KonanTest.Logger.GTEST + task.finalizedBy("resultsTask") + task.enabled = (project.testTarget != 'wasm32') // Uses exceptions +} + +/** + * Builds tests into a single binary with TestRunner + */ +task buildKonanTests { t -> + def compileList = [ "codegen", "datagen", "lower", "runtime", "serialization" ] + + // These tests should not be built into the TestRunner's test executable + def excludeList = [ "codegen/inline/returnLocalClassFromBlock.kt" ] + project.tasks + .withType(KonanStandaloneTest.class) + .each { + // add library and source files + if (it instanceof KonanLinkTest) { + excludeList += it.lib + } + if (it.source != null) { + excludeList += it.source + } + } + def sources = UtilsKt.getFilesToCompile(project, compileList, excludeList) + + konanArtifacts { + program('localTest', targets: [target.name]) { + srcFiles sources + baseDir testOutputLocal + extraOpts '-tr' + extraOpts project.globalTestArgs + } + } + + // Set build dependencies. + dependsOn compileKonanLocalTest + def buildTask = UtilsKt.findKonanBuildTask(project, "localTest", target) + UtilsKt.dependsOnDist(buildTask) + + // Local tests build into a single binary should depend on this task + project.tasks + .withType(KonanLocalTest.class) + .matching { !(it instanceof KonanStandaloneTest) } + .forEach { it.dependsOn(t) } +} + + +sourceSets { + nopPlugin { + kotlin { + srcDir 'extensions/nop/src/main/kotlin' + } + } + test { + kotlin { + srcDir 'debugger/src/test/kotlin' + } + } +} + +Task pluginTest(String name, String pluginName, Closure configureClosure) { + def jarTask = project.tasks.create("jar-$pluginName", Jar).configure { + it.dependsOn("compile${pluginName.capitalize()}Kotlin") + from { + sourceSets[pluginName].output + } + baseName = pluginName + destinationDirectory = buildDir + } + def taskName = "$name-with-$pluginName" + return KotlinNativeTestKt.createTest(project, taskName, KonanStandaloneTest) { task -> + task.configure(configureClosure) + task.dependsOn(jarTask) + if (task.enabled) { + konanArtifacts { + program(taskName, targets: [target.name]) { + baseDir "$testOutputLocal/$taskName" + srcFiles task.getSources() + extraOpts task.flags + "-Xplugin=$buildDir/nop-plugin.jar" + extraOpts project.globalTestArgs + } + } + } + } +} + +pluginTest("runtime_basic_init", "nopPlugin") { + disabled = (project.testTarget == 'wasm32') + source = "runtime/basic/hello3.kt" + flags = ["-tr"] +} + +dependencies { + nopPluginCompile kotlinCompilerModule + compile kotlinCompilerModule + compile project(path: ':backend.native', configuration: 'cli_bc') + compile 'junit:junit:4.12' +} + +project.tasks.named("test").configure { + // Don't run this task as it will try to execute debugger tests too + // that is not desired as they are platform-specific. + enabled = false +} + +project.tasks.register("debugger_test", Test.class) { + enabled = (target.family == Family.OSX) // KT-30366 + testLogging { exceptionFormat = 'full' } + UtilsKt.dependsOnDist(it) + systemProperties = ['kotlin.native.home': dist] +} + +// Configure build for iOS device targets. +if (target.family == Family.IOS && (target.architecture == ARM32 || target.architecture == ARM64)) { + project.tasks + .withType(KonanTestExecutable.class) + .forEach { + ExecutorServiceKt.configureXcodeBuild((KonanTestExecutable) it) + } + // Exclude tasks that cannot be run on device + project.tasks + .withType(KonanTest.class) + .matching { (it instanceof KonanLocalTest && ((KonanLocalTest) it).testData != null) || + // Filter out tests that depend on libs. TODO: copy them too + it instanceof KonanInteropTest || + it instanceof KonanDynamicTest || + it instanceof KonanLinkTest + } + .forEach { it.enabled = false } +} diff --git a/kotlin-native/backend.native/tests/codegen/annotations/annotations0.kt b/kotlin-native/backend.native/tests/codegen/annotations/annotations0.kt new file mode 100644 index 00000000000..2b1cd2ece97 --- /dev/null +++ b/kotlin-native/backend.native/tests/codegen/annotations/annotations0.kt @@ -0,0 +1,27 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +// FILE: 1.kt + +package codegen.annotations.annotations0 + +import kotlin.test.* +import kotlinx.serialization.* + +@SerialInfo +annotation class Foo(val x: Int, val y: String) + +@Test fun runTest() { + val foo = @Suppress("ANNOTATION_CLASS_CONSTRUCTOR_CALL") Foo(42, "17") + assertEquals(foo.x, 42) + assertEquals(foo.y, "17") +} + +// FILE: 2.kt + +package kotlinx.serialization + +@Target(AnnotationTarget.ANNOTATION_CLASS) +annotation class SerialInfo diff --git a/kotlin-native/backend.native/tests/codegen/arithmetic/basic.kt b/kotlin-native/backend.native/tests/codegen/arithmetic/basic.kt new file mode 100644 index 00000000000..28afd4c1746 --- /dev/null +++ b/kotlin-native/backend.native/tests/codegen/arithmetic/basic.kt @@ -0,0 +1,96 @@ +package codegen.arithmetic.basic + +import kotlin.test.* + +// Check that compiler doesn't optimize it to `true` +fun selfCmp1(x: Int) = x + 1 > x + +fun selfCmp2(x: Int) = x - 1 < x + +@Test +fun selfComparison() { + assertFalse(selfCmp1(Int.MAX_VALUE)) + assertFalse(selfCmp2(Int.MIN_VALUE)) +} + +private fun charCornersMinus(): Int { + val a: Char = 0xFFFF.toChar() + val b: Char = 0.toChar() + return a - b +} + +private fun charCornersComparison(): Boolean { + val a = 0xFFFF.toChar() + val b = 0.toChar() + return a < b +} + +@Test +fun charCornerCases() { + assertEquals(65535, charCornersMinus()) + assertFalse(charCornersComparison()) +} + +@Test +fun shifts() { + assertEquals(-2147483648, 1 shl -1) + assertEquals(0, 1 shr -1) + assertEquals(1, 1 shl 32) + assertEquals(1073741823, -1 ushr 2) + assertEquals(-1, -1 shr 2) +} + +@Test +@kotlin.ExperimentalUnsignedTypes +fun uintTests() { + assertEquals(UInt.MAX_VALUE, UInt.MIN_VALUE - 1u) +} + +@Test +fun charConversions() { + assertEquals(97.0, 'a'.toDouble()) + assertEquals(-1, Char.MAX_VALUE.toShort()) + assertEquals(32768, Short.MIN_VALUE.toChar().toInt()) + assertEquals(-1, Char.MAX_VALUE.toByte()) + assertEquals(65408, Byte.MIN_VALUE.toChar().toInt()) + assertEquals(0, Float.MIN_VALUE.toChar().toInt()) +} + +@Test +fun doubleBasic() { + assertEquals(1, 0f.compareTo(-0f)) + assertEquals(1, 0.0.compareTo(-0.0)) + + assertEquals(1.0, Double.fromBits(1.0.toBits())) + assertEquals(1.0f, Float.fromBits(1.0f.toBits())) + + assertEquals(Double.NaN, Double.fromBits((0 / 0.0).toBits())) + assertEquals(Float.NaN, Float.fromBits((0 / 0f).toBits())) +} + +@Test +fun integralToFloat() { + assertEquals(9.223372E18f, Long.MAX_VALUE.toFloat()) + assertEquals(-9.223372E18f, Long.MIN_VALUE.toFloat()) + + assertEquals(-2.147483648E9, Int.MIN_VALUE.toDouble()) + assertEquals(2.147483647E9, Int.MAX_VALUE.toDouble()) + + assertEquals(2147483647, Double.MAX_VALUE.toInt()) + assertEquals(0, Float.MIN_VALUE.toLong()) + + assertEquals(9223372036854775807, Float.MAX_VALUE.toLong()) + assertEquals(0, Double.MIN_VALUE.toInt()) +} + +@Test +fun compareIntToFloat() { + assertEquals(1, 0.compareTo(-0.0f)) + assertEquals(0, 0.compareTo(+0.0f)) +} + +@Test +fun testKt37412() { + val two = 2.0 + assertEquals(2, two.toInt()) +} \ No newline at end of file diff --git a/kotlin-native/backend.native/tests/codegen/arithmetic/division.kt b/kotlin-native/backend.native/tests/codegen/arithmetic/division.kt new file mode 100644 index 00000000000..9a8a8188cc3 --- /dev/null +++ b/kotlin-native/backend.native/tests/codegen/arithmetic/division.kt @@ -0,0 +1,11 @@ +package codegen.arithmetic.division + +import kotlin.test.* + +@Test +fun divisionByZero() { + assertFailsWith(ArithmeticException::class, { 5 / 0 }) + assertFailsWith(ArithmeticException::class, { 5 % 0 }) + assertEquals(1, 5 / try { 0 / 0; 1 } catch (e: ArithmeticException) { 5 }) + assertEquals(Double.NaN, 0.0 / 0.0) +} diff --git a/kotlin-native/backend.native/tests/codegen/arithmetic/github1856.kt b/kotlin-native/backend.native/tests/codegen/arithmetic/github1856.kt new file mode 100644 index 00000000000..667a0c11202 --- /dev/null +++ b/kotlin-native/backend.native/tests/codegen/arithmetic/github1856.kt @@ -0,0 +1,26 @@ +package codegen.arithmetic.github1856 + +import kotlin.test.* + +object RGBA { + fun packFast(r: Int, g: Int, b: Int, a: Int) = (r shl 0) or (g shl 8) or (b shl 16) or (a shl 24) + + fun getFastR(v: Int): Int = (v ushr 0) and 0xFF + fun getFastG(v: Int): Int = (v ushr 8) and 0xFF + fun getFastB(v: Int): Int = (v ushr 16) and 0xFF + fun getFastA(v: Int): Int = (v ushr 24) and 0xFF + + fun premultiplyFastInt(v: Int): Int { + val A = getFastA(v) + 1 + val RB = (((v and 0x00FF00FF) * A) ushr 8) and 0x00FF00FF + val G = (((v and 0x0000FF00) * A) ushr 8) and 0x0000FF00 + return (v and 0x00FFFFFF.inv()) or RB or G + } +} + +@Test +fun main() { + val source = listOf(0xFFFFFFFF.toInt(), 0xFFFFFF77.toInt(), 0x777777FF.toInt(), 0x77777777.toInt()) + val expect = listOf(-1, -137, 2000107383, 2000107319) + assertEquals(expect, source.map { RGBA.premultiplyFastInt(it) }) +} \ No newline at end of file diff --git a/kotlin-native/backend.native/tests/codegen/associatedObjects/associatedObjects1.kt b/kotlin-native/backend.native/tests/codegen/associatedObjects/associatedObjects1.kt new file mode 100644 index 00000000000..02f1862655f --- /dev/null +++ b/kotlin-native/backend.native/tests/codegen/associatedObjects/associatedObjects1.kt @@ -0,0 +1,86 @@ +/* + * Copyright 2010-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +package codegen.associatedObjects.associatedObjects1 + +import kotlin.test.* +import kotlin.reflect.* + +@Test +@OptIn(ExperimentalAssociatedObjects::class) +fun testBasics1() { + assertSame(Bar, Foo::class.findAssociatedObject()) + assertSame(Baz, Foo::class.findAssociatedObject()) + assertSame(null, Foo::class.findAssociatedObject()) + + assertSame(null, Bar::class.findAssociatedObject()) +} + +@OptIn(ExperimentalAssociatedObjects::class) +@AssociatedObjectKey +@Retention(AnnotationRetention.BINARY) +annotation class Associated1(val kClass: KClass<*>) + +@OptIn(ExperimentalAssociatedObjects::class) +@AssociatedObjectKey +@Retention(AnnotationRetention.BINARY) +annotation class Associated2(val kClass: KClass<*>) + +@OptIn(ExperimentalAssociatedObjects::class) +@AssociatedObjectKey +@Retention(AnnotationRetention.BINARY) +annotation class Associated3(val kClass: KClass<*>) + +@Associated1(Bar::class) +@Associated2(Baz::class) +class Foo + +object Bar +object Baz + +@Test +@OptIn(ExperimentalAssociatedObjects::class) +fun testGlobalOptimizations1() { + val i1 = I1ImplHolder::class.findAssociatedObject()!! as I1 + assertEquals(42, i1.foo()) + val c = C(null) + i1.bar(c) + assertEquals("zzz", c.list!![0]) +} + +private class C(var list: List?) + +private interface I1 { + fun foo(): Int + fun bar(c: C) +} + +private object I1Impl : I1 { + override fun foo() = 42 + override fun bar(c: C) { + c.list = mutableListOf("zzz") + } +} + +@Associated1(I1Impl::class) +private class I1ImplHolder + +@Test +@OptIn(ExperimentalAssociatedObjects::class) +fun testGlobalOptimizations2() { + val i2 = I2ImplHolder()::class.findAssociatedObject()!! as I2 + assertEquals(17, i2.foo()) +} + +private interface I2 { + fun foo(): Int +} + +private object I2Impl : I2 { + override fun foo() = 17 +} + +@Associated1(I2Impl::class) +private class I2ImplHolder \ No newline at end of file diff --git a/kotlin-native/backend.native/tests/codegen/basics/array_to_any.kt b/kotlin-native/backend.native/tests/codegen/basics/array_to_any.kt new file mode 100644 index 00000000000..6e1b6bd28f5 --- /dev/null +++ b/kotlin-native/backend.native/tests/codegen/basics/array_to_any.kt @@ -0,0 +1,17 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +package codegen.basics.array_to_any + +import kotlin.test.* + +@Test +fun runTest() { + foo().hashCode() +} + +fun foo(): Any { + return Array(0, { i -> null }) +} \ No newline at end of file diff --git a/kotlin-native/backend.native/tests/codegen/basics/canonical_name.kt b/kotlin-native/backend.native/tests/codegen/basics/canonical_name.kt new file mode 100644 index 00000000000..cd2497c7855 --- /dev/null +++ b/kotlin-native/backend.native/tests/codegen/basics/canonical_name.kt @@ -0,0 +1,39 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +package codegen.basics.canonical_name + +import kotlin.test.* + +interface I { + fun foo(a: U): T + fun qux(a: T): U +} + +//-----------------------------------------------------------------------------// + +class A1 +class A2 + +//-----------------------------------------------------------------------------// + +class A : I { + override fun foo(a: A1): A2 { println("A:foo"); return A2() } + override fun qux(a: A2): A1 { println("A:qux"); return A1() } +} + +//-----------------------------------------------------------------------------// + +fun baz(i: I, u: U, v:V) { + i.foo(u) + i.qux(v) +} + +//-----------------------------------------------------------------------------// + +@Test +fun runTest() { + baz(A(), A1(), A2()) +} \ No newline at end of file diff --git a/kotlin-native/backend.native/tests/codegen/basics/cast_null.kt b/kotlin-native/backend.native/tests/codegen/basics/cast_null.kt new file mode 100644 index 00000000000..ea47db9ccc0 --- /dev/null +++ b/kotlin-native/backend.native/tests/codegen/basics/cast_null.kt @@ -0,0 +1,58 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +package codegen.basics.cast_null + +import kotlin.test.* + +@Test +fun runTest() { + testCast(null, false) + testCastToNullable(null, true) + testCastToNullable(TestKlass(), true) + testCastToNullable("", false) + testCastNotNullableToNullable(TestKlass(), true) + testCastNotNullableToNullable("", false) + + println("Ok") +} + +class TestKlass + +fun ensure(b: Boolean) { + if (!b) { + println("Error") + } +} + +fun testCast(x: Any?, expectSuccess: Boolean) { + try { + x as TestKlass + } catch (e: Throwable) { + ensure(!expectSuccess) + return + } + ensure(expectSuccess) +} + +fun testCastToNullable(x: Any?, expectSuccess: Boolean) { + try { + x as TestKlass? + } catch (e: Throwable) { + ensure(!expectSuccess) + return + } + ensure(expectSuccess) +} + +fun testCastNotNullableToNullable(x: Any, expectSuccess: Boolean) { + try { + x as TestKlass? + } catch (e: Throwable) { + ensure(!expectSuccess) + return + } + ensure(expectSuccess) +} \ No newline at end of file diff --git a/kotlin-native/backend.native/tests/codegen/basics/cast_simple.kt b/kotlin-native/backend.native/tests/codegen/basics/cast_simple.kt new file mode 100644 index 00000000000..80555ab3f9b --- /dev/null +++ b/kotlin-native/backend.native/tests/codegen/basics/cast_simple.kt @@ -0,0 +1,24 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +package codegen.basics.cast_simple + +import kotlin.test.* + +open class A() {} +class B(): A() {} + +fun castSimple(o: Any) : A = o as A + +fun castTest(): Boolean { + val b = B() + castSimple(b) + return true +} + +@Test +fun runTest() { + if (!castTest()) throw Error() +} \ No newline at end of file diff --git a/kotlin-native/backend.native/tests/codegen/basics/check_type.kt b/kotlin-native/backend.native/tests/codegen/basics/check_type.kt new file mode 100644 index 00000000000..b92232ef337 --- /dev/null +++ b/kotlin-native/backend.native/tests/codegen/basics/check_type.kt @@ -0,0 +1,48 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +package codegen.basics.check_type + +import kotlin.test.* + +interface I +class A() : I {} +class B() {} + +//-----------------------------------------------------------------------------// + +fun isTypeOf(a: Any?) : Boolean { + return a is A +} + +//-----------------------------------------------------------------------------// + +fun isTypeNullableOf(a: Any?) : Boolean { + return a is A? +} + +//-----------------------------------------------------------------------------// + +fun isNotTypeOf(a: Any) : Boolean { + return a !is A +} + +//-----------------------------------------------------------------------------// + +fun isTypeOfInterface(a: Any) : Boolean { + return a is I +} + +//-----------------------------------------------------------------------------// + +@Test +fun runTest() { + println(isTypeOf(A())) + println(isTypeOf(null)) + println(isTypeNullableOf(A())) + println(isTypeNullableOf(null)) + println(isNotTypeOf(B())) + println(isTypeOfInterface(A())) +} diff --git a/kotlin-native/backend.native/tests/codegen/basics/companion.kt b/kotlin-native/backend.native/tests/codegen/basics/companion.kt new file mode 100644 index 00000000000..b753406bf18 --- /dev/null +++ b/kotlin-native/backend.native/tests/codegen/basics/companion.kt @@ -0,0 +1,10 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +class A { + companion object { + fun foo() = "comp" + } +} diff --git a/kotlin-native/backend.native/tests/codegen/basics/concatenation.kt b/kotlin-native/backend.native/tests/codegen/basics/concatenation.kt new file mode 100644 index 00000000000..e772e4dd4c4 --- /dev/null +++ b/kotlin-native/backend.native/tests/codegen/basics/concatenation.kt @@ -0,0 +1,19 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +package codegen.basics.concatenation + +import kotlin.test.* + +@Test +fun runTest() { + val s = "world" + val i = 1 + println("Hello $s $i ${2*i}") + + for (item in listOf("a", "b")) { + println("Hello, $item") + } +} \ No newline at end of file diff --git a/kotlin-native/backend.native/tests/codegen/basics/const_infinity.kt b/kotlin-native/backend.native/tests/codegen/basics/const_infinity.kt new file mode 100644 index 00000000000..bd05fc84cc9 --- /dev/null +++ b/kotlin-native/backend.native/tests/codegen/basics/const_infinity.kt @@ -0,0 +1,21 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +package codegen.basics.const_infinity + +import kotlin.test.* + +//Original issue here https://youtrack.jetbrains.com/issue/KT-37212 +@Suppress("DIVISION_BY_ZERO") +const val fpInfConst = 1.0F / 0.0F +@Suppress("DIVISION_BY_ZERO") +val fpInfVal = 1.0F / 0.0F + +@Test +fun runTest() { + assertEquals(fpInfConst, Float.POSITIVE_INFINITY) + assertEquals(fpInfVal, Float.POSITIVE_INFINITY) + assertEquals(fpInfConst, fpInfVal) +} \ No newline at end of file diff --git a/kotlin-native/backend.native/tests/codegen/basics/expression_as_statement.kt b/kotlin-native/backend.native/tests/codegen/basics/expression_as_statement.kt new file mode 100644 index 00000000000..b59662329cd --- /dev/null +++ b/kotlin-native/backend.native/tests/codegen/basics/expression_as_statement.kt @@ -0,0 +1,24 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +package codegen.basics.expression_as_statement + +import kotlin.test.* + +fun foo() { + Any() as String +} + +@Test +fun runTest() { + try { + foo() + } catch (e: Throwable) { + println("Ok") + return + } + + println("Fail") +} \ No newline at end of file diff --git a/kotlin-native/backend.native/tests/codegen/basics/k42000_1.kt b/kotlin-native/backend.native/tests/codegen/basics/k42000_1.kt new file mode 100644 index 00000000000..7f18c7fd110 --- /dev/null +++ b/kotlin-native/backend.native/tests/codegen/basics/k42000_1.kt @@ -0,0 +1,37 @@ +package codegen.basics.k42000_1 + +import kotlin.test.* + +@Test +fun runTest() { + assertTrue(Reproducer().repro() > 0) +} + +// Based on https://youtrack.jetbrains.com/issue/KT-42000#focus=Comments-27-4404934.0-0 + +val Int.isEven get() = this % 2 == 0 + +inline operator fun T.plus(other: T): T = when (T::class) { + Double::class -> (this as Double) + (other as Double) + Int::class -> (this as Int) + (other as Int) + Long::class -> (this as Long) + (other as Long) + else -> TODO() +} as T + +inline fun Collection.median(): Double { + val sorted = this.sortedBy { + it.toDouble() + } + + return if (size.isEven || size == 1) { + sorted[size / 2] + } else { + sorted[size / 2] + sorted[size / 2 + 1] + }.toDouble() +} + +class Reproducer { + private var someListOfLongs = mutableListOf(1L) + + fun repro() = someListOfLongs.median() +} diff --git a/kotlin-native/backend.native/tests/codegen/basics/k42000_2.kt b/kotlin-native/backend.native/tests/codegen/basics/k42000_2.kt new file mode 100644 index 00000000000..fe264739fe7 --- /dev/null +++ b/kotlin-native/backend.native/tests/codegen/basics/k42000_2.kt @@ -0,0 +1,14 @@ +package codegen.basics.k42000_2 + +import kotlin.test.* + +// https://youtrack.jetbrains.com/issue/KT-42000 + +@Test +fun runTest() { + assertFailsWith { + when (1) { + else -> throw Error() + } as String + } +} diff --git a/kotlin-native/backend.native/tests/codegen/basics/local_variable.kt b/kotlin-native/backend.native/tests/codegen/basics/local_variable.kt new file mode 100644 index 00000000000..6ad41164f0f --- /dev/null +++ b/kotlin-native/backend.native/tests/codegen/basics/local_variable.kt @@ -0,0 +1,19 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +package codegen.basics.local_variable + +import kotlin.test.* + +fun local_variable(a: Int) : Int { + var b = 0 + b = a + 11 + return b +} + +@Test +fun runTest() { + if (local_variable(3) != 14) throw Error() +} \ No newline at end of file diff --git a/kotlin-native/backend.native/tests/codegen/basics/null_check.kt b/kotlin-native/backend.native/tests/codegen/basics/null_check.kt new file mode 100644 index 00000000000..777789d397a --- /dev/null +++ b/kotlin-native/backend.native/tests/codegen/basics/null_check.kt @@ -0,0 +1,40 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +package codegen.basics.null_check + +import kotlin.test.* + +//--- Test "eqeq" -------------------------------------------------------------// + +fun check_eqeq(a: Any?) = a == null + +fun null_check_eqeq1() : Boolean { + return check_eqeq(Any()) +} + +fun null_check_eqeq2() : Boolean { + return check_eqeq(null) +} + +//--- Test "eqeqeq" -----------------------------------------------------------// + +fun check_eqeqeq(a: Any?) = a === null + +fun null_check_eqeqeq1() : Boolean { + return check_eqeqeq(Any()) +} + +fun null_check_eqeqeq2() : Boolean { + return check_eqeqeq(null) +} + +@Test +fun runTest() { + if (null_check_eqeq1()) throw Error() + if (!null_check_eqeq2()) throw Error() + if (null_check_eqeqeq1()) throw Error() + if (!null_check_eqeqeq2()) throw Error() +} \ No newline at end of file diff --git a/kotlin-native/backend.native/tests/codegen/basics/safe_cast.kt b/kotlin-native/backend.native/tests/codegen/basics/safe_cast.kt new file mode 100644 index 00000000000..0448e1b3542 --- /dev/null +++ b/kotlin-native/backend.native/tests/codegen/basics/safe_cast.kt @@ -0,0 +1,32 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +package codegen.basics.safe_cast + +import kotlin.test.* + +open class A +class B : A() +class C + +fun foo(a: Any) : A? = a as? A + +fun safe_cast_positive(): Boolean { + val b = B() + return foo(b) === b +} + +fun safe_cast_negative(): Boolean { + val c = C() + return foo(c) == null +} + +@Test +fun runTest() { + val safeCastPositive = safe_cast_positive().toString() + val safeCastNegative = safe_cast_negative().toString() + println("safe_cast_positive: " + safeCastPositive) + println("safe_cast_negative: " + safeCastNegative) +} \ No newline at end of file diff --git a/kotlin-native/backend.native/tests/codegen/basics/spread_operator_0.kt b/kotlin-native/backend.native/tests/codegen/basics/spread_operator_0.kt new file mode 100644 index 00000000000..426d750fa75 --- /dev/null +++ b/kotlin-native/backend.native/tests/codegen/basics/spread_operator_0.kt @@ -0,0 +1,22 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +package codegen.basics.spread_operator_0 + +import kotlin.test.* + +@Test +fun runTest() { + val list0 = _arrayOf("K", "o", "t", "l", "i", "n") + val list1 = _arrayOf("l", "a","n", "g", "u", "a", "g", "e") + val list = foo(list0, list1) + println(list.toString()) +} + + +fun foo(a:Array, b:Array) = listOf(*a," ", "i", "s", " ", "c", "o", "o", "l", " ", *b) + + +fun _arrayOf(vararg arg:String) = arg \ No newline at end of file diff --git a/kotlin-native/backend.native/tests/codegen/basics/superFunCall.kt b/kotlin-native/backend.native/tests/codegen/basics/superFunCall.kt new file mode 100644 index 00000000000..b7e7a0b7b8e --- /dev/null +++ b/kotlin-native/backend.native/tests/codegen/basics/superFunCall.kt @@ -0,0 +1,29 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +package codegen.basics.superFunCall + +import kotlin.test.* + +open class C { + open fun f() = "" +} + +class C1: C() { + override fun f() = super.f() + "" +} + +open class C2: C() { +} + +class C3: C2() { + override fun f() = super.f() + "" +} + +@Test +fun runTest() { + println(C1().f()) + println(C3().f()) +} \ No newline at end of file diff --git a/kotlin-native/backend.native/tests/codegen/basics/superGetterCall.kt b/kotlin-native/backend.native/tests/codegen/basics/superGetterCall.kt new file mode 100644 index 00000000000..d4820a8b438 --- /dev/null +++ b/kotlin-native/backend.native/tests/codegen/basics/superGetterCall.kt @@ -0,0 +1,29 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +package codegen.basics.superGetterCall + +import kotlin.test.* + +open class C { + open val p1 = "" +} + +class C1: C() { + override val p1 = super.p1 + "" +} + +open class C2: C() { +} + +class C3: C2() { + override val p1 = super.p1 + "" +} + +@Test +fun runTest() { + println(C1().p1) + println(C3().p1) +} \ No newline at end of file diff --git a/kotlin-native/backend.native/tests/codegen/basics/superSetterCall.kt b/kotlin-native/backend.native/tests/codegen/basics/superSetterCall.kt new file mode 100644 index 00000000000..f21de91121d --- /dev/null +++ b/kotlin-native/backend.native/tests/codegen/basics/superSetterCall.kt @@ -0,0 +1,42 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +package codegen.basics.superSetterCall + +import kotlin.test.* + +open class C { + open var p2 = "" + set(value) { field = "" + value } +} + +class C1: C() { + override var p2 = super.p2 + "" + set(value) { + super.p2 = value + field = "" + super.p2 + } +} + +open class C2: C() { +} + +class C3: C2() { + override var p2 = super.p2 + "" + set(value) { + super.p2 = value + field = "" + super.p2 + } +} + +@Test +fun runTest() { + val c1 = C1() + val c3 = C3() + c1.p2 = "zzz" + c3.p2 = "zzz" + println(c1.p2) + println(c3.p2) +} \ No newline at end of file diff --git a/kotlin-native/backend.native/tests/codegen/basics/typealias1.kt b/kotlin-native/backend.native/tests/codegen/basics/typealias1.kt new file mode 100644 index 00000000000..6cd60ec3014 --- /dev/null +++ b/kotlin-native/backend.native/tests/codegen/basics/typealias1.kt @@ -0,0 +1,16 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +package codegen.basics.typealias1 + +import kotlin.test.* + +@Test +fun runTest() { + println(Bar(42).x) +} + +class Foo(val x: Int) +typealias Bar = Foo \ No newline at end of file diff --git a/kotlin-native/backend.native/tests/codegen/basics/unchecked_cast1.kt b/kotlin-native/backend.native/tests/codegen/basics/unchecked_cast1.kt new file mode 100644 index 00000000000..ac50d1c73df --- /dev/null +++ b/kotlin-native/backend.native/tests/codegen/basics/unchecked_cast1.kt @@ -0,0 +1,26 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +package codegen.basics.unchecked_cast1 + +import kotlin.test.* + +@Test +fun runTest() { + foo("17") + bar("17") + foo(42) + bar(42) +} + +fun foo(x: Any?) { + val y = x as T + println(y.toString()) +} + +fun bar(x: Any?) { + val y = x as? T + println(y.toString()) +} \ No newline at end of file diff --git a/kotlin-native/backend.native/tests/codegen/basics/unchecked_cast2.kt b/kotlin-native/backend.native/tests/codegen/basics/unchecked_cast2.kt new file mode 100644 index 00000000000..0b938520f31 --- /dev/null +++ b/kotlin-native/backend.native/tests/codegen/basics/unchecked_cast2.kt @@ -0,0 +1,20 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +package codegen.basics.unchecked_cast2 + +import kotlin.test.* + +@Test +fun runTest() { + try { + val x = cast(Any()) + println(x.length) + } catch (e: Throwable) { + println("Ok") + } +} + +fun cast(x: Any?) = x as T \ No newline at end of file diff --git a/kotlin-native/backend.native/tests/codegen/basics/unchecked_cast3.kt b/kotlin-native/backend.native/tests/codegen/basics/unchecked_cast3.kt new file mode 100644 index 00000000000..bd4557a7739 --- /dev/null +++ b/kotlin-native/backend.native/tests/codegen/basics/unchecked_cast3.kt @@ -0,0 +1,45 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +package codegen.basics.unchecked_cast3 + +import kotlin.test.* + +@Test +fun runTest() { + testCast(TestKlass(), true) + testCast(null, false) + testCastToNullable(null, true) + + println("Ok") +} + +class TestKlass + +fun ensure(b: Boolean) { + if (!b) { + println("Error") + } +} + +fun testCast(x: Any?, expectSuccess: Boolean) { + try { + x as T + } catch (e: Throwable) { + ensure(!expectSuccess) + return + } + ensure(expectSuccess) +} + +fun testCastToNullable(x: Any?, expectSuccess: Boolean) { + try { + x as T? + } catch (e: Throwable) { + ensure(!expectSuccess) + return + } + ensure(expectSuccess) +} \ No newline at end of file diff --git a/kotlin-native/backend.native/tests/codegen/basics/unchecked_cast4.kt b/kotlin-native/backend.native/tests/codegen/basics/unchecked_cast4.kt new file mode 100644 index 00000000000..39b266cdca6 --- /dev/null +++ b/kotlin-native/backend.native/tests/codegen/basics/unchecked_cast4.kt @@ -0,0 +1,31 @@ +/* + * Copyright 2010-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +package codegen.basics.unchecked_cast4 + +import kotlin.test.* + +@Test +fun runTest() { + CI1I2().uncheckedCast() + CI1I2().uncheckedCast() + + assertFailsWith { + Any().uncheckedCast() + } + + println("Ok") +} + +fun Any?.uncheckedCast() where R : I1, R : I2 { + this as R +} + +interface I1 +interface I2 +open class C + +class CI1I2 : C(), I1, I2 +class OtherCI1I2 : C(), I1, I2 \ No newline at end of file diff --git a/kotlin-native/backend.native/tests/codegen/basics/unit1.kt b/kotlin-native/backend.native/tests/codegen/basics/unit1.kt new file mode 100644 index 00000000000..6841a536c6e --- /dev/null +++ b/kotlin-native/backend.native/tests/codegen/basics/unit1.kt @@ -0,0 +1,13 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +package codegen.basics.unit1 + +import kotlin.test.* + +@Test +fun runTest() { + println(println("First").toString()) +} \ No newline at end of file diff --git a/kotlin-native/backend.native/tests/codegen/basics/unit2.kt b/kotlin-native/backend.native/tests/codegen/basics/unit2.kt new file mode 100644 index 00000000000..83d178e7723 --- /dev/null +++ b/kotlin-native/backend.native/tests/codegen/basics/unit2.kt @@ -0,0 +1,18 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +package codegen.basics.unit2 + +import kotlin.test.* + +@Test +fun runTest() { + val x = foo() + println(x.toString()) +} + +fun foo() { + return Unit +} \ No newline at end of file diff --git a/kotlin-native/backend.native/tests/codegen/basics/unit3.kt b/kotlin-native/backend.native/tests/codegen/basics/unit3.kt new file mode 100644 index 00000000000..34776bbe37d --- /dev/null +++ b/kotlin-native/backend.native/tests/codegen/basics/unit3.kt @@ -0,0 +1,17 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +package codegen.basics.unit3 + +import kotlin.test.* + +@Test +fun runTest() { + foo(Unit) +} + +fun foo(x: Any) { + println(x.toString()) +} \ No newline at end of file diff --git a/kotlin-native/backend.native/tests/codegen/basics/unit4.kt b/kotlin-native/backend.native/tests/codegen/basics/unit4.kt new file mode 100644 index 00000000000..2ffa8ab7117 --- /dev/null +++ b/kotlin-native/backend.native/tests/codegen/basics/unit4.kt @@ -0,0 +1,47 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +package codegen.basics.unit4 + +import kotlin.test.* + +@Test +fun runTest() { + for (x in 0 .. 8) { + foo(x, Unit) + } + println("Done") +} + +var global = 42 + +fun foo(x: Int, unit: Unit) { + var local = 5 + val y: Unit = when (x) { + 0 -> {} + 1 -> local = 6 + 2 -> global = 43 + 3 -> unit + 4 -> Unit + 5 -> bar() + 6 -> return + 7 -> { + 5 + bar() + } + 8 -> { + val z: Any = Unit + z as Unit + } + else -> throw Error() + } + + if (y !== Unit) { + println("Fail at x = $x") + } +} + +fun bar() { +} \ No newline at end of file diff --git a/kotlin-native/backend.native/tests/codegen/boxing/box_cache0.kt b/kotlin-native/backend.native/tests/codegen/boxing/box_cache0.kt new file mode 100644 index 00000000000..67330fbbafe --- /dev/null +++ b/kotlin-native/backend.native/tests/codegen/boxing/box_cache0.kt @@ -0,0 +1,54 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +package codegen.boxing.box_cache0 + +import kotlin.test.* + +fun areSame(arg1: T, arg2: T): Boolean { + return arg1 === arg2 +} + +@Test fun runTest() { + var acc = 0 + val range = 1000 + + for (i in arrayOf(false, true)) { + for (j in arrayOf(false, true)) { + acc += areSame(i, j).hashCode() + } + } + println(acc) + + acc = 0 + for (i in Byte.MIN_VALUE..Byte.MAX_VALUE) { + acc += areSame(i, i).hashCode() + } + println(acc) + + acc = 0 + for (i in Short.MIN_VALUE..Short.MAX_VALUE) { + acc += areSame(i, i).hashCode() + } + println(acc) + + acc = 0 + for (i in 0.toChar()..range.toChar()) { + acc += areSame(i, i).hashCode() + } + println(acc) + + acc = 0 + for (i in -range..range) { + acc += areSame(i, i).hashCode() + } + println(acc) + + acc = 0 + for (i in -range.toLong()..range.toLong()) { + acc += areSame(i, i).hashCode() + } + println(acc) +} \ No newline at end of file diff --git a/kotlin-native/backend.native/tests/codegen/boxing/boxing0.kt b/kotlin-native/backend.native/tests/codegen/boxing/boxing0.kt new file mode 100644 index 00000000000..c5d14cbfeb6 --- /dev/null +++ b/kotlin-native/backend.native/tests/codegen/boxing/boxing0.kt @@ -0,0 +1,18 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +package codegen.boxing.boxing0 + +import kotlin.test.* + +class Box(t: T) { + var value = t +} + +@Test fun runTest() { + val box: Box = Box(17) + println(box.value) +} + diff --git a/kotlin-native/backend.native/tests/codegen/boxing/boxing1.kt b/kotlin-native/backend.native/tests/codegen/boxing/boxing1.kt new file mode 100644 index 00000000000..0f02a747bfe --- /dev/null +++ b/kotlin-native/backend.native/tests/codegen/boxing/boxing1.kt @@ -0,0 +1,18 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +package codegen.boxing.boxing1 + +import kotlin.test.* + +fun foo(arg: Any) { + println(arg.toString()) +} + +@Test fun runTest() { + foo(1) + foo(false) + foo("Hello") +} \ No newline at end of file diff --git a/kotlin-native/backend.native/tests/codegen/boxing/boxing10.kt b/kotlin-native/backend.native/tests/codegen/boxing/boxing10.kt new file mode 100644 index 00000000000..b33acbe3ad1 --- /dev/null +++ b/kotlin-native/backend.native/tests/codegen/boxing/boxing10.kt @@ -0,0 +1,18 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +package codegen.boxing.boxing10 + +import kotlin.test.* + +@Test fun runTest() { + val FALSE: Boolean? = false + + if (FALSE != null) { + do { + println("Ok") + } while (FALSE) + } +} \ No newline at end of file diff --git a/kotlin-native/backend.native/tests/codegen/boxing/boxing11.kt b/kotlin-native/backend.native/tests/codegen/boxing/boxing11.kt new file mode 100644 index 00000000000..282952ecc98 --- /dev/null +++ b/kotlin-native/backend.native/tests/codegen/boxing/boxing11.kt @@ -0,0 +1,21 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +package codegen.boxing.boxing11 + +import kotlin.test.* + +fun printInt(x: Int) = println(x) + +class Foo(val value: Int?) { + fun foo() { + printInt(if (value != null) value else 42) + } +} + +@Test fun runTest() { + Foo(17).foo() + Foo(null).foo() +} \ No newline at end of file diff --git a/kotlin-native/backend.native/tests/codegen/boxing/boxing12.kt b/kotlin-native/backend.native/tests/codegen/boxing/boxing12.kt new file mode 100644 index 00000000000..0e1da69f866 --- /dev/null +++ b/kotlin-native/backend.native/tests/codegen/boxing/boxing12.kt @@ -0,0 +1,16 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +package codegen.boxing.boxing12 + +import kotlin.test.* + +fun foo(x: Number) { + println(x.toByte()) +} + +@Test fun runTest() { + foo(18) +} \ No newline at end of file diff --git a/kotlin-native/backend.native/tests/codegen/boxing/boxing13.kt b/kotlin-native/backend.native/tests/codegen/boxing/boxing13.kt new file mode 100644 index 00000000000..2e09d4c39ae --- /dev/null +++ b/kotlin-native/backend.native/tests/codegen/boxing/boxing13.kt @@ -0,0 +1,19 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +package codegen.boxing.boxing13 + +import kotlin.test.* + +fun is42(x: Any?) { + println(x == 42) + println(42 == x) +} + +@Test fun runTest() { + is42(16) + is42(42) + is42("42") +} \ No newline at end of file diff --git a/kotlin-native/backend.native/tests/codegen/boxing/boxing14.kt b/kotlin-native/backend.native/tests/codegen/boxing/boxing14.kt new file mode 100644 index 00000000000..d27c00d625b --- /dev/null +++ b/kotlin-native/backend.native/tests/codegen/boxing/boxing14.kt @@ -0,0 +1,14 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +package codegen.boxing.boxing14 + +import kotlin.test.* + +@Test fun runTest() { + 42.println() +} + +fun T.println() = println(this.toString()) \ No newline at end of file diff --git a/kotlin-native/backend.native/tests/codegen/boxing/boxing15.kt b/kotlin-native/backend.native/tests/codegen/boxing/boxing15.kt new file mode 100644 index 00000000000..5ad45971230 --- /dev/null +++ b/kotlin-native/backend.native/tests/codegen/boxing/boxing15.kt @@ -0,0 +1,14 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +package codegen.boxing.boxing15 + +import kotlin.test.* + +@Test fun runTest() { + println(foo(17)) +} + +fun foo(x: T): Int = x \ No newline at end of file diff --git a/kotlin-native/backend.native/tests/codegen/boxing/boxing2.kt b/kotlin-native/backend.native/tests/codegen/boxing/boxing2.kt new file mode 100644 index 00000000000..ab629b63a5f --- /dev/null +++ b/kotlin-native/backend.native/tests/codegen/boxing/boxing2.kt @@ -0,0 +1,26 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +package codegen.boxing.boxing2 + +import kotlin.test.* + +fun printInt(x: Int) = println(x) +fun printBoolean(x: Boolean) = println(x) + +fun foo(arg: Any) { + if (arg is Int) + printInt(arg) + else if (arg is Boolean) + printBoolean(arg) + else + println("other") +} + +@Test fun runTest() { + foo(1) + foo(true) + foo("Hello") +} \ No newline at end of file diff --git a/kotlin-native/backend.native/tests/codegen/boxing/boxing3.kt b/kotlin-native/backend.native/tests/codegen/boxing/boxing3.kt new file mode 100644 index 00000000000..5b4a8cc6545 --- /dev/null +++ b/kotlin-native/backend.native/tests/codegen/boxing/boxing3.kt @@ -0,0 +1,19 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +package codegen.boxing.boxing3 + +import kotlin.test.* + +fun printInt(x: Int) = println(x) + +fun foo(arg: Int?) { + if (arg != null) + printInt(arg) +} + +@Test fun runTest() { + foo(42) +} \ No newline at end of file diff --git a/kotlin-native/backend.native/tests/codegen/boxing/boxing4.kt b/kotlin-native/backend.native/tests/codegen/boxing/boxing4.kt new file mode 100644 index 00000000000..dc353896d54 --- /dev/null +++ b/kotlin-native/backend.native/tests/codegen/boxing/boxing4.kt @@ -0,0 +1,19 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +package codegen.boxing.boxing4 + +import kotlin.test.* + +fun printInt(x: Int) = println(x) + +fun foo(arg: Any?) { + if (arg is Int? && arg != null) + printInt(arg) +} + +@Test fun runTest() { + foo(16) +} \ No newline at end of file diff --git a/kotlin-native/backend.native/tests/codegen/boxing/boxing5.kt b/kotlin-native/backend.native/tests/codegen/boxing/boxing5.kt new file mode 100644 index 00000000000..abca34851f4 --- /dev/null +++ b/kotlin-native/backend.native/tests/codegen/boxing/boxing5.kt @@ -0,0 +1,19 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +package codegen.boxing.boxing5 + +import kotlin.test.* + +fun printInt(x: Int) = println(x) + +fun foo(arg: Int?) { + printInt(arg ?: 16) +} + +@Test fun runTest() { + foo(null) + foo(42) +} \ No newline at end of file diff --git a/kotlin-native/backend.native/tests/codegen/boxing/boxing6.kt b/kotlin-native/backend.native/tests/codegen/boxing/boxing6.kt new file mode 100644 index 00000000000..dc5fe1d6e62 --- /dev/null +++ b/kotlin-native/backend.native/tests/codegen/boxing/boxing6.kt @@ -0,0 +1,19 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +package codegen.boxing.boxing6 + +import kotlin.test.* + +fun printInt(x: Int) = println(x) + +fun foo(arg: Any) { + printInt(arg as? Int ?: 16) +} + +@Test fun runTest() { + foo(42) + foo("Hello") +} \ No newline at end of file diff --git a/kotlin-native/backend.native/tests/codegen/boxing/boxing7.kt b/kotlin-native/backend.native/tests/codegen/boxing/boxing7.kt new file mode 100644 index 00000000000..6544e4ee9b6 --- /dev/null +++ b/kotlin-native/backend.native/tests/codegen/boxing/boxing7.kt @@ -0,0 +1,24 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +package codegen.boxing.boxing7 + +import kotlin.test.* + +fun printInt(x: Int) = println(x) + +fun foo(arg: Any) { + val argAsInt = try { + arg as Int + } catch (e: ClassCastException) { + 0 + } + printInt(argAsInt) +} + +@Test fun runTest() { + foo(1) + foo("Hello") +} \ No newline at end of file diff --git a/kotlin-native/backend.native/tests/codegen/boxing/boxing8.kt b/kotlin-native/backend.native/tests/codegen/boxing/boxing8.kt new file mode 100644 index 00000000000..feff969e87c --- /dev/null +++ b/kotlin-native/backend.native/tests/codegen/boxing/boxing8.kt @@ -0,0 +1,18 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +package codegen.boxing.boxing8 + +import kotlin.test.* + +fun foo(vararg args: Any?) { + for (arg in args) { + println(arg.toString()) + } +} + +@Test fun runTest() { + foo(1, null, true, "Hello") +} \ No newline at end of file diff --git a/kotlin-native/backend.native/tests/codegen/boxing/boxing9.kt b/kotlin-native/backend.native/tests/codegen/boxing/boxing9.kt new file mode 100644 index 00000000000..82c850a77f2 --- /dev/null +++ b/kotlin-native/backend.native/tests/codegen/boxing/boxing9.kt @@ -0,0 +1,22 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +package codegen.boxing.boxing9 + +import kotlin.test.* + +fun foo(vararg args: Any?) { + for (arg in args) { + println(arg.toString()) + } +} + +fun bar(vararg args: Any?) { + foo(1, *args, 2, *args, 3) +} + +@Test fun runTest() { + bar(null, true, "Hello") +} \ No newline at end of file diff --git a/kotlin-native/backend.native/tests/codegen/branching/advanced_when2.kt b/kotlin-native/backend.native/tests/codegen/branching/advanced_when2.kt new file mode 100644 index 00000000000..1bc3e268502 --- /dev/null +++ b/kotlin-native/backend.native/tests/codegen/branching/advanced_when2.kt @@ -0,0 +1,23 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +package codegen.branching.advanced_when2 + +import kotlin.test.* + +fun advanced_when2(i: Int): Int { + var value = 1 + when (i) { + 10 -> {val v = 42; value = v} + 11 -> {val v = 43; value = v} + 12 -> {val v = 44; value = v} + } + + return value +} + +@Test fun runTest() { + if (advanced_when2(10) != 42) throw Error() +} diff --git a/kotlin-native/backend.native/tests/codegen/branching/advanced_when5.kt b/kotlin-native/backend.native/tests/codegen/branching/advanced_when5.kt new file mode 100644 index 00000000000..aaf6b20ac05 --- /dev/null +++ b/kotlin-native/backend.native/tests/codegen/branching/advanced_when5.kt @@ -0,0 +1,23 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +package codegen.branching.advanced_when5 + +import kotlin.test.* + +fun advanced_when5(i: Int): Int { + when (i) { + 0 -> { val v = 42; return v} + 1 -> { val v = 42; return v} + 2 -> { val v = 42; return v} + 3 -> { val v = 42; return v} + 4 -> { val v = 42; return v} + else -> return 24 + } +} + +@Test fun runTest() { + if (advanced_when5(5) != 24) throw Error() +} \ No newline at end of file diff --git a/kotlin-native/backend.native/tests/codegen/branching/if_else.kt b/kotlin-native/backend.native/tests/codegen/branching/if_else.kt new file mode 100644 index 00000000000..2aa2577e286 --- /dev/null +++ b/kotlin-native/backend.native/tests/codegen/branching/if_else.kt @@ -0,0 +1,17 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +package codegen.branching.if_else + +import kotlin.test.* + +fun if_else(b: Boolean): Int { + if (b) return 42 + else return 24 +} + +@Test fun runTest() { + if (if_else(false) != 24) throw Error() +} \ No newline at end of file diff --git a/kotlin-native/backend.native/tests/codegen/branching/when2.kt b/kotlin-native/backend.native/tests/codegen/branching/when2.kt new file mode 100644 index 00000000000..87c885c7280 --- /dev/null +++ b/kotlin-native/backend.native/tests/codegen/branching/when2.kt @@ -0,0 +1,19 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +package codegen.branching.when2 + +import kotlin.test.* + +fun when2(i: Int): Int { + when (i) { + 0 -> return 42 + else -> return 24 + } +} + +@Test fun runTest() { + if (when2(0) != 42) throw Error() +} \ No newline at end of file diff --git a/kotlin-native/backend.native/tests/codegen/branching/when4.kt b/kotlin-native/backend.native/tests/codegen/branching/when4.kt new file mode 100644 index 00000000000..32b44a1471e --- /dev/null +++ b/kotlin-native/backend.native/tests/codegen/branching/when4.kt @@ -0,0 +1,19 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +package codegen.branching.when4 + +import kotlin.test.* + +fun when5(i: Int): Int { + when (i) { + 0 -> return 42 + 1 -> return 4 + 2 -> return 3 + 3 -> return 2 + 4 -> return 1 + } + return 24 +} \ No newline at end of file diff --git a/kotlin-native/backend.native/tests/codegen/branching/when5.kt b/kotlin-native/backend.native/tests/codegen/branching/when5.kt new file mode 100644 index 00000000000..8401132e4ef --- /dev/null +++ b/kotlin-native/backend.native/tests/codegen/branching/when5.kt @@ -0,0 +1,23 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +package codegen.branching.when5 + +import kotlin.test.* + +fun when5(i: Int): Int { + when (i) { + 0 -> return 42 + 1 -> return 4 + 2 -> return 3 + 3 -> return 2 + 4 -> return 1 + else -> return 24 + } +} + +@Test fun runTest() { + if (when5(2) != 3) throw Error() +} \ No newline at end of file diff --git a/kotlin-native/backend.native/tests/codegen/branching/when6.kt b/kotlin-native/backend.native/tests/codegen/branching/when6.kt new file mode 100644 index 00000000000..352e59fdd9d --- /dev/null +++ b/kotlin-native/backend.native/tests/codegen/branching/when6.kt @@ -0,0 +1,15 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +package codegen.branching.when6 + +import kotlin.test.* + +fun foo() { +} + +@Test fun runTest() { + if (true) foo() else foo() +} \ No newline at end of file diff --git a/kotlin-native/backend.native/tests/codegen/branching/when7.kt b/kotlin-native/backend.native/tests/codegen/branching/when7.kt new file mode 100644 index 00000000000..65de6be8274 --- /dev/null +++ b/kotlin-native/backend.native/tests/codegen/branching/when7.kt @@ -0,0 +1,17 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +package codegen.branching.when7 + +import kotlin.test.* + +@Test fun runTest() { + main(emptyArray()) +} + +fun main(args: Array) { + val b = args.size < 1 + val x = if (b) Any() else throw Error() +} \ No newline at end of file diff --git a/kotlin-native/backend.native/tests/codegen/branching/when8.kt b/kotlin-native/backend.native/tests/codegen/branching/when8.kt new file mode 100644 index 00000000000..be9b52a0250 --- /dev/null +++ b/kotlin-native/backend.native/tests/codegen/branching/when8.kt @@ -0,0 +1,15 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +package codegen.branching.when8 + +import kotlin.test.* + +@Test fun runTest() { + when (true) { + true -> println("true") + false -> println("false") + } +} diff --git a/kotlin-native/backend.native/tests/codegen/branching/when9.kt b/kotlin-native/backend.native/tests/codegen/branching/when9.kt new file mode 100644 index 00000000000..84702808e43 --- /dev/null +++ b/kotlin-native/backend.native/tests/codegen/branching/when9.kt @@ -0,0 +1,19 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +package codegen.branching.when9 + +import kotlin.test.* + +@Test fun runTest() { + foo(0) + println("Ok") +} + +fun foo(x: Int) { + when (x) { + 0 -> 0 + } +} \ No newline at end of file diff --git a/kotlin-native/backend.native/tests/codegen/branching/when_through.kt b/kotlin-native/backend.native/tests/codegen/branching/when_through.kt new file mode 100644 index 00000000000..16a6fbc92fd --- /dev/null +++ b/kotlin-native/backend.native/tests/codegen/branching/when_through.kt @@ -0,0 +1,23 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +package codegen.branching.when_through + +import kotlin.test.* + +fun when_through(i: Int): Int { + var value = 1 + when (i) { + 10 -> value = 42 + 11 -> value = 43 + 12 -> value = 44 + } + + return value +} + +@Test fun runTest() { + if (when_through(2) != 1) throw Error() +} \ No newline at end of file diff --git a/kotlin-native/backend.native/tests/codegen/branching/when_with_try1.kt b/kotlin-native/backend.native/tests/codegen/branching/when_with_try1.kt new file mode 100644 index 00000000000..e10c2416143 --- /dev/null +++ b/kotlin-native/backend.native/tests/codegen/branching/when_with_try1.kt @@ -0,0 +1,27 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +package codegen.branching.when_with_try1 + +import kotlin.test.* + +@Test fun runTest() { + println(foo(Any())) + println(foo("zzz")) + println(foo("42")) +} + +fun foo(value: Any): Int? { + if (value is CharSequence) { + try { + return value.toString().toInt() + } catch (e: NumberFormatException) { + return null + } + } + else { + return null + } +} \ No newline at end of file diff --git a/kotlin-native/backend.native/tests/codegen/bridges/linkTest2_lib.kt b/kotlin-native/backend.native/tests/codegen/bridges/linkTest2_lib.kt new file mode 100644 index 00000000000..2dd54bf5e42 --- /dev/null +++ b/kotlin-native/backend.native/tests/codegen/bridges/linkTest2_lib.kt @@ -0,0 +1,20 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +sealed class Tag { + abstract fun value(): Any +} + +sealed class TagBoolean : Tag() { + abstract override fun value(): Boolean + + object True : TagBoolean() { + override fun value() = true + } + + object False : TagBoolean() { + override fun value() = false + } +} \ No newline at end of file diff --git a/kotlin-native/backend.native/tests/codegen/bridges/linkTest2_main.kt b/kotlin-native/backend.native/tests/codegen/bridges/linkTest2_main.kt new file mode 100644 index 00000000000..86e5845fc8b --- /dev/null +++ b/kotlin-native/backend.native/tests/codegen/bridges/linkTest2_main.kt @@ -0,0 +1,9 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +fun main(args: Array) { + val test: TagBoolean = TagBoolean.True + println(test.value()) +} diff --git a/kotlin-native/backend.native/tests/codegen/bridges/linkTest_lib.kt b/kotlin-native/backend.native/tests/codegen/bridges/linkTest_lib.kt new file mode 100644 index 00000000000..52eeb61a0d2 --- /dev/null +++ b/kotlin-native/backend.native/tests/codegen/bridges/linkTest_lib.kt @@ -0,0 +1,14 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +package a + +interface A { + fun foo(): T +} + +open class C: A { + override fun foo(): Int = 42 +} \ No newline at end of file diff --git a/kotlin-native/backend.native/tests/codegen/bridges/linkTest_main.kt b/kotlin-native/backend.native/tests/codegen/bridges/linkTest_main.kt new file mode 100644 index 00000000000..f2ff083fc16 --- /dev/null +++ b/kotlin-native/backend.native/tests/codegen/bridges/linkTest_main.kt @@ -0,0 +1,17 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +import a.* + +class B: C() + +fun main(args: Array) { + val b = B() + println(b.foo()) + val c: C = b + println(c.foo()) + val a: A = b + println(a.foo()) +} \ No newline at end of file diff --git a/kotlin-native/backend.native/tests/codegen/bridges/nativePointed.kt b/kotlin-native/backend.native/tests/codegen/bridges/nativePointed.kt new file mode 100644 index 00000000000..00151feb2a4 --- /dev/null +++ b/kotlin-native/backend.native/tests/codegen/bridges/nativePointed.kt @@ -0,0 +1,23 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +package codegen.bridges.nativePointed + +import kotlinx.cinterop.* +import kotlin.test.* + +abstract class C { + abstract fun foo(x: Int): CPointer<*>? +} + +class CImpl : C() { + override fun foo(x: Int) = null +} + +@Test fun runTest() { + val c: C = CImpl() + assertNull(c.foo(42)) +} + diff --git a/kotlin-native/backend.native/tests/codegen/bridges/returnTypeSignature.kt b/kotlin-native/backend.native/tests/codegen/bridges/returnTypeSignature.kt new file mode 100644 index 00000000000..d9e0e8d5aff --- /dev/null +++ b/kotlin-native/backend.native/tests/codegen/bridges/returnTypeSignature.kt @@ -0,0 +1,34 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +package codegen.bridges.signature + +import kotlin.test.* + +class A { } + +class B { } + +class C { } + +interface Parser { + fun parse(source: IN): OUT +} + +interface MultiParser { + fun parse(source: IN): Collection +} + +interface ExtendsInterface: Parser, MultiParser { + override fun parse(source: B): Collection = ArrayList() +} + +abstract class AbstractClass(): ExtendsInterface { + public override fun parse(source: A): C = C() +} + +@Test fun runTest() { + val array = object : AbstractClass() { }.parse(B()) +} \ No newline at end of file diff --git a/kotlin-native/backend.native/tests/codegen/bridges/special.kt b/kotlin-native/backend.native/tests/codegen/bridges/special.kt new file mode 100644 index 00000000000..0a685a4f8f3 --- /dev/null +++ b/kotlin-native/backend.native/tests/codegen/bridges/special.kt @@ -0,0 +1,46 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +package codegen.bridges.special + +import kotlin.test.* + +private object NotEmptyMap : MutableMap { + override fun containsKey(key: Any): Boolean = true + override fun containsValue(value: Int): Boolean = true + + // non-special bridges get(Object)Integer -> get(Object)I + override fun get(key: Any): Int = 1 + override fun remove(key: Any): Int = 1 + + override val size: Int get() = 0 + override fun isEmpty(): Boolean = true + override fun put(key: Any, value: Int): Int? = throw UnsupportedOperationException() + override fun putAll(from: Map): Unit = throw UnsupportedOperationException() + override fun clear(): Unit = throw UnsupportedOperationException() + override val entries: MutableSet> get() = null!! + override val keys: MutableSet get() = null!! + override val values: MutableCollection get() = null!! +} + +fun box(): String { + val n = NotEmptyMap as MutableMap + + if (n.get(null) != null) return "fail 1" + if (n.containsKey(null)) return "fail 2" + if (n.containsValue(null)) return "fail 3" + if (n.remove(null) != null) return "fail 4" + + if (n.get(1) == null) return "fail 5" + if (!n.containsKey("")) return "fail 6" + if (!n.containsValue(3)) return "fail 7" + if (n.remove("") == null) return "fail 8" + + return "Ok" +} + +@Test fun runTest() { + println(box()) +} \ No newline at end of file diff --git a/kotlin-native/backend.native/tests/codegen/bridges/test0.kt b/kotlin-native/backend.native/tests/codegen/bridges/test0.kt new file mode 100644 index 00000000000..41a28b75383 --- /dev/null +++ b/kotlin-native/backend.native/tests/codegen/bridges/test0.kt @@ -0,0 +1,24 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +package codegen.bridges.test0 + +import kotlin.test.* + +// vtable call +open class A { + open fun foo(): Any = "A" +} + +open class C : A() { + override fun foo(): Int = 42 +} + +@Test fun runTest() { + val c = C() + val a: A = c + println(c.foo().toString()) + println(a.foo().toString()) +} \ No newline at end of file diff --git a/kotlin-native/backend.native/tests/codegen/bridges/test1.kt b/kotlin-native/backend.native/tests/codegen/bridges/test1.kt new file mode 100644 index 00000000000..9c677232844 --- /dev/null +++ b/kotlin-native/backend.native/tests/codegen/bridges/test1.kt @@ -0,0 +1,27 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +package codegen.bridges.test1 + +import kotlin.test.* + +// interface call, bridge overridden +interface Z1 { + fun foo(x: Int) : Any +} + +open class A : Z1 { + override fun foo(x: Int) : Int = 5 +} + +open class B : A() { + override fun foo(x: Int) : Int = 42 +} + +@Test fun runTest() { + val z1: A = B() + println((z1.foo(1) + 1000).toString()) +} + diff --git a/kotlin-native/backend.native/tests/codegen/bridges/test10.kt b/kotlin-native/backend.native/tests/codegen/bridges/test10.kt new file mode 100644 index 00000000000..8a6c0b62f79 --- /dev/null +++ b/kotlin-native/backend.native/tests/codegen/bridges/test10.kt @@ -0,0 +1,37 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +package codegen.bridges.test10 + +import kotlin.test.* + +open class A { + open fun foo(x: T) { + println(x.toString()) + } +} + +interface I { + fun foo(x: Int) +} + +class B : A(), I { + var z: Int = 5 + override fun foo(x: Int) { + z = x + } +} + +fun zzz(a: A) { + a.foo(42) +} + +@Test fun runTest() { + val b = B() + zzz(b) + val a = A() + zzz(a) + println(b.z) +} \ No newline at end of file diff --git a/kotlin-native/backend.native/tests/codegen/bridges/test11.kt b/kotlin-native/backend.native/tests/codegen/bridges/test11.kt new file mode 100644 index 00000000000..eed0d47b2c9 --- /dev/null +++ b/kotlin-native/backend.native/tests/codegen/bridges/test11.kt @@ -0,0 +1,29 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +package codegen.bridges.test11 + +import kotlin.test.* + +interface I { + fun foo(x: Int) +} + +abstract class A { + abstract fun foo(x: T) +} + +class B : A(), I { + override fun foo(x: Int) = println(x) +} + +@Test fun runTest() { + val b = B() + val a: A = b + val c: I = b + b.foo(42) + a.foo(42) + c.foo(42) +} \ No newline at end of file diff --git a/kotlin-native/backend.native/tests/codegen/bridges/test12.kt b/kotlin-native/backend.native/tests/codegen/bridges/test12.kt new file mode 100644 index 00000000000..61b203bf347 --- /dev/null +++ b/kotlin-native/backend.native/tests/codegen/bridges/test12.kt @@ -0,0 +1,33 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +package codegen.bridges.test12 + +import kotlin.test.* + +abstract class A { + abstract fun foo(x: T) +} + +class B : A() { + override fun foo(x: Int) { + println("B: $x") + } +} + +class C : A() { + override fun foo(x: Any) { + println("C: $x") + } +} + +fun foo(arg: A) { + arg.foo(42) +} + +@Test fun runTest() { + foo(B()) + foo(C()) +} \ No newline at end of file diff --git a/kotlin-native/backend.native/tests/codegen/bridges/test13.kt b/kotlin-native/backend.native/tests/codegen/bridges/test13.kt new file mode 100644 index 00000000000..f564ae68c34 --- /dev/null +++ b/kotlin-native/backend.native/tests/codegen/bridges/test13.kt @@ -0,0 +1,31 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +package codegen.bridges.test13 + +import kotlin.test.* + +open class A { + open fun T.foo() { + println(this.toString()) + } + + fun bar(x: T) { + x.foo() + } +} + +open class B: A() { + override fun Int.foo() { + println(this) + } +} + +@Test fun runTest() { + val b = B() + val a = A() + b.bar(42) + a.bar(42) +} \ No newline at end of file diff --git a/kotlin-native/backend.native/tests/codegen/bridges/test14.kt b/kotlin-native/backend.native/tests/codegen/bridges/test14.kt new file mode 100644 index 00000000000..738deb16f12 --- /dev/null +++ b/kotlin-native/backend.native/tests/codegen/bridges/test14.kt @@ -0,0 +1,53 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +package codegen.bridges.test14 + +import kotlin.test.* + +open class A { + open fun foo(x: T, y: U) { + println(x.toString()) + println(y.toString()) + } +} + +interface I1 { + fun foo(x: Int, y: T) +} + +interface I2 { + fun foo(x: T, y: Int) +} + +class B : A(), I1, I2 { + var z: Int = 5 + var q: Int = 7 + override fun foo(x: Int, y: Int) { + z = x + q = y + } +} + +fun zzz(a: A) { + a.foo(42, 56) +} + +@Test fun runTest() { + val b = B() + zzz(b) + val a = A() + zzz(a) + println(b.z) + println(b.q) + val i1: I1 = b + i1.foo(56, 42) + println(b.z) + println(b.q) + val i2: I2 = b + i2.foo(156, 142) + println(b.z) + println(b.q) +} \ No newline at end of file diff --git a/kotlin-native/backend.native/tests/codegen/bridges/test15.kt b/kotlin-native/backend.native/tests/codegen/bridges/test15.kt new file mode 100644 index 00000000000..7e53ac2598b --- /dev/null +++ b/kotlin-native/backend.native/tests/codegen/bridges/test15.kt @@ -0,0 +1,44 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +package codegen.bridges.test15 + +import kotlin.test.* + +// non-generic interface, generic impl, vtable call + interface call +open class A { + open var size: T = 56 as T +} + +interface C { + var size: Int +} + +open class B : C, A() + +open class D: B() { + override var size: Int = 117 +} + +fun foo(a: A) { + a.size = 42 as T +} + +fun box(): String { + val b = B() + + foo(b) + if (b.size != 42) return "fail 1" + val d = D() + if (d.size != 117) return "fail 2" + foo(d) + if (d.size != 42) return "fail 3" + + return "OK" +} + +@Test fun runTest() { + println(box()) +} \ No newline at end of file diff --git a/kotlin-native/backend.native/tests/codegen/bridges/test16.kt b/kotlin-native/backend.native/tests/codegen/bridges/test16.kt new file mode 100644 index 00000000000..b691a585c82 --- /dev/null +++ b/kotlin-native/backend.native/tests/codegen/bridges/test16.kt @@ -0,0 +1,29 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +package codegen.bridges.test16 + +import kotlin.test.* + +interface A { + fun foo(): String +} + +abstract class C: A + +open class B: C() { + override fun foo(): String { + return "OK" + } +} + +fun bar(c: C) = c.foo() + +@Test fun runTest() { + val b = B() + val c: C = b + println(bar(b)) + println(bar(c)) +} \ No newline at end of file diff --git a/kotlin-native/backend.native/tests/codegen/bridges/test17.kt b/kotlin-native/backend.native/tests/codegen/bridges/test17.kt new file mode 100644 index 00000000000..21af6f99e2d --- /dev/null +++ b/kotlin-native/backend.native/tests/codegen/bridges/test17.kt @@ -0,0 +1,34 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +package codegen.bridges.test17 + +import kotlin.test.* + +// abstract bridge +interface A { + fun foo(): T +} + +abstract class B: A + +abstract class C: B() + +class D: C() { + override fun foo(): Int { + return 42 + } +} + +@Test fun runTest() { + val d = D() + val c: C = d + val b: B = d + val a: A = d + println(d.foo()) + println(c.foo()) + println(b.foo()) + println(a.foo()) +} \ No newline at end of file diff --git a/kotlin-native/backend.native/tests/codegen/bridges/test18.kt b/kotlin-native/backend.native/tests/codegen/bridges/test18.kt new file mode 100644 index 00000000000..c6d47b73475 --- /dev/null +++ b/kotlin-native/backend.native/tests/codegen/bridges/test18.kt @@ -0,0 +1,22 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +package codegen.bridges.test18 + +import kotlin.test.* + +// overriden function returns Unit +open class A { + open fun foo(): Any = 42 +} + +open class B: A() { + override fun foo(): Unit { } +} + +@Test fun runTest() { + val a: A = B() + println(a.foo()) +} diff --git a/kotlin-native/backend.native/tests/codegen/bridges/test2.kt b/kotlin-native/backend.native/tests/codegen/bridges/test2.kt new file mode 100644 index 00000000000..df13d9d14b0 --- /dev/null +++ b/kotlin-native/backend.native/tests/codegen/bridges/test2.kt @@ -0,0 +1,26 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +package codegen.bridges.test2 + +import kotlin.test.* + +// vtable call, bridge inherited +open class A { + open fun foo(): Any = "A" +} + +open class C : A() { + override fun foo(): Int = 42 +} + +open class D: C() + +@Test fun runTest() { + val c = D() + val a: A = c + println(c.foo().toString()) + println(a.foo().toString()) +} \ No newline at end of file diff --git a/kotlin-native/backend.native/tests/codegen/bridges/test3.kt b/kotlin-native/backend.native/tests/codegen/bridges/test3.kt new file mode 100644 index 00000000000..60e88a22909 --- /dev/null +++ b/kotlin-native/backend.native/tests/codegen/bridges/test3.kt @@ -0,0 +1,39 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +package codegen.bridges.test3 + +import kotlin.test.* + +// non-generic interface, generic impl, non-virtual call + interface call +open class A { + var size: T = 56 as T +} + +interface C { + var size: Int +} + +class B : C, A() + +fun box(): String { + val b = B() + if (b.size != 56) return "fail 1" + + b.size = 55 + if (b.size != 55) return "fail 2" + + val c: C = b + if (c.size != 55) return "fail 3" + + c.size = 57 + if (c.size != 57) return "fail 4" + + return "OK" +} + +@Test fun runTest() { + println(box()) +} diff --git a/kotlin-native/backend.native/tests/codegen/bridges/test4.kt b/kotlin-native/backend.native/tests/codegen/bridges/test4.kt new file mode 100644 index 00000000000..68092d868f0 --- /dev/null +++ b/kotlin-native/backend.native/tests/codegen/bridges/test4.kt @@ -0,0 +1,30 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +package codegen.bridges.test4 + +import kotlin.test.* + +// vtable call + interface call +interface Z { + fun foo(): Any +} + +interface Y { + fun foo(): Int +} + +open class A { + fun foo(): Int = 42 +} + +open class B: A(), Z, Y + +@Test fun runTest() { + val z: Z = B() + val y: Y = z as Y + println(z.foo().toString()) + println(y.foo().toString()) +} \ No newline at end of file diff --git a/kotlin-native/backend.native/tests/codegen/bridges/test5.kt b/kotlin-native/backend.native/tests/codegen/bridges/test5.kt new file mode 100644 index 00000000000..d96af81e848 --- /dev/null +++ b/kotlin-native/backend.native/tests/codegen/bridges/test5.kt @@ -0,0 +1,39 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +package codegen.bridges.test5 + +import kotlin.test.* + +// non-generic interface, generic impl, vtable call + interface call +open class A { + open var size: T = 56 as T +} + +interface C { + var size: Int +} + +open class B : C, A() + +fun box(): String { + val b = B() + if (b.size != 56) return "fail 1" + + b.size = 55 + if (b.size != 55) return "fail 2" + + val c: C = b + if (c.size != 55) return "fail 3" + + c.size = 57 + if (c.size != 57) return "fail 4" + + return "OK" +} + +@Test fun runTest() { + println(box()) +} \ No newline at end of file diff --git a/kotlin-native/backend.native/tests/codegen/bridges/test6.kt b/kotlin-native/backend.native/tests/codegen/bridges/test6.kt new file mode 100644 index 00000000000..d2ac309edc9 --- /dev/null +++ b/kotlin-native/backend.native/tests/codegen/bridges/test6.kt @@ -0,0 +1,40 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +package codegen.bridges.test6 + +import kotlin.test.* + +// vtable call + interface call +interface Z { + fun foo(): Any +} + +interface Y { + fun foo(): Int +} + +open class A { + open fun foo(): Any = "A" +} + +open class C : A() { + override fun foo(): Int = 42 +} + +open class D: C(), Y, Z + +@Test fun runTest() { + val d = D() + val y: Y = d + val z: Z = d + val c: C = d + val a: A = d + println(d.foo().toString()) + println(y.foo().toString()) + println(z.foo().toString()) + println(c.foo().toString()) + println(a.foo().toString()) +} \ No newline at end of file diff --git a/kotlin-native/backend.native/tests/codegen/bridges/test7.kt b/kotlin-native/backend.native/tests/codegen/bridges/test7.kt new file mode 100644 index 00000000000..943756ebc31 --- /dev/null +++ b/kotlin-native/backend.native/tests/codegen/bridges/test7.kt @@ -0,0 +1,39 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +package codegen.bridges.test7 + +import kotlin.test.* + +// generic interface, non-generic impl, vtable call + interface call +open class A { + open var size: Int = 56 +} + +interface C { + var size: T +} + +open class B : C, A() + +fun box(): String { + val b = B() + if (b.size != 56) return "fail 1" + + b.size = 55 + if (b.size != 55) return "fail 2" + + val c: C = b + if (c.size != 55) return "fail 3" + + c.size = 57 + if (c.size != 57) return "fail 4" + + return "OK" +} + +@Test fun runTest() { + println(box()) +} \ No newline at end of file diff --git a/kotlin-native/backend.native/tests/codegen/bridges/test8.kt b/kotlin-native/backend.native/tests/codegen/bridges/test8.kt new file mode 100644 index 00000000000..a401382a272 --- /dev/null +++ b/kotlin-native/backend.native/tests/codegen/bridges/test8.kt @@ -0,0 +1,39 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +package codegen.bridges.test8 + +import kotlin.test.* + +// generic interface, non-generic impl, non-virtual call + interface call +open class A { + var size: Int = 56 +} + +interface C { + var size: T +} + +class B : C, A() + +fun box(): String { + val b = B() + if (b.size != 56) return "fail 1" + + b.size = 55 + if (b.size != 55) return "fail 2" + + val c: C = b + if (c.size != 55) return "fail 3" + + c.size = 57 + if (c.size != 57) return "fail 4" + + return "OK" +} + +@Test fun runTest() { + println(box()) +} \ No newline at end of file diff --git a/kotlin-native/backend.native/tests/codegen/bridges/test9.kt b/kotlin-native/backend.native/tests/codegen/bridges/test9.kt new file mode 100644 index 00000000000..176ceae69b7 --- /dev/null +++ b/kotlin-native/backend.native/tests/codegen/bridges/test9.kt @@ -0,0 +1,36 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +package codegen.bridges.test9 + +import kotlin.test.* + +// abstract class vtable call +abstract class A { + abstract fun foo(): String +} + +abstract class B : A() + +class Z : B() { + override fun foo() = "Z" +} + + +fun box(): String { + val z = Z() + val b: B = z + val a: A = z + return when { + z.foo() != "Z" -> "Fail #1" + b.foo() != "Z" -> "Fail #2" + a.foo() != "Z" -> "Fail #3" + else -> "OK" + } +} + +@Test fun runTest() { + println(box()) +} \ No newline at end of file diff --git a/kotlin-native/backend.native/tests/codegen/classDelegation/generic.kt b/kotlin-native/backend.native/tests/codegen/classDelegation/generic.kt new file mode 100644 index 00000000000..022696b8824 --- /dev/null +++ b/kotlin-native/backend.native/tests/codegen/classDelegation/generic.kt @@ -0,0 +1,30 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +package codegen.classDelegation.generic + +import kotlin.test.* + +open class Content() { + override fun toString() = "OK" +} + +interface Box { + fun get(): E +} + +interface ContentBox : Box + +object Impl : ContentBox { + override fun get(): Content = Content() +} + +class ContentBoxDelegate() : ContentBox by (Impl as ContentBox) + +fun box() = ContentBoxDelegate().get().toString() + +@Test fun runTest() { + println(box()) +} \ No newline at end of file diff --git a/kotlin-native/backend.native/tests/codegen/classDelegation/linkTest_lib.kt b/kotlin-native/backend.native/tests/codegen/classDelegation/linkTest_lib.kt new file mode 100644 index 00000000000..a9d001fab69 --- /dev/null +++ b/kotlin-native/backend.native/tests/codegen/classDelegation/linkTest_lib.kt @@ -0,0 +1,19 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +package zzz + +interface I { + fun foo(): Int +} + +open class A : I { + override fun foo() = 42 +} + +open class B : I by A() { + val x = 117 + val y = "zzz" +} \ No newline at end of file diff --git a/kotlin-native/backend.native/tests/codegen/classDelegation/linkTest_main.kt b/kotlin-native/backend.native/tests/codegen/classDelegation/linkTest_main.kt new file mode 100644 index 00000000000..0005ae4752b --- /dev/null +++ b/kotlin-native/backend.native/tests/codegen/classDelegation/linkTest_main.kt @@ -0,0 +1,20 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +import zzz.* + +class C : B() { + val a = "qxx" + val b = 123 +} + +fun main(args: Array) { + val c = C() + println(c.a) + println(c.b) + println(c.foo()) + println(c.x) + println(c.y) +} \ No newline at end of file diff --git a/kotlin-native/backend.native/tests/codegen/classDelegation/method.kt b/kotlin-native/backend.native/tests/codegen/classDelegation/method.kt new file mode 100644 index 00000000000..1b013f831de --- /dev/null +++ b/kotlin-native/backend.native/tests/codegen/classDelegation/method.kt @@ -0,0 +1,28 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +package codegen.classDelegation.method + +import kotlin.test.* + +interface A { + fun foo(): T +} + +class B : A { + override fun foo() = "OK" +} + +class C(a: A) : A by a + +fun box(): String { + val c = C(B()) + val a: A = c + return c.foo() + a.foo() +} + +@Test fun runTest() { + println(box()) +} \ No newline at end of file diff --git a/kotlin-native/backend.native/tests/codegen/classDelegation/property.kt b/kotlin-native/backend.native/tests/codegen/classDelegation/property.kt new file mode 100644 index 00000000000..a55a5458a17 --- /dev/null +++ b/kotlin-native/backend.native/tests/codegen/classDelegation/property.kt @@ -0,0 +1,28 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +package codegen.classDelegation.property + +import kotlin.test.* + +interface A { + val x: Int +} + +class C: A { + override val x: Int = 42 +} + +class Q(a: A): A by a + +fun box(): String { + val q = Q(C()) + val a: A = q + return q.x.toString() + a.x.toString() +} + +@Test fun runTest() { + println(box()) +} \ No newline at end of file diff --git a/kotlin-native/backend.native/tests/codegen/classDelegation/withBridge.kt b/kotlin-native/backend.native/tests/codegen/classDelegation/withBridge.kt new file mode 100644 index 00000000000..60112822c3c --- /dev/null +++ b/kotlin-native/backend.native/tests/codegen/classDelegation/withBridge.kt @@ -0,0 +1,37 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +package codegen.classDelegation.withBridge + +import kotlin.test.* + +interface A { + fun foo(t: T): String +} + +interface B { + fun foo(t: Int) = "B" +} + +class Z : B + +class Z1 : A, B by Z() + +fun box(): String { + val z1 = Z1() + val z1a: A = z1 + val z1b: B = z1 + + return when { + z1.foo( 0) != "B" -> "Fail #1" + z1a.foo( 0) != "B" -> "Fail #2" + z1b.foo( 0) != "B" -> "Fail #3" + else -> "OK" + } +} + +@Test fun runTest() { + println(box()) +} \ No newline at end of file diff --git a/kotlin-native/backend.native/tests/codegen/contracts/contracts.kt b/kotlin-native/backend.native/tests/codegen/contracts/contracts.kt new file mode 100644 index 00000000000..cf87b973605 --- /dev/null +++ b/kotlin-native/backend.native/tests/codegen/contracts/contracts.kt @@ -0,0 +1,47 @@ +import kotlin.test.* +import kotlin.contracts.* + +open class S +class P(val str: String = "P") : S() + +@OptIn(kotlin.contracts.ExperimentalContracts::class) +fun check(actual: Boolean) { + contract { returns() implies actual } + assertTrue(actual) +} + +@Test fun testContractForCast() { + val s: S = P() + + check(s is P) + assertEquals(s.str, "P") +} + +@Test fun testRequire() { + val s: S = P() + + require(s is P) + assertEquals(s.str, "P") +} + +@Test fun testNonNullSmartCast() { + val i: Int? = 1234 + requireNotNull(i) + assertEquals(i, 1234) +} + +@Test fun testRunLambdaForVal() { + val x: Int + run { + x = 42 + } + assertEquals(x, 42) +} + +@Test fun testIsNullString() { + assertEquals("STR", nullableString("str")) + + assertEquals("", nullableString(null)) +} + +private fun nullableString(string: String?): String = if (string.isNullOrBlank()) "" else "STR" \ No newline at end of file diff --git a/kotlin-native/backend.native/tests/codegen/controlflow/break.kt b/kotlin-native/backend.native/tests/codegen/controlflow/break.kt new file mode 100644 index 00000000000..46a230b4662 --- /dev/null +++ b/kotlin-native/backend.native/tests/codegen/controlflow/break.kt @@ -0,0 +1,61 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +package codegen.controlflow.`break` + +import kotlin.test.* + +fun foo() { + var i = 0 + l1@while (true) { + println("foo@l1") + try { + l2@while (true) { + if ((i++ % 2) == 0) continue@l2 + println("foo@l2") + if (i > 4) break@l1 + } + } finally { + } + } +} + +fun bar() { + var i = 0 + l1@do { + try { + println("bar@l1") + throw Exception() + } catch (e: Exception) { + l2@do { + if ((i++ % 2) == 0) continue@l2 + println("bar@l2") + if (i > 4) break@l1 + } while (true) + } + } while (true) +} + +fun qux() { + l1@for (i in 1..6) { + t1@try { + println("qux@t1") + throw Exception() + } + finally { + l2@ for (j in 1..6) { + if ((j % 2) == 0) continue@l2 + println("qux@l2") + if (j > 4) break@l1 + } + } + } +} + +@Test fun runTest() { + foo() + bar() + qux() +} diff --git a/kotlin-native/backend.native/tests/codegen/controlflow/break1.kt b/kotlin-native/backend.native/tests/codegen/controlflow/break1.kt new file mode 100644 index 00000000000..b9aac1dbd05 --- /dev/null +++ b/kotlin-native/backend.native/tests/codegen/controlflow/break1.kt @@ -0,0 +1,16 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +package codegen.controlflow.break1 + +import kotlin.test.* + +@Test fun runTest() { + loop@ while (true) { + println("Body") + break + } + println("Done") +} diff --git a/kotlin-native/backend.native/tests/codegen/controlflow/for_loops.kt b/kotlin-native/backend.native/tests/codegen/controlflow/for_loops.kt new file mode 100644 index 00000000000..124441eb91d --- /dev/null +++ b/kotlin-native/backend.native/tests/codegen/controlflow/for_loops.kt @@ -0,0 +1,83 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +package codegen.controlflow.for_loops + +import kotlin.test.* + +@Test fun runTest() { + + // Simple loops + for (i in 0..4) { + print(i) + } + println() + + for (i in 0 until 4) { + print(i) + } + println() + + for (i in 4 downTo 0) { + print(i) + } + println() + println() + + // Steps + for (i in 0..4 step 2) { + print(i) + } + println() + + for (i in 0 until 4 step 2) { + print(i) + } + println() + + for (i in 4 downTo 0 step 2) { + print(i) + } + println() + println() + + + // Two steps + for (i in 0..6 step 2 step 3) { + print(i) + } + println() + + for (i in 0 until 6 step 2 step 3) { + print(i) + } + println() + + for (i in 6 downTo 0 step 2 step 3) { + print(i) + } + println() + println() + + // Without constants + val a = 0 + val b = 4 + val s = 2 + for (i in a..b step s) { + print(i) + } + println() + + for (i in a until b step s) { + print(i) + } + println() + + for (i in b downTo a step s) { + print(i) + } + println() + println() +} \ No newline at end of file diff --git a/kotlin-native/backend.native/tests/codegen/controlflow/for_loops_array.kt b/kotlin-native/backend.native/tests/codegen/controlflow/for_loops_array.kt new file mode 100644 index 00000000000..68cec2fed38 --- /dev/null +++ b/kotlin-native/backend.native/tests/codegen/controlflow/for_loops_array.kt @@ -0,0 +1,40 @@ +package codegen.controlflow.for_loops_array + +import kotlin.test.* + +fun genericArray(data : T): Int { + var sum = 0 + for (element in data) { + sum += element + } + return sum +} + +fun IntArray.sum(): Int { + var sum = 0 + for (element in this) { + sum += element + } + return sum +} + +@Test fun runTest() { + val intArray = intArrayOf(4, 0, 3, 5) + + val emptyArray = arrayOf() + + for (element in intArray) { + print(element) + } + println() + for (element in emptyArray) { + print(element) + } + println() + + val byteArray = byteArrayOf(1, -1) + println(genericArray(byteArray)) + + val fives = intArrayOf(5, 5, 5, -5, -5, -5) + println(fives.sum()) +} \ No newline at end of file diff --git a/kotlin-native/backend.native/tests/codegen/controlflow/for_loops_array_break_continue.kt b/kotlin-native/backend.native/tests/codegen/controlflow/for_loops_array_break_continue.kt new file mode 100644 index 00000000000..d107a550726 --- /dev/null +++ b/kotlin-native/backend.native/tests/codegen/controlflow/for_loops_array_break_continue.kt @@ -0,0 +1,21 @@ +package codegen.controlflow.for_loops_array_break_continue + +import kotlin.test.* + +@Test fun runTest() { + val intArray = intArrayOf(4, 0, 3, 5) + + val emptyArray = arrayOf() + + for (element in intArray) { + print(element) + if (element == 3) { + break + } + } + println() + for (element in emptyArray) { + print(element) + } + println() +} \ No newline at end of file diff --git a/kotlin-native/backend.native/tests/codegen/controlflow/for_loops_array_indices.kt b/kotlin-native/backend.native/tests/codegen/controlflow/for_loops_array_indices.kt new file mode 100644 index 00000000000..89d21c2892e --- /dev/null +++ b/kotlin-native/backend.native/tests/codegen/controlflow/for_loops_array_indices.kt @@ -0,0 +1,18 @@ +package codegen.controlflow.for_loops_array_indices + +import kotlin.test.* + +@Test fun runTest() { + val intArray = intArrayOf(4, 0, 3, 5) + + val emptyArray = arrayOf() + + for (index in intArray.indices) { + print(index) + } + println() + for (index in emptyArray.indices) { + print(index) + } + println() +} \ No newline at end of file diff --git a/kotlin-native/backend.native/tests/codegen/controlflow/for_loops_array_mutation.kt b/kotlin-native/backend.native/tests/codegen/controlflow/for_loops_array_mutation.kt new file mode 100644 index 00000000000..0d1c5b707e8 --- /dev/null +++ b/kotlin-native/backend.native/tests/codegen/controlflow/for_loops_array_mutation.kt @@ -0,0 +1,13 @@ +package codegen.controlflow.for_loops_array_mutation + +import kotlin.test.* + +@Test fun runTest() { + val intArray = arrayOf(4, 0, 3, 5) + + for (element in intArray) { + intArray[2] = 0 + intArray[3] = 0 + print(element) + } +} \ No newline at end of file diff --git a/kotlin-native/backend.native/tests/codegen/controlflow/for_loops_array_nested.kt b/kotlin-native/backend.native/tests/codegen/controlflow/for_loops_array_nested.kt new file mode 100644 index 00000000000..9ecf83bca48 --- /dev/null +++ b/kotlin-native/backend.native/tests/codegen/controlflow/for_loops_array_nested.kt @@ -0,0 +1,25 @@ +package codegen.controlflow.for_loops_array_nested + +import kotlin.test.* + +@Test fun arrayOfArrays() { + val metaArray = arrayOf( + arrayOf(1, 2, 3), + arrayOf("Hello"), + arrayOf(), + arrayOf(1..10) + ) + for (array in metaArray) { + inner@for (elem in array) { + if (elem is IntProgression) { + for (i in elem) { + print(i) + } + continue@inner + } else { + print(elem) + } + } + println() + } +} \ No newline at end of file diff --git a/kotlin-native/backend.native/tests/codegen/controlflow/for_loops_array_nullable.kt b/kotlin-native/backend.native/tests/codegen/controlflow/for_loops_array_nullable.kt new file mode 100644 index 00000000000..032f54bf312 --- /dev/null +++ b/kotlin-native/backend.native/tests/codegen/controlflow/for_loops_array_nullable.kt @@ -0,0 +1,16 @@ +package codegen.controlflow.for_loops_array_nullable + +import kotlin.test.* + +private fun nullableArray(a: Array): Array? { + return a +} + +@Test fun nullable() { + val array = arrayOf(1, 2, 3) + nullableArray(array)?.let { + for (elem in it) { + print(elem) + } + } +} \ No newline at end of file diff --git a/kotlin-native/backend.native/tests/codegen/controlflow/for_loops_array_side_effects.kt b/kotlin-native/backend.native/tests/codegen/controlflow/for_loops_array_side_effects.kt new file mode 100644 index 00000000000..28222f046e5 --- /dev/null +++ b/kotlin-native/backend.native/tests/codegen/controlflow/for_loops_array_side_effects.kt @@ -0,0 +1,23 @@ +package codegen.controlflow.for_loops_array_side_effects + +import kotlin.test.* + +private fun sideEffect(array: T): T { + println("side-effect") + return array +} + +@Test fun runTest() { + val intArray = intArrayOf(4, 0, 3, 5) + + val emptyArray = arrayOf() + + for (element in sideEffect(intArray)) { + print(element) + } + println() + for (element in sideEffect(emptyArray)) { + print(element) + } + println() +} \ No newline at end of file diff --git a/kotlin-native/backend.native/tests/codegen/controlflow/for_loops_call_order.kt b/kotlin-native/backend.native/tests/codegen/controlflow/for_loops_call_order.kt new file mode 100644 index 00000000000..47b1802fdac --- /dev/null +++ b/kotlin-native/backend.native/tests/codegen/controlflow/for_loops_call_order.kt @@ -0,0 +1,19 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +package codegen.controlflow.for_loops_call_order + +import kotlin.test.* + +fun f1(): Int { print("1"); return 0 } +fun f2(): Int { print("2"); return 6 } +fun f3(): Int { print("3"); return 2 } +fun f4(): Int { print("4"); return 3 } + +@Test fun runTest() { + for (i in f1()..f2() step f3() step f4()) { }; println() + for (i in f1() until f2() step f3() step f4()) {}; println() + for (i in f2() downTo f1() step f3() step f4()) {}; println() +} \ No newline at end of file diff --git a/kotlin-native/backend.native/tests/codegen/controlflow/for_loops_coroutines.kt b/kotlin-native/backend.native/tests/codegen/controlflow/for_loops_coroutines.kt new file mode 100644 index 00000000000..d05faedee5b --- /dev/null +++ b/kotlin-native/backend.native/tests/codegen/controlflow/for_loops_coroutines.kt @@ -0,0 +1,21 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +package codegen.controlflow.for_loops_coroutines + +import kotlin.test.* + +import kotlin.coroutines.* + +@Test fun runTest() { + val sq = sequence { + for (i in 0..6 step 2) { + print("before: $i ") + yield(i) + println("after: $i") + } + } + println("Got: ${sq.joinToString(separator = " ")}") +} \ No newline at end of file diff --git a/kotlin-native/backend.native/tests/codegen/controlflow/for_loops_empty_range.kt b/kotlin-native/backend.native/tests/codegen/controlflow/for_loops_empty_range.kt new file mode 100644 index 00000000000..457c0a2eaf0 --- /dev/null +++ b/kotlin-native/backend.native/tests/codegen/controlflow/for_loops_empty_range.kt @@ -0,0 +1,25 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +package codegen.controlflow.for_loops_empty_range + +import kotlin.test.* + +@Test fun runTest() { + // Simple loops + for (i in 4..0) { print(i) } + for (i in 4 until 0) { print(i) } + for (i in 0 downTo 4) { print(i) } + // Steps + for (i in 4..0 step 2) { print(i) } + for (i in 4 until 0 step 2) { print(i) } + for (i in 0 downTo 4 step 2) { print(i) } + // Two steps + for (i in 6..0 step 2 step 3) { print(i) } + for (i in 6 until 0 step 2 step 3) { print(i) } + for (i in 0 downTo 6 step 2 step 3) { print(i) } + + println("OK") +} \ No newline at end of file diff --git a/kotlin-native/backend.native/tests/codegen/controlflow/for_loops_errors.kt b/kotlin-native/backend.native/tests/codegen/controlflow/for_loops_errors.kt new file mode 100644 index 00000000000..e39fc2a2ef5 --- /dev/null +++ b/kotlin-native/backend.native/tests/codegen/controlflow/for_loops_errors.kt @@ -0,0 +1,60 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +package codegen.controlflow.for_loops_errors + +import kotlin.test.* + +@Test fun runTest() { + // Negative step. + try { + for (i in 0 .. 4 step -2) print(i); println() + throw AssertionError() + } catch (e: IllegalArgumentException) {} + + try { + for (i in 0 until 4 step -2) print(i); println() + throw AssertionError() + } catch (e: IllegalArgumentException) {} + + try { + for (i in 4 downTo 0 step -2) print(i); println() + throw AssertionError() + } catch (e: IllegalArgumentException) {} + + // Zero step. + try { + for (i in 0 .. 4 step 0) print(i); println() + throw AssertionError() + } catch (e: IllegalArgumentException) {} + + try { + for (i in 0 until 4 step 0) print(i); println() + throw AssertionError() + } catch (e: IllegalArgumentException) {} + + try { + for (i in 4 downTo 0 step 0) print(i); println() + throw AssertionError() + } catch (e: IllegalArgumentException) {} + + // Two steps, one is negative. + try { + for (i in 0 .. 4 step -2 step 3) print(i); println() + throw AssertionError() + } catch (e: IllegalArgumentException) {} + + try { + for (i in 0 until 4 step -2 step 3) print(i); println() + throw AssertionError() + } catch (e: IllegalArgumentException) {} + + try { + for (i in 4 downTo 0 step -2 step 3) print(i); println() + throw AssertionError() + } catch (e: IllegalArgumentException) {} + + println("OK") +} diff --git a/kotlin-native/backend.native/tests/codegen/controlflow/for_loops_let_with_nullable.kt b/kotlin-native/backend.native/tests/codegen/controlflow/for_loops_let_with_nullable.kt new file mode 100644 index 00000000000..26045afcd48 --- /dev/null +++ b/kotlin-native/backend.native/tests/codegen/controlflow/for_loops_let_with_nullable.kt @@ -0,0 +1,156 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +package codegen.controlflow.for_loops_let_with_nullable + +import kotlin.test.* + +// Github issue #1012 +fun testInt(left: Int?, right: Int?, step: Int?) { + right?.let { + for (i in 0..it) { print(i) } + } + println() + + left?.let { + for (i in it..5) { print(i) } + } + println() + + step?.let { + for (i in 0..5 step it) { print(i) } + } + println() + + right?.let { + for (i in 0 until it) { print(i) } + } + println() + + left?.let { + for (i in it until 5) { print(i) } + } + println() + + step?.let { + for (i in 0 until 5 step it) { print(i) } + } + println() + + right?.let { + for (i in it downTo 0) { print(i) } + } + println() + + left?.let { + for (i in 5 downTo it) { print(i) } + } + println() + + step?.let { + for (i in 5 downTo 0 step it) { print(i) } + } + println() +} + +fun testLong(left: Long?, right: Long?, step: Long?) { + right?.let { + for (i in 0..it) { print(i) } + } + println() + + left?.let { + for (i in it..5) { print(i) } + } + println() + + step?.let { + for (i in 0..5L step it) { print(i) } + } + println() + + right?.let { + for (i in 0 until it) { print(i) } + } + println() + + left?.let { + for (i in it until 5) { print(i) } + } + println() + + step?.let { + for (i in 0 until 5L step it) { print(i) } + } + println() + + right?.let { + for (i in it downTo 0) { print(i) } + } + println() + + left?.let { + for (i in 5 downTo it) { print(i) } + } + println() + + step?.let { + for (i in 5 downTo 0L step it) { print(i) } + } + println() +} + +fun testChar(left: Char?, right: Char?, step: Int?) { + right?.let { + for (i in 'a'..it) { print(i) } + } + println() + + left?.let { + for (i in it..'f') { print(i) } + } + println() + + step?.let { + for (i in 'a'..'f' step it) { print(i) } + } + println() + + right?.let { + for (i in 'a' until it) { print(i) } + } + println() + + left?.let { + for (i in it until 'f') { print(i) } + } + println() + + step?.let { + for (i in 'a' until 'f' step it) { print(i) } + } + println() + + right?.let { + for (i in it downTo 'a') { print(i) } + } + println() + + left?.let { + for (i in 'f' downTo it) { print(i) } + } + println() + + step?.let { + for (i in 'f' downTo 'a' step it) { print(i) } + } + println() +} + +@Test fun runTest() { + testInt(0, 5, 2) + testLong(0, 5, 2) + testChar('a', 'f', 2) +} \ No newline at end of file diff --git a/kotlin-native/backend.native/tests/codegen/controlflow/for_loops_nested.kt b/kotlin-native/backend.native/tests/codegen/controlflow/for_loops_nested.kt new file mode 100644 index 00000000000..1c7deacfd00 --- /dev/null +++ b/kotlin-native/backend.native/tests/codegen/controlflow/for_loops_nested.kt @@ -0,0 +1,68 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +package codegen.controlflow.for_loops_nested + +import kotlin.test.* + +@Test fun runTest() { + // Simple + for (i in 0..2) { + for (j in 0..2) { + print("$i$j ") + } + } + println() + + // Break + l1@for (i in 0..2) { + l2@for (j in 0..2) { + print("$i$j ") + if (j == 1) break + } + } + println() + + l1@for (i in 0..2) { + l2@for (j in 0..2) { + print("$i$j ") + if (j == 1) break@l2 + } + } + println() + + l1@for (i in 0..2) { + l2@for (j in 0..2) { + print("$i$j ") + if (j == 1) break@l1 + } + } + println() + + // Continue + l1@for (i in 0..2) { + l2@for (j in 0..2) { + if (j == 1) continue + print("$i$j ") + } + } + println() + + l1@for (i in 0..2) { + l2@for (j in 0..2) { + if (j == 1) continue@l2 + print("$i$j ") + } + } + println() + + l1@for (i in 0..2) { + l2@for (j in 0..2) { + if (j == 1) continue@l1 + print("$i$j ") + } + } + println() +} \ No newline at end of file diff --git a/kotlin-native/backend.native/tests/codegen/controlflow/for_loops_overflow.kt b/kotlin-native/backend.native/tests/codegen/controlflow/for_loops_overflow.kt new file mode 100644 index 00000000000..a6c89058e12 --- /dev/null +++ b/kotlin-native/backend.native/tests/codegen/controlflow/for_loops_overflow.kt @@ -0,0 +1,31 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +package codegen.controlflow.for_loops_overflow + +import kotlin.test.* + +@Test fun runTest() { + for (i in Int.MAX_VALUE - 1 .. Int.MAX_VALUE) { print(i); print(' ') }; println() + for (i in Int.MAX_VALUE - 1 until Int.MAX_VALUE) { print(i); print(' ') }; println() + for (i in Int.MIN_VALUE + 1 downTo Int.MIN_VALUE) { print(i); print(' ') }; println() + + // Empty loops + for (i in Byte.MIN_VALUE until Byte.MIN_VALUE) { print(i); print(' ') } + for (i in Short.MIN_VALUE until Short.MIN_VALUE) { print(i); print(' ') } + for (i in Int.MIN_VALUE until Int.MIN_VALUE) { print(i); print(' ') } + for (i in Long.MIN_VALUE until Long.MIN_VALUE) { print(i); print(' ') } + for (i in 0.toChar() until 0.toChar()) { print(i); print(' ') } + + for (i in 0 until Byte.MIN_VALUE) { print(i); print(' ') } + for (i in 0 until Short.MIN_VALUE) { print(i); print(' ') } + for (i in 0 until Int.MIN_VALUE) { print(i); print(' ') } + for (i in 0 until Long.MIN_VALUE) { print(i); print(' ') } + for (i in 'a' until 0.toChar()) { print(i); print(' ') } + + + val M = Int.MAX_VALUE / 2 + for (i in M + 4..M + 10 step M) { print(i); print(' ') }; println() +} \ No newline at end of file diff --git a/kotlin-native/backend.native/tests/codegen/controlflow/for_loops_types.kt b/kotlin-native/backend.native/tests/codegen/controlflow/for_loops_types.kt new file mode 100644 index 00000000000..0e7fbafe362 --- /dev/null +++ b/kotlin-native/backend.native/tests/codegen/controlflow/for_loops_types.kt @@ -0,0 +1,114 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +package codegen.controlflow.for_loops_types + +import kotlin.test.* + +@Test fun runTest() { + for (i in 0.toByte() .. 4.toByte()) print(i); println() + for (i in 0.toByte() .. 4.toShort()) print(i); println() + for (i in 0.toByte() .. 4.toInt()) print(i); println() + for (i in 0.toByte() .. 4.toLong()) print(i); println() + for (i in 0.toShort() .. 4.toByte()) print(i); println() + for (i in 0.toShort() .. 4.toShort()) print(i); println() + for (i in 0.toShort() .. 4.toInt()) print(i); println() + for (i in 0.toShort() .. 4.toLong()) print(i); println() + for (i in 0.toInt() .. 4.toByte()) print(i); println() + for (i in 0.toInt() .. 4.toShort()) print(i); println() + for (i in 0.toInt() .. 4.toInt()) print(i); println() + for (i in 0.toInt() .. 4.toLong()) print(i); println() + for (i in 0.toLong() .. 4.toByte()) print(i); println() + for (i in 0.toLong() .. 4.toShort()) print(i); println() + for (i in 0.toLong() .. 4.toInt()) print(i); println() + for (i in 0.toLong() .. 4.toLong()) print(i); println() + for (i in 0.toByte() until 4.toByte()) print(i); println() + for (i in 0.toByte() until 4.toShort()) print(i); println() + for (i in 0.toByte() until 4.toInt()) print(i); println() + for (i in 0.toByte() until 4.toLong()) print(i); println() + for (i in 0.toShort() until 4.toByte()) print(i); println() + for (i in 0.toShort() until 4.toShort()) print(i); println() + for (i in 0.toShort() until 4.toInt()) print(i); println() + for (i in 0.toShort() until 4.toLong()) print(i); println() + for (i in 0.toInt() until 4.toByte()) print(i); println() + for (i in 0.toInt() until 4.toShort()) print(i); println() + for (i in 0.toInt() until 4.toInt()) print(i); println() + for (i in 0.toInt() until 4.toLong()) print(i); println() + for (i in 0.toLong() until 4.toByte()) print(i); println() + for (i in 0.toLong() until 4.toShort()) print(i); println() + for (i in 0.toLong() until 4.toInt()) print(i); println() + for (i in 0.toLong() until 4.toLong()) print(i); println() + for (i in 4.toByte() downTo 0.toByte()) print(i); println() + for (i in 4.toByte() downTo 0.toShort()) print(i); println() + for (i in 4.toByte() downTo 0.toInt()) print(i); println() + for (i in 4.toByte() downTo 0.toLong()) print(i); println() + for (i in 4.toShort() downTo 0.toByte()) print(i); println() + for (i in 4.toShort() downTo 0.toShort()) print(i); println() + for (i in 4.toShort() downTo 0.toInt()) print(i); println() + for (i in 4.toShort() downTo 0.toLong()) print(i); println() + for (i in 4.toInt() downTo 0.toByte()) print(i); println() + for (i in 4.toInt() downTo 0.toShort()) print(i); println() + for (i in 4.toInt() downTo 0.toInt()) print(i); println() + for (i in 4.toInt() downTo 0.toLong()) print(i); println() + for (i in 4.toLong() downTo 0.toByte()) print(i); println() + for (i in 4.toLong() downTo 0.toShort()) print(i); println() + for (i in 4.toLong() downTo 0.toInt()) print(i); println() + for (i in 4.toLong() downTo 0.toLong()) print(i); println() + for (i in 'a' .. 'd') print(i); println() + for (i in 'a' until 'd') print(i); println() + for (i in 'd' downTo 'a') print(i); println() + + for (i in 0.toByte() .. 4.toByte() step 2) print(i); println() + for (i in 0.toByte() .. 4.toShort() step 2) print(i); println() + for (i in 0.toByte() .. 4.toInt() step 2) print(i); println() + for (i in 0.toByte() .. 4.toLong() step 2L) print(i); println() + for (i in 0.toShort() .. 4.toByte() step 2) print(i); println() + for (i in 0.toShort() .. 4.toShort() step 2) print(i); println() + for (i in 0.toShort() .. 4.toInt() step 2) print(i); println() + for (i in 0.toShort() .. 4.toLong() step 2L) print(i); println() + for (i in 0.toInt() .. 4.toByte() step 2) print(i); println() + for (i in 0.toInt() .. 4.toShort() step 2) print(i); println() + for (i in 0.toInt() .. 4.toInt() step 2) print(i); println() + for (i in 0.toInt() .. 4.toLong() step 2L) print(i); println() + for (i in 0.toLong() .. 4.toByte() step 2L) print(i); println() + for (i in 0.toLong() .. 4.toShort() step 2L) print(i); println() + for (i in 0.toLong() .. 4.toInt() step 2L) print(i); println() + for (i in 0.toLong() .. 4.toLong() step 2L) print(i); println() + for (i in 0.toByte() until 4.toByte() step 2) print(i); println() + for (i in 0.toByte() until 4.toShort() step 2) print(i); println() + for (i in 0.toByte() until 4.toInt() step 2) print(i); println() + for (i in 0.toByte() until 4.toLong() step 2L) print(i); println() + for (i in 0.toShort() until 4.toByte() step 2) print(i); println() + for (i in 0.toShort() until 4.toShort() step 2) print(i); println() + for (i in 0.toShort() until 4.toInt() step 2) print(i); println() + for (i in 0.toShort() until 4.toLong() step 2L) print(i); println() + for (i in 0.toInt() until 4.toByte() step 2) print(i); println() + for (i in 0.toInt() until 4.toShort() step 2) print(i); println() + for (i in 0.toInt() until 4.toInt() step 2) print(i); println() + for (i in 0.toInt() until 4.toLong() step 2L) print(i); println() + for (i in 0.toLong() until 4.toByte() step 2L) print(i); println() + for (i in 0.toLong() until 4.toShort() step 2L) print(i); println() + for (i in 0.toLong() until 4.toInt() step 2L) print(i); println() + for (i in 0.toLong() until 4.toLong() step 2L) print(i); println() + for (i in 4.toByte() downTo 0.toByte() step 2) print(i); println() + for (i in 4.toByte() downTo 0.toShort() step 2) print(i); println() + for (i in 4.toByte() downTo 0.toInt() step 2) print(i); println() + for (i in 4.toByte() downTo 0.toLong() step 2L) print(i); println() + for (i in 4.toShort() downTo 0.toByte() step 2) print(i); println() + for (i in 4.toShort() downTo 0.toShort() step 2) print(i); println() + for (i in 4.toShort() downTo 0.toInt() step 2) print(i); println() + for (i in 4.toShort() downTo 0.toLong() step 2L) print(i); println() + for (i in 4.toInt() downTo 0.toByte() step 2) print(i); println() + for (i in 4.toInt() downTo 0.toShort() step 2) print(i); println() + for (i in 4.toInt() downTo 0.toInt() step 2) print(i); println() + for (i in 4.toInt() downTo 0.toLong() step 2L) print(i); println() + for (i in 4.toLong() downTo 0.toByte() step 2L) print(i); println() + for (i in 4.toLong() downTo 0.toShort() step 2L) print(i); println() + for (i in 4.toLong() downTo 0.toInt() step 2L) print(i); println() + for (i in 4.toLong() downTo 0.toLong() step 2L) print(i); println() + for (i in 'a' .. 'd' step 2) print(i); println() + for (i in 'a' until 'd' step 2) print(i); println() + for (i in 'd' downTo 'a' step 2) print(i); println() +} \ No newline at end of file diff --git a/kotlin-native/backend.native/tests/codegen/controlflow/unreachable1.kt b/kotlin-native/backend.native/tests/codegen/controlflow/unreachable1.kt new file mode 100644 index 00000000000..05fcfa06a13 --- /dev/null +++ b/kotlin-native/backend.native/tests/codegen/controlflow/unreachable1.kt @@ -0,0 +1,17 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +package codegen.controlflow.unreachable1 + +import kotlin.test.* + +@Test fun runTest() { + println(foo()) +} + +fun foo(): Int { + return 1 + println("After return") +} \ No newline at end of file diff --git a/kotlin-native/backend.native/tests/codegen/coroutines/anonymousObject.kt b/kotlin-native/backend.native/tests/codegen/coroutines/anonymousObject.kt new file mode 100644 index 00000000000..172580524b1 --- /dev/null +++ b/kotlin-native/backend.native/tests/codegen/coroutines/anonymousObject.kt @@ -0,0 +1,50 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +package codegen.coroutines.anonymousObject + +import kotlin.test.* + +import kotlin.coroutines.* +import kotlin.coroutines.intrinsics.* + +open class EmptyContinuation(override val context: CoroutineContext = EmptyCoroutineContext) : Continuation { + companion object : EmptyContinuation() + override fun resumeWith(result: Result) { result.getOrThrow() } +} + +suspend fun suspendHere(): Int = suspendCoroutineUninterceptedOrReturn { x -> + x.resume(42) + COROUTINE_SUSPENDED +} + +fun builder(c: suspend () -> Unit) { + c.startCoroutine(EmptyContinuation) +} + +interface I { + suspend fun foo(lambda: suspend (String) -> Unit) + suspend fun bar(s: String) +} + +fun create() = object: I { + var lambda: suspend (String) -> Unit = {} + + override suspend fun foo(lambda: suspend (String) -> Unit) { + this.lambda = lambda + } + + override suspend fun bar(s: String) { + lambda(s) + } +} + +@Test fun runTest() { + builder { + val z = create() + z.foo { suspendHere(); println(it) } + z.bar("zzz") + } +} \ No newline at end of file diff --git a/kotlin-native/backend.native/tests/codegen/coroutines/controlFlow_chain.kt b/kotlin-native/backend.native/tests/codegen/coroutines/controlFlow_chain.kt new file mode 100644 index 00000000000..4b14bdf5681 --- /dev/null +++ b/kotlin-native/backend.native/tests/codegen/coroutines/controlFlow_chain.kt @@ -0,0 +1,43 @@ +/* + * Copyright 2010-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +package codegen.coroutines.controlFlow_chain + +import kotlin.test.* + +import kotlin.coroutines.* +import kotlin.coroutines.intrinsics.* + +open class EmptyContinuation(override val context: CoroutineContext = EmptyCoroutineContext) : Continuation { + companion object : EmptyContinuation() + override fun resumeWith(result: Result) { result.getOrThrow() } +} + +suspend fun suspendHere(): Int = suspendCoroutineUninterceptedOrReturn { x -> + x.resume(42) + COROUTINE_SUSPENDED +} + +fun builder(c: suspend () -> Unit) { + c.startCoroutine(EmptyContinuation) +} + +// See https://github.com/JetBrains/kotlin-native/issues/3476 +@Test fun runTest() { + var result = 0 + builder { + foo().bar() + result = 1 + } + assertEquals(1, result) +} + +class Foo { + suspend fun bar() { + suspendHere() + } +} + +suspend fun foo() = Foo() \ No newline at end of file diff --git a/kotlin-native/backend.native/tests/codegen/coroutines/controlFlow_finally1.kt b/kotlin-native/backend.native/tests/codegen/coroutines/controlFlow_finally1.kt new file mode 100644 index 00000000000..2f3e47dd8ca --- /dev/null +++ b/kotlin-native/backend.native/tests/codegen/coroutines/controlFlow_finally1.kt @@ -0,0 +1,57 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +package codegen.coroutines.controlFlow_finally1 + +import kotlin.test.* + +import kotlin.coroutines.* +import kotlin.coroutines.intrinsics.* + +open class EmptyContinuation(override val context: CoroutineContext = EmptyCoroutineContext) : Continuation { + companion object : EmptyContinuation() + override fun resumeWith(result: Result) { result.getOrThrow() } +} + +suspend fun s1(): Int = suspendCoroutineUninterceptedOrReturn { x -> + println("s1") + x.resume(42) + COROUTINE_SUSPENDED +} + +fun f1(): Int { + println("f1") + return 117 +} + +fun f2(): Int { + println("f2") + return 1 +} + +fun f3(x: Int, y: Int): Int { + println("f3") + return x + y +} + +fun builder(c: suspend () -> Unit) { + c.startCoroutine(EmptyContinuation) +} + +@Test fun runTest() { + var result = 0 + + builder { + result = try { + f1() + } catch (t: Throwable) { + f2() + } finally { + s1() + } + } + + println(result) +} \ No newline at end of file diff --git a/kotlin-native/backend.native/tests/codegen/coroutines/controlFlow_finally2.kt b/kotlin-native/backend.native/tests/codegen/coroutines/controlFlow_finally2.kt new file mode 100644 index 00000000000..3aa49853d04 --- /dev/null +++ b/kotlin-native/backend.native/tests/codegen/coroutines/controlFlow_finally2.kt @@ -0,0 +1,58 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +package codegen.coroutines.controlFlow_finally2 + +import kotlin.test.* + +import kotlin.coroutines.* +import kotlin.coroutines.intrinsics.* + +open class EmptyContinuation(override val context: CoroutineContext = EmptyCoroutineContext) : Continuation { + companion object : EmptyContinuation() + override fun resumeWith(result: Result) { result.getOrThrow() } +} + +suspend fun s1(): Int = suspendCoroutineUninterceptedOrReturn { x -> + println("s1") + x.resume(42) + COROUTINE_SUSPENDED +} + +fun f1(): Int { + println("f1") + return 117 +} + +fun f2(): Int { + println("f2") + return 1 +} + +fun f3(x: Int, y: Int): Int { + println("f3") + return x + y +} + +fun builder(c: suspend () -> Unit) { + c.startCoroutine(EmptyContinuation) +} + +@Test fun runTest() { + var result = 0 + + builder { + val x = try { + f1() + } catch (t: Throwable) { + f2() + } finally { + s1() + } + result = x + } + + println(result) +} \ No newline at end of file diff --git a/kotlin-native/backend.native/tests/codegen/coroutines/controlFlow_finally3.kt b/kotlin-native/backend.native/tests/codegen/coroutines/controlFlow_finally3.kt new file mode 100644 index 00000000000..d5104bd45b7 --- /dev/null +++ b/kotlin-native/backend.native/tests/codegen/coroutines/controlFlow_finally3.kt @@ -0,0 +1,57 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +package codegen.coroutines.controlFlow_finally3 + +import kotlin.test.* + +import kotlin.coroutines.* +import kotlin.coroutines.intrinsics.* + +open class EmptyContinuation(override val context: CoroutineContext = EmptyCoroutineContext) : Continuation { + companion object : EmptyContinuation() + override fun resumeWith(result: Result) { result.getOrThrow() } +} + +suspend fun s1(): Int = suspendCoroutineUninterceptedOrReturn { x -> + println("s1") + x.resume(42) + COROUTINE_SUSPENDED +} + +fun f1(): Int { + println("f1") + return 117 +} + +fun f2(): Int { + println("f2") + return 1 +} + +fun f3(x: Int, y: Int): Int { + println("f3") + return x + y +} + +fun builder(c: suspend () -> Unit) { + c.startCoroutine(EmptyContinuation) +} + +@Test fun runTest() { + var result = 0 + + builder { + try { + result = f1() + } catch (t: Throwable) { + result = f2() + } finally { + s1() + } + } + + println(result) +} \ No newline at end of file diff --git a/kotlin-native/backend.native/tests/codegen/coroutines/controlFlow_finally4.kt b/kotlin-native/backend.native/tests/codegen/coroutines/controlFlow_finally4.kt new file mode 100644 index 00000000000..c46d87a62d9 --- /dev/null +++ b/kotlin-native/backend.native/tests/codegen/coroutines/controlFlow_finally4.kt @@ -0,0 +1,57 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +package codegen.coroutines.controlFlow_finally4 + +import kotlin.test.* + +import kotlin.coroutines.* +import kotlin.coroutines.intrinsics.* + +open class EmptyContinuation(override val context: CoroutineContext = EmptyCoroutineContext) : Continuation { + companion object : EmptyContinuation() + override fun resumeWith(result: Result) { result.getOrThrow() } +} + +suspend fun s1(): Int = suspendCoroutineUninterceptedOrReturn { x -> + println("s1") + x.resume(42) + COROUTINE_SUSPENDED +} + +fun f1(): Int { + println("f1") + return 117 +} + +fun f2(): Int { + println("f2") + return 1 +} + +fun f3(x: Int, y: Int): Int { + println("f3") + return x + y +} + +fun builder(c: suspend () -> Unit) { + c.startCoroutine(EmptyContinuation) +} + +@Test fun runTest() { + var result = 0 + + builder { + try { + result = s1() + } catch (t: Throwable) { + result = f2() + } finally { + println("finally") + } + } + + println(result) +} \ No newline at end of file diff --git a/kotlin-native/backend.native/tests/codegen/coroutines/controlFlow_finally5.kt b/kotlin-native/backend.native/tests/codegen/coroutines/controlFlow_finally5.kt new file mode 100644 index 00000000000..3ff1aabc669 --- /dev/null +++ b/kotlin-native/backend.native/tests/codegen/coroutines/controlFlow_finally5.kt @@ -0,0 +1,57 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +package codegen.coroutines.controlFlow_finally5 + +import kotlin.test.* + +import kotlin.coroutines.* +import kotlin.coroutines.intrinsics.* + +open class EmptyContinuation(override val context: CoroutineContext = EmptyCoroutineContext) : Continuation { + companion object : EmptyContinuation() + override fun resumeWith(result: Result) { result.getOrThrow() } +} + +suspend fun s1(): Int = suspendCoroutineUninterceptedOrReturn { x -> + println("s1") + x.resumeWithException(Error()) + COROUTINE_SUSPENDED +} + +fun f1(): Int { + println("f1") + return 117 +} + +fun f2(): Int { + println("f2") + return 1 +} + +fun f3(x: Int, y: Int): Int { + println("f3") + return x + y +} + +fun builder(c: suspend () -> Unit) { + c.startCoroutine(EmptyContinuation) +} + +@Test fun runTest() { + var result = 0 + + builder { + try { + result = s1() + } catch (t: Throwable) { + result = f2() + } finally { + println("finally") + } + } + + println(result) +} \ No newline at end of file diff --git a/kotlin-native/backend.native/tests/codegen/coroutines/controlFlow_finally6.kt b/kotlin-native/backend.native/tests/codegen/coroutines/controlFlow_finally6.kt new file mode 100644 index 00000000000..98a26d33baf --- /dev/null +++ b/kotlin-native/backend.native/tests/codegen/coroutines/controlFlow_finally6.kt @@ -0,0 +1,62 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +package codegen.coroutines.controlFlow_finally6 + +import kotlin.test.* + +import kotlin.coroutines.* +import kotlin.coroutines.intrinsics.* + +open class EmptyContinuation(override val context: CoroutineContext = EmptyCoroutineContext) : Continuation { + companion object : EmptyContinuation() + override fun resumeWith(result: Result) { result.getOrThrow() } +} + +suspend fun s1(): Int = suspendCoroutineUninterceptedOrReturn { x -> + println("s1") + x.resumeWithException(Error("error")) + COROUTINE_SUSPENDED +} + +fun f1(): Int { + println("f1") + return 117 +} + +fun f2(): Int { + println("f2") + return 1 +} + +fun f3(x: Int, y: Int): Int { + println("f3") + return x + y +} + +fun builder(c: suspend () -> Unit) { + c.startCoroutine(EmptyContinuation) +} + +@Test fun runTest() { + var result = 0 + + builder { + try { + try { + result = s1() + } catch (t: ClassCastException) { + result = f2() + } finally { + println("finally") + } + } + catch(t: Error) { + println(t.message) + } + } + + println(result) +} \ No newline at end of file diff --git a/kotlin-native/backend.native/tests/codegen/coroutines/controlFlow_finally7.kt b/kotlin-native/backend.native/tests/codegen/coroutines/controlFlow_finally7.kt new file mode 100644 index 00000000000..a3fc579569e --- /dev/null +++ b/kotlin-native/backend.native/tests/codegen/coroutines/controlFlow_finally7.kt @@ -0,0 +1,68 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +package codegen.coroutines.controlFlow_finally7 + +import kotlin.test.* + +import kotlin.coroutines.* +import kotlin.coroutines.intrinsics.* + +open class EmptyContinuation(override val context: CoroutineContext = EmptyCoroutineContext) : Continuation { + companion object : EmptyContinuation() + override fun resumeWith(result: Result) { result.getOrThrow() } +} + +suspend fun s1(): Int = suspendCoroutineUninterceptedOrReturn { x -> + println("s1") + x.resumeWithException(Error()) + COROUTINE_SUSPENDED +} + +suspend fun s2(): Int = suspendCoroutineUninterceptedOrReturn { x -> + println("s2") + x.resume(42) + COROUTINE_SUSPENDED +} + +fun f1(): Int { + println("f1") + return 117 +} + +fun f2(): Int { + println("f2") + return 1 +} + +fun f3(x: Int, y: Int): Int { + println("f3") + return x + y +} + +fun builder(c: suspend () -> Unit) { + c.startCoroutine(EmptyContinuation) +} + +@Test fun runTest() { + var result = 0 + + builder { + try { + try { + result = s1() + } catch (t: Throwable) { + result = f2() + } finally { + println("finally1") + result = s2() + } + } finally { + println("finally2") + } + } + + println(result) +} \ No newline at end of file diff --git a/kotlin-native/backend.native/tests/codegen/coroutines/controlFlow_if1.kt b/kotlin-native/backend.native/tests/codegen/coroutines/controlFlow_if1.kt new file mode 100644 index 00000000000..21976de2248 --- /dev/null +++ b/kotlin-native/backend.native/tests/codegen/coroutines/controlFlow_if1.kt @@ -0,0 +1,51 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +package codegen.coroutines.controlFlow_if1 + +import kotlin.test.* + +import kotlin.coroutines.* +import kotlin.coroutines.intrinsics.* + +open class EmptyContinuation(override val context: CoroutineContext = EmptyCoroutineContext) : Continuation { + companion object : EmptyContinuation() + override fun resumeWith(result: Result) { result.getOrThrow() } +} + +suspend fun s1(): Int = suspendCoroutineUninterceptedOrReturn { x -> + println("s1") + x.resume(42) + COROUTINE_SUSPENDED +} + +fun f1(): Int { + println("f1") + return 117 +} + +fun f2(): Int { + println("f2") + return 1 +} + +fun f3(x: Int, y: Int): Int { + println("f3") + return x + y +} + +fun builder(c: suspend () -> Unit) { + c.startCoroutine(EmptyContinuation) +} + +@Test fun runTest() { + var result = 0 + + builder { + result = f3(if (f1() > 100) s1() else f2(), 42) + } + + println(result) +} \ No newline at end of file diff --git a/kotlin-native/backend.native/tests/codegen/coroutines/controlFlow_if2.kt b/kotlin-native/backend.native/tests/codegen/coroutines/controlFlow_if2.kt new file mode 100644 index 00000000000..b1b7f643037 --- /dev/null +++ b/kotlin-native/backend.native/tests/codegen/coroutines/controlFlow_if2.kt @@ -0,0 +1,54 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +package codegen.coroutines.controlFlow_if2 + +import kotlin.test.* + +import kotlin.coroutines.* +import kotlin.coroutines.intrinsics.* + +open class EmptyContinuation(override val context: CoroutineContext = EmptyCoroutineContext) : Continuation { + companion object : EmptyContinuation() + override fun resumeWith(result: Result) { result.getOrThrow() } +} + +suspend fun s1(): Int = suspendCoroutineUninterceptedOrReturn { x -> + println("s1") + x.resume(42) + COROUTINE_SUSPENDED +} + +fun f1(): Int { + println("f1") + return 117 +} + +fun f2(): Int { + println("f2") + return 1 +} + +fun f3(x: Int, y: Int): Int { + println("f3") + return x + y +} + +fun builder(c: suspend () -> Unit) { + c.startCoroutine(EmptyContinuation) +} + +@Test fun runTest() { + var result = 0 + + builder { + if (f1() > 100) + result = s1() + f2() + else + result = 42 + } + + println(result) +} \ No newline at end of file diff --git a/kotlin-native/backend.native/tests/codegen/coroutines/controlFlow_inline1.kt b/kotlin-native/backend.native/tests/codegen/coroutines/controlFlow_inline1.kt new file mode 100644 index 00000000000..5703c9c7e7d --- /dev/null +++ b/kotlin-native/backend.native/tests/codegen/coroutines/controlFlow_inline1.kt @@ -0,0 +1,40 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +package codegen.coroutines.controlFlow_inline1 + +import kotlin.test.* + +import kotlin.coroutines.* +import kotlin.coroutines.intrinsics.* + +open class EmptyContinuation(override val context: CoroutineContext = EmptyCoroutineContext) : Continuation { + companion object : EmptyContinuation() + override fun resumeWith(result: Result) { result.getOrThrow() } +} + +suspend fun s1(): Int = suspendCoroutineUninterceptedOrReturn { x -> + println("s1") + x.resume(42) + COROUTINE_SUSPENDED +} + +fun builder(c: suspend () -> Unit) { + c.startCoroutine(EmptyContinuation) +} + +inline suspend fun inline_s2(): Int { + return 42 +} + +@Test fun runTest() { + var result = 0 + + builder { + result = inline_s2() + } + + println(result) +} \ No newline at end of file diff --git a/kotlin-native/backend.native/tests/codegen/coroutines/controlFlow_inline2.kt b/kotlin-native/backend.native/tests/codegen/coroutines/controlFlow_inline2.kt new file mode 100644 index 00000000000..8d99a8acc81 --- /dev/null +++ b/kotlin-native/backend.native/tests/codegen/coroutines/controlFlow_inline2.kt @@ -0,0 +1,41 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +package codegen.coroutines.controlFlow_inline2 + +import kotlin.test.* + +import kotlin.coroutines.* +import kotlin.coroutines.intrinsics.* + +open class EmptyContinuation(override val context: CoroutineContext = EmptyCoroutineContext) : Continuation { + companion object : EmptyContinuation() + override fun resumeWith(result: Result) { result.getOrThrow() } +} + +suspend fun s1(): Int = suspendCoroutineUninterceptedOrReturn { x -> + println("s1") + x.resume(42) + COROUTINE_SUSPENDED +} + +fun builder(c: suspend () -> Unit) { + c.startCoroutine(EmptyContinuation) +} + +inline suspend fun inline_s2(): Int { + var x = s1() + return x +} + +@Test fun runTest() { + var result = 0 + + builder { + result = inline_s2() + } + + println(result) +} diff --git a/kotlin-native/backend.native/tests/codegen/coroutines/controlFlow_inline3.kt b/kotlin-native/backend.native/tests/codegen/coroutines/controlFlow_inline3.kt new file mode 100644 index 00000000000..69f59f9b50e --- /dev/null +++ b/kotlin-native/backend.native/tests/codegen/coroutines/controlFlow_inline3.kt @@ -0,0 +1,54 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +package codegen.coroutines.controlFlow_inline3 + +import kotlin.test.* + +import kotlin.coroutines.* +import kotlin.coroutines.intrinsics.* + +open class EmptyContinuation(override val context: CoroutineContext = EmptyCoroutineContext) : Continuation { + companion object : EmptyContinuation() + override fun resumeWith(result: Result) { result.getOrThrow() } +} + +suspend fun s1(): Int = suspendCoroutineUninterceptedOrReturn { x -> + println("s1") + x.resume(42) + COROUTINE_SUSPENDED +} + +fun builder(c: suspend () -> Unit) { + c.startCoroutine(EmptyContinuation) +} + +fun f1(): Int { + println("f1") + return 117 +} + +fun f2(): Int { + println("f2") + return 1 +} + +inline suspend fun inline_s2(): Int { + var x = 0 + if (f1() > 0) + x = s1() + else x = f2() + return x +} + +@Test fun runTest() { + var result = 0 + + builder { + result = inline_s2() + } + + println(result) +} diff --git a/kotlin-native/backend.native/tests/codegen/coroutines/controlFlow_tryCatch1.kt b/kotlin-native/backend.native/tests/codegen/coroutines/controlFlow_tryCatch1.kt new file mode 100644 index 00000000000..685b48a78b8 --- /dev/null +++ b/kotlin-native/backend.native/tests/codegen/coroutines/controlFlow_tryCatch1.kt @@ -0,0 +1,56 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +package codegen.coroutines.controlFlow_tryCatch1 + +import kotlin.test.* + +import kotlin.coroutines.* +import kotlin.coroutines.intrinsics.* + +open class EmptyContinuation(override val context: CoroutineContext = EmptyCoroutineContext) : Continuation { + companion object : EmptyContinuation() + override fun resumeWith(result: Result) { result.getOrThrow() } +} + +suspend fun s1(): Int = suspendCoroutineUninterceptedOrReturn { x -> + println("s1") + x.resume(42) + COROUTINE_SUSPENDED +} + +fun f1(): Int { + println("f1") + return 117 +} + +fun f2(): Int { + println("f2") + return 1 +} + +fun f3(x: Int, y: Int): Int { + println("f3") + return x + y +} + +fun builder(c: suspend () -> Unit) { + c.startCoroutine(EmptyContinuation) +} + +@Test fun runTest() { + var result = 0 + + builder { + val x = try { + s1() + } catch (t: Throwable) { + f2() + } + result = x + } + + println(result) +} \ No newline at end of file diff --git a/kotlin-native/backend.native/tests/codegen/coroutines/controlFlow_tryCatch2.kt b/kotlin-native/backend.native/tests/codegen/coroutines/controlFlow_tryCatch2.kt new file mode 100644 index 00000000000..2f0c4bf13a4 --- /dev/null +++ b/kotlin-native/backend.native/tests/codegen/coroutines/controlFlow_tryCatch2.kt @@ -0,0 +1,55 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +package codegen.coroutines.controlFlow_tryCatch2 + +import kotlin.test.* + +import kotlin.coroutines.* +import kotlin.coroutines.intrinsics.* + +open class EmptyContinuation(override val context: CoroutineContext = EmptyCoroutineContext) : Continuation { + companion object : EmptyContinuation() + override fun resumeWith(result: Result) { result.getOrThrow() } +} + +suspend fun s1(): Int = suspendCoroutineUninterceptedOrReturn { x -> + println("s1") + x.resume(42) + COROUTINE_SUSPENDED +} + +fun f1(): Int { + println("f1") + return 117 +} + +fun f2(): Int { + println("f2") + return 1 +} + +fun f3(x: Int, y: Int): Int { + println("f3") + return x + y +} + +fun builder(c: suspend () -> Unit) { + c.startCoroutine(EmptyContinuation) +} + +@Test fun runTest() { + var result = 0 + + builder { + result = try { + s1() + } catch (t: Throwable) { + f2() + } + } + + println(result) +} \ No newline at end of file diff --git a/kotlin-native/backend.native/tests/codegen/coroutines/controlFlow_tryCatch3.kt b/kotlin-native/backend.native/tests/codegen/coroutines/controlFlow_tryCatch3.kt new file mode 100644 index 00000000000..371ed5fd866 --- /dev/null +++ b/kotlin-native/backend.native/tests/codegen/coroutines/controlFlow_tryCatch3.kt @@ -0,0 +1,61 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +package codegen.coroutines.controlFlow_tryCatch3 + +import kotlin.test.* + +import kotlin.coroutines.* +import kotlin.coroutines.intrinsics.* + +open class EmptyContinuation(override val context: CoroutineContext = EmptyCoroutineContext) : Continuation { + companion object : EmptyContinuation() + override fun resumeWith(result: Result) { result.getOrThrow() } +} + +suspend fun s1(): Int = suspendCoroutineUninterceptedOrReturn { x -> + println("s1") + x.resume(42) + COROUTINE_SUSPENDED +} + +suspend fun s2(): Int = suspendCoroutineUninterceptedOrReturn { x -> + println("s2") + x.resumeWithException(Error()) + COROUTINE_SUSPENDED +} + +fun f1(): Int { + println("f1") + return 117 +} + +fun f2(): Int { + println("f2") + return 1 +} + +fun f3(x: Int, y: Int): Int { + println("f3") + return x + y +} + +fun builder(c: suspend () -> Unit) { + c.startCoroutine(EmptyContinuation) +} + +@Test fun runTest() { + var result = 0 + + builder { + result = try { + s2() + } catch (t: Throwable) { + f2() + } + } + + println(result) +} \ No newline at end of file diff --git a/kotlin-native/backend.native/tests/codegen/coroutines/controlFlow_tryCatch4.kt b/kotlin-native/backend.native/tests/codegen/coroutines/controlFlow_tryCatch4.kt new file mode 100644 index 00000000000..919bbd29c90 --- /dev/null +++ b/kotlin-native/backend.native/tests/codegen/coroutines/controlFlow_tryCatch4.kt @@ -0,0 +1,62 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +package codegen.coroutines.controlFlow_tryCatch4 + +import kotlin.test.* + +import kotlin.coroutines.* +import kotlin.coroutines.intrinsics.* + +open class EmptyContinuation(override val context: CoroutineContext = EmptyCoroutineContext) : Continuation { + companion object : EmptyContinuation() + override fun resumeWith(result: Result) { result.getOrThrow() } +} + +suspend fun s1(): Int = suspendCoroutineUninterceptedOrReturn { x -> + println("s1") + x.resume(42) + COROUTINE_SUSPENDED +} + +suspend fun s2(): Int = suspendCoroutineUninterceptedOrReturn { x -> + println("s2") + x.resumeWithException(Error()) + COROUTINE_SUSPENDED +} + +fun f1(): Int { + println("f1") + return 117 +} + +fun f2(): Int { + println("f2") + return 1 +} + +fun f3(x: Int, y: Int): Int { + println("f3") + return x + y +} + +fun builder(c: suspend () -> Unit) { + c.startCoroutine(EmptyContinuation) +} + +@Test fun runTest() { + var result = 0 + + builder { + val x = try { + s2() + } catch (t: Throwable) { + f2() + } + result = x + } + + println(result) +} \ No newline at end of file diff --git a/kotlin-native/backend.native/tests/codegen/coroutines/controlFlow_tryCatch5.kt b/kotlin-native/backend.native/tests/codegen/coroutines/controlFlow_tryCatch5.kt new file mode 100644 index 00000000000..458a371c863 --- /dev/null +++ b/kotlin-native/backend.native/tests/codegen/coroutines/controlFlow_tryCatch5.kt @@ -0,0 +1,63 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +package codegen.coroutines.controlFlow_tryCatch5 + +import kotlin.test.* + +import kotlin.coroutines.* +import kotlin.coroutines.intrinsics.* + +open class EmptyContinuation(override val context: CoroutineContext = EmptyCoroutineContext) : Continuation { + companion object : EmptyContinuation() + override fun resumeWith(result: Result) { result.getOrThrow() } +} + +suspend fun s1(): Int = suspendCoroutineUninterceptedOrReturn { x -> + println("s1") + x.resume(42) + COROUTINE_SUSPENDED +} + +suspend fun s2(): Int = suspendCoroutineUninterceptedOrReturn { x -> + println("s2") + x.resumeWithException(Error("Error")) + COROUTINE_SUSPENDED +} + +fun f1(): Int { + println("f1") + return 117 +} + +fun f2(): Int { + println("f2") + return 1 +} + +fun f3(x: Int, y: Int): Int { + println("f3") + return x + y +} + +fun builder(c: suspend () -> Unit) { + c.startCoroutine(EmptyContinuation) +} + +@Test fun runTest() { + var result = 0 + + builder { + result = try { + s2() + } catch (t: Throwable) { + val x = s1() + println(t.message) + x + } + } + + println(result) +} \ No newline at end of file diff --git a/kotlin-native/backend.native/tests/codegen/coroutines/controlFlow_while1.kt b/kotlin-native/backend.native/tests/codegen/coroutines/controlFlow_while1.kt new file mode 100644 index 00000000000..b7946119f44 --- /dev/null +++ b/kotlin-native/backend.native/tests/codegen/coroutines/controlFlow_while1.kt @@ -0,0 +1,64 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +package codegen.coroutines.controlFlow_while1 + +import kotlin.test.* + +import kotlin.coroutines.* +import kotlin.coroutines.intrinsics.* + +open class EmptyContinuation(override val context: CoroutineContext = EmptyCoroutineContext) : Continuation { + companion object : EmptyContinuation() + override fun resumeWith(result: Result) { result.getOrThrow() } +} + +suspend fun s1(): Int = suspendCoroutineUninterceptedOrReturn { x -> + println("s1") + x.resume(42) + COROUTINE_SUSPENDED +} + +suspend fun s2(): Int = suspendCoroutineUninterceptedOrReturn { x -> + println("s2") + x.resumeWithException(Error("Error")) + COROUTINE_SUSPENDED +} + +suspend fun s3(value: Int): Int = suspendCoroutineUninterceptedOrReturn { x -> + println("s3") + x.resume(value) + COROUTINE_SUSPENDED +} + +fun f1(): Int { + println("f1") + return 117 +} + +fun f2(): Int { + println("f2") + return 1 +} + +fun f3(x: Int, y: Int): Int { + println("f3") + return x + y +} + +fun builder(c: suspend () -> Unit) { + c.startCoroutine(EmptyContinuation) +} + +@Test fun runTest() { + var result = 0 + + builder { + while (s3(result) < 3) + ++result + } + + println(result) +} \ No newline at end of file diff --git a/kotlin-native/backend.native/tests/codegen/coroutines/controlFlow_while2.kt b/kotlin-native/backend.native/tests/codegen/coroutines/controlFlow_while2.kt new file mode 100644 index 00000000000..c2f7880fab1 --- /dev/null +++ b/kotlin-native/backend.native/tests/codegen/coroutines/controlFlow_while2.kt @@ -0,0 +1,64 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +package codegen.coroutines.controlFlow_while2 + +import kotlin.test.* + +import kotlin.coroutines.* +import kotlin.coroutines.intrinsics.* + +open class EmptyContinuation(override val context: CoroutineContext = EmptyCoroutineContext) : Continuation { + companion object : EmptyContinuation() + override fun resumeWith(result: Result) { result.getOrThrow() } +} + +suspend fun s1(): Int = suspendCoroutineUninterceptedOrReturn { x -> + println("s1") + x.resume(42) + COROUTINE_SUSPENDED +} + +suspend fun s2(): Int = suspendCoroutineUninterceptedOrReturn { x -> + println("s2") + x.resumeWithException(Error("Error")) + COROUTINE_SUSPENDED +} + +suspend fun s3(value: Int): Int = suspendCoroutineUninterceptedOrReturn { x -> + println("s3") + x.resume(value) + COROUTINE_SUSPENDED +} + +fun f1(): Int { + println("f1") + return 117 +} + +fun f2(): Int { + println("f2") + return 1 +} + +fun f3(x: Int, y: Int): Int { + println("f3") + return x + y +} + +fun builder(c: suspend () -> Unit) { + c.startCoroutine(EmptyContinuation) +} + +@Test fun runTest() { + var result = 0 + + builder { + while (result < 3) + result = s3(result) + 1 + } + + println(result) +} \ No newline at end of file diff --git a/kotlin-native/backend.native/tests/codegen/coroutines/coroutineContext1.kt b/kotlin-native/backend.native/tests/codegen/coroutines/coroutineContext1.kt new file mode 100644 index 00000000000..2bc57a602d6 --- /dev/null +++ b/kotlin-native/backend.native/tests/codegen/coroutines/coroutineContext1.kt @@ -0,0 +1,24 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +package codegen.coroutines.coroutineContext1 + +import kotlin.test.* + +import kotlin.coroutines.* +import kotlin.coroutines.intrinsics.* + +open class EmptyContinuation(override val context: CoroutineContext = EmptyCoroutineContext) : Continuation { + companion object : EmptyContinuation() + override fun resumeWith(result: Result) { result.getOrThrow() } +} + +fun builder(c: suspend () -> Unit) { + c.startCoroutine(EmptyContinuation) +} + +@Test fun runTest() { + builder { println(coroutineContext) } +} \ No newline at end of file diff --git a/kotlin-native/backend.native/tests/codegen/coroutines/coroutineContext2.kt b/kotlin-native/backend.native/tests/codegen/coroutines/coroutineContext2.kt new file mode 100644 index 00000000000..1d96d8d6797 --- /dev/null +++ b/kotlin-native/backend.native/tests/codegen/coroutines/coroutineContext2.kt @@ -0,0 +1,26 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +package codegen.coroutines.coroutineContext2 + +import kotlin.test.* + +import kotlin.coroutines.* +import kotlin.coroutines.intrinsics.* + +open class EmptyContinuation(override val context: CoroutineContext = EmptyCoroutineContext) : Continuation { + companion object : EmptyContinuation() + override fun resumeWith(result: Result) { result.getOrThrow() } +} + +fun builder(c: suspend () -> Unit) { + c.startCoroutine(EmptyContinuation) +} + +suspend fun foo() = coroutineContext + +@Test fun runTest() { + builder { println(foo()) } +} \ No newline at end of file diff --git a/kotlin-native/backend.native/tests/codegen/coroutines/correctOrder1.kt b/kotlin-native/backend.native/tests/codegen/coroutines/correctOrder1.kt new file mode 100644 index 00000000000..6be6b1d2846 --- /dev/null +++ b/kotlin-native/backend.native/tests/codegen/coroutines/correctOrder1.kt @@ -0,0 +1,46 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +package codegen.coroutines.correctOrder1 + +import kotlin.test.* + +import kotlin.coroutines.* +import kotlin.coroutines.intrinsics.* + +open class EmptyContinuation(override val context: CoroutineContext = EmptyCoroutineContext) : Continuation { + companion object : EmptyContinuation() + override fun resumeWith(result: Result) { result.getOrThrow() } +} + +suspend fun s1(): Int = suspendCoroutineUninterceptedOrReturn { x -> + println("s1") + x.resume(42) + COROUTINE_SUSPENDED +} + +fun f1(): Int { + println("f1") + return 117 +} + +fun f2(): Int { + println("f2") + return 1 +} + +fun builder(c: suspend () -> Unit) { + c.startCoroutine(EmptyContinuation) +} + +@Test fun runTest() { + var result = 0 + + builder { + result = f1() + s1() + f2() + } + + println(result) +} \ No newline at end of file diff --git a/kotlin-native/backend.native/tests/codegen/coroutines/degenerate1.kt b/kotlin-native/backend.native/tests/codegen/coroutines/degenerate1.kt new file mode 100644 index 00000000000..d73de5a7213 --- /dev/null +++ b/kotlin-native/backend.native/tests/codegen/coroutines/degenerate1.kt @@ -0,0 +1,30 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +package codegen.coroutines.degenerate1 + +import kotlin.test.* + +import kotlin.coroutines.* +import kotlin.coroutines.intrinsics.* + +open class EmptyContinuation(override val context: CoroutineContext = EmptyCoroutineContext) : Continuation { + companion object : EmptyContinuation() + override fun resumeWith(result: Result) { result.getOrThrow() } +} + +suspend fun s1() { + println("s1") +} + +fun builder(c: suspend () -> Unit) { + c.startCoroutine(EmptyContinuation) +} + +@Test fun runTest() { + builder { + s1() + } +} \ No newline at end of file diff --git a/kotlin-native/backend.native/tests/codegen/coroutines/degenerate2.kt b/kotlin-native/backend.native/tests/codegen/coroutines/degenerate2.kt new file mode 100644 index 00000000000..4281162b780 --- /dev/null +++ b/kotlin-native/backend.native/tests/codegen/coroutines/degenerate2.kt @@ -0,0 +1,37 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +package codegen.coroutines.degenerate2 + +import kotlin.test.* + +import kotlin.coroutines.* +import kotlin.coroutines.intrinsics.* + +open class EmptyContinuation(override val context: CoroutineContext = EmptyCoroutineContext) : Continuation { + companion object : EmptyContinuation() + override fun resumeWith(result: Result) { result.getOrThrow() } +} + +suspend fun s1(): Unit = suspendCoroutineUninterceptedOrReturn { x -> + println("s1") + x.resume(Unit) + COROUTINE_SUSPENDED +} + +suspend fun s2() { + println("s2") + s1() +} + +fun builder(c: suspend () -> Unit) { + c.startCoroutine(EmptyContinuation) +} + +@Test fun runTest() { + builder { + s2() + } +} \ No newline at end of file diff --git a/kotlin-native/backend.native/tests/codegen/coroutines/functionReference_eqeq_name.kt b/kotlin-native/backend.native/tests/codegen/coroutines/functionReference_eqeq_name.kt new file mode 100644 index 00000000000..600284984de --- /dev/null +++ b/kotlin-native/backend.native/tests/codegen/coroutines/functionReference_eqeq_name.kt @@ -0,0 +1,32 @@ +/* + * Copyright 2010-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +package codegen.coroutines.functionReference_eqeq_name + +import kotlin.test.* + +suspend fun foo(x: Int) = x + +class Foo(val x: Int) { + suspend fun bar() = x +} + +@Test fun runTest() { + val ref1 = ::foo + val rec = Foo(42) + val ref2 = rec::bar + val ref3 = ::foo + val ref4 = Foo(42)::bar + val ref5 = rec::bar + val ref6 = Foo::bar + assertEquals("foo", ref1.name) + assertEquals("bar", ref2.name) + assertEquals("bar", ref6.name) + assertFalse(ref1 == ref2) + assertTrue(ref1 == ref3) + assertFalse(ref2 == ref4) + assertTrue(ref2 == ref5) + assertFalse(ref6 == ref2) +} diff --git a/kotlin-native/backend.native/tests/codegen/coroutines/functionReference_invokeAsFunction.kt b/kotlin-native/backend.native/tests/codegen/coroutines/functionReference_invokeAsFunction.kt new file mode 100644 index 00000000000..0d64ac94c97 --- /dev/null +++ b/kotlin-native/backend.native/tests/codegen/coroutines/functionReference_invokeAsFunction.kt @@ -0,0 +1,28 @@ +/* + * Copyright 2010-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +package codegen.coroutines.functionReference_invokeAsFunction + +import kotlin.test.* + +import kotlin.coroutines.* +import kotlin.coroutines.intrinsics.* + +open class EmptyContinuation(override val context: CoroutineContext = EmptyCoroutineContext) : Continuation { + companion object : EmptyContinuation() + override fun resumeWith(result: Result) { result.getOrThrow() } +} + +class Foo(val x: Int) { + suspend fun bar(y: Int) = foo(y) + x +} + +suspend fun foo(x: Int) = x + +@Test fun runTest() { + val ref = Foo(42)::bar + + println((ref as Function2, Any?>)(117, EmptyContinuation)) +} diff --git a/kotlin-native/backend.native/tests/codegen/coroutines/functionReference_lambdaAsSuspendLambda.kt b/kotlin-native/backend.native/tests/codegen/coroutines/functionReference_lambdaAsSuspendLambda.kt new file mode 100644 index 00000000000..df9eb23b52a --- /dev/null +++ b/kotlin-native/backend.native/tests/codegen/coroutines/functionReference_lambdaAsSuspendLambda.kt @@ -0,0 +1,19 @@ +/* + * Copyright 2010-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +package codegen.coroutines.functionReference_lambdaAsSuspendLambda + +import kotlin.test.* + +import kotlin.coroutines.* +import kotlin.coroutines.intrinsics.* + +fun foo(block: (Continuation) -> Any?) { + block as (suspend () -> Unit) +} + +@Test fun runTest() { + foo {} +} \ No newline at end of file diff --git a/kotlin-native/backend.native/tests/codegen/coroutines/functionReference_simple.kt b/kotlin-native/backend.native/tests/codegen/coroutines/functionReference_simple.kt new file mode 100644 index 00000000000..d574dc9d373 --- /dev/null +++ b/kotlin-native/backend.native/tests/codegen/coroutines/functionReference_simple.kt @@ -0,0 +1,39 @@ +/* + * Copyright 2010-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +package codegen.coroutines.functionReference_simple + +import kotlin.test.* + +import kotlin.coroutines.* +import kotlin.coroutines.intrinsics.* + +open class EmptyContinuation(override val context: CoroutineContext = EmptyCoroutineContext) : Continuation { + companion object : EmptyContinuation() + override fun resumeWith(result: Result) { result.getOrThrow() } +} + +suspend fun suspendHere(): Int = suspendCoroutineUninterceptedOrReturn { x -> + x.resume(42) + COROUTINE_SUSPENDED +} + +suspend fun foo(x: suspend () -> Int) = x() + +fun builder(c: suspend () -> Unit) { + c.startCoroutine(EmptyContinuation) +} + +@Test fun runTest() { + var result = 0 + + val ref = ::suspendHere + + builder { + result = foo(ref) + } + + println(result) +} diff --git a/kotlin-native/backend.native/tests/codegen/coroutines/kt41394.kt b/kotlin-native/backend.native/tests/codegen/coroutines/kt41394.kt new file mode 100644 index 00000000000..60908e9009c --- /dev/null +++ b/kotlin-native/backend.native/tests/codegen/coroutines/kt41394.kt @@ -0,0 +1,40 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +package codegen.coroutines.kt41394 + +import kotlin.test.* + +import kotlin.coroutines.* +import kotlin.coroutines.intrinsics.* + +open class EmptyContinuation(override val context: CoroutineContext = EmptyCoroutineContext) : Continuation { + companion object : EmptyContinuation() + override fun resumeWith(result: Result) { result.getOrThrow() } +} + +suspend fun suspendHere(): Int = suspendCoroutineUninterceptedOrReturn { x -> + x.resume(42) + COROUTINE_SUSPENDED +} + +suspend fun foo(label: String): String { + val x = suspendHere() + return label + x.toString() +} + +fun builder(c: suspend () -> Unit) { + c.startCoroutine(EmptyContinuation) +} + +@Test fun runTest() { + var result = "" + + builder { + result = foo("zzz") + } + + assertEquals("zzz42", result) +} \ No newline at end of file diff --git a/kotlin-native/backend.native/tests/codegen/coroutines/returnsNothing1.kt b/kotlin-native/backend.native/tests/codegen/coroutines/returnsNothing1.kt new file mode 100644 index 00000000000..7f74e03b535 --- /dev/null +++ b/kotlin-native/backend.native/tests/codegen/coroutines/returnsNothing1.kt @@ -0,0 +1,40 @@ +/* + * Copyright 2010-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +package codegen.coroutines.returnsNothing1 + +import kotlin.test.* + +import kotlin.coroutines.* +import kotlin.coroutines.intrinsics.* + +open class EmptyContinuation(override val context: CoroutineContext = EmptyCoroutineContext) : Continuation { + companion object : EmptyContinuation() + override fun resumeWith(result: Result) { result.getOrThrow() } +} + +suspend fun suspendForever(): Int = suspendCoroutineUninterceptedOrReturn { + COROUTINE_SUSPENDED +} + +suspend fun foo(): Nothing { + suspendForever() + throw Error() +} + +suspend fun bar() { + foo() +} + +fun builder(c: suspend () -> Unit) { + c.startCoroutine(EmptyContinuation) +} + +@Test fun runTest() { + builder { + bar() + } + println("OK") +} \ No newline at end of file diff --git a/kotlin-native/backend.native/tests/codegen/coroutines/returnsUnit1.kt b/kotlin-native/backend.native/tests/codegen/coroutines/returnsUnit1.kt new file mode 100644 index 00000000000..0a3fa3b8964 --- /dev/null +++ b/kotlin-native/backend.native/tests/codegen/coroutines/returnsUnit1.kt @@ -0,0 +1,45 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +package codegen.coroutines.returnsUnit1 + +import kotlin.test.* + +import kotlin.coroutines.* +import kotlin.coroutines.intrinsics.* + +open class EmptyContinuation(override val context: CoroutineContext = EmptyCoroutineContext) : Continuation { + companion object : EmptyContinuation() + override fun resumeWith(result: Result) { result.getOrThrow() } +} + +suspend fun s1(): Unit = suspendCoroutineUninterceptedOrReturn { x -> + println("s1") + x.resume(Unit) + COROUTINE_SUSPENDED +} + +fun builder(c: suspend () -> Unit) { + c.startCoroutine(EmptyContinuation) +} + +inline suspend fun inline_s2(x: Int): Unit { + println(x) + s1() +} + +suspend fun s3(x: Int) { + inline_s2(x) +} + +@Test fun runTest() { + var result = 0 + + builder { + s3(117) + } + + println(result) +} \ No newline at end of file diff --git a/kotlin-native/backend.native/tests/codegen/coroutines/simple.kt b/kotlin-native/backend.native/tests/codegen/coroutines/simple.kt new file mode 100644 index 00000000000..ff90298307e --- /dev/null +++ b/kotlin-native/backend.native/tests/codegen/coroutines/simple.kt @@ -0,0 +1,35 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +package codegen.coroutines.simple + +import kotlin.test.* + +import kotlin.coroutines.* +import kotlin.coroutines.intrinsics.* + +open class EmptyContinuation(override val context: CoroutineContext = EmptyCoroutineContext) : Continuation { + companion object : EmptyContinuation() + override fun resumeWith(result: Result) { result.getOrThrow() } +} + +suspend fun suspendHere(): Int = suspendCoroutineUninterceptedOrReturn { x -> + x.resume(42) + COROUTINE_SUSPENDED +} + +fun builder(c: suspend () -> Unit) { + c.startCoroutine(EmptyContinuation) +} + +@Test fun runTest() { + var result = 0 + + builder { + result = suspendHere() + } + + println(result) +} \ No newline at end of file diff --git a/kotlin-native/backend.native/tests/codegen/coroutines/suspendConversion.kt b/kotlin-native/backend.native/tests/codegen/coroutines/suspendConversion.kt new file mode 100644 index 00000000000..12c66352e7e --- /dev/null +++ b/kotlin-native/backend.native/tests/codegen/coroutines/suspendConversion.kt @@ -0,0 +1,27 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +import kotlin.test.* + +import kotlin.coroutines.* +import kotlin.coroutines.intrinsics.* + +open class EmptyContinuation(override val context: CoroutineContext = EmptyCoroutineContext) : Continuation { + companion object : EmptyContinuation() + override fun resumeWith(result: Result) { result.getOrThrow() } +} + +fun builder(c: suspend () -> Unit) { + c.startCoroutine(EmptyContinuation) +} + +fun main() { + var result = 0 + + val f: () -> Unit = { result = 42 } + builder(f) + + assertEquals(42, result) +} \ No newline at end of file diff --git a/kotlin-native/backend.native/tests/codegen/coroutines/withReceiver.kt b/kotlin-native/backend.native/tests/codegen/coroutines/withReceiver.kt new file mode 100644 index 00000000000..cf841061a25 --- /dev/null +++ b/kotlin-native/backend.native/tests/codegen/coroutines/withReceiver.kt @@ -0,0 +1,37 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +package codegen.coroutines.withReceiver + +import kotlin.test.* + +import kotlin.coroutines.* +import kotlin.coroutines.intrinsics.* + +open class EmptyContinuation(override val context: CoroutineContext = EmptyCoroutineContext) : Continuation { + companion object : EmptyContinuation() + override fun resumeWith(result: Result) { result.getOrThrow() } +} + +class Controller { + suspend fun suspendHere(): Int = suspendCoroutineUninterceptedOrReturn { x -> + x.resume(42) + COROUTINE_SUSPENDED + } +} + +fun builder(c: suspend Controller.() -> Unit) { + c.startCoroutine(Controller(), EmptyContinuation) +} + +@Test fun runTest() { + var result = 0 + + builder { + result = suspendHere() + } + + println(result) +} \ No newline at end of file diff --git a/kotlin-native/backend.native/tests/codegen/cycles/cycle.kt b/kotlin-native/backend.native/tests/codegen/cycles/cycle.kt new file mode 100644 index 00000000000..1c4d68e3bd7 --- /dev/null +++ b/kotlin-native/backend.native/tests/codegen/cycles/cycle.kt @@ -0,0 +1,21 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +package codegen.cycles.cycle + +import kotlin.test.* + +fun cycle(cnt: Int): Int { + var sum = 1 + while (sum == cnt) { + sum = sum + 1 + } + return sum +} + +@Test fun runTest() { + if (cycle(1) != 2) throw Error() + if (cycle(0) != 1) throw Error() +} diff --git a/kotlin-native/backend.native/tests/codegen/cycles/cycle_do.kt b/kotlin-native/backend.native/tests/codegen/cycles/cycle_do.kt new file mode 100644 index 00000000000..59094cb94a0 --- /dev/null +++ b/kotlin-native/backend.native/tests/codegen/cycles/cycle_do.kt @@ -0,0 +1,21 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +package codegen.cycles.cycle_do + +import kotlin.test.* + +fun cycle_do(cnt: Int): Int { + var sum = 1 + do { + sum = sum + 2 + } while (sum == cnt) + return sum +} + +@Test fun runTest() { + if (cycle_do(3) != 5) throw Error() + if (cycle_do(0) != 3) throw Error() +} \ No newline at end of file diff --git a/kotlin-native/backend.native/tests/codegen/cycles/cycle_for.kt b/kotlin-native/backend.native/tests/codegen/cycles/cycle_for.kt new file mode 100644 index 00000000000..493ae570b38 --- /dev/null +++ b/kotlin-native/backend.native/tests/codegen/cycles/cycle_for.kt @@ -0,0 +1,20 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +package codegen.cycles.cycle_for + +import kotlin.test.* + +fun cycle_for(arr: Array) : Int { + var sum = 0 + for (i in arr) { + sum += i + } + return sum +} + +@Test fun runTest() { + if (cycle_for(Array(4, init = { it })) != 6) throw Error() +} \ No newline at end of file diff --git a/kotlin-native/backend.native/tests/codegen/dataflow/scope1.kt b/kotlin-native/backend.native/tests/codegen/dataflow/scope1.kt new file mode 100644 index 00000000000..9191d2354e7 --- /dev/null +++ b/kotlin-native/backend.native/tests/codegen/dataflow/scope1.kt @@ -0,0 +1,18 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +package codegen.dataflow.scope1 + +import kotlin.test.* + +var b = true + +@Test fun runTest() { + var x = 1 + if (b) { + var x = 2 + } + println(x) +} diff --git a/kotlin-native/backend.native/tests/codegen/dataflow/uninitialized_val.kt b/kotlin-native/backend.native/tests/codegen/dataflow/uninitialized_val.kt new file mode 100644 index 00000000000..579111abc59 --- /dev/null +++ b/kotlin-native/backend.native/tests/codegen/dataflow/uninitialized_val.kt @@ -0,0 +1,26 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +package codegen.dataflow.uninitialized_val + +import kotlin.test.* + +fun foo(b: Boolean): Int { + val x: Int + if (b) { + x = 1 + } else { + x = 2 + } + + return x +} + +@Test fun runTest() { + val uninitializedUnused: Int + + println(foo(true)) + println(foo(false)) +} \ No newline at end of file diff --git a/kotlin-native/backend.native/tests/codegen/delegatedProperty/correctFieldsOrder_lib.kt b/kotlin-native/backend.native/tests/codegen/delegatedProperty/correctFieldsOrder_lib.kt new file mode 100644 index 00000000000..8ddf4cb6c47 --- /dev/null +++ b/kotlin-native/backend.native/tests/codegen/delegatedProperty/correctFieldsOrder_lib.kt @@ -0,0 +1,12 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +package zzz + +open class B { + val z by lazy { "qzz" } + val x = 117 + val zzz = "zzz" +} \ No newline at end of file diff --git a/kotlin-native/backend.native/tests/codegen/delegatedProperty/correctFieldsOrder_main.kt b/kotlin-native/backend.native/tests/codegen/delegatedProperty/correctFieldsOrder_main.kt new file mode 100644 index 00000000000..c9c4fec3aec --- /dev/null +++ b/kotlin-native/backend.native/tests/codegen/delegatedProperty/correctFieldsOrder_main.kt @@ -0,0 +1,18 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +import zzz.* + +class C : B() { + val a = "qxx" +} + +fun main(args: Array) { + val c = C() + println(c.a) + println(c.x) + println(c.zzz) + println(c.z) +} \ No newline at end of file diff --git a/kotlin-native/backend.native/tests/codegen/delegatedProperty/delegatedOverride_lib.kt b/kotlin-native/backend.native/tests/codegen/delegatedProperty/delegatedOverride_lib.kt new file mode 100644 index 00000000000..910bafcbd61 --- /dev/null +++ b/kotlin-native/backend.native/tests/codegen/delegatedProperty/delegatedOverride_lib.kt @@ -0,0 +1,28 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +package a + +import kotlin.reflect.KProperty + +open class A { + open val x = 42 +} + +class Delegate { + val f = 117 + operator fun getValue(receiver: Any?, p: KProperty<*>): Int { + println(p.name) + return f + } +} + +open class B: A() { + override val x: Int by Delegate() + + fun bar() { + println(super.x) + } +} \ No newline at end of file diff --git a/kotlin-native/backend.native/tests/codegen/delegatedProperty/delegatedOverride_main.kt b/kotlin-native/backend.native/tests/codegen/delegatedProperty/delegatedOverride_main.kt new file mode 100644 index 00000000000..a138d22f57d --- /dev/null +++ b/kotlin-native/backend.native/tests/codegen/delegatedProperty/delegatedOverride_main.kt @@ -0,0 +1,22 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +import a.* + +open class C: B() { + override val x: Int = 156 + + fun foo() { + println(x) + + println(super.x) + bar() + } +} + +fun main(args: Array) { + val c = C() + c.foo() +} diff --git a/kotlin-native/backend.native/tests/codegen/delegatedProperty/lazy.kt b/kotlin-native/backend.native/tests/codegen/delegatedProperty/lazy.kt new file mode 100644 index 00000000000..d48e70fb587 --- /dev/null +++ b/kotlin-native/backend.native/tests/codegen/delegatedProperty/lazy.kt @@ -0,0 +1,18 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +package codegen.delegatedProperty.lazy + +import kotlin.test.* + +val lazyValue: String by lazy { + println("computed!") + "Hello" +} + +@Test fun runTest() { + println(lazyValue) + println(lazyValue) +} \ No newline at end of file diff --git a/kotlin-native/backend.native/tests/codegen/delegatedProperty/local.kt b/kotlin-native/backend.native/tests/codegen/delegatedProperty/local.kt new file mode 100644 index 00000000000..fca85a5a3d3 --- /dev/null +++ b/kotlin-native/backend.native/tests/codegen/delegatedProperty/local.kt @@ -0,0 +1,27 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +package codegen.delegatedProperty.local + +import kotlin.test.* + +import kotlin.reflect.KProperty + +fun foo(): Int { + class Delegate { + operator fun getValue(receiver: Any?, p: KProperty<*>): Int { + println(p.name) + return 42 + } + } + + val x: Int by Delegate() + + return x +} + +@Test fun runTest() { + println(foo()) +} \ No newline at end of file diff --git a/kotlin-native/backend.native/tests/codegen/delegatedProperty/map.kt b/kotlin-native/backend.native/tests/codegen/delegatedProperty/map.kt new file mode 100644 index 00000000000..598ce40aa06 --- /dev/null +++ b/kotlin-native/backend.native/tests/codegen/delegatedProperty/map.kt @@ -0,0 +1,22 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +package codegen.delegatedProperty.map + +import kotlin.test.* + +class User(val map: Map) { + val name: String by map + val age: Int by map +} + +@Test fun runTest() { + val user = User(mapOf( + "name" to "John Doe", + "age" to 25 + )) + println(user.name) // Prints "John Doe" + println(user.age) // Prints 25 +} \ No newline at end of file diff --git a/kotlin-native/backend.native/tests/codegen/delegatedProperty/observable.kt b/kotlin-native/backend.native/tests/codegen/delegatedProperty/observable.kt new file mode 100644 index 00000000000..583a16b4d00 --- /dev/null +++ b/kotlin-native/backend.native/tests/codegen/delegatedProperty/observable.kt @@ -0,0 +1,23 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +package codegen.delegatedProperty.observable + +import kotlin.test.* + +import kotlin.properties.Delegates + +class User { + var name: String by Delegates.observable("") { + prop, old, new -> + println("$old -> $new") + } +} + +@Test fun runTest() { + val user = User() + user.name = "first" + user.name = "second" +} \ No newline at end of file diff --git a/kotlin-native/backend.native/tests/codegen/delegatedProperty/packageLevel.kt b/kotlin-native/backend.native/tests/codegen/delegatedProperty/packageLevel.kt new file mode 100644 index 00000000000..1092b490cb9 --- /dev/null +++ b/kotlin-native/backend.native/tests/codegen/delegatedProperty/packageLevel.kt @@ -0,0 +1,23 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +package codegen.delegatedProperty.packageLevel + +import kotlin.test.* + +import kotlin.reflect.KProperty + +class Delegate { + operator fun getValue(receiver: Any?, p: KProperty<*>): Int { + println(p.name) + return 42 + } +} + +val x: Int by Delegate() + +@Test fun runTest() { + println(x) +} \ No newline at end of file diff --git a/kotlin-native/backend.native/tests/codegen/delegatedProperty/simpleVal.kt b/kotlin-native/backend.native/tests/codegen/delegatedProperty/simpleVal.kt new file mode 100644 index 00000000000..73f36b93d6f --- /dev/null +++ b/kotlin-native/backend.native/tests/codegen/delegatedProperty/simpleVal.kt @@ -0,0 +1,25 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +package codegen.delegatedProperty.simpleVal + +import kotlin.test.* + +import kotlin.reflect.KProperty + +class Delegate { + operator fun getValue(receiver: Any?, p: KProperty<*>): Int { + println(p.name) + return 42 + } +} + +class C { + val x: Int by Delegate() +} + +@Test fun runTest() { + println(C().x) +} \ No newline at end of file diff --git a/kotlin-native/backend.native/tests/codegen/delegatedProperty/simpleVar.kt b/kotlin-native/backend.native/tests/codegen/delegatedProperty/simpleVar.kt new file mode 100644 index 00000000000..ed4e19a5b0f --- /dev/null +++ b/kotlin-native/backend.native/tests/codegen/delegatedProperty/simpleVar.kt @@ -0,0 +1,35 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +package codegen.delegatedProperty.simpleVar + +import kotlin.test.* + +import kotlin.reflect.KProperty + +class Delegate { + var f: Int = 42 + + operator fun getValue(receiver: Any?, p: KProperty<*>): Int { + println("get ${p.name}") + return f + } + + operator fun setValue(receiver: Any?, p: KProperty<*>, value: Int) { + println("set ${p.name}") + f = value + } +} + +class C { + var x: Int by Delegate() +} + +@Test fun runTest() { + val c = C() + println(c.x) + c.x = 117 + println(c.x) +} \ No newline at end of file diff --git a/kotlin-native/backend.native/tests/codegen/devirtualization/anonymousObject.kt b/kotlin-native/backend.native/tests/codegen/devirtualization/anonymousObject.kt new file mode 100644 index 00000000000..9eb9165d014 --- /dev/null +++ b/kotlin-native/backend.native/tests/codegen/devirtualization/anonymousObject.kt @@ -0,0 +1,22 @@ +/* + * Copyright 2010-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +interface I { + fun foo() +} + +fun test() { + val impl = object : I { + override fun foo() { println("zzz") } + } + + val delegating = object: I by impl { } + + delegating.foo() +} + +fun main() { + test() +} \ No newline at end of file diff --git a/kotlin-native/backend.native/tests/codegen/devirtualization/getter_looking_as_box_function.kt b/kotlin-native/backend.native/tests/codegen/devirtualization/getter_looking_as_box_function.kt new file mode 100644 index 00000000000..f379eb56e16 --- /dev/null +++ b/kotlin-native/backend.native/tests/codegen/devirtualization/getter_looking_as_box_function.kt @@ -0,0 +1,5 @@ +class Foo(val box: String = "box") + +fun main() { + println(Foo().box) +} \ No newline at end of file diff --git a/kotlin-native/backend.native/tests/codegen/devirtualization/lateinitInterface.kt b/kotlin-native/backend.native/tests/codegen/devirtualization/lateinitInterface.kt new file mode 100644 index 00000000000..1bb5bd22980 --- /dev/null +++ b/kotlin-native/backend.native/tests/codegen/devirtualization/lateinitInterface.kt @@ -0,0 +1,14 @@ +interface I { + fun foo(): Int +} + +class A : I { + override fun foo() = 42 +} + +fun main(args: Array) { + lateinit var a: I + if (args.size == 0) + a = A() + println(a.foo()) +} \ No newline at end of file diff --git a/kotlin-native/backend.native/tests/codegen/enum/companionObject.kt b/kotlin-native/backend.native/tests/codegen/enum/companionObject.kt new file mode 100644 index 00000000000..c4581f24c58 --- /dev/null +++ b/kotlin-native/backend.native/tests/codegen/enum/companionObject.kt @@ -0,0 +1,33 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +package codegen.enum.companionObject + +import kotlin.test.* + +enum class Game { + ROCK, + PAPER, + SCISSORS; + + companion object { + fun foo() = ROCK + val bar = PAPER + val values2 = values() + val scissors = valueOf("SCISSORS") + } +} + +fun box(): String { + if (Game.foo() != Game.ROCK) return "Fail 1" + if (Game.bar != Game.PAPER) return "Fail 2: ${Game.bar}" + if (Game.values().size != 3) return "Fail 3" + if (Game.valueOf("SCISSORS") != Game.SCISSORS) return "Fail 4" + if (Game.values2.size != 3) return "Fail 5" + if (Game.scissors != Game.SCISSORS) return "Fail 6" + return "OK" +} + +@Test fun runTest() = println(box()) \ No newline at end of file diff --git a/kotlin-native/backend.native/tests/codegen/enum/interfaceCallNoEntryClass.kt b/kotlin-native/backend.native/tests/codegen/enum/interfaceCallNoEntryClass.kt new file mode 100644 index 00000000000..cb8fe06685c --- /dev/null +++ b/kotlin-native/backend.native/tests/codegen/enum/interfaceCallNoEntryClass.kt @@ -0,0 +1,28 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +package codegen.enum.interfaceCallNoEntryClass + +import kotlin.test.* + +interface A { + fun foo(): String +} + +enum class Zzz(val zzz: String, val x: Int) : A { + Z1("z1", 1), + Z2("z2", 2), + Z3("z3", 3); + + override fun foo(): String{ + return "('$zzz', $x)" + } +} + +@Test fun runTest() { + println(Zzz.Z3.foo()) + val a: A = Zzz.Z3 + println(a.foo()) +} \ No newline at end of file diff --git a/kotlin-native/backend.native/tests/codegen/enum/interfaceCallWithEntryClass.kt b/kotlin-native/backend.native/tests/codegen/enum/interfaceCallWithEntryClass.kt new file mode 100644 index 00000000000..bab52500843 --- /dev/null +++ b/kotlin-native/backend.native/tests/codegen/enum/interfaceCallWithEntryClass.kt @@ -0,0 +1,31 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +package codegen.enum.interfaceCallWithEntryClass + +import kotlin.test.* + +interface A { + fun f(): String +} + +enum class Zzz: A { + Z1 { + override fun f() = "z1" + }, + + Z2 { + override fun f() = "z2" + }; + + override fun f() = "" +} + +@Test fun runTest() { + println(Zzz.Z1.f() + Zzz.Z2.f()) + val a1: A = Zzz.Z1 + val a2: A = Zzz.Z2 + println(a1.f() + a2.f()) +} \ No newline at end of file diff --git a/kotlin-native/backend.native/tests/codegen/enum/isFrozen.kt b/kotlin-native/backend.native/tests/codegen/enum/isFrozen.kt new file mode 100644 index 00000000000..b6e19af5897 --- /dev/null +++ b/kotlin-native/backend.native/tests/codegen/enum/isFrozen.kt @@ -0,0 +1,18 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +package codegen.enum.isFrozen + +import kotlin.test.* +import kotlin.native.concurrent.* + +enum class Zzz(val zzz: String) { + Z1("z1"), + Z2("z2") +} + +@Test fun runTest() { + println(Zzz.Z1.isFrozen) +} \ No newline at end of file diff --git a/kotlin-native/backend.native/tests/codegen/enum/lambdaInDefault.kt b/kotlin-native/backend.native/tests/codegen/enum/lambdaInDefault.kt new file mode 100644 index 00000000000..1d497d74144 --- /dev/null +++ b/kotlin-native/backend.native/tests/codegen/enum/lambdaInDefault.kt @@ -0,0 +1,18 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +package codegen.enum.lambdaInDefault + +import kotlin.test.* + +enum class Zzz(val value: String.() -> Int = { + length +}) { + Q() +} + +@Test fun runTest() { + println(Zzz.Q) +} \ No newline at end of file diff --git a/kotlin-native/backend.native/tests/codegen/enum/linkTest_lib.kt b/kotlin-native/backend.native/tests/codegen/enum/linkTest_lib.kt new file mode 100644 index 00000000000..d80af8e23ae --- /dev/null +++ b/kotlin-native/backend.native/tests/codegen/enum/linkTest_lib.kt @@ -0,0 +1,12 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +package a + +enum class A(val x: Int) { + Z1(42), + Z2(117), + Z3(-1) +} \ No newline at end of file diff --git a/kotlin-native/backend.native/tests/codegen/enum/linkTest_main.kt b/kotlin-native/backend.native/tests/codegen/enum/linkTest_main.kt new file mode 100644 index 00000000000..7484bbcb7d4 --- /dev/null +++ b/kotlin-native/backend.native/tests/codegen/enum/linkTest_main.kt @@ -0,0 +1,12 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +import a.* + +fun main(args: Array) { + println(A.Z1.x) + println(A.valueOf("Z2").x) + println(A.values()[2].x) +} \ No newline at end of file diff --git a/kotlin-native/backend.native/tests/codegen/enum/loop.kt b/kotlin-native/backend.native/tests/codegen/enum/loop.kt new file mode 100644 index 00000000000..326c81353c5 --- /dev/null +++ b/kotlin-native/backend.native/tests/codegen/enum/loop.kt @@ -0,0 +1,20 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +package codegen.enum.loop + +import kotlin.test.* + +enum class Zzz { + Z { + init { + println(Z.name) + } + } +} + +@Test fun runTest() { + println(Zzz.Z) +} \ No newline at end of file diff --git a/kotlin-native/backend.native/tests/codegen/enum/nested.kt b/kotlin-native/backend.native/tests/codegen/enum/nested.kt new file mode 100644 index 00000000000..eb938a04096 --- /dev/null +++ b/kotlin-native/backend.native/tests/codegen/enum/nested.kt @@ -0,0 +1,18 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +package codegen.enum.nested + +import kotlin.test.* + +enum class Foo { + A; + enum class Bar { C } +} + +@Test fun runTest() { + println(Foo.A) + println(Foo.Bar.C) +} \ No newline at end of file diff --git a/kotlin-native/backend.native/tests/codegen/enum/reorderedArguments.kt b/kotlin-native/backend.native/tests/codegen/enum/reorderedArguments.kt new file mode 100644 index 00000000000..21a8a8d5e04 --- /dev/null +++ b/kotlin-native/backend.native/tests/codegen/enum/reorderedArguments.kt @@ -0,0 +1,73 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +package codegen.enum.reorderedArguments + +import kotlin.test.* + +// Regression test for https://github.com/JetBrains/kotlin-native/issues/1779 +enum class Foo(val a: Int, val b: Int, val c: Int = 0) { + A(a = 1, b = 0), + B(b = 1, a = 0), + C(c = 1, b = 0, a = 0), + D(0, 0), + E(1, 1, 1) +} + +interface Base { + val value: T +} + +enum class Bar(override val value: Foo) : Base { + A(Foo.A), + B(Foo.B), + C(Foo.C), + D(Foo.D), + E(Foo.E) +} + +@Test fun runTest() { + + assertEquals(Foo.A.a, 1) + assertEquals(Foo.A.b, 0) + assertEquals(Foo.A.c, 0) + + assertEquals(Foo.B.a, 0) + assertEquals(Foo.B.b, 1) + assertEquals(Foo.B.c, 0) + + assertEquals(Foo.C.a, 0) + assertEquals(Foo.C.b, 0) + assertEquals(Foo.C.c, 1) + + assertEquals(Foo.D.a, 0) + assertEquals(Foo.D.b, 0) + assertEquals(Foo.D.c, 0) + + assertEquals(Foo.E.a, 1) + assertEquals(Foo.E.b, 1) + assertEquals(Foo.E.c, 1) + + assertEquals(Bar.A.value.a, 1) + assertEquals(Bar.A.value.b, 0) + assertEquals(Bar.A.value.c, 0) + + assertEquals(Bar.B.value.a, 0) + assertEquals(Bar.B.value.b, 1) + assertEquals(Bar.B.value.c, 0) + + assertEquals(Bar.C.value.a, 0) + assertEquals(Bar.C.value.b, 0) + assertEquals(Bar.C.value.c, 1) + + assertEquals(Bar.D.value.a, 0) + assertEquals(Bar.D.value.b, 0) + assertEquals(Bar.D.value.c, 0) + + assertEquals(Bar.E.value.a, 1) + assertEquals(Bar.E.value.b, 1) + assertEquals(Bar.E.value.c, 1) + +} \ No newline at end of file diff --git a/kotlin-native/backend.native/tests/codegen/enum/switchLowering.kt b/kotlin-native/backend.native/tests/codegen/enum/switchLowering.kt new file mode 100644 index 00000000000..8db7d17328f --- /dev/null +++ b/kotlin-native/backend.native/tests/codegen/enum/switchLowering.kt @@ -0,0 +1,91 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +package codegen.enum.switchLowering + +import kotlin.test.* + +enum class EnumA { + A, B, C +} + +enum class EnumB { + A, B +} + +enum class E { + ONE, TWO, THREE +} + +fun produceEntry() = EnumA.A + +// Check that we fail on comparison of different enum types. +fun differentEnums() { + println(when (produceEntry()) { + EnumB.A -> "EnumB.A" + EnumA.A -> "EnumA.A" + EnumA.B -> "EnumA.B" + else -> "nah" + }) +} + +// Nullable subject shouldn't be lowered. +fun nullable() { + val x: EnumA? = null + when(x) { + EnumA.A -> println("fail") + else -> println("ok") + } +} + +// Operator overloading won't trick us! +fun operatorOverloading() { + operator fun E.contains(other: E): Boolean = false + + val y = E.ONE + when(y) { + in E.ONE -> println("Should not reach here") + else -> println("ok") + } +} + +fun smoke1() { + when (produceEntry()) { + EnumA.B -> println("error") + EnumA.A -> println("ok") + EnumA.C -> println("error") + } +} + +fun smoke2() { + when (produceEntry()) { + EnumA.B -> println("error") + else -> println("ok") + } +} + +fun eA() = EnumA.A + +fun eB() = EnumA.B + + +fun nestedWhen() { + println(when (eA()) { + EnumA.A, EnumA.C -> when (eB()) { + EnumA.B -> "ok" + else -> "nope" + } + else -> "nope" + }) +} + +fun main() { + differentEnums() + nullable() + operatorOverloading() + smoke1() + smoke2() + nestedWhen() +} \ No newline at end of file diff --git a/kotlin-native/backend.native/tests/codegen/enum/test0.kt b/kotlin-native/backend.native/tests/codegen/enum/test0.kt new file mode 100644 index 00000000000..6cccc68431f --- /dev/null +++ b/kotlin-native/backend.native/tests/codegen/enum/test0.kt @@ -0,0 +1,18 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +package codegen.enum.test0 + +import kotlin.test.* + +val TOP_LEVEL = 5 + +enum class MyEnum(value: Int) { + VALUE(TOP_LEVEL) +} + +@Test fun runTest() { + println(MyEnum.VALUE.toString()) +} diff --git a/kotlin-native/backend.native/tests/codegen/enum/test1.kt b/kotlin-native/backend.native/tests/codegen/enum/test1.kt new file mode 100644 index 00000000000..3fda72ea328 --- /dev/null +++ b/kotlin-native/backend.native/tests/codegen/enum/test1.kt @@ -0,0 +1,17 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +package codegen.enum.test1 + +import kotlin.test.* + +enum class Zzz(val zzz: String, val x: Int) { + Z1("z1", 1), + Z2("z2", 2) +} + +@Test fun runTest() { + println(Zzz.Z1.zzz + Zzz.Z2.x) +} \ No newline at end of file diff --git a/kotlin-native/backend.native/tests/codegen/enum/vCallNoEntryClass.kt b/kotlin-native/backend.native/tests/codegen/enum/vCallNoEntryClass.kt new file mode 100644 index 00000000000..ea2007085f5 --- /dev/null +++ b/kotlin-native/backend.native/tests/codegen/enum/vCallNoEntryClass.kt @@ -0,0 +1,22 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +package codegen.enum.vCallNoEntryClass + +import kotlin.test.* + +enum class Zzz(val zzz: String, val x: Int) { + Z1("z1", 1), + Z2("z2", 2), + Z3("z3", 3); + + override fun toString(): String{ + return "('$zzz', $x)" + } +} + +@Test fun runTest() { + println(Zzz.Z3.toString()) +} \ No newline at end of file diff --git a/kotlin-native/backend.native/tests/codegen/enum/vCallWithEntryClass.kt b/kotlin-native/backend.native/tests/codegen/enum/vCallWithEntryClass.kt new file mode 100644 index 00000000000..5bc8a08c1da --- /dev/null +++ b/kotlin-native/backend.native/tests/codegen/enum/vCallWithEntryClass.kt @@ -0,0 +1,24 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +package codegen.enum.vCallWithEntryClass + +import kotlin.test.* + +enum class Zzz { + Z1 { + override fun f() = "z1" + }, + + Z2 { + override fun f() = "z2" + }; + + open fun f() = "" +} + +@Test fun runTest() { + println(Zzz.Z1.f() + Zzz.Z2.f()) +} \ No newline at end of file diff --git a/kotlin-native/backend.native/tests/codegen/enum/valueOf.kt b/kotlin-native/backend.native/tests/codegen/enum/valueOf.kt new file mode 100644 index 00000000000..002e4f6a645 --- /dev/null +++ b/kotlin-native/backend.native/tests/codegen/enum/valueOf.kt @@ -0,0 +1,23 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +package codegen.enum.valueOf + +import kotlin.test.* + +enum class E { + E3, + E1, + E2 +} + +@Test fun runTest() { + println(E.valueOf("E1").toString()) + println(E.valueOf("E2").toString()) + println(E.valueOf("E3").toString()) + println(enumValueOf("E1").toString()) + println(enumValueOf("E2").toString()) + println(enumValueOf("E3").toString()) +} \ No newline at end of file diff --git a/kotlin-native/backend.native/tests/codegen/enum/values.kt b/kotlin-native/backend.native/tests/codegen/enum/values.kt new file mode 100644 index 00000000000..0e27ebc2ab5 --- /dev/null +++ b/kotlin-native/backend.native/tests/codegen/enum/values.kt @@ -0,0 +1,23 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +package codegen.enum.values + +import kotlin.test.* + +enum class E { + E3, + E1, + E2 +} + +@Test fun runTest() { + println(E.values()[0].toString()) + println(E.values()[1].toString()) + println(E.values()[2].toString()) + println(enumValues()[0].toString()) + println(enumValues()[1].toString()) + println(enumValues()[2].toString()) +} \ No newline at end of file diff --git a/kotlin-native/backend.native/tests/codegen/enum/varargParam.kt b/kotlin-native/backend.native/tests/codegen/enum/varargParam.kt new file mode 100644 index 00000000000..99a637868f5 --- /dev/null +++ b/kotlin-native/backend.native/tests/codegen/enum/varargParam.kt @@ -0,0 +1,16 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +package codegen.enum.varargParam + +import kotlin.test.* + +enum class Piece(vararg val states: Int) { + I(3, 4, 5) +} + +@Test fun runTest() { + println(Piece.I.states[0]) +} \ No newline at end of file diff --git a/kotlin-native/backend.native/tests/codegen/escapeAnalysis/recursion.kt b/kotlin-native/backend.native/tests/codegen/escapeAnalysis/recursion.kt new file mode 100644 index 00000000000..08015939f1f --- /dev/null +++ b/kotlin-native/backend.native/tests/codegen/escapeAnalysis/recursion.kt @@ -0,0 +1,24 @@ +/* + * Copyright 2010-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +package codegen.escapeAnalysis.recursion + +import kotlin.test.* + +class A { + var f: A? = null +} + +fun foo(k: Int, a1: A, a2: A): A { + val a3 = A() + if (k == 0) + return a1 + a3.f = a1 + return foo(k - 1, a2, a3) +} + +@Test fun runTest() { + foo(3, A(), A()).toString() +} \ No newline at end of file diff --git a/kotlin-native/backend.native/tests/codegen/escapeAnalysis/test1.kt b/kotlin-native/backend.native/tests/codegen/escapeAnalysis/test1.kt new file mode 100644 index 00000000000..99284436de1 --- /dev/null +++ b/kotlin-native/backend.native/tests/codegen/escapeAnalysis/test1.kt @@ -0,0 +1,20 @@ +/* + * Copyright 2010-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +package codegen.escapeAnalysis.test1 + +class A(val s: String) + +// ----- Agressive ----- +// PointsTo: +// RET.v@lue -> P0 +// Escapes: +// ----- Passive ----- +// PointsTo: +// RET.v@lue -> P0 +// Escapes: +fun foo(a: A) = a + +fun main() = println(foo(A("zzz"))) \ No newline at end of file diff --git a/kotlin-native/backend.native/tests/codegen/escapeAnalysis/test10.kt b/kotlin-native/backend.native/tests/codegen/escapeAnalysis/test10.kt new file mode 100644 index 00000000000..a1ddef9774f --- /dev/null +++ b/kotlin-native/backend.native/tests/codegen/escapeAnalysis/test10.kt @@ -0,0 +1,41 @@ +/* + * Copyright 2010-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +package codegen.escapeAnalysis.test10 + +class G(val x: Int) + +class F(val s: String) { + var g = G(0) +} + +class A { + var f = F("") +} + +// ----- Agressive ----- +// PointsTo: +// P0.f -> D0 +// RET.v@lue -> D0 +// Escapes: +// ----- Passive ----- +// PointsTo: +// P0.f -> D0 +// RET.v@lue -> D0 +// Escapes: D0 +fun foo(a: A): F { + val v = F("zzz") + a.f = v + return v +} + +fun bar(): F { + val w = A() + val u = foo(w) + w.f.g = G(42) + return u +} + +fun main() = println(bar().g.x) \ No newline at end of file diff --git a/kotlin-native/backend.native/tests/codegen/escapeAnalysis/test11.kt b/kotlin-native/backend.native/tests/codegen/escapeAnalysis/test11.kt new file mode 100644 index 00000000000..1e8730a8db5 --- /dev/null +++ b/kotlin-native/backend.native/tests/codegen/escapeAnalysis/test11.kt @@ -0,0 +1,31 @@ +/* + * Copyright 2010-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +package codegen.escapeAnalysis.test11 + +class F(val x: Int) + +class A(val s: String) { + var f = F(0) +} + +var f: F? = null + +// ----- Agressive ----- +// PointsTo: +// RET.v@lue -> P0.f +// D0 -> P0.f +// Escapes: D0 +// ----- Passive ----- +// PointsTo: +// RET.v@lue -> P0.f +// D0 -> P0.f +// Escapes: D0 +fun foo(a: A): F { + f = a.f + return a.f +} + +fun main() = println(foo(A("zzz"))) \ No newline at end of file diff --git a/kotlin-native/backend.native/tests/codegen/escapeAnalysis/test12.kt b/kotlin-native/backend.native/tests/codegen/escapeAnalysis/test12.kt new file mode 100644 index 00000000000..44785fb24e2 --- /dev/null +++ b/kotlin-native/backend.native/tests/codegen/escapeAnalysis/test12.kt @@ -0,0 +1,20 @@ +/* + * Copyright 2010-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +package codegen.escapeAnalysis.test12 + +class A(val s: String) + +// ----- Agressive ----- +// PointsTo: +// RET.v@lue -> P0.inte$tines +// Escapes: +// ----- Passive ----- +// PointsTo: +// RET.v@lue -> P0.inte$tines +// Escapes: +fun foo(arr: Array) = arr[0] + +fun main() = println(foo(arrayOf(A("zzz"))).s) \ No newline at end of file diff --git a/kotlin-native/backend.native/tests/codegen/escapeAnalysis/test13.kt b/kotlin-native/backend.native/tests/codegen/escapeAnalysis/test13.kt new file mode 100644 index 00000000000..e07456a3333 --- /dev/null +++ b/kotlin-native/backend.native/tests/codegen/escapeAnalysis/test13.kt @@ -0,0 +1,20 @@ +/* + * Copyright 2010-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +package codegen.escapeAnalysis.test13 + +class A { + var f: A? = null +} + +fun foo(a: A, k: Int): A { + return if (k == 0) a else foo(a.f!!, k - 1) +} + +fun main() { + val a = A() + a.f = A() + println(foo(a, 1)) +} \ No newline at end of file diff --git a/kotlin-native/backend.native/tests/codegen/escapeAnalysis/test2.kt b/kotlin-native/backend.native/tests/codegen/escapeAnalysis/test2.kt new file mode 100644 index 00000000000..d9068afb897 --- /dev/null +++ b/kotlin-native/backend.native/tests/codegen/escapeAnalysis/test2.kt @@ -0,0 +1,20 @@ +/* + * Copyright 2010-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +package codegen.escapeAnalysis.test2 + +class A(val s: String) + +// ----- Agressive ----- +// PointsTo: +// RET.v@lue -> P0.s +// Escapes: +// ----- Passive ----- +// PointsTo: +// RET.v@lue -> P0.s +// Escapes: +fun foo(a: A) = a.s + +fun main() = println(foo(A("zzz"))) \ No newline at end of file diff --git a/kotlin-native/backend.native/tests/codegen/escapeAnalysis/test3.kt b/kotlin-native/backend.native/tests/codegen/escapeAnalysis/test3.kt new file mode 100644 index 00000000000..85ceb956100 --- /dev/null +++ b/kotlin-native/backend.native/tests/codegen/escapeAnalysis/test3.kt @@ -0,0 +1,28 @@ +/* + * Copyright 2010-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +package codegen.escapeAnalysis.test3 + +class A(val s: String) +class B { + var s: String? = null +} + +// ----- Agressive ----- +// PointsTo: +// P1.s -> P0.s +// RET.v@lue -> P0.s +// Escapes: +// ----- Passive ----- +// PointsTo: +// P1.s -> P0.s +// RET.v@lue -> P0.s +// Escapes: +fun foo(a: A, b: B): String { + b.s = a.s + return a.s +} + +fun main() = println(foo(A("zzz"), B())) \ No newline at end of file diff --git a/kotlin-native/backend.native/tests/codegen/escapeAnalysis/test4.kt b/kotlin-native/backend.native/tests/codegen/escapeAnalysis/test4.kt new file mode 100644 index 00000000000..34eee09a3a8 --- /dev/null +++ b/kotlin-native/backend.native/tests/codegen/escapeAnalysis/test4.kt @@ -0,0 +1,30 @@ +/* + * Copyright 2010-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +package codegen.escapeAnalysis.test4 + +class A(val s: String) +class B { + var f: A = A("qzz") +} +class C { + var g: B = B() +} + +// ----- Agressive ----- +// PointsTo: +// P0.g.f -> P1.g.f +// RET.v@lue -> D0 +// Escapes: D0 +// ----- Passive ----- +// PointsTo: +// P0.g.f -> P1.g.f +// RET.v@lue -> D0 +// Escapes: D0 +fun foo(c1: C, c2: C) { + c1.g.f = c2.g.f +} + +fun main() = println(foo(C(), C())) \ No newline at end of file diff --git a/kotlin-native/backend.native/tests/codegen/escapeAnalysis/test5.kt b/kotlin-native/backend.native/tests/codegen/escapeAnalysis/test5.kt new file mode 100644 index 00000000000..d86bc22fac4 --- /dev/null +++ b/kotlin-native/backend.native/tests/codegen/escapeAnalysis/test5.kt @@ -0,0 +1,35 @@ +/* + * Copyright 2010-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +package codegen.escapeAnalysis.test5 + +class A(val s: String) +class B { + var f: A = A("qzz") +} +class C { + var g: B = B() +} + +// ----- Agressive ----- +// PointsTo: +// RET.v@lue -> D0 +// D0.f -> P0.g.f +// Escapes: +// ----- Passive ----- +// PointsTo: +// P0.g.f -> D2 +// RET.v@lue -> D0 +// D0.f -> P0.g.f +// D0.f -> D1 +// D1 -> D2 +// Escapes: D0 D1 +fun foo(c1: C, c2: C): B { + val b = B() + b.f = c1.g.f + return b +} + +fun main() = println(foo(C(), C())) \ No newline at end of file diff --git a/kotlin-native/backend.native/tests/codegen/escapeAnalysis/test6.kt b/kotlin-native/backend.native/tests/codegen/escapeAnalysis/test6.kt new file mode 100644 index 00000000000..4d6798f48ef --- /dev/null +++ b/kotlin-native/backend.native/tests/codegen/escapeAnalysis/test6.kt @@ -0,0 +1,40 @@ +/* + * Copyright 2010-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +package codegen.escapeAnalysis.test6 + +class A(val s: String) +class B { + var f: A = A("qzz") +} +class C { + var g: B = B() +} + +// ----- Agressive ----- +// PointsTo: +// P1.g -> D0 +// P2.g -> D0 +// RET.v@lue -> P1.g +// RET.v@lue -> P2.g +// RET.v@lue -> D0 +// D0.f -> P3 +// Escapes: +// ----- Passive ----- +// PointsTo: +// P1.g -> D0 +// P2.g -> D0 +// RET.v@lue -> P1.g +// RET.v@lue -> P2.g +// RET.v@lue -> D0 +// D0.f -> P3 +// Escapes: +fun foo(z: Boolean, c1: C, c2: C, a: A): B { + val v = if(z) c1.g else c2.g + v.f = a + return v +} + +fun main() = println(foo(true, C(), C(), A("zzz"))) \ No newline at end of file diff --git a/kotlin-native/backend.native/tests/codegen/escapeAnalysis/test7.kt b/kotlin-native/backend.native/tests/codegen/escapeAnalysis/test7.kt new file mode 100644 index 00000000000..f0952125e3a --- /dev/null +++ b/kotlin-native/backend.native/tests/codegen/escapeAnalysis/test7.kt @@ -0,0 +1,52 @@ +/* + * Copyright 2010-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +package codegen.escapeAnalysis.test7 + +class A(val s: String) { + var h: String = "" + var p: C = C() +} +class B { + var f: A = A("qzz") +} +class C { + var g: A = A("") +} +class D { + var o: A = A("") +} + +// ----- Agressive ----- +// PointsTo: +// P1.g -> D0 +// P2.f -> D0 +// P4.o -> P1.g +// P4.o -> P2.f +// P4.o -> D0 +// RET.v@lue -> D1 +// D0.p -> P1 +// D0.h -> P3 +// Escapes: D1 +// ----- Passive ----- +// PointsTo: +// P1.g -> D0 +// P2.f -> D0 +// P4.o -> P1.g +// P4.o -> P2.f +// P4.o -> D0 +// RET.v@lue -> D1 +// D0.p -> P1 +// D0.h -> P3 +// Escapes: D1 +fun foo(z: Boolean, c: C, b: B, s: String, d: D) { + val v = if(z) c.g else b.f + v.h = s + d.o = v + val u = v + u.p = c +} + +fun main() = println(foo(true, C(), B(), "zzz", D())) \ No newline at end of file diff --git a/kotlin-native/backend.native/tests/codegen/escapeAnalysis/test8.kt b/kotlin-native/backend.native/tests/codegen/escapeAnalysis/test8.kt new file mode 100644 index 00000000000..5b95b1c4059 --- /dev/null +++ b/kotlin-native/backend.native/tests/codegen/escapeAnalysis/test8.kt @@ -0,0 +1,43 @@ +/* + * Copyright 2010-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +package codegen.escapeAnalysis.test8 + +class F(val s: String) { + var g = F("") +} + +class A { + var f = F("qzz") +} + +// ----- Agressive ----- +// PointsTo: +// P0.f -> D0 +// RET.v@lue -> P0.f +// RET.v@lue -> D0 +// RET.v@lue -> D0.g +// D0.g -> P0.f +// D0.g -> D0 +// Escapes: +// ----- Passive ----- +// PointsTo: +// P0.f -> D0 +// RET.v@lue -> P0.f +// RET.v@lue -> D0 +// RET.v@lue -> D0.g +// D0.g -> P0.f +// D0.g -> D0 +// D0.g -> D2 +// D1 -> D0 +// D2 -> D0 +// Escapes: D1 D2 +fun foo(a: A): F { + a.f = F("zzz") + a.f.g = a.f + return a.f.g.g +} + +fun main() = println(foo(A()).s) \ No newline at end of file diff --git a/kotlin-native/backend.native/tests/codegen/escapeAnalysis/test9.kt b/kotlin-native/backend.native/tests/codegen/escapeAnalysis/test9.kt new file mode 100644 index 00000000000..ccbc9097872 --- /dev/null +++ b/kotlin-native/backend.native/tests/codegen/escapeAnalysis/test9.kt @@ -0,0 +1,36 @@ +/* + * Copyright 2010-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +package codegen.escapeAnalysis.test9 + +class H(val x: Int) + +class F(val s: String) { + var g = F("") + var h = H(0) +} + +class A { + var f = F("qzz") +} + +// ----- Agressive ----- +// PointsTo: +// P0.f -> P1.g +// RET.v@lue -> P1.g.h +// Escapes: +// ----- Passive ----- +// PointsTo: +// P0.f -> P1.g +// P1.g.h -> D0 +// RET.v@lue -> P1.g.h +// Escapes: D0 +fun foo(a: A, f: F): H { + a.f = f.g + a.f.h = H(42) + return f.g.h +} + +fun main() = println(foo(A(), F("zzz")).x) \ No newline at end of file diff --git a/kotlin-native/backend.native/tests/codegen/escapeAnalysis/zeroOutObjectOnAlloc.kt b/kotlin-native/backend.native/tests/codegen/escapeAnalysis/zeroOutObjectOnAlloc.kt new file mode 100644 index 00000000000..b1a25997e3e --- /dev/null +++ b/kotlin-native/backend.native/tests/codegen/escapeAnalysis/zeroOutObjectOnAlloc.kt @@ -0,0 +1,25 @@ +/* + * Copyright 2010-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +package codegen.escapeAnalysis.zeroOutObjectOnAlloc + +import kotlin.test.* + +class A { + var x = 0 +} + +@Test fun runTest() { + var sum1 = 0 + var sum2 = 0 + for (i in 0 until 10) { + val a = A() + sum1 += a.x + a.x = i + sum2 += a.x + } + assertEquals(0, sum1) + assertEquals(45, sum2) +} \ No newline at end of file diff --git a/kotlin-native/backend.native/tests/codegen/function/arithmetic.kt b/kotlin-native/backend.native/tests/codegen/function/arithmetic.kt new file mode 100644 index 00000000000..7c6b2fb5825 --- /dev/null +++ b/kotlin-native/backend.native/tests/codegen/function/arithmetic.kt @@ -0,0 +1,22 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +package codegen.function.arithmetic + +import kotlin.test.* + +fun square(a:Int):Int = a * a +fun sumOfSquares(a:Int, b:Int):Int = square(a) + square(b) +fun diffOfSquares(a:Int, b:Int):Int = square(a) - square(b) +fun mod(a:Int,b:Int):Int = a / b +fun remainder(a:Int, b:Int):Int = a % b + +@Test fun runTest() { + if (square(2) != 4) throw Error() + if (sumOfSquares(2, 4) != 20) throw Error() + if (diffOfSquares(2, 4) != -12) throw Error() + if (mod(5, 2) != 2) throw Error() + if (remainder(5, 2) != 1) throw Error() +} \ No newline at end of file diff --git a/kotlin-native/backend.native/tests/codegen/function/boolean.kt b/kotlin-native/backend.native/tests/codegen/function/boolean.kt new file mode 100644 index 00000000000..0cf3bf62500 --- /dev/null +++ b/kotlin-native/backend.native/tests/codegen/function/boolean.kt @@ -0,0 +1,14 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +package codegen.function.boolean + +import kotlin.test.* + +fun bool_yes(): Boolean = true + +@Test fun runTest() { + if (!bool_yes()) throw Error() +} diff --git a/kotlin-native/backend.native/tests/codegen/function/defaults.kt b/kotlin-native/backend.native/tests/codegen/function/defaults.kt new file mode 100644 index 00000000000..4dcc1b96a6b --- /dev/null +++ b/kotlin-native/backend.native/tests/codegen/function/defaults.kt @@ -0,0 +1,102 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +package codegen.function.defaults + +import kotlin.test.* + +/** + * Created by minamoto on 12/26/16. + */ +//package defaults + +open class A(val a:Int) { + override fun equals(other: Any?): Boolean { + if (other == null || other as? A == null) return false + return (other as A).a == a // Where is smart casting? + } + + companion object { + val zero = A(0) + val one = A(1) + val magic = A(42) + } +} + +// FUN public fun foo(a: defaults.A = ...): kotlin.Int +// a: EXPRESSION_BODY +// CALL '(): A' type=defaults.A origin=GET_PROPERTY +// $this: GET_OBJECT 'companion object of A' type=defaults.A.Companion +// BLOCK_BODY +// RETURN type=kotlin.Nothing from='foo(A = ...): Int' +// CALL '(): Int' type=kotlin.Int origin=GET_PROPERTY +// $this: GET_VAR 'value-parameter a: A = ...' type=defaults.A origin=null +fun foo(a: A = A.magic, b:Int = 0xdeadbeef.toInt()) = a.a + +// FUN public fun bar(a: defaults.A, inc: kotlin.Int = ...): defaults.A +// inc: EXPRESSION_BODY +// CONST Int type=kotlin.Int value='0' +// BLOCK_BODY +// RETURN type=kotlin.Nothing from='bar(A, Int = ...): A' +// CALL 'constructor A(Int)' type=defaults.A origin=null +// a: CALL 'plus(Int): Int' type=kotlin.Int origin=PLUS +// $this: CALL '(): Int' type=kotlin.Int origin=GET_PROPERTY +// $this: GET_VAR 'value-parameter a: A' type=defaults.A origin=null +// other: GET_VAR 'value-parameter inc: Int = ...' type=kotlin.Int origin=null +fun bar(a:A, inc:Int = 0) = A(a.a + inc) + + +@Test fun runTest() { + +// if: CALL 'NOT(Boolean): Boolean' type=kotlin.Boolean origin=EXCLEQ +// arg0: CALL 'EQEQ(Any?, Any?): Boolean' type=kotlin.Boolean origin=EXCLEQ +// arg0: CALL 'foo(A = ...): Int' type=kotlin.Int origin=null +// arg1: CALL '(): Int' type=kotlin.Int origin=GET_PROPERTY +// $this: CALL '(): A' type=defaults.A origin=GET_PROPERTY +// $this: GET_OBJECT 'companion object of A' type=defaults.A.Companion + if (foo() != A.magic.a) { + println("magic failed") + throw Error() + } + +// if: CALL 'NOT(Boolean): Boolean' type=kotlin.Boolean origin=EXCLEQ +// arg0: CALL 'EQEQ(Any?, Any?): Boolean' type=kotlin.Boolean origin=EXCLEQ +// arg0: CALL 'foo(A = ...): Int' type=kotlin.Int origin=null +// a: CALL 'constructor A(Int)' type=defaults.A origin=null +// a: CONST Int type=kotlin.Int value='1' +// arg1: CONST Int type=kotlin.Int value='1' + if (foo(A(1)) != 1) { + println("one failed: foo(A(1))") + throw Error() + } + +// if: CALL 'NOT(Boolean): Boolean' type=kotlin.Boolean origin=EXCLEQ +// arg0: CALL 'EQEQ(Any?, Any?): Boolean' type=kotlin.Boolean origin=EXCLEQ +// arg0: CALL 'bar(A, Int = ...): A' type=defaults.A origin=null +// a: CALL '(): A' type=defaults.A origin=GET_PROPERTY <--- +// $this: GET_OBJECT 'companion object of A' type=defaults.A.Companion +// arg1: CALL '(): A' type=defaults.A origin=GET_PROPERTY +// $this: GET_OBJECT 'companion object of A' type=defaults.A.Companion + + if (bar(A.one) != A.one) { + println("A one failed") + throw Error() + } + + +// if: CALL 'NOT(Boolean): Boolean' type=kotlin.Boolean origin=EXCLEQ +// arg0: CALL 'EQEQ(Any?, Any?): Boolean' type=kotlin.Boolean origin=EXCLEQ +// arg0: CALL '(): Int' type=kotlin.Int origin=GET_PROPERTY +// $this: CALL 'bar(A, Int = ...): A' type=defaults.A origin=null +// a: CALL '(): A' type=defaults.A origin=GET_PROPERTY +// $this: GET_OBJECT 'companion object of A' type=defaults.A.Companion +// inc: CONST Int type=kotlin.Int value='1' +// arg1: CONST Int type=kotlin.Int value='2' + if (bar(A.one, 1).a != 2) { + println("A one + 1 failed") + throw Error() + } + println("all tests passed") +} diff --git a/kotlin-native/backend.native/tests/codegen/function/defaults1.kt b/kotlin-native/backend.native/tests/codegen/function/defaults1.kt new file mode 100644 index 00000000000..d37e43de7a3 --- /dev/null +++ b/kotlin-native/backend.native/tests/codegen/function/defaults1.kt @@ -0,0 +1,18 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +package codegen.function.defaults1 + +import kotlin.test.* + +fun foo(x:Int = 0, y:Int = x + 1, z:Int = x + y + 1) = x + y + z + +@Test fun runTest() { + val v = foo() + if (v != 3) { + println("test failed $v expected 3") + throw Error() + } +} \ No newline at end of file diff --git a/kotlin-native/backend.native/tests/codegen/function/defaults10.kt b/kotlin-native/backend.native/tests/codegen/function/defaults10.kt new file mode 100644 index 00000000000..5e51f847493 --- /dev/null +++ b/kotlin-native/backend.native/tests/codegen/function/defaults10.kt @@ -0,0 +1,16 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +package codegen.function.defaults10 + +import kotlin.test.* + +enum class A(one: Int, val two: Int = one) { + FOO(42) +} + +@Test fun runTest() { + println(A.FOO.two) +} \ No newline at end of file diff --git a/kotlin-native/backend.native/tests/codegen/function/defaults2.kt b/kotlin-native/backend.native/tests/codegen/function/defaults2.kt new file mode 100644 index 00000000000..36ece284eef --- /dev/null +++ b/kotlin-native/backend.native/tests/codegen/function/defaults2.kt @@ -0,0 +1,19 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +package codegen.function.defaults2 + +import kotlin.test.* + + +fun Int.foo(inc0:Int, inc:Int = 0) = this + inc0 + inc + +@Test fun runTest() { + val v = 42.foo(0) + if (v != 42) { + println("test failed v:$v expected:42") + throw Error() + } +} diff --git a/kotlin-native/backend.native/tests/codegen/function/defaults3.kt b/kotlin-native/backend.native/tests/codegen/function/defaults3.kt new file mode 100644 index 00000000000..4b82f762f3f --- /dev/null +++ b/kotlin-native/backend.native/tests/codegen/function/defaults3.kt @@ -0,0 +1,21 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +package codegen.function.defaults3 + +import kotlin.test.* + +fun foo(a:Int = 2, b:String = "Hello", c:Int = 4):String = "$b-$c$a" +fun foo(a:Int = 3, b:Int = a + 1, c:Int = a + b) = a + b + c + +@Test fun runTest() { + val a = foo(b="Universe") + if (a != "Universe-42") + throw Error() + + val b = foo(b = 5) + if (b != (/* a = */ 3 + /* b = */ 5 + /* c = */ (3 + 5))) + throw Error() +} \ No newline at end of file diff --git a/kotlin-native/backend.native/tests/codegen/function/defaults4.kt b/kotlin-native/backend.native/tests/codegen/function/defaults4.kt new file mode 100644 index 00000000000..6b1a02c5909 --- /dev/null +++ b/kotlin-native/backend.native/tests/codegen/function/defaults4.kt @@ -0,0 +1,22 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +package codegen.function.defaults4 + +import kotlin.test.* + +open class A { + open fun foo(x: Int = 42) = println(x) +} + +open class B : A() + +class C : B() { + override fun foo(x: Int) = println(x + 1) +} + +@Test fun runTest() { + C().foo() +} \ No newline at end of file diff --git a/kotlin-native/backend.native/tests/codegen/function/defaults5.kt b/kotlin-native/backend.native/tests/codegen/function/defaults5.kt new file mode 100644 index 00000000000..3c079c00d08 --- /dev/null +++ b/kotlin-native/backend.native/tests/codegen/function/defaults5.kt @@ -0,0 +1,23 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +package codegen.function.defaults5 + +import kotlin.test.* + +class TestClass(val x: Int) { + fun foo(y: Int = x) { + println(y) + } +} + +fun TestClass.bar(y: Int = x) { + println(y) +} + +@Test fun runTest() { + TestClass(5).foo() + TestClass(6).bar() +} \ No newline at end of file diff --git a/kotlin-native/backend.native/tests/codegen/function/defaults6.kt b/kotlin-native/backend.native/tests/codegen/function/defaults6.kt new file mode 100644 index 00000000000..8edbb145bda --- /dev/null +++ b/kotlin-native/backend.native/tests/codegen/function/defaults6.kt @@ -0,0 +1,15 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +package codegen.function.defaults6 + +import kotlin.test.* + +open class Foo(val x: Int = 42) +class Bar : Foo() + +@Test fun runTest() { + println(Bar().x) +} \ No newline at end of file diff --git a/kotlin-native/backend.native/tests/codegen/function/defaults7.kt b/kotlin-native/backend.native/tests/codegen/function/defaults7.kt new file mode 100644 index 00000000000..d8dd0c6c4d4 --- /dev/null +++ b/kotlin-native/backend.native/tests/codegen/function/defaults7.kt @@ -0,0 +1,25 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +package codegen.function.defaults7 + +import kotlin.test.* + +/** + * Test fails with code generation: + * Call parameter type does not match function signature! + * %5 = invoke %struct.ObjHeader* @"kfun:kotlin.native.internal.boxInt(kotlin.Int)"(i32 1, %struct.ObjHeader** %4) + * to label %label_ unwind label %cleanup_landingpad + * i32 invoke void @"kfun:foo$default(kotlin.Int;kotlin.Int;kotlin.Int)"(%struct.ObjHeader* %5, i32 0, i32 2) + * to label %label_1 unwind label %cleanup_landingpad + */ + +fun foo(a : T, b : Int = 42){ + println(b) +} + +@Test fun runTest() { + foo(1) +} \ No newline at end of file diff --git a/kotlin-native/backend.native/tests/codegen/function/defaults8.kt b/kotlin-native/backend.native/tests/codegen/function/defaults8.kt new file mode 100644 index 00000000000..7067196511f --- /dev/null +++ b/kotlin-native/backend.native/tests/codegen/function/defaults8.kt @@ -0,0 +1,20 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +package codegen.function.defaults8 + +import kotlin.test.* + +class Foo { + fun test(x: Int = 1) = x +} + +class Bar { + fun test(x: Int = 2) = x +} + +@Test fun runTest() { + println(Bar().test()) +} \ No newline at end of file diff --git a/kotlin-native/backend.native/tests/codegen/function/defaults9.kt b/kotlin-native/backend.native/tests/codegen/function/defaults9.kt new file mode 100644 index 00000000000..4253e740a27 --- /dev/null +++ b/kotlin-native/backend.native/tests/codegen/function/defaults9.kt @@ -0,0 +1,16 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +package codegen.function.defaults9 + +import kotlin.test.* + +class Foo { + inner class Bar(x: Int, val y: Int = 1) { + constructor() : this(42) + } +} + +@Test fun runTest() = println(Foo().Bar().y) diff --git a/kotlin-native/backend.native/tests/codegen/function/defaultsFromFakeOverride.kt b/kotlin-native/backend.native/tests/codegen/function/defaultsFromFakeOverride.kt new file mode 100644 index 00000000000..f79e3bb25cc --- /dev/null +++ b/kotlin-native/backend.native/tests/codegen/function/defaultsFromFakeOverride.kt @@ -0,0 +1,23 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +package codegen.function.defaultsFromFakeOverride + +import kotlin.test.* + +interface I { + fun f(x: String = "42"): String +} + +open class A { + open fun f(x: String) = x +} + +class B : A(), I + +@Test fun runTest() { + val b = B() + println(b.f()) +} \ No newline at end of file diff --git a/kotlin-native/backend.native/tests/codegen/function/defaultsWithInlineClasses.kt b/kotlin-native/backend.native/tests/codegen/function/defaultsWithInlineClasses.kt new file mode 100644 index 00000000000..6a21b2a1915 --- /dev/null +++ b/kotlin-native/backend.native/tests/codegen/function/defaultsWithInlineClasses.kt @@ -0,0 +1,16 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +package codegen.function.defaultsWithInlineClasses + +import kotlin.test.* + +inline class Foo(val value: Int) +fun foo(x: Foo = Foo(42)) = x.value + +@Test fun runTest() { + assertEquals(foo(), 42) + assertEquals(foo(Foo(17)), 17) +} \ No newline at end of file diff --git a/kotlin-native/backend.native/tests/codegen/function/defaultsWithVarArg1.kt b/kotlin-native/backend.native/tests/codegen/function/defaultsWithVarArg1.kt new file mode 100644 index 00000000000..6cbefc1e0a3 --- /dev/null +++ b/kotlin-native/backend.native/tests/codegen/function/defaultsWithVarArg1.kt @@ -0,0 +1,26 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +package codegen.function.defaultsWithVarArg1 + +import kotlin.test.* + +fun foo(s: String = "", vararg args: Any) { + if (args == null) { + println("Failed!") + } else { + print("$s ") + args.forEach { + print("$it") + } + println(", Correct!") + } +} + +@Test fun runTest() { + foo("Hello") + foo("Hello", "World") + foo() +} \ No newline at end of file diff --git a/kotlin-native/backend.native/tests/codegen/function/defaultsWithVarArg2.kt b/kotlin-native/backend.native/tests/codegen/function/defaultsWithVarArg2.kt new file mode 100644 index 00000000000..6962fda8b86 --- /dev/null +++ b/kotlin-native/backend.native/tests/codegen/function/defaultsWithVarArg2.kt @@ -0,0 +1,17 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +package codegen.function.defaultsWithVarArg2 + +import kotlin.test.* + +fun foo(vararg arr: Int = intArrayOf(1, 2)) { + arr.forEach { println(it) } +} + +@Test fun runTest() { + foo() + foo(42) +} \ No newline at end of file diff --git a/kotlin-native/backend.native/tests/codegen/function/eqeq.kt b/kotlin-native/backend.native/tests/codegen/function/eqeq.kt new file mode 100644 index 00000000000..65bcb6f7008 --- /dev/null +++ b/kotlin-native/backend.native/tests/codegen/function/eqeq.kt @@ -0,0 +1,64 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +package codegen.function.eqeq + +import kotlin.test.* + +fun eqeqB (a:Byte, b:Byte ) = a == b +fun eqeqS (a:Short, b:Short ) = a == b +fun eqeqI (a:Int, b:Int ) = a == b +fun eqeqL (a:Long, b:Long ) = a == b +fun eqeqF (a:Float, b:Float ) = a == b +fun eqeqD (a:Double, b:Double) = a == b +fun eqeqStr(a:String, b:String) = a == b + +fun eqeqN (a: Nothing, b: Nothing) = a == b +fun eqeqNN (a: Nothing?, b: Nothing?) = a == b + +fun eqeqeq (a: Any?, b: Any?) = a === b + +fun gtI (a:Int, b:Int ) = a > b +fun ltI (a:Int, b:Int ) = a < b +fun geI (a:Int, b:Int ) = a >= b +fun leI (a:Int, b:Int ) = a <= b +fun neI (a:Int, b:Int ) = a != b + +fun gtF (a:Float, b:Float ) = a > b +fun ltF (a:Float, b:Float ) = a < b +fun geF (a:Float, b:Float ) = a >= b +fun leF (a:Float, b:Float ) = a <= b +fun neF (a:Float, b:Float ) = a != b + +fun helloString() = "Hello" +fun goodbyeString() = "Goodbye" + +@Test fun runTest() { + if (!eqeqB(3 , 3 )) throw Error() + if (!eqeqS(3 , 3 )) throw Error() + if (!eqeqI(3 , 3 )) throw Error() + if (!eqeqL(3L , 3L )) throw Error() + if (!eqeqF(3.0f, 3.0f)) throw Error() + if (!eqeqD(3.0 , 3.0 )) throw Error() + + if (!eqeqStr(helloString(), helloString())) throw Error() + + if (!eqeqNN(null, null)) throw Error() + + if (!eqeqeq(helloString(), helloString())) throw Error() + if (eqeqeq(helloString(), goodbyeString())) throw Error() + + if (gtI (2 , 3 )) throw Error() + if (ltI (3 , 2 )) throw Error() + if (geI (2 , 3 )) throw Error() + if (leI (3 , 2 )) throw Error() + if (neI (2 , 2 )) throw Error() + + if (gtF (2.0f , 3.0f )) throw Error() + if (ltF (3.0f , 2.0f )) throw Error() + if (geF (2.0f , 3.0f )) throw Error() + if (leF (3.0f , 2.0f )) throw Error() + if (neF (2.0f , 2.0f )) throw Error() +} \ No newline at end of file diff --git a/kotlin-native/backend.native/tests/codegen/function/extension.kt b/kotlin-native/backend.native/tests/codegen/function/extension.kt new file mode 100644 index 00000000000..33ff3db55b8 --- /dev/null +++ b/kotlin-native/backend.native/tests/codegen/function/extension.kt @@ -0,0 +1,8 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +class B(val a: Int) + +fun B.foo() = this.a \ No newline at end of file diff --git a/kotlin-native/backend.native/tests/codegen/function/intrinsic.kt b/kotlin-native/backend.native/tests/codegen/function/intrinsic.kt new file mode 100644 index 00000000000..2f507b8fd6b --- /dev/null +++ b/kotlin-native/backend.native/tests/codegen/function/intrinsic.kt @@ -0,0 +1,23 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +package codegen.function.intrinsic + +import kotlin.test.* + +// This code fails to link when bultins are taken from the +// frontend generated module, instead of our library. +// Because the generated module doesn't see our name changing annotations, +// the function names are all wrong. + +fun intrinsic(b: Int): Int { + var sum = 1 + sum = sum + b + return sum +} + +@Test fun runTest() { + if (intrinsic(3) != 4) throw Error() +} \ No newline at end of file diff --git a/kotlin-native/backend.native/tests/codegen/function/localFunction.kt b/kotlin-native/backend.native/tests/codegen/function/localFunction.kt new file mode 100644 index 00000000000..406a05e2346 --- /dev/null +++ b/kotlin-native/backend.native/tests/codegen/function/localFunction.kt @@ -0,0 +1,32 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +package codegen.function.localFunction + +import kotlin.test.* + +@Test fun runTest() { + val x = 1 + fun local0() = println(x) + fun local1() { + fun local2() { + local1() + } + local0() + } + + fun l1() { + var x = 1 + fun l2() { + fun l3() { + l1() + x = 5 + } + l3() + } + } + + println("OK") +} \ No newline at end of file diff --git a/kotlin-native/backend.native/tests/codegen/function/localFunction2.kt b/kotlin-native/backend.native/tests/codegen/function/localFunction2.kt new file mode 100644 index 00000000000..0f7ca113cc2 --- /dev/null +++ b/kotlin-native/backend.native/tests/codegen/function/localFunction2.kt @@ -0,0 +1,25 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +package codegen.function.localFunction2 + +import kotlin.test.* + +@Test fun runTest() { + var a = 0 + fun local() { + class A { + val b = 0 + fun f() { + a = b + } + + } + fun local2() : A { + return A() + } + } + println("OK") +} \ No newline at end of file diff --git a/kotlin-native/backend.native/tests/codegen/function/localFunction3.kt b/kotlin-native/backend.native/tests/codegen/function/localFunction3.kt new file mode 100644 index 00000000000..80cc882c9d9 --- /dev/null +++ b/kotlin-native/backend.native/tests/codegen/function/localFunction3.kt @@ -0,0 +1,25 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +package codegen.function.localFunction3 + +import kotlin.test.* + +@Test fun runTest() { + fun bar() { + fun local1() { + bar() + } + local1() + + var x = 0 + fun local2() { + x++ + bar() + } + local2() + } + println("OK") +} \ No newline at end of file diff --git a/kotlin-native/backend.native/tests/codegen/function/minus_eq.kt b/kotlin-native/backend.native/tests/codegen/function/minus_eq.kt new file mode 100644 index 00000000000..986e3d9e525 --- /dev/null +++ b/kotlin-native/backend.native/tests/codegen/function/minus_eq.kt @@ -0,0 +1,18 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +package codegen.function.minus_eq + +import kotlin.test.* + +fun minus_eq(a: Int): Int { + var b = 11 + b -= a + return b +} + +@Test fun runTest() { + if (minus_eq(23) != -12) throw Error() +} \ No newline at end of file diff --git a/kotlin-native/backend.native/tests/codegen/function/named.kt b/kotlin-native/backend.native/tests/codegen/function/named.kt new file mode 100644 index 00000000000..fe0b9aaf3cc --- /dev/null +++ b/kotlin-native/backend.native/tests/codegen/function/named.kt @@ -0,0 +1,15 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +package codegen.function.named + +import kotlin.test.* + +fun foo(a:Int, b:Int) = a - b + +@Test fun runTest() { + if (foo(b = 24, a = 42) != 18) + throw Error() +} \ No newline at end of file diff --git a/kotlin-native/backend.native/tests/codegen/function/plus_eq.kt b/kotlin-native/backend.native/tests/codegen/function/plus_eq.kt new file mode 100644 index 00000000000..b17daa93ffa --- /dev/null +++ b/kotlin-native/backend.native/tests/codegen/function/plus_eq.kt @@ -0,0 +1,18 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +package codegen.function.plus_eq + +import kotlin.test.* + +fun plus_eq(a: Int): Int { + var b = 11 + b += a + return b +} + +@Test fun runTest() { + if (plus_eq(3) != 14) throw Error() +} \ No newline at end of file diff --git a/kotlin-native/backend.native/tests/codegen/function/referenceBigArity.kt b/kotlin-native/backend.native/tests/codegen/function/referenceBigArity.kt new file mode 100644 index 00000000000..0490124f03c --- /dev/null +++ b/kotlin-native/backend.native/tests/codegen/function/referenceBigArity.kt @@ -0,0 +1,21 @@ +/* + * Copyright 2010-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +package codegen.function.referenceBigArity + +import kotlin.test.* + +fun фу(а: Int, б: Int, в: Int, г: Int, д: Int, е: Int, ё: Int, ж: Int, з: Int, и: Int, й: Int, к: Int, + л: Int, м: Int, н: Int, о: Int, п: Int, р: Int, с: Int, т: Int, у: Int, ф: Int, х: Int, ц: Int, + ч: Int, ш: Int, щ: Int, ъ: Int, ы: Int, ь: Int, э: Int, ю: Int, я: Int): Int { + return а + б + в + г + д + е + ё + ж + з + и + й + к + л + м + н + о + + п + р + с + т + у + ф + х + ц + ч + ш + щ + ъ + ы + ь + э + ю + я +} + +@Test fun runTest() { + val ref = ::фу + println(ref(0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, + 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32)) +} \ No newline at end of file diff --git a/kotlin-native/backend.native/tests/codegen/function/sum.kt b/kotlin-native/backend.native/tests/codegen/function/sum.kt new file mode 100644 index 00000000000..2c1fade5980 --- /dev/null +++ b/kotlin-native/backend.native/tests/codegen/function/sum.kt @@ -0,0 +1,27 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +package codegen.function.sum + +import kotlin.test.* + +fun sumIB(a:Int, b:Byte ) = a + b +fun sumIS(a:Int, b:Short ) = a + b +fun sumII(a:Int, b:Int ) = a + b +fun sumIL(a:Int, b:Long ) = a + b +fun sumIF(a:Int, b:Float ) = a + b +fun sumID(a:Int, b:Double) = a + b + +fun modID(a:Int, b:Double) = a % b + +@Test fun runTest() { + if (sumIB(2, 3) != 5) throw Error() + if (sumIS(2, 3) != 5) throw Error() + if (sumII(2, 3) != 5) throw Error() + if (sumIL(2, 3L) != 5L) throw Error() + if (sumIF(2, 3.0f) != 5.0f) throw Error() + if (sumID(2, 3.0) != 5.0) throw Error() + if (modID(5, 3.0) != 2.0) throw Error() +} \ No newline at end of file diff --git a/kotlin-native/backend.native/tests/codegen/function/sum_3const.kt b/kotlin-native/backend.native/tests/codegen/function/sum_3const.kt new file mode 100644 index 00000000000..10a746a23b4 --- /dev/null +++ b/kotlin-native/backend.native/tests/codegen/function/sum_3const.kt @@ -0,0 +1,15 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +package codegen.function.sum_3const + +import kotlin.test.* + +fun sum3():Int = sum(1, 2, 33) +fun sum(a:Int, b:Int, c:Int): Int = a + b + c + +@Test fun runTest() { + if (sum3() != 36) throw Error() +} \ No newline at end of file diff --git a/kotlin-native/backend.native/tests/codegen/function/sum_foo_bar.kt b/kotlin-native/backend.native/tests/codegen/function/sum_foo_bar.kt new file mode 100644 index 00000000000..7fe24b3f84a --- /dev/null +++ b/kotlin-native/backend.native/tests/codegen/function/sum_foo_bar.kt @@ -0,0 +1,17 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +package codegen.function.sum_foo_bar + +import kotlin.test.* + +fun foo(a:Int):Int = a +fun bar(a:Int):Int = a + +fun sumFooBar(a:Int, b:Int):Int = foo(a) + bar(b) + +@Test fun runTest() { + if (sumFooBar(2, 3) != 5) throw Error() +} \ No newline at end of file diff --git a/kotlin-native/backend.native/tests/codegen/function/sum_func.kt b/kotlin-native/backend.native/tests/codegen/function/sum_func.kt new file mode 100644 index 00000000000..9b1cf07d08d --- /dev/null +++ b/kotlin-native/backend.native/tests/codegen/function/sum_func.kt @@ -0,0 +1,14 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +package codegen.function.sum_func + +import kotlin.test.* + +fun foo():Int = 1 +//fun bar():Int = 2 +//fun sum():Int = foo() + bar() + +// FIXME: has no checks \ No newline at end of file diff --git a/kotlin-native/backend.native/tests/codegen/function/sum_imm.kt b/kotlin-native/backend.native/tests/codegen/function/sum_imm.kt new file mode 100644 index 00000000000..0386c2a6e21 --- /dev/null +++ b/kotlin-native/backend.native/tests/codegen/function/sum_imm.kt @@ -0,0 +1,14 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +package codegen.function.sum_imm + +import kotlin.test.* + +fun sum(a:Int): Int = a + 33 + +@Test fun runTest() { + if (sum(2) != 35) throw Error() +} \ No newline at end of file diff --git a/kotlin-native/backend.native/tests/codegen/function/sum_mixed.kt b/kotlin-native/backend.native/tests/codegen/function/sum_mixed.kt new file mode 100644 index 00000000000..9a259e37351 --- /dev/null +++ b/kotlin-native/backend.native/tests/codegen/function/sum_mixed.kt @@ -0,0 +1,11 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +package codegen.function.sum_mixed + +import kotlin.test.* + +// FIXME: has no checks +fun sum(a:Float, b:Int) = a + b \ No newline at end of file diff --git a/kotlin-native/backend.native/tests/codegen/function/sum_silly.kt b/kotlin-native/backend.native/tests/codegen/function/sum_silly.kt new file mode 100644 index 00000000000..f979af5d5c4 --- /dev/null +++ b/kotlin-native/backend.native/tests/codegen/function/sum_silly.kt @@ -0,0 +1,16 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +package codegen.function.sum_silly + +import kotlin.test.* + +// FIXME: has no checks + +fun sum(a:Int, b:Int):Int { + var c:Int + c = a + b + return c +} \ No newline at end of file diff --git a/kotlin-native/backend.native/tests/codegen/initializers/correctOrder1.kt b/kotlin-native/backend.native/tests/codegen/initializers/correctOrder1.kt new file mode 100644 index 00000000000..68121d41048 --- /dev/null +++ b/kotlin-native/backend.native/tests/codegen/initializers/correctOrder1.kt @@ -0,0 +1,22 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +package codegen.initializers.correctOrder1 + +import kotlin.test.* + +class TestClass { + val x: Int + + init { + x = 42 + } + + val y = x +} + +@Test fun runTest() { + println(TestClass().y) +} \ No newline at end of file diff --git a/kotlin-native/backend.native/tests/codegen/initializers/correctOrder2.kt b/kotlin-native/backend.native/tests/codegen/initializers/correctOrder2.kt new file mode 100644 index 00000000000..4cdfe3c99a2 --- /dev/null +++ b/kotlin-native/backend.native/tests/codegen/initializers/correctOrder2.kt @@ -0,0 +1,22 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +package codegen.initializers.correctOrder2 + +import kotlin.test.* + +class TestClass { + val x: Int + + val y = 42 + + init { + x = y + } +} + +@Test fun runTest() { + println(TestClass().x) +} \ No newline at end of file diff --git a/kotlin-native/backend.native/tests/codegen/initializers/linkTest1_lib.kt b/kotlin-native/backend.native/tests/codegen/initializers/linkTest1_lib.kt new file mode 100644 index 00000000000..145c8e0d9b3 --- /dev/null +++ b/kotlin-native/backend.native/tests/codegen/initializers/linkTest1_lib.kt @@ -0,0 +1,3 @@ +val a = 10 +val b = a * 6 +val c = a * b * 2 \ No newline at end of file diff --git a/kotlin-native/backend.native/tests/codegen/initializers/linkTest1_main.kt b/kotlin-native/backend.native/tests/codegen/initializers/linkTest1_main.kt new file mode 100644 index 00000000000..2fdafb7c6e2 --- /dev/null +++ b/kotlin-native/backend.native/tests/codegen/initializers/linkTest1_main.kt @@ -0,0 +1 @@ +fun main() = println(c) \ No newline at end of file diff --git a/kotlin-native/backend.native/tests/codegen/initializers/linkTest2_lib.kt b/kotlin-native/backend.native/tests/codegen/initializers/linkTest2_lib.kt new file mode 100644 index 00000000000..9aafbdbf060 --- /dev/null +++ b/kotlin-native/backend.native/tests/codegen/initializers/linkTest2_lib.kt @@ -0,0 +1,3 @@ +val a = mutableListOf() +val b = 1.also { a += 2 } +val c = a.single() \ No newline at end of file diff --git a/kotlin-native/backend.native/tests/codegen/initializers/linkTest2_main.kt b/kotlin-native/backend.native/tests/codegen/initializers/linkTest2_main.kt new file mode 100644 index 00000000000..2fdafb7c6e2 --- /dev/null +++ b/kotlin-native/backend.native/tests/codegen/initializers/linkTest2_main.kt @@ -0,0 +1 @@ +fun main() = println(c) \ No newline at end of file diff --git a/kotlin-native/backend.native/tests/codegen/initializers/sharedVarInInitBlock_lib.kt b/kotlin-native/backend.native/tests/codegen/initializers/sharedVarInInitBlock_lib.kt new file mode 100644 index 00000000000..641e7def76b --- /dev/null +++ b/kotlin-native/backend.native/tests/codegen/initializers/sharedVarInInitBlock_lib.kt @@ -0,0 +1,13 @@ +class A { + val x: Int + + init { + var y = 10 + + fun foo() { y = 42 } + + foo() + + x = y + } +} \ No newline at end of file diff --git a/kotlin-native/backend.native/tests/codegen/initializers/sharedVarInInitBlock_main.kt b/kotlin-native/backend.native/tests/codegen/initializers/sharedVarInInitBlock_main.kt new file mode 100644 index 00000000000..8a1b4f274f2 --- /dev/null +++ b/kotlin-native/backend.native/tests/codegen/initializers/sharedVarInInitBlock_main.kt @@ -0,0 +1,3 @@ +import kotlin.test.* + +fun main() = assertEquals(42, (A().x)) \ No newline at end of file diff --git a/kotlin-native/backend.native/tests/codegen/inline/changingCapturedLocal.kt b/kotlin-native/backend.native/tests/codegen/inline/changingCapturedLocal.kt new file mode 100644 index 00000000000..81f70318bb4 --- /dev/null +++ b/kotlin-native/backend.native/tests/codegen/inline/changingCapturedLocal.kt @@ -0,0 +1,30 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +package codegen.inline.changingCapturedLocal + +import kotlin.test.* + +var log = "" + +inline fun foo(x: Int, action: (Int) -> Unit) = action(x) + +fun box(): String { + var x = 23 + foo(x) { + log += "$it;" + x++ + log += "$it;" + } + + if (log != "23;23;") return "fail1: $log" + if (x != 24) return "fail2: $x" + + return "OK" +} + +@Test fun runTest() { + println(box()) +} \ No newline at end of file diff --git a/kotlin-native/backend.native/tests/codegen/inline/classDeclarationInsideInline.kt b/kotlin-native/backend.native/tests/codegen/inline/classDeclarationInsideInline.kt new file mode 100644 index 00000000000..f4a8593709f --- /dev/null +++ b/kotlin-native/backend.native/tests/codegen/inline/classDeclarationInsideInline.kt @@ -0,0 +1,29 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +package codegen.inline.classDeclarationInsideInline + +import kotlin.test.* + +fun f() { + run { + class Test1(val x: T, val y: G) { + override fun toString() = "test1: ${x.toDouble()}" + } + + class Test2(val a: Test1) { + override fun toString() = "test2" + } + + val v = Test2(Test1(1, Test2(Test1(1, 3)))) + println(v.a) + println(v.a.x) + println(v.a.y) + } +} + +@Test fun test() { + f() +} diff --git a/kotlin-native/backend.native/tests/codegen/inline/coercionToUnit.kt b/kotlin-native/backend.native/tests/codegen/inline/coercionToUnit.kt new file mode 100644 index 00000000000..58f8700156d --- /dev/null +++ b/kotlin-native/backend.native/tests/codegen/inline/coercionToUnit.kt @@ -0,0 +1,22 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +package codegen.inline.coercionToUnit + +import kotlin.test.* + +fun myRun(action: () -> T): T = action() + +fun foo(n: Number, b: Boolean) { + n.let { + if (b) return@let + + myRun() { 42 } + } +} + +@Test fun runTest() { + println(foo(42, false)) +} diff --git a/kotlin-native/backend.native/tests/codegen/inline/correctOrderFunctionReference.kt b/kotlin-native/backend.native/tests/codegen/inline/correctOrderFunctionReference.kt new file mode 100644 index 00000000000..bd99d731e0b --- /dev/null +++ b/kotlin-native/backend.native/tests/codegen/inline/correctOrderFunctionReference.kt @@ -0,0 +1,40 @@ +/* + * Copyright 2010-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +package codegen.inline.correctOrderFunctionReference + +import kotlin.test.* + +class Foo(val a: String) { + + fun test() = a +} + +inline fun test(a: String, b: () -> String, c: () -> String, d: () -> String, e: String): String { + return a + b() + c() + d() + e +} + +var effects = "" + +fun create(a: String): Foo { + effects += a + return Foo(a) +} + +fun create2(a: String, f: () -> String): Foo { + effects += a + return Foo(a) +} + +fun box(): String { + val result = test(create("A").a, create("B")::a, create("C")::test, create2("E", create("D")::test)::test, create("F").a) + if (effects != "ABCDEF") return "fail 1: $effects" + + return if (result == "ABCEF") "OK" else "fail 2: $result" +} + +@Test fun runTest() { + println(box()) +} \ No newline at end of file diff --git a/kotlin-native/backend.native/tests/codegen/inline/defaultArgs.kt b/kotlin-native/backend.native/tests/codegen/inline/defaultArgs.kt new file mode 100644 index 00000000000..9dd0fd07f4f --- /dev/null +++ b/kotlin-native/backend.native/tests/codegen/inline/defaultArgs.kt @@ -0,0 +1,19 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +package codegen.inline.defaultArgs + +import kotlin.test.* + +class Z + +inline fun Z.foo(x: Int = 42, y: Int = x) { + println(y) +} + +@Test fun runTest() { + val z = Z() + z.foo() +} \ No newline at end of file diff --git a/kotlin-native/backend.native/tests/codegen/inline/defaultArgs_linkTest_lib.kt b/kotlin-native/backend.native/tests/codegen/inline/defaultArgs_linkTest_lib.kt new file mode 100644 index 00000000000..c8053f8c38a --- /dev/null +++ b/kotlin-native/backend.native/tests/codegen/inline/defaultArgs_linkTest_lib.kt @@ -0,0 +1,8 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +package a + +inline fun foo(x: Int, y: Int = 117) = x + y \ No newline at end of file diff --git a/kotlin-native/backend.native/tests/codegen/inline/defaultArgs_linkTest_main.kt b/kotlin-native/backend.native/tests/codegen/inline/defaultArgs_linkTest_main.kt new file mode 100644 index 00000000000..f8ed29ab609 --- /dev/null +++ b/kotlin-native/backend.native/tests/codegen/inline/defaultArgs_linkTest_main.kt @@ -0,0 +1,11 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +import a.* + +fun main(args: Array) { + println(foo(5)) + println(foo(5, 42)) +} \ No newline at end of file diff --git a/kotlin-native/backend.native/tests/codegen/inline/genericFunctionReference.kt b/kotlin-native/backend.native/tests/codegen/inline/genericFunctionReference.kt new file mode 100644 index 00000000000..70ec4e151b0 --- /dev/null +++ b/kotlin-native/backend.native/tests/codegen/inline/genericFunctionReference.kt @@ -0,0 +1,19 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +package codegen.inline.genericFunctionReference + +import kotlin.test.* + +class Z(val x: T) + +inline fun foo(x: T, f: (T) -> R): R { + return f(x) +} + +@Test fun runTest() { + val arr = Array(1) { foo(it, ::Z) } + println(arr[0].x) +} \ No newline at end of file diff --git a/kotlin-native/backend.native/tests/codegen/inline/getClass.kt b/kotlin-native/backend.native/tests/codegen/inline/getClass.kt new file mode 100644 index 00000000000..e2fad509b1a --- /dev/null +++ b/kotlin-native/backend.native/tests/codegen/inline/getClass.kt @@ -0,0 +1,23 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +package codegen.inline.getClass + +import kotlin.test.* + +fun foo() { + val cls1: Any? = Int + val cls2: Any? = null + + cls1?.let { + cls2?.let { + var itClass = it::class + } + } +} + +@Test fun runTest() { + println("OK") +} diff --git a/kotlin-native/backend.native/tests/codegen/inline/inline0.kt b/kotlin-native/backend.native/tests/codegen/inline/inline0.kt new file mode 100644 index 00000000000..d90b7766d7b --- /dev/null +++ b/kotlin-native/backend.native/tests/codegen/inline/inline0.kt @@ -0,0 +1,22 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +package codegen.inline.inline0 + +import kotlin.test.* + +@Suppress("NOTHING_TO_INLINE") +inline fun foo(i1: Int, j1: Int): Int { + return i1 + j1 +} + +fun bar(i: Int, j: Int): Int { + return i + foo(i, j) +} + +@Test fun runTest() { + println(bar(41, 2).toString()) +} + diff --git a/kotlin-native/backend.native/tests/codegen/inline/inline1.kt b/kotlin-native/backend.native/tests/codegen/inline/inline1.kt new file mode 100644 index 00000000000..86ac21dea9f --- /dev/null +++ b/kotlin-native/backend.native/tests/codegen/inline/inline1.kt @@ -0,0 +1,23 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +package codegen.inline.inline1 + +import kotlin.test.* + +@Suppress("NOTHING_TO_INLINE") +inline fun foo(s4: String, s5: String): String { + return s4 + s5 +} + +fun bar(s1: String, s2: String, s3: String): String { + return s1 + foo(s2, s3) +} + +@Test fun runTest() { + println(bar("Hello ", "wor", "ld")) +} + + diff --git a/kotlin-native/backend.native/tests/codegen/inline/inline10.kt b/kotlin-native/backend.native/tests/codegen/inline/inline10.kt new file mode 100644 index 00000000000..de24425676e --- /dev/null +++ b/kotlin-native/backend.native/tests/codegen/inline/inline10.kt @@ -0,0 +1,21 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +package codegen.inline.inline10 + +import kotlin.test.* + +@Suppress("NOTHING_TO_INLINE") +inline fun foo(i2: Int, body: () -> Int): Int { + return i2 + body() +} + +fun bar(i1: Int): Int { + return foo(i1) { 1 } +} + +@Test fun runTest() { + println(bar(1).toString()) +} diff --git a/kotlin-native/backend.native/tests/codegen/inline/inline11.kt b/kotlin-native/backend.native/tests/codegen/inline/inline11.kt new file mode 100644 index 00000000000..76c87f91bb0 --- /dev/null +++ b/kotlin-native/backend.native/tests/codegen/inline/inline11.kt @@ -0,0 +1,21 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +package codegen.inline.inline11 + +import kotlin.test.* + +@Suppress("NOTHING_TO_INLINE") +inline fun foo (i2: Any): Boolean { + return i2 is T +} + +fun bar(i1: Int): Boolean { + return foo(i1) +} + +@Test fun runTest() { + println(bar(1).toString()) +} diff --git a/kotlin-native/backend.native/tests/codegen/inline/inline12.kt b/kotlin-native/backend.native/tests/codegen/inline/inline12.kt new file mode 100644 index 00000000000..2ad95d86140 --- /dev/null +++ b/kotlin-native/backend.native/tests/codegen/inline/inline12.kt @@ -0,0 +1,21 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +package codegen.inline.inline12 + +import kotlin.test.* + +@Suppress("NOTHING_TO_INLINE") +inline fun foo (): Boolean { + return Any() is Any +} + +fun bar(i1: Int): Boolean { + return foo() +} + +@Test fun runTest() { + println(bar(1).toString()) +} diff --git a/kotlin-native/backend.native/tests/codegen/inline/inline13.kt b/kotlin-native/backend.native/tests/codegen/inline/inline13.kt new file mode 100644 index 00000000000..9c8b5842299 --- /dev/null +++ b/kotlin-native/backend.native/tests/codegen/inline/inline13.kt @@ -0,0 +1,24 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +package codegen.inline.inline13 + +import kotlin.test.* + +open class A() +class B() : A() + +@Suppress("NOTHING_TO_INLINE") +inline fun > foo(f: Any?): Boolean { + return f is T? +} + +fun bar(): Boolean { + return foo>(B()) +} + +@Test fun runTest() { + println(bar().toString()) +} diff --git a/kotlin-native/backend.native/tests/codegen/inline/inline14.kt b/kotlin-native/backend.native/tests/codegen/inline/inline14.kt new file mode 100644 index 00000000000..0c53e64df7e --- /dev/null +++ b/kotlin-native/backend.native/tests/codegen/inline/inline14.kt @@ -0,0 +1,31 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +package codegen.inline.inline14 + +import kotlin.test.* + +@Suppress("NOTHING_TO_INLINE") +inline fun foo3(i3: Int): Int { + return i3 + 3 +} + +@Suppress("NOTHING_TO_INLINE") +inline fun foo2(i2: Int): Int { + return i2 + 2 +} + +@Suppress("NOTHING_TO_INLINE") +inline fun foo1(i1: Int): Int { + return foo2(i1) +} + +fun bar(i0: Int): Int { + return foo1(i0) + foo3(i0) +} + +@Test fun runTest() { + println(bar(2).toString()) +} diff --git a/kotlin-native/backend.native/tests/codegen/inline/inline15.kt b/kotlin-native/backend.native/tests/codegen/inline/inline15.kt new file mode 100644 index 00000000000..8c0ccfc781c --- /dev/null +++ b/kotlin-native/backend.native/tests/codegen/inline/inline15.kt @@ -0,0 +1,26 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +package codegen.inline.inline15 + +import kotlin.test.* + +@Suppress("NOTHING_TO_INLINE") +inline fun foo2(i1: Int): Int { + return i1 + 1 +} + +@Suppress("NOTHING_TO_INLINE") +inline fun foo1(i1: Int, body: (Int) -> Int): Int { + return body(i1) +} + +fun bar(i0: Int): Int { + return foo1(i0) { foo2(it) + 1 } +} + +@Test fun runTest() { + println(bar(2).toString()) +} diff --git a/kotlin-native/backend.native/tests/codegen/inline/inline16.kt b/kotlin-native/backend.native/tests/codegen/inline/inline16.kt new file mode 100644 index 00000000000..a012bdedd09 --- /dev/null +++ b/kotlin-native/backend.native/tests/codegen/inline/inline16.kt @@ -0,0 +1,26 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +package codegen.inline.inline16 + +import kotlin.test.* + +@Suppress("NOTHING_TO_INLINE") +inline fun > foo(destination: C, predicate: (T) -> Boolean): C { + for (element in destination) { + val value = element as T + if (!predicate(value)) destination.add(value) + } + return destination +} + +fun bar(): Boolean { + val result = foo > (mutableListOf(1, 2, 3)) { true } + return result.isEmpty() +} + +@Test fun runTest() { + println(bar().toString()) +} diff --git a/kotlin-native/backend.native/tests/codegen/inline/inline17.kt b/kotlin-native/backend.native/tests/codegen/inline/inline17.kt new file mode 100644 index 00000000000..2b495048141 --- /dev/null +++ b/kotlin-native/backend.native/tests/codegen/inline/inline17.kt @@ -0,0 +1,23 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +package codegen.inline.inline17 + +import kotlin.test.* + +@Suppress("NOTHING_TO_INLINE") +inline fun foo(i1: T, i2: T): List { + val j1 = i1 + val j2 = i2 + return listOf(j1, j2) +} + +fun bar(): List { + return foo (1, 2) +} + +@Test fun runTest() { + println(bar().toString()) +} diff --git a/kotlin-native/backend.native/tests/codegen/inline/inline18.kt b/kotlin-native/backend.native/tests/codegen/inline/inline18.kt new file mode 100644 index 00000000000..33370f84983 --- /dev/null +++ b/kotlin-native/backend.native/tests/codegen/inline/inline18.kt @@ -0,0 +1,27 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +package codegen.inline.inline18 + +import kotlin.test.* + +@Suppress("NOTHING_TO_INLINE") +inline fun foo2(i2: T, j2: T, p2: (T, T) -> Boolean): Boolean { + return p2(i2, j2) +} + +@Suppress("NOTHING_TO_INLINE") +inline fun foo1(i1: T, j1: T, p1: (T, T) -> Boolean): Boolean { + return foo2(i1, j1, p1) +} + +fun bar(): Boolean { + val result = foo1 (3, 3) { x1: Int, x2: Int -> x1 == x2 } + return result +} + +@Test fun runTest() { + println(bar().toString()) +} diff --git a/kotlin-native/backend.native/tests/codegen/inline/inline19.kt b/kotlin-native/backend.native/tests/codegen/inline/inline19.kt new file mode 100644 index 00000000000..f5bb1377a88 --- /dev/null +++ b/kotlin-native/backend.native/tests/codegen/inline/inline19.kt @@ -0,0 +1,23 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +package codegen.inline.inline19 + +import kotlin.test.* + +@Suppress("NOTHING_TO_INLINE") +inline private fun foo(i: Int): Int { + val result = i + return result + i +} + +fun bar(): Int { + return foo(1) + foo(2) +} + +@Test fun runTest() { + println(bar().toString()) +} + diff --git a/kotlin-native/backend.native/tests/codegen/inline/inline2.kt b/kotlin-native/backend.native/tests/codegen/inline/inline2.kt new file mode 100644 index 00000000000..4b0c31e8099 --- /dev/null +++ b/kotlin-native/backend.native/tests/codegen/inline/inline2.kt @@ -0,0 +1,21 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +package codegen.inline.inline2 + +import kotlin.test.* + +@Suppress("NOTHING_TO_INLINE") +inline fun foo(i4: Int, i5: Int) { + println("hello $i4 $i5") +} + +fun bar(i1: Int, i2: Int) { + foo(i1, i2) +} + +@Test fun runTest() { + bar(1, 8) +} diff --git a/kotlin-native/backend.native/tests/codegen/inline/inline20.kt b/kotlin-native/backend.native/tests/codegen/inline/inline20.kt new file mode 100644 index 00000000000..68cc6e21f1d --- /dev/null +++ b/kotlin-native/backend.native/tests/codegen/inline/inline20.kt @@ -0,0 +1,21 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +package codegen.inline.inline20 + +import kotlin.test.* + +@Suppress("NOTHING_TO_INLINE") +inline fun bar(block: () -> String) : String { + return block() +} + +fun bar2() : String { + return bar { return "def" } +} + +@Test fun runTest() { + println(bar2()) +} diff --git a/kotlin-native/backend.native/tests/codegen/inline/inline21.kt b/kotlin-native/backend.native/tests/codegen/inline/inline21.kt new file mode 100644 index 00000000000..cf0ec4e5a9d --- /dev/null +++ b/kotlin-native/backend.native/tests/codegen/inline/inline21.kt @@ -0,0 +1,27 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +package codegen.inline.inline21 + +import kotlin.test.* + +inline fun foo2(block2: () -> Int) : Int { + println("foo2") + return block2() +} + +inline fun foo1(block1: () -> Int) : Int { + println("foo1") + return foo2(block1) +} + +fun bar(block: () -> Int) : Int { + println("bar") + return foo1(block) +} + +@Test fun runTest() { + println(bar { 33 }) +} diff --git a/kotlin-native/backend.native/tests/codegen/inline/inline22.kt b/kotlin-native/backend.native/tests/codegen/inline/inline22.kt new file mode 100644 index 00000000000..ff016b849be --- /dev/null +++ b/kotlin-native/backend.native/tests/codegen/inline/inline22.kt @@ -0,0 +1,24 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +package codegen.inline.inline22 + +import kotlin.test.* + +inline fun foo2(i2: Int): Int { + return i2 + 3 +} + +inline fun foo1(i1: Int): Int { + return foo2(i1) +} + +fun bar(): Int { + return foo1(11) +} + +@Test fun runTest() { + println(bar().toString()) +} diff --git a/kotlin-native/backend.native/tests/codegen/inline/inline23.kt b/kotlin-native/backend.native/tests/codegen/inline/inline23.kt new file mode 100644 index 00000000000..8ddbd638b74 --- /dev/null +++ b/kotlin-native/backend.native/tests/codegen/inline/inline23.kt @@ -0,0 +1,20 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +package codegen.inline.inline23 + +import kotlin.test.* + +inline fun foo(i2: Any): T { + return i2 as T +} + +fun bar(i1: Int): Int { + return foo(i1) +} + +@Test fun runTest() { + println(bar(33)) +} diff --git a/kotlin-native/backend.native/tests/codegen/inline/inline24.kt b/kotlin-native/backend.native/tests/codegen/inline/inline24.kt new file mode 100644 index 00000000000..43117aaf984 --- /dev/null +++ b/kotlin-native/backend.native/tests/codegen/inline/inline24.kt @@ -0,0 +1,17 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +package codegen.inline.inline24 + +import kotlin.test.* + +fun foo() = println("foo") +fun bar() = println("bar") + +inline fun baz(x: Unit = foo(), y: Unit) {} + +@Test fun runTest() { + baz(y = bar()) +} diff --git a/kotlin-native/backend.native/tests/codegen/inline/inline25.kt b/kotlin-native/backend.native/tests/codegen/inline/inline25.kt new file mode 100644 index 00000000000..bb312a4d6d2 --- /dev/null +++ b/kotlin-native/backend.native/tests/codegen/inline/inline25.kt @@ -0,0 +1,30 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +package codegen.inline.inline25 + +import kotlin.test.* + +inline fun foo(block: String.() -> Unit) { + "Ok".block() +} + +inline fun bar(block: (String) -> Unit) { + foo(block) +} + +inline fun baz(block: String.() -> Unit) { + block("Ok") +} + +@Test fun runTest() { + bar { + println(it) + } + + baz { + println(this) + } +} diff --git a/kotlin-native/backend.native/tests/codegen/inline/inline26.kt b/kotlin-native/backend.native/tests/codegen/inline/inline26.kt new file mode 100644 index 00000000000..cdc22a1faa5 --- /dev/null +++ b/kotlin-native/backend.native/tests/codegen/inline/inline26.kt @@ -0,0 +1,18 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +package codegen.inline.inline26 + +import kotlin.test.* + +inline fun call(block1: () -> Unit, noinline block2: () -> Int): Int { + block1() + return block2() +} + +@Test fun runTest() { + var x = 5 + println(call({ x = 7 }, x::toInt)) +} diff --git a/kotlin-native/backend.native/tests/codegen/inline/inline3.kt b/kotlin-native/backend.native/tests/codegen/inline/inline3.kt new file mode 100644 index 00000000000..44078dbdd99 --- /dev/null +++ b/kotlin-native/backend.native/tests/codegen/inline/inline3.kt @@ -0,0 +1,25 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +package codegen.inline.inline3 + +import kotlin.test.* + +@Suppress("NOTHING_TO_INLINE") +inline fun foo(i4: Int, i5: Int): Int { + try { + return i4 / i5 + } catch (e: Throwable) { + return i4 + } +} + +fun bar(i1: Int, i2: Int, i3: Int): Int { + return i1 + foo(i2, i3) +} + +@Test fun runTest() { + println(bar(1, 8, 2).toString()) +} diff --git a/kotlin-native/backend.native/tests/codegen/inline/inline4.kt b/kotlin-native/backend.native/tests/codegen/inline/inline4.kt new file mode 100644 index 00000000000..b04b86c9e60 --- /dev/null +++ b/kotlin-native/backend.native/tests/codegen/inline/inline4.kt @@ -0,0 +1,22 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +package codegen.inline.inline4 + +import kotlin.test.* + +@Suppress("NOTHING_TO_INLINE") +inline fun foo(i4: Int, i5: Int): Int { + if (i4 > 0) return i4 + return i5 +} + +fun bar(i1: Int, i2: Int): Int { + return foo(i1, i2) +} + +@Test fun runTest() { + println(bar(3, 8).toString()) +} diff --git a/kotlin-native/backend.native/tests/codegen/inline/inline5.kt b/kotlin-native/backend.native/tests/codegen/inline/inline5.kt new file mode 100644 index 00000000000..1e53d894c47 --- /dev/null +++ b/kotlin-native/backend.native/tests/codegen/inline/inline5.kt @@ -0,0 +1,22 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +package codegen.inline.inline5 + +import kotlin.test.* + +@Suppress("NOTHING_TO_INLINE") +inline fun foo(i2: Int, body: () -> Int): Int { + return i2 + body() +} + +fun bar(i1: Int): Int { + return foo(i1) { return 33 } +} + +@Test fun runTest() { + println(bar(1).toString()) +} + diff --git a/kotlin-native/backend.native/tests/codegen/inline/inline6.kt b/kotlin-native/backend.native/tests/codegen/inline/inline6.kt new file mode 100644 index 00000000000..2a518ccc075 --- /dev/null +++ b/kotlin-native/backend.native/tests/codegen/inline/inline6.kt @@ -0,0 +1,26 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +package codegen.inline.inline6 + +import kotlin.test.* + +@Suppress("NOTHING_TO_INLINE") +inline fun foo(body: () -> Unit) { + println("hello1") + body() + println("hello4") +} + +fun bar() { + foo { + println("hello2") + println("hello3") + } +} + +@Test fun runTest() { + bar() +} diff --git a/kotlin-native/backend.native/tests/codegen/inline/inline7.kt b/kotlin-native/backend.native/tests/codegen/inline/inline7.kt new file mode 100644 index 00000000000..1f1423a3fa0 --- /dev/null +++ b/kotlin-native/backend.native/tests/codegen/inline/inline7.kt @@ -0,0 +1,23 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +package codegen.inline.inline7 + +import kotlin.test.* + +@Suppress("NOTHING_TO_INLINE") +inline fun foo(vararg args: Int) { + for (a in args) { + println(a.toString()) + } +} + +fun bar() { + foo(1, 2, 3) +} + +@Test fun runTest() { + bar() +} diff --git a/kotlin-native/backend.native/tests/codegen/inline/inline8.kt b/kotlin-native/backend.native/tests/codegen/inline/inline8.kt new file mode 100644 index 00000000000..c47e535e783 --- /dev/null +++ b/kotlin-native/backend.native/tests/codegen/inline/inline8.kt @@ -0,0 +1,21 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +package codegen.inline.inline8 + +import kotlin.test.* + +@Suppress("NOTHING_TO_INLINE") +inline fun foo(i3: Int, i4: Int) : Int { + return i3 + i3 + i4 +} + +fun bar(i1: Int, i2: Int) : Int { + return foo(i1 + i2, 2) +} + +@Test fun runTest() { + println(bar(1, 2).toString()) +} diff --git a/kotlin-native/backend.native/tests/codegen/inline/inline9.kt b/kotlin-native/backend.native/tests/codegen/inline/inline9.kt new file mode 100644 index 00000000000..f5fb36286ad --- /dev/null +++ b/kotlin-native/backend.native/tests/codegen/inline/inline9.kt @@ -0,0 +1,26 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +package codegen.inline.inline9 + +import kotlin.test.* + +@Suppress("NOTHING_TO_INLINE") +inline fun foo(i3: Int, i4: Int): Int { + return i3 + i3 + i4 +} + +fun quiz(i: Int) : Int { + println("hello") + return i + 1 +} + +fun bar(i1: Int, i2: Int): Int { + return foo(quiz(i1), i2) +} + +@Test fun runTest() { + println(bar(1, 2).toString()) +} diff --git a/kotlin-native/backend.native/tests/codegen/inline/inlineCtor_linkTest_lib.kt b/kotlin-native/backend.native/tests/codegen/inline/inlineCtor_linkTest_lib.kt new file mode 100644 index 00000000000..5c6a2059f97 --- /dev/null +++ b/kotlin-native/backend.native/tests/codegen/inline/inlineCtor_linkTest_lib.kt @@ -0,0 +1,13 @@ +/* + * Copyright 2010-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +package a + +fun foo(n: Int, block: (Int) -> Int): Int { + val arr = IntArray(n) { block(it) } + var sum = 0 + for (x in arr) sum += x + return sum +} \ No newline at end of file diff --git a/kotlin-native/backend.native/tests/codegen/inline/inlineCtor_linkTest_main.kt b/kotlin-native/backend.native/tests/codegen/inline/inlineCtor_linkTest_main.kt new file mode 100644 index 00000000000..6281b09a7d5 --- /dev/null +++ b/kotlin-native/backend.native/tests/codegen/inline/inlineCtor_linkTest_main.kt @@ -0,0 +1,11 @@ +/* + * Copyright 2010-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +import a.* +import kotlin.test.* + +fun main() { + assertEquals(42, foo(7) { it * 2 }) +} \ No newline at end of file diff --git a/kotlin-native/backend.native/tests/codegen/inline/lambdaAsAny.kt b/kotlin-native/backend.native/tests/codegen/inline/lambdaAsAny.kt new file mode 100644 index 00000000000..7e99a5286e7 --- /dev/null +++ b/kotlin-native/backend.native/tests/codegen/inline/lambdaAsAny.kt @@ -0,0 +1,16 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +package codegen.inline.lambdaAsAny + +import kotlin.test.* + +inline fun foo(x: Any) { + println(if (x === x) "Ok" else "Fail") +} + +@Test fun runTest() { + foo { 42 } +} \ No newline at end of file diff --git a/kotlin-native/backend.native/tests/codegen/inline/lambdaInDefaultValue.kt b/kotlin-native/backend.native/tests/codegen/inline/lambdaInDefaultValue.kt new file mode 100644 index 00000000000..e9530a314f2 --- /dev/null +++ b/kotlin-native/backend.native/tests/codegen/inline/lambdaInDefaultValue.kt @@ -0,0 +1,20 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +package codegen.inline.lambdaInDefaultValue + +import kotlin.test.* + +inline fun inlineFun(param: String, lambda: (String) -> String = { it }): String { + return lambda(param) +} + +fun box(): String { + return inlineFun("OK") +} + +@Test fun runTest() { + println(box()) +} \ No newline at end of file diff --git a/kotlin-native/backend.native/tests/codegen/inline/lateinitProperty_linkTest_lib.kt b/kotlin-native/backend.native/tests/codegen/inline/lateinitProperty_linkTest_lib.kt new file mode 100644 index 00000000000..abfed1ee210 --- /dev/null +++ b/kotlin-native/backend.native/tests/codegen/inline/lateinitProperty_linkTest_lib.kt @@ -0,0 +1,19 @@ +/* + * Copyright 2010-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +package a + +fun IntArray.forEachNoInline(block: (Int) -> Unit) = this.forEach { block(it) } + +inline fun foo(values: IntArray, crossinline block: (Int, Int, Int) -> Int): Int { + val o = object { + lateinit var s: String + var x: Int = 42 + } + values.forEachNoInline { + o.x = block(o.x, o.s.length, it) + } + return o.x +} \ No newline at end of file diff --git a/kotlin-native/backend.native/tests/codegen/inline/lateinitProperty_linkTest_main.kt b/kotlin-native/backend.native/tests/codegen/inline/lateinitProperty_linkTest_main.kt new file mode 100644 index 00000000000..d4b1cb03c17 --- /dev/null +++ b/kotlin-native/backend.native/tests/codegen/inline/lateinitProperty_linkTest_main.kt @@ -0,0 +1,15 @@ +/* + * Copyright 2010-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +import a.* + +fun main() { + try { + val res = foo(intArrayOf(1, 2, 3)) { x, y, z -> x + y - z } + println(res) + } catch (t: UninitializedPropertyAccessException) { + println("OK") + } +} \ No newline at end of file diff --git a/kotlin-native/backend.native/tests/codegen/inline/localFunctionInInitializerBlock.kt b/kotlin-native/backend.native/tests/codegen/inline/localFunctionInInitializerBlock.kt new file mode 100644 index 00000000000..c6f531fd938 --- /dev/null +++ b/kotlin-native/backend.native/tests/codegen/inline/localFunctionInInitializerBlock.kt @@ -0,0 +1,22 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +package codegen.inline.localFunctionInInitializerBlock + +import kotlin.test.* + +class Foo { + init { + bar() + } +} + +inline fun bar() { + println({ "Ok" }()) +} + +@Test fun runTest() { + Foo() +} \ No newline at end of file diff --git a/kotlin-native/backend.native/tests/codegen/inline/localObjectReturnedFromWhen.kt b/kotlin-native/backend.native/tests/codegen/inline/localObjectReturnedFromWhen.kt new file mode 100644 index 00000000000..ec7266de504 --- /dev/null +++ b/kotlin-native/backend.native/tests/codegen/inline/localObjectReturnedFromWhen.kt @@ -0,0 +1,21 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +package codegen.inline.localObjectReturnedFromWhen + +import kotlin.test.* + +fun foo() { + 123?.let { + object : () -> Unit { + override fun invoke() = Unit + } + } +} + +@Test fun runTest() { + foo() + println("Ok") +} \ No newline at end of file diff --git a/kotlin-native/backend.native/tests/codegen/inline/returnLocalClassFromBlock.kt b/kotlin-native/backend.native/tests/codegen/inline/returnLocalClassFromBlock.kt new file mode 100644 index 00000000000..f8c90fa05dd --- /dev/null +++ b/kotlin-native/backend.native/tests/codegen/inline/returnLocalClassFromBlock.kt @@ -0,0 +1,20 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +package codegen.inline.returnLocalClassFromBlock + +import kotlin.test.* + +inline fun call(block: ()->R): R { + try { + return block() + } finally { + println("Zzz") + } +} + +@Test fun runTest() { + call { class Z(); Z() } +} diff --git a/kotlin-native/backend.native/tests/codegen/inline/sharedVar_linkTest_lib.kt b/kotlin-native/backend.native/tests/codegen/inline/sharedVar_linkTest_lib.kt new file mode 100644 index 00000000000..e27fc6f994d --- /dev/null +++ b/kotlin-native/backend.native/tests/codegen/inline/sharedVar_linkTest_lib.kt @@ -0,0 +1,16 @@ +/* + * Copyright 2010-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +package a + +fun IntArray.forEachNoInline(block: (Int) -> Unit) = this.forEach { block(it) } + +inline fun fold(initial: Int, values: IntArray, crossinline block: (Int, Int) -> Int): Int { + var res = initial + values.forEachNoInline { + res = block(res, it) + } + return res +} \ No newline at end of file diff --git a/kotlin-native/backend.native/tests/codegen/inline/sharedVar_linkTest_main.kt b/kotlin-native/backend.native/tests/codegen/inline/sharedVar_linkTest_main.kt new file mode 100644 index 00000000000..f5d4b0788a1 --- /dev/null +++ b/kotlin-native/backend.native/tests/codegen/inline/sharedVar_linkTest_main.kt @@ -0,0 +1,10 @@ +/* + * Copyright 2010-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +import a.* + +fun main() { + println(fold(0, intArrayOf(1, 2, 3)) { x, y -> x + y }) +} \ No newline at end of file diff --git a/kotlin-native/backend.native/tests/codegen/inline/statementAsLastExprInBlock.kt b/kotlin-native/backend.native/tests/codegen/inline/statementAsLastExprInBlock.kt new file mode 100644 index 00000000000..91ab477ae6f --- /dev/null +++ b/kotlin-native/backend.native/tests/codegen/inline/statementAsLastExprInBlock.kt @@ -0,0 +1,23 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +package codegen.inline.statementAsLastExprInBlock + +import kotlin.test.* + +fun foo() { + val cls1: Any? = Int + val cls2: Any? = null + + cls1?.let { + if (cls2 != null) { + val zzz = 42 + } + } +} + +@Test fun runTest() { + println("OK") +} diff --git a/kotlin-native/backend.native/tests/codegen/inline/twiceInlinedObject.kt b/kotlin-native/backend.native/tests/codegen/inline/twiceInlinedObject.kt new file mode 100644 index 00000000000..f84ea764905 --- /dev/null +++ b/kotlin-native/backend.native/tests/codegen/inline/twiceInlinedObject.kt @@ -0,0 +1,28 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +package codegen.inline.twiceInlinedObject + +import kotlin.test.* + +inline fun exec(f: () -> Unit) = f() + +inline fun test2() { + val obj = object { + fun sayOk() = println("Ok") + } + obj.sayOk() +} + +inline fun noExec(f: () -> Unit) { } + +@Test fun runTest() { + exec { + test2() + } + noExec { + test2() + } +} \ No newline at end of file diff --git a/kotlin-native/backend.native/tests/codegen/inline/typeSubstitutionInFakeOverride.kt b/kotlin-native/backend.native/tests/codegen/inline/typeSubstitutionInFakeOverride.kt new file mode 100644 index 00000000000..e21719860ca --- /dev/null +++ b/kotlin-native/backend.native/tests/codegen/inline/typeSubstitutionInFakeOverride.kt @@ -0,0 +1,26 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +package codegen.inline.typeSubstitutionInFakeOverride + +import kotlin.test.* + +abstract class A { + inline fun baz(): String { + return T::class.simpleName!! + } +} + +class B : A() { + fun bar(): String { + return baz() + } +} + +class OK + +@Test fun runTest() { + println(B().bar()) +} \ No newline at end of file diff --git a/kotlin-native/backend.native/tests/codegen/inlineClass/customEquals.kt b/kotlin-native/backend.native/tests/codegen/inlineClass/customEquals.kt new file mode 100644 index 00000000000..03b447b43d3 --- /dev/null +++ b/kotlin-native/backend.native/tests/codegen/inlineClass/customEquals.kt @@ -0,0 +1,16 @@ +/* + * Copyright 2010-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ +@file:Suppress("RESERVED_MEMBER_INSIDE_INLINE_CLASS") +package codegen.inlineClass.customEquals + +import kotlin.test.* + +private inline class Z(val data: Int) { + override fun equals(other: Any?) = other is Z && data % 256 == other.data % 256 +} + +@Test fun runTest() { + assertTrue(Z(0) == Z(256)) +} diff --git a/kotlin-native/backend.native/tests/codegen/inlineClass/defaultEquals.kt b/kotlin-native/backend.native/tests/codegen/inlineClass/defaultEquals.kt new file mode 100644 index 00000000000..8fa1792eb29 --- /dev/null +++ b/kotlin-native/backend.native/tests/codegen/inlineClass/defaultEquals.kt @@ -0,0 +1,24 @@ +/* + * Copyright 2010-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +package codegen.inlineClass.defaultEquals + +import kotlin.test.* + +inline class A(val x: Int) +inline class B(val a: A) +inline class C(val s: String) +inline class D(val c: C) + +@Test fun runTest() { + val a = A(42) + val b = B(a) + val c = C("zzz") + val d = D(c) + assertTrue(a.equals(a)) + assertTrue(b.equals(b)) + assertTrue(c.equals(c)) + assertTrue(d.equals(d)) +} diff --git a/kotlin-native/backend.native/tests/codegen/inlineClass/inlineClass0.kt b/kotlin-native/backend.native/tests/codegen/inlineClass/inlineClass0.kt new file mode 100644 index 00000000000..d4204320bc2 --- /dev/null +++ b/kotlin-native/backend.native/tests/codegen/inlineClass/inlineClass0.kt @@ -0,0 +1,20 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +package codegen.inlineClass.inlineClass0 + +import kotlin.test.* + +// Based on KT-27225. + +inline class First(val value: Int) + +inline class Second(val value: First) { + constructor(c: Int) : this(First(c)) +} + +@Test fun runTest() { + assertEquals(Second(42).value.value, 42) +} diff --git a/kotlin-native/backend.native/tests/codegen/inlineClass/secondaryConstructorWithGenerics.kt b/kotlin-native/backend.native/tests/codegen/inlineClass/secondaryConstructorWithGenerics.kt new file mode 100644 index 00000000000..8bef556cfab --- /dev/null +++ b/kotlin-native/backend.native/tests/codegen/inlineClass/secondaryConstructorWithGenerics.kt @@ -0,0 +1,18 @@ +/* + * Copyright 2010-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +package codegen.inlineClass.secondaryConstructorWithGenerics + +import kotlin.test.* + +// Based on KT-42649. +inline class IC(val value: List) { + constructor(value: T) : this(listOf(value)) +} + +@Test +fun runTest() { + assertEquals("abc", IC("abc").value.singleOrNull()) +} diff --git a/kotlin-native/backend.native/tests/codegen/innerClass/doubleInner.kt b/kotlin-native/backend.native/tests/codegen/innerClass/doubleInner.kt new file mode 100644 index 00000000000..8d82723a579 --- /dev/null +++ b/kotlin-native/backend.native/tests/codegen/innerClass/doubleInner.kt @@ -0,0 +1,30 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +package codegen.innerClass.doubleInner + +import kotlin.test.* + +open class Father(val param: String) { + abstract inner class InClass { + fun work(): String { + return param + } + } + + inner class Child(p: String) : Father(p) { + inner class Child2 : Father.InClass { + constructor(): super() + } + } +} + +fun box(): String { + return Father("fail").Child("OK").Child2().work() +} + +@Test fun runTest() { + println(box()) +} \ No newline at end of file diff --git a/kotlin-native/backend.native/tests/codegen/innerClass/generic.kt b/kotlin-native/backend.native/tests/codegen/innerClass/generic.kt new file mode 100644 index 00000000000..19a0adb1dde --- /dev/null +++ b/kotlin-native/backend.native/tests/codegen/innerClass/generic.kt @@ -0,0 +1,24 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +package codegen.innerClass.generic + +import kotlin.test.* + +class Outer { + inner class Inner(val t: T) { + fun box() = t + } +} + +fun box(): String { + if (Outer().Inner("OK").box() != "OK") return "Fail" + val x: Outer.Inner = Outer().Inner("OK") + return x.box() +} + +@Test fun runTest() { + println(box()) +} \ No newline at end of file diff --git a/kotlin-native/backend.native/tests/codegen/innerClass/getOuterVal.kt b/kotlin-native/backend.native/tests/codegen/innerClass/getOuterVal.kt new file mode 100644 index 00000000000..0932a35a0a3 --- /dev/null +++ b/kotlin-native/backend.native/tests/codegen/innerClass/getOuterVal.kt @@ -0,0 +1,21 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +package codegen.innerClass.getOuterVal + +import kotlin.test.* + +class Outer(val s: String) { + inner class Inner { + fun box() = s + } +} + +fun box() = Outer("OK").Inner().box() + +@Test fun runTest() +{ + println(box()) +} \ No newline at end of file diff --git a/kotlin-native/backend.native/tests/codegen/innerClass/linkTest_lib.kt b/kotlin-native/backend.native/tests/codegen/innerClass/linkTest_lib.kt new file mode 100644 index 00000000000..c497f75a54e --- /dev/null +++ b/kotlin-native/backend.native/tests/codegen/innerClass/linkTest_lib.kt @@ -0,0 +1,10 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +open class A { + open inner class Inner { + val x = 42 + } +} \ No newline at end of file diff --git a/kotlin-native/backend.native/tests/codegen/innerClass/linkTest_main.kt b/kotlin-native/backend.native/tests/codegen/innerClass/linkTest_main.kt new file mode 100644 index 00000000000..4cfb90ff336 --- /dev/null +++ b/kotlin-native/backend.native/tests/codegen/innerClass/linkTest_main.kt @@ -0,0 +1,12 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +open class B : A() { + open inner class Inner : A.Inner() +} + +fun main(args: Array) { + B().Inner() +} \ No newline at end of file diff --git a/kotlin-native/backend.native/tests/codegen/innerClass/noPrimaryConstructor.kt b/kotlin-native/backend.native/tests/codegen/innerClass/noPrimaryConstructor.kt new file mode 100644 index 00000000000..9e7e7ea2ec3 --- /dev/null +++ b/kotlin-native/backend.native/tests/codegen/innerClass/noPrimaryConstructor.kt @@ -0,0 +1,30 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +package codegen.innerClass.noPrimaryConstructor + +import kotlin.test.* + +class Outer(val s: String) { + inner class Inner { + constructor(x: Int) { + this.x = x + } + + constructor(z: String) { + x = z.length + } + + val x: Int + + fun foo() = s + } + +} + +@Test fun runTest() { + println(Outer("OK").Inner(42).foo()) + println(Outer("OK").Inner("zzz").foo()) +} \ No newline at end of file diff --git a/kotlin-native/backend.native/tests/codegen/innerClass/qualifiedThis.kt b/kotlin-native/backend.native/tests/codegen/innerClass/qualifiedThis.kt new file mode 100644 index 00000000000..c3faf9f9b60 --- /dev/null +++ b/kotlin-native/backend.native/tests/codegen/innerClass/qualifiedThis.kt @@ -0,0 +1,55 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +package codegen.innerClass.qualifiedThis + +import kotlin.test.* + +open class ABase +{ + open fun zzz() = "a_base" +} + +open class BBase +{ + open fun zzz() = "b_base" +} + +class D() { + val z = "d" +} + +class A: ABase() { // implicit label @A + val z = "a" + override fun zzz() = "a" + inner class B: BBase() { // implicit label @B + val z = "b" + override fun zzz() = "b" + fun D.foo() : String { // implicit label @foo + if(this@A.z != "a") return "Fail1" + if(this@B.z != "b") return "Fail2" + + if(super@A.zzz() != "a_base") return "Fail3" + if(super.zzz() != "b_base") return "Fail4" + if(super@B.zzz() != "b_base") return "Fail5" + if(this@A.zzz() != "a") return "Fail6" + if(this@B.zzz() != "b") return "Fail7" + + if(this.z != "d") return "Fail8" + + return "OK" + } + + fun bar(d: D): String { + return d.foo() + } + } +} + +fun box() = A().B().bar(D()) + +@Test fun runTest() { + println(box()) +} diff --git a/kotlin-native/backend.native/tests/codegen/innerClass/secondaryConstructor.kt b/kotlin-native/backend.native/tests/codegen/innerClass/secondaryConstructor.kt new file mode 100644 index 00000000000..59b8eae9c59 --- /dev/null +++ b/kotlin-native/backend.native/tests/codegen/innerClass/secondaryConstructor.kt @@ -0,0 +1,29 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +package codegen.innerClass.secondaryConstructor + +import kotlin.test.* + +class Outer(val x: Int) { + inner class Inner() { + inner class InnerInner() { + + init { + println(x) + } + + lateinit var s: String + + constructor(s: String) : this() { + this.s = s + } + } + } +} + +@Test fun runTest() { + Outer(42).Inner().InnerInner("zzz") +} diff --git a/kotlin-native/backend.native/tests/codegen/innerClass/simple.kt b/kotlin-native/backend.native/tests/codegen/innerClass/simple.kt new file mode 100644 index 00000000000..9dad4c94dd2 --- /dev/null +++ b/kotlin-native/backend.native/tests/codegen/innerClass/simple.kt @@ -0,0 +1,21 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +package codegen.innerClass.simple + +import kotlin.test.* + +class Outer { + inner class Inner { + fun box() = "OK" + } +} + +fun box() = Outer().Inner().box() + +@Test fun runTest() +{ + println(box()) +} \ No newline at end of file diff --git a/kotlin-native/backend.native/tests/codegen/innerClass/superOuter.kt b/kotlin-native/backend.native/tests/codegen/innerClass/superOuter.kt new file mode 100644 index 00000000000..71863a2fe40 --- /dev/null +++ b/kotlin-native/backend.native/tests/codegen/innerClass/superOuter.kt @@ -0,0 +1,22 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +package codegen.innerClass.superOuter + +import kotlin.test.* + +open class Outer(val outer: String) { + open inner class Inner(val inner: String): Outer(inner) { + fun foo() = outer + } + + fun value() = Inner("OK").foo() +} + +fun box() = Outer("Fail").value() + +@Test fun runTest() { + println(box()) +} \ No newline at end of file diff --git a/kotlin-native/backend.native/tests/codegen/interfaceCallsNCasts/conservativeItable.kt b/kotlin-native/backend.native/tests/codegen/interfaceCallsNCasts/conservativeItable.kt new file mode 100644 index 00000000000..fffc6c51848 --- /dev/null +++ b/kotlin-native/backend.native/tests/codegen/interfaceCallsNCasts/conservativeItable.kt @@ -0,0 +1,686 @@ +/* + * Copyright 2010-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +package codegen.interfaceCallsNCasts.conservativeItable + +import kotlin.test.* + +interface I0 { + fun foo0(x: Int): Int +} +interface I1 { + fun foo1(x: Int): Int +} +interface I2 { + fun foo2(x: Int): Int +} +interface I3 { + fun foo3(x: Int): Int +} +interface I4 { + fun foo4(x: Int): Int +} +interface I5 { + fun foo5(x: Int): Int +} +interface I6 { + fun foo6(x: Int): Int +} +interface I7 { + fun foo7(x: Int): Int +} +interface I8 { + fun foo8(x: Int): Int +} +interface I9 { + fun foo9(x: Int): Int +} +interface I10 { + fun foo10(x: Int): Int +} +interface I11 { + fun foo11(x: Int): Int +} +interface I12 { + fun foo12(x: Int): Int +} +interface I13 { + fun foo13(x: Int): Int +} +interface I14 { + fun foo14(x: Int): Int +} +interface I15 { + fun foo15(x: Int): Int +} +interface I16 { + fun foo16(x: Int): Int +} +interface I17 { + fun foo17(x: Int): Int +} +interface I18 { + fun foo18(x: Int): Int +} +interface I19 { + fun foo19(x: Int): Int +} +interface I20 { + fun foo20(x: Int): Int +} +interface I21 { + fun foo21(x: Int): Int +} +interface I22 { + fun foo22(x: Int): Int +} +interface I23 { + fun foo23(x: Int): Int +} +interface I24 { + fun foo24(x: Int): Int +} +interface I25 { + fun foo25(x: Int): Int +} +interface I26 { + fun foo26(x: Int): Int +} +interface I27 { + fun foo27(x: Int): Int +} +interface I28 { + fun foo28(x: Int): Int +} +interface I29 { + fun foo29(x: Int): Int +} +interface I30 { + fun foo30(x: Int): Int +} +interface I31 { + fun foo31(x: Int): Int +} +interface I32 { + fun foo32(x: Int): Int +} +interface I33 { + fun foo33(x: Int): Int +} +interface I34 { + fun foo34(x: Int): Int +} +interface I35 { + fun foo35(x: Int): Int +} +interface I36 { + fun foo36(x: Int): Int +} +interface I37 { + fun foo37(x: Int): Int +} +interface I38 { + fun foo38(x: Int): Int +} +interface I39 { + fun foo39(x: Int): Int +} +interface I40 { + fun foo40(x: Int): Int +} +interface I41 { + fun foo41(x: Int): Int +} +interface I42 { + fun foo42(x: Int): Int +} +interface I43 { + fun foo43(x: Int): Int +} +interface I44 { + fun foo44(x: Int): Int +} +interface I45 { + fun foo45(x: Int): Int +} +interface I46 { + fun foo46(x: Int): Int +} +interface I47 { + fun foo47(x: Int): Int +} +interface I48 { + fun foo48(x: Int): Int +} +interface I49 { + fun foo49(x: Int): Int +} +interface I50 { + fun foo50(x: Int): Int +} +interface I51 { + fun foo51(x: Int): Int +} +interface I52 { + fun foo52(x: Int): Int +} +interface I53 { + fun foo53(x: Int): Int +} +interface I54 { + fun foo54(x: Int): Int +} +interface I55 { + fun foo55(x: Int): Int +} +interface I56 { + fun foo56(x: Int): Int +} +interface I57 { + fun foo57(x: Int): Int +} +interface I58 { + fun foo58(x: Int): Int +} +interface I59 { + fun foo59(x: Int): Int +} +interface I60 { + fun foo60(x: Int): Int +} +interface I61 { + fun foo61(x: Int): Int +} +interface I62 { + fun foo62(x: Int): Int +} +interface I63 { + fun foo63(x: Int): Int +} +interface I64 { + fun foo64(x: Int): Int +} +interface I65 { + fun foo65(x: Int): Int +} +interface I66 { + fun foo66(x: Int): Int +} +interface I67 { + fun foo67(x: Int): Int +} +interface I68 { + fun foo68(x: Int): Int +} +interface I69 { + fun foo69(x: Int): Int +} +interface I70 { + fun foo70(x: Int): Int +} +interface I71 { + fun foo71(x: Int): Int +} +interface I72 { + fun foo72(x: Int): Int +} +interface I73 { + fun foo73(x: Int): Int +} +interface I74 { + fun foo74(x: Int): Int +} +interface I75 { + fun foo75(x: Int): Int +} +interface I76 { + fun foo76(x: Int): Int +} +interface I77 { + fun foo77(x: Int): Int +} +interface I78 { + fun foo78(x: Int): Int +} +interface I79 { + fun foo79(x: Int): Int +} +interface I80 { + fun foo80(x: Int): Int +} +interface I81 { + fun foo81(x: Int): Int +} +interface I82 { + fun foo82(x: Int): Int +} +interface I83 { + fun foo83(x: Int): Int +} +interface I84 { + fun foo84(x: Int): Int +} +interface I85 { + fun foo85(x: Int): Int +} +interface I86 { + fun foo86(x: Int): Int +} +interface I87 { + fun foo87(x: Int): Int +} +interface I88 { + fun foo88(x: Int): Int +} +interface I89 { + fun foo89(x: Int): Int +} +interface I90 { + fun foo90(x: Int): Int +} +interface I91 { + fun foo91(x: Int): Int +} +interface I92 { + fun foo92(x: Int): Int +} +interface I93 { + fun foo93(x: Int): Int +} +interface I94 { + fun foo94(x: Int): Int +} +interface I95 { + fun foo95(x: Int): Int +} +interface I96 { + fun foo96(x: Int): Int +} +interface I97 { + fun foo97(x: Int): Int +} +interface I98 { + fun foo98(x: Int): Int +} +interface I99 { + fun foo99(x: Int): Int +} +class Bar : I0, I1, I2, I3, I4, I5, I6, I7, I8, I9, I10, I11, I12, I13, I14, I15, I16, I17, I18, I19, I20, I21, I22, + I23, I24, I25, I26, I27, I28, I29, I30, I31, I32, I33, I34, I35, I36, I37, I38, I39, I40, I41, I42, I43, I44, + I45, I46, I47, I48, I49, I50, I51, I52, I53, I54, I55, I56, I57, I58, I59, I60, I61, I62, I63, I64, I65, I66, + I67, I68, I69, I70, I71, I72, I73, I74, I75, I76, I77, I78, I79, I80, I81, I82, I83, I84, I85, I86, I87, I88, + I89, I90, I91, I92, I93, I94, I95, I96, I97, I98, I99 { + override fun foo0(x: Int) = x + 0 + override fun foo1(x: Int) = x + 1 + override fun foo2(x: Int) = x + 2 + override fun foo3(x: Int) = x + 3 + override fun foo4(x: Int) = x + 4 + override fun foo5(x: Int) = x + 5 + override fun foo6(x: Int) = x + 6 + override fun foo7(x: Int) = x + 7 + override fun foo8(x: Int) = x + 8 + override fun foo9(x: Int) = x + 9 + override fun foo10(x: Int) = x + 10 + override fun foo11(x: Int) = x + 11 + override fun foo12(x: Int) = x + 12 + override fun foo13(x: Int) = x + 13 + override fun foo14(x: Int) = x + 14 + override fun foo15(x: Int) = x + 15 + override fun foo16(x: Int) = x + 16 + override fun foo17(x: Int) = x + 17 + override fun foo18(x: Int) = x + 18 + override fun foo19(x: Int) = x + 19 + override fun foo20(x: Int) = x + 20 + override fun foo21(x: Int) = x + 21 + override fun foo22(x: Int) = x + 22 + override fun foo23(x: Int) = x + 23 + override fun foo24(x: Int) = x + 24 + override fun foo25(x: Int) = x + 25 + override fun foo26(x: Int) = x + 26 + override fun foo27(x: Int) = x + 27 + override fun foo28(x: Int) = x + 28 + override fun foo29(x: Int) = x + 29 + override fun foo30(x: Int) = x + 30 + override fun foo31(x: Int) = x + 31 + override fun foo32(x: Int) = x + 32 + override fun foo33(x: Int) = x + 33 + override fun foo34(x: Int) = x + 34 + override fun foo35(x: Int) = x + 35 + override fun foo36(x: Int) = x + 36 + override fun foo37(x: Int) = x + 37 + override fun foo38(x: Int) = x + 38 + override fun foo39(x: Int) = x + 39 + override fun foo40(x: Int) = x + 40 + override fun foo41(x: Int) = x + 41 + override fun foo42(x: Int) = x + 42 + override fun foo43(x: Int) = x + 43 + override fun foo44(x: Int) = x + 44 + override fun foo45(x: Int) = x + 45 + override fun foo46(x: Int) = x + 46 + override fun foo47(x: Int) = x + 47 + override fun foo48(x: Int) = x + 48 + override fun foo49(x: Int) = x + 49 + override fun foo50(x: Int) = x + 50 + override fun foo51(x: Int) = x + 51 + override fun foo52(x: Int) = x + 52 + override fun foo53(x: Int) = x + 53 + override fun foo54(x: Int) = x + 54 + override fun foo55(x: Int) = x + 55 + override fun foo56(x: Int) = x + 56 + override fun foo57(x: Int) = x + 57 + override fun foo58(x: Int) = x + 58 + override fun foo59(x: Int) = x + 59 + override fun foo60(x: Int) = x + 60 + override fun foo61(x: Int) = x + 61 + override fun foo62(x: Int) = x + 62 + override fun foo63(x: Int) = x + 63 + override fun foo64(x: Int) = x + 64 + override fun foo65(x: Int) = x + 65 + override fun foo66(x: Int) = x + 66 + override fun foo67(x: Int) = x + 67 + override fun foo68(x: Int) = x + 68 + override fun foo69(x: Int) = x + 69 + override fun foo70(x: Int) = x + 70 + override fun foo71(x: Int) = x + 71 + override fun foo72(x: Int) = x + 72 + override fun foo73(x: Int) = x + 73 + override fun foo74(x: Int) = x + 74 + override fun foo75(x: Int) = x + 75 + override fun foo76(x: Int) = x + 76 + override fun foo77(x: Int) = x + 77 + override fun foo78(x: Int) = x + 78 + override fun foo79(x: Int) = x + 79 + override fun foo80(x: Int) = x + 80 + override fun foo81(x: Int) = x + 81 + override fun foo82(x: Int) = x + 82 + override fun foo83(x: Int) = x + 83 + override fun foo84(x: Int) = x + 84 + override fun foo85(x: Int) = x + 85 + override fun foo86(x: Int) = x + 86 + override fun foo87(x: Int) = x + 87 + override fun foo88(x: Int) = x + 88 + override fun foo89(x: Int) = x + 89 + override fun foo90(x: Int) = x + 90 + override fun foo91(x: Int) = x + 91 + override fun foo92(x: Int) = x + 92 + override fun foo93(x: Int) = x + 93 + override fun foo94(x: Int) = x + 94 + override fun foo95(x: Int) = x + 95 + override fun foo96(x: Int) = x + 96 + override fun foo97(x: Int) = x + 97 + override fun foo98(x: Int) = x + 98 + override fun foo99(x: Int) = x + 99 +} + +fun check_is_I0(x: Any) = x is I0 +fun check_is_I1(x: Any) = x is I1 +fun check_is_I2(x: Any) = x is I2 +fun check_is_I3(x: Any) = x is I3 +fun check_is_I4(x: Any) = x is I4 +fun check_is_I5(x: Any) = x is I5 +fun check_is_I6(x: Any) = x is I6 +fun check_is_I7(x: Any) = x is I7 +fun check_is_I8(x: Any) = x is I8 +fun check_is_I9(x: Any) = x is I9 +fun check_is_I10(x: Any) = x is I10 +fun check_is_I11(x: Any) = x is I11 +fun check_is_I12(x: Any) = x is I12 +fun check_is_I13(x: Any) = x is I13 +fun check_is_I14(x: Any) = x is I14 +fun check_is_I15(x: Any) = x is I15 +fun check_is_I16(x: Any) = x is I16 +fun check_is_I17(x: Any) = x is I17 +fun check_is_I18(x: Any) = x is I18 +fun check_is_I19(x: Any) = x is I19 +fun check_is_I20(x: Any) = x is I20 +fun check_is_I21(x: Any) = x is I21 +fun check_is_I22(x: Any) = x is I22 +fun check_is_I23(x: Any) = x is I23 +fun check_is_I24(x: Any) = x is I24 +fun check_is_I25(x: Any) = x is I25 +fun check_is_I26(x: Any) = x is I26 +fun check_is_I27(x: Any) = x is I27 +fun check_is_I28(x: Any) = x is I28 +fun check_is_I29(x: Any) = x is I29 +fun check_is_I30(x: Any) = x is I30 +fun check_is_I31(x: Any) = x is I31 +fun check_is_I32(x: Any) = x is I32 +fun check_is_I33(x: Any) = x is I33 +fun check_is_I34(x: Any) = x is I34 +fun check_is_I35(x: Any) = x is I35 +fun check_is_I36(x: Any) = x is I36 +fun check_is_I37(x: Any) = x is I37 +fun check_is_I38(x: Any) = x is I38 +fun check_is_I39(x: Any) = x is I39 +fun check_is_I40(x: Any) = x is I40 +fun check_is_I41(x: Any) = x is I41 +fun check_is_I42(x: Any) = x is I42 +fun check_is_I43(x: Any) = x is I43 +fun check_is_I44(x: Any) = x is I44 +fun check_is_I45(x: Any) = x is I45 +fun check_is_I46(x: Any) = x is I46 +fun check_is_I47(x: Any) = x is I47 +fun check_is_I48(x: Any) = x is I48 +fun check_is_I49(x: Any) = x is I49 +fun check_is_I50(x: Any) = x is I50 +fun check_is_I51(x: Any) = x is I51 +fun check_is_I52(x: Any) = x is I52 +fun check_is_I53(x: Any) = x is I53 +fun check_is_I54(x: Any) = x is I54 +fun check_is_I55(x: Any) = x is I55 +fun check_is_I56(x: Any) = x is I56 +fun check_is_I57(x: Any) = x is I57 +fun check_is_I58(x: Any) = x is I58 +fun check_is_I59(x: Any) = x is I59 +fun check_is_I60(x: Any) = x is I60 +fun check_is_I61(x: Any) = x is I61 +fun check_is_I62(x: Any) = x is I62 +fun check_is_I63(x: Any) = x is I63 +fun check_is_I64(x: Any) = x is I64 +fun check_is_I65(x: Any) = x is I65 +fun check_is_I66(x: Any) = x is I66 +fun check_is_I67(x: Any) = x is I67 +fun check_is_I68(x: Any) = x is I68 +fun check_is_I69(x: Any) = x is I69 +fun check_is_I70(x: Any) = x is I70 +fun check_is_I71(x: Any) = x is I71 +fun check_is_I72(x: Any) = x is I72 +fun check_is_I73(x: Any) = x is I73 +fun check_is_I74(x: Any) = x is I74 +fun check_is_I75(x: Any) = x is I75 +fun check_is_I76(x: Any) = x is I76 +fun check_is_I77(x: Any) = x is I77 +fun check_is_I78(x: Any) = x is I78 +fun check_is_I79(x: Any) = x is I79 +fun check_is_I80(x: Any) = x is I80 +fun check_is_I81(x: Any) = x is I81 +fun check_is_I82(x: Any) = x is I82 +fun check_is_I83(x: Any) = x is I83 +fun check_is_I84(x: Any) = x is I84 +fun check_is_I85(x: Any) = x is I85 +fun check_is_I86(x: Any) = x is I86 +fun check_is_I87(x: Any) = x is I87 +fun check_is_I88(x: Any) = x is I88 +fun check_is_I89(x: Any) = x is I89 +fun check_is_I90(x: Any) = x is I90 +fun check_is_I91(x: Any) = x is I91 +fun check_is_I92(x: Any) = x is I92 +fun check_is_I93(x: Any) = x is I93 +fun check_is_I94(x: Any) = x is I94 +fun check_is_I95(x: Any) = x is I95 +fun check_is_I96(x: Any) = x is I96 +fun check_is_I97(x: Any) = x is I97 +fun check_is_I98(x: Any) = x is I98 +fun check_is_I99(x: Any) = x is I99 + +interface I_M1 { + fun bar(x: Int): Int +} + +class Bar2 : I_M1 { + override fun bar(x: Int) = 497 * x + 42 +} + +class I42_Impl1 : I42 { + override fun foo42(x: Int) = x * 2 + 42 +} + +class I42_Impl2 : I42 { + override fun foo42(x: Int) = x * 3 + 42 +} + +class I42_Impl3 : I42 { + override fun foo42(x: Int) = x * 4 + 42 +} + +class I42_Impl4 : I42 { + override fun foo42(x: Int) = x * 5 + 42 +} + +class I42_Impl5 : I42 { + override fun foo42(x: Int) = x * 6 + 42 +} + +class I42_Impl6 : I42 { + override fun foo42(x: Int) = x * 7 + 42 +} + +class I42_Impl7 : I42 { + override fun foo42(x: Int) = x * 8 + 42 +} + +class I42_Impl8 : I42 { + override fun foo42(x: Int) = x * 9 + 42 +} + +fun foo(i42: I42, x: Int) = i42.foo42(x) + +fun bar(i_m1: I_M1, x: Int) = i_m1.bar(x) + +@Test fun runTest() { + val y = Bar2() + println(bar(y, 1)) + val x0 = Bar() + var t = 0 + if (check_is_I0(x0)) t = t + 1 + if (check_is_I1(x0)) t = t + 2 + if (check_is_I2(x0)) t = t + 3 + if (check_is_I3(x0)) t = t + 4 + if (check_is_I4(x0)) t = t + 5 + if (check_is_I5(x0)) t = t + 6 + if (check_is_I6(x0)) t = t + 7 + if (check_is_I7(x0)) t = t + 8 + if (check_is_I8(x0)) t = t + 9 + if (check_is_I9(x0)) t = t + 10 + if (check_is_I10(x0)) t = t + 11 + if (check_is_I11(x0)) t = t + 12 + if (check_is_I12(x0)) t = t + 13 + if (check_is_I13(x0)) t = t + 14 + if (check_is_I14(x0)) t = t + 15 + if (check_is_I15(x0)) t = t + 16 + if (check_is_I16(x0)) t = t + 17 + if (check_is_I17(x0)) t = t + 18 + if (check_is_I18(x0)) t = t + 19 + if (check_is_I19(x0)) t = t + 20 + if (check_is_I20(x0)) t = t + 21 + if (check_is_I21(x0)) t = t + 22 + if (check_is_I22(x0)) t = t + 23 + if (check_is_I23(x0)) t = t + 24 + if (check_is_I24(x0)) t = t + 25 + if (check_is_I25(x0)) t = t + 26 + if (check_is_I26(x0)) t = t + 27 + if (check_is_I27(x0)) t = t + 28 + if (check_is_I28(x0)) t = t + 29 + if (check_is_I29(x0)) t = t + 30 + if (check_is_I30(x0)) t = t + 31 + if (check_is_I31(x0)) t = t + 32 + if (check_is_I32(x0)) t = t + 33 + if (check_is_I33(x0)) t = t + 34 + if (check_is_I34(x0)) t = t + 35 + if (check_is_I35(x0)) t = t + 36 + if (check_is_I36(x0)) t = t + 37 + if (check_is_I37(x0)) t = t + 38 + if (check_is_I38(x0)) t = t + 39 + if (check_is_I39(x0)) t = t + 40 + if (check_is_I40(x0)) t = t + 41 + if (check_is_I41(x0)) t = t + 42 + if (check_is_I42(x0)) t = t + 43 + if (check_is_I43(x0)) t = t + 44 + if (check_is_I44(x0)) t = t + 45 + if (check_is_I45(x0)) t = t + 46 + if (check_is_I46(x0)) t = t + 47 + if (check_is_I47(x0)) t = t + 48 + if (check_is_I48(x0)) t = t + 49 + if (check_is_I49(x0)) t = t + 50 + if (check_is_I50(x0)) t = t + 51 + if (check_is_I51(x0)) t = t + 52 + if (check_is_I52(x0)) t = t + 53 + if (check_is_I53(x0)) t = t + 54 + if (check_is_I54(x0)) t = t + 55 + if (check_is_I55(x0)) t = t + 56 + if (check_is_I56(x0)) t = t + 57 + if (check_is_I57(x0)) t = t + 58 + if (check_is_I58(x0)) t = t + 59 + if (check_is_I59(x0)) t = t + 60 + if (check_is_I60(x0)) t = t + 61 + if (check_is_I61(x0)) t = t + 62 + if (check_is_I62(x0)) t = t + 63 + if (check_is_I63(x0)) t = t + 64 + if (check_is_I64(x0)) t = t + 65 + if (check_is_I65(x0)) t = t + 66 + if (check_is_I66(x0)) t = t + 67 + if (check_is_I67(x0)) t = t + 68 + if (check_is_I68(x0)) t = t + 69 + if (check_is_I69(x0)) t = t + 70 + if (check_is_I70(x0)) t = t + 71 + if (check_is_I71(x0)) t = t + 72 + if (check_is_I72(x0)) t = t + 73 + if (check_is_I73(x0)) t = t + 74 + if (check_is_I74(x0)) t = t + 75 + if (check_is_I75(x0)) t = t + 76 + if (check_is_I76(x0)) t = t + 77 + if (check_is_I77(x0)) t = t + 78 + if (check_is_I78(x0)) t = t + 79 + if (check_is_I79(x0)) t = t + 80 + if (check_is_I80(x0)) t = t + 81 + if (check_is_I81(x0)) t = t + 82 + if (check_is_I82(x0)) t = t + 83 + if (check_is_I83(x0)) t = t + 84 + if (check_is_I84(x0)) t = t + 85 + if (check_is_I85(x0)) t = t + 86 + if (check_is_I86(x0)) t = t + 87 + if (check_is_I87(x0)) t = t + 88 + if (check_is_I88(x0)) t = t + 89 + if (check_is_I89(x0)) t = t + 90 + if (check_is_I90(x0)) t = t + 91 + if (check_is_I91(x0)) t = t + 92 + if (check_is_I92(x0)) t = t + 93 + if (check_is_I93(x0)) t = t + 94 + if (check_is_I94(x0)) t = t + 95 + if (check_is_I95(x0)) t = t + 96 + if (check_is_I96(x0)) t = t + 97 + if (check_is_I97(x0)) t = t + 98 + if (check_is_I98(x0)) t = t + 99 + if (check_is_I99(x0)) t = t + 100 + println(t) + val x1 = I42_Impl1() + val x2 = I42_Impl2() + val x3 = I42_Impl3() + val x4 = I42_Impl4() + val x5 = I42_Impl5() + val x6 = I42_Impl6() + val x7 = I42_Impl7() + val x8 = I42_Impl8() + t = foo(x0, 1) + t = foo(x1, t) + t = foo(x2, t) + t = foo(x3, t) + t = foo(x4, t) + t = foo(x5, t) + t = foo(x6, t) + t = foo(x7, t) + t = foo(x8, t) + println(t) +} diff --git a/kotlin-native/backend.native/tests/codegen/intrinsics/interop_convert.kt b/kotlin-native/backend.native/tests/codegen/intrinsics/interop_convert.kt new file mode 100644 index 00000000000..722428b53b6 --- /dev/null +++ b/kotlin-native/backend.native/tests/codegen/intrinsics/interop_convert.kt @@ -0,0 +1,173 @@ +package codegen.intrinsics.interop_convert + +import kotlin.test.* +import kotlinx.cinterop.* + +fun convertIntToShortOrNull(i: Int, b: Boolean): Short? = if (b) i.convert() else null +fun narrowIntToShortOrNull(i: Int, b: Boolean): Short? = if (b) i.narrow() else null +fun signExtendShortToIntOrNull(i: Short, b: Boolean): Int? = if (b) i.signExtend() else null + +@Test +fun testNI() { + assertNull(convertIntToShortOrNull(0, false)) + assertEquals(1, convertIntToShortOrNull(1, true)) + + assertNull(narrowIntToShortOrNull(2, false)) + assertEquals(3, narrowIntToShortOrNull(3, true)) + + assertNull(signExtendShortToIntOrNull(4, false)) + assertEquals(5, signExtendShortToIntOrNull(5, true)) +} + +@Test +fun testConvertSimple() { + assertEquals(1, 257.convert()) + assertEquals(255u, (-1).convert()) + assertEquals(0, Long.MIN_VALUE.narrow()) + assertEquals(-1, Long.MAX_VALUE.narrow()) + assertEquals(-1L, (-1).signExtend()) +} + +@Test +fun convertAll() { + val values = mutableListOf() + for (value in listOf( + 0L, + Byte.MIN_VALUE.toLong(), Byte.MAX_VALUE.toLong(), UByte.MAX_VALUE.toLong(), + Short.MIN_VALUE.toLong(), Short.MAX_VALUE.toLong(), UShort.MAX_VALUE.toLong(), + Int.MIN_VALUE.toLong(), Int.MAX_VALUE.toLong(), UInt.MAX_VALUE.toLong(), + Long.MIN_VALUE.toLong(), Long.MAX_VALUE.toLong(), ULong.MAX_VALUE.toLong() + )) { + values.add(value - 1) + values.add(value) + values.add(value + 1) + } + + for (value in values) { + testConvertAll(value.toByte()) + testConvertAll(value.toUByte()) + testConvertAll(value.toShort()) + testConvertAll(value.toUShort()) + testConvertAll(value.toInt()) + testConvertAll(value.toUInt()) + testConvertAll(value.toLong()) + testConvertAll(value.toULong()) + } +} + +fun testConvertAll(value: Byte) { + assertEquals(value.toByte(), value.convert()) + assertEquals(value.toUByte(), value.convert()) + assertEquals(value.toShort(), value.convert()) + assertEquals(value.toUShort(), value.convert()) + assertEquals(value.toInt(), value.convert()) + assertEquals(value.toUInt(), value.convert()) + assertEquals(value.toLong(), value.convert()) + assertEquals(value.toULong(), value.convert()) + + assertEquals(value.toByte(), value.narrow()) + + assertEquals(value.toByte(), value.signExtend()) + assertEquals(value.toShort(), value.signExtend()) + assertEquals(value.toInt(), value.signExtend()) + assertEquals(value.toLong(), value.signExtend()) +} + +fun testConvertAll(value: Short) { + assertEquals(value.toByte(), value.convert()) + assertEquals(value.toUByte(), value.convert()) + assertEquals(value.toShort(), value.convert()) + assertEquals(value.toUShort(), value.convert()) + assertEquals(value.toInt(), value.convert()) + assertEquals(value.toUInt(), value.convert()) + assertEquals(value.toLong(), value.convert()) + assertEquals(value.toULong(), value.convert()) + + assertEquals(value.toByte(), value.narrow()) + assertEquals(value.toShort(), value.narrow()) + + assertEquals(value.toShort(), value.signExtend()) + assertEquals(value.toInt(), value.signExtend()) + assertEquals(value.toLong(), value.signExtend()) +} + +fun testConvertAll(value: Int) { + assertEquals(value.toByte(), value.convert()) + assertEquals(value.toUByte(), value.convert()) + assertEquals(value.toShort(), value.convert()) + assertEquals(value.toUShort(), value.convert()) + assertEquals(value.toInt(), value.convert()) + assertEquals(value.toUInt(), value.convert()) + assertEquals(value.toLong(), value.convert()) + assertEquals(value.toULong(), value.convert()) + + assertEquals(value.toByte(), value.narrow()) + assertEquals(value.toShort(), value.narrow()) + assertEquals(value.toInt(), value.narrow()) + + assertEquals(value.toInt(), value.signExtend()) + assertEquals(value.toLong(), value.signExtend()) +} + +fun testConvertAll(value: Long) { + assertEquals(value.toByte(), value.convert()) + assertEquals(value.toUByte(), value.convert()) + assertEquals(value.toShort(), value.convert()) + assertEquals(value.toUShort(), value.convert()) + assertEquals(value.toInt(), value.convert()) + assertEquals(value.toUInt(), value.convert()) + assertEquals(value.toLong(), value.convert()) + assertEquals(value.toULong(), value.convert()) + + assertEquals(value.toByte(), value.narrow()) + assertEquals(value.toShort(), value.narrow()) + assertEquals(value.toInt(), value.narrow()) + assertEquals(value.toLong(), value.narrow()) + + assertEquals(value.toLong(), value.signExtend()) +} + + +fun testConvertAll(value: UByte) { + assertEquals(value.toByte(), value.convert()) + assertEquals(value.toUByte(), value.convert()) + assertEquals(value.toShort(), value.convert()) + assertEquals(value.toUShort(), value.convert()) + assertEquals(value.toInt(), value.convert()) + assertEquals(value.toUInt(), value.convert()) + assertEquals(value.toLong(), value.convert()) + assertEquals(value.toULong(), value.convert()) +} + +fun testConvertAll(value: UShort) { + assertEquals(value.toByte(), value.convert()) + assertEquals(value.toUByte(), value.convert()) + assertEquals(value.toShort(), value.convert()) + assertEquals(value.toUShort(), value.convert()) + assertEquals(value.toInt(), value.convert()) + assertEquals(value.toUInt(), value.convert()) + assertEquals(value.toLong(), value.convert()) + assertEquals(value.toULong(), value.convert()) +} + +fun testConvertAll(value: UInt) { + assertEquals(value.toByte(), value.convert()) + assertEquals(value.toUByte(), value.convert()) + assertEquals(value.toShort(), value.convert()) + assertEquals(value.toUShort(), value.convert()) + assertEquals(value.toInt(), value.convert()) + assertEquals(value.toUInt(), value.convert()) + assertEquals(value.toLong(), value.convert()) + assertEquals(value.toULong(), value.convert()) +} + +fun testConvertAll(value: ULong) { + assertEquals(value.toByte(), value.convert()) + assertEquals(value.toUByte(), value.convert()) + assertEquals(value.toShort(), value.convert()) + assertEquals(value.toUShort(), value.convert()) + assertEquals(value.toInt(), value.convert()) + assertEquals(value.toUInt(), value.convert()) + assertEquals(value.toLong(), value.convert()) + assertEquals(value.toULong(), value.convert()) +} diff --git a/kotlin-native/backend.native/tests/codegen/kclass/kClassEnumArgument.kt b/kotlin-native/backend.native/tests/codegen/kclass/kClassEnumArgument.kt new file mode 100644 index 00000000000..911102b2328 --- /dev/null +++ b/kotlin-native/backend.native/tests/codegen/kclass/kClassEnumArgument.kt @@ -0,0 +1,18 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +package codegen.kclass.kClassEnumArgument + +import kotlin.test.* +import kotlin.reflect.KClass + +enum class E(val arg: KClass<*>?) { + A(null as KClass<*>?), + B(String::class); +} + +@Test fun runTest() { + println(E.B.arg?.simpleName) +} \ No newline at end of file diff --git a/kotlin-native/backend.native/tests/codegen/kclass/kclass0.kt b/kotlin-native/backend.native/tests/codegen/kclass/kclass0.kt new file mode 100644 index 00000000000..88875f29edc --- /dev/null +++ b/kotlin-native/backend.native/tests/codegen/kclass/kclass0.kt @@ -0,0 +1,88 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +package codegen.kclass.kclass0 + +import kotlin.test.* +import kotlin.reflect.KClass + +@Test fun runTest() { + main(emptyArray()) +} + +fun main(args: Array) { + checkClass(Any::class, "kotlin.Any", "Any", Any(), null) + checkClass(Int::class, "kotlin.Int", "Int", 42, "17") + checkClass(String::class, "kotlin.String", "String", "17", 42) + checkClass(RootClass::class, "codegen.kclass.kclass0.RootClass", "RootClass", RootClass(), Any()) + checkClass(RootClass.Nested::class, "codegen.kclass.kclass0.RootClass.Nested", "Nested", RootClass.Nested(), Any()) + + class Local { + val captured = args + + inner class Inner + } + checkClass(Local::class, null, "Local", Local(), Any()) + checkClass(Local.Inner::class, null, "Inner", Local().Inner(), Any()) + + val obj = object : Any() { + val captured = args + + inner class Inner + val innerKClass = Inner::class + } + checkClass(obj::class, null, null, obj, Any()) + checkClass(obj.innerKClass, null, "Inner", obj.Inner(), Any()) + + // Interfaces: + checkClass(Comparable::class, "kotlin.Comparable", "Comparable", 42, Any()) + checkClass(Interface::class, "codegen.kclass.kclass0.Interface", "Interface", object : Interface {}, Any()) + + checkInstanceClass(Any(), Any::class) + checkInstanceClass(42, Int::class) + assert(42::class == Int::class) + + checkReifiedClass(Int::class) + checkReifiedClass(Int::class) + checkReifiedClass2(Int::class) + checkReifiedClass2(Int::class) + checkReifiedClass(Any::class) + checkReifiedClass2(Any::class) + checkReifiedClass2(Any::class) + checkReifiedClass(Local::class) + checkReifiedClass2(Local::class) + checkReifiedClass(RootClass::class) + checkReifiedClass2(RootClass::class) +} + +class RootClass { + class Nested +} +interface Interface + +fun checkClass( + clazz: KClass<*>, + expectedQualifiedName: String?, expectedSimpleName: String?, + expectedInstance: Any, expectedNotInstance: Any? +) { + assert(clazz.qualifiedName == expectedQualifiedName) + assert(clazz.simpleName == expectedSimpleName) + + assert(clazz.isInstance(expectedInstance)) + if (expectedNotInstance != null) assert(!clazz.isInstance(expectedNotInstance)) +} + +fun checkInstanceClass(instance: Any, clazz: KClass<*>) { + assert(instance::class == clazz) +} + +inline fun checkReifiedClass(expectedClass: KClass<*>) { + assert(T::class == expectedClass) +} + +inline fun checkReifiedClass2(expectedClass: KClass<*>) { + checkReifiedClass(expectedClass) + checkReifiedClass(expectedClass) +} diff --git a/kotlin-native/backend.native/tests/codegen/kclass/kclass1.kt b/kotlin-native/backend.native/tests/codegen/kclass/kclass1.kt new file mode 100644 index 00000000000..d98726cb0f2 --- /dev/null +++ b/kotlin-native/backend.native/tests/codegen/kclass/kclass1.kt @@ -0,0 +1,59 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +package codegen.kclass.kclass1 + +import kotlin.test.* + +// FILE: main.kt +@Test fun runTest() { + App(testQualified = true) +} + +// FILE: app.kt + +// Taken from: +// https://github.com/SalomonBrys/kmffkn/blob/master/shared/main/kotlin/com/github/salomonbrys/kmffkn/app.kt + +@DslMarker +annotation class MyDsl + +@MyDsl +class DslMain { + fun kClass(block: KClassDsl.() -> T): T = KClassDsl().block() +} + +@MyDsl +class KClassDsl { + inline fun of() = T::class +} + +fun dsl(block: DslMain.() -> T): T = DslMain().block() + +class TestClass + +class App(testQualified: Boolean) { + + var type = dsl { + kClass { + //kClass { } // This should error if uncommented because of `@DslMarker`. + of() + } + } + + init { + assert(type.simpleName == "TestClass") + if (testQualified) + assert(type.qualifiedName == "codegen.kclass.kclass1.TestClass") // This is not really necessary, but always better :). + + assert(String::class == String::class) + assert(String::class != Int::class) + + assert(TestClass()::class == TestClass()::class) + assert(TestClass()::class == TestClass::class) + + println("OK :D") + } +} diff --git a/kotlin-native/backend.native/tests/codegen/ktype/ktype1.kt b/kotlin-native/backend.native/tests/codegen/ktype/ktype1.kt new file mode 100644 index 00000000000..d7a841c9093 --- /dev/null +++ b/kotlin-native/backend.native/tests/codegen/ktype/ktype1.kt @@ -0,0 +1,58 @@ +/* + * Copyright 2010-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +package codegen.ktype.ktype1 + +import kotlin.test.* +import kotlin.reflect.* + +@OptIn(ExperimentalStdlibApi::class) +inline fun kType() = typeOf() + +inline fun kType(obj: R) = kType() + +class C +class D + +fun kTypeForCWithTypeParameter() = kType>() + +class Outer { + companion object Friend + inner class Inner +} + +object Object + +private val pkg = "codegen.ktype.ktype1" + +@Test +fun testBasics1() { + assertEquals("$pkg.C", kType>().toString()) + assertEquals("$pkg.C<$pkg.C>", kType>>().toString()) + + assertEquals("$pkg.C", kTypeForCWithTypeParameter().toString()) + assertEquals("$pkg.Object", kType().toString()) + assertEquals("$pkg.Outer.Friend", kType().toString()) +} + +@Test +fun testInner() { + val innerKType = kType.Inner>() + assertEquals(Outer.Inner::class, innerKType.classifier) + assertEquals(String::class, innerKType.arguments.first().type!!.classifier) + assertEquals(D::class, innerKType.arguments.last().type!!.classifier) +} + +@Test +fun testAnonymousObject() { + val obj = object {} + val objType = kType(obj) + + assertEquals("(non-denotable type)", objType.toString()) + assertEquals(obj::class, objType.classifier) + + assertTrue(objType.arguments.isEmpty()) + assertFalse(objType.isMarkedNullable) +} \ No newline at end of file diff --git a/kotlin-native/backend.native/tests/codegen/ktype/nonReified.kt b/kotlin-native/backend.native/tests/codegen/ktype/nonReified.kt new file mode 100644 index 00000000000..5dc5670251e --- /dev/null +++ b/kotlin-native/backend.native/tests/codegen/ktype/nonReified.kt @@ -0,0 +1,78 @@ +/* + * Copyright 2010-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +package codegen.ktype.nonReified + +import kotlin.test.* +import kotlin.reflect.* + +@OptIn(kotlin.ExperimentalStdlibApi::class) +fun foo() = typeOf>() + +@Test +fun test_fun() { + val l = foo() + assertEquals(List::class, l.classifier) + val t = l.arguments.single().type!!.classifier + assertTrue(t is KTypeParameter) + assertFalse((t as KTypeParameter).isReified) + assertEquals("T", (t as KTypeParameter).name) +} + +class C { + @OptIn(kotlin.ExperimentalStdlibApi::class) + fun foo() = typeOf>() +} + +@Test +fun test_class() { + val l = C().foo() + assertEquals(List::class, l.classifier) + val t = l.arguments.single().type!!.classifier + assertTrue(t is KTypeParameter) + assertFalse((t as KTypeParameter).isReified) + assertEquals("T", (t as KTypeParameter).name) +} + +@OptIn(kotlin.ExperimentalStdlibApi::class) +fun bar1() = typeOf>() + +@OptIn(kotlin.ExperimentalStdlibApi::class) +fun bar2() = typeOf>() + +class D { + @OptIn(kotlin.ExperimentalStdlibApi::class) + fun bar1() = typeOf>() +} + +@Test +fun test_equality() { + val t1 = bar1().arguments.single().type!!.classifier + val t2 = bar2().arguments.single().type!!.classifier + val t3 = D().bar1().arguments.single().type!!.classifier + assertNotEquals(t1, t2) + assertNotEquals(t1, t3) + assertNotEquals(t2, t3) + assertEquals(t1, bar1().arguments.single().type!!.classifier) + assertEquals(t2, bar2().arguments.single().type!!.classifier) + assertEquals(t3, D().bar1().arguments.single().type!!.classifier) +} + +@OptIn(kotlin.ExperimentalStdlibApi::class) +inline fun reifiedUpperBound() = typeOf>() + +@Test +fun test_reifiedUpperBound() { + val l = reifiedUpperBound() + assertEquals(List::class, l.classifier) + val r = l.arguments.single().type!!.classifier + assertTrue(r is KTypeParameter) + assertFalse((r as KTypeParameter).isReified) + assertEquals("R", (r as KTypeParameter).name) + val t = (r as KTypeParameter).upperBounds.single().classifier + assertTrue(t is KTypeParameter) + assertTrue((t as KTypeParameter).isReified) + assertEquals("T", (t as KTypeParameter).name) +} diff --git a/kotlin-native/backend.native/tests/codegen/lambda/lambda1.kt b/kotlin-native/backend.native/tests/codegen/lambda/lambda1.kt new file mode 100644 index 00000000000..d40793d594e --- /dev/null +++ b/kotlin-native/backend.native/tests/codegen/lambda/lambda1.kt @@ -0,0 +1,18 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +package codegen.lambda.lambda1 + +import kotlin.test.* + +@Test fun runTest() { + run { + println("lambda") + } +} + +fun run(f: () -> Unit) { + f() +} \ No newline at end of file diff --git a/kotlin-native/backend.native/tests/codegen/lambda/lambda10.kt b/kotlin-native/backend.native/tests/codegen/lambda/lambda10.kt new file mode 100644 index 00000000000..46afaadd863 --- /dev/null +++ b/kotlin-native/backend.native/tests/codegen/lambda/lambda10.kt @@ -0,0 +1,21 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +package codegen.lambda.lambda10 + +import kotlin.test.* + +@Test fun runTest() { + var str = "original" + + val lambda = { + println(str) + } + + lambda() + + str = "changed" + lambda() +} \ No newline at end of file diff --git a/kotlin-native/backend.native/tests/codegen/lambda/lambda11.kt b/kotlin-native/backend.native/tests/codegen/lambda/lambda11.kt new file mode 100644 index 00000000000..cb76f709497 --- /dev/null +++ b/kotlin-native/backend.native/tests/codegen/lambda/lambda11.kt @@ -0,0 +1,22 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +package codegen.lambda.lambda11 + +import kotlin.test.* + +@Test fun runTest() { + val first = "first" + val second = "second" + + run { + println(first) + println(second) + } +} + +fun run(f: () -> Unit) { + f() +} \ No newline at end of file diff --git a/kotlin-native/backend.native/tests/codegen/lambda/lambda12.kt b/kotlin-native/backend.native/tests/codegen/lambda/lambda12.kt new file mode 100644 index 00000000000..9101aaf11ae --- /dev/null +++ b/kotlin-native/backend.native/tests/codegen/lambda/lambda12.kt @@ -0,0 +1,17 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +package codegen.lambda.lambda12 + +import kotlin.test.* + +@Test fun runTest() { + val lambda = { s1: String, s2: String -> + println(s1) + println(s2) + } + + lambda("one", "two") +} \ No newline at end of file diff --git a/kotlin-native/backend.native/tests/codegen/lambda/lambda13.kt b/kotlin-native/backend.native/tests/codegen/lambda/lambda13.kt new file mode 100644 index 00000000000..534c444a9c8 --- /dev/null +++ b/kotlin-native/backend.native/tests/codegen/lambda/lambda13.kt @@ -0,0 +1,18 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +package codegen.lambda.lambda13 + +import kotlin.test.* + +@Test fun runTest() { + apply("foo") { + println(this) + } +} + +fun apply(str: String, block: String.() -> Unit) { + str.block() +} \ No newline at end of file diff --git a/kotlin-native/backend.native/tests/codegen/lambda/lambda14.kt b/kotlin-native/backend.native/tests/codegen/lambda/lambda14.kt new file mode 100644 index 00000000000..7d9a0d14b71 --- /dev/null +++ b/kotlin-native/backend.native/tests/codegen/lambda/lambda14.kt @@ -0,0 +1,23 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +// FILE: 1.kt + +package codegen.lambda.lambda14 + +import kotlin.test.* + +@Test fun runTest() { + assertEquals(foo()(), "foo1") + assertEquals(foo(0)(), "foo2") +} + +fun foo() = { "foo1" } + +// FILE: 2.kt + +package codegen.lambda.lambda14 + +fun foo(ignored: Int) = { "foo2" } diff --git a/kotlin-native/backend.native/tests/codegen/lambda/lambda2.kt b/kotlin-native/backend.native/tests/codegen/lambda/lambda2.kt new file mode 100644 index 00000000000..7b94afad76e --- /dev/null +++ b/kotlin-native/backend.native/tests/codegen/lambda/lambda2.kt @@ -0,0 +1,22 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +package codegen.lambda.lambda2 + +import kotlin.test.* + +@Test fun runTest() { + main(arrayOf("arg0")) +} + +fun main(args : Array) { + run { + println(args[0]) + } +} + +fun run(f: () -> Unit) { + f() +} \ No newline at end of file diff --git a/kotlin-native/backend.native/tests/codegen/lambda/lambda3.kt b/kotlin-native/backend.native/tests/codegen/lambda/lambda3.kt new file mode 100644 index 00000000000..9f7ef9bfc8a --- /dev/null +++ b/kotlin-native/backend.native/tests/codegen/lambda/lambda3.kt @@ -0,0 +1,19 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +package codegen.lambda.lambda3 + +import kotlin.test.* + +@Test fun runTest() { + var str = "lambda" + run { + println(str) + } +} + +fun run(f: () -> Unit) { + f() +} \ No newline at end of file diff --git a/kotlin-native/backend.native/tests/codegen/lambda/lambda4.kt b/kotlin-native/backend.native/tests/codegen/lambda/lambda4.kt new file mode 100644 index 00000000000..544feb1be80 --- /dev/null +++ b/kotlin-native/backend.native/tests/codegen/lambda/lambda4.kt @@ -0,0 +1,37 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +package codegen.lambda.lambda4 + +import kotlin.test.* + +@Test fun runTest() { + val lambda = bar() + lambda() + lambda() +} + +fun bar(): () -> Unit { + var x = Integer(0) + + val lambda = { + println(x.toString()) + x = x + 1 + } + + x = x + 1 + + lambda() + lambda() + + println(x.toString()) + + return lambda +} + +class Integer(val value: Int) { + override fun toString() = value.toString() + operator fun plus(other: Int) = Integer(value + other) +} \ No newline at end of file diff --git a/kotlin-native/backend.native/tests/codegen/lambda/lambda5.kt b/kotlin-native/backend.native/tests/codegen/lambda/lambda5.kt new file mode 100644 index 00000000000..de84e981929 --- /dev/null +++ b/kotlin-native/backend.native/tests/codegen/lambda/lambda5.kt @@ -0,0 +1,18 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +package codegen.lambda.lambda5 + +import kotlin.test.* + +@Test fun runTest() { + foo { + println(it) + } +} + +fun foo(f: (Int) -> Unit) { + f(42) +} \ No newline at end of file diff --git a/kotlin-native/backend.native/tests/codegen/lambda/lambda6.kt b/kotlin-native/backend.native/tests/codegen/lambda/lambda6.kt new file mode 100644 index 00000000000..fb0f08a4090 --- /dev/null +++ b/kotlin-native/backend.native/tests/codegen/lambda/lambda6.kt @@ -0,0 +1,20 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +package codegen.lambda.lambda6 + +import kotlin.test.* + +@Test fun runTest() { + val str = "captured" + foo { + println(it) + println(str) + } +} + +fun foo(f: (Int) -> Unit) { + f(42) +} \ No newline at end of file diff --git a/kotlin-native/backend.native/tests/codegen/lambda/lambda7.kt b/kotlin-native/backend.native/tests/codegen/lambda/lambda7.kt new file mode 100644 index 00000000000..cdd0e46a697 --- /dev/null +++ b/kotlin-native/backend.native/tests/codegen/lambda/lambda7.kt @@ -0,0 +1,17 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +package codegen.lambda.lambda7 + +import kotlin.test.* + +@Test fun runTest() { + val x = foo { + it + 1 + } + println(x) +} + +fun foo(f: (Int) -> Int) = f(42) \ No newline at end of file diff --git a/kotlin-native/backend.native/tests/codegen/lambda/lambda8.kt b/kotlin-native/backend.native/tests/codegen/lambda/lambda8.kt new file mode 100644 index 00000000000..0ff6c8eac44 --- /dev/null +++ b/kotlin-native/backend.native/tests/codegen/lambda/lambda8.kt @@ -0,0 +1,33 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +package codegen.lambda.lambda8 + +import kotlin.test.* + +@Test fun runTest() { + val lambda1 = bar("first") + val lambda2 = bar("second") + + lambda1() + lambda2() + lambda1() + lambda2() +} + +fun bar(str: String): () -> Unit { + var x = Integer(0) + + return { + println(str) + println(x.toString()) + x = x + 1 + } +} + +class Integer(val value: Int) { + override fun toString() = value.toString() + operator fun plus(other: Int) = Integer(value + other) +} \ No newline at end of file diff --git a/kotlin-native/backend.native/tests/codegen/lambda/lambda9.kt b/kotlin-native/backend.native/tests/codegen/lambda/lambda9.kt new file mode 100644 index 00000000000..bb281a5155b --- /dev/null +++ b/kotlin-native/backend.native/tests/codegen/lambda/lambda9.kt @@ -0,0 +1,36 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +package codegen.lambda.lambda9 + +import kotlin.test.* + +@Test fun runTest() { + val lambdas = ArrayList<() -> Unit>() + + for (i in 0..1) { + var x = Integer(0) + val istr = i.toString() + + lambdas.add { + println(istr) + println(x.toString()) + x = x + 1 + } + } + + val lambda1 = lambdas[0] + val lambda2 = lambdas[1] + + lambda1() + lambda2() + lambda1() + lambda2() +} + +class Integer(val value: Int) { + override fun toString() = value.toString() + operator fun plus(other: Int) = Integer(value + other) +} \ No newline at end of file diff --git a/kotlin-native/backend.native/tests/codegen/lateinit/globalIsInitialized.kt b/kotlin-native/backend.native/tests/codegen/lateinit/globalIsInitialized.kt new file mode 100644 index 00000000000..7230c3c98e8 --- /dev/null +++ b/kotlin-native/backend.native/tests/codegen/lateinit/globalIsInitialized.kt @@ -0,0 +1,20 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +package codegen.lateinit.globalIsInitialized + +import kotlin.test.* + +lateinit var s: String + +fun foo() { + println(::s.isInitialized) +} + +@Test fun runTest() { + foo() + s = "zzz" + foo() +} \ No newline at end of file diff --git a/kotlin-native/backend.native/tests/codegen/lateinit/inBaseClass.kt b/kotlin-native/backend.native/tests/codegen/lateinit/inBaseClass.kt new file mode 100644 index 00000000000..e21be883db8 --- /dev/null +++ b/kotlin-native/backend.native/tests/codegen/lateinit/inBaseClass.kt @@ -0,0 +1,24 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +package codegen.lateinit.inBaseClass + +import kotlin.test.* + +class A(val a: Int) + +open class B { + lateinit var a: A +} + +class C: B() { + fun foo() { a = A(42) } +} + +@Test fun runTest() { + val c = C() + c.foo() + println(c.a.a) +} diff --git a/kotlin-native/backend.native/tests/codegen/lateinit/initialized.kt b/kotlin-native/backend.native/tests/codegen/lateinit/initialized.kt new file mode 100644 index 00000000000..ada8507493d --- /dev/null +++ b/kotlin-native/backend.native/tests/codegen/lateinit/initialized.kt @@ -0,0 +1,20 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +package codegen.lateinit.initialized + +import kotlin.test.* + +class A { + lateinit var s: String + + fun foo() = s +} + +@Test fun runTest() { + val a = A() + a.s = "zzz" + println(a.foo()) +} \ No newline at end of file diff --git a/kotlin-native/backend.native/tests/codegen/lateinit/innerIsInitialized.kt b/kotlin-native/backend.native/tests/codegen/lateinit/innerIsInitialized.kt new file mode 100644 index 00000000000..b8411ab5d1c --- /dev/null +++ b/kotlin-native/backend.native/tests/codegen/lateinit/innerIsInitialized.kt @@ -0,0 +1,28 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +package codegen.lateinit.innerIsInitialized + +import kotlin.test.* + +open class Foo { + lateinit var bar: String + + fun test(): String { + return InnerSubclass().testInner() + } + + inner class InnerSubclass : Foo() { + fun testInner(): String { + // This is access to InnerSubclass.bar which is inherited from Foo.bar + if (this::bar.isInitialized) return "Fail" + return "OK" + } + } +} + +@Test fun runTest() { + println(Foo().test()) +} diff --git a/kotlin-native/backend.native/tests/codegen/lateinit/isInitialized.kt b/kotlin-native/backend.native/tests/codegen/lateinit/isInitialized.kt new file mode 100644 index 00000000000..9c69400d235 --- /dev/null +++ b/kotlin-native/backend.native/tests/codegen/lateinit/isInitialized.kt @@ -0,0 +1,23 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +package codegen.lateinit.isInitialized + +import kotlin.test.* + +class A { + lateinit var s: String + + fun foo() { + println(::s.isInitialized) + } +} + +@Test fun runTest() { + val a = A() + a.foo() + a.s = "zzz" + a.foo() +} \ No newline at end of file diff --git a/kotlin-native/backend.native/tests/codegen/lateinit/localCapturedInitialized.kt b/kotlin-native/backend.native/tests/codegen/lateinit/localCapturedInitialized.kt new file mode 100644 index 00000000000..19449a0644f --- /dev/null +++ b/kotlin-native/backend.native/tests/codegen/lateinit/localCapturedInitialized.kt @@ -0,0 +1,17 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +package codegen.lateinit.localCapturedInitialized + +import kotlin.test.* + +@Test fun runTest() { + lateinit var s: String + + fun foo() = s + + s = "zzz" + println(foo()) +} \ No newline at end of file diff --git a/kotlin-native/backend.native/tests/codegen/lateinit/localCapturedNotInitialized.kt b/kotlin-native/backend.native/tests/codegen/lateinit/localCapturedNotInitialized.kt new file mode 100644 index 00000000000..0d66a6c07be --- /dev/null +++ b/kotlin-native/backend.native/tests/codegen/lateinit/localCapturedNotInitialized.kt @@ -0,0 +1,23 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +package codegen.lateinit.localCapturedNotInitialized + +import kotlin.test.* + +@Test fun runTest() { + lateinit var s: String + + fun foo() = s + + try { + println(foo()) + } + catch (e: RuntimeException) { + println("OK") + return + } + println("Fail") +} \ No newline at end of file diff --git a/kotlin-native/backend.native/tests/codegen/lateinit/localInitialized.kt b/kotlin-native/backend.native/tests/codegen/lateinit/localInitialized.kt new file mode 100644 index 00000000000..446ef98a2ce --- /dev/null +++ b/kotlin-native/backend.native/tests/codegen/lateinit/localInitialized.kt @@ -0,0 +1,14 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +package codegen.lateinit.localInitialized + +import kotlin.test.* + +@Test fun runTest() { + lateinit var s: String + s = "zzz" + println(s) +} \ No newline at end of file diff --git a/kotlin-native/backend.native/tests/codegen/lateinit/localNotInitialized.kt b/kotlin-native/backend.native/tests/codegen/lateinit/localNotInitialized.kt new file mode 100644 index 00000000000..dbed93596b2 --- /dev/null +++ b/kotlin-native/backend.native/tests/codegen/lateinit/localNotInitialized.kt @@ -0,0 +1,21 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +package codegen.lateinit.localNotInitialized + +import kotlin.test.* + +@Test fun runTest() { + lateinit var s: String + + try { + println(s) + } + catch (e: RuntimeException) { + println("OK") + return + } + println("Fail") +} \ No newline at end of file diff --git a/kotlin-native/backend.native/tests/codegen/lateinit/notInitialized.kt b/kotlin-native/backend.native/tests/codegen/lateinit/notInitialized.kt new file mode 100644 index 00000000000..b42906e55b4 --- /dev/null +++ b/kotlin-native/backend.native/tests/codegen/lateinit/notInitialized.kt @@ -0,0 +1,26 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +package codegen.lateinit.notInitialized + +import kotlin.test.* + +class A { + lateinit var s: String + + fun foo() = s +} + +@Test fun runTest() { + val a = A() + try { + println(a.foo()) + } + catch (e: RuntimeException) { + println("OK") + return + } + println("Fail") +} \ No newline at end of file diff --git a/kotlin-native/backend.native/tests/codegen/localClass/innerTakesCapturedFromOuter.kt b/kotlin-native/backend.native/tests/codegen/localClass/innerTakesCapturedFromOuter.kt new file mode 100644 index 00000000000..c06dc27a3e5 --- /dev/null +++ b/kotlin-native/backend.native/tests/codegen/localClass/innerTakesCapturedFromOuter.kt @@ -0,0 +1,27 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +package codegen.localClass.innerTakesCapturedFromOuter + +import kotlin.test.* + +fun box() { + var previous: Any? = null + for (i in 0 .. 2) { + class Outer { + inner class Inner { + override fun toString() = i.toString() + } + + override fun toString() = Inner().toString() + } + if (previous != null) println(previous.toString()) + previous = Outer() + } +} + +@Test fun runTest() { + box() +} \ No newline at end of file diff --git a/kotlin-native/backend.native/tests/codegen/localClass/innerWithCapture.kt b/kotlin-native/backend.native/tests/codegen/localClass/innerWithCapture.kt new file mode 100644 index 00000000000..82d4eaee3ae --- /dev/null +++ b/kotlin-native/backend.native/tests/codegen/localClass/innerWithCapture.kt @@ -0,0 +1,22 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +package codegen.localClass.innerWithCapture + +import kotlin.test.* + +fun box(s: String): String { + class Local { + open inner class Inner() { + open fun result() = s + } + } + + return Local().Inner().result() +} + +@Test fun runTest() { + println(box("OK")) +} \ No newline at end of file diff --git a/kotlin-native/backend.native/tests/codegen/localClass/localFunctionCallFromLocalClass.kt b/kotlin-native/backend.native/tests/codegen/localClass/localFunctionCallFromLocalClass.kt new file mode 100644 index 00000000000..d8a426c515d --- /dev/null +++ b/kotlin-native/backend.native/tests/codegen/localClass/localFunctionCallFromLocalClass.kt @@ -0,0 +1,23 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +package codegen.localClass.localFunctionCallFromLocalClass + +import kotlin.test.* + +@Test fun runTest() { + var x = 1 + fun local1() { + x++ + } + + class A { + fun bar() { + local1() + } + } + A().bar() + println("OK") +} \ No newline at end of file diff --git a/kotlin-native/backend.native/tests/codegen/localClass/localFunctionInLocalClass.kt b/kotlin-native/backend.native/tests/codegen/localClass/localFunctionInLocalClass.kt new file mode 100644 index 00000000000..df9f3051645 --- /dev/null +++ b/kotlin-native/backend.native/tests/codegen/localClass/localFunctionInLocalClass.kt @@ -0,0 +1,30 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +package codegen.localClass.localFunctionInLocalClass + +import kotlin.test.* + +@Test fun runTest() { + var x = 0 + class A { + fun bar() { + fun local() { + class B { + fun baz() { + fun local2() { + x++ + } + local2() + } + } + B().baz() + } + local() + } + } + A().bar() + println("OK") +} \ No newline at end of file diff --git a/kotlin-native/backend.native/tests/codegen/localClass/localHierarchy.kt b/kotlin-native/backend.native/tests/codegen/localClass/localHierarchy.kt new file mode 100644 index 00000000000..dae25bfe043 --- /dev/null +++ b/kotlin-native/backend.native/tests/codegen/localClass/localHierarchy.kt @@ -0,0 +1,24 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +package codegen.localClass.localHierarchy + +import kotlin.test.* + +fun foo(s: String): String { + open class Local { + fun f() = s + } + + open class Derived: Local() { + fun g() = f() + } + + return Derived().g() +} + +@Test fun runTest() { + println(foo("OK")) +} \ No newline at end of file diff --git a/kotlin-native/backend.native/tests/codegen/localClass/noPrimaryConstructor.kt b/kotlin-native/backend.native/tests/codegen/localClass/noPrimaryConstructor.kt new file mode 100644 index 00000000000..d1ea6acb7bc --- /dev/null +++ b/kotlin-native/backend.native/tests/codegen/localClass/noPrimaryConstructor.kt @@ -0,0 +1,30 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +package codegen.localClass.noPrimaryConstructor + +import kotlin.test.* + +fun box(s: String): String { + class Local { + constructor(x: Int) { + this.x = x + } + + constructor(z: String) { + x = z.length + } + + val x: Int + + fun result() = s + } + + return Local(42).result() + Local("zzz").result() +} + +@Test fun runTest() { + println(box("OK")) +} \ No newline at end of file diff --git a/kotlin-native/backend.native/tests/codegen/localClass/objectExpressionInInitializer.kt b/kotlin-native/backend.native/tests/codegen/localClass/objectExpressionInInitializer.kt new file mode 100644 index 00000000000..8678f840645 --- /dev/null +++ b/kotlin-native/backend.native/tests/codegen/localClass/objectExpressionInInitializer.kt @@ -0,0 +1,34 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +package codegen.localClass.objectExpressionInInitializer + +import kotlin.test.* + +abstract class Father { + abstract inner class InClass { + abstract fun work(): String + } +} + +class Child : Father() { + val ChildInClass : InClass + + init { + ChildInClass = object : Father.InClass() { + override fun work(): String { + return "OK" + } + } + } +} + +fun box(): String { + return Child().ChildInClass.work() +} + +@Test fun runTest() { + println(box()) +} \ No newline at end of file diff --git a/kotlin-native/backend.native/tests/codegen/localClass/objectExpressionInProperty.kt b/kotlin-native/backend.native/tests/codegen/localClass/objectExpressionInProperty.kt new file mode 100644 index 00000000000..b9b1a0fcd5f --- /dev/null +++ b/kotlin-native/backend.native/tests/codegen/localClass/objectExpressionInProperty.kt @@ -0,0 +1,30 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +package codegen.localClass.objectExpressionInProperty + +import kotlin.test.* + +abstract class Father { + abstract inner class InClass { + abstract fun work(): String + } +} + +class Child : Father() { + val ChildInClass = object : Father.InClass() { + override fun work(): String { + return "OK" + } + } +} + +fun box(): String { + return Child().ChildInClass.work() +} + +@Test fun runTest() { + println(box()) +} \ No newline at end of file diff --git a/kotlin-native/backend.native/tests/codegen/localClass/tryCatch.kt b/kotlin-native/backend.native/tests/codegen/localClass/tryCatch.kt new file mode 100644 index 00000000000..67f588d2de7 --- /dev/null +++ b/kotlin-native/backend.native/tests/codegen/localClass/tryCatch.kt @@ -0,0 +1,25 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +package codegen.localClass.tryCatch + +import kotlin.test.* + +private fun foo() { + val local = + object { + fun bar() { + try { + } catch (t: Throwable) { + println(t) + } + } + } + local.bar() +} + +@Test fun runTest() { + foo() +} \ No newline at end of file diff --git a/kotlin-native/backend.native/tests/codegen/localClass/virtualCallFromConstructor.kt b/kotlin-native/backend.native/tests/codegen/localClass/virtualCallFromConstructor.kt new file mode 100644 index 00000000000..95c75365179 --- /dev/null +++ b/kotlin-native/backend.native/tests/codegen/localClass/virtualCallFromConstructor.kt @@ -0,0 +1,34 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +package codegen.localClass.virtualCallFromConstructor + +import kotlin.test.* + +abstract class WaitFor { + init { + condition() + } + + abstract fun condition(): Boolean; +} + +fun box(): String { + val local = "" + var result = "fail" + val s = object : WaitFor() { + + override fun condition(): Boolean { + result = "OK" + return result.length == 2 + } + } + + return result; +} + +@Test fun runTest() { + println(box()) +} \ No newline at end of file diff --git a/kotlin-native/backend.native/tests/codegen/localEscapeAnalysis/arraysFieldWrite.kt b/kotlin-native/backend.native/tests/codegen/localEscapeAnalysis/arraysFieldWrite.kt new file mode 100644 index 00000000000..75098792ac8 --- /dev/null +++ b/kotlin-native/backend.native/tests/codegen/localEscapeAnalysis/arraysFieldWrite.kt @@ -0,0 +1,73 @@ +/* + * Copyright 2010-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +class ArraysConstructor { + private val memberArray: IntArray + constructor(int1: Int, int2: Int) { + memberArray = IntArray(2) + set(int1, int2) + } + fun set(int1: Int, int2: Int) { + memberArray[0] = int1 + memberArray[1] = int2 + } + fun log() { + println("Array (constructor init):") + println("Size: ${memberArray.size}") + println("Contents: ${memberArray.contentToString()}") + } +} + +class ArraysDefault { + private val memberArray = IntArray(2) + constructor(int1: Int, int2: Int) { + set(int1, int2) + } + fun set(int1: Int, int2: Int) { + memberArray[0] = int1 + memberArray[1] = int2 + } + fun log() { + println("Array (default value init):") + println("Size: ${memberArray.size}") + println("Contents: ${memberArray.contentToString()}") + } +} + +class ArraysInitBlock { + private val memberArray : IntArray + init { + memberArray = IntArray(2) + } + constructor(int1: Int, int2: Int) { + set(int1, int2) + } + fun set(int1: Int, int2: Int) { + memberArray[0] = int1 + memberArray[1] = int2 + } + fun log() { + println("Array (init block):") + println("Size: ${memberArray.size}") + println("Contents: ${memberArray.contentToString()}") + } +} + +fun main() { + val array1 = (::ArraysConstructor)(1, 2) + array1.log() + array1.set( 3, 4) + array1.log() + + val array2 = (::ArraysDefault)(1, 2) + array2.log() + array2.set( 3, 4) + array2.log() + + val array3 = (::ArraysInitBlock)(1, 2) + array3.log() + array3.set( 3, 4) + array3.log() +} \ No newline at end of file diff --git a/kotlin-native/backend.native/tests/codegen/mpp/libmpp2.kt b/kotlin-native/backend.native/tests/codegen/mpp/libmpp2.kt new file mode 100644 index 00000000000..f8ae8e6da57 --- /dev/null +++ b/kotlin-native/backend.native/tests/codegen/mpp/libmpp2.kt @@ -0,0 +1,21 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +expect class C { + constructor(arg: Any?) +} + +actual data class C actual constructor(val arg: Any?) { + +} + +expect class T +actual typealias T = C + +expect fun f(arg: Int): Int +actual fun f(arg: Int) = arg + +expect var p: String +actual var p: String = "p" diff --git a/kotlin-native/backend.native/tests/codegen/mpp/mpp1.kt b/kotlin-native/backend.native/tests/codegen/mpp/mpp1.kt new file mode 100644 index 00000000000..312b5ba11c0 --- /dev/null +++ b/kotlin-native/backend.native/tests/codegen/mpp/mpp1.kt @@ -0,0 +1,36 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +package codegen.mpp.mpp1 + +import kotlin.test.* + +fun box() { + assertEquals(A().B().fourtyTwo(), 42) + assertEquals(seventeen(), 17) +} + +expect class A { + constructor() + + inner class B { + fun fourtyTwo(): Int + + constructor() + } +} + +actual class A { + actual inner class B actual constructor() { + actual fun fourtyTwo() = 42 + } +} + +actual fun seventeen() = 17 +expect fun seventeen(): Int + +@Test fun runTest() { + box() +} diff --git a/kotlin-native/backend.native/tests/codegen/mpp/mpp2.kt b/kotlin-native/backend.native/tests/codegen/mpp/mpp2.kt new file mode 100644 index 00000000000..0d370f2d46d --- /dev/null +++ b/kotlin-native/backend.native/tests/codegen/mpp/mpp2.kt @@ -0,0 +1,13 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +fun main(args: Array) { + println(C(42)) + println(C(42) is T) + println(f(1)) + + p = "h" + println(p) +} diff --git a/kotlin-native/backend.native/tests/codegen/mpp/mpp_default_args.kt b/kotlin-native/backend.native/tests/codegen/mpp/mpp_default_args.kt new file mode 100644 index 00000000000..6164e2d76d2 --- /dev/null +++ b/kotlin-native/backend.native/tests/codegen/mpp/mpp_default_args.kt @@ -0,0 +1,75 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +package codegen.mpp.mpp_default_args + +import kotlin.test.* + +@Test fun runTest() { + box() +} + +fun box() { + assertEquals(test1(), 42) + assertEquals(test2(17), 34) + assertEquals(test3(), -1) + + Test4().test() + Test5().Inner().test() + + 42.test6() + assertEquals(inlineFunction("OK"), "OK,0,null") +} + +expect fun test1(x: Int = 42): Int +actual fun test1(x: Int) = x + +expect fun test2(x: Int, y: Int = x): Int +actual fun test2(x: Int, y: Int) = x + y + +expect fun test3(x: Int = 42, y: Int = x + 1): Int +actual fun test3(x: Int, y: Int) = x - y + +expect class Test4 { + fun test(arg: Any = this) +} + +actual class Test4 { + actual fun test(arg: Any) { + assertEquals(arg, this) + } +} + +expect class Test5 { + inner class Inner { + constructor(arg: Any = this@Test5) + + fun test(arg1: Any = this@Test5, arg2: Any = this@Inner) + } +} + +actual class Test5 { + actual inner class Inner { + actual constructor(arg: Any) { + assertEquals(arg, this@Test5) + } + + actual fun test(arg1: Any, arg2: Any) { + assertEquals(arg1, this@Test5) + assertEquals(arg2, this@Inner) + } + } +} + +expect fun Int.test6(arg: Int = this) +actual fun Int.test6(arg: Int) { + assertEquals(arg, this) +} + +// Default parameter in inline function. +expect inline fun inlineFunction(a: String, b: Int = 0, c: () -> Double? = { null }): String + +actual inline fun inlineFunction(a: String, b: Int, c: () -> Double?): String = a + "," + b + "," + c() + diff --git a/kotlin-native/backend.native/tests/codegen/mpp/mpp_optional_expectation.kt b/kotlin-native/backend.native/tests/codegen/mpp/mpp_optional_expectation.kt new file mode 100644 index 00000000000..42ff5550055 --- /dev/null +++ b/kotlin-native/backend.native/tests/codegen/mpp/mpp_optional_expectation.kt @@ -0,0 +1,17 @@ +@file:Suppress("EXPERIMENTAL_API_USAGE_ERROR") + +import kotlin.js.* + +@OptionalExpectation +expect annotation class Optional() + +@Optional +fun foo() { println(42) } + +@JsName("jsBar") +fun bar() { println(43) } + +fun main(args: Array) { + foo() + bar() +} \ No newline at end of file diff --git a/kotlin-native/backend.native/tests/codegen/object/constructor.kt b/kotlin-native/backend.native/tests/codegen/object/constructor.kt new file mode 100644 index 00000000000..e9ca664df35 --- /dev/null +++ b/kotlin-native/backend.native/tests/codegen/object/constructor.kt @@ -0,0 +1,12 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +package codegen.`object`.constructor + +class A() + +class B(val a:Int) + +class C(val a:Int, b:Int) \ No newline at end of file diff --git a/kotlin-native/backend.native/tests/codegen/object/constructor0.kt b/kotlin-native/backend.native/tests/codegen/object/constructor0.kt new file mode 100644 index 00000000000..faf5829cf4f --- /dev/null +++ b/kotlin-native/backend.native/tests/codegen/object/constructor0.kt @@ -0,0 +1,15 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +package codegen.`object`.constructor0 + +import kotlin.test.* + +class A { + var field0:Int = 0; + constructor(arg0:Int) { + field0 = arg0 + } +} diff --git a/kotlin-native/backend.native/tests/codegen/object/fields.kt b/kotlin-native/backend.native/tests/codegen/object/fields.kt new file mode 100644 index 00000000000..295cc83ba52 --- /dev/null +++ b/kotlin-native/backend.native/tests/codegen/object/fields.kt @@ -0,0 +1,25 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +package codegen.`object`.fields + +import kotlin.test.* + +private var globalValue = 1 +var global:Int + get() = globalValue + set(value:Int) {globalValue = value} + +fun globalTest(i:Int):Int { + global += i + return global +} + + +@Test fun runTest() { + if (global != 1) throw Error() + if (globalTest(41) != 42) throw Error() + if (global != 42) throw Error() +} \ No newline at end of file diff --git a/kotlin-native/backend.native/tests/codegen/object/fields1.kt b/kotlin-native/backend.native/tests/codegen/object/fields1.kt new file mode 100644 index 00000000000..d86d6ca43d2 --- /dev/null +++ b/kotlin-native/backend.native/tests/codegen/object/fields1.kt @@ -0,0 +1,22 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +package codegen.`object`.fields1 + +import kotlin.test.* + +class B(val a:Int, b:Int) { + constructor(pos:Int):this(1, pos) {} + val pos = b + 1 +} + +fun primaryConstructorCall(a:Int, b:Int) = B(a, b).pos + +fun secondaryConstructorCall(a:Int) = B(a).pos + +@Test fun runTest() { + if (primaryConstructorCall(0xdeadbeef.toInt(), 41) != 42) throw Error() + if (secondaryConstructorCall(41) != 42) throw Error() +} \ No newline at end of file diff --git a/kotlin-native/backend.native/tests/codegen/object/fields2.kt b/kotlin-native/backend.native/tests/codegen/object/fields2.kt new file mode 100644 index 00000000000..defec5342a7 --- /dev/null +++ b/kotlin-native/backend.native/tests/codegen/object/fields2.kt @@ -0,0 +1,55 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +package codegen.`object`.fields2 + +import kotlin.test.* + +var global: Int = 0 + get() { + println("Get global = $field") + return field + } + set(value) { + println("Set global = $value") + field = value + } + +class TestClass { + var member: Int = 0 + get() { + println("Get member = $field") + return field + } + set(value) { + println("Set member = $value") + field = value + } +} + +@Test fun runTest1() { + global = 1 + + val test = TestClass() + test.member = 42 + + global = test.member + test.member = global +} + +@ThreadLocal +val xInt = 42 + +@ThreadLocal +val xString = "42" + +@ThreadLocal +val xAny = Any() + +@Test fun runTest2() { + assertEquals(42, xInt) + assertEquals("42", xString) + assertTrue(xAny is Any) +} diff --git a/kotlin-native/backend.native/tests/codegen/object/globalInitializer.kt b/kotlin-native/backend.native/tests/codegen/object/globalInitializer.kt new file mode 100644 index 00000000000..1ac31a56090 --- /dev/null +++ b/kotlin-native/backend.native/tests/codegen/object/globalInitializer.kt @@ -0,0 +1,12 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +// Does not fail with TR. + +public val z: Any = Z + +private object Z + +fun main(args: Array) { } \ No newline at end of file diff --git a/kotlin-native/backend.native/tests/codegen/object/init0.kt b/kotlin-native/backend.native/tests/codegen/object/init0.kt new file mode 100644 index 00000000000..e574977f809 --- /dev/null +++ b/kotlin-native/backend.native/tests/codegen/object/init0.kt @@ -0,0 +1,15 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +package codegen.`object`.init0 + +import kotlin.test.* + +class A(a:Int) { + var i:Int = 0 + init { + if (a == 0) i = 1 + } +} \ No newline at end of file diff --git a/kotlin-native/backend.native/tests/codegen/object/initialization.kt b/kotlin-native/backend.native/tests/codegen/object/initialization.kt new file mode 100644 index 00000000000..a6423d122c2 --- /dev/null +++ b/kotlin-native/backend.native/tests/codegen/object/initialization.kt @@ -0,0 +1,33 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +package codegen.`object`.initialization + +import kotlin.test.* + +open class A(val a:Int, val b:Int) + +open class B(val c:Int, d:Int):A(c, d) + +open class C(i:Int, j:Int):B(i + j, 42) + +class D (i: Int, j:Int) : C(i, j){ + constructor(i: Int, j:Int, k:Int) : this(i, j) { + foo(i) + } + constructor():this(1, 2) +} + +fun foo(i:Int) : Unit {} + + +fun foo(i:Int, j:Int):Int { + val c = D(i, j) + return c.c +} + +@Test fun runTest() { + if (foo(2, 3) != 5) throw Error() +} \ No newline at end of file diff --git a/kotlin-native/backend.native/tests/codegen/object/initialization1.kt b/kotlin-native/backend.native/tests/codegen/object/initialization1.kt new file mode 100644 index 00000000000..18121584c6b --- /dev/null +++ b/kotlin-native/backend.native/tests/codegen/object/initialization1.kt @@ -0,0 +1,29 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +package codegen.`object`.initialization1 + +import kotlin.test.* + +class TestClass { + constructor() { + println("constructor1") + } + + constructor(x: Int) : this() { + println("constructor2") + } + + init { + println("init") + } + + val f = println("field") +} + +@Test fun runTest() { + TestClass() + TestClass(1) +} \ No newline at end of file diff --git a/kotlin-native/backend.native/tests/codegen/object/method_call.kt b/kotlin-native/backend.native/tests/codegen/object/method_call.kt new file mode 100644 index 00000000000..a670edbb1b5 --- /dev/null +++ b/kotlin-native/backend.native/tests/codegen/object/method_call.kt @@ -0,0 +1,18 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +package codegen.`object`.method_call + +import kotlin.test.* + +class A(val a:Int) { + fun foo(i:Int) = a + i +} + +fun fortyTwo() = A(41).foo(1) + +@Test fun runTest() { + if (fortyTwo() != 42) throw Error() +} \ No newline at end of file diff --git a/kotlin-native/backend.native/tests/codegen/objectExpression/expr1.kt b/kotlin-native/backend.native/tests/codegen/objectExpression/expr1.kt new file mode 100644 index 00000000000..93a718c9a36 --- /dev/null +++ b/kotlin-native/backend.native/tests/codegen/objectExpression/expr1.kt @@ -0,0 +1,22 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +package codegen.objectExpression.expr1 + +import kotlin.test.* + +@Test fun runTest() { + val a = "a" + + val x = object { + override fun toString(): String { + return foo(a) + foo("b") + } + + fun foo(s: String) = s + s + } + + println(x.toString()) +} \ No newline at end of file diff --git a/kotlin-native/backend.native/tests/codegen/objectExpression/expr2.kt b/kotlin-native/backend.native/tests/codegen/objectExpression/expr2.kt new file mode 100644 index 00000000000..8efb6677aa4 --- /dev/null +++ b/kotlin-native/backend.native/tests/codegen/objectExpression/expr2.kt @@ -0,0 +1,25 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +package codegen.objectExpression.expr2 +import kotlin.test.* + +@Test fun runTest() { + val a = "a" + + val x = object { + override fun toString(): String { + return foo { + a + } + } + + fun foo(lambda: () -> String) = lambda() + } + + print(x) +} + +fun print(x: Any) = println(x.toString()) \ No newline at end of file diff --git a/kotlin-native/backend.native/tests/codegen/objectExpression/expr3.kt b/kotlin-native/backend.native/tests/codegen/objectExpression/expr3.kt new file mode 100644 index 00000000000..438478090c6 --- /dev/null +++ b/kotlin-native/backend.native/tests/codegen/objectExpression/expr3.kt @@ -0,0 +1,26 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +package codegen.objectExpression.expr3 + +import kotlin.test.* + +@Test fun runTest() { + var cnt = 0 + + var x: Any = "" + + for (i in 0 .. 1) { + print(x) + cnt++ + val y = object { + override fun toString() = cnt.toString() + } + x = y + } + print(x) +} + +fun print(x: Any) = println(x.toString()) \ No newline at end of file diff --git a/kotlin-native/backend.native/tests/codegen/propertyCallableReference/dynamicReceiver.kt b/kotlin-native/backend.native/tests/codegen/propertyCallableReference/dynamicReceiver.kt new file mode 100644 index 00000000000..726f42ed825 --- /dev/null +++ b/kotlin-native/backend.native/tests/codegen/propertyCallableReference/dynamicReceiver.kt @@ -0,0 +1,21 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +package codegen.propertyCallableReference.dynamicReceiver + +import kotlin.test.* + +class TestClass { + var x: Int = 42 +} + +fun foo(): TestClass { + println(42) + return TestClass() +} + +@Test fun runTest() { + foo()::x +} \ No newline at end of file diff --git a/kotlin-native/backend.native/tests/codegen/propertyCallableReference/linkTest_lib.kt b/kotlin-native/backend.native/tests/codegen/propertyCallableReference/linkTest_lib.kt new file mode 100644 index 00000000000..d85930a4974 --- /dev/null +++ b/kotlin-native/backend.native/tests/codegen/propertyCallableReference/linkTest_lib.kt @@ -0,0 +1,8 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +package a + +class A(val x: Int) \ No newline at end of file diff --git a/kotlin-native/backend.native/tests/codegen/propertyCallableReference/linkTest_main.kt b/kotlin-native/backend.native/tests/codegen/propertyCallableReference/linkTest_main.kt new file mode 100644 index 00000000000..0d122653f82 --- /dev/null +++ b/kotlin-native/backend.native/tests/codegen/propertyCallableReference/linkTest_main.kt @@ -0,0 +1,14 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +import a.A + +fun main(args: Array) { + val p1 = A::x + println(p1.get(A(42))) + val a = A(117) + val p2 = a::x + println(p2.get()) +} \ No newline at end of file diff --git a/kotlin-native/backend.native/tests/codegen/propertyCallableReference/valClass.kt b/kotlin-native/backend.native/tests/codegen/propertyCallableReference/valClass.kt new file mode 100644 index 00000000000..6f23a2e3100 --- /dev/null +++ b/kotlin-native/backend.native/tests/codegen/propertyCallableReference/valClass.kt @@ -0,0 +1,18 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +package codegen.propertyCallableReference.valClass + +import kotlin.test.* + +class A(val x: Int) + +@Test fun runTest() { + val p1 = A::x + println(p1.get(A(42))) + val a = A(117) + val p2 = a::x + println(p2.get()) +} \ No newline at end of file diff --git a/kotlin-native/backend.native/tests/codegen/propertyCallableReference/valExtension.kt b/kotlin-native/backend.native/tests/codegen/propertyCallableReference/valExtension.kt new file mode 100644 index 00000000000..85bc5e9b919 --- /dev/null +++ b/kotlin-native/backend.native/tests/codegen/propertyCallableReference/valExtension.kt @@ -0,0 +1,22 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +package codegen.propertyCallableReference.valExtension + +import kotlin.test.* + +class A(y: Int) { + var x = y +} + +val A.z get() = this.x + +@Test fun runTest() { + val p1 = A::z + println(p1.get(A(42))) + val a = A(117) + val p2 = a::z + println(p2.get()) +} \ No newline at end of file diff --git a/kotlin-native/backend.native/tests/codegen/propertyCallableReference/valModule.kt b/kotlin-native/backend.native/tests/codegen/propertyCallableReference/valModule.kt new file mode 100644 index 00000000000..edc3109846b --- /dev/null +++ b/kotlin-native/backend.native/tests/codegen/propertyCallableReference/valModule.kt @@ -0,0 +1,15 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +package codegen.propertyCallableReference.valModule + +import kotlin.test.* + +val x = 42 + +@Test fun runTest() { + val p = ::x + println(p.get()) +} \ No newline at end of file diff --git a/kotlin-native/backend.native/tests/codegen/propertyCallableReference/varClass.kt b/kotlin-native/backend.native/tests/codegen/propertyCallableReference/varClass.kt new file mode 100644 index 00000000000..fc89021ee59 --- /dev/null +++ b/kotlin-native/backend.native/tests/codegen/propertyCallableReference/varClass.kt @@ -0,0 +1,22 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +package codegen.propertyCallableReference.varClass + +import kotlin.test.* + +class A(var x: Int) + +@Test fun runTest() { + val p1 = A::x + val a = A(42) + p1.set(a, 117) + println(a.x) + println(p1.get(a)) + val p2 = a::x + p2.set(42) + println(a.x) + println(p2.get()) +} \ No newline at end of file diff --git a/kotlin-native/backend.native/tests/codegen/propertyCallableReference/varExtension.kt b/kotlin-native/backend.native/tests/codegen/propertyCallableReference/varExtension.kt new file mode 100644 index 00000000000..4e2fba76601 --- /dev/null +++ b/kotlin-native/backend.native/tests/codegen/propertyCallableReference/varExtension.kt @@ -0,0 +1,30 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +package codegen.propertyCallableReference.varExtension + +import kotlin.test.* + +class A(y: Int) { + var x = y +} + +var A.z: Int + get() = this.x + set(value: Int) { + this.x = value + } + +@Test fun runTest() { + val p1 = A::z + val a = A(42) + p1.set(a, 117) + println(a.x) + println(p1.get(a)) + val p2 = a::z + p2.set(42) + println(a.x) + println(p2.get()) +} \ No newline at end of file diff --git a/kotlin-native/backend.native/tests/codegen/propertyCallableReference/varModule.kt b/kotlin-native/backend.native/tests/codegen/propertyCallableReference/varModule.kt new file mode 100644 index 00000000000..c0316406ae8 --- /dev/null +++ b/kotlin-native/backend.native/tests/codegen/propertyCallableReference/varModule.kt @@ -0,0 +1,17 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +package codegen.propertyCallableReference.varModule + +import kotlin.test.* + +var x = 42 + +@Test fun runTest() { + val p = ::x + p.set(117) + println(x) + println(p.get()) +} \ No newline at end of file diff --git a/kotlin-native/backend.native/tests/codegen/try/catch3.kt b/kotlin-native/backend.native/tests/codegen/try/catch3.kt new file mode 100644 index 00000000000..5afc7f64e1b --- /dev/null +++ b/kotlin-native/backend.native/tests/codegen/try/catch3.kt @@ -0,0 +1,20 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +package codegen.`try`.catch3 + +import kotlin.test.* + +@Test fun runTest() { + try { + println("Before") + throw Error("Error happens") + println("After") + } catch (e: Throwable) { + println("Caught Throwable") + } + + println("Done") +} \ No newline at end of file diff --git a/kotlin-native/backend.native/tests/codegen/try/catch4.kt b/kotlin-native/backend.native/tests/codegen/try/catch4.kt new file mode 100644 index 00000000000..99ed3677405 --- /dev/null +++ b/kotlin-native/backend.native/tests/codegen/try/catch4.kt @@ -0,0 +1,24 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +package codegen.`try`.catch4 + +import kotlin.test.* + +@Test fun runTest() { + try { + println("Before") + throw Error("Error happens") + println("After") + } catch (e: Exception) { + println("Caught Exception") + } catch (e: Error) { + println("Caught Error") + } catch (e: Throwable) { + println("Caught Throwable") + } + + println("Done") +} \ No newline at end of file diff --git a/kotlin-native/backend.native/tests/codegen/try/catch5.kt b/kotlin-native/backend.native/tests/codegen/try/catch5.kt new file mode 100644 index 00000000000..87ab8fd14fa --- /dev/null +++ b/kotlin-native/backend.native/tests/codegen/try/catch5.kt @@ -0,0 +1,34 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +package codegen.`try`.catch5 + +import kotlin.test.* + +@Test fun runTest() { + try { + try { + println("Before") + foo() + println("After") + } catch (e: Exception) { + println("Caught Exception") + } + + println("After nested try") + + } catch (e: Error) { + println("Caught Error") + } catch (e: Throwable) { + println("Caught Throwable") + } + + println("Done") +} + +fun foo() { + throw Error("Error happens") + println("After in foo()") +} \ No newline at end of file diff --git a/kotlin-native/backend.native/tests/codegen/try/catch6.kt b/kotlin-native/backend.native/tests/codegen/try/catch6.kt new file mode 100644 index 00000000000..1e63115d598 --- /dev/null +++ b/kotlin-native/backend.native/tests/codegen/try/catch6.kt @@ -0,0 +1,30 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +package codegen.`try`.catch6 + +import kotlin.test.* + +@Test fun runTest() { + try { + println("Before") + foo() + println("After") + } catch (e: Exception) { + println("Caught Exception") + } catch (e: Error) { + println("Caught Error") + } + + println("Done") +} + +fun foo() { + try { + throw Error("Error happens") + } catch (e: Exception) { + println("Caught Exception") + } +} \ No newline at end of file diff --git a/kotlin-native/backend.native/tests/codegen/try/catch8.kt b/kotlin-native/backend.native/tests/codegen/try/catch8.kt new file mode 100644 index 00000000000..48649916a3a --- /dev/null +++ b/kotlin-native/backend.native/tests/codegen/try/catch8.kt @@ -0,0 +1,19 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +package codegen.`try`.catch8 + +import kotlin.test.* + +@Test fun runTest() { + try { + throw Error("Error happens") + } catch (e: Throwable) { + val message = e.message + if (message != null) { + println(message) + } + } +} \ No newline at end of file diff --git a/kotlin-native/backend.native/tests/codegen/try/finally1.kt b/kotlin-native/backend.native/tests/codegen/try/finally1.kt new file mode 100644 index 00000000000..b513bc84294 --- /dev/null +++ b/kotlin-native/backend.native/tests/codegen/try/finally1.kt @@ -0,0 +1,19 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +package codegen.`try`.finally1 + +import kotlin.test.* + +@Test fun runTest() { + + try { + println("Try") + } finally { + println("Finally") + } + + println("Done") +} \ No newline at end of file diff --git a/kotlin-native/backend.native/tests/codegen/try/finally10.kt b/kotlin-native/backend.native/tests/codegen/try/finally10.kt new file mode 100644 index 00000000000..4347a182901 --- /dev/null +++ b/kotlin-native/backend.native/tests/codegen/try/finally10.kt @@ -0,0 +1,21 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +package codegen.`try`.finally10 + +import kotlin.test.* + +@Test fun runTest() { + while (true) { + try { + continue + } finally { + println("Finally") + break + } + } + + println("After") +} \ No newline at end of file diff --git a/kotlin-native/backend.native/tests/codegen/try/finally11.kt b/kotlin-native/backend.native/tests/codegen/try/finally11.kt new file mode 100644 index 00000000000..3ffdaf91786 --- /dev/null +++ b/kotlin-native/backend.native/tests/codegen/try/finally11.kt @@ -0,0 +1,25 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +package codegen.`try`.finally11 + +import kotlin.test.* + +@Test fun runTest() { + try { + try { + return + } catch (e: Error) { + println("Catch 1") + } finally { + println("Finally") + throw Error() + } + } catch (e: Error) { + println("Catch 2") + } + + println("Done") +} \ No newline at end of file diff --git a/kotlin-native/backend.native/tests/codegen/try/finally2.kt b/kotlin-native/backend.native/tests/codegen/try/finally2.kt new file mode 100644 index 00000000000..3aae9ba9c25 --- /dev/null +++ b/kotlin-native/backend.native/tests/codegen/try/finally2.kt @@ -0,0 +1,23 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +package codegen.`try`.finally2 + +import kotlin.test.* + +@Test fun runTest() { + + try { + println("Try") + throw Error("Error happens") + println("After throw") + } catch (e: Error) { + println("Caught Error") + } finally { + println("Finally") + } + + println("Done") +} \ No newline at end of file diff --git a/kotlin-native/backend.native/tests/codegen/try/finally3.kt b/kotlin-native/backend.native/tests/codegen/try/finally3.kt new file mode 100644 index 00000000000..13faf1d7a0b --- /dev/null +++ b/kotlin-native/backend.native/tests/codegen/try/finally3.kt @@ -0,0 +1,28 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +package codegen.`try`.finally3 + +import kotlin.test.* + +@Test fun runTest() { + + try { + try { + println("Try") + throw Error("Error happens") + println("After throw") + } finally { + println("Finally") + } + + println("After nested try") + + } catch (e: Error) { + println("Caught Error") + } + + println("Done") +} \ No newline at end of file diff --git a/kotlin-native/backend.native/tests/codegen/try/finally4.kt b/kotlin-native/backend.native/tests/codegen/try/finally4.kt new file mode 100644 index 00000000000..484ce7e76be --- /dev/null +++ b/kotlin-native/backend.native/tests/codegen/try/finally4.kt @@ -0,0 +1,34 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +package codegen.`try`.finally4 + +import kotlin.test.* + +@Test fun runTest() { + + try { + try { + println("Try") + throw Error("Error happens") + println("After throw") + } catch (e: Error) { + println("Catch") + throw Exception() + println("After throw") + } finally { + println("Finally") + } + + println("After nested try") + + } catch (e: Error) { + println("Caught Error") + } catch (e: Exception) { + println("Caught Exception") + } + + println("Done") +} \ No newline at end of file diff --git a/kotlin-native/backend.native/tests/codegen/try/finally5.kt b/kotlin-native/backend.native/tests/codegen/try/finally5.kt new file mode 100644 index 00000000000..8198d7ac0db --- /dev/null +++ b/kotlin-native/backend.native/tests/codegen/try/finally5.kt @@ -0,0 +1,24 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +package codegen.`try`.finally5 + +import kotlin.test.* + +@Test fun runTest() { + println(foo()) +} + +fun foo(): Int { + try { + println("Done") + return 0 + } finally { + println("Finally") + } + + println("After") + return 1 +} \ No newline at end of file diff --git a/kotlin-native/backend.native/tests/codegen/try/finally6.kt b/kotlin-native/backend.native/tests/codegen/try/finally6.kt new file mode 100644 index 00000000000..f746fd1ddff --- /dev/null +++ b/kotlin-native/backend.native/tests/codegen/try/finally6.kt @@ -0,0 +1,25 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +package codegen.`try`.finally6 + +import kotlin.test.* + +@Test fun runTest() { + println(foo()) +} + +fun foo(): Int { + try { + println("Done") + return 0 + } finally { + println("Finally") + return 1 + } + + println("After") + return 2 +} \ No newline at end of file diff --git a/kotlin-native/backend.native/tests/codegen/try/finally7.kt b/kotlin-native/backend.native/tests/codegen/try/finally7.kt new file mode 100644 index 00000000000..190e7245a39 --- /dev/null +++ b/kotlin-native/backend.native/tests/codegen/try/finally7.kt @@ -0,0 +1,25 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +package codegen.`try`.finally7 + +import kotlin.test.* + +@Test fun runTest() { + println(foo()) +} + +fun foo(): Int { + try { + println("Done") + throw Error() + } finally { + println("Finally") + return 1 + } + + println("After") + return 2 +} \ No newline at end of file diff --git a/kotlin-native/backend.native/tests/codegen/try/finally8.kt b/kotlin-native/backend.native/tests/codegen/try/finally8.kt new file mode 100644 index 00000000000..c6c8c201880 --- /dev/null +++ b/kotlin-native/backend.native/tests/codegen/try/finally8.kt @@ -0,0 +1,27 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +package codegen.`try`.finally8 + +import kotlin.test.* + +@Test fun runTest() { + println(foo()) +} + +fun foo(): Int { + try { + try { + return 42 + } finally { + println("Finally 1") + } + } finally { + println("Finally 2") + } + + println("After") + return 2 +} \ No newline at end of file diff --git a/kotlin-native/backend.native/tests/codegen/try/finally9.kt b/kotlin-native/backend.native/tests/codegen/try/finally9.kt new file mode 100644 index 00000000000..b3d35de9b72 --- /dev/null +++ b/kotlin-native/backend.native/tests/codegen/try/finally9.kt @@ -0,0 +1,30 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +package codegen.`try`.finally9 + +import kotlin.test.* + +@Test fun runTest() { + do { + try { + break + } finally { + println("Finally 1") + } + } while (false) + + var stop = false + while (!stop) { + try { + stop = true + continue + } finally { + println("Finally 2") + } + } + + println("After") +} \ No newline at end of file diff --git a/kotlin-native/backend.native/tests/codegen/try/returnsDifferentTypes.kt b/kotlin-native/backend.native/tests/codegen/try/returnsDifferentTypes.kt new file mode 100644 index 00000000000..11ec87b7541 --- /dev/null +++ b/kotlin-native/backend.native/tests/codegen/try/returnsDifferentTypes.kt @@ -0,0 +1,33 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +package codegen.`try`.returnsDifferentTypes + +import kotlin.test.* + +class ReceiveChannel + +inline fun ReceiveChannel.consume(block: ReceiveChannel.() -> R): R { + try { + return block() + } + finally { + println("zzz") + } +} + +inline fun ReceiveChannel.elementAtOrElse(index: Int, defaultValue: (Int) -> E): E = + consume { + if (index < 0) + return defaultValue(index) + return 42 as E + } + +fun ReceiveChannel.elementAt(index: Int): E = + elementAtOrElse(index) { throw IndexOutOfBoundsException("qxx") } + +@Test fun runTest() { + println(ReceiveChannel().elementAt(0)) +} \ No newline at end of file diff --git a/kotlin-native/backend.native/tests/codegen/try/try1.kt b/kotlin-native/backend.native/tests/codegen/try/try1.kt new file mode 100644 index 00000000000..632d452f755 --- /dev/null +++ b/kotlin-native/backend.native/tests/codegen/try/try1.kt @@ -0,0 +1,18 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +package codegen.`try`.try1 + +import kotlin.test.* + +@Test fun runTest() { + val x = try { + 5 + } catch (e: Throwable) { + 6 + } + + println(x) +} \ No newline at end of file diff --git a/kotlin-native/backend.native/tests/codegen/try/try2.kt b/kotlin-native/backend.native/tests/codegen/try/try2.kt new file mode 100644 index 00000000000..b0c3c00d8b7 --- /dev/null +++ b/kotlin-native/backend.native/tests/codegen/try/try2.kt @@ -0,0 +1,19 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +package codegen.`try`.try2 + +import kotlin.test.* + +@Test fun runTest() { + val x = try { + throw Error() + 5 + } catch (e: Throwable) { + 6 + } + + println(x) +} \ No newline at end of file diff --git a/kotlin-native/backend.native/tests/codegen/try/try3.kt b/kotlin-native/backend.native/tests/codegen/try/try3.kt new file mode 100644 index 00000000000..890fbb01d56 --- /dev/null +++ b/kotlin-native/backend.native/tests/codegen/try/try3.kt @@ -0,0 +1,18 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +package codegen.`try`.try3 + +import kotlin.test.* + +@Test fun runTest() { + val x = try { + throw Error() + } catch (e: Throwable) { + 6 + } + + println(x) +} \ No newline at end of file diff --git a/kotlin-native/backend.native/tests/codegen/try/try4.kt b/kotlin-native/backend.native/tests/codegen/try/try4.kt new file mode 100644 index 00000000000..2c8357171f4 --- /dev/null +++ b/kotlin-native/backend.native/tests/codegen/try/try4.kt @@ -0,0 +1,19 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +package codegen.`try`.try4 + +import kotlin.test.* + +@Test fun runTest() { + val x = try { + println("Try") + 5 + } catch (e: Throwable) { + throw e + } + + println(x) +} \ No newline at end of file diff --git a/kotlin-native/backend.native/tests/compilerChecks/README.md b/kotlin-native/backend.native/tests/compilerChecks/README.md new file mode 100644 index 00000000000..d75d95ab9ee --- /dev/null +++ b/kotlin-native/backend.native/tests/compilerChecks/README.md @@ -0,0 +1 @@ +These tests aren't invoked so far because there is no mechanism of checking compilation errors yet. \ No newline at end of file diff --git a/kotlin-native/backend.native/tests/compilerChecks/t1.kt b/kotlin-native/backend.native/tests/compilerChecks/t1.kt new file mode 100644 index 00000000000..e81a3254c87 --- /dev/null +++ b/kotlin-native/backend.native/tests/compilerChecks/t1.kt @@ -0,0 +1,11 @@ +import kotlinx.cinterop.* + +fun foo(x: Int, vararg s: String): Int { + var sum = x + s.forEach { sum += it.length } + return sum +} + +fun bar() { + staticCFunction(::foo) +} diff --git a/kotlin-native/backend.native/tests/compilerChecks/t10.kt b/kotlin-native/backend.native/tests/compilerChecks/t10.kt new file mode 100644 index 00000000000..fbbbba0954a --- /dev/null +++ b/kotlin-native/backend.native/tests/compilerChecks/t10.kt @@ -0,0 +1,7 @@ +import kotlinx.cinterop.* + +fun foo(f: Function1<*, Int>) = f + +fun bar() { + staticCFunction(::foo) +} diff --git a/kotlin-native/backend.native/tests/compilerChecks/t11.kt b/kotlin-native/backend.native/tests/compilerChecks/t11.kt new file mode 100644 index 00000000000..707553a0c4b --- /dev/null +++ b/kotlin-native/backend.native/tests/compilerChecks/t11.kt @@ -0,0 +1,7 @@ +import kotlinx.cinterop.* + +fun foo(f: Function1) = f + +fun bar() { + staticCFunction(::foo) +} diff --git a/kotlin-native/backend.native/tests/compilerChecks/t12.kt b/kotlin-native/backend.native/tests/compilerChecks/t12.kt new file mode 100644 index 00000000000..b904dae2d67 --- /dev/null +++ b/kotlin-native/backend.native/tests/compilerChecks/t12.kt @@ -0,0 +1,7 @@ +import kotlinx.cinterop.* + +fun foo(x: CValue<*>?) = x + +fun bar() { + staticCFunction(::foo) +} diff --git a/kotlin-native/backend.native/tests/compilerChecks/t13.kt b/kotlin-native/backend.native/tests/compilerChecks/t13.kt new file mode 100644 index 00000000000..0874088c4c9 --- /dev/null +++ b/kotlin-native/backend.native/tests/compilerChecks/t13.kt @@ -0,0 +1,8 @@ +import kotlinx.cinterop.* + +fun bar() { + + fun foo(x: CValue) = x + + staticCFunction(::foo) +} diff --git a/kotlin-native/backend.native/tests/compilerChecks/t14.kt b/kotlin-native/backend.native/tests/compilerChecks/t14.kt new file mode 100644 index 00000000000..05f27179537 --- /dev/null +++ b/kotlin-native/backend.native/tests/compilerChecks/t14.kt @@ -0,0 +1,9 @@ +import kotlinx.cinterop.* + +class Z(rawPtr: NativePtr): CStructVar(rawPtr) + +fun foo(x: CValue) = x + +fun bar() { + staticCFunction(::foo) +} diff --git a/kotlin-native/backend.native/tests/compilerChecks/t15.kt b/kotlin-native/backend.native/tests/compilerChecks/t15.kt new file mode 100644 index 00000000000..8f9b60dd74b --- /dev/null +++ b/kotlin-native/backend.native/tests/compilerChecks/t15.kt @@ -0,0 +1,4 @@ +import platform.darwin.* +import platform.Foundation.* + +fun foo() = NSLog("zzz", {}) diff --git a/kotlin-native/backend.native/tests/compilerChecks/t16.kt b/kotlin-native/backend.native/tests/compilerChecks/t16.kt new file mode 100644 index 00000000000..69e31415fe1 --- /dev/null +++ b/kotlin-native/backend.native/tests/compilerChecks/t16.kt @@ -0,0 +1,6 @@ +import platform.darwin.* +import platform.Foundation.* + +class Z + +fun foo() = NSLog("zzz", Z()) diff --git a/kotlin-native/backend.native/tests/compilerChecks/t17.kt b/kotlin-native/backend.native/tests/compilerChecks/t17.kt new file mode 100644 index 00000000000..fce3da8a57c --- /dev/null +++ b/kotlin-native/backend.native/tests/compilerChecks/t17.kt @@ -0,0 +1,8 @@ +import platform.darwin.* +import platform.Foundation.* + +class Foo : NSObject(), NSPortDelegateProtocol { + fun foo() { + super.handlePortMessage(TODO()) + } +} diff --git a/kotlin-native/backend.native/tests/compilerChecks/t18.kt b/kotlin-native/backend.native/tests/compilerChecks/t18.kt new file mode 100644 index 00000000000..6ca701a7d4b --- /dev/null +++ b/kotlin-native/backend.native/tests/compilerChecks/t18.kt @@ -0,0 +1,9 @@ +import platform.darwin.* + +class Foo : NSObject() { + companion object : NSObjectMeta() { + fun bar() { + super.hash() + } + } +} diff --git a/kotlin-native/backend.native/tests/compilerChecks/t2.kt b/kotlin-native/backend.native/tests/compilerChecks/t2.kt new file mode 100644 index 00000000000..03be45bb590 --- /dev/null +++ b/kotlin-native/backend.native/tests/compilerChecks/t2.kt @@ -0,0 +1,6 @@ +import platform.darwin.* +import platform.Foundation.* + +class Zzz : NSAssertionHandler() { + override fun handleFailureInFunction(functionName: String, file: String, lineNumber: NSInteger /* = Long */, description: String?, vararg args: Any?) { } +} diff --git a/kotlin-native/backend.native/tests/compilerChecks/t20.kt b/kotlin-native/backend.native/tests/compilerChecks/t20.kt new file mode 100644 index 00000000000..50e2de5cc32 --- /dev/null +++ b/kotlin-native/backend.native/tests/compilerChecks/t20.kt @@ -0,0 +1,4 @@ +import platform.darwin.* +import platform.Foundation.* + +interface Zzz : NSCopyingProtocolMeta diff --git a/kotlin-native/backend.native/tests/compilerChecks/t21.kt b/kotlin-native/backend.native/tests/compilerChecks/t21.kt new file mode 100644 index 00000000000..6a0f459b8d5 --- /dev/null +++ b/kotlin-native/backend.native/tests/compilerChecks/t21.kt @@ -0,0 +1,4 @@ +import platform.darwin.* +import platform.Foundation.* + +open class Zzz : NSAssertionHandler() diff --git a/kotlin-native/backend.native/tests/compilerChecks/t22.kt b/kotlin-native/backend.native/tests/compilerChecks/t22.kt new file mode 100644 index 00000000000..a095f936c1a --- /dev/null +++ b/kotlin-native/backend.native/tests/compilerChecks/t22.kt @@ -0,0 +1,8 @@ +import platform.darwin.* +import platform.Foundation.* + +class Zzz : NSAssertionHandler() { + companion object { + val Z = 42 + } +} diff --git a/kotlin-native/backend.native/tests/compilerChecks/t23.kt b/kotlin-native/backend.native/tests/compilerChecks/t23.kt new file mode 100644 index 00000000000..e4d06a2efe8 --- /dev/null +++ b/kotlin-native/backend.native/tests/compilerChecks/t23.kt @@ -0,0 +1,6 @@ +import platform.darwin.* +import platform.Foundation.* + +interface I + +class Zzz : NSAssertionHandler(), I diff --git a/kotlin-native/backend.native/tests/compilerChecks/t24.kt b/kotlin-native/backend.native/tests/compilerChecks/t24.kt new file mode 100644 index 00000000000..1e996546be2 --- /dev/null +++ b/kotlin-native/backend.native/tests/compilerChecks/t24.kt @@ -0,0 +1,4 @@ +import platform.darwin.* +import platform.Foundation.* + +class Zzz : NSCopyingProtocolMeta diff --git a/kotlin-native/backend.native/tests/compilerChecks/t25.kt b/kotlin-native/backend.native/tests/compilerChecks/t25.kt new file mode 100644 index 00000000000..b57b8fabeb4 --- /dev/null +++ b/kotlin-native/backend.native/tests/compilerChecks/t25.kt @@ -0,0 +1,6 @@ +import platform.darwin.* +import platform.Foundation.* + +class Zzz : NSAssertionHandler() { + override fun toString() = "zzz" +} diff --git a/kotlin-native/backend.native/tests/compilerChecks/t26.kt b/kotlin-native/backend.native/tests/compilerChecks/t26.kt new file mode 100644 index 00000000000..dd79c6bff10 --- /dev/null +++ b/kotlin-native/backend.native/tests/compilerChecks/t26.kt @@ -0,0 +1,8 @@ +import kotlinx.cinterop.* +import platform.darwin.* +import platform.Foundation.* + +class Zzz : NSAssertionHandler() { + @ObjCAction + fun String.foo() = println(this) +} diff --git a/kotlin-native/backend.native/tests/compilerChecks/t27.kt b/kotlin-native/backend.native/tests/compilerChecks/t27.kt new file mode 100644 index 00000000000..ca088a337b2 --- /dev/null +++ b/kotlin-native/backend.native/tests/compilerChecks/t27.kt @@ -0,0 +1,8 @@ +import kotlinx.cinterop.* +import platform.darwin.* +import platform.Foundation.* + +class Zzz : NSAssertionHandler() { + @ObjCAction + fun foo(x: String) = println(x) +} diff --git a/kotlin-native/backend.native/tests/compilerChecks/t28.kt b/kotlin-native/backend.native/tests/compilerChecks/t28.kt new file mode 100644 index 00000000000..70de49cc2c6 --- /dev/null +++ b/kotlin-native/backend.native/tests/compilerChecks/t28.kt @@ -0,0 +1,8 @@ +import kotlinx.cinterop.* +import platform.darwin.* +import platform.Foundation.* + +class Zzz : NSAssertionHandler() { + @ObjCAction + fun foo() = 42 +} diff --git a/kotlin-native/backend.native/tests/compilerChecks/t29.kt b/kotlin-native/backend.native/tests/compilerChecks/t29.kt new file mode 100644 index 00000000000..99600ea848d --- /dev/null +++ b/kotlin-native/backend.native/tests/compilerChecks/t29.kt @@ -0,0 +1,8 @@ +import kotlinx.cinterop.* +import platform.darwin.* +import platform.Foundation.* + +class Zzz : NSAssertionHandler() { + @ObjCOutlet + val x: NSObject get() = this +} diff --git a/kotlin-native/backend.native/tests/compilerChecks/t3.kt b/kotlin-native/backend.native/tests/compilerChecks/t3.kt new file mode 100644 index 00000000000..990b6549265 --- /dev/null +++ b/kotlin-native/backend.native/tests/compilerChecks/t3.kt @@ -0,0 +1,5 @@ +import platform.posix.* + +fun main() { + println(::printf) +} diff --git a/kotlin-native/backend.native/tests/compilerChecks/t30.kt b/kotlin-native/backend.native/tests/compilerChecks/t30.kt new file mode 100644 index 00000000000..c7726d491ed --- /dev/null +++ b/kotlin-native/backend.native/tests/compilerChecks/t30.kt @@ -0,0 +1,10 @@ +import kotlinx.cinterop.* +import platform.darwin.* +import platform.Foundation.* + +class Zzz : NSAssertionHandler() { + @ObjCOutlet + var NSObject.x: NSObject + get() = this + set(value: NSObject) { } +} diff --git a/kotlin-native/backend.native/tests/compilerChecks/t31.kt b/kotlin-native/backend.native/tests/compilerChecks/t31.kt new file mode 100644 index 00000000000..df6b62782a9 --- /dev/null +++ b/kotlin-native/backend.native/tests/compilerChecks/t31.kt @@ -0,0 +1,10 @@ +import kotlinx.cinterop.* +import platform.darwin.* +import platform.Foundation.* + +class Zzz : NSAssertionHandler() { + @ObjCOutlet + var x: String + get() = "zzz" + set(value: String) { } +} diff --git a/kotlin-native/backend.native/tests/compilerChecks/t32.kt b/kotlin-native/backend.native/tests/compilerChecks/t32.kt new file mode 100644 index 00000000000..60be6649f8d --- /dev/null +++ b/kotlin-native/backend.native/tests/compilerChecks/t32.kt @@ -0,0 +1,8 @@ +import kotlinx.cinterop.* +import platform.darwin.* +import platform.Foundation.* + +class Zzz : NSAssertionHandler { + @OverrideInit + constructor(x: Int) { } +} diff --git a/kotlin-native/backend.native/tests/compilerChecks/t33.kt b/kotlin-native/backend.native/tests/compilerChecks/t33.kt new file mode 100644 index 00000000000..a628b0bd1a9 --- /dev/null +++ b/kotlin-native/backend.native/tests/compilerChecks/t33.kt @@ -0,0 +1,10 @@ +import kotlinx.cinterop.* +import platform.darwin.* +import platform.Foundation.* + +class Zzz : NSString { + @OverrideInit + constructor(coder: NSCoder) { } + + override fun initWithCoder(coder: NSCoder): String? = "zzz" +} diff --git a/kotlin-native/backend.native/tests/compilerChecks/t34.kt b/kotlin-native/backend.native/tests/compilerChecks/t34.kt new file mode 100644 index 00000000000..bca42e1ec95 --- /dev/null +++ b/kotlin-native/backend.native/tests/compilerChecks/t34.kt @@ -0,0 +1,8 @@ +import kotlinx.cinterop.* +import platform.darwin.* +import platform.Foundation.* + +class Zzz : NSAssertionHandler() { + @ObjCAction + fun foo(x: NSObject, y: NSObject, z: NSObject) { } +} diff --git a/kotlin-native/backend.native/tests/compilerChecks/t35.kt b/kotlin-native/backend.native/tests/compilerChecks/t35.kt new file mode 100644 index 00000000000..8af8740565a --- /dev/null +++ b/kotlin-native/backend.native/tests/compilerChecks/t35.kt @@ -0,0 +1,5 @@ +import kotlinx.cinterop.* +import platform.darwin.* +import platform.Foundation.* + +class Zzz : NSValue() diff --git a/kotlin-native/backend.native/tests/compilerChecks/t36.kt b/kotlin-native/backend.native/tests/compilerChecks/t36.kt new file mode 100644 index 00000000000..2b71817f750 --- /dev/null +++ b/kotlin-native/backend.native/tests/compilerChecks/t36.kt @@ -0,0 +1,4 @@ +import kotlinx.cinterop.* +import platform.posix.* + +fun foo() = stat(malloc(42)!!.rawValue) diff --git a/kotlin-native/backend.native/tests/compilerChecks/t37.kt b/kotlin-native/backend.native/tests/compilerChecks/t37.kt new file mode 100644 index 00000000000..be41239bc02 --- /dev/null +++ b/kotlin-native/backend.native/tests/compilerChecks/t37.kt @@ -0,0 +1,11 @@ +import kotlinx.cinterop.* +import kotlinx.cinterop.internal.* + +@CStruct(spelling = "struct { }") class Z constructor(rawPtr: NativePtr) : CStructVar(rawPtr) { + val x: Pair? = null + @CStruct.MemberAt(offset = 0L) get +} + +fun foo(z: Z) = z.x + +fun main() { } diff --git a/kotlin-native/backend.native/tests/compilerChecks/t38.kt b/kotlin-native/backend.native/tests/compilerChecks/t38.kt new file mode 100644 index 00000000000..893994fde2d --- /dev/null +++ b/kotlin-native/backend.native/tests/compilerChecks/t38.kt @@ -0,0 +1,14 @@ +import kotlinx.cinterop.* +import kotlinx.cinterop.internal.* + +@CStruct(spelling = "struct { }") class Z constructor(rawPtr: NativePtr) : CStructVar(rawPtr) { + var x: Pair? = null + @CStruct.MemberAt(offset = 0L) get + @CStruct.MemberAt(offset = 0L) set +} + +fun foo(z: Z) { + z.x = 42 to 117 +} + +fun main() { } diff --git a/kotlin-native/backend.native/tests/compilerChecks/t4.kt b/kotlin-native/backend.native/tests/compilerChecks/t4.kt new file mode 100644 index 00000000000..221d7844690 --- /dev/null +++ b/kotlin-native/backend.native/tests/compilerChecks/t4.kt @@ -0,0 +1,4 @@ +import platform.darwin.* +import platform.Foundation.* + +fun foo() = println(NSAssertionHandler()::handleFailureInFunction) diff --git a/kotlin-native/backend.native/tests/compilerChecks/t40.kt b/kotlin-native/backend.native/tests/compilerChecks/t40.kt new file mode 100644 index 00000000000..4dfde08192e --- /dev/null +++ b/kotlin-native/backend.native/tests/compilerChecks/t40.kt @@ -0,0 +1,9 @@ +import kotlinx.cinterop.* + +class Z { + fun foo(x: Int) = x +} + +fun bar() { + staticCFunction(Z()::foo) +} diff --git a/kotlin-native/backend.native/tests/compilerChecks/t41.kt b/kotlin-native/backend.native/tests/compilerChecks/t41.kt new file mode 100644 index 00000000000..e50949ca4d3 --- /dev/null +++ b/kotlin-native/backend.native/tests/compilerChecks/t41.kt @@ -0,0 +1,8 @@ +import kotlinx.cinterop.* + +fun bar(x: Int) { + + fun foo() = x + + staticCFunction(::foo) +} diff --git a/kotlin-native/backend.native/tests/compilerChecks/t42.kt b/kotlin-native/backend.native/tests/compilerChecks/t42.kt new file mode 100644 index 00000000000..8f409411fb9 --- /dev/null +++ b/kotlin-native/backend.native/tests/compilerChecks/t42.kt @@ -0,0 +1,7 @@ +import kotlinx.cinterop.* + +fun foo(x: Any) = x + +fun bar() { + staticCFunction(::foo) +} diff --git a/kotlin-native/backend.native/tests/compilerChecks/t43.kt b/kotlin-native/backend.native/tests/compilerChecks/t43.kt new file mode 100644 index 00000000000..b30ae793fd1 --- /dev/null +++ b/kotlin-native/backend.native/tests/compilerChecks/t43.kt @@ -0,0 +1,3 @@ +import kotlinx.cinterop.* + +fun bar(x: Float) = x.signExtend() diff --git a/kotlin-native/backend.native/tests/compilerChecks/t44.kt b/kotlin-native/backend.native/tests/compilerChecks/t44.kt new file mode 100644 index 00000000000..069546b5c34 --- /dev/null +++ b/kotlin-native/backend.native/tests/compilerChecks/t44.kt @@ -0,0 +1,3 @@ +import kotlinx.cinterop.* + +fun bar(x: Int) = x.signExtend() diff --git a/kotlin-native/backend.native/tests/compilerChecks/t45.kt b/kotlin-native/backend.native/tests/compilerChecks/t45.kt new file mode 100644 index 00000000000..19c83ebf6d5 --- /dev/null +++ b/kotlin-native/backend.native/tests/compilerChecks/t45.kt @@ -0,0 +1,3 @@ +import kotlinx.cinterop.* + +fun bar(x: Int) = x.signExtend() diff --git a/kotlin-native/backend.native/tests/compilerChecks/t46.kt b/kotlin-native/backend.native/tests/compilerChecks/t46.kt new file mode 100644 index 00000000000..3b4e7ab349a --- /dev/null +++ b/kotlin-native/backend.native/tests/compilerChecks/t46.kt @@ -0,0 +1,3 @@ +import kotlinx.cinterop.* + +fun bar(x: Int) = x.narrow() diff --git a/kotlin-native/backend.native/tests/compilerChecks/t47.kt b/kotlin-native/backend.native/tests/compilerChecks/t47.kt new file mode 100644 index 00000000000..63ce4ea0c23 --- /dev/null +++ b/kotlin-native/backend.native/tests/compilerChecks/t47.kt @@ -0,0 +1,3 @@ +import kotlinx.cinterop.* + +fun bar(x: Int) = x.convert() diff --git a/kotlin-native/backend.native/tests/compilerChecks/t48.kt b/kotlin-native/backend.native/tests/compilerChecks/t48.kt new file mode 100644 index 00000000000..5ae065ceebf --- /dev/null +++ b/kotlin-native/backend.native/tests/compilerChecks/t48.kt @@ -0,0 +1,10 @@ +import kotlin.native.concurrent.* + +class Z(val x: Int) { + fun bar(s: String) = s + x.toString() +} + +fun foo(x: Int) { + val worker = Worker.start() + worker.execute(TransferMode.SAFE, { "zzz" }, Z(x)::bar) +} diff --git a/kotlin-native/backend.native/tests/compilerChecks/t49.kt b/kotlin-native/backend.native/tests/compilerChecks/t49.kt new file mode 100644 index 00000000000..2188c38b023 --- /dev/null +++ b/kotlin-native/backend.native/tests/compilerChecks/t49.kt @@ -0,0 +1,6 @@ +import kotlin.native.concurrent.* + +fun foo(x: Int) { + val worker = Worker.start() + worker.execute(TransferMode.SAFE, { "zzz" }) { s -> s + x.toString() } +} diff --git a/kotlin-native/backend.native/tests/compilerChecks/t5.kt b/kotlin-native/backend.native/tests/compilerChecks/t5.kt new file mode 100644 index 00000000000..0b6fa0bbc49 --- /dev/null +++ b/kotlin-native/backend.native/tests/compilerChecks/t5.kt @@ -0,0 +1,4 @@ +import platform.darwin.* +import platform.Foundation.* + +fun foo() = NSAssertionHandler().handleFailureInFunction("zzz", "zzz", 0L, null, "qzz") diff --git a/kotlin-native/backend.native/tests/compilerChecks/t50.kt b/kotlin-native/backend.native/tests/compilerChecks/t50.kt new file mode 100644 index 00000000000..41d5868c00a --- /dev/null +++ b/kotlin-native/backend.native/tests/compilerChecks/t50.kt @@ -0,0 +1,13 @@ +import kotlin.native.concurrent.* + +class Z(val x: Int) { + fun bar(s: String) = s + x.toString() +} + +class Q(x: Int) { + init { + val worker = Worker.start() + worker.execute(TransferMode.SAFE, { "zzz" }, Z(x)::bar) + } +} + diff --git a/kotlin-native/backend.native/tests/compilerChecks/t51.kt b/kotlin-native/backend.native/tests/compilerChecks/t51.kt new file mode 100644 index 00000000000..5d3baa4a347 --- /dev/null +++ b/kotlin-native/backend.native/tests/compilerChecks/t51.kt @@ -0,0 +1,10 @@ +import kotlin.native.concurrent.* + +class Z(val x: Int) { + fun bar(s: String) = s + x.toString() +} + +class Q(x: Int) { + val z = Worker.start().execute(TransferMode.SAFE, { "zzz" }, Z(x)::bar) +} + diff --git a/kotlin-native/backend.native/tests/compilerChecks/t52.kt b/kotlin-native/backend.native/tests/compilerChecks/t52.kt new file mode 100644 index 00000000000..1372cc106c5 --- /dev/null +++ b/kotlin-native/backend.native/tests/compilerChecks/t52.kt @@ -0,0 +1,6 @@ +import kotlin.native.internal.* + +@OptIn(kotlin.ExperimentalStdlibApi::class) +fun foo(x: Int) { + createCleaner(42) { println(x) } +} diff --git a/kotlin-native/backend.native/tests/compilerChecks/t53.kt b/kotlin-native/backend.native/tests/compilerChecks/t53.kt new file mode 100644 index 00000000000..117948147b3 --- /dev/null +++ b/kotlin-native/backend.native/tests/compilerChecks/t53.kt @@ -0,0 +1,10 @@ +import kotlin.native.internal.* + +class C(val x: Int) { + fun bar(y: Int) = println(x + y) +} + +@OptIn(kotlin.ExperimentalStdlibApi::class) +fun foo(x: Int) { + createCleaner(42, C(x)::bar) +} diff --git a/kotlin-native/backend.native/tests/compilerChecks/t54.kt b/kotlin-native/backend.native/tests/compilerChecks/t54.kt new file mode 100644 index 00000000000..fe3d45cd7b3 --- /dev/null +++ b/kotlin-native/backend.native/tests/compilerChecks/t54.kt @@ -0,0 +1 @@ +fun foo(arr: ShortArray) = immutableBlobOf(*arr) diff --git a/kotlin-native/backend.native/tests/compilerChecks/t55.kt b/kotlin-native/backend.native/tests/compilerChecks/t55.kt new file mode 100644 index 00000000000..561fa724bf8 --- /dev/null +++ b/kotlin-native/backend.native/tests/compilerChecks/t55.kt @@ -0,0 +1 @@ +fun foo(x: Short) = immutableBlobOf(x) diff --git a/kotlin-native/backend.native/tests/compilerChecks/t56.kt b/kotlin-native/backend.native/tests/compilerChecks/t56.kt new file mode 100644 index 00000000000..d286a28d7be --- /dev/null +++ b/kotlin-native/backend.native/tests/compilerChecks/t56.kt @@ -0,0 +1 @@ +fun foo() = immutableBlobOf(1000) diff --git a/kotlin-native/backend.native/tests/compilerChecks/t57.kt b/kotlin-native/backend.native/tests/compilerChecks/t57.kt new file mode 100644 index 00000000000..d947c4e05c9 --- /dev/null +++ b/kotlin-native/backend.native/tests/compilerChecks/t57.kt @@ -0,0 +1 @@ +fun foo() = immutableBlobOf() diff --git a/kotlin-native/backend.native/tests/compilerChecks/t58.kt b/kotlin-native/backend.native/tests/compilerChecks/t58.kt new file mode 100644 index 00000000000..e1a9ec73ef0 --- /dev/null +++ b/kotlin-native/backend.native/tests/compilerChecks/t58.kt @@ -0,0 +1,7 @@ +import kotlin.reflect.* + +@OptIn(kotlin.ExperimentalStdlibApi::class) +fun > foo() { + typeOf>() +} + diff --git a/kotlin-native/backend.native/tests/compilerChecks/t59.kt b/kotlin-native/backend.native/tests/compilerChecks/t59.kt new file mode 100644 index 00000000000..66d180a17d0 --- /dev/null +++ b/kotlin-native/backend.native/tests/compilerChecks/t59.kt @@ -0,0 +1,7 @@ +import kotlin.reflect.* + +@OptIn(kotlin.ExperimentalStdlibApi::class) +inline fun > foo() { + typeOf>() +} + diff --git a/kotlin-native/backend.native/tests/compilerChecks/t6.kt b/kotlin-native/backend.native/tests/compilerChecks/t6.kt new file mode 100644 index 00000000000..ea60cfb3c3e --- /dev/null +++ b/kotlin-native/backend.native/tests/compilerChecks/t6.kt @@ -0,0 +1,4 @@ +import platform.darwin.* +import platform.Foundation.* + +fun foo(s: Array) = NSAssertionHandler().handleFailureInFunction("zzz", "zzz", 0L, null, *s) diff --git a/kotlin-native/backend.native/tests/compilerChecks/t7.kt b/kotlin-native/backend.native/tests/compilerChecks/t7.kt new file mode 100644 index 00000000000..1b85b8f3a31 --- /dev/null +++ b/kotlin-native/backend.native/tests/compilerChecks/t7.kt @@ -0,0 +1,4 @@ +import platform.darwin.* +import platform.Foundation.* + +fun foo(s: Array) = NSLog("zzz", *s) diff --git a/kotlin-native/backend.native/tests/compilerChecks/t8.kt b/kotlin-native/backend.native/tests/compilerChecks/t8.kt new file mode 100644 index 00000000000..91280d2d9ca --- /dev/null +++ b/kotlin-native/backend.native/tests/compilerChecks/t8.kt @@ -0,0 +1,7 @@ +import kotlinx.cinterop.* + +fun foo(f: Function0<*>) = f + +fun bar() { + staticCFunction(::foo) +} diff --git a/kotlin-native/backend.native/tests/compilerChecks/t9.kt b/kotlin-native/backend.native/tests/compilerChecks/t9.kt new file mode 100644 index 00000000000..f65f2ebe230 --- /dev/null +++ b/kotlin-native/backend.native/tests/compilerChecks/t9.kt @@ -0,0 +1,7 @@ +import kotlinx.cinterop.* + +fun foo(f: Function0) = f + +fun bar() { + staticCFunction(::foo) +} diff --git a/kotlin-native/backend.native/tests/coverage/basic/controlflow/main.kt b/kotlin-native/backend.native/tests/coverage/basic/controlflow/main.kt new file mode 100644 index 00000000000..41788ed83eb --- /dev/null +++ b/kotlin-native/backend.native/tests/coverage/basic/controlflow/main.kt @@ -0,0 +1,126 @@ +package coverage.basic.controlflow + +fun main() { + + // If Expression + + var a = 1 + var b = 2 + if (a < b) println("a < b") + + if (a > b) { + println("a > b") + } else if (a == b) { + println("a == b") + } else { + println("a < b") + } + + if (a < b) { + println("a < b") + } + else + { + println("a >= b") + } + + var max = if (a > b) a else b + + max = if (a > b) { + println("Choose a") + a + } else { + println("Choose b") + b + } + + if (a < b) + + println("a < b") + else + + println("a >= b") + + if (a > b) + + println("a > b") + + else + + println("a <= b") + + // When Expression + + when { + a < b -> { + println("a < b") + } + + a == b -> + + println("a == b") + a > b -> { + println("a > b") + } + + else -> { + + + + } + } + + var x = 1 + when (x) { + 1 -> print("x == 1") + 2 -> print("x == 2") + else -> { // Note the block + print("x is neither 1 nor 2") + } + } + x = 2 + when (x) { + 1 -> print("x == 1") + 2 -> print("x == 2") + else -> { // Note the block + print("x is neither 1 nor 2") + } + } + x = 3 + when (x) { + 1 -> print("x == 1") + 2 -> print("x == 2") + else -> { // Note the block + print("x is neither 1 nor 2") + } + } + + when (x) { + 0, 1 + -> + print("x == 0 or x == 1") + else -> + print("otherwise") + } + + when { + else -> println("=)") + } + + // While Loops + + do { + b++ + } while (b < 5) + + while (a < 10) { + a++ + if (a > 7) { + println(a) + } + } + + while (a > 0) + + a-- +} \ No newline at end of file diff --git a/kotlin-native/backend.native/tests/coverage/basic/jumps/main.kt b/kotlin-native/backend.native/tests/coverage/basic/jumps/main.kt new file mode 100644 index 00000000000..a0306316b00 --- /dev/null +++ b/kotlin-native/backend.native/tests/coverage/basic/jumps/main.kt @@ -0,0 +1,90 @@ +package coverage.basic.jumps + +fun simpleReturn(n: Int) { + if (n == 0) return + println(n) +} + +fun returnFromIfBranch(n: Int) { + if (n > 0) { + if (n > 10) { + return + } + } else if (n < -10) { + return + } else if (n == 0) { + return + } + println(n) +} + +fun returnFromWhenBranch(n: Int) { + when { + n == 0 -> return + n == 1 -> return + n == 2 -> { + println(n) + return + } + else -> println(n) + } +} + +fun breakFromWhile() { + var a = 7 + while (true) { + if (a < 4) break + println(a) + a-- + } +} + +fun continueFromDoWhile() { + var a = 0 + do { + if (a % 3 == 0) { + a++ + continue + } + println(a) + a++ + } while (a < 10) +} + +fun singleReturn() { + return +} + +fun nestedReturn() { + while (true) { + while (true) { + while (true) { + if (1 < 2) { + return + } + println() + } + println() + } + } + println() +} + +fun main() { + simpleReturn(0) + simpleReturn(1) + + returnFromIfBranch(1) + returnFromIfBranch(11) + returnFromIfBranch(-11) + returnFromIfBranch(0) + + returnFromWhenBranch(0) + returnFromWhenBranch(1) + returnFromWhenBranch(2) + + breakFromWhile() + continueFromDoWhile() + singleReturn() + nestedReturn() +} \ No newline at end of file diff --git a/kotlin-native/backend.native/tests/coverage/basic/library/library.kt b/kotlin-native/backend.native/tests/coverage/basic/library/library.kt new file mode 100644 index 00000000000..1e47ead0a75 --- /dev/null +++ b/kotlin-native/backend.native/tests/coverage/basic/library/library.kt @@ -0,0 +1,3 @@ +package coverage_library + +fun foo() = "foo" \ No newline at end of file diff --git a/kotlin-native/backend.native/tests/coverage/basic/library/main.kt b/kotlin-native/backend.native/tests/coverage/basic/library/main.kt new file mode 100644 index 00000000000..c62f3636f90 --- /dev/null +++ b/kotlin-native/backend.native/tests/coverage/basic/library/main.kt @@ -0,0 +1,5 @@ +package coverage.basic.library + +fun main() { + println(coverage_library.foo()) +} \ No newline at end of file diff --git a/kotlin-native/backend.native/tests/coverage/basic/program/main.kt b/kotlin-native/backend.native/tests/coverage/basic/program/main.kt new file mode 100644 index 00000000000..f06f146bc65 --- /dev/null +++ b/kotlin-native/backend.native/tests/coverage/basic/program/main.kt @@ -0,0 +1,5 @@ +package coverage.basic.program + +fun main() { + println("OK") +} \ No newline at end of file diff --git a/kotlin-native/backend.native/tests/coverage/basic/smoke0/smoke0.kt b/kotlin-native/backend.native/tests/coverage/basic/smoke0/smoke0.kt new file mode 100644 index 00000000000..b32041494c9 --- /dev/null +++ b/kotlin-native/backend.native/tests/coverage/basic/smoke0/smoke0.kt @@ -0,0 +1,8 @@ +package coverage.basic.smoke0 + +data class User(val name: String) + +fun main() { + val user = User("Happy Kotlin/Native user") + println(user) +} \ No newline at end of file diff --git a/kotlin-native/backend.native/tests/coverage/basic/smoke1/smoke1.kt b/kotlin-native/backend.native/tests/coverage/basic/smoke1/smoke1.kt new file mode 100644 index 00000000000..c7302e5eaf4 --- /dev/null +++ b/kotlin-native/backend.native/tests/coverage/basic/smoke1/smoke1.kt @@ -0,0 +1,48 @@ +package coverage.basic.smoke1 + +class A(val prop: Int) { + + constructor() : this(1) + + fun action1() { + println(prop) + } + + fun action2() { + + } +} + +class B private constructor(val prop: String) { + + init { + println("init block") + } + + constructor(prop1: String, prop2: String) : this("$prop1, $prop2") + + constructor() : this("dummy") { + if (1 > 2) { + println("uncovered") + } else { + println("foo") + } + println("bar") + } + + override fun toString() = prop +} + +fun main(args: Array) { + val a1 = A(2) + a1.action1() + a1.action2() + val a2 = A() + a2.action1() + a2.action1() + + val b1 = B("Hello", "world") + val b2 = B() + println(b1) + println(b2) +} diff --git a/kotlin-native/backend.native/tests/datagen/literals/empty_string.kt b/kotlin-native/backend.native/tests/datagen/literals/empty_string.kt new file mode 100644 index 00000000000..ebb331c690a --- /dev/null +++ b/kotlin-native/backend.native/tests/datagen/literals/empty_string.kt @@ -0,0 +1,12 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +package datagen.literals.empty_string + +import kotlin.test.* + +@Test fun runTest() { + println("") +} diff --git a/kotlin-native/backend.native/tests/datagen/literals/listof1.kt b/kotlin-native/backend.native/tests/datagen/literals/listof1.kt new file mode 100644 index 00000000000..8c01cb18a0e --- /dev/null +++ b/kotlin-native/backend.native/tests/datagen/literals/listof1.kt @@ -0,0 +1,18 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +package datagen.literals.listof1 + +import kotlin.test.* + +@Test fun runTest() { + val list = foo() + println(list === foo()) + println(list.toString()) +} + +fun foo(): List { + return listOf("a", "b", "c") +} \ No newline at end of file diff --git a/kotlin-native/backend.native/tests/datagen/literals/strdedup1.kt b/kotlin-native/backend.native/tests/datagen/literals/strdedup1.kt new file mode 100644 index 00000000000..1e1cc37c5a9 --- /dev/null +++ b/kotlin-native/backend.native/tests/datagen/literals/strdedup1.kt @@ -0,0 +1,15 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +package datagen.literals.strdedup1 + +import kotlin.test.* + +@Test fun runTest() { + val str1 = "Hello" + val str2 = "Hello" + println(str1 == str2) + println(str1 === str2) +} diff --git a/kotlin-native/backend.native/tests/datagen/literals/strdedup2.kt b/kotlin-native/backend.native/tests/datagen/literals/strdedup2.kt new file mode 100644 index 00000000000..763062dfb50 --- /dev/null +++ b/kotlin-native/backend.native/tests/datagen/literals/strdedup2.kt @@ -0,0 +1,15 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +package datagen.literals.strdedup2 + +import kotlin.test.* + +@Test fun runTest() { + val str1 = "" + val str2 = "hello".subSequence(2, 2) + println(str1 == str2) + println(str1 === str2) +} diff --git a/kotlin-native/backend.native/tests/datagen/rtti/abstract_super.kt b/kotlin-native/backend.native/tests/datagen/rtti/abstract_super.kt new file mode 100644 index 00000000000..3af0a753458 --- /dev/null +++ b/kotlin-native/backend.native/tests/datagen/rtti/abstract_super.kt @@ -0,0 +1,17 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +package datagen.rtti.abstract_super + +import kotlin.test.* + +abstract class Super + +class Foo : Super() + +@Test fun runTest() { + // This test now checks that the source can be successfully compiled and linked; + // TODO: check the contents of TypeInfo? +} diff --git a/kotlin-native/backend.native/tests/datagen/rtti/vtable1.kt b/kotlin-native/backend.native/tests/datagen/rtti/vtable1.kt new file mode 100644 index 00000000000..fa1090c8c8b --- /dev/null +++ b/kotlin-native/backend.native/tests/datagen/rtti/vtable1.kt @@ -0,0 +1,21 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +package datagen.rtti.vtable1 + +import kotlin.test.* + +abstract class Super { + abstract fun bar() +} + +class Foo : Super() { + final override fun bar() {} +} + +@Test fun runTest() { + // This test now checks that the source can be successfully compiled and linked; + // TODO: check the contents of TypeInfo? +} \ No newline at end of file diff --git a/kotlin-native/backend.native/tests/datagen/rtti/vtable_any.kt b/kotlin-native/backend.native/tests/datagen/rtti/vtable_any.kt new file mode 100644 index 00000000000..7a464adb20e --- /dev/null +++ b/kotlin-native/backend.native/tests/datagen/rtti/vtable_any.kt @@ -0,0 +1,23 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +package datagen.rtti.vtable_any + +import kotlin.test.* + +@Test +fun runTest() { + // Try to trick devirtualizer + println(anyMethods(arrayListOf("1"))) + println(anyMethods(mapOf("2" to 1).keys)) + println(anyMethods(mapOf("1" to 3).values)) + println(anyMethods(setOf("4"))) +} + +fun anyMethods(iterable: Iterable<*>): String { + assert(iterable.equals(iterable)) + assert(iterable.hashCode() != 0) + return iterable.toString() +} diff --git a/kotlin-native/backend.native/tests/debugger/src/test/kotlin/org/jetbrains/kotlin/native/test/debugger/DistProperties.kt b/kotlin-native/backend.native/tests/debugger/src/test/kotlin/org/jetbrains/kotlin/native/test/debugger/DistProperties.kt new file mode 100644 index 00000000000..ead2acee774 --- /dev/null +++ b/kotlin-native/backend.native/tests/debugger/src/test/kotlin/org/jetbrains/kotlin/native/test/debugger/DistProperties.kt @@ -0,0 +1,27 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +package org.jetbrains.kotlin.native.test.debugger + +import org.jetbrains.kotlin.konan.target.Family +import org.jetbrains.kotlin.konan.target.HostManager +import java.nio.file.Path +import java.nio.file.Paths + +object DistProperties { + private val dist: Path = Paths.get(requireProp("kotlin.native.home")) + private val konancDriver = if (HostManager.host.family == Family.MINGW) "konanc.bat" else "konanc" + private val cinteropDriver = if (HostManager.host.family == Family.MINGW) "cinterop.bat" else "cinterop" + val konanc: Path = dist.resolve("bin/$konancDriver") + val cinterop: Path = dist.resolve("bin/$cinteropDriver") + val lldb: Path = Paths.get("lldb") + val devToolsSecurity: Path = Paths.get("DevToolsSecurity") + val dwarfDump: Path = Paths.get("dwarfdump") + val swiftc: Path = Paths.get("swiftc") + val lldbPrettyPrinters: Path = dist.resolve("tools/konan_lldb.py") + + private fun requireProp(name: String): String + = System.getProperty(name) ?: error("Property `$name` is not defined") +} \ No newline at end of file diff --git a/kotlin-native/backend.native/tests/debugger/src/test/kotlin/org/jetbrains/kotlin/native/test/debugger/Driver.kt b/kotlin-native/backend.native/tests/debugger/src/test/kotlin/org/jetbrains/kotlin/native/test/debugger/Driver.kt new file mode 100644 index 00000000000..6366ae74ff0 --- /dev/null +++ b/kotlin-native/backend.native/tests/debugger/src/test/kotlin/org/jetbrains/kotlin/native/test/debugger/Driver.kt @@ -0,0 +1,137 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +package org.jetbrains.kotlin.native.test.debugger + +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.GlobalScope +import kotlinx.coroutines.async +import kotlinx.coroutines.runBlocking +import org.jetbrains.kotlin.cli.bc.K2Native +import java.io.ByteArrayOutputStream +import java.io.InputStream +import java.io.StringReader +import java.nio.file.Files +import java.nio.file.Path +import java.util.concurrent.TimeUnit + + +class ToolDriver( + private val useInProcessCompiler: Boolean = false +) { + fun compile(source: Path, output: Path, vararg args: String) = compile(output, *args) { + listOf("-output", output.toString(), source.toString(), *args).toTypedArray() + } + + fun compile(output: Path, srcs:Array, vararg args: String) = compile(output, *args) { + listOf("-output", output.toString(), *srcs.map{it.toString()}.toTypedArray(), *args).toTypedArray() + } + + private fun compile(output: Path, vararg args: String, argsCalculator:() -> Array) { + check(!Files.exists(output)) + val allArgs = argsCalculator() + + if (useInProcessCompiler) { + K2Native.main(allArgs) + } else { + subprocess(DistProperties.konanc, *allArgs).thrownIfFailed() + } + check(Files.exists(output)) { + "Compiler has not produced an output at $output" + } + } + + fun cinterop(defFile:Path, output: Path, pkg: String, vararg args: String) { + val allArgs = listOf("-o", output.toString(), "-def", defFile.toString(), "-pkg", pkg, *args).toTypedArray() + + //TODO: do we need in process cinterop? + subprocess(DistProperties.cinterop, *allArgs).thrownIfFailed() + check(Files.exists(output)) { + "Compiler has not produced an output at $output" + } + } + + fun runLldb(program: Path, commands: List): String { + val args = listOf("-b", "-o", "command script import \"${DistProperties.lldbPrettyPrinters}\"") + + commands.flatMap { listOf("-o", it) } + return subprocess(DistProperties.lldb, program.toString(), "-b", *args.toTypedArray()) + .thrownIfFailed() + .stdout + } + + fun runDwarfDump(program: Path, vararg args:String = emptyArray(), processor:List.()->Unit) { + val dwarfProcess = subprocess(DistProperties.dwarfDump, *args, "${program}.dSYM/Contents/Resources/DWARF/${program.fileName}") + val out = dwarfProcess.takeIf { it.process.exitValue() == 0 }?.stdout ?: error(dwarfProcess.stderr) + DwarfUtilParser().parse(StringReader(out)).tags.toList().processor() + } + + fun swiftc(output: Path, swiftSrc: Path, vararg args: String) { + val swiftProcess = subprocess(DistProperties.swiftc, "-o", output.toString(), swiftSrc.toString(), *args) + val out = swiftProcess.takeIf { it.process.exitValue() == 0 }?.stdout ?: error(swiftProcess.stderr) + } +} + +data class ProcessOutput( + val program: Path, + val process: Process, + val stdout: String, + val stderr: String, + val durationMs: Long +) { + fun thrownIfFailed(): ProcessOutput { + fun renderStdStream(name: String, text: String): String = + if (text.isBlank()) "$name is empty" else "$name:\n$text" + + check(process.exitValue() == 0) { + """$program exited with non-zero value: ${process.exitValue()} + |${renderStdStream("stdout", stdout)} + |${renderStdStream("stderr", stderr)} + """.trimMargin() + } + return this + } +} + +fun subprocess(program: Path, vararg args: String): ProcessOutput { + val start = System.currentTimeMillis() + val process = ProcessBuilder(program.toString(), *args).start() + val out = GlobalScope.async(Dispatchers.IO) { + readStream(process, process.inputStream.buffered()) + } + + val err = GlobalScope.async(Dispatchers.IO) { + readStream(process, process.errorStream.buffered()) + } + + return runBlocking { + try { + val status = process.waitFor(5L, TimeUnit.MINUTES) + if (!status) { + out.cancel() + err.cancel() + error("$program timeouted") + } + }catch (e:Exception) { + out.cancel() + err.cancel() + error(e) + } + ProcessOutput(program, process, out.await(), err.await(), System.currentTimeMillis() - start) + } +} + +private fun readStream(process: Process, stream: InputStream): String { + var size = 4096 + val buffer = ByteArray(size) { 0 } + val sunk = ByteArrayOutputStream() + while (true) { + size = stream.read(buffer, 0, buffer.size) + if (size < 0 && !process.isAlive) + break + if (size > 0) + sunk.write(buffer, 0, size) + } + return String(sunk.toByteArray()) +} diff --git a/kotlin-native/backend.native/tests/debugger/src/test/kotlin/org/jetbrains/kotlin/native/test/debugger/DwarfDumpParser.kt b/kotlin-native/backend.native/tests/debugger/src/test/kotlin/org/jetbrains/kotlin/native/test/debugger/DwarfDumpParser.kt new file mode 100644 index 00000000000..d9d89e30ec5 --- /dev/null +++ b/kotlin-native/backend.native/tests/debugger/src/test/kotlin/org/jetbrains/kotlin/native/test/debugger/DwarfDumpParser.kt @@ -0,0 +1,363 @@ +package org.jetbrains.kotlin.native.test.debugger + +import java.io.File +import java.io.Reader +import java.lang.StringBuilder + +sealed class DwarfTag(val tag: Tag) { + enum class Tag(val value: Int) { + DW_TAG_array_type(0x0001), + DW_TAG_class_type(0x0002), + DW_TAG_entry_point(0x0003), + DW_TAG_enumeration_type(0x0004), + DW_TAG_formal_parameter(0x0005), + DW_TAG_imported_declaration(0x0008), + DW_TAG_label(0x000a), + DW_TAG_lexical_block(0x000b), + DW_TAG_member(0x000d), + DW_TAG_pointer_type(0x000f), + DW_TAG_reference_type(0x0010), + DW_TAG_compile_unit(0x0011), + DW_TAG_string_type(0x0012), + DW_TAG_structure_type(0x0013), + DW_TAG_subroutine_type(0x0015), + DW_TAG_typedef(0x0016), + DW_TAG_union_type(0x0017), + DW_TAG_unspecified_parameters(0x0018), + DW_TAG_variant(0x0019), + DW_TAG_common_block(0x001a), + DW_TAG_common_inclusion(0x001b), + DW_TAG_inheritance(0x001c), + DW_TAG_inlined_subroutine(0x001d), + DW_TAG_module(0x001e), + DW_TAG_ptr_to_member_type(0x001f), + DW_TAG_set_type(0x0020), + DW_TAG_subrange_type(0x0021), + DW_TAG_with_stmt(0x0022), + DW_TAG_access_declaration(0x0023), + DW_TAG_base_type(0x0024), + DW_TAG_catch_block(0x0025), + DW_TAG_const_type(0x0026), + DW_TAG_constant(0x0027), + DW_TAG_enumerator(0x0028), + DW_TAG_file_type(0x0029), + DW_TAG_friend(0x002a), + DW_TAG_namelist(0x002b), + DW_TAG_namelist_item(0x002c), + DW_TAG_packed_type(0x002d), + DW_TAG_subprogram(0x002e), + DW_TAG_template_type_parameter(0x002f), + DW_TAG_template_value_parameter(0x0030), + DW_TAG_thrown_type(0x0031), + DW_TAG_try_block(0x0032), + DW_TAG_variant_part(0x0033), + DW_TAG_variable(0x0034), + DW_TAG_volatile_type(0x0035), + DW_TAG_dwarf_procedure(0x0036), + DW_TAG_restrict_type(0x0037), + DW_TAG_interface_type(0x0038), + DW_TAG_namespace(0x0039), + DW_TAG_imported_module(0x003a), + DW_TAG_unspecified_type(0x003b), + DW_TAG_partial_unit(0x003c), + DW_TAG_imported_unit(0x003d), + DW_TAG_condition(0x003f), + DW_TAG_shared_type(0x0040), + DW_TAG_type_unit(0x0041), + DW_TAG_rvalue_reference_type(0x0042), + DW_TAG_template_alias(0x0043), + DW_TAG_coarray_type(0x0044), + DW_TAG_generic_subrange(0x0045), + DW_TAG_dynamic_type(0x0046), + DW_TAG_MIPS_loop(0x4081), + DW_TAG_format_label(0x4101), + DW_TAG_function_template(0x4102), + DW_TAG_class_template(0x4103), + DW_TAG_GNU_template_template_param(0x4106), + DW_TAG_GNU_template_parameter_pack(0x4107), + DW_TAG_GNU_formal_parameter_pack(0x4108), + DW_TAG_APPLE_property(0x4200), + DW_TAG_BORLAND_property(0xb000), + DW_TAG_BORLAND_Delphi_string(0xb001), + DW_TAG_BORLAND_Delphi_dynamic_array(0xb002), + DW_TAG_BORLAND_Delphi_set(0xb003), + DW_TAG_BORLAND_Delphi_variant(0xb004), + } + val attributes = mutableMapOf() + operator fun DwarfAttribute.unaryPlus() { attributes[this.attribute] = this } + companion object { + fun by(name: String) = by(Tag.valueOf(name)) + fun by(tag: Tag) = when(tag) { + Tag.DW_TAG_subprogram -> DwarfTagSubprogram() + else -> DwarfTagDefault(tag) + } + } +} + +class DwarfTagDefault(tag: DwarfTag.Tag): DwarfTag(tag) +class DwarfTagSubprogram: DwarfTag(Tag.DW_TAG_subprogram) { + val name: String + get() = attributes[DwarfAttribute.Attribute.DW_AT_name]!!.rvString + val path: String? + get() = attributes[DwarfAttribute.Attribute.DW_AT_decl_file]?.rvString + val file: File? + get() = path?.run { File(this) } +} + +class DwarfAttribute(val attribute: Attribute, val rawValue: String) { + enum class Attribute(val value: Int) { + DW_AT_sibling(0x01), + DW_AT_location(0x02), + DW_AT_name(0x03), + DW_AT_ordering(0x09), + DW_AT_byte_size(0x0b), + DW_AT_bit_offset(0x0c), + DW_AT_bit_size(0x0d), + DW_AT_stmt_list(0x10), + DW_AT_low_pc(0x11), + DW_AT_high_pc(0x12), + DW_AT_language(0x13), + DW_AT_discr(0x15), + DW_AT_discr_value(0x16), + DW_AT_visibility(0x17), + DW_AT_import(0x18), + DW_AT_string_length(0x19), + DW_AT_common_reference(0x1a), + DW_AT_comp_dir(0x1b), + DW_AT_const_value(0x1c), + DW_AT_containing_type(0x1d), + DW_AT_default_value(0x1e), + DW_AT_inline(0x20), + DW_AT_is_optional(0x21), + DW_AT_lower_bound(0x22), + DW_AT_producer(0x25), + DW_AT_prototyped(0x27), + DW_AT_return_addr(0x2a), + DW_AT_start_scope(0x2c), + DW_AT_bit_stride(0x2e), + DW_AT_upper_bound(0x2f), + DW_AT_abstract_origin(0x31), + DW_AT_accessibility(0x32), + DW_AT_address_class(0x33), + DW_AT_artificial(0x34), + DW_AT_base_types(0x35), + DW_AT_calling_convention(0x36), + DW_AT_count(0x37), + DW_AT_data_member_location(0x38), + DW_AT_decl_column(0x39), + DW_AT_decl_file(0x3a), + DW_AT_decl_line(0x3b), + DW_AT_declaration(0x3c), + DW_AT_discr_list(0x3d), + DW_AT_encoding(0x3e), + DW_AT_external(0x3f), + DW_AT_frame_base(0x40), + DW_AT_friend(0x41), + DW_AT_identifier_case(0x42), + DW_AT_macro_info(0x43), + DW_AT_namelist_item(0x44), + DW_AT_priority(0x45), + DW_AT_segment(0x46), + DW_AT_specification(0x47), + DW_AT_static_link(0x48), + DW_AT_type(0x49), + DW_AT_use_location(0x4a), + DW_AT_variable_parameter(0x4b), + DW_AT_virtuality(0x4c), + DW_AT_vtable_elem_location(0x4d), + DW_AT_allocated(0x4e), + DW_AT_associated(0x4f), + DW_AT_data_location(0x50), + DW_AT_byte_stride(0x51), + DW_AT_entry_pc(0x52), + DW_AT_use_UTF8(0x53), + DW_AT_extension(0x54), + DW_AT_ranges(0x55), + DW_AT_trampoline(0x56), + DW_AT_call_column(0x57), + DW_AT_call_file(0x58), + DW_AT_call_line(0x59), + DW_AT_description(0x5a), + DW_AT_binary_scale(0x5b), + DW_AT_decimal_scale(0x5c), + DW_AT_small(0x5d), + DW_AT_decimal_sign(0x5e), + DW_AT_digit_count(0x5f), + DW_AT_picture_string(0x60), + DW_AT_mutable(0x61), + DW_AT_threads_scaled(0x62), + DW_AT_explicit(0x63), + DW_AT_object_pointer(0x64), + DW_AT_endianity(0x65), + DW_AT_elemental(0x66), + DW_AT_pure(0x67), + DW_AT_recursive(0x68), + DW_AT_signature(0x69), + DW_AT_main_subprogram(0x6a), + DW_AT_data_bit_offset(0x6b), + DW_AT_const_expr(0x6c), + DW_AT_enum_class(0x6d), + DW_AT_linkage_name(0x6e), + DW_AT_string_length_bit_size(0x6f), + DW_AT_string_length_byte_size(0x70), + DW_AT_rank(0x71), + DW_AT_str_offsets_base(0x72), + DW_AT_addr_base(0x73), + DW_AT_rnglists_base(0x74), + DW_AT_dwo_id(0x75), ///< Retracted from DWARF v5. + DW_AT_dwo_name(0x76), + DW_AT_reference(0x77), + DW_AT_rvalue_reference(0x78), + DW_AT_macros(0x79), + DW_AT_call_all_calls(0x7a), + DW_AT_call_all_source_calls(0x7b), + DW_AT_call_all_tail_calls(0x7c), + DW_AT_call_return_pc(0x7d), + DW_AT_call_value(0x7e), + DW_AT_call_origin(0x7f), + DW_AT_call_parameter(0x80), + DW_AT_call_pc(0x81), + DW_AT_call_tail_call(0x82), + DW_AT_call_target(0x83), + DW_AT_call_target_clobbered(0x84), + DW_AT_call_data_location(0x85), + DW_AT_call_data_value(0x86), + DW_AT_noreturn(0x87), + DW_AT_alignment(0x88), + DW_AT_export_symbols(0x89), + DW_AT_deleted(0x8a), + DW_AT_defaulted(0x8b), + DW_AT_loclists_base(0x8c), + DW_AT_MIPS_loop_begin(0x2002), + DW_AT_MIPS_tail_loop_begin(0x2003), + DW_AT_MIPS_epilog_begin(0x2004), + DW_AT_MIPS_loop_unroll_factor(0x2005), + DW_AT_MIPS_software_pipeline_depth(0x2006), + DW_AT_MIPS_linkage_name(0x2007), + DW_AT_MIPS_stride(0x2008), + DW_AT_MIPS_abstract_name(0x2009), + DW_AT_MIPS_clone_origin(0x200a), + DW_AT_MIPS_has_inlines(0x200b), + DW_AT_MIPS_stride_byte(0x200c), + DW_AT_MIPS_stride_elem(0x200d), + DW_AT_MIPS_ptr_dopetype(0x200e), + DW_AT_MIPS_allocatable_dopetype(0x200f), + DW_AT_MIPS_assumed_shape_dopetype(0x2010), + DW_AT_MIPS_assumed_size(0x2011), + DW_AT_sf_names(0x2101), + DW_AT_src_info(0x2102), + DW_AT_mac_info(0x2103), + DW_AT_src_coords(0x2104), + DW_AT_body_begin(0x2105), + DW_AT_body_end(0x2106), + DW_AT_GNU_vector(0x2107), + DW_AT_GNU_template_name(0x2110), + DW_AT_GNU_odr_signature(0x210f), + DW_AT_GNU_call_site_value(0x2111), + DW_AT_GNU_all_call_sites(0x2117), + DW_AT_GNU_macros(0x2119), + DW_AT_GNU_dwo_name(0x2130), + DW_AT_GNU_dwo_id(0x2131), + DW_AT_GNU_ranges_base(0x2132), + DW_AT_GNU_addr_base(0x2133), + DW_AT_GNU_pubnames(0x2134), + DW_AT_GNU_pubtypes(0x2135), + DW_AT_GNU_discriminator(0x2136), + DW_AT_BORLAND_property_read(0x3b11), + DW_AT_BORLAND_property_write(0x3b12), + DW_AT_BORLAND_property_implements(0x3b13), + DW_AT_BORLAND_property_index(0x3b14), + DW_AT_BORLAND_property_default(0x3b15), + DW_AT_BORLAND_Delphi_unit(0x3b20), + DW_AT_BORLAND_Delphi_class(0x3b21), + DW_AT_BORLAND_Delphi_record(0x3b22), + DW_AT_BORLAND_Delphi_metaclass(0x3b23), + DW_AT_BORLAND_Delphi_constructor(0x3b24), + DW_AT_BORLAND_Delphi_destructor(0x3b25), + DW_AT_BORLAND_Delphi_anonymous_method(0x3b26), + DW_AT_BORLAND_Delphi_interface(0x3b27), + DW_AT_BORLAND_Delphi_ABI(0x3b28), + DW_AT_BORLAND_Delphi_return(0x3b29), + DW_AT_BORLAND_Delphi_frameptr(0x3b30), + DW_AT_BORLAND_closure(0x3b31), + DW_AT_LLVM_include_path(0x3e00), + DW_AT_LLVM_config_macros(0x3e01), + DW_AT_LLVM_isysroot(0x3e02), + DW_AT_APPLE_optimized(0x3fe1), + DW_AT_APPLE_flags(0x3fe2), + DW_AT_APPLE_isa(0x3fe3), + DW_AT_APPLE_block(0x3fe4), + DW_AT_APPLE_major_runtime_vers(0x3fe5), + DW_AT_APPLE_runtime_class(0x3fe6), + DW_AT_APPLE_omit_frame_ptr(0x3fe7), + DW_AT_APPLE_property_name(0x3fe8), + DW_AT_APPLE_property_getter(0x3fe9), + DW_AT_APPLE_property_setter(0x3fea), + DW_AT_APPLE_property_attribute(0x3feb), + DW_AT_APPLE_objc_complete_type(0x3fec), + DW_AT_APPLE_property(0x3fed), + } + + companion object { + fun by(name: String, rawValue: String): DwarfAttribute = by(Attribute.valueOf(name), rawValue) + fun by(attribute: Attribute, rawValue: String) = DwarfAttribute(attribute, rawValue) + } +} + +val DwarfAttribute.rvString: String + get() = rawValue.trim().substring(1, rawValue.length - 2) + + +class DwarfUtilParser() { + val tags = mutableListOf() + var currentTag: DwarfTag? = null + var currentAttribute: DwarfAttribute.Attribute? = null + val currentAttributePayload = StringBuilder() + companion object { + val tagRegexp = Regex("^(0x[0-9a-f]{8}):\\ +([^\\ .]*)$") + val attributeRegexp = Regex("^\\s+(DW_AT_[a-zA-Z0-9_]*)\\s+\\((.*)\\)$") + } + + fun tag(tag: DwarfTag) { + appendCurrentAttribute() + tags.add(tag) + currentTag = tag + currentAttribute = null + } + + private fun appendCurrentAttribute() { + currentTag ?: return + with(currentTag!!) { + currentAttribute ?: return + +DwarfAttribute.by(currentAttribute!!, currentAttributePayload.toString()) + currentAttributePayload.clear() + } + } + + fun attribute(attribute: DwarfAttribute.Attribute, payload: String) { + appendCurrentAttribute() + currentAttribute = attribute + currentAttributePayload.appendLine(payload) + } + + fun parse(reader: Reader): DwarfUtilParser { + reader.forEachLine { line -> + tagRegexp.find(line)?.apply { + val str = this.destructured.component2().trim() + if (str == "NULL") + return@forEachLine + tag(DwarfTag.by(str)) + return@forEachLine + } + + attributeRegexp.find(line)?.apply { + attribute(DwarfAttribute.Attribute.valueOf(destructured.component1()), destructured.component2()) + return@forEachLine + } + + currentTag ?: return@forEachLine + currentAttributePayload.appendLine(line) + } + return this + } +} diff --git a/kotlin-native/backend.native/tests/debugger/src/test/kotlin/org/jetbrains/kotlin/native/test/debugger/DwarfTests.kt b/kotlin-native/backend.native/tests/debugger/src/test/kotlin/org/jetbrains/kotlin/native/test/debugger/DwarfTests.kt new file mode 100644 index 00000000000..3913f88ba9d --- /dev/null +++ b/kotlin-native/backend.native/tests/debugger/src/test/kotlin/org/jetbrains/kotlin/native/test/debugger/DwarfTests.kt @@ -0,0 +1,73 @@ +package org.jetbrains.kotlin.native.test.debugger + +import junit.framework.Assert.* +import org.junit.Ignore +import org.junit.Test + +class DwarfTests { + @Test + fun `prefix test`() = dwarfDumpTest(""" + fun main(args: Array) { + val xs = intArrayOf(3, 5, 8) + return + } + + data class Point(val x: Int, val y: Int) + """.trimIndent(), listOf("-Xdebug-prefix-map=${System.getProperty("user.home")}=/xxx")){ + val map = flatMap( fun (it: DwarfTag): List { return it.attributes.values.toList()}) + .filter { it.attribute == DwarfAttribute.Attribute.DW_AT_decl_file }.map { it.rvString } + assertNotSame(0, map.size) + } + + /** + * TODO: to enable this test it's required to fix issue with poisonig call site with wrong file owner ship of lambda + * passed as parameter to inline function. + */ + @Test + fun `address of VolatileLambda lookup`() = dwarfDumpComplexTest { + val callbackLibrary = """ + --- + int callback(int (*f)(int)) { + return 42 + f(0xdeadbeef); + } + """.trimIndent().cinterop("callback", "callback") + val trapLibrary = """ + --- + void trap() { + __builtin_trap(); + } + """.trimIndent().cinterop("trap", "trap") + + val poisonLibrary = """ + package poison + import trap.* + import callback.* + import kotlinx.cinterop.staticCFunction + + + inline fun execute():Int { + return callback(staticCFunction{ + a -> + trap() + 2 * a + }) + } + """.trimIndent().library("poison", "-l", callbackLibrary.toString(), "-l", trapLibrary.toString()) + + val binary = """ + import poison.* + + fun main() { + execute() + } + """.trimIndent().binary("poisoned", "-g", "-l", poisonLibrary.toString(), "-l", callbackLibrary.toString(), "-l", trapLibrary.toString()) + + binary.dwarfDumpLookup("kfun:main\$_1#internal") { + assertFalse(this.isEmpty()) + val subprogram = single { it.tag == DwarfTag.Tag.DW_TAG_subprogram } as DwarfTagSubprogram + assertEquals(subprogram.file!!.name, "poison.kt") + } + } + + +} \ No newline at end of file diff --git a/kotlin-native/backend.native/tests/debugger/src/test/kotlin/org/jetbrains/kotlin/native/test/debugger/LldbTests.kt b/kotlin-native/backend.native/tests/debugger/src/test/kotlin/org/jetbrains/kotlin/native/test/debugger/LldbTests.kt new file mode 100644 index 00000000000..b06536b32c6 --- /dev/null +++ b/kotlin-native/backend.native/tests/debugger/src/test/kotlin/org/jetbrains/kotlin/native/test/debugger/LldbTests.kt @@ -0,0 +1,150 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +import org.jetbrains.kotlin.native.test.debugger.lldbComplexTest +import org.jetbrains.kotlin.native.test.debugger.lldbTest +import org.junit.Test + +class LldbTests { + @Test + fun `can step through code`() = lldbTest(""" + fun main(args: Array) { + var x = 1 + var y = 2 + var z = x + y + println(z) + } + """, """ + > b main.kt:2 + Breakpoint 1: [..] + + > r + Process [..] stopped + [..] stop reason = breakpoint 1.1 + [..] at main.kt:2[..] + + > n + Process [..] stopped + [..] stop reason = step over + [..] at main.kt:3[..] + + > n + Process [..] stopped + [..] stop reason = step over + [..] at main.kt:4[..] + + > n + Process [..] stopped + [..] stop reason = step over + [..] at main.kt:5[..] + """) + + @Test + fun `can inspect values of primitive types`() = lldbTest(""" + fun main(args: Array) { + var a: Byte = 1 + var b: Int = 2 + var c: Long = -3 + var d: Char = 'c' + var e: Boolean = true + return + } + """, """ + > b main.kt:7 + > r + > fr var + (char) a = '\x01' + (int) b = 2 + (long) c = -3 + (short) d = 99 + (bool) e = true + """) + + @Test + fun `can inspect classes`() = lldbTest(""" + fun main(args: Array) { + val point = Point(1, 2) + val person = Person() + return + } + + data class Point(val x: Int, val y: Int) + class Person { + override fun toString() = "John Doe" + } + """, """ + > b main.kt:4 + > r + > fr var + (ObjHeader *) args = [] + (ObjHeader *) point = {'x': 1, 'y': 2} + (ObjHeader *) person = {} + """) + + @Test + fun `can inspect arrays`() = lldbTest(""" + fun main(args: Array) { + val xs = IntArray(3) + xs[0] = 1 + xs[1] = 2 + xs[2] = 3 + val ys: Array = arrayOfNulls(2) + ys[0] = Point(1, 2) + return + } + + data class Point(val x: Int, val y: Int) + """, """ + > b main.kt:8 + > r + > fr var + (ObjHeader *) args = [] + (ObjHeader *) xs = [1, 2, 3] + (ObjHeader *) ys = [{'x': 1, 'y': 2}, 'null'] + """) + + @Test + fun `can inspect array children`() = lldbTest(""" + fun main(args: Array) { + val xs = intArrayOf(3, 5, 8) + return + } + + data class Point(val x: Int, val y: Int) + """, """ + > b main.kt:3 + > r + > fr var xs + (ObjHeader *) xs = [3, 5, 8] + """) + + @Test + fun `swift with kotlin static framework`() = lldbComplexTest { + val aKtSrc = """ + fun a() = "a" + """.feedOutput("a.kt") + val bKtSrc = """ + fun b() = "b" + """.feedOutput("b.kt") + + arrayOf(aKtSrc, bKtSrc).framework("AandBFramework", "-g", "-Xstatic-framework") + + val swiftSrc = """ + import AandBFramework + + print(AKt.a()) + print(BKt.b()) + + """.feedOutput("test.swift") + val application = swiftc("application", swiftSrc, "-F", root.toString()) + """ + > b kfun:#b(){}kotlin.String + Breakpoint 1: where = [..]`kfun:#b(){}kotlin.String [..] at b.kt:1:1, [..] + + > b kfun:#a(){}kotlin.String + Breakpoint 2: where = [..]`kfun:#a(){}kotlin.String [..] at a.kt:1:1, [..] + """.trimIndent().lldb(application) + } +} \ No newline at end of file diff --git a/kotlin-native/backend.native/tests/debugger/src/test/kotlin/org/jetbrains/kotlin/native/test/debugger/Matchers.kt b/kotlin-native/backend.native/tests/debugger/src/test/kotlin/org/jetbrains/kotlin/native/test/debugger/Matchers.kt new file mode 100644 index 00000000000..88a0df6bb0e --- /dev/null +++ b/kotlin-native/backend.native/tests/debugger/src/test/kotlin/org/jetbrains/kotlin/native/test/debugger/Matchers.kt @@ -0,0 +1,310 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +package org.jetbrains.kotlin.native.test.debugger + +import org.intellij.lang.annotations.Language +import org.junit.Assert.fail +import java.io.IOException +import java.nio.file.Files +import java.nio.file.Path + +/** + * An integration test for debug info. + * + * It works by compiling a given [programText] with debug info, + * then launching lldb, feeding it commands from [lldbSession] + * and matching the output. + * + * [lldbSession] specifies both lldb commands and expected output + * using a DLS, which looks like this: + * + * > b main.kt:5 + * Breakpoint 1: [..] + * > r + * Process [..] stopped + * [..] at main.kt:5, [..] stop reason = breakpoint [..] + * > fr var + * (int) a = 92 + * (int) b = 2 + * + * It consists of blocks of the form + * + * > lldb command + * response line pattern + * another pattern + * + * Command after `>` is passed to lldb exactly. The output of the command + * is then matched against a set of patterns. Matching is done line by line: + * for every pattern, there must be a matching line in the output, but you don't + * have to specify a pattern for every line. In particular, it's possible not to + * specify any patterns at all: + * + * > b main.kt:2 + * > r + * > n + * [..] at main.kt:3, [..] stop reason = step over + * + * The patterns themselves are simple. The only special symbol is `[..]` which + * means arbitrary substring, which can help match random data, timings, and OS-dependent output. + * For example, to match + * + * Current executable set to '/tmp/debugger_test7458723719928260513/program.kexe' (x86_64). + * + * one writes + * + * Current executable set to [..]program.kexe[..] + */ +fun lldbTest(@Language("kotlin") programText: String, lldbSession: String) { + if (!haveLldb) { + println("Skipping test: no LLDB") + return + } + + if (!isOsxDevToolsEnabled) { + println("""Development tools aren't available. + |Please consider to execute: + | ${DistProperties.devToolsSecurity} -enable + |or + | csrutil disable + |to run lldb tests""".trimMargin()) + return + } + val lldbSessionSpec = LldbSessionSpecification.parse(lldbSession) + + val tmpdir = Files.createTempDirectory("debugger_test") + tmpdir.toFile().deleteOnExit() + val source = tmpdir.resolve("main.kt") + val output = tmpdir.resolve("program.kexe") + + val driver = ToolDriver() + Files.write(source, programText.trimIndent().toByteArray()) + driver.compile(source, output, "-g") + val result = driver.runLldb(output, lldbSessionSpec.commands) + lldbSessionSpec.match(result) +} + +private val isOsxDevToolsEnabled: Boolean by lazy { + //TODO: add OSX checks. + val rawStatus = subprocess(DistProperties.devToolsSecurity, "-status") + println("> status: $rawStatus") + + val r = Regex("^.*\\ (enabled|disabled).$") + r.find(rawStatus.stdout)?.destructured?.component1() == "enabled" +} + +fun dwarfDumpTest(@Language("kotlin") programText: String, flags: List, test:List.()->Unit) { + if (!haveDwarfDump) { + println("Skipping test: no dwarfdump") + return + } + + + with(Files.createTempDirectory("dwarfdump_test")) { + toFile().deleteOnExit() + val source = resolve("main.kt") + val output = resolve("program.kexe") + + val driver = ToolDriver() + Files.write(source, programText.trimIndent().toByteArray()) + driver.compile(source, output, "-g", *flags.toTypedArray()) + driver.runDwarfDump(output, processor = test) + } +} + +class ToolDriverHelper(private val driver: ToolDriver, val root:Path) { + fun String.cinterop(pkg:String, output: String):Path { + val def = feedOutput("$output.def") + val lib = root.resolve("$output.klib") + driver.cinterop(def, lib, pkg) + return lib + } + + + fun String.library(output: String, vararg flags:String) = feedOutput("$output.kt").compile(root.resolve("$output.klib"), "-p", "library", *flags) + + fun String.binary(output: String, vararg flags:String)= feedOutput("$output.kt").compile(root.resolve("$output.kexe"), *flags) + + private fun Path.compile(output: Path, vararg flags:String) = output.also{ driver.compile(source = this, it, *flags) } + + fun Path.dwarfDumpLookup(address: Long, parser:List.() -> Unit) = driver.runDwarfDump(this, "-lookup", address.toString(), processor = parser) + fun Path.dwarfDumpLookup(name: String, parser:List.() -> Unit) = driver.runDwarfDump(this, "-find", name, processor = parser) + + + fun String.feedOutput(output: String) = root.resolve(output).also { + Files.write(it, this.trimIndent().toByteArray()) + } + + fun Array.framework(name:String, vararg args:String = emptyArray()):Path = root.resolve("$name.framework").also { + + driver.compile(it, this, "-produce", "framework", *args) + } + + fun swiftc(output: String, swiftSrc: Path, vararg args: String) = root.resolve(output).also { + driver.swiftc(it, swiftSrc, *args, "-Xlinker", "-rpath", "-Xlinker", "@executable_path") + } + + fun String.lldb(program:Path) { + val lldbSessionSpec = LldbSessionSpecification.parse(this) + val result = driver.runLldb(program, lldbSessionSpec.commands) + lldbSessionSpec.match(result) + } + +} + +fun dwarfDumpComplexTest(test:ToolDriverHelper.()->Unit) { + if (!haveDwarfDump) { + println("Skipping test: no dwarfdump") + return + } + + + with(Files.createTempDirectory("dwarfdump_test_complex")) { + toFile().deleteOnExit() + val driver = ToolDriverHelper(ToolDriver(), this).test() + } +} + +fun lldbComplexTest(test:ToolDriverHelper.()->Unit) { + if (!haveLldb) { + println("Skipping test: no lldb") + return + } + + + with(Files.createTempDirectory("lldb_test_complex")) { + toFile().deleteOnExit() + val driver = ToolDriverHelper(ToolDriver(), this).test() + } +} + + +private val haveDwarfDump: Boolean by lazy { + val version = try { + subprocess(DistProperties.dwarfDump, "--version") + .takeIf { it.process.exitValue() == 0 } + ?.stdout + } catch (e: IOException) { + null + } + + if (version == null) { + println("No LLDB found") + } else { + println("Using $version") + } + + version != null +} + +private val haveLldb: Boolean by lazy { + val lldbVersion = try { + subprocess(DistProperties.lldb, "-version") + .takeIf { it.process.exitValue() == 0 } + ?.stdout + } catch (e: IOException) { + null + } + + if (lldbVersion == null) { + println("No LLDB found") + } else { + println("Using $lldbVersion") + } + + lldbVersion != null +} + +private class LldbSessionSpecification private constructor( + val commands: List, + val patterns: List> +) { + + fun match(output: String) { + val blocks = output.split("""(?=\(lldb\))""".toRegex()).filterNot(String::isEmpty) + check(blocks[0].startsWith("(lldb) target create")) { "Missing block \"target create\". Got: ${blocks[0]}" } + check(blocks[1].startsWith("(lldb) command script import")) { + "Missing block \"command script import\". Got: ${blocks[0]}" + } + val responses = blocks.drop(2) + val executedCommands = responses.map { it.lines().first() } + val bodies = responses.map { it.lines().drop(1) } + val responsesMatch = executedCommands.size == commands.size + && commands.zip(executedCommands).all { (cmd, h) -> h == "(lldb) $cmd" } + + if (!responsesMatch) { + val message = """ + |Responses do not match commands. + | + |COMMANDS: |$commands + |RESPONSES: |$executedCommands + | + |FULL SESSION: + |$output + """.trimMargin() + fail(message) + } + + for ((patternBody, command) in patterns.zip(bodies).zip(executedCommands)) { + val (pattern, body) = patternBody + val mismatch = findMismatch(pattern, body) + if (mismatch != null) { + val message = """ + |Wrong LLDB output. + | + |COMMAND: $command + |PATTERN: $mismatch + |OUTPUT: + |${body.joinToString("\n")} + | + |FULL SESSION: + |$output + """.trimMargin() + fail(message) + } + } + } + + private fun findMismatch(patterns: List, actualLines: List): String? { + val indices = mutableListOf() + for (pattern in patterns) { + val idx = actualLines.indexOfFirst { match(pattern, it) } + if (idx == -1) { + return pattern + } + indices += idx + } + check(indices == indices.sorted()) + return null + } + + private fun match(pattern: String, line: String): Boolean { + val chunks = pattern.split("""\s*\[\.\.]\s*""".toRegex()) + .filter { it.isNotBlank() } + .map { it.trim() } + check(chunks.isNotEmpty()) + val trimmedLine = line.trim() + + val indices = chunks.map { trimmedLine.indexOf(it) } + if (indices.any { it == -1 } || indices != indices.sorted()) return false + if (!(trimmedLine.startsWith(chunks.first()) || pattern.startsWith("[..]"))) return false + if (!(trimmedLine.endsWith(chunks.last()) || pattern.endsWith("[..]"))) return false + return true + } + + companion object { + fun parse(spec: String): LldbSessionSpecification { + val blocks = spec.trimIndent() + .split("(?=^>)".toRegex(RegexOption.MULTILINE)) + .filterNot(String::isEmpty) + for (cmd in blocks) { + check(cmd.startsWith(">")) { "Invalid lldb session specification: $cmd" } + } + val commands = blocks.map { it.lines().first().substring(1).trim() } + val patterns = blocks.map { it.lines().drop(1).filter { it.isNotBlank() } } + return LldbSessionSpecification(commands, patterns) + } + } +} diff --git a/kotlin-native/backend.native/tests/extensions/nop/src/main/kotlin/org/jetbrains/konan/test/plugin/nop/NopPlugin.kt b/kotlin-native/backend.native/tests/extensions/nop/src/main/kotlin/org/jetbrains/konan/test/plugin/nop/NopPlugin.kt new file mode 100644 index 00000000000..2893b033e3d --- /dev/null +++ b/kotlin-native/backend.native/tests/extensions/nop/src/main/kotlin/org/jetbrains/konan/test/plugin/nop/NopPlugin.kt @@ -0,0 +1,14 @@ +package org.jetbrains.konan.test.plugin.nop + +import org.jetbrains.kotlin.backend.common.extensions.IrPluginContext +import org.jetbrains.kotlin.backend.common.extensions.IrGenerationExtension +import org.jetbrains.kotlin.ir.declarations.IrModuleFragment + +open class NopExtension : IrGenerationExtension { + override fun generate( + moduleFragment: IrModuleFragment, + pluginContext: IrPluginContext + ) { + + } +} \ No newline at end of file diff --git a/kotlin-native/backend.native/tests/external/codegen/box/properties/lateinit/accessor.kt b/kotlin-native/backend.native/tests/external/codegen/box/properties/lateinit/accessor.kt new file mode 100644 index 00000000000..0b3e12be136 --- /dev/null +++ b/kotlin-native/backend.native/tests/external/codegen/box/properties/lateinit/accessor.kt @@ -0,0 +1,5 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + diff --git a/kotlin-native/backend.native/tests/framework/gh3343/ktlib.kt b/kotlin-native/backend.native/tests/framework/gh3343/ktlib.kt new file mode 100644 index 00000000000..b20316f4c4d --- /dev/null +++ b/kotlin-native/backend.native/tests/framework/gh3343/ktlib.kt @@ -0,0 +1,15 @@ +import kotlinx.cinterop.* +import objclib.* +import kotlin.native.ref.* + +fun run(): List { + val result = mutableListOf() + result.add(foo1(42)) + val list = foo2(117) + if (list != null) { + result.add(list.size) + for (x in list) + result.add(x) + } + return result +} \ No newline at end of file diff --git a/kotlin-native/backend.native/tests/framework/gh3343/objclib.def b/kotlin-native/backend.native/tests/framework/gh3343/objclib.def new file mode 100644 index 00000000000..5372fd7a975 --- /dev/null +++ b/kotlin-native/backend.native/tests/framework/gh3343/objclib.def @@ -0,0 +1,3 @@ +language = Objective-C +headers = Foundation/NSArray.h Foundation/NSValue.h Foundation/NSString.h +headerFilter = **/objclib.h Foundation/NSArray.h Foundation/NSValue.h Foundation/NSString.h diff --git a/kotlin-native/backend.native/tests/framework/gh3343/objclib.h b/kotlin-native/backend.native/tests/framework/gh3343/objclib.h new file mode 100644 index 00000000000..38574c72a92 --- /dev/null +++ b/kotlin-native/backend.native/tests/framework/gh3343/objclib.h @@ -0,0 +1,11 @@ +#import + +NSString* foo1(int x) { + return [NSString stringWithFormat:@"%d", x]; +} + +NSArray* foo2(int x) { + NSValue* xx = @(x); + NSString* s = @"zzz"; + return [NSArray arrayWithObjects: xx, s, nil]; +} \ No newline at end of file diff --git a/kotlin-native/backend.native/tests/framework/gh3343/uselib.swift b/kotlin-native/backend.native/tests/framework/gh3343/uselib.swift new file mode 100644 index 00000000000..fc22748eec1 --- /dev/null +++ b/kotlin-native/backend.native/tests/framework/gh3343/uselib.swift @@ -0,0 +1,23 @@ +import Foundation +import Gh3343 + +func testGh3343() throws { + let list = KtlibKt.run() + try assertEquals(actual: list[0] as? String, expected: "42") + try assertEquals(actual: list[1] as? Int, expected: 2) + try assertEquals(actual: list[2] as? Int, expected: 117) + try assertEquals(actual: list[3] as? String, expected: "zzz") +} + +// -------- Execution of the test -------- + +class UselibTests : TestProvider { + var tests: [TestCase] = [] + + init() { + providers.append(self) + tests = [ + TestCase(name: "Gh3343", method: withAutorelease(testGh3343)), + ] + } +} \ No newline at end of file diff --git a/kotlin-native/backend.native/tests/framework/kt42397/knlibrary.kt b/kotlin-native/backend.native/tests/framework/kt42397/knlibrary.kt new file mode 100644 index 00000000000..3d4a4d25cb0 --- /dev/null +++ b/kotlin-native/backend.native/tests/framework/kt42397/knlibrary.kt @@ -0,0 +1,12 @@ +// The following 2 singletons are unused. However, since we are generating ObjC bindings for them, +// they should be marked as used, so that the code generator emits their deinitialization. + +object A { + fun foo() = 1 +} + +class B { + companion object { + fun foo() = 2 + } +} diff --git a/kotlin-native/backend.native/tests/framework/kt42397/test.swift b/kotlin-native/backend.native/tests/framework/kt42397/test.swift new file mode 100644 index 00000000000..e154ca1c476 --- /dev/null +++ b/kotlin-native/backend.native/tests/framework/kt42397/test.swift @@ -0,0 +1,39 @@ +import Kt42397 + +class Results { + var aFoo: Int32 = 0 + var bFoo: Int32 = 0 +} + +func runTestKt42397(pointer: UnsafeMutableRawPointer) -> UnsafeMutableRawPointer? { + autoreleasepool { + let results = pointer.bindMemory(to: Results.self, capacity: 1).pointee + results.aFoo = A().foo() + results.bFoo = B.Companion().foo() + } + + return nil +} + +func testKt42397() throws { + let results = Results() + let resultsPtr = UnsafeMutablePointer.allocate(capacity: 1) + resultsPtr.initialize(to: results) + var thread: pthread_t? = nil + let result = pthread_create(&thread, nil, runTestKt42397, resultsPtr) + try assertEquals(actual: result, expected: 0) + pthread_join(thread!, nil) + + try assertEquals(actual: results.aFoo, expected: 1) + try assertEquals(actual: results.bFoo, expected: 2) +} + +// -------- Execution of the test -------- + +class TestTests : SimpleTestProvider { + override init() { + super.init() + + test("Kt42397", testKt42397) + } +} diff --git a/kotlin-native/backend.native/tests/framework/main.swift b/kotlin-native/backend.native/tests/framework/main.swift new file mode 100644 index 00000000000..7db9f6948a8 --- /dev/null +++ b/kotlin-native/backend.native/tests/framework/main.swift @@ -0,0 +1,247 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import Foundation + +enum TestError : Error { + case assertFailed(String) + case failure + case testsFailed([String]) +} + +// ---------------- Assertions ---------------- + +private func throwAssertFailed(message: String, file: String, line: Int) throws -> Never { + throw TestError.assertFailed("\(file):\(line): \(message)") +} + +func assertEquals(actual: T, expected: T, + _ message: String = "Assertion failed:", + file: String = #file, line: Int = #line) throws { + if (actual != expected) { + try throwAssertFailed(message: message + " Expected value: \(expected), but got: \(actual)", + file: file, line: line) + } +} + +func assertSame(actual: AnyObject?, expected: AnyObject?, + _ message: String = "Assertion failed:", + file: String = #file, line: Int = #line) throws { + if (actual !== expected) { + try throwAssertFailed(message: message + " Expected value: \(expected), but got: \(actual)", + file: file, line: line) + } +} + +func assertEquals(actual: [T], expected: [T], + _ message: String = "Assertion failed: arrays not equal", + file: String = #file, line: Int = #line) throws { + try assertEquals(actual: actual.count, expected: expected.count, "Size differs", file: file, line: line) + try assertTrue(actual.elementsEqual(expected), "Arrays elements are not equal", file: file, line: line) +} + +func assertTrue(_ value: Bool, + _ message: String = "Assertion failed:", + file: String = #file, line: Int = #line) throws { + if (value != true) { + try throwAssertFailed(message: message + " Expected value to be TRUE, but got: \(value)", + file: file, line: line) + } +} + +func assertFalse(_ value: Bool, + _ message: String = "Assertion failed:", + file: String = #file, line: Int = #line) throws { + if (value != false) { + try throwAssertFailed(message: message + " Expected value to be FALSE, but got: \(value)", + file: file, line: line) + } +} + +func assertNil(_ value: Any?, + _ message: String = "Assertion failed:", + file: String = #file, line: Int = #line) throws { + if (value != nil) { + try throwAssertFailed(message: message + " Expected value to be nil, but got: \(value!)", + file: file, line: line) + } +} + +func fail(_ message: String = "Should not reach here", file: String = #file, line: Int = #line) throws -> Never { + try throwAssertFailed(message: message, file: file, line: line) +} + +func assertFailsWith(_ errorType: T.Type, + _ message: String = "Assertion failed:", + file: String = #file, line: Int = #line, + block: () throws -> Void) throws { + do { + try block() + } catch let error { + if error is T { return } + try throwAssertFailed(message: message + " Expected error \(errorType), got \(error)", + file: file, line: line) + } + + try throwAssertFailed(message: message + " Expected error \(errorType), but finished successfully", + file: file, line: line) +} + +func assertFailsWithKotlin(_ exceptionType: T.Type, + _ message: String = "Assertion failed:", + file: String = #file, line: Int = #line, + block: () throws -> Void) throws { + do { + try block() + } catch let error { + let kotlinException = error.kotlinException + if kotlinException is T { return } + let got = kotlinException ?? error + try throwAssertFailed(message: message + " Expected Kotlin exception \(exceptionType), got \(got)", + file: file, line: line) + } + + try throwAssertFailed(message: message + " Expected Kotlin exception \(exceptionType), but finished successfully", + file: file, line: line) +} + + +// ---------------- Utils -------------------- + +func withAutorelease( _ method: @escaping () throws -> Void) -> () throws -> Void { + return { () throws -> Void in + try autoreleasepool { try method() } + } +} + +extension Error { + var kotlinException: Any? { + get { + return (self as NSError).userInfo["KotlinException"] + } + } +} + +// ---------------- Execution ---------------- + +private final class Statistics : CustomStringConvertible { + var passed: [String] = [] + var failed: [String] = [] + + var description: String { + return """ + ---- RESULTS: + PASSED: \(passed.count) + FAILED: \(failed.count) + """ + } + + static let instance = Statistics() + + static func getInstance() -> Statistics { + return instance + } + + func start(_ name: String) { + print("---- Starting test: \(name)") + } + + func passed(_ name: String) { + print("---- PASSED test: \(name)") + passed.append(name) + } + + func failed(_ name: String, error: Error) { + print("---- FAILED test: \(name) with error: \(error)") + failed.append(name) + } +} +/** + * TestCase represents a single test + */ +struct TestCase { + let name: String + let method: () throws -> Void + + init(name: String, method: @escaping () throws -> Void) { + self.name = name + self.method = method + } + + func run() { + let stats = Statistics.getInstance() + stats.start(name) + do { + try method() + stats.passed(name) + } catch { + stats.failed(name, error: error) + } + } +} + +protocol TestProvider { + var tests: [TestCase] { get } +} + +class SimpleTestProvider : TestProvider { + var tests: [TestCase] = [] + + init() { + providers.append(self) + } + + func test(_ name: String, _ method: @escaping () throws -> Void) { + tests.append(TestCase(name: name, method: withAutorelease(method))) + } +} + +var providers: [TestProvider] = [] + +private func execute(tests: [TestCase]) { + for test in tests { + test.run() + } +} + +/** + * Entry point of the test + */ +private func main() { + // Generated method that instantiates test providers. + registerProviders() + + let stats = Statistics.getInstance() + for pr in providers { + let name = String(describing: type(of: pr)) + print("-- \(name) started") + execute(tests: pr.tests) + print("-- \(name) finished") + } + print(stats) + + let failed = stats.failed + if !failed.isEmpty { + print() + print("Tests failed:") + for testName in failed { + print(":: \(testName)") + } + abort() + } +} + +main() \ No newline at end of file diff --git a/kotlin-native/backend.native/tests/framework/multiple/framework1/first.kt b/kotlin-native/backend.native/tests/framework/multiple/framework1/first.kt new file mode 100644 index 00000000000..f4bb6db5a33 --- /dev/null +++ b/kotlin-native/backend.native/tests/framework/multiple/framework1/first.kt @@ -0,0 +1,31 @@ +/* + * Copyright 2010-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +@file:Suppress("UNUSED") + +package multiple + +interface I1 { + fun getFortyTwo(): Int +} + +class I1Impl : I1 { + override fun getFortyTwo(): Int = 42 +} + +fun getI1() = object : I1 { + override fun getFortyTwo(): Int = 42 +} + +class C + +fun getUnit(): Unit? = Unit + +/* +// Disabled for now to avoid depending on platform libs. +fun getAnonymousObject() = object : platform.darwin.NSObject() {} +class NamedObject : platform.darwin.NSObject() +fun getNamedObject() = NamedObject() + */ \ No newline at end of file diff --git a/kotlin-native/backend.native/tests/framework/multiple/framework1/test.kt b/kotlin-native/backend.native/tests/framework/multiple/framework1/test.kt new file mode 100644 index 00000000000..c25f00f106f --- /dev/null +++ b/kotlin-native/backend.native/tests/framework/multiple/framework1/test.kt @@ -0,0 +1,10 @@ +/* + * Copyright 2010-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +@file:Suppress("UNUSED") + +package multiple + +val name = "first" \ No newline at end of file diff --git a/kotlin-native/backend.native/tests/framework/multiple/framework2/second.kt b/kotlin-native/backend.native/tests/framework/multiple/framework2/second.kt new file mode 100644 index 00000000000..485fafd6326 --- /dev/null +++ b/kotlin-native/backend.native/tests/framework/multiple/framework2/second.kt @@ -0,0 +1,29 @@ +/* + * Copyright 2010-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +@file:Suppress("UNUSED") + +package multiple + +interface I2 { + fun getFortyTwo(): Int +} + +fun getFortyTwoFrom(i2: I2): Int = i2.getFortyTwo() + +fun getI2() = object : I2 { + override fun getFortyTwo(): Int = 42 +} + +class C + +fun isUnit(obj: Any?): Boolean = (obj === Unit) + +/* +// Disabled for now to avoid depending on platform libs. +fun getAnonymousObject() = object : platform.darwin.NSObject() {} +class NamedObject : platform.darwin.NSObject() +fun getNamedObject() = NamedObject() + */ \ No newline at end of file diff --git a/kotlin-native/backend.native/tests/framework/multiple/framework2/test.kt b/kotlin-native/backend.native/tests/framework/multiple/framework2/test.kt new file mode 100644 index 00000000000..4a424e63fc4 --- /dev/null +++ b/kotlin-native/backend.native/tests/framework/multiple/framework2/test.kt @@ -0,0 +1,10 @@ +/* + * Copyright 2010-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +@file:Suppress("UNUSED") + +package multiple + +val name = "second" \ No newline at end of file diff --git a/kotlin-native/backend.native/tests/framework/multiple/multiple.swift b/kotlin-native/backend.native/tests/framework/multiple/multiple.swift new file mode 100644 index 00000000000..e97bfee64b2 --- /dev/null +++ b/kotlin-native/backend.native/tests/framework/multiple/multiple.swift @@ -0,0 +1,86 @@ +/* + * Copyright 2010-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +import First +import Second + +func testClashingNames() throws { + try assertEquals(actual: "first", expected: First.TestKt.name) + try assertEquals(actual: "second", expected: Second.TestKt.name) + + let c1 = First.C() + let c2 = Second.C() + try assertTrue(type(of: c1) == First.C.self) + try assertTrue(type(of: c2) == Second.C.self) + try assertTrue(First.C.self != Second.C.self) + try assertTrue(objc_getClass(class_getName(First.C.self)) as AnyObject === First.C.self) + try assertTrue(objc_getClass(class_getName(Second.C.self)) as AnyObject === Second.C.self) +} + +extension I1Impl : I2 {} + +func testInteraction() throws { + try assertEquals(actual: SecondKt.getFortyTwoFrom(i2: I1Impl()), expected: 42) +} + +func testIsolation1() throws { + try assertFalse(SecondKt.isUnit(obj: FirstKt.getUnit())) + + // Ensure frameworks don't share the same runtime (state): + try assertFalse(First.RuntimeState().consumeChange()) + try assertFalse(Second.RuntimeState().consumeChange()) + Second.RuntimeState().produceChange() + try assertFalse(First.RuntimeState().consumeChange()) + try assertTrue(Second.RuntimeState().consumeChange()) +} + +func testIsolation2() throws { + try assertEquals(actual: FirstKt.getI1().getFortyTwo(), expected: 42) + try assertEquals(actual: SecondKt.getI2().getFortyTwo(), expected: 42) +} + +func testIsolation3() throws { +#if false // Disabled for now to avoid depending on platform libs. + FirstKt.getAnonymousObject() + SecondKt.getAnonymousObject() + FirstKt.getNamedObject() + SecondKt.getNamedObject() +#endif +} + +// https://youtrack.jetbrains.com/issue/KT-34261 +// When First and Second are static frameworks with caches, this test fails due to bad cache isolation: +// Caches included into both frameworks have 'ktypew' globals (with same name, hidden visibility and common linkage) +// for writable part of this "unexposed stdlib class" TypeInfo. +// ld ignores hidden visibility and merges common globals, so two independent frameworks happen to share +// the same global instead of two different globals. Things go wrong at runtime then: this writable TypeInfo part +// is used to store Obj-C class for this Kotlin class. So after the first object is obtained in Swift, both TypeInfos +// have its class, and the second object is wrong then. +func testIsolation4() throws { + let obj1: Any = First.SharedKt.getUnexposedStdlibClassInstance() + try assertTrue(obj1 is First.KotlinBase) + try assertFalse(obj1 is Second.KotlinBase) + + let obj2: Any = Second.SharedKt.getUnexposedStdlibClassInstance() + try assertFalse(obj2 is First.KotlinBase) + try assertTrue(obj2 is Second.KotlinBase) +} + +class MultipleTests : TestProvider { + var tests: [TestCase] = [] + + init() { + tests = [ + TestCase(name: "TestClashingNames", method: withAutorelease(testClashingNames)), + TestCase(name: "TestInteraction", method: withAutorelease(testInteraction)), + TestCase(name: "TestIsolation1", method: withAutorelease(testIsolation1)), + TestCase(name: "TestIsolation2", method: withAutorelease(testIsolation2)), + TestCase(name: "TestIsolation3", method: withAutorelease(testIsolation3)), + TestCase(name: "TestIsolation4", method: withAutorelease(testIsolation4)), + ] + providers.append(self) + } + +} \ No newline at end of file diff --git a/kotlin-native/backend.native/tests/framework/multiple/shared/shared.kt b/kotlin-native/backend.native/tests/framework/multiple/shared/shared.kt new file mode 100644 index 00000000000..60e655680d6 --- /dev/null +++ b/kotlin-native/backend.native/tests/framework/multiple/shared/shared.kt @@ -0,0 +1,14 @@ +import kotlin.native.concurrent.Worker + +object RuntimeState { + fun produceChange() { + Worker.current.executeAfter {} + } + + fun consumeChange(): Boolean { + return Worker.current.processQueue() + } +} + +// Note: this assumes that IntRange class is not exposed by the enclosing framework. +fun getUnexposedStdlibClassInstance(): Any = 0..2 diff --git a/kotlin-native/backend.native/tests/framework/stdlib/stdlib.kt b/kotlin-native/backend.native/tests/framework/stdlib/stdlib.kt new file mode 100644 index 00000000000..65d0d297f99 --- /dev/null +++ b/kotlin-native/backend.native/tests/framework/stdlib/stdlib.kt @@ -0,0 +1,64 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +@file:Suppress("UNUSED") + +package stdlib + +fun isEmpty(map: Map) = map.isEmpty() + +fun getKeysAsSet(map: Map) = map.keys +fun getKeysAsList(map: Map) = map.keys.toList() + +fun toMutableMap(map: HashMap) = map.toMutableMap() + +fun getFirstElement(collection: Collection) = collection.first() + +class GenericExtensionClass> (private val holder: T?) { + fun getFirstKey(): K? = holder?.entries?.first()?.key + + fun getFirstValue() : V? { + holder?.entries?.forEach { e -> println("KEY: ${e.key} VALUE: ${e.value}") } + return holder?.entries?.first()?.value + } +} + +fun createPair(): + Pair, GenericExtensionClass>> { + val l = createLinkedMap() + val g = GenericExtensionClass(l) + return Pair(l, g) +} + +fun createLinkedMap() = linkedMapOf() + +fun createTypedMutableMap() = linkedMapOf() + +fun addSomeElementsToMap(map: MutableMap) { + map.put(key = "XYZ", value = 321) + map.put(key = "TMP", value = 451) +} + +fun list(vararg elements: Any?): Any = listOf(*elements) +fun set(vararg elements: Any?): Any = setOf(*elements) +fun map(vararg keysAndValues: Any?): Any = mutableMapOf().apply { + (0 until keysAndValues.size step 2).forEach {index -> + this[keysAndValues[index]] = keysAndValues[index + 1] + } +} + +fun emptyMutableList(): Any = mutableListOf() +fun emptyMutableSet(): Any = mutableSetOf() +fun emptyMutableMap(): Any = mutableMapOf() + +data class TripleVals(val first: T, val second: T, val third: T) + +data class TripleVars(var first: T, var second: T, var third: T) { + override fun toString(): String { + return "[$first, $second, $third]" + } +} + +fun gc() = kotlin.native.internal.GC.collect() \ No newline at end of file diff --git a/kotlin-native/backend.native/tests/framework/stdlib/stdlib.swift b/kotlin-native/backend.native/tests/framework/stdlib/stdlib.swift new file mode 100644 index 00000000000..298048677cd --- /dev/null +++ b/kotlin-native/backend.native/tests/framework/stdlib/stdlib.swift @@ -0,0 +1,462 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import Foundation +import Stdlib + +extension NSEnumerator { + func remainingObjects() -> [Any?] { + var result = [Any?]() + while (true) { + if let next = self.nextObject() { + result.append(next as AnyObject as Any?) + } else { + break + } + } + return result + } +} + +class StdlibTests : TestProvider { + var tests: [TestCase] = [] + + init() { + tests = [ + TestCase(name: "TestEmptyDictionary", method: withAutorelease(testEmptyDictionary)), + TestCase(name: "TestGenericMapUsage", method: withAutorelease(testGenericMapUsage)), + TestCase(name: "TestOrderedMapStored", method: withAutorelease(testOrderedMapStored)), + TestCase(name: "TestTypedMapUsage", method: withAutorelease(testTypedMapUsage)), + TestCase(name: "TestFirstElement", method: withAutorelease(testFirstElement)), + TestCase(name: "TestAddDictionary", method: withAutorelease(testAddDictionary)), + TestCase(name: "TestList", method: withAutorelease(testList)), + TestCase(name: "TestMutableList", method: withAutorelease(testMutableList)), + TestCase(name: "TestSet", method: withAutorelease(testSet)), + TestCase(name: "TestMutableSet", method: withAutorelease(testMutableSet)), + TestCase(name: "TestMap", method: withAutorelease(testMap)), + TestCase(name: "TestMutableMap", method: withAutorelease(testMutableMap)), + TestCase(name: "TestKotlinMutableSetInit", method: withAutorelease(testKotlinMutableSetInit)), + TestCase(name: "TestKotlinMutableDictionaryInit", method: withAutorelease(testKotlinMutableDictionaryInit)), + ] + providers.append(self) + } + + /** + * Pass empty dictionary to Kotlin. + */ + func testEmptyDictionary() throws { + let immutableEmptyDict = [String: Int]() + try assertTrue(StdlibKt.isEmpty(map: immutableEmptyDict), "Empty dictionary") + let keys = StdlibKt.getKeysAsSet(map: immutableEmptyDict) + try assertTrue(keys.isEmpty, "Should have empty set") + } + + /** + * Tests usage of a map with generics. + */ + func testGenericMapUsage() throws { + let map = StdlibKt.createLinkedMap() + map[1] = "One" + map[10] = "Ten" + map[11] = "Eleven" + map["10"] = "Ten as string" + for (k, v) in map { + print("MAP: \(k) - \(v)") + } + + try assertEquals(actual: map[11] as! String, expected: "Eleven", "An element of the map for key: 11") + } + + /** + * Checks order of the underlying LinkedHashMap. + */ + func testOrderedMapStored() throws { + let pair = StdlibKt.createPair() + let map = pair.first as? NSMutableDictionary + + map?[1] = "One" + map?[10] = "Ten" + map?[11] = "Eleven" + map?["10"] = "Ten as string" + + let gen = pair.second as! GenericExtensionClass + let value: String? = gen.getFirstValue() as? String + try assertEquals(actual: value!, expected: "One", "First value of the map") + + let key: Int? = gen.getFirstKey() as? Int + try assertEquals(actual: key!, expected: 1, "First key of the map") + } + + /** + * Tests typed map created in Kotlin. + */ + func testTypedMapUsage() throws { + let map = StdlibKt.createTypedMutableMap() + map[1] = "One" + map[1.0 as Float] = "Float" + map[11] = "Eleven" + map["10"] = "Ten as string" + + try assertEquals(actual: map["10"] as! String, expected: "Ten as string", "String key") + try assertEquals(actual: map[1.0 as Float] as! String, expected: "Float", "Float key") + } + + /** + * Get first element of the collection. + */ + func testFirstElement() throws { + let m = StdlibKt.createTypedMutableMap() + m[10] = "Str" + try assertEquals(actual: StdlibKt.getFirstElement(collection: m.allKeys) as! Int, expected: 10, "First key") + + try assertEquals(actual: StdlibKt.getFirstElement(collection: StdlibKt.getKeysAsList(map: m as! Dictionary)) as! Int, + expected: 10, "First key from a list") + } + + /** + * Add element to dictionary in Kotlin + */ + func testAddDictionary() throws { + let m = [ "ABC": 10, "CDE": 12, "FGH": 3 ] + StdlibKt.addSomeElementsToMap(map: KotlinMutableDictionary(dictionary: m)) + for (k, v) in m { + print("MAP: \(k) - \(v)") + } + + var smd = KotlinMutableDictionary() + smd.setObject(333, forKey: "333" as NSString) + try assertEquals(actual: smd.object(forKey: "333" as NSString) as! Int, expected: 333, "Add element to dict") + + StdlibKt.addSomeElementsToMap(map: smd) + for (k, v) in smd { + print("MAP: \(k) - \(v)") + } + try assertEquals(actual: smd.object(forKey: "XYZ" as NSString) as! Int, expected: 321, "Get element from Kotlin") + } + + func zeroTo(_ n: Int32) -> KotlinArray { return KotlinArray(size: n) { $0 } } + + func testList() throws { + let elements = zeroTo(5) + elements.set(index: 1, value: nil) + let list = StdlibKt.list(elements: elements) as! NSArray + try assertEquals(actual: list.object(at: 2) as! NSNumber, expected: NSNumber(value: 2)) + try assertEquals(actual: list.object(at: 1) as! NSNull, expected: NSNull()) + try assertEquals(actual: list.count, expected: 5) + } + + func testMutableList() throws { + let kotlinList = StdlibKt.emptyMutableList() as! NSMutableArray + let nsList = NSMutableArray() + + func apply(op: (NSMutableArray)->T) throws { + let actual = op(kotlinList) + let expected = op(nsList) + try assertEquals(actual: actual, expected: expected) + try assertEquals(actual: kotlinList, expected: nsList) + try assertEquals(actual: kotlinList.hash, expected: nsList.hash) + } + + func applyVoid(op: (NSMutableArray)->Void) throws { + op(kotlinList) + op(nsList) + try assertEquals(actual: kotlinList, expected: nsList) + try assertEquals(actual: kotlinList.hash, expected: nsList.hash) + } + + try apply { $0.count } + try applyVoid { $0.insert(0, at: 0) } + try applyVoid { $0.insert(1, at: 0) } + try applyVoid { $0.insert(2, at: 1) } + try applyVoid { $0.removeObject(at: 0) } + try applyVoid { $0.add("foo") } + try applyVoid { $0.removeLastObject() } + try applyVoid { $0.replaceObject(at: 0, with: "bar") } + let NULL: Any? = nil + try applyVoid { $0.add(NULL as Any) } + try applyVoid { $0.insert(NULL as Any, at: 2) } + try applyVoid { $0.replaceObject(at: 1, with: NULL as Any) } + try apply { $0.count } + } + + func testMutableSet() throws { + let kotlinSet = StdlibKt.emptyMutableSet() as! NSMutableSet + let nsSet = NSMutableSet() + + func apply(op: (NSMutableSet)->T) throws { + let actual = op(kotlinSet) + let expected = op(nsSet) + try assertEquals(actual: actual, expected: expected) + try assertEquals(actual: kotlinSet, expected: nsSet) + try assertEquals(actual: kotlinSet.hash, expected: nsSet.hash) + } + + func applyVoid(op: (NSMutableSet)->Void) throws { + op(kotlinSet) + op(nsSet) + try assertEquals(actual: kotlinSet, expected: nsSet) + try assertEquals(actual: kotlinSet.hash, expected: nsSet.hash) + } + + try apply { $0.count } + try applyVoid { $0.add("foo") } + try applyVoid { $0.add("bar") } + try applyVoid { $0.remove("baz") } + try applyVoid { $0.add("baz") } + try applyVoid { $0.add(TripleVals(first: 1, second: 2, third: 3)) } + try apply { $0.member(TripleVals(first: 1, second: 2, third: 3)) as! TripleVals } + try apply { $0.member(42) == nil } + try applyVoid { $0.remove(TripleVals(first: 1, second: 2, third: 3)) } + + let NULL0: Any? = nil + let NULL = NULL0 as Any + + try applyVoid { $0.add(NULL) } + try apply { $0.member(NULL) == nil } + try apply { $0.member(NULL) as! NSObject } + try applyVoid { $0.remove(NULL) } + try apply { $0.member(NULL) == nil } + + try apply { NSSet(array: $0.objectEnumerator().remainingObjects()) } + + try apply { $0.count } + } + + func testMutableMap() throws { + // TODO: test KotlinMutableSet/Dictionary constructors + let kotlinMap = StdlibKt.emptyMutableMap() as! NSMutableDictionary + let nsMap = NSMutableDictionary() + + func apply(op: (NSMutableDictionary)->T) throws { + let actual = op(kotlinMap) + let expected = op(nsMap) + try assertEquals(actual: actual, expected: expected) + try assertEquals(actual: kotlinMap, expected: nsMap) + try assertEquals(actual: kotlinMap.hash, expected: nsMap.hash) + } + + func applyVoid(op: (NSMutableDictionary) throws -> Void) throws { + try op(kotlinMap) + try op(nsMap) + try assertEquals(actual: kotlinMap, expected: nsMap) + try assertEquals(actual: kotlinMap.hash, expected: nsMap.hash) + } + + try apply { $0.count } + try apply { $0.object(forKey: 42) == nil } + try applyVoid { $0.setObject(42, forKey: 42 as NSNumber) } + try applyVoid { $0.setObject(17, forKey: "foo" as NSString) } + let triple = TripleVals(first: 3, second: 2, third: 1) + try applyVoid { $0.setObject("bar", forKey: triple) } + try applyVoid { $0.removeObject(forKey: 42) } + try apply { $0.count } + try apply { $0.object(forKey: 42) == nil } + try apply { $0.object(forKey: "foo") as! NSObject } + try apply { $0.object(forKey: triple) as! NSObject } + + try apply { NSSet(array: $0.keyEnumerator().remainingObjects()) } + + let NULL0: Any? = nil + let NULL = NULL0 as Any + + try apply { $0.object(forKey: NULL) == nil } + + + try applyVoid { $0.setObject(42, forKey: NULL as! NSCopying) } + try applyVoid { $0.setObject(NULL, forKey: "baz" as NSString) } + try apply { $0.object(forKey: NULL) as! NSObject } + try apply { $0.object(forKey: "baz") as! NSObject } + + try apply { NSSet(array: $0.keyEnumerator().remainingObjects()) } + + try applyVoid { $0.removeObject(forKey: NULL) } + try applyVoid { $0.removeObject(forKey: "baz") } + + try applyVoid { $0.removeAllObjects() } + + let myKey = MyKey() + try applyVoid { $0.setObject(myKey, forKey: myKey) } + try applyVoid { + let key = $0.allKeys[0] as! MyKey + let value = $0.allValues[0] as! MyKey + try assertFalse(key === myKey) + try assertTrue(value === myKey) + } + + } + + @objc class MyKey : NSObject, NSCopying { + override var hash: Int { + return 42 + } + + override func isEqual(_ object: Any?) -> Bool { + return object is MyKey + } + + func copy(with: NSZone? = nil) -> Any { + return MyKey() + } + + } + + func testSet() throws { + let elements = KotlinArray(size: 2) { index in nil } + elements.set(index: 0, value: nil) + elements.set(index: 1, value: 42 as NSNumber) + let set = StdlibKt.set(elements: elements) as! NSSet + try assertEquals(actual: set.count, expected: 2) + try assertEquals(actual: set.member(NSNull()) as! NSNull, expected: NSNull()) + try assertEquals(actual: set.member(42) as! NSNumber, expected: NSNumber(value: 42 as Int32)) + try assertTrue(set.member(17) == nil) + try assertFalse(set.member(42) as AnyObject === NSNumber(value: 42 as Int32)) + try assertTrue(set.contains(42)) + try assertTrue(set.contains(nil as Any?)) + try assertFalse(set.contains(17)) + + try assertEquals(actual: NSSet(array: set.objectEnumerator().remainingObjects()), expected: NSSet(array: [nil, 42] as [AnyObject])) + } + + func testMap() throws { + let elements = KotlinArray(size: 6) { index in nil } + elements.set(index: 0, value: nil) + elements.set(index: 1, value: 42 as NSNumber) + elements.set(index: 2, value: "foo" as NSString) + elements.set(index: 3, value: "bar" as NSString) + elements.set(index: 4, value: 42 as NSNumber) + elements.set(index: 5, value: nil) + + let map = StdlibKt.map(keysAndValues: elements) as! NSDictionary + try assertEquals(actual: map.count, expected: 3) + + try assertEquals(actual: map.object(forKey: NSNull()) as! NSNumber, expected: NSNumber(value: 42)) + try assertEquals(actual: map.object(forKey: "foo") as! String, expected: "bar") + try assertEquals(actual: map.object(forKey: 42) as! NSNull, expected: NSNull()) + try assertTrue(map.object(forKey: "bar") == nil) + + try assertEquals(actual: NSSet(array: map.keyEnumerator().remainingObjects()), expected: NSSet(array: [nil, 42, "foo"] as [AnyObject])) + } + + func testKotlinMutableSetInit() throws { + func test( + _ set: KotlinMutableSet, + _ check: (KotlinMutableSet) throws -> Void = { _ in } + ) throws { + try assertEquals(actual: String(describing: type(of: set)), expected: "StdlibMutableSet") + try check(set) + try assertFalse(set.contains("1")) + set.add("1") + try assertTrue(set.contains("1")) + } + + try test(KotlinMutableSet()) + try test(KotlinMutableSet(capacity: 1)) + try test(KotlinMutableSet(object: "2")) { + try assertTrue($0.contains("2")) + } + + var threeAndFour = ["3", "4"] as [AnyObject] + try test(KotlinMutableSet(objects: &threeAndFour, count: 2)) { + try assertTrue($0.contains("3")) + try assertTrue($0.contains("4")) + } + + try test(KotlinMutableSet(array: ["5", "6"])) { + try assertTrue($0.contains("5")) + try assertTrue($0.contains("6")) + } + + try test(KotlinMutableSet(set: ["7", "8"])) { + try assertTrue($0.contains("7")) + try assertTrue($0.contains("8")) + } + + for flag in [false, true] { + try test(KotlinMutableSet(set: ["9", "10"], copyItems: flag)) { + try assertTrue($0.contains("9")) + try assertTrue($0.contains("10")) + } + } + + /* + TODO: doesn't work, KotlinMutableSet seems to be serialized as NSMutableSet. + if #available(macOS 10.13, *) { + let data = try! NSKeyedArchiver.archivedData( + withRootObject: KotlinMutableSet(array: ["11", "12"]), + requiringSecureCoding: false + ) + + try test(try! NSKeyedUnarchiver.unarchivedObject(ofClass: KotlinMutableSet.self, from: data)!) { + try assertTrue($0.contains("11")) + try assertTrue($0.contains("12")) + } + } + */ + + StdlibKt.gc() // To reproduce https://github.com/JetBrains/kotlin-native/issues/3259 + } + + func testKotlinMutableDictionaryInit() throws { + func test( + _ dict: KotlinMutableDictionary, + _ check: (KotlinMutableDictionary) throws -> Void = { _ in } + ) throws { + try assertEquals(actual: String(describing: type(of: dict)), expected: "StdlibMutableDictionary") + try check(dict) + try assertTrue(dict["1"] == nil) + dict["1"] = "2" + try assertTrue(dict["1"] as? NSString == "2") + } + + try test(KotlinMutableDictionary()) + try test(KotlinMutableDictionary(capacity: 4)) + + // TODO: test [initWithCoder:]. + + try test(KotlinMutableDictionary(objects: ["3", "4"], forKeys: ["4", "3"] as [NSString])) { + try assertEquals(actual: $0["3"] as? String, expected: "4") + try assertEquals(actual: $0["4"] as? String, expected: "3") + } + + var fiveAndSix = ["5", "6"] as [AnyObject] + var sixAndFive = ["6", "5"] as [NSCopying] + try test(KotlinMutableDictionary(objects: &fiveAndSix, forKeys: &sixAndFive, count: 2)) { + try assertEquals(actual: $0["5"] as? String, expected: "6") + try assertEquals(actual: $0["6"] as? String, expected: "5") + } + + try test(KotlinMutableDictionary(object: "7", forKey: "8" as NSString)) { + try assertEquals(actual: $0["8"] as? String, expected: "7") + } + + try test(KotlinMutableDictionary(dictionary: ["10" : "9"])) { + try assertEquals(actual: $0["10"] as? String, expected: "9") + } + + for flag in [false, true] { + try test(KotlinMutableDictionary(dictionary: ["12" : "11"], copyItems: flag)) { + try assertEquals(actual: $0["12"] as? String, expected: "11") + } + } + + try test(KotlinMutableDictionary(dictionaryLiteral: ("14", "13"))) { + try assertEquals(actual: $0["14"] as? String, expected: "13") + } + + StdlibKt.gc() // To reproduce https://github.com/JetBrains/kotlin-native/issues/3259 + } + +} diff --git a/kotlin-native/backend.native/tests/framework/values_generics/values.swift b/kotlin-native/backend.native/tests/framework/values_generics/values.swift new file mode 100644 index 00000000000..66f84f203a5 --- /dev/null +++ b/kotlin-native/backend.native/tests/framework/values_generics/values.swift @@ -0,0 +1,297 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import Foundation +import ValuesGenerics + +// -------- Tests -------- + +func testVararg() throws { + let ktArray = KotlinArray(size: 3, init: { (_) -> KotlinInt in return KotlinInt(int:42) }) + let arr: [Int] = ValuesKt.varargToList(args: ktArray as! KotlinArray) as! [Int] + try assertEquals(actual: arr, expected: [42, 42, 42]) +} + +func testDataClass() throws { + let f = "1" as NSString + let s = "2" as NSString + let t = "3" as NSString + + let tripleVal = TripleVals(first: f, second: s, third: t) + try assertEquals(actual: tripleVal.first, expected: f, "Data class' value") + try assertEquals(actual: tripleVal.first, expected: "1", "Data class' value literal") + try assertEquals(actual: tripleVal.component2(), expected: s, "Data class' component") + print(tripleVal) + try assertEquals(actual: String(describing: tripleVal), expected: "TripleVals(first=\(f), second=\(s), third=\(t))") + + let tripleVar = TripleVars(first: f, second: s, third: t) + try assertEquals(actual: tripleVar.first, expected: f, "Data class' value") + try assertEquals(actual: tripleVar.component2(), expected: s, "Data class' component") + print(tripleVar) + try assertEquals(actual: String(describing: tripleVar), expected: "[\(f), \(s), \(t)]") + + tripleVar.first = t + tripleVar.second = f + tripleVar.third = s + try assertEquals(actual: tripleVar.component2(), expected: f, "Data class' component") + try assertEquals(actual: String(describing: tripleVar), expected: "[\(t), \(f), \(s)]") +} + +func testInlineClasses() throws { + let ic1: Int32 = 42 + let ic1N = ValuesKt.box(ic1: 17) + let ic2 = "foo" + let ic2N = "bar" + let ic3 = TripleVals(first: KotlinInt(int:1), second: KotlinInt(int:2), third: KotlinInt(int:3)) + let ic3N = ValuesKt.box(ic3: nil) + + try assertEquals( + actual: ValuesKt.concatenateInlineClassValues(ic1: ic1, ic1N: ic1N, ic2: ic2, ic2N: ic2N, ic3: ic3, ic3N: ic3N), + expected: "42 17 foo bar TripleVals(first=1, second=2, third=3) null" + ) + + try assertEquals( + actual: ValuesKt.concatenateInlineClassValues(ic1: ic1, ic1N: nil, ic2: ic2, ic2N: nil, ic3: nil, ic3N: nil), + expected: "42 null foo null null null" + ) + + try assertEquals(actual: ValuesKt.getValue1(ic1), expected: 42) + try assertEquals(actual: ValuesKt.getValueOrNull1(ic1N) as! Int, expected: 17) + + try assertEquals(actual: ValuesKt.getValue2(ic2), expected: "foo") + try assertEquals(actual: ValuesKt.getValueOrNull2(ic2N), expected: "bar") + + try assertEquals(actual: ValuesKt.getValue3(ic3), expected: ic3) + try assertEquals(actual: ValuesKt.getValueOrNull3(ic3N), expected: nil) +} + +func testGeneric() throws { + let a = SomeGeneric(t: SomeData(num: 52)) + let asd : SomeData = a.myVal()! + try assertEquals(actual: asd.num, expected: 52) + + let nulls = GenOpen(arg: SomeData(num: 62)) + let nullssd : SomeData = nulls.arg! + try assertEquals(actual: nullssd.num, expected: 62) + + let isnull = GenOpen(arg: nil) + try assertEquals(actual: isnull.arg, expected: nil) + + let nonnulls = GenNonNull(arg: SomeData(num: 72)) + let nonnullssd : SomeData = nonnulls.arg + try assertEquals(actual: nonnullssd.num, expected: 72) + try assertEquals(actual: (Values_genericsKt.starGeneric(arg: nonnulls as! GenNonNull) as! SomeData).num, expected: 72) + + let sd = SomeData(num: 33) + let nullColl = GenCollectionsNull(arg: sd, coll: [sd]) + let nonNullColl = GenCollectionsNonNull(arg: sd, coll: [sd]) + + try assertEquals(actual: (nullColl.coll[0] as! SomeData).num, expected: 33) + let nonNullCollSd : SomeData = nonNullColl.coll[0] + try assertEquals(actual: nonNullCollSd.num, expected: 33) + try assertEquals(actual: nonNullColl.arg, expected: nonNullCollSd) + + let mixed = GenNullability(arg: sd, nArg: sd) + try assertEquals(actual: mixed.asNullable()?.num, expected: 33) + try assertEquals(actual: mixed.pAsNullable?.num, expected: 33) + let mixedSd : SomeData? = mixed.pAsNullable + try assertEquals(actual: mixedSd, expected: mixed.nArg) +} + +// Swift ignores the variance and lets you force-cast to whatever you need, for better or worse. +// This would *not* work with direct Swift interop. +func testGenericVariance() throws { + let sd = SomeData(num: 22) + + let variOut = GenVarOut(arg: sd) + let variOutAny : GenVarOut = variOut as! GenVarOut + let variOutOther : GenVarOut = variOut as! GenVarOut + + let variOutCheck = "variOut: \(variOut.arg.asString()), variOutAny: \(variOutAny.arg.asString()), variOutOther: \(variOutOther.arg.asString())" + try assertEquals(actual: variOutCheck, expected: "variOut: 22, variOutAny: 22, variOutOther: 22") + + let variIn = GenVarIn(tArg: sd) + let variInAny : GenVarIn = variIn as! GenVarIn + let variInOther : GenVarIn = variIn as! GenVarIn + + let varInCheck = "variIn: \(variIn.valString()), variInAny: \(variInAny.valString()), variInOther: \(variInOther.valString())" + try assertEquals(actual: varInCheck, expected: "variIn: SomeData(num=22), variInAny: SomeData(num=22), variInOther: SomeData(num=22)") + + let variCoType:GenVarOut = Values_genericsKt.variCoType() + try assertEquals(actual: "890", expected: variCoType.arg.asString()) + + let variContraType:GenVarIn = Values_genericsKt.variContraType() + try assertEquals(actual: "SomeData(num=1890)", expected: variContraType.valString()) +} + +// Swift should completely ignore this, as should objc. Really verifying that the header generator +// deals with this +func testGenericUseSiteVariance() throws { + let sd = SomeData(num: 22) + + let varUse = GenVarUse(arg: sd) + let varUseArg = GenVarUse(arg: sd) + + varUse.varUse(a: varUseArg, b: GenVarUse(arg: sd) as! GenVarUse) +} + +func testGenericInterface() throws { + let a: NoGeneric = SomeGeneric(t: SomeData(num: 52)) + try assertEquals(actual: (a.myVal() as! SomeData).num, expected: 52) +} + +func testGenericInheritance() throws { + let ge = GenEx(myT:SomeOtherData(str:"Hello"), baseT:SomeData(num: 11)) + let geT : SomeData = ge.t + try assertEquals(actual: geT.num, expected: 11) + let gemyT : SomeOtherData = ge.myT + try assertEquals(actual: gemyT.str, expected: "Hello") + let geBase = ge as GenBase + let geBaseT : SomeData = geBase.t + try assertEquals(actual: geBaseT.num, expected: 11) + + //Similar to above but param names don't match and will dupe property definitions on child class + //Functional, but should be fixed + let ge2 = GenEx2(myT:SomeOtherData(str:"Hello2"), baseT:SomeData(num: 22)) + let ge2Val : SomeData = ge2.t + let ge2SODVal : SomeOtherData = ge2.myT + let ge2base : GenBase = ge2 as GenBase + let ge2BaseVal : SomeData = ge2base.t + try assertEquals(actual: ge2Val, expected: ge2BaseVal) + + let geAny = GenExAny(myT:SomeOtherData(str:"Hello"), baseT:SomeData(num: 131)) + try assertEquals(actual: (geAny.t as! SomeData).num, expected: 131) + let geBaseAny = geAny as! GenBase + let geBaseAnyT : SomeData = geBaseAny.t + try assertEquals(actual: geBaseAnyT.num, expected: 131) +} + +func testGenericInnerClass() throws { + + let nestedClass = GenOuterGenNested(b: SomeData(num: 543)) + let nestedClassB : SomeData = nestedClass.b + try assertEquals(actual: nestedClassB.num, expected: 543) + + let innerClass = GenOuterGenInner(GenOuter(a: SomeOtherData(str: "ggg")), c: SomeData(num: 66), aInner: SomeOtherData(str: "ttt")) + let innerClassC : SomeData = innerClass.c + try assertEquals(actual: innerClassC.num, expected: 66) + let outerFun : SomeOtherData = innerClass.outerFun() + let outerVal : SomeOtherData = innerClass.outerVal + try assertEquals(actual: outerFun, expected: outerVal) + try assertEquals(actual: outerFun.str, expected: "ggg") + + Values_genericsKt.genInnerFunc(obj: innerClass) + Values_genericsKt.genInnerFuncAny(obj: innerClass as! GenOuterGenInner) + + let innerReturned : GenOuterGenInner = Values_genericsKt.genInnerCreate() + let innerReturnedInner : SomeOtherData = innerReturned.c + try assertEquals(actual: innerReturnedInner.str, expected: "ppp") + + let nestedClassSame = GenOuterSameGenNestedSame(a: SomeData(num: 545)) + let nestedClassSameA : SomeData = nestedClassSame.a + try assertEquals(actual: nestedClassSameA.num, expected: 545) + + let nested = GenOuterSameNestedNoGeneric() + + let innerClassSame = GenOuterSameGenInnerSame(GenOuterSame(a: SomeData(num: 44)), a: SomeOtherData(str: "rrr")) + let innerClassSameA : SomeOtherData = innerClassSame.a + try assertEquals(actual: innerClassSame.a.str, expected: "rrr") + + let gob : GenOuterBlankGenInner = GenOuterBlankGenInner(GenOuterBlank(sd: SomeData(num: 321)), arg: SomeOtherData(str: "aaa")) + let gob2 : GenOuterBlank2GenInner = GenOuterBlank2GenInner(GenOuterBlank2(oarg: SomeOtherData(str: "ooo")), arg: SomeOtherData(str: "bbb")) + + let gobsod : SomeOtherData = gob.arg! + try assertEquals(actual: gobsod.str, expected: "aaa") + + let gob2arg : SomeOtherData = gob2.arg! + let gob2out : SomeOtherData = gob2.fromOuter()! + + try assertEquals(actual: gob2arg.str, expected: "bbb") + try assertEquals(actual: gob2out.str, expected: "ooo") + + let inarg = GenOuterDeepGenShallowInner(GenOuterDeep(oarg: SomeOtherData(str: "fff"))) + let godeep : GenOuterDeepGenShallowInnerGenDeepInner = GenOuterDeepGenShallowInnerGenDeepInner(inarg) + let deepval : SomeOtherData = godeep.o()! + try assertEquals(actual: deepval.str, expected: "fff") + + let deep2 = GenOuterDeep2() + let deep2Before = GenOuterDeep2.Before(deep2) + let deep2After = GenOuterDeep2.After(deep2) + let deep2soi = GenOuterDeep2.GenShallowOuterInner(deep2) + let deep2si = GenOuterDeep2GenShallowOuterInnerGenShallowInner(deep2soi) + let deep2i = GenOuterDeep2GenShallowOuterInnerGenShallowInnerGenDeepInner(deep2si) + + let gbb : GenBothBlank.GenInner = GenBothBlank.GenInner(GenBothBlank(a: SomeData(num: 22)), b: SomeOtherData(str: "ttt")) + try assertEquals(actual: gbb.b.str, expected: "ttt") +} + +func testGenericClashing() throws { + let gcId = GenClashId(arg: SomeData(num: 22), arg2: SomeOtherData(str: "lll")) + try assertEquals(actual: gcId.x() as! NSString, expected: "Foo") + let gcIdArg : SomeData = gcId.arg + try assertEquals(actual: gcIdArg.num, expected: 22) + let gcIdArg2 : SomeOtherData = gcId.arg2 + try assertEquals(actual: gcIdArg2.str, expected: "lll") + + let gcClass = GenClashClass(arg: SomeData(num: 432), arg2: SomeOtherData(str: "lll"), arg3: "Bar") + try assertEquals(actual: gcClass.int(), expected: 55) + try assertEquals(actual: gcClass.sd().num, expected: 88) + try assertEquals(actual: gcClass.list()[1].num, expected: 22) + try assertEquals(actual: gcClass.arg.num, expected: 432) + try assertEquals(actual: gcClass.clash().str, expected: "aaa") + try assertEquals(actual: gcClass.arg2.str, expected: "lll") + try assertEquals(actual: gcClass.arg3, expected: "Bar") + + //GenClashNames uses type parameter names that force the Objc class name itself to be mangled. Swift keeps names however + let clashNames = GenClashNames() + try assertEquals(actual: clashNames.foo().str, expected: "nnn") + try assertEquals(actual: clashNames.bar().str, expected: "qqq") + try assertTrue(clashNames.baz(arg: ClashnameParam(str: "meh")), "ClashnameParam issue") + + let clashNamesEx = GenClashEx() + + let geClash = GenExClash(myT:SomeOtherData(str:"Hello")) + try assertEquals(actual: geClash.t.num, expected: 55) + try assertEquals(actual: geClash.myT.str, expected: "Hello") +} + +func testGenericExtensions() throws { + let gnn = GenNonNull(arg: SomeData(num: 432)) + try assertEquals(actual: (gnn.foo() as! SomeData).num, expected: 432) +} + +// -------- Execution of the test -------- + +class ValuesTests : TestProvider { + var tests: [TestCase] = [] + + init() { + providers.append(self) + tests = [ + TestCase(name: "TestVararg", method: withAutorelease(testVararg)), + TestCase(name: "TestDataClass", method: withAutorelease(testDataClass)), + TestCase(name: "TestInlineClasses", method: withAutorelease(testInlineClasses)), + TestCase(name: "TestGeneric", method: withAutorelease(testGeneric)), + TestCase(name: "TestGenericVariance", method: withAutorelease(testGenericVariance)), + TestCase(name: "TestGenericUseSiteVariance", method: withAutorelease(testGenericUseSiteVariance)), + TestCase(name: "TestGenericInheritance", method: withAutorelease(testGenericInheritance)), + TestCase(name: "TestGenericInterface", method: withAutorelease(testGenericInterface)), + TestCase(name: "TestGenericInnerClass", method: withAutorelease(testGenericInnerClass)), + TestCase(name: "TestGenericClashing", method: withAutorelease(testGenericClashing)), + TestCase(name: "TestGenericExtensions", method: withAutorelease(testGenericExtensions)), + ] + } +} diff --git a/kotlin-native/backend.native/tests/framework/values_generics/values_generics.kt b/kotlin-native/backend.native/tests/framework/values_generics/values_generics.kt new file mode 100644 index 00000000000..58c0f1be3a3 --- /dev/null +++ b/kotlin-native/backend.native/tests/framework/values_generics/values_generics.kt @@ -0,0 +1,196 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +// All classes and methods should be used in tests +@file:Suppress("UNUSED") + +package conversions + +import kotlin.native.concurrent.isFrozen +import kotlin.properties.ReadWriteProperty +import kotlin.reflect.KProperty + +// Generics +abstract class BaseData{ + abstract fun asString():String +} + +data class SomeData(val num:Int = 42):BaseData() { + override fun asString(): String = num.toString() +} + +data class SomeOtherData(val str:String):BaseData() { + fun anotherFun(){} + override fun asString(): String = str +} + +interface NoGeneric { + fun myVal():T +} + +data class SomeGeneric(val t:T):NoGeneric{ + override fun myVal(): T = t +} + +class GenOpen(val arg:T) +class GenNonNull(val arg:T) + +class GenCollectionsNull(val arg: T, val coll: List) +class GenCollectionsNonNull(val arg: T, val coll: List) + +//Force @class declaration at top of file with Objc variance +object ForceUse { + val gvo = GenVarOut(SomeData()) +} + +class GenVarOut(val arg:T) + +class GenVarIn(tArg:T){ + private val t = tArg + + fun valString():String = t.toString() + + fun goIn(t:T){ + //Just taking a val + } +} + +class GenVarUse(val arg:T){ + fun varUse(a:GenVarUse, b:GenVarUse){ + //Should complile but do nothing + } +} + +fun variCoType():GenVarOut{ + val compileVarOutSD:GenVarOut = GenVarOut(SomeData(890)) + val compileVarOut:GenVarOut = compileVarOutSD + return compileVarOut +} + +fun variContraType():GenVarIn{ + val compileVariIn:GenVarIn = GenVarIn(SomeData(1890)) + val compileVariInSD:GenVarIn = compileVariIn + return compileVariInSD +} + +open class GenBase(val t:T) +class GenEx(val myT:T, baseT:TT):GenBase(baseT) +class GenEx2(val myT:S, baseT:T):GenBase(baseT) + +class GenExAny(val myT:T, baseT:TT):GenBase(baseT) + +class GenNullability(val arg: T, val nArg:T?){ + fun asNullable():T? = arg + val pAsNullable:T? + get() = arg +} + +fun starGeneric(arg: GenNonNull<*>):Any{ + return arg.arg +} + +class GenOuter(val a:A){ + class GenNested(val b:B) + inner class GenInner(val c:C, val aInner:A) { + fun outerFun(): A = a + val outerVal: A = a + } +} + +class GenOuterSame(val a:A){ + class GenNestedSame(val a:A) + inner class GenInnerSame(val a:A) + class NestedNoGeneric() +} + +fun genInnerFunc(obj: GenOuter.GenInner) {} +fun genInnerFuncAny(obj: GenOuter.GenInner){} + +fun genInnerCreate(): GenOuter.GenInner = + GenOuter(SomeData(33)).GenInner(SomeOtherData("ppp"), SomeData(77)) + +class GenOuterBlank(val sd: SomeData) { + inner class GenInner(val arg: T){ + fun fromOuter(): SomeData = sd + } +} + +class GenOuterBlank2(val oarg: T) { + inner class GenInner(val arg: T){ + fun fromOuter(): T = oarg + } +} + +class GenOuterDeep(val oarg: T) { + inner class GenShallowInner(){ + inner class GenDeepInner(){ + fun o(): T = oarg + } + } +} + +class GenOuterDeep2() { + inner class Before() + inner class GenShallowOuterInner() { + inner class GenShallowInner() { + inner class GenDeepInner() + } + } + inner class After() +} + +class GenBothBlank(val a: SomeData) { + inner class GenInner(val b: SomeOtherData) +} + +class GenClashId(val arg: id, val arg2: id_){ + fun x(): Any = "Foo" +} + +class GenClashClass( + val arg: ValuesGenericsClashingData, val arg2: NSArray, val arg3: int32_t +) { + fun sd(): SomeData = SomeData(88) + fun list(): List = listOf(SomeData(11), SomeData(22)) + fun int(): Int = 55 + fun clash(): ClashingData = ClashingData("aaa") +} + +data class ClashingData(val str: String) + +class GenClashNames() { + fun foo() = ClashnameClass("nnn") + + fun bar(): ClashnameProtocol = object : ClashnameProtocol{ + override val str = "qqq" + } + + fun baz(arg: ClashnameParam): Boolean { + return arg.str == "meh" + } +} + +class GenClashEx: ClashnameClass("ttt"){ + fun foo() = ClashnameClass("nnn") +} + +open class ClashnameClass(val str: String) +interface ClashnameProtocol { + val str: String +} +data class ClashnameParam(val str: String) + +class GenExClash(val myT:ValuesGenericsSomeData):GenBase(SomeData(55)) + +class SelfRef : GenBasic() + +open class GenBasic() + +//Extensions +fun GenNonNull.foo(): T = arg + +class StarProjectionInfiniteRecursion> + +fun testStarProjectionInfiniteRecursion(x: StarProjectionInfiniteRecursion<*>) {} \ No newline at end of file diff --git a/kotlin-native/backend.native/tests/harmony_regex/AllCodePointsTest.kt b/kotlin-native/backend.native/tests/harmony_regex/AllCodePointsTest.kt new file mode 100644 index 00000000000..532d2958f12 --- /dev/null +++ b/kotlin-native/backend.native/tests/harmony_regex/AllCodePointsTest.kt @@ -0,0 +1,65 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package test.text.harmony_regex + +import kotlin.text.* +import kotlin.test.* + +class AllCodePointsTest { + + fun assertTrue(msg: String, value: Boolean) = assertTrue(value, msg) + fun assertFalse(msg: String, value: Boolean) = assertFalse(value, msg) + + fun codePointToString(codePoint: Int): String { + val charArray = Char.toChars(codePoint) + return String(charArray, 0, charArray.size) + } + + // TODO: Here is a performance problem: an execution of this test requires much more time than it in Kotlin/JVM. + @Test fun test() { + // Regression for HARMONY-3145 + var p = Regex("(\\p{all})+") + var res = true + var cnt = 0 + var s: String + for (i in 0..1114111) { + s = codePointToString(i) + if (!s.matches(p)) { + cnt++ + res = false + } + } + assertTrue(res) + assertEquals(0, cnt) + + p = Regex("(\\P{all})+") + res = true + cnt = 0 + + for (i in 0..1114111) { + s = codePointToString(i) + if (!s.matches(p)) { + cnt++ + res = false + } + } + + assertFalse(res) + assertEquals(0x110000, cnt) + } +} \ No newline at end of file diff --git a/kotlin-native/backend.native/tests/harmony_regex/MatchResultTest.kt b/kotlin-native/backend.native/tests/harmony_regex/MatchResultTest.kt new file mode 100644 index 00000000000..46b070a8c97 --- /dev/null +++ b/kotlin-native/backend.native/tests/harmony_regex/MatchResultTest.kt @@ -0,0 +1,479 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package test.text.harmony_regex + +import kotlin.text.* +import kotlin.test.* + +class MatchResultTest { + + fun assertTrue(msg: String, value: Boolean) = assertTrue(value, msg) + fun assertFalse(msg: String, value: Boolean) = assertFalse(value, msg) + + internal var testPatterns = arrayOf("(a|b)*abb", "(1*2*3*4*)*567", "(a|b|c|d)*aab", "(1|2|3|4|5|6|7|8|9|0)(1|2|3|4|5|6|7|8|9|0)*", "(abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ)*", "(a|b)*(a|b)*A(a|b)*lice.*", "(a|b|c|d|e|f|g|h|i|j|k|l|m|n|o|p|q|r|s|t|u|v|w|x|y|z)(a|b|c|d|e|f|g|h|" + "i|j|k|l|m|n|o|p|q|r|s|t|u|v|w|x|y|z)*(1|2|3|4|5|6|7|8|9|0)*|while|for|struct|if|do") + + internal var groupPatterns = arrayOf("(a|b)*aabb", "((a)|b)*aabb", "((a|b)*)a(abb)", "(((a)|(b))*)aabb", "(((a)|(b))*)aa(b)b", "(((a)|(b))*)a(a(b)b)") + + @Test fun testReplaceAll() { + val input = "aabfooaabfooabfoob" + val pattern = "a*b" + val regex = Regex(pattern) + + assertEquals("-foo-foo-foo-", regex.replace(input, "-")) + } + + @Test fun testReplaceFirst() { + val input = "zzzdogzzzdogzzz" + val pattern = "dog" + val regex = Regex(pattern) + + assertEquals("zzzcatzzzdogzzz", regex.replaceFirst(input, "cat")) + } + + /* + * Class under test for String group(int) + */ + @Test fun testGroupint() { + val positiveTestString = "ababababbaaabb" + + // test IndexOutOfBoundsException + // // + for (i in groupPatterns.indices) { + val regex = Regex(groupPatterns[i]) + val result = regex.matchEntire(positiveTestString)!! + try { + // groupPattern equals to number of groups + // of the specified pattern + // // + result.groups[i + 2] + fail("IndexOutBoundsException expected") + result.groups[i + 100] + fail("IndexOutBoundsException expected") + result.groups[-1] + fail("IndexOutBoundsException expected") + result.groups[-100] + fail("IndexOutBoundsException expected") + } catch (e: IndexOutOfBoundsException) { + } + } + + val groupResults = arrayOf( + arrayOf("a"), + arrayOf("a", "a"), + arrayOf("ababababba", "a", "abb"), + arrayOf("ababababba", "a", "a", "b"), + arrayOf("ababababba", "a", "a", "b", "b"), + arrayOf("ababababba", "a", "a", "b", "abb", "b") + ) + + for (i in groupPatterns.indices) { + val regex = Regex(groupPatterns[i]) + val result = regex.matchEntire(positiveTestString)!! + for (j in 0..groupResults[i].size - 1) { + assertEquals(groupResults[i][j], result.groupValues[j + 1], "i: $i j: $j") + } + } + + } + + @Test fun testGroup() { + val positiveTestString = "ababababbaaabb" + val negativeTestString = "gjhfgdsjfhgcbv" + for (element in groupPatterns) { + val regex = Regex(element) + val result = regex.matchEntire(positiveTestString)!! + assertEquals(positiveTestString, result.groupValues[0]) + assertEquals(positiveTestString, result.groups[0]!!.value) + assertEquals(0 until positiveTestString.length, result.groups[0]!!.range) + } + + for (element in groupPatterns) { + val regex = Regex(element) + val result = regex.matchEntire(negativeTestString) + assertEquals(result, null) + } + } + + @Test fun testGroupPossessive() { + val regex = Regex("((a)|(b))++c") + assertEquals("a", regex.matchEntire("aac")!!.groupValues[1]) + } + + @Test fun testMatchesMisc() { + val posSeq = arrayOf( + arrayOf("abb", "ababb", "abababbababb", "abababbababbabababbbbbabb"), + arrayOf("213567", "12324567", "1234567", "213213567", "21312312312567", "444444567"), + arrayOf("abcdaab", "aab", "abaab", "cdaab", "acbdadcbaab"), + arrayOf("213234567", "3458", "0987654", "7689546432", "0398576", "98432", "5"), + arrayOf("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ", + "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ" + "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"), + arrayOf("ababbaAabababblice", "ababbaAliceababab", "ababbAabliceaaa", "abbbAbbbliceaaa", "Alice"), + arrayOf("a123", "bnxnvgds156", "for", "while", "if", "struct")) + + for (i in testPatterns.indices) { + val regex = Regex(testPatterns[i]) + for (j in 0..posSeq[i].size - 1) { + assertTrue("Incorrect match: " + testPatterns[i] + " vs " + posSeq[i][j], regex.matches(posSeq[i][j])) + } + } + } + + @Test fun testMatchesQuantifiers() { + val testPatternsSingles = arrayOf("a{5}", "a{2,4}", "a{3,}") + val testPatternsMultiple = arrayOf("((a)|(b)){1,2}abb", "((a)|(b)){2,4}", "((a)|(b)){3,}") + + val stringSingles = arrayOf( + arrayOf("aaaaa", "aaa"), + arrayOf("aa", "a", "aaa", "aaaaaa", "aaaa", "aaaaa"), + arrayOf("aaa", "a", "aaaa", "aa") + ) + + val stringMultiples = arrayOf( + arrayOf("ababb", "aba"), + arrayOf("ab", "b", "bab", "ababa", "abba", "abababbb"), + arrayOf("aba", "b", "abaa", "ba") + ) + + for (i in testPatternsSingles.indices) { + val regex = Regex(testPatternsSingles[i]) + for (j in 0..stringSingles.size / 2 - 1) { + assertTrue("Match expected, but failed: " + regex.pattern + " : " + stringSingles[i][j], + regex.matches(stringSingles[i][j * 2]) + ) + assertFalse("Match failure expected, but match succeed: " + regex.pattern + " : " + stringSingles[i][j * 2 + 1], + regex.matches(stringSingles[i][j * 2 + 1]) + ) + } + } + + for (i in testPatternsMultiple.indices) { + val regex = Regex(testPatternsMultiple[i]) + for (j in 0..stringMultiples.size / 2 - 1) { + assertTrue("Match expected, but failed: " + regex.pattern + " : " + stringMultiples[i][j], + regex.matches(stringMultiples[i][j * 2]) + ) + assertFalse("Match failure expected, but match succeed: " + regex.pattern + " : " + stringMultiples[i][j * 2 + 1], + regex.matches(stringMultiples[i][j * 2 + 1]) + ) + } + } + + // Test for the optimized '.+' quantifier node. + assertFalse(Regex(".+abc").matches("abc")) + assertFalse(Regex(".+\nabc", RegexOption.DOT_MATCHES_ALL).matches("\nabc")) + assertFalse(Regex(".+").matches("")) + assertFalse(Regex(".+\n", RegexOption.DOT_MATCHES_ALL).matches("\n")) + assertFalse(Regex(".+abc").containsMatchIn("abc")) + assertFalse(Regex(".+\nabc", RegexOption.DOT_MATCHES_ALL).containsMatchIn("\nabc")) + assertFalse(Regex(".+").containsMatchIn("")) + assertFalse(Regex(".+\n", RegexOption.DOT_MATCHES_ALL).containsMatchIn("\n")) + + assertTrue(Regex(".+abc").matches("aabc")) + assertTrue(Regex(".+\nabc", RegexOption.DOT_MATCHES_ALL).matches("a\nabc")) + assertTrue(Regex(".+").matches("a")) + assertTrue(Regex(".+\n", RegexOption.DOT_MATCHES_ALL).matches("a\n")) + assertTrue(Regex(".+abc").containsMatchIn("aabc")) + assertTrue(Regex(".+\nabc", RegexOption.DOT_MATCHES_ALL).containsMatchIn("a\nabc")) + assertTrue(Regex(".+").containsMatchIn("a")) + assertTrue(Regex(".+\n", RegexOption.DOT_MATCHES_ALL).containsMatchIn("a\n")) + } + + @Test fun testQuantVsGroup() { + val patternString = "(d{1,3})((a|c)*)(d{1,3})((a|c)*)(d{1,3})" + val testString = "dacaacaacaaddaaacaacaaddd" + + val regex = Regex(patternString) + + val result = regex.matchEntire(testString)!! + assertEquals("dacaacaacaaddaaacaacaaddd", result.groupValues[0]) + assertEquals("d", result.groupValues[1]) + assertEquals("acaacaacaa", result.groupValues[2]) + assertEquals("dd", result.groupValues[4]) + assertEquals("aaacaacaa", result.groupValues[5]) + assertEquals("ddd", result.groupValues[7]) + } + + /* + * Class under test for boolean find() + */ + @Test fun testFind() { + var testPattern = "(abb)" + var testString = "cccabbabbabbabbabb" + val regex = Regex(testPattern) + var result = regex.find(testString) + var start = 3 + var end = 6 + while (result != null) { + assertEquals(start, result.groups[1]!!.range.start) + assertEquals(end, result.groups[1]!!.range.endInclusive + 1) + + start = end + end += 3 + result = result.next() + } + + testPattern = "(\\d{1,3})" + testString = "aaaa123456789045" + + val regex2 = Regex(testPattern) + var result2 = regex2.find(testString) + start = 4 + val length = 3 + while (result2 != null) { + assertEquals(testString.substring(start, start + length), result2.groupValues[1]) + start += length + result2 = result2.next() + } + } + + @Test fun testSEOLsymbols() { + val regex = Regex("^a\\(bb\\[$") + assertTrue(regex.matches("a(bb[")) + } + + @Test fun testGroupCount() { + for (i in groupPatterns.indices) { + val regex = Regex(groupPatterns[i]) + val result = regex.matchEntire("ababababbaaabb")!! + assertEquals(i + 1, result.groups.size - 1) + } + } + + @Test fun testReluctantQuantifiers() { + val regex = Regex("(ab*)*b") + val result = regex.matchEntire("abbbb") + if (result != null) { + assertEquals("abbb", result.groupValues[1]) + } else { + fail("Match expected: (ab*)*b vs abbbb") + } + } + + @Test fun testEnhancedFind() { + val input = "foob" + val pattern = "a*b" + val regex = Regex(pattern) + val result = regex.find(input)!! + assertEquals("b", result.groupValues[0]) + } + + @Test fun testPosCompositeGroup() { + val posExamples = arrayOf("aabbcc", "aacc", "bbaabbcc") + val negExamples = arrayOf("aabb", "bb", "bbaabb") + val posPat = Regex("(aa|bb){1,3}+cc") + val negPat = Regex("(aa|bb){1,3}+bb") + + for (element in posExamples) { + assertTrue(posPat.matches(element)) + } + + for (element in negExamples) { + assertFalse(negPat.matches(element)) + } + + assertTrue(Regex("(aa|bb){1,3}+bb").matches("aabbaabb")) + } + + @Test fun testPosAltGroup() { + val posExamples = arrayOf("aacc", "bbcc", "cc") + val negExamples = arrayOf("bb", "aa") + val posPat = Regex("(aa|bb)?+cc") + val negPat = Regex("(aa|bb)?+bb") + + for (element in posExamples) { + assertTrue(posPat.toString() + " vs: " + element, posPat.matches(element)) + } + + for (element in negExamples) { + assertFalse(negPat.matches(element)) + } + + assertTrue(Regex("(aa|bb)?+bb").matches("aabb")) + } + + @Test fun testRelCompGroup() { + var res = "" + for (i in 0..3) { + val regex = Regex("((aa|bb){$i,3}?).*cc") + val result = regex.matchEntire("aaaaaacc") + assertTrue(regex.toString() + " vs: " + "aaaaaacc", result != null) + assertEquals(res, result!!.groupValues[1]) + res += "aa" + } + } + + @Test fun testRelAltGroup() { + var regex = Regex("((aa|bb)??).*cc") + var result = regex.matchEntire("aacc") + assertTrue(regex.toString() + " vs: " + "aacc", result != null) + assertEquals("", result!!.groupValues[1]) + + regex = Regex("((aa|bb)??)cc") + result = regex.matchEntire("aacc") + assertTrue(regex.toString() + " vs: " + "aacc", result != null) + assertEquals("aa", result!!.groupValues[1]) + } + + @Test fun testIgnoreCase() { + var regex = Regex("(aa|bb)*", RegexOption.IGNORE_CASE) + assertTrue(regex.matches("aAbb")) + + regex = Regex("(a|b|c|d|e)*", RegexOption.IGNORE_CASE) + assertTrue(regex.matches("aAebbAEaEdebbedEccEdebbedEaedaebEbdCCdbBDcdcdADa")) + + regex = Regex("[a-e]*", RegexOption.IGNORE_CASE) + assertTrue(regex.matches("aAebbAEaEdebbedEccEdebbedEaedaebEbdCCdbBDcdcdADa")) + } + + @Test fun testQuoteReplacement() { + assertEquals("\\\\aaCC\\$1", Regex.escapeReplacement("\\aaCC$1")) + } + + @Test fun testOverFlow() { + var regex = Regex("(a*)*") + var result = regex.matchEntire("aaa") + assertTrue(result != null) + assertEquals("", result!!.groupValues[1]) + + assertTrue(Regex("(1+)\\1+").matches("11")) + assertTrue(Regex("(1+)(2*)\\2+").matches("11")) + + regex = Regex("(1+)\\1*") + result = regex.matchEntire("11") + + assertTrue(result != null) + assertEquals("11", result!!.groupValues[1]) + + regex = Regex("((1+)|(2+))(\\2+)") + result = regex.matchEntire("11") + + assertTrue(result != null) + assertEquals("1", result!!.groupValues[2]) + assertEquals("1", result.groupValues[1]) + assertEquals("1", result.groupValues[4]) + assertEquals("", result.groupValues[3]) + } + + @Test fun testUnicode() { + assertTrue(Regex("\\x61a").matches("aa")) + assertTrue(Regex("\\u0061a").matches("aa")) + assertTrue(Regex("\\0141a").matches("aa")) + assertTrue(Regex("\\0777").matches("?7")) + } + + @Test fun testUnicodeCategory() { + assertTrue(Regex("\\p{Ll}").matches("k")) // Unicode lower case + assertTrue(Regex("\\P{Ll}").matches("K")) // Unicode non-lower + // case + assertTrue(Regex("\\p{Lu}").matches("K")) // Unicode upper case + assertTrue(Regex("\\P{Lu}").matches("k")) // Unicode non-upper + // case combinations + assertTrue(Regex("[\\p{L}&&[^\\p{Lu}]]").matches("k")) + assertTrue(Regex("[\\p{L}&&[^\\p{Ll}]]").matches("K")) + assertFalse(Regex("[\\p{L}&&[^\\p{Lu}]]").matches("K")) + assertFalse(Regex("[\\p{L}&&[^\\p{Ll}]]").matches("k")) + + // category/character combinations + assertFalse(Regex("[\\p{L}&&[^a-z]]").matches("k")) + assertTrue(Regex("[\\p{L}&&[^a-z]]").matches("K")) + + assertTrue(Regex("[\\p{Lu}a-z]").matches("k")) + assertTrue(Regex("[a-z\\p{Lu}]").matches("k")) + + assertFalse(Regex("[\\p{Lu}a-d]").matches("k")) + assertTrue(Regex("[a-d\\p{Lu}]").matches("K")) + + assertFalse(Regex("[\\p{L}&&[^\\p{Lu}&&[^G]]]").matches("K")) + + } + + @Test fun testSplitEmpty() { + + val regex = Regex("") + val s = regex.split("", 0) + + assertEquals(2, s.size) + assertEquals("", s[0]) + assertEquals("", s[1]) + } + + @Test fun testFindDollar() { + val regex = Regex("a$") + val result = regex.find("a\n") + assertTrue(result != null) + assertEquals("a", result!!.groupValues[0]) + } + + /* + * Regression test for HARMONY-674 + */ + @Test fun testPatternMatcher() { + assertTrue(Regex("(?:\\d+)(?:pt)").matches("14pt")) + } + + /** + * Inspired by HARMONY-3360 + */ + @Test fun test3360() { + val str = "!\"#%&'(),-./" + val regex = Regex("\\s") + assertFalse(regex.containsMatchIn(str)) + } + + /** + * Regression test for HARMONY-3360 + */ + @Test fun testGeneralPunctuationCategory() { + val s = arrayOf(",", "!", "\"", "#", "%", "&", "'", "(", ")", "-", ".", "/") + val regexp = "\\p{P}" + + for (i in s.indices) { + val regex = Regex(regexp) + assertTrue(regex.containsMatchIn(s[i])) + } + } + + /** + * Regression test for https://github.com/JetBrains/kotlin-native/issues/2297 + */ + @Test fun test2297() { + assertTrue(Regex("^(:[0-5]?[0-9])+$").matches(":20:30")) + assertTrue(Regex("(.{1,}){2}").matches("aa")) + + assertTrue(Regex("(.+b)+").matches("0b0b")) + assertTrue(Regex("(.+?b)+").matches("0b0b")) + assertTrue(Regex("(.?b)+").matches("0b0b")) + assertTrue(Regex("(.??b)+").matches("0b0b")) + assertTrue(Regex("(.*b)+").matches("0b0b")) + assertTrue(Regex("(.*?b)+").matches("0b0b")) + assertTrue(Regex("(.{1,2}b)+").matches("0b00b")) + assertTrue(Regex("(.{1,2}?b)+").matches("0b00b")) + + assertTrue(Regex("([0]?[0]?)+").matches("0000")) + assertTrue(Regex("([0]?[0]?b)+").matches("00b00b")) + assertTrue(Regex("((b{2}){3})+").matches("bbbbbbbbbbbb")) + + assertTrue(Regex("[^a]").matches("b")) + } + + @Test fun kt28158() { + val comment = "😃😃😃😃😃😃" + val regex = Regex("(.{3,})\\1+", RegexOption.IGNORE_CASE) + assertTrue(comment.contains(regex)) + } +} \ No newline at end of file diff --git a/kotlin-native/backend.native/tests/harmony_regex/MatchResultTest2.kt b/kotlin-native/backend.native/tests/harmony_regex/MatchResultTest2.kt new file mode 100644 index 00000000000..611ed053594 --- /dev/null +++ b/kotlin-native/backend.native/tests/harmony_regex/MatchResultTest2.kt @@ -0,0 +1,117 @@ +/* Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package test.text.harmony_regex + +import kotlin.text.* +import kotlin.test.* + +class MatchResultTest2 { + + @Test fun testErrorConditions2() { + // Test match cursors in absence of a match + val regex = Regex("(foo[0-9])(bar[a-z])") + var result = regex.find("foo1barzfoo2baryfoozbar5") + + assertTrue(result != null) + assertEquals(0, result!!.range.start) + assertEquals(7, result.range.endInclusive) + assertEquals(0, result.groups[0]!!.range.start) + assertEquals(7, result.groups[0]!!.range.endInclusive) + assertEquals(0, result.groups[1]!!.range.start) + assertEquals(3, result.groups[1]!!.range.endInclusive) + assertEquals(4, result.groups[2]!!.range.start) + assertEquals(7, result.groups[2]!!.range.endInclusive) + + try { + result.groups[3] + fail("IndexOutOfBoundsException expected") + } catch (e: IndexOutOfBoundsException) { + } + + try { + result.groupValues[3] + fail("IndexOutOfBoundsException expected") + } catch (e: IndexOutOfBoundsException) { + } + + try { + result.groups[-1] + fail("IndexOutOfBoundsException expected") + } catch (e: IndexOutOfBoundsException) { + } + + try { + result.groupValues[-1] + fail("IndexOutOfBoundsException expected") + } catch (e: IndexOutOfBoundsException) { + } + + result = result.next() + assertTrue(result != null) + assertEquals(8, result!!.range.start) + assertEquals(15, result.range.endInclusive) + assertEquals(8, result.groups[0]!!.range.start) + assertEquals(15, result.groups[0]!!.range.endInclusive) + assertEquals(8, result.groups[1]!!.range.start) + assertEquals(11, result.groups[1]!!.range.endInclusive) + assertEquals(12, result.groups[2]!!.range.start) + assertEquals(15, result.groups[2]!!.range.endInclusive) + + try { + result.groups[3] + fail("IndexOutOfBoundsException expected") + } catch (e: IndexOutOfBoundsException) { + } + + try { + result.groupValues[3] + fail("IndexOutOfBoundsException expected") + } catch (e: IndexOutOfBoundsException) { + } + + try { + result.groups[-1] + fail("IndexOutOfBoundsException expected") + } catch (e: IndexOutOfBoundsException) { + } + + try { + result.groupValues[-1] + fail("IndexOutOfBoundsException expected") + } catch (e: IndexOutOfBoundsException) { + } + + result = result.next() + assertFalse(result != null) + } + + /* + * Regression test for HARMONY-997 + */ + @Test fun testReplacementBackSlash() { + val str = "replace me" + val replacedString = "me" + val substitutionString = "\\" + val regex = Regex(replacedString) + try { + regex.replace(str, substitutionString) + fail("IllegalArgumentException should be thrown") + } catch (e: IllegalArgumentException) { + } + } + +} diff --git a/kotlin-native/backend.native/tests/harmony_regex/ModeTest.kt b/kotlin-native/backend.native/tests/harmony_regex/ModeTest.kt new file mode 100644 index 00000000000..a068e0b0ee8 --- /dev/null +++ b/kotlin-native/backend.native/tests/harmony_regex/ModeTest.kt @@ -0,0 +1,117 @@ +/* Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package test.text.harmony_regex + +import kotlin.text.* +import kotlin.test.* + +class ModeTest { + + /** + * Tests Pattern compilation modes and modes triggered in pattern strings + */ + @Test fun testCase() { + var regex: Regex + var result: MatchResult? + + regex = Regex("([a-z]+)[0-9]+") + result = regex.find("cAT123#dog345") + assertNotNull(result) + assertEquals("dog", result!!.groupValues[1]) + assertNull(result.next()) + + regex = Regex("([a-z]+)[0-9]+", RegexOption.IGNORE_CASE) + result = regex.find("cAt123#doG345") + assertNotNull(result) + assertEquals("cAt", result!!.groupValues[1]) + result = result.next() + assertNotNull(result) + assertEquals("doG", result!!.groupValues[1]) + assertNull(result.next()) + + regex = Regex("(?i)([a-z]+)[0-9]+") + result = regex.find("cAt123#doG345") + assertNotNull(result) + assertEquals("cAt", result!!.groupValues[1]) + result = result.next() + assertNotNull(result) + assertEquals("doG", result!!.groupValues[1]) + assertNull(result.next()) + } + + @Test fun testMultiline() { + var regex: Regex + var result: MatchResult? + + regex = Regex("^foo") + result = regex.find("foobar") + assertNotNull(result) + assertTrue(result!!.range.start == 0 && result.range.endInclusive == 2) + assertTrue(result.groups[0]!!.range.start == 0 && result.groups[0]!!.range.endInclusive == 2) + assertNull(result.next()) + + result = regex.find("barfoo") + assertNull(result) + + regex = Regex("foo$") + result = regex.find("foobar") + assertNull(result) + + result = regex.find("barfoo") + assertNotNull(result) + assertTrue(result!!.range.start == 3 && result.range.endInclusive == 5) + assertTrue(result.groups[0]!!.range.start == 3 && result.groups[0]!!.range.endInclusive == 5) + assertNull(result.next()) + + regex = Regex("^foo([0-9]*)", RegexOption.MULTILINE) + result = regex.find("foo1bar\nfoo2foo3\nbarfoo4") + assertNotNull(result) + assertEquals("1", result!!.groupValues[1]) + result = result.next() + assertNotNull(result) + assertEquals("2", result!!.groupValues[1]) + assertNull(result.next()) + + regex = Regex("foo([0-9]*)$", RegexOption.MULTILINE) + result = regex.find("foo1bar\nfoo2foo3\nbarfoo4") + assertNotNull(result) + assertEquals("3", result!!.groupValues[1]) + result = result.next() + assertNotNull(result) + assertEquals("4", result!!.groupValues[1]) + assertNull(result.next()) + + regex = Regex("(?m)^foo([0-9]*)") + result = regex.find("foo1bar\nfoo2foo3\nbarfoo4") + assertNotNull(result) + assertEquals("1", result!!.groupValues[1]) + result = result.next() + assertNotNull(result) + assertEquals("2", result!!.groupValues[1]) + assertNull(result.next()) + + regex = Regex("(?m)foo([0-9]*)$") + result = regex.find("foo1bar\nfoo2foo3\nbarfoo4") + assertNotNull(result) + assertEquals("3", result!!.groupValues[1]) + result = result.next() + assertNotNull(result) + assertEquals("4", result!!.groupValues[1]) + assertNull(result.next()) + } + +} diff --git a/kotlin-native/backend.native/tests/harmony_regex/PatternErrorTest.kt b/kotlin-native/backend.native/tests/harmony_regex/PatternErrorTest.kt new file mode 100644 index 00000000000..010816430e3 --- /dev/null +++ b/kotlin-native/backend.native/tests/harmony_regex/PatternErrorTest.kt @@ -0,0 +1,44 @@ +/* Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package test.text.harmony_regex + +import kotlin.text.* +import kotlin.test.* + +class PatternErrorTest { + + @Test fun testCompileErrors() { + // empty regex string - no exception should be thrown + Regex("") + + // note: invalid regex syntax checked in PatternSyntaxExceptionTest + + // flags = 0 should raise no exception + Regex("foo", emptySet()) + + // check that all valid flags accepted without exception + val options = setOf( + RegexOption.UNIX_LINES, + RegexOption.IGNORE_CASE, + RegexOption.MULTILINE, + RegexOption.CANON_EQ, + RegexOption.COMMENTS, + RegexOption.DOT_MATCHES_ALL) + Regex("foo", options) + } + +} diff --git a/kotlin-native/backend.native/tests/harmony_regex/PatternSyntaxExceptionTest.kt b/kotlin-native/backend.native/tests/harmony_regex/PatternSyntaxExceptionTest.kt new file mode 100644 index 00000000000..b956e573097 --- /dev/null +++ b/kotlin-native/backend.native/tests/harmony_regex/PatternSyntaxExceptionTest.kt @@ -0,0 +1,44 @@ +/* Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package test.text.harmony_regex + +import kotlin.text.* +import kotlin.test.* + +class PatternSyntaxExceptionTest { + + @Test fun testCase() { + val regex = "(" + try { + Regex(regex) + fail("IllegalArgumentException expected") + } catch (e: IllegalArgumentException) { + // TODO: Check the exception's properties. + } + + } + + @Test fun testCase2() { + val regex = "[4-" + try { + Regex(regex) + fail("IllegalArgumentException expected") + } catch (e: IllegalArgumentException) { + } + + } +} diff --git a/kotlin-native/backend.native/tests/harmony_regex/PatternTest.kt b/kotlin-native/backend.native/tests/harmony_regex/PatternTest.kt new file mode 100644 index 00000000000..121a43875d5 --- /dev/null +++ b/kotlin-native/backend.native/tests/harmony_regex/PatternTest.kt @@ -0,0 +1,1256 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package test.text.harmony_regex + +import kotlin.text.* +import kotlin.test.* + +class PatternTest { + + fun assertTrue(msg: String, value: Boolean) = assertTrue(value, msg) + fun assertFalse(msg: String, value: Boolean) = assertFalse(value, msg) + + internal var testPatterns = arrayOf("(a|b)*abb", "(1*2*3*4*)*567", "(a|b|c|d)*aab", "(1|2|3|4|5|6|7|8|9|0)(1|2|3|4|5|6|7|8|9|0)*", "(abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ)*", "(a|b)*(a|b)*A(a|b)*lice.*", "(a|b|c|d|e|f|g|h|i|j|k|l|m|n|o|p|q|r|s|t|u|v|w|x|y|z)(a|b|c|d|e|f|g|h|" + "i|j|k|l|m|n|o|p|q|r|s|t|u|v|w|x|y|z)*(1|2|3|4|5|6|7|8|9|0)*|while|for|struct|if|do", "x(?c)y", "x(?cc)y", "x(?:c)y") + + @Test fun testCommentsInPattern() { + val p = Regex("ab# this is a comment\ncd", RegexOption.COMMENTS) + assertTrue(p.matches("abcd")) + } + + @Test fun testSplitCharSequenceint() { + // Splitting CharSequence which ends with pattern. + // Harmony regress tests. + assertEquals(",,".split(",".toRegex(), 3).toTypedArray().size, 3) + assertEquals(",,".split(",".toRegex(), 4).toTypedArray().size, 3) + assertEquals(Regex("o").split("boo:and:foo", 5).size, 5) + assertEquals(Regex("b").split("ab", 0).size, 2) + var s: List + var regex = Regex("x") + s = regex.split("zxx:zzz:zxx", 10) + assertEquals(s.size, 5) + s = regex.split("zxx:zzz:zxx", 3) + assertEquals(s.size, 3) + s = regex.split("zxx:zzz:zxx", 0) + assertEquals(s.size, 5) + + // Other splitting. + // Negative limit + regex = Regex("b") + s = regex.split("abccbadfebb", 0) + assertEquals(s.size, 5) + s = regex.split("", 0) + assertEquals(s.size, 1) + regex = Regex("") + s = regex.split("", 0) + assertEquals(s.size, 2) + s = regex.split("abccbadfe", 0) + assertEquals(s.size, 11) + + // positive limit + regex = Regex("b") + s = regex.split("abccbadfebb", 12) + assertEquals(s.size, 5) + s = regex.split("", 6) + assertEquals(s.size, 1) + regex = Regex("") + s = regex.split("", 11) + assertEquals(s.size, 2) + s = regex.split("abccbadfe", 15) + assertEquals(s.size, 11) + + regex = Regex("b") + s = regex.split("abccbadfebb", 5) + assertEquals(s.size, 5) + s = regex.split("", 1) + assertEquals(s.size, 1) + regex = Regex("") + s = regex.split("", 1) + assertEquals(s.size, 1) + s = regex.split("abccbadfe", 11) + assertEquals(s.size, 11) + + regex = Regex("b") + s = regex.split("abccbadfebb", 3) + assertEquals(s.size, 3) + regex = Regex("") + s = regex.split("abccbadfe", 5) + assertEquals(s.size, 5) + } + + @Test fun testFlags() { + var baseString: String + var testString: String + var regex: Regex + + baseString = "((?i)|b)a" + testString = "A" + regex = Regex(baseString) + assertFalse(regex.matches(testString)) + + baseString = "(?i)a|b" + testString = "A" + regex = Regex(baseString) + assertTrue(regex.matches(testString)) + + baseString = "(?i)a|b" + testString = "B" + regex = Regex(baseString) + assertTrue(regex.matches(testString)) + + baseString = "c|(?i)a|b" + testString = "B" + regex = Regex(baseString) + assertTrue(regex.matches(testString)) + + baseString = "(?i)a|(?s)b" + testString = "B" + regex = Regex(baseString) + assertTrue(regex.matches(testString)) + + baseString = "(?i)a|(?-i)b" + testString = "B" + regex = Regex(baseString) + assertFalse(regex.matches(testString)) + + baseString = "(?i)a|(?-i)c|b" + testString = "B" + regex = Regex(baseString) + assertFalse(regex.matches(testString)) + + baseString = "(?i)a|(?-i)c|(?i)b" + testString = "B" + regex = Regex(baseString) + assertTrue(regex.matches(testString)) + + baseString = "(?i)a|(?-i)b" + testString = "A" + regex = Regex(baseString) + assertTrue(regex.matches(testString)) + + baseString = "((?i))a" + testString = "A" + regex = Regex(baseString) + assertFalse(regex.matches(testString)) + + baseString = "|(?i)|a" + testString = "A" + regex = Regex(baseString) + assertTrue(regex.matches(testString)) + + baseString = "(?i)((?s)a.)" + testString = "A\n" + regex = Regex(baseString) + assertTrue(regex.matches(testString)) + + baseString = "(?i)((?-i)a)" + testString = "A" + regex = Regex(baseString) + assertFalse(regex.matches(testString)) + + baseString = "(?i)(?s:a.)" + testString = "A\n" + regex = Regex(baseString) + assertTrue(regex.matches(testString)) + + baseString = "(?i)fgh(?s:aa)" + testString = "fghAA" + regex = Regex(baseString) + assertTrue(regex.matches(testString)) + + baseString = "(?i)((?-i))a" + testString = "A" + regex = Regex(baseString) + assertTrue(regex.matches(testString)) + + baseString = "abc(?i)d" + testString = "ABCD" + regex = Regex(baseString) + assertFalse(regex.matches(testString)) + + testString = "abcD" + assertTrue(regex.matches(testString)) + + baseString = "a(?i)a(?-i)a(?i)a(?-i)a" + testString = "aAaAa" + regex = Regex(baseString) + assertTrue(regex.matches(testString)) + + testString = "aAAAa" + assertFalse(regex.matches(testString)) + } + + fun Set.containsOnly(vararg options: RegexOption): Boolean { + val toCheck = options.toSet() + return size == toCheck.size && containsAll(toCheck) + } + + @Test fun testFlagsMethod() { + val a = kotlin.text.Regex("sdf") + var baseString: String + var regex: Regex + + baseString = "(?-i)" + regex = Regex(baseString) + + baseString = "(?idmsux)abc(?-i)vg(?-dmu)" + regex = Regex(baseString) + assertTrue(regex.options.containsOnly(RegexOption.DOT_MATCHES_ALL, RegexOption.COMMENTS)) + + baseString = "(?idmsux)abc|(?-i)vg|(?-dmu)" + regex = Regex(baseString) + assertTrue(regex.options.containsOnly(RegexOption.DOT_MATCHES_ALL, RegexOption.COMMENTS)) + + baseString = "(?is)a((?x)b.)" + regex = Regex(baseString) + assertTrue(regex.options.containsOnly(RegexOption.DOT_MATCHES_ALL, RegexOption.IGNORE_CASE)) + + baseString = "(?i)a((?-i))" + regex = Regex(baseString) + assertTrue(regex.options.containsOnly(RegexOption.IGNORE_CASE)) + + baseString = "((?i)a)" + regex = Regex(baseString) + assertTrue(regex.options.isEmpty()) + + regex = Regex("(?is)abc") + assertTrue(regex.options.containsOnly(RegexOption.IGNORE_CASE, RegexOption.DOT_MATCHES_ALL)) + } + + @Test fun testCompileStringint() { + /* + * this tests are needed to verify that appropriate exceptions are hrown + */ + var pattern = "b)a" + try { + Regex(pattern) + fail("Expected a IllegalArgumentException when compiling pattern: " + pattern) + } catch (e: IllegalArgumentException) { + // pass + } + + pattern = "bcde)a" + try { + Regex(pattern) + fail("Expected a IllegalArgumentException when compiling pattern: " + pattern) + } catch (e: IllegalArgumentException) { + // pass + } + + pattern = "bbg())a" + try { + Regex(pattern) + fail("Expected a IllegalArgumentException when compiling pattern: " + pattern) + } catch (e: IllegalArgumentException) { + // pass + } + + pattern = "cdb(?i))a" + try { + Regex(pattern) + fail("Expected a IllegalArgumentException when compiling pattern: " + pattern) + } catch (e: IllegalArgumentException) { + // pass + } + + /* + * This pattern should compile (Originally it is a regression test for HARMONY-2127) + */ + pattern = "x(?c)y" + Regex(pattern) + + /* + * This pattern doesn't match any string, but should be compiled anyway + */ + pattern = "(b\\u0001)a" + Regex(pattern) + } + + + @Test fun testQuantCompileNeg() { + val patterns = arrayOf("5{,2}", "{5asd", "{hgdhg", "{5,hjkh", "{,5hdsh", "{5,3shdfkjh}") + for (element in patterns) { + try { + Regex(element) + fail("IllegalArgumentException was expected, but compilation succeeds") + } catch (pse: IllegalArgumentException) { + continue + } + + } + } + + @Test fun testQuantCompilePos() { + val patterns = arrayOf("abc{2,}", "abc{5}") + for (element in patterns) { + Regex(element) + } + } + + @Test fun testQuantComposition() { + val pattern = "(a{1,3})aab" + val regex = Regex(pattern) + val result = regex.matchEntire("aaab") + assertNotNull(result) + assertEquals(result!!.groups[1]!!.range.start, 0) + assertEquals(result.groupValues[1], "a") + } + + @Test fun testTimeZoneIssue() { + val regex = Regex("GMT(\\+|\\-)(\\d+)(:(\\d+))?") + val result = regex.matchEntire("GMT-9:45") + assertNotNull(result) + assertEquals("-", result!!.groupValues[1]) + assertEquals("9", result.groupValues[2]) + assertEquals(":45", result.groupValues[3]) + assertEquals("45", result.groupValues[4]) + } + + @Test fun testCompileRanges() { + val correctTestPatterns = arrayOf("[^]*abb]*", "[^a-d[^m-p]]*abb", "[a-d\\d]*abb", "[abc]*abb", + "[a-e&&[de]]*abb", "[^abc]*abb", "[a-e&&[^de]]*abb", "[a-z&&[^m-p]]*abb", "[a-d[m-p]]*abb", + "[a-zA-Z]*abb", "[+*?]*abb", "[^+*?]*abb") + + val inputSecuence = arrayOf("kkkk", "admpabb", "abcabcd124654abb", "abcabccbacababb", + "dededededededeedabb", "gfdhfghgdfghabb", "accabacbcbaabb", "acbvfgtyabb", "adbcacdbmopabcoabb", + "jhfkjhaSDFGHJkdfhHNJMjkhfabb", "+*??+*abb", "sdfghjkabb") + + for (i in correctTestPatterns.indices) { + assertTrue("pattern: " + correctTestPatterns[i] + " input: " + inputSecuence[i], + Regex(correctTestPatterns[i]).matches(inputSecuence[i])) + } + + val wrongInputSecuence = arrayOf("]", "admpkk", "abcabcd124k654abb", "abwcabccbacababb", + "abababdeababdeabb", "abcabcacbacbabb", "acdcbecbaabb", "acbotyabb", "adbcaecdbmopabcoabb", + "jhfkjhaSDFGHJk;dfhHNJMjkhfabb", "+*?a?+*abb", "sdf+ghjkabb") + + for (i in correctTestPatterns.indices) { + assertFalse("pattern: " + correctTestPatterns[i] + " input: " + wrongInputSecuence[i], + Regex(correctTestPatterns[i]).matches(wrongInputSecuence[i])) + } + } + + @Test fun testRangesSpecialCases() { + val neg_patterns = arrayOf("[a-&&[b-c]]", "[a-\\w]", "[b-a]", "[]") + + for (element in neg_patterns) { + try { + Regex(element) + fail("IllegalArgumentException was expected: " + element) + } catch (pse: IllegalArgumentException) { + } + + } + + val pos_patterns = arrayOf("[-]+", "----", "[a-]+", "a-a-a-a-aa--", "[\\w-a]+", "123-2312--aaa-213", "[a-]]+", "-]]]]]]]]]]]]]]]") + + var i = 0 + while (i < pos_patterns.size) { + val pat = pos_patterns[i++] + val inp = pos_patterns[i] + assertTrue("pattern: $pat input: $inp", Regex(pat).matches(inp)) + i++ + } + } + + @Test fun testZeroSymbols() { + assertTrue(Regex("[\u0000]*abb").matches("\u0000\u0000\u0000\u0000\u0000\u0000abb")) + } + + @Test fun testEscapes() { + val regex = Regex("\\Q{]()*?") + assertTrue(regex.matches("{]()*?")) + } + + @Test fun testRegressions() { + // Bug 181 + Regex("[\\t-\\r]") + + // HARMONY-4472 + Regex("a*.+") + + // Bug187 + Regex("|(?idmsux-idmsux)|(?idmsux-idmsux)|[^|\\[-\\0274|\\,-\\\\[^|W\\}\\nq\\x65\\002\\xFE\\05\\06\\00\\x66\\x47i\\,\\xF2\\=\\06\\u0EA4\\x9B\\x3C\\f\\|\\{\\xE5\\05\\r\\u944A\\xCA\\e|\\x19\\04\\x07\\04\\u607B\\023\\0073\\x91Tr\\0150\\x83]]?(?idmsux-idmsux:\\p{Alpha}{7}?)||(?<=[^\\uEC47\\01\\02\\u3421\\a\\f\\a\\013q\\035w\\e])(?<=\\p{Punct}{0,}?)(?=^\\p{Lower})(?!\\b{8,14})(?[\\x3E-\\]])|(?idmsux-idmsux:\\p{Punct})|(?[|\\n\\042\\uB09F\\06\\u0F2B\\uC96D\\x89\\uC166\\xAA|\\04-\\][^|\\a\\|\\rx\\04\\uA770\\n\\02\\t\\052\\056\\0274\\|\\=\\07\\e|\\00-\\x1D&&[^\\005\\uB15B\\uCDAC\\n\\x74\\0103\\0147\\uD91B\\n\\062G\\u9B4B\\077\\}\\0324&&[^\\0302\\,\\0221\\04\\u6D16\\04xy\\uD193\\[\\061\\06\\045\\x0F|\\e\\xBB\\f\\u1B52\\023\\u3AD2\\033\\007\\022\\}\\x66\\uA63FJ-\\0304]]]]{0,0})||(?^+)|(?![^|\\|\\nJ\\t\\<\\04E\\\\\\t\\01\\\\\\02\\|\\=\\}\\xF3\\uBEC2\\032K\\014\\uCC5F\\072q\\|\\0153\\xD9\\0322\\uC6C8[^\\t\\0342\\x34\\x91\\06\\{\\xF1\\a\\u1710\\?\\xE7\\uC106\\02pF\\<&&[^|\\]\\064\\u381D\\u50CF\\eO&&[^|\\06\\x2F\\04\\045\\032\\u8536W\\0377\\0017|\\x06\\uE5FA\\05\\xD4\\020\\04c\\xFC\\02H\\x0A\\r]]]]+?)(?idmsux-idmsux)|(?[\\{-\\0207|\\06-\\0276\\p{XDigit}])(?idmsux-idmsux:[^|\\x52\\0012\\]u\\xAD\\0051f\\0142\\\\l\\|\\050\\05\\f\\t\\u7B91\\r\\u7763\\{|h\\0104\\a\\f\\0234\\u2D4F&&^\\P{InGreek}]))") + + // HARMONY-5858 + Regex("\\u6211", RegexOption.LITERAL) + } + + @Test fun testOrphanQuantifiers() { + try { + Regex("+++++") + fail("IllegalArgumentException expected") + } catch (pse: IllegalArgumentException) { + } + + } + + @Test fun testOrphanQuantifiers2() { + try { + Regex("\\d+*") + fail("IllegalArgumentException expected") + } catch (pse: IllegalArgumentException) { + } + + } + + @Test fun testBug197() { + val vals = arrayOf(":", 2, arrayOf("boo", "and:foo"), + ":", 5, arrayOf("boo", "and", "foo"), + ":", 0, arrayOf("boo", "and", "foo"), + ":", 3, arrayOf("boo", "and", "foo"), + ":", 1, arrayOf("boo:and:foo"), + "o", 5, arrayOf("b", "", ":and:f", "", ""), + "o", 4, arrayOf("b", "", ":and:f", "o"), + "o", 0, arrayOf("b", "", ":and:f", "", "") + ) + + var i = 0 + while (i < vals.size / 3) { + val res = Regex(vals[i++].toString()).split("boo:and:foo", (vals[i++] as Int)) + val expectedRes = vals[i++] as Array + + assertEquals(expectedRes.size, res.size) + + for (j in expectedRes.indices) { + assertEquals(expectedRes[j], res[j]) + } + } + } + + @Test fun testURIPatterns() { + val URI_REGEXP_STR = "^(([^:/?#]+):)?(//([^/?#]*))?([^?#]*)(\\?([^#]*))?(#(.*))?"; + val SCHEME_REGEXP_STR = "^[a-zA-Z]{1}[\\w+-.]+$"; + val REL_URI_REGEXP_STR = "^(//([^/?#]*))?([^?#]*)(\\?([^#]*))?(#(.*))?"; + val IPV6_REGEXP_STR = "^[0-9a-fA-F\\:\\.]+(\\%\\w+)?$"; + val IPV6_REGEXP_STR2 = "^\\[[0-9a-fA-F\\:\\.]+(\\%\\w+)?\\]$"; + val IPV4_REGEXP_STR = "^[0-9]{1,3}\\.[0-9]{1,3}\\.[0-9]{1,3}\\.[0-9]{1,3}$"; + val HOSTNAME_REGEXP_STR = "\\w+[\\w\\-\\.]*"; + + Regex(URI_REGEXP_STR) + Regex(REL_URI_REGEXP_STR) + Regex(SCHEME_REGEXP_STR) + Regex(IPV4_REGEXP_STR) + Regex(IPV6_REGEXP_STR) + Regex(IPV6_REGEXP_STR2) + Regex(HOSTNAME_REGEXP_STR) + } + + @Test fun testFindBoundaryCases1() { + val regex = Regex(".*\n") + val result = regex.find("a\n") + + assertNotNull(result) + assertEquals("a\n", result!!.value) + } + + @Test fun testFindBoundaryCases2() { + val regex = Regex(".*A") + val result = regex.find("aAa") + + assertNotNull(result) + assertEquals("aA", result!!.value) + + } + + @Test fun testFindBoundaryCases3() { + val regex = Regex(".*A") + val result = regex.find("a\naA\n") + + assertNotNull(result) + assertEquals("aA", result!!.value) + + } + + @Test fun testFindBoundaryCases4() { + val regex = Regex("A.*") + val result = regex.find("A\n") + + assertNotNull(result) + assertEquals("A", result!!.value) + + } + + @Test fun testFindBoundaryCases5() { + val regex = Regex(".*A.*") + var result = regex.find("\nA\naaa\nA\naaAaa\naaaA\n") + val expected = arrayOf("A", "A", "aaAaa", "aaaA") + + var k = 0 + while (result != null) { + assertEquals(expected[k], result.value) + result = result.next() + k++ + } + } + + @Test fun testFindBoundaryCases6() { + val regex = Regex(".*") + var result = regex.find("\na\n") + val expected = arrayOf("", "a", "", "") + + var k = 0 + while (result != null) { + assertEquals(expected[k], result.value) + k++ + result = result.next() + } + } + + @Test fun testBackReferences() { + var regex = Regex("(\\((\\w*):(.*):(\\2)\\))") + var result = regex.find("(start1: word :start1)(start2: word :start2)") + + var k = 1 + while (result != null) { + assertEquals("start" + k, result.groupValues[2]) + assertEquals(" word ", result.groupValues[3]) + assertEquals("start" + k, result.groupValues[4]) + k++ + result = result.next() + } + + assertEquals(3, k) + regex = Regex(".*(.)\\1") + assertTrue(regex.matches("saa")) + } + + @Test fun testNewLine() { + val regex = Regex("(^$)*\n", RegexOption.MULTILINE) + var result = regex.find("\r\n\n") + var counter = 0 + while (result != null) { + counter++ + result = result.next() + } + assertEquals(2, counter) + } + + @Test fun testFindGreedy() { + val regex = Regex(".*aaa", RegexOption.DOT_MATCHES_ALL) + val result = regex.matchEntire("aaaa\naaa\naaaaaa") + assertNotNull(result) + assertEquals(14, result!!.range.endInclusive) + } + + @Test fun testSOLQuant() { + val regex = Regex("$*", RegexOption.MULTILINE) + var result = regex.find("\n\n") + var counter = 0 + while (result != null) { + counter++ + result = result.next() + } + assertEquals(3, counter) + } + + @Test fun testIllegalEscape() { + try { + Regex("\\y") + fail("IllegalArgumentException expected") + } catch (pse: IllegalArgumentException) { + } + } + + @Test fun testEmptyFamily() { + Regex("\\p{Lower}") + } + + @Test fun testNonCaptConstr() { + // Flags + var regex = Regex("(?i)b*(?-i)a*") + assertTrue(regex.matches("bBbBaaaa")) + assertFalse(regex.matches("bBbBAaAa")) + + // Non-capturing groups + regex = Regex("(?i:b*)a*") + assertTrue(regex.matches("bBbBaaaa")) + assertFalse(regex.matches("bBbBAaAa")) + + // 1 2 3 4 5 6 7 8 9 10 11 + regex = Regex("(?:-|(-?\\d+\\d\\d\\d))?(?:-|-(\\d\\d))?(?:-|-(\\d\\d))?(T)?(?:(\\d\\d):(\\d\\d):(\\d\\d)(\\.\\d+)?)?(?:(?:((?:\\+|\\-)\\d\\d):(\\d\\d))|(Z))?") + val result = regex.matchEntire("-1234-21-31T41:51:61.789+71:81") + assertNotNull(result) + assertEquals("-1234", result!!.groupValues[1]) + assertEquals("21", result.groupValues[2]) + assertEquals("31", result.groupValues[3]) + assertEquals("T", result.groupValues[4]) + assertEquals("41", result.groupValues[5]) + assertEquals("51", result.groupValues[6]) + assertEquals("61", result.groupValues[7]) + assertEquals(".789", result.groupValues[8]) + assertEquals("+71", result.groupValues[9]) + assertEquals("81", result.groupValues[10]) + + // positive lookahead + regex = Regex(".*\\.(?=log$).*$") + assertTrue(regex.matches("a.b.c.log")) + assertFalse(regex.matches("a.b.c.log.")) + + // negative lookahead + regex = Regex(".*\\.(?!log$).*$") + assertFalse(regex.matches("abc.log")) + assertTrue(regex.matches("abc.logg")) + + // positive lookbehind + regex = Regex(".*(?<=abc)\\.log$") + assertFalse(regex.matches("cde.log")) + assertTrue(regex.matches("abc.log")) + + // negative lookbehind + regex = Regex(".*(?a*)abb") + assertFalse(regex.matches("aaabb")) + regex = Regex("(?>a*)bb") + assertTrue(regex.matches("aaabb")) + + regex = Regex("(?>a|aa)aabb") + assertTrue(regex.matches("aaabb")) + regex = Regex("(?>aa|a)aabb") + assertFalse(regex.matches("aaabb")) + + // quantifiers over look ahead + regex = Regex(".*(?<=abc)*\\.log$") + assertTrue(regex.matches("cde.log")) + regex = Regex(".*(?<=abc)+\\.log$") + assertFalse(regex.matches("cde.log")) + } + + @Test fun testCompilePatternWithTerminatorMark() { + val regex = Regex("a\u0000\u0000cd") + assertTrue(regex.matches("a\u0000\u0000cd")) + } + + @Test fun testAlternations() { + var baseString = "|a|bc" + var regex = Regex(baseString) + assertTrue(regex.matches("")) + + baseString = "a||bc" + regex = Regex(baseString) + assertTrue(regex.matches("")) + + baseString = "a|bc|" + regex = Regex(baseString) + assertTrue(regex.matches("")) + + baseString = "a|b|" + regex = Regex(baseString) + assertTrue(regex.matches("")) + + baseString = "a(|b|cd)e" + regex = Regex(baseString) + assertTrue(regex.matches("ae")) + + baseString = "a(b||cd)e" + regex = Regex(baseString) + assertTrue(regex.matches("ae")) + + baseString = "a(b|cd|)e" + regex = Regex(baseString) + assertTrue(regex.matches("ae")) + + baseString = "a(b|c|)e" + regex = Regex(baseString) + assertTrue(regex.matches("ae")) + + baseString = "a(|)e" + regex = Regex(baseString) + assertTrue(regex.matches("ae")) + + baseString = "|" + regex = Regex(baseString) + assertTrue(regex.matches("")) + + baseString = "a(?:|)e" + regex = Regex(baseString) + assertTrue(regex.matches("ae")) + + baseString = "a||||bc" + regex = Regex(baseString) + assertTrue(regex.matches("")) + + baseString = "(?i-is)|a" + regex = Regex(baseString) + assertTrue(regex.matches("a")) + } + + @Test fun testMatchWithGroups() { + var baseString = "jwkerhjwehrkwjehrkwjhrwkjehrjwkehrjkwhrkwehrkwhrkwrhwkhrwkjehr" + var pattern = ".*(..).*\\1.*" + assertTrue(Regex(pattern).matches(baseString)) + + baseString = "saa" + pattern = ".*(.)\\1" + assertTrue(Regex(pattern).matches(baseString)) + assertTrue(Regex(pattern).containsMatchIn(baseString)) + } + + @Test fun testSplitEmptyCharSequence() { + val s1 = "" + val arr = s1.split(":".toRegex()) + assertEquals(arr.size, 1) + } + + @Test fun testSplitEndsWithPattern() { + assertEquals(",,".split(",".toRegex(), 3).toTypedArray().size, 3) + assertEquals(",,".split(",".toRegex(), 4).toTypedArray().size, 3) + + assertEquals(Regex("o").split("boo:and:foo", 5).size, 5) + assertEquals(Regex("b").split("ab", 0).size, 2) + } + + @Test fun testCaseInsensitiveFlag() { + assertTrue(Regex("(?i-:AbC)").matches("ABC")) + } + + @Test fun testEmptyGroups() { + var regex = Regex("ab(?>)cda") + assertTrue(regex.matches("abcda")) + + regex = Regex("ab()") + assertTrue(regex.matches("ab")) + + regex = Regex("abc(?:)(..)") + assertTrue(regex.matches("abcgf")) + } + + @Test fun testCompileNonCaptGroup() { + var isCompiled = false + + try { + Regex("(?:)", RegexOption.CANON_EQ) + Regex("(?:)", setOf(RegexOption.CANON_EQ, RegexOption.DOT_MATCHES_ALL)) + Regex("(?:)", setOf(RegexOption.CANON_EQ, RegexOption.IGNORE_CASE)) + Regex("(?:)", setOf(RegexOption.CANON_EQ, RegexOption.COMMENTS, RegexOption.UNIX_LINES)) + isCompiled = true + } catch (e: IllegalArgumentException) { + println(e) + } + assertTrue(isCompiled) + } + + @Test fun testEmbeddedFlags() { + var baseString = "(?i)((?s)a)" + var testString = "A" + var regex = Regex(baseString) + assertTrue(regex.matches(testString)) + + baseString = "(?x)(?i)(?s)(?d)a" + testString = "A" + regex = Regex(baseString) + assertTrue(regex.matches(testString)) + + baseString = "(?x)(?i)(?s)(?d)a." + testString = "a\n" + regex = Regex(baseString) + assertTrue(regex.matches(testString)) + + baseString = "abc(?x:(?i)(?s)(?d)a.)" + testString = "abcA\n" + regex = Regex(baseString) + assertTrue(regex.matches(testString)) + + baseString = "abc((?x)d)(?i)(?s)a" + testString = "abcdA" + regex = Regex(baseString) + assertTrue(regex.matches(testString)) + } + + @Test fun testAltWithFlags() { + Regex("|(?i-xi)|()") + } + + @Test fun testRestoreFlagsAfterGroup() { + val baseString = "abc((?x)d) a" + val testString = "abcd a" + val regex = Regex(baseString) + assertTrue(regex.matches(testString)) + } + + @Test fun testCanonEqFlag() { + + /* + * for decompositions see + * http://www.unicode.org/Public/4.0-Update/UnicodeData-4.0.0.txt + * http://www.unicode.org/reports/tr15/#Decomposition + */ + var baseString: String + var testString: String + var regex: Regex + + baseString = "ab(a*)\\u0001" + regex = Regex(baseString, RegexOption.CANON_EQ) + + baseString = "a(abcdf)d" + regex = Regex(baseString, RegexOption.CANON_EQ) + + baseString = "aabcdfd" + regex = Regex(baseString, RegexOption.CANON_EQ) + + // \u01E0 -> \u0226\u0304 ->\u0041\u0307\u0304 + // \u00CC -> \u0049\u0300 + + baseString = "\u01E0\u00CCcdb(ac)" + testString = "\u0226\u0304\u0049\u0300cdbac" + regex = Regex(baseString, RegexOption.CANON_EQ) + assertTrue(regex.matches(testString)) + + baseString = "\u01E0cdb(a\u00CCc)" + testString = "\u0041\u0307\u0304cdba\u0049\u0300c" + regex = Regex(baseString, RegexOption.CANON_EQ) + assertTrue(regex.matches(testString)) + + baseString = "a\u00CC" + testString = "a\u0049\u0300" + regex = Regex(baseString, RegexOption.CANON_EQ) + assertTrue(regex.matches(testString)) + + baseString = "\u0226\u0304cdb(ac\u0049\u0300)" + testString = "\u01E0cdbac\u00CC" + regex = Regex(baseString, RegexOption.CANON_EQ) + assertTrue(regex.matches(testString)) + + baseString = "cdb(?:\u0041\u0307\u0304\u00CC)" + testString = "cdb\u0226\u0304\u0049\u0300" + regex = Regex(baseString, RegexOption.CANON_EQ) + assertTrue(regex.matches(testString)) + + baseString = "\u01E0[a-c]\u0049\u0300cdb(ac)" + testString = "\u01E0b\u00CCcdbac" + regex = Regex(baseString, RegexOption.CANON_EQ) + assertTrue(regex.matches(testString)) + + baseString = "\u01E0|\u00CCcdb(ac)" + testString = "\u0041\u0307\u0304" + regex = Regex(baseString, RegexOption.CANON_EQ) + assertTrue(regex.matches(testString)) + + baseString = "\u00CC?cdb(ac)*(\u01E0)*[a-c]" + testString = "cdb\u0041\u0307\u0304b" + regex = Regex(baseString, RegexOption.CANON_EQ) + assertTrue(regex.matches(testString)) + + baseString = "a\u0300" + regex = Regex(baseString, RegexOption.CANON_EQ) + assertTrue(regex.containsMatchIn("a\u00E0a")) + + baseString = "\u7B20\uF9F8abc" + regex = Regex(baseString, RegexOption.CANON_EQ) + assertTrue(regex.matches("\uF9F8\uF9F8abc")) + + // \u01F9 -> \u006E\u0300 + // \u00C3 -> \u0041\u0303 + + baseString = "cdb(?:\u00C3\u006E\u0300)" + testString = "cdb\u0041\u0303\u01F9" + regex = Regex(baseString, RegexOption.CANON_EQ) + assertTrue(regex.matches(testString)) + + // \u014C -> \u004F\u0304 + // \u0163 -> \u0074\u0327 + + baseString = "cdb(?:\u0163\u004F\u0304)" + testString = "cdb\u0074\u0327\u014C" + regex = Regex(baseString, RegexOption.CANON_EQ) + assertTrue(regex.matches(testString)) + + // \u00E1->a\u0301 + // canonical ordering takes place \u0301\u0327 -> \u0327\u0301 + + baseString = "c\u0327\u0301" + testString = "c\u0301\u0327" + regex = Regex(baseString, RegexOption.CANON_EQ) + assertTrue(regex.matches(testString)) + + /* + * Hangul decompositions + */ + // \uD4DB->\u1111\u1171\u11B6 + // \uD21E->\u1110\u116D\u11B5 + // \uD264->\u1110\u1170 + // not Hangul:\u0453->\u0433\u0301 + baseString = "a\uD4DB\u1111\u1171\u11B6\uD264" + regex = Regex(baseString, RegexOption.CANON_EQ) + + baseString = "\u0453c\uD4DB" + regex = Regex(baseString, RegexOption.CANON_EQ) + + baseString = "a\u1110\u116D\u11B5b\uD21Ebc" + regex = Regex(baseString, RegexOption.CANON_EQ) + + baseString = "\uD4DB\uD21E\u1110\u1170cdb(ac)" + testString = "\u1111\u1171\u11B6\u1110\u116D\u11B5\uD264cdbac" + regex = Regex(baseString, RegexOption.CANON_EQ) + assertTrue(regex.matches(testString)) + + baseString = "\uD4DB\uD264cdb(a\uD21Ec)" + testString = "\u1111\u1171\u11B6\u1110\u1170cdba\u1110\u116D\u11B5c" + regex = Regex(baseString, RegexOption.CANON_EQ) + assertTrue(regex.matches(testString)) + + baseString = "a\uD4DB" + testString = "a\u1111\u1171\u11B6" + regex = Regex(baseString, RegexOption.CANON_EQ) + assertTrue(regex.matches(testString)) + + baseString = "a\uD21E" + testString = "a\u1110\u116D\u11B5" + regex = Regex(baseString, RegexOption.CANON_EQ) + assertTrue(regex.matches(testString)) + + baseString = "\u1111\u1171\u11B6cdb(ac\u1110\u116D\u11B5)" + testString = "\uD4DBcdbac\uD21E" + regex = Regex(baseString, RegexOption.CANON_EQ) + assertTrue(regex.matches(testString)) + + baseString = "cdb(?:\u1111\u1171\u11B6\uD21E)" + testString = "cdb\uD4DB\u1110\u116D\u11B5" + regex = Regex(baseString, RegexOption.CANON_EQ) + assertTrue(regex.matches(testString)) + + baseString = "\uD4DB[a-c]\u1110\u116D\u11B5cdb(ac)" + testString = "\uD4DBb\uD21Ecdbac" + regex = Regex(baseString, RegexOption.CANON_EQ) + assertTrue(regex.matches(testString)) + + baseString = "\uD4DB|\u00CCcdb(ac)" + testString = "\u1111\u1171\u11B6" + regex = Regex(baseString, RegexOption.CANON_EQ) + assertTrue(regex.matches(testString)) + + baseString = "\uD4DB|\u00CCcdb(ac)" + testString = "\u1111\u1171" + regex = Regex(baseString, RegexOption.CANON_EQ) + assertFalse(regex.matches(testString)) + + baseString = "\u00CC?cdb(ac)*(\uD4DB)*[a-c]" + testString = "cdb\u1111\u1171\u11B6b" + regex = Regex(baseString, RegexOption.CANON_EQ) + assertTrue(regex.matches(testString)) + + baseString = "\uD4DB" + regex = Regex(baseString, RegexOption.CANON_EQ) + assertTrue(regex.containsMatchIn("a\u1111\u1171\u11B6a")) + + baseString = "\u1111" + regex = Regex(baseString, RegexOption.CANON_EQ) + assertFalse(regex.containsMatchIn("bcda\uD4DBr")) + } + + @Test fun testIndexesCanonicalEq() { + var baseString: String + var testString: String + var regex: Regex + var result: MatchResult? + + baseString = "\uD4DB" + testString = "bcda\u1111\u1171\u11B6awr" + regex = Regex(baseString, RegexOption.CANON_EQ) + result = regex.find(testString) + assertNotNull(result) + assertEquals(result!!.range.start, 4) + assertEquals(result.range.endInclusive, 6) + + baseString = "\uD4DB\u1111\u1171\u11B6" + testString = "bcda\u1111\u1171\u11B6\uD4DBawr" + regex = Regex(baseString, RegexOption.CANON_EQ) + result = regex.find(testString) // Use the same testString + assertNotNull(result) + assertEquals(result!!.range.start, 4) + assertEquals(result.range.endInclusive, 7) + + baseString = "\uD4DB\uD21E\u1110\u1170" + testString = "abcabc\u1111\u1171\u11B6\u1110\u116D\u11B5\uD264cdbac" + regex = Regex(baseString, RegexOption.CANON_EQ) + result = regex.find(testString) + assertNotNull(result) + assertEquals(result!!.range.start, 6) + assertEquals(result.range.endInclusive, 12) + } + + @Test fun testCanonEqFlagWithSupplementaryCharacters() { + + /* + * \u1D1BF->\u1D1BB\u1D16F->\u1D1B9\u1D165\u1D16F in UTF32 + * \uD834\uDDBF->\uD834\uDDBB\uD834\uDD6F + * ->\uD834\uDDB9\uD834\uDD65\uD834\uDD6F in UTF16 + */ + var patString = "abc\uD834\uDDBFef" + var testString = "abc\uD834\uDDB9\uD834\uDD65\uD834\uDD6Fef" + var regex = Regex(patString, RegexOption.CANON_EQ) + assertTrue(regex.matches(testString)) + + testString = "abc\uD834\uDDBB\uD834\uDD6Fef" + assertTrue(regex.matches(testString)) + + patString = "abc\uD834\uDDBB\uD834\uDD6Fef" + testString = "abc\uD834\uDDBFef" + regex = Regex(patString, RegexOption.CANON_EQ) + assertTrue(regex.matches(testString)) + + testString = "abc\uD834\uDDB9\uD834\uDD65\uD834\uDD6Fef" + assertTrue(regex.matches(testString)) + + patString = "abc\uD834\uDDB9\uD834\uDD65\uD834\uDD6Fef" + testString = "abc\uD834\uDDBFef" + regex = Regex(patString, RegexOption.CANON_EQ) + assertTrue(regex.matches(testString)) + + testString = "abc\uD834\uDDBB\uD834\uDD6Fef" + assertTrue(regex.matches(testString)) + + /* + * testSupplementary characters with no decomposition + */ + patString = "a\uD9A0\uDE8Ebc\uD834\uDDBB\uD834\uDD6Fe\uDE8Ef" + testString = "a\uD9A0\uDE8Ebc\uD834\uDDBFe\uDE8Ef" + regex = Regex(patString, RegexOption.CANON_EQ) + assertTrue(regex.matches(testString)) + } + + @Test fun testRangesWithSurrogatesSupplementary() { + var patString = "[abc\uD8D2]" + var testString = "\uD8D2" + var regex = Regex(patString) + assertTrue(regex.matches(testString)) + + testString = "a" + assertTrue(regex.matches(testString)) + + testString = "ef\uD8D2\uDD71gh" + assertFalse(regex.containsMatchIn(testString)) + + testString = "ef\uD8D2gh" + assertTrue(regex.containsMatchIn(testString)) + + patString = "[abc\uD8D3&&[c\uD8D3]]" + testString = "c" + regex = Regex(patString) + assertTrue(regex.matches(testString)) + + testString = "a" + assertFalse(regex.matches(testString)) + + testString = "ef\uD8D3\uDD71gh" + assertFalse(regex.containsMatchIn(testString)) + + testString = "ef\uD8D3gh" + assertTrue(regex.containsMatchIn(testString)) + + patString = "[abc\uD8D3\uDBEE\uDF0C&&[c\uD8D3\uDBEE\uDF0C]]" + testString = "c" + regex = Regex(patString) + assertTrue(regex.matches(testString)) + + testString = "\uDBEE\uDF0C" + assertTrue(regex.matches(testString)) + + testString = "ef\uD8D3\uDD71gh" + assertFalse(regex.containsMatchIn(testString)) + + testString = "ef\uD8D3gh" + assertTrue(regex.containsMatchIn(testString)) + + patString = "[abc\uDBFC]\uDDC2cd" + testString = "\uDBFC\uDDC2cd" + regex = Regex(patString) + assertFalse(regex.matches(testString)) + + testString = "a\uDDC2cd" + assertTrue(regex.matches(testString)) + } + + @Test fun testSequencesWithSurrogatesSupplementary() { + var patString = "abcd\uD8D3" + var testString = "abcd\uD8D3\uDFFC" + var regex = Regex(patString) + assertFalse(regex.containsMatchIn(testString)) + + testString = "abcd\uD8D3abc" + assertTrue(regex.containsMatchIn(testString)) + + patString = "ab\uDBEFcd" + testString = "ab\uDBEFcd" + regex = Regex(patString) + assertTrue(regex.matches(testString)) + + patString = "\uDFFCabcd" + testString = "\uD8D3\uDFFCabcd" + regex = Regex(patString) + assertFalse(regex.containsMatchIn(testString)) + + testString = "abc\uDFFCabcdecd" + assertTrue(regex.containsMatchIn(testString)) + + patString = "\uD8D3\uDFFCabcd" + testString = "abc\uD8D3\uD8D3\uDFFCabcd" + regex = Regex(patString) + assertTrue(regex.containsMatchIn(testString)) + } + + @Test fun testPredefinedClassesWithSurrogatesSupplementary() { + var patString = "[123\\D]" + var testString = "a" + var regex = Regex(patString) + assertTrue(regex.containsMatchIn(testString)) + + testString = "5" + assertFalse(regex.containsMatchIn(testString)) + + testString = "3" + assertTrue(regex.containsMatchIn(testString)) + + // low surrogate + testString = "\uDFC4" + assertTrue(regex.containsMatchIn(testString)) + + // high surrogate + testString = "\uDADA" + assertTrue(regex.containsMatchIn(testString)) + + testString = "\uDADA\uDFC4" + assertTrue(regex.containsMatchIn(testString)) + + testString = "5" + assertFalse(regex.containsMatchIn(testString)) + + testString = "3" + assertTrue(regex.containsMatchIn(testString)) + + // low surrogate + testString = "\uDFC4" + assertTrue(regex.containsMatchIn(testString)) + + // high surrogate + testString = "\uDADA" + assertTrue(regex.containsMatchIn(testString)) + + testString = "\uDADA\uDFC4" + assertTrue(regex.containsMatchIn(testString)) + + // surrogate characters + patString = "\\p{Cs}" + testString = "\uD916\uDE27" + regex = Regex(patString) + /* + * see http://www.unicode.org/reports/tr18/#Supplementary_Characters we + * have to treat text as code points not code units. \\p{Cs} matches any + * surrogate character but here testString is a one code point + * consisting of two code units (two surrogate characters) so we find + * nothing + */ + assertFalse(regex.containsMatchIn(testString)) + + // swap low and high surrogates + testString = "\uDE27\uD916" + assertTrue(regex.containsMatchIn(testString)) + + patString = "[\uD916\uDE271\uD91623&&[^\\p{Cs}]]" + testString = "1" + regex = Regex(patString) + assertTrue(regex.containsMatchIn(testString)) + + testString = "\uD916" + regex = Regex(patString) + assertFalse(regex.containsMatchIn(testString)) + + testString = "\uD916\uDE27" + regex = Regex(patString) + assertTrue(regex.containsMatchIn(testString)) + + // \uD9A0\uDE8E=\u7828E + // \u78281=\uD9A0\uDE81 + patString = "[a-\uD9A0\uDE8E]" + testString = "\uD9A0\uDE81" + regex = Regex(patString) + assertTrue(regex.matches(testString)) + } + + @Test fun testDotConstructionWithSurrogatesSupplementary() { + var patString = "." + var testString = "\uD9A0\uDE81" + var regex = Regex(patString) + assertTrue(regex.matches(testString)) + + testString = "\uDE81" + assertTrue(regex.matches(testString)) + + testString = "\uD9A0" + assertTrue(regex.matches(testString)) + + testString = "\n" + assertFalse(regex.matches(testString)) + + patString = ".*\uDE81" + testString = "\uD9A0\uDE81\uD9A0\uDE81\uD9A0\uDE81" + regex = Regex(patString) + assertFalse(regex.matches(testString)) + + testString = "\uD9A0\uDE81\uD9A0\uDE81\uDE81" + assertTrue(regex.matches(testString)) + + patString = ".*" + testString = "\uD9A0\uDE81\n\uD9A0\uDE81\uD9A0\n\uDE81" + regex = Regex(patString, RegexOption.DOT_MATCHES_ALL) + assertTrue(regex.matches(testString)) + } + + @Test fun testQuantifiersWithSurrogatesSupplementary() { + val patString = "\uD9A0\uDE81*abc" + var testString = "\uD9A0\uDE81\uD9A0\uDE81abc" + val regex = Regex(patString) + assertTrue(regex.matches(testString)) + + testString = "abc" + assertTrue(regex.matches(testString)) + } + + @Test fun testAlternationsWithSurrogatesSupplementary() { + val patString = "\uDE81|\uD9A0\uDE81|\uD9A0" + var testString = "\uD9A0" + val regex = Regex(patString) + assertTrue(regex.matches(testString)) + + testString = "\uDE81" + assertTrue(regex.matches(testString)) + + testString = "\uD9A0\uDE81" + assertTrue(regex.matches(testString)) + + testString = "\uDE81\uD9A0" + assertFalse(regex.matches(testString)) + } + + @Test fun testGroupsWithSurrogatesSupplementary() { + + // this pattern matches nothing + var patString = "(\uD9A0)\uDE81" + var testString = "\uD9A0\uDE81" + var regex = Regex(patString) + assertFalse(regex.matches(testString)) + + patString = "(\uD9A0)" + testString = "\uD9A0\uDE81" + regex = Regex(patString, RegexOption.DOT_MATCHES_ALL) + assertFalse(regex.containsMatchIn(testString)) + } +} diff --git a/kotlin-native/backend.native/tests/harmony_regex/PatternTest2.kt b/kotlin-native/backend.native/tests/harmony_regex/PatternTest2.kt new file mode 100644 index 00000000000..6dfb82bced0 --- /dev/null +++ b/kotlin-native/backend.native/tests/harmony_regex/PatternTest2.kt @@ -0,0 +1,1195 @@ +/* Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package test.text.harmony_regex + +import kotlin.text.* +import kotlin.test.* + +class PatternTest2 { + + fun assertTrue(msg: String, value: Boolean) = assertTrue(value, msg) + fun assertFalse(msg: String, value: Boolean) = assertFalse(value, msg) + + /** + * Tests simple pattern compilation and matching methods + */ + @Test fun testSimpleMatch() { + val regex = Regex("foo.*") + + var testString = "foo123" + assertTrue(regex.matches(testString)) + assertTrue(regex in testString) + assertTrue(regex.find(testString) != null) + + testString = "fox" + assertFalse(regex.matches(testString)) + assertFalse(regex in testString) + assertFalse(regex.find(testString) != null) + + assertTrue(Regex("foo.*").matches("foo123")) + assertFalse(Regex("foo.*").matches("fox")) + assertFalse(Regex("bar").matches("foobar")) + assertTrue(Regex("").matches("")) + } + + @Test fun testCursors() { + val regex: Regex + var result: MatchResult? + + try { + regex = Regex("foo") + + result = regex.find("foobar") + assertNotNull(result) + assertEquals(0, result!!.range.start) + assertEquals(3, result.range.endInclusive + 1) + assertNull(result.next()) + + + result = regex.find("barfoobar") + assertNotNull(result) + assertEquals(3, result!!.range.start) + assertEquals(6, result.range.endInclusive + 1) + assertNull(result.next()) + + result = regex.find("barfoo") + assertNotNull(result) + assertEquals(3, result!!.range.start) + assertEquals(6, result.range.endInclusive + 1) + assertNull(result.next()) + + result = regex.find("foobarfoobarfoo") + assertNotNull(result) + assertEquals(0, result!!.range.start) + assertEquals(3, result.range.endInclusive + 1) + result = result.next() + assertNotNull(result) + assertEquals(6, result!!.range.start) + assertEquals(9, result.range.endInclusive + 1) + result = result.next() + assertNotNull(result) + assertEquals(12, result!!.range.start) + assertEquals(15, result.range.endInclusive + 1) + assertNull(result.next()) + + result = regex.find("foobarfoobarfoo", 0) + assertNotNull(result) + assertEquals(0, result!!.range.start) + assertEquals(3, result.range.endInclusive + 1) + + result = regex.find("foobarfoobarfoo", 4) + assertNotNull(result) + assertEquals(6, result!!.range.start) + assertEquals(9, result.range.endInclusive + 1) + } catch (e: IllegalArgumentException) { + println(e.message) + fail() + } + + } + + @Test fun testGroups() { + val regex: Regex + var result: MatchResult? + + regex = Regex("(p[0-9]*)#?(q[0-9]*)") + + result = regex.find("p1#q3p2q42p5p71p63#q888") + assertNotNull(result) + assertEquals(0, result!!.range.start) + assertEquals(5, result.range.endInclusive + 1) + assertEquals(3, result.groups.size) + assertEquals(0, result.groups[0]!!.range.start) + assertEquals(5, result.groups[0]!!.range.endInclusive + 1) + assertEquals(0, result.groups[1]!!.range.start) + assertEquals(2, result.groups[1]!!.range.endInclusive + 1) + assertEquals(3, result.groups[2]!!.range.start) + assertEquals(5, result.groups[2]!!.range.endInclusive + 1) + assertEquals("p1#q3", result.value) + assertEquals("p1#q3", result.groupValues[0]) + assertEquals("p1", result.groupValues[1]) + assertEquals("q3", result.groupValues[2]) + + result = result.next() + assertNotNull(result) + assertEquals(5, result!!.range.start) + assertEquals(10, result.range.endInclusive + 1) + assertEquals(3, result.groups.size) + assertEquals(10, result.groups[0]!!.range.endInclusive + 1) + assertEquals(5, result.groups[1]!!.range.start) + assertEquals(7, result.groups[1]!!.range.endInclusive + 1) + assertEquals(7, result.groups[2]!!.range.start) + assertEquals(10, result.groups[2]!!.range.endInclusive + 1) + assertEquals("p2q42", result.value) + assertEquals("p2q42", result.groupValues[0]) + assertEquals("p2", result.groupValues[1]) + assertEquals("q42", result.groupValues[2]) + + result = result.next() + assertNotNull(result) + assertEquals(15, result!!.range.start) + assertEquals(23, result.range.endInclusive + 1) + assertEquals(3, result.groups.size) + assertEquals(15, result.groups[0]!!.range.start) + assertEquals(23, result.groups[0]!!.range.endInclusive + 1) + assertEquals(15, result.groups[1]!!.range.start) + assertEquals(18, result.groups[1]!!.range.endInclusive + 1) + assertEquals(19, result.groups[2]!!.range.start) + assertEquals(23, result.groups[2]!!.range.endInclusive + 1) + assertEquals("p63#q888", result.value) + assertEquals("p63#q888", result.groupValues[0]) + assertEquals("p63", result.groupValues[1]) + assertEquals("q888", result.groupValues[2]) + assertNull(result.next()) + } + + @Test fun testReplace() { + var regex: Regex + + // Note: examples from book, + // Hitchens, Ron, 2002, "Java NIO", O'Reilly, page 171 + regex = Regex("a*b") + + var testString = "aabfooaabfooabfoob" + assertTrue(regex.replace(testString, "-") == "-foo-foo-foo-") + assertTrue(regex.replaceFirst(testString, "-") == "-fooaabfooabfoob") + + regex = Regex("([bB])yte") + + testString = "Byte for byte" + assertTrue(regex.replaceFirst(testString, "$1ite") == "Bite for byte") + assertTrue(regex.replace(testString, "$1ite") == "Bite for bite") + + regex = Regex("\\d\\d\\d\\d([- ])") + + testString = "card #1234-5678-1234" + assertTrue(regex.replaceFirst(testString, "xxxx$1") == "card #xxxx-5678-1234") + assertTrue(regex.replace(testString, "xxxx$1") == "card #xxxx-xxxx-1234") + + regex = Regex("(up|left)( *)(right|down)") + + testString = "left right, up down" + assertTrue(regex.replaceFirst(testString, "$3$2$1") == "right left, up down") + assertTrue(regex.replace(testString, "$3$2$1") == "right left, down up") + + regex = Regex("([CcPp][hl]e[ea]se)") + + testString = "I want cheese. Please." + assertTrue(regex.replaceFirst(testString, " $1 ") == "I want cheese . Please.") + assertTrue(regex.replace(testString, " $1 ") == "I want cheese . Please .") + } + + @Test fun testEscapes() { + var regex: Regex + var result: MatchResult? + + // Test \\ sequence + regex = Regex("([a-z]+)\\\\([a-z]+);") + result = regex.find("fred\\ginger;abbott\\costello;jekell\\hyde;") + assertNotNull(result) + assertEquals("fred", result!!.groupValues[1]) + assertEquals("ginger", result.groupValues[2]) + result = result.next() + assertNotNull(result) + assertEquals("abbott", result!!.groupValues[1]) + assertEquals("costello", result.groupValues[2]) + result = result.next() + assertNotNull(result) + assertEquals("jekell", result!!.groupValues[1]) + assertEquals("hyde", result.groupValues[2]) + assertNull(result.next()) + + // Test \n, \t, \r, \f, \e, \a sequences + regex = Regex("([a-z]+)[\\n\\t\\r\\f\\e\\a]+([a-z]+)") + result = regex.find("aa\nbb;cc\u0009\rdd;ee\u000C\u001Bff;gg\n\u0007hh") + assertNotNull(result) + assertEquals("aa", result!!.groupValues[1]) + assertEquals("bb", result.groupValues[2]) + result = result.next() + assertNotNull(result) + assertEquals("cc", result!!.groupValues[1]) + assertEquals("dd", result.groupValues[2]) + result = result.next() + assertNotNull(result) + assertEquals("ee", result!!.groupValues[1]) + assertEquals("ff", result.groupValues[2]) + result = result.next() + assertNotNull(result) + assertEquals("gg", result!!.groupValues[1]) + assertEquals("hh", result.groupValues[2]) + assertNull(result.next()) + + // Test \\u and \\x sequences + regex = Regex("([0-9]+)[\\u0020:\\x21];") + result = regex.find("11:;22 ;33-;44!;") + assertNotNull(result) + assertEquals("11", result!!.groupValues[1]) + result = result.next() + assertNotNull(result) + assertEquals("22", result!!.groupValues[1]) + result = result.next() + assertNotNull(result) + assertEquals("44", result!!.groupValues[1]) + assertNull(result.next()) + + // Test invalid unicode sequences // TODO: Double check it. + try { + regex = Regex("\\u") + fail("IllegalArgumentException expected") + } catch (e: IllegalArgumentException) { + } + + try { + regex = Regex("\\u;") + fail("IllegalArgumentException expected") + } catch (e: IllegalArgumentException) { + } + + try { + regex = Regex("\\u002") + fail("IllegalArgumentException expected") + } catch (e: IllegalArgumentException) { + } + + try { + regex = Regex("\\u002;") + fail("IllegalArgumentException expected") + } catch (e: IllegalArgumentException) { + } + + // Test invalid hex sequences + try { + regex = Regex("\\x") + fail("IllegalArgumentException expected") + } catch (e: IllegalArgumentException) { + } + + try { + regex = Regex("\\x;") + fail("IllegalArgumentException expected") + } catch (e: IllegalArgumentException) { + } + + try { + regex = Regex("\\xa") + fail("IllegalArgumentException expected") + } catch (e: IllegalArgumentException) { + } + + try { + regex = Regex("\\xa;") + fail("IllegalArgumentException expected") + } catch (e: IllegalArgumentException) { + } + + // Test \0 (octal) sequences (1, 2 and 3 digit) + regex = Regex("([0-9]+)[\\07\\040\\0160];") + result = regex.find("11\u0007;22:;33 ;44p;") + assertNotNull(result) + assertEquals("11", result!!.groupValues[1]) + result = result.next() + assertNotNull(result) + assertEquals("33", result!!.groupValues[1]) + result = result.next() + assertNotNull(result) + assertEquals("44", result!!.groupValues[1]) + assertNull(result.next()) + + // Test invalid octal sequences + try { + regex = Regex("\\08") + fail("IllegalArgumentException expected") + } catch (e: IllegalArgumentException) { + } + + try { + regex = Regex("\\0") + fail("IllegalArgumentException expected") + } catch (e: IllegalArgumentException) { + } + + try { + regex = Regex("\\0;") + fail("IllegalArgumentException expected") + } catch (e: IllegalArgumentException) { + } + + // Test \c (control character) sequence + regex = Regex("([0-9]+)[\\cA\\cB\\cC\\cD];") + result = regex.find("11\u0001;22:;33\u0002;44p;55\u0003;66\u0004;") + assertNotNull(result) + assertEquals("11", result!!.groupValues[1]) + result = result.next() + assertNotNull(result) + assertEquals("33", result!!.groupValues[1]) + result = result.next() + assertNotNull(result) + assertEquals("55", result!!.groupValues[1]) + result = result.next() + assertNotNull(result) + assertEquals("66", result!!.groupValues[1]) + assertNull(result.next()) + + // More thorough control escape test + // Ensure that each escape matches exactly the corresponding + // character + // code and no others (well, from 0-255 at least) + for (i in 0..25) { + regex = Regex("\\c${'A' + i}") + var match_char = -1 + for (j in 0..255) { + if (regex.matches("${j.toChar()}")) { + assertEquals(-1, match_char) + match_char = j + } + } + assertTrue(match_char == i + 1) + } + + + // Test invalid control escapes + try { + regex = Regex("\\c") + fail("IllegalArgumentException expected") + } catch (e: IllegalArgumentException) { + } + } + + @Test fun testCharacterClasses() { + var regex: Regex + + // Test one character range + regex = Regex("[p].*[l]") + assertTrue(regex.matches("paul")) + assertTrue(regex.matches("pool")) + assertFalse(regex.matches("pong")) + assertTrue(regex.matches("pl")) + + // Test two character range + regex = Regex("[pm].*[lp]") + assertTrue(regex.matches("prop")) + assertTrue(regex.matches("mall")) + assertFalse(regex.matches("pong")) + assertTrue(regex.matches("pill")) + + // Test range including [ and ] + regex = Regex("[<\\[].*[\\]>]") + assertTrue(regex.matches("")) + assertTrue(regex.matches("[bar]")) + assertFalse(regex.matches("{foobar]")) + assertTrue(regex.matches("") + assertTrue(regex.matches("")) + assertFalse(regex.matches("")) + val result = regex.find("xyz zzz") + assertNotNull(result) + assertNotNull(result!!.next()) + assertNull(result.next()!!.next()) + + // Test \S (not whitespace) // TODO: We've removed \f from string since kotlin doesn't recognize this escape in a string. + regex = Regex("<[a-z] \\S[0-9][\\S\n]+[^\\S]221>") + assertTrue(regex.matches("")) + assertTrue(regex.matches("")) + assertFalse(regex.matches("")) + assertTrue(regex.matches("")) + regex = Regex("<[a-z] \\S[0-9][\\S\n]+[^\\S]221[\\S&&[^abc]]>") + assertTrue(regex.matches("")) + assertTrue(regex.matches("")) + assertFalse(regex.matches("")) + assertFalse(regex.matches("")) + assertFalse(regex.matches("")) + assertTrue(regex.matches("")) + + // Test \w (ascii word) + regex = Regex("<\\w+\\s[0-9]+;[^\\w]\\w+/[\\w$]+;") + assertTrue(regex.matches(""); + * m = p.matcher(""); assertTrue(m.matches()); m = p.matcher(""); + * assertTrue(m.matches()); m = p.matcher(""); + * assertFalse(m.matches()); + */ + regex = Regex("\\p{Lower}+") + assertTrue(regex.matches("abcdefghijklmnopqrstuvwxyz")) + + // Invalid uses of \p{Lower} + try { + regex = Regex("\\p") + fail("IllegalArgumentException expected") + } catch (e: IllegalArgumentException) { + } + + try { + regex = Regex("\\p;") + fail("IllegalArgumentException expected") + } catch (e: IllegalArgumentException) { + } + + try { + regex = Regex("\\p{") + fail("IllegalArgumentException expected") + } catch (e: IllegalArgumentException) { + } + + try { + regex = Regex("\\p{;") + fail("IllegalArgumentException expected") + } catch (e: IllegalArgumentException) { + } + + try { + regex = Regex("\\p{Lower") + fail("IllegalArgumentException expected") + } catch (e: IllegalArgumentException) { + } + + try { + regex = Regex("\\p{Lower;") + fail("IllegalArgumentException expected") + } catch (e: IllegalArgumentException) { + } + + // Test \p{Upper} + /* + * FIXME: Requires complex range processing p = Regex("<\\p{Upper}\\d\\P{Upper}:[\\p{Upper}z]\\s[^\\P{Upper}]>"); + * m = p.matcher(""); assertTrue(m.matches()); m = p.matcher(""); + * assertTrue(m.matches()); m = p.matcher(""); + * assertFalse(m.matches()); + */ + regex = Regex("\\p{Upper}+") + assertTrue(regex.matches("ABCDEFGHIJKLMNOPQRSTUVWXYZ")) + + // Invalid uses of \p{Upper} + try { + regex = Regex("\\p{Upper") + fail("IllegalArgumentException expected") + } catch (e: IllegalArgumentException) { + } + + try { + regex = Regex("\\p{Upper;") + fail("IllegalArgumentException expected") + } catch (e: IllegalArgumentException) { + } + + // Test \p{ASCII} + /* + * FIXME: Requires complex range processing p = Regex("<\\p{ASCII}\\d\\P{ASCII}:[\\p{ASCII}\u1234]\\s[^\\P{ASCII}]>"); + * m = p.matcher(""); assertTrue(m.matches()); m = + * p.matcher(""); assertTrue(m.matches()); m = + * p.matcher("<\u00846#:E E>"); assertFalse(m.matches()) + */ + regex = Regex("\\p{ASCII}") + for (i in 0 until 0x80) { + assertTrue(regex.matches("${i.toChar()}")) + } + for (i in 0x80..0xff) { + assertFalse(regex.matches("${i.toChar()}")) + } + + // Invalid uses of \p{ASCII} + try { + regex = Regex("\\p{ASCII") + fail("IllegalArgumentException expected") + } catch (e: IllegalArgumentException) { + } + + try { + regex = Regex("\\p{ASCII;") + fail("IllegalArgumentException expected") + } catch (e: IllegalArgumentException) { + } + + // Test \p{Alpha} + // TODO + + // Test \p{Digit} + // TODO + + // Test \p{XDigit} + // TODO + + // Test \p{Alnum} + // TODO + + // Test \p{Punct} + // TODO + + // Test \p{Graph} + // TODO + + // Test \p{Print} + // TODO + + // Test \p{Blank} + // TODO + + // Test \p{Space} + // TODO + + // Test \p{Cntrl} + // TODO + } + + @Test fun testUnicodeCategories() { + // Test Unicode categories using \p and \P + // One letter codes: L, M, N, P, S, Z, C + // Two letter codes: Lu, Nd, Sc, Sm, ... + // See java.lang.Character and Unicode standard for complete list + // TODO + // Test \p{L} + // TODO + + // Test \p{N} + // TODO + + // ... etc + + // Test two letter codes: + // From unicode.org: + // Lu + // Ll + // Lt + // Lm + // Lo + // Mn + // Mc + // Me + // Nd + // Nl + // No + // Pc + // Pd + // Ps + // Pe + // Pi + // Pf + // Po + // Sm + // Sc + // Sk + // So + // Zs + // Zl + // Zp + // Cc + // Cf + // Cs + // Co + // Cn + } + + @Test fun testUnicodeBlocks() { + var regex: Regex + + // Test Unicode blocks using \p and \P + for (block in UBlocks) { + regex = Regex("\\p{In" + block.name + "}") + if (block.low > 0) { + assertFalse(regex.matches((block.low - 1).toChar().toString())) + } + for (i in block.low..block.high) { + assertTrue(regex.matches(i.toChar().toString())) + } + if (block.high < 0xFFFF) { + assertFalse(regex.matches((block.high + 1).toChar().toString())) + } + + regex = Regex("\\P{In" + block.name + "}") + if (block.low > 0) { + assertTrue(regex.matches((block.low - 1).toChar().toString())) + } + for (i in block.low..block.high) { + assertFalse("assert: Regex: $regex, match to: ${i.toChar()} ($i)", regex.matches(i.toChar().toString())) + } + if (block.high < 0xFFFF) { + assertTrue(regex.matches((block.high + 1).toChar().toString())) + } + + } + } + + @Test fun testCapturingGroups() { + // Test simple capturing groups + // TODO + + // Test grouping without capture (?:...) + // TODO + + // Test combination of grouping and capture + // TODO + + // Test \ sequence with capturing and non-capturing groups + // TODO + + // Test \ with out of range + // TODO + } + + @Test fun testRepeats() { + // Test ? + // TODO + + // Test * + // TODO + + // Test + + // TODO + + // Test {}, including 0, 1 and more + // TODO + + // Test {,}, including 0, 1 and more + // TODO + + // Test {,}, with n1 < n2, n1 = n2 and n1 > n2 (illegal?) + // TODO + } + + @Test fun testAnchors() { + // Test ^, default and MULTILINE + // TODO + + // Test $, default and MULTILINE + // TODO + + // Test \b (word boundary) + // TODO + + // Test \B (not a word boundary) + // TODO + + // Test \A (beginning of string) + // TODO + + // Test \Z (end of string) + // TODO + + // Test \z (end of string) + // TODO + + // Test \G + // TODO + + // Test positive lookahead using (?=...) + // TODO + + // Test negative lookahead using (?!...) + // TODO + + // Test positive lookbehind using (?<=...) + // TODO + + // Test negative lookbehind using (?...) + // TODO + + // Test (?onflags-offflags) + // Valid flags are i,m,d,s,u,x + // TODO + + // Test (?onflags-offflags:...) + // TODO + + // Test \Q, \E + regex = Regex("[a-z]+;\\Q[a-z]+;\\Q(foo.*);\\E[0-9]+") + assertTrue(regex.matches("abc;[a-z]+;\\Q(foo.*);411")) + assertFalse(regex.matches("abc;def;foo42;555")) + assertFalse(regex.matches("abc;\\Qdef;\\Qfoo99;\\E123")) + + regex = Regex("[a-z]+;(foo[0-9]-\\Q(...)\\E);[0-9]+") + val result = regex.matchEntire("abc;foo5-(...);123") + assertNotNull(result) + assertEquals("foo5-(...)", result!!.groupValues[1]) + assertFalse(regex.matches("abc;foo9-(xxx);789")) + + regex = Regex("[a-z]+;(bar[0-9]-[a-z\\Q$-\\E]+);[0-9]+") + assertTrue(regex.matches("abc;bar0-def$-;123")) + + regex = Regex("[a-z]+;(bar[0-9]-[a-z\\Q-$\\E]+);[0-9]+") + assertTrue(regex.matches("abc;bar0-def$-;123")) + + regex = Regex("[a-z]+;(bar[0-9]-[a-z\\Q[0-9]\\E]+);[0-9]+") + assertTrue(regex.matches("abc;bar0-def[99]-]0x[;123")); + + regex = Regex("[a-z]+;(bar[0-9]-[a-z\\[0\\-9\\]]+);[0-9]+") + assertTrue(regex.matches("abc;bar0-def[99]-]0x[;123")) + + // Test # + // TODO + } + + @Test fun testCompile1() { + val regex = Regex("[0-9A-Za-z][0-9A-Za-z\\x2e\\x3a\\x2d\\x5f]*") + val name = "iso-8859-1" + assertTrue(regex.matches(name)) + } + + @Test fun testCompile2() { + val findString = "\\Qimport\\E" + val regex = Regex(findString) + assertTrue(regex in "import a.A;\n\n import b.B;\nclass C {}") + } + + @Test fun testCompile3() { + var regex: Regex + var result: MatchResult? + + regex = Regex("a$") + result = regex.find("a\n") + assertNotNull(result) + assertEquals("a", result!!.value) + assertNull(result.next()) + + regex = Regex("(a$)") + result = regex.find("a\n") + assertNotNull(result) + assertEquals("a", result!!.value) + assertEquals("a", result.groupValues[1]) + assertNull(result.next()) + + regex = Regex("^.*$", RegexOption.MULTILINE) + + result = regex.find("a\n") + assertNotNull(result) + assertEquals("a", result!!.value) + assertNull(result.next()) + + result = regex.find("a\nb\n") + assertNotNull(result) + assertEquals("a", result!!.value) + result = result.next() + assertNotNull(result) + assertEquals("b", result!!.value) + assertNull(result.next()) + + result = regex.find("a\nb") + assertNotNull(result) + assertEquals("a", result!!.value) + result = result.next() + assertNotNull(result) + assertEquals("b", result!!.value) + assertNull(result.next()) + + result = regex.find("\naa\r\nbb\rcc\n\n") + assertNotNull(result) + assertTrue(result!!.value == "") + result = result.next() + assertNotNull(result) + assertEquals("aa", result!!.value) + result = result.next() + assertNotNull(result) + assertEquals("bb", result!!.value) + result = result.next() + assertNotNull(result) + assertEquals("cc", result!!.value) + result = result.next() + assertNotNull(result) + assertTrue(result!!.value == "") + assertNull(result.next()) + + result = regex.find("a") + assertNotNull(result) + assertEquals("a", result!!.value) + assertNull(result.next()) + + result = regex.find("") + assertNull(result) + + regex = Regex("^.*$") + result = regex.find("") + assertNotNull(result) + assertTrue(result!!.value == "") + assertNull(result.next()) + } + + @Test fun testCompile4() { + val findString = "\\Qpublic\\E" + val text = StringBuilder(" public class Class {\n" + " public class Class {") + val regex = Regex(findString) + + val result = regex.find(text) + assertNotNull(result) + assertEquals(4, result!!.range.start) + + // modify text + text.setLength(0) + text.append("Text have been changed.") + + assertNull(regex.find(text)) + } + + @Test fun testCompile5() { + val p = Regex("^[0-9]") + val s = p.split("12", 0) + assertEquals("", s[0]) + assertEquals("2", s[1]) + assertEquals(2, s.size) + } + + private class UBInfo(var low: Int, var high: Int, var name: String) + + // A table representing the unicode categories + // private static UBInfo[] UCategories = { + // Lu + // Ll + // Lt + // Lm + // Lo + // Mn + // Mc + // Me + // Nd + // Nl + // No + // Pc + // Pd + // Ps + // Pe + // Pi + // Pf + // Po + // Sm + // Sc + // Sk + // So + // Zs + // Zl + // Zp + // Cc + // Cf + // Cs + // Co + // Cn + // }; + + // A table representing the unicode character blocks + private val UBlocks = arrayOf( + /* 0000; 007F; Basic Latin */ + UBInfo(0x0000, 0x007F, "BasicLatin"), // Character.UnicodeBlock.BASIC_LATIN + /* 0080; 00FF; Latin-1 Supplement */ + UBInfo(0x0080, 0x00FF, "Latin-1Supplement"), // Character.UnicodeBlock.LATIN_1_SUPPLEMENT + /* 0100; 017F; Latin Extended-A */ + UBInfo(0x0100, 0x017F, "LatinExtended-A"), // Character.UnicodeBlock.LATIN_EXTENDED_A + /* 0180; 024F; Latin Extended-B */ + // new UBInfo (0x0180,0x024F,"InLatinExtended-B"), // + // Character.UnicodeBlock.LATIN_EXTENDED_B + /* 0250; 02AF; IPA Extensions */ + UBInfo(0x0250, 0x02AF, "IPAExtensions"), // Character.UnicodeBlock.IPA_EXTENSIONS + /* 02B0; 02FF; Spacing Modifier Letters */ + UBInfo(0x02B0, 0x02FF, "SpacingModifierLetters"), // Character.UnicodeBlock.SPACING_MODIFIER_LETTERS + /* 0300; 036F; Combining Diacritical Marks */ + UBInfo(0x0300, 0x036F, "CombiningDiacriticalMarks"), // Character.UnicodeBlock.COMBINING_DIACRITICAL_MARKS + /* 0370; 03FF; Greek */ + UBInfo(0x0370, 0x03FF, "Greek"), // Character.UnicodeBlock.GREEK + /* 0400; 04FF; Cyrillic */ + UBInfo(0x0400, 0x04FF, "Cyrillic"), // Character.UnicodeBlock.CYRILLIC + /* 0530; 058F; Armenian */ + UBInfo(0x0530, 0x058F, "Armenian"), // Character.UnicodeBlock.ARMENIAN + /* 0590; 05FF; Hebrew */ + UBInfo(0x0590, 0x05FF, "Hebrew"), // Character.UnicodeBlock.HEBREW + /* 0600; 06FF; Arabic */ + UBInfo(0x0600, 0x06FF, "Arabic"), // Character.UnicodeBlock.ARABIC + /* 0700; 074F; Syriac */ + UBInfo(0x0700, 0x074F, "Syriac"), // Character.UnicodeBlock.SYRIAC + /* 0780; 07BF; Thaana */ + UBInfo(0x0780, 0x07BF, "Thaana"), // Character.UnicodeBlock.THAANA + /* 0900; 097F; Devanagari */ + UBInfo(0x0900, 0x097F, "Devanagari"), // Character.UnicodeBlock.DEVANAGARI + /* 0980; 09FF; Bengali */ + UBInfo(0x0980, 0x09FF, "Bengali"), // Character.UnicodeBlock.BENGALI + /* 0A00; 0A7F; Gurmukhi */ + UBInfo(0x0A00, 0x0A7F, "Gurmukhi"), // Character.UnicodeBlock.GURMUKHI + /* 0A80; 0AFF; Gujarati */ + UBInfo(0x0A80, 0x0AFF, "Gujarati"), // Character.UnicodeBlock.GUJARATI + /* 0B00; 0B7F; Oriya */ + UBInfo(0x0B00, 0x0B7F, "Oriya"), // Character.UnicodeBlock.ORIYA + /* 0B80; 0BFF; Tamil */ + UBInfo(0x0B80, 0x0BFF, "Tamil"), // Character.UnicodeBlock.TAMIL + /* 0C00; 0C7F; Telugu */ + UBInfo(0x0C00, 0x0C7F, "Telugu"), // Character.UnicodeBlock.TELUGU + /* 0C80; 0CFF; Kannada */ + UBInfo(0x0C80, 0x0CFF, "Kannada"), // Character.UnicodeBlock.KANNADA + /* 0D00; 0D7F; Malayalam */ + UBInfo(0x0D00, 0x0D7F, "Malayalam"), // Character.UnicodeBlock.MALAYALAM + /* 0D80; 0DFF; Sinhala */ + UBInfo(0x0D80, 0x0DFF, "Sinhala"), // Character.UnicodeBlock.SINHALA + /* 0E00; 0E7F; Thai */ + UBInfo(0x0E00, 0x0E7F, "Thai"), // Character.UnicodeBlock.THAI + /* 0E80; 0EFF; Lao */ + UBInfo(0x0E80, 0x0EFF, "Lao"), // Character.UnicodeBlock.LAO + /* 0F00; 0FFF; Tibetan */ + UBInfo(0x0F00, 0x0FFF, "Tibetan"), // Character.UnicodeBlock.TIBETAN + /* 1000; 109F; Myanmar */ + UBInfo(0x1000, 0x109F, "Myanmar"), // Character.UnicodeBlock.MYANMAR + /* 10A0; 10FF; Georgian */ + UBInfo(0x10A0, 0x10FF, "Georgian"), // Character.UnicodeBlock.GEORGIAN + /* 1100; 11FF; Hangul Jamo */ + UBInfo(0x1100, 0x11FF, "HangulJamo"), // Character.UnicodeBlock.HANGUL_JAMO + /* 1200; 137F; Ethiopic */ + UBInfo(0x1200, 0x137F, "Ethiopic"), // Character.UnicodeBlock.ETHIOPIC + /* 13A0; 13FF; Cherokee */ + UBInfo(0x13A0, 0x13FF, "Cherokee"), // Character.UnicodeBlock.CHEROKEE + /* 1400; 167F; Unified Canadian Aboriginal Syllabics */ + UBInfo(0x1400, 0x167F, "UnifiedCanadianAboriginalSyllabics"), // Character.UnicodeBlock.UNIFIED_CANADIAN_ABORIGINAL_SYLLABICS + /* 1680; 169F; Ogham */ + UBInfo(0x1680, 0x169F, "Ogham"), // Character.UnicodeBlock.OGHAM + /* 16A0; 16FF; Runic */ + UBInfo(0x16A0, 0x16FF, "Runic"), // Character.UnicodeBlock.RUNIC + /* 1780; 17FF; Khmer */ + UBInfo(0x1780, 0x17FF, "Khmer"), // Character.UnicodeBlock.KHMER + /* 1800; 18AF; Mongolian */ + UBInfo(0x1800, 0x18AF, "Mongolian"), // Character.UnicodeBlock.MONGOLIAN + /* 1E00; 1EFF; Latin Extended Additional */ + UBInfo(0x1E00, 0x1EFF, "LatinExtendedAdditional"), // Character.UnicodeBlock.LATIN_EXTENDED_ADDITIONAL + /* 1F00; 1FFF; Greek Extended */ + UBInfo(0x1F00, 0x1FFF, "GreekExtended"), // Character.UnicodeBlock.GREEK_EXTENDED + /* 2000; 206F; General Punctuation */ + UBInfo(0x2000, 0x206F, "GeneralPunctuation"), // Character.UnicodeBlock.GENERAL_PUNCTUATION + /* 2070; 209F; Superscripts and Subscripts */ + UBInfo(0x2070, 0x209F, "SuperscriptsandSubscripts"), // Character.UnicodeBlock.SUPERSCRIPTS_AND_SUBSCRIPTS + /* 20A0; 20CF; Currency Symbols */ + UBInfo(0x20A0, 0x20CF, "CurrencySymbols"), // Character.UnicodeBlock.CURRENCY_SYMBOLS + /* 20D0; 20FF; Combining Marks for Symbols */ + UBInfo(0x20D0, 0x20FF, "CombiningMarksforSymbols"), // Character.UnicodeBlock.COMBINING_MARKS_FOR_SYMBOLS + /* 2100; 214F; Letterlike Symbols */ + UBInfo(0x2100, 0x214F, "LetterlikeSymbols"), // Character.UnicodeBlock.LETTERLIKE_SYMBOLS + /* 2150; 218F; Number Forms */ + UBInfo(0x2150, 0x218F, "NumberForms"), // Character.UnicodeBlock.NUMBER_FORMS + /* 2190; 21FF; Arrows */ + UBInfo(0x2190, 0x21FF, "Arrows"), // Character.UnicodeBlock.ARROWS + /* 2200; 22FF; Mathematical Operators */ + UBInfo(0x2200, 0x22FF, "MathematicalOperators"), // Character.UnicodeBlock.MATHEMATICAL_OPERATORS + /* 2300; 23FF; Miscellaneous Technical */ + UBInfo(0x2300, 0x23FF, "MiscellaneousTechnical"), // Character.UnicodeBlock.MISCELLANEOUS_TECHNICAL + /* 2400; 243F; Control Pictures */ + UBInfo(0x2400, 0x243F, "ControlPictures"), // Character.UnicodeBlock.CONTROL_PICTURES + /* 2440; 245F; Optical Character Recognition */ + UBInfo(0x2440, 0x245F, "OpticalCharacterRecognition"), // Character.UnicodeBlock.OPTICAL_CHARACTER_RECOGNITION + /* 2460; 24FF; Enclosed Alphanumerics */ + UBInfo(0x2460, 0x24FF, "EnclosedAlphanumerics"), // Character.UnicodeBlock.ENCLOSED_ALPHANUMERICS + /* 2500; 257F; Box Drawing */ + UBInfo(0x2500, 0x257F, "BoxDrawing"), // Character.UnicodeBlock.BOX_DRAWING + /* 2580; 259F; Block Elements */ + UBInfo(0x2580, 0x259F, "BlockElements"), // Character.UnicodeBlock.BLOCK_ELEMENTS + /* 25A0; 25FF; Geometric Shapes */ + UBInfo(0x25A0, 0x25FF, "GeometricShapes"), // Character.UnicodeBlock.GEOMETRIC_SHAPES + /* 2600; 26FF; Miscellaneous Symbols */ + UBInfo(0x2600, 0x26FF, "MiscellaneousSymbols"), // Character.UnicodeBlock.MISCELLANEOUS_SYMBOLS + /* 2700; 27BF; Dingbats */ + UBInfo(0x2700, 0x27BF, "Dingbats"), // Character.UnicodeBlock.DINGBATS + /* 2800; 28FF; Braille Patterns */ + UBInfo(0x2800, 0x28FF, "BraillePatterns"), // Character.UnicodeBlock.BRAILLE_PATTERNS + /* 2E80; 2EFF; CJK Radicals Supplement */ + UBInfo(0x2E80, 0x2EFF, "CJKRadicalsSupplement"), // Character.UnicodeBlock.CJK_RADICALS_SUPPLEMENT + /* 2F00; 2FDF; Kangxi Radicals */ + UBInfo(0x2F00, 0x2FDF, "KangxiRadicals"), // Character.UnicodeBlock.KANGXI_RADICALS + /* 2FF0; 2FFF; Ideographic Description Characters */ + UBInfo(0x2FF0, 0x2FFF, "IdeographicDescriptionCharacters"), // Character.UnicodeBlock.IDEOGRAPHIC_DESCRIPTION_CHARACTERS + /* 3000; 303F; CJK Symbols and Punctuation */ + UBInfo(0x3000, 0x303F, "CJKSymbolsandPunctuation"), // Character.UnicodeBlock.CJK_SYMBOLS_AND_PUNCTUATION + /* 3040; 309F; Hiragana */ + UBInfo(0x3040, 0x309F, "Hiragana"), // Character.UnicodeBlock.HIRAGANA + /* 30A0; 30FF; Katakana */ + UBInfo(0x30A0, 0x30FF, "Katakana"), // Character.UnicodeBlock.KATAKANA + /* 3100; 312F; Bopomofo */ + UBInfo(0x3100, 0x312F, "Bopomofo"), // Character.UnicodeBlock.BOPOMOFO + /* 3130; 318F; Hangul Compatibility Jamo */ + UBInfo(0x3130, 0x318F, "HangulCompatibilityJamo"), // Character.UnicodeBlock.HANGUL_COMPATIBILITY_JAMO + /* 3190; 319F; Kanbun */ + UBInfo(0x3190, 0x319F, "Kanbun"), // Character.UnicodeBlock.KANBUN + /* 31A0; 31BF; Bopomofo Extended */ + UBInfo(0x31A0, 0x31BF, "BopomofoExtended"), // Character.UnicodeBlock.BOPOMOFO_EXTENDED + /* 3200; 32FF; Enclosed CJK Letters and Months */ + UBInfo(0x3200, 0x32FF, "EnclosedCJKLettersandMonths"), // Character.UnicodeBlock.ENCLOSED_CJK_LETTERS_AND_MONTHS + /* 3300; 33FF; CJK Compatibility */ + UBInfo(0x3300, 0x33FF, "CJKCompatibility"), // Character.UnicodeBlock.CJK_COMPATIBILITY + /* 3400; 4DB5; CJK Unified Ideographs Extension A */ + UBInfo(0x3400, 0x4DB5, "CJKUnifiedIdeographsExtensionA"), // Character.UnicodeBlock.CJK_UNIFIED_IDEOGRAPHS_EXTENSION_A + /* 4E00; 9FFF; CJK Unified Ideographs */ + UBInfo(0x4E00, 0x9FFF, "CJKUnifiedIdeographs"), // Character.UnicodeBlock.CJK_UNIFIED_IDEOGRAPHS + /* A000; A48F; Yi Syllables */ + UBInfo(0xA000, 0xA48F, "YiSyllables"), // Character.UnicodeBlock.YI_SYLLABLES + /* A490; A4CF; Yi Radicals */ + UBInfo(0xA490, 0xA4CF, "YiRadicals"), // Character.UnicodeBlock.YI_RADICALS + /* AC00; D7A3; Hangul Syllables */ + UBInfo(0xAC00, 0xD7A3, "HangulSyllables"), // Character.UnicodeBlock.HANGUL_SYLLABLES + /* D800; DB7F; High Surrogates */ + /* DB80; DBFF; High Private Use Surrogates */ + /* DC00; DFFF; Low Surrogates */ + /* E000; F8FF; Private Use */ + /* F900; FAFF; CJK Compatibility Ideographs */ + UBInfo(0xF900, 0xFAFF, "CJKCompatibilityIdeographs"), // Character.UnicodeBlock.CJK_COMPATIBILITY_IDEOGRAPHS + /* FB00; FB4F; Alphabetic Presentation Forms */ + UBInfo(0xFB00, 0xFB4F, "AlphabeticPresentationForms"), // Character.UnicodeBlock.ALPHABETIC_PRESENTATION_FORMS + /* FB50; FDFF; Arabic Presentation Forms-A */ + UBInfo(0xFB50, 0xFDFF, "ArabicPresentationForms-A"), // Character.UnicodeBlock.ARABIC_PRESENTATION_FORMS_A + /* FE20; FE2F; Combining Half Marks */ + UBInfo(0xFE20, 0xFE2F, "CombiningHalfMarks"), // Character.UnicodeBlock.COMBINING_HALF_MARKS + /* FE30; FE4F; CJK Compatibility Forms */ + UBInfo(0xFE30, 0xFE4F, "CJKCompatibilityForms"), // Character.UnicodeBlock.CJK_COMPATIBILITY_FORMS + /* FE50; FE6F; Small Form Variants */ + UBInfo(0xFE50, 0xFE6F, "SmallFormVariants"), // Character.UnicodeBlock.SMALL_FORM_VARIANTS + /* FE70; FEFE; Arabic Presentation Forms-B */ + // new UBInfo (0xFE70,0xFEFE,"InArabicPresentationForms-B"), // + // Character.UnicodeBlock.ARABIC_PRESENTATION_FORMS_B + /* FEFF; FEFF; Specials */ + UBInfo(0xFEFF, 0xFEFF, "Specials"), // Character.UnicodeBlock.SPECIALS + /* FF00; FFEF; Halfwidth and Fullwidth Forms */ + UBInfo(0xFF00, 0xFFEF, "HalfwidthandFullwidthForms"), // Character.UnicodeBlock.HALFWIDTH_AND_FULLWIDTH_FORMS + /* FFF0; FFFD; Specials */ + UBInfo(0xFFF0, 0xFFFD, "Specials") // Character.UnicodeBlock.SPECIALS + ) +} diff --git a/kotlin-native/backend.native/tests/harmony_regex/ReplaceTest.kt b/kotlin-native/backend.native/tests/harmony_regex/ReplaceTest.kt new file mode 100644 index 00000000000..9f888d01bf4 --- /dev/null +++ b/kotlin-native/backend.native/tests/harmony_regex/ReplaceTest.kt @@ -0,0 +1,84 @@ +/* Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package test.text.harmony_regex + +import kotlin.text.* +import kotlin.test.* + +class ReplaceTest { + + @Test fun testSimpleReplace() { + val target: String + val pattern: String + val repl: String + + target = "foobarfobarfoofo1" + pattern = "fo[^o]" + repl = "xxx" + + val regex = Regex(pattern) + + assertEquals("foobarxxxarfoofo1", regex.replaceFirst(target, repl)) + assertEquals("foobarxxxarfooxxx", regex.replace(target, repl)) + } + + @Test fun testCaptureReplace() { + var target: String + var pattern: String + var repl: String + var s: String + var regex: Regex + + target = "[31]foo;bar[42];[99]xyz" + pattern = "\\[([0-9]+)\\]([a-z]+)" + repl = "$2[$1]" + + regex = Regex(pattern) + s = regex.replaceFirst(target, repl) + assertEquals("foo[31];bar[42];[99]xyz", s) + s = regex.replace(target, repl) + assertEquals("foo[31];bar[42];xyz[99]", s) + + target = "[31]foo(42)bar{63}zoo;[12]abc(34)def{56}ghi;{99}xyz[88]xyz(77)xyz;" + pattern = "\\[([0-9]+)\\]([a-z]+)\\(([0-9]+)\\)([a-z]+)\\{([0-9]+)\\}([a-z]+)" + repl = "[$5]$6($3)$4{$1}$2" + regex = Regex(pattern) + s = regex.replaceFirst(target, repl) + assertEquals("[63]zoo(42)bar{31}foo;[12]abc(34)def{56}ghi;{99}xyz[88]xyz(77)xyz;", s) + s = regex.replace(target, repl) + assertEquals("[63]zoo(42)bar{31}foo;[56]ghi(34)def{12}abc;{99}xyz[88]xyz(77)xyz;", s) + } + + @Test fun testEscapeReplace() { + val target: String + val pattern: String + var repl: String + var s: String + + target = "foo'bar''foo" + pattern = "'" + repl = "\\'" + s = target.replace(pattern.toRegex(), repl) + assertEquals("foo'bar''foo", s) + repl = "\\\\'" + s = target.replace(pattern.toRegex(), repl) + assertEquals("foo\\'bar\\'\\'foo", s) + repl = "\\$3" + s = target.replace(pattern.toRegex(), repl) + assertEquals("foo$3bar$3$3foo", s) + } +} diff --git a/kotlin-native/backend.native/tests/harmony_regex/SplitTest.kt b/kotlin-native/backend.native/tests/harmony_regex/SplitTest.kt new file mode 100644 index 00000000000..932fdb956d3 --- /dev/null +++ b/kotlin-native/backend.native/tests/harmony_regex/SplitTest.kt @@ -0,0 +1,156 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package test.text.harmony_regex + +import kotlin.text.* +import kotlin.test.* + +class SplitTest { + + @Test fun testSimple() { + val p = Regex("/") + val results = p.split("have/you/done/it/right") + val expected = arrayOf("have", "you", "done", "it", "right") + assertEquals(expected.size, results.size) + for (i in expected.indices) { + assertEquals(results[i], expected[i]) + } + } + + @Test fun testSplit1() { + var p = Regex(" ") + + val input = "poodle zoo" + var tokens: List + + tokens = p.split(input, 1) + assertEquals(1, tokens.size) + assertTrue(tokens[0] == input) + tokens = p.split(input, 2) + assertEquals(2, tokens.size) + assertEquals("poodle", tokens[0]) + assertEquals("zoo", tokens[1]) + tokens = p.split(input, 5) + assertEquals(2, tokens.size) + assertEquals("poodle", tokens[0]) + assertEquals("zoo", tokens[1]) + tokens = p.split(input, 0) + assertEquals(2, tokens.size) + assertEquals("poodle", tokens[0]) + assertEquals("zoo", tokens[1]) + tokens = p.split(input) + assertEquals(2, tokens.size) + assertEquals("poodle", tokens[0]) + assertEquals("zoo", tokens[1]) + + p = Regex("d") + + tokens = p.split(input, 1) + assertEquals(1, tokens.size) + assertTrue(tokens[0] == input) + tokens = p.split(input, 2) + assertEquals(2, tokens.size) + assertEquals("poo", tokens[0]) + assertEquals("le zoo", tokens[1]) + tokens = p.split(input, 5) + assertEquals(2, tokens.size) + assertEquals("poo", tokens[0]) + assertEquals("le zoo", tokens[1]) + tokens = p.split(input, 0) + assertEquals(2, tokens.size) + assertEquals("poo", tokens[0]) + assertEquals("le zoo", tokens[1]) + tokens = p.split(input) + assertEquals(2, tokens.size) + assertEquals("poo", tokens[0]) + assertEquals("le zoo", tokens[1]) + + p = Regex("o") + + tokens = p.split(input, 1) + assertEquals(1, tokens.size) + assertTrue(tokens[0] == input) + tokens = p.split(input, 2) + assertEquals(2, tokens.size) + assertEquals("p", tokens[0]) + assertEquals("odle zoo", tokens[1]) + tokens = p.split(input, 5) + assertEquals(5, tokens.size) + assertEquals("p", tokens[0]) + assertTrue(tokens[1] == "") + assertEquals("dle z", tokens[2]) + assertTrue(tokens[3] == "") + assertTrue(tokens[4] == "") + tokens = p.split(input, 0) + assertEquals(5, tokens.size) + assertEquals("p", tokens[0]) + assertTrue(tokens[1] == "") + assertEquals("dle z", tokens[2]) + assertTrue(tokens[3] == "") + assertTrue(tokens[4] == "") + tokens = p.split(input) + assertEquals(5, tokens.size) + assertEquals("p", tokens[0]) + assertTrue(tokens[1] == "") + assertEquals("dle z", tokens[2]) + assertTrue(tokens[3] == "") + assertTrue(tokens[4] == "") + } + + @Test fun testSplit2() { + val p = Regex("") + var s: List + s = p.split("a", 0) + assertEquals(3, s.size) + assertEquals("", s[0]) + assertEquals("a", s[1]) + assertEquals("", s[2]) + + s = p.split("", 0) + assertEquals(2, s.size) + assertEquals("", s[0]) + assertEquals("", s[1]) + + s = p.split("abcd", 0) + assertEquals(6, s.size) + assertEquals("", s[0]) + assertEquals("a", s[1]) + assertEquals("b", s[2]) + assertEquals("c", s[3]) + assertEquals("d", s[4]) + assertEquals("", s[5]) + } + + @Test fun testSplitSupplementaryWithEmptyString() { + + /* + * See http://www.unicode.org/reports/tr18/#Supplementary_Characters We + * have to treat text as code points not code units. + */ + val p = Regex("") + val s: List + s = p.split("a\ud869\uded6b", 0) + assertEquals(5, s.size) + assertEquals("", s[0]) + assertEquals("a", s[1]) + assertEquals("\ud869\uded6", s[2]) + assertEquals("b", s[3]) + assertEquals("", s[4]) + } + +} diff --git a/kotlin-native/backend.native/tests/interop/auxiliary_sources/auxiliaryCppSources.def b/kotlin-native/backend.native/tests/interop/auxiliary_sources/auxiliaryCppSources.def new file mode 100644 index 00000000000..e69de29bb2d diff --git a/kotlin-native/backend.native/tests/interop/auxiliary_sources/main.kt b/kotlin-native/backend.native/tests/interop/auxiliary_sources/main.kt new file mode 100644 index 00000000000..69873293e18 --- /dev/null +++ b/kotlin-native/backend.native/tests/interop/auxiliary_sources/main.kt @@ -0,0 +1,7 @@ +import auxiliaryCppSources.* +import kotlin.test.* +import kotlinx.cinterop.* + +fun main() { + assertEquals(name()!!.toKString(), "Hello from C++") +} \ No newline at end of file diff --git a/kotlin-native/backend.native/tests/interop/auxiliary_sources/name.cpp b/kotlin-native/backend.native/tests/interop/auxiliary_sources/name.cpp new file mode 100644 index 00000000000..14f6b211d85 --- /dev/null +++ b/kotlin-native/backend.native/tests/interop/auxiliary_sources/name.cpp @@ -0,0 +1,8 @@ +#include +#include "name.h" + +static std::string _name = "Hello from C++"; + +const char* name() { + return _name.c_str(); +} \ No newline at end of file diff --git a/kotlin-native/backend.native/tests/interop/auxiliary_sources/name.h b/kotlin-native/backend.native/tests/interop/auxiliary_sources/name.h new file mode 100644 index 00000000000..9235363abdb --- /dev/null +++ b/kotlin-native/backend.native/tests/interop/auxiliary_sources/name.h @@ -0,0 +1,9 @@ +#ifdef __cplusplus +extern "C" { +#endif + +const char* name(); + +#ifdef __cplusplus +} +#endif \ No newline at end of file diff --git a/kotlin-native/backend.native/tests/interop/basics/0.kt b/kotlin-native/backend.native/tests/interop/basics/0.kt new file mode 100644 index 00000000000..ffcda1a9244 --- /dev/null +++ b/kotlin-native/backend.native/tests/interop/basics/0.kt @@ -0,0 +1,14 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +import sysstat.* +import kotlinx.cinterop.* + +fun main(args: Array) { + val statBuf = nativeHeap.alloc() + val res = stat("/", statBuf.ptr) + println(res) + println(statBuf.st_uid) +} \ No newline at end of file diff --git a/kotlin-native/backend.native/tests/interop/basics/1.kt b/kotlin-native/backend.native/tests/interop/basics/1.kt new file mode 100644 index 00000000000..5abf6cdce93 --- /dev/null +++ b/kotlin-native/backend.native/tests/interop/basics/1.kt @@ -0,0 +1,17 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +import cstdlib.* +import kotlinx.cinterop.* + +fun main(args: Array) { + println(atoi("257")) + + val divResult = div(-5, 3) + val (quot, rem) = divResult.useContents { Pair(quot, rem) } + println(quot) + println(rem) + +} \ No newline at end of file diff --git a/kotlin-native/backend.native/tests/interop/basics/2.kt b/kotlin-native/backend.native/tests/interop/basics/2.kt new file mode 100644 index 00000000000..da76c28a84b --- /dev/null +++ b/kotlin-native/backend.native/tests/interop/basics/2.kt @@ -0,0 +1,10 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +import cstdio.* + +fun main(args: Array) { + puts("Hello") +} \ No newline at end of file diff --git a/kotlin-native/backend.native/tests/interop/basics/3.kt b/kotlin-native/backend.native/tests/interop/basics/3.kt new file mode 100644 index 00000000000..7f3cb8d81f4 --- /dev/null +++ b/kotlin-native/backend.native/tests/interop/basics/3.kt @@ -0,0 +1,24 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +import kotlinx.cinterop.* + +fun main(args: Array) { + val values = intArrayOf(14, 12, 9, 13, 8) + val count = values.size + + cstdlib.qsort(values.refTo(0), count.convert(), IntVar.size.convert(), staticCFunction { a, b -> + val aValue = a!!.reinterpret()[0] + val bValue = b!!.reinterpret()[0] + + (aValue - bValue) + }) + + for (i in 0..count - 1) { + print(values[i]) + print(" ") + } + println() +} diff --git a/kotlin-native/backend.native/tests/interop/basics/4.kt b/kotlin-native/backend.native/tests/interop/basics/4.kt new file mode 100644 index 00000000000..f76c55105f1 --- /dev/null +++ b/kotlin-native/backend.native/tests/interop/basics/4.kt @@ -0,0 +1,22 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +import cstdio.* +import kotlinx.cinterop.* + +val stdout + get() = getStdout() + +fun main(args: Array) { + fprintf(stdout, "%s %s %d %d %d %lld %.1f %.1lf %d %d\n", + "a", "b".cstr, (-1).toByte(), 2.toShort(), 3, Long.MAX_VALUE, 0.1.toFloat(), 0.2, true, false) + + memScoped { + val aVar = alloc() + val bVar = alloc() + val sscanfResult = sscanf("42", "%d%d", aVar.ptr, bVar.ptr) + printf("%d %d\n", sscanfResult, aVar.value) + } +} \ No newline at end of file diff --git a/kotlin-native/backend.native/tests/interop/basics/5.kt b/kotlin-native/backend.native/tests/interop/basics/5.kt new file mode 100644 index 00000000000..a4b15a66c44 --- /dev/null +++ b/kotlin-native/backend.native/tests/interop/basics/5.kt @@ -0,0 +1,12 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +import platform.posix.printf + +val golden = immutableBlobOf(0x48, 0x65, 0x6C, 0x6C, 0x6F, 0x21, 0x00).asCPointer(0) + +fun main(args: Array) { + printf("%s\n", golden) +} diff --git a/kotlin-native/backend.native/tests/interop/basics/arrayPointers.kt b/kotlin-native/backend.native/tests/interop/basics/arrayPointers.kt new file mode 100644 index 00000000000..06ea7067b47 --- /dev/null +++ b/kotlin-native/backend.native/tests/interop/basics/arrayPointers.kt @@ -0,0 +1,16 @@ +import carrayPointers.* +import kotlin.test.* +import kotlinx.cinterop.* + +fun main() { + arrayPointer = globalArray + assertEquals(globalArray[0], arrayPointer!![0]) + arrayPointer!![0] = 15 + assertEquals(15, globalArray[0]) + + memScoped { + val struct = alloc() + struct.arrayPointer = globalArray + assertEquals(globalArray[0], struct.arrayPointer!![0]) + } +} \ No newline at end of file diff --git a/kotlin-native/backend.native/tests/interop/basics/bf.kt b/kotlin-native/backend.native/tests/interop/basics/bf.kt new file mode 100644 index 00000000000..0739d4a6dc9 --- /dev/null +++ b/kotlin-native/backend.native/tests/interop/basics/bf.kt @@ -0,0 +1,91 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +import bitfields.* +import kotlinx.cinterop.* + +fun assertEquals(value1: Any?, value2: Any?) { + if (value1 != value2) + throw AssertionError("Expected $value1, got $value2") +} + +fun check(s: S, x1: Long, x2: B2, x3: UShort, x4: UInt, x5: Int, x6: Long, x7: E, x8: Boolean) { + assertEquals(x1, s.x1) + assertEquals(x1, getX1(s.ptr)) + + assertEquals(x2, s.x2) + assertEquals(x2, getX2(s.ptr)) + + assertEquals(x3, s.x3) + assertEquals(x3, getX3(s.ptr)) + + assertEquals(x4, s.x4) + assertEquals(x4, getX4(s.ptr)) + + assertEquals(x5, s.x5) + assertEquals(x5, getX5(s.ptr)) + + assertEquals(x6, s.x6) + assertEquals(x6, getX6(s.ptr)) + + assertEquals(x7, s.x7) + assertEquals(x7, getX7(s.ptr)) + + assertEquals(x8, s.x8) + assertEquals(x8, getX8(s.ptr)) +} + +fun assign(s: S, x1: Long, x2: B2, x3: UShort, x4: UInt, x5: Int, x6: Long, x7: E, x8: Boolean) { + s.x1 = x1 + s.x2 = x2 + s.x3 = x3 + s.x4 = x4 + s.x5 = x5 + s.x6 = x6 + s.x7 = x7 + s.x8 = x8 +} + +fun assignReversed(s: S, x1: Long, x2: B2, x3: UShort, x4: UInt, x5: Int, x6: Long, x7: E, x8: Boolean) { + s.x8 = x8 + s.x7 = x7 + s.x6 = x6 + s.x5 = x5 + s.x4 = x4 + s.x3 = x3 + s.x2 = x2 + s.x1 = x1 +} + +fun test(s: S, x1: Long, x2: B2, x3: UShort, x4: UInt, x5: Int, x6: Long, x7: E, x8: Boolean) { + assign(s, x1, x2, x3, x4, x5, x6, x7, x8) + check(s, x1, x2, x3, x4, x5, x6, x7, x8) + + assignReversed(s, x1, x2, x3, x4, x5, x6, x7, x8) + check(s, x1, x2, x3, x4, x5, x6, x7, x8) + + // Also check with some insignificant bits modified: + + assign(s, x1 + 2, x2, (x3 + 8u).toUShort(), x4 - 16u, x5 + 32, x6 + Long.MIN_VALUE, x7, x8) + check(s, x1, x2, x3, x4, x5, x6, x7, x8) + + assignReversed(s, x1 + 2, x2, (x3 + 8u).toUShort(), x4 - 16u, x5 + 32, x6 + Long.MIN_VALUE, x7, x8) + check(s, x1, x2, x3, x4, x5, x6, x7, x8) +} + +fun main(args: Array) { + memScoped { + val s = alloc() + for (x1 in -1L..0L) + for (x2 in B2.values()) + for (x3 in 0..7) + for (x4 in uintArrayOf(0u, 6u, 15u)) + for (x5 in intArrayOf(-16, -2, -1, 0, 5, 15)) + for (x6 in longArrayOf(Long.MIN_VALUE/2, -1L shl 36, -325L, 0, 1L shl 48, Long.MAX_VALUE/2)) + for (x7 in E.values()) + for (x8 in arrayOf(false, true)) + test(s, x1, x2, x3.toUShort(), x4, x5, x6, x7, x8) + } +} diff --git a/kotlin-native/backend.native/tests/interop/basics/bitfields.def b/kotlin-native/backend.native/tests/interop/basics/bitfields.def new file mode 100644 index 00000000000..729ab79c953 --- /dev/null +++ b/kotlin-native/backend.native/tests/interop/basics/bitfields.def @@ -0,0 +1,28 @@ +--- +enum B2 { + ZERO, ONE, TWO, THREE +}; + +enum E : short { + A, B +}; + +struct __attribute__((packed)) S { + long long x1 : 1; + enum B2 x2 : 2; + unsigned short x3 : 3; + unsigned int x4 : 4; + int x5 : 5; + long long x6 : 63; + enum E x7: 2; + _Bool x8 : 1; +}; + +static long long getX1(struct S* s) { return s->x1; } +static enum B2 getX2(struct S* s) { return s->x2; } +static unsigned short getX3(struct S* s) { return s->x3; } +static unsigned int getX4(struct S* s) { return s->x4; } +static int getX5(struct S* s) { return s->x5; } +static long long getX6(struct S* s) { return s->x6; } +static enum E getX7(struct S* s) { return s->x7; } +static _Bool getX8(struct S* s) { return s->x8; } diff --git a/kotlin-native/backend.native/tests/interop/basics/callbacksAndVarargs.kt b/kotlin-native/backend.native/tests/interop/basics/callbacksAndVarargs.kt new file mode 100644 index 00000000000..5ac6aa863aa --- /dev/null +++ b/kotlin-native/backend.native/tests/interop/basics/callbacksAndVarargs.kt @@ -0,0 +1,70 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +import kotlin.test.* +import kotlinx.cinterop.* +import ccallbacksAndVarargs.* + +fun main() { + testStructCallbacks() + testVarargs() + testCallableReferences() +} + +fun testStructCallbacks() { + assertEquals(42, getX(staticCFunction { -> cValue { x = 42 } })) + applyCallback(cValue { x = 17 }, staticCFunction { it: CValue -> + assertEquals(17, it.useContents { x }) + }) + + assertEquals(66, makeS(66, 111).useContents { x }) +} + +fun testVarargs() { + assertEquals(E.ONE, makeE(1)) + + getVarargs( + 0, + true, + 2.toByte(), + Short.MIN_VALUE, + 42, + Long.MAX_VALUE, + 3.14f, + 2.71, + 0x1234ABCDL.toCPointer(), + UByte.MAX_VALUE, + 22.toUShort(), + 111u, + ULong.MAX_VALUE, + E.TWO, + cValue { x = 15 }, + null + ).useContents { + assertEquals(1, a1) + assertEquals(2.toByte(), a2) + assertEquals(Short.MIN_VALUE, a3) + assertEquals(42, a4) + assertEquals(Long.MAX_VALUE, a5) + assertEquals(3.14f, a6) + assertEquals(2.71, a7) + assertEquals(0x1234ABCDL, a8.toLong()) + assertEquals(UByte.MAX_VALUE, a9) + assertEquals(22.toUShort(), a10) + assertEquals(111u, a11) + assertEquals(ULong.MAX_VALUE, a12) + assertEquals(E.TWO, a13) + assertEquals(15, a14.x) + assertEquals(null, a15) + } +} + +fun testCallableReferences() { + val sumRef = ::sum + assertEquals(3, sumRef(1, 2)) + + val sumPtr = staticCFunction(::sum) + assertEquals(7, sumPtr(3, 4)) +} diff --git a/kotlin-native/backend.native/tests/interop/basics/carrayPointers.def b/kotlin-native/backend.native/tests/interop/basics/carrayPointers.def new file mode 100644 index 00000000000..ddd358781ea --- /dev/null +++ b/kotlin-native/backend.native/tests/interop/basics/carrayPointers.def @@ -0,0 +1,8 @@ +--- +int (*arrayPointer)[1]; + +int globalArray[3] = {1, 2, 3}; + +struct StructWithArrayPtr { + int (*arrayPointer)[1]; +}; \ No newline at end of file diff --git a/kotlin-native/backend.native/tests/interop/basics/ccallbacksAndVarargs.def b/kotlin-native/backend.native/tests/interop/basics/ccallbacksAndVarargs.def new file mode 100644 index 00000000000..e38c45b9c3d --- /dev/null +++ b/kotlin-native/backend.native/tests/interop/basics/ccallbacksAndVarargs.def @@ -0,0 +1,78 @@ + + +--- + +#include + +struct S { + int x; +}; + +static int getX(struct S (*callback)(void)) { + return callback().x; +} + +static void applyCallback(struct S s, void (*callback)(struct S)) { + callback(s); +} + +static struct S makeS(int x, ...) { + return (struct S){ x }; +} + +enum E { + ZERO, ONE, TWO +}; + +static enum E makeE(int ordinal, ...) { + return ordinal; +} + +struct Args { + char a1; + char a2; + short a3; + int a4; + long long a5; + float a6; + double a7; + void* a8; + unsigned char a9; + unsigned short a10; + unsigned int a11; + unsigned long long a12; + enum E a13; + struct S a14; + void* a15; +}; + +static struct Args getVarargs(int ignore, ...) { + va_list args; + va_start(args, ignore); + + struct Args result = { + va_arg(args, char), + va_arg(args, char), + va_arg(args, short), + va_arg(args, int), + va_arg(args, long long), + va_arg(args, double), + va_arg(args, double), + va_arg(args, void*), + va_arg(args, unsigned char), + va_arg(args, unsigned short), + va_arg(args, unsigned int), + va_arg(args, unsigned long long), + va_arg(args, enum E), + va_arg(args, struct S), + va_arg(args, void*) + }; + + va_end(args); + + return result; +} + +static int sum(int first, int second) { + return first + second; +} diff --git a/kotlin-native/backend.native/tests/interop/basics/cenums.def b/kotlin-native/backend.native/tests/interop/basics/cenums.def new file mode 100644 index 00000000000..7c81845152c --- /dev/null +++ b/kotlin-native/backend.native/tests/interop/basics/cenums.def @@ -0,0 +1,4 @@ +--- +enum E { + A, B, C +}; \ No newline at end of file diff --git a/kotlin-native/backend.native/tests/interop/basics/cfunptr.def b/kotlin-native/backend.native/tests/interop/basics/cfunptr.def new file mode 100644 index 00000000000..7506e77b623 --- /dev/null +++ b/kotlin-native/backend.native/tests/interop/basics/cfunptr.def @@ -0,0 +1,94 @@ +headerFilter = NOTHING +--- +#include +#include + +typedef int (*atoiPtrType)(const char*); + +static atoiPtrType getAtoiPtr() { + return &atoi; +} + +static void __printInt(int x) { + printf("%d\n", x); +} + +static void* __getPrintIntPtr() { + return &__printInt; +} + +typedef void* (*getPrintIntPtrPtrType)(void); + +static getPrintIntPtrPtrType getGetPrintIntPtrPtr() { + return &__getPrintIntPtr; +} + +static double __add(double x, double y) { + return x + y; +} + +typedef double (*addPtrType)(double, double); + +static addPtrType getAddPtr() { + return &__add; +} + +static int __doubleToInt(double x) { + return (int) x; +} + +typedef int (*doubleToIntPtrType)(double); + +static doubleToIntPtrType getDoubleToIntPtr() { + return &__doubleToInt; +} + +static _Bool __isIntPositive(int x) { + return x > 0; +} + +typedef _Bool (*isIntPositivePtrType)(int); + +static isIntPositivePtrType getIsIntPositivePtr() { + return &__isIntPositive; +} + +static unsigned int getMaxUInt(void) { + return 0xffffffff; +} + +static typeof(&getMaxUInt) getMaxUIntGetter() { + return &getMaxUInt; +} + +typedef int (*longSignatureFunctionPtrType)( + int, int, int, int, int, int, int, int, int, int, int, int, + int, int, int, int, int, int, int, int, int, int, int +); + +typedef int (*notSoLongSignatureFunctionPtrType)( + int, int, int, int, int, int, int, int, int, int, int, + int, int, int, int, int, int, int, int, int, int, int +); + +static int longSignatureFunction( + int p1, int p2, int p3, int p4, int p5, int p6, int p7, int p8, int p9, int p10, int p11, int p12, + int p13, int p14, int p15, int p16, int p17, int p18, int p19, int p20, int p21, int p22, int p23 +) { + return 42; +} + +static int notSoLongSignatureFunction( + int p1, int p2, int p3, int p4, int p5, int p6, int p7, int p8, int p9, int p10, int p11, int p12, + int p13, int p14, int p15, int p16, int p17, int p18, int p19, int p20, int p21, int p22 +) { + return 42; +} + +static longSignatureFunctionPtrType getLongSignatureFunctionPtr() { + return &longSignatureFunction; +} + +static notSoLongSignatureFunctionPtrType getNotSoLongSignatureFunctionPtr() { + return ¬SoLongSignatureFunction; +} \ No newline at end of file diff --git a/kotlin-native/backend.native/tests/interop/basics/cglobals.def b/kotlin-native/backend.native/tests/interop/basics/cglobals.def new file mode 100644 index 00000000000..0dfeb14627a --- /dev/null +++ b/kotlin-native/backend.native/tests/interop/basics/cglobals.def @@ -0,0 +1,33 @@ +--- +const int g1 = 42; + +int g2 = 17; + +struct S { + int x; +} g3 = { 128 }; + +int g4[2] = { 13, 14 }; + +int g5[2][2] = { 15, 16, 17, 18 }; + +struct S* const g6 = &g3; + +void foo() { + // Test that local vars are not treated as global ones. + float g1; +} + +// Test non-compilable variable: +typedef int MyInt; +MyInt g7; +#define g7 bad macro + +// Test property name mangling: +struct g1 {}; +struct g1_ {}; + +typedef void* voidptr; +_Pragma("clang assume_nonnull begin") +const voidptr g8 = 0x1, g9 = 0x2; +_Pragma("clang assume_nonnull end") \ No newline at end of file diff --git a/kotlin-native/backend.native/tests/interop/basics/cmacros.def b/kotlin-native/backend.native/tests/interop/basics/cmacros.def new file mode 100644 index 00000000000..803a22a7bff --- /dev/null +++ b/kotlin-native/backend.native/tests/interop/basics/cmacros.def @@ -0,0 +1,78 @@ +excludedMacros = EXCLUDED +--- +int* ptr_call() { + return (int*) 1; +} + +int int_call() { + return 42; +} + +void void_call() {} + +int arg_call(int x) { + return x; +} + +typedef struct { + int value +} struct_t; + +struct_t getStruct() { + return (struct_t){ 1 }; +} + +int global_var = 5; + +#define TOO_MANY_ERRORS x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x + +#define LEFT_BRACE { + +#define ZERO 0 +#define ONE 1 + +#define RIGHT_BRACE } + +#define MAX_LONG 9223372036854775807 +#define FOO_STRING "foo" +// This one should be ignored: +#define WIDE_FOO_STRING L"foo" +#define FOURTY_TWO 42 +#define SEVENTEEN ((long long) 17) +#define ONE_POINT_ZERO 1.0 +#define ONE_POINT_FIVE 1.5f + +#define LEFT_PAREN ( + +#define NULL_PTR ((void*)0) +#define VOID_PTR ((void*)1) +#define INT_PTR ((int*)1) +#define PTR_SUM (INT_PTR + 1) +#define PTR_SUM_EXPECTED (sizeof(int) + 1) + +#define RIGHT_PAREN ) + +enum { + INT_CALL = 1 // Should be replaced by macro below. +}; + +#define PTR_CALL ptr_call() +#define INT_CALL int_call() +#define CALL_SUM (int_call() + int_call()) +#define GLOBAL_VAR (global_var) + +// This one should be excluded: +#define EXCLUDED 42 + +// These ones should be ignored: +#define VOID_CALL (void_call()) +#define ARG_CALL(x) (arg_call(x)) +#define GET_STRUCT (getStruct()) +#define UNDECLARED (undeclared()) + +#define BAD1 bar +#define BAD2 5; +#define BAD3 { foo(); } + +void increment(int* counter); +#define increment(counter) { (*(counter))++; } diff --git a/kotlin-native/backend.native/tests/interop/basics/cstdio.def b/kotlin-native/backend.native/tests/interop/basics/cstdio.def new file mode 100644 index 00000000000..13dc2a82526 --- /dev/null +++ b/kotlin-native/backend.native/tests/interop/basics/cstdio.def @@ -0,0 +1,8 @@ +headers = stdio.h +compilerOpts.osx = -D_ANSI_SOURCE + +--- + +static inline FILE* getStdout() { + return stdout; +} \ No newline at end of file diff --git a/kotlin-native/backend.native/tests/interop/basics/cstructs.def b/kotlin-native/backend.native/tests/interop/basics/cstructs.def new file mode 100644 index 00000000000..429f787b7bf --- /dev/null +++ b/kotlin-native/backend.native/tests/interop/basics/cstructs.def @@ -0,0 +1,41 @@ +nonStrictEnums = NonStrict +--- +typedef struct { + int i; +} Trivial; + +enum E { + R, G, B +}; + +enum NonStrict { + N, S, K +}; + +struct Complex { + unsigned int ui; + Trivial t; + struct Complex* next; + enum E e; + enum NonStrict nonStrict; + int arr[2]; + _Bool b; +}; + +struct __attribute__((packed)) Packed { + int i : 1; + enum E e : 2; +}; + +struct Complex produceComplex() { + struct Complex complex = { + .ui = 128, + .t = {1}, + .next = 0, + .e = R, + .nonStrict = K, + .arr = {-51, -19}, + .b = 1 + }; + return complex; +}; \ No newline at end of file diff --git a/kotlin-native/backend.native/tests/interop/basics/ctypes.def b/kotlin-native/backend.native/tests/interop/basics/ctypes.def new file mode 100644 index 00000000000..8fdf6942216 --- /dev/null +++ b/kotlin-native/backend.native/tests/interop/basics/ctypes.def @@ -0,0 +1,89 @@ +--- +// KT-28065 +struct StructWithConstFields { + int x; + const int y; +}; + +struct StructWithConstFields getStructWithConstFields() { + struct StructWithConstFields result = { 111, 222 }; + return result; +} + +enum ForwardDeclaredEnum; +enum ForwardDeclaredEnum { + ZERO, ONE, TWO +}; + +static int vlaSum(int size, int array[size]) { + int result = 0; + for (int i = 0; i < size; ++i) { + result += array[i]; + } + return result; +} + +static int vlaSum2D(int size, int array[][size]) { + int result = 0; + for (int i = 0; i < size; ++i) { + for (int j = 0; j < size; ++j) { + result += array[i][j]; + } + } + return result; +} + +static int vlaSum2DBothDimensions(int rows, int columns, int array[rows][columns]) { + int result = 0; + for (int i = 0; i < rows; ++i) { + for (int j = 0; j < columns; ++j) { + result += array[i][j]; + } + } + return result; +} + +/* +// Not supported by clang: +static int vlaSum2DForward(int size; int array[][size], int size) { + return vlaSum2D(size, array); +} +*/ + +// "Strict" enums heuristic based on whether enum constants are defined explicitly: +enum StrictEnum1 { + StrictEnum1A, + StrictEnum1B +}; + +enum StrictEnum2 { + StrictEnum2A __attribute__((unused)), + StrictEnum2B __attribute__((unused)) +}; + +enum NonStrictEnum1 { + NonStrictEnum1A = 0, + NonStrictEnum1B __attribute__((unused)) +}; + +enum NonStrictEnum2 { + NonStrictEnum2A, + NonStrictEnum2B __attribute__((unused)) = 1 +}; + +// KT-34025 +typedef char Char; +enum EnumCharBase : Char { + EnumCharBaseA, + EnumCharBaseB +}; + +static int sendEnum(enum EnumCharBase x) { + return (int)x + 2; +} + +enum EnumExplicitChar : char { + EnumExplicitCharA = 'a', + EnumExplicitCharB = 'b', + EnumExplicitCharDup = 'a' +}; diff --git a/kotlin-native/backend.native/tests/interop/basics/cunion.def b/kotlin-native/backend.native/tests/interop/basics/cunion.def new file mode 100644 index 00000000000..58407a348cd --- /dev/null +++ b/kotlin-native/backend.native/tests/interop/basics/cunion.def @@ -0,0 +1,17 @@ +--- +typedef union { + short s; + long long ll; +} BasicUnion; + +typedef struct { + union { + int i; + float f; + } as; +} StructWithUnion; + +typedef union { + unsigned int i : 31; + unsigned char b : 1; +} Packed; \ No newline at end of file diff --git a/kotlin-native/backend.native/tests/interop/basics/cunsupported.def b/kotlin-native/backend.native/tests/interop/basics/cunsupported.def new file mode 100644 index 00000000000..e4c19142291 --- /dev/null +++ b/kotlin-native/backend.native/tests/interop/basics/cunsupported.def @@ -0,0 +1,27 @@ +compilerOpts = -mno-xsave + +--- + +static void noAttr() {} +__attribute__((always_inline)) noTargetAttr() {} + +__attribute__((always_inline, __target__("xsave"))) void plainAttrs1() {} +__attribute__((__target__("xsave"), always_inline)) void plainAttrs2() {} + +#define TARGET __target__ + +__attribute__((always_inline, TARGET("xsave"))) void macroAttr1() {} +__attribute__((TARGET("xsave"), always_inline)) void macroAttr2() {} + +#define TARGET_ATTR __target__("xsave") + +__attribute__((TARGET_ATTR, always_inline)) void macroAttr3() {} +__attribute__((always_inline, TARGET_ATTR)) void macroAttr4() {} + +#define ALL_ATTRS1 __attribute__((always_inline, __target__("xsave"))) + +ALL_ATTRS1 void macroAttr5() {} + +#define ALL_ATTRS2 __attribute__((always_inline, __target__("xsave"))) + +ALL_ATTRS2 void macroAttr6() {} diff --git a/kotlin-native/backend.native/tests/interop/basics/custom headers/custom.h b/kotlin-native/backend.native/tests/interop/basics/custom headers/custom.h new file mode 100644 index 00000000000..1e9e547aca7 --- /dev/null +++ b/kotlin-native/backend.native/tests/interop/basics/custom headers/custom.h @@ -0,0 +1,7 @@ +#include +#include +#include + +int custom_strcmp(const char* str1, const char* str2) { + return strcmp(str1, str2); +} \ No newline at end of file diff --git a/kotlin-native/backend.native/tests/interop/basics/cvalues.def b/kotlin-native/backend.native/tests/interop/basics/cvalues.def new file mode 100644 index 00000000000..77e0cbac565 --- /dev/null +++ b/kotlin-native/backend.native/tests/interop/basics/cvalues.def @@ -0,0 +1,10 @@ +--- +_Bool isNullString(const char* str) { + return str == (const char*)0; +} + +typedef const short* LPCWSTR; + +_Bool isNullWString(LPCWSTR str) { + return str == (LPCWSTR)0; +} diff --git a/kotlin-native/backend.native/tests/interop/basics/cvectors.def b/kotlin-native/backend.native/tests/interop/basics/cvectors.def new file mode 100644 index 00000000000..9c303835d44 --- /dev/null +++ b/kotlin-native/backend.native/tests/interop/basics/cvectors.def @@ -0,0 +1,28 @@ +--- +typedef float __attribute__ ((__vector_size__ (16))) KVector4f; +typedef int __attribute__ ((__vector_size__ (16))) KVector4i32; + +struct Complex { + unsigned int ui; + KVector4f vec4f; + struct Complex* next; + int arr[2]; +}; + +struct Complex produceComplex() { + struct Complex complex = { + .ui = 128, + .vec4f = {1.0, 1.0, 1.0, 1.0}, + .next = 0, + .arr = {-51, -19} + }; + return complex; +}; + +static float sendV4F(KVector4f v) { + return v[0] + 2 * v[1] + 4 * v[2] + 8 * v[3]; +} + +static int sendV4I(KVector4i32 v) { + return v[0] + 2 * v[1] + 4 * v[2] + 8 * v[3]; +} diff --git a/kotlin-native/backend.native/tests/interop/basics/echo_server.kt b/kotlin-native/backend.native/tests/interop/basics/echo_server.kt new file mode 100644 index 00000000000..347711e580d --- /dev/null +++ b/kotlin-native/backend.native/tests/interop/basics/echo_server.kt @@ -0,0 +1,69 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +import kotlinx.cinterop.* +import sockets.* + +fun main(args: Array) { + if (args.size < 1) { + println("Usage: ./echo_server ") + return + } + + val port = atoi(args[0]).toUShort() + + memScoped { + + val bufferLength = 100L + val buffer = allocArray(bufferLength) + val serverAddr = alloc() + + val listenFd = socket(AF_INET, SOCK_STREAM, 0) + .toInt().ensureUnixCallResult { it >= 0 } + + with(serverAddr) { + memset(this.ptr, 0, sockaddr_in.size.convert()) + sin_family = AF_INET.convert() + sin_addr.s_addr = htons(0u).convert() + sin_port = htons(port) + } + + bind(listenFd, serverAddr.ptr.reinterpret(), sockaddr_in.size.toUInt()) + .toInt().ensureUnixCallResult { it == 0 } + + listen(listenFd, 10) + .toInt().ensureUnixCallResult { it == 0 } + + val commFd = accept(listenFd, null, null) + .toInt().ensureUnixCallResult { it >= 0 } + + while (true) { + val length = read(commFd, buffer, bufferLength.convert()) + .toInt().ensureUnixCallResult { it >= 0 } + + if (length == 0) { + break + } + + write(commFd, buffer, length.convert()) + .toInt().ensureUnixCallResult { it >= 0 } + } + } +} + +// Not available through interop because declared as macro: +fun htons(value: UShort) = ((value.toInt() ushr 8) or (value.toInt() shl 8)).toUShort() + +fun throwUnixError(): Nothing { + perror(null) // TODO: store error message to exception instead. + throw Error("UNIX call failed") +} + +inline fun Int.ensureUnixCallResult(predicate: (Int) -> Boolean): Int { + if (!predicate(this)) { + throwUnixError() + } + return this +} diff --git a/kotlin-native/backend.native/tests/interop/basics/enums.kt b/kotlin-native/backend.native/tests/interop/basics/enums.kt new file mode 100644 index 00000000000..56eedaa0d01 --- /dev/null +++ b/kotlin-native/backend.native/tests/interop/basics/enums.kt @@ -0,0 +1,15 @@ +import cenums.* +import kotlinx.cinterop.* +import kotlin.test.* + +fun main() { + memScoped { + val e = alloc() + e.value = E.C + assertEquals(E.C, e.value) + + assertFailsWith { + e.value = TODO() + } + } +} \ No newline at end of file diff --git a/kotlin-native/backend.native/tests/interop/basics/funptr.kt b/kotlin-native/backend.native/tests/interop/basics/funptr.kt new file mode 100644 index 00000000000..6e1e677ba1c --- /dev/null +++ b/kotlin-native/backend.native/tests/interop/basics/funptr.kt @@ -0,0 +1,46 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +import kotlinx.cinterop.* +import cfunptr.* +import kotlin.test.* + +typealias NotSoLongSignatureFunction = ( + Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, + Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int +) -> Int + +fun main(args: Array) { + val atoiPtr = getAtoiPtr()!! + + val getPrintIntPtrPtr = getGetPrintIntPtrPtr()!! + val printIntPtr = getPrintIntPtrPtr()!!.reinterpret Unit>>() + + val fortyTwo = memScoped { + atoiPtr("42".cstr.getPointer(memScope)) + } + + printIntPtr(fortyTwo) + + printIntPtr( + getDoubleToIntPtr()!!( + getAddPtr()!!(5.1, 12.2) + ) + ) + + val isIntPositivePtr = getIsIntPositivePtr()!! + + printIntPtr(isIntPositivePtr(42).ifThenOneElseZero()) + printIntPtr(isIntPositivePtr(-42).ifThenOneElseZero()) + + assertEquals(getMaxUIntGetter()!!(), UInt.MAX_VALUE) + + val longSignaturePtr: COpaquePointer? = getLongSignatureFunctionPtr() + val notSoLongSignaturePtr: CPointer>? = getNotSoLongSignatureFunctionPtr() + printIntPtr(notSoLongSignaturePtr!!.invoke(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0)) + printIntPtr(notSoLongSignatureFunction(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0)) +} + +fun Boolean.ifThenOneElseZero() = if (this) 1 else 0 \ No newline at end of file diff --git a/kotlin-native/backend.native/tests/interop/basics/globals.kt b/kotlin-native/backend.native/tests/interop/basics/globals.kt new file mode 100644 index 00000000000..9a48e87db72 --- /dev/null +++ b/kotlin-native/backend.native/tests/interop/basics/globals.kt @@ -0,0 +1,33 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +import kotlinx.cinterop.* +import cglobals.* + +fun main(args: Array) { + assert(g1__ == 42) + + assert(g2 == 17) + g2 = 42 + assert(g2 == 42) + + assert(g3.x == 128) + g3.x = 7 + assert(g3.x == 7) + + assert(g4[1] == 14) + g4[1] = 15 + assert(g4[1] == 15) + + assert(g5[0] == 15) + assert(g5[3] == 18) + g5[0] = 16 + assert(g5[0] == 16) + + assert(g6 == g3.ptr) + + assert(g8.toLong() == 0x1L) + assert(g9.toLong() == 0x2L) +} diff --git a/kotlin-native/backend.native/tests/interop/basics/macros.kt b/kotlin-native/backend.native/tests/interop/basics/macros.kt new file mode 100644 index 00000000000..826f3e70887 --- /dev/null +++ b/kotlin-native/backend.native/tests/interop/basics/macros.kt @@ -0,0 +1,48 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +import kotlin.test.* +import cmacros.* +import kotlinx.cinterop.* + +fun main(args: Array) { + assertEquals("foo", FOO_STRING) + assertEquals(0, ZERO) + assertEquals(1, ONE) + assertEquals(Long.MAX_VALUE, MAX_LONG) + assertEquals(42, FOURTY_TWO) + + val seventeen: Long = SEVENTEEN + assertEquals(17L, seventeen) + + val onePointFive: Float = ONE_POINT_FIVE + val onePointZero: Double = ONE_POINT_ZERO + + assertEquals(1.5f, onePointFive) + assertEquals(1.0, onePointZero) + + val nullPtr: COpaquePointer? = NULL_PTR + val voidPtr: COpaquePointer? = VOID_PTR + val intPtr: CPointer? = INT_PTR + val ptrSum: CPointer? = PTR_SUM + val ptrCall: CPointer? = PTR_CALL + + assertEquals(null, nullPtr) + assertEquals(1L, voidPtr.rawValue.toLong()) + assertEquals(1L, intPtr.rawValue.toLong()) + assertEquals(PTR_SUM_EXPECTED.toLong(), ptrSum.rawValue.toLong()) + assertEquals(1L, ptrCall.rawValue.toLong()) + + assertEquals(42, INT_CALL) + assertEquals(84, CALL_SUM) + assertEquals(5, GLOBAL_VAR) + + memScoped { + val counter = alloc() + counter.value = 42 + increment(counter.ptr) + assertEquals(43, counter.value) + } +} diff --git a/kotlin-native/backend.native/tests/interop/basics/mangling.def b/kotlin-native/backend.native/tests/interop/basics/mangling.def new file mode 100644 index 00000000000..99fe71b2fa1 --- /dev/null +++ b/kotlin-native/backend.native/tests/interop/basics/mangling.def @@ -0,0 +1,6 @@ +--- + +// test mangling of special names + +enum _Companion {Companion, Any}; +enum _Companion companion = Companion; diff --git a/kotlin-native/backend.native/tests/interop/basics/mangling.kt b/kotlin-native/backend.native/tests/interop/basics/mangling.kt new file mode 100644 index 00000000000..3bf58ae1b84 --- /dev/null +++ b/kotlin-native/backend.native/tests/interop/basics/mangling.kt @@ -0,0 +1,9 @@ +import kotlinx.cinterop.* +import kotlin.test.* +import mangling.* + +fun main() { + companion = _Companion.`Companion$` + assertEquals(_Companion.`Companion$`, companion) +} + diff --git a/kotlin-native/backend.native/tests/interop/basics/mangling2.def b/kotlin-native/backend.native/tests/interop/basics/mangling2.def new file mode 100644 index 00000000000..60dec063505 --- /dev/null +++ b/kotlin-native/backend.native/tests/interop/basics/mangling2.def @@ -0,0 +1,6 @@ +--- + +// test mangling of special names + +enum Companion {One, Two}; + diff --git a/kotlin-native/backend.native/tests/interop/basics/mangling2.kt b/kotlin-native/backend.native/tests/interop/basics/mangling2.kt new file mode 100644 index 00000000000..3179e430f5e --- /dev/null +++ b/kotlin-native/backend.native/tests/interop/basics/mangling2.kt @@ -0,0 +1,9 @@ +import kotlinx.cinterop.* +import kotlin.test.* +import mangling2.* + +fun main() { + val mangled = `Companion$`.Two + assertEquals(`Companion$`.Two, mangled) +} + diff --git a/kotlin-native/backend.native/tests/interop/basics/mangling_keywords.def b/kotlin-native/backend.native/tests/interop/basics/mangling_keywords.def new file mode 100644 index 00000000000..942ac988bb4 --- /dev/null +++ b/kotlin-native/backend.native/tests/interop/basics/mangling_keywords.def @@ -0,0 +1,21 @@ +--- +#define as "as" +#define class "class" +#define dynamic "dynamic" +#define false "false" +#define fun "fun" +#define in "in" +#define interface "interface" +#define is "is" +#define null "null" +#define object "object" +#define package "package" +#define super "super" +#define this "this" +#define throw "throw" +#define true "true" +#define try "try" +#define typealias "typealias" +#define val "val" +#define var "var" +#define when "when" \ No newline at end of file diff --git a/kotlin-native/backend.native/tests/interop/basics/mangling_keywords.kt b/kotlin-native/backend.native/tests/interop/basics/mangling_keywords.kt new file mode 100644 index 00000000000..d9f9805a871 --- /dev/null +++ b/kotlin-native/backend.native/tests/interop/basics/mangling_keywords.kt @@ -0,0 +1,27 @@ +import kotlin.test.* +import mangling_keywords.* + +fun main() { + // Check that all Kotlin keywords are imported and mangled. + assertEquals("as", `as`) + assertEquals("class", `class`) + assertEquals("dynamic", `dynamic`) + assertEquals("false", `false`) + assertEquals("fun", `fun`) + assertEquals("in", `in`) + assertEquals("interface", `interface`) + assertEquals("is", `is`) + assertEquals("null", `null`) + assertEquals("object", `object`) + assertEquals("package", `package`) + assertEquals("super", `super`) + assertEquals("this", `this`) + assertEquals("throw", `throw`) + assertEquals("true", `true`) + assertEquals("try", `try`) + assertEquals("typealias", `typealias`) + assertEquals("val", `val`) + assertEquals("var", `var`) + assertEquals("when", `when`) +} + diff --git a/kotlin-native/backend.native/tests/interop/basics/mangling_keywords2.def b/kotlin-native/backend.native/tests/interop/basics/mangling_keywords2.def new file mode 100644 index 00000000000..e8257e78aaa --- /dev/null +++ b/kotlin-native/backend.native/tests/interop/basics/mangling_keywords2.def @@ -0,0 +1,72 @@ +--- +enum KotlinKeywordsEnum { + as, + class, + dynamic, + false, + fun, + in, + interface, + is, + null, + object, + package, + super, + this, + throw, + true, + try, + typealias, + val, + var, + when, +}; + +struct KotlinKeywordsStruct { + int as; + int class; + int dynamic; + int false; + int fun; + int in; + int interface; + int is; + int null; + int object; + int package; + int super; + int this; + int throw; + int true; + int try; + int typealias; + int val; + int var; + int when; +}; + +struct KotlinKeywordsStruct createKotlinKeywordsStruct() { + struct KotlinKeywordsStruct s = { + .as = 0, + .class = 0, + .dynamic = 0, + .false = 0, + .fun = 0, + .in = 0, + .interface = 0, + .is = 0, + .null = 0, + .object = 0, + .package = 0, + .super = 0, + .this = 0, + .throw = 0, + .true = 0, + .try = 0, + .typealias = 0, + .val = 0, + .var = 0, + .when = 0, + }; + return s; +} \ No newline at end of file diff --git a/kotlin-native/backend.native/tests/interop/basics/mangling_keywords2.kt b/kotlin-native/backend.native/tests/interop/basics/mangling_keywords2.kt new file mode 100644 index 00000000000..a003d3af108 --- /dev/null +++ b/kotlin-native/backend.native/tests/interop/basics/mangling_keywords2.kt @@ -0,0 +1,50 @@ +import kotlin.test.* +import mangling_keywords2.* +import kotlinx.cinterop.useContents + +fun main() { + // Check that all Kotlin keywords are imported and mangled. + createKotlinKeywordsStruct().useContents { + assertEquals(0, `as`) + assertEquals(0, `class`) + assertEquals(0, `dynamic`) + assertEquals(0, `false`) + assertEquals(0, `fun`) + assertEquals(0, `in`) + assertEquals(0, `interface`) + assertEquals(0, `is`) + assertEquals(0, `null`) + assertEquals(0, `object`) + assertEquals(0, `package`) + assertEquals(0, `super`) + assertEquals(0, `this`) + assertEquals(0, `throw`) + assertEquals(0, `true`) + assertEquals(0, `try`) + assertEquals(0, `typealias`) + assertEquals(0, `val`) + assertEquals(0, `var`) + assertEquals(0, `when`) + } + + assertEquals(KotlinKeywordsEnum.`as`, KotlinKeywordsEnum.`as`) + assertEquals(KotlinKeywordsEnum.`class`, KotlinKeywordsEnum.`class`) + assertEquals(KotlinKeywordsEnum.`dynamic`, KotlinKeywordsEnum.`dynamic`) + assertEquals(KotlinKeywordsEnum.`false`, KotlinKeywordsEnum.`false`) + assertEquals(KotlinKeywordsEnum.`fun`, KotlinKeywordsEnum.`fun`) + assertEquals(KotlinKeywordsEnum.`in`, KotlinKeywordsEnum.`in`) + assertEquals(KotlinKeywordsEnum.`interface`, KotlinKeywordsEnum.`interface`) + assertEquals(KotlinKeywordsEnum.`is`, KotlinKeywordsEnum.`is`) + assertEquals(KotlinKeywordsEnum.`null`, KotlinKeywordsEnum.`null`) + assertEquals(KotlinKeywordsEnum.`object`, KotlinKeywordsEnum.`object`) + assertEquals(KotlinKeywordsEnum.`package`, KotlinKeywordsEnum.`package`) + assertEquals(KotlinKeywordsEnum.`super`, KotlinKeywordsEnum.`super`) + assertEquals(KotlinKeywordsEnum.`this`, KotlinKeywordsEnum.`this`) + assertEquals(KotlinKeywordsEnum.`throw`, KotlinKeywordsEnum.`throw`) + assertEquals(KotlinKeywordsEnum.`true`, KotlinKeywordsEnum.`true`) + assertEquals(KotlinKeywordsEnum.`try`, KotlinKeywordsEnum.`try`) + assertEquals(KotlinKeywordsEnum.`typealias`, KotlinKeywordsEnum.`typealias`) + assertEquals(KotlinKeywordsEnum.`val`, KotlinKeywordsEnum.`val`) + assertEquals(KotlinKeywordsEnum.`var`, KotlinKeywordsEnum.`var`) + assertEquals(KotlinKeywordsEnum.`when`, KotlinKeywordsEnum.`when`) +} \ No newline at end of file diff --git a/kotlin-native/backend.native/tests/interop/basics/opengl_teapot.kt b/kotlin-native/backend.native/tests/interop/basics/opengl_teapot.kt new file mode 100644 index 00000000000..5c88879c897 --- /dev/null +++ b/kotlin-native/backend.native/tests/interop/basics/opengl_teapot.kt @@ -0,0 +1,116 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +import kotlinx.cinterop.* +import platform.GLUT.* +import platform.OpenGL.* +import platform.OpenGLCommon.* + +// Ported from http://openglsamples.sourceforge.net/projects/index.php/blog/index/ + +private var rotation: GLfloat = 0.0f +private val rotationSpeed: GLfloat = 0.2f + +private val windowWidth = 640 +private val windowHeight = 480 + +fun display() { + // Clear Screen and Depth Buffer + glClear((GL_COLOR_BUFFER_BIT or GL_DEPTH_BUFFER_BIT).convert()) + glLoadIdentity() + + // Define a viewing transformation + gluLookAt(4.0, 2.0, 0.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0) + + // Push and pop the current matrix stack. + // This causes that translations and rotations on this matrix wont influence others. + + glPushMatrix() + glColor3f(1.0f, 0.0f, 0.0f) + glTranslatef(0.0f, 0.0f, 0.0f) + glRotatef(rotation, 0.0f, 1.0f, 0.0f) + glRotatef(90.0f, 0.0f, 1.0f, 0.0f) + + // Draw the teapot + glutSolidTeapot(1.0) + glPopMatrix() + + + rotation += rotationSpeed + glutSwapBuffers() +} + + +fun initialize() { + // select projection matrix + glMatrixMode(GL_PROJECTION) + + // set the viewport + glViewport(0, 0, windowWidth, windowHeight) + + // set matrix mode + glMatrixMode(GL_PROJECTION) + + // reset projection matrix + glLoadIdentity() + val aspect = windowWidth.toDouble() / windowHeight + + // set up a perspective projection matrix + gluPerspective(45.0, aspect, 1.0, 500.0) + + // specify which matrix is the current matrix + glMatrixMode(GL_MODELVIEW) + glShadeModel(GL_SMOOTH) + + // specify the clear value for the depth buffer + glClearDepth(1.0) + glEnable(GL_DEPTH_TEST) + glDepthFunc(GL_LEQUAL) + + // specify implementation-specific hints + glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST) + + glLightModelfv(GL_LIGHT_MODEL_AMBIENT, cValuesOf(0.1f, 0.1f, 0.1f, 1.0f)) + glLightfv(GL_LIGHT0, GL_DIFFUSE, cValuesOf(0.6f, 0.6f, 0.6f, 1.0f)) + glLightfv(GL_LIGHT0, GL_SPECULAR, cValuesOf(0.7f, 0.7f, 0.3f, 1.0f)) + + glEnable(GL_LIGHT0) + glEnable(GL_COLOR_MATERIAL) + glShadeModel(GL_SMOOTH) + glLightModeli(GL_LIGHT_MODEL_TWO_SIDE, GL_FALSE) + glDepthFunc(GL_LEQUAL) + glEnable(GL_DEPTH_TEST) + glEnable(GL_LIGHTING) + glEnable(GL_LIGHT0) + glClearColor(0.0f, 0.0f, 0.0f, 1.0f) +} + +fun main(args: Array) { + // initialize and run program + memScoped { + val argc = alloc().apply { value = 0 } + glutInit(argc.ptr, null) // TODO: pass real args + } + + // Display Mode + glutInitDisplayMode((GLUT_RGB or GLUT_DOUBLE or GLUT_DEPTH).convert()) + + // Set window size + glutInitWindowSize(windowWidth, windowHeight) + + // create Window + glutCreateWindow("The GLUT Teapot") + + // register Display Function + glutDisplayFunc(staticCFunction(::display)) + + // register Idle Function + glutIdleFunc(staticCFunction(::display)) + + initialize() + + // run GLUT mainloop + glutMainLoop() +} \ No newline at end of file diff --git a/kotlin-native/backend.native/tests/interop/basics/pinning.kt b/kotlin-native/backend.native/tests/interop/basics/pinning.kt new file mode 100644 index 00000000000..0bc48331552 --- /dev/null +++ b/kotlin-native/backend.native/tests/interop/basics/pinning.kt @@ -0,0 +1,247 @@ +/* + * Copyright 2010-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +import kotlin.test.* +import kotlinx.cinterop.* + +@Test fun pinnedByteArrayAddressOf() { + val arr = ByteArray(10) { 0 } + arr.usePinned { + assertEquals(0, it.addressOf(0).pointed.value) + assertEquals(0, it.addressOf(9).pointed.value) + assertFailsWith { + it.addressOf(10) + } + assertFailsWith { + it.addressOf(-1) + } + assertFailsWith { + it.addressOf(Int.MAX_VALUE) + } + assertFailsWith { + it.addressOf(Int.MIN_VALUE) + } + } +} + +@Test fun pinnedStringAddressOf() { + val str = "0000000000" + str.usePinned { + it.addressOf(0) + it.addressOf(9) + assertFailsWith { + it.addressOf(10) + } + assertFailsWith { + it.addressOf(-1) + } + assertFailsWith { + it.addressOf(Int.MAX_VALUE) + } + assertFailsWith { + it.addressOf(Int.MIN_VALUE) + } + } +} + +@Test fun pinnedCharArrayAddressOf() { + val arr = CharArray(10) { '0' } + arr.usePinned { + it.addressOf(0) + it.addressOf(9) + assertFailsWith { + it.addressOf(10) + } + assertFailsWith { + it.addressOf(-1) + } + assertFailsWith { + it.addressOf(Int.MAX_VALUE) + } + assertFailsWith { + it.addressOf(Int.MIN_VALUE) + } + } +} + +@Test fun pinnedShortArrayAddressOf() { + val arr = ShortArray(10) { 0 } + arr.usePinned { + assertEquals(0, it.addressOf(0).pointed.value) + assertEquals(0, it.addressOf(9).pointed.value) + assertFailsWith { + it.addressOf(10) + } + assertFailsWith { + it.addressOf(-1) + } + assertFailsWith { + it.addressOf(Int.MAX_VALUE) + } + assertFailsWith { + it.addressOf(Int.MIN_VALUE) + } + } +} + +@Test fun pinnedIntArrayAddressOf() { + val arr = IntArray(10) { 0 } + arr.usePinned { + assertEquals(0, it.addressOf(0).pointed.value) + assertEquals(0, it.addressOf(9).pointed.value) + assertFailsWith { + it.addressOf(10) + } + assertFailsWith { + it.addressOf(-1) + } + assertFailsWith { + it.addressOf(Int.MAX_VALUE) + } + assertFailsWith { + it.addressOf(Int.MIN_VALUE) + } + } +} + +@Test fun pinnedLongArrayAddressOf() { + val arr = LongArray(10) { 0 } + arr.usePinned { + assertEquals(0, it.addressOf(0).pointed.value) + assertEquals(0, it.addressOf(9).pointed.value) + assertFailsWith { + it.addressOf(10) + } + assertFailsWith { + it.addressOf(-1) + } + assertFailsWith { + it.addressOf(Int.MAX_VALUE) + } + assertFailsWith { + it.addressOf(Int.MIN_VALUE) + } + } +} + +@Test fun pinnedUByteArrayAddressOf() { + val arr = UByteArray(10) { 0U } + arr.usePinned { + assertEquals(0U, it.addressOf(0).pointed.value) + assertEquals(0U, it.addressOf(9).pointed.value) + assertFailsWith { + it.addressOf(10) + } + assertFailsWith { + it.addressOf(-1) + } + assertFailsWith { + it.addressOf(Int.MAX_VALUE) + } + assertFailsWith { + it.addressOf(Int.MIN_VALUE) + } + } +} + +@Test fun pinnedUShortArrayAddressOf() { + val arr = UShortArray(10) { 0U } + arr.usePinned { + assertEquals(0U, it.addressOf(0).pointed.value) + assertEquals(0U, it.addressOf(9).pointed.value) + assertFailsWith { + it.addressOf(10) + } + assertFailsWith { + it.addressOf(-1) + } + assertFailsWith { + it.addressOf(Int.MAX_VALUE) + } + assertFailsWith { + it.addressOf(Int.MIN_VALUE) + } + } +} + +@Test fun pinnedUIntArrayAddressOf() { + val arr = UIntArray(10) { 0U } + arr.usePinned { + assertEquals(0U, it.addressOf(0).pointed.value) + assertEquals(0U, it.addressOf(9).pointed.value) + assertFailsWith { + it.addressOf(10) + } + assertFailsWith { + it.addressOf(-1) + } + assertFailsWith { + it.addressOf(Int.MAX_VALUE) + } + assertFailsWith { + it.addressOf(Int.MIN_VALUE) + } + } +} + +@Test fun pinnedULongArrayAddressOf() { + val arr = ULongArray(10) { 0U } + arr.usePinned { + assertEquals(0U, it.addressOf(0).pointed.value) + assertEquals(0U, it.addressOf(9).pointed.value) + assertFailsWith { + it.addressOf(10) + } + assertFailsWith { + it.addressOf(-1) + } + assertFailsWith { + it.addressOf(Int.MAX_VALUE) + } + assertFailsWith { + it.addressOf(Int.MIN_VALUE) + } + } +} + +@Test fun pinnedFloatArrayAddressOf() { + val arr = FloatArray(10) { 0.0f } + arr.usePinned { + assertEquals(0.0f, it.addressOf(0).pointed.value) + assertEquals(0.0f, it.addressOf(9).pointed.value) + assertFailsWith { + it.addressOf(10) + } + assertFailsWith { + it.addressOf(-1) + } + assertFailsWith { + it.addressOf(Int.MAX_VALUE) + } + assertFailsWith { + it.addressOf(Int.MIN_VALUE) + } + } +} + +@Test fun pinnedDoubleArrayAddressOf() { + val arr = DoubleArray(10) { 0.0 } + arr.usePinned { + assertEquals(0.0, it.addressOf(0).pointed.value) + assertEquals(0.0, it.addressOf(9).pointed.value) + assertFailsWith { + it.addressOf(10) + } + assertFailsWith { + it.addressOf(-1) + } + assertFailsWith { + it.addressOf(Int.MAX_VALUE) + } + assertFailsWith { + it.addressOf(Int.MIN_VALUE) + } + } +} diff --git a/kotlin-native/backend.native/tests/interop/basics/sockets.def b/kotlin-native/backend.native/tests/interop/basics/sockets.def new file mode 100644 index 00000000000..bacfa1315a8 --- /dev/null +++ b/kotlin-native/backend.native/tests/interop/basics/sockets.def @@ -0,0 +1,12 @@ +headers = sys/socket.h sys/errno.h netdb.h stdio.h string.h unistd.h stdlib.h netinet/in.h +compilerOpts.osx = -D_ANSI_SOURCE -D_POSIX_SOURCE +excludeFunctions.osx = addrsel_policy_init +--- + +static int interop_errno() { + return errno; +} + +static short interop_htons(short x) { + return htons(x); +} diff --git a/kotlin-native/backend.native/tests/interop/basics/structs.kt b/kotlin-native/backend.native/tests/interop/basics/structs.kt new file mode 100644 index 00000000000..e5351c22d7b --- /dev/null +++ b/kotlin-native/backend.native/tests/interop/basics/structs.kt @@ -0,0 +1,76 @@ +import cstructs.* +import kotlinx.cinterop.* +import kotlin.test.* + +fun main() { + produceComplex().useContents { + assertEquals(ui, 128u) + ui = 333u + assertEquals(ui, 333u) + + assertEquals(t.i, 1) + t.i += 15 + assertEquals(t.i, 16) + + assertEquals(next, null) + next = this.ptr + assertEquals(next, this.ptr) + // Check null pointer because it has Nothing? type. + next = null + assertEquals(next, null) + + assertEquals(e, E.R) + e = E.G + assertEquals(e, E.G) + + assertEquals(K, nonStrict) + nonStrict = S + assertEquals(S, nonStrict) + + assertEquals(arr[0], -51) + assertEquals(arr[1], -19) + arr[0] = 51 + arr[1] = 19 + assertEquals(arr[0], 51) + assertEquals(arr[1], 19) + + assertEquals(true, b) + b = false + assertEquals(false, b) + + // Check that subtyping via Nothing-returning functions does not break compiler. + assertFailsWith { + ui = TODO() + t.i = TODO() + next = TODO() + e = TODO() + nonStrict = TODO() + b = TODO() + } + } + memScoped { + val packed = alloc() + packed.i = -1 + assertEquals(-1, packed.i) + packed.e = E.R + assertEquals(E.R, packed.e) + // Check that subtyping via Nothing-returning functions does not break compiler. + assertFailsWith { + packed.i = TODO() + packed.e = TODO() + } + } + // Check that generics doesn't break anything. + checkEnumSubTyping(E.R) + checkIntSubTyping(630090) +} + +fun checkEnumSubTyping(e: T) = memScoped { + val s = alloc() + s.e = e +} + +fun checkIntSubTyping(x: T) = memScoped { + val s = alloc() + s.i = x +} \ No newline at end of file diff --git a/kotlin-native/backend.native/tests/interop/basics/typedefs.def b/kotlin-native/backend.native/tests/interop/basics/typedefs.def new file mode 100644 index 00000000000..97880cddca5 --- /dev/null +++ b/kotlin-native/backend.native/tests/interop/basics/typedefs.def @@ -0,0 +1,2 @@ +--- +typedef int my_int; \ No newline at end of file diff --git a/kotlin-native/backend.native/tests/interop/basics/types.kt b/kotlin-native/backend.native/tests/interop/basics/types.kt new file mode 100644 index 00000000000..46300f26cb5 --- /dev/null +++ b/kotlin-native/backend.native/tests/interop/basics/types.kt @@ -0,0 +1,31 @@ +import kotlinx.cinterop.* +import kotlin.native.* +import kotlin.test.* +import ctypes.* + +fun main() { + getStructWithConstFields().useContents { + assertEquals(111, x) + assertEquals(222, y) + } + + assertEquals(1u, ForwardDeclaredEnum.ONE.value) + + assertEquals(6, vlaSum(3, cValuesOf(1, 2, 3))) + assertEquals(10, vlaSum2D(2, cValuesOf(1, 2, 3, 4))) + assertEquals(21, vlaSum2DBothDimensions(2, 3, cValuesOf(1, 2, 3, 4, 5, 6))) + + // Not supported by clang: + // assertEquals(10, vlaSum2DForward(cValuesOf(1, 2, 3, 4), 2)) + + assertEquals(0u, StrictEnum1.StrictEnum1A.value) + assertEquals(1u, StrictEnum2.StrictEnum2B.value) + assertEquals(0u, NonStrictEnum1A) + assertEquals(1u, NonStrictEnum2B) + assertEquals(1, EnumCharBase.EnumCharBaseB.value) + assertEquals(3, sendEnum(EnumCharBase.EnumCharBaseB)) + assertEquals('a'.toByte(), EnumExplicitCharA) + assertEquals('b'.toByte(), EnumExplicitCharB) + assertEquals(EnumExplicitCharA, EnumExplicitCharDup) +} + diff --git a/kotlin-native/backend.native/tests/interop/basics/unable_to_import.def b/kotlin-native/backend.native/tests/interop/basics/unable_to_import.def new file mode 100644 index 00000000000..a877fb6c03c --- /dev/null +++ b/kotlin-native/backend.native/tests/interop/basics/unable_to_import.def @@ -0,0 +1,10 @@ +--- +int global; +#define global bad macro + +void foo(void); +#define foo < + +// Setter for x should not be generated. +typedef const int cint; +cint x; diff --git a/kotlin-native/backend.native/tests/interop/basics/union.kt b/kotlin-native/backend.native/tests/interop/basics/union.kt new file mode 100644 index 00000000000..9eb21d51921 --- /dev/null +++ b/kotlin-native/backend.native/tests/interop/basics/union.kt @@ -0,0 +1,36 @@ +import cunion.* +import kotlinx.cinterop.* +import kotlin.native.* +import kotlin.test.* + +fun main() { + memScoped { + val basicUnion = alloc() + for (value in Short.MIN_VALUE..Short.MAX_VALUE) { + basicUnion.ll = value.toLong() + val expected = if (Platform.isLittleEndian) { + value + } else { + value.toLong() ushr (Long.SIZE_BITS - Short.SIZE_BITS) + } + assertEquals(expected.toShort(), basicUnion.s) + } + } + memScoped { + val struct = alloc() + struct.`as`.i = Float.NaN.toRawBits() + assertEquals(Float.NaN, struct.`as`.f) + } + memScoped { + val union = alloc() + union.b = 1u + var expected = if (Platform.isLittleEndian) { + 1u + } else { + 1u shl (Int.SIZE_BITS - Byte.SIZE_BITS) + } + assertEquals(expected, union.i) + union.i = 0u + assertEquals(0u, union.b) + } +} \ No newline at end of file diff --git a/kotlin-native/backend.native/tests/interop/basics/unsupported.kt b/kotlin-native/backend.native/tests/interop/basics/unsupported.kt new file mode 100644 index 00000000000..08bfe60a730 --- /dev/null +++ b/kotlin-native/backend.native/tests/interop/basics/unsupported.kt @@ -0,0 +1,12 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +import kotlin.test.* +import cunsupported.* + +fun main(args: Array) { + noAttr() + noTargetAttr() +} diff --git a/kotlin-native/backend.native/tests/interop/basics/values.kt b/kotlin-native/backend.native/tests/interop/basics/values.kt new file mode 100644 index 00000000000..8a6e03941c8 --- /dev/null +++ b/kotlin-native/backend.native/tests/interop/basics/values.kt @@ -0,0 +1,10 @@ +import kotlinx.cinterop.* +import kotlin.test.* +import cvalues.* + +fun main() { + assertTrue(isNullString(null)) + assertTrue(isNullWString(null)) + assertFalse(isNullString("a")) + assertFalse(isNullWString("b")) +} \ No newline at end of file diff --git a/kotlin-native/backend.native/tests/interop/basics/vectors.kt b/kotlin-native/backend.native/tests/interop/basics/vectors.kt new file mode 100644 index 00000000000..52b1f294693 --- /dev/null +++ b/kotlin-native/backend.native/tests/interop/basics/vectors.kt @@ -0,0 +1,35 @@ +import kotlinx.cinterop.* +import kotlin.native.* +import kotlin.test.* +import cvectors.* + +fun isWin32() = Platform.osFamily == OsFamily.WINDOWS && Platform.cpuArchitecture == CpuArchitecture.X86 + +fun main(args: Array) { + val mimalloc = args.takeIf { it.size == 1 }?.get(0) == "mimalloc" + + // See KT-37272. Fixed in mimalloc + if (mimalloc || !isWin32()) { + produceComplex().useContents { + assertEquals(vec4f, vectorOf(1.0f, 1.0f, 1.0f, 1.0f)) + vec4f = vectorOf(0.0f, 0.0f, 0.0f, 0.0f) + assertEquals(vec4f, vectorOf(0.0f, 0.0f, 0.0f, 0.0f)) + } + } + + // FIXME: KT-36285 + if (Platform.osFamily != OsFamily.LINUX || Platform.cpuArchitecture != CpuArchitecture.ARM32) { + assertEquals(49, sendV4I(vectorOf(1, 2, 3, 4))) + } + assertEquals(49, (sendV4F(vectorOf(1f, 2f, 3f, 4f)) + 0.00001).toInt()) + + if (mimalloc || !isWin32()) { + memScoped { + val vector = alloc().also { + it.value = vectorOf(1, 2, 3, 4) + } + assertEquals(vector.value, vectorOf(1, 2, 3, 4)) + } + } +} + diff --git a/kotlin-native/backend.native/tests/interop/basics/withSpaces.kt b/kotlin-native/backend.native/tests/interop/basics/withSpaces.kt new file mode 100644 index 00000000000..71d8bee4a17 --- /dev/null +++ b/kotlin-native/backend.native/tests/interop/basics/withSpaces.kt @@ -0,0 +1,12 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +import kotlin.test.* +import kotlinx.cinterop.* +import withSpaces.* + +fun main(args: Array) { + customCompare("first", "second") +} diff --git a/kotlin-native/backend.native/tests/interop/cleaners/cleaners.kt b/kotlin-native/backend.native/tests/interop/cleaners/cleaners.kt new file mode 100644 index 00000000000..a00050c863a --- /dev/null +++ b/kotlin-native/backend.native/tests/interop/cleaners/cleaners.kt @@ -0,0 +1,26 @@ +/* + * Copyright 2010-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ +@file:OptIn(ExperimentalStdlibApi::class) + +import kotlin.native.internal.* + +fun createCleaner() { + createCleaner(42) { + println(it) + } +} + +fun performGC() { + GC.collect() + performGCOnCleanerWorker() +} + +private var globalCleaner: Cleaner? = null + +fun initializeGlobalCleaner() { + globalCleaner = createCleaner(11) { + println(it) + } +} diff --git a/kotlin-native/backend.native/tests/interop/cleaners/leak.cpp b/kotlin-native/backend.native/tests/interop/cleaners/leak.cpp new file mode 100644 index 00000000000..092bb70cc2c --- /dev/null +++ b/kotlin-native/backend.native/tests/interop/cleaners/leak.cpp @@ -0,0 +1,11 @@ +/* + * Copyright 2010-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +#include "testlib_api.h" + +int main() { + testlib_symbols()->kotlin.root.initializeGlobalCleaner(); + return 0; +} diff --git a/kotlin-native/backend.native/tests/interop/cleaners/main_thread.cpp b/kotlin-native/backend.native/tests/interop/cleaners/main_thread.cpp new file mode 100644 index 00000000000..68777ada796 --- /dev/null +++ b/kotlin-native/backend.native/tests/interop/cleaners/main_thread.cpp @@ -0,0 +1,12 @@ +/* + * Copyright 2010-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +#include "testlib_api.h" + +int main() { + testlib_symbols()->kotlin.root.createCleaner(); + testlib_symbols()->kotlin.root.performGC(); + return 0; +} diff --git a/kotlin-native/backend.native/tests/interop/cleaners/second_thread.cpp b/kotlin-native/backend.native/tests/interop/cleaners/second_thread.cpp new file mode 100644 index 00000000000..9ab0dda0941 --- /dev/null +++ b/kotlin-native/backend.native/tests/interop/cleaners/second_thread.cpp @@ -0,0 +1,15 @@ +/* + * Copyright 2010-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +#include "testlib_api.h" + +#include + +int main() { + std::thread t([]() { testlib_symbols()->kotlin.root.createCleaner(); }); + t.join(); + testlib_symbols()->kotlin.root.performGC(); + return 0; +} diff --git a/kotlin-native/backend.native/tests/interop/concurrentTerminate/async.cpp b/kotlin-native/backend.native/tests/interop/concurrentTerminate/async.cpp new file mode 100644 index 00000000000..b7c2251f4f3 --- /dev/null +++ b/kotlin-native/backend.native/tests/interop/concurrentTerminate/async.cpp @@ -0,0 +1,29 @@ +#include +#include +#include +#include +#include // signal.h + +#include "async.h" + +int test_ConcurrentTerminate() { + signal(SIGABRT, *[](int){ exit(99); }); // Windows does not have sigaction + + std::vector> futures; +#ifdef __linux__ + // TODO: invalid terminate handler called from bridge on non-main thread on Linux X64 + throw std::runtime_error("Reporting error!"); +#endif + + for (size_t i = 0; i < 100; ++i) { + futures.emplace_back(std::async(std::launch::async, + [](size_t param) { + std::this_thread::sleep_for(std::chrono::milliseconds(param)); + throw std::runtime_error("Reporting error!"); + }, + 200 - i)); + } + + for (auto &future : futures) future.get(); + return 0; +} diff --git a/kotlin-native/backend.native/tests/interop/concurrentTerminate/async.h b/kotlin-native/backend.native/tests/interop/concurrentTerminate/async.h new file mode 100644 index 00000000000..3eed47c4a5c --- /dev/null +++ b/kotlin-native/backend.native/tests/interop/concurrentTerminate/async.h @@ -0,0 +1,9 @@ +#ifdef __cplusplus +extern "C" { +#endif + +int test_ConcurrentTerminate(); + +#ifdef __cplusplus +} +#endif diff --git a/kotlin-native/backend.native/tests/interop/concurrentTerminate/concurrentTerminate.def b/kotlin-native/backend.native/tests/interop/concurrentTerminate/concurrentTerminate.def new file mode 100644 index 00000000000..3174df6637d --- /dev/null +++ b/kotlin-native/backend.native/tests/interop/concurrentTerminate/concurrentTerminate.def @@ -0,0 +1,5 @@ +package async + +--- + +int test_ConcurrentTerminate(); diff --git a/kotlin-native/backend.native/tests/interop/concurrentTerminate/main.cpp b/kotlin-native/backend.native/tests/interop/concurrentTerminate/main.cpp new file mode 100644 index 00000000000..451a73c1408 --- /dev/null +++ b/kotlin-native/backend.native/tests/interop/concurrentTerminate/main.cpp @@ -0,0 +1,44 @@ +#include "testlib_api.h" + +#include +#include +#include +#include +#include +#include // signal.h + +using namespace std; + +static +int runConcurrent() { + + std::vector> futures; + + for (size_t i = 0; i < 100; ++i) { + futures.emplace_back(std::async(std::launch::async, + [](auto delay) { + std::this_thread::sleep_for(std::chrono::milliseconds(delay)); + testlib_symbols()->kotlin.root.testTerminate(); + }, + 100)); + } + + for (auto &future : futures) future.get(); + return 0; +} + +int main() { + signal(SIGABRT, *[](int){ exit(99); }); // Windows does not have sigaction + + set_terminate([](){ + cout << "This is the original terminate handler\n" << flush; + std::abort(); + }); + + try { + runConcurrent(); + } catch(...) { + std::cerr << "Unknown exception caught\n" << std::flush; + } + return 0; +} \ No newline at end of file diff --git a/kotlin-native/backend.native/tests/interop/concurrentTerminate/main.kt b/kotlin-native/backend.native/tests/interop/concurrentTerminate/main.kt new file mode 100644 index 00000000000..d9bbd63bcdd --- /dev/null +++ b/kotlin-native/backend.native/tests/interop/concurrentTerminate/main.kt @@ -0,0 +1,7 @@ +import async.* +import kotlinx.cinterop.* + +fun main() { + test_ConcurrentTerminate() + println("This is not expected.") +} \ No newline at end of file diff --git a/kotlin-native/backend.native/tests/interop/concurrentTerminate/reverseInterop.kt b/kotlin-native/backend.native/tests/interop/concurrentTerminate/reverseInterop.kt new file mode 100644 index 00000000000..9ba62825f6a --- /dev/null +++ b/kotlin-native/backend.native/tests/interop/concurrentTerminate/reverseInterop.kt @@ -0,0 +1,5 @@ +import kotlin.system.exitProcess + +fun testTerminate() { + throw RuntimeException("Example") +} \ No newline at end of file diff --git a/kotlin-native/backend.native/tests/interop/embedStaticLibraries/1.c b/kotlin-native/backend.native/tests/interop/embedStaticLibraries/1.c new file mode 100644 index 00000000000..1b08c920edb --- /dev/null +++ b/kotlin-native/backend.native/tests/interop/embedStaticLibraries/1.c @@ -0,0 +1,3 @@ +int get1() { + return 1; +} diff --git a/kotlin-native/backend.native/tests/interop/embedStaticLibraries/2.c b/kotlin-native/backend.native/tests/interop/embedStaticLibraries/2.c new file mode 100644 index 00000000000..52b9914d8e6 --- /dev/null +++ b/kotlin-native/backend.native/tests/interop/embedStaticLibraries/2.c @@ -0,0 +1,3 @@ +int get2() { + return 2; +} diff --git a/kotlin-native/backend.native/tests/interop/embedStaticLibraries/3.c b/kotlin-native/backend.native/tests/interop/embedStaticLibraries/3.c new file mode 100644 index 00000000000..17b9646ec50 --- /dev/null +++ b/kotlin-native/backend.native/tests/interop/embedStaticLibraries/3.c @@ -0,0 +1,3 @@ +int get3() { + return 3; +} diff --git a/kotlin-native/backend.native/tests/interop/embedStaticLibraries/4.c b/kotlin-native/backend.native/tests/interop/embedStaticLibraries/4.c new file mode 100644 index 00000000000..ab697746441 --- /dev/null +++ b/kotlin-native/backend.native/tests/interop/embedStaticLibraries/4.c @@ -0,0 +1,3 @@ +int get4() { + return 4; +} diff --git a/kotlin-native/backend.native/tests/interop/embedStaticLibraries/embedStaticLibraries.def b/kotlin-native/backend.native/tests/interop/embedStaticLibraries/embedStaticLibraries.def new file mode 100644 index 00000000000..bd6d7b82b73 --- /dev/null +++ b/kotlin-native/backend.native/tests/interop/embedStaticLibraries/embedStaticLibraries.def @@ -0,0 +1,2 @@ +libraryPaths = backend.native/tests/build/embedStaticLibraries +staticLibraries = 3.a 4.a diff --git a/kotlin-native/backend.native/tests/interop/embedStaticLibraries/embedStaticLibraries.h b/kotlin-native/backend.native/tests/interop/embedStaticLibraries/embedStaticLibraries.h new file mode 100644 index 00000000000..e481df854db --- /dev/null +++ b/kotlin-native/backend.native/tests/interop/embedStaticLibraries/embedStaticLibraries.h @@ -0,0 +1,4 @@ +int get1(void); +int get2(void); +int get3(void); +int get4(void); diff --git a/kotlin-native/backend.native/tests/interop/embedStaticLibraries/main.kt b/kotlin-native/backend.native/tests/interop/embedStaticLibraries/main.kt new file mode 100644 index 00000000000..9f8e8902570 --- /dev/null +++ b/kotlin-native/backend.native/tests/interop/embedStaticLibraries/main.kt @@ -0,0 +1,9 @@ +import kotlin.test.* +import embedStaticLibraries.* + +fun main() { + assertEquals(1, get1()) + assertEquals(2, get2()) + assertEquals(3, get3()) + assertEquals(4, get4()) +} diff --git a/kotlin-native/backend.native/tests/interop/incomplete_types/library.cpp b/kotlin-native/backend.native/tests/interop/incomplete_types/library.cpp new file mode 100644 index 00000000000..60d1bc8750f --- /dev/null +++ b/kotlin-native/backend.native/tests/interop/incomplete_types/library.cpp @@ -0,0 +1,50 @@ +#include "library.h" + +extern "C" { + +struct S { + const char* name; +}; + +struct S s = { + .name = "initial" +}; + +void setContent(struct S* s, const char* name) { + s->name = name; +} + +const char* getContent(struct S* s) { + return s->name; +} + +union U { + float f; + double d; +}; + +void setDouble(union U* u, double value) { + u->d = value; +} + +double getDouble(union U* u) { + return u->d; +} + +union U u = { + .d = 0.0 +}; + +char array[5] = { 0, 0, 0, 0, 0 }; + +void setArrayValue(char* array, char value) { + for (int i = 0; i < 5; ++i) { + array[i] = value; + } +} + +int arrayLength() { + return sizeof(array) / sizeof(char); +} + +} \ No newline at end of file diff --git a/kotlin-native/backend.native/tests/interop/incomplete_types/library.def b/kotlin-native/backend.native/tests/interop/incomplete_types/library.def new file mode 100644 index 00000000000..e69de29bb2d diff --git a/kotlin-native/backend.native/tests/interop/incomplete_types/library.h b/kotlin-native/backend.native/tests/interop/incomplete_types/library.h new file mode 100644 index 00000000000..ff02c8894a7 --- /dev/null +++ b/kotlin-native/backend.native/tests/interop/incomplete_types/library.h @@ -0,0 +1,27 @@ +#ifdef __cplusplus +extern "C" { +#endif + +// Forward declaration. +struct S; +extern struct S s; + +const char* getContent(struct S* s); +void setContent(struct S* s, const char* name); + +union U; +extern union U u; + +double getDouble(union U* u); +void setDouble(union U* u, double value); + +// Global array of unknown size. +extern char array[]; + + +int arrayLength(); +void setArrayValue(char* array, char value); + +#ifdef __cplusplus +} +#endif \ No newline at end of file diff --git a/kotlin-native/backend.native/tests/interop/incomplete_types/main.kt b/kotlin-native/backend.native/tests/interop/incomplete_types/main.kt new file mode 100644 index 00000000000..8118c449c29 --- /dev/null +++ b/kotlin-native/backend.native/tests/interop/incomplete_types/main.kt @@ -0,0 +1,25 @@ +import library.* +import kotlinx.cinterop.* +import kotlin.test.* + +fun main() { + assertNotNull(s.ptr) + assertNotNull(u.ptr) + assertNotNull(array) + + assertEquals("initial", getContent(s.ptr)?.toKString()) + setContent(s.ptr, "yo") + assertEquals("yo", getContent(s.ptr)?.toKString()) + + assertEquals(0.0, getDouble(u.ptr)) + setDouble(u.ptr, Double.MIN_VALUE) + assertEquals(Double.MIN_VALUE, getDouble(u.ptr)) + + for (i in 0 until arrayLength()) { + assertEquals(0x0, array[i]) + } + setArrayValue(array, 0x1) + for (i in 0 until arrayLength()) { + assertEquals(0x1, array[i]) + } +} \ No newline at end of file diff --git a/kotlin-native/backend.native/tests/interop/kt42397/knlibrary.kt b/kotlin-native/backend.native/tests/interop/kt42397/knlibrary.kt new file mode 100644 index 00000000000..eaefd5a1ad6 --- /dev/null +++ b/kotlin-native/backend.native/tests/interop/kt42397/knlibrary.kt @@ -0,0 +1,10 @@ +package knlibrary + +// The following 2 singletons are unused. However, since we are generating C bindings for them, +// they should be marked as used, so that the code generator emits their deinitialization. + +object A {} + +class B { + companion object {} +} diff --git a/kotlin-native/backend.native/tests/interop/kt42397/test.cpp b/kotlin-native/backend.native/tests/interop/kt42397/test.cpp new file mode 100644 index 00000000000..2bd5cc286db --- /dev/null +++ b/kotlin-native/backend.native/tests/interop/kt42397/test.cpp @@ -0,0 +1,26 @@ +#include "testlib_api.h" + +#include + +int main() { + auto t = std::thread([] { + auto lib = testlib_symbols(); + + // Initialize A and B.Companion and get their stable pointers. + auto a = lib->kotlin.root.knlibrary.A._instance(); + auto bCompanion = lib->kotlin.root.knlibrary.B.Companion._instance(); + + // Now, dispose of the stable pointers. + lib->DisposeStablePointer(bCompanion.pinned); + lib->DisposeStablePointer(a.pinned); + + // A and B.Companion now are owned by the global references only. + }); + + // This causes Kotlin runtime full deinitialization, because `t` is the only thread + // with the Kotlin runtime. So, all the globals will get deinitialized and memory + // leak checker will get executed (because .kt code is compiled with -g). + t.join(); + + return 0; +} diff --git a/kotlin-native/backend.native/tests/interop/libiconv.kt b/kotlin-native/backend.native/tests/interop/libiconv.kt new file mode 100644 index 00000000000..3dc58ba4610 --- /dev/null +++ b/kotlin-native/backend.native/tests/interop/libiconv.kt @@ -0,0 +1,44 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +import kotlinx.cinterop.* +import platform.iconv.* +import platform.posix.size_tVar + +fun main(args: Array) { + + val sourceByteArray = "Hello!".encodeToByteArray() + + val golden = listOf(0x48, 0x65, 0x6C, 0x6C, 0x6F, 0x21) + + memScoped { + + val sourceLength = alloc() + val destLength = alloc() + + val sourceBytes = allocArrayOf(sourceByteArray) + val destBytes = allocArray(golden.size) + + val sourcePtr = alloc>() + sourcePtr.value = sourceBytes + + val destPtr = alloc>() + destPtr.value = destBytes + + sourceLength.value = sourceByteArray.size.convert() + destLength.value = golden.size.convert() + + val conversion = iconv_open("UTF-8", "LATIN1") + + iconv(conversion, sourcePtr.ptr, sourceLength.ptr, destPtr.ptr, destLength.ptr) + + golden.forEachIndexed { index, it -> + println("$it ${destBytes[index]}") + it == destBytes[index].toInt() + } + + iconv_close(conversion) + } +} diff --git a/kotlin-native/backend.native/tests/interop/objc/Localizable.stringsdict b/kotlin-native/backend.native/tests/interop/objc/Localizable.stringsdict new file mode 100644 index 00000000000..1f284ab9b84 --- /dev/null +++ b/kotlin-native/backend.native/tests/interop/objc/Localizable.stringsdict @@ -0,0 +1,27 @@ + + + + + + + + screen_main_plural_string + + NSStringLocalizedFormatKey + %#@value@ + value + + NSStringFormatSpecTypeKey + NSStringPluralRuleType + NSStringFormatValueTypeKey + d + other + Plural: %d apples + one + Plural: one apple + zero + Plural: no apples + + + + diff --git a/kotlin-native/backend.native/tests/interop/objc/allocException.kt b/kotlin-native/backend.native/tests/interop/objc/allocException.kt new file mode 100644 index 00000000000..1f028457ce5 --- /dev/null +++ b/kotlin-native/backend.native/tests/interop/objc/allocException.kt @@ -0,0 +1,30 @@ +/* + * Copyright 2010-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +import platform.Foundation.* +import platform.objc.* +import kotlin.test.* + +import kotlinx.cinterop.* +import platform.posix.* +import kotlin.system.exitProcess + +fun exc_handler(x: Any?) : Unit { + println("Uncaught exception handler") + println(x.toString()) + exitProcess(0) +} + +fun main() { + // This does not work anymore, as NSException propagated as ForeignException + // so we got `Uncaught Kotlin exception` instead. Use normal try/catch. + objc_setUncaughtExceptionHandler(staticCFunction(::exc_handler)) + + try { + println(NSJSONSerialization()) + } catch (e: Exception) { // ForeignException expected + println(e) + } +} diff --git a/kotlin-native/backend.native/tests/interop/objc/foreignException/objcExceptionMode.def b/kotlin-native/backend.native/tests/interop/objc/foreignException/objcExceptionMode.def new file mode 100644 index 00000000000..a4e99951650 --- /dev/null +++ b/kotlin-native/backend.native/tests/interop/objc/foreignException/objcExceptionMode.def @@ -0,0 +1,3 @@ +language = Objective-C +headerFilter = **/objc_wrap.h +linkerOpts = -lobjcexception diff --git a/kotlin-native/backend.native/tests/interop/objc/foreignException/objcExceptionMode.kt b/kotlin-native/backend.native/tests/interop/objc/foreignException/objcExceptionMode.kt new file mode 100644 index 00000000000..722b614772f --- /dev/null +++ b/kotlin-native/backend.native/tests/interop/objc/foreignException/objcExceptionMode.kt @@ -0,0 +1,47 @@ +/* + * Test different behavior depending on foreignExceptionMode option + */ + +import kotlin.test.* +import objcExceptionMode.* +import kotlinx.cinterop.* +import platform.objc.* +import kotlin.system.exitProcess + +@Suppress("VARIABLE_WITH_REDUNDANT_INITIALIZER") +@Test fun testKT35056() { + val name = "Some native exception" + val reason = "Illegal value" + var finallyBlockTest = "FAILED" + var catchBlockTest = "FAILED" + try { + raiseExc(name, reason) + assertNotEquals("FAILED", catchBlockTest) // shall not get here anyway + } catch (e: ForeignException) { + val ret = logExc(e.nativeException) // return NSException name + assertEquals(name, ret) + assertEquals("$name:: $reason", e.message) + println("OK: ForeignException") + catchBlockTest = "PASSED" + } finally { + finallyBlockTest = "PASSED" + } + assertEquals("PASSED", catchBlockTest) + assertEquals("PASSED", finallyBlockTest) +} + +@Suppress("UNUSED_PARAMETER") +fun abnormal_handler(x: Any?) : Unit { + println("OK: Ends with uncaught exception handler") + exitProcess(0) +} + +fun main() { + // Depending on the `foreignxceptionMode` option (def file or cinterop cli) this test should ends + // normally with `ForeignException` handled or abnormally with `abnormal_handler`. + // Test shall validate output (golden value) from `abnormal_handler`. + + objc_setUncaughtExceptionHandler(staticCFunction(::abnormal_handler)) + + testKT35056() +} \ No newline at end of file diff --git a/kotlin-native/backend.native/tests/interop/objc/foreignException/objc_wrap.def b/kotlin-native/backend.native/tests/interop/objc/foreignException/objc_wrap.def new file mode 100644 index 00000000000..48416e6d2d0 --- /dev/null +++ b/kotlin-native/backend.native/tests/interop/objc/foreignException/objc_wrap.def @@ -0,0 +1,4 @@ +language = Objective-C +headerFilter = **/objc_wrap.h +linkerOpts = -lobjcexception +foreignExceptionMode = objc-wrap diff --git a/kotlin-native/backend.native/tests/interop/objc/foreignException/objc_wrap.h b/kotlin-native/backend.native/tests/interop/objc/foreignException/objc_wrap.h new file mode 100644 index 00000000000..384a558bbaa --- /dev/null +++ b/kotlin-native/backend.native/tests/interop/objc/foreignException/objc_wrap.h @@ -0,0 +1,9 @@ +#import + +void raiseExc(id name, id reason); +id logExc(id exception); + +@interface Foo : NSObject +- (void)instanceMethodThrow:(id)name reason:(id)reason; ++ (void)classMethodThrow:(id)name reason:(id)reason; +@end diff --git a/kotlin-native/backend.native/tests/interop/objc/foreignException/objc_wrap.kt b/kotlin-native/backend.native/tests/interop/objc/foreignException/objc_wrap.kt new file mode 100644 index 00000000000..1d71721afb6 --- /dev/null +++ b/kotlin-native/backend.native/tests/interop/objc/foreignException/objc_wrap.kt @@ -0,0 +1,53 @@ +/* + * Test different types of callable with foreignExceptionMode=objc-wrap + */ + +import kotlin.test.* +//import objcTests.* +import objc_wrap.* +import kotlinx.cinterop.* + +fun testInner(name: String, reason: String) { + var finallyBlockTest = "FAILED" + var catchBlockTest = "NOT EXPECTED" + try { + raiseExc(name, reason) + } catch (e: RuntimeException) { + catchBlockTest = "This shouldn't happen" + } finally { + finallyBlockTest = "PASSED" + } + assertEquals("NOT EXPECTED", catchBlockTest) + assertEquals("PASSED", finallyBlockTest) +} + +typealias CallMe = (String, String) -> Unit + +@Test fun testExceptionWrap(raise: CallMe) { + val name = "Some native exception" + val reason = "Illegal value" + var finallyBlockTest = "FAILED" + var catchBlockTest = "FAILED" + try { + raise(name, reason) + } catch (e: ForeignException) { + val ret = logExc(e.nativeException) // return NSException name + assertEquals(name, ret) + assertEquals("$name:: $reason", e.message) + catchBlockTest = "PASSED" + } finally { + finallyBlockTest = "PASSED" + } + assertEquals("PASSED", catchBlockTest) + assertEquals("PASSED", finallyBlockTest) +} + +class Bar() : Foo() + +fun main() { + testExceptionWrap(::raiseExc) // simple + testExceptionWrap(::testInner) // nested try block + testExceptionWrap(Foo::classMethodThrow) // class method + testExceptionWrap(Foo()::instanceMethodThrow) // instance method + testExceptionWrap(Bar()::instanceMethodThrow) // fake override +} \ No newline at end of file diff --git a/kotlin-native/backend.native/tests/interop/objc/foreignException/objc_wrap.m b/kotlin-native/backend.native/tests/interop/objc/foreignException/objc_wrap.m new file mode 100644 index 00000000000..d77e6de0ab3 --- /dev/null +++ b/kotlin-native/backend.native/tests/interop/objc/foreignException/objc_wrap.m @@ -0,0 +1,21 @@ +#include "objc_wrap.h" + +#import + +void raiseExc(id name, id reason) { + [NSException raise:name format:@"%@", reason]; +} + +id logExc(id exc) { + assert([exc isKindOfClass:[NSException class]]); + return ((NSException*)exc).name; +} + +@implementation Foo : NSObject +- (void) instanceMethodThrow:(id)name reason:(id)reason { + raiseExc(name, reason); +} ++ (void) classMethodThrow:(id)name reason:(id)reason { + raiseExc(name, reason); +} +@end diff --git a/kotlin-native/backend.native/tests/interop/objc/illegal_sharing.kt b/kotlin-native/backend.native/tests/interop/objc/illegal_sharing.kt new file mode 100644 index 00000000000..12f7bfe0283 --- /dev/null +++ b/kotlin-native/backend.native/tests/interop/objc/illegal_sharing.kt @@ -0,0 +1,30 @@ +import kotlin.native.concurrent.* +import kotlin.test.* +import platform.Foundation.* +import platform.darwin.NSObject + +fun Worker.runInWorker(block: () -> Unit) { + this.execute(TransferMode.SAFE, { block.freeze() }) { + it() + }.result +} + +private class NSObjectImpl : NSObject() { + var x = 111 +} + +// Also see counterpart in interop/objc/tests/sharing.kt +fun main() = withWorker { + val obj = NSObjectImpl() + val array: NSArray = NSMutableArray().apply { + addObject(obj) + } + + assertFalse(obj.isFrozen) + + println("Before") + runInWorker { + array.objectAtIndex(0) + } + println("After") +} diff --git a/kotlin-native/backend.native/tests/interop/objc/illegal_sharing_with_weak/main.kt b/kotlin-native/backend.native/tests/interop/objc/illegal_sharing_with_weak/main.kt new file mode 100644 index 00000000000..d615e3bbc88 --- /dev/null +++ b/kotlin-native/backend.native/tests/interop/objc/illegal_sharing_with_weak/main.kt @@ -0,0 +1,28 @@ +import kotlin.native.concurrent.* +import kotlinx.cinterop.autoreleasepool +import objclib.* + +fun main() { + autoreleasepool { + run() + } +} + +private class NSObjectImpl : NSObject() { + var x = 111 +} + +fun run() = withWorker { + val obj = NSObjectImpl() + setObject(obj) + + println("Before") + val isAlive = try { + execute(TransferMode.SAFE, {}) { + isObjectAliveShouldCrash() + }.result + } catch (e: Throwable) { + false + } + println("After $isAlive") +} diff --git a/kotlin-native/backend.native/tests/interop/objc/illegal_sharing_with_weak/objclib.def b/kotlin-native/backend.native/tests/interop/objc/illegal_sharing_with_weak/objclib.def new file mode 100644 index 00000000000..758f44a49a2 --- /dev/null +++ b/kotlin-native/backend.native/tests/interop/objc/illegal_sharing_with_weak/objclib.def @@ -0,0 +1,2 @@ +language = Objective-C +headerFilter = **/objclib.h diff --git a/kotlin-native/backend.native/tests/interop/objc/illegal_sharing_with_weak/objclib.h b/kotlin-native/backend.native/tests/interop/objc/illegal_sharing_with_weak/objclib.h new file mode 100644 index 00000000000..b44bffe7dc3 --- /dev/null +++ b/kotlin-native/backend.native/tests/interop/objc/illegal_sharing_with_weak/objclib.h @@ -0,0 +1,13 @@ +#import + +static NSObject* __weak globalObject = nil; + +void setObject(NSObject* obj) { + globalObject = obj; +} + +// Make sure this function persists, because the test expects to find this function in the stack trace. +__attribute__((noinline)) +bool isObjectAliveShouldCrash() { + return globalObject != nil; +} diff --git a/kotlin-native/backend.native/tests/interop/objc/kt34467/foo.h b/kotlin-native/backend.native/tests/interop/objc/kt34467/foo.h new file mode 100644 index 00000000000..6f57fb0a9b4 --- /dev/null +++ b/kotlin-native/backend.native/tests/interop/objc/kt34467/foo.h @@ -0,0 +1 @@ +#define ANSWER 42 \ No newline at end of file diff --git a/kotlin-native/backend.native/tests/interop/objc/kt34467/foo.kt b/kotlin-native/backend.native/tests/interop/objc/kt34467/foo.kt new file mode 100644 index 00000000000..34dfbdfc5ce --- /dev/null +++ b/kotlin-native/backend.native/tests/interop/objc/kt34467/foo.kt @@ -0,0 +1,6 @@ +import module_library.* + +fun main() { + println("OK") + println(ANSWER) +} \ No newline at end of file diff --git a/kotlin-native/backend.native/tests/interop/objc/kt34467/module_library.def b/kotlin-native/backend.native/tests/interop/objc/kt34467/module_library.def new file mode 100644 index 00000000000..3038e078a4f --- /dev/null +++ b/kotlin-native/backend.native/tests/interop/objc/kt34467/module_library.def @@ -0,0 +1,2 @@ +language = Objective-C +modules = module_library \ No newline at end of file diff --git a/kotlin-native/backend.native/tests/interop/objc/kt34467/module_library.modulemap b/kotlin-native/backend.native/tests/interop/objc/kt34467/module_library.modulemap new file mode 100644 index 00000000000..b9fbc34f98d --- /dev/null +++ b/kotlin-native/backend.native/tests/interop/objc/kt34467/module_library.modulemap @@ -0,0 +1,6 @@ +module module_library { + umbrella header "module_library_umbrella.h" + + export * + module * { export * } +} diff --git a/kotlin-native/backend.native/tests/interop/objc/kt34467/module_library_umbrella.h b/kotlin-native/backend.native/tests/interop/objc/kt34467/module_library_umbrella.h new file mode 100644 index 00000000000..e3262d6e539 --- /dev/null +++ b/kotlin-native/backend.native/tests/interop/objc/kt34467/module_library_umbrella.h @@ -0,0 +1 @@ +#import diff --git a/kotlin-native/backend.native/tests/interop/objc/msg_send/main.kt b/kotlin-native/backend.native/tests/interop/objc/msg_send/main.kt new file mode 100644 index 00000000000..84ba36a842f --- /dev/null +++ b/kotlin-native/backend.native/tests/interop/objc/msg_send/main.kt @@ -0,0 +1,58 @@ +import messaging.* +import kotlinx.cinterop.* +import kotlin.test.* + +fun main(args: Array) { + autoreleasepool { + primitives() + aggregates() + } +} + +private fun primitives() { + assertEquals(3.14f, PrimitiveTestSubject.floatFn()) + assertEquals(3.14, PrimitiveTestSubject.doubleFn()) + assertEquals(42, PrimitiveTestSubject.intFn()) + assertEquals(vectorOf(2f, 4f, 5f, 8f), PrimitiveTestSubject.simdFn()) +} + +private fun aggregates() { + AggregateTestSubject.singleFloatFn().useContents { + assertEquals(3.14f, f) + } + AggregateTestSubject.simplePackedFn().useContents { + assertEquals('0'.toByte(), f1) + assertEquals(111, f2) + } + AggregateTestSubject.evenSmallerPackedFn().useContents { + assertEquals('x'.toByte(), x) + assertEquals(169, y) + assertEquals('z'.toByte(), z) + } + AggregateTestSubject.homogeneousBigFn().useContents { + assertEquals(1.0f, f1) + assertEquals(2.0f, f2) + assertEquals(3.0f, f3) + assertEquals(4.0f, f4) + assertEquals(5.0f, f5) + assertEquals(6.0f, f6) + assertEquals(7.0f, f7) + assertEquals(8.0f, f8) + } + AggregateTestSubject.homogeneousSmallFn().useContents { + assertEquals(1.0f, f1) + assertEquals(2.0f, f2) + assertEquals(3.0f, f3) + assertEquals(4.0f, f4) + } + AggregateTestSubject.simd_quatfFn().useContents { + assertEquals(vectorOf(1f, 4f, 9f, 25f), vector) + } + AggregateTestSubject.geterogeneousSmallFn().useContents { + assertEquals(1, s1) + assertEquals(vectorOf(1f, 4f, 9f, 25f), v2) + assertEquals(3f, f3) + assertEquals(4, i4) + } +} + diff --git a/kotlin-native/backend.native/tests/interop/objc/msg_send/messaging.def b/kotlin-native/backend.native/tests/interop/objc/msg_send/messaging.def new file mode 100644 index 00000000000..c1aab35b013 --- /dev/null +++ b/kotlin-native/backend.native/tests/interop/objc/msg_send/messaging.def @@ -0,0 +1,3 @@ +language = Objective-C +headerFilter = **/messaging.h +linkerOpts = -lobjcmessaging \ No newline at end of file diff --git a/kotlin-native/backend.native/tests/interop/objc/msg_send/messaging.h b/kotlin-native/backend.native/tests/interop/objc/msg_send/messaging.h new file mode 100644 index 00000000000..bb80a427d26 --- /dev/null +++ b/kotlin-native/backend.native/tests/interop/objc/msg_send/messaging.h @@ -0,0 +1,68 @@ +#import +#include + +@interface PrimitiveTestSubject : NSObject + ++ (int)intFn; ++ (float)floatFn; ++ (double)doubleFn; ++ (simd_float4)simdFn; + +@end; + +typedef struct { + float f; +} SingleFloat; + +typedef struct __attribute__((packed)) { + char f1; + short f2; + char f3; + char f4; +} SimplePacked; + +typedef struct __attribute__((packed)) { + char x; + short y; + char z; +} EvenSmallerPacked; + +typedef struct { + float f1; + float f2; + float f3; + float f4; +} HomogeneousSmall; + +typedef struct { + float f1; + float f2; + float f3; + float f4; + float f5; + float f6; + float f7; + float f8; +} HomogeneousBig; + +// TODO: Add more cases later: SIMD, bitfields. + +typedef struct { + short s1; + simd_float4 v2; + float f3; + int i4; +} GeterogeneousSmall; + +@interface AggregateTestSubject : NSObject + ++ (SingleFloat)singleFloatFn; ++ (SimplePacked)simplePackedFn; ++ (EvenSmallerPacked)evenSmallerPackedFn; ++ (HomogeneousSmall)homogeneousSmallFn; ++ (HomogeneousBig)homogeneousBigFn; ++ (simd_quatf)simd_quatfFn; ++ (GeterogeneousSmall)geterogeneousSmallFn; + + +@end; \ No newline at end of file diff --git a/kotlin-native/backend.native/tests/interop/objc/msg_send/messaging.m b/kotlin-native/backend.native/tests/interop/objc/msg_send/messaging.m new file mode 100644 index 00000000000..6c82209321f --- /dev/null +++ b/kotlin-native/backend.native/tests/interop/objc/msg_send/messaging.m @@ -0,0 +1,81 @@ +#import "messaging.h" + +@implementation PrimitiveTestSubject + ++ (int)intFn { + return 42; +} + ++ (float)floatFn { + return 3.14f; +} + ++ (double)doubleFn { + return 3.14; +} + ++ (simd_float4)simdFn { + simd_float4 v; + v.x = 2; + v.y = 4; + v.z = 5; + v.w = 8; + return v; +} + +@end; + +@implementation AggregateTestSubject + ++ (SingleFloat)singleFloatFn { + SingleFloat s; + s.f = 3.14f; + return s; +} + ++ (SimplePacked)simplePackedFn { + SimplePacked s; + s.f1 = '0'; + s.f2 = 111; + return s; +} + ++ (EvenSmallerPacked)evenSmallerPackedFn { + EvenSmallerPacked s; + s.x = 'x'; + s.y = 169; + s.z = 'z'; + return s; +} + ++ (HomogeneousSmall)homogeneousSmallFn { + HomogeneousSmall s; + s.f1 = 1.0f; + s.f2 = 2.0f; + s.f3 = 3.0f; + s.f4 = 4.0f; + return s; +} + ++ (HomogeneousBig)homogeneousBigFn { + HomogeneousBig s; + s.f1 = 1.0f; + s.f2 = 2.0f; + s.f3 = 3.0f; + s.f4 = 4.0f; + s.f5 = 5.0f; + s.f6 = 6.0f; + s.f7 = 7.0f; + s.f8 = 8.0f; + return s; +} + ++ (GeterogeneousSmall)geterogeneousSmallFn { + return (GeterogeneousSmall){1, {1, 4, 9, 25}, 3, 4}; +} + ++ (simd_quatf)simd_quatfFn { + return (simd_quatf){ {1, 4, 9, 25} }; +} + +@end; \ No newline at end of file diff --git a/kotlin-native/backend.native/tests/interop/objc/objcSmoke.def b/kotlin-native/backend.native/tests/interop/objc/objcSmoke.def new file mode 100644 index 00000000000..7337fd643a2 --- /dev/null +++ b/kotlin-native/backend.native/tests/interop/objc/objcSmoke.def @@ -0,0 +1,5 @@ +language = Objective-C +headers = Foundation/NSArray.h Foundation/NSValue.h Foundation/NSString.h Foundation/NSStream.h Foundation/NSBundle.h +headerFilter = **/smoke.h Foundation/NSArray.h Foundation/NSValue.h Foundation/NSString.h Foundation/NSStream.h \ + objc/objc.h Foundation/NSBundle.h +linkerOpts = -lobjcsmoke diff --git a/kotlin-native/backend.native/tests/interop/objc/objcTests.def b/kotlin-native/backend.native/tests/interop/objc/objcTests.def new file mode 100644 index 00000000000..66090941d9a --- /dev/null +++ b/kotlin-native/backend.native/tests/interop/objc/objcTests.def @@ -0,0 +1,6 @@ +language = Objective-C +headers = Foundation/NSArray.h Foundation/NSValue.h Foundation/NSString.h Foundation/NSStream.h Foundation/NSBundle.h +headerFilter = **/interop/objc/tests/**.h \ + Foundation/NSArray.h Foundation/NSValue.h Foundation/NSString.h Foundation/NSStream.h \ + objc/objc.h Foundation/NSBundle.h +linkerOpts = -lobjctests diff --git a/kotlin-native/backend.native/tests/interop/objc/smoke.h b/kotlin-native/backend.native/tests/interop/objc/smoke.h new file mode 100644 index 00000000000..b651871bfc8 --- /dev/null +++ b/kotlin-native/backend.native/tests/interop/objc/smoke.h @@ -0,0 +1,117 @@ +#import +#import + +@class Foo; + +@protocol Printer; +@protocol Printer; + +@protocol Empty +@end; + +@protocol Forward; +@class Forward; + +void useForward1(Forward * p) {} +void useForward2(id p) {} + +typedef NSString NSStringTypedef; + +@interface Foo : NSObject +@property NSStringTypedef* name; +-(void)helloWithPrinter:(id )printer; +@end; + +@interface Foo (FooExtensions) +-(void)hello; +@end; + +@protocol Printer +@required +-(void)print:(const char*)string; +@end; + +@protocol MutablePair +@required +@property (readonly) int first; +@property (readonly) int second; + +-(void)update:(int)index add:(int)delta; +-(void)update:(int)index sub:(int)delta; + +@end; + +void replacePairElements(id pair, int first, int second); + +int invoke1(int arg, int (^block)(int)) { + return block(arg); +} + +void invoke2(void (^block)(void)) { + block(); +} + +int (^getSupplier(int x))(void); +Class (^ _Nonnull getClassGetter(NSObject* obj))(void); + +extern NSString* globalString; +extern NSObject* globalObject; + +int formatStringLength(NSString* format, ...); + +#define STRING_MACRO @"String macro" +#define CFSTRING_MACRO CFSTR("CFString macro") + +typedef NS_ENUM(int32_t, ForwardDeclaredEnum); +typedef NS_ENUM(int32_t, ForwardDeclaredEnum) { + ZERO, ONE, TWO, +}; + +@protocol ObjectFactory +@required +-(id)create; +@end; + +id createObjectWithFactory(id factory) { + return [factory create]; +} + +@protocol CustomRetainMethods +@required +-(id)returnRetained:(id)obj __attribute__((ns_returns_retained)); +-(void)consume:(id) __attribute__((ns_consumed)) obj; +-(void)consumeSelf __attribute__((ns_consumes_self)); +-(void (^)(void))returnRetainedBlock:(void (^)(void))block __attribute__((ns_returns_retained)); +@end; + +extern BOOL unexpectedDeallocation; + +@interface MustNotBeDeallocated : NSObject +@end; + +@interface CustomRetainMethodsImpl : MustNotBeDeallocated +@end; + +static MustNotBeDeallocated* retainedObj; +static void (^retainedBlock)(void); + +void useCustomRetainMethods(id p) { + MustNotBeDeallocated* obj = [MustNotBeDeallocated new]; + retainedObj = obj; // Retain to detect possible over-release. + [p returnRetained:obj]; + + [p consume:p]; + [p consumeSelf]; + + MustNotBeDeallocated* capturedObj = [MustNotBeDeallocated new]; + retainedBlock = ^{ [capturedObj description]; }; // Retain to detect possible over-release. + [p returnRetainedBlock:retainedBlock](); +} + +id getPrinterProtocolRaw() { + return @protocol(Printer); +} + +Protocol* getPrinterProtocol() { + return @protocol(Printer); +} diff --git a/kotlin-native/backend.native/tests/interop/objc/smoke.kt b/kotlin-native/backend.native/tests/interop/objc/smoke.kt new file mode 100644 index 00000000000..c65be68f0bd --- /dev/null +++ b/kotlin-native/backend.native/tests/interop/objc/smoke.kt @@ -0,0 +1,239 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +import kotlinx.cinterop.* +import objcSmoke.* +import kotlin.native.concurrent.* +import kotlin.native.ref.* +import kotlin.test.* + +fun main(args: Array) { + autoreleasepool { + run() + } +} + +fun run() { + // TODO: migrate remaining tests to interop/objc/tests/ + testTypeOps() + testCustomRetain() + testExportObjCClass() + testLocalizedStrings() + + assertEquals(2, ForwardDeclaredEnum.TWO.value) + + println( + getSupplier( + invoke1(42) { it * 2 } + )!!() + ) + + val foo = Foo() + + val classGetter = getClassGetter(foo) + invoke2 { println(classGetter()) } + + foo.hello() + foo.name = "everybody" + foo.helloWithPrinter(object : NSObject(), PrinterProtocol { + override fun print(string: CPointer?) { + println("Kotlin says: " + string?.toKString()) + } + }) + + Bar().hello() + + val pair = MutablePairImpl(42, 17) + replacePairElements(pair, 1, 2) + pair.swap() + println("${pair.first}, ${pair.second}") + + val defaultPair = MutablePairImpl() + assertEquals(defaultPair.first(), 123) + assertEquals(defaultPair.second(), 321) + + // equals and hashCode (virtually): + val map = mapOf(foo to pair, pair to foo) + + // equals (directly): + if (!foo.equals(pair)) { + // toString (directly): + println(map[pair].toString() + map[foo].toString() == foo.description() + pair.description()) + } + + // hashCode (directly): + // hash() returns value of NSUInteger type. + val hash = when (Platform.osFamily) { + // `typedef unsigned int NSInteger` on watchOS. + OsFamily.WATCHOS -> foo.hash().toInt() + // `typedef unsigned long NSUInteger` on iOS, macOS, tvOS. + else -> foo.hash().let { it.toInt() xor (it shr 32).toInt() } + } + if (foo.hashCode() == hash) { + // toString (virtually): + if (Platform.memoryModel == MemoryModel.STRICT) + println(map.keys.map { it.toString() }.min() == foo.description()) + else + // TODO: hack until proper cycle collection in maps. + println(true) + } + println(globalString) + autoreleasepool { + globalString = "Another global string" + } + println(globalString) + + println(globalObject) + globalObject = object : NSObject() { + override fun description() = "global object" + } + println(globalObject) + globalObject = null // Prevent Kotlin object above from leaking. + + println(formatStringLength("%d %d", 42, 17)) + + println(STRING_MACRO) + println(CFSTRING_MACRO) + + // Ensure that overriding method bridge has retain-autorelease sequence: + createObjectWithFactory(object : NSObject(), ObjectFactoryProtocol { + override fun create() = autoreleasepool { NSObject() } + }) + +} + +fun MutablePairProtocol.swap() { + update(0, add = second) + update(1, sub = first) + update(0, add = second) + update(1, sub = second*2) +} + +class Bar : Foo() { + override fun helloWithPrinter(printer: PrinterProtocol?) = memScoped { + printer!!.print("Hello from Kotlin".cstr.getPointer(memScope)) + } +} + +@Suppress("CONFLICTING_OVERLOADS") +class MutablePairImpl(first: Int, second: Int) : NSObject(), MutablePairProtocol { + private var elements = intArrayOf(first, second) + + override fun first() = elements.first() + override fun second() = elements.last() + + override fun update(index: Int, add: Int) { + elements[index] += add + } + + override fun update(index: Int, sub: Int) { + elements[index] -= sub + } + + constructor() : this(123, 321) +} + +interface Zzz + +fun testTypeOps() { + assertTrue(99.asAny() is NSNumber) + assertTrue(null.asAny() is NSNumber?) + assertFalse(null.asAny() is NSNumber) + assertFalse("".asAny() is NSNumber) + assertTrue("bar".asAny() is NSString) + + assertTrue(Foo.asAny() is FooMeta) + assertFalse(Foo.asAny() is Zzz) + assertTrue(Foo.asAny() is NSObjectMeta) + assertTrue(Foo.asAny() is NSObject) + assertFalse(Foo.asAny() is Foo) + assertTrue(NSString.asAny() is NSCopyingProtocolMeta) + assertFalse(NSString.asAny() is NSCopyingProtocol) + assertTrue(NSValue.asAny() is NSObjectProtocolMeta) + assertFalse(NSValue.asAny() is NSObjectProtocol) // Must be true, but not implemented properly yet. + + assertFalse(Any() is ObjCClass) + assertFalse(Any() is ObjCClassOf<*>) + assertFalse(NSObject().asAny() is ObjCClass) + assertFalse(NSObject().asAny() is ObjCClassOf<*>) + assertTrue(NSObject.asAny() is ObjCClass) + assertTrue(NSObject.asAny() is ObjCClassOf<*>) + + assertFalse(Any() is ObjCProtocol) + assertTrue(getPrinterProtocolRaw() is ObjCProtocol) + val printerProtocol = getPrinterProtocol()!! + assertTrue(printerProtocol.asAny() is ObjCProtocol) + + assertEquals(3u, ("foo" as NSString).length()) + assertEquals(4u, ((1..4).joinToString("") as NSString).length()) + assertEquals(2u, (listOf(0, 1) as NSArray).count()) + assertEquals(42L, (42 as NSNumber).longLongValue()) + + assertFails { "bar" as NSNumber } + assertFails { 42 as NSArray } + assertFails { listOf(1) as NSString } + assertFails { NSObject() as Bar } + assertFails { NSObject() as NSValue } + + MutablePairImpl(1, 2).asAny() as MutablePairProtocol + assertFails { MutablePairImpl(1, 2).asAny() as Foo } +} + +private lateinit var retainedMustNotBeDeallocated: MustNotBeDeallocated + +fun testCustomRetain() { + fun test() { + useCustomRetainMethods(object : Foo(), CustomRetainMethodsProtocol { + override fun returnRetained(obj: Any?) = obj + override fun consume(obj: Any?) {} + override fun consumeSelf() {} + override fun returnRetainedBlock(block: (() -> Unit)?) = block + }) + + CustomRetainMethodsImpl().let { + it.returnRetained(Any()) + retainedMustNotBeDeallocated = MustNotBeDeallocated() // Retain to detect possible over-release. + it.consume(retainedMustNotBeDeallocated) + it.consumeSelf() + it.returnRetainedBlock({})!!() + } + } + + autoreleasepool { + test() + kotlin.native.internal.GC.collect() + } + + assertFalse(unexpectedDeallocation) +} + +private const val TestExportObjCClass1Name = "TestExportObjCClass" +@ExportObjCClass(TestExportObjCClass1Name) class TestExportObjCClass1 : NSObject() + +@ExportObjCClass class TestExportObjCClass2 : NSObject() + +const val TestExportObjCClass34Name = "TestExportObjCClass34" +@ExportObjCClass(TestExportObjCClass34Name) class TestExportObjCClass3 : NSObject() +@ExportObjCClass(TestExportObjCClass34Name) class TestExportObjCClass4 : NSObject() + +fun testExportObjCClass() { + assertEquals(TestExportObjCClass1Name, TestExportObjCClass1().objCClassName) + assertEquals("TestExportObjCClass2", TestExportObjCClass2().objCClassName) + + assertTrue((TestExportObjCClass3().objCClassName == TestExportObjCClass34Name) + xor (TestExportObjCClass4().objCClassName == TestExportObjCClass34Name)) +} + +fun testLocalizedStrings() { + val key = "screen_main_plural_string" + val localizedString = NSBundle.mainBundle.localizedStringForKey(key, value = "", table = "Localizable") + val string = NSString.localizedStringWithFormat(localizedString, 5) + assertEquals("Plural: 5 apples", string) +} + +private val Any.objCClassName: String + get() = object_getClassName(this)!!.toKString() + +fun Any?.asAny(): Any? = this diff --git a/kotlin-native/backend.native/tests/interop/objc/smoke.m b/kotlin-native/backend.native/tests/interop/objc/smoke.m new file mode 100644 index 00000000000..08504da42a0 --- /dev/null +++ b/kotlin-native/backend.native/tests/interop/objc/smoke.m @@ -0,0 +1,97 @@ +#import +#import +#import "smoke.h" + +@interface CPrinter : NSObject +-(void)print:(const char*)string; +@end; + +@implementation CPrinter +-(void)print:(const char*)string { + printf("%s\n", string); + fflush(stdout); +} +@end; + +@implementation Foo + +@synthesize name; + +-(instancetype)init { + if (self = [super init]) { + self.name = @"World"; + } + return self; +} + +-(void)helloWithPrinter:(id )printer { + NSString* message = [NSString stringWithFormat:@"Hello, %@!", self.name]; + [printer print:message.UTF8String]; +} + +-(void)dealloc { + printf("Deallocated\n"); +} + +@end; + +@implementation Foo (FooExtensions) + +-(void)hello { + CPrinter* printer = [[CPrinter alloc] init]; + [self helloWithPrinter:printer]; +} +@end; + +void replacePairElements(id pair, int first, int second) { + [pair update:0 add:(first - pair.first)]; + [pair update:1 sub:(pair.second - second)]; +} + +int (^getSupplier(int x))(void) { + return ^{ + return x; + }; +} + +Class (^ _Nonnull getClassGetter(NSObject* obj))() { + return ^{ return obj.class; }; +} + +NSString* globalString = @"Global string"; +NSObject* globalObject = nil; + +int formatStringLength(NSString* format, ...) { + va_list args; + va_start(args, format); + NSString* result = [[NSString alloc] initWithFormat:format arguments:args]; + va_end(args); + return result.length; +} + +BOOL unexpectedDeallocation = NO; + +@implementation MustNotBeDeallocated +-(void)dealloc { + unexpectedDeallocation = YES; +} +@end; + +static CustomRetainMethodsImpl* retainedCustomRetainMethodsImpl; + +@implementation CustomRetainMethodsImpl +-(id)returnRetained:(id)obj __attribute__((ns_returns_retained)) { + return obj; +} + +-(void)consume:(id) __attribute__((ns_consumed)) obj { +} + +-(void)consumeSelf __attribute__((ns_consumes_self)) { + retainedCustomRetainMethodsImpl = self; // Retain to detect possible over-release. +} + +-(void (^)(void))returnRetainedBlock:(void (^)(void))block __attribute__((ns_returns_retained)) { + return block; +} +@end; diff --git a/kotlin-native/backend.native/tests/interop/objc/tests/KT38234_override.h b/kotlin-native/backend.native/tests/interop/objc/tests/KT38234_override.h new file mode 100644 index 00000000000..8a1561d8513 --- /dev/null +++ b/kotlin-native/backend.native/tests/interop/objc/tests/KT38234_override.h @@ -0,0 +1,9 @@ +#import + +@protocol KT38234_P1 +-(int)foo; +@end; + +@interface KT38234_Base : NSObject +-(int)callFoo; +@end; diff --git a/kotlin-native/backend.native/tests/interop/objc/tests/KT38234_override.kt b/kotlin-native/backend.native/tests/interop/objc/tests/KT38234_override.kt new file mode 100644 index 00000000000..5e5ea4c5b1b --- /dev/null +++ b/kotlin-native/backend.native/tests/interop/objc/tests/KT38234_override.kt @@ -0,0 +1,10 @@ +import kotlin.test.* +import objcTests.* + +class KT38234_Impl : KT38234_P1Protocol, KT38234_Base() { + override fun foo(): Int = 566 +} + +@Test fun testKT38234() { + assertEquals(566, KT38234_Impl().callFoo()) +} diff --git a/kotlin-native/backend.native/tests/interop/objc/tests/KT38234_override.m b/kotlin-native/backend.native/tests/interop/objc/tests/KT38234_override.m new file mode 100644 index 00000000000..675baa38af0 --- /dev/null +++ b/kotlin-native/backend.native/tests/interop/objc/tests/KT38234_override.m @@ -0,0 +1,10 @@ +#include "KT38234_override.h" + +@implementation KT38234_Base +-(int)foo { + return 1; +} +-(int)callFoo { + return [self foo]; +} +@end; diff --git a/kotlin-native/backend.native/tests/interop/objc/tests/allocNoRetain.h b/kotlin-native/backend.native/tests/interop/objc/tests/allocNoRetain.h new file mode 100644 index 00000000000..313ef9b0ada --- /dev/null +++ b/kotlin-native/backend.native/tests/interop/objc/tests/allocNoRetain.h @@ -0,0 +1,5 @@ +#import + +@interface TestAllocNoRetain : NSObject +@property BOOL ok; +@end; \ No newline at end of file diff --git a/kotlin-native/backend.native/tests/interop/objc/tests/allocNoRetain.kt b/kotlin-native/backend.native/tests/interop/objc/tests/allocNoRetain.kt new file mode 100644 index 00000000000..5cba873ea32 --- /dev/null +++ b/kotlin-native/backend.native/tests/interop/objc/tests/allocNoRetain.kt @@ -0,0 +1,27 @@ +import kotlinx.cinterop.* +import kotlin.test.* +import objcTests.* + +@Test fun testAllocNoRetain() { + // Ensure that calling Kotlin constructor generated for Objective-C initializer doesn't result in + // redundant retain-release sequence for `alloc` result, since it may provoke specific bugs to reproduce, e.g. + // the one found in [[NSOutputStream alloc] initToMemory] sequence where initToMemory deallocates its receiver + // forcibly when replacing it with other object: (to be compiled with ARC enabled) + /* + #import + + void* mem; + NSOutputStream* allocated = nil; + + int main() { + allocated = [NSOutputStream alloc]; + NSOutputStream* initialized = [allocated initToMemory]; + mem = calloc(1, 0x10); // To corrupt the 'allocated' object header. + allocated = nil; // Crashes here in objc_release. + + return 0; + } + */ + + assertTrue(TestAllocNoRetain().ok) +} \ No newline at end of file diff --git a/kotlin-native/backend.native/tests/interop/objc/tests/allocNoRetain.m b/kotlin-native/backend.native/tests/interop/objc/tests/allocNoRetain.m new file mode 100644 index 00000000000..122ccb9be0e --- /dev/null +++ b/kotlin-native/backend.native/tests/interop/objc/tests/allocNoRetain.m @@ -0,0 +1,14 @@ +#import "allocNoRetain.h" + +@implementation TestAllocNoRetain +-(instancetype)init { + __weak id weakSelf = self; + self = [TestAllocNoRetain alloc]; + if (self = [super init]) { + // Ensure that original self value was deallocated: + self.ok = (weakSelf == nil); + // So it's RC was 1, which means there wasn't redundant retain applied to it. + } + return self; +} +@end; \ No newline at end of file diff --git a/kotlin-native/backend.native/tests/interop/objc/tests/blocks.h b/kotlin-native/backend.native/tests/interop/objc/tests/blocks.h new file mode 100644 index 00000000000..585827fb2f3 --- /dev/null +++ b/kotlin-native/backend.native/tests/interop/objc/tests/blocks.h @@ -0,0 +1,27 @@ +#import + +@protocol BlockProvider +@required +-(int (^)(int)) block; +@end; + +int callProvidedBlock(id blockProvider, int argument) { + return [blockProvider block](argument); +} + +@protocol BlockConsumer +@required +-(int)callBlock:(int (^)(int))block argument:(int)argument; +@end; + +int callPlusOneBlock(id blockConsumer, int argument) { + return [blockConsumer callBlock:^int(int p) { return p + 1; } argument:argument]; +} + +@interface Blocks : NSObject ++(BOOL)blockIsNull:(void (^)(void))block; ++(int (^)(int, int, int, int))same:(int (^)(int, int, int, int))block; + +@property (class) void (^nullBlock)(void); +@property (class) void (^notNullBlock)(void); +@end; diff --git a/kotlin-native/backend.native/tests/interop/objc/tests/blocks.kt b/kotlin-native/backend.native/tests/interop/objc/tests/blocks.kt new file mode 100644 index 00000000000..1cee38f95e7 --- /dev/null +++ b/kotlin-native/backend.native/tests/interop/objc/tests/blocks.kt @@ -0,0 +1,21 @@ +import kotlinx.cinterop.* +import kotlin.test.* +import objcTests.* + +@Test fun testBlocks() { + assertTrue(Blocks.blockIsNull(null)) + assertFalse(Blocks.blockIsNull({})) + + assertEquals(null, Blocks.nullBlock) + assertNotEquals(null, Blocks.notNullBlock) + + assertEquals(10, Blocks.same({ a, b, c, d -> a + b + c + d })!!(1, 2, 3, 4)) + + assertEquals(222, callProvidedBlock(object : NSObject(), BlockProviderProtocol { + override fun block(): (Int) -> Int = { it * 2 } + }, 111)) + + assertEquals(322, callPlusOneBlock(object : NSObject(), BlockConsumerProtocol { + override fun callBlock(block: ((Int) -> Int)?, argument: Int) = block!!(argument) + }, 321)) +} diff --git a/kotlin-native/backend.native/tests/interop/objc/tests/blocks.m b/kotlin-native/backend.native/tests/interop/objc/tests/blocks.m new file mode 100644 index 00000000000..bb32316a1a3 --- /dev/null +++ b/kotlin-native/backend.native/tests/interop/objc/tests/blocks.m @@ -0,0 +1,20 @@ +#import "blocks.h" + +@implementation Blocks ++(BOOL)blockIsNull:(void (^)(void))block { + return block == nil; +} + ++(int (^)(int, int, int, int))same:(int (^)(int, int, int, int))block { + return block; +} + ++(void (^)(void)) nullBlock { + return nil; +} + ++(void (^)(void)) notNullBlock { + return ^{}; +} + +@end; \ No newline at end of file diff --git a/kotlin-native/backend.native/tests/interop/objc/tests/callableReferences.h b/kotlin-native/backend.native/tests/interop/objc/tests/callableReferences.h new file mode 100644 index 00000000000..90af865e4e4 --- /dev/null +++ b/kotlin-native/backend.native/tests/interop/objc/tests/callableReferences.h @@ -0,0 +1,7 @@ +#import + +@interface TestCallableReferences : NSObject +@property int value; +- (int)instanceMethod; ++ (int)classMethod:(int)first :(int)second; +@end; \ No newline at end of file diff --git a/kotlin-native/backend.native/tests/interop/objc/tests/callableReferences.kt b/kotlin-native/backend.native/tests/interop/objc/tests/callableReferences.kt new file mode 100644 index 00000000000..eb7176af39b --- /dev/null +++ b/kotlin-native/backend.native/tests/interop/objc/tests/callableReferences.kt @@ -0,0 +1,28 @@ +import kotlinx.cinterop.* +import kotlin.test.* +import objcTests.* + +@Test fun testCallableReferences() { + val createTestCallableReferences = ::TestCallableReferences + assertEquals("", createTestCallableReferences.name) + val testCallableReferences: Any = createTestCallableReferences() + assertTrue(testCallableReferences is TestCallableReferences) + + val valueRef: kotlin.reflect.KMutableProperty0 = testCallableReferences::value + assertEquals("value", valueRef.name) + assertEquals(0, valueRef()) + valueRef.set(42) + assertEquals(42, valueRef()) + + val classMethodRef = (TestCallableReferences)::classMethod + assertEquals("classMethod", classMethodRef.name) + assertEquals(3, classMethodRef(1, 2)) + + val instanceMethodRef = TestCallableReferences::instanceMethod + assertEquals("instanceMethod", instanceMethodRef.name) + assertEquals(42, instanceMethodRef(testCallableReferences)) + + val boundInstanceMethodRef = testCallableReferences::instanceMethod + assertEquals("instanceMethod", boundInstanceMethodRef.name) + assertEquals(42, boundInstanceMethodRef()) +} \ No newline at end of file diff --git a/kotlin-native/backend.native/tests/interop/objc/tests/callableReferences.m b/kotlin-native/backend.native/tests/interop/objc/tests/callableReferences.m new file mode 100644 index 00000000000..17a7b232559 --- /dev/null +++ b/kotlin-native/backend.native/tests/interop/objc/tests/callableReferences.m @@ -0,0 +1,11 @@ +#import "callableReferences.h" + +@implementation TestCallableReferences +- (int)instanceMethod { + return self.value; +} + ++ (int)classMethod:(int)first :(int)second { + return first + second; +} +@end; \ No newline at end of file diff --git a/kotlin-native/backend.native/tests/interop/objc/tests/clashingWithAny.h b/kotlin-native/backend.native/tests/interop/objc/tests/clashingWithAny.h new file mode 100644 index 00000000000..897e408528a --- /dev/null +++ b/kotlin-native/backend.native/tests/interop/objc/tests/clashingWithAny.h @@ -0,0 +1,22 @@ +#import +#import + +@interface TestClashingWithAny1 : NSObject +-(NSString*)toString; +-(NSString*)toString_; +-(int)hashCode; +-(BOOL)equals:(id _Nullable)other; +@end; + +@interface TestClashingWithAny2 : NSObject +-(void)toString; +-(void)hashCode; +-(void)equals:(int)p; // May clash. +@end; + +@interface TestClashingWithAny3 : NSObject +// Not clashing actually. +-(NSString*)toString:(int)p; +-(int)hashCode:(int)p; +-(BOOL)equals; +@end; diff --git a/kotlin-native/backend.native/tests/interop/objc/tests/clashingWithAny.kt b/kotlin-native/backend.native/tests/interop/objc/tests/clashingWithAny.kt new file mode 100644 index 00000000000..cacf89ecd1c --- /dev/null +++ b/kotlin-native/backend.native/tests/interop/objc/tests/clashingWithAny.kt @@ -0,0 +1,27 @@ +import kotlinx.cinterop.* +import kotlin.test.* +import objcTests.* + +@Test fun testClashingWithAny() { + assertEquals("description", TestClashingWithAny1().toString()) + assertEquals("toString", TestClashingWithAny1().toString_()) + assertEquals("toString_", TestClashingWithAny1().toString__()) + assertEquals(1, TestClashingWithAny1().hashCode()) + assertEquals(31, TestClashingWithAny1().hashCode_()) + assertFalse(TestClashingWithAny1().equals(TestClashingWithAny1())) + assertTrue(TestClashingWithAny1().equals_(TestClashingWithAny1())) + + assertEquals("description", TestClashingWithAny2().toString()) + assertEquals(Unit, TestClashingWithAny2().toString_()) + assertEquals(2, TestClashingWithAny2().hashCode()) + assertEquals(Unit, TestClashingWithAny2().hashCode_()) + assertFalse(TestClashingWithAny2().equals(TestClashingWithAny2())) + assertEquals(Unit, TestClashingWithAny2().equals_(42)) + + assertEquals("description", TestClashingWithAny3().toString()) + assertEquals("toString:11", TestClashingWithAny3().toString(11)) + assertEquals(3, TestClashingWithAny3().hashCode()) + assertEquals(4, TestClashingWithAny3().hashCode(3)) + assertFalse(TestClashingWithAny3().equals(TestClashingWithAny3())) + assertTrue(TestClashingWithAny3().equals()) +} diff --git a/kotlin-native/backend.native/tests/interop/objc/tests/clashingWithAny.m b/kotlin-native/backend.native/tests/interop/objc/tests/clashingWithAny.m new file mode 100644 index 00000000000..789bd5baa8e --- /dev/null +++ b/kotlin-native/backend.native/tests/interop/objc/tests/clashingWithAny.m @@ -0,0 +1,68 @@ +#import "clashingWithAny.h" + +@implementation TestClashingWithAny1 +-(NSString*)description { + return @"description"; +} + +-(NSString*)toString { + return @"toString"; +} + +-(NSString*)toString_ { + return @"toString_"; +} + +-(NSUInteger)hash { + return 1; +} + +-(int)hashCode { + return 31; +} + +-(BOOL)equals:(id _Nullable)other { + return YES; +} +@end; + +@implementation TestClashingWithAny2 +-(NSString*)description { + return @"description"; +} + +-(void)toString { +} + +-(NSUInteger)hash { + return 2; +} + +-(void)hashCode { +} + +-(void)equals:(int)p { +} +@end; + +@implementation TestClashingWithAny3 +-(NSString*)description { + return @"description"; +} + +-(NSString*)toString:(int)p { + return [NSString stringWithFormat:@"%s:%d", "toString", p]; +} + +-(NSUInteger)hash { + return 3; +} + +-(int)hashCode:(int)p { + return p + 1; +} + +-(BOOL)equals { + return YES; +} +@end; \ No newline at end of file diff --git a/kotlin-native/backend.native/tests/interop/objc/tests/constructorReturnsNull.h b/kotlin-native/backend.native/tests/interop/objc/tests/constructorReturnsNull.h new file mode 100644 index 00000000000..25b079f5a95 --- /dev/null +++ b/kotlin-native/backend.native/tests/interop/objc/tests/constructorReturnsNull.h @@ -0,0 +1,5 @@ +#import + +@interface TestConstructorReturnsNull : NSObject +- (instancetype)init; +@end; \ No newline at end of file diff --git a/kotlin-native/backend.native/tests/interop/objc/tests/constructorReturnsNull.kt b/kotlin-native/backend.native/tests/interop/objc/tests/constructorReturnsNull.kt new file mode 100644 index 00000000000..782ca591cbe --- /dev/null +++ b/kotlin-native/backend.native/tests/interop/objc/tests/constructorReturnsNull.kt @@ -0,0 +1,9 @@ +import kotlinx.cinterop.* +import kotlin.test.* +import objcTests.* + +@Test fun testConstructorReturnsNull() { + assertFailsWith() { + TestConstructorReturnsNull() + } +} \ No newline at end of file diff --git a/kotlin-native/backend.native/tests/interop/objc/tests/constructorReturnsNull.m b/kotlin-native/backend.native/tests/interop/objc/tests/constructorReturnsNull.m new file mode 100644 index 00000000000..07a6116f0dd --- /dev/null +++ b/kotlin-native/backend.native/tests/interop/objc/tests/constructorReturnsNull.m @@ -0,0 +1,7 @@ +#import "constructorReturnsNull.h" + +@implementation TestConstructorReturnsNull +- (instancetype)init { + return nil; +} +@end; \ No newline at end of file diff --git a/kotlin-native/backend.native/tests/interop/objc/tests/conversions.kt b/kotlin-native/backend.native/tests/interop/objc/tests/conversions.kt new file mode 100644 index 00000000000..a413dca0c11 --- /dev/null +++ b/kotlin-native/backend.native/tests/interop/objc/tests/conversions.kt @@ -0,0 +1,18 @@ +import kotlinx.cinterop.* +import kotlin.test.* +import objcTests.* + +@Test fun testConversions() { + testMethodsOfAny(emptyList(), NSArray()) + testMethodsOfAny(listOf(1, "foo"), nsArrayOf(1, "foo")) + testMethodsOfAny(42, NSNumber.numberWithInt(42), 17) + testMethodsOfAny(true, NSNumber.numberWithBool(true), false) +} + +private fun testMethodsOfAny(kotlinObject: Any, equalNsObject: NSObject, otherObject: Any = Any()) { + assertEquals(kotlinObject.hashCode(), equalNsObject.hashCode()) + assertEquals(kotlinObject.toString(), equalNsObject.toString()) + assertEquals(kotlinObject, equalNsObject) + assertEquals(equalNsObject, kotlinObject) + assertNotEquals(equalNsObject, otherObject) +} diff --git a/kotlin-native/backend.native/tests/interop/objc/tests/customString.h b/kotlin-native/backend.native/tests/interop/objc/tests/customString.h new file mode 100644 index 00000000000..1e3078b0ee7 --- /dev/null +++ b/kotlin-native/backend.native/tests/interop/objc/tests/customString.h @@ -0,0 +1,16 @@ +#import + +@interface CustomString : NSString +- (instancetype)initWithValue:(int)value; +@property int value; +@end; + +CustomString* _Nonnull createCustomString(int value) { + return [[CustomString alloc] initWithValue:value]; +} + +int getCustomStringValue(CustomString* str) { + return str.value; +} + +extern BOOL customStringDeallocated; \ No newline at end of file diff --git a/kotlin-native/backend.native/tests/interop/objc/tests/customString.kt b/kotlin-native/backend.native/tests/interop/objc/tests/customString.kt new file mode 100644 index 00000000000..6b90633a4dd --- /dev/null +++ b/kotlin-native/backend.native/tests/interop/objc/tests/customString.kt @@ -0,0 +1,21 @@ +import kotlinx.cinterop.* +import kotlin.test.* +import objcTests.* + +@Test fun testCustomString() { + assertFalse(customStringDeallocated) + + fun test() = autoreleasepool { + val str: String = createCustomString(321) + assertEquals("321", str) + assertEquals("CustomString", str.objCClassName) + assertEquals(321, getCustomStringValue(str)) + } + + test() + kotlin.native.internal.GC.collect() + assertTrue(customStringDeallocated) +} + +private val Any.objCClassName: String + get() = object_getClassName(this)!!.toKString() \ No newline at end of file diff --git a/kotlin-native/backend.native/tests/interop/objc/tests/customString.m b/kotlin-native/backend.native/tests/interop/objc/tests/customString.m new file mode 100644 index 00000000000..1a03f684ca9 --- /dev/null +++ b/kotlin-native/backend.native/tests/interop/objc/tests/customString.m @@ -0,0 +1,32 @@ +#import "customString.h" + +BOOL customStringDeallocated = NO; + +@implementation CustomString { + NSString* delegate; +} + +- (instancetype)initWithValue:(int)value { + if (self = [super init]) { + self->delegate = @(value).description; + self.value = value; + } + return self; +} + +- (unichar)characterAtIndex:(NSUInteger)index { + return [self->delegate characterAtIndex:index]; +} + +- (NSUInteger)length { + return self->delegate.length; +} + +- (id)copyWithZone:(NSZone *)zone { + return self; +} + +- (void)dealloc { + customStringDeallocated = YES; +} +@end; \ No newline at end of file diff --git a/kotlin-native/backend.native/tests/interop/objc/tests/exceptions.h b/kotlin-native/backend.native/tests/interop/objc/tests/exceptions.h new file mode 100644 index 00000000000..8350db2d591 --- /dev/null +++ b/kotlin-native/backend.native/tests/interop/objc/tests/exceptions.h @@ -0,0 +1,9 @@ +#import + +@protocol ExceptionThrower +-(void)throwException; +@end; + +@interface ExceptionThrowerManager : NSObject ++(void)throwExceptionWith:(id)thrower; +@end; diff --git a/kotlin-native/backend.native/tests/interop/objc/tests/exceptions.kt b/kotlin-native/backend.native/tests/interop/objc/tests/exceptions.kt new file mode 100644 index 00000000000..f01f8314dd5 --- /dev/null +++ b/kotlin-native/backend.native/tests/interop/objc/tests/exceptions.kt @@ -0,0 +1,15 @@ +import kotlinx.cinterop.* +import kotlin.test.* +import objcTests.* + +@Test fun testExceptions() { + assertFailsWith { + ExceptionThrowerManager.throwExceptionWith(object : NSObject(), ExceptionThrowerProtocol { + override fun throwException() { + throw MyException() + } + }) + } +} + +private class MyException : Throwable() \ No newline at end of file diff --git a/kotlin-native/backend.native/tests/interop/objc/tests/exceptions.m b/kotlin-native/backend.native/tests/interop/objc/tests/exceptions.m new file mode 100644 index 00000000000..1154f23d56f --- /dev/null +++ b/kotlin-native/backend.native/tests/interop/objc/tests/exceptions.m @@ -0,0 +1,7 @@ +#import "exceptions.h" + +@implementation ExceptionThrowerManager ++(void)throwExceptionWith:(id)thrower { + [thrower throwException]; +} +@end; \ No newline at end of file diff --git a/kotlin-native/backend.native/tests/interop/objc/tests/initWithCustomSelector.h b/kotlin-native/backend.native/tests/interop/objc/tests/initWithCustomSelector.h new file mode 100644 index 00000000000..47d026e2259 --- /dev/null +++ b/kotlin-native/backend.native/tests/interop/objc/tests/initWithCustomSelector.h @@ -0,0 +1,8 @@ +#import + +@interface TestInitWithCustomSelector : NSObject +-(instancetype)initCustom; +@property BOOL custom; + ++(instancetype _Nonnull)createCustom; +@end; \ No newline at end of file diff --git a/kotlin-native/backend.native/tests/interop/objc/tests/initWithCustomSelector.kt b/kotlin-native/backend.native/tests/interop/objc/tests/initWithCustomSelector.kt new file mode 100644 index 00000000000..df924753777 --- /dev/null +++ b/kotlin-native/backend.native/tests/interop/objc/tests/initWithCustomSelector.kt @@ -0,0 +1,25 @@ +import kotlinx.cinterop.* +import kotlin.test.* +import objcTests.* + +@Test fun testInitWithCustomSelector() { + assertFalse(TestInitWithCustomSelector().custom) + assertTrue(TestInitWithCustomSelector(custom = Unit).custom) + + val customSubclass: TestInitWithCustomSelector = TestInitWithCustomSelectorSubclass.createCustom() + assertTrue(customSubclass is TestInitWithCustomSelectorSubclass) + assertTrue(customSubclass.custom) + + // Test side effect: + var ok = false + assertTrue(TestInitWithCustomSelector(run { ok = true }).custom) + assertTrue(ok) +} + +private class TestInitWithCustomSelectorSubclass : TestInitWithCustomSelector { + @OverrideInit constructor(custom: Unit) : super(custom) { + assertSame(Unit, custom) + } + + companion object : TestInitWithCustomSelectorMeta() +} \ No newline at end of file diff --git a/kotlin-native/backend.native/tests/interop/objc/tests/initWithCustomSelector.m b/kotlin-native/backend.native/tests/interop/objc/tests/initWithCustomSelector.m new file mode 100644 index 00000000000..0e5edee5823 --- /dev/null +++ b/kotlin-native/backend.native/tests/interop/objc/tests/initWithCustomSelector.m @@ -0,0 +1,23 @@ +#import "initWithCustomSelector.h" + +@implementation TestInitWithCustomSelector + +-(instancetype)initCustom { + if (self = [super init]) { + self.custom = YES; + } + return self; +} + +-(instancetype)init { + if (self = [super init]) { + self.custom = NO; + } + return self; +} + ++(instancetype)createCustom { + return [[self alloc] initCustom]; +} + +@end; \ No newline at end of file diff --git a/kotlin-native/backend.native/tests/interop/objc/tests/kt36766.h b/kotlin-native/backend.native/tests/interop/objc/tests/kt36766.h new file mode 100644 index 00000000000..06105e139b5 --- /dev/null +++ b/kotlin-native/backend.native/tests/interop/objc/tests/kt36766.h @@ -0,0 +1 @@ +void kt36766(void (^block)()) {} \ No newline at end of file diff --git a/kotlin-native/backend.native/tests/interop/objc/tests/kt36766.kt b/kotlin-native/backend.native/tests/interop/objc/tests/kt36766.kt new file mode 100644 index 00000000000..a5a28003ceb --- /dev/null +++ b/kotlin-native/backend.native/tests/interop/objc/tests/kt36766.kt @@ -0,0 +1,6 @@ +import kotlin.test.* +import objcTests.* + +@Test fun testKt36766() { + kt36766(null) +} \ No newline at end of file diff --git a/kotlin-native/backend.native/tests/interop/objc/tests/kt41811.h b/kotlin-native/backend.native/tests/interop/objc/tests/kt41811.h new file mode 100644 index 00000000000..724c4e55b40 --- /dev/null +++ b/kotlin-native/backend.native/tests/interop/objc/tests/kt41811.h @@ -0,0 +1,24 @@ +#import + +extern BOOL deallocRetainReleaseDeallocated; + +@interface DeallocRetainRelease : NSObject +@end; + +extern DeallocRetainRelease* globalDeallocRetainRelease; + +@protocol WeakReference +@required +@property (weak) id referent; +@end; + +@interface ObjCWeakReference : NSObject +@property (weak) id referent; +@end; + +extern id weakDeallocLoadWeak; +extern BOOL deallocLoadWeakDeallocated; + +@interface DeallocLoadWeak : NSObject +-(void)checkWeak; +@end; diff --git a/kotlin-native/backend.native/tests/interop/objc/tests/kt41811.kt b/kotlin-native/backend.native/tests/interop/objc/tests/kt41811.kt new file mode 100644 index 00000000000..ae0c2dd50d6 --- /dev/null +++ b/kotlin-native/backend.native/tests/interop/objc/tests/kt41811.kt @@ -0,0 +1,118 @@ +import kotlin.native.ref.WeakReference +import kotlinx.cinterop.* +import kotlin.test.* +import objcTests.* + +// Note: these tests rely on GC assertions: without the fix and the assertions it won't actually crash. +// GC should fire an assertion if it obtains a reference to Kotlin object that is being (or has been) deallocated. + +@Test +fun testKT41811() { + // Attempt to make the state predictable: + kotlin.native.internal.GC.collect() + + deallocRetainReleaseDeallocated = false + assertFalse(deallocRetainReleaseDeallocated) + + createGarbageDeallocRetainRelease() + + // Runs [DeallocRetainRelease dealloc]: + kotlin.native.internal.GC.collect() + + assertTrue(deallocRetainReleaseDeallocated) + + // Might crash due to double-dispose if the dealloc applied addRef/releaseRef to reclaimed Kotlin object: + kotlin.native.internal.GC.collect() +} + +private fun createGarbageDeallocRetainRelease() { + autoreleasepool { + object : DeallocRetainRelease() {} + } +} + +@Test +fun testKT41811LoadWeak() { + testKT41811LoadWeak(ObjCWeakReference()) +} + +@Test +fun testKT41811LoadKotlinWeak() { + val kotlinWeak = object : NSObject(), WeakReferenceProtocol { + lateinit var weakReference: WeakReference + + override fun referent(): Any? { + return weakReference.value + } + + override fun setReferent(referent: Any?) { + weakReference = WeakReference(referent!!) + } + } + + testKT41811LoadWeak(kotlinWeak) +} + +private fun testKT41811LoadWeak(weakRef: WeakReferenceProtocol) { + // Attempt to make the state predictable: + kotlin.native.internal.GC.collect() + + deallocLoadWeakDeallocated = false + assertFalse(deallocLoadWeakDeallocated) + + createGarbageDeallocLoadWeak(weakRef) + + // Runs [DeallocLoadWeak dealloc]: + kotlin.native.internal.GC.collect() + + assertTrue(deallocLoadWeakDeallocated) + + // Might crash due to double-dispose if the dealloc applied addRef/releaseRef to reclaimed Kotlin object: + kotlin.native.internal.GC.collect() + + weakDeallocLoadWeak = null +} + +private fun createGarbageDeallocLoadWeak(weakRef: WeakReferenceProtocol) { + autoreleasepool { + val obj = object : DeallocLoadWeak() {} + weakDeallocLoadWeak = weakRef.apply { referent = obj } + obj.checkWeak() + assertSame(obj, weakDeallocLoadWeak!!.referent) + } +} + +@Test +fun testKT41811WithGlobal() { + // Attempt to make the state predictable: + kotlin.native.internal.GC.collect() + + deallocRetainReleaseDeallocated = false + assertFalse(deallocRetainReleaseDeallocated) + + autoreleasepool { + { + globalDeallocRetainRelease = object: DeallocRetainRelease() {} + }() + } + + assertFalse(deallocRetainReleaseDeallocated) + + // Clean up local DeallocRetainRelease on Kotlin side + kotlin.native.internal.GC.collect() + + assertFalse(deallocRetainReleaseDeallocated) + + // And drop the last reference to DeallocRetainRelease from ObjC global scope. + globalDeallocRetainRelease = null + + assertFalse(deallocRetainReleaseDeallocated) + + // This will dispose `DeallocRetainRelease` on Kotlin side, which will cause `dealloc` + // on ObjC side, which triggers `retain` and `release` of `self`. If these messages + // were to reach Kotlin side, the `release` would have immediately scheduled the + // second disposal of Kotlin object. + kotlin.native.internal.GC.collect() + + assertTrue(deallocRetainReleaseDeallocated) +} diff --git a/kotlin-native/backend.native/tests/interop/objc/tests/kt41811.m b/kotlin-native/backend.native/tests/interop/objc/tests/kt41811.m new file mode 100644 index 00000000000..0a7335df931 --- /dev/null +++ b/kotlin-native/backend.native/tests/interop/objc/tests/kt41811.m @@ -0,0 +1,39 @@ +#import "kt41811.h" +#import "assert.h" + +id retainObject = nil; +BOOL deallocRetainReleaseDeallocated = NO; + +@implementation DeallocRetainRelease +-(void)dealloc { + retainObject = self; + assert(retainObject == self); + retainObject = nil; + + assert(!deallocRetainReleaseDeallocated); + deallocRetainReleaseDeallocated = YES; +} +@end; + +DeallocRetainRelease* globalDeallocRetainRelease = nil; + +@implementation ObjCWeakReference +@end; + +id weakDeallocLoadWeak = nil; +BOOL deallocLoadWeakDeallocated = NO; + +@implementation DeallocLoadWeak +-(void)checkWeak { + assert(weakDeallocLoadWeak != nil); + assert(weakDeallocLoadWeak.referent == self); +} + +-(void)dealloc { + assert(weakDeallocLoadWeak != nil); + assert(weakDeallocLoadWeak.referent == nil); + + assert(!deallocLoadWeakDeallocated); + deallocLoadWeakDeallocated = YES; +} +@end; diff --git a/kotlin-native/backend.native/tests/interop/objc/tests/main.kt b/kotlin-native/backend.native/tests/interop/objc/tests/main.kt new file mode 100644 index 00000000000..178c49725de --- /dev/null +++ b/kotlin-native/backend.native/tests/interop/objc/tests/main.kt @@ -0,0 +1,11 @@ +import kotlin.system.exitProcess +import kotlinx.cinterop.autoreleasepool +import kotlin.native.internal.test.testLauncherEntryPoint + +fun main(args: Array) { + autoreleasepool { + val exitCode = testLauncherEntryPoint(args) + // Note: this test runner checks for memory leaks after successful execution, unlike standard one. + if (exitCode != 0) exitProcess(exitCode) + } +} \ No newline at end of file diff --git a/kotlin-native/backend.native/tests/interop/objc/tests/mangling.h b/kotlin-native/backend.native/tests/interop/objc/tests/mangling.h new file mode 100644 index 00000000000..a4a7868b52b --- /dev/null +++ b/kotlin-native/backend.native/tests/interop/objc/tests/mangling.h @@ -0,0 +1,25 @@ +#import + +// [KT-36067] cinterop tool fails when there is a structure member named Companion + +struct EnumFieldMangleStruct { + enum {Companion, Any} smth; +}; +struct EnumFieldMangleStruct enumMangledStruct = { Any }; + +struct MyStruct { + int Companion; // simple clash + int _Companion; + int $_Companion; + int super; +}; + +struct MyStruct myStruct = {11, 12, 13, 14}; + +@protocol Proto +@property int Companion; // clash on implementing +@end; + +@interface FooMangled : NSObject +//- (void) CompanionS; // mangleSimple does not support this: it may clash after mangling +@end; diff --git a/kotlin-native/backend.native/tests/interop/objc/tests/mangling.kt b/kotlin-native/backend.native/tests/interop/objc/tests/mangling.kt new file mode 100644 index 00000000000..1682357618d --- /dev/null +++ b/kotlin-native/backend.native/tests/interop/objc/tests/mangling.kt @@ -0,0 +1,18 @@ +import kotlinx.cinterop.* +import kotlin.test.* +import objcTests.* + +@Test fun testMangling() { + assertEquals(11, myStruct.`Companion$`) + assertEquals(12, myStruct._Companion) + assertEquals(13, myStruct.`$_Companion`) + assertEquals(14, myStruct.`super`) + + val objc = FooMangled() + objc.`Companion$` = 99 + assertEquals(99, objc.Companion()) + assertEquals(99, objc.`Companion$`) + + enumMangledStruct.smth = Companion + assertEquals(Companion, enumMangledStruct.smth) +} \ No newline at end of file diff --git a/kotlin-native/backend.native/tests/interop/objc/tests/mangling.m b/kotlin-native/backend.native/tests/interop/objc/tests/mangling.m new file mode 100644 index 00000000000..90f6b717b97 --- /dev/null +++ b/kotlin-native/backend.native/tests/interop/objc/tests/mangling.m @@ -0,0 +1,6 @@ +#import "mangling.h" + +// [KT-36067] mangling +@implementation FooMangled : NSObject +@synthesize Companion; +@end; diff --git a/kotlin-native/backend.native/tests/interop/objc/tests/multipleInheritanceClash.h b/kotlin-native/backend.native/tests/interop/objc/tests/multipleInheritanceClash.h new file mode 100644 index 00000000000..a1f25e029f0 --- /dev/null +++ b/kotlin-native/backend.native/tests/interop/objc/tests/multipleInheritanceClash.h @@ -0,0 +1,17 @@ +#import + +@interface MultipleInheritanceClashBase : NSObject +@property (nonnull) MultipleInheritanceClashBase* delegate; +@end; + +@protocol MultipleInheritanceClash +@optional +@property (nullable) id delegate; +@end; + +@interface MultipleInheritanceClash1 : MultipleInheritanceClashBase +@end; + +@interface MultipleInheritanceClash2 : MultipleInheritanceClashBase +@property MultipleInheritanceClashBase* delegate; +@end; \ No newline at end of file diff --git a/kotlin-native/backend.native/tests/interop/objc/tests/multipleInheritanceClash.kt b/kotlin-native/backend.native/tests/interop/objc/tests/multipleInheritanceClash.kt new file mode 100644 index 00000000000..078b42458fa --- /dev/null +++ b/kotlin-native/backend.native/tests/interop/objc/tests/multipleInheritanceClash.kt @@ -0,0 +1,18 @@ +import kotlinx.cinterop.* +import kotlin.test.* +import objcTests.* + +@Test fun testMultipleInheritanceClash() { + val clash1 = MultipleInheritanceClash1() + val clash2 = MultipleInheritanceClash2() + + clash1.delegate = clash1 + assertEquals(clash1, clash1.delegate) + clash1.setDelegate(clash2) + assertEquals(clash2, clash1.delegate()) + + clash2.delegate = clash1 + assertEquals(clash1, clash2.delegate) + clash2.setDelegate(clash2) + assertEquals(clash2, clash2.delegate()) +} \ No newline at end of file diff --git a/kotlin-native/backend.native/tests/interop/objc/tests/multipleInheritanceClash.m b/kotlin-native/backend.native/tests/interop/objc/tests/multipleInheritanceClash.m new file mode 100644 index 00000000000..5586cfbf12c --- /dev/null +++ b/kotlin-native/backend.native/tests/interop/objc/tests/multipleInheritanceClash.m @@ -0,0 +1,10 @@ +#import "multipleInheritanceClash.h" + +@implementation MultipleInheritanceClashBase +@end; + +@implementation MultipleInheritanceClash1 +@end; + +@implementation MultipleInheritanceClash2 +@end; diff --git a/kotlin-native/backend.native/tests/interop/objc/tests/nsOutputStream.kt b/kotlin-native/backend.native/tests/interop/objc/tests/nsOutputStream.kt new file mode 100644 index 00000000000..2bd82ab34a7 --- /dev/null +++ b/kotlin-native/backend.native/tests/interop/objc/tests/nsOutputStream.kt @@ -0,0 +1,8 @@ +import kotlinx.cinterop.* +import kotlin.test.* +import objcTests.* + +@Test fun testNSOutputStreamToMemoryConstructor() { + val stream: Any = NSOutputStream(toMemory = Unit) + assertTrue(stream is NSOutputStream) +} \ No newline at end of file diff --git a/kotlin-native/backend.native/tests/interop/objc/tests/objcWeakRefs.h b/kotlin-native/backend.native/tests/interop/objc/tests/objcWeakRefs.h new file mode 100644 index 00000000000..15ff66dd4cf --- /dev/null +++ b/kotlin-native/backend.native/tests/interop/objc/tests/objcWeakRefs.h @@ -0,0 +1,13 @@ +#import + +@class DeallocListener; + +@interface DeallocExecutor : NSObject +@property DeallocListener* deallocListener; +@end; + +@interface DeallocListener : NSObject +@property (weak) DeallocExecutor* deallocExecutor; +@property BOOL deallocated; +-(BOOL)deallocExecutorIsNil; +@end; diff --git a/kotlin-native/backend.native/tests/interop/objc/tests/objcWeakRefs.kt b/kotlin-native/backend.native/tests/interop/objc/tests/objcWeakRefs.kt new file mode 100644 index 00000000000..64428150f65 --- /dev/null +++ b/kotlin-native/backend.native/tests/interop/objc/tests/objcWeakRefs.kt @@ -0,0 +1,50 @@ +import kotlinx.cinterop.* +import kotlin.native.concurrent.* +import kotlin.test.* +import objcTests.* + +@Test fun testObjCWeakRef() { + val deallocListener = DeallocListener() + assertFalse(deallocListener.deallocated) + + // [deallocListener.deallocExecutorIsNil()] calls deallocExecutor getter, which retains the result and either + // puts it to autoreleasepool or releases it immediately (Obj-C ARC optimization). It seems to depend on the platform. + // Wrap the call to autoreleasepool to ensure the object will be released: + autoreleasepool { + testObjCWeakRef0(deallocListener) + } + + kotlin.native.internal.GC.collect() + assertTrue(deallocListener.deallocated) + assertTrue(deallocListener.deallocExecutorIsNil()) +} + +private fun testObjCWeakRef0(deallocListener: DeallocListener) = withWorker { + assertTrue(deallocListener.deallocExecutorIsNil()) + + val obj = object : DeallocExecutor() {} + deallocListener.deallocExecutor = obj + obj.deallocListener = deallocListener + + assertFalse(deallocListener.deallocExecutorIsNil()) + +// TODO: can't actually test, Obj-C runtime doesn't expect _tryRetain throwing an exception. +// runInWorker { +// assertFailsWith { +// deallocListener.deallocExecutorIsNil() +// } +// } + + obj.freeze() + + runInWorker { + // [deallocListener.deallocExecutorIsNil()] calls deallocExecutor getter, which retains [obj] and either + // puts it to autoreleasepool or releases it immediately (Obj-C ARC optimization). + // Wrap the call to autoreleasepool to ensure [obj] will be released: + autoreleasepool { + assertFalse(deallocListener.deallocExecutorIsNil()) + } + // Process release of Kotlin reference to [obj] in any case: + kotlin.native.internal.GC.collect() + } +} diff --git a/kotlin-native/backend.native/tests/interop/objc/tests/objcWeakRefs.m b/kotlin-native/backend.native/tests/interop/objc/tests/objcWeakRefs.m new file mode 100644 index 00000000000..42c2ee9fa16 --- /dev/null +++ b/kotlin-native/backend.native/tests/interop/objc/tests/objcWeakRefs.m @@ -0,0 +1,13 @@ +#import "objcWeakRefs.h" + +@implementation DeallocExecutor +-(void)dealloc { + self.deallocListener.deallocated = YES; +} +@end; + +@implementation DeallocListener +-(BOOL)deallocExecutorIsNil { + return self.deallocExecutor == nil; +} +@end; \ No newline at end of file diff --git a/kotlin-native/backend.native/tests/interop/objc/tests/overrideInit.h b/kotlin-native/backend.native/tests/interop/objc/tests/overrideInit.h new file mode 100644 index 00000000000..85a3624822e --- /dev/null +++ b/kotlin-native/backend.native/tests/interop/objc/tests/overrideInit.h @@ -0,0 +1,6 @@ +#import + +@interface TestOverrideInit : NSObject +-(instancetype)initWithValue:(int)value NS_DESIGNATED_INITIALIZER; ++(instancetype)createWithValue:(int)value; +@end; \ No newline at end of file diff --git a/kotlin-native/backend.native/tests/interop/objc/tests/overrideInit.kt b/kotlin-native/backend.native/tests/interop/objc/tests/overrideInit.kt new file mode 100644 index 00000000000..d251cb0f387 --- /dev/null +++ b/kotlin-native/backend.native/tests/interop/objc/tests/overrideInit.kt @@ -0,0 +1,22 @@ +import kotlinx.cinterop.* +import kotlin.test.* +import objcTests.* + +@Test fun testOverrideInit1() { + assertEquals(42, (TestOverrideInitImpl1.createWithValue(42) as TestOverrideInitImpl1).value) +} + +private class TestOverrideInitImpl1 @OverrideInit constructor(val value: Int) : TestOverrideInit(value) { + companion object : TestOverrideInitMeta() +} + +// See https://youtrack.jetbrains.com/issue/KT-41910 +@Test fun testOverrideInitWithDefaultArguments() { + assertEquals(42, (TestOverrideInitImpl2.createWithValue(42) as TestOverrideInitImpl2).value) + assertEquals(123, TestOverrideInitImpl2(123).value) + assertEquals(17, TestOverrideInitImpl2().value) +} + +private class TestOverrideInitImpl2 @OverrideInit constructor(val value: Int = 17) : TestOverrideInit(value) { + companion object : TestOverrideInitMeta() +} diff --git a/kotlin-native/backend.native/tests/interop/objc/tests/overrideInit.m b/kotlin-native/backend.native/tests/interop/objc/tests/overrideInit.m new file mode 100644 index 00000000000..34321177d18 --- /dev/null +++ b/kotlin-native/backend.native/tests/interop/objc/tests/overrideInit.m @@ -0,0 +1,11 @@ +#import "overrideInit.h" + +@implementation TestOverrideInit +-(instancetype)initWithValue:(int)value { + return self = [super init]; +} + ++(instancetype)createWithValue:(int)value { + return [[self alloc] initWithValue:value]; +} +@end; diff --git a/kotlin-native/backend.native/tests/interop/objc/tests/sharing.kt b/kotlin-native/backend.native/tests/interop/objc/tests/sharing.kt new file mode 100644 index 00000000000..0d72e58337c --- /dev/null +++ b/kotlin-native/backend.native/tests/interop/objc/tests/sharing.kt @@ -0,0 +1,31 @@ +import kotlinx.cinterop.* +import kotlin.native.concurrent.* +import kotlin.test.* +import objcTests.* + +private class NSObjectImpl : NSObject() { + var x = 111 +} + +// Also see counterpart interop/objc/illegal_sharing.kt +@Test fun testSharing() = withWorker { + val obj = NSObjectImpl() + val array = nsArrayOf(obj) + + assertFalse(obj.isFrozen) + + obj.x = 222 + obj.freeze() + assertTrue(obj.isFrozen) + + runInWorker { + val obj1 = array.objectAtIndex(0) as NSObjectImpl + assertFailsWith { + obj1.x = 333 + } + } + + assertEquals(222, obj.x) + + // TODO: test [obj release] etc. +} diff --git a/kotlin-native/backend.native/tests/interop/objc/tests/structWithNSObject.h b/kotlin-native/backend.native/tests/interop/objc/tests/structWithNSObject.h new file mode 100644 index 00000000000..86d6acb763e --- /dev/null +++ b/kotlin-native/backend.native/tests/interop/objc/tests/structWithNSObject.h @@ -0,0 +1,17 @@ +#import + +struct CStructWithNSObjects { + id any; + + NSString* nsString; + NSString* _Nonnull nonNullString; + NSObject* object; + + NSArray* array; + NSMutableArray* mutableArray; + + NSSet* set; + + NSDictionary* dictionary; +}; + diff --git a/kotlin-native/backend.native/tests/interop/objc/tests/structWithNSObject.kt b/kotlin-native/backend.native/tests/interop/objc/tests/structWithNSObject.kt new file mode 100644 index 00000000000..67459f8b17f --- /dev/null +++ b/kotlin-native/backend.native/tests/interop/objc/tests/structWithNSObject.kt @@ -0,0 +1,65 @@ +import kotlinx.cinterop.* +import kotlin.test.* +import objcTests.* + +private class NSObjectSubClass : NSObject() { + val x = 111 +} + +@Test +fun testStructWithNSObject() { + memScoped { + val struct = alloc() + + struct.any = 5 + assertEquals(5, struct.any) + struct.any = null + assertEquals(null, struct.any) + + struct.nsString = "hello" + assertEquals("hello", struct.nsString) + struct.nsString = null + assertEquals(null, struct.nsString) + + struct.nonNullString = "world" + assertEquals("world", struct.nonNullString) + + struct.`object` = NSObjectSubClass() + assertEquals(111, (struct.`object` as NSObjectSubClass).x) + struct.`object` = null + assertEquals(null, struct.`object`) + + struct.array = null + assertEquals(null, struct.array) + struct.array = listOf(1, 2, 3) + assertEquals(listOf(1, 2, 3), struct.array) + + struct.set = null + assertEquals(null, struct.set) + struct.set = setOf("hello", "world") + assertEquals(setOf("hello", "world"), struct.set) + + struct.dictionary = null + assertEquals(null, struct.dictionary) + struct.dictionary = mapOf("k1" to "v1", "k2" to "v2") + assertEquals(mapOf("k1" to "v1", "k2" to "v2"), struct.dictionary) + + struct.mutableArray = null + assertEquals(null, struct.mutableArray) + struct.mutableArray = mutableListOf(1, 2) + struct.mutableArray!! += 3 + assertEquals(mutableListOf(1, 2, 3), struct.mutableArray) + + // Check that subtyping via Nothing-returning functions does not break compiler. + assertFailsWith { + struct.any = TODO() + struct.nsString = TODO() + struct.nonNullString = TODO() + struct.`object` = TODO() + struct.array = TODO() + struct.set = TODO() + struct.dictionary = TODO() + struct.mutableArray = TODO() + } + } +} \ No newline at end of file diff --git a/kotlin-native/backend.native/tests/interop/objc/tests/tryRetainGC.h b/kotlin-native/backend.native/tests/interop/objc/tests/tryRetainGC.h new file mode 100644 index 00000000000..e86f91d4ff5 --- /dev/null +++ b/kotlin-native/backend.native/tests/interop/objc/tests/tryRetainGC.h @@ -0,0 +1,6 @@ +#import + +@interface WeakRefHolder : NSObject +@property (weak) id obj; +-(void)loadManyTimes; +@end; \ No newline at end of file diff --git a/kotlin-native/backend.native/tests/interop/objc/tests/tryRetainGC.kt b/kotlin-native/backend.native/tests/interop/objc/tests/tryRetainGC.kt new file mode 100644 index 00000000000..21f17d5352a --- /dev/null +++ b/kotlin-native/backend.native/tests/interop/objc/tests/tryRetainGC.kt @@ -0,0 +1,25 @@ +import kotlinx.cinterop.* +import kotlin.test.* +import objcTests.* + +@Test +fun testTryRetainGC() { + kotlin.native.internal.GC.collect() + val weakRefHolder = WeakRefHolder() + createGarbageNSObjects(weakRefHolder) + weakRefHolder.obj = object : NSObject() {} + // Loading weak ref takes a lock. If K/N runtime runs GC while the lock is taken, + // then it releases garbage objects and thus Obj-C runtime might take a recursive lock + // and abort in _os_unfair_lock_recursive_abort. + weakRefHolder.loadManyTimes() +} + +private fun createGarbageNSObjects(weakRefHolder: WeakRefHolder) { + autoreleasepool { + repeat(100) { + // Assigning the object to a weak reference so Obj-C would take a lock when deallocating it: + weakRefHolder.obj = NSObject() + } + weakRefHolder.obj = null + } +} \ No newline at end of file diff --git a/kotlin-native/backend.native/tests/interop/objc/tests/tryRetainGC.m b/kotlin-native/backend.native/tests/interop/objc/tests/tryRetainGC.m new file mode 100644 index 00000000000..b89c9ba26db --- /dev/null +++ b/kotlin-native/backend.native/tests/interop/objc/tests/tryRetainGC.m @@ -0,0 +1,11 @@ +#import "tryRetainGC.h" +#import + +@implementation WeakRefHolder +-(void)loadManyTimes { + NSMutableArray* array = [NSMutableArray new]; + for (int i = 0; i < 10000; ++i) { + [array addObject:self.obj]; + } +} +@end; \ No newline at end of file diff --git a/kotlin-native/backend.native/tests/interop/objc/tests/utils.kt b/kotlin-native/backend.native/tests/interop/objc/tests/utils.kt new file mode 100644 index 00000000000..4dc98a58f0f --- /dev/null +++ b/kotlin-native/backend.native/tests/interop/objc/tests/utils.kt @@ -0,0 +1,17 @@ +import kotlinx.cinterop.* +import kotlin.native.concurrent.* +import objcTests.* + +fun Worker.runInWorker(block: () -> Unit) { + block.freeze() + val future = this.execute(TransferMode.SAFE, { block }) { + it() + } + future.result // Throws on failure. +} + +fun nsArrayOf(vararg elements: Any): NSArray = NSMutableArray().apply { + elements.forEach { + this.addObject(it as ObjCObject) + } +} \ No newline at end of file diff --git a/kotlin-native/backend.native/tests/interop/objc/tests/varargs.h b/kotlin-native/backend.native/tests/interop/objc/tests/varargs.h new file mode 100644 index 00000000000..113844b27ed --- /dev/null +++ b/kotlin-native/backend.native/tests/interop/objc/tests/varargs.h @@ -0,0 +1,20 @@ +#import + +@interface TestVarargs : NSObject +-(instancetype _Nonnull)initWithFormat:(NSString*)format, ...; ++(instancetype _Nonnull)testVarargsWithFormat:(NSString*)format, ...; +@property NSString* formatted; + ++(NSString* _Nonnull)stringWithFormat:(NSString*)format, ...; ++(NSObject* _Nonnull)stringWithFormat:(NSString*)format args:(void*)args; +@end; + +@interface TestVarargs (TestVarargsExtension) +-(instancetype _Nonnull)initWithFormat:(NSString*)format, ...; +@end; + +@interface TestVarargsSubclass : TestVarargs +// Test clashes: +-(instancetype _Nonnull)initWithFormat:(NSString*)format args:(void*)args; ++(NSString* _Nonnull)stringWithFormat:(NSString*)format args:(void*)args; +@end; diff --git a/kotlin-native/backend.native/tests/interop/objc/tests/varargs.kt b/kotlin-native/backend.native/tests/interop/objc/tests/varargs.kt new file mode 100644 index 00000000000..c1808fb9e09 --- /dev/null +++ b/kotlin-native/backend.native/tests/interop/objc/tests/varargs.kt @@ -0,0 +1,53 @@ +import kotlinx.cinterop.* +import kotlin.test.* +import objcTests.* + +@Test fun testVarargs() { + assertEquals( + "a b -1", + TestVarargs.testVarargsWithFormat( + "%@ %s %d", + "a" as NSString, "b".cstr, (-1).toByte() + ).formatted + ) + + assertEquals( + "2 3 9223372036854775807", + TestVarargs( + "%d %d %lld", + 2.toShort(), 3, Long.MAX_VALUE + ).formatted + ) + + assertEquals( + "0.1 0.2 1 0", + TestVarargs.create( + "%.1f %.1lf %d %d", + 0.1.toFloat(), 0.2, true, false + ).formatted + ) + + assertEquals( + "1 2 3", + TestVarargs( + format = "%d %d %d", + args = *arrayOf(1, 2, 3) + ).formatted + ) + + assertEquals( + "4 5 6", + TestVarargs( + args = *arrayOf(4, *arrayOf(5, 6)), + format = "%d %d %d" + ).formatted + ) + + assertEquals( + "7", + TestVarargsSubclass.stringWithFormat( + "%d", + 7 + ) + ) +} \ No newline at end of file diff --git a/kotlin-native/backend.native/tests/interop/objc/tests/varargs.m b/kotlin-native/backend.native/tests/interop/objc/tests/varargs.m new file mode 100644 index 00000000000..4b9e0b41cb0 --- /dev/null +++ b/kotlin-native/backend.native/tests/interop/objc/tests/varargs.m @@ -0,0 +1,51 @@ +#import +#import +#import "varargs.h" + +@implementation TestVarargs +-(instancetype _Nonnull)initWithFormat:(NSString*)format, ... { + self = [super init]; + + va_list args; + va_start(args, format); + self.formatted = [[NSString alloc] initWithFormat:format arguments:args]; + va_end(args); + + return self; +} + ++(instancetype _Nonnull)testVarargsWithFormat:(NSString*)format, ... { + TestVarargs* result = [[self alloc] init]; + + va_list args; + va_start(args, format); + result.formatted = [[NSString alloc] initWithFormat:format arguments:args]; + va_end(args); + + return result; +} + ++(NSString* _Nonnull)stringWithFormat:(NSString*)format, ... { + va_list args; + va_start(args, format); + NSString* result = [[NSString alloc] initWithFormat:format arguments:args]; + va_end(args); + + return result; +} + ++(NSObject* _Nonnull)stringWithFormat:(NSString*)format args:(void*)args { + abort(); +} + +@end; + +@implementation TestVarargsSubclass +-(instancetype _Nonnull)initWithFormat:(NSString*)format args:(void*)args { + abort(); +} + ++(NSString* _Nonnull)stringWithFormat:(NSString*)format args:(void*)args { + abort(); +} +@end; \ No newline at end of file diff --git a/kotlin-native/backend.native/tests/interop/objc/tests/weakRefs.h b/kotlin-native/backend.native/tests/interop/objc/tests/weakRefs.h new file mode 100644 index 00000000000..826629c564b --- /dev/null +++ b/kotlin-native/backend.native/tests/interop/objc/tests/weakRefs.h @@ -0,0 +1,5 @@ +#import + +NSObject* createNSObject() { + return [NSObject new]; +} \ No newline at end of file diff --git a/kotlin-native/backend.native/tests/interop/objc/tests/weakRefs.kt b/kotlin-native/backend.native/tests/interop/objc/tests/weakRefs.kt new file mode 100644 index 00000000000..fa714be5601 --- /dev/null +++ b/kotlin-native/backend.native/tests/interop/objc/tests/weakRefs.kt @@ -0,0 +1,35 @@ +import kotlin.native.ref.* +import kotlinx.cinterop.* +import kotlin.test.* +import objcTests.* + +@Test fun testWeakRefs() { + testWeakReference({ createNSObject()!! }) + + createAndAbandonWeakRef(NSObject()) + + testWeakReference({ NSArray.arrayWithArray(listOf(42)) as NSArray }) +} + +private fun testWeakReference(block: () -> NSObject) { + val ref = autoreleasepool { + createAndTestWeakReference(block) + } + + kotlin.native.internal.GC.collect() + + assertNull(ref.get()) +} + +private fun createAndTestWeakReference(block: () -> NSObject): WeakReference { + val ref = createWeakReference(block) + assertNotNull(ref.get()) + assertEquals(ref.get()!!.hash(), ref.get()!!.hash()) + return ref +} + +private fun createWeakReference(block: () -> NSObject) = WeakReference(block()) + +private fun createAndAbandonWeakRef(obj: NSObject) { + WeakReference(obj) +} \ No newline at end of file diff --git a/kotlin-native/backend.native/tests/interop/objc_with_initializer/objc_misc.def b/kotlin-native/backend.native/tests/interop/objc_with_initializer/objc_misc.def new file mode 100644 index 00000000000..df262119679 --- /dev/null +++ b/kotlin-native/backend.native/tests/interop/objc_with_initializer/objc_misc.def @@ -0,0 +1,5 @@ +language = Objective-C +headers = Foundation/NSArray.h Foundation/NSValue.h Foundation/NSString.h +headerFilter = **/objc_misc.h Foundation/NSArray.h Foundation/NSValue.h Foundation/NSString.h +linkerOpts = -lobjcmisc + diff --git a/kotlin-native/backend.native/tests/interop/objc_with_initializer/objc_misc.h b/kotlin-native/backend.native/tests/interop/objc_with_initializer/objc_misc.h new file mode 100644 index 00000000000..60ab23c5db7 --- /dev/null +++ b/kotlin-native/backend.native/tests/interop/objc_with_initializer/objc_misc.h @@ -0,0 +1,11 @@ +#include +@interface A:NSObject + +@end + +@interface B:A ++(A*)giveC; +@end + +@interface C:A +@end diff --git a/kotlin-native/backend.native/tests/interop/objc_with_initializer/objc_misc.m b/kotlin-native/backend.native/tests/interop/objc_with_initializer/objc_misc.m new file mode 100644 index 00000000000..a186c1ef729 --- /dev/null +++ b/kotlin-native/backend.native/tests/interop/objc_with_initializer/objc_misc.m @@ -0,0 +1,20 @@ +#import +#include "objc_misc.h" +@implementation A + +@end + +@implementation B:A ++(A*)giveC{ + return [[C alloc] init]; +} +@end + +@implementation C:A +@end + +#if 0 +int main() { + [B giveC]; +} +#endif diff --git a/kotlin-native/backend.native/tests/interop/objc_with_initializer/objc_test.kt b/kotlin-native/backend.native/tests/interop/objc_with_initializer/objc_test.kt new file mode 100644 index 00000000000..fdce20d8a3f --- /dev/null +++ b/kotlin-native/backend.native/tests/interop/objc_with_initializer/objc_test.kt @@ -0,0 +1,7 @@ +import objc_misc.* + +val a = B.giveC()!! as C + +fun main() { + println("OK") +} \ No newline at end of file diff --git a/kotlin-native/backend.native/tests/interop/platform_zlib.kt b/kotlin-native/backend.native/tests/interop/platform_zlib.kt new file mode 100644 index 00000000000..0de4f44fea8 --- /dev/null +++ b/kotlin-native/backend.native/tests/interop/platform_zlib.kt @@ -0,0 +1,27 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +import kotlinx.cinterop.* + +import platform.zlib.* + +val source = immutableBlobOf(0xF3, 0x48, 0xCD, 0xC9, 0xC9, 0x57, 0x04, 0x00).asCPointer().reinterpret() +val golden = immutableBlobOf(0x48, 0x65, 0x6C, 0x6C, 0x6F, 0x21, 0x00).asCPointer() + +fun main(args: Array) = memScoped { + val buffer = ByteArray(32) + buffer.usePinned { pinned -> + val z = alloc().apply { + next_in = source + avail_in = 8u + next_out = pinned.addressOf(0).reinterpret() + avail_out = buffer.size.toUInt() + }.ptr + + if (inflateInit2(z, -15) == Z_OK && inflate(z, Z_FINISH) == Z_STREAM_END && inflateEnd(z) == Z_OK) + println(buffer.toKString()) + } + println(golden.toKString()) +} diff --git a/kotlin-native/backend.native/tests/iosLauncher/.gitignore b/kotlin-native/backend.native/tests/iosLauncher/.gitignore new file mode 100644 index 00000000000..4f405ccc66e --- /dev/null +++ b/kotlin-native/backend.native/tests/iosLauncher/.gitignore @@ -0,0 +1 @@ +xcuserdata \ No newline at end of file diff --git a/kotlin-native/backend.native/tests/iosLauncher/KonanTestLauncher.xcodeproj/project.pbxproj b/kotlin-native/backend.native/tests/iosLauncher/KonanTestLauncher.xcodeproj/project.pbxproj new file mode 100644 index 00000000000..0c736eaf44d --- /dev/null +++ b/kotlin-native/backend.native/tests/iosLauncher/KonanTestLauncher.xcodeproj/project.pbxproj @@ -0,0 +1,381 @@ +// !$*UTF8*$! +{ + archiveVersion = 1; + classes = { + }; + objectVersion = 46; + objects = { + +/* Begin PBXBuildFile section */ + 6522238E98511C4FCE1C84DB /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 65222E77B9880A666F68B517 /* Main.storyboard */; }; + 652225006B71BB79B6D0D726 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 652225CB5CBA03A47F5148C4 /* Assets.xcassets */; }; + 65222623D2703AEFB363121F /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 6522214B5DB6829939E3F325 /* LaunchScreen.storyboard */; }; +/* End PBXBuildFile section */ + +/* Begin PBXFileReference section */ + 65222402702E398002CC649E /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.info; path = Info.plist; sourceTree = ""; }; + 652225210978EC9016CB5EFF /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = ""; }; + 652225CB5CBA03A47F5148C4 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; + 6522292479593142D11AD88A /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = ""; }; + 65222B6AE5EB6447D2D3E6ED /* KonanTestLauncher.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = KonanTestLauncher.app; sourceTree = BUILT_PRODUCTS_DIR; }; +/* End PBXFileReference section */ + +/* Begin PBXFrameworksBuildPhase section */ + 65222DAFA15A9AB521E55317 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXFrameworksBuildPhase section */ + +/* Begin PBXGroup section */ + 65222113FD4C67E6BA46614D /* gradle */ = { + isa = PBXGroup; + children = ( + 6522242531A4CAB63B2BFE71 /* wrapper */, + ); + path = gradle; + sourceTree = ""; + }; + 6522238C8FBBB7F836D071CF /* KonanTestLauncher */ = { + isa = PBXGroup; + children = ( + 65222402702E398002CC649E /* Info.plist */, + 652225CB5CBA03A47F5148C4 /* Assets.xcassets */, + 6522214B5DB6829939E3F325 /* LaunchScreen.storyboard */, + 65222E77B9880A666F68B517 /* Main.storyboard */, + ); + path = KonanTestLauncher; + sourceTree = ""; + }; + 65222469E9E3E627366829E9 /* src */ = { + isa = PBXGroup; + children = ( + 65222A6C6191FBB233B995FB /* KonanTestLauncherMain */, + ); + path = src; + sourceTree = ""; + }; + 652229EDCC8B5D981F51A0FE /* Products */ = { + isa = PBXGroup; + children = ( + 65222B6AE5EB6447D2D3E6ED /* KonanTestLauncher.app */, + ); + name = Products; + sourceTree = ""; + }; + 65222A6C6191FBB233B995FB /* KonanTestLauncherMain */ = { + isa = PBXGroup; + children = ( + 65222B5F2F23FCBC77FE9C46 /* kotlin */, + ); + path = KonanTestLauncherMain; + sourceTree = ""; + }; + 65222B5F2F23FCBC77FE9C46 /* kotlin */ = { + isa = PBXGroup; + children = ( + ); + path = kotlin; + sourceTree = ""; + }; + 65222C68A5CC689D5AA66D3B = { + isa = PBXGroup; + children = ( + 652229EDCC8B5D981F51A0FE /* Products */, + 6522238C8FBBB7F836D071CF /* KonanTestLauncher */, + ); + sourceTree = ""; + }; +/* End PBXGroup section */ + +/* Begin PBXNativeTarget section */ + 65222A26710249E058596147 /* KonanTestLauncher */ = { + isa = PBXNativeTarget; + buildConfigurationList = 6522285AF364E21A1540BD08 /* Build configuration list for PBXNativeTarget "KonanTestLauncher" */; + buildPhases = ( + 652225D77218699A3A7F6722 /* Sources */, + 65222DAFA15A9AB521E55317 /* Frameworks */, + 65222B3A6677E222C51FAFB8 /* Resources */, + 65222EB12A851E15D756D3F8 /* Compile Kotlin/Native */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = KonanTestLauncher; + productName = KonanTestLauncher; + productReference = 65222B6AE5EB6447D2D3E6ED /* KonanTestLauncher.app */; + productType = "com.apple.product-type.application"; + }; +/* End PBXNativeTarget section */ + +/* Begin PBXProject section */ + 65222D052D6D41A4EEFB4821 /* Project object */ = { + isa = PBXProject; + attributes = { + CLASSPREFIX = ""; + ORGANIZATIONNAME = jetbrains; + TargetAttributes = { + 65222A26710249E058596147 = { + DevelopmentTeam = ""; + ProvisioningStyle = Automatic; + }; + }; + }; + buildConfigurationList = 6522294C3F904F562F8F0628 /* Build configuration list for PBXProject "KonanTestLauncher" */; + compatibilityVersion = "Xcode 3.2"; + developmentRegion = English; + hasScannedForEncodings = 0; + knownRegions = ( + English, + en, + Base, + ); + mainGroup = 65222C68A5CC689D5AA66D3B; + productRefGroup = 652229EDCC8B5D981F51A0FE /* Products */; + projectDirPath = ""; + projectRoot = ""; + targets = ( + 65222A26710249E058596147 /* KonanTestLauncher */, + ); + }; +/* End PBXProject section */ + +/* Begin PBXResourcesBuildPhase section */ + 65222B3A6677E222C51FAFB8 /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 652225006B71BB79B6D0D726 /* Assets.xcassets in Resources */, + 65222623D2703AEFB363121F /* LaunchScreen.storyboard in Resources */, + 6522238E98511C4FCE1C84DB /* Main.storyboard in Resources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXResourcesBuildPhase section */ + +/* Begin PBXShellScriptBuildPhase section */ + 65222EB12A851E15D756D3F8 /* Compile Kotlin/Native */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputPaths = ( + ); + name = "Compile Kotlin/Native"; + outputPaths = ( + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/bash; + shellScript = "set -x\n\ncp \"$PROJECT_DIR/KonanTestLauncher/build/$TARGET_NAME.kexe\" \"$TARGET_BUILD_DIR/$EXECUTABLE_PATH\"\n"; + }; +/* End PBXShellScriptBuildPhase section */ + +/* Begin PBXSourcesBuildPhase section */ + 652225D77218699A3A7F6722 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXSourcesBuildPhase section */ + +/* Begin PBXVariantGroup section */ + 6522214B5DB6829939E3F325 /* LaunchScreen.storyboard */ = { + isa = PBXVariantGroup; + children = ( + 652225210978EC9016CB5EFF /* Base */, + ); + name = LaunchScreen.storyboard; + sourceTree = ""; + }; + 65222E77B9880A666F68B517 /* Main.storyboard */ = { + isa = PBXVariantGroup; + children = ( + 6522292479593142D11AD88A /* Base */, + ); + name = Main.storyboard; + sourceTree = ""; + }; +/* End PBXVariantGroup section */ + +/* Begin XCBuildConfiguration section */ + 65222812DCD81B77CE1F15D9 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES; + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ANALYZER_NONNULL = YES; + CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_ENABLE_OBJC_WEAK = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_DOCUMENTATION_COMMENTS = YES; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + CODE_SIGN_IDENTITY = "iPhone Developer"; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + ENABLE_NS_ASSERTIONS = NO; + ENABLE_STRICT_OBJC_MSGSEND = YES; + GCC_C_LANGUAGE_STANDARD = gnu11; + GCC_NO_COMMON_BLOCKS = YES; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + IPHONEOS_DEPLOYMENT_TARGET = 12.4; + MTL_ENABLE_DEBUG_INFO = NO; + MTL_FAST_MATH = YES; + SDKROOT = iphoneos; + VALIDATE_PRODUCT = YES; + }; + name = Release; + }; + 65222AF1F63AE763ED0326E5 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CODE_SIGN_IDENTITY = "iPhone Developer"; + CODE_SIGN_STYLE = Automatic; + DEVELOPMENT_TEAM = ""; + INFOPLIST_FILE = KonanTestLauncher/Info.plist; + IPHONEOS_DEPLOYMENT_TARGET = 10.3; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; + PRODUCT_BUNDLE_IDENTIFIER = org.jetbrains.kotlin.KonanTestLauncher; + PRODUCT_NAME = "$(TARGET_NAME)"; + PROVISIONING_PROFILE_SPECIFIER = ""; + TARGETED_DEVICE_FAMILY = "1,2"; + VALID_ARCHS = arm64; + }; + name = Debug; + }; + 65222BB9FE8C772F3939AE5A /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES; + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ANALYZER_NONNULL = YES; + CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_ENABLE_OBJC_WEAK = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_DOCUMENTATION_COMMENTS = YES; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + CODE_SIGN_IDENTITY = "iPhone Developer"; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = dwarf; + ENABLE_STRICT_OBJC_MSGSEND = YES; + ENABLE_TESTABILITY = YES; + GCC_C_LANGUAGE_STANDARD = gnu11; + GCC_DYNAMIC_NO_PIC = NO; + GCC_NO_COMMON_BLOCKS = YES; + GCC_OPTIMIZATION_LEVEL = 0; + GCC_PREPROCESSOR_DEFINITIONS = ( + "DEBUG=1", + "$(inherited)", + ); + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + IPHONEOS_DEPLOYMENT_TARGET = 12.4; + MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE; + MTL_FAST_MATH = YES; + ONLY_ACTIVE_ARCH = YES; + SDKROOT = iphoneos; + }; + name = Debug; + }; + 65222EF46F1047DBF88CFC60 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CODE_SIGN_IDENTITY = "iPhone Developer"; + CODE_SIGN_STYLE = Automatic; + DEVELOPMENT_TEAM = ""; + INFOPLIST_FILE = KonanTestLauncher/Info.plist; + IPHONEOS_DEPLOYMENT_TARGET = 10.3; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; + PRODUCT_BUNDLE_IDENTIFIER = org.jetbrains.kotlin.KonanTestLauncher; + PRODUCT_NAME = "$(TARGET_NAME)"; + PROVISIONING_PROFILE_SPECIFIER = ""; + TARGETED_DEVICE_FAMILY = "1,2"; + VALID_ARCHS = arm64; + }; + name = Release; + }; +/* End XCBuildConfiguration section */ + +/* Begin XCConfigurationList section */ + 6522285AF364E21A1540BD08 /* Build configuration list for PBXNativeTarget "KonanTestLauncher" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 65222AF1F63AE763ED0326E5 /* Debug */, + 65222EF46F1047DBF88CFC60 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 6522294C3F904F562F8F0628 /* Build configuration list for PBXProject "KonanTestLauncher" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 65222BB9FE8C772F3939AE5A /* Debug */, + 65222812DCD81B77CE1F15D9 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; +/* End XCConfigurationList section */ + }; + rootObject = 65222D052D6D41A4EEFB4821 /* Project object */; +} diff --git a/kotlin-native/backend.native/tests/iosLauncher/KonanTestLauncher.xcodeproj/project.xcworkspace/contents.xcworkspacedata b/kotlin-native/backend.native/tests/iosLauncher/KonanTestLauncher.xcodeproj/project.xcworkspace/contents.xcworkspacedata new file mode 100644 index 00000000000..919434a6254 --- /dev/null +++ b/kotlin-native/backend.native/tests/iosLauncher/KonanTestLauncher.xcodeproj/project.xcworkspace/contents.xcworkspacedata @@ -0,0 +1,7 @@ + + + + + diff --git a/kotlin-native/backend.native/tests/iosLauncher/KonanTestLauncher.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist b/kotlin-native/backend.native/tests/iosLauncher/KonanTestLauncher.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist new file mode 100644 index 00000000000..18d981003d6 --- /dev/null +++ b/kotlin-native/backend.native/tests/iosLauncher/KonanTestLauncher.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist @@ -0,0 +1,8 @@ + + + + + IDEDidComputeMac32BitWarning + + + diff --git a/kotlin-native/backend.native/tests/iosLauncher/KonanTestLauncher.xcodeproj/project.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings b/kotlin-native/backend.native/tests/iosLauncher/KonanTestLauncher.xcodeproj/project.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings new file mode 100644 index 00000000000..5f88f383a29 --- /dev/null +++ b/kotlin-native/backend.native/tests/iosLauncher/KonanTestLauncher.xcodeproj/project.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings @@ -0,0 +1,10 @@ + + + + + BuildSystemType + Original + PreviewsEnabled + + + \ No newline at end of file diff --git a/kotlin-native/backend.native/tests/iosLauncher/KonanTestLauncher/Assets.xcassets/AppIcon.appiconset/Contents.json b/kotlin-native/backend.native/tests/iosLauncher/KonanTestLauncher/Assets.xcassets/AppIcon.appiconset/Contents.json new file mode 100644 index 00000000000..d8db8d65fd7 --- /dev/null +++ b/kotlin-native/backend.native/tests/iosLauncher/KonanTestLauncher/Assets.xcassets/AppIcon.appiconset/Contents.json @@ -0,0 +1,98 @@ +{ + "images" : [ + { + "idiom" : "iphone", + "size" : "20x20", + "scale" : "2x" + }, + { + "idiom" : "iphone", + "size" : "20x20", + "scale" : "3x" + }, + { + "idiom" : "iphone", + "size" : "29x29", + "scale" : "2x" + }, + { + "idiom" : "iphone", + "size" : "29x29", + "scale" : "3x" + }, + { + "idiom" : "iphone", + "size" : "40x40", + "scale" : "2x" + }, + { + "idiom" : "iphone", + "size" : "40x40", + "scale" : "3x" + }, + { + "idiom" : "iphone", + "size" : "60x60", + "scale" : "2x" + }, + { + "idiom" : "iphone", + "size" : "60x60", + "scale" : "3x" + }, + { + "idiom" : "ipad", + "size" : "20x20", + "scale" : "1x" + }, + { + "idiom" : "ipad", + "size" : "20x20", + "scale" : "2x" + }, + { + "idiom" : "ipad", + "size" : "29x29", + "scale" : "1x" + }, + { + "idiom" : "ipad", + "size" : "29x29", + "scale" : "2x" + }, + { + "idiom" : "ipad", + "size" : "40x40", + "scale" : "1x" + }, + { + "idiom" : "ipad", + "size" : "40x40", + "scale" : "2x" + }, + { + "idiom" : "ipad", + "size" : "76x76", + "scale" : "1x" + }, + { + "idiom" : "ipad", + "size" : "76x76", + "scale" : "2x" + }, + { + "idiom" : "ipad", + "size" : "83.5x83.5", + "scale" : "2x" + }, + { + "idiom" : "ios-marketing", + "size" : "1024x1024", + "scale" : "1x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/kotlin-native/backend.native/tests/iosLauncher/KonanTestLauncher/Base.lproj/LaunchScreen.storyboard b/kotlin-native/backend.native/tests/iosLauncher/KonanTestLauncher/Base.lproj/LaunchScreen.storyboard new file mode 100644 index 00000000000..f83f6fd5810 --- /dev/null +++ b/kotlin-native/backend.native/tests/iosLauncher/KonanTestLauncher/Base.lproj/LaunchScreen.storyboard @@ -0,0 +1,25 @@ + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/kotlin-native/backend.native/tests/iosLauncher/KonanTestLauncher/Base.lproj/Main.storyboard b/kotlin-native/backend.native/tests/iosLauncher/KonanTestLauncher/Base.lproj/Main.storyboard new file mode 100644 index 00000000000..b52868927a9 --- /dev/null +++ b/kotlin-native/backend.native/tests/iosLauncher/KonanTestLauncher/Base.lproj/Main.storyboard @@ -0,0 +1,48 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/kotlin-native/backend.native/tests/iosLauncher/KonanTestLauncher/Info.plist b/kotlin-native/backend.native/tests/iosLauncher/KonanTestLauncher/Info.plist new file mode 100644 index 00000000000..16be3b68112 --- /dev/null +++ b/kotlin-native/backend.native/tests/iosLauncher/KonanTestLauncher/Info.plist @@ -0,0 +1,45 @@ + + + + + CFBundleDevelopmentRegion + $(DEVELOPMENT_LANGUAGE) + CFBundleExecutable + $(EXECUTABLE_NAME) + CFBundleIdentifier + $(PRODUCT_BUNDLE_IDENTIFIER) + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + $(PRODUCT_NAME) + CFBundlePackageType + APPL + CFBundleShortVersionString + 1.0 + CFBundleVersion + 1 + LSRequiresIPhoneOS + + UILaunchStoryboardName + LaunchScreen + UIMainStoryboardFile + Main + UIRequiredDeviceCapabilities + + armv7 + + UISupportedInterfaceOrientations + + UIInterfaceOrientationPortrait + UIInterfaceOrientationLandscapeLeft + UIInterfaceOrientationLandscapeRight + + UISupportedInterfaceOrientations~ipad + + UIInterfaceOrientationPortrait + UIInterfaceOrientationPortraitUpsideDown + UIInterfaceOrientationLandscapeLeft + UIInterfaceOrientationLandscapeRight + + + diff --git a/kotlin-native/backend.native/tests/jsinterop/math.kt b/kotlin-native/backend.native/tests/jsinterop/math.kt new file mode 100644 index 00000000000..e337c1b4749 --- /dev/null +++ b/kotlin-native/backend.native/tests/jsinterop/math.kt @@ -0,0 +1,21 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +import kotlinx.interop.wasm.math.* +import kotlinx.wasm.jsinterop.* + +fun main(args: Array) { + + val e = Math.E + val pi = Math.PI + + val sin_pi = Math.sin(pi) + val sin_pi_2 = Math.sin(pi/2) + val ln_1 = Math.log(1.0) + val ln_e = Math.log(e) + + println("e = $e, pi = $pi, sin(pi) = $sin_pi, sin(pi/2) = $sin_pi_2, ln(1) = $ln_1, ln(e) = $ln_e") +} + diff --git a/kotlin-native/backend.native/tests/link/default/default.kt b/kotlin-native/backend.native/tests/link/default/default.kt new file mode 100644 index 00000000000..96482ed7b0d --- /dev/null +++ b/kotlin-native/backend.native/tests/link/default/default.kt @@ -0,0 +1,13 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +import kotlinx.cinterop.convert +import platform.posix.* + +fun main(args: Array) { + // Just check the typealias is in scope. + val sizet: size_t = 0.convert() + println("sizet = $sizet") +} diff --git a/kotlin-native/backend.native/tests/link/fake_overrides/base.kt b/kotlin-native/backend.native/tests/link/fake_overrides/base.kt new file mode 100644 index 00000000000..a52fbad5de4 --- /dev/null +++ b/kotlin-native/backend.native/tests/link/fake_overrides/base.kt @@ -0,0 +1,6 @@ +package serialization.fake_overrides + +open class A { + open fun qux() = "Super" + open fun tic() = "Super" +} diff --git a/kotlin-native/backend.native/tests/link/fake_overrides/main.kt b/kotlin-native/backend.native/tests/link/fake_overrides/main.kt new file mode 100644 index 00000000000..c455409502b --- /dev/null +++ b/kotlin-native/backend.native/tests/link/fake_overrides/main.kt @@ -0,0 +1,9 @@ +import serialization.fake_overrides.* +fun test1() = println(Z().bar()) + +fun main() { + test0() + test1() + test2() + test3() +} diff --git a/kotlin-native/backend.native/tests/link/fake_overrides/move.kt b/kotlin-native/backend.native/tests/link/fake_overrides/move.kt new file mode 100644 index 00000000000..b707c1a8a44 --- /dev/null +++ b/kotlin-native/backend.native/tests/link/fake_overrides/move.kt @@ -0,0 +1,15 @@ +package serialization.fake_overrides + +open class X { +} + +class Y: X() { + fun bar() = "Stale" +} + +class B: A() { +} + +class C: A() { + override fun tic() = "Child" +} diff --git a/kotlin-native/backend.native/tests/link/fake_overrides/move2.kt b/kotlin-native/backend.native/tests/link/fake_overrides/move2.kt new file mode 100644 index 00000000000..655cf7eda1e --- /dev/null +++ b/kotlin-native/backend.native/tests/link/fake_overrides/move2.kt @@ -0,0 +1,15 @@ +package serialization.fake_overrides + +open class X { + fun bar() = "Moved" +} + +class Y: X() { +} + +class B: A() { + override fun qux() = "Child" +} + +class C: A() { +} diff --git a/kotlin-native/backend.native/tests/link/fake_overrides/use.kt b/kotlin-native/backend.native/tests/link/fake_overrides/use.kt new file mode 100644 index 00000000000..fcee6cbffd7 --- /dev/null +++ b/kotlin-native/backend.native/tests/link/fake_overrides/use.kt @@ -0,0 +1,8 @@ +package serialization.fake_overrides + +class Z: X() { +} + +fun test0() = println(Y().bar()) +fun test2() = println(B().qux()) +fun test3() = println(C().qux()) diff --git a/kotlin-native/backend.native/tests/link/ir_providers/hello.kt b/kotlin-native/backend.native/tests/link/ir_providers/hello.kt new file mode 100644 index 00000000000..dbd2d6996f7 --- /dev/null +++ b/kotlin-native/backend.native/tests/link/ir_providers/hello.kt @@ -0,0 +1 @@ +fun main() = println("hello") \ No newline at end of file diff --git a/kotlin-native/backend.native/tests/link/ir_providers/library/empty.kt b/kotlin-native/backend.native/tests/link/ir_providers/library/empty.kt new file mode 100644 index 00000000000..e69de29bb2d diff --git a/kotlin-native/backend.native/tests/link/ir_providers/library/manifest.properties b/kotlin-native/backend.native/tests/link/ir_providers/library/manifest.properties new file mode 100644 index 00000000000..c2751ab1308 --- /dev/null +++ b/kotlin-native/backend.native/tests/link/ir_providers/library/manifest.properties @@ -0,0 +1 @@ +ir_provider=UNSUPPORTED \ No newline at end of file diff --git a/kotlin-native/backend.native/tests/link/lib/foo.kt b/kotlin-native/backend.native/tests/link/lib/foo.kt new file mode 100644 index 00000000000..5ceaa7740fa --- /dev/null +++ b/kotlin-native/backend.native/tests/link/lib/foo.kt @@ -0,0 +1,12 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +package qwerty + +fun foo(a: Int): Int { + return a +} + + diff --git a/kotlin-native/backend.native/tests/link/lib/foo2.kt b/kotlin-native/backend.native/tests/link/lib/foo2.kt new file mode 100644 index 00000000000..af5db52e965 --- /dev/null +++ b/kotlin-native/backend.native/tests/link/lib/foo2.kt @@ -0,0 +1,12 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +package qwerty + +fun foo2(a: Int): Int { + return a +} + + diff --git a/kotlin-native/backend.native/tests/link/omit/hello.kt b/kotlin-native/backend.native/tests/link/omit/hello.kt new file mode 100644 index 00000000000..41886e3b9cf --- /dev/null +++ b/kotlin-native/backend.native/tests/link/omit/hello.kt @@ -0,0 +1,8 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +fun main(args: Array) { + println("Hello") +} diff --git a/kotlin-native/backend.native/tests/link/omit/lib.kt b/kotlin-native/backend.native/tests/link/omit/lib.kt new file mode 100644 index 00000000000..4286010b189 --- /dev/null +++ b/kotlin-native/backend.native/tests/link/omit/lib.kt @@ -0,0 +1,7 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +package foo +fun foo() {} diff --git a/kotlin-native/backend.native/tests/link/private_fake_overrides/inherit_lib.kt b/kotlin-native/backend.native/tests/link/private_fake_overrides/inherit_lib.kt new file mode 100644 index 00000000000..79d005ea442 --- /dev/null +++ b/kotlin-native/backend.native/tests/link/private_fake_overrides/inherit_lib.kt @@ -0,0 +1,53 @@ +/* + * Copyright 2010-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +// Private classes +private open class A { + public fun foo1() = println("PASS") + internal fun foo2() = println("PASS") + protected fun foo3() = println("PASS") +} + +private class B:A() { + fun foo4() = foo3() +} + +// Private interfaces +private interface C { + fun foo() = println("PASS") +} + +private class D: C + +fun runner() { + B().foo1() + B().foo2() + B().foo4() + + D().foo() + + // Objects + object : A(){ + fun foo4() = foo3() + }.apply { + foo1() + foo2() + foo4() + } + + // Function local classes + abstract class E { + public open fun foo1() = println("PASS") + internal open fun foo2() = println("PASS") + protected open fun foo3() = println("PASS") + } + class F : E() { + fun foo4() = foo3() + } + F().foo1() + F().foo2() + F().foo4() +} + diff --git a/kotlin-native/backend.native/tests/link/private_fake_overrides/inherit_main.kt b/kotlin-native/backend.native/tests/link/private_fake_overrides/inherit_main.kt new file mode 100644 index 00000000000..46b1d2d0bd2 --- /dev/null +++ b/kotlin-native/backend.native/tests/link/private_fake_overrides/inherit_main.kt @@ -0,0 +1,9 @@ +/* + * Copyright 2010-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +fun main() { + runner() +} + diff --git a/kotlin-native/backend.native/tests/link/private_fake_overrides/override_lib.kt b/kotlin-native/backend.native/tests/link/private_fake_overrides/override_lib.kt new file mode 100644 index 00000000000..6af4bca65ab --- /dev/null +++ b/kotlin-native/backend.native/tests/link/private_fake_overrides/override_lib.kt @@ -0,0 +1,97 @@ +/* + * Copyright 2010-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +// Private classes +private open class A { + public open fun foo1() = println("FAIL") + internal open fun foo2() = println("FAIL") + protected open fun foo3() = println("FAIL") + private fun foo4() = println("FAIL") +} + +private class B:A() { + override public fun foo1() = println("PASS") + override internal fun foo2() = println("PASS") + override protected fun foo3() = println("PASS") + private fun foo4() = println("PASS") + fun foo5() = foo3() + fun foo6() = foo4() +} + +private abstract class G { + public abstract fun foo1() + internal abstract fun foo2() + protected abstract fun foo3() + private fun foo4() = println("FAIL") +} + +private class H:A() { + override public fun foo1() = println("PASS") + override internal fun foo2() = println("PASS") + override protected fun foo3() = println("PASS") + private fun foo4() = println("PASS") + fun foo5() = foo3() + fun foo6() = foo4() +} + + +// Private interfaces +private interface C { + fun foo() = println("FAIL") +} + +private class D: C { + override fun foo() = println("PASS") +} + +fun runner() { + B().foo1() + B().foo2() + B().foo5() + B().foo6() + + H().foo1() + H().foo2() + H().foo5() + H().foo6() + + D().foo() + + // Objects + object : A(){ + override public fun foo1() = println("PASS") + override internal fun foo2() = println("PASS") + override protected fun foo3() = println("PASS") + private fun foo4() = println("PASS") + fun foo5() = foo3() + fun foo6() = foo4() + }.apply { + foo1() + foo2() + foo5() + foo6() + } + + // Function local classes + open class E { + public open fun foo1() = println("FAIL") + internal open fun foo2() = println("FAIL") + protected open fun foo3() = println("FAIL") + private fun foo4() = println("FAIL") + } + class F : E() { + public override fun foo1() = println("PASS") + internal override fun foo2() = println("PASS") + protected override fun foo3() = println("PASS") + private fun foo4() = println("PASS") + fun foo5() = foo3() + fun foo6() = foo4() + } + F().foo1() + F().foo2() + F().foo5() + F().foo6() +} + diff --git a/kotlin-native/backend.native/tests/link/private_fake_overrides/override_main.kt b/kotlin-native/backend.native/tests/link/private_fake_overrides/override_main.kt new file mode 100644 index 00000000000..281b809b23b --- /dev/null +++ b/kotlin-native/backend.native/tests/link/private_fake_overrides/override_main.kt @@ -0,0 +1,8 @@ +/* + * Copyright 2010-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +fun main() { + runner() +} diff --git a/kotlin-native/backend.native/tests/link/purge1/lib.kt b/kotlin-native/backend.native/tests/link/purge1/lib.kt new file mode 100644 index 00000000000..52618cd1422 --- /dev/null +++ b/kotlin-native/backend.native/tests/link/purge1/lib.kt @@ -0,0 +1,14 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +import kotlinx.cinterop.convert +import platform.posix.* + +fun foo() { + println("linked library") + val size: size_t = 17.convert() + val e = fabs(1.toDouble()) + println("and symbols from posix available: $size; $e") +} diff --git a/kotlin-native/backend.native/tests/link/purge1/prog.kt b/kotlin-native/backend.native/tests/link/purge1/prog.kt new file mode 100644 index 00000000000..8a0446a79af --- /dev/null +++ b/kotlin-native/backend.native/tests/link/purge1/prog.kt @@ -0,0 +1,9 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + + +fun main(args: Array) { + foo() +} diff --git a/kotlin-native/backend.native/tests/link/src/bar.kt b/kotlin-native/backend.native/tests/link/src/bar.kt new file mode 100644 index 00000000000..a728d09ba7d --- /dev/null +++ b/kotlin-native/backend.native/tests/link/src/bar.kt @@ -0,0 +1,11 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +import qwerty.* + +fun main(args: Array) { + val size = foo(foo2(args.size)) + println(size.toString()) +} diff --git a/kotlin-native/backend.native/tests/link/versioning/empty.kt b/kotlin-native/backend.native/tests/link/versioning/empty.kt new file mode 100644 index 00000000000..48f97f12737 --- /dev/null +++ b/kotlin-native/backend.native/tests/link/versioning/empty.kt @@ -0,0 +1,2 @@ +/* This file has intentionally been left blank */ + diff --git a/kotlin-native/backend.native/tests/link/versioning/hello.kt b/kotlin-native/backend.native/tests/link/versioning/hello.kt new file mode 100644 index 00000000000..124bc45574b --- /dev/null +++ b/kotlin-native/backend.native/tests/link/versioning/hello.kt @@ -0,0 +1,3 @@ +fun main() { + println("Hello, versioned world!") +} diff --git a/kotlin-native/backend.native/tests/lower/immutable_blob_in_lambda.kt b/kotlin-native/backend.native/tests/lower/immutable_blob_in_lambda.kt new file mode 100644 index 00000000000..badd1e642f2 --- /dev/null +++ b/kotlin-native/backend.native/tests/lower/immutable_blob_in_lambda.kt @@ -0,0 +1,14 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +package lower.immutable_blob_in_lambda + +import kotlin.test.* + +@Test +fun runTest() = run { + val golden = immutableBlobOf(123) + println(golden[0]) +} \ No newline at end of file diff --git a/kotlin-native/backend.native/tests/lower/local_delegated_property_link/lib.kt b/kotlin-native/backend.native/tests/lower/local_delegated_property_link/lib.kt new file mode 100644 index 00000000000..bea7249286e --- /dev/null +++ b/kotlin-native/backend.native/tests/lower/local_delegated_property_link/lib.kt @@ -0,0 +1,8 @@ +fun foo(): String{ + val bar: String by lazy { + "OK" + } + + return bar +} + diff --git a/kotlin-native/backend.native/tests/lower/local_delegated_property_link/main.kt b/kotlin-native/backend.native/tests/lower/local_delegated_property_link/main.kt new file mode 100644 index 00000000000..f9033e15661 --- /dev/null +++ b/kotlin-native/backend.native/tests/lower/local_delegated_property_link/main.kt @@ -0,0 +1,3 @@ +fun main() { + println(foo()) +} diff --git a/kotlin-native/backend.native/tests/lower/tailrec.kt b/kotlin-native/backend.native/tests/lower/tailrec.kt new file mode 100644 index 00000000000..bd8194474b7 --- /dev/null +++ b/kotlin-native/backend.native/tests/lower/tailrec.kt @@ -0,0 +1,97 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +package lower.tailrec + + +fun main() { + println(add(5, 7)) + println(add(100000000, 0)) + + println(fib(6)) + + println(one(5)) + + countdown(3) + + println(listOf(1, 2, 3).indexOf(3)) + println(listOf(1, 2, 3).indexOf(4)) + + println(Integer(5).isLessOrEqualThan(7)) + println(Integer(42).isLessOrEqualThan(1)) + + println(DefaultArgGetter().foo("non-default")) + println(EitherDelegatedOrNot(NotDelegated()).get42()) +} + +tailrec fun add(x: Int, y: Int): Int = if (x > 0) add(x - 1, y + 1) else y + +fun fib(n: Int): Int { + tailrec fun fibAcc(n: Int, acc: Int): Int = if (n < 2) { + n + acc + } else { + fibAcc(n - 1, fibAcc(n - 2, acc)) + } + + return fibAcc(n, 0) +} + +tailrec fun one(delay: Int, result: Int = delay + 1): Int = if (delay > 0) one(delay - 1) else result + +tailrec fun countdown(iterations: Int): Unit { + if (iterations > 0) { + println("$iterations ...") + countdown(iterations - 1) + } else { + println("ready!") + } +} + +tailrec fun List.indexOf(x: T, startIndex: Int = 0): Int { + if (startIndex >= this.size) { + return -1 + } + + if (this[startIndex] != x) { + return this.indexOf(x, startIndex + 1) + } + + return startIndex + +} + +open class Integer(val value: Int) { + open tailrec fun isLessOrEqualThan(value: Int): Boolean { + if (this.value == value) { + return true + } else if (value > 0) { + return this.isLessOrEqualThan(value - 1) + } else { + return false + } + } +} + +open class DefaultArgHolder { + open fun foo(s: String = "default") = s +} + +class DefaultArgGetter : DefaultArgHolder() { + override tailrec fun foo(s: String): String { + return if (s == "default") s else foo() + } +} + +open class EitherDelegatedOrNot(val delegate: EitherDelegatedOrNot?) { + open tailrec fun get42(): Int = if (delegate != null) { + delegate.get42() + } else { + throw Error() + } +} + +class NotDelegated : EitherDelegatedOrNot(null) { + override fun get42() = 42 +} \ No newline at end of file diff --git a/kotlin-native/backend.native/tests/lower/vararg.kt b/kotlin-native/backend.native/tests/lower/vararg.kt new file mode 100644 index 00000000000..946f177bb7f --- /dev/null +++ b/kotlin-native/backend.native/tests/lower/vararg.kt @@ -0,0 +1,15 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +package lower.vararg + +import kotlin.test.* + +fun foo(vararg x: Any?) {} +fun bar() = foo() + +@Test fun runTest() { + bar() +} \ No newline at end of file diff --git a/kotlin-native/backend.native/tests/lower/vararg_of_literals.kt b/kotlin-native/backend.native/tests/lower/vararg_of_literals.kt new file mode 100644 index 00000000000..601c86c9b86 --- /dev/null +++ b/kotlin-native/backend.native/tests/lower/vararg_of_literals.kt @@ -0,0 +1,19 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +package lower.vararg_of_literals + +import kotlin.test.* + +@Test fun runTest() { + foo() + foo() +} + +fun foo() { + val array = arrayOf("a", "b") + println(array[0]) + array[0] = "42" +} \ No newline at end of file diff --git a/kotlin-native/backend.native/tests/mangling/mangling.kt b/kotlin-native/backend.native/tests/mangling/mangling.kt new file mode 100644 index 00000000000..19f2bd19a4f --- /dev/null +++ b/kotlin-native/backend.native/tests/mangling/mangling.kt @@ -0,0 +1,41 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +fun test_direct() { + val mutListInt = mutableListOf(1, 2, 3, 4) + val mutListNum = mutableListOf(9, 10, 11, 12) + val mutListAny = mutableListOf(5, 6, 7, 8) + + mangle1(mutListInt) + mangle1(mutListNum) + mangle1(mutListAny) +} + +fun test_param() { + val mutListInt = mutableListOf(1, 2, 3, 4) + val mutListNum = mutableListOf(9, 10, 11, 12) + val mutListAny = mutableListOf(5, 6, 7, 8) + + mangle2(mutListInt) + mangle2(mutListNum) + mangle2(mutListAny) +} + +fun test_multiple_constructors() { + val any = mapOf() + val comparable = "some string" + val number = 17 + + mangle3(any) + mangle3(comparable) + mangle3(number) +} + +fun main(args: Array) { + test_direct() + test_param() + test_multiple_constructors() +} + diff --git a/kotlin-native/backend.native/tests/mangling/manglinglib.kt b/kotlin-native/backend.native/tests/mangling/manglinglib.kt new file mode 100644 index 00000000000..a431f5a0cef --- /dev/null +++ b/kotlin-native/backend.native/tests/mangling/manglinglib.kt @@ -0,0 +1,52 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +public fun mangle1(l: List) { + println("Int direct $l") +} + +public fun mangle1(l: List) { + println("out Number direct $l") +} + +public fun mangle1(l: List<*>) { + println("star direct $l") +} + +public fun mangle2(l: T) where T: List +{ + println("Int param $l") +} + +public fun mangle2(l: T) where T: List +{ + println("out Number param $l") +} + +public fun mangle2(l: T) where T: List<*> +{ + println("star param $l") +} + +public fun mangle3(l: T) +{ + println("no constructors $l") +} + +public fun mangle3(l: T) + where + T: Comparable +{ + println("single constructor $l") +} + +public fun mangle3(l: T) + where + T: Comparable, + T: Number +{ + println("two constructors $l") +} + diff --git a/kotlin-native/backend.native/tests/objcexport/coroutines.kt b/kotlin-native/backend.native/tests/objcexport/coroutines.kt new file mode 100644 index 00000000000..15f60c76955 --- /dev/null +++ b/kotlin-native/backend.native/tests/objcexport/coroutines.kt @@ -0,0 +1,178 @@ +/* + * Copyright 2010-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +package coroutines + +import kotlin.coroutines.* +import kotlin.coroutines.cancellation.CancellationException +import kotlin.coroutines.intrinsics.* +import kotlin.native.concurrent.isFrozen +import kotlin.native.internal.ObjCErrorException +import kotlin.test.* + +class CoroutineException : Throwable() + +suspend fun suspendFun() = 42 + +@Throws(CoroutineException::class, CancellationException::class) +suspend fun suspendFun(result: Any?, doSuspend: Boolean, doThrow: Boolean): Any? { + if (doSuspend) { + suspendCoroutineUninterceptedOrReturn { + it.resume(Unit) + COROUTINE_SUSPENDED + } + } + + if (doThrow) throw CoroutineException() + + return result +} + +class ContinuationHolder { + internal lateinit var continuation: Continuation + + fun resume(value: T) { + continuation.resume(value) + } + + fun resumeWithException(exception: Throwable) { + continuation.resumeWithException(exception) + } +} + +@Throws(CoroutineException::class, CancellationException::class) +suspend fun suspendFunAsync(result: Any?, continuationHolder: ContinuationHolder): Any? = + suspendCoroutineUninterceptedOrReturn { + continuationHolder.continuation = it + COROUTINE_SUSPENDED + } ?: result + +@Throws(CoroutineException::class, CancellationException::class) +fun throwException(exception: Throwable) { + throw exception +} + +interface SuspendFun { + @Throws(CoroutineException::class, CancellationException::class) + suspend fun suspendFun(doYield: Boolean, doThrow: Boolean): Int +} + +class ResultHolder { + var completed: Int = 0 + var result: T? = null + var exception: Throwable? = null + + internal fun complete(result: Result) { + this.result = result.getOrNull() + this.exception = result.exceptionOrNull() + this.completed += 1 + } +} + +private class ResultHolderCompletion(val resultHolder: ResultHolder) : Continuation { + override val context: CoroutineContext + get() = EmptyCoroutineContext + + override fun resumeWith(result: Result) { + resultHolder.complete(result) + } +} + +fun callSuspendFun(suspendFun: SuspendFun, doYield: Boolean, doThrow: Boolean, resultHolder: ResultHolder) { + suspend { suspendFun.suspendFun(doYield = doYield, doThrow = doThrow) } + .startCoroutine(ResultHolderCompletion(resultHolder)) +} + +@Throws(CoroutineException::class, CancellationException::class) +suspend fun callSuspendFun2(suspendFun: SuspendFun, doYield: Boolean, doThrow: Boolean): Int { + return suspendFun.suspendFun(doYield = doYield, doThrow = doThrow) +} + +interface SuspendBridge { + suspend fun int(value: T): Int + suspend fun intAsAny(value: T): Any? + + suspend fun unit(value: T): Unit + suspend fun unitAsAny(value: T): Any? + + @Throws(Throwable::class) suspend fun nothing(value: T): Nothing + @Throws(Throwable::class) suspend fun nothingAsInt(value: T): Int + @Throws(Throwable::class) suspend fun nothingAsAny(value: T): Any? + @Throws(Throwable::class) suspend fun nothingAsUnit(value: T): Unit +} + +abstract class AbstractSuspendBridge : SuspendBridge { + override suspend fun intAsAny(value: Int): Int = TODO() + + override suspend fun unitAsAny(value: Int): Unit = TODO() + + override suspend fun nothingAsInt(value: Int): Nothing = TODO() + override suspend fun nothingAsAny(value: Int): Nothing = TODO() + override suspend fun nothingAsUnit(value: Int): Nothing = TODO() +} + +private suspend fun callSuspendBridgeImpl(bridge: SuspendBridge) { + assertEquals(1, bridge.intAsAny(1)) + + assertSame(Unit, bridge.unitAsAny(2)) + + assertFailsWith { bridge.nothingAsInt(3) } + assertFailsWith { bridge.nothingAsAny(4) } + assertFailsWith { bridge.nothingAsUnit(5) } +} + +private suspend fun callAbstractSuspendBridgeImpl(bridge: AbstractSuspendBridge) { + assertEquals(6, bridge.intAsAny(6)) + + assertSame(Unit, bridge.unitAsAny(7)) + + assertFailsWith { bridge.nothingAsInt(8) } + assertFailsWith { bridge.nothingAsAny(9) } + assertFailsWith { bridge.nothingAsUnit(10) } +} + +@Throws(Throwable::class) +fun callSuspendBridge(bridge: AbstractSuspendBridge, resultHolder: ResultHolder) { + suspend { + callSuspendBridgeImpl(bridge) + callAbstractSuspendBridgeImpl(bridge) + }.startCoroutine(ResultHolderCompletion(resultHolder)) +} + +suspend fun throwCancellationException(): Unit { + val exception = CancellationException("coroutine is cancelled") + + // Note: frontend checker hardcodes fq names of CancellationException super classes (see NativeThrowsChecker). + // This is our best effort to keep that list in sync with actual stdlib code: + assertTrue(exception is kotlin.Throwable) + assertTrue(exception is kotlin.Exception) + assertTrue(exception is kotlin.RuntimeException) + assertTrue(exception is kotlin.IllegalStateException) + assertTrue(exception is kotlin.coroutines.cancellation.CancellationException) + + throw exception +} + +abstract class ThrowCancellationException { + internal abstract suspend fun throwCancellationException() +} + +class ThrowCancellationExceptionImpl : ThrowCancellationException() { + public override suspend fun throwCancellationException() { + throw CancellationException() + } +} + +fun getSuspendLambda0(): suspend () -> String = { "lambda 0" } + +private suspend fun suspendCallableReference0Target(): String = "callable reference 0" +fun getSuspendCallableReference0(): suspend () -> String = ::suspendCallableReference0Target + +fun getSuspendLambda1(): suspend (String) -> String = { "$it 1" } + +private suspend fun suspendCallableReference1Target(str: String): String = "$str 1" +fun getSuspendCallableReference1(): suspend (String) -> String = ::suspendCallableReference1Target + +suspend fun invoke1(block: suspend (Any?) -> Any?, argument: Any?): Any? = block(argument) diff --git a/kotlin-native/backend.native/tests/objcexport/coroutines.swift b/kotlin-native/backend.native/tests/objcexport/coroutines.swift new file mode 100644 index 00000000000..a3e37913749 --- /dev/null +++ b/kotlin-native/backend.native/tests/objcexport/coroutines.swift @@ -0,0 +1,334 @@ +/* + * Copyright 2010-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +import Kt + +private func testCallSimple() throws { + var result: KotlinInt? = nil + var error: Error? = nil + var completionCalled = 0 + + CoroutinesKt.suspendFun { _result, _error in + completionCalled += 1 + result = _result + error = _error + } + + try assertEquals(actual: completionCalled, expected: 1) + try assertEquals(actual: result, expected: 42) + try assertNil(error) +} + +private func testCallSuspendFun(doSuspend: Bool, doThrow: Bool) throws { + class C {} + let expectedResult = C() + + var completionCalled = 0 + var result: AnyObject? = nil + var error: Error? = nil + + CoroutinesKt.suspendFun(result: expectedResult, doSuspend: doSuspend, doThrow: doThrow) { _result, _error in + completionCalled += 1 + result = _result as AnyObject? + error = _error + } + + try assertEquals(actual: completionCalled, expected: 1) + + if doThrow { + try assertNil(result) + try assertTrue(error?.kotlinException is CoroutineException) + } else { + try assertSame(actual: result, expected: expectedResult) + try assertNil(error) + } +} + +private func testSuspendFuncAsync(doThrow: Bool) throws { + var completionCalled = 0 + var result: AnyObject? = nil + var error: Error? = nil + + let continuationHolder = ContinuationHolder() + + CoroutinesKt.suspendFunAsync(result: nil, continuationHolder: continuationHolder) { _result, _error in + completionCalled += 1 + result = _result as AnyObject? + error = _error + } + + try assertEquals(actual: completionCalled, expected: 0) + + if doThrow { + let exception = CoroutineException() + continuationHolder.resumeWithException(exception: exception) + + try assertEquals(actual: completionCalled, expected: 1) + + try assertNil(result) + try assertSame(actual: error?.kotlinException as AnyObject?, expected: exception) + } else { + class C {} + let expectedResult = C() + continuationHolder.resume(value: expectedResult) + + try assertEquals(actual: completionCalled, expected: 1) + + try assertSame(actual: result, expected: expectedResult) + try assertNil(error) + } +} + +private func testCall() throws { + try testCallSuspendFun(doSuspend: true, doThrow: false) + try testCallSuspendFun(doSuspend: false, doThrow: false) + try testCallSuspendFun(doSuspend: true, doThrow: true) + try testCallSuspendFun(doSuspend: false, doThrow: true) + + try testSuspendFuncAsync(doThrow: false) + try testSuspendFuncAsync(doThrow: true) +} + +private class SuspendFunImpl : SuspendFun { + class E : Error {} + + var completion: (() -> Void)? = nil + + func suspendFun(doYield: Bool, doThrow: Bool, completionHandler: @escaping (KotlinInt?, Error?) -> Void) { + func callCompletion() { + if doThrow { + completionHandler(nil, E()) + } else { + completionHandler(17, nil) + } + } + + if doYield { + self.completion = callCompletion + } else { + callCompletion() + } + } +} + +private func testSuspendFunImpl(doYield: Bool, doThrow: Bool) throws { + let resultHolder = ResultHolder() + + let impl = SuspendFunImpl() + + CoroutinesKt.callSuspendFun( + suspendFun: impl, + doYield: doYield, + doThrow: doThrow, + resultHolder: resultHolder + ) + + if doYield { + try assertEquals(actual: resultHolder.completed, expected: 0) + guard let completion = impl.completion else { try fail() } + completion() + } + + try assertEquals(actual: resultHolder.completed, expected: 1) + + if doThrow { + try assertNil(resultHolder.result) + if let e = resultHolder.exception { + try assertFailsWith(SuspendFunImpl.E.self) { try CoroutinesKt.throwException(exception: e) } + } else { + try fail() + } + } else { + try assertEquals(actual: resultHolder.result, expected: 17) + try assertNil(resultHolder.exception) + } +} + +private func testSuspendFunImpl2(doYield: Bool, doThrow: Bool) throws { + let impl = SuspendFunImpl() + + var completionCalled = 0 + var result: KotlinInt? = nil + var error: Error? = nil + + CoroutinesKt.callSuspendFun2(suspendFun: impl, doYield: doYield, doThrow: doThrow) { _result, _error in + completionCalled += 1 + result = _result + error = _error + } + + if doYield { + try assertEquals(actual: completionCalled, expected: 0) + guard let completion = impl.completion else { try fail() } + completion() + } + + try assertEquals(actual: completionCalled, expected: 1) + + if doThrow { + try assertNil(result) + try assertTrue(error is SuspendFunImpl.E) + } else { + try assertEquals(actual: result, expected: 17) + try assertNil(error) + } +} + +private func testOverride() throws { + try testSuspendFunImpl(doYield: false, doThrow: false) + try testSuspendFunImpl(doYield: false, doThrow: true) + try testSuspendFunImpl(doYield: true, doThrow: false) + try testSuspendFunImpl(doYield: true, doThrow: true) + + try testSuspendFunImpl2(doYield: false, doThrow: false) + try testSuspendFunImpl2(doYield: false, doThrow: true) + try testSuspendFunImpl2(doYield: true, doThrow: false) + try testSuspendFunImpl2(doYield: true, doThrow: true) +} + +private class SwiftSuspendBridge : AbstractSuspendBridge { + class E : Error {} + + override func intAsAny(value: KotlinInt, completionHandler: @escaping (KotlinInt?, Error?) -> Void) { + completionHandler(value, nil) + } + + override func unitAsAny(value: KotlinInt, completionHandler: @escaping (KotlinUnit?, Error?) -> Void) { + completionHandler(KotlinUnit(), nil) + } + + override func nothingAsInt(value: KotlinInt, completionHandler: @escaping (KotlinNothing?, Error?) -> Void) { + completionHandler(nil, E()) + } + + override func nothingAsAny(value: KotlinInt, completionHandler: @escaping (KotlinNothing?, Error?) -> Void) { + completionHandler(nil, E()) + } + + override func nothingAsUnit(value: KotlinInt, completionHandler: @escaping (KotlinNothing?, Error?) -> Void) { + completionHandler(nil, E()) + } +} + +private func testBridges() throws { + let resultHolder = ResultHolder() + try CoroutinesKt.callSuspendBridge(bridge: SwiftSuspendBridge(), resultHolder: resultHolder) + + try assertEquals(actual: resultHolder.completed, expected: 1) + try assertNil(resultHolder.exception) + try assertSame(actual: resultHolder.result, expected: KotlinUnit()) +} + +private func testImplicitThrows1() throws { + var result: KotlinUnit? = nil + var error: Error? = nil + var completionCalled = 0 + + CoroutinesKt.throwCancellationException { _result, _error in + completionCalled += 1 + result = _result + error = _error + } + + try assertEquals(actual: completionCalled, expected: 1) + try assertNil(result) + try assertTrue(error?.kotlinException is KotlinCancellationException) +} + +private func testImplicitThrows2() throws { + var result: KotlinUnit? = nil + var error: Error? = nil + var completionCalled = 0 + + ThrowCancellationExceptionImpl().throwCancellationException { _result, _error in + completionCalled += 1 + result = _result + error = _error + } + + try assertEquals(actual: completionCalled, expected: 1) + try assertNil(result) + try assertTrue(error?.kotlinException is KotlinCancellationException) +} + +private func testSuspendFunctionType0(f: KotlinSuspendFunction0, expectedResult: String) throws { + try assertTrue((f as AnyObject) is KotlinSuspendFunction0) + + var result: String? = nil + var error: Error? = nil + var completionCalled = 0 + + f.invoke { _result, _error in + completionCalled += 1 + result = _result as? String + error = _error + } + + try assertEquals(actual: completionCalled, expected: 1) + try assertEquals(actual: result, expected: expectedResult) + try assertNil(error) +} + +private func testSuspendFunctionType1(f: KotlinSuspendFunction1) throws { + try assertTrue((f as AnyObject) is KotlinSuspendFunction1) + + var result: String? = nil + var error: Error? = nil + var completionCalled = 0 + + f.invoke(p1: "suspend function type") { _result, _error in + completionCalled += 1 + result = _result as? String + error = _error + } + + try assertEquals(actual: completionCalled, expected: 1) + try assertEquals(actual: result, expected: "suspend function type 1") + try assertNil(error) +} + +private func testSuspendFunctionType() throws { + try testSuspendFunctionType0(f: CoroutinesKt.getSuspendLambda0(), expectedResult: "lambda 0") + try testSuspendFunctionType0(f: CoroutinesKt.getSuspendCallableReference0(), expectedResult: "callable reference 0") + try testSuspendFunctionType1(f: CoroutinesKt.getSuspendLambda1()) + try testSuspendFunctionType1(f: CoroutinesKt.getSuspendCallableReference1()) +} + +private func testSuspendFunctionSwiftImpl() throws { + var result: String? = nil + var error: Error? = nil + var completionCalled = 0 + + CoroutinesKt.invoke1(block: SuspendFunction1SwiftImpl(), argument: "suspend function") { _result, _error in + completionCalled += 1 + result = _result as? String + error = _error + } + + try assertEquals(actual: completionCalled, expected: 1) + try assertEquals(actual: result, expected: "suspend function Swift") + try assertNil(error) +} + +private class SuspendFunction1SwiftImpl : KotlinSuspendFunction1 { + func invoke(p1: Any?, completionHandler: (Any?, Error?) -> Void) { + completionHandler("\(p1 ?? "nil") Swift", nil) + } +} + +class CoroutinesTests : SimpleTestProvider { + override init() { + super.init() + + test("TestCallSimple", testCallSimple) + test("TestCall", testCall) + test("TestOverride", testOverride) + test("TestBridges", testBridges) + test("TestImplicitThrows1", testImplicitThrows1) + test("TestImplicitThrows2", testImplicitThrows2) + test("TestSuspendFunctionType", testSuspendFunctionType) + test("TestSuspendFunctionSwiftImpl", testSuspendFunctionSwiftImpl) + } +} \ No newline at end of file diff --git a/kotlin-native/backend.native/tests/objcexport/deallocRetain.kt b/kotlin-native/backend.native/tests/objcexport/deallocRetain.kt new file mode 100644 index 00000000000..540e3776b62 --- /dev/null +++ b/kotlin-native/backend.native/tests/objcexport/deallocRetain.kt @@ -0,0 +1,12 @@ +/* + * Copyright 2010-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +package deallocretain + +open class DeallocRetainBase + +fun garbageCollect() = kotlin.native.internal.GC.collect() + +fun createWeakReference(value: Any) = kotlin.native.ref.WeakReference(value) diff --git a/kotlin-native/backend.native/tests/objcexport/deallocRetain.swift b/kotlin-native/backend.native/tests/objcexport/deallocRetain.swift new file mode 100644 index 00000000000..3677337b667 --- /dev/null +++ b/kotlin-native/backend.native/tests/objcexport/deallocRetain.swift @@ -0,0 +1,67 @@ +/* + * Copyright 2010-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +import Kt + +// Note: these tests rely on GC assertions: without the fix and the assertions it won't actually crash. +// GC should fire an assertion if it obtains a reference to Kotlin object that is being (or has been) deallocated. + +private func test1() throws { + // Attempt to make the state predictable: + DeallocRetainKt.garbageCollect() + + DeallocRetain.deallocated = false + try assertFalse(DeallocRetain.deallocated) + + try autoreleasepool { + let obj = DeallocRetain() + try obj.checkWeak() + } + + // Runs DeallocRetain.deinit: + DeallocRetainKt.garbageCollect() + + try assertTrue(DeallocRetain.deallocated) + + // Might crash due to double-dispose if the dealloc applied addRef/releaseRef to reclaimed Kotlin object: + DeallocRetainKt.garbageCollect() +} + +private class DeallocRetain : DeallocRetainBase { + static var deallocated = false + static var retainObject: DeallocRetain? = nil + static weak var weakObject: DeallocRetain? = nil + static var kotlinWeakRef: KotlinWeakReference? = nil + + override init() { + super.init() + DeallocRetain.weakObject = self + DeallocRetain.kotlinWeakRef = DeallocRetainKt.createWeakReference(value: self) + } + + func checkWeak() throws { + try assertSame(actual: DeallocRetain.weakObject, expected: self) + try assertSame(actual: DeallocRetain.kotlinWeakRef!.value, expected: self) + } + + deinit { + DeallocRetain.retainObject = self + DeallocRetain.retainObject = nil + + try! assertNil(DeallocRetain.weakObject) + try! assertNil(DeallocRetain.kotlinWeakRef!.value) + + try! assertFalse(DeallocRetain.deallocated) + DeallocRetain.deallocated = true + } +} + +class DeallocRetainTests : SimpleTestProvider { + override init() { + super.init() + + test("Test1", test1) + } +} diff --git a/kotlin-native/backend.native/tests/objcexport/expectedLazy.h b/kotlin-native/backend.native/tests/objcexport/expectedLazy.h new file mode 100644 index 00000000000..c96ee87923e --- /dev/null +++ b/kotlin-native/backend.native/tests/objcexport/expectedLazy.h @@ -0,0 +1,2056 @@ +__attribute__((swift_name("KotlinBase"))) +@interface KtBase : NSObject +- (instancetype)init __attribute__((unavailable)); ++ (instancetype)new __attribute__((unavailable)); ++ (void)initialize __attribute__((objc_requires_super)); +@end; + +@interface KtBase (KtBaseCopying) +@end; + +__attribute__((swift_name("KotlinMutableSet"))) +@interface KtMutableSet : NSMutableSet +@end; + +__attribute__((swift_name("KotlinMutableDictionary"))) +@interface KtMutableDictionary : NSMutableDictionary +@end; + +@interface NSError (NSErrorKtKotlinException) +@property (readonly) id _Nullable kotlinException; +@end; + +__attribute__((swift_name("KotlinNumber"))) +@interface KtNumber : NSNumber +- (instancetype)initWithChar:(char)value __attribute__((unavailable)); +- (instancetype)initWithUnsignedChar:(unsigned char)value __attribute__((unavailable)); +- (instancetype)initWithShort:(short)value __attribute__((unavailable)); +- (instancetype)initWithUnsignedShort:(unsigned short)value __attribute__((unavailable)); +- (instancetype)initWithInt:(int)value __attribute__((unavailable)); +- (instancetype)initWithUnsignedInt:(unsigned int)value __attribute__((unavailable)); +- (instancetype)initWithLong:(long)value __attribute__((unavailable)); +- (instancetype)initWithUnsignedLong:(unsigned long)value __attribute__((unavailable)); +- (instancetype)initWithLongLong:(long long)value __attribute__((unavailable)); +- (instancetype)initWithUnsignedLongLong:(unsigned long long)value __attribute__((unavailable)); +- (instancetype)initWithFloat:(float)value __attribute__((unavailable)); +- (instancetype)initWithDouble:(double)value __attribute__((unavailable)); +- (instancetype)initWithBool:(BOOL)value __attribute__((unavailable)); +- (instancetype)initWithInteger:(NSInteger)value __attribute__((unavailable)); +- (instancetype)initWithUnsignedInteger:(NSUInteger)value __attribute__((unavailable)); ++ (instancetype)numberWithChar:(char)value __attribute__((unavailable)); ++ (instancetype)numberWithUnsignedChar:(unsigned char)value __attribute__((unavailable)); ++ (instancetype)numberWithShort:(short)value __attribute__((unavailable)); ++ (instancetype)numberWithUnsignedShort:(unsigned short)value __attribute__((unavailable)); ++ (instancetype)numberWithInt:(int)value __attribute__((unavailable)); ++ (instancetype)numberWithUnsignedInt:(unsigned int)value __attribute__((unavailable)); ++ (instancetype)numberWithLong:(long)value __attribute__((unavailable)); ++ (instancetype)numberWithUnsignedLong:(unsigned long)value __attribute__((unavailable)); ++ (instancetype)numberWithLongLong:(long long)value __attribute__((unavailable)); ++ (instancetype)numberWithUnsignedLongLong:(unsigned long long)value __attribute__((unavailable)); ++ (instancetype)numberWithFloat:(float)value __attribute__((unavailable)); ++ (instancetype)numberWithDouble:(double)value __attribute__((unavailable)); ++ (instancetype)numberWithBool:(BOOL)value __attribute__((unavailable)); ++ (instancetype)numberWithInteger:(NSInteger)value __attribute__((unavailable)); ++ (instancetype)numberWithUnsignedInteger:(NSUInteger)value __attribute__((unavailable)); +@end; + +__attribute__((swift_name("KotlinByte"))) +@interface KtByte : KtNumber +- (instancetype)initWithChar:(char)value; ++ (instancetype)numberWithChar:(char)value; +@end; + +__attribute__((swift_name("KotlinUByte"))) +@interface KtUByte : KtNumber +- (instancetype)initWithUnsignedChar:(unsigned char)value; ++ (instancetype)numberWithUnsignedChar:(unsigned char)value; +@end; + +__attribute__((swift_name("KotlinShort"))) +@interface KtShort : KtNumber +- (instancetype)initWithShort:(short)value; ++ (instancetype)numberWithShort:(short)value; +@end; + +__attribute__((swift_name("KotlinUShort"))) +@interface KtUShort : KtNumber +- (instancetype)initWithUnsignedShort:(unsigned short)value; ++ (instancetype)numberWithUnsignedShort:(unsigned short)value; +@end; + +__attribute__((swift_name("KotlinInt"))) +@interface KtInt : KtNumber +- (instancetype)initWithInt:(int)value; ++ (instancetype)numberWithInt:(int)value; +@end; + +__attribute__((swift_name("KotlinUInt"))) +@interface KtUInt : KtNumber +- (instancetype)initWithUnsignedInt:(unsigned int)value; ++ (instancetype)numberWithUnsignedInt:(unsigned int)value; +@end; + +__attribute__((swift_name("KotlinLong"))) +@interface KtLong : KtNumber +- (instancetype)initWithLongLong:(long long)value; ++ (instancetype)numberWithLongLong:(long long)value; +@end; + +__attribute__((swift_name("KotlinULong"))) +@interface KtULong : KtNumber +- (instancetype)initWithUnsignedLongLong:(unsigned long long)value; ++ (instancetype)numberWithUnsignedLongLong:(unsigned long long)value; +@end; + +__attribute__((swift_name("KotlinFloat"))) +@interface KtFloat : KtNumber +- (instancetype)initWithFloat:(float)value; ++ (instancetype)numberWithFloat:(float)value; +@end; + +__attribute__((swift_name("KotlinDouble"))) +@interface KtDouble : KtNumber +- (instancetype)initWithDouble:(double)value; ++ (instancetype)numberWithDouble:(double)value; +@end; + +__attribute__((swift_name("KotlinBoolean"))) +@interface KtBoolean : KtNumber +- (instancetype)initWithBool:(BOOL)value; ++ (instancetype)numberWithBool:(BOOL)value; +@end; + +__attribute__((objc_subclassing_restricted)) +__attribute__((swift_name("CoroutineException"))) +@interface KtCoroutineException : KtKotlinThrowable +- (instancetype)init __attribute__((swift_name("init()"))) __attribute__((objc_designated_initializer)); ++ (instancetype)new __attribute__((availability(swift, unavailable, message="use object initializers instead"))); +- (instancetype)initWithMessage:(NSString * _Nullable)message __attribute__((swift_name("init(message:)"))) __attribute__((objc_designated_initializer)) __attribute__((unavailable)); +- (instancetype)initWithCause:(KtKotlinThrowable * _Nullable)cause __attribute__((swift_name("init(cause:)"))) __attribute__((objc_designated_initializer)) __attribute__((unavailable)); +- (instancetype)initWithMessage:(NSString * _Nullable)message cause:(KtKotlinThrowable * _Nullable)cause __attribute__((swift_name("init(message:cause:)"))) __attribute__((objc_designated_initializer)) __attribute__((unavailable)); +@end; + +__attribute__((objc_subclassing_restricted)) +__attribute__((swift_name("ContinuationHolder"))) +@interface KtContinuationHolder : KtBase +- (instancetype)init __attribute__((swift_name("init()"))) __attribute__((objc_designated_initializer)); ++ (instancetype)new __attribute__((availability(swift, unavailable, message="use object initializers instead"))); +- (void)resumeValue:(T _Nullable)value __attribute__((swift_name("resume(value:)"))); +- (void)resumeWithExceptionException:(KtKotlinThrowable *)exception __attribute__((swift_name("resumeWithException(exception:)"))); +@end; + +__attribute__((swift_name("SuspendFun"))) +@protocol KtSuspendFun +@required + +/** + @note This method converts instances of CoroutineException, CancellationException to errors. + Other uncaught Kotlin exceptions are fatal. +*/ +- (void)suspendFunDoYield:(BOOL)doYield doThrow:(BOOL)doThrow completionHandler:(void (^)(KtInt * _Nullable, NSError * _Nullable))completionHandler __attribute__((swift_name("suspendFun(doYield:doThrow:completionHandler:)"))); +@end; + +__attribute__((objc_subclassing_restricted)) +__attribute__((swift_name("ResultHolder"))) +@interface KtResultHolder : KtBase +- (instancetype)init __attribute__((swift_name("init()"))) __attribute__((objc_designated_initializer)); ++ (instancetype)new __attribute__((availability(swift, unavailable, message="use object initializers instead"))); +@property int32_t completed __attribute__((swift_name("completed"))); +@property T _Nullable result __attribute__((swift_name("result"))); +@property KtKotlinThrowable * _Nullable exception __attribute__((swift_name("exception"))); +@end; + +__attribute__((swift_name("SuspendBridge"))) +@protocol KtSuspendBridge +@required + +/** + @note This method converts instances of CancellationException to errors. + Other uncaught Kotlin exceptions are fatal. +*/ +- (void)intValue:(id _Nullable)value completionHandler:(void (^)(KtInt * _Nullable, NSError * _Nullable))completionHandler __attribute__((swift_name("int(value:completionHandler:)"))); + +/** + @note This method converts instances of CancellationException to errors. + Other uncaught Kotlin exceptions are fatal. +*/ +- (void)intAsAnyValue:(id _Nullable)value completionHandler:(void (^)(id _Nullable, NSError * _Nullable))completionHandler __attribute__((swift_name("intAsAny(value:completionHandler:)"))); + +/** + @note This method converts instances of CancellationException to errors. + Other uncaught Kotlin exceptions are fatal. +*/ +- (void)unitValue:(id _Nullable)value completionHandler:(void (^)(KtKotlinUnit * _Nullable, NSError * _Nullable))completionHandler __attribute__((swift_name("unit(value:completionHandler:)"))); + +/** + @note This method converts instances of CancellationException to errors. + Other uncaught Kotlin exceptions are fatal. +*/ +- (void)unitAsAnyValue:(id _Nullable)value completionHandler:(void (^)(id _Nullable, NSError * _Nullable))completionHandler __attribute__((swift_name("unitAsAny(value:completionHandler:)"))); + +/** + @note This method converts all Kotlin exceptions to errors. +*/ +- (void)nothingValue:(id _Nullable)value completionHandler:(void (^)(KtKotlinNothing * _Nullable, NSError * _Nullable))completionHandler __attribute__((swift_name("nothing(value:completionHandler:)"))); + +/** + @note This method converts all Kotlin exceptions to errors. +*/ +- (void)nothingAsIntValue:(id _Nullable)value completionHandler:(void (^)(KtInt * _Nullable, NSError * _Nullable))completionHandler __attribute__((swift_name("nothingAsInt(value:completionHandler:)"))); + +/** + @note This method converts all Kotlin exceptions to errors. +*/ +- (void)nothingAsAnyValue:(id _Nullable)value completionHandler:(void (^)(id _Nullable, NSError * _Nullable))completionHandler __attribute__((swift_name("nothingAsAny(value:completionHandler:)"))); + +/** + @note This method converts all Kotlin exceptions to errors. +*/ +- (void)nothingAsUnitValue:(id _Nullable)value completionHandler:(void (^)(KtKotlinUnit * _Nullable, NSError * _Nullable))completionHandler __attribute__((swift_name("nothingAsUnit(value:completionHandler:)"))); +@end; + +__attribute__((swift_name("AbstractSuspendBridge"))) +@interface KtAbstractSuspendBridge : KtBase +- (instancetype)init __attribute__((swift_name("init()"))) __attribute__((objc_designated_initializer)); ++ (instancetype)new __attribute__((availability(swift, unavailable, message="use object initializers instead"))); + +/** + @note This method converts instances of CancellationException to errors. + Other uncaught Kotlin exceptions are fatal. +*/ +- (void)intAsAnyValue:(KtInt *)value completionHandler:(void (^)(KtInt * _Nullable, NSError * _Nullable))completionHandler __attribute__((swift_name("intAsAny(value:completionHandler:)"))); + +/** + @note This method converts instances of CancellationException to errors. + Other uncaught Kotlin exceptions are fatal. +*/ +- (void)unitAsAnyValue:(KtInt *)value completionHandler:(void (^)(KtKotlinUnit * _Nullable, NSError * _Nullable))completionHandler __attribute__((swift_name("unitAsAny(value:completionHandler:)"))); + +/** + @note This method converts all Kotlin exceptions to errors. +*/ +- (void)nothingAsIntValue:(KtInt *)value completionHandler:(void (^)(KtKotlinNothing * _Nullable, NSError * _Nullable))completionHandler __attribute__((swift_name("nothingAsInt(value:completionHandler:)"))); + +/** + @note This method converts all Kotlin exceptions to errors. +*/ +- (void)nothingAsAnyValue:(KtInt *)value completionHandler:(void (^)(KtKotlinNothing * _Nullable, NSError * _Nullable))completionHandler __attribute__((swift_name("nothingAsAny(value:completionHandler:)"))); + +/** + @note This method converts all Kotlin exceptions to errors. +*/ +- (void)nothingAsUnitValue:(KtInt *)value completionHandler:(void (^)(KtKotlinNothing * _Nullable, NSError * _Nullable))completionHandler __attribute__((swift_name("nothingAsUnit(value:completionHandler:)"))); +@end; + +__attribute__((swift_name("ThrowCancellationException"))) +@interface KtThrowCancellationException : KtBase +- (instancetype)init __attribute__((swift_name("init()"))) __attribute__((objc_designated_initializer)); ++ (instancetype)new __attribute__((availability(swift, unavailable, message="use object initializers instead"))); +@end; + +__attribute__((objc_subclassing_restricted)) +__attribute__((swift_name("ThrowCancellationExceptionImpl"))) +@interface KtThrowCancellationExceptionImpl : KtThrowCancellationException +- (instancetype)init __attribute__((swift_name("init()"))) __attribute__((objc_designated_initializer)); ++ (instancetype)new __attribute__((availability(swift, unavailable, message="use object initializers instead"))); + +/** + @note This method converts instances of CancellationException to errors. + Other uncaught Kotlin exceptions are fatal. +*/ +- (void)throwCancellationExceptionWithCompletionHandler:(void (^)(KtKotlinUnit * _Nullable, NSError * _Nullable))completionHandler __attribute__((swift_name("throwCancellationException(completionHandler:)"))); +@end; + +__attribute__((objc_subclassing_restricted)) +__attribute__((swift_name("CoroutinesKt"))) +@interface KtCoroutinesKt : KtBase + +/** + @note This method converts instances of CancellationException to errors. + Other uncaught Kotlin exceptions are fatal. +*/ ++ (void)suspendFunWithCompletionHandler:(void (^)(KtInt * _Nullable, NSError * _Nullable))completionHandler __attribute__((swift_name("suspendFun(completionHandler:)"))); + +/** + @note This method converts instances of CoroutineException, CancellationException to errors. + Other uncaught Kotlin exceptions are fatal. +*/ ++ (void)suspendFunResult:(id _Nullable)result doSuspend:(BOOL)doSuspend doThrow:(BOOL)doThrow completionHandler:(void (^)(id _Nullable, NSError * _Nullable))completionHandler __attribute__((swift_name("suspendFun(result:doSuspend:doThrow:completionHandler:)"))); + +/** + @note This method converts instances of CoroutineException, CancellationException to errors. + Other uncaught Kotlin exceptions are fatal. +*/ ++ (void)suspendFunAsyncResult:(id _Nullable)result continuationHolder:(KtContinuationHolder *)continuationHolder completionHandler:(void (^)(id _Nullable, NSError * _Nullable))completionHandler __attribute__((swift_name("suspendFunAsync(result:continuationHolder:completionHandler:)"))); + +/** + @note This method converts instances of CoroutineException, CancellationException to errors. + Other uncaught Kotlin exceptions are fatal. +*/ ++ (BOOL)throwExceptionException:(KtKotlinThrowable *)exception error:(NSError * _Nullable * _Nullable)error __attribute__((swift_name("throwException(exception:)"))); ++ (void)callSuspendFunSuspendFun:(id)suspendFun doYield:(BOOL)doYield doThrow:(BOOL)doThrow resultHolder:(KtResultHolder *)resultHolder __attribute__((swift_name("callSuspendFun(suspendFun:doYield:doThrow:resultHolder:)"))); + +/** + @note This method converts instances of CoroutineException, CancellationException to errors. + Other uncaught Kotlin exceptions are fatal. +*/ ++ (void)callSuspendFun2SuspendFun:(id)suspendFun doYield:(BOOL)doYield doThrow:(BOOL)doThrow completionHandler:(void (^)(KtInt * _Nullable, NSError * _Nullable))completionHandler __attribute__((swift_name("callSuspendFun2(suspendFun:doYield:doThrow:completionHandler:)"))); + +/** + @note This method converts all Kotlin exceptions to errors. +*/ ++ (BOOL)callSuspendBridgeBridge:(KtAbstractSuspendBridge *)bridge resultHolder:(KtResultHolder *)resultHolder error:(NSError * _Nullable * _Nullable)error __attribute__((swift_name("callSuspendBridge(bridge:resultHolder:)"))); + +/** + @note This method converts instances of CancellationException to errors. + Other uncaught Kotlin exceptions are fatal. +*/ ++ (void)throwCancellationExceptionWithCompletionHandler:(void (^)(KtKotlinUnit * _Nullable, NSError * _Nullable))completionHandler __attribute__((swift_name("throwCancellationException(completionHandler:)"))); ++ (id)getSuspendLambda0 __attribute__((swift_name("getSuspendLambda0()"))); ++ (id)getSuspendCallableReference0 __attribute__((swift_name("getSuspendCallableReference0()"))); ++ (id)getSuspendLambda1 __attribute__((swift_name("getSuspendLambda1()"))); ++ (id)getSuspendCallableReference1 __attribute__((swift_name("getSuspendCallableReference1()"))); + +/** + @note This method converts instances of CancellationException to errors. + Other uncaught Kotlin exceptions are fatal. +*/ ++ (void)invoke1Block:(id)block argument:(id _Nullable)argument completionHandler:(void (^)(id _Nullable, NSError * _Nullable))completionHandler __attribute__((swift_name("invoke1(block:argument:completionHandler:)"))); +@end; + +__attribute__((swift_name("DeallocRetainBase"))) +@interface KtDeallocRetainBase : KtBase +- (instancetype)init __attribute__((swift_name("init()"))) __attribute__((objc_designated_initializer)); ++ (instancetype)new __attribute__((availability(swift, unavailable, message="use object initializers instead"))); +@end; + +__attribute__((objc_subclassing_restricted)) +__attribute__((swift_name("DeallocRetainKt"))) +@interface KtDeallocRetainKt : KtBase ++ (void)garbageCollect __attribute__((swift_name("garbageCollect()"))); ++ (KtKotlinWeakReference *)createWeakReferenceValue:(id)value __attribute__((swift_name("createWeakReference(value:)"))); +@end; + +__attribute__((swift_name("FHolder"))) +@interface KtFHolder : KtBase +- (instancetype)init __attribute__((swift_name("init()"))) __attribute__((objc_designated_initializer)); ++ (instancetype)new __attribute__((availability(swift, unavailable, message="use object initializers instead"))); +@property (readonly) id _Nullable value __attribute__((swift_name("value"))); +@end; + +__attribute__((objc_subclassing_restricted)) +__attribute__((swift_name("F2Holder"))) +@interface KtF2Holder : KtFHolder +- (instancetype)initWithValue:(id _Nullable (^)(id _Nullable, id _Nullable))value __attribute__((swift_name("init(value:)"))) __attribute__((objc_designated_initializer)); +- (instancetype)init __attribute__((swift_name("init()"))) __attribute__((objc_designated_initializer)) __attribute__((unavailable)); ++ (instancetype)new __attribute__((unavailable)); +@property (readonly) id _Nullable (^value)(id _Nullable, id _Nullable) __attribute__((swift_name("value"))); +@end; + +__attribute__((objc_subclassing_restricted)) +__attribute__((swift_name("F32Holder"))) +@interface KtF32Holder : KtFHolder +- (instancetype)initWithValue:(id _Nullable (^)(id _Nullable, id _Nullable, id _Nullable, id _Nullable, id _Nullable, id _Nullable, id _Nullable, id _Nullable, id _Nullable, id _Nullable, id _Nullable, id _Nullable, id _Nullable, id _Nullable, id _Nullable, id _Nullable, id _Nullable, id _Nullable, id _Nullable, id _Nullable, id _Nullable, id _Nullable, id _Nullable, id _Nullable, id _Nullable, id _Nullable, id _Nullable, id _Nullable, id _Nullable, id _Nullable, id _Nullable, id _Nullable))value __attribute__((swift_name("init(value:)"))) __attribute__((objc_designated_initializer)); +- (instancetype)init __attribute__((swift_name("init()"))) __attribute__((objc_designated_initializer)) __attribute__((unavailable)); ++ (instancetype)new __attribute__((unavailable)); +@property (readonly) id _Nullable (^value)(id _Nullable, id _Nullable, id _Nullable, id _Nullable, id _Nullable, id _Nullable, id _Nullable, id _Nullable, id _Nullable, id _Nullable, id _Nullable, id _Nullable, id _Nullable, id _Nullable, id _Nullable, id _Nullable, id _Nullable, id _Nullable, id _Nullable, id _Nullable, id _Nullable, id _Nullable, id _Nullable, id _Nullable, id _Nullable, id _Nullable, id _Nullable, id _Nullable, id _Nullable, id _Nullable, id _Nullable, id _Nullable) __attribute__((swift_name("value"))); +@end; + +__attribute__((objc_subclassing_restricted)) +__attribute__((swift_name("F33Holder"))) +@interface KtF33Holder : KtFHolder +- (instancetype)initWithValue:(id _Nullable (^)(id _Nullable, id _Nullable, id _Nullable, id _Nullable, id _Nullable, id _Nullable, id _Nullable, id _Nullable, id _Nullable, id _Nullable, id _Nullable, id _Nullable, id _Nullable, id _Nullable, id _Nullable, id _Nullable, id _Nullable, id _Nullable, id _Nullable, id _Nullable, id _Nullable, id _Nullable, id _Nullable, id _Nullable, id _Nullable, id _Nullable, id _Nullable, id _Nullable, id _Nullable, id _Nullable, id _Nullable, id _Nullable, id _Nullable))value __attribute__((swift_name("init(value:)"))) __attribute__((objc_designated_initializer)); +- (instancetype)init __attribute__((swift_name("init()"))) __attribute__((objc_designated_initializer)) __attribute__((unavailable)); ++ (instancetype)new __attribute__((unavailable)); +@property (readonly) id value __attribute__((swift_name("value"))); +@end; + +__attribute__((objc_subclassing_restricted)) +__attribute__((swift_name("FunctionalTypesKt"))) +@interface KtFunctionalTypesKt : KtBase ++ (void)callDynType2List:(NSArray *)list param:(id _Nullable)param __attribute__((swift_name("callDynType2(list:param:)"))); ++ (void)callStaticType2Fct:(id _Nullable (^)(id _Nullable, id _Nullable))fct param:(id _Nullable)param __attribute__((swift_name("callStaticType2(fct:param:)"))); ++ (void)callDynType32List:(NSArray *)list param:(id _Nullable)param __attribute__((swift_name("callDynType32(list:param:)"))); ++ (void)callStaticType32Fct:(id _Nullable (^)(id _Nullable, id _Nullable, id _Nullable, id _Nullable, id _Nullable, id _Nullable, id _Nullable, id _Nullable, id _Nullable, id _Nullable, id _Nullable, id _Nullable, id _Nullable, id _Nullable, id _Nullable, id _Nullable, id _Nullable, id _Nullable, id _Nullable, id _Nullable, id _Nullable, id _Nullable, id _Nullable, id _Nullable, id _Nullable, id _Nullable, id _Nullable, id _Nullable, id _Nullable, id _Nullable, id _Nullable, id _Nullable))fct param:(id _Nullable)param __attribute__((swift_name("callStaticType32(fct:param:)"))); ++ (void)callDynType33List:(NSArray> *)list param:(id _Nullable)param __attribute__((swift_name("callDynType33(list:param:)"))); ++ (void)callStaticType33Fct:(id _Nullable (^)(id _Nullable, id _Nullable, id _Nullable, id _Nullable, id _Nullable, id _Nullable, id _Nullable, id _Nullable, id _Nullable, id _Nullable, id _Nullable, id _Nullable, id _Nullable, id _Nullable, id _Nullable, id _Nullable, id _Nullable, id _Nullable, id _Nullable, id _Nullable, id _Nullable, id _Nullable, id _Nullable, id _Nullable, id _Nullable, id _Nullable, id _Nullable, id _Nullable, id _Nullable, id _Nullable, id _Nullable, id _Nullable, id _Nullable))fct param:(id _Nullable)param __attribute__((swift_name("callStaticType33(fct:param:)"))); ++ (KtF2Holder *)getDynTypeLambda2 __attribute__((swift_name("getDynTypeLambda2()"))); ++ (id _Nullable (^)(id _Nullable, id _Nullable))getStaticLambda2 __attribute__((swift_name("getStaticLambda2()"))); ++ (KtF2Holder *)getDynTypeRef2 __attribute__((swift_name("getDynTypeRef2()"))); ++ (id _Nullable (^)(id _Nullable, id _Nullable))getStaticRef2 __attribute__((swift_name("getStaticRef2()"))); ++ (KtF32Holder *)getDynType32 __attribute__((swift_name("getDynType32()"))); ++ (id _Nullable (^)(id _Nullable, id _Nullable, id _Nullable, id _Nullable, id _Nullable, id _Nullable, id _Nullable, id _Nullable, id _Nullable, id _Nullable, id _Nullable, id _Nullable, id _Nullable, id _Nullable, id _Nullable, id _Nullable, id _Nullable, id _Nullable, id _Nullable, id _Nullable, id _Nullable, id _Nullable, id _Nullable, id _Nullable, id _Nullable, id _Nullable, id _Nullable, id _Nullable, id _Nullable, id _Nullable, id _Nullable, id _Nullable))getStaticType32 __attribute__((swift_name("getStaticType32()"))); ++ (KtF33Holder *)getDynTypeRef33 __attribute__((swift_name("getDynTypeRef33()"))); ++ (id _Nullable (^)(id _Nullable, id _Nullable, id _Nullable, id _Nullable, id _Nullable, id _Nullable, id _Nullable, id _Nullable, id _Nullable, id _Nullable, id _Nullable, id _Nullable, id _Nullable, id _Nullable, id _Nullable, id _Nullable, id _Nullable, id _Nullable, id _Nullable, id _Nullable, id _Nullable, id _Nullable, id _Nullable, id _Nullable, id _Nullable, id _Nullable, id _Nullable, id _Nullable, id _Nullable, id _Nullable, id _Nullable, id _Nullable, id _Nullable))getStaticTypeRef33 __attribute__((swift_name("getStaticTypeRef33()"))); ++ (KtF33Holder *)getDynTypeLambda33 __attribute__((swift_name("getDynTypeLambda33()"))); ++ (id _Nullable (^)(id _Nullable, id _Nullable, id _Nullable, id _Nullable, id _Nullable, id _Nullable, id _Nullable, id _Nullable, id _Nullable, id _Nullable, id _Nullable, id _Nullable, id _Nullable, id _Nullable, id _Nullable, id _Nullable, id _Nullable, id _Nullable, id _Nullable, id _Nullable, id _Nullable, id _Nullable, id _Nullable, id _Nullable, id _Nullable, id _Nullable, id _Nullable, id _Nullable, id _Nullable, id _Nullable, id _Nullable, id _Nullable, id _Nullable))getStaticTypeLambda33 __attribute__((swift_name("getStaticTypeLambda33()"))); +@end; + +__attribute__((swift_name("GH4002ArgumentBase"))) +@interface KtGH4002ArgumentBase : KtBase +- (instancetype)init __attribute__((swift_name("init()"))) __attribute__((objc_designated_initializer)); ++ (instancetype)new __attribute__((availability(swift, unavailable, message="use object initializers instead"))); +@end; + +__attribute__((objc_subclassing_restricted)) +__attribute__((swift_name("GH4002Argument"))) +@interface KtGH4002Argument : KtGH4002ArgumentBase +- (instancetype)init __attribute__((swift_name("init()"))) __attribute__((objc_designated_initializer)); ++ (instancetype)new __attribute__((availability(swift, unavailable, message="use object initializers instead"))); +@end; + +__attribute__((objc_subclassing_restricted)) +__attribute__((swift_name("TestIncompatiblePropertyTypeWarning"))) +@interface KtTestIncompatiblePropertyTypeWarning : KtBase +- (instancetype)init __attribute__((swift_name("init()"))) __attribute__((objc_designated_initializer)); ++ (instancetype)new __attribute__((availability(swift, unavailable, message="use object initializers instead"))); +@end; + +__attribute__((objc_subclassing_restricted)) +__attribute__((swift_name("TestIncompatiblePropertyTypeWarningGeneric"))) +@interface KtTestIncompatiblePropertyTypeWarningGeneric : KtBase +- (instancetype)initWithValue:(T _Nullable)value __attribute__((swift_name("init(value:)"))) __attribute__((objc_designated_initializer)); +@property (readonly) T _Nullable value __attribute__((swift_name("value"))); +@end; + +__attribute__((swift_name("TestIncompatiblePropertyTypeWarningInterfaceWithGenericProperty"))) +@protocol KtTestIncompatiblePropertyTypeWarningInterfaceWithGenericProperty +@required +@property (readonly) KtTestIncompatiblePropertyTypeWarningGeneric *p __attribute__((swift_name("p"))); +@end; + +__attribute__((objc_subclassing_restricted)) +__attribute__((swift_name("TestIncompatiblePropertyTypeWarning.ClassOverridingInterfaceWithGenericProperty"))) +@interface KtTestIncompatiblePropertyTypeWarningClassOverridingInterfaceWithGenericProperty : KtBase +- (instancetype)initWithP:(KtTestIncompatiblePropertyTypeWarningGeneric *)p __attribute__((swift_name("init(p:)"))) __attribute__((objc_designated_initializer)); +@property (readonly) KtTestIncompatiblePropertyTypeWarningGeneric *p __attribute__((swift_name("p"))); +@end; + +__attribute__((objc_subclassing_restricted)) +__attribute__((swift_name("TestGH3992"))) +@interface KtTestGH3992 : KtBase +- (instancetype)init __attribute__((swift_name("init()"))) __attribute__((objc_designated_initializer)); ++ (instancetype)new __attribute__((availability(swift, unavailable, message="use object initializers instead"))); +@end; + +__attribute__((swift_name("TestGH3992.C"))) +@interface KtTestGH3992C : KtBase +- (instancetype)initWithA:(KtTestGH3992A *)a __attribute__((swift_name("init(a:)"))) __attribute__((objc_designated_initializer)); +@property (readonly) KtTestGH3992A *a __attribute__((swift_name("a"))); +@end; + +__attribute__((objc_subclassing_restricted)) +__attribute__((swift_name("TestGH3992.D"))) +@interface KtTestGH3992D : KtTestGH3992C +- (instancetype)initWithA:(KtTestGH3992B *)a __attribute__((swift_name("init(a:)"))) __attribute__((objc_designated_initializer)); +@property (readonly) KtTestGH3992B *a __attribute__((swift_name("a"))); +@end; + +__attribute__((swift_name("TestGH3992.A"))) +@interface KtTestGH3992A : KtBase +- (instancetype)init __attribute__((swift_name("init()"))) __attribute__((objc_designated_initializer)); ++ (instancetype)new __attribute__((availability(swift, unavailable, message="use object initializers instead"))); +@end; + +__attribute__((objc_subclassing_restricted)) +__attribute__((swift_name("TestGH3992.B"))) +@interface KtTestGH3992B : KtTestGH3992A +- (instancetype)init __attribute__((swift_name("init()"))) __attribute__((objc_designated_initializer)); ++ (instancetype)new __attribute__((availability(swift, unavailable, message="use object initializers instead"))); +@end; + +__attribute__((objc_subclassing_restricted)) +__attribute__((swift_name("Kt35940Kt"))) +@interface KtKt35940Kt : KtBase ++ (NSString *)testKt35940 __attribute__((swift_name("testKt35940()"))); +@end; + +__attribute__((objc_subclassing_restricted)) +__attribute__((swift_name("KT38641"))) +@interface KtKT38641 : KtBase +- (instancetype)init __attribute__((swift_name("init()"))) __attribute__((objc_designated_initializer)); ++ (instancetype)new __attribute__((availability(swift, unavailable, message="use object initializers instead"))); +@end; + +__attribute__((objc_subclassing_restricted)) +__attribute__((swift_name("KT38641.IntType"))) +@interface KtKT38641IntType : KtBase +- (instancetype)init __attribute__((swift_name("init()"))) __attribute__((objc_designated_initializer)); ++ (instancetype)new __attribute__((availability(swift, unavailable, message="use object initializers instead"))); +@property (getter=description, setter=setDescription:) int32_t description_ __attribute__((swift_name("description_"))); +@end; + +__attribute__((objc_subclassing_restricted)) +__attribute__((swift_name("KT38641.Val"))) +@interface KtKT38641Val : KtBase +- (instancetype)init __attribute__((swift_name("init()"))) __attribute__((objc_designated_initializer)); ++ (instancetype)new __attribute__((availability(swift, unavailable, message="use object initializers instead"))); +@property (readonly, getter=description) NSString *description_ __attribute__((swift_name("description_"))); +@end; + +__attribute__((objc_subclassing_restricted)) +__attribute__((swift_name("KT38641.Var"))) +@interface KtKT38641Var : KtBase +- (instancetype)init __attribute__((swift_name("init()"))) __attribute__((objc_designated_initializer)); ++ (instancetype)new __attribute__((availability(swift, unavailable, message="use object initializers instead"))); +@property (getter=description, setter=setDescription:) NSString *description_ __attribute__((swift_name("description_"))); +@end; + +__attribute__((objc_subclassing_restricted)) +__attribute__((swift_name("KT38641.TwoProperties"))) +@interface KtKT38641TwoProperties : KtBase +- (instancetype)init __attribute__((swift_name("init()"))) __attribute__((objc_designated_initializer)); ++ (instancetype)new __attribute__((availability(swift, unavailable, message="use object initializers instead"))); +@property (readonly, getter=description) NSString *description_ __attribute__((swift_name("description_"))); +@property (readonly) NSString *description_ __attribute__((swift_name("description_"))); +@end; + +__attribute__((swift_name("KT38641.OverrideVal"))) +@interface KtKT38641OverrideVal : KtBase +- (instancetype)init __attribute__((swift_name("init()"))) __attribute__((objc_designated_initializer)); ++ (instancetype)new __attribute__((availability(swift, unavailable, message="use object initializers instead"))); +@property (readonly, getter=description) NSString *description_ __attribute__((swift_name("description_"))); +@end; + +__attribute__((swift_name("KT38641OverrideVar"))) +@protocol KtKT38641OverrideVar +@required +@property (getter=description, setter=setDescription:) NSString *description_ __attribute__((swift_name("description_"))); +@end; + +__attribute__((objc_subclassing_restricted)) +__attribute__((swift_name("Kt38641Kt"))) +@interface KtKt38641Kt : KtBase ++ (NSString *)getOverrideValDescriptionImpl:(KtKT38641OverrideVal *)impl __attribute__((swift_name("getOverrideValDescription(impl:)"))); ++ (NSString *)getOverrideVarDescriptionImpl:(id)impl __attribute__((swift_name("getOverrideVarDescription(impl:)"))); ++ (void)setOverrideVarDescriptionImpl:(id)impl newValue:(NSString *)newValue __attribute__((swift_name("setOverrideVarDescription(impl:newValue:)"))); +@end; + +__attribute__((swift_name("JsonConfiguration"))) +@interface KtJsonConfiguration : KtBase +- (instancetype)init __attribute__((swift_name("init()"))) __attribute__((objc_designated_initializer)) __attribute__((unavailable("This class is deprecated for removal during serialization 1.0 API stabilization.\nFor configuring Json instances, the corresponding builder function can be used instead, e.g. instead of'Json(JsonConfiguration.Stable.copy(isLenient = true))' 'Json { isLenient = true }' should be used.\nInstead of storing JsonConfiguration instances of the code, Json instances can be used directly:'Json(MyJsonConfiguration.copy(prettyPrint = true))' can be replaced with 'Json(from = MyApplicationJson) { prettyPrint = true }'"))); ++ (instancetype)new __attribute__((availability(swift, unavailable, message="use object initializers instead"))); +@end; + +__attribute__((objc_subclassing_restricted)) +__attribute__((swift_name("MoreTrickyChars"))) +@interface KtMoreTrickyChars : KtBase +- (instancetype)init __attribute__((swift_name("init()"))) __attribute__((objc_designated_initializer)) __attribute__((deprecated("'\"\\@$(){}\r\n"))); ++ (instancetype)new __attribute__((availability(swift, unavailable, message="use object initializers instead"))); +@end; + +__attribute__((objc_subclassing_restricted)) +__attribute__((swift_name("Kt39206Kt"))) +@interface KtKt39206Kt : KtBase ++ (int32_t)myFunc __attribute__((swift_name("myFunc()"))) __attribute__((deprecated("Don't call this\nPlease"))); +@end; + +__attribute__((objc_subclassing_restricted)) +__attribute__((swift_name("Ckt41907"))) +@interface KtCkt41907 : KtBase +- (instancetype)init __attribute__((swift_name("init()"))) __attribute__((objc_designated_initializer)); ++ (instancetype)new __attribute__((availability(swift, unavailable, message="use object initializers instead"))); +@end; + +__attribute__((swift_name("Ikt41907"))) +@protocol KtIkt41907 +@required +- (void)fooC:(KtCkt41907 *)c __attribute__((swift_name("foo(c:)"))); +@end; + +__attribute__((objc_subclassing_restricted)) +__attribute__((swift_name("Kt41907Kt"))) +@interface KtKt41907Kt : KtBase ++ (void)escapeCC:(KtCkt41907 *)c __attribute__((swift_name("escapeC(c:)"))); ++ (void)testKt41907O:(id)o __attribute__((swift_name("testKt41907(o:)"))); +@end; + +__attribute__((objc_subclassing_restricted)) +__attribute__((swift_name("LibraryKt"))) +@interface KtLibraryKt : KtBase ++ (NSString *)readDataFromLibraryClassInput:(KtA *)input __attribute__((swift_name("readDataFromLibraryClass(input:)"))); ++ (NSString *)readDataFromLibraryInterfaceInput:(id)input __attribute__((swift_name("readDataFromLibraryInterface(input:)"))); ++ (NSString *)readDataFromLibraryEnumInput:(KtE *)input __attribute__((swift_name("readDataFromLibraryEnum(input:)"))); +@end; + +__attribute__((objc_subclassing_restricted)) +__attribute__((swift_name("ArraysConstructor"))) +@interface KtArraysConstructor : KtBase +- (instancetype)initWithInt1:(int32_t)int1 int2:(int32_t)int2 __attribute__((swift_name("init(int1:int2:)"))) __attribute__((objc_designated_initializer)); +- (void)setInt1:(int32_t)int1 int2:(int32_t)int2 __attribute__((swift_name("set(int1:int2:)"))); +- (NSString *)log __attribute__((swift_name("log()"))); +@end; + +__attribute__((objc_subclassing_restricted)) +__attribute__((swift_name("ArraysDefault"))) +@interface KtArraysDefault : KtBase +- (instancetype)initWithInt1:(int32_t)int1 int2:(int32_t)int2 __attribute__((swift_name("init(int1:int2:)"))) __attribute__((objc_designated_initializer)); +- (void)setInt1:(int32_t)int1 int2:(int32_t)int2 __attribute__((swift_name("set(int1:int2:)"))); +- (NSString *)log __attribute__((swift_name("log()"))); +@end; + +__attribute__((objc_subclassing_restricted)) +__attribute__((swift_name("ArraysInitBlock"))) +@interface KtArraysInitBlock : KtBase +- (instancetype)initWithInt1:(int32_t)int1 int2:(int32_t)int2 __attribute__((swift_name("init(int1:int2:)"))) __attribute__((objc_designated_initializer)); +- (void)setInt1:(int32_t)int1 int2:(int32_t)int2 __attribute__((swift_name("set(int1:int2:)"))); +- (NSString *)log __attribute__((swift_name("log()"))); +@end; + +__attribute__((objc_subclassing_restricted)) +__attribute__((swift_name("ThrowsEmptyKt"))) +@interface KtThrowsEmptyKt : KtBase + +/** + @warning All uncaught Kotlin exceptions are fatal. +*/ ++ (BOOL)throwsEmptyAndReturnError:(NSError * _Nullable * _Nullable)error __attribute__((swift_name("throwsEmpty()"))); +@end; + +__attribute__((objc_subclassing_restricted)) +__attribute__((swift_name("TopLevelManglingAKt"))) +@interface KtTopLevelManglingAKt : KtBase ++ (NSString *)foo __attribute__((swift_name("foo()"))); ++ (int32_t)sameNumberValue:(int32_t)value __attribute__((swift_name("sameNumber(value:)"))); ++ (int64_t)sameNumberValue:(int64_t)value __attribute__((swift_name("sameNumber(value:)"))); +@property (class, readonly) NSString *bar __attribute__((swift_name("bar"))); +@end; + +__attribute__((objc_subclassing_restricted)) +__attribute__((swift_name("TopLevelManglingBKt"))) +@interface KtTopLevelManglingBKt : KtBase ++ (NSString *)foo __attribute__((swift_name("foo()"))); +@property (class, readonly) NSString *bar __attribute__((swift_name("bar"))); +@end; + +__attribute__((objc_subclassing_restricted)) +__attribute__((swift_name("DelegateClass"))) +@interface KtDelegateClass : KtBase +- (instancetype)init __attribute__((swift_name("init()"))) __attribute__((objc_designated_initializer)); ++ (instancetype)new __attribute__((availability(swift, unavailable, message="use object initializers instead"))); +- (KtKotlinArray *)getValueThisRef:(KtKotlinNothing * _Nullable)thisRef property:(id)property __attribute__((swift_name("getValue(thisRef:property:)"))); +- (void)setValueThisRef:(KtKotlinNothing * _Nullable)thisRef property:(id)property value:(KtKotlinArray *)value __attribute__((swift_name("setValue(thisRef:property:value:)"))); +@end; + +__attribute__((swift_name("I"))) +@protocol KtI +@required +- (NSString *)iFun __attribute__((swift_name("iFun()"))); +@end; + +__attribute__((objc_subclassing_restricted)) +__attribute__((swift_name("DefaultInterfaceExt"))) +@interface KtDefaultInterfaceExt : KtBase +- (instancetype)init __attribute__((swift_name("init()"))) __attribute__((objc_designated_initializer)); ++ (instancetype)new __attribute__((availability(swift, unavailable, message="use object initializers instead"))); +@end; + +__attribute__((swift_name("OpenClassI"))) +@interface KtOpenClassI : KtBase +- (instancetype)init __attribute__((swift_name("init()"))) __attribute__((objc_designated_initializer)); ++ (instancetype)new __attribute__((availability(swift, unavailable, message="use object initializers instead"))); +- (NSString *)iFun __attribute__((swift_name("iFun()"))); +@end; + +__attribute__((objc_subclassing_restricted)) +__attribute__((swift_name("FinalClassExtOpen"))) +@interface KtFinalClassExtOpen : KtOpenClassI +- (instancetype)init __attribute__((swift_name("init()"))) __attribute__((objc_designated_initializer)); ++ (instancetype)new __attribute__((availability(swift, unavailable, message="use object initializers instead"))); +- (NSString *)iFun __attribute__((swift_name("iFun()"))); +@end; + +__attribute__((swift_name("MultiExtClass"))) +@interface KtMultiExtClass : KtOpenClassI +- (instancetype)init __attribute__((swift_name("init()"))) __attribute__((objc_designated_initializer)); ++ (instancetype)new __attribute__((availability(swift, unavailable, message="use object initializers instead"))); +- (id)piFun __attribute__((swift_name("piFun()"))); +- (NSString *)iFun __attribute__((swift_name("iFun()"))); +@end; + +__attribute__((swift_name("ConstrClass"))) +@interface KtConstrClass : KtOpenClassI +- (instancetype)initWithI:(int32_t)i s:(NSString *)s a:(id)a __attribute__((swift_name("init(i:s:a:)"))) __attribute__((objc_designated_initializer)); +- (instancetype)init __attribute__((swift_name("init()"))) __attribute__((objc_designated_initializer)) __attribute__((unavailable)); ++ (instancetype)new __attribute__((unavailable)); +@property (readonly) int32_t i __attribute__((swift_name("i"))); +@property (readonly) NSString *s __attribute__((swift_name("s"))); +@property (readonly) id a __attribute__((swift_name("a"))); +@end; + +__attribute__((objc_subclassing_restricted)) +__attribute__((swift_name("ExtConstrClass"))) +@interface KtExtConstrClass : KtConstrClass +- (instancetype)initWithI:(int32_t)i __attribute__((swift_name("init(i:)"))) __attribute__((objc_designated_initializer)); +- (instancetype)initWithI:(int32_t)i s:(NSString *)s a:(id)a __attribute__((swift_name("init(i:s:a:)"))) __attribute__((objc_designated_initializer)) __attribute__((unavailable)); +- (NSString *)iFun __attribute__((swift_name("iFun()"))); +@property (readonly) int32_t i __attribute__((swift_name("i"))); +@end; + +__attribute__((objc_subclassing_restricted)) +__attribute__((swift_name("Enumeration"))) +@interface KtEnumeration : KtKotlinEnum ++ (instancetype)alloc __attribute__((unavailable)); ++ (instancetype)allocWithZone:(struct _NSZone *)zone __attribute__((unavailable)); +- (instancetype)initWithName:(NSString *)name ordinal:(int32_t)ordinal __attribute__((swift_name("init(name:ordinal:)"))) __attribute__((objc_designated_initializer)) __attribute__((unavailable)); +@property (class, readonly) KtEnumeration *answer __attribute__((swift_name("answer"))); +@property (class, readonly) KtEnumeration *year __attribute__((swift_name("year"))); +@property (class, readonly) KtEnumeration *temperature __attribute__((swift_name("temperature"))); +@property (readonly) int32_t enumValue __attribute__((swift_name("enumValue"))); +@end; + +__attribute__((objc_subclassing_restricted)) +__attribute__((swift_name("TripleVals"))) +@interface KtTripleVals : KtBase +- (instancetype)initWithFirst:(T _Nullable)first second:(T _Nullable)second third:(T _Nullable)third __attribute__((swift_name("init(first:second:third:)"))) __attribute__((objc_designated_initializer)); +- (BOOL)isEqual:(id _Nullable)other __attribute__((swift_name("isEqual(_:)"))); +- (NSUInteger)hash __attribute__((swift_name("hash()"))); +- (NSString *)description __attribute__((swift_name("description()"))); +- (T _Nullable)component1 __attribute__((swift_name("component1()"))); +- (T _Nullable)component2 __attribute__((swift_name("component2()"))); +- (T _Nullable)component3 __attribute__((swift_name("component3()"))); +- (KtTripleVals *)doCopyFirst:(T _Nullable)first second:(T _Nullable)second third:(T _Nullable)third __attribute__((swift_name("doCopy(first:second:third:)"))); +@property (readonly) T _Nullable first __attribute__((swift_name("first"))); +@property (readonly) T _Nullable second __attribute__((swift_name("second"))); +@property (readonly) T _Nullable third __attribute__((swift_name("third"))); +@end; + +__attribute__((objc_subclassing_restricted)) +__attribute__((swift_name("TripleVars"))) +@interface KtTripleVars : KtBase +- (instancetype)initWithFirst:(T _Nullable)first second:(T _Nullable)second third:(T _Nullable)third __attribute__((swift_name("init(first:second:third:)"))) __attribute__((objc_designated_initializer)); +- (NSString *)description __attribute__((swift_name("description()"))); +- (BOOL)isEqual:(id _Nullable)other __attribute__((swift_name("isEqual(_:)"))); +- (NSUInteger)hash __attribute__((swift_name("hash()"))); +- (T _Nullable)component1 __attribute__((swift_name("component1()"))); +- (T _Nullable)component2 __attribute__((swift_name("component2()"))); +- (T _Nullable)component3 __attribute__((swift_name("component3()"))); +- (KtTripleVars *)doCopyFirst:(T _Nullable)first second:(T _Nullable)second third:(T _Nullable)third __attribute__((swift_name("doCopy(first:second:third:)"))); +@property T _Nullable first __attribute__((swift_name("first"))); +@property T _Nullable second __attribute__((swift_name("second"))); +@property T _Nullable third __attribute__((swift_name("third"))); +@end; + +__attribute__((swift_name("WithCompanionAndObject"))) +@interface KtWithCompanionAndObject : KtBase +- (instancetype)init __attribute__((swift_name("init()"))) __attribute__((objc_designated_initializer)); ++ (instancetype)new __attribute__((availability(swift, unavailable, message="use object initializers instead"))); +@end; + +__attribute__((objc_subclassing_restricted)) +__attribute__((swift_name("WithCompanionAndObject.Companion"))) +@interface KtWithCompanionAndObjectCompanion : KtBase ++ (instancetype)alloc __attribute__((unavailable)); ++ (instancetype)allocWithZone:(struct _NSZone *)zone __attribute__((unavailable)); ++ (instancetype)companion __attribute__((swift_name("init()"))); +@property (readonly) NSString *str __attribute__((swift_name("str"))); +@property id _Nullable named __attribute__((swift_name("named"))); +@end; + +__attribute__((objc_subclassing_restricted)) +__attribute__((swift_name("WithCompanionAndObject.Named"))) +@interface KtWithCompanionAndObjectNamed : KtOpenClassI ++ (instancetype)alloc __attribute__((unavailable)); ++ (instancetype)allocWithZone:(struct _NSZone *)zone __attribute__((unavailable)); +- (instancetype)init __attribute__((swift_name("init()"))) __attribute__((objc_designated_initializer)) __attribute__((unavailable)); ++ (instancetype)new __attribute__((unavailable)); ++ (instancetype)named __attribute__((swift_name("init()"))); +- (NSString *)iFun __attribute__((swift_name("iFun()"))); +@end; + +__attribute__((objc_subclassing_restricted)) +__attribute__((swift_name("MyException"))) +@interface KtMyException : KtKotlinException +- (instancetype)init __attribute__((swift_name("init()"))) __attribute__((objc_designated_initializer)); ++ (instancetype)new __attribute__((availability(swift, unavailable, message="use object initializers instead"))); +- (instancetype)initWithMessage:(NSString * _Nullable)message __attribute__((swift_name("init(message:)"))) __attribute__((objc_designated_initializer)) __attribute__((unavailable)); +- (instancetype)initWithMessage:(NSString * _Nullable)message cause:(KtKotlinThrowable * _Nullable)cause __attribute__((swift_name("init(message:cause:)"))) __attribute__((objc_designated_initializer)) __attribute__((unavailable)); +- (instancetype)initWithCause:(KtKotlinThrowable * _Nullable)cause __attribute__((swift_name("init(cause:)"))) __attribute__((objc_designated_initializer)) __attribute__((unavailable)); +@end; + +__attribute__((objc_subclassing_restricted)) +__attribute__((swift_name("MyError"))) +@interface KtMyError : KtKotlinError +- (instancetype)init __attribute__((swift_name("init()"))) __attribute__((objc_designated_initializer)); ++ (instancetype)new __attribute__((availability(swift, unavailable, message="use object initializers instead"))); +- (instancetype)initWithMessage:(NSString * _Nullable)message __attribute__((swift_name("init(message:)"))) __attribute__((objc_designated_initializer)) __attribute__((unavailable)); +- (instancetype)initWithMessage:(NSString * _Nullable)message cause:(KtKotlinThrowable * _Nullable)cause __attribute__((swift_name("init(message:cause:)"))) __attribute__((objc_designated_initializer)) __attribute__((unavailable)); +- (instancetype)initWithCause:(KtKotlinThrowable * _Nullable)cause __attribute__((swift_name("init(cause:)"))) __attribute__((objc_designated_initializer)) __attribute__((unavailable)); +@end; + +__attribute__((swift_name("SwiftOverridableMethodsWithThrows"))) +@protocol KtSwiftOverridableMethodsWithThrows +@required + +/** + @note This method converts instances of MyException to errors. + Other uncaught Kotlin exceptions are fatal. +*/ +- (BOOL)unitAndReturnError:(NSError * _Nullable * _Nullable)error __attribute__((swift_name("unit()"))); + +/** + @note This method converts instances of MyException to errors. + Other uncaught Kotlin exceptions are fatal. +*/ +- (BOOL)nothingAndReturnError:(NSError * _Nullable * _Nullable)error __attribute__((swift_name("nothing()"))); + +/** + @note This method converts instances of MyException to errors. + Other uncaught Kotlin exceptions are fatal. +*/ +- (id _Nullable)anyAndReturnError:(NSError * _Nullable * _Nullable)error __attribute__((swift_name("any()"))); + +/** + @note This method converts instances of MyException to errors. + Other uncaught Kotlin exceptions are fatal. +*/ +- (KtInt *(^ _Nullable)(void))blockAndReturnError:(NSError * _Nullable * _Nullable)error __attribute__((swift_name("block()"))); +@end; + +__attribute__((swift_name("MethodsWithThrows"))) +@protocol KtMethodsWithThrows +@required + +/** + @note This method converts instances of MyException to errors. + Other uncaught Kotlin exceptions are fatal. +*/ +- (KtKotlinNothing * _Nullable)nothingNAndReturnError:(NSError * _Nullable * _Nullable)error __attribute__((swift_name("nothingN()"))) __attribute__((swift_error(nonnull_error))); + +/** + @note This method converts instances of MyException to errors. + Other uncaught Kotlin exceptions are fatal. +*/ +- (id _Nullable)anyNAndReturnError:(NSError * _Nullable * _Nullable)error __attribute__((swift_name("anyN()"))) __attribute__((swift_error(nonnull_error))); + +/** + @note This method converts instances of MyException to errors. + Other uncaught Kotlin exceptions are fatal. +*/ +- (KtInt *(^ _Nullable)(void))blockNAndReturnError:(NSError * _Nullable * _Nullable)error __attribute__((swift_name("blockN()"))) __attribute__((swift_error(nonnull_error))); + +/** + @note This method converts instances of MyException to errors. + Other uncaught Kotlin exceptions are fatal. +*/ +- (void * _Nullable)pointerAndReturnError:(NSError * _Nullable * _Nullable)error __attribute__((swift_name("pointer()"))); + +/** + @note This method converts instances of MyException to errors. + Other uncaught Kotlin exceptions are fatal. +*/ +- (void * _Nullable)pointerNAndReturnError:(NSError * _Nullable * _Nullable)error __attribute__((swift_name("pointerN()"))) __attribute__((swift_error(nonnull_error))); + +/** + @note This method converts instances of MyException to errors. + Other uncaught Kotlin exceptions are fatal. +*/ +- (int32_t)intAndReturnError:(NSError * _Nullable * _Nullable)error __attribute__((swift_name("int()"))) __attribute__((swift_error(nonnull_error))); + +/** + @note This method converts instances of MyException to errors. + Other uncaught Kotlin exceptions are fatal. +*/ +- (KtLong * _Nullable)longNAndReturnError:(NSError * _Nullable * _Nullable)error __attribute__((swift_name("longN()"))) __attribute__((swift_error(nonnull_error))); + +/** + @note This method converts instances of MyException to errors. + Other uncaught Kotlin exceptions are fatal. +*/ +- (double)doubleAndReturnError:(NSError * _Nullable * _Nullable)error __attribute__((swift_name("double()"))) __attribute__((swift_error(nonnull_error))); +@end; + +__attribute__((swift_name("MethodsWithThrowsUnitCaller"))) +@protocol KtMethodsWithThrowsUnitCaller +@required + +/** + @note This method converts instances of MyException to errors. + Other uncaught Kotlin exceptions are fatal. +*/ +- (BOOL)callMethods:(id)methods error:(NSError * _Nullable * _Nullable)error __attribute__((swift_name("call(methods:)"))); +@end; + +__attribute__((swift_name("Throwing"))) +@interface KtThrowing : KtBase + +/** + @note This method converts instances of MyException to errors. + Other uncaught Kotlin exceptions are fatal. +*/ +- (instancetype _Nullable)initWithDoThrow:(BOOL)doThrow error:(NSError * _Nullable * _Nullable)error __attribute__((swift_name("init(doThrow:)"))) __attribute__((objc_designated_initializer)); + +/** + @note This method converts instances of MyException to errors. + Other uncaught Kotlin exceptions are fatal. +*/ +- (BOOL)unitAndReturnError:(NSError * _Nullable * _Nullable)error __attribute__((swift_name("unit()"))); + +/** + @note This method converts instances of MyException to errors. + Other uncaught Kotlin exceptions are fatal. +*/ +- (BOOL)nothingAndReturnError:(NSError * _Nullable * _Nullable)error __attribute__((swift_name("nothing()"))); + +/** + @note This method converts instances of MyException to errors. + Other uncaught Kotlin exceptions are fatal. +*/ +- (KtKotlinNothing * _Nullable)nothingNAndReturnError:(NSError * _Nullable * _Nullable)error __attribute__((swift_name("nothingN()"))) __attribute__((swift_error(nonnull_error))); + +/** + @note This method converts instances of MyException to errors. + Other uncaught Kotlin exceptions are fatal. +*/ +- (id _Nullable)anyAndReturnError:(NSError * _Nullable * _Nullable)error __attribute__((swift_name("any()"))); + +/** + @note This method converts instances of MyException to errors. + Other uncaught Kotlin exceptions are fatal. +*/ +- (id _Nullable)anyNAndReturnError:(NSError * _Nullable * _Nullable)error __attribute__((swift_name("anyN()"))) __attribute__((swift_error(nonnull_error))); + +/** + @note This method converts instances of MyException to errors. + Other uncaught Kotlin exceptions are fatal. +*/ +- (KtInt *(^ _Nullable)(void))blockAndReturnError:(NSError * _Nullable * _Nullable)error __attribute__((swift_name("block()"))); + +/** + @note This method converts instances of MyException to errors. + Other uncaught Kotlin exceptions are fatal. +*/ +- (KtInt *(^ _Nullable)(void))blockNAndReturnError:(NSError * _Nullable * _Nullable)error __attribute__((swift_name("blockN()"))) __attribute__((swift_error(nonnull_error))); + +/** + @note This method converts instances of MyException to errors. + Other uncaught Kotlin exceptions are fatal. +*/ +- (void * _Nullable)pointerAndReturnError:(NSError * _Nullable * _Nullable)error __attribute__((swift_name("pointer()"))); + +/** + @note This method converts instances of MyException to errors. + Other uncaught Kotlin exceptions are fatal. +*/ +- (void * _Nullable)pointerNAndReturnError:(NSError * _Nullable * _Nullable)error __attribute__((swift_name("pointerN()"))) __attribute__((swift_error(nonnull_error))); + +/** + @note This method converts instances of MyException to errors. + Other uncaught Kotlin exceptions are fatal. +*/ +- (int32_t)intAndReturnError:(NSError * _Nullable * _Nullable)error __attribute__((swift_name("int()"))) __attribute__((swift_error(nonnull_error))); + +/** + @note This method converts instances of MyException to errors. + Other uncaught Kotlin exceptions are fatal. +*/ +- (KtLong * _Nullable)longNAndReturnError:(NSError * _Nullable * _Nullable)error __attribute__((swift_name("longN()"))) __attribute__((swift_error(nonnull_error))); + +/** + @note This method converts instances of MyException to errors. + Other uncaught Kotlin exceptions are fatal. +*/ +- (double)doubleAndReturnError:(NSError * _Nullable * _Nullable)error __attribute__((swift_name("double()"))) __attribute__((swift_error(nonnull_error))); +@end; + +__attribute__((objc_subclassing_restricted)) +__attribute__((swift_name("NotThrowing"))) +@interface KtNotThrowing : KtBase + +/** + @note This method converts instances of MyException to errors. + Other uncaught Kotlin exceptions are fatal. +*/ +- (instancetype _Nullable)initAndReturnError:(NSError * _Nullable * _Nullable)error __attribute__((swift_name("init()"))) __attribute__((objc_designated_initializer)); + +/** + @note This method converts instances of MyException to errors. + Other uncaught Kotlin exceptions are fatal. +*/ +- (BOOL)unitAndReturnError:(NSError * _Nullable * _Nullable)error __attribute__((swift_name("unit()"))); + +/** + @note This method converts instances of MyException to errors. + Other uncaught Kotlin exceptions are fatal. +*/ +- (BOOL)nothingAndReturnError:(NSError * _Nullable * _Nullable)error __attribute__((swift_name("nothing()"))); + +/** + @note This method converts instances of MyException to errors. + Other uncaught Kotlin exceptions are fatal. +*/ +- (KtKotlinNothing * _Nullable)nothingNAndReturnError:(NSError * _Nullable * _Nullable)error __attribute__((swift_name("nothingN()"))) __attribute__((swift_error(nonnull_error))); + +/** + @note This method converts instances of MyException to errors. + Other uncaught Kotlin exceptions are fatal. +*/ +- (id _Nullable)anyAndReturnError:(NSError * _Nullable * _Nullable)error __attribute__((swift_name("any()"))); + +/** + @note This method converts instances of MyException to errors. + Other uncaught Kotlin exceptions are fatal. +*/ +- (id _Nullable)anyNAndReturnError:(NSError * _Nullable * _Nullable)error __attribute__((swift_name("anyN()"))) __attribute__((swift_error(nonnull_error))); + +/** + @note This method converts instances of MyException to errors. + Other uncaught Kotlin exceptions are fatal. +*/ +- (KtInt *(^ _Nullable)(void))blockAndReturnError:(NSError * _Nullable * _Nullable)error __attribute__((swift_name("block()"))); + +/** + @note This method converts instances of MyException to errors. + Other uncaught Kotlin exceptions are fatal. +*/ +- (KtInt *(^ _Nullable)(void))blockNAndReturnError:(NSError * _Nullable * _Nullable)error __attribute__((swift_name("blockN()"))) __attribute__((swift_error(nonnull_error))); + +/** + @note This method converts instances of MyException to errors. + Other uncaught Kotlin exceptions are fatal. +*/ +- (void * _Nullable)pointerAndReturnError:(NSError * _Nullable * _Nullable)error __attribute__((swift_name("pointer()"))); + +/** + @note This method converts instances of MyException to errors. + Other uncaught Kotlin exceptions are fatal. +*/ +- (void * _Nullable)pointerNAndReturnError:(NSError * _Nullable * _Nullable)error __attribute__((swift_name("pointerN()"))) __attribute__((swift_error(nonnull_error))); + +/** + @note This method converts instances of MyException to errors. + Other uncaught Kotlin exceptions are fatal. +*/ +- (int32_t)intAndReturnError:(NSError * _Nullable * _Nullable)error __attribute__((swift_name("int()"))) __attribute__((swift_error(nonnull_error))); + +/** + @note This method converts instances of MyException to errors. + Other uncaught Kotlin exceptions are fatal. +*/ +- (KtLong * _Nullable)longNAndReturnError:(NSError * _Nullable * _Nullable)error __attribute__((swift_name("longN()"))) __attribute__((swift_error(nonnull_error))); + +/** + @note This method converts instances of MyException to errors. + Other uncaught Kotlin exceptions are fatal. +*/ +- (double)doubleAndReturnError:(NSError * _Nullable * _Nullable)error __attribute__((swift_name("double()"))) __attribute__((swift_error(nonnull_error))); +@end; + +__attribute__((swift_name("ThrowsWithBridgeBase"))) +@protocol KtThrowsWithBridgeBase +@required + +/** + @note This method converts instances of MyException to errors. + Other uncaught Kotlin exceptions are fatal. +*/ +- (id _Nullable)plusOneX:(int32_t)x error:(NSError * _Nullable * _Nullable)error __attribute__((swift_name("plusOne(x:)"))); +@end; + +__attribute__((swift_name("ThrowsWithBridge"))) +@interface KtThrowsWithBridge : KtBase +- (instancetype)init __attribute__((swift_name("init()"))) __attribute__((objc_designated_initializer)); ++ (instancetype)new __attribute__((availability(swift, unavailable, message="use object initializers instead"))); + +/** + @note This method converts instances of MyException to errors. + Other uncaught Kotlin exceptions are fatal. +*/ +- (KtInt * _Nullable)plusOneX:(int32_t)x error:(NSError * _Nullable * _Nullable)error __attribute__((swift_name("plusOne(x:)"))); +@end; + +__attribute__((objc_subclassing_restricted)) +__attribute__((swift_name("Deeply"))) +@interface KtDeeply : KtBase +- (instancetype)init __attribute__((swift_name("init()"))) __attribute__((objc_designated_initializer)); ++ (instancetype)new __attribute__((availability(swift, unavailable, message="use object initializers instead"))); +@end; + +__attribute__((objc_subclassing_restricted)) +__attribute__((swift_name("Deeply.Nested"))) +@interface KtDeeplyNested : KtBase +- (instancetype)init __attribute__((swift_name("init()"))) __attribute__((objc_designated_initializer)); ++ (instancetype)new __attribute__((availability(swift, unavailable, message="use object initializers instead"))); +@end; + +__attribute__((objc_subclassing_restricted)) +__attribute__((swift_name("Deeply.NestedType"))) +@interface KtDeeplyNestedType : KtBase +- (instancetype)init __attribute__((swift_name("init()"))) __attribute__((objc_designated_initializer)); ++ (instancetype)new __attribute__((availability(swift, unavailable, message="use object initializers instead"))); +@property (readonly) int32_t thirtyTwo __attribute__((swift_name("thirtyTwo"))); +@end; + +__attribute__((swift_name("DeeplyNestedIType"))) +@protocol KtDeeplyNestedIType +@required +@end; + +__attribute__((objc_subclassing_restricted)) +__attribute__((swift_name("WithGenericDeeply"))) +@interface KtWithGenericDeeply : KtBase +- (instancetype)init __attribute__((swift_name("init()"))) __attribute__((objc_designated_initializer)); ++ (instancetype)new __attribute__((availability(swift, unavailable, message="use object initializers instead"))); +@end; + +__attribute__((objc_subclassing_restricted)) +__attribute__((swift_name("WithGenericDeeply.Nested"))) +@interface KtWithGenericDeeplyNested : KtBase +- (instancetype)init __attribute__((swift_name("init()"))) __attribute__((objc_designated_initializer)); ++ (instancetype)new __attribute__((availability(swift, unavailable, message="use object initializers instead"))); +@end; + +__attribute__((objc_subclassing_restricted)) +__attribute__((swift_name("WithGenericDeeplyNestedType"))) +@interface KtWithGenericDeeplyNestedType : KtBase +- (instancetype)init __attribute__((swift_name("init()"))) __attribute__((objc_designated_initializer)); ++ (instancetype)new __attribute__((availability(swift, unavailable, message="use object initializers instead"))); +@property (readonly) int32_t thirtyThree __attribute__((swift_name("thirtyThree"))); +@end; + +__attribute__((objc_subclassing_restricted)) +__attribute__((swift_name("TypeOuter"))) +@interface KtTypeOuter : KtBase +- (instancetype)init __attribute__((swift_name("init()"))) __attribute__((objc_designated_initializer)); ++ (instancetype)new __attribute__((availability(swift, unavailable, message="use object initializers instead"))); +@end; + +__attribute__((objc_subclassing_restricted)) +__attribute__((swift_name("TypeOuter.Type_"))) +@interface KtTypeOuterType_ : KtBase +- (instancetype)init __attribute__((swift_name("init()"))) __attribute__((objc_designated_initializer)); ++ (instancetype)new __attribute__((availability(swift, unavailable, message="use object initializers instead"))); +@property (readonly) int32_t thirtyFour __attribute__((swift_name("thirtyFour"))); +@end; + +__attribute__((objc_subclassing_restricted)) +__attribute__((swift_name("CKeywords"))) +@interface KtCKeywords : KtBase +- (instancetype)initWithFloat:(float)float_ enum:(int32_t)enum_ goto:(BOOL)goto_ __attribute__((swift_name("init(float:enum:goto:)"))) __attribute__((objc_designated_initializer)); +- (BOOL)isEqual:(id _Nullable)other __attribute__((swift_name("isEqual(_:)"))); +- (NSUInteger)hash __attribute__((swift_name("hash()"))); +- (NSString *)description __attribute__((swift_name("description()"))); +- (float)component1 __attribute__((swift_name("component1()"))); +- (int32_t)component2 __attribute__((swift_name("component2()"))); +- (BOOL)component3 __attribute__((swift_name("component3()"))); +- (KtCKeywords *)doCopyFloat:(float)float_ enum:(int32_t)enum_ goto:(BOOL)goto_ __attribute__((swift_name("doCopy(float:enum:goto:)"))); +@property (readonly, getter=float) float float_ __attribute__((swift_name("float_"))); +@property (readonly, getter=enum) int32_t enum_ __attribute__((swift_name("enum_"))); +@property (getter=goto, setter=setGoto:) BOOL goto_ __attribute__((swift_name("goto_"))); +@end; + +__attribute__((swift_name("Base1"))) +@protocol KtBase1 +@required +- (KtInt * _Nullable)sameValue:(KtInt * _Nullable)value __attribute__((swift_name("same(value:)"))); +@end; + +__attribute__((swift_name("ExtendedBase1"))) +@protocol KtExtendedBase1 +@required +@end; + +__attribute__((swift_name("Base2"))) +@protocol KtBase2 +@required +- (KtInt * _Nullable)sameValue:(KtInt * _Nullable)value __attribute__((swift_name("same(value:)"))); +@end; + +__attribute__((swift_name("Base23"))) +@interface KtBase23 : KtBase +- (instancetype)init __attribute__((swift_name("init()"))) __attribute__((objc_designated_initializer)); ++ (instancetype)new __attribute__((availability(swift, unavailable, message="use object initializers instead"))); +- (KtInt *)sameValue:(KtInt * _Nullable)value __attribute__((swift_name("same(value:)"))); +@end; + +__attribute__((swift_name("Transform"))) +@protocol KtTransform +@required +- (id _Nullable)mapValue:(id _Nullable)value __attribute__((swift_name("map(value:)"))); +@end; + +__attribute__((swift_name("TransformWithDefault"))) +@protocol KtTransformWithDefault +@required +@end; + +__attribute__((objc_subclassing_restricted)) +__attribute__((swift_name("TransformInheritingDefault"))) +@interface KtTransformInheritingDefault : KtBase +- (instancetype)init __attribute__((swift_name("init()"))) __attribute__((objc_designated_initializer)); ++ (instancetype)new __attribute__((availability(swift, unavailable, message="use object initializers instead"))); +@end; + +__attribute__((swift_name("TransformIntString"))) +@protocol KtTransformIntString +@required +- (NSString *)mapIntValue:(int32_t)intValue __attribute__((swift_name("map(intValue:)"))); +@end; + +__attribute__((swift_name("TransformIntToString"))) +@interface KtTransformIntToString : KtBase +- (instancetype)init __attribute__((swift_name("init()"))) __attribute__((objc_designated_initializer)); ++ (instancetype)new __attribute__((availability(swift, unavailable, message="use object initializers instead"))); +- (NSString *)mapValue:(KtInt *)intValue __attribute__((swift_name("map(value:)"))); +- (NSString *)mapIntValue:(int32_t)intValue __attribute__((swift_name("map(intValue:)"))); +@end; + +__attribute__((swift_name("TransformIntToDecimalString"))) +@interface KtTransformIntToDecimalString : KtTransformIntToString +- (instancetype)init __attribute__((swift_name("init()"))) __attribute__((objc_designated_initializer)); ++ (instancetype)new __attribute__((availability(swift, unavailable, message="use object initializers instead"))); +- (NSString *)mapValue:(KtInt *)intValue __attribute__((swift_name("map(value:)"))); +- (NSString *)mapIntValue:(int32_t)intValue __attribute__((swift_name("map(intValue:)"))); +@end; + +__attribute__((swift_name("TransformIntToLong"))) +@interface KtTransformIntToLong : KtBase +- (instancetype)init __attribute__((swift_name("init()"))) __attribute__((objc_designated_initializer)); ++ (instancetype)new __attribute__((availability(swift, unavailable, message="use object initializers instead"))); +- (KtLong *)mapValue:(KtInt *)value __attribute__((swift_name("map(value:)"))); +@end; + +__attribute__((objc_subclassing_restricted)) +__attribute__((swift_name("GH2931"))) +@interface KtGH2931 : KtBase +- (instancetype)init __attribute__((swift_name("init()"))) __attribute__((objc_designated_initializer)); ++ (instancetype)new __attribute__((availability(swift, unavailable, message="use object initializers instead"))); +@end; + +__attribute__((objc_subclassing_restricted)) +__attribute__((swift_name("GH2931.Data"))) +@interface KtGH2931Data : KtBase +- (instancetype)init __attribute__((swift_name("init()"))) __attribute__((objc_designated_initializer)); ++ (instancetype)new __attribute__((availability(swift, unavailable, message="use object initializers instead"))); +@end; + +__attribute__((objc_subclassing_restricted)) +__attribute__((swift_name("GH2931.Holder"))) +@interface KtGH2931Holder : KtBase +- (instancetype)init __attribute__((swift_name("init()"))) __attribute__((objc_designated_initializer)); ++ (instancetype)new __attribute__((availability(swift, unavailable, message="use object initializers instead"))); +@property (readonly) KtGH2931Data *data __attribute__((swift_name("data"))); +@end; + +__attribute__((objc_subclassing_restricted)) +__attribute__((swift_name("GH2945"))) +@interface KtGH2945 : KtBase +- (instancetype)initWithErrno:(int32_t)errno __attribute__((swift_name("init(errno:)"))) __attribute__((objc_designated_initializer)); +- (int32_t)testErrnoInSelectorP:(int32_t)p errno:(int32_t)errno __attribute__((swift_name("testErrnoInSelector(p:errno:)"))); +@property int32_t errno __attribute__((swift_name("errno"))); +@end; + +__attribute__((objc_subclassing_restricted)) +__attribute__((swift_name("GH2830"))) +@interface KtGH2830 : KtBase +- (instancetype)init __attribute__((swift_name("init()"))) __attribute__((objc_designated_initializer)); ++ (instancetype)new __attribute__((availability(swift, unavailable, message="use object initializers instead"))); +- (id)getI __attribute__((swift_name("getI()"))); +@end; + +__attribute__((swift_name("GH2830I"))) +@protocol KtGH2830I +@required +@end; + +__attribute__((objc_subclassing_restricted)) +__attribute__((swift_name("GH2959"))) +@interface KtGH2959 : KtBase +- (instancetype)init __attribute__((swift_name("init()"))) __attribute__((objc_designated_initializer)); ++ (instancetype)new __attribute__((availability(swift, unavailable, message="use object initializers instead"))); +- (NSArray> *)getIId:(int32_t)id __attribute__((swift_name("getI(id:)"))); +@end; + +__attribute__((swift_name("GH2959I"))) +@protocol KtGH2959I +@required +@property (readonly) int32_t id __attribute__((swift_name("id"))); +@end; + +__attribute__((swift_name("IntBlocks"))) +@protocol KtIntBlocks +@required +- (id _Nullable)getPlusOneBlock __attribute__((swift_name("getPlusOneBlock()"))); +- (int32_t)callBlockArgument:(int32_t)argument block:(id _Nullable)block __attribute__((swift_name("callBlock(argument:block:)"))); +@end; + +__attribute__((objc_subclassing_restricted)) +__attribute__((swift_name("IntBlocksImpl"))) +@interface KtIntBlocksImpl : KtBase ++ (instancetype)alloc __attribute__((unavailable)); ++ (instancetype)allocWithZone:(struct _NSZone *)zone __attribute__((unavailable)); ++ (instancetype)intBlocksImpl __attribute__((swift_name("init()"))); +- (KtInt *(^)(KtInt *))getPlusOneBlock __attribute__((swift_name("getPlusOneBlock()"))); +- (int32_t)callBlockArgument:(int32_t)argument block:(KtInt *(^)(KtInt *))block __attribute__((swift_name("callBlock(argument:block:)"))); +@end; + +__attribute__((swift_name("UnitBlockCoercion"))) +@protocol KtUnitBlockCoercion +@required +- (id)coerceBlock:(void (^)(void))block __attribute__((swift_name("coerce(block:)"))); +- (void (^)(void))uncoerceBlock:(id)block __attribute__((swift_name("uncoerce(block:)"))); +@end; + +__attribute__((objc_subclassing_restricted)) +__attribute__((swift_name("UnitBlockCoercionImpl"))) +@interface KtUnitBlockCoercionImpl : KtBase ++ (instancetype)alloc __attribute__((unavailable)); ++ (instancetype)allocWithZone:(struct _NSZone *)zone __attribute__((unavailable)); ++ (instancetype)unitBlockCoercionImpl __attribute__((swift_name("init()"))); +- (KtKotlinUnit *(^)(void))coerceBlock:(void (^)(void))block __attribute__((swift_name("coerce(block:)"))); +- (void (^)(void))uncoerceBlock:(KtKotlinUnit *(^)(void))block __attribute__((swift_name("uncoerce(block:)"))); +@end; + +__attribute__((swift_name("MyAbstractList"))) +@interface KtMyAbstractList : NSObject +@end; + +__attribute__((objc_subclassing_restricted)) +__attribute__((swift_name("TestKClass"))) +@interface KtTestKClass : KtBase +- (instancetype)init __attribute__((swift_name("init()"))) __attribute__((objc_designated_initializer)); ++ (instancetype)new __attribute__((availability(swift, unavailable, message="use object initializers instead"))); +- (id _Nullable)getKotlinClassClazz:(Class)clazz __attribute__((swift_name("getKotlinClass(clazz:)"))); +- (id _Nullable)getKotlinClassProtocol:(Protocol *)protocol __attribute__((swift_name("getKotlinClass(protocol:)"))); +- (BOOL)isTestKClassKClass:(id)kClass __attribute__((swift_name("isTestKClass(kClass:)"))); +- (BOOL)isIKClass:(id)kClass __attribute__((swift_name("isI(kClass:)"))); +@end; + +__attribute__((swift_name("TestKClassI"))) +@protocol KtTestKClassI +@required +@end; + +__attribute__((swift_name("ForwardI2"))) +@protocol KtForwardI2 +@required +@end; + +__attribute__((swift_name("ForwardI1"))) +@protocol KtForwardI1 +@required +- (id)getForwardI2 __attribute__((swift_name("getForwardI2()"))); +@end; + +__attribute__((swift_name("ForwardC2"))) +@interface KtForwardC2 : KtForwardC1 +- (instancetype)init __attribute__((swift_name("init()"))) __attribute__((objc_designated_initializer)); ++ (instancetype)new __attribute__((availability(swift, unavailable, message="use object initializers instead"))); +@end; + +__attribute__((swift_name("ForwardC1"))) +@interface KtForwardC1 : KtBase +- (instancetype)init __attribute__((swift_name("init()"))) __attribute__((objc_designated_initializer)); ++ (instancetype)new __attribute__((availability(swift, unavailable, message="use object initializers instead"))); +- (KtForwardC2 *)getForwardC2 __attribute__((swift_name("getForwardC2()"))); +@end; + +__attribute__((swift_name("TestSR10177Workaround"))) +@protocol KtTestSR10177Workaround +@required +@end; + +__attribute__((swift_name("TestClashes1"))) +@protocol KtTestClashes1 +@required +@property (readonly) int32_t clashingProperty __attribute__((swift_name("clashingProperty"))); +@end; + +__attribute__((swift_name("TestClashes2"))) +@protocol KtTestClashes2 +@required +@property (readonly) id clashingProperty __attribute__((swift_name("clashingProperty"))); +@property (readonly) id clashingProperty_ __attribute__((swift_name("clashingProperty_"))); +@end; + +__attribute__((objc_subclassing_restricted)) +__attribute__((swift_name("TestClashesImpl"))) +@interface KtTestClashesImpl : KtBase +- (instancetype)init __attribute__((swift_name("init()"))) __attribute__((objc_designated_initializer)); ++ (instancetype)new __attribute__((availability(swift, unavailable, message="use object initializers instead"))); +@property (readonly) int32_t clashingProperty __attribute__((swift_name("clashingProperty"))); +@property (readonly) KtInt *clashingProperty_ __attribute__((swift_name("clashingProperty_"))); +@end; + +__attribute__((objc_subclassing_restricted)) +__attribute__((swift_name("TestInvalidIdentifiers"))) +@interface KtTestInvalidIdentifiers : KtBase +- (instancetype)init __attribute__((swift_name("init()"))) __attribute__((objc_designated_initializer)); ++ (instancetype)new __attribute__((availability(swift, unavailable, message="use object initializers instead"))); +- (int32_t)a_d_d_1:(int32_t)_1 _2:(int32_t)_2 _3:(int32_t)_3 __attribute__((swift_name("a_d_d(_1:_2:_3:)"))); +@property NSString *_status __attribute__((swift_name("_status"))); +@property (readonly) unichar __ __attribute__((swift_name("__"))); +@property (readonly) unichar __ __attribute__((swift_name("__"))); +@end; + +__attribute__((objc_subclassing_restricted)) +__attribute__((swift_name("TestInvalidIdentifiers._Foo"))) +@interface KtTestInvalidIdentifiers_Foo : KtBase +- (instancetype)init __attribute__((swift_name("init()"))) __attribute__((objc_designated_initializer)); ++ (instancetype)new __attribute__((availability(swift, unavailable, message="use object initializers instead"))); +@end; + +__attribute__((objc_subclassing_restricted)) +__attribute__((swift_name("TestInvalidIdentifiers.Bar_"))) +@interface KtTestInvalidIdentifiersBar_ : KtBase +- (instancetype)init __attribute__((swift_name("init()"))) __attribute__((objc_designated_initializer)); ++ (instancetype)new __attribute__((availability(swift, unavailable, message="use object initializers instead"))); +@end; + +__attribute__((objc_subclassing_restricted)) +__attribute__((swift_name("TestInvalidIdentifiers.E"))) +@interface KtTestInvalidIdentifiersE : KtKotlinEnum ++ (instancetype)alloc __attribute__((unavailable)); ++ (instancetype)allocWithZone:(struct _NSZone *)zone __attribute__((unavailable)); +- (instancetype)initWithName:(NSString *)name ordinal:(int32_t)ordinal __attribute__((swift_name("init(name:ordinal:)"))) __attribute__((objc_designated_initializer)) __attribute__((unavailable)); +@property (class, readonly) KtTestInvalidIdentifiersE *_4_ __attribute__((swift_name("_4_"))); +@property (class, readonly) KtTestInvalidIdentifiersE *_5_ __attribute__((swift_name("_5_"))); +@property (class, readonly) KtTestInvalidIdentifiersE *__ __attribute__((swift_name("__"))); +@property (class, readonly) KtTestInvalidIdentifiersE *__ __attribute__((swift_name("__"))); +@property (readonly) int32_t value __attribute__((swift_name("value"))); +@end; + +__attribute__((objc_subclassing_restricted)) +__attribute__((swift_name("TestInvalidIdentifiers.Companion_"))) +@interface KtTestInvalidIdentifiersCompanion_ : KtBase ++ (instancetype)alloc __attribute__((unavailable)); ++ (instancetype)allocWithZone:(struct _NSZone *)zone __attribute__((unavailable)); ++ (instancetype)companion_ __attribute__((swift_name("init()"))); +@property (readonly) int32_t _42 __attribute__((swift_name("_42"))); +@end; + +__attribute__((swift_name("TestDeprecation"))) +@interface KtTestDeprecation : KtBase +- (instancetype)initWithError:(int16_t)error __attribute__((swift_name("init(error:)"))) __attribute__((objc_designated_initializer)) __attribute__((unavailable("error"))); +- (instancetype)initWithWarning:(int32_t)warning __attribute__((swift_name("init(warning:)"))) __attribute__((objc_designated_initializer)) __attribute__((deprecated("warning"))); +- (instancetype)initWithNormal:(int64_t)normal __attribute__((swift_name("init(normal:)"))) __attribute__((objc_designated_initializer)); +- (instancetype)init __attribute__((swift_name("init()"))) __attribute__((objc_designated_initializer)); ++ (instancetype)new __attribute__((availability(swift, unavailable, message="use object initializers instead"))); +- (int32_t)callEffectivelyHiddenObj:(id)obj __attribute__((swift_name("callEffectivelyHidden(obj:)"))); +- (id)getHidden __attribute__((swift_name("getHidden()"))); +- (KtTestDeprecationError *)getError __attribute__((swift_name("getError()"))); +- (void)error __attribute__((swift_name("error()"))) __attribute__((unavailable("error"))); +- (void)openError __attribute__((swift_name("openError()"))) __attribute__((unavailable("error"))); +- (KtTestDeprecationWarning *)getWarning __attribute__((swift_name("getWarning()"))); +- (void)warning __attribute__((swift_name("warning()"))) __attribute__((deprecated("warning"))); +- (void)openWarning __attribute__((swift_name("openWarning()"))) __attribute__((deprecated("warning"))); +- (void)normal __attribute__((swift_name("normal()"))); +- (int32_t)openNormal __attribute__((swift_name("openNormal()"))); +- (void)testHiddenNested:(id)hiddenNested __attribute__((swift_name("test(hiddenNested:)"))); +- (void)testHiddenNestedNested:(id)hiddenNestedNested __attribute__((swift_name("test(hiddenNestedNested:)"))); +- (void)testHiddenNestedInner:(id)hiddenNestedInner __attribute__((swift_name("test(hiddenNestedInner:)"))); +- (void)testHiddenInner:(id)hiddenInner __attribute__((swift_name("test(hiddenInner:)"))); +- (void)testHiddenInnerInner:(id)hiddenInnerInner __attribute__((swift_name("test(hiddenInnerInner:)"))); +- (void)testTopLevelHidden:(id)topLevelHidden __attribute__((swift_name("test(topLevelHidden:)"))); +- (void)testTopLevelHiddenNested:(id)topLevelHiddenNested __attribute__((swift_name("test(topLevelHiddenNested:)"))); +- (void)testTopLevelHiddenNestedNested:(id)topLevelHiddenNestedNested __attribute__((swift_name("test(topLevelHiddenNestedNested:)"))); +- (void)testTopLevelHiddenNestedInner:(id)topLevelHiddenNestedInner __attribute__((swift_name("test(topLevelHiddenNestedInner:)"))); +- (void)testTopLevelHiddenInner:(id)topLevelHiddenInner __attribute__((swift_name("test(topLevelHiddenInner:)"))); +- (void)testTopLevelHiddenInnerInner:(id)topLevelHiddenInnerInner __attribute__((swift_name("test(topLevelHiddenInnerInner:)"))); +- (void)testExtendingHiddenNested:(id)extendingHiddenNested __attribute__((swift_name("test(extendingHiddenNested:)"))); +- (void)testExtendingNestedInHidden:(id)extendingNestedInHidden __attribute__((swift_name("test(extendingNestedInHidden:)"))); +@property (readonly) id _Nullable errorVal __attribute__((swift_name("errorVal"))) __attribute__((unavailable("error"))); +@property id _Nullable errorVar __attribute__((swift_name("errorVar"))) __attribute__((unavailable("error"))); +@property (readonly) id _Nullable openErrorVal __attribute__((swift_name("openErrorVal"))) __attribute__((unavailable("error"))); +@property id _Nullable openErrorVar __attribute__((swift_name("openErrorVar"))) __attribute__((unavailable("error"))); +@property (readonly) id _Nullable warningVal __attribute__((swift_name("warningVal"))) __attribute__((deprecated("warning"))); +@property id _Nullable warningVar __attribute__((swift_name("warningVar"))) __attribute__((deprecated("warning"))); +@property (readonly) id _Nullable openWarningVal __attribute__((swift_name("openWarningVal"))) __attribute__((deprecated("warning"))); +@property id _Nullable openWarningVar __attribute__((swift_name("openWarningVar"))) __attribute__((deprecated("warning"))); +@property (readonly) id _Nullable normalVal __attribute__((swift_name("normalVal"))); +@property id _Nullable normalVar __attribute__((swift_name("normalVar"))); +@property (readonly) id _Nullable openNormalVal __attribute__((swift_name("openNormalVal"))); +@property id _Nullable openNormalVar __attribute__((swift_name("openNormalVar"))); +@end; + +__attribute__((swift_name("TestDeprecation.OpenHidden"))) +@interface KtTestDeprecationOpenHidden : NSObject +@end; + +__attribute__((objc_subclassing_restricted)) +__attribute__((swift_name("TestDeprecation.ExtendingHidden"))) +@interface KtTestDeprecationExtendingHidden : NSObject +@end; + +__attribute__((objc_subclassing_restricted)) +__attribute__((swift_name("TestDeprecation.ExtendingHiddenNested"))) +@interface KtTestDeprecationExtendingHiddenNested : NSObject +@end; + +__attribute__((swift_name("TestDeprecationHiddenInterface"))) +@protocol KtTestDeprecationHiddenInterface +@required +@end; + +__attribute__((swift_name("TestDeprecation.ImplementingHidden"))) +@interface KtTestDeprecationImplementingHidden : KtBase +- (instancetype)init __attribute__((swift_name("init()"))) __attribute__((objc_designated_initializer)); ++ (instancetype)new __attribute__((availability(swift, unavailable, message="use object initializers instead"))); +- (int32_t)effectivelyHidden __attribute__((swift_name("effectivelyHidden()"))); +@end; + +__attribute__((objc_subclassing_restricted)) +__attribute__((swift_name("TestDeprecation.Hidden"))) +@interface KtTestDeprecationHidden : NSObject +@end; + +__attribute__((swift_name("TestDeprecation.HiddenNested"))) +@interface KtTestDeprecationHiddenNested : NSObject +@end; + +__attribute__((objc_subclassing_restricted)) +__attribute__((swift_name("TestDeprecation.HiddenNestedNested"))) +@interface KtTestDeprecationHiddenNestedNested : NSObject +@end; + +__attribute__((objc_subclassing_restricted)) +__attribute__((swift_name("TestDeprecation.HiddenNestedInner"))) +@interface KtTestDeprecationHiddenNestedInner : NSObject +@end; + +__attribute__((objc_subclassing_restricted)) +__attribute__((swift_name("TestDeprecation.HiddenInner"))) +@interface KtTestDeprecationHiddenInner : NSObject +@end; + +__attribute__((objc_subclassing_restricted)) +__attribute__((swift_name("TestDeprecation.HiddenInnerInner"))) +@interface KtTestDeprecationHiddenInnerInner : NSObject +@end; + +__attribute__((objc_subclassing_restricted)) +__attribute__((swift_name("TestDeprecation.ExtendingNestedInHidden"))) +@interface KtTestDeprecationExtendingNestedInHidden : NSObject +@end; + +__attribute__((swift_name("TestDeprecation.OpenError"))) +@interface KtTestDeprecationOpenError : KtTestDeprecation +- (instancetype)init __attribute__((swift_name("init()"))) __attribute__((objc_designated_initializer)) __attribute__((unavailable("error"))); ++ (instancetype)new __attribute__((availability(swift, unavailable, message="use object initializers instead"))); +- (instancetype)initWithError:(int16_t)error __attribute__((swift_name("init(error:)"))) __attribute__((objc_designated_initializer)) __attribute__((unavailable)); +- (instancetype)initWithWarning:(int32_t)warning __attribute__((swift_name("init(warning:)"))) __attribute__((objc_designated_initializer)) __attribute__((unavailable)); +- (instancetype)initWithNormal:(int64_t)normal __attribute__((swift_name("init(normal:)"))) __attribute__((objc_designated_initializer)) __attribute__((unavailable)); +@end; + +__attribute__((objc_subclassing_restricted)) +__attribute__((swift_name("TestDeprecation.ExtendingError"))) +@interface KtTestDeprecationExtendingError : KtTestDeprecationOpenError +- (instancetype)init __attribute__((swift_name("init()"))) __attribute__((objc_designated_initializer)); ++ (instancetype)new __attribute__((availability(swift, unavailable, message="use object initializers instead"))); +@end; + +__attribute__((swift_name("TestDeprecationErrorInterface"))) +@protocol KtTestDeprecationErrorInterface +@required +@end; + +__attribute__((objc_subclassing_restricted)) +__attribute__((swift_name("TestDeprecation.ImplementingError"))) +@interface KtTestDeprecationImplementingError : KtBase +- (instancetype)init __attribute__((swift_name("init()"))) __attribute__((objc_designated_initializer)); ++ (instancetype)new __attribute__((availability(swift, unavailable, message="use object initializers instead"))); +@end; + +__attribute__((objc_subclassing_restricted)) +__attribute__((swift_name("TestDeprecation.Error"))) +@interface KtTestDeprecationError : KtTestDeprecation +- (instancetype)init __attribute__((swift_name("init()"))) __attribute__((objc_designated_initializer)) __attribute__((unavailable("error"))); ++ (instancetype)new __attribute__((availability(swift, unavailable, message="use object initializers instead"))); +- (instancetype)initWithError:(int16_t)error __attribute__((swift_name("init(error:)"))) __attribute__((objc_designated_initializer)) __attribute__((unavailable)); +- (instancetype)initWithWarning:(int32_t)warning __attribute__((swift_name("init(warning:)"))) __attribute__((objc_designated_initializer)) __attribute__((unavailable)); +- (instancetype)initWithNormal:(int64_t)normal __attribute__((swift_name("init(normal:)"))) __attribute__((objc_designated_initializer)) __attribute__((unavailable)); +@end; + +__attribute__((swift_name("TestDeprecation.OpenWarning"))) +@interface KtTestDeprecationOpenWarning : KtTestDeprecation +- (instancetype)init __attribute__((swift_name("init()"))) __attribute__((objc_designated_initializer)) __attribute__((deprecated("warning"))); ++ (instancetype)new __attribute__((availability(swift, unavailable, message="use object initializers instead"))); +- (instancetype)initWithError:(int16_t)error __attribute__((swift_name("init(error:)"))) __attribute__((objc_designated_initializer)) __attribute__((unavailable)); +- (instancetype)initWithWarning:(int32_t)warning __attribute__((swift_name("init(warning:)"))) __attribute__((objc_designated_initializer)) __attribute__((unavailable)); +- (instancetype)initWithNormal:(int64_t)normal __attribute__((swift_name("init(normal:)"))) __attribute__((objc_designated_initializer)) __attribute__((unavailable)); +@end; + +__attribute__((objc_subclassing_restricted)) +__attribute__((swift_name("TestDeprecation.ExtendingWarning"))) +@interface KtTestDeprecationExtendingWarning : KtTestDeprecationOpenWarning +- (instancetype)init __attribute__((swift_name("init()"))) __attribute__((objc_designated_initializer)); ++ (instancetype)new __attribute__((availability(swift, unavailable, message="use object initializers instead"))); +@end; + +__attribute__((swift_name("TestDeprecationWarningInterface"))) +@protocol KtTestDeprecationWarningInterface +@required +@end; + +__attribute__((objc_subclassing_restricted)) +__attribute__((swift_name("TestDeprecation.ImplementingWarning"))) +@interface KtTestDeprecationImplementingWarning : KtBase +- (instancetype)init __attribute__((swift_name("init()"))) __attribute__((objc_designated_initializer)); ++ (instancetype)new __attribute__((availability(swift, unavailable, message="use object initializers instead"))); +@end; + +__attribute__((objc_subclassing_restricted)) +__attribute__((swift_name("TestDeprecation.Warning"))) +@interface KtTestDeprecationWarning : KtTestDeprecation +- (instancetype)init __attribute__((swift_name("init()"))) __attribute__((objc_designated_initializer)) __attribute__((deprecated("warning"))); ++ (instancetype)new __attribute__((availability(swift, unavailable, message="use object initializers instead"))); +- (instancetype)initWithError:(int16_t)error __attribute__((swift_name("init(error:)"))) __attribute__((objc_designated_initializer)) __attribute__((unavailable)); +- (instancetype)initWithWarning:(int32_t)warning __attribute__((swift_name("init(warning:)"))) __attribute__((objc_designated_initializer)) __attribute__((unavailable)); +- (instancetype)initWithNormal:(int64_t)normal __attribute__((swift_name("init(normal:)"))) __attribute__((objc_designated_initializer)) __attribute__((unavailable)); +@end; + +__attribute__((objc_subclassing_restricted)) +__attribute__((swift_name("TestDeprecation.HiddenOverride"))) +@interface KtTestDeprecationHiddenOverride : KtTestDeprecation +- (instancetype)init __attribute__((swift_name("init()"))) __attribute__((objc_designated_initializer)); ++ (instancetype)new __attribute__((availability(swift, unavailable, message="use object initializers instead"))); +- (instancetype)initWithError:(int16_t)error __attribute__((swift_name("init(error:)"))) __attribute__((objc_designated_initializer)) __attribute__((unavailable)); +- (instancetype)initWithWarning:(int32_t)warning __attribute__((swift_name("init(warning:)"))) __attribute__((objc_designated_initializer)) __attribute__((unavailable)); +- (instancetype)initWithNormal:(int64_t)normal __attribute__((swift_name("init(normal:)"))) __attribute__((objc_designated_initializer)) __attribute__((unavailable)); +- (void)openError __attribute__((swift_name("openError()"))) __attribute__((unavailable("hidden"))); +- (void)openWarning __attribute__((swift_name("openWarning()"))) __attribute__((unavailable("hidden"))); +- (int32_t)openNormal __attribute__((swift_name("openNormal()"))) __attribute__((unavailable("hidden"))); +@property (readonly) id _Nullable openErrorVal __attribute__((swift_name("openErrorVal"))) __attribute__((unavailable("hidden"))); +@property id _Nullable openErrorVar __attribute__((swift_name("openErrorVar"))) __attribute__((unavailable("hidden"))); +@property (readonly) id _Nullable openWarningVal __attribute__((swift_name("openWarningVal"))) __attribute__((unavailable("hidden"))); +@property id _Nullable openWarningVar __attribute__((swift_name("openWarningVar"))) __attribute__((unavailable("hidden"))); +@property (readonly) id _Nullable openNormalVal __attribute__((swift_name("openNormalVal"))) __attribute__((unavailable("hidden"))); +@property id _Nullable openNormalVar __attribute__((swift_name("openNormalVar"))) __attribute__((unavailable("hidden"))); +@end; + +__attribute__((objc_subclassing_restricted)) +__attribute__((swift_name("TestDeprecation.ErrorOverride"))) +@interface KtTestDeprecationErrorOverride : KtTestDeprecation +- (instancetype)initWithHidden:(int8_t)hidden __attribute__((swift_name("init(hidden:)"))) __attribute__((objc_designated_initializer)) __attribute__((unavailable("error"))); +- (instancetype)initWithError:(int16_t)error __attribute__((swift_name("init(error:)"))) __attribute__((objc_designated_initializer)) __attribute__((unavailable("error"))); +- (instancetype)initWithWarning:(int32_t)warning __attribute__((swift_name("init(warning:)"))) __attribute__((objc_designated_initializer)) __attribute__((unavailable("error"))); +- (instancetype)initWithNormal:(int64_t)normal __attribute__((swift_name("init(normal:)"))) __attribute__((objc_designated_initializer)) __attribute__((unavailable("error"))); +- (instancetype)init __attribute__((swift_name("init()"))) __attribute__((objc_designated_initializer)); ++ (instancetype)new __attribute__((availability(swift, unavailable, message="use object initializers instead"))); +- (void)openHidden __attribute__((swift_name("openHidden()"))) __attribute__((unavailable("error"))); +- (void)openError __attribute__((swift_name("openError()"))) __attribute__((unavailable("error"))); +- (void)openWarning __attribute__((swift_name("openWarning()"))) __attribute__((unavailable("error"))); +- (int32_t)openNormal __attribute__((swift_name("openNormal()"))) __attribute__((unavailable("error"))); +@property (readonly) id _Nullable openHiddenVal __attribute__((swift_name("openHiddenVal"))) __attribute__((unavailable("error"))); +@property id _Nullable openHiddenVar __attribute__((swift_name("openHiddenVar"))) __attribute__((unavailable("error"))); +@property (readonly) id _Nullable openErrorVal __attribute__((swift_name("openErrorVal"))) __attribute__((unavailable("error"))); +@property id _Nullable openErrorVar __attribute__((swift_name("openErrorVar"))) __attribute__((unavailable("error"))); +@property (readonly) id _Nullable openWarningVal __attribute__((swift_name("openWarningVal"))) __attribute__((unavailable("error"))); +@property id _Nullable openWarningVar __attribute__((swift_name("openWarningVar"))) __attribute__((unavailable("error"))); +@property (readonly) id _Nullable openNormalVal __attribute__((swift_name("openNormalVal"))) __attribute__((unavailable("error"))); +@property id _Nullable openNormalVar __attribute__((swift_name("openNormalVar"))) __attribute__((unavailable("error"))); +@end; + +__attribute__((objc_subclassing_restricted)) +__attribute__((swift_name("TestDeprecation.WarningOverride"))) +@interface KtTestDeprecationWarningOverride : KtTestDeprecation +- (instancetype)initWithHidden:(int8_t)hidden __attribute__((swift_name("init(hidden:)"))) __attribute__((objc_designated_initializer)) __attribute__((deprecated("warning"))); +- (instancetype)initWithError:(int16_t)error __attribute__((swift_name("init(error:)"))) __attribute__((objc_designated_initializer)) __attribute__((deprecated("warning"))); +- (instancetype)initWithWarning:(int32_t)warning __attribute__((swift_name("init(warning:)"))) __attribute__((objc_designated_initializer)) __attribute__((deprecated("warning"))); +- (instancetype)initWithNormal:(int64_t)normal __attribute__((swift_name("init(normal:)"))) __attribute__((objc_designated_initializer)) __attribute__((deprecated("warning"))); +- (instancetype)init __attribute__((swift_name("init()"))) __attribute__((objc_designated_initializer)); ++ (instancetype)new __attribute__((availability(swift, unavailable, message="use object initializers instead"))); +- (void)openHidden __attribute__((swift_name("openHidden()"))) __attribute__((deprecated("warning"))); +- (void)openError __attribute__((swift_name("openError()"))) __attribute__((deprecated("warning"))); +- (void)openWarning __attribute__((swift_name("openWarning()"))) __attribute__((deprecated("warning"))); +- (int32_t)openNormal __attribute__((swift_name("openNormal()"))) __attribute__((deprecated("warning"))); +@property (readonly) id _Nullable openHiddenVal __attribute__((swift_name("openHiddenVal"))) __attribute__((deprecated("warning"))); +@property id _Nullable openHiddenVar __attribute__((swift_name("openHiddenVar"))) __attribute__((deprecated("warning"))); +@property (readonly) id _Nullable openErrorVal __attribute__((swift_name("openErrorVal"))) __attribute__((deprecated("warning"))); +@property id _Nullable openErrorVar __attribute__((swift_name("openErrorVar"))) __attribute__((deprecated("warning"))); +@property (readonly) id _Nullable openWarningVal __attribute__((swift_name("openWarningVal"))) __attribute__((deprecated("warning"))); +@property id _Nullable openWarningVar __attribute__((swift_name("openWarningVar"))) __attribute__((deprecated("warning"))); +@property (readonly) id _Nullable openNormalVal __attribute__((swift_name("openNormalVal"))) __attribute__((deprecated("warning"))); +@property id _Nullable openNormalVar __attribute__((swift_name("openNormalVar"))) __attribute__((deprecated("warning"))); +@end; + +__attribute__((objc_subclassing_restricted)) +__attribute__((swift_name("TestDeprecation.NormalOverride"))) +@interface KtTestDeprecationNormalOverride : KtTestDeprecation +- (instancetype)initWithHidden:(int8_t)hidden __attribute__((swift_name("init(hidden:)"))) __attribute__((objc_designated_initializer)); +- (instancetype)initWithError:(int16_t)error __attribute__((swift_name("init(error:)"))) __attribute__((objc_designated_initializer)); +- (instancetype)initWithWarning:(int32_t)warning __attribute__((swift_name("init(warning:)"))) __attribute__((objc_designated_initializer)); +- (instancetype)initWithNormal:(int64_t)normal __attribute__((swift_name("init(normal:)"))) __attribute__((objc_designated_initializer)); +- (instancetype)init __attribute__((swift_name("init()"))) __attribute__((objc_designated_initializer)); ++ (instancetype)new __attribute__((availability(swift, unavailable, message="use object initializers instead"))); +- (void)openError __attribute__((swift_name("openError()"))) __attribute__((unavailable("Overrides deprecated member in 'conversions.TestDeprecation'. error"))); +- (void)openWarning __attribute__((swift_name("openWarning()"))) __attribute__((deprecated("Overrides deprecated member in 'conversions.TestDeprecation'. warning"))); +- (int32_t)openNormal __attribute__((swift_name("openNormal()"))); +@property (readonly) id _Nullable openErrorVal __attribute__((swift_name("openErrorVal"))) __attribute__((unavailable("Overrides deprecated member in 'conversions.TestDeprecation'. error"))); +@property id _Nullable openErrorVar __attribute__((swift_name("openErrorVar"))) __attribute__((unavailable("Overrides deprecated member in 'conversions.TestDeprecation'. error"))); +@property (readonly) id _Nullable openWarningVal __attribute__((swift_name("openWarningVal"))) __attribute__((deprecated("Overrides deprecated member in 'conversions.TestDeprecation'. warning"))); +@property id _Nullable openWarningVar __attribute__((swift_name("openWarningVar"))) __attribute__((deprecated("Overrides deprecated member in 'conversions.TestDeprecation'. warning"))); +@property (readonly) id _Nullable openNormalVal __attribute__((swift_name("openNormalVal"))); +@property id _Nullable openNormalVar __attribute__((swift_name("openNormalVar"))); +@end; + +__attribute__((objc_subclassing_restricted)) +__attribute__((swift_name("TopLevelHidden"))) +@interface KtTopLevelHidden : NSObject +@end; + +__attribute__((objc_subclassing_restricted)) +__attribute__((swift_name("TopLevelHidden.Nested"))) +@interface KtTopLevelHiddenNested : NSObject +@end; + +__attribute__((objc_subclassing_restricted)) +__attribute__((swift_name("TopLevelHidden.NestedNested"))) +@interface KtTopLevelHiddenNestedNested : NSObject +@end; + +__attribute__((objc_subclassing_restricted)) +__attribute__((swift_name("TopLevelHidden.NestedInner"))) +@interface KtTopLevelHiddenNestedInner : NSObject +@end; + +__attribute__((objc_subclassing_restricted)) +__attribute__((swift_name("TopLevelHidden.Inner"))) +@interface KtTopLevelHiddenInner : NSObject +@end; + +__attribute__((objc_subclassing_restricted)) +__attribute__((swift_name("TopLevelHidden.InnerInner"))) +@interface KtTopLevelHiddenInnerInner : NSObject +@end; + +__attribute__((objc_subclassing_restricted)) +__attribute__((swift_name("TestWeakRefs"))) +@interface KtTestWeakRefs : KtBase +- (instancetype)initWithFrozen:(BOOL)frozen __attribute__((swift_name("init(frozen:)"))) __attribute__((objc_designated_initializer)); +- (id)getObj __attribute__((swift_name("getObj()"))); +- (void)clearObj __attribute__((swift_name("clearObj()"))); +- (NSArray *)createCycle __attribute__((swift_name("createCycle()"))); +@end; + +__attribute__((objc_subclassing_restricted)) +__attribute__((swift_name("SharedRefs"))) +@interface KtSharedRefs : KtBase +- (instancetype)init __attribute__((swift_name("init()"))) __attribute__((objc_designated_initializer)); ++ (instancetype)new __attribute__((availability(swift, unavailable, message="use object initializers instead"))); +- (KtSharedRefsMutableData *)createRegularObject __attribute__((swift_name("createRegularObject()"))); +- (void (^)(void))createLambda __attribute__((swift_name("createLambda()"))); +- (NSMutableArray *)createCollection __attribute__((swift_name("createCollection()"))); +- (KtSharedRefsMutableData *)createFrozenRegularObject __attribute__((swift_name("createFrozenRegularObject()"))); +- (void (^)(void))createFrozenLambda __attribute__((swift_name("createFrozenLambda()"))); +- (NSMutableArray *)createFrozenCollection __attribute__((swift_name("createFrozenCollection()"))); +- (BOOL)hasAliveObjects __attribute__((swift_name("hasAliveObjects()"))); +@end; + +__attribute__((objc_subclassing_restricted)) +__attribute__((swift_name("SharedRefs.MutableData"))) +@interface KtSharedRefsMutableData : KtBase +- (instancetype)init __attribute__((swift_name("init()"))) __attribute__((objc_designated_initializer)); ++ (instancetype)new __attribute__((availability(swift, unavailable, message="use object initializers instead"))); +- (void)update __attribute__((swift_name("update()"))); +@property int32_t x __attribute__((swift_name("x"))); +@end; + +__attribute__((swift_name("TestRememberNewObject"))) +@protocol KtTestRememberNewObject +@required +- (id)getObject __attribute__((swift_name("getObject()"))); +- (void)waitForCleanup __attribute__((swift_name("waitForCleanup()"))); +@end; + +__attribute__((swift_name("ClassForTypeCheck"))) +@interface KtClassForTypeCheck : KtBase +- (instancetype)init __attribute__((swift_name("init()"))) __attribute__((objc_designated_initializer)); ++ (instancetype)new __attribute__((availability(swift, unavailable, message="use object initializers instead"))); +@end; + +__attribute__((swift_name("InterfaceForTypeCheck"))) +@protocol KtInterfaceForTypeCheck +@required +@end; + +__attribute__((swift_name("IAbstractInterface"))) +@protocol KtIAbstractInterface +@required +- (int32_t)foo __attribute__((swift_name("foo()"))); +@end; + +__attribute__((swift_name("IAbstractInterface2"))) +@protocol KtIAbstractInterface2 +@required +- (int32_t)foo __attribute__((swift_name("foo()"))); +@end; + +__attribute__((swift_name("AbstractInterfaceBase"))) +@interface KtAbstractInterfaceBase : KtBase +- (instancetype)init __attribute__((swift_name("init()"))) __attribute__((objc_designated_initializer)); ++ (instancetype)new __attribute__((availability(swift, unavailable, message="use object initializers instead"))); +- (int32_t)foo __attribute__((swift_name("foo()"))); +- (int32_t)bar __attribute__((swift_name("bar()"))); +@end; + +__attribute__((swift_name("AbstractInterfaceBase2"))) +@interface KtAbstractInterfaceBase2 : KtBase +- (instancetype)init __attribute__((swift_name("init()"))) __attribute__((objc_designated_initializer)); ++ (instancetype)new __attribute__((availability(swift, unavailable, message="use object initializers instead"))); +@end; + +__attribute__((swift_name("AbstractInterfaceBase3"))) +@interface KtAbstractInterfaceBase3 : KtBase +- (instancetype)init __attribute__((swift_name("init()"))) __attribute__((objc_designated_initializer)); ++ (instancetype)new __attribute__((availability(swift, unavailable, message="use object initializers instead"))); +- (int32_t)foo __attribute__((swift_name("foo()"))); +@end; + +__attribute__((swift_name("GH3525Base"))) +@interface KtGH3525Base : KtBase +- (instancetype)init __attribute__((swift_name("init()"))) __attribute__((objc_designated_initializer)); ++ (instancetype)new __attribute__((availability(swift, unavailable, message="use object initializers instead"))); +@end; + +__attribute__((objc_subclassing_restricted)) +__attribute__((swift_name("GH3525"))) +@interface KtGH3525 : KtGH3525Base ++ (instancetype)alloc __attribute__((unavailable)); ++ (instancetype)allocWithZone:(struct _NSZone *)zone __attribute__((unavailable)); +- (instancetype)init __attribute__((swift_name("init()"))) __attribute__((objc_designated_initializer)) __attribute__((unavailable)); ++ (instancetype)new __attribute__((unavailable)); ++ (instancetype)gH3525 __attribute__((swift_name("init()"))); +@end; + +__attribute__((objc_subclassing_restricted)) +__attribute__((swift_name("TestStringConversion"))) +@interface KtTestStringConversion : KtBase +- (instancetype)init __attribute__((swift_name("init()"))) __attribute__((objc_designated_initializer)); ++ (instancetype)new __attribute__((availability(swift, unavailable, message="use object initializers instead"))); +@property id str __attribute__((swift_name("str"))); +@end; + +__attribute__((swift_name("GH3825"))) +@protocol KtGH3825 +@required + +/** + @note This method converts instances of MyException to errors. + Other uncaught Kotlin exceptions are fatal. +*/ +- (BOOL)call0AndReturnError:(NSError * _Nullable * _Nullable)error callback:(KtBoolean *(^)(void))callback __attribute__((swift_name("call0(callback:)"))); + +/** + @note This method converts instances of MyException to errors. + Other uncaught Kotlin exceptions are fatal. +*/ +- (BOOL)call1DoThrow:(BOOL)doThrow error:(NSError * _Nullable * _Nullable)error callback:(void (^)(void))callback __attribute__((swift_name("call1(doThrow:callback:)"))); + +/** + @note This method converts instances of MyException to errors. + Other uncaught Kotlin exceptions are fatal. +*/ +- (BOOL)call2Callback:(void (^)(void))callback doThrow:(BOOL)doThrow error:(NSError * _Nullable * _Nullable)error __attribute__((swift_name("call2(callback:doThrow:)"))); +@end; + +__attribute__((objc_subclassing_restricted)) +__attribute__((swift_name("GH3825KotlinImpl"))) +@interface KtGH3825KotlinImpl : KtBase +- (instancetype)init __attribute__((swift_name("init()"))) __attribute__((objc_designated_initializer)); ++ (instancetype)new __attribute__((availability(swift, unavailable, message="use object initializers instead"))); + +/** + @note This method converts instances of MyException to errors. + Other uncaught Kotlin exceptions are fatal. +*/ +- (BOOL)call0AndReturnError:(NSError * _Nullable * _Nullable)error callback:(KtBoolean *(^)(void))callback __attribute__((swift_name("call0(callback:)"))); + +/** + @note This method converts instances of MyException to errors. + Other uncaught Kotlin exceptions are fatal. +*/ +- (BOOL)call1DoThrow:(BOOL)doThrow error:(NSError * _Nullable * _Nullable)error callback:(void (^)(void))callback __attribute__((swift_name("call1(doThrow:callback:)"))); + +/** + @note This method converts instances of MyException to errors. + Other uncaught Kotlin exceptions are fatal. +*/ +- (BOOL)call2Callback:(void (^)(void))callback doThrow:(BOOL)doThrow error:(NSError * _Nullable * _Nullable)error __attribute__((swift_name("call2(callback:doThrow:)"))); +@end; + +@interface KtEnumeration (ValuesKt) +- (KtEnumeration *)getAnswer __attribute__((swift_name("getAnswer()"))); +@end; + +__attribute__((objc_subclassing_restricted)) +__attribute__((swift_name("ValuesKt"))) +@interface KtValuesKt : KtBase ++ (KtBoolean * _Nullable)boxBooleanValue:(BOOL)booleanValue __attribute__((swift_name("box(booleanValue:)"))); ++ (KtByte * _Nullable)boxByteValue:(int8_t)byteValue __attribute__((swift_name("box(byteValue:)"))); ++ (KtShort * _Nullable)boxShortValue:(int16_t)shortValue __attribute__((swift_name("box(shortValue:)"))); ++ (KtInt * _Nullable)boxIntValue:(int32_t)intValue __attribute__((swift_name("box(intValue:)"))); ++ (KtLong * _Nullable)boxLongValue:(int64_t)longValue __attribute__((swift_name("box(longValue:)"))); ++ (KtUByte * _Nullable)boxUByteValue:(uint8_t)uByteValue __attribute__((swift_name("box(uByteValue:)"))); ++ (KtUShort * _Nullable)boxUShortValue:(uint16_t)uShortValue __attribute__((swift_name("box(uShortValue:)"))); ++ (KtUInt * _Nullable)boxUIntValue:(uint32_t)uIntValue __attribute__((swift_name("box(uIntValue:)"))); ++ (KtULong * _Nullable)boxULongValue:(uint64_t)uLongValue __attribute__((swift_name("box(uLongValue:)"))); ++ (KtFloat * _Nullable)boxFloatValue:(float)floatValue __attribute__((swift_name("box(floatValue:)"))); ++ (KtDouble * _Nullable)boxDoubleValue:(double)doubleValue __attribute__((swift_name("box(doubleValue:)"))); ++ (void)ensureEqualBooleansActual:(KtBoolean * _Nullable)actual expected:(BOOL)expected __attribute__((swift_name("ensureEqualBooleans(actual:expected:)"))); ++ (void)ensureEqualBytesActual:(KtByte * _Nullable)actual expected:(int8_t)expected __attribute__((swift_name("ensureEqualBytes(actual:expected:)"))); ++ (void)ensureEqualShortsActual:(KtShort * _Nullable)actual expected:(int16_t)expected __attribute__((swift_name("ensureEqualShorts(actual:expected:)"))); ++ (void)ensureEqualIntsActual:(KtInt * _Nullable)actual expected:(int32_t)expected __attribute__((swift_name("ensureEqualInts(actual:expected:)"))); ++ (void)ensureEqualLongsActual:(KtLong * _Nullable)actual expected:(int64_t)expected __attribute__((swift_name("ensureEqualLongs(actual:expected:)"))); ++ (void)ensureEqualUBytesActual:(KtUByte * _Nullable)actual expected:(uint8_t)expected __attribute__((swift_name("ensureEqualUBytes(actual:expected:)"))); ++ (void)ensureEqualUShortsActual:(KtUShort * _Nullable)actual expected:(uint16_t)expected __attribute__((swift_name("ensureEqualUShorts(actual:expected:)"))); ++ (void)ensureEqualUIntsActual:(KtUInt * _Nullable)actual expected:(uint32_t)expected __attribute__((swift_name("ensureEqualUInts(actual:expected:)"))); ++ (void)ensureEqualULongsActual:(KtULong * _Nullable)actual expected:(uint64_t)expected __attribute__((swift_name("ensureEqualULongs(actual:expected:)"))); ++ (void)ensureEqualFloatsActual:(KtFloat * _Nullable)actual expected:(float)expected __attribute__((swift_name("ensureEqualFloats(actual:expected:)"))); ++ (void)ensureEqualDoublesActual:(KtDouble * _Nullable)actual expected:(double)expected __attribute__((swift_name("ensureEqualDoubles(actual:expected:)"))); ++ (void)emptyFun __attribute__((swift_name("emptyFun()"))); ++ (NSString *)strFun __attribute__((swift_name("strFun()"))); ++ (id)argsFunI:(int32_t)i l:(int64_t)l d:(double)d s:(NSString *)s __attribute__((swift_name("argsFun(i:l:d:s:)"))); ++ (NSString *)funArgumentFoo:(NSString *(^)(void))foo __attribute__((swift_name("funArgument(foo:)"))); ++ (id _Nullable)genericFooT:(id _Nullable)t foo:(id _Nullable (^)(id _Nullable))foo __attribute__((swift_name("genericFoo(t:foo:)"))); ++ (id)fooGenericNumberR:(id)r foo:(id (^)(id))foo __attribute__((swift_name("fooGenericNumber(r:foo:)"))); ++ (NSArray *)varargToListArgs:(KtKotlinArray *)args __attribute__((swift_name("varargToList(args:)"))); ++ (NSString *)subExt:(NSString *)receiver i:(int32_t)i __attribute__((swift_name("subExt(_:i:)"))); ++ (NSString *)toString:(id _Nullable)receiver __attribute__((swift_name("toString(_:)"))); ++ (void)print:(id _Nullable)receiver __attribute__((swift_name("print(_:)"))); ++ (id _Nullable)boxChar:(unichar)receiver __attribute__((swift_name("boxChar(_:)"))); ++ (BOOL)isA:(id _Nullable)receiver __attribute__((swift_name("isA(_:)"))); ++ (NSString *)iFunExt:(id)receiver __attribute__((swift_name("iFunExt(_:)"))); ++ (KtEnumeration *)passEnum __attribute__((swift_name("passEnum()"))); ++ (void)receiveEnumE:(int32_t)e __attribute__((swift_name("receiveEnum(e:)"))); ++ (KtEnumeration *)getValue:(int32_t)value __attribute__((swift_name("get(value:)"))); ++ (KtWithCompanionAndObjectCompanion *)getCompanionObject __attribute__((swift_name("getCompanionObject()"))); ++ (KtWithCompanionAndObjectNamed *)getNamedObject __attribute__((swift_name("getNamedObject()"))); ++ (KtOpenClassI *)getNamedObjectInterface __attribute__((swift_name("getNamedObjectInterface()"))); ++ (id)boxIc1:(int32_t)ic1 __attribute__((swift_name("box(ic1:)"))); ++ (id)boxIc2:(id)ic2 __attribute__((swift_name("box(ic2:)"))); ++ (id)boxIc3:(id _Nullable)ic3 __attribute__((swift_name("box(ic3:)"))); ++ (NSString *)concatenateInlineClassValuesIc1:(int32_t)ic1 ic1N:(id _Nullable)ic1N ic2:(id)ic2 ic2N:(id _Nullable)ic2N ic3:(id _Nullable)ic3 ic3N:(id _Nullable)ic3N __attribute__((swift_name("concatenateInlineClassValues(ic1:ic1N:ic2:ic2N:ic3:ic3N:)"))); ++ (int32_t)getValue1:(int32_t)receiver __attribute__((swift_name("getValue1(_:)"))); ++ (KtInt * _Nullable)getValueOrNull1:(id _Nullable)receiver __attribute__((swift_name("getValueOrNull1(_:)"))); ++ (NSString *)getValue2:(id)receiver __attribute__((swift_name("getValue2(_:)"))); ++ (NSString * _Nullable)getValueOrNull2:(id _Nullable)receiver __attribute__((swift_name("getValueOrNull2(_:)"))); ++ (KtTripleVals * _Nullable)getValue3:(id _Nullable)receiver __attribute__((swift_name("getValue3(_:)"))); ++ (KtTripleVals * _Nullable)getValueOrNull3:(id _Nullable)receiver __attribute__((swift_name("getValueOrNull3(_:)"))); ++ (BOOL)isFrozenObj:(id)obj __attribute__((swift_name("isFrozen(obj:)"))); ++ (id)kotlinLambdaBlock:(id (^)(id))block __attribute__((swift_name("kotlinLambda(block:)"))); ++ (int64_t)multiplyInt:(int32_t)int_ long:(int64_t)long_ __attribute__((swift_name("multiply(int:long:)"))); + +/** + @note This method converts instances of MyException, MyError to errors. + Other uncaught Kotlin exceptions are fatal. +*/ ++ (BOOL)throwExceptionError:(BOOL)error error:(NSError * _Nullable * _Nullable)error_ __attribute__((swift_name("throwException(error:)"))); + +/** + @note This method converts all Kotlin exceptions to errors. +*/ ++ (KtKotlinObjCErrorException * _Nullable)testSwiftThrowingMethods:(id)methods error:(NSError * _Nullable * _Nullable)error __attribute__((swift_name("testSwiftThrowing(methods:)"))); + +/** + @note This method converts all Kotlin exceptions to errors. +*/ ++ (BOOL)testSwiftNotThrowingMethods:(id)methods error:(NSError * _Nullable * _Nullable)error __attribute__((swift_name("testSwiftNotThrowing(methods:)"))); + +/** + @note This method converts instances of MyError to errors. + Other uncaught Kotlin exceptions are fatal. +*/ ++ (BOOL)callUnitMethods:(id)methods error:(NSError * _Nullable * _Nullable)error __attribute__((swift_name("callUnit(methods:)"))); + +/** + @note This method converts all Kotlin exceptions to errors. +*/ ++ (BOOL)callUnitCallerCaller:(id)caller methods:(id)methods error:(NSError * _Nullable * _Nullable)error __attribute__((swift_name("callUnitCaller(caller:methods:)"))); + +/** + @note This method converts all Kotlin exceptions to errors. +*/ ++ (BOOL)testSwiftThrowingTest:(id)test flag:(BOOL)flag error:(NSError * _Nullable * _Nullable)error __attribute__((swift_name("testSwiftThrowing(test:flag:)"))); + +/** + @note This method converts all Kotlin exceptions to errors. +*/ ++ (BOOL)testSwiftNotThrowingTest:(id)test error:(NSError * _Nullable * _Nullable)error __attribute__((swift_name("testSwiftNotThrowing(test:)"))); ++ (id)same:(id)receiver __attribute__((swift_name("same(_:)"))); ++ (KtInt * _Nullable)callBase1:(id)base1 value:(KtInt * _Nullable)value __attribute__((swift_name("call(base1:value:)"))); ++ (KtInt * _Nullable)callExtendedBase1:(id)extendedBase1 value:(KtInt * _Nullable)value __attribute__((swift_name("call(extendedBase1:value:)"))); ++ (KtInt * _Nullable)callBase2:(id)base2 value:(KtInt * _Nullable)value __attribute__((swift_name("call(base2:value:)"))); ++ (int32_t)callBase3:(id)base3 value:(KtInt * _Nullable)value __attribute__((swift_name("call(base3:value:)"))); ++ (int32_t)callBase23:(KtBase23 *)base23 value:(KtInt * _Nullable)value __attribute__((swift_name("call(base23:value:)"))); ++ (id)createTransformDecimalStringToInt __attribute__((swift_name("createTransformDecimalStringToInt()"))); ++ (BOOL)runUnitBlockBlock:(void (^)(void))block __attribute__((swift_name("runUnitBlock(block:)"))); ++ (void (^)(void))asUnitBlockBlock:(id _Nullable (^)(void))block __attribute__((swift_name("asUnitBlock(block:)"))); ++ (BOOL)runNothingBlockBlock:(void (^)(void))block __attribute__((swift_name("runNothingBlock(block:)"))); ++ (void (^)(void))asNothingBlockBlock:(id _Nullable (^)(void))block __attribute__((swift_name("asNothingBlock(block:)"))); ++ (void (^ _Nullable)(void))getNullBlock __attribute__((swift_name("getNullBlock()"))); ++ (BOOL)isBlockNullBlock:(void (^ _Nullable)(void))block __attribute__((swift_name("isBlockNull(block:)"))); ++ (BOOL)isFunctionObj:(id _Nullable)obj __attribute__((swift_name("isFunction(obj:)"))); ++ (BOOL)isFunction0Obj:(id _Nullable)obj __attribute__((swift_name("isFunction0(obj:)"))); ++ (void)takeForwardDeclaredClassObj:(ForwardDeclaredClass *)obj __attribute__((swift_name("takeForwardDeclaredClass(obj:)"))); ++ (void)takeForwardDeclaredProtocolObj:(id)obj __attribute__((swift_name("takeForwardDeclaredProtocol(obj:)"))); ++ (void)error __attribute__((swift_name("error()"))) __attribute__((unavailable("error"))); ++ (void)warning __attribute__((swift_name("warning()"))) __attribute__((deprecated("warning"))); ++ (void)gc __attribute__((swift_name("gc()"))); ++ (void)testRememberNewObjectTest:(id)test __attribute__((swift_name("testRememberNewObject(test:)"))); ++ (BOOL)testClassTypeCheckX:(id)x __attribute__((swift_name("testClassTypeCheck(x:)"))); ++ (BOOL)testInterfaceTypeCheckX:(id)x __attribute__((swift_name("testInterfaceTypeCheck(x:)"))); ++ (int32_t)testAbstractInterfaceCallX:(id)x __attribute__((swift_name("testAbstractInterfaceCall(x:)"))); ++ (int32_t)testAbstractInterfaceCall2X:(id)x __attribute__((swift_name("testAbstractInterfaceCall2(x:)"))); ++ (void)fooA:(KtKotlinAtomicReference *)a __attribute__((swift_name("foo(a:)"))); + +/** + @note This method converts all Kotlin exceptions to errors. +*/ ++ (BOOL)testGH3825Gh3825:(id)gh3825 error:(NSError * _Nullable * _Nullable)error __attribute__((swift_name("testGH3825(gh3825:)"))); ++ (NSDictionary *)mapBoolean2String __attribute__((swift_name("mapBoolean2String()"))); ++ (NSDictionary *)mapByte2Short __attribute__((swift_name("mapByte2Short()"))); ++ (NSDictionary *)mapShort2Byte __attribute__((swift_name("mapShort2Byte()"))); ++ (NSDictionary *)mapInt2Long __attribute__((swift_name("mapInt2Long()"))); ++ (NSDictionary *)mapLong2Long __attribute__((swift_name("mapLong2Long()"))); ++ (NSDictionary *)mapUByte2Boolean __attribute__((swift_name("mapUByte2Boolean()"))); ++ (NSDictionary *)mapUShort2Byte __attribute__((swift_name("mapUShort2Byte()"))); ++ (NSDictionary *)mapUInt2Long __attribute__((swift_name("mapUInt2Long()"))); ++ (NSDictionary *)mapULong2Long __attribute__((swift_name("mapULong2Long()"))); ++ (NSDictionary *)mapFloat2Float __attribute__((swift_name("mapFloat2Float()"))); ++ (NSDictionary *)mapDouble2String __attribute__((swift_name("mapDouble2String()"))); ++ (KtMutableDictionary *)mutBoolean2String __attribute__((swift_name("mutBoolean2String()"))); ++ (KtMutableDictionary *)mutByte2Short __attribute__((swift_name("mutByte2Short()"))); ++ (KtMutableDictionary *)mutShort2Byte __attribute__((swift_name("mutShort2Byte()"))); ++ (KtMutableDictionary *)mutInt2Long __attribute__((swift_name("mutInt2Long()"))); ++ (KtMutableDictionary *)mutLong2Long __attribute__((swift_name("mutLong2Long()"))); ++ (KtMutableDictionary *)mutUByte2Boolean __attribute__((swift_name("mutUByte2Boolean()"))); ++ (KtMutableDictionary *)mutUShort2Byte __attribute__((swift_name("mutUShort2Byte()"))); ++ (KtMutableDictionary *)mutUInt2Long __attribute__((swift_name("mutUInt2Long()"))); ++ (KtMutableDictionary *)mutULong2Long __attribute__((swift_name("mutULong2Long()"))); ++ (KtMutableDictionary *)mutFloat2Float __attribute__((swift_name("mutFloat2Float()"))); ++ (KtMutableDictionary *)mutDouble2String __attribute__((swift_name("mutDouble2String()"))); +@property (class, readonly) double dbl __attribute__((swift_name("dbl"))); +@property (class, readonly) float flt __attribute__((swift_name("flt"))); +@property (class, readonly) int32_t integer __attribute__((swift_name("integer"))); +@property (class, readonly) int64_t longInt __attribute__((swift_name("longInt"))); +@property (class) int32_t intVar __attribute__((swift_name("intVar"))); +@property (class) NSString *str __attribute__((swift_name("str"))); +@property (class) id strAsAny __attribute__((swift_name("strAsAny"))); +@property (class) id minDoubleVal __attribute__((swift_name("minDoubleVal"))); +@property (class) id maxDoubleVal __attribute__((swift_name("maxDoubleVal"))); +@property (class, readonly) double nanDoubleVal __attribute__((swift_name("nanDoubleVal"))); +@property (class, readonly) float nanFloatVal __attribute__((swift_name("nanFloatVal"))); +@property (class, readonly) double infDoubleVal __attribute__((swift_name("infDoubleVal"))); +@property (class, readonly) float infFloatVal __attribute__((swift_name("infFloatVal"))); +@property (class, readonly) BOOL boolVal __attribute__((swift_name("boolVal"))); +@property (class, readonly) id boolAnyVal __attribute__((swift_name("boolAnyVal"))); +@property (class, readonly) NSArray *numbersList __attribute__((swift_name("numbersList"))); +@property (class, readonly) NSArray *anyList __attribute__((swift_name("anyList"))); +@property (class) id lateinitIntVar __attribute__((swift_name("lateinitIntVar"))); +@property (class, readonly) NSString *lazyVal __attribute__((swift_name("lazyVal"))); +@property (class) KtKotlinArray *delegatedGlobalArray __attribute__((swift_name("delegatedGlobalArray"))); +@property (class, readonly) NSArray *delegatedList __attribute__((swift_name("delegatedList"))); +@property (class, readonly) id _Nullable nullVal __attribute__((swift_name("nullVal"))); +@property (class) NSString * _Nullable nullVar __attribute__((swift_name("nullVar"))); +@property (class) id anyValue __attribute__((swift_name("anyValue"))); +@property (class, readonly) KtInt *(^sumLambda)(KtInt *, KtInt *) __attribute__((swift_name("sumLambda"))); +@property (class, readonly) int32_t PROPERTY_NAME_MUST_NOT_BE_ALTERED_BY_SWIFT __attribute__((swift_name("PROPERTY_NAME_MUST_NOT_BE_ALTERED_BY_SWIFT"))); +@property (class, readonly) id _Nullable errorVal __attribute__((swift_name("errorVal"))) __attribute__((unavailable("error"))); +@property (class) id _Nullable errorVar __attribute__((swift_name("errorVar"))) __attribute__((unavailable("error"))); +@property (class, readonly) id _Nullable warningVal __attribute__((swift_name("warningVal"))) __attribute__((deprecated("warning"))); +@property (class) id _Nullable warningVar __attribute__((swift_name("warningVar"))) __attribute__((deprecated("warning"))); +@property (class) int32_t gh3525BaseInitCount __attribute__((swift_name("gh3525BaseInitCount"))); +@property (class) int32_t gh3525InitCount __attribute__((swift_name("gh3525InitCount"))); +@end; + diff --git a/kotlin-native/backend.native/tests/objcexport/functionalTypes.kt b/kotlin-native/backend.native/tests/objcexport/functionalTypes.kt new file mode 100644 index 00000000000..695653764af --- /dev/null +++ b/kotlin-native/backend.native/tests/objcexport/functionalTypes.kt @@ -0,0 +1,125 @@ +/* + * Copyright 2010-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ +package functionalTypes + +import kotlin.test.* + +typealias AN = Any? + +typealias F2 = (AN, AN) -> AN +typealias F5 = (AN, AN, AN, AN, AN) -> AN +typealias F6 = (AN, AN, AN, AN, AN, AN,) -> AN +typealias F32 = (AN, AN, AN, AN, AN, AN, AN, AN, AN, AN, AN, AN, + AN, AN, AN, AN, AN, AN, AN, AN, AN, AN, AN, AN, + AN, AN, AN, AN, AN, AN, AN, AN) -> AN +typealias F33 = (AN, AN, AN, AN, AN, AN, AN, AN, AN, AN, AN, AN, + AN, AN, AN, AN, AN, AN, AN, AN, AN, AN, AN, AN, + AN, AN, AN, AN, AN, AN, AN, AN, AN) -> AN + +fun callDynType2(list: List, param: AN) { + val fct = list.first() + val ret = fct(param, null) + assertEquals(param, ret) +} + +fun callStaticType2(fct: F2, param: AN) { + val ret = fct(param, null) + assertEquals(param, ret) +} + +fun callDynType32(list: List, param: AN) { + val fct = list.first() + val ret = fct(param + , null, null, null, null, null, null, null + , null, null, null, null, null, null, null, null + , null, null, null, null, null, null, null, null + , null, null, null, null, null, null, null, null + ) + assertEquals(param, ret) +} + +fun callStaticType32(fct: F32, param: AN) { + val ret = fct(param + , null, null, null, null, null, null, null + , null, null, null, null, null, null, null, null + , null, null, null, null, null, null, null, null + , null, null, null, null, null, null, null, null + ) + assertEquals(param, ret) +} + +fun callDynType33(list: List, param: AN) { + val fct = list.first() + val ret = fct(param + , null, null, null, null, null, null, null + , null, null, null, null, null, null, null, null + , null, null, null, null, null, null, null, null + , null, null, null, null, null, null, null, null, null + ) + assertEquals(param, ret) +} + +fun callStaticType33(fct: F33, param: AN) { + val ret = fct(param + , null, null, null, null, null, null, null + , null, null, null, null, null, null, null, null + , null, null, null, null, null, null, null, null + , null, null, null, null, null, null, null, null, null + ) + assertEquals(param, ret) +} + +abstract class FHolder { + abstract val value: Any? +} + +// Note: can't provoke dynamic function type conversion using list (as above) or generics +// due to Swift <-> Obj-C interop bugs/limitations. +// Use covariant return type instead: +class F2Holder(override val value: F2) : FHolder() + +fun getDynTypeLambda2(): F2Holder = F2Holder({ p1, _ -> p1 }) +fun getStaticLambda2(): F2 = { p1, _ -> p1 } + +private fun f2(p1: AN, p2: AN): AN = p1 + +fun getDynTypeRef2(): F2Holder = F2Holder(::f2) +fun getStaticRef2(): F2 = ::f2 + +private fun f32( + p1: AN, p2: AN, p3: AN, p4: AN, p5: AN, p6: AN, p7: AN, p8: AN, + p9: AN, p10: AN, p11: AN, p12: AN, p13: AN, p14: AN, p15: AN, p16: AN, + p17: AN, p18: AN, p19: AN, p20: AN, p21: AN, p22: AN, p23: AN, p24: AN, + p25: AN, p26: AN, p27: AN, p28: AN, p29: AN, p30: AN, p31: AN, p32: AN +): AN = p1 + +private fun f33( + p1: AN, p2: AN, p3: AN, p4: AN, p5: AN, p6: AN, p7: AN, p8: AN, + p9: AN, p10: AN, p11: AN, p12: AN, p13: AN, p14: AN, p15: AN, p16: AN, + p17: AN, p18: AN, p19: AN, p20: AN, p21: AN, p22: AN, p23: AN, p24: AN, + p25: AN, p26: AN, p27: AN, p28: AN, p29: AN, p30: AN, p31: AN, p32: AN, + p33: AN +): AN = p1 + +class F32Holder(override val value: F32) : FHolder() + +fun getDynType32(): F32Holder = F32Holder(::f32) +fun getStaticType32(): F32 = ::f32 + +class F33Holder(override val value: F33) : FHolder() + +fun getDynTypeRef33(): F33Holder = F33Holder(::f33) +fun getStaticTypeRef33(): F33 = ::f33 + +fun getDynTypeLambda33(): F33Holder = F33Holder(getStaticTypeLambda33()) +fun getStaticTypeLambda33(): F33 = { + p, + _, _, _, _, _, _, _, _, + _, _, _, _, _, _, _, _, + _, _, _, _, _, _, _, _, + _, _, _, _, _, _, _, _ + -> + p +} diff --git a/kotlin-native/backend.native/tests/objcexport/functionalTypes.swift b/kotlin-native/backend.native/tests/objcexport/functionalTypes.swift new file mode 100644 index 00000000000..e00c8ceacee --- /dev/null +++ b/kotlin-native/backend.native/tests/objcexport/functionalTypes.swift @@ -0,0 +1,145 @@ +/* + * Copyright 2010-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +import Kt + +private func test1() { + FunctionalTypesKt.callStaticType2(fct: foo2, param: "from swift") + FunctionalTypesKt.callDynType2(list: [ foo2 ], param: "from swift") + + FunctionalTypesKt.callStaticType2(fct : {a1, _ in return a1 }, param: "from swift block") + FunctionalTypesKt.callDynType2(list: [ {a1, _ in return a1 } ], param: "from swift block") + + // 32 params is mapped as regular; block is OK + FunctionalTypesKt.callStaticType32(fct : { + a1, _, _, _, _, _, _, _, + _, _, _, _, _, _, _, _, + _, _, _, _, _, _, _, _, + _, _, _, _, _, _, _, _ + in return a1 }, param: "from swift block") + + FunctionalTypesKt.callDynType32(list : [{ + a1, _, _, _, _, _, _, _, + _, _, _, _, _, _, _, _, + _, _, _, _, _, _, _, _, + _, _, _, _, _, _, _, _ + in return a1 }], param: "from swift block") + + // 33 params requires explicit implementation of KotlinFunction33 + FunctionalTypesKt.callStaticType33(fct: foo33, param: "from swift") + FunctionalTypesKt.callDynType33(list: [ Foo33() ], param: "from swift") +} + +private func test2() throws { + try assertEquals(actual: FunctionalTypesKt.getDynTypeLambda2().value("one", nil) as? String, expected: "one") + try assertEquals(actual: FunctionalTypesKt.getStaticLambda2()("two", nil) as? String, expected: "two") + + try assertEquals(actual: FunctionalTypesKt.getDynTypeRef2().value("three", nil) as? String, expected: "three") + try assertEquals(actual: FunctionalTypesKt.getStaticRef2()("four", nil) as? String, expected: "four") + + // 32 params is mapped as regular; calling result as block is OK + try assertEquals( + actual: FunctionalTypesKt.getDynType32().value( + "five", + nil, nil, nil, nil, nil, nil, nil, nil, + nil, nil, nil, nil, nil, nil, nil, nil, + nil, nil, nil, nil, nil, nil, nil, nil, + nil, nil, nil, nil, nil, nil, nil + ) as? String, + expected: "five" + ) + + try assertEquals( + actual: FunctionalTypesKt.getStaticType32()( + "six", + nil, nil, nil, nil, nil, nil, nil, nil, + nil, nil, nil, nil, nil, nil, nil, nil, + nil, nil, nil, nil, nil, nil, nil, nil, + nil, nil, nil, nil, nil, nil, nil + ) as? String, + expected: "six" + ) + + // 33 params requires explicit invocation of KotlinFunction33.invoke + try assertEquals( + actual: FunctionalTypesKt.getDynTypeRef33().value.invoke( + p1: "seven", + p2: nil, p3: nil, p4: nil, p5: nil, p6: nil, p7: nil, p8: nil, p9: nil, + p10: nil, p11: nil, p12: nil, p13: nil, p14: nil, p15: nil, p16: nil, p17: nil, + p18: nil, p19: nil, p20: nil, p21: nil, p22: nil, p23: nil, p24: nil, p25: nil, + p26: nil, p27: nil, p28: nil, p29: nil, p30: nil, p31: nil, p32: nil, p33: nil + ) as? String, + expected: "seven" + ) + + // static conversion is ok though. + try assertEquals( + actual: FunctionalTypesKt.getStaticTypeRef33()( + "eight", + nil, nil, nil, nil, nil, nil, nil, nil, + nil, nil, nil, nil, nil, nil, nil, nil, + nil, nil, nil, nil, nil, nil, nil, nil, + nil, nil, nil, nil, nil, nil, nil, nil + ) as? String, + expected: "eight" + ) + + try assertEquals( + actual: FunctionalTypesKt.getDynTypeLambda33().value.invoke( + p1: "nine", + p2: nil, p3: nil, p4: nil, p5: nil, p6: nil, p7: nil, p8: nil, p9: nil, + p10: nil, p11: nil, p12: nil, p13: nil, p14: nil, p15: nil, p16: nil, p17: nil, + p18: nil, p19: nil, p20: nil, p21: nil, p22: nil, p23: nil, p24: nil, p25: nil, + p26: nil, p27: nil, p28: nil, p29: nil, p30: nil, p31: nil, p32: nil, p33: nil + ) as? String, + expected: "nine" + ) + + try assertEquals( + actual: FunctionalTypesKt.getStaticTypeLambda33()( + "ten", + nil, nil, nil, nil, nil, nil, nil, nil, + nil, nil, nil, nil, nil, nil, nil, nil, + nil, nil, nil, nil, nil, nil, nil, nil, + nil, nil, nil, nil, nil, nil, nil, nil + ) as? String, + expected: "ten" + ) +} + +class FunctionalTypesTests : SimpleTestProvider { + override init() { + super.init() + + test("Test1", test1) + test("Test2", test2) + } +} + +private func foo2(a1: Any?, _: Any?) -> Any? { + return a1 +} + +private func foo33(a1: Any?, _: Any?, _: Any?, _: Any?, _: Any?, _: Any?, _: Any?, _: Any?, + _: Any?, _: Any?, _: Any?, _: Any?, _: Any?, _: Any?, _: Any?, _: Any?, + _: Any?, _: Any?, _: Any?, _: Any?, _: Any?, _: Any?, _: Any?, _: Any?, + _: Any?, _: Any?, _: Any?, _: Any?, _: Any?, _: Any?, _: Any?, _: Any?, _: Any? +) -> Any? { + return a1 +} + +private class Foo33 : KotlinFunction33 { + func invoke(p1: Any?, p2: Any?, p3: Any?, p4: Any?, p5: Any?, p6: Any?, p7: Any?, p8: Any?, p9: Any?, + p10: Any?, p11: Any?, p12: Any?, p13: Any?, p14: Any?, p15: Any?, p16: Any?, p17: Any?, p18: Any?, p19: Any?, + p20: Any?, p21: Any?, p22: Any?, p23: Any?, p24: Any?, p25: Any?, p26: Any?, p27: Any?, p28: Any?, p29: Any?, + p30: Any?, p31: Any?, p32: Any?, p33: Any? + ) -> Any? { + return foo33(a1: p1 + , nil, nil, nil, nil, nil, nil, nil, nil + , nil, nil, nil, nil, nil, nil, nil, nil + , nil, nil, nil, nil, nil, nil, nil, nil + , nil, nil, nil, nil, nil, nil, nil, nil) + } +} diff --git a/kotlin-native/backend.native/tests/objcexport/gh4002.kt b/kotlin-native/backend.native/tests/objcexport/gh4002.kt new file mode 100644 index 00000000000..b162084fc2b --- /dev/null +++ b/kotlin-native/backend.native/tests/objcexport/gh4002.kt @@ -0,0 +1,9 @@ +/* + * Copyright 2010-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +package gh4002 + +open class GH4002ArgumentBase +class GH4002Argument : GH4002ArgumentBase() \ No newline at end of file diff --git a/kotlin-native/backend.native/tests/objcexport/gh4002.swift b/kotlin-native/backend.native/tests/objcexport/gh4002.swift new file mode 100644 index 00000000000..d0bfbd19aa1 --- /dev/null +++ b/kotlin-native/backend.native/tests/objcexport/gh4002.swift @@ -0,0 +1,31 @@ +/* + * Copyright 2010-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +import Kt + +// See https://github.com/JetBrains/kotlin-native/issues/4002 + +class GH4002Base0 : NSObject, NSCoding { + required init(coder: NSCoder) { fatalError() } + + func encode(with coder: NSCoder) { fatalError() } +} + +class GH4002Base1 : GH4002Base0 {} + +@objc(ObjCGH4002) +class GH4002 : GH4002Base1 {} + +private func test1() throws { + try assertEquals(actual: String(cString: class_getName(GH4002.self)), expected: "ObjCGH4002") +} + +class Gh4002Tests : SimpleTestProvider { + override init() { + super.init() + + test("Test1", test1) + } +} \ No newline at end of file diff --git a/kotlin-native/backend.native/tests/objcexport/headerWarnings.kt b/kotlin-native/backend.native/tests/objcexport/headerWarnings.kt new file mode 100644 index 00000000000..2859dfe25ff --- /dev/null +++ b/kotlin-native/backend.native/tests/objcexport/headerWarnings.kt @@ -0,0 +1,29 @@ +/* + * Copyright 2010-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +package headerWarnings + +// Note: the test parses the generated header with -Werror to detect warnings. + +class TestIncompatiblePropertyTypeWarning { + class Generic(val value: T) + + interface InterfaceWithGenericProperty { + val p: Generic + } + + class ClassOverridingInterfaceWithGenericProperty(override val p: Generic) : InterfaceWithGenericProperty +} + +// https://github.com/JetBrains/kotlin-native/issues/3992 +class TestGH3992 { + abstract class C(open val a: A) + + class D(override val a: B) : C(a) + + abstract class A + + class B : A() +} diff --git a/kotlin-native/backend.native/tests/objcexport/headerWarnings.swift b/kotlin-native/backend.native/tests/objcexport/headerWarnings.swift new file mode 100644 index 00000000000..7c23c799b82 --- /dev/null +++ b/kotlin-native/backend.native/tests/objcexport/headerWarnings.swift @@ -0,0 +1,42 @@ +/* + * Copyright 2010-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +import Kt + +// Note: the test parses the generated header with -Werror to detect warnings. +// It is enough to have just Kotlin declarations at the moment. +// Adding usages for all declarations to avoid any kind of DCE that may appear later. + +private func testIncompatiblePropertyType() throws { + let c = TestIncompatiblePropertyTypeWarning.ClassOverridingInterfaceWithGenericProperty( + p: TestIncompatiblePropertyTypeWarningGeneric(value: "cba") + ) + + let pc: TestIncompatiblePropertyTypeWarningGeneric = c.p + try assertEquals(actual: pc.value, expected: "cba") + + let i: TestIncompatiblePropertyTypeWarningInterfaceWithGenericProperty = c + let pi: TestIncompatiblePropertyTypeWarningGeneric = i.p + try assertEquals(actual: pi.value as! String, expected: "cba") +} + +private func testGH3992() throws { + let d = TestGH3992.D(a: TestGH3992.B()) + let c: TestGH3992.C = d + + let b: TestGH3992.B = d.a + let a: TestGH3992.A = b + + try assertTrue(a is TestGH3992.B) +} + +class HeaderWarningsTests : SimpleTestProvider { + override init() { + super.init() + + test("TestIncompatiblePropertyType", testIncompatiblePropertyType) + test("TestGH3992", testGH3992) + } +} \ No newline at end of file diff --git a/kotlin-native/backend.native/tests/objcexport/kt35940.kt b/kotlin-native/backend.native/tests/objcexport/kt35940.kt new file mode 100644 index 00000000000..7a032bfcdcf --- /dev/null +++ b/kotlin-native/backend.native/tests/objcexport/kt35940.kt @@ -0,0 +1,44 @@ +/* + * Copyright 2010-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +package kt35940 + +import kotlin.reflect.* + +@OptIn(ExperimentalAssociatedObjects::class) +@AssociatedObjectKey +@Retention(AnnotationRetention.BINARY) +annotation class Associated(val kClass: KClass<*>) + +private interface I1 { + val s: String +} + +private class I1Impl : I1 { + override val s = "zzz" +} + +private class C(var i1: I1?) + +private interface I2 { + fun bar(c: C) +} + +private object I2Impl : I2 { + override fun bar(c: C) { + c.i1 = I1Impl() + } +} + +@Associated(I2Impl::class) +private class I2ImplHolder + +@OptIn(ExperimentalAssociatedObjects::class) +fun testKt35940(): String { + val i2 = I2ImplHolder::class.findAssociatedObject()!! as I2 + val c = C(null) + i2.bar(c) + return c.i1!!.s +} diff --git a/kotlin-native/backend.native/tests/objcexport/kt35940.swift b/kotlin-native/backend.native/tests/objcexport/kt35940.swift new file mode 100644 index 00000000000..6fba9a53182 --- /dev/null +++ b/kotlin-native/backend.native/tests/objcexport/kt35940.swift @@ -0,0 +1,18 @@ +/* + * Copyright 2010-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +import Kt + +private func test1() throws { + try assertEquals(actual: Kt35940Kt.testKt35940(), expected: "zzz") +} + +class Kt35940Tests : SimpleTestProvider { + override init() { + super.init() + + test("Test1", test1) + } +} \ No newline at end of file diff --git a/kotlin-native/backend.native/tests/objcexport/kt38641.kt b/kotlin-native/backend.native/tests/objcexport/kt38641.kt new file mode 100644 index 00000000000..18c3a74dcfe --- /dev/null +++ b/kotlin-native/backend.native/tests/objcexport/kt38641.kt @@ -0,0 +1,36 @@ +package kt38641 + +// See https://youtrack.jetbrains.com/issue/KT-38641. +class KT38641 { + class IntType { + var description = 42 + } + + class Val { + val description = "val" + } + + class Var { + var description = "var" + } + + class TwoProperties { + val description = "description" + val description_ = "description_" + } + + abstract class OverrideVal { + abstract val description: String + } + + interface OverrideVar { + var description: String + } +} + +fun getOverrideValDescription(impl: KT38641.OverrideVal) = impl.description + +fun getOverrideVarDescription(impl: KT38641.OverrideVar) = impl.description +fun setOverrideVarDescription(impl: KT38641.OverrideVar, newValue: String) { + impl.description = newValue +} diff --git a/kotlin-native/backend.native/tests/objcexport/kt38641.swift b/kotlin-native/backend.native/tests/objcexport/kt38641.swift new file mode 100644 index 00000000000..871f23f23d6 --- /dev/null +++ b/kotlin-native/backend.native/tests/objcexport/kt38641.swift @@ -0,0 +1,72 @@ +/* + * Copyright 2010-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +import Kt + +private func testIntType() throws { + let i = KT38641.IntType() + + try assertEquals(actual: i.description_, expected: 42) + + i.description_ = 17 + try assertEquals(actual: i.description_, expected: 17) +} + +private func testVal() throws { + try assertEquals(actual: KT38641.Val().description_, expected: "val") +} + +private func testVar() throws { + let v = KT38641.Var() + + try assertEquals(actual: v.description_, expected: "var") + + v.description_ = "newValue" + try assertEquals(actual: v.description_, expected: "newValue") +} + +private func testTwoProperties() throws { + let t = KT38641.TwoProperties() + try assertEquals(actual: t.description_, expected: "description") + try assertEquals(actual: t.description__, expected: "description_") +} + +private func testOverrideVal() throws { + try assertEquals(actual: Kt38641Kt.getOverrideValDescription(impl: KT38641OverrideValImpl()), expected: "description_") +} + +class KT38641OverrideValImpl : KT38641.OverrideVal { + override var description_: String { + get { + return "description_" + } + } +} + +private func testOverrideVar() throws { + let impl = KT38641OverrideVarImpl() + + try assertEquals(actual: Kt38641Kt.getOverrideVarDescription(impl: impl), expected: "description_") + + Kt38641Kt.setOverrideVarDescription(impl: impl, newValue: "d") + try assertEquals(actual: Kt38641Kt.getOverrideVarDescription(impl: impl), expected: "d") +} + +class KT38641OverrideVarImpl : KT38641OverrideVar { + var description_: String = "description_" +} + +class Kt38641Tests : SimpleTestProvider { + override init() { + super.init() + + test("TestIntType", testIntType) + test("TestVal", testVal) + test("TestVar", testVar) + test("TestTwoProperties", testTwoProperties) + test("TestOverrideVal", testOverrideVal) + test("TestOverrideVar", testOverrideVar) + } +} \ No newline at end of file diff --git a/kotlin-native/backend.native/tests/objcexport/kt39206.kt b/kotlin-native/backend.native/tests/objcexport/kt39206.kt new file mode 100644 index 00000000000..3f31038311e --- /dev/null +++ b/kotlin-native/backend.native/tests/objcexport/kt39206.kt @@ -0,0 +1,17 @@ +// See https://youtrack.jetbrains.com/issue/KT-39206. +@Deprecated("Don't call this\nPlease") +fun myFunc() = 17 + +// See https://youtrack.jetbrains.com/issue/KT-41193. +@Deprecated( + level = DeprecationLevel.ERROR, + message = "This class is deprecated for removal during serialization 1.0 API stabilization.\n" + + "For configuring Json instances, the corresponding builder function can be used instead, e.g. instead of" + + "'Json(JsonConfiguration.Stable.copy(isLenient = true))' 'Json { isLenient = true }' should be used.\n" + + "Instead of storing JsonConfiguration instances of the code, Json instances can be used directly:" + + "'Json(MyJsonConfiguration.copy(prettyPrint = true))' can be replaced with 'Json(from = MyApplicationJson) { prettyPrint = true }'" +) +public open class JsonConfiguration + +@Deprecated("'\"\\@\$(){}\r\n") +class MoreTrickyChars \ No newline at end of file diff --git a/kotlin-native/backend.native/tests/objcexport/kt39206.swift b/kotlin-native/backend.native/tests/objcexport/kt39206.swift new file mode 100644 index 00000000000..c186ede91a0 --- /dev/null +++ b/kotlin-native/backend.native/tests/objcexport/kt39206.swift @@ -0,0 +1,18 @@ +import Kt + +private func test1() throws { + try assertEquals(actual: Kt39206Kt.myFunc(), expected: 17) +} + +private func test2() throws { + try assertTrue(MoreTrickyChars() as AnyObject is MoreTrickyChars) +} + +class Kt39206Tests : SimpleTestProvider { + override init() { + super.init() + + test("Test1", test1) + test("Test2", test2) + } +} \ No newline at end of file diff --git a/kotlin-native/backend.native/tests/objcexport/kt41907.kt b/kotlin-native/backend.native/tests/objcexport/kt41907.kt new file mode 100644 index 00000000000..9e361392f4e --- /dev/null +++ b/kotlin-native/backend.native/tests/objcexport/kt41907.kt @@ -0,0 +1,27 @@ +/* + * Copyright 2010-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +package kt41907 + +class Ckt41907 + +interface Ikt41907 { + fun foo(c: Ckt41907) +} + +private class Bkt41907 { + var c: Ckt41907? = null +} + +private val b = Bkt41907() + +fun escapeC(c: Ckt41907) { + b.c = c +} + +fun testKt41907(o: Ikt41907) { + val c = Ckt41907() + o.foo(c) +} diff --git a/kotlin-native/backend.native/tests/objcexport/kt41907.swift b/kotlin-native/backend.native/tests/objcexport/kt41907.swift new file mode 100644 index 00000000000..d88e2ca79e2 --- /dev/null +++ b/kotlin-native/backend.native/tests/objcexport/kt41907.swift @@ -0,0 +1,24 @@ +/* + * Copyright 2010-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +import Kt + +class Ikt41907Impl : Ikt41907 { + func foo(c: Ckt41907) { + Kt41907Kt.escapeC(c: c) + } +} + +private func test1() { + Kt41907Kt.testKt41907(o: Ikt41907Impl()) +} + +class Kt41907Tests : SimpleTestProvider { + override init() { + super.init() + + test("Test1", test1) + } +} \ No newline at end of file diff --git a/kotlin-native/backend.native/tests/objcexport/library.kt b/kotlin-native/backend.native/tests/objcexport/library.kt new file mode 100644 index 00000000000..d0f6f142bb0 --- /dev/null +++ b/kotlin-native/backend.native/tests/objcexport/library.kt @@ -0,0 +1,18 @@ +/* + * Copyright 2010-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +package library + +fun readDataFromLibraryClass(input: A): String { + return input.data +} + +fun readDataFromLibraryInterface(input: I): String { + return input.data +} + +fun readDataFromLibraryEnum(input: E): String { + return input.data +} \ No newline at end of file diff --git a/kotlin-native/backend.native/tests/objcexport/library.swift b/kotlin-native/backend.native/tests/objcexport/library.swift new file mode 100644 index 00000000000..f3c3dcd5d19 --- /dev/null +++ b/kotlin-native/backend.native/tests/objcexport/library.swift @@ -0,0 +1,30 @@ +/* + * Copyright 2010-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +import Kt + +func testAccessClassFromLibraryWithShortName() throws { + + let object: MyLibraryA = MyLibraryA(data: "Data from Class") + let interface: MyLibraryI = MyLibraryA(data: "Data from Interface") + let enumObject: MyLibraryE = MyLibraryE.b + + + let dataFromClass = LibraryKt.readDataFromLibraryClass(input: object) + let dataFromInterface = LibraryKt.readDataFromLibraryInterface(input: interface) + let dataFromEnum = LibraryKt.readDataFromLibraryEnum(input: enumObject) + + try assertEquals(actual: dataFromClass, expected: "Data from Class") + try assertEquals(actual: dataFromInterface, expected: "Data from Interface") + try assertEquals(actual: dataFromEnum, expected: "Enum entry B") +} + +class LibraryTests : SimpleTestProvider { + override init() { + super.init() + + test("testAccessClassFromLibraryWithShortName", testAccessClassFromLibraryWithShortName) + } +} \ No newline at end of file diff --git a/kotlin-native/backend.native/tests/objcexport/library/library.kt b/kotlin-native/backend.native/tests/objcexport/library/library.kt new file mode 100644 index 00000000000..e53e436eb86 --- /dev/null +++ b/kotlin-native/backend.native/tests/objcexport/library/library.kt @@ -0,0 +1,18 @@ +/* + * Copyright 2010-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +package library + +interface I { + val data: String +} + +class A(override val data: String): I + +enum class E(val data: String) { + A("Enum entry A"), + B("Enum entry B"), + C("Enum entry C") +} \ No newline at end of file diff --git a/kotlin-native/backend.native/tests/objcexport/localEA.kt b/kotlin-native/backend.native/tests/objcexport/localEA.kt new file mode 100644 index 00000000000..827373725a7 --- /dev/null +++ b/kotlin-native/backend.native/tests/objcexport/localEA.kt @@ -0,0 +1,48 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +// All classes and methods should be used in tests +@file:Suppress("UNUSED") + +package localEA + +class ArraysConstructor { + private val memberArray: IntArray + constructor(int1: Int, int2: Int) { + memberArray = IntArray(2) + set(int1, int2) + } + fun set(int1: Int, int2: Int) { + memberArray[0] = int1 + memberArray[1] = int2 + } + fun log() = "size: ${memberArray.size}, contents: ${memberArray.contentToString()}" +} +class ArraysDefault { + private val memberArray = IntArray(2) + constructor(int1: Int, int2: Int) { + set(int1, int2) + } + fun set(int1: Int, int2: Int) { + memberArray[0] = int1 + memberArray[1] = int2 + } + fun log() = "size: ${memberArray.size}, contents: ${memberArray.contentToString()}" +} +class ArraysInitBlock { + private val memberArray : IntArray + init { + memberArray = IntArray(2) + } + constructor(int1: Int, int2: Int) { + set(int1, int2) + } + fun set(int1: Int, int2: Int) { + memberArray[0] = int1 + memberArray[1] = int2 + } + fun log() = "size: ${memberArray.size}, contents: ${memberArray.contentToString()}" +} + diff --git a/kotlin-native/backend.native/tests/objcexport/localEA.swift b/kotlin-native/backend.native/tests/objcexport/localEA.swift new file mode 100644 index 00000000000..9887730af5e --- /dev/null +++ b/kotlin-native/backend.native/tests/objcexport/localEA.swift @@ -0,0 +1,35 @@ +/* + * Copyright 2010-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +import Kt + +// -------- Tests -------- + +func testArraysEscapeAsParameter() throws { + let array1 = ArraysConstructor(int1: 1, int2: 2) + try assertEquals(actual: array1.log(), expected: "size: 2, contents: [1, 2]", "Wrong array values in class ArraysConstructor.") + array1.set(int1: 3, int2: 4) + try assertEquals(actual: array1.log(), expected: "size: 2, contents: [3, 4]", "Wrong array values in class ArraysConstructor.") + + let array2 = ArraysDefault(int1: 1, int2: 2) + try assertEquals(actual: array2.log(), expected: "size: 2, contents: [1, 2]", "Wrong array values in class ArraysDefault.") + array2.set(int1: 3, int2: 4) + try assertEquals(actual: array2.log(), expected: "size: 2, contents: [3, 4]", "Wrong array values in class ArraysDefault.") + + let array3 = ArraysInitBlock(int1: 1, int2: 2) + try assertEquals(actual: array3.log(), expected: "size: 2, contents: [1, 2]", "Wrong array values in class ArraysInitBlock.") + array3.set(int1: 3, int2: 4) + try assertEquals(actual: array3.log(), expected: "size: 2, contents: [3, 4]", "Wrong array values in class ArraysInitBlock.") +} + +// -------- Execution of the test -------- + +class LocalEATests : SimpleTestProvider { + override init() { + super.init() + + test("TestArraysEscapeAsParameter", testArraysEscapeAsParameter) + } +} \ No newline at end of file diff --git a/kotlin-native/backend.native/tests/objcexport/throwsEmpty.kt b/kotlin-native/backend.native/tests/objcexport/throwsEmpty.kt new file mode 100644 index 00000000000..1508b0e30ce --- /dev/null +++ b/kotlin-native/backend.native/tests/objcexport/throwsEmpty.kt @@ -0,0 +1,6 @@ +package throwsEmpty + +// Suppressing compilation error. +// Only the generated comment is checked. +@Suppress("THROWS_LIST_EMPTY") +@Throws fun throwsEmpty() {} diff --git a/kotlin-native/backend.native/tests/objcexport/topLevelMangling.swift b/kotlin-native/backend.native/tests/objcexport/topLevelMangling.swift new file mode 100644 index 00000000000..f22966e8f2e --- /dev/null +++ b/kotlin-native/backend.native/tests/objcexport/topLevelMangling.swift @@ -0,0 +1,26 @@ +import Kt + +private func testFunctionsInDifferentFilesAreNotMangled() throws { + try assertEquals(actual: TopLevelManglingAKt.foo(), expected: "a1") + try assertEquals(actual: TopLevelManglingBKt.foo(), expected: "b1") +} + +private func testPropertiesInDifferentFilesAreNotMangled() throws { + try assertEquals(actual: TopLevelManglingAKt.bar, expected: "a2") + try assertEquals(actual: TopLevelManglingBKt.bar, expected: "b2") +} + +private func testFunctionsInSameFileAreMangled() throws { + try assertEquals(actual: TopLevelManglingAKt.sameNumber(value: Int32(1)), expected: 1) + try assertEquals(actual: TopLevelManglingAKt.sameNumber(value_: Int64(2)), expected: 2) +} + +class TopLevelManglingTests : SimpleTestProvider { + override init() { + super.init() + + test("TestFunctionsInDifferentFilesAreNotMangled", testFunctionsInDifferentFilesAreNotMangled) + test("TestPropertiesInDifferentFilesAreNotMangled", testPropertiesInDifferentFilesAreNotMangled) + test("TestFunctionsInSameFileAreMangled", testFunctionsInSameFileAreMangled) + } +} diff --git a/kotlin-native/backend.native/tests/objcexport/topLevelManglingA.kt b/kotlin-native/backend.native/tests/objcexport/topLevelManglingA.kt new file mode 100644 index 00000000000..870261322bb --- /dev/null +++ b/kotlin-native/backend.native/tests/objcexport/topLevelManglingA.kt @@ -0,0 +1,7 @@ +package topLevelManglingA + +fun foo() = "a1" +val bar = "a2" + +fun sameNumber(value: Int) = value +fun sameNumber(value: Long) = value diff --git a/kotlin-native/backend.native/tests/objcexport/topLevelManglingB.kt b/kotlin-native/backend.native/tests/objcexport/topLevelManglingB.kt new file mode 100644 index 00000000000..106840ed2dc --- /dev/null +++ b/kotlin-native/backend.native/tests/objcexport/topLevelManglingB.kt @@ -0,0 +1,4 @@ +package topLevelManglingB + +fun foo() = "b1" +val bar = "b2" diff --git a/kotlin-native/backend.native/tests/objcexport/values.kt b/kotlin-native/backend.native/tests/objcexport/values.kt new file mode 100644 index 00000000000..01753e1c599 --- /dev/null +++ b/kotlin-native/backend.native/tests/objcexport/values.kt @@ -0,0 +1,1014 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +// All classes and methods should be used in tests +@file:Suppress("UNUSED") + +package conversions + +import kotlin.native.concurrent.freeze +import kotlin.native.concurrent.isFrozen +import kotlin.native.internal.ObjCErrorException +import kotlin.native.ref.WeakReference +import kotlin.properties.ReadWriteProperty +import kotlin.reflect.KClass +import kotlin.reflect.KProperty +import kotlin.test.* +import kotlinx.cinterop.* + +// Ensure loaded function IR classes aren't ordered by arity: +internal fun referenceFunction1(block: (Any?) -> Unit) {} + +// Constants +const val dbl: Double = 3.14 +const val flt: Float = 2.73F +const val integer: Int = 42 +const val longInt: Long = 1984 + +// Vars +var intVar: Int = 451 +var str = "Kotlin String" +var strAsAny: Any = "Kotlin String as Any" + +// MIN/MAX values as Numbers +var minDoubleVal: kotlin.Number = Double.MIN_VALUE +var maxDoubleVal: kotlin.Number = Double.MAX_VALUE + +// Infinities and NaN +val nanDoubleVal: Double = Double.NaN +val nanFloatVal: Float = Float.NaN +val infDoubleVal: Double = Double.POSITIVE_INFINITY +val infFloatVal: Float = Float.NEGATIVE_INFINITY + +private fun T.toNullable(): T? = this + +fun box(booleanValue: Boolean) = booleanValue.toNullable() +fun box(byteValue: Byte) = byteValue.toNullable() +fun box(shortValue: Short) = shortValue.toNullable() +fun box(intValue: Int) = intValue.toNullable() +fun box(longValue: Long) = longValue.toNullable() +fun box(uByteValue: UByte) = uByteValue.toNullable() +fun box(uShortValue: UShort) = uShortValue.toNullable() +fun box(uIntValue: UInt) = uIntValue.toNullable() +fun box(uLongValue: ULong) = uLongValue.toNullable() +fun box(floatValue: Float) = floatValue.toNullable() +fun box(doubleValue: Double) = doubleValue.toNullable() + +private inline fun ensureEquals(actual: T?, expected: T) { + if (actual !is T) error(T::class) + if (actual != expected) error(T::class) +} + +fun ensureEqualBooleans(actual: Boolean?, expected: Boolean) = ensureEquals(actual, expected) +fun ensureEqualBytes(actual: Byte?, expected: Byte) = ensureEquals(actual, expected) +fun ensureEqualShorts(actual: Short?, expected: Short) = ensureEquals(actual, expected) +fun ensureEqualInts(actual: Int?, expected: Int) = ensureEquals(actual, expected) +fun ensureEqualLongs(actual: Long?, expected: Long) = ensureEquals(actual, expected) +fun ensureEqualUBytes(actual: UByte?, expected: UByte) = ensureEquals(actual, expected) +fun ensureEqualUShorts(actual: UShort?, expected: UShort) = ensureEquals(actual, expected) +fun ensureEqualUInts(actual: UInt?, expected: UInt) = ensureEquals(actual, expected) +fun ensureEqualULongs(actual: ULong?, expected: ULong) = ensureEquals(actual, expected) +fun ensureEqualFloats(actual: Float?, expected: Float) = ensureEquals(actual, expected) +fun ensureEqualDoubles(actual: Double?, expected: Double) = ensureEquals(actual, expected) + +// Boolean +val boolVal: Boolean = true +val boolAnyVal: Any = false + +// Lists +val numbersList: List = listOf(1.toByte(), 2.toShort(), 13) +val anyList: List = listOf("Str", 42, 3.14, true) + +// lateinit +lateinit var lateinitIntVar: Any + +// lazy +val lazyVal: String by lazy { + println("Lazy value initialization") + "Lazily initialized string" +} + +// Delegation +var delegatedGlobalArray: Array by DelegateClass() + +class DelegateClass: ReadWriteProperty> { + + private var holder: Array = arrayOf("property") + + override fun getValue(thisRef: Nothing?, property: KProperty<*>): Array { + return arrayOf("Delegated", "global", "array") + holder + } + + override fun setValue(thisRef: Nothing?, property: KProperty<*>, value: Array) { + holder = value + } +} + +// Getter with delegation +val delegatedList: List + get() = delegatedGlobalArray.toList() + +// Null +val nullVal: Any? = null +var nullVar: String? = "" + +// Any +var anyValue: Any = "Str" + +// Functions +fun emptyFun() { } + +fun strFun(): String = "fooStr" + +fun argsFun(i: Int, l: Long, d: Double, s: String): Any = s + i + l + d + +fun funArgument(foo: () -> String): String = foo() + +// Generic functions +fun genericFoo(t: T, foo: (T) -> R): R = foo(t) + +fun fooGenericNumber(r: R, foo: (T) -> Number): Number = foo(r) + +fun varargToList(vararg args: T): List = args.toList() + +// Extensions +fun String.subExt(i: Int): String { + return if (i < this.length) this[i].toString() else "nothing" +} + +fun Any?.toString(): String = this?.toString() ?: "null" + +fun Any?.print() = println(this.toString()) + +fun Char.boxChar(): Char? = this +fun Char?.isA(): Boolean = (this == 'A') + +// Lambdas +val sumLambda = { x: Int, y: Int -> x + y } + + +// Inheritance +interface I { + fun iFun(): String = "I::iFun" +} + +fun I.iFunExt() = iFun() + +private interface PI { + fun piFun(): Any + fun iFun(): String = "PI::iFun" +} + +class DefaultInterfaceExt : I + +open class OpenClassI : I { + override fun iFun(): String = "OpenClassI::iFun" +} + +class FinalClassExtOpen : OpenClassI() { + override fun iFun(): String = "FinalClassExtOpen::iFun" +} + +open class MultiExtClass : OpenClassI(), PI { + override fun piFun(): Any { + return 42 + } + + override fun iFun(): String = super.iFun() +} + +open class ConstrClass(open val i: Int, val s: String, val a: Any = "AnyS") : OpenClassI() + +class ExtConstrClass(override val i: Int) : ConstrClass(i, "String") { + override fun iFun(): String = "ExtConstrClass::iFun::$i-$s-$a" +} + +// Enum +enum class Enumeration(val enumValue: Int) { + ANSWER(42), YEAR(1984), TEMPERATURE(451) +} + +fun passEnum(): Enumeration { + return Enumeration.ANSWER +} + +fun receiveEnum(e: Int) { + println("ENUM got: ${get(e).enumValue}") +} + +fun get(value: Int): Enumeration { + return Enumeration.values()[value] +} + +// Data class values and generated properties: component# and toString() +data class TripleVals(val first: T, val second: T, val third: T) + +data class TripleVars(var first: T, var second: T, var third: T) { + override fun toString(): String { + return "[$first, $second, $third]" + } +} + +open class WithCompanionAndObject { + companion object { + val str = "String" + var named: I? = Named + } + + object Named : OpenClassI() { + override fun iFun(): String = "WithCompanionAndObject.Named::iFun" + } +} + +fun getCompanionObject() = WithCompanionAndObject.Companion +fun getNamedObject() = WithCompanionAndObject.Named +fun getNamedObjectInterface(): OpenClassI = WithCompanionAndObject.Named + +typealias EE = Enumeration +fun EE.getAnswer() : EE = Enumeration.ANSWER + +inline class IC1(val value: Int) +inline class IC2(val value: String) +inline class IC3(val value: TripleVals?) + +fun box(ic1: IC1): Any = ic1 +fun box(ic2: IC2): Any = ic2 +fun box(ic3: IC3): Any = ic3 + +fun concatenateInlineClassValues(ic1: IC1, ic1N: IC1?, ic2: IC2, ic2N: IC2?, ic3: IC3, ic3N: IC3?): String = + "${ic1.value} ${ic1N?.value} ${ic2.value} ${ic2N?.value} ${ic3.value} ${ic3N?.value}" + +fun IC1.getValue1() = this.value +fun IC1?.getValueOrNull1() = this?.value + +fun IC2.getValue2() = value +fun IC2?.getValueOrNull2() = this?.value + +fun IC3.getValue3() = value +fun IC3?.getValueOrNull3() = this?.value + +fun isFrozen(obj: Any): Boolean = obj.isFrozen +fun kotlinLambda(block: (Any) -> Any): Any = block + +fun multiply(int: Int, long: Long) = int * long + +class MyException : Exception() +class MyError : Error() + +@Throws(MyException::class, MyError::class) +fun throwException(error: Boolean): Unit { + throw if (error) MyError() else MyException() +} + +interface SwiftOverridableMethodsWithThrows { + @Throws(MyException::class) fun unit(): Unit + @Throws(MyException::class) fun nothing(): Nothing + @Throws(MyException::class) fun any(): Any + @Throws(MyException::class) fun block(): () -> Int +} + +interface MethodsWithThrows : SwiftOverridableMethodsWithThrows { + @Throws(MyException::class) fun nothingN(): Nothing? + @Throws(MyException::class) fun anyN(): Any? + @Throws(MyException::class) fun blockN(): (() -> Int)? + @Throws(MyException::class) fun pointer(): CPointer<*> + @Throws(MyException::class) fun pointerN(): CPointer<*>? + @Throws(MyException::class) fun int(): Int + @Throws(MyException::class) fun longN(): Long? + @Throws(MyException::class) fun double(): Double + + interface UnitCaller { + @Throws(MyException::class) fun call(methods: MethodsWithThrows): Unit + } +} + +open class Throwing : MethodsWithThrows { + @Throws(MyException::class) constructor(doThrow: Boolean) { + if (doThrow) throw MyException() + } + + override fun unit(): Unit = throw MyException() + override fun nothing(): Nothing = throw MyException() + override fun nothingN(): Nothing? = throw MyException() + override fun any(): Any = throw MyException() + override fun anyN(): Any? = throw MyException() + override fun block(): () -> Int = throw MyException() + override fun blockN(): (() -> Int)? = throw MyException() + override fun pointer(): CPointer<*> = throw MyException() + override fun pointerN(): CPointer<*>? = throw MyException() + override fun int(): Int = throw MyException() + override fun longN(): Long? = throw MyException() + override fun double(): Double = throw MyException() +} + +class NotThrowing : MethodsWithThrows { + @Throws(MyException::class) constructor() {} + + override fun unit(): Unit {} + override fun nothing(): Nothing = throw MyException() + override fun nothingN(): Nothing? = null + override fun any(): Any = Any() + override fun anyN(): Any? = Any() + override fun block(): () -> Int = { 42 } + override fun blockN(): (() -> Int)? = null + override fun pointer(): CPointer<*> = 1L.toCPointer()!! + override fun pointerN(): CPointer<*>? = null + override fun int(): Int = 42 + override fun longN(): Long? = null + override fun double(): Double = 3.14 +} + +@Throws(Throwable::class) +fun testSwiftThrowing(methods: SwiftOverridableMethodsWithThrows) = with(methods) { + assertSwiftThrowing { unit() } + assertSwiftThrowing { nothing() } + assertSwiftThrowing { any() } + assertSwiftThrowing { block() } +} + +private inline fun assertSwiftThrowing(block: () -> Unit) = + assertFailsWith(block = block) + +@Throws(Throwable::class) +fun testSwiftNotThrowing(methods: SwiftOverridableMethodsWithThrows) = with(methods) { + unit() + assertEquals(42, any()) + assertEquals(17, block()()) +} + +@Throws(MyError::class) +fun callUnit(methods: SwiftOverridableMethodsWithThrows) = methods.unit() + +@Throws(Throwable::class) +fun callUnitCaller(caller: MethodsWithThrows.UnitCaller, methods: MethodsWithThrows) { + assertFailsWith { caller.call(methods) } +} + +interface ThrowsWithBridgeBase { + @Throws(MyException::class) + fun plusOne(x: Int): Any +} + +abstract class ThrowsWithBridge : ThrowsWithBridgeBase { + abstract override fun plusOne(x: Int): Int +} + +@Throws(Throwable::class) +fun testSwiftThrowing(test: ThrowsWithBridgeBase, flag: Boolean) { + assertFailsWith { + if (flag) { + test.plusOne(0) + } else { + val test1 = test as ThrowsWithBridge + val ignore: Int = test1.plusOne(1) + } + } +} + +@Throws(Throwable::class) +fun testSwiftNotThrowing(test: ThrowsWithBridgeBase) { + assertEquals(3, test.plusOne(2)) + val test1 = test as ThrowsWithBridge + assertEquals(4, test1.plusOne(3)) +} + +fun Any.same() = this + +// https://github.com/JetBrains/kotlin-native/issues/2571 +val PROPERTY_NAME_MUST_NOT_BE_ALTERED_BY_SWIFT = 111 + +// https://github.com/JetBrains/kotlin-native/issues/2667 +class Deeply { + class Nested { + class Type { + val thirtyTwo = 32 + } + + interface IType + } +} + +class WithGenericDeeply() { + class Nested { + class Type { + val thirtyThree = 33 + } + } +} + +// https://github.com/JetBrains/kotlin-native/issues/3167 +class TypeOuter { + class Type { + val thirtyFour = 34 + } +} + +data class CKeywords(val float: Float, val `enum`: Int, var goto: Boolean) + +interface Base1 { + fun same(value: Int?): Int? +} + +interface ExtendedBase1 : Base1 { + override fun same(value: Int?): Int? +} + +interface Base2 { + fun same(value: Int?): Int? +} + +internal interface Base3 { + fun same(value: Int?): Int +} + +open class Base23 : Base2, Base3 { + override fun same(value: Int?): Int = error("should not reach here") +} + +fun call(base1: Base1, value: Int?) = base1.same(value) +fun call(extendedBase1: ExtendedBase1, value: Int?) = extendedBase1.same(value) +fun call(base2: Base2, value: Int?) = base2.same(value) +fun call(base3: Any, value: Int?) = (base3 as Base3).same(value) +fun call(base23: Base23, value: Int?) = base23.same(value) + +interface Transform { + fun map(value: T): R +} + +interface TransformWithDefault : Transform { + override fun map(value: T): T = value +} + +class TransformInheritingDefault : TransformWithDefault + +interface TransformIntString { + fun map(intValue: Int): String +} + +abstract class TransformIntToString : Transform, TransformIntString { + override abstract fun map(intValue: Int): String +} + +open class TransformIntToDecimalString : TransformIntToString() { + override fun map(intValue: Int): String = intValue.toString() +} + +private class TransformDecimalStringToInt : Transform { + override fun map(stringValue: String): Int = stringValue.toInt() +} + +fun createTransformDecimalStringToInt(): Transform = TransformDecimalStringToInt() + +open class TransformIntToLong : Transform { + override fun map(value: Int): Long = value.toLong() +} + +class GH2931 { + class Data + + class Holder { + val data = Data() + + init { + freeze() + } + } +} + +class GH2945(var errno: Int) { + fun testErrnoInSelector(p: Int, errno: Int) = p + errno +} + +class GH2830 { + interface I + private class PrivateImpl : I + + fun getI(): Any = PrivateImpl() +} + +class GH2959 { + interface I { + val id: Int + } + private class PrivateImpl(override val id: Int) : I + + fun getI(id: Int): List = listOf(PrivateImpl(id)) +} + +fun runUnitBlock(block: () -> Unit): Boolean { + val blockAny: () -> Any? = block + return blockAny() === Unit +} + +fun asUnitBlock(block: () -> Any?): () -> Unit = { block() } + +fun runNothingBlock(block: () -> Nothing) = try { + block() + false +} catch (e: Throwable) { + true +} + +fun asNothingBlock(block: () -> Any?): () -> Nothing = { + block() + TODO() +} + +fun getNullBlock(): (() -> Unit)? = null +fun isBlockNull(block: (() -> Unit)?): Boolean = block == null + +interface IntBlocks { + fun getPlusOneBlock(): T + fun callBlock(argument: Int, block: T): Int +} + +object IntBlocksImpl : IntBlocks<(Int) -> Int> { + override fun getPlusOneBlock(): (Int) -> Int = { it: Int -> it + 1 } + override fun callBlock(argument: Int, block: (Int) -> Int): Int = block(argument) +} + +interface UnitBlockCoercion { + fun coerce(block: () -> Unit): T + fun uncoerce(block: T): () -> Unit +} + +object UnitBlockCoercionImpl : UnitBlockCoercion<() -> Unit> { + override fun coerce(block: () -> Unit): () -> Unit = block + override fun uncoerce(block: () -> Unit): () -> Unit = block +} + +fun isFunction(obj: Any?): Boolean = obj is Function<*> +fun isFunction0(obj: Any?): Boolean = obj is Function0<*> + +abstract class MyAbstractList : List + +fun takeForwardDeclaredClass(obj: objcnames.classes.ForwardDeclaredClass) {} +fun takeForwardDeclaredProtocol(obj: objcnames.protocols.ForwardDeclaredProtocol) {} + +class TestKClass { + fun getKotlinClass(clazz: ObjCClass) = getOriginalKotlinClass(clazz) + fun getKotlinClass(protocol: ObjCProtocol) = getOriginalKotlinClass(protocol) + + fun isTestKClass(kClass: KClass<*>): Boolean = (kClass == TestKClass::class) + fun isI(kClass: KClass<*>): Boolean = (kClass == TestKClass.I::class) + + interface I +} + +// https://kotlinlang.slack.com/archives/C3SGXARS6/p1560954372179300 +interface ForwardI2 : ForwardI1 +interface ForwardI1 { + fun getForwardI2(): ForwardI2 +} + +abstract class ForwardC2 : ForwardC1() +abstract class ForwardC1 { + abstract fun getForwardC2(): ForwardC2 +} + +interface TestSR10177Workaround + +interface TestClashes1 { + val clashingProperty: Int +} + +interface TestClashes2 { + val clashingProperty: Any + val clashingProperty_: Any +} + +class TestClashesImpl : TestClashes1, TestClashes2 { + override val clashingProperty: Int + get() = 1 + + override val clashingProperty_: Int + get() = 2 +} + +class TestInvalidIdentifiers { + class `$Foo` + class `Bar$` + + fun `a$d$d`(`$1`: Int, `2`: Int, `3`: Int): Int = `$1` + `2` + `3` + + var `$status`: String = "" + + enum class E(val value: Int) { + `4$`(4), + `5$`(5), + `_`(6), + `__`(7) + } + + companion object `Companion$` { + val `42` = 42 + } + + val `$` = '$' + val `_` = '_' +} + +@Suppress("UNUSED_PARAMETER") +open class TestDeprecation() { + @Deprecated("hidden", level = DeprecationLevel.HIDDEN) open class OpenHidden : TestDeprecation() + @Suppress("DEPRECATION_ERROR") class ExtendingHidden : OpenHidden() { + class Nested + } + + @Deprecated("hidden", level = DeprecationLevel.HIDDEN) interface HiddenInterface { + fun effectivelyHidden(): Any + } + + @Suppress("DEPRECATION_ERROR") open class ImplementingHidden : Any(), HiddenInterface { + override fun effectivelyHidden(): Int = -1 + } + + @Suppress("DEPRECATION_ERROR") + fun callEffectivelyHidden(obj: Any): Int = (obj as HiddenInterface).effectivelyHidden() as Int + + @Deprecated("hidden", level = DeprecationLevel.HIDDEN) class Hidden : TestDeprecation() { + open class Nested { + class Nested + inner class Inner + } + + inner class Inner { + inner class Inner + } + } + + @Suppress("DEPRECATION_ERROR") class ExtendingNestedInHidden : Hidden.Nested() + + @Suppress("DEPRECATION_ERROR") fun getHidden() = Hidden() + + @Deprecated("hidden", level = DeprecationLevel.HIDDEN) constructor(hidden: Byte) : this() + @Deprecated("hidden", level = DeprecationLevel.HIDDEN) fun hidden() {} + @Deprecated("hidden", level = DeprecationLevel.HIDDEN) val hiddenVal: Any? = null + @Deprecated("hidden", level = DeprecationLevel.HIDDEN) var hiddenVar: Any? = null + @Deprecated("hidden", level = DeprecationLevel.HIDDEN) open fun openHidden() {} + @Deprecated("hidden", level = DeprecationLevel.HIDDEN) open val openHiddenVal: Any? = null + @Deprecated("hidden", level = DeprecationLevel.HIDDEN) open var openHiddenVar: Any? = null + + @Deprecated("error", level = DeprecationLevel.ERROR) open class OpenError : TestDeprecation() + @Suppress("DEPRECATION_ERROR") class ExtendingError : OpenError() + + @Deprecated("error", level = DeprecationLevel.ERROR) interface ErrorInterface + @Suppress("DEPRECATION_ERROR") class ImplementingError : ErrorInterface + + @Deprecated("error", level = DeprecationLevel.ERROR) class Error : TestDeprecation() + @Suppress("DEPRECATION_ERROR") fun getError() = Error() + + @Deprecated("error", level = DeprecationLevel.ERROR) constructor(error: Short) : this() + @Deprecated("error", level = DeprecationLevel.ERROR) fun error() {} + @Deprecated("error", level = DeprecationLevel.ERROR) val errorVal: Any? = null + @Deprecated("error", level = DeprecationLevel.ERROR) var errorVar: Any? = null + @Deprecated("error", level = DeprecationLevel.ERROR) open fun openError() {} + @Deprecated("error", level = DeprecationLevel.ERROR) open val openErrorVal: Any? = null + @Deprecated("error", level = DeprecationLevel.ERROR) open var openErrorVar: Any? = null + + @Deprecated("warning", level = DeprecationLevel.WARNING) open class OpenWarning : TestDeprecation() + @Suppress("DEPRECATION") class ExtendingWarning : OpenWarning() + + @Deprecated("warning", level = DeprecationLevel.WARNING) interface WarningInterface + @Suppress("DEPRECATION") class ImplementingWarning : WarningInterface + + @Deprecated("warning", level = DeprecationLevel.WARNING) class Warning : TestDeprecation() + @Suppress("DEPRECATION") fun getWarning() = Warning() + + @Deprecated("warning", level = DeprecationLevel.WARNING) constructor(warning: Int) : this() + @Deprecated("warning", level = DeprecationLevel.WARNING) fun warning() {} + @Deprecated("warning", level = DeprecationLevel.WARNING) val warningVal: Any? = null + @Deprecated("warning", level = DeprecationLevel.WARNING) var warningVar: Any? = null + @Deprecated("warning", level = DeprecationLevel.WARNING) open fun openWarning() {} + @Deprecated("warning", level = DeprecationLevel.WARNING) open val openWarningVal: Any? = null + @Deprecated("warning", level = DeprecationLevel.WARNING) open var openWarningVar: Any? = null + + constructor(normal: Long) : this() + fun normal() {} + val normalVal: Any? = null + var normalVar: Any? = null + open fun openNormal(): Int = 1 + open val openNormalVal: Any? = null + open var openNormalVar: Any? = null + + class HiddenOverride() : TestDeprecation() { + @Deprecated("hidden", level = DeprecationLevel.HIDDEN) constructor(hidden: Byte) : this() + @Deprecated("hidden", level = DeprecationLevel.HIDDEN) override fun openHidden() {} + @Deprecated("hidden", level = DeprecationLevel.HIDDEN) override val openHiddenVal: Any? = null + @Deprecated("hidden", level = DeprecationLevel.HIDDEN) override var openHiddenVar: Any? = null + + @Deprecated("hidden", level = DeprecationLevel.HIDDEN) constructor(error: Short) : this() + @Deprecated("hidden", level = DeprecationLevel.HIDDEN) override fun openError() {} + @Deprecated("hidden", level = DeprecationLevel.HIDDEN) override val openErrorVal: Any? = null + @Deprecated("hidden", level = DeprecationLevel.HIDDEN) override var openErrorVar: Any? = null + + @Deprecated("hidden", level = DeprecationLevel.HIDDEN) constructor(warning: Int) : this() + @Deprecated("hidden", level = DeprecationLevel.HIDDEN) override fun openWarning() {} + @Deprecated("hidden", level = DeprecationLevel.HIDDEN) override val openWarningVal: Any? = null + @Deprecated("hidden", level = DeprecationLevel.HIDDEN) override var openWarningVar: Any? = null + + @Deprecated("hidden", level = DeprecationLevel.HIDDEN) constructor(normal: Long) : this() + @Deprecated("hidden", level = DeprecationLevel.HIDDEN) override fun openNormal(): Int = 2 + @Deprecated("hidden", level = DeprecationLevel.HIDDEN) override val openNormalVal: Any? = null + @Deprecated("hidden", level = DeprecationLevel.HIDDEN) override var openNormalVar: Any? = null + } + + class ErrorOverride() : TestDeprecation() { + @Deprecated("error", level = DeprecationLevel.ERROR) constructor(hidden: Byte) : this() + @Deprecated("error", level = DeprecationLevel.ERROR) override fun openHidden() {} + @Deprecated("error", level = DeprecationLevel.ERROR) override val openHiddenVal: Any? = null + @Deprecated("error", level = DeprecationLevel.ERROR) override var openHiddenVar: Any? = null + + @Deprecated("error", level = DeprecationLevel.ERROR) constructor(error: Short) : this() + @Deprecated("error", level = DeprecationLevel.ERROR) override fun openError() {} + @Deprecated("error", level = DeprecationLevel.ERROR) override val openErrorVal: Any? = null + @Deprecated("error", level = DeprecationLevel.ERROR) override var openErrorVar: Any? = null + + @Deprecated("error", level = DeprecationLevel.ERROR) constructor(warning: Int) : this() + @Deprecated("error", level = DeprecationLevel.ERROR) override fun openWarning() {} + @Deprecated("error", level = DeprecationLevel.ERROR) override val openWarningVal: Any? = null + @Deprecated("error", level = DeprecationLevel.ERROR) override var openWarningVar: Any? = null + + @Deprecated("error", level = DeprecationLevel.ERROR) constructor(normal: Long) : this() + @Deprecated("error", level = DeprecationLevel.ERROR) override fun openNormal(): Int = 3 + @Deprecated("error", level = DeprecationLevel.ERROR) override val openNormalVal: Any? = null + @Deprecated("error", level = DeprecationLevel.ERROR) override var openNormalVar: Any? = null + } + + class WarningOverride() : TestDeprecation() { + @Deprecated("warning", level = DeprecationLevel.WARNING) constructor(hidden: Byte) : this() + @Deprecated("warning", level = DeprecationLevel.WARNING) override fun openHidden() {} + @Deprecated("warning", level = DeprecationLevel.WARNING) override val openHiddenVal: Any? = null + @Deprecated("warning", level = DeprecationLevel.WARNING) override var openHiddenVar: Any? = null + + @Deprecated("warning", level = DeprecationLevel.WARNING) constructor(error: Short) : this() + @Deprecated("warning", level = DeprecationLevel.WARNING) override fun openError() {} + @Deprecated("warning", level = DeprecationLevel.WARNING) override val openErrorVal: Any? = null + @Deprecated("warning", level = DeprecationLevel.WARNING) override var openErrorVar: Any? = null + + @Deprecated("warning", level = DeprecationLevel.WARNING) constructor(warning: Int) : this() + @Deprecated("warning", level = DeprecationLevel.WARNING) override fun openWarning() {} + @Deprecated("warning", level = DeprecationLevel.WARNING) override val openWarningVal: Any? = null + @Deprecated("warning", level = DeprecationLevel.WARNING) override var openWarningVar: Any? = null + + @Deprecated("warning", level = DeprecationLevel.WARNING) constructor(normal: Long) : this() + @Deprecated("warning", level = DeprecationLevel.WARNING) override fun openNormal(): Int = 4 + @Deprecated("warning", level = DeprecationLevel.WARNING) override val openNormalVal: Any? = null + @Deprecated("warning", level = DeprecationLevel.WARNING) override var openNormalVar: Any? = null + } + + class NormalOverride() : TestDeprecation() { + constructor(hidden: Byte) : this() + override fun openHidden() {} + override val openHiddenVal: Any? = null + override var openHiddenVar: Any? = null + + constructor(error: Short) : this() + override fun openError() {} + override val openErrorVal: Any? = null + override var openErrorVar: Any? = null + + constructor(warning: Int) : this() + override fun openWarning() {} + override val openWarningVal: Any? = null + override var openWarningVar: Any? = null + + constructor(normal: Long) : this() + override fun openNormal(): Int = 5 + override val openNormalVal: Any? = null + override var openNormalVar: Any? = null + } + + @Suppress("DEPRECATION_ERROR") fun test(hiddenNested: Hidden.Nested) {} + @Suppress("DEPRECATION_ERROR") fun test(hiddenNestedNested: Hidden.Nested.Nested) {} + @Suppress("DEPRECATION_ERROR") fun test(hiddenNestedInner: Hidden.Nested.Inner) {} + @Suppress("DEPRECATION_ERROR") fun test(hiddenInner: Hidden.Inner) {} + @Suppress("DEPRECATION_ERROR") fun test(hiddenInnerInner: Hidden.Inner.Inner) {} + + @Suppress("DEPRECATION_ERROR") fun test(topLevelHidden: TopLevelHidden) {} + @Suppress("DEPRECATION_ERROR") fun test(topLevelHiddenNested: TopLevelHidden.Nested) {} + @Suppress("DEPRECATION_ERROR") fun test(topLevelHiddenNestedNested: TopLevelHidden.Nested.Nested) {} + @Suppress("DEPRECATION_ERROR") fun test(topLevelHiddenNestedInner: TopLevelHidden.Nested.Inner) {} + @Suppress("DEPRECATION_ERROR") fun test(topLevelHiddenInner: TopLevelHidden.Inner) {} + @Suppress("DEPRECATION_ERROR") fun test(topLevelHiddenInnerInner: TopLevelHidden.Inner.Inner) {} + + @Suppress("DEPRECATION_ERROR") fun test(extendingHiddenNested: ExtendingHidden.Nested) {} + @Suppress("DEPRECATION_ERROR") fun test(extendingNestedInHidden: ExtendingNestedInHidden) {} + +} + +@Deprecated("hidden", level = DeprecationLevel.HIDDEN) class TopLevelHidden { + class Nested { + class Nested + inner class Inner + } + + inner class Inner { + inner class Inner + } +} + +@Deprecated("hidden", level = DeprecationLevel.HIDDEN) fun hidden() {} +@Deprecated("hidden", level = DeprecationLevel.HIDDEN) val hiddenVal: Any? = null +@Deprecated("hidden", level = DeprecationLevel.HIDDEN) var hiddenVar: Any? = null + +@Deprecated("error", level = DeprecationLevel.ERROR) fun error() {} +@Deprecated("error", level = DeprecationLevel.ERROR) val errorVal: Any? = null +@Deprecated("error", level = DeprecationLevel.ERROR) var errorVar: Any? = null + +@Deprecated("warning", level = DeprecationLevel.WARNING) fun warning() {} +@Deprecated("warning", level = DeprecationLevel.WARNING) val warningVal: Any? = null +@Deprecated("warning", level = DeprecationLevel.WARNING) var warningVar: Any? = null + +fun gc() { + kotlin.native.internal.GC.collect() +} + +class TestWeakRefs(private val frozen: Boolean) { + private var obj: Any? = Any().also { + if (frozen) it.freeze() + } + + fun getObj() = obj!! + + fun clearObj() { + obj = null + } + + fun createCycle(): List { + val node1 = Node(null) + val node2 = Node(node1) + node1.next = node2 + + if (frozen) node1.freeze() + + return listOf(node1, node2) + } + + private class Node(var next: Node?) +} + +class SharedRefs { + class MutableData { + var x = 0 + + fun update() { x += 1 } + } + + fun createRegularObject(): MutableData = create { MutableData() } + + fun createLambda(): () -> Unit = create { + var mutableData = 0 + { + println(mutableData++) + } + } + + fun createCollection(): MutableList = create { + mutableListOf() + } + + fun createFrozenRegularObject() = createRegularObject().freeze() + fun createFrozenLambda() = createLambda().freeze() + fun createFrozenCollection() = createCollection().freeze() + + fun hasAliveObjects(): Boolean { + kotlin.native.internal.GC.collect() + return mustBeRemoved.any { it.get() != null } + } + + private fun create(block: () -> T) = block() + .also { mustBeRemoved += WeakReference(it) } + + private val mustBeRemoved = mutableListOf>() +} + +interface TestRememberNewObject { + fun getObject(): Any + fun waitForCleanup() +} + +fun testRememberNewObject(test: TestRememberNewObject) { + val obj = autoreleasepool { test.getObject() } + test.waitForCleanup() + assertNotEquals("", obj.toString()) // Likely crashes if object is removed. +} + +open class ClassForTypeCheck + +fun testClassTypeCheck(x: Any) = x is ClassForTypeCheck + +interface InterfaceForTypeCheck + +fun testInterfaceTypeCheck(x: Any) = x is InterfaceForTypeCheck + +interface IAbstractInterface { + fun foo(): Int +} + +interface IAbstractInterface2 { + fun foo() = 42 +} + +fun testAbstractInterfaceCall(x: IAbstractInterface) = x.foo() +fun testAbstractInterfaceCall2(x: IAbstractInterface2) = x.foo() + +abstract class AbstractInterfaceBase : IAbstractInterface { + override fun foo() = bar() + + abstract fun bar(): Int +} + +abstract class AbstractInterfaceBase2 : IAbstractInterface2 + +abstract class AbstractInterfaceBase3 : IAbstractInterface { + abstract override fun foo(): Int +} + +var gh3525BaseInitCount = 0 + +open class GH3525Base { + init { + gh3525BaseInitCount++ + } +} + +var gh3525InitCount = 0 + +object GH3525 : GH3525Base() { + init { + gh3525InitCount++ + } +} + +class TestStringConversion { + lateinit var str: Any +} + +fun foo(a: kotlin.native.concurrent.AtomicReference<*>) {} + +interface GH3825 { + @Throws(MyException::class) fun call0(callback: () -> Boolean) + @Throws(MyException::class) fun call1(doThrow: Boolean, callback: () -> Unit) + @Throws(MyException::class) fun call2(callback: () -> Unit, doThrow: Boolean) +} + +class GH3825KotlinImpl : GH3825 { + override fun call0(callback: () -> Boolean) { + if (callback()) throw MyException() + } + + override fun call1(doThrow: Boolean, callback: () -> Unit) { + if (doThrow) throw MyException() + callback() + } + + override fun call2(callback: () -> Unit, doThrow: Boolean) { + if (doThrow) throw MyException() + callback() + } +} + +@Throws(Throwable::class) +fun testGH3825(gh3825: GH3825) { + var count = 0 + + assertFailsWith { gh3825.call0({ true }) } + gh3825.call0({ count += 1; false }) + assertEquals(1, count) + + assertFailsWith { gh3825.call1(true, { fail() }) } + gh3825.call1(false, { count += 1 }) + assertEquals(2, count) + + assertFailsWith { gh3825.call2({ fail() }, true) } + gh3825.call2({ count += 1 }, false) + assertEquals(3, count) +} + +fun mapBoolean2String(): Map = mapOf(Pair(false, "false"), Pair(true, "true")) +fun mapByte2Short(): Map = mapOf(Pair(-1, 2)) +fun mapShort2Byte(): Map = mapOf(Pair(-2, 1)) +fun mapInt2Long(): Map = mapOf(Pair(-4, 8)) +fun mapLong2Long(): Map = mapOf(Pair(-8, 8)) +fun mapUByte2Boolean(): Map = mapOf(Pair(0x80U, true)) +fun mapUShort2Byte(): Map = mapOf(Pair(0x8000U, 1)) +fun mapUInt2Long(): Map = mapOf(Pair(0x7FFF_FFFFU, 7), Pair(0x8000_0000U, 8)) +fun mapULong2Long(): Map = mapOf(Pair(0x8000_0000_0000_0000UL, 8)) +fun mapFloat2Float(): Map = mapOf(Pair(3.14f, 100f)) +fun mapDouble2String(): Map = mapOf(Pair(2.718281828459045, "2.718281828459045")) + +fun mutBoolean2String(): MutableMap = mutableMapOf(Pair(false, "false"), Pair(true, "true")) +fun mutByte2Short(): MutableMap = mutableMapOf(Pair(-1, 2)) +fun mutShort2Byte(): MutableMap = mutableMapOf(Pair(-2, 1)) +fun mutInt2Long(): MutableMap = mutableMapOf(Pair(-4, 8)) +fun mutLong2Long(): MutableMap = mutableMapOf(Pair(-8, 8)) +fun mutUByte2Boolean(): MutableMap = mutableMapOf(Pair(128U, true)) +fun mutUShort2Byte(): MutableMap = mutableMapOf(Pair(32768U, 1)) +fun mutUInt2Long(): MutableMap = mutableMapOf(Pair(0x8000_0000U, 8)) +fun mutULong2Long(): MutableMap = mutableMapOf(Pair(0x8000_0000_0000_0000UL, 8)) +fun mutFloat2Float(): MutableMap = mutableMapOf(Pair(3.14f, 100f)) +fun mutDouble2String(): MutableMap = mutableMapOf(Pair(2.718281828459045, "2.718281828459045")) + diff --git a/kotlin-native/backend.native/tests/objcexport/values.swift b/kotlin-native/backend.native/tests/objcexport/values.swift new file mode 100644 index 00000000000..8ae7fe998ed --- /dev/null +++ b/kotlin-native/backend.native/tests/objcexport/values.swift @@ -0,0 +1,1381 @@ +/* + * Copyright 2010-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +import Foundation +import Kt + +// -------- Tests -------- + +func testVals() throws { + print("Values from Swift") + let dbl = ValuesKt.dbl + let flt = ValuesKt.flt + let int = ValuesKt.integer + let long = ValuesKt.longInt + + print(dbl) + print(flt) + print(int) + print(long) + + try assertEquals(actual: dbl, expected: 3.14 as Double, "Double value isn't equal.") + try assertEquals(actual: flt, expected: 2.73 as Float, "Float value isn't equal.") + try assertEquals(actual: int, expected: 42) + try assertEquals(actual: long, expected: 1984) +} + +func testVars() throws { + print("Variables from Swift") + var intVar = ValuesKt.intVar + var strVar = ValuesKt.str + var strAsId = ValuesKt.strAsAny + + print(intVar) + print(strVar) + print(strAsId) + + try assertEquals(actual: intVar, expected: 451) + try assertEquals(actual: strVar, expected: "Kotlin String") + try assertEquals(actual: strAsId as! String, expected: "Kotlin String as Any") + + strAsId = "Swift str" + ValuesKt.strAsAny = strAsId + print(ValuesKt.strAsAny) + try assertEquals(actual: ValuesKt.strAsAny as! String, expected: strAsId as! String) + + // property with custom getter/setter backed by the Kotlin's var + var intProp : Int32 { + get { + return ValuesKt.intVar * 2 + } + set(value) { + ValuesKt.intVar = 123 + value + } + } + intProp += 10 + print(intProp) + print(ValuesKt.intVar) + try assertEquals(actual: ValuesKt.intVar * 2, expected: intProp, "Property backed by var") +} + +func testDoubles() throws { + print("Doubles in Swift") + let minDouble = ValuesKt.minDoubleVal as! Double + let maxDouble = ValuesKt.maxDoubleVal as! NSNumber + + print(minDouble) + print(maxDouble) + print(ValuesKt.nanDoubleVal) + print(ValuesKt.nanFloatVal) + print(ValuesKt.infDoubleVal) + print(ValuesKt.infFloatVal) + + try assertEquals(actual: minDouble, expected: Double.leastNonzeroMagnitude, "Min double") + try assertEquals(actual: maxDouble, expected: Double.greatestFiniteMagnitude as NSNumber, "Max double") + try assertTrue(ValuesKt.nanDoubleVal.isNaN, "NaN double") + try assertTrue(ValuesKt.nanFloatVal.isNaN, "NaN float") + try assertEquals(actual: ValuesKt.infDoubleVal, expected: Double.infinity, "Inf double") + try assertEquals(actual: ValuesKt.infFloatVal, expected: -Float.infinity, "-Inf float") +} + +func testNumbers() throws { + try assertEquals(actual: KotlinBoolean(value: true).boolValue, expected: true) + try assertEquals(actual: KotlinBoolean(value: false).intValue, expected: 0) + try assertEquals(actual: KotlinBoolean(value: true), expected: true) + try assertFalse(KotlinBoolean(value: false) as! Bool) + + try assertEquals(actual: KotlinByte(value: -1).int8Value, expected: -1) + try assertEquals(actual: KotlinByte(value: -1).int32Value, expected: -1) + try assertEquals(actual: KotlinByte(value: -1).doubleValue, expected: -1.0) + try assertEquals(actual: KotlinByte(value: -1), expected: NSNumber(value: Int64(-1))) + try assertFalse(KotlinByte(value: -1) == NSNumber(value: -1.5)) + try assertEquals(actual: KotlinByte(value: -1), expected: -1) + try assertTrue(KotlinByte(value: -1) == -1) + try assertFalse(KotlinByte(value: -1) == 1) + try assertEquals(actual: KotlinByte(value: -1) as! Int32, expected: -1) + + try assertEquals(actual: KotlinShort(value: 111).int16Value, expected: 111) + try assertEquals(actual: KotlinShort(value: -15) as! Int16, expected: -15) + try assertEquals(actual: KotlinShort(value: 47), expected: 47) + + try assertEquals(actual: KotlinInt(value: 99).int32Value, expected: 99) + try assertEquals(actual: KotlinInt(value: -1) as! Int32, expected: -1) + try assertEquals(actual: KotlinInt(value: 72), expected: 72) + + try assertEquals(actual: KotlinLong(value: 65).int64Value, expected: 65) + try assertEquals(actual: KotlinLong(value: 10000000000) as! Int64, expected: 10000000000) + try assertEquals(actual: KotlinLong(value: 8), expected: 8) + + try assertEquals(actual: KotlinUByte(value: 17).uint8Value, expected: 17) + try assertEquals(actual: KotlinUByte(value: 42) as! UInt8, expected: 42) + try assertEquals(actual: 88, expected: KotlinUByte(value: 88)) + + try assertEquals(actual: KotlinUShort(value: 40000).uint16Value, expected: 40000) + try assertEquals(actual: KotlinUShort(value: 1) as! UInt16, expected: UInt16(1)) + try assertEquals(actual: KotlinUShort(value: 65000), expected: 65000) + + try assertEquals(actual: KotlinUInt(value: 3).uint32Value, expected: 3) + try assertEquals(actual: KotlinUInt(value: UInt32.max) as! UInt32, expected: UInt32.max) + try assertEquals(actual: KotlinUInt(value: 2), expected: 2) + + try assertEquals(actual: KotlinULong(value: 55).uint64Value, expected: 55) + try assertEquals(actual: KotlinULong(value: 0) as! UInt64, expected: 0) + try assertEquals(actual: KotlinULong(value: 7), expected: 7) + + try assertEquals(actual: KotlinFloat(value: 1.0).floatValue, expected: 1.0) + try assertEquals(actual: KotlinFloat(value: 22.0) as! Float, expected: 22) + try assertEquals(actual: KotlinFloat(value: 41.0), expected: 41) + try assertEquals(actual: KotlinFloat(value: -5.5), expected: -5.5) + + try assertEquals(actual: KotlinDouble(value: 0.5).doubleValue, expected: 0.5) + try assertEquals(actual: KotlinDouble(value: 45.0) as! Double, expected: 45) + try assertEquals(actual: KotlinDouble(value: 89.0), expected: 89) + try assertEquals(actual: KotlinDouble(value: -3.7), expected: -3.7) + + ValuesKt.ensureEqualBooleans(actual: KotlinBoolean(value: true), expected: true) + ValuesKt.ensureEqualBooleans(actual: false, expected: false) + + ValuesKt.ensureEqualBytes(actual: KotlinByte(value: 42), expected: 42) + ValuesKt.ensureEqualBytes(actual: -11, expected: -11) + + ValuesKt.ensureEqualShorts(actual: KotlinShort(value: 256), expected: 256) + ValuesKt.ensureEqualShorts(actual: -1, expected: -1) + + ValuesKt.ensureEqualInts(actual: KotlinInt(value: 100000), expected: 100000) + ValuesKt.ensureEqualInts(actual: -7, expected: -7) + + ValuesKt.ensureEqualLongs(actual: KotlinLong(value: Int64.max), expected: Int64.max) + ValuesKt.ensureEqualLongs(actual: 17, expected: 17) + + ValuesKt.ensureEqualUBytes(actual: KotlinUByte(value: 6), expected: 6) + ValuesKt.ensureEqualUBytes(actual: 255, expected: 255) + + ValuesKt.ensureEqualUShorts(actual: KotlinUShort(value: 300), expected: 300) + ValuesKt.ensureEqualUShorts(actual: 65535, expected: UInt16.max) + + ValuesKt.ensureEqualUInts(actual: KotlinUInt(value: 70000), expected: 70000) + ValuesKt.ensureEqualUInts(actual: 48, expected: 48) + + ValuesKt.ensureEqualULongs(actual: KotlinULong(value: UInt64.max), expected: UInt64.max) + ValuesKt.ensureEqualULongs(actual: 39, expected: 39) + + ValuesKt.ensureEqualFloats(actual: KotlinFloat(value: 36.6), expected: 36.6) + ValuesKt.ensureEqualFloats(actual: 49.5, expected: 49.5) + ValuesKt.ensureEqualFloats(actual: 18, expected: 18.0) + + ValuesKt.ensureEqualDoubles(actual: KotlinDouble(value: 12.34), expected: 12.34) + ValuesKt.ensureEqualDoubles(actual: 56.78, expected: 56.78) + ValuesKt.ensureEqualDoubles(actual: 3, expected: 3) + + func checkBox(_ value: T, _ boxFunction: (T) -> B?) throws { + let box = boxFunction(value)! + try assertEquals(actual: box as! T, expected: value) + print(type(of: box)) + print(B.self) + try assertTrue(box.isKind(of: B.self)) + } + + try checkBox(true, ValuesKt.box) + try checkBox(Int8(-1), ValuesKt.box) + try checkBox(Int16(-2), ValuesKt.box) + try checkBox(Int32(-3), ValuesKt.box) + try checkBox(Int64(-4), ValuesKt.box) + try checkBox(UInt8(5), ValuesKt.box) + try checkBox(UInt16(6), ValuesKt.box) + try checkBox(UInt32(7), ValuesKt.box) + try checkBox(UInt64(8), ValuesKt.box) + try checkBox(Float(8.7), ValuesKt.box) + try checkBox(Double(9.4), ValuesKt.box) +} + +func testLists() throws { + let numbersList = ValuesKt.numbersList + let gold = [1, 2, 13] + for i in 0.. Void { throw E() } + func nothing() throws -> Void { throw E() } + func any() throws -> Any { throw E() } + func block() throws -> () -> KotlinInt { throw E() } +} + +class TestThrowingConstructorRelease : Throwing { + static var deinitialized = false + deinit { + TestThrowingConstructorRelease.deinitialized = true + } +} + +class SwiftNotThrowing : SwiftOverridableMethodsWithThrows { + func unit() throws -> Void { } + func nothing() throws -> Void { throw SwiftThrowing.E() } + func any() throws -> Any { return 42 as Int32 } + func block() throws -> () -> KotlinInt { return { 17 } } +} + +class SwiftUnitCaller : MethodsWithThrowsUnitCaller { + func call(methods: MethodsWithThrows) throws -> Void { + try methods.unit() + } +} + +class SwiftThrowingWithBridge : ThrowsWithBridge { + override func plusOne(x: Int32) throws -> KotlinInt { + throw SwiftThrowing.E() + } +} + +class SwiftNotThrowingWithBridge : ThrowsWithBridge { + override func plusOne(x: Int32) throws -> KotlinInt { + return KotlinInt(value: x + 1) + } +} + +private func testThrowing(file: String = #file, line: Int = #line, _ block: () throws -> Void) throws { + try assertFailsWithKotlin(MyException.self, file: file, line: line, block: block) +} + +func testExceptions() throws { + try testThrowing { try ValuesKt.throwException(error: false) } + do { + try ValuesKt.throwException(error: true) + } catch let error as NSError { + try assertTrue(error.kotlinException is MyError) + } + + try assertFalse(TestThrowingConstructorRelease.deinitialized) + try testThrowing { try TestThrowingConstructorRelease(doThrow: true) } + ValuesKt.gc() + try assertTrue(TestThrowingConstructorRelease.deinitialized) + + try testThrowing { try Throwing(doThrow: true) } + + let throwing = try Throwing(doThrow: false) + try testThrowing { try throwing.unit() } + try testThrowing { try throwing.nothing() } + try testThrowing { try throwing.nothingN() } + try testThrowing { try throwing.any() } + try testThrowing { try throwing.anyN() } + try testThrowing { try throwing.block()() } + try testThrowing { try throwing.blockN() } + try testThrowing { try throwing.pointer() } + try testThrowing { try throwing.pointerN() } + try testThrowing { try throwing.int() } + try testThrowing { try throwing.longN() } + try testThrowing { try throwing.double() } + + let notThrowing = try NotThrowing() + + try notThrowing.unit() + try assertEquals(actual: notThrowing.nothingN(), expected: nil) + try assertTrue(notThrowing.any() is KotlinBase) + try assertTrue(notThrowing.anyN() is KotlinBase) + try assertEquals(actual: notThrowing.block()(), expected: 42) + try assertTrue(notThrowing.blockN() == nil) + try assertEquals(actual: Int(bitPattern: notThrowing.pointer()), expected: 1) + try assertEquals(actual: notThrowing.pointerN(), expected: nil) + try assertEquals(actual: notThrowing.int(), expected: 42) + try assertEquals(actual: notThrowing.longN(), expected: nil) + try assertEquals(actual: notThrowing.double(), expected: 3.14) + + try ValuesKt.testSwiftThrowing(methods: SwiftThrowing()) + try ValuesKt.testSwiftNotThrowing(methods: SwiftNotThrowing()) + + do { + try ValuesKt.callUnit(methods: SwiftThrowing()) + } catch let e as SwiftThrowing.E { + // Ok. + } + + try ValuesKt.callUnitCaller(caller: SwiftUnitCaller(), methods: throwing) + + try ValuesKt.testSwiftThrowing(test: SwiftThrowingWithBridge(), flag: false) + try ValuesKt.testSwiftThrowing(test: SwiftThrowingWithBridge(), flag: true) + try ValuesKt.testSwiftNotThrowing(test: SwiftNotThrowingWithBridge()) +} + +func testFuncType() throws { + let s = "str" + let fFunc: () -> String = { return s } + try assertEquals(actual: ValuesKt.funArgument(foo: fFunc), expected: s, "Using function type arguments failed") +} + +func testGenericsFoo() throws { + let fun = { (i: Int) -> String in return "S \(i)" } + // wrap lambda to workaround issue with type conversion inability: + // (Int) -> String can't be cast to (Any?) -> Any? + let wrapper = { (t: Any?) -> Any? in return fun(t as! Int) } + let res = ValuesKt.genericFoo(t: 42, foo: wrapper) + try assertEquals(actual: res as! String, expected: "S 42") +} + +func testVararg() throws { + let ktArray = KotlinArray(size: 3, init: { (_) -> NSNumber in return 42 }) + let arr: [Int] = ValuesKt.varargToList(args: ktArray) as! [Int] + try assertEquals(actual: arr, expected: [42, 42, 42]) +} + +func testStrExtFun() throws { + try assertEquals(actual: ValuesKt.subExt("String", i: 2), expected: "r") + try assertEquals(actual: ValuesKt.subExt("A", i: 2), expected: "nothing") +} + +func testAnyToString() throws { + try assertEquals(actual: ValuesKt.toString(nil), expected: "null") + try assertEquals(actual: ValuesKt.toString(42), expected: "42") +} + +func testAnyPrint() throws { + print("BEGIN") + ValuesKt.print(nil) + ValuesKt.print("Print") + ValuesKt.print(123456789) + ValuesKt.print(3.14) + ValuesKt.print([3, 2, 1]) + print("END") +} + +func testCharExtensions() throws { + try assertTrue(ValuesKt.isA(ValuesKt.boxChar(65))) + try assertFalse(ValuesKt.isA(ValuesKt.boxChar(66))) +} + +func testLambda() throws { + try assertEquals(actual: ValuesKt.sumLambda(3, 4), expected: 7) + + var blockRuns = 0 + + try assertTrue(ValuesKt.runUnitBlock { blockRuns += 1 }) + try assertEquals(actual: blockRuns, expected: 1) + + let unitBlock: () -> Void = ValuesKt.asUnitBlock { + blockRuns += 1 + return 42 + } + try assertTrue(unitBlock() == Void()) + try assertEquals(actual: blockRuns, expected: 2) + + let nothingBlock: () -> Void = ValuesKt.asNothingBlock { blockRuns += 1 } + try assertTrue(ValuesKt.runNothingBlock(block: nothingBlock)) + try assertEquals(actual: blockRuns, expected: 3) + + try assertTrue(ValuesKt.getNullBlock() == nil) + try assertTrue(ValuesKt.isBlockNull(block: nil)) + + // Test dynamic conversion: + let intBlocks = IntBlocksImpl() + try assertEquals(actual: intBlocks.getPlusOneBlock()(1), expected: 2) + try assertEquals(actual: intBlocks.callBlock(argument: 2) { KotlinInt(value: $0.int32Value + 2) }, expected: 4) + + // Test round trip with dynamic conversion: + let coercedUnitBlock: () -> KotlinUnit = UnitBlockCoercionImpl().coerce { blockRuns += 1 } + try assertTrue(coercedUnitBlock() === KotlinUnit()) + try assertEquals(actual: blockRuns, expected: 4) + + let uncoercedUnitBlock: () -> Void = UnitBlockCoercionImpl().uncoerce { + blockRuns += 1 + return KotlinUnit() + } + try assertTrue(uncoercedUnitBlock() == Void()) + try assertEquals(actual: blockRuns, expected: 5) + + let blockMustBeFunction0: @convention(block) () -> AnyObject? = { return nil } + try assertTrue(ValuesKt.isFunction(obj: blockMustBeFunction0)) + try assertTrue(ValuesKt.isFunction0(obj: blockMustBeFunction0)) + try assertFalse(ValuesKt.isFunction(obj: NSObject())) + try assertFalse(ValuesKt.isFunction0(obj: NSObject())) + + // Test no function class for dynamic conversion: + let blockAsMissingFunction: @convention(block) (AnyObject?, AnyObject?, AnyObject?, AnyObject?, AnyObject?) -> AnyObject? + = { return $0 ?? $1 ?? $2 ?? $3 ?? $4 } + + try assertTrue(ValuesKt.isFunction(obj: blockAsMissingFunction)) + try assertFalse(ValuesKt.isFunction0(obj: blockAsMissingFunction)) +} + +// -------- Tests for classes and interfaces ------- +class ValIEmptyExt : I { + func iFun() -> String { + return "ValIEmptyExt::iFun" + } +} + +class ValIExt : I { + func iFun() -> String { + return "ValIExt::iFun" + } +} + +func testInterfaceExtension() throws { + try assertEquals(actual: ValIEmptyExt().iFun(), expected: "ValIEmptyExt::iFun") + try assertEquals(actual: ValIExt().iFun(), expected: "ValIExt::iFun") +} + +func testClassInstances() throws { + try assertEquals(actual: OpenClassI().iFun(), expected: "OpenClassI::iFun") + try assertEquals(actual: DefaultInterfaceExt().iFun(), expected: "I::iFun") + try assertEquals(actual: FinalClassExtOpen().iFun(), expected: "FinalClassExtOpen::iFun") + try assertEquals(actual: MultiExtClass().iFun(), expected: "PI::iFun") + try assertEquals(actual: MultiExtClass().piFun() as! Int, expected: 42) + try assertEquals(actual: ConstrClass(i: 1, s: "str", a: "Any").iFun(), expected: "OpenClassI::iFun") + try assertEquals(actual: ExtConstrClass(i: 123).iFun(), expected: "ExtConstrClass::iFun::123-String-AnyS") +} + +func testEnum() throws { + try assertEquals(actual: ValuesKt.passEnum(), expected: Enumeration.answer) + try assertEquals(actual: ValuesKt.passEnum().enumValue, expected: 42) + try assertEquals(actual: ValuesKt.passEnum().name, expected: "ANSWER") + ValuesKt.receiveEnum(e: 1) +} + +func testDataClass() throws { + let f = "1" + let s = "2" + let t = "3" + + let tripleVal = TripleVals(first: f as NSString, second: s as NSString, third: t as NSString) + try assertEquals(actual: tripleVal.first as! String, expected: f, "Data class' value") + try assertEquals(actual: tripleVal.component2() as! String, expected: s, "Data class' component") + print(tripleVal) + try assertEquals(actual: String(describing: tripleVal), expected: "TripleVals(first=\(f), second=\(s), third=\(t))") + + let tripleVar = TripleVars(first: f as NSString, second: s as NSString, third: t as NSString) + try assertEquals(actual: tripleVar.first as! String, expected: f, "Data class' value") + try assertEquals(actual: tripleVar.component2() as! String, expected: s, "Data class' component") + print(tripleVar) + try assertEquals(actual: String(describing: tripleVar), expected: "[\(f), \(s), \(t)]") + + tripleVar.first = t as NSString + tripleVar.second = f as NSString + tripleVar.third = s as NSString + try assertEquals(actual: tripleVar.component2() as! String, expected: f, "Data class' component") + try assertEquals(actual: String(describing: tripleVar), expected: "[\(t), \(f), \(s)]") +} + +func testCompanionObj() throws { + try assertEquals(actual: WithCompanionAndObject.Companion().str, expected: "String") + try assertEquals(actual: ValuesKt.getCompanionObject().str, expected: "String") + + let namedFromCompanion = ValuesKt.getCompanionObject().named + let named = ValuesKt.getNamedObject() + try assertTrue(named === namedFromCompanion, "Should be the same Named object") + + try assertEquals(actual: ValuesKt.getNamedObjectInterface().iFun(), expected: named.iFun(), "Named object's method") +} + +func testInlineClasses() throws { + let ic1: Int32 = 42 + let ic1N = ValuesKt.box(ic1: 17) + let ic2 = "foo" + let ic2N = "bar" + let ic3 = TripleVals(first: 1, second: 2, third: 3) + let ic3N = ValuesKt.box(ic3: nil) + + try assertEquals( + actual: ValuesKt.concatenateInlineClassValues(ic1: ic1, ic1N: ic1N, ic2: ic2, ic2N: ic2N, ic3: ic3, ic3N: ic3N), + expected: "42 17 foo bar TripleVals(first=1, second=2, third=3) null" + ) + + try assertEquals( + actual: ValuesKt.concatenateInlineClassValues(ic1: ic1, ic1N: nil, ic2: ic2, ic2N: nil, ic3: nil, ic3N: nil), + expected: "42 null foo null null null" + ) + + try assertEquals(actual: ValuesKt.getValue1(ic1), expected: 42) + try assertEquals(actual: ValuesKt.getValueOrNull1(ic1N) as! Int, expected: 17) + + try assertEquals(actual: ValuesKt.getValue2(ic2), expected: "foo") + try assertEquals(actual: ValuesKt.getValueOrNull2(ic2N), expected: "bar") + + try assertEquals(actual: ValuesKt.getValue3(ic3), expected: ic3) + try assertEquals(actual: ValuesKt.getValueOrNull3(ic3N), expected: nil) +} + +class TestSharedIImpl : NSObject, I { + func iFun() -> String { + return "TestSharedIImpl::iFun" + } +} + +func testShared() throws { + func assertFrozen(_ obj: AnyObject) throws { + try assertTrue(ValuesKt.isFrozen(obj: obj), "isFrozen(\(obj))") + } + + func assertNotFrozen(_ obj: AnyObject) throws { + try assertFalse(ValuesKt.isFrozen(obj: obj), "isFrozen(\(obj))") + } + + try assertFrozen(NSObject()) + try assertFrozen(TestSharedIImpl()) + try assertFrozen(ValuesKt.kotlinLambda(block: { return $0 }) as AnyObject) + try assertNotFrozen(FinalClassExtOpen()) +} + +class PureSwiftClass { +} + +struct PureSwiftStruct { + var x: Int +} +class PureSwiftKotlinInterfaceImpl : I { + func iFun() -> String { + return "pure" + } +} + +func testPureSwiftClasses() throws { + let pureSwiftClass = PureSwiftClass() + try assertTrue(ValuesKt.same(pureSwiftClass) as? AnyObject === pureSwiftClass) + + try assertEquals(actual: 123, expected: (ValuesKt.same(PureSwiftStruct(x: 123)) as? PureSwiftStruct)?.x) + try assertEquals(actual: "pure", expected: ValuesKt.iFunExt(PureSwiftKotlinInterfaceImpl())) +} + +func testNames() throws { + try assertEquals(actual: ValuesKt.PROPERTY_NAME_MUST_NOT_BE_ALTERED_BY_SWIFT, expected: 111) + try assertEquals(actual: Deeply.NestedType().thirtyTwo, expected: 32) + try assertEquals(actual: WithGenericDeeplyNestedType().thirtyThree, expected: 33) + try assertEquals(actual: CKeywords(float: 1.0, enum : 42, goto: true).goto_, expected: true) + try assertEquals(actual: TypeOuter.Type_().thirtyFour, expected: 34) + try assertTrue(String(describing: DeeplyNestedIType.self).hasSuffix("DeeplyNestedIType")) +} + +class Base123 : Base23, ExtendedBase1 { + override func same(value: KotlinInt?) -> KotlinInt { + return value! + } +} + +func testSwiftOverride() throws { + let impl = Base123() + try assertEquals(actual: ValuesKt.call(base1: impl, value: 1), expected: 1) + try assertEquals(actual: ValuesKt.call(extendedBase1: impl, value: 2), expected: 2) + try assertEquals(actual: ValuesKt.call(base2: impl, value: 3), expected: 3) + try assertEquals(actual: ValuesKt.call(base3: impl, value: 4), expected: 4) + try assertEquals(actual: ValuesKt.call(base23: impl, value: 5), expected: 5) +} + +class TransformIntToLongCallingSuper : TransformIntToLong { + override func map(value: KotlinInt) -> KotlinLong { + return super.map(value: value) + } +} + +func testKotlinOverride() throws { + try assertEquals(actual: TransformInheritingDefault().map(value: 1) as! Int32, expected: 1) + try assertEquals(actual: TransformIntToDecimalString().map(value: 2), expected: "2") + try assertEquals(actual: TransformIntToDecimalString().map(intValue: 3), expected: "3") + try assertEquals(actual: ValuesKt.createTransformDecimalStringToInt().map(value: "4") as! Int32, expected: 4) + try assertEquals(actual: TransformIntToLongCallingSuper().map(value: 5), expected: 5) +} + +// See https://github.com/JetBrains/kotlin-native/issues/2945 +func testGH2945() throws { + let gh2945 = GH2945(errno: 1) + try assertEquals(actual: 1, expected: gh2945.errno) + gh2945.errno = 2 + try assertEquals(actual: 2, expected: gh2945.errno) + + try assertEquals(actual: 7, expected: gh2945.testErrnoInSelector(p: 3, errno: 4)) +} + +// See https://github.com/JetBrains/kotlin-native/issues/2830 +func testGH2830() throws { + try assertTrue(GH2830().getI() is GH2830I) +} + +// See https://github.com/JetBrains/kotlin-native/issues/2959 +func testGH2959() throws { + try assertEquals(actual: GH2959().getI(id: 2959)[0].id, expected: 2959) +} + +func testKClass() throws { + let test = TestKClass() + + let testKClass = test.getKotlinClass(clazz: TestKClass.self)! + try assertTrue(test.isTestKClass(kClass: testKClass)) + try assertFalse(test.isI(kClass: testKClass)) + try assertEquals(actual: testKClass.simpleName, expected: "TestKClass") + + let iKClass = test.getKotlinClass(protocol: TestKClassI.self)! + try assertFalse(test.isTestKClass(kClass: iKClass)) + try assertTrue(test.isI(kClass: iKClass)) + try assertEquals(actual: iKClass.simpleName, expected: "I") + + try assertTrue(test.getKotlinClass(clazz: NSObject.self) == nil) + try assertTrue(test.getKotlinClass(clazz: PureSwiftClass.self) == nil) + try assertTrue(test.getKotlinClass(clazz: PureSwiftKotlinInterfaceImpl.self) == nil) + try assertTrue(test.getKotlinClass(clazz: Base123.self) == nil) + + try assertTrue(test.getKotlinClass(protocol: NSObjectProtocol.self) == nil) +} + +open class TestSR10177WorkaroundBase {} +class TestSR10177WorkaroundDerived : TestSR10177WorkaroundBase {} + +// See https://bugs.swift.org/browse/SR-10177 and https://bugs.swift.org/browse/SR-10217 +func testSR10177Workaround() throws { + let test = TestSR10177WorkaroundDerived() + try assertTrue(String(describing: test).contains("TestSR10177WorkaroundDerived")) +} + +func testClashes() throws { + let test = TestClashesImpl() + let test1: TestClashes1 = test + let test2: TestClashes2 = test + + try assertEquals(actual: 1, expected: test1.clashingProperty) + try assertEquals(actual: 1, expected: test2.clashingProperty_ as! Int32) + try assertEquals(actual: 2, expected: test2.clashingProperty__ as! Int32) +} + +func testInvalidIdentifiers() throws { + let test = TestInvalidIdentifiers() + + try assertTrue(TestInvalidIdentifiers._Foo() is TestInvalidIdentifiers._Foo) + try assertFalse(TestInvalidIdentifiers.Bar_() is TestInvalidIdentifiers._Foo) + + try assertEquals(actual: 42, expected: test.a_d_d(_1: 13, _2: 14, _3: 15)) + + test._status = "OK" + try assertEquals(actual: "OK", expected: test._status) + + try assertEquals(actual: TestInvalidIdentifiers.E._4_.value, expected: 4) + try assertEquals(actual: TestInvalidIdentifiers.E._5_.value, expected: 5) + try assertEquals(actual: TestInvalidIdentifiers.E.__.value, expected: 6) + try assertEquals(actual: TestInvalidIdentifiers.E.___.value, expected: 7) + + try assertEquals(actual: TestInvalidIdentifiers.Companion_()._42, expected: 42) + + try assertEquals(actual: Set([test.__, test.___]), expected: Set(["$".utf16.first, "_".utf16.first])) +} + +class ImplementingHiddenSubclass : TestDeprecation.ImplementingHidden { + override func effectivelyHidden() -> Int32 { + return -2 + } +} + +func testDeprecation() throws { + let test = TestDeprecation() + try assertEquals(actual: test.openNormal(), expected: 1) + + let testHiddenOverride: TestDeprecation = TestDeprecation.HiddenOverride() + try assertEquals(actual: testHiddenOverride.openNormal(), expected: 2) + + let testErrorOverride: TestDeprecation = TestDeprecation.ErrorOverride() + try assertEquals(actual: testErrorOverride.openNormal(), expected: 3) + + let testWarningOverride: TestDeprecation = TestDeprecation.WarningOverride() + try assertEquals(actual: testWarningOverride.openNormal(), expected: 4) + + try assertEquals(actual: test.callEffectivelyHidden(obj: ImplementingHiddenSubclass()), expected: -2) +} + +func setAssociatedObject(object: AnyObject, value: AnyObject) { + objc_setAssociatedObject( + object, + UnsafeRawPointer(bitPattern: 1)!, + value, + objc_AssociationPolicy.OBJC_ASSOCIATION_RETAIN + ) +} + +func testWeakRefs() throws { + try testWeakRefs0(frozen: false) + try testWeakRefs0(frozen: true) +} + +func testWeakRefs0(frozen: Bool) throws { + func getObj(test: TestWeakRefs) -> AnyObject { + return autoreleasepool { test.getObj() as AnyObject } + } + + func test1() throws { + var test = TestWeakRefs(frozen: frozen) + + var obj: AnyObject? = getObj(test: test) + weak var ref = getObj(test: test) + + ValuesKt.gc() + try assertTrue(ref === getObj(test: test)) // There are both Kotlin and Swift references to the object. + + obj = nil + ValuesKt.gc() + try assertTrue(ref === getObj(test: test)) // There are only Kotlin references to the object. + + test.clearObj() + ValuesKt.gc() + try assertTrue(ref === nil) + } + + func test2() throws { + var test = TestWeakRefs(frozen: frozen) + + var obj: AnyObject? = getObj(test: test) + weak var ref = getObj(test: test) + + ValuesKt.gc() + try assertTrue(ref === obj!) // There are both Kotlin and Swift references to the object. + + test.clearObj() + ValuesKt.gc() + try assertTrue(ref === obj!) // There are only Swift references to the object. + + obj = nil + ValuesKt.gc() + try assertTrue(ref === nil) + } + + func test3() throws { + class Holder { + static weak var ref: AnyObject? = nil + static var deinitialized = false + + deinit { + // Access weak ref to Kotlin object during its counterpart dealloc: + try! assertTrue(Holder.ref === nil) + Holder.deinitialized = true + } + } + + Holder.deinitialized = false + Holder.ref = nil + + var test = TestWeakRefs(frozen: frozen) + + Holder.ref = getObj(test: test) + + // Prepare Holder() to get deinitialized along with getObj(test: test): + setAssociatedObject( + object: getObj(test: test), + value: Holder() + ) + + try assertFalse(Holder.ref === nil) + try assertFalse(Holder.deinitialized) + + test.clearObj() + ValuesKt.gc() + + try assertTrue(Holder.ref === nil) + try assertTrue(Holder.deinitialized) + } + + func test4() throws { + class Holder { + static weak var ref1: AnyObject? = nil + static weak var ref2: AnyObject? = nil + static var deinitialized: Int = 0 + + deinit { + // Access weak ref to Kotlin object during its counterpart dealloc: + try! assertTrue(Holder.ref1 === nil) + try! assertTrue(Holder.ref2 === nil) + Holder.deinitialized += 1 + } + } + + Holder.deinitialized = 0 + Holder.ref1 = nil + Holder.ref2 = nil + + var test = TestWeakRefs(frozen: frozen) + + autoreleasepool { + let cycle = test.createCycle() + + let obj1 = cycle[0] as AnyObject + let obj2 = cycle[1] as AnyObject + + // Prepare Holders to get deinitialized along with obj1 and obj2: + setAssociatedObject(object: obj1, value: Holder()) + setAssociatedObject(object: obj2, value: Holder()) + + Holder.ref1 = obj1 + Holder.ref2 = obj2 + } + + try assertFalse(Holder.ref1 === nil) + try assertFalse(Holder.ref2 === nil) + try assertEquals(actual: Holder.deinitialized, expected: 0) + + ValuesKt.gc() + + try assertTrue(Holder.ref1 === nil) + try assertTrue(Holder.ref2 === nil) + try assertEquals(actual: Holder.deinitialized, expected: 2) + } + + try test1() + try test2() + try test3() + try test4() +} + +var falseFlag = false + +class TestSharedRefs { + private func testLambdaSimple() throws { + func getClosure() -> (() -> Void) { + let lambda = autoreleasepool { + SharedRefs().createLambda() + } + return { if falseFlag { lambda() } } + } + + DispatchQueue.global().async(execute: getClosure()) + } + + private static func launchInNewThread(initializeKotlinRuntime: Bool, block: @escaping () -> Void) -> pthread_t { + class Closure { + static var currentBlock: (() -> Void)? = nil + static var initializeKotlinRuntime: Bool = false + } + + Closure.currentBlock = block + Closure.initializeKotlinRuntime = initializeKotlinRuntime + + var thread: pthread_t? = nil + let createCode = pthread_create(&thread, nil, { _ in + if Closure.initializeKotlinRuntime { + let ignore = SharedRefs() // Ensures that Kotlin runtime gets initialized. + } + + Closure.currentBlock!() + Closure.currentBlock = nil + + return nil + }, nil) + try! assertEquals(actual: createCode, expected: 0) + return thread! + } + + private static func joinThread(thread: pthread_t) { + let joinCode = pthread_join(thread, nil) + try! assertEquals(actual: joinCode, expected: 0) + } + + private static func runInNewThread(initializeKotlinRuntime: Bool, block: @escaping () -> Void) { + let thread = launchInNewThread(initializeKotlinRuntime: initializeKotlinRuntime, block: block) + joinThread(thread: thread) + } + + private func runInNewThread(initializeKotlinRuntime: Bool, block: @escaping () -> Void) { + return TestSharedRefs.runInNewThread(initializeKotlinRuntime: initializeKotlinRuntime, block: block) + } + + private func testObjectPartialRelease() { + let object = autoreleasepool { SharedRefs().createRegularObject() } + var objectVar: AnyObject? = object + + runInNewThread(initializeKotlinRuntime: true) { + objectVar = nil + } + } + + private func testRunRefCount( + run: (@escaping () -> Void) -> Void, + createObject: @escaping (SharedRefs) -> T + ) throws { + let refs = SharedRefs() + + var objectVar1: T? = autoreleasepool { createObject(refs) } + var objectVar2: T? = nil + + try assertTrue(refs.hasAliveObjects()) + + run { + objectVar2 = objectVar1! + objectVar1 = nil + } + + try assertTrue(refs.hasAliveObjects()) + + run { + objectVar2 = nil + } + + try assertFalse(refs.hasAliveObjects()) + } + + private func testBackgroundRefCount(createObject: @escaping (SharedRefs) -> T) throws { + try testRunRefCount( + run: { runInNewThread(initializeKotlinRuntime: false, block: $0) }, + createObject: createObject + ) + + try testRunRefCount( + run: { runInNewThread(initializeKotlinRuntime: true, block: $0) }, + createObject: createObject + ) + } + + private func testReferenceOutlivesThread(releaseWithKotlinRuntime: Bool) throws { + var objectVar: AnyObject? = nil + weak var objectWeakVar: AnyObject? = nil + var collection: AnyObject? = nil + + runInNewThread(initializeKotlinRuntime: false) { + autoreleasepool { + let refs = SharedRefs() + collection = refs.createCollection() + + let object = refs.createRegularObject() + objectVar = object + objectWeakVar = object + + try! assertTrue(objectWeakVar === object) + } + } + + runInNewThread(initializeKotlinRuntime: releaseWithKotlinRuntime) { + objectVar = nil + collection = nil + ValuesKt.gc() + try! assertTrue(objectWeakVar === nil) + } + + } + + private func testMoreWorkBeforeThreadExit() throws { + class Deinit { + static var object1: AnyObject? = nil + static var object2: AnyObject? = nil + static weak var weakVar2: AnyObject? = nil + + deinit { + TestSharedRefs.runInNewThread(initializeKotlinRuntime: false) { + Deinit.object2 = nil + } + } + } + + runInNewThread(initializeKotlinRuntime: false) { + autoreleasepool { + let object1 = SharedRefs.MutableData() + Deinit.object1 = object1 + setAssociatedObject(object: object1, value: Deinit()) + + let object2 = SharedRefs.MutableData() + Deinit.object2 = object2 + Deinit.weakVar2 = object2 + } + + TestSharedRefs.runInNewThread(initializeKotlinRuntime: false) { + Deinit.object1 = nil + } + } + + try assertTrue(Deinit.weakVar2 === nil) + } + + func testRememberNewObject(createObject: @escaping (SharedRefs) -> AnyObject) throws { + + class TestImpl : TestRememberNewObject { + let cleanupFinishedSemaphore = DispatchSemaphore(value: 0) + let threadWaitingForCleanupSemaphore = DispatchSemaphore(value: 0) + + var obj: AnyObject? = nil + + func getObject() -> Any { + return obj! + } + + func waitForCleanup() { + threadWaitingForCleanupSemaphore.signal() + cleanupFinishedSemaphore.wait() + } + } + + let test = TestImpl() + + let refs = SharedRefs() + try assertFalse(refs.hasAliveObjects()) + + autoreleasepool { + test.obj = createObject(refs) + } + + try assertTrue(refs.hasAliveObjects()) + + let thread = TestSharedRefs.launchInNewThread(initializeKotlinRuntime: false) { + ValuesKt.testRememberNewObject(test: test) + } + + test.threadWaitingForCleanupSemaphore.wait() + test.obj = nil + ValuesKt.gc() + + try assertTrue(refs.hasAliveObjects()) + + test.cleanupFinishedSemaphore.signal() + + TestSharedRefs.joinThread(thread: thread) + try assertFalse(refs.hasAliveObjects()) + } + + func test() throws { + try testLambdaSimple() + try testObjectPartialRelease() + + try testBackgroundRefCount(createObject: { $0.createLambda() }) + try testBackgroundRefCount(createObject: { $0.createRegularObject() }) + try testBackgroundRefCount(createObject: { $0.createCollection() }) + + try testBackgroundRefCount(createObject: { $0.createFrozenLambda() }) + try testBackgroundRefCount(createObject: { $0.createFrozenRegularObject() }) + try testBackgroundRefCount(createObject: { $0.createFrozenCollection() }) + + try testReferenceOutlivesThread(releaseWithKotlinRuntime: false) + try testReferenceOutlivesThread(releaseWithKotlinRuntime: true) + try testMoreWorkBeforeThreadExit() + + try testRememberNewObject(createObject: { $0.createFrozenRegularObject() }) + try testRememberNewObject(createObject: { $0.createFrozenCollection() }) + + usleep(300 * 1000) + } +} + +// See https://github.com/JetBrains/kotlin-native/issues/2931 +func testGH2931() throws { + for i in 0..<50000 { + let holder = GH2931.Holder() + let queue = DispatchQueue.global(qos: .background) + let group = DispatchGroup() + + for j in 0..<2 { + group.enter() + queue.async { + autoreleasepool { + holder.data + } + group.leave() + } + } + + group.wait() + } +} + +class ClassForTypeCheckInheritor : ClassForTypeCheck { } + +func testClassTypeCheck() throws { + try assertTrue(ValuesKt.testClassTypeCheck(x: ClassForTypeCheckInheritor())) +} + +class ClassForInterfaceTypeCheckInheritor1 : InterfaceForTypeCheck { } +class ClassForInterfaceTypeCheckInheritor2 : Base23, InterfaceForTypeCheck { } +class ClassForInterfaceTypeCheckInheritor3 : Base23, ExtendedBase1, InterfaceForTypeCheck { } +class ClassForInterfaceTypeCheck_Fail : Base23 { } + +func testInterfaceTypeCheck() throws { + try assertTrue(ValuesKt.testInterfaceTypeCheck(x: ClassForInterfaceTypeCheckInheritor1())) + try assertTrue(ValuesKt.testInterfaceTypeCheck(x: ClassForInterfaceTypeCheckInheritor2())) + try assertTrue(ValuesKt.testInterfaceTypeCheck(x: ClassForInterfaceTypeCheckInheritor3())) + try assertFalse(ValuesKt.testInterfaceTypeCheck(x: ClassForInterfaceTypeCheck_Fail())) +} + +class AbstractInterface : AbstractInterfaceBase { + override func bar() -> Int32 { + return 42 + } +} + +// See https://github.com/JetBrains/kotlin-native/issues/3503 +func testGH3503_1() throws { + try assertEquals(actual: ValuesKt.testAbstractInterfaceCall(x: AbstractInterface()), expected: 42) +} + +class AbstractInterface2 : AbstractInterfaceBase2 { + +} + +func testGH3503_2() throws { + try assertEquals(actual: ValuesKt.testAbstractInterfaceCall2(x: AbstractInterface2()), expected: 42) +} + +class AbstractInterface3 : AbstractInterfaceBase3 { + override func foo() -> Int32 { + return 42 + } +} + +func testGH3503_3() throws { + try assertEquals(actual: ValuesKt.testAbstractInterfaceCall(x: AbstractInterface3()), expected: 42) +} + +func testGH3525() throws { + try assertEquals(actual: ValuesKt.gh3525BaseInitCount, expected: 0) + try assertEquals(actual: ValuesKt.gh3525InitCount, expected: 0) + + let gh3525_1 = GH3525() + try assertTrue(gh3525_1 is GH3525) + + try assertEquals(actual: ValuesKt.gh3525BaseInitCount, expected: 1) + try assertEquals(actual: ValuesKt.gh3525InitCount, expected: 1) + + let gh3525_2 = GH3525() + try assertTrue(gh3525_2 is GH3525) + + try assertEquals(actual: ValuesKt.gh3525BaseInitCount, expected: 1) + try assertEquals(actual: ValuesKt.gh3525InitCount, expected: 1) + + try assertTrue(gh3525_1 === gh3525_2) +} + +func testStringConversion() throws { + func test1() throws { + let test = TestStringConversion() + + let buffer = NSMutableString() + buffer.append("a") + test.str = buffer + buffer.append("b") + + try assertEquals(actual: buffer, expected: "ab") + // Ensure test.str isn't affected by buffer mutation: + try assertEquals(actual: test.str as! NSString, expected: "a") + } + + func ensureNoCopy(nsStr: NSString) throws { + let test = TestStringConversion() + + test.str = nsStr + let nsStr2 = test.str as! NSString + + // Ensure no additional NSString created on both conversions: + try assertTrue(nsStr === nsStr2) + } + + func test2() throws { + var str = "a" + str += NSObject().description + try ensureNoCopy(nsStr: str as NSString) + + try ensureNoCopy(nsStr: NSString("abc")) + + try ensureNoCopy(nsStr: NSString(format: "%d%d%d", 3, 2, 1)) + } + + try test1() + try test2() +} + +class GH3825SwiftImpl : GH3825 { + class E : Error {} + + func call0(callback: () -> KotlinBoolean) throws { + if callback().boolValue { throw E() } + } + + func call1(doThrow: Bool, callback: () -> Void) throws { + if doThrow { throw E() } + callback() + } + + func call2(callback: () -> Void, doThrow: Bool) throws { + if doThrow { throw E() } + callback() + } +} + +func testGH3825() throws { + try ValuesKt.testGH3825(gh3825: GH3825SwiftImpl()) + + let test = GH3825KotlinImpl() + var count = 0 + + try testThrowing { try test.call0 { true } } + try test.call0 { + count += 1 + return false + } + try assertEquals(actual: count, expected: 1) + + try testThrowing { try test.call1(doThrow: true) { count += 1 } } + try test.call1(doThrow: false) { count += 1 } + try assertEquals(actual: count, expected: 2) + + try testThrowing { try test.call2(callback: { count += 1 }, doThrow: true)} + try test.call2(callback: { count += 1 }, doThrow: false) + try assertEquals(actual: count, expected: 3) +} + + +func testMapsExport() throws { + // Original reproducer failed in different way for MutableMap (iOS 11) and Map (MacOS 10.14, iOS 13) + + try assertEquals(actual: ValuesKt.mapBoolean2String()[true], expected: "true") + try assertEquals(actual: ValuesKt.mapByte2Short()[-1], expected: 2) + try assertEquals(actual: ValuesKt.mapShort2Byte()[-2], expected: 1) + try assertEquals(actual: ValuesKt.mapInt2Long()[-4], expected: 8) + try assertEquals(actual: ValuesKt.mapLong2Long()[-8], expected: 8) + try assertEquals(actual: ValuesKt.mapUByte2Boolean()[128], expected: true) + try assertEquals(actual: ValuesKt.mapUShort2Byte()[0x8000], expected: 1) + try assertEquals(actual: ValuesKt.mapUInt2Long()[0x7FFFFFFF], expected: 7) + // the following samples require explicit cast to KotlinUInt or KotlinULong + try assertEquals(actual: ValuesKt.mapUInt2Long()[KotlinUInt(-0x8000_0000)], expected: 8) + _ = ValuesKt.mapULong2Long() as! [KotlinULong: KotlinLong] // test cast + var u64: UInt64 = 0x8000_0000_0000_0000 + try assertEquals(actual: ValuesKt.mapULong2Long()[KotlinULong(value: u64)], expected: 8) + + _ = ValuesKt.mapFloat2Float() as! [KotlinFloat: KotlinFloat] // test cast + try assertEquals(actual: ValuesKt.mapFloat2Float()[3.14], expected: 100.0) + try assertEquals(actual: ValuesKt.mapDouble2String()[2.718281828459045], expected: "2.718281828459045") + + // test also explicit cast to [:] of primitiva types, e.g. [Int: Int] + try assertEquals(actual: (ValuesKt.mutBoolean2String() as! [Bool: String])[true], expected: "true") + try assertEquals(actual: (ValuesKt.mutByte2Short() as! [Int8: Int16])[-1], expected: 2) + try assertEquals(actual: (ValuesKt.mutShort2Byte() as! [Int16: Int8])[-2], expected: 1) + try assertEquals(actual: (ValuesKt.mutInt2Long() as! [Int: Int64])[-4], expected: 8) + try assertEquals(actual: (ValuesKt.mutLong2Long() as! [Int64: Int64])[-8], expected: 8) + + try assertEquals(actual: (ValuesKt.mutUByte2Boolean() as! [UInt8: Bool])[128], expected: true) + try assertEquals(actual: (ValuesKt.mutUShort2Byte() as! [UInt16: Int8])[0x8000], expected: 1) + // the following samples require explicit cast to KotlinUInt or KotlinULong + try assertEquals(actual: (ValuesKt.mutUInt2Long() as! [UInt: Int64])[UInt(0x8000_0000)], expected: 8) + + try assertEquals(actual: (ValuesKt.mutULong2Long() as! [UInt64: Int64])[u64], expected: 8) + + try assertEquals(actual: (ValuesKt.mutFloat2Float() as! [Float: Float])[3.14], expected: 100.0) + try assertEquals(actual: (ValuesKt.mutDouble2String() as! [Double: String])[2.718281828459045], expected: "2.718281828459045") +} + +// -------- Execution of the test -------- + +class ValuesTests : SimpleTestProvider { + override init() { + super.init() + + test("TestValues", testVals) + test("TestVars", testVars) + test("TestDoubles", testDoubles) + test("TestNumbers", testNumbers) + test("TestLists", testLists) + test("TestLazyValues", testLazyVal) + test("TestDelegatedProperties", testDelegatedProp) + test("TestGetterDelegate", testGetterDelegate) + test("TestNulls", testNulls) + test("TestAnyVar", testAnyVar) + test("TestFunctions", testFunctions) + test("TestExceptions", testExceptions) + test("TestFuncType", testFuncType) + test("TestGenericsFoo", testGenericsFoo) + test("TestVararg", testVararg) + test("TestStringExtension", testStrExtFun) + test("TestAnyToString", testAnyToString) + test("TestAnyPrint", testAnyPrint) + test("TestCharExtensions", testCharExtensions) + test("TestLambda", testLambda) + test("TestInterfaceExtension", testInterfaceExtension) + test("TestClassInstances", testClassInstances) + test("TestEnum", testEnum) + test("TestDataClass", testDataClass) + test("TestCompanionObj", testCompanionObj) + test("TestInlineClasses", testInlineClasses) + test("TestShared", testShared) + test("TestPureSwiftClasses", testPureSwiftClasses) + test("TestNames", testNames) + test("TestSwiftOverride", testSwiftOverride) + test("TestKotlinOverride", testKotlinOverride) + test("TestGH2945", testGH2945) + test("TestGH2830", testGH2830) + test("TestGH2959", testGH2959) + test("TestKClass", testKClass) + test("TestSR10177Workaround", testSR10177Workaround) + test("TestClashes", testClashes) + test("TestInvalidIdentifiers", testInvalidIdentifiers) + test("TestDeprecation", testDeprecation) + test("TestWeakRefs", testWeakRefs) + test("TestSharedRefs", TestSharedRefs().test) + test("TestClassTypeCheck", testClassTypeCheck) + test("TestInterfaceTypeCheck", testInterfaceTypeCheck) + test("TestGH3503_1", testGH3503_1) + test("TestGH3503_2", testGH3503_2) + test("TestGH3503_3", testGH3503_3) + test("TestGH3525", testGH3525) + test("TestStringConversion", testStringConversion) + test("TestGH3825", testGH3825) + test("TestMapsExport", testMapsExport) + + // Stress test, must remain the last one: + test("TestGH2931", testGH2931) + } +} \ No newline at end of file diff --git a/kotlin-native/backend.native/tests/produce_dynamic/simple/hello.kt b/kotlin-native/backend.native/tests/produce_dynamic/simple/hello.kt new file mode 100644 index 00000000000..3ea037214a5 --- /dev/null +++ b/kotlin-native/backend.native/tests/produce_dynamic/simple/hello.kt @@ -0,0 +1,157 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +// FILE: hello.kt + +import kotlinx.cinterop.* + +import kotlin.native.CName +import kotlin.native.concurrent.freeze + +// Top level functions. +fun hello() { + println("Hello, dynamic!") +} + +fun getString() = "Kotlin/Native" + +data class Data(var string: String) + +fun getMutable() = Data("foo") + +// Class with inheritance. +open class Base { + open fun foo() = println("Base.foo") + + open fun fooParam(arg0: String, arg1: Int, arg2: String?) = + println("Base.fooParam: $arg0 $arg1 ${arg2 ?: "null"}") + + @CName(externName = "", shortName = "strangeName") fun странноеИмя() = 111 + +} + +// Top level functions. +@CName(externName = "topLevelFunctionFromC", shortName = "topLevelFunctionFromCShort") +fun topLevelFunction(x1: Int, x2: Int) = x1 - x2 + +@CName("topLevelFunctionVoidFromC") +fun topLevelFunctionVoid(x1: Int, x2: Int?, x3: Unit?, pointer: COpaquePointer?) { + assert(x1 == 42) + assert(x2 == 77) + assert(x3 != null) + assert(pointer == null) +} + +// Enum. +enum class Enum(val code: Int) { + ONE(1), + TWO(2), + HUNDRED(100) +} + + +interface Interface { + fun foo(): Int +} + +enum class EnumWithInterface : Interface { + ZERO + ; + override fun foo(): Int = 42 +} + +// Object. +interface Codeable { + fun asCode(): Int +} + +val an_object = object : Codeable { + override fun asCode() = 42 +} + +object Singleton { + override fun toString() = "I am single" +} + +class Child : Base() { + override fun fooParam(arg0: String, arg1: Int, arg2: String?) = + println("Child.fooParam: $arg0 $arg1 ${arg2 ?: "null"}") + + val roProperty: Int + get() = 42 + + var rwProperty: Int = 0 + get() = field + set(value) { field = value + 1 } +} + +// Interface. +interface I { + fun foo(arg0: String, arg1: Int, arg2: I) + fun fooImpl() = foo("Hi", 239, this) +} + +open class Impl1: I { + override fun foo(arg0: String, arg1: Int, arg2: I) { + println("Impl1.I: $arg0 $arg1 ${arg2::class.qualifiedName}") + } +} + +class Impl2 : Impl1() { + override fun foo(arg0: String, arg1: Int, arg2: I) { + println("Impl2.I: $arg0 $arg1 ${arg2::class.qualifiedName}") + } +} + +inline class IC1(val value: Int) +inline class IC2(val value: String) +inline class IC3(val value: Base?) + +fun useInlineClasses(ic1: IC1, ic2: IC2, ic3: IC3) { + assert(ic1.value == 42) + assert(ic2.value == "bar") + assert(ic3.value is Base) +} + +fun testNullableWithNulls(arg1: Int?, arg2: Unit?) { + assert(arg1 == null) + assert(arg2 == null) +} + +fun setCErrorHandler(callback: CPointer) -> Unit>>?) { + setUnhandledExceptionHook({ + throwable: Throwable -> + memScoped { + callback!!(throwable.toString().cstr.ptr) + } + kotlin.system.exitProcess(0) + }.freeze()) +} + +fun throwException() { + throw Error("Expected error") +} + +fun getNullableString(param: Int) : String? { + if (param == 0) { + return "Hi" + } else { + return null + } +} + +fun getVector128() = vectorOf(1, 2, 3, 4) + +// FILE: gh3952.sync.kt + +package gh3952.sync + +class PlainSync {} + +// FILE: gh3952.nested.sync.kt + +package gh3952.nested.sync + +class NestedSync {} diff --git a/kotlin-native/backend.native/tests/produce_dynamic/simple/main.c b/kotlin-native/backend.native/tests/produce_dynamic/simple/main.c new file mode 100644 index 00000000000..ce0bbfa540b --- /dev/null +++ b/kotlin-native/backend.native/tests/produce_dynamic/simple/main.c @@ -0,0 +1,109 @@ +#include +#include "testlib_api.h" + +#define __ testlib_symbols()-> +#define T_(x) testlib_kref_ ## x +#define CAST(T, v) testlib_kref_ ## T { .pinned = v } + +void errorHandler(const char* str) { + printf("Error handler: %s\n", str); +} + +void testVector128() { + int __attribute__ ((__vector_size__ (16))) v4f = __ kotlin.root.getVector128(); + printf("getVector128 = (%d, %d, %d, %d)\n", v4f[0], v4f[1], v4f[2], v4f[3]); +} + +// See https://github.com/JetBrains/kotlin-native/issues/3952 +void testGH3952() { + T_(gh3952_nested_sync_NestedSync) good = __ kotlin.root.gh3952.nested.sync.NestedSync.NestedSync(); + + T_(gh3952_sync_PlainSync) alsoGood = __ kotlin.root.gh3952.sync.PlainSync.PlainSync(); + + __ DisposeStablePointer(good.pinned); + __ DisposeStablePointer(alsoGood.pinned); +} + +int main(void) { + T_(Singleton) singleton = __ kotlin.root.Singleton._instance(); + T_(Base) base = __ kotlin.root.Base.Base(); + T_(Child) child = __ kotlin.root.Child.Child(); + T_(Impl1) impl1 = __ kotlin.root.Impl1.Impl1(); + T_(Impl2) impl2 = __ kotlin.root.Impl2.Impl2(); + T_(Base) casted_child = { .pinned = child.pinned }; + T_(I) casted_impl1 = { .pinned = impl1.pinned }; + T_(I) casted_impl2 = { .pinned = impl2.pinned }; + T_(Enum) enum1 = __ kotlin.root.Enum.HUNDRED.get(); + T_(Codeable) object1 = __ kotlin.root.get_an_object(); + T_(Data) data = __ kotlin.root.getMutable(); + T_(kotlin_Int) nullableInt = __ createNullableInt(77); + T_(kotlin_Unit) nullableUnit = __ createNullableUnit(); + T_(kotlin_Int) nullableIntNull = { .pinned = 0 }; + T_(kotlin_Unit) nullableUnitNull = { .pinned = 0 }; + T_(EnumWithInterface) enum2 = __ kotlin.root.EnumWithInterface.ZERO.get(); + + const char* string1 = __ kotlin.root.getString(); + const char* string2 = __ kotlin.root.Singleton.toString(singleton); + const char* string3 = __ kotlin.root.Data.get_string(data); + const char* string4 = __ kotlin.root.getNullableString(0); + const char* string5 = __ kotlin.root.getNullableString(1); + + __ kotlin.root.hello(); + __ kotlin.root.Base.foo(base); + __ kotlin.root.Base.fooParam(base, "a", 1, "q"); + __ kotlin.root.Child.fooParam(child, "b", 2, (char*)0); + __ kotlin.root.Base.fooParam(casted_child, "c", 3, (char*)0); + __ kotlin.root.I.foo(casted_impl1, "d", 4, casted_impl1); + __ kotlin.root.I.foo(casted_impl2, "e", 5, casted_impl2); + + printf("String is %s nullable is %s null is %s\n", string1, string4, + string5 ? "BAD" : "OK"); + + printf("RO property is %d\n", __ kotlin.root.Child.get_roProperty(child)); + __ kotlin.root.Child.set_rwProperty(child, 238); + printf("RW property is %d\n", __ kotlin.root.Child.get_rwProperty(child)); + + printf("enum100 = %d\n", __ kotlin.root.Enum.get_code(enum1)); + printf("enum42 = %d\n", __ kotlin.root.EnumWithInterface.foo(enum2)); + + printf("object = %d\n", __ kotlin.root.Codeable.asCode(object1)); + + printf("singleton = %s\n", string2); + + printf("mutable = %s\n", string3); + + topLevelFunctionVoidFromC(42, nullableInt, nullableUnit, 0); + __ kotlin.root.topLevelFunctionVoid(42, nullableInt, nullableUnit, 0); + printf("topLevel = %d %d\n", topLevelFunctionFromC(780, 3), __ kotlin.root.topLevelFunctionFromCShort(5, 2)); + + __ kotlin.root.useInlineClasses(42, "bar", base); + + __ kotlin.root.testNullableWithNulls(nullableIntNull, nullableUnitNull); + + printf("IsInstance1 = %s\n", __ IsInstance(singleton.pinned, __ kotlin.root.Singleton._type()) ? "PASS" : "FAIL"); + printf("IsInstance2 = %s\n", !(__ IsInstance(singleton.pinned, __ kotlin.root.Codeable._type())) ? "PASS" : "FAIL"); + + testVector128(); + testGH3952(); + + __ DisposeStablePointer(singleton.pinned); + __ DisposeString(string1); + __ DisposeString(string2); + __ DisposeString(string3); + __ DisposeString(string4); + __ DisposeString(string5); + __ DisposeStablePointer(base.pinned); + __ DisposeStablePointer(child.pinned); + __ DisposeStablePointer(impl1.pinned); + __ DisposeStablePointer(impl2.pinned); + __ DisposeStablePointer(enum1.pinned); + __ DisposeStablePointer(object1.pinned); + __ DisposeStablePointer(nullableInt.pinned); + __ DisposeStablePointer(enum2.pinned); + + __ kotlin.root.setCErrorHandler(&errorHandler); + __ kotlin.root.throwException(); + + return 0; +} + diff --git a/kotlin-native/backend.native/tests/runtime/basic/args0.kt b/kotlin-native/backend.native/tests/runtime/basic/args0.kt new file mode 100644 index 00000000000..88b91bc1dc5 --- /dev/null +++ b/kotlin-native/backend.native/tests/runtime/basic/args0.kt @@ -0,0 +1,10 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +fun main(args : Array) { + for (s in args) { + println(s) + } +} diff --git a/kotlin-native/backend.native/tests/runtime/basic/assert_failed.kt b/kotlin-native/backend.native/tests/runtime/basic/assert_failed.kt new file mode 100644 index 00000000000..e8f91168394 --- /dev/null +++ b/kotlin-native/backend.native/tests/runtime/basic/assert_failed.kt @@ -0,0 +1,8 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +fun main(args: Array) { + assert(false) +} \ No newline at end of file diff --git a/kotlin-native/backend.native/tests/runtime/basic/assert_passed.kt b/kotlin-native/backend.native/tests/runtime/basic/assert_passed.kt new file mode 100644 index 00000000000..d49eacc0642 --- /dev/null +++ b/kotlin-native/backend.native/tests/runtime/basic/assert_passed.kt @@ -0,0 +1,8 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +fun main(args: Array) { + assert(true) +} \ No newline at end of file diff --git a/kotlin-native/backend.native/tests/runtime/basic/cleaner_basic.kt b/kotlin-native/backend.native/tests/runtime/basic/cleaner_basic.kt new file mode 100644 index 00000000000..b7dd61581ff --- /dev/null +++ b/kotlin-native/backend.native/tests/runtime/basic/cleaner_basic.kt @@ -0,0 +1,204 @@ +/* + * Copyright 2010-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ +@file:OptIn(ExperimentalStdlibApi::class) + +package runtime.basic.cleaner_basic + +import kotlin.test.* + +import kotlin.native.internal.* +import kotlin.native.concurrent.* +import kotlin.native.ref.WeakReference + +class AtomicBoolean(initialValue: Boolean) { + private val impl = AtomicInt(if (initialValue) 1 else 0) + + init { + freeze() + } + + public var value: Boolean + get() = impl.value != 0 + set(new) { impl.value = if (new) 1 else 0 } +} + +class FunBox(private val impl: () -> Unit) { + fun call() { + impl() + } +} + +@Test +fun testCleanerLambda() { + val called = AtomicBoolean(false); + var funBoxWeak: WeakReference? = null + var cleanerWeak: WeakReference? = null + { + val cleaner = { + val funBox = FunBox { called.value = true }.freeze() + funBoxWeak = WeakReference(funBox) + createCleaner(funBox) { it.call() } + }() + GC.collect() // Make sure local funBox reference is gone + cleanerWeak = WeakReference(cleaner) + assertFalse(called.value) + }() + + GC.collect() + performGCOnCleanerWorker() + + assertNull(cleanerWeak!!.value) + assertTrue(called.value) + assertNull(funBoxWeak!!.value) +} + +@Test +fun testCleanerAnonymousFunction() { + val called = AtomicBoolean(false); + var funBoxWeak: WeakReference? = null + var cleanerWeak: WeakReference? = null + { + val cleaner = { + val funBox = FunBox { called.value = true }.freeze() + funBoxWeak = WeakReference(funBox) + createCleaner(funBox, fun (it: FunBox) { it.call() }) + }() + GC.collect() // Make sure local funBox reference is gone + cleanerWeak = WeakReference(cleaner) + assertFalse(called.value) + }() + + GC.collect() + performGCOnCleanerWorker() + + assertNull(cleanerWeak!!.value) + assertTrue(called.value) + assertNull(funBoxWeak!!.value) +} + +@Test +fun testCleanerFunctionReference() { + val called = AtomicBoolean(false); + var funBoxWeak: WeakReference? = null + var cleanerWeak: WeakReference? = null + { + val cleaner = { + val funBox = FunBox { called.value = true }.freeze() + funBoxWeak = WeakReference(funBox) + createCleaner(funBox, FunBox::call) + }() + GC.collect() // Make sure local funBox reference is gone + cleanerWeak = WeakReference(cleaner) + assertFalse(called.value) + }() + + GC.collect() + performGCOnCleanerWorker() + + assertNull(cleanerWeak!!.value) + assertTrue(called.value) + assertNull(funBoxWeak!!.value) +} + +@Test +fun testCleanerFailWithNonShareableArgument() { + val funBox = FunBox {} + assertFailsWith { + createCleaner(funBox) {} + } +} + +@Test +fun testCleanerCleansWithoutGC() { + val called = AtomicBoolean(false); + var funBoxWeak: WeakReference? = null + var cleanerWeak: WeakReference? = null + { + val cleaner = { + val funBox = FunBox { called.value = true }.freeze() + funBoxWeak = WeakReference(funBox) + createCleaner(funBox) { it.call() } + }() + GC.collect() // Make sure local funBox reference is gone + cleaner.freeze() + cleanerWeak = WeakReference(cleaner) + assertFalse(called.value) + }() + + GC.collect() + + assertNull(cleanerWeak!!.value) + + waitCleanerWorker() + + assertTrue(called.value) + // If this fails, GC has somehow ran on the cleaners worker. + assertNotNull(funBoxWeak!!.value) +} + +val globalInt = AtomicInt(0) + +@Test +fun testCleanerWithInt() { + var cleanerWeak: WeakReference? = null + { + val cleaner = createCleaner(42) { + globalInt.value = it + }.freeze() + cleanerWeak = WeakReference(cleaner) + assertEquals(0, globalInt.value) + }() + + GC.collect() + performGCOnCleanerWorker() + + assertNull(cleanerWeak!!.value) + assertEquals(42, globalInt.value) +} + +val globalPtr = AtomicNativePtr(NativePtr.NULL) + +@Test +fun testCleanerWithNativePtr() { + var cleanerWeak: WeakReference? = null + { + val cleaner = createCleaner(NativePtr.NULL + 42L) { + globalPtr.value = it + } + cleanerWeak = WeakReference(cleaner) + assertEquals(NativePtr.NULL, globalPtr.value) + }() + + GC.collect() + performGCOnCleanerWorker() + + assertNull(cleanerWeak!!.value) + assertEquals(NativePtr.NULL + 42L, globalPtr.value) +} + +@Test +fun testCleanerWithException() { + val called = AtomicBoolean(false); + var funBoxWeak: WeakReference? = null + var cleanerWeak: WeakReference? = null + { + val funBox = FunBox { called.value = true }.freeze() + funBoxWeak = WeakReference(funBox) + val cleaner = createCleaner(funBox) { + it.call() + error("Cleaner block failed") + } + cleanerWeak = WeakReference(cleaner) + }() + + GC.collect() + performGCOnCleanerWorker() + + assertNull(cleanerWeak!!.value) + // Cleaners block started executing. + assertTrue(called.value) + // Even though the block failed, the captured funBox is freed. + assertNull(funBoxWeak!!.value) +} diff --git a/kotlin-native/backend.native/tests/runtime/basic/cleaner_in_main_with_checker.kt b/kotlin-native/backend.native/tests/runtime/basic/cleaner_in_main_with_checker.kt new file mode 100644 index 00000000000..e15f7a3210e --- /dev/null +++ b/kotlin-native/backend.native/tests/runtime/basic/cleaner_in_main_with_checker.kt @@ -0,0 +1,21 @@ +/* + * Copyright 2010-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ +@file:OptIn(ExperimentalStdlibApi::class) + +import kotlin.native.internal.* +import kotlin.native.Platform + +fun main() { + // Cleaner holds onto a finalization lambda. If it doesn't get executed, + // the memory will leak. Suppress memory leak checker to check for cleaners + // leak only. + Platform.isMemoryLeakCheckerActive = false + Platform.isCleanersLeakCheckerActive = true + // This cleaner will run, because with the checker active this cleaner + // will get collected, block scheduled and executed before cleaners are disabled. + createCleaner(42) { + println(it) + } +} diff --git a/kotlin-native/backend.native/tests/runtime/basic/cleaner_in_main_without_checker.kt b/kotlin-native/backend.native/tests/runtime/basic/cleaner_in_main_without_checker.kt new file mode 100644 index 00000000000..ce163b605f7 --- /dev/null +++ b/kotlin-native/backend.native/tests/runtime/basic/cleaner_in_main_without_checker.kt @@ -0,0 +1,21 @@ +/* + * Copyright 2010-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ +@file:OptIn(ExperimentalStdlibApi::class) + +import kotlin.native.internal.* +import kotlin.native.Platform + +fun main() { + // Cleaner holds onto a finalization lambda. If it doesn't get executed, + // the memory will leak. Suppress memory leak checker to check for cleaners + // leak only. + Platform.isMemoryLeakCheckerActive = false + Platform.isCleanersLeakCheckerActive = false + // This cleaner will not run, because with the checker inactive this cleaner + // will not get collected before cleaners are disabled. + createCleaner(42) { + println(it) + } +} diff --git a/kotlin-native/backend.native/tests/runtime/basic/cleaner_in_tls_main_with_checker.kt b/kotlin-native/backend.native/tests/runtime/basic/cleaner_in_tls_main_with_checker.kt new file mode 100644 index 00000000000..718017a823e --- /dev/null +++ b/kotlin-native/backend.native/tests/runtime/basic/cleaner_in_tls_main_with_checker.kt @@ -0,0 +1,26 @@ +/* + * Copyright 2010-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ +@file:OptIn(ExperimentalStdlibApi::class) + +import kotlin.test.* + +import kotlin.native.concurrent.* +import kotlin.native.internal.* +import kotlin.native.Platform + +@ThreadLocal +var tlsCleaner: Cleaner? = null + +fun main() { + // Cleaner holds onto a finalization lambda. If it doesn't get executed, + // the memory will leak. Suppress memory leak checker to check for cleaners + // leak only. + Platform.isMemoryLeakCheckerActive = false + Platform.isCleanersLeakCheckerActive = true + // This cleaner won't be run + tlsCleaner = createCleaner(42) { + println(it) + } +} diff --git a/kotlin-native/backend.native/tests/runtime/basic/cleaner_in_tls_main_without_checker.kt b/kotlin-native/backend.native/tests/runtime/basic/cleaner_in_tls_main_without_checker.kt new file mode 100644 index 00000000000..54267f712c6 --- /dev/null +++ b/kotlin-native/backend.native/tests/runtime/basic/cleaner_in_tls_main_without_checker.kt @@ -0,0 +1,26 @@ +/* + * Copyright 2010-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ +@file:OptIn(ExperimentalStdlibApi::class) + +import kotlin.test.* + +import kotlin.native.concurrent.* +import kotlin.native.internal.* +import kotlin.native.Platform + +@ThreadLocal +var tlsCleaner: Cleaner? = null + +fun main() { + // Cleaner holds onto a finalization lambda. If it doesn't get executed, + // the memory will leak. Suppress memory leak checker to check for cleaners + // leak only. + Platform.isMemoryLeakCheckerActive = false + Platform.isCleanersLeakCheckerActive = false + // This cleaner won't be run + tlsCleaner = createCleaner(42) { + println(it) + } +} diff --git a/kotlin-native/backend.native/tests/runtime/basic/cleaner_in_tls_worker.kt b/kotlin-native/backend.native/tests/runtime/basic/cleaner_in_tls_worker.kt new file mode 100644 index 00000000000..e6ef93faeba --- /dev/null +++ b/kotlin-native/backend.native/tests/runtime/basic/cleaner_in_tls_worker.kt @@ -0,0 +1,31 @@ +/* + * Copyright 2010-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ +@file:OptIn(ExperimentalStdlibApi::class) + +import kotlin.test.* + +import kotlin.native.concurrent.* +import kotlin.native.internal.* + +@ThreadLocal +var tlsCleaner: Cleaner? = null + +val value = AtomicInt(0) + +fun main() { + val worker = Worker.start() + + worker.execute(TransferMode.SAFE, {}) { + tlsCleaner = createCleaner(42) { + value.value = it + } + } + + worker.requestTermination().result + waitWorkerTermination(worker) + waitCleanerWorker() + + assertEquals(42, value.value) +} diff --git a/kotlin-native/backend.native/tests/runtime/basic/cleaner_leak.kt b/kotlin-native/backend.native/tests/runtime/basic/cleaner_leak.kt new file mode 100644 index 00000000000..01f2a5277a2 --- /dev/null +++ b/kotlin-native/backend.native/tests/runtime/basic/cleaner_leak.kt @@ -0,0 +1,24 @@ +/* + * Copyright 2010-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ +@file:OptIn(ExperimentalStdlibApi::class) + +import kotlin.test.* + +import kotlin.native.internal.* + +// This cleaner won't be run, because it's deinitialized with globals after +// cleaners are disabled. +val globalCleaner = createCleaner(42) { + println(it) +} + +fun main() { + // Cleaner holds onto a finalization lambda. If it doesn't get executed, + // the memory will leak. Suppress memory leak checker to check for cleaners + // leak only. + Platform.isMemoryLeakCheckerActive = false + // Make sure cleaner is initialized. + assertNotNull(globalCleaner) +} diff --git a/kotlin-native/backend.native/tests/runtime/basic/cleaner_leak_with_checker.kt b/kotlin-native/backend.native/tests/runtime/basic/cleaner_leak_with_checker.kt new file mode 100644 index 00000000000..053c1146d7c --- /dev/null +++ b/kotlin-native/backend.native/tests/runtime/basic/cleaner_leak_with_checker.kt @@ -0,0 +1,26 @@ +/* + * Copyright 2010-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ +@file:OptIn(ExperimentalStdlibApi::class) + +import kotlin.test.* + +import kotlin.native.internal.* +import kotlin.native.Platform + +// This cleaner won't be run, because it's deinitialized with globals after +// cleaners are disabled. +val globalCleaner = createCleaner(42) { + println(it) +} + +fun main() { + // Cleaner holds onto a finalization lambda. If it doesn't get executed, + // the memory will leak. Suppress memory leak checker to check for cleaners + // leak only. + Platform.isMemoryLeakCheckerActive = false + Platform.isCleanersLeakCheckerActive = true + // Make sure cleaner is initialized. + assertNotNull(globalCleaner) +} diff --git a/kotlin-native/backend.native/tests/runtime/basic/cleaner_leak_without_checker.kt b/kotlin-native/backend.native/tests/runtime/basic/cleaner_leak_without_checker.kt new file mode 100644 index 00000000000..7391ef50de0 --- /dev/null +++ b/kotlin-native/backend.native/tests/runtime/basic/cleaner_leak_without_checker.kt @@ -0,0 +1,26 @@ +/* + * Copyright 2010-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ +@file:OptIn(ExperimentalStdlibApi::class) + +import kotlin.test.* + +import kotlin.native.internal.* +import kotlin.native.Platform + +// This cleaner won't be run, because it's deinitialized with globals after +// cleaners are disabled. +val globalCleaner = createCleaner(42) { + println(it) +} + +fun main() { + // Cleaner holds onto a finalization lambda. If it doesn't get executed, + // the memory will leak. Suppress memory leak checker to check for cleaners + // leak only. + Platform.isMemoryLeakCheckerActive = false + Platform.isCleanersLeakCheckerActive = false + // Make sure cleaner is initialized. + assertNotNull(globalCleaner) +} diff --git a/kotlin-native/backend.native/tests/runtime/basic/cleaner_workers.kt b/kotlin-native/backend.native/tests/runtime/basic/cleaner_workers.kt new file mode 100644 index 00000000000..f87e4ab2dbb --- /dev/null +++ b/kotlin-native/backend.native/tests/runtime/basic/cleaner_workers.kt @@ -0,0 +1,174 @@ +/* + * Copyright 2010-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ +@file:OptIn(ExperimentalStdlibApi::class) + +package runtime.basic.cleaner_workers + +import kotlin.test.* + +import kotlin.native.internal.* +import kotlin.native.concurrent.* +import kotlin.native.ref.WeakReference + +class AtomicBoolean(initialValue: Boolean) { + private val impl = AtomicInt(if (initialValue) 1 else 0) + + init { + freeze() + } + + public var value: Boolean + get() = impl.value != 0 + set(new) { impl.value = if (new) 1 else 0 } +} + +class FunBox(private val impl: () -> Unit) { + fun call() { + impl() + } +} + +@Test +fun testCleanerDestroyInChild() { + val worker = Worker.start() + + val called = AtomicBoolean(false); + var funBoxWeak: WeakReference? = null + var cleanerWeak: WeakReference? = null + worker.execute(TransferMode.SAFE, { + val funBox = FunBox { called.value = true }.freeze() + funBoxWeak = WeakReference(funBox) + val cleaner = createCleaner(funBox) { it.call() } + cleanerWeak = WeakReference(cleaner) + Pair(called, cleaner) + }) { (called, cleaner) -> + assertFalse(called.value) + }.result + + GC.collect() + worker.execute(TransferMode.SAFE, {}) { GC.collect() }.result + performGCOnCleanerWorker() + + assertNull(cleanerWeak!!.value) + assertTrue(called.value) + assertNull(funBoxWeak!!.value) + + worker.requestTermination().result +} + +@Test +fun testCleanerDestroyWithChild() { + val worker = Worker.start() + + val called = AtomicBoolean(false); + var funBoxWeak: WeakReference? = null + var cleanerWeak: WeakReference? = null + worker.execute(TransferMode.SAFE, { + val funBox = FunBox { called.value = true }.freeze() + funBoxWeak = WeakReference(funBox) + val cleaner = createCleaner(funBox) { it.call() } + cleanerWeak = WeakReference(cleaner) + Pair(called, cleaner) + }) { (called, cleaner) -> + assertFalse(called.value) + }.result + + GC.collect() + worker.requestTermination().result + waitWorkerTermination(worker) + + performGCOnCleanerWorker() // Collect cleaners stack + + assertNull(cleanerWeak!!.value) + assertTrue(called.value) + assertNull(funBoxWeak!!.value) +} + +@Test +fun testCleanerDestroyInMain() { + val worker = Worker.start() + + val called = AtomicBoolean(false); + var funBoxWeak: WeakReference? = null + var cleanerWeak: WeakReference? = null + { + val result = worker.execute(TransferMode.SAFE, { called }) { called -> + val funBox = FunBox { called.value = true }.freeze() + val cleaner = createCleaner(funBox) { it.call() } + Triple(cleaner, WeakReference(funBox), WeakReference(cleaner)) + }.result + val cleaner = result.first + funBoxWeak = result.second + cleanerWeak = result.third + assertFalse(called.value) + }() + + GC.collect() + worker.execute(TransferMode.SAFE, {}) { GC.collect() }.result + performGCOnCleanerWorker() + + assertNull(cleanerWeak!!.value) + assertTrue(called.value) + assertNull(funBoxWeak!!.value) + + worker.requestTermination().result +} + +@Test +fun testCleanerDestroyShared() { + val worker = Worker.start() + + val called = AtomicBoolean(false); + var funBoxWeak: WeakReference? = null + var cleanerWeak: WeakReference? = null + val cleanerHolder: AtomicReference = AtomicReference(null); + { + val funBox = FunBox { called.value = true }.freeze() + funBoxWeak = WeakReference(funBox) + val cleaner = createCleaner(funBox) { it.call() } + cleanerWeak = WeakReference(cleaner) + cleanerHolder.value = cleaner + worker.execute(TransferMode.SAFE, { Pair(called, cleanerHolder) }) { (called, cleanerHolder) -> + cleanerHolder.value = null + assertFalse(called.value) + }.result + }() + + GC.collect() + worker.execute(TransferMode.SAFE, {}) { GC.collect() }.result + performGCOnCleanerWorker() + + assertNull(cleanerWeak!!.value) + assertTrue(called.value) + assertNull(funBoxWeak!!.value) + + worker.requestTermination().result +} + +@ThreadLocal +var tlsValue = 11 + +@Test +fun testCleanerWithTLS() { + val worker = Worker.start() + + tlsValue = 12 + + val value = AtomicInt(0) + worker.execute(TransferMode.SAFE, {value}) { + tlsValue = 13 + createCleaner(it) { + it.value = tlsValue + } + Unit + }.result + + worker.execute(TransferMode.SAFE, {}) { GC.collect() }.result + performGCOnCleanerWorker() + + assertEquals(11, value.value) + + worker.requestTermination().result +} diff --git a/kotlin-native/backend.native/tests/runtime/basic/driver0.kt b/kotlin-native/backend.native/tests/runtime/basic/driver0.kt new file mode 100644 index 00000000000..4feb92951c3 --- /dev/null +++ b/kotlin-native/backend.native/tests/runtime/basic/driver0.kt @@ -0,0 +1,9 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +// TODO: remove kotlin_native.io once overrides are in place. +fun main(args : Array) { + println("Hello, world!") +} \ No newline at end of file diff --git a/kotlin-native/backend.native/tests/runtime/basic/empty_substring.kt b/kotlin-native/backend.native/tests/runtime/basic/empty_substring.kt new file mode 100644 index 00000000000..02741c2ab96 --- /dev/null +++ b/kotlin-native/backend.native/tests/runtime/basic/empty_substring.kt @@ -0,0 +1,13 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +package runtime.basic.empty_substring + +import kotlin.test.* + +@Test fun runTest() { + val hello = "Hello world" + println(hello.subSequence(1, 1).toString()) +} \ No newline at end of file diff --git a/kotlin-native/backend.native/tests/runtime/basic/entry0.kt b/kotlin-native/backend.native/tests/runtime/basic/entry0.kt new file mode 100644 index 00000000000..c910222464c --- /dev/null +++ b/kotlin-native/backend.native/tests/runtime/basic/entry0.kt @@ -0,0 +1,37 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +package runtime.basic.entry0 + +fun fail() { + println("Test failed, this is a wrong main() function.") +} + +fun main() { + fail() +} + +fun main(args: Array) { + fail() +} + +fun main(args: Array) { + fail() +} + +fun main(args: Array, second_arg: Int) { + fail() +} + +class Foo { + fun main(args: Array) { + fail() + } +} + +fun main(args: Array) { + println("Hello.") +} + diff --git a/kotlin-native/backend.native/tests/runtime/basic/entry1.kt b/kotlin-native/backend.native/tests/runtime/basic/entry1.kt new file mode 100644 index 00000000000..53ba7d1b8a4 --- /dev/null +++ b/kotlin-native/backend.native/tests/runtime/basic/entry1.kt @@ -0,0 +1,22 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +fun fail() { + println("Test failed, this is a wrong main() function.") +} + +fun foo(args: Array) { + println("Hello.") +} + +fun bar() { + println("Hello, without args.") +} + + +fun main(args: Array) { + fail() +} + diff --git a/kotlin-native/backend.native/tests/runtime/basic/entry2.kt b/kotlin-native/backend.native/tests/runtime/basic/entry2.kt new file mode 100644 index 00000000000..9bc6bf7da6e --- /dev/null +++ b/kotlin-native/backend.native/tests/runtime/basic/entry2.kt @@ -0,0 +1,9 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +fun main(args: Array) { + fail() +} + diff --git a/kotlin-native/backend.native/tests/runtime/basic/entry4.kt b/kotlin-native/backend.native/tests/runtime/basic/entry4.kt new file mode 100644 index 00000000000..2bb0ac9bd6f --- /dev/null +++ b/kotlin-native/backend.native/tests/runtime/basic/entry4.kt @@ -0,0 +1,3 @@ +fun main() { + println("This is main without args") +} diff --git a/kotlin-native/backend.native/tests/runtime/basic/enum_equals.kt b/kotlin-native/backend.native/tests/runtime/basic/enum_equals.kt new file mode 100644 index 00000000000..b5db82a51b9 --- /dev/null +++ b/kotlin-native/backend.native/tests/runtime/basic/enum_equals.kt @@ -0,0 +1,22 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +package runtime.basic.enum_equals + +import kotlin.test.* + +enum class EnumA { + A, B +} + +enum class EnumB { + B +} + +fun main() { + println(EnumA.A == EnumA.A) + println(EnumA.A == EnumA.B) + println(EnumA.A == EnumB.B) +} \ No newline at end of file diff --git a/kotlin-native/backend.native/tests/runtime/basic/exit.kt b/kotlin-native/backend.native/tests/runtime/basic/exit.kt new file mode 100644 index 00000000000..e32bae61f8e --- /dev/null +++ b/kotlin-native/backend.native/tests/runtime/basic/exit.kt @@ -0,0 +1,12 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +import kotlin.system.* + +fun main(args: Array) { + exitProcess(42) + @Suppress("UNREACHABLE_CODE") + throw RuntimeException("Exit function call returned normally") +} \ No newline at end of file diff --git a/kotlin-native/backend.native/tests/runtime/basic/for0.kt b/kotlin-native/backend.native/tests/runtime/basic/for0.kt new file mode 100644 index 00000000000..1dd37fb04d2 --- /dev/null +++ b/kotlin-native/backend.native/tests/runtime/basic/for0.kt @@ -0,0 +1,18 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +package runtime.basic.for0 + +import kotlin.test.* + +@Test fun runTest() { + val byteArray = ByteArray(3) + byteArray[0] = 2 + byteArray[1] = 3 + byteArray[2] = 4 + for (item in byteArray) { + println(item) + } +} \ No newline at end of file diff --git a/kotlin-native/backend.native/tests/runtime/basic/hash0.kt b/kotlin-native/backend.native/tests/runtime/basic/hash0.kt new file mode 100644 index 00000000000..42e576f1ce2 --- /dev/null +++ b/kotlin-native/backend.native/tests/runtime/basic/hash0.kt @@ -0,0 +1,26 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +package runtime.basic.hash0 + +import kotlin.test.* + +@Test fun runTest() { + println(239.hashCode()) + println((-1L).hashCode()) + println('a'.hashCode()) + println(1.0f.hashCode()) + println(1.0.hashCode()) + println(true.hashCode()) + println(false.hashCode()) + println(Any().hashCode() != Any().hashCode()) + val a = CharArray(5) + a[0] = 'H' + a[1] = 'e' + a[2] = 'l' + a[3] = 'l' + a[4] = 'o' + println("Hello".hashCode() == String(a, 0, 5).hashCode()) +} \ No newline at end of file diff --git a/kotlin-native/backend.native/tests/runtime/basic/hello0.kt b/kotlin-native/backend.native/tests/runtime/basic/hello0.kt new file mode 100644 index 00000000000..761e65ce3ec --- /dev/null +++ b/kotlin-native/backend.native/tests/runtime/basic/hello0.kt @@ -0,0 +1,12 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +package runtime.basic.hello0 + +import kotlin.test.* + +@Test fun runTest() { + println("Hello, world!") +} diff --git a/kotlin-native/backend.native/tests/runtime/basic/hello1.kt b/kotlin-native/backend.native/tests/runtime/basic/hello1.kt new file mode 100644 index 00000000000..b08c1f3e65e --- /dev/null +++ b/kotlin-native/backend.native/tests/runtime/basic/hello1.kt @@ -0,0 +1,10 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +// TODO: TestRuner should be able to pass input to stdin +// TODO: remove kotlin_native.io once overrides are in place. +fun main(args: Array) { + print(readLine().toString()) +} diff --git a/kotlin-native/backend.native/tests/runtime/basic/hello2.kt b/kotlin-native/backend.native/tests/runtime/basic/hello2.kt new file mode 100644 index 00000000000..4418fb815ef --- /dev/null +++ b/kotlin-native/backend.native/tests/runtime/basic/hello2.kt @@ -0,0 +1,10 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +// TODO: TestRuner should be able to pass input to stdin +// TODO: remove kotlin_native.io once overrides are in place. +fun main(args : Array) { + print("you entered '" + readLine() + "'") +} diff --git a/kotlin-native/backend.native/tests/runtime/basic/hello3.kt b/kotlin-native/backend.native/tests/runtime/basic/hello3.kt new file mode 100644 index 00000000000..f52bec265b8 --- /dev/null +++ b/kotlin-native/backend.native/tests/runtime/basic/hello3.kt @@ -0,0 +1,16 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +package runtime.basic.hello3 + +import kotlin.test.* + +@Test fun runTest() { + println(239) + // TODO: enable, once override by name is implemented. + println(true) + println(3.14159) + println('A') +} \ No newline at end of file diff --git a/kotlin-native/backend.native/tests/runtime/basic/hello4.kt b/kotlin-native/backend.native/tests/runtime/basic/hello4.kt new file mode 100644 index 00000000000..dacd5b11a70 --- /dev/null +++ b/kotlin-native/backend.native/tests/runtime/basic/hello4.kt @@ -0,0 +1,14 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +package runtime.basic.hello4 + +import kotlin.test.* + +@Test fun runTest() { + val x = 2 + println(if (x == 2) "Hello" else "Привет") + println(if (x == 3) "Bye" else "Пока") + } \ No newline at end of file diff --git a/kotlin-native/backend.native/tests/runtime/basic/hypot.kt b/kotlin-native/backend.native/tests/runtime/basic/hypot.kt new file mode 100644 index 00000000000..f125ecd1046 --- /dev/null +++ b/kotlin-native/backend.native/tests/runtime/basic/hypot.kt @@ -0,0 +1,28 @@ +/* + * Copyright 2010-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +import kotlin.test.* +import kotlin.math.* + +fun main() { + val hf = hypot(Float.NEGATIVE_INFINITY, Float.NaN) + println("float hypot: $hf ${hf.toRawBits().toString(16)}") + println("Float.NaN: ${Float.NaN.toRawBits().toString(16)}") + println("Float.+Inf: ${Float.POSITIVE_INFINITY} ${Float.POSITIVE_INFINITY.toRawBits().toString(16)}") + println("Float.-Inf: ${Float.NEGATIVE_INFINITY} ${Float.NEGATIVE_INFINITY.toRawBits().toUInt().toString(16)}") + println(Float.POSITIVE_INFINITY == Float.NEGATIVE_INFINITY) + assertEquals(Float.POSITIVE_INFINITY, hypot(Float.NEGATIVE_INFINITY, Float.NaN)) + + val hd = hypot(Double.NEGATIVE_INFINITY, Double.NaN) + println("Double hypot: $hd ${hd.toRawBits().toString(16)}") + println("Double.NaN: ${Double.NaN.toRawBits().toString(16)}") + println("Double.+Inf: ${Double.POSITIVE_INFINITY} ${Double.POSITIVE_INFINITY.toRawBits().toString(16)}") + println("Double.-Inf: ${Double.NEGATIVE_INFINITY} ${Double.NEGATIVE_INFINITY.toRawBits().toUInt().toString(16)}") + println(Double.POSITIVE_INFINITY == Double.NEGATIVE_INFINITY) + assertEquals(Double.POSITIVE_INFINITY, hypot(Double.NEGATIVE_INFINITY, Double.NaN)) + + println("hypot NaN, 0: ${hypot(Double.NaN, 0.0).toRawBits().toString(16)}") + assertTrue(hypot(Double.NaN, 0.0).isNaN()) +} \ No newline at end of file diff --git a/kotlin-native/backend.native/tests/runtime/basic/ieee754.kt b/kotlin-native/backend.native/tests/runtime/basic/ieee754.kt new file mode 100644 index 00000000000..c836dae690b --- /dev/null +++ b/kotlin-native/backend.native/tests/runtime/basic/ieee754.kt @@ -0,0 +1,34 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +package runtime.basic.ieee754 + +import kotlin.test.* + +@Test fun runTest() { + val v = Float.POSITIVE_INFINITY + val i = v.toInt() + println("$v $i ${v.toShort()} ${i.toShort()}") + + val a = 42 + val b = Float.MAX_VALUE + println("${a + b}") + + val s = Float.NaN.toShort() + println("NAN2SHORT:: $s") + + val d: Float = Float.MAX_VALUE + println("MAX2SHORT:: ${d.toShort()}") + val d2i = d.toInt() + println("$d2i ${d2i.toShort()}") + + for (f in arrayOf(Float.POSITIVE_INFINITY, Float.MAX_VALUE / 2, Float.MAX_VALUE, + 3.14f, Float.NaN, -33333.12312f, Float.MIN_VALUE, Float.NEGATIVE_INFINITY, + -1.2f, -12.6f, 2.3f)) { + println("FLOAT:: $f INT:: ${f.toInt()}") + } + + println("OK") +} \ No newline at end of file diff --git a/kotlin-native/backend.native/tests/runtime/basic/init.kt b/kotlin-native/backend.native/tests/runtime/basic/init.kt new file mode 100644 index 00000000000..780339071d5 --- /dev/null +++ b/kotlin-native/backend.native/tests/runtime/basic/init.kt @@ -0,0 +1,4 @@ +val x = initRuntimeIfNeeded() + +fun main() { +} diff --git a/kotlin-native/backend.native/tests/runtime/basic/initializers0.kt b/kotlin-native/backend.native/tests/runtime/basic/initializers0.kt new file mode 100644 index 00000000000..31d7d291b4c --- /dev/null +++ b/kotlin-native/backend.native/tests/runtime/basic/initializers0.kt @@ -0,0 +1,53 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +package runtime.basic.initializers0 + +import kotlin.test.* + +class A { + init{ + println ("A::init") + } + + val a = 1 + + companion object :B(1) { + init { + println ("A::companion") + } + + fun foo() { + println("A::companion::foo") + } + } + + object AObj : B(){ + init { + println("A::Obj") + } + fun foo() { + println("A::AObj::foo") + } + } +} + +@Test fun runTest() { + println("main") + A.foo() + A.foo() + A.AObj.foo() + A.AObj.foo() +} + +open class B(val a:Int, val b:Int) { + constructor(a:Int):this (a, 0) { + println("B::constructor(" + a.toString()+ ")") + } + constructor():this(0) { + println("B::constructor()") + } +} + diff --git a/kotlin-native/backend.native/tests/runtime/basic/initializers1.kt b/kotlin-native/backend.native/tests/runtime/basic/initializers1.kt new file mode 100644 index 00000000000..7b8c7cc2851 --- /dev/null +++ b/kotlin-native/backend.native/tests/runtime/basic/initializers1.kt @@ -0,0 +1,22 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +package runtime.basic.initializers1 + +import kotlin.test.* + +class TestClass { + companion object { + init { + println("Init Test") + } + } +} + +@Test fun runTest() { + val t1 = TestClass() + val t2 = TestClass() + println("Done") +} \ No newline at end of file diff --git a/kotlin-native/backend.native/tests/runtime/basic/initializers2.kt b/kotlin-native/backend.native/tests/runtime/basic/initializers2.kt new file mode 100644 index 00000000000..aa24adce598 --- /dev/null +++ b/kotlin-native/backend.native/tests/runtime/basic/initializers2.kt @@ -0,0 +1,22 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +class A(val msg: String) { + init { + println("init $msg") + } + override fun toString(): String = msg +} + +val globalValue1 = 1 +val globalValue2 = A("globalValue2") +val globalValue3 = A("globalValue3") + +fun main(args: Array) { + println(globalValue1.toString()) + println(globalValue2.toString()) + println(globalValue3.toString()) +} + diff --git a/kotlin-native/backend.native/tests/runtime/basic/initializers3.kt b/kotlin-native/backend.native/tests/runtime/basic/initializers3.kt new file mode 100644 index 00000000000..5dfb0c67803 --- /dev/null +++ b/kotlin-native/backend.native/tests/runtime/basic/initializers3.kt @@ -0,0 +1,16 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +package runtime.basic.initializers3 + +import kotlin.test.* + +class Foo(val bar: Int) + +var x = Foo(42) + +@Test fun runTest() { + println(x.bar) +} \ No newline at end of file diff --git a/kotlin-native/backend.native/tests/runtime/basic/initializers4.kt b/kotlin-native/backend.native/tests/runtime/basic/initializers4.kt new file mode 100644 index 00000000000..008b512b138 --- /dev/null +++ b/kotlin-native/backend.native/tests/runtime/basic/initializers4.kt @@ -0,0 +1,16 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +package runtime.basic.initializers4 + +import kotlin.test.* + +const val INT_MAX_POWER_OF_TWO: Int = Int.MAX_VALUE / 2 + 1 +val DOUBLE = Double.MAX_VALUE - 1.0 + +@Test fun runTest() { + println(INT_MAX_POWER_OF_TWO) + println(DOUBLE > 0.0) +} diff --git a/kotlin-native/backend.native/tests/runtime/basic/initializers5.kt b/kotlin-native/backend.native/tests/runtime/basic/initializers5.kt new file mode 100644 index 00000000000..0c67dcb38b0 --- /dev/null +++ b/kotlin-native/backend.native/tests/runtime/basic/initializers5.kt @@ -0,0 +1,17 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +package runtime.basic.initializers5 + +import kotlin.test.* + +object A { + val a = 42 + val b = A.a +} + +@Test fun runTest() { + println(A.b) +} \ No newline at end of file diff --git a/kotlin-native/backend.native/tests/runtime/basic/initializers6.kt b/kotlin-native/backend.native/tests/runtime/basic/initializers6.kt new file mode 100644 index 00000000000..7c08d654282 --- /dev/null +++ b/kotlin-native/backend.native/tests/runtime/basic/initializers6.kt @@ -0,0 +1,74 @@ +/* + * Copyright 2010-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +package runtime.basic.initializers6 + +import kotlin.test.* + +import kotlin.native.concurrent.* + +val aWorkerId = AtomicInt(0) +val bWorkersCount = 3 + +val aWorkerUnlocker = AtomicInt(0) +val bWorkerUnlocker = AtomicInt(0) + +object A { + init { + // Must be called by aWorker only. + assertEquals(aWorkerId.value, Worker.current.id) + // Only allow b workers to run, when a worker has started initialization. + bWorkerUnlocker.increment() + // Only proceed with initialization, when all b workers have started executing. + while (aWorkerUnlocker.value < bWorkersCount) {} + // And now wait a bit, to increase probability of races. + Worker.current.park(100 * 1000L) + } + val a = produceA() + val b = produceB() +} + +fun produceA(): String { + // Must've been called by aWorker only. + assertEquals(aWorkerId.value, Worker.current.id) + return "A" +} + +fun produceB(): String { + // Must've been called by aWorker only. + assertEquals(aWorkerId.value, Worker.current.id) + // Also check that it's ok to get A.a while initializing A.b. + return "B+${A.a}" +} + +@Test fun runTest() { + val aWorker = Worker.start() + aWorkerId.value = aWorker.id + val bWorkers = Array(bWorkersCount, { _ -> Worker.start() }) + + val aFuture = aWorker.execute(TransferMode.SAFE, {}, { + A.b + }) + val bFutures = Array(bWorkers.size, { + bWorkers[it].execute(TransferMode.SAFE, {}, { + // Wait until A has started to initialize. + while (bWorkerUnlocker.value < 1) {} + // Now allow A initialization to continue. + aWorkerUnlocker.increment() + // And this should not've tried to init A itself. + A.a + A.b + }) + }) + + for (future in bFutures) { + assertEquals("AB+A", future.result) + } + assertEquals("B+A", aFuture.result) + + for (worker in bWorkers) { + worker.requestTermination().result + } + aWorker.requestTermination().result +} diff --git a/kotlin-native/backend.native/tests/runtime/basic/initializers7.kt b/kotlin-native/backend.native/tests/runtime/basic/initializers7.kt new file mode 100644 index 00000000000..7327675675f --- /dev/null +++ b/kotlin-native/backend.native/tests/runtime/basic/initializers7.kt @@ -0,0 +1,60 @@ +/* + * Copyright 2010-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +package runtime.basic.initializers7 + +import kotlin.test.* + +object A { + init { + assertAUninitialized() + } + val a1 = 7 + val a2 = 12 +} + +// Check that A is initialized dynamically. +fun assertAUninitialized() { + assertEquals(0, A.a1) + assertEquals(0, A.a2) +} + +object B { + init { + assertBUninitialized() + } + val b1 = A.a2 + val b2 = C.c1 +} + +// Check that B is initialized dynamically. +fun assertBUninitialized() { + assertEquals(0, B.b1) + assertEquals(0, B.b2) +} + +object C { + init { + assertCUninitialized() + } + val c1 = 42 + val c2 = A.a1 + val c3 = B.b1 + val c4 = B.b2 +} + +// Check that C is initialized dynamically. +fun assertCUninitialized() { + assertEquals(0, C.c1) + assertEquals(0, C.c2) + assertEquals(0, C.c3) + assertEquals(0, C.c4) +} + +@Test fun runTest() { + assertEquals(A.a1, C.c2) + assertEquals(A.a2, C.c3) + assertEquals(C.c1, C.c4) +} diff --git a/kotlin-native/backend.native/tests/runtime/basic/interface0.kt b/kotlin-native/backend.native/tests/runtime/basic/interface0.kt new file mode 100644 index 00000000000..347e562c5b6 --- /dev/null +++ b/kotlin-native/backend.native/tests/runtime/basic/interface0.kt @@ -0,0 +1,25 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +package runtime.basic.interface0 + +import kotlin.test.* + +interface A { + fun b() = c() + fun c() +} + +class B(): A { + override fun c() { + println("PASSED") + } +} + +@Test fun runTest() { + val a:A = B() + a.b() +} + diff --git a/kotlin-native/backend.native/tests/runtime/basic/libentry2.kt b/kotlin-native/backend.native/tests/runtime/basic/libentry2.kt new file mode 100644 index 00000000000..4e70e2cd305 --- /dev/null +++ b/kotlin-native/backend.native/tests/runtime/basic/libentry2.kt @@ -0,0 +1,13 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +fun fail() { + println("Test failed, this is a wrong main() function.") +} + +fun foo(args: Array) { + println("Hello.") +} + diff --git a/kotlin-native/backend.native/tests/runtime/basic/main_exception.kt b/kotlin-native/backend.native/tests/runtime/basic/main_exception.kt new file mode 100644 index 00000000000..78a20406592 --- /dev/null +++ b/kotlin-native/backend.native/tests/runtime/basic/main_exception.kt @@ -0,0 +1,12 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +package runtime.basic.main_exception + +import kotlin.test.* + +@Test fun runTest() { + throw Error("Hello!") +} diff --git a/kotlin-native/backend.native/tests/runtime/basic/random.kt b/kotlin-native/backend.native/tests/runtime/basic/random.kt new file mode 100644 index 00000000000..8afeac16175 --- /dev/null +++ b/kotlin-native/backend.native/tests/runtime/basic/random.kt @@ -0,0 +1,63 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +package runtime.basic.random + +import kotlin.collections.* +import kotlin.random.* +import kotlin.system.* +import kotlin.test.* + +/** + * Tests that setting the same seed make random generate the same sequence + */ +private inline fun testReproducibility(seed: Long, generator: Random.() -> T) { + // Reset seed. This will make Random to start a new sequence + val r1 = Random(seed) + val first = Array(50, { i -> r1.generator() }).toList() + + // Reset seed and try again + val r2 = Random(seed) + val second = Array(50, { i -> r2.generator() }).toList() + assertTrue(first == second, "FAIL: got different sequences of generated values " + + "first: $first, second: $second") +} + +/** + * Tests that setting seed makes random generate different sequence. + */ +private inline fun testDifference(generator: Random.() -> T) { + val r1 = Random(12345678L) + val first = Array(100, { i -> r1.generator() }).toList() + + val r2 = Random(87654321L) + val second = Array(100, { i -> r2.generator() }).toList() + assertTrue(first != second, "FAIL: got the same sequence of generated values " + + "first: $first, second: $second") +} + +@Test +fun testInts() { + testReproducibility(getTimeMillis(), { nextInt() }) + testReproducibility(Long.MAX_VALUE, { nextInt() }) +} + +@Test +fun testLong() { + testReproducibility(getTimeMillis(), { nextLong() }) + testReproducibility(Long.MAX_VALUE, { nextLong() }) +} + +@Test +fun testDiffInt() = testDifference { nextInt() } + +@Test +fun testDiffLong() = testDifference { nextLong() } + +@Test +fun testNextInt() { + testReproducibility(getTimeMillis(), { nextInt(1000) }) + testReproducibility(1000L, { nextInt(1024) }) +} diff --git a/kotlin-native/backend.native/tests/runtime/basic/readline0.kt b/kotlin-native/backend.native/tests/runtime/basic/readline0.kt new file mode 100644 index 00000000000..d158665106a --- /dev/null +++ b/kotlin-native/backend.native/tests/runtime/basic/readline0.kt @@ -0,0 +1,8 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +fun main(args: Array) { + print(readLine()!!.toInt()) +} \ No newline at end of file diff --git a/kotlin-native/backend.native/tests/runtime/basic/readline1.kt b/kotlin-native/backend.native/tests/runtime/basic/readline1.kt new file mode 100644 index 00000000000..3dc9b11df78 --- /dev/null +++ b/kotlin-native/backend.native/tests/runtime/basic/readline1.kt @@ -0,0 +1,8 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +fun main(args: Array) { + print(readLine()!!) +} \ No newline at end of file diff --git a/kotlin-native/backend.native/tests/runtime/basic/simd.kt b/kotlin-native/backend.native/tests/runtime/basic/simd.kt new file mode 100644 index 00000000000..65b2ee3e064 --- /dev/null +++ b/kotlin-native/backend.native/tests/runtime/basic/simd.kt @@ -0,0 +1,104 @@ +/* + * Copyright 2010-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +package runtime.basic.simd + +import kotlin.test.* + + +@Test fun runTest() { + testBoxingSimple() + testBoxing() + testSetGet() + testString() + testOOB() + testEquals() + testHash() + testDefaultValue() +} + + +class Box(t: T) { + var value = t +} + +class UnalignedC(t: Vector128) { + var smth = 1 + var value = t +} + +fun testBoxingSimple() { + val v = vectorOf(1f, 3.162f, 10f, 31f) + val box: Box = Box(v) + assertEquals(v, box.value, "testBoxingSimple FAILED") +} + +fun testBoxing() { + var u = UnalignedC(vectorOf(0, 1, 2, 3)) + assertEquals(3, u.value.getIntAt(3)) + u.value = vectorOf(0f, 1f, 2f, 3f) + assertEquals(vectorOf(0f, 1f, 2f, 3f), u.value, "testBoxing FAILED") +} + +fun testSetGet() { + var v4any = vectorOf(0, 1, 2, 3) + (0 until 4).forEach { assertEquals(it, v4any.getIntAt(it), "testSetGet FAILED for <4 x i32>") } + + // type punning: set the variable to another runtime type + val a = arrayOf(1f, 3.162f, 10f, 31f) + v4any = vectorOf(a[0], a[1], a[2], a[3]) + (0 until 4).forEach { assertEquals(a[it], v4any.getFloatAt(it), "testSetGet FAILED for <4 x float>") } +} + +fun testString() { + val v4i = vectorOf(100, 1024, Int.MAX_VALUE, Int.MIN_VALUE) + assertEquals("(0x64, 0x400, 0x7fffffff, 0x80000000)", v4i.toString(), "testString FAILED") +} + +fun testOOB() { + val f = vectorOf(1f, 3.162f, 10f, 31f) + + println("f.getByteAt(15) is OK ${f.getByteAt(15)}") + + assertFailsWith("f.getByteAt(16) should fail") { + f.getByteAt(16) + } + + assertFailsWith("f.getIntAt(-1) should fail") { + f.getIntAt(-1) + } + + assertFailsWith("f.getFloatAt(4) should fail") { + f.getFloatAt(4) + } +} + +fun testEquals() { + var v1 = vectorOf(-1f, 0f, 0f, -7f) + var v2 = vectorOf(1f, 4f, 3f, 7f) + assertEquals(false, v1 == v2) + assertEquals(false, v1.equals(v2)) + assertEquals(false, v1.equals(Any())) + assertEquals(true, v2 == v2) + + v1 = v2 + assertEquals(true, v1 == v2) +} + +fun testHash() { + val h1 = vectorOf(1f, 4f, 3f, 7f).hashCode() + val h2 = vectorOf(3f, 7f, 1f, 4f).hashCode() + assertEquals(false, h1 == h2) + + val i = 654687 + assertEquals(true, vectorOf(0, 0, i, 0).hashCode() == i.hashCode()) // exploit little endianness + assertEquals(true, vectorOf(1, 0, 0, 0).hashCode() == vectorOf(0, 0, 31, 0).hashCode()) +} + +private fun funDefaultValue(v: Vector128 = vectorOf(1.0f, 2.0f, 3.0f, 4.0f)) = v + +fun testDefaultValue() { + assertEquals(vectorOf(1.0f, 2.0f, 3.0f, 4.0f), funDefaultValue()) +} diff --git a/kotlin-native/backend.native/tests/runtime/basic/standard.kt b/kotlin-native/backend.native/tests/runtime/basic/standard.kt new file mode 100644 index 00000000000..0a8b96f83e1 --- /dev/null +++ b/kotlin-native/backend.native/tests/runtime/basic/standard.kt @@ -0,0 +1,32 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +package runtime.basic.standard + +import kotlin.test.* + +class Foo(val bar: Int) + +fun assertEquals(actual: T, expected: T) { + if (actual != expected) throw AssertionError("Assertion failed. Expected value: $expected, actual value: $actual") +} + +@Test fun runTest() { + try { + TODO() + throw AssertionError("TODO() doesn't throw an exception") + } catch(e: NotImplementedError) {} + + val foo = Foo(42) + assertEquals(run { 42 }, 42) + assertEquals(foo.run { bar }, 42) + assertEquals(with(foo) { bar }, 42) + assertEquals(foo.apply { bar }, foo) + assertEquals(foo.also { it.bar }, foo) + assertEquals(foo.let { it.bar }, 42) + var i = 0 + repeat(10) { i++ } + assertEquals(i, 10) +} \ No newline at end of file diff --git a/kotlin-native/backend.native/tests/runtime/basic/statements0.kt b/kotlin-native/backend.native/tests/runtime/basic/statements0.kt new file mode 100644 index 00000000000..8011155b17b --- /dev/null +++ b/kotlin-native/backend.native/tests/runtime/basic/statements0.kt @@ -0,0 +1,42 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +package runtime.basic.statements0 + +import kotlin.test.* + +fun simple() { + var a = 238 + a++ + println(a) + --a + println(a) +} + +class Foo() { + val j = 2 + var i = 29 + + fun more() { + i++ + } + + fun less() { + --i + } +} + +fun fields() { + val foo = Foo() + foo.more() + println(foo.i) + foo.less() + println(foo.i) +} + +@Test fun runTest() { + simple() + fields() +} \ No newline at end of file diff --git a/kotlin-native/backend.native/tests/runtime/basic/throw0.kt b/kotlin-native/backend.native/tests/runtime/basic/throw0.kt new file mode 100644 index 00000000000..1970a638fe7 --- /dev/null +++ b/kotlin-native/backend.native/tests/runtime/basic/throw0.kt @@ -0,0 +1,17 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +package runtime.basic.throw0 + +import kotlin.test.* + +@Test fun runTest() { + val cond = 1 + if (cond == 2) throw RuntimeException() + if (cond == 3) throw NoSuchElementException("no such element") + if (cond == 4) throw Error("error happens") + + println("Done") +} diff --git a/kotlin-native/backend.native/tests/runtime/basic/tostring0.kt b/kotlin-native/backend.native/tests/runtime/basic/tostring0.kt new file mode 100644 index 00000000000..aebff72d9c1 --- /dev/null +++ b/kotlin-native/backend.native/tests/runtime/basic/tostring0.kt @@ -0,0 +1,27 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +package runtime.basic.tostring0 + +import kotlin.test.* + +@Test fun runTest() { + println(127.toByte().toString()) + println(255.toByte().toString()) + println(239.toShort().toString()) + println('A'.toString()) + println('Ё'.toString()) + println('ト'.toString()) + println(1122334455.toString()) + println(112233445566778899.toString()) + // Here we differ from Java, as have no dtoa() yet. + println(3.14159265358.toString()) + // Here we differ from Java, as have no dtoa() yet. + println(1e27.toFloat().toString()) + println(1e7.toString()) + println(1e-300.toDouble().toString()) + println(true.toString()) + println(false.toString()) +} \ No newline at end of file diff --git a/kotlin-native/backend.native/tests/runtime/basic/tostring1.kt b/kotlin-native/backend.native/tests/runtime/basic/tostring1.kt new file mode 100644 index 00000000000..ccf26ceb4b8 --- /dev/null +++ b/kotlin-native/backend.native/tests/runtime/basic/tostring1.kt @@ -0,0 +1,13 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +package runtime.basic.tostring1 + +import kotlin.test.* + +@Test fun runTest() { + val hello = "Hello world" + println(hello.subSequence(1, 5).toString()) +} \ No newline at end of file diff --git a/kotlin-native/backend.native/tests/runtime/basic/tostring2.kt b/kotlin-native/backend.native/tests/runtime/basic/tostring2.kt new file mode 100644 index 00000000000..c767028700c --- /dev/null +++ b/kotlin-native/backend.native/tests/runtime/basic/tostring2.kt @@ -0,0 +1,19 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +package runtime.basic.tostring2 + +import kotlin.test.* + +@Test fun runTest() { + val hello = "Hello" + val array = hello.toCharArray() + for (ch in array) { + print(ch) + print(" ") + } + println() + println(String(array, 0, array.size)) +} \ No newline at end of file diff --git a/kotlin-native/backend.native/tests/runtime/basic/tostring3.kt b/kotlin-native/backend.native/tests/runtime/basic/tostring3.kt new file mode 100644 index 00000000000..5381283ea3e --- /dev/null +++ b/kotlin-native/backend.native/tests/runtime/basic/tostring3.kt @@ -0,0 +1,78 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +package runtime.basic.tostring3 + +import kotlin.test.* + +fun testByte() { + val values = ByteArray(2) + values[0] = Byte.MIN_VALUE + values[1] = Byte.MAX_VALUE + for (v in values) { + println(v) + } +} + +fun testShort() { + val values = ShortArray(2) + values[0] = Short.MIN_VALUE + values[1] = Short.MAX_VALUE + for (v in values) { + println(v) + } +} + +fun testInt() { + val values = IntArray(2) + values[0] = Int.MIN_VALUE + values[1] = Int.MAX_VALUE + for (v in values) { + println(v) + } +} + +fun testLong() { + val values = LongArray(2) + values[0] = Long.MIN_VALUE + values[1] = Long.MAX_VALUE + for (v in values) { + println(v) + } +} + +fun testFloat() { + val values = FloatArray(5) + values[0] = Float.MIN_VALUE + values[1] = Float.MAX_VALUE + values[2] = Float.NEGATIVE_INFINITY + values[3] = Float.POSITIVE_INFINITY + values[4] = Float.NaN + for (v in values) { + println(v) + } +} + +fun testDouble() { + val values = DoubleArray(5) + values[0] = Double.MIN_VALUE + values[1] = Double.MAX_VALUE + values[2] = Double.NEGATIVE_INFINITY + values[3] = Double.POSITIVE_INFINITY + values[4] = Double.NaN + for (v in values) { + println(v) + } +} + +@Test fun runTest() { + testByte() + testShort() + testInt() + testLong() + testFloat() + testDouble() + +} diff --git a/kotlin-native/backend.native/tests/runtime/basic/worker_random.kt b/kotlin-native/backend.native/tests/runtime/basic/worker_random.kt new file mode 100644 index 00000000000..e46d6cc2493 --- /dev/null +++ b/kotlin-native/backend.native/tests/runtime/basic/worker_random.kt @@ -0,0 +1,42 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +package runtime.basic.worker_random + +import kotlin.native.concurrent.* +import kotlin.collections.* +import kotlin.random.* +import kotlin.system.* +import kotlin.test.* + +@Test +fun testRandomWorkers() { + val seed = getTimeMillis() + val workers = Array(5, { _ -> Worker.start() }) + + val attempts = 3 + val results = Array(attempts, { ArrayList() } ) + for (attempt in 0 until attempts) { + // Produce a list of random numbers in each worker + val futures = Array(workers.size, { workerIndex -> + workers[workerIndex].execute(TransferMode.SAFE, { workerIndex }) { + input -> + Array(10, { Random.nextInt() }).toList() + } + }) + // Now collect all results into current attempt's list + val futureSet = futures.toSet() + var finished = 0 + while (finished < futureSet.size) { + val ready = waitForMultipleFutures(futureSet, 10000) + ready.forEach { results[attempt].addAll(it.result) } + finished += ready.size + } + } + + workers.forEach { + it.requestTermination().result + } +} \ No newline at end of file diff --git a/kotlin-native/backend.native/tests/runtime/collections/AbstractMutableCollection.kt b/kotlin-native/backend.native/tests/runtime/collections/AbstractMutableCollection.kt new file mode 100644 index 00000000000..536be5acf14 --- /dev/null +++ b/kotlin-native/backend.native/tests/runtime/collections/AbstractMutableCollection.kt @@ -0,0 +1,72 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +package runtime.collections.AbstractMutableCollection + +import kotlin.test.* + +class TestCollection(): AbstractMutableCollection() { + companion object { + const val SIZE = 7 + } + + private val array = IntArray(SIZE) + private var len = 0 + + override val size: Int + get() = len + + override fun add(element: Int): Boolean { + if (len >= SIZE) return false + array[len++] = element + return true + } + + override fun iterator(): MutableIterator = object: MutableIterator { + var nextIndex = 0 + + override fun hasNext() = nextIndex < len + override fun next() = array[nextIndex++] + + override fun remove() { + if (nextIndex == 0) throw IllegalStateException() + for (i in nextIndex..len - 1) { + array[i - 1] = array[i] + } + len-- + nextIndex-- + } + } + + override fun clear() { + len = 0 + } + +} + +fun assertEquals(a: TestCollection, b: List) { + if (a.size != b.size) { + throw AssertionError() + } + val aIt = a.iterator() + val bIt = b.iterator() + while (aIt.hasNext()) { + if (aIt.next() != bIt.next()) throw AssertionError("TestCollection contains wrong elements. Expected: $b, actual: $a.") + } +} + +@Test fun runTest() { + val c = TestCollection() + if (!c.addAll(listOf(1, 2, 3, 2, 4, 5, 4))) throw AssertionError("addAll is false when it must be true.") + if (c.addAll(listOf(1, 2)) != false) throw AssertionError("addAll is true when it must be false.") + c.removeAll(listOf(1, 2)) + assertEquals(c, listOf(3, 4, 5, 4)) + c.retainAll(listOf(4, 5)) + assertEquals(c, listOf(4, 5, 4)) + c.remove(4) + assertEquals(c, listOf(5, 4)) + c.clear() + assertEquals(c, listOf()) +} \ No newline at end of file diff --git a/kotlin-native/backend.native/tests/runtime/collections/BitSet.kt b/kotlin-native/backend.native/tests/runtime/collections/BitSet.kt new file mode 100644 index 00000000000..98abcad5db8 --- /dev/null +++ b/kotlin-native/backend.native/tests/runtime/collections/BitSet.kt @@ -0,0 +1,456 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +package runtime.collections.BitSet + +import kotlin.test.* + +fun assertContainsOnly(bitSet: BitSet, trueBits: Set, size: Int) { + for (i in 0 until size) { + val expectedBit = i in trueBits + if (bitSet[i] != expectedBit) { + throw AssertionError() + } + } +} + +fun assertNotContainsOnly(bitSet: BitSet, falseBits: Set, size: Int) { + for (i in 0 until size) { + val expectedBit = i !in falseBits + if (bitSet[i] != expectedBit) { + throw AssertionError() + } + } +} + +fun assertTrue(str: String, cond: Boolean) { if (!cond) throw AssertionError(str) } +fun assertFalse(str: String, cond: Boolean) { if (cond) throw AssertionError(str) } +fun assertEquals(str: String, a: T, b: T) { if (a != b) throw AssertionError(str) } + +fun assertTrue(cond: Boolean) = assertTrue("", cond) +fun assertFalse(cond: Boolean) = assertFalse("", cond) +fun assertEquals(a: T, b: T) = assertEquals("", a, b) + +fun fail(): Unit = throw AssertionError() + +fun testConstructor() { + var b = BitSet(12) + assertContainsOnly(b, setOf(), 12) + + b = BitSet(12) { it == 0 || it in 5..6 || it == 11 } + assertContainsOnly(b, setOf(0, 5, 6, 11), 12) +} + +fun testSet() { + var b = BitSet(0) + assertEquals(b.lastTrueIndex, -1) + b = BitSet(2) + // Test set and clear operation for single index. + assertTrue(b.isEmpty) + b.set(0, true) + b.set(3, true) + assertEquals(b.lastTrueIndex, 3) + assertFalse(b.isEmpty) + assertContainsOnly(b, setOf(0, 3), 4) + b.clear() + assertContainsOnly(b, setOf(), 4) + b.set(1) + b.set(5) + assertEquals(b.lastTrueIndex, 5) + assertContainsOnly(b, setOf(1, 5), 6) + b.set(1, false) + b.set(7, false) + assertEquals(b.lastTrueIndex, 5) + assertContainsOnly(b, setOf(5), 8) + b.clear(5) + assertEquals(b.lastTrueIndex, -1) + assertContainsOnly(b, setOf(), 8) + b.set(70) + assertEquals(b.lastTrueIndex, 70) + assertContainsOnly(b, setOf(70), 71) + b.clear(70) + assertEquals(b.lastTrueIndex, -1) + assertContainsOnly(b, setOf(), 71) + + // Test set and clear operations for ranges. + // Set false and clear. + b = BitSet(2) + assertContainsOnly(b, setOf(), 2) + b.set(0..70, true) + assertNotContainsOnly(b, setOf(), 71) + b.set(0..2, false) + assertNotContainsOnly(b, setOf(0, 1, 2), 71) + b.set(63..65, false) + assertNotContainsOnly(b, setOf(0, 1, 2, 63, 64, 65), 71) + b.set(68..70, false) + assertNotContainsOnly(b, setOf(0, 1, 2, 63, 64, 65, 68, 69, 70), 71) + b.set(68..72, false) + assertNotContainsOnly(b, setOf(0, 1, 2, 63, 64, 65, 68, 69, 70, 71, 72), 73) + b.set(0..72, false) + assertContainsOnly(b, setOf(), 73) + + b.set(0..72) + assertNotContainsOnly(b, setOf(), 73) + b.clear(0..2) + assertNotContainsOnly(b, setOf(0, 1, 2), 73) + b.clear(63..65) + assertNotContainsOnly(b, setOf(0, 1, 2, 63, 64, 65), 73) + b.clear(68..70) + assertNotContainsOnly(b, setOf(0, 1, 2, 63, 64, 65, 68, 69, 70), 73) + b.clear(68..72) + assertNotContainsOnly(b, setOf(0, 1, 2, 63, 64, 65, 68, 69, 70, 71, 72), 73) + b.clear(0..72) + assertContainsOnly(b, setOf(), 73) + + // Set true. + b.set(0..2, true) + assertContainsOnly(b, setOf(0, 1, 2), 73) + b.set(63..65, true) + assertContainsOnly(b, setOf(0, 1, 2, 63, 64, 65), 73) + b.set(70..72, true) + assertContainsOnly(b, setOf(0, 1, 2, 63, 64, 65, 70, 71, 72), 73) + b.set(73..74, true) + assertContainsOnly(b, setOf(0, 1, 2, 63, 64, 65, 70, 71, 72, 73, 74), 75) + b.set(0..74, true) + assertNotContainsOnly(b, setOf(), 75) + + // Test set and clear for pair of indices. + b = BitSet(2) + assertContainsOnly(b, setOf(), 71) + b.set(0, 71, true) + assertNotContainsOnly(b, setOf(), 71) + b.set(0, 3, false) + assertNotContainsOnly(b, setOf(0, 1, 2), 71) + b.set(63, 66, false) + assertNotContainsOnly(b, setOf(0, 1, 2, 63, 64, 65), 71) + b.set(68, 71, false) + assertNotContainsOnly(b, setOf(0, 1, 2, 63, 64, 65, 68, 69, 70), 71) + b.set(68, 73, false) + assertNotContainsOnly(b, setOf(0, 1, 2, 63, 64, 65, 68, 69, 70, 71, 72), 73) + b.set(0, 73, false) + assertContainsOnly(b, setOf(), 73) + + b.set(0, 73) + assertNotContainsOnly(b, setOf(), 73) + b.clear(0, 3) + assertNotContainsOnly(b, setOf(0, 1, 2), 73) + b.clear(63, 66) + assertNotContainsOnly(b, setOf(0, 1, 2, 63, 64, 65), 73) + b.clear(68, 71) + assertNotContainsOnly(b, setOf(0, 1, 2, 63, 64, 65, 68, 69, 70), 73) + b.clear(68, 73) + assertNotContainsOnly(b, setOf(0, 1, 2, 63, 64, 65, 68, 69, 70, 71, 72), 73) + b.clear(0, 73) + assertContainsOnly(b, setOf(), 73) + + // Set true. + b.set(0, 3, true) + assertContainsOnly(b, setOf(0, 1, 2), 73) + b.set(63, 66, true) + assertContainsOnly(b, setOf(0, 1, 2, 63, 64, 65), 73) + b.set(70, 73, true) + assertContainsOnly(b, setOf(0, 1, 2, 63, 64, 65, 70, 71, 72), 73) + b.set(73, 75, true) + assertContainsOnly(b, setOf(0, 1, 2, 63, 64, 65, 70, 71, 72, 73, 74), 75) + b.set(0, 75, true) + assertNotContainsOnly(b, setOf(), 75) + + // Access to negative elements must cause an exception + try { + b.set(-1) + fail() + } catch(e: IndexOutOfBoundsException) {} + try { + b.clear(-1) + fail() + } catch(e: IndexOutOfBoundsException) {} + try { + b.clear(-1..0) + fail() + } catch(e: IndexOutOfBoundsException) {} + try { + b.set(-1..0) + fail() + } catch(e: IndexOutOfBoundsException) {} + try { + b[-1] + fail() + } catch(e: IndexOutOfBoundsException) {} +} + +fun testFlip() { + val b = BitSet(2) + b.set(0, true) + b.set(70, true) + b.set(63..65, true) + assertEquals(b.lastTrueIndex, 70) + // 0 element + assertContainsOnly(b, setOf(0, 63, 64, 65, 70), 71) + b.flip(0) + assertContainsOnly(b, setOf(63, 64, 65, 70), 71) + b.flip(1) + assertContainsOnly(b, setOf(1, 63, 64, 65, 70), 71) + b.flip(0) + assertContainsOnly(b, setOf(0, 1, 63, 64, 65, 70), 71) + + // last element + b.flip(70) + assertContainsOnly(b, setOf(0, 1, 63, 64, 65), 71) + b.flip(69) + assertContainsOnly(b, setOf(0, 1, 63, 64, 65, 69), 71) + b.flip(70) + assertContainsOnly(b, setOf(0, 1, 63, 64, 65, 69, 70), 71) + + // element in the middle + b.flip(64) + assertContainsOnly(b, setOf(0, 1, 63, 65, 69, 70), 71) + b.flip(65) + assertContainsOnly(b, setOf(0, 1, 63, 69, 70), 71) + b.flip(65) + b.flip(64) + assertContainsOnly(b, setOf(0, 1, 63, 64, 65, 69, 70), 71) + + // range in the beginning + b.flip(0..2) + assertContainsOnly(b, setOf(2, 63, 64, 65, 69, 70), 71) + b.flip(0, 3) + assertContainsOnly(b, setOf(0, 1, 63, 64, 65, 69, 70), 71) + + // In the end + b.flip(68..70) + assertContainsOnly(b, setOf(0, 1, 63, 64, 65, 68), 71) + b.flip(68, 71) + assertContainsOnly(b, setOf(0, 1, 63, 64, 65, 69, 70), 71) + + // In the middle + b.flip(64..66) + assertContainsOnly(b, setOf(0, 1, 63, 66, 69, 70), 71) + b.flip(64, 67) + assertContainsOnly(b, setOf(0, 1, 63, 64, 65, 69, 70), 71) + + // Access to a negative element must cause an exception. + try { + b.flip(-1) + fail() + } catch(e: IndexOutOfBoundsException) {} + try { + b.flip(-1..0) + fail() + } catch(e: IndexOutOfBoundsException) {} +} + +fun testNextBit() { + val b = BitSet(71) + b.set(0) + b.set(65) + b.set(70) + assertEquals(b.nextSetBit(), 0) + assertEquals(b.nextSetBit(0), 0) + assertEquals(b.nextSetBit(1), 65) + assertEquals(b.nextSetBit(65), 65) + assertEquals(b.nextSetBit(66), 70) + assertEquals(b.nextSetBit(70), 70) + assertEquals(b.nextSetBit(71), -1) + + assertEquals(b.previousSetBit(0), 0) + assertEquals(b.previousSetBit(64), 0) + assertEquals(b.previousSetBit(65), 65) + assertEquals(b.previousSetBit(69), 65) + assertEquals(b.previousSetBit(70), 70) + assertEquals(b.previousSetBit(71), 70) + + b.clear() + assertEquals(b.nextSetBit(), -1) + assertEquals(b.previousSetBit(70), -1) + + b.set(0..70) + assertEquals(b.nextClearBit(), 71) + assertEquals(b.previousClearBit(70), -1) + + b.clear(0) + b.clear(65) + b.clear(70) + assertEquals(b.nextClearBit(), 0) + assertEquals(b.nextClearBit(0), 0) + assertEquals(b.nextClearBit(1), 65) + assertEquals(b.nextClearBit(65), 65) + assertEquals(b.nextClearBit(66), 70) + assertEquals(b.nextClearBit(70), 70) + assertEquals(b.nextClearBit(71), 71) // assume that the bitset is extended here (virtually). + + assertEquals(b.previousClearBit(0), 0) + assertEquals(b.previousClearBit(64), 0) + assertEquals(b.previousClearBit(65), 65) + assertEquals(b.previousClearBit(69), 65) + assertEquals(b.previousClearBit(70), 70) + assertEquals(b.previousClearBit(71), 71) + + // See http://docs.oracle.com/javase/8/docs/api/java/util/BitSet.html#previousClearBit-int- + assertEquals(b.previousClearBit(-1), -1) + assertEquals(b.previousSetBit(-1), -1) + + // Test behaviour on the right border of the bit vector. + // We assume that the vector is infinite and have zeros after (size - 1)th bit. + var a = BitSet(64) + assertEquals(a.nextClearBit(63), 63) + assertEquals(a.nextClearBit(64), 64) + assertEquals(a.nextSetBit(63), -1) + assertEquals(a.nextSetBit(64), -1) + a.set(0, 64) + assertEquals(a.nextClearBit(63), 64) + assertEquals(a.nextClearBit(64), 64) + assertEquals(a.nextSetBit(63), 63) + assertEquals(a.nextSetBit(64), -1) + + a.clear() + assertEquals(a.previousClearBit(63), 63) + assertEquals(a.previousClearBit(64), 64) + assertEquals(a.previousSetBit(63), -1) + assertEquals(a.previousSetBit(64), -1) + a.set(0, 64) + assertEquals(a.previousClearBit(63), -1) + assertEquals(a.previousClearBit(64), 64) + assertEquals(a.previousSetBit(63), 63) + assertEquals(a.previousSetBit(64), 63) + + a = BitSet(0) + assertEquals(a.nextSetBit(0), -1) + assertEquals(a.nextClearBit(0), 0) + assertEquals(a.previousSetBit(0), -1) + assertEquals(a.previousClearBit(0), 0) + + // Access to a negative element must cause an exception. + try { + b.previousSetBit(-2) + fail() + } catch(e: IndexOutOfBoundsException) {} + try { + b.previousClearBit(-2) + fail() + } catch(e: IndexOutOfBoundsException) {} + try { + b.nextSetBit(-1) + fail() + } catch(e: IndexOutOfBoundsException) {} + try { + b.nextClearBit(-1) + fail() + } catch(e: IndexOutOfBoundsException) {} +} + +fun BitSet.setBits(vararg indices: Int, value: Boolean = true) { + indices.forEach { + set(it, value) + } +} + +fun testLogic() { + var b2 = BitSet(76) + b2.setBits(1, 3, + 61, 63, + 65, 67, + 70, 72) + + // and + var b1 = BitSet(73) + b1.set(2..3); b1.set(62..63); b1.set(66..67); b1.set(71..72) + b1.and(b2) + assertContainsOnly(b1, setOf(3, 63, 67, 72), 76) + b1 = BitSet(73) + b1.set(2..3); b1.set(62..63); b1.set(66..67); b1.set(71..72) + b1.set(128) + b1.and(b2) + assertContainsOnly(b1, setOf(3, 63, 67, 72), 129) + + // or + b1 = BitSet(73) + b1.set(2..3); b1.set(62..63); b1.set(66..67); b1.set(71..72) + b1.or(b2) + assertContainsOnly(b1, setOf(1, 2, 3, 61, 62, 63, 65, 66, 67, 70, 71, 72), 76) + + b1 = BitSet(73) + b1.set(2..3); b1.set(62..63); b1.set(66..67); b1.set(71..72) + b1.set(128) + b1.or(b2) + assertContainsOnly(b1, setOf(1, 2, 3, 61, 62, 63, 65, 66, 67, 70, 71, 72, 128), 129) + + // xor + b1 = BitSet(73) + b1.set(2..3); b1.set(62..63); b1.set(66..67); b1.set(71..72) + b1.xor(b2) + assertContainsOnly(b1, setOf(1, 2, 61, 62, 65, 66, 70, 71), 76) + + b1 = BitSet(73) + b1.set(2..3); b1.set(62..63); b1.set(66..67); b1.set(71..72) + b1.set(128) + b1.xor(b2) + assertContainsOnly(b1, setOf(1, 2, 61, 62, 65, 66, 70, 71, 128), 129) + + // andNot + b1 = BitSet(73) + b1.set(2..3); b1.set(62..63); b1.set(66..67); b1.set(71..72) + b1.andNot(b2) + assertContainsOnly(b1, setOf(2, 62, 66, 71), 76) + + b1 = BitSet(73) + b1.set(2..3); b1.set(62..63); b1.set(66..67); b1.set(71..72) + b1.set(128) + b1.andNot(b2) + assertContainsOnly(b1, setOf(2, 62, 66, 71, 128), 129) + + // intersects + b1 = BitSet(73) + b1.set(0..1); b1.set(62..63); b1.set(64..65); b1.set(71..72) + b2.clear(); b2.set(0) + assertTrue(b1.intersects(b2)) + b2.clear(); b2.set(62..65) + assertTrue(b1.intersects(b2)) + b2.clear(); b2.set(72) + assertTrue(b1.intersects(b2)) + b2.clear() + assertFalse(b1.intersects(b2)) + b2.set(128) + assertFalse(b1.intersects(b2)) +} + +// Based on Harmony tests. +fun testEqualsHashCode() { + // HashCode. + val b = BitSet() + b.set(0..7) + b.clear(2) + b.clear(6) + assertEquals("BitSet returns wrong hash value", 1129, b.hashCode()) + b.set(10) + b.clear(3) + assertEquals("BitSet returns wrong hash value", 97, b.hashCode()) + + // Equals. + val b1 = BitSet() + val b2 = BitSet() + b1.set(0..7) + b2.set(0..7) + + assertTrue("Same BitSet returned false", b1 == b1) + assertTrue("Identical BitSet returned false", b1 == b2) + b2.clear(6) + assertFalse("Different BitSets returned true", b1 == b2) + + val b3 = BitSet() + b3.set(0..7) + b3.set(128) + assertFalse("Different sized BitSet with higher bit set returned true", b1 == b3) + b3.clear(128) + assertTrue("Different sized BitSet with higher bits not set returned false", b1 == b3) +} + +@Test fun runTest() { + testConstructor() + testSet() + testFlip() + testNextBit() + testLogic() + testEqualsHashCode() +} \ No newline at end of file diff --git a/kotlin-native/backend.native/tests/runtime/collections/SortWith.kt b/kotlin-native/backend.native/tests/runtime/collections/SortWith.kt new file mode 100644 index 00000000000..3b819a6e54a --- /dev/null +++ b/kotlin-native/backend.native/tests/runtime/collections/SortWith.kt @@ -0,0 +1,112 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +package runtime.collections.SortWith + +import kotlin.test.* + +val correctIncreasing = Comparator { a, b -> // correct one. + when { + a > b -> 1 + a < b -> -1 + else -> 0 + } +} + +val correctDecreasing = Comparator { a, b -> // correct one. + when { + a < b -> 1 + a > b -> -1 + else -> 0 + } +} + +fun Array.assertSorted(cmp: Comparator, message: String = "") { + for (i in 1 until size) { + assertTrue(cmp.compare(this[i - 1], this[i]) <= 0, message) + } +} + +fun Array.assertSorted(message: String = "") { + for (i in 1 until size) { + assertTrue(this[i - 1] <= this[i], message) + } +} + +data class ComparatorInfo(val name: String, val comparator: Comparator, val isCorrect: Boolean) + +class MyComparable (val value: Int, val comparator: Comparator): Comparable { + override fun compareTo(other: MyComparable): Int = comparator.compare(value, other.value) +} + +// Assert that the array is sorted in terms of a comparator only for correct/partially correct cases +val comparators = listOf( + ComparatorInfo("Correct increasing", correctIncreasing , true), + ComparatorInfo("Correct decreasing", correctDecreasing , true), + ComparatorInfo("Incorrect increasing", Comparator { a ,b -> if (a > b) 1 else -1 }, false), + ComparatorInfo("Incorrect decreasing", Comparator { a ,b -> if (a < b) 1 else -1 }, false), + ComparatorInfo("Always 1", Comparator { a ,b -> 1 }, false), + ComparatorInfo("Always -1", Comparator { a ,b -> -1 }, false), + ComparatorInfo("Always 0", Comparator { a ,b -> 0 }, false) +) + +val arrays = listOf>( + arrayOf(), + arrayOf(1), + arrayOf(Int.MIN_VALUE, 0, Int.MAX_VALUE), + arrayOf(Int.MAX_VALUE, 0, Int.MIN_VALUE), + arrayOf(1, 2, 3), + arrayOf(-2, -1, 99, 1, 2), + arrayOf(90, 91, 0, 98, 99), + arrayOf(2, 1, 99, -1, 2), + arrayOf(99, 98, 0, 91, 90), + arrayOf(42, 42, 42), + arrayOf(99, 42, 0, 42, 50), + arrayOf( + 100000, 190001, 200002, 200003, 200004, 210005, 220006, 250007, 300008, 310009, 360010, 365011, + 380012, 390013, 390014, 399015, 400016, 400017, 400018, 400019, 400020, 400021, 400022, 400023, + 400024, 400025, 400026, 450027, 450028, 480029, 480030, 500031, 500032, 500033, 500034, 500035, + 500036, 500037, 500038, 500039, 500040, 500041, 500042, 500043, 500044, 500045, 500046, 500047, + 500048, 500049, 500050, 500051, 500052, 500053, 505054, 510055, 510056, 510057, 510058, 510059, + 510060, 510061, 510062, 510063, 410064, 410065, 511066, 511067, 520068, 520069, 420070, 520071, + 530072, 530073, 530074, 430075, 430076, 530077, 540078, 540079, 540080, 540081, 540082, 540083, + 540084, 490085, 540086, 540087, 542088, 544089, 546090, 550091, 550092, 550093, 550094, 590095, + 590096, 595097, 600098, 600099, 600100, 600101, 600102, 600103, 600104, 550105, 600106, 600107, + 600108, 600109, 600110, 610111, 610112, 610113, 620114, 620115, 620116, 620117, 620118, 620119, + 640120, 640121, 645122, 645123, 645124, 645125, 645126, 645127, 650128, 700129, 700130 + ) +) + + +@Test fun runTest() { + arrays.forEach { array -> + comparators.forEach { + // Test with custom comparator + val arrayUnderTest = array.copyOf() + arrayUnderTest.sortWith(it.comparator) + if (it.isCorrect) { + arrayUnderTest.assertSorted(it.comparator, """ + Assert sorted failed for comparator: "${it.name}" + Array: ${array.joinToString()} + Array after sorting: ${arrayUnderTest.joinToString()} + """.trimIndent()) + } + + // Test of a custom comparable + val comparableArrayUnderTest = Array(array.size) { i -> + MyComparable(array[i], it.comparator) + } + comparableArrayUnderTest.sort() + + if (it.isCorrect) { + comparableArrayUnderTest.assertSorted(""" + Assert sorted failed for Comparable: "${it.name}" + Array: ${array.joinToString()} + Array after sorting: ${comparableArrayUnderTest.joinToString()} + """.trimIndent()) + } + } + } +} diff --git a/kotlin-native/backend.native/tests/runtime/collections/array0.kt b/kotlin-native/backend.native/tests/runtime/collections/array0.kt new file mode 100644 index 00000000000..57665d74fa7 --- /dev/null +++ b/kotlin-native/backend.native/tests/runtime/collections/array0.kt @@ -0,0 +1,38 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +package runtime.collections.array0 + +import kotlin.test.* + +@Test fun runTest() { + // Create instances of all array types. + val byteArray = ByteArray(5) + println(byteArray.size.toString()) + + val charArray = CharArray(6) + println(charArray.size.toString()) + + val shortArray = ShortArray(7) + println(shortArray.size.toString()) + + val intArray = IntArray(8) + println(intArray.size.toString()) + + val longArray = LongArray(9) + println(longArray.size.toString()) + + val floatArray = FloatArray(10) + println(floatArray.size.toString()) + + val doubleArray = FloatArray(11) + println(doubleArray.size.toString()) + + val booleanArray = BooleanArray(12) + println(booleanArray.size.toString()) + + val stringArray = Array(13, { i -> ""}) + println(stringArray.size.toString()) +} \ No newline at end of file diff --git a/kotlin-native/backend.native/tests/runtime/collections/array1.kt b/kotlin-native/backend.native/tests/runtime/collections/array1.kt new file mode 100644 index 00000000000..75f2e72879c --- /dev/null +++ b/kotlin-native/backend.native/tests/runtime/collections/array1.kt @@ -0,0 +1,36 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +package runtime.collections.array1 + +import kotlin.test.* + +@Test fun runTest() { + val byteArray = ByteArray(5) + byteArray[1] = 2 + byteArray[3] = 4 + println(byteArray[3].toString() + " " + byteArray[1].toString()) + + val shortArray = ShortArray(2) + shortArray[0] = -1 + shortArray[1] = 1 + print(shortArray[1].toString()) + print(shortArray[0].toString()) + println() + + val intArray = IntArray(7) + intArray[1] = 9 + intArray[3] = 6 + print(intArray[3].toString()) + print(intArray[1].toString()) + println() + + val longArray = LongArray(9) + longArray[8] = 8 + longArray[3] = 3 + print(longArray[3].toString()) + print(longArray[8].toString()) + println() +} \ No newline at end of file diff --git a/kotlin-native/backend.native/tests/runtime/collections/array2.kt b/kotlin-native/backend.native/tests/runtime/collections/array2.kt new file mode 100644 index 00000000000..a36f3114cf5 --- /dev/null +++ b/kotlin-native/backend.native/tests/runtime/collections/array2.kt @@ -0,0 +1,16 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +package runtime.collections.array2 + +import kotlin.test.* + +@Test fun runTest() { + val byteArray = Array(5, { i -> (i * 2).toByte() }) + byteArray.map { println(it) } + + val intArray = Array(5, { i -> i * 4 }) + println(intArray.sum()) +} \ No newline at end of file diff --git a/kotlin-native/backend.native/tests/runtime/collections/array3.kt b/kotlin-native/backend.native/tests/runtime/collections/array3.kt new file mode 100644 index 00000000000..4ca65147ef7 --- /dev/null +++ b/kotlin-native/backend.native/tests/runtime/collections/array3.kt @@ -0,0 +1,22 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +package runtime.collections.array3 + +import kotlin.test.* + +import kotlin.native.* + +@Test fun runTest() { + val data = immutableBlobOf(0x1, 0x2, 0x3, 0x7, 0x8, 0x9, 0x80, 0xff) + for (b in data) { + print("$b ") + } + println() + + val dataClone = data.toByteArray() + dataClone.map { print("$it ") } + println() +} \ No newline at end of file diff --git a/kotlin-native/backend.native/tests/runtime/collections/array4.kt b/kotlin-native/backend.native/tests/runtime/collections/array4.kt new file mode 100644 index 00000000000..2ce60f89e89 --- /dev/null +++ b/kotlin-native/backend.native/tests/runtime/collections/array4.kt @@ -0,0 +1,64 @@ +/* + * Copyright 2010-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +package runtime.collections.array4 + +import kotlin.test.* + +@Test fun runTest() { + assertFailsWith { + val a = Array(-2) { "nope" } + println(a) + } + assertFailsWith { + val a = ByteArray(-2) + println(a) + } + assertFailsWith { + val a = UByteArray(-2) + println(a) + } + assertFailsWith { + val a = ShortArray(-2) + println(a) + } + assertFailsWith { + val a = UShortArray(-2) + println(a) + } + assertFailsWith { + val a = IntArray(-2) + println(a) + } + assertFailsWith { + val a = UIntArray(-2) + println(a) + } + assertFailsWith { + val a = LongArray(-2) + println(a) + } + assertFailsWith { + val a = ULongArray(-2) + println(a) + } + assertFailsWith { + val a = FloatArray(-2) + println(a) + } + assertFailsWith { + val a = DoubleArray(-2) + println(a) + } + assertFailsWith { + val a = BooleanArray(-2) + println(a) + } + assertFailsWith { + val a = CharArray(-2) + println(a) + } + println("OK") +} \ No newline at end of file diff --git a/kotlin-native/backend.native/tests/runtime/collections/array5.kt b/kotlin-native/backend.native/tests/runtime/collections/array5.kt new file mode 100644 index 00000000000..8cc1b18fab1 --- /dev/null +++ b/kotlin-native/backend.native/tests/runtime/collections/array5.kt @@ -0,0 +1,969 @@ +/* + * Copyright 2010-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +package runtime.collections.array5 + +import kotlin.test.* +import kotlinx.cinterop.* + +@Test fun arrayGet() { + val arr = Array(10) { 0 } + assertEquals(0, arr[0]) + assertEquals(0, arr[9]) + assertFailsWith { + arr[10] + } + assertFailsWith { + arr[-1] + } + assertFailsWith { + arr[Int.MAX_VALUE] + } + assertFailsWith { + arr[Int.MIN_VALUE] + } +} + +@Test fun arraySet() { + val arr = Array(10) { 0 } + arr[0] = 1 + arr[9] = 1 + assertFailsWith { + arr[10] = 1 + } + assertFailsWith { + arr[-1] = 1 + } + assertFailsWith { + arr[Int.MAX_VALUE] = 1 + } + assertFailsWith { + arr[Int.MIN_VALUE] = 1 + } +} + +@Test fun byteArrayGet() { + val arr = ByteArray(10) { 0 } + assertEquals(0, arr[0]) + assertEquals(0, arr[9]) + assertFailsWith { + arr[10] + } + assertFailsWith { + arr[-1] + } + assertFailsWith { + arr[Int.MAX_VALUE] + } + assertFailsWith { + arr[Int.MIN_VALUE] + } +} + +@Test fun byteArraySet() { + val arr = ByteArray(10) { 0 } + arr[0] = 1 + arr[9] = 1 + assertFailsWith { + arr[10] = 1 + } + assertFailsWith { + arr[-1] = 1 + } + assertFailsWith { + arr[Int.MAX_VALUE] = 1 + } + assertFailsWith { + arr[Int.MIN_VALUE] = 1 + } +} + +@Test fun uByteArrayGet() { + val arr = UByteArray(10) { 0U } + assertEquals(0U, arr[0]) + assertEquals(0U, arr[9]) + assertFailsWith { + arr[10] + } + assertFailsWith { + arr[-1] + } + assertFailsWith { + arr[Int.MAX_VALUE] + } + assertFailsWith { + arr[Int.MIN_VALUE] + } +} + +@Test fun uByteArraySet() { + val arr = UByteArray(10) { 0U } + arr[0] = 1U + arr[9] = 1U + assertFailsWith { + arr[10] = 1U + } + assertFailsWith { + arr[-1] = 1U + } + assertFailsWith { + arr[Int.MAX_VALUE] = 1U + } + assertFailsWith { + arr[Int.MIN_VALUE] = 1U + } +} + +@Test fun shortArrayGet() { + val arr = ShortArray(10) { 0 } + assertEquals(0, arr[0]) + assertEquals(0, arr[9]) + assertFailsWith { + arr[10] + } + assertFailsWith { + arr[-1] + } + assertFailsWith { + arr[Int.MAX_VALUE] + } + assertFailsWith { + arr[Int.MIN_VALUE] + } +} + +@Test fun shortArraySet() { + val arr = ShortArray(10) { 0 } + arr[0] = 1 + arr[9] = 1 + assertFailsWith { + arr[10] = 1 + } + assertFailsWith { + arr[-1] = 1 + } + assertFailsWith { + arr[Int.MAX_VALUE] = 1 + } + assertFailsWith { + arr[Int.MIN_VALUE] = 1 + } +} + +@Test fun uShortArrayGet() { + val arr = UShortArray(10) { 0U } + assertEquals(0U, arr[0]) + assertEquals(0U, arr[9]) + assertFailsWith { + arr[10] + } + assertFailsWith { + arr[-1] + } + assertFailsWith { + arr[Int.MAX_VALUE] + } + assertFailsWith { + arr[Int.MIN_VALUE] + } +} + +@Test fun uShortArraySet() { + val arr = UShortArray(10) { 0U } + arr[0] = 1U + arr[9] = 1U + assertFailsWith { + arr[10] = 1U + } + assertFailsWith { + arr[-1] = 1U + } + assertFailsWith { + arr[Int.MAX_VALUE] = 1U + } + assertFailsWith { + arr[Int.MIN_VALUE] = 1U + } +} + +@Test fun intArrayGet() { + val arr = IntArray(10) { 0 } + assertEquals(0, arr[0]) + assertEquals(0, arr[9]) + assertFailsWith { + arr[10] + } + assertFailsWith { + arr[-1] + } + assertFailsWith { + arr[Int.MAX_VALUE] + } + assertFailsWith { + arr[Int.MIN_VALUE] + } +} + +@Test fun intArraySet() { + val arr = IntArray(10) { 0 } + arr[0] = 1 + arr[9] = 1 + assertFailsWith { + arr[10] = 1 + } + assertFailsWith { + arr[-1] = 1 + } + assertFailsWith { + arr[Int.MAX_VALUE] = 1 + } + assertFailsWith { + arr[Int.MIN_VALUE] = 1 + } +} + +@Test fun uIntArrayGet() { + val arr = UIntArray(10) { 0U } + assertEquals(0U, arr[0]) + assertEquals(0U, arr[9]) + assertFailsWith { + arr[10] + } + assertFailsWith { + arr[-1] + } + assertFailsWith { + arr[Int.MAX_VALUE] + } + assertFailsWith { + arr[Int.MIN_VALUE] + } +} + +@Test fun uIntArraySet() { + val arr = UIntArray(10) { 0U } + arr[0] = 1U + arr[9] = 1U + assertFailsWith { + arr[10] = 1U + } + assertFailsWith { + arr[-1] = 1U + } + assertFailsWith { + arr[Int.MAX_VALUE] = 1U + } + assertFailsWith { + arr[Int.MIN_VALUE] = 1U + } +} + +@Test fun longArrayGet() { + val arr = LongArray(10) { 0 } + assertEquals(0, arr[0]) + assertEquals(0, arr[9]) + assertFailsWith { + arr[10] + } + assertFailsWith { + arr[-1] + } + assertFailsWith { + arr[Int.MAX_VALUE] + } + assertFailsWith { + arr[Int.MIN_VALUE] + } +} + +@Test fun longArraySet() { + val arr = LongArray(10) { 0 } + arr[0] = 1 + arr[9] = 1 + assertFailsWith { + arr[10] = 1 + } + assertFailsWith { + arr[-1] = 1 + } + assertFailsWith { + arr[Int.MAX_VALUE] = 1 + } + assertFailsWith { + arr[Int.MIN_VALUE] = 1 + } +} + +@Test fun uLongArrayGet() { + val arr = ULongArray(10) { 0U } + assertEquals(0U, arr[0]) + assertEquals(0U, arr[9]) + assertFailsWith { + arr[10] + } + assertFailsWith { + arr[-1] + } + assertFailsWith { + arr[Int.MAX_VALUE] + } + assertFailsWith { + arr[Int.MIN_VALUE] + } +} + +@Test fun uLongArraySet() { + val arr = ULongArray(10) { 0U } + arr[0] = 1U + arr[9] = 1U + assertFailsWith { + arr[10] = 1U + } + assertFailsWith { + arr[-1] = 1U + } + assertFailsWith { + arr[Int.MAX_VALUE] = 1U + } + assertFailsWith { + arr[Int.MIN_VALUE] = 1U + } +} + +@Test fun floatArrayGet() { + val arr = FloatArray(10) { 0.0f } + assertEquals(0.0f, arr[0]) + assertEquals(0.0f, arr[9]) + assertFailsWith { + arr[10] + } + assertFailsWith { + arr[-1] + } + assertFailsWith { + arr[Int.MAX_VALUE] + } + assertFailsWith { + arr[Int.MIN_VALUE] + } +} + +@Test fun floatArraySet() { + val arr = FloatArray(10) { 0.0f } + arr[0] = 1.0f + arr[9] = 1.0f + assertFailsWith { + arr[10] = 1.0f + } + assertFailsWith { + arr[-1] = 1.0f + } + assertFailsWith { + arr[Int.MAX_VALUE] = 1.0f + } + assertFailsWith { + arr[Int.MIN_VALUE] = 1.0f + } +} + +@Test fun doubleArrayGet() { + val arr = DoubleArray(10) { 0.0 } + assertEquals(0.0, arr[0]) + assertEquals(0.0, arr[9]) + assertFailsWith { + arr[10] + } + assertFailsWith { + arr[-1] + } + assertFailsWith { + arr[Int.MAX_VALUE] + } + assertFailsWith { + arr[Int.MIN_VALUE] + } +} + +@Test fun doubleArraySet() { + val arr = DoubleArray(10) { 0.0 } + arr[0] = 1.0 + arr[9] = 1.0 + assertFailsWith { + arr[10] = 1.0 + } + assertFailsWith { + arr[-1] = 1.0 + } + assertFailsWith { + arr[Int.MAX_VALUE] = 1.0 + } + assertFailsWith { + arr[Int.MIN_VALUE] = 1.0 + } +} + +@Test fun booleanArrayGet() { + val arr = BooleanArray(10) { false } + assertEquals(false, arr[0]) + assertEquals(false, arr[9]) + assertFailsWith { + arr[10] + } + assertFailsWith { + arr[-1] + } + assertFailsWith { + arr[Int.MAX_VALUE] + } + assertFailsWith { + arr[Int.MIN_VALUE] + } +} + +@Test fun booleanArraySet() { + val arr = BooleanArray(10) { false } + arr[0] = true + arr[9] = true + assertFailsWith { + arr[10] = true + } + assertFailsWith { + arr[-1] = true + } + assertFailsWith { + arr[Int.MAX_VALUE] = true + } + assertFailsWith { + arr[Int.MIN_VALUE] = true + } +} + +@Test fun charArrayGet() { + val arr = CharArray(10) { '0' } + assertEquals('0', arr[0]) + assertEquals('0', arr[9]) + assertFailsWith { + arr[10] + } + assertFailsWith { + arr[-1] + } + assertFailsWith { + arr[Int.MAX_VALUE] + } + assertFailsWith { + arr[Int.MIN_VALUE] + } +} + +@Test fun charArraySet() { + val arr = CharArray(10) { '0' } + arr[0] = '1' + arr[9] = '1' + assertFailsWith { + arr[10] = '1' + } + assertFailsWith { + arr[-1] = '1' + } + assertFailsWith { + arr[Int.MAX_VALUE] = '1' + } + assertFailsWith { + arr[Int.MIN_VALUE] = '1' + } +} + +@Test fun byteArrayGetUByte() { + val arr = ByteArray(10) { 0 } + assertEquals(0U, arr.getUByteAt(0)) + assertEquals(0U, arr.getUByteAt(9)) + assertFailsWith { + arr.getUByteAt(10) + } + assertFailsWith { + arr.getUByteAt(-1) + } + assertFailsWith { + arr.getUByteAt(Int.MAX_VALUE) + } + assertFailsWith { + arr.getUByteAt(Int.MIN_VALUE) + } +} + +@Test fun byteArraySetUByte() { + val arr = ByteArray(10) { 0 } + arr.setUByteAt(0, 1U) + arr.setUByteAt(9, 1U) + assertFailsWith { + arr.setUByteAt(10, 1U) + } + assertFailsWith { + arr.setUByteAt(-1, 1U) + } + assertFailsWith { + arr.setUByteAt(Int.MAX_VALUE, 1U) + } + assertFailsWith { + arr.setUByteAt(Int.MIN_VALUE, 1U) + } +} + +@Test fun byteArrayGetChar() { + val arr = ByteArray(10) { 0 } + assertEquals(0.toChar(), arr.getCharAt(0)) + assertEquals(0.toChar(), arr.getCharAt(8)) + assertFailsWith { + arr.getCharAt(9) + } + assertFailsWith { + arr.getCharAt(10) + } + assertFailsWith { + arr.getCharAt(-1) + } + assertFailsWith { + arr.getCharAt(Int.MAX_VALUE) + } + assertFailsWith { + arr.getCharAt(Int.MIN_VALUE) + } +} + +@Test fun byteArraySetChar() { + val arr = ByteArray(10) { 0 } + arr.setCharAt(0, '1') + arr.setCharAt(8, '1') + assertFailsWith { + arr.setCharAt(9, '1') + } + assertFailsWith { + arr.setCharAt(10, '1') + } + assertFailsWith { + arr.setCharAt(-1, '1') + } + assertFailsWith { + arr.setCharAt(Int.MAX_VALUE, '1') + } + assertFailsWith { + arr.setCharAt(Int.MIN_VALUE, '1') + } +} + +@Test fun byteArrayGetShort() { + val arr = ByteArray(10) { 0 } + assertEquals(0, arr.getShortAt(0)) + assertEquals(0, arr.getShortAt(8)) + assertFailsWith { + arr.getShortAt(9) + } + assertFailsWith { + arr.getShortAt(10) + } + assertFailsWith { + arr.getShortAt(-1) + } + assertFailsWith { + arr.getShortAt(Int.MAX_VALUE) + } + assertFailsWith { + arr.getShortAt(Int.MIN_VALUE) + } +} + +@Test fun byteArraySetShort() { + val arr = ByteArray(10) { 0 } + arr.setShortAt(0, 0) + arr.setShortAt(8, 0) + assertFailsWith { + arr.setShortAt(9, 1) + } + assertFailsWith { + arr.setShortAt(10, 1) + } + assertFailsWith { + arr.setShortAt(-1, 1) + } + assertFailsWith { + arr.setShortAt(Int.MAX_VALUE, 1) + } + assertFailsWith { + arr.setShortAt(Int.MIN_VALUE, 1) + } +} + +@Test fun byteArrayGetUShort() { + val arr = ByteArray(10) { 0 } + assertEquals(0U, arr.getUShortAt(0)) + assertEquals(0U, arr.getUShortAt(8)) + assertFailsWith { + arr.getUShortAt(9) + } + assertFailsWith { + arr.getUShortAt(10) + } + assertFailsWith { + arr.getUShortAt(-1) + } + assertFailsWith { + arr.getUShortAt(Int.MAX_VALUE) + } + assertFailsWith { + arr.getUShortAt(Int.MIN_VALUE) + } +} + +@Test fun byteArraySetUShort() { + val arr = ByteArray(10) { 0 } + arr.setUShortAt(0, 0U) + arr.setUShortAt(8, 0U) + assertFailsWith { + arr.setUShortAt(9, 1U) + } + assertFailsWith { + arr.setUShortAt(10, 1U) + } + assertFailsWith { + arr.setUShortAt(-1, 1U) + } + assertFailsWith { + arr.setUShortAt(Int.MAX_VALUE, 1U) + } + assertFailsWith { + arr.setUShortAt(Int.MIN_VALUE, 1U) + } +} + +@Test fun byteArrayGetInt() { + val arr = ByteArray(10) { 0 } + assertEquals(0, arr.getIntAt(0)) + assertEquals(0, arr.getIntAt(6)) + assertFailsWith { + arr.getIntAt(7) + } + assertFailsWith { + arr.getIntAt(10) + } + assertFailsWith { + arr.getIntAt(-1) + } + assertFailsWith { + arr.getIntAt(Int.MAX_VALUE) + } + assertFailsWith { + arr.getIntAt(Int.MIN_VALUE) + } +} + +@Test fun byteArraySetInt() { + val arr = ByteArray(10) { 0 } + arr.setIntAt(0, 1) + arr.setIntAt(6, 1) + assertFailsWith { + arr.setIntAt(7, 1) + } + assertFailsWith { + arr.setIntAt(10, 1) + } + assertFailsWith { + arr.setIntAt(-1, 1) + } + assertFailsWith { + arr.setIntAt(Int.MAX_VALUE, 1) + } + assertFailsWith { + arr.setIntAt(Int.MIN_VALUE, 1) + } +} + +@Test fun byteArrayGetUInt() { + val arr = ByteArray(10) { 0 } + assertEquals(0U, arr.getUIntAt(0)) + assertEquals(0U, arr.getUIntAt(6)) + assertFailsWith { + arr.getUIntAt(7) + } + assertFailsWith { + arr.getUIntAt(10) + } + assertFailsWith { + arr.getUIntAt(-1) + } + assertFailsWith { + arr.getUIntAt(Int.MAX_VALUE) + } + assertFailsWith { + arr.getUIntAt(Int.MIN_VALUE) + } +} + +@Test fun byteArraySetUInt() { + val arr = ByteArray(10) { 0 } + arr.setUIntAt(0, 1U) + arr.setUIntAt(6, 1U) + assertFailsWith { + arr.setUIntAt(7, 1U) + } + assertFailsWith { + arr.setUIntAt(10, 1U) + } + assertFailsWith { + arr.setUIntAt(-1, 1U) + } + assertFailsWith { + arr.setUIntAt(Int.MAX_VALUE, 1U) + } + assertFailsWith { + arr.setUIntAt(Int.MIN_VALUE, 1U) + } +} + +@Test fun byteArrayGetLong() { + val arr = ByteArray(10) { 0 } + assertEquals(0, arr.getLongAt(0)) + assertEquals(0, arr.getLongAt(2)) + assertFailsWith { + arr.getLongAt(3) + } + assertFailsWith { + arr.getLongAt(10) + } + assertFailsWith { + arr.getLongAt(-1) + } + assertFailsWith { + arr.getLongAt(Int.MAX_VALUE) + } + assertFailsWith { + arr.getLongAt(Int.MIN_VALUE) + } +} + +@Test fun byteArraySetLong() { + val arr = ByteArray(10) { 0 } + arr.setLongAt(0, 1) + arr.setLongAt(2, 1) + assertFailsWith { + arr.setLongAt(3, 1) + } + assertFailsWith { + arr.setLongAt(10, 1) + } + assertFailsWith { + arr.setLongAt(-1, 1) + } + assertFailsWith { + arr.setLongAt(Int.MAX_VALUE, 1) + } + assertFailsWith { + arr.setLongAt(Int.MIN_VALUE, 1) + } +} + +@Test fun byteArrayGetULong() { + val arr = ByteArray(10) { 0 } + assertEquals(0U, arr.getULongAt(0)) + assertEquals(0U, arr.getULongAt(2)) + assertFailsWith { + arr.getULongAt(3) + } + assertFailsWith { + arr.getULongAt(10) + } + assertFailsWith { + arr.getULongAt(-1) + } + assertFailsWith { + arr.getULongAt(Int.MAX_VALUE) + } + assertFailsWith { + arr.getULongAt(Int.MIN_VALUE) + } +} + +@Test fun byteArraySetULong() { + val arr = ByteArray(10) { 0 } + arr.setULongAt(0, 1U) + arr.setULongAt(2, 1U) + assertFailsWith { + arr.setULongAt(3, 1U) + } + assertFailsWith { + arr.setULongAt(10, 1U) + } + assertFailsWith { + arr.setULongAt(-1, 1U) + } + assertFailsWith { + arr.setULongAt(Int.MAX_VALUE, 1U) + } + assertFailsWith { + arr.setULongAt(Int.MIN_VALUE, 1U) + } +} + +@Test fun byteArrayGetFloat() { + val arr = ByteArray(10) { 0 } + assertEquals(0.0f, arr.getFloatAt(0)) + assertEquals(0.0f, arr.getFloatAt(6)) + assertFailsWith { + arr.getFloatAt(7) + } + assertFailsWith { + arr.getFloatAt(10) + } + assertFailsWith { + arr.getFloatAt(-1) + } + assertFailsWith { + arr.getFloatAt(Int.MAX_VALUE) + } + assertFailsWith { + arr.getFloatAt(Int.MIN_VALUE) + } +} + +@Test fun byteArraySetFloat() { + val arr = ByteArray(10) { 0 } + arr.setFloatAt(0, 1.0f) + arr.setFloatAt(6, 1.0f) + assertFailsWith { + arr.setFloatAt(7, 1.0f) + } + assertFailsWith { + arr.setFloatAt(10, 1.0f) + } + assertFailsWith { + arr.setFloatAt(-1, 1.0f) + } + assertFailsWith { + arr.setFloatAt(Int.MAX_VALUE, 1.0f) + } + assertFailsWith { + arr.setFloatAt(Int.MIN_VALUE, 1.0f) + } +} + +@Test fun byteArrayGetDouble() { + val arr = ByteArray(10) { 0 } + assertEquals(0.0, arr.getDoubleAt(0)) + assertEquals(0.0, arr.getDoubleAt(2)) + assertFailsWith { + arr.getDoubleAt(3) + } + assertFailsWith { + arr.getDoubleAt(10) + } + assertFailsWith { + arr.getDoubleAt(-1) + } + assertFailsWith { + arr.getDoubleAt(Int.MAX_VALUE) + } + assertFailsWith { + arr.getDoubleAt(Int.MIN_VALUE) + } +} + +@Test fun byteArraySetDouble() { + val arr = ByteArray(10) { 0 } + arr.setDoubleAt(0, 1.0) + arr.setDoubleAt(2, 1.0) + assertFailsWith { + arr.setDoubleAt(3, 1.0) + } + assertFailsWith { + arr.setDoubleAt(10, 1.0) + } + assertFailsWith { + arr.setDoubleAt(-1, 1.0) + } + assertFailsWith { + arr.setDoubleAt(Int.MAX_VALUE, 1.0) + } + assertFailsWith { + arr.setDoubleAt(Int.MIN_VALUE, 1.0) + } +} + +@Test fun immutableBlobToByteArray() { + val blob = immutableBlobOf(0, 0) + val arr = blob.toByteArray(0, 1) + assertEquals(1, arr.size) + assertEquals(0, arr[0]) + assertFailsWith { + blob.toByteArray(-1, 1) + } + assertFailsWith { + blob.toByteArray(0, -1) + } + assertFailsWith { + blob.toByteArray(0, 10) + } + assertFailsWith { + blob.toByteArray(10, 11) + } + assertFailsWith { + blob.toByteArray(10, 1) + } +} + +@Test fun immutableBlobToUByteArray() { + val blob = immutableBlobOf(0, 0) + val arr = blob.toUByteArray(0, 1) + assertEquals(1, arr.size) + assertEquals(0U, arr[0]) + assertFailsWith { + blob.toUByteArray(-1, 1) + } + assertFailsWith { + blob.toUByteArray(0, -1) + } + assertFailsWith { + blob.toUByteArray(0, 10) + } + assertFailsWith { + blob.toUByteArray(10, 11) + } + assertFailsWith { + blob.toUByteArray(10, 1) + } +} + +@Test fun immutableBlobAsCPointer() { + val blob = immutableBlobOf(0, 0) + assertEquals(0, blob.asCPointer(0).pointed.value) + assertFailsWith { + blob.asCPointer(10) + } + assertFailsWith { + blob.asCPointer(-1) + } + assertFailsWith { + blob.asCPointer(Int.MAX_VALUE) + } + assertFailsWith { + blob.asCPointer(Int.MIN_VALUE) + } +} + +@Test fun immutableBlobAsUCPointer() { + val blob = immutableBlobOf(0, 0) + assertEquals(0U, blob.asUCPointer(0).pointed.value) + assertFailsWith { + blob.asUCPointer(10) + } + assertFailsWith { + blob.asUCPointer(-1) + } + assertFailsWith { + blob.asUCPointer(Int.MAX_VALUE) + } + assertFailsWith { + blob.asUCPointer(Int.MIN_VALUE) + } +} diff --git a/kotlin-native/backend.native/tests/runtime/collections/array_list1.kt b/kotlin-native/backend.native/tests/runtime/collections/array_list1.kt new file mode 100644 index 00000000000..73e7fdbb054 --- /dev/null +++ b/kotlin-native/backend.native/tests/runtime/collections/array_list1.kt @@ -0,0 +1,385 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +package runtime.collections.array_list1 + +import kotlin.test.* + +fun assertTrue(cond: Boolean) { + if (!cond) + println("FAIL") +} + +fun assertFalse(cond: Boolean) { + if (cond) + println("FAIL") +} + +fun assertEquals(value1: Any?, value2: Any?) { + if (value1 != value2) + throw Error("FAIL " + value1 + " " + value2) +} + +fun assertEquals(value1: Int, value2: Int) { + if (value1 != value2) + throw Error("FAIL " + value1 + " " + value2) +} + +fun testBasic() { + val a = ArrayList() + assertTrue(a.isEmpty()) + assertEquals(0, a.size) + + assertTrue(a.add("1")) + assertTrue(a.add("2")) + assertTrue(a.add("3")) + assertFalse(a.isEmpty()) + assertEquals(3, a.size) + assertEquals("1", a[0]) + assertEquals("2", a[1]) + assertEquals("3", a[2]) + + a[0] = "11" + assertEquals("11", a[0]) + + assertEquals("11", a.removeAt(0)) + assertEquals(2, a.size) + assertEquals("2", a[0]) + assertEquals("3", a[1]) + + a.add(1, "22") + assertEquals(3, a.size) + assertEquals("2", a[0]) + assertEquals("22", a[1]) + assertEquals("3", a[2]) + + a.clear() + assertTrue(a.isEmpty()) + assertEquals(0, a.size) +} + +fun testIterator() { + val a = ArrayList(listOf("1", "2", "3")) + val it = a.iterator() + assertTrue(it.hasNext()) + assertEquals("1", it.next()) + assertTrue(it.hasNext()) + assertEquals("2", it.next()) + assertTrue(it.hasNext()) + assertEquals("3", it.next()) + assertFalse(it.hasNext()) +} + +fun testContainsAll() { + val a = ArrayList(listOf("1", "2", "3", "4", "5")) + assertFalse(a.containsAll(listOf("6", "7", "8"))) + assertFalse(a.containsAll(listOf("5", "6", "7"))) + assertFalse(a.containsAll(listOf("4", "5", "6"))) + assertTrue(a.containsAll(listOf("3", "4", "5"))) + assertTrue(a.containsAll(listOf("2", "3", "4"))) +} + +fun testRemove() { + val a = ArrayList(listOf("1", "2", "3")) + assertTrue(a.remove("2")) + assertEquals(2, a.size) + assertEquals("1", a[0]) + assertEquals("3", a[1]) + assertFalse(a.remove("2")) + assertEquals(2, a.size) + assertEquals("1", a[0]) + assertEquals("3", a[1]) +} + +fun testRemoveAll() { + val a = ArrayList(listOf("1", "2", "3", "4", "5", "1")) + assertFalse(a.removeAll(listOf("6", "7", "8"))) + assertEquals(listOf("1", "2", "3", "4", "5", "1"), a) + assertTrue(a.removeAll(listOf("5", "3", "1"))) + assertEquals(listOf("2", "4"), a) +} + +fun testRetainAll() { + val a = ArrayList(listOf("1", "2", "3", "4", "5")) + assertFalse(a.retainAll(listOf("1", "2", "3", "4", "5"))) + assertEquals(listOf("1", "2", "3", "4", "5"), a) + assertTrue(a.retainAll(listOf("5", "3", "1"))) + assertEquals(listOf("1", "3", "5"), a) +} + +fun testEquals() { + val a = ArrayList(listOf("1", "2", "3")) + assertTrue(a == listOf("1", "2", "3")) + assertFalse(a == listOf("2", "3", "1")) // order matters + assertFalse(a == listOf("1", "2", "4")) + assertFalse(a == listOf("1", "2")) +} + +fun testHashCode() { + val a = ArrayList(listOf("1", "2", "3")) + assertTrue(a.hashCode() == listOf("1", "2", "3").hashCode()) +} + +fun testToString() { + val a = ArrayList(listOf("1", "2", "3")) + assertTrue(a.toString() == listOf("1", "2", "3").toString()) +} + + +fun testSubList() { + val a0 = ArrayList(listOf("0", "1", "2", "3", "4")) + val a = a0.subList(1, 4) + assertEquals(3, a.size) + assertEquals("1", a[0]) + assertEquals("2", a[1]) + assertEquals("3", a[2]) + assertTrue(a == listOf("1", "2", "3")) + assertTrue(a.hashCode() == listOf("1", "2", "3").hashCode()) + assertTrue(a.toString() == listOf("1", "2", "3").toString()) +} + +fun testResize() { + val a = ArrayList() + val n = 10000 + for (i in 1..n) + assertTrue(a.add(i.toString())) + assertEquals(n, a.size) + for (i in 1..n) + assertEquals(i.toString(), a[i - 1]) + a.trimToSize() + assertEquals(n, a.size) + for (i in 1..n) + assertEquals(i.toString(), a[i - 1]) +} + +fun testSubListContains() { + val a = ArrayList(listOf("1", "2", "3", "4")) + val s = a.subList(1, 3) + assertTrue(a.contains("1")) + assertFalse(s.contains("1")) + assertTrue(a.contains("2")) + assertTrue(s.contains("2")) + assertTrue(a.contains("3")) + assertTrue(s.contains("3")) + assertTrue(a.contains("4")) + assertFalse(s.contains("4")) +} + +fun testSubListIndexOf() { + val a = ArrayList(listOf("1", "2", "3", "4", "1")) + val s = a.subList(1, 3) + assertEquals(0, a.indexOf("1")) + assertEquals(-1, s.indexOf("1")) + assertEquals(1, a.indexOf("2")) + assertEquals(0, s.indexOf("2")) + assertEquals(2, a.indexOf("3")) + assertEquals(1, s.indexOf("3")) + assertEquals(3, a.indexOf("4")) + assertEquals(-1, s.indexOf("4")) +} + +fun testSubListLastIndexOf() { + val a = ArrayList(listOf("1", "2", "3", "4", "1")) + val s = a.subList(1, 3) + assertEquals(4, a.lastIndexOf("1")) + assertEquals(-1, s.lastIndexOf("1")) + assertEquals(1, a.lastIndexOf("2")) + assertEquals(0, s.lastIndexOf("2")) + assertEquals(2, a.lastIndexOf("3")) + assertEquals(1, s.lastIndexOf("3")) + assertEquals(3, a.lastIndexOf("4")) + assertEquals(-1, s.lastIndexOf("4")) +} + +fun testSubListClear() { + val a = ArrayList(listOf("1", "2", "3", "4")) + val s = a.subList(1, 3) + assertEquals(listOf("2", "3"), s) + + s.clear() + assertEquals(listOf(), s) + assertEquals(listOf("1", "4"), a) +} + +fun testSubListSubListClear() { + val a = ArrayList(listOf("1", "2", "3", "4", "5", "6")) + val s = a.subList(1, 5) + val q = s.subList(1, 3) + assertEquals(listOf("2", "3", "4", "5"), s) + assertEquals(listOf("3", "4"), q) + + q.clear() + assertEquals(listOf(), q) + assertEquals(listOf("2", "5"), s) + assertEquals(listOf("1", "2", "5", "6"), a) +} + +fun testSubListAdd() { + val a = ArrayList(listOf("1", "2", "3", "4")) + val s = a.subList(1, 3) + assertEquals(listOf("2", "3"), s) + + assertTrue(s.add("5")) + assertEquals(listOf("2", "3", "5"), s) + assertEquals(listOf("1", "2", "3", "5", "4"), a) +} + +fun testSubListSubListAdd() { + val a = ArrayList(listOf("1", "2", "3", "4", "5", "6")) + val s = a.subList(1, 5) + val q = s.subList(1, 3) + assertEquals(listOf("2", "3", "4", "5"), s) + assertEquals(listOf("3", "4"), q) + + assertTrue(q.add("7")) + assertEquals(listOf("3", "4", "7"), q) + assertEquals(listOf("2", "3", "4", "7", "5"), s) + assertEquals(listOf("1", "2", "3", "4", "7", "5", "6"), a) +} + +fun testSubListAddAll() { + val a = ArrayList(listOf("1", "2", "3", "4")) + val s = a.subList(1, 3) + assertEquals(listOf("2", "3"), s) + + assertTrue(s.addAll(listOf("5", "6"))) + assertEquals(listOf("2", "3", "5", "6"), s) + assertEquals(listOf("1", "2", "3", "5", "6", "4"), a) +} + +fun testSubListSubListAddAll() { + val a = ArrayList(listOf("1", "2", "3", "4", "5", "6")) + val s = a.subList(1, 5) + val q = s.subList(1, 3) + assertEquals(listOf("2", "3", "4", "5"), s) + assertEquals(listOf("3", "4"), q) + + assertTrue(q.addAll(listOf("7", "8"))) + assertEquals(listOf("3", "4", "7", "8"), q) + assertEquals(listOf("2", "3", "4", "7", "8", "5"), s) + assertEquals(listOf("1", "2", "3", "4", "7", "8", "5", "6"), a) +} + +fun testSubListRemoveAt() { + val a = ArrayList(listOf("1", "2", "3", "4", "5")) + val s = a.subList(1, 4) + assertEquals(listOf("2", "3", "4"), s) + + assertEquals("3", s.removeAt(1)) + assertEquals(listOf("2", "4"), s) + assertEquals(listOf("1", "2", "4", "5"), a) +} + +fun testSubListSubListRemoveAt() { + val a = ArrayList(listOf("1", "2", "3", "4", "5", "6", "7")) + val s = a.subList(1, 6) + val q = s.subList(1, 4) + assertEquals(listOf("2", "3", "4", "5", "6"), s) + assertEquals(listOf("3", "4", "5"), q) + + assertEquals("4", q.removeAt(1)) + assertEquals(listOf("3", "5"), q) + assertEquals(listOf("2", "3", "5", "6"), s) + assertEquals(listOf("1", "2", "3", "5", "6", "7"), a) +} + +fun testSubListRemoveAll() { + val a = ArrayList(listOf("1", "2", "3", "3", "4", "5")) + val s = a.subList(1, 5) + assertEquals(listOf("2", "3", "3", "4"), s) + + assertTrue(s.removeAll(listOf("3", "5"))) + assertEquals(listOf("2", "4"), s) + assertEquals(listOf("1", "2", "4", "5"), a) +} + +fun testSubListSubListRemoveAll() { + val a = ArrayList(listOf("1", "2", "3", "4", "5", "6", "7")) + val s = a.subList(1, 6) + val q = s.subList(1, 4) + assertEquals(listOf("2", "3", "4", "5", "6"), s) + assertEquals(listOf("3", "4", "5"), q) + + assertTrue(q.removeAll(listOf("4", "6"))) + assertEquals(listOf("3", "5"), q) + assertEquals(listOf("2", "3", "5", "6"), s) + assertEquals(listOf("1", "2", "3", "5", "6", "7"), a) +} + +fun testSubListRetainAll() { + val a = ArrayList(listOf("1", "2", "3", "4", "5")) + val s = a.subList(1, 4) + assertEquals(listOf("2", "3", "4"), s) + + assertTrue(s.retainAll(listOf("5", "3"))) + assertEquals(listOf("3"), s) + assertEquals(listOf("1", "3", "5"), a) +} + +fun testSubListSubListRetainAll() { + val a = ArrayList(listOf("1", "2", "3", "4", "5", "6", "7")) + val s = a.subList(1, 6) + val q = s.subList(1, 4) + assertEquals(listOf("2", "3", "4", "5", "6"), s) + assertEquals(listOf("3", "4", "5"), q) + + assertTrue(q.retainAll(listOf("5", "3"))) + assertEquals(listOf("3", "5"), q) + assertEquals(listOf("2", "3", "5", "6"), s) + assertEquals(listOf("1", "2", "3", "5", "6", "7"), a) +} + +fun testIteratorRemove() { + val a = ArrayList(listOf("1", "2", "3", "4", "5")) + val it = a.iterator() + while (it.hasNext()) + if (it.next()[0].toInt() % 2 == 0) + it.remove() + assertEquals(listOf("1", "3", "5"), a) +} + +fun testIteratorAdd() { + val a = ArrayList(listOf("1", "2", "3", "4", "5")) + val it = a.listIterator() + while (it.hasNext()) { + val next = it.next() + if (next[0].toInt() % 2 == 0) + it.add("-" + next) + } + assertEquals(listOf("1", "2", "-2", "3", "4", "-4", "5"), a) +} + +@Test fun runTest() { + testBasic() + testIterator() + testRemove() + testRemoveAll() + testRetainAll() + testEquals() + testHashCode() + testToString() + testSubList() + testResize() + testSubListContains() + testSubListIndexOf() + testSubListLastIndexOf() + testSubListClear() + testSubListSubListClear() + testSubListAdd() + testSubListSubListAdd() + testSubListAddAll() + testSubListSubListAddAll() + testSubListRemoveAt() + testSubListSubListRemoveAt() + testSubListRemoveAll() + testSubListSubListRemoveAll() + testSubListSubListRemoveAll() + testSubListRetainAll() + testSubListSubListRetainAll() + testIteratorRemove() + testIteratorAdd() + + println("OK") +} \ No newline at end of file diff --git a/kotlin-native/backend.native/tests/runtime/collections/array_list2.kt b/kotlin-native/backend.native/tests/runtime/collections/array_list2.kt new file mode 100644 index 00000000000..afd880ef72e --- /dev/null +++ b/kotlin-native/backend.native/tests/runtime/collections/array_list2.kt @@ -0,0 +1,36 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +package runtime.collections.array_list2 + +import kotlin.test.* + +fun testIteratorNext() { + val a = arrayListOf("1", "2", "3", "4", "5") + val it = a.listIterator() + assertFailsWith { + while (true) { + it.next() + } + } +} + +fun testIteratorPrevious() { + val a = arrayListOf("1", "2", "3", "4", "5") + val it = a.listIterator() + it.next() + assertFailsWith { + while (true) { + it.previous() + } + } +} + +@Test fun runTest() { + testIteratorNext() + testIteratorPrevious() + + println("OK") +} \ No newline at end of file diff --git a/kotlin-native/backend.native/tests/runtime/collections/hash_map0.kt b/kotlin-native/backend.native/tests/runtime/collections/hash_map0.kt new file mode 100644 index 00000000000..d147ecd9485 --- /dev/null +++ b/kotlin-native/backend.native/tests/runtime/collections/hash_map0.kt @@ -0,0 +1,275 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +package runtime.collections.hash_map0 + +import kotlin.test.* + +fun assertTrue(cond: Boolean) { + if (!cond) + println("FAIL") +} + +fun assertFalse(cond: Boolean) { + if (cond) + println("FAIL") +} + +fun assertEquals(value1: Any?, value2: Any?) { + if (value1 != value2) + println("FAIL") +} + +fun assertNotEquals(value1: Any?, value2: Any?) { + if (value1 == value2) + println("FAIL") +} + +fun assertEquals(value1: Int, value2: Int) { + if (value1 != value2) + println("FAIL") +} + +fun testBasic() { + val m = HashMap() + assertTrue(m.isEmpty()) + assertEquals(0, m.size) + + assertFalse(m.containsKey("1")) + assertFalse(m.containsValue("a")) + assertEquals(null, m.get("1")) + + assertEquals(null, m.put("1", "a")) + assertTrue(m.containsKey("1")) + assertTrue(m.containsValue("a")) + assertEquals("a", m.get("1")) + assertFalse(m.isEmpty()) + assertEquals(1, m.size) + + assertFalse(m.containsKey("2")) + assertFalse(m.containsValue("b")) + assertEquals(null, m.get("2")) + + assertEquals(null, m.put("2", "b")) + assertTrue(m.containsKey("1")) + assertTrue(m.containsValue("a")) + assertEquals("a", m.get("1")) + assertTrue(m.containsKey("2")) + assertTrue(m.containsValue("b")) + assertEquals("b", m.get("2")) + assertFalse(m.isEmpty()) + assertEquals(2, m.size) + + assertEquals("b", m.put("2", "bb")) + assertTrue(m.containsKey("1")) + assertTrue(m.containsValue("a")) + assertEquals("a", m.get("1")) + assertTrue(m.containsKey("2")) + assertTrue(m.containsValue("a")) + assertTrue(m.containsValue("bb")) + assertEquals("bb", m.get("2")) + assertFalse(m.isEmpty()) + assertEquals(2, m.size) + + assertEquals("a", m.remove("1")) + assertFalse(m.containsKey("1")) + assertFalse(m.containsValue("a")) + assertEquals(null, m.get("1")) + assertTrue(m.containsKey("2")) + assertTrue(m.containsValue("bb")) + assertEquals("bb", m.get("2")) + assertFalse(m.isEmpty()) + assertEquals(1, m.size) + + assertEquals("bb", m.remove("2")) + assertFalse(m.containsKey("1")) + assertFalse(m.containsValue("a")) + assertEquals(null, m.get("1")) + assertFalse(m.containsKey("2")) + assertFalse(m.containsValue("bb")) + assertEquals(null, m.get("2")) + assertTrue(m.isEmpty()) + assertEquals(0, m.size) +} + +fun testRehashAndCompact() { + val m = HashMap() + for (repeat in 1..10) { + val n = when (repeat) { + 1 -> 1000 + 2 -> 10000 + 3 -> 10 + else -> 100000 + } + for (i in 1..n) { + assertFalse(m.containsKey(i.toString())) + assertEquals(null, m.put(i.toString(), "val$i")) + assertTrue(m.containsKey(i.toString())) + assertEquals(i, m.size) + } + for (i in 1..n) { + assertTrue(m.containsKey(i.toString())) + } + for (i in 1..n) { + assertEquals("val$i", m.remove(i.toString())) + assertFalse(m.containsKey(i.toString())) + assertEquals(n - i, m.size) + } + assertTrue(m.isEmpty()) + } +} + +fun testClear() { + val m = HashMap() + for (repeat in 1..10) { + val n = when (repeat) { + 1 -> 1000 + 2 -> 10000 + 3 -> 10 + else -> 100000 + } + for (i in 1..n) { + assertFalse(m.containsKey(i.toString())) + assertEquals(null, m.put(i.toString(), "val$i")) + assertTrue(m.containsKey(i.toString())) + assertEquals(i, m.size) + } + for (i in 1..n) { + assertTrue(m.containsKey(i.toString())) + } + m.clear() + assertEquals(0, m.size) + for (i in 1..n) { + assertFalse(m.containsKey(i.toString())) + } + } +} +fun testEquals() { + val expected = mapOf("a" to "1", "b" to "2", "c" to "3") + val m = HashMap(expected) + assertTrue(m == expected) + assertTrue(m == mapOf("b" to "2", "c" to "3", "a" to "1")) // order does not matter + assertFalse(m == mapOf("a" to "1", "b" to "2", "c" to "4")) + assertFalse(m == mapOf("a" to "1", "b" to "2", "c" to "5")) + assertFalse(m == mapOf("a" to "1", "b" to "2")) + assertEquals(m.keys, expected.keys) + assertEquals(m.values.toList(), expected.values.toList()) + assertEquals(m.entries, expected.entries) +} + +fun testHashCode() { + val expected = mapOf("a" to "1", "b" to "2", "c" to "3") + val m = HashMap(expected) + assertEquals(expected.hashCode(), m.hashCode()) + assertEquals(expected.entries.hashCode(), m.entries.hashCode()) + assertEquals(expected.keys.hashCode(), m.keys.hashCode()) +} + +fun testToString() { + val expected = mapOf("a" to "1", "b" to "2", "c" to "3") + val m = HashMap(expected) + assertEquals(expected.toString(), m.toString()) + assertEquals(expected.entries.toString(), m.entries.toString()) + assertEquals(expected.keys.toString(), m.keys.toString()) + assertEquals(expected.values.toString(), m.values.toString()) +} + +fun testPutEntry() { + val expected = mapOf("a" to "1", "b" to "2", "c" to "3") + val m = HashMap(expected) + val e = expected.entries.iterator().next() as MutableMap.MutableEntry + assertTrue(m.entries.contains(e)) + assertTrue(m.entries.remove(e)) + assertTrue(mapOf("b" to "2", "c" to "3") == m) + assertEquals(null, m.put(e.key, e.value)) + assertTrue(expected == m) + assertEquals(e.value, m.put(e.key, e.value)) + assertTrue(expected == m) +} + +fun testRemoveAllEntries() { + val expected = mapOf("a" to "1", "b" to "2", "c" to "3") + val m = HashMap(expected) + assertFalse(m.entries.removeAll(mapOf("a" to "2", "b" to "3", "c" to "4").entries)) + assertEquals(expected, m) + assertTrue(m.entries.removeAll(mapOf("b" to "22", "c" to "3", "d" to "4").entries)) + assertNotEquals(expected, m) + assertEquals(mapOf("a" to "1", "b" to "2"), m) +} + +fun testRetainAllEntries() { + val expected = mapOf("a" to "1", "b" to "2", "c" to "3") + val m = HashMap(expected) + assertFalse(m.entries.retainAll(expected.entries)) + assertEquals(expected, m) + assertTrue(m.entries.retainAll(mapOf("b" to "22", "c" to "3", "d" to "4").entries)) + assertEquals(mapOf("c" to "3"), m) +} + +fun testContainsAllValues() { + val m = HashMap(mapOf("a" to "1", "b" to "2", "c" to "3")) + assertTrue(m.values.containsAll(listOf("1", "2"))) + assertTrue(m.values.containsAll(listOf("1", "2", "3"))) + assertFalse(m.values.containsAll(listOf("1", "2", "3", "4"))) + assertFalse(m.values.containsAll(listOf("2", "3", "4"))) +} + +fun testRemoveValue() { + val expected = mapOf("a" to "1", "b" to "2", "c" to "3") + val m = HashMap(expected) + assertFalse(m.values.remove("b")) + assertEquals(expected, m) + assertTrue(m.values.remove("2")) + assertEquals(mapOf("a" to "1", "c" to "3"), m) +} + +fun testRemoveAllValues() { + val expected = mapOf("a" to "1", "b" to "2", "c" to "3") + val m = HashMap(expected) + assertFalse(m.values.removeAll(listOf("b", "c"))) + assertEquals(expected, m) + assertTrue(m.values.removeAll(listOf("b", "3"))) + assertEquals(mapOf("a" to "1", "b" to "2"), m) +} + +fun testRetainAllValues() { + val expected = mapOf("a" to "1", "b" to "2", "c" to "3") + val m = HashMap(expected) + assertFalse(m.values.retainAll(listOf("1", "2", "3"))) + assertEquals(expected, m) + assertTrue(m.values.retainAll(listOf("1", "2", "c"))) + assertEquals(mapOf("a" to "1", "b" to "2"), m) +} + +fun testEntriesIteratorSet() { + val expected = mapOf("a" to "1", "b" to "2", "c" to "3") + val m = HashMap(expected) + val it = m.iterator() + while (it.hasNext()) { + val entry = it.next() + entry.setValue(entry.value + "!") + } + assertNotEquals(expected, m) + assertEquals(mapOf("a" to "1!", "b" to "2!", "c" to "3!"), m) +} + +@Test fun runTest() { + testBasic() + testRehashAndCompact() + testClear() + testEquals() + testHashCode() + testToString() + testPutEntry() + testRemoveAllEntries() + testRetainAllEntries() + testContainsAllValues() + testRemoveValue() + testRemoveAllValues() + testRetainAllValues() + testEntriesIteratorSet() + //testDegenerateKeys() + println("OK") +} \ No newline at end of file diff --git a/kotlin-native/backend.native/tests/runtime/collections/hash_set0.kt b/kotlin-native/backend.native/tests/runtime/collections/hash_set0.kt new file mode 100644 index 00000000000..6a3709d9d19 --- /dev/null +++ b/kotlin-native/backend.native/tests/runtime/collections/hash_set0.kt @@ -0,0 +1,140 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +package runtime.collections.hash_set0 + +import kotlin.test.* + +fun assertTrue(cond: Boolean) { + if (!cond) + println("FAIL") +} + +fun assertFalse(cond: Boolean) { + if (cond) + println("FAIL") +} + +fun assertEquals(value1: Any?, value2: Any?) { + if (value1 != value2) + println("FAIL") +} + +fun assertEquals(value1: Int, value2: Int) { + if (value1 != value2) + println("FAIL") +} + +fun testBasic() { + val a = HashSet() + assertTrue(a.isEmpty()) + assertEquals(0, a.size) + + assertTrue(a.add("1")) + assertTrue(a.add("2")) + assertTrue(a.add("3")) + assertFalse(a.isEmpty()) + assertEquals(3, a.size) + assertTrue(a.contains("1")) + assertTrue(a.contains("2")) + assertTrue(a.contains("3")) + assertFalse(a.contains("4")) + + assertTrue(a.remove("1")) + assertEquals(2, a.size) + assertFalse(a.contains("1")) + assertTrue(a.contains("2")) + assertTrue(a.contains("3")) + assertFalse(a.contains("4")) + + assertTrue(a.add("4")) + assertEquals(3, a.size) + assertFalse(a.contains("1")) + assertTrue(a.contains("2")) + assertTrue(a.contains("3")) + assertTrue(a.contains("4")) + + assertFalse(a.add("4")) + assertEquals(3, a.size) + assertFalse(a.contains("1")) + assertTrue(a.contains("2")) + assertTrue(a.contains("3")) + assertTrue(a.contains("4")) + + a.clear() + assertTrue(a.isEmpty()) + assertEquals(0, a.size) + assertFalse(a.contains("1")) + assertFalse(a.contains("2")) + assertFalse(a.contains("3")) + assertFalse(a.contains("4")) +} + +fun testIterator() { + val s = HashSet(listOf("1", "2", "3")) + val it = s.iterator() + assertTrue(it.hasNext()) + assertEquals("1", it.next()) + assertTrue(it.hasNext()) + assertEquals("2", it.next()) + assertTrue(it.hasNext()) + assertEquals("3", it.next()) + assertFalse(it.hasNext()) +} + +fun testEquals() { + val s = HashSet(listOf("1", "2", "3")) + assertTrue(s == setOf("1", "2", "3")) + assertTrue(s == setOf("2", "3", "1")) // order does not matter + assertFalse(s == setOf("1", "2", "4")) + assertFalse(s == setOf("1", "2")) +} + +fun testHashCode() { + val s = HashSet(listOf("1", "2", "3")) + assertTrue(s.hashCode() == setOf("1", "2", "3").hashCode()) +} + +fun testToString() { + val s = HashSet(listOf("1", "2", "3")) + assertTrue(s.toString() == setOf("1", "2", "3").toString()) +} + +fun testContainsAll() { + val s = HashSet(listOf("1", "2", "3", "4", "5")) + assertFalse(s.containsAll(listOf("6", "7", "8"))) + assertFalse(s.containsAll(listOf("5", "6", "7"))) + assertFalse(s.containsAll(listOf("4", "5", "6"))) + assertTrue(s.containsAll(listOf("3", "4", "5"))) + assertTrue(s.containsAll(listOf("2", "3", "4"))) +} + +fun testRemoveAll() { + val s = HashSet(listOf("1", "2", "3", "4", "5", "1")) + assertFalse(s.removeAll(listOf("6", "7", "8"))) + assertEquals(setOf("1", "2", "3", "4", "5", "1"), s) + assertTrue(s.removeAll(listOf("5", "3", "1"))) + assertEquals(setOf("2", "4"), s) +} + +fun testRetainAll() { + val s = HashSet(listOf("1", "2", "3", "4", "5")) + assertFalse(s.retainAll(listOf("1", "2", "3", "4", "5"))) + assertEquals(setOf("1", "2", "3", "4", "5"), s) + assertTrue(s.retainAll(listOf("5", "3", "1"))) + assertEquals(setOf("1", "3", "5"), s) +} + +@Test fun runTest() { + testBasic() + testIterator() + testEquals() + testHashCode() + testToString() + testContainsAll() + testRemoveAll() + testRetainAll() + println("OK") +} \ No newline at end of file diff --git a/kotlin-native/backend.native/tests/runtime/collections/listof0.kt b/kotlin-native/backend.native/tests/runtime/collections/listof0.kt new file mode 100644 index 00000000000..62d7a3ca171 --- /dev/null +++ b/kotlin-native/backend.native/tests/runtime/collections/listof0.kt @@ -0,0 +1,24 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +package runtime.collections.listof0 + +import kotlin.test.* + +@Test fun runTest() { + main(arrayOf("a")) +} + +fun main(args : Array) { + val nonConstStr = args[0] + val list = arrayListOf(nonConstStr, "b", "c") + for (element in list) print(element) + println() + list.add("d") + println(list.toString()) + + val list2 = listOf("n", "s", nonConstStr) + println(list2.toString()) +} \ No newline at end of file diff --git a/kotlin-native/backend.native/tests/runtime/collections/moderately_large_array.kt b/kotlin-native/backend.native/tests/runtime/collections/moderately_large_array.kt new file mode 100644 index 00000000000..3a657d4fe2a --- /dev/null +++ b/kotlin-native/backend.native/tests/runtime/collections/moderately_large_array.kt @@ -0,0 +1,20 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +package runtime.collections.moderately_large_array + +import kotlin.test.* + +@Test fun runTest() { + val a = ByteArray(1000000) + + var sum = 0 + for (b in a) { + sum += b + } + + println(sum) +} + diff --git a/kotlin-native/backend.native/tests/runtime/collections/moderately_large_array1.kt b/kotlin-native/backend.native/tests/runtime/collections/moderately_large_array1.kt new file mode 100644 index 00000000000..d37cca92e00 --- /dev/null +++ b/kotlin-native/backend.native/tests/runtime/collections/moderately_large_array1.kt @@ -0,0 +1,20 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +package runtime.collections.moderately_large_array1 + +import kotlin.test.* + +@Test fun runTest() { + val a = Array(100000, { i -> i.toByte()}) + + var sum = 0 + for (b in a) { + sum += b + } + + println(sum) +} + diff --git a/kotlin-native/backend.native/tests/runtime/collections/range0.kt b/kotlin-native/backend.native/tests/runtime/collections/range0.kt new file mode 100644 index 00000000000..a7fad0967f9 --- /dev/null +++ b/kotlin-native/backend.native/tests/runtime/collections/range0.kt @@ -0,0 +1,15 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +package runtime.collections.range0 + +import kotlin.test.* + +@Test fun runTest() { + for (i in 1..3) print(i) + println() + for (i in 'a'..'d') print(i) + println() +} \ No newline at end of file diff --git a/kotlin-native/backend.native/tests/runtime/collections/sort0.kt b/kotlin-native/backend.native/tests/runtime/collections/sort0.kt new file mode 100644 index 00000000000..38b1c281ebd --- /dev/null +++ b/kotlin-native/backend.native/tests/runtime/collections/sort0.kt @@ -0,0 +1,13 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +package runtime.collections.sort0 + +import kotlin.test.* + +@Test fun runTest() { + println(arrayOf("x", "a", "b").sorted().toString()) + println(intArrayOf(239, 42, -1, 100500, 0).sorted().toString()); +} diff --git a/kotlin-native/backend.native/tests/runtime/collections/sort1.kt b/kotlin-native/backend.native/tests/runtime/collections/sort1.kt new file mode 100644 index 00000000000..44c8712abad --- /dev/null +++ b/kotlin-native/backend.native/tests/runtime/collections/sort1.kt @@ -0,0 +1,18 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +package runtime.collections.sort1 + +import kotlin.test.* + +@Test fun runTest() { + val foo = mutableListOf("x", "a", "b") + foo.sort() + println(foo.toString()) + + var bar = mutableListOf(239, 42, -1, 100500, 0) + bar.sort() + println(bar.toString()) +} \ No newline at end of file diff --git a/kotlin-native/backend.native/tests/runtime/collections/stack_array.kt b/kotlin-native/backend.native/tests/runtime/collections/stack_array.kt new file mode 100644 index 00000000000..d68d3ad529a --- /dev/null +++ b/kotlin-native/backend.native/tests/runtime/collections/stack_array.kt @@ -0,0 +1,17 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +package runtime.collections.stack_array + +import kotlin.test.* + +@Test fun runTest() { + val array = IntArray(2) + array[0] = 1 + array[1] = 2 + val check = array is IntArray + println(check) + println(array[0] + array[1]) +} \ No newline at end of file diff --git a/kotlin-native/backend.native/tests/runtime/collections/typed_array0.kt b/kotlin-native/backend.native/tests/runtime/collections/typed_array0.kt new file mode 100644 index 00000000000..e2baf4f40d9 --- /dev/null +++ b/kotlin-native/backend.native/tests/runtime/collections/typed_array0.kt @@ -0,0 +1,30 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +package runtime.collections.typed_array0 + +import kotlin.test.* + +@Test fun runTest() { + // Those tests assume little endian bit ordering. + val array = ByteArray(42) + array.setLongAt(5, 0x1234_5678_9abc_def0) + + expect(0x1234_5678_9abc_def0) { array.getLongAt(5) } + expect(0xdef0.toInt()) { array.getCharAt(5).toInt() } + expect(0x9abc.toShort()) { array.getShortAt(7) } + expect(0x1234_5678) { array.getIntAt(9) } + expect(0xdef0_0000u) { array.getUIntAt(3) } + expect(0xf0_00u) { array.getUShortAt(4) } + expect(0xf0u) { array.getUByteAt(5) } + expect(0x1234_5678_9abcuL) { array.getULongAt(7) } + + array.setIntAt(2, 0x40100000) + expect(2.25f) { array.getFloatAt(2) } + array.setLongAt(11, 0x400c_0000_0000_0000) + expect(3.5) { array.getDoubleAt(11) } + + println("OK") +} \ No newline at end of file diff --git a/kotlin-native/backend.native/tests/runtime/collections/typed_array1.kt b/kotlin-native/backend.native/tests/runtime/collections/typed_array1.kt new file mode 100644 index 00000000000..62f49a5b17d --- /dev/null +++ b/kotlin-native/backend.native/tests/runtime/collections/typed_array1.kt @@ -0,0 +1,73 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +package runtime.collections.typed_array1 + +import kotlin.test.* +import kotlin.native.concurrent.* + +@Test fun runTest() { + val array = ByteArray(17) + val results = mutableSetOf() + var counter = 0 + assertFailsWith { + results += array.getShortAt(16) + } + assertFailsWith { + results += array.getCharAt(22) + } + assertFailsWith { + results += array.getIntAt(15) + } + assertFailsWith { + results += array.getLongAt(14) + } + assertFailsWith { + results += array.getFloatAt(14) + } + assertFailsWith { + results += array.getDoubleAt(13) + } + assertFailsWith { + array.setShortAt(16, 2.toShort()) + } + assertFailsWith { + array.setCharAt(22, 'a') + } + assertFailsWith { + array.setIntAt(15, 1234) + } + assertFailsWith { + array.setLongAt(14, 1.toLong()) + } + assertFailsWith { + array.setFloatAt(14, 1.0f) + } + assertFailsWith { + array.setDoubleAt(13, 3.0) + } + expect(0) { results.size } + + array.freeze() + assertFailsWith { + array.setShortAt(0, 2.toShort()) + } + assertFailsWith { + array.setCharAt(0, 'a') + } + assertFailsWith { + array.setIntAt(0, 2) + } + assertFailsWith { + array.setLongAt(0, 2) + } + assertFailsWith { + array.setFloatAt(0, 1.0f) + } + assertFailsWith { + array.setDoubleAt(0, 1.0) + } + println("OK") +} \ No newline at end of file diff --git a/kotlin-native/backend.native/tests/runtime/concurrent/worker_bound_reference0.kt b/kotlin-native/backend.native/tests/runtime/concurrent/worker_bound_reference0.kt new file mode 100644 index 00000000000..108ab0a5a43 --- /dev/null +++ b/kotlin-native/backend.native/tests/runtime/concurrent/worker_bound_reference0.kt @@ -0,0 +1,780 @@ +/* + * Copyright 2010-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +package runtime.concurrent.worker_bound_reference0 + +import kotlin.test.* + +import kotlin.native.concurrent.* +import kotlin.native.internal.GC +import kotlin.native.ref.WeakReference +import kotlin.text.Regex + +class A(var a: Int) + +@SharedImmutable +val global1: WorkerBoundReference = WorkerBoundReference(A(3)) + +@Test +fun testGlobal() { + assertEquals(3, global1.value.a) + assertEquals(3, global1.valueOrNull?.a) + + val worker = Worker.start() + val future = worker.execute(TransferMode.SAFE, {}) { + global1 + } + + val value = future.result + assertEquals(3, value.value.a) + assertEquals(3, value.valueOrNull?.a) + worker.requestTermination().result +} + +@SharedImmutable +val global2: WorkerBoundReference = WorkerBoundReference(A(3)) + +@Test +fun testGlobalDenyAccessOnWorker() { + assertEquals(3, global2.value.a) + + val worker = Worker.start() + val future = worker.execute(TransferMode.SAFE, {}) { + val local = global2 + assertFailsWith { + local.value + } + assertEquals(null, local.valueOrNull) + Unit + } + + future.result + worker.requestTermination().result +} + +@SharedImmutable +val global3: WorkerBoundReference = WorkerBoundReference(A(3).freeze()) + +@Test +fun testGlobalAccessOnWorkerFrozenInitially() { + assertEquals(3, global3.value.a) + assertEquals(3, global3.valueOrNull?.a) + + val worker = Worker.start() + val future = worker.execute(TransferMode.SAFE, {}) { + global3.value.a + } + + val value = future.result + assertEquals(3, value) + worker.requestTermination().result +} + +@SharedImmutable +val global4: WorkerBoundReference = WorkerBoundReference(A(3)) + +@Test +fun testGlobalAccessOnWorkerFrozenBeforePassing() { + assertEquals(3, global4.value.a) + global4.value.freeze() + + val worker = Worker.start() + val future = worker.execute(TransferMode.SAFE, {}) { + global4.value.a + } + + val value = future.result + assertEquals(3, value) + worker.requestTermination().result +} + +@SharedImmutable +val global5: WorkerBoundReference = WorkerBoundReference(A(3)) + +@Test +fun testGlobalAccessOnWorkerFrozenBeforeAccess() { + val semaphore: AtomicInt = AtomicInt(0) + + assertEquals(3, global5.value.a) + + val worker = Worker.start() + val future = worker.execute(TransferMode.SAFE, { semaphore }) { semaphore -> + semaphore.increment() + while (semaphore.value < 2) { + } + + global5.value.a + } + + while (semaphore.value < 1) { + } + global5.value.freeze() + semaphore.increment() + + val value = future.result + assertEquals(3, value) + worker.requestTermination().result +} + +@SharedImmutable +val global6: WorkerBoundReference = WorkerBoundReference(A(3)) + +@Test +fun testGlobalModification() { + val semaphore: AtomicInt = AtomicInt(0) + + assertEquals(3, global6.value.a) + + val worker = Worker.start() + val future = worker.execute(TransferMode.SAFE, { semaphore }) { semaphore -> + semaphore.increment() + while (semaphore.value < 2) { + } + global6 + } + + while (semaphore.value < 1) { + } + global6.value.a = 4 + semaphore.increment() + + val value = future.result + assertEquals(4, value.value.a) + assertEquals(4, value.valueOrNull?.a) + worker.requestTermination().result +} + +@SharedImmutable +val global7: WorkerBoundReference = WorkerBoundReference(A(3)) + +@Test +fun testGlobalGetWorker() { + val ownerId = Worker.current.id + assertEquals(ownerId, global7.worker.id) + + val worker = Worker.start() + val future = worker.execute(TransferMode.SAFE, { ownerId }) { ownerId -> + assertEquals(ownerId, global7.worker.id) + Unit + } + + future.result + worker.requestTermination().result +} + +@Test +fun testLocal() { + val local = WorkerBoundReference(A(3)) + assertEquals(3, local.value.a) + assertEquals(3, local.valueOrNull?.a) +} + +@Test +fun testLocalFrozen() { + val local = WorkerBoundReference(A(3)).freeze() + assertEquals(3, local.value.a) + assertEquals(3, local.valueOrNull?.a) + + val worker = Worker.start() + val future = worker.execute(TransferMode.SAFE, { local }) { local -> + local + } + + val value = future.result + assertEquals(3, value.value.a) + assertEquals(3, value.valueOrNull?.a) + worker.requestTermination().result +} + +@Test +fun testLocalDenyAccessOnWorkerFrozen() { + val local = WorkerBoundReference(A(3)).freeze() + assertEquals(3, local.value.a) + + val worker = Worker.start() + val future = worker.execute(TransferMode.SAFE, { local }) { local -> + assertFailsWith { + local.value + } + assertEquals(null, local.valueOrNull) + Unit + } + + future.result + worker.requestTermination().result +} + +@Test +fun testLocalAccessOnWorkerFrozenInitiallyFrozen() { + val local = WorkerBoundReference(A(3).freeze()).freeze() + assertEquals(3, local.value.a) + assertEquals(3, local.valueOrNull?.a) + + val worker = Worker.start() + val future = worker.execute(TransferMode.SAFE, { local }) { local -> + local.value.a + } + + val value = future.result + assertEquals(3, value) + worker.requestTermination().result +} + +@Test +fun testLocalAccessOnWorkerFrozenBeforePassingFrozen() { + val local = WorkerBoundReference(A(3)).freeze() + assertEquals(3, local.value.a) + local.value.freeze() + + val worker = Worker.start() + val future = worker.execute(TransferMode.SAFE, { local }) { local -> + local.value.a + } + + val value = future.result + assertEquals(3, value) + worker.requestTermination().result +} + +@Test +fun testLocalAccessOnWorkerFrozenBeforeAccessFrozen() { + val semaphore: AtomicInt = AtomicInt(0) + + val local = WorkerBoundReference(A(3)).freeze() + assertEquals(3, local.value.a) + + val worker = Worker.start() + val future = worker.execute(TransferMode.SAFE, { Pair(local, semaphore) }) { (local, semaphore) -> + semaphore.increment() + while (semaphore.value < 2) { + } + + local.value.a + } + + while (semaphore.value < 1) { + } + local.value.freeze() + semaphore.increment() + + val value = future.result + assertEquals(3, value) + worker.requestTermination().result +} + +@Test +fun testLocalAccessOnMainThread() { + val worker = Worker.start() + val future = worker.execute(TransferMode.SAFE, {}) { + WorkerBoundReference(A(3)) + } + + assertEquals(3, future.result.value.a) + + worker.requestTermination().result +} + +@Test +fun testLocalDenyAccessOnMainThreadFrozen() { + val worker = Worker.start() + val future = worker.execute(TransferMode.SAFE, {}) { + WorkerBoundReference(A(3)).freeze() + } + + val value = future.result + assertFailsWith { + value.value + } + assertEquals(null, value.valueOrNull) + + worker.requestTermination().result +} + +@Test +fun testLocalModificationFrozen() { + val semaphore: AtomicInt = AtomicInt(0) + + val local = WorkerBoundReference(A(3)).freeze() + assertEquals(3, local.value.a) + + val worker = Worker.start() + val future = worker.execute(TransferMode.SAFE, { Pair(local, semaphore) }) { (local, semaphore) -> + semaphore.increment() + while (semaphore.value < 2) { + } + local + } + + while (semaphore.value < 1) { + } + local.value.a = 4 + semaphore.increment() + + val value = future.result + assertEquals(4, value.value.a) + assertEquals(4, value.valueOrNull?.a) + worker.requestTermination().result +} + +@Test +fun testLocalGetWorkerFrozen() { + val local = WorkerBoundReference(A(3)).freeze() + + val ownerId = Worker.current.id + assertEquals(ownerId, local.worker.id) + + val worker = Worker.start() + val future = worker.execute(TransferMode.SAFE, { Pair(local, ownerId) }) { (local, ownerId) -> + assertEquals(ownerId, local.worker.id) + Unit + } + + future.result + worker.requestTermination().result +} + +@Test +fun testLocalForeignGetWorker() { + val worker = Worker.start() + val ownerId = worker.id + val future = worker.execute(TransferMode.SAFE, { ownerId }) { ownerId -> + val local = WorkerBoundReference(A(3)) + assertEquals(ownerId, local.worker.id) + local + } + + val value = future.result + assertEquals(ownerId, value.worker.id) + + worker.requestTermination().result +} + +@Test +fun testLocalForeignGetWorkerFrozen() { + val worker = Worker.start() + val ownerId = worker.id + val future = worker.execute(TransferMode.SAFE, { ownerId }) { ownerId -> + val local = WorkerBoundReference(A(3)).freeze() + assertEquals(ownerId, local.worker.id) + local + } + + val value = future.result + assertEquals(ownerId, value.worker.id) + + worker.requestTermination().result +} + +class Wrapper(val ref: WorkerBoundReference) + +@Test +fun testLocalWithWrapperFrozen() { + val local = Wrapper(WorkerBoundReference(A(3))).freeze() + assertEquals(3, local.ref.value.a) + + val worker = Worker.start() + val future = worker.execute(TransferMode.SAFE, { local }) { local -> + local + } + + val value = future.result + assertEquals(3, value.ref.value.a) + worker.requestTermination().result +} + +@Test +fun testLocalDenyAccessWithWrapperFrozen() { + val local = Wrapper(WorkerBoundReference(A(3))).freeze() + assertEquals(3, local.ref.value.a) + + val worker = Worker.start() + val future = worker.execute(TransferMode.SAFE, { local }) { local -> + assertFailsWith { + local.ref.value + } + assertEquals(null, local.ref.valueOrNull) + Unit + } + + future.result + worker.requestTermination().result +} + +fun getOwnerAndWeaks(initial: Int): Triple?>, WeakReference>, WeakReference> { + val ref = WorkerBoundReference(A(initial)) + val refOwner: FreezableAtomicReference?> = FreezableAtomicReference(ref) + val refWeak = WeakReference(ref) + val refValueWeak = WeakReference(ref.value) + + return Triple(refOwner, refWeak, refValueWeak) +} + +@Test +fun testCollect() { + val (refOwner, refWeak, refValueWeak) = getOwnerAndWeaks(3) + + refOwner.value = null + GC.collect() + + // Last reference to WorkerBoundReference is gone, so it and it's referent are destroyed. + assertNull(refWeak.value) + assertNull(refValueWeak.value) +} + +fun getOwnerAndWeaksFrozen(initial: Int): Triple?>, WeakReference>, WeakReference> { + val ref = WorkerBoundReference(A(initial)).freeze() + val refOwner: AtomicReference?> = AtomicReference(ref) + val refWeak = WeakReference(ref) + val refValueWeak = WeakReference(ref.value) + + return Triple(refOwner, refWeak, refValueWeak) +} + +@Test +fun testCollectFrozen() { + val (refOwner, refWeak, refValueWeak) = getOwnerAndWeaksFrozen(3) + + refOwner.value = null + GC.collect() + + // Last reference to WorkerBoundReference is gone, so it and it's referent are destroyed. + assertNull(refWeak.value) + assertNull(refValueWeak.value) +} + +fun collectInWorkerFrozen(worker: Worker, semaphore: AtomicInt): Pair, Future> { + val (refOwner, _, refValueWeak) = getOwnerAndWeaksFrozen(3) + + val future = worker.execute(TransferMode.SAFE, { Pair(refOwner, semaphore) }) { (refOwner, semaphore) -> + semaphore.increment() + while (semaphore.value < 2) { + } + + refOwner.value = null + GC.collect() + } + + while (semaphore.value < 1) { + } + // At this point worker is spinning on semaphore. refOwner still contains reference to + // WorkerBoundReference, so referent is kept alive. + GC.collect() + assertNotNull(refValueWeak.value) + + return Pair(refValueWeak, future) +} + +@Test +fun testCollectInWorkerFrozen() { + val semaphore: AtomicInt = AtomicInt(0) + + val worker = Worker.start() + + val (refValueWeak, future) = collectInWorkerFrozen(worker, semaphore) + semaphore.increment() + future.result + + // At this point WorkerBoundReference no longer has a reference, so it's referent is destroyed. + GC.collect() + assertNull(refValueWeak.value) + + worker.requestTermination().result +} + +fun doNotCollectInWorkerFrozen(worker: Worker, semaphore: AtomicInt): Future> { + val ref = WorkerBoundReference(A(3)).freeze() + + return worker.execute(TransferMode.SAFE, { Pair(ref, semaphore) }) { (ref, semaphore) -> + semaphore.increment() + while (semaphore.value < 2) { + } + + GC.collect() + ref + } +} + +@Test +fun testDoNotCollectInWorkerFrozen() { + val semaphore: AtomicInt = AtomicInt(0) + + val worker = Worker.start() + + val future = doNotCollectInWorkerFrozen(worker, semaphore) + while (semaphore.value < 1) { + } + GC.collect() + semaphore.increment() + + val value = future.result + assertEquals(3, value.value.a) + worker.requestTermination().result +} + +class B1 { + lateinit var b2: WorkerBoundReference +} + +data class B2(val b1: WorkerBoundReference) + +fun createCyclicGarbage(): Triple?>, WeakReference, WeakReference> { + val ref1 = WorkerBoundReference(B1()) + val ref1Owner: FreezableAtomicReference?> = FreezableAtomicReference(ref1) + val ref1Weak = WeakReference(ref1.value) + + val ref2 = WorkerBoundReference(B2(ref1)) + val ref2Weak = WeakReference(ref2.value) + + ref1.value.b2 = ref2 + + return Triple(ref1Owner, ref1Weak, ref2Weak) +} + +@Test +fun collectCyclicGarbage() { + val (ref1Owner, ref1Weak, ref2Weak) = createCyclicGarbage() + + ref1Owner.value = null + GC.collect() + + assertNull(ref1Weak.value) + assertNull(ref2Weak.value) +} + +fun createCyclicGarbageFrozen(): Triple?>, WeakReference, WeakReference> { + val ref1 = WorkerBoundReference(B1()).freeze() + val ref1Owner: AtomicReference?> = AtomicReference(ref1) + val ref1Weak = WeakReference(ref1.value) + + val ref2 = WorkerBoundReference(B2(ref1)).freeze() + val ref2Weak = WeakReference(ref2.value) + + ref1.value.b2 = ref2 + + return Triple(ref1Owner, ref1Weak, ref2Weak) +} + +@Test +fun doesNotCollectCyclicGarbageFrozen() { + val (ref1Owner, ref1Weak, ref2Weak) = createCyclicGarbageFrozen() + + ref1Owner.value = null + GC.collect() + + // If these asserts fail, that means WorkerBoundReference managed to clean up cyclic garbage all by itself. + assertNotNull(ref1Weak.value) + assertNotNull(ref2Weak.value) +} + +fun createCrossThreadCyclicGarbageFrozen( + worker: Worker +): Triple?>, WeakReference, WeakReference> { + val ref1 = WorkerBoundReference(B1()).freeze() + val ref1Owner: AtomicReference?> = AtomicReference(ref1) + val ref1Weak = WeakReference(ref1.value) + + val future = worker.execute(TransferMode.SAFE, { ref1 }) { ref1 -> + val ref2 = WorkerBoundReference(B2(ref1)).freeze() + Pair(ref2, WeakReference(ref2.value)) + } + val (ref2, ref2Weak) = future.result + + ref1.value.b2 = ref2 + + return Triple(ref1Owner, ref1Weak, ref2Weak) +} + +@Test +fun doesNotCollectCrossThreadCyclicGarbageFrozen() { + val worker = Worker.start() + + val (ref1Owner, ref1Weak, ref2Weak) = createCrossThreadCyclicGarbageFrozen(worker) + + ref1Owner.value = null + GC.collect() + worker.execute(TransferMode.SAFE, {}) { GC.collect() }.result + + // If these asserts fail, that means WorkerBoundReference managed to clean up cyclic garbage all by itself. + assertNotNull(ref1Weak.value) + assertNotNull(ref2Weak.value) + + worker.requestTermination().result +} + +class C1 { + lateinit var c2: AtomicReference?> + + fun dispose() { + c2.value = null + } +} + +data class C2(val c1: AtomicReference>) + +fun createCyclicGarbageWithAtomicsFrozen(): Triple?>, WeakReference, WeakReference> { + val ref1 = WorkerBoundReference(C1()).freeze() + val ref1Weak = WeakReference(ref1.value) + + val ref2 = WorkerBoundReference(C2(AtomicReference(ref1))).freeze() + val ref2Weak = WeakReference(ref2.value) + + ref1.value.c2 = AtomicReference(ref2) + + return Triple(AtomicReference(ref1), ref1Weak, ref2Weak) +} + +fun dispose(refOwner: AtomicReference?>) { + refOwner.value!!.value.dispose() + refOwner.value = null +} + +@Test +fun doesNotCollectCyclicGarbageWithAtomicsFrozen() { + val (ref1Owner, ref1Weak, ref2Weak) = createCyclicGarbageWithAtomicsFrozen() + + ref1Owner.value = null + GC.collect() + + // If these asserts fail, that means AtomicReference managed to clean up cyclic garbage all by itself. + assertNotNull(ref1Weak.value) + assertNotNull(ref2Weak.value) +} + +@Test +fun collectCyclicGarbageWithAtomicsFrozen() { + val (ref1Owner, ref1Weak, ref2Weak) = createCyclicGarbageWithAtomicsFrozen() + + dispose(ref1Owner) + GC.collect() + + assertNull(ref1Weak.value) + assertNull(ref2Weak.value) +} + +fun createCrossThreadCyclicGarbageWithAtomicsFrozen( + worker: Worker +): Triple?>, WeakReference, WeakReference> { + val ref1 = WorkerBoundReference(C1()).freeze() + val ref1Weak = WeakReference(ref1.value) + + val future = worker.execute(TransferMode.SAFE, { ref1 }) { ref1 -> + val ref2 = WorkerBoundReference(C2(AtomicReference(ref1))).freeze() + Pair(ref2, WeakReference(ref2.value)) + } + val (ref2, ref2Weak) = future.result + + ref1.value.c2 = AtomicReference(ref2) + + return Triple(AtomicReference(ref1), ref1Weak, ref2Weak) +} + +@Test +fun doesNotCollectCrossThreadCyclicGarbageWithAtomicsFrozen() { + val worker = Worker.start() + + val (ref1Owner, ref1Weak, ref2Weak) = createCrossThreadCyclicGarbageWithAtomicsFrozen(worker) + + ref1Owner.value = null + GC.collect() + worker.execute(TransferMode.SAFE, {}) { GC.collect() }.result + + // If these asserts fail, that means AtomicReference managed to clean up cyclic garbage all by itself. + assertNotNull(ref1Weak.value) + assertNotNull(ref2Weak.value) + + worker.requestTermination().result +} + +@Test +fun collectCrossThreadCyclicGarbageWithAtomicsFrozen() { + val worker = Worker.start() + + val (ref1Owner, ref1Weak, ref2Weak) = createCrossThreadCyclicGarbageWithAtomicsFrozen(worker) + + dispose(ref1Owner) + // This marks C2 as gone on the main thread + GC.collect() + // This cleans up all the references from the worker thread and destroys C2, but C1 is still alive. + worker.execute(TransferMode.SAFE, {}) { GC.collect() }.result + // And this finally destroys C1 + GC.collect() + + assertNull(ref1Weak.value) + assertNull(ref2Weak.value) + + worker.requestTermination().result +} + +@Test +fun concurrentAccessFrozen() { + val workerCount = 10 + val workerUnlocker = AtomicInt(0) + + val ref = WorkerBoundReference(A(3)).freeze() + assertEquals(3, ref.value.a) + + val workers = Array(workerCount) { + Worker.start() + } + val futures = Array(workers.size) { + workers[it].execute(TransferMode.SAFE, { Pair(ref, workerUnlocker) }) { (ref, workerUnlocker) -> + while (workerUnlocker.value < 1) { + } + + assertFailsWith { + ref.value + } + Unit + } + } + workerUnlocker.increment() + + for (future in futures) { + future.result + } + + for (worker in workers) { + worker.requestTermination().result + } +} + +@Test +fun testExceptionMessageFrozen() { + val worker = Worker.start() + val future = worker.execute(TransferMode.SAFE, {}) { + WorkerBoundReference(A(3)).freeze() + } + val value = future.result + + val ownerName = worker.name + val messagePattern = Regex("illegal attempt to access non-shared runtime\\.concurrent\\.worker_bound_reference0\\.A@[a-f0-9]+ bound to `$ownerName` from `${Worker.current.name}`") + + val exception = assertFailsWith { + value.value + } + assertTrue(messagePattern matches exception.message!!) + + worker.requestTermination().result +} + +@Test +fun testDoubleFreeze() { + val ref = WorkerBoundReference(A(3)) + val wrapper = Wrapper(ref) + ref.freeze() + ref.freeze() + wrapper.freeze() +} + +@Test +fun testDoubleFreezeWithFreezeBlocker() { + val ref = WorkerBoundReference(A(3)) + val wrapper = Wrapper(ref) + wrapper.ensureNeverFrozen() + assertFailsWith { + wrapper.freeze() + } + ref.freeze() +} diff --git a/kotlin-native/backend.native/tests/runtime/exceptions/catch1.kt b/kotlin-native/backend.native/tests/runtime/exceptions/catch1.kt new file mode 100644 index 00000000000..e22562c4ad1 --- /dev/null +++ b/kotlin-native/backend.native/tests/runtime/exceptions/catch1.kt @@ -0,0 +1,25 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +package runtime.exceptions.catch1 + +import kotlin.test.* + +@Test fun runTest() { + try { + println("Before") + foo() + println("After") + } catch (e: Throwable) { + println("Caught Throwable") + } + + println("Done") +} + +fun foo() { + throw Error("Error happens") + println("After in foo()") +} \ No newline at end of file diff --git a/kotlin-native/backend.native/tests/runtime/exceptions/catch2.kt b/kotlin-native/backend.native/tests/runtime/exceptions/catch2.kt new file mode 100644 index 00000000000..5eee69f5301 --- /dev/null +++ b/kotlin-native/backend.native/tests/runtime/exceptions/catch2.kt @@ -0,0 +1,29 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +package runtime.exceptions.catch2 + +import kotlin.test.* + +@Test fun runTest() { + try { + println("Before") + foo() + println("After") + } catch (e: Exception) { + println("Caught Exception") + } catch (e: Error) { + println("Caught Error") + } catch (e: Throwable) { + println("Caught Throwable") + } + + println("Done") +} + +fun foo() { + throw Error("Error happens") + println("After in foo()") +} \ No newline at end of file diff --git a/kotlin-native/backend.native/tests/runtime/exceptions/catch7.kt b/kotlin-native/backend.native/tests/runtime/exceptions/catch7.kt new file mode 100644 index 00000000000..91ae88cd742 --- /dev/null +++ b/kotlin-native/backend.native/tests/runtime/exceptions/catch7.kt @@ -0,0 +1,23 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +package runtime.exceptions.catch7 + +import kotlin.test.* + +@Test fun runTest() { + try { + foo() + } catch (e: Throwable) { + val message = e.message + if (message != null) { + println(message) + } + } +} + +fun foo() { + throw Error("Error happens") +} \ No newline at end of file diff --git a/kotlin-native/backend.native/tests/runtime/exceptions/check_stacktrace_format.kt b/kotlin-native/backend.native/tests/runtime/exceptions/check_stacktrace_format.kt new file mode 100644 index 00000000000..2f21dc84d64 --- /dev/null +++ b/kotlin-native/backend.native/tests/runtime/exceptions/check_stacktrace_format.kt @@ -0,0 +1,42 @@ +// Checks that on Apple targets first two lines of exception stacktrace of symbolized executable looks like +// "\tat 1 main.kexe\t\t 0x000000010d7cdb4c kfun:package.function(kotlin.Int) + 108 (/path/to/file/name.kt:10:27)\n" +// If test is broken, org.jetbrains.kotlin.idea.filters.KotlinExceptionFilter (in main Kotlin repo) should be updated. + +import kotlin.test.* +import kotlin.text.Regex + +val EXTENSION = ".kt:" +val LOCATION_PATTERN = Regex("\\d+:\\d+") + +fun checkStringFormat(s: String) { + val trimmed = s.trim() + + assertTrue(trimmed.endsWith(')'), "Line is not ended with ')'") + assertNotEquals(trimmed.indexOf('('), -1, "No '(' before filename") + + val fileName = trimmed.substring(trimmed.lastIndexOf('(') + 1, trimmed.lastIndex) + assertNotEquals(fileName.indexOf(EXTENSION), -1, "Filename 'kt' extension is absent") + + val location = fileName.substring(fileName.indexOf(EXTENSION) + EXTENSION.length) + assertTrue(LOCATION_PATTERN.matches(location), "Expected location of form 12:8") +} + +fun functionA() { + throw Error("an error") +} + +fun functionB() { + functionA() +} + +const val depth = 5 + +fun main(args : Array) { + try { + functionB() + } catch (e: Throwable) { + val stacktrace = e.getStackTrace() + assert(stacktrace.size >= depth) + stacktrace.take(depth).forEach(::checkStringFormat) + } +} diff --git a/kotlin-native/backend.native/tests/runtime/exceptions/custom_hook.kt b/kotlin-native/backend.native/tests/runtime/exceptions/custom_hook.kt new file mode 100644 index 00000000000..edb2c682a6e --- /dev/null +++ b/kotlin-native/backend.native/tests/runtime/exceptions/custom_hook.kt @@ -0,0 +1,22 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ +import kotlin.test.* + +import kotlin.native.concurrent.* + +fun main(args : Array) { + assertFailsWith { + setUnhandledExceptionHook { _ -> println("wrong") } + } + + val x = 42 + val old = setUnhandledExceptionHook({ + throwable: Throwable -> println("value $x: ${throwable::class.simpleName}") + }.freeze()) + + assertNull(old) + + throw Error("an error") +} \ No newline at end of file diff --git a/kotlin-native/backend.native/tests/runtime/exceptions/extend0.kt b/kotlin-native/backend.native/tests/runtime/exceptions/extend0.kt new file mode 100644 index 00000000000..298bc0e3781 --- /dev/null +++ b/kotlin-native/backend.native/tests/runtime/exceptions/extend0.kt @@ -0,0 +1,18 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +package runtime.exceptions.extend0 + +import kotlin.test.* + +class C : Exception("OK") + +@Test fun runTest() { + try { + throw C() + } catch (e: Throwable) { + println(e.message!!) + } +} \ No newline at end of file diff --git a/kotlin-native/backend.native/tests/runtime/exceptions/kt-37572.kt b/kotlin-native/backend.native/tests/runtime/exceptions/kt-37572.kt new file mode 100644 index 00000000000..eee281de776 --- /dev/null +++ b/kotlin-native/backend.native/tests/runtime/exceptions/kt-37572.kt @@ -0,0 +1,42 @@ +import kotlin.text.Regex +import kotlin.test.* + +fun main() { + try { + foo() + } catch (tw:Throwable) { + val stackTrace = tw.getStackTrace() + stackTrace.take(6).forEach(::checkFrame) + } +} + +fun foo() { + myRun { + //platform.darwin.NSObject() + throwException() + } +} + +inline fun myRun(block: () -> Unit) { + block() +} + +fun throwException() { + throw Error() +} +internal val regex = Regex("^(\\d+)\\ +.*/(.*):(\\d+):.*$") +internal val goldValues = arrayOf?>( + null, + null, + "kt-37572.kt" to 25, + "kt-37572.kt" to 16, + "kt-37572.kt" to 6, + "kt-37572.kt" to 4) + +internal fun checkFrame(value:String) { + val (pos, file, line) = regex.find(value)!!.destructured + goldValues[pos.toInt()]?.let{ + assertEquals(it.first, file) + assertEquals(it.second, line.toInt()) + } +} \ No newline at end of file diff --git a/kotlin-native/backend.native/tests/runtime/exceptions/stack_trace_inline.kt b/kotlin-native/backend.native/tests/runtime/exceptions/stack_trace_inline.kt new file mode 100644 index 00000000000..6b4514726cc --- /dev/null +++ b/kotlin-native/backend.native/tests/runtime/exceptions/stack_trace_inline.kt @@ -0,0 +1,31 @@ +import kotlin.text.Regex +import kotlin.test.* + +fun exception() { + error("FAIL!") +} + +fun main() { + try { + exception() + } + catch (e:Exception) { + val stackTrace = e.getStackTrace() + stackTrace.take(6).forEach(::checkFrame) + } +} +internal val regex = Regex("^(\\d+)\\ +.*/(.*):(\\d+):.*$") +internal val goldValues = arrayOf?>( + null, + null, + null, + null, + "stack_trace_inline.kt" to 5, + "stack_trace_inline.kt" to 10) +internal fun checkFrame(value:String) { + val (pos, file, line) = regex.find(value)!!.destructured + goldValues[pos.toInt()]?.let{ + assertEquals(it.first, file) + assertEquals(it.second, line.toInt()) + } +} \ No newline at end of file diff --git a/kotlin-native/backend.native/tests/runtime/memory/basic0.kt b/kotlin-native/backend.native/tests/runtime/memory/basic0.kt new file mode 100644 index 00000000000..3fce09e781d --- /dev/null +++ b/kotlin-native/backend.native/tests/runtime/memory/basic0.kt @@ -0,0 +1,19 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +package runtime.memory.basic0 + +import kotlin.test.* + +class A { + var field: B? = null +} + +class B(var field: Int) + +@Test fun runTest() { + val a = A() + a.field = B(2) +} diff --git a/kotlin-native/backend.native/tests/runtime/memory/cycle_collector.kt b/kotlin-native/backend.native/tests/runtime/memory/cycle_collector.kt new file mode 100644 index 00000000000..88ec23dcce7 --- /dev/null +++ b/kotlin-native/backend.native/tests/runtime/memory/cycle_collector.kt @@ -0,0 +1,190 @@ +import kotlin.native.concurrent.* +import kotlin.native.internal.GC +import kotlin.test.* + +fun test1() { + val a = AtomicReference(null) + val b = AtomicReference(null) + a.value = b + b.value = a +} + +class Holder(var other: Any?) + +fun test2() { + val array = arrayOf(AtomicReference(null), AtomicReference(null)) + val obj1 = Holder(array).freeze() + array[0].value = obj1 +} + +fun test3() { + val a1 = FreezableAtomicReference(null) + val head = Holder(null) + var current = head + repeat(30) { + val next = Holder(null) + current.other = next + current = next + } + a1.value = head + current.other = a1 + current.freeze() +} + + +fun makeIt(): Holder { + val atomic = AtomicReference(null) + val holder = Holder(atomic).freeze() + atomic.value = holder + return holder +} + + +fun test4() { + val holder = makeIt() + // To clean rc count coming from rememberNewContainer(). + kotlin.native.internal.GC.collect() + // Request cyclic collection. + kotlin.native.internal.GC.collectCyclic() + // Ensure we processed delayed release. + repeat(10) { + // Wait a bit and process queue. + Worker.current.park(10) + Worker.current.processQueue() + kotlin.native.internal.GC.collect() + } + val value = @Suppress("UNCHECKED_CAST") (holder.other as? AtomicReference?) + assertTrue(value != null) + assertTrue(value.value == holder) +} + +fun createRef(): AtomicReference { + val atomic1 = AtomicReference(null) + val atomic2 = AtomicReference(null) + atomic1.value = atomic2 + atomic2.value = atomic1 + return atomic1 +} + +class Holder2(var value: AtomicReference) { + fun switch() { + value = value.value as AtomicReference + } +} + +fun createHolder2() = Holder2(createRef()) + +fun test5() { + val holder = createHolder2() + kotlin.native.internal.GC.collect() + kotlin.native.internal.GC.collectCyclic() + Worker.current.park(100 * 1000) + holder.switch() + kotlin.native.internal.GC.collect() + Worker.current.park(100 * 1000) + withWorker { + executeAfter(0L, { + kotlin.native.internal.GC.collect() + }.freeze()) + } + Worker.current.park(1000) + assertTrue(holder.value.value != null) +} + +fun test6() { + val atomic = AtomicReference(null) + atomic.value = Pair(atomic, Holder(atomic)).freeze() +} + +fun createRoot(): AtomicReference { + val ref1 = AtomicReference(null) + val ref2 = AtomicReference(null) + + ref1.value = Holder(ref2).freeze() + ref2.value = Any().freeze() + + return ref1 +} + +fun test7() { + val ref1 = createRoot() + kotlin.native.internal.GC.collect() + + kotlin.native.internal.GC.collectCyclic() + Worker.current.park(500 * 1000L) + + withWorker { + executeAfter(0L, {}.freeze()) + Worker.current.park(500 * 1000L) + + val node = ref1.value as Holder + val ref2 = node.other as AtomicReference + assertTrue(ref2.value != null) + } +} + +fun array(size: Int) = Array(size, { null }) + +fun test8() { + val ref = AtomicReference(null) + val obj1 = array(2) + val obj2 = array(1) + val obj3 = array(2) + + obj1[0] = obj2 + obj1[1] = obj3 + + obj2[0] = obj3 + + obj3[0] = obj2 + obj3[1] = ref + + ref.value = obj1.freeze() +} + +fun createNode1(): Holder { + val ref = AtomicReference(null) + val node2 = Holder(ref) + val node1 = Holder(node2) + ref.value = node1.freeze() + + return node1 +} + +fun getNode2(): Holder { + val node1 = createNode1() + GC.collect() + + return node1.other as Holder +} + +fun test9() { + withWorker { + val node2 = getNode2() + executeAfter(10 * 1000L, { GC.collectCyclic() }.freeze()) + + GC.collect() + + Worker.current.park(50 * 1000L) + + execute(TransferMode.SAFE, {}, {}).result + + val ref = node2.other as AtomicReference + assertTrue(ref.value != null) + } +} + +fun main() { + kotlin.native.internal.GC.cyclicCollectorEnabled = true + test1() + test2() + test3() + test4() + repeat(10) { + test5() + } + test6() + test7() + test8() + test9() +} \ No newline at end of file diff --git a/kotlin-native/backend.native/tests/runtime/memory/cycle_collector_deadlock1.kt b/kotlin-native/backend.native/tests/runtime/memory/cycle_collector_deadlock1.kt new file mode 100644 index 00000000000..3b7c32d5924 --- /dev/null +++ b/kotlin-native/backend.native/tests/runtime/memory/cycle_collector_deadlock1.kt @@ -0,0 +1,16 @@ +import kotlin.native.concurrent.* +import kotlin.native.internal.GC +import kotlin.test.* + +fun main() { + kotlin.native.internal.GC.cyclicCollectorEnabled = true + + repeat(10000) { + // Create atomic cyclic garbage: + val ref = AtomicReference(null) + ref.value = ref + } + + // main thread will then run cycle collector termination, which involves running it and cleaning everything up. + // 10000 references should hit [kGcThreshold] then. +} \ No newline at end of file diff --git a/kotlin-native/backend.native/tests/runtime/memory/cycle_detector.kt b/kotlin-native/backend.native/tests/runtime/memory/cycle_detector.kt new file mode 100644 index 00000000000..0f4113856e7 --- /dev/null +++ b/kotlin-native/backend.native/tests/runtime/memory/cycle_detector.kt @@ -0,0 +1,193 @@ +import kotlin.native.concurrent.* +import kotlin.native.internal.GC +import kotlin.test.* + +class Holder(var other: Any?) + +class Holder2(var field1: Any?, var field2: Any?) + +val Array.description: String + get() { + val result = StringBuilder() + result.append('[') + for (elem in this) { + result.append(elem.toString()) + result.append(',') + } + result.append(']') + return result.toString() + } + +fun assertArrayEquals( + expected: Array, + actual: Array +): Unit { + val lazyMessage: () -> String? = { + "Expected <${expected.description}>, actual <${actual.description}>." + } + + asserter.assertTrue(lazyMessage, expected.size == actual.size) + for (i in expected.indices) { + asserter.assertTrue(lazyMessage, expected[i] == actual[i]) + } +} + +@Test +fun noCycles() { + val atomic1 = AtomicReference(null) + val atomic2 = AtomicReference(null) + try { + atomic1.value = atomic2 + val cycles = GC.detectCycles()!! + assertEquals(0, cycles.size) + assertNull(GC.findCycle(atomic1)); + assertNull(GC.findCycle(atomic2)); + } finally { + atomic1.value = null + atomic2.value = null + } +} + +@Test +fun oneCycle() { + val atomic = AtomicReference(null) + try { + atomic.value = atomic + val cycles = GC.detectCycles()!! + assertEquals(1, cycles.size) + assertArrayEquals(arrayOf(atomic, atomic), GC.findCycle(cycles[0])!!) + } finally { + atomic.value = null + } +} + +@Test +fun oneCycleWithHolder() { + val atomic = AtomicReference(null) + try { + atomic.value = Holder(atomic).freeze() + val cycles = GC.detectCycles()!! + assertEquals(1, cycles.size) + assertArrayEquals(arrayOf(atomic, atomic.value!!, atomic), GC.findCycle(cycles[0])!!) + assertArrayEquals(arrayOf(atomic.value!!, atomic, atomic.value!!), GC.findCycle(atomic.value!!)!!) + } finally { + atomic.value = null + } +} + +@Test +fun oneCycleWithArray() { + val array = arrayOf(AtomicReference(null), AtomicReference(null)) + try { + array[0].value = Holder(array).freeze() + val cycles = GC.detectCycles()!! + assertEquals(1, cycles.size) + assertArrayEquals(arrayOf(array[0], array[0].value!!, array, array[0]), GC.findCycle(cycles[0])!!) + } finally { + array[0].value = null + array[1].value = null + } +} + +@Test +fun oneCycleWithLongChain() { + val atomic = AtomicReference(null) + try { + val head = Holder(null) + var current = head + repeat(30) { + val next = Holder(null) + current.other = next + current = next + } + current.other = atomic + atomic.value = head.freeze() + val cycles = GC.detectCycles()!! + assertEquals(1, cycles.size) + val cycle = GC.findCycle(cycles[0])!! + assertEquals(33, cycle.size) + } finally { + atomic.value = null + } +} + +@Test +fun twoCycles() { + val atomic1 = AtomicReference(null) + val atomic2 = AtomicReference(null) + try { + atomic1.value = atomic2 + atomic2.value = atomic1 + val cycles = GC.detectCycles()!! + assertEquals(2, cycles.size) + assertArrayEquals(arrayOf(atomic2, atomic1, atomic2), GC.findCycle(cycles[0])!!) + assertArrayEquals(arrayOf(atomic1, atomic2, atomic1), GC.findCycle(cycles[1])!!) + } finally { + atomic1.value = null + atomic2.value = null + } +} + +@Test +fun twoCyclesWithHolder() { + val atomic1 = AtomicReference(null) + val atomic2 = AtomicReference(null) + try { + atomic1.value = atomic2 + atomic2.value = Holder(atomic1).freeze() + val cycles = GC.detectCycles()!! + assertEquals(2, cycles.size) + assertArrayEquals(arrayOf(atomic2, atomic2.value!!, atomic1, atomic2), GC.findCycle(cycles[0])!!) + assertArrayEquals(arrayOf(atomic1, atomic2, atomic2.value!!, atomic1), GC.findCycle(cycles[1])!!) + } finally { + atomic1.value = null + atomic2.value = null + } +} + +@Test +fun threeSeparateCycles() { + val atomic1 = AtomicReference(null) + val atomic2 = AtomicReference(null) + val atomic3 = AtomicReference(null) + try { + atomic1.value = atomic1 + atomic2.value = Holder2(atomic1, atomic2).freeze() + atomic3.value = Holder2(atomic3, atomic1).freeze() + val cycles = GC.detectCycles()!! + assertEquals(3, cycles.size) + assertArrayEquals(arrayOf(atomic3, atomic3.value!!, atomic3), GC.findCycle(cycles[0])!!) + assertArrayEquals(arrayOf(atomic2, atomic2.value!!, atomic2), GC.findCycle(cycles[1])!!) + assertArrayEquals(arrayOf(atomic1, atomic1), GC.findCycle(cycles[2])!!) + } finally { + atomic1.value = null + atomic2.value = null + atomic3.value = null + } +} + +@Test +fun noCyclesWithFreezableAtomicReference() { + val atomic = FreezableAtomicReference(null) + try { + atomic.value = atomic + val cycles = GC.detectCycles()!! + assertEquals(0, cycles.size) + } finally { + atomic.value = null + } +} + +@Test +fun oneCycleWithFrozenFreezableAtomicReference() { + val atomic = FreezableAtomicReference(null) + try { + atomic.value = atomic + atomic.freeze() + val cycles = GC.detectCycles()!! + assertEquals(1, cycles.size) + assertArrayEquals(arrayOf(atomic, atomic), GC.findCycle(cycles[0])!!) + } finally { + atomic.value = null + } +} diff --git a/kotlin-native/backend.native/tests/runtime/memory/cycles0.kt b/kotlin-native/backend.native/tests/runtime/memory/cycles0.kt new file mode 100644 index 00000000000..b2d09fdec0b --- /dev/null +++ b/kotlin-native/backend.native/tests/runtime/memory/cycles0.kt @@ -0,0 +1,54 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +package runtime.memory.cycles0 + +import kotlin.test.* + +data class Node(val data: Int, var next: Node?, var prev: Node?, val outer: Node?) + +fun makeCycle(len: Int, outer: Node?): Node { + val start = Node(0, null, null, outer) + var prev = start + for (i in 1 .. len - 1) { + prev = Node(i, prev, null, outer) + } + start.next = prev + return start +} + +fun makeDoubleCycle(len: Int): Node { + val start = makeCycle(len, null) + var prev = start + var cur = prev.next + while (cur != start) { + cur!!.prev = prev + prev = cur + cur = cur.next + } + start.prev = prev + return start +} + +fun createCycles(junk: Node) { + val cycle1 = makeCycle(1, junk) + val cycle2 = makeCycle(2, junk) + val cycle10 = makeCycle(10, junk) + val cycle100 = makeCycle(100, junk) + val dcycle1 = makeDoubleCycle(1) + val dcycle2 = makeDoubleCycle(2) + val dcycle10 = makeDoubleCycle(10) + val dcycle100 = makeDoubleCycle(100) + +} + +@Test fun runTest() { + // Create outer link from cyclic garbage. + val outer = Node(42, null, null, null) + createCycles(outer) + kotlin.native.internal.GC.collect() + // Ensure outer is not collected. + println(outer.data) +} diff --git a/kotlin-native/backend.native/tests/runtime/memory/cycles1.kt b/kotlin-native/backend.native/tests/runtime/memory/cycles1.kt new file mode 100644 index 00000000000..ae7572e7b0b --- /dev/null +++ b/kotlin-native/backend.native/tests/runtime/memory/cycles1.kt @@ -0,0 +1,24 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +package runtime.memory.cycles1 + +import kotlin.test.* +import kotlin.native.ref.* + +@Test fun runTest() { + // TODO: make it work in relaxed model as well. + if (Platform.memoryModel == MemoryModel.RELAXED) return + val weakRefToTrashCycle = createLoop() + kotlin.native.internal.GC.collect() + assertNull(weakRefToTrashCycle.get()) +} + +private fun createLoop(): WeakReference { + val loop = Array(1, { null }) + loop[0] = loop + + return WeakReference(loop) +} \ No newline at end of file diff --git a/kotlin-native/backend.native/tests/runtime/memory/escape0.kt b/kotlin-native/backend.native/tests/runtime/memory/escape0.kt new file mode 100644 index 00000000000..5e60deef32c --- /dev/null +++ b/kotlin-native/backend.native/tests/runtime/memory/escape0.kt @@ -0,0 +1,62 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +package runtime.memory.escape0 + +import kotlin.test.* + +//fun foo1(arg: String) : String = foo0(arg) +fun foo1(arg: Any) : Any = foo0(arg) + +fun foo0(arg: Any) : Any = Any() + +var global : Any = Any() + +fun foo0_escape(arg: Any) : Any{ + global = arg + return Any() +} + +class Node(var previous: Node?) + +fun zoo3() : Node { + var current = Node(null) + for (i in 1 .. 5) { + current = Node(current) + } + return current +} + +fun zoo4(arg: Int) : Any { + var a = Any() + var b = Any() + var c = Any() + a = b + val x = 3 + a = when { + x < arg -> b + else -> c + } + return a +} + +fun zoo5(arg: Any) : Any{ + foo1(arg) + return arg +} + +fun zoo6(arg: Any) : Any { + return zoo7(arg, "foo", 11) +} + +fun zoo7(arg1: Any, arg2: Any, selector: Int) : Any { + return if (selector < 2) arg1 else arg2; +} + +@Test fun runTest() { + //val z = zoo7(Any(), Any(), 1) + val x = zoo5(Any()) + //println(bar(foo1(foo2("")), foo2(foo1("")))) +} diff --git a/kotlin-native/backend.native/tests/runtime/memory/escape1.kt b/kotlin-native/backend.native/tests/runtime/memory/escape1.kt new file mode 100644 index 00000000000..07c516aa6a7 --- /dev/null +++ b/kotlin-native/backend.native/tests/runtime/memory/escape1.kt @@ -0,0 +1,23 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +package runtime.memory.escape1 + +import kotlin.test.* + +class B(val s: String) + +class A { + val b = B("zzz") +} + +fun foo(): B { + val a = A() + return a.b +} + +@Test fun runTest() { + println(foo().s) +} \ No newline at end of file diff --git a/kotlin-native/backend.native/tests/runtime/memory/escape2.kt b/kotlin-native/backend.native/tests/runtime/memory/escape2.kt new file mode 100644 index 00000000000..935ff63f4ad --- /dev/null +++ b/kotlin-native/backend.native/tests/runtime/memory/escape2.kt @@ -0,0 +1,33 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +package runtime.memory.escape2 + +import kotlin.test.* + +class A(val s: String) + +class B { + var a: A? = null +} + +class C(val b: B) + +fun foo(c: C) { + c.b.a = A("zzz") +} + +fun bar(b: B) { + val c = C(b) + foo(c) +} + +@ThreadLocal +val global = B() + +@Test fun runTest() { + bar(global) + println(global.a!!.s) +} \ No newline at end of file diff --git a/kotlin-native/backend.native/tests/runtime/memory/leak_memory.kt b/kotlin-native/backend.native/tests/runtime/memory/leak_memory.kt new file mode 100644 index 00000000000..487662fff28 --- /dev/null +++ b/kotlin-native/backend.native/tests/runtime/memory/leak_memory.kt @@ -0,0 +1,5 @@ +import kotlinx.cinterop.* + +fun main() { + StableRef.create(Any()) +} diff --git a/kotlin-native/backend.native/tests/runtime/memory/only_gc.kt b/kotlin-native/backend.native/tests/runtime/memory/only_gc.kt new file mode 100644 index 00000000000..df04646d834 --- /dev/null +++ b/kotlin-native/backend.native/tests/runtime/memory/only_gc.kt @@ -0,0 +1,9 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +fun main(args: Array) { + kotlin.native.internal.GC.collect() +} + diff --git a/kotlin-native/backend.native/tests/runtime/memory/stable_ref_cross_thread_check.kt b/kotlin-native/backend.native/tests/runtime/memory/stable_ref_cross_thread_check.kt new file mode 100644 index 00000000000..7634a3c6a8d --- /dev/null +++ b/kotlin-native/backend.native/tests/runtime/memory/stable_ref_cross_thread_check.kt @@ -0,0 +1,48 @@ +/* + * Copyright 2010-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +package runtime.memory.stable_ref_cross_thread_check + +import kotlin.test.* + +import kotlin.native.concurrent.* +import kotlinx.cinterop.* + +@Test +fun runTest1() { + val worker = Worker.start() + + val future = worker.execute(TransferMode.SAFE, { }) { + StableRef.create(Any()) + } + val ref = future.result + assertFailsWith { + val value = ref.get() + println(value.toString()) + } + + worker.requestTermination().result +} + +@Test +fun runTest2() { + val worker = Worker.start() + + val mainThreadRef = StableRef.create(Any()) + // Simulate this going through interop as raw C pointer. + val pointerValue: Long = mainThreadRef.asCPointer().toLong() + val future = worker.execute(TransferMode.SAFE, { pointerValue }) { + val pointer: COpaquePointer = it.toCPointer()!! + assertFailsWith { + // Even attempting to convert a pointer to StableRef should fail. + val otherThreadRef: StableRef = pointer.asStableRef() + println(otherThreadRef.toString()) + } + Unit + } + future.result + + worker.requestTermination().result +} diff --git a/kotlin-native/backend.native/tests/runtime/memory/throw_cleanup.kt b/kotlin-native/backend.native/tests/runtime/memory/throw_cleanup.kt new file mode 100644 index 00000000000..d96bb6ce00c --- /dev/null +++ b/kotlin-native/backend.native/tests/runtime/memory/throw_cleanup.kt @@ -0,0 +1,25 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +package runtime.memory.throw_cleanup + +import kotlin.test.* + +@Test fun runTest() { + foo(false) + try { + foo(true) + } catch (e: Error) { + println("Ok") + } +} + +fun foo(b: Boolean): Any { + var result = Any() + if (b) { + throw Error() + } + return result +} \ No newline at end of file diff --git a/kotlin-native/backend.native/tests/runtime/memory/var1.kt b/kotlin-native/backend.native/tests/runtime/memory/var1.kt new file mode 100644 index 00000000000..774c02f8d91 --- /dev/null +++ b/kotlin-native/backend.native/tests/runtime/memory/var1.kt @@ -0,0 +1,62 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +package runtime.memory.var1 + +import kotlin.test.* + +class Integer(val value: Int) { + operator fun inc() = Integer(value + 1) +} + +fun foo(x: Any, y: Any) { + x.use() + y.use() +} + +@Test fun runTest1() { + var x = Integer(0) + + for (i in 0..1) { + val c = Integer(0) + if (i == 0) x = c + } + + // x refcount is 1. + + foo(x, ++x) +} + +fun Any?.use() { + var x = this +} + +@kotlin.native.internal.CanBePrecreated +object CompileTime { + + const val int = Int.MIN_VALUE + const val byte = Byte.MIN_VALUE + const val short = Short.MIN_VALUE + const val long = Long.MIN_VALUE + const val boolean = true + const val float = 1.0f + const val double = 1.0 + const val char = Char.MIN_VALUE +} + +class AClass { + companion object {} +} + +@Test fun runTest2() { + assertEquals(Int.MIN_VALUE, CompileTime.int) + assertEquals(Byte.MIN_VALUE, CompileTime.byte) + assertEquals(Short.MIN_VALUE, CompileTime.short) + assertEquals(Long.MIN_VALUE, CompileTime.long) + assertEquals(true, CompileTime.boolean) + assertEquals(1.0f, CompileTime.float) + assertEquals(1.0, CompileTime.double) + assertEquals(Char.MIN_VALUE, CompileTime.char) +} \ No newline at end of file diff --git a/kotlin-native/backend.native/tests/runtime/memory/var2.kt b/kotlin-native/backend.native/tests/runtime/memory/var2.kt new file mode 100644 index 00000000000..690f9a04738 --- /dev/null +++ b/kotlin-native/backend.native/tests/runtime/memory/var2.kt @@ -0,0 +1,31 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +package runtime.memory.var2 + +import kotlin.test.* + +@Test fun runTest() { + var x = Any() + + for (i in 0..1) { + val c = Any() + if (i == 0) x = c + } + + // x refcount is 1. + + val y = try { + x + } finally { + x = Any() + } + + y.use() +} + +fun Any?.use() { + var x = this +} \ No newline at end of file diff --git a/kotlin-native/backend.native/tests/runtime/memory/var3.kt b/kotlin-native/backend.native/tests/runtime/memory/var3.kt new file mode 100644 index 00000000000..08534402ce3 --- /dev/null +++ b/kotlin-native/backend.native/tests/runtime/memory/var3.kt @@ -0,0 +1,33 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +package runtime.memory.var3 + +import kotlin.test.* + +@Test fun runTest() { + foo().use() +} + +fun foo(): Any { + var x = Any() + + for (i in 0..1) { + val c = Any() + if (i == 0) x = c + } + + // x refcount is 1. + + try { + return x + } finally { + x = Any() + } +} + +fun Any?.use() { + var x = this +} \ No newline at end of file diff --git a/kotlin-native/backend.native/tests/runtime/memory/var4.kt b/kotlin-native/backend.native/tests/runtime/memory/var4.kt new file mode 100644 index 00000000000..4e2892a562e --- /dev/null +++ b/kotlin-native/backend.native/tests/runtime/memory/var4.kt @@ -0,0 +1,33 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +package runtime.memory.var4 + +import kotlin.test.* + +@Test fun runTest() { + var x = Error() + + for (i in 0..1) { + val c = Error() + if (i == 0) x = c + } + + // x refcount is 1. + + try { + try { + throw x + } finally { + x = Error() + } + } catch (e: Error) { + e.use() + } +} + +fun Any?.use() { + var x = this +} \ No newline at end of file diff --git a/kotlin-native/backend.native/tests/runtime/memory/weak0.kt b/kotlin-native/backend.native/tests/runtime/memory/weak0.kt new file mode 100644 index 00000000000..b0eac53d4e3 --- /dev/null +++ b/kotlin-native/backend.native/tests/runtime/memory/weak0.kt @@ -0,0 +1,43 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +package runtime.memory.weak0 + +import kotlin.test.* +import kotlin.native.ref.* + +data class Data(val s: String) + +fun localWeak(): WeakReference { + val x = Data("Hello") + val weak = WeakReference(x) + println(weak.get()) + return weak +} + +fun multiWeak(): Array> { + val x = Data("Hello") + val weaks = Array(100, { WeakReference(x) } ) + weaks.forEach { + it -> if (it.get()?.s != "Hello") throw Error("bad reference") + } + return weaks +} + +@Test fun runTest() { + val weak = localWeak() + kotlin.native.internal.GC.collect() + val value = weak.get() + println(value?.toString()) + + val weaks = multiWeak() + + kotlin.native.internal.GC.collect() + + weaks.forEach { + it -> if (it.get()?.s != null) throw Error("not null") + } + println("OK") +} \ No newline at end of file diff --git a/kotlin-native/backend.native/tests/runtime/memory/weak1.kt b/kotlin-native/backend.native/tests/runtime/memory/weak1.kt new file mode 100644 index 00000000000..57dffc65550 --- /dev/null +++ b/kotlin-native/backend.native/tests/runtime/memory/weak1.kt @@ -0,0 +1,32 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +package runtime.memory.weak1 + +import kotlin.test.* +import kotlin.native.ref.* + +class Node(var next: Node?) + +@Test fun runTest1() { + val node1 = Node(null) + val node2 = Node(node1) + node1.next = node2 + + kotlin.native.ref.WeakReference(node1) + println("OK") +} + +@Test fun runTest2() { + val string = "Hello" + val refString = WeakReference(string) + assertEquals(string, refString.value) + val zero = 0 + val refZero = WeakReference(zero) + assertEquals(0, refZero.value) + val long = Long.MAX_VALUE + val refLong = WeakReference(long) + assertEquals(Long.MAX_VALUE, refLong.value) +} diff --git a/kotlin-native/backend.native/tests/runtime/text/chars0.kt b/kotlin-native/backend.native/tests/runtime/text/chars0.kt new file mode 100644 index 00000000000..c2595667244 --- /dev/null +++ b/kotlin-native/backend.native/tests/runtime/text/chars0.kt @@ -0,0 +1,122 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +package runtime.text.chars0 + +import kotlin.test.* + +fun assertTrue(v: Boolean) = if (!v) throw AssertionError() else Unit +fun assertFalse(v: Boolean) = if (v) throw AssertionError() else Unit +fun assertEquals(a: Int, b: Int) { if (a != b) throw AssertionError() } + +fun testIsSupplementaryCodePoint() { + assertFalse(Char.isSupplementaryCodePoint(-1)) + for (c in 0..0xFFFF) { + assertFalse(Char.isSupplementaryCodePoint(c.toInt())) + } + for (c in 0xFFFF + 1..0x10FFFF) { + assertTrue(Char.isSupplementaryCodePoint(c)) + } + assertFalse(Char.isSupplementaryCodePoint(0x10FFFF + 1)) +} + +fun testIsSurrogatePair() { + assertFalse(Char.isSurrogatePair('\u0000', '\u0000')) + assertFalse(Char.isSurrogatePair('\u0000', '\uDC00')) + assertTrue( Char.isSurrogatePair('\uD800', '\uDC00')) + assertTrue( Char.isSurrogatePair('\uD800', '\uDFFF')) + assertTrue( Char.isSurrogatePair('\uDBFF', '\uDFFF')) + assertFalse(Char.isSurrogatePair('\uDBFF', '\uF000')) +} + +fun testToChars() { + assertTrue(charArrayOf('\uD800', '\uDC00').contentEquals(Char.toChars(0x010000))) + assertTrue(charArrayOf('\uD800', '\uDC01').contentEquals(Char.toChars(0x010001))) + assertTrue(charArrayOf('\uD801', '\uDC01').contentEquals(Char.toChars(0x010401))) + assertTrue(charArrayOf('\uDBFF', '\uDFFF').contentEquals(Char.toChars(0x10FFFF))) + + try { + Char.toChars(Int.MAX_VALUE) + throw AssertionError() + } catch (e: IllegalArgumentException) {} +} + +fun testToCodePoint() { + assertEquals(0x010000, Char.toCodePoint('\uD800', '\uDC00')) + assertEquals(0x010001, Char.toCodePoint('\uD800', '\uDC01')) + assertEquals(0x010401, Char.toCodePoint('\uD801', '\uDC01')) + assertEquals(0x10FFFF, Char.toCodePoint('\uDBFF', '\uDFFF')) +} + +// TODO: Uncomment when such operations are supported for supplementary codepoints and the API is public. +fun testCase() { + /* + assertEquals('A'.toInt(), Char.toUpperCase('a'.toInt())) + assertEquals('A'.toInt(), Char.toUpperCase('A'.toInt())) + assertEquals('1'.toInt(), Char.toUpperCase('1'.toInt())) + + assertEquals('a'.toInt(), Char.toLowerCase('A'.toInt())) + assertEquals('a'.toInt(), Char.toLowerCase('a'.toInt())) + assertEquals('1'.toInt(), Char.toLowerCase('1'.toInt())) + + assertEquals(0x010400, Char.toUpperCase(0x010428)) + assertEquals(0x010400, Char.toUpperCase(0x010400)) + assertEquals(0x10FFFF, Char.toUpperCase(0x10FFFF)) + assertEquals(0x110000, Char.toUpperCase(0x110000)) + + assertEquals(0x010428, Char.toLowerCase(0x010400)) + assertEquals(0x010428, Char.toLowerCase(0x010428)) + assertEquals(0x10FFFF, Char.toLowerCase(0x10FFFF)) + assertEquals(0x110000, Char.toLowerCase(0x110000)) + */ +} + +fun testCategory() { + assertEquals('\n'.category.value, CharCategory.CONTROL.value) + assertEquals('1'.category.value, CharCategory.DECIMAL_DIGIT_NUMBER.value) + assertEquals(' '.category.value, CharCategory.SPACE_SEPARATOR.value) + assertEquals('a'.category.value, CharCategory.LOWERCASE_LETTER.value) + assertEquals('A'.category.value, CharCategory.UPPERCASE_LETTER.value) + assertEquals('<'.category.value, CharCategory.MATH_SYMBOL.value) + assertEquals(';'.category.value, CharCategory.OTHER_PUNCTUATION.value) + assertEquals('_'.category.value, CharCategory.CONNECTOR_PUNCTUATION.value) + assertEquals('$'.category.value, CharCategory.CURRENCY_SYMBOL.value) + assertEquals('\u2029'.category.value, CharCategory.PARAGRAPH_SEPARATOR.value) + + assertTrue('\n' in CharCategory.CONTROL) + assertTrue('1' in CharCategory.DECIMAL_DIGIT_NUMBER) + assertTrue(' ' in CharCategory.SPACE_SEPARATOR) + assertTrue('a' in CharCategory.LOWERCASE_LETTER) + assertTrue('A' in CharCategory.UPPERCASE_LETTER) + assertTrue('<' in CharCategory.MATH_SYMBOL) + assertTrue(';' in CharCategory.OTHER_PUNCTUATION) + assertTrue('_' in CharCategory.CONNECTOR_PUNCTUATION) + assertTrue('$' in CharCategory.CURRENCY_SYMBOL) + assertTrue('\u2029' in CharCategory.PARAGRAPH_SEPARATOR) + + try { + CharCategory.valueOf(-1) + throw AssertionError() + } catch (e: IllegalArgumentException) {} + + try { + CharCategory.valueOf(31) + throw AssertionError() + } catch (e: IllegalArgumentException) {} + + try { + CharCategory.valueOf(17) + throw AssertionError() + } catch (e: IllegalArgumentException) {} +} + +@Test fun runTest() { + testIsSurrogatePair() + testToChars() + testToCodePoint() + testIsSupplementaryCodePoint() + testCase() + testCategory() +} \ No newline at end of file diff --git a/kotlin-native/backend.native/tests/runtime/text/indexof.kt b/kotlin-native/backend.native/tests/runtime/text/indexof.kt new file mode 100644 index 00000000000..6e44c6891cd --- /dev/null +++ b/kotlin-native/backend.native/tests/runtime/text/indexof.kt @@ -0,0 +1,38 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +package runtime.text.indexof + +import kotlin.test.* + +@Test fun runTest() { + var str = "Hello World!!" // for indexOf String + var ch = 'a' // for indexOf Char + + assertEquals(6, str.indexOf("World", 0)) + assertEquals(6, str.indexOf("World", -1)) + + assertEquals(-1, str.indexOf(ch, 0)) + + str = "Kotlin/Native" + assertEquals(-1, str.indexOf("/", str.length + 1)) + assertEquals(-1, str.indexOf("/", Int.MAX_VALUE)) + assertEquals(str.length, str.indexOf("", Int.MAX_VALUE)) + assertEquals(1, str.indexOf("", 1)) + + assertEquals(8, str.indexOf(ch, 1)) + assertEquals(-1, str.indexOf(ch, str.length - 1)) + + str = "" + assertEquals(-1, str.indexOf("a", -3)) + assertEquals(0, str.indexOf("", 0)) + + assertEquals(-1, str.indexOf(ch, -3)) + assertEquals(-1, str.indexOf(ch, 10)) + + ch = 0.toChar() + assertEquals(-1, str.indexOf(ch, -3)) + assertEquals(-1, str.indexOf(ch, 10)) +} \ No newline at end of file diff --git a/kotlin-native/backend.native/tests/runtime/text/parse0.kt b/kotlin-native/backend.native/tests/runtime/text/parse0.kt new file mode 100644 index 00000000000..fed2f3d4c99 --- /dev/null +++ b/kotlin-native/backend.native/tests/runtime/text/parse0.kt @@ -0,0 +1,25 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +package runtime.text.parse0 + +import kotlin.test.* + +@Test fun runTest() { + println("false".toBoolean()) + println("true".toBoolean()) + println("-1".toByte()) + println("a".toByte(16)) + println("aa".toShort(16)) + println("11110".toInt(2)) + println("ffffffff".toLong(16)) + try { + val x = "ffffffff".toLong(10) + } catch (ne: NumberFormatException) { + println("bad format") + } + println("0.5".toFloat()) + println("2.39".toDouble()) +} \ No newline at end of file diff --git a/kotlin-native/backend.native/tests/runtime/text/string0.kt b/kotlin-native/backend.native/tests/runtime/text/string0.kt new file mode 100644 index 00000000000..b4d5eb55ec6 --- /dev/null +++ b/kotlin-native/backend.native/tests/runtime/text/string0.kt @@ -0,0 +1,19 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +package runtime.text.string0 + +import kotlin.test.* + +@Test fun runTest() { + val str = "hello" + println(str.equals("HElLo", true)) + val strI18n = "Привет" + println(strI18n.equals("прИВет", true)) + println(strI18n.toUpperCase()) + println(strI18n.toLowerCase()) + println("пока".capitalize()) + println("http://jetbrains.com".startsWith("http://")) +} \ No newline at end of file diff --git a/kotlin-native/backend.native/tests/runtime/text/string_builder0.kt b/kotlin-native/backend.native/tests/runtime/text/string_builder0.kt new file mode 100644 index 00000000000..36b3ed2b7a7 --- /dev/null +++ b/kotlin-native/backend.native/tests/runtime/text/string_builder0.kt @@ -0,0 +1,280 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +package runtime.text.string_builder0 + +import kotlin.test.* + +// Utils ==================================================================================================== +fun assertTrue(cond: Boolean) { + if (!cond) + throw AssertionError("Condition expected to be true") +} + +fun assertFalse(cond: Boolean) { + if (cond) + throw AssertionError("Condition expected to be false") +} + +fun assertEquals(value1: String, value2: String) { + if (value1 != value2) + throw AssertionError("FAIL: '" + value1 + "' != '" + value2 + "'") +} + +fun assertEquals(value1: Int, value2: Int) { + if (value1 != value2) + throw AssertionError("FAIL" + value1.toString() + " != " + value2.toString()) +} + +fun assertEquals(builder: StringBuilder, content: String) = assertEquals(builder.toString(), content) + +// IndexOutOfBoundsException. +fun assertException(body: () -> Unit) { + try { + body() + throw AssertionError ("Test failed: no IndexOutOfBoundsException on wrong indices") + } catch (e: IndexOutOfBoundsException) { + } catch (e: IllegalArgumentException) {} +} + +// Insert =================================================================================================== +fun testInsertString(initial: String, index: Int, toInsert: String, expected: String) { + assertEquals(StringBuilder(initial).insert(index, toInsert), expected) + assertEquals(StringBuilder(initial).insert(index, toInsert.toCharArray()), expected) + assertEquals(StringBuilder(initial).insert(index, toInsert as CharSequence), expected) +} + +fun testInsertStringException(initial: String, index: Int, toInsert: String) { + assertException { StringBuilder(initial).insert(index, toInsert) } + assertException { StringBuilder(initial).insert(index, toInsert.toCharArray()) } + assertException { StringBuilder(initial).insert(index, toInsert as CharSequence) } +} + +fun testInsertSingle(value: Byte) { + assertEquals(StringBuilder("abcd").insert(0, value), value.toString() + "abcd") + assertEquals(StringBuilder("abcd").insert(4, value), "abcd" + value.toString()) + assertEquals(StringBuilder("abcd").insert(2, value), "ab" + value.toString() + "cd") + assertEquals(StringBuilder("").insert(0, value), value.toString()) +} + +fun testInsertSingle(value: Short) { + assertEquals(StringBuilder("abcd").insert(0, value), value.toString() + "abcd") + assertEquals(StringBuilder("abcd").insert(4, value), "abcd" + value.toString()) + assertEquals(StringBuilder("abcd").insert(2, value), "ab" + value.toString() + "cd") + assertEquals(StringBuilder("").insert(0, value), value.toString()) +} + +fun testInsertSingle(value: Int) { + assertEquals(StringBuilder("abcd").insert(0, value), value.toString() + "abcd") + assertEquals(StringBuilder("abcd").insert(4, value), "abcd" + value.toString()) + assertEquals(StringBuilder("abcd").insert(2, value), "ab" + value.toString() + "cd") + assertEquals(StringBuilder("").insert(0, value), value.toString()) +} + +fun testInsertSingle(value: Long) { + assertEquals(StringBuilder("abcd").insert(0, value), value.toString() + "abcd") + assertEquals(StringBuilder("abcd").insert(4, value), "abcd" + value.toString()) + assertEquals(StringBuilder("abcd").insert(2, value), "ab" + value.toString() + "cd") + assertEquals(StringBuilder("").insert(0, value), value.toString()) +} + +fun testInsertSingle(value: Float) { + assertEquals(StringBuilder("abcd").insert(0, value), value.toString() + "abcd") + assertEquals(StringBuilder("abcd").insert(4, value), "abcd" + value.toString()) + assertEquals(StringBuilder("abcd").insert(2, value), "ab" + value.toString() + "cd") + assertEquals(StringBuilder("").insert(0, value), value.toString()) +} + +fun testInsertSingle(value: Double) { + assertEquals(StringBuilder("abcd").insert(0, value), value.toString() + "abcd") + assertEquals(StringBuilder("abcd").insert(4, value), "abcd" + value.toString()) + assertEquals(StringBuilder("abcd").insert(2, value), "ab" + value.toString() + "cd") + assertEquals(StringBuilder("").insert(0, value), value.toString()) +} + +fun testInsertSingle(value: Any?) { + assertEquals(StringBuilder("abcd").insert(0, value), value.toString() + "abcd") + assertEquals(StringBuilder("abcd").insert(4, value), "abcd" + value.toString()) + assertEquals(StringBuilder("abcd").insert(2, value), "ab" + value.toString() + "cd") + assertEquals(StringBuilder("").insert(0, value), value.toString()) +} + +fun testInsertSingle(value: Char) { + assertEquals(StringBuilder("abcd").insert(0, value), value.toString() + "abcd") + assertEquals(StringBuilder("abcd").insert(4, value), "abcd" + value.toString()) + assertEquals(StringBuilder("abcd").insert(2, value), "ab" + value.toString() + "cd") + assertEquals(StringBuilder("").insert(0, value), value.toString()) +} + +fun testInsert() { + // String/CharSequence/CharArray. + testInsertString("abcd", 0, "12", "12abcd") + testInsertString("abcd", 4, "12", "abcd12") + testInsertString("abcd", 2, "12", "ab12cd") + testInsertString("", 0, "12", "12") + testInsertStringException("a", -1, "1") + testInsertStringException("a", 2, "1") + + // Null inserting. + assertEquals(StringBuilder("abcd").insert(0, null as CharSequence?), "nullabcd") + assertEquals(StringBuilder("abcd").insert(4, null as CharSequence?), "abcdnull") + assertEquals(StringBuilder("abcd").insert(2, null as CharSequence?), "abnullcd") + assertEquals(StringBuilder("").insert(0, null as CharSequence?), "null") + + // Subsequence of CharSequence. + // Insert in the beginning. + assertEquals(StringBuilder("abcd").insert(0, "1234", 0, 0), "abcd") // 0 symbols + assertEquals(StringBuilder("abcd").insert(0, "1234", 0, 1), "1abcd") // 1 symbol + assertEquals(StringBuilder("abcd").insert(0, "1234", 1, 3), "23abcd") // 2 symbols + assertEquals(StringBuilder("abcd").insert(0, null as CharSequence?, 1, 3), "ulabcd") // 2 symbols of null + + // Insert in the end. + assertEquals(StringBuilder("abcd").insert(4, "1234", 0, 0), "abcd") + assertEquals(StringBuilder("abcd").insert(4, "1234", 0, 1), "abcd1") + assertEquals(StringBuilder("abcd").insert(4, "1234", 1, 3), "abcd23") + assertEquals(StringBuilder("abcd").insert(4, null as CharSequence?, 1, 3), "abcdul") + + // Insert in the middle. + assertEquals(StringBuilder("abcd").insert(2, "1234", 0, 0), "abcd") + assertEquals(StringBuilder("abcd").insert(2, "1234", 0, 1), "ab1cd") + assertEquals(StringBuilder("abcd").insert(2, "1234", 1, 3), "ab23cd") + assertEquals(StringBuilder("abcd").insert(2, null as CharSequence?, 1, 3), "abulcd") + + // Incorrect indices. + assertException { StringBuilder("a").insert(-1, "1", 0, 0) } + assertException { StringBuilder("a").insert(2, "1", 0, 0) } + assertException { StringBuilder("a").insert(1, "1", -1, 0) } + assertException { StringBuilder("a").insert(1, "1", 0, 2) } + assertException { StringBuilder("a").insert(1, "123", 2, 0) } + + // Other types. + testInsertSingle(true) + testInsertSingle(42.toByte()) + testInsertSingle(42.toShort()) + testInsertSingle(42.toInt()) + testInsertSingle(42.toLong()) + testInsertSingle(42.2.toFloat()) + testInsertSingle(42.2.toDouble()) + testInsertSingle(object { + override fun toString(): String { + return "Object" + } + }) + testInsertSingle('a') +} + +// Reverse ================================================================================================== +fun testReverse(original: String, reversed: String, reversedBack: String) { + assertEquals(StringBuilder(original).reverse(), reversed) + assertEquals(StringBuilder(reversed).reverse(), reversedBack) +} + +fun testReverse() { + var builder = StringBuilder("123456") + assertTrue(builder === builder.reverse()) + assertEquals(builder, "654321") + + builder.setLength(1) + assertEquals(builder, "6") + + builder.setLength(0) + assertEquals(builder, "") + + var str: String = "a" + testReverse(str, str, str) + + str = "ab" + testReverse(str, "ba", str) + + str = "abcdef" + testReverse(str, "fedcba", str) + + str = "abcdefg" + testReverse(str, "gfedcba", str) + + str = "\ud800\udc00" + testReverse(str, str, str) + + str = "\udc00\ud800" + testReverse(str, "\ud800\udc00", "\ud800\udc00") + + str = "a\ud800\udc00" + testReverse(str, "\ud800\udc00a", str) + + str = "ab\ud800\udc00" + testReverse(str, "\ud800\udc00ba", str) + + str = "abc\ud800\udc00" + testReverse(str, "\ud800\udc00cba", str) + + str = "\ud800\udc00\udc01\ud801\ud802\udc02" + testReverse(str, "\ud802\udc02\ud801\udc01\ud800\udc00", + "\ud800\udc00\ud801\udc01\ud802\udc02") + + str = "\ud800\udc00\ud801\udc01\ud802\udc02" + testReverse(str, "\ud802\udc02\ud801\udc01\ud800\udc00", str) + + str = "\ud800\udc00\udc01\ud801a" + testReverse(str, "a\ud801\udc01\ud800\udc00", + "\ud800\udc00\ud801\udc01a") + + str = "a\ud800\udc00\ud801\udc01" + testReverse(str, "\ud801\udc01\ud800\udc00a", str) + + str = "\ud800\udc00\udc01\ud801ab" + testReverse(str, "ba\ud801\udc01\ud800\udc00", + "\ud800\udc00\ud801\udc01ab") + + str = "ab\ud800\udc00\ud801\udc01" + testReverse(str, "\ud801\udc01\ud800\udc00ba", str) + + str = "\ud800\udc00\ud801\udc01" + testReverse(str, "\ud801\udc01\ud800\udc00", str) + + str = "a\ud800\udc00z\ud801\udc01" + testReverse(str, "\ud801\udc01z\ud800\udc00a", str) + + str = "a\ud800\udc00bz\ud801\udc01" + testReverse(str, "\ud801\udc01zb\ud800\udc00a", str) + + str = "abc\ud802\udc02\ud801\udc01\ud800\udc00" + testReverse(str, "\ud800\udc00\ud801\udc01\ud802\udc02cba", str) + + str = "abcd\ud802\udc02\ud801\udc01\ud800\udc00" + testReverse(str, "\ud800\udc00\ud801\udc01\ud802\udc02dcba", str) +} + +// Basic ==================================================================================================== +fun testBasic() { + val sb = StringBuilder() + assertEquals(0, sb.length) + assertEquals("", sb.toString()) + sb.append(1) + assertEquals(1, sb.length) + assertEquals("1", sb.toString()) + sb.append(", ") + assertEquals(3, sb.length) + assertEquals("1, ", sb.toString()) + sb.append(true) + assertEquals(7, sb.length) + assertEquals("1, true", sb.toString()) + sb.append(12345678L) + assertEquals(15, sb.length) + assertEquals("1, true12345678", sb.toString()) + sb.append(null as CharSequence?) + assertEquals(19, sb.length) + assertEquals("1, true12345678null", sb.toString()) + + sb.setLength(0) + assertEquals(0, sb.length) + assertEquals("", sb.toString()) +} + +@Test fun runTest() { + testBasic() + testInsert() + testReverse() + println("OK") +} \ No newline at end of file diff --git a/kotlin-native/backend.native/tests/runtime/text/string_builder1.kt b/kotlin-native/backend.native/tests/runtime/text/string_builder1.kt new file mode 100644 index 00000000000..bd783f99441 --- /dev/null +++ b/kotlin-native/backend.native/tests/runtime/text/string_builder1.kt @@ -0,0 +1,14 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +package runtime.text.string_builder1 + +import kotlin.test.* + +@Test fun runTest() { + val a = StringBuilder() + a.append("Hello").appendln("Kotlin").appendln(42).appendln(0.1).appendln(true) + println(a.toString()) +} diff --git a/kotlin-native/backend.native/tests/runtime/text/to_string0.kt b/kotlin-native/backend.native/tests/runtime/text/to_string0.kt new file mode 100644 index 00000000000..573dce8ef38 --- /dev/null +++ b/kotlin-native/backend.native/tests/runtime/text/to_string0.kt @@ -0,0 +1,50 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +package runtime.text.to_string0 + +import kotlin.test.* + +// Based on Apache Harmony tests. + +fun assertEquals(actual: String, expected: String, msg: String) { + if (actual != expected) throw AssertionError("$msg. Actual: $actual. Expected: $expected") +} + +fun testIntToStringWithRadix() { + assertEquals(2147483647.toString(8), "17777777777", "Octal string") + assertEquals(2147483647.toString(16), "7fffffff", "Hex string") + assertEquals(2147483647.toString(2), "1111111111111111111111111111111", "Binary string") + assertEquals(2147483647.toString(10), "2147483647", "Decimal string") + + assertEquals((-2147483647).toString(8), "-17777777777", "Octal string") + assertEquals((-2147483647).toString(16), "-7fffffff", "Hex string") + assertEquals((-2147483647).toString(2), "-1111111111111111111111111111111", "Binary string") + assertEquals((-2147483647).toString(10), "-2147483647", "Decimal string") + + assertEquals((-2147483648).toString(8), "-20000000000", "Octal string") + assertEquals((-2147483648).toString(16), "-80000000", "Hex string") + assertEquals((-2147483648).toString(2), "-10000000000000000000000000000000", "Binary string") + assertEquals((-2147483648).toString(10), "-2147483648", "Decimal string") +} + +fun testLongToStringWithRadix() { + assertEquals(100000000L.toString(10), "100000000", "Decimal string") + assertEquals(68719476735L.toString(16), "fffffffff", "Hex string") + assertEquals(8589934591L.toString(8), "77777777777", "Octal string") + assertEquals(8796093022207L.toString(2), "1111111111111111111111111111111111111111111", "Binary string") + + assertEquals((-0x7fffffffffffffffL - 1).toString(10), "-9223372036854775808", "Min decimal string") + assertEquals(0x7fffffffffffffffL.toString(10), "9223372036854775807", "Max decimal string") + assertEquals((-0x7fffffffffffffffL - 1).toString(16), "-8000000000000000", "Min hex string") + assertEquals(0x7fffffffffffffffL.toString(16), "7fffffffffffffff", "Max hex string") + +} + +@Test fun runTest() { + testIntToStringWithRadix() + testLongToStringWithRadix() + println("OK") +} \ No newline at end of file diff --git a/kotlin-native/backend.native/tests/runtime/text/trim.kt b/kotlin-native/backend.native/tests/runtime/text/trim.kt new file mode 100644 index 00000000000..0fd5c149139 --- /dev/null +++ b/kotlin-native/backend.native/tests/runtime/text/trim.kt @@ -0,0 +1,54 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +package runtime.text.trim + +import kotlin.test.* + +/** + * Tests correct conversions of floats/doubles along with trimming of leading/trailing whitespaces. + * String.trim() trims all whitespaces (see kotlin/text/Strings.kt) while String.toFloat() uses + * the same approach as java.lang.Float.parseFloat() + */ +@Test fun runTest() { + convertToFloatingPoint() + convertWithWhitespaces() + trimWhitespaces() + + println("OK") +} + +private fun convertToFloatingPoint() { + assertEquals(expected = 3.14F, actual = " 3.14 ".toFloat(), message = "String float should be trimmed") + assertEquals(expected = 3.14, actual = " 3.14 ".toDouble(), message = "String double should be trimmed") + assertEquals(expected = 7.15F, actual = "\u0019 7.15 ".toFloat(), message = "String float should be trimmed") + assertEquals(expected = 42.3, actual = "\n 42.3 ".toDouble(), message = "String double should be trimmed") +} + +private fun convertWithWhitespaces() { + val s = "\u0009 \u000A 2.71 \u000D" + assertEquals(expected = 2.71F, actual = s.toFloat(), + message = "String should be cleared of LF, CR, TAB and converted to Float") + assertEquals(expected = 2.71, actual = s.toDouble(), + message = "String should be cleared of LF, CR, TAB and converted to Double") + + // Special symbols should not be trimmed during String to Float/Double conversion + assertFailsWith { "\u202F3.14".toFloat() } + assertFailsWith { "\u20293.14".toDouble() } + assertFailsWith { "3.14\u200B".toDouble() } + assertFailsWith { "3.14\u200B ABC".toDouble() } +} + +private fun trimWhitespaces() { + assertEquals(expected = "String", actual = " String".trim(), message = "Trim leading spaces") + assertEquals(expected = "String ", actual = " String ".trimStart(), message = "Trim start") + assertEquals(expected = " String", actual = " String \t ".trimEnd(), message = "Trim end") + + assertEquals(expected = "String", actual = "\u0020 \u202FString\u2028\u2029".trim(), + message = "Trim special whitespaces") + assertEquals(expected = "\u1FFFString", actual = "\u0085 \u1FFFString".trim(), + message = "Trim special whitespace but should left a unicode symbol") + assertEquals(expected = "String\tSTR", actual = " \nString\tSTR ".trim(), message = "Trim newline") +} diff --git a/kotlin-native/backend.native/tests/runtime/text/utf8.kt b/kotlin-native/backend.native/tests/runtime/text/utf8.kt new file mode 100644 index 00000000000..ffbeabf8ccc --- /dev/null +++ b/kotlin-native/backend.native/tests/runtime/text/utf8.kt @@ -0,0 +1,476 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +package runtime.text.utf8 + +import kotlin.test.* +import kotlin.reflect.KClass +import kotlinx.cinterop.toKString + +// -------------------------------------- Utils -------------------------------------- +fun assertEquals(expected: ByteArray, actual: ByteArray, message: String) = + assertTrue(expected.contentEquals(actual), message) + + +fun checkUtf16to8(string: String, expected: IntArray, conversion: String.() -> ByteArray) { + expected.forEach { + assertTrue(it in Byte.MIN_VALUE..Byte.MAX_VALUE, "Expected array contains illegal values") + } + val expectedBytes = ByteArray(expected.size) { i -> expected[i].toByte() } + val actual = string.conversion() + assertEquals(expectedBytes, actual, """ + Assert failed for string: $string + Expected: ${expected.joinToString()} + Actual: ${actual.joinToString()} + """.trimIndent()) +} + +// Utils for checking successful UTF-16 to UTF-8 conversion. +fun checkUtf16to8Replacing(string: String, expected: IntArray) { + checkUtf16to8(string, expected) { encodeToByteArray() } +} +fun checkUtf16to8Throwing(string: String, expected: IntArray) { + checkUtf16to8(string, expected) { encodeToByteArray(throwOnInvalidSequence = true) } +} +fun checkValidUtf16to8(string: String, expected: IntArray) { + checkUtf16to8Replacing(string, expected) + checkUtf16to8Throwing(string, expected) +} + +fun checkUtf16to8Replacing(string: String, expected: IntArray, start: Int, size: Int) { + checkUtf16to8(string, expected) { encodeToByteArray(start, start + size) } +} +fun checkUtf16to8Throwing(string: String, expected: IntArray, start: Int, size: Int) { + checkUtf16to8(string, expected) { encodeToByteArray(start, start + size, true) } +} +fun checkValidUtf16to8(string: String, expected: IntArray, start: Int, size: Int) { + checkUtf16to8Replacing(string, expected, start, size) + checkUtf16to8Throwing(string, expected, start, size) +} + + +// Utils for checking successful UTF-8 to UTF-16 conversion. +fun checkUtf8to16(expected: String, array: IntArray, conversion: ByteArray.() -> String) { + array.forEach { + assertTrue(it in Byte.MIN_VALUE..Byte.MAX_VALUE, "Expected array contains illegal values") + } + val arrayBytes = ByteArray(array.size) { i -> array[i].toByte() } + val actual = arrayBytes.conversion() + assertEquals(expected, actual, """ + Assert failed for string: $expected + Expected: $expected + Actual: $actual + """.trimIndent()) +} + +fun checkZeroTerminatedUtf8to16Replacing(expected: String, array: IntArray) { + checkUtf8to16(expected, array) { toKString() } + checkUtf8to16(expected, array.copyOf(array.size + 1)) { toKString() } +} +fun checkUtf8to16Replacing(expected: String, array: IntArray) { + checkUtf8to16(expected, array) { decodeToString() } + checkZeroTerminatedUtf8to16Replacing(expected, array) +} +fun checkZeroTerminatedUtf8to16Throwing(expected: String, array: IntArray) { + checkUtf8to16(expected, array) { toKString(throwOnInvalidSequence = true) } + checkUtf8to16(expected, array.copyOf(array.size + 1)) { toKString(throwOnInvalidSequence = true) } +} +fun checkUtf8to16Throwing(expected: String, array: IntArray) { + checkUtf8to16(expected, array) { decodeToString(throwOnInvalidSequence = true) } + checkZeroTerminatedUtf8to16Throwing(expected, array) +} +fun checkValidUtf8to16(expected: String, array: IntArray) { + checkUtf8to16Replacing(expected, array) + checkUtf8to16Throwing(expected, array) +} +fun checkValidZeroTerminatedUtf8to16(expected: String, array: IntArray) { + checkZeroTerminatedUtf8to16Replacing(expected, array) + checkZeroTerminatedUtf8to16Throwing(expected, array) +} + +fun checkZeroTerminatedUtf8to16Replacing(expected: String, array: IntArray, start: Int, size: Int) { + checkUtf8to16(expected, array) { toKString(start, start + size) } + checkUtf8to16(expected, array.copyOf(array.size + 1)) { toKString(start, start + size) } +} +fun checkUtf8to16Replacing(expected: String, array: IntArray, start: Int, size: Int) { + checkUtf8to16(expected, array) { decodeToString(start, start + size) } + checkZeroTerminatedUtf8to16Replacing(expected, array, start, size) +} +fun checkZeroTerminatedUtf8to16Throwing(expected: String, array: IntArray, start: Int, size: Int) { + checkUtf8to16(expected, array) { toKString(start, start + size, true) } + checkUtf8to16(expected, array.copyOf(array.size + 1)) { toKString(start, start + size, true) } +} +fun checkUtf8to16Throwing(expected: String, array: IntArray, start: Int, size: Int) { + checkUtf8to16(expected, array) { decodeToString(start, start + size, true) } + checkZeroTerminatedUtf8to16Throwing(expected, array, start, size) +} +fun checkValidUtf8to16(expected: String, array: IntArray, start: Int, size: Int) { + checkUtf8to16Replacing(expected, array, start, size) + checkUtf8to16Throwing(expected, array, start, size) +} +fun checkValidZeroTerminatedUtf8to16(expected: String, array: IntArray, start: Int, size: Int) { + checkZeroTerminatedUtf8to16Replacing(expected, array, start, size) + checkZeroTerminatedUtf8to16Throwing(expected, array, start, size) +} + + +// Utils for checking malformed UTF-16 to UTF-8 conversion. +fun checkThrows(e: KClass, string: String, action: () -> Unit) { + var exception: Throwable? = null + try { + action() + } catch (e: Throwable) { + exception = e + } + assertNotNull(exception, "No exception was thrown for string: $string") + assertTrue(e.isInstance(exception),""" + Wrong exception was thrown for string: $string + Expected: ${e.qualifiedName} + Actual: ${exception::class.qualifiedName}: $exception} + """.trimIndent()) +} + +fun checkUtf16to8Throws(string: String) { + checkThrows(CharacterCodingException::class, string) { string.encodeToByteArray(throwOnInvalidSequence = true) } +} +fun checkUtf16to8Throws(string: String, start: Int, size: Int) { + checkThrows(CharacterCodingException::class, string) { string.encodeToByteArray(start, start + size, true) } +} + + +// Utils for checking malformed UTF-8 to UTF-16 conversion. +fun checkUtf8to16Throws(e: KClass, string: String, array: IntArray, conversion: ByteArray.() -> String) + = checkThrows(e, string) { + array.forEach { + assertTrue(it in Byte.MIN_VALUE..Byte.MAX_VALUE, "Expected array contains illegal values") + } + val arrayBytes = ByteArray(array.size) { i -> array[i].toByte() } + arrayBytes.conversion() +} + +fun checkZeroTerminatedUtf8to16Throws(string: String, array: IntArray) { + checkUtf8to16Throws(CharacterCodingException::class, string, array) { toKString(throwOnInvalidSequence = true) } + checkUtf8to16Throws(CharacterCodingException::class, string, array.copyOf(array.size + 1)) { toKString(throwOnInvalidSequence = true) } +} +fun checkUtf8to16Throws(string: String, array: IntArray) { + checkUtf8to16Throws(CharacterCodingException::class, string, array) { decodeToString(throwOnInvalidSequence = true) } + checkZeroTerminatedUtf8to16Throws(string, array) +} +fun checkZeroTerminatedUtf8to16Throws(string: String, array: IntArray, start: Int, size: Int) { + checkUtf8to16Throws(CharacterCodingException::class, string, array) { toKString(start, start + size, true) } + checkUtf8to16Throws(CharacterCodingException::class, string, array.copyOf(array.size + 1)) { toKString(start, start + size, true) } +} +fun checkUtf8to16Throws(string: String, array: IntArray, start: Int, size: Int) { + checkUtf8to16Throws(CharacterCodingException::class, string, array) { decodeToString(start, start + size, true) } + checkZeroTerminatedUtf8to16Throws(string, array, start, size) +} + + +// Utils for checking String to floating-point number conversion. +fun checkDoubleConversionThrows(string: String) = checkThrows(NumberFormatException::class, string) { + string.toDouble() +} + +fun checkFloatConversionThrows(string: String) = checkThrows(NumberFormatException::class, string) { + string.toFloat() +} + + +// Utils for checking invalid-bounds-exception thrown by UTF-16 to UTF-8 conversion. +fun checkOutOfBoundsUtf16to8Replacing(e: KClass, string: String, start: Int, size: Int) { + checkThrows(e, string) { string.encodeToByteArray(start, start + size) } +} +fun checkOutOfBoundsUtf16to8Throwing(e: KClass, string: String, start: Int, size: Int) { + checkThrows(e, string) { string.encodeToByteArray(start, start + size, true) } +} +fun checkOutOfBoundsUtf16to8(e: KClass, string: String, start: Int, size: Int) { + checkOutOfBoundsUtf16to8Replacing(e, string, start, size) + checkOutOfBoundsUtf16to8Throwing(e, string, start, size) +} + + +// Utils for checking invalid-bounds-exception thrown by UTF-8 to UTF-16 conversion. +fun checkOutOfBoundsZeroTerminatedUtf8to16Replacing(e: KClass, string: String, byteArray: ByteArray, start: Int, size: Int) { + checkThrows(e, string) { byteArray.toKString(start, start + size) } +} +fun checkOutOfBoundsUtf8to16Replacing(e: KClass, string: String, byteArray: ByteArray, start: Int, size: Int) { + checkThrows(e, string) { byteArray.decodeToString(start, start + size) } + checkOutOfBoundsZeroTerminatedUtf8to16Replacing(e, string, byteArray, start, size) +} +fun checkOutOfBoundsZeroTerminatedUtf8to16Throwing(e: KClass, string: String, byteArray: ByteArray, start: Int, size: Int) { + checkThrows(e, string) { byteArray.toKString(start, start + size, true) } +} +fun checkOutOfBoundsUtf8to16Throwing(e: KClass, string: String, byteArray: ByteArray, start: Int, size: Int) { + checkThrows(e, string) { byteArray.decodeToString(start, start + size, true) } + checkOutOfBoundsZeroTerminatedUtf8to16Throwing(e, string, byteArray, start, size) +} +fun checkOutOfBoundsUtf8to16(e: KClass, string: String, byteArray: ByteArray, start: Int, size: Int) { + checkOutOfBoundsUtf8to16Replacing(e, string, byteArray, start, size) + checkOutOfBoundsUtf8to16Throwing(e, string, byteArray, start, size) +} +fun checkOutOfBoundsZeroTerminatedUtf8to16(e: KClass, string: String, byteArray: ByteArray, start: Int, size: Int) { + checkOutOfBoundsZeroTerminatedUtf8to16Replacing(e, string, byteArray, start, size) + checkOutOfBoundsZeroTerminatedUtf8to16Throwing(e, string, byteArray, start, size) +} + + +// Util for performing action on result of UTF-8 to UTF-16 conversion. +fun convertUtf8to16(byteArray: ByteArray, action: (String) -> Unit) { + byteArray.decodeToString().let { action(it) } + byteArray.toKString().let { action(it) } +} + +// ------------------------- Test UTF-16 to UTF-8 conversion ------------------------- +fun test16to8() { + // Valid strings. + checkValidUtf16to8("Hello", intArrayOf('H'.toInt(), 'e'.toInt(), 'l'.toInt(), 'l'.toInt(), 'o'.toInt())) + checkValidUtf16to8("Привет", intArrayOf(-48, -97, -47, -128, -48, -72, -48, -78, -48, -75, -47, -126)) + checkValidUtf16to8("\uD800\uDC00", intArrayOf(-16, -112, -128, -128)) + checkValidUtf16to8("", intArrayOf()) + + // Test manual conversion with replacement. + // Illegal surrogate pair -> replace with default + checkUtf16to8Replacing("\uDC00\uD800", intArrayOf(-17, -65, -67, -17, -65, -67)) + // Different kinds of input + checkUtf16to8Replacing("\uD800\uDC001\uDC00\uD800", + intArrayOf(-16, -112, -128, -128, '1'.toInt(), -17, -65, -67, -17, -65, -67)) + // Lone surrogate - replace with default + checkUtf16to8Replacing("\uD80012", intArrayOf(-17, -65, -67, '1'.toInt(), '2'.toInt())) + checkUtf16to8Replacing("\uDC0012", intArrayOf(-17, -65, -67, '1'.toInt(), '2'.toInt())) + checkUtf16to8Replacing("12\uD800", intArrayOf('1'.toInt(), '2'.toInt(), -17, -65, -67)) + + // Test manual conversion with an exception if an input is invalid. + // Illegal surrogate pair -> throw + checkUtf16to8Throws("\uDC00\uD800") + // Different kinds of input (including illegal one) -> throw + checkUtf16to8Throws("\uD800\uDC001\uDC00\uD800") + // Lone surrogate - throw + checkUtf16to8Throws("\uD80012") + checkUtf16to8Throws("\uDC0012") + checkUtf16to8Throws("12\uD800") + + // Test double parsing. + assertEquals(4.2, "4.2".toDouble()) + // Illegal surrogate pair -> throw + checkDoubleConversionThrows("\uDC00\uD800") + // Different kinds of input (including illegal one) -> throw + checkDoubleConversionThrows("\uD800\uDC001\uDC00\uD800") + // Lone surrogate - throw + checkDoubleConversionThrows("\uD80012") + checkDoubleConversionThrows("\uDC0012") + checkDoubleConversionThrows("12\uD800") + + // Test float parsing. + assertEquals(4.2F, "4.2".toFloat()) + // Illegal surrogate pair -> throw + checkFloatConversionThrows("\uDC00\uD800") + // Different kinds of input (including illegal one) -> throw + checkFloatConversionThrows("\uD800\uDC001\uDC00\uD800") + // Lone surrogate - throw + checkFloatConversionThrows("\uD80012") + checkFloatConversionThrows("\uDC0012") + checkFloatConversionThrows("12\uD800") +} + +fun test16to8CustomBorders() { + // Valid strings. + checkValidUtf16to8("Hello!", intArrayOf('H'.toInt(), 'e'.toInt()), 0, 2) + checkValidUtf16to8("Hello!", intArrayOf('e'.toInt(), 'l'.toInt()), 1, 2) + checkValidUtf16to8("Hello!", intArrayOf('o'.toInt(), '!'.toInt()), 4, 2) + checkValidUtf16to8("Hello!", intArrayOf(), 0, 0) + checkValidUtf16to8("Hello!", intArrayOf(), 6, 0) + + checkValidUtf16to8("\uD800\uDC00\uD800\uDC00\uD800\uDC00\uD800\uDC00", + intArrayOf(-16, -112, -128, -128, -16, -112, -128, -128), 0, 4) + checkValidUtf16to8("\uD800\uDC00\uD800\uDC00\uD800\uDC00\uD800\uDC00", + intArrayOf(-16, -112, -128, -128, -16, -112, -128, -128), 2, 4) + checkValidUtf16to8("\uD800\uDC00\uD800\uDC00\uD800\uDC00\uD800\uDC00", + intArrayOf(-16, -112, -128, -128, -16, -112, -128, -128), 4, 4) + + // Index out of bound + checkOutOfBoundsUtf16to8(IndexOutOfBoundsException::class, "Hello", -1, 4) + checkOutOfBoundsUtf16to8(IndexOutOfBoundsException::class, "Hello", 5, 10) + checkOutOfBoundsUtf16to8(IndexOutOfBoundsException::class, "Hello", 2, 10) + checkOutOfBoundsUtf16to8(IllegalArgumentException::class, "Hello", 3, -2) + + // Test manual conversion with replacement and custom borders. + // Illegal surrogate pair -> replace with default + checkUtf16to8Replacing("\uDC00\uD80012", + intArrayOf(-17, -65, -67, -17, -65, -67, '1'.toInt()), 0, 3) + checkUtf16to8Replacing("1\uDC00\uD8002", + intArrayOf(-17, -65, -67, -17, -65, -67, '2'.toInt()), 1, 3) + checkUtf16to8Replacing("12\uDC00\uD800", + intArrayOf('2'.toInt(), -17, -65, -67, -17, -65, -67), 1, 3) + + // Lone surrogate - replace with default + checkUtf16to8Replacing("1\uD800\uDC002", intArrayOf('1'.toInt(), -17, -65, -67), 0, 2) + checkUtf16to8Replacing("1\uD800\uDC002", intArrayOf(-17, -65, -67, '2'.toInt()), 2, 2) + + // Test manual conversion with an exception if an input is invalid and custom borders. + // Illegal surrogate pair -> throw + checkUtf16to8Throws("\uDC00\uD80012", 0, 3) + checkUtf16to8Throws("1\uDC00\uD8002", 1, 3) + checkUtf16to8Throws("12\uDC00\uD800", 1, 3) + + // Lone surrogate -> throw + checkUtf16to8Throws("1\uD800\uDC002", 0, 2) + checkUtf16to8Throws("1\uD800\uDC002", 2, 2) +} + +fun testPrint() { + // Valid strings. + println("Hello") + println("Привет") + println("\uD800\uDC00") + println("") + + // Illegal surrogate pair -> default output + println("\uDC00\uD800") + // Lone surrogate -> default output + println("\uD80012") + println("\uDC0012") + println("12\uD800") + + // https://github.com/JetBrains/kotlin-native/issues/1091 + val array = byteArrayOf(0xF0.toByte(), 0x9F.toByte(), 0x98.toByte(), 0xA5.toByte()) + convertUtf8to16(array) { badString -> + assertEquals(2, badString.length) + println(badString) + } +} + +// ------------------------- Test UTF-8 to UTF-16 conversion ------------------------- +fun test8to16() { + // Valid strings. + checkValidUtf8to16("Hello", intArrayOf('H'.toInt(), 'e'.toInt(), 'l'.toInt(), 'l'.toInt(), 'o'.toInt())) + checkValidUtf8to16("Привет", intArrayOf(-48, -97, -47, -128, -48, -72, -48, -78, -48, -75, -47, -126)) + checkValidUtf8to16("\uD800\uDC00", intArrayOf(-16, -112, -128, -128)) + checkValidUtf8to16("", intArrayOf()) + + // Test manual conversion with replacement. + // Incorrect UTF-8 lead character. + checkUtf8to16Replacing("\uFFFD1", intArrayOf(-1, '1'.toInt())) + + // Incomplete codepoint. + checkUtf8to16Replacing("\uFFFD1", intArrayOf(-16, -97, -104, '1'.toInt())) + checkUtf8to16Replacing("\uFFFD1\uFFFD", intArrayOf(-16, -97, -104, '1'.toInt(), -16, -97, -104)) + + // Test manual conversion with exception throwing + // Incorrect UTF-8 lead character -> throw. + checkUtf8to16Throws("\uFFFD1", intArrayOf(-1, '1'.toInt())) + + // Incomplete codepoint -> throw. + checkUtf8to16Throws("\uFFFD1", intArrayOf(-16, -97, -104, '1'.toInt())) + checkUtf8to16Throws("\uFFFD1\uFFFD", intArrayOf(-16, -97, -104, '1'.toInt(), -16, -97, -104)) +} + +fun test8to16CustomBorders() { + // Valid strings. + checkValidUtf8to16("He", + intArrayOf('H'.toInt(), 'e'.toInt(), 'l'.toInt(), 'l'.toInt(), 'o'.toInt()),0, 2) + checkValidUtf8to16("ll", + intArrayOf('H'.toInt(), 'e'.toInt(), 'l'.toInt(), 'l'.toInt(), 'o'.toInt()), 2, 2) + checkValidUtf8to16("lo", + intArrayOf('H'.toInt(), 'e'.toInt(), 'l'.toInt(), 'l'.toInt(), 'o'.toInt()), 3, 2) + checkValidUtf8to16("", + intArrayOf('H'.toInt(), 'e'.toInt(), 'l'.toInt(), 'l'.toInt(), 'o'.toInt()), 0, 0) + + checkValidUtf8to16("\uD800\uDC00\uD800\uDC00", + intArrayOf(-16, -112, -128, -128, -16, -112, -128, -128, -16, -112, -128, -128, -16, -112, -128, -128), + 0, 8) + checkValidUtf8to16("\uD800\uDC00\uD800\uDC00", + intArrayOf(-16, -112, -128, -128, -16, -112, -128, -128, -16, -112, -128, -128, -16, -112, -128, -128), + 4, 8) + checkValidUtf8to16("\uD800\uDC00\uD800\uDC00", + intArrayOf(-16, -112, -128, -128, -16, -112, -128, -128, -16, -112, -128, -128, -16, -112, -128, -128), + 8, 8) + + // Index out of bound + val helloArray = byteArrayOf('H'.toByte(), 'e'.toByte(), 'l'.toByte(), 'l'.toByte(), 'o'.toByte()) + checkOutOfBoundsUtf8to16(IndexOutOfBoundsException::class, "Hello", helloArray, -1, 4) + checkOutOfBoundsUtf8to16(IndexOutOfBoundsException::class, "Hello", helloArray, 5, 10) + checkOutOfBoundsUtf8to16(IndexOutOfBoundsException::class, "Hello", helloArray, 2, 10) + checkOutOfBoundsUtf8to16(IndexOutOfBoundsException::class, "Hello", helloArray, 10, 0) + checkOutOfBoundsUtf8to16(IllegalArgumentException::class, "Hello", helloArray, 3, -2) + + // Test manual conversion with replacement and custom borders. + // Incorrect UTF-8 lead character. + checkUtf8to16Replacing("\uFFFD1", intArrayOf(-1, '1'.toInt(), '2'.toInt()), 0, 2) + checkUtf8to16Replacing("\uFFFD2", intArrayOf('1'.toInt(), -1, '2'.toInt(), '3'.toInt()), 1, 2) + checkUtf8to16Replacing("2\uFFFD", intArrayOf('1'.toInt(), '2'.toInt(), -1), 1, 2) + + // Incomplete codepoint. + checkUtf8to16Replacing("\uFFFD1", intArrayOf(-16, -97, -104, '1'.toInt(), '2'.toInt()), 0, 4) + checkUtf8to16Replacing("\uFFFD2", intArrayOf('1'.toInt(), -16, -97, -104, '2'.toInt(), '3'.toInt()), 1, 4) + checkUtf8to16Replacing("2\uFFFD", intArrayOf('1'.toInt(), '2'.toInt(), -16, -97, -104), 1, 4) + + // Test manual conversion with an exception if an input is invalid and custom borders. + // Incorrect UTF-8 lead character. + checkUtf8to16Throws("\uFFFD1", intArrayOf(-1, '1'.toInt(), '2'.toInt()), 0, 2) + checkUtf8to16Throws("\uFFFD2", intArrayOf('1'.toInt(), -1, '2'.toInt(), '3'.toInt()), 1, 2) + checkUtf8to16Throws("2\uFFFD", intArrayOf('1'.toInt(), '2'.toInt(), -1), 1, 2) + + // Incomplete codepoint. + checkUtf8to16Throws("\uFFFD1", intArrayOf(-16, -97, -104, '1'.toInt(), '2'.toInt()), 0, 4) + checkUtf8to16Throws("\uFFFD2", intArrayOf('1'.toInt(), -16, -97, -104, '2'.toInt(), '3'.toInt()), 1, 4) + checkUtf8to16Throws("2\uFFFD", intArrayOf('1'.toInt(), '2'.toInt(), -16, -97, -104), 1, 4) +} + +// ----------------- Test zero-terminated UTF-8 to UTF-16 conversion ----------------- +fun testZeroTerminated8To16() { + // Valid strings. + checkValidZeroTerminatedUtf8to16("Hell", intArrayOf('H'.toInt(), 'e'.toInt(), 'l'.toInt(), 'l'.toInt(), 0, 'o'.toInt())) + checkValidZeroTerminatedUtf8to16("При", intArrayOf(-48, -97, -47, -128, -48, -72, 0, -48, -78, 0, -48, -75, -47, -126)) + checkValidZeroTerminatedUtf8to16("\uD800\uDC00", intArrayOf(-16, -112, -128, -128, 0, -16, -112, -128, -128)) + checkValidZeroTerminatedUtf8to16("", intArrayOf(0, 'H'.toInt())) + + // Test manual conversion with replacement. + // Incorrect UTF-8 lead character. + checkZeroTerminatedUtf8to16Replacing("\uFFFD", intArrayOf(-1, 0, '1'.toInt())) + + // Incomplete codepoint. + checkZeroTerminatedUtf8to16Replacing("\uFFFD", intArrayOf(-16, -97, -104, 0, '1'.toInt())) + checkZeroTerminatedUtf8to16Replacing("\uFFFD1", intArrayOf(-16, -97, -104, '1'.toInt(), 0, -16, -97, -104)) + + // Test manual conversion with exception throwing + // Incorrect UTF-8 lead character -> throw. + checkZeroTerminatedUtf8to16Throws("\uFFFD", intArrayOf(-1, 0, '1'.toInt())) + + // Incomplete codepoint -> throw. + checkZeroTerminatedUtf8to16Throws("\uFFFD", intArrayOf(-16, -97, -104, 0, '1'.toInt())) + checkZeroTerminatedUtf8to16Throws("\uFFFD1", intArrayOf(-16, -97, -104, '1'.toInt(), 0, -16, -97, -104)) +} + +fun testZeroTerminated8To16CustomBorders() { + val array = intArrayOf('a'.toInt(), 'a'.toInt(), 'a'.toInt(), 0, 'b'.toInt(), 'b'.toInt(), 'b'.toInt(), 0) + checkValidZeroTerminatedUtf8to16("aaa", array, 0, 5) + checkValidZeroTerminatedUtf8to16("a", array, 2, 2) + checkValidZeroTerminatedUtf8to16("", array, 3, 2) + checkValidZeroTerminatedUtf8to16("bb", array, 4, 2) + checkValidZeroTerminatedUtf8to16("bbb", array, 4, 3) + checkValidZeroTerminatedUtf8to16("bbb", array, 4, 4) + checkValidZeroTerminatedUtf8to16("bb", array, 5, 3) + checkValidZeroTerminatedUtf8to16("b", array, 6, 2) + checkValidZeroTerminatedUtf8to16("", array, 7, 1) + checkValidZeroTerminatedUtf8to16("", array, 8, 0) + + val byteArray = ByteArray(array.size) { array[it].toByte() } + checkOutOfBoundsZeroTerminatedUtf8to16(IndexOutOfBoundsException::class, "aaa0bbb0", byteArray, -1, 4) + checkOutOfBoundsZeroTerminatedUtf8to16(IndexOutOfBoundsException::class, "aaa0bbb0", byteArray, 8, 10) + checkOutOfBoundsZeroTerminatedUtf8to16(IndexOutOfBoundsException::class, "aaa0bbb0", byteArray, 2, 10) + checkOutOfBoundsZeroTerminatedUtf8to16(IndexOutOfBoundsException::class, "aaa0bbb0", byteArray, 10, 0) + checkOutOfBoundsZeroTerminatedUtf8to16(IllegalArgumentException::class, "aaa0bbb0", byteArray, 3, -2) +} + +// ------------------------------------ Run tests ------------------------------------ +@Test fun runTest() { + test16to8() + test16to8CustomBorders() + test8to16() + test8to16CustomBorders() + testZeroTerminated8To16() + testZeroTerminated8To16CustomBorders() + testPrint() +} diff --git a/kotlin-native/backend.native/tests/runtime/workers/atomic0.kt b/kotlin-native/backend.native/tests/runtime/workers/atomic0.kt new file mode 100644 index 00000000000..a0db629698a --- /dev/null +++ b/kotlin-native/backend.native/tests/runtime/workers/atomic0.kt @@ -0,0 +1,141 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +package runtime.workers.atomic0 + +import kotlin.test.* + +import kotlin.native.concurrent.* + +fun test1(workers: Array) { + val atomic = AtomicInt(15) + val futures = Array(workers.size, { workerIndex -> + workers[workerIndex].execute(TransferMode.SAFE, { atomic }) { + input -> input.addAndGet(1) + } + }) + futures.forEach { + it.result + } + println(atomic.value) +} + +fun test2(workers: Array) { + val atomic = AtomicInt(1) + val counter = AtomicInt(0) + val futures = Array(workers.size, { workerIndex -> + workers[workerIndex].execute(TransferMode.SAFE, { Triple(atomic, workerIndex, counter) }) { + (place, index, result) -> + // Here we simulate mutex using [place] location to store tag of the current worker. + // When it is negative - worker executes exclusively. + val tag = index + 1 + while (place.compareAndSwap(tag, -tag) != tag) {} + val ok1 = result.addAndGet(1) == index + 1 + // Now, let the next worker run. + val ok2 = place.compareAndSwap(-tag, tag + 1) == -tag + ok1 && ok2 + } + }) + futures.forEach { + assertEquals(it.result, true) + } + println(counter.value) +} + +data class Data(val value: Int) + +fun test3(workers: Array) { + val common = AtomicReference(null) + val futures = Array(workers.size, { workerIndex -> + workers[workerIndex].execute(TransferMode.SAFE, { Pair(common, workerIndex) }) { + (place, index) -> + val mine = Data(index).freeze() + // Try to publish our own data, until successful, in a tight loop. + while (!place.compareAndSet(null, mine)) {} + } + }) + val seen = mutableSetOf() + for (i in 0 until workers.size) { + do { + val current = common.value + if (current != null && !seen.contains(current)) { + seen += current + // Let others publish. + assertEquals(common.compareAndSwap(current, null), current) + break + } + } while (true) + } + futures.forEach { + it.result + } + assertEquals(seen.size, workers.size) +} + +fun test4() { + assertFailsWith { + AtomicReference(Data(1)) + } + assertFailsWith { + AtomicReference(null).compareAndSwap(null, Data(2)) + } +} + +fun test5() { + assertFailsWith { + AtomicReference(null).value = Data(2) + } + val ref = AtomicReference(null) + val value = Data(3).freeze() + assertEquals(null, ref.value) + ref.value = value + assertEquals(3, ref.value!!.value) +} + +fun test6() { + val int = AtomicInt(0) + int.value = 239 + assertEquals(239, int.value) + val long = AtomicLong(0) + long.value = 239L + assertEquals(239L, long.value) +} + + +fun test7() { + val ref = FreezableAtomicReference(Array(1) { "hey" }) + ref.value[0] = "ho" + assertEquals(ref.value[0], "ho") + ref.value = Array(1) { "po" } + assertEquals(ref.value[0], "po") + ref.freeze() + assertFailsWith { + ref.value = Array(1) { "no" } + } + assertFailsWith { + ref.value[0] = "go" + } + ref.value = Array(1) { "so" }.freeze() + assertEquals(ref.value[0], "so") +} + +@Test fun runTest() { + val COUNT = 20 + val workers = Array(COUNT, { _ -> Worker.start()}) + + test1(workers) + test2(workers) + test3(workers) + test4() + test5() + test6() + test7() + + workers.forEach { + it.requestTermination().result + } + println("OK") +} + diff --git a/kotlin-native/backend.native/tests/runtime/workers/atomic1.kt b/kotlin-native/backend.native/tests/runtime/workers/atomic1.kt new file mode 100644 index 00000000000..d6b065a2f83 --- /dev/null +++ b/kotlin-native/backend.native/tests/runtime/workers/atomic1.kt @@ -0,0 +1,58 @@ +/* + * Copyright 2010-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +// Note: This test reproduces a race, so it'll start flaking if problem is reintroduced. + +import kotlin.test.* + +import kotlin.native.concurrent.* +import kotlin.native.internal.* + +val thrashGC = AtomicInt(1) +val canStartCreating = AtomicInt(0) +val createdCount = AtomicInt(0) +val canStartReading = AtomicInt(0) +const val atomicsCount = 1000 +const val workersCount = 10 + +fun main() { + val gcWorker = Worker.start() + val future = gcWorker.execute(TransferMode.SAFE, {}, { + canStartCreating.value = 1 + while (thrashGC.value != 0) { + GC.collectCyclic() + } + GC.collect() + }) + + while (canStartCreating.value == 0) {} + + val workers = Array(workersCount) { Worker.start() } + val futures = workers.map { + it.execute(TransferMode.SAFE, {}, { + val atomics = Array(atomicsCount) { + AtomicReference(Any().freeze()) + } + createdCount.increment() + while (canStartReading.value == 0) {} + GC.collect() + atomics.all { it.value != null } + }) + } + + while (createdCount.value != workersCount) {} + + thrashGC.value = 0 + future.result + GC.collect() + canStartReading.value = 1 + + assertTrue(futures.all { it.result }) + + for (worker in workers) { + worker.requestTermination().result + } + gcWorker.requestTermination().result +} diff --git a/kotlin-native/backend.native/tests/runtime/workers/enum_identity.kt b/kotlin-native/backend.native/tests/runtime/workers/enum_identity.kt new file mode 100644 index 00000000000..eb8d4010988 --- /dev/null +++ b/kotlin-native/backend.native/tests/runtime/workers/enum_identity.kt @@ -0,0 +1,24 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +package runtime.workers.enum_identity + +import kotlin.test.* +import kotlin.native.concurrent.* + +enum class A { + A, B +} + +data class Foo(val kind: A) + +// Enums are shared between threads so identity should be kept. +@Test +fun runTest() { + val result = Worker.start().execute(TransferMode.SAFE, { Foo(A.B) }, { input -> + input.kind == A.B + }).result + println(result) +} \ No newline at end of file diff --git a/kotlin-native/backend.native/tests/runtime/workers/freeze0.kt b/kotlin-native/backend.native/tests/runtime/workers/freeze0.kt new file mode 100644 index 00000000000..0eff9602588 --- /dev/null +++ b/kotlin-native/backend.native/tests/runtime/workers/freeze0.kt @@ -0,0 +1,32 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +package runtime.workers.freeze0 + +import kotlin.test.* + +import kotlin.native.concurrent.* + +data class SharedDataMember(val double: Double) + +data class SharedData(val string: String, val int: Int, val member: SharedDataMember) + +@Test fun runTest() { + val worker = Worker.start() + // Create immutable shared data. + val immutable = SharedData("Hello", 10, SharedDataMember(0.1)).freeze() + println("frozen bit is ${immutable.isFrozen}") + + val future = worker.execute(TransferMode.SAFE, { immutable } ) { + input -> + println("Worker: $input") + input + } + future.consume { + result -> println("Main: $result") + } + worker.requestTermination().result + println("OK") +} \ No newline at end of file diff --git a/kotlin-native/backend.native/tests/runtime/workers/freeze1.kt b/kotlin-native/backend.native/tests/runtime/workers/freeze1.kt new file mode 100644 index 00000000000..6a8b9f9a054 --- /dev/null +++ b/kotlin-native/backend.native/tests/runtime/workers/freeze1.kt @@ -0,0 +1,46 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +package runtime.workers.freeze1 + +import kotlin.test.* + +import kotlin.native.concurrent.* + +data class Node(var previous: Node?, var data: Int) + +fun makeCycle(count: Int): Node { + val first = Node(null, 0) + var current = first + for (index in 1 .. count - 1) { + current = Node(current, index) + } + first.previous = current + return first +} + +data class Node2(var leaf1: Node2?, var leaf2: Node2?) + +fun makeDiamond(): Node2 { + val bottom = Node2(null, null) + val mid1prime = Node2(bottom, null) + val mid1 = Node2(mid1prime, null) + val mid2 = Node2(bottom, null) + return Node2(mid1, mid2) +} + +@Test fun runTest() { + makeCycle(10).freeze() + + // Must be able to freeze diamond shaped graph. + val diamond = makeDiamond().freeze() + + val immutable = Node(null, 4).freeze() + try { + immutable.data = 42 + } catch (e: InvalidMutabilityException) { + println("OK, cannot mutate frozen") + } +} \ No newline at end of file diff --git a/kotlin-native/backend.native/tests/runtime/workers/freeze2.kt b/kotlin-native/backend.native/tests/runtime/workers/freeze2.kt new file mode 100644 index 00000000000..c0ede937cf9 --- /dev/null +++ b/kotlin-native/backend.native/tests/runtime/workers/freeze2.kt @@ -0,0 +1,90 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +package runtime.workers.freeze2 + +import kotlin.test.* + +import kotlin.native.concurrent.* + +data class Data(var int: Int) + +@Test fun runTest() { + // Ensure that we can not mutate frozen objects and arrays. + val a0 = Data(2) + a0.int++ + a0.freeze() + assertFailsWith {a0.int++ } + + val a1 = ByteArray(2) + a1[1]++ + a1.freeze() + assertFailsWith { a1[1]++ } + + val a2 = ShortArray(2) + a2[1]++ + a2.freeze() + assertFailsWith { a2[1]++ } + + val a3 = IntArray(2) + a3[1]++ + a3.freeze() + assertFailsWith { a3[1]++ } + + val a4 = LongArray(2) + a4[1]++ + a4.freeze() + assertFailsWith { a4[1]++ } + + val a5 = BooleanArray(2) + a5[1] = true + a5.freeze() + assertFailsWith { a5[1] = false } + + val a6 = CharArray(2) + a6[1] = 'a' + a6.freeze() + assertFailsWith { a6[1] = 'b' } + + val a7 = FloatArray(2) + a7[1] = 1.0f + a7.freeze() + assertFailsWith { a7[1] = 2.0f } + + val a8 = DoubleArray(2) + a8[1] = 1.0 + a8.freeze() + assertFailsWith { a8[1] = 2.0 } + + // Ensure that String and integral boxes are frozen by default, by passing local to the worker. + val worker = Worker.start() + var data: Any = "Hello" + " " + "world" + assert(data.isFrozen) + worker.execute(TransferMode.SAFE, { data } ) { + input -> println("Worker 1: $input") + }.result + + data = 42 + assert(data.isFrozen) + worker.execute(TransferMode.SAFE, { data } ) { + input -> println("Worker2: $input") + }.result + + data = 239.0 + assert(data.isFrozen) + worker.execute(TransferMode.SAFE, { data } ) { + input -> println("Worker3: $input") + }.result + + data = 'a' + assert(data.isFrozen) + worker.execute(TransferMode.SAFE, { data } ) { + input -> println("Worker4: $input") + }.result + + worker.requestTermination().result + + println("OK") +} \ No newline at end of file diff --git a/kotlin-native/backend.native/tests/runtime/workers/freeze3.kt b/kotlin-native/backend.native/tests/runtime/workers/freeze3.kt new file mode 100644 index 00000000000..05dab88d7bf --- /dev/null +++ b/kotlin-native/backend.native/tests/runtime/workers/freeze3.kt @@ -0,0 +1,50 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +package runtime.workers.freeze3 + +import kotlin.test.* + +import kotlin.native.concurrent.* + +object AnObject { + var x = 1 +} + +@ThreadLocal +object Mutable { + var x = 2 +} + +val topLevelInline: ULong = 0xc3a5c85c97cb3127U + +@Test fun runTest1() { + assertEquals(1, AnObject.x) + if (Platform.memoryModel == MemoryModel.STRICT) { + assertFailsWith { + AnObject.x++ + } + assertEquals(1, AnObject.x) + } else { + AnObject.x++ + assertEquals(2, AnObject.x) + } + + Mutable.x++ + assertEquals(3, Mutable.x) + println("OK") +} + +@Test fun runTest2() { + val ok = AtomicInt(0) + withWorker() { + executeAfter(0, { + assertEquals(0xc3a5c85c97cb3127U, topLevelInline) + ok.increment() + }.freeze()) + } + assertEquals(1, ok.value) +} + diff --git a/kotlin-native/backend.native/tests/runtime/workers/freeze4.kt b/kotlin-native/backend.native/tests/runtime/workers/freeze4.kt new file mode 100644 index 00000000000..2b1fad294a0 --- /dev/null +++ b/kotlin-native/backend.native/tests/runtime/workers/freeze4.kt @@ -0,0 +1,29 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +package runtime.workers.freeze4 + +import kotlin.test.* + +import kotlin.native.concurrent.* + +data class Data(val x: Int, val s: String, val next: Data? = null) + +@Test fun runTest() { + val data1 = Data(1, "") + data1.freeze() + assertFailsWith { + data1.ensureNeverFrozen() + } + + val dataNF = Data(42, "42") + dataNF.ensureNeverFrozen() + val data2 = Data(2, "2", dataNF) + assertFailsWith { + data2.freeze() + } + assert(!data2.isFrozen) + println("OK") +} diff --git a/kotlin-native/backend.native/tests/runtime/workers/freeze5.kt b/kotlin-native/backend.native/tests/runtime/workers/freeze5.kt new file mode 100644 index 00000000000..e8ad3bca269 --- /dev/null +++ b/kotlin-native/backend.native/tests/runtime/workers/freeze5.kt @@ -0,0 +1,48 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +package runtime.workers.freeze5 + +import kotlin.test.* + +object Keys { + internal val myMap: Map> = mapOf( + "val1" to listOf("a1", "a2", "a3"), + "val2" to listOf("b1", "b2") + ) + + fun getKey(name: String): String { + for (key in myMap.keys) { + if (key == name) { + return key + } + } + return "" + } + + fun getValue(name: String): String { + for (value in myMap.values) { + if (value.contains(name)) { + return name + } + } + return "" + } + + fun getEntry(name: String): String { + for (entry in myMap.entries) { + if (entry.key == name) { + return entry.key + } + } + return "" + } +} +@Test fun runTest() { + assertEquals("val2", Keys.getKey("val2")) + assertEquals("a1", Keys.getValue("a1")) + assertEquals("val1", Keys.getEntry("val1")) + println("OK") +} \ No newline at end of file diff --git a/kotlin-native/backend.native/tests/runtime/workers/freeze6.kt b/kotlin-native/backend.native/tests/runtime/workers/freeze6.kt new file mode 100644 index 00000000000..e32450ea22b --- /dev/null +++ b/kotlin-native/backend.native/tests/runtime/workers/freeze6.kt @@ -0,0 +1,159 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +package runtime.workers.freeze6 + +import kotlin.test.* +import kotlin.native.concurrent.* +import kotlin.native.ref.* + +data class Hi(val s: String) +data class Nested(val hi: Hi) + +@Test +fun ensureNeverFrozenNoFreezeChild(){ + val noFreeze = Hi("qwert") + noFreeze.ensureNeverFrozen() + + val nested = Nested(noFreeze) + assertFails { nested.freeze() } + + println("OK") +} + +@Test +fun ensureNeverFrozenFailsTarget(){ + val noFreeze = Hi("qwert") + noFreeze.ensureNeverFrozen() + + assertFalse(noFreeze.isFrozen) + assertFails { noFreeze.freeze() } + assertFalse(noFreeze.isFrozen) + println("OK") +} + +fun createRef1(): FreezableAtomicReference { + val ref = FreezableAtomicReference(null) + ref.value = ref + ref.freeze() + ref.value = null + return ref +} + +var global = 0 + +@Test +fun ensureFreezableHandlesCycles1() { + val ref = createRef1() + kotlin.native.internal.GC.collect() + + val obj: Any = ref + global = obj.hashCode() +} + +class Node(var ref: Any?) + +/** + * ref1 -> Node <- ref3 + * | /\ + * V | + * ref2 --- + */ +fun createRef2(): Pair, Any> { + val ref1 = FreezableAtomicReference(null) + + val node = Node(null) + val ref3 = FreezableAtomicReference(node) + val ref2 = FreezableAtomicReference(ref3) + + node.ref = ref2 + ref1.value = node + + ref1.freeze() + ref3.value = null + + assertTrue(node.isFrozen) + assertTrue(ref1.isFrozen) + assertTrue(ref2.isFrozen) + assertTrue(ref3.isFrozen) + + return ref1 to ref2 +} + +@Test +fun ensureFreezableHandlesCycles2() { + val (ref, obj) = createRef2() + kotlin.native.internal.GC.collect() + + assertTrue(obj.toString().length > 0) + global = ref.value!!.ref!!.hashCode() +} + +fun createRef3(): FreezableAtomicReference { + val ref = FreezableAtomicReference(null) + val node = Node(ref) + ref.value = node + ref.freeze() + + assertTrue(node.isFrozen) + assertTrue(ref.isFrozen) + + return ref +} + +@Test +fun ensureFreezableHandlesCycles3() { + val ref = createRef3() + ref.value = null + kotlin.native.internal.GC.collect() + + val obj: Any = ref + assertTrue(obj.toString().length > 0) + global = obj.hashCode() +} + +lateinit var weakRef: WeakReference + +fun createRef4(): FreezableAtomicReference { + val ref = FreezableAtomicReference(null) + val node = Node(ref) + weakRef = WeakReference(node) + ref.value = node + ref.freeze() + assertTrue(weakRef.get() != null) + return ref +} + +@Test +fun ensureWeakRefNotLeaks1() { + val ref = createRef4() + ref.value = null + // We cannot check weakRef.get() here, as value read will be stored in the stack slot, + // and thus hold weak reference from release. + kotlin.native.internal.GC.collect() + + assertTrue(weakRef.get() == null) +} + +lateinit var node1: Node +lateinit var weakNode2: WeakReference + +fun createRef5() { + val ref = FreezableAtomicReference(null) + node1 = Node(ref) + val node2 = Node(node1) + weakNode2 = WeakReference(node2) + ref.value = node2 + node1.freeze() + assertTrue(weakNode2.get() != null) + ref.value = null +} + +@Test +fun ensureWeakRefNotLeaks2() { + createRef5() + kotlin.native.internal.GC.collect() + assertTrue(weakNode2.get() == null) +} \ No newline at end of file diff --git a/kotlin-native/backend.native/tests/runtime/workers/freeze_stress.kt b/kotlin-native/backend.native/tests/runtime/workers/freeze_stress.kt new file mode 100644 index 00000000000..3c15d27c6f7 --- /dev/null +++ b/kotlin-native/backend.native/tests/runtime/workers/freeze_stress.kt @@ -0,0 +1,151 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +package runtime.workers.freeze_stress + +import kotlin.test.* + +import kotlin.native.concurrent.* + +class Random(private var seed: Int) { + fun next(): Int { + seed = (1103515245 * seed + 12345) and 0x7fffffff + return seed + } + + fun next(maxExclusiveValue: Int) = if (maxExclusiveValue == 0) 0 else next() % maxExclusiveValue + + fun next(minInclusiveValue: Int, maxInclusiveValue: Int) = + minInclusiveValue + next(maxInclusiveValue - minInclusiveValue + 1) +} + +class Node(val id: Int) { + var numberOfEdges = 0 + + lateinit var edge0: Node + lateinit var edge1: Node + lateinit var edge2: Node + lateinit var edge3: Node + lateinit var edge4: Node + lateinit var edge5: Node + lateinit var edge6: Node + lateinit var edge7: Node + lateinit var edge8: Node + lateinit var edge9: Node + + fun addEdge(child: Node) { + when (numberOfEdges) { + 0 -> edge0 = child + 1 -> edge1 = child + 2 -> edge2 = child + 3 -> edge3 = child + 4 -> edge4 = child + 5 -> edge5 = child + 6 -> edge6 = child + 7 -> edge7 = child + 8 -> edge8 = child + 9 -> edge9 = child + else -> error("Too many edges") + } + ++numberOfEdges + } + + fun getEdges(): List { + val result = mutableListOf() + if (numberOfEdges > 0) result += edge0 + if (numberOfEdges > 1) result += edge1 + if (numberOfEdges > 2) result += edge2 + if (numberOfEdges > 3) result += edge3 + if (numberOfEdges > 4) result += edge4 + if (numberOfEdges > 5) result += edge5 + if (numberOfEdges > 6) result += edge6 + if (numberOfEdges > 7) result += edge7 + if (numberOfEdges > 8) result += edge8 + if (numberOfEdges > 9) result += edge9 + return result + } +} + +class Graph(val nodes: List, val roots: List) + +fun min(x: Int, y: Int) = if (x < y) x else y +fun max(x: Int, y: Int) = if (x > y) x else y + +@ThreadLocal +val random = Random(42) + +fun generate(condensationSize: Int, branchingFactor: Int, swellingFactor: Int): Graph { + var id = 0 + val nodes = mutableListOf() + + fun genDAG(n: Int): Node { + val node = Node(id++) + nodes += node + if (n == 1) return node + val numberOfChildren = random.next(1, min(n - 1, branchingFactor)) + val used = BooleanArray(n) + val points = IntArray(numberOfChildren + 1) + points[0] = 0 + points[numberOfChildren] = n - 1 + used[0] = true + used[n - 1] = true + for (i in 1 until numberOfChildren) { + var p: Int + do { + p = random.next(1, n - 1) + } while (used[p]) + used[p] = true + points[i] = p + } + points.sort() + for (i in 1..numberOfChildren) { + val childSize = points[i] - points[i - 1] + val child = genDAG(childSize) + if (random.next(2) == 0) + node.addEdge(child) + else + child.addEdge(node) + } + return node + } + + genDAG(condensationSize) + + val numberOfEnters = IntArray(condensationSize) + for (node in nodes) + for (edge in node.getEdges()) + ++numberOfEnters[edge.id] + val roots = nodes.filter { numberOfEnters[it.id] == 0 } + for (i in 0 until condensationSize) { + val node = nodes[i] + val componentSize = random.next(1, swellingFactor) + if (componentSize == 1 && random.next(2) == 0) + continue + val component = Array(componentSize) { + if (it == 0) node else Node(id++).also { nodes += it } + } + for (j in 0 until componentSize) + component[j].addEdge(component[(j - 1 + componentSize) % componentSize]) + val numberOfAdditionalEdges = random.next((componentSize + 1) / 2) + for (j in 0 until numberOfAdditionalEdges) + component[random.next(componentSize)].addEdge(component[random.next(componentSize)]) + } + + return Graph(nodes, roots) +} + +fun freezeOneGraph() { + val graph = generate(100, 5, 20) + graph.roots.forEach { it.freeze() } + for (node in graph.nodes) + assert (node.isFrozen, { "All nodes should be frozen" }) +} + +@Test fun runTest() { + for (i in 0..1000) { + freezeOneGraph() + } + println("OK") +} \ No newline at end of file diff --git a/kotlin-native/backend.native/tests/runtime/workers/lazy0.kt b/kotlin-native/backend.native/tests/runtime/workers/lazy0.kt new file mode 100644 index 00000000000..3322a8779e2 --- /dev/null +++ b/kotlin-native/backend.native/tests/runtime/workers/lazy0.kt @@ -0,0 +1,88 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +package runtime.workers.lazy0 + +import kotlin.test.* + +import kotlin.native.concurrent.* + +data class Data(val x: Int, val y: String) + +object Immutable { + val x by atomicLazy { + 42 + } +} + +object Immutable2 { + val y by atomicLazy { + Data(239, "Kotlin") + } +} + +object Immutable3 { + val x by lazy { + var result = 0 + for (i in 1 .. 1000) + result += i + result + } +} + +fun testSingleData(workers: Array) { + val set = mutableSetOf() + for (attempt in 1 .. 3) { + val futures = Array(workers.size, { workerIndex -> + workers[workerIndex].execute(TransferMode.SAFE, { "" }) { _ -> Immutable2.y } + }) + futures.forEach { set += it.result } + } + assertEquals(set.size, 1) + assertEquals(set.single(), Immutable2.y) +} + +fun testFrozenLazy(workers: Array) { + // To make sure it is always frozen, and we don't race in relaxed mode. + Immutable3.freeze() + val set = mutableSetOf() + for (attempt in 1 .. 3) { + val futures = Array(workers.size, { workerIndex -> + workers[workerIndex].execute(TransferMode.SAFE, { "" }) { _ -> Immutable3.x } + }) + futures.forEach { set += it.result } + } + assertEquals(1, set.size) + assertEquals(Immutable3.x, set.single()) + assertEquals(1001 * 500, set.single()) +} + +fun testLiquidLazy() { + class L { + val value by lazy { + 17 + } + } + val l1 = L() + for (i in 1 .. 100) + assertEquals(l1.value, 17) + + val l2 = L() + l2.freeze() + for (i in 1 .. 100) + assertEquals(l2.value, 17) +} + +@Test fun runTest() { + assertEquals(42, Immutable.x) + + val COUNT = 5 + val workers = Array(COUNT, { _ -> Worker.start()}) + testSingleData(workers) + testFrozenLazy(workers) + testLiquidLazy() + + println("OK") +} diff --git a/kotlin-native/backend.native/tests/runtime/workers/lazy1.kt b/kotlin-native/backend.native/tests/runtime/workers/lazy1.kt new file mode 100644 index 00000000000..f15cc8f6bb2 --- /dev/null +++ b/kotlin-native/backend.native/tests/runtime/workers/lazy1.kt @@ -0,0 +1,60 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +package runtime.workers.lazy1 + +import kotlin.test.* +import kotlin.native.concurrent.* + +class Lazy { + val x = 17 + val self by lazy { this } + val recursion: Int by lazy { + if (x < 17) 42 else recursion + } + val freezer: Int by lazy { + freeze() + 42 + } + val thrower: String by lazy { + if (x < 100) throw IllegalArgumentException() + "FAIL" + } +} + +@Test fun runTest1() { + assertFailsWith { + println(Lazy().recursion) + } + assertFailsWith { + println(Lazy().freeze().recursion) + } +} + +@Test fun runTest2() { + var sum = 0 + for (i in 1 .. 100) { + val self = Lazy().freeze() + assertEquals(self, self.self) + sum += self.self.hashCode() + } + println("OK") +} + + +@Test fun runTest3() { + assertFailsWith { + println(Lazy().freezer) + } +} + +@Test fun runTest4() { + val self = Lazy() + repeat(10) { + assertFailsWith { + println(self.thrower) + } + } +} \ No newline at end of file diff --git a/kotlin-native/backend.native/tests/runtime/workers/lazy2.kt b/kotlin-native/backend.native/tests/runtime/workers/lazy2.kt new file mode 100644 index 00000000000..49d08ae9957 --- /dev/null +++ b/kotlin-native/backend.native/tests/runtime/workers/lazy2.kt @@ -0,0 +1,31 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ +import kotlin.test.* + +object Foo { + val bar = Bar() +} + +class Bar { + val f by lazy { + foo() + } + + fun foo() = 123 +} + +fun printAll() { + println(Foo.bar.f) +} + +// This test is extracted from the real problem found in kotlinx.serialization, where zeroing out +// initializer field in frozen lazy object led to the crash, induced by breaking frozen objects' +// invariant (initializer end up in the same container as the lazy object itself, so it was destroyed +// earlier than it should when reference counter was decremented). +fun main(args: Array) { + printAll() + kotlin.native.internal.GC.collect() + println("OK") +} \ No newline at end of file diff --git a/kotlin-native/backend.native/tests/runtime/workers/lazy3.kt b/kotlin-native/backend.native/tests/runtime/workers/lazy3.kt new file mode 100644 index 00000000000..308df46ee15 --- /dev/null +++ b/kotlin-native/backend.native/tests/runtime/workers/lazy3.kt @@ -0,0 +1,54 @@ +import kotlin.native.concurrent.* +import kotlin.native.ref.* +import kotlin.test.* + +fun main() { + test1() + test2() +} + +fun test1() { + ensureGetsCollectedFrozenAndNotFrozen { LazyCapturesThis() } + ensureGetsCollectedFrozenAndNotFrozen { + val l = LazyCapturesThis() + l.bar + l + } + ensureGetsCollected { + val l = LazyCapturesThis().freeze() + l.bar + l + } +} + +class LazyCapturesThis { + fun foo() = 42 + val bar by lazy { foo() } +} + +fun test2() { + ensureGetsCollectedFrozenAndNotFrozen { Throwable() } + ensureGetsCollectedFrozenAndNotFrozen { + val throwable = Throwable() + throwable.getStackTrace() + throwable + } + ensureGetsCollected { + val throwable = Throwable().freeze() + throwable.getStackTrace() + throwable + } +} + +fun ensureGetsCollectedFrozenAndNotFrozen(create: () -> Any) { + ensureGetsCollected { create().freeze() } + ensureGetsCollected(create) +} + +fun ensureGetsCollected(create: () -> Any) { + val ref = makeWeakRef(create) + kotlin.native.internal.GC.collect() + assertNull(ref.get()) +} + +fun makeWeakRef(create: () -> Any) = WeakReference(create()) \ No newline at end of file diff --git a/kotlin-native/backend.native/tests/runtime/workers/leak_memory_with_worker_termination.kt b/kotlin-native/backend.native/tests/runtime/workers/leak_memory_with_worker_termination.kt new file mode 100644 index 00000000000..32a9d0a3a69 --- /dev/null +++ b/kotlin-native/backend.native/tests/runtime/workers/leak_memory_with_worker_termination.kt @@ -0,0 +1,10 @@ +import kotlin.native.concurrent.* +import kotlinx.cinterop.* + +fun main() { + val worker = Worker.start() + // Make sure worker is initialized. + worker.execute(TransferMode.SAFE, {}, {}).result; + StableRef.create(Any()) + worker.requestTermination().result +} diff --git a/kotlin-native/backend.native/tests/runtime/workers/leak_worker.kt b/kotlin-native/backend.native/tests/runtime/workers/leak_worker.kt new file mode 100644 index 00000000000..1df5bfac135 --- /dev/null +++ b/kotlin-native/backend.native/tests/runtime/workers/leak_worker.kt @@ -0,0 +1,9 @@ +import kotlin.native.concurrent.* +import kotlinx.cinterop.* + +fun main() { + val worker = Worker.start() + // Make sure worker is initialized. + worker.execute(TransferMode.SAFE, {}, {}).result; + StableRef.create(Any()) +} diff --git a/kotlin-native/backend.native/tests/runtime/workers/mutableData1.kt b/kotlin-native/backend.native/tests/runtime/workers/mutableData1.kt new file mode 100644 index 00000000000..4cadf459db0 --- /dev/null +++ b/kotlin-native/backend.native/tests/runtime/workers/mutableData1.kt @@ -0,0 +1,47 @@ +package runtime.workers.mutableData1 + +import kotlin.native.concurrent.* +import kotlin.test.* + +// See https://youtrack.jetbrains.com/issue/KT-39145 +@Test +fun kt39145_1() = withWorker { + execute(TransferMode.SAFE, { "test" }) { + val data = MutableData(1_000) + val bytes = byteArrayOf(0, 10, 20, 30) + data.append(bytes, 0, 4) + assertEquals(4, data.size) + + assertContentsEquals(bytes, data) + }.result +} + +@Test +fun kt39145_2() = withWorker { + val externalData = MutableData(1_000) + execute(TransferMode.SAFE, { externalData }) { + val bytes = byteArrayOf(0, 10, 20, 30) + it.append(bytes, 0, 4) + assertEquals(4, it.size) + + assertContentsEquals(bytes, it) + }.result +} + +@Test +fun kt39145_3() { + val mainThreadData = MutableData(1_000) + val bytes = byteArrayOf(0, 10, 20, 30) + mainThreadData.append(bytes, 0, 4) + assertEquals(4, mainThreadData.size) + + assertContentsEquals(bytes, mainThreadData) +} + +private fun assertContentsEquals(expected: ByteArray, actual: MutableData) { + assertEquals(expected.size, actual.size) + + expected.forEachIndexed { index, byte -> + assertEquals(byte, actual.get(index)) + } +} \ No newline at end of file diff --git a/kotlin-native/backend.native/tests/runtime/workers/worker0.kt b/kotlin-native/backend.native/tests/runtime/workers/worker0.kt new file mode 100644 index 00000000000..0a6f63bb656 --- /dev/null +++ b/kotlin-native/backend.native/tests/runtime/workers/worker0.kt @@ -0,0 +1,25 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +package runtime.workers.worker0 + +import kotlin.test.* + +import kotlin.native.concurrent.* + +@Test fun runTest() { + val worker = Worker.start() + val future = worker.execute(TransferMode.SAFE, { "Input" }) { + input -> + assertEquals(1, 1) + assertFailsWith { assertEquals(1, 2) } + input + " processed" + } + future.consume { + result -> println("Got $result") + } + worker.requestTermination().result + println("OK") +} \ No newline at end of file diff --git a/kotlin-native/backend.native/tests/runtime/workers/worker1.kt b/kotlin-native/backend.native/tests/runtime/workers/worker1.kt new file mode 100644 index 00000000000..3f86cd876f3 --- /dev/null +++ b/kotlin-native/backend.native/tests/runtime/workers/worker1.kt @@ -0,0 +1,35 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +package runtime.workers.worker1 + +import kotlin.test.* + +import kotlin.native.concurrent.* + +@Test fun runTest() { + val COUNT = 5 + val workers = Array(COUNT, { _ -> Worker.start()}) + + for (attempt in 1 .. 3) { + val futures = Array(workers.size, + { i -> workers[i].execute(TransferMode.SAFE, { "$attempt: Input $i" }) + { input -> input + " processed" } + }) + futures.forEachIndexed { index, future -> + future.consume { + result -> + if ("$attempt: Input $index processed" != result) { + println("Got unexpected $result") + throw Error(result) + } + } + } + } + workers.forEach { + it.requestTermination().result + } + println("OK") +} \ No newline at end of file diff --git a/kotlin-native/backend.native/tests/runtime/workers/worker10.kt b/kotlin-native/backend.native/tests/runtime/workers/worker10.kt new file mode 100644 index 00000000000..9acab985759 --- /dev/null +++ b/kotlin-native/backend.native/tests/runtime/workers/worker10.kt @@ -0,0 +1,184 @@ +package runtime.workers.worker10 + +import kotlin.test.* + +import kotlin.native.concurrent.* +import kotlin.native.ref.WeakReference +import kotlinx.cinterop.StableRef + +class Data(val x: Int) + +val topInt = 1 +val topString = "string" +var topStringVar = "string" +val topSharedStringWithGetter: String + get() = "top" +val topData = Data(42) +@SharedImmutable +val topSharedData = Data(43) + +@Test fun runTest1() { + val worker = Worker.start() + + assertEquals(1, topInt) + assertEquals("string", topString) + assertEquals(42, topData.x) + assertEquals(43, topSharedData.x) + assertEquals("top", topSharedStringWithGetter) + + worker.execute(TransferMode.SAFE, { -> }, { + it -> topInt == 1 + }).consume { + result -> assertEquals(true, result) + } + + worker.execute(TransferMode.SAFE, { -> }, { + it -> topString == "string" + }).consume { + result -> assertEquals(true, result) + } + + worker.execute(TransferMode.SAFE, { -> }, { + it -> try { + topStringVar == "string" + } catch (e: IncorrectDereferenceException) { + false + } + }).consume { + result -> assertEquals(Platform.memoryModel == MemoryModel.RELAXED, result) + } + + worker.execute(TransferMode.SAFE, { -> }, { + it -> try { + topSharedStringWithGetter == "top" + } catch (e: IncorrectDereferenceException) { + false + } + }).consume { + result -> assertEquals(true, result) + } + + worker.execute(TransferMode.SAFE, { -> }, { + it -> try { + topData.x == 42 + } catch (e: IncorrectDereferenceException) { + false + } + }).consume { + result -> assertEquals(Platform.memoryModel == MemoryModel.RELAXED, result) + } + + worker.execute(TransferMode.SAFE, { -> }, { + it -> try { + topSharedData.x == 43 + } catch (e: Throwable) { + false + } + }).consume { + result -> assertEquals(true, result) + } + + worker.requestTermination().result + println("OK") +} + +val atomicRef = AtomicReference(Any().freeze()) +@SharedImmutable +val stableRef = StableRef.create(Any().freeze()) +val semaphore = AtomicInt(0) + +@Test fun runTest2() { + semaphore.value = 0 + val worker = Worker.start() + val future = worker.execute(TransferMode.SAFE, { null }) { + val value = atomicRef.value + semaphore.increment() + while (semaphore.value != 2) {} + println(value.toString() != "") + } + while (semaphore.value != 1) {} + atomicRef.value = null + kotlin.native.internal.GC.collect() + semaphore.increment() + future.result + worker.requestTermination().result +} + +@Test fun runTest3() { + semaphore.value = 0 + val worker = Worker.start() + val future = worker.execute(TransferMode.SAFE, { null }) { + val value = stableRef.get() + semaphore.increment() + while (semaphore.value != 2) {} + println(value.toString() != "") + } + while (semaphore.value != 1) {} + stableRef.dispose() + kotlin.native.internal.GC.collect() + semaphore.increment() + future.result + worker.requestTermination().result +} + +fun ensureWeakIs(weak: WeakReference, expected: T?) { + assertEquals(expected, weak.get()) +} + +val stableHolder1 = StableRef.create(("hello" to "world").freeze()) + +@Test fun runTest4() { + val worker = Worker.start() + semaphore.value = 0 + val future = worker.execute(TransferMode.SAFE, { WeakReference(stableHolder1.get()) }) { + ensureWeakIs(it, "hello" to "world") + semaphore.increment() + while (semaphore.value != 2) {} + kotlin.native.internal.GC.collect() + ensureWeakIs(it, null) + } + while (semaphore.value != 1) {} + stableHolder1.dispose() + kotlin.native.internal.GC.collect() + semaphore.increment() + future.result + worker.requestTermination().result +} + +val stableHolder2 = StableRef.create(("hello" to "world").freeze()) + +@Test fun runTest5() { + val worker = Worker.start() + semaphore.value = 0 + val future = worker.execute(TransferMode.SAFE, { WeakReference(stableHolder2.get()) }) { + val value = it.get() + semaphore.increment() + while (semaphore.value != 2) {} + kotlin.native.internal.GC.collect() + assertEquals("hello" to "world", value) + } + while (semaphore.value != 1) {} + stableHolder2.dispose() + kotlin.native.internal.GC.collect() + semaphore.increment() + future.result + worker.requestTermination().result +} + +val atomicRef2 = AtomicReference(Any().freeze()) +@Test fun runTest6() { + semaphore.value = 0 + val worker = Worker.start() + val future = worker.execute(TransferMode.SAFE, { null }) { + val value = atomicRef2.compareAndSwap(null, null) + semaphore.increment() + while (semaphore.value != 2) {} + assertEquals(true, value.toString() != "") + } + while (semaphore.value != 1) {} + atomicRef2.value = null + kotlin.native.internal.GC.collect() + semaphore.increment() + future.result + worker.requestTermination().result +} \ No newline at end of file diff --git a/kotlin-native/backend.native/tests/runtime/workers/worker11.kt b/kotlin-native/backend.native/tests/runtime/workers/worker11.kt new file mode 100644 index 00000000000..e3a61d18107 --- /dev/null +++ b/kotlin-native/backend.native/tests/runtime/workers/worker11.kt @@ -0,0 +1,117 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +package runtime.workers.worker11 + +import kotlin.test.* + +import kotlin.native.concurrent.* +import kotlinx.cinterop.convert + +data class Job(val index: Int, var input: Int, var counter: Int) + +fun initJobs(count: Int) = Array(count) { i -> Job(i, i * 2, i)} + +@Test fun runTest0() { + val workers = Array(100, { _ -> Worker.start() }) + val jobs = initJobs(workers.size) + val futures = Array(workers.size, { workerIndex -> + workers[workerIndex].execute(TransferMode.SAFE, { + val job = jobs[workerIndex] + jobs[workerIndex] = null + job!! + }) { job -> + job.counter += job.input + job + } + }) + val futureSet = futures.toSet() + var consumed = 0 + while (consumed < futureSet.size) { + val ready = waitForMultipleFutures(futureSet, 10000) + ready.forEach { + it.consume { job -> + assertEquals(job.index * 3, job.counter) + jobs[job.index] = job + } + consumed++ + } + } + assertEquals(consumed, workers.size) + workers.forEach { + it.requestTermination().result + } + println("OK") +} + +val COUNT = 2 + +@SharedImmutable +val counters = Array(COUNT) { AtomicInt(0) } + +@Test fun runTest1() { + val workers = Array(COUNT) { Worker.start() } + // Ensure processQueue() can only be called on current Worker. + workers.forEach { + assertFailsWith { + it.processQueue() + } + } + val futures = Array(workers.size) { workerIndex -> + workers[workerIndex].execute(TransferMode.SAFE, { + workerIndex + }) { + index -> + assertEquals(0, counters[index].value) + // Process following request. + while (!Worker.current!!.processQueue()) {} + // Ensure it has an effect. + assertEquals(1, counters[index].value) + // No more non-terminating tasks in this worker queue. + assertEquals(false, Worker.current!!.processQueue()) + } + } + val futures2 = Array(workers.size) { workerIndex -> + workers[workerIndex].execute(TransferMode.SAFE, { + workerIndex + }) { index -> + assertEquals(0, counters[index].value) + counters[index].increment() + } + } + futures2.forEach { it.result } + futures.forEach { it.result } + workers.forEach { + it.requestTermination().result + } + + // Ensure terminated workers are no longer there. + workers.forEach { + assertFailsWith { it.execute(TransferMode.SAFE, { Unit }) { println("ERROR") } } + } +} + +@Test fun runTest2() { + val workers = Array(COUNT) { Worker.start() } + val futures = Array(workers.size) { workerIndex -> + workers[workerIndex].execute(TransferMode.SAFE, { null }) { + // Here we processed termination request. + assertEquals(false, Worker.current.processQueue()) + } + } + workers.forEach { + it.executeAfter(1000*1000*1000, { + println("DELAY EXECUTED") + assert(false) + }.freeze()) + } + workers.forEach { + it.requestTermination(processScheduledJobs = false).result + } + // Process futures, ignoring possible cancelled ones. + futures.forEach { + try { it.result } catch (e: IllegalStateException) {} + } +} diff --git a/kotlin-native/backend.native/tests/runtime/workers/worker2.kt b/kotlin-native/backend.native/tests/runtime/workers/worker2.kt new file mode 100644 index 00000000000..2cc47f2afb6 --- /dev/null +++ b/kotlin-native/backend.native/tests/runtime/workers/worker2.kt @@ -0,0 +1,45 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +package runtime.workers.worker2 + +import kotlin.test.* + +import kotlin.native.concurrent.* + +data class WorkerArgument(val intParam: Int, val stringParam: String) +data class WorkerResult(val intResult: Int, val stringResult: String) + +@Test fun runTest() { + val COUNT = 5 + val workers = Array(COUNT, { _ -> Worker.start()}) + + for (attempt in 1 .. 3) { + val futures = Array(workers.size, { workerIndex -> workers[workerIndex].execute(TransferMode.SAFE, { + WorkerArgument(workerIndex, "attempt $attempt") }) { input -> + var sum = 0 + for (i in 0..input.intParam * 1000) { + sum += i + } + WorkerResult(sum, input.stringParam + " result") + } + }) + val futureSet = futures.toSet() + var consumed = 0 + while (consumed < futureSet.size) { + val ready = waitForMultipleFutures(futureSet, 10000) + ready.forEach { + it.consume { result -> + if (result.stringResult != "attempt $attempt result") throw Error("Unexpected $result") + consumed++ + } + } + } + } + workers.forEach { + it.requestTermination().result + } + println("OK") +} \ No newline at end of file diff --git a/kotlin-native/backend.native/tests/runtime/workers/worker3.kt b/kotlin-native/backend.native/tests/runtime/workers/worker3.kt new file mode 100644 index 00000000000..03e54aee3c8 --- /dev/null +++ b/kotlin-native/backend.native/tests/runtime/workers/worker3.kt @@ -0,0 +1,36 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +package runtime.workers.worker3 + +import kotlin.test.* + +import kotlin.native.concurrent.* + +data class DataParam(var int: Int) +data class WorkerArgument(val intParam: Int, val dataParam: DataParam) +data class WorkerResult(val intResult: Int, val stringResult: String) + +@Test fun runTest() { + main(emptyArray()) +} + +fun main(args: Array) { + val worker = Worker.start() + val dataParam = DataParam(17) + val future = try { + worker.execute(TransferMode.SAFE, + { WorkerArgument(42, dataParam) }) { + input -> WorkerResult(input.intParam, input.dataParam.toString() + " result") + } + } catch (e: IllegalStateException) { + null + } + if (future != null && Platform.memoryModel == MemoryModel.STRICT) + println("Fail 1") + if (dataParam.int != 17) println("Fail 2") + worker.requestTermination().result + println("OK") +} \ No newline at end of file diff --git a/kotlin-native/backend.native/tests/runtime/workers/worker4.kt b/kotlin-native/backend.native/tests/runtime/workers/worker4.kt new file mode 100644 index 00000000000..a6a20b207de --- /dev/null +++ b/kotlin-native/backend.native/tests/runtime/workers/worker4.kt @@ -0,0 +1,120 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +package runtime.workers.worker4 + +import kotlin.test.* + +import kotlin.native.concurrent.* + +@Test fun runTest1() { + withWorker { + val future = execute(TransferMode.SAFE, { 41 }) { input -> + input + 1 + } + future.consume { result -> + println("Got $result") + } + } + println("OK") +} + +@Test fun runTest2() { + withWorker { + val counter = AtomicInt(0) + + executeAfter(0, { + assertTrue(Worker.current.park(10_000_000, false)) + assertEquals(counter.value, 0) + assertTrue(Worker.current.processQueue()) + assertEquals(1, counter.value) + // Let main proceed. + counter.increment() // counter becomes 2 here. + assertTrue(Worker.current.park(10_000_000, true)) + assertEquals(3, counter.value) + }.freeze()) + + executeAfter(0, { + counter.increment() + }.freeze()) + + while (counter.value < 2) { + Worker.current.park(1_000) + } + + executeAfter(0, { + counter.increment() + }.freeze()) + + while (counter.value == 2) { + Worker.current.park(1_000) + } + } +} + +@Test fun runTest3() { + val worker = Worker.start(name = "Lumberjack") + val counter = AtomicInt(0) + worker.executeAfter(0, { + assertEquals("Lumberjack", Worker.current.name) + counter.increment() + }.freeze()) + + while (counter.value == 0) { + Worker.current.park(1_000) + } + assertEquals("Lumberjack", worker.name) + worker.requestTermination().result + assertFailsWith { + println(worker.name) + } +} + +@Test fun runTest4() { + val counter = AtomicInt(0) + Worker.current.executeAfter(10_000, { + counter.increment() + }.freeze()) + assertTrue(Worker.current.park(1_000_000, process = true)) + assertEquals(1, counter.value) +} + +@Test fun runTest5() { + val main = Worker.current + val counter = AtomicInt(0) + withWorker { + executeAfter(1000, { + main.executeAfter(1, { + counter.increment() + }.freeze()) + }.freeze()) + assertTrue(main.park(1000L * 1000 * 1000, process = true)) + assertEquals(1, counter.value) + } +} + +@Test fun runTest6() { + // Ensure zero timeout works properly. + Worker.current.park(0, process = true) +} + +@Test fun runTest7() { + val counter = AtomicInt(0) + withWorker { + val f1 = execute(TransferMode.SAFE, { counter }) { counter -> + Worker.current.park(Long.MAX_VALUE / 1000L, process = true) + counter.increment() + } + // wait a bit + Worker.current.park(10_000L) + // submit a task + val f2 = execute(TransferMode.SAFE, { counter }) { counter -> + counter.increment() + } + f1.consume {} + f2.consume {} + assertEquals(2, counter.value) + } +} diff --git a/kotlin-native/backend.native/tests/runtime/workers/worker5.kt b/kotlin-native/backend.native/tests/runtime/workers/worker5.kt new file mode 100644 index 00000000000..7463eb026b1 --- /dev/null +++ b/kotlin-native/backend.native/tests/runtime/workers/worker5.kt @@ -0,0 +1,52 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +import kotlin.test.* + +import kotlin.native.concurrent.* + +@Test fun runTest0() { + val worker = Worker.start() + val future = worker.execute(TransferMode.SAFE, { "zzz" }) { + input -> input.length + } + future.consume { + result -> println("Got $result") + } + worker.requestTermination().result + println("OK") +} + +var done = false + +@Test fun runTest1() { + val worker = Worker.current + done = false + // Here we request execution of the operation on the current worker. + worker.executeAfter(0, { + done = true + }.freeze()) + while (!done) + worker.processQueue() +} + +// Ensure that termination of current worker on main thread doesn't lead to problems. +@Test fun runTest2() { + val worker = Worker.current + val future = worker.requestTermination(false) + worker.processQueue() + assertEquals(future.state, FutureState.COMPUTED) + future.consume {} + // After termination request this worker is no longer addressable. + assertFailsWith { worker.executeAfter(0, { + println("BUG!") + }.freeze()) } +} + +fun main() { + runTest0() + runTest1() + runTest2() +} \ No newline at end of file diff --git a/kotlin-native/backend.native/tests/runtime/workers/worker6.kt b/kotlin-native/backend.native/tests/runtime/workers/worker6.kt new file mode 100644 index 00000000000..0bd0a4df46a --- /dev/null +++ b/kotlin-native/backend.native/tests/runtime/workers/worker6.kt @@ -0,0 +1,38 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +package runtime.workers.worker6 + +import kotlin.test.* + +import kotlin.native.concurrent.* + +@Test fun runTest1() { + withWorker { + val future = execute(TransferMode.SAFE, { 42 }) { input -> + input.toString() + } + future.consume { result -> + println("Got $result") + } + } + println("OK") +} + +var int1 = 1 +val int2 = 77 + +@Test fun runTest2() { + int1++ + withWorker { + executeAfter(0, { + assertFailsWith { + int1++ + } + assertEquals(2, int1) + assertEquals(77, int2) + }.freeze()) + } +} \ No newline at end of file diff --git a/kotlin-native/backend.native/tests/runtime/workers/worker7.kt b/kotlin-native/backend.native/tests/runtime/workers/worker7.kt new file mode 100644 index 00000000000..b045cb9dc1b --- /dev/null +++ b/kotlin-native/backend.native/tests/runtime/workers/worker7.kt @@ -0,0 +1,28 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +package runtime.workers.worker7 + +import kotlin.test.* + +import kotlin.native.concurrent.* + +@Test fun runTest() { + val worker = Worker.start(false) + val future = worker.execute(TransferMode.SAFE, { "Input" }) { + input -> println(input) + } + future.consume { + result -> println("Got $result") + } + + assertFailsWith { + println(worker.execute(TransferMode.SAFE, { null }, { _ -> throw Error("An error") }).result) + } + + worker.requestTermination().result + + println("OK") +} \ No newline at end of file diff --git a/kotlin-native/backend.native/tests/runtime/workers/worker8.kt b/kotlin-native/backend.native/tests/runtime/workers/worker8.kt new file mode 100644 index 00000000000..72ebb86b2fd --- /dev/null +++ b/kotlin-native/backend.native/tests/runtime/workers/worker8.kt @@ -0,0 +1,32 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +package runtime.workers.worker8 + +import kotlin.test.* + +import kotlin.native.concurrent.* + +data class SharedDataMember(val double: Double) + +data class SharedData(val string: String, val int: Int, val member: SharedDataMember) + +@Test fun runTest() { + val worker = Worker.start() + // Here we do rather strange thing. To test object detach API we detach object graph, + // pass detached graph to a worker, where we manually reattached passed value. + val future = worker.execute(TransferMode.SAFE, { + DetachedObjectGraph { SharedData("Hello", 10, SharedDataMember(0.1)) }.asCPointer() + }) { + inputDetached -> + val input = DetachedObjectGraph(inputDetached).attach() + println(input) + } + future.consume { + result -> println("Got $result") + } + worker.requestTermination().result + println("OK") +} \ No newline at end of file diff --git a/kotlin-native/backend.native/tests/runtime/workers/worker9.kt b/kotlin-native/backend.native/tests/runtime/workers/worker9.kt new file mode 100644 index 00000000000..247780f5e8a --- /dev/null +++ b/kotlin-native/backend.native/tests/runtime/workers/worker9.kt @@ -0,0 +1,84 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +package runtime.workers.worker9 + +import kotlin.test.* + +import kotlin.native.concurrent.* + +@Test fun runTest1() { + withLock { println("zzz") } + val worker = Worker.start() + val future = worker.execute(TransferMode.SAFE, {}) { + withLock { + println("42") + } + } + future.result + worker.requestTermination().result + println("OK") +} + +fun withLock(op: () -> Unit) { + op() +} + +@Test fun runTest2() { + val worker = Worker.start() + val future = worker.execute(TransferMode.SAFE, {}) { + val me = Worker.current + var x = 1 + me.executeAfter (20000) { + println("second ${++x}") + } + me.executeAfter(10000) { + println("first ${++x}") + } + } + worker.requestTermination().result +} + +@Test fun runTest3() { + val worker = Worker.start() + assertFailsWith { + worker.executeAfter { + println("shall not happen") + } + } + assertFailsWith { + worker.executeAfter(-1, { + println("shall not happen") + }.freeze()) + } + + worker.executeAfter(0, { + println("frozen OK") + }.freeze()) + + worker.requestTermination().result +} + +class Node(var node: Node?, var outher: Node?) + +fun makeCyclic(): Node { + val inner = Node(null, null) + inner.node = inner + val outer = Node(null, null) + inner.outher = outer + return outer +} + +@Test fun runTest4() { + val worker = Worker.start() + + val future = worker.execute(TransferMode.SAFE, { }) { + makeCyclic().also { + kotlin.native.internal.GC.collect() + } + } + assert(future.result != null) + worker.requestTermination().result +} \ No newline at end of file diff --git a/kotlin-native/backend.native/tests/serialization/catch.kt b/kotlin-native/backend.native/tests/serialization/catch.kt new file mode 100644 index 00000000000..9ed7fc76f5a --- /dev/null +++ b/kotlin-native/backend.native/tests/serialization/catch.kt @@ -0,0 +1,18 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + + +inline fun foo() { + try { + try { + throw Exception("XXX") + } catch (e: Throwable) { + println("Gotcha1: ${e.message}") + throw Exception("YYY") + } + } catch (e: Throwable) { + println("Gotcha2: ${e.message}") + } +} diff --git a/kotlin-native/backend.native/tests/serialization/char_const.kt b/kotlin-native/backend.native/tests/serialization/char_const.kt new file mode 100644 index 00000000000..31cc0e9bfd4 --- /dev/null +++ b/kotlin-native/backend.native/tests/serialization/char_const.kt @@ -0,0 +1,6 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +inline fun foo(x: Char = '\u042b') = x diff --git a/kotlin-native/backend.native/tests/serialization/default_args.kt b/kotlin-native/backend.native/tests/serialization/default_args.kt new file mode 100644 index 00000000000..d019ebb1e1e --- /dev/null +++ b/kotlin-native/backend.native/tests/serialization/default_args.kt @@ -0,0 +1,10 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + + +inline val Int.prop get() = SomeDataClass(second = this) + +data class SomeDataClass(val first: Int = 17, val second: Int = 19, val third: Int = 23) + diff --git a/kotlin-native/backend.native/tests/serialization/deserialize_members.kt b/kotlin-native/backend.native/tests/serialization/deserialize_members.kt new file mode 100644 index 00000000000..b9817955960 --- /dev/null +++ b/kotlin-native/backend.native/tests/serialization/deserialize_members.kt @@ -0,0 +1,39 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +import foo.bar.* + +fun main(args: Array) { + val c = C() + val d = C.D() + val e = C.D.E() + c.foo() + d.foo() + e.foo() + + val c2 = C2() + val d2 = C2().D2() + val e2 = C2().D2().E2() + c2.foo() + d2.foo() + e2.foo() + + val c3 = C3() + val d3 = C3.D3() + val e3 = C3.D3.E3() + c3.foo(13) + d3.foo("cha-cha-cha") + e3.foo(1.0f) + + // This part doesn't work with file local inline functions. + // So disabled for now. + // val c4 = C4() + // val d4 = C4().D4() + // val e4 = C4().D4().E4() + // c4.foo(13) + // d4.foo("cawabunga", 17) + // e4.foo(19, "raqa-taqa", 23) + +} diff --git a/kotlin-native/backend.native/tests/serialization/deserialized_inline0.kt b/kotlin-native/backend.native/tests/serialization/deserialized_inline0.kt new file mode 100644 index 00000000000..8fc31da568e --- /dev/null +++ b/kotlin-native/backend.native/tests/serialization/deserialized_inline0.kt @@ -0,0 +1,34 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +package serialization.deserialized_inline0 + +import kotlin.test.* + + +fun inline_todo() { + try { + TODO("OK") + } catch (e: Throwable) { + println(e.message) + } +} + +fun inline_maxof() { + println(maxOf(10, 17)) + println(maxOf(17, 13)) + println(maxOf(17, 17)) +} + +fun inline_assert() { + //assert(true) +} + +@Test fun runTest() { + inline_todo() + inline_assert() + inline_maxof() +} + diff --git a/kotlin-native/backend.native/tests/serialization/deserialized_listof0.kt b/kotlin-native/backend.native/tests/serialization/deserialized_listof0.kt new file mode 100644 index 00000000000..28a97a61bdf --- /dev/null +++ b/kotlin-native/backend.native/tests/serialization/deserialized_listof0.kt @@ -0,0 +1,37 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +package serialization.deserialized_listof0 + +import kotlin.test.* + +fun test_arrayList() { + val l = listOf(1, 2, 3) + val m = listOf() + val n = l + m + println(n) +} + +fun test_arrayList2(x: T, y: T, z: T) { + val l = listOf(x, y, z) + val m = listOf() + val n = m + l + println(l) +} + +fun test_arrayList3() { + val l = listOf() + val m = listOf("a", "b", "c") + val n = l + m + println(n) +} + +@Test fun runTest() { + test_arrayList() + test_arrayList2(5, 6, 7) + test_arrayList2("a", "b", "c") + test_arrayList3() +} + diff --git a/kotlin-native/backend.native/tests/serialization/do_while.kt b/kotlin-native/backend.native/tests/serialization/do_while.kt new file mode 100644 index 00000000000..eb96619bdbb --- /dev/null +++ b/kotlin-native/backend.native/tests/serialization/do_while.kt @@ -0,0 +1,12 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + + +inline fun foo() { + do { + var x: Int = 999 + println(x) + } while (x != 999) +} diff --git a/kotlin-native/backend.native/tests/serialization/enum_ordinal/library.kt b/kotlin-native/backend.native/tests/serialization/enum_ordinal/library.kt new file mode 100644 index 00000000000..e4a53af9306 --- /dev/null +++ b/kotlin-native/backend.native/tests/serialization/enum_ordinal/library.kt @@ -0,0 +1,14 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +enum class Color { + RED, GREEN, BLUE, CYAN, MAGENTA, YELLOW +} + +fun determineColor(code: Int): Color = when (code) { + 0 -> Color.BLUE + 1 -> Color.MAGENTA + else -> Color.CYAN +} \ No newline at end of file diff --git a/kotlin-native/backend.native/tests/serialization/enum_ordinal/main.kt b/kotlin-native/backend.native/tests/serialization/enum_ordinal/main.kt new file mode 100644 index 00000000000..7801b043164 --- /dev/null +++ b/kotlin-native/backend.native/tests/serialization/enum_ordinal/main.kt @@ -0,0 +1,19 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +fun main(args: Array) { + println(Color.RED.ordinal) + println(Color.GREEN.ordinal) + println(Color.BLUE.ordinal) + val color = when (determineColor(args.size)) { + Color.RED -> println("r") + Color.GREEN -> println("g") + Color.BLUE -> println("b") + Color.CYAN -> println("c") + Color.MAGENTA -> println("m") + Color.YELLOW -> println("y") + + } +} \ No newline at end of file diff --git a/kotlin-native/backend.native/tests/serialization/prop.kt b/kotlin-native/backend.native/tests/serialization/prop.kt new file mode 100644 index 00000000000..20751feb97f --- /dev/null +++ b/kotlin-native/backend.native/tests/serialization/prop.kt @@ -0,0 +1,8 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +fun main(args: Array) { + println(666.prop) +} diff --git a/kotlin-native/backend.native/tests/serialization/regression/no_type_map.kt b/kotlin-native/backend.native/tests/serialization/regression/no_type_map.kt new file mode 100644 index 00000000000..b46b92c5466 --- /dev/null +++ b/kotlin-native/backend.native/tests/serialization/regression/no_type_map.kt @@ -0,0 +1,13 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +import kotlinx.cinterop.* +fun main(args: Array) { + memScoped { + val bufferLength = 100L + val buffer = allocArray(bufferLength) + } + println("OK") +} diff --git a/kotlin-native/backend.native/tests/serialization/serialize_members.kt b/kotlin-native/backend.native/tests/serialization/serialize_members.kt new file mode 100644 index 00000000000..1cd454e1ae0 --- /dev/null +++ b/kotlin-native/backend.native/tests/serialization/serialize_members.kt @@ -0,0 +1,85 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +package foo.bar + +class R { + inline fun bar(t: T) { + println("just a single class: $t") + } +} + +class C { + inline fun foo() { + println("first level") + } + + class D { + inline fun foo() { + println("second level") + } + + class E { + inline fun foo() { + println("third levelxz") + } + } + } +} + +class C2 { + inline fun foo() { + println("inner first level") + } + + inner class D2 { + inline fun foo() { + println("inner second level") + } + + inner class E2 { + inline fun foo() { + println("inner third level") + } + } + } +} + +class C3 { + inline fun foo(x: X) { + println("types first level: $x") + } + + class D3 { + inline fun foo(x: X) { + println("types second level $x") + } + + class E3 { + inline fun foo(x: X) { + println("types third level $x") + } + } + } +} + +class C4 { + inline fun foo(x: X) { + println("inner types first level: $x") + } + + inner class D4 { + inline fun foo(x: X, y: Y) { + println("inner types second level $x, $y") + } + + inner class E4 { + inline fun foo(x: X, y: Y, z: Z) { + println("inner types third level $x, $y, $z") + } + } + } +} + diff --git a/kotlin-native/backend.native/tests/serialization/use.kt b/kotlin-native/backend.native/tests/serialization/use.kt new file mode 100644 index 00000000000..8a0446a79af --- /dev/null +++ b/kotlin-native/backend.native/tests/serialization/use.kt @@ -0,0 +1,9 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + + +fun main(args: Array) { + foo() +} diff --git a/kotlin-native/backend.native/tests/serialization/use_char_const.kt b/kotlin-native/backend.native/tests/serialization/use_char_const.kt new file mode 100644 index 00000000000..82bd39a9e27 --- /dev/null +++ b/kotlin-native/backend.native/tests/serialization/use_char_const.kt @@ -0,0 +1,8 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +fun main(args: Array) { + println(foo()) +} diff --git a/kotlin-native/backend.native/tests/serialization/vararg.kt b/kotlin-native/backend.native/tests/serialization/vararg.kt new file mode 100644 index 00000000000..46f037d89ec --- /dev/null +++ b/kotlin-native/backend.native/tests/serialization/vararg.kt @@ -0,0 +1,14 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +fun bar(vararg x: Int) { + x.forEach { + println(it) + } + println("size: ${x.size}") +} + +inline fun foo() = bar(17, 19, 23, *intArrayOf(29, 31)) + diff --git a/kotlin-native/backend.native/tests/stdlib_external/jsCollectionFactoriesActuals.kt b/kotlin-native/backend.native/tests/stdlib_external/jsCollectionFactoriesActuals.kt new file mode 100644 index 00000000000..bebf7f4792f --- /dev/null +++ b/kotlin-native/backend.native/tests/stdlib_external/jsCollectionFactoriesActuals.kt @@ -0,0 +1,11 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +package test.collections.js + +actual fun stringMapOf(vararg pairs: Pair): HashMap = hashMapOf(*pairs) +actual fun linkedStringMapOf(vararg pairs: Pair): LinkedHashMap = linkedMapOf(*pairs) +actual fun stringSetOf(vararg elements: String): HashSet = hashSetOf(*elements) +actual fun linkedStringSetOf(vararg elements: String): LinkedHashSet = linkedSetOf(*elements) \ No newline at end of file diff --git a/kotlin-native/backend.native/tests/stdlib_external/numbers/HarmonyMathTests.kt b/kotlin-native/backend.native/tests/stdlib_external/numbers/HarmonyMathTests.kt new file mode 100644 index 00000000000..488c1301013 --- /dev/null +++ b/kotlin-native/backend.native/tests/stdlib_external/numbers/HarmonyMathTests.kt @@ -0,0 +1,824 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package test.numbers.harmony_math + +import kotlin.math.* +import kotlin.test.* + +class HarmonyMath { + + fun assertEquals(expected: Double, actual: Double, tolerance: Double? = null) = + assertEquals(null, expected, actual, tolerance) + + fun assertEquals(expected: Float, actual: Float, tolerance: Float? = null) = + assertEquals(null, expected, actual, tolerance) + + fun Double.Companion.isNaN(v: Double) = v.isNaN() + fun Float.Companion.isNaN(v: Float) = v.isNaN() + + fun pow(a: Double, b: Double) = a.pow(b) + fun pow(a: Float, b: Float) = a.pow(b) + + fun ulp(v: Double) = v.ulp + fun ulp(v: Float) = v.ulp + + fun assertEquals(message: String?, expected: Int, actual: Int) = assertEquals(expected, actual, message) + fun assertEquals(message: String?, expected: Long, actual: Long) = assertEquals(expected, actual, message) + + fun assertEquals(message: String?, expected: Double, actual: Double, tolerance: Double? = null) { + val tolerance_ = tolerance?.let { abs(it) } ?: 0.000000000001 + if (abs(expected - actual) > tolerance_) { + assertEquals(expected, actual, message) + } + } + + fun assertEquals(message: String?, expected: Float, actual: Float, tolerance: Float? = null) { + val tolerance_ = tolerance?.let { abs(it) } ?: 0.0000001f + if (abs(expected - actual) > tolerance_) { + assertEquals(expected, actual, message) + } + } + + fun assertTrue(message: String? = null, condition: Boolean) = assertTrue(condition, message) + + internal var HYP = sqrt(2.0) + + internal var OPP = 1.0 + + internal var ADJ = 1.0 + + /* Required to make previous preprocessor flags work - do not remove */ + internal var unused = 0 + + /** + * Tests kotlin.math.abs(Double) + */ + @Test fun absD() { + // Test for abs(Double): Double + + assertTrue("Incorrect Double abs value", + abs(-1908.8976) == 1908.8976) + assertTrue("Incorrect Double abs value", + abs(1908.8976) == 1908.8976) + } + + /** + * Tests kotlin.math.abs(float) + */ + @Test fun absF() { + // Test for abs(float): float + assertTrue("Incorrect float abs value", + abs(-1908.8976f) == 1908.8976f) + assertTrue("Incorrect float abs value", + abs(1908.8976f) == 1908.8976f) + } + + /** + * Tests kotlin.math.abs(int) + */ + @Test fun absI() { + // Test for abs(int): int + assertTrue("Incorrect int abs value", abs(-1908897) == 1908897) + assertTrue("Incorrect int abs value", abs(1908897) == 1908897) + } + + /** + * Tests kotlin.math.abs(long) + */ + @Test fun absJ() { + // Test for abs(long): long + assertTrue("Incorrect long abs value", + abs(-19088976000089L) == 19088976000089L) + assertTrue("Incorrect long abs value", + abs(19088976000089L) == 19088976000089L) + } + + /** + * Tests kotlin.math.acos(Double) + */ + @Test fun acosD() { + // Test for acos(Double): Double + val r = cos(acos(ADJ / HYP)) + val lr = r.toBits() + val t = (ADJ / HYP).toBits() + assertTrue("Returned incorrect arc cosine", lr == t || lr + 1 == t || lr - 1 == t) + } + + /** + * Tests kotlin.math.asin(Double) + */ + @Test fun asinD() { + // Test for asin(Double): Double + val r = sin(asin(OPP / HYP)) + val lr = r.toBits() + val t = (OPP / HYP).toBits() + assertTrue("Returned incorrect arc sine", lr == t || lr + 1 == t || lr - 1 == t) + } + + /** + * Tests kotlin.math.atan(Double) + */ + @Test fun atanD() { + // Test for atan(Double): Double + val answer = tan(atan(1.0)) + assertTrue("Returned incorrect arc tangent: " + answer, answer <= 1.0 && answer >= 9.9999999999999983E-1) + } + + /** + * Tests kotlin.math.atan2(Double, Double) + */ + @Test fun atan2DD() { + // Test for atan2(Double, Double): Double + val answer = atan(tan(1.0)) + assertTrue("Returned incorrect arc tangent: " + answer, answer <= 1.0 && answer >= 9.9999999999999983E-1) + } + + /** + * Tests kotlin.math.ceil(Double) + */ + @Test fun ceilD() { + // Test for ceil(Double): Double + assertEquals("Incorrect ceiling for Double", + 79.0, ceil(78.89), 0.0) + assertEquals("Incorrect ceiling for Double", + -78.0, ceil(-78.89), 0.0) + } + + /** + * Tests kotlin.math.withSign(Double) + */ + @Test fun withSign_D() { + for (i in COPYSIGN_DD_CASES.indices) { + val magnitude = COPYSIGN_DD_CASES[i] + val absMagnitudeBits = abs(magnitude).toBits() + val negMagnitudeBits = (-abs(magnitude)).toBits() + + assertTrue("The result should be NaN.", Double.isNaN(Double.NaN.withSign(magnitude))) + + for (j in COPYSIGN_DD_CASES.indices) { + val sign = COPYSIGN_DD_CASES[j] + val resultBits = magnitude.withSign(sign).toBits() + + if (sign > 0 || (+0.0).toBits() == sign.toBits() || 0.0.toBits() == sign.toBits()) { + assertEquals( + "If the sign is positive, the result should be positive.", + absMagnitudeBits, resultBits) + } + if (sign < 0 || (-0.0).toBits() == sign.toBits()) { + assertEquals( + "If the sign is negative, the result should be negative.", + negMagnitudeBits, resultBits) + } + } + } + + assertTrue("The result should be NaN.", Double.isNaN(Double.NaN.withSign(Double.NaN))) + } + + /** + * Tests kotlin.math.withSign(Float) + */ + @Test fun withSign_F() { + for (i in COPYSIGN_FF_CASES.indices) { + val magnitude = COPYSIGN_FF_CASES[i] + val absMagnitudeBits = abs(magnitude).toBits() + val negMagnitudeBits = (-abs(magnitude)).toBits() + + assertTrue("The result should be NaN.", Float.isNaN(Float.NaN.withSign(magnitude))) + + for (j in COPYSIGN_FF_CASES.indices) { + val sign = COPYSIGN_FF_CASES[j] + val resultBits = magnitude.withSign(sign).toBits() + if (sign > 0 || (+0.0f).toBits() == sign.toBits() || 0.0f.toBits() == sign.toBits()) { + assertEquals( + "If the sign is positive, the result should be positive.", + absMagnitudeBits, resultBits) + } + if (sign < 0 || (-0.0f).toBits() == sign.toBits()) { + assertEquals( + "If the sign is negative, the result should be negative.", + negMagnitudeBits, resultBits) + } + } + } + + assertTrue("The result should be NaN.", Float.isNaN(Float.NaN.withSign(Float.NaN))) + } + + /** + * Tests kotlin.math.cos(Double) + */ + @Test fun cosD() { + // Test for cos(Double): Double + assertEquals("Incorrect answer", 1.0, cos(0.0), 0.0) + assertEquals("Incorrect answer", 0.5403023058681398, cos(1.0), 0.0) + } + + /** + * Tests kotlin.math.cosh(Double) + */ + @Test fun cosh_D() { + // Test for special situations + assertTrue(Double.isNaN(cosh(Double.NaN))) + assertEquals("Should return POSITIVE_INFINITY", + Double.POSITIVE_INFINITY, cosh(Double.POSITIVE_INFINITY), 0.0) + assertEquals("Should return POSITIVE_INFINITY", + Double.POSITIVE_INFINITY, cosh(Double.NEGATIVE_INFINITY), 0.0) + assertEquals("Should return 1.0", 1.0, cosh(+0.0), 0.0) + assertEquals("Should return 1.0", 1.0, cosh(-0.0), 0.0) + + assertEquals("Should return POSITIVE_INFINITY", + Double.POSITIVE_INFINITY, cosh(1234.56), 0.0) + assertEquals("Should return POSITIVE_INFINITY", + Double.POSITIVE_INFINITY, cosh(-1234.56), 0.0) + assertEquals("Should return 1.0000000000005", 1.0000000000005, cosh(0.000001), 0.0) + assertEquals("Should return 1.0000000000005", 1.0000000000005, cosh(-0.000001), 0.0) + assertEquals("Should return 5.212214351945598", 5.212214351945598, cosh(2.33482), 0.0) + + assertEquals("Should return POSITIVE_INFINITY", + Double.POSITIVE_INFINITY, cosh(Double.MAX_VALUE), 0.0) + assertEquals("Should return 1.0", 1.0, cosh(Double.MIN_VALUE), 0.0) + } + + /** + * Tests kotlin.math.exp(Double) + */ + @Test fun expD() { + // Test for exp(Double): Double + assertTrue("Incorrect answer returned for simple power", abs(exp(4.0) - E * E * E * E) < 0.1) + assertTrue("Incorrect answer returned for larger power", ln(abs(exp(5.5)) - 5.5) < 10.0) + } + + /** + * Tests kotlin.math.expm1(Double) + */ + @Test fun expm1_D() { + // Test for special cases + assertTrue("Should return NaN", Double.isNaN(expm1(Double.NaN))) + assertEquals("Should return POSITIVE_INFINITY", + Double.POSITIVE_INFINITY, expm1(Double.POSITIVE_INFINITY), 0.0) + assertEquals("Should return -1.0", -1.0, expm1(Double.NEGATIVE_INFINITY), 0.0) + + assertEquals(0.0.toBits(), expm1(0.0).toBits()) + assertEquals(+0.0.toBits(), expm1(+0.0).toBits()) + assertEquals((-0.0).toBits(), expm1(-0.0).toBits()) + + assertEquals("Should return -9.999950000166666E-6", + -9.999950000166666E-6, expm1(-0.00001)) + assertEquals("Should return 1.0145103074469635E60", + 1.0145103074469635E60, expm1(138.16951162), 0.0) + assertEquals("Should return POSITIVE_INFINITY", + Double.POSITIVE_INFINITY, expm1(123456789123456789123456789.4521584223), 0.0) + assertEquals("Should return POSITIVE_INFINITY", + Double.POSITIVE_INFINITY, expm1(Double.MAX_VALUE), 0.0) + assertEquals("Should return MIN_VALUE", Double.MIN_VALUE, expm1(Double.MIN_VALUE), 0.0) + } + + /** + * Tests kotlin.math.floor(Double) + */ + @Test fun floorD() { + assertEquals("Incorrect floor for int", 42.0, floor(42.0), 0.0) + assertEquals("Incorrect floor for -int", -2.0, floor(-2.0), 0.0) + assertEquals("Incorrect floor for zero", 0.0, floor(0.0), 0.0) + + assertEquals("Incorrect floor for +Double", 78.0, floor(78.89), 0.0) + assertEquals("Incorrect floor for -Double", -79.0, floor(-78.89), 0.0) + assertEquals("floor large +Double", 3.7314645675925406E19, floor(3.7314645675925406E19), 0.0) + assertEquals("floor large -Double", -8.173521839218E12, floor(-8.173521839218E12), 0.0) + assertEquals("floor small Double", 0.0, floor(1.11895241315E-102), 0.0) + + // Compare toString representations here since -0.0 = +0.0, and + // NaN != NaN and we need to distinguish + + assertEquals(Double.NaN.toString(), floor(Double.NaN).toString(), "Floor failed for NaN") + assertEquals((+0.0).toString(), floor(+0.0).toString(), "Floor failed for +0.0") + assertEquals((-0.0).toString(), floor(-0.0).toString(), "Floor failed for -0.0") + assertEquals(Double.POSITIVE_INFINITY.toString(), floor(Double.POSITIVE_INFINITY).toString(), + "Floor failed for +infinity") + assertEquals(Double.NEGATIVE_INFINITY.toString(), floor(Double.NEGATIVE_INFINITY).toString(), + "Floor failed for -infinity") + } + + /** + * Tests kotlin.math.hypot(Double, Double) + */ + @Test fun hypot_DD() { + // Test for special cases + assertEquals("Should return POSITIVE_INFINITY", + Double.POSITIVE_INFINITY, hypot(Double.POSITIVE_INFINITY, + 1.0), 0.0) + assertEquals("Should return POSITIVE_INFINITY", + Double.POSITIVE_INFINITY, hypot(Double.NEGATIVE_INFINITY, + 123.324), 0.0) + assertEquals("Should return POSITIVE_INFINITY", + Double.POSITIVE_INFINITY, hypot(-758.2587, + Double.POSITIVE_INFINITY), 0.0) + assertEquals("Should return POSITIVE_INFINITY", + Double.POSITIVE_INFINITY, hypot(5687.21, + Double.NEGATIVE_INFINITY), 0.0) + assertEquals("Should return POSITIVE_INFINITY", + Double.POSITIVE_INFINITY, hypot(Double.POSITIVE_INFINITY, + Double.NEGATIVE_INFINITY), 0.0) + assertEquals("Should return POSITIVE_INFINITY", + Double.POSITIVE_INFINITY, hypot(Double.NEGATIVE_INFINITY, + Double.POSITIVE_INFINITY), 0.0) + assertTrue("Should be NaN", Double.isNaN(hypot(Double.NaN, + 2342301.89843))) + assertTrue("Should be NaN", Double.isNaN(hypot(-345.2680, + Double.NaN))) + + assertEquals("Should return 2396424.905416697", 2396424.905416697, hypot(12322.12, -2396393.2258), 0.0) + assertEquals("Should return 138.16958070558556", 138.16958070558556, + hypot(-138.16951162, 0.13817035864), 0.0) + assertEquals("Should return 1.7976931348623157E308", + 1.7976931348623157E308, hypot(Double.MAX_VALUE, 211370.35), 0.0) + assertEquals("Should return 5413.7185", 5413.7185, hypot( + -5413.7185, Double.MIN_VALUE), 0.0) + } + + /** + * Tests kotlin.math.IEEEremainder(Double, Double) + */ + @Test fun IEEEremainderDD() { + // Test for IEEEremainder(Double, Double): Double + assertEquals("Incorrect remainder returned", + 0.0, 1.0.IEEErem(1.0), 0.0) + assertTrue("Incorrect remainder returned", + 1.32.IEEErem(89.765) >= 1.4705063220631647E-2 || 1.32.IEEErem(89.765) >= 1.4705063220631649E-2) + } + + /** + * Tests kotlin.math.ln(Double) + */ + @Test fun lnD() { + // Test for log(Double): Double + var d = 10.0 + while (d >= -10) { + val answer = ln(exp(d)) + assertTrue("Answer does not equal expected answer for d = " + d + + " answer = " + answer, abs(answer - d) <= abs(d * 0.00000001)) + d -= 0.5 + } + } + + /** + * Tests kotlin.math.log10(Double) + */ + @Test fun log10_D() { + // Test for special cases + assertTrue(Double.isNaN(log10(Double.NaN))) + assertTrue(Double.isNaN(log10(-2541.05745687234187532))) + assertTrue(Double.isNaN(log10(-0.1))) + assertEquals(Double.POSITIVE_INFINITY, log10(Double.POSITIVE_INFINITY)) + assertEquals(Double.NEGATIVE_INFINITY, log10(0.0)) + assertEquals(Double.NEGATIVE_INFINITY, log10(+0.0)) + assertEquals(Double.NEGATIVE_INFINITY, log10(-0.0)) + + assertEquals(3.0, log10(1000.0)) + assertEquals(14.0, log10(10.0.pow(14.0))) + assertEquals(3.7389561269540406, log10(5482.2158)) + assertEquals(14.661551142893833, log10(458723662312872.125782332587)) + assertEquals(-0.9083828622192334, log10(0.12348583358871)) + assertEquals(308.25471555991675, log10(Double.MAX_VALUE)) + assertEquals(-323.3062153431158, log10(Double.MIN_VALUE)) + } + + /** + * Tests kotlin.math.ln1p(Double) + */ + @Test fun ln1p_D() { + // Test for special cases + assertTrue("Should return NaN", Double.isNaN(ln1p(Double.NaN))) + assertTrue("Should return NaN", Double.isNaN(ln1p(-32.0482175))) + assertEquals("Should return POSITIVE_INFINITY", + Double.POSITIVE_INFINITY, ln1p(Double.POSITIVE_INFINITY), 0.0) + assertEquals(0.0.toBits(), ln1p(0.0).toBits()) + assertEquals(+0.0.toBits(), ln1p(+0.0).toBits()) + assertEquals((-0.0).toBits(), ln1p(-0.0).toBits()) + + assertEquals("Should return -0.2941782295312541", -0.2941782295312541, + ln1p(-0.254856327), 0.0) + assertEquals("Should return 7.368050685564151", 7.368050685564151, ln1p(1583.542), 0.0) + assertEquals("Should return 0.4633708685409921", 0.4633708685409921, + ln1p(0.5894227), 0.0) + assertEquals("Should return 709.782712893384", 709.782712893384, ln1p(Double.MAX_VALUE), 0.0) + assertEquals("Should return Double.MIN_VALUE", Double.MIN_VALUE, ln1p(Double.MIN_VALUE), 0.0) + } + + /** + * Tests kotlin.math.max(Double, Double) + */ + @Test fun maxDD() { + // Test for max(Double, Double): Double + assertEquals("Incorrect Double max value", 1908897.6000089, max(-1908897.6000089, + 1908897.6000089), 0.0) + assertEquals("Incorrect Double max value", + 1908897.6000089, max(2.0, 1908897.6000089), 0.0) + assertEquals("Incorrect Double max value", -2.0, max(-2.0, + -1908897.6000089), 0.0) + + // Compare toString representations here since -0.0 = +0.0, and + // NaN != NaN and we need to distinguish + assertEquals((Double.NaN).toString(), max(Double.NaN, 42.0).toString(), "Max failed for NaN") + assertEquals((Double.NaN).toString(), max(42.0, Double.NaN).toString(), "Max failed for NaN") + assertEquals((+0.0).toString(), max(+0.0, -0.0).toString(), "Max failed for 0.0") + assertEquals((+0.0).toString(), max(-0.0, +0.0).toString(), "Max failed for 0.0") + assertEquals((-0.0).toString(), max(-0.0, -0.0).toString(), "Max failed for -0.0d") + assertEquals((+0.0).toString(), max(+0.0, +0.0).toString(), "Max failed for 0.0") + } + + /** + * Tests kotlin.math.max(float, float) + */ + @Test fun maxFF() { + // Test for max(float, float): float + assertTrue("Incorrect float max value", max(-1908897.600f, + 1908897.600f) == 1908897.600f) + assertTrue("Incorrect float max value", + max(2.0f, 1908897.600f) == 1908897.600f) + assertTrue("Incorrect float max value", + max(-2.0f, -1908897.600f) == -2.0f) + + // Compare toString representations here since -0.0 = +0.0, and + // NaN != NaN and we need to distinguish + assertEquals(Float.NaN.toString(), max(Float.NaN, 42.0f).toString(), "Max failed for NaN") + assertEquals(Float.NaN.toString(), max(42.0f, Float.NaN).toString(), "Max failed for NaN") + assertEquals((+0.0f).toString(), max(+0.0f, -0.0f).toString(), "Max failed for 0.0") + assertEquals((+0.0f).toString(), max(-0.0f, +0.0f).toString(), "Max failed for 0.0") + assertEquals((-0.0f).toString(), max(-0.0f, -0.0f).toString(), "Max failed for -0.0f") + assertEquals((+0.0f).toString(), max(+0.0f, +0.0f).toString(), "Max failed for 0.0") + } + + /** + * Tests kotlin.math.max(int, int) + */ + @Test fun maxII() { + // Test for max(int, int): int + assertEquals("Incorrect int max value", + 19088976, max(-19088976, 19088976)) + assertEquals("Incorrect int max value", + 19088976, max(20, 19088976)) + assertEquals("Incorrect int max value", -20, max(-20, -19088976)) + } + + /** + * Tests kotlin.math.max(long, long) + */ + @Test fun maxJJ() { + // Test for max(long, long): long + assertEquals("Incorrect long max value", 19088976000089L, max(-19088976000089L, + 19088976000089L)) + assertEquals("Incorrect long max value", + 19088976000089L, max(20, 19088976000089L)) + assertEquals("Incorrect long max value", + -20, max(-20, -19088976000089L)) + } + + /** + * Tests kotlin.math.min(Double, Double) + */ + @Test fun minDD() { + // Test for min(Double, Double): Double + assertEquals("Incorrect Double min value", -1908897.6000089, min(-1908897.6000089, + 1908897.6000089), 0.0) + assertEquals("Incorrect Double min value", + 2.0, min(2.0, 1908897.6000089), 0.0) + assertEquals("Incorrect Double min value", -1908897.6000089, min(-2.0, + -1908897.6000089), 0.0) + assertEquals("Incorrect Double min value", 1.0, min(1.0, 1.0)) + + // Compare toString representations here since -0.0 = +0.0, and + // NaN != NaN and we need to distinguish + assertEquals(Double.NaN.toString(), min(Double.NaN, 42.0).toString(), "Min failed for NaN") + assertEquals(Double.NaN.toString(), min(42.0, Double.NaN).toString(), "Min failed for NaN") + assertEquals((-0.0).toString(), min(+0.0, -0.0).toString(), "Min failed for -0.0") + assertEquals((-0.0).toString(), min(-0.0, +0.0).toString(), "Min failed for -0.0") + assertEquals((-0.0).toString(), min(-0.0, -0.0).toString(), "Min failed for -0.0d") + assertEquals((+0.0).toString(), min(+0.0, +0.0).toString(), "Min failed for 0.0") + } + + /** + * Tests kotlin.math.min(float, float) + */ + @Test fun minFF() { + // Test for min(float, float): float + assertTrue("Incorrect float min value", min(-1908897.600f, + 1908897.600f) == -1908897.600f) + assertTrue("Incorrect float min value", + min(2.0f, 1908897.600f) == 2.0f) + assertTrue("Incorrect float min value", + min(-2.0f, -1908897.600f) == -1908897.600f) + assertEquals("Incorrect float min value", 1.0f, min(1.0f, 1.0f)) + + // Compare toString representations here since -0.0 = +0.0, and + // NaN != NaN and we need to distinguish + assertEquals(Float.NaN.toString(), min(Float.NaN, 42.0f).toString(), "Min failed for NaN") + assertEquals(Float.NaN.toString(), min(42.0f, Float.NaN).toString(), "Min failed for NaN") + assertEquals((-0.0f).toString(), min(+0.0f, -0.0f).toString(), "Min failed for -0.0") + assertEquals((-0.0f).toString(), min(-0.0f, +0.0f).toString(), "Min failed for -0.0") + assertEquals((-0.0f).toString(), min(-0.0f, -0.0f).toString(), "Min failed for -0.0f") + assertEquals((+0.0f).toString(), min(+0.0f, +0.0f).toString(), "Min failed for 0.0") + } + + /** + * Tests kotlin.math.min(int, int) + */ + @Test fun minII() { + // Test for min(int, int): int + assertEquals("Incorrect int min value", + -19088976, min(-19088976, 19088976)) + assertEquals("Incorrect int min value", 20, min(20, 19088976)) + assertEquals("Incorrect int min value", + -19088976, min(-20, -19088976)) + + } + + /** + * @tests java.lang.Math#pow(double, double) + */ + fun test_powDD() { + // Test for method double java.lang.Math.pow(double, double) + assertTrue("pow returned incorrect value", + 2.0.pow(8.0).toLong() == 256L) + assertTrue("pow returned incorrect value", + 2.0.pow(-8.0) == 0.00390625) + assertEquals("Incorrect root returned1", + 2.0, sqrt(sqrt(2.0).pow(4.0)), 0.0) + } + + /** + * Tests kotlin.math.round(Double) + */ + @Test fun roundD() { + // Test for round(Double): Double + assertEquals("Failed to round properly - up to odd", + 3.0, round(2.9), 0.0) + assertTrue("Failed to round properly - NaN", Double.isNaN(round(Double.NaN))) + assertEquals("Failed to round properly down to even", + 2.0, round(2.1), 0.0) + assertTrue("Failed to round properly " + 2.5 + " to even", round(2.5) == 2.0) + assertTrue("Failed to round properly " + +0.0, + round(+0.0) == +0.0) + assertTrue("Failed to round properly " + -0.0, + round(-0.0) == -0.0) + } + + /** + * Tests kotlin.math.sign(Double) + */ + @Test fun sign_D() { + assertTrue(Double.isNaN(sign(Double.NaN))) + assertTrue(Double.isNaN(sign(Double.NaN))) + assertEquals(0.0.toBits(), sign(0.0).toBits()) + assertEquals(+0.0.toBits(), sign(+0.0).toBits()) + assertEquals((-0.0).toBits(), sign(-0.0).toBits()) + + assertEquals(1.0, sign(253681.2187962), 0.0) + assertEquals(-1.0, sign(-125874693.56), 0.0) + assertEquals(1.0, sign(1.2587E-308), 0.0) + assertEquals(-1.0, sign(-1.2587E-308), 0.0) + + assertEquals(1.0, sign(Double.MAX_VALUE), 0.0) + assertEquals(1.0, sign(Double.MIN_VALUE), 0.0) + assertEquals(-1.0, sign(-Double.MAX_VALUE), 0.0) + assertEquals(-1.0, sign(-Double.MIN_VALUE), 0.0) + assertEquals(1.0, sign(Double.POSITIVE_INFINITY), 0.0) + assertEquals(-1.0, sign(Double.NEGATIVE_INFINITY), 0.0) + } + + /** + * Tests kotlin.math.sign(float) + */ + @Test fun sign_F() { + assertTrue(Float.isNaN(sign(Float.NaN))) + assertEquals(0.0f.toBits(), sign(0.0f).toBits()) + assertEquals(+0.0f.toBits(), sign(+0.0f).toBits()) + assertEquals((-0.0f).toBits(), sign(-0.0f).toBits()) + + assertEquals(1.0f, sign(253681.2187962f), 0f) + assertEquals(-1.0f, sign(-125874693.56f), 0f) + assertEquals(1.0f, sign(1.2587E-11f), 0f) + assertEquals(-1.0f, sign(-1.2587E-11f), 0f) + + assertEquals(1.0f, sign(Float.MAX_VALUE), 0f) + assertEquals(1.0f, sign(Float.MIN_VALUE), 0f) + assertEquals(-1.0f, sign(-Float.MAX_VALUE), 0f) + assertEquals(-1.0f, sign(-Float.MIN_VALUE), 0f) + assertEquals(1.0f, sign(Float.POSITIVE_INFINITY), 0f) + assertEquals(-1.0f, sign(Float.NEGATIVE_INFINITY), 0f) + } + + /** + * Tests kotlin.math.sin(Double) + */ + @Test fun sinD() { + // Test for sin(Double): Double + assertEquals("Incorrect answer", 0.0, sin(0.0), 0.0) + assertEquals("Incorrect answer", 0.8414709848078965, sin(1.0), 0.0) + } + + /** + * Tests kotlin.math.sinh(Double) + */ + @Test fun sinh_D() { + // Test for special situations + assertTrue("Should return NaN", Double.isNaN(sinh(Double.NaN))) + assertEquals("Should return POSITIVE_INFINITY", + Double.POSITIVE_INFINITY, sinh(Double.POSITIVE_INFINITY), 0.0) + assertEquals("Should return NEGATIVE_INFINITY", + Double.NEGATIVE_INFINITY, sinh(Double.NEGATIVE_INFINITY), 0.0) + assertEquals(0.0.toBits(), sinh(0.0).toBits()) + assertEquals(+0.0.toBits(), sinh(+0.0).toBits()) + assertEquals((-0.0).toBits(), sinh(-0.0).toBits()) + + assertEquals("Should return POSITIVE_INFINITY", + Double.POSITIVE_INFINITY, sinh(1234.56), 0.0) + assertEquals("Should return NEGATIVE_INFINITY", + Double.NEGATIVE_INFINITY, sinh(-1234.56), 0.0) + assertEquals("Should return 1.0000000000001666E-6", + 1.0000000000001666E-6, sinh(0.000001), 0.0) + assertEquals("Should return -1.0000000000001666E-6", + -1.0000000000001666E-6, sinh(-0.000001), 0.0) + assertEquals("Should return 5.115386441963859", 5.115386441963859, sinh(2.33482)) + assertEquals("Should return POSITIVE_INFINITY", + Double.POSITIVE_INFINITY, sinh(Double.MAX_VALUE), 0.0) + assertEquals("Should return 4.9E-324", 4.9E-324, sinh(Double.MIN_VALUE), 0.0) + } + + /** + * Tests kotlin.math.sqrt(Double) + */ + @Test fun sqrt_D() { + // Test for sqrt(Double): Double + assertEquals("Incorrect root returned2", 7.0, sqrt(49.0), 0.0) + } + + /** + * Tests kotlin.math.tan(Double) + */ + @Test fun tan_D() { + // Test for tan(Double): Double + assertEquals("Incorrect answer", 0.0, tan(0.0), 0.0) + assertEquals("Incorrect answer", 1.5574077246549023, tan(1.0)) + + } + + /** + * Tests kotlin.math.tanh(Double) + */ + @Test fun tanh_D() { + // Test for special situations + assertTrue("Should return NaN", Double.isNaN(tanh(Double.NaN))) + assertEquals("Should return +1.0", +1.0, tanh(Double.POSITIVE_INFINITY), 0.0) + assertEquals("Should return -1.0", -1.0, tanh(Double.NEGATIVE_INFINITY), 0.0) + assertEquals(0.0.toBits(), tanh(0.0).toBits()) + assertEquals(+0.0.toBits(), tanh(+0.0).toBits()) + assertEquals((-0.0).toBits(), tanh(-0.0).toBits()) + + assertEquals("Should return 1.0", 1.0, tanh(1234.56), 0.0) + assertEquals("Should return -1.0", -1.0, tanh(-1234.56), 0.0) + assertEquals("Should return 9.999999999996666E-7", + 9.999999999996666E-7, tanh(0.000001), 0.0) + assertEquals("Should return 0.981422884124941", 0.981422884124941, tanh(2.33482), 0.0) + assertEquals("Should return 1.0", 1.0, tanh(Double.MAX_VALUE), 0.0) + assertEquals("Should return 4.9E-324", 4.9E-324, tanh(Double.MIN_VALUE), 0.0) + } + + /** + * Tests kotlin.Double.ulp + */ + fun test_ulp_D() { + // Test for special cases + assertTrue("Should return NaN", Double.isNaN(ulp(Double.NaN))) + assertEquals("Returned incorrect value", Double.POSITIVE_INFINITY, ulp(Double.POSITIVE_INFINITY), 0.0) + assertEquals("Returned incorrect value", Double.POSITIVE_INFINITY, ulp(Double.NEGATIVE_INFINITY), 0.0) + assertEquals("Returned incorrect value", Double.MIN_VALUE, ulp(0.0), 0.0) + assertEquals("Returned incorrect value", Double.MIN_VALUE, ulp(+0.0), 0.0) + assertEquals("Returned incorrect value", Double.MIN_VALUE, ulp(-0.0), 0.0) + assertEquals("Returned incorrect value", pow(2.0, 971.0), ulp(Double.MAX_VALUE), 0.0) + assertEquals("Returned incorrect value", pow(2.0, 971.0), ulp(-Double.MAX_VALUE), 0.0) + + assertEquals("Returned incorrect value", Double.MIN_VALUE, ulp(Double.MIN_VALUE), 0.0) + assertEquals("Returned incorrect value", Double.MIN_VALUE, ulp(-Double.MIN_VALUE), 0.0) + + assertEquals("Returned incorrect value", 2.220446049250313E-16, ulp(1.0), 0.0) + assertEquals("Returned incorrect value", 2.220446049250313E-16, ulp(-1.0), 0.0) + assertEquals("Returned incorrect value", 2.2737367544323206E-13, ulp(1153.0), 0.0) + } + + /** + * Tests kotlin.Float.ulp + */ + fun test_ulp_f() { + // Test for special cases + assertTrue("Should return NaN", Float.isNaN(ulp(Float.NaN))) + assertEquals("Returned incorrect value", Float.POSITIVE_INFINITY, ulp(Float.POSITIVE_INFINITY), 0f) + assertEquals("Returned incorrect value", Float.POSITIVE_INFINITY, ulp(Float.NEGATIVE_INFINITY), 0f) + assertEquals("Returned incorrect value", Float.MIN_VALUE, ulp(0.0f), 0f) + assertEquals("Returned incorrect value", Float.MIN_VALUE, ulp(+0.0f), 0f) + assertEquals("Returned incorrect value", Float.MIN_VALUE, ulp(-0.0f), 0f) + assertEquals("Returned incorrect value", 2.028241E31f, ulp(Float.MAX_VALUE), 0f) + assertEquals("Returned incorrect value", 2.028241E31f, ulp(-Float.MAX_VALUE), 0f) + + assertEquals("Returned incorrect value", 1.4E-45f, ulp(Float.MIN_VALUE), 0f) + assertEquals("Returned incorrect value", 1.4E-45f, ulp(-Float.MIN_VALUE), 0f) + + assertEquals("Returned incorrect value", 1.1920929E-7f, ulp(1.0f), + 0f) + assertEquals("Returned incorrect value", 1.1920929E-7f, + ulp(-1.0f), 0f) + assertEquals("Returned incorrect value", 1.2207031E-4f, ulp(1153.0f), 0f) + assertEquals("Returned incorrect value", 5.6E-45f, ulp(9.403954E-38f), 0f) + } + + companion object { + + const val MIN_NORMAL_D: Double = 2.2250738585072014E-308 + const val MIN_NORMAL_F: Float = 1.1754943508222875E-38f + + /** + * cases for test_copySign_DD in est/Strictest + */ + internal val COPYSIGN_DD_CASES = doubleArrayOf(Double.POSITIVE_INFINITY, Double.MAX_VALUE, 3.4E302, 2.3, + MIN_NORMAL_D, MIN_NORMAL_D / 2, Double.MIN_VALUE, +0.0, 0.0, -0.0, -Double.MIN_VALUE, + -MIN_NORMAL_D / 2, -MIN_NORMAL_D, -4.5, -3.4E102, -Double.MAX_VALUE, Double.NEGATIVE_INFINITY) + + /** + * cases for test_copySign_FF in est/Strictest + */ + internal val COPYSIGN_FF_CASES = floatArrayOf(Float.POSITIVE_INFINITY, Float.MAX_VALUE, 3.4E12f, 2.3f, + MIN_NORMAL_F, MIN_NORMAL_F / 2, Float.MIN_VALUE, +0.0f, 0.0f, -0.0f, -Float.MIN_VALUE, + -MIN_NORMAL_F / 2, -MIN_NORMAL_F, -4.5f, -5.6442E21f, -Float.MAX_VALUE, Float.NEGATIVE_INFINITY) + + /** + * start number cases for test_nextTowards_DD in est/Strictest + * NEXTAFTER_DD_START_CASES[i][0] is the start number + * NEXTAFTER_DD_START_CASES[i][1] is the nextUp of start number + * NEXTAFTER_DD_START_CASES[i][2] is the nextDown of start number + */ + internal val NEXTAFTER_DD_START_CASES = arrayOf( + doubleArrayOf(3.4, 3.4000000000000004, 3.3999999999999995), + doubleArrayOf(-3.4, -3.3999999999999995, -3.4000000000000004), + doubleArrayOf(3.4233E109, 3.4233000000000005E109, 3.4232999999999996E109), + doubleArrayOf(-3.4233E109, -3.4232999999999996E109, -3.4233000000000005E109), + doubleArrayOf(+0.0, Double.MIN_VALUE, -Double.MIN_VALUE), + doubleArrayOf(0.0, Double.MIN_VALUE, -Double.MIN_VALUE), + doubleArrayOf(-0.0, Double.MIN_VALUE, -Double.MIN_VALUE), + doubleArrayOf(Double.MIN_VALUE, 1.0E-323, +0.0), + doubleArrayOf(-Double.MIN_VALUE, -0.0, -1.0E-323), + doubleArrayOf(MIN_NORMAL_D, 2.225073858507202E-308, 2.225073858507201E-308), + doubleArrayOf(-MIN_NORMAL_D, -2.225073858507201E-308, -2.225073858507202E-308), + doubleArrayOf(Double.MAX_VALUE, Double.POSITIVE_INFINITY, 1.7976931348623155E308), + doubleArrayOf(-Double.MAX_VALUE, -1.7976931348623155E308, Double.NEGATIVE_INFINITY), + doubleArrayOf(Double.POSITIVE_INFINITY, Double.POSITIVE_INFINITY, Double.MAX_VALUE), + doubleArrayOf(Double.NEGATIVE_INFINITY, -Double.MAX_VALUE, Double.NEGATIVE_INFINITY) + ) + + /** + * direction number cases for test_nextTowards_DD/test_nextTowards_FD in + * est/Strictest + */ + internal val NEXTAFTER_DD_FD_DIRECTION_CASES = doubleArrayOf(Double.POSITIVE_INFINITY, + Double.MAX_VALUE, 8.8, 3.4, 1.4, MIN_NORMAL_D, MIN_NORMAL_D / 2, + Double.MIN_VALUE, +0.0, 0.0, -0.0, -Double.MIN_VALUE, -MIN_NORMAL_D / 2, + -MIN_NORMAL_D, -1.4, -3.4, -8.8, -Double.MAX_VALUE, Double.NEGATIVE_INFINITY) + + /** + * start number cases for test_nextTowards_FD in est/Strictest + * NEXTAFTER_FD_START_CASES[i][0] is the start number + * NEXTAFTER_FD_START_CASES[i][1] is the nextUp of start number + * NEXTAFTER_FD_START_CASES[i][2] is the nextDown of start number + */ + internal val NEXTAFTER_FD_START_CASES = arrayOf(floatArrayOf(3.4f, 3.4000003f, 3.3999999f), + floatArrayOf(-3.4f, -3.3999999f, -3.4000003f), + floatArrayOf(3.4233E19f, 3.4233002E19f, 3.4232998E19f), + floatArrayOf(-3.4233E19f, -3.4232998E19f, -3.4233002E19f), + floatArrayOf(+0.0f, Float.MIN_VALUE, -Float.MIN_VALUE), + floatArrayOf(0.0f, Float.MIN_VALUE, -Float.MIN_VALUE), + floatArrayOf(-0.0f, Float.MIN_VALUE, -Float.MIN_VALUE), + floatArrayOf(Float.MIN_VALUE, 2.8E-45f, +0.0f), + floatArrayOf(-Float.MIN_VALUE, -0.0f, -2.8E-45f), + floatArrayOf(MIN_NORMAL_F, 1.1754945E-38f, 1.1754942E-38f), + floatArrayOf(-MIN_NORMAL_F, -1.1754942E-38f, -1.1754945E-38f), + floatArrayOf(Float.MAX_VALUE, Float.POSITIVE_INFINITY, 3.4028233E38f), + floatArrayOf(-Float.MAX_VALUE, -3.4028233E38f, Float.NEGATIVE_INFINITY), + floatArrayOf(Float.POSITIVE_INFINITY, Float.POSITIVE_INFINITY, Float.MAX_VALUE), + floatArrayOf(Float.NEGATIVE_INFINITY, -Float.MAX_VALUE, Float.NEGATIVE_INFINITY)) + } +} \ No newline at end of file diff --git a/kotlin-native/backend.native/tests/stdlib_external/numbers/MathExceptionTest.kt b/kotlin-native/backend.native/tests/stdlib_external/numbers/MathExceptionTest.kt new file mode 100644 index 00000000000..d9699ad337e --- /dev/null +++ b/kotlin-native/backend.native/tests/stdlib_external/numbers/MathExceptionTest.kt @@ -0,0 +1,21 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +package test.numbers + +import kotlin.math.* +import kotlin.test.* + +class MathExceptionTest { + + @Test fun exceptions() { + assertFails { Double.NaN.roundToLong() } + assertFails { Double.NaN.roundToInt() } + + assertFails { Float.NaN.roundToLong() } + assertFails { Float.NaN.roundToInt() } + } + +} \ No newline at end of file diff --git a/kotlin-native/backend.native/tests/stdlib_external/numbers/MathTest.kt b/kotlin-native/backend.native/tests/stdlib_external/numbers/MathTest.kt new file mode 100644 index 00000000000..4e1ee470689 --- /dev/null +++ b/kotlin-native/backend.native/tests/stdlib_external/numbers/MathTest.kt @@ -0,0 +1,800 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +package test.numbers + +import kotlin.math.* +import kotlin.test.* + +fun assertAlmostEquals(expected: Double, actual: Double, tolerance: Double? = null) { + val tolerance_ = tolerance?.let { abs(it) } ?: 0.000000000001 + if (abs(expected - actual) > tolerance_) { + assertEquals(expected, actual) + } +} + +fun assertAlmostEquals(expected: Float, actual: Float, tolerance: Double? = null) { + val tolerance_ = tolerance?.let { abs(it) } ?: 0.0000001 + if (abs(expected - actual) > tolerance_) { + assertEquals(expected, actual) + } +} + +class DoubleMathTest { + + @Test fun trigonometric() { + assertEquals(0.0, sin(0.0)) + assertAlmostEquals(0.0, sin(PI)) + + assertEquals(0.0, asin(0.0)) + assertAlmostEquals(PI / 2, asin(1.0)) + + assertEquals(1.0, cos(0.0)) + assertAlmostEquals(-1.0, cos(PI)) + + assertEquals(0.0, acos(1.0)) + assertAlmostEquals(PI / 2, acos(0.0)) + + assertEquals(0.0, tan(0.0)) + assertAlmostEquals(1.0, tan(PI / 4)) + + assertAlmostEquals(0.0, atan(0.0)) + assertAlmostEquals(PI / 4, atan(1.0)) + + assertAlmostEquals(PI / 4, atan2(10.0, 10.0)) + assertAlmostEquals(-PI / 4, atan2(Double.NEGATIVE_INFINITY, Double.POSITIVE_INFINITY)) + assertAlmostEquals(0.0, atan2(0.0, 0.0)) + assertAlmostEquals(0.0, atan2(0.0, 10.0)) + assertAlmostEquals(PI / 2, atan2(2.0, 0.0)) + + for (angle in listOf(Double.NaN, Double.POSITIVE_INFINITY, Double.NEGATIVE_INFINITY)) { + assertTrue(sin(angle).isNaN(), "sin($angle)") + assertTrue(cos(angle).isNaN(), "cos($angle)") + assertTrue(tan(angle).isNaN(), "tan($angle)") + } + + for (value in listOf(Double.NaN, 1.2, -1.1)) { + assertTrue(asin(value).isNaN()) + assertTrue(acos(value).isNaN()) + } + assertTrue(atan(Double.NaN).isNaN()) + assertTrue(atan2(Double.NaN, 0.0).isNaN()) + assertTrue(atan2(0.0, Double.NaN).isNaN()) + } + + @Test fun hyperbolic() { + assertEquals(Double.POSITIVE_INFINITY, sinh(Double.POSITIVE_INFINITY)) + assertEquals(Double.NEGATIVE_INFINITY, sinh(Double.NEGATIVE_INFINITY)) + assertTrue(sinh(Double.MIN_VALUE) != 0.0) + assertTrue(sinh(710.0).isFinite()) + assertTrue(sinh(-710.0).isFinite()) + assertTrue(sinh(Double.NaN).isNaN()) + + assertEquals(Double.POSITIVE_INFINITY, cosh(Double.POSITIVE_INFINITY)) + assertEquals(Double.POSITIVE_INFINITY, cosh(Double.NEGATIVE_INFINITY)) + assertTrue(cosh(710.0).isFinite()) + assertTrue(cosh(-710.0).isFinite()) + assertTrue(cosh(Double.NaN).isNaN()) + + assertAlmostEquals(1.0, tanh(Double.POSITIVE_INFINITY)) + assertAlmostEquals(-1.0, tanh(Double.NEGATIVE_INFINITY)) + assertTrue(tanh(Double.MIN_VALUE) != 0.0) + assertTrue(tanh(Double.NaN).isNaN()) + } + + @Test fun inverseHyperbolicSin() { + for (exact in listOf(Double.POSITIVE_INFINITY, Double.NEGATIVE_INFINITY, 0.0, Double.MIN_VALUE, -Double.MIN_VALUE, 0.00001)) { + assertEquals(exact, asinh(sinh(exact))) + } + for (approx in listOf(Double.MIN_VALUE, 0.1, 1.0, 100.0, 710.0)) { + assertAlmostEquals(approx, asinh(sinh(approx))) + assertAlmostEquals(-approx, asinh(sinh(-approx))) + } + assertTrue(asinh(Double.NaN).isNaN()) + } + + @Test fun inverseHyperbolicCos() { + for (exact in listOf(Double.POSITIVE_INFINITY, Double.NEGATIVE_INFINITY, 0.0)) { + assertEquals(abs(exact), acosh(cosh(exact))) + } + for (approx in listOf(Double.MIN_VALUE, 0.00001, 1.0, 100.0, 710.0)) { + assertAlmostEquals(approx, acosh(cosh(approx))) + assertAlmostEquals(approx, acosh(cosh(-approx))) + } + for (invalid in listOf(-1.0, 0.0, 0.99999, Double.NaN)) { + assertTrue(acosh(invalid).isNaN()) + } + } + + @Test fun inverseHyperbolicTan() { + for (exact in listOf(Double.POSITIVE_INFINITY, Double.NEGATIVE_INFINITY, 0.0, Double.MIN_VALUE, -Double.MIN_VALUE)) { + assertEquals(exact, atanh(tanh(exact))) + } + for (approx in listOf(0.00001)) { + assertAlmostEquals(approx, atanh(tanh(approx))) + } + + for (invalid in listOf(-1.00001, 1.00001, Double.NaN, Double.MAX_VALUE, -Double.MAX_VALUE, Double.NEGATIVE_INFINITY, Double.POSITIVE_INFINITY)) { + assertTrue(atanh(invalid).isNaN()) + } + } + + @Test fun powers() { + assertEquals(5.0, hypot(3.0, 4.0)) + assertEquals(Double.POSITIVE_INFINITY, hypot(Double.NEGATIVE_INFINITY, Double.NaN)) + assertEquals(Double.POSITIVE_INFINITY, hypot(Double.NaN, Double.POSITIVE_INFINITY)) + assertTrue(hypot(Double.NaN, 0.0).isNaN()) + + assertEquals(1.0, Double.NaN.pow(0.0)) + assertEquals(1.0, Double.POSITIVE_INFINITY.pow(0)) + assertEquals(49.0, 7.0.pow(2)) + assertEquals(0.25, 2.0.pow(-2)) + assertTrue(0.0.pow(Double.NaN).isNaN()) + assertTrue(Double.NaN.pow(-1).isNaN()) + assertTrue((-7.0).pow(1/3.0).isNaN()) + assertTrue(1.0.pow(Double.POSITIVE_INFINITY).isNaN()) + assertTrue((-1.0).pow(Double.NEGATIVE_INFINITY).isNaN()) + + assertEquals(5.0, sqrt(9.0 + 16.0)) + assertTrue(sqrt(-1.0).isNaN()) + assertTrue(sqrt(Double.NaN).isNaN()) + + assertTrue(exp(Double.NaN).isNaN()) + assertAlmostEquals(E, exp(1.0)) + assertEquals(1.0, exp(0.0)) + assertEquals(0.0, exp(Double.NEGATIVE_INFINITY)) + assertEquals(Double.POSITIVE_INFINITY, exp(Double.POSITIVE_INFINITY)) + + assertEquals(0.0, expm1(0.0)) + assertEquals(Double.MIN_VALUE, expm1(Double.MIN_VALUE)) + assertEquals(0.00010000500016667084, expm1(1e-4)) + assertEquals(-1.0, expm1(Double.NEGATIVE_INFINITY)) + assertEquals(Double.POSITIVE_INFINITY, expm1(Double.POSITIVE_INFINITY)) + } + + @Test fun logarithms() { + assertTrue(log(1.0, Double.NaN).isNaN()) + assertTrue(log(Double.NaN, 1.0).isNaN()) + assertTrue(log(-1.0, 2.0).isNaN()) + assertTrue(log(2.0, -1.0).isNaN()) + assertTrue(log(2.0, 0.0).isNaN()) + assertTrue(log(2.0, 1.0).isNaN()) + assertTrue(log(Double.POSITIVE_INFINITY, Double.POSITIVE_INFINITY).isNaN()) + assertEquals(-2.0, log(0.25, 2.0)) + assertEquals(-0.5, log(2.0, 0.25)) + assertEquals(Double.NEGATIVE_INFINITY, log(Double.POSITIVE_INFINITY, 0.25)) + assertEquals(Double.POSITIVE_INFINITY, log(Double.POSITIVE_INFINITY, 2.0)) + assertEquals(Double.NEGATIVE_INFINITY, log(0.0, 2.0)) + assertEquals(Double.POSITIVE_INFINITY, log(0.0, 0.25)) + + assertTrue(ln(Double.NaN).isNaN()) + assertTrue(ln(-1.0).isNaN()) + assertEquals(1.0, ln(E)) + assertEquals(Double.NEGATIVE_INFINITY, ln(0.0)) + assertEquals(Double.POSITIVE_INFINITY, ln(Double.POSITIVE_INFINITY)) + + assertEquals(1.0, log10(10.0)) + assertAlmostEquals(-1.0, log10(0.1)) + + assertAlmostEquals(3.0, log2(8.0)) + assertEquals(-1.0, log2(0.5)) + + assertTrue(ln1p(Double.NaN).isNaN()) + assertTrue(ln1p(-1.1).isNaN()) + assertEquals(0.0, ln1p(0.0)) + assertEquals(9.999995000003334e-7, ln1p(1e-6)) + assertEquals(Double.MIN_VALUE, ln1p(Double.MIN_VALUE)) + assertEquals(Double.NEGATIVE_INFINITY, ln1p(-1.0)) + } + + @Test fun rounding() { + for (value in listOf(Double.POSITIVE_INFINITY, Double.NEGATIVE_INFINITY, 0.0, 1.0, -10.0)) { + assertEquals(value, ceil(value)) + assertEquals(value, floor(value)) + assertEquals(value, truncate(value)) + assertEquals(value, round(value)) + } + assertTrue(ceil(Double.NaN).isNaN()) + assertTrue(floor(Double.NaN).isNaN()) + assertTrue(truncate(Double.NaN).isNaN()) + assertTrue(round(Double.NaN).isNaN()) + val data = arrayOf( // v floor trunc round ceil + doubleArrayOf( 1.3, 1.0, 1.0, 1.0, 2.0), + doubleArrayOf(-1.3, -2.0, -1.0, -1.0, -1.0), + doubleArrayOf( 1.5, 1.0, 1.0, 2.0, 2.0), + doubleArrayOf(-1.5, -2.0, -1.0, -2.0, -1.0), + doubleArrayOf( 1.8, 1.0, 1.0, 2.0, 2.0), + doubleArrayOf(-1.8, -2.0, -1.0, -2.0, -1.0), + + doubleArrayOf( 2.3, 2.0, 2.0, 2.0, 3.0), + doubleArrayOf(-2.3, -3.0, -2.0, -2.0, -2.0), + doubleArrayOf( 2.5, 2.0, 2.0, 2.0, 3.0), + doubleArrayOf(-2.5, -3.0, -2.0, -2.0, -2.0), + doubleArrayOf( 2.8, 2.0, 2.0, 3.0, 3.0), + doubleArrayOf(-2.8, -3.0, -2.0, -3.0, -2.0) + ) + for ((v, f, t, r, c) in data) { + assertEquals(f, floor(v), "floor($v)") + assertEquals(t, truncate(v), "truncate($v)") + assertEquals(r, round(v), "round($v)") + assertEquals(c, ceil(v), "ceil($v)") + } + } + + @Test fun roundingConversion() { + assertEquals(1L, 1.0.roundToLong()) + assertEquals(1L, 1.1.roundToLong()) + assertEquals(2L, 1.5.roundToLong()) + assertEquals(3L, 2.5.roundToLong()) + assertEquals(-2L, (-2.5).roundToLong()) + assertEquals(-3L, (-2.6).roundToLong()) + assertEquals(9223372036854774784, (9223372036854774800.0).roundToLong()) + assertEquals(Long.MAX_VALUE, Double.MAX_VALUE.roundToLong()) + assertEquals(Long.MIN_VALUE, (-Double.MAX_VALUE).roundToLong()) + assertEquals(Long.MAX_VALUE, Double.POSITIVE_INFINITY.roundToLong()) + assertEquals(Long.MIN_VALUE, Double.NEGATIVE_INFINITY.roundToLong()) + + assertEquals(1, 1.0.roundToInt()) + assertEquals(1, 1.1.roundToInt()) + assertEquals(2, 1.5.roundToInt()) + assertEquals(3, 2.5.roundToInt()) + assertEquals(-2, (-2.5).roundToInt()) + assertEquals(-3, (-2.6).roundToInt()) + assertEquals(2123456789, (2123456789.0).roundToInt()) + assertEquals(Int.MAX_VALUE, Double.MAX_VALUE.roundToInt()) + assertEquals(Int.MIN_VALUE, (-Double.MAX_VALUE).roundToInt()) + assertEquals(Int.MAX_VALUE, Double.POSITIVE_INFINITY.roundToInt()) + assertEquals(Int.MIN_VALUE, Double.NEGATIVE_INFINITY.roundToInt()) + } + + @Test fun absoluteValue() { + assertTrue(abs(Double.NaN).isNaN()) + assertTrue(Double.NaN.absoluteValue.isNaN()) + + for (value in listOf(0.0, Double.MIN_VALUE, 0.1, 1.0, 1000.0, Double.MAX_VALUE, Double.POSITIVE_INFINITY)) { + assertEquals(value, value.absoluteValue) + assertEquals(value, (-value).absoluteValue) + assertEquals(value, abs(value)) + assertEquals(value, abs(-value)) + } + } + + @Test fun signs() { + assertTrue(sign(Double.NaN).isNaN()) + assertTrue(Double.NaN.sign.isNaN()) + + val negatives = listOf(Double.NEGATIVE_INFINITY, -Double.MAX_VALUE, -1.0, -Double.MIN_VALUE) + for (value in negatives) { + assertEquals(-1.0, sign(value)) + assertEquals(-1.0, value.sign) + } + + val zeroes = listOf(0.0, -0.0) + for (value in zeroes) { + assertEquals(value, sign(value)) + assertEquals(value, value.sign) + } + + + val positives = listOf(Double.POSITIVE_INFINITY, Double.MAX_VALUE, 1.0, Double.MIN_VALUE) + for (value in positives) { + assertEquals(1.0, sign(value)) + assertEquals(1.0, value.sign) + } + + val allValues = negatives + positives + for (a in allValues) { + for (b in allValues) { + val r = a.withSign(b) + assertEquals(a.absoluteValue, r.absoluteValue) + assertEquals(b.sign, r.sign, "expected $a with sign bit of $b to have sign ${b.sign}") + } + + val rp0 = a.withSign(0.0) + assertEquals(1.0, rp0.sign) + assertEquals(a.absoluteValue, rp0.absoluteValue) + + val rm0 = a.withSign(-0.0) + assertEquals(-1.0, rm0.sign) + assertEquals(a.absoluteValue, rm0.absoluteValue) + + val ri = a.withSign(-1) + assertEquals(-1.0, ri.sign) + assertEquals(a.absoluteValue, ri.absoluteValue) + + val rn = a.withSign(Double.NaN) + assertEquals(a.absoluteValue, rn.absoluteValue) + } + } + + @Test fun nextAndPrev() { + for (value in listOf(0.0, -0.0, Double.MIN_VALUE, -1.0, 2.0.pow(10))) { + val next = value.nextUp() + if (next > 0) { + assertEquals(next, value + value.ulp) + } else { + assertEquals(value, next - next.ulp) + } + + val prev = value.nextDown() + if (prev > 0) { + assertEquals(value, prev + prev.ulp) + } + else { + assertEquals(prev, value - value.ulp) + } + + val toZero = value.nextTowards(0.0) + if (toZero != 0.0) { + assertEquals(value, toZero + toZero.ulp.withSign(toZero)) + } + + assertEquals(Double.POSITIVE_INFINITY, Double.MAX_VALUE.nextUp()) + assertEquals(Double.MAX_VALUE, Double.POSITIVE_INFINITY.nextDown()) + + assertEquals(Double.NEGATIVE_INFINITY, (-Double.MAX_VALUE).nextDown()) + assertEquals((-Double.MAX_VALUE), Double.NEGATIVE_INFINITY.nextUp()) + + assertTrue(Double.NaN.ulp.isNaN()) + assertTrue(Double.NaN.nextDown().isNaN()) + assertTrue(Double.NaN.nextUp().isNaN()) + assertTrue(Double.NaN.nextTowards(0.0).isNaN()) + + assertEquals(Double.MIN_VALUE, (0.0).ulp) + assertEquals(Double.MIN_VALUE, (-0.0).ulp) + assertEquals(Double.POSITIVE_INFINITY, Double.POSITIVE_INFINITY.ulp) + assertEquals(Double.POSITIVE_INFINITY, Double.NEGATIVE_INFINITY.ulp) + + val maxUlp = 2.0.pow(971) + assertEquals(maxUlp, Double.MAX_VALUE.ulp) + assertEquals(maxUlp, (-Double.MAX_VALUE).ulp) + } + } + + @Test fun IEEEremainder() { + val data = arrayOf( // a a IEEErem 2.5 + doubleArrayOf(-2.0, 0.5), + doubleArrayOf(-1.25, -1.25), + doubleArrayOf( 0.0, 0.0), + doubleArrayOf( 1.0, 1.0), + doubleArrayOf( 1.25, 1.25), + doubleArrayOf( 1.5, -1.0), + doubleArrayOf( 2.0, -0.5), + doubleArrayOf( 2.5, 0.0), + doubleArrayOf( 3.5, 1.0), + doubleArrayOf( 3.75, -1.25), + doubleArrayOf( 4.0, -1.0) + ) + for ((a, r) in data) { + assertEquals(r, a.IEEErem(2.5), "($a).IEEErem(2.5)") + } + + assertTrue(Double.NaN.IEEErem(2.5).isNaN()) + assertTrue(2.0.IEEErem(Double.NaN).isNaN()) + assertTrue(Double.POSITIVE_INFINITY.IEEErem(2.0).isNaN()) + assertTrue(2.0.IEEErem(0.0).isNaN()) + assertEquals(PI, PI.IEEErem(Double.NEGATIVE_INFINITY)) + } + + /* + * Special cases: + * - `atan2(0.0, 0.0)` is `0.0` + * - `atan2(0.0, x)` is `0.0` for `x > 0` and `PI` for `x < 0` + * - `atan2(-0.0, x)` is `-0.0` for 'x > 0` and `-PI` for `x < 0` + * - `atan2(y, +Inf)` is `0.0` for `0 < y < +Inf` and `-0.0` for '-Inf < y < 0` + * - `atan2(y, -Inf)` is `PI` for `0 < y < +Inf` and `-PI` for `-Inf < y < 0` + * - `atan2(y, 0.0)` is `PI/2` for `y > 0` and `-PI/2` for `y < 0` + * - `atan2(+Inf, x)` is `PI/2` for finite `x`y + * - `atan2(-Inf, x)` is `-PI/2` for finite `x` + * - `atan2(NaN, x)` and `atan2(y, NaN)` is `NaN` + */ + @Test fun atan2SpecialCases() { + + assertEquals(atan2(0.0, 0.0), 0.0) + assertEquals(atan2(0.0, 1.0), 0.0) + assertEquals(atan2(0.0, -1.0), PI) + assertEquals(atan2(-0.0, 1.0), -0.0) + assertEquals(atan2(-0.0, -1.0), -PI) + assertEquals(atan2(1.0, Double.POSITIVE_INFINITY), 0.0) + assertEquals(atan2(-1.0, Double.POSITIVE_INFINITY), -0.0) + assertEquals(atan2(1.0, Double.NEGATIVE_INFINITY), PI) + assertEquals(atan2(-1.0, Double.NEGATIVE_INFINITY), -PI) + assertEquals(atan2(1.0, 0.0), PI/2) + assertEquals(atan2(-1.0, 0.0), -PI/2) + assertEquals(atan2(Double.POSITIVE_INFINITY, 1.0), PI/2) + assertEquals(atan2(Double.NEGATIVE_INFINITY, 1.0), -PI/2) + + assertTrue(atan2(Double.NaN, 1.0).isNaN()) + assertTrue(atan2(1.0, Double.NaN).isNaN()) + } +} + +class FloatMathTest { + + companion object { + const val PI = kotlin.math.PI.toFloat() + const val E = kotlin.math.E.toFloat() + } + + @Test fun trigonometric() { + assertEquals(0.0F, sin(0.0F)) + assertAlmostEquals(0.0F, sin(PI)) + + assertEquals(0.0F, asin(0.0F)) + assertAlmostEquals(PI / 2, asin(1.0F), 0.0000002) + + assertEquals(1.0F, cos(0.0F)) + assertAlmostEquals(-1.0F, cos(PI)) + + assertEquals(0.0F, acos(1.0F)) + assertAlmostEquals(PI / 2, acos(0.0F)) + + assertEquals(0.0F, tan(0.0F)) + assertAlmostEquals(1.0F, tan(PI / 4)) + + assertAlmostEquals(0.0F, atan(0.0F)) + assertAlmostEquals(PI / 4, atan(1.0F)) + + assertAlmostEquals(PI / 4, atan2(10.0F, 10.0F)) + assertAlmostEquals(-PI / 4, atan2(Float.NEGATIVE_INFINITY, Float.POSITIVE_INFINITY)) + assertAlmostEquals(0.0F, atan2(0.0F, 0.0F)) + assertAlmostEquals(0.0F, atan2(0.0F, 10.0F)) + assertAlmostEquals(PI / 2, atan2(2.0F, 0.0F)) + + for (angle in listOf(Float.NaN, Float.POSITIVE_INFINITY, Float.NEGATIVE_INFINITY)) { + assertTrue(sin(angle).isNaN(), "sin($angle)") + assertTrue(cos(angle).isNaN(), "cos($angle)") + assertTrue(tan(angle).isNaN(), "tan($angle)") + } + + for (value in listOf(Float.NaN, 1.2F, -1.1F)) { + assertTrue(asin(value).isNaN()) + assertTrue(acos(value).isNaN()) + } + assertTrue(atan(Float.NaN).isNaN()) + assertTrue(atan2(Float.NaN, 0.0F).isNaN()) + assertTrue(atan2(0.0F, Float.NaN).isNaN()) + } + + @Test fun hyperbolic() { + assertEquals(Float.POSITIVE_INFINITY, sinh(Float.POSITIVE_INFINITY)) + assertEquals(Float.NEGATIVE_INFINITY, sinh(Float.NEGATIVE_INFINITY)) + assertTrue(sinh(Float.MIN_VALUE) != 0.0F) + assertTrue(sinh(89.0F).isFinite()) + assertTrue(sinh(-89.0F).isFinite()) + assertTrue(sinh(Float.NaN).isNaN()) + + assertEquals(Float.POSITIVE_INFINITY, cosh(Float.POSITIVE_INFINITY)) + assertEquals(Float.POSITIVE_INFINITY, cosh(Float.NEGATIVE_INFINITY)) + assertTrue(cosh(89.0F).isFinite()) + assertTrue(cosh(-89.0F).isFinite()) + assertTrue(cosh(Float.NaN).isNaN()) + + assertAlmostEquals(1.0F, tanh(Float.POSITIVE_INFINITY)) + assertAlmostEquals(-1.0F, tanh(Float.NEGATIVE_INFINITY)) + assertTrue(tanh(Float.MIN_VALUE) != 0.0F) + assertTrue(tanh(Float.NaN).isNaN()) + } + + @Test fun inverseHyperbolicSin() { + for (exact in listOf(Float.POSITIVE_INFINITY, Float.NEGATIVE_INFINITY, 0.0F, Float.MIN_VALUE, -Float.MIN_VALUE, 0.00001F)) { + assertEquals(exact, asinh(sinh(exact))) + } + for (approx in listOf(Float.MIN_VALUE, 0.1F, 1.0F, 89.0F)) { + assertAlmostEquals(approx, asinh(sinh(approx))) + assertAlmostEquals(-approx, asinh(sinh(-approx))) + } + assertTrue(asinh(Float.NaN).isNaN()) + } + + @Test fun inverseHyperbolicCos() { + for (exact in listOf(Float.POSITIVE_INFINITY, Float.NEGATIVE_INFINITY, 0.0F)) { + assertEquals(abs(exact), acosh(cosh(exact))) + } + for (approx in listOf(Float.MIN_VALUE, 0.1F, 1.0F, 89.0F)) { + assertAlmostEquals(approx, acosh(cosh(approx))) + assertAlmostEquals(approx, acosh(cosh(-approx))) + } + for (invalid in listOf(-1.0F, 0.0F, 0.99999F, Float.NaN)) { + assertTrue(acosh(invalid).isNaN()) + } + } + + @Test fun inverseHyperbolicTan() { + for (exact in listOf(Float.POSITIVE_INFINITY, Float.NEGATIVE_INFINITY, 0.0F, Float.MIN_VALUE, -Float.MIN_VALUE)) { + assertEquals(exact, atanh(tanh(exact))) + } + + for (approx in listOf(0.00001F)) { + assertAlmostEquals(approx, atanh(tanh(approx))) + } + + for (invalid in listOf(-1.00001F, 1.00001F, Float.NaN, Float.MAX_VALUE, -Float.MAX_VALUE, Float.NEGATIVE_INFINITY, Float.POSITIVE_INFINITY)) { + assertTrue(atanh(invalid).isNaN()) + } + } + + @Test fun powers() { + assertEquals(5.0F, hypot(3.0F, 4.0F)) + assertEquals(Float.POSITIVE_INFINITY, hypot(Float.NEGATIVE_INFINITY, Float.NaN)) + assertEquals(Float.POSITIVE_INFINITY, hypot(Float.NaN, Float.POSITIVE_INFINITY)) + assertTrue(hypot(Float.NaN, 0.0F).isNaN()) + + assertEquals(1.0F, Float.NaN.pow(0.0F)) + assertEquals(1.0F, Float.POSITIVE_INFINITY.pow(0)) + assertEquals(49.0F, 7.0F.pow(2)) + assertEquals(0.25F, 2.0F.pow(-2)) + assertTrue(0.0F.pow(Float.NaN).isNaN()) + assertTrue(Float.NaN.pow(-1).isNaN()) + assertTrue((-7.0F).pow(1/3.0F).isNaN()) + assertTrue(1.0F.pow(Float.POSITIVE_INFINITY).isNaN()) + assertTrue((-1.0F).pow(Float.NEGATIVE_INFINITY).isNaN()) + + assertEquals(5.0F, sqrt(9.0F + 16.0F)) + assertTrue(sqrt(-1.0F).isNaN()) + assertTrue(sqrt(Float.NaN).isNaN()) + + assertTrue(exp(Float.NaN).isNaN()) + assertAlmostEquals(E, exp(1.0F)) + assertEquals(1.0F, exp(0.0F)) + assertEquals(0.0F, exp(Float.NEGATIVE_INFINITY)) + assertEquals(Float.POSITIVE_INFINITY, exp(Float.POSITIVE_INFINITY)) + + assertEquals(0.0F, expm1(0.0F)) + assertEquals(-1.0F, expm1(Float.NEGATIVE_INFINITY)) + assertEquals(Float.POSITIVE_INFINITY, expm1(Float.POSITIVE_INFINITY)) + } + + @Test fun logarithms() { + assertTrue(log(1.0F, Float.NaN).isNaN()) + assertTrue(log(Float.NaN, 1.0F).isNaN()) + assertTrue(log(-1.0F, 2.0F).isNaN()) + assertTrue(log(2.0F, -1.0F).isNaN()) + assertTrue(log(2.0F, 0.0F).isNaN()) + assertTrue(log(2.0F, 1.0F).isNaN()) + assertTrue(log(Float.POSITIVE_INFINITY, Float.POSITIVE_INFINITY).isNaN()) + assertEquals(-2.0F, log(0.25F, 2.0F)) + assertEquals(-0.5F, log(2.0F, 0.25F)) + assertEquals(Float.NEGATIVE_INFINITY, log(Float.POSITIVE_INFINITY, 0.25F)) + assertEquals(Float.POSITIVE_INFINITY, log(Float.POSITIVE_INFINITY, 2.0F)) + assertEquals(Float.NEGATIVE_INFINITY, log(0.0F, 2.0F)) + assertEquals(Float.POSITIVE_INFINITY, log(0.0F, 0.25F)) + + assertTrue(ln(Float.NaN).isNaN()) + assertTrue(ln(-1.0F).isNaN()) + assertAlmostEquals(1.0F, ln(E)) + assertEquals(Float.NEGATIVE_INFINITY, ln(0.0F)) + assertEquals(Float.POSITIVE_INFINITY, ln(Float.POSITIVE_INFINITY)) + + assertEquals(1.0F, log10(10.0F)) + assertAlmostEquals(-1.0F, log10(0.1F)) + + assertAlmostEquals(3.0F, log2(8.0F)) + assertEquals(-1.0F, log2(0.5F)) + + assertTrue(ln1p(Float.NaN).isNaN()) + assertTrue(ln1p(-1.1F).isNaN()) + assertEquals(0.0F, ln1p(0.0F)) + assertEquals(Float.NEGATIVE_INFINITY, ln1p(-1.0F)) + } + + @Test fun rounding() { + for (value in listOf(Float.POSITIVE_INFINITY, Float.NEGATIVE_INFINITY, 0.0F, 1.0F, -10.0F)) { + assertEquals(value, ceil(value)) + assertEquals(value, floor(value)) + assertEquals(value, truncate(value)) + assertEquals(value, round(value)) + } + assertTrue(ceil(Float.NaN).isNaN()) + assertTrue(floor(Float.NaN).isNaN()) + assertTrue(truncate(Float.NaN).isNaN()) + assertTrue(round(Float.NaN).isNaN()) + val data = arrayOf( // v floor trunc round ceil + floatArrayOf( 1.3F, 1.0F, 1.0F, 1.0F, 2.0F), + floatArrayOf(-1.3F, -2.0F, -1.0F, -1.0F, -1.0F), + floatArrayOf( 1.5F, 1.0F, 1.0F, 2.0F, 2.0F), + floatArrayOf(-1.5F, -2.0F, -1.0F, -2.0F, -1.0F), + floatArrayOf( 1.8F, 1.0F, 1.0F, 2.0F, 2.0F), + floatArrayOf(-1.8F, -2.0F, -1.0F, -2.0F, -1.0F), + + floatArrayOf( 2.3F, 2.0F, 2.0F, 2.0F, 3.0F), + floatArrayOf(-2.3F, -3.0F, -2.0F, -2.0F, -2.0F), + floatArrayOf( 2.5F, 2.0F, 2.0F, 2.0F, 3.0F), + floatArrayOf(-2.5F, -3.0F, -2.0F, -2.0F, -2.0F), + floatArrayOf( 2.8F, 2.0F, 2.0F, 3.0F, 3.0F), + floatArrayOf(-2.8F, -3.0F, -2.0F, -3.0F, -2.0F) + ) + for ((v, f, t, r, c) in data) { + assertEquals(f, floor(v), "floor($v)") + assertEquals(t, truncate(v), "truncate($v)") + assertEquals(r, round(v), "round($v)") + assertEquals(c, ceil(v), "ceil($v)") + } + } + + @Test fun roundingConversion() { + assertEquals(1L, 1.0F.roundToLong()) + assertEquals(1L, 1.1F.roundToLong()) + assertEquals(2L, 1.5F.roundToLong()) + assertEquals(3L, 2.5F.roundToLong()) + assertEquals(-2L, (-2.5F).roundToLong()) + assertEquals(-3L, (-2.6F).roundToLong()) + // assertEquals(9223372036854774784, (9223372036854774800.0F).roundToLong()) // platform-specific + assertEquals(Long.MAX_VALUE, Float.MAX_VALUE.roundToLong()) + assertEquals(Long.MIN_VALUE, (-Float.MAX_VALUE).roundToLong()) + assertEquals(Long.MAX_VALUE, Float.POSITIVE_INFINITY.roundToLong()) + assertEquals(Long.MIN_VALUE, Float.NEGATIVE_INFINITY.roundToLong()) + + assertEquals(1, 1.0F.roundToInt()) + assertEquals(1, 1.1F.roundToInt()) + assertEquals(2, 1.5F.roundToInt()) + assertEquals(3, 2.5F.roundToInt()) + assertEquals(-2, (-2.5F).roundToInt()) + assertEquals(-3, (-2.6F).roundToInt()) + assertEquals(16777218, (16777218F).roundToInt()) + assertEquals(Int.MAX_VALUE, Float.MAX_VALUE.roundToInt()) + assertEquals(Int.MIN_VALUE, (-Float.MAX_VALUE).roundToInt()) + assertEquals(Int.MAX_VALUE, Float.POSITIVE_INFINITY.roundToInt()) + assertEquals(Int.MIN_VALUE, Float.NEGATIVE_INFINITY.roundToInt()) + } + + @Test fun absoluteValue() { + assertTrue(abs(Float.NaN).isNaN()) + assertTrue(Float.NaN.absoluteValue.isNaN()) + + for (value in listOf(0.0F, Float.MIN_VALUE, 0.1F, 1.0F, 1000.0F, Float.MAX_VALUE, Float.POSITIVE_INFINITY)) { + assertEquals(value, value.absoluteValue) + assertEquals(value, (-value).absoluteValue) + assertEquals(value, abs(value)) + assertEquals(value, abs(-value)) + } + } + + @Test fun signs() { + assertTrue(sign(Float.NaN).isNaN()) + assertTrue(Float.NaN.sign.isNaN()) + + val negatives = listOf(Float.NEGATIVE_INFINITY, -Float.MAX_VALUE, -1.0F, -Float.MIN_VALUE) + for (value in negatives) { + assertEquals(-1.0F, sign(value)) + assertEquals(-1.0F, value.sign) + } + + val zeroes = listOf(0.0F, -0.0F) + for (value in zeroes) { + assertEquals(value, sign(value)) + assertEquals(value, value.sign) + } + + + val positives = listOf(Float.POSITIVE_INFINITY, Float.MAX_VALUE, 1.0F, Float.MIN_VALUE) + for (value in positives) { + assertEquals(1.0F, sign(value)) + assertEquals(1.0F, value.sign) + } + + val allValues = negatives + positives + for (a in allValues) { + for (b in allValues) { + val r = a.withSign(b) + assertEquals(a.absoluteValue, r.absoluteValue) + assertEquals(b.sign, r.sign) + } + + val rp0 = a.withSign(0.0F) + assertEquals(1.0F, rp0.sign) + assertEquals(a.absoluteValue, rp0.absoluteValue) + + val rm0 = a.withSign(-0.0F) + assertEquals(-1.0F, rm0.sign) + assertEquals(a.absoluteValue, rm0.absoluteValue) + + val ri = a.withSign(-1) + assertEquals(-1.0F, ri.sign) + assertEquals(a.absoluteValue, ri.absoluteValue) + } + } + + @Test fun nextAndPrev() { + for (value in listOf(0.0f, -0.0f, Float.MIN_VALUE, -1.0f, 2.0f.pow(10))) { + val next = value.nextUp() + if (next > 0) { + assertEquals(next, value + value.ulp) + } else { + assertEquals(value, next - next.ulp) + } + + val prev = value.nextDown() + if (prev > 0) { + assertEquals(value, prev + prev.ulp) + } + else { + assertEquals(prev, value - value.ulp) + } + + val toZero = value.nextTowards(0.0f) + if (toZero != 0.0f) { + assertEquals(value, toZero + toZero.ulp.withSign(toZero)) + } + + assertEquals(Float.POSITIVE_INFINITY, Float.MAX_VALUE.nextUp()) + assertEquals(Float.MAX_VALUE, Float.POSITIVE_INFINITY.nextDown()) + + assertEquals(Float.NEGATIVE_INFINITY, (-Float.MAX_VALUE).nextDown()) + assertEquals((-Float.MAX_VALUE), Float.NEGATIVE_INFINITY.nextUp()) + + assertTrue(Float.NaN.ulp.isNaN()) + assertTrue(Float.NaN.nextDown().isNaN()) + assertTrue(Float.NaN.nextUp().isNaN()) + assertTrue(Float.NaN.nextTowards(0.0f).isNaN()) + + assertEquals(Float.MIN_VALUE, (0.0f).ulp) + assertEquals(Float.MIN_VALUE, (-0.0f).ulp) + assertEquals(Float.POSITIVE_INFINITY, Float.POSITIVE_INFINITY.ulp) + assertEquals(Float.POSITIVE_INFINITY, Float.NEGATIVE_INFINITY.ulp) + + val maxUlp = 2.0f.pow(104) + assertEquals(maxUlp, Float.MAX_VALUE.ulp) + assertEquals(maxUlp, (-Float.MAX_VALUE).ulp) + } + } + + @Test fun IEEEremainder() { + val data = arrayOf( // a a IEEErem 2.5 + floatArrayOf(-2.0f, 0.5f), + floatArrayOf(-1.25f, -1.25f), + floatArrayOf( 0.0f, 0.0f), + floatArrayOf( 1.0f, 1.0f), + floatArrayOf( 1.25f, 1.25f), + floatArrayOf( 1.5f, -1.0f), + floatArrayOf( 2.0f, -0.5f), + floatArrayOf( 2.5f, 0.0f), + floatArrayOf( 3.5f, 1.0f), + floatArrayOf( 3.75f, -1.25f), + floatArrayOf( 4.0f, -1.0f) + ) + for ((a, r) in data) { + assertEquals(r, a.IEEErem(2.5f), "($a).IEEErem(2.5f)") + } + + assertTrue(Float.NaN.IEEErem(2.5f).isNaN()) + assertTrue(2.0f.IEEErem(Float.NaN).isNaN()) + assertTrue(Float.POSITIVE_INFINITY.IEEErem(2.0f).isNaN()) + assertTrue(2.0f.IEEErem(0.0f).isNaN()) + assertEquals(PI.toFloat(), PI.toFloat().IEEErem(Float.NEGATIVE_INFINITY)) + } +} + +class IntegerMathTest { + + @Test + fun intSigns() { + val negatives = listOf(Int.MIN_VALUE, -65536, -1) + val positives = listOf(1, 100, 256, Int.MAX_VALUE) + negatives.forEach { assertEquals(-1, it.sign) } + positives.forEach { assertEquals(1, it.sign) } + assertEquals(0, 0.sign) + + (negatives - Int.MIN_VALUE).forEach { assertEquals(-it, it.absoluteValue) } + assertEquals(Int.MIN_VALUE, Int.MIN_VALUE.absoluteValue) + + positives.forEach { assertEquals(it, it.absoluteValue) } + } + + + @Test + fun longSigns() { + val negatives = listOf(Long.MIN_VALUE, -65536L, -1L) + val positives = listOf(1L, 100L, 256L, Long.MAX_VALUE) + negatives.forEach { assertEquals(-1, it.sign) } + positives.forEach { assertEquals(1, it.sign) } + assertEquals(0, 0L.sign) + + (negatives - Long.MIN_VALUE).forEach { assertEquals(-it, it.absoluteValue) } + assertEquals(Long.MIN_VALUE, Long.MIN_VALUE.absoluteValue) + + positives.forEach { assertEquals(it, it.absoluteValue) } + } +} diff --git a/kotlin-native/backend.native/tests/stdlib_external/text/StringEncodingTestNative.kt b/kotlin-native/backend.native/tests/stdlib_external/text/StringEncodingTestNative.kt new file mode 100644 index 00000000000..e4148285d97 --- /dev/null +++ b/kotlin-native/backend.native/tests/stdlib_external/text/StringEncodingTestNative.kt @@ -0,0 +1,11 @@ +/* + * Copyright 2010-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +package test.text + + +internal actual val surrogateCodePointDecoding: String = "\uFFFD".repeat(3) + +internal actual val surrogateCharEncoding: ByteArray = byteArrayOf(0xEF.toByte(), 0xBF.toByte(), 0xBD.toByte()) diff --git a/kotlin-native/backend.native/tests/stdlib_external/utils.kt b/kotlin-native/backend.native/tests/stdlib_external/utils.kt new file mode 100644 index 00000000000..6a5d6e51c6c --- /dev/null +++ b/kotlin-native/backend.native/tests/stdlib_external/utils.kt @@ -0,0 +1,31 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +package test + +import kotlin.test.* + +public actual fun assertTypeEquals(expected: Any?, actual: Any?) { + if (expected != null && actual != null) { + assertTrue(expected::class.isInstance(actual) || actual::class.isInstance(expected), + "Expected: $expected, Actual: $actual") + } else { + assertTrue(expected == null && actual == null) + } +} + +internal actual fun String.removeLeadingPlusOnJava6(): String = this + +internal actual inline fun testOnNonJvm6And7(f: () -> Unit) { + f() +} + +actual fun testOnJvm(action: () -> Unit) {} +actual fun testOnJs(action: () -> Unit) {} + + +public actual val isFloat32RangeEnforced: Boolean get() = true + +public actual val supportsSuppressedExceptions: Boolean get() = true \ No newline at end of file diff --git a/kotlin-native/backend.native/tests/teamcity-test.property b/kotlin-native/backend.native/tests/teamcity-test.property new file mode 100644 index 00000000000..c78053c4f48 --- /dev/null +++ b/kotlin-native/backend.native/tests/teamcity-test.property @@ -0,0 +1,12 @@ +# +# Test property for teamcity integration tests. +# how to launch tests: +# 1. place well-formed result.json in test.output/external +# 2. launch following command: +# > export TEAMCITY_BUILD_PROPERTIES_FILE=backend.native/tests/teamcity-test.property +# > ./gradlew :backend.native:tests:slackReport +# +teamcity.build.id=test-build +teamcity.buildType.id=test-type-build +konan-reporter-token= +konan-channel-name= \ No newline at end of file diff --git a/kotlin-native/backend.native/tests/testLibrary/kotlin/test_platform_lib.kt b/kotlin-native/backend.native/tests/testLibrary/kotlin/test_platform_lib.kt new file mode 100644 index 00000000000..cac5e26b17c --- /dev/null +++ b/kotlin-native/backend.native/tests/testLibrary/kotlin/test_platform_lib.kt @@ -0,0 +1,14 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +package test.konan.platform + +fun produceMessage() { + println("""This is a side effect of a test library linked into the binary. +You should not be seeing this. +""") +} + +val x: Unit = produceMessage() diff --git a/kotlin-native/backend.native/tests/testing/annotations.kt b/kotlin-native/backend.native/tests/testing/annotations.kt new file mode 100644 index 00000000000..2c1a28f6ae8 --- /dev/null +++ b/kotlin-native/backend.native/tests/testing/annotations.kt @@ -0,0 +1,70 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +package kotlin.test.tests + +import kotlin.test.* +import kotlin.native.internal.test.* + +@Ignore +class IgnoredClass { + @Ignore object IgnoredObject { + @Test fun test() { throw AssertionError("Ignored test") } + } + + @Test fun test() { throw AssertionError("Ignored test") } +} + +@Ignore +object IgnoredObject { + @Test fun test() { throw AssertionError("Ignored test") } +} + +class A { + companion object { + @BeforeTest fun before() { println("before (A.companion)") } + @AfterTest fun after() { println("after (A.companion)") } + @Test fun test1() { println("test1 (A.companion)") } + + @BeforeClass fun beforeClass() { println("beforeClass (A.companion)") } + @AfterClass fun afterClass() { println("afterClass (A.companion)") } + } + + @BeforeTest fun before() { println("before (A)") } + @AfterTest fun after() { println("after (A)") } + @Test fun test1() { println("test1 (A)") } + @Ignore @Test fun ignoredTest() { throw AssertionError("Ignored test") } + + @BeforeClass fun beforeClass() { println("beforeClass (A)") } + @AfterClass fun afterClass() { println("afterClass (A)") } + + object O { + @BeforeTest fun before() { println("before (A.object)") } + @AfterTest fun after() { println("after (A.object)") } + @Test fun test1() { println("test1 (A.object)") } + @Ignore @Test fun ignoredTest() { throw AssertionError("Ignored test") } + + @BeforeClass fun beforeClass() { println("beforeClass (A.object)") } + @AfterClass fun afterClass() { println("afterClass (A.object)") } + } +} + +object O { + @BeforeTest fun before() { println("before (object)") } + @AfterTest fun after() { println("after (object)") } + @Test fun test1() { println("test1 (object)") } + @Ignore @Test fun ignoredTest() { throw AssertionError("Ignored test") } + + @BeforeClass fun beforeClass() { println("beforeClass (object)") } + @AfterClass fun afterClass() { println("afterClass (object)") } +} + +@BeforeTest fun before() { println("before (file)") } +@AfterTest fun after() { println("after (file)") } +@Test fun test1() { println("test1 (file)") } +@Ignore @Test fun ignoredTest() { throw AssertionError("Ignored test") } + +@BeforeClass fun beforeClass() { println("beforeClass (file)") } +@AfterClass fun afterClass() { println("afterClass (file)") } diff --git a/kotlin-native/backend.native/tests/testing/assertions.kt b/kotlin-native/backend.native/tests/testing/assertions.kt new file mode 100644 index 00000000000..2f927e3e361 --- /dev/null +++ b/kotlin-native/backend.native/tests/testing/assertions.kt @@ -0,0 +1,194 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +package kotlin.test.tests + +import kotlin.test.* + +class BasicAssertionsTest { + @Test + fun testAssertEquals() { + assertEquals(1, 1) + } + + @Test + fun testAssertEqualsString() { + assertEquals("a", "a") + } + + @Test + fun testAssertFailsWith() { + assertFailsWith { throw IllegalStateException() } + assertFailsWith { throw AssertionError() } + } + + @Test + fun testAssertFailsWithFails() { + withDefaultAsserter run@ { + try { + assertFailsWith { throw IllegalArgumentException() } + } + catch (e: AssertionError) { + return@run + } + throw AssertionError("Expected to fail") + } + withDefaultAsserter run@ { + try { + assertFailsWith { } + } + catch (e: AssertionError) { + return@run + } + throw AssertionError("Expected to fail") + } + } + + @Test + fun testAssertFailsWithClass() { + assertFailsWith { + throw IllegalArgumentException("This is illegal") + } + } + + @Test + fun testAssertFailsWithClassFails() { + checkFailedAssertion { + assertFailsWith { throw IllegalStateException() } + } + + checkFailedAssertion { + assertFailsWith { } + } + } + + @Test + fun testAssertEqualsFails() { + checkFailedAssertion { assertEquals(1, 2) } + } + + @Test + fun testAssertTrue() { + assertTrue(true) + assertTrue { true } + } + + @Test() + fun testAssertTrueFails() { + checkFailedAssertion { assertTrue(false) } + checkFailedAssertion { assertTrue { false } } + } + + @Test + fun testAssertFalse() { + assertFalse(false) + assertFalse { false } + } + + @Test + fun testAssertFalseFails() { + checkFailedAssertion { assertFalse(true) } + checkFailedAssertion{ assertFalse { true } } + } + + @Test + fun testAssertFails() { + assertFails { throw IllegalStateException() } + } + + @Test() + fun testAssertFailsFails() { + checkFailedAssertion { assertFails { } } + } + + + @Test + fun testAssertNotEquals() { + assertNotEquals(1, 2) + } + + @Test() + fun testAssertNotEqualsFails() { + checkFailedAssertion { assertNotEquals(1, 1) } + } + + @Test + fun testAssertNotNull() { + assertNotNull(true) + } + + @Test() + fun testAssertNotNullFails() { + checkFailedAssertion { assertNotNull(null) } + } + + @Test + fun testAssertNotNullLambda() { + assertNotNull("") { assertEquals("", it) } + } + + @Test + fun testAssertNotNullLambdaFails() { + checkFailedAssertion { + val value: String? = null + assertNotNull(value) { + it.substring(0, 0) + } + } + } + + @Test + fun testAssertNull() { + assertNull(null) + } + + @Test + fun testAssertNullFails() { + checkFailedAssertion { assertNull("") } + } + + @Test() + fun testFail() { + checkFailedAssertion { fail("should fail") } + } + + @Test + fun testExpect() { + expect(1) { 1 } + } + + @Test + fun testExpectFails() { + checkFailedAssertion { expect(1) { 2 } } + } + + @Test + fun testContracts() { + open class S + class P(val str: String = "P") : S() + + val s: S = P() + val p: Any = P("A") + + assertTrue(s is P) + assertEquals("P", s.str) + assertFalse(p !is P) + assertEquals("A", p.str) + + val nullableT: P? = P("N") + assertNotNull(nullableT) + assertEquals("N", nullableT.str) + } +} + + +private fun checkFailedAssertion(assertion: () -> Unit) { + assertFailsWith { withDefaultAsserter(assertion) } +} + +@Suppress("INVISIBLE_MEMBER") +private fun withDefaultAsserter(block: () -> Unit) { + block() +} diff --git a/kotlin-native/backend.native/tests/testing/custom_main.kt b/kotlin-native/backend.native/tests/testing/custom_main.kt new file mode 100644 index 00000000000..50a52b21be6 --- /dev/null +++ b/kotlin-native/backend.native/tests/testing/custom_main.kt @@ -0,0 +1,19 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +package kotlin.test.tests + +import kotlin.test.* +import kotlin.native.internal.test.* + +@Test +fun test() { + println("test") +} + +fun main(args: Array) { + println("Custom main") + testLauncherEntryPoint(args) +} \ No newline at end of file diff --git a/kotlin-native/backend.native/tests/testing/filters.kt b/kotlin-native/backend.native/tests/testing/filters.kt new file mode 100644 index 00000000000..c63b196c564 --- /dev/null +++ b/kotlin-native/backend.native/tests/testing/filters.kt @@ -0,0 +1,34 @@ +package kotlin.test.tests + +import kotlin.test.* + +class A { + @Test + fun foo1() {} + + @Test + fun foo2() {} + + @Test + fun bar() {} +} + +class B { + @Test + fun foo1() {} + + @Test + fun foo2() {} + + @Test + fun bar() {} +} + +@Test +fun foo1() {} + +@Test +fun foo2() {} + +@Test +fun bar() {} \ No newline at end of file diff --git a/kotlin-native/backend.native/tests/testing/library.kt b/kotlin-native/backend.native/tests/testing/library.kt new file mode 100644 index 00000000000..047d654fc1f --- /dev/null +++ b/kotlin-native/backend.native/tests/testing/library.kt @@ -0,0 +1,66 @@ +package library + +import kotlin.test.* + +val output = mutableListOf() + +interface I1 { + @Test + fun foo() +} + +interface I2 { + @Test + fun foo() +} + +open class A { + + @BeforeTest + open fun before() { + output.add("A.before") + } + + @AfterTest + open fun after() { + output.add("A.after") + } + + @Test + open fun test0() { + output.add("A.test0") + } + + @Test + open fun test1() { + output.add("A.test1") + } + + @Test + open fun test2() { + output.add("A.test2") + } + + @Test + open fun test3() { + output.add("A.test3") + } + + @Ignore + @Test + open fun ignored0() { + output.add("A.ignored0") + } + + @Ignore + @Test + open fun ignored1() { + output.add("A.ignored1") + } + + @Ignore + @Test + open fun ignored2() { + output.add("A.ignored2") + } +} \ No newline at end of file diff --git a/kotlin-native/backend.native/tests/testing/library_user.kt b/kotlin-native/backend.native/tests/testing/library_user.kt new file mode 100644 index 00000000000..ab5de47a748 --- /dev/null +++ b/kotlin-native/backend.native/tests/testing/library_user.kt @@ -0,0 +1,74 @@ +import kotlin.native.internal.test.* +import kotlin.test.* +import library.* + +open class B : A() { + // Override test methods without a test annotation. + // We should run these methods anyway. + + override fun before() { + output.add("B.before") + } + + // test0 should be executed. + + // Should be executed. + override fun test1() { + output.add("B.test1") + } + + // Should be executed + @Ignore + override fun test2() { + output.add("B.test2") + } + + // Should be ignored. + @Ignore + @Test + override fun test3() { + output.add("B.test3") + } + + // ignored0 should be ignored. + + // Should be ignored. + override fun ignored1() { + output.add("B.ignored1") + } + + // Should be executed. + @Test + override fun ignored2() { + output.add("B.ignored2") + } +} + +// All test methods from B should be executed for C. +class C: B() {} + +class D: I1, I2 { + // This method shouldn't be executed because its parent methods annotated + // with @Test belong to an interface instead of an abstract class. + override fun foo(){ + output.add("D.foo") + } +} + +fun main(args: Array) { + testLauncherEntryPoint(args) + output.forEach(::println) + assertEquals(8, output.count { it == "A.after" }) + assertEquals(8, output.count { it == "B.before" }) + + assertEquals(2, output.count { it == "A.test0" }) + assertEquals(2, output.count { it == "B.test1" }) + assertEquals(2, output.count { it == "B.test2" }) + assertEquals(2, output.count { it == "B.ignored2" }) + + assertTrue(output.none { it == "B.test3" }) + assertTrue(output.none { it == "A.ignored0" }) + assertTrue(output.none { it == "B.ignored1" }) + + assertTrue(output.none { it == "D.foo" }) +} \ No newline at end of file diff --git a/kotlin-native/backend.native/tests/testing/stacktrace.kt b/kotlin-native/backend.native/tests/testing/stacktrace.kt new file mode 100644 index 00000000000..deb859a1398 --- /dev/null +++ b/kotlin-native/backend.native/tests/testing/stacktrace.kt @@ -0,0 +1,24 @@ +package kotlin.test.tests + +import kotlin.test.* + +@Ignore +class Ignored { + @Test + fun foo() {} +} + +class Failed { + @Test + fun bar() { + try { + baz() + } catch(e: Exception) { + throw Exception("Bar", e) + } + } + + fun baz() { + throw Exception("Baz") + } +} diff --git a/kotlin-native/build-tools/build.gradle.kts b/kotlin-native/build-tools/build.gradle.kts new file mode 100644 index 00000000000..84c4df40623 --- /dev/null +++ b/kotlin-native/build-tools/build.gradle.kts @@ -0,0 +1,114 @@ +/* + * Copyright 2010-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the license/LICENSE.txt file. + */ + +import org.jetbrains.kotlin.gradle.plugin.KotlinSourceSet +import org.jetbrains.kotlin.gradle.tasks.KotlinCompile +import java.util.Properties + +plugins { + // We explicitly configure versions of plugins in settings.gradle.kts. + // due to https://github.com/gradle/gradle/issues/1697. + id("kotlin") + groovy + `java-gradle-plugin` +} + +buildscript { + dependencies { + classpath("com.google.code.gson:gson:2.8.6") + } +} + +val rootProperties = Properties().apply { + rootDir.resolve("../gradle.properties").reader().use(::load) +} + +val kotlinVersion: String by rootProperties +val kotlinCompilerRepo: String by rootProperties +val buildKotlinVersion: String by rootProperties +val buildKotlinCompilerRepo: String by rootProperties +val konanVersion: String by rootProperties +val slackApiVersion: String by rootProperties +val ktorVersion: String by rootProperties +val shadowVersion: String by rootProperties +val metadataVersion: String by rootProperties + +group = "org.jetbrains.kotlin" +version = konanVersion + +repositories { + jcenter() + maven(kotlinCompilerRepo) + maven(buildKotlinCompilerRepo) + maven("https://cache-redirector.jetbrains.com/maven-central") + mavenCentral() + maven("https://kotlin.bintray.com/kotlinx") + maven("https://dl.bintray.com/kotlin/kotlin-dev") +} + +dependencies { + compileOnly(gradleApi()) + + implementation("org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlinVersion") + implementation("org.jetbrains.kotlin:kotlin-stdlib:$kotlinVersion") + implementation("org.jetbrains.kotlin:kotlin-reflect:$kotlinVersion") + implementation("com.ullink.slack:simpleslackapi:$slackApiVersion") + + implementation("io.ktor:ktor-client-auth:$ktorVersion") + implementation("io.ktor:ktor-client-core:$ktorVersion") + implementation("io.ktor:ktor-client-cio:$ktorVersion") + + api("org.jetbrains.kotlin:kotlin-native-utils:$kotlinVersion") + + // Located in /shared and always provided by the composite build. + api("org.jetbrains.kotlin:kotlin-native-shared:$konanVersion") + implementation("com.github.jengelman.gradle.plugins:shadow:$shadowVersion") + + implementation("org.jetbrains.kotlinx:kotlinx-metadata-klib:$metadataVersion") +} + +sourceSets["main"].withConvention(KotlinSourceSet::class) { + kotlin.srcDir("$projectDir/../tools/benchmarks/shared/src/main/kotlin/report") +} + +gradlePlugin { + plugins { + create("benchmarkPlugin") { + id = "benchmarking" + implementationClass = "org.jetbrains.kotlin.benchmark.KotlinNativeBenchmarkingPlugin" + } + create("compileBenchmarking") { + id = "compile-benchmarking" + implementationClass = "org.jetbrains.kotlin.benchmark.CompileBenchmarkingPlugin" + } + create("swiftBenchmarking") { + id = "swift-benchmarking" + implementationClass = "org.jetbrains.kotlin.benchmark.SwiftBenchmarkingPlugin" + } + create("compileToBitcode") { + id = "compile-to-bitcode" + implementationClass = "org.jetbrains.kotlin.bitcode.CompileToBitcodePlugin" + } + create("runtimeTesting") { + id = "runtime-testing" + implementationClass = "org.jetbrains.kotlin.testing.native.RuntimeTestingPlugin" + } + } +} + +val compileKotlin: KotlinCompile by tasks +val compileGroovy: GroovyCompile by tasks + +// https://youtrack.jetbrains.com/issue/KT-37435 +compileKotlin.apply { + kotlinOptions.jvmTarget = "1.8" + kotlinOptions.freeCompilerArgs += listOf("-Xno-optimized-callable-references", "-Xskip-prerelease-check") +} + +// Add Kotlin classes to a classpath for the Groovy compiler +compileGroovy.apply { + classpath += project.files(compileKotlin.destinationDir) + dependsOn(compileKotlin) +} diff --git a/kotlin-native/build-tools/settings.gradle.kts b/kotlin-native/build-tools/settings.gradle.kts new file mode 100644 index 00000000000..65d17a5790f --- /dev/null +++ b/kotlin-native/build-tools/settings.gradle.kts @@ -0,0 +1,26 @@ +pluginManagement { + val rootProperties = java.util.Properties().apply { + rootDir.resolve("../gradle.properties").reader().use(::load) + } + + val kotlinCompilerRepo: String by rootProperties + val kotlinVersion by rootProperties + + repositories { + maven(kotlinCompilerRepo) + maven("https://cache-redirector.jetbrains.com/maven-central") + mavenCentral() + } + + resolutionStrategy { + eachPlugin { + if (requested.id.id == "kotlin") { + useModule("org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlinVersion") + } + } + } +} + +rootProject.name = "kotlin-native-build-tools" + +includeBuild("../shared") diff --git a/kotlin-native/build-tools/src/main/groovy/org/jetbrains/kotlin/KonanTest.groovy b/kotlin-native/build-tools/src/main/groovy/org/jetbrains/kotlin/KonanTest.groovy new file mode 100644 index 00000000000..7be49e1a6ce --- /dev/null +++ b/kotlin-native/build-tools/src/main/groovy/org/jetbrains/kotlin/KonanTest.groovy @@ -0,0 +1,579 @@ +/* + * Copyright 2010-2017 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.jetbrains.kotlin + +import org.gradle.api.tasks.Input +import org.gradle.api.tasks.JavaExec +import org.gradle.api.tasks.TaskAction +import org.gradle.process.ExecResult +import org.jetbrains.kotlin.utils.DFS + +import java.nio.file.Paths +import java.util.function.Function +import java.util.function.UnaryOperator +import java.util.regex.Pattern +import java.util.stream.Collectors + +class RunExternalTestGroup extends JavaExec { + def platformManager = project.rootProject.platformManager + def target = platformManager.targetManager(project.testTarget).target + def dist = UtilsKt.getKotlinNativeDist(project) + + def enableKonanAssertions = true + String outputDirectory = null + String goldValue = null + // Checks test's output against gold value and returns true if the output matches the expectation + Function outputChecker = { str -> (goldValue == null || goldValue == str) } + boolean printOutput = true + String testData = null + int expectedExitStatus = 0 + List arguments = null + List flags = null + + boolean multiRuns = false + List> multiArguments = null + + boolean expectedFail = false + boolean compilerMessages = false + + // Uses directory defined in $outputSourceSetName source set + void createOutputDirectory() { + if (outputDirectory != null) { + return + } + def outputSourceSet = UtilsKt.getTestOutputExternal(project) + outputDirectory = Paths.get(outputSourceSet, name).toString() + project.file(outputDirectory).mkdirs() + } + + RunExternalTestGroup() { + // We don't build the compiler if a custom dist path is specified. + UtilsKt.dependsOnDist(this) + main = 'org.jetbrains.kotlin.cli.bc.K2NativeKt' + } + + @Override + void exec() { + // Perhaps later we will return this exec() back but for now rest of infrastructure expects + // compilation begins on runCompiler call, to emulate this behaviour we call super.exec() after + // configuration part at runCompiler. + } + + protected void runCompiler(List filesToCompile, String output, List moreArgs) { + def log = new ByteArrayOutputStream() + try { + classpath = project.fileTree("$dist.canonicalPath/konan/lib/") { + include '*.jar' + } + jvmArgs "-Xmx4G" + enableAssertions = true + def sources = File.createTempFile(name,".lst") + sources.deleteOnExit() + def sourcesWriter = sources.newWriter() + filesToCompile.each { f -> + sourcesWriter.write(f.chars().any { Character.isWhitespace(it) } + ? "\"${f.replace("\\", "\\\\")}\"\n" // escape file name + : "$f\n") + } + sourcesWriter.close() + args = ["-output", output, + "@${sources.absolutePath}", + *moreArgs, + *project.globalTestArgs] + if (project.testTarget) { + args "-target", target.visibleName + } + if (enableKonanAssertions) { + args "-ea" + } + if (project.hasProperty("test_verbose")) { + println("Files to compile: $filesToCompile") + println(args) + } + standardOutput = log + errorOutput = log + super.exec() + } finally { + def logString = log.toString("UTF-8") + project.file("${output}.compilation.log").write(logString) + println(logString) + } + } + + // FIXME: output directory here changes and hence this is not a property + String executablePath() { return "$outputDirectory/program.tr" } + + OutputStream out + + void runExecutable() { + if (!enabled) { + println "Test is disabled: $name" + return + } + def program = executablePath() + def suffix = target.family.exeSuffix + def exe = "$program.$suffix" + + println "execution: $exe" + + def compilerMessagesText = compilerMessages ? project.file("${program}.compilation.log").getText('UTF-8') : "" + + out = new ByteArrayOutputStream() + //TODO Add test timeout + + def times = multiRuns ? multiArguments.size() : 1 + + def exitCodeMismatch = false + for (int i = 0; i < times; i++) { + ExecResult execResult = project.execute { + + commandLine exe + + if (arguments != null) { + args arguments + } + if (multiRuns && multiArguments[i] != null) { + args multiArguments[i] + } + if (testData != null) { + standardInput = new ByteArrayInputStream(testData.bytes) + } + standardOutput = out + + ignoreExitValue = true + } + + exitCodeMismatch |= execResult.exitValue != expectedExitStatus + if (exitCodeMismatch) { + def message = "Expected exit status: $expectedExitStatus, actual: ${execResult.exitValue}" + if (this.expectedFail) { + println("Expected failure. $message") + } else { + throw new TestFailedException("Test failed on iteration $i. $message\n ${out.toString("UTF-8")}") + } + } + } + def result = compilerMessagesText + out.toString("UTF-8") + if (printOutput) { + println(result) + } + result = result.replace(System.lineSeparator(), "\n") + def goldValueMismatch = !outputChecker.apply(result) + if (goldValueMismatch) { + def message + if (goldValue != null) { + message = "Expected output: $goldValue, actual output: $result" + } else { + message = "Actual output doesn't match output checker: $result" + } + if (this.expectedFail) { + println("Expected failure. $message") + } else { + throw new TestFailedException("Test failed. $message") + } + } + + if (!exitCodeMismatch && !goldValueMismatch && this.expectedFail) println("Unexpected pass") + } + + /** + * If true, the test executable will be built in two stages: + * 1. Build a klibrary from sources. + * 2. Build a final executable from this klibrary. + */ + @Input + public def enableTwoStageCompilation = false + + @Input + def groupDirectory = "." + + String filter = project.findProperty("filter") + + def testGroupReporter = new KonanTestGroupReportEnvironment(project) + + void parseLanguageFlags(String src) { + def text = project.buildDir.toPath().resolve(src).text + def languageSettings = findLinesWithPrefixesRemoved(text, "// !LANGUAGE: ") + if (languageSettings.size() != 0) { + languageSettings.forEach { line -> + line.split(" ").toList().forEach { flags.add("-XXLanguage:$it") } + } + } + + def experimentalSettings = findLinesWithPrefixesRemoved(text, "// !USE_EXPERIMENTAL: ") + if (experimentalSettings.size() != 0) { + experimentalSettings.forEach { line -> + line.split(" ").toList().forEach { flags.add("-Xopt-in=$it") } + } + } + def expectActualLinker = findLinesWithPrefixesRemoved(text, "// EXPECT_ACTUAL_LINKER") + if (expectActualLinker.size() != 0) { + flags.add("-Xexpect-actual-linker") + } + } + + static String markMutableObjects(String text) { + def lines = text.readLines() + def result = new ArrayList(lines.size()) + lines.forEach { line -> + // FIXME: find only those who has vars inside + // Find object declarations and companion objects + if (line.matches("\\s*(private|public|internal)?\\s*object [a-zA-Z_][a-zA-Z0-9_]*\\s*.*") + || line.matches("\\s*(private|public|internal)?\\s*companion object.*")) { + result += "@kotlin.native.ThreadLocal" + } + result += line + } + return result.join(System.lineSeparator()) + } + + static String insertInTextAfter(String text, String insert, String after) { + def begin = text.indexOf(after) + if (begin != -1) { + def end = text.indexOf("\n", begin) + text = text.substring(0, end) + insert + text.substring(end) + } else { + text = insert + text + } + return text + } + + List createTestFiles(String src) { + def identifier = /[a-zA-Z_][a-zA-Z0-9_]/ + def fullQualified = /[a-zA-Z_][a-zA-Z0-9_.]/ + def importRegex = /(?m)^\s*import\s+/ + + def packagePattern = ~/(?m)^\s*package\s+(${fullQualified}*)/ + def boxPattern = ~/(?m)fun\s+box\s*\(\s*\)/ + def classPattern = ~/.*(class|object|enum|interface)\s+(${identifier}*).*/ + + def sourceName = "_" + normalize(project.buildDir.toPath().resolve(src).toFile().name) + def packages = new LinkedHashSet() + def imports = [] + def classes = [] + def vars = new HashSet() // variables that has the same name as a package + TestModule mainModule = null + + def testFiles = TestDirectivesKt.buildCompileList(project.file("build/$src").toPath(), "$outputDirectory/$src") + for (TestFile testFile: testFiles) { + def text = testFile.text + def filePath = testFile.path + if (text.contains('COROUTINES_PACKAGE')) { + text = text.replace('COROUTINES_PACKAGE', 'kotlin.coroutines') + } + def pkg + if (text =~ packagePattern) { + pkg = (text =~ packagePattern)[0][1] + packages.add(pkg) + pkg = "$sourceName.$pkg" + text = text.replaceFirst(packagePattern, "package $pkg") + } else { + pkg = sourceName + text = insertInTextAfter(text, "\npackage $pkg\n", "@file:") + } + if (text =~ boxPattern) { + imports.add("${pkg}.*") + mainModule = testFile.module + } + + // Find mutable objects that should be marked as ThreadLocal + if (filePath != "$outputDirectory/$src/helpers.kt") { + text = markMutableObjects(text) + } + testFile.text = text + } + for (TestFile testFile: testFiles) { + def text = testFile.text + // Find if there are any imports in the file + def matcher = (text =~ ~/${importRegex}(${fullQualified}*)/) + if (matcher) { + // Prepend package name to found imports + for (int i = 0; i < matcher.count; i++) { + String importStatement = matcher[i][1] + def subImport = importStatement.with { + int dotIdx = indexOf('.') + dotIdx > 0 ? substring(0, dotIdx) : it + } + if (packages.contains(subImport) || classes.contains(subImport)) { + // add only to those who import packages or import classes from the test files + text = text.replaceFirst(~/${importRegex}${Pattern.quote(importStatement)}/, + "import $sourceName.$importStatement") + } else if (text =~ classPattern) { + // special case for import from the local class + def clsMatcher = (text =~ classPattern) + for (int j = 0; j < clsMatcher.count; j++) { + def cl = (text =~ classPattern)[j][2] + classes.add(cl) + if (subImport == cl) { + text = text.replaceFirst(~/${importRegex}${Pattern.quote(importStatement)}/, + "import $sourceName.$importStatement") + } + } + } + } + } else if (packages.empty) { + // Add import statement after package + def pkg = null + if (text =~ packagePattern) { + pkg = 'package ' + (text =~ packagePattern)[0][1] + text = text.replaceFirst(packagePattern, '') + } + text = insertInTextAfter(text, (pkg ? "\n$pkg\n" : "") + "import $sourceName.*\n", "@file:") + } + // now replace all package usages in full qualified names + def res = "" // filesToCompile + text.eachLine { line -> + packages.each { pkg -> + // line contains val or var declaration or function parameter declaration + if ((line =~ ~/va(l|r) *$pkg*( *: *$fullQualified*)?( *get\(\))? *\=.*/) || + (line =~ ~/fun .*\(\n?\s*$pkg:.*/)) { + vars.add(pkg) + } + if (line.contains("$pkg.") && !(line =~ packagePattern || line =~ importRegex) + && !vars.contains(pkg)) { + def idx = 0 + while ((idx = line.indexOf(pkg, idx)) >= 0) { + if (!Character.isJavaIdentifierPart(line.charAt(idx - 1))) { + line = line.substring(0, idx) + "$sourceName.$pkg" + line.substring(idx + pkg.length()) + idx += sourceName.length() + pkg.length() + 1 + } else { + idx += pkg.length() + } + } + } + } + res += "$line\n" + } + testFile.text = res + } + def launcherText = createLauncherFileText(src, imports) + testFiles.add(new TestFile("_launcher.kt", "$outputDirectory/$src/_launcher.kt".toString(), + launcherText, mainModule != null ? mainModule : TestModule.default)) + return testFiles + } + + String normalize(String name) { + name.replace('.kt', '') + .replace('-','_') + .replace('.', '_') + } + + /** + * There are tests that require non-trivial 'package foo' in test launcher. + */ + String createLauncherFileText(String src, List imports) { + StringBuilder text = new StringBuilder() + def pack = normalize(project.file(src).name) + text.append("package _$pack\n") + for (v in imports) { + text.append("import $v\n") + } + text.append( +""" +import kotlin.test.Test + +@Test +fun runTest() { + @Suppress("UNUSED_VARIABLE") + val result = box() + if (result != "OK") throw AssertionError("Test failed with: " + result) +} +""" ) + return text.toString() + } + + List findLinesWithPrefixesRemoved(String text, String prefix) { + def result = [] + text.eachLine { + if (it.startsWith(prefix)) { + result.add(it - prefix) + } + } + return result + } + + static def excludeList = [ + "external/compiler/codegen/boxInline/multiplatform/defaultArguments/receiversAndParametersInLambda.kt", // KT-36880 + "external/compiler/compileKotlinAgainstKotlin/specialBridgesInDependencies.kt", // KT-42723 + "external/compiler/codegen/box/collections/kt41123.kt", // KT-42723 + "external/compiler/codegen/box/multiplatform/multiModule/expectActualTypealiasLink.kt", // KT-40137 + "external/compiler/codegen/box/multiplatform/multiModule/expectActualMemberLink.kt", // KT-33091 + "external/compiler/codegen/box/multiplatform/multiModule/expectActualLink.kt", // KT-41901 + "external/compiler/codegen/box/coroutines/multiModule/", // KT-40121 + "external/compiler/codegen/box/callableReference/genericConstructorReference.kt", // KT-42631 + "external/compiler/codegen/box/defaultArguments/recursiveDefaultArguments.kt" // KT-42684 + ] + + boolean isEnabledForNativeBackend(String fileName) { + def text = project.buildDir.toPath().resolve(fileName).text + + if (excludeList.any { fileName.replace(File.separator, "/").contains(it) }) return false + + def languageSettings = findLinesWithPrefixesRemoved(text, '// !LANGUAGE: ') + if (!languageSettings.empty) { + def settings = languageSettings.first() + if (settings.contains('-ProperIeee754Comparisons') || // K/N supports only proper IEEE754 comparisons + settings.contains('-ReleaseCoroutines') || // only release coroutines + settings.contains('-DataClassInheritance') || // old behavior is not supported + settings.contains('-ProhibitAssigningSingleElementsToVarargsInNamedForm')) { // Prohibit these assignments + return false + } + } + + def version = findLinesWithPrefixesRemoved(text, '// LANGUAGE_VERSION: ') + if (version.size() != 0 && (!version.contains("1.3") || !version.contains("1.4"))) { + // Support tests for 1.3 and exclude 1.2 + return false + } + + def apiVersion = findLinesWithPrefixesRemoved(text, '// !API_VERSION: ') + if (apiVersion.size() != 0 && !apiVersion.contains("1.4")) { + return false + } + + def targetBackend = findLinesWithPrefixesRemoved(text, "// TARGET_BACKEND") + if (targetBackend.size() != 0) { + // There is some target backend. Check if it is NATIVE or not. + for (String s : targetBackend) { + if (s.contains("NATIVE")){ return true } + } + return false + } else { + // No target backend. Check if NATIVE backend is ignored. + def ignoredBackends = findLinesWithPrefixesRemoved(text, "// IGNORE_BACKEND: ") + for (String s : ignoredBackends) { + if (s.contains("NATIVE")) { return false } + } + // No ignored backends. Check if test is targeted to FULL_JDK or has JVM_TARGET set + if (!findLinesWithPrefixesRemoved(text, "// FULL_JDK").isEmpty()) { return false } + if (!findLinesWithPrefixesRemoved(text, "// JVM_TARGET:").isEmpty()) { return false } + return true + } + } + + @TaskAction + void executeTest() { + createOutputDirectory() + // Form the test list. + List ktFiles = project.buildDir.toPath().resolve(groupDirectory).toFile() + .listFiles({ + it.isFile() && it.name.endsWith(".kt") + } as FileFilter) + if (filter != null) { + def pattern = ~filter + ktFiles = ktFiles.findAll { + it.name =~ pattern + } + } + + testGroupReporter.suite(name) { suite -> + // Build tests in the group + flags = (flags ?: []) + "-tr" + List compileList = [] + ktFiles.each { + def src = project.buildDir.relativePath(it) + if (isEnabledForNativeBackend(src)) { + // Create separate output directory for each test in the group. + project.file("$outputDirectory/${it.name}").mkdirs() + parseLanguageFlags(src) + compileList.addAll(createTestFiles(src)) + } + } + compileList*.writeTextToFile() + try { + if (enableTwoStageCompilation) { + // Two-stage compilation. + def klibPath = "${executablePath()}.klib" + def files = compileList.stream() + .map { it.path } + .collect(Collectors.toList()) + if (!files.empty) { + runCompiler(files, klibPath, flags + ["-p", "library"]) + runCompiler([], executablePath(), flags + ["-Xinclude=$klibPath"]) + } + } else { + // Regular compilation with modules. + Map modules = compileList.stream() + .map { it.module } + .distinct() + .collect(Collectors.toMap({ it.name }, UnaryOperator.identity() )) + + List orderedModules = DFS.INSTANCE.topologicalOrder(modules.values()) { module -> + module.dependencies.collect { modules[it] }.findAll { it != null } + } + Set libs = new HashSet() + orderedModules.reverse().each { module -> + if (!module.isDefaultModule()) { + def klibModulePath = "${executablePath()}.${module.name}.klib" + libs.addAll(module.dependencies) + def klibs = libs.collectMany { ["-l", "${executablePath()}.${it}.klib"] }.toList() + def friends = module.friends ? + module.friends.collectMany { + ["-friend-modules", "${executablePath()}.${it}.klib"] + }.toList() : [] + runCompiler(compileList.findAll { it.module == module }.collect { it.path }, + klibModulePath, flags + ["-p", "library"] + klibs + friends) + } + } + + def compileMain = compileList.findAll { + it.module.isDefaultModule() || it.module == TestModule.support + } + compileMain.forEach { f -> + libs.addAll(f.module.dependencies) + } + def friends = compileMain.collectMany {it.module.friends }.toSet() + if (!compileMain.empty) { + runCompiler(compileMain.collect { it.path }, executablePath(), flags + + libs.collectMany { ["-l", "${executablePath()}.${it}.klib"] }.toList() + + friends.collectMany {["-friend-modules", "${executablePath()}.${it}.klib"]}.toList() + ) + } + } + } catch (Exception ex) { + project.logger.quiet("ERROR: Compilation failed for test suite: $name with exception", ex) + project.logger.quiet("The following files were unable to compile:") + ktFiles.each { project.logger.quiet(it.name) } + suite.abort(ex, ktFiles.size()) + throw new RuntimeException("Compilation failed", ex) + } + + // Run the tests. + arguments = (arguments ?: []) + "--ktest_logger=SILENT" + ktFiles.each { file -> + def src = project.buildDir.relativePath(file) + def savedArgs = arguments + arguments += "--ktest_filter=_${normalize(file.name)}.*" + use(KonanTestSuiteReportKt) { + project.logger.quiet("TEST: $file.name " + + "(done: $testGroupReporter.statistics.total/${ktFiles.size()}, " + + "passed: $testGroupReporter.statistics.passed, " + + "skipped: $testGroupReporter.statistics.skipped)") + } + if (isEnabledForNativeBackend(src)) { + suite.executeTest(file.name) { + project.logger.quiet(src) + runExecutable() + } + } else { + suite.skipTest(file.name) + } + arguments = savedArgs + } + } + } +} diff --git a/kotlin-native/build-tools/src/main/groovy/org/jetbrains/kotlin/NativeInteropPlugin.groovy b/kotlin-native/build-tools/src/main/groovy/org/jetbrains/kotlin/NativeInteropPlugin.groovy new file mode 100644 index 00000000000..5db18fb4552 --- /dev/null +++ b/kotlin-native/build-tools/src/main/groovy/org/jetbrains/kotlin/NativeInteropPlugin.groovy @@ -0,0 +1,313 @@ +/* + * Copyright 2010-2017 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.jetbrains.kotlin + +import org.gradle.api.Named +import org.gradle.api.Plugin +import org.gradle.api.Project +import org.gradle.api.Task +import org.gradle.api.artifacts.Configuration +import org.gradle.api.file.FileCollection +import org.gradle.api.internal.AbstractNamedDomainObjectContainer +import org.gradle.api.internal.CollectionCallbackActionDecorator +import org.gradle.api.internal.file.AbstractFileCollection +import org.gradle.api.tasks.JavaExec +import org.gradle.api.tasks.SourceSet +import org.gradle.api.tasks.TaskDependency +import org.gradle.internal.reflect.Instantiator +import org.jetbrains.kotlin.konan.target.* +import org.jetbrains.kotlin.konan.util.* + +class NamedNativeInteropConfig implements Named { + + private final Project project + final String name + + + private String interopStubsName + private SourceSet interopStubs + final JavaExec genTask + + private String flavor = "jvm" + + private String defFile + + private String pkg + private String target + + private List compilerOpts = [] + private List headers; + private String linker + List linkerOpts = [] + private FileCollection linkFiles; + private List linkTasks = [] + + Configuration configuration + + void flavor(String value) { + flavor = value + } + + void defFile(String value) { + defFile = value + genTask.inputs.file(project.file(defFile)) + } + + void target(String value) { + target = value + } + + void pkg(String value) { + pkg = value + } + + void compilerOpts(List values) { + compilerOpts.addAll(values) + } + + void compilerOpts(String... values) { + compilerOpts.addAll(values) + } + + void headers(FileCollection files) { + dependsOnFiles(files) + headers = headers + files.toSet().collect { it.absolutePath } + } + + void headers(String... values) { + headers = headers + values.toList() + } + + void linker(String value) { + linker = value + } + + void linkerOpts(String... values) { + this.linkerOpts(values.toList()) + } + + void linkerOpts(List values) { + linkerOpts.addAll(values) + } + + void dependsOn(Object... deps) { + // TODO: add all files to inputs + genTask.dependsOn(deps) + } + + private void dependsOnFiles(FileCollection files) { + dependsOn(files) + genTask.inputs.files(files) + } + + void link(FileCollection files) { + linkFiles = linkFiles + files + dependsOnFiles(files) + } + + void linkOutputs(Task task) { + linkOutputs(task.name) + } + + void linkOutputs(String task) { + linkTasks += task + dependsOn(task) + + final Project prj; + String taskName; + int index = task.lastIndexOf(':') + if (index != -1) { + prj = project.project(task.substring(0, index)) + taskName = task.substring(index + 1) + } else { + prj = project + taskName = task + } + + prj.tasks.matching { it.name == taskName }.all { // TODO: it is a hack + this.dependsOnFiles(it.outputs.files) + } + } + + void includeDirs(String... values) { + compilerOpts.addAll(values.collect {"-I$it"}) + } + + File getNativeLibsDir() { + return new File(project.buildDir, "nativelibs/$target") + } + + File getGeneratedSrcDir() { + return new File(project.buildDir, "nativeInteropStubs/$name/kotlin") + } + + File getTemporaryFilesDir() { + return new File(project.buildDir, "interopTemp") + } + + NamedNativeInteropConfig(Project project, String name, String target = null, String flavor = 'jvm') { + this.name = name + this.project = project + this.flavor = flavor + + def platformManager = project.rootProject.ext.platformManager + def targetManager = platformManager.targetManager(target) + this.target = targetManager.targetName + + this.headers = [] + this.linkFiles = project.files() + + interopStubsName = name + "InteropStubs" + genTask = project.task("gen" + interopStubsName.capitalize(), type: JavaExec) + + this.configure() + } + + private void configure() { + if (project.plugins.hasPlugin("kotlin")) { + interopStubs = project.sourceSets.create(interopStubsName) + configuration = project.configurations.create(interopStubs.name) + project.tasks.getByName(interopStubs.getTaskName("compile", "Kotlin")) { + dependsOn genTask + } + + interopStubs.kotlin.srcDirs generatedSrcDir + + project.dependencies { + add interopStubs.getCompileConfigurationName(), project(path: ':Interop:Runtime') + } + + this.configuration.extendsFrom project.configurations[interopStubs.runtimeConfigurationName] + project.dependencies.add(this.configuration.name, interopStubs.output) + } + + genTask.configure { + classpath = project.configurations.interopStubGenerator + main = "org.jetbrains.kotlin.native.interop.gen.jvm.MainKt" + jvmArgs '-ea' + + systemProperties "java.library.path" : project.files( + new File(project.findProject(":Interop:Indexer").buildDir, "nativelibs"), + new File(project.findProject(":Interop:Runtime").buildDir, "nativelibs") + ).asPath + // Set the konan.home property because we run the cinterop tool not from a distribution jar + // so it will not be able to determine this path by itself. + systemProperties "konan.home": project.rootProject.projectDir + environment "LIBCLANG_DISABLE_CRASH_RECOVERY": "1" + + outputs.dir generatedSrcDir + outputs.dir nativeLibsDir + outputs.dir temporaryFilesDir + + // defer as much as possible + doFirst { + List linkerOpts = this.linkerOpts + + linkTasks.each { + linkerOpts += project.tasks.getByPath(it).outputs.files.files + } + + linkerOpts += linkFiles.files + + args '-generated', generatedSrcDir + args '-natives', nativeLibsDir + args '-Xtemporary-files-dir', temporaryFilesDir + args '-flavor', this.flavor + if (flavor == "jvm") { + args '-mode', 'sourcecode' + } + // Uncomment to debug. + // args '-verbose', 'true' + + if (defFile != null) { + args '-def', project.file(defFile) + } + + if (pkg != null) { + args '-pkg', pkg + } + + if (linker != null) { + args '-linker', linker + } + + if (target != null) { + args '-target', target + } + + // TODO: the interop plugin should probably be reworked to execute clang from build scripts directly + environment['PATH'] = project.files(project.hostPlatform.clang.clangPaths).asPath + + File.pathSeparator + environment['PATH'] + + args compilerOpts.collectMany { ['-compiler-option', it] } + args linkerOpts.collectMany { ['-linker-option', it] } + + headers.each { + args '-header', it + } + + } + } + } +} + +class NativeInteropExtension extends AbstractNamedDomainObjectContainer { + + private final Project project + private String target = null + private String flavor = 'jvm' + + protected NativeInteropExtension(Project project) { + super(NamedNativeInteropConfig, project.gradle.services.get(Instantiator), project.gradle.services.get(CollectionCallbackActionDecorator)) + this.project = project + } + + @Override + protected NamedNativeInteropConfig doCreate(String name) { + def config = new NamedNativeInteropConfig(project, name, target, flavor) + return config + } + + public void target(String value) { + this.target = value + } + + public void flavor(String value) { + this.flavor = value + } +} + +class NativeInteropPlugin implements Plugin { + + @Override + void apply(Project prj) { + prj.extensions.add("kotlinNativeInterop", new NativeInteropExtension(prj)) + + def runtimeNativeLibsDir = new File(prj.findProject(':Interop:Runtime').buildDir, 'nativelibs') + + def nativeLibsDir = new File(prj.buildDir, "nativelibs") + + prj.configurations { + interopStubGenerator + } + + prj.dependencies { + interopStubGenerator project(path: ":Interop:StubGenerator") + interopStubGenerator project(path: ":endorsedLibraries:kotlinx.cli", configuration: "jvmRuntimeElements") + } + } +} diff --git a/kotlin-native/build-tools/src/main/kotlin/org/jetbrains/kotlin/BenchmarkRepeatingType.kt b/kotlin-native/build-tools/src/main/kotlin/org/jetbrains/kotlin/BenchmarkRepeatingType.kt new file mode 100644 index 00000000000..6f62eb7afe6 --- /dev/null +++ b/kotlin-native/build-tools/src/main/kotlin/org/jetbrains/kotlin/BenchmarkRepeatingType.kt @@ -0,0 +1,6 @@ +package org.jetbrains.kotlin + +enum class BenchmarkRepeatingType { + INTERNAL, // Let the benchmark perform warmups and repeats. + EXTERNAL, // Repeat by relaunching benchmark +} \ No newline at end of file diff --git a/kotlin-native/build-tools/src/main/kotlin/org/jetbrains/kotlin/BuildRegister.kt b/kotlin-native/build-tools/src/main/kotlin/org/jetbrains/kotlin/BuildRegister.kt new file mode 100644 index 00000000000..a67b2f1c113 --- /dev/null +++ b/kotlin-native/build-tools/src/main/kotlin/org/jetbrains/kotlin/BuildRegister.kt @@ -0,0 +1,88 @@ +/* + * Copyright 2010-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the license/LICENSE.txt file. + */ + +package org.jetbrains.kotlin + +import org.gradle.api.DefaultTask +import org.gradle.api.tasks.TaskAction +import java.io.BufferedReader +import java.io.FileInputStream +import java.io.InputStreamReader +import java.io.OutputStreamWriter +import java.net.HttpURLConnection +import java.net.URL +import java.util.* + +/** + * Task to save benchmarks results on server. + * + * @property bundleSize size of build + * @property onlyBranch register only builds for branch + * @property fileWithResult json file with benchmarks run results + */ +open class BuildRegister : DefaultTask() { + var onlyBranch: String? = null + + var bundleSize: Int? = null + var fileWithResult: String = "nativeReport.json" + + val performanceServer = "https://kotlin-native-perf-summary.labs.jb.gg" + + private fun sendPostRequest(url: String, body: String): String { + val connection = URL(url).openConnection() as HttpURLConnection + return connection.apply { + setRequestProperty("Content-Type", "application/json; charset=utf-8") + requestMethod = "POST" + doOutput = true + val outputWriter = OutputStreamWriter(outputStream) + outputWriter.write(body) + outputWriter.flush() + }.let { + if (it.responseCode == 200) it.inputStream else it.errorStream + }.let { streamToRead -> + BufferedReader(InputStreamReader(streamToRead)).use { + val response = StringBuffer() + + var inputLine = it.readLine() + while (inputLine != null) { + response.append(inputLine) + inputLine = it.readLine() + } + it.close() + response.toString() + } + } + } + + @TaskAction + fun run() { + // Get TeamCity properties. + val teamcityConfig = System.getenv("TEAMCITY_BUILD_PROPERTIES_FILE") ?: error("Can't load teamcity config!") + + val buildProperties = Properties() + buildProperties.load(FileInputStream(teamcityConfig)) + val buildId = buildProperties.getProperty("teamcity.build.id") + val teamCityUser = buildProperties.getProperty("teamcity.auth.userId") + val teamCityPassword = buildProperties.getProperty("teamcity.auth.password") + + // Get branch. + val currentBuild = getBuild("id:$buildId", teamCityUser, teamCityPassword) + val branch = getBuildProperty(currentBuild, "branchName") + + // Send post request to register build. + val requestBody = buildString { + append("{\"buildId\":\"$buildId\",") + append("\"teamCityUser\":\"$teamCityUser\",") + append("\"teamCityPassword\":\"$teamCityPassword\",") + append("\"fileWithResult\":\"$fileWithResult\",") + append("\"bundleSize\": ${bundleSize?.let { "\"$bundleSize\"" } ?: bundleSize}}") + } + if (onlyBranch == null || onlyBranch == branch) { + println(sendPostRequest("$performanceServer/register", requestBody)) + } else { + println("Skipping registration. Current branch $branch, need registration for $onlyBranch!") + } + } +} \ No newline at end of file diff --git a/kotlin-native/build-tools/src/main/kotlin/org/jetbrains/kotlin/CacheTesting.kt b/kotlin-native/build-tools/src/main/kotlin/org/jetbrains/kotlin/CacheTesting.kt new file mode 100644 index 00000000000..b7377d845f6 --- /dev/null +++ b/kotlin-native/build-tools/src/main/kotlin/org/jetbrains/kotlin/CacheTesting.kt @@ -0,0 +1,60 @@ +package org.jetbrains.kotlin + +import org.gradle.api.Project +import org.gradle.api.Task +import org.gradle.api.tasks.Exec +import org.jetbrains.kotlin.konan.target.CompilerOutputKind +import org.jetbrains.kotlin.konan.util.visibleName + +class CacheTesting(val buildCacheTask: Task, val compilerArgs: List, val isDynamic: Boolean) + +fun configureCacheTesting(project: Project): CacheTesting? { + val cacheKindString = project.findProperty("test_with_cache_kind") as String? ?: return null + val isDynamic = when (cacheKindString) { + "dynamic" -> true + "static" -> false + else -> error(cacheKindString) + } + + val cacheKind = if (isDynamic) { + CompilerOutputKind.DYNAMIC_CACHE + } else { + CompilerOutputKind.STATIC_CACHE + } + + val target = project.testTarget + + val cacheDir = project.file("${project.buildDir}/cache") + val cacheFile = "$cacheDir/stdlib-cache" + val dist = project.kotlinNativeDist + val stdlib = "$dist/klib/common/stdlib" + val compilerArgs = listOf("-Xcached-library=$stdlib,$cacheFile") + + val buildCacheTask = project.tasks.create("buildStdlibCache", Exec::class.java) { + it.doFirst { + cacheDir.mkdirs() + } + + if (!(project.property("useCustomDist") as Boolean)) { + val tasks = listOf( + "${target}CrossDist", + "${target}CrossDistRuntime", + "distCompiler" + ).map { task -> project.rootProject.tasks.getByName(task) } + + it.dependsOn(tasks) + } + + it.commandLine( + "$dist/bin/konanc", + "-p", cacheKind.visibleName, + "-o", "$cacheDir/stdlib-cache", + "-Xmake-cache=$stdlib", + "-no-default-libs", "-nostdlib", + "-target", target, + "-g" + ) + } + + return CacheTesting(buildCacheTask, compilerArgs, isDynamic) +} \ No newline at end of file diff --git a/kotlin-native/build-tools/src/main/kotlin/org/jetbrains/kotlin/CollisionDetector.kt b/kotlin-native/build-tools/src/main/kotlin/org/jetbrains/kotlin/CollisionDetector.kt new file mode 100644 index 00000000000..f0357738378 --- /dev/null +++ b/kotlin-native/build-tools/src/main/kotlin/org/jetbrains/kotlin/CollisionDetector.kt @@ -0,0 +1,85 @@ +/* + * Copyright 2010-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the license/LICENSE.txt file. + */ + +package org.jetbrains.kotlin + +import org.gradle.api.DefaultTask +import org.gradle.api.tasks.TaskAction +import org.gradle.api.artifacts.Configuration +import org.gradle.api.tasks.Input +import org.gradle.api.tasks.InputFiles +import java.io.File +import java.util.zip.ZipFile + +/** + * Task to find out collisions before producing fat jar. + * + * @property configurations added to fat jar configurations + * @property resolvingRules a map containing rules to resolve conflicts. Key - conflicting file, value - a jar to copy the file from + * @property resolvingRulesWithRegexes a map containing rules to resolve conflicts. Key - regular expression describing conflicting file, value - a jar to copy the file from + * @property librariesWithIgnoredClassCollisions libraries which collision in class files are ignored + */ +open class CollisionDetector : DefaultTask() { + @InputFiles + var configurations = listOf() + @Input + val resolvingRules = mutableMapOf() + @Input + val resolvingRulesWithRegexes = mutableMapOf() + @Input + val librariesWithIgnoredClassCollisions = mutableListOf() + val resolvedConflicts = mutableMapOf() + + // Key - filename, value - jar file containing it. + private val filesInfo = mutableMapOf() + + @TaskAction + fun run() { + configurations.forEach { configuration -> + configuration.files.filter { it.name.endsWith(".jar") }.forEach { processedFile -> + ZipFile(processedFile).use { zip -> + zip.entries().asSequence().filterNot { + it.isDirectory || + it.name.equals("META-INF/MANIFEST.MF", ignoreCase = true) || + it.name.equals("META-INF/versions/9/module-info.class", ignoreCase = true) || + it.name.startsWith("META-INF/services/", ignoreCase = true) + }.forEach { + val outputPath = it.name + if (outputPath in filesInfo.keys) { + val rule = resolvingRules.getOrElse(outputPath) { + resolvingRulesWithRegexes.entries.firstOrNull { (key, _) -> key.matches(outputPath) }?.value + } + var ignoreJar = false + if (rule != null && processedFile.name.startsWith(rule)) { + resolvedConflicts[outputPath] = processedFile + } else { + // Skip class files from ignored libraries if version of libraries had collision are the same. + val versionRegex = "\\d+\\.\\d+(\\.\\d+)?(-M\\d)?(-\\w+(-\\d+)?)?".toRegex() + val currentVersion = versionRegex.find(processedFile.name)?.groupValues?.get(0) + val collisionLibVersion = versionRegex.find(filesInfo.getValue(outputPath))?.groupValues?.get(0) + if (outputPath.endsWith(".class") && currentVersion == collisionLibVersion) { + if (processedFile.name == filesInfo[outputPath]) { + ignoreJar = true + } else { + librariesWithIgnoredClassCollisions.forEach { + if (processedFile.name.startsWith(it)) { + ignoreJar = true + } + } + } + } + } + if (rule == null && !ignoreJar) { + error("Collision is detected. File $outputPath is found in ${filesInfo[outputPath]} and ${processedFile.name}") + } + } else { + filesInfo[outputPath] = processedFile.name + } + } + } + } + } + } +} diff --git a/kotlin-native/build-tools/src/main/kotlin/org/jetbrains/kotlin/CollisionTransformer.kt b/kotlin-native/build-tools/src/main/kotlin/org/jetbrains/kotlin/CollisionTransformer.kt new file mode 100644 index 00000000000..ccf81693bd6 --- /dev/null +++ b/kotlin-native/build-tools/src/main/kotlin/org/jetbrains/kotlin/CollisionTransformer.kt @@ -0,0 +1,48 @@ +/* + * Copyright 2010-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the license/LICENSE.txt file. + */ + +package org.jetbrains.kotlin + +import com.github.jengelman.gradle.plugins.shadow.transformers.Transformer +import com.github.jengelman.gradle.plugins.shadow.transformers.TransformerContext +import org.gradle.api.file.FileTreeElement +import shadow.org.apache.tools.zip.ZipOutputStream +import java.io.File +import shadow.org.apache.commons.io.IOUtils +import shadow.org.apache.tools.zip.ZipEntry +import shadow.org.apache.tools.zip.ZipFile + +class CollisionTransformer: Transformer { + var resolvedConflicts = mutableMapOf() + private val foundConflictsFiles = mutableSetOf() + + override fun canTransformResource(element: FileTreeElement): Boolean { + val result = element.name in resolvedConflicts.keys + if (result) { + foundConflictsFiles.add(element.name) + } + return result + } + + override fun transform(context: TransformerContext) {} + + override fun hasTransformedResource(): Boolean { + return foundConflictsFiles.isNotEmpty() + } + + override fun modifyOutputStream(jos: ZipOutputStream, preserveFileTimestamps: Boolean) { + foundConflictsFiles.forEach { + val entry = ZipEntry(it) + entry.time = TransformerContext.getEntryTimestamp(preserveFileTimestamps, entry.time) + jos.putNextEntry(entry) + val archive = ZipFile(resolvedConflicts[it]) + archive.getInputStream(archive.getEntry(it)).use { + IOUtils.copyLarge(it, jos) + } + jos.closeEntry() + } + foundConflictsFiles.clear() + } +} \ No newline at end of file diff --git a/kotlin-native/build-tools/src/main/kotlin/org/jetbrains/kotlin/CompilationDatabase.kt b/kotlin-native/build-tools/src/main/kotlin/org/jetbrains/kotlin/CompilationDatabase.kt new file mode 100644 index 00000000000..999a64db016 --- /dev/null +++ b/kotlin-native/build-tools/src/main/kotlin/org/jetbrains/kotlin/CompilationDatabase.kt @@ -0,0 +1,129 @@ +/* + * Copyright 2010-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +package org.jetbrains.kotlin + +import java.io.File +import javax.inject.Inject +import org.gradle.api.GradleException +import com.google.gson.annotations.Expose +import org.gradle.api.Project +import org.gradle.api.Task +import org.gradle.api.DefaultTask +import org.gradle.api.tasks.Input +import org.gradle.api.tasks.InputFiles +import org.gradle.api.tasks.OutputFile +import org.gradle.api.tasks.TaskAction +import org.jetbrains.kotlin.bitcode.CompileToBitcode +import java.io.FileReader +import java.io.FileWriter + +internal data class Entry( + @Expose val directory: String, + @Expose val file: String, + @Expose val arguments: List, + @Expose val output: String +) { + companion object { + fun create( + directory: File, + file: File, + args: List, + outputDir: File + ): Entry { + return Entry( + directory.absolutePath, + file.absolutePath, + args + listOf(file.absolutePath), + File(outputDir, file.name + ".o").absolutePath + ) + } + + fun writeListTo(file: File, entries: List) = FileWriter(file).use { + gson.toJson(entries, it) + } + + fun readListFrom(file: File): Array = FileReader(file).use { + gson.fromJson(it, Array::class.java) + } + } +} + +open class GenerateCompilationDatabase @Inject constructor(@Input val target: String, + @Input val srcRoot: File, + @Input val files: Iterable, + @Input val executable: String, + @Input val compilerFlags: List, + @Input val outputDir: File +) : DefaultTask() { + @OutputFile + var outputFile = File(outputDir, "compile_commands.json") + + @TaskAction + fun run() { + val plugin = project.convention.getPlugin(ExecClang::class.java) + val executable = plugin.resolveExecutable(executable) + val args = listOf(executable) + compilerFlags + plugin.konanArgs(target) + val entries: List = files.map { Entry.create(srcRoot, it, args, outputDir) } + Entry.writeListTo(outputFile, entries) + } +} + +open class MergeCompilationDatabases @Inject constructor() : DefaultTask() { + @InputFiles + val inputFiles = mutableListOf() + + @OutputFile + var outputFile = File(project.buildDir, "compile_commands.json") + + @TaskAction + fun run() { + val entries = mutableListOf() + for (file in inputFiles) { + entries.addAll(Entry.readListFrom(file)) + } + Entry.writeListTo(outputFile, entries) + } +} + +fun mergeCompilationDatabases(project: Project, name: String, paths: List): Task { + val subtasks: List = paths.map { + val task = project.tasks.getByPath(it) + if (task !is MergeCompilationDatabases) { + throw GradleException("Unknown task type for compdb merging: $task") + } + task + } + return project.tasks.create(name, MergeCompilationDatabases::class.java) { task -> + task.dependsOn(subtasks) + task.inputFiles.addAll(subtasks.map { it.outputFile }) + } +} + +/** + * Get all [CompileToBitcode] tasks in the project, group them by target, and generate + * compilation database for each target. Tasks will be named [name]. Databases + * will be placed in a build dir in /compile_commands.json + */ +fun createCompilationDatabasesFromCompileToBitcodeTasks(project: Project, name: String) { + val compileTasks = project.tasks.withType(CompileToBitcode::class.java).toList() + val compdbTasks = compileTasks.groupBy({ task -> task.target }) { task -> + project.tasks.create("${task.name}_CompilationDatabase", + GenerateCompilationDatabase::class.java, + task.target, + task.srcRoot, + task.inputFiles, + task.executable, + task.compilerFlags, + task.objDir) + } + for ((target, tasks) in compdbTasks) { + project.tasks.create("${target}${name}", MergeCompilationDatabases::class.java) { task -> + task.dependsOn(tasks) + task.inputFiles.addAll(tasks.map { it.outputFile }) + task.outputFile = File(File(project.buildDir, target), "compile_commands.json") + } + } +} diff --git a/kotlin-native/build-tools/src/main/kotlin/org/jetbrains/kotlin/CopyCommonSources.kt b/kotlin-native/build-tools/src/main/kotlin/org/jetbrains/kotlin/CopyCommonSources.kt new file mode 100644 index 00000000000..b6ca78c7926 --- /dev/null +++ b/kotlin-native/build-tools/src/main/kotlin/org/jetbrains/kotlin/CopyCommonSources.kt @@ -0,0 +1,79 @@ +package org.jetbrains.kotlin + +import org.gradle.api.DefaultTask +import org.gradle.api.file.ConfigurableFileCollection +import org.gradle.api.tasks.Input +import org.gradle.api.tasks.InputFiles +import org.gradle.api.tasks.OutputDirectory +import org.gradle.api.tasks.TaskAction +import java.io.File + +open class CopyCommonSources : DefaultTask() { + @Input + var zipSources: Boolean = false + + @InputFiles + var sourcePaths: ConfigurableFileCollection = project.files() + + @OutputDirectory + var outputDir: File = project.buildDir.resolve("sources") + + fun zipSources(needToZip: Boolean) { + zipSources = needToZip + } + + fun outputDir(path: Any) { + outputDir = project.file(path) + } + + fun sourcePaths(paths: Any) { + sourcePaths = project.files(paths) + } + + @TaskAction + fun copySources() { + if (zipSources) copyAndZip() else copyPlain() + } + + private fun copyPlain() { + for (sourcePath in sourcePaths) { + sourcePath.copyFilteredTo(outputDir) + } + } + + private fun copyAndZip() { + for (sourcePath in sourcePaths) { + val filePrefix = sourcePath.name.replace(Regex("-\\d+.*"), "") + val targetFileName = "$filePrefix-sources.zip" + + val tempDir = project.buildDir.resolve(name).resolve(filePrefix).also { + it.deleteRecursively() + it.mkdirs() + } + + sourcePath.copyFilteredTo(tempDir) + + project.ant.invokeMethod( + "zip", + mapOf( + "destfile" to outputDir.resolve(targetFileName).absolutePath, + "basedir" to tempDir.absolutePath + ) + ) + } + } + + private fun File.copyFilteredTo(destinationDir: File) { + val fileTree = if (isFile) project.zipTree(this) else project.fileTree(this) + + project.copy { + it.from(fileTree) + it.includeEmptyDirs = false + it.include("generated/**/*.kt") + it.include("kotlin/**/*.kt") + it.include("kotlin.test/*.kt") + it.into(destinationDir) + } + } +} + diff --git a/kotlin-native/build-tools/src/main/kotlin/org/jetbrains/kotlin/CopySamples.kt b/kotlin-native/build-tools/src/main/kotlin/org/jetbrains/kotlin/CopySamples.kt new file mode 100644 index 00000000000..796b955e77d --- /dev/null +++ b/kotlin-native/build-tools/src/main/kotlin/org/jetbrains/kotlin/CopySamples.kt @@ -0,0 +1,55 @@ +package org.jetbrains.kotlin + +import groovy.lang.Closure +import org.gradle.api.Task +import org.gradle.api.tasks.Copy + +/** + * A task that copies samples and replaces direct repository URLs with ones provided by the cache-redirector service. + */ +open class CopySamples: Copy() { + + var samplesDir = project.file("samples") + + init { + configureReplacements() + } + + fun samplesDir(path: Any) { + samplesDir = project.file(path) + } + + private fun configureReplacements() { + from(samplesDir) { + it.exclude("**/*.gradle") + } + from(samplesDir) { + it.include("**/*.gradle") + it.filter { line -> + replacements.forEach { (repo, replacement) -> + if (line.contains(repo)) { + return@filter line.replace(repo, replacement) + } + } + return@filter line + } + } + } + + override fun configure(closure: Closure): Task { + super.configure(closure) + configureReplacements() + return this + } + + companion object { + val replacements = listOf( + "mavenCentral()" to "maven { url 'https://cache-redirector.jetbrains.com/maven-central' }", + "jcenter()" to "maven { url 'https://cache-redirector.jetbrains.com/jcenter' }", + "https://dl.bintray.com/kotlin/kotlin-dev" to "https://cache-redirector.jetbrains.com/dl.bintray.com/kotlin/kotlin-dev", + "https://dl.bintray.com/kotlin/kotlin-eap" to "https://cache-redirector.jetbrains.com/dl.bintray.com/kotlin/kotlin-eap", + "https://dl.bintray.com/kotlin/ktor" to "https://cache-redirector.jetbrains.com/dl.bintray.com/kotlin/ktor", + "https://plugins.gradle.org/m2" to "https://cache-redirector.jetbrains.com/plugins.gradle.org/m2" + ) + } +} diff --git a/kotlin-native/build-tools/src/main/kotlin/org/jetbrains/kotlin/CoverageTest.kt b/kotlin-native/build-tools/src/main/kotlin/org/jetbrains/kotlin/CoverageTest.kt new file mode 100644 index 00000000000..31ace23e381 --- /dev/null +++ b/kotlin-native/build-tools/src/main/kotlin/org/jetbrains/kotlin/CoverageTest.kt @@ -0,0 +1,138 @@ +/* + * Copyright 2010-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +package org.jetbrains.kotlin + +import groovy.lang.Closure +import org.gradle.api.DefaultTask +import org.gradle.api.Task +import org.gradle.api.tasks.Input +import org.gradle.api.tasks.TaskAction +import org.jetbrains.kotlin.konan.target.AppleConfigurables + +/** + * Test task for -Xcoverage and -Xlibraries-to-cover flags. Requires a binary to be built by the Konan plugin + * with + * konanArtifacts { + * program([binaryName], targets: [testTarget]) { + * ... + * extraOpts "-Xcoverage"/"-Xlibrary-to-cover=...", "-Xcoverage-file=$[profrawFile]" + * } + * } + * and a dependency set according to a pattern "run${binaryName}". + * + * @property numberOfCoveredFunctions Expected number of covered functions + * @property numberOfCoveredLines Expected number of covered lines in all functions + * @property binaryName Name of the produced binary + */ +open class CoverageTest : DefaultTask() { + + private val target = project.testTarget + private val platform = project.platformManager.platform(target) + private val configurables = platform.configurables + + // Use the same LLVM version as compiler when producing machine code: + private val llvmToolsDir = if (configurables is AppleConfigurables) { + "${configurables.absoluteTargetToolchain}/usr/bin" + } else { + "${configurables.absoluteLlvmHome}/bin" + } + + @Input + lateinit var binaryName: String + + // TODO: Consider better metric. + @Input + var numberOfCoveredFunctions: Int? = null + @Input + var numberOfCoveredLines: Int? = null + + val profrawFile: String by lazy { + "${project.buildDir.absolutePath}/$binaryName.profraw" + } + + private val profdataFile: String by lazy { + "${project.buildDir.absolutePath}/$binaryName.profdata" + } + + private val outputDir: String by lazy { + project.file(project.property("testOutputCoverage")!!).absolutePath + } + + override fun configure(closure: Closure): Task { + super.configure(closure) + dependsOnDist() + dependsOn(project.tasks.getByName("compileKonan$binaryName")) + return this + } + + @TaskAction + fun run() { + val suffix = target.family.exeSuffix + val pathToBinary = "$outputDir/$binaryName/$target/$binaryName.$suffix" + runProcess({ project.executor.execute(it) }, pathToBinary) + .ensureSuccessful(pathToBinary) + exec("llvm-profdata", "merge", profrawFile, "-o", profdataFile) + val llvmCovResult = exec("llvm-cov", "export", pathToBinary, "-instr-profile", profdataFile) + val jsonReport = llvmCovResult.stdOut + val llvmCovReport = parseLlvmCovReport(jsonReport) + try { + CoverageValidator(numberOfCoveredFunctions, numberOfCoveredLines).validateReport(llvmCovReport) + } catch (e: TestFailedException) { + // Show report in message to make debug easier. + val show = exec("llvm-cov", "show", pathToBinary, "-instr-profile", profdataFile).stdOut + // llvm-cov output contains '|' so another symbol is used as margin prefix. + throw TestFailedException(""" + >${e.message} + >$show + """.trimMargin(">")) + } + } + + private fun exec(llvmTool: String, vararg args: String): ProcessOutput { + val executable = "$llvmToolsDir/$llvmTool" + val result = runProcess(localExecutor(project), executable, args.toList()) + result.ensureSuccessful(llvmTool) + return result + } + + private fun ProcessOutput.ensureSuccessful(executable: String) { + if (exitCode != 0) { + println(""" + $executable failed. + exitCode: $exitCode + stdout: + $stdOut + stderr: + $stdErr + """.trimIndent()) + error("$executable failed") + } + } +} + +private class CoverageValidator( + val numberOfCoveredFunctions: Int?, + val numberOfCoveredLines: Int? +) { + fun validateReport(report: LlvmCovReport) { + val data = report.data + if (data.isEmpty()) { + failTest("Report data should not be empty!") + } + compareNumbers(numberOfCoveredFunctions, data[0].totals.functions.covered, "Number of covered functions") + compareNumbers(numberOfCoveredLines, data[0].totals.lines.covered, "Number of covered lines") + } + + private fun compareNumbers(expected: Int?, actual: Int, description: String) { + if (expected != null && actual != expected) { + failTest("$description differs from expected! Expected: $expected. Got: $actual") + } + } + + private fun failTest(message: String) { + throw TestFailedException(message) + } +} \ No newline at end of file diff --git a/kotlin-native/build-tools/src/main/kotlin/org/jetbrains/kotlin/EndorsedLibraryInfo.kt b/kotlin-native/build-tools/src/main/kotlin/org/jetbrains/kotlin/EndorsedLibraryInfo.kt new file mode 100644 index 00000000000..890a3704263 --- /dev/null +++ b/kotlin-native/build-tools/src/main/kotlin/org/jetbrains/kotlin/EndorsedLibraryInfo.kt @@ -0,0 +1,13 @@ +package org.jetbrains.kotlin + +import org.gradle.api.Project + +data class EndorsedLibraryInfo(val project: Project, val name: String) { + + val projectName: String + get() = project.name + + val taskName: String by lazy { + projectName.split('.').joinToString(separator = "") { it.capitalize() } + } +} \ No newline at end of file diff --git a/kotlin-native/build-tools/src/main/kotlin/org/jetbrains/kotlin/ExecClang.kt b/kotlin-native/build-tools/src/main/kotlin/org/jetbrains/kotlin/ExecClang.kt new file mode 100644 index 00000000000..5b587b77f69 --- /dev/null +++ b/kotlin-native/build-tools/src/main/kotlin/org/jetbrains/kotlin/ExecClang.kt @@ -0,0 +1,107 @@ +/* + * Copyright 2010-2017 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.jetbrains.kotlin + +import org.gradle.api.Action +import groovy.lang.Closure +import org.gradle.api.GradleException +import org.gradle.api.Project +import org.gradle.process.ExecResult +import org.gradle.process.ExecSpec +import org.gradle.util.ConfigureUtil +import org.jetbrains.kotlin.konan.target.* +import org.jetbrains.kotlin.konan.file.* + +class ExecClang(private val project: Project) { + + private val platformManager = project.rootProject.findProperty("platformManager") as PlatformManager + + private fun konanArgs(target: KonanTarget): List { + return platformManager.platform(target).clang.clangArgsForKonanSources.asList() + } + + fun konanArgs(targetName: String?): List { + val target = platformManager.targetManager(targetName).target + return konanArgs(target) + } + + fun resolveExecutable(executable: String?): String { + val executable = executable ?: "clang" + + if (listOf("clang", "clang++").contains(executable)) { + val llvmDir = project.findProperty("llvmDir") + return "${llvmDir}/bin/$executable" + } else { + throw GradleException("unsupported clang executable: $executable") + } + } + + // The bare ones invoke clang with system default sysroot. + + fun execBareClang(action: Action): ExecResult { + return this.execClang(emptyList(), action) + } + + fun execBareClang(closure: Closure): ExecResult { + return this.execClang(emptyList(), closure) + } + + // The konan ones invoke clang with konan provided sysroots. + // So they require a target or assume it to be the host. + // The target can be specified as KonanTarget or as a + // (nullable, which means host) target name. + + fun execKonanClang(target: String?, action: Action): ExecResult { + return this.execClang(konanArgs(target), action) + } + + fun execKonanClang(target: KonanTarget, action: Action): ExecResult { + return this.execClang(konanArgs(target), action) + } + + fun execKonanClang(target: String?, closure: Closure): ExecResult { + return this.execClang(konanArgs(target), closure) + } + + fun execKonanClang(target: KonanTarget, closure: Closure): ExecResult { + return this.execClang(konanArgs(target), closure) + } + + // These ones are private, so one has to choose either Bare or Konan. + + private fun execClang(defaultArgs: List, closure: Closure): ExecResult { + return this.execClang(defaultArgs, ConfigureUtil.configureUsing(closure)) + } + + private fun execClang(defaultArgs: List, action: Action): ExecResult { + val extendedAction = object : Action { + override fun execute(execSpec: ExecSpec) { + action.execute(execSpec) + + execSpec.apply { + executable = resolveExecutable(executable) + + val hostPlatform = project.findProperty("hostPlatform") as Platform + environment["PATH"] = project.files(hostPlatform.clang.clangPaths).asPath + + java.io.File.pathSeparator + environment["PATH"] + args(defaultArgs) + } + } + } + return project.exec(extendedAction) + } +} diff --git a/kotlin-native/build-tools/src/main/kotlin/org/jetbrains/kotlin/ExecLlvm.kt b/kotlin-native/build-tools/src/main/kotlin/org/jetbrains/kotlin/ExecLlvm.kt new file mode 100644 index 00000000000..e69de29bb2d diff --git a/kotlin-native/build-tools/src/main/kotlin/org/jetbrains/kotlin/ExecutorService.kt b/kotlin-native/build-tools/src/main/kotlin/org/jetbrains/kotlin/ExecutorService.kt new file mode 100644 index 00000000000..b2e7fe01e89 --- /dev/null +++ b/kotlin-native/build-tools/src/main/kotlin/org/jetbrains/kotlin/ExecutorService.kt @@ -0,0 +1,571 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.jetbrains.kotlin + +import com.google.gson.annotations.Expose +import groovy.lang.Closure +import org.gradle.api.Action +import org.gradle.api.Project +import org.gradle.process.ExecResult +import org.gradle.process.ExecSpec +import org.gradle.util.ConfigureUtil +import org.jetbrains.kotlin.konan.target.Architecture + +import org.jetbrains.kotlin.konan.target.KonanTarget +import org.jetbrains.kotlin.konan.target.Xcode +import java.io.* + +import java.nio.file.Path +import java.nio.file.Paths +import java.time.LocalDateTime +import java.time.format.DateTimeFormatter +import java.util.concurrent.TimeUnit + +/** + * A replacement of the standard `exec {}` + * @see org.gradle.api.Project.exec + */ +interface ExecutorService { + fun execute(closure: Closure): ExecResult? = execute(ConfigureUtil.configureUsing(closure)) + fun execute(action: Action): ExecResult? +} + +/** + * Creates an ExecutorService depending on a test target -Ptest_target + */ +fun create(project: Project): ExecutorService { + val platformManager = project.platformManager + val testTarget = project.testTarget + val platform = platformManager.platform(testTarget) + val absoluteTargetToolchain = platform.absoluteTargetToolchain + val absoluteTargetSysRoot = platform.absoluteTargetSysRoot + + return when (testTarget) { + KonanTarget.WASM32 -> object : ExecutorService { + override fun execute(action: Action): ExecResult? = project.exec { execSpec -> + action.execute(execSpec) + with(execSpec) { + val exe = executable + val d8 = "$absoluteTargetToolchain/bin/d8" + val launcherJs = "$executable.js" + executable = d8 + args = listOf("--expose-wasm", launcherJs, "--", exe) + args + } + } + } + + KonanTarget.LINUX_MIPS32, KonanTarget.LINUX_MIPSEL32 -> object : ExecutorService { + override fun execute(action: Action): ExecResult? = project.exec { execSpec -> + action.execute(execSpec) + with(execSpec) { + val qemu = if (platform.target === KonanTarget.LINUX_MIPS32) "qemu-mips" else "qemu-mipsel" + val absoluteQemu = "$absoluteTargetToolchain/bin/$qemu" + val exe = executable + executable = absoluteQemu + args = listOf("-L", absoluteTargetSysRoot, + // This is to workaround an endianess issue. + // See https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=731082 for details. + "$absoluteTargetSysRoot/lib/ld.so.1", "--inhibit-cache", + exe) + args + } + } + } + + KonanTarget.IOS_X64, + KonanTarget.TVOS_X64, + KonanTarget.WATCHOS_X86, + KonanTarget.WATCHOS_X64 -> simulator(project) + + KonanTarget.IOS_ARM32, + KonanTarget.IOS_ARM64 -> deviceLauncher(project) + + else -> { + if (project.hasProperty("remote")) sshExecutor(project) + else localExecutorService(project) + } + } +} + +data class ProcessOutput(var stdOut: String, var stdErr: String, var exitCode: Int) + +/** + * Runs process using a given executor. + * + * @param executor a method that is able to run a given executable, e.g. ExecutorService::execute + * @param executable a process executable to be run + * @param args arguments for a process + */ +fun runProcess(executor: (Action) -> ExecResult?, + executable: String, args: List): ProcessOutput { + val outStream = ByteArrayOutputStream() + val errStream = ByteArrayOutputStream() + + val execResult = executor(Action { + it.executable = executable + it.args = args.toList() + it.standardOutput = outStream + it.errorOutput = errStream + it.isIgnoreExitValue = true + }) + + checkNotNull(execResult) + + val stdOut = outStream.toString("UTF-8") + val stdErr = errStream.toString("UTF-8") + + return ProcessOutput(stdOut, stdErr, execResult.exitValue) +} + +fun runProcess(executor: (Action) -> ExecResult?, + executable: String, vararg args: String) = runProcess(executor, executable, args.toList()) + +/** + * Runs process using a given executor. + * + * @param executor a method that is able to run a given executable, e.g. ExecutorService::execute + * @param executable a process executable to be run + * @param args arguments for a process + * @param input an input string to be passed through the standard input stream + */ +fun runProcessWithInput(executor: (Action) -> ExecResult?, + executable: String, args: List, input: String): ProcessOutput { + val outStream = ByteArrayOutputStream() + val errStream = ByteArrayOutputStream() + val inStream = ByteArrayInputStream(input.toByteArray()) + + val execResult = executor(Action { + it.executable = executable + it.args = args.toList() + it.standardOutput = outStream + it.errorOutput = errStream + it.isIgnoreExitValue = true + it.standardInput = inStream + }) + + checkNotNull(execResult) + + val stdOut = outStream.toString("UTF-8") + val stdErr = errStream.toString("UTF-8") + + return ProcessOutput(stdOut, stdErr, execResult.exitValue) +} + +/** + * The [ExecutorService] being set in the given project. + * @throws IllegalStateException if there are no executor in the project. + */ +val Project.executor: ExecutorService + get() = this.convention.plugins["executor"] as? ExecutorService + ?: throw IllegalStateException("Executor wasn't found") + +/** + * Creates a new executor service with additional action [actionParameter] executed after the main one. + * The following is an example how to pass an environment parameter + * @code `executor.add(Action { it.environment = mapOf("JAVA_OPTS" to "-verbose:gc") })::execute` + */ +fun ExecutorService.add(actionParameter: Action) = object : ExecutorService { + override fun execute(action: Action): ExecResult? = + this@add.execute(Action { + action.execute(it) + actionParameter.execute(it) + }) +} + +/** + * Executes the [executable] with the given [arguments] + * and checks that the program finished with zero exit code. + */ +fun Project.executeAndCheck(executable: Path, arguments: List = emptyList()) { + val (stdOut, stdErr, exitCode) = runProcess( + executor = executor::execute, + executable = executable.toString(), + args = arguments + ) + + println(""" + |stdout: $stdOut + |stderr: $stdErr + """.trimMargin()) + check(exitCode == 0) { "Execution failed with exit code: $exitCode" } +} + +/** + * Returns [project]'s process executor. + * @see Project.exec + */ +fun localExecutor(project: Project) = { a: Action -> project.exec(a) } + +fun localExecutorService(project: Project): ExecutorService = object : ExecutorService { + override fun execute(action: Action): ExecResult? = project.exec(action) +} + +/** + * Executes a given action with iPhone Simulator. + * + * The test target should be specified with -Ptest_target=ios_x64 + * @see KonanTarget.IOS_X64 + * @param iosDevice an optional project property used to control simulator's device type + * Specify -PiosDevice=iPhone X to set it + */ +private fun simulator(project: Project): ExecutorService = object : ExecutorService { + + private val target = project.testTarget + + private val simctl by lazy { + val sdk = when (target) { + KonanTarget.TVOS_X64 -> Xcode.current.appletvsimulatorSdk + KonanTarget.IOS_X64 -> Xcode.current.iphonesimulatorSdk + KonanTarget.WATCHOS_X64, + KonanTarget.WATCHOS_X86 -> Xcode.current.watchsimulatorSdk + else -> error("Unexpected simulation target: $target") + } + val out = ByteArrayOutputStream() + val result = project.exec { + it.commandLine("/usr/bin/xcrun", "--find", "simctl", "--sdk", sdk) + it.standardOutput = out + } + result.assertNormalExitValue() + out.toString("UTF-8").trim() + } + + private val device = project.findProperty("iosDevice")?.toString() ?: when (target) { + KonanTarget.TVOS_X64 -> "Apple TV 4K" + KonanTarget.IOS_X64 -> "iPhone 8" + KonanTarget.WATCHOS_X64, + KonanTarget.WATCHOS_X86 -> "Apple Watch Series 4 - 40mm" + else -> error("Unexpected simulation target: $target") + } + + private val archSpecification = when (target.architecture) { + Architecture.X86 -> listOf("-a", "i386") + Architecture.X64 -> listOf() // x86-64 is used by default. + else -> error("${target.architecture} can't be used in simulator.") + }.toTypedArray() + + override fun execute(action: Action): ExecResult? = project.exec { execSpec -> + action.execute(execSpec) + // Starting Xcode 11 `simctl spawn` requires explicit `--standalone` flag. + with(execSpec) { commandLine = listOf(simctl, "spawn", "--standalone", *archSpecification, device, executable) + args } + } +} + +/** + * Remote process executor. + * + * @param remote makes binaries be executed on a remote host + * Specify it as -Premote=user@host + */ +private fun sshExecutor(project: Project): ExecutorService = object : ExecutorService { + + private val remote: String = project.property("remote").toString() + private val sshArgs: List = System.getenv("SSH_ARGS")?.split(" ") ?: emptyList() + private val sshHome = System.getenv("SSH_HOME") ?: "/usr/bin" + + // Unique remote dir name to be used in the target host + private val remoteDir = run { + val date = LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyyMMddHHmmss")) + Paths.get(project.findProperty("remoteRoot").toString(), "tmp", + System.getProperty("user.name") + "_" + date).toString() + } + + override fun execute(action: Action): ExecResult { + var execFile: String? = null + + createRemoteDir() + val execResult = project.exec { execSpec -> + action.execute(execSpec) + with(execSpec) { + upload(executable) + executable = "$remoteDir/${File(executable).name}" + execFile = executable + commandLine = arrayListOf("$sshHome/ssh") + sshArgs + remote + commandLine + } + } + cleanup(execFile!!) + return execResult + } + + private fun createRemoteDir() { + project.exec { + it.commandLine = arrayListOf("$sshHome/ssh") + sshArgs + remote + "mkdir" + "-p" + remoteDir + } + } + + private fun upload(fileName: String) { + project.exec { + it.commandLine = arrayListOf("$sshHome/scp") + sshArgs + fileName + "$remote:$remoteDir" + } + } + + private fun cleanup(fileName: String) { + project.exec { + it.commandLine = arrayListOf("$sshHome/ssh") + sshArgs + remote + "rm" + fileName + } + } +} + +internal data class DeviceTarget( + @Expose val name: String, + @Expose val udid: String, + @Expose val state: String, + @Expose val type: String +) + +private fun deviceLauncher(project: Project) = object : ExecutorService { + private val xcProject = Paths.get(project.testOutputRoot, "launcher") + + private val idb = project.findProperty("idb_path") as? String ?: "idb" + + private val deviceName = project.findProperty("device_name") as? String + + override fun execute(action: Action): ExecResult? { + var result: ExecResult? = null + try { + val udid = targetUDID() + println("Found device UDID: $udid") + install(udid, xcProject.resolve("build/KonanTestLauncher.ipa").toString()) + val bundleId = "org.jetbrains.kotlin.KonanTestLauncher" + val commands = startDebugServer(udid, bundleId) + .split("\n") + .filter { it.isNotBlank() } + .flatMap { listOf("-o", it) } + + var savedOut: OutputStream? = null + val out = ByteArrayOutputStream() + result = project.exec { execSpec: ExecSpec -> + action.execute(execSpec) + execSpec.executable = "lldb" + execSpec.args = commands + "-b" + "-o" + "command script import ${pythonScript()}" + + "-o" + ("process launch" + + (execSpec.args.takeUnless { it.isEmpty() } + ?.let { " -- ${it.joinToString(" ")}" } + ?: "")) + + "-o" + "get_exit_code" + + "-k" + "get_exit_code" + + "-k" + "exit -1" + // A test task that uses project.exec { } sets the stdOut to parse the result, + // but the test executable is being run under debugger that has its own output mixed with the + // output from the test. Save the stdOut from the test to write the parsed output to it. + savedOut = execSpec.standardOutput + execSpec.standardOutput = out + } + out.toString() + .also { if (project.verboseTest) println(it) } + .split("\n") + .dropWhile { s -> !s.startsWith("(lldb) process launch") } + .drop(1) // drop 'process launch' also + .dropLastWhile { !it.matches(".*Process [0-9]* exited with status .*".toRegex()) } + .joinToString("\n") { + it.replace("Process [0-9]* exited with status .*".toRegex(), "") + .replace("\r", "") // TODO: investigate: where does the \r comes from + } + .also { + savedOut?.write(it.toByteArray()) + } + + uninstall(udid, bundleId) + } catch (exc: Exception) { + throw RuntimeException("iOS-device execution failed", exc) + } finally { + kill() + } + return result + } + + /* + * This script kills the target process in case it has been stopped, + * and exists lldb with the same exit code as a target process. + */ + private fun pythonScript(): String = xcProject.resolve("lldb_cmd.py").toFile().run { + writeText( // language=Python + """ + import lldb + + def exit_code(debugger, command, exe_ctx, result, internal_dict): + process = exe_ctx.GetProcess() + state = process.GetState() + if state == lldb.eStateStopped: + # Call flush method, otherwise some output isn't shown in the debugger + debugger.HandleCommand("expression -- (int) fflush(NULL)") + debugger.HandleCommand("bt all") + process.Kill() + code = process.GetExitStatus() + debugger.HandleCommand("exit %d" % code) + + def __lldb_init_module(debugger, _): + debugger.HandleCommand('command script add -f lldb_cmd.exit_code get_exit_code') + """.trimIndent()) + absolutePath + } + + private fun kill() = project.exec { it.commandLine(idb, "kill") } + + private inline fun tryUntilTrue(times: Int = 3, f: () -> Boolean) { + for (i in 1..times) { + if (f()) break + else TimeUnit.SECONDS.sleep(i.toLong()) + } + } + + private fun targetUDID(): String { + val out = ByteArrayOutputStream() + // idb launches idb_companion but doesn't wait for it and just exits. + // So relaunch `list-targets` again. + tryUntilTrue { + project.exec { + it.commandLine(idb, "list-targets", "--json") + it.standardOutput = out + }.assertNormalExitValue() + out.toString().trim().isNotEmpty() + } + return out.toString().run { + check(isNotEmpty()) + split("\n") + .filter { it.isNotEmpty() } + .map { + gson.fromJson(it, DeviceTarget::class.java) + } + .first { + it.type == "device" && deviceName?.run { this == it.name } ?: true + } + .udid + } + } + + private fun install(udid: String, bundlePath: String) { + val out = ByteArrayOutputStream() + lateinit var result: ExecResult + tryUntilTrue { + result = project.exec { + it.workingDir = xcProject.toFile() + it.commandLine = listOf(idb, "install", "--udid", udid, bundlePath) + it.standardOutput = out + it.errorOutput = out + it.isIgnoreExitValue = true + } + println(out.toString()) + result.exitValue == 0 + } + check(result.exitValue == 0) { "Installation of $bundlePath failed: $out" } + } + + private fun uninstall(udid: String, bundleId: String) { + val out = ByteArrayOutputStream() + + project.exec { + it.workingDir = xcProject.toFile() + it.commandLine = listOf(idb, "uninstall", "--udid", udid, bundleId) + it.standardOutput = out + it.errorOutput = out + it.isIgnoreExitValue = true + } + println(out.toString()) + } + + private fun startDebugServer(udid: String, bundleId: String): String { + val out = ByteArrayOutputStream() + + val result = project.exec { + it.workingDir = xcProject.toFile() + it.commandLine = listOf(idb, "debugserver", "start", "--udid", udid, bundleId) + it.standardOutput = out + it.errorOutput = out + it.isIgnoreExitValue = true + } + check(result.exitValue == 0) { "Failed to start debug server: $out" } + return out.toString() + } +} + +fun KonanTestExecutable.configureXcodeBuild() { + this.doBeforeRun = Action { + val signIdentity = project.findProperty("sign_identity") as? String ?: "iPhone Developer" + val developmentTeam = project.findProperty("development_team") as? String + requireNotNull(developmentTeam) { "Specify '-Pdevelopment_team=' with the your team id" } + val xcProject = Paths.get(project.testOutputRoot, "launcher") + + val shellScript: String = // language=Bash + mutableListOf(""" + set -x + # Copy executable to the build dir. + COPY_TO="${"$"}TARGET_BUILD_DIR/${"$"}EXECUTABLE_PATH" + cp "${project.file(executable).absolutePath}" "${"$"}COPY_TO" + # copy dSYM if it exists + DSYM_DIR="${project.file("$executable.dSYM").absolutePath}" + if [ -d "${"$"}DSYM_DIR" ]; then + cp -r "${"$"}DSYM_DIR" "${"$"}TARGET_BUILD_DIR/${"$"}EXECUTABLE_FOLDER_PATH/" + fi + """.trimIndent()).also { + if (this is FrameworkTest) { + // Create a Frameworks folder inside the build dir. + it += "mkdir -p \"\$TARGET_BUILD_DIR/\$FRAMEWORKS_FOLDER_PATH\"" + // Copy each framework to the Frameworks dir. + it += frameworks.filter { framework -> !framework.isStatic } + .map { framework -> + val artifact = framework.artifact + "cp -r \"$testOutput/${this.name}/${project.testTarget.name}/$artifact.framework\" " + + "\"\$TARGET_BUILD_DIR/\$FRAMEWORKS_FOLDER_PATH/$artifact.framework\"" + } + } + }.joinToString(separator = "\\n") { it.replace("\"", "\\\"") } + + // Copy template xcode project. + project.file("iosLauncher").copyRecursively(xcProject.toFile(), overwrite = true) + + xcProject.resolve("KonanTestLauncher.xcodeproj/project.pbxproj") + .toFile() + .apply { + val text = readLines().joinToString("\n") { + when { + it.contains("CODE_SIGN_IDENTITY") -> + it.replaceAfter("= ", "\"$signIdentity\";") + it.contains("DEVELOPMENT_TEAM") || it.contains("DevelopmentTeam") -> + it.replaceAfter("= ", "$developmentTeam;") + it.contains("shellScript = ") -> + it.replaceAfter("= ", "\"$shellScript\";") + else -> it + } + } + writeText(text) + } + + val sdk = when (project.testTarget) { + KonanTarget.IOS_ARM32, KonanTarget.IOS_ARM64 -> Xcode.current.iphoneosSdk + else -> error("Unsupported target: ${project.testTarget}") + } + + fun xcodebuild(vararg elements: String) { + val xcode = listOf("/usr/bin/xcrun", "-sdk", sdk, "xcodebuild") + val out = ByteArrayOutputStream() + val result = project.exec { + it.workingDir = xcProject.toFile() + it.commandLine = xcode + elements.toList() + it.standardOutput = out + } + println(out.toString("UTF-8")) + result.assertNormalExitValue() + } + xcodebuild("-workspace", "KonanTestLauncher.xcodeproj/project.xcworkspace", + "-scheme", "KonanTestLauncher", "-allowProvisioningUpdates", "-destination", + "generic/platform=iOS", "build") + val archive = xcProject.resolve("build/KonanTestLauncher.xcarchive").toString() + xcodebuild("-workspace", "KonanTestLauncher.xcodeproj/project.xcworkspace", + "-scheme", "KonanTestLauncher", "archive", "-archivePath", archive) + xcodebuild("-exportArchive", "-archivePath", archive, "-exportOptionsPlist", "KonanTestLauncher/Info.plist", + "-exportPath", xcProject.resolve("build").toString()) + } +} diff --git a/kotlin-native/build-tools/src/main/kotlin/org/jetbrains/kotlin/ExternalReportUtils.kt b/kotlin-native/build-tools/src/main/kotlin/org/jetbrains/kotlin/ExternalReportUtils.kt new file mode 100644 index 00000000000..8fe4a5669d1 --- /dev/null +++ b/kotlin-native/build-tools/src/main/kotlin/org/jetbrains/kotlin/ExternalReportUtils.kt @@ -0,0 +1,26 @@ +package org.jetbrains.kotlin + + +import com.google.gson.annotations.* +import com.google.gson.* +import com.google.gson.stream.JsonReader +import java.io.File +import java.io.FileReader +import java.io.PrintWriter + + +data class ExternalTestReport(@Expose val statistics: Statistics, @Expose val groups: List) + +fun saveReport(reportFileName: String, statistics: Statistics, groups:List){ + File(reportFileName).apply { + parentFile.mkdirs() + PrintWriter(this).use { + it.append(gson.toJson(ExternalTestReport(statistics, groups))) + } + } +} + +internal val gson = GsonBuilder().excludeFieldsWithoutExposeAnnotation().create()!! +fun loadReport(reportFileName: String) : ExternalTestReport = JsonReader(FileReader(reportFileName)).use { + gson.fromJson(it, ExternalTestReport::class.java) +} diff --git a/kotlin-native/build-tools/src/main/kotlin/org/jetbrains/kotlin/FrameworkTest.kt b/kotlin-native/build-tools/src/main/kotlin/org/jetbrains/kotlin/FrameworkTest.kt new file mode 100644 index 00000000000..088f071b4ae --- /dev/null +++ b/kotlin-native/build-tools/src/main/kotlin/org/jetbrains/kotlin/FrameworkTest.kt @@ -0,0 +1,270 @@ +package org.jetbrains.kotlin + +import groovy.lang.Closure +import org.gradle.api.Action +import org.gradle.api.DefaultTask +import org.gradle.api.Task +import org.gradle.api.file.FileTree +import org.gradle.api.tasks.Input +import org.gradle.api.tasks.Optional +import org.gradle.api.tasks.TaskAction +import org.gradle.language.base.plugins.LifecycleBasePlugin + +import org.jetbrains.kotlin.konan.target.* +import java.io.File + +import java.io.FileWriter +import java.nio.file.Files +import java.nio.file.Path +import java.nio.file.Paths + +/** + * Test task for -produce framework testing. Requires a framework to be built by the Konan plugin + * with konanArtifacts { framework(frameworkName, targets: [ testTarget] ) } and a dependency set + * according to a pattern "compileKonan${frameworkName}". + * + * @property swiftSources Swift-language test sources that use a given framework + * @property frameworks names of frameworks + */ +open class FrameworkTest : DefaultTask(), KonanTestExecutable { + @Input + lateinit var swiftSources: List + + @Input + lateinit var frameworks: MutableList + + @Input + var fullBitcode: Boolean = false + + @Input + var codesign: Boolean = true + + val testOutput: String = project.testOutputFramework + + @Input @Optional + var expectedExitStatus: Int? = null + + /** + * Framework description. + * + * @param name is the framework name, + * @param sources framework sources, + * @param bitcode bitcode embedding in the framework, + * @param isStatic determines that framework is static + * @param artifact the name of the resulting artifact, + * @param library library dependency name, + * @param opts additional options for the compiler. + */ + class Framework( + val name: String, + var sources: List = emptyList(), + var bitcode: Boolean = false, + var isStatic: Boolean = false, + var artifact: String = name, + var library: String? = null, + var opts: List = emptyList() + ) + + /** + * Used for the framework configuration in the task's closure. + */ + fun framework(name: String, closure: Closure): Framework { + val f = Framework(name).apply { + closure.delegate = this + closure.resolveStrategy = Closure.DELEGATE_FIRST + closure.call() + // map to file paths + sources = sources.toFiles(Language.Kotlin).map { it.path } + } + if (!::frameworks.isInitialized) { + frameworks = mutableListOf(f) + } else { + frameworks.add(f) + } + return f + } + + enum class Language(val extension: String) { + Kotlin(".kt"), ObjC(".m"), Swift(".swift") + } + + fun Language.filesFrom(dir: String): FileTree = project.fileTree(dir) { + // include only files with the language extension + it.include("*${this.extension}") + } + + fun List.toFiles(language: Language): List = + this.map { language.filesFrom(it) } + .flatMap { it.files } + + override val executable: String + get() = Paths.get(testOutput, name, "swiftTestExecutable").toString() + + override var doBeforeRun: Action? = null + + override var doBeforeBuild: Action? = null + + override val buildTasks: List + get() = frameworks.map { project.tasks.getByName("compileKonan${it.name}") } + + @Suppress("UnstableApiUsage") + override fun configure(config: Closure<*>): Task { + super.configure(config) + // set crossdist build dependency if custom konan.home wasn't set + this.dependsOnDist() + + // Set Gradle properties for the better navigation + group = LifecycleBasePlugin.VERIFICATION_GROUP + description = "Kotlin/Native test infrastructure task" + + check(::frameworks.isInitialized) { "Frameworks should be set" } + return this + } + + private fun buildTestExecutable() { + val frameworkParentDirPath = "$testOutput/$name/${project.testTarget.name}" + frameworks.forEach { framework -> + val frameworkArtifact = framework.artifact + val frameworkPath = "$frameworkParentDirPath/$frameworkArtifact.framework" + val frameworkBinaryPath = "$frameworkPath/$frameworkArtifact" + validateBitcodeEmbedding(frameworkBinaryPath) + if (codesign) codesign(project, frameworkPath) + } + + // create a test provider and get main entry point + val provider = Paths.get(testOutput, name, "provider.swift") + FileWriter(provider.toFile()).use { writer -> + val providers = swiftSources.toFiles(Language.Swift) + .map { it.name.toString().removeSuffix(".swift").capitalize() } + .map { "${it}Tests" } + + writer.write(""" + |// THIS IS AUTOGENERATED FILE + |// This method is invoked by the main routine to get a list of tests + |func registerProviders() { + | ${providers.joinToString("\n ") { "$it()" }} + |} + """.trimMargin()) + } + val testHome = project.file("framework").toPath() + val swiftMain = Paths.get(testHome.toString(), "main.swift").toString() + + // Compile swift sources + val sources = swiftSources.toFiles(Language.Swift) + .map { it.path } + listOf(provider.toString(), swiftMain) + val options = listOf( + "-g", + "-Xlinker", "-rpath", "-Xlinker", "@executable_path/Frameworks", + "-Xlinker", "-rpath", "-Xlinker", frameworkParentDirPath, + "-F", frameworkParentDirPath, + "-Xcc", "-Werror" // To fail compilation on warnings in framework header. + ) + compileSwift(project, project.testTarget, sources, options, Paths.get(executable), fullBitcode) + } + + @TaskAction + fun run() { + // Build test executable as a first action of the task before executing the test + buildTestExecutable() + doBeforeRun?.execute(this) + runTest(executorService = project.executor, testExecutable = Paths.get(executable)) + } + + /** + * Returns path to directory that contains `libswiftCore.dylib` for the current + * test target. + */ + private fun getSwiftLibsPathForTestTarget(): String { + val target = project.testTarget + val platform = project.platformManager.platform(target) + val configs = platform.configurables as AppleConfigurables + val swiftPlatform = when (target) { + KonanTarget.IOS_X64 -> "iphonesimulator" + KonanTarget.IOS_ARM32, KonanTarget.IOS_ARM64 -> "iphoneos" + KonanTarget.TVOS_X64 -> "appletvsimulator" + KonanTarget.TVOS_ARM64 -> "appletvos" + KonanTarget.MACOS_X64 -> "macosx" + KonanTarget.WATCHOS_ARM64 -> "watchos" + KonanTarget.WATCHOS_X64, KonanTarget.WATCHOS_X86 -> "watchsimulator" + else -> throw IllegalStateException("Test target $target is not supported") + } + val simulatorPath = when (target) { + KonanTarget.TVOS_X64, + KonanTarget.IOS_X64, + KonanTarget.WATCHOS_X86, + KonanTarget.WATCHOS_X64 -> Xcode.current.getLatestSimulatorRuntimeFor(target, configs.osVersionMin)?.bundlePath?.let { + "$it/Contents/Resources/RuntimeRoot/usr/lib/swift" + } + else -> null + } + // Use default path from toolchain if we cannot get `bundlePath` for target. + // It may be the case for simulators if Xcode/macOS is old. + return simulatorPath ?: configs.absoluteTargetToolchain + "/usr/lib/swift-5.0/$swiftPlatform" + } + + private fun buildEnvironment(): Map { + val target = project.testTarget + // Hopefully, lexicographical comparison will work. + val newMacos = System.getProperty("os.version").compareTo("10.14.4") >= 0 + val dyldLibraryPathKey = when (target) { + KonanTarget.IOS_X64, + KonanTarget.WATCHOS_X86, + KonanTarget.WATCHOS_X64, + KonanTarget.TVOS_X64 -> "SIMCTL_CHILD_DYLD_LIBRARY_PATH" + else -> "DYLD_LIBRARY_PATH" + } + return if (newMacos && target == KonanTarget.MACOS_X64) emptyMap() else mapOf( + dyldLibraryPathKey to getSwiftLibsPathForTestTarget() + ) + } + + private fun runTest(executorService: ExecutorService, testExecutable: Path, args: List = emptyList()) { + val (stdOut, stdErr, exitCode) = runProcess( + executor = { executorService.add(Action { + it.environment = buildEnvironment() + it.workingDir = Paths.get(testOutput).toFile() + }).execute(it) }, + executable = testExecutable.toString(), + args = args) + + val testExecName = testExecutable.fileName + println(""" + |$testExecName + |stdout: $stdOut + |stderr: $stdErr + """.trimMargin()) + check(exitCode == expectedExitStatus ?: 0) { "Execution of $testExecName failed with exit code: $exitCode " } + } + + private fun validateBitcodeEmbedding(frameworkBinary: String) { + // Check only the full bitcode embedding for now. + if (!fullBitcode) { + return + } + val testTarget = project.testTarget + val configurables = project.platformManager.platform(testTarget).configurables as AppleConfigurables + + val bitcodeBuildTool = "${configurables.absoluteAdditionalToolsDir}/bin/bitcode-build-tool" + val toolPath = "${configurables.absoluteTargetToolchain}/usr/bin/" + val sdk = when (testTarget) { + KonanTarget.IOS_X64, + KonanTarget.TVOS_X64, + KonanTarget.WATCHOS_X86, + KonanTarget.WATCHOS_X64 -> return // bitcode-build-tool doesn't support simulators. + KonanTarget.IOS_ARM64, + KonanTarget.IOS_ARM32 -> Xcode.current.iphoneosSdk + KonanTarget.MACOS_X64 -> Xcode.current.macosxSdk + KonanTarget.TVOS_ARM64 -> Xcode.current.appletvosSdk + KonanTarget.WATCHOS_ARM32, + KonanTarget.WATCHOS_ARM64 -> Xcode.current.watchosSdk + else -> error("Cannot validate bitcode for test target $testTarget") + } + + val python3 = listOf("/usr/bin/python3", "/usr/local/bin/python3") + .map { Paths.get(it) }.firstOrNull { Files.exists(it) } + ?: error("Can't find python3") + + runTest(executorService = localExecutorService(project), testExecutable = python3, + args = listOf("-B", bitcodeBuildTool, "--sdk", sdk, "-v", "-t", toolPath, frameworkBinary)) + } +} \ No newline at end of file diff --git a/kotlin-native/build-tools/src/main/kotlin/org/jetbrains/kotlin/Internals.kt b/kotlin-native/build-tools/src/main/kotlin/org/jetbrains/kotlin/Internals.kt new file mode 100644 index 00000000000..74dd8bcc52d --- /dev/null +++ b/kotlin-native/build-tools/src/main/kotlin/org/jetbrains/kotlin/Internals.kt @@ -0,0 +1,48 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the license/LICENSE.txt file. + */ + +package org.jetbrains.kotlin + +import org.gradle.api.NamedDomainObjectCollection +import org.gradle.api.NamedDomainObjectContainer +import org.gradle.api.Project +import org.gradle.api.file.FileCollection +import org.gradle.api.plugins.ExtraPropertiesExtension +import org.gradle.api.provider.Provider +import org.jetbrains.kotlin.gradle.dsl.KotlinMultiplatformExtension +import org.jetbrains.kotlin.gradle.plugin.KotlinCompilation +import org.jetbrains.kotlin.gradle.plugin.KotlinTargetPreset +import org.jetbrains.kotlin.gradle.plugin.mpp.KotlinNativeCompilation +import java.io.File + +/* + * This file includes internal short-cuts visible only inside of the 'buildSrc' module. + */ + +internal val hostOs by lazy { System.getProperty("os.name") } +internal val userHome by lazy { System.getProperty("user.home") } + +internal val Project.ext: ExtraPropertiesExtension + get() = extensions.getByName("ext") as ExtraPropertiesExtension + +internal val Project.kotlin: KotlinMultiplatformExtension + get() = extensions.getByName("kotlin") as KotlinMultiplatformExtension + +internal val NamedDomainObjectCollection>.macosX64: KotlinTargetPreset<*> + get() = getByName(::macosX64.name) as KotlinTargetPreset<*> + +internal val NamedDomainObjectCollection>.linuxX64: KotlinTargetPreset<*> + get() = getByName(::linuxX64.name) as KotlinTargetPreset<*> + +internal val NamedDomainObjectCollection>.mingwX64: KotlinTargetPreset<*> + get() = getByName(::mingwX64.name) as KotlinTargetPreset<*> + +internal val NamedDomainObjectContainer>.main: KotlinNativeCompilation + get() = getByName(::main.name) as KotlinNativeCompilation + +internal val FileCollection.isNotEmpty: Boolean + get() = !isEmpty + +internal fun Provider.resolve(child: String): Provider = map { it.resolve(child) } \ No newline at end of file diff --git a/kotlin-native/build-tools/src/main/kotlin/org/jetbrains/kotlin/KLibInstall.kt b/kotlin-native/build-tools/src/main/kotlin/org/jetbrains/kotlin/KLibInstall.kt new file mode 100644 index 00000000000..07bc51be939 --- /dev/null +++ b/kotlin-native/build-tools/src/main/kotlin/org/jetbrains/kotlin/KLibInstall.kt @@ -0,0 +1,47 @@ +package org.jetbrains.kotlin + +import groovy.lang.Closure +import org.gradle.api.Task +import org.gradle.api.tasks.Exec +import org.gradle.api.tasks.Input +import org.gradle.api.tasks.InputFile +import org.gradle.api.tasks.OutputDirectory +import org.jetbrains.kotlin.konan.target.KonanTarget +import org.jetbrains.kotlin.konan.target.HostManager +import java.io.File + +// TODO: Implement as a part of the gradle plugin +open class KlibInstall: Exec() { + @InputFile + lateinit var klib: File + var repo: File = project.rootDir + + val installDir: File + @OutputDirectory + get() { + val klibName = klib.name.take(klib.name.lastIndexOf('.')) + return project.file("${repo.absolutePath}/$klibName") + } + + @Input + var target: String = HostManager.hostName + + override fun configure(config: Closure<*>): Task { + val result = super.configure(config) + val konanHomePath = project.findProperty("org.jetbrains.kotlin.native.home") ?: "dist" + val konanHome = project.rootProject.file(konanHomePath) + val suffix = if (HostManager.host == KonanTarget.MINGW_X64) ".bat" else "" + val klibProgram = "$konanHome/bin/klib$suffix" + + doFirst { + repo.mkdirs() + + commandLine(klibProgram, + "install", klib.absolutePath, + "-target", target, + "-repository", repo.absolutePath + ) + } + return result + } +} \ No newline at end of file diff --git a/kotlin-native/build-tools/src/main/kotlin/org/jetbrains/kotlin/KonanTestExecutable.kt b/kotlin-native/build-tools/src/main/kotlin/org/jetbrains/kotlin/KonanTestExecutable.kt new file mode 100644 index 00000000000..32c7a518f8c --- /dev/null +++ b/kotlin-native/build-tools/src/main/kotlin/org/jetbrains/kotlin/KonanTestExecutable.kt @@ -0,0 +1,33 @@ +package org.jetbrains.kotlin + +import org.gradle.api.Action +import org.gradle.api.Task + +/** + * An interface that any test that works with ExecutorService + * should implement to be run on different platforms. + */ +interface KonanTestExecutable : Task { + /** + * Test executable to be run by the service. + */ + val executable: String + + /** + * Action that configures task or does some workload before the test will be executed. + * Could be done as a first step in the test or just as a `doFirst` action in the test task. + */ + var doBeforeRun: Action? + + /** + * Action that configures task or does some workload before the test will be built. + * Depending on the test task implementation this action is done before the build task + * or as its `doFirst` action. + */ + var doBeforeBuild: Action? + + /** + * Build tasks that this [executable] depends on, or is built from. + */ + val buildTasks: List +} \ No newline at end of file diff --git a/kotlin-native/build-tools/src/main/kotlin/org/jetbrains/kotlin/KonanTestSuiteReport.kt b/kotlin-native/build-tools/src/main/kotlin/org/jetbrains/kotlin/KonanTestSuiteReport.kt new file mode 100644 index 00000000000..b6923007498 --- /dev/null +++ b/kotlin-native/build-tools/src/main/kotlin/org/jetbrains/kotlin/KonanTestSuiteReport.kt @@ -0,0 +1,164 @@ +package org.jetbrains.kotlin + +import com.google.gson.annotations.Expose +import java.io.PrintWriter +import java.io.StringWriter +import org.gradle.api.Project + +enum class TestStatus { + PASSED, + FAILED, + ERROR, + SKIPPED +} + +data class Statistics( + @Expose var passed: Int = 0, + @Expose var failed: Int = 0, + @Expose var error: Int = 0, + @Expose var skipped: Int = 0) { + + + fun pass(count: Int = 1) { passed += count } + + fun skip(count: Int = 1) { skipped += count } + + fun fail(count: Int = 1) { failed += count } + + fun error(count: Int = 1) { error += count } + + fun add(other: Statistics) { + passed += other.passed + failed += other.failed + error += other.error + skipped += other.skipped + } +} + +val Statistics.total: Int + get() = passed + failed + error + skipped + +class TestFailedException(msg:String) : RuntimeException(msg) + + +data class KonanTestGroupReport(@Expose val name: String, val suites: List) + +data class KonanTestSuiteReport(@Expose val name: String, val tests: List) + +data class KonanTestCaseReport(@Expose val name: String, @Expose val status: TestStatus, @Expose val comment: String? = null) + +class KonanTestSuiteReportEnvironment(val name: String, val project: Project, val statistics: Statistics) { + private val tc = if (Tc.enabled) TeamCityTestPrinter(project) else null + val tests = mutableListOf() + fun executeTest(testName: String, action:() -> Unit) { + var test: KonanTestCaseReport? + try { + tc?.startTest(testName) + action() + tc?.passTest(testName) + statistics.pass() + test = KonanTestCaseReport(testName, TestStatus.PASSED) + } catch (e:TestFailedException) { + tc?.failedTest(testName, e) + statistics.fail() + test = KonanTestCaseReport(testName, TestStatus.FAILED, "Exception: ${e.message}. Cause: ${e.cause?.message}") + project.logger.quiet("test: $testName failed") + } catch (e:Exception) { + tc?.errorTest(testName, e) + statistics.error() + test = KonanTestCaseReport(testName, TestStatus.ERROR, "Exception: ${e.message}. Cause: ${e.cause?.message}") + project.logger.quiet("error on test: $testName", e) + } + test!!.apply { + tests += this + if (status == TestStatus.ERROR || status == TestStatus.FAILED) { + project.logger.quiet("Command to reproduce: ./gradlew $name -Pfilter=${test.name}\n") + } + } + } + + fun skipTest(name: String) { + tc?.skipTest(name) + statistics.skip() + tests += KonanTestCaseReport(name, TestStatus.SKIPPED) + } + + fun abort(throwable: Throwable, count:Int) { + statistics.error(count) + project.logger.quiet("suite `$name` aborted with exception", throwable) + } + + internal operator fun invoke(action: (KonanTestSuiteReportEnvironment) -> Unit) { + tc?.suiteStart(name) + action(this) + tc?.suiteFinish(name) + } +} + +class KonanTestGroupReportEnvironment(val project:Project) { + val statistics = Statistics() + val suiteReports = mutableListOf() + fun suite(suiteName:String, action:(KonanTestSuiteReportEnvironment)->Unit) { + val konanTestSuiteEnvironment = KonanTestSuiteReportEnvironment(suiteName, project, statistics) + konanTestSuiteEnvironment { + action(it) + } + suiteReports += KonanTestSuiteReport(suiteName, konanTestSuiteEnvironment.tests) + } +} + +private class TeamCityTestPrinter(val project:Project) { + fun suiteStart(name: String) { + teamcityReport("testSuiteStarted name='$name'") + } + + fun suiteFinish(name: String) { + teamcityReport("testSuiteFinished name='$name'") + } + + fun startTest(name: String) { + teamcityReport("testStarted name='$name'") + } + + fun passTest(testName: String) = teamcityFinish(testName) + + + fun failedTest(testName: String, testFailedException: TestFailedException) { + teamcityReport("testFailed type='comparisonFailure' name='$testName' message='${testFailedException.message.toTeamCityFormat()}'") + teamcityFinish(testName) + } + + fun errorTest(testName: String, exception: Exception) { + val writer = StringWriter() + exception.printStackTrace(PrintWriter(writer)) + val rawString = writer.toString() + + teamcityReport("testFailed name='$testName' message='${exception.message.toTeamCityFormat()}' " + + "details='${rawString.toTeamCityFormat()}'") + teamcityFinish(testName) + } + + fun skipTest(testName: String) { + teamcityReport("testIgnored name='$testName'") + teamcityFinish(testName) + } + + private fun teamcityFinish(testName:String) { + teamcityReport("testFinished name='$testName'") + } + + /** + * Teamcity require escaping some symbols in pipe manner. + * https://github.com/GitTools/GitVersion/issues/94 + */ + private fun String?.toTeamCityFormat(): String = this?.let { + it.replace("\\|", "||") + .replace("\r", "|r") + .replace("\n", "|n") + .replace("'", "|'") + .replace("\\[", "|[") + .replace("]", "|]")} ?: "null" + private fun teamcityReport(msg: String) { + project.logger.quiet("##teamcity[$msg]") + } +} \ No newline at end of file diff --git a/kotlin-native/build-tools/src/main/kotlin/org/jetbrains/kotlin/KotlinBuildPusher.kt b/kotlin-native/build-tools/src/main/kotlin/org/jetbrains/kotlin/KotlinBuildPusher.kt new file mode 100644 index 00000000000..3844a9a5850 --- /dev/null +++ b/kotlin-native/build-tools/src/main/kotlin/org/jetbrains/kotlin/KotlinBuildPusher.kt @@ -0,0 +1,106 @@ +package org.jetbrains.kotlin + +import io.ktor.client.HttpClient +import io.ktor.client.request.get +import io.ktor.client.request.header +import io.ktor.client.request.post +import io.ktor.content.TextContent +import io.ktor.http.ContentType +import kotlinx.coroutines.runBlocking +import org.gradle.api.DefaultTask +import org.gradle.api.tasks.Input +import org.gradle.api.tasks.TaskAction +import org.gradle.api.tasks.options.Option + +@Suppress("UnstableApiUsage") +open class KotlinBuildPusher : DefaultTask() { + @Input + @Option(option = "token", description = "Teamcity Bear token") + var token: String? = "" + + @Input + @Option(option = "buildServer", description = "Teamcity server") + var buildServer: String = "" + + @Input + @Option(option = "compilerConfigurationId", description = "Teamcity configuration id") + var compilerConfigurationId: String = "Kotlin_dev_Compiler" + + @Input + @Option(option = "overrideConfigurationId", description = "Teamcity kotlin override configuration id") + var overrideConfigurationId: String = "Kotlin_dev_DeployMavenArtifacts_OverrideNative" + + @Input + @Option(option = "kotlinVersion", description = "Kotlin Compiler Version") + var kotlinVersion: String = "" + + @Input + @Option(option = "konanVersion", description = "Kotlin Native Compiler Version") + var konanVersion: String = "" + + @TaskAction + fun run() { + requireNotNull(token, { "Teamcity Bear token required" }) + val client = HttpClient() + runBlocking { + val buildId = client.get( + scheme = "https", + host = buildServer, + path = "/app/rest/builds/buildType:(id:$compilerConfigurationId),number:$kotlinVersion/id" + ) { + header("Authorization", "Bearer $token") + } + project.logger.info("pusher: buildId: $buildId") + + /** + * + * + * + * + * + * + * + * + * + */ + val content = buildString { + build { + buildType(overrideConfigurationId) + lastChanges { + change(buildId) + } + properties { + property("system.versions.kotlin-native", konanVersion) + } + } + } + project.logger.info("pusher: content: \"$content\"") + + val res = client.post( + scheme = "https", + host = buildServer, + path = "/app/rest/buildQueue" + ) { + header("Authorization", "Bearer $token") + header("Origin", "https://$buildServer") + body = TextContent(content, ContentType.Application.Xml) + } + project.logger.info("pusher: result: \"$res\"") + } + client.close() + } +} + +internal fun StringBuilder.paired(tag:String, body:StringBuilder.()->Unit) { + appendln("<$tag>") + body() + appendln("") +} + +internal fun StringBuilder.build(body: StringBuilder.() -> Unit) = paired("build", body) +internal fun StringBuilder.buildType(id: String) = appendln("") +internal fun StringBuilder.lastChanges(body: StringBuilder.() -> Unit) = paired("lastChanges", body) +internal fun StringBuilder.change(build: String) = appendln("") +internal fun StringBuilder.properties(body: StringBuilder.() -> Unit) = paired("properties", body) +internal fun StringBuilder.property(key: String, value: String) = appendln("") + diff --git a/kotlin-native/build-tools/src/main/kotlin/org/jetbrains/kotlin/KotlinNativeTest.kt b/kotlin-native/build-tools/src/main/kotlin/org/jetbrains/kotlin/KotlinNativeTest.kt new file mode 100644 index 00000000000..438c6f00044 --- /dev/null +++ b/kotlin-native/build-tools/src/main/kotlin/org/jetbrains/kotlin/KotlinNativeTest.kt @@ -0,0 +1,463 @@ +/* + * Copyright 2010-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ +package org.jetbrains.kotlin + +import groovy.lang.Closure +import org.gradle.api.Action +import org.gradle.api.DefaultTask +import org.gradle.api.Project +import org.gradle.api.Task +import org.gradle.api.provider.Provider +import org.gradle.api.tasks.Input +import org.gradle.api.tasks.Optional +import org.gradle.api.tasks.TaskAction +import org.gradle.language.base.plugins.LifecycleBasePlugin +import org.gradle.process.ExecSpec + +import java.io.File +import java.io.ByteArrayOutputStream +import java.util.regex.Pattern + +import org.jetbrains.kotlin.konan.target.HostManager + +abstract class KonanTest : DefaultTask(), KonanTestExecutable { + enum class Logger { + EMPTY, // Built without test runner + GTEST, // Google test log output + TEAMCITY, // TeamCity log output + SIMPLE, // Prints simple messages of passed/failed tests + SILENT // Prints no log of passed/failed tests + } + + var disabled: Boolean + get() = !enabled + set(value) { enabled = !value } + + /** + * Test output directory. Used to store processed sources and binary artifacts. + */ + abstract val outputDirectory: String + + /** + * Test logger to be used for the test built with TestRunner (`-tr` option). + */ + abstract var testLogger: Logger + + /** + * Test executable arguments. + */ + @Input + var arguments = mutableListOf() + + /** + * Test executable. + */ + abstract override val executable: String + + /** + * Test source. + */ + lateinit var source: String + + /** + * Sets test filtering to choose the exact test in the executable built with TestRunner. + */ + @Input + var useFilter = true + + /** + * An action to be executed before the build. + * As this run task comes after the build task all actions for doFirst + * should be done before the build and not run. + */ + @Input @Optional + override var doBeforeBuild: Action? = null + + @Input @Optional + override var doBeforeRun: Action? = null + + override val buildTasks: List + get() = listOf(project.findKonanBuildTask(name, project.testTarget)) + + @Suppress("UnstableApiUsage") + override fun configure(config: Closure<*>): Task { + super.configure(config) + + // Set Gradle properties for the better navigation + group = LifecycleBasePlugin.VERIFICATION_GROUP + description = "Kotlin/Native test infrastructure task" + + if (testLogger != Logger.EMPTY) { + arguments.add("--ktest_logger=$testLogger") + } + if (useFilter && ::source.isInitialized) { + arguments.add("--ktest_filter=${source.convertToPattern()}") + } + this.dependsOnDist() + return this + } + + @TaskAction + open fun run() = project.executeAndCheck(project.file(executable).toPath(), arguments) + + // Converts to runner's pattern + private fun String.convertToPattern() = this.removeSuffix(".kt").replace("/", ".") + ".*" + + internal fun ProcessOutput.print(prepend: String = "") { + if (project.verboseTest) + println(prepend + """ + |stdout: + |$stdOut + |stderr: + |$stdErr + |exit code: $exitCode + """.trimMargin()) + } +} + +/** + * Create a test task of the given type. Supports configuration with Closure passed form build.gradle file. + */ +fun Project.createTest(name: String, type: Class, config: Closure<*>): T = + project.tasks.create(name, type).apply { + // Apply closure set in build.gradle to get all parameters. + this.configure(config) + if (enabled) { + // If run task depends on something, build tasks should also depend on this. + buildTasks.forEach { buildTask -> + buildTask.sameDependenciesAs(this) + // Run task should depend on compile task + this.dependsOn(buildTask) + doBeforeBuild?.let { buildTask.doFirst(it) } + buildTask.enabled = enabled + } + } + } + +/** + * Task to run tests compiled with TestRunner. + * Runs tests with GTEST output and parses it to create statistics info + */ +open class KonanGTest : KonanTest() { + override val outputDirectory = "${project.testOutputStdlib}/$name" + + // Use GTEST logger to parse test results later + override var testLogger = Logger.GTEST + + override val executable: String + get() = "$outputDirectory/${project.testTarget.name}/$name.${project.testTarget.family.exeSuffix}" + + var statistics = Statistics() + + @TaskAction + override fun run() { + doBeforeRun?.execute(this) + runProcess( + executor = {project.executor.execute(it)}, + executable = executable, + args = arguments + ).run { + parse(stdOut) + println(""" + |stdout: + |$stdOut + |stderr: + |$stdErr + |exit code: $exitCode + """.trimMargin()) + check(exitCode == 0) { "Test $executable exited with $exitCode" } + } + } + + private fun parse(output: String) = statistics.apply { + Pattern.compile("\\[ PASSED ] ([0-9]*) tests\\.").matcher(output) + .apply { if (find()) pass(group(1).toInt()) } + + Pattern.compile("\\[ FAILED ] ([0-9]*) tests.*").matcher(output) + .apply { if (find()) fail(group(1).toInt()) } + if (total == 0) { + // No test were run. Try to find if we've tried to run something + error(Pattern.compile("\\[={10}] Running ([0-9]*) tests from ([0-9]*) test cases\\..*") + .matcher(output) + .run { if (find()) group(1).toInt() else 1 }) + } + } +} + +/** + * Task to run tests built into a single predefined binary named `localTest`. + * Note: this task should depend on task that builds a test binary. + */ +open class KonanLocalTest : KonanTest() { + override val outputDirectory = project.testOutputLocal + + // local tests built into a single binary with the known name + override val executable: String + get() = "$outputDirectory/${project.testTarget.name}/localTest.${project.testTarget.family.exeSuffix}" + + override var testLogger = Logger.SILENT + + @Input @Optional + var expectedExitStatus: Int? = null + + @Input @Optional + var expectedExitStatusChecker: (Int) -> Boolean = { it == (expectedExitStatus ?: 0) } + + /** + * Should this test fail or not. + */ + @Input @Optional + var expectedFail = false + + /** + * Used to validate output as a gold value. + */ + @Input @Optional + var goldValue: String? = null + + /** + * Checks test's output against gold value and returns true if the output matches the expectation. + */ + @Input @Optional + var outputChecker: (String) -> Boolean = { str -> goldValue == null || goldValue == str } + /** + * Input test data to be passed to process' stdin. + */ + @Input @Optional + var testData: String? = null + + /** + * Should compiler message be read and validated with output checker or gold value. + */ + @Input @Optional + var compilerMessages = false + + @Input @Optional + var multiRuns = false + + @Input @Optional + var multiArguments: List>? = null + + @TaskAction + override fun run() { + doBeforeRun?.execute(this) + val times = if (multiRuns && multiArguments != null) multiArguments!!.size else 1 + var output = ProcessOutput("", "", 0) + for (i in 1..times) { + val args = arguments + (multiArguments?.get(i - 1) ?: emptyList()) + output += if (testData != null) + runProcessWithInput({project.executor.execute(it)}, executable, args, testData!!) + else + runProcess({project.executor.execute(it)}, executable, args) + } + if (compilerMessages) { + // TODO: as for now it captures output only in the driver task. + // It should capture output from the build task using Gradle's LoggerManager and LoggerOutput + val compilationLog = project.file("$executable.compilation.log").readText() + // TODO: ugly hack to fix irrelevant warnings. + val filteredCompilationLog = compilationLog.split('\n').filter { + it != "warning: relaxed memory model is not yet fully functional" + }.joinToString(separator = "\n") + output.stdOut = filteredCompilationLog + output.stdOut + } + output.check() + output.print() + } + + private operator fun ProcessOutput.plus(other: ProcessOutput) = ProcessOutput( + stdOut + other.stdOut, + stdErr + other.stdErr, + exitCode + other.exitCode) + + private fun ProcessOutput.check() { + val exitCodeMismatch = !expectedExitStatusChecker(exitCode) + if (exitCodeMismatch) { + val message = if (expectedExitStatus != null) + "Expected exit status: $expectedExitStatus, actual: $exitCode" + else + "Actual exit status doesn't match with exit status checker: $exitCode" + check(expectedFail) { """ + |Test failed. $message + |stdout: + |$stdOut + |stderr: + |$stdErr + """.trimMargin() + } + println("Expected failure. $message") + } + + val result = stdOut + stdErr + val goldValueMismatch = !outputChecker(result.replace(System.lineSeparator(), "\n")) + if (goldValueMismatch) { + val message = if (goldValue != null) + "Expected output: $goldValue, actual output: $result" + else + "Actual output doesn't match with output checker: $result" + + check(expectedFail) { "Test failed. $message" } + println("Expected failure. $message") + } + + check ((exitCodeMismatch || goldValueMismatch) || !expectedFail) { """ + |Unexpected pass: + | * exit code mismatch: $exitCodeMismatch + | * gold value mismatch: $goldValueMismatch + | * expected fail: $expectedFail + """.trimMargin() + } + } +} + +/** + * Executes a standalone tests provided with either @param executable or by the tasks @param name. + * The executable itself should be built by the konan plugin. + */ +open class KonanStandaloneTest : KonanLocalTest() { + init { + useFilter = false + } + + override val outputDirectory: String + get() = "${project.testOutputLocal}/$name" + + override var testLogger = Logger.EMPTY + + override val executable: String + get() = "$outputDirectory/${project.testTarget.name}/$name.${project.testTarget.family.exeSuffix}" + + @Input @Optional + var enableKonanAssertions = true + + /** + * Compiler flags used to build a test. + */ + var flags: List = listOf() + get() = if (enableKonanAssertions) field + "-ea" else field + + fun getSources(): Provider> = project.provider { + val sources = buildCompileList(project.file(source).toPath(), outputDirectory) + sources.forEach { it.writeTextToFile() } + sources.map { it.path } + } +} + +/** + * This is another way to run the konanc compiler. It runs a konanc shell script. + * + * @note This task is not intended for regular testing as project.exec + a shell script isolate the jvm from IDEA. + * @see KonanLocalTest to be used as a regular task. + */ +open class KonanDriverTest : KonanStandaloneTest() { + override fun configure(config: Closure<*>): Task { + super.configure(config) + doFirst { konan() } + doBeforeBuild?.let { doFirst(it) } + return this + } + + private fun konan() { + val dist = project.kotlinNativeDist + val konancDriver = if (HostManager.hostIsMingw) "konanc.bat" else "konanc" + val konanc = File("${dist.canonicalPath}/bin/$konancDriver").absolutePath + + File(executable).parentFile.mkdirs() + + val args = mutableListOf("-output", executable).apply { + if (project.testTarget != HostManager.host) { + add("-target") + add(project.testTarget.visibleName) + } + addAll(getSources().get()) + addAll(flags) + addAll(project.globalTestArgs) + } + + // run konanc compiler locally + runProcess(localExecutor(project), konanc, args).let { + it.print("Konanc compiler execution:") + project.file("$executable.compilation.log").run { + writeText(it.stdOut) + writeText(it.stdErr) + } + check(it.exitCode == 0) { "Compiler failed with exit code ${it.exitCode}" } + } + } +} + +open class KonanInteropTest : KonanStandaloneTest() { + /** + * Name of the interop library + */ + @Input + lateinit var interop: String +} + +open class KonanLinkTest : KonanStandaloneTest() { + @Input + lateinit var lib: String +} + +/** + * Test task to check a library built by `-produce dynamic`. + * C source code should contain `testlib` as a reference to a testing library. + * It will be replaced then by the actual library name. + */ +open class KonanDynamicTest : KonanStandaloneTest() { + override fun configure(config: Closure<*>): Task { + super.configure(config) + doFirst { clang() } + return this + } + + /** + * File path to the C source. + */ + @Input + lateinit var cSource: String + + var clangTool = "clang" + + // Replace testlib_api.h and all occurrences of the testlib with the actual name of the test + private fun processCSource(): String { + val sourceFile = File(cSource) + val prefixedName = if (HostManager.hostIsMingw) name else "lib$name" + val res = sourceFile.readText() + .replace("#include \"testlib_api.h\"", "#include \"${prefixedName}_api.h\"") + .replace("testlib", prefixedName) + val newFileName = "$outputDirectory/${sourceFile.name}" + println(newFileName) + File(newFileName).run { + createNewFile() + writeText(res) + } + return newFileName + } + + private fun clang() { + val log = ByteArrayOutputStream() + val plugin = project.convention.getPlugin(ExecClang::class.java) + val execResult = plugin.execKonanClang(project.testTarget, Action { + it.workingDir = File(outputDirectory) + it.executable = clangTool + val artifactsDir = "$outputDirectory/${project.testTarget}" + it.args = listOf(processCSource(), + "-o", executable, + "-I", artifactsDir, + "-L", artifactsDir, + "-l", name, + "-Wl,-rpath,$artifactsDir") + + it.standardOutput = log + it.errorOutput = log + it.isIgnoreExitValue = true + }) + log.toString("UTF-8").also { + project.file("$executable.compilation.log").writeText(it) + println(it) + } + execResult.assertNormalExitValue() + } +} \ No newline at end of file diff --git a/kotlin-native/build-tools/src/main/kotlin/org/jetbrains/kotlin/LlvmCovReport.kt b/kotlin-native/build-tools/src/main/kotlin/org/jetbrains/kotlin/LlvmCovReport.kt new file mode 100644 index 00000000000..04c3e7d8064 --- /dev/null +++ b/kotlin-native/build-tools/src/main/kotlin/org/jetbrains/kotlin/LlvmCovReport.kt @@ -0,0 +1,54 @@ +package org.jetbrains.kotlin + +import com.google.gson.* +import com.google.gson.annotations.* + + +data class LlvmCovReportFunction( + @Expose val name: String, + @Expose val count: Int, + @Expose val regions: List>, + @Expose val filenames: List +) + +data class LlvmCovReportSummary( + @Expose val lines: LlvmCovReportStatistics, + @Expose val functions: LlvmCovReportStatistics, + @Expose val instantiations: LlvmCovReportStatistics, + @Expose val regions: LlvmCovReportStatistics + +) + +/** + * TODO: Add support for `segments` field later. + * It's a bit complicated since every segment + * is encoded not as dictionary, but as array of ints and bools. + */ +data class LlvmCovReportFile( + @Expose val filename: String, + @Expose val summary: LlvmCovReportSummary +) + +data class LlvmCovReportStatistics( + @Expose val count: Int, + @Expose val covered: Int, + @Expose val percent: Double +) + +data class LlvmCovReportData( + @Expose val files: List, + @Expose val functions: List, + @Expose val totals: LlvmCovReportSummary +) + +data class LlvmCovReport( + @Expose val version: String, + @Expose val type: String, + @Expose val data: List +) + +fun parseLlvmCovReport(llvmCovReport: String): LlvmCovReport = gson.fromJson(llvmCovReport, LlvmCovReport::class.java) + +val LlvmCovReport.isValid + get() = type == "llvm.coverage.json.export" + diff --git a/kotlin-native/build-tools/src/main/kotlin/org/jetbrains/kotlin/MPPTools.kt b/kotlin-native/build-tools/src/main/kotlin/org/jetbrains/kotlin/MPPTools.kt new file mode 100644 index 00000000000..050da54140a --- /dev/null +++ b/kotlin-native/build-tools/src/main/kotlin/org/jetbrains/kotlin/MPPTools.kt @@ -0,0 +1,268 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the license/LICENSE.txt file. + */ + +@file:JvmName("MPPTools") + +package org.jetbrains.kotlin + +import groovy.lang.Closure +import org.gradle.api.Project +import org.gradle.api.Task +import org.gradle.api.tasks.TaskState +import org.gradle.api.execution.TaskExecutionListener +import org.jetbrains.kotlin.gradle.plugin.KotlinTargetPreset +import org.jetbrains.kotlin.gradle.plugin.mpp.NativeBuildType +import org.jetbrains.kotlin.gradle.tasks.KotlinNativeLink +import org.jetbrains.kotlin.konan.target.HostManager +import org.jetbrains.report.* +import org.jetbrains.report.json.* +import java.nio.file.Paths +import java.io.File +import java.io.FileInputStream +import java.io.BufferedOutputStream +import java.io.BufferedInputStream +import java.net.HttpURLConnection +import java.net.URL +import java.util.Base64 + +/* + * This file includes short-cuts that may potentially be implemented in Kotlin MPP Gradle plugin in the future. + */ + +// Short-cuts for mostly used paths. +@get:JvmName("mingwPath") +val mingwPath by lazy { System.getenv("MINGW64_DIR") ?: "c:/msys64/mingw64" } + +@get:JvmName("kotlinNativeDataPath") +val kotlinNativeDataPath by lazy { + System.getenv("KONAN_DATA_DIR") ?: Paths.get(userHome, ".konan").toString() +} + +// A short-cut for evaluation of the default host Kotlin/Native preset. +@JvmOverloads +fun defaultHostPreset( + subproject: Project, + whitelist: List> = listOf(subproject.kotlin.presets.macosX64, subproject.kotlin.presets.linuxX64, subproject.kotlin.presets.mingwX64) +): KotlinTargetPreset<*> { + + if (whitelist.isEmpty()) + throw Exception("Preset whitelist must not be empty in Kotlin/Native ${subproject.displayName}.") + + val presetCandidate = when { + PlatformInfo.isMac() -> subproject.kotlin.presets.macosX64 + PlatformInfo.isLinux() -> subproject.kotlin.presets.linuxX64 + PlatformInfo.isWindows() -> subproject.kotlin.presets.mingwX64 + else -> null + } + + return if (presetCandidate != null && presetCandidate in whitelist) + presetCandidate + else + throw Exception("Host OS '$hostOs' is not supported in Kotlin/Native ${subproject.displayName}.") +} + +fun getNativeProgramExtension(): String = when { + PlatformInfo.isMac() -> ".kexe" + PlatformInfo.isLinux() -> ".kexe" + PlatformInfo.isWindows() -> ".exe" + else -> error("Unknown host") +} + +fun getFileSize(filePath: String): Long? { + val file = File(filePath) + return if (file.exists()) file.length() else null +} + +fun getCodeSizeBenchmark(programName: String, filePath: String): BenchmarkResult { + val codeSize = getFileSize(filePath) + return BenchmarkResult(programName, + codeSize?. let { BenchmarkResult.Status.PASSED } ?: run { BenchmarkResult.Status.FAILED }, + codeSize?.toDouble() ?: 0.0, BenchmarkResult.Metric.CODE_SIZE, codeSize?.toDouble() ?: 0.0, 1, 0) +} + +fun toCodeSizeBenchmark(metricDescription: String, status: String, programName: String): BenchmarkResult { + if (!metricDescription.startsWith("CODE_SIZE")) { + error("Wrong metric is used as code size.") + } + val codeSize = metricDescription.split(' ')[1].toDouble() + return BenchmarkResult(programName, + if (status == "PASSED") BenchmarkResult.Status.PASSED else BenchmarkResult.Status.FAILED, + codeSize, BenchmarkResult.Metric.CODE_SIZE, codeSize, 1, 0) +} + +// Create benchmarks json report based on information get from gradle project +fun createJsonReport(projectProperties: Map): String { + fun getValue(key: String): String = projectProperties[key] as? String ?: "unknown" + val machine = Environment.Machine(getValue("cpu"), getValue("os")) + val jdk = Environment.JDKInstance(getValue("jdkVersion"), getValue("jdkVendor")) + val env = Environment(machine, jdk) + val flags = (projectProperties["flags"] ?: emptyList()) as List + val backend = Compiler.Backend(Compiler.backendTypeFromString(getValue("type"))!! , + getValue("compilerVersion"), flags) + val kotlin = Compiler(backend, getValue("kotlinVersion")) + val benchDesc = getValue("benchmarks") + val benchmarksArray = JsonTreeParser.parse(benchDesc) + val benchmarks = parseBenchmarksArray(benchmarksArray) + .union(projectProperties["compileTime"] as List).union( + listOf(projectProperties["codeSize"] as? BenchmarkResult).filterNotNull()).toList() + val report = BenchmarksReport(env, benchmarks, kotlin) + return report.toJson() +} + +fun mergeReports(reports: List): String { + val reportsToMerge = reports.filter { it.exists() }.map { + val json = it.inputStream().bufferedReader().use { it.readText() } + val reportElement = JsonTreeParser.parse(json) + BenchmarksReport.create(reportElement) + } + val structuredReports = mutableMapOf>() + reportsToMerge.map { it.compiler.backend.flags.joinToString() to it }.forEach { + structuredReports.getOrPut(it.first) { mutableListOf() }.add(it.second) + } + val jsons = structuredReports.map { (_, value) -> value.reduce { result, it -> result + it }.toJson() } + return when(jsons.size) { + 0 -> "" + 1 -> jsons[0] + else -> jsons.joinToString(prefix = "[", postfix = "]") + } +} + +fun getCompileOnlyBenchmarksOpts(project: Project, defaultCompilerOpts: List): List { + val dist = project.file(project.findProperty("kotlin.native.home") ?: "dist") + val useCache = !project.hasProperty("disableCompilerCaches") + val cacheOption = "-Xcache-directory=$dist/klib/cache/${HostManager.host.name}-gSTATIC" + .takeIf { useCache && PlatformInfo.isMac() } // TODO: remove target condition when we have cache support for other targets. + return (project.findProperty("nativeBuildType") as String?)?.let { + if (it.equals("RELEASE", true)) + listOf("-opt") + else if (it.equals("DEBUG", true)) + listOfNotNull("-g", cacheOption) + else listOf() + } ?: defaultCompilerOpts + listOfNotNull(cacheOption?.takeIf { !defaultCompilerOpts.contains("-opt") }) +} + +// Find file with set name in directory. +fun findFile(fileName: String, directory: String): String? = + File(directory).walkTopDown().filter { !it.absolutePath.contains(".dSYM") } + .find { it.name == fileName }?.getAbsolutePath() + +fun uploadFileToArtifactory(url: String, project: String, artifactoryFilePath: String, + filePath: String, password: String) { + val uploadUrl = "$url/$project/$artifactoryFilePath" + sendUploadRequest(uploadUrl, filePath, extraHeaders = listOf(Pair("X-JFrog-Art-Api", password))) +} + +fun sendUploadRequest(url: String, fileName: String, username: String? = null, password: String? = null, + extraHeaders: List> = emptyList()) { + val uploadingFile = File(fileName) + val connection = URL(url).openConnection() as HttpURLConnection + connection.doOutput = true + connection.doInput = true + connection.requestMethod = "PUT" + connection.setRequestProperty("Content-type", "text/plain") + if (username != null && password != null) { + val auth = Base64.getEncoder().encode((username + ":" + password).toByteArray()).toString(Charsets.UTF_8) + connection.addRequestProperty("Authorization", "Basic $auth") + } + extraHeaders.forEach { + connection.addRequestProperty(it.first, it.second) + } + try { + connection.connect() + BufferedOutputStream(connection.outputStream).use { output -> + BufferedInputStream(FileInputStream(uploadingFile)).use { input -> + input.copyTo(output) + } + } + val response = connection.responseMessage + println("Upload request ended with ${connection.responseCode} - $response") + } catch (t: Throwable) { + error("Couldn't upload file $fileName to $url") + } +} + +// A short-cut to add a Kotlin/Native run task. +@JvmOverloads +fun createRunTask( + subproject: Project, + name: String, + linkTask: Task, + executable: String, + outputFileName: String +): Task { + return subproject.tasks.create(name, RunKotlinNativeTask::class.java, linkTask, executable, outputFileName) +} + +fun getJvmCompileTime(subproject: Project,programName: String): BenchmarkResult = + TaskTimerListener.getTimerListenerOfSubproject(subproject) + .getBenchmarkResult(programName, listOf("compileKotlinMetadata", "jvmJar")) + +@JvmOverloads +fun getNativeCompileTime(subproject: Project, programName: String, + tasks: List = listOf("linkBenchmarkReleaseExecutableNative")): BenchmarkResult = + TaskTimerListener.getTimerListenerOfSubproject(subproject).getBenchmarkResult(programName, tasks) + +fun getCompileBenchmarkTime(subproject: Project, + programName: String, tasksNames: Iterable, + repeats: Int, exitCodes: Map) = + (1..repeats).map { number -> + var time = 0.0 + var status = BenchmarkResult.Status.PASSED + tasksNames.forEach { + time += TaskTimerListener.getTimerListenerOfSubproject(subproject).getTime("$it$number") + status = if (exitCodes["$it$number"] != 0) BenchmarkResult.Status.FAILED else status + } + + BenchmarkResult(programName, status, time, BenchmarkResult.Metric.COMPILE_TIME, time, number, 0) + }.toList() + +fun toCompileBenchmark(metricDescription: String, status: String, programName: String): BenchmarkResult { + if (!metricDescription.startsWith("COMPILE_TIME")) { + error("Wrong metric is used as compile time.") + } + val time = metricDescription.split(' ')[1].toDouble() + return BenchmarkResult(programName, + if (status == "PASSED") BenchmarkResult.Status.PASSED else BenchmarkResult.Status.FAILED, + time, BenchmarkResult.Metric.COMPILE_TIME, time, 1, 0) +} + +// Class time tracker for all tasks. +class TaskTimerListener: TaskExecutionListener { + companion object { + internal val timerListeners = mutableMapOf() + + internal fun getTimerListenerOfSubproject(subproject: Project) = + timerListeners[subproject.name] ?: error("TimeListener for project ${subproject.name} wasn't set") + } + + val tasksTimes = mutableMapOf() + + fun getBenchmarkResult(programName: String, tasksNames: List): BenchmarkResult { + val time = tasksNames.map { tasksTimes[it] ?: 0.0 }.sum() + // TODO get this info from gradle plugin with exit code end stacktrace. + val status = tasksNames.map { tasksTimes.containsKey(it) }.reduce { a, b -> a && b } + return BenchmarkResult(programName, + if (status) BenchmarkResult.Status.PASSED else BenchmarkResult.Status.FAILED, + time, BenchmarkResult.Metric.COMPILE_TIME, time, 1, 0) + } + + fun getTime(taskName: String) = tasksTimes[taskName] ?: 0.0 + + private var startTime = System.nanoTime() + + override fun beforeExecute(task: Task) { + startTime = System.nanoTime() + } + + override fun afterExecute(task: Task, taskState: TaskState) { + tasksTimes[task.name] = (System.nanoTime() - startTime) / 1000.0 + } +} + +fun addTimeListener(subproject: Project) { + val listener = TaskTimerListener() + TaskTimerListener.timerListeners.put(subproject.name, listener) + subproject.gradle.addListener(listener) +} diff --git a/kotlin-native/build-tools/src/main/kotlin/org/jetbrains/kotlin/MetadataComparisonTest.kt b/kotlin-native/build-tools/src/main/kotlin/org/jetbrains/kotlin/MetadataComparisonTest.kt new file mode 100644 index 00000000000..baca92269d9 --- /dev/null +++ b/kotlin-native/build-tools/src/main/kotlin/org/jetbrains/kotlin/MetadataComparisonTest.kt @@ -0,0 +1,87 @@ +/* + * Copyright 2010-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ +package org.jetbrains.kotlin + +import org.gradle.api.DefaultTask +import org.gradle.api.tasks.Input +import org.gradle.api.tasks.TaskAction +import org.jetbrains.kotlin.klib.metadata.CInteropComparisonConfig +import org.jetbrains.kotlin.klib.metadata.MetadataCompareResult +import org.jetbrains.kotlin.klib.metadata.compareKlibMetadata +import org.jetbrains.kotlin.klib.metadata.expandFail +import org.jetbrains.kotlin.konan.target.HostManager +import java.io.File + +/** + * Produces 2 interop libraries from the given [defFile]. + * One in legacy `sourcecode` mode and another one in `metadata` mode. + * Then structurally compares metadata of the produced klibs. + * + * + * Motivation for this kind of tests: + * + * `sourcecode` mode generates Kotlin source file that is passes to a + * regular Kotlin/Native compiler. + * Thus, the produced metadata is correct (from compiler's point of view) + * because it is produced by the compiler itself. + * + * `metadata` mode generates metadata directly from parsed Clang AST. + * Since another algorithm is used, produced metadata may be incorrect. + * + * So we have to check that these two are more or less the same. + */ +open class MetadataComparisonTest : DefaultTask() { + + private enum class Mode { + METADATA, SOURCECODE + } + + /** + * Path to a cinterop *.def file. + */ + @Input + lateinit var defFile: String + + @TaskAction + fun run() { + val metadataLibrary = cinterop(project.file(defFile), Mode.METADATA) + val sourcecodeLibrary = cinterop(project.file(defFile), Mode.SOURCECODE) + compareKlibMetadata(CInteropComparisonConfig(), sourcecodeLibrary.absolutePath, metadataLibrary.absolutePath).let { result -> + if (result is MetadataCompareResult.Fail) { + val message = StringBuilder().also { + expandFail(result, it::appendln) + }.toString() + throw TestFailedException(message) + } + } + } + + private fun cinterop(defFile: File, mode: Mode): File { + val dist = project.kotlinNativeDist + val output = "${project.buildDir.absolutePath}/${defFile.nameWithoutExtension}_$mode" + val tool = if (HostManager.hostIsMingw) "cinterop.bat" else "cinterop" + val cinterop = File("${dist.canonicalPath}/bin/$tool").absolutePath + val args = listOf( + "-def", defFile.absolutePath, + "-mode", mode.name.toLowerCase(), + "-target", project.testTarget.visibleName, + "-no-default-libs", "-no-endorsed-libs", + "-o", output + ) + runProcess(localExecutor(project), cinterop, args).let { result -> + if (result.exitCode != 0) { + println(""" + cinterop failed. + exitCode: ${result.exitCode} + stdout: + ${result.stdOut} + stderr: + ${result.stdErr} + """.trimIndent()) + } + } + return File(output) + } +} \ No newline at end of file diff --git a/kotlin-native/build-tools/src/main/kotlin/org/jetbrains/kotlin/PlatformInfo.kt b/kotlin-native/build-tools/src/main/kotlin/org/jetbrains/kotlin/PlatformInfo.kt new file mode 100644 index 00000000000..cbd63cc1a8a --- /dev/null +++ b/kotlin-native/build-tools/src/main/kotlin/org/jetbrains/kotlin/PlatformInfo.kt @@ -0,0 +1,60 @@ +package org.jetbrains.kotlin + +import org.jetbrains.kotlin.konan.target.* +import org.jetbrains.kotlin.konan.util.* +import org.gradle.api.Project + +object PlatformInfo { + @JvmStatic + fun isMac() = HostManager.hostIsMac + @JvmStatic + fun isWindows() = HostManager.hostIsMingw + @JvmStatic + fun isLinux() = HostManager.hostIsLinux + + @JvmStatic + fun isAppleTarget(project: Project): Boolean { + val target = getTarget(project) + return target.family.isAppleFamily + } + + @JvmStatic + fun isAppleTarget(target: KonanTarget): Boolean { + return target.family.isAppleFamily + } + + @JvmStatic + fun isWindowsTarget(project: Project) = getTarget(project).family == Family.MINGW + + @JvmStatic + fun isWasmTarget(project: Project) = + getTarget(project).family == Family.WASM + + @JvmStatic + fun getTarget(project: Project): KonanTarget { + val platformManager = project.rootProject.platformManager + val targetName = project.project.testTarget.name + return platformManager.targetManager(targetName).target + } + + @JvmStatic + fun checkXcodeVersion(project: Project) { + val properties = PropertiesProvider(project) + val requiredMajorVersion = properties.xcodeMajorVersion + + if (!DependencyProcessor.isInternalSeverAvailable + && properties.checkXcodeVersion + && requiredMajorVersion != null + ) { + val currentXcodeVersion = Xcode.current.version + val currentMajorVersion = currentXcodeVersion.splitToSequence('.').first() + if (currentMajorVersion != requiredMajorVersion) { + throw IllegalStateException( + "Incorrect Xcode version: ${currentXcodeVersion}. Required major Xcode version is ${requiredMajorVersion}." + ) + } + } + } + + fun unsupportedPlatformException() = TargetSupportException() +} \ No newline at end of file diff --git a/kotlin-native/build-tools/src/main/kotlin/org/jetbrains/kotlin/PropertiesProvider.kt b/kotlin-native/build-tools/src/main/kotlin/org/jetbrains/kotlin/PropertiesProvider.kt new file mode 100644 index 00000000000..8dfc98583c9 --- /dev/null +++ b/kotlin-native/build-tools/src/main/kotlin/org/jetbrains/kotlin/PropertiesProvider.kt @@ -0,0 +1,31 @@ +package org.jetbrains.kotlin + +import org.gradle.api.Project +import java.util.* + +class PropertiesProvider(val project: Project) { + private val localProperties by lazy { + Properties().apply { + project.file("local.properties").takeIf { it.isFile }?.inputStream()?.use { + load(it) + } + } + } + + fun findProperty(name: String): Any? = + project.findProperty(name) ?: localProperties.getProperty(name) + + fun getProperty(name: String): Any = + findProperty(name) ?: throw IllegalArgumentException("No such property: $name") + + fun hasProperty(name: String): Boolean = + project.hasProperty(name) || localProperties.containsKey(name) + + val xcodeMajorVersion: String? + get() = findProperty("xcodeMajorVersion") as String? + + val checkXcodeVersion: Boolean + get() = findProperty("checkXcodeVersion")?.let { + it == "true" + } ?: true +} diff --git a/kotlin-native/build-tools/src/main/kotlin/org/jetbrains/kotlin/RegressionsReporter.kt b/kotlin-native/build-tools/src/main/kotlin/org/jetbrains/kotlin/RegressionsReporter.kt new file mode 100644 index 00000000000..5159a9b8e47 --- /dev/null +++ b/kotlin-native/build-tools/src/main/kotlin/org/jetbrains/kotlin/RegressionsReporter.kt @@ -0,0 +1,173 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the license/LICENSE.txt file. + */ +package org.jetbrains.kotlin + +import groovy.lang.Closure +import org.gradle.api.Action +import org.gradle.api.DefaultTask +import org.gradle.api.Project +import org.gradle.api.Task +import org.gradle.api.tasks.Input +import org.gradle.api.tasks.TaskAction + +import com.ullink.slack.simpleslackapi.impl.SlackSessionFactory + +import org.jetbrains.report.json.* + +import java.io.FileInputStream +import java.io.IOException +import java.io.File +import java.util.concurrent.TimeUnit +import java.net.HttpURLConnection +import java.net.URL +import java.util.Base64 +import java.util.Properties + +/** + * Task to produce regressions report and send it to slack. Requires a report with current benchmarks result + * and path to analyzer tool + * + * @property currentBenchmarksReportFile path to file with becnhmarks result + * @property analyzer path to analyzer tool + * @property htmlReport name of result html report + * @property defaultBranch name of default branch + * @property summaryFile name of file with short summary + * @property bundleBuild property to show if current build is full or not + */ +open class RegressionsReporter : DefaultTask() { + + val slackUsers = mapOf( + "olonho" to "nikolay.igotti", + "nikolay.igotti" to "nikolay.igotti", + "ilya.matveev" to "ilya.matveev", + "ilmat192" to "ilya.matveev", + "vasily.v.levchenko" to "minamoto", + "vasily.levchenko" to "minamoto", + "alexander.gorshenev" to "alexander.gorshenev", + "igor.chevdar" to "igor.chevdar", + "pavel.punegov" to "Pavel Punegov", + "dmitriy.dolovov" to "dmitriy.dolovov", + "svyatoslav.scherbina" to "svyatoslav.scherbina", + "sbogolepov" to "sergey.bogolepov", + "Alexey.Zubakov" to "Alexey.Zubakov", + "kirill.shmakov" to "kirill.shmakov", + "elena.lepilkina" to "elena.lepilkina") + + @Input + lateinit var currentBenchmarksReportFile: String + + @Input + lateinit var analyzer: String + + @Input + lateinit var htmlReport: String + + @Input + lateinit var defaultBranch: String + + @Input + lateinit var summaryFile: String + + @Input + var bundleBuild: Boolean = false + + private fun tabUrl(buildId: String, buildTypeId: String, tab: String) = + "$teamCityUrl/viewLog.html?buildId=$buildId&buildTypeId=$buildTypeId&tab=$tab" + + private fun testReportUrl(buildId: String, buildTypeId: String) = + tabUrl(buildId, buildTypeId, "testsInfo") + + private fun previousBuildLocator(buildTypeId: String, branchName: String) = + "buildType:id:$buildTypeId,branch:name:$branchName,status:SUCCESS,state:finished,count:1" + + private fun changesListUrl(buildLocator: String) = + "$teamCityUrl/app/rest/changes/?locator=build:$buildLocator" + + private fun getCommits(buildLocator: String, user: String, password: String): CommitsList { + val changes = try { + sendGetRequest(changesListUrl(buildLocator), user, password) + } catch (t: Throwable) { + error("Try to get commits! TeamCity is unreachable!") + } + return CommitsList(JsonTreeParser.parse(changes)) + } + + @TaskAction + fun run() { + // Get TeamCity properties. + val teamcityConfig = System.getenv("TEAMCITY_BUILD_PROPERTIES_FILE") ?: + error("Can't load teamcity config!") + + val buildProperties = Properties() + buildProperties.load(FileInputStream(teamcityConfig)) + val buildId = buildProperties.getProperty("teamcity.build.id") + val buildTypeId = buildProperties.getProperty("teamcity.buildType.id") + val buildNumber = buildProperties.getProperty("build.number") + val user = buildProperties.getProperty("teamcity.auth.userId") + val password = buildProperties.getProperty("teamcity.auth.password") + + // Get branch. + val currentBuild = getBuild("id:$buildId", user, password) + val branch = getBuildProperty(currentBuild,"branchName") + + val testReportUrl = testReportUrl(buildId, buildTypeId) + + // Get previous build on branch. + val builds = getBuild(previousBuildLocator(buildTypeId,branch), user, password) + + // Get changes description. + val changesList = getCommits("id:$buildId", user, password) + val changesInfo = "*Changes* in branch *$branch:*\n" + buildString { + changesList.commits.forEach { + append(" - Change ${it.revision} by ${it.developer} (details: ${it.webUrlWithDescription})\n") + } + } + + // File name on Artifactory is the same as current. + val artifactoryFileName = currentBenchmarksReportFile.substringAfterLast("/") + + // Get compare to build. + val compareToBuild = getBuild(previousBuildLocator(buildTypeId, defaultBranch), user, password) + val compareToBuildLink = getBuildProperty(compareToBuild,"webUrl") + val compareToBuildNumber = getBuildProperty(compareToBuild,"number") + val target = System.getProperty("os.name").replace("\\s".toRegex(), "") + + // Generate comparison report. + val output = arrayOf("$analyzer", "-r", "html", "$currentBenchmarksReportFile", "artifactory:$compareToBuildNumber:$target:$artifactoryFileName", "-o", "$htmlReport") + .runCommand() + + if (output.contains("Uncaught exception")) { + error("Error during comparasion of $currentBenchmarksReportFile and " + + "artifactory:$compareToBuildNumber:$target:$artifactoryFileName with $analyzer! " + + "Please check files existance and their correctness.") + } + arrayOf("$analyzer", "-r", "statistics", "$currentBenchmarksReportFile", "artifactory:$compareToBuildNumber:$target:$artifactoryFileName", "-o", "$summaryFile") + .runCommand() + + val reportLink = "https://kotlin-native-perf-summary.labs.jb.gg/?target=$target&build=$buildNumber" + val detailedReportLink = "https://kotlin-native-performance.labs.jb.gg/?" + + "report=artifactory:$buildNumber:$target:$artifactoryFileName&" + + "compareTo=artifactory:$compareToBuildNumber:$target:$artifactoryFileName" + + val title = "\n*Performance report for target $target (build $buildNumber)* - $reportLink\n" + + "*Detailed info - * $detailedReportLink" + + val header = "$title\n$changesInfo\n\nCompare to build $compareToBuildNumber: $compareToBuildLink\n\n" + val footer = "*Benchmarks statistics:* $testReportUrl" + val message = "$header\n$footer\n" + + // Send to channel or user directly. + val session = SlackSessionFactory.createWebSocketSlackSession(buildProperties.getProperty("konan-reporter-token")) + session.connect() + + if (branch == defaultBranch) { + if (bundleBuild) { + val channel = session.findChannelByName(buildProperties.getProperty("konan-channel-name")) + session.sendMessage(channel, message) + } + } + session.disconnect() + } +} \ No newline at end of file diff --git a/kotlin-native/build-tools/src/main/kotlin/org/jetbrains/kotlin/RegressionsSummaryReporter.kt b/kotlin-native/build-tools/src/main/kotlin/org/jetbrains/kotlin/RegressionsSummaryReporter.kt new file mode 100644 index 00000000000..aaaf4447d96 --- /dev/null +++ b/kotlin-native/build-tools/src/main/kotlin/org/jetbrains/kotlin/RegressionsSummaryReporter.kt @@ -0,0 +1,105 @@ +/* + * Copyright 2010-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the license/LICENSE.txt file. + */ + +package org.jetbrains.kotlin + +import groovy.lang.Closure +import org.gradle.api.Action +import org.gradle.api.DefaultTask +import org.gradle.api.Project +import org.gradle.api.Task +import org.gradle.api.tasks.Input +import org.gradle.api.tasks.TaskAction + +import com.ullink.slack.simpleslackapi.impl.SlackSessionFactory +import com.ullink.slack.simpleslackapi.SlackAttachment +import com.ullink.slack.simpleslackapi.SlackPreparedMessage + +import java.io.FileInputStream +import java.io.File +import java.util.Properties + +/** + * Task to produce regressions report and send it to slack. Requires a report with current benchmarks result + * and path to analyzer tool + * + * @property targetsResultFiles map with pathes to results of each target + */ +open class RegressionsSummaryReporter : DefaultTask() { + @Input + lateinit var targetsResultFiles: Map + + val performanceServer = "https://kotlin-native-perf-summary.labs.jb.gg/" + + @TaskAction + fun run() { + // Get TeamCity properties. + val teamcityConfig = System.getenv("TEAMCITY_BUILD_PROPERTIES_FILE") ?: + error("Can't load teamcity config!") + + val buildProperties = Properties() + buildProperties.load(FileInputStream(teamcityConfig)) + val buildId = buildProperties.getProperty("teamcity.build.id") + val buildTypeId = buildProperties.getProperty("teamcity.buildType.id") + val buildNumber = buildProperties.getProperty("build.number") + val results = mutableMapOf>() + + // Parse and merge results from all targets. + targetsResultFiles.forEach { (key, value) -> + val file = File(value) + if (file.exists()) { + file.forEachLine { + val matchResult = "(\\w+)\\s*:\\s*(\\w+)".toRegex().find(it) + val propertyName = matchResult?.groups?.get(1)?.value + val propertyValue = matchResult?.groups?.get(2)?.value + if (propertyName != null && propertyValue != null) { + results[propertyName]?.let { it[key] = propertyValue } + ?: run { results.put(propertyName, mutableMapOf(key to propertyValue)) } + } + } + } + } + + val message = buildString { + append("*Performance summary on charts* - $performanceServer\n") + results.forEach { (property, targets) -> + append("$property: ${targets.map {(target, value) -> "$value ($target)"}.joinToString(" | ")}\n") + } + } + val summaryStatus = results["status"]?.values?.fold("STABLE") {summary, element -> + when { + summary == "FAILED" || element == "FAILED" -> "FAILED" + summary == "FIXED" || element == "FIXED" -> "FIXED" + summary == "STABLE" -> element + summary == element -> summary + else -> "UNSTABLE" + } + } + + val attachement = SlackAttachment() + with (attachement) { + setTitle("Performance Summary (build $buildNumber)") + setTitleLink("https://buildserver.labs.intellij.net/viewLog.html?buildId=$buildId&buildTypeId=$buildTypeId") + setText(message) + if (summaryStatus == "FIXED" || summaryStatus == "IMPROVED") { + setColor("#36a64f") + } else if (summaryStatus == "FAILED" || summaryStatus == "REGRESSED") { + setColor("#ff0000") + } + } + + // Send to channel or user directly. + val session = SlackSessionFactory.createWebSocketSlackSession(buildProperties.getProperty("konan-reporter-token")) + session.connect() + + val channel = session.findChannelByName(buildProperties.getProperty("konan-channel-name")) + val preparedMessage = SlackPreparedMessage.Builder() + .addAttachment(attachement) + .build() + session.sendMessage(channel, preparedMessage) + + session.disconnect() + } +} \ No newline at end of file diff --git a/kotlin-native/build-tools/src/main/kotlin/org/jetbrains/kotlin/Reporter.kt b/kotlin-native/build-tools/src/main/kotlin/org/jetbrains/kotlin/Reporter.kt new file mode 100644 index 00000000000..a133be2de56 --- /dev/null +++ b/kotlin-native/build-tools/src/main/kotlin/org/jetbrains/kotlin/Reporter.kt @@ -0,0 +1,109 @@ +/* + * Copyright 2010-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +package org.jetbrains.kotlin + +import com.ullink.slack.simpleslackapi.impl.SlackSessionFactory +import org.gradle.api.DefaultTask +import org.gradle.api.tasks.Input +import org.gradle.api.tasks.TaskAction +import java.io.FileInputStream +import java.util.* + + +internal object Tc { + private val teamcityConfig = System.getenv("TEAMCITY_BUILD_PROPERTIES_FILE") + val enabled:Boolean = (teamcityConfig != null) + private val buildConfig by lazy { + teamcityConfig ?: return@lazy null + val properties = Properties() + properties.load(FileInputStream(teamcityConfig)) + properties + } + val buildId = buildConfig?.getProperty("teamcity.build.id") + val buildTypeId = buildConfig?.getProperty("teamcity.buildType.id") + val konanReporterToken = buildConfig?.getProperty("konan-reporter-token") + val konanChannelName = buildConfig?.getProperty("konan-channel-name") + +} + +private fun buildLogUrlTab(buildId: String?, buildTypeId: String?): String = tabUrl(buildId, buildTypeId, "buildLog") + +private fun tabUrl(buildId: String?, buildTypeId: String?, tab: String?): String = + "http://buildserver.labs.intellij.net/viewLog.html?buildId=$buildId&buildTypeId=$buildTypeId&tab=$tab" + +private fun testReportUrl(buildId: String?, buildTypeId: String?): String = tabUrl(buildId, buildTypeId, "testsInfo") + +private fun sendTextToSlack(report: String) { + with(SlackSessionFactory.createWebSocketSlackSession(Tc.konanReporterToken)) { + connect() + sendMessage(findChannelByName(Tc.konanChannelName), + "Hello, аборигены Котлина!\n текущий статус:\n$report") + disconnect() + } +} + +private fun reportEpilogue(): String { + val logUrl = buildLogUrlTab(Tc.buildId, Tc.buildTypeId) + val testReportUrl = testReportUrl(Tc.buildId, Tc.buildTypeId) + return "\nlog url: $logUrl\ntest report url: $testReportUrl" +} + +private val Statistics.report + get() = "total: $total\npassed: $passed\nfailed: $failed\nerror: $error\nskipped: $skipped" + +private val Statistics.oneLineReport + get() = "(total: $total, passed: $passed, failed: $failed, error: $error, skipped: $skipped)" + + +open class Reporter : DefaultTask() { + + @Input + lateinit var reportHome: String + + @TaskAction + fun report() { + + val reportJson = loadReport("$reportHome/external/results.json") + + val report: String = + "${reportJson.statistics.report}\n ${reportEpilogue()}" + + project.logger.info(report) + if (doSlackSending()) + sendTextToSlack(report) + } +} + +private fun DefaultTask.doSlackSending() = !project.hasProperty("build.reporter.noSlack") + || !project.property("build.reporter.noSlack").toString().toBoolean() + +open class NightlyReporter: DefaultTask() { + @Input + lateinit var externalMacosReport:String + @Input + lateinit var externalLinuxReport:String + @Input + lateinit var externalWindowsReport:String + + @TaskAction + fun report() { + val externalMacosJsonReport = loadReport("${project.rootDir.absolutePath}/$externalMacosReport") + val externalLinuxJsonReport = loadReport("${project.rootDir.absolutePath}/$externalLinuxReport") + val externalWindowsJsonReport = loadReport("${project.rootDir.absolutePath}/$externalWindowsReport") + val report = buildString { + append("Mac OS ") + appendln(externalMacosJsonReport.statistics.oneLineReport) + append("Linux ") + appendln(externalLinuxJsonReport.statistics.oneLineReport) + append("Windows ") + appendln(externalWindowsJsonReport.statistics.oneLineReport) + appendln(reportEpilogue()) + } + project.logger.info(report) + if (doSlackSending()) + sendTextToSlack(report) + } +} \ No newline at end of file diff --git a/kotlin-native/build-tools/src/main/kotlin/org/jetbrains/kotlin/RunJvmTask.kt b/kotlin-native/build-tools/src/main/kotlin/org/jetbrains/kotlin/RunJvmTask.kt new file mode 100644 index 00000000000..fcd67fdcb03 --- /dev/null +++ b/kotlin-native/build-tools/src/main/kotlin/org/jetbrains/kotlin/RunJvmTask.kt @@ -0,0 +1,125 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the license/LICENSE.txt file. + */ + +package org.jetbrains.kotlin + +import org.gradle.api.tasks.JavaExec +import org.gradle.api.tasks.TaskAction +import org.gradle.api.tasks.options.Option +import org.gradle.api.tasks.Input +import org.jetbrains.kotlin.benchmark.LogLevel +import org.jetbrains.kotlin.benchmark.Logger +import org.jetbrains.report.json.* +import java.io.ByteArrayOutputStream +import java.io.File + +data class ExecParameters(val warmupCount: Int, val repeatCount: Int, + val filterArgs: List, val filterRegexArgs: List, + val verbose: Boolean, val outputFileName: String?) + +open class RunJvmTask: JavaExec() { + @Input + @Option(option = "filter", description = "Benchmarks to run (comma-separated)") + var filter: String = "" + @Input + @Option(option = "filterRegex", description = "Benchmarks to run, described by regular expressions (comma-separated)") + var filterRegex: String = "" + @Input + @Option(option = "verbose", description = "Verbose mode of running benchmarks") + var verbose: Boolean = false + @Input + var warmupCount: Int = 0 + @Input + var repeatCount: Int = 0 + @Input + var repeatingType = BenchmarkRepeatingType.INTERNAL + @Input + var outputFileName: String? = null + + private var predefinedArgs: List = emptyList() + + private fun executeTask(execParameters: ExecParameters): String { + // Firstly clean arguments. + setArgs(emptyList()) + args(predefinedArgs) + args(execParameters.filterArgs) + args(execParameters.filterRegexArgs) + args("-w", execParameters.warmupCount) + args("-r", execParameters.repeatCount) + if (execParameters.verbose) { + args("-v") + } + execParameters.outputFileName?.let { args("-o", outputFileName) } + standardOutput = ByteArrayOutputStream() + super.exec() + return standardOutput.toString() + } + + private fun getBenchmarksList(filterArgs: List, filterRegexArgs: List): List { + // Firstly clean arguments. + setArgs(emptyList()) + args("list") + standardOutput = ByteArrayOutputStream() + super.exec() + val benchmarks = standardOutput.toString().lines() + val regexes = filterRegexArgs.map { it.toRegex() } + return if (filterArgs.isNotEmpty() || regexes.isNotEmpty()) { + benchmarks.filter { benchmark -> benchmark in filterArgs || regexes.any { it.matches(benchmark) } } + } else benchmarks.filter { !it.isEmpty() } + } + + private fun execSeparateBenchmarkRepeatedly(benchmark: String): List { + // Logging with application should be done only in case it controls running benchmarks itself. + // Although it's a responsibility of gradle task. + val logger = if (verbose) Logger(LogLevel.DEBUG) else Logger() + logger.log("Warm up iterations for benchmark $benchmark\n") + for (i in 0.until(warmupCount)) { + executeTask(ExecParameters(0, 1, listOf("-f", benchmark), + emptyList(), false, null)) + } + val result = mutableListOf() + logger.log("Running benchmark $benchmark ") + for (i in 0.until(repeatCount)) { + logger.log(".", usePrefix = false) + val benchmarkReport = JsonTreeParser.parse( + executeTask(ExecParameters(0, 1, listOf("-f", benchmark), + emptyList(), false, null) + ).removePrefix("[").removeSuffix("]") + ).jsonObject + val modifiedBenchmarkReport = JsonObject(HashMap(benchmarkReport.content).apply { + put("repeat", JsonLiteral(i)) + put("warmup", JsonLiteral(warmupCount)) + }) + result.add(modifiedBenchmarkReport.toString()) + } + logger.log("\n", usePrefix = false) + return result + } + + private fun execBenchmarksRepeatedly(filterArgs: List, filterRegexArgs: List) { + val benchmarksToRun = getBenchmarksList(filterArgs, filterRegexArgs) + val results = benchmarksToRun.flatMap { benchmark -> + execSeparateBenchmarkRepeatedly(benchmark) + } + File(outputFileName).printWriter().use { out -> + out.println("[${results.joinToString(",")}]") + } + } + + @TaskAction + override fun exec() { + assert(outputFileName != null) { "Output file name should be always set" } + predefinedArgs = args ?: emptyList() + val filterArgs = filter.splitCommaSeparatedOption("-f") + val filterRegexArgs = filterRegex.splitCommaSeparatedOption("-fr") + when (repeatingType) { + BenchmarkRepeatingType.INTERNAL -> executeTask( + ExecParameters(warmupCount, repeatCount, filterArgs, filterRegexArgs, verbose, outputFileName) + ) + BenchmarkRepeatingType.EXTERNAL -> execBenchmarksRepeatedly(filterArgs, filterRegexArgs) + } + + } +} \ No newline at end of file diff --git a/kotlin-native/build-tools/src/main/kotlin/org/jetbrains/kotlin/RunKotlinNativeTask.kt b/kotlin-native/build-tools/src/main/kotlin/org/jetbrains/kotlin/RunKotlinNativeTask.kt new file mode 100644 index 00000000000..433bb64830e --- /dev/null +++ b/kotlin-native/build-tools/src/main/kotlin/org/jetbrains/kotlin/RunKotlinNativeTask.kt @@ -0,0 +1,131 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the license/LICENSE.txt file. + */ + +package org.jetbrains.kotlin + +import org.gradle.api.DefaultTask +import org.gradle.api.Task +import org.jetbrains.kotlin.benchmark.Logger +import org.jetbrains.kotlin.benchmark.LogLevel +import org.jetbrains.report.json.* +import org.gradle.api.tasks.TaskAction +import org.gradle.api.tasks.options.Option +import org.gradle.api.tasks.Input +import java.io.ByteArrayOutputStream +import java.io.File +import javax.inject.Inject +import kotlin.collections.HashMap + +open class RunKotlinNativeTask @Inject constructor(private val linkTask: Task, + private val executable: String, + private val outputFileName: String +) : DefaultTask() { + + @Input + @Option(option = "filter", description = "Benchmarks to run (comma-separated)") + var filter: String = "" + @Input + @Option(option = "filterRegex", description = "Benchmarks to run, described by regular expressions (comma-separated)") + var filterRegex: String = "" + @Input + @Option(option = "verbose", description = "Verbose mode of running benchmarks") + var verbose: Boolean = false + @Input + var warmupCount: Int = 0 + @Input + var repeatCount: Int = 0 + @Input + var repeatingType = BenchmarkRepeatingType.INTERNAL + + private val argumentsList = mutableListOf() + + init { + this.dependsOn += linkTask.name + this.finalizedBy("konanJsonReport") + } + + fun depends(taskName: String) { + this.dependsOn += taskName + } + + fun args(vararg arguments: String) { + argumentsList.addAll(arguments.toList()) + } + + private fun execBenchmarkOnce(benchmark: String, warmupCount: Int, repeatCount: Int) : String { + val output = ByteArrayOutputStream() + val useCset = project.findProperty("useCset")?.toString()?.toBoolean() ?: false + project.exec { + if (useCset) { + it.executable = "cset" + it.args("shield", "--exec", "--", executable) + } else { + it.executable = executable + } + + it.args(argumentsList) + it.args("-f", benchmark) + // Logging with application should be done only in case it controls running benchmarks itself. + // Although it's a responsibility of gradle task. + if (verbose && repeatingType == BenchmarkRepeatingType.INTERNAL) { + it.args("-v") + } + it.args("-w", warmupCount.toString()) + it.args("-r", repeatCount.toString()) + it.standardOutput = output + } + return output.toString().substringAfter("[").removeSuffix("]") + } + + private fun execBenchmarkRepeatedly(benchmark: String, warmupCount: Int, repeatCount: Int) : List { + val logger = if (verbose) Logger(LogLevel.DEBUG) else Logger() + logger.log("Warm up iterations for benchmark $benchmark\n") + for (i in 0.until(warmupCount)) { + execBenchmarkOnce(benchmark, 0, 1) + } + val result = mutableListOf() + logger.log("Running benchmark $benchmark ") + for (i in 0.until(repeatCount)) { + logger.log(".", usePrefix = false) + val benchmarkReport = JsonTreeParser.parse(execBenchmarkOnce(benchmark, 0, 1)).jsonObject + val modifiedBenchmarkReport = JsonObject(HashMap(benchmarkReport.content).apply { + put("repeat", JsonLiteral(i)) + put("warmup", JsonLiteral(warmupCount)) + }) + result.add(modifiedBenchmarkReport.toString()) + } + logger.log("\n", usePrefix = false) + return result + } + + @TaskAction + fun run() { + val output = ByteArrayOutputStream() + project.exec { + it.executable = executable + it.args("list") + it.standardOutput = output + } + val benchmarks = output.toString().lines() + val filterArgs = filter.splitCommaSeparatedOption("-f") + val filterRegexArgs = filterRegex.splitCommaSeparatedOption("-fr") + val regexes = filterRegexArgs.map { it.toRegex() } + val benchmarksToRun = if (filterArgs.isNotEmpty() || regexes.isNotEmpty()) { + benchmarks.filter { benchmark -> benchmark in filterArgs || regexes.any { it.matches(benchmark) } } + } else benchmarks.filter { !it.isEmpty() } + + val results = benchmarksToRun.flatMap { benchmark -> + when (repeatingType) { + BenchmarkRepeatingType.INTERNAL -> listOf(execBenchmarkOnce(benchmark, warmupCount, repeatCount)) + BenchmarkRepeatingType.EXTERNAL -> execBenchmarkRepeatedly(benchmark, warmupCount, repeatCount) + } + } + + File(outputFileName).printWriter().use { out -> + out.println("[${results.joinToString(",")}]") + } + + } +} diff --git a/kotlin-native/build-tools/src/main/kotlin/org/jetbrains/kotlin/TestDirectives.kt b/kotlin-native/build-tools/src/main/kotlin/org/jetbrains/kotlin/TestDirectives.kt new file mode 100644 index 00000000000..6621b68b42e --- /dev/null +++ b/kotlin-native/build-tools/src/main/kotlin/org/jetbrains/kotlin/TestDirectives.kt @@ -0,0 +1,116 @@ +/* + * Copyright 2010-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +package org.jetbrains.kotlin + +import java.nio.file.Path +import java.nio.file.Paths +import java.util.regex.Pattern + +private const val MODULE_DELIMITER = ",\\s*" +// This pattern is a copy from the kotlin/compiler/tests-common/tests/org/jetbrains/kotlin/test/TestFiles.java +private val FILE_OR_MODULE_PATTERN: Pattern = Pattern.compile("(?://\\s*MODULE:\\s*([^()\\n]+)(?:\\(([^()]+(?:" + + "$MODULE_DELIMITER[^()]+)*)\\))?\\s*(?:\\(([^()]+(?:$MODULE_DELIMITER[^()]+)*)\\))?\\s*)?//\\s*FILE:\\s*(.*)$", + Pattern.MULTILINE) + +/** + * Creates test files from the given source file that may contain different test directives. + * + * @return list of test files [TestFile] to be compiled + */ +fun buildCompileList(source: Path, outputDirectory: String): List { + val result = mutableListOf() + val srcFile = source.toFile() + // Remove diagnostic parameters in external tests. + val srcText = srcFile.readText().replace(Regex("(.*?)")) { match -> match.groupValues[1] } + + if (srcText.contains("// WITH_COROUTINES")) { + result.add(TestFile("helpers.kt", "$outputDirectory/helpers.kt", + createTextForHelpers(true), TestModule.support)) + } + + val matcher = FILE_OR_MODULE_PATTERN.matcher(srcText) + if (!matcher.find()) { + // There is only one file in the input + result.add(TestFile(srcFile.name, "$outputDirectory/${srcFile.name}", srcText)) + } else { + // There are several files + var processedChars = 0 + var module: TestModule = TestModule.default + var nextFileExists = true + while (nextFileExists) { + var moduleName = matcher.group(1) + val moduleDependencies = matcher.group(2) + val moduleFriends = matcher.group(3) + + if (moduleName != null) { + moduleName = moduleName.trim { it <= ' ' } + module = TestModule("${srcFile.name}.$moduleName", + moduleDependencies.parseModuleList().map { + if (it != "support") "${srcFile.name}.$it" else it + }, + moduleFriends.parseModuleList().map { "${srcFile.name}.$it" }) + } + + val fileName = matcher.group(4) + val filePath = "$outputDirectory/$fileName" + val start = processedChars + nextFileExists = matcher.find() + val end = if (nextFileExists) matcher.start() else srcText.length + val fileText = srcText.substring(start, end) + processedChars = end + if (fileName.endsWith(".kt")) { + result.add(TestFile(fileName, filePath, fileText, module)) + } + } + } + return result +} + +private fun String?.parseModuleList() = this + ?.split(Pattern.compile(MODULE_DELIMITER), 0) + ?: emptyList() + +/** + * Test module from the test source declared by the [FILE_OR_MODULE_PATTERN]. + * Module should have a [name] and could have [dependencies] on other modules and [friends]. + * + * There are 2 predefined modules: + * - [default] that contains all sources that don't declare a module, + * - [support] for a helper sources like Coroutines support. + */ +data class TestModule( + val name: String, + val dependencies: List, + val friends: List +) { + fun isDefaultModule() = this == default || name.endsWith(".main") + + companion object { + val default = TestModule("default", emptyList(), emptyList()) + val support = TestModule("support", emptyList(), emptyList()) + } +} + +/** + * Represent a single test file that belongs to the [module]. + */ +data class TestFile(val name: String, + val path: String, + var text: String = "", + val module: TestModule = TestModule.default +) { + /** + * Writes [text] to the file created from the [path]. + */ + fun writeTextToFile() { + Paths.get(path).takeUnless { text.isEmpty() }?.run { + parent.toFile() + .takeUnless { it.exists() } + ?.mkdirs() + toFile().writeText(text) + } + } +} diff --git a/kotlin-native/build-tools/src/main/kotlin/org/jetbrains/kotlin/Utils.kt b/kotlin-native/build-tools/src/main/kotlin/org/jetbrains/kotlin/Utils.kt new file mode 100644 index 00000000000..ee556923507 --- /dev/null +++ b/kotlin-native/build-tools/src/main/kotlin/org/jetbrains/kotlin/Utils.kt @@ -0,0 +1,351 @@ +/* + * Copyright 2010-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +package org.jetbrains.kotlin + +import org.gradle.api.Project +import org.gradle.api.Task +import org.jetbrains.kotlin.konan.properties.loadProperties +import org.jetbrains.kotlin.konan.properties.propertyList +import org.jetbrains.kotlin.konan.properties.saveProperties +import org.jetbrains.kotlin.konan.target.* +import org.jetbrains.kotlin.library.KLIB_PROPERTY_NATIVE_TARGETS +import java.io.File +import java.util.concurrent.TimeUnit +import java.net.HttpURLConnection +import java.net.URL +import java.util.Base64 +import org.jetbrains.report.json.* +import java.nio.file.Path +import org.jetbrains.kotlin.konan.file.File as KFile + +//region Project properties. + +val Project.platformManager + get() = findProperty("platformManager") as PlatformManager + +val Project.testTarget + get() = findProperty("target") as KonanTarget + +val Project.verboseTest + get() = hasProperty("test_verbose") + +val Project.testOutputRoot + get() = findProperty("testOutputRoot") as String + +val Project.testOutputLocal + get() = (findProperty("testOutputLocal") as File).toString() + +val Project.testOutputStdlib + get() = (findProperty("testOutputStdlib") as File).toString() + +val Project.testOutputFramework + get() = (findProperty("testOutputFramework") as File).toString() + +val Project.testOutputExternal + get() = (findProperty("testOutputExternal") as File).toString() + +val Project.kotlinNativeDist + get() = this.rootProject.file(this.findProperty("org.jetbrains.kotlin.native.home") + ?: this.findProperty("konan.home") ?: "dist") + +@Suppress("UNCHECKED_CAST") +val Project.globalTestArgs: List + get() = with(findProperty("globalTestArgs")) { + if (this is Array<*>) this.toList() as List + else this as List + } + +val Project.testTargetSupportsCodeCoverage: Boolean + get() = this.testTarget.supportsCodeCoverage() + +//endregion + +/** + * Ad-hoc signing of the specified path. + */ +fun codesign(project: Project, path: String) { + check(HostManager.hostIsMac) { "Apple specific code signing" } + val (stdOut, stdErr, exitCode) = runProcess(executor = localExecutor(project), executable = "/usr/bin/codesign", + args = listOf("--verbose", "-s", "-", path)) + check(exitCode == 0) { """ + |Codesign failed with exitCode: $exitCode + |stdout: $stdOut + |stderr: $stdErr + """.trimMargin() + } +} + +/** + * Creates a list of file paths to be compiled from the given [compile] list with regard to [exclude] list. + */ +fun Project.getFilesToCompile(compile: List, exclude: List): List { + // convert exclude list to paths + val excludeFiles = exclude.map { project.file(it).absolutePath }.toList() + + // create list of tests to compile + return compile.flatMap { f -> + project.file(f) + .walk() + .filter { it.isFile && it.name.endsWith(".kt") && !excludeFiles.contains(it.absolutePath) } + .map{ it.absolutePath } + .asIterable() + } +} + +//region Task dependency. + +fun Project.findKonanBuildTask(artifact: String, target: KonanTarget): Task = + tasks.getByName("compileKonan${artifact.capitalize()}${target.name.capitalize()}") + +fun Project.dependsOnDist(taskName: String) { + project.tasks.getByName(taskName).dependsOnDist() +} + +fun Task.dependsOnDist() { + val rootTasks = project.rootProject.tasks + // We don't build the compiler if a custom dist path is specified. + if (!(project.findProperty("useCustomDist") as Boolean)) { + dependsOn(rootTasks.getByName("dist")) + val target = project.testTarget + if (target != HostManager.host) { + // if a test_target property is set then tests should depend on a crossDist + // otherwise, runtime components would not be build for a target. + dependsOn(rootTasks.getByName("${target.name}CrossDist")) + } + } +} + +/** + * Sets the same dependencies for the receiver task from the given [task] + */ +fun String.sameDependenciesAs(task: Task) { + val t = task.project.tasks.getByName(this) + t.sameDependenciesAs(task) +} + +/** + * Sets the same dependencies for the receiver task from the given [task] + */ +fun Task.sameDependenciesAs(task: Task) { + val dependencies = task.dependsOn.toList() // save to the list, otherwise it will cause cyclic dependency. + this.dependsOn(dependencies) +} + +/** + * Set dependency on [artifact] built by the Konan Plugin for the receiver task, + * also make [artifact] depend on `dist` and all dependencies of the task to make [artifact] execute before the task. + */ +fun Task.dependsOnKonanBuildingTask(artifact: String, target: KonanTarget) { + val buildTask = project.findKonanBuildTask(artifact, target) + buildTask.dependsOnDist() + buildTask.sameDependenciesAs(this) + dependsOn(buildTask) +} + +//endregion +// Run command line from string. +fun Array.runCommand(workingDir: File = File("."), + timeoutAmount: Long = 60, + timeoutUnit: TimeUnit = TimeUnit.SECONDS): String { + return try { + ProcessBuilder(*this) + .directory(workingDir) + .redirectOutput(ProcessBuilder.Redirect.PIPE) + .redirectError(ProcessBuilder.Redirect.PIPE) + .start().apply { + waitFor(timeoutAmount, timeoutUnit) + }.inputStream.bufferedReader().readText() + } catch (e: Exception) { + println("Couldn't run command ${this.joinToString(" ")}") + println(e.stackTrace.joinToString("\n")) + error(e.message!!) + } +} + +fun String.splitCommaSeparatedOption(optionName: String) = + split("\\s*,\\s*".toRegex()).map { + if (it.isNotEmpty()) listOf(optionName, it) else listOf(null) + }.flatten().filterNotNull() + +data class Commit(val revision: String, val developer: String, val webUrlWithDescription: String) + +val teamCityUrl = "http://buildserver.labs.intellij.net" + +// List of commits. +class CommitsList(data: JsonElement): ConvertedFromJson { + + val commits: List + + init { + if (data !is JsonObject) { + error("Commits description is expected to be a json object!") + } + val changesElement = data.getOptionalField("change") + commits = changesElement?.let { + if (changesElement !is JsonArray) { + error("Change field is expected to be an array. Please, check source.") + } + changesElement.jsonArray.map { + with(it as JsonObject) { + Commit(elementToString(getRequiredField("version"), "version"), + elementToString(getRequiredField("username"), "username"), + elementToString(getRequiredField("webUrl"), "webUrl") + ) + } + } + } ?: listOf() + } +} + +fun buildsUrl(buildLocator: String) = + "$teamCityUrl/app/rest/builds/?locator=$buildLocator" + +fun getBuild(buildLocator: String, user: String, password: String) = + try { + sendGetRequest(buildsUrl(buildLocator), user, password) + } catch (t: Throwable) { + error("Try to get build! TeamCity is unreachable!") + } + +fun sendGetRequest(url: String, username: String? = null, password: String? = null) : String { + val connection = URL(url).openConnection() as HttpURLConnection + if (username != null && password != null) { + val auth = Base64.getEncoder().encode(("$username:$password").toByteArray()).toString(Charsets.UTF_8) + connection.addRequestProperty("Authorization", "Basic $auth") + } + connection.setRequestProperty("Accept", "application/json"); + connection.connect() + return connection.inputStream.use { it.reader().use { reader -> reader.readText() } } +} + +fun getBuildProperty(buildJsonDescription: String, property: String) = + with(JsonTreeParser.parse(buildJsonDescription) as JsonObject) { + if (getPrimitive("count").int == 0) { + error("No build information on TeamCity for $buildJsonDescription!") + } + (getArray("build").getObject(0).getPrimitive(property) as JsonLiteral).unquoted() + } + +@JvmOverloads +fun compileSwift(project: Project, target: KonanTarget, sources: List, options: List, + output: Path, fullBitcode: Boolean = false) { + val platform = project.platformManager.platform(target) + assert(platform.configurables is AppleConfigurables) + val configs = platform.configurables as AppleConfigurables + val compiler = configs.absoluteTargetToolchain + "/usr/bin/swiftc" + + val swiftTarget = when (target) { + KonanTarget.IOS_X64 -> "x86_64-apple-ios" + configs.osVersionMin + KonanTarget.IOS_ARM32 -> "armv7-apple-ios" + configs.osVersionMin + KonanTarget.IOS_ARM64 -> "arm64-apple-ios" + configs.osVersionMin + KonanTarget.TVOS_X64 -> "x86_64-apple-tvos" + configs.osVersionMin + KonanTarget.TVOS_ARM64 -> "arm64-apple-tvos" + configs.osVersionMin + KonanTarget.MACOS_X64 -> "x86_64-apple-macosx" + configs.osVersionMin + KonanTarget.WATCHOS_X86 -> "i386-apple-watchos" + configs.osVersionMin + KonanTarget.WATCHOS_X64 -> "x86_64-apple-watchos" + configs.osVersionMin + else -> throw IllegalStateException("Test target $target is not supported") + } + + val args = listOf("-sdk", configs.absoluteTargetSysRoot, "-target", swiftTarget) + + options + "-o" + output.toString() + sources + + if (fullBitcode) listOf("-embed-bitcode", "-Xlinker", "-bitcode_verify") else listOf("-embed-bitcode-marker") + + val (stdOut, stdErr, exitCode) = runProcess(executor = localExecutor(project), executable = compiler, args = args) + + println(""" + |$compiler finished with exit code: $exitCode + |options: ${args.joinToString(separator = " ")} + |stdout: $stdOut + |stderr: $stdErr + """.trimMargin()) + check(exitCode == 0) { "Compilation failed" } + check(output.toFile().exists()) { "Compiler swiftc hasn't produced an output file: $output" } +} + +fun targetSupportsMimallocAllocator(targetName: String) = + HostManager().targetByName(targetName).supportsMimallocAllocator() + +fun Project.mergeManifestsByTargets(source: File, destination: File) { + logger.info("Merging manifests: $source -> $destination") + + val sourceFile = KFile(source.absolutePath) + val sourceProperties = sourceFile.loadProperties() + + val destinationFile = KFile(destination.absolutePath) + val destinationProperties = destinationFile.loadProperties() + + // check that all properties except for KLIB_PROPERTY_NATIVE_TARGETS are equivalent + val mismatchedProperties = (sourceProperties.keys + destinationProperties.keys) + .asSequence() + .map { it.toString() } + .filter { it != KLIB_PROPERTY_NATIVE_TARGETS } + .sorted() + .mapNotNull { propertyKey: String -> + val sourceProperty: String? = sourceProperties.getProperty(propertyKey) + val destinationProperty: String? = destinationProperties.getProperty(propertyKey) + when { + sourceProperty == null -> "\"$propertyKey\" is absent in $sourceFile" + destinationProperty == null -> "\"$propertyKey\" is absent in $destinationFile" + sourceProperty == destinationProperty -> { + // properties match, OK + null + } + sourceProperties.propertyList(propertyKey, escapeInQuotes = true).toSet() == + destinationProperties.propertyList(propertyKey, escapeInQuotes = true).toSet() -> { + // properties match, OK + null + } + else -> "\"$propertyKey\" differ: [$sourceProperty] vs [$destinationProperty]" + } + } + .toList() + + check(mismatchedProperties.isEmpty()) { + buildString { + appendln("Found mismatched properties while merging manifest files: $source -> $destination") + mismatchedProperties.joinTo(this, "\n") + } + } + + // merge KLIB_PROPERTY_NATIVE_TARGETS property + val sourceNativeTargets = sourceProperties.propertyList(KLIB_PROPERTY_NATIVE_TARGETS) + val destinationNativeTargets = destinationProperties.propertyList(KLIB_PROPERTY_NATIVE_TARGETS) + + val mergedNativeTargets = HashSet().apply { + addAll(sourceNativeTargets) + addAll(destinationNativeTargets) + } + + destinationProperties[KLIB_PROPERTY_NATIVE_TARGETS] = mergedNativeTargets.joinToString(" ") + + destinationFile.saveProperties(destinationProperties) +} + +fun Project.buildStaticLibrary(cSources: Collection, output: File, objDir: File) { + delete(objDir) + delete(output) + + val platform = platformManager.platform(testTarget) + + objDir.mkdirs() + exec { + it.commandLine(platform.clang.clangC( + "-c", + *cSources.map { it.absolutePath }.toTypedArray() + )) + it.workingDir(objDir) + } + + output.parentFile.mkdirs() + exec { + it.commandLine( + "${platform.configurables.absoluteLlvmHome}/bin/llvm-ar", + "-rc", + output, + *fileTree(objDir).files.toTypedArray() + ) + } +} \ No newline at end of file diff --git a/kotlin-native/build-tools/src/main/kotlin/org/jetbrains/kotlin/Wrappers.kt b/kotlin-native/build-tools/src/main/kotlin/org/jetbrains/kotlin/Wrappers.kt new file mode 100644 index 00000000000..b37b3acd8e0 --- /dev/null +++ b/kotlin-native/build-tools/src/main/kotlin/org/jetbrains/kotlin/Wrappers.kt @@ -0,0 +1,53 @@ +package org.jetbrains.kotlin + +import org.gradle.api.Plugin +import org.gradle.api.Project +import org.gradle.api.tasks.Input +import org.gradle.api.tasks.Optional +import org.gradle.api.tasks.wrapper.Wrapper + +open class CustomWrapper : Wrapper() { + internal lateinit var mainWrapperTask: Wrapper + + val mainWrapperVersion: String + @Input get() = mainWrapperTask.gradleVersion + val mainWrapperDistrSha256: String? + @Optional @Input get() = mainWrapperTask.distributionSha256Sum +} + +open class WrappersExtension { + var projects = mutableListOf() + var distributionType = Wrapper.DistributionType.BIN +} + +class GradleWrappers : Plugin { + + override fun apply(project: Project): Unit = with(project) { + val mainWrapperTask = tasks.findByName("wrapper") as? Wrapper ?: return@with + val wrappers = extensions.create( + WrappersExtension::class.java, + "wrappers", + WrappersExtension::class.java + ) + afterEvaluate { + wrappers.projects.map { file(it) }.forEach { + tasks.create("${it.name}Wrapper", CustomWrapper::class.java).apply { + this.mainWrapperTask = mainWrapperTask + jarFile = it.resolve("gradle/wrapper/gradle-wrapper.jar") + scriptFile = it.resolve("gradlew") + distributionType = wrappers.distributionType + mainWrapperTask.dependsOn(this) + + // Get these parameters from the main wrapper task to support + // command line options like --gradle-version. + // Gradle doesn't provide access to the values passed in command line + // at the configuration phase, so we have to get these values at the execution phase. + doFirst { + gradleVersion = mainWrapperVersion + distributionSha256Sum = mainWrapperDistrSha256 + } + } + } + } + } +} diff --git a/kotlin-native/build-tools/src/main/kotlin/org/jetbrains/kotlin/XcRunRuntimeUtils.kt b/kotlin-native/build-tools/src/main/kotlin/org/jetbrains/kotlin/XcRunRuntimeUtils.kt new file mode 100644 index 00000000000..84828a6723b --- /dev/null +++ b/kotlin-native/build-tools/src/main/kotlin/org/jetbrains/kotlin/XcRunRuntimeUtils.kt @@ -0,0 +1,67 @@ +package org.jetbrains.kotlin + +import com.google.gson.annotations.Expose +import org.jetbrains.kotlin.konan.target.KonanTarget +import org.jetbrains.kotlin.konan.target.Xcode +import kotlin.math.min + +/** + * Compares two strings assuming that both are representing numeric version strings. + * Examples of numeric version strings: "12.4.1.2", "9", "0.5". + */ +private fun compareStringsAsVersions(version1: String, version2: String): Int { + val version1 = version1.split('.').map { it.toInt() } + val version2 = version2.split('.').map { it.toInt() } + val minimalLength = min(version1.size, version2.size) + for (index in 0 until minimalLength) { + if (version1[index] < version2[index]) return -1 + if (version1[index] > version2[index]) return 1 + } + return version1.size.compareTo(version2.size) +} + +/** + * Returns parsed output of `xcrun simctl list runtimes -j`. + */ +private fun Xcode.getSimulatorRuntimeDescriptors(): List = gson.fromJson(simulatorRuntimes, ListRuntimesReport::class.java).runtimes + +/** + * Returns first available simulator runtime for [target] with at least [osMinVersion] OS version. + * */ +fun Xcode.getLatestSimulatorRuntimeFor(target: KonanTarget, osMinVersion: String): SimulatorRuntimeDescriptor? { + val osName = when (target) { + KonanTarget.IOS_X64 -> "iOS" + KonanTarget.WATCHOS_X64, KonanTarget.WATCHOS_X86 -> "watchOS" + KonanTarget.TVOS_X64 -> "tvOS" + else -> error("Unexpected simulator target: $target") + } + return getSimulatorRuntimeDescriptors().firstOrNull { + it.checkAvailability() && it.name.startsWith(osName) && compareStringsAsVersions(it.version, osMinVersion) >= 0 + } +} + +// Result of `xcrun simctl list runtimes -j`. +data class ListRuntimesReport( + @Expose val runtimes: List +) + +data class SimulatorRuntimeDescriptor( + @Expose val version: String, + // bundlePath field may not exist in the old Xcode (prior to 10.3). + @Expose val bundlePath: String? = null, + @Expose val isAvailable: Boolean? = null, + @Expose val availability: String? = null, + @Expose val name: String, + @Expose val identifier: String, + @Expose val buildversion: String +) { + /** + * Different Xcode/macOS combinations give different fields that checks + * runtime availability. This method is an umbrella for these fields. + */ + fun checkAvailability(): Boolean { + if (isAvailable == true) return true + if (availability?.contains("unavailable") == true) return false + return false + } +} diff --git a/kotlin-native/build-tools/src/main/kotlin/org/jetbrains/kotlin/benchmark/BenchmarkLogger.kt b/kotlin-native/build-tools/src/main/kotlin/org/jetbrains/kotlin/benchmark/BenchmarkLogger.kt new file mode 100644 index 00000000000..4e13ca68b79 --- /dev/null +++ b/kotlin-native/build-tools/src/main/kotlin/org/jetbrains/kotlin/benchmark/BenchmarkLogger.kt @@ -0,0 +1,25 @@ +package org.jetbrains.kotlin.benchmark + +import java.text.SimpleDateFormat +import java.util.* + +enum class LogLevel { DEBUG, OFF } + +class Logger(val level: LogLevel = LogLevel.OFF) { + private fun printStderr(message: String) { + System.err.print(message) + } + + private fun currentTime(): String = + SimpleDateFormat("HH:mm:ss").format(Date()) + + fun log(message: String, messageLevel: LogLevel = LogLevel.DEBUG, usePrefix: Boolean = true) { + if (messageLevel == level) { + if (usePrefix) { + printStderr("[$level][${currentTime()}] $message") + } else { + printStderr("$message") + } + } + } +} \ No newline at end of file diff --git a/kotlin-native/build-tools/src/main/kotlin/org/jetbrains/kotlin/benchmark/BenchmarkingPlugin.kt b/kotlin-native/build-tools/src/main/kotlin/org/jetbrains/kotlin/benchmark/BenchmarkingPlugin.kt new file mode 100644 index 00000000000..49012e52e60 --- /dev/null +++ b/kotlin-native/build-tools/src/main/kotlin/org/jetbrains/kotlin/benchmark/BenchmarkingPlugin.kt @@ -0,0 +1,278 @@ +package org.jetbrains.kotlin.benchmark + +import groovy.lang.Closure +import org.gradle.api.NamedDomainObjectContainer +import org.gradle.api.Plugin +import org.gradle.api.Project +import org.gradle.api.Task +import org.gradle.api.artifacts.Dependency +import org.gradle.util.ConfigureUtil +import org.jetbrains.kotlin.* +import org.jetbrains.kotlin.gradle.plugin.KotlinSourceSet +import org.jetbrains.kotlin.gradle.plugin.mpp.KotlinNativeTarget +import org.jetbrains.kotlin.gradle.plugin.mpp.AbstractKotlinNativeTargetPreset +import org.jetbrains.kotlin.gradle.plugin.mpp.NativeBuildType +import org.jetbrains.kotlin.konan.target.HostManager +import javax.inject.Inject +import kotlin.reflect.KClass + +internal val NamedDomainObjectContainer.commonMain + get() = maybeCreate("commonMain") + +internal val NamedDomainObjectContainer.nativeMain + get() = maybeCreate("nativeMain") + +internal val Project.nativeWarmup: Int + get() = (property("nativeWarmup") as String).toInt() + +internal val Project.attempts: Int + get() = (property("attempts") as String).toInt() + +internal val Project.nativeBenchResults: String + get() = property("nativeBenchResults") as String + +// Gradle property to add flags to benchmarks run from command line. +internal val Project.compilerArgs: List + get() = (findProperty("compilerArgs") as String?)?.split("\\s").orEmpty() + +internal val Project.kotlinVersion: String + get() = property("kotlinVersion") as String + +internal val Project.konanVersion: String + get() = property("konanVersion") as String + +internal val Project.kotlinStdlibVersion: String + get() = property("kotlinStdlibVersion") as String + +internal val Project.kotlinStdlibRepo: String + get() = property("kotlinStdlibRepo") as String + +internal val Project.nativeJson: String + get() = project.property("nativeJson") as String + +internal val Project.jvmJson: String + get() = project.property("jvmJson") as String + +internal val Project.commonBenchmarkProperties: Map + get() = mapOf( + "cpu" to System.getProperty("os.arch"), + "os" to System.getProperty("os.name"), + "jdkVersion" to System.getProperty("java.version"), + "jdkVendor" to System.getProperty("java.vendor"), + "kotlinVersion" to kotlinVersion + ) + +open class BenchmarkExtension @Inject constructor(val project: Project) { + var applicationName: String = project.name + var commonSrcDirs: Collection = emptyList() + var nativeSrcDirs: Collection = emptyList() + var compileTasks: List = emptyList() + var linkerOpts: Collection = emptyList() + var compilerOpts: List = emptyList() + var buildType: NativeBuildType = NativeBuildType.RELEASE + var repeatingType: BenchmarkRepeatingType = BenchmarkRepeatingType.INTERNAL + + val dependencies: BenchmarkDependencies = BenchmarkDependencies() + + fun dependencies(action: BenchmarkDependencies.() -> Unit) = + dependencies.action() + + fun dependencies(action: Closure<*>) { + ConfigureUtil.configure(action, dependencies) + } + + inner class BenchmarkDependencies { + public val sourceSets: NamedDomainObjectContainer + get() = project.kotlin.sourceSets + + fun project(path: String): Dependency = project.dependencies.project(mapOf("path" to path)) + + fun project(path: String, configuration: String): Dependency = + project.dependencies.project(mapOf("path" to path, "configuration" to configuration)) + + fun common(notation: Any) = sourceSets.commonMain.dependencies { + implementation(notation) + } + + fun native(notation: Any) = sourceSets.nativeMain.dependencies { + implementation(notation) + } + } +} + +/** + * A plugin configuring a benchmark Kotlin/Native project. + */ +abstract class BenchmarkingPlugin: Plugin { + protected abstract val Project.nativeExecutable: String + protected abstract val Project.nativeLinkTask: Task + protected abstract val Project.benchmark: BenchmarkExtension + protected abstract val benchmarkExtensionName: String + protected abstract val benchmarkExtensionClass: KClass<*> + + protected val mingwPath: String = System.getenv("MINGW64_DIR") ?: "c:/msys64/mingw64" + + protected open fun Project.determinePreset(): AbstractKotlinNativeTargetPreset<*> = + defaultHostPreset(this).also { preset -> + logger.quiet("$project has been configured for ${preset.name} platform.") + } as AbstractKotlinNativeTargetPreset<*> + + protected abstract fun NamedDomainObjectContainer.configureSources(project: Project) + + protected open fun NamedDomainObjectContainer.additionalConfigurations(project: Project) {} + + protected open fun Project.configureSourceSets(kotlinVersion: String) { + with(kotlin.sourceSets) { + commonMain.dependencies { + implementation("org.jetbrains.kotlin:kotlin-stdlib-common:$kotlinStdlibVersion") + } + + project.configurations.getByName(nativeMain.implementationConfigurationName).apply { + // Exclude dependencies already included into K/N distribution (aka endorsed libraries). + exclude(mapOf("module" to "kotlinx.cli")) + } + + repositories.maven { + it.setUrl(kotlinStdlibRepo) + } + + additionalConfigurations(this@configureSourceSets) + + // Add sources specified by a user in the benchmark DSL. + afterEvaluate { + configureSources(project) + } + } + } + + protected open fun KotlinNativeTarget.configureNativeOutput(project: Project) { + binaries.executable(NATIVE_EXECUTABLE_NAME, listOf(project.benchmark.buildType)) { + if (HostManager.hostIsMingw) { + linkerOpts.add("-L${mingwPath}/lib") + } + + runTask!!.apply { + group = "" + enabled = false + } + + // Specify settings configured by a user in the benchmark extension. + project.afterEvaluate { + linkerOpts.addAll(project.benchmark.linkerOpts) + freeCompilerArgs = project.benchmark.compilerOpts + project.compilerArgs + } + } + } + + protected fun Project.configureNativeTarget(hostPreset: AbstractKotlinNativeTargetPreset<*>) { + kotlin.targetFromPreset(hostPreset, NATIVE_TARGET_NAME) { + compilations.getByName("main").kotlinOptions.freeCompilerArgs = benchmark.compilerOpts + project.compilerArgs + compilations.getByName("main").enableEndorsedLibs = true + configureNativeOutput(this@configureNativeTarget) + } + } + + protected open fun configureMPPExtension(project: Project) { + project.configureSourceSets(project.kotlinVersion) + project.configureNativeTarget(project.determinePreset()) + } + + protected open fun Project.configureNativeTask(nativeTarget: KotlinNativeTarget): Task { + val konanRun = createRunTask(this, "konanRun", nativeLinkTask, + nativeExecutable, buildDir.resolve(nativeBenchResults).absolutePath).apply { + group = BENCHMARKING_GROUP + description = "Runs the benchmark for Kotlin/Native." + } + afterEvaluate { + val task = konanRun as RunKotlinNativeTask + task.args("-p", "${benchmark.applicationName}::") + task.warmupCount = nativeWarmup + task.repeatCount = attempts + task.repeatingType = benchmark.repeatingType + } + return konanRun + } + + protected abstract fun Project.configureJvmTask(): Task + + protected fun compilerFlagsFromBinary(project: Project): List { + val result = mutableListOf() + if (project.benchmark.buildType.optimized) { + result.add("-opt") + } + if (project.benchmark.buildType.debuggable) { + result.add("-g") + } + return result + } + + protected open fun getCompilerFlags(project: Project, nativeTarget: KotlinNativeTarget) = + compilerFlagsFromBinary(project) + nativeTarget.compilations.main.kotlinOptions.freeCompilerArgs.map { "\"$it\"" } + + protected open fun Project.collectCodeSize(applicationName: String) = + getCodeSizeBenchmark(applicationName, nativeExecutable) + + protected open fun Project.configureKonanJsonTask(nativeTarget: KotlinNativeTarget): Task { + return tasks.create("konanJsonReport") { + it.group = BENCHMARKING_GROUP + it.description = "Builds the benchmarking report for Kotlin/Native." + + it.doLast { + val applicationName = benchmark.applicationName + val benchContents = buildDir.resolve(nativeBenchResults).readText() + val nativeCompileTime = if (benchmark.compileTasks.isEmpty()) getNativeCompileTime(project, applicationName) + else getNativeCompileTime(project, applicationName, benchmark.compileTasks) + + val properties = commonBenchmarkProperties + mapOf( + "type" to "native", + "compilerVersion" to konanVersion, + "flags" to getCompilerFlags(project, nativeTarget).sorted(), + "benchmarks" to benchContents, + "compileTime" to listOf(nativeCompileTime), + "codeSize" to collectCodeSize(applicationName) + ) + + val output = createJsonReport(properties) + buildDir.resolve(nativeJson).writeText(output) + } + } + } + + protected abstract fun Project.configureJvmJsonTask(jvmRun: Task): Task + + protected open fun Project.configureExtraTasks() {} + + private fun Project.configureTasks() { + val nativeTarget = kotlin.targets.getByName(NATIVE_TARGET_NAME) as KotlinNativeTarget + configureExtraTasks() + // Native run task. + configureNativeTask(nativeTarget) + + // JVM run task. + val jvmRun = configureJvmTask() + + // Native report task. + configureKonanJsonTask(nativeTarget) + + // JVM report task. + configureJvmJsonTask(jvmRun) + } + + override fun apply(target: Project) = with(target) { + pluginManager.apply("kotlin-multiplatform") + + // Use Kotlin compiler version specified by the project property. + dependencies.add("kotlinCompilerClasspath", "org.jetbrains.kotlin:kotlin-compiler-embeddable:$kotlinVersion") + addTimeListener(this) + + extensions.create(benchmarkExtensionName, benchmarkExtensionClass.java, this) + configureMPPExtension(this) + configureTasks() + } + + companion object { + const val NATIVE_TARGET_NAME = "native" + const val NATIVE_EXECUTABLE_NAME = "benchmark" + const val BENCHMARKING_GROUP = "benchmarking" + } +} diff --git a/kotlin-native/build-tools/src/main/kotlin/org/jetbrains/kotlin/benchmark/CompileBenchmarkingPlugin.kt b/kotlin-native/build-tools/src/main/kotlin/org/jetbrains/kotlin/benchmark/CompileBenchmarkingPlugin.kt new file mode 100644 index 00000000000..79ca911f97c --- /dev/null +++ b/kotlin-native/build-tools/src/main/kotlin/org/jetbrains/kotlin/benchmark/CompileBenchmarkingPlugin.kt @@ -0,0 +1,148 @@ +package org.jetbrains.kotlin.benchmark + +import groovy.lang.Closure +import org.gradle.api.* +import org.gradle.api.tasks.Delete +import org.gradle.api.tasks.Exec +import org.gradle.util.ConfigureUtil +import org.jetbrains.kotlin.* +import javax.inject.Inject + +class BuildStep (private val _name: String): Named { + override fun getName(): String = _name + lateinit var command: List + + fun command(vararg command: String) { + this.command = command.toList() + } +} + +class BuildStepContainer(project: Project): NamedDomainObjectContainer by project.container(BuildStep::class.java) { + fun step(name: String, configure: Action) = + maybeCreate(name).apply { configure.execute(this) } + + fun step(name: String, configure: Closure) = + step(name, ConfigureUtil.configureUsing(configure)) +} + +open class CompileBenchmarkExtension @Inject constructor(val project: Project) { + var applicationName = project.name + var repeatNumber: Int = 1 + var buildSteps: BuildStepContainer = BuildStepContainer(project) + var compilerOpts: List = emptyList() + + fun buildSteps(configure: Action): Unit = buildSteps.let { configure.execute(it) } + fun buildSteps(configure: Closure): Unit = buildSteps(ConfigureUtil.configureUsing(configure)) +} + +open class CompileBenchmarkingPlugin : Plugin { + + private val exitCodes: MutableMap = mutableMapOf() + + private fun Project.configureUtilityTasks() { + tasks.create("configureBuild") { + it.doLast { mkdir(buildDir) } + } + + tasks.create("clean", Delete::class.java) { + it.delete(buildDir) + } + } + + private fun Project.configureKonanRun( + benchmarkExtension: CompileBenchmarkExtension + ): Unit = with(benchmarkExtension) { + // Aggregate task. + val konanRun = tasks.create("konanRun") { task -> + task.dependsOn("configureBuild") + + task.group = BenchmarkingPlugin.BENCHMARKING_GROUP + task.description = "Runs the compile only benchmark for Kotlin/Native." + } + + // Compile tasks. + afterEvaluate { + for (number in 1..repeatNumber) { + buildSteps.forEach { step -> + val taskName = step.name + tasks.create("$taskName$number", Exec::class.java).apply { + commandLine(step.command) + isIgnoreExitValue = true + konanRun.dependsOn(this) + doLast { + exitCodes[name] = execResult!!.exitValue + } + } + } + } + } + + // Report task. + tasks.create("konanJsonReport").apply { + + group = BenchmarkingPlugin.BENCHMARKING_GROUP + description = "Builds the benchmarking report for Kotlin/Native." + + doLast { + val nativeCompileTime = getCompileBenchmarkTime( + project, + applicationName, + buildSteps.names, + repeatNumber, + exitCodes + ) + val nativeExecutable = buildDir.resolve("program${getNativeProgramExtension()}") + val properties = commonBenchmarkProperties + mapOf( + "type" to "native", + "compilerVersion" to konanVersion, + "benchmarks" to "[]", + "flags" to getCompilerFlags(benchmarkExtension).sorted(), + "compileTime" to nativeCompileTime, + "codeSize" to getCodeSizeBenchmark(applicationName, nativeExecutable.absolutePath) + ) + val output = createJsonReport(properties) + buildDir.resolve(nativeJson).writeText(output) + } + konanRun.finalizedBy(this) + } + } + + private fun getCompilerFlags(benchmarkExtension: CompileBenchmarkExtension) = + benchmarkExtension.compilerOpts + + private fun Project.configureJvmRun( + benchmarkExtension: CompileBenchmarkExtension + ) { + val jvmRun = tasks.create("jvmRun") { + it.group = BenchmarkingPlugin.BENCHMARKING_GROUP + it.description = "Runs the compile only benchmark for Kotlin/JVM." + it.doLast { println("JVM run isn't supported") } + } + + tasks.create("jvmJsonReport") { + it.group = BenchmarkingPlugin.BENCHMARKING_GROUP + it.description = "Builds the benchmarking report for Kotlin/Native." + it.doLast { println("JVM run isn't supported") } + jvmRun.finalizedBy(it) + } + } + + override fun apply(target: Project): Unit = with(target) { + addTimeListener(this) + + val benchmarkExtension = extensions.create( + COMPILE_BENCHMARK_EXTENSION_NAME, + CompileBenchmarkExtension::class.java, + this + ) + + // Create tasks. + configureUtilityTasks() + configureKonanRun(benchmarkExtension) + configureJvmRun(benchmarkExtension) + } + + companion object { + const val COMPILE_BENCHMARK_EXTENSION_NAME = "compileBenchmark" + } +} diff --git a/kotlin-native/build-tools/src/main/kotlin/org/jetbrains/kotlin/benchmark/KotlinNativeBenchmarkingPlugin.kt b/kotlin-native/build-tools/src/main/kotlin/org/jetbrains/kotlin/benchmark/KotlinNativeBenchmarkingPlugin.kt new file mode 100644 index 00000000000..5dc4c5c4e02 --- /dev/null +++ b/kotlin-native/build-tools/src/main/kotlin/org/jetbrains/kotlin/benchmark/KotlinNativeBenchmarkingPlugin.kt @@ -0,0 +1,146 @@ +package org.jetbrains.kotlin.benchmark + +import org.gradle.jvm.tasks.Jar +import org.gradle.api.NamedDomainObjectContainer +import org.gradle.api.Project +import org.gradle.api.Task +import org.jetbrains.kotlin.* +import org.jetbrains.kotlin.gradle.plugin.KotlinSourceSet +import org.jetbrains.kotlin.gradle.plugin.mpp.Executable +import org.jetbrains.kotlin.gradle.plugin.mpp.KotlinNativeTarget +import org.jetbrains.kotlin.konan.target.HostManager +import javax.inject.Inject +import kotlin.reflect.KClass + +private val NamedDomainObjectContainer.jvmMain + get() = maybeCreate("jvmMain") + +private val Project.jvmWarmup: Int + get() = (property("jvmWarmup") as String).toInt() + +private val Project.jvmBenchResults: String + get() = property("jvmBenchResults") as String + +open class KotlinNativeBenchmarkExtension @Inject constructor(project: Project) : BenchmarkExtension(project) { + var jvmSrcDirs: Collection = emptyList() + var mingwSrcDirs: Collection = emptyList() + var posixSrcDirs: Collection = emptyList() + + fun BenchmarkExtension.BenchmarkDependencies.jvm(notation: Any) = sourceSets.jvmMain.dependencies { + implementation(notation) + } +} + +/** + * A plugin configuring a benchmark Kotlin/Native project. + */ +open class KotlinNativeBenchmarkingPlugin: BenchmarkingPlugin() { + override fun Project.configureJvmJsonTask(jvmRun: Task): Task { + return tasks.create("jvmJsonReport") { + it.group = BENCHMARKING_GROUP + it.description = "Builds the benchmarking report for Kotlin/JVM." + + it.doLast { + val applicationName = benchmark.applicationName + val jarPath = (tasks.getByName("jvmJar") as Jar).archiveFile.get().asFile + val jvmCompileTime = getJvmCompileTime(project, applicationName) + val benchContents = buildDir.resolve(jvmBenchResults).readText() + + val properties: Map = commonBenchmarkProperties + mapOf( + "type" to "jvm", + "compilerVersion" to kotlinVersion, + "benchmarks" to benchContents, + "compileTime" to listOf(jvmCompileTime), + "codeSize" to getCodeSizeBenchmark(applicationName, jarPath.absolutePath) + ) + + val output = createJsonReport(properties) + buildDir.resolve(jvmJson).writeText(output) + } + + jvmRun.finalizedBy(it) + } + } + + override fun Project.configureJvmTask(): Task { + return tasks.create("jvmRun", RunJvmTask::class.java) { task -> + task.dependsOn("jvmJar") + val mainCompilation = kotlin.jvm().compilations.getByName("main") + val runtimeDependencies = configurations.getByName(mainCompilation.runtimeDependencyConfigurationName) + task.classpath(files(mainCompilation.output.allOutputs, runtimeDependencies)) + task.main = "MainKt" + + task.group = BENCHMARKING_GROUP + task.description = "Runs the benchmark for Kotlin/JVM." + + // Specify settings configured by a user in the benchmark extension. + afterEvaluate { + task.args("-p", "${benchmark.applicationName}::") + task.warmupCount = jvmWarmup + task.repeatCount = attempts + task.outputFileName = buildDir.resolve(jvmBenchResults).absolutePath + task.repeatingType = benchmark.repeatingType + } + } + } + + override val benchmarkExtensionClass: KClass<*> + get() = KotlinNativeBenchmarkExtension::class + + override val Project.benchmark: KotlinNativeBenchmarkExtension + get() = extensions.getByName(benchmarkExtensionName) as KotlinNativeBenchmarkExtension + + override val benchmarkExtensionName: String = "benchmark" + + private val Project.nativeBinary: Executable + get() = (kotlin.targets.getByName(NATIVE_TARGET_NAME) as KotlinNativeTarget) + .binaries.getExecutable(NATIVE_EXECUTABLE_NAME, benchmark.buildType) + + override val Project.nativeExecutable: String + get() = nativeBinary.outputFile.absolutePath + + override val Project.nativeLinkTask: Task + get() = nativeBinary.linkTask + + override fun configureMPPExtension(project: Project) { + super.configureMPPExtension(project) + project.configureJVMTarget() + } + + override fun getCompilerFlags(project: Project, nativeTarget: KotlinNativeTarget) = + super.getCompilerFlags(project, nativeTarget) + project.nativeBinary.freeCompilerArgs.map { "\"$it\"" } + + override fun NamedDomainObjectContainer.configureSources(project: Project) { + project.benchmark.let { + commonMain.kotlin.srcDirs(*it.commonSrcDirs.toTypedArray()) + if (HostManager.hostIsMingw) { + nativeMain.kotlin.srcDirs(*(it.nativeSrcDirs + it.mingwSrcDirs).toTypedArray()) + } else { + nativeMain.kotlin.srcDirs(*(it.nativeSrcDirs + it.posixSrcDirs).toTypedArray()) + } + jvmMain.kotlin.srcDirs(*it.jvmSrcDirs.toTypedArray()) + } + } + + override fun NamedDomainObjectContainer.additionalConfigurations(project: Project) { + jvmMain.dependencies { + implementation("org.jetbrains.kotlin:kotlin-stdlib-jdk8:${project.kotlinStdlibVersion}") + } + } + + private fun Project.configureJVMTarget() { + kotlin.jvm { + compilations.all { + it.compileKotlinTask.kotlinOptions { + jvmTarget = "1.8" + suppressWarnings = true + freeCompilerArgs = project.benchmark.compilerOpts + project.compilerArgs + } + } + } + } + + companion object { + const val BENCHMARK_EXTENSION_NAME = "benchmark" + } +} diff --git a/kotlin-native/build-tools/src/main/kotlin/org/jetbrains/kotlin/benchmark/SwiftBenchmarkingPlugin.kt b/kotlin-native/build-tools/src/main/kotlin/org/jetbrains/kotlin/benchmark/SwiftBenchmarkingPlugin.kt new file mode 100644 index 00000000000..5f0c8bdadbb --- /dev/null +++ b/kotlin-native/build-tools/src/main/kotlin/org/jetbrains/kotlin/benchmark/SwiftBenchmarkingPlugin.kt @@ -0,0 +1,107 @@ +package org.jetbrains.kotlin.benchmark + +import org.gradle.api.NamedDomainObjectContainer +import org.gradle.api.Project +import org.gradle.api.Task +import org.jetbrains.kotlin.* +import org.jetbrains.kotlin.gradle.plugin.KotlinSourceSet +import org.jetbrains.kotlin.gradle.plugin.mpp.Framework +import org.jetbrains.kotlin.gradle.plugin.mpp.KotlinNativeTarget +import org.jetbrains.kotlin.gradle.plugin.mpp.AbstractKotlinNativeTargetPreset +import org.jetbrains.kotlin.gradle.plugin.mpp.NativeBuildType +import java.io.File +import javax.inject.Inject +import java.nio.file.Paths +import kotlin.reflect.KClass + +enum class CodeSizeEntity { FRAMEWORK, EXECUTABLE } + +open class SwiftBenchmarkExtension @Inject constructor(project: Project) : BenchmarkExtension(project) { + var swiftSources: List = emptyList() + var useCodeSize: CodeSizeEntity = CodeSizeEntity.FRAMEWORK // use as code size metric framework size or executable +} + +/** + * A plugin configuring a benchmark Kotlin/Native project. + */ +open class SwiftBenchmarkingPlugin : BenchmarkingPlugin() { + override fun Project.configureJvmJsonTask(jvmRun: Task): Task { + return tasks.create("jvmJsonReport") { + logger.info("JVM run is unsupported") + jvmRun.finalizedBy(it) + } + } + + override fun Project.configureJvmTask(): Task { + return tasks.create("jvmRun") { task -> + task.doLast { + logger.info("JVM run is unsupported") + } + } + } + + override val benchmarkExtensionClass: KClass<*> + get() = SwiftBenchmarkExtension::class + + override val Project.benchmark: SwiftBenchmarkExtension + get() = extensions.getByName(benchmarkExtensionName) as SwiftBenchmarkExtension + + override val benchmarkExtensionName: String = "swiftBenchmark" + + override val Project.nativeExecutable: String + get() = Paths.get(buildDir.absolutePath, benchmark.applicationName).toString() + + override val Project.nativeLinkTask: Task + get() = tasks.getByName("buildSwift") + + private lateinit var framework: Framework + val nativeFrameworkName = "benchmark" + + override fun NamedDomainObjectContainer.configureSources(project: Project) { + project.benchmark.let { + commonMain.kotlin.srcDirs(*it.commonSrcDirs.toTypedArray()) + nativeMain.kotlin.srcDirs(*(it.nativeSrcDirs).toTypedArray()) + } + } + + override fun Project.determinePreset(): AbstractKotlinNativeTargetPreset<*> = kotlin.presets.macosX64 as AbstractKotlinNativeTargetPreset<*> + + override fun KotlinNativeTarget.configureNativeOutput(project: Project) { + binaries.framework(nativeFrameworkName, listOf(project.benchmark.buildType)) { + // Specify settings configured by a user in the benchmark extension. + project.afterEvaluate { + linkerOpts.addAll(project.benchmark.linkerOpts) + } + } + } + + override fun Project.configureExtraTasks() { + val nativeTarget = kotlin.targets.getByName(NATIVE_TARGET_NAME) as KotlinNativeTarget + // Build executable from swift code. + framework = nativeTarget.binaries.getFramework(nativeFrameworkName, benchmark.buildType) + val buildSwift = tasks.create("buildSwift") { task -> + task.dependsOn(framework.linkTaskName) + task.doLast { + val frameworkParentDirPath = framework.outputDirectory.absolutePath + val options = listOf("-O", "-wmo", "-Xlinker", "-rpath", "-Xlinker", frameworkParentDirPath, "-F", frameworkParentDirPath) + compileSwift(project, nativeTarget.konanTarget, benchmark.swiftSources, options, + Paths.get(buildDir.absolutePath, benchmark.applicationName), false) + } + } + } + + override fun Project.collectCodeSize(applicationName: String) = + getCodeSizeBenchmark(applicationName, + if (benchmark.useCodeSize == CodeSizeEntity.FRAMEWORK) + File("${framework.outputFile.absolutePath}/$nativeFrameworkName").canonicalPath + else + nativeExecutable + ) + + override fun getCompilerFlags(project: Project, nativeTarget: KotlinNativeTarget) = + if (project.benchmark.useCodeSize == CodeSizeEntity.FRAMEWORK) { + super.getCompilerFlags(project, nativeTarget) + framework.freeCompilerArgs.map { "\"$it\"" } + } else { + listOf("-O", "-wmo") + } +} \ No newline at end of file diff --git a/kotlin-native/build-tools/src/main/kotlin/org/jetbrains/kotlin/bitcode/CompileToBitcode.kt b/kotlin-native/build-tools/src/main/kotlin/org/jetbrains/kotlin/bitcode/CompileToBitcode.kt new file mode 100644 index 00000000000..4cd0298ef37 --- /dev/null +++ b/kotlin-native/build-tools/src/main/kotlin/org/jetbrains/kotlin/bitcode/CompileToBitcode.kt @@ -0,0 +1,134 @@ +/* + * Copyright 2010-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the license/LICENSE.txt file. + */ + +package org.jetbrains.kotlin.bitcode + +import org.gradle.api.DefaultTask +import org.gradle.api.file.FileCollection +import org.gradle.api.tasks.* +import org.jetbrains.kotlin.ExecClang +import org.jetbrains.kotlin.konan.target.Family +import org.jetbrains.kotlin.konan.target.HostManager +import org.jetbrains.kotlin.konan.target.KonanTarget +import java.io.File +import javax.inject.Inject + +open class CompileToBitcode @Inject constructor( + val srcRoot: File, + val folderName: String, + val target: String, + val outputGroup: String +) : DefaultTask() { + + enum class Language { + C, CPP + } + + // Compiler args are part of compilerFlags so we don't register them as an input. + val compilerArgs = mutableListOf() + @Input + val linkerArgs = mutableListOf() + var excludeFiles: List = listOf( + "**/*Test.cpp", + "**/*Test.mm", + ) + var includeFiles: List = listOf( + "**/*.cpp", + "**/*.mm" + ) + + // Source files and headers are registered as inputs by the `inputFiles` and `headers` properties. + var srcDirs: FileCollection = project.files(srcRoot.resolve("cpp")) + var headersDirs: FileCollection = project.files(srcRoot.resolve("headers")) + + @Input + var skipLinkagePhase = false + + @Input + var language = Language.CPP + + private val targetDir by lazy { project.buildDir.resolve("bitcode/$outputGroup/$target") } + + val objDir by lazy { File(targetDir, folderName) } + + private val KonanTarget.isMINGW + get() = this.family == Family.MINGW + + val executable + get() = when (language) { + Language.C -> "clang" + Language.CPP -> "clang++" + } + + @get:Input + val compilerFlags: List + get() { + val commonFlags = listOf("-c", "-emit-llvm") + headersDirs.map { "-I$it" } + val languageFlags = when (language) { + Language.C -> + // Used flags provided by original build of allocator C code. + listOf("-std=gnu11", "-O3", "-Wall", "-Wextra", "-Werror") + Language.CPP -> + listOfNotNull("-std=c++14", "-Werror", "-O2", + "-Wall", "-Wextra", + "-Wno-unused-parameter", // False positives with polymorphic functions. + "-Wno-unused-function", // TODO: Enable this warning when we have C++ runtime tests. + "-fPIC".takeIf { !HostManager().targetByName(target).isMINGW }) + } + return commonFlags + languageFlags + compilerArgs + } + + @get:SkipWhenEmpty + @get:InputFiles + val inputFiles: Iterable + get() { + return srcDirs.flatMap { srcDir -> + project.fileTree(srcDir) { + it.include(includeFiles) + it.exclude(excludeFiles) + }.files + } + } + + @get:InputFiles + protected val headers: Iterable + get() { + return headersDirs.files.flatMap { dir -> + project.fileTree(dir) { + val includePatterns = when (language) { + Language.C -> arrayOf("**/.h") + Language.CPP -> arrayOf("**/*.h", "**/*.hpp") + } + it.include(*includePatterns) + }.files + } + } + + @OutputFile + val outFile = File(targetDir, "${folderName}.bc") + + @TaskAction + fun compile() { + objDir.mkdirs() + val plugin = project.convention.getPlugin(ExecClang::class.java) + + plugin.execKonanClang(target) { + it.workingDir = objDir + it.executable = executable + it.args = compilerFlags + inputFiles.map { it.absolutePath } + } + + if (!skipLinkagePhase) { + project.exec { + val llvmDir = project.findProperty("llvmDir") + it.executable = "$llvmDir/bin/llvm-link" + it.args = listOf("-o", outFile.absolutePath) + linkerArgs + + project.fileTree(objDir) { + it.include("**/*.bc") + }.files.map { it.absolutePath } + } + } + } +} \ No newline at end of file diff --git a/kotlin-native/build-tools/src/main/kotlin/org/jetbrains/kotlin/bitcode/CompileToBitcodePlugin.kt b/kotlin-native/build-tools/src/main/kotlin/org/jetbrains/kotlin/bitcode/CompileToBitcodePlugin.kt new file mode 100644 index 00000000000..85af1c8a588 --- /dev/null +++ b/kotlin-native/build-tools/src/main/kotlin/org/jetbrains/kotlin/bitcode/CompileToBitcodePlugin.kt @@ -0,0 +1,64 @@ +/* + * Copyright 2010-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the license/LICENSE.txt file. + */ + +package org.jetbrains.kotlin.bitcode + +import org.gradle.api.Plugin +import org.gradle.api.Project +import org.gradle.api.plugins.BasePlugin +import org.jetbrains.kotlin.createCompilationDatabasesFromCompileToBitcodeTasks +import java.io.File +import javax.inject.Inject + +/** + * A plugin creating extensions to compile + */ +open class CompileToBitcodePlugin: Plugin { + override fun apply(target: Project) = with(target) { + extensions.create(EXTENSION_NAME, CompileToBitcodeExtension::class.java, target) + + afterEvaluate { + // TODO: Support providers (https://docs.gradle.org/current/userguide/lazy_configuration.html) + // in database tasks and create them along with corresponding compile tasks (not in afterEvaluate). + createCompilationDatabasesFromCompileToBitcodeTasks(project, COMPILATION_DATABASE_TASK_NAME) + } + } + + companion object { + const val EXTENSION_NAME = "bitcode" + const val COMPILATION_DATABASE_TASK_NAME = "CompilationDatabase" + } +} + +open class CompileToBitcodeExtension @Inject constructor(val project: Project) { + + private val targetList = with(project) { + provider { rootProject.property("targetList") as List } // TODO: Can we make it better? + } + + fun create( + name: String, + srcDir: File = project.file("src/$name"), + outputGroup: String = "main", + configurationBlock: CompileToBitcode.() -> Unit = {} + ) { + targetList.get().forEach { targetName -> + project.tasks.register( + "${targetName}${name.snakeCaseToCamelCase().capitalize()}", + CompileToBitcode::class.java, + srcDir, name, targetName, outputGroup + ).configure { + it.group = BasePlugin.BUILD_GROUP + it.description = "Compiles '$name' to bitcode for $targetName" + it.configurationBlock() + } + } + } + + companion object { + private fun String.snakeCaseToCamelCase() = + split('_').joinToString(separator = "") { it.capitalize() } + } +} diff --git a/kotlin-native/build-tools/src/main/kotlin/org/jetbrains/kotlin/coroutineTestUtil.kt b/kotlin-native/build-tools/src/main/kotlin/org/jetbrains/kotlin/coroutineTestUtil.kt new file mode 100644 index 00000000000..00ef38be4d4 --- /dev/null +++ b/kotlin-native/build-tools/src/main/kotlin/org/jetbrains/kotlin/coroutineTestUtil.kt @@ -0,0 +1,144 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the license/LICENSE.txt file. + */ + +package org.jetbrains.kotlin + +// This is almost a full copy of kotlin/compiler/tests-common/tests/org/jetbrains/kotlin/coroutineTestUtil.kt +// TODO: get it automatically as a dependency +fun createTextForHelpers(isReleaseCoroutines: Boolean): String { + val coroutinesPackage = "kotlin.coroutines" + + val emptyContinuationBody = + if (isReleaseCoroutines) + """ + |override fun resumeWith(result: Result) { + | result.getOrThrow() + |} + """.trimMargin() + else + """ + |override fun resume(data: Any?) {} + |override fun resumeWithException(exception: Throwable) { throw exception } + """.trimMargin() + + val handleResultContinuationBody = + if (isReleaseCoroutines) + """ + |override fun resumeWith(result: Result) { + | x(result.getOrThrow()) + |} + """.trimMargin() + else + """ + |override fun resumeWithException(exception: Throwable) { + | throw exception + |} + | + |override fun resume(data: T) = x(data) + """.trimMargin() + + val handleExceptionContinuationBody = + if (isReleaseCoroutines) + """ + |override fun resumeWith(result: Result) { + | result.exceptionOrNull()?.let(x) + |} + """.trimMargin() + else + """ + |override fun resumeWithException(exception: Throwable) { + | x(exception) + |} + | + |override fun resume(data: Any?) {} + """.trimMargin() + + val continuationAdapterBody = + if (isReleaseCoroutines) + """ + |override fun resumeWith(result: Result) { + | if (result.isSuccess) { + | resume(result.getOrThrow()) + | } else { + | resumeWithException(result.exceptionOrNull()!!) + | } + |} + | + |abstract fun resumeWithException(exception: Throwable) + |abstract fun resume(value: T) + """.trimMargin() + else + "" + + return """ + |package helpers + |import $coroutinesPackage.* + | + |fun handleResultContinuation(x: (T) -> Unit): Continuation = object: Continuation { + | override val context = EmptyCoroutineContext + | $handleResultContinuationBody + |} + | + | + |fun handleExceptionContinuation(x: (Throwable) -> Unit): Continuation = object: Continuation { + | override val context = EmptyCoroutineContext + | $handleExceptionContinuationBody + |} + | + |open class EmptyContinuation(override val context: CoroutineContext = EmptyCoroutineContext) : Continuation { + | companion object : EmptyContinuation() + | $emptyContinuationBody + |} + | + |abstract class ContinuationAdapter : Continuation { + | override val context: CoroutineContext = EmptyCoroutineContext + | $continuationAdapterBody + |} + |class StateMachineCheckerClass { + | private var counter = 0 + | var finished = false + | + | var proceed: () -> Unit = {} + | + | fun reset() { + | counter = 0 + | finished = false + | proceed = {} + | } + | + | suspend fun suspendHere() = suspendCoroutine { c -> + | counter++ + | proceed = { c.resume(Unit) } + | } + | + | fun check(numberOfSuspensions: Int, checkFinished: Boolean = true) { + | for (i in 1..numberOfSuspensions) { + | if (counter != i) error("Wrong state-machine generated: suspendHere called should be called exactly once in one state. Expected " + i + ", got " + counter) + | proceed() + | } + | if (counter != numberOfSuspensions) + | error("Wrong state-machine generated: suspendHere called should be called exactly once in one state. Expected " + numberOfSuspensions + ", got " + counter) + | if (finished) error("Wrong state-machine generated: it is finished early") + | proceed() + | if (checkFinished && !finished) error("Wrong state-machine generated: it is not finished yet") + | } + |} + |val StateMachineChecker = StateMachineCheckerClass() + |object CheckStateMachineContinuation: ContinuationAdapter() { + | override val context: CoroutineContext + | get() = EmptyCoroutineContext + | + | override fun resume(value: Unit) { + | StateMachineChecker.proceed = { + | StateMachineChecker.finished = true + | } + | } + | + | override fun resumeWithException(exception: Throwable) { + | throw exception + | } + |} + """.trimMargin() +} diff --git a/kotlin-native/build-tools/src/main/kotlin/org/jetbrains/kotlin/genTestKT39548.kt b/kotlin-native/build-tools/src/main/kotlin/org/jetbrains/kotlin/genTestKT39548.kt new file mode 100644 index 00000000000..f8a7e3298e1 --- /dev/null +++ b/kotlin-native/build-tools/src/main/kotlin/org/jetbrains/kotlin/genTestKT39548.kt @@ -0,0 +1,37 @@ +package org.jetbrains.kotlin + +import java.io.File + +fun genTestKT39548(file: File) { + val longName = StringBuilder().apply { + repeat(10_000_000) { + append('a') + } + } + + val text = """ + import kotlin.test.* + + fun $longName(): Int = 42 + fun same(value: T): T = value + val globalInt1: Int = same(1) + val globalStringA: String = same("a") + @ThreadLocal val threadLocalInt2: Int = same(2) + @ThreadLocal val threadLocalStringB: String = same("b") + + fun main() { + // Ensure function don't get DCEd: + val resultOfFunctionWithLongName = $longName() + assertEquals(42, resultOfFunctionWithLongName) + + // Check that top-level initializers did run as expected: + assertEquals(1, globalInt1) + assertEquals("a", globalStringA) + assertEquals(2, threadLocalInt2) + assertEquals("b", threadLocalStringB) + } + """.trimIndent() + + file.parentFile.mkdirs() + file.writeText(text) +} diff --git a/kotlin-native/build-tools/src/main/kotlin/org/jetbrains/kotlin/klib/metadata/KmComparator.kt b/kotlin-native/build-tools/src/main/kotlin/org/jetbrains/kotlin/klib/metadata/KmComparator.kt new file mode 100644 index 00000000000..0a14a87e364 --- /dev/null +++ b/kotlin-native/build-tools/src/main/kotlin/org/jetbrains/kotlin/klib/metadata/KmComparator.kt @@ -0,0 +1,195 @@ +/* + * Copyright 2010-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ +package org.jetbrains.kotlin.klib.metadata + +import kotlinx.metadata.* +import kotlinx.metadata.klib.* + +/** + * Structural comparison of Km* metadata. + * [configuration] allows to tune comparison process. + * + */ +internal class KmComparator(private val configuration: ComparisonConfig) { + + fun compare(kmClass1: KmClass, kmClass2: KmClass): MetadataCompareResult = serialComparator( + compare(KmClass::name, ::compare) to "Different names: ${kmClass1.name}, ${kmClass2.name}", + ::compareClassFlags to "Different flags for ${kmClass1.name}", + compare(KmClass::constructors, compareLists(::compare)) to "Constructors mismatch for ${kmClass1.name}", + compare(KmClass::properties, compareLists(::compare, KmProperty::mangle)) to "Properties mismatch for ${kmClass1.name}", + compare(KmClass::functions, compareLists(::compare, KmFunction::mangle)) to "Functions mismatch for ${kmClass1.name}", + )(kmClass1, kmClass2) + + fun compare(typealias1: KmTypeAlias, typealias2: KmTypeAlias): MetadataCompareResult = serialComparator( + compare(KmTypeAlias::name, ::compare) to "Different names", + compare(KmTypeAlias::underlyingType, ::compareTypes) to "Underlying types mismatch", + compare(KmTypeAlias::expandedType, ::compareTypes) to "Expanded types mismatch", + compare(KmTypeAlias::typeParameters, compareLists(::compare)) to "Type parameters mismatch" + )(typealias1, typealias2) + + fun compare(function1: KmFunction, function2: KmFunction): MetadataCompareResult = serialComparator( + compare(KmFunction::name, ::compare) to "Different names", + compare(KmFunction::returnType, ::compareTypes) to "Return type mismatch", + compare(KmFunction::valueParameters, compareLists(::compare)) to "Value parameters mismatch", + ::compareFunctionFlags to "Flags mismatch" + )(function1, function2) + + fun compare(property1: KmProperty, property2: KmProperty): MetadataCompareResult = serialComparator( + compare(KmProperty::name, ::compare) to "Different names", + compare(KmProperty::returnType, ::compareTypes) to "Return type mismatch", + ::comparePropertyFlags to "Flags mismatch", + (compare(KmProperty::getterFlags, ::comparePropertyAccessorFlags) to "Getter flags mismatch") + .takeIf { Flag.Property.HAS_GETTER(property1.flags) && Flag.Property.HAS_GETTER(property2.flags) }, + (compare(KmProperty::setterFlags, ::comparePropertyAccessorFlags) to "Setter flags mismatch") + .takeIf { Flag.Property.HAS_SETTER(property1.flags) && Flag.Property.HAS_SETTER(property2.flags) } + )(property1, property2) + + private fun compare(entry1: KlibEnumEntry, entry2: KlibEnumEntry): MetadataCompareResult = serialComparator( + compare(KlibEnumEntry::annotations, compareLists(::compare)) to "Different annotations", + compare(KlibEnumEntry::name, ::compare) to "Different names", + compare(KlibEnumEntry::ordinal, compareNullable(::compare)) to "Different ordinals" + )(entry1, entry2) + + private fun checkFlag(flag: Flag, flagName: String? = null): (Flags, Flags) -> MetadataCompareResult = { f1, f2 -> + when { + flag(f1) != flag(f2) -> Fail("Flags mismatch: ${flag(f1)}, ${flag(f2)} for $flagName") + else -> Ok + } + } + + private fun compare(value1: Int, value2: Int): MetadataCompareResult = when { + value1 == value2 -> Ok + else -> Fail("$value1 != $value2") + } + + private fun compare(string1: String, string2: String): MetadataCompareResult = when { + string1 == string2 -> Ok + else -> Fail("$string1 != $string2") + } + + private fun compareFunctionFlags(function1: KmFunction, function2: KmFunction): MetadataCompareResult = + serialComparator( + checkFlag(Flag.Function.IS_EXTERNAL, "IS_EXTERNAL"), + checkFlag(Flag.Function.IS_DECLARATION, "IS_DECLARATION"), + ::compareVisibilityFlags, + ::compareModalityFlags + )(function1.flags, function2.flags) + + private fun comparePropertyFlags(property1: KmProperty, property2: KmProperty): MetadataCompareResult = + serialComparator( + checkFlag(Flag.Property.IS_CONST, "IS_CONST"), + checkFlag(Flag.Property.HAS_SETTER, "HAS_SETTER"), + checkFlag(Flag.Property.HAS_GETTER, "HAS_GETTER"), + checkFlag(Flag.Property.IS_VAR, "IS_VAR"), + checkFlag(Flag.Property.HAS_CONSTANT, "HAS_CONSTANT"), + checkFlag(Flag.Property.IS_DECLARATION, "IS_DECLARATION"), + checkFlag(Flag.Property.IS_EXTERNAL, "IS_EXTERNAL") + )(property1.flags, property2.flags) + + private fun comparePropertyAccessorFlags(flags1: Flags, flags2: Flags): MetadataCompareResult = serialComparator( + checkFlag(Flag.PropertyAccessor.IS_NOT_DEFAULT, "IS_NOT_DEFAULT"), + checkFlag(Flag.PropertyAccessor.IS_INLINE, "IS_INLINE"), + checkFlag(Flag.PropertyAccessor.IS_EXTERNAL, "IS_EXTERNAL"), + ::compareVisibilityFlags, + ::compareModalityFlags + )(flags1, flags2) + + + private fun compareClassFlags(class1: KmClass, class2: KmClass): MetadataCompareResult = serialComparator( + checkFlag(Flag.Class.IS_CLASS, "IS_CLASS"), + checkFlag(Flag.Class.IS_COMPANION_OBJECT, "IS_COMPANION_OBJECT"), + checkFlag(Flag.Class.IS_ENUM_CLASS, "IS_ENUM_CLASS"), + checkFlag(Flag.Class.IS_ENUM_ENTRY, "IS_ENUM_ENTRY"), + checkFlag(Flag.Class.IS_OBJECT, "IS_OBJECT"), + checkFlag(Flag.IS_FINAL, "IS_FINAL"), + checkFlag(Flag.IS_OPEN, "IS_OPEN"), + checkFlag(Flag.HAS_ANNOTATIONS, "HAS_ANNOTATIONS"), + ::compareVisibilityFlags, + ::compareModalityFlags + )(class1.flags, class2.flags) + + private fun compareVisibilityFlags(flags1: Flags, flags2: Flags): MetadataCompareResult = serialComparator( + checkFlag(Flag.IS_PUBLIC, "IS_PUBLIC"), + checkFlag(Flag.IS_PRIVATE_TO_THIS, "IS_PRIVATE_TO_THIS"), + checkFlag(Flag.IS_PRIVATE, "IS_PRIVATE"), + checkFlag(Flag.IS_PROTECTED, "IS_PROTECTED"), + checkFlag(Flag.IS_INTERNAL, "IS_INTERNAL") + )(flags1, flags2) + + private fun compareModalityFlags(flags1: Flags, flags2: Flags): MetadataCompareResult = serialComparator( + checkFlag(Flag.IS_FINAL, "IS_FINAL"), + checkFlag(Flag.IS_ABSTRACT, "IS_ABSTRACT"), + checkFlag(Flag.IS_OPEN, "IS_OPEN"), + checkFlag(Flag.IS_SEALED, "IS_SEALED") + )(flags1, flags2) + + private fun compare(annotation1: KmAnnotation, annotation2: KmAnnotation): MetadataCompareResult = when { + annotation1.className != annotation2.className -> Fail("${annotation1.className} != ${annotation2.className}") + // TODO: compare values + else -> Ok + } + + private fun compare(p1: KmValueParameter, p2: KmValueParameter): MetadataCompareResult = serialComparator( + compare(KmValueParameter::name, ::compare) to "Different names", + compare(KmValueParameter::type, compareNullable(::compareTypes)) to "Type mismatch", + compare(KmValueParameter::annotations, compareLists(::compare)) to "Annotations mismatch" + )(p1, p2) + + private fun compareTypeFlags(flags1: Flags, flags2: Flags): MetadataCompareResult = serialComparator( + checkFlag(Flag.Type.IS_NULLABLE) to "Nullable flag mismatch", + checkFlag(Flag.Type.IS_SUSPEND) to "Suspend flag mismatch" + )(flags1, flags2) + + private fun compareConstructorFlags(flags1: Flags, flags2: Flags): MetadataCompareResult = serialComparator( + checkFlag(Flag.Constructor.IS_SECONDARY) to "IS_SECONDARY mismatch" + )(flags1, flags2) + + private fun compare(constructor1: KmConstructor, constructor2: KmConstructor): MetadataCompareResult = serialComparator( + ::compareVisibilityFlags, + ::compareConstructorFlags + )(constructor1.flags, constructor2.flags) + + private fun compare(typeArgument1: KmTypeProjection, typeArgument2: KmTypeProjection): MetadataCompareResult = serialComparator( + compare(KmTypeProjection::type, compareNullable(::compareTypes)) + )(typeArgument1, typeArgument2) + + private fun compare(typeParameter1: KmTypeParameter, typeParameter2: KmTypeParameter): MetadataCompareResult = + when { + typeParameter1.variance != typeParameter2.variance -> Fail("Different variance") + typeParameter1.name != typeParameter2.name -> Fail("${typeParameter1.name}, ${typeParameter2.name}") + else -> Ok + } + + private fun compareTypes(type1: KmType, type2: KmType): MetadataCompareResult = serialComparator( + compare(KmType::classifier, ::compare) to "Classifiers mismatch", + compare(KmType::arguments, compareLists(::compare)) to "Type arguments mismatch", + compare(KmType::flags, ::compareTypeFlags) to "Type flags mismatch for", + compare(KmType::abbreviatedType, compareNullable(::compareTypes)) to "Abbreviated types mismatch" + )(type1, type2) + + private fun compare(class1: KmClassifier, class2: KmClassifier): MetadataCompareResult = when { + class1 is KmClassifier.TypeAlias && class2 is KmClassifier.TypeAlias -> { + if (class1.name == class2.name) Ok else Fail("Different type aliases: ${class1.name}, ${class2.name}") + } + class1 is KmClassifier.Class && class2 is KmClassifier.Class -> { + when (class1.name) { + class2.name -> Ok + else -> Fail("Different classes: ${class1.name}, ${class2.name}") + } + } + class1 is KmClassifier.TypeParameter && class2 is KmClassifier.TypeParameter -> { + // TODO: How to correctly compare type ids? + Ok + } + else -> Fail("class1 is $class1 and class2 is $class2") + } + + private fun compare( + property: T.() -> R, + comparator: (R, R) -> MetadataCompareResult + ): (T, T) -> MetadataCompareResult = { o1, o2 -> + if (configuration.shouldCheck(property)) comparator(o1.property(), o2.property()) else Ok + } +} \ No newline at end of file diff --git a/kotlin-native/build-tools/src/main/kotlin/org/jetbrains/kotlin/klib/metadata/KmComparatorUtils.kt b/kotlin-native/build-tools/src/main/kotlin/org/jetbrains/kotlin/klib/metadata/KmComparatorUtils.kt new file mode 100644 index 00000000000..1e744812d54 --- /dev/null +++ b/kotlin-native/build-tools/src/main/kotlin/org/jetbrains/kotlin/klib/metadata/KmComparatorUtils.kt @@ -0,0 +1,60 @@ +/* + * Copyright 2010-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ +package org.jetbrains.kotlin.klib.metadata + +import kotlinx.metadata.* + +private fun render(element: Any?): String = when (element) { + is KmTypeAlias -> "typealias ${element.name}" + is KmFunction -> "function ${element.name}" + is KmProperty -> "property ${element.name}" + is KmClass -> "class ${element.name}" + is KmType -> "`type ${element.classifier}`" + else -> element.toString() +} + +internal fun serialComparator( + vararg comparators: Pair<(T, T) -> MetadataCompareResult, String>? +): (T, T) -> MetadataCompareResult = { o1, o2 -> + comparators.filterNotNull().map { (comparator, message) -> + comparator(o1, o2).let { result -> + if (result is Fail) Fail(message, result) else result + } + }.wrap() +} + +internal fun serialComparator( + vararg comparators: (T, T) -> MetadataCompareResult +): (T, T) -> MetadataCompareResult = { o1, o2 -> + comparators + .map { comparator -> comparator(o1, o2) } + .wrap() +} + +internal fun Collection.wrap(): MetadataCompareResult = + filterIsInstance().let { fails -> + when (fails.size) { + 0 -> Ok + else -> Fail(fails) + } + } + +internal fun compareNullable( + comparator: (T, T) -> MetadataCompareResult +): (T?, T?) -> MetadataCompareResult = { a, b -> + when { + a != null && b != null -> comparator(a, b) + a == null && b == null -> Ok + else -> Fail("${render(a)} ${render(b)}") + } +} + +internal fun compareLists(elementComparator: (T, T) -> MetadataCompareResult, sortBy: T.() -> String? = { null }) = + { list1: List, list2: List -> compareLists(list1.sortedBy(sortBy), list2.sortedBy(sortBy), elementComparator) } + +private fun compareLists(l1: List, l2: List, comparator: (T, T) -> MetadataCompareResult) = when { + l1.size != l2.size -> Fail("${l1.size} != ${l2.size}") + else -> l1.zip(l2).map { comparator(it.first, it.second) }.wrap() +} \ No newline at end of file diff --git a/kotlin-native/build-tools/src/main/kotlin/org/jetbrains/kotlin/klib/metadata/SortedMergeStrategy.kt b/kotlin-native/build-tools/src/main/kotlin/org/jetbrains/kotlin/klib/metadata/SortedMergeStrategy.kt new file mode 100644 index 00000000000..93d040e77b8 --- /dev/null +++ b/kotlin-native/build-tools/src/main/kotlin/org/jetbrains/kotlin/klib/metadata/SortedMergeStrategy.kt @@ -0,0 +1,54 @@ +/* + * Copyright 2010-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ +package org.jetbrains.kotlin.klib.metadata + +import kotlinx.metadata.* +import kotlinx.metadata.klib.KlibModuleFragmentReadStrategy +import kotlinx.metadata.klib.fqName + +/** + * Output klib declarations in predictable sorted order. + */ +internal class SortedMergeStrategy : KlibModuleFragmentReadStrategy { + + override fun processModuleParts(parts: List): List = + parts.fold(KmModuleFragment(), ::joinFragments).let(::listOf) +} + +/** + * We need a stable order for overloaded functions. + */ +internal fun KmFunction.mangle(): String { + val typeParameters = typeParameters.joinToString(prefix = "<", postfix = ">", transform = KmTypeParameter::name) + val valueParameters = valueParameters.joinToString(prefix = "(", postfix = ")", transform = KmValueParameter::name) + val receiver = receiverParameterType?.classifier + return "$receiver.${name}.$typeParameters.$valueParameters" +} + +internal fun KmProperty.mangle(): String { + val receiver = receiverParameterType?.classifier + return "$receiver.$name" +} + +private fun joinAndSortPackages(pkg1: KmPackage, pkg2: KmPackage) = KmPackage().apply { + functions += (pkg1.functions + pkg2.functions).sortedBy(KmFunction::mangle) + properties += (pkg1.properties + pkg2.properties).sortedBy(KmProperty::name) + typeAliases += (pkg1.typeAliases + pkg2.typeAliases).sortedBy(KmTypeAlias::name) +} + +/** + * Merges two fragments of a single module into one. + */ +internal fun joinFragments(fragment1: KmModuleFragment, fragment2: KmModuleFragment) = KmModuleFragment().apply { + assert(fragment1.fqName == fragment2.fqName) + pkg = when { + fragment1.pkg != null && fragment2.pkg != null -> joinAndSortPackages(fragment1.pkg!!, fragment2.pkg!!) + fragment1.pkg != null -> joinAndSortPackages(fragment1.pkg!!, KmPackage()) + fragment2.pkg != null -> joinAndSortPackages(KmPackage(), fragment2.pkg!!) + else -> null + } + fqName = fragment1.fqName + classes += fragment1.classes.sortedBy(KmClass::name) + fragment2.classes.sortedBy(KmClass::name) +} \ No newline at end of file diff --git a/kotlin-native/build-tools/src/main/kotlin/org/jetbrains/kotlin/klib/metadata/TrivialLibraryProvider.kt b/kotlin-native/build-tools/src/main/kotlin/org/jetbrains/kotlin/klib/metadata/TrivialLibraryProvider.kt new file mode 100644 index 00000000000..2f81c86f1b9 --- /dev/null +++ b/kotlin-native/build-tools/src/main/kotlin/org/jetbrains/kotlin/klib/metadata/TrivialLibraryProvider.kt @@ -0,0 +1,25 @@ +/* + * Copyright 2010-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ +package org.jetbrains.kotlin.klib.metadata + +import kotlinx.metadata.klib.KlibModuleMetadata +import org.jetbrains.kotlin.library.MetadataLibrary + +/** + * Provides access to metadata using default compiler's routine. + */ +internal class TrivialLibraryProvider( + private val library: MetadataLibrary +) : KlibModuleMetadata.MetadataLibraryProvider { + + override val moduleHeaderData: ByteArray + get() = library.moduleHeaderData + + override fun packageMetadata(fqName: String, partName: String): ByteArray = + library.packageMetadata(fqName, partName) + + override fun packageMetadataParts(fqName: String): Set = + library.packageMetadataParts(fqName) +} \ No newline at end of file diff --git a/kotlin-native/build-tools/src/main/kotlin/org/jetbrains/kotlin/klib/metadata/comparison.kt b/kotlin-native/build-tools/src/main/kotlin/org/jetbrains/kotlin/klib/metadata/comparison.kt new file mode 100644 index 00000000000..f1fe3abbbdf --- /dev/null +++ b/kotlin-native/build-tools/src/main/kotlin/org/jetbrains/kotlin/klib/metadata/comparison.kt @@ -0,0 +1,202 @@ +/* + * Copyright 2010-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ +package org.jetbrains.kotlin.klib.metadata + +import kotlinx.metadata.* +import kotlinx.metadata.klib.KlibModuleMetadata +import org.jetbrains.kotlin.konan.file.File +import org.jetbrains.kotlin.library.CompilerSingleFileKlibResolveAllowingIrProvidersStrategy +import org.jetbrains.kotlin.library.resolveSingleFileKlib + +private inline fun compareElements( + comparisonConfig: ComparisonConfig, + elements: Map>, + crossinline comparator: (T, T) -> MetadataCompareResult +): MetadataCompareResult = elements + .entries + .asSequence() + .filter { comparisonConfig.shouldCheckDeclaration(it.key) } + .map { comparator(it.value.first, it.value.second).messageIfFail("${it.key} mismatch") } + .toList() + .wrap() + +private class JoinedFragments( + val classes: JoinResult, + val functions: JoinResult, + val properties: JoinResult, + val typeAliases: JoinResult, +) + +private fun processMissing(comparisonConfig: ComparisonConfig, joinResult: JoinResult<*>): MetadataCompareResult { + val missingInFirst = joinResult.missingInFirst + .filter(comparisonConfig::shouldCheckDeclaration) + .map { Fail("$it missing in first fragment") } + val missingInSecond = joinResult.missingInSecond + .filter(comparisonConfig::shouldCheckDeclaration) + .map { Fail("$it missing in second fragment") } + return (missingInFirst + missingInSecond).let { + if (it.isEmpty()) Ok else Fail(it) + } +} + +private fun MetadataCompareResult.messageIfFail(message: String): MetadataCompareResult = + if (this is Fail) Fail(message, this) else this + +private fun processMissing( + comparisonConfig: ComparisonConfig, + joinedFragments: JoinedFragments +): MetadataCompareResult = listOf( + processMissing(comparisonConfig, joinedFragments.classes) + .messageIfFail("Missing classes"), + processMissing(comparisonConfig, joinedFragments.functions) + .messageIfFail("Missing functions"), + processMissing(comparisonConfig, joinedFragments.typeAliases) + .messageIfFail("Missing type aliases"), + processMissing(comparisonConfig, joinedFragments.properties) + .messageIfFail("Missing properties"), +).wrap() + +private data class JoinResult( + val joined: Map>, + val missingInFirst: List, + val missingInSecond: List +) + +private fun buildJoined(e1: List, e2: List, key: T.() -> String): JoinResult { + val m1 = e1.associateBy { it.key() } + val m2 = e2.associateBy { it.key() } + val joinedKeys = e1.map(key).filter { it in m2 }.toSet() + val joined = m1 + .filterKeys(joinedKeys::contains) + .mapValues { (key, value) -> value to m2.getValue(key) } + return JoinResult( + joined, + (m1 - joinedKeys).keys.toList(), + (m2 - joinedKeys).keys.toList() + ) +} + +/** + * Wrapper around direct access to [fragment] that allows + * to uniformly process all its components. + */ +private fun processFragment( + fragment: KmModuleFragment, + action: (List, List, List, List) -> T +): T { + val classes = fragment.classes + val pkg = fragment.pkg + return when { + pkg != null -> action(classes, pkg.functions, pkg.properties, pkg.typeAliases) + else -> action(classes, emptyList(), emptyList(), emptyList()) + } +} + +private fun compareMetadata( + comparisonConfig: ComparisonConfig, + metadataModuleA: KlibModuleMetadata, + metadataModuleB: KlibModuleMetadata +): MetadataCompareResult { + val fragmentA = metadataModuleA.fragments.fold(KmModuleFragment(), ::joinFragments) + val fragmentB = metadataModuleB.fragments.fold(KmModuleFragment(), ::joinFragments) + + val joinedFragments = processFragment(fragmentA) { classesA, functionsA, propertiesA, typeAliasesA -> + processFragment(fragmentB) { classesB, functionsB, propertiesB, typeAliasesB -> + JoinedFragments( + buildJoined(classesA, classesB, KmClass::name), + buildJoined(functionsA, functionsB, KmFunction::name), + buildJoined(propertiesA, propertiesB, KmProperty::name), + buildJoined(typeAliasesA, typeAliasesB, KmTypeAlias::name) + ) + } + } + + val comparator = KmComparator(comparisonConfig) + return joinedFragments.run { + listOf( + compareElements(comparisonConfig, classes.joined, comparator::compare), + compareElements(comparisonConfig, functions.joined, comparator::compare), + compareElements(comparisonConfig, properties.joined, comparator::compare), + compareElements(comparisonConfig, typeAliases.joined, comparator::compare), + processMissing(comparisonConfig, this) + ) + }.wrap() + +} + +sealed class MetadataCompareResult { + class Fail( + val children: Collection, val message: String? = null + ) : MetadataCompareResult() { + constructor(message: String, child: Fail? = null) + : this(listOfNotNull(child), message) + } + + object Ok : MetadataCompareResult() +} + +// A neat way to have short names internally without polluting client's namespace. +internal typealias Fail = MetadataCompareResult.Fail +internal typealias Ok = MetadataCompareResult.Ok + +fun expandFail(fail: Fail, output: (String) -> Unit, padding: String = "") { + fail.message?.let { output("$padding$it") } + fail.children.forEach { + expandFail(it, output, "$padding ") + } +} + +/** + * Configure what should be tested and what shouldn't. + * + * TODO: Add a way to conditionally disable property comparison. + * E.g. "If class name is Companion do not compare flags". + */ +interface ComparisonConfig { + /** + * Should the declaration be compared at all. + */ + fun shouldCheckDeclaration(element: String): Boolean + + /** + * Should we check property of declaration. + */ + fun shouldCheck(property: T.() -> R): Boolean +} + +/** + * Configuration for comparing `metadata` and `sourcecode` cinterop modes. + */ +class CInteropComparisonConfig : ComparisonConfig { + override fun shouldCheck(property: T.() -> R): Boolean = when (property) { + // Kotlin compiler may incorrectly omit abbreviatedType in some cases. + KmType::abbreviatedType -> false + else -> true + } + + override fun shouldCheckDeclaration(element: String): Boolean = when { + // kniBridge is generated only in sourcecode mode. + element.startsWith("kniBridge") -> false + else -> true + } +} + +/** + * Structurally compares metadata of given libraries. + */ +fun compareKlibMetadata( + comparisonConfig: ComparisonConfig, + pathToFirstLibrary: String, + pathToSecondLibrary: String +): MetadataCompareResult { + val resolveStrategy = CompilerSingleFileKlibResolveAllowingIrProvidersStrategy( + knownIrProviders = listOf("kotlin.native.cinterop") + ) + val klib1 = resolveSingleFileKlib(File(pathToFirstLibrary), strategy = resolveStrategy) + val klib2 = resolveSingleFileKlib(File(pathToSecondLibrary), strategy = resolveStrategy) + val metadata1 = KlibModuleMetadata.read(TrivialLibraryProvider(klib1), SortedMergeStrategy()) + val metadata2 = KlibModuleMetadata.read(TrivialLibraryProvider(klib2), SortedMergeStrategy()) + return compareMetadata(comparisonConfig, metadata1, metadata2) +} \ No newline at end of file diff --git a/kotlin-native/build-tools/src/main/kotlin/org/jetbrains/kotlin/testing/native/GitDownloadTask.kt b/kotlin-native/build-tools/src/main/kotlin/org/jetbrains/kotlin/testing/native/GitDownloadTask.kt new file mode 100644 index 00000000000..b576a08e5d4 --- /dev/null +++ b/kotlin-native/build-tools/src/main/kotlin/org/jetbrains/kotlin/testing/native/GitDownloadTask.kt @@ -0,0 +1,170 @@ +/* + * Copyright 2010-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +package org.jetbrains.kotlin.testing.native + +import org.gradle.api.DefaultTask +import org.gradle.api.provider.Property +import org.gradle.api.provider.Provider +import org.gradle.api.tasks.TaskAction +import org.gradle.api.tasks.options.Option +import org.gradle.process.ExecResult +import org.gradle.process.ExecSpec +import org.jetbrains.kotlin.isNotEmpty +import java.io.File +import java.net.URL +import java.util.* +import javax.inject.Inject + +/** + * Clones the given revision of the given Git repository to the given directory. + */ +@Suppress("UnstableApiUsage") +open class GitDownloadTask @Inject constructor( + val repositoryProvider: Provider, + val revisionProvider: Provider, + val outputDirectoryProvider: Provider +) : DefaultTask() { + + private val repository: URL + get() = repositoryProvider.get() + + private val revision: String + get() = revisionProvider.get() + + private val outputDirectory: File + get() = outputDirectoryProvider.get() + + @Option(option = "refresh", + description = "Fetch and checkout the revision even if the output directory already contains it. " + + "All changes in the output directory will be overwritten") + val refresh: Property = project.objects.property(Boolean::class.java).apply { + set(false) + } + + private val upToDateChecker = UpToDateChecker() + + init { + outputs.upToDateWhen { upToDateChecker.isUpToDate() } + } + + private fun git( + vararg args: String, + ignoreExitValue: Boolean = false, + execConfiguration: ExecSpec.() -> Unit = {} + ): ExecResult = + project.exec { + it.executable = "git" + it.args(*args) + it.isIgnoreExitValue = ignoreExitValue + it.execConfiguration() + } + + private fun tryCloneBranch(): Boolean { + val execResult = git( + "clone", repository.toString(), + outputDirectory.absolutePath, + "--depth", "1", + "--branch", revision, + ignoreExitValue = true + ) + return execResult.exitValue == 0 + } + + private fun fetchByHash() { + git("init", outputDirectory.absolutePath) + git("fetch", repository.toString(), "--depth", "1", revision) { + workingDir(outputDirectory) + } + git("reset", "--hard", revision) { + workingDir(outputDirectory) + } + } + + @TaskAction + fun clone() { + // Gradle ignores outputs.upToDateWhen { ... } and reruns a task if the classpath of the task was changed + // So we have to perform the up-to-date check manually one more time in the task action. + if (upToDateChecker.isUpToDate()) { + logger.info("Skip cloning to avoid rewriting possible debug changes in ${outputDirectory.absolutePath}.") + return + } + + project.delete { + it.delete(outputDirectory) + } + + if (!tryCloneBranch()) { + logger.info("Cannot use the revision '$revision' to clone the repository. Trying to use init && fetch instead.") + fetchByHash() + } + + // Store info about used revision for the manual up-to-date check. + upToDateChecker.storeRevisionInfo() + } + + + /** + * This class performs manual UP-TO-DATE checking. + * + * We want to be able to edit downloaded sources for debug purposes. Thus this task should not rewrite changes in + * the output directory. + * + * Gradle does allow us to provide a custom logic to determine if task outputs are UP-TO-DATE or not (see + * Task.outputs.upToDateWhen). But Gradle still reruns a task if its classpath was changed. This may lead + * to rewriting our manual debug changes in downloaded sources if there are some changes in the + * `build-tools` project. + * + * So we have to manually check up-to-dateness in upToDateWhen and as a first step of the task action. + */ + private inner class UpToDateChecker() { + + private val revisionInfoFile: File + get() = outputDirectory.resolve(".revision") + + /** + * The download task should be executed in the following cases: + * + * - The output directory doesn't exist or is empty; + * - Repository or revision was changed since the last execution; + * - A user forced rerunning this tasks manually (see [GitDownloadTask.refresh]). + * + * In all other cases we consider the task UP-TO-DATE. + */ + fun isUpToDate(): Boolean { + return !refresh.get() && + outputDirectory.let { it.exists() && project.fileTree(it).isNotEmpty } && + noRevisionChanges() + } + + private fun noRevisionChanges(): Boolean = + revisionInfoFile.exists() && loadRevisionInfo() == RevisionInfo(repository, revision) + + fun storeRevisionInfo() { + val properties = Properties() + properties["repository"] = repository.toString() + properties["revision"] = revision + revisionInfoFile.bufferedWriter().use { + properties.store(it, null) + } + } + + private fun loadRevisionInfo(): RevisionInfo? { + return try { + val properties = Properties() + revisionInfoFile.bufferedReader().use { + properties.load(it) + } + RevisionInfo(properties.getProperty("repository"), properties.getProperty("revision")) + } catch (_ : Exception) { + null + } + } + } + + private data class RevisionInfo(val repository: String, val revision: String) { + constructor(repository: URL, revision: String): this(repository.toString(), revision) + } +} diff --git a/kotlin-native/build-tools/src/main/kotlin/org/jetbrains/kotlin/testing/native/NativeTest.kt b/kotlin-native/build-tools/src/main/kotlin/org/jetbrains/kotlin/testing/native/NativeTest.kt new file mode 100644 index 00000000000..e6734c3e645 --- /dev/null +++ b/kotlin-native/build-tools/src/main/kotlin/org/jetbrains/kotlin/testing/native/NativeTest.kt @@ -0,0 +1,261 @@ +/* + * Copyright 2010-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +package org.jetbrains.kotlin.testing.native + +import groovy.lang.Closure +import java.io.File +import javax.inject.Inject +import org.gradle.api.* +import org.gradle.api.file.ConfigurableFileCollection +import org.gradle.api.tasks.* +import org.jetbrains.kotlin.ExecClang +import org.jetbrains.kotlin.bitcode.CompileToBitcode +import org.jetbrains.kotlin.konan.target.* + +open class CompileNativeTest @Inject constructor( + @InputFile val inputFile: File, + @Input val target: String +) : DefaultTask() { + @OutputFile + var outputFile = project.buildDir.resolve("bin/test/$target/${inputFile.nameWithoutExtension}.o") + + @Input + val clangArgs = mutableListOf() + + @TaskAction + fun compile() { + val plugin = project.convention.getPlugin(ExecClang::class.java) + plugin.execBareClang { + it.executable = "clang++" + it.args = clangArgs + listOf(inputFile.absolutePath, "-o", outputFile.absolutePath) + } + } +} + +open class LlvmLinkNativeTest @Inject constructor( + val baseName: String, + @Input val target: String, + @InputFile val mainFile: File +) : DefaultTask() { + + @SkipWhenEmpty + @InputFiles + var inputFiles: ConfigurableFileCollection = project.files() + + @OutputFile + var outputFile: File = project.buildDir.resolve("bitcode/test/$target/$baseName.bc") + + @TaskAction + fun llvmLink() { + val llvmDir = project.property("llvmDir") + val tmpOutput = File.createTempFile("runtimeTests", ".bc").apply { + deleteOnExit() + } + + // The runtime provides our implementations for some standard functions (see StdCppStubs.cpp). + // We need to internalize these symbols to avoid clashes with symbols provided by the C++ stdlib. + // But llvm-link -internalize is kinda broken: it links modules one by one and can't see usages + // of a symbol in subsequent modules. So it will mangle such symbols causing "unresolved symbol" + // errors at the link stage. So we have to run llvm-link twice: the first one links all modules + // except the one containing the entry point to a single *.bc without internalization. The second + // run internalizes this big module and links it with a module containing the entry point. + project.exec { + it.executable = "$llvmDir/bin/llvm-link" + it.args = listOf("-o", tmpOutput.absolutePath) + inputFiles.map { it.absolutePath } + } + + project.exec { + it.executable = "$llvmDir/bin/llvm-link" + it.args = listOf( + "-o", outputFile.absolutePath, + mainFile.absolutePath, + tmpOutput.absolutePath, + "-internalize" + ) + } + } +} + +open class LinkNativeTest @Inject constructor( + @InputFiles val inputFiles: List, + @OutputFile val outputFile: File, + @Internal val target: String, + @Internal val linkerArgs: List, + private val platformManager: PlatformManager, + private val mimallocEnabled: Boolean +) : DefaultTask () { + companion object { + fun create( + project: Project, + platformManager: PlatformManager, + taskName: String, + inputFiles: List, + target: String, + outputFile: File, + linkerArgs: List, + mimallocEnabled: Boolean + ): LinkNativeTest = project.tasks.create( + taskName, + LinkNativeTest::class.java, + inputFiles, + outputFile, + target, + linkerArgs, + platformManager, + mimallocEnabled) + + fun create( + project: Project, + platformManager: PlatformManager, + taskName: String, + inputFiles: List, + target: String, + executableName: String, + mimallocEnabled: Boolean, + linkerArgs: List = listOf() + ): LinkNativeTest = create( + project, + platformManager, + taskName, + inputFiles, + target, + project.buildDir.resolve("bin/test/$target/$executableName"), + linkerArgs, mimallocEnabled) + } + + @get:Input + val commands: List> + get() { + // Getting link commands requires presence of a target toolchain. + // Thus we cannot get them at the configuration stage because the toolchain may be not downloaded yet. + val linker = platformManager.platform(platformManager.targetByName(target)).linker + return linker.finalLinkCommands( + inputFiles.map { it.absolutePath }, + outputFile.absolutePath, + listOf(), + linkerArgs, + optimize = false, + debug = false, + kind = LinkerOutputKind.EXECUTABLE, + outputDsymBundle = "", + needsProfileLibrary = false, + mimallocEnabled = mimallocEnabled + ).map { it.argsWithExecutable } + } + + @TaskAction + fun link() { + for (command in commands) { + project.exec { + it.commandLine(command) + } + } + } +} + +fun createTestTask( + project: Project, + testName: String, + testTaskName: String, + testedTaskNames: List, + configureCompileToBitcode: CompileToBitcode.() -> Unit = {}, +): Task { + val platformManager = project.rootProject.findProperty("platformManager") as PlatformManager + val googleTestExtension = project.extensions.getByName(RuntimeTestingPlugin.GOOGLE_TEST_EXTENSION_NAME) as GoogleTestExtension + val testedTasks = testedTaskNames.map { + project.tasks.getByName(it) as CompileToBitcode + } + val target = testedTasks.map { + it.target + }.distinct().single() + val konanTarget = platformManager.targetByName(target) + val compileToBitcodeTasks = testedTasks.mapNotNull { + val name = "${it.name}TestBitcode" + val task = project.tasks.findByName(name) as? CompileToBitcode ?: + project.tasks.create(name, + CompileToBitcode::class.java, + it.srcRoot, + "${it.folderName}Tests", + target, "test" + ).apply { + excludeFiles = emptyList() + includeFiles = listOf("**/*Test.cpp", "**/*Test.mm") + dependsOn(it) + compilerArgs.addAll(it.compilerArgs) + headersDirs += googleTestExtension.headersDirs + this.configureCompileToBitcode() + } + if (task.inputFiles.count() == 0) + null + else + task + } + val testFrameworkTasks = listOf( + project.tasks.getByName("${target}Googletest") as CompileToBitcode, + project.tasks.getByName("${target}Googlemock") as CompileToBitcode + ) + + val testSupportTask = project.tasks.getByName("${target}TestSupport") as CompileToBitcode + + // TODO: It may make sense to merge llvm-link, compile and link to a single task. + val llvmLinkTask = project.tasks.create( + "${testTaskName}LlvmLink", + LlvmLinkNativeTest::class.java, + testTaskName, target, testSupportTask.outFile + ).apply { + val tasksToLink = (compileToBitcodeTasks + testedTasks + testFrameworkTasks) + inputFiles = project.files(tasksToLink.map { it.outFile }) + dependsOn(testSupportTask) + dependsOn(tasksToLink) + } + + val clangFlags = platformManager.platform(konanTarget).configurables as ClangFlags + val compileTask = project.tasks.create( + "${testTaskName}Compile", + CompileNativeTest::class.java, + llvmLinkTask.outputFile, + target + ).apply { + dependsOn(llvmLinkTask) + clangArgs.addAll(clangFlags.clangFlags) + clangArgs.addAll(clangFlags.clangNooptFlags) + } + + val mimallocEnabled = testedTaskNames.any { it.contains("mimalloc", ignoreCase = true) } + val linkTask = LinkNativeTest.create( + project, + platformManager, + "${testTaskName}Link", + listOf(compileTask.outputFile), + target, + testTaskName, + mimallocEnabled + ).apply { + dependsOn(compileTask) + } + + return project.tasks.create(testTaskName, Exec::class.java).apply { + dependsOn(linkTask) + + workingDir = project.buildDir.resolve("testReports/$testTaskName") + val xmlReport = workingDir.resolve("report.xml") + executable(linkTask.outputFile) + args("--gtest_output=xml:${xmlReport.absoluteFile}") + + doFirst { + workingDir.mkdirs() + } + + doLast { + // TODO: Better to use proper XML parsing. + var contents = xmlReport.readText() + contents = contents.replace(" { + override fun apply(target: Project): Unit = with(target) { + val extension = extensions.create(GOOGLE_TEST_EXTENSION_NAME, GoogleTestExtension::class.java, target) + val downloadTask = registerDownloadTask(extension) + + val googleTestRoot = project.provider { extension.sourceDirectory } + + createBitcodeTasks(googleTestRoot, listOf(downloadTask)) + } + + private fun Project.registerDownloadTask(extension: GoogleTestExtension): TaskProvider { + val task = tasks.register( + "downloadGoogleTest", + GitDownloadTask::class.java, + provider { URL(extension.repository) }, + provider { extension.revision }, + provider { extension.fetchDirectory } + ) + task.configure { + it.refresh.set(provider { extension.refresh }) + it.onlyIf { extension.localSourceRoot == null } + it.description = "Retrieves GoogleTest from the given repository" + it.group = "Google Test" + } + return task + } + + private fun Project.createBitcodeTasks( + googleTestRoot: Provider, + dependencies: Iterable> + ) { + pluginManager.withPlugin("compile-to-bitcode") { + val bitcodeExtension = + project.extensions.getByName(CompileToBitcodePlugin.EXTENSION_NAME) as CompileToBitcodeExtension + + bitcodeExtension.create("googletest", outputGroup = "test") { + srcDirs = project.files( + googleTestRoot.resolve("googletest/src") + ) + headersDirs = project.files( + googleTestRoot.resolve("googletest/include"), + googleTestRoot.resolve("googletest") + ) + includeFiles = listOf("*.cc") + excludeFiles = listOf("gtest-all.cc", "gtest_main.cc") + // Original GTest sources contain an unused variable on Windows (kAlternatePathSeparatorString). + compilerArgs.add("-Wno-unused") + dependsOn(dependencies) + } + + bitcodeExtension.create("googlemock", outputGroup = "test") { + srcDirs = project.files( + googleTestRoot.resolve("googlemock/src") + ) + headersDirs = project.files( + googleTestRoot.resolve("googlemock"), + googleTestRoot.resolve("googlemock/include"), + googleTestRoot.resolve("googletest/include") + ) + includeFiles = listOf("*.cc") + excludeFiles = listOf("gmock-all.cc", "gmock_main.cc") + dependsOn(dependencies) + } + } + } + + companion object { + internal const val GOOGLE_TEST_EXTENSION_NAME = "googletest" + } + +} + +/** + * A project extension to configure from where we get the GoogleTest framework. + */ +open class GoogleTestExtension @Inject constructor(private val project: Project) { + + /** + * A repository to fetch GoogleTest from. + */ + var repository: String = "https://github.com/google/googletest.git" + + private var _revision: String? = null + + /** + * A particular revision in the [repository] to be fetched. It can be a branch, a tag or a commit hash. + */ + var revision: String + get() = _revision + ?: throw InvalidUserDataException( + "No value provided for property '${RuntimeTestingPlugin.GOOGLE_TEST_EXTENSION_NAME}.revision'. " + + "Please specify it in the buildscript." + ) + set(value) { _revision = value } + + /** + * Fetch the [revision] even if the [fetchDirectory] already contains it. Overwrite all changes manually made in the output directory. + */ + var refresh: Boolean = false + + /** + * A directory to fetch the [revision] to. + */ + var fetchDirectory: File = project.file("googletest") + + internal var localSourceRoot: File? = null + + /** + * Use a local [directory] with GoogleTest instead of the fetched one. If set, the download task will not be executed. + */ + fun useLocalSources(directory: File) { + localSourceRoot = directory + } + + /** + * Use a local [directory] with GoogleTest instead of the fetched one. If set, the download task will not be executed. + */ + fun useLocalSources(directory: String) { + localSourceRoot = project.file(directory) + } + + /** + * A getter for directory that contains the GTest sources. + * Returns a local source directory if it's specified (see [useLocalSources]) or [fetchDirectory] otherwise. + */ + val sourceDirectory: File + get() = localSourceRoot ?: fetchDirectory + + /** + * A file collection with header directories for GoogleTest and GoogleMock. + * Useful to configure compilation against GTest. + */ + val headersDirs: FileCollection = project.files( + project.provider { sourceDirectory.resolve("googletest/include") }, + project.provider { sourceDirectory.resolve("googlemock/include") } + ) +} + diff --git a/kotlin-native/build-tools/src/main/kotlin/org/jetbrains/kotlin/utils/DFS.kt b/kotlin-native/build-tools/src/main/kotlin/org/jetbrains/kotlin/utils/DFS.kt new file mode 100644 index 00000000000..87438995b56 --- /dev/null +++ b/kotlin-native/build-tools/src/main/kotlin/org/jetbrains/kotlin/utils/DFS.kt @@ -0,0 +1,121 @@ +package org.jetbrains.kotlin.utils + +import java.util.* + +// Copied from Kotlin org.jetbrains.kotlin.utils.DFS class +@Suppress("MemberVisibilityCanBePrivate", "MemberVisibilityCanBePrivate", "unused") +object DFS { + fun dfs(nodes: Collection, neighbors: Neighbors, visited: Visited, handler: NodeHandler): R { + for (node in nodes) { + doDfs(node, neighbors, visited, handler) + } + return handler.result() + } + + fun dfs( + nodes: Collection, + neighbors: Neighbors, + handler: NodeHandler + ): R { + return dfs(nodes, neighbors, VisitedWithSet(), handler) + } + + fun ifAny( + nodes: Collection, + neighbors: Neighbors, + predicate: Function1 + ): Boolean { + val result = BooleanArray(1) + return dfs(nodes, neighbors, object : AbstractNodeHandler() { + override fun beforeChildren(current: N): Boolean { + if (predicate.invoke(current)) { + result[0] = true + } + return !result[0] + } + + override fun result(): Boolean { + return result[0] + } + })!! + } + + fun dfsFromNode(node: N, neighbors: Neighbors, visited: Visited, handler: NodeHandler): R { + doDfs(node, neighbors, visited, handler) + return handler.result() + } + + fun dfsFromNode( + node: N, + neighbors: Neighbors, + visited: Visited + ) { + dfsFromNode(node, neighbors, visited, object : AbstractNodeHandler() { + override fun result(): Void? { + return null + } + }) + } + + fun topologicalOrder(nodes: Iterable, neighbors: Neighbors, visited: Visited): List { + val handler = TopologicalOrder() + for (node in nodes) { + doDfs(node, neighbors, visited, handler) + } + return handler.result() + } + + fun topologicalOrder(nodes: Iterable, neighbors: Neighbors): List { + return topologicalOrder(nodes, neighbors, VisitedWithSet()) + } + + fun doDfs(current: N, neighbors: Neighbors, visited: Visited, handler: NodeHandler) { + if (!visited.checkAndMarkVisited(current)) return + if (!handler.beforeChildren(current)) return + for (neighbor in neighbors.getNeighbors(current)) { + doDfs(neighbor, neighbors, visited, handler) + } + handler.afterChildren(current) + } + + interface NodeHandler { + fun beforeChildren(current: N): Boolean + fun afterChildren(current: N) + fun result(): R + } + + interface Neighbors { + fun getNeighbors(current: N): Iterable + } + + interface Visited { + fun checkAndMarkVisited(current: N): Boolean + } + + abstract class AbstractNodeHandler : NodeHandler { + override fun beforeChildren(current: N): Boolean { + return true + } + + override fun afterChildren(current: N) {} + } + + class VisitedWithSet @JvmOverloads constructor(private val visited: MutableSet = HashSet()) : Visited { + override fun checkAndMarkVisited(current: N): Boolean { + return visited.add(current) + } + } + + abstract class CollectingNodeHandler> protected constructor(protected val result: C) : AbstractNodeHandler() { + override fun result(): C { + return result + } + } + + abstract class NodeHandlerWithListResult protected constructor() : CollectingNodeHandler>(LinkedList()) + class TopologicalOrder : NodeHandlerWithListResult() { + override fun afterChildren(current: N) { + result.addFirst(current) + } + } +} \ No newline at end of file diff --git a/kotlin-native/build.gradle b/kotlin-native/build.gradle new file mode 100644 index 00000000000..254fab291df --- /dev/null +++ b/kotlin-native/build.gradle @@ -0,0 +1,786 @@ +/* + * Copyright 2010-2017 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import kotlin.text.Regex +import org.jetbrains.kotlin.konan.target.* +import org.jetbrains.kotlin.konan.util.* +import org.jetbrains.kotlin.CopySamples +import org.jetbrains.kotlin.CopyCommonSources +import org.jetbrains.kotlin.PlatformInfo +import org.jetbrains.kotlin.KotlinBuildPusher +import org.jetbrains.kotlin.CollisionDetector +import org.jetbrains.kotlin.CollisionTransformer +import org.jetbrains.kotlin.CompilationDatabaseKt +import com.github.jengelman.gradle.plugins.shadow.tasks.ShadowJar +import org.apache.tools.ant.filters.ReplaceTokens +import org.jetbrains.kotlin.UtilsKt + +buildscript { + apply from: "gradle/kotlinGradlePlugin.gradle" + + repositories { + maven { url kotlinCompilerRepo } + maven { url "https://kotlin.bintray.com/kotlinx" } + maven { url "https://cache-redirector.jetbrains.com/maven-central" } + mavenCentral() + maven { url "https://dl.bintray.com/kotlin/kotlin-dev" } + jcenter() + } + + dependencies { + classpath "org.jetbrains.kotlin:kotlin-native-utils:$kotlinVersion" + classpath "org.jetbrains.kotlin:kotlin-native-shared:$konanVersion" + classpath "org.jetbrains.kotlin:kotlin-native-build-tools:$konanVersion" + classpath 'com.github.jengelman.gradle.plugins:shadow:5.1.0' + } +} +import org.jetbrains.kotlin.konan.* + +// Allows generating wrappers for the root build and all the samples during execution of the default 'wrapper' task. +// Run './gradlew wrapper --gradle-version ' to update all the wrappers. +apply plugin: org.jetbrains.kotlin.GradleWrappers + +wrappers.projects = ['samples', 'samples/calculator', 'samples/androidNativeActivity', 'samples/cocoapods/kotlin-library'] +wrapper.distributionType = Wrapper.DistributionType.ALL + +// FIXME: Remove until IDEA-231214 is fixed. +//defaultTasks 'clean', 'dist' + +convention.plugins.platformInfo = PlatformInfo + +if (isMac()) { + checkXcodeVersion(project) +} + +ext { + distDir = file('dist') + dependenciesDir = DependencyProcessor.defaultDependenciesRoot + experimentalEnabled = project.hasProperty("org.jetbrains.kotlin.native.experimentalTargets") + platformManager = new PlatformManager(DistributionKt.buildDistribution(projectDir.absolutePath), + ext.experimentalEnabled) + + cacheableTargets = [ + KonanTarget.MACOS_X64.INSTANCE, + KonanTarget.IOS_X64.INSTANCE + ] + cacheableTargetNames = cacheableTargets.collect { it.visibleName } + + // Some targets miss zlib in their sysroots. + // We skip these targets when generate a corresponding platform library. + // See also: the :distDef task, targetDefFiles in the :platformLibs project. + targetsWithoutZlib = [ + KonanTarget.LINUX_MIPS32.INSTANCE, + KonanTarget.LINUX_MIPSEL32.INSTANCE + ] + + kotlinCompilerModule="org.jetbrains.kotlin:kotlin-compiler:${kotlinVersion}" + kotlinStdLibModule="org.jetbrains.kotlin:kotlin-stdlib:${kotlinVersion}" + kotlinCommonStdlibModule="org.jetbrains.kotlin:kotlin-stdlib-common:${kotlinStdlibVersion}:sources" + kotlinTestCommonModule="org.jetbrains.kotlin:kotlin-test-common:${kotlinStdlibVersion}:sources" + kotlinTestAnnotationsCommonModule="org.jetbrains.kotlin:kotlin-test-annotations-common:${kotlinStdlibVersion}:sources" + kotlinReflectModule="org.jetbrains.kotlin:kotlin-reflect:${kotlinVersion}" + kotlinScriptRuntimeModule="org.jetbrains.kotlin:kotlin-script-runtime:${kotlinVersion}" + kotlinUtilKliMetadatabModule="org.jetbrains.kotlin:kotlin-util-klib-metadata:${kotlinVersion}" + + konanVersionFull = CompilerVersionGeneratedKt.getCurrentCompilerVersion() + gradlePluginVersion = konanVersionFull +} + +allprojects { + buildscript { + repositories { + maven { + url 'https://cache-redirector.jetbrains.com/jcenter' + } + jcenter() + maven { url "https://dl.bintray.com/kotlin/kotlin-dev" } + } + } + if (path != ":dependencies") { + evaluationDependsOn(":dependencies") + } + + repositories { + maven { + url 'https://cache-redirector.jetbrains.com/maven-central' + } + mavenCentral() + maven { + url kotlinStdlibRepo + } + maven { + url kotlinCompilerRepo + } + maven { + url "https://dl.bintray.com/kotlin/kotlin-dev" + } + } + + setupHostAndTarget() + loadCommandLineProperties() + loadLocalProperties() + setupClang(project) +} + +void setupHostAndTarget() { + ext.hostName = platformManager.hostName + ext.targetList = platformManager.filteredOutEnabledButNotSupported.collect { it.visibleName } as List + ext.konanTargetList = platformManager.enabled as List +} + +void setupClang(Project project) { + + project.convention.plugins.platformManager = project.rootProject.ext.platformManager + project.convention.plugins.execClang = new org.jetbrains.kotlin.ExecClang(project) + + project.plugins.withType(NativeComponentPlugin) { + project.model { + if (isWindows()) { + platforms { + host { + architecture 'x86_64' + } + } + + components { + withType(NativeComponentSpec) { + targetPlatform 'host' + } + } + + toolChains { + gcc(Gcc) { + path "$llvmDir/bin" + } + } + } else { + + toolChains { + clang(Clang) { + hostPlatform.clang.clangPaths.each { + path it + } + + eachPlatform { // TODO: will not work when cross-compiling + [cCompiler, cppCompiler, linker].each { + it.withArguments { it.addAll(project.hostPlatform.clang.clangArgs) } + } + + } + } + } + } + } + } +} + +void loadLocalProperties() { + if (new File("$project.rootDir/local.properties").exists()) { + Properties props = new Properties() + props.load(new FileInputStream("$project.rootDir/local.properties")) + props.each { prop -> project.ext.set(prop.key, prop.value) } + } +} + +void loadCommandLineProperties() { + if (project.hasProperty("konanc_flags")) { + throw new Error("Specify either -Ptest_flags or -Pbuild_flags.") + } + ext.globalBuildArgs = project.hasProperty("build_flags") ? ext.build_flags.split() : [] + ext.globalTestArgs = project.hasProperty("test_flags") ? ext.test_flags.split() : [] + ext.testTarget = project.hasProperty("test_target") ? ext.test_target : null +} + +configurations { + ftpAntTask + kotlinCommonSources + distPack +} + +dependencies { + ftpAntTask 'org.apache.ant:ant-commons-net:1.9.9' + [kotlinCommonStdlibModule, kotlinTestCommonModule, kotlinTestAnnotationsCommonModule].each { + kotlinCommonSources(it) { transitive = false } + } + distPack project(':Interop:Runtime') + distPack project(':Interop:Indexer') + distPack project(':Interop:StubGenerator') + distPack project(':backend.native') + distPack project(':utilities:cli-runner') + distPack project(':utilities:basic-utils') + distPack project(':klib') + distPack project(path: ':endorsedLibraries:kotlinx.cli', configuration: "jvmRuntimeElements") + distPack "org.jetbrains.kotlin:kotlin-native-shared:$konanVersion" +} + +task sharedJar { + dependsOn gradle.includedBuild('shared').task(':jar') +} + +task gradlePluginJar { + dependsOn gradle.includedBuild('kotlin-native-gradle-plugin').task(':shadowJar') +} + +task gradlePluginCheck { + dependsOn gradle.includedBuild('kotlin-native-gradle-plugin').task(':check') +} + +task dist_compiler(dependsOn: "distCompiler") +task dist_runtime(dependsOn: "distRuntime") +task cross_dist(dependsOn: "crossDist") +task list_dist(dependsOn: "listDist") +task build { + dependsOn ':dist', ':distPlatformLibs' +} + +task distCommonSources(type: CopyCommonSources) { + outputDir "$distDir/sources" + sourcePaths configurations.kotlinCommonSources.files + zipSources true +} + +task distNativeSources(type: Zip) { + destinationDirectory = file("$distDir/sources") + archiveFileName = "kotlin-stdlib-native-sources.zip" + + includeEmptyDirs = false + include('**/*.kt') + + from(project(':runtime').file('src/main/kotlin')) + from(project(':Interop:Runtime').file('src/main/kotlin')) + from(project(':Interop:Runtime').file('src/native/kotlin')) + from(project(':Interop:JsRuntime').file('src/main/kotlin')) { + into('kotlinx/wasm/jsinterop') + } +} + +task distEndorsedSources { + dependsOn(':endorsedLibraries:endorsedLibsSources') +} + +task distSources { + dependsOn(distCommonSources) + dependsOn(distNativeSources) + dependsOn(distEndorsedSources) +} + +task detectJarCollision(type: CollisionDetector) { + configurations = [project.configurations.distPack] + resolvingRules["META-INF/kotlin-util-klib.kotlin_module"] = "kotlin-compiler" + resolvingRules["META-INF/kotlin-util-io.kotlin_module"] = "kotlin-compiler" + resolvingRules["META-INF/descriptors.jvm.kotlin_module"] = "kotlin-compiler" + resolvingRules["META-INF/descriptors.kotlin_module"] = "kotlin-compiler" + resolvingRules["META-INF/descriptors.runtime.kotlin_module"] = "kotlin-compiler" + resolvingRules["META-INF/deserialization.kotlin_module"] = "kotlin-compiler" + resolvingRules["META-INF/metadata.jvm.kotlin_module"] = "kotlin-compiler" + resolvingRules["META-INF/metadata.kotlin_module"] = "kotlin-compiler" + resolvingRules["META-INF/type-system.kotlin_module"] = "kotlin-compiler" + resolvingRules["META-INF/util.runtime.kotlin_module"] = "kotlin-compiler" + resolvingRules["META-INF/kotlin-native-utils.kotlin_module"] = "kotlin-compiler" + resolvingRules["META-INF/compiler.common.kotlin_module"] = "kotlin-compiler" + resolvingRules["META-INF/compiler.common.jvm.kotlin_module"] = "kotlin-compiler" + resolvingRules["META-INF/deserialization.common.jvm.kotlin_module"] = "kotlin-compiler" + resolvingRules["META-INF/deserialization.common.kotlin_module"] = "kotlin-compiler" + + // These collisions are introduced by kotlinx-metadata-klib. + resolvingRules["META-INF/serialization.kotlin_module"] = "kotlin-compiler" + resolvingRules["META-INF/kotlin-util-klib-metadata.kotlin_module"] = "kotlin-compiler" + + resolvingRules["kotlin/annotation/annotation.kotlin_builtins"] = "kotlin-compiler" + resolvingRules["kotlin/collections/collections.kotlin_builtins"] = "kotlin-compiler" + resolvingRules["kotlin/coroutines/coroutines.kotlin_builtins"] = "kotlin-compiler" + resolvingRules["kotlin/internal/internal.kotlin_builtins"] = "kotlin-compiler" + resolvingRules["kotlin/kotlin.kotlin_builtins"] = "kotlin-compiler" + resolvingRules["kotlin/ranges/ranges.kotlin_builtins"] = "kotlin-compiler" + resolvingRules["kotlin/reflect/reflect.kotlin_builtins"] = "kotlin-compiler" + resolvingRules["META-INF/maven/com.google.protobuf/protobuf-java/pom.properties"] = "kotlin-compiler" + resolvingRules["META-INF/maven/com.google.protobuf/protobuf-java/pom.xml"] = "kotlin-compiler" + resolvingRules["org/jetbrains/kotlin/builtins/konan/KonanBuiltIns.class"] = "kotlin-compiler" + resolvingRules["org/jetbrains/kotlin/resolve/konan/platform/NativeInliningRule.class"] = "kotlin-compiler" + resolvingRules["org/jetbrains/kotlin/resolve/konan/platform/NativePlatformAnalyzerServices.class"] = "kotlin-compiler" + resolvingRules["org/jetbrains/annotations/Nls.class"] = "kotlin-compiler" + librariesWithIgnoredClassCollisions.addAll(["kotlin-util-klib", "kotlin-util-io", "kotlinx-metadata-klib", "kotlin-native-utils"]) + if (project.hasProperty('kotlinProjectPath')) { + resolvingRulesWithRegexes[new Regex("META-INF/.+\\.kotlin_module")] = "kotlin-compiler" + resolvingRules["META-INF/extensions/compiler.xml"] = "kotlin-compiler" + resolvingRules["META-INF/compiler.version"] = "kotlin-compiler" + resolvingRules["kotlinManifest.properties"] = "kotlin-compiler" + librariesWithIgnoredClassCollisions.addAll(["util", "container", "resolution.common", "resolution", "serialization", "psi", + "deserialization.common", "deserialization.common.jvm", "compiler.backend.common.jvm", + "frontend", "config", "config.jvm", "js.config", "javac-wrapper", + "frontend.common", "frontend.java", "cli-common", "ir.tree", + "ir.tree.impl", "ir.tree.persisting", + "ir.psi2ir", "ir.backend.common", "backend.jvm", "backend.js", + "backend.wasm", "ir.serialization.common", "ir.serialization.js", + "ir.serialization.jvm", "ir.interpreter", "jvm", "compiler.version", + "backend-common", "backend", "plugin-api", "light-classes", "cli", + "cli-js", "incremental-compilation-impl", "js.ast", "js.serializer", + "js.parser", "js.frontend", "js.translator", "js.dce", "metadata", + "metadata.jvm", "descriptors", "descriptors.jvm", "descriptors.runtime", + "deserialization", "util.runtime", "compiler.common", "type-system", "cones", "resolve", + "tree", "psi2fir", "fir2ir", "java", "kotlin-build-common", "lightTree", + "jvm", "checkers", "raw-fir.common", "light-tree2fir", + "fir-serialization", "fir-deserialization", "entrypoint"]) + } +} + +task shadowJar(type: ShadowJar) { + dependsOn ':detectJarCollision' + mergeServiceFiles() + destinationDirectory.set(file("$distDir/konan/lib")) + archiveBaseName.set("kotlin-native") + // Exclude trove4j because of license agreement. + exclude "*trove4j*" + exclude("META-INF/versions/9/module-info.class") + configurations = [project.configurations.distPack] + archiveClassifier.set(null) + transform(CollisionTransformer.class) { + resolvedConflicts = detectJarCollision.resolvedConflicts + } +} + +task distCompiler(type: Copy) { + dependsOn ':shadowJar' + + destinationDir distDir + + from(project(':backend.native').file("build/nativelibs/$hostName")) { + into('konan/nativelib') + } + + from(project(':backend.native').file('build/external_jars/trove4j.jar')) { + into('konan/lib') + } + + from(project(':Interop').file('Indexer/build/nativelibs')) { + into('konan/nativelib') + } + + from(project(':Interop').file('Runtime/build/nativelibs')) { + into('konan/nativelib') + } + + from(project(':llvmCoverageMappingC').file('build/libs/coverageMapping/shared')) { + into('konan/nativelib') + } + + from(project(':llvmDebugInfoC').file('build/libs/debugInfo/shared')) { + into('konan/nativelib') + } + + from(project(':llvmDebugInfoC').file('src/scripts/konan_lldb.py')) { + into('tools') + } + + from(project(':utilities').file('env_blacklist')) { + into('tools') + } + + from(file('cmd')) { + fileMode(0755) + into('bin') + if (!PlatformInfo.isWindows()) { + exclude('**/*.bat') + } + } + + from(project.file('konan')) { + into('konan') + exclude('**/*.properties') + } + + from(project.file('konan')) { + into('konan') + include('**/*.properties') + filter(ReplaceTokens, tokens: [compilerVersion: konanVersionFull.toString()]) + } + if (experimentalEnabled) { + file('konan/experimentalTargetsEnabled').text = "" + } else { + delete('konan/experimentalTargetsEnabled') + } +} + +task distDef(type: Copy) { + + destinationDir distDir + + platformManager.targetValues.each { target -> + from(project("platformLibs").file("src/platform/${target.family.name().toLowerCase()}")) { + into("konan/platformDef/${target.visibleName}") + include '**/*.def' + if (target in targetsWithoutZlib) { + exclude '**/zlib.def' + } + } + } +} + +task listDist(type: Exec) { + commandLine 'find', distDir +} + +task distRuntime(type: Copy) { + dependsOn "${hostName}CrossDistRuntime" +} + +task distEndorsedLibraries { + dependsOn "${hostName}CrossDistEndorsedLibraries" +} + +task distStdlibCache { + if (hostName in cacheableTargetNames) { + dependsOn("${hostName}StdlibCache") + } +} + +task distEndorsedCache { + if (hostName in cacheableTargetNames) { + dependsOn("${hostName}EndorsedCache") + } +} + +def stdlib = 'klib/common/stdlib' +def stdlibDefaultComponent = "$stdlib/default" +def endorsedLibs = 'klib/common/endorsedLibraries' +def endorsedLibsBase = 'klib/common' + +task crossDistRuntime(type: Copy) { + dependsOn.addAll(targetList.collect { "${it}CrossDistRuntime" }) +} + +task crossDistEndorsedLibraries(type: Copy) { + dependsOn.addAll(targetList.collect { "${it}CrossDistEndorsedLibraries" }) +} + +task crossDistPlatformLibs { + dependsOn.addAll(targetList.collect { "${it}PlatformLibs" }) +} + +task crossDistStdlibCache { + dependsOn.addAll(targetList.findAll { it in cacheableTargetNames }.collect { "${it}StdlibCache" }) +} + +task crossDistEndorsedCache { + dependsOn.addAll(targetList.findAll { it in cacheableTargetNames }.collect { "${it}EndorsedCache" }) +} + +targetList.each { target -> + task("${target}CrossDistRuntime", type: Copy) { + dependsOn ":runtime:${target}Runtime" + dependsOn ":backend.native:${target}Stdlib" + + destinationDir distDir + + from(project(':runtime').file("build/${target}Stdlib")) { + include('**') + into(stdlib) + eachFile { + if (name == 'manifest') { + def existingManifest = file("$destinationDir/$path") + if (existingManifest.exists()) { + UtilsKt.mergeManifestsByTargets(project, file, existingManifest) + exclude() + } + } + } + } + from(project(':runtime').file("build/bitcode/main/$target")) { + include("runtime.bc") + into("$stdlibDefaultComponent/targets/$target/native") + } + from(project(':runtime').file("build/bitcode/main/$target")) { + include("*.bc") + exclude("runtime.bc") + into("konan/targets/$target/native") + } + if (target == 'wasm32') { + into("$stdlibDefaultComponent/targets/wasm32/included") { + from(project(':runtime').file('src/main/js')) + from(project(':runtime').file('src/launcher/js')) + from(project(':Interop:JsRuntime').file('src/main/js')) + } + } + } + + task("${target}PlatformLibs") { + dependsOn ":platformLibs:${target}Install" + if (target in cacheableTargetNames) { + dependsOn(":platformLibs:${target}Cache") + } + } + + if (target in cacheableTargetNames) { + task "${target}StdlibCache" { + dependsOn ":platformLibs:${target}StdlibCache" + } + + task "${target}EndorsedCache" { + dependsOn ":endorsedLibraries:${target}Cache" + } + } + + task("${target}CrossDist") { + dependsOn "${target}CrossDistRuntime", "distCompiler", "${target}CrossDistEndorsedLibraries" + if (target in cacheableTargetNames) { + dependsOn "${target}StdlibCache", "${target}EndorsedCache" + } + } + + task("${target}CrossDistEndorsedLibraries", type: Copy) { + dependsOn ":endorsedLibraries:${target}EndorsedLibraries" + + destinationDir distDir + from(project(':endorsedLibraries').file("build")) { + include('**') + into("$endorsedLibsBase") + } + } +} + +task distPlatformLibs { + dependsOn ':platformLibs:hostInstall' + dependsOn ':platformLibs:hostCache' +} + +task dist { + dependsOn "distCompiler", + "distRuntime", + "distEndorsedLibraries", + "distDef", + "distStdlibCache", + "distEndorsedCache" +} + +task crossDist { + dependsOn "distCompiler", + "crossDistRuntime", + "crossDistEndorsedLibraries", + "distDef", + "crossDistStdlibCache", + "crossDistEndorsedCache" +} + +task bundle { + dependsOn 'bundleRegular', 'bundlePrebuilt' +} + +task bundleRegular(type: (isWindows()) ? Zip : Tar) { + def simpleOsName = HostManager.simpleOsName() + archiveBaseName.set("kotlin-native-$simpleOsName-$konanVersionFull") + from("$project.rootDir/dist") { + include '**' + exclude 'dependencies' + exclude 'klib/testLibrary' + // Don't include platform libraries into the bundle (generate them at the user side instead). + exclude 'klib/platform' + // Exclude platform libraries caches too. Keep caches for stdlib and endorsed libs. + exclude 'klib/cache/*/org.jetbrains.kotlin.native.platform.*/**' + into archiveBaseName + } + from(project.rootDir) { + include 'licenses/**' + exclude '**/xcode_license.pdf' + into archiveBaseName + } +} + +task bundlePrebuilt(type: (isWindows()) ? Zip : Tar) { + dependsOn("crossDistPlatformLibs") + def simpleOsName = HostManager.simpleOsName() + archiveBaseName.set("kotlin-native-prebuilt-$simpleOsName-$konanVersionFull") + from("$project.rootDir/dist") { + include '**' + exclude 'dependencies' + exclude 'klib/testLibrary' + into archiveBaseName + } + from(project.rootDir) { + include 'licenses/**' + into archiveBaseName + } +} + +configure([bundleRegular, bundlePrebuilt]) { + dependsOn("crossDist") + dependsOn("crossDistStdlibCache") + dependsOn("crossDistEndorsedCache") + dependsOn("distSources") + dependsOn("distDef") + from(project.rootDir) { + include 'DISTRO_README.md' + rename { + return "README.md" + } + into baseName + } + from(project.rootDir) { + include 'RELEASE_NOTES.md' + into baseName + } + + destinationDirectory.set(file('.')) + + if (isWindows()) { + zip64 true + } else { + archiveExtension.set('tar.gz') + compression = Compression.GZIP + } +} + +task 'tc-dist'(type: (isWindows()) ? Zip : Tar) { + dependsOn('distPlatformLibs') + dependsOn('dist') + dependsOn('distSources') + def simpleOsName = HostManager.simpleOsName() + archiveBaseName.set("kotlin-native-dist-$simpleOsName-$konanVersionFull") + from("$project.rootDir/dist") { + include '**' + exclude 'dependencies' + into archiveBaseName + } + + destinationDirectory.set(file('.')) + + if (isWindows()) { + zip64 true + } else { + archiveExtension.set('tar.gz') + compression = Compression.GZIP + } +} + +task samples { + dependsOn 'samplesZip', 'samplesTar' +} + +task performance { + dependsOn 'dist' + dependsOn ':performance:clean' + dependsOn ':performance:konanRun' +} + +task samplesZip(type: Zip) +task samplesTar(type: Tar) { + extension = 'tar.gz' + compression = Compression.GZIP +} + +configure([samplesZip, samplesTar]) { + baseName "kotlin-native-samples-$konanVersionFull" + destinationDir = projectDir + into(baseName) + + from(file('samples')) { + // Process properties files separately. + exclude '**/gradle.properties' + } + + from(project.rootDir) { + include 'licenses/**' + } + + from(file('samples')) { + include '**/gradle.properties' + filter { + it.startsWith('org.jetbrains.kotlin.native.home=') || it.startsWith('# Use custom Kotlin/Native home:') ? null : it + } + } + + // Exclude build artifacts. + exclude '**/build' + exclude '**/.gradle' + exclude '**/.idea' + exclude '**/*.kt.bc-build/' +} + +task copy_samples(dependsOn: 'copySamples') +task copySamples(type: CopySamples) { + destinationDir file('build/samples-under-test') +} + +task uploadBundle { + dependsOn ':bundle' + if (isMac()) { + dependsOn ':bundleRestricted' + } + doLast { + def kind = (konanVersionFull.meta == MetaVersion.DEV) ? "dev" : "releases" + def ftpSettings = [ + server: project.findProperty("cdnUrl") ?: System.getenv("CDN_URL"), + userid: project.findProperty("cdnUser") ?: System.getenv("CDN_USER"), + password: project.findProperty("cdnPass") ?: System.getenv("CDN_PASS"), + remoteDir: "/builds/$kind/$konanVersion/${HostManager.simpleOsName()}" + ] + ant { + taskdef(name: 'ftp', + classname: 'org.apache.tools.ant.taskdefs.optional.net.FTP', + classpath: configurations.ftpAntTask.asPath) + ftp([action: "mkdir"] + ftpSettings) + ftp(ftpSettings) { + fileset(file: bundle.archivePath) + } + if (isMac()) { + ftp(ftpSettings) { + fileset(file: bundleRestricted.archivePath) + } + } + } + } +} + +task teamcityCompilerVersion { + doLast { + println("##teamcity[setParameter name='kotlin.native.version.base' value='$konanVersion']") + println("##teamcity[setParameter name='kotlin.native.version.full' value='$konanVersionFull']") + println("##teamcity[setParameter name='kotlin.native.version.meta' value='${konanVersionFull.meta.toString().toLowerCase()}']") + println("##teamcity[buildNumber '${konanVersionFull.toString(true, true)}']") + } +} + +task clean { + dependsOn subprojects.collect { it.tasks.matching { it.name == "clean" } } + doLast { + delete distDir + delete bundle.outputs.files + delete "${projectDir}/compile_commands.json" + } +} + +task pusher(type: KotlinBuildPusher){ + kotlinVersion = project.kotlinVersion + konanVersion = CompilerVersionGeneratedKt.getCurrentCompilerVersion() + buildServer = "buildserver.labs.intellij.net" + compilerConfigurationId = System.getenv("TEAMCITY_COMPILER_ID") ?: "Kotlin_KotlinDev_Compiler" + overrideConfigurationId = System.getenv("TEAMCITY_OVERRIDE_NATIVE_ID") ?: "Kotlin_KotlinDev_DeployMavenArtifacts_OverrideNative" + token = project.findProperty("teamcityBearToken") ?: System.getenv("TEAMCITY_BEAR_TOKEN") +} + +targetList.each { target -> + CompilationDatabaseKt.mergeCompilationDatabases(project, "${target}CompilationDatabase".toString(), [ + ":common:${target}CompilationDatabase".toString(), + ":runtime:${target}CompilationDatabase".toString() + ]).configure { + outputFile = file("$buildDir/${target}/compile_commands.json") + } +} + +task compdb(type: Copy) { + dependsOn "${hostName}CompilationDatabase" + from "$buildDir/${hostName}/compile_commands.json" + into "$projectDir" +} diff --git a/kotlin-native/cmd/cinterop b/kotlin-native/cmd/cinterop new file mode 100755 index 00000000000..ddaafe2e314 --- /dev/null +++ b/kotlin-native/cmd/cinterop @@ -0,0 +1,20 @@ +#!/usr/bin/env bash + +# Copyright 2010-2017 JetBrains s.r.o. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +DIR="${BASH_SOURCE[0]%/*}" +: ${DIR:="."} + +"${DIR}"/run_konan cinterop "$@" diff --git a/kotlin-native/cmd/cinterop.bat b/kotlin-native/cmd/cinterop.bat new file mode 100644 index 00000000000..7b1e1f57d58 --- /dev/null +++ b/kotlin-native/cmd/cinterop.bat @@ -0,0 +1,17 @@ +@echo off + +rem Copyright 2010-2017 JetBrains s.r.o. +rem +rem Licensed under the Apache License, Version 2.0 (the "License"); +rem you may not use this file except in compliance with the License. +rem You may obtain a copy of the License at +rem +rem http://www.apache.org/licenses/LICENSE-2.0 +rem +rem Unless required by applicable law or agreed to in writing, software +rem distributed under the License is distributed on an "AS IS" BASIS, +rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +rem See the License for the specific language governing permissions and +rem limitations under the License. + +call %~dps0run_konan.bat cinterop %* diff --git a/kotlin-native/cmd/generate-platform b/kotlin-native/cmd/generate-platform new file mode 100755 index 00000000000..6b219a1eafa --- /dev/null +++ b/kotlin-native/cmd/generate-platform @@ -0,0 +1,20 @@ +#!/usr/bin/env bash + +# Copyright 2010-2017 JetBrains s.r.o. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +DIR="${BASH_SOURCE[0]%/*}" +: ${DIR:="."} + +"${DIR}"/run_konan generatePlatformLibraries "$@" diff --git a/kotlin-native/cmd/generate-platform.bat b/kotlin-native/cmd/generate-platform.bat new file mode 100644 index 00000000000..39265eebd01 --- /dev/null +++ b/kotlin-native/cmd/generate-platform.bat @@ -0,0 +1,17 @@ +@echo off + +rem Copyright 2010-2017 JetBrains s.r.o. +rem +rem Licensed under the Apache License, Version 2.0 (the "License"); +rem you may not use this file except in compliance with the License. +rem You may obtain a copy of the License at +rem +rem http://www.apache.org/licenses/LICENSE-2.0 +rem +rem Unless required by applicable law or agreed to in writing, software +rem distributed under the License is distributed on an "AS IS" BASIS, +rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +rem See the License for the specific language governing permissions and +rem limitations under the License. + +call %~dps0run_konan.bat generatePlatformLibraries %* diff --git a/kotlin-native/cmd/jsinterop b/kotlin-native/cmd/jsinterop new file mode 100755 index 00000000000..f550237d48a --- /dev/null +++ b/kotlin-native/cmd/jsinterop @@ -0,0 +1,20 @@ +#!/usr/bin/env bash + +# Copyright 2010-2017 JetBrains s.r.o. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +DIR="${BASH_SOURCE[0]%/*}" +: ${DIR:="."} + +"${DIR}"/run_konan jsinterop "$@" diff --git a/kotlin-native/cmd/jsinterop.bat b/kotlin-native/cmd/jsinterop.bat new file mode 100644 index 00000000000..a83bc2792e6 --- /dev/null +++ b/kotlin-native/cmd/jsinterop.bat @@ -0,0 +1,17 @@ +@echo off + +rem Copyright 2010-2017 JetBrains s.r.o. +rem +rem Licensed under the Apache License, Version 2.0 (the "License"); +rem you may not use this file except in compliance with the License. +rem You may obtain a copy of the License at +rem +rem http://www.apache.org/licenses/LICENSE-2.0 +rem +rem Unless required by applicable law or agreed to in writing, software +rem distributed under the License is distributed on an "AS IS" BASIS, +rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +rem See the License for the specific language governing permissions and +rem limitations under the License. + +call %~dps0run_konan.bat jsinterop %* diff --git a/kotlin-native/cmd/klib b/kotlin-native/cmd/klib new file mode 100755 index 00000000000..8d47e413e0d --- /dev/null +++ b/kotlin-native/cmd/klib @@ -0,0 +1,20 @@ +#!/usr/bin/env bash + +# Copyright 2010-2017 JetBrains s.r.o. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +DIR="${BASH_SOURCE[0]%/*}" +: ${DIR:="."} + +"${DIR}"/run_konan klib "$@" diff --git a/kotlin-native/cmd/klib.bat b/kotlin-native/cmd/klib.bat new file mode 100644 index 00000000000..cd3336c7598 --- /dev/null +++ b/kotlin-native/cmd/klib.bat @@ -0,0 +1,17 @@ +@echo off + +rem Copyright 2010-2017 JetBrains s.r.o. +rem +rem Licensed under the Apache License, Version 2.0 (the "License"); +rem you may not use this file except in compliance with the License. +rem You may obtain a copy of the License at +rem +rem http://www.apache.org/licenses/LICENSE-2.0 +rem +rem Unless required by applicable law or agreed to in writing, software +rem distributed under the License is distributed on an "AS IS" BASIS, +rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +rem See the License for the specific language governing permissions and +rem limitations under the License. + +call %~dps0run_konan.bat klib %* diff --git a/kotlin-native/cmd/konan-lldb b/kotlin-native/cmd/konan-lldb new file mode 100644 index 00000000000..10376d4bf43 --- /dev/null +++ b/kotlin-native/cmd/konan-lldb @@ -0,0 +1,18 @@ +#!/usr/bin/env bash +# +# Copyright 2010-2018 JetBrains s.r.o. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +DISTDIR=$(dirname $0)/.. +exec lldb -o "command script import $DISTDIR/tools/konan_lldb.py" $* diff --git a/kotlin-native/cmd/konanc b/kotlin-native/cmd/konanc new file mode 100755 index 00000000000..5ef55695419 --- /dev/null +++ b/kotlin-native/cmd/konanc @@ -0,0 +1,20 @@ +#!/usr/bin/env bash + +# Copyright 2010-2017 JetBrains s.r.o. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +DIR="${BASH_SOURCE[0]%/*}" +: ${DIR:="."} + +"${DIR}"/run_konan konanc "$@" diff --git a/kotlin-native/cmd/konanc.bat b/kotlin-native/cmd/konanc.bat new file mode 100644 index 00000000000..1c015cc6c78 --- /dev/null +++ b/kotlin-native/cmd/konanc.bat @@ -0,0 +1,17 @@ +@echo off + +rem Copyright 2010-2017 JetBrains s.r.o. +rem +rem Licensed under the Apache License, Version 2.0 (the "License"); +rem you may not use this file except in compliance with the License. +rem You may obtain a copy of the License at +rem +rem http://www.apache.org/licenses/LICENSE-2.0 +rem +rem Unless required by applicable law or agreed to in writing, software +rem distributed under the License is distributed on an "AS IS" BASIS, +rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +rem See the License for the specific language governing permissions and +rem limitations under the License. + +call %~dps0run_konan.bat konanc %* diff --git a/kotlin-native/cmd/kotlinc b/kotlin-native/cmd/kotlinc new file mode 100755 index 00000000000..5ef55695419 --- /dev/null +++ b/kotlin-native/cmd/kotlinc @@ -0,0 +1,20 @@ +#!/usr/bin/env bash + +# Copyright 2010-2017 JetBrains s.r.o. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +DIR="${BASH_SOURCE[0]%/*}" +: ${DIR:="."} + +"${DIR}"/run_konan konanc "$@" diff --git a/kotlin-native/cmd/kotlinc-native b/kotlin-native/cmd/kotlinc-native new file mode 100755 index 00000000000..5ef55695419 --- /dev/null +++ b/kotlin-native/cmd/kotlinc-native @@ -0,0 +1,20 @@ +#!/usr/bin/env bash + +# Copyright 2010-2017 JetBrains s.r.o. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +DIR="${BASH_SOURCE[0]%/*}" +: ${DIR:="."} + +"${DIR}"/run_konan konanc "$@" diff --git a/kotlin-native/cmd/kotlinc-native.bat b/kotlin-native/cmd/kotlinc-native.bat new file mode 100644 index 00000000000..1c015cc6c78 --- /dev/null +++ b/kotlin-native/cmd/kotlinc-native.bat @@ -0,0 +1,17 @@ +@echo off + +rem Copyright 2010-2017 JetBrains s.r.o. +rem +rem Licensed under the Apache License, Version 2.0 (the "License"); +rem you may not use this file except in compliance with the License. +rem You may obtain a copy of the License at +rem +rem http://www.apache.org/licenses/LICENSE-2.0 +rem +rem Unless required by applicable law or agreed to in writing, software +rem distributed under the License is distributed on an "AS IS" BASIS, +rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +rem See the License for the specific language governing permissions and +rem limitations under the License. + +call %~dps0run_konan.bat konanc %* diff --git a/kotlin-native/cmd/kotlinc.bat b/kotlin-native/cmd/kotlinc.bat new file mode 100644 index 00000000000..1c015cc6c78 --- /dev/null +++ b/kotlin-native/cmd/kotlinc.bat @@ -0,0 +1,17 @@ +@echo off + +rem Copyright 2010-2017 JetBrains s.r.o. +rem +rem Licensed under the Apache License, Version 2.0 (the "License"); +rem you may not use this file except in compliance with the License. +rem You may obtain a copy of the License at +rem +rem http://www.apache.org/licenses/LICENSE-2.0 +rem +rem Unless required by applicable law or agreed to in writing, software +rem distributed under the License is distributed on an "AS IS" BASIS, +rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +rem See the License for the specific language governing permissions and +rem limitations under the License. + +call %~dps0run_konan.bat konanc %* diff --git a/kotlin-native/cmd/run_konan b/kotlin-native/cmd/run_konan new file mode 100755 index 00000000000..310806dc301 --- /dev/null +++ b/kotlin-native/cmd/run_konan @@ -0,0 +1,82 @@ +#!/usr/bin/env bash +# +# Copyright 2010-2017 JetBrains s.r.o. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +TOOL_NAME="$1" +shift + +if [ -z "$JAVACMD" -a -n "$JAVA_HOME" -a -x "$JAVA_HOME/bin/java" ]; then + JAVACMD="$JAVA_HOME/bin/java" +else + JAVACMD=java +fi +[ -n "$JAVACMD" ] || JAVACMD=java + +declare -a java_args +declare -a java_opts +declare -a konan_args + +while [ $# -gt 0 ]; do + case "$1" in + -D*) + java_args=("${java_args[@]}" "$1") + shift + ;; + -J*) + java_args=("${java_args[@]}" "${1:2}") + shift + ;; + --time) + konan_args=("${konan_args[@]}" --time) + java_args=("${java_args[@]}" -Dkonan.profile=true) + TIMECMD=time + shift + ;; + *) + konan_args[${#konan_args[@]}]=$1 + shift + ;; + esac +done + +findHome() { + local source="${BASH_SOURCE[0]}" + while [ -h "$source" ] ; do + local linked="$(readlink "$source")" + local dir="$(cd -P $(dirname "$source") && cd -P $(dirname "$linked") && pwd)" + source="$dir/$(basename "$linked")" + done + (cd -P "$(dirname "$source")/.." && pwd) +} +KONAN_HOME="$(findHome)" + +java_opts=(-ea \ + -Xmx3G \ + -XX:TieredStopAtLevel=1 \ + -Dfile.encoding=UTF-8 \ + ${JAVA_OPTS}) + +# Unset some environment variables which are set by XCode and may potentially affect the tool executed. +while IFS=$'\r' read -r line || [[ -n "$line" ]]; do + unset $line +done < "${KONAN_HOME}/tools/env_blacklist" + +KONAN_JAR="${KONAN_HOME}/konan/lib/kotlin-native.jar" +TROVE_JAR="${KONAN_HOME}/konan/lib/trove4j.jar" +KONAN_CLASSPATH="$KONAN_JAR:$TROVE_JAR" +TOOL_CLASS=org.jetbrains.kotlin.cli.utilities.MainKt +LIBCLANG_DISABLE_CRASH_RECOVERY=1 \ +$TIMECMD "$JAVACMD" "${java_opts[@]}" "${java_args[@]}" -cp "$KONAN_CLASSPATH" "$TOOL_CLASS" "$TOOL_NAME" "${konan_args[@]}" + diff --git a/kotlin-native/cmd/run_konan.bat b/kotlin-native/cmd/run_konan.bat new file mode 100644 index 00000000000..7cc74d98b4f --- /dev/null +++ b/kotlin-native/cmd/run_konan.bat @@ -0,0 +1,91 @@ +@echo off +rem based on scalac.bat from the Scala distribution +rem ########################################################################## +rem # Copyright 2002-2011, LAMP/EPFL +rem # Copyright 2011-2017, JetBrains +rem # +rem # This is free software; see the distribution for copying conditions. +rem # There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A +rem # PARTICULAR PURPOSE. +rem ########################################################################## + +setlocal enabledelayedexpansion +call :set_home +call :set_path + +set "TOOL_NAME=%1" +shift + +if "%_TOOL_CLASS%"=="" set _TOOL_CLASS=org.jetbrains.kotlin.cli.utilities.MainKt + +if not "%JAVA_HOME%"=="" ( + if exist "%JAVA_HOME%\bin\java.exe" set "_JAVACMD=%JAVA_HOME%\bin\java.exe" +) + +if "%_JAVACMD%"=="" set _JAVACMD=java + +set JAVA_ARGS= +set KONAN_ARGS= + +:again +set "ARG=%1" +if not "!ARG!" == "" ( + if "!ARG:~0,2!" == "-D" ( + set "JAVA_ARGS=%JAVA_ARGS% %ARG%" + goto next + ) + if "!ARG:~0,2!" == "-J" ( + set "JAVA_ARGS=%JAVA_ARGS% !ARG:~2!" + goto next + ) + if "!ARG!" == "--time" ( + set "KONAN_ARGS=%KONAN_ARGS% --time" + set "JAVA_ARGS=%JAVA_ARGS% -Dkonan.profile=true" + goto next + ) + + set "KONAN_ARGS=%KONAN_ARGS% %ARG%" + + :next + shift + goto again +) + +set "KONAN_LIB=%_KONAN_HOME%\konan\lib" + +set "KONAN_JAR=%KONAN_LIB%\kotlin-native.jar" +set TROVE_JAR="%KONAN_LIB%\trove4j.jar" + +set "KONAN_CLASSPATH=%KONAN_JAR%;%TROVE_JAR%" + +set JAVA_OPTS=-ea ^ + -Xmx3G ^ + -XX:TieredStopAtLevel=1 ^ + -Dfile.encoding=UTF-8 ^ + %JAVA_OPTS% + +set LIBCLANG_DISABLE_CRASH_RECOVERY=1 + +"%_JAVACMD%" %JAVA_OPTS% %JAVA_ARGS% -cp "%KONAN_CLASSPATH%" %_TOOL_CLASS% %TOOL_NAME% %KONAN_ARGS% + +exit /b %ERRORLEVEL% +goto end + +rem ########################################################################## +rem # subroutines + +:set_home + set _BIN_DIR= + for %%i in (%~sf0) do set _BIN_DIR=%_BIN_DIR%%%~dpsi + set _KONAN_HOME=%_BIN_DIR%.. +goto :eof + +:set_path + rem libclang.dll is dynamically linked and thus requires correct PATH to be loaded. + rem TODO: remove this hack. + if "%KONAN_DATA_DIR%"=="" (set KONAN_DATA_DIR=%USERPROFILE%\.konan) + set "PATH=%KONAN_DATA_DIR%\dependencies\msys2-mingw-w64-x86_64-clang-llvm-lld-compiler_rt-8.0.1\bin;%PATH%" +goto :eof + +:end +endlocal diff --git a/kotlin-native/codestyle/cpp/CLionFormat.xml b/kotlin-native/codestyle/cpp/CLionFormat.xml new file mode 100644 index 00000000000..92e72963b74 --- /dev/null +++ b/kotlin-native/codestyle/cpp/CLionFormat.xml @@ -0,0 +1,56 @@ + + \ No newline at end of file diff --git a/kotlin-native/codestyle/cpp/README.md b/kotlin-native/codestyle/cpp/README.md new file mode 100644 index 00000000000..0a078aa2a1b --- /dev/null +++ b/kotlin-native/codestyle/cpp/README.md @@ -0,0 +1,39 @@ +# Code style for C++ + +**TODO**: Expand beyond naming and formatting + +## Headers + +* Headers should live in the same folder with it's implementation counterpart (if there's one) +* Headers should use header guards + +## Naming + +* Types should use `PascalCase` +* Local variables and function parameters should use `camelCase` +* Global variables should use `camelCase` +* Constants should use `kPascalCase` (with prefix `k`) +* Private functions (not visible outside a compilation unit) should use `camelCase` +* Exported functions (declared in headers or shared with Kotlin) should use `PascalCase` +* Member fields should use `camelCase`. Private member fields should add `_` suffix: `camelCase_` +* Member functions should use `camelCase` +* Macros should use `SCREAMING_SNAKE_CASE` +* namespaces should use `snake_case` +* `enum` and `enum class` members should use `kPascalCase` + +If API is designed to mimic C++ stdlib (e.g. stubbing `` for platforms that do not support it), its allowed +to follow stdlib naming conventions. + +## Formatting + +For automated formatting you can use [config for CLion](codestyle/cpp/CLionFormat.xml) or `clang-format` (see [config](.clang-format) at the repo's root). Note, that CLion uses `clang-format` by default; this can be turned off if you prefer to use rules from `CLionFormat.xml`. + +Formatting rules are designed to closely mirror [Kotlin rules](https://kotlinlang.org/docs/reference/coding-conventions.html). + +* Use spaces instead of tabs. Indentation width is 4 spaces. Continuation width is 8 spaces +* Do not indent namespaces +* Visibility modifiers are placed without indentation +* All operators should be wrapped with a space or a line break +* In pointer and reference definitions `*` and `&` should be placed on a type instead of a variable +* In pointer to functions prefer not to use `*` at all. +* Add a space between `template` and `<` diff --git a/kotlin-native/common/build.gradle.kts b/kotlin-native/common/build.gradle.kts new file mode 100644 index 00000000000..a9bdc671fdb --- /dev/null +++ b/kotlin-native/common/build.gradle.kts @@ -0,0 +1,26 @@ +/* + * Copyright 2010-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +plugins { + id("compile-to-bitcode") +} + +bitcode { + create("hash") + create("files") +} + +val hostName: String by project + +val build by tasks.registering { + dependsOn("${hostName}Hash") + dependsOn("${hostName}Files") +} + +val clean by tasks.registering { + doLast { + delete(buildDir) + } +} diff --git a/kotlin-native/common/src/files/cpp/Files.cpp b/kotlin-native/common/src/files/cpp/Files.cpp new file mode 100644 index 00000000000..9f6aef7662b --- /dev/null +++ b/kotlin-native/common/src/files/cpp/Files.cpp @@ -0,0 +1,34 @@ +/* + * Copyright 2010-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ +#include "Files.h" + +#include + +#ifdef __APPLE__ + +bool renameAtomic(const char* from, const char* to, bool replaceExisting) { + return renamex_np(from, to, replaceExisting ? 0 : RENAME_EXCL) == 0; +} + +#elif _WIN32 + +#include + +bool renameAtomic(const char* from, const char* to, bool replaceExisting) { + return MoveFileExA(from, to, replaceExisting ? MOVEFILE_REPLACE_EXISTING : 0) != 0; +} + +#else + +#include +#include +#include + +bool renameAtomic(const char* from, const char* to, bool replaceExisting) { + return syscall(SYS_renameat2, 0, from, 0, to, replaceExisting ? 0 : RENAME_NOREPLACE) == 0; +} + + +#endif \ No newline at end of file diff --git a/kotlin-native/common/src/files/headers/Files.h b/kotlin-native/common/src/files/headers/Files.h new file mode 100644 index 00000000000..9fe41524868 --- /dev/null +++ b/kotlin-native/common/src/files/headers/Files.h @@ -0,0 +1,20 @@ +/* + * Copyright 2010-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ +#ifndef COMMON_FILES_H +#define COMMON_FILES_H + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +bool renameAtomic(const char* from, const char* to, bool replaceExisting); + +#ifdef __cplusplus +} +#endif + +#endif // COMMON_FILES_H diff --git a/kotlin-native/common/src/hash/cpp/Base64.cpp b/kotlin-native/common/src/hash/cpp/Base64.cpp new file mode 100644 index 00000000000..031b4dc071e --- /dev/null +++ b/kotlin-native/common/src/hash/cpp/Base64.cpp @@ -0,0 +1,184 @@ +/* + * Copyright 2010-2017 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#include +#include + +#include "Base64.h" + +namespace { + +// From https://en.wikibooks.org/wiki/Algorithm_Implementation/Miscellaneous/Base64 +// with minor tweaks. + +#define WHITESPACE 64 +#define EQUALS 65 +#define INVALID 66 + +const char kAlphabet[] = + "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; + +static const unsigned char kDecode[] = { + 66,66,66,66,66,66,66,66,66,66,64,66,66,66,66,66,66,66,66,66,66,66,66,66,66, + 66,66,66,66,66,66,66,66,66,66,66,66,66,66,66,66,66,66,62,66,66,66,63,52,53, + 54,55,56,57,58,59,60,61,66,66,66,65,66,66,66, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, + 10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,66,66,66,66,66,66,26,27,28, + 29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,66,66, + 66,66,66,66,66,66,66,66,66,66,66,66,66,66,66,66,66,66,66,66,66,66,66,66,66, + 66,66,66,66,66,66,66,66,66,66,66,66,66,66,66,66,66,66,66,66,66,66,66,66,66, + 66,66,66,66,66,66,66,66,66,66,66,66,66,66,66,66,66,66,66,66,66,66,66,66,66, + 66,66,66,66,66,66,66,66,66,66,66,66,66,66,66,66,66,66,66,66,66,66,66,66,66, + 66,66,66,66,66,66,66,66,66,66,66,66,66,66,66,66,66,66,66,66,66,66,66,66,66, + 66,66,66,66,66,66 +}; + +} // namespace + +#ifdef __cplusplus +extern "C" { +#endif + +int EncodeBase64( + const void* dataBuf, uint32_t dataLength, void* resultBuf, uint32_t resultSize) { + char *result = reinterpret_cast(resultBuf); + const uint8_t *data = reinterpret_cast(dataBuf); + size_t resultIndex = 0; + size_t x; + uint32_t n = 0; + int padCount = dataLength % 3; + uint8_t n0, n1, n2, n3; + + /* increment over the length of the string, three characters at a time */ + for (x = 0; x < dataLength; x += 3) { + /* these three 8-bit (ASCII) characters become one 24-bit number */ + n = ((uint32_t)data[x]) << 16; + + if ((x+1) < dataLength) + n += ((uint32_t)data[x+1]) << 8; + + if ((x+2) < dataLength) + n += data[x+2]; + + /* this 24-bit number gets separated into four 6-bit numbers */ + n0 = (uint8_t)(n >> 18) & 63; + n1 = (uint8_t)(n >> 12) & 63; + n2 = (uint8_t)(n >> 6) & 63; + n3 = (uint8_t)n & 63; + + /* + * if we have one byte available, then its encoding is spread + * out over two characters + */ + if (resultIndex >= resultSize) + return 1; /* indicate failure: buffer too small */ + result[resultIndex++] = kAlphabet[n0]; + if (resultIndex >= resultSize) + return 1; /* indicate failure: buffer too small */ + result[resultIndex++] = kAlphabet[n1]; + + /* + * if we have only two bytes available, then their encoding is + * spread out over three chars + */ + if ((x+1) < dataLength) { + if (resultIndex >= resultSize) + return 1; /* indicate failure: buffer too small */ + result[resultIndex++] = kAlphabet[n2]; + } + + /* + * if we have all three bytes available, then their encoding is spread + * out over four characters + */ + if ((x+2) < dataLength) { + if (resultIndex >= resultSize) + return 1; /* indicate failure: buffer too small */ + result[resultIndex++] = kAlphabet[n3]; + } + } + + /* + * create and add padding that is required if we did not have a multiple of 3 + * number of characters available + */ + if (padCount > 0) { + for (; padCount < 3; padCount++) { + if (resultIndex >= resultSize) + return 1; /* indicate failure: buffer too small */ + result[resultIndex++] = '='; + } + } + if (resultIndex >= resultSize) + return 1; /* indicate failure: buffer too small */ + + result[resultIndex] = 0; + + return 0; /* indicate success */ +} + +int DecodeBase64( + const char *in, uint32_t inLen, void* outBuf, uint32_t* outLen) { + uint8_t* out = reinterpret_cast(outBuf); + const char* end = in + inLen; + char iter = 0; + size_t buf = 0, len = 0; + + while (in < end) { + // char may be a signed type. Explicitly convert it to an unsigned byte, + // so that indexing into kDecode array is safe. The latter has exactly + // 256 elements, so any unsigned byte value is valid. + uint8_t index = *in++; + unsigned char c = kDecode[index]; + + switch (c) { + case WHITESPACE: continue; /* skip whitespace */ + case INVALID: return 1; /* invalid input, return error */ + case EQUALS: /* pad character, end of data */ + in = end; + continue; + default: + buf = buf << 6 | c; + iter++; // increment the number of iteration + /* If the buffer is full, split it into bytes */ + if (iter == 4) { + if ((len += 3) > *outLen) + return 1; /* buffer overflow */ + *(out++) = (buf >> 16) & 255; + *(out++) = (buf >> 8) & 255; + *(out++) = buf & 255; + buf = 0; iter = 0; + } + } + } + + if (iter == 3) { + if ((len += 2) > *outLen) + return 1; /* buffer overflow */ + *(out++) = (buf >> 10) & 255; + *(out++) = (buf >> 2) & 255; + } + else if (iter == 2) { + if (++len > *outLen) + return 1; /* buffer overflow */ + *(out++) = (buf >> 4) & 255; + } + + *outLen = len; /* modify to reflect the actual output size */ + return 0; +} + +#ifdef __cplusplus +} +#endif diff --git a/kotlin-native/common/src/hash/cpp/City.cpp b/kotlin-native/common/src/hash/cpp/City.cpp new file mode 100644 index 00000000000..cb263dc926f --- /dev/null +++ b/kotlin-native/common/src/hash/cpp/City.cpp @@ -0,0 +1,229 @@ +/* + * Copyright 2010-2017 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#include "City.h" + +#include + +#include + +namespace { + +// Some primes between 2^63 and 2^64 for various uses. +static const uint64_t k0 = 0xc3a5c85c97cb3127ULL; +static const uint64_t k1 = 0xb492b66fbe98f273ULL; +static const uint64_t k2 = 0x9ae16a3b2f90404fULL; + +uint64_t UNALIGNED_LOAD64(const char *p) { + uint64_t result; + memcpy(&result, p, sizeof(result)); + return result; +} + +uint32_t UNALIGNED_LOAD32(const char *p) { + uint32_t result; + memcpy(&result, p, sizeof(result)); + return result; +} + +#define bswap32(x) __builtin_bswap32(x) +#define bswap64(x) __builtin_bswap64(x) + +#ifdef WORDS_BIGENDIAN +#define uint32_in_expected_order(x) (bswap32(x)) +#define uint64_in_expected_order(x) (bswap64(x)) +#else +#define uint32_in_expected_order(x) (x) +#define uint64_in_expected_order(x) (x) +#endif + +uint64_t Fetch64(const char *p) { + return uint64_in_expected_order(UNALIGNED_LOAD64(p)); +} + +uint32_t Fetch32(const char *p) { + return uint32_in_expected_order(UNALIGNED_LOAD32(p)); +} + +uint32_t Rotate32(uint32_t val, int shift) { + // Avoid shifting by 32: doing so yields an undefined result. + return shift == 0 ? val : ((val >> shift) | (val << (32 - shift))); +} + +// Bitwise right rotate. Normally this will compile to a single +// instruction, especially if the shift is a manifest constant. +uint64_t Rotate(uint64_t val, int shift) { + // Avoid shifting by 64: doing so yields an undefined result. + return shift == 0 ? val : ((val >> shift) | (val << (64 - shift))); +} + +uint64_t ShiftMix(uint64_t val) { + return val ^ (val >> 47); +} + +uint64_t HashLen16(uint64_t u, uint64_t v, uint64_t mul) { + // Murmur-inspired hashing. + uint64_t a = (u ^ v) * mul; + a ^= (a >> 47); + uint64_t b = (v ^ a) * mul; + b ^= (b >> 47); + b *= mul; + return b; +} + +typedef std::pair uint128_t; + +uint64_t Hash128to64(const uint128_t& x) { + // Murmur-inspired hashing. + const uint64_t kMul = 0x9ddfea08eb382d69ULL; + uint64_t a = (x.first ^ x.second) * kMul; + a ^= (a >> 47); + uint64_t b = (x.second ^ a) * kMul; + b ^= (b >> 47); + b *= kMul; + return b; +} + +uint64_t HashLen16(uint64_t u, uint64_t v) { + return Hash128to64(uint128_t(u, v)); +} + +uint64_t HashLen0to16(const char *s, size_t len) { + if (len >= 8) { + uint64_t mul = k2 + len * 2; + uint64_t a = Fetch64(s) + k2; + uint64_t b = Fetch64(s + len - 8); + uint64_t c = Rotate(b, 37) * mul + a; + uint64_t d = (Rotate(a, 25) + b) * mul; + return HashLen16(c, d, mul); + } + if (len >= 4) { + uint64_t mul = k2 + len * 2; + uint64_t a = Fetch32(s); + return HashLen16(len + (a << 3), Fetch32(s + len - 4), mul); + } + if (len > 0) { + uint8_t a = s[0]; + uint8_t b = s[len >> 1]; + uint8_t c = s[len - 1]; + uint32_t y = static_cast(a) + (static_cast(b) << 8); + uint32_t z = len + (static_cast(c) << 2); + return ShiftMix(y * k2 ^ z * k0) * k2; + } + return k2; +} + +// This probably works well for 16-byte strings as well, but it may be overkill +// in that case. +static uint64_t HashLen17to32(const char *s, size_t len) { + uint64_t mul = k2 + len * 2; + uint64_t a = Fetch64(s) * k1; + uint64_t b = Fetch64(s + 8); + uint64_t c = Fetch64(s + len - 8) * mul; + uint64_t d = Fetch64(s + len - 16) * k2; + return HashLen16(Rotate(a + b, 43) + Rotate(c, 30) + d, + a + Rotate(b + k2, 18) + c, mul); +} + +// Return a 16-byte hash for 48 bytes. Quick and dirty. +// Callers do best to use "random-looking" values for a and b. +std::pair WeakHashLen32WithSeeds( + uint64_t w, uint64_t x, uint64_t y, uint64_t z, uint64_t a, uint64_t b) { + a += w; + b = Rotate(b + a + z, 21); + uint64_t c = a; + a += x; + a += y; + b += Rotate(a, 44); + return std::make_pair(a + z, b + c); +} + +// Return a 16-byte hash for s[0] ... s[31], a, and b. Quick and dirty. +std::pair WeakHashLen32WithSeeds( + const char* s, uint64_t a, uint64_t b) { + return WeakHashLen32WithSeeds(Fetch64(s), + Fetch64(s + 8), + Fetch64(s + 16), + Fetch64(s + 24), + a, + b); +} + +// Return an 8-byte hash for 33 to 64 bytes. +uint64_t HashLen33to64(const char *s, size_t len) { + uint64_t mul = k2 + len * 2; + uint64_t a = Fetch64(s) * k2; + uint64_t b = Fetch64(s + 8); + uint64_t c = Fetch64(s + len - 24); + uint64_t d = Fetch64(s + len - 32); + uint64_t e = Fetch64(s + 16) * k2; + uint64_t f = Fetch64(s + 24) * 9; + uint64_t g = Fetch64(s + len - 8); + uint64_t h = Fetch64(s + len - 16) * mul; + uint64_t u = Rotate(a + g, 43) + (Rotate(b, 30) + c) * 9; + uint64_t v = ((a + g) ^ d) + f + 1; + uint64_t w = bswap64((u + v) * mul) + h; + uint64_t x = Rotate(e + f, 42) + c; + uint64_t y = (bswap64((v + w) * mul) + g) * mul; + uint64_t z = e + f + c; + a = bswap64((x + z) * mul + y) + b; + b = ShiftMix((z + a) * mul + d + h) * mul; + return b + x; +} + +} // namespace + +extern "C" { + +uint64_t CityHash64(const void* data, size_t len) { + const char* s = reinterpret_cast(data); + if (len <= 32) { + if (len <= 16) { + return HashLen0to16(s, len); + } else { + return HashLen17to32(s, len); + } + } else if (len <= 64) { + return HashLen33to64(s, len); + } + + // For strings over 64 bytes we hash the end first, and then as we + // loop we keep 56 bytes of state: v, w, x, y, and z. + uint64_t x = Fetch64(s + len - 40); + uint64_t y = Fetch64(s + len - 16) + Fetch64(s + len - 56); + uint64_t z = HashLen16(Fetch64(s + len - 48) + len, Fetch64(s + len - 24)); + std::pair v = WeakHashLen32WithSeeds(s + len - 64, len, z); + std::pair w = WeakHashLen32WithSeeds(s + len - 32, y + k1, x); + x = x * k1 + Fetch64(s); + + // Decrease len to the nearest multiple of 64, and operate on 64-byte chunks. + len = (len - 1) & ~static_cast(63); + do { + x = Rotate(x + y + v.first + Fetch64(s + 8), 37) * k1; + y = Rotate(y + v.second + Fetch64(s + 48), 42) * k1; + x ^= w.second; + y += v.first + Fetch64(s + 40); + z = Rotate(z + w.first, 33) * k1; + v = WeakHashLen32WithSeeds(s, v.second * k1, x + w.first); + w = WeakHashLen32WithSeeds(s + 32, z + w.second, y + Fetch64(s + 16)); + std::swap(z, x); + s += 64; + len -= 64; + } while (len != 0); + return HashLen16(HashLen16(v.first, w.first) + ShiftMix(y) * k1 + z, + HashLen16(v.second, w.second) + x); +} + +} // extern "C" diff --git a/kotlin-native/common/src/hash/cpp/Names.cpp b/kotlin-native/common/src/hash/cpp/Names.cpp new file mode 100644 index 00000000000..182eeef3cc7 --- /dev/null +++ b/kotlin-native/common/src/hash/cpp/Names.cpp @@ -0,0 +1,82 @@ +/* + * Copyright 2010-2017 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#include + +#include "Names.h" + +#include "Base64.h" +#include "City.h" +#include "Sha1.h" + +namespace { + +constexpr uint32_t PrintableHexSize(uint32_t input_length) { + return input_length * 2; +} + +void PrintableHex(const uint8_t* data, uint32_t data_length, char* hex) { + static const char* hex_digits = "0123456789ABCDEF"; + for (uint32_t i = 0; i < data_length; ++i) { + *hex++ = hex_digits[(*data >> 4) & 0xf]; + *hex++ = hex_digits[(*data++) & 0xf]; + } +} + +constexpr uint32_t PrintableBase64Size(uint32_t input_length) { + return ((input_length + 2) / 3 * 4) + 1; +} + +void PrintableBase64(const uint8_t* data, uint32_t data_length, char* base64) { + int rv = EncodeBase64(data, data_length, base64, PrintableBase64Size(data_length)); + assert(rv == 0); +} + +} // namespace + +extern "C" { + +// Make local hash out of arbitrary data. +void MakeLocalHash(const void* data, uint32_t size, LocalHash* hash) { + *hash = CityHash64(data, size); +} + +// Make global hash out of arbitrary data. +void MakeGlobalHash(const void* data, uint32_t size, GlobalHash* hash) { + SHA1_CTX ctx; + SHA1Init(&ctx); + SHA1Update(&ctx, reinterpret_cast(data), size); + SHA1Final(&hash->bits[0], &ctx); +} + +// Make printable C string out of local hash. +void PrintableLocalHash(const LocalHash* hash, char* buffer, uint32_t size) { + if (size < PrintableBase64Size(sizeof(*hash))) { + assert(false); + return; + } + PrintableBase64(reinterpret_cast(&hash), sizeof(*hash), buffer); +} + +// Make printable C string out of global hash. +void PrintableGlobalHash(const GlobalHash* hash, char* buffer, uint32_t size) { + if (size < PrintableBase64Size(sizeof(*hash))) { + assert(false); + return; + } + PrintableBase64(hash->bits, sizeof(*hash), buffer); +} + +} // extern "C" diff --git a/kotlin-native/common/src/hash/cpp/Sha1.cpp b/kotlin-native/common/src/hash/cpp/Sha1.cpp new file mode 100644 index 00000000000..73db0b3ac3a --- /dev/null +++ b/kotlin-native/common/src/hash/cpp/Sha1.cpp @@ -0,0 +1,190 @@ +/* + * Copyright 2010-2017 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/* +SHA-1 in C +By Steve Reid +100% Public Domain + +Test Vectors (from FIPS PUB 180-1) +"abc" + A9993E36 4706816A BA3E2571 7850C26C 9CD0D89D +"abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq" + 84983E44 1C3BD26E BAAE4AA1 F95129E5 E54670F1 +A million repetitions of "a" + 34AA973C D4C4DAA4 F61EEB2B DBAD2731 6534016F +*/ + +/* #define LITTLE_ENDIAN * This should be #define'd already, if true. */ +/* #define SHA1HANDSOFF * Copies data before messing with it. */ + +#define SHA1HANDSOFF + +#include +#include +#include + +#include "Sha1.h" + +#define rol(value, bits) (((value) << (bits)) | ((value) >> (32 - (bits)))) + +/* blk0() and blk() perform the initial expand. */ +/* I got the idea of expanding during the round function from SSLeay */ +#if BYTE_ORDER == LITTLE_ENDIAN +#define blk0(i) (block->l[i] = (rol(block->l[i],24)&0xFF00FF00) \ + |(rol(block->l[i],8)&0x00FF00FF)) +#elif BYTE_ORDER == BIG_ENDIAN +#define blk0(i) block->l[i] +#else +#error "Endianness not defined!" +#endif +#define blk(i) (block->l[i&15] = rol(block->l[(i+13)&15]^block->l[(i+8)&15] \ + ^block->l[(i+2)&15]^block->l[i&15],1)) + +/* (R0+R1), R2, R3, R4 are the different operations used in SHA1 */ +#define R0(v,w,x,y,z,i) z+=((w&(x^y))^y)+blk0(i)+0x5A827999+rol(v,5);w=rol(w,30); +#define R1(v,w,x,y,z,i) z+=((w&(x^y))^y)+blk(i)+0x5A827999+rol(v,5);w=rol(w,30); +#define R2(v,w,x,y,z,i) z+=(w^x^y)+blk(i)+0x6ED9EBA1+rol(v,5);w=rol(w,30); +#define R3(v,w,x,y,z,i) z+=(((w|x)&y)|(w&x))+blk(i)+0x8F1BBCDC+rol(v,5);w=rol(w,30); +#define R4(v,w,x,y,z,i) z+=(w^x^y)+blk(i)+0xCA62C1D6+rol(v,5);w=rol(w,30); + +/* Hash a single 512-bit block. This is the core of the algorithm. */ +static void SHA1Transform(uint32_t state[5], const unsigned char buffer[64]) +{ + uint32_t a, b, c, d, e; + typedef union { + unsigned char c[64]; + uint32_t l[16]; + } CHAR64LONG16; +#ifdef SHA1HANDSOFF + CHAR64LONG16 block[1]; /* use array to appear as a pointer */ + memcpy(block, buffer, 64); +#else + /* The following had better never be used because it causes the + * pointer-to-const buffer to be cast into a pointer to non-const. + * And the result is written through. I threw a "const" in, hoping + * this will cause a diagnostic. + */ + CHAR64LONG16* block = (const CHAR64LONG16*)buffer; +#endif + /* Copy context->state[] to working vars */ + a = state[0]; + b = state[1]; + c = state[2]; + d = state[3]; + e = state[4]; + /* 4 rounds of 20 operations each. Loop unrolled. */ + R0(a,b,c,d,e, 0); R0(e,a,b,c,d, 1); R0(d,e,a,b,c, 2); R0(c,d,e,a,b, 3); + R0(b,c,d,e,a, 4); R0(a,b,c,d,e, 5); R0(e,a,b,c,d, 6); R0(d,e,a,b,c, 7); + R0(c,d,e,a,b, 8); R0(b,c,d,e,a, 9); R0(a,b,c,d,e,10); R0(e,a,b,c,d,11); + R0(d,e,a,b,c,12); R0(c,d,e,a,b,13); R0(b,c,d,e,a,14); R0(a,b,c,d,e,15); + R1(e,a,b,c,d,16); R1(d,e,a,b,c,17); R1(c,d,e,a,b,18); R1(b,c,d,e,a,19); + R2(a,b,c,d,e,20); R2(e,a,b,c,d,21); R2(d,e,a,b,c,22); R2(c,d,e,a,b,23); + R2(b,c,d,e,a,24); R2(a,b,c,d,e,25); R2(e,a,b,c,d,26); R2(d,e,a,b,c,27); + R2(c,d,e,a,b,28); R2(b,c,d,e,a,29); R2(a,b,c,d,e,30); R2(e,a,b,c,d,31); + R2(d,e,a,b,c,32); R2(c,d,e,a,b,33); R2(b,c,d,e,a,34); R2(a,b,c,d,e,35); + R2(e,a,b,c,d,36); R2(d,e,a,b,c,37); R2(c,d,e,a,b,38); R2(b,c,d,e,a,39); + R3(a,b,c,d,e,40); R3(e,a,b,c,d,41); R3(d,e,a,b,c,42); R3(c,d,e,a,b,43); + R3(b,c,d,e,a,44); R3(a,b,c,d,e,45); R3(e,a,b,c,d,46); R3(d,e,a,b,c,47); + R3(c,d,e,a,b,48); R3(b,c,d,e,a,49); R3(a,b,c,d,e,50); R3(e,a,b,c,d,51); + R3(d,e,a,b,c,52); R3(c,d,e,a,b,53); R3(b,c,d,e,a,54); R3(a,b,c,d,e,55); + R3(e,a,b,c,d,56); R3(d,e,a,b,c,57); R3(c,d,e,a,b,58); R3(b,c,d,e,a,59); + R4(a,b,c,d,e,60); R4(e,a,b,c,d,61); R4(d,e,a,b,c,62); R4(c,d,e,a,b,63); + R4(b,c,d,e,a,64); R4(a,b,c,d,e,65); R4(e,a,b,c,d,66); R4(d,e,a,b,c,67); + R4(c,d,e,a,b,68); R4(b,c,d,e,a,69); R4(a,b,c,d,e,70); R4(e,a,b,c,d,71); + R4(d,e,a,b,c,72); R4(c,d,e,a,b,73); R4(b,c,d,e,a,74); R4(a,b,c,d,e,75); + R4(e,a,b,c,d,76); R4(d,e,a,b,c,77); R4(c,d,e,a,b,78); R4(b,c,d,e,a,79); + /* Add the working vars back into context.state[] */ + state[0] += a; + state[1] += b; + state[2] += c; + state[3] += d; + state[4] += e; + /* Wipe variables */ + a = b = c = d = e = 0; +#ifdef SHA1HANDSOFF + memset(block, '\0', sizeof(block)); +#endif +} + +#ifdef __cplusplus +extern "C" { +#endif + +/* SHA1Init - Initialize new context */ +void SHA1Init(SHA1_CTX* context) +{ + /* SHA1 initialization constants */ + context->state[0] = 0x67452301; + context->state[1] = 0xEFCDAB89; + context->state[2] = 0x98BADCFE; + context->state[3] = 0x10325476; + context->state[4] = 0xC3D2E1F0; + context->count[0] = context->count[1] = 0; +} + + +/* Run your data through this. */ +void SHA1Update(SHA1_CTX* context, const unsigned char* data, uint32_t len) +{ + uint32_t i, j; + + j = context->count[0]; + if ((context->count[0] += len << 3) < j) + context->count[1]++; + context->count[1] += (len>>29); + j = (j >> 3) & 63; + if ((j + len) > 63) { + memcpy(&context->buffer[j], data, (i = 64-j)); + SHA1Transform(context->state, context->buffer); + for ( ; i + 63 < len; i += 64) { + SHA1Transform(context->state, &data[i]); + } + j = 0; + } + else i = 0; + memcpy(&context->buffer[j], &data[i], len - i); +} + +/* Add padding and return the message digest. */ +void SHA1Final(unsigned char digest[20], SHA1_CTX* context) +{ + unsigned i; + unsigned char finalcount[8]; + unsigned char c; + + for (i = 0; i < 8; i++) { + finalcount[i] = (unsigned char)((context->count[(i >= 4 ? 0 : 1)] + >> ((3-(i & 3)) * 8) ) & 255); /* Endian independent */ + } + c = 0200; + SHA1Update(context, &c, 1); + while ((context->count[0] & 504) != 448) { + c = 0000; + SHA1Update(context, &c, 1); + } + SHA1Update(context, finalcount, 8); /* Should cause a SHA1Transform() */ + for (i = 0; i < 20; i++) { + digest[i] = (unsigned char) + ((context->state[i>>2] >> ((3-(i & 3)) * 8) ) & 255); + } + /* Wipe variables */ + memset(context, '\0', sizeof(*context)); + memset(&finalcount, '\0', sizeof(finalcount)); +} + +#ifdef __cplusplus +} +#endif diff --git a/kotlin-native/common/src/hash/headers/Base64.h b/kotlin-native/common/src/hash/headers/Base64.h new file mode 100644 index 00000000000..1efcf118416 --- /dev/null +++ b/kotlin-native/common/src/hash/headers/Base64.h @@ -0,0 +1,35 @@ +/* + * Copyright 2010-2017 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#ifndef COMMON_BASE64_H +#define COMMON_BASE64_H + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +int EncodeBase64( + const void* input, uint32_t inputLen, void* output, uint32_t outputLen); + +int DecodeBase64( + const char* input, uint32_t inputLen, void* output, uint32_t* outputLen); + +#ifdef __cplusplus +} +#endif + +#endif // COMMON_BASE64_H diff --git a/kotlin-native/common/src/hash/headers/City.h b/kotlin-native/common/src/hash/headers/City.h new file mode 100644 index 00000000000..4adf2cc3f8f --- /dev/null +++ b/kotlin-native/common/src/hash/headers/City.h @@ -0,0 +1,35 @@ +/* + * Copyright 2010-2017 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#ifndef COMMON_CITY_H +#define COMMON_CITY_H + +// CityHash, by Geoff Pike and Jyrki Alakuijala. + +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +// Hash function for a byte array. +uint64_t CityHash64(const void* buf, size_t len); + +#ifdef __cplusplus +} +#endif + +#endif // COMMON_CITY_H diff --git a/kotlin-native/common/src/hash/headers/Names.h b/kotlin-native/common/src/hash/headers/Names.h new file mode 100644 index 00000000000..bb3823907a1 --- /dev/null +++ b/kotlin-native/common/src/hash/headers/Names.h @@ -0,0 +1,58 @@ +/* + * Copyright 2010-2017 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#ifndef COMMON_NAMES_H +#define COMMON_NAMES_H + +#include + +// All names in system are stored as hashes (or maybe, for debug builds, +// as pointers to uniqued C strings containing names?). +// There are two types of hashes: +// - local hash, must be unique per class/scope (CityHash64 is being used) +// - global hash, must be unique globally (SHA1 is being used) +// Generic guideline is that global hash is being used in global persistent +// context, while local hashes are more local in scope. +// Local hash. +typedef int64_t LocalHash; +// Hash of field name. +typedef LocalHash FieldNameHash; +// Hash of open method name. +typedef LocalHash MethodNameHash; +// Global hash. +typedef struct { + uint8_t bits[20]; +} GlobalHash; +// Hash of function name. +typedef GlobalHash FunctionNameHash; +// Hash of class name. +typedef GlobalHash ClassNameHash; + +#ifdef __cplusplus +extern "C" { +#endif +// Make local hash out of arbitrary data. +void MakeLocalHash(const void* data, uint32_t size, LocalHash* hash); +// Make global hash out of arbitrary data. +void MakeGlobalHash(const void* data, uint32_t size, GlobalHash* hash); +// Make printable C string out of local hash. +void PrintableLocalHash(const LocalHash* hash, char* buffer, uint32_t size); +// Make printable C string out of global hash. +void PrintableGlobalHash(const GlobalHash* hash, char* buffer, uint32_t size); +#ifdef __cplusplus +} // extern "C" +#endif + +#endif // COMMON_NAMES_H diff --git a/kotlin-native/common/src/hash/headers/Sha1.h b/kotlin-native/common/src/hash/headers/Sha1.h new file mode 100644 index 00000000000..07158174d94 --- /dev/null +++ b/kotlin-native/common/src/hash/headers/Sha1.h @@ -0,0 +1,45 @@ +/* + * Copyright 2010-2017 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#ifndef COMMON_SHA1_H +#define COMMON_SHA1_H + +#include + +/* +SHA-1 in C +By Steve Reid +100% Public Domain +*/ + +#ifdef __cplusplus +extern "C" { +#endif + +typedef struct SHA1_CTX { + uint32_t state[5]; + uint32_t count[2]; + unsigned char buffer[64]; +} SHA1_CTX; + +void SHA1Init(SHA1_CTX* context); +void SHA1Update(SHA1_CTX* context, const unsigned char* data, uint32_t len); +void SHA1Final(unsigned char digest[20], SHA1_CTX* context); + +#ifdef __cplusplus +} +#endif + +#endif // COMMON_SHA1_H diff --git a/kotlin-native/dependencies/build.gradle b/kotlin-native/dependencies/build.gradle new file mode 100644 index 00000000000..6e467ac4448 --- /dev/null +++ b/kotlin-native/dependencies/build.gradle @@ -0,0 +1,115 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ +import groovy.transform.stc.ClosureParams +import groovy.transform.stc.FromString +import org.jetbrains.kotlin.konan.target.* +import static org.jetbrains.kotlin.konan.target.KonanTarget.* +import org.jetbrains.kotlin.konan.util.Named +import org.jetbrains.kotlin.konan.properties.KonanPropertiesLoader +import org.jetbrains.kotlin.konan.util.ArchiveType +import org.jetbrains.kotlin.konan.util.DependencyProcessor + +import static org.jetbrains.kotlin.konan.util.VisibleNamedKt.getVisibleName + +buildscript { + apply from: "$rootDir/gradle/kotlinGradlePlugin.gradle" + + repositories { + maven { + url = 'https://cache-redirector.jetbrains.com/jcenter' + } + } +} + +/** + * Downloads dependencies from the given URL into the given directory. + * The set of dependencies is determined by konanPropertiesLoader. + */ +class NativeDep extends DefaultTask { + static final String baseUrl = "https://cache-redirector.jetbrains.com/download.jetbrains.com/kotlin/native" + + KonanPropertiesLoader konanPropertiesLoader = null + + final File getBaseOutDir() { + final File res = project.rootProject.ext.dependenciesDir + res.mkdirs() + return res + } + + @TaskAction + void downloadAndExtract() { + def downloader = new DependencyProcessor(baseOutDir, konanPropertiesLoader, baseUrl, false, ArchiveType.systemDefault) + downloader.showInfo = false + downloader.run() + } +} + +enum DependencyKind { + LLVM( "llvm", { it.llvmHome }, { "llvmDir" } ), + LIBFFI( "libffi", { it.libffiDir } ) + + + DependencyKind(String name, + @ClosureParams(value = FromString.class, options = "KonanPropertiesLoader") Closure dirGetter, + @ClosureParams(value = FromString.class, options = "KonanTarget") Closure propertyNameGetter = + {target -> "${target.visibleName}${name.capitalize()}Dir"}) { + this.name = name + this.dirGetter = dirGetter + this.propertyNameGetter = propertyNameGetter + } + + private String name + private Closure dirGetter // KonanProperties -> String + private Closure propertyNameGetter // KonanTarget -> String + + String getDirectory(KonanPropertiesLoader properties) { + return dirGetter(properties) + } + + String getPropertyName(KonanTarget target) { + return propertyNameGetter(target) + } + + String toString() { return name } +} + +def platformManager = rootProject.ext.platformManager + + +platformManager.filteredOutEnabledButNotSupported.each { target -> + def loader = platformManager.loader(target) + + task "${target}Dependencies"(type: NativeDep) { + konanPropertiesLoader = loader + } + + // Also resolves all dependencies: + final DependencyProcessor dependencyProcessor = new DependencyProcessor( + project.rootProject.ext.dependenciesDir, + loader.properties, + loader.dependencies, + NativeDep.baseUrl, + false, + ArchiveType.systemDefault + ) + + DependencyKind.values().each { kind -> + def dir = kind.getDirectory(loader) + if (dir != null) { + String path = dependencyProcessor.resolve(dir).canonicalPath + rootProject.ext.set(kind.getPropertyName(target), path) + } + } +} + +task update(type: Copy) { + dependsOn tasks.withType(NativeDep) +} + +task rmDotKonan(type: Delete) { + def dir = System.getenv("KONAN_DATA_DIR") ?: "${System.getProperty("user.home")}/.konan" + delete dir +} + diff --git a/kotlin-native/dependencyPacker/build.gradle.kts b/kotlin-native/dependencyPacker/build.gradle.kts new file mode 100644 index 00000000000..0f53b258637 --- /dev/null +++ b/kotlin-native/dependencyPacker/build.gradle.kts @@ -0,0 +1,90 @@ +/* + * Copyright 2010-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ +import org.jetbrains.kotlin.konan.properties.KonanPropertiesLoader +import org.jetbrains.kotlin.konan.util.DependencyProcessor +import org.jetbrains.kotlin.konan.target.KonanTarget +import org.jetbrains.kotlin.konan.target.Distribution +import org.jetbrains.kotlin.konan.target.presetName + +/** + * Creates an archive with LLVM distribution without files + * that are not required for Kotlin/Native. + * + * For example, it excludes binaries that are part of LLVM testing infrastructure. + */ +inline fun createLlvmPackingTask( + host: KonanTarget, + whitelist: File?, + blacklist: File?, + crossinline additionalConfiguration: T.() -> Unit +) { + val distribution = Distribution(rootProject.projectDir.absolutePath) + val reducedLlvmAppendix = distribution.properties + .getProperty("reducedLlvmAppendix") + val propertiesLoader = object : KonanPropertiesLoader( + host = host, + target = host, + properties = distribution.properties, + baseDir = DependencyProcessor.defaultDependenciesRoot.absolutePath + ) {} + + val hostName = host.presetName.capitalize() + val downloadTaskName = "downloadLlvmFor$hostName" + + tasks.create(downloadTaskName) { + doFirst { + propertiesLoader.downloadDependencies() + } + } + tasks.create("packLlvmFor$hostName") { + dependsOn(downloadTaskName) + additionalConfiguration() + + description = "Packs LLVM dependency for $hostName into archive" + group = "Distribution packing" + + // > When both inclusion and exclusion are used, + // > only files/directories that match at least one of the include patterns + // > and don't match any of the exclude patterns are used. + // + // See: https://ant.apache.org/manual/dirtasks.html + whitelist?.let { + it.readLines() + .filter { !it.startsWith("#") && it.isNotBlank() } + .forEach(this::include) + } + blacklist?.let { + it.readLines() + .filter { !it.startsWith("#") && it.isNotBlank() } + .forEach(this::exclude) + } + from(propertiesLoader.absoluteLlvmHome) + destinationDirectory.set(buildDir.resolve("artifacts")) + archiveBaseName.set(propertiesLoader.llvmHome) + archiveAppendix.set(reducedLlvmAppendix) + } +} + +createLlvmPackingTask( + KonanTarget.MACOS_X64, + whitelist = file("macos_llvm_whitelist"), + blacklist = null +) { + compression = Compression.GZIP +} + +createLlvmPackingTask( + KonanTarget.LINUX_X64, + whitelist = file("linux_llvm_whitelist"), + blacklist = file("linux_llvm_blacklist") +) { + compression = Compression.GZIP +} + +createLlvmPackingTask( + KonanTarget.MINGW_X64, + whitelist = file("mingw_llvm_whitelist"), + blacklist = file("mingw_llvm_blacklist") +) {} \ No newline at end of file diff --git a/kotlin-native/dependencyPacker/linux_llvm_blacklist b/kotlin-native/dependencyPacker/linux_llvm_blacklist new file mode 100644 index 00000000000..130477178c4 --- /dev/null +++ b/kotlin-native/dependencyPacker/linux_llvm_blacklist @@ -0,0 +1,6 @@ +# Unused large files +lib/liblldb.so +lib/liblldb.so.8 +lib/libLTO.so +lib/libLTO.so.8 +lib/python2.7/site-packages/lldb/_lldb.so \ No newline at end of file diff --git a/kotlin-native/dependencyPacker/linux_llvm_whitelist b/kotlin-native/dependencyPacker/linux_llvm_whitelist new file mode 100644 index 00000000000..ffa1596665d --- /dev/null +++ b/kotlin-native/dependencyPacker/linux_llvm_whitelist @@ -0,0 +1,28 @@ +# Compilation process +bin/clang +bin/clang++ +bin/clang-8 + +# Linkage +bin/dsymutil +bin/lld +bin/ld.lld +bin/wasm-ld +bin/llvm-ar + +# Useful utility +bin/llvm-dis +bin/c-index-test +bin/llvm-config + +# Coverage support +bin/llvm-cov +bin/llvm-profdata + +# Used to link runtime files +bin/llvm-link + +include/** +lib/** +libexec/** +share/** \ No newline at end of file diff --git a/kotlin-native/dependencyPacker/macos_llvm_whitelist b/kotlin-native/dependencyPacker/macos_llvm_whitelist new file mode 100644 index 00000000000..c7ec28a676a --- /dev/null +++ b/kotlin-native/dependencyPacker/macos_llvm_whitelist @@ -0,0 +1,29 @@ +# Compilation process +bin/clang +bin/clang++ +bin/clang-8 + +# Linkage +bin/dsymutil +bin/lld +bin/ld.lld +bin/wasm-ld +bin/llvm-ar + +# Useful utility +bin/llvm-dis +bin/c-index-test +bin/llvm-config + +# Coverage support +bin/llvm-cov +bin/llvm-profdata + +# Used to link runtime files +bin/llvm-link + +include/** +lib/** +libexec/** +local/** +share/** \ No newline at end of file diff --git a/kotlin-native/dependencyPacker/mingw_llvm_blacklist b/kotlin-native/dependencyPacker/mingw_llvm_blacklist new file mode 100644 index 00000000000..ed0a4146b34 --- /dev/null +++ b/kotlin-native/dependencyPacker/mingw_llvm_blacklist @@ -0,0 +1,5 @@ +lib/gcc/x86_64-w64-mingw32/9.2.0/cc1plus.exe +lib/gcc/x86_64-w64-mingw32/9.2.0/plugin/cc1.exe.a +lib/gcc/x86_64-w64-mingw32/9.2.0/plugin/cc1plus.exe.a +lib/gcc/x86_64-w64-mingw32/9.2.0/lto1.exe +lib/gcc/x86_64-w64-mingw32/9.2.0/cc1.exe diff --git a/kotlin-native/dependencyPacker/mingw_llvm_whitelist b/kotlin-native/dependencyPacker/mingw_llvm_whitelist new file mode 100644 index 00000000000..2d74d888343 --- /dev/null +++ b/kotlin-native/dependencyPacker/mingw_llvm_whitelist @@ -0,0 +1,39 @@ +# Compilation process +bin/clang.exe +bin/clang++.exe +bin/clang-8.exe + +# Linkage +bin/lld.exe +bin/ld.lld.exe +bin/wasm-ld.exe +bin/llvm-ar.exe + +# Useful utility +bin/llvm-dis.exe +bin/llvm-config.exe + +# Coverage support +bin/llvm-cov.exe +bin/llvm-profdata.exe + +# Used to link runtime files +bin/llvm-link.exe + +# Used for samples +bin/windres.exe + +# Used by other binaries +bin/zlib1.dll +bin/libwinpthread-1.dll +bin/libgcc_s_seh-1.dll +bin/libstdc++-6.dll +bin/libz3.dll + +include/** +lib/** +etc/** +local/** +share/** +x86_64-w64-mingw32/** +libclang.dll \ No newline at end of file diff --git a/kotlin-native/endorsedLibraries/build.gradle b/kotlin-native/endorsedLibraries/build.gradle new file mode 100644 index 00000000000..05a6cc69cd0 --- /dev/null +++ b/kotlin-native/endorsedLibraries/build.gradle @@ -0,0 +1,109 @@ +import org.jetbrains.kotlin.UtilsKt +import org.jetbrains.kotlin.gradle.plugin.konan.tasks.KonanCacheTask +import org.jetbrains.kotlin.EndorsedLibraryInfo + +buildscript { + repositories { + maven { url 'https://cache-redirector.jetbrains.com/jcenter' } + jcenter() + } + + dependencies { + classpath "org.jetbrains.kotlin:kotlin-native-gradle-plugin:$gradlePluginVersion" + } +} + +ext { + endorsedLibraries = [ + new EndorsedLibraryInfo(project('kotlinx.cli'), "org.jetbrains.kotlinx.kotlinx-cli") + ].collectEntries { [it.project, it] } +} + +Collection endorsedLibrariesList = ext.endorsedLibraries.values() + +task clean { + doLast { + delete buildDir + } +} + +task jvmJar { + endorsedLibrariesList.each { library -> + dependsOn "$library.projectName:jvmJar" + } +} + +// Build all default libraries. +targetList.each { target -> + task("${target}EndorsedLibraries", type: Copy) { + endorsedLibrariesList.each { library -> + dependsOn "$library.projectName:${target}${library.taskName}" + } + + destinationDir project.buildDir + + endorsedLibrariesList.each { library -> + from(library.project.file("build/${target}${library.taskName}")) { + include('**') + into(library.name) + eachFile { + if (name == 'manifest') { + def existingManifest = file("$destinationDir/$path") + if (existingManifest.exists()) { + UtilsKt.mergeManifestsByTargets(project, file, existingManifest) + exclude() + } + } + } + } + } + } + + if (target in cacheableTargetNames) { + def cacheTask = task("${target}Cache") + + endorsedLibrariesList.each { library -> + def dist = rootProject.file("dist") + task("${target}${library.taskName}Cache", type: KonanCacheTask) { + it.target = target + originalKlib = file("${project.buildDir}/${library.name}") + cacheRoot = file("$dist/klib/cache") + compilerDistributionPath.set(distDir) + + dependsOn "${target}EndorsedLibraries" + dependsOn ":${target}CrossDistRuntime" + dependsOn ":${target}StdlibCache" + + cacheTask.dependsOn it + } + } + } +} + +endorsedLibrariesList.each { library -> + task("${library.taskName}CommonSources", type: Zip) { + destinationDirectory = file("${rootProject.projectDir}/dist/sources") + archiveFileName = "${library.name}-common-sources.zip" + + includeEmptyDirs = false + include('**/*.kt') + + from(library.project.file('src/main/kotlin')) + } + task("${library.taskName}NativeSources", type: Zip) { + destinationDirectory = file("${rootProject.projectDir}/dist/sources") + archiveFileName = "${library.name}-native-sources.zip" + + includeEmptyDirs = false + include('**/*.kt') + + from(library.project.file('src/main/kotlin-native')) + } +} + +task endorsedLibsSources { + endorsedLibrariesList.each { library -> + dependsOn "${library.taskName}CommonSources" + dependsOn "${library.taskName}NativeSources" + } +} diff --git a/kotlin-native/endorsedLibraries/kotlinx.cli/build.gradle b/kotlin-native/endorsedLibraries/kotlinx.cli/build.gradle new file mode 100644 index 00000000000..e53f30dab02 --- /dev/null +++ b/kotlin-native/endorsedLibraries/kotlinx.cli/build.gradle @@ -0,0 +1,113 @@ +import org.jetbrains.kotlin.konan.target.HostManager +import org.jetbrains.kotlin.konan.util.PlatformLibsInfo + +buildscript { + repositories { + maven { + url 'https://cache-redirector.jetbrains.com/jcenter' + } + jcenter() + maven { + url kotlinCompilerRepo + } + } + + dependencies { + classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlinVersion" + } +} + +apply plugin: 'kotlin-multiplatform' + +repositories { + maven { + url 'https://cache-redirector.jetbrains.com/jcenter' + } + jcenter() + maven { + url kotlinCompilerRepo + } + maven { + url buildKotlinCompilerRepo + } +} + +kotlin { + sourceSets { + commonMain { + dependencies { + implementation "org.jetbrains.kotlin:kotlin-stdlib-common:$kotlinVersion" + } + kotlin.srcDir 'src/main/kotlin' + + } + commonTest { + dependencies { + implementation "org.jetbrains.kotlin:kotlin-test-common:$kotlinVersion" + implementation "org.jetbrains.kotlin:kotlin-test-annotations-common:$kotlinVersion" + } + kotlin.srcDir 'src/tests' + } + jvm().compilations.main.defaultSourceSet { + dependencies { + implementation kotlin('stdlib-jdk8') + } + kotlin.srcDir 'src/main/kotlin-jvm' + } + // JVM-specific tests and their dependencies: + jvm().compilations.test.defaultSourceSet { + dependencies { + implementation kotlin('test-junit') + } + } + + jvm().compilations.all { + kotlinOptions { + freeCompilerArgs = ["-Xopt-in=kotlinx.cli.ExperimentalCli", "-Xopt-in=kotlin.RequiresOptIn"] + suppressWarnings = true + } + } + } +} + +def commonSrc = new File("$projectDir/src/main/kotlin") +def nativeSrc = new File("$projectDir/src/main/kotlin-native") + +targetList.each { target -> + def konanJvmArgs = [*HostManager.regularJvmArgs] + + def defaultArgs = ['-nopack', '-no-default-libs', '-no-endorsed-libs'] + if (target != "wasm32") defaultArgs += '-g' + def konanArgs = [*defaultArgs, + '-target', target, + "-Xruntime=${project(':runtime').file('build/bitcode/main/' + target + '/runtime.bc')}", + *project.globalBuildArgs] + + task("${target}KotlinxCli", type: JavaExec) { + def outputFile = project.file("build/${target}KotlinxCli") + // See :endorsedLibraries.ext for full endorsedLibraries list. + def moduleName = endorsedLibraries[project].name + + dependsOn ":distCompiler" + dependsOn ":${target}CrossDistRuntime" + + main = 'org.jetbrains.kotlin.cli.bc.K2NativeKt' + // This task depends on distCompiler, so the compiler jar is already in the dist directory. + classpath = fileTree("${rootProject.projectDir}/dist/konan/lib") { + include "*.jar" + } + jvmArgs = konanJvmArgs + args = [*konanArgs, + '-output', outputFile, + '-produce', 'library', '-module-name', moduleName, '-XXLanguage:+AllowContractsForCustomFunctions', + '-Xmulti-platform', '-Xopt-in=kotlinx.cli.ExperimentalCli', + '-Xopt-in=kotlin.ExperimentalMultiplatform', + '-Xallow-result-return-type', '-Werror', '-Xopt-in=kotlin.RequiresOptIn', + commonSrc.absolutePath, + "-Xcommon-sources=${commonSrc.absolutePath}", + nativeSrc] + inputs.dir(nativeSrc) + inputs.dir(commonSrc) + outputs.dir(outputFile) + } +} diff --git a/kotlin-native/endorsedLibraries/kotlinx.cli/gradle.properties b/kotlin-native/endorsedLibraries/kotlinx.cli/gradle.properties new file mode 100644 index 00000000000..23a0cc91ff7 --- /dev/null +++ b/kotlin-native/endorsedLibraries/kotlinx.cli/gradle.properties @@ -0,0 +1,2 @@ +org.jetbrains.kotlin.native.home=../../dist +org.jetbrains.kotlin.native.jvmArgs=-Xmx6G \ No newline at end of file diff --git a/kotlin-native/endorsedLibraries/kotlinx.cli/src/main/kotlin-js/kotlinx.cli/Utils.kt b/kotlin-native/endorsedLibraries/kotlinx.cli/src/main/kotlin-js/kotlinx.cli/Utils.kt new file mode 100644 index 00000000000..6b02f1a2f4f --- /dev/null +++ b/kotlin-native/endorsedLibraries/kotlinx.cli/src/main/kotlin-js/kotlinx.cli/Utils.kt @@ -0,0 +1,10 @@ +/* + * Copyright 2010-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +package kotlinx.cli + +internal actual fun exitProcess(status: Int): Nothing { + error("Not implemented for JS!") +} \ No newline at end of file diff --git a/kotlin-native/endorsedLibraries/kotlinx.cli/src/main/kotlin-jvm/kotlinx/cli/nonStdlibUtils.kt b/kotlin-native/endorsedLibraries/kotlinx.cli/src/main/kotlin-jvm/kotlinx/cli/nonStdlibUtils.kt new file mode 100644 index 00000000000..bcc87bd5d9f --- /dev/null +++ b/kotlin-native/endorsedLibraries/kotlinx.cli/src/main/kotlin-jvm/kotlinx/cli/nonStdlibUtils.kt @@ -0,0 +1,11 @@ +/* + * Copyright 2010-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +package kotlinx.cli + +internal actual fun exitProcess(status: Int): Nothing { + kotlin.system.exitProcess(0) +} + diff --git a/kotlin-native/endorsedLibraries/kotlinx.cli/src/main/kotlin-native/kotlinx/cli/Utils.kt b/kotlin-native/endorsedLibraries/kotlinx.cli/src/main/kotlin-native/kotlinx/cli/Utils.kt new file mode 100644 index 00000000000..52d171a0ff8 --- /dev/null +++ b/kotlin-native/endorsedLibraries/kotlinx.cli/src/main/kotlin-native/kotlinx/cli/Utils.kt @@ -0,0 +1,10 @@ +/* + * Copyright 2010-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +package kotlinx.cli + +internal actual fun exitProcess(status: Int): Nothing { + kotlin.system.exitProcess(0) +} \ No newline at end of file diff --git a/kotlin-native/endorsedLibraries/kotlinx.cli/src/main/kotlin/kotlinx/cli/ArgParser.kt b/kotlin-native/endorsedLibraries/kotlinx.cli/src/main/kotlin/kotlinx/cli/ArgParser.kt new file mode 100644 index 00000000000..241ececc491 --- /dev/null +++ b/kotlin-native/endorsedLibraries/kotlinx.cli/src/main/kotlin/kotlinx/cli/ArgParser.kt @@ -0,0 +1,664 @@ +/* + * Copyright 2010-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +package kotlinx.cli + +import kotlin.reflect.KProperty + +internal expect fun exitProcess(status: Int): Nothing + +/** + * Queue of arguments descriptors. + * Arguments can have several values, so one descriptor can be returned several times. + */ +internal class ArgumentsQueue(argumentsDescriptors: List>) { + /** + * Map of arguments descriptors and their current usage number. + */ + private val argumentsUsageNumber = linkedMapOf(*argumentsDescriptors.map { it to 0 }.toTypedArray()) + + /** + * Get next descriptor from queue. + */ + fun pop(): String? { + if (argumentsUsageNumber.isEmpty()) + return null + + val (currentDescriptor, usageNumber) = argumentsUsageNumber.iterator().next() + currentDescriptor.number?.let { + // Parse all arguments for current argument description. + if (usageNumber + 1 >= currentDescriptor.number) { + // All needed arguments were provided. + argumentsUsageNumber.remove(currentDescriptor) + } else { + argumentsUsageNumber[currentDescriptor] = usageNumber + 1 + } + } + return currentDescriptor.fullName + } +} + +/** + * A property delegate that provides access to the argument/option value. + */ +interface ArgumentValueDelegate { + /** + * The value of an option or argument parsed from command line. + * + * Accessing this value before [ArgParser.parse] method is called will result in an exception. + * + * @see CLIEntity.value + */ + var value: T + + /** Provides the value for the delegated property getter. Returns the [value] property. + * @throws IllegalStateException in case of accessing the value before [ArgParser.parse] method is called. + */ + operator fun getValue(thisRef: Any?, property: KProperty<*>): T = value + + /** Sets the [value] to the [ArgumentValueDelegate.value] property from the delegated property setter. + * This operation is possible only after command line arguments were parsed with [ArgParser.parse] + * @throws IllegalStateException in case of resetting value before command line arguments are parsed. + */ + operator fun setValue(thisRef: Any?, property: KProperty<*>, value: T) { + this.value = value + } +} + +/** + * Abstract base class for subcommands. + */ +@ExperimentalCli +abstract class Subcommand(val name: String, val actionDescription: String): ArgParser(name) { + /** + * Execute action if subcommand was provided. + */ + abstract fun execute() + + val helpMessage: String + get() = " $name - $actionDescription\n" +} + +/** + * Argument parsing result. + * Contains name of subcommand which was called. + * + * @property commandName name of command which was called. + */ +class ArgParserResult(val commandName: String) + +/** + * Arguments parser. + * + * @property programName the name of the current program. + * @property useDefaultHelpShortName specifies whether to register "-h" option for printing the usage information. + * @property prefixStyle the style of option prefixing. + * @property skipExtraArguments specifies whether the extra unmatched arguments in a command line string + * can be skipped without producing an error message. + */ +open class ArgParser( + val programName: String, + var useDefaultHelpShortName: Boolean = true, + var prefixStyle: OptionPrefixStyle = OptionPrefixStyle.LINUX, + var skipExtraArguments: Boolean = false +) { + + /** + * Map of options: key - full name of option, value - pair of descriptor and parsed values. + */ + private val options = mutableMapOf>() + /** + * Map of arguments: key - full name of argument, value - pair of descriptor and parsed values. + */ + private val arguments = mutableMapOf>() + + /** + * Map with declared options. + */ + private val declaredOptions = mutableListOf() + + /** + * Map with declared arguments. + */ + private val declaredArguments = mutableListOf() + + /** + * State of parser. Stores last parsing result or null. + */ + private var parsingState: ArgParserResult? = null + + /** + * Map of subcommands. + */ + @OptIn(ExperimentalCli::class) + protected val subcommands = mutableMapOf() + + /** + * Mapping for short options names for quick search. + */ + private val shortNames = mutableMapOf>() + + /** + * Used prefix form for full option form. + */ + private val optionFullFormPrefix = if (prefixStyle == OptionPrefixStyle.JVM) "-" else "--" + + /** + * Used prefix form for short option form. + */ + private val optionShortFromPrefix = "-" + + /** + * Name with all commands that should be executed. + */ + protected val fullCommandName = mutableListOf(programName) + + /** + * Flag to recognize if CLI entities can be treated as options. + */ + protected var treatAsOption = true + + /** + * The way an option/argument has got its value. + */ + enum class ValueOrigin { + /* The value was parsed from command line arguments. */ + SET_BY_USER, + /* The value was missing in command line, therefore the default value was used. */ + SET_DEFAULT_VALUE, + /* The value is not initialized by command line values or by default values. */ + UNSET, + /* The value was redefined after parsing manually (usually with the property setter). */ + REDEFINED, + /* The value is undefined, because parsing wasn't called. */ + UNDEFINED + } + + /** + * The style of option prefixing. + */ + enum class OptionPrefixStyle { + /* Linux style: the full name of an option is prefixed with two hyphens "--" and the short name — with one "-". */ + LINUX, + /* JVM style: both full and short names are prefixed with one hyphen "-". */ + JVM, + /* GNU style: the full name of an option is prefixed with two hyphens "--" and "=" between options and value + and the short name — with one "-". + Detailed information https://www.gnu.org/software/libc/manual/html_node/Argument-Syntax.html + */ + GNU + } + + @Deprecated("OPTION_PREFIX_STYLE is deprecated. Please, use OptionPrefixStyle.", + ReplaceWith("OptionPrefixStyle", "kotlinx.cli.OptionPrefixStyle")) + @Suppress("TOPLEVEL_TYPEALIASES_ONLY") + typealias OPTION_PREFIX_STYLE = OptionPrefixStyle + + /** + * Declares a named option and returns an object which can be used to access the option value + * after all arguments are parsed or to delegate a property for accessing the option value to. + * + * By default, the option supports only a single value, is optional, and has no default value, + * therefore its value's type is `T?`. + * + * You can alter the option properties by chaining extensions for the option type on the returned object: + * - [AbstractSingleOption.default] to provide a default value that is used when the option is not specified; + * - [SingleNullableOption.required] to make the option non-optional; + * - [AbstractSingleOption.delimiter] to allow specifying multiple values in one command line argument with a delimiter; + * - [AbstractSingleOption.multiple] to allow specifying the option several times. + * + * @param type The type describing how to parse an option value from a string, + * an instance of [ArgType], e.g. [ArgType.String] or [ArgType.Choice]. + * @param fullName the full name of the option, can be omitted if the option name is inferred + * from the name of a property delegated to this option. + * @param shortName the short name of the option, `null` if the option cannot be specified in a short form. + * @param description the description of the option used when rendering the usage information. + * @param deprecatedWarning the deprecation message for the option. + * Specifying anything except `null` makes this option deprecated. The message is rendered in a help message and + * issued as a warning when the option is encountered when parsing command line arguments. + */ + fun option( + type: ArgType, + fullName: String? = null, + shortName: String ? = null, + description: String? = null, + deprecatedWarning: String? = null + ): SingleNullableOption { + if (prefixStyle == OptionPrefixStyle.GNU && shortName != null) + require(shortName.length == 1) { + """ + GNU standart for options allow to use short form whuch consists of one character. + For more information, please, see https://www.gnu.org/software/libc/manual/html_node/Argument-Syntax.html + """.trimIndent() + } + val option = SingleNullableOption(OptionDescriptor(optionFullFormPrefix, optionShortFromPrefix, type, + fullName, shortName, description, deprecatedWarning = deprecatedWarning), CLIEntityWrapper()) + option.owner.entity = option + declaredOptions.add(option.owner) + return option + } + + /** + * Check usage of required property for arguments. + * Make sense only for several last arguments. + */ + private fun inspectRequiredAndDefaultUsage() { + var previousArgument: ParsingValue<*, *>? = null + arguments.forEach { (_, currentArgument) -> + previousArgument?.let { previous -> + // Previous argument has default value. + if (previous.descriptor.defaultValueSet) { + if (!currentArgument.descriptor.defaultValueSet && currentArgument.descriptor.required) { + error("Default value of argument ${previous.descriptor.fullName} will be unused, " + + "because next argument ${currentArgument.descriptor.fullName} is always required and has no default value.") + } + } + // Previous argument is optional. + if (!previous.descriptor.required) { + if (!currentArgument.descriptor.defaultValueSet && currentArgument.descriptor.required) { + error("Argument ${previous.descriptor.fullName} will be always required, " + + "because next argument ${currentArgument.descriptor.fullName} is always required.") + } + } + } + previousArgument = currentArgument + } + } + + /** + * Declares an argument and returns an object which can be used to access the argument value + * after all arguments are parsed or to delegate a property for accessing the argument value to. + * + * By default, the argument supports only a single value, is required, and has no default value, + * therefore its value's type is `T`. + * + * You can alter the argument properties by chaining extensions for the argument type on the returned object: + * - [AbstractSingleArgument.default] to provide a default value that is used when the argument is not specified; + * - [SingleArgument.optional] to allow omitting the argument; + * - [AbstractSingleArgument.multiple] to require the argument to have exactly the number of values specified; + * - [AbstractSingleArgument.vararg] to allow specifying an unlimited number of values for the _last_ argument. + * + * @param type The type describing how to parse an option value from a string, + * an instance of [ArgType], e.g. [ArgType.String] or [ArgType.Choice]. + * @param fullName the full name of the argument, can be omitted if the argument name is inferred + * from the name of a property delegated to this argument. + * @param description the description of the argument used when rendering the usage information. + * @param deprecatedWarning the deprecation message for the argument. + * Specifying anything except `null` makes this argument deprecated. The message is rendered in a help message and + * issued as a warning when the argument is encountered when parsing command line arguments. + */ + fun argument( + type: ArgType, + fullName: String? = null, + description: String? = null, + deprecatedWarning: String? = null + ) : SingleArgument { + val argument = SingleArgument(ArgDescriptor(type, fullName, 1, + description, deprecatedWarning = deprecatedWarning), CLIEntityWrapper()) + argument.owner.entity = argument + declaredArguments.add(argument.owner) + return argument + } + + /** + * Registers one or more subcommands. + * + * @param subcommandsList subcommands to add. + */ + @ExperimentalCli + fun subcommands(vararg subcommandsList: Subcommand) { + subcommandsList.forEach { + if (it.name in subcommands) { + error("Subcommand with name ${it.name} was already defined.") + } + + // Set same settings as main parser. + it.prefixStyle = prefixStyle + it.useDefaultHelpShortName = useDefaultHelpShortName + fullCommandName.forEachIndexed { index, namePart -> + it.fullCommandName.add(index, namePart) + } + subcommands[it.name] = it + } + } + + /** + * Outputs an error message adding the usage information after it. + * + * @param message error message. + */ + fun printError(message: String): Nothing { + error("$message\n${makeUsage()}") + } + + /** + * Save value as argument value. + * + * @param arg string with argument value. + * @param argumentsQueue queue with active argument descriptors. + */ + private fun saveAsArg(arg: String, argumentsQueue: ArgumentsQueue): Boolean { + // Find next uninitialized arguments. + val name = argumentsQueue.pop() + name?.let { + val argumentValue = arguments[name]!! + argumentValue.descriptor.deprecatedWarning?.let { printWarning(it) } + argumentValue.addValue(arg) + return true + } + return false + } + + /** + * Treat value as argument value. + * + * @param arg string with argument value. + * @param argumentsQueue queue with active argument descriptors. + */ + private fun treatAsArgument(arg: String, argumentsQueue: ArgumentsQueue) { + if (!saveAsArg(arg, argumentsQueue)) { + printError("Too many arguments! Couldn't process argument $arg!") + } + } + + /** + * Save value as option value. + */ + private fun saveAsOption(parsingValue: ParsingValue, value: String) { + parsingValue.addValue(value) + } + + /** + * Try to recognize and save command line element as full form of option. + * + * @param candidate string with candidate in options. + * @param argIterator iterator over command line arguments. + */ + private fun recognizeAndSaveOptionFullForm(candidate: String, argIterator: Iterator): Boolean { + if (prefixStyle == OptionPrefixStyle.GNU && candidate == optionFullFormPrefix) { + // All other arguments after `--` are treated as non-option arguments. + treatAsOption = false + return false + } + if (!candidate.startsWith(optionFullFormPrefix)) + return false + + val optionString = candidate.substring(optionFullFormPrefix.length) + val argValue = if (prefixStyle == OptionPrefixStyle.GNU) null else options[optionString] + if (argValue != null) { + saveStandardOptionForm(argValue, argIterator) + return true + } else { + // Check GNU style of options. + if (prefixStyle == OptionPrefixStyle.GNU) { + // Option without a parameter. + if (options[optionString]?.descriptor?.type?.hasParameter == false) { + saveOptionWithoutParameter(options[optionString]!!) + return true + } + // Option with parameters. + val optionParts = optionString.split('=', limit = 2) + if (optionParts.size != 2) + return false + if (options[optionParts[0]] != null) { + saveAsOption(options[optionParts[0]]!!, optionParts[1]) + return true + } + } + } + return false + } + + /** + * Save option without parameter. + * + * @param argValue argument value with all information about option. + */ + private fun saveOptionWithoutParameter(argValue: ParsingValue<*, *>) { + // Boolean flags. + if (argValue.descriptor.fullName == "help") { + println(makeUsage()) + exitProcess(0) + } + saveAsOption(argValue, "true") + } + + /** + * Save option described with standard separated form `--name value`. + * + * @param argValue argument value with all information about option. + * @param argIterator iterator over command line arguments. + */ + private fun saveStandardOptionForm(argValue: ParsingValue<*, *>, argIterator: Iterator) { + if (argValue.descriptor.type.hasParameter) { + if (argIterator.hasNext()) { + saveAsOption(argValue, argIterator.next()) + } else { + // An error, option with value without value. + printError("No value for ${argValue.descriptor.textDescription}") + } + } else { + saveOptionWithoutParameter(argValue) + } + } + + /** + * Try to recognize and save command line element as short form of option. + * + * @param candidate string with candidate in options. + * @param argIterator iterator over command line arguments. + */ + private fun recognizeAndSaveOptionShortForm(candidate: String, argIterator: Iterator): Boolean { + if (!candidate.startsWith(optionShortFromPrefix) || + optionFullFormPrefix != optionShortFromPrefix && candidate.startsWith(optionFullFormPrefix)) return false + // Try to find exact match. + val option = candidate.substring(optionShortFromPrefix.length) + val argValue = shortNames[option] + if (argValue != null) { + saveStandardOptionForm(argValue, argIterator) + } else { + if (prefixStyle != OptionPrefixStyle.GNU || option.isEmpty()) + return false + + // Try to find collapsed form. + val firstOption = shortNames["${option[0]}"] ?: return false + // Form with value after short form without separator. + if (firstOption.descriptor.type.hasParameter) { + saveAsOption(firstOption, option.substring(1)) + } else { + // Form with several short forms as one string. + val otherBooleanOptions = option.substring(1) + saveOptionWithoutParameter(firstOption) + for (opt in otherBooleanOptions) { + shortNames["$opt"]?.let { + if (it.descriptor.type.hasParameter) { + printError( + "Option $optionShortFromPrefix$opt can't be used in option combination $candidate, " + + "because parameter value of type ${it.descriptor.type.description} should be " + + "provided for current option." + ) + } + }?: printError("Unknown option $optionShortFromPrefix$opt in option combination $candidate.") + + saveOptionWithoutParameter(shortNames["$opt"]!!) + } + } + } + return true + } + + /** + * Parses the provided array of command line arguments. + * After a successful parsing, the options and arguments declared in this parser get their values and can be accessed + * with the properties delegated to them. + * + * @param args the array with command line arguments. + * + * @return an [ArgParserResult] if all arguments were parsed successfully. + * Otherwise, prints the usage information and terminates the program execution. + * @throws IllegalStateException in case of attempt of calling parsing several times. + */ + fun parse(args: Array): ArgParserResult = parse(args.asList()) + + protected fun parse(args: List): ArgParserResult { + check(parsingState == null) { "Parsing of command line options can be called only once." } + + // Add help option. + val helpDescriptor = if (useDefaultHelpShortName) OptionDescriptor( + optionFullFormPrefix, + optionShortFromPrefix, ArgType.Boolean, + "help", "h", "Usage info" + ) + else OptionDescriptor( + optionFullFormPrefix, optionShortFromPrefix, + ArgType.Boolean, "help", description = "Usage info" + ) + val helpOption = SingleNullableOption(helpDescriptor, CLIEntityWrapper()) + helpOption.owner.entity = helpOption + declaredOptions.add(helpOption.owner) + + // Add default list with arguments if there can be extra free arguments. + if (skipExtraArguments) { + argument(ArgType.String, "").vararg() + } + + // Clean options and arguments maps. + options.clear() + arguments.clear() + + // Map declared options and arguments to maps. + declaredOptions.forEachIndexed { index, option -> + val value = option.entity?.delegate as ParsingValue<*, *> + value.descriptor.fullName?.let { + // Add option. + if (options.containsKey(it)) { + error("Option with full name $it was already added.") + } + with(value.descriptor as OptionDescriptor) { + if (shortName != null && shortNames.containsKey(shortName)) { + error("Option with short name ${shortName} was already added.") + } + shortName?.let { + shortNames[it] = value + } + } + options[it] = value + + } ?: error("Option was added, but unnamed. Added option under №${index + 1}") + } + + declaredArguments.forEachIndexed { index, argument -> + val value = argument.entity?.delegate as ParsingValue<*, *> + value.descriptor.fullName?.let { + // Add option. + if (arguments.containsKey(it)) { + error("Argument with full name $it was already added.") + } + arguments[it] = value + } ?: error("Argument was added, but unnamed. Added argument under №${index + 1}") + } + // Make inspections for arguments. + inspectRequiredAndDefaultUsage() + + listOf(arguments, options).forEach { + it.forEach { (_, value) -> + value.valueOrigin = ValueOrigin.UNSET + } + } + + val argumentsQueue = ArgumentsQueue(arguments.map { it.value.descriptor as ArgDescriptor<*, *> }) + + val argIterator = args.listIterator() + try { + while (argIterator.hasNext()) { + val arg = argIterator.next() + // Check for subcommands. + @OptIn(ExperimentalCli::class) + subcommands.forEach { (name, subcommand) -> + if (arg == name) { + // Use parser for this subcommand. + subcommand.parse(args.slice(argIterator.nextIndex() until args.size)) + subcommand.execute() + parsingState = ArgParserResult(name) + + return parsingState!! + } + } + // Parse arguments from command line. + if (treatAsOption && arg.startsWith('-')) { + // Candidate in being option. + // Option is found. + if (!(recognizeAndSaveOptionShortForm(arg, argIterator) || + recognizeAndSaveOptionFullForm(arg, argIterator))) { + // State is changed so next options are arguments. + if (!treatAsOption) { + // Argument is found. + treatAsArgument(argIterator.next(), argumentsQueue) + } else { + // Try save as argument. + if (!saveAsArg(arg, argumentsQueue)) { + printError("Unknown option $arg") + } + } + } + } else { + // Argument is found. + treatAsArgument(arg, argumentsQueue) + } + } + // Postprocess results of parsing. + options.values.union(arguments.values).forEach { value -> + // Not inited, append default value if needed. + if (value.isEmpty()) { + value.addDefaultValue() + } + if (value.valueOrigin != ValueOrigin.SET_BY_USER && value.descriptor.required) { + printError("Value for ${value.descriptor.textDescription} should be always provided in command line.") + } + } + } catch (exception: ParsingException) { + printError(exception.message!!) + } + parsingState = ArgParserResult(programName) + return parsingState!! + } + + /** + * Creates a message with the usage information. + */ + internal fun makeUsage(): String { + val result = StringBuilder() + result.append("Usage: ${fullCommandName.joinToString(" ")} options_list\n") + if (subcommands.isNotEmpty()) { + result.append("Subcommands: \n") + subcommands.forEach { (_, subcommand) -> + result.append(subcommand.helpMessage) + } + result.append("\n") + } + if (arguments.isNotEmpty()) { + result.append("Arguments: \n") + arguments.forEach { + result.append(it.value.descriptor.helpMessage) + } + } + if (options.isNotEmpty()) { + result.append("Options: \n") + options.forEach { + result.append(it.value.descriptor.helpMessage) + } + } + return result.toString() + } +} + +/** + * Output warning. + * + * @param message warning message. + */ +internal fun printWarning(message: String) { + println("WARNING $message") +} \ No newline at end of file diff --git a/kotlin-native/endorsedLibraries/kotlinx.cli/src/main/kotlin/kotlinx/cli/ArgType.kt b/kotlin-native/endorsedLibraries/kotlinx.cli/src/main/kotlin/kotlinx/cli/ArgType.kt new file mode 100644 index 00000000000..d5da8e21da6 --- /dev/null +++ b/kotlin-native/endorsedLibraries/kotlinx.cli/src/main/kotlin/kotlinx/cli/ArgType.kt @@ -0,0 +1,86 @@ +/* + * Copyright 2010-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +package kotlinx.cli + +/** + * Possible types of arguments. + * + * Inheritors describe type of argument value. New types can be added by user. + * In case of options type can have parameter or not. + */ +abstract class ArgType(val hasParameter: kotlin.Boolean) { + /** + * Text description of type for helpMessage. + */ + abstract val description: kotlin.String + + /** + * Function to convert string argument value to its type. + * In case of error during conversion also provides help message. + * + * @param value value + */ + abstract fun convert(value: kotlin.String, name: kotlin.String): T + + /** + * Argument type for flags that can be only set/unset. + */ + object Boolean : ArgType(false) { + override val description: kotlin.String + get() = "" + + override fun convert(value: kotlin.String, name: kotlin.String): kotlin.Boolean = + value != "false" + } + + /** + * Argument type for string values. + */ + object String : ArgType(true) { + override val description: kotlin.String + get() = "{ String }" + + override fun convert(value: kotlin.String, name: kotlin.String): kotlin.String = value + } + + /** + * Argument type for integer values. + */ + object Int : ArgType(true) { + override val description: kotlin.String + get() = "{ Int }" + + override fun convert(value: kotlin.String, name: kotlin.String): kotlin.Int = + value.toIntOrNull() + ?: throw ParsingException("Option $name is expected to be integer number. $value is provided.") + } + + /** + * Argument type for double values. + */ + object Double : ArgType(true) { + override val description: kotlin.String + get() = "{ Double }" + + override fun convert(value: kotlin.String, name: kotlin.String): kotlin.Double = + value.toDoubleOrNull() + ?: throw ParsingException("Option $name is expected to be double number. $value is provided.") + } + + /** + * Type for arguments that have limited set of possible values. + */ + class Choice(val values: List) : ArgType(true) { + override val description: kotlin.String + get() = "{ Value should be one of $values }" + + override fun convert(value: kotlin.String, name: kotlin.String): kotlin.String = + if (value in values) value + else throw ParsingException("Option $name is expected to be one of $values. $value is provided.") + } +} + +internal class ParsingException(message: String) : Exception(message) \ No newline at end of file diff --git a/kotlin-native/endorsedLibraries/kotlinx.cli/src/main/kotlin/kotlinx/cli/ArgumentValues.kt b/kotlin-native/endorsedLibraries/kotlinx.cli/src/main/kotlin/kotlinx/cli/ArgumentValues.kt new file mode 100644 index 00000000000..81a1ac4f0d1 --- /dev/null +++ b/kotlin-native/endorsedLibraries/kotlinx.cli/src/main/kotlin/kotlinx/cli/ArgumentValues.kt @@ -0,0 +1,168 @@ +/* + * Copyright 2010-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ +package kotlinx.cli + +/** + * Parsing value of option/argument. + */ +internal abstract class ParsingValue(val descriptor: Descriptor) { + /** + * Values of arguments. + */ + protected lateinit var parsedValue: TResult + + /** + * Value origin. + */ + var valueOrigin = ArgParser.ValueOrigin.UNDEFINED + internal set + + /** + * Check if values of argument are empty. + */ + abstract fun isEmpty(): Boolean + + /** + * Check if value of argument was initialized. + */ + protected fun valueIsInitialized() = ::parsedValue.isInitialized + + /** + * Sace value from command line. + * + * @param stringValue value from command line. + */ + protected abstract fun saveValue(stringValue: String) + + /** + * Set value of delegated property. + */ + fun setDelegatedValue(providedValue: TResult) { + parsedValue = providedValue + valueOrigin = ArgParser.ValueOrigin.REDEFINED + } + + /** + * Add parsed value from command line. + * + * @param stringValue value from command line. + */ + internal fun addValue(stringValue: String) { + // Check of possibility to set several values to one option/argument. + if (descriptor is OptionDescriptor<*, *> && !descriptor.multiple && + !isEmpty() && descriptor.delimiter == null) { + throw ParsingException("Try to provide more than one value for ${descriptor.fullName}.") + } + // Show deprecated warning only first time of using option/argument. + descriptor.deprecatedWarning?.let { + if (isEmpty()) + println ("Warning: $it") + } + // Split value if needed. + if (descriptor is OptionDescriptor<*, *> && descriptor.delimiter != null) { + stringValue.split(descriptor.delimiter).forEach { + saveValue(it) + } + } else { + saveValue(stringValue) + } + } + + /** + * Set default value to option. + */ + fun addDefaultValue() { + if (descriptor.defaultValueSet) { + parsedValue = descriptor.defaultValue!! + valueOrigin = ArgParser.ValueOrigin.SET_DEFAULT_VALUE + } + } + + /** + * Provide name for CLI entity. + * + * @param name name for CLI entity. + */ + fun provideName(name: String) { + descriptor.fullName ?: run { descriptor.fullName = name } + } +} + +/** + * Single argument value. + * + * @property descriptor descriptor of option/argument. + */ +internal abstract class AbstractArgumentSingleValue(descriptor: Descriptor): + ParsingValue(descriptor) { + + override fun saveValue(stringValue: String) { + if (!valueIsInitialized()) { + parsedValue = descriptor.type.convert(stringValue, descriptor.fullName!!) + valueOrigin = ArgParser.ValueOrigin.SET_BY_USER + } else { + throw ParsingException("Try to provide more than one value $parsedValue and $stringValue for ${descriptor.fullName}.") + } + } + + override fun isEmpty(): Boolean = !valueIsInitialized() +} + +/** + * Single argument value. + * + * @property descriptor descriptor of option/argument. + */ +internal class ArgumentSingleValue(descriptor: Descriptor): AbstractArgumentSingleValue(descriptor), + ArgumentValueDelegate { + override var value: T + get() = if (!isEmpty()) parsedValue else error("Value for argument ${descriptor.fullName} isn't set. " + + "ArgParser.parse(...) method should be called before.") + set(value) = setDelegatedValue(value) +} + +/** + * Single nullable argument value. + * + * @property descriptor descriptor of option/argument. + */ +internal class ArgumentSingleNullableValue(descriptor: Descriptor): + AbstractArgumentSingleValue(descriptor), ArgumentValueDelegate { + private var setToNull = false + override var value: T? + get() = if (!isEmpty() && !setToNull) parsedValue else null + set(providedValue) = providedValue?.let { + setDelegatedValue(it) + setToNull = false + } ?: run { + setToNull = true + valueOrigin = ArgParser.ValueOrigin.REDEFINED + } +} + +/** + * Multiple argument values. + * + * @property descriptor descriptor of option/argument. + */ +internal class ArgumentMultipleValues(descriptor: Descriptor>): + ParsingValue>(descriptor), ArgumentValueDelegate> { + + private val addedValue = mutableListOf() + init { + parsedValue = addedValue + } + + override var value: List + get() = parsedValue + set(value) = setDelegatedValue(value) + + override fun saveValue(stringValue: String) { + addedValue.add(descriptor.type.convert(stringValue, descriptor.fullName!!)) + valueOrigin = ArgParser.ValueOrigin.SET_BY_USER + } + + override fun isEmpty() = parsedValue.isEmpty() +} \ No newline at end of file diff --git a/kotlin-native/endorsedLibraries/kotlinx.cli/src/main/kotlin/kotlinx/cli/Arguments.kt b/kotlin-native/endorsedLibraries/kotlinx.cli/src/main/kotlin/kotlinx/cli/Arguments.kt new file mode 100644 index 00000000000..e25d860e5dc --- /dev/null +++ b/kotlin-native/endorsedLibraries/kotlinx.cli/src/main/kotlin/kotlinx/cli/Arguments.kt @@ -0,0 +1,253 @@ +/* + * Copyright 2010-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ +package kotlinx.cli + +import kotlin.reflect.KProperty + +internal data class CLIEntityWrapper(var entity: CLIEntity<*>? = null) + +/** + * Base interface for all possible types of entities with default and required values. + * Provides limitations for API that is accessible for different options/arguments types. + * Allows to save the reason why option/argument can(or can't) be omitted in command line. + * + * @see [SingleOption], [MultipleOption], [SingleArgument], [MultipleArgument]. + */ +interface DefaultRequiredType { + /** + * Type of an entity with default value. + */ + class Default : DefaultRequiredType + + /** + * Type of an entity which value should always be provided in command line. + */ + class Required : DefaultRequiredType + + /** + * Type of entity which is optional and has no default value. + */ + class None : DefaultRequiredType +} + +/** + * The base class for a command line argument or an option. + */ +abstract class CLIEntity internal constructor(val delegate: ArgumentValueDelegate, + internal val owner: CLIEntityWrapper) { + /** + * The value of the option or argument parsed from command line. + * + * Accessing this property before it gets its value will result in an exception. + * You can use [valueOrigin] property to find out whether the property has been already set. + * + * @see ArgumentValueDelegate.value + */ + var value: TResult + get() = delegate.value + set(value) { + check((delegate as ParsingValue<*, *>).valueOrigin != ArgParser.ValueOrigin.UNDEFINED) { + "Resetting value of option/argument is only possible after parsing command line arguments." + + " ArgParser.parse(...) method should be called before" + } + delegate.value = value + } + + /** + * The origin of the option/argument value. + */ + val valueOrigin: ArgParser.ValueOrigin + get() = (delegate as ParsingValue<*, *>).valueOrigin + + private var delegateProvided = false + + /** + * Returns the delegate object for property delegation and initializes it with the name of the delegated property. + * + * This operator makes it possible to delegate a property to this instance. It returns [delegate] object + * to be used as an actual delegate and uses the name of the delegated property to initialize the full name + * of the option/argument if it wasn't done during construction of that option/argument. + * + * @throws IllegalStateException in case of trying to use same delegate several times. + */ + operator fun provideDelegate(thisRef: Any?, prop: KProperty<*>): ArgumentValueDelegate { + check(!delegateProvided) { + "There is already used delegate for ${(delegate as ParsingValue<*, *>).descriptor.fullName}." + } + (delegate as ParsingValue<*, *>).provideName(prop.name) + delegateProvided = true + return delegate + } +} + +/** + * The base class for command line arguments. + * + * You can use [ArgParser.argument] function to declare an argument. + */ +abstract class Argument internal constructor(delegate: ArgumentValueDelegate, + owner: CLIEntityWrapper): CLIEntity(delegate, owner) + +/** + * The base class of an argument with a single value. + * + * A non-optional argument or an optional argument with a default value is represented with the [SingleArgument] inheritor. + * An optional argument having nullable value is represented with the [SingleNullableArgument] inheritor. + */ +// TODO: investigate if we can collapse two inheritors into the single base class and specialize extensions by TResult upper bound +abstract class AbstractSingleArgument internal constructor( + delegate: ArgumentValueDelegate, + owner: CLIEntityWrapper): + Argument(delegate, owner) { + /** + * Check descriptor for this kind of argument. + */ + internal fun checkDescriptor(descriptor: ArgDescriptor<*, *>) { + if (descriptor.number == null || descriptor.number > 1) { + failAssertion("Argument with single value can't be initialized with descriptor for multiple values.") + } + } +} + +/** + * A non-optional argument or an optional argument with a default value. + * + * The [value] of such argument is non-null. + */ +class SingleArgument internal constructor(descriptor: ArgDescriptor, + owner: CLIEntityWrapper): + AbstractSingleArgument(ArgumentSingleValue(descriptor), owner) { + init { + checkDescriptor(descriptor) + } +} + +/** + * An optional argument with nullable [value]. + */ +class SingleNullableArgument internal constructor(descriptor: ArgDescriptor, owner: CLIEntityWrapper): + AbstractSingleArgument(ArgumentSingleNullableValue(descriptor), owner) { + init { + checkDescriptor(descriptor) + } +} + +/** + * An argument that allows several values to be provided in command line string. + * + * The [value] property of such argument has type `List`. + */ +class MultipleArgument internal constructor( + descriptor: ArgDescriptor>, owner: CLIEntityWrapper): + Argument>(ArgumentMultipleValues(descriptor), owner) { + init { + if (descriptor.number != null && descriptor.number < 2) { + failAssertion("Argument with multiple values can't be initialized with descriptor for single one.") + } + } +} + +/** + * Allows the argument to have several values specified in command line string. + * + * @param number the exact number of values expected for this argument, but at least 2. + * + * @throws IllegalArgumentException if number of values expected for this argument less than 2. + */ +fun + AbstractSingleArgument.multiple(number: Int): MultipleArgument { + require(number >= 2) { "multiple() modifier with value less than 2 is unavailable. It's already set to 1." } + val newArgument = with(delegate.cast>().descriptor as ArgDescriptor) { + MultipleArgument(ArgDescriptor(type, fullName, number, description, listOfNotNull(defaultValue), + required, deprecatedWarning), owner) + } + owner.entity = newArgument + return newArgument +} + +/** + * Allows the last argument to take all the trailing values in command line string. + */ +fun AbstractSingleArgument.vararg(): + MultipleArgument { + val newArgument = with(delegate.cast>().descriptor as ArgDescriptor) { + MultipleArgument(ArgDescriptor(type, fullName, null, description, listOfNotNull(defaultValue), + required, deprecatedWarning), owner) + } + owner.entity = newArgument + return newArgument +} + +/** + * Specifies the default value for the argument, that will be used when no value is provided for the argument + * in command line string. + * + * Argument becomes optional, because value for it is set even if it isn't provided in command line. + * + * @param value the default value. + */ +fun SingleNullableArgument.default(value: T): SingleArgument { + val newArgument = with(delegate.cast>().descriptor as ArgDescriptor) { + SingleArgument(ArgDescriptor(type, fullName, number, description, value, + false, deprecatedWarning), owner) + } + owner.entity = newArgument + return newArgument +} + +/** + * Specifies the default value for the argument with multiple values, that will be used when no values are provided + * for the argument in command line string. + * + * Argument becomes optional, because value for it is set even if it isn't provided in command line. + * + * @param value the default value, must be a non-empty collection. + */ +fun MultipleArgument.default(value: Collection): + MultipleArgument { + require (value.isNotEmpty()) { "Default value for argument can't be empty collection." } + val newArgument = with(delegate.cast>>().descriptor as ArgDescriptor) { + MultipleArgument(ArgDescriptor(type, fullName, number, description, value.toList(), + required, deprecatedWarning), owner) + } + owner.entity = newArgument + return newArgument +} + +/** + * Allows the argument to have no value specified in command line string. + * + * The value of the argument is `null` in case if no value was specified in command line string. + * + * Note that only trailing arguments can be optional, i.e. no required arguments can follow optional ones. + */ +fun SingleArgument.optional(): SingleNullableArgument { + val newArgument = with(delegate.cast>().descriptor as ArgDescriptor) { + SingleNullableArgument(ArgDescriptor(type, fullName, number, description, defaultValue, + false, deprecatedWarning), owner) + } + owner.entity = newArgument + return newArgument +} + +/** + * Allows the argument with multiple values to have no values specified in command line string. + * + * The value of the argument is an empty list in case if no value was specified in command line string. + * + * Note that only trailing arguments can be optional: no required arguments can follow the optional ones. + */ +fun MultipleArgument.optional(): MultipleArgument { + val newArgument = with(delegate.cast>>().descriptor as ArgDescriptor) { + MultipleArgument(ArgDescriptor(type, fullName, number, description, + defaultValue?.toList() ?: listOf(), false, deprecatedWarning), owner) + } + owner.entity = newArgument + return newArgument +} + +internal fun failAssertion(message: String): Nothing = throw AssertionError(message) + +internal inline fun Any?.cast(): T = this as T \ No newline at end of file diff --git a/kotlin-native/endorsedLibraries/kotlinx.cli/src/main/kotlin/kotlinx/cli/Descriptors.kt b/kotlin-native/endorsedLibraries/kotlinx.cli/src/main/kotlin/kotlinx/cli/Descriptors.kt new file mode 100644 index 00000000000..098fc4adfa2 --- /dev/null +++ b/kotlin-native/endorsedLibraries/kotlinx.cli/src/main/kotlin/kotlinx/cli/Descriptors.kt @@ -0,0 +1,152 @@ +/* + * Copyright 2010-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ +package kotlinx.cli + +/** + * Common descriptor both for options and positional arguments. + * + * @property type option/argument type, one of [ArgType]. + * @property fullName option/argument full name. + * @property description text description of option/argument. + * @property defaultValue default value for option/argument. + * @property required if option/argument is required or not. If it's required and not provided in command line, error will be generated. + * @property deprecatedWarning text message with information in case if option is deprecated. + */ +internal abstract class Descriptor(val type: ArgType, + var fullName: String? = null, + val description: String? = null, + val defaultValue: TResult? = null, + val required: Boolean = false, + val deprecatedWarning: String? = null) { + /** + * Text description for help message. + */ + abstract val textDescription: String + /** + * Help message for descriptor. + */ + abstract val helpMessage: String + + /** + * Provide text description of value. + * + * @param value value got getting text description for. + */ + fun valueDescription(value: TResult?) = value?.let { + if (it is List<*> && it.isNotEmpty()) + " [${it.joinToString()}]" + else if (it !is List<*>) + " [$it]" + else null + } + + /** + * Flag to check if descriptor has set default value for option/argument. + */ + val defaultValueSet by lazy { + defaultValue != null && (defaultValue is List<*> && defaultValue.isNotEmpty() || defaultValue !is List<*>) + } +} + +/** + * Option descriptor. + * + * Command line entity started with some prefix (-/--) and can have value as next entity in command line string. + * + * @property optionFullFormPrefix prefix used before full form of option. + * @property optionShortFromPrefix prefix used before short form of option. + * @property type option type, one of [ArgType]. + * @property fullName option full name. + * @property shortName option short name. + * @property description text description of option. + * @property defaultValue default value for option. + * @property required if option is required or not. If it's required and not provided in command line, error will be generated. + * @property multiple if option can be repeated several times in command line with different values. All values are stored. + * @property delimiter delimiter that separate option provided as one string to several values. + * @property deprecatedWarning text message with information in case if option is deprecated. + */ +internal class OptionDescriptor( + val optionFullFormPrefix: String, + val optionShortFromPrefix: String, + type: ArgType, + fullName: String? = null, + val shortName: String ? = null, + description: String? = null, + defaultValue: TResult? = null, + required: Boolean = false, + val multiple: Boolean = false, + val delimiter: String? = null, + deprecatedWarning: String? = null) : Descriptor(type, fullName, description, defaultValue, + required, deprecatedWarning) { + + override val textDescription: String + get() = "option $optionFullFormPrefix$fullName" + + override val helpMessage: String + get() { + val result = StringBuilder() + result.append(" $optionFullFormPrefix$fullName") + shortName?.let { result.append(", $optionShortFromPrefix$it") } + valueDescription(defaultValue)?.let { + result.append(it) + } + description?.let {result.append(" -> $it")} + if (required) result.append(" (always required)") + result.append(" ${type.description}") + deprecatedWarning?.let { result.append(" Warning: $it") } + result.append("\n") + return result.toString() + } +} + +/** + * Argument descriptor. + * + * Command line entity which role is connected only with its position. + * + * @property type argument type, one of [ArgType]. + * @property fullName argument full name. + * @property number expected number of values. Null means any possible number of values. + * @property description text description of argument. + * @property defaultValue default value for argument. + * @property required if argument is required or not. If it's required and not provided in command line and have no default value, error will be generated. + * @property deprecatedWarning text message with information in case if argument is deprecated. + */ +internal class ArgDescriptor( + type: ArgType, + fullName: String?, + val number: Int? = null, + description: String? = null, + defaultValue: TResult? = null, + required: Boolean = true, + deprecatedWarning: String? = null) : Descriptor(type, fullName, description, defaultValue, + required, deprecatedWarning) { + + init { + // Check arguments number correctness. + number?.let { + if (it < 1) + error("Number of arguments for argument description $fullName should be greater than zero.") + } + } + + override val textDescription: String + get() = "argument $fullName" + + override val helpMessage: String + get() { + val result = StringBuilder() + result.append(" ${fullName}") + valueDescription(defaultValue)?.let { + result.append(it) + } + description?.let { result.append(" -> $it") } + if (!required) result.append(" (optional)") + result.append(" ${type.description}") + deprecatedWarning?.let { result.append(" Warning: $it") } + result.append("\n") + return result.toString() + } +} \ No newline at end of file diff --git a/kotlin-native/endorsedLibraries/kotlinx.cli/src/main/kotlin/kotlinx/cli/ExperimentalCli.kt b/kotlin-native/endorsedLibraries/kotlinx.cli/src/main/kotlin/kotlinx/cli/ExperimentalCli.kt new file mode 100644 index 00000000000..d35f6be01bf --- /dev/null +++ b/kotlin-native/endorsedLibraries/kotlinx.cli/src/main/kotlin/kotlinx/cli/ExperimentalCli.kt @@ -0,0 +1,36 @@ +/* + * Copyright 2010-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +package kotlinx.cli + +import kotlin.annotation.AnnotationTarget.* + +/** + * This annotation marks the experimental API for working with command line arguments. + * + * > Beware using the annotated API especially if you're developing a library, since your library might become binary incompatible + * with the future versions of the CLI library. + * + * Any usage of a declaration annotated with `@ExperimentalCli` must be accepted either by + * annotating that usage with the [UseExperimental] annotation, e.g. `@UseExperimental(ExperimentalCli::class)`, + * or by using the compiler argument `-Xuse-experimental=kotlinx.cli.ExperimentalCli`. + */ +@RequiresOptIn("This API is experimental. It may be changed in the future without notice.", level = RequiresOptIn.Level.WARNING) +@Retention(AnnotationRetention.BINARY) +@Target( + CLASS, + ANNOTATION_CLASS, + PROPERTY, + FIELD, + LOCAL_VARIABLE, + VALUE_PARAMETER, + CONSTRUCTOR, + FUNCTION, + PROPERTY_GETTER, + PROPERTY_SETTER, + TYPEALIAS +) + +public annotation class ExperimentalCli \ No newline at end of file diff --git a/kotlin-native/endorsedLibraries/kotlinx.cli/src/main/kotlin/kotlinx/cli/Options.kt b/kotlin-native/endorsedLibraries/kotlinx.cli/src/main/kotlin/kotlinx/cli/Options.kt new file mode 100644 index 00000000000..69999451842 --- /dev/null +++ b/kotlin-native/endorsedLibraries/kotlinx.cli/src/main/kotlin/kotlinx/cli/Options.kt @@ -0,0 +1,266 @@ +/* + * Copyright 2010-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ +package kotlinx.cli + +/** + * Base interface for all possible types of options with multiple values. + * Provides limitations for API that is accessible for options with several values. + * Allows to save the way of providing several values in command line. + * + * @see [MultipleOption] + */ +interface MultipleOptionType { + /** + * Type of an option with multiple values allowed to be provided several times in command line. + */ + class Repeated : MultipleOptionType + + /** + * Type of an option with multiple values allowed to be provided using delimiter in one command line value. + */ + class Delimited : MultipleOptionType + + /** + * Type of an option with multiple values allowed to be provided several times in command line + * both with specifying several values and with delimiter. + */ + class RepeatedDelimited : MultipleOptionType +} + +/** + * The base class for command line options. + * + * You can use [ArgParser.option] function to declare an option. + */ +abstract class Option internal constructor(delegate: ArgumentValueDelegate, + owner: CLIEntityWrapper) : CLIEntity(delegate, owner) + +/** + * The base class of an option with a single value. + * + * A required option or an option with a default value is represented with the [SingleOption] inheritor. + * An option having nullable value is represented with the [SingleNullableOption] inheritor. + */ +abstract class AbstractSingleOption internal constructor( + delegate: ArgumentValueDelegate, + owner: CLIEntityWrapper) : + Option(delegate, owner) { + /** + * Check descriptor for this kind of option. + */ + internal fun checkDescriptor(descriptor: OptionDescriptor<*, *>) { + if (descriptor.multiple || descriptor.delimiter != null) { + failAssertion("Option with single value can't be initialized with descriptor for multiple values.") + } + } +} + +/** + * A required option or an option with a default value. + * + * The [value] of such option is non-null. + */ +class SingleOption internal constructor(descriptor: OptionDescriptor, + owner: CLIEntityWrapper) : + AbstractSingleOption(ArgumentSingleValue(descriptor), owner) { + init { + checkDescriptor(descriptor) + } +} + +/** + * An option with nullable [value]. + */ +class SingleNullableOption internal constructor(descriptor: OptionDescriptor, owner: CLIEntityWrapper) : + AbstractSingleOption(ArgumentSingleNullableValue(descriptor), owner) { + init { + checkDescriptor(descriptor) + } +} + +/** + * An option that allows several values to be provided in command line string. + * + * The [value] property of such option has type `List`. + */ +class MultipleOption internal constructor( + descriptor: OptionDescriptor>, + owner: CLIEntityWrapper +) : + Option>( ArgumentMultipleValues(descriptor), owner) { + init { + if (!descriptor.multiple && descriptor.delimiter == null) { + failAssertion("Option with multiple values can't be initialized with descriptor for single one.") + } + } +} + +/** + * Allows the option to have several values specified in command line string. + * Number of values is unlimited. + */ +fun AbstractSingleOption.multiple(): + MultipleOption { + val newOption = with(delegate.cast>().descriptor as OptionDescriptor) { + MultipleOption( + OptionDescriptor( + optionFullFormPrefix, optionShortFromPrefix, type, fullName, shortName, + description, listOfNotNull(defaultValue), + required, true, delimiter, deprecatedWarning + ), owner + ) + } + owner.entity = newOption + return newOption +} + +/** + * Allows the option to have several values specified in command line string. + * Number of values is unlimited. + */ +fun MultipleOption.multiple(): + MultipleOption { + val newOption = with(delegate.cast>>().descriptor as OptionDescriptor) { + if (multiple) { + error("Try to use modifier multiple() twice on option ${fullName ?: ""}") + } + MultipleOption( + OptionDescriptor( + optionFullFormPrefix, optionShortFromPrefix, type, fullName, shortName, + description, defaultValue?.toList() ?: listOf(), + required, true, delimiter, deprecatedWarning + ), owner + ) + } + owner.entity = newOption + return newOption +} + +/** + * Specifies the default value for the option, that will be used when no value is provided for it + * in command line string. + * + * @param value the default value. + */ +fun SingleNullableOption.default(value: T): SingleOption { + val newOption = with(delegate.cast>().descriptor as OptionDescriptor) { + SingleOption( + OptionDescriptor( + optionFullFormPrefix, optionShortFromPrefix, type, fullName, shortName, + description, value, required, multiple, delimiter, deprecatedWarning + ), owner + ) + } + owner.entity = newOption + return newOption +} + +/** + * Specifies the default value for the option with multiple values, that will be used when no values are provided + * for it in command line string. + * + * @param value the default value, must be a non-empty collection. + * @throws IllegalArgumentException if provided default value is empty collection. + */ +fun + MultipleOption.default(value: Collection): + MultipleOption { + val newOption = with(delegate.cast>>().descriptor as OptionDescriptor) { + require(value.isNotEmpty()) { "Default value for option can't be empty collection." } + MultipleOption( + OptionDescriptor( + optionFullFormPrefix, optionShortFromPrefix, type, fullName, + shortName, description, value.toList(), + required, multiple, delimiter, deprecatedWarning + ), owner + ) + } + owner.entity = newOption + return newOption +} + +/** + * Requires the option to be always provided in command line. + */ +fun SingleNullableOption.required(): SingleOption { + val newOption = with(delegate.cast>().descriptor as OptionDescriptor) { + SingleOption( + OptionDescriptor( + optionFullFormPrefix, optionShortFromPrefix, type, fullName, + shortName, description, defaultValue, + true, multiple, delimiter, deprecatedWarning + ), owner + ) + } + owner.entity = newOption + return newOption +} + +/** + * Requires the option to be always provided in command line. + */ +fun + MultipleOption.required(): + MultipleOption { + val newOption = with(delegate.cast>>().descriptor as OptionDescriptor) { + MultipleOption( + OptionDescriptor( + optionFullFormPrefix, optionShortFromPrefix, type, fullName, shortName, + description, defaultValue?.toList() ?: listOf(), + true, multiple, delimiter, deprecatedWarning + ), owner + ) + } + owner.entity = newOption + return newOption +} + +/** + * Allows the option to have several values joined with [delimiter] specified in command line string. + * Number of values is unlimited. + * + * The value of the argument is an empty list in case if no value was specified in command line string. + * + * @param delimiterValue delimiter used to separate string value to option values list. + */ +fun AbstractSingleOption.delimiter( + delimiterValue: String): + MultipleOption { + val newOption = with(delegate.cast>().descriptor as OptionDescriptor) { + MultipleOption( + OptionDescriptor( + optionFullFormPrefix, optionShortFromPrefix, type, fullName, shortName, + description, listOfNotNull(defaultValue), + required, multiple, delimiterValue, deprecatedWarning + ), owner + ) + } + owner.entity = newOption + return newOption +} + +/** + * Allows the option to have several values joined with [delimiter] specified in command line string. + * Number of values is unlimited. + * + * The value of the argument is an empty list in case if no value was specified in command line string. + * + * @param delimiterValue delimiter used to separate string value to option values list. + */ +fun MultipleOption.delimiter( + delimiterValue: String): + MultipleOption { + val newOption = with(delegate.cast>>().descriptor as OptionDescriptor) { + MultipleOption( + OptionDescriptor( + optionFullFormPrefix, optionShortFromPrefix, type, fullName, shortName, + description, defaultValue?.toList() ?: listOf(), + required, multiple, delimiterValue, deprecatedWarning + ), owner + ) + } + owner.entity = newOption + return newOption +} \ No newline at end of file diff --git a/kotlin-native/endorsedLibraries/kotlinx.cli/src/tests/ArgumentsTests.kt b/kotlin-native/endorsedLibraries/kotlinx.cli/src/tests/ArgumentsTests.kt new file mode 100644 index 00000000000..db49aa8e2b4 --- /dev/null +++ b/kotlin-native/endorsedLibraries/kotlinx.cli/src/tests/ArgumentsTests.kt @@ -0,0 +1,59 @@ +/* + * Copyright 2010-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +package kotlinx.cli + +import kotlinx.cli.ArgParser +import kotlinx.cli.ArgType +import kotlin.test.* + +class ArgumentsTests { + @Test + fun testPositionalArguments() { + val argParser = ArgParser("testParser") + val debugMode by argParser.option(ArgType.Boolean, "debug", "d", "Debug mode") + val input by argParser.argument(ArgType.String, "input", "Input file") + val output by argParser.argument(ArgType.String, "output", "Output file") + argParser.parse(arrayOf("-d", "input.txt", "out.txt")) + assertEquals(true, debugMode) + assertEquals("out.txt", output) + assertEquals("input.txt", input) + } + + @Test + fun testArgumetsWithAnyNumberOfValues() { + val argParser = ArgParser("testParser") + val output by argParser.argument(ArgType.String, "output", "Output file") + val inputs by argParser.argument(ArgType.String, description = "Input files").vararg() + argParser.parse(arrayOf("out.txt", "input1.txt", "input2.txt", "input3.txt", + "input4.txt")) + assertEquals("out.txt", output) + assertEquals(4, inputs.size) + } + + @Test + fun testArgumetsWithSeveralValues() { + val argParser = ArgParser("testParser") + val addendums by argParser.argument(ArgType.Int, "addendums", description = "Addendums").multiple(2) + val output by argParser.argument(ArgType.String, "output", "Output file") + val debugMode by argParser.option(ArgType.Boolean, "debug", "d", "Debug mode") + argParser.parse(arrayOf("2", "-d", "3", "out.txt")) + assertEquals("out.txt", output) + val (first, second) = addendums + assertEquals(2, addendums.size) + assertEquals(2, first) + assertEquals(3, second) + } + + @Test + fun testSkippingExtraArguments() { + val argParser = ArgParser("testParser", skipExtraArguments = true) + val addendums by argParser.argument(ArgType.Int, "addendums", description = "Addendums").multiple(2) + val output by argParser.argument(ArgType.String, "output", "Output file") + val debugMode by argParser.option(ArgType.Boolean, "debug", "d", "Debug mode") + argParser.parse(arrayOf("2", "-d", "3", "out.txt", "something", "else", "in", "string")) + assertEquals("out.txt", output) + } +} diff --git a/kotlin-native/endorsedLibraries/kotlinx.cli/src/tests/ErrorTests.kt b/kotlin-native/endorsedLibraries/kotlinx.cli/src/tests/ErrorTests.kt new file mode 100644 index 00000000000..411d3f48738 --- /dev/null +++ b/kotlin-native/endorsedLibraries/kotlinx.cli/src/tests/ErrorTests.kt @@ -0,0 +1,56 @@ +/* + * Copyright 2010-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +package kotlinx.cli + +import kotlinx.cli.ArgParser +import kotlinx.cli.ArgType +import kotlin.test.* + +class ErrorTests { + @Test + fun testExtraArguments() { + val argParser = ArgParser("testParser") + val addendums by argParser.argument(ArgType.Int, "addendums", description = "Addendums").multiple(2) + val output by argParser.argument(ArgType.String, "output", "Output file") + val debugMode by argParser.option(ArgType.Boolean, "debug", "d", "Debug mode") + val exception = assertFailsWith { argParser.parse( + arrayOf("2", "-d", "3", "out.txt", "something", "else", "in", "string")) } + assertTrue("Too many arguments! Couldn't process argument something" in exception.message!!) + } + + @Test + fun testUnknownOption() { + val argParser = ArgParser("testParser") + val output by argParser.option(ArgType.String, "output", "o", "Output file") + val input by argParser.option(ArgType.String, "input", "i", "Input file") + val exception = assertFailsWith { + argParser.parse(arrayOf("-o", "out.txt", "-d", "-i", "input.txt")) + } + assertTrue("Unknown option -d" in exception.message!!) + } + + @Test + fun testWrongFormat() { + val argParser = ArgParser("testParser") + val number by argParser.option(ArgType.Int, "number", description = "Integer number") + val exception = assertFailsWith { + argParser.parse(arrayOf("--number", "out.txt")) + } + assertTrue("Option number is expected to be integer number. out.txt is provided." in exception.message!!) + } + + @Test + fun testWrongChoice() { + val argParser = ArgParser("testParser") + val useShortForm by argParser.option(ArgType.Boolean, "short", "s", "Show short version of report").default(false) + val renders by argParser.option(ArgType.Choice(listOf("text", "html")), + "renders", "r", "Renders for showing information").multiple().default(listOf("text")) + val exception = assertFailsWith { + argParser.parse(arrayOf("-r", "xml")) + } + assertTrue("Option renders is expected to be one of [text, html]. xml is provided." in exception.message!!) + } +} diff --git a/kotlin-native/endorsedLibraries/kotlinx.cli/src/tests/HelpTests.kt b/kotlin-native/endorsedLibraries/kotlinx.cli/src/tests/HelpTests.kt new file mode 100644 index 00000000000..eafa058a663 --- /dev/null +++ b/kotlin-native/endorsedLibraries/kotlinx.cli/src/tests/HelpTests.kt @@ -0,0 +1,144 @@ +/* + * Copyright 2010-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ +@file:OptIn(ExperimentalCli::class) +package kotlinx.cli + +import kotlinx.cli.ArgParser +import kotlinx.cli.ArgType +import kotlinx.cli.ExperimentalCli +import kotlinx.cli.Subcommand +import kotlin.math.exp +import kotlin.test.* + +class HelpTests { + @Test + fun testHelpMessage() { + val argParser = ArgParser("test") + val mainReport by argParser.argument(ArgType.String, description = "Main report for analysis") + val compareToReport by argParser.argument(ArgType.String, description = "Report to compare to").optional() + + val output by argParser.option(ArgType.String, shortName = "o", description = "Output file") + val epsValue by argParser.option(ArgType.Double, "eps", "e", "Meaningful performance changes").default(1.0) + val useShortForm by argParser.option(ArgType.Boolean, "short", "s", + "Show short version of report").default(false) + val renders by argParser.option(ArgType.Choice(listOf("text", "html", "teamcity", "statistics", "metrics")), + shortName = "r", description = "Renders for showing information").multiple().default(listOf("text")) + val user by argParser.option(ArgType.String, shortName = "u", description = "User access information for authorization") + argParser.parse(arrayOf("main.txt")) + val helpOutput = argParser.makeUsage().trimIndent() + @Suppress("CanBeVal") // can't be val in order to build expectedOutput only in run time. + var epsDefault = 1.0 + val expectedOutput = """ +Usage: test options_list +Arguments: + mainReport -> Main report for analysis { String } + compareToReport -> Report to compare to (optional) { String } +Options: + --output, -o -> Output file { String } + --eps, -e [$epsDefault] -> Meaningful performance changes { Double } + --short, -s [false] -> Show short version of report + --renders, -r [text] -> Renders for showing information { Value should be one of [text, html, teamcity, statistics, metrics] } + --user, -u -> User access information for authorization { String } + --help, -h -> Usage info + """.trimIndent() + assertEquals(expectedOutput, helpOutput) + } + + @Test + fun testHelpForSubcommands() { + class Summary: Subcommand("summary", "Get summary information") { + val exec by option(ArgType.Choice(listOf("samples", "geomean")), + description = "Execution time way of calculation").default("geomean") + val execSamples by option(ArgType.String, "exec-samples", + description = "Samples used for execution time metric (value 'all' allows use all samples)").delimiter(",") + val execNormalize by option(ArgType.String, "exec-normalize", + description = "File with golden results which should be used for normalization") + val compile by option(ArgType.Choice(listOf("samples", "geomean")), + description = "Compile time way of calculation").default("geomean") + val compileSamples by option(ArgType.String, "compile-samples", + description = "Samples used for compile time metric (value 'all' allows use all samples)").delimiter(",") + val compileNormalize by option(ArgType.String, "compile-normalize", + description = "File with golden results which should be used for normalization") + val codesize by option(ArgType.Choice(listOf("samples", "geomean")), + description = "Code size way of calculation").default("geomean") + val codesizeSamples by option(ArgType.String, "codesize-samples", + description = "Samples used for code size metric (value 'all' allows use all samples)").delimiter(",") + val codesizeNormalize by option(ArgType.String, "codesize-normalize", + description = "File with golden results which should be used for normalization") + val user by option(ArgType.String, shortName = "u", description = "User access information for authorization") + val mainReport by argument(ArgType.String, description = "Main report for analysis") + + override fun execute() { + println("Do some important things!") + } + } + val action = Summary() + // Parse args. + val argParser = ArgParser("test") + argParser.subcommands(action) + argParser.parse(arrayOf("summary", "out.txt")) + val helpOutput = action.makeUsage().trimIndent() + val expectedOutput = """ +Usage: test summary options_list +Arguments: + mainReport -> Main report for analysis { String } +Options: + --exec [geomean] -> Execution time way of calculation { Value should be one of [samples, geomean] } + --exec-samples -> Samples used for execution time metric (value 'all' allows use all samples) { String } + --exec-normalize -> File with golden results which should be used for normalization { String } + --compile [geomean] -> Compile time way of calculation { Value should be one of [samples, geomean] } + --compile-samples -> Samples used for compile time metric (value 'all' allows use all samples) { String } + --compile-normalize -> File with golden results which should be used for normalization { String } + --codesize [geomean] -> Code size way of calculation { Value should be one of [samples, geomean] } + --codesize-samples -> Samples used for code size metric (value 'all' allows use all samples) { String } + --codesize-normalize -> File with golden results which should be used for normalization { String } + --user, -u -> User access information for authorization { String } + --help, -h -> Usage info +""".trimIndent() + assertEquals(expectedOutput, helpOutput) + } + + @Test + fun testHelpMessageWithSubcommands() { + abstract class CommonOptions(name: String, actionDescription: String): Subcommand(name, actionDescription) { + val numbers by argument(ArgType.Int, "numbers", description = "Numbers").vararg() + } + class Summary: CommonOptions("summary", "Calculate summary") { + val invert by option(ArgType.Boolean, "invert", "i", "Invert results") + var result: Int = 0 + + override fun execute() { + result = numbers.sum() + result = invert?.let { -1 * result } ?: result + } + } + + class Subtraction : CommonOptions("sub", "Calculate subtraction") { + var result: Int = 0 + + override fun execute() { + result = numbers.map { -it }.sum() + } + } + + val summaryAction = Summary() + val subtractionAction = Subtraction() + val argParser = ArgParser("testParser") + argParser.subcommands(summaryAction, subtractionAction) + argParser.parse(emptyArray()) + val helpOutput = argParser.makeUsage().trimIndent() + println(helpOutput) + val expectedOutput = """ +Usage: testParser options_list +Subcommands: + summary - Calculate summary + sub - Calculate subtraction + +Options: + --help, -h -> Usage info +""".trimIndent() + assertEquals(expectedOutput, helpOutput) + } +} diff --git a/kotlin-native/endorsedLibraries/kotlinx.cli/src/tests/OptionsTests.kt b/kotlin-native/endorsedLibraries/kotlinx.cli/src/tests/OptionsTests.kt new file mode 100644 index 00000000000..8a883c1fca3 --- /dev/null +++ b/kotlin-native/endorsedLibraries/kotlinx.cli/src/tests/OptionsTests.kt @@ -0,0 +1,120 @@ +/* + * Copyright 2010-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +package kotlinx.cli + +import kotlin.test.* + +class OptionsTests { + @Test + fun testShortForm() { + val argParser = ArgParser("testParser") + val output by argParser.option(ArgType.String, "output", "o", "Output file") + val input by argParser.option(ArgType.String, "input", "i", "Input file") + argParser.parse(arrayOf("-o", "out.txt", "-i", "input.txt")) + assertEquals("out.txt", output) + assertEquals("input.txt", input) + } + + @Test + fun testFullForm() { + val argParser = ArgParser("testParser") + val output by argParser.option(ArgType.String, shortName = "o", description = "Output file") + val input by argParser.option(ArgType.String, shortName = "i", description = "Input file") + argParser.parse(arrayOf("--output", "out.txt", "--input", "input.txt")) + assertEquals("out.txt", output) + assertEquals("input.txt", input) + } + + @Test + fun testJavaPrefix() { + val argParser = ArgParser("testParser", prefixStyle = ArgParser.OptionPrefixStyle.JVM) + val output by argParser.option(ArgType.String, "output", "o", "Output file") + val input by argParser.option(ArgType.String, "input", "i", "Input file") + argParser.parse(arrayOf("-output", "out.txt", "-i", "input.txt")) + assertEquals("out.txt", output) + assertEquals("input.txt", input) + } + + @Test + fun testGNUPrefix() { + val argParser = ArgParser("testParser", prefixStyle = ArgParser.OptionPrefixStyle.GNU) + val output by argParser.option(ArgType.String, "output", "o", "Output file") + val input by argParser.option(ArgType.String, "input", "i", "Input file") + val verbose by argParser.option(ArgType.Boolean, "verbose", "v", "Verbose print") + val shortForm by argParser.option(ArgType.Boolean, "short", "s", "Short output form") + val text by argParser.option(ArgType.Boolean, "text", "t", "Use text format") + argParser.parse(arrayOf("-oout.txt", "--input=input.txt", "-vst")) + assertEquals("out.txt", output) + assertEquals("input.txt", input) + assertEquals(verbose, true) + assertEquals(shortForm, true) + assertEquals(text, true) + } + + @Test + fun testGNUArguments() { + val argParser = ArgParser("testParser", prefixStyle = ArgParser.OptionPrefixStyle.GNU) + val output by argParser.argument(ArgType.String, "output", "Output file") + val input by argParser.argument(ArgType.String, "input", "Input file") + val verbose by argParser.option(ArgType.Boolean, "verbose", "v", "Verbose print") + val shortForm by argParser.option(ArgType.Boolean, "short", "s", "Short output form").default(false) + val text by argParser.option(ArgType.Boolean, "text", "t", "Use text format").default(false) + argParser.parse(arrayOf("--verbose", "--", "out.txt", "--input.txt")) + assertEquals("out.txt", output) + assertEquals("--input.txt", input) + assertEquals(verbose, true) + assertEquals(shortForm, false) + assertEquals(text, false) + } + + @Test + fun testMultipleOptions() { + val argParser = ArgParser("testParser") + val useShortForm by argParser.option(ArgType.Boolean, "short", "s", "Show short version of report").default(false) + val renders by argParser.option(ArgType.Choice(listOf("text", "html", "xml", "json")), + "renders", "r", "Renders for showing information").multiple().default(listOf("text")) + argParser.parse(arrayOf("-s", "-r", "text", "-r", "json")) + assertEquals(true, useShortForm) + assertEquals(2, renders.size) + val (firstRender, secondRender) = renders + assertEquals("text", firstRender) + assertEquals("json", secondRender) + } + + @Test + fun testDefaultOptions() { + val argParser = ArgParser("testParser") + val useShortForm by argParser.option(ArgType.Boolean, "short", "s", "Show short version of report").default(false) + val renders by argParser.option(ArgType.Choice(listOf("text", "html", "xml", "json")), + "renders", "r", "Renders for showing information").multiple().default(listOf("text")) + val output by argParser.option(ArgType.String, "output", "o", "Output file") + argParser.parse(arrayOf("-o", "out.txt")) + assertEquals(false, useShortForm) + assertEquals("text", renders[0]) + } + + @Test + fun testResetOptionsValues() { + val argParser = ArgParser("testParser") + val useShortFormOption = argParser.option(ArgType.Boolean, "short", "s", "Show short version of report").default(false) + var useShortForm by useShortFormOption + val rendersOption = argParser.option(ArgType.Choice(listOf("text", "html", "xml", "json")), + "renders", "r", "Renders for showing information").multiple().default(listOf("text")) + var renders by rendersOption + val outputOption = argParser.option(ArgType.String, "output", "o", "Output file") + var output by outputOption + argParser.parse(arrayOf("-o", "out.txt")) + output = null + useShortForm = true + renders = listOf() + assertEquals(true, useShortForm) + assertEquals(null, output) + assertEquals(0, renders.size) + assertEquals(ArgParser.ValueOrigin.REDEFINED, outputOption.valueOrigin) + assertEquals(ArgParser.ValueOrigin.REDEFINED, useShortFormOption.valueOrigin) + assertEquals(ArgParser.ValueOrigin.REDEFINED, rendersOption.valueOrigin) + } +} diff --git a/kotlin-native/endorsedLibraries/kotlinx.cli/src/tests/SubcommandsTests.kt b/kotlin-native/endorsedLibraries/kotlinx.cli/src/tests/SubcommandsTests.kt new file mode 100644 index 00000000000..2d13d10d11b --- /dev/null +++ b/kotlin-native/endorsedLibraries/kotlinx.cli/src/tests/SubcommandsTests.kt @@ -0,0 +1,103 @@ +/* + * Copyright 2010-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ +@file:OptIn(ExperimentalCli::class) +package kotlinx.cli + +import kotlinx.cli.ArgParser +import kotlinx.cli.ArgType +import kotlinx.cli.ExperimentalCli +import kotlinx.cli.Subcommand +import kotlin.test.* + +class SubcommandsTests { + @Test + fun testSubcommand() { + val argParser = ArgParser("testParser") + val output by argParser.option(ArgType.String, "output", "o", "Output file") + class Summary: Subcommand("summary", "Calculate summary") { + val invert by option(ArgType.Boolean, "invert", "i", "Invert results") + val addendums by argument(ArgType.Int, "addendums", description = "Addendums").vararg() + var result: Int = 0 + + override fun execute() { + result = addendums.sum() + result = if (invert!!) -1 * result else result + } + } + val action = Summary() + argParser.subcommands(action) + argParser.parse(arrayOf("-o", "out.txt", "summary", "-i", "2", "3", "5")) + assertEquals("out.txt", output) + assertEquals(-10, action.result) + } + + @Test + fun testCommonOptions() { + abstract class CommonOptions(name: String, actionDescription: String): Subcommand(name, actionDescription) { + val numbers by argument(ArgType.Int, "numbers", description = "Numbers").vararg() + } + class Summary: CommonOptions("summary", "Calculate summary") { + val invert by option(ArgType.Boolean, "invert", "i", "Invert results") + var result: Int = 0 + + override fun execute() { + result = numbers.sum() + result = invert?.let { -1 * result } ?: result + } + } + + class Subtraction : CommonOptions("sub", "Calculate subtraction") { + var result: Int = 0 + + override fun execute() { + result = numbers.map { -it }.sum() + } + } + + val summaryAction = Summary() + val subtractionAction = Subtraction() + val argParser = ArgParser("testParser") + argParser.subcommands(summaryAction, subtractionAction) + argParser.parse(arrayOf("summary", "2", "3", "5")) + assertEquals(10, summaryAction.result) + + val argParserSubtraction = ArgParser("testParser") + argParserSubtraction.subcommands(summaryAction, subtractionAction) + argParserSubtraction.parse(arrayOf("sub", "8", "-2", "3")) + assertEquals(-9, subtractionAction.result) + } + + @Test + fun testRecursiveSubcommands() { + val argParser = ArgParser("testParser") + + class Summary: Subcommand("summary", "Calculate summary") { + val addendums by argument(ArgType.Int, "addendums", description = "Addendums").vararg() + var result: Int = 0 + + override fun execute() { + result = addendums.sum() + } + } + + class Calculation: Subcommand("calc", "Execute calculation") { + init { + subcommands(Summary()) + } + val invert by option(ArgType.Boolean, "invert", "i", "Invert results") + var result: Int = 0 + + override fun execute() { + result = (subcommands["summary"] as Summary).result + result = if (invert!!) -1 * result else result + } + } + + val action = Calculation() + argParser.subcommands(action) + argParser.parse(arrayOf("calc", "-i", "summary", "2", "3", "5")) + assertEquals(-10, action.result) + } +} diff --git a/kotlin-native/gradle.properties b/kotlin-native/gradle.properties new file mode 100644 index 00000000000..7375caeaea3 --- /dev/null +++ b/kotlin-native/gradle.properties @@ -0,0 +1,46 @@ +# +# Copyright 2010-2019 JetBrains s.r.o. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +# A version of the Kotlin compiler that is used to build Kotlin/Native. +buildKotlinVersion=1.4.20-dev-2167 +buildKotlinCompilerRepo=https://teamcity.jetbrains.com/guestAuth/app/rest/builds/buildType:(id:Kotlin_KotlinPublic_Compiler),number:1.4.20-dev-2167,branch:default:any,pinned:true/artifacts/content/maven +remoteRoot=konan_tests +kotlinCompilerRepo=https://teamcity.jetbrains.com/guestAuth/app/rest/builds/buildType:(id:Kotlin_KotlinPublic_Compiler),number:1.4.30-dev-1895,branch:default:any,pinned:true/artifacts/content/maven +kotlinVersion=1.4.30-dev-1895 +kotlinStdlibRepo=https://teamcity.jetbrains.com/guestAuth/app/rest/builds/buildType:(id:Kotlin_KotlinPublic_Compiler),number:1.4.30-dev-1895,branch:default:any,pinned:true/artifacts/content/maven +kotlinStdlibVersion=1.4.30-dev-1895 +kotlinStdlibTestsVersion=1.4.30-dev-1895 +testKotlinCompilerVersion=1.4.30-dev-1895 +konanVersion=1.4.30 + +# A version of Xcode required to build the Kotlin/Native compiler. +xcodeMajorVersion=12 + +# A GTest revision used to test the runtime. +# The latest release GTest (1.10.0) doesn't properly register skipped tests in an XML-report. +# Therefore we use a fixed commit form the master branch where this problem is already fixed. +# https://github.com/google/googletest/commit/07f4869221012b16b7f9ee685d94856e1fc9f361 +gtestRevision=07f4869221012b16b7f9ee685d94856e1fc9f361 + +org.gradle.jvmargs='-Dfile.encoding=UTF-8' +org.gradle.workers.max=4 +slackApiVersion=1.2.0 +ktorVersion=1.2.1 +shadowVersion=5.1.0 +metadataVersion=0.0.1-dev-10 + +# Uncomment to enable composite build +#kotlinProjectPath= diff --git a/kotlin-native/gradle/kotlinGradlePlugin.gradle b/kotlin-native/gradle/kotlinGradlePlugin.gradle new file mode 100644 index 00000000000..2a53ac309ca --- /dev/null +++ b/kotlin-native/gradle/kotlinGradlePlugin.gradle @@ -0,0 +1,37 @@ +def properties = ['buildKotlinVersion', 'buildKotlinCompilerRepo', 'kotlinVersion', 'kotlinCompilerRepo'] + +for (prop in properties) { + if (!hasProperty(prop)) { + throw new GradleException("Please ensure the '$prop' property is defined before applying this script.") + } +} + +project.buildscript.repositories { + maven { + url buildKotlinCompilerRepo + } + maven { + url kotlinCompilerRepo + } + maven { + url 'https://cache-redirector.jetbrains.com/maven-central' + } + mavenCentral() +} + +project.buildscript.dependencies { + classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlinVersion" +} +configurations { + kotlinCompilerClasspath +} +project.repositories { + maven { url buildKotlinCompilerRepo } + maven { + url kotlinCompilerRepo + } +} + +project.dependencies { + kotlinCompilerClasspath("org.jetbrains.kotlin:kotlin-compiler-embeddable:$buildKotlinVersion") +} diff --git a/kotlin-native/gradle/loadRootProperties.gradle b/kotlin-native/gradle/loadRootProperties.gradle new file mode 100644 index 00000000000..25edb22f83b --- /dev/null +++ b/kotlin-native/gradle/loadRootProperties.gradle @@ -0,0 +1,16 @@ +if (!project.hasProperty("rootBuildDirectory")) { + throw new GradleException('Please ensure the "rootBuildDirectory" property is defined before applying this script.') +} + +ext.distDir = file("$rootBuildDirectory/dist") + +def rootProperties = new Properties() +def rootDir = file(rootBuildDirectory).absolutePath +file("$rootDir/gradle.properties").withReader { + rootProperties.load(it) +} +rootProperties.each { k, v -> + if (!project.hasProperty(k)) { + ext.set(k, v) + } +} diff --git a/kotlin-native/gradle/wrapper/gradle-wrapper.jar b/kotlin-native/gradle/wrapper/gradle-wrapper.jar new file mode 100644 index 00000000000..e708b1c023e Binary files /dev/null and b/kotlin-native/gradle/wrapper/gradle-wrapper.jar differ diff --git a/kotlin-native/gradle/wrapper/gradle-wrapper.properties b/kotlin-native/gradle/wrapper/gradle-wrapper.properties new file mode 100644 index 00000000000..33682bbbf90 --- /dev/null +++ b/kotlin-native/gradle/wrapper/gradle-wrapper.properties @@ -0,0 +1,5 @@ +distributionBase=GRADLE_USER_HOME +distributionPath=wrapper/dists +distributionUrl=https\://services.gradle.org/distributions/gradle-6.6.1-all.zip +zipStoreBase=GRADLE_USER_HOME +zipStorePath=wrapper/dists diff --git a/kotlin-native/gradlew b/kotlin-native/gradlew new file mode 100755 index 00000000000..4f906e0c811 --- /dev/null +++ b/kotlin-native/gradlew @@ -0,0 +1,185 @@ +#!/usr/bin/env sh + +# +# Copyright 2015 the original author or authors. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# https://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +############################################################################## +## +## Gradle start up script for UN*X +## +############################################################################## + +# Attempt to set APP_HOME +# Resolve links: $0 may be a link +PRG="$0" +# Need this for relative symlinks. +while [ -h "$PRG" ] ; do + ls=`ls -ld "$PRG"` + link=`expr "$ls" : '.*-> \(.*\)$'` + if expr "$link" : '/.*' > /dev/null; then + PRG="$link" + else + PRG=`dirname "$PRG"`"/$link" + fi +done +SAVED="`pwd`" +cd "`dirname \"$PRG\"`/" >/dev/null +APP_HOME="`pwd -P`" +cd "$SAVED" >/dev/null + +APP_NAME="Gradle" +APP_BASE_NAME=`basename "$0"` + +# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"' + +# Use the maximum available, or set MAX_FD != -1 to use that value. +MAX_FD="maximum" + +warn () { + echo "$*" +} + +die () { + echo + echo "$*" + echo + exit 1 +} + +# OS specific support (must be 'true' or 'false'). +cygwin=false +msys=false +darwin=false +nonstop=false +case "`uname`" in + CYGWIN* ) + cygwin=true + ;; + Darwin* ) + darwin=true + ;; + MINGW* ) + msys=true + ;; + NONSTOP* ) + nonstop=true + ;; +esac + +CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar + + +# Determine the Java command to use to start the JVM. +if [ -n "$JAVA_HOME" ] ; then + if [ -x "$JAVA_HOME/jre/sh/java" ] ; then + # IBM's JDK on AIX uses strange locations for the executables + JAVACMD="$JAVA_HOME/jre/sh/java" + else + JAVACMD="$JAVA_HOME/bin/java" + fi + if [ ! -x "$JAVACMD" ] ; then + die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME + +Please set the JAVA_HOME variable in your environment to match the +location of your Java installation." + fi +else + JAVACMD="java" + which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. + +Please set the JAVA_HOME variable in your environment to match the +location of your Java installation." +fi + +# Increase the maximum file descriptors if we can. +if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then + MAX_FD_LIMIT=`ulimit -H -n` + if [ $? -eq 0 ] ; then + if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then + MAX_FD="$MAX_FD_LIMIT" + fi + ulimit -n $MAX_FD + if [ $? -ne 0 ] ; then + warn "Could not set maximum file descriptor limit: $MAX_FD" + fi + else + warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT" + fi +fi + +# For Darwin, add options to specify how the application appears in the dock +if $darwin; then + GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\"" +fi + +# For Cygwin or MSYS, switch paths to Windows format before running java +if [ "$cygwin" = "true" -o "$msys" = "true" ] ; then + APP_HOME=`cygpath --path --mixed "$APP_HOME"` + CLASSPATH=`cygpath --path --mixed "$CLASSPATH"` + + JAVACMD=`cygpath --unix "$JAVACMD"` + + # We build the pattern for arguments to be converted via cygpath + ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null` + SEP="" + for dir in $ROOTDIRSRAW ; do + ROOTDIRS="$ROOTDIRS$SEP$dir" + SEP="|" + done + OURCYGPATTERN="(^($ROOTDIRS))" + # Add a user-defined pattern to the cygpath arguments + if [ "$GRADLE_CYGPATTERN" != "" ] ; then + OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)" + fi + # Now convert the arguments - kludge to limit ourselves to /bin/sh + i=0 + for arg in "$@" ; do + CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -` + CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option + + if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition + eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"` + else + eval `echo args$i`="\"$arg\"" + fi + i=`expr $i + 1` + done + case $i in + 0) set -- ;; + 1) set -- "$args0" ;; + 2) set -- "$args0" "$args1" ;; + 3) set -- "$args0" "$args1" "$args2" ;; + 4) set -- "$args0" "$args1" "$args2" "$args3" ;; + 5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;; + 6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;; + 7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;; + 8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;; + 9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;; + esac +fi + +# Escape application args +save () { + for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done + echo " " +} +APP_ARGS=`save "$@"` + +# Collect all arguments for the java command, following the shell quoting and substitution rules +eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS" + +exec "$JAVACMD" "$@" diff --git a/kotlin-native/gradlew.bat b/kotlin-native/gradlew.bat new file mode 100644 index 00000000000..ac1b06f9382 --- /dev/null +++ b/kotlin-native/gradlew.bat @@ -0,0 +1,89 @@ +@rem +@rem Copyright 2015 the original author or authors. +@rem +@rem Licensed under the Apache License, Version 2.0 (the "License"); +@rem you may not use this file except in compliance with the License. +@rem You may obtain a copy of the License at +@rem +@rem https://www.apache.org/licenses/LICENSE-2.0 +@rem +@rem Unless required by applicable law or agreed to in writing, software +@rem distributed under the License is distributed on an "AS IS" BASIS, +@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +@rem See the License for the specific language governing permissions and +@rem limitations under the License. +@rem + +@if "%DEBUG%" == "" @echo off +@rem ########################################################################## +@rem +@rem Gradle startup script for Windows +@rem +@rem ########################################################################## + +@rem Set local scope for the variables with windows NT shell +if "%OS%"=="Windows_NT" setlocal + +set DIRNAME=%~dp0 +if "%DIRNAME%" == "" set DIRNAME=. +set APP_BASE_NAME=%~n0 +set APP_HOME=%DIRNAME% + +@rem Resolve any "." and ".." in APP_HOME to make it shorter. +for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi + +@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m" + +@rem Find java.exe +if defined JAVA_HOME goto findJavaFromJavaHome + +set JAVA_EXE=java.exe +%JAVA_EXE% -version >NUL 2>&1 +if "%ERRORLEVEL%" == "0" goto execute + +echo. +echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. +echo. +echo Please set the JAVA_HOME variable in your environment to match the +echo location of your Java installation. + +goto fail + +:findJavaFromJavaHome +set JAVA_HOME=%JAVA_HOME:"=% +set JAVA_EXE=%JAVA_HOME%/bin/java.exe + +if exist "%JAVA_EXE%" goto execute + +echo. +echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% +echo. +echo Please set the JAVA_HOME variable in your environment to match the +echo location of your Java installation. + +goto fail + +:execute +@rem Setup the command line + +set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar + + +@rem Execute Gradle +"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %* + +:end +@rem End local scope for the variables with windows NT shell +if "%ERRORLEVEL%"=="0" goto mainEnd + +:fail +rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of +rem the _cmd.exe /c_ return code! +if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 +exit /b 1 + +:mainEnd +if "%OS%"=="Windows_NT" endlocal + +:omega diff --git a/kotlin-native/klib/build.gradle b/kotlin-native/klib/build.gradle new file mode 100644 index 00000000000..817e8e2fed5 --- /dev/null +++ b/kotlin-native/klib/build.gradle @@ -0,0 +1,67 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ +buildscript { + apply from: "$rootDir/gradle/kotlinGradlePlugin.gradle" + dependencies { + classpath "org.jetbrains.kotlin:kotlin-native-gradle-plugin:$gradlePluginVersion" + } + + ext.useCustomDist = project.hasProperty("org.jetbrains.kotlin.native.home") || project.hasProperty("konan.home") + if (!useCustomDist) { + ext.setProperty("org.jetbrains.kotlin.native.home", distDir.absolutePath) + } + if (project.hasProperty("konan.home")) { + ext.setProperty("org.jetbrains.kotlin.native.home", project.getProperty("konan.home")) + } +} + +apply plugin: 'kotlin' +apply plugin: 'konan' + +konanArtifacts { + def testFiles = fileTree('src/test/testData') { + include "*.kt" + } + testFiles.files.each { file -> + def name = file.name + library(name.take(name.lastIndexOf('.'))) { + srcFiles file.absolutePath + + // Build the compiler before building the test unless a custom path to the distribution is specified. + if (!useCustomDist) { + dependsOn ':dist' + } + } + } +} + +repositories { + maven { + url buildKotlinCompilerRepo + } +} + +dependencies { + implementation "org.jetbrains.kotlin:kotlin-stdlib:$kotlinVersion" + implementation project(path: ':backend.native', configuration: 'cli_bc') + implementation project(":utilities:basic-utils") + testImplementation "junit:junit:4.12" + testImplementation "org.jetbrains.kotlin:kotlin-test-junit:$buildKotlinVersion" + testImplementation "org.jetbrains.kotlin:kotlin-test:$buildKotlinVersion" +} + +test { + dependsOn 'cleanTest' + // Specify a path to the distribution that is used in the tests. + systemProperty('konan.home', getProperty("org.jetbrains.kotlin.native.home")) + dependsOn konanArtifacts.collect { it.getByTarget('host') } + if (useCustomDist) { + // Use the klib utility from the distribution + def distClasspath = fileTree("${project.getProperty("org.jetbrains.kotlin.native.home")}/konan/lib") { + include "**/*.jar" + } + classpath = distClasspath + sourceSets.test.runtimeClasspath - sourceSets.main.runtimeClasspath + } +} \ No newline at end of file diff --git a/kotlin-native/klib/src/main/kotlin/org/jetbrains/kotlin/cli/klib/DeclarationHeaderRenderer.kt b/kotlin-native/klib/src/main/kotlin/org/jetbrains/kotlin/cli/klib/DeclarationHeaderRenderer.kt new file mode 100644 index 00000000000..4523ed42b25 --- /dev/null +++ b/kotlin-native/klib/src/main/kotlin/org/jetbrains/kotlin/cli/klib/DeclarationHeaderRenderer.kt @@ -0,0 +1,7 @@ +package org.jetbrains.kotlin.cli.klib + +import org.jetbrains.kotlin.descriptors.DeclarationDescriptor + +interface DeclarationHeaderRenderer { + fun render(descriptor: DeclarationDescriptor): String +} diff --git a/kotlin-native/klib/src/main/kotlin/org/jetbrains/kotlin/cli/klib/DeclarationPrinter.kt b/kotlin-native/klib/src/main/kotlin/org/jetbrains/kotlin/cli/klib/DeclarationPrinter.kt new file mode 100644 index 00000000000..2298c34926f --- /dev/null +++ b/kotlin-native/klib/src/main/kotlin/org/jetbrains/kotlin/cli/klib/DeclarationPrinter.kt @@ -0,0 +1,100 @@ +package org.jetbrains.kotlin.cli.klib + +import org.jetbrains.kotlin.backend.konan.descriptors.getPackageFragments +import org.jetbrains.kotlin.descriptors.* +import org.jetbrains.kotlin.descriptors.impl.DeclarationDescriptorVisitorEmptyBodies +import org.jetbrains.kotlin.utils.Printer + +class DeclarationPrinter( + out: Appendable, + private val headerRenderer: DeclarationHeaderRenderer, + private val signatureRenderer: IdSignatureRenderer +) { + private val printer = Printer(out, 1, " ") + + private val DeclarationDescriptorWithVisibility.isPublicOrProtected: Boolean + get() = visibility == DescriptorVisibilities.PUBLIC || visibility == DescriptorVisibilities.PROTECTED + + private val CallableMemberDescriptor.isFakeOverride: Boolean + get() = kind == CallableMemberDescriptor.Kind.FAKE_OVERRIDE + + private val DeclarationDescriptor.shouldBePrinted: Boolean + get() = this is ClassifierDescriptorWithTypeParameters && isPublicOrProtected + || this is CallableMemberDescriptor && isPublicOrProtected && !isFakeOverride + + fun print(module: ModuleDescriptor) { + module.accept(PrinterVisitor(), Unit) + } + + private fun Printer.printWithBody(header: String, signature: String? = null, body: () -> Unit) { + println() + printPlain(header, signature, suffix = " {") + pushIndent() + body() + popIndent() + println("}") + println() + } + + private fun Printer.printPlain(header: String, signature: String? = null, suffix: String? = null) { + if (signature != null) println(signature) + println(if (suffix != null ) header + suffix else header) + } + + private inner class PrinterVisitor : DeclarationDescriptorVisitorEmptyBodies() { + override fun visitModuleDeclaration(descriptor: ModuleDescriptor, data: Unit) { + descriptor.getPackageFragments().forEach { it.accept(this, data) } + } + + override fun visitPackageFragmentDescriptor(descriptor: PackageFragmentDescriptor, data: Unit) { + val children = descriptor.getMemberScope().getContributedDescriptors().filter { it.shouldBePrinted } + if (children.isNotEmpty()) { + printer.printWithBody(header = headerRenderer.render(descriptor)) { + children.forEach { it.accept(this, data) } + } + } + } + + override fun visitClassDescriptor(descriptor: ClassDescriptor, data: Unit) { + val header = headerRenderer.render(descriptor) + val signature = signatureRenderer.render(descriptor) + + val children = descriptor.unsubstitutedMemberScope.getContributedDescriptors().filter { it.shouldBePrinted } + val constructors = descriptor.constructors.filter { !it.isPrimary && it.shouldBePrinted } + if (children.isNotEmpty() || constructors.isNotEmpty()) { + printer.printWithBody(header, signature) { + constructors.forEach { it.accept(this, data) } + children.forEach { it.accept(this, data) } + } + } else { + printer.printPlain(header, signature) + } + } + + override fun visitFunctionDescriptor(descriptor: FunctionDescriptor, data: Unit) { + printer.printPlain(header = headerRenderer.render(descriptor), signature = signatureRenderer.render(descriptor)) + } + + override fun visitPropertyDescriptor(descriptor: PropertyDescriptor, data: Unit) { + printer.printPlain(header = headerRenderer.render(descriptor), signature = signatureRenderer.render(descriptor)) + descriptor.getter?.takeIf { !it.annotations.isEmpty() }?.let { getter -> + printer.pushIndent() + printer.printPlain(header = headerRenderer.render(getter), signature = signatureRenderer.render(getter)) + printer.popIndent() + } + descriptor.setter?.takeIf { !it.annotations.isEmpty() || it.visibility != descriptor.visibility }?.let { setter -> + printer.pushIndent() + printer.printPlain(header = headerRenderer.render(setter), signature = signatureRenderer.render(setter)) + printer.popIndent() + } + } + + override fun visitConstructorDescriptor(descriptor: ConstructorDescriptor, data: Unit) { + printer.printPlain(header = headerRenderer.render(descriptor), signature = signatureRenderer.render(descriptor)) + } + + override fun visitTypeAliasDescriptor(descriptor: TypeAliasDescriptor, data: Unit) { + printer.printPlain(header = headerRenderer.render(descriptor), signature = signatureRenderer.render(descriptor)) + } + } +} diff --git a/kotlin-native/klib/src/main/kotlin/org/jetbrains/kotlin/cli/klib/DefaultDeclarationHeaderRenderer.kt b/kotlin-native/klib/src/main/kotlin/org/jetbrains/kotlin/cli/klib/DefaultDeclarationHeaderRenderer.kt new file mode 100644 index 00000000000..efd252eec42 --- /dev/null +++ b/kotlin-native/klib/src/main/kotlin/org/jetbrains/kotlin/cli/klib/DefaultDeclarationHeaderRenderer.kt @@ -0,0 +1,79 @@ +package org.jetbrains.kotlin.cli.klib + +import org.jetbrains.kotlin.builtins.StandardNames +import org.jetbrains.kotlin.descriptors.* +import org.jetbrains.kotlin.renderer.AnnotationArgumentsRenderingPolicy +import org.jetbrains.kotlin.renderer.DescriptorRenderer +import org.jetbrains.kotlin.renderer.DescriptorRendererModifier +import org.jetbrains.kotlin.renderer.OverrideRenderingPolicy + +object DefaultDeclarationHeaderRenderer : DeclarationHeaderRenderer { + override fun render(descriptor: DeclarationDescriptor): String = when (descriptor) { + is PackageFragmentDescriptor -> render(descriptor) + is ClassifierDescriptorWithTypeParameters -> render(descriptor) + is PropertyAccessorDescriptor -> render(descriptor) + is CallableMemberDescriptor -> render(descriptor) + else -> throw AssertionError("Unknown declaration descriptor type: $descriptor") + } + + private fun render(descriptor: PackageFragmentDescriptor): String { + val packageName = descriptor.fqName.let { if (it.isRoot) "" else it.asString() } + return "package $packageName" + } + + private fun render(descriptor: ClassifierDescriptorWithTypeParameters): String { + val renderer = when (descriptor.modality) { + // Don't render 'final' modality + Modality.FINAL -> Renderers.WITHOUT_MODALITY + else -> Renderers.DEFAULT + } + return renderer.render(descriptor) + } + + private fun render(descriptor: CallableMemberDescriptor): String { + val containingDeclaration = descriptor.containingDeclaration + val renderer = when { + // Don't render modality for non-override final methods and interface methods. + containingDeclaration is ClassDescriptor && containingDeclaration.kind == ClassKind.INTERFACE || + descriptor.modality == Modality.FINAL && descriptor.overriddenDescriptors.isEmpty() -> Renderers.WITHOUT_MODALITY + else -> Renderers.DEFAULT + } + return renderer.render(descriptor) + } + + private fun render(descriptor: PropertyAccessorDescriptor) = buildString { + descriptor.annotations.forEach { + append(Renderers.DEFAULT.renderAnnotation(it)).append(" ") + } + if (descriptor.visibility != DescriptorVisibilities.DEFAULT_VISIBILITY) { + append(descriptor.visibility.internalDisplayName).append(" ") + } + when (descriptor) { + is PropertyGetterDescriptor -> append("get") + is PropertySetterDescriptor -> append("set") + else -> throw AssertionError("Unknown accessor descriptor type: $descriptor") + } + } + + private object Renderers { + val DEFAULT = DescriptorRenderer.COMPACT_WITH_SHORT_TYPES.withOptions { + modifiers = DescriptorRendererModifier.ALL + overrideRenderingPolicy = OverrideRenderingPolicy.RENDER_OVERRIDE + annotationArgumentsRenderingPolicy = AnnotationArgumentsRenderingPolicy.UNLESS_EMPTY + excludedAnnotationClasses += StandardNames.FqNames.suppress + + classWithPrimaryConstructor = true + renderConstructorKeyword = true + includePropertyConstant = true + + unitReturnType = false + withDefinedIn = false + renderDefaultVisibility = false + secondaryConstructorsAsPrimary = false + } + + val WITHOUT_MODALITY = DEFAULT.withOptions { + modifiers -= DescriptorRendererModifier.MODALITY + } + } +} diff --git a/kotlin-native/klib/src/main/kotlin/org/jetbrains/kotlin/cli/klib/DefaultIdSignatureRenderer.kt b/kotlin-native/klib/src/main/kotlin/org/jetbrains/kotlin/cli/klib/DefaultIdSignatureRenderer.kt new file mode 100644 index 00000000000..33e38813c1c --- /dev/null +++ b/kotlin-native/klib/src/main/kotlin/org/jetbrains/kotlin/cli/klib/DefaultIdSignatureRenderer.kt @@ -0,0 +1,24 @@ +package org.jetbrains.kotlin.cli.klib + +import org.jetbrains.kotlin.backend.konan.serialization.KonanIdSignaturer +import org.jetbrains.kotlin.backend.konan.serialization.KonanManglerDesc +import org.jetbrains.kotlin.descriptors.ClassDescriptor +import org.jetbrains.kotlin.descriptors.ClassKind +import org.jetbrains.kotlin.descriptors.DeclarationDescriptor + +class DefaultIdSignatureRenderer(private val prefix: String? = null) : IdSignatureRenderer { + private val idSignaturer = KonanIdSignaturer(KonanManglerDesc) + + override fun render(descriptor: DeclarationDescriptor): String? { + val idSignature = if (descriptor is ClassDescriptor && descriptor.kind == ClassKind.ENUM_ENTRY) { + idSignaturer.composeEnumEntrySignature(descriptor) + } else { + idSignaturer.composeSignature(descriptor) + } ?: return null + + return if (prefix != null) + prefix + idSignature.render() + else + idSignature.render() + } +} diff --git a/kotlin-native/klib/src/main/kotlin/org/jetbrains/kotlin/cli/klib/IdSignatureRenderer.kt b/kotlin-native/klib/src/main/kotlin/org/jetbrains/kotlin/cli/klib/IdSignatureRenderer.kt new file mode 100644 index 00000000000..cbbae6b8617 --- /dev/null +++ b/kotlin-native/klib/src/main/kotlin/org/jetbrains/kotlin/cli/klib/IdSignatureRenderer.kt @@ -0,0 +1,13 @@ +package org.jetbrains.kotlin.cli.klib + +import org.jetbrains.kotlin.descriptors.DeclarationDescriptor + +interface IdSignatureRenderer { + fun render(descriptor: DeclarationDescriptor): String? + + companion object { + val NO_SIGNATURE = object : IdSignatureRenderer { + override fun render(descriptor: DeclarationDescriptor): String? = null + } + } +} diff --git a/kotlin-native/klib/src/main/kotlin/org/jetbrains/kotlin/cli/klib/SignaturePrinter.kt b/kotlin-native/klib/src/main/kotlin/org/jetbrains/kotlin/cli/klib/SignaturePrinter.kt new file mode 100644 index 00000000000..50dd51edc47 --- /dev/null +++ b/kotlin-native/klib/src/main/kotlin/org/jetbrains/kotlin/cli/klib/SignaturePrinter.kt @@ -0,0 +1,55 @@ +package org.jetbrains.kotlin.cli.klib + +import org.jetbrains.kotlin.backend.konan.descriptors.getPackageFragments +import org.jetbrains.kotlin.descriptors.* +import org.jetbrains.kotlin.descriptors.impl.DeclarationDescriptorVisitorEmptyBodies +import org.jetbrains.kotlin.utils.Printer + +class SignaturePrinter( + out: Appendable, + private val signatureRenderer: IdSignatureRenderer +) { + private val printer = Printer(out) + + fun print(module: ModuleDescriptor) { + module.accept(PrinterVisitor(), Unit) + } + + private fun Printer.printlnIfNotNull(line: String?) { + if (line != null) println(line) + } + + private inner class PrinterVisitor : DeclarationDescriptorVisitorEmptyBodies() { + override fun visitModuleDeclaration(descriptor: ModuleDescriptor, data: Unit) { + descriptor.getPackageFragments().forEach { it.accept(this, data) } + } + + override fun visitPackageFragmentDescriptor(descriptor: PackageFragmentDescriptor, data: Unit) { + descriptor.getMemberScope().getContributedDescriptors().forEach { it.accept(this, data) } + } + + override fun visitClassDescriptor(descriptor: ClassDescriptor, data: Unit) { + printer.printlnIfNotNull(signatureRenderer.render(descriptor)) + descriptor.constructors.forEach { it.accept(this, data) } + descriptor.unsubstitutedMemberScope.getContributedDescriptors().forEach { it.accept(this, data) } + } + + override fun visitFunctionDescriptor(descriptor: FunctionDescriptor, data: Unit) { + printer.printlnIfNotNull(signatureRenderer.render(descriptor)) + } + + override fun visitPropertyDescriptor(descriptor: PropertyDescriptor, data: Unit) { + printer.printlnIfNotNull(signatureRenderer.render(descriptor)) + descriptor.getter?.let { printer.printlnIfNotNull(signatureRenderer.render(it)) } + descriptor.setter?.let { printer.printlnIfNotNull(signatureRenderer.render(it)) } + } + + override fun visitConstructorDescriptor(descriptor: ConstructorDescriptor, data: Unit) { + printer.printlnIfNotNull(signatureRenderer.render(descriptor)) + } + + override fun visitTypeAliasDescriptor(descriptor: TypeAliasDescriptor, data: Unit) { + printer.printlnIfNotNull(signatureRenderer.render(descriptor)) + } + } +} diff --git a/kotlin-native/klib/src/main/kotlin/org/jetbrains/kotlin/cli/klib/main.kt b/kotlin-native/klib/src/main/kotlin/org/jetbrains/kotlin/cli/klib/main.kt new file mode 100644 index 00000000000..591799bc1a8 --- /dev/null +++ b/kotlin-native/klib/src/main/kotlin/org/jetbrains/kotlin/cli/klib/main.kt @@ -0,0 +1,240 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +package org.jetbrains.kotlin.cli.klib + +// TODO: Extract `library` package as a shared jar? +import org.jetbrains.kotlin.config.ApiVersion +import org.jetbrains.kotlin.config.LanguageVersion +import org.jetbrains.kotlin.config.LanguageVersionSettingsImpl +import org.jetbrains.kotlin.descriptors.impl.ModuleDescriptorImpl +import org.jetbrains.kotlin.konan.file.File +import org.jetbrains.kotlin.library.KLIB_FILE_EXTENSION_WITH_DOT +import org.jetbrains.kotlin.konan.target.Distribution +import org.jetbrains.kotlin.konan.target.PlatformManager +import org.jetbrains.kotlin.konan.util.DependencyProcessor +import org.jetbrains.kotlin.library.unpackZippedKonanLibraryTo +import org.jetbrains.kotlin.konan.util.KlibMetadataFactories +import org.jetbrains.kotlin.backend.common.serialization.metadata.DynamicTypeDeserializer +import org.jetbrains.kotlin.descriptors.konan.isNativeStdlib +import org.jetbrains.kotlin.builtins.konan.KonanBuiltIns +import org.jetbrains.kotlin.descriptors.ModuleDescriptor +import org.jetbrains.kotlin.descriptors.deserialization.PlatformDependentTypeTransformer +import org.jetbrains.kotlin.util.Logger +import org.jetbrains.kotlin.library.metadata.KlibMetadataProtoBuf +import org.jetbrains.kotlin.konan.library.KonanLibrary +import org.jetbrains.kotlin.konan.library.resolverByName +import org.jetbrains.kotlin.konan.util.KonanHomeProvider +import org.jetbrains.kotlin.library.metadata.parseModuleHeader +import org.jetbrains.kotlin.storage.LockBasedStorageManager +import kotlin.system.exitProcess + +internal val KlibFactories = KlibMetadataFactories(::KonanBuiltIns, DynamicTypeDeserializer, PlatformDependentTypeTransformer.None) + +fun printUsage() { + println("Usage: klib ") + println("where the commands are:") + println("\tinfo\tgeneral information about the library") + println("\tinstall\tinstall the library to the local repository") + println("\tcontents\tlist contents of the library") + println("\tsignatures\tlist of ID signatures in the library") + println("\tremove\tremove the library from the local repository") + println("and the options are:") + println("\t-repository \twork with the specified repository") + println("\t-target \tinspect specifics of the given target") + println("\t-print-signatures [true|false]\tprint ID signature for every declaration (only for \"contents\" command)") +} + +private fun parseArgs(args: Array): Map> { + val commandLine = mutableMapOf>() + for (index in args.indices step 2) { + val key = args[index] + if (key[0] != '-') { + throw IllegalArgumentException("Expected a flag with initial dash: $key") + } + if (index + 1 == args.size) { + throw IllegalArgumentException("Expected an value after $key") + } + val value = listOf(args[index + 1]) + commandLine[key]?.addAll(value) ?: commandLine.put(key, value.toMutableList()) + } + return commandLine +} + + +class Command(args: Array) { + init { + if (args.size < 2) { + printUsage() + exitProcess(0) + } + } + + val verb = args[0] + val library = args[1] + val options = parseArgs(args.drop(2).toTypedArray()) +} + +fun warn(text: String) { + println("warning: $text") +} + +fun error(text: String): Nothing { + kotlin.error("error: $text") +} + +object KlibToolLogger : Logger { + override fun warning(message: String) = org.jetbrains.kotlin.cli.klib.warn(message) + override fun error(message: String) = org.jetbrains.kotlin.cli.klib.warn(message) + override fun fatal(message: String) = org.jetbrains.kotlin.cli.klib.error(message) + override fun log(message: String) = println(message) +} + +val defaultRepository = File(DependencyProcessor.localKonanDir.resolve("klib").absolutePath) + +open class ModuleDeserializer(val library: ByteArray) { + protected val moduleHeader: KlibMetadataProtoBuf.Header + get() = parseModuleHeader(library) + + val moduleName: String + get() = moduleHeader.moduleName + + val packageFragmentNameList: List + get() = moduleHeader.packageFragmentNameList + +} + +class Library(val name: String, val requestedRepository: String?, val target: String) { + + val repository = requestedRepository?.File() ?: defaultRepository + fun info() { + val library = libraryInRepoOrCurrentDir(repository, name) + val headerAbiVersion = library.versions.abiVersion + val headerCompilerVersion = library.versions.compilerVersion + val headerLibraryVersion = library.versions.libraryVersion + val headerMetadataVersion = library.versions.metadataVersion + val headerIrVersion = library.versions.irVersion + val moduleName = ModuleDeserializer(library.moduleHeaderData).moduleName + + println("") + println("Resolved to: ${library.libraryName.File().absolutePath}") + println("Module name: $moduleName") + println("ABI version: $headerAbiVersion") + println("Compiler version: ${headerCompilerVersion}") + println("Library version: $headerLibraryVersion") + println("Metadata version: $headerMetadataVersion") + println("IR version: $headerIrVersion") + + if (library is KonanLibrary) { + val targets = library.targetList.joinToString(", ") + print("Available targets: $targets\n") + } + } + + fun install() { + if (!repository.exists) { + warn("Repository does not exist: $repository. Creating.") + repository.mkdirs() + } + + Library(File(name).name.removeSuffix(KLIB_FILE_EXTENSION_WITH_DOT), requestedRepository, target).remove(true) + + val library = libraryInCurrentDir(name) + val newLibDir = File(repository, library.libraryFile.name.removeSuffix(KLIB_FILE_EXTENSION_WITH_DOT)) + + library.libraryFile.unpackZippedKonanLibraryTo(newLibDir) + } + + fun remove(blind: Boolean = false) { + if (!repository.exists) error("Repository does not exist: $repository") + + val library = try { + val library = libraryInRepo(repository, name) + if (blind) warn("Removing The previously installed $name from $repository.") + library + + } catch (e: Throwable) { + if (!blind) println(e.message) + null + + } + library?.libraryFile?.deleteRecursively() + } + + fun contents(output: Appendable, printSignatures: Boolean) { + val module = loadModule() + val signatureRenderer = if (printSignatures) DefaultIdSignatureRenderer("// ID signature: ") else IdSignatureRenderer.NO_SIGNATURE + val printer = DeclarationPrinter(output, DefaultDeclarationHeaderRenderer, signatureRenderer) + + printer.print(module) + } + + fun signatures(output: Appendable) { + val module = loadModule() + val printer = SignaturePrinter(output, DefaultIdSignatureRenderer()) + + printer.print(module) + } + + private fun loadModule(): ModuleDescriptor { + val storageManager = LockBasedStorageManager("klib") + val library = libraryInRepoOrCurrentDir(repository, name) + val versionSpec = LanguageVersionSettingsImpl(currentLanguageVersion, currentApiVersion) + val module = KlibFactories.DefaultDeserializedDescriptorFactory.createDescriptorAndNewBuiltIns(library, versionSpec, storageManager, null) + + val defaultModules = mutableListOf() + if (!module.isNativeStdlib()) { + val resolver = resolverByName( + emptyList(), + distributionKlib = Distribution(KonanHomeProvider.determineKonanHome()).klib, + skipCurrentDir = true, + logger = KlibToolLogger + ) + resolver.defaultLinks(false, true, true).mapTo(defaultModules) { + KlibFactories.DefaultDeserializedDescriptorFactory.createDescriptor(it, versionSpec, storageManager, module.builtIns, null) + } + } + + (defaultModules + module).let { allModules -> + allModules.forEach { it.setDependencies(allModules) } + } + + return module + } +} + +val currentLanguageVersion = LanguageVersion.LATEST_STABLE +val currentApiVersion = ApiVersion.LATEST_STABLE + +fun libraryInRepo(repository: File, name: String) = + resolverByName(listOf(repository.absolutePath), skipCurrentDir = true, logger = KlibToolLogger).resolve(name) + +fun libraryInCurrentDir(name: String) = resolverByName(emptyList(), logger = KlibToolLogger).resolve(name) + +fun libraryInRepoOrCurrentDir(repository: File, name: String) = + resolverByName(listOf(repository.absolutePath), logger = KlibToolLogger).resolve(name) + +fun main(args: Array) { + val command = Command(args) + + val targetManager = PlatformManager(KonanHomeProvider.determineKonanHome()) + .targetManager(command.options["-target"]?.last()) + val target = targetManager.targetName + + val repository = command.options["-repository"]?.last() + val printSignatures = command.options["-print-signatures"]?.last()?.toBoolean() == true + + val library = Library(command.library, repository, target) + + when (command.verb) { + "contents" -> library.contents(System.out, printSignatures) + "signatures" -> library.signatures(System.out) + "info" -> library.info() + "install" -> library.install() + "remove" -> library.remove() + else -> error("Unknown command ${command.verb}.") + } +} + diff --git a/kotlin-native/klib/src/test/kotlin/org/jetbrains/kotlin/cli/klib/test/ContentsTest.kt b/kotlin-native/klib/src/test/kotlin/org/jetbrains/kotlin/cli/klib/test/ContentsTest.kt new file mode 100644 index 00000000000..64ea0c3633c --- /dev/null +++ b/kotlin-native/klib/src/test/kotlin/org/jetbrains/kotlin/cli/klib/test/ContentsTest.kt @@ -0,0 +1,363 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +package org.jetbrains.kotlin.cli.klib.test + +import com.intellij.openapi.util.text.StringUtil +import kotlin.test.* +import org.jetbrains.kotlin.cli.klib.* +import org.jetbrains.kotlin.konan.target.Distribution +import org.jetbrains.kotlin.konan.target.HostManager +import java.nio.file.Paths + +class ContentsTest { + + private fun testLibrary(name: String) = LIBRARY_DIRECTORY.resolve("$name.klib").toFile().absolutePath + + private fun klibContents(library: String, printOutput: Boolean = false, expected: () -> String) { + val output = StringBuilder() + val lib = Library(library, null, "host") + lib.contents(output, false) + if (printOutput) { + println(output.trim().toString()) + } + assertEquals( + StringUtil.convertLineSeparators(expected()), + StringUtil.convertLineSeparators(output.trim().toString()), + "klib contents test failed for library: $library" + ) + } + + @Test + fun `Stdlib content should be printed without exceptions`() { + val output = StringBuilder() + val distributionPath = System.getProperty("konan.home") + Library(Distribution(distributionPath).stdlib, null, "host").contents(output, false) + } + + @Test + fun topLevelFunctions() = klibContents(testLibrary("TopLevelFunctions")) { + """ + package { + annotation class A constructor() : Annotation + annotation class B constructor() : Annotation + class Foo constructor() + } + + package { + @A @B fun a() + fun f1(x: Foo) + fun f2(x: Foo, y: Foo): Int + inline fun i1(block: () -> Foo) + inline fun i2(noinline block: () -> Foo) + inline fun i3(crossinline block: () -> Foo) + fun i4(block: (Foo) -> Int) + fun i5(block: (Foo, Foo) -> Int) + fun i6(block: Foo.() -> Int) + fun i7(block: Foo.(Foo) -> Int) + fun t1(x: Foo) + fun t2(x: T) + fun t3(x: T, y: F) + inline fun t4(x: T) + fun t5(x: T) + fun Foo.e() + } + """.trimIndent() + } + + @Test + fun constructors() = klibContents(testLibrary("Constructors")) { + """ + package { + annotation class A constructor() : Annotation + class Bar @A constructor(x: Int) + class Baz private constructor(x: Int) + + class Foo constructor(x: Int) { + constructor() + constructor(x: Double) + constructor(x: Double, y: Int) + protected constructor(x: String) + @A constructor(x: Foo) + } + + class Qux protected constructor(x: Int) + + class Typed constructor(x: Int) { + constructor() + constructor(x: Double) + constructor(x: Double, y: Int) + protected constructor(x: String) + @A constructor(x: Foo) + } + + } + """.trimIndent() + } + + @Test + fun objects() = klibContents(testLibrary("Objects")) { + """ + package { + + object A { + fun a() + } + + class B constructor() { + + object C { + fun c() + } + + companion object { + fun b() + } + + } + + class D constructor() { + + companion object E { + fun e() + } + + } + + } + """.trimIndent() + } + + @Test + fun classes() = klibContents(testLibrary("Classes")) { + """ + package { + + class A constructor() { + val aVal: Int = 0 + var aVar: String + fun aFun() + + inner class B constructor() { + val bVal: Int = 0 + var bVar: String + fun bFun() + + inner class C constructor() { + val cVal: Int = 0 + var cVar: String + fun cFun() + } + + } + + class E constructor() { + val eVal: Int = 0 + var eVar: String + fun eFun() + } + + } + + data class F constructor(fVal: Int, fVar: String) { + val fVal: Int + var fVar: String + operator fun component1(): Int + operator fun component2(): String + fun copy(fVal: Int = ..., fVar: String = ...): F + override fun equals(other: Any?): Boolean + fun fFun() + override fun hashCode(): Int + override fun toString(): String + } + + class FinalImpl constructor() : OpenImpl { + override val iVal: Int = 0 + override var iVar: String + override fun iFun() + } + + interface Interface { + val iVal: Int + var iVar: String + fun iFun() + } + + open class OpenImpl constructor() : Interface { + override val iVal: Int = 0 + override var iVar: String + override fun iFun() + } + + } + """.trimIndent() + } + + @Test + fun methodModality() = klibContents(testLibrary("MethodModality")) { + """ + package { + + abstract class AbstractClass constructor() : Interface { + abstract fun abstractFun() + override fun interfaceFun() + } + + class FinalClass constructor() : OpenClass { + override fun openFun1() + final override fun openFun2() + } + + interface Interface { + fun interfaceFun() + } + + open class OpenClass constructor() : AbstractClass { + override fun abstractFun() + fun finalFun() + open fun openFun1() + open fun openFun2() + } + + } + """.trimIndent() + } + + @Test + fun functionModifiers() = klibContents(testLibrary("FunctionModifiers")) { + """ + package { + + class Foo constructor() { + fun f1() + infix fun f2(x: Int) + suspend fun f3() + tailrec fun f4() + fun f5(vararg x: Int) + operator fun plus(x: Int) + } + + } + """.trimIndent() + } + + @Test + // TODO: Support enum entry methods in serialization/deserialization. + fun enum() = klibContents(testLibrary("Enum")) { + """ + package { + + enum class E private constructor(x: Int = ...) : Enum { + enum entry A + enum entry B + enum entry C + val enumVal: Int = 0 + var enumVar: String + val x: Int + open fun enumFun(): Int + } + + } + """.trimIndent() + } + + @Test + // TODO: Support getter/setter annotations in serialization/deserialization. + fun accessors() = klibContents(testLibrary("Accessors")) { + """ + package custom.pkg { + annotation class A constructor() : Annotation + + class Foo constructor() { + @A val annotated: Int = 0 + var annotatedAccessors: Int + @A get + @A set + val annotatedGetter: Int = 0 + @A get + var annotatedSetter: Int + @A set + var privateSetter: Int + private set + protected val protectedSimple: Int = 0 + val simple: Int = 0 + } + + } + """.trimIndent() + } + + @Test + fun topLevelPropertiesCustomPackage() = klibContents(testLibrary("TopLevelPropertiesCustomPackage")) { + """ + package custom.pkg { + typealias MyTransformer = (String) -> Int + } + + package custom.pkg { + val v1: Int = 1 + val v2: String = "hello" + val v3: (String) -> Int + val v4: MyTransformer /* = (String) -> Int */ + } + """.trimIndent() + } + + @Test + fun topLevelPropertiesRootPackage() = klibContents(testLibrary("TopLevelPropertiesRootPackage")) { + """ + package { + typealias MyTransformer = (String) -> Int + } + + package { + val v1: Int = 1 + val v2: String = "hello" + val v3: (String) -> Int + val v4: MyTransformer /* = (String) -> Int */ + } + """.trimIndent() + } + + @Test + fun topLevelPropertiesWithClassesCustomPackage() = klibContents(testLibrary("TopLevelPropertiesWithClassesCustomPackage")) { + """ + package custom.pkg { + typealias MyTransformer = (String) -> Int + object Bar + class Foo constructor() + } + + package custom.pkg { + val v1: Int = 1 + val v2: String = "hello" + val v3: (String) -> Int + val v4: MyTransformer /* = (String) -> Int */ + } + """.trimIndent() + } + + @Test + fun topLevelPropertiesWithClassesRootPackage() = klibContents(testLibrary("TopLevelPropertiesWithClassesRootPackage")) { + """ + package { + typealias MyTransformer = (String) -> Int + object Bar + class Foo constructor() + } + + package { + val v1: Int = 1 + val v2: String = "hello" + val v3: (String) -> Int + val v4: MyTransformer /* = (String) -> Int */ + } + """.trimIndent() + } + + companion object { + val LIBRARY_DIRECTORY = Paths.get("build/konan/libs").resolve(HostManager.hostName) + } +} \ No newline at end of file diff --git a/kotlin-native/klib/src/test/testData/Accessors.kt b/kotlin-native/klib/src/test/testData/Accessors.kt new file mode 100644 index 00000000000..bcbbd1c33e2 --- /dev/null +++ b/kotlin-native/klib/src/test/testData/Accessors.kt @@ -0,0 +1,42 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package custom.pkg + +annotation class A + +class Foo { + val simple = 0 + + private val privateSimple = 0 + + protected val protectedSimple = 0 + + var privateSetter = 0 + private set + + @A val annotated = 0 + + val annotatedGetter = 0 + @A get + + var annotatedSetter = 0 + @A set + + var annotatedAccessors = 0 + @A set + @A get +} diff --git a/kotlin-native/klib/src/test/testData/Classes.kt b/kotlin-native/klib/src/test/testData/Classes.kt new file mode 100644 index 00000000000..9471b75ae02 --- /dev/null +++ b/kotlin-native/klib/src/test/testData/Classes.kt @@ -0,0 +1,68 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +class A { + fun aFun() {} + val aVal = 0 + var aVar = "" + + inner class B { + fun bFun() {} + val bVal = 0 + var bVar = "" + + inner class C { + fun cFun() {} + val cVal = 0 + var cVar = "" + } + + private inner class D { + fun dFun() {} + val dVal = 0 + var dVar = "" + } + } + + class E { + fun eFun() {} + val eVal = 0 + var eVar = "" + } + +} + +data class F(val fVal: Int, var fVar: String) { + fun fFun() {} +} + +interface Interface { + fun iFun() + val iVal: Int + var iVar: String +} + +open class OpenImpl: Interface { + override fun iFun() {} + override val iVal = 0 + override var iVar = "" +} + +class FinalImpl: OpenImpl() { + override fun iFun() {} + override val iVal = 0 + override var iVar = "" +} diff --git a/kotlin-native/klib/src/test/testData/Constructors.kt b/kotlin-native/klib/src/test/testData/Constructors.kt new file mode 100644 index 00000000000..939f517b697 --- /dev/null +++ b/kotlin-native/klib/src/test/testData/Constructors.kt @@ -0,0 +1,43 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +@file:Suppress("UNUSED_PARAMETER") + +annotation class A + +class Foo(x: Int) { + constructor(): this(0) + constructor(x: Double): this(x.toInt()) + constructor(x: Double, y: Int): this(y) + + private constructor(x: Long): this(0) + protected constructor(x: String): this(0) + @A constructor(x: Foo) : this(0) +} + +class Bar @A constructor(x: Int) +class Baz private constructor(x: Int) +class Qux protected constructor(x: Int) + +class Typed(x: Int) { + constructor(): this(0) + constructor(x: Double): this(x.toInt()) + constructor(x: Double, y: Int): this(y) + + private constructor(x: Long): this(0) + protected constructor(x: String): this(0) + @A constructor(x: Foo) : this(0) +} diff --git a/kotlin-native/klib/src/test/testData/Enum.kt b/kotlin-native/klib/src/test/testData/Enum.kt new file mode 100644 index 00000000000..76b9fbfe7e0 --- /dev/null +++ b/kotlin-native/klib/src/test/testData/Enum.kt @@ -0,0 +1,27 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +enum class E(val x: Int = 0) { + A, + B, + C(1) { + override fun enumFun() = 42 + }; + + open fun enumFun(): Int = 0 + val enumVal = 0 + var enumVar = "" +} \ No newline at end of file diff --git a/kotlin-native/klib/src/test/testData/FunctionModifiers.kt b/kotlin-native/klib/src/test/testData/FunctionModifiers.kt new file mode 100644 index 00000000000..d6df51571e8 --- /dev/null +++ b/kotlin-native/klib/src/test/testData/FunctionModifiers.kt @@ -0,0 +1,24 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +class Foo { + fun f1() {} + infix fun f2(x: Int) {} + suspend fun f3() {} + operator fun plus(x: Int) {} + tailrec fun f4() {} + fun f5(vararg x: Int) {} +} \ No newline at end of file diff --git a/kotlin-native/klib/src/test/testData/MethodModality.kt b/kotlin-native/klib/src/test/testData/MethodModality.kt new file mode 100644 index 00000000000..72fba5f867d --- /dev/null +++ b/kotlin-native/klib/src/test/testData/MethodModality.kt @@ -0,0 +1,36 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +interface Interface { + fun interfaceFun() +} + +abstract class AbstractClass: Interface { + override fun interfaceFun() {} + abstract fun abstractFun() +} + +open class OpenClass: AbstractClass() { + override fun abstractFun() {} + open fun openFun1() {} + open fun openFun2() {} + fun finalFun() {} +} + +class FinalClass: OpenClass() { + override fun openFun1() {} + final override fun openFun2() {} +} \ No newline at end of file diff --git a/kotlin-native/klib/src/test/testData/Objects.kt b/kotlin-native/klib/src/test/testData/Objects.kt new file mode 100644 index 00000000000..cebde7f171b --- /dev/null +++ b/kotlin-native/klib/src/test/testData/Objects.kt @@ -0,0 +1,35 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +object A { + fun a() {} +} + +class B { + companion object { + fun b() {} + } + + object C { + fun c() {} + } +} + +class D { + companion object E { + fun e() {} + } +} diff --git a/kotlin-native/klib/src/test/testData/TopLevelFunctions.kt b/kotlin-native/klib/src/test/testData/TopLevelFunctions.kt new file mode 100644 index 00000000000..0f05388ae10 --- /dev/null +++ b/kotlin-native/klib/src/test/testData/TopLevelFunctions.kt @@ -0,0 +1,49 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +@file:Suppress("UNUSED_PARAMETER") + +annotation class A +annotation class B + +class Foo + +fun f1(x: Foo): Unit {} +fun f2(x: Foo, y: Foo) = 0 + +// inline +inline fun i1(block: () -> Foo) {} +inline fun i2(noinline block: () -> Foo) {} +inline fun i3(crossinline block: () -> Foo) {} + +// callable args +fun i4(block: (Foo) -> Int) {} +fun i5(block: (Foo, Foo) -> Int) {} +fun i6(block: Foo.() -> Int) {} +fun i7(block: Foo.(Foo) -> Int) {} + +// type parameters +fun t1(x: Foo) {} +fun t2(x: T) {} +fun t3(x: T, y: F) {} +inline fun t4(x: T) {} +fun t5(x: T) {} + +// extension +fun Foo.e() {} + +// annotations +@A @B fun a() {} \ No newline at end of file diff --git a/kotlin-native/klib/src/test/testData/TopLevelPropertiesCustomPackage.kt b/kotlin-native/klib/src/test/testData/TopLevelPropertiesCustomPackage.kt new file mode 100644 index 00000000000..a31ce844488 --- /dev/null +++ b/kotlin-native/klib/src/test/testData/TopLevelPropertiesCustomPackage.kt @@ -0,0 +1,28 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +@file:Suppress("UNUSED_PARAMETER") + +package custom.pkg + +typealias MyTransformer = (String) -> Int + +// top-level properties +val v1 = 1 +val v2 = "hello" +val v3: (String) -> Int = { it.length } +val v4: MyTransformer = v3 + diff --git a/kotlin-native/klib/src/test/testData/TopLevelPropertiesRootPackage.kt b/kotlin-native/klib/src/test/testData/TopLevelPropertiesRootPackage.kt new file mode 100644 index 00000000000..1937b6b6aa1 --- /dev/null +++ b/kotlin-native/klib/src/test/testData/TopLevelPropertiesRootPackage.kt @@ -0,0 +1,26 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +@file:Suppress("UNUSED_PARAMETER") + +typealias MyTransformer = (String) -> Int + +// top-level properties +val v1 = 1 +val v2 = "hello" +val v3: (String) -> Int = { it.length } +val v4: MyTransformer = v3 + diff --git a/kotlin-native/klib/src/test/testData/TopLevelPropertiesWithClassesCustomPackage.kt b/kotlin-native/klib/src/test/testData/TopLevelPropertiesWithClassesCustomPackage.kt new file mode 100644 index 00000000000..49b1fc1c07c --- /dev/null +++ b/kotlin-native/klib/src/test/testData/TopLevelPropertiesWithClassesCustomPackage.kt @@ -0,0 +1,31 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +@file:Suppress("UNUSED_PARAMETER") + +package custom.pkg + +class Foo + +typealias MyTransformer = (String) -> Int + +// top-level properties +val v1 = 1 +val v2 = "hello" +val v3: (String) -> Int = { it.length } +val v4: MyTransformer = v3 + +object Bar diff --git a/kotlin-native/klib/src/test/testData/TopLevelPropertiesWithClassesRootPackage.kt b/kotlin-native/klib/src/test/testData/TopLevelPropertiesWithClassesRootPackage.kt new file mode 100644 index 00000000000..87e367adadb --- /dev/null +++ b/kotlin-native/klib/src/test/testData/TopLevelPropertiesWithClassesRootPackage.kt @@ -0,0 +1,29 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +@file:Suppress("UNUSED_PARAMETER") + +class Foo + +typealias MyTransformer = (String) -> Int + +// top-level properties +val v1 = 1 +val v2 = "hello" +val v3: (String) -> Int = { it.length } +val v4: MyTransformer = v3 + +object Bar diff --git a/kotlin-native/konan/konan.properties b/kotlin-native/konan/konan.properties new file mode 100644 index 00000000000..20741278b7a --- /dev/null +++ b/kotlin-native/konan/konan.properties @@ -0,0 +1,730 @@ +# +# Copyright 2010-2018 JetBrains s.r.o. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +# TODO: Do we need a $variable substitution mechanism here? +dependenciesUrl = https://download.jetbrains.com/kotlin/native + +# In order of preference: +dependencyProfiles = default alt + +# Don't check dependencies on a server. +# If true, dependency downloader will throw an exception if a dependency isn't found in $KONAN_DATA_DIR/dependencies +airplaneMode = false +# if true, ignores Xcode version check. +ignoreXcodeVersionCheck = false + +minimalXcodeVersion=11.0 + +downloadingAttempts = 10 +downloadingAttemptIntervalMs = 3000 +homeDependencyCache = .konan/cache + +# Appendix that is used for smaller version of LLVM distributions. +reducedLlvmAppendix = compact + +predefinedLlvmDistributions = \ + clang-llvm-8.0.0-linux-x86-64 \ + msys2-mingw-w64-x86_64-clang-llvm-lld-compiler_rt-8.0.1 \ + clang-llvm-apple-8.0.0-darwin-macos + +llvm.linux_x64.dev = clang-llvm-8.0.0-linux-x86-64 +llvm.linux_x64.user = clang-llvm-8.0.0-linux-x86-64 + +llvm.mingw_x64.dev = msys2-mingw-w64-x86_64-clang-llvm-lld-compiler_rt-8.0.1 +llvm.mingw_x64.user = msys2-mingw-w64-x86_64-clang-llvm-lld-compiler_rt-8.0.1 + +llvm.macos_x64.dev = clang-llvm-apple-8.0.0-darwin-macos +llvm.macos_x64.user = clang-llvm-apple-8.0.0-darwin-macos + +clangDebugFlags = -O0 +llvmVersion.linux_x64 = 8.0.0 +llvmVersion.mingw_x64 = 8.0.1 +llvmVersion.macos_x64 = 8.0.0 + +# Mac OS X. +# Can be an absolute path instead of predefined value. +llvmHome.macos_x64 = $llvm.macos_x64.dev +targetToolchain.macos_x64 = target-toolchain-xcode_12_0-macos_x64 +libffiDir.macos_x64 = libffi-3.2.1-3-darwin-macos +additionalToolsDir.macos_x64 = xcode-addon-xcode_12_0-macos_x64 + +arch.macos_x64 = x86_64 +targetSysRoot.macos_x64 = target-sysroot-xcode_12_0-macos_x64 + +clangFlags.macos_x64 = -cc1 -emit-obj -disable-llvm-passes -x ir +clangNooptFlags.macos_x64 = -O1 +clangOptFlags.macos_x64 = -O3 +clangDebugFlags.macos_x64 = -O0 +clangDynamicFlags.macos_x64 = + +linkerKonanFlags.macos_x64 = -lSystem -lc++ -lobjc -framework Foundation -sdk_version 10.15.6 +linkerOptimizationFlags.macos_x64 = -dead_strip +linkerNoDebugFlags.macos_x64 = -S +linkerDynamicFlags.macos_x64 = -dylib + +osVersionMinFlagLd.macos_x64 = -macosx_version_min +osVersionMinFlagClang.macos_x64 = -mmacosx-version-min +osVersionMin.macos_x64 = 10.11 +runtimeDefinitions.macos_x64 = KONAN_OSX=1 KONAN_MACOSX=1 KONAN_X64=1 KONAN_OBJC_INTEROP=1 \ + KONAN_CORE_SYMBOLICATION=1 KONAN_HAS_CXX11_EXCEPTION_FUNCTIONS=1 +dependencies.macos_x64 = \ + libffi-3.2.1-3-darwin-macos \ + lldb-3-macos + +target-sysroot-xcode_12_0-macos_x64.default = \ + remote:internal + +target-toolchain-xcode_12_0-macos_x64.default = \ + remote:internal + +xcode-addon-xcode_12_0-macos_x64.default = \ + remote:internal + + +# Apple's 32-bit iOS. +targetToolchain.macos_x64-ios_arm32 = target-toolchain-xcode_12_0-macos_x64 +dependencies.macos_x64-ios_arm32 = \ + libffi-3.2.1-3-darwin-macos + +target-sysroot-xcode_12_0-ios_arm32.default = \ + remote:internal + +arch.ios_arm32 = armv7 +# Shared with 64-bit version. +targetSysRoot.ios_arm32 = target-sysroot-xcode_12_0-ios_arm64 + +clangFlags.ios_arm32 = -cc1 -emit-obj -disable-llvm-optzns -x ir +clangNooptFlags.ios_arm32 = -O1 +clangOptFlags.ios_arm32 = -O3 +clangDebugFlags.ios_arm32 = -O0 +clangDynamicFlags.ios_arm32 = +linkerNoDebugFlags.ios_arm32 = -S +linkerDynamicFlags.ios_arm32 = -dylib +linkerKonanFlags.ios_arm32 = -lSystem -lc++ -lobjc -framework Foundation -sdk_version 14.0 +linkerOptimizationFlags.ios_arm32 = -dead_strip +osVersionMinFlagLd.ios_arm32 = -iphoneos_version_min +osVersionMinFlagClang.ios_arm32 = -miphoneos-version-min +osVersionMin.ios_arm32 = 9.0 +# Regarding KONAN_NO_64BIT_ATOMIC: +# While not 100% correct here, using atomic ops on iOS armv7 requires 8 byte alignment, +# and general ABI requires 4-byte alignment on 64-bit long fields as mentioned in +# https://developer.apple.com/library/archive/documentation/Xcode/Conceptual/iPhoneOSABIReference/Articles/ARMv6FunctionCallingConventions.html#//apple_ref/doc/uid/TP40009021-SW1 +# See https://github.com/ktorio/ktor/issues/941 for the context. +runtimeDefinitions.ios_arm32 = KONAN_OBJC_INTEROP=1 KONAN_IOS KONAN_ARM32=1 \ + KONAN_HAS_CXX11_EXCEPTION_FUNCTIONS=1 KONAN_REPORT_BACKTRACE_TO_IOS_CRASH_LOG=1 MACHSIZE=32 \ + KONAN_NO_64BIT_ATOMIC=1 KONAN_NO_UNALIGNED_ACCESS=1 + +# Apple's 64-bit iOS. +targetToolchain.macos_x64-ios_arm64 = target-toolchain-xcode_12_0-macos_x64 +dependencies.macos_x64-ios_arm64 = \ + libffi-3.2.1-3-darwin-macos + +target-sysroot-xcode_12_0-ios_arm64.default = \ + remote:internal + +arch.ios_arm64 = arm64 +targetSysRoot.ios_arm64 = target-sysroot-xcode_12_0-ios_arm64 + +clangFlags.ios_arm64 = -cc1 -emit-obj -disable-llvm-passes -x ir +clangNooptFlags.ios_arm64 = -O1 +clangOptFlags.ios_arm64 = -O3 +# We force LLVM to use SelectionDAG because fast isel may miscompile sign extension. +# Related: +# https://github.com/JetBrains/kotlin-native/issues/3290 +clangDebugFlags.ios_arm64 = -O0 -mllvm -fast-isel=false -mllvm -global-isel=false +clangDynamicFlags.ios_arm64 = + +linkerNoDebugFlags.ios_arm64 = -S +linkerDynamicFlags.ios_arm64 = -dylib +linkerKonanFlags.ios_arm64 = -lSystem -lc++ -lobjc -framework Foundation -sdk_version 14.0 +linkerOptimizationFlags.ios_arm64 = -dead_strip +osVersionMinFlagLd.ios_arm64 = -iphoneos_version_min +osVersionMinFlagClang.ios_arm64 = -miphoneos-version-min +osVersionMin.ios_arm64 = 9.0 +runtimeDefinitions.ios_arm64 = KONAN_OBJC_INTEROP=1 KONAN_IOS=1 KONAN_ARM64=1 \ + KONAN_HAS_CXX11_EXCEPTION_FUNCTIONS=1 KONAN_REPORT_BACKTRACE_TO_IOS_CRASH_LOG=1 MACHSIZE=64 + +# Apple's iOS simulator. +targetToolchain.macos_x64-ios_x64 = target-toolchain-xcode_12_0-macos_x64 +dependencies.macos_x64-ios_x64 = \ + libffi-3.2.1-3-darwin-macos + +target-sysroot-xcode_12_0-ios_x64.default = \ + remote:internal + +arch.ios_x64 = x86_64 +targetSysRoot.ios_x64 = target-sysroot-xcode_12_0-ios_x64 + +clangFlags.ios_x64 = -cc1 -emit-obj -disable-llvm-passes -x ir +clangNooptFlags.ios_x64 = -O1 +clangOptFlags.ios_x64 = -O3 +clangDebugFlags.ios_x64 = -O0 +clangDynamicFlags.ios_x64 = + +linkerKonanFlags.ios_x64 = -lSystem -lc++ -lobjc -framework Foundation -sdk_version 14.0 +linkerOptimizationFlags.ios_x64 = -dead_strip +linkerNoDebugFlags.ios_x64 = -S +linkerDynamicFlags.ios_x64 = -dylib +osVersionMinFlagLd.ios_x64 = -ios_simulator_version_min +osVersionMinFlagClang.ios_x64 = -mios-simulator-version-min +osVersionMin.ios_x64 = 9.0 +runtimeDefinitions.ios_x64 = KONAN_OBJC_INTEROP=1 KONAN_IOS=1 KONAN_X64=1 \ + KONAN_CORE_SYMBOLICATION=1 KONAN_HAS_CXX11_EXCEPTION_FUNCTIONS=1 + +# Apple's tvOS simulator. +targetToolchain.macos_x64-tvos_x64 = target-toolchain-xcode_12_0-macos_x64 +dependencies.macos_x64-tvos_x64 = \ + libffi-3.2.1-3-darwin-macos + +target-sysroot-xcode_12_0-tvos_x64.default = \ + remote:internal + +arch.tvos_x64 = x86_64 +targetSysRoot.tvos_x64 = target-sysroot-xcode_12_0-tvos_x64 + +clangFlags.tvos_x64 = -cc1 -emit-obj -disable-llvm-passes -x ir +clangNooptFlags.tvos_x64 = -O1 +clangOptFlags.tvos_x64 = -O3 +clangDebugFlags.tvos_x64 = -O0 +clangDynamicFlags.tvos_x64 = + +linkerKonanFlags.tvos_x64 = -lSystem -lc++ -lobjc -framework Foundation -sdk_version 14.0 +linkerOptimizationFlags.tvos_x64 = -dead_strip +linkerNoDebugFlags.tvos_x64 = -S +linkerDynamicFlags.tvos_x64 = -dylib +osVersionMinFlagLd.tvos_x64 = -tvos_simulator_version_min +osVersionMinFlagClang.tvos_x64 = -mtvos-simulator-version-min +osVersionMin.tvos_x64 = 9.0 +runtimeDefinitions.tvos_x64 = KONAN_OBJC_INTEROP=1 KONAN_TVOS=1 KONAN_X64=1 \ + KONAN_CORE_SYMBOLICATION=1 KONAN_HAS_CXX11_EXCEPTION_FUNCTIONS=1 + +# Apple's 64-bit tvOS. +targetToolchain.macos_x64-tvos_arm64 = target-toolchain-xcode_12_0-macos_x64 +dependencies.macos_x64-tvos_arm64 = \ + libffi-3.2.1-3-darwin-macos + +target-sysroot-xcode_12_0-tvos_arm64.default = \ + remote:internal + +arch.tvos_arm64 = arm64 +targetSysRoot.tvos_arm64 = target-sysroot-xcode_12_0-tvos_arm64 + +clangFlags.tvos_arm64 = -cc1 -emit-obj -disable-llvm-passes -x ir +clangNooptFlags.tvos_arm64 = -O1 +clangOptFlags.tvos_arm64 = -O3 +clangDebugFlags.tvos_arm64 = -O0 -mllvm -fast-isel=false -mllvm -global-isel=false +clangDynamicFlags.tvos_arm64 = + +linkerNoDebugFlags.tvos_arm64 = -S +linkerDynamicFlags.tvos_arm64 = -dylib +linkerKonanFlags.tvos_arm64 = -lSystem -lc++ -lobjc -framework Foundation -sdk_version 14.0 +linkerOptimizationFlags.tvos_arm64 = -dead_strip +osVersionMinFlagLd.tvos_arm64 = -tvos_version_min +osVersionMinFlagClang.tvos_arm64 = -mtvos-version-min +osVersionMin.tvos_arm64 = 9.0 +runtimeDefinitions.tvos_arm64 = KONAN_OBJC_INTEROP=1 KONAN_TVOS=1 KONAN_ARM64=1 \ + KONAN_HAS_CXX11_EXCEPTION_FUNCTIONS=1 KONAN_REPORT_BACKTRACE_TO_IOS_CRASH_LOG=1 MACHSIZE=64 + +# watchOS armv7k +targetToolchain.macos_x64-watchos_arm32 = target-toolchain-xcode_12_0-macos_x64 +dependencies.macos_x64-watchos_arm32 = \ + libffi-3.2.1-3-darwin-macos + +target-sysroot-xcode_12_0-watchos_arm32.default = \ + remote:internal + +arch.watchos_arm32 = armv7k +targetSysRoot.watchos_arm32 = target-sysroot-xcode_12_0-watchos_arm32 + +clangFlags.watchos_arm32 = -cc1 -emit-obj -disable-llvm-passes -x ir +clangNooptFlags.watchos_arm32 = -O1 +clangOptFlags.watchos_arm32 = -O3 +clangDebugFlags.watchos_arm32 = -O0 +clangDynamicFlags.watchos_arm32 = + +linkerKonanFlags.watchos_arm32 = -lSystem -lc++ -lobjc -framework Foundation -sdk_version 7.0 +linkerOptimizationFlags.watchos_arm32 = -dead_strip +linkerNoDebugFlags.watchos_arm32 = -S +linkerDynamicFlags.watchos_arm32 = -dylib +osVersionMinFlagLd.watchos_arm32 = -watchos_version_min +osVersionMinFlagClang.watchos_arm32 = -mwatchos-version-min +osVersionMin.watchos_arm32 = 5.0 +# Regarding KONAN_NO_64BIT_ATOMIC=1: see explanation for ios_arm32 above. +runtimeDefinitions.watchos_arm32 = KONAN_OBJC_INTEROP=1 KONAN_WATCHOS KONAN_ARM32=1 \ + KONAN_HAS_CXX11_EXCEPTION_FUNCTIONS=1 KONAN_REPORT_BACKTRACE_TO_IOS_CRASH_LOG=1 \ + MACHSIZE=32 KONAN_NO_64BIT_ATOMIC=1 KONAN_NO_UNALIGNED_ACCESS=1 + +# watchOS arm64_32 +targetToolchain.macos_x64-watchos_arm64 = target-toolchain-xcode_12_0-macos_x64 +dependencies.macos_x64-watchos_arm64 = \ + libffi-3.2.1-3-darwin-macos + +target-sysroot-xcode_12_0-watchos_arm64.default = \ + remote:internal + +arch.watchos_arm64 = arm64_32 +targetSysRoot.watchos_arm64 = target-sysroot-xcode_12_0-watchos_arm32 + +clangFlags.watchos_arm64 = -cc1 -emit-obj -disable-llvm-passes -x ir -mllvm -aarch64-watch-bitcode-compatibility \ + -mllvm -arm-bitcode-compatibility -mllvm -fast-isel=false -mllvm -global-isel=false +clangNooptFlags.watchos_arm64 = -O1 +clangOptFlags.watchos_arm64 = -O3 +clangDebugFlags.watchos_arm64 = -O0 +clangDynamicFlags.watchos_arm64 = + +linkerKonanFlags.watchos_arm64 = -lSystem -lc++ -lobjc -framework Foundation -sdk_version 7.0 +linkerOptimizationFlags.watchos_arm64 = -dead_strip +linkerNoDebugFlags.watchos_arm64 = -S +linkerDynamicFlags.watchos_arm64 = -dylib +osVersionMinFlagLd.watchos_arm64 = -watchos_version_min +osVersionMinFlagClang.watchos_arm64 = -mwatchos-version-min +osVersionMin.watchos_arm64 = 5.0 +# Regarding KONAN_NO_64BIT_ATOMIC=1: see explanation for ios_arm32 above. +runtimeDefinitions.watchos_arm64 = KONAN_OBJC_INTEROP=1 KONAN_WATCHOS KONAN_ARM32=1 \ + KONAN_HAS_CXX11_EXCEPTION_FUNCTIONS=1 KONAN_REPORT_BACKTRACE_TO_IOS_CRASH_LOG=1 \ + MACHSIZE=32 KONAN_NO_64BIT_ATOMIC=1 KONAN_NO_UNALIGNED_ACCESS=1 + +# Apple's watchOS i386 simulator. +targetToolchain.macos_x64-watchos_x86 = target-toolchain-xcode_12_0-macos_x64 +dependencies.macos_x64-watchos_x86 = \ + libffi-3.2.1-3-darwin-macos + +target-sysroot-xcode_12_0-watchos_x86.default = \ + remote:internal + +arch.watchos_x86 = i386 +targetSysRoot.watchos_x86 = target-sysroot-xcode_12_0-watchos_x86 + +# -target-cpu pentium4 makes sure that cogenerator knows which CPU flavour to emit code for. +# Can be seen on optimized build and FP tests, where value is passed on stack +# by Kotlin and taken from SSE registers by C code. +# TODO: once this information is available in function attributes, we can remove this flag. +clangFlags.watchos_x86 = -cc1 -emit-obj -disable-llvm-passes -x ir -target-cpu pentium4 +clangNooptFlags.watchos_x86 = -O1 +clangOptFlags.watchos_x86 = -O3 +clangDebugFlags.watchos_x86 = -O0 +clangDynamicFlags.watchos_x86 = + +linkerKonanFlags.watchos_x86 = -lSystem -lc++ -lobjc -framework Foundation -sdk_version 7.0 +linkerOptimizationFlags.watchos_x86 = -dead_strip +linkerNoDebugFlags.watchos_x86 = -S +linkerDynamicFlags.watchos_x86 = -dylib +osVersionMinFlagLd.watchos_x86 = -watchos_simulator_version_min +osVersionMinFlagClang.watchos_x86 = -mwatchos-simulator-version-min +osVersionMin.watchos_x86 = 5.0 +runtimeDefinitions.watchos_x86 = KONAN_OBJC_INTEROP=1 KONAN_WATCHOS=1 KONAN_NO_64BIT_ATOMIC=1 \ + KONAN_X86=1 KONAN_CORE_SYMBOLICATION=1 KONAN_HAS_CXX11_EXCEPTION_FUNCTIONS=1 + +# Linux x86-64. +llvmHome.linux_x64 = $llvm.linux_x64.dev +libffiDir.linux_x64 = libffi-3.2.1-2-linux-x86-64 + +gccToolchain.linux_x64 = target-gcc-toolchain-3-linux-x86-64 +targetToolchain.linux_x64 = target-gcc-toolchain-3-linux-x86-64/x86_64-unknown-linux-gnu +dependencies.linux_x64 = \ + target-gcc-toolchain-3-linux-x86-64 \ + libffi-3.2.1-2-linux-x86-64 \ + lldb-3-linux + +gccToolchain.mingw_x64 = target-gcc-toolchain-3-linux-x86-64 +targetToolchain.mingw_x64-linux_x64 = msys2-mingw-w64-x86_64-clang-llvm-lld-compiler_rt-8.0.1 +dependencies.mingw_x64-linux_x64 = \ + libffi-3.2.1-mingw-w64-x86-64 \ + target-gcc-toolchain-3-linux-x86-64 + +gccToolchain.macos_x64 = target-gcc-toolchain-3-linux-x86-64 +targetToolchain.macos_x64-linux_x64 = $llvmHome.macos_x64 +dependencies.macos_x64-linux_x64 = \ + libffi-3.2.1-3-darwin-macos \ + target-gcc-toolchain-3-linux-x86-64 + +quadruple.linux_x64 = x86_64-unknown-linux-gnu +targetSysRoot.linux_x64 = target-gcc-toolchain-3-linux-x86-64/x86_64-unknown-linux-gnu/sysroot +# targetSysroot-relative. +libGcc.linux_x64 = ../../lib/gcc/x86_64-unknown-linux-gnu/4.8.5 +clangFlags.linux_x64 = -cc1 -target-cpu x86-64 -emit-obj -disable-llvm-optzns -x ir +clangNooptFlags.linux_x64 = -O1 +clangOptFlags.linux_x64 = -O3 -ffunction-sections +clangDebugFlags.linux_x64 = -O0 +clangDynamicFlags.linux_x64 = -mrelocation-model pic +linkerKonanFlags.linux_x64 = -Bstatic -lstdc++ -Bdynamic -ldl -lm -lpthread \ + --defsym __cxa_demangle=Konan_cxa_demangle --no-threads +linkerOptimizationFlags.linux_x64 = --gc-sections +linkerNoDebugFlags.linux_x64 = -S +linkerDynamicFlags.linux_x64 = -shared +dynamicLinker.linux_x64 = /lib64/ld-linux-x86-64.so.2 +# targetSysRoot relative +abiSpecificLibraries.linux_x64 = ../lib64 lib64 usr/lib64 +runtimeDefinitions.linux_x64 = USE_GCC_UNWIND=1 KONAN_LINUX=1 KONAN_X64=1 \ + USE_ELF_SYMBOLS=1 ELFSIZE=64 KONAN_HAS_CXX11_EXCEPTION_FUNCTIONS=1 + +# Raspberry Pi +targetToolchain.linux_x64-linux_arm32_hfp = target-gcc-toolchain-3-linux-x86-64/x86_64-unknown-linux-gnu +targetToolchain.mingw_x64-linux_arm32_hfp = msys2-mingw-w64-x86_64-clang-llvm-lld-compiler_rt-8.0.1 +targetToolchain.macos_x64-linux_arm32_hfp = $llvmHome.macos_x64 +dependencies.linux_x64-linux_arm32_hfp = \ + target-gcc-toolchain-3-linux-x86-64 \ + target-sysroot-2-raspberrypi \ + libffi-3.2.1-2-linux-x86-64 +dependencies.mingw_x64-linux_arm32_hfp = \ + libffi-3.2.1-mingw-w64-x86-64 \ + target-gcc-toolchain-3-linux-x86-64 \ + target-sysroot-2-raspberrypi +dependencies.macos_x64-linux_arm32_hfp = \ + libffi-3.2.1-3-darwin-macos \ + target-gcc-toolchain-3-linux-x86-64 \ + target-sysroot-2-raspberrypi + +quadruple.linux_arm32_hfp = armv6-unknown-linux-gnueabihf +linkerNoDebugFlags.linux_arm32_hfp = -S +linkerDynamicFlags.linux_arm32_hfp = -shared +linkerOptimizationFlags.linux_arm32_hfp = --gc-sections +targetSysRoot.linux_arm32_hfp = target-sysroot-2-raspberrypi +# We could reuse host toolchain here. +linkerKonanFlags.linux_arm32_hfp = -Bstatic -lstdc++ -Bdynamic -ldl -lm -lpthread \ + --defsym __cxa_demangle=Konan_cxa_demangle --no-threads +# targetSysroot-relative. +libGcc.linux_arm32_hfp = lib/gcc/arm-linux-gnueabihf/4.8.3 +clangFlags.linux_arm32_hfp = -cc1 -target-cpu arm1136jf-s -mfloat-abi hard -emit-obj -disable-llvm-optzns -x ir +clangNooptFlags.linux_arm32_hfp = -O1 +clangOptFlags.linux_arm32_hfp = -O3 -ffunction-sections +clangDebugFlags.linux_arm32_hfp = -O0 +clangDynamicFlags.linux_arm32_hfp = -mrelocation-model pic +dynamicLinker.linux_arm32_hfp = /lib/ld-linux-armhf.so.3 +# targetSysRoot relative +abiSpecificLibraries.linux_arm32_hfp = \ + ../lib/arm-linux-gnueabihf \ + lib/arm-linux-gnueabihf \ + usr/lib/arm-linux-gnueabihf +runtimeDefinitions.linux_arm32_hfp = USE_GCC_UNWIND=1 KONAN_LINUX=1 \ + KONAN_ARM32=1 USE_ELF_SYMBOLS=1 ELFSIZE=32 KONAN_NO_UNALIGNED_ACCESS=1 + +# Linux arm64 +targetToolchain.linux_x64-linux_arm64 = target-gcc-toolchain-3-linux-x86-64/x86_64-unknown-linux-gnu +targetToolchain.mingw_x64-linux_arm64 = msys2-mingw-w64-x86_64-clang-llvm-lld-compiler_rt-8.0.1 +targetToolchain.macos_x64-linux_arm64 = $llvmHome.macos_x64 +dependencies.linux_x64-linux_arm64 = \ + target-gcc-toolchain-3-linux-x86-64 \ + target-sysroot-1-linux-glibc-arm64 \ + libffi-3.2.1-2-linux-x86-64 +dependencies.mingw_x64-linux_arm64 = \ + libffi-3.2.1-mingw-w64-x86-64 \ + target-gcc-toolchain-3-linux-x86-64 \ + target-sysroot-1-linux-glibc-arm64 +dependencies.macos_x64-linux_arm64 = \ + libffi-3.2.1-3-darwin-macos \ + target-gcc-toolchain-3-linux-x86-64 \ + target-sysroot-1-linux-glibc-arm64 + +quadruple.linux_arm64 = aarch64-unknown-linux-gnu +linkerNoDebugFlags.linux_arm64 = -S +linkerDynamicFlags.linux_arm64 = -shared +linkerOptimizationFlags.linux_arm64 = --gc-sections +# From https://releases.linaro.org/components/toolchain/binaries/latest-7/aarch64-linux-gnu/. +targetSysRoot.linux_arm64 = target-sysroot-1-linux-glibc-arm64 +# We could reuse host toolchain here. +linkerKonanFlags.linux_arm64 = -Bstatic -lstdc++ -Bdynamic -ldl -lm -lpthread \ + --defsym __cxa_demangle=Konan_cxa_demangle --no-threads +# targetSysroot-relative. +libGcc.linux_arm64 = usr/lib +clangFlags.linux_arm64 = -cc1 -target-cpu cortex-a57 -emit-obj -disable-llvm-optzns -x ir +clangNooptFlags.linux_arm64 = -O1 +clangOptFlags.linux_arm64 = -O3 -ffunction-sections +clangDebugFlags.linux_arm64 = -O0 +clangDynamicFlags.linux_arm64 = -mrelocation-model pic +dynamicLinker.linux_arm64 = /lib/ld-linux-aarch64.so.1 +# targetSysRoot relative +abiSpecificLibraries.linux_arm64 = \ + lib \ + usr/lib +runtimeDefinitions.linux_arm64 = USE_GCC_UNWIND=1 KONAN_LINUX=1 KONAN_ARM64=1 \ + USE_ELF_SYMBOLS=1 ELFSIZE=64 + +# MIPS +targetToolchain.linux_x64-linux_mips32 = target-gcc-toolchain-2-linux-mips/x86_64-unknown-linux-gnu +dependencies.linux_x64-linux_mips32 = \ + target-gcc-toolchain-2-linux-mips \ + target-gcc-toolchain-3-linux-x86-64 \ + target-sysroot-2-mips \ + libffi-3.2.1-2-linux-x86-64 + +quadruple.linux_mips32 = mips-unknown-linux-gnu +linkerOptimizationFlags.linux_mips32 = --gc-sections +linkerDynamicFlags.linux_mips32 = -shared +targetSysRoot.linux_mips32 = target-sysroot-2-mips +# We could reuse host toolchain here. +linkerKonanFlags.linux_mips32 = -Bstatic -lstdc++ -Bdynamic -ldl -lm -lpthread \ + --defsym __cxa_demangle=Konan_cxa_demangle -z notext +# targetSysroot-relative. +libGcc.linux_mips32 = lib/gcc/mips-unknown-linux-gnu/4.9.4 +clangFlags.linux_mips32 = -cc1 -emit-obj -disable-llvm-optzns -x ir -target-cpu mips32r2 +clangNooptFlags.linux_mips32 = -O1 +clangOptFlags.linux_mips32 = -O3 -ffunction-sections +clangDebugFlags.linux_mips32 = -O0 +clangDynamicFlags.linux_mips32 = -mrelocation-model pic +dynamicLinker.linux_mips32 = /lib/ld.so.1 +# targetSysRoot relative +abiSpecificLibraries.linux_mips32 = +# TODO: reconsider KONAN_NO_64BIT_ATOMIC, once target MIPS can do proper 64-bit load/store/CAS. +runtimeDefinitions.linux_mips32 = USE_GCC_UNWIND=1 KONAN_LINUX=1 KONAN_MIPS32=1 \ + USE_ELF_SYMBOLS=1 ELFSIZE=32 KONAN_NO_64BIT_ATOMIC=1 KONAN_NO_UNALIGNED_ACCESS=1 + +# MIPSel +targetToolchain.linux_x64-linux_mipsel32 = target-gcc-toolchain-2-linux-mips/x86_64-unknown-linux-gnu +dependencies.linux_x64-linux_mipsel32 = \ + target-gcc-toolchain-2-linux-mips \ + target-gcc-toolchain-3-linux-x86-64 \ + target-sysroot-2-mipsel \ + libffi-3.2.1-2-linux-x86-64 +quadruple.linux_mipsel32 = mipsel-unknown-linux-gnu +linkerOptimizationFlags.linux_mipsel32 = --gc-sections +linkerDynamicFlags.linux_mipsel32 = -shared +targetSysRoot.linux_mipsel32 = target-sysroot-2-mipsel +# We could reuse host toolchain here. +linkerKonanFlags.linux_mipsel32 = -Bstatic -lstdc++ -Bdynamic -ldl -lm -lpthread \ + --defsym __cxa_demangle=Konan_cxa_demangle -z notext +# targetSysroot-relative. +libGcc.linux_mipsel32 = lib/gcc/mipsel-unknown-linux-gnu/4.9.4 +clangFlags.linux_mipsel32 = -cc1 -emit-obj -disable-llvm-optzns -x ir -target-cpu mips32r2 +clangNooptFlags.linux_mipsel32 = -O1 +clangOptFlags.linux_mipsel32 = -O3 -ffunction-sections +clangDebugFlags.linux_mipsel32 = -O0 +clangDynamicFlags.linux_mipsel32 = -mrelocation-model pic +dynamicLinker.linux_mipsel32 = /lib/ld.so.1 +# targetSysRoot relative +abiSpecificLibraries.linux_mipsel32 = +# TODO: reconsider KONAN_NO_64BIT_ATOMIC, once target MIPS can do proper 64-bit load/store/CAS. +runtimeDefinitions.linux_mipsel32 = USE_GCC_UNWIND=1 KONAN_LINUX=1 \ + KONAN_MIPSEL32=1 USE_ELF_SYMBOLS=1 ELFSIZE=32 KONAN_NO_64BIT_ATOMIC=1 KONAN_NO_UNALIGNED_ACCESS=1 + +# Android ARM32, based on NDK for android-21. +targetToolchain.macos_x64-android_arm32 = target-toolchain-2-osx-android_ndk +dependencies.macos_x64-android_arm32 = \ + target-sysroot-1-android_ndk \ + target-toolchain-2-osx-android_ndk \ + libffi-3.2.1-3-darwin-macos +targetToolchain.linux_x64-android_arm32 = target-toolchain-2-linux-android_ndk +dependencies.linux_x64-android_arm32 = \ + target-sysroot-1-android_ndk \ + target-toolchain-2-linux-android_ndk \ + libffi-3.2.1-2-linux-x86-64 +targetToolchain.mingw_x64-android_arm32 = target-toolchain-2-windows-android_ndk +dependencies.mingw_x64-android_arm32 = \ + target-sysroot-1-android_ndk \ + target-toolchain-2-windows-android_ndk \ + libffi-3.2.1-mingw-w64-x86-64 + +quadruple.android_arm32 = arm-linux-androideabi +clangFlags.android_arm32 = -cc1 -target-cpu arm7tdmi -emit-obj -disable-llvm-optzns -x ir -femulated-tls -mrelocation-model pic +clangOptFlags.android_arm32 = -O3 -ffunction-sections +linkerNoDebugFlags.android_arm32 = -Wl,-S +clangNooptFlags.android_arm32 = -O1 +targetSysRoot.android_arm32 = target-sysroot-1-android_ndk +linkerKonanFlags.android_arm32 = -lm -lc++_static -lc++abi -landroid -llog -latomic +runtimeDefinitions.android_arm32 = __ANDROID__ USE_GCC_UNWIND=1 USE_ELF_SYMBOLS=1 ELFSIZE=32 \ + KONAN_ANDROID=1 KONAN_ARM32=1 KONAN_NO_UNALIGNED_ACCESS=1 + +# Android ARM64, based on NDK. +targetToolchain.macos_x64-android_arm64 = target-toolchain-2-osx-android_ndk +dependencies.macos_x64-android_arm64 = \ + target-sysroot-1-android_ndk \ + target-toolchain-2-osx-android_ndk \ + libffi-3.2.1-3-darwin-macos +targetToolchain.linux_x64-android_arm64 = target-toolchain-2-linux-android_ndk +dependencies.linux_x64-android_arm64 = \ + target-sysroot-1-android_ndk \ + target-toolchain-2-linux-android_ndk \ + libffi-3.2.1-2-linux-x86-64 +targetToolchain.mingw_x64-android_arm64 = target-toolchain-2-windows-android_ndk +dependencies.mingw_x64-android_arm64 = \ + target-sysroot-1-android_ndk \ + target-toolchain-2-windows-android_ndk \ + libffi-3.2.1-mingw-w64-x86-64 + +quadruple.android_arm64 = aarch64-linux-android +clangFlags.android_arm64 = -cc1 -target-cpu cortex-a57 -emit-obj -disable-llvm-passes -x ir -femulated-tls -mrelocation-model pic +clangOptFlags.android_arm64 = -O3 -ffunction-sections +clangNooptFlags.android_arm64 = -O1 +targetSysRoot.android_arm64 = target-sysroot-1-android_ndk +linkerKonanFlags.android_arm64 = -lm -lc++_static -lc++abi -landroid -llog -latomic +linkerNoDebugFlags.android_arm64 = -Wl,-S +runtimeDefinitions.android_arm64 = __ANDROID__ USE_GCC_UNWIND=1 USE_ELF_SYMBOLS=1 \ + ELFSIZE=64 KONAN_ANDROID=1 KONAN_ARM64=1 KONAN_HAS_CXX11_EXCEPTION_FUNCTIONS=1 + +# Android X86, based on NDK. +targetToolchain.macos_x64-android_x86 = target-toolchain-2-osx-android_ndk +dependencies.macos_x64-android_x86 = \ + target-sysroot-1-android_ndk \ + target-toolchain-2-osx-android_ndk \ + libffi-3.2.1-3-darwin-macos +targetToolchain.linux_x64-android_x86 = target-toolchain-2-linux-android_ndk +dependencies.linux_x64-android_x86 = \ + target-sysroot-1-android_ndk \ + target-toolchain-2-linux-android_ndk \ + libffi-3.2.1-2-linux-x86-64 +targetToolchain.mingw_x64-android_x86 = target-toolchain-2-windows-android_ndk +dependencies.mingw_x64-android_x86 = \ + target-sysroot-1-android_ndk \ + target-toolchain-2-windows-android_ndk \ + libffi-3.2.1-mingw-w64-x86-64 + +quadruple.android_x86 = i686-linux-android + +# -target-cpu pentium4 makes sure that cogenerator knows which CPU flavour to emit code for. +# Can be seen on optimized build and FP tests, where value is passed on stack +# by Kotlin and taken from SSE registers by C code. +# TODO: once this information is available in function attributes, we can set target CPU to i686. +clangFlags.android_x86 = -cc1 -target-cpu pentium4 -emit-obj -disable-llvm-passes -x ir -femulated-tls -mrelocation-model pic +clangOptFlags.android_x86 = -O3 -ffunction-sections +clangNooptFlags.android_x86 = -O1 +targetSysRoot.android_x86 = target-sysroot-1-android_ndk +linkerKonanFlags.android_x86 = -lm -lc++_static -lc++abi -landroid -llog -latomic +linkerNoDebugFlags.android_x86 = -Wl,-S +runtimeDefinitions.android_x86 = __ANDROID__ USE_GCC_UNWIND=1 USE_ELF_SYMBOLS=1 \ + ELFSIZE=32 KONAN_ANDROID=1 KONAN_X86=1 KONAN_HAS_CXX11_EXCEPTION_FUNCTIONS=1 + +# Android X64, based on NDK. +targetToolchain.macos_x64-android_x64 = target-toolchain-2-osx-android_ndk +dependencies.macos_x64-android_x64 = \ + target-sysroot-1-android_ndk \ + target-toolchain-2-osx-android_ndk \ + libffi-3.2.1-3-darwin-macos +targetToolchain.linux_x64-android_x64 = target-toolchain-2-linux-android_ndk +dependencies.linux_x64-android_x64 = \ + target-sysroot-1-android_ndk \ + target-toolchain-2-linux-android_ndk \ + libffi-3.2.1-2-linux-x86-64 +targetToolchain.mingw_x64-android_x64 = target-toolchain-2-windows-android_ndk +dependencies.mingw_x64-android_x64 = \ + target-sysroot-1-android_ndk \ + target-toolchain-2-windows-android_ndk \ + libffi-3.2.1-mingw-w64-x86-64 + +quadruple.android_x64 = x86_64-linux-android +clangFlags.android_x64 = -cc1 -target-cpu x86-64 -emit-obj -disable-llvm-passes -x ir -femulated-tls -mrelocation-model pic +clangOptFlags.android_x64 = -O3 -ffunction-sections +clangNooptFlags.android_x64 = -O1 +targetSysRoot.android_x64 = target-sysroot-1-android_ndk +linkerKonanFlags.android_x64 = -lm -lc++_static -lc++abi -landroid -llog -latomic +linkerNoDebugFlags.android_x64 = -Wl,-S +runtimeDefinitions.android_x64 = __ANDROID__ USE_GCC_UNWIND=1 USE_ELF_SYMBOLS=1 \ + ELFSIZE=64 KONAN_ANDROID=1 KONAN_X64=1 KONAN_HAS_CXX11_EXCEPTION_FUNCTIONS=1 + +# Windows x86-64, based on mingw-w64. +llvmHome.mingw_x64 = $llvm.mingw_x64.dev +targetToolchain.mingw_x64 = msys2-mingw-w64-x86_64-clang-llvm-lld-compiler_rt-8.0.1 +libffiDir.mingw_x64 = libffi-3.2.1-mingw-w64-x86-64 + +targetToolchain.linux_x64-mingw_x64 = msys2-mingw-w64-x86_64-clang-llvm-lld-compiler_rt-8.0.1 +targetToolchain.macos_x64-mingw_x64 = msys2-mingw-w64-x86_64-clang-llvm-lld-compiler_rt-8.0.1 +# for Windows we are currently using LLDB 9 +dependencies.mingw_x64 = \ + libffi-3.2.1-mingw-w64-x86-64 \ + lldb-2-windows +dependencies.linux_x64-mingw_x64 = \ + libffi-3.2.1-2-linux-x86-64 +dependencies.macos_x64-mingw_x64 = \ + libffi-3.2.1-3-darwin-macos + +quadruple.mingw_x64 = x86_64-w64-mingw32 +targetSysRoot.mingw_x64 = msys2-mingw-w64-x86_64-clang-llvm-lld-compiler_rt-8.0.1 +# For using with Universal Windows Platform (UWP) we need to use this slower option. +# See https://youtrack.jetbrains.com/issue/KT-27654. +# TODO: remove, once fixed in mingw, check with the bug testcase. +clangFlags.mingw_x64 = -cc1 -emit-obj -disable-llvm-passes -x ir -femulated-tls -target-cpu x86-64 +clangOptFlags.mingw_x64 = -O3 -ffunction-sections +clangNooptFlags.mingw_x64 = -O1 +linkerNoDebugFlags.mingw_x64 = -Wl,-S +linkerDynamicFlags.mingw_x64 = -shared +linkerKonanFlags.mingw_x64 =-static-libgcc -static-libstdc++ \ + -Xclang -flto-visibility-public-std -Wl,--dynamicbase \ + -Wl,-Bstatic,--whole-archive -lwinpthread -Wl,--no-whole-archive,-Bdynamic \ + -Wl,--defsym,__cxa_demangle=Konan_cxa_demangle +linkerOptimizationFlags.mingw_x64 = -Wl,--gc-sections +mimallocLinkerDependencies.mingw_x64 = -lbcrypt +runtimeDefinitions.mingw_x64 = USE_GCC_UNWIND=1 USE_PE_COFF_SYMBOLS=1 KONAN_WINDOWS=1 \ + UNICODE KONAN_X64=1 KONAN_NO_MEMMEM=1 KONAN_HAS_CXX11_EXCEPTION_FUNCTIONS=1 + +# Windows i686, based on mingw-w64. +targetToolchain.mingw_x64-mingw_x86 = msys2-mingw-w64-i686-clang-llvm-lld-compiler_rt-8.0.1 +dependencies.mingw_x64-mingw_x86 = \ + msys2-mingw-w64-i686-clang-llvm-lld-compiler_rt-8.0.1 \ + libffi-3.2.1-mingw-w64-x86-64 +targetToolchain.linux_x64-mingw_x86 = msys2-mingw-w64-i686-clang-llvm-lld-compiler_rt-8.0.1 +targetToolchain.macos_x64-mingw_x86 = msys2-mingw-w64-i686-clang-llvm-lld-compiler_rt-8.0.1 +dependencies.linux_x64-mingw_x86 = \ + msys2-mingw-w64-i686-clang-llvm-lld-compiler_rt-8.0.1 \ + libffi-3.2.1-2-linux-x86-64 +dependencies.macos_x64-mingw_x86 = \ + msys2-mingw-w64-i686-clang-llvm-lld-compiler_rt-8.0.1 \ + libffi-3.2.1-3-darwin-macos + +quadruple.mingw_x86 = i686-w64-mingw32 +targetSysRoot.mingw_x86 = msys2-mingw-w64-i686-clang-llvm-lld-compiler_rt-8.0.1 +# For using with Universal Windows Platform (UWP) we need to use slower -emulated-tls option. +# See https://youtrack.jetbrains.com/issue/KT-27654. +# TODO: remove, once fixed in mingw, check with the bug testcase. +# -target-cpu pentium4 makes sure that cogenerator knows which CPU flavour to emit code for. +# Can be seen on optimized build and FP tests, where value is passed in coprocessor registers +# by Kotlin and taken from SSE registers by C code. +# TODO: once this information is available in function attributes, we can remove this flag. +clangFlags.mingw_x86 = -cc1 -emit-obj -disable-llvm-passes -x ir -femulated-tls -target-cpu pentium4 +clangOptFlags.mingw_x86 = -O3 -ffunction-sections +clangNooptFlags.mingw_x86 = -O1 +linkerNoDebugFlags.mingw_x86 = -Wl,-S +linkerDynamicFlags.mingw_x86 = -shared +linkerKonanFlags.mingw_x86 = -static-libgcc -static-libstdc++ \ + -Xclang -flto-visibility-public-std -Wl,--dynamicbase \ + -Wl,-Bstatic,--whole-archive -lwinpthread -Wl,--no-whole-archive,-Bdynamic \ + -Wl,--defsym,___cxa_demangle=_Konan_cxa_demangle +mimallocLinkerDependencies.mingw_x86 = -lbcrypt +linkerOptimizationFlags.mingw_x86 = -Wl,--gc-sections +runtimeDefinitions.mingw_x86 = USE_GCC_UNWIND=1 USE_PE_COFF_SYMBOLS=1 KONAN_WINDOWS=1 \ + UNICODE KONAN_X86=1 KONAN_NO_MEMMEM=1 KONAN_HAS_CXX11_EXCEPTION_FUNCTIONS=1 + +# WebAssembly 32-bit. +targetToolchain.macos_x64-wasm32 = target-toolchain-3-macos-wasm +dependencies.macos_x64-wasm32 = \ + libffi-3.2.1-3-darwin-macos \ + target-sysroot-4-embedded \ + target-toolchain-3-macos-wasm + +targetToolchain.linux_x64-wasm32 = target-toolchain-2-linux-wasm +dependencies.linux_x64-wasm32 = \ + libffi-3.2.1-2-linux-x86-64 \ + target-sysroot-4-embedded \ + target-toolchain-2-linux-wasm + +targetToolchain.mingw_x64-wasm32 = target-toolchain-2-mingw-wasm +dependencies.mingw_x64-wasm32 = \ + libffi-3.2.1-mingw-w64-x86-64 \ + target-sysroot-4-embedded \ + target-toolchain-2-mingw-wasm + +quadruple.wasm32 = wasm32-unknown-unknown +targetSysRoot.wasm32 = target-sysroot-4-embedded +clangFlags.wasm32 = -cc1 -emit-obj -disable-llvm-optzns -x ir +clangNooptFlags.wasm32 = -O1 +clangOptFlags.wasm32 = -O3 +clangDebugFlags.wasm32 = -O0 +# TODO: make explicit list of external symbols +lld.wasm32 = --allow-undefined --no-entry --global-base=0 --no-threads --export-dynamic +runtimeDefinitions.wasm32 = KONAN_WASM=1 KONAN_NO_FFI=1 KONAN_NO_THREADS=1 \ + KONAN_NO_EXCEPTIONS=1 KONAN_INTERNAL_DLMALLOC=1 KONAN_INTERNAL_SNPRINTF=1 \ + KONAN_INTERNAL_NOW=1 KONAN_NO_MEMMEM KONAN_NO_CTORS_SECTION=1 + +# The version of Kotlin/Native compiler +compilerVersion=@compilerVersion@ \ No newline at end of file diff --git a/kotlin-native/konan/platforms/zephyr/stm32f4_disco b/kotlin-native/konan/platforms/zephyr/stm32f4_disco new file mode 100644 index 00000000000..6690bd1c790 --- /dev/null +++ b/kotlin-native/konan/platforms/zephyr/stm32f4_disco @@ -0,0 +1,51 @@ +# +# Copyright 2010-2018 JetBrains s.r.o. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +# Zephyr RTOS. +# STM32 F4 Discovery + +quadruple.zephyr_stm32f4_disco = armv7m-none-eabi +targetSysRoot.zephyr_stm32f4_disco = target-sysroot-4-embedded + +boardSpecificClangFlags.zephyr_stm32f4_disco = -mthumb +targetCpu.zephyr_stm32f4_disco = cortex-m4 +targetAbi.zephyr_stm32f4_disco = aapcs +clangFlags = -Os +runtimeDefinitions.zephyr_stm32f4_disco = KONAN_ZEPHYR=1 KONAN_NO_FFI=1 \ + KONAN_NO_THREADS=1 KONAN_NO_EXCEPTIONS=1 KONAN_NO_MATH=1 \ + KONAN_INTERNAL_SNPRINTF=1 KONAN_INTERNAL_NOW=1 KONAN_NO_MEMMEM=1 \ + KONAN_NO_CTORS_SECTION=1 KONAN_NO_UNALIGNED_ACCESS=1 + +targetToolchain.linux_x64-zephyr_stm32f4_disco = gcc-arm-none-eabi-7-2017-q4-major-linux/arm-none-eabi +dependencies.linux_x64-zephyr_stm32f4_disco = \ + libffi-3.2.1-2-linux-x86-64 \ + clang-llvm-8.0.0-linux-x86-64 \ + gcc-arm-none-eabi-7-2017-q4-major-linux \ + target-sysroot-4-embedded + +targetToolchain.macos_x64-zephyr_stm32f4_disco = gcc-arm-none-eabi-7-2017-q4-major-mac/arm-none-eabi +dependencies.macos_x64-zephyr_stm32f4_disco = \ + gcc-arm-none-eabi-7-2017-q4-major-mac \ + libffi-3.2.1-3-darwin-macos \ + clang-llvm-apple-8.0.0-darwin-macos \ + target-sysroot-4-embedded + +targetToolchain.mingw_x64-zephyr_stm32f4_disco = gcc-arm-none-eabi-7-2017-q4-major-win32/arm-none-eabi +dependencies.mingw_x64-zephyr_stm32f4_disco = \ + libffi-3.2.1-mingw-w64-x86-64 \ + msys2-mingw-w64-x86_64-clang-llvm-lld-compiler_rt-8.0.1 \ + gcc-arm-none-eabi-7-2017-q4-major-win32 \ + target-sysroot-4-embedded diff --git a/kotlin-native/libclangext/build.gradle b/kotlin-native/libclangext/build.gradle new file mode 100644 index 00000000000..dd5dd3c356d --- /dev/null +++ b/kotlin-native/libclangext/build.gradle @@ -0,0 +1,63 @@ +/* + * Copyright 2010-2017 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +apply plugin: "cpp" +apply plugin: "c" +buildscript { + ext.rootBuildDirectory = file('..') + + apply from: "$rootBuildDirectory/gradle/kotlinGradlePlugin.gradle" + + dependencies { + classpath "org.jetbrains.kotlin:kotlin-stdlib:$kotlinVersion" + classpath "org.jetbrains.kotlin:kotlin-native-shared:$konanVersion" + } +} +import org.jetbrains.kotlin.konan.target.ClangArgs +import org.jetbrains.kotlin.PlatformInfo +ext.isEnabled = PlatformInfo.isMac() + +model { + components { + clangext(NativeLibrarySpec) { + sources { + cpp { + source.srcDirs "src/main/cpp" + exportedHeaders.srcDirs "src/main/include" + } + } + binaries.withType(StaticLibraryBinarySpec) { binary -> + if (!project.parent.convention.plugins.platformInfo.isWindows()) + cppCompiler.args "-fPIC" + cppCompiler.args "--std=c++11", "-g", "-I${llvmDir}/include" + if (isEnabled) { + cppCompiler.args '-DLIBCLANGEXT_ENABLE=1' + } + } + binaries.withType(SharedLibraryBinarySpec) { binary -> + buildable = false + } + } + } + + toolChains { + clang(Clang) { + eachPlatform { + cppCompiler.withArguments(ClangArgs.&filterGradleNativeSoftwareFlags) + } + } + } +} diff --git a/kotlin-native/libclangext/src/main/cpp/ClangExt.cpp b/kotlin-native/libclangext/src/main/cpp/ClangExt.cpp new file mode 100644 index 00000000000..74d966faab8 --- /dev/null +++ b/kotlin-native/libclangext/src/main/cpp/ClangExt.cpp @@ -0,0 +1,220 @@ +/* + * Copyright 2010-2017 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include + +#include +#include +#include +#include "clang-c/ext.h" + +using namespace clang; + +#if LIBCLANGEXT_ENABLE + +static CXCursor makeObjCProtocolDeclCXCursor(const ObjCProtocolDecl* decl, CXTranslationUnit translationUnit) { + auto kind = CXCursor_ObjCProtocolDecl; + CXCursor result = { kind, 0, { decl, (void*)(intptr_t) 1, translationUnit } }; + return result; +} + +static const Attr* getCursorAttr(CXCursor cursor) { + return static_cast(cursor.data[1]); +} + +static const Decl *getCursorDecl(CXCursor Cursor) { + return static_cast(Cursor.data[0]); +} + +static const QualType unwrapCXType(CXType type) { + return QualType::getFromOpaquePtr(type.data[0]); +} + +static CXTranslationUnit getTranslationUnit(CXType type) { + return static_cast(type.data[1]); +} + +static ASTUnit* getASTUnit(CXTranslationUnit translationUnit) { + return reinterpret_cast(translationUnit)[1]; +} + +// The functions above are totally libclang-implementation-specific and thus version-dependent. + +static CXTypeAttributes makeCXTypeAttributes(QualType qualType) { + CXTypeAttributes result = { qualType.getAsOpaquePtr() }; + return result; +} + +static QualType unwrapCXTypeAttributes(CXTypeAttributes attributes) { + return QualType::getFromOpaquePtr(attributes.typeOpaquePtr); +} + +#else // LIBCLANGEXT_ENABLE + +static CXTypeAttributes makeCXTypeAttributes() { + CXTypeAttributes result = { nullptr }; + return result; +} + +#endif // LIBCLANGEXT_ENABLE + +extern "C" { + + const char* clang_Cursor_getAttributeSpelling(CXCursor cursor) { +#if LIBCLANGEXT_ENABLE + if (clang_isAttribute(cursor.kind) == 0) { + return nullptr; + } + + return getCursorAttr(cursor)->getSpelling(); +#else + return ""; +#endif + } + + CXTypeAttributes clang_getDeclTypeAttributes(CXCursor cursor) { +#if LIBCLANGEXT_ENABLE + CXType cxType = clang_getCursorType(cursor); + if (clang_isDeclaration(cursor.kind)) { + const Decl *D = getCursorDecl(cursor); + if (D) { + if (const DeclaratorDecl *DD = dyn_cast(D)) + return makeCXTypeAttributes(DD->getType()); + } + } + return makeCXTypeAttributes(QualType()); +#else + return makeCXTypeAttributes(); +#endif + } + + CXTypeAttributes clang_getResultTypeAttributes(CXTypeAttributes typeAttributes) { +#if LIBCLANGEXT_ENABLE + QualType qualType = unwrapCXTypeAttributes(typeAttributes); + if (qualType.isNull()) + return makeCXTypeAttributes(qualType); + + if (const FunctionType *functionType = qualType->getAs()) + return makeCXTypeAttributes(functionType->getReturnType()); + + return makeCXTypeAttributes(QualType()); +#else + return makeCXTypeAttributes(); +#endif + } + + CXTypeAttributes clang_getCursorResultTypeAttributes(CXCursor cursor) { +#if LIBCLANGEXT_ENABLE + if (clang_isDeclaration(cursor.kind)) { + const Decl *decl = getCursorDecl(cursor); + if (const ObjCMethodDecl *methodDecl = dyn_cast_or_null(decl)) + return makeCXTypeAttributes(methodDecl->getReturnType()); + + return clang_getResultTypeAttributes(clang_getDeclTypeAttributes(cursor)); + } + + return makeCXTypeAttributes(QualType()); +#else + return makeCXTypeAttributes(); +#endif + } + + enum CXNullabilityKind clang_Type_getNullabilityKind(CXType type, CXTypeAttributes attributes) { +#if LIBCLANGEXT_ENABLE + CXTranslationUnit translationUnit = getTranslationUnit(type); + ASTContext& astContext = getASTUnit(translationUnit)->getASTContext(); + + QualType qualType = unwrapCXTypeAttributes(attributes); + + auto kind = qualType->getNullability(astContext); + if (!kind.hasValue()) { + return CXNullabilityKind_Unspecified; + } + + switch (*kind) { + case NullabilityKind::NonNull: return CXNullabilityKind_NonNull; + case NullabilityKind::Nullable: return CXNullabilityKind_Nullable; + case NullabilityKind::Unspecified: return CXNullabilityKind_Unspecified; + default: assert(false); + } +#else + return CXNullabilityKind_Unspecified; +#endif + } + + unsigned clang_Type_getNumProtocols(CXType type) { +#if LIBCLANGEXT_ENABLE + QualType qualType = unwrapCXType(type); + if (auto objCObjectPointerType = qualType->getAs()) { + return objCObjectPointerType->getObjectType()->getNumProtocols(); + } +#endif + return 0; + } + + CXCursor clang_Type_getProtocol(CXType type, unsigned index) { +#if LIBCLANGEXT_ENABLE + QualType qualType = unwrapCXType(type); + if (auto objCObjectPointerType = qualType->getAs()) { + auto objectType = objCObjectPointerType->getObjectType(); + unsigned n = objectType->getNumProtocols(); + if (index < n) { + auto protocolDecl = objectType->getProtocol(index); + auto kind = CXCursor_ObjCProtocolDecl; + return makeObjCProtocolDeclCXCursor(protocolDecl, getTranslationUnit(type)); + } + } +#endif + return clang_getNullCursor(); + } + + unsigned clang_Cursor_isObjCInitMethod(CXCursor cursor) { +#if LIBCLANGEXT_ENABLE + if (cursor.kind == CXCursor_ObjCInstanceMethodDecl) { + const Decl *decl = getCursorDecl(cursor); + if (const ObjCMethodDecl *methodDecl = dyn_cast_or_null(decl)) { + return methodDecl->getMethodFamily() == OMF_init; + } + } +#endif + return 0; + } + + unsigned clang_Cursor_isObjCReturningRetainedMethod(CXCursor cursor) { +#if LIBCLANGEXT_ENABLE + if (cursor.kind == CXCursor_ObjCInstanceMethodDecl) { + const Decl *decl = getCursorDecl(cursor); + if (const ObjCMethodDecl *methodDecl = dyn_cast_or_null(decl)) { + return methodDecl->hasAttr(); + } + } +#endif + return 0; + } + + unsigned clang_Cursor_isObjCConsumingSelfMethod(CXCursor cursor) { +#if LIBCLANGEXT_ENABLE + if (cursor.kind == CXCursor_ObjCInstanceMethodDecl) { + const Decl *decl = getCursorDecl(cursor); + if (const ObjCMethodDecl *methodDecl = dyn_cast_or_null(decl)) { + return methodDecl->hasAttr(); + } + } +#endif + return 0; + } + +} diff --git a/kotlin-native/libclangext/src/main/cpp/ExtVector.cpp b/kotlin-native/libclangext/src/main/cpp/ExtVector.cpp new file mode 100644 index 00000000000..0aca72efa8c --- /dev/null +++ b/kotlin-native/libclangext/src/main/cpp/ExtVector.cpp @@ -0,0 +1,38 @@ +/* + * Copyright 2010-2017 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + + +#include + +#include +#include + + +using namespace clang; + + +static inline QualType GetQualType(CXType CT) { + return QualType::getFromOpaquePtr(CT.data[0]); +} + +extern "C" +int clang_isExtVectorType(CXType CT) { + static_assert(CINDEX_VERSION < 59, "Use CXType_ExtVector for this libclang version"); + + QualType T = GetQualType(CT); + const clang::Type *TP = T.getTypePtrOrNull(); + return TP && TP->isExtVectorType(); +} diff --git a/kotlin-native/libclangext/src/main/include/clang-c/ExtVector.h b/kotlin-native/libclangext/src/main/include/clang-c/ExtVector.h new file mode 100644 index 00000000000..d2fe4b59c90 --- /dev/null +++ b/kotlin-native/libclangext/src/main/include/clang-c/ExtVector.h @@ -0,0 +1,27 @@ +/* + * Copyright 2010-2017 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +int clang_isExtVectorType(CXType type); + +#ifdef __cplusplus +} +#endif diff --git a/kotlin-native/libclangext/src/main/include/clang-c/ext.h b/kotlin-native/libclangext/src/main/include/clang-c/ext.h new file mode 100644 index 00000000000..7b4d004cdd3 --- /dev/null +++ b/kotlin-native/libclangext/src/main/include/clang-c/ext.h @@ -0,0 +1,60 @@ +/* + * Copyright 2010-2017 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include + +// TODO: the API declared below should eventually be refined and contributed to libclang. + + +// libclang doesn't include the type attributes when constructing `CXType`, +// so attributes have to be represented separately: +typedef struct { + const void* typeOpaquePtr; +} CXTypeAttributes; + +enum CXNullabilityKind { + CXNullabilityKind_Nullable, + CXNullabilityKind_NonNull, + CXNullabilityKind_Unspecified +}; + +#ifdef __cplusplus +extern "C" { +#endif + +const char* clang_Cursor_getAttributeSpelling(CXCursor cursor); + +CXTypeAttributes clang_getDeclTypeAttributes(CXCursor cursor); + +CXTypeAttributes clang_getResultTypeAttributes(CXTypeAttributes typeAttributes); + +CXTypeAttributes clang_getCursorResultTypeAttributes(CXCursor cursor); + +enum CXNullabilityKind clang_Type_getNullabilityKind(CXType type, CXTypeAttributes attributes); + +unsigned clang_Type_getNumProtocols(CXType type); + +CXCursor clang_Type_getProtocol(CXType type, unsigned index); + +unsigned clang_Cursor_isObjCInitMethod(CXCursor cursor); + +unsigned clang_Cursor_isObjCReturningRetainedMethod(CXCursor cursor); + +unsigned clang_Cursor_isObjCConsumingSelfMethod(CXCursor cursor); + +#ifdef __cplusplus +} +#endif diff --git a/kotlin-native/licenses/LICENSE.txt b/kotlin-native/licenses/LICENSE.txt new file mode 100644 index 00000000000..9e385b9d099 --- /dev/null +++ b/kotlin-native/licenses/LICENSE.txt @@ -0,0 +1,202 @@ + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright 2000-2020 JetBrains s.r.o. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. diff --git a/kotlin-native/licenses/NOTICE.txt b/kotlin-native/licenses/NOTICE.txt new file mode 100644 index 00000000000..84f6cc4bd45 --- /dev/null +++ b/kotlin-native/licenses/NOTICE.txt @@ -0,0 +1,8 @@ + ========================================================================= + == NOTICE file corresponding to the section 4 d of == + == the Apache License, Version 2.0, == + == in this case for the Kotlin Compiler distribution. == + ========================================================================= + + Kotlin Compiler + Copyright 2010-2017 JetBrains s.r.o and respective authors and developers diff --git a/kotlin-native/licenses/third_party/args4j_LICENSE.txt b/kotlin-native/licenses/third_party/args4j_LICENSE.txt new file mode 100644 index 00000000000..04471dd7be3 --- /dev/null +++ b/kotlin-native/licenses/third_party/args4j_LICENSE.txt @@ -0,0 +1,21 @@ +The MIT License + +Copyright (c) 2003, Kohsuke Kawaguchi + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. diff --git a/kotlin-native/licenses/third_party/asm_license.txt b/kotlin-native/licenses/third_party/asm_license.txt new file mode 100644 index 00000000000..d0cd82defe0 --- /dev/null +++ b/kotlin-native/licenses/third_party/asm_license.txt @@ -0,0 +1,28 @@ + + ASM: a very small and fast Java bytecode manipulation framework + Copyright (c) 2000-2005 INRIA, France Telecom + All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + 3. Neither the name of the copyright holders nor the names of its + contributors may be used to endorse or promote products derived from + this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF + THE POSSIBILITY OF SUCH DAMAGE. diff --git a/kotlin-native/licenses/third_party/boost_LICENSE.txt b/kotlin-native/licenses/third_party/boost_LICENSE.txt new file mode 100644 index 00000000000..127a5bc39ba --- /dev/null +++ b/kotlin-native/licenses/third_party/boost_LICENSE.txt @@ -0,0 +1,23 @@ +Boost Software License - Version 1.0 - August 17th, 2003 + +Permission is hereby granted, free of charge, to any person or organization +obtaining a copy of the software and accompanying documentation covered by +this license (the "Software") to use, reproduce, display, distribute, +execute, and transmit the Software, and to prepare derivative works of the +Software, and to permit third-parties to whom the Software is furnished to +do so, all subject to the following: + +The copyright notices in the Software and this entire statement, including +the above license grant, this restriction and the following disclaimer, +must be included in all copies of the Software, in whole or in part, and +all derivative works of the Software, unless such copies or derivative +works are solely in the form of machine-executable object code generated by +a source language processor. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +DEALINGS IN THE SOFTWARE. \ No newline at end of file diff --git a/kotlin-native/licenses/third_party/closure-compiler_LICENSE.txt b/kotlin-native/licenses/third_party/closure-compiler_LICENSE.txt new file mode 100644 index 00000000000..d6456956733 --- /dev/null +++ b/kotlin-native/licenses/third_party/closure-compiler_LICENSE.txt @@ -0,0 +1,202 @@ + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. diff --git a/kotlin-native/licenses/third_party/dart_LICENSE.txt b/kotlin-native/licenses/third_party/dart_LICENSE.txt new file mode 100644 index 00000000000..0e7aabed93c --- /dev/null +++ b/kotlin-native/licenses/third_party/dart_LICENSE.txt @@ -0,0 +1,48 @@ +This license applies to all parts of Dart that are not externally +maintained libraries. The external maintained libraries used by +Dart are: + +7-Zip - in third_party/7zip +JSCRE - in runtime/third_party/jscre +Ant - in third_party/apache_ant +args4j - in third_party/args4j +bzip2 - in third_party/bzip2 +dromaeo - in samples/third_party/dromaeo +Eclipse - in third_party/eclipse +gsutil = in third_party/gsutil +Guava - in third_party/guava +hamcrest - in third_party/hamcrest +Httplib2 - in samples/third_party/httplib2 +JSON - in third_party/json +JUnit - in third_party/junit +Oauth - in samples/third_party/oauth2client +Rhino - in third_party/rhino +weberknecht - in third_party/weberknecht + +The libraries may have their own licenses; we recommend you read them, +as their terms may differ from the terms below. + +Copyright 2012, the Dart project authors. All rights reserved. +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above + copyright notice, this list of conditions and the following + disclaimer in the documentation and/or other materials provided + with the distribution. + * Neither the name of Google Inc. nor the names of its + contributors may be used to endorse or promote products derived + from this software without specific prior written permission. +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/kotlin-native/licenses/third_party/glibc_license.txt b/kotlin-native/licenses/third_party/glibc_license.txt new file mode 100644 index 00000000000..dc60a4cb78e --- /dev/null +++ b/kotlin-native/licenses/third_party/glibc_license.txt @@ -0,0 +1,75 @@ +GCC RUNTIME LIBRARY EXCEPTION + +Version 3.1, 31 March 2009 + +Copyright (C) 2009 Free Software Foundation, Inc. + +Everyone is permitted to copy and distribute verbatim copies of this +license document, but changing it is not allowed. + +This GCC Runtime Library Exception ("Exception") is an additional +permission under section 7 of the GNU General Public License, version +3 ("GPLv3"). It applies to a given file (the "Runtime Library") that +bears a notice placed by the copyright holder of the file stating that +the file is governed by GPLv3 along with this Exception. + +When you use GCC to compile a program, GCC may combine portions of +certain GCC header files and runtime libraries with the compiled +program. The purpose of this Exception is to allow compilation of +non-GPL (including proprietary) programs to use, in this way, the +header files and runtime libraries covered by this Exception. + +0. Definitions. + +A file is an "Independent Module" if it either requires the Runtime +Library for execution after a Compilation Process, or makes use of an +interface provided by the Runtime Library, but is not otherwise based +on the Runtime Library. + +"GCC" means a version of the GNU Compiler Collection, with or without +modifications, governed by version 3 (or a specified later version) of +the GNU General Public License (GPL) with the option of using any +subsequent versions published by the FSF. + +"GPL-compatible Software" is software whose conditions of propagation, +modification and use would permit combination with GCC in accord with +the license of GCC. + +"Target Code" refers to output from any compiler for a real or virtual +target processor architecture, in executable form or suitable for +input to an assembler, loader, linker and/or execution +phase. Notwithstanding that, Target Code does not include data in any +format that is used as a compiler intermediate representation, or used +for producing a compiler intermediate representation. + +The "Compilation Process" transforms code entirely represented in +non-intermediate languages designed for human-written code, and/or in +Java Virtual Machine byte code, into Target Code. Thus, for example, +use of source code generators and preprocessors need not be considered +part of the Compilation Process, since the Compilation Process can be +understood as starting with the output of the generators or +preprocessors. + +A Compilation Process is "Eligible" if it is done using GCC, alone or +with other GPL-compatible software, or if it is done without using any +work based on GCC. For example, using non-GPL-compatible Software to +optimize any GCC intermediate representations would not qualify as an +Eligible Compilation Process. + +1. Grant of Additional Permission. + +You have permission to propagate a work of Target Code formed by +combining the Runtime Library with Independent Modules, even if such +propagation would otherwise violate the terms of GPLv3, provided that +all Target Code was generated by Eligible Compilation Processes. You +may then convey such a combination under terms of your choice, +consistent with the licensing of the Independent Modules. + +2. No Weakening of GCC Copyleft. + +The availability of this Exception does not imply any general +presumption that third-party software is unaffected by the copyleft +requirements of the license of GCC. + + +Hopefully that text is self-explanatory. If it isn't, you need to speak to your lawyer, or the Free Software Foundation. diff --git a/kotlin-native/licenses/third_party/harmony_LICENSE.txt b/kotlin-native/licenses/third_party/harmony_LICENSE.txt new file mode 100644 index 00000000000..aa07fc96d34 --- /dev/null +++ b/kotlin-native/licenses/third_party/harmony_LICENSE.txt @@ -0,0 +1,1419 @@ + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + + + +================================================================================ +================================================================================ + + + +APACHE HARMONY SUBCOMPONENTS: + +Apache Harmony includes a number of subcomponents with separate +copyright notices and license terms. Your use of the source code +for the these subcomponents is subject to the terms and conditions +of the following licenses. + + + +License Notice for ICU4C version 3.4 +==================================== + +ICU License - ICU 1.8.1 and later + +COPYRIGHT AND PERMISSION NOTICE + +Copyright (c) 1995-2005 International Business Machines Corporation and others +All rights reserved. + +Permission is hereby granted, free of charge, to any person obtaining a +copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, and/or sell copies of the Software, and to permit persons +to whom the Software is furnished to do so, provided that the above +copyright notice(s) and this permission notice appear in all copies of +the Software and that both the above copyright notice(s) and this +permission notice appear in supporting documentation. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT +OF THIRD PARTY RIGHTS. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +HOLDERS INCLUDED IN THIS NOTICE BE LIABLE FOR ANY CLAIM, OR ANY SPECIAL +INDIRECT OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES WHATSOEVER RESULTING +FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, +NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION +WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + +Except as contained in this notice, the name of a copyright holder +shall not be used in advertising or otherwise to promote the sale, use +or other dealings in this Software without prior written authorization +of the copyright holder. + +-------------------------------------------------------------------------------- +All trademarks and registered trademarks mentioned herein are the property of +their respective owners. + + + +================================================================================ +================================================================================ + + + +License Notice for ICU4J version 4.2.1 +====================================== + +ICU4J license - ICU4J 1.8.1 and later + +COPYRIGHT AND PERMISSION NOTICE + +Copyright (c) 1995-2009 International Business Machines Corporation and others + +All rights reserved. + +Permission is hereby granted, free of charge, to any person obtaining a copy of +this software and associated documentation files (the "Software"), to deal in +the Software without restriction, including without limitation the rights to +use, copy, modify, merge, publish, distribute, and/or sell copies of the +Software, and to permit persons to whom the Software is furnished to do so, +provided that the above copyright notice(s) and this permission notice appear +in all copies of the Software and that both the above copyright notice(s) and +this permission notice appear in supporting documentation. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT +OF THIRD PARTY RIGHTS. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +HOLDERS INCLUDED IN THIS NOTICE BE LIABLE FOR ANY CLAIM, OR ANY SPECIAL +INDIRECT OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES WHATSOEVER RESULTING +FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, +NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION +WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + +Except as contained in this notice, the name of a copyright holder +shall not be used in advertising or otherwise to promote the sale, use +or other dealings in this Software without prior written authorization +of the copyright holder. + +-------------------------------------------------------------------------------- + +All trademarks and registered trademarks mentioned herein are the property of +their respective owners. + + + +================================================================================ +================================================================================ + + + +License Notice for FDLIBM version 5.2 +===================================== + +Copyright (C) 2004 by Sun Microsystems, Inc. All rights reserved. + +Developed at SunSoft, a Sun Microsystems, Inc. business. +Permission to use, copy, modify, and distribute this software is freely +granted, provided that this notice is preserved. + + + +================================================================================ +================================================================================ + + + +License Notice for ZLIB version 1.2.3 +===================================== + + (C) 1995-2004 Jean-loup Gailly and Mark Adler + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. + + Jean-loup Gailly Mark Adler + jloup@gzip.org madler@alumni.caltech.edu + + + +================================================================================ +================================================================================ + + + +Visual C++ Runtime Files +======================== + +The file msvcr71.dll is the Microsoft(R) C Runtime Library. +The file msvcp71.dll is the Microsoft Multithreaded Standard C++ Library. + +These files are redistributed from Microsoft(R) Visual Studio 7.1 as described in +the file "redist.txt" available with that product. + + + +================================================================================ +================================================================================ + + + +License Notice for Bouncy Castle version 1.45 +============================================= + +Copyright (c) 2000 - 2009 The Legion Of The Bouncy Castle (http://www.bouncycastle.org) + +Permission is hereby granted, free of charge, to any person obtaining a copy of +this software and associated documentation files (the "Software"), to deal in +the Software without restriction, including without limitation the rights to use, +copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the +Software, and to permit persons to whom the Software is furnished to do so, subject +to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + + + +=============================================================================== +=============================================================================== + + + +License Notice for MX4J 3.0.2. +============================== + +The MX4J License, Version 1.0 + +Copyright (c) 2001-2004 by the MX4J contributors. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions +are met: + + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the + distribution. + + 3. The end-user documentation included with the redistribution, + if any, must include the following acknowledgment: + "This product includes software developed by the + MX4J project (http://mx4j.sourceforge.net)." + Alternately, this acknowledgment may appear in the software itself, + if and wherever such third-party acknowledgments normally appear. + + 4. The name "MX4J" must not be used to endorse or promote + products derived from this software without prior written + permission. + For written permission, please contact + biorn_steedom [at] users [dot] sourceforge [dot] net + + 5. Products derived from this software may not be called "MX4J", + nor may "MX4J" appear in their name, without prior written + permission of Simone Bordet. + + THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED + WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + DISCLAIMED. IN NO EVENT SHALL THE MX4J CONTRIBUTORS + BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF + USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + SUCH DAMAGE. + ==================================================================== + + This software consists of voluntary contributions made by many + individuals on behalf of the MX4J project. For more information on + MX4J, please see the MX4J website (http://mx4j.sourceforge.net/). + + + +=============================================================================== +=============================================================================== + + + +Notice for The Independent JPEG Group's JPEG software +===================================================== + +This distribution may contain software that is based in part on the work of +the Independent JPEG Group for which the following notice applies: + +The authors make NO WARRANTY or representation, either express or implied, +with respect to this software, its quality, accuracy, merchantability, or +fitness for a particular purpose. This software is provided "AS IS", and you, +its user, assume the entire risk as to its quality and accuracy. + +This software is copyright (C) 1991-1998, Thomas G. Lane. +All Rights Reserved except as specified below. + +Permission is hereby granted to use, copy, modify, and distribute this +software (or portions thereof) for any purpose, without fee, subject to these +conditions: +(1) If any part of the source code for this software is distributed, then this +README file must be included, with this copyright and no-warranty notice +unaltered; and any additions, deletions, or changes to the original files +must be clearly indicated in accompanying documentation. +(2) If only executable code is distributed, then the accompanying +documentation must state that "this software is based in part on the work of +the Independent JPEG Group". +(3) Permission for use of this software is granted only if the user accepts +full responsibility for any undesirable consequences; the authors accept +NO LIABILITY for damages of any kind. + +These conditions apply to any software derived from or based on the IJG code, +not just to the unmodified library. If you use our work, you ought to +acknowledge us. + +Permission is NOT granted for the use of any IJG author's name or company name +in advertising or publicity relating to this software or products derived from +it. This software may be referred to only as "the Independent JPEG Group's +software". + +We specifically permit and encourage the use of this software as the basis of +commercial products, provided that all warranty or liability claims are +assumed by the product vendor. + + + +=============================================================================== +=============================================================================== + + + +Notice for Little CMS +===================== + +This distribution may contain software that is based in part on Little cms +for which the following notice applies: + +Copyright (c) 1998-2007 Marti Maria Saguer + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is furnished +to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR +OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, +ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +OTHER DEALINGS IN THE SOFTWARE. + + + +=============================================================================== +=============================================================================== + + + +Notice for libpng +================= + +This distribution may contain software that is based in part on libpng +v1.2.38 for which the following notice applies: + +libpng versions 1.2.6, August 15, 2004, through 1.2.38, July 16, 2009, are +Copyright (c) 2004, 2006-2009 Glenn Randers-Pehrson, and are +distributed according to the same disclaimer and license as libpng-1.2.5 +with the following individual added to the list of Contributing Authors: + + Cosmin Truta + +libpng versions 1.0.7, July 1, 2000, through 1.2.5, October 3, 2002, are +Copyright (c) 2000-2002 Glenn Randers-Pehrson, and are +distributed according to the same disclaimer and license as libpng-1.0.6 +with the following individuals added to the list of Contributing Authors: + + Simon-Pierre Cadieux + Eric S. Raymond + Gilles Vollant + +and with the following additions to the disclaimer: + + There is no warranty against interference with your enjoyment of the + library or against infringement. There is no warranty that our + efforts or the library will fulfill any of your particular purposes + or needs. This library is provided with all faults, and the entire + risk of satisfactory quality, performance, accuracy, and effort is with + the user. + +libpng versions 0.97, January 1998, through 1.0.6, March 20, 2000, are +Copyright (c) 1998, 1999, 2000 Glenn Randers-Pehrson, and are +distributed according to the same disclaimer and license as libpng-0.96, +with the following individuals added to the list of Contributing Authors: + + Tom Lane + Glenn Randers-Pehrson + Willem van Schaik + +libpng versions 0.89, June 1996, through 0.96, May 1997, are +Copyright (c) 1996, 1997 Andreas Dilger +Distributed according to the same disclaimer and license as libpng-0.88, +with the following individuals added to the list of Contributing Authors: + + John Bowler + Kevin Bracey + Sam Bushell + Magnus Holmgren + Greg Roelofs + Tom Tanner + +libpng versions 0.5, May 1995, through 0.88, January 1996, are +Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc. + +For the purposes of this copyright and license, "Contributing Authors" +is defined as the following set of individuals: + + Andreas Dilger + Dave Martindale + Guy Eric Schalnat + Paul Schmidt + Tim Wegner + +The PNG Reference Library is supplied "AS IS". The Contributing Authors +and Group 42, Inc. disclaim all warranties, expressed or implied, +including, without limitation, the warranties of merchantability and of +fitness for any purpose. The Contributing Authors and Group 42, Inc. +assume no liability for direct, indirect, incidental, special, exemplary, +or consequential damages, which may result from the use of the PNG +Reference Library, even if advised of the possibility of such damage. + +Permission is hereby granted to use, copy, modify, and distribute this +source code, or portions hereof, for any purpose, without fee, subject +to the following restrictions: + +1. The origin of this source code must not be misrepresented. + +2. Altered versions must be plainly marked as such and must not + be misrepresented as being the original source. + +3. This Copyright notice may not be removed or altered from any + source or altered source distribution. + +The Contributing Authors and Group 42, Inc. specifically permit, without +fee, and encourage the use of this source code as a component to +supporting the PNG file format in commercial products. If you use this +source code in a product, acknowledgment is not required but would be +appreciated. + + + +=============================================================================== +=============================================================================== + + + +Notice for Unicode Character Database +===================================== + +Copyright (c) 1991-2005 Unicode, Inc. All rights reserved. Distributed under the +Terms of Use in http://www.unicode.org/copyright.html. + +Permission is hereby granted, free of charge, to any person obtaining a copy of +the Unicode data files and any associated documentation (the "Data Files") or +Unicode software and any associated documentation (the "Software") to deal in +the Data Files or Software without restriction, including without limitation +the rights to use, copy, modify, merge, publish, distribute, and/or sell copies +of the Data Files or Software, and to permit persons to whom the Data Files or +Software are furnished to do so, provided that (a) the above copyright +notice(s) and this permission notice appear with all copies of the Data Files +or Software, (b) both the above copyright notice(s) and this permission notice +appear in associated documentation, and (c) there is clear notice in each +modified Data File or in the Software as well as in the documentation +associated with the Data File(s) or Software that the data or software has been +modified. + +THE DATA FILES AND SOFTWARE ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF THIRD +PARTY RIGHTS. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR HOLDERS INCLUDED IN +THIS NOTICE BE LIABLE FOR ANY CLAIM, OR ANY SPECIAL INDIRECT OR CONSEQUENTIAL +DAMAGES, OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, +WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING +OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THE DATA FILES OR +SOFTWARE. + +Except as contained in this notice, the name of a copyright holder shall not be +used in advertising or otherwise to promote the sale, use or other dealings in +these Data Files or Software without prior written authorization of the +copyright holder. + + + +=============================================================================== +=============================================================================== + + + +Notice for IETF RFCs prior to 2005 +================================== + +This distribution may contain software that is based in part on the work of +the following IETF RFCs. Portions of the IETF RFC specifications may be +included in source code comments for reference, and in accordance with +the licensing terms, the licenses are reproduced here: + +RFC 1779 - A String Representation of Distinguished Names + +RFC 2045 - Multipurpose Internet Mail Extensions (MIME) Part One: Format of + Internet Message Bodies + +RFC 2251 - Lightweight Directory Access Protocol (v3) + Copyright (C) The Internet Society (1997). All Rights Reserved. + +RFC 2253 - Lightweight Directory Access Protocol (v3): UTF-8 String + Representation of Distinguished Names + Copyright (C) The Internet Society (1997). All Rights Reserved. + +RFC 2313 - PKCS #1: RSA Encryption + Copyright (C) The Internet Society (1998). All Rights Reserved. + +RFC 2315 - PKCS #7: Cryptographic Message Syntax + Copyright (C) The Internet Society (1998). All Rights Reserved. + +RFC 2459 - Internet X.509 Public Key Infrastructure Certificate and CRL Profile + Copyright (C) The Internet Society (1999). All Rights Reserved. + +RFC 2616 - Hypertext Transfer Protocol -- HTTP/1.1 + Copyright (C) The Internet Society (1999). All Rights Reserved. + +RFC 2781 - UTF-16, an encoding of ISO 10646 + Copyright (C) The Internet Society (2000). All Rights Reserved. + +RFC 2891 - LDAP Control Extension for Server Side Sorting of Search Results + Copyright (C) The Internet Society (2000). All Rights Reserved. + +RFC 2985 - PKCS #9: Selected Object Classes and Attribute Types + Copyright (C) The Internet Society (2000). All Rights Reserved. + +RFC 3161 - Internet X.509 Public Key Infrastructure Time-Stamp Protocol (TSP) + Copyright (C) The Internet Society (2001). All Rights Reserved. + +RFC 3280 - Internet X.509 Public Key Infrastructure, Certificate and + Certificate Revocation List (CRL) Profile + Copyright (C) The Internet Society (2002). All Rights Reserved. + +INTERNET-DRAFT - Persistent Search: A Simple LDAP Change Notification Mechanism + + Copyright (C) The Internet Society (1997-2000). All Rights Reserved. + +The following statement applies to each RFC: + + This document and translations of it may be copied and furnished to + others, and derivative works that comment on or otherwise explain it + or assist in its implementation may be prepared, copied, published + and distributed, in whole or in part, without restriction of any + kind, provided that the above copyright notice and this paragraph are + included on all such copies and derivative works. However, this + document itself may not be modified in any way, such as by removing + the copyright notice or references to the Internet Society or other + Internet organizations, except as needed for the purpose of + developing Internet standards in which case the procedures for + copyrights defined in the Internet Standards process must be + followed, or as required to translate it into languages other than + English. + + The limited permissions granted above are perpetual and will not be + revoked by the Internet Society or its successors or assigns. + + This document and the information contained herein is provided on an + "AS IS" basis and THE INTERNET SOCIETY AND THE INTERNET ENGINEERING + TASK FORCE DISCLAIMS ALL WARRANTIES, EXPRESS OR IMPLIED, INCLUDING + BUT NOT LIMITED TO ANY WARRANTY THAT THE USE OF THE INFORMATION + HEREIN WILL NOT INFRINGE ANY RIGHTS OR ANY IMPLIED WARRANTIES OF + MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. + + +Notice for IETF RFCs from 2005 onwards +====================================== + +This distribution may contain software that is based in part on the work of +the following IETF RFCs. Portions of the IETF RFC specifications may be +included in source code comments for reference, and in accordance with +the licensing terms, the licenses are reproduced here: + +RFC 4122 - A Universally Unique Identifier (UUID) URN Namespace + Copyright (C) The Internet Society (2005). + + +The following statement applies to this RFC: + + Copyright (C) The Internet Society (2005). + + This document is subject to the rights, licenses and restrictions + contained in BCP 78, and except as set forth therein, the authors + retain all their rights. + + This document and the information contained herein are provided + on an "AS IS" basis and THE CONTRIBUTOR, THE ORGANIZATION HE/SHE + REPRESENTS OR IS SPONSORED BY (IF ANY), THE INTERNET SOCIETY AND + THE INTERNET ENGINEERING TASK FORCE DISCLAIM ALL WARRANTIES, + EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTY THAT + THE USE OF THE INFORMATION HEREIN WILL NOT INFRINGE ANY RIGHTS OR + ANY IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A + PARTICULAR PURPOSE. + + + +=============================================================================== +=============================================================================== + + + +Notice for RSA Public-Key Cryptography Standards +================================================ + +Portions of Apache Harmony reference RSA Public-Key Cryptography Standards: +PKCS#7, PKCS#8 and PKSC#10. Portions of these standards are included +in Harmony Javadoc for reference, and in accordance with the licensing terms +for PKCS#7, PKCS#8 and PKSC#10, the full copyright statement is here: + +Copyright 1991-1993 RSA Laboratories, a division of RSA Data Security, Inc. +License to copy this document is granted provided that it is identified as +"RSA Data Security, Inc. Public-Key Cryptography Standards (PKCS)" in all +material mentioning or referencing this document. + + + +=============================================================================== +=============================================================================== + + + +Notice for Apache Yoko +====================== + +This distribution may contain software that is based in part on Apache Yoko +for which the following notice applies: + +Apache Yoko is an effort undergoing incubation at the Apache Software +Foundation (ASF). Incubation is required of all newly accepted projects until +a further review indicates that the infrastructure, communications, and decision +making process have stabilized in a manner consistent with other successful +ASF projects. While incubation status is not necessarily a reflection of the +completeness or stability of the code, it does indicate that the project has +yet to be fully endorsed by the ASF. + +http://incubator.apache.org/yoko/ + + + +=============================================================================== +=============================================================================== + + + +Notice for the Eclipse JDT Core Batch Compiler +============================================== + +The license terms for the Eclipse JDT Core Batch Compiler are available at + http://www.eclipse.org/legal/epl-v10.html + + +Source code for the Eclipse JDT Core Batch Compiler can be found at: + http://download.eclipse.org/eclipse/downloads/ + +Navigate to the version of ECJ used in this distribution, and the source is +provided in a ZIP file in the section titled "JDT Core Batch Compiler". + + + +=============================================================================== +=============================================================================== + + + +License notice for the DejaVu fonts package +============================================== + +Fonts are (c) Bitstream (see below). DejaVu changes are in public domain. +Glyphs imported from Arev fonts are (c) Tavmjung Bah (see below) + +Bitstream Vera Fonts Copyright +------------------------------ + +Copyright (c) 2003 by Bitstream, Inc. All Rights Reserved. Bitstream Vera is +a trademark of Bitstream, Inc. + +Permission is hereby granted, free of charge, to any person obtaining a copy +of the fonts accompanying this license ("Fonts") and associated +documentation files (the "Font Software"), to reproduce and distribute the +Font Software, including without limitation the rights to use, copy, merge, +publish, distribute, and/or sell copies of the Font Software, and to permit +persons to whom the Font Software is furnished to do so, subject to the +following conditions: + +The above copyright and trademark notices and this permission notice shall +be included in all copies of one or more of the Font Software typefaces. + +The Font Software may be modified, altered, or added to, and in particular +the designs of glyphs or characters in the Fonts may be modified and +additional glyphs or characters may be added to the Fonts, only if the fonts +are renamed to names not containing either the words "Bitstream" or the word +"Vera". + +This License becomes null and void to the extent applicable to Fonts or Font +Software that has been modified and is distributed under the "Bitstream +Vera" names. + +The Font Software may be sold as part of a larger software package but no +copy of one or more of the Font Software typefaces may be sold by itself. + +THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF COPYRIGHT, PATENT, +TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL BITSTREAM OR THE GNOME +FOUNDATION BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, INCLUDING +ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL DAMAGES, +WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF +THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM OTHER DEALINGS IN THE +FONT SOFTWARE. + +Except as contained in this notice, the names of Gnome, the Gnome +Foundation, and Bitstream Inc., shall not be used in advertising or +otherwise to promote the sale, use or other dealings in this Font Software +without prior written authorization from the Gnome Foundation or Bitstream +Inc., respectively. For further information, contact: fonts at gnome dot +org. + +Arev Fonts Copyright +------------------------------ + +Copyright (c) 2006 by Tavmjong Bah. All Rights Reserved. + +Permission is hereby granted, free of charge, to any person obtaining +a copy of the fonts accompanying this license ("Fonts") and +associated documentation files (the "Font Software"), to reproduce +and distribute the modifications to the Bitstream Vera Font Software, +including without limitation the rights to use, copy, merge, publish, +distribute, and/or sell copies of the Font Software, and to permit +persons to whom the Font Software is furnished to do so, subject to +the following conditions: + +The above copyright and trademark notices and this permission notice +shall be included in all copies of one or more of the Font Software +typefaces. + +The Font Software may be modified, altered, or added to, and in +particular the designs of glyphs or characters in the Fonts may be +modified and additional glyphs or characters may be added to the +Fonts, only if the fonts are renamed to names not containing either +the words "Tavmjong Bah" or the word "Arev". + +This License becomes null and void to the extent applicable to Fonts +or Font Software that has been modified and is distributed under the +"Tavmjong Bah Arev" names. + +The Font Software may be sold as part of a larger software package but +no copy of one or more of the Font Software typefaces may be sold by +itself. + +THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT +OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL +TAVMJONG BAH BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL +DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM +OTHER DEALINGS IN THE FONT SOFTWARE. + +Except as contained in this notice, the name of Tavmjong Bah shall not +be used in advertising or otherwise to promote the sale, use or other +dealings in this Font Software without prior written authorization +from Tavmjong Bah. For further information, contact: tavmjong @ free +. fr. + + + +=============================================================================== +=============================================================================== + + + +License notice for ASM +======================= + + ASM: a very small and fast Java bytecode manipulation framework + Copyright (c) 2000-2005 INRIA, France Telecom + All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + 3. Neither the name of the copyright holders nor the names of its + contributors may be used to endorse or promote products derived from + this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF + THE POSSIBILITY OF SUCH DAMAGE. + + + +=============================================================================== +=============================================================================== + + + +License notice for Junit +======================== + +This distribution may contain a jar file based on Junit 4.2.1 for +which the following notice applies: + +Copyright 2001-2009 Kent Beck +Copyright 2000-2009 Erich Gamma +Copyright 2006-2009 David Saff + + Common Public License - v 1.0 + +THE ACCOMPANYING PROGRAM IS PROVIDED UNDER THE TERMS OF THIS COMMON PUBLIC +LICENSE ("AGREEMENT"). ANY USE, REPRODUCTION OR DISTRIBUTION OF THE PROGRAM +CONSTITUTES RECIPIENT'S ACCEPTANCE OF THIS AGREEMENT. + +1. DEFINITIONS + +"Contribution" means: + + a) in the case of the initial Contributor, the initial code and + documentation distributed under this Agreement, and + b) in the case of each subsequent Contributor: + + i) changes to the Program, and + + ii) additions to the Program; + + where such changes and/or additions to the Program originate from and are + distributed by that particular Contributor. A Contribution 'originates' + from a Contributor if it was added to the Program by such Contributor + itself or anyone acting on such Contributor's behalf. Contributions do not + include additions to the Program which: (i) are separate modules of + software distributed in conjunction with the Program under their own + license agreement, and (ii) are not derivative works of the Program. + +"Contributor" means any person or entity that distributes the Program. + +"Licensed Patents " mean patent claims licensable by a Contributor which are +necessarily infringed by the use or sale of its Contribution alone or when +combined with the Program. + +"Program" means the Contributions distributed in accordance with this +Agreement. + +"Recipient" means anyone who receives the Program under this Agreement, +including all Contributors. + +2. GRANT OF RIGHTS + + a) Subject to the terms of this Agreement, each Contributor hereby grants + Recipient a non-exclusive, worldwide, royalty-free copyright license to + reproduce, prepare derivative works of, publicly display, publicly perform, + distribute and sublicense the Contribution of such Contributor, if any, and + such derivative works, in source code and object code form. + + b) Subject to the terms of this Agreement, each Contributor hereby grants + Recipient a non-exclusive, worldwide, royalty-free patent license under + Licensed Patents to make, use, sell, offer to sell, import and otherwise + transfer the Contribution of such Contributor, if any, in source code and + object code form. This patent license shall apply to the combination of the + Contribution and the Program if, at the time the Contribution is added by + the Contributor, such addition of the Contribution causes such combination + to be covered by the Licensed Patents. The patent license shall not apply + to any other combinations which include the Contribution. No hardware per + se is licensed hereunder. + + c) Recipient understands that although each Contributor grants the licenses + to its Contributions set forth herein, no assurances are provided by any + Contributor that the Program does not infringe the patent or other + intellectual property rights of any other entity. Each Contributor + disclaims any liability to Recipient for claims brought by any other entity + based on infringement of intellectual property rights or otherwise. As a + condition to exercising the rights and licenses granted hereunder, each + Recipient hereby assumes sole responsibility to secure any other + intellectual property rights needed, if any. For example, if a third party + patent license is required to allow Recipient to distribute the Program, it + is Recipient's responsibility to acquire that license before distributing + the Program. + + d) Each Contributor represents that to its knowledge it has sufficient + copyright rights in its Contribution, if any, to grant the copyright + license set forth in this Agreement. + +3. REQUIREMENTS + +A Contributor may choose to distribute the Program in object code form under +its own license agreement, provided that: + + a) it complies with the terms and conditions of this Agreement; and + + b) its license agreement: + + i) effectively disclaims on behalf of all Contributors all warranties and + conditions, express and implied, including warranties or conditions of + title and non-infringement, and implied warranties or conditions of + merchantability and fitness for a particular purpose; + + ii) effectively excludes on behalf of all Contributors all liability for + damages, including direct, indirect, special, incidental and consequential + damages, such as lost profits; + + iii) states that any provisions which differ from this Agreement are + offered by that Contributor alone and not by any other party; and + + iv) states that source code for the Program is available from such + Contributor, and informs licensees how to obtain it in a reasonable manner + on or through a medium customarily used for software exchange. + +When the Program is made available in source code form: + + a) it must be made available under this Agreement; and + + b) a copy of this Agreement must be included with each copy of the Program. + + +Contributors may not remove or alter any copyright notices contained +within the Program. + +Each Contributor must identify itself as the originator of its Contribution, if +any, in a manner that reasonably allows subsequent Recipients to identify the +originator of the Contribution. + +4. COMMERCIAL DISTRIBUTION + +Commercial distributors of software may accept certain responsibilities with +respect to end users, business partners and the like. While this license is +intended to facilitate the commercial use of the Program, the Contributor who +includes the Program in a commercial product offering should do so in a manner +which does not create potential liability for other Contributors. Therefore, if +a Contributor includes the Program in a commercial product offering, such +Contributor ("Commercial Contributor") hereby agrees to defend and indemnify +every other Contributor ("Indemnified Contributor") against any losses, damages +and costs (collectively "Losses") arising from claims, lawsuits and other legal +actions brought by a third party against the Indemnified Contributor to the +extent caused by the acts or omissions of such Commercial Contributor in +connection with its distribution of the Program in a commercial product +offering. The obligations in this section do not apply to any claims or Losses +relating to any actual or alleged intellectual property infringement. In order +to qualify, an Indemnified Contributor must: a) promptly notify the Commercial +Contributor in writing of such claim, and b) allow the Commercial Contributor +to control, and cooperate with the Commercial Contributor in, the defense and +any related settlement negotiations. The Indemnified Contributor may +participate in any such claim at its own expense. + +For example, a Contributor might include the Program in a commercial product +offering, Product X. That Contributor is then a Commercial Contributor. If that +Commercial Contributor then makes performance claims, or offers warranties +related to Product X, those performance claims and warranties are such +Commercial Contributor's responsibility alone. Under this section, the +Commercial Contributor would have to defend claims against the other +Contributors related to those performance claims and warranties, and if a court +requires any other Contributor to pay any damages as a result, the Commercial +Contributor must pay those damages. + +5. NO WARRANTY + +EXCEPT AS EXPRESSLY SET FORTH IN THIS AGREEMENT, THE PROGRAM IS PROVIDED ON AN +"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, EITHER EXPRESS OR +IMPLIED INCLUDING, WITHOUT LIMITATION, ANY WARRANTIES OR CONDITIONS OF TITLE, +NON-INFRINGEMENT, MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. Each +Recipient is solely responsible for determining the appropriateness of using +and distributing the Program and assumes all risks associated with its exercise +of rights under this Agreement, including but not limited to the risks and +costs of program errors, compliance with applicable laws, damage to or loss of +data, programs or equipment, and unavailability or interruption of operations. + +6. DISCLAIMER OF LIABILITY + +EXCEPT AS EXPRESSLY SET FORTH IN THIS AGREEMENT, NEITHER RECIPIENT NOR ANY +CONTRIBUTORS SHALL HAVE ANY LIABILITY FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING WITHOUT LIMITATION LOST +PROFITS), HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, +STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY +WAY OUT OF THE USE OR DISTRIBUTION OF THE PROGRAM OR THE EXERCISE OF ANY RIGHTS +GRANTED HEREUNDER, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. + +7. GENERAL + +If any provision of this Agreement is invalid or unenforceable under applicable +law, it shall not affect the validity or enforceability of the remainder of the +terms of this Agreement, and without further action by the parties hereto, such +provision shall be reformed to the minimum extent necessary to make such +provision valid and enforceable. + +If Recipient institutes patent litigation against a Contributor with respect to +a patent applicable to software (including a cross-claim or counterclaim in a +lawsuit), then any patent licenses granted by that Contributor to such +Recipient under this Agreement shall terminate as of the date such litigation +is filed. In addition, if Recipient institutes patent litigation against any +entity (including a cross-claim or counterclaim in a lawsuit) alleging that the +Program itself (excluding combinations of the Program with other software or +hardware) infringes such Recipient's patent(s), then such Recipient's rights +granted under Section 2(b) shall terminate as of the date such litigation is +filed. + +All Recipient's rights under this Agreement shall terminate if it fails to +comply with any of the material terms or conditions of this Agreement and does +not cure such failure in a reasonable period of time after becoming aware of +such noncompliance. If all Recipient's rights under this Agreement terminate, +Recipient agrees to cease use and distribution of the Program as soon as +reasonably practicable. However, Recipient's obligations under this Agreement +and any licenses granted by Recipient relating to the Program shall continue +and survive. + +Everyone is permitted to copy and distribute copies of this Agreement, but in +order to avoid inconsistency the Agreement is copyrighted and may only be +modified in the following manner. The Agreement Steward reserves the right to +publish new versions (including revisions) of this Agreement from time to time. +No one other than the Agreement Steward has the right to modify this Agreement. +IBM is the initial Agreement Steward. IBM may assign the responsibility to +serve as the Agreement Steward to a suitable separate entity. Each new version +of the Agreement will be given a distinguishing version number. The Program +(including Contributions) may always be distributed subject to the version of +the Agreement under which it was received. In addition, after a new version of +the Agreement is published, Contributor may elect to distribute the Program +(including its Contributions) under the new version. Except as expressly stated +in Sections 2(a) and 2(b) above, Recipient receives no rights or licenses to +the intellectual property of any Contributor under this Agreement, whether +expressly, by implication, estoppel or otherwise. All rights in the Program not +expressly granted under this Agreement are reserved. + +This Agreement is governed by the laws of the State of New York and the +intellectual property laws of the United States of America. No party to this +Agreement will bring a legal action under this Agreement more than one year +after the cause of action arose. Each party waives its rights to a jury trial +in any resulting litigation. + + + +=============================================================================== +=============================================================================== + + + +The Apache Harmony DRLVM uses the Apache Portable Runtime which +includes a number of subcomponents with separate copyright notices and +license terms. Your use of the source code for the these subcomponents +is subject to the terms and conditions of the following licenses. + +From strings/apr_fnmatch.c, include/apr_fnmatch.h, misc/unix/getopt.c, +file_io/unix/mktemp.c, strings/apr_strings.c: + +/* + * Copyright (c) 1987, 1993, 1994 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + +From network_io/unix/inet_ntop.c, network_io/unix/inet_pton.c: + +/* Copyright (c) 1996 by Internet Software Consortium. + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS + * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE + * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS + * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS + * SOFTWARE. + +From dso/aix/dso.c: + + * Based on libdl (dlfcn.c/dlfcn.h) which is + * Copyright (c) 1992,1993,1995,1996,1997,1988 + * Jens-Uwe Mager, Helios Software GmbH, Hannover, Germany. + * + * Not derived from licensed software. + * + * Permission is granted to freely use, copy, modify, and redistribute + * this software, provided that the author is not construed to be liable + * for any results of using the software, alterations are clearly marked + * as such, and this notice is not modified. + +From strings/apr_strnatcmp.c, include/apr_strings.h: + + strnatcmp.c -- Perform 'natural order' comparisons of strings in C. + Copyright (C) 2000 by Martin Pool + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. + +From strings/apr_snprintf.c: + + * + * cvt - IEEE floating point formatting routines. + * Derived from UNIX V7, Copyright(C) Caldera International Inc. + * + + Copyright(C) Caldera International Inc. 2001-2002. All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are + met: + + Redistributions of source code and documentation must retain the above + copyright notice, this list of conditions and the following disclaimer. + + Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + All advertising materials mentioning features or use of this software + must display the following acknowledgement: + + This product includes software developed or owned by Caldera + International, Inc. + + Neither the name of Caldera International, Inc. nor the names of other + contributors may be used to endorse or promote products derived from + this software without specific prior written permission. + + USE OF THE SOFTWARE PROVIDED FOR UNDER THIS LICENSE BY CALDERA + INTERNATIONAL, INC. AND CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED + WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN + NO EVENT SHALL CALDERA INTERNATIONAL, INC. BE LIABLE FOR ANY DIRECT, + INDIRECT INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. + + + +=============================================================================== +=============================================================================== + + + +License notice for Hamcrest +=========================== + +BSD License + +Copyright (c) 2000-2006, www.hamcrest.org +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + +Redistributions of source code must retain the above copyright notice, this list of +conditions and the following disclaimer. Redistributions in binary form must reproduce +the above copyright notice, this list of conditions and the following disclaimer in +the documentation and/or other materials provided with the distribution. + +Neither the name of Hamcrest nor the names of its contributors may be used to endorse +or promote products derived from this software without specific prior written +permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY +EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES +OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT +SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED +TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR +BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY +WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH +DAMAGE. + + + +=============================================================================== +=============================================================================== diff --git a/kotlin-native/licenses/third_party/jshashtable_license.txt b/kotlin-native/licenses/third_party/jshashtable_license.txt new file mode 100644 index 00000000000..cd6d0f6bca6 --- /dev/null +++ b/kotlin-native/licenses/third_party/jshashtable_license.txt @@ -0,0 +1,15 @@ +/** + * Copyright 2010 Tim Down. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ \ No newline at end of file diff --git a/kotlin-native/licenses/third_party/json_LICENSE.txt b/kotlin-native/licenses/third_party/json_LICENSE.txt new file mode 100644 index 00000000000..9be5071d079 --- /dev/null +++ b/kotlin-native/licenses/third_party/json_LICENSE.txt @@ -0,0 +1,23 @@ +JSON + +Copyright (c) 2002 JSON.org + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +The Software shall be used for Good, not Evil. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/kotlin-native/licenses/third_party/libffi_license.txt b/kotlin-native/licenses/third_party/libffi_license.txt new file mode 100644 index 00000000000..a66fab4f25a --- /dev/null +++ b/kotlin-native/licenses/third_party/libffi_license.txt @@ -0,0 +1,21 @@ +libffi - Copyright (c) 1996-2014 Anthony Green, Red Hat, Inc and others. +See source files for details. + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +``Software''), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/kotlin-native/licenses/third_party/llvm_license.txt b/kotlin-native/licenses/third_party/llvm_license.txt new file mode 100644 index 00000000000..c278f2c9283 --- /dev/null +++ b/kotlin-native/licenses/third_party/llvm_license.txt @@ -0,0 +1,76 @@ +============================================================================== +libc++ License +============================================================================== + +The libc++ library is dual licensed under both the University of Illinois +"BSD-Like" license and the MIT license. As a user of this code you may choose +to use it under either license. As a contributor, you agree to allow your code +to be used under both. + +Full text of the relevant licenses is included below. + +============================================================================== + +University of Illinois/NCSA +Open Source License + +Copyright (c) 2009-2017 by the contributors listed in CREDITS.TXT + +All rights reserved. + +Developed by: + + LLVM Team + + University of Illinois at Urbana-Champaign + + http://llvm.org + +Permission is hereby granted, free of charge, to any person obtaining a copy of +this software and associated documentation files (the "Software"), to deal with +the Software without restriction, including without limitation the rights to +use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies +of the Software, and to permit persons to whom the Software is furnished to do +so, subject to the following conditions: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimers. + + * Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimers in the + documentation and/or other materials provided with the distribution. + + * Neither the names of the LLVM Team, University of Illinois at + Urbana-Champaign, nor the names of its contributors may be used to + endorse or promote products derived from this Software without specific + prior written permission. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS +FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +CONTRIBUTORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS WITH THE +SOFTWARE. + +============================================================================== + +Copyright (c) 2009-2014 by the contributors listed in CREDITS.TXT + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. diff --git a/kotlin-native/licenses/third_party/maven_LICENSE.txt b/kotlin-native/licenses/third_party/maven_LICENSE.txt new file mode 100644 index 00000000000..d6456956733 --- /dev/null +++ b/kotlin-native/licenses/third_party/maven_LICENSE.txt @@ -0,0 +1,202 @@ + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. diff --git a/kotlin-native/licenses/third_party/mimalloc_LICENSE.txt b/kotlin-native/licenses/third_party/mimalloc_LICENSE.txt new file mode 100644 index 00000000000..4151dbe4ab1 --- /dev/null +++ b/kotlin-native/licenses/third_party/mimalloc_LICENSE.txt @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2019 Microsoft Corporation, Daan Leijen + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/kotlin-native/licenses/third_party/pcollections_LICENSE.txt b/kotlin-native/licenses/third_party/pcollections_LICENSE.txt new file mode 100644 index 00000000000..345a0dad954 --- /dev/null +++ b/kotlin-native/licenses/third_party/pcollections_LICENSE.txt @@ -0,0 +1,19 @@ +Copyright (c) 2008 Harold Cooper + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. diff --git a/kotlin-native/licenses/third_party/prototype_license.txt b/kotlin-native/licenses/third_party/prototype_license.txt new file mode 100644 index 00000000000..dd3f40902fc --- /dev/null +++ b/kotlin-native/licenses/third_party/prototype_license.txt @@ -0,0 +1,16 @@ +Copyright (c) 2005-2010 Sam Stephenson + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. \ No newline at end of file diff --git a/kotlin-native/licenses/third_party/rhino_LICENSE.txt b/kotlin-native/licenses/third_party/rhino_LICENSE.txt new file mode 100644 index 00000000000..eb16d6f2084 --- /dev/null +++ b/kotlin-native/licenses/third_party/rhino_LICENSE.txt @@ -0,0 +1,851 @@ +The majority of Rhino is MPL 1.1 / GPL 2.0 dual licensed: + +The Mozilla Public License (http://www.mozilla.org/MPL/MPL-1.1.txt): +============================================================================ + MOZILLA PUBLIC LICENSE + Version 1.1 + + --------------- + + 1. Definitions. + + 1.0.1. "Commercial Use" means distribution or otherwise making the + Covered Code available to a third party. + + 1.1. "Contributor" means each entity that creates or contributes to + the creation of Modifications. + + 1.2. "Contributor Version" means the combination of the Original + Code, prior Modifications used by a Contributor, and the Modifications + made by that particular Contributor. + + 1.3. "Covered Code" means the Original Code or Modifications or the + combination of the Original Code and Modifications, in each case + including portions thereof. + + 1.4. "Electronic Distribution Mechanism" means a mechanism generally + accepted in the software development community for the electronic + transfer of data. + + 1.5. "Executable" means Covered Code in any form other than Source + Code. + + 1.6. "Initial Developer" means the individual or entity identified + as the Initial Developer in the Source Code notice required by Exhibit + A. + + 1.7. "Larger Work" means a work which combines Covered Code or + portions thereof with code not governed by the terms of this License. + + 1.8. "License" means this document. + + 1.8.1. "Licensable" means having the right to grant, to the maximum + extent possible, whether at the time of the initial grant or + subsequently acquired, any and all of the rights conveyed herein. + + 1.9. "Modifications" means any addition to or deletion from the + substance or structure of either the Original Code or any previous + Modifications. When Covered Code is released as a series of files, a + Modification is: + A. Any addition to or deletion from the contents of a file + containing Original Code or previous Modifications. + + B. Any new file that contains any part of the Original Code or + previous Modifications. + + 1.10. "Original Code" means Source Code of computer software code + which is described in the Source Code notice required by Exhibit A as + Original Code, and which, at the time of its release under this + License is not already Covered Code governed by this License. + + 1.10.1. "Patent Claims" means any patent claim(s), now owned or + hereafter acquired, including without limitation, method, process, + and apparatus claims, in any patent Licensable by grantor. + + 1.11. "Source Code" means the preferred form of the Covered Code for + making modifications to it, including all modules it contains, plus + any associated interface definition files, scripts used to control + compilation and installation of an Executable, or source code + differential comparisons against either the Original Code or another + well known, available Covered Code of the Contributor's choice. The + Source Code can be in a compressed or archival form, provided the + appropriate decompression or de-archiving software is widely available + for no charge. + + 1.12. "You" (or "Your") means an individual or a legal entity + exercising rights under, and complying with all of the terms of, this + License or a future version of this License issued under Section 6.1. + For legal entities, "You" includes any entity which controls, is + controlled by, or is under common control with You. For purposes of + this definition, "control" means (a) the power, direct or indirect, + to cause the direction or management of such entity, whether by + contract or otherwise, or (b) ownership of more than fifty percent + (50%) of the outstanding shares or beneficial ownership of such + entity. + + 2. Source Code License. + + 2.1. The Initial Developer Grant. + The Initial Developer hereby grants You a world-wide, royalty-free, + non-exclusive license, subject to third party intellectual property + claims: + (a) under intellectual property rights (other than patent or + trademark) Licensable by Initial Developer to use, reproduce, + modify, display, perform, sublicense and distribute the Original + Code (or portions thereof) with or without Modifications, and/or + as part of a Larger Work; and + + (b) under Patents Claims infringed by the making, using or + selling of Original Code, to make, have made, use, practice, + sell, and offer for sale, and/or otherwise dispose of the + Original Code (or portions thereof). + + (c) the licenses granted in this Section 2.1(a) and (b) are + effective on the date Initial Developer first distributes + Original Code under the terms of this License. + + (d) Notwithstanding Section 2.1(b) above, no patent license is + granted: 1) for code that You delete from the Original Code; 2) + separate from the Original Code; or 3) for infringements caused + by: i) the modification of the Original Code or ii) the + combination of the Original Code with other software or devices. + + 2.2. Contributor Grant. + Subject to third party intellectual property claims, each Contributor + hereby grants You a world-wide, royalty-free, non-exclusive license + + (a) under intellectual property rights (other than patent or + trademark) Licensable by Contributor, to use, reproduce, modify, + display, perform, sublicense and distribute the Modifications + created by such Contributor (or portions thereof) either on an + unmodified basis, with other Modifications, as Covered Code + and/or as part of a Larger Work; and + + (b) under Patent Claims infringed by the making, using, or + selling of Modifications made by that Contributor either alone + and/or in combination with its Contributor Version (or portions + of such combination), to make, use, sell, offer for sale, have + made, and/or otherwise dispose of: 1) Modifications made by that + Contributor (or portions thereof); and 2) the combination of + Modifications made by that Contributor with its Contributor + Version (or portions of such combination). + + (c) the licenses granted in Sections 2.2(a) and 2.2(b) are + effective on the date Contributor first makes Commercial Use of + the Covered Code. + + (d) Notwithstanding Section 2.2(b) above, no patent license is + granted: 1) for any code that Contributor has deleted from the + Contributor Version; 2) separate from the Contributor Version; + 3) for infringements caused by: i) third party modifications of + Contributor Version or ii) the combination of Modifications made + by that Contributor with other software (except as part of the + Contributor Version) or other devices; or 4) under Patent Claims + infringed by Covered Code in the absence of Modifications made by + that Contributor. + + 3. Distribution Obligations. + + 3.1. Application of License. + The Modifications which You create or to which You contribute are + governed by the terms of this License, including without limitation + Section 2.2. The Source Code version of Covered Code may be + distributed only under the terms of this License or a future version + of this License released under Section 6.1, and You must include a + copy of this License with every copy of the Source Code You + distribute. You may not offer or impose any terms on any Source Code + version that alters or restricts the applicable version of this + License or the recipients' rights hereunder. However, You may include + an additional document offering the additional rights described in + Section 3.5. + + 3.2. Availability of Source Code. + Any Modification which You create or to which You contribute must be + made available in Source Code form under the terms of this License + either on the same media as an Executable version or via an accepted + Electronic Distribution Mechanism to anyone to whom you made an + Executable version available; and if made available via Electronic + Distribution Mechanism, must remain available for at least twelve (12) + months after the date it initially became available, or at least six + (6) months after a subsequent version of that particular Modification + has been made available to such recipients. You are responsible for + ensuring that the Source Code version remains available even if the + Electronic Distribution Mechanism is maintained by a third party. + + 3.3. Description of Modifications. + You must cause all Covered Code to which You contribute to contain a + file documenting the changes You made to create that Covered Code and + the date of any change. You must include a prominent statement that + the Modification is derived, directly or indirectly, from Original + Code provided by the Initial Developer and including the name of the + Initial Developer in (a) the Source Code, and (b) in any notice in an + Executable version or related documentation in which You describe the + origin or ownership of the Covered Code. + + 3.4. Intellectual Property Matters + (a) Third Party Claims. + If Contributor has knowledge that a license under a third party's + intellectual property rights is required to exercise the rights + granted by such Contributor under Sections 2.1 or 2.2, + Contributor must include a text file with the Source Code + distribution titled "LEGAL" which describes the claim and the + party making the claim in sufficient detail that a recipient will + know whom to contact. If Contributor obtains such knowledge after + the Modification is made available as described in Section 3.2, + Contributor shall promptly modify the LEGAL file in all copies + Contributor makes available thereafter and shall take other steps + (such as notifying appropriate mailing lists or newsgroups) + reasonably calculated to inform those who received the Covered + Code that new knowledge has been obtained. + + (b) Contributor APIs. + If Contributor's Modifications include an application programming + interface and Contributor has knowledge of patent licenses which + are reasonably necessary to implement that API, Contributor must + also include this information in the LEGAL file. + + (c) Representations. + Contributor represents that, except as disclosed pursuant to + Section 3.4(a) above, Contributor believes that Contributor's + Modifications are Contributor's original creation(s) and/or + Contributor has sufficient rights to grant the rights conveyed by + this License. + + 3.5. Required Notices. + You must duplicate the notice in Exhibit A in each file of the Source + Code. If it is not possible to put such notice in a particular Source + Code file due to its structure, then You must include such notice in a + location (such as a relevant directory) where a user would be likely + to look for such a notice. If You created one or more Modification(s) + You may add your name as a Contributor to the notice described in + Exhibit A. You must also duplicate this License in any documentation + for the Source Code where You describe recipients' rights or ownership + rights relating to Covered Code. You may choose to offer, and to + charge a fee for, warranty, support, indemnity or liability + obligations to one or more recipients of Covered Code. However, You + may do so only on Your own behalf, and not on behalf of the Initial + Developer or any Contributor. You must make it absolutely clear than + any such warranty, support, indemnity or liability obligation is + offered by You alone, and You hereby agree to indemnify the Initial + Developer and every Contributor for any liability incurred by the + Initial Developer or such Contributor as a result of warranty, + support, indemnity or liability terms You offer. + + 3.6. Distribution of Executable Versions. + You may distribute Covered Code in Executable form only if the + requirements of Section 3.1-3.5 have been met for that Covered Code, + and if You include a notice stating that the Source Code version of + the Covered Code is available under the terms of this License, + including a description of how and where You have fulfilled the + obligations of Section 3.2. The notice must be conspicuously included + in any notice in an Executable version, related documentation or + collateral in which You describe recipients' rights relating to the + Covered Code. You may distribute the Executable version of Covered + Code or ownership rights under a license of Your choice, which may + contain terms different from this License, provided that You are in + compliance with the terms of this License and that the license for the + Executable version does not attempt to limit or alter the recipient's + rights in the Source Code version from the rights set forth in this + License. If You distribute the Executable version under a different + license You must make it absolutely clear that any terms which differ + from this License are offered by You alone, not by the Initial + Developer or any Contributor. You hereby agree to indemnify the + Initial Developer and every Contributor for any liability incurred by + the Initial Developer or such Contributor as a result of any such + terms You offer. + + 3.7. Larger Works. + You may create a Larger Work by combining Covered Code with other code + not governed by the terms of this License and distribute the Larger + Work as a single product. In such a case, You must make sure the + requirements of this License are fulfilled for the Covered Code. + + 4. Inability to Comply Due to Statute or Regulation. + + If it is impossible for You to comply with any of the terms of this + License with respect to some or all of the Covered Code due to + statute, judicial order, or regulation then You must: (a) comply with + the terms of this License to the maximum extent possible; and (b) + describe the limitations and the code they affect. Such description + must be included in the LEGAL file described in Section 3.4 and must + be included with all distributions of the Source Code. Except to the + extent prohibited by statute or regulation, such description must be + sufficiently detailed for a recipient of ordinary skill to be able to + understand it. + + 5. Application of this License. + + This License applies to code to which the Initial Developer has + attached the notice in Exhibit A and to related Covered Code. + + 6. Versions of the License. + + 6.1. New Versions. + Netscape Communications Corporation ("Netscape") may publish revised + and/or new versions of the License from time to time. Each version + will be given a distinguishing version number. + + 6.2. Effect of New Versions. + Once Covered Code has been published under a particular version of the + License, You may always continue to use it under the terms of that + version. You may also choose to use such Covered Code under the terms + of any subsequent version of the License published by Netscape. No one + other than Netscape has the right to modify the terms applicable to + Covered Code created under this License. + + 6.3. Derivative Works. + If You create or use a modified version of this License (which you may + only do in order to apply it to code which is not already Covered Code + governed by this License), You must (a) rename Your license so that + the phrases "Mozilla", "MOZILLAPL", "MOZPL", "Netscape", + "MPL", "NPL" or any confusingly similar phrase do not appear in your + license (except to note that your license differs from this License) + and (b) otherwise make it clear that Your version of the license + contains terms which differ from the Mozilla Public License and + Netscape Public License. (Filling in the name of the Initial + Developer, Original Code or Contributor in the notice described in + Exhibit A shall not of themselves be deemed to be modifications of + this License.) + + 7. DISCLAIMER OF WARRANTY. + + COVERED CODE IS PROVIDED UNDER THIS LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, + WITHOUT LIMITATION, WARRANTIES THAT THE COVERED CODE IS FREE OF + DEFECTS, MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE OR NON-INFRINGING. + THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE COVERED CODE + IS WITH YOU. SHOULD ANY COVERED CODE PROVE DEFECTIVE IN ANY RESPECT, + YOU (NOT THE INITIAL DEVELOPER OR ANY OTHER CONTRIBUTOR) ASSUME THE + COST OF ANY NECESSARY SERVICING, REPAIR OR CORRECTION. THIS DISCLAIMER + OF WARRANTY CONSTITUTES AN ESSENTIAL PART OF THIS LICENSE. NO USE OF + ANY COVERED CODE IS AUTHORIZED HEREUNDER EXCEPT UNDER THIS DISCLAIMER. + + 8. TERMINATION. + + 8.1. This License and the rights granted hereunder will terminate + automatically if You fail to comply with terms herein and fail to cure + such breach within 30 days of becoming aware of the breach. All + sublicenses to the Covered Code which are properly granted shall + survive any termination of this License. Provisions which, by their + nature, must remain in effect beyond the termination of this License + shall survive. + + 8.2. If You initiate litigation by asserting a patent infringement + claim (excluding declatory judgment actions) against Initial Developer + or a Contributor (the Initial Developer or Contributor against whom + You file such action is referred to as "Participant") alleging that: + + (a) such Participant's Contributor Version directly or indirectly + infringes any patent, then any and all rights granted by such + Participant to You under Sections 2.1 and/or 2.2 of this License + shall, upon 60 days notice from Participant terminate prospectively, + unless if within 60 days after receipt of notice You either: (i) + agree in writing to pay Participant a mutually agreeable reasonable + royalty for Your past and future use of Modifications made by such + Participant, or (ii) withdraw Your litigation claim with respect to + the Contributor Version against such Participant. If within 60 days + of notice, a reasonable royalty and payment arrangement are not + mutually agreed upon in writing by the parties or the litigation claim + is not withdrawn, the rights granted by Participant to You under + Sections 2.1 and/or 2.2 automatically terminate at the expiration of + the 60 day notice period specified above. + + (b) any software, hardware, or device, other than such Participant's + Contributor Version, directly or indirectly infringes any patent, then + any rights granted to You by such Participant under Sections 2.1(b) + and 2.2(b) are revoked effective as of the date You first made, used, + sold, distributed, or had made, Modifications made by that + Participant. + + 8.3. If You assert a patent infringement claim against Participant + alleging that such Participant's Contributor Version directly or + indirectly infringes any patent where such claim is resolved (such as + by license or settlement) prior to the initiation of patent + infringement litigation, then the reasonable value of the licenses + granted by such Participant under Sections 2.1 or 2.2 shall be taken + into account in determining the amount or value of any payment or + license. + + 8.4. In the event of termination under Sections 8.1 or 8.2 above, + all end user license agreements (excluding distributors and resellers) + which have been validly granted by You or any distributor hereunder + prior to termination shall survive termination. + + 9. LIMITATION OF LIABILITY. + + UNDER NO CIRCUMSTANCES AND UNDER NO LEGAL THEORY, WHETHER TORT + (INCLUDING NEGLIGENCE), CONTRACT, OR OTHERWISE, SHALL YOU, THE INITIAL + DEVELOPER, ANY OTHER CONTRIBUTOR, OR ANY DISTRIBUTOR OF COVERED CODE, + OR ANY SUPPLIER OF ANY OF SUCH PARTIES, BE LIABLE TO ANY PERSON FOR + ANY INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES OF ANY + CHARACTER INCLUDING, WITHOUT LIMITATION, DAMAGES FOR LOSS OF GOODWILL, + WORK STOPPAGE, COMPUTER FAILURE OR MALFUNCTION, OR ANY AND ALL OTHER + COMMERCIAL DAMAGES OR LOSSES, EVEN IF SUCH PARTY SHALL HAVE BEEN + INFORMED OF THE POSSIBILITY OF SUCH DAMAGES. THIS LIMITATION OF + LIABILITY SHALL NOT APPLY TO LIABILITY FOR DEATH OR PERSONAL INJURY + RESULTING FROM SUCH PARTY'S NEGLIGENCE TO THE EXTENT APPLICABLE LAW + PROHIBITS SUCH LIMITATION. SOME JURISDICTIONS DO NOT ALLOW THE + EXCLUSION OR LIMITATION OF INCIDENTAL OR CONSEQUENTIAL DAMAGES, SO + THIS EXCLUSION AND LIMITATION MAY NOT APPLY TO YOU. + + 10. U.S. GOVERNMENT END USERS. + + The Covered Code is a "commercial item," as that term is defined in + 48 C.F.R. 2.101 (Oct. 1995), consisting of "commercial computer + software" and "commercial computer software documentation," as such + terms are used in 48 C.F.R. 12.212 (Sept. 1995). Consistent with 48 + C.F.R. 12.212 and 48 C.F.R. 227.7202-1 through 227.7202-4 (June 1995), + all U.S. Government End Users acquire Covered Code with only those + rights set forth herein. + + 11. MISCELLANEOUS. + + This License represents the complete agreement concerning subject + matter hereof. If any provision of this License is held to be + unenforceable, such provision shall be reformed only to the extent + necessary to make it enforceable. This License shall be governed by + California law provisions (except to the extent applicable law, if + any, provides otherwise), excluding its conflict-of-law provisions. + With respect to disputes in which at least one party is a citizen of, + or an entity chartered or registered to do business in the United + States of America, any litigation relating to this License shall be + subject to the jurisdiction of the Federal Courts of the Northern + District of California, with venue lying in Santa Clara County, + California, with the losing party responsible for costs, including + without limitation, court costs and reasonable attorneys' fees and + expenses. The application of the United Nations Convention on + Contracts for the International Sale of Goods is expressly excluded. + Any law or regulation which provides that the language of a contract + shall be construed against the drafter shall not apply to this + License. + + 12. RESPONSIBILITY FOR CLAIMS. + + As between Initial Developer and the Contributors, each party is + responsible for claims and damages arising, directly or indirectly, + out of its utilization of rights under this License and You agree to + work with Initial Developer and Contributors to distribute such + responsibility on an equitable basis. Nothing herein is intended or + shall be deemed to constitute any admission of liability. + + 13. MULTIPLE-LICENSED CODE. + + Initial Developer may designate portions of the Covered Code as + "Multiple-Licensed". "Multiple-Licensed" means that the Initial + Developer permits you to utilize portions of the Covered Code under + Your choice of the NPL or the alternative licenses, if any, specified + by the Initial Developer in the file described in Exhibit A. + + EXHIBIT A -Mozilla Public License. + + ``The contents of this file are subject to the Mozilla Public License + Version 1.1 (the "License"); you may not use this file except in + compliance with the License. You may obtain a copy of the License at + http://www.mozilla.org/MPL/ + + Software distributed under the License is distributed on an "AS IS" + basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the + License for the specific language governing rights and limitations + under the License. + + The Original Code is ______________________________________. + + The Initial Developer of the Original Code is ________________________. + Portions created by ______________________ are Copyright (C) ______ + _______________________. All Rights Reserved. + + Contributor(s): ______________________________________. + + Alternatively, the contents of this file may be used under the terms + of the _____ license (the "[___] License"), in which case the + provisions of [______] License are applicable instead of those + above. If you wish to allow use of your version of this file only + under the terms of the [____] License and not to allow others to use + your version of this file under the MPL, indicate your decision by + deleting the provisions above and replace them with the notice and + other provisions required by the [___] License. If you do not delete + the provisions above, a recipient may use your version of this file + under either the MPL or the [___] License." + + [NOTE: The text of this Exhibit A may differ slightly from the text of + the notices in the Source Code files of the Original Code. You should + use the text of this Exhibit A rather than the text found in the + Original Code Source Code for Your Modifications.] +============================================================================ + +============================================================================ + GNU GENERAL PUBLIC LICENSE + Version 2, June 1991 + + Copyright (C) 1989, 1991 Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The licenses for most software are designed to take away your + freedom to share and change it. By contrast, the GNU General Public + License is intended to guarantee your freedom to share and change free + software--to make sure the software is free for all its users. This + General Public License applies to most of the Free Software + Foundation's software and to any other program whose authors commit to + using it. (Some other Free Software Foundation software is covered by + the GNU Lesser General Public License instead.) You can apply it to + your programs, too. + + When we speak of free software, we are referring to freedom, not + price. Our General Public Licenses are designed to make sure that you + have the freedom to distribute copies of free software (and charge for + this service if you wish), that you receive source code or can get it + if you want it, that you can change the software or use pieces of it + in new free programs; and that you know you can do these things. + + To protect your rights, we need to make restrictions that forbid + anyone to deny you these rights or to ask you to surrender the rights. + These restrictions translate to certain responsibilities for you if you + distribute copies of the software, or if you modify it. + + For example, if you distribute copies of such a program, whether + gratis or for a fee, you must give the recipients all the rights that + you have. You must make sure that they, too, receive or can get the + source code. And you must show them these terms so they know their + rights. + + We protect your rights with two steps: (1) copyright the software, and + (2) offer you this license which gives you legal permission to copy, + distribute and/or modify the software. + + Also, for each author's protection and ours, we want to make certain + that everyone understands that there is no warranty for this free + software. If the software is modified by someone else and passed on, we + want its recipients to know that what they have is not the original, so + that any problems introduced by others will not reflect on the original + authors' reputations. + + Finally, any free program is threatened constantly by software + patents. We wish to avoid the danger that redistributors of a free + program will individually obtain patent licenses, in effect making the + program proprietary. To prevent this, we have made it clear that any + patent must be licensed for everyone's free use or not licensed at all. + + The precise terms and conditions for copying, distribution and + modification follow. + + GNU GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License applies to any program or other work which contains + a notice placed by the copyright holder saying it may be distributed + under the terms of this General Public License. The "Program", below, + refers to any such program or work, and a "work based on the Program" + means either the Program or any derivative work under copyright law: + that is to say, a work containing the Program or a portion of it, + either verbatim or with modifications and/or translated into another + language. (Hereinafter, translation is included without limitation in + the term "modification".) Each licensee is addressed as "you". + + Activities other than copying, distribution and modification are not + covered by this License; they are outside its scope. The act of + running the Program is not restricted, and the output from the Program + is covered only if its contents constitute a work based on the + Program (independent of having been made by running the Program). + Whether that is true depends on what the Program does. + + 1. You may copy and distribute verbatim copies of the Program's + source code as you receive it, in any medium, provided that you + conspicuously and appropriately publish on each copy an appropriate + copyright notice and disclaimer of warranty; keep intact all the + notices that refer to this License and to the absence of any warranty; + and give any other recipients of the Program a copy of this License + along with the Program. + + You may charge a fee for the physical act of transferring a copy, and + you may at your option offer warranty protection in exchange for a fee. + + 2. You may modify your copy or copies of the Program or any portion + of it, thus forming a work based on the Program, and copy and + distribute such modifications or work under the terms of Section 1 + above, provided that you also meet all of these conditions: + + a) You must cause the modified files to carry prominent notices + stating that you changed the files and the date of any change. + + b) You must cause any work that you distribute or publish, that in + whole or in part contains or is derived from the Program or any + part thereof, to be licensed as a whole at no charge to all third + parties under the terms of this License. + + c) If the modified program normally reads commands interactively + when run, you must cause it, when started running for such + interactive use in the most ordinary way, to print or display an + announcement including an appropriate copyright notice and a + notice that there is no warranty (or else, saying that you provide + a warranty) and that users may redistribute the program under + these conditions, and telling the user how to view a copy of this + License. (Exception: if the Program itself is interactive but + does not normally print such an announcement, your work based on + the Program is not required to print an announcement.) + + These requirements apply to the modified work as a whole. If + identifiable sections of that work are not derived from the Program, + and can be reasonably considered independent and separate works in + themselves, then this License, and its terms, do not apply to those + sections when you distribute them as separate works. But when you + distribute the same sections as part of a whole which is a work based + on the Program, the distribution of the whole must be on the terms of + this License, whose permissions for other licensees extend to the + entire whole, and thus to each and every part regardless of who wrote it. + + Thus, it is not the intent of this section to claim rights or contest + your rights to work written entirely by you; rather, the intent is to + exercise the right to control the distribution of derivative or + collective works based on the Program. + + In addition, mere aggregation of another work not based on the Program + with the Program (or with a work based on the Program) on a volume of + a storage or distribution medium does not bring the other work under + the scope of this License. + + 3. You may copy and distribute the Program (or a work based on it, + under Section 2) in object code or executable form under the terms of + Sections 1 and 2 above provided that you also do one of the following: + + a) Accompany it with the complete corresponding machine-readable + source code, which must be distributed under the terms of Sections + 1 and 2 above on a medium customarily used for software interchange; or, + + b) Accompany it with a written offer, valid for at least three + years, to give any third party, for a charge no more than your + cost of physically performing source distribution, a complete + machine-readable copy of the corresponding source code, to be + distributed under the terms of Sections 1 and 2 above on a medium + customarily used for software interchange; or, + + c) Accompany it with the information you received as to the offer + to distribute corresponding source code. (This alternative is + allowed only for noncommercial distribution and only if you + received the program in object code or executable form with such + an offer, in accord with Subsection b above.) + + The source code for a work means the preferred form of the work for + making modifications to it. For an executable work, complete source + code means all the source code for all modules it contains, plus any + associated interface definition files, plus the scripts used to + control compilation and installation of the executable. However, as a + special exception, the source code distributed need not include + anything that is normally distributed (in either source or binary + form) with the major components (compiler, kernel, and so on) of the + operating system on which the executable runs, unless that component + itself accompanies the executable. + + If distribution of executable or object code is made by offering + access to copy from a designated place, then offering equivalent + access to copy the source code from the same place counts as + distribution of the source code, even though third parties are not + compelled to copy the source along with the object code. + + 4. You may not copy, modify, sublicense, or distribute the Program + except as expressly provided under this License. Any attempt + otherwise to copy, modify, sublicense or distribute the Program is + void, and will automatically terminate your rights under this License. + However, parties who have received copies, or rights, from you under + this License will not have their licenses terminated so long as such + parties remain in full compliance. + + 5. You are not required to accept this License, since you have not + signed it. However, nothing else grants you permission to modify or + distribute the Program or its derivative works. These actions are + prohibited by law if you do not accept this License. Therefore, by + modifying or distributing the Program (or any work based on the + Program), you indicate your acceptance of this License to do so, and + all its terms and conditions for copying, distributing or modifying + the Program or works based on it. + + 6. Each time you redistribute the Program (or any work based on the + Program), the recipient automatically receives a license from the + original licensor to copy, distribute or modify the Program subject to + these terms and conditions. You may not impose any further + restrictions on the recipients' exercise of the rights granted herein. + You are not responsible for enforcing compliance by third parties to + this License. + + 7. If, as a consequence of a court judgment or allegation of patent + infringement or for any other reason (not limited to patent issues), + conditions are imposed on you (whether by court order, agreement or + otherwise) that contradict the conditions of this License, they do not + excuse you from the conditions of this License. If you cannot + distribute so as to satisfy simultaneously your obligations under this + License and any other pertinent obligations, then as a consequence you + may not distribute the Program at all. For example, if a patent + license would not permit royalty-free redistribution of the Program by + all those who receive copies directly or indirectly through you, then + the only way you could satisfy both it and this License would be to + refrain entirely from distribution of the Program. + + If any portion of this section is held invalid or unenforceable under + any particular circumstance, the balance of the section is intended to + apply and the section as a whole is intended to apply in other + circumstances. + + It is not the purpose of this section to induce you to infringe any + patents or other property right claims or to contest validity of any + such claims; this section has the sole purpose of protecting the + integrity of the free software distribution system, which is + implemented by public license practices. Many people have made + generous contributions to the wide range of software distributed + through that system in reliance on consistent application of that + system; it is up to the author/donor to decide if he or she is willing + to distribute software through any other system and a licensee cannot + impose that choice. + + This section is intended to make thoroughly clear what is believed to + be a consequence of the rest of this License. + + 8. If the distribution and/or use of the Program is restricted in + certain countries either by patents or by copyrighted interfaces, the + original copyright holder who places the Program under this License + may add an explicit geographical distribution limitation excluding + those countries, so that distribution is permitted only in or among + countries not thus excluded. In such case, this License incorporates + the limitation as if written in the body of this License. + + 9. The Free Software Foundation may publish revised and/or new versions + of the General Public License from time to time. Such new versions will + be similar in spirit to the present version, but may differ in detail to + address new problems or concerns. + + Each version is given a distinguishing version number. If the Program + specifies a version number of this License which applies to it and "any + later version", you have the option of following the terms and conditions + either of that version or of any later version published by the Free + Software Foundation. If the Program does not specify a version number of + this License, you may choose any version ever published by the Free Software + Foundation. + + 10. If you wish to incorporate parts of the Program into other free + programs whose distribution conditions are different, write to the author + to ask for permission. For software which is copyrighted by the Free + Software Foundation, write to the Free Software Foundation; we sometimes + make exceptions for this. Our decision will be guided by the two goals + of preserving the free status of all derivatives of our free software and + of promoting the sharing and reuse of software generally. + + NO WARRANTY + + 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY + FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN + OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES + PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED + OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS + TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE + PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, + REPAIR OR CORRECTION. + + 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING + WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR + REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, + INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING + OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED + TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY + YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER + PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE + POSSIBILITY OF SUCH DAMAGES. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest + possible use to the public, the best way to achieve this is to make it + free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest + to attach them to the start of each source file to most effectively + convey the exclusion of warranty; and each file should have at least + the "copyright" line and a pointer to where the full notice is found. + + + Copyright (C) + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along + with this program; if not, write to the Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + + Also add information on how to contact you by electronic and paper mail. + + If the program is interactive, make it output a short notice like this + when it starts in an interactive mode: + + Gnomovision version 69, Copyright (C) year name of author + Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + + The hypothetical commands `show w' and `show c' should show the appropriate + parts of the General Public License. Of course, the commands you use may + be called something other than `show w' and `show c'; they could even be + mouse-clicks or menu items--whatever suits your program. + + You should also get your employer (if you work as a programmer) or your + school, if any, to sign a "copyright disclaimer" for the program, if + necessary. Here is a sample; alter the names: + + Yoyodyne, Inc., hereby disclaims all copyright interest in the program + `Gnomovision' (which makes passes at compilers) written by James Hacker. + + , 1 April 1989 + Ty Coon, President of Vice + + This General Public License does not permit incorporating your program into + proprietary programs. If your program is a subroutine library, you may + consider it more useful to permit linking proprietary applications with the + library. If this is what you want to do, use the GNU Lesser General + Public License instead of this License. +============================================================================ + +Additionally, some files (currently the contents of +toolsrc/org/mozilla/javascript/tools/debugger/treetable/) are available +only under the following license: + +============================================================================ + * Copyright 1997, 1998 Sun Microsystems, Inc. All Rights Reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * - Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * - Neither the name of Sun Microsystems nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS + * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +============================================================================ diff --git a/kotlin-native/licenses/third_party/scala_license.txt b/kotlin-native/licenses/third_party/scala_license.txt new file mode 100644 index 00000000000..7863fb0f7e1 --- /dev/null +++ b/kotlin-native/licenses/third_party/scala_license.txt @@ -0,0 +1,35 @@ +SCALA LICENSE + +Copyright (c) 2002-2012 EPFL, Lausanne, unless otherwise specified. +All rights reserved. + +This software was developed by the Programming Methods Laboratory of the +Swiss Federal Institute of Technology (EPFL), Lausanne, Switzerland. + +Permission to use, copy, modify, and distribute this software in source +or binary form for any purpose with or without fee is hereby granted, +provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + 3. Neither the name of the EPFL nor the names of its contributors + may be used to endorse or promote products derived from this + software without specific prior written permission. + + +THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +SUCH DAMAGE. \ No newline at end of file diff --git a/kotlin-native/licenses/third_party/sdl_license.txt b/kotlin-native/licenses/third_party/sdl_license.txt new file mode 100644 index 00000000000..61f6da39d81 --- /dev/null +++ b/kotlin-native/licenses/third_party/sdl_license.txt @@ -0,0 +1,17 @@ +SDL 2.0 and newer are available under the zlib license : + +This software is provided 'as-is', without any express or implied +warranty. In no event will the authors be held liable for any damages +arising from the use of this software. + +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute it +freely, subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. +2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. +3. This notice may not be removed or altered from any source distribution. diff --git a/kotlin-native/licenses/third_party/trove_license.txt b/kotlin-native/licenses/third_party/trove_license.txt new file mode 100644 index 00000000000..583509c7efb --- /dev/null +++ b/kotlin-native/licenses/third_party/trove_license.txt @@ -0,0 +1,504 @@ + GNU LESSER GENERAL PUBLIC LICENSE + Version 2.1, February 1999 + + Copyright (C) 1991, 1999 Free Software Foundation, Inc. + 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + +[This is the first released version of the Lesser GPL. It also counts + as the successor of the GNU Library Public License, version 2, hence + the version number 2.1.] + + Preamble + + The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +Licenses are intended to guarantee your freedom to share and change +free software--to make sure the software is free for all its users. + + This license, the Lesser General Public License, applies to some +specially designated software packages--typically libraries--of the +Free Software Foundation and other authors who decide to use it. You +can use it too, but we suggest you first think carefully about whether +this license or the ordinary General Public License is the better +strategy to use in any particular case, based on the explanations below. + + When we speak of free software, we are referring to freedom of use, +not price. Our General Public Licenses are designed to make sure that +you have the freedom to distribute copies of free software (and charge +for this service if you wish); that you receive source code or can get +it if you want it; that you can change the software and use pieces of +it in new free programs; and that you are informed that you can do +these things. + + To protect your rights, we need to make restrictions that forbid +distributors to deny you these rights or to ask you to surrender these +rights. These restrictions translate to certain responsibilities for +you if you distribute copies of the library or if you modify it. + + For example, if you distribute copies of the library, whether gratis +or for a fee, you must give the recipients all the rights that we gave +you. You must make sure that they, too, receive or can get the source +code. If you link other code with the library, you must provide +complete object files to the recipients, so that they can relink them +with the library after making changes to the library and recompiling +it. And you must show them these terms so they know their rights. + + We protect your rights with a two-step method: (1) we copyright the +library, and (2) we offer you this license, which gives you legal +permission to copy, distribute and/or modify the library. + + To protect each distributor, we want to make it very clear that +there is no warranty for the free library. Also, if the library is +modified by someone else and passed on, the recipients should know +that what they have is not the original version, so that the original +author's reputation will not be affected by problems that might be +introduced by others. + + Finally, software patents pose a constant threat to the existence of +any free program. We wish to make sure that a company cannot +effectively restrict the users of a free program by obtaining a +restrictive license from a patent holder. Therefore, we insist that +any patent license obtained for a version of the library must be +consistent with the full freedom of use specified in this license. + + Most GNU software, including some libraries, is covered by the +ordinary GNU General Public License. This license, the GNU Lesser +General Public License, applies to certain designated libraries, and +is quite different from the ordinary General Public License. We use +this license for certain libraries in order to permit linking those +libraries into non-free programs. + + When a program is linked with a library, whether statically or using +a shared library, the combination of the two is legally speaking a +combined work, a derivative of the original library. The ordinary +General Public License therefore permits such linking only if the +entire combination fits its criteria of freedom. The Lesser General +Public License permits more lax criteria for linking other code with +the library. + + We call this license the "Lesser" General Public License because it +does Less to protect the user's freedom than the ordinary General +Public License. It also provides other free software developers Less +of an advantage over competing non-free programs. These disadvantages +are the reason we use the ordinary General Public License for many +libraries. However, the Lesser license provides advantages in certain +special circumstances. + + For example, on rare occasions, there may be a special need to +encourage the widest possible use of a certain library, so that it becomes +a de-facto standard. To achieve this, non-free programs must be +allowed to use the library. A more frequent case is that a free +library does the same job as widely used non-free libraries. In this +case, there is little to gain by limiting the free library to free +software only, so we use the Lesser General Public License. + + In other cases, permission to use a particular library in non-free +programs enables a greater number of people to use a large body of +free software. For example, permission to use the GNU C Library in +non-free programs enables many more people to use the whole GNU +operating system, as well as its variant, the GNU/Linux operating +system. + + Although the Lesser General Public License is Less protective of the +users' freedom, it does ensure that the user of a program that is +linked with the Library has the freedom and the wherewithal to run +that program using a modified version of the Library. + + The precise terms and conditions for copying, distribution and +modification follow. Pay close attention to the difference between a +"work based on the library" and a "work that uses the library". The +former contains code derived from the library, whereas the latter must +be combined with the library in order to run. + + GNU LESSER GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License Agreement applies to any software library or other +program which contains a notice placed by the copyright holder or +other authorized party saying it may be distributed under the terms of +this Lesser General Public License (also called "this License"). +Each licensee is addressed as "you". + + A "library" means a collection of software functions and/or data +prepared so as to be conveniently linked with application programs +(which use some of those functions and data) to form executables. + + The "Library", below, refers to any such software library or work +which has been distributed under these terms. A "work based on the +Library" means either the Library or any derivative work under +copyright law: that is to say, a work containing the Library or a +portion of it, either verbatim or with modifications and/or translated +straightforwardly into another language. (Hereinafter, translation is +included without limitation in the term "modification".) + + "Source code" for a work means the preferred form of the work for +making modifications to it. For a library, complete source code means +all the source code for all modules it contains, plus any associated +interface definition files, plus the scripts used to control compilation +and installation of the library. + + Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running a program using the Library is not restricted, and output from +such a program is covered only if its contents constitute a work based +on the Library (independent of the use of the Library in a tool for +writing it). Whether that is true depends on what the Library does +and what the program that uses the Library does. + + 1. You may copy and distribute verbatim copies of the Library's +complete source code as you receive it, in any medium, provided that +you conspicuously and appropriately publish on each copy an +appropriate copyright notice and disclaimer of warranty; keep intact +all the notices that refer to this License and to the absence of any +warranty; and distribute a copy of this License along with the +Library. + + You may charge a fee for the physical act of transferring a copy, +and you may at your option offer warranty protection in exchange for a +fee. + + 2. You may modify your copy or copies of the Library or any portion +of it, thus forming a work based on the Library, and copy and +distribute such modifications or work under the terms of Section 1 +above, provided that you also meet all of these conditions: + + a) The modified work must itself be a software library. + + b) You must cause the files modified to carry prominent notices + stating that you changed the files and the date of any change. + + c) You must cause the whole of the work to be licensed at no + charge to all third parties under the terms of this License. + + d) If a facility in the modified Library refers to a function or a + table of data to be supplied by an application program that uses + the facility, other than as an argument passed when the facility + is invoked, then you must make a good faith effort to ensure that, + in the event an application does not supply such function or + table, the facility still operates, and performs whatever part of + its purpose remains meaningful. + + (For example, a function in a library to compute square roots has + a purpose that is entirely well-defined independent of the + application. Therefore, Subsection 2d requires that any + application-supplied function or table used by this function must + be optional: if the application does not supply it, the square + root function must still compute square roots.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Library, +and can be reasonably considered independent and separate works in +themselves, then this License, and its terms, do not apply to those +sections when you distribute them as separate works. But when you +distribute the same sections as part of a whole which is a work based +on the Library, the distribution of the whole must be on the terms of +this License, whose permissions for other licensees extend to the +entire whole, and thus to each and every part regardless of who wrote +it. + +Thus, it is not the intent of this section to claim rights or contest +your rights to work written entirely by you; rather, the intent is to +exercise the right to control the distribution of derivative or +collective works based on the Library. + +In addition, mere aggregation of another work not based on the Library +with the Library (or with a work based on the Library) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + 3. You may opt to apply the terms of the ordinary GNU General Public +License instead of this License to a given copy of the Library. To do +this, you must alter all the notices that refer to this License, so +that they refer to the ordinary GNU General Public License, version 2, +instead of to this License. (If a newer version than version 2 of the +ordinary GNU General Public License has appeared, then you can specify +that version instead if you wish.) Do not make any other change in +these notices. + + Once this change is made in a given copy, it is irreversible for +that copy, so the ordinary GNU General Public License applies to all +subsequent copies and derivative works made from that copy. + + This option is useful when you wish to copy part of the code of +the Library into a program that is not a library. + + 4. You may copy and distribute the Library (or a portion or +derivative of it, under Section 2) in object code or executable form +under the terms of Sections 1 and 2 above provided that you accompany +it with the complete corresponding machine-readable source code, which +must be distributed under the terms of Sections 1 and 2 above on a +medium customarily used for software interchange. + + If distribution of object code is made by offering access to copy +from a designated place, then offering equivalent access to copy the +source code from the same place satisfies the requirement to +distribute the source code, even though third parties are not +compelled to copy the source along with the object code. + + 5. A program that contains no derivative of any portion of the +Library, but is designed to work with the Library by being compiled or +linked with it, is called a "work that uses the Library". Such a +work, in isolation, is not a derivative work of the Library, and +therefore falls outside the scope of this License. + + However, linking a "work that uses the Library" with the Library +creates an executable that is a derivative of the Library (because it +contains portions of the Library), rather than a "work that uses the +library". The executable is therefore covered by this License. +Section 6 states terms for distribution of such executables. + + When a "work that uses the Library" uses material from a header file +that is part of the Library, the object code for the work may be a +derivative work of the Library even though the source code is not. +Whether this is true is especially significant if the work can be +linked without the Library, or if the work is itself a library. The +threshold for this to be true is not precisely defined by law. + + If such an object file uses only numerical parameters, data +structure layouts and accessors, and small macros and small inline +functions (ten lines or less in length), then the use of the object +file is unrestricted, regardless of whether it is legally a derivative +work. (Executables containing this object code plus portions of the +Library will still fall under Section 6.) + + Otherwise, if the work is a derivative of the Library, you may +distribute the object code for the work under the terms of Section 6. +Any executables containing that work also fall under Section 6, +whether or not they are linked directly with the Library itself. + + 6. As an exception to the Sections above, you may also combine or +link a "work that uses the Library" with the Library to produce a +work containing portions of the Library, and distribute that work +under terms of your choice, provided that the terms permit +modification of the work for the customer's own use and reverse +engineering for debugging such modifications. + + You must give prominent notice with each copy of the work that the +Library is used in it and that the Library and its use are covered by +this License. You must supply a copy of this License. If the work +during execution displays copyright notices, you must include the +copyright notice for the Library among them, as well as a reference +directing the user to the copy of this License. Also, you must do one +of these things: + + a) Accompany the work with the complete corresponding + machine-readable source code for the Library including whatever + changes were used in the work (which must be distributed under + Sections 1 and 2 above); and, if the work is an executable linked + with the Library, with the complete machine-readable "work that + uses the Library", as object code and/or source code, so that the + user can modify the Library and then relink to produce a modified + executable containing the modified Library. (It is understood + that the user who changes the contents of definitions files in the + Library will not necessarily be able to recompile the application + to use the modified definitions.) + + b) Use a suitable shared library mechanism for linking with the + Library. A suitable mechanism is one that (1) uses at run time a + copy of the library already present on the user's computer system, + rather than copying library functions into the executable, and (2) + will operate properly with a modified version of the library, if + the user installs one, as long as the modified version is + interface-compatible with the version that the work was made with. + + c) Accompany the work with a written offer, valid for at + least three years, to give the same user the materials + specified in Subsection 6a, above, for a charge no more + than the cost of performing this distribution. + + d) If distribution of the work is made by offering access to copy + from a designated place, offer equivalent access to copy the above + specified materials from the same place. + + e) Verify that the user has already received a copy of these + materials or that you have already sent this user a copy. + + For an executable, the required form of the "work that uses the +Library" must include any data and utility programs needed for +reproducing the executable from it. However, as a special exception, +the materials to be distributed need not include anything that is +normally distributed (in either source or binary form) with the major +components (compiler, kernel, and so on) of the operating system on +which the executable runs, unless that component itself accompanies +the executable. + + It may happen that this requirement contradicts the license +restrictions of other proprietary libraries that do not normally +accompany the operating system. Such a contradiction means you cannot +use both them and the Library together in an executable that you +distribute. + + 7. You may place library facilities that are a work based on the +Library side-by-side in a single library together with other library +facilities not covered by this License, and distribute such a combined +library, provided that the separate distribution of the work based on +the Library and of the other library facilities is otherwise +permitted, and provided that you do these two things: + + a) Accompany the combined library with a copy of the same work + based on the Library, uncombined with any other library + facilities. This must be distributed under the terms of the + Sections above. + + b) Give prominent notice with the combined library of the fact + that part of it is a work based on the Library, and explaining + where to find the accompanying uncombined form of the same work. + + 8. You may not copy, modify, sublicense, link with, or distribute +the Library except as expressly provided under this License. Any +attempt otherwise to copy, modify, sublicense, link with, or +distribute the Library is void, and will automatically terminate your +rights under this License. However, parties who have received copies, +or rights, from you under this License will not have their licenses +terminated so long as such parties remain in full compliance. + + 9. You are not required to accept this License, since you have not +signed it. However, nothing else grants you permission to modify or +distribute the Library or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Library (or any work based on the +Library), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Library or works based on it. + + 10. Each time you redistribute the Library (or any work based on the +Library), the recipient automatically receives a license from the +original licensor to copy, distribute, link with or modify the Library +subject to these terms and conditions. You may not impose any further +restrictions on the recipients' exercise of the rights granted herein. +You are not responsible for enforcing compliance by third parties with +this License. + + 11. If, as a consequence of a court judgment or allegation of patent +infringement or for any other reason (not limited to patent issues), +conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot +distribute so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you +may not distribute the Library at all. For example, if a patent +license would not permit royalty-free redistribution of the Library by +all those who receive copies directly or indirectly through you, then +the only way you could satisfy both it and this License would be to +refrain entirely from distribution of the Library. + +If any portion of this section is held invalid or unenforceable under any +particular circumstance, the balance of the section is intended to apply, +and the section as a whole is intended to apply in other circumstances. + +It is not the purpose of this section to induce you to infringe any +patents or other property right claims or to contest validity of any +such claims; this section has the sole purpose of protecting the +integrity of the free software distribution system which is +implemented by public license practices. Many people have made +generous contributions to the wide range of software distributed +through that system in reliance on consistent application of that +system; it is up to the author/donor to decide if he or she is willing +to distribute software through any other system and a licensee cannot +impose that choice. + +This section is intended to make thoroughly clear what is believed to +be a consequence of the rest of this License. + + 12. If the distribution and/or use of the Library is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Library under this License may add +an explicit geographical distribution limitation excluding those countries, +so that distribution is permitted only in or among countries not thus +excluded. In such case, this License incorporates the limitation as if +written in the body of this License. + + 13. The Free Software Foundation may publish revised and/or new +versions of the Lesser General Public License from time to time. +Such new versions will be similar in spirit to the present version, +but may differ in detail to address new problems or concerns. + +Each version is given a distinguishing version number. If the Library +specifies a version number of this License which applies to it and +"any later version", you have the option of following the terms and +conditions either of that version or of any later version published by +the Free Software Foundation. If the Library does not specify a +license version number, you may choose any version ever published by +the Free Software Foundation. + + 14. If you wish to incorporate parts of the Library into other free +programs whose distribution conditions are incompatible with these, +write to the author to ask for permission. For software which is +copyrighted by the Free Software Foundation, write to the Free +Software Foundation; we sometimes make exceptions for this. Our +decision will be guided by the two goals of preserving the free status +of all derivatives of our free software and of promoting the sharing +and reuse of software generally. + + NO WARRANTY + + 15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO +WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW. +EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR +OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY +KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE +LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME +THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. + + 16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN +WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY +AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU +FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR +CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE +LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING +RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A +FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF +SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH +DAMAGES. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Libraries + + If you develop a new library, and you want it to be of the greatest +possible use to the public, we recommend making it free software that +everyone can redistribute and change. You can do so by permitting +redistribution under these terms (or, alternatively, under the terms of the +ordinary General Public License). + + To apply these terms, attach the following notices to the library. It is +safest to attach them to the start of each source file to most effectively +convey the exclusion of warranty; and each file should have at least the +"copyright" line and a pointer to where the full notice is found. + + + Copyright (C) + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + +Also add information on how to contact you by electronic and paper mail. + +You should also get your employer (if you work as a programmer) or your +school, if any, to sign a "copyright disclaimer" for the library, if +necessary. Here is a sample; alter the names: + + Yoyodyne, Inc., hereby disclaims all copyright interest in the + library `Frob' (a library for tweaking knobs) written by James Random Hacker. + + , 1 April 1990 + Ty Coon, President of Vice + +That's all there is to it! + + diff --git a/kotlin-native/licenses/third_party/trove_readme_license.txt b/kotlin-native/licenses/third_party/trove_readme_license.txt new file mode 100644 index 00000000000..dcb598cf6fe --- /dev/null +++ b/kotlin-native/licenses/third_party/trove_readme_license.txt @@ -0,0 +1,18 @@ +The Trove library is licensed under the Lesser GNU Public License, +which is included with the distribution in a file called trove_license.txt. + + +The PrimeFinder and HashFunctions classes in Trove are subject to the +following license restrictions: + +Copyright (c) 1999 CERN - European Organization for Nuclear Research. + +Permission to use, copy, modify, distribute and sell this software and +its documentation for any purpose is hereby granted without fee, +provided that the above copyright notice appear in all copies and that +both that copyright notice and this permission notice appear in +supporting documentation. CERN makes no representations about the +suitability of this software for any purpose. It is provided "as is" +without expressed or implied warranty. + + diff --git a/kotlin-native/licenses/third_party/unicode_LICENSE.txt b/kotlin-native/licenses/third_party/unicode_LICENSE.txt new file mode 100644 index 00000000000..3ffc0fa00a6 --- /dev/null +++ b/kotlin-native/licenses/third_party/unicode_LICENSE.txt @@ -0,0 +1,61 @@ +Portions, Copyright © 1991-2005 Unicode, Inc. The following applies to Unicode. + +COPYRIGHT AND PERMISSION NOTICE + +Copyright © 1991-2005 Unicode, Inc. All rights reserved. Distributed under +the Terms of Use in http://www.unicode.org/copyright.html. Permission is +hereby granted, free of charge, to any person obtaining a copy of the +Unicode data files and any associated documentation (the "Data Files") +or Unicode software and any associated documentation (the "Software") +to deal in the Data Files or Software without restriction, including without +limitation the rights to use, copy, modify, merge, publish, distribute, +and/or sell copies of the Data Files or Software, and to permit persons +to whom the Data Files or Software are furnished to do so, provided that +(a) the above copyright notice(s) and this permission notice appear with +all copies of the Data Files or Software, (b) both the above copyright +notice(s) and this permission notice appear in associated documentation, +and (c) there is clear notice in each modified Data File or in the Software +as well as in the documentation associated with the Data File(s) or Software +that the data or software has been modified. + +THE DATA FILES AND SOFTWARE ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY +KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT +OF THIRD PARTY RIGHTS. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR HOLDERS +INCLUDED IN THIS NOTICE BE LIABLE FOR ANY CLAIM, OR ANY SPECIAL INDIRECT +OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS +OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR +OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR +PERFORMANCE OF THE DATA FILES OR SOFTWARE. + +Except as contained in this notice, the name of a copyright holder shall +not be used in advertising or otherwise to promote the sale, use or other +dealings in these Data Files or Software without prior written +authorization of the copyright holder. + +2. Additional terms from the Database: + +Copyright © 1995-1999 Unicode, Inc. All Rights reserved. + +Disclaimer + +The Unicode Character Database is provided as is by Unicode, Inc. +No claims are made as to fitness for any particular purpose. No warranties +of any kind are expressed or implied. The recipient agrees to determine +applicability of information provided. If this file has been purchased +on magnetic or optical media from Unicode, Inc., the sole remedy for any claim +will be exchange of defective media within 90 days of receipt. This disclaimer +is applicable for all other data files accompanying the Unicode Character Database, +some of which have been compiled by the Unicode Consortium, and some of which +have been supplied by other sources. + +Limitations on Rights to Redistribute This Data + +Recipient is granted the right to make copies in any form for internal +distribution and to freely use the information supplied in the creation of +products supporting the UnicodeTM Standard. The files in +the Unicode Character Database can be redistributed to third parties or other +organizations (whether for profit or not) as long as this notice and the disclaimer +notice are retained. Information can be extracted from these files and used +in documentation or programs, as long as there is an accompanying notice +indicating the source. diff --git a/kotlin-native/licenses/third_party/xcode_license.pdf b/kotlin-native/licenses/third_party/xcode_license.pdf new file mode 100644 index 00000000000..f0165238da4 Binary files /dev/null and b/kotlin-native/licenses/third_party/xcode_license.pdf differ diff --git a/kotlin-native/licenses/third_party/zephyr_LICENSE.txt b/kotlin-native/licenses/third_party/zephyr_LICENSE.txt new file mode 100644 index 00000000000..8f71f43fee3 --- /dev/null +++ b/kotlin-native/licenses/third_party/zephyr_LICENSE.txt @@ -0,0 +1,202 @@ + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "{}" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright {yyyy} {name of copyright owner} + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + diff --git a/kotlin-native/llvmCoverageMappingC/build.gradle b/kotlin-native/llvmCoverageMappingC/build.gradle new file mode 100644 index 00000000000..12128e116c9 --- /dev/null +++ b/kotlin-native/llvmCoverageMappingC/build.gradle @@ -0,0 +1,65 @@ +/* + * Copyright 2010-2017 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +apply plugin: "cpp" +apply plugin: "c" + +buildscript { + ext.rootBuildDirectory = file('..') + + apply from: "$rootBuildDirectory/gradle/kotlinGradlePlugin.gradle" + + dependencies { + classpath "org.jetbrains.kotlin:kotlin-stdlib:$kotlinVersion" + classpath "org.jetbrains.kotlin:kotlin-native-shared:$konanVersion" + } +} +import org.jetbrains.kotlin.konan.target.ClangArgs + +model { + components { + coverageMapping(NativeLibrarySpec) { + sources.cpp.source.srcDirs "src/main/cpp" + + binaries.withType(StaticLibraryBinarySpec) { binary -> + if (!project.parent.convention.plugins.platformInfo.isWindows()) + cppCompiler.args "-fPIC" + cppCompiler.args "--std=c++14", "-I${llvmDir}/include", "-I${projectDir}/src/main/include" + if (isMac()) { + cppCompiler.args "-DKONAN_MACOS=1" + } else if (isWindows()) { + cppCompiler.args "-DKONAN_WINDOWS=1" + } else if (isLinux()) { + cppCompiler.args "-DKONAN_LINUX=1", "-D_GLIBCXX_USE_CXX11_ABI=0" + } else { + throw new Error("Unsupported host OS.") + } + linker.args "-L${llvmDir}/lib", "-lLLVMCore", "-lLLVMSupport" + } + binaries.withType(SharedLibraryBinarySpec) { binary -> + buildable = false + } + } + } + + toolChains { + clang(Clang) { + eachPlatform { + cppCompiler.withArguments(ClangArgs.&filterGradleNativeSoftwareFlags) + } + } + } +} diff --git a/kotlin-native/llvmCoverageMappingC/src/main/cpp/CoverageMappingC.cpp b/kotlin-native/llvmCoverageMappingC/src/main/cpp/CoverageMappingC.cpp new file mode 100644 index 00000000000..0b3046d2841 --- /dev/null +++ b/kotlin-native/llvmCoverageMappingC/src/main/cpp/CoverageMappingC.cpp @@ -0,0 +1,257 @@ +/* + * Copyright 2010-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +#include "CoverageMappingC.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +using namespace llvm; +using namespace llvm::coverage; + +namespace llvm { + DEFINE_SIMPLE_CONVERSION_FUNCTIONS(TargetLibraryInfoImpl, LLVMTargetLibraryInfoRef) +} + +struct LLVMFunctionCoverage { + explicit LLVMFunctionCoverage(std::string coverageData) : coverageData(std::move(coverageData)) {} + + std::string coverageData; +}; + +static coverage::CounterMappingRegion::RegionKind determineRegionKind(const struct LLVMCoverageRegion& region) { + switch (region.kind) { + case LLVMCoverageRegionKind::CODE: + return coverage::CounterMappingRegion::RegionKind::CodeRegion; + case LLVMCoverageRegionKind::GAP: + return coverage::CounterMappingRegion::RegionKind::GapRegion; + case LLVMCoverageRegionKind::EXPANSION: + return coverage::CounterMappingRegion::RegionKind::ExpansionRegion; + } +} + +static coverage::CounterMappingRegion createCounterMappingRegion(struct LLVMCoverageRegion& region) { + auto regionKind = determineRegionKind(region); + int expandedFileId = 0; + if (regionKind == coverage::CounterMappingRegion::RegionKind::ExpansionRegion) { + expandedFileId = region.expandedFileId; + } + const Counter &counter = coverage::Counter::getCounter(region.counterId); + return coverage::CounterMappingRegion(counter, region.fileId, expandedFileId, region.lineStart, + region.columnStart, region.lineEnd, region.columnEnd, regionKind); +} + +LLVMFunctionCoverage* LLVMWriteCoverageRegionMapping(unsigned int *fileIdMapping, size_t fileIdMappingSize, + struct LLVMCoverageRegion **mappingRegions, size_t mappingRegionsSize) { + std::vector counterMappingRegions; + for (size_t i = 0; i < mappingRegionsSize; ++i) { + struct LLVMCoverageRegion region = *mappingRegions[i]; + counterMappingRegions.emplace_back(createCounterMappingRegion(region)); + } + CoverageMappingWriter writer(ArrayRef(fileIdMapping, fileIdMappingSize), None, counterMappingRegions); + std::string CoverageMapping; + raw_string_ostream OS(CoverageMapping); + writer.write(OS); + OS.flush(); + // Should be disposed with `LLVMFunctionCoverageDispose`. + return new LLVMFunctionCoverage(CoverageMapping); +} + +void LLVMFunctionCoverageDispose(struct LLVMFunctionCoverage* functionCoverage) { + delete functionCoverage; +} + +static StructType *getFunctionRecordTy(LLVMContext &Ctx) { +#define COVMAP_FUNC_RECORD(Type, LLVMType, Name, Init) LLVMType, + Type *FunctionRecordTypes[] = { +#include "llvm/ProfileData/InstrProfData.inc" + }; + StructType *FunctionRecordTy = StructType::get(Ctx, makeArrayRef(FunctionRecordTypes), true); + return FunctionRecordTy; +} + +static llvm::Constant *addFunctionMappingRecord(llvm::LLVMContext &Ctx, StringRef NameValue, uint64_t FuncHash, + const std::string &CoverageMapping) { + llvm::StructType *FunctionRecordTy = getFunctionRecordTy(Ctx); + +#define COVMAP_FUNC_RECORD(Type, LLVMType, Name, Init) Init, + llvm::Constant *FunctionRecordVals[] = { +#include "llvm/ProfileData/InstrProfData.inc" + }; + return llvm::ConstantStruct::get(FunctionRecordTy, makeArrayRef(FunctionRecordVals)); +} + +// See https://github.com/llvm/llvm-project/blob/fa8fa044ec46b94e64971efa8852df0d58114062/clang/lib/CodeGen/CoverageMappingGen.cpp#L1284. +LLVMValueRef LLVMAddFunctionMappingRecord(LLVMContextRef context, const char *name, uint64_t hash, + struct LLVMFunctionCoverage *coverageMapping) { + return llvm::wrap(addFunctionMappingRecord(*llvm::unwrap(context), name, hash, coverageMapping->coverageData)); +} + +// See https://github.com/llvm/llvm-project/blob/fa8fa044ec46b94e64971efa8852df0d58114062/clang/lib/CodeGen/CoverageMappingGen.cpp#L1335. +// Please note that llvm/ProfileData/InstrProfData.inc refers to variable names of the function that includes it. So be careful with renaming. +static llvm::GlobalVariable* emitCoverageGlobal( + llvm::LLVMContext &Ctx, + llvm::Module &module, + std::vector &FunctionRecords, + const llvm::SmallVector &FilenameRefs, + const std::string &RawCoverageMappings) { + + auto *Int32Ty = llvm::Type::getInt32Ty(Ctx); + + std::string FilenamesAndCoverageMappings; + llvm::raw_string_ostream outputStream(FilenamesAndCoverageMappings); + CoverageFilenamesSectionWriter(FilenameRefs).write(outputStream); + outputStream << RawCoverageMappings; + size_t CoverageMappingSize = RawCoverageMappings.size(); + size_t FilenamesSize = outputStream.str().size() - CoverageMappingSize; + + // See https://llvm.org/docs/CoverageMappingFormat.html#llvm-ir-representation + // + // > Coverage mapping data which is an array of bytes. Zero paddings are added at the end to force 8 byte alignment. + // + if (size_t rem = outputStream.str().size() % 8) { + CoverageMappingSize += 8 - rem; + for (size_t i = 0; i < 8 - rem; ++i) { + outputStream << '\0'; + } + } + + StructType *functionRecordTy = getFunctionRecordTy(Ctx); + // Create the deferred function records array + auto functionRecordsTy = llvm::ArrayType::get(functionRecordTy, FunctionRecords.size()); + auto functionRecordsVal = llvm::ConstantArray::get(functionRecordsTy, FunctionRecords); + + llvm::Type *CovDataHeaderTypes[] = { +#define COVMAP_HEADER(Type, LLVMType, Name, Init) LLVMType, + +#include "llvm/ProfileData/InstrProfData.inc" + }; + auto CovDataHeaderTy = llvm::StructType::get(Ctx, makeArrayRef(CovDataHeaderTypes)); + llvm::Constant *CovDataHeaderVals[] = { +#define COVMAP_HEADER(Type, LLVMType, Name, Init) Init, + +#include "llvm/ProfileData/InstrProfData.inc" + }; + auto covDataHeaderVal = llvm::ConstantStruct::get(CovDataHeaderTy, makeArrayRef(CovDataHeaderVals)); + + auto *filenamesAndMappingsVal = llvm::ConstantDataArray::getString(Ctx, outputStream.str(), false); + // Create the coverage data record + llvm::Type *covDataTypes[] = {CovDataHeaderTy, functionRecordsTy, filenamesAndMappingsVal->getType()}; + auto covDataTy = llvm::StructType::get(Ctx, makeArrayRef(covDataTypes)); + + llvm::Constant *TUDataVals[] = {covDataHeaderVal, functionRecordsVal, filenamesAndMappingsVal}; + auto covDataVal = llvm::ConstantStruct::get(covDataTy, makeArrayRef(TUDataVals)); + // Will be deleted when module is disposed. + return new llvm::GlobalVariable(module, covDataTy, true, llvm::GlobalValue::InternalLinkage, + covDataVal, llvm::getCoverageMappingVarName()); +} + +static std::string createRawCoverageMapping(struct LLVMFunctionCoverage **functionCoverages, size_t functionCoveragesSize) { + std::vector coverageMappings; + for (size_t i = 0; i < functionCoveragesSize; ++i) { + coverageMappings.emplace_back(functionCoverages[i]->coverageData); + } + return llvm::join(coverageMappings.begin(), coverageMappings.end(), ""); +} + +LLVMValueRef LLVMCoverageEmit(LLVMModuleRef moduleRef, + LLVMValueRef *records, size_t recordsSize, + const char **filenames, int *filenamesIndices, size_t filenamesSize, + struct LLVMFunctionCoverage **functionCoverages, size_t functionCoveragesSize) { + LLVMContext &ctx = *unwrap(LLVMGetModuleContext(moduleRef)); + Module &module = *unwrap(moduleRef); + + std::vector functionRecords; + for (size_t i = 0; i < recordsSize; ++i) { + functionRecords.push_back(dyn_cast(unwrap(records[i]))); + } + llvm::SmallVector filenameRefs; + filenameRefs.resize(filenamesSize); + for (size_t i = 0; i < filenamesSize; ++i) { + if (sys::path::is_absolute(filenames[i])) { + filenameRefs[filenamesIndices[i]] = filenames[i]; + } else { + SmallString<256> path(filenames[i]); + sys::fs::make_absolute(path); + sys::path::remove_dots(path, true); + filenameRefs[filenamesIndices[i]] = path; + } + } + const std::string &rawCoverageMappings = createRawCoverageMapping(functionCoverages, functionCoveragesSize); + GlobalVariable *coverageGlobal = emitCoverageGlobal(ctx, module, functionRecords, filenameRefs, rawCoverageMappings); + + const std::string §ion = getInstrProfSectionName(IPSK_covmap, Triple(module.getTargetTriple()).getObjectFormat()); + coverageGlobal->setSection(section); + coverageGlobal->setAlignment(8); + return wrap(coverageGlobal); +} + +LLVMValueRef LLVMInstrProfIncrement(LLVMModuleRef moduleRef) { + Module &module = *unwrap(moduleRef); + return wrap(Intrinsic::getDeclaration(&module, Intrinsic::instrprof_increment, None)); +} + +LLVMValueRef LLVMCreatePGOFunctionNameVar(LLVMValueRef llvmFunction, const char *pgoFunctionName) { + auto *fnPtr = cast(unwrap(llvmFunction)); + return wrap(createPGOFuncNameVar(*fnPtr, pgoFunctionName)); +} + +void LLVMAddInstrProfPass(LLVMPassManagerRef passManagerRef, const char* outputFileName) { + legacy::PassManagerBase *passManager = unwrap(passManagerRef); + InstrProfOptions options; + options.InstrProfileOutput = outputFileName; + passManager->add(createInstrProfilingLegacyPass(options)); +} + +void LLVMKotlinAddTargetLibraryInfoWrapperPass(LLVMPassManagerRef passManagerRef, const char* targetTriple) { + legacy::PassManagerBase *passManager = unwrap(passManagerRef); + passManager->add(new TargetLibraryInfoWrapperPass(Triple(targetTriple))); +} + +void LLVMKotlinInitializeTargets() { +#define INIT_LLVM_TARGET(TargetName) \ + LLVMInitialize##TargetName##TargetInfo();\ + LLVMInitialize##TargetName##Target();\ + LLVMInitialize##TargetName##TargetMC(); +#if KONAN_MACOS + INIT_LLVM_TARGET(AArch64) + INIT_LLVM_TARGET(ARM) + INIT_LLVM_TARGET(Mips) + INIT_LLVM_TARGET(X86) + INIT_LLVM_TARGET(WebAssembly) +#elif KONAN_LINUX + INIT_LLVM_TARGET(AArch64) + INIT_LLVM_TARGET(ARM) + INIT_LLVM_TARGET(Mips) + INIT_LLVM_TARGET(X86) + INIT_LLVM_TARGET(WebAssembly) +#elif KONAN_WINDOWS + INIT_LLVM_TARGET(AArch64) + INIT_LLVM_TARGET(ARM) + INIT_LLVM_TARGET(X86) + INIT_LLVM_TARGET(WebAssembly) +#endif + +#undef INIT_LLVM_TARGET +} \ No newline at end of file diff --git a/kotlin-native/llvmCoverageMappingC/src/main/include/CoverageMappingC.h b/kotlin-native/llvmCoverageMappingC/src/main/include/CoverageMappingC.h new file mode 100644 index 00000000000..a0160c2afcf --- /dev/null +++ b/kotlin-native/llvmCoverageMappingC/src/main/include/CoverageMappingC.h @@ -0,0 +1,82 @@ +/* + * Copyright 2010-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +#ifndef __COVERAGE_MAPPING_C_H__ +# define __COVERAGE_MAPPING_C_H__ + +#include +#include + + +# ifdef __cplusplus +extern "C" { +# endif + +/** + * See org.jetbrains.kotlin.backend.konan.llvm.coverage.RegionKind. + */ +enum LLVMCoverageRegionKind { + CODE, + GAP, + EXPANSION +}; + +/** + * See org.jetbrains.kotlin.backend.konan.llvm.coverage.Region. + */ +struct LLVMCoverageRegion { + int fileId; + int lineStart; + int columnStart; + int lineEnd; + int columnEnd; + int counterId; + int expandedFileId; + enum LLVMCoverageRegionKind kind; +}; + +struct LLVMFunctionCoverage; + +/** + * Add record in the following format: https://llvm.org/docs/CoverageMappingFormat.html#function-record. + */ +LLVMValueRef +LLVMAddFunctionMappingRecord(LLVMContextRef context, const char *name, uint64_t hash, struct LLVMFunctionCoverage* coverageMapping); + +/** + * Wraps creation of coverage::CoverageMappingWriter and call to coverage::CoverageMappingWriter::write. + */ +struct LLVMFunctionCoverage* LLVMWriteCoverageRegionMapping(unsigned int *fileIdMapping, size_t fileIdMappingSize, + struct LLVMCoverageRegion **mappingRegions, size_t mappingRegionsSize); + +void LLVMFunctionCoverageDispose(struct LLVMFunctionCoverage* functionCoverage); + +/** + * Create __llvm_coverage_mapping global. + */ +LLVMValueRef LLVMCoverageEmit(LLVMModuleRef moduleRef, LLVMValueRef *records, size_t recordsSize, + const char **filenames, int *filenamesIndices, size_t filenamesSize, + struct LLVMFunctionCoverage** functionCoverages, size_t functionCoveragesSize); + +/** + * Wrapper for `llvm.instrprof.increment` declaration. + */ +LLVMValueRef LLVMInstrProfIncrement(LLVMModuleRef moduleRef); + +/** + * Wrapper for llvm::createPGOFuncNameVar. + */ +LLVMValueRef LLVMCreatePGOFunctionNameVar(LLVMValueRef llvmFunction, const char *pgoFunctionName); + +void LLVMAddInstrProfPass(LLVMPassManagerRef passManagerRef, const char* outputFileName); + +void LLVMKotlinAddTargetLibraryInfoWrapperPass(LLVMPassManagerRef passManagerRef, const char* targetTriple); + +void LLVMKotlinInitializeTargets(); + +# ifdef __cplusplus +} +# endif +#endif diff --git a/kotlin-native/llvmDebugInfoC/build.gradle b/kotlin-native/llvmDebugInfoC/build.gradle new file mode 100644 index 00000000000..76f434c6756 --- /dev/null +++ b/kotlin-native/llvmDebugInfoC/build.gradle @@ -0,0 +1,56 @@ +/* + * Copyright 2010-2019 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +apply plugin: "cpp" +apply plugin: "c" + +buildscript { + ext.rootBuildDirectory = file('..') + + apply from: "$rootBuildDirectory/gradle/kotlinGradlePlugin.gradle" + + dependencies { + classpath "org.jetbrains.kotlin:kotlin-stdlib:$kotlinVersion" + classpath "org.jetbrains.kotlin:kotlin-native-shared:$konanVersion" + } +} +import org.jetbrains.kotlin.konan.target.ClangArgs + +model { + components { + debugInfo(NativeLibrarySpec) { + sources.cpp.source.srcDirs "src/main/cpp" + + binaries.withType(StaticLibraryBinarySpec) { binary -> + if (!project.parent.convention.plugins.platformInfo.isWindows()) + cppCompiler.args "-fPIC" + cppCompiler.args "--std=c++14", "-I${llvmDir}/include", "-I${projectDir}/src/main/include" + linker.args "-L${llvmDir}/lib", "-lLLVMCore", "-lLLVMSupport" + } + binaries.withType(SharedLibraryBinarySpec) { binary -> + buildable = false + } + } + } + + toolChains { + clang(Clang) { + eachPlatform { + cppCompiler.withArguments(ClangArgs.&filterGradleNativeSoftwareFlags) + } + } + } +} diff --git a/kotlin-native/llvmDebugInfoC/src/dwarf/include/dwarf_util.kt.pp b/kotlin-native/llvmDebugInfoC/src/dwarf/include/dwarf_util.kt.pp new file mode 100644 index 00000000000..205162cc7fa --- /dev/null +++ b/kotlin-native/llvmDebugInfoC/src/dwarf/include/dwarf_util.kt.pp @@ -0,0 +1,47 @@ +/* + * Copyright 2010-2017 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.jetbrains.kotlin.backend.konan.llvm + +/** + * This code was generated with following command: + * $ clang -xc -E -Idist/dependencies/clang-llvm-3.9.0-darwin-macos/include/ llvmDebugInfoC/src/dwarf/include/dwarf_util.kt.pp -Wp,-P -Wp,-CC -o - | sed -e '/^$/d' -e '/^\ *\/\/.*$/d' > backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/Dwarf.kt + * + */ + +internal enum class DwarfTag(val value:Int) { +#define HANDLE_DW_TAG(ID, NAME) DW_TAG_##NAME(ID), +#include "llvm/Support/Dwarf.def" +#undef HANDLE_DW_TAG +} + +internal enum class DwarfTypeKind(val value:Byte) { +#define HANDLE_DW_ATE(ID, NAME) DW_ATE_##NAME(ID), +#include "llvm/Support/Dwarf.def" +#undef HANDLE_DW_ATE +} + +internal enum class DwarfOp(val value:Long) { +#define HANDLE_DW_OP(ID, NAME) DW_OP_##NAME(ID), +#include "llvm/Support/Dwarf.def" +#undef HANDLE_DW_OP +} + +internal enum class DwarfLanguage(val value:Int) { +#define HANDLE_DW_LANG(ID, NAME) DW_LANG_##NAME(ID), +#include "llvm/Support/Dwarf.def" +#undef HANDLE_DW_LANG + DW_LANG_Kotlin(0x0001) /* manually added, should be changed someday. */ +} \ No newline at end of file diff --git a/kotlin-native/llvmDebugInfoC/src/main/cpp/DebugInfoC.cpp b/kotlin-native/llvmDebugInfoC/src/main/cpp/DebugInfoC.cpp new file mode 100644 index 00000000000..8d07c27ea21 --- /dev/null +++ b/kotlin-native/llvmDebugInfoC/src/main/cpp/DebugInfoC.cpp @@ -0,0 +1,297 @@ +/* + * Copyright 2010-2017 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "DebugInfoC.h" +/** + * c++ --std=c++14 llvmDebugInfoC/src/DebugInfoC.cpp -IllvmDebugInfoC/include/ -Idependencies/all/clang+llvm-3.9.0-darwin-macos/include -Ldependencies/all/clang+llvm-3.9.0-darwin-macos/lib -lLLVMCore -lLLVMSupport -lncurses -shared -o libLLVMDebugInfoC.dylib + */ + +namespace llvm { +//DEFINE_SIMPLE_CONVERSION_FUNCTIONS(DIBuilder, DIBuilderRef) +DEFINE_SIMPLE_CONVERSION_FUNCTIONS(DICompileUnit, DICompileUnitRef) +DEFINE_SIMPLE_CONVERSION_FUNCTIONS(DIFile, DIFileRef) +DEFINE_SIMPLE_CONVERSION_FUNCTIONS(DIBasicType, DIBasicTypeRef) +DEFINE_SIMPLE_CONVERSION_FUNCTIONS(DICompositeType, DICompositeTypeRef) +DEFINE_SIMPLE_CONVERSION_FUNCTIONS(DIType, DITypeOpaqueRef) +DEFINE_SIMPLE_CONVERSION_FUNCTIONS(DIDerivedType, DIDerivedTypeRef) +DEFINE_SIMPLE_CONVERSION_FUNCTIONS(DIModule, DIModuleRef) +DEFINE_SIMPLE_CONVERSION_FUNCTIONS(DIScope, DIScopeOpaqueRef) +DEFINE_SIMPLE_CONVERSION_FUNCTIONS(DISubroutineType, DISubroutineTypeRef) +DEFINE_SIMPLE_CONVERSION_FUNCTIONS(DISubprogram, DISubprogramRef) +DEFINE_SIMPLE_CONVERSION_FUNCTIONS(DILocation, DILocationRef) +DEFINE_SIMPLE_CONVERSION_FUNCTIONS(DILocalVariable, DILocalVariableRef) +DEFINE_SIMPLE_CONVERSION_FUNCTIONS(DIExpression, DIExpressionRef) + +// from Module.cpp +//DEFINE_SIMPLE_CONVERSION_FUNCTIONS(Module, LLVMModuleRef) +} + +/** + * see [DIFlags::FlagFwdDecl]. + */ +#define DI_FORWARD_DECLARAION (4) +extern "C" { + +void DIFinalize(DIBuilderRef builder) { + auto diBuilder = llvm::unwrap(builder); + diBuilder->finalize(); +} + +DICompileUnitRef DICreateCompilationUnit(DIBuilderRef builder, unsigned int lang, + const char *file, const char* dir, + const char * producer, int isOptimized, + const char * flags, unsigned int rv) { + llvm::DIBuilder *D = llvm::unwrap(builder); + return llvm::wrap(llvm::unwrap(builder)->createCompileUnit(lang, D->createFile(file, dir), producer, isOptimized, flags, rv)); +} + +DIFileRef DICreateFile(DIBuilderRef builder, const char *filename, const char *directory) { + return llvm::wrap(llvm::unwrap(builder)->createFile(filename, directory)); +} + +DIBasicTypeRef DICreateBasicType(DIBuilderRef builder, const char* name, uint64_t sizeInBits, uint64_t alignment, unsigned encoding) { + return llvm::wrap(llvm::unwrap(builder)->createBasicType(name, sizeInBits, encoding)); +} + +DIModuleRef DICreateModule(DIBuilderRef builder, DIScopeOpaqueRef scope, + const char* name, const char* configurationMacro, + const char* includePath, const char *iSysRoot) { + return llvm::wrap(llvm::unwrap(builder)->createModule(llvm::unwrap(scope), name, configurationMacro, includePath, iSysRoot)); +} + +DISubprogramRef DICreateFunction(DIBuilderRef builderRef, DIScopeOpaqueRef scope, + const char* name, const char *linkageName, + DIFileRef file, unsigned lineNo, + DISubroutineTypeRef type, int isLocal, + int isDefinition, unsigned scopeLine) { + auto builder = llvm::unwrap(builderRef); + auto subprogram = builder->createFunction(llvm::unwrap(scope), + name, + linkageName, + llvm::unwrap(file), + lineNo, + llvm::unwrap(type), + scopeLine, llvm::DINode::DIFlags::FlagZero, llvm::DISubprogram::toSPFlags(false, true, false)); + auto tmp = subprogram->getRetainedNodes().get(); + if (!tmp && tmp->isTemporary()) + llvm::MDTuple::deleteTemporary(tmp); + + builder->finalizeSubprogram(subprogram); + return llvm::wrap(subprogram); +} + +DIScopeOpaqueRef DICreateLexicalBlockFile(DIBuilderRef builderRef, DIScopeOpaqueRef scopeRef, DIFileRef fileRef) { + return llvm::wrap(llvm::unwrap(builderRef)->createLexicalBlockFile(llvm::unwrap(scopeRef), llvm::unwrap(fileRef))); +} + +DIScopeOpaqueRef DICreateLexicalBlock(DIBuilderRef builderRef, DIScopeOpaqueRef scopeRef, DIFileRef fileRef, int line, int column) { + return llvm::wrap(llvm::unwrap(builderRef)->createLexicalBlock(llvm::unwrap(scopeRef), llvm::unwrap(fileRef), line, column)); +} + + +DICompositeTypeRef DICreateStructType(DIBuilderRef refBuilder, + DIScopeOpaqueRef scope, const char *name, + DIFileRef file, unsigned lineNumber, + uint64_t sizeInBits, uint64_t alignInBits, + unsigned flags, DITypeOpaqueRef derivedFrom, + DIDerivedTypeRef *elements, + uint64_t elementsCount, + DICompositeTypeRef refPlace) { + auto builder = llvm::unwrap(refBuilder); + if ((flags & DI_FORWARD_DECLARAION) != 0) { + auto tmp = builder->createReplaceableCompositeType( + llvm::dwarf::DW_TAG_structure_type, name, llvm::unwrap(scope), llvm::unwrap(file), lineNumber, 0, sizeInBits, alignInBits, + (llvm::DINode::DIFlags)flags); + builder->replaceTemporary(llvm::TempDIType(tmp), tmp); + builder->retainType(tmp); + return llvm::wrap(tmp); + } + assert(false); + return nullptr; +} + + +DICompositeTypeRef DICreateArrayType(DIBuilderRef refBuilder, + uint64_t size, uint64_t alignInBits, + DITypeOpaqueRef refType, + uint64_t elementsCount) { + auto builder = llvm::unwrap(refBuilder); + auto range = std::vector({llvm::dyn_cast(builder->getOrCreateSubrange(0, size))}); + auto type = builder->createArrayType(size, alignInBits, llvm::unwrap(refType), + builder->getOrCreateArray(range)); + builder->retainType(type); + return llvm::wrap(type); +} + + +DIDerivedTypeRef DICreateMemberType(DIBuilderRef refBuilder, + DIScopeOpaqueRef refScope, + const char *name, + DIFileRef file, + unsigned lineNum, + uint64_t sizeInBits, + uint64_t alignInBits, + uint64_t offsetInBits, + unsigned flags, + DITypeOpaqueRef type) { + return llvm::wrap(llvm::unwrap(refBuilder)->createMemberType( + llvm::unwrap(refScope), + name, + llvm::unwrap(file), + lineNum, + sizeInBits, + alignInBits, + offsetInBits, + (llvm::DINode::DIFlags)flags, + llvm::unwrap(type))); +} + +DICompositeTypeRef DICreateReplaceableCompositeType(DIBuilderRef refBuilder, + int tag, + const char *name, + DIScopeOpaqueRef refScope, + DIFileRef refFile, + unsigned line) { + auto builder = llvm::unwrap(refBuilder); + auto type = builder->createReplaceableCompositeType( + tag, name, llvm::unwrap(refScope), llvm::unwrap(refFile), line); + builder->retainType(type); + return llvm::wrap(type); +} + +DIDerivedTypeRef DICreateReferenceType(DIBuilderRef refBuilder, DITypeOpaqueRef refType) { + auto builder = llvm::unwrap(refBuilder); + auto type = builder->createReferenceType( + llvm::dwarf::DW_TAG_reference_type, + llvm::unwrap(refType)); + builder->retainType(type); + return llvm::wrap(type); +} + +DIDerivedTypeRef DICreatePointerType(DIBuilderRef refBuilder, DITypeOpaqueRef refType) { + auto builder = llvm::unwrap(refBuilder); + auto type = builder->createReferenceType( + llvm::dwarf::DW_TAG_pointer_type, + llvm::unwrap(refType)); + builder->retainType(type); + return llvm::wrap(type); +} + +DISubroutineTypeRef DICreateSubroutineType(DIBuilderRef builder, + DITypeOpaqueRef* types, + unsigned typesCount) { + std::vector parameterTypes; + for (int i = 0; i != typesCount; ++i) { + parameterTypes.push_back(llvm::unwrap(types[i])); + } + llvm::DIBuilder *b = llvm::unwrap(builder); + llvm::DITypeRefArray typeArray = b->getOrCreateTypeArray(parameterTypes); + auto type = b->createSubroutineType(typeArray); + b->retainType(type); + return llvm::wrap(type); +} + +void DIFunctionAddSubprogram(LLVMValueRef fn, DISubprogramRef sp) { + auto f = llvm::cast(llvm::unwrap(fn)); + auto dsp = llvm::cast(llvm::unwrap(sp)); + f->setSubprogram(dsp); + if (!dsp->describes(f)) { + fprintf(stderr, "error!!! f:%s, sp:%s\n", f->getName().str().c_str(), dsp->getLinkageName().str().c_str()); + } +} + +DILocalVariableRef DICreateAutoVariable(DIBuilderRef builder, DIScopeOpaqueRef scope, const char *name, DIFileRef file, unsigned line, DITypeOpaqueRef type) { + return llvm::wrap(llvm::unwrap(builder)->createAutoVariable( + llvm::unwrap(scope), + name, + llvm::unwrap(file), + line, + llvm::unwrap(type))); +} + +DILocalVariableRef DICreateParameterVariable(DIBuilderRef builder, DIScopeOpaqueRef scope, const char *name, unsigned argNo, DIFileRef file, unsigned line, DITypeOpaqueRef type) { + return llvm::wrap(llvm::unwrap(builder)->createParameterVariable( + llvm::unwrap(scope), + name, + argNo, + llvm::unwrap(file), + line, + llvm::unwrap(type))); +} + +DIExpressionRef DICreateEmptyExpression(DIBuilderRef builder) { + return llvm::wrap(llvm::unwrap(builder)->createExpression()); +} + +void DIInsertDeclaration(DIBuilderRef builder, LLVMValueRef value, DILocalVariableRef localVariable, DILocationRef location, LLVMBasicBlockRef bb, int64_t *expr, uint64_t exprCount) { + auto di_builder = llvm::unwrap(builder); + std::vector expression; + for (uint64_t i = 0; i < exprCount; ++i) + expression.push_back(expr[i]); + di_builder->insertDeclare(llvm::unwrap(value), + llvm::unwrap(localVariable), + di_builder->createExpression(expression), + llvm::unwrap(location), + llvm::unwrap(bb)); +} + +DILocationRef LLVMCreateLocation(LLVMContextRef contextRef, unsigned line, + unsigned col, DIScopeOpaqueRef scope) { + auto location = llvm::DILocation::get(*llvm::unwrap(contextRef), line, col, llvm::unwrap(scope), nullptr); + return llvm::wrap(location); +} + +DILocationRef LLVMCreateLocationInlinedAt(LLVMContextRef contextRef, unsigned line, + unsigned col, DIScopeOpaqueRef scope, DILocationRef refLocationInlinedAt) { + auto location = llvm::DILocation::get(*llvm::unwrap(contextRef), line, col, llvm::unwrap(scope), llvm::unwrap(refLocationInlinedAt)); + return llvm::wrap(location); +} + +void LLVMBuilderSetDebugLocation(LLVMBuilderRef builder, DILocationRef refLocation) { + llvm::unwrap(builder)->SetCurrentDebugLocation(llvm::unwrap(refLocation)); +} + +void LLVMBuilderResetDebugLocation(LLVMBuilderRef builder) { + llvm::unwrap(builder)->SetCurrentDebugLocation(nullptr); +} + +LLVMValueRef LLVMBuilderGetCurrentFunction(LLVMBuilderRef builder) { + return llvm::wrap(llvm::unwrap(builder)->GetInsertBlock()->getParent()); +} + +const char* LLVMBuilderGetCurrentBbName(LLVMBuilderRef builder) { + return llvm::unwrap(builder)->GetInsertBlock()->getName().str().c_str(); +} + + +const char *DIGetSubprogramLinkName(DISubprogramRef sp) { + return llvm::unwrap(sp)->getLinkageName().str().c_str(); +} + +int DISubprogramDescribesFunction(DISubprogramRef sp, LLVMValueRef fn) { + return llvm::unwrap(sp)->describes(llvm::cast(llvm::unwrap(fn))); +} +} /* extern "C" */ + diff --git a/kotlin-native/llvmDebugInfoC/src/main/include/DebugInfoC.h b/kotlin-native/llvmDebugInfoC/src/main/include/DebugInfoC.h new file mode 100644 index 00000000000..0ef7ea747f3 --- /dev/null +++ b/kotlin-native/llvmDebugInfoC/src/main/include/DebugInfoC.h @@ -0,0 +1,116 @@ +/* + * Copyright 2010-2017 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef __DEBUG_INFO_C_H__ +# define __DEBUG_INFO_C_H__ +#include +# ifdef __cplusplus +extern "C" { +# endif + +typedef struct LLVMOpaqueDIBuilder *DIBuilderRef; +//typedef struct DIBuilder *DIBuilderRef; +typedef struct DICompileUnit *DICompileUnitRef; +typedef struct DIFile *DIFileRef; +typedef struct DIBasicType *DIBasicTypeRef; +typedef struct DICompositeType *DICompositeTypeRef; +typedef struct DIDerivedType *DIDerivedTypeRef; +typedef struct DIType *DITypeOpaqueRef; +typedef struct DISubprogram *DISubprogramRef; +typedef struct DIModule *DIModuleRef; +typedef struct DIScope *DIScopeOpaqueRef; +typedef struct DISubroutineType *DISubroutineTypeRef; +//typedef struct DISubprogram *DISubprogramRef; +typedef struct DILocation *DILocationRef; +typedef struct DILocalVariable *DILocalVariableRef; +typedef struct DIExpression *DIExpressionRef; + +void DIFinalize(DIBuilderRef builder); + +DICompileUnitRef DICreateCompilationUnit(DIBuilderRef builder, unsigned int lang, const char *File, const char* dir, const char * producer, int isOptimized, const char * flags, unsigned int rv); + +DIFileRef DICreateFile(DIBuilderRef builder, const char *filename, const char *directory); + +DIBasicTypeRef DICreateBasicType(DIBuilderRef builder, const char* name, uint64_t sizeInBits, uint64_t alignment, unsigned encoding); + +DICompositeTypeRef DICreateStructType(DIBuilderRef refBuilder, + DIScopeOpaqueRef scope, const char *name, + DIFileRef file, unsigned lineNumber, + uint64_t sizeInBits, uint64_t alignInBits, + unsigned flags, DITypeOpaqueRef derivedFrom, + DIDerivedTypeRef *elements, + uint64_t elementsCount, + DICompositeTypeRef refPlace); +DICompositeTypeRef DICreateArrayType(DIBuilderRef refBuilder, + uint64_t size, uint64_t alignInBits, + DITypeOpaqueRef type, + uint64_t elementsCount); + +DIDerivedTypeRef DICreateReferenceType(DIBuilderRef refBuilder, DITypeOpaqueRef refType); +DIDerivedTypeRef DICreatePointerType(DIBuilderRef refBuilder, DITypeOpaqueRef refType); +DICompositeTypeRef DICreateReplaceableCompositeType(DIBuilderRef refBuilder, + int tag, + const char *name, + DIScopeOpaqueRef refScope, + DIFileRef refFile, + unsigned line); +DIDerivedTypeRef DICreateMemberType(DIBuilderRef refBuilder, + DIScopeOpaqueRef refScope, + const char *name, + DIFileRef file, + unsigned lineNum, + uint64_t sizeInBits, + uint64_t alignInBits, + uint64_t offsetInBits, + unsigned flags, + DITypeOpaqueRef type); + + +DIModuleRef DICreateModule(DIBuilderRef builder, DIScopeOpaqueRef scope, + const char* name, const char* configurationMacro, + const char* includePath, const char *iSysRoot); + +DIScopeOpaqueRef DICreateLexicalBlockFile(DIBuilderRef builderRef, DIScopeOpaqueRef scopeRef, DIFileRef fileRef); + +DIScopeOpaqueRef DICreateLexicalBlock(DIBuilderRef builderRef, DIScopeOpaqueRef scopeRef, DIFileRef fileRef, int line, int column); + +DISubprogramRef DICreateFunction(DIBuilderRef builder, DIScopeOpaqueRef scope, + const char* name, const char *linkageName, + DIFileRef file, unsigned lineNo, + DISubroutineTypeRef type, int isLocal, + int isDefinition, unsigned scopeLine); + +DISubroutineTypeRef DICreateSubroutineType(DIBuilderRef builder, + DITypeOpaqueRef* types, + unsigned typesCount); + +DILocalVariableRef DICreateAutoVariable(DIBuilderRef builder, DIScopeOpaqueRef scope, const char *name, DIFileRef file, unsigned line, DITypeOpaqueRef type); +DILocalVariableRef DICreateParameterVariable(DIBuilderRef builder, DIScopeOpaqueRef scope, const char *name, unsigned argNo, DIFileRef file, unsigned line, DITypeOpaqueRef type); +void DIInsertDeclaration(DIBuilderRef builder, LLVMValueRef value, DILocalVariableRef localVariable, DILocationRef location, LLVMBasicBlockRef bb, int64_t *expr, uint64_t exprCount); +DIExpressionRef DICreateEmptyExpression(DIBuilderRef builder); +void DIFunctionAddSubprogram(LLVMValueRef fn, DISubprogramRef sp); +DILocationRef LLVMCreateLocation(LLVMContextRef contextRef, unsigned line, unsigned col, DIScopeOpaqueRef scope); +DILocationRef LLVMCreateLocationInlinedAt(LLVMContextRef contextRef, unsigned line, unsigned col, DIScopeOpaqueRef scope, DILocationRef refLocation); +void LLVMBuilderSetDebugLocation(LLVMBuilderRef builder, DILocationRef refLocation); +void LLVMBuilderResetDebugLocation(LLVMBuilderRef builder); +const char* LLVMBuilderGetCurrentBbName(LLVMBuilderRef builder); +const char *DIGetSubprogramLinkName(DISubprogramRef sp); +LLVMValueRef LLVMBuilderGetCurrentFunction(LLVMBuilderRef builder); +int DISubprogramDescribesFunction(DISubprogramRef sp, LLVMValueRef fn); +# ifdef __cplusplus +} +# endif +#endif diff --git a/kotlin-native/llvmDebugInfoC/src/scripts/konan_lldb.py b/kotlin-native/llvmDebugInfoC/src/scripts/konan_lldb.py new file mode 100644 index 00000000000..549f9521507 --- /dev/null +++ b/kotlin-native/llvmDebugInfoC/src/scripts/konan_lldb.py @@ -0,0 +1,490 @@ +#!/usr/bin/python + +## +# Copyright 2010-2017 JetBrains s.r.o. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +# +# (lldb) command script import llvmDebugInfoC/src/scripts/konan_lldb.py +# (lldb) p kotlin_variable +# + +import lldb +import struct +import re +import sys + +NULL = 'null' + +def log(msg): + if False: + print(msg(), file=sys.stderr) + +def exelog(stmt): + if False: + f = open(os.getenv('HOME', '') + "/lldbexelog.txt", "a") + f.write(stmt()) + f.write("\n") + f.close() + +def lldb_val_to_ptr(lldb_val): + addr = lldb_val.GetValueAsUnsigned() + return '((struct ObjHeader *) {:#x})'.format(addr) + + +def evaluate(expr): + result = lldb.debugger.GetSelectedTarget().EvaluateExpression(expr, lldb.SBExpressionOptions()) + evallog = lambda : "{} => {}".format(expr, result) + log(evallog) + exelog(evallog) + return result + +def _symbol_loaded_address(name, debugger = lldb.debugger): + target = debugger.GetSelectedTarget() + process = target.GetProcess() + thread = process.GetSelectedThread() + frame = thread.GetSelectedFrame() + candidates = list(filter(lambda x: x.name == name, frame.module.symbols)) + # take first + for candidate in candidates: + address = candidate.GetStartAddress().GetLoadAddress(target) + log(lambda: "_symbol_loaded_address:{} {:#x}".format(name, address)) + return address + +def _type_info_by_address(address, debugger = lldb.debugger): + target = debugger.GetSelectedTarget() + process = target.GetProcess() + thread = process.GetSelectedThread() + frame = thread.GetSelectedFrame() + candidates = list(filter(lambda x: x.GetStartAddress().GetLoadAddress(target) == address, frame.module.symbols)) + return candidates + +def is_instance_of(addr, typeinfo): + return evaluate("(bool)IsInstance({}, {:#x})".format(addr, typeinfo)).GetValue() == "true" + +def is_string_or_array(value): + return evaluate("(int)IsInstance({0}, {1}) ? 1 : ((int)Konan_DebugIsArray({0}) ? 2 : 0)".format(lldb_val_to_ptr(value), _symbol_loaded_address('kclass:kotlin.String'))).unsigned + +def type_info(value): + """This method checks self-referencing of pointer of first member of TypeInfo including case when object has an + meta-object pointed by TypeInfo. Two lower bits are reserved for memory management needs see runtime/src/main/cpp/Memory.h.""" + if value.GetTypeName() != "ObjHeader *": + return False + expr = "*(void **)((uintptr_t)(*(void**){0:#x}) & ~0x3) == **(void***)((uintptr_t)(*(void**){0:#x}) & ~0x3) ? *(void **)((uintptr_t)(*(void**){0:#x}) & ~0x3) : (void *)0".format(value.unsigned) + result = evaluate(expr) + return result.unsigned if result.IsValid() and result.unsigned != 0 else None + + +__FACTORY = {} + + +# Cache type info pointer to [ChildMetaInfo] +SYNTHETIC_OBJECT_LAYOUT_CACHE = {} +TO_STRING_DEPTH = 2 +ARRAY_TO_STRING_LIMIT = 10 + +def kotlin_object_type_summary(lldb_val, internal_dict = {}): + """Hook that is run by lldb to display a Kotlin object.""" + log(lambda: "kotlin_object_type_summary({:#x}, {})".format(lldb_val.unsigned, internal_dict)) + fallback = lldb_val.GetValue() + if str(lldb_val.type) != "struct ObjHeader *": + if lldb_val.GetValue() is None: + return NULL + return lldb_val.GetValueAsSigned() + + if lldb_val.unsigned == 0: + return NULL + tip = internal_dict["type_info"] if "type_info" in internal_dict.keys() else type_info(lldb_val) + + if not tip: + return fallback + + return select_provider(lldb_val, tip, internal_dict).to_string() + + +def select_provider(lldb_val, tip, internal_dict): + log(lambda : "select_provider: name:{} : {}, {}".format(lldb_val.name, lldb_val, internal_dict)) + soa = is_string_or_array(lldb_val) + log(lambda : "select_provider: {} : soa: {}".format(lldb_val, soa)) + return __FACTORY['string'](lldb_val, tip, internal_dict) if soa == 1 else __FACTORY['array'](lldb_val, tip, internal_dict) if soa == 2 \ + else __FACTORY['object'](lldb_val, tip, internal_dict) + +class KonanHelperProvider(lldb.SBSyntheticValueProvider): + def __init__(self, valobj, amString, internal_dict = {}): + self._target = lldb.debugger.GetSelectedTarget() + self._process = self._target.GetProcess() + self._valobj = valobj + self._ptr = lldb_val_to_ptr(self._valobj) + if amString: + return + self._internal_dict = internal_dict.copy() + self._to_string_depth = TO_STRING_DEPTH if "to_string_depth" not in self._internal_dict.keys() else self._internal_dict["to_string_depth"] + if self._children_count == 0: + self._children_count = evaluate("(int)Konan_DebugGetFieldCount({})".format(self._ptr)).signed + self._children = [] + self._type_conversion = [ + lambda address, name: self._valobj.CreateValueFromExpression(name, "(void *){:#x}".format(address)), + lambda address, name: self._create_synthetic_child(address, name), + lambda address, name: self._valobj.CreateValueFromExpression(name, "(int8_t *){:#x}".format(address)), + lambda address, name: self._valobj.CreateValueFromExpression(name, "(int16_t *){:#x}".format(address)), + lambda address, name: self._valobj.CreateValueFromExpression(name, "(int32_t *){:#x}".format(address)), + lambda address, name: self._valobj.CreateValueFromExpression(name, "(int64_t *){:#x}".format(address)), + lambda address, name: self._valobj.CreateValueFromExpression(name, "(float *){:#x}".format(address)), + lambda address, name: self._valobj.CreateValueFromExpression(name, "(double *){:#x}".format(address)), + lambda address, name: self._valobj.CreateValueFromExpression(name, "(void **){:#x}".format(address)), + lambda address, name: self._valobj.CreateValueFromExpression(name, "(bool *){:#x}".format(address)), + lambda address, name: None] + + self._types = [ + valobj.GetType().GetBasicType(lldb.eBasicTypeVoid).GetPointerType(), + valobj.GetType(), + valobj.GetType().GetBasicType(lldb.eBasicTypeChar), + valobj.GetType().GetBasicType(lldb.eBasicTypeShort), + valobj.GetType().GetBasicType(lldb.eBasicTypeInt), + valobj.GetType().GetBasicType(lldb.eBasicTypeLongLong), + valobj.GetType().GetBasicType(lldb.eBasicTypeFloat), + valobj.GetType().GetBasicType(lldb.eBasicTypeDouble), + valobj.GetType().GetBasicType(lldb.eBasicTypeVoid).GetPointerType(), + valobj.GetType().GetBasicType(lldb.eBasicTypeBool) + ] + + def _read_string(self, expr, error): + return self._process.ReadCStringFromMemory(evaluate(expr).unsigned, 0x1000, error) + + def _read_value(self, index): + value_type = self._children[index].type() + address = self._valobj.unsigned + self._children[index].offset() + return self._type_conversion[int(value_type)](address, str(self._children[index].name())) + + def _create_synthetic_child(self, address, name): + if self._to_string_depth == 0: + return None + index = self.get_child_index(name) + value = self._valobj.CreateChildAtOffset(str(name), + self._children[index].offset(), + self._read_type(index)) + value.SetSyntheticChildrenGenerated(True) + value.SetPreferSyntheticValue(True) + return value + + def _read_type(self, index): + type = self._types[self._children[index].type()] + log(lambda: "type:{0} of {1:#x} of {2:#x}".format(type, self._valobj.unsigned, self._valobj.unsigned + self._children[index].offset())) + return type + + def _deref_or_obj_summary(self, index, internal_dict): + value = self._values[index] + if not value: + log(lambda : "_deref_or_obj_summary: value none, index:{}, type:{}".format(index, self._children[index].type())) + return None + + tip = type_info(value) + if tip: + internal_dict["type_info"] = tip + return kotlin_object_type_summary(value, internal_dict) + tip = type_info(value.deref) + + if tip: + internal_dict["type_info"] = tip + return kotlin_object_type_summary(value.deref, internal_dict) + + return kotlin_object_type_summary(value.deref, internal_dict) + + def _field_address(self, index): + return evaluate("(void *)Konan_DebugGetFieldAddress({}, {})".format(self._ptr, index)).unsigned + + def _field_type(self, index): + return evaluate("(int)Konan_DebugGetFieldType({}, {})".format(self._ptr, index)).unsigned + +class KonanStringSyntheticProvider(KonanHelperProvider): + def __init__(self, valobj): + self._children_count = 0 + super(KonanStringSyntheticProvider, self).__init__(valobj, True) + fallback = valobj.GetValue() + buff_addr = evaluate("(void *)Konan_DebugBuffer()").unsigned + buff_len = evaluate( + '(int)Konan_DebugObjectToUtf8Array({}, (void *){:#x}, (int)Konan_DebugBufferSize());'.format( + self._ptr, buff_addr) + ).signed + + if not buff_len: + self._representation = fallback + return + + error = lldb.SBError() + s = self._process.ReadCStringFromMemory(int(buff_addr), int(buff_len), error) + if not error.Success(): + raise DebuggerException() + self._representation = s if error.Success() else fallback + self._logger = lldb.formatters.Logger.Logger() + + def update(self): + pass + + def num_children(self): + return 0 + + def has_children(self): + return False + + def get_child_index(self, _): + return None + + def get_child_at_index(self, _): + return None + + def to_string(self): + return self._representation + + +class DebuggerException(Exception): + pass + +class MemberLayout: + def __init__(self, name, type, offset): + self._name = name + self._type = type + self._offset = offset + + def name(self): + return self._name + + def type(self): + return self._type + + def offset(self): + return self._offset + +class KonanObjectSyntheticProvider(KonanHelperProvider): + def __init__(self, valobj, tip, internal_dict): + # Save an extra call into the process + if tip in SYNTHETIC_OBJECT_LAYOUT_CACHE: + log(lambda : "TIP: {:#x} EARLYHIT".format(tip)) + self._children = SYNTHETIC_OBJECT_LAYOUT_CACHE[tip] + self._children_count = len(self._children) + else: + self._children_count = 0 + + super(KonanObjectSyntheticProvider, self).__init__(valobj, False, internal_dict) + + if not tip in SYNTHETIC_OBJECT_LAYOUT_CACHE: + SYNTHETIC_OBJECT_LAYOUT_CACHE[tip] = [ + MemberLayout(self._field_name(i), self._field_type(i), self._field_address(i) - self._valobj.unsigned) + for i in range(self._children_count)] + log(lambda : "TIP: {:#x} MISSED".format(tip)) + else: + log(lambda : "TIP: {:#x} HIT".format(tip)) + self._children = SYNTHETIC_OBJECT_LAYOUT_CACHE[tip] + self._values = [self._read_value(index) for index in range(self._children_count)] + + + def _field_name(self, index): + error = lldb.SBError() + name = self._read_string("(void *)Konan_DebugGetFieldName({}, (int){})".format(self._ptr, index), error) + if not error.Success(): + raise DebuggerException() + return name + + def num_children(self): + return self._children_count + + def has_children(self): + return self._children_count > 0 + + def get_child_index(self, name): + def __none(iterable, f): + return not any(f(x) for x in iterable) + if __none(self._children, lambda x: x.name() == name): + return -1 + return next(i for i,v in enumerate(self._children) if v.name() == name) + + def get_child_at_index(self, index): + result = self._values[index] + if result is None: + result = self._read_value(index) + self._values[index] = result + return result + + + # TODO: fix cyclic structures stringification. + def to_string(self): + if self._to_string_depth == 0: + return "..." + else: + internal_dict = self._internal_dict.copy() + internal_dict["to_string_depth"] = self._to_string_depth - 1 + return dict([(self._children[i].name(), self._deref_or_obj_summary(i, internal_dict)) for i in range(self._children_count)]) + +class KonanArraySyntheticProvider(KonanHelperProvider): + def __init__(self, valobj, internal_dict): + self._children_count = 0 + super(KonanArraySyntheticProvider, self).__init__(valobj, False, internal_dict) + if self._ptr is None: + return + valobj.SetSyntheticChildrenGenerated(True) + type = self._field_type(0) + zerro_address = self._field_address(0) + first_address = self._field_address(1) + offset = zerro_address - valobj.unsigned + size = first_address - zerro_address + self._children = [MemberLayout(str(x), type, offset + x * size) for x in range(self.num_children())] + self._values = [self._read_value(i) for i in range(min(ARRAY_TO_STRING_LIMIT, self._children_count))] + + + def cap_children_count(self): + return self._children_count + + def num_children(self): + return self.cap_children_count() + + def has_children(self): + return self._children_count > 0 + + def get_child_index(self, name): + index = int(name) + return index if (0 <= index < self._children_count) else -1 + + def get_child_at_index(self, index): + result = self._values[index] + if result is None: + result = self._read_value(index) + self._values[index] = result + return result + + def to_string(self): + return [self._deref_or_obj_summary(i, self._internal_dict.copy()) for i in range(min(ARRAY_TO_STRING_LIMIT, self._children_count))] + + +class KonanProxyTypeProvider: + def __init__(self, valobj, internal_dict): + log(lambda : "KonanProxyTypeProvider: {:#x}".format(valobj.unsigned)) + tip = type_info(valobj) + + if not tip: + return + log(lambda : "KonanProxyTypeProvider: tip: {:#x}".format(tip)) + self._proxy = select_provider(valobj, tip, internal_dict) + log(lambda: "KonanProxyTypeProvider: _proxy: {}".format(self._proxy.__class__.__name__)) + self.update() + + def __getattr__(self, item): + return getattr(self._proxy, item) + +def clear_cache_command(debugger, command, result, internal_dict): + SYNTHETIC_OBJECT_LAYOUT_CACHE.clear() + + +def type_name_command(debugger, command, result, internal_dict): + result.AppendMessage(evaluate('(char *)Konan_DebugGetTypeName({})'.format(command)).summary) + +__KONAN_VARIABLE = re.compile('kvar:(.*)#internal') +__KONAN_VARIABLE_TYPE = re.compile('^kfun:\\(\\)(.*)$') +__TYPES_KONAN_TO_C = { + 'kotlin.Byte': ('int8_t', lambda v: v.signed), + 'kotlin.Short': ('short', lambda v: v.signed), + 'kotlin.Int': ('int', lambda v: v.signed), + 'kotlin.Long': ('long', lambda v: v.signed), + 'kotlin.UByte': ('int8_t', lambda v: v.unsigned), + 'kotlin.UShort': ('short', lambda v: v.unsigned), + 'kotlin.UInt': ('int', lambda v: v.unsigned), + 'kotlin.ULong': ('long', lambda v: v.unsigned), + 'kotlin.Char': ('short', lambda v: v.signed), + 'kotlin.Boolean': ('bool', lambda v: v.signed), + 'kotlin.Float': ('float', lambda v: v.value), + 'kotlin.Double': ('double', lambda v: v.value) +} + +def type_by_address_command(debugger, command, result, internal_dict): + result.AppendMessage("DEBUG: {}".format(command)) + tokens = command.split() + target = debugger.GetSelectedTarget() + process = target.GetProcess() + thread = process.GetSelectedThread() + types = _type_info_by_address(tokens[0]) + result.AppendMessage("DEBUG: {}".format(types)) + for t in types: + result.AppendMessage("{}: {:#x}".format(t.name, t.GetStartAddress().GetLoadAddress(target))) + +def symbol_by_name_command(debugger, command, result, internal_dict): + target = debugger.GetSelectedTarget() + process = target.GetProcess() + thread = process.GetSelectedThread() + frame = thread.GetSelectedFrame() + tokens = command.split() + mask = re.compile(tokens[0]) + symbols = list(filter(lambda v: mask.match(v.name), frame.GetModule().symbols)) + visited = list() + for symbol in symbols: + name = symbol.name + if name in visited: + continue + visited.append(name) + result.AppendMessage("{}: {:#x}".format(name, symbol.GetStartAddress().GetLoadAddress(target))) + +def konan_globals_command(debugger, command, result, internal_dict): + target = debugger.GetSelectedTarget() + process = target.GetProcess() + thread = process.GetSelectedThread() + frame = thread.GetSelectedFrame() + + konan_variable_symbols = list(filter(lambda v: __KONAN_VARIABLE.match(v.name), frame.GetModule().symbols)) + visited = list() + for symbol in konan_variable_symbols: + name = __KONAN_VARIABLE.search(symbol.name).group(1) + + if name in visited: + continue + visited.append(name) + + getters = list(filter(lambda v: re.match('^kfun:\\(\\).*$'.format(name), v.name), frame.module.symbols)) + if not getters: + result.AppendMessage("storage not found for name:{}".format(name)) + continue + + getter_functions = frame.module.FindFunctions(getters[0].name) + if not getter_functions: + continue + + address = getter_functions[0].function.GetStartAddress().GetLoadAddress(target) + type = __KONAN_VARIABLE_TYPE.search(getters[0].name).group(2) + (c_type, extractor) = __TYPES_KONAN_TO_C[type] if type in __TYPES_KONAN_TO_C.keys() else ('struct ObjHeader *', lambda v: kotlin_object_type_summary(v)) + value = evaluate('(({0} (*)()){1:#x})()'.format(c_type, address)) + str_value = extractor(value) + result.AppendMessage('{} {}: {}'.format(type, name, str_value)) + +def __lldb_init_module(debugger, _): + __FACTORY['object'] = lambda x, y, z: KonanObjectSyntheticProvider(x, y, z) + __FACTORY['array'] = lambda x, y, z: KonanArraySyntheticProvider(x, z) + __FACTORY['string'] = lambda x, y, _: KonanStringSyntheticProvider(x) + debugger.HandleCommand('\ + type summary add \ + --no-value \ + --expand \ + --python-function konan_lldb.kotlin_object_type_summary \ + "struct ObjHeader *" \ + --category Kotlin\ + ') + debugger.HandleCommand('\ + type synthetic add \ + --python-class konan_lldb.KonanProxyTypeProvider\ + "ObjHeader *" \ + --category Kotlin\ + ') + debugger.HandleCommand('type category enable Kotlin') + debugger.HandleCommand('command script add -f {}.clear_cache_command clear_kotlin_cache'.format(__name__)) + debugger.HandleCommand('command script add -f {}.type_name_command type_name'.format(__name__)) + debugger.HandleCommand('command script add -f {}.type_by_address_command type_by_address'.format(__name__)) + debugger.HandleCommand('command script add -f {}.symbol_by_name_command symbol_by_name'.format(__name__)) + diff --git a/kotlin-native/performance/KotlinVsSwift/build.gradle b/kotlin-native/performance/KotlinVsSwift/build.gradle new file mode 100644 index 00000000000..712a7278933 --- /dev/null +++ b/kotlin-native/performance/KotlinVsSwift/build.gradle @@ -0,0 +1,58 @@ +buildscript { + apply from: "$rootProject.projectDir/gradle/kotlinGradlePlugin.gradle" + repositories { + maven { + url 'https://cache-redirector.jetbrains.com/jcenter' + } + jcenter() + } +} + +def rootBuildDirectory = rootProject.projectDir + +task konanRun { + subprojects.each { + dependsOn it.getTasksByName('konanRun', true)[0] + } +} + +task jvmRun { + subprojects.each { + dependsOn it.getTasksByName('jvmRun', true)[0] + } +} + +task clean { + subprojects.each { + dependsOn it.getTasksByName('clean', true)[0] + } + doLast { + delete "${buildDir.absolutePath}" + } +} + +defaultTasks 'konanRun' + +task mergeNativeReports { + doLast { + mergeReports(nativeJson) + uploadBenchmarkResultToArtifactory(nativeJson) + } +} + +task mergeJvmReports { + doLast { + mergeReports(jvmJson) + uploadBenchmarkResultToArtifactory(jvmJson) + } +} + +subprojects.each { + it.getTasksByName('jvmJsonReport', true)[0].finalizedBy mergeJvmReports + it.getTasksByName('konanJsonReport', true)[0].finalizedBy mergeNativeReports +} + +task ring { + dependsOn 'clean' + dependsOn 'ring:konanRun' +} diff --git a/kotlin-native/performance/KotlinVsSwift/ring/build.gradle.kts b/kotlin-native/performance/KotlinVsSwift/ring/build.gradle.kts new file mode 100644 index 00000000000..bb82af8837a --- /dev/null +++ b/kotlin-native/performance/KotlinVsSwift/ring/build.gradle.kts @@ -0,0 +1,22 @@ +/* + * Copyright 2010-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +import org.jetbrains.kotlin.benchmark.CodeSizeEntity + +plugins { + id("swift-benchmarking") +} + +val toolsPath = "../../../tools" + +swiftBenchmark { + applicationName = "Ring" + commonSrcDirs = listOf("$toolsPath/benchmarks/shared/src/main/kotlin", "../../shared/src/main/kotlin") + nativeSrcDirs = listOf("../../shared/src/main/kotlin-native/common", "../../shared/src/main/kotlin-native/posix") + swiftSources = File("$projectDir/src").list().map { "$projectDir/src/$it" }.toList() + compileTasks = listOf("buildSwift") + useCodeSize = CodeSizeEntity.EXECUTABLE + dependencies.common(project(":endorsedLibraries:kotlinx.cli")) +} \ No newline at end of file diff --git a/kotlin-native/performance/KotlinVsSwift/ring/gradle.properties b/kotlin-native/performance/KotlinVsSwift/ring/gradle.properties new file mode 100644 index 00000000000..864349da299 --- /dev/null +++ b/kotlin-native/performance/KotlinVsSwift/ring/gradle.properties @@ -0,0 +1 @@ +kotlin.native.home=../../../dist \ No newline at end of file diff --git a/kotlin-native/performance/KotlinVsSwift/ring/src/AbstractMethodBenchmark.swift b/kotlin-native/performance/KotlinVsSwift/ring/src/AbstractMethodBenchmark.swift new file mode 100644 index 00000000000..c73662c67da --- /dev/null +++ b/kotlin-native/performance/KotlinVsSwift/ring/src/AbstractMethodBenchmark.swift @@ -0,0 +1,39 @@ +/* + * Copyright 2010-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +import Foundation + +class AbstractMethodBenchmark { + private let arr: [String] = zdf_win + private let sequence = "абвгдеёжзийклмнопрстуфхцчшщъыьэюя" + + private var sequenceMap: [Character: Int] = [:] + + init() { + var i = 0 + for ch in sequence { + sequenceMap[ch] = i + i += 1 + } + } + + func sortStrings() -> Set { + var size = arr.count + if (Constants.BENCHMARK_SIZE < size) { + size = Constants.BENCHMARK_SIZE + } + let res = Set(arr[0.. Set { + var res = Set() + var size = Constants.BENCHMARK_SIZE < arr.count ? Constants.BENCHMARK_SIZE : arr.count + arr[0.. Int +} + +protocol E { + func foo() -> Any +} + +extension I { + func foo1() -> Int { + return 1 + } + func foo2() -> Int { + return 2 + } + func foo3() -> Int { + return 3 + } + func foo4() -> Int { + return 4 + } + func foo5() -> Int { + return 5 + } + func foo6() -> Int { + return 6 + } + func foo7() -> Int { + return 7 + } + func foo8() -> Int { + return 8 + } + func foo9() -> Int { + return 9 + } + func foo10() -> Int { + return 10 + } + func foo11() -> Int { + return 11 + } + func foo12() -> Int { + return 12 + } + func foo13() -> Int { + return 13 + } + func foo14() -> Int { + return 14 + } + func foo15() -> Int { + return 15 + } + func foo16() -> Int { + return 16 + } + func foo17() -> Int { + return 17 + } + func foo18() -> Int { + return 18 + } + func foo19() -> Int { + return 19 + } + func foo20() -> Int { + return 20 + } + func foo21() -> Int { + return 21 + } + func foo22() -> Int { + return 22 + } + func foo23() -> Int { + return 23 + } + func foo24() -> Int { + return 24 + } + func foo25() -> Int { + return 25 + } + func foo26() -> Int { + return 26 + } + func foo27() -> Int { + return 27 + } + func foo28() -> Int { + return 28 + } + func foo29() -> Int { + return 29 + } + func foo30() -> Int { + return 30 + } + func foo31() -> Int { + return 31 + } + func foo32() -> Int { + return 32 + } + func foo33() -> Int { + return 33 + } + func foo34() -> Int { + return 34 + } + func foo35() -> Int { + return 35 + } + func foo36() -> Int { + return 36 + } + func foo37() -> Int { + return 37 + } + func foo38() -> Int { + return 38 + } + func foo39() -> Int { + return 39 + } + func foo40() -> Int { + return 40 + } + func foo41() -> Int { + return 41 + } + func foo42() -> Int { + return 42 + } + func foo43() -> Int { + return 43 + } + func foo44() -> Int { + return 44 + } + func foo45() -> Int { + return 45 + } + func foo46() -> Int { + return 46 + } + func foo47() -> Int { + return 47 + } + func foo48() -> Int { + return 48 + } + func foo49() -> Int { + return 49 + } + func foo50() -> Int { + return 50 + } + func foo51() -> Int { + return 51 + } + func foo52() -> Int { + return 52 + } + func foo53() -> Int { + return 53 + } + func foo54() -> Int { + return 54 + } + func foo55() -> Int { + return 55 + } + func foo56() -> Int { + return 56 + } + func foo57() -> Int { + return 57 + } + func foo58() -> Int { + return 58 + } + func foo59() -> Int { + return 59 + } + func foo60() -> Int { + return 60 + } + func foo61() -> Int { + return 31 + } + func foo62() -> Int { + return 62 + } + func foo63() -> Int { + return 63 + } + func foo64() -> Int { + return 64 + } + func foo65() -> Int { + return 65 + } + func foo66() -> Int { + return 66 + } + func foo67() -> Int { + return 67 + } + func foo68() -> Int { + return 68 + } + func foo69() -> Int { + return 69 + } + func foo70() -> Int { + return 70 + } + func foo71() -> Int { + return 71 + } + func foo72() -> Int { + return 72 + } + func foo73() -> Int { + return 73 + } + func foo74() -> Int { + return 74 + } + func foo75() -> Int { + return 75 + } + func foo76() -> Int { + return 76 + } + func foo77() -> Int { + return 77 + } + func foo78() -> Int { + return 78 + } + func foo79() -> Int { + return 79 + } + func foo80() -> Int { + return 80 + } + func foo81() -> Int { + return 81 + } + func foo82() -> Int { + return 82 + } + func foo83() -> Int { + return 83 + } + func foo84() -> Int { + return 84 + } + func foo85() -> Int { + return 85 + } + func foo86() -> Int { + return 86 + } + func foo87() -> Int { + return 87 + } + func foo88() -> Int { + return 88 + } + func foo89() -> Int { + return 89 + } + func foo90() -> Int { + return 90 + } + func foo91() -> Int { + return 91 + } + func foo92() -> Int { + return 92 + } + func foo93() -> Int { + return 93 + } + func foo94() -> Int { + return 94 + } + func foo95() -> Int { + return 95 + } + func foo96() -> Int { + return 96 + } + func foo97() -> Int { + return 97 + } + func foo98() -> Int { + return 98 + } + func foo99() -> Int { + return 99 + } + +} + +protocol A : I {} + +class CallsBenchmarks { + class B : A { + func foo() -> Int { + return 42 + } + } + class C : A { + func foo() -> Int { + return 117 + } + } + class D : A { + func foo() -> Int { + return 314 + } + } + class X : A { + func foo() -> Int { + return 456456 + } + } + class Y : A { + func foo() -> Int { + return -398473 + } + } + class Z : A { + func foo() -> Int { + return 8298734 + } + } + + let d = D() + let a1: A = B() + let a2: A = C() + lazy var a3: A = d + lazy var i1: I = a1 + lazy var i2: I = a2 + lazy var i3: I = d + let i4: I = X() + let i5: I = Y() + let i6: I = Z() + + func finalMethodCall() -> Int { + var x = 0 + let d = self.d + for _ in 0.. Int { + var x = 0 + let a1 = self.a1 + for _ in 0.. Int { + var x = 0 + let a1 = self.a1 + let a2 = self.a2 + for i in 0.. Int { + var x = 0 + + let a1 = self.a1 + let a2 = self.a2 + let a3 = self.a3 + for i in 0.. Int { + var x = 0 + let i1 = self.i1 + for _ in 0.. Int { + var x = 0 + let i1 = self.i1 + let i2 = self.i2 + for i in 0.. Int { + var x = 0 + let i1 = self.i1 + let i2 = self.i2 + let i3 = self.i3 + for i in 0.. Int { + var x = 0 + let i1 = self.i1 + let i2 = self.i2 + let i3 = self.i3 + let i4 = self.i4 + let i5 = self.i5 + let i6 = self.i6 + for i in 0.. Any { + return 42 + } + } + + let e: E = F() + + func returnBoxUnboxFolding() -> Int { + var x = 0 + let e = self.e + for _ in 0.. Int { + var x = x + if (c is C0) { + x = x &+ i + } + if (c is C1) { + x = x ^ i + } + if (c is C2) { + x = x &+ i + } + if (c is C3) { + x = x ^ i + } + if (c is C4) { + x = x &+ i + } + if (c is C5) { + x = x ^ i + } + if (c is C6) { + x = x &+ i + } + if (c is C7) { + x = x ^ i + } + if (c is C8) { + x = x &+ i + } + if (c is C9) { + x = x ^ i + } + return x + } + + private func foo_iface(_ c: Any, _ x: Int, _ i: Int) -> Int { + var x = x + if (c is I0) { + x = x &+ i + } + if (c is I1) { + x = x ^ i + } + if (c is I2) { + x = x &+ i + } + if (c is I3) { + x = x ^ i + } + if (c is I4) { + x = x &+ i + } + if (c is I5) { + x = x ^ i + } + if (c is I6) { + x = x &+ i + } + if (c is I7) { + x = x ^ i + } + if (c is I8) { + x = x &+ i + } + if (c is I9) { + x = x ^ i + } + return x + } + + func classCast() -> Int { + let c0: Any = C0() + let c1: Any = C1() + let c2: Any = C2() + let c3: Any = C3() + let c4: Any = C4() + let c5: Any = C5() + let c6: Any = C6() + let c7: Any = C7() + let c8: Any = C8() + let c9: Any = C9() + + var x = 0 + for i in 0.. Int { + let c0: Any = C0() + let c1: Any = C1() + let c2: Any = C2() + let c3: Any = C3() + let c4: Any = C4() + let c5: Any = C5() + let c6: Any = C6() + let c7: Any = C7() + let c8: Any = C8() + let c9: Any = C9() + + var x = 0 + for i in 0.. [Value] { + return Array(data) + } + + func copyManual() -> [Value] { + var list: [Value] = [] + for item in data { + list.append(item) + } + return list + } + + func filterAndCount() -> Int { + return data.filter { filterLoad($0) }.count + } + + func filterAndMap() -> [String] { + return data.filter { filterLoad($0) }.map { mapLoad($0) } + } + + func filterAndMapManual() -> [String] { + var list: [String] = [] + for it in data { + if (filterLoad(it)) { + let value = mapLoad(it) + list.append(value) + } + } + return list + } + + func filter() -> [Value] { + return data.filter { filterLoad($0) } + } + + func filterManual() -> [Value] { + var list: [Value] = [] + for it in data { + if (filterLoad(it)) { + list.append(it) + } + } + return list + } + + func countFilteredManual() -> Int { + var count = 0 + for it in data { + if (filterLoad(it)) { + count += 1 + } + } + return count + } + + func countFiltered() -> Int { + return data.count { filterLoad($0) } + } + + func countFilteredLocal() -> Int { + return data.cnt { filterLoad($0) } + } +} + +extension Collection { + func count(where test: (Element) throws -> Bool) rethrows -> Int { + return try self.filter(test).count + } +} diff --git a/kotlin-native/performance/KotlinVsSwift/ring/src/ClassBaselineBenchmark.swift b/kotlin-native/performance/KotlinVsSwift/ring/src/ClassBaselineBenchmark.swift new file mode 100644 index 00000000000..2d20dfe42d4 --- /dev/null +++ b/kotlin-native/performance/KotlinVsSwift/ring/src/ClassBaselineBenchmark.swift @@ -0,0 +1,60 @@ +/* + * Copyright 2010-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +import Foundation + +class ClassBaselineBenchmark { + + func consume() { + for item in 1...Constants.BENCHMARK_SIZE { + Blackhole.consume(Value(item)) + } + } + + func consumeField() { + let value = Value(0) + for item in 1...Constants.BENCHMARK_SIZE { + value.value = item + Blackhole.consume(value) + } + } + + func allocateList() -> [Value] { + let list = [Value](repeating: Value(0), count: Constants.BENCHMARK_SIZE) + return list + } + + func allocateArray() -> [Value?] { + let list = [Value?](repeating: nil, count: Constants.BENCHMARK_SIZE) + return list + } + + func allocateListAndFill() -> [Value] { + var list: [Value] = [] + for item in 1...Constants.BENCHMARK_SIZE { + list.append(Value(item)) + } + return list + } + + func allocateListAndWrite() -> [Value] { + let value = Value(0) + var list: [Value] = [] + for _ in 1...Constants.BENCHMARK_SIZE { + list.append(value) + } + return list + } + + func allocateArrayAndFill() -> [Value?] { + var list = [Value?](repeating: nil, count: Constants.BENCHMARK_SIZE) + var index = 0 + for item in 1...Constants.BENCHMARK_SIZE { + list[index] = Value(item) + index += 1 + } + return list + } +} diff --git a/kotlin-native/performance/KotlinVsSwift/ring/src/ClassListBenchmark.swift b/kotlin-native/performance/KotlinVsSwift/ring/src/ClassListBenchmark.swift new file mode 100644 index 00000000000..963cb10892e --- /dev/null +++ b/kotlin-native/performance/KotlinVsSwift/ring/src/ClassListBenchmark.swift @@ -0,0 +1,50 @@ +/* + * Copyright 2010-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +import Foundation + + +class ClassListBenchmark { + private var _data: [Value]? = nil + var data: [Value] { + return _data! + } + + init() { + var list: [Value] = [] + for n in classValues(Constants.BENCHMARK_SIZE) { + list.append(n) + } + _data = list + } + + func filterAndCountWithLambda() -> Int { + return data.filter { $0.value % 2 == 0 }.count + } + + func filterWithLambda() -> [Value] { + return data.filter { $0.value % 2 == 0 } + } + + func mapWithLambda() -> [String] { + return data.map { String($0.value) } + } + + func countWithLambda() -> Int { + return data.count { $0.value % 2 == 0 } + } + + func filterAndMapWithLambda() -> [String] { + return data.filter { $0.value % 2 == 0 }.map { String($0.value) } + } + + func filterAndMapWithLambdaAsSequence() -> [String] { + return data.lazy.filter { $0.value % 2 == 0 }.map { String($0.value) } + } + + func reduce() -> Int { + return data.reduce(0) { if (filterLoad($1)) { return $0 + 1 } else { return $0 }} + } +} diff --git a/kotlin-native/performance/KotlinVsSwift/ring/src/ClassStreamBenchmark.swift b/kotlin-native/performance/KotlinVsSwift/ring/src/ClassStreamBenchmark.swift new file mode 100644 index 00000000000..6e9bbf62a45 --- /dev/null +++ b/kotlin-native/performance/KotlinVsSwift/ring/src/ClassStreamBenchmark.swift @@ -0,0 +1,77 @@ +/* + * Copyright 2010-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +import Foundation + +class ClassStreamBenchmark { + private var _data: AnySequence? = nil + var data: AnySequence { + return _data! + } + + init() { + _data = AnySequence(classValues(Constants.BENCHMARK_SIZE)) + } + + func copy() -> [Value] { + return Array(data) + } + + func copyManual() -> [Value] { + var list: [Value] = [] + for item in data.lazy { + list.append(item) + } + return list + } + + func filterAndCount() -> Int { + return data.lazy.filter { filterLoad($0) }.count + } + + func filterAndMap() { + for item in (data.lazy.filter { filterLoad($0) }.map { mapLoad($0) }) { + Blackhole.consume(item) + } + } + + func filterAndMapManual() { + for it in data.lazy { + if (filterLoad(it)) { + let item = mapLoad(it) + Blackhole.consume(item) + } + } + } + + func filter() { + for item in (data.lazy.filter { filterLoad($0) }) { + Blackhole.consume(item) + } + } + + func filterManual() { + for it in data.lazy { + if (filterLoad(it)) { + Blackhole.consume(it) + } + } + } + + func countFilteredManual() -> Int { + var count = 0 + for it in data.lazy { + if (filterLoad(it)) { + count += 1 + } + } + return count + } + + + func reduce() -> Int { + return data.lazy.reduce(0) {if (filterLoad($1)) { return $0 + 1 } else { return $0 }} + } +} diff --git a/kotlin-native/performance/KotlinVsSwift/ring/src/CompanionObjectBenchmark.swift b/kotlin-native/performance/KotlinVsSwift/ring/src/CompanionObjectBenchmark.swift new file mode 100644 index 00000000000..d6f18a28c95 --- /dev/null +++ b/kotlin-native/performance/KotlinVsSwift/ring/src/CompanionObjectBenchmark.swift @@ -0,0 +1,16 @@ +/* + * Copyright 2010-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +import Foundation + +class CompanionObjectBenchmark { + func invokeRegularFunction() { + CompanionObjectBenchmark.regularCompanionObjectFunction("") + } + + static func regularCompanionObjectFunction(_ o: Any) -> Any { + return o + } +} diff --git a/kotlin-native/performance/KotlinVsSwift/ring/src/CoordinatesSolver.swift b/kotlin-native/performance/KotlinVsSwift/ring/src/CoordinatesSolver.swift new file mode 100644 index 00000000000..7a3f1cc46c6 --- /dev/null +++ b/kotlin-native/performance/KotlinVsSwift/ring/src/CoordinatesSolver.swift @@ -0,0 +1,365 @@ +/* + * Copyright 2010-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +import Foundation + +class CoordinatesSolverBenchmark { + let solver: Solver + + init() { + let inputValue = """ +12 5 3 25 3 9 3 9 1 3 +13 3 12 6 10 10 12 2 10 10 +9 2 9 5 6 12 5 0 2 10 +10 14 12 5 3 9 5 2 10 10 +8 1 3 9 4 0 3 14 10 10 +12 0 4 6 9 6 12 5 6 10 +11 12 3 9 6 9 5 3 9 6 +8 5 6 8 3 12 7 10 10 11 +12 3 13 6 12 3 9 6 12 2 +13 4 5 5 5 6 12 5 5 2 +1 +""" + let input = CoordinatesSolverBenchmark.readTillParsed(inputValue) + + solver = Solver(input!) + } + + struct Coordinate: Equatable { + let x: Int + let y: Int + } + + struct Field { + let x: Int + let y: Int + let value: Int8 + func northWall() -> Bool { + return value & 1 != 0 + } + + func eastWall() -> Bool { + return value & 2 != 0 + } + + func southWall() -> Bool { + return value & 4 != 0 + } + + func westWall() -> Bool { + return value & 8 != 0 + } + + func hasObject() -> Bool { + return value & 16 != 0 + } + } + + struct Input { + let labyrinth: Labyrinth + let nObjects: Int + } + + class Labyrinth { + let width: Int + let height: Int + let fields: [Field] + init(_ width: Int, _ height: Int, _ fields: Array) { + self.width = width + self.height = height + self.fields = fields + } + func getField(_ x: Int, _ y: Int) -> Field { + return fields[x + y * width] + } + } + + struct Output { + let steps: [Coordinate?] + } + + class InputParser { + private var rows : [[Field]] = [] + private var numObjects: Int = 0 + + private var input: Input { + get { + let width = rows[0].count + var fields = [Field?](repeating: nil, count: width * rows.count) + + for y in rows.indices { + let row = rows[y] + for p in (y*width)..<(y*width + width) { + fields[p] = row[p-y*width] + } + } + + let labyrinth = Labyrinth(width, rows.count, fields.filter { $0 != nil } as! Array) + + return Input(labyrinth: labyrinth, nObjects: numObjects) + } + } + + func feedLine(line: String) -> Input? { + let items = line.split(separator: " ").filter { $0 != "" } + + if (items.count == 1) { + numObjects = Int(items[0]) ?? 0 + return input + } else if (items.count > 0) { + let rowNum = rows.count + var row = [Field?](repeating: nil, count: items.count) + + for col in items.indices { + row[col] = Field(x: rowNum, y: col, value: Int8(items[col]) ?? 0) + } + + rows.append(row as! [CoordinatesSolverBenchmark.Field]) + } + + return nil + } + } + + + class Solver { + private let input: Input + init(_ input: Input) { + self.input = input + objects = [] + for f in input.labyrinth.fields { + if (f.hasObject()) { + objects.append(Coordinate(x: f.x, y: f.y)) + } + } + + width = input.labyrinth.width + height = input.labyrinth.height + maze_end = Coordinate(x: width - 1, y: height - 1) + } + private var objects: [Coordinate] + + private let width: Int + private let height: Int + private let maze_end: Coordinate + + private var counter: Int64 = 0 + + func solve() -> Output { + var steps = [Coordinate]() + + for o in objects.indices { + var limit = input.labyrinth.width + input.labyrinth.height - 2 + + var ss: [Coordinate]? = nil + while (ss == nil) { + if (o == 0) { + ss = solveWithLimit(limit, Solver.MAZE_START) { $0[$0.count - 1] == objects[0] } + } else { + ss = solveWithLimit(limit, objects[o - 1]) { $0[$0.count - 1] == objects[o] } + } + + if (ss != nil) { + steps.append(contentsOf: ss!) + } + + limit += 1 + } + } + + var limit = input.labyrinth.width + input.labyrinth.height - 2 + + var ss: [Coordinate]? = nil + while (ss == nil) { + ss = solveWithLimit(limit, objects[objects.count - 1]) { $0[$0.count - 1] == maze_end } + + if (ss != nil) { + steps.append(contentsOf: ss!) + } + + limit += 1 + } + + return createOutput(steps: steps) + } + + private func createOutput(steps: [Coordinate]) -> Output { + var objects : [Coordinate] = self.objects + var outSteps : [Coordinate?] = [] + + for step in steps { + outSteps.append(step) + + if (objects.contains(step)) { + outSteps.append(nil) + objects = objects.filter { $0 != step } + } + } + + return Output(steps: outSteps) + } + + private func isValid(steps: [Coordinate]) -> Bool { + counter += 1 + let coords = steps[steps.count - 1] + let x = coords.x + let y = coords.y + return (!(x == input.labyrinth.width - 1 && y == input.labyrinth.height - 1)) ? false : objects.filter{ steps.contains($0) == false }.count == 0 + } + + private func getPossibleSteps(_ now: Coordinate, _ previous: Coordinate?) -> [Coordinate] { + let field = input.labyrinth.getField(now.x, now.y) + + var possibleSteps: [Coordinate] = [] + + if (now.x != width - 1 && !field.eastWall()) { + possibleSteps.append(Coordinate(x: now.x + 1, y: now.y)) + } + if (now.x != 0 && !field.westWall()) { + possibleSteps.append(Coordinate(x: now.x - 1, y: now.y)) + } + if (now.y != 0 && !field.northWall()) { + possibleSteps.append(Coordinate(x: now.x, y: now.y - 1)) + } + if (now.y != height - 1 && !field.southWall()) { + possibleSteps.append(Coordinate(x: now.x, y: now.y + 1)) + } + + if (!field.hasObject() && previous != nil) { + possibleSteps = possibleSteps.filter { $0 != previous } + } + + return possibleSteps + } + + private func solveWithLimit(_ limit: Int, _ start: Coordinate, _ validFn: ([Coordinate]) -> Bool) -> [Coordinate]? { + var steps: [Coordinate]? = findFirstLegitSteps(nil, start, limit) + + while (steps != nil && !validFn(steps!)) { + steps = alter(start, nil, &steps!) + } + + return steps + } + + private func findFirstLegitSteps(_ startPrev: Coordinate?, _ start: Coordinate, _ num: Int) -> [Coordinate]? { + var steps: [Coordinate]? = [] + + var i = 0 + while (i < num) { + let prev: Coordinate? + let state: Coordinate + + if (i == 0) { + state = start + prev = startPrev + } else if (i == 1) { + state = steps![i - 1] + prev = startPrev + } else { + state = steps![i - 1] + prev = steps![i - 2] + } + + let possibleSteps = getPossibleSteps(state, prev) + + if (possibleSteps.count == 0) { + if (steps!.count == 0) { + return nil + } + + steps = alter(start, startPrev, &steps!) + if (steps == nil) { + return nil + } + + i -= 1 + i += 1 + continue + } + + let newStep = possibleSteps[0] + steps!.append(newStep) + i += 1 + } + + return steps + } + + private func alter(_ start: Coordinate, _ startPrev: Coordinate?, _ steps: inout [Coordinate]) -> [Coordinate]? { + let size = steps.count + + var i = size - 1 + while (i >= 0) { + let current = steps[i] + let prev = i == 0 ? start : steps[i - 1] + let prevprev: Coordinate? + if (i > 1) { + prevprev = steps[i - 2] + } else if (i == 1) { + prevprev = start + } else { + prevprev = startPrev + } + + let alternatives = getPossibleSteps(prev, prevprev) + let index = alternatives.firstIndex(of: current) + + if (index != nil && index != alternatives.count - 1) { + let newItem = alternatives[index! + 1] + steps[i] = newItem + + let remainder = findFirstLegitSteps(prev, newItem, size - i - 1) + if (remainder == nil) { + i += 1 + i -= 1 + continue + } + + Solver.removeAfterIndexExclusive(&steps, i) + steps.append(contentsOf: remainder ?? []) + + return steps + } else { + if (i == 0) { + return nil + } + } + i -= 1 + } + + return steps + } + + + private static let MAZE_START = Coordinate(x: 0, y: 0) + private static func removeAfterIndexExclusive(_ list: inout [Coordinate], _ index: Int) { + let rnum = list.count - 1 - index + + for _ in 0.. Input? { + let parser = InputParser() + var input: Input? = nil + inputValue.split(separator: "\n").forEach { line in + input = parser.feedLine(line: String(line)) + } + + return input + } + + func solve() { + let output = solver.solve() + + for c in output.steps { + let value = (c == nil) ? "felvesz" : "${c.x} ${c.y}" + } + } +} diff --git a/kotlin-native/performance/KotlinVsSwift/ring/src/Data.swift b/kotlin-native/performance/KotlinVsSwift/ring/src/Data.swift new file mode 100644 index 00000000000..5f7c1f2b84a --- /dev/null +++ b/kotlin-native/performance/KotlinVsSwift/ring/src/Data.swift @@ -0,0 +1,114 @@ +/* + * Copyright 2010-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +import Foundation + +public class Value: Hashable { + public func hash(into hasher: inout Hasher) { + return value.hash(into: &hasher) + } + + public static func == (lhs: Value, rhs: Value) -> Bool { + return lhs.value == rhs.value + } + + public var hashValue: Int { + return value.hashValue + } + + var value: Int + init(_ value: Int) { + self.value = value + } + lazy var text = String(String(value).reversed()) +} + +public func intValues(_ size: Int) -> [Int] { + return Array(1...size) +} + +public func classValues(_ size: Int) -> [Value] { + return intValues(size).map { Value($0) } +} + +public func stringValues(_ size: Int) -> [String] { + return intValues(size).map { String($0) } +} + +public func filterLoad(_ v: Value) -> Bool { + return v.text.contains(String(v.value)) +} + +public func mapLoad(_ v: Value) -> String { + return String(v.text.reversed()) +} + +public func filterLoad(_ v: Int) -> Bool { + return "0123456789".contains(String(v)) +} + +public func mapLoad(_ v: Int) -> String { + return String(v) +} + +public func filterSome(_ v: Int) -> Bool { + return v % 7 == 0 || v % 11 == 0 +} + +public func filterPrime(_ v: Int) -> Bool { + if (v <= 1) { + return false + } + if (v <= 3) { + return true + } + if (v % 2 == 0) { + return false + } + var i = 3 + while (i*i <= v) { + if (v % i == 0) { + return false + } + i += 2 + } + return true +} + +extension Array where Element: Value { + @inlinable func cnt(predicate: (Value) -> Bool) -> Int { + var count = 0 + for element in self { + if (predicate(element)) { + count += 1 + } + } + return count + } +} + +extension Array where Element == Int { + @inlinable func cnt(predicate: (Int) -> Bool) -> Int { + var count = 0 + for element in self { + if (predicate(element)) { + count += 1 + } + } + return count + } +} + +extension Sequence where Element == Int { + @inlinable func cnt(predicate: (Int) -> Bool) -> Int { + var count = 0 + for element in self { + if (predicate(element)) { + count += 1 + } + } + return count + } +} diff --git a/kotlin-native/performance/KotlinVsSwift/ring/src/DefaultArgumentBenchmark.swift b/kotlin-native/performance/KotlinVsSwift/ring/src/DefaultArgumentBenchmark.swift new file mode 100644 index 00000000000..a4109355c7f --- /dev/null +++ b/kotlin-native/performance/KotlinVsSwift/ring/src/DefaultArgumentBenchmark.swift @@ -0,0 +1,52 @@ +/* + * Copyright 2010-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +import Foundation + +class DefaultArgumentBenchmark { + private var arg = 0 + + init() { + arg = Int.random(in: 0...100) + } + + + func sumTwo(_ first: Int, _ second: Int = 0) -> Int { + return first + second + } + + + func sumFour(_ first: Int, _ second: Int = 0, _ third: Int = 1, _ fourth: Int = 1) -> Int { + return first + second + third + fourth + } + + func sumEight(_ first: Int, _ second: Int = 0, _ third: Int = 1, _ fourth: Int = 1, _ fifth: Int = 1, _ sixth: Int = 1, _ seventh: Int = 1, _ eighth: Int = 1) -> Int { + return first + second + third + fourth + fifth + sixth + seventh + eighth + } + + func testOneOfTwo() { + sumTwo(arg) + } + + func testTwoOfTwo() { + sumTwo(arg, arg) + } + + func testOneOfFour() { + sumFour(arg) + } + + func testFourOfFour() { + sumFour(arg, arg, arg, arg) + } + + func testOneOfEight() { + sumEight(arg) + } + + func testEightOfEight() { + sumEight(arg, arg, arg, arg, arg, arg, arg, arg) + } +} diff --git a/kotlin-native/performance/KotlinVsSwift/ring/src/ElvisBenchmark.swift b/kotlin-native/performance/KotlinVsSwift/ring/src/ElvisBenchmark.swift new file mode 100644 index 00000000000..2b977140ac6 --- /dev/null +++ b/kotlin-native/performance/KotlinVsSwift/ring/src/ElvisBenchmark.swift @@ -0,0 +1,34 @@ +/* + * Copyright 2010-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +import Foundation + +class ElvisBenchmark { + + class Value { + var value: Int + init(_ value: Int) { + self.value = value + } + } + + var array : [Value?] = [] + + init() { + array = (0 ..< Constants.BENCHMARK_SIZE).map { _ in + if (Int.random(in: 0...Constants.BENCHMARK_SIZE) < Constants.BENCHMARK_SIZE / 10) { + return nil + } else { + return Value(Int.random(in: 0...100)) + } + } + } + + func testElvis() { + for obj in array { + Blackhole.consume(obj?.value ?? 0) + } + } +} diff --git a/kotlin-native/performance/KotlinVsSwift/ring/src/EulerBenchmark.swift b/kotlin-native/performance/KotlinVsSwift/ring/src/EulerBenchmark.swift new file mode 100644 index 00000000000..c32385b7ef9 --- /dev/null +++ b/kotlin-native/performance/KotlinVsSwift/ring/src/EulerBenchmark.swift @@ -0,0 +1,241 @@ +/* + * Copyright 2010-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +import Foundation + + +struct FibonacciGenerator: Sequence, IteratorProtocol { + var a = 0 + var b = 1 + var current = 1 + mutating func next() -> Int? { + defer { + current = a + b + a = b + b = current + } + return current + } +} + +extension Int64 { + func isPalindrome() -> Bool { + return String(self) == String(String(self).reversed()) + } +} + +extension Range where Bound == Int { + @inlinable func sum(_ predicate: (Int) -> Bool) -> Int { + var sum = 0 + for i in self { + if (predicate(i)) { + sum += i + } + } + return sum + } +} + +extension Sequence where Element == Int { + @inlinable func sum(_ predicate: (Int) -> Bool) -> Int { + var sum = 0 + for i in self { + if (predicate(i)) { + sum += i + } + } + return sum + } +} + +extension Sequence { + func takeWhile(condition: (Element) -> Bool) -> [Element] { + var result: [Element] = [] + for x in self { + guard condition(x) else { break } + result.append(x) + } + return result + } +} + +class EulerBenchmark { + func problem1bySequence() -> Int { + return AnySequence(1...Constants.BENCHMARK_SIZE).lazy.sum( { $0 % 3 == 0 || $0 % 5 == 0} ) + } + + func problem1() -> Int { + return (1...Constants.BENCHMARK_SIZE).sum( { $0 % 3 == 0 || $0 % 5 == 0} ) + } + + func problem2() -> Int { + return FibonacciGenerator().takeWhile { $0 < Constants.BENCHMARK_SIZE }.sum { $0 % 2 == 0 } + } + + func problem4() -> Int64 { + let s: Int64 = Int64(Constants.BENCHMARK_SIZE) + let maxLimit = (s-1)*(s-1) + let minLimit = (s/10)*(s/10) + let maxDiv = Constants.BENCHMARK_SIZE-1 + let minDiv = Constants.BENCHMARK_SIZE/10 + for i in stride(from: maxLimit, through: minLimit, by: -1) { + if (!i.isPalindrome()) { + continue + } + for j in minDiv...maxDiv { + if (i % Int64(j) == 0) { + let res = i / Int64(j) + if ((Int64(minDiv)...Int64(maxDiv)).contains(res)) { + return i + } + } + } + } + return -1 + } + + private let veryLongNumber = """ + 73167176531330624919225119674426574742355349194934 + 96983520312774506326239578318016984801869478851843 + 85861560789112949495459501737958331952853208805511 + 12540698747158523863050715693290963295227443043557 + 66896648950445244523161731856403098711121722383113 + 62229893423380308135336276614282806444486645238749 + 30358907296290491560440772390713810515859307960866 + 70172427121883998797908792274921901699720888093776 + 65727333001053367881220235421809751254540594752243 + 52584907711670556013604839586446706324415722155397 + 53697817977846174064955149290862569321978468622482 + 83972241375657056057490261407972968652414535100474 + 82166370484403199890008895243450658541227588666881 + 16427171479924442928230863465674813919123162824586 + 17866458359124566529476545682848912883142607690042 + 24219022671055626321111109370544217506941658960408 + 07198403850962455444362981230987879927244284909188 + 84580156166097919133875499200524063689912560717606 + 05886116467109405077541002256983155200055935729725 + 71636269561882670428252483600823257530420752963450 + """ + + func problem8() -> Int64 { + var productSize = 13 + if ((1...10).contains(Constants.BENCHMARK_SIZE)) { + productSize = 4 + } else if ((11...1000).contains(Constants.BENCHMARK_SIZE)) { + productSize = 8 + } + var digits: [Int] = [] + for digit in veryLongNumber { + if (("0"..."9").contains(digit)) { + if let number = Int(String(digit)) { + if let secNumber = Int(String("0")) { + digits.append(number - secNumber) + } + } + } + } + var largest: Int64 = 0 + for i in 0...digits.count - productSize - 1 { + var product: Int64 = 1 + for j in 0...productSize-1 { + product *= Int64(digits[i+j]) + } + if (product > largest) { + largest = product + } + } + return largest + } + + func problem9() -> Int64 { + for c in Constants.BENCHMARK_SIZE/3...Constants.BENCHMARK_SIZE-3 { + let c2 = Int64(c) * Int64(c) + for b in (Constants.BENCHMARK_SIZE-c)/2..= Constants.BENCHMARK_SIZE) { + break + } + let a = Constants.BENCHMARK_SIZE - b - c + if (a >= b) { + continue + } + let b2 = Int64(b) * Int64(b) + let a2 = Int64(a) * Int64(a) + if (c2 == b2 + a2) { + return Int64(a) * Int64(b) * Int64(c) + } + } + } + return -1 + } + + class Children { + let left: Int + let right: Int + init(_ left: Int, _ right: Int) { + self.left = left + self.right = right + } + } + + func problem14() -> [Int] { + // Build a tree + // index is produced from first & second + let tree = (0..4 && (i+2) % 6 == 0) ? (i-1)/3 : 0)} + // Find longest chain by DFS + func dfs(_ begin: Int) -> [Int] { + if (begin == 0 || begin >= Constants.BENCHMARK_SIZE) { + return [] + } + let left = dfs(tree[begin].left) + let right = dfs(tree[begin].right) + return [begin] + ((left.count > right.count) ? left : right) + } + return dfs(1) + } + + class Way { + let length: Int + let next: Int + init(_ length: Int, _ next: Int) { + self.length = length + self.next = next + } + } + + func problem14full() -> [Int] { + var map: [Int: Way] = [:] + // Starting point + map[1] = Way(0, 0) + // Check all other numbers + var bestNum = 0 + var bestLen = 0 + func go(_ begin: Int) -> Way { + let res = map[begin] + if (res != nil) { + return res! + } + let next = (begin % 2 == 0) ? begin/2 : 3*begin+1 + let childRes = go(next) + let myRes = Way(childRes.length + 1, next) + map[begin] = myRes + return myRes + } + for i in 2...Constants.BENCHMARK_SIZE-1 { + let res = go(i) + if (res.length > bestLen) { + bestLen = res.length + bestNum = i + } + } + func unroll(_ begin: Int) -> [Int] { + if (begin == 0) { + return [] + } + let next = map[begin]?.next ?? 0 + return [begin] + unroll(next) + } + return unroll(bestNum) + } +} diff --git a/kotlin-native/performance/KotlinVsSwift/ring/src/FibonacciBenchmark.swift b/kotlin-native/performance/KotlinVsSwift/ring/src/FibonacciBenchmark.swift new file mode 100644 index 00000000000..cf99f9b28c2 --- /dev/null +++ b/kotlin-native/performance/KotlinVsSwift/ring/src/FibonacciBenchmark.swift @@ -0,0 +1,56 @@ +/* + * Copyright 2010-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +import Foundation + +class FibonacciBenchmark { + func calcClassic() -> Int64 { + var a: Int64 = 1 + var b: Int64 = 2 + let size = Constants.BENCHMARK_SIZE + for _ in 0...size-1 { + let next = a &+ b + a = b + b = next + } + return b + } + + func calc() -> Int64 { + var a: Int64 = 1 + var b: Int64 = 2 + for _ in stride(from: Constants.BENCHMARK_SIZE, through: 1, by: -1) { + let next = a &+ b + a = b + b = next + } + return b + } + + func calcWithProgression() -> Int64 { + var a: Int64 = 1 + var b: Int64 = 2 + for _ in stride(from: 1, through: 2*Constants.BENCHMARK_SIZE-1, by: 2) { + let next = a &+ b + a = b + b = next + } + return b + } + + func calcSquare() -> Int64 { + var a: Int64 = 1 + var b: Int64 = 2 + let s = Int64(Constants.BENCHMARK_SIZE) + let limit = s*s + + for _ in stride(from: limit, through: 1, by: -1) { + let next = a &+ b + a = b + b = next + } + return b + } +} diff --git a/kotlin-native/performance/KotlinVsSwift/ring/src/ForLoopsBenchmark.swift b/kotlin-native/performance/KotlinVsSwift/ring/src/ForLoopsBenchmark.swift new file mode 100644 index 00000000000..0f5be99f6f3 --- /dev/null +++ b/kotlin-native/performance/KotlinVsSwift/ring/src/ForLoopsBenchmark.swift @@ -0,0 +1,83 @@ +/* + * Copyright 2010-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +import Foundation + + +class ForLoopsBenchmark { + + private let array: [Int] = (1...Constants.BENCHMARK_SIZE).map { $0 } + + private let charArray: [Character] = (1...Constants.BENCHMARK_SIZE).map { Character(UnicodeScalar($0) ?? "0") } + + private lazy var string: String = String(charArray) + + private let floatArray: [Float] = (1...Constants.BENCHMARK_SIZE).map { Float($0) } + + func arrayLoop() -> Int64 { + var sum: Int64 = 0 + for e in array { + sum += Int64(e) + } + return sum + } + + + func charArrayLoop() -> Int64 { + var sum : Int64 = 0 + for e in charArray { + sum += Int64(String(e)) ?? 0 + } + return sum + } + + func stringLoop() -> Int64 { + var sum: Int64 = 0 + for e in string { + sum = sum &+ (Int64(String(e)) ?? 0) + } + return sum + } + + func floatArrayLoop() -> Double { + var sum = 0.0 + for e in floatArray { + sum += Double(e) + } + return sum + } + + func arrayIndicesLoop() -> Int64 { + var sum = 0 + for i in array.indices { + sum += array[i] + } + return Int64(sum) + } + + func charArrayIndicesLoop() -> Int64 { + var sum: Int64 = 0 + for i in charArray.indices { + sum += Int64(String(charArray[i])) ?? 0 + } + return sum + } + + func stringIndicesLoop() -> Int64 { + var sum: Int64 = 0 + for i in string.indices { + sum = sum &+ Int64(string[i].hashValue) + } + return sum + } + + func floatArrayIndicesLoop() -> Double { + var sum = 0.0 + for i in floatArray.indices { + sum += Double(floatArray[i]) + } + return sum + } +} diff --git a/kotlin-native/performance/KotlinVsSwift/ring/src/GraphSolverBenchmark.swift b/kotlin-native/performance/KotlinVsSwift/ring/src/GraphSolverBenchmark.swift new file mode 100644 index 00000000000..d8ca15c0743 --- /dev/null +++ b/kotlin-native/performance/KotlinVsSwift/ring/src/GraphSolverBenchmark.swift @@ -0,0 +1,1122 @@ +/* + * Copyright 2010-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +import Foundation + +private class Graph { + var nodes: [Node] = [] + var size: Int { + get { + return nodes.count + } + } + + func first() -> Node { + nodes.first! + } + + subscript(nodeId: Int) -> Node { + get { + if (!nodes.indices.contains(nodeId)) { + nodes.insert(Node(nodeId), at: nodeId) + } + return nodes[nodeId] + } + } +} + +private class Node: Hashable { + static func == (lhs: Node, rhs: Node) -> Bool { + return lhs.id == rhs.id + } + + let id: Int + var neighbors: [Node:Int] = [:] + init(_ id: Int) { + self.id = id + } + + public func hash(into hasher: inout Hasher) { + return id.hash(into: &hasher) + } + + public var hashValue: Int { + var hasher = Hasher() + self.hash(into: &hasher) + return hasher.finalize() + } +} + +extension String { + func blank() -> Bool { + let trimmed = self.trimmingCharacters(in: CharacterSet.whitespacesAndNewlines) + return trimmed.isEmpty + } +} + + +private func addNeighbors(_ line: String, _ graph: Graph, _ lineNumber: Int) -> Node { + let node = graph[lineNumber] + for (index, value) in line.split(separator: ",").enumerated() { + node.neighbors[graph[index]] = Int(value.trimmingCharacters(in: .whitespacesAndNewlines)) + } + return node +} + +private func parseData(_ content: [String]) -> Graph { + let graph = Graph() + + for (lineNumber, line) in (content.filter { !$0.blank() }).enumerated() { + addNeighbors(line, graph, lineNumber) + } + + return graph +} + +private struct ClosestNode { + let node: Node + let distance: Int +} + +class Greedy { + private let graph: Graph + private var visitedNodes = Set() + fileprivate init(_ graph: Graph) { + self.graph = graph + } + + private func getClosest(_ node: Node) -> ClosestNode? { + let nodes = node.neighbors.filter { $0.value != 0 && !visitedNodes.contains($0.key)} + let closest = nodes.min { a,b in a.value < b.value }! + return ClosestNode(node: closest.key, distance: closest.value) + } + + func solve() { + var previousNode = graph.first() + visitedNodes.insert(graph.first()) + var cost = 0 + + while (visitedNodes.count != graph.size) { + let closest = getClosest(previousNode)! + visitedNodes.insert(closest.node) + cost += closest.distance + previousNode = closest.node + } + + cost += (Array(visitedNodes).last?.neighbors[graph.first()]!)! + } + +} + + +class GraphSolverBenchmark { +let content = [ +"0,604,802,57,278,84,33,758,908,420,610,484,195,474,254,969,172,463,130,335,704,507,358,852,356,444,396,95,446,86,397,893,56,812,967,40,229,33,112,913,548,902,793,563,318,311,579,58,145,304,133,440,159,219,300,855,443,385,157,770,29,97,229,734,829,324,917,380,817,597,461,386,536,942,533,774,71,996,752,6,741,644,701,782,870,947,159,464,412,807,765,174,334,77,930,536,885,533,202,191,825,342,578,76,394,432,786,313,693,587,659,55,491,467,33,955,883,353,452,60,588,87,109,473,66,965,973,950,952,492,624,810,87,62,218,435,559,283,562,798,349,201,383,249,69,263,415,961,56,755,616,27,186,63,247,800,503,767,869,13,252,746,6,436,793,189,926,442,465,225,573,379,875,620,294,452,832,739,354,781,348,264,790,110,369,393,678,873,8,708,268,177,722,49,448,849,381,720,166,208,178,634,557,595,969,968,384,682,558,298,726,899,444,420,481,714,524,633,897,279,760,755,101,37,769,460,252,869,700,182,507,389,263,88,291,885,106,638,375,661,375,941,487,58,890,700,121,852,700,888,814,546,374,771,683,730,478,446,456,447,369,727,258,307,794,669,438,604,549,921,848,918,694,512,390,913,118,776,441,438,488,187,813,668,373,522,411,772,943,183,6,84,984,619,453,729,744,166,880,800,860,869,805,873,296,706,901,155,111,286,958,119,652,2,140,248,809,475,752,368,924,108,276,472,469,704,92,680,374,473,372,607,251,454,718,228,252,116,812,561,49,248,826,682,598,900,239,652,367,293,196,868,18,555,746,142,170,75,788,675,661,697,632,185,283,838,509,843,222,690,783,963,550,621,211,276,133,303,695,211,957,685,686,98,902,725,707,758,194,461,411,177,912,818,92,512,480,795,586,161,962,546,891,223,476,937,669,938,516,247,668,751,195,678,848,764,888,40,291,456,710,685,129,637,876,293,194,102,153,903,414,766,368,31,561,537,962,873,902,529,362,225,936,743,782,307,217,300,921,699,664,638,862,170,916,806,721,100,395,800,244,50,746,500,962,753,547,889,199,743,611,357,952,781,899,548,507,875,434,702,109,32,835,788,108,469,171,993,886,130,871,752,217,896,446,66,223,648,352,497,782,182,463,557,20,849,685,956,834,676,28,533,256,904,606,334,472,206,942,166,38,203,953,201,566,409,64,833,958,784,852,817,835,829,911,254,917,706,681,35,456,795,615,349,597,198,643,18,955,531,431,49,80,699,35,345,830,687,406,605,872,293,697,348,296,472,951,117,464,843,96,359,945,388,226,338,41,429,367,940,474,477,978,867,975,632,388,319,999,409,145,748,136,226,853,21,620,89,319,557,602,206,759,638,977,499,723,381,223,299,298,981,642,100,95,828,794,689,778,983,201,195,905,670,313,555,762,962,212,311,572,852,657,622,461,101,771,644,925,761,286,275,297,246,904,24,327,474,455,395,148,330,919,710,485,709,341,871,669,27,5,643,840,999,940,489,803,164,806,187,989,178,257,835,516,172,594,661,77,28,961,222,953,604,611,111,296,784,967,175,448,130,611,998,669,350,234,272,149,714,942,501,378,192,28,891,694,37,788,495,961,770,736,207,903,664,21,345,480,604,451,271,99,81,131,902,314,436,979,634,63,164,849,736,283,210,5,131,117,978,379,488,392,649,951,927,757,835,567,472,530,589,959,213,74,904,270,677,787,884,287,569,182,11,604,384,440,914,286,110,760,639,284,3,523,275,968,342,759,765,907,624,468,674,891,81,205,226,907,158,473,622,67,981,858,790,268,176,998,811,987,130,307,735,414,822,625,147,210,875,778,175,388,671,762,352,550,496,82,985,340,915,946,803,441,822,142,297,409,773,356,890,170,201,815,931,486,626,223,290,722,178,39,873,601,741,88,690,295,272,189,397,631,546,178,718,124,397,234,251,503,64,990,295,733,948,449,540,728,801,351,2,553,75,595,907,299,469,258,40,524,845,281,892,64,50,994,630,380,785,60,341,278,468,828,213,711,17,190,952,370,464,291,918,454,239,399,914,451,281,720,215,62,962,8,208,617,285,391,544,521,254,215,559,184,805,737,774,661,784,206,345,994,238,979,394,685,131,822,717,397,715,607,502,400,937,653,653,352,619,733,275,753,257,766,839,814,308,402,528,912,260,754,367,8,301,917,351,988,696,570,416,444,784,581,829,870,378,368,224,956,237,86,648,448,10,856,196,146,484,229,344,870,673,738,250,949,264,995,873", +"604,0,40,254,413,440,450,189,382,388,460,802,266,415,70,10,137,344,215,456,530,796,664,686,149,440,863,46,325,418,304,904,295,948,626,722,167,27,396,183,396,822,81,117,114,950,786,101,888,750,550,293,584,254,732,694,278,971,813,730,589,978,214,629,781,358,941,962,144,609,629,25,779,492,412,778,302,220,159,617,673,703,602,256,997,805,922,332,116,639,333,384,526,980,764,929,183,987,806,519,293,758,992,261,587,366,154,544,480,983,148,855,372,746,876,207,833,719,607,546,124,719,555,154,264,486,643,437,828,729,571,950,71,908,63,125,560,335,612,16,296,884,446,530,622,121,742,378,816,616,307,115,492,646,831,308,254,860,338,739,614,918,21,493,370,512,817,584,872,221,184,321,218,878,919,841,327,320,949,838,138,537,868,329,759,923,496,960,488,452,407,844,390,619,477,822,968,17,632,471,639,273,142,763,708,694,395,53,976,778,842,967,875,668,980,367,48,424,692,958,223,374,929,828,450,465,411,75,199,145,705,227,66,620,982,33,317,925,780,598,712,29,191,650,287,301,735,765,117,501,324,264,10,538,808,114,389,563,375,421,267,265,554,862,609,244,662,714,194,853,788,359,355,944,781,907,520,52,669,597,292,269,463,378,64,452,672,474,660,455,32,871,305,571,646,477,890,624,850,69,155,897,498,813,295,719,696,381,341,877,30,213,227,394,332,421,924,385,405,407,486,681,293,515,590,497,657,130,680,535,881,478,474,541,522,135,163,180,442,380,478,682,218,350,355,533,870,515,757,740,73,837,600,762,337,555,950,316,235,236,786,502,476,804,44,717,793,688,246,854,85,476,243,513,895,569,29,561,528,525,333,986,829,680,587,336,182,909,196,614,118,198,700,94,100,29,381,933,46,32,920,646,46,482,479,588,596,263,550,902,261,326,272,780,568,295,597,704,46,768,76,731,369,25,421,622,846,756,686,176,583,435,364,415,614,571,145,888,999,235,727,913,128,904,57,300,25,764,822,924,415,526,689,858,224,381,526,607,119,646,544,202,365,277,556,681,668,350,496,113,14,914,813,974,528,389,490,491,550,983,812,652,170,618,665,439,966,386,512,521,589,218,481,288,995,791,791,674,582,593,29,787,687,878,640,11,883,827,723,884,670,129,831,500,422,196,936,719,10,736,641,227,538,609,954,84,304,961,667,781,137,842,79,937,810,56,179,335,760,197,991,995,876,5,342,379,132,231,783,59,459,932,907,612,40,138,857,958,614,164,338,5,467,894,513,352,630,460,511,179,419,826,155,584,448,16,82,909,104,608,900,971,763,98,464,955,314,12,618,150,252,880,429,309,539,687,681,883,888,13,931,804,158,451,768,954,695,751,230,61,834,940,156,410,734,599,444,399,956,210,290,117,878,725,758,453,652,41,207,144,162,46,689,775,318,311,247,748,318,828,500,276,191,218,503,751,994,171,530,884,538,653,69,728,14,905,147,88,291,192,669,742,260,206,152,419,84,814,656,236,262,476,806,589,155,935,197,623,546,492,794,179,487,555,710,215,94,707,326,469,456,186,82,830,22,865,589,375,312,626,550,221,670,295,353,690,167,99,370,833,642,437,746,565,23,956,830,266,866,792,56,337,424,136,669,2,568,584,294,362,421,304,621,582,439,825,45,208,249,63,468,764,594,90,745,7,24,252,528,973,117,290,548,202,264,831,235,162,683,648,530,873,286,333,221,223,95,665,884,235,8,839,225,756,840,748,901,385,514,720,113,972,196,509,601,160,133,350,444,846,464,507,733,303,597,568,640,328,932,520,288,663,519,741,115,152,722,948,318,60,973,239,488,813,322,616,336,241,957,892,196,691,424,249,932,603,677,122,731,939,960,571,430,280,976,144,894,356,855,794,830,721,988,887,318,723,560,688,644,44,946,988,512,979,431,640,688,805,386,809,863,329,152,131,603,77,781,325,321,501,876,240,152,734,13,707,607,375,159,446,415,422,808,798,299,683,47,260,871,344,638,799,881,997,342,572,487,984,96,757,77,843,367,32,840,777,640,38,541,59,160,765,92,32,56,662,451,449,517,476,672,902,22,352,970,140,513,198,595,85,601,341,719,608,663,861,509,621,813,37,195,915,662,284,749,33,812,480,949,133,947,204,246,782,244,810,48,661,585,135,99,321,450,513,70,896,564,677,490,703,977,243,630,613,262,721,100,807,17,24,534,892,626,618,59,640,908,996,874,212,342,778,657,755,777,470,233,547,913,804", +"802,40,0,321,721,986,467,509,781,544,43,803,544,354,937,252,687,373,142,628,327,167,769,538,459,857,820,971,750,652,904,223,132,909,607,679,461,628,781,698,361,121,216,819,304,475,74,324,59,349,120,555,62,299,840,451,353,402,539,565,562,424,973,187,553,859,381,51,696,343,79,63,286,499,302,842,682,896,576,942,68,454,786,497,517,255,417,518,417,523,896,784,55,673,417,665,893,870,4,795,396,418,483,566,132,985,566,605,837,448,985,334,36,409,227,428,625,275,207,176,190,881,447,530,458,382,466,65,16,85,21,223,921,353,134,593,511,430,516,646,640,294,623,203,717,762,715,496,442,11,113,751,888,803,934,210,870,900,656,780,679,147,201,135,932,785,923,240,390,636,534,846,415,993,977,910,132,949,7,624,684,720,651,556,534,661,852,457,259,348,990,365,284,260,652,788,918,689,104,967,837,653,656,465,154,321,722,553,402,768,262,257,941,118,51,170,229,865,45,982,109,575,320,879,331,990,887,921,368,294,743,78,415,23,434,618,22,574,692,953,154,656,121,543,160,848,724,366,765,598,880,5,389,660,481,221,771,398,304,816,918,372,353,586,487,698,386,823,849,784,78,850,855,107,868,269,162,197,338,314,996,294,133,874,638,314,711,534,132,564,482,430,564,128,996,185,345,714,848,217,648,244,67,94,26,492,982,336,300,246,275,61,888,197,978,191,448,747,975,182,972,469,986,770,12,700,977,216,324,839,723,259,101,875,823,242,809,249,681,417,257,492,881,511,86,105,262,641,977,257,182,126,672,693,864,252,424,351,634,190,90,507,122,398,763,207,252,209,561,354,206,829,537,510,279,277,316,143,32,948,772,901,538,930,299,181,886,162,473,446,210,8,431,161,747,529,206,568,758,752,346,738,131,601,827,22,448,216,892,617,622,39,447,898,759,749,103,341,435,900,113,994,760,96,410,175,731,591,318,731,431,338,476,193,735,106,716,479,344,571,294,498,719,921,571,881,136,929,603,541,608,192,118,36,921,715,831,958,774,933,473,588,207,107,864,34,556,490,890,874,642,256,945,701,214,45,937,929,415,221,6,666,263,1,314,643,299,857,539,210,559,670,477,766,400,17,869,915,361,882,934,471,397,92,714,569,886,133,47,370,801,455,849,326,32,329,750,458,445,665,420,613,596,755,870,406,727,935,530,366,822,203,704,449,665,158,322,293,927,98,165,409,238,94,442,877,445,266,706,312,712,321,65,914,962,71,172,795,973,430,355,969,510,610,957,696,505,533,884,754,968,998,994,214,388,509,980,622,353,233,496,178,988,344,445,890,50,376,620,766,552,98,392,700,723,753,83,245,967,253,563,736,880,519,76,3,624,102,254,8,574,804,798,832,883,137,694,608,28,318,326,928,330,987,173,553,181,402,156,163,331,587,771,204,607,979,404,137,688,572,967,206,595,5,895,787,47,844,458,451,269,716,260,849,592,462,850,840,359,296,830,724,101,730,795,997,795,415,475,851,274,953,899,29,442,830,374,754,622,73,622,190,271,412,275,427,398,206,953,138,198,947,234,745,669,47,270,799,300,67,102,566,502,796,11,186,127,426,656,576,398,723,266,895,899,439,509,1000,517,991,77,617,659,695,334,797,375,721,220,739,464,67,62,396,530,888,346,67,264,744,772,726,838,590,964,760,201,16,9,160,868,124,267,460,928,316,325,173,52,820,394,410,759,46,246,275,400,664,787,817,860,333,452,897,618,760,943,24,834,426,894,126,413,484,412,769,301,349,973,720,343,210,915,640,221,94,937,576,995,751,235,914,855,548,434,415,280,83,405,104,197,213,852,907,357,4,99,969,116,474,421,86,950,62,216,409,559,488,511,618,766,232,239,591,556,351,839,689,387,944,336,262,156,978,879,623,634,258,805,64,603,919,87,809,605,36,197,183,639,333,991,644,570,761,180,673,802,137,78,680,825,283,630,661,843,964,443,945,868,455,470,458,710,493,378,467,194,984,178,44,765,755,523,121,834,711,136,668,888,467,799,429,25,817,322,339,141,662,560,647,840,462,761,410,764,177,39,138,974,919,138,965,727,270,191,780,59,213,694,381,534,970,20,39,952,195,784,683,218,146,915,520,335,561,873,916,478,11,470,583,601,973,266,88,141,299,916,97,951,306,220,434,419,183,307,287,216,258,162,249,210,135,677,290,752,535,984,861,840,436,14,529,762,746,944,873,838,795,296,199,149,675,941,533,422,227,581,470,328,976", +"57,254,321,0,726,976,877,679,555,918,259,522,153,491,650,419,377,449,295,813,575,548,550,571,135,708,85,803,595,15,973,375,674,439,832,866,244,950,993,821,818,906,58,492,863,955,503,775,396,520,652,572,404,747,304,949,222,7,383,658,89,188,122,919,600,45,473,37,105,517,619,545,30,163,866,785,54,219,573,636,635,557,930,80,595,94,675,781,143,384,363,838,109,41,294,160,950,754,224,659,377,26,517,74,503,784,953,482,526,469,13,183,732,180,775,752,408,597,866,425,684,790,475,48,839,592,379,950,990,980,716,332,189,908,819,65,555,158,438,681,78,447,931,721,183,377,333,839,570,636,296,301,947,552,920,443,592,793,781,277,326,971,673,208,83,916,373,413,642,157,212,366,680,482,876,431,961,307,10,286,188,982,970,237,614,274,50,808,973,66,918,456,370,723,118,301,412,789,988,80,886,457,333,603,737,985,546,479,222,881,247,954,128,478,249,511,378,363,108,577,932,170,241,733,500,357,200,713,503,588,513,833,440,189,241,10,210,56,331,982,572,675,525,801,546,827,99,741,130,337,869,743,702,585,401,725,478,889,796,244,310,251,484,862,94,179,486,991,626,301,855,974,793,135,183,768,746,162,3,73,810,559,822,836,74,250,739,982,336,284,604,411,974,808,349,808,688,280,743,824,396,664,467,751,156,576,183,930,471,667,564,731,900,938,249,300,542,745,24,119,41,486,869,298,149,310,350,146,568,159,209,243,164,575,305,881,528,618,755,484,103,720,541,355,467,478,787,937,241,812,835,148,453,881,774,126,782,884,518,356,981,248,862,177,472,490,194,179,788,663,855,673,728,479,937,890,328,961,91,311,494,25,587,780,924,897,532,749,460,8,857,632,316,271,872,797,99,729,76,585,832,837,838,4,777,300,30,78,656,867,583,57,407,584,442,766,895,420,238,492,552,379,572,399,353,828,763,588,735,331,837,551,855,570,15,700,400,897,800,53,800,860,105,1,616,56,840,279,360,881,322,51,34,810,143,908,482,932,521,535,174,560,208,277,693,95,928,461,747,762,718,635,225,458,617,128,272,463,260,74,531,726,822,622,831,442,410,74,411,459,89,577,969,74,672,930,663,387,973,674,275,791,723,360,238,270,588,401,704,258,575,407,823,406,50,451,566,20,547,237,307,430,331,176,121,682,696,25,379,450,458,28,899,169,627,879,97,84,702,720,820,766,328,198,794,41,970,978,175,847,324,706,885,931,724,124,423,731,15,553,949,79,979,134,926,103,578,97,905,866,443,885,11,984,698,613,689,931,623,390,532,752,456,497,438,363,701,198,900,928,344,688,842,506,946,19,933,650,97,166,439,746,837,697,444,208,346,711,674,198,784,184,159,845,876,87,817,726,301,895,295,810,239,528,531,733,988,941,654,334,9,294,441,194,902,117,969,201,451,589,106,322,482,542,746,391,529,74,858,355,46,530,200,344,955,789,221,131,555,217,275,964,137,204,388,96,121,329,156,488,645,398,23,214,709,875,129,491,668,139,276,678,673,94,764,731,778,196,10,87,3,644,914,500,643,579,508,878,52,830,363,921,839,113,129,710,623,992,97,807,906,592,985,349,872,383,83,351,431,323,391,359,930,967,986,306,796,625,65,379,201,693,135,814,498,358,847,895,906,570,936,826,397,333,62,296,431,960,424,916,47,52,69,164,479,380,496,455,615,750,957,397,293,645,50,469,67,923,552,198,698,698,741,676,831,92,846,775,142,839,268,538,803,695,765,125,263,627,877,119,195,596,480,138,858,596,439,930,922,316,917,751,203,557,26,735,95,549,702,424,479,674,86,978,189,763,34,950,927,895,947,759,83,330,348,651,773,914,494,387,644,66,219,333,87,427,163,279,443,445,189,148,665,866,855,267,417,553,94,423,992,97,737,177,97,858,890,591,23,84,945,621,755,459,536,719,128,992,591,861,91,261,411,717,702,901,488,350,620,526,733,350,364,31,590,971,381,803,419,488,319,131,741,671,756,970,751,675,855,933,133,489,195,268,776,634,871,454,976,605,380,868,472,410,549,277,392,907,893,987,408,739,799,175,752,288,861,39,40,346,963,861,481,800,907,122,455,8,770,153,338,773,13,374,709,839,956,600,429,600,92,276,650,489,804,157,259,655,193,882,169,220,309,887,270,963,648,658,221,396,15,324,725,825,479,418,240,353,110,219,78,229,348,141,223,37,50,312,367,307,885,215,565,658,738,191,136,994,706,299", +"278,413,721,726,0,584,44,514,846,58,260,489,486,66,420,805,805,115,978,230,125,277,219,921,253,211,368,206,811,700,708,271,620,26,885,289,859,190,731,963,186,586,52,700,83,981,733,396,915,102,122,905,891,296,198,736,352,527,836,911,443,87,176,376,531,656,959,381,929,609,312,81,1000,453,659,936,930,252,904,894,70,352,793,354,862,234,644,180,361,702,792,312,448,312,410,924,337,720,907,222,319,153,584,855,512,917,630,916,484,362,926,942,653,37,484,416,381,553,441,433,689,677,393,767,8,904,387,965,540,463,362,112,154,430,25,850,374,206,544,833,198,844,658,692,135,85,377,546,260,736,21,40,309,74,164,250,183,886,464,540,586,85,769,967,781,41,271,412,854,961,528,724,947,269,7,530,363,253,495,230,683,634,851,906,983,610,966,563,165,217,116,528,285,413,431,736,366,235,90,514,739,357,806,963,754,213,427,819,981,661,158,123,21,946,140,526,149,85,254,710,100,317,239,471,217,966,557,263,433,940,597,706,38,330,856,790,509,460,143,434,493,332,536,989,647,96,247,695,888,276,684,916,343,55,767,754,289,190,185,906,463,10,235,374,696,742,176,98,799,394,334,620,956,45,119,527,444,102,62,169,396,806,906,889,931,706,303,468,620,208,428,374,89,572,288,456,506,667,725,392,37,641,545,137,495,653,317,90,734,473,599,566,508,383,727,957,237,607,595,683,954,325,619,544,66,607,614,236,324,201,96,373,275,738,567,516,698,89,387,14,354,780,507,305,462,897,623,397,247,241,442,888,513,754,614,277,764,716,100,162,636,592,792,827,181,620,758,118,311,525,676,765,933,298,257,668,939,971,661,4,853,257,935,245,552,766,465,922,650,824,706,553,75,185,901,342,892,859,356,312,803,982,221,565,799,161,557,185,453,164,931,35,304,724,451,305,491,572,297,716,348,606,789,268,887,224,574,308,86,348,942,839,86,52,523,396,839,841,707,919,348,140,44,526,636,479,5,507,903,582,708,988,190,983,55,243,621,141,25,64,537,171,714,685,820,43,323,800,535,249,92,178,146,125,77,374,432,388,758,158,121,868,961,959,641,370,164,925,454,333,458,739,15,856,35,467,465,404,29,956,215,265,533,307,424,501,166,501,87,268,363,134,415,175,483,103,983,327,45,527,311,248,973,862,683,951,91,681,381,923,869,307,21,469,992,196,617,598,60,70,57,62,893,315,76,635,477,538,938,757,911,414,700,648,266,682,578,597,447,734,570,236,559,417,419,971,269,858,28,151,504,236,19,941,499,760,963,163,332,910,877,116,41,128,146,582,11,573,432,919,207,846,584,704,118,44,731,780,416,806,885,332,663,999,915,174,549,545,430,738,797,127,576,100,980,867,204,620,287,178,803,153,696,80,791,526,923,824,658,602,86,332,104,689,959,217,466,184,313,774,735,829,644,115,935,807,283,48,38,796,924,559,160,206,490,866,432,511,231,445,841,657,468,723,124,940,212,387,855,65,382,504,586,70,704,459,831,492,220,308,770,832,239,828,764,273,149,191,607,382,895,187,513,554,997,630,52,938,264,872,260,187,911,918,541,328,517,743,975,485,967,608,24,647,760,861,226,362,600,681,528,416,971,781,46,230,837,541,235,391,594,274,263,372,648,593,792,626,755,535,235,739,8,808,65,759,13,59,364,50,485,393,960,972,970,967,711,876,786,423,412,254,107,395,785,784,220,876,21,6,904,304,305,809,359,276,533,921,150,496,606,147,111,541,85,646,710,749,708,357,354,33,80,28,356,181,864,889,143,916,455,731,655,620,704,544,462,593,295,507,389,530,650,938,349,42,308,910,587,124,492,893,574,341,652,447,701,258,565,510,804,90,290,221,926,273,147,725,871,507,777,462,209,996,989,491,232,39,221,962,152,667,200,311,195,652,81,95,307,739,685,403,955,525,289,474,172,634,987,30,171,900,638,276,703,265,664,944,563,128,263,453,400,748,515,777,114,893,20,299,530,472,598,381,288,224,610,115,941,795,565,101,837,655,613,991,940,305,438,9,902,863,58,951,266,135,131,44,133,411,77,961,778,84,857,877,378,987,612,313,8,855,543,461,724,511,154,900,464,356,42,972,42,463,353,417,733,999,854,307,510,421,702,158,19,960,930,522,360,459,142,19,826,580,833,483,779,982,61,449,490,271,884,416,9,14,178,92,142,576,113,56,15,400,212,935,668,332,465,78,957,826,559,501,195,588,558,952,887,90", +"84,440,986,976,584,0,109,366,390,794,546,750,18,671,300,198,220,770,609,610,544,818,439,158,84,27,534,980,462,713,488,755,518,552,134,652,299,852,156,676,904,251,841,175,504,116,242,248,794,281,805,595,59,924,109,36,87,931,779,556,782,393,576,675,456,939,788,887,922,858,606,22,943,781,129,203,381,316,445,851,976,223,902,231,910,48,531,336,936,64,421,685,890,581,899,792,947,188,981,373,819,114,983,410,313,752,402,350,142,295,285,2,25,319,458,666,716,671,842,659,288,987,558,590,853,878,812,337,210,805,262,360,209,461,756,97,523,220,821,140,285,367,287,922,213,359,961,319,674,229,245,848,181,394,165,388,319,497,690,797,985,796,96,484,873,694,607,736,713,371,559,476,446,7,431,981,181,64,237,962,445,63,561,882,980,211,458,409,222,559,641,570,185,33,389,435,961,606,170,962,72,777,127,261,532,979,344,263,451,602,48,408,122,297,161,685,422,83,288,284,866,289,828,859,732,853,816,481,776,586,175,168,591,206,784,533,541,381,423,522,148,569,995,386,382,119,123,876,440,695,838,940,338,791,594,427,825,688,535,185,420,307,834,229,508,748,502,745,643,656,122,190,543,340,552,360,441,988,911,846,39,154,10,577,874,447,240,332,512,112,357,714,536,203,95,570,861,815,978,287,31,875,428,246,888,903,710,205,946,117,457,713,368,959,930,361,614,446,575,234,875,264,620,608,952,510,256,966,191,610,786,661,45,108,333,399,371,971,354,102,382,937,739,149,732,597,236,703,633,191,512,569,328,903,32,657,890,789,873,258,187,634,205,397,870,895,344,448,910,415,595,81,977,659,648,742,463,7,65,572,807,967,221,16,131,72,635,394,389,609,382,805,632,55,538,92,696,452,703,891,218,502,645,815,611,696,310,328,129,186,275,164,28,379,136,194,322,483,572,630,357,673,216,738,994,171,174,216,51,175,878,821,883,356,825,69,512,984,694,394,477,145,115,292,971,911,75,372,893,645,46,588,209,681,247,154,105,619,319,272,501,367,219,524,797,253,589,699,340,421,192,999,53,339,250,510,284,43,354,49,389,606,522,695,531,805,144,140,433,396,516,367,764,935,892,78,8,306,72,130,215,210,312,635,595,79,226,990,395,307,630,279,938,203,728,848,258,574,425,63,396,478,171,348,37,64,461,50,753,587,751,573,947,221,624,363,693,442,41,858,767,632,994,759,462,559,678,625,692,897,51,425,119,567,895,664,536,207,162,841,227,760,143,956,426,241,20,569,828,373,843,870,284,246,152,87,106,801,876,249,802,529,722,154,263,891,703,650,872,155,196,749,154,16,648,11,383,482,235,373,648,206,249,417,712,517,492,251,137,559,974,70,306,933,457,864,437,910,834,181,348,372,213,48,903,74,969,145,406,485,253,210,338,36,277,533,632,420,213,53,823,430,75,619,463,196,760,490,338,757,161,64,626,395,717,79,839,274,903,630,282,966,337,290,656,166,637,967,735,177,766,349,119,493,957,388,574,422,513,339,453,676,262,313,924,444,115,895,53,405,463,422,575,2,386,120,896,422,569,189,414,596,996,4,697,939,246,41,657,801,12,28,206,396,835,161,359,70,493,509,365,595,142,234,819,305,924,312,678,123,445,105,454,944,221,249,131,967,433,694,240,856,553,22,91,684,191,882,530,691,712,446,837,726,790,197,263,511,936,938,427,718,186,141,274,981,777,558,152,635,279,862,988,779,683,555,710,68,186,640,200,301,599,320,466,344,123,342,449,638,124,667,105,180,965,56,446,9,568,837,211,865,280,10,144,488,270,187,147,263,664,695,592,990,950,790,235,528,992,108,543,239,161,592,124,348,117,779,827,951,762,679,837,892,640,722,154,730,412,269,81,203,201,59,764,616,170,292,254,306,43,547,950,8,63,73,889,91,873,829,512,3,769,862,225,147,221,373,886,830,290,344,379,174,273,988,561,899,397,739,169,137,866,383,219,304,546,576,342,500,682,873,424,61,156,632,802,549,15,535,981,21,921,188,345,152,612,888,224,529,445,486,727,165,94,23,53,415,16,109,392,569,650,117,589,546,981,572,213,572,239,522,559,932,672,394,734,883,703,758,609,942,128,811,998,103,821,190,73,647,715,315,877,162,417,608,215,671,160,235,332,30,472,905,503,385,772,467,9,739,23,814,719,862,674,138,258,562,714,67,423,220,485,699,427,752,873,174,771,921,89,607,196,535,191,89,761,182,869,282", +"33,450,467,877,44,109,0,352,21,21,261,739,777,16,839,512,876,59,263,709,919,213,354,765,858,223,556,268,898,611,385,74,864,503,490,891,805,551,77,475,499,367,648,899,319,175,223,988,808,296,3,216,197,192,807,627,976,46,264,139,974,339,715,810,819,945,897,607,144,862,835,899,562,391,157,933,691,918,516,169,380,484,378,977,227,914,681,70,970,789,910,187,914,381,999,749,341,828,857,735,438,782,840,517,151,305,449,120,631,278,314,880,642,84,408,693,358,960,799,544,434,865,975,997,6,484,873,206,860,36,171,814,737,834,185,148,472,479,969,463,751,379,202,58,855,233,826,245,408,345,736,303,16,576,212,586,909,532,443,1000,180,352,740,341,215,940,618,140,760,427,228,771,698,371,882,533,728,996,572,242,143,962,133,390,664,786,580,895,212,873,589,171,625,558,770,356,535,784,930,214,210,51,932,163,617,662,588,139,152,417,852,326,445,917,924,798,425,323,297,389,483,151,569,529,292,298,569,270,942,671,785,569,805,232,328,315,966,65,852,726,788,349,169,870,783,324,281,584,278,219,120,909,935,557,541,706,587,419,755,576,642,363,387,228,385,632,2,815,899,790,587,494,813,65,477,543,874,356,33,518,998,110,306,25,965,769,226,909,535,597,878,101,87,32,404,194,555,544,597,886,282,890,215,973,211,751,527,769,887,873,704,803,864,296,609,396,229,670,895,222,739,438,40,256,939,377,256,512,335,850,182,404,680,529,297,362,801,53,607,385,80,880,586,930,860,162,509,899,464,917,31,743,275,381,874,906,921,596,405,75,522,322,838,198,354,885,657,580,519,588,224,156,745,834,34,768,258,68,722,727,255,819,521,605,886,353,937,657,340,105,332,240,945,437,260,398,945,948,762,39,474,897,604,11,965,945,709,705,151,240,772,682,688,692,676,177,308,504,586,118,109,445,610,344,751,510,120,104,959,131,925,680,736,812,763,985,268,815,64,714,482,886,439,496,496,11,736,304,833,818,393,83,161,51,62,419,496,372,810,953,368,171,439,698,939,370,711,482,106,925,562,341,529,829,260,941,279,925,327,901,56,528,113,289,780,181,460,640,557,566,9,235,410,959,527,370,646,257,43,710,408,205,74,150,496,805,363,333,577,154,471,906,921,504,752,302,415,329,592,628,305,919,521,285,545,342,934,653,696,267,167,699,775,723,274,910,535,893,644,818,917,306,400,694,43,679,826,866,837,311,263,568,957,63,260,523,834,747,627,863,691,192,189,555,88,41,663,150,13,367,747,765,810,952,697,811,909,895,375,608,664,496,128,100,210,631,702,553,779,629,532,989,160,198,455,258,144,518,979,486,159,89,91,168,178,429,621,286,95,574,949,493,175,153,273,73,276,353,224,468,914,910,885,11,85,168,3,38,823,572,915,41,817,812,61,730,597,543,601,31,163,389,26,543,593,847,648,138,134,430,266,439,858,20,186,967,710,264,802,265,317,325,453,549,104,412,156,54,103,668,113,700,736,399,458,984,689,85,738,357,148,343,992,903,916,982,428,271,947,383,605,606,553,287,511,891,537,243,101,532,262,223,948,859,463,91,700,195,364,942,891,411,202,954,444,548,581,988,562,116,400,21,111,369,898,20,653,498,915,933,398,893,140,264,674,221,426,628,639,467,614,480,89,777,903,861,457,133,711,487,708,677,428,159,468,675,927,897,216,734,162,769,996,168,859,901,93,630,989,343,85,575,415,907,24,35,537,311,783,799,657,11,792,52,935,669,542,311,687,757,47,551,106,87,70,111,628,694,514,117,617,239,425,839,960,52,415,810,85,178,937,760,98,193,574,301,863,431,611,1,193,832,447,18,333,493,773,40,129,638,642,914,908,880,163,240,558,485,621,217,825,76,898,172,816,165,36,51,509,123,198,645,880,628,331,591,964,91,823,41,843,605,449,123,361,833,977,39,382,466,605,22,574,750,443,385,172,167,470,539,881,2,760,855,126,747,839,402,158,193,933,445,478,20,311,54,448,144,272,144,895,336,630,716,119,529,869,350,462,867,382,686,65,561,989,337,754,901,348,599,209,545,229,847,542,484,350,678,98,302,503,792,528,681,137,733,843,101,754,678,573,221,962,393,64,522,277,372,660,484,5,758,35,707,982,780,937,125,775,48,912,516,36,409,138,140,70,5,354,319,351,811,989,151,615,276,357,364,656,256,629,151,36,31,529,864,676,620,901,788,450,981,210,594,198,834,984,953,356,615", +"758,189,509,679,514,366,352,0,16,948,324,345,508,350,958,671,191,112,473,406,520,758,86,333,694,407,370,771,674,426,505,434,727,207,989,692,965,677,716,680,907,936,958,437,991,17,26,520,62,551,559,991,725,857,542,434,948,381,285,492,768,785,292,660,971,74,410,654,894,494,772,171,721,50,30,345,332,991,807,406,79,962,361,385,671,639,703,192,930,605,515,398,40,15,193,759,461,212,870,888,208,809,105,879,722,693,840,129,647,159,759,668,390,542,938,186,921,931,876,323,98,161,612,366,943,400,117,683,948,673,784,636,61,936,794,170,167,509,986,13,375,779,478,393,292,552,119,960,292,334,973,949,25,417,447,821,398,782,166,274,576,392,929,16,621,938,983,853,129,116,868,436,86,47,806,981,197,160,320,323,721,619,998,763,152,4,591,731,795,633,419,666,491,146,905,454,658,97,210,591,875,959,158,278,218,106,749,847,63,667,580,959,648,234,62,275,765,225,714,273,324,532,228,819,588,784,99,727,574,839,948,234,389,326,594,396,467,750,366,713,4,265,870,415,442,696,720,732,153,578,286,636,400,68,607,755,853,301,494,359,193,11,664,49,972,444,933,753,543,631,801,419,164,442,419,916,736,57,504,204,868,692,404,680,681,544,553,215,835,276,581,167,624,183,953,552,245,760,305,58,657,230,43,759,770,252,321,126,333,939,937,281,864,383,720,204,137,198,413,911,21,306,600,683,155,219,280,959,67,655,926,355,280,663,80,404,474,647,558,732,377,821,462,46,327,46,1000,936,412,585,804,956,239,61,384,489,226,356,638,990,527,670,763,73,270,807,180,821,786,832,877,433,468,532,438,276,544,53,47,372,257,43,765,652,81,518,314,145,923,466,908,757,846,365,626,919,875,274,927,242,716,829,145,68,911,884,352,766,704,419,589,351,5,560,146,226,139,8,984,354,384,369,149,993,511,918,356,447,999,173,125,654,494,491,878,548,653,600,912,977,584,199,75,817,60,55,644,75,828,940,472,291,410,912,479,684,837,639,560,723,704,300,499,717,614,535,190,302,770,874,740,459,430,217,242,923,541,619,92,105,976,429,685,303,453,302,219,812,514,256,41,821,398,717,885,940,801,971,791,181,38,460,713,75,367,249,36,64,734,534,8,291,254,471,879,91,435,325,501,301,586,186,747,745,731,715,762,349,608,775,367,320,980,478,217,344,820,636,555,611,932,505,746,334,864,711,840,680,945,8,478,40,823,823,141,401,352,426,905,647,757,950,351,926,400,169,612,600,322,451,321,604,201,733,147,459,106,271,562,518,443,953,990,485,380,723,618,987,457,97,926,439,14,653,477,548,290,458,762,361,102,840,516,904,344,158,27,158,786,24,876,311,54,227,577,339,537,115,226,983,481,672,120,18,750,538,756,455,860,98,431,416,524,629,405,827,836,795,122,296,953,103,928,855,883,117,45,955,882,877,718,174,536,461,461,776,643,762,383,575,503,143,421,152,508,839,769,581,627,340,686,690,248,880,878,492,914,889,901,657,257,545,813,949,616,465,710,828,209,539,227,662,925,69,78,795,821,888,297,479,612,716,409,362,543,452,994,374,961,932,299,864,24,646,476,717,856,871,194,530,145,879,578,52,733,158,218,976,574,134,895,452,801,450,650,953,13,720,726,657,950,637,591,669,814,827,582,892,200,473,946,765,598,555,503,111,45,553,782,755,233,493,939,716,583,922,471,365,919,736,251,655,422,606,133,710,763,302,548,843,55,568,560,640,778,249,485,294,495,598,224,178,939,526,442,371,532,871,618,852,992,84,430,937,566,711,801,425,70,50,711,828,727,395,233,692,640,934,642,14,455,254,998,1,755,565,161,400,423,114,114,875,963,88,645,482,717,975,320,42,761,595,12,256,972,462,173,377,969,277,295,103,708,292,231,356,780,5,718,752,608,417,928,129,191,462,625,216,200,968,875,425,519,939,924,447,356,988,725,461,17,361,52,857,637,424,587,424,820,616,400,126,331,229,968,225,537,182,852,159,225,774,929,482,146,103,346,260,114,131,981,380,927,238,594,5,9,877,943,539,538,76,257,554,170,815,886,334,878,421,543,234,231,687,732,578,132,379,23,637,106,478,763,842,479,185,97,907,373,969,19,346,504,455,941,844,857,9,792,736,13,397,207,848,49,962,893,761,467,112,70,763,222,757,970,825,24,737,670,493,191,806,119,118,591,153,787,944,919,638,579,758,75,191,543,926,692,111,754,299", +"908,382,781,555,846,390,21,16,0,495,554,294,295,629,687,230,555,311,18,358,529,427,183,32,412,279,915,63,722,811,624,517,195,57,654,14,815,500,464,742,842,641,923,117,654,955,690,491,962,786,155,695,926,374,383,406,957,187,738,930,945,404,533,218,244,681,924,640,849,880,78,395,920,72,272,622,583,278,571,10,211,329,173,393,793,509,839,152,287,549,202,741,557,931,904,155,418,527,881,546,216,551,185,918,485,259,73,953,402,701,729,299,354,681,251,359,99,179,420,502,390,842,589,332,80,446,572,19,331,830,440,585,514,601,150,845,943,520,438,947,309,441,43,680,725,146,201,407,364,388,855,747,933,882,213,828,769,181,777,96,443,927,478,364,290,121,831,447,54,76,45,195,375,94,57,589,889,119,143,613,371,209,57,89,326,539,207,631,658,639,993,433,715,489,956,860,812,165,634,688,682,306,567,447,804,698,943,273,255,287,147,195,163,166,594,671,903,873,660,948,695,589,81,54,718,408,135,697,926,581,527,309,884,887,512,715,381,960,181,236,39,358,579,427,377,734,814,621,370,279,218,107,442,525,533,416,212,222,225,349,213,352,213,784,397,824,381,38,642,764,616,286,278,43,471,258,732,57,651,810,559,307,586,80,625,815,379,492,101,148,593,329,630,646,343,509,647,892,134,194,988,370,770,145,941,910,526,70,937,608,253,730,227,983,527,889,952,220,890,762,86,788,359,82,499,954,120,843,213,731,440,107,909,448,105,167,971,462,604,806,910,349,365,911,363,539,768,415,102,508,501,509,624,812,288,262,73,464,930,953,798,736,960,740,835,891,268,438,611,174,520,824,452,884,179,255,894,19,553,936,616,104,673,92,234,454,653,442,939,476,470,249,130,772,156,414,695,314,152,662,621,132,970,341,732,562,314,607,845,84,235,645,375,135,284,242,533,184,334,573,70,659,922,577,634,401,917,341,552,404,197,67,713,260,556,943,617,164,336,723,740,579,975,13,488,468,882,55,957,676,962,686,734,491,108,990,355,658,204,597,733,88,994,188,879,432,637,23,527,699,195,214,941,756,230,726,559,17,113,670,354,685,345,20,78,248,12,455,171,23,770,940,972,368,53,785,928,700,666,684,803,738,861,263,3,893,121,402,932,644,444,352,652,525,215,90,757,863,604,762,915,527,478,960,288,649,899,269,961,876,862,100,417,548,423,462,298,834,146,935,674,536,660,640,843,880,180,466,994,894,12,388,51,106,569,90,572,66,622,101,335,319,528,878,751,825,756,957,821,500,192,755,582,653,834,552,272,661,312,470,488,109,516,770,281,224,746,734,822,298,854,620,471,312,524,830,339,453,510,86,936,575,882,18,572,901,252,131,135,146,616,445,725,318,562,571,801,724,916,513,758,766,894,541,793,542,433,208,479,441,256,947,998,357,184,771,130,663,498,536,855,230,680,931,594,105,617,359,169,649,80,20,285,548,725,454,985,321,248,40,661,717,626,203,709,679,367,492,964,544,852,961,608,115,242,783,664,917,134,698,672,173,629,359,506,410,86,648,22,560,793,857,260,703,849,295,308,739,534,559,298,623,816,200,793,514,228,687,745,575,547,772,980,640,105,778,623,946,247,967,406,206,370,568,80,790,262,773,330,839,508,660,484,209,615,649,202,330,118,847,346,913,649,780,750,454,705,780,998,761,392,96,468,305,384,698,777,635,548,783,382,713,672,75,73,597,599,951,499,649,928,252,127,872,913,713,304,195,235,708,176,495,552,809,188,428,171,804,703,346,613,160,124,98,222,934,211,423,177,423,250,523,750,186,537,209,209,175,10,997,640,328,917,698,909,565,837,908,967,83,800,125,901,958,632,998,959,632,45,673,814,924,838,324,994,837,758,915,236,970,350,420,309,790,497,496,291,830,948,226,136,903,924,464,66,249,132,882,320,215,351,191,265,690,28,363,463,671,973,836,330,595,127,270,968,972,718,188,214,425,585,437,249,164,304,867,500,212,69,839,938,689,883,837,411,608,866,638,464,297,72,375,203,869,838,115,343,492,122,14,815,258,606,127,39,868,750,36,308,603,933,296,878,683,909,928,555,662,809,410,121,478,514,791,436,918,397,907,156,422,988,279,705,775,980,820,673,505,679,351,31,667,103,362,311,27,906,601,928,266,228,148,260,199,11,219,609,973,647,418,155,998,535,751,757,991,418,474,396,202,326,726,45,190,658,609,912,157,875,272,354,480,128,192,279,878,552,249,407,823", +"420,388,544,918,58,794,21,948,495,0,906,650,437,53,933,817,60,131,55,582,893,880,829,213,669,73,736,131,573,120,403,566,346,932,878,9,187,198,621,731,396,65,529,612,196,130,591,875,15,187,802,769,214,671,331,611,474,305,521,745,991,195,227,791,853,739,158,898,390,180,403,79,812,252,187,260,706,2,142,852,582,265,22,190,134,824,608,952,465,637,875,648,756,91,38,732,141,802,664,824,107,364,957,216,205,78,98,510,295,359,166,476,23,533,618,951,242,228,42,758,301,431,961,245,778,830,396,406,618,552,777,542,287,627,859,457,90,342,314,568,326,952,541,216,593,909,164,816,460,891,999,294,884,228,991,978,487,168,649,868,100,979,942,304,625,552,300,340,275,986,223,626,801,650,714,197,186,558,811,755,44,622,15,820,55,960,518,850,870,876,109,984,273,167,528,279,578,338,938,996,663,465,603,70,140,509,83,122,85,655,328,177,197,911,890,562,659,736,183,903,747,944,880,324,820,773,395,676,435,637,505,729,232,145,282,353,322,285,771,498,64,112,157,333,211,631,751,496,404,917,846,328,238,740,853,596,377,188,313,234,928,472,832,69,551,786,359,763,50,85,365,77,821,660,782,662,468,724,52,110,936,392,778,750,872,407,562,867,951,404,277,454,202,514,458,514,958,770,505,709,114,212,20,463,105,113,674,566,6,540,134,164,106,200,639,839,382,227,91,934,918,362,35,509,326,231,284,753,833,627,620,407,116,261,421,775,292,441,923,764,249,734,52,37,886,981,178,845,796,670,917,277,905,449,777,206,819,542,236,609,518,117,1,202,725,710,812,678,179,352,713,136,383,896,582,749,340,979,70,588,389,826,430,288,898,467,637,462,179,299,471,503,301,433,701,553,759,861,224,387,451,624,833,83,911,305,280,247,796,112,742,398,55,211,326,388,669,331,536,181,330,645,935,158,519,881,517,629,451,427,619,771,557,523,353,20,368,699,795,229,873,787,984,501,554,308,765,21,90,896,523,627,549,854,544,896,12,168,159,342,133,800,164,413,634,517,524,198,33,193,514,909,285,608,755,137,931,425,410,805,829,990,72,191,607,492,910,410,432,339,627,935,499,73,507,421,693,258,899,381,276,995,86,969,802,410,411,77,203,991,625,843,538,103,736,200,601,453,834,216,490,821,323,760,607,431,439,767,210,165,664,770,60,884,394,127,512,403,270,641,497,654,658,987,812,875,528,948,782,713,878,184,588,193,129,681,980,786,667,71,666,663,909,411,221,23,829,125,549,323,190,433,957,530,270,933,601,243,429,208,877,786,323,11,234,71,861,757,141,25,239,670,315,445,578,607,104,109,824,523,462,792,39,937,991,103,134,271,408,120,672,327,455,770,134,842,329,994,902,899,116,90,543,821,211,649,562,588,773,349,388,245,748,385,339,940,8,126,996,242,984,718,795,346,773,259,546,564,265,928,365,612,390,795,687,931,179,767,518,997,477,624,616,270,448,468,496,102,330,547,550,336,70,555,305,595,628,115,522,184,166,873,566,122,490,64,682,794,925,557,305,609,812,675,201,556,970,541,530,354,509,949,266,468,392,393,567,383,978,81,927,817,162,598,792,79,736,77,212,598,555,805,173,312,377,278,78,33,570,440,609,216,533,183,313,400,726,851,599,931,269,213,940,984,133,838,320,835,760,288,775,52,170,422,830,998,692,788,113,410,24,303,616,926,951,760,904,408,508,516,547,458,473,702,850,807,79,891,683,448,559,195,184,424,857,108,226,359,900,558,474,496,244,437,596,295,730,969,926,313,755,791,579,967,855,424,872,918,643,808,577,723,31,871,427,86,145,468,338,593,796,498,512,923,500,865,303,486,87,321,859,363,180,204,535,931,77,981,545,875,941,959,367,842,474,385,76,171,494,751,248,596,509,678,420,213,168,606,39,836,27,625,777,4,392,337,711,157,976,138,658,146,177,817,204,801,600,145,904,365,76,895,886,907,254,354,219,744,842,205,307,277,245,495,265,251,849,29,632,823,196,477,122,35,504,698,724,445,628,746,987,528,315,531,374,428,942,806,533,646,167,626,436,213,460,34,753,14,142,362,412,882,727,698,390,713,588,773,621,626,560,90,954,781,841,49,876,372,873,354,78,52,980,212,943,275,307,559,378,854,294,998,990,145,654,829,815,627,578,142,921,255,946,86,61,457,18,142,18,54,808,306,550,691,122,143,837,306,561,793,838,805,229,418,373,295,501,346,12,509", +"610,460,43,259,260,546,261,324,554,906,0,354,773,953,227,795,438,900,794,598,528,234,86,872,523,742,913,352,841,518,392,982,264,47,325,816,178,620,786,202,218,529,921,751,224,543,129,72,529,848,167,509,840,471,851,544,945,328,797,300,43,899,845,307,420,634,460,995,662,779,939,880,64,655,936,602,814,436,545,729,248,617,917,301,305,250,368,491,354,760,119,984,940,302,476,19,145,863,675,876,400,435,56,906,480,543,342,408,906,639,211,571,731,354,484,964,466,734,815,262,678,553,703,270,455,894,302,697,499,126,746,585,828,929,102,782,766,478,295,512,484,542,210,58,727,292,704,596,371,828,238,415,730,183,660,372,459,530,857,541,450,302,879,922,274,836,203,712,257,866,581,518,280,188,924,223,425,619,149,349,797,664,629,295,188,39,786,204,897,506,84,563,739,84,710,906,691,848,873,689,547,480,769,287,418,185,62,9,606,582,451,450,475,717,851,373,989,311,731,911,300,882,402,442,805,102,764,89,91,847,808,110,311,977,927,702,260,517,71,656,487,158,191,280,797,416,64,286,23,26,751,700,179,956,955,732,322,865,592,89,131,242,656,763,26,494,927,990,85,958,282,810,146,859,375,634,189,387,557,56,324,285,579,696,111,693,55,214,439,339,329,789,270,472,485,373,67,4,98,868,871,926,70,757,489,240,180,719,210,32,484,403,29,679,450,658,80,891,54,654,653,725,385,85,119,952,38,817,466,633,222,661,480,560,181,364,52,213,503,431,117,206,295,637,815,756,216,965,396,748,843,896,953,608,7,311,690,903,664,116,340,956,819,17,26,846,453,259,905,635,185,368,174,505,573,423,922,923,425,339,481,426,487,26,374,839,319,795,63,663,21,433,777,702,414,112,381,396,791,10,780,563,851,835,224,150,552,634,864,437,954,164,398,629,624,388,530,579,497,945,746,770,922,945,364,507,932,164,869,183,839,943,467,271,948,753,334,585,97,238,555,486,813,567,603,219,116,700,81,797,552,261,428,759,522,373,608,847,401,199,675,723,134,382,672,915,721,762,488,497,103,69,325,282,550,907,718,851,888,424,482,735,637,656,43,281,529,839,90,670,442,842,65,520,320,513,663,396,949,767,15,366,975,497,685,160,766,906,475,725,906,948,145,128,281,19,434,451,809,35,439,684,251,242,84,503,513,511,728,502,794,618,915,205,675,682,134,82,307,695,390,385,848,126,265,341,492,686,760,525,118,32,35,990,752,752,690,13,746,626,492,320,526,666,551,158,72,20,631,751,43,417,60,954,53,106,133,261,812,379,808,600,452,899,75,474,766,606,792,879,499,599,627,991,450,83,236,868,375,52,19,495,503,458,400,841,679,147,416,610,890,648,28,474,394,51,926,197,56,960,330,228,556,994,211,800,573,260,853,513,520,746,711,548,552,964,395,132,444,154,203,567,907,724,602,150,442,336,278,813,709,766,238,895,704,728,335,867,393,99,942,926,591,929,344,523,601,363,284,636,445,850,798,516,465,159,259,551,656,849,903,467,175,883,697,274,306,415,728,344,806,398,342,750,525,24,147,834,174,439,238,478,142,983,25,864,757,810,295,91,113,812,506,526,282,817,237,607,367,984,399,973,458,931,500,355,119,801,781,571,800,623,681,54,818,365,675,20,981,762,557,244,362,998,915,243,509,381,237,662,818,814,156,923,657,900,533,32,46,190,617,775,959,627,376,440,289,173,646,976,201,856,567,104,40,914,983,394,939,358,665,474,512,946,936,313,897,450,881,979,117,506,954,861,94,395,893,280,764,231,276,637,655,275,789,636,585,570,294,174,692,54,25,298,54,905,895,926,348,189,611,442,995,338,133,900,990,133,261,770,834,318,217,435,235,185,571,798,510,469,926,77,100,214,518,657,476,484,39,39,172,880,209,135,762,351,375,856,300,833,588,591,563,882,661,74,875,788,86,753,760,749,549,657,207,400,129,268,58,512,281,953,539,603,697,982,271,78,908,673,214,78,727,962,605,789,421,430,856,663,139,334,548,278,401,840,641,195,596,242,530,557,196,480,301,528,438,492,381,352,737,160,374,154,921,531,412,878,387,444,129,307,921,414,131,509,360,626,436,947,928,717,749,468,259,366,427,458,908,297,67,492,983,411,6,276,275,818,268,916,845,821,164,599,798,484,124,467,240,778,232,867,289,135,410,958,52,975,168,642,60,578,705,41,560,54,774,940,501,457,773,153,171,405,94,105,113,50,632,738", +"484,802,803,522,489,750,739,345,294,650,354,0,879,269,568,43,905,661,885,938,831,68,641,935,878,424,774,63,352,484,122,756,55,875,305,105,785,232,574,24,310,982,609,630,633,802,420,952,8,600,243,323,748,412,46,140,483,755,879,204,434,514,32,906,660,831,705,293,929,793,341,215,442,575,543,913,296,33,61,1,675,259,733,932,89,250,531,728,444,924,356,253,864,245,829,293,562,126,657,764,376,26,326,613,405,70,267,388,239,405,991,507,952,270,279,784,547,601,9,771,828,645,421,60,617,643,832,489,455,24,754,444,321,709,110,178,788,787,271,923,880,858,213,818,463,238,241,242,389,35,682,165,872,22,102,508,436,251,254,252,363,874,2,925,635,866,371,982,618,354,97,473,293,594,643,262,253,479,868,250,430,681,359,356,818,66,626,323,817,498,670,61,545,837,327,532,772,557,269,374,38,735,954,340,158,99,414,601,618,473,248,789,754,567,381,793,563,852,151,66,537,192,881,421,920,487,354,240,58,859,61,174,385,73,644,570,154,570,199,136,920,70,917,712,603,907,475,901,368,40,288,313,235,770,101,496,492,7,867,627,968,424,60,541,306,792,486,824,923,926,644,497,194,335,471,855,326,189,369,357,598,119,848,553,387,339,136,543,111,352,659,347,542,180,502,606,996,320,414,974,388,625,396,256,863,479,711,522,356,627,729,668,458,74,245,311,369,780,68,689,124,95,512,100,672,142,650,243,104,153,296,149,680,654,304,88,529,72,214,49,866,885,244,411,123,105,565,701,256,382,804,444,503,406,877,729,542,11,212,86,766,903,311,204,340,354,518,180,854,131,904,615,956,834,153,54,142,423,861,961,231,126,765,160,710,299,41,656,592,432,82,387,69,699,697,143,935,143,736,872,11,716,975,987,366,742,145,838,686,651,383,400,185,859,801,740,171,975,7,124,402,916,231,750,195,347,194,552,823,598,251,666,440,747,400,724,922,24,760,925,511,448,858,429,305,249,866,917,643,376,830,70,754,951,305,431,209,352,947,541,28,442,306,207,631,274,337,130,265,246,287,983,457,568,370,266,152,738,824,383,670,201,572,667,809,265,732,313,38,963,361,431,537,418,275,295,836,466,365,567,396,949,529,181,303,627,738,486,281,897,858,566,569,834,860,576,244,613,746,887,759,772,712,463,781,529,397,242,302,445,175,155,588,718,803,615,292,686,184,896,213,558,157,171,583,437,629,184,445,787,697,248,440,908,327,558,310,806,334,809,494,601,503,797,247,352,651,104,462,920,821,839,926,871,482,172,571,164,85,333,983,343,591,287,3,652,167,283,156,374,976,598,920,966,35,52,324,884,702,264,995,898,149,493,454,50,697,117,151,868,292,618,642,566,973,932,51,782,355,771,275,409,723,183,481,579,966,600,165,876,667,42,450,643,538,230,391,306,929,350,778,677,102,220,511,303,585,5,109,189,859,250,387,921,982,251,547,555,617,146,817,541,32,541,397,839,568,900,639,80,617,774,145,633,261,825,625,821,166,802,766,320,330,449,197,832,226,377,350,273,446,272,335,883,706,231,75,580,380,835,735,161,453,545,345,438,308,381,80,395,927,41,683,528,505,867,235,284,172,379,571,461,19,506,892,978,606,285,534,717,737,217,264,74,141,954,99,559,36,988,550,603,81,497,495,342,392,329,404,424,309,3,330,828,434,537,392,273,789,263,151,513,605,336,329,6,28,906,258,75,806,145,735,959,754,481,890,916,648,678,152,116,432,497,580,301,105,922,128,194,728,440,897,278,3,84,166,566,850,713,735,63,627,516,19,975,336,147,654,895,748,3,638,648,498,718,101,546,786,801,156,10,413,132,164,923,252,132,857,122,400,608,818,644,319,198,81,473,56,306,981,500,394,805,824,490,40,236,571,662,880,304,279,701,113,834,394,319,251,534,247,725,882,884,828,378,531,869,884,873,211,401,280,705,815,644,923,221,642,128,162,500,830,294,348,910,203,898,456,327,138,492,723,592,401,786,357,428,883,66,282,832,563,204,155,662,450,248,775,649,51,205,640,87,729,538,295,166,363,996,788,301,947,6,945,40,611,907,214,218,853,895,692,351,771,494,19,454,916,655,317,992,874,73,547,295,776,975,291,52,57,991,281,359,819,288,43,808,69,693,208,488,705,406,56,663,598,72,349,515,869,299,293,167,960,56,78,930,685,562,654,736,739,978,526,481,88,493,422,604,806,624,840,598,59,286,889,744,711,437", +"195,266,544,153,486,18,777,508,295,437,773,879,0,171,471,291,787,106,859,102,784,760,146,473,131,720,555,110,194,684,590,158,346,780,667,911,951,198,340,54,504,549,491,280,220,347,268,486,9,299,597,386,352,938,893,767,400,262,637,281,979,87,554,476,847,195,19,3,745,892,732,862,901,991,990,135,976,17,242,402,856,4,260,205,751,300,780,861,242,36,508,58,527,966,612,88,946,542,398,439,223,254,44,520,883,533,793,287,467,423,118,227,758,547,842,612,906,609,671,520,52,952,506,658,506,736,465,73,739,56,52,258,590,651,441,968,711,451,283,906,890,172,416,632,677,774,433,108,677,398,220,984,888,47,459,716,683,93,360,919,697,416,372,851,248,911,958,927,471,818,648,640,460,869,473,588,539,484,126,75,351,749,262,897,271,671,168,21,927,892,512,908,721,508,346,279,119,263,7,105,905,122,454,331,189,635,672,219,199,360,362,368,711,736,232,33,812,149,232,900,183,916,943,257,953,108,750,326,454,652,382,618,136,870,184,920,194,204,774,47,642,203,113,199,514,789,31,26,708,46,854,492,577,582,701,357,398,928,755,604,890,723,30,404,154,321,978,583,520,677,503,325,244,18,482,447,694,887,529,930,618,981,790,196,925,714,441,208,772,568,673,629,299,960,54,528,520,413,911,314,543,205,128,227,287,795,386,817,471,779,151,867,632,514,667,356,151,152,320,631,943,801,687,314,692,872,406,647,143,726,114,183,905,195,554,923,626,181,558,300,429,354,760,809,272,102,948,52,325,171,426,986,253,884,52,651,725,460,707,654,316,922,996,342,585,843,895,8,291,654,58,99,536,353,44,999,944,470,197,564,525,137,683,450,148,161,608,698,61,758,209,726,580,698,668,37,820,215,276,651,161,914,587,155,479,670,998,468,167,486,40,974,795,968,514,310,426,439,872,339,781,979,282,376,438,168,75,439,314,507,184,117,90,153,956,392,710,193,713,359,76,713,275,946,214,615,806,995,342,454,80,419,980,771,985,972,855,710,948,213,896,515,692,364,527,415,155,801,586,939,529,88,612,731,246,649,829,917,937,302,998,954,290,304,473,492,733,921,274,280,796,541,402,456,110,256,983,678,392,730,542,569,286,795,596,11,713,601,402,589,23,810,440,126,430,20,858,964,379,2,471,786,759,810,104,222,127,521,897,426,222,366,49,177,177,907,649,653,881,894,930,890,128,196,55,870,167,669,509,715,482,891,536,934,483,749,466,521,745,358,538,815,396,147,807,230,875,996,189,557,149,112,359,521,701,214,503,807,865,752,386,397,293,268,339,351,891,977,536,253,610,620,748,379,66,570,141,53,681,855,506,410,781,464,463,979,729,968,492,669,538,190,97,262,598,657,916,147,669,256,318,105,214,174,381,730,542,115,406,813,47,270,677,964,549,884,412,750,109,136,21,896,200,46,535,366,258,858,980,761,407,951,425,622,532,50,64,974,735,311,448,227,920,685,194,467,603,838,672,776,937,989,62,850,262,788,364,290,783,528,473,497,432,853,146,909,192,965,357,529,630,68,436,958,242,54,873,539,740,864,938,301,983,294,118,223,174,333,213,338,419,732,897,416,890,754,151,616,581,561,259,653,951,485,469,195,814,112,512,280,94,470,748,787,839,117,404,231,260,465,128,517,464,783,577,739,675,748,729,364,625,568,575,473,671,924,279,950,482,725,747,700,732,1,511,369,346,444,695,742,365,121,332,343,245,609,918,317,355,222,572,437,188,745,371,737,506,32,54,73,780,712,560,532,510,773,695,695,391,891,325,714,929,520,219,296,231,919,943,860,999,258,119,88,845,319,63,235,23,648,965,903,155,799,844,513,388,187,724,928,953,555,453,604,205,397,864,356,718,444,102,396,154,855,947,907,725,980,23,955,200,875,95,449,806,349,129,921,428,881,201,718,895,656,742,29,921,30,4,724,250,425,192,926,488,301,306,145,527,132,952,584,433,735,348,497,743,258,797,644,52,94,398,708,364,646,258,15,791,33,461,487,94,376,402,68,678,199,26,560,946,370,722,527,133,821,546,213,957,708,726,74,441,833,296,69,896,595,33,880,3,625,933,433,430,876,921,391,252,588,244,160,152,358,759,727,755,850,676,4,250,921,413,590,278,862,529,983,315,457,644,403,974,667,413,189,503,755,875,903,779,213,598,981,11,937,993,523,679,479,753,19,248,616,758,112,687,903,380,224,259,908,843,909,500,311,890,142,346,999", +"474,415,354,491,66,671,16,350,629,53,953,269,171,0,370,567,309,812,670,925,317,695,660,548,423,717,659,520,184,281,506,575,658,880,711,541,122,654,833,38,195,850,264,354,217,256,39,184,807,183,471,522,274,155,496,90,624,931,714,44,118,891,255,22,446,569,488,980,299,928,550,209,256,703,953,165,935,415,478,737,450,369,683,385,492,491,299,906,31,551,157,957,995,608,806,928,415,414,584,674,887,262,776,668,872,272,736,764,135,252,749,734,961,373,784,490,33,703,725,50,816,160,609,225,428,208,796,654,70,363,657,29,630,903,90,529,456,379,560,32,748,629,629,795,890,766,557,208,680,979,556,753,93,468,788,141,686,944,305,220,724,198,262,741,86,238,844,624,344,283,813,60,483,650,935,200,613,321,737,389,657,292,152,794,800,60,22,392,784,791,25,517,115,576,414,831,724,381,143,143,498,710,458,409,623,637,56,732,322,616,476,823,651,177,177,963,532,708,58,356,615,888,120,815,324,718,333,44,996,809,145,441,106,40,451,445,450,204,698,356,912,827,438,785,49,268,600,613,827,643,647,267,626,616,561,860,764,38,459,285,35,225,932,474,511,864,284,321,385,469,244,767,950,123,635,871,405,57,596,930,517,297,949,388,28,235,526,902,135,336,105,708,119,844,440,306,102,914,858,564,738,819,886,318,218,173,317,512,504,111,840,105,424,424,340,847,438,403,74,124,609,54,846,348,389,134,686,913,262,21,141,764,28,221,963,203,50,354,646,924,388,955,933,773,856,796,209,839,188,679,662,768,161,566,554,647,267,532,122,992,263,149,387,670,554,98,736,617,550,693,1000,768,159,673,292,163,117,157,893,890,558,844,217,152,464,967,55,64,537,840,224,791,530,709,18,274,298,227,504,799,684,824,204,114,723,863,320,934,53,455,505,933,643,159,360,731,251,782,210,339,645,921,179,314,363,959,641,231,604,131,973,433,927,515,741,195,680,902,547,98,616,616,622,750,982,754,830,347,307,907,272,5,844,213,812,192,958,659,136,665,156,522,97,160,951,395,629,62,957,688,78,299,668,803,426,934,877,743,344,918,895,12,409,851,271,295,650,790,368,859,246,106,15,694,233,331,590,181,694,329,414,959,801,128,170,390,227,191,157,208,708,670,742,219,755,156,252,403,367,968,97,18,933,516,203,475,112,211,518,484,331,633,920,226,766,981,422,821,494,408,776,625,24,845,930,893,992,331,267,642,104,444,89,46,416,589,278,230,113,281,107,962,560,815,936,460,313,990,157,398,678,602,814,881,427,237,741,270,825,790,74,222,12,29,505,311,333,503,347,230,480,188,347,631,44,521,785,376,694,912,179,624,802,145,808,991,427,645,400,702,111,132,856,149,449,658,151,542,523,243,382,144,975,109,919,467,435,826,730,142,796,991,32,413,552,785,121,952,932,600,147,945,380,128,334,866,16,356,25,366,431,587,677,11,138,258,135,354,388,167,186,929,55,408,256,194,869,16,734,12,131,794,153,315,454,770,441,791,347,6,958,627,293,17,672,771,159,788,111,342,820,704,353,995,512,82,226,686,79,511,76,183,115,514,844,964,230,914,592,671,196,794,297,911,208,496,483,695,399,6,127,936,767,509,459,894,986,87,578,674,972,675,589,526,831,542,226,561,954,499,269,969,163,133,937,939,488,37,929,259,598,775,991,797,321,247,332,302,927,556,960,264,756,769,472,270,248,216,402,197,460,468,144,404,77,729,585,36,546,154,983,58,329,522,833,822,184,255,433,301,573,341,731,379,997,865,153,161,43,573,924,692,17,737,563,943,830,587,55,334,762,122,419,574,719,479,422,194,395,369,591,510,564,542,66,18,62,904,989,475,495,47,885,878,650,296,490,435,620,841,921,297,155,590,925,870,788,161,549,951,204,545,205,199,95,833,448,773,327,973,853,399,179,252,271,181,589,671,295,600,152,838,929,369,942,140,231,550,846,582,279,830,942,927,767,138,775,731,616,459,752,168,978,489,891,601,525,991,862,112,577,958,338,19,132,554,279,710,565,339,286,429,350,486,594,73,25,987,161,99,680,773,809,901,116,93,356,155,936,168,191,450,467,490,32,609,968,247,891,331,897,939,414,548,918,936,159,70,312,721,883,62,997,28,187,817,778,28,694,819,677,115,499,498,969,38,709,409,327,974,977,568,402,983,478,510,68,490,140,441,314,698,339,19,152,925,76,681,694,119,340,936,567,700,346,353,938,415,732,899", +"254,70,937,650,420,300,839,958,687,933,227,568,471,370,0,417,780,847,487,857,293,818,622,123,96,762,744,354,512,654,425,493,763,12,396,149,785,594,312,273,841,941,480,554,262,675,654,65,908,547,131,166,475,995,10,529,720,343,818,8,865,416,795,542,26,225,147,801,708,703,382,440,35,368,104,866,595,94,458,87,637,278,164,524,254,56,414,615,330,50,373,616,659,986,328,671,395,473,566,432,162,751,708,574,481,253,616,700,446,405,557,269,708,132,895,182,994,518,499,509,225,150,547,619,820,705,884,841,302,64,47,376,399,926,732,112,225,176,258,702,647,849,288,149,199,493,908,733,864,180,164,932,363,9,638,989,563,182,88,858,205,171,21,76,518,828,597,754,817,721,957,126,819,14,573,342,789,880,88,572,621,310,501,485,382,890,360,890,774,460,506,905,286,538,744,307,855,148,235,378,944,1,554,368,718,69,96,452,398,354,191,385,742,801,431,971,906,415,345,560,932,630,189,160,393,933,371,856,909,844,423,998,301,201,319,39,14,815,505,893,233,930,42,306,780,455,635,671,116,194,90,292,11,418,360,293,966,373,489,668,285,671,95,87,420,807,702,590,591,36,377,705,380,105,479,291,745,326,698,649,794,94,923,798,491,571,786,498,357,129,412,268,816,118,890,642,197,471,557,835,712,386,144,198,266,452,915,822,348,437,343,172,388,94,319,56,869,596,183,333,734,948,47,133,333,914,393,496,894,901,147,755,232,433,258,77,772,142,970,621,307,621,903,917,606,585,913,78,516,365,918,323,623,901,566,953,59,252,599,719,473,21,919,603,781,454,173,660,431,924,737,425,428,33,60,264,699,919,369,763,863,479,163,73,322,2,176,939,292,526,890,449,596,241,922,314,195,576,857,608,80,300,880,65,203,902,949,389,567,438,268,946,672,968,366,739,986,160,245,339,215,43,347,579,318,85,86,951,627,479,628,302,938,320,643,859,995,705,319,903,79,72,214,260,770,616,285,53,328,586,148,573,76,600,438,195,819,685,852,231,608,585,293,351,888,129,948,469,477,650,898,983,178,465,947,918,768,422,274,489,283,610,876,567,960,254,230,324,176,738,720,472,523,221,609,45,958,411,265,96,573,82,493,323,461,942,589,453,269,158,463,987,353,581,448,850,215,832,968,425,507,900,227,126,9,488,335,839,724,907,442,618,311,106,321,849,156,307,666,315,434,966,203,313,835,948,182,395,213,237,773,29,876,195,86,826,335,679,233,344,808,105,482,603,189,487,510,380,658,387,774,581,252,192,531,838,762,913,128,642,36,61,494,38,176,278,763,610,342,572,664,450,226,67,419,514,377,364,212,820,530,428,632,408,16,826,788,766,788,280,362,754,691,790,115,921,508,841,665,632,771,541,746,729,590,757,63,180,546,734,233,552,886,200,91,87,785,657,786,151,141,107,685,297,353,357,159,158,702,42,715,917,832,59,11,977,227,879,797,9,567,514,412,979,872,579,630,201,903,576,577,245,53,764,828,902,88,631,525,376,504,888,435,612,155,147,401,993,473,157,655,280,769,828,297,931,819,147,123,723,693,781,501,35,240,783,638,103,343,632,901,548,874,784,298,874,39,483,118,625,875,209,762,182,504,185,327,232,742,702,373,982,78,871,815,48,809,303,293,187,894,446,463,364,395,791,222,877,786,614,348,7,772,229,78,409,538,924,89,600,101,773,834,891,714,123,955,852,209,946,392,151,357,927,847,290,718,777,714,154,628,885,360,705,656,72,26,186,107,581,430,722,773,253,527,798,733,798,253,327,947,595,4,886,288,525,488,357,280,137,829,280,511,436,749,218,697,401,525,19,732,265,261,398,160,828,382,929,255,88,356,153,785,402,488,137,781,30,908,898,504,931,648,19,194,587,318,379,463,416,586,130,797,958,824,664,782,243,161,238,325,824,653,595,180,608,937,121,278,785,358,170,436,487,968,898,623,637,833,726,423,743,995,283,517,905,6,730,328,777,290,708,925,189,493,875,287,371,740,904,100,25,77,458,31,211,694,881,220,215,335,229,822,23,914,968,13,814,218,303,976,578,449,136,685,148,789,974,534,697,963,782,218,317,931,159,800,606,593,416,553,604,46,266,676,615,956,822,879,10,351,188,125,869,910,619,946,777,900,261,620,973,202,798,280,742,940,912,48,769,467,284,157,52,856,437,287,253,601,902,950,568,105,707,976,93,172,471,11,477,810,282,609,956,414,349,545,824,765,501", +"969,10,252,419,805,198,512,671,230,817,795,43,291,567,417,0,669,407,187,539,62,456,304,977,900,967,804,163,336,640,427,233,478,804,284,994,373,134,567,694,759,761,88,361,216,196,886,340,312,440,30,811,652,51,758,529,324,113,509,431,992,697,80,283,626,159,963,640,734,917,633,332,458,82,736,793,446,626,233,69,310,933,325,244,45,196,69,374,264,613,748,66,299,484,672,515,531,836,420,883,621,429,297,175,171,239,897,489,48,262,455,486,490,358,491,917,621,68,359,325,958,922,438,864,471,318,771,14,724,71,932,259,356,383,296,389,651,275,178,549,624,102,291,911,218,471,841,909,306,185,587,609,154,477,303,657,544,821,302,270,303,546,429,549,515,122,199,867,262,296,754,34,214,761,210,141,746,334,404,32,807,695,306,393,134,310,137,511,494,786,913,467,697,889,413,105,49,631,639,959,939,628,169,732,275,248,427,593,256,150,117,205,323,794,59,600,32,445,436,272,209,371,361,625,559,62,193,825,813,83,955,814,429,679,570,439,716,83,493,864,879,374,159,429,730,78,782,852,374,237,901,587,499,225,998,418,113,211,156,283,224,672,408,665,343,858,85,890,339,371,674,685,664,738,867,168,819,811,819,817,882,715,941,429,410,653,937,428,188,822,501,96,964,18,315,523,954,520,502,992,290,659,91,113,885,624,310,512,751,453,873,930,748,432,905,132,849,674,454,874,793,50,454,780,958,343,247,313,567,850,609,254,788,711,811,438,183,294,950,273,254,976,671,937,89,567,348,251,360,823,160,509,618,345,147,788,767,506,486,833,365,206,471,271,831,279,297,116,335,507,778,646,887,364,977,784,836,656,129,558,169,931,228,133,632,785,648,519,330,413,286,932,351,476,455,481,608,152,674,53,567,217,375,929,469,709,335,187,460,52,500,895,602,94,252,165,947,205,187,787,463,994,443,71,760,65,523,667,99,818,974,661,774,29,45,711,372,518,700,104,741,120,558,335,835,795,476,438,863,968,418,596,620,669,157,331,781,552,628,693,639,350,713,400,112,318,692,181,95,30,620,46,124,840,961,822,321,576,598,797,292,816,757,995,525,728,907,334,722,565,18,895,851,479,225,102,368,492,405,536,839,180,677,462,2,494,456,835,454,190,697,473,499,987,704,618,420,879,746,517,86,426,169,861,106,57,412,535,479,928,227,802,604,479,222,758,618,20,385,207,402,862,935,250,621,260,655,196,941,112,815,79,973,423,852,983,101,62,49,336,613,505,617,348,339,469,458,602,340,538,551,351,450,417,108,863,226,67,386,654,78,181,231,587,892,95,604,387,518,277,467,788,297,7,126,65,339,430,420,553,219,722,125,239,953,777,569,394,324,784,23,116,738,505,463,857,663,202,665,70,843,314,103,308,67,913,96,326,854,224,542,859,351,914,725,144,44,919,60,467,384,475,122,722,690,676,805,149,491,613,56,281,49,419,962,152,866,508,937,226,226,943,745,85,239,422,607,799,400,724,628,969,509,761,278,940,591,482,571,362,908,292,860,577,532,685,844,409,482,860,143,128,649,239,795,536,76,20,447,182,367,39,144,135,150,544,40,411,766,20,687,867,920,155,763,843,472,498,518,382,471,984,876,446,32,556,752,39,247,742,931,51,616,870,371,140,900,490,456,753,896,874,504,445,969,529,623,351,773,635,906,910,521,365,356,389,748,268,585,119,907,598,879,821,316,835,275,625,484,251,450,982,547,253,425,538,733,775,857,98,12,11,688,482,43,583,935,601,797,113,41,416,209,25,804,569,553,726,341,378,690,231,168,568,683,906,121,716,168,708,933,669,338,236,216,679,913,311,307,651,499,901,787,251,197,337,179,465,196,127,906,654,850,426,710,33,556,174,795,326,536,748,925,835,61,343,9,526,377,305,356,404,774,260,39,121,707,487,572,524,689,289,220,44,789,186,946,114,382,657,442,611,45,519,755,587,2,265,28,969,453,430,379,442,516,330,652,752,60,402,719,75,173,270,218,221,931,769,886,647,196,838,211,867,370,318,460,593,874,253,924,360,119,417,946,660,446,484,41,893,401,187,757,294,968,252,581,759,997,495,21,887,366,252,86,256,672,967,195,93,523,400,7,763,869,740,15,227,741,790,5,759,122,168,139,602,131,241,390,286,112,676,560,539,693,885,809,652,326,924,995,699,540,176,520,4,774,92,945,139,221,825,104,518,534,59,404,795,700,100,803,313,202,319,137,796,278,7,696,303", +"172,137,687,377,805,220,876,191,555,60,438,905,787,309,780,669,0,676,334,535,110,499,368,115,167,93,409,442,485,233,729,548,200,876,622,439,257,847,921,91,385,914,469,58,706,858,307,636,277,311,413,744,988,697,463,635,601,20,450,955,448,809,805,954,160,645,63,139,986,676,831,656,920,827,776,465,599,199,149,553,204,956,86,616,803,55,462,526,701,599,883,75,572,571,325,666,847,750,26,949,367,617,394,710,982,566,351,51,430,142,705,697,255,436,82,706,910,302,52,414,824,800,383,176,913,630,806,788,267,26,608,719,532,365,687,980,278,191,139,92,852,34,768,784,627,691,447,74,46,598,475,183,584,339,356,226,73,709,953,913,369,331,737,283,21,749,500,570,703,271,59,350,252,457,638,43,989,427,63,355,4,959,680,858,500,813,281,67,235,220,452,676,32,838,494,375,622,135,585,695,691,642,220,671,755,236,832,486,206,10,776,648,169,636,65,532,116,110,549,370,315,775,99,423,812,864,837,582,44,641,812,895,853,725,276,463,212,295,64,892,770,693,848,362,535,674,31,193,605,18,604,928,56,626,433,382,179,458,978,771,671,749,109,205,93,232,159,598,110,594,946,969,862,566,224,416,385,108,118,752,353,225,557,522,644,985,171,649,495,555,148,566,163,552,643,513,918,666,503,778,486,59,46,714,636,214,122,674,647,684,625,398,34,74,248,555,429,577,64,650,671,435,583,252,809,321,931,473,881,905,668,984,673,348,917,419,322,258,872,781,695,520,351,158,24,649,587,172,110,252,938,812,137,790,77,499,26,72,631,587,67,26,498,988,772,250,858,282,594,854,769,6,896,140,296,221,669,276,262,509,66,358,670,409,287,352,482,85,328,705,581,906,680,526,835,782,611,777,594,410,245,675,884,783,723,540,989,954,20,481,303,625,132,704,669,805,695,592,950,914,649,394,559,456,689,189,414,558,490,601,424,500,890,574,787,667,220,960,613,681,992,219,594,736,275,889,782,111,513,612,587,75,509,178,542,836,193,569,923,664,93,977,978,439,471,389,221,301,623,159,423,780,892,408,656,234,454,79,553,182,827,290,790,736,740,896,329,929,462,104,230,358,485,190,164,810,583,943,399,454,365,105,605,96,81,746,828,962,63,61,342,837,586,807,190,765,575,97,725,257,6,150,771,923,602,350,810,873,81,755,33,447,575,33,422,915,215,331,340,503,207,705,568,307,922,537,349,556,739,366,199,642,366,166,547,941,176,338,558,718,53,407,250,925,411,920,674,411,169,633,900,320,953,777,204,382,478,870,742,907,84,154,436,516,229,525,262,171,539,457,947,73,992,980,442,186,871,218,939,80,64,193,554,572,690,417,762,572,996,427,109,755,18,454,227,897,626,720,392,231,512,340,132,703,350,254,832,994,708,841,734,387,456,467,631,783,960,911,835,213,302,382,496,983,238,182,303,380,734,349,254,965,224,237,712,333,39,86,205,616,689,686,759,401,837,417,468,183,138,844,56,336,354,963,915,880,802,672,879,84,342,438,351,217,942,273,315,128,611,416,45,763,220,745,871,13,933,436,464,457,870,176,265,545,909,457,762,448,146,785,768,533,954,551,11,660,257,421,208,607,406,527,815,100,632,964,52,828,162,171,234,213,130,853,720,811,519,496,62,151,841,880,375,881,578,545,244,911,723,714,940,659,217,923,877,951,248,481,978,408,276,404,892,873,520,500,220,182,63,931,212,507,818,745,614,298,792,616,755,650,655,430,514,388,797,834,703,127,949,248,438,631,966,630,133,305,998,437,614,602,270,470,190,831,538,302,53,385,191,718,833,537,936,56,501,143,540,971,45,925,625,131,79,608,806,862,869,8,30,319,605,631,613,605,893,652,658,292,888,941,386,506,782,206,208,965,497,663,816,411,939,687,228,396,628,845,855,416,881,196,801,835,895,798,393,843,794,940,210,952,116,453,566,510,80,216,722,378,383,567,642,41,464,252,154,221,177,375,905,72,284,758,765,727,591,635,229,59,747,729,716,825,237,555,873,723,962,365,273,890,535,261,9,613,516,597,626,974,950,343,953,880,231,600,36,528,284,785,581,481,783,68,600,876,349,736,742,338,119,235,654,715,94,447,732,413,501,421,75,103,473,23,954,94,759,880,522,562,578,874,610,232,255,977,249,416,690,522,800,955,789,974,104,552,499,352,189,676,625,742,465,941,522,417,298,714,112,508,417,523,684,301,33,895,529,570,443,314,937,758", +"463,344,373,449,115,770,59,112,311,131,900,661,106,812,847,407,676,0,40,23,996,231,587,141,284,596,718,189,487,11,264,597,427,921,151,214,109,947,617,842,393,142,840,240,51,446,53,749,512,341,949,115,55,309,951,611,910,245,274,827,124,507,726,978,615,539,989,338,870,1,883,789,220,534,777,976,672,700,106,711,306,160,359,687,576,905,598,694,529,391,686,503,55,934,24,774,331,257,348,383,315,442,239,828,341,228,829,684,218,38,943,866,564,80,686,965,898,820,698,4,113,969,362,489,124,794,684,376,808,848,527,102,939,359,344,226,613,390,189,327,413,267,669,63,543,301,230,373,437,17,381,273,792,586,494,596,997,68,843,946,55,174,651,469,430,871,815,958,754,652,816,936,572,906,641,438,940,267,449,284,739,370,539,909,249,310,235,493,166,574,972,223,418,517,407,721,677,76,534,959,726,319,11,963,27,20,694,15,137,457,66,239,552,777,226,687,799,490,316,72,102,762,762,16,11,639,957,36,326,603,107,428,845,444,836,578,744,769,237,688,796,70,910,357,685,665,519,584,16,574,502,38,975,705,388,729,701,76,538,956,56,207,950,623,31,584,751,272,818,480,390,257,661,934,137,990,647,710,786,629,702,650,685,460,982,231,600,617,994,915,672,468,206,222,748,787,30,146,664,249,610,727,197,610,501,682,327,862,285,694,497,177,359,192,336,568,63,293,73,776,317,127,6,260,476,86,503,831,271,203,679,271,356,340,756,652,323,849,49,539,976,420,244,243,847,36,477,578,211,681,279,34,303,268,165,867,503,318,75,296,866,245,490,768,948,718,541,112,619,276,988,324,596,822,397,586,381,438,67,776,289,111,329,895,621,944,125,324,370,208,149,966,437,910,113,345,63,259,757,86,357,325,149,884,459,802,915,917,191,113,208,488,579,420,545,219,237,325,390,4,28,597,484,268,562,740,571,176,631,377,683,280,988,889,589,718,338,350,753,457,942,343,322,257,564,20,282,239,124,132,854,215,617,730,98,61,831,264,702,416,678,830,635,441,927,38,809,540,66,72,236,558,893,515,978,280,746,663,999,39,629,427,306,848,669,223,323,842,920,200,735,751,438,435,788,290,714,782,725,167,718,890,116,664,303,521,848,809,334,87,579,245,2,243,306,466,455,116,189,281,989,455,791,37,968,551,392,28,34,857,853,663,936,943,410,480,407,296,118,985,68,42,497,97,430,780,207,142,574,680,518,382,873,826,157,915,51,582,79,432,84,182,444,530,614,208,823,908,547,116,922,556,811,866,321,130,867,937,667,311,218,88,18,880,154,335,718,720,988,429,26,677,525,852,421,493,425,713,923,568,946,776,602,832,73,659,425,254,712,563,111,482,264,429,200,835,815,874,389,619,125,732,902,704,344,935,736,895,59,258,216,48,619,588,653,159,621,909,474,376,66,369,967,253,717,587,582,774,382,154,261,897,383,639,777,451,497,329,780,515,313,218,127,269,238,508,661,13,101,146,208,962,513,566,770,64,314,836,24,242,552,778,487,22,288,773,870,339,916,56,861,207,234,994,367,473,960,562,393,705,816,133,774,347,762,381,350,170,126,647,114,986,774,826,42,856,505,368,73,33,899,101,790,551,769,38,771,890,432,513,368,587,190,15,531,971,729,121,769,307,964,473,790,746,751,484,128,566,761,637,251,734,798,929,729,348,231,842,926,261,440,145,354,500,551,933,376,235,593,560,60,281,808,676,741,169,701,869,274,120,37,958,970,195,1000,130,68,503,72,185,288,448,103,558,448,374,987,402,637,698,566,702,848,664,121,314,756,116,121,779,768,898,821,443,653,884,768,58,40,629,804,741,427,555,755,953,242,484,237,29,119,598,340,402,346,914,663,616,794,320,70,316,941,875,304,954,870,573,555,551,429,47,724,777,477,93,188,26,244,138,246,379,251,173,197,80,186,560,123,732,948,710,589,446,476,28,524,270,951,462,331,872,22,503,668,536,751,588,545,184,782,995,223,606,630,574,208,577,807,902,742,823,25,826,920,445,927,381,970,907,411,568,412,489,191,27,888,55,485,492,275,799,159,678,227,626,255,159,979,364,280,378,682,346,26,394,682,699,399,932,961,199,51,136,251,645,466,690,188,849,285,452,81,303,303,457,379,397,887,129,751,383,288,651,600,814,680,916,515,334,632,220,959,304,989,658,236,740,371,303,668,47,770,83,697,787,46,735,558,492,267,368,548,544,755,250,44,258,478,899", +"130,215,142,295,978,609,263,473,18,55,794,885,859,670,487,187,334,40,0,961,451,126,268,474,960,830,869,969,534,5,142,574,324,240,649,478,379,779,978,288,265,48,517,758,431,775,101,841,59,565,609,600,483,562,234,912,588,224,640,155,46,208,705,846,944,668,919,230,828,211,293,675,498,622,456,910,498,713,451,566,903,793,250,285,666,433,188,760,297,268,318,403,663,268,45,149,105,440,737,112,30,34,631,609,949,101,804,103,980,490,400,985,795,955,738,549,602,81,464,431,306,133,576,436,121,85,1000,477,79,861,968,54,330,872,148,631,773,247,854,632,999,466,589,948,295,626,680,535,14,267,211,999,598,403,838,616,282,315,903,701,734,430,311,6,40,969,578,562,77,279,84,595,910,152,289,681,342,269,390,14,386,356,822,356,314,690,752,244,920,199,6,186,808,652,82,808,587,370,105,14,935,1,695,414,904,912,820,662,780,29,348,175,724,245,246,913,731,902,406,635,370,657,138,795,520,629,133,864,237,731,806,973,478,166,932,15,569,160,803,867,207,650,268,340,942,455,325,869,3,35,23,211,983,45,108,421,254,540,947,513,27,487,75,635,335,198,317,426,692,305,556,259,827,64,367,789,280,473,895,85,264,616,786,207,162,227,445,971,409,769,834,971,438,492,387,574,573,939,850,923,956,814,562,254,902,773,280,489,392,547,349,574,739,42,738,126,940,601,425,112,244,862,733,905,315,942,371,961,881,976,908,415,33,265,542,60,148,427,825,27,441,441,25,579,272,366,28,650,613,770,956,745,353,303,182,874,824,565,184,139,148,84,45,327,479,81,550,542,340,210,878,857,72,454,491,649,580,293,805,24,69,447,152,629,771,586,353,309,421,846,380,39,82,287,249,337,433,36,589,71,940,54,626,712,646,59,401,499,879,893,101,434,46,695,471,700,892,140,501,586,783,982,973,579,852,98,81,971,50,457,708,450,337,621,301,823,717,387,276,904,260,990,447,206,878,601,181,67,392,420,237,683,27,591,242,469,630,347,749,650,793,925,298,923,476,953,666,549,104,629,185,153,355,701,403,234,829,203,235,319,385,527,599,301,980,911,81,319,741,516,940,520,758,257,316,813,569,722,314,843,650,896,722,22,237,768,34,401,475,511,519,644,443,803,359,783,698,824,266,659,752,313,159,505,545,333,286,359,467,568,13,201,581,520,811,100,152,797,321,884,830,556,257,302,546,736,619,894,229,388,105,594,4,840,736,105,10,207,158,283,238,872,8,111,454,476,201,110,299,913,395,645,329,580,774,987,96,200,459,665,526,639,101,935,891,925,714,617,665,820,388,90,185,179,111,440,137,894,405,87,5,888,630,135,813,389,990,98,318,358,351,446,834,515,820,395,281,100,25,147,349,606,865,835,885,158,895,453,707,658,120,427,102,476,244,145,808,55,477,829,640,747,489,720,504,350,154,681,564,143,881,130,67,239,111,149,537,554,191,952,248,383,926,617,69,939,235,663,853,543,491,791,738,757,903,58,86,591,709,281,454,332,660,947,296,17,926,182,898,144,445,314,939,95,907,368,563,816,949,501,467,83,328,592,952,109,269,5,767,37,839,482,353,830,722,891,847,961,801,496,634,531,252,553,591,746,734,87,355,260,989,829,725,669,420,896,948,93,572,527,742,953,672,625,463,353,432,629,494,555,354,631,217,888,303,738,935,85,377,766,114,966,575,987,152,629,58,31,951,76,470,44,439,587,789,210,827,471,946,997,228,312,12,699,631,578,583,210,49,624,408,297,274,302,884,941,338,749,93,809,60,509,593,824,938,389,774,744,208,113,196,357,404,530,120,110,640,514,720,173,466,325,81,330,868,345,441,468,862,205,448,107,317,485,816,31,744,648,475,769,569,953,947,916,659,462,61,219,764,890,769,997,927,946,233,866,178,192,325,521,32,573,352,171,259,890,761,747,134,810,808,998,663,254,253,14,475,609,148,709,566,364,932,209,768,668,183,869,755,598,770,218,434,172,752,329,898,123,795,531,255,235,634,454,374,737,322,285,75,415,158,616,90,767,97,263,552,870,984,520,76,963,785,740,137,249,484,89,91,170,299,174,696,298,336,22,197,690,624,347,462,583,667,713,268,108,425,820,626,391,927,55,854,483,105,631,270,60,861,625,247,222,239,272,712,857,769,101,273,753,838,638,683,139,815,806,81,362,109,377,319,296,830,846,53,514,779,353,386,707,798,648,992,935,59,847,425,998,201,69", +"335,456,628,813,230,610,709,406,358,582,598,938,102,925,857,539,535,23,961,0,564,541,18,691,671,992,980,200,957,281,761,131,916,499,866,525,447,991,102,120,116,344,457,957,671,801,139,906,787,718,463,818,851,42,296,9,4,335,558,419,182,611,5,695,103,414,217,81,545,573,987,608,545,100,559,274,257,452,785,833,387,649,451,627,727,694,916,473,544,67,930,143,551,906,222,144,697,334,527,215,677,180,299,982,127,552,921,74,629,258,512,679,852,100,210,700,642,531,578,329,172,337,815,560,18,175,173,602,66,193,368,223,775,357,305,854,682,582,549,693,373,326,337,706,361,85,130,39,581,475,889,658,193,73,80,97,446,415,668,284,208,499,376,498,299,111,476,811,985,132,844,395,73,166,162,661,414,234,473,509,500,98,256,952,626,722,544,862,238,666,842,448,591,822,228,692,835,867,440,485,352,407,319,955,808,426,552,722,389,252,153,299,914,703,564,48,939,849,414,573,193,871,940,468,404,567,675,711,464,42,905,689,580,213,387,684,704,814,223,366,284,118,126,721,741,663,19,32,475,4,193,288,265,37,444,108,696,496,664,960,531,80,420,642,507,711,837,52,15,664,798,220,379,419,846,269,463,25,785,620,293,112,807,637,913,600,820,998,126,760,172,100,318,874,152,667,380,796,628,94,2,968,870,940,270,36,594,595,685,321,732,387,601,750,10,410,432,792,493,43,51,654,700,57,255,775,735,355,200,527,490,123,766,537,109,504,947,537,775,572,527,193,962,295,794,1,396,118,371,114,856,463,70,707,533,213,964,350,480,877,284,421,485,657,180,953,889,249,772,28,361,139,31,494,86,739,838,182,684,460,166,550,841,386,440,750,517,242,716,532,605,532,825,732,399,897,261,660,805,283,238,32,710,603,914,629,698,252,635,852,137,352,812,100,153,431,882,246,920,407,127,4,752,995,210,52,831,492,514,213,777,265,848,874,445,503,944,837,139,350,39,764,721,410,100,184,760,948,417,32,105,936,276,696,482,292,325,93,623,278,289,401,34,932,152,822,406,720,785,98,476,542,830,807,146,430,907,207,495,629,331,877,737,577,184,214,119,277,717,845,197,513,892,527,20,410,938,793,992,262,931,344,805,778,701,373,377,837,362,468,704,59,136,190,843,623,580,747,412,426,127,725,339,922,900,127,435,957,681,354,604,166,286,724,206,173,169,759,735,694,199,604,829,468,174,289,854,691,903,562,116,241,284,430,271,119,206,64,116,937,663,149,612,297,273,733,132,468,710,80,408,313,768,384,383,360,536,586,393,51,65,280,341,691,733,290,78,775,556,797,144,632,973,558,287,703,276,686,588,71,402,836,374,416,332,741,797,650,736,152,986,757,50,857,325,227,254,59,820,502,594,278,793,702,357,689,959,138,231,585,754,622,141,126,459,112,620,474,9,770,149,237,289,836,116,171,757,111,272,479,695,7,550,860,253,96,744,875,816,12,249,545,823,994,570,767,916,754,291,31,805,537,766,543,61,622,366,820,265,821,566,988,460,84,859,345,117,890,236,166,939,943,515,688,860,341,742,318,71,675,11,843,184,611,707,256,148,906,882,459,186,408,342,254,405,72,423,732,286,234,505,920,668,324,959,410,851,471,629,352,873,895,277,112,52,805,200,937,568,523,945,941,932,612,88,599,273,398,280,265,785,678,158,509,186,762,565,457,961,107,822,19,773,62,756,270,601,71,117,220,756,333,791,715,433,860,994,143,741,320,625,567,574,55,133,861,485,631,292,685,612,725,476,860,810,238,279,799,870,420,652,678,119,323,360,400,792,899,372,925,721,496,820,173,352,605,513,804,463,83,459,282,596,35,961,343,395,356,439,286,341,563,338,65,381,971,797,886,834,388,224,923,763,152,854,424,248,888,804,174,148,103,548,155,88,371,424,563,334,992,908,948,421,350,474,862,405,924,29,312,78,830,91,74,292,105,690,887,907,212,802,519,99,392,633,124,632,702,190,206,920,421,718,24,365,665,489,734,858,653,921,868,796,469,602,735,178,595,41,76,895,311,531,617,537,737,877,823,379,804,994,642,374,593,445,470,920,356,843,110,647,753,381,31,566,578,995,352,396,772,241,879,362,464,590,828,182,291,143,8,866,611,620,643,793,455,631,569,284,638,124,296,381,607,440,765,937,969,606,655,653,934,547,934,976,425,715,104,803,933,838,562,506,802,515,512,798,349,396,9,485,43,934,861,212,148,11,943,838,148", +"704,530,327,575,125,544,919,520,529,893,528,831,784,317,293,62,110,996,451,564,0,818,652,964,387,318,521,261,165,483,239,417,828,995,62,168,179,42,224,832,281,356,885,459,93,317,449,469,118,909,631,847,359,805,622,712,925,802,585,207,301,445,390,678,550,584,783,111,805,122,112,989,711,106,168,343,853,231,7,109,501,733,883,707,20,726,39,590,303,516,457,206,368,152,612,452,229,709,470,799,404,973,124,446,955,614,524,435,668,159,125,840,410,238,114,416,680,41,630,967,818,424,474,34,894,637,605,184,616,844,769,503,763,630,380,23,671,17,708,154,427,964,446,436,56,554,746,643,333,448,739,558,711,219,235,163,554,574,166,95,895,323,257,323,140,264,48,38,335,333,148,608,777,620,336,460,952,111,13,262,131,952,753,416,386,865,459,176,926,793,482,762,885,147,945,86,376,730,732,290,88,866,181,887,163,771,574,903,146,461,369,23,535,362,18,398,648,854,501,436,102,12,683,878,655,324,242,660,72,119,418,212,132,783,266,505,225,670,928,923,217,784,914,516,712,322,859,241,515,312,731,939,51,219,103,57,882,461,591,370,74,225,832,337,542,304,829,832,357,568,406,494,343,206,323,882,945,564,220,93,6,946,890,448,102,545,569,463,137,29,859,960,467,744,84,259,197,385,671,899,754,251,59,63,676,153,761,224,530,997,694,957,661,446,218,143,15,421,541,640,306,439,39,63,299,865,147,696,917,56,705,64,451,425,115,384,932,751,211,251,364,15,874,138,439,552,488,346,451,666,10,126,341,793,422,994,782,34,248,726,895,403,963,857,630,75,250,118,325,948,503,863,525,619,717,642,632,480,9,685,609,194,973,865,313,270,570,671,352,651,148,885,996,794,771,992,471,458,1000,273,784,982,153,933,356,460,483,509,61,969,992,315,455,260,997,245,368,792,772,50,53,381,288,243,347,157,767,88,316,639,341,445,608,363,933,267,474,42,84,271,142,766,715,160,759,557,90,236,31,662,587,896,571,647,653,620,746,728,673,865,853,320,435,144,404,987,606,591,322,985,74,387,939,660,84,252,665,329,479,684,394,966,887,605,298,197,995,408,118,931,894,293,65,706,99,577,355,79,293,420,334,883,200,478,663,469,426,838,928,57,460,408,403,748,715,545,504,928,192,597,886,251,211,101,277,492,552,689,951,537,567,632,690,213,675,76,9,169,886,274,147,656,891,616,664,267,653,628,209,656,910,701,618,126,561,466,650,141,910,235,548,512,707,329,597,724,591,157,445,470,648,505,820,454,796,277,332,172,134,905,896,906,747,130,141,852,329,685,567,600,524,726,678,743,404,830,856,201,401,356,546,127,483,55,898,529,166,98,493,305,438,741,697,642,631,728,294,861,684,190,688,735,517,850,457,879,614,570,631,197,974,618,656,536,870,96,200,422,355,759,936,358,741,460,348,520,947,474,371,60,291,60,809,822,12,450,485,872,100,147,414,315,823,591,571,391,846,264,556,952,693,847,663,171,576,825,111,908,587,49,696,710,250,303,396,40,10,933,92,405,865,31,860,673,552,471,726,619,730,263,242,862,640,25,181,737,397,970,523,155,562,814,736,18,597,210,443,473,873,960,62,246,3,986,749,66,552,351,802,515,580,556,593,767,678,268,834,860,70,466,267,523,233,760,456,652,567,264,477,608,772,522,506,359,954,63,216,103,460,335,784,440,390,525,609,734,337,213,37,393,691,438,954,309,294,957,279,714,886,892,9,911,423,489,773,399,648,940,959,129,401,660,755,101,675,875,35,865,50,127,356,400,376,627,383,142,262,782,112,316,36,148,319,266,461,32,2,235,128,896,102,493,609,611,396,437,23,978,884,587,494,71,176,748,618,787,555,440,720,765,594,47,65,469,69,363,19,65,986,56,562,276,153,132,201,932,660,843,232,134,654,308,458,899,808,931,734,609,841,927,87,804,522,281,60,719,263,54,54,789,667,869,986,572,347,642,393,987,368,400,243,788,177,204,492,574,693,846,196,534,839,524,781,282,632,431,100,825,988,928,171,173,841,69,963,552,649,203,792,416,581,285,476,714,724,721,543,342,15,430,254,232,886,449,269,765,591,554,246,541,351,252,167,781,737,587,62,487,328,908,772,813,174,709,796,248,49,216,161,101,127,508,102,694,98,530,562,1000,88,413,780,120,309,119,727,447,523,861,140,229,568,412,449,525,904,313,219,650,157,426,416,60,676,299,313,317,400,54,888,774", +"507,796,167,548,277,818,213,758,427,880,234,68,760,695,818,456,499,231,126,541,818,0,253,24,452,95,64,826,727,77,988,67,57,877,89,355,338,517,755,736,371,820,301,912,686,86,206,212,1,443,810,940,799,698,861,924,335,630,434,265,90,699,838,363,740,377,333,222,86,171,794,984,907,268,979,16,26,111,298,878,277,858,826,659,272,260,606,627,532,654,119,843,918,462,552,310,954,895,890,622,179,331,414,32,683,795,420,210,161,62,833,199,351,334,92,657,106,126,249,429,978,814,474,243,653,979,263,732,864,214,950,763,61,276,848,868,499,396,871,87,15,366,261,986,992,650,515,2,397,983,215,159,491,289,799,952,668,60,676,676,566,918,86,951,934,716,990,924,530,124,358,928,739,599,903,259,842,515,932,947,918,333,279,153,918,394,37,590,598,622,648,440,791,620,963,244,582,319,536,912,419,73,73,53,50,140,490,319,836,328,843,948,441,685,479,100,797,614,294,137,108,551,411,678,37,51,808,828,19,424,178,638,438,332,149,13,665,3,195,341,472,993,371,12,636,621,985,962,316,226,67,381,510,554,881,75,432,219,443,575,559,892,880,425,374,49,602,24,923,444,39,970,803,54,340,746,187,292,102,418,228,334,962,968,161,308,532,659,323,208,942,342,223,991,389,329,957,554,279,596,664,741,502,924,115,378,745,98,827,996,101,984,715,456,974,452,902,862,267,214,44,637,422,334,296,980,238,467,290,974,362,48,93,861,158,562,223,443,87,8,969,946,29,147,449,396,146,584,740,449,562,383,940,506,583,362,837,81,998,472,418,220,725,491,982,506,288,586,546,798,622,180,132,741,453,857,684,436,214,309,774,34,349,945,265,95,235,216,447,777,709,757,665,788,420,820,47,960,87,163,299,948,654,264,884,225,529,154,97,880,129,543,842,911,886,498,721,572,584,523,411,226,441,645,489,219,409,80,519,904,597,486,789,569,502,558,395,605,413,935,914,814,413,443,263,107,810,726,401,701,386,504,103,281,230,803,994,9,457,973,572,462,854,197,925,338,777,366,624,299,708,523,754,986,346,908,264,308,124,293,418,839,427,602,819,391,810,814,550,72,76,829,69,311,31,66,298,973,440,391,233,157,336,778,712,450,229,728,922,360,584,107,425,45,243,254,905,322,499,583,61,578,979,660,28,65,230,600,825,864,347,937,378,754,475,130,76,148,341,385,734,306,312,7,966,73,245,607,959,143,335,436,931,885,532,295,774,634,218,358,387,407,298,161,306,831,386,128,163,471,525,559,730,179,274,196,531,787,859,307,357,164,406,964,408,43,433,146,706,160,752,76,815,707,965,141,247,352,118,203,364,424,151,709,888,267,429,157,911,944,810,722,530,277,660,23,756,697,357,456,121,222,964,431,503,518,651,699,779,531,588,550,560,114,414,201,562,813,602,978,273,877,967,903,770,491,579,350,880,406,991,568,158,141,327,226,517,806,584,825,624,504,630,866,846,347,824,633,946,837,725,391,38,712,21,443,872,988,14,702,745,309,975,6,275,706,165,461,644,560,204,34,260,719,53,480,686,904,266,979,607,601,898,808,121,721,539,685,380,533,285,947,521,400,913,816,502,176,251,342,449,121,160,488,494,126,142,598,420,614,302,228,869,555,613,712,531,333,938,631,967,989,416,700,352,193,620,401,775,954,167,63,3,572,222,471,468,968,719,352,895,859,733,323,530,981,543,671,420,904,182,196,381,711,152,580,406,149,731,308,71,206,995,956,808,645,526,828,141,754,902,775,853,976,314,915,660,355,350,805,507,200,507,45,362,470,254,261,507,265,475,246,879,306,104,424,186,240,278,648,692,804,932,568,3,811,216,137,950,957,397,43,313,902,367,537,310,717,867,387,102,148,638,454,968,220,606,752,6,144,601,392,546,631,852,790,426,95,772,433,84,700,435,516,521,909,170,786,995,892,437,480,516,516,863,965,660,450,131,771,281,339,360,381,327,290,321,571,635,331,846,186,398,98,134,398,806,901,302,326,922,371,177,510,718,347,235,322,874,775,928,284,366,436,622,998,763,257,305,384,640,329,504,75,306,69,466,719,323,401,657,386,40,173,11,767,787,64,856,476,391,540,692,699,20,313,273,219,212,47,932,586,14,309,643,367,945,853,582,572,745,866,104,532,265,554,200,3,86,246,443,432,257,597,209,55,451,316,935,971,693,16,745,623,62,357,476,133,689,824,227,858,549,415,53,366,208,865,341,947", +"358,664,769,550,219,439,354,86,183,829,86,641,146,660,622,304,368,587,268,18,652,253,0,873,213,93,216,408,976,798,427,620,229,638,875,168,304,548,176,848,393,716,954,364,180,31,116,597,499,229,688,965,829,632,71,116,674,382,836,308,277,187,821,18,426,800,223,405,95,286,638,630,998,569,967,425,319,599,101,383,380,246,138,664,836,680,607,124,624,19,911,747,889,747,704,317,309,578,799,893,894,585,961,592,173,370,116,513,706,498,523,688,103,128,686,789,343,46,735,217,305,918,288,22,68,526,533,934,201,466,52,814,48,463,97,340,976,652,122,182,203,535,808,108,19,356,898,23,769,409,399,616,160,32,764,311,244,595,84,554,436,483,95,209,909,473,713,662,326,509,370,814,427,285,808,288,695,177,771,849,512,961,512,499,803,834,395,481,421,25,297,433,486,417,202,606,223,189,662,310,670,459,242,382,273,883,412,132,35,773,880,962,339,54,810,852,368,395,654,756,643,745,668,113,29,129,382,424,858,327,110,912,592,511,65,77,645,292,855,71,431,759,156,604,537,557,909,379,949,444,113,117,960,45,412,406,156,899,873,657,179,933,804,389,484,126,726,619,789,565,177,903,808,631,988,940,326,844,314,623,114,228,538,491,528,772,39,853,280,336,412,587,722,869,300,70,718,141,152,935,716,634,270,568,477,411,114,314,20,261,561,903,27,65,751,393,735,572,419,742,6,459,245,147,72,51,538,737,674,471,474,742,943,372,17,58,611,142,434,94,996,801,267,775,739,345,528,380,628,853,429,192,291,428,804,561,797,825,497,493,1,414,626,873,221,686,168,11,349,73,988,86,144,336,627,149,701,143,352,684,373,835,523,826,582,816,981,518,548,906,822,330,350,879,962,778,390,868,386,326,188,496,653,803,352,38,886,295,430,155,826,594,125,477,457,844,58,905,368,4,594,862,783,386,969,829,420,295,115,490,22,507,602,267,975,245,190,680,260,154,733,754,385,447,31,376,337,941,164,970,893,714,880,498,424,219,9,3,89,583,57,932,746,422,584,70,926,544,319,265,498,326,449,507,291,854,591,170,475,269,184,332,945,930,430,650,637,301,562,898,669,697,560,28,841,790,909,836,664,697,149,965,751,439,286,223,125,669,870,674,711,976,507,32,339,68,753,938,450,856,33,118,398,228,348,470,676,423,812,567,134,460,857,130,818,230,476,79,982,437,679,185,900,751,96,460,185,84,916,529,346,645,215,830,999,839,131,90,389,929,211,534,568,685,473,48,891,652,412,144,371,340,384,759,312,415,921,516,519,705,294,935,486,733,268,731,198,55,670,270,165,849,357,211,708,710,39,584,174,529,855,990,665,746,629,843,279,728,249,131,935,566,104,518,609,27,674,675,315,927,325,8,209,346,848,301,624,388,87,480,798,487,49,225,170,324,610,921,469,550,306,511,370,798,518,659,195,752,670,763,144,884,764,427,101,113,507,598,421,486,917,535,740,337,290,452,132,198,973,952,16,265,351,308,22,706,327,49,787,560,494,530,348,120,322,961,269,437,372,307,334,132,797,650,483,169,383,654,496,620,492,118,702,4,457,50,529,374,169,710,888,763,527,978,126,548,252,680,922,100,619,36,645,728,472,468,303,907,175,258,568,258,673,888,120,282,341,627,168,981,7,14,820,596,569,104,281,402,486,745,49,787,363,18,526,696,896,732,6,66,194,639,16,135,997,20,882,713,438,770,281,447,866,34,459,159,796,499,448,354,566,103,986,925,765,423,85,604,561,869,950,226,302,214,552,948,465,662,160,733,435,460,638,123,335,919,733,880,21,483,187,653,38,33,338,436,336,603,555,711,983,574,786,596,39,325,688,714,159,565,779,451,644,360,940,678,342,662,255,532,407,366,580,724,166,340,677,237,202,920,193,917,748,955,767,876,336,642,638,451,847,480,348,313,643,153,616,132,361,421,680,131,285,27,640,342,777,479,20,506,491,47,180,197,690,732,966,255,94,71,22,863,767,269,961,686,415,498,81,660,719,154,586,967,120,260,162,550,493,388,852,721,870,208,128,56,64,274,160,306,962,181,881,851,892,923,662,956,725,849,521,449,798,353,984,775,504,319,499,582,735,211,214,147,769,452,513,883,975,290,153,414,393,556,621,760,708,152,392,201,384,613,883,674,231,945,549,860,263,828,716,470,634,242,93,845,767,75,320,931,572,647,779,564,303,10,245,904,801,291,723,723,881,696,138,632,795,664,490,127", +"852,686,538,571,921,158,765,333,32,213,872,935,473,548,123,977,115,141,474,691,964,24,873,0,8,930,962,128,274,555,24,852,567,553,386,709,481,436,99,42,651,318,186,953,242,868,322,603,543,476,937,625,980,128,910,71,368,12,513,915,810,455,175,3,589,602,871,700,319,567,456,140,54,679,382,793,213,730,283,920,779,726,107,369,208,116,113,877,36,63,136,148,977,282,753,58,490,62,174,879,995,452,956,528,23,778,609,878,237,651,935,523,846,732,84,937,118,925,814,228,708,664,236,756,535,434,794,929,188,760,676,505,949,981,609,19,147,647,6,2,568,709,661,704,54,775,311,963,388,678,497,446,71,675,468,462,233,29,798,779,555,662,992,172,122,388,677,157,318,482,881,164,395,114,98,131,921,93,823,385,789,82,631,112,82,320,959,237,653,41,151,685,240,260,169,823,62,171,504,950,750,577,281,887,713,454,760,113,141,72,774,525,400,15,344,845,779,755,564,36,162,224,805,381,34,873,417,500,482,831,537,226,159,489,219,211,732,328,651,275,976,432,472,972,812,483,217,171,78,440,452,939,483,679,563,544,981,381,809,543,455,305,935,766,596,417,48,97,336,381,834,729,820,333,304,352,445,444,963,145,873,557,27,583,843,142,817,457,577,406,648,230,927,74,395,558,264,490,650,814,270,745,453,584,911,973,510,612,270,278,646,26,391,83,194,310,299,164,541,328,277,228,688,665,145,746,991,984,629,65,2,123,973,465,916,141,534,376,825,296,978,102,151,264,224,627,538,151,169,783,754,731,63,423,816,616,963,90,137,660,926,864,880,921,448,990,895,449,703,640,907,155,247,549,118,15,156,338,818,49,85,165,314,695,13,785,294,734,579,908,461,736,307,792,509,567,241,563,798,176,841,32,949,567,643,87,133,811,412,330,525,137,51,459,631,72,37,800,213,707,88,9,968,338,931,610,825,864,69,283,837,852,966,48,238,562,898,597,170,337,176,750,749,86,969,54,190,765,333,29,140,194,802,274,811,687,601,804,403,686,112,509,554,764,914,372,842,654,824,427,625,808,231,168,792,158,875,661,720,976,822,942,816,84,901,609,883,274,111,661,778,222,674,328,499,811,618,703,420,295,632,263,770,148,99,702,681,995,343,66,125,131,263,228,148,299,239,303,396,792,523,842,385,418,317,93,724,122,869,8,244,960,367,870,755,146,727,867,587,835,303,288,782,750,964,881,654,379,187,646,792,66,290,933,270,559,293,19,232,353,796,554,170,784,238,248,108,228,498,337,609,561,604,176,639,268,583,479,671,203,764,883,690,606,247,555,499,216,508,77,81,198,184,304,339,856,275,981,403,470,250,869,161,989,597,583,30,587,306,484,503,607,837,197,691,201,192,893,247,728,420,15,594,457,678,445,206,503,360,989,695,127,403,11,522,595,268,296,976,145,925,364,323,753,805,614,138,576,778,897,621,796,791,617,834,475,710,291,364,632,56,846,518,300,559,421,736,786,918,589,389,591,714,825,471,477,304,448,276,291,32,980,667,485,377,884,40,896,359,528,173,813,863,20,88,333,966,588,174,506,425,737,349,200,79,728,823,582,666,464,97,982,665,655,237,656,53,943,390,893,141,911,652,681,910,822,387,959,983,278,129,694,70,903,169,849,217,418,665,824,759,65,316,262,605,541,765,876,919,583,692,171,139,110,574,792,100,992,431,787,528,321,122,731,643,138,393,130,112,185,644,997,213,225,70,877,882,172,942,934,288,446,848,314,409,169,754,894,152,860,577,771,874,936,653,276,203,638,152,515,799,359,134,254,20,83,823,29,744,68,444,575,442,25,706,515,126,46,489,881,636,14,951,497,918,391,52,940,383,248,742,203,828,72,32,949,174,961,739,809,154,107,490,815,509,969,74,485,810,831,146,744,538,263,34,332,62,826,456,643,675,894,462,764,984,188,482,304,244,317,438,348,41,171,665,969,106,950,497,837,548,776,322,61,746,802,352,152,843,306,793,161,109,353,407,380,791,541,382,775,504,787,367,950,128,990,209,857,427,649,330,392,655,213,636,51,212,605,337,490,393,837,52,307,353,110,187,617,668,570,69,977,818,717,68,883,516,934,109,490,444,592,790,42,310,149,5,692,752,644,612,34,831,516,959,4,948,621,300,559,845,41,744,411,593,314,470,428,77,137,4,203,587,574,613,5,592,591,815,330,478,889,900,231,136,995,668,843,366,931,664,51,467,952,259,852,559,243,17,83", +"356,149,459,135,253,84,858,694,412,669,523,878,131,423,96,900,167,284,960,671,387,452,213,8,0,135,511,388,733,119,454,770,527,977,384,286,345,139,774,3,896,861,342,433,219,528,849,703,763,327,234,107,613,928,57,591,91,323,727,210,537,641,54,493,515,412,568,605,121,540,805,771,506,967,376,534,779,19,8,495,936,27,229,799,819,946,537,504,789,534,434,818,323,600,182,193,719,736,367,835,176,517,84,236,831,126,565,864,898,985,975,186,91,450,315,995,974,872,463,308,855,342,277,978,960,916,283,517,545,291,856,770,160,811,270,899,145,116,410,246,271,696,231,914,436,140,805,679,173,582,29,752,740,130,624,667,115,69,303,349,284,384,126,456,103,371,936,329,666,348,667,346,848,341,194,702,168,29,316,395,869,855,391,87,92,690,874,361,395,182,810,423,345,389,604,306,727,668,367,900,215,240,561,30,661,119,906,202,830,862,140,681,790,155,263,22,715,792,177,732,551,995,604,640,771,232,766,649,596,519,26,948,255,430,80,960,514,462,88,753,597,557,985,61,60,184,783,787,861,768,820,732,91,471,868,790,220,395,550,580,625,11,229,740,251,439,745,200,514,197,993,280,880,859,749,532,433,763,844,410,978,814,686,329,611,663,5,57,794,946,351,13,704,290,732,718,496,906,200,850,739,759,294,16,357,37,544,56,88,44,165,120,204,315,881,333,577,663,840,574,941,564,626,76,40,338,251,501,410,200,510,348,923,437,939,335,672,379,563,764,857,880,333,905,985,62,971,214,530,717,558,764,955,940,735,337,205,157,218,594,254,264,501,781,168,893,866,40,89,218,624,239,8,802,824,688,329,157,250,762,789,919,304,919,373,326,845,422,864,699,946,743,841,422,109,454,953,397,48,791,507,766,85,402,262,535,412,31,684,982,673,78,211,747,396,835,216,882,734,419,699,384,210,673,584,803,205,110,506,419,679,253,635,378,995,983,831,986,674,68,130,311,437,172,266,117,569,848,29,912,235,107,968,266,17,420,108,286,410,995,510,260,59,912,629,209,943,654,154,52,351,411,660,642,739,892,10,390,819,950,899,374,841,140,303,867,625,776,350,165,393,431,915,840,351,424,951,739,504,522,364,977,108,337,92,80,819,639,455,413,218,132,13,178,815,739,375,222,36,247,612,77,461,459,911,4,487,793,994,900,677,503,399,296,255,806,411,991,371,578,768,436,444,457,592,427,446,462,991,666,920,509,57,595,823,487,308,453,201,176,27,962,981,265,223,598,249,949,436,759,498,687,749,51,626,564,236,400,802,577,910,762,318,115,786,401,410,538,951,734,53,439,61,532,667,623,651,635,385,680,128,34,806,148,243,714,788,634,274,265,983,358,716,920,922,286,982,699,593,978,655,245,919,338,270,997,186,719,170,593,500,701,155,846,177,883,559,525,60,706,852,120,330,999,576,938,56,459,822,817,165,798,116,718,51,735,168,712,903,668,910,621,184,692,714,624,66,746,648,409,108,285,472,470,730,368,195,679,15,295,95,820,90,68,112,246,731,598,769,969,979,807,346,820,886,630,358,905,463,948,586,816,523,122,876,235,68,23,784,900,479,592,690,240,512,335,84,222,70,847,333,932,359,508,786,982,463,380,168,1000,658,418,241,507,577,112,343,613,827,19,37,222,735,199,106,17,928,910,754,496,257,638,328,461,681,569,49,31,828,438,395,484,641,306,97,115,951,937,422,97,429,148,368,576,256,992,258,448,66,102,100,864,696,336,78,755,986,251,328,279,646,658,811,20,294,742,67,786,35,265,75,926,927,854,338,930,45,373,16,645,934,330,796,250,306,788,313,161,252,925,463,390,942,214,7,928,5,653,77,644,394,352,443,669,793,217,100,476,574,354,615,492,987,667,385,912,778,183,24,219,836,480,291,931,190,319,679,121,856,763,68,682,923,435,164,35,628,76,805,797,899,104,566,646,922,402,776,735,559,724,92,558,162,312,82,888,886,523,591,129,863,712,986,412,383,333,557,966,242,14,378,135,767,483,612,372,827,224,967,151,459,675,319,342,988,434,857,569,531,983,270,103,401,740,332,17,707,675,569,589,501,854,667,803,118,355,806,404,415,841,265,815,155,946,692,457,543,276,414,859,743,364,554,874,623,614,553,308,59,343,539,294,412,101,976,387,238,354,94,494,13,204,468,599,84,629,133,734,560,684,39,730,563,97,218,512,525,915,52,172,689,511,394,472,79,412,556,623,78,684", +"444,440,857,708,211,27,223,407,279,73,742,424,720,717,762,967,93,596,830,992,318,95,93,930,135,0,392,530,608,328,271,341,90,140,472,212,167,781,718,147,197,993,337,764,233,377,70,102,425,306,970,951,945,636,924,752,167,867,901,265,581,739,891,25,734,46,598,521,348,95,142,667,357,879,30,609,946,53,263,766,314,539,625,877,111,59,637,929,336,844,653,503,732,866,832,657,829,413,245,973,781,739,187,50,40,589,140,390,967,787,800,551,817,906,388,381,582,245,543,981,2,372,612,111,950,837,566,659,23,679,344,654,850,491,870,237,203,850,107,327,586,731,452,550,810,451,167,72,907,497,670,26,554,396,308,720,307,199,654,721,418,409,826,962,787,729,702,906,600,679,643,976,756,804,197,361,504,450,758,133,998,168,881,753,17,798,608,441,296,783,735,702,991,787,460,720,392,433,678,824,238,91,982,872,56,832,729,903,445,113,486,578,287,474,338,133,933,400,619,809,694,670,818,30,184,136,955,632,996,141,434,292,69,542,565,883,925,46,207,663,611,381,394,875,119,517,327,416,460,766,296,287,571,461,265,655,752,716,377,244,938,404,47,952,460,338,771,787,815,733,453,111,895,484,523,582,692,390,219,526,830,227,893,881,246,236,167,68,566,194,687,866,439,767,373,513,85,303,665,58,885,796,209,188,54,839,363,554,585,238,769,424,271,195,687,854,255,490,906,524,669,865,231,988,607,930,36,384,247,965,283,422,542,124,88,406,255,926,407,586,87,906,390,971,359,313,318,155,102,517,98,238,888,284,628,212,860,206,461,598,320,147,383,90,516,660,2,934,640,238,315,187,586,603,642,511,85,794,58,958,520,936,712,345,763,234,345,798,194,447,194,323,920,932,988,26,122,923,856,128,908,793,394,593,536,591,182,682,562,769,886,953,798,464,492,840,344,838,450,499,475,874,874,231,285,874,90,359,560,382,907,266,918,93,70,854,406,70,277,635,294,313,363,313,846,943,782,4,9,250,699,235,357,954,275,797,5,933,542,117,687,790,854,895,686,482,794,835,999,120,18,160,274,855,119,84,519,800,573,207,481,68,789,927,670,741,803,47,279,216,493,222,238,140,447,447,995,200,253,188,964,296,598,924,849,303,846,943,845,701,542,670,765,545,716,807,434,707,247,326,772,49,679,785,893,685,261,373,960,156,325,215,958,101,385,530,164,236,696,178,634,12,466,918,606,280,887,148,189,416,142,418,748,619,638,907,911,366,288,658,528,939,243,450,766,23,793,838,862,322,454,516,90,960,743,797,841,407,370,468,9,176,160,568,809,752,471,968,735,158,368,695,703,570,420,957,512,854,819,167,894,215,527,374,337,283,539,52,133,715,821,661,384,187,914,386,484,738,995,869,166,604,662,483,416,198,971,719,311,972,166,428,115,931,431,339,55,839,933,191,378,693,673,67,25,618,81,673,297,243,678,272,330,958,617,289,912,775,550,526,187,915,106,983,604,768,750,633,136,389,887,301,689,586,705,317,729,656,611,845,454,294,12,393,562,117,90,258,392,96,114,403,222,3,428,621,353,150,496,940,59,730,576,45,981,546,332,110,471,998,623,187,487,296,26,683,280,474,983,125,455,566,966,371,502,835,19,706,454,835,588,201,324,586,504,173,426,579,620,481,969,526,65,958,14,582,145,282,343,744,570,299,529,989,449,709,245,807,665,279,830,450,319,46,428,840,695,710,496,445,129,343,749,926,31,484,676,432,961,205,547,314,171,109,189,766,969,851,952,492,373,843,163,493,370,341,461,210,862,332,941,613,200,409,973,902,51,541,100,147,307,10,494,651,825,399,93,124,450,417,165,866,108,190,189,808,394,23,399,883,87,883,189,432,74,703,634,512,156,799,1,1,131,725,697,738,984,166,24,520,562,21,535,878,40,86,554,255,233,932,478,758,448,21,152,665,734,509,499,963,373,626,801,74,688,836,185,803,185,884,788,88,17,710,111,92,518,172,798,28,474,983,458,207,890,541,252,319,710,151,140,522,601,241,74,426,295,371,474,674,130,691,29,180,156,875,778,247,771,358,569,742,638,112,511,979,819,569,869,719,344,531,783,752,430,843,360,89,852,475,223,907,521,133,77,229,548,279,961,680,612,221,782,715,904,7,620,850,639,244,136,448,186,747,885,560,414,906,228,667,510,228,197,563,650,833,672,333,763,548,872,400,699,948,917,61,814,222,49,558,944,67,664,857,71,722,894,213,9,438", +"396,863,820,85,368,534,556,370,915,736,913,774,555,659,744,804,409,718,869,980,521,64,216,962,511,392,0,900,77,745,968,52,97,341,18,418,53,305,301,718,621,641,566,324,468,154,792,470,65,824,547,889,90,460,677,734,40,640,368,168,156,661,579,260,273,700,600,204,844,449,907,905,134,58,955,818,578,195,675,417,236,192,418,659,238,928,360,824,133,127,584,722,992,108,382,987,160,340,478,396,849,486,533,802,608,827,71,385,471,370,912,284,30,306,928,144,773,328,959,458,356,211,153,743,702,658,432,64,251,741,105,54,36,969,972,388,874,833,433,970,263,582,365,131,300,222,15,167,315,733,156,181,757,221,494,933,32,537,61,53,293,784,234,365,155,388,439,16,15,217,974,171,282,547,884,937,902,652,173,597,564,569,493,735,47,144,474,291,454,24,619,846,257,878,116,512,131,299,776,783,783,307,225,187,724,827,310,341,21,852,941,864,447,417,410,152,194,575,265,747,529,788,563,913,614,94,80,148,629,93,72,289,694,813,811,150,393,13,467,993,102,885,908,184,688,615,357,145,102,64,361,316,468,408,862,975,211,117,918,847,34,210,776,431,121,598,541,364,928,668,483,327,704,527,337,57,400,3,868,725,537,687,969,355,141,434,198,301,843,918,288,405,275,264,674,468,166,327,900,83,614,861,534,166,528,914,528,334,515,753,812,684,275,526,677,279,248,853,877,341,419,651,363,705,170,792,887,621,743,119,701,275,52,517,618,729,777,228,495,751,616,786,920,129,966,949,560,98,81,883,815,103,493,53,764,188,935,859,758,539,659,38,220,825,865,466,212,892,322,992,334,648,727,828,481,556,54,259,461,276,273,708,517,69,224,193,625,951,54,204,476,743,687,55,507,567,222,155,372,298,592,352,767,383,351,102,679,635,841,199,677,882,262,530,412,428,664,233,391,490,620,626,354,625,997,105,326,479,811,465,92,526,601,79,249,399,11,505,886,573,919,564,295,911,852,934,587,181,150,108,327,810,440,692,178,707,908,999,69,39,340,662,45,64,526,967,446,564,530,4,552,170,169,408,482,71,641,988,276,463,460,428,958,86,100,220,915,797,447,827,681,707,923,745,897,663,645,538,208,70,124,715,535,95,408,578,985,557,689,219,977,765,189,480,811,682,579,611,200,450,144,762,238,125,861,232,753,930,35,504,572,440,733,812,832,11,913,675,306,101,848,978,263,157,693,829,505,492,301,633,362,810,857,272,764,392,741,18,591,618,809,270,950,881,789,820,165,14,198,405,968,908,921,869,509,33,793,384,899,810,238,77,612,223,176,442,33,703,119,591,255,67,997,154,129,409,492,252,300,205,729,341,663,368,606,572,807,801,518,135,646,154,767,572,64,297,346,238,997,940,369,351,655,8,21,981,280,888,266,338,320,585,635,990,571,944,378,448,768,616,77,337,287,838,695,521,479,623,694,716,14,607,185,675,491,480,809,942,228,322,67,65,266,323,530,38,889,703,859,178,491,439,347,168,876,362,751,831,296,73,994,485,859,654,312,414,386,226,544,462,644,667,704,346,875,741,167,813,184,549,628,714,589,785,270,778,212,606,495,886,500,63,224,736,940,197,650,339,922,964,160,480,824,347,158,643,632,528,287,892,133,501,264,641,961,187,836,427,287,694,390,810,111,781,677,867,14,56,431,599,115,341,786,990,884,630,896,20,201,295,655,253,281,370,281,988,567,629,648,430,591,624,613,117,479,587,876,554,219,607,348,761,396,963,682,184,108,742,890,634,231,954,418,138,19,290,481,460,485,107,564,719,932,463,890,331,622,241,155,105,789,319,144,690,217,271,180,732,786,886,879,575,375,502,953,937,593,782,38,665,927,110,375,422,698,291,279,27,779,411,350,603,895,811,894,434,234,597,850,784,722,913,518,495,862,942,451,44,246,22,526,121,854,836,954,749,678,195,972,201,976,794,660,691,203,642,301,457,923,453,826,233,701,734,331,862,923,164,189,316,844,214,499,867,822,856,489,768,723,55,776,767,928,609,543,175,265,754,856,883,110,489,352,266,747,11,293,273,286,757,820,592,563,534,304,416,810,471,547,572,932,837,427,859,18,626,766,859,809,655,639,109,15,57,592,991,176,745,930,929,320,756,634,807,115,738,847,748,29,941,712,723,31,88,214,64,274,716,392,486,948,419,575,482,861,467,149,106,468,562,566,798,31,373,325,492,30,338,519,296,755,175,875,740,570,945,753,250,919,756", +"95,46,971,803,206,980,268,771,63,131,352,63,110,520,354,163,442,189,969,200,261,826,408,128,388,530,900,0,492,882,490,660,480,216,925,575,165,974,995,391,559,338,861,311,617,37,53,659,525,153,516,88,746,365,255,772,67,175,677,690,544,857,607,617,767,644,882,454,293,696,937,892,183,611,575,839,23,150,472,123,987,735,918,18,369,51,589,281,357,637,359,294,996,953,117,664,39,792,786,627,720,259,522,994,337,159,302,746,35,642,305,488,191,534,177,709,7,718,443,21,734,858,543,945,661,111,486,209,496,426,686,140,549,197,736,551,308,368,133,666,48,113,317,917,496,11,736,489,173,399,499,643,448,62,673,496,205,352,949,209,555,154,958,761,314,477,278,213,435,600,339,173,84,322,623,22,708,240,570,381,892,397,127,687,584,674,259,204,785,203,529,807,618,869,230,337,705,647,484,289,555,867,940,676,333,552,727,17,424,79,377,13,374,75,873,358,152,631,587,875,691,446,764,388,396,712,211,23,187,582,774,730,916,623,721,784,787,705,880,493,544,768,619,755,299,299,833,76,906,372,596,289,59,627,265,909,552,131,62,540,978,697,958,102,875,71,377,344,237,672,953,551,983,122,382,77,573,473,626,768,462,32,419,639,417,809,203,647,945,716,292,634,646,628,631,97,774,556,581,204,742,479,448,944,514,288,385,399,787,179,611,258,481,368,756,381,364,425,546,885,894,869,959,473,499,683,729,884,902,523,494,482,241,552,410,42,645,10,736,7,921,939,248,141,909,754,830,708,795,862,698,602,616,514,528,624,480,988,433,250,540,804,185,223,884,42,294,104,983,979,69,32,907,237,890,613,203,25,463,166,48,860,297,714,799,871,621,451,937,556,761,381,206,338,939,912,675,659,989,312,106,979,125,399,541,887,802,77,322,601,550,81,474,310,345,120,156,917,37,238,933,108,485,351,985,113,804,109,599,901,844,540,883,807,934,193,515,741,515,2,624,781,138,883,355,373,63,426,759,41,484,671,616,187,969,408,160,790,356,29,650,525,52,529,7,196,461,174,612,561,1,415,182,129,876,583,697,194,610,346,764,14,935,692,867,513,710,726,610,520,78,530,684,515,761,378,859,19,856,589,143,306,733,419,348,39,635,824,383,234,450,382,684,309,622,671,68,859,39,41,348,971,251,57,109,956,127,985,560,773,651,444,748,881,704,951,940,30,765,88,588,720,310,242,896,607,367,894,887,569,440,333,239,825,794,211,569,774,986,818,262,832,466,910,144,655,415,601,118,119,470,559,500,161,967,259,34,141,594,903,379,529,277,407,604,198,594,561,129,455,809,887,939,705,998,915,839,794,280,819,927,343,172,191,881,68,578,850,966,399,302,194,815,534,968,956,607,134,557,383,979,105,522,814,551,699,979,252,737,42,395,798,587,554,71,529,797,761,684,66,520,996,302,87,762,501,892,149,11,2,200,266,868,568,497,407,387,95,954,625,620,340,151,704,671,724,237,463,600,503,627,851,258,496,856,143,625,414,749,504,320,229,335,234,1,850,518,286,730,803,2,40,458,457,638,78,670,404,461,242,881,20,345,199,777,834,284,863,420,531,163,985,197,414,58,850,897,837,462,893,713,120,516,454,284,721,715,137,119,448,193,349,544,162,501,501,511,827,837,350,347,427,400,230,451,678,279,716,821,879,908,773,30,268,855,754,596,701,557,713,952,932,386,11,682,919,178,535,102,827,908,988,138,203,267,766,994,547,699,702,266,424,206,263,785,316,782,335,834,521,898,442,371,437,163,509,638,858,895,463,55,813,913,645,887,860,897,275,370,990,775,824,239,775,726,979,914,890,822,883,616,135,524,613,241,370,519,876,662,192,123,841,483,165,478,945,711,146,16,372,508,878,427,758,932,537,627,331,246,575,262,496,471,201,503,824,756,350,958,540,146,422,175,775,634,789,969,944,847,261,358,806,629,666,96,982,270,63,939,758,515,653,840,520,440,999,584,768,26,34,767,601,623,570,995,8,888,211,775,147,437,691,633,49,407,716,49,387,220,855,789,258,821,148,684,797,444,629,63,776,894,255,445,887,51,819,129,476,890,540,732,357,526,670,463,42,624,137,727,269,646,300,945,168,122,28,826,477,523,11,800,448,181,764,871,178,758,49,901,233,96,213,878,306,2,537,899,393,861,533,572,504,923,713,393,113,420,767,832,181,5,833,995,657,845,565,615,398,787,288,659,179,626,723,142,972,722,844,469,264", +"446,325,750,595,811,462,898,674,722,573,841,352,194,184,512,336,485,487,534,957,165,727,976,274,733,608,77,492,0,383,129,57,115,794,896,829,523,476,567,959,492,596,239,16,265,809,732,470,156,464,66,480,332,55,412,873,600,123,658,25,157,550,202,615,371,574,461,425,659,412,548,161,161,287,160,969,617,516,450,605,718,571,725,322,222,250,787,600,606,51,898,594,843,917,789,174,486,914,698,218,315,589,757,961,663,875,573,665,556,212,323,736,456,566,37,723,662,953,613,751,162,227,431,233,863,595,353,53,908,645,710,241,28,681,337,661,356,348,815,438,444,860,570,20,33,638,322,717,812,351,276,920,717,746,603,79,274,43,3,201,210,758,436,141,899,708,979,627,280,645,784,743,492,285,95,268,990,740,721,465,292,738,621,329,389,437,837,223,178,899,708,708,511,295,101,580,504,562,168,815,471,841,151,337,879,442,650,949,271,211,593,522,37,229,765,675,26,313,895,293,458,235,414,405,501,528,377,257,952,887,908,769,206,239,883,974,383,497,907,824,384,966,477,630,958,57,62,87,274,550,963,993,71,970,655,724,769,247,628,541,48,275,357,831,135,797,827,426,334,291,621,78,635,411,988,590,445,392,431,364,987,338,468,173,237,125,557,769,291,231,866,20,808,473,726,177,556,349,801,770,712,611,274,353,560,550,98,240,177,362,209,682,305,461,495,921,581,61,427,770,238,243,719,619,597,3,330,825,232,424,107,799,332,867,424,907,274,805,929,534,631,159,841,762,688,780,131,725,798,287,766,115,46,664,509,882,310,55,670,512,464,951,4,409,320,742,843,919,13,896,646,958,260,256,341,772,61,846,186,528,391,983,291,16,776,805,49,715,639,965,310,344,358,732,190,185,75,798,907,697,577,924,460,446,130,107,874,360,912,84,286,33,726,102,919,910,306,815,860,942,789,710,545,369,34,659,893,797,879,517,967,13,946,361,652,296,738,975,512,394,88,192,61,655,382,885,355,856,482,935,310,228,455,288,92,721,14,329,587,928,78,162,9,117,948,526,348,979,107,932,406,107,59,861,793,165,811,539,344,377,394,439,812,441,992,969,160,562,24,386,911,550,299,547,189,499,412,351,921,282,497,357,173,548,815,778,657,720,956,57,526,264,925,647,612,882,470,248,628,239,133,729,281,530,143,388,433,628,768,294,724,213,945,145,885,239,150,305,315,932,644,726,97,671,381,431,354,17,278,940,498,460,56,919,455,491,1000,744,32,349,529,121,238,690,184,611,386,817,209,114,104,750,810,599,631,394,774,44,240,351,380,493,806,897,197,708,325,597,474,279,924,319,871,57,773,296,888,438,760,860,264,889,384,675,286,282,783,781,33,237,827,125,660,28,539,843,415,282,834,826,660,621,577,39,283,439,380,511,756,856,374,616,368,496,888,884,584,80,610,221,899,604,25,416,476,775,613,505,133,40,758,363,632,109,2,292,431,754,994,885,65,794,328,787,960,780,892,834,209,677,431,359,374,694,352,559,9,246,780,33,119,444,710,610,28,366,156,391,251,259,18,901,114,83,85,383,960,90,577,910,441,575,255,901,991,254,247,577,97,563,76,854,554,976,863,769,157,954,104,553,485,842,334,808,371,726,625,465,30,674,538,774,872,391,950,53,127,407,734,258,913,817,117,969,761,935,685,398,111,566,172,873,591,407,814,980,469,239,10,635,339,245,892,900,654,313,910,602,511,483,326,778,487,623,448,160,229,898,343,94,474,734,916,155,372,978,840,684,257,295,141,964,712,26,872,851,829,553,363,572,801,972,203,124,247,993,781,536,759,538,994,249,653,353,485,575,367,268,620,777,647,851,802,378,970,830,753,731,622,228,321,579,761,637,854,928,627,722,270,784,693,50,607,34,757,899,232,415,784,796,299,80,193,627,478,402,982,990,95,308,149,461,576,434,609,146,687,2,308,209,958,440,61,808,141,687,385,290,735,564,629,840,852,698,981,739,230,195,953,456,81,637,275,714,951,67,764,445,783,143,972,428,120,599,789,271,626,253,170,551,699,608,152,430,693,509,188,319,198,847,536,337,575,803,375,944,722,101,228,161,746,235,123,652,971,857,247,971,947,742,142,598,248,958,679,254,77,723,999,176,589,429,523,748,398,618,914,814,749,114,539,955,564,511,994,59,859,441,546,549,342,401,475,836,151,182,360,999,676,750,297,154,374,558,206,425,315,817,474,999,375,765,354,615,824,510,200,475,860,851", +"86,418,652,15,700,713,611,426,811,120,518,484,684,281,654,640,233,11,5,281,483,77,798,555,119,328,745,882,383,0,806,714,266,69,179,807,425,846,564,334,148,810,112,360,273,168,723,779,511,273,761,417,813,184,955,183,592,912,48,14,777,968,274,799,314,56,563,488,650,887,162,697,487,726,431,332,510,412,92,215,347,858,459,169,208,899,615,522,322,9,663,351,174,547,524,774,66,935,563,511,532,816,238,297,570,455,180,596,541,629,180,169,986,749,471,423,564,10,117,149,858,617,681,82,534,286,183,396,404,986,517,112,147,874,64,542,323,661,149,88,520,814,621,134,855,29,429,127,938,920,758,980,985,236,44,748,730,783,915,654,30,800,768,27,407,184,641,90,637,653,291,579,372,187,731,514,201,526,254,418,458,601,31,30,194,582,539,345,759,95,563,765,416,849,512,864,221,351,194,91,375,228,424,983,388,807,279,521,318,697,625,710,937,959,58,686,387,750,582,532,433,342,269,592,612,84,80,683,745,654,253,855,427,841,527,573,818,1,122,276,141,377,225,911,804,568,952,355,844,937,441,678,129,128,813,688,697,438,601,187,154,819,718,366,604,189,44,912,956,30,661,152,346,431,420,275,670,708,977,86,375,749,344,544,452,75,394,977,705,329,881,856,495,955,744,462,172,34,12,296,139,189,92,336,531,951,485,362,436,356,513,420,285,890,268,947,852,555,176,593,793,777,636,815,936,427,309,218,149,695,874,585,731,441,458,924,606,592,763,653,504,318,313,438,859,956,904,258,917,192,118,809,524,157,912,268,627,79,49,449,840,727,781,514,349,25,282,764,971,740,351,307,315,782,236,742,138,362,516,306,588,40,996,835,153,746,713,705,855,624,34,877,251,350,261,816,486,686,657,940,466,222,255,419,823,944,226,74,916,916,343,118,692,965,501,533,737,32,156,671,220,666,551,984,613,308,306,308,873,274,321,532,919,266,311,596,171,68,757,949,483,22,446,251,860,519,992,431,249,153,479,16,948,542,301,326,166,685,132,858,635,789,789,112,884,340,637,958,394,433,184,443,901,821,699,174,596,648,487,977,845,781,865,32,343,177,823,115,461,780,548,268,83,458,468,349,591,705,689,713,603,37,764,913,18,698,282,10,557,932,44,763,326,892,557,42,863,136,680,592,292,232,65,788,146,283,331,512,291,640,613,593,845,729,272,870,953,298,223,351,493,762,841,306,925,16,753,271,323,13,435,622,392,477,835,367,20,293,912,857,761,294,302,35,706,520,574,896,259,367,527,423,781,387,233,260,727,224,255,422,655,126,666,465,617,554,420,53,670,178,210,186,597,186,983,772,474,690,583,802,290,49,558,232,260,962,195,615,885,799,575,582,190,581,556,703,52,758,967,416,386,742,801,307,936,49,33,20,842,935,570,14,420,572,254,307,99,730,561,220,204,814,793,234,293,377,643,148,207,415,471,398,400,963,484,288,4,295,477,330,160,403,776,537,813,569,762,77,985,586,341,884,371,381,300,351,510,902,829,183,374,364,527,80,503,938,970,149,977,453,576,432,414,756,543,424,217,275,460,280,122,227,140,64,691,835,478,117,943,286,600,458,491,904,843,480,893,922,44,55,516,356,307,463,196,364,36,291,965,457,22,479,248,229,742,79,351,396,522,335,716,509,712,648,912,428,601,710,210,531,2,992,289,246,230,759,98,438,59,113,778,760,622,298,308,996,302,17,899,541,618,43,675,83,191,949,946,365,756,599,479,931,682,667,366,644,543,858,362,487,569,935,620,692,486,703,322,566,458,470,938,748,35,25,874,654,983,489,168,602,462,732,656,401,204,93,466,14,59,339,542,108,439,839,525,775,737,366,40,827,629,435,257,140,176,426,224,378,330,440,760,931,75,584,806,382,769,534,155,38,185,49,970,13,683,918,328,343,891,219,92,822,179,553,554,431,249,405,888,284,490,901,388,963,838,655,618,439,282,95,206,749,276,761,876,92,32,604,543,498,63,887,907,415,534,587,896,714,884,837,215,975,848,159,298,662,273,314,909,767,885,314,347,442,72,959,793,316,160,735,735,302,838,618,43,619,562,961,578,225,948,743,235,874,4,952,463,240,532,577,128,276,66,328,68,351,768,810,970,917,157,670,385,290,920,446,614,928,532,80,789,604,952,584,94,449,683,470,582,84,81,603,62,940,967,256,36,965,204,487,667,842,431,552,601,768,332,27,563,642,996,198,319,425,99,541,396,347,216,423", +"397,304,904,973,708,488,385,505,624,403,392,122,590,506,425,427,729,264,142,761,239,988,427,24,454,271,968,490,129,806,0,500,19,949,953,345,971,962,839,732,325,290,11,445,78,904,992,30,398,35,59,817,89,224,157,955,876,736,232,567,492,30,241,888,678,871,753,546,449,666,408,803,937,332,314,213,694,594,295,294,765,436,143,496,495,683,463,49,574,516,610,266,751,672,385,367,781,267,425,123,737,548,957,24,705,750,685,267,550,933,173,285,953,269,406,218,625,702,726,258,854,738,383,193,523,879,350,895,550,279,448,194,89,391,527,118,51,644,296,715,523,535,731,861,878,356,171,899,782,944,520,879,739,626,23,656,643,121,318,457,92,152,794,422,424,712,858,906,65,813,283,773,790,542,531,670,555,125,76,297,277,112,630,676,411,281,869,973,548,108,549,226,185,560,344,760,491,433,776,630,574,287,447,674,903,381,747,187,811,185,985,302,70,765,261,838,133,993,275,286,461,694,562,430,632,848,334,163,262,156,146,764,631,153,146,554,860,110,128,941,660,109,676,609,187,217,796,455,115,707,514,199,383,769,488,440,440,5,680,79,338,161,809,153,940,125,290,841,505,220,913,299,349,416,545,5,3,494,628,469,948,741,860,170,126,792,383,897,27,497,152,572,86,36,631,342,905,536,217,474,603,597,371,777,399,997,70,813,869,680,408,454,58,481,810,735,377,813,644,760,275,212,943,673,167,417,936,424,391,169,502,230,727,813,745,855,109,563,711,33,555,651,599,866,879,586,61,269,926,260,468,713,845,394,651,806,552,948,899,307,698,718,595,312,807,849,124,860,788,911,742,703,828,607,200,870,662,955,93,194,559,271,332,303,320,323,813,550,234,961,331,56,594,260,658,232,856,806,898,31,394,445,462,491,705,113,857,518,862,349,328,550,841,860,618,330,998,414,400,939,353,994,123,992,983,906,631,971,188,875,34,717,77,693,559,790,725,225,499,34,400,662,845,734,752,537,269,534,749,690,798,523,877,712,568,635,197,789,294,809,710,752,404,784,461,443,894,53,696,550,835,310,291,704,560,895,36,98,569,542,92,399,986,379,596,586,114,946,758,613,303,879,753,437,631,702,779,788,712,537,997,917,716,684,159,748,176,151,496,90,700,437,723,272,943,188,670,239,294,195,410,105,784,402,149,737,29,904,593,240,679,428,335,862,126,921,511,293,556,191,526,215,769,255,421,337,521,368,526,496,81,747,457,488,912,557,597,277,234,600,390,994,438,872,960,168,349,230,946,945,874,999,22,914,194,503,808,755,761,543,384,530,247,225,685,674,321,593,175,481,556,451,955,570,264,747,98,470,56,829,957,678,76,648,627,82,654,721,171,46,133,702,955,816,294,734,952,584,106,564,221,915,760,635,35,148,672,95,851,807,579,833,648,14,541,58,665,80,636,613,115,517,48,146,524,794,185,695,220,391,157,808,322,717,734,701,893,740,834,906,48,619,56,279,556,161,426,81,90,909,816,802,29,514,883,476,391,233,329,597,3,721,279,397,262,438,181,218,914,4,275,123,384,950,97,762,198,98,557,284,927,205,87,432,981,924,137,14,33,623,844,471,271,482,749,701,464,225,859,538,750,417,963,459,643,104,183,459,563,397,452,800,574,16,647,611,125,759,656,204,433,823,183,237,143,530,799,241,584,952,591,989,148,955,36,259,831,896,981,436,858,117,941,209,31,904,388,782,982,365,254,394,936,381,581,179,105,101,270,582,995,180,44,249,439,833,307,495,434,812,253,868,546,429,965,613,399,411,240,646,850,586,173,503,686,150,443,83,749,424,905,532,507,174,679,699,592,630,255,722,397,200,343,968,553,751,558,859,495,848,607,402,700,615,126,825,336,422,486,708,838,43,66,287,84,766,138,840,339,184,638,366,885,705,599,782,950,618,666,542,873,437,215,450,566,87,155,710,676,644,820,535,678,43,583,786,337,94,32,148,777,958,409,157,412,138,668,773,812,522,98,732,265,902,937,204,777,21,874,829,171,609,331,828,325,635,567,611,988,661,453,93,708,603,629,904,964,759,278,252,832,809,776,632,860,822,995,173,817,952,519,352,764,852,516,481,691,429,471,684,968,767,384,207,286,208,950,537,133,371,573,704,585,146,745,949,959,598,345,702,747,32,955,55,544,25,422,102,287,842,554,108,807,905,163,706,804,144,76,463,641,642,591,980,922,764,875,968,154,768,925,205,156,984,474,227,499,518,946,653", +"893,904,223,375,271,755,74,434,517,566,982,756,158,575,493,233,548,597,574,131,417,67,620,852,770,341,52,660,57,714,500,0,126,276,671,125,556,179,628,311,665,594,340,115,195,834,240,860,740,164,145,473,502,670,332,922,645,981,296,286,786,838,389,175,673,803,246,587,725,687,82,935,486,615,778,216,402,237,530,570,759,474,338,513,217,949,914,682,736,813,467,541,248,29,14,794,895,66,34,549,523,545,32,3,669,157,824,271,192,210,283,324,375,724,339,96,833,252,15,311,587,663,328,258,236,328,991,407,19,514,730,871,415,631,167,986,812,450,235,902,804,563,620,192,481,528,470,403,605,897,850,649,213,694,683,350,630,385,311,220,486,31,477,535,398,285,688,98,407,710,949,305,879,395,559,648,780,797,323,524,261,853,233,312,896,960,693,450,144,74,739,614,318,663,82,781,452,648,304,701,798,610,89,347,821,538,182,102,544,857,634,983,967,53,108,983,512,284,795,128,880,443,334,37,172,197,561,663,26,196,911,121,768,930,856,379,87,866,831,517,489,332,301,291,340,474,355,541,59,974,164,991,851,599,230,285,992,158,858,32,248,793,91,559,294,126,893,791,74,972,379,812,328,682,815,995,484,538,292,334,681,381,938,460,728,373,547,395,134,300,560,997,110,932,611,464,675,117,396,171,176,320,52,40,854,144,792,410,122,247,91,289,824,921,579,532,971,379,729,941,48,115,548,905,568,768,651,582,808,505,641,205,399,607,439,138,354,836,276,6,914,995,468,721,97,884,853,603,295,519,958,344,625,252,297,619,412,211,532,287,829,847,452,612,50,729,683,995,875,365,882,886,919,93,23,141,94,345,428,741,530,619,490,12,545,165,42,174,67,232,249,203,33,936,489,596,139,435,677,83,612,186,188,450,533,194,711,371,341,715,927,767,217,566,750,46,632,113,729,983,283,559,192,28,674,955,315,285,919,980,398,518,159,894,358,595,539,967,828,329,980,831,117,945,789,194,17,71,346,433,920,377,243,644,26,38,538,546,601,682,986,643,700,396,510,524,601,48,269,598,445,496,37,279,210,15,446,698,133,4,745,457,31,462,146,459,425,962,251,452,910,986,451,919,429,387,151,655,323,106,833,276,145,251,950,884,156,25,798,302,432,640,914,458,172,671,459,682,767,144,217,440,397,185,581,733,15,204,253,552,543,773,718,918,713,122,936,35,406,931,614,884,774,195,94,854,607,840,22,834,396,917,315,536,371,943,43,496,967,71,971,101,271,55,126,426,82,616,61,263,498,640,987,630,145,162,811,472,101,365,688,931,91,195,442,994,219,319,202,524,141,161,45,862,162,977,999,941,153,420,203,192,820,505,792,698,548,17,616,647,477,696,168,709,949,679,681,948,248,585,895,238,743,590,822,394,644,154,348,454,173,635,992,876,91,676,951,880,617,399,763,653,848,460,527,641,529,585,963,347,474,747,577,501,376,70,787,383,675,874,131,402,865,480,919,258,951,136,729,557,550,127,415,282,501,526,907,466,108,897,731,206,148,448,849,507,26,656,219,115,673,119,814,693,726,290,653,419,58,823,593,241,36,293,724,690,77,438,283,353,746,70,485,625,825,241,968,123,962,854,146,80,200,55,978,830,794,143,402,518,451,96,689,541,834,978,520,223,554,858,632,484,794,152,392,80,389,578,397,119,397,490,514,535,556,569,826,208,741,276,790,291,78,793,606,72,445,200,158,997,623,249,992,491,967,223,994,909,303,833,868,381,336,230,186,289,918,304,288,847,444,7,264,228,397,309,473,394,911,780,468,887,787,286,658,537,881,956,980,380,845,988,406,494,170,556,479,482,437,773,252,901,490,890,415,697,760,652,101,219,108,773,705,283,946,813,974,631,995,901,267,734,44,173,962,479,398,967,669,543,115,871,114,434,357,797,28,549,258,558,223,139,155,787,641,820,594,429,678,97,272,861,648,264,829,845,696,837,715,58,981,607,807,4,812,622,355,856,651,512,659,291,766,450,474,745,994,638,853,829,803,482,86,523,26,856,8,819,995,463,305,510,625,111,306,331,75,851,143,346,704,640,129,968,489,998,757,573,673,339,137,110,667,939,115,653,248,2,666,78,787,541,236,364,85,793,266,182,156,738,581,445,523,969,587,647,493,346,214,793,675,447,782,431,105,351,363,571,456,832,496,509,736,440,982,292,960,319,444,772,16,922,851,405,502,940,149,252,529,402,960,323,739,542,466,972,390,668,38,22", +"56,295,132,674,620,518,864,727,195,346,264,55,346,658,763,478,200,427,324,916,828,57,229,567,527,90,97,480,115,266,19,126,0,897,271,659,573,383,611,885,405,848,699,379,648,93,218,473,398,771,379,679,342,853,453,121,443,371,767,882,808,573,42,862,473,453,891,955,227,958,102,81,139,887,666,6,782,837,780,548,663,337,610,557,69,129,488,336,920,66,463,93,195,681,866,349,259,754,100,334,815,969,537,934,528,28,721,574,947,459,657,232,663,672,221,44,226,805,953,195,672,191,493,975,262,485,958,683,395,507,85,477,188,455,579,602,732,388,620,822,788,93,593,277,721,878,758,237,217,361,815,825,378,109,243,874,804,190,232,467,561,715,234,339,185,150,739,861,406,895,234,275,341,559,265,618,189,70,857,294,457,427,921,629,460,704,621,794,186,78,331,572,794,123,941,728,555,335,474,234,409,339,81,620,450,674,217,751,90,609,888,437,440,994,817,971,261,676,25,251,985,956,366,830,679,913,478,410,878,313,532,132,142,96,359,410,593,747,716,268,932,303,727,851,891,422,139,674,911,312,502,898,551,629,994,328,708,347,324,160,462,870,910,491,994,372,999,286,529,234,26,32,47,483,958,302,12,580,956,370,809,329,835,167,227,396,419,999,552,202,474,260,975,809,852,540,737,561,573,989,23,506,676,237,246,23,62,104,774,893,180,808,96,395,261,602,508,643,909,185,854,944,532,121,406,922,77,571,113,530,624,868,520,285,478,980,276,447,439,918,247,131,690,564,334,511,416,825,150,551,554,205,891,258,140,545,402,334,556,171,330,222,781,926,112,473,547,816,166,341,746,495,168,403,816,395,441,411,122,71,955,796,490,912,744,391,248,535,864,612,358,178,613,651,646,435,479,798,597,6,638,941,559,775,933,469,391,388,950,924,763,283,930,39,847,898,416,37,802,971,346,896,662,68,425,714,855,698,946,564,763,435,102,386,94,475,586,20,660,310,985,637,470,124,127,534,111,140,94,763,234,412,319,61,622,516,212,393,663,305,113,168,797,420,358,764,23,404,17,872,874,459,499,624,718,238,994,353,194,454,142,6,716,114,710,947,6,215,791,151,428,919,539,207,910,184,366,818,445,123,640,486,369,684,601,394,636,807,633,189,813,588,842,580,332,117,169,773,477,244,476,961,866,768,510,121,701,218,405,686,573,583,657,485,886,271,884,669,423,756,749,38,900,163,268,741,795,236,772,489,536,216,596,810,941,945,122,662,55,800,918,179,611,854,791,102,504,718,392,651,838,406,764,28,204,364,614,430,904,895,795,753,956,643,393,904,795,544,836,163,892,240,870,803,533,528,811,122,635,617,274,742,306,242,319,474,404,746,381,853,964,223,154,474,480,411,356,544,562,899,117,354,626,4,898,109,943,940,707,610,780,89,110,14,953,126,136,940,3,181,536,654,42,784,753,583,438,48,512,186,455,980,972,756,737,513,8,331,137,866,979,449,273,817,509,219,174,844,76,974,566,636,22,345,828,577,731,164,602,632,597,654,128,820,185,737,273,726,213,286,138,571,125,195,459,171,27,193,6,603,179,198,360,909,631,478,646,604,826,747,932,156,728,289,743,838,193,758,80,359,967,283,699,962,664,684,782,598,671,878,777,524,15,207,323,137,127,722,63,532,139,989,34,862,489,777,855,737,494,895,63,833,438,985,321,307,491,1000,369,419,280,522,496,930,923,144,496,365,130,878,812,261,709,687,766,3,777,711,382,671,344,845,529,443,211,249,699,772,577,656,417,192,514,633,244,641,121,434,429,144,357,441,273,723,201,817,535,913,910,801,296,166,188,178,237,722,895,15,954,397,24,932,191,254,391,804,905,75,194,356,594,220,600,153,194,892,540,445,220,428,159,781,930,895,176,167,189,700,670,941,488,14,760,793,628,186,736,124,356,80,109,312,978,105,623,314,596,936,856,427,896,627,125,813,585,60,133,702,921,621,532,212,849,945,631,758,263,895,989,513,203,840,726,72,272,226,539,268,557,256,870,340,461,947,165,49,298,731,970,533,253,680,816,224,690,659,596,217,874,58,410,930,272,59,142,909,247,527,78,151,766,337,805,748,708,154,408,991,996,298,908,514,973,994,107,989,630,537,958,437,409,854,564,992,421,90,945,116,585,798,514,854,774,256,151,402,104,400,677,434,884,181,35,623,708,392,797,981,671,944,571,703,630,802,539,529,313,635,315,969,182,143,404,646,542,102,929,488,507,979", +"812,948,909,439,26,552,503,207,57,932,47,875,780,880,12,804,876,921,240,499,995,877,638,553,977,140,341,216,794,69,949,276,897,0,406,545,822,554,704,814,512,285,329,674,956,121,655,534,857,147,130,932,814,413,613,609,533,574,517,993,519,46,217,328,427,435,133,32,973,925,796,521,262,915,817,572,427,768,632,986,9,979,986,351,4,264,190,12,482,571,183,857,739,527,56,326,970,857,851,762,200,813,694,950,52,199,140,882,539,825,457,959,687,168,838,505,78,651,860,995,598,567,167,307,42,810,306,720,862,97,952,543,915,349,328,260,888,448,75,824,971,592,958,582,430,383,770,18,751,115,540,947,373,96,307,40,324,99,655,68,883,489,571,954,172,58,523,476,507,247,765,617,360,750,390,580,999,220,503,944,673,521,927,883,108,658,895,336,935,994,680,386,325,247,744,880,404,736,279,931,757,677,95,139,758,125,471,719,153,411,955,886,476,712,687,240,348,753,664,919,163,903,775,804,697,603,107,962,218,140,59,109,473,528,990,515,108,188,410,911,601,722,542,256,423,259,140,355,918,41,463,354,283,634,215,675,934,700,572,571,374,382,15,29,615,839,873,873,451,515,515,747,394,334,660,601,775,21,33,691,437,111,989,314,447,361,126,660,930,782,98,341,209,266,911,589,670,163,146,714,786,541,674,607,478,411,889,774,414,81,225,473,947,316,587,191,139,512,728,112,608,201,205,716,371,448,893,117,704,411,212,199,337,741,942,10,63,613,229,445,164,317,653,137,952,697,641,955,221,760,90,678,421,426,471,996,570,502,912,16,899,404,663,509,589,684,600,975,62,465,780,881,407,864,162,8,680,639,350,961,597,694,421,100,196,561,36,928,462,345,929,670,627,787,918,246,765,792,497,951,110,712,312,276,593,616,264,7,105,844,959,106,258,184,763,869,341,793,262,912,869,817,816,801,443,909,601,538,462,42,192,64,288,941,736,266,124,523,187,905,237,254,207,278,134,83,776,666,238,476,108,940,181,651,858,330,418,882,256,491,466,401,183,178,897,885,803,772,334,154,355,42,231,463,912,600,439,411,150,565,153,76,796,807,287,65,722,403,420,204,795,296,447,948,562,238,121,461,40,726,368,828,944,256,604,438,552,296,302,690,570,927,586,202,28,798,346,962,602,177,814,935,621,123,735,108,333,269,602,887,586,4,130,454,403,260,980,7,102,398,218,323,826,295,341,980,541,378,905,532,535,877,839,849,1000,677,920,946,491,34,73,680,618,78,936,480,436,932,323,306,117,771,400,187,485,762,900,182,335,468,811,991,825,438,554,298,770,878,347,230,28,77,182,54,871,676,647,50,762,312,233,777,858,434,337,34,635,577,545,469,949,357,401,215,850,881,942,937,865,315,861,456,816,577,934,703,220,63,955,91,610,751,355,109,203,272,73,466,395,572,701,829,823,127,524,892,536,484,235,460,708,991,69,633,71,983,657,685,973,116,802,539,127,943,577,53,21,738,327,352,703,250,261,93,538,48,304,6,929,462,462,354,741,621,481,902,942,941,177,36,972,727,575,893,970,326,459,734,215,936,510,724,233,307,885,698,85,577,40,543,594,779,369,671,446,254,222,665,137,608,388,923,958,280,608,763,336,376,415,982,218,381,400,146,410,727,359,218,920,378,716,527,566,387,218,935,315,253,741,378,411,765,862,474,606,340,256,907,767,644,760,238,278,68,388,156,383,529,114,439,561,673,342,211,989,540,985,379,248,3,824,731,685,407,187,622,425,269,774,379,364,937,820,770,330,312,991,895,391,716,736,661,710,45,229,625,459,301,533,612,695,962,34,566,205,44,402,828,502,165,20,996,57,89,404,492,694,136,369,827,740,119,646,155,543,817,557,699,512,542,190,666,878,988,138,135,727,734,68,370,2,720,492,456,38,432,848,244,457,796,877,67,78,854,645,926,370,177,339,752,286,593,61,55,90,787,739,313,411,502,434,129,499,719,655,830,29,183,599,297,903,537,579,531,393,112,177,257,503,710,435,24,394,935,321,742,978,880,663,33,257,873,42,293,337,377,708,49,706,691,143,228,979,972,809,818,657,471,780,137,805,418,987,365,193,755,136,24,624,686,866,302,947,395,93,897,84,676,324,519,375,137,58,94,996,785,880,99,923,489,468,802,711,836,571,762,760,593,534,681,187,190,842,686,941,191,51,679,751,157,260,232,952,60,612,590,607,646,92,752,103,914,842,553,30,317,756,635,69,697", +"967,626,607,832,885,134,490,989,654,878,325,305,667,711,396,284,622,151,649,866,62,89,875,386,384,472,18,925,896,179,953,671,271,406,0,352,114,710,187,521,922,379,983,956,176,705,159,602,29,494,890,905,937,977,346,35,73,12,633,805,541,909,534,304,818,730,355,644,826,153,261,98,855,894,863,419,717,379,257,814,582,557,870,364,557,881,950,382,499,578,939,193,433,187,997,673,217,108,396,427,46,8,926,627,366,462,601,621,455,269,878,474,183,315,709,942,767,277,967,502,698,262,332,135,385,23,718,503,671,562,45,712,745,470,95,706,550,386,798,286,634,580,584,596,589,421,815,548,727,276,442,868,760,993,937,296,929,126,256,275,847,6,247,85,180,320,545,200,90,84,161,275,425,553,718,317,700,461,339,554,759,15,972,424,693,571,53,362,988,98,130,926,766,817,865,148,418,993,309,190,382,445,750,295,760,32,915,148,367,862,658,824,364,235,446,384,118,813,456,993,347,536,61,685,558,930,793,500,269,715,327,10,649,618,597,410,785,703,433,832,943,281,518,129,707,744,391,927,489,711,761,698,98,798,263,843,124,800,41,973,341,396,189,146,460,324,176,707,985,410,358,385,237,141,939,658,145,803,781,811,495,613,837,713,981,4,987,645,121,584,164,261,356,423,247,643,234,150,519,627,800,612,998,124,505,640,974,360,675,998,396,516,118,918,546,511,493,64,917,442,979,240,860,632,620,52,827,569,388,514,238,678,977,989,499,574,336,78,199,673,325,728,466,684,48,929,662,425,96,953,768,50,600,806,449,974,935,895,105,568,894,613,653,396,334,226,308,364,240,107,331,696,44,561,153,757,905,382,908,983,488,808,496,215,446,204,532,127,642,182,721,834,31,300,590,974,107,297,976,478,346,809,368,320,29,921,721,470,810,240,944,232,517,351,754,450,900,519,407,847,610,755,710,559,502,796,846,708,589,582,225,864,681,624,8,177,770,924,524,52,190,303,787,78,93,119,559,730,577,305,271,3,842,960,873,171,618,981,177,344,361,963,800,255,569,360,467,194,798,769,957,986,759,257,31,595,52,145,289,391,795,891,686,365,206,223,921,540,689,87,933,764,262,436,585,30,37,711,347,442,608,80,3,919,35,161,375,253,510,732,489,298,120,885,481,831,283,78,575,290,47,287,829,332,559,637,308,413,585,567,324,943,239,976,121,263,217,283,269,471,654,658,559,393,600,558,466,825,413,150,355,575,33,599,909,440,753,400,468,759,824,491,926,499,831,942,994,702,441,811,71,596,95,586,173,47,945,996,901,560,496,682,853,622,672,660,928,841,77,407,878,751,696,236,423,927,398,710,28,540,812,589,532,540,914,260,21,177,99,811,630,229,83,624,684,661,912,429,830,552,875,947,272,329,571,169,894,386,921,16,469,187,321,922,161,335,358,306,209,499,285,55,602,298,499,188,831,457,598,440,62,621,857,915,536,989,868,506,323,875,484,175,297,409,364,10,764,953,888,32,502,334,990,382,293,144,243,411,840,953,176,73,13,74,31,911,893,521,828,306,648,37,722,471,496,323,797,447,149,846,83,586,643,476,978,213,744,342,435,596,643,789,82,196,167,882,900,840,106,334,354,273,37,382,632,365,365,70,627,865,949,567,325,433,848,737,276,284,809,674,690,392,519,654,697,978,96,725,232,551,387,221,331,559,466,249,280,759,843,142,504,265,397,671,319,925,688,141,94,829,49,630,657,953,417,788,630,446,319,555,31,517,717,894,734,757,705,835,858,604,264,694,77,218,303,857,80,878,14,728,922,881,149,455,772,762,324,819,845,435,483,302,754,82,989,574,1,811,933,326,310,742,995,141,418,688,623,187,786,496,470,629,150,582,345,915,708,43,690,871,707,462,521,490,474,749,743,603,264,834,555,480,586,412,44,269,461,912,293,545,982,986,328,484,182,112,546,495,377,661,496,173,667,486,447,117,997,841,753,276,943,82,714,596,436,344,718,609,336,535,915,694,278,504,685,818,719,476,769,513,854,331,41,401,98,707,844,215,909,639,839,883,876,1000,263,137,436,112,827,798,48,304,333,103,997,263,508,134,309,853,134,569,656,70,570,584,42,910,458,253,607,201,48,332,204,342,417,958,583,40,630,417,786,221,798,286,899,553,8,695,854,554,829,41,764,287,353,725,674,751,844,234,669,671,763,100,443,843,556,66,639,242,640,844,382,898,284,968,873,260,105,699,899,381,407,947,739,102,937,938", +"40,722,679,866,289,652,891,692,14,9,816,105,911,541,149,994,439,214,478,525,168,355,168,709,286,212,418,575,829,807,345,125,659,545,352,0,310,336,656,507,41,260,375,99,406,593,307,816,240,12,690,244,765,408,961,959,699,532,274,333,241,510,709,631,550,340,107,628,666,492,999,435,386,337,618,992,376,845,652,713,979,824,679,210,388,107,151,436,977,379,701,759,568,457,440,516,479,236,520,525,221,683,254,436,348,60,833,140,116,243,943,938,773,370,564,869,318,236,340,946,633,363,712,745,39,94,701,698,464,121,611,694,872,815,948,577,110,168,382,121,790,590,779,492,871,51,506,48,218,753,295,134,349,94,682,100,707,856,993,481,498,351,245,383,326,46,522,660,303,37,222,413,70,667,818,330,349,643,400,967,963,289,201,245,748,22,177,191,699,726,296,313,526,674,299,123,133,183,321,573,301,709,258,469,762,976,309,719,195,828,762,327,783,926,230,220,474,528,833,292,546,877,742,305,86,445,870,917,75,430,796,204,165,767,745,839,513,495,204,801,823,969,666,255,978,347,578,644,951,918,584,75,702,125,561,408,916,843,515,923,773,262,683,873,162,14,29,340,835,709,59,364,850,643,463,66,584,612,37,496,687,319,736,337,87,656,262,376,186,64,708,836,877,501,101,36,980,733,606,332,140,457,484,998,182,716,479,279,719,751,548,869,911,886,72,497,764,572,907,124,971,598,352,309,1,638,190,449,534,81,9,506,810,628,304,816,563,957,424,408,691,302,990,253,950,167,122,302,487,797,307,634,310,558,64,621,113,664,804,348,518,842,327,119,226,971,623,173,11,423,61,428,402,15,546,569,780,232,425,465,387,2,459,88,943,291,774,639,914,785,659,465,519,393,763,641,893,447,73,615,484,922,41,962,48,447,918,786,928,451,630,483,387,285,280,76,319,769,902,47,631,969,35,68,894,669,527,248,281,199,251,344,457,65,439,888,801,478,293,622,447,929,855,54,440,136,573,551,512,121,319,114,682,131,84,880,872,85,623,859,882,929,135,394,333,397,963,370,311,254,271,885,520,301,240,697,162,920,105,14,113,25,345,466,803,571,931,104,202,946,168,940,466,648,199,6,878,887,219,433,242,693,131,938,278,511,661,246,642,527,296,886,414,44,649,562,614,652,291,583,792,61,960,102,516,947,991,161,560,858,923,219,118,641,852,753,808,303,272,836,830,479,769,557,331,832,256,255,228,668,871,417,370,441,161,32,892,672,294,746,106,524,246,578,783,511,699,267,596,914,227,977,995,513,464,540,274,595,482,685,697,873,89,742,490,511,663,347,110,659,108,99,536,757,180,876,245,310,696,405,359,871,853,994,737,650,431,243,903,964,273,22,505,114,314,676,247,761,759,372,58,511,302,895,104,814,50,435,781,30,831,824,930,716,762,462,358,755,29,420,411,884,573,921,914,813,408,647,646,687,834,968,110,531,46,668,810,866,234,190,602,633,287,437,347,958,183,776,464,914,928,931,772,932,339,822,865,206,633,828,895,7,57,957,203,321,944,720,362,974,381,199,34,825,75,854,792,153,103,827,151,544,580,395,777,3,245,723,911,935,540,219,956,610,264,410,607,253,896,534,64,456,533,112,823,833,423,779,136,593,385,794,855,464,697,626,268,814,595,500,594,40,189,182,813,239,928,684,490,896,128,287,16,233,858,298,532,824,88,252,142,327,132,959,220,758,649,68,480,953,87,846,589,399,430,76,785,223,305,893,44,840,324,399,742,891,256,424,384,225,136,936,763,166,746,705,222,258,406,884,729,486,177,78,622,282,96,605,440,597,961,959,625,706,963,969,827,488,450,701,882,807,782,242,876,277,521,443,395,814,293,419,936,599,5,283,112,2,937,131,544,34,304,318,873,633,107,664,107,977,294,604,751,987,520,906,767,631,520,744,494,753,187,645,934,553,777,872,850,314,264,188,214,466,967,22,9,303,24,369,671,229,255,250,558,306,953,913,75,59,843,523,374,902,739,414,547,597,529,646,370,432,743,805,973,796,224,527,343,621,573,498,975,660,204,194,245,854,974,44,633,380,834,395,655,90,854,307,94,758,246,17,790,630,137,552,487,653,763,929,29,172,482,986,318,224,503,942,580,444,827,369,17,186,373,839,57,954,200,157,377,554,730,795,770,981,128,861,839,917,493,952,295,87,611,880,951,50,908,162,989,851,474,304,986,525,211,353,128,824,599,220,164,802,441,142,826,696,229,476", +"229,167,461,244,859,299,805,965,815,187,178,785,951,122,785,373,257,109,379,447,179,338,304,481,345,167,53,165,523,425,971,556,573,822,114,310,0,153,876,804,859,472,364,502,573,351,181,496,790,304,743,367,765,359,16,450,964,328,948,617,440,43,730,703,481,131,94,972,304,414,269,165,66,350,577,165,199,649,204,865,998,953,996,244,239,866,203,723,649,281,749,77,990,905,16,751,620,756,142,673,532,525,582,944,376,463,88,253,161,507,87,681,920,83,256,359,904,330,606,681,744,702,713,805,780,289,988,740,714,88,928,493,668,600,672,907,841,819,521,40,941,558,137,9,327,309,302,913,697,22,793,154,909,879,341,581,955,732,584,8,420,183,193,955,391,79,970,229,928,217,238,856,491,154,195,193,128,842,303,353,94,104,138,267,313,59,702,604,372,487,231,663,525,258,305,723,824,215,248,630,949,831,315,331,65,978,568,978,626,526,935,662,790,843,547,708,607,714,685,983,651,374,258,903,620,565,614,43,408,616,60,201,510,826,23,832,710,36,916,465,853,24,623,646,481,191,343,584,782,737,37,992,12,427,905,986,865,737,268,717,245,712,221,51,907,687,40,541,679,464,242,719,89,992,881,300,474,717,492,73,601,136,122,261,203,267,445,708,866,339,807,906,956,674,721,244,510,400,535,668,949,24,499,274,325,573,112,511,733,10,496,403,661,223,363,519,84,579,785,889,362,948,130,493,443,155,863,116,966,870,620,533,914,414,989,670,149,404,44,923,966,365,645,337,161,741,79,642,227,918,879,816,210,804,360,986,177,222,746,740,587,989,21,610,344,127,476,9,586,892,830,689,866,25,972,822,15,193,366,829,85,666,102,160,8,833,792,834,503,912,35,650,764,380,44,714,831,428,94,956,759,35,270,509,112,347,174,799,930,62,963,558,790,299,654,955,715,521,196,924,822,245,220,538,171,76,567,917,745,305,202,999,414,830,723,906,477,34,256,674,880,813,403,780,280,315,45,946,498,696,882,50,969,282,608,339,501,875,805,108,584,241,446,249,448,744,985,335,303,997,173,520,10,881,488,16,297,88,665,628,720,850,983,505,753,952,501,602,364,564,26,84,576,301,786,361,68,561,850,416,56,719,990,101,697,699,248,45,681,575,314,405,478,365,291,969,748,374,217,260,343,198,768,905,960,29,283,866,863,137,860,501,839,585,125,170,46,277,209,346,128,234,357,355,24,451,908,182,508,877,430,195,96,368,373,279,614,260,326,192,551,61,933,128,670,546,646,742,320,410,70,555,689,298,769,237,703,608,585,923,899,282,924,853,677,978,938,110,726,677,329,913,466,878,884,698,86,862,962,254,846,92,542,600,95,463,516,373,140,103,385,258,226,932,384,195,343,499,127,465,705,152,511,758,395,360,437,39,426,89,53,368,419,914,826,149,695,727,206,681,568,163,891,798,167,723,205,130,769,321,437,985,527,289,450,496,556,567,973,540,545,244,559,182,390,357,130,668,905,546,792,68,105,912,88,854,256,46,336,826,320,219,765,28,502,260,446,518,430,156,721,169,291,384,564,423,386,885,591,98,542,692,618,880,400,777,885,59,589,624,626,621,517,63,547,424,523,493,608,676,584,181,623,675,722,525,238,629,649,968,860,647,926,333,659,78,41,878,497,966,869,301,28,483,801,869,160,724,411,411,351,575,388,232,60,342,818,362,742,102,387,855,712,306,944,486,887,735,696,318,691,258,614,269,133,706,65,652,693,438,44,232,30,483,492,979,954,837,915,112,349,97,447,500,371,403,800,123,505,258,437,330,79,207,297,91,430,452,651,708,274,821,780,673,499,159,309,701,394,998,877,743,333,852,765,710,502,450,193,875,629,731,475,633,284,514,690,295,273,344,921,818,935,689,419,391,468,785,80,530,376,194,259,224,298,555,355,473,961,306,987,200,639,443,812,481,685,293,794,253,41,163,481,6,166,419,654,298,939,808,637,12,403,853,405,438,838,950,654,243,870,925,901,897,619,436,303,112,897,420,109,217,404,639,306,202,801,835,942,369,507,105,676,335,356,510,879,217,951,63,947,550,939,551,224,440,209,44,853,96,243,58,960,162,249,458,506,453,787,511,667,145,666,41,484,712,389,925,415,988,545,403,320,95,477,383,345,127,614,921,69,173,419,538,947,278,877,618,2,98,358,384,641,81,27,663,47,522,773,995,976,190,777,264,655,748,424,83,88,690,645,31,60,872,996,250,984,757,512,835", +"33,27,628,950,190,852,551,677,500,198,620,232,198,654,594,134,847,947,779,991,42,517,548,436,139,781,305,974,476,846,962,179,383,554,710,336,153,0,636,824,690,230,321,896,269,479,951,740,713,401,891,908,530,467,603,945,713,693,486,424,981,809,67,431,167,780,782,171,630,686,553,631,529,221,534,823,274,171,891,556,815,211,629,863,411,924,11,314,622,566,267,49,538,922,572,198,25,996,101,4,709,793,475,259,993,442,605,516,305,513,77,733,808,155,501,836,573,553,460,908,702,707,778,893,600,15,228,458,223,735,211,401,958,285,322,850,236,91,809,63,12,129,170,51,416,486,27,919,494,798,244,93,879,520,994,997,507,324,867,274,897,852,965,614,129,719,958,315,57,675,583,153,511,70,350,320,730,965,498,993,232,544,915,394,226,323,943,210,974,650,309,539,615,992,825,645,251,49,769,381,678,640,927,612,933,908,489,341,153,435,877,349,573,388,530,125,784,871,603,334,853,195,440,692,68,268,496,947,373,907,826,270,771,292,219,935,158,992,418,345,42,884,1,331,944,318,903,757,249,797,847,74,408,107,397,120,151,254,307,418,832,407,533,549,560,418,525,393,280,101,842,108,366,91,974,265,982,857,234,926,560,188,850,770,777,827,609,240,25,740,167,622,655,658,241,419,147,441,83,229,352,645,83,919,474,696,668,278,882,662,475,123,326,151,595,620,305,241,322,4,917,295,791,105,674,189,971,434,930,896,850,358,927,934,105,218,673,794,874,580,507,211,284,759,737,241,86,482,99,505,816,212,143,949,549,42,611,385,303,779,930,105,329,376,98,29,258,248,600,901,109,510,351,601,313,49,874,910,39,881,576,475,451,130,314,923,657,839,580,286,516,329,688,352,606,10,358,913,564,463,574,154,977,833,977,973,255,786,425,946,432,169,782,678,383,177,868,988,270,776,486,848,110,79,279,221,83,848,590,3,546,972,871,697,387,190,819,684,864,867,15,161,927,222,973,851,618,170,822,343,784,44,664,491,418,37,207,932,881,812,274,727,735,600,288,708,606,387,200,244,484,923,732,80,613,176,458,50,278,198,209,949,966,534,198,21,849,161,343,474,373,807,225,685,310,117,701,77,950,555,973,990,639,185,490,990,886,377,228,255,489,42,709,648,267,39,706,265,988,788,791,149,613,690,224,701,954,22,795,443,741,369,188,978,576,577,433,906,848,81,226,19,564,38,9,726,881,152,201,219,187,337,250,854,948,990,181,622,753,756,267,603,892,731,658,875,259,629,757,78,873,97,37,817,938,718,840,464,638,666,772,299,650,349,282,743,808,130,236,472,881,973,130,565,232,887,452,667,389,980,84,799,406,183,297,444,380,404,141,330,268,379,374,963,204,58,486,292,337,530,748,737,44,812,65,849,196,233,107,810,690,35,855,921,951,821,483,893,768,187,350,985,52,657,507,274,686,955,823,903,883,63,234,398,43,281,819,756,992,353,263,36,599,155,646,865,452,797,680,561,649,500,318,667,269,513,742,963,729,852,169,385,398,120,595,408,619,471,301,862,846,900,930,242,574,216,425,110,112,144,851,180,377,300,132,595,497,955,758,991,164,649,354,869,309,461,629,743,652,35,22,75,809,199,307,298,386,479,265,511,911,890,393,857,991,155,770,405,690,842,49,599,339,674,805,810,716,621,329,974,130,257,598,807,857,629,835,118,972,277,654,904,497,707,377,434,844,886,548,495,352,754,990,567,696,267,522,254,874,612,228,775,364,101,213,241,799,938,284,669,922,988,361,992,469,342,435,515,394,795,508,599,740,924,437,601,4,407,468,304,399,650,889,228,325,44,917,416,690,652,761,400,502,801,797,140,582,799,153,679,664,38,260,597,595,664,947,784,830,323,929,35,112,992,527,265,640,944,926,118,317,662,333,40,953,731,833,273,834,872,927,465,908,668,611,310,461,274,36,509,701,36,381,76,945,605,813,924,170,923,52,767,773,893,700,730,156,401,439,581,874,871,579,894,857,9,739,980,757,543,811,348,389,291,730,999,767,201,872,857,469,307,773,111,556,999,128,667,208,543,319,602,266,312,103,294,759,721,936,940,495,214,258,531,221,2,179,460,949,512,599,539,790,487,635,770,650,92,512,655,754,228,441,728,259,468,105,447,432,674,171,267,686,745,947,541,615,411,306,251,506,798,165,817,302,145,652,351,260,790,493,261,774,830,60,787,359,121,885,237,91,440,95,355,215,188,750,537,763,349", +"112,396,781,993,731,156,77,716,464,621,786,574,340,833,312,567,921,617,978,102,224,755,176,99,774,718,301,995,567,564,839,628,611,704,187,656,876,636,0,634,880,367,291,800,380,358,7,279,299,800,601,318,951,884,884,930,921,2,719,23,701,861,760,289,366,519,158,114,203,857,217,823,727,126,677,667,568,882,584,996,892,952,870,490,564,739,891,50,532,857,342,273,13,282,684,878,505,999,515,939,392,996,894,603,942,959,141,716,709,821,324,813,409,745,552,623,742,854,256,787,946,953,811,33,260,577,802,76,176,417,725,730,148,393,776,273,776,773,177,610,671,35,338,150,725,834,274,600,583,59,274,801,337,696,65,755,931,548,808,266,345,654,507,723,479,467,222,179,227,619,442,22,728,918,31,479,524,902,26,987,938,346,4,855,911,287,35,147,787,89,348,107,810,944,750,898,106,996,347,652,43,378,825,968,484,7,720,551,635,356,768,298,564,212,122,442,221,349,99,539,146,830,766,352,131,394,547,387,885,885,976,694,59,898,823,39,786,396,81,217,511,149,64,674,959,934,459,354,510,399,98,571,984,342,902,443,541,65,240,253,367,778,432,880,468,561,626,309,423,12,420,643,860,885,414,364,649,151,827,477,129,41,359,957,177,485,390,134,890,966,33,219,317,609,924,208,952,34,150,438,479,711,698,22,383,202,523,946,900,583,17,492,511,500,413,983,739,188,665,438,223,228,724,288,632,960,732,626,379,392,514,114,895,574,15,785,373,489,592,802,821,351,914,592,894,67,429,260,989,846,956,750,138,327,39,756,643,153,316,118,617,54,524,676,88,912,741,884,340,288,406,695,728,500,259,85,586,755,261,408,250,248,268,915,37,592,510,201,432,790,629,823,67,594,109,316,71,675,558,522,693,200,591,750,748,211,678,625,291,819,892,797,304,444,433,699,911,311,905,934,285,522,543,33,447,785,204,490,757,59,9,848,631,997,673,431,929,197,453,554,16,845,156,885,490,915,233,310,207,709,536,635,64,620,763,28,243,433,609,159,839,903,403,246,122,387,368,481,4,185,535,625,827,837,232,886,591,948,547,671,348,779,442,431,423,349,215,311,182,896,523,460,422,874,523,139,19,322,585,917,229,236,149,413,996,42,468,610,665,188,238,395,152,61,97,608,945,291,31,781,322,598,146,748,585,219,225,107,464,251,79,5,711,819,411,893,762,885,177,334,545,982,416,71,822,673,450,618,462,399,944,884,373,129,248,385,986,786,191,330,398,298,495,811,908,116,852,167,859,439,736,234,936,457,719,515,208,291,194,666,236,800,656,440,535,817,167,33,463,506,929,550,765,984,307,320,677,307,630,469,404,240,844,308,522,408,371,870,669,629,580,948,134,348,992,312,556,140,420,153,405,540,266,643,486,612,617,496,50,959,232,485,414,371,773,696,998,160,512,846,358,450,705,691,55,899,999,97,395,197,779,293,213,970,715,669,928,721,563,6,107,535,823,782,375,486,582,328,365,117,289,822,861,12,589,750,524,234,670,541,136,509,700,375,441,622,508,146,106,828,502,670,246,569,203,571,238,902,148,211,514,328,359,798,733,993,427,7,97,252,706,129,753,633,510,257,742,183,436,927,398,364,605,96,722,121,676,440,147,364,381,81,423,406,797,514,441,168,51,667,173,711,945,113,425,599,915,959,329,972,399,643,112,709,204,783,833,297,564,533,37,980,448,157,490,442,209,86,751,806,879,222,680,107,192,837,729,121,584,84,444,41,439,236,206,506,560,452,41,27,687,754,637,659,261,886,144,246,945,636,62,138,930,588,528,153,58,674,97,187,648,646,856,555,669,269,158,933,451,249,872,973,648,403,783,406,698,582,36,909,696,569,450,682,194,977,447,445,445,501,681,922,117,99,648,855,664,767,859,583,251,192,960,427,629,911,805,257,184,428,558,78,404,172,913,981,722,357,859,668,582,608,784,704,327,492,428,484,982,646,356,367,117,922,985,52,784,468,540,250,245,359,616,727,350,647,152,711,498,416,328,491,275,719,281,556,222,805,994,123,320,534,772,839,914,570,403,371,81,340,242,856,707,569,71,46,396,556,251,619,544,251,265,516,754,751,507,665,154,297,115,407,749,671,814,859,885,220,468,294,657,268,847,175,172,388,305,161,352,190,707,422,369,324,824,505,301,175,303,679,816,225,141,718,479,392,887,723,773,920,516,553,916,379,334,157,847,783,198,322,847,250,318,779,257,342,915,995,985,915", +"913,183,698,821,963,676,475,680,742,731,202,24,54,38,273,694,91,842,288,120,832,736,848,42,3,147,718,391,959,334,732,311,885,814,521,507,804,824,634,0,825,126,977,599,271,612,352,534,649,208,203,99,308,108,1,202,765,370,611,451,992,42,846,387,568,305,771,189,985,806,458,44,833,585,442,455,143,507,274,717,127,365,655,510,463,481,928,350,52,800,134,649,619,981,365,151,906,251,184,675,609,74,208,997,359,620,706,473,770,871,918,164,952,170,969,549,341,1,695,160,119,462,297,646,396,812,944,339,6,665,240,906,994,598,714,433,448,652,864,113,383,317,977,628,332,611,740,167,875,997,60,217,332,319,501,609,557,665,68,53,600,486,656,772,336,431,27,552,865,545,106,766,862,266,806,575,285,560,899,512,614,280,499,888,820,875,224,866,540,461,815,613,391,678,88,782,656,607,300,996,520,831,400,749,815,615,93,382,778,406,231,761,30,582,168,732,608,655,539,264,286,42,645,706,207,58,506,606,177,501,176,421,539,636,35,968,200,91,27,890,359,658,974,842,33,910,526,122,487,237,501,742,576,322,503,444,165,695,466,683,473,104,920,30,265,624,864,135,181,248,141,170,962,10,85,5,531,850,301,200,296,590,358,713,898,103,844,66,519,272,229,948,315,943,39,13,602,338,14,919,208,52,311,653,622,71,392,939,593,889,826,197,89,746,125,365,958,4,252,362,627,158,363,263,399,776,951,324,775,212,427,480,528,584,79,338,425,874,430,342,861,441,731,87,886,421,254,77,631,331,535,364,285,598,120,612,782,593,834,29,287,71,255,345,973,98,15,82,4,963,931,818,616,960,441,303,642,211,91,77,320,862,975,238,397,47,422,735,51,489,170,340,623,94,652,683,901,414,244,196,292,611,735,939,365,474,677,730,108,639,944,833,101,916,326,754,777,431,61,223,337,91,66,553,123,325,7,603,143,434,378,740,668,780,347,680,845,451,193,517,743,716,105,129,321,88,411,666,622,516,927,196,441,735,660,169,96,792,898,118,53,479,778,872,178,641,577,525,846,293,37,19,351,7,229,390,397,857,898,210,184,272,551,792,276,288,578,913,392,608,320,978,695,44,130,283,524,844,415,30,500,781,137,973,422,338,36,406,597,48,61,925,839,641,108,198,271,578,863,40,135,222,962,807,500,544,390,40,391,303,620,129,459,516,879,752,776,647,932,764,254,918,709,190,241,827,818,366,170,847,20,26,831,820,351,116,143,459,645,824,562,229,301,194,746,14,236,380,892,395,785,622,200,19,260,970,841,482,389,767,576,318,396,421,31,31,44,913,882,331,742,856,208,466,456,818,14,873,371,319,348,421,398,13,235,330,402,561,237,608,332,385,342,557,693,517,287,377,79,208,236,6,811,282,893,427,297,309,292,552,986,373,450,81,88,755,520,21,208,914,617,550,517,907,830,79,529,386,768,739,999,214,905,576,351,863,234,616,952,925,91,356,656,131,194,848,243,828,175,772,786,528,82,576,959,588,325,740,986,516,381,373,702,551,60,167,20,279,483,245,219,103,865,950,584,914,118,481,210,664,151,158,538,986,920,462,201,496,638,306,806,638,950,826,690,489,283,569,662,81,555,571,45,244,245,208,958,111,802,80,415,476,535,585,637,767,41,595,837,799,931,997,304,693,687,802,671,33,963,768,610,228,932,762,727,844,285,731,449,470,578,644,799,133,300,159,767,954,540,446,970,902,349,185,615,362,43,635,150,266,398,405,371,669,192,50,841,27,25,45,301,361,216,335,58,712,768,722,253,116,346,217,523,500,702,808,991,13,110,740,440,991,448,584,173,437,533,180,951,695,266,494,740,393,637,437,898,117,778,779,363,635,720,222,817,637,63,315,583,245,925,549,294,765,884,768,983,854,170,119,292,915,505,158,792,725,178,581,895,915,534,393,971,922,229,612,307,634,859,619,37,11,955,6,663,288,879,560,137,570,82,605,103,781,648,202,869,124,139,916,811,556,553,297,344,387,85,998,581,821,440,952,885,110,188,661,388,650,197,453,999,515,145,507,765,815,832,248,128,192,668,126,210,737,217,211,544,382,568,409,502,162,16,184,248,822,343,19,620,625,828,298,599,35,813,55,435,579,369,89,438,845,578,643,217,522,991,335,987,80,9,979,415,565,531,201,336,98,870,809,810,234,619,95,197,308,731,204,17,367,260,903,317,302,318,912,792,338,801,523,585,388,179,511,281,220,154,887,587,966", +"548,396,361,818,186,904,499,907,842,396,218,310,504,195,841,759,385,393,265,116,281,371,393,651,896,197,621,559,492,148,325,665,405,512,922,41,859,690,880,825,0,208,684,473,706,130,446,885,211,143,367,99,258,196,77,706,32,895,875,793,422,661,77,655,499,786,700,126,53,775,324,233,156,651,39,229,893,487,98,771,439,972,401,737,425,70,901,151,837,763,490,232,140,518,706,934,198,959,106,367,958,414,627,484,431,462,407,368,129,251,454,698,627,101,420,364,350,759,154,443,210,805,254,580,759,791,370,965,916,684,499,760,120,584,852,104,556,536,995,770,834,303,239,335,915,776,781,703,436,557,48,252,480,451,388,290,354,259,936,47,347,750,858,901,702,412,187,114,433,472,868,402,445,154,769,95,858,683,342,779,77,797,641,377,304,634,237,610,235,262,500,581,253,592,167,122,347,834,892,499,342,628,922,211,673,46,837,822,877,873,748,556,314,713,762,27,949,253,468,502,269,4,172,641,497,365,168,648,778,637,53,884,157,618,477,555,641,500,160,745,798,892,289,862,659,244,34,127,545,346,116,761,826,202,478,521,174,217,732,267,988,502,509,703,586,23,333,889,666,321,590,210,910,505,274,283,271,236,96,383,881,293,798,889,703,96,779,575,309,23,938,756,586,604,634,613,379,21,248,676,642,40,275,392,110,270,266,415,270,204,496,995,427,357,598,855,556,395,561,897,330,305,939,598,56,559,916,737,484,620,937,229,74,827,35,789,581,358,252,947,154,96,924,965,563,968,900,938,774,56,892,960,807,262,663,172,888,922,835,834,879,92,415,309,290,862,464,525,232,804,893,755,320,442,496,979,576,982,591,856,537,185,70,584,812,282,510,389,663,46,289,583,851,181,804,999,988,833,975,337,755,660,62,17,569,741,710,158,969,863,979,315,701,351,296,446,569,475,652,49,738,275,709,181,849,306,608,561,106,315,317,734,306,891,530,629,16,531,139,677,932,640,295,527,504,180,579,823,552,797,640,771,42,432,829,855,569,432,988,8,924,538,801,243,198,262,632,714,824,679,898,166,705,380,664,134,959,224,577,157,428,453,468,96,801,192,409,321,334,55,247,134,618,180,603,503,960,394,165,574,207,133,504,76,983,851,819,904,221,728,187,297,979,662,460,86,693,114,205,284,300,401,72,222,357,101,265,527,715,388,354,462,268,485,875,650,101,224,406,467,708,947,874,932,630,81,126,217,764,44,965,138,506,717,862,967,172,390,485,244,743,134,931,241,639,300,164,580,92,412,187,562,509,790,628,716,276,323,807,270,624,547,419,361,498,177,224,54,662,827,504,81,462,12,449,292,959,991,253,865,877,898,162,886,214,966,641,902,828,446,419,895,480,255,793,620,490,682,149,750,874,412,967,200,797,824,631,406,182,202,135,478,378,770,661,229,847,448,95,818,398,889,496,67,520,163,352,230,157,492,302,440,256,204,564,794,755,650,548,580,532,128,194,408,924,710,830,721,914,897,884,389,573,772,335,15,790,597,935,894,592,404,582,471,201,786,918,951,647,217,91,344,717,640,820,193,48,801,172,885,928,973,739,963,365,828,81,484,888,322,359,331,544,95,847,274,369,668,853,373,306,622,514,313,235,202,468,821,954,935,813,420,190,890,159,191,254,706,415,987,587,578,402,944,428,926,993,863,81,603,746,269,723,697,278,697,114,57,353,629,273,993,456,103,696,987,843,893,650,731,460,900,180,670,665,465,359,233,895,22,248,237,226,101,612,884,424,611,610,216,534,108,92,506,567,321,912,668,543,307,510,334,685,63,182,563,245,930,169,230,649,381,796,56,814,832,468,196,519,923,578,541,98,68,233,441,864,87,807,219,440,673,369,582,356,733,732,869,776,92,859,461,870,105,143,958,775,82,592,634,820,617,303,437,492,40,122,166,517,95,964,381,727,216,333,496,934,979,962,880,604,78,969,368,201,352,654,604,232,719,151,352,62,508,795,333,775,590,875,93,89,584,417,556,186,391,502,208,101,88,619,557,87,413,52,542,991,352,91,746,302,562,92,264,588,507,924,148,360,836,931,64,844,90,668,406,779,7,892,828,103,529,335,90,593,941,448,200,406,550,885,788,105,887,943,990,833,868,898,141,293,759,470,508,289,698,248,754,756,867,526,550,308,263,858,648,475,593,111,662,420,719,298,482,300,233,750,110,309,433,769,527,819,727,826,754,540,50,888,21,935,369,617,137,359,14,45,687,111,543", +"902,822,121,906,586,251,367,936,641,65,529,982,549,850,941,761,914,142,48,344,356,820,716,318,861,993,641,338,596,810,290,594,848,285,379,260,472,230,367,126,208,0,641,88,268,757,539,283,405,356,594,265,179,605,753,735,959,145,736,685,678,902,215,835,136,218,592,401,512,660,310,625,936,828,67,433,37,868,126,352,51,923,546,496,508,709,892,44,666,464,693,191,79,536,635,232,248,99,996,562,90,971,393,687,743,951,744,70,989,380,456,44,219,607,604,7,362,876,613,569,155,380,962,718,84,406,524,90,82,832,16,679,527,474,46,422,122,735,105,411,810,444,357,720,536,495,546,589,468,965,937,975,150,609,880,862,813,554,642,556,693,362,889,247,961,61,195,6,895,414,687,987,847,627,323,243,986,523,495,36,515,480,256,490,731,879,192,813,356,780,266,472,345,339,742,463,639,232,418,656,991,99,735,228,384,443,668,337,33,842,437,319,535,264,930,119,61,395,576,639,403,58,632,873,865,112,499,835,491,314,629,246,74,315,464,540,832,907,515,58,561,790,423,855,127,717,71,408,410,144,14,464,73,191,728,570,883,699,746,116,177,647,121,611,326,743,94,933,207,216,860,295,748,556,305,673,961,952,913,697,491,397,376,702,256,13,788,386,467,299,699,794,796,964,361,597,763,173,105,757,802,42,773,968,619,796,485,291,259,26,106,53,289,585,811,219,968,572,22,275,873,128,57,739,201,995,176,752,863,354,981,954,188,488,144,303,599,328,128,192,194,149,920,741,864,414,829,384,535,149,112,790,466,975,898,855,179,785,150,412,84,461,96,960,682,936,278,326,932,561,136,628,823,898,354,564,399,693,678,512,509,992,105,250,78,375,811,706,200,69,968,49,559,731,110,526,472,824,38,596,103,933,219,648,321,415,95,210,303,552,215,991,562,775,991,722,998,361,902,495,539,766,798,754,986,556,715,911,88,953,981,769,487,993,44,315,765,701,478,819,595,114,568,874,485,460,646,646,736,920,528,84,867,598,775,950,389,936,565,891,382,799,217,27,248,521,254,144,88,586,544,609,552,938,205,97,579,796,158,576,967,68,611,64,938,769,658,410,187,28,156,573,746,346,42,343,800,597,94,998,347,573,56,121,283,795,212,25,581,678,179,858,362,168,504,503,127,643,329,791,743,749,417,609,59,694,637,365,973,685,509,24,929,890,335,472,775,455,721,908,530,438,27,120,603,397,528,615,848,576,752,353,145,41,201,754,366,233,190,133,704,154,839,993,81,670,918,152,955,464,108,32,60,243,793,608,162,377,238,957,7,986,286,862,280,791,146,670,857,569,525,780,753,772,117,575,576,398,429,34,661,756,890,90,540,922,132,731,181,142,688,884,225,254,106,215,718,257,403,710,210,206,182,140,422,626,937,465,273,127,136,816,717,648,662,650,284,30,410,689,147,714,914,775,347,855,130,141,684,149,56,808,930,24,19,745,409,625,326,335,779,522,144,554,405,551,454,698,408,79,654,73,317,478,519,829,887,441,670,212,24,157,969,20,993,29,690,553,664,989,634,360,547,500,373,860,616,734,949,944,717,64,977,642,616,119,449,655,490,619,396,737,585,304,446,45,489,644,595,785,712,854,661,428,625,218,540,891,252,988,244,76,563,391,456,582,644,25,626,858,392,253,759,512,258,333,590,279,507,427,830,883,10,138,779,917,441,412,809,611,601,720,401,84,525,994,54,977,709,347,701,765,765,217,798,331,895,585,877,818,663,727,719,386,367,913,2,326,50,682,167,404,226,723,95,760,504,935,632,663,733,768,531,392,274,490,377,217,76,385,559,789,673,377,957,517,866,544,749,783,215,36,163,14,508,374,519,932,866,181,294,752,121,143,348,546,135,536,320,669,141,986,947,587,886,959,213,41,180,585,959,239,413,424,293,509,825,886,66,312,580,621,963,737,992,814,521,297,169,451,892,156,581,694,527,714,307,341,344,120,486,623,298,687,809,488,66,413,295,109,889,545,624,199,40,59,12,243,884,681,786,649,804,565,470,130,94,611,746,558,885,40,365,655,471,755,518,466,489,27,766,529,912,139,560,603,663,380,568,23,589,470,52,934,597,19,785,693,706,603,812,986,104,713,600,912,328,52,46,960,55,967,143,802,530,591,613,369,584,115,651,887,600,677,655,705,823,414,643,758,369,530,975,451,665,298,232,592,216,707,451,754,634,224,302,356,205,159,665,688,517,235,805,526,420,151,476,415,224,921", +"793,81,216,58,52,841,648,958,923,529,921,609,491,264,480,88,469,840,517,457,885,301,954,186,342,337,566,861,239,112,11,340,699,329,983,375,364,321,291,977,684,641,0,438,867,729,43,24,58,214,419,195,449,860,328,109,866,403,359,786,574,682,838,848,727,170,867,525,171,636,152,930,705,571,804,990,447,128,857,950,239,389,956,670,67,640,751,59,810,1000,851,592,670,790,230,549,991,369,500,465,173,35,596,698,308,651,823,119,288,453,856,318,902,452,726,929,920,15,6,886,947,37,423,766,88,400,867,422,458,686,588,502,536,635,927,12,252,241,448,926,884,965,307,455,197,511,132,303,647,83,686,152,979,611,650,642,609,75,834,721,980,235,694,456,901,677,505,281,109,478,337,629,322,600,4,364,117,989,904,902,532,790,490,441,876,128,761,219,220,214,636,560,410,288,828,733,576,928,454,107,106,424,160,158,355,273,835,850,824,852,53,4,701,166,777,119,801,238,284,687,345,309,125,643,413,320,278,208,20,165,356,221,339,812,817,525,439,265,795,646,172,696,572,108,177,557,317,428,310,509,232,672,3,349,767,589,829,671,994,453,876,312,481,565,270,28,863,710,861,779,944,106,322,853,120,648,675,346,779,179,388,934,904,754,499,527,603,775,644,335,934,937,726,68,723,156,794,32,388,63,458,300,228,720,566,979,770,351,696,292,589,104,136,10,843,833,118,679,32,212,789,501,326,374,934,678,84,943,38,311,59,190,78,224,544,179,984,988,625,953,31,987,876,239,244,111,103,281,858,659,426,331,234,693,218,873,341,559,913,494,923,213,280,241,636,308,693,417,653,837,685,18,16,723,623,74,891,62,614,630,300,735,638,883,917,144,515,948,643,730,535,790,308,632,114,897,148,355,198,476,148,445,483,273,693,331,486,615,490,508,607,254,260,930,169,462,545,711,889,291,244,104,790,824,38,663,464,676,3,91,93,263,263,895,335,960,35,326,877,98,494,574,801,713,285,332,652,723,774,525,275,310,23,322,346,194,41,635,190,968,597,10,132,406,116,220,845,217,729,181,825,315,937,518,539,130,436,38,583,428,430,173,865,208,967,169,321,814,262,266,33,667,89,934,864,29,870,801,96,197,407,577,919,865,455,185,864,747,434,923,155,642,153,614,316,925,266,626,12,600,644,441,198,37,268,662,779,618,537,110,77,297,889,830,980,191,263,42,498,21,120,148,273,316,427,725,830,937,127,241,966,96,153,509,951,171,268,188,386,223,150,318,747,838,638,790,164,560,476,69,121,756,53,385,207,830,533,250,992,478,210,947,516,808,392,911,139,911,157,972,274,191,185,265,387,182,151,531,290,424,700,116,410,162,42,622,557,979,74,705,891,791,978,108,728,145,795,389,602,21,748,25,410,306,600,419,919,445,905,900,526,100,606,970,860,918,709,928,105,526,138,361,181,843,11,927,22,26,972,326,268,10,34,262,963,173,312,422,521,477,888,787,973,265,382,519,820,656,765,353,214,91,983,739,990,520,55,543,829,418,323,677,96,516,856,46,416,335,881,911,814,247,82,128,110,704,954,43,846,709,228,792,227,337,373,756,7,605,311,622,649,863,789,131,756,500,988,26,985,944,154,344,94,586,917,522,588,498,791,928,550,664,354,345,668,734,718,176,800,233,610,313,777,332,358,650,109,609,257,607,48,557,520,54,85,153,345,170,350,908,304,874,699,849,929,223,998,896,725,101,392,887,661,737,740,391,764,190,75,266,720,258,916,395,634,347,403,504,297,517,939,569,244,813,655,831,303,81,496,202,320,522,131,242,57,919,885,56,231,693,565,974,852,603,87,573,419,750,797,624,421,364,301,530,120,729,804,787,836,417,535,278,346,445,222,613,864,784,309,403,439,986,643,854,944,2,522,274,717,834,215,821,936,860,553,845,606,556,891,167,10,208,924,153,839,346,884,361,201,476,271,37,992,942,918,140,895,502,306,137,983,527,553,639,672,515,628,652,903,63,896,150,313,620,603,616,312,289,343,840,986,399,161,615,795,640,821,985,465,232,397,698,544,350,426,972,644,3,850,506,293,60,684,21,463,598,217,782,640,138,295,387,690,209,81,937,321,706,556,54,824,220,838,328,432,910,628,164,98,986,239,110,1,386,501,829,622,722,195,955,9,154,776,111,819,857,395,766,976,655,25,224,83,735,689,461,587,180,840,197,636,537,653,361,796,225,415,27,427,97,866,650,824,478,142,20,675,715,595,590", +"563,117,819,492,700,175,899,437,117,612,751,630,280,354,554,361,58,240,758,957,459,912,364,953,433,764,324,311,16,360,445,115,379,674,956,99,502,896,800,599,473,88,438,0,752,566,320,297,213,597,810,563,743,121,71,497,4,551,788,167,73,421,90,402,435,989,509,423,285,285,698,648,871,1000,896,534,492,148,342,385,816,986,443,449,219,69,990,606,903,788,753,132,756,582,918,980,205,220,484,395,473,318,27,914,783,912,51,620,538,16,579,327,626,946,406,223,898,412,360,848,981,544,83,625,335,423,636,969,945,865,187,890,794,538,57,90,255,919,455,310,539,738,787,954,994,851,803,469,285,307,790,998,121,535,249,38,180,235,899,757,636,955,498,757,535,215,330,428,608,139,653,119,126,830,688,377,479,262,138,243,536,853,73,139,711,431,760,357,900,742,761,540,240,852,239,91,821,351,558,85,74,195,682,873,597,107,172,561,908,721,865,87,193,946,977,32,375,605,205,739,714,179,339,818,714,334,678,294,320,638,901,430,331,852,4,493,743,435,390,237,298,202,941,215,422,883,444,173,456,828,248,750,343,810,538,273,442,502,130,458,568,779,188,502,920,786,224,370,469,619,603,780,73,897,528,406,579,400,871,756,354,412,728,608,484,824,606,292,902,47,463,433,526,348,563,88,714,465,462,91,435,135,565,232,769,320,913,80,196,642,796,247,176,21,446,610,156,8,22,654,28,225,632,259,478,189,240,705,768,958,9,929,172,99,163,411,619,28,492,818,327,342,303,241,205,440,614,55,713,517,262,398,974,607,928,755,628,308,396,408,723,264,883,84,699,231,684,975,765,110,513,53,399,395,535,712,386,27,977,203,694,629,286,772,740,899,676,382,495,300,870,554,734,919,98,669,457,539,609,416,62,236,627,168,188,246,791,697,283,945,285,472,95,749,97,423,665,321,446,497,692,893,428,728,613,490,75,627,23,991,267,474,83,75,637,390,130,512,133,846,223,72,448,84,957,401,497,954,711,560,608,849,432,352,271,916,682,810,805,761,330,912,313,456,894,583,725,875,878,412,54,145,826,114,574,338,389,712,913,208,840,159,346,359,892,476,689,264,537,986,249,947,947,17,634,974,225,540,441,289,202,519,356,974,643,253,989,422,141,621,362,707,940,356,929,499,193,751,506,427,255,792,283,414,319,82,446,302,671,293,346,881,557,386,961,933,292,22,619,313,819,231,293,710,47,311,453,678,459,935,191,230,220,464,354,753,987,689,362,632,867,174,919,355,702,499,140,405,273,426,337,661,551,794,218,658,973,800,185,105,592,708,625,201,198,600,19,3,940,856,311,288,895,749,30,68,83,404,604,359,699,603,991,841,613,415,671,841,970,851,846,516,694,602,454,538,534,279,433,446,285,405,898,257,846,776,535,602,567,306,551,406,216,198,972,643,591,549,242,978,82,516,679,543,849,121,300,520,33,19,343,964,876,503,283,494,768,742,876,21,284,882,872,639,460,527,219,84,600,640,592,200,345,35,174,912,517,298,996,370,740,662,706,736,312,728,967,567,767,855,946,178,266,518,30,742,217,877,535,270,566,739,428,113,418,183,341,123,232,449,508,859,255,803,813,94,815,443,297,602,913,106,941,268,440,680,14,982,215,560,649,489,230,136,837,970,738,896,559,460,140,549,346,762,735,165,361,495,130,756,876,508,980,765,382,146,249,968,936,821,657,492,436,746,641,418,38,168,977,575,271,288,20,261,526,801,364,228,229,104,132,680,833,457,918,939,335,342,709,609,743,370,15,601,50,710,685,267,399,332,779,594,844,26,756,878,122,10,297,62,255,747,425,824,611,14,309,961,572,226,526,745,59,172,850,286,934,769,858,809,988,861,763,982,616,919,847,988,897,764,404,743,75,531,951,739,303,493,89,416,583,336,155,599,103,455,242,55,840,881,326,717,839,600,785,121,947,211,28,993,366,715,513,7,476,362,108,742,906,595,810,154,512,889,683,428,932,930,996,41,661,711,67,562,851,269,692,400,613,337,524,858,378,27,765,702,96,696,801,917,761,814,286,416,742,690,498,840,487,911,92,225,484,452,895,244,689,370,817,260,175,183,845,167,133,58,316,855,926,95,303,426,151,862,493,87,845,155,876,980,350,314,667,798,899,973,82,948,833,288,811,491,288,198,727,141,973,384,270,793,379,9,59,286,252,744,450,231,313,674,374,308,253,974,56,568,602,79,1,5,141,815,371,459,23,997,387,259,91,967", +"318,114,304,863,83,504,319,991,654,196,224,633,220,217,262,216,706,51,431,671,93,686,180,242,219,233,468,617,265,273,78,195,648,956,176,406,573,269,380,271,706,268,867,752,0,959,664,268,830,946,536,541,953,851,468,50,828,534,94,452,300,576,642,695,641,548,157,42,105,384,508,566,880,729,329,454,522,408,426,831,42,622,65,313,472,942,656,175,217,421,684,642,336,912,475,987,684,399,958,719,73,115,525,35,488,511,122,228,764,343,509,211,266,645,199,735,219,290,502,515,497,80,938,995,168,764,656,54,18,108,515,153,743,974,670,776,316,274,53,948,669,772,43,730,583,614,853,584,924,581,589,775,168,642,427,461,176,515,136,809,725,984,818,357,269,433,177,910,110,848,188,661,929,533,116,307,671,111,255,8,587,945,438,397,840,935,140,230,181,299,603,714,486,954,737,747,923,794,828,343,141,429,953,311,264,146,938,416,351,239,510,4,298,242,1,602,813,577,738,626,251,950,811,275,476,945,447,702,53,927,442,252,681,213,403,245,344,789,735,331,672,470,510,396,269,717,282,145,884,561,715,248,498,439,673,59,776,307,379,603,501,552,977,34,551,304,222,84,561,586,79,944,243,261,548,661,801,277,663,393,291,472,52,707,244,869,327,130,569,302,920,349,220,517,586,966,907,225,519,921,608,531,25,482,557,465,97,680,64,837,758,33,396,551,218,715,718,547,741,70,552,866,472,33,715,1000,899,816,371,490,251,208,34,327,176,212,578,242,211,100,44,562,236,635,55,703,600,533,699,791,952,800,945,377,615,740,849,476,444,750,445,425,66,2,878,495,665,638,383,402,73,420,451,153,280,489,892,842,973,579,625,204,228,170,611,683,510,364,637,890,607,502,3,767,646,161,260,909,403,641,342,303,641,63,765,167,790,488,276,414,873,389,500,227,746,74,166,966,541,331,686,447,207,69,152,396,958,3,190,17,386,205,744,746,517,132,381,750,412,908,183,945,813,902,34,357,341,915,969,325,606,24,257,858,721,145,776,449,35,513,65,34,261,453,571,922,1,828,775,464,68,332,874,174,474,273,18,835,218,562,993,267,329,294,940,976,875,499,783,101,809,497,703,437,539,554,605,879,992,124,978,553,679,66,338,463,321,494,190,209,841,413,269,769,158,50,825,458,281,507,207,610,504,120,975,448,193,826,978,134,687,283,740,768,835,810,531,652,380,383,172,171,818,676,578,207,447,469,787,326,649,348,138,116,591,271,564,397,416,882,938,798,491,609,869,21,483,175,944,591,765,301,737,252,541,226,442,286,932,425,570,575,188,493,112,806,869,637,968,335,874,691,377,610,134,91,784,830,45,714,563,664,277,429,89,322,207,605,405,307,162,77,452,411,995,181,386,648,983,896,684,670,559,375,156,986,463,642,143,433,13,883,475,67,384,932,96,36,884,308,929,402,889,211,474,579,910,285,499,419,445,996,286,897,910,804,90,764,962,724,31,131,134,741,701,291,864,372,662,585,625,70,224,24,693,83,555,878,303,475,827,613,825,564,193,60,601,644,592,796,830,601,969,960,571,470,507,917,631,613,234,814,666,174,704,456,198,162,196,187,311,984,778,627,245,309,346,636,439,484,188,541,655,444,568,935,696,464,849,446,408,27,571,305,801,96,546,911,474,592,32,840,716,427,302,472,600,908,619,846,420,77,68,430,280,591,108,46,76,993,272,107,868,188,675,704,894,291,117,485,781,145,781,124,287,505,981,928,29,949,835,5,16,598,706,735,234,205,48,794,346,7,283,217,783,358,559,289,584,472,182,139,333,764,74,993,633,764,96,478,980,92,493,262,128,635,429,517,299,924,120,822,317,730,907,120,33,873,982,137,834,544,128,550,59,567,481,140,499,972,297,922,415,392,355,922,318,381,753,763,371,334,506,3,154,805,34,826,92,109,503,618,315,24,388,175,628,772,988,790,237,131,679,122,274,491,134,51,812,213,887,894,841,231,384,350,779,181,355,325,386,130,864,870,954,983,919,937,474,191,156,344,82,625,489,173,351,244,445,895,84,580,856,256,805,436,915,703,873,447,41,345,386,100,703,603,376,121,657,701,383,165,716,527,532,693,187,379,883,187,22,742,565,385,823,379,35,654,338,702,831,283,814,914,520,2,352,394,299,542,487,282,921,587,94,907,134,336,453,755,488,731,909,77,387,756,974,803,259,715,72,43,65,399,404,226,342,146,191,576,723,305,125,831,447,465,811,474,714,536", +"311,950,475,955,981,116,175,17,955,130,543,802,347,256,675,196,858,446,775,801,317,86,31,868,528,377,154,37,809,168,904,834,93,121,705,593,351,479,358,612,130,757,729,566,959,0,6,724,543,988,115,77,57,895,461,937,927,240,577,446,911,730,121,10,666,706,829,350,574,223,597,242,84,744,143,320,905,56,970,226,730,847,430,181,909,747,484,314,293,88,145,787,829,321,109,713,80,751,677,343,149,465,147,230,414,359,135,152,210,493,857,226,756,687,951,319,492,302,645,746,643,244,891,93,65,314,731,612,946,72,363,993,738,322,149,146,57,563,271,613,419,245,753,322,614,785,24,180,286,790,673,665,709,70,434,178,251,435,978,154,381,586,216,602,24,14,203,459,250,873,932,820,282,884,361,649,824,783,740,139,210,637,573,876,580,531,725,977,958,190,547,14,329,885,23,282,627,863,816,542,764,504,221,711,465,898,568,459,392,282,952,85,994,832,846,627,951,725,172,456,241,270,277,755,743,73,551,300,755,858,909,418,729,676,529,840,799,718,130,363,119,937,484,974,572,548,895,771,477,444,416,548,839,866,944,507,960,391,601,922,828,419,384,92,976,986,914,793,277,790,936,846,947,26,911,872,39,137,827,227,82,664,862,470,578,452,784,89,205,896,911,88,506,62,626,653,887,498,963,44,929,638,867,301,268,150,723,928,922,333,41,687,161,336,672,688,647,973,201,692,176,825,270,716,643,71,241,974,881,835,551,747,718,705,917,824,908,286,391,905,854,697,123,46,506,470,522,883,70,615,972,501,869,404,331,689,719,306,861,678,27,942,66,603,514,645,533,337,44,185,681,156,292,251,534,834,388,763,890,530,617,827,800,151,226,335,884,395,86,101,871,366,23,359,757,174,811,828,361,53,21,988,910,802,529,834,831,833,108,560,317,917,453,305,148,917,733,36,260,498,913,757,319,87,203,304,311,955,708,388,739,641,126,124,16,706,582,60,24,904,846,820,606,823,932,6,935,715,705,142,41,143,419,373,992,13,617,518,148,624,292,293,459,640,59,644,23,176,109,381,43,142,36,542,61,990,153,414,969,190,255,554,767,523,74,259,501,118,735,874,261,643,629,478,483,32,2,729,440,431,258,669,708,679,559,336,384,487,400,510,910,700,704,346,686,953,944,617,935,448,263,935,77,915,74,441,870,110,28,878,962,180,203,776,773,609,6,405,235,168,80,848,211,782,282,716,656,956,360,886,94,469,941,188,673,968,298,843,892,363,710,400,378,477,71,656,610,427,635,946,521,363,873,144,176,939,11,58,150,564,31,717,480,300,58,722,848,176,89,760,589,428,232,345,89,114,487,655,584,174,802,543,178,778,811,925,457,322,19,358,8,664,192,674,381,107,947,911,338,804,908,510,710,190,16,581,804,747,615,408,32,570,261,523,998,181,725,396,920,18,541,661,670,407,124,243,513,419,336,935,965,684,691,299,142,711,209,33,826,788,798,818,765,900,730,261,6,907,751,630,334,473,346,846,184,432,276,921,908,553,781,771,148,295,613,967,801,39,375,36,836,386,601,486,26,153,699,768,631,653,471,537,758,747,652,476,768,612,259,861,398,548,157,35,332,27,896,514,736,453,561,463,958,21,598,333,843,906,837,250,916,81,325,891,145,790,621,70,577,219,858,240,911,675,450,774,538,126,126,14,258,50,909,486,560,706,254,906,653,320,758,310,195,663,85,801,444,861,193,108,288,307,959,796,215,4,731,332,14,895,604,178,401,389,38,787,684,902,638,104,562,570,942,864,352,878,5,251,824,828,8,801,595,321,232,454,41,435,898,904,233,121,130,333,713,483,452,663,449,671,832,207,86,72,305,743,46,953,542,458,196,204,795,714,772,417,72,29,191,553,423,285,461,937,404,92,690,979,994,65,671,146,97,767,510,451,768,73,385,740,738,750,618,518,815,40,402,955,619,107,643,608,126,628,431,727,993,807,985,651,724,361,772,444,159,782,965,407,517,721,815,159,157,169,280,577,838,249,328,600,859,980,975,975,686,920,434,538,465,727,125,671,646,368,712,625,630,921,607,760,481,863,288,260,848,850,384,303,219,337,58,895,806,116,307,505,770,484,881,135,325,893,365,675,255,958,552,614,389,352,225,533,683,581,444,260,786,5,542,582,5,308,25,327,226,693,452,890,620,926,850,669,825,259,254,163,989,707,164,332,649,514,424,719,447,257,246,252,400,820,497,172,307,4,326,542,846,547,733,647", +"579,786,74,503,733,242,223,26,690,591,129,420,268,39,654,886,307,53,101,139,449,206,116,322,849,70,792,53,732,723,992,240,218,655,159,307,181,951,7,352,446,539,43,320,664,6,0,878,543,871,960,864,898,314,371,263,859,100,427,343,591,541,42,786,982,982,776,774,430,83,332,530,357,385,245,895,887,445,716,433,990,542,205,931,693,618,140,524,813,808,204,704,685,599,528,963,262,337,700,766,965,673,34,159,145,681,634,789,656,554,669,349,760,823,766,99,71,353,800,267,616,256,134,286,153,300,546,78,996,117,304,54,884,808,617,47,932,767,571,391,768,694,86,639,392,76,397,674,603,216,723,812,155,343,514,993,596,976,120,306,190,680,666,3,435,541,678,888,803,649,94,961,20,760,979,643,888,384,917,802,35,346,274,146,663,913,105,838,348,152,543,956,811,419,879,481,197,514,765,525,665,134,514,295,493,686,731,354,987,857,485,475,966,706,21,841,382,665,533,184,432,345,677,493,111,129,89,920,917,515,346,711,552,85,390,375,715,829,995,600,237,803,558,395,736,861,198,477,843,470,255,945,964,888,883,977,64,326,999,979,499,268,457,551,482,113,23,556,759,87,524,100,114,793,221,555,525,846,442,998,160,841,322,986,807,877,398,542,815,244,300,747,49,110,11,703,193,537,161,655,223,437,928,978,494,199,340,31,45,592,92,899,330,962,889,10,409,517,48,994,932,850,507,244,356,695,70,62,397,723,40,977,731,652,768,698,485,725,92,317,532,165,133,481,807,137,592,103,263,820,618,84,799,557,194,527,872,459,100,968,916,110,209,18,793,777,503,242,297,588,671,948,464,638,590,629,577,494,680,560,681,393,182,551,57,125,933,753,268,456,126,557,891,444,401,659,158,24,392,551,523,437,550,796,244,289,355,556,906,173,208,782,801,563,173,254,515,57,487,603,234,524,196,770,505,716,240,974,827,309,678,598,165,188,60,389,180,167,842,111,310,631,451,231,969,164,150,917,757,801,354,808,319,590,560,27,349,676,314,960,774,562,790,139,564,939,992,803,684,149,474,404,159,63,228,43,879,334,771,82,970,595,872,870,932,481,165,100,426,482,383,579,803,147,310,193,881,372,840,159,820,472,2,18,810,762,624,731,287,293,642,366,485,718,836,135,584,154,729,142,987,601,281,54,42,891,614,815,3,144,31,700,75,618,281,424,450,624,602,829,752,235,428,331,660,512,841,376,789,999,979,452,767,733,243,742,479,149,598,694,774,13,582,325,570,976,19,950,172,454,831,487,146,646,625,869,909,378,772,806,807,815,923,903,511,361,295,363,888,546,645,428,270,618,386,128,185,287,223,21,652,174,69,770,119,642,467,381,430,551,513,367,956,989,594,106,559,257,170,794,808,328,691,889,775,781,90,283,322,78,315,228,539,503,195,117,525,670,203,576,967,886,454,51,35,348,832,965,291,942,969,78,222,42,565,503,400,516,517,283,564,813,840,677,259,273,930,958,691,129,964,957,349,243,783,862,360,453,996,844,882,319,639,635,568,911,520,260,964,959,729,160,900,104,649,779,908,159,389,887,959,857,352,560,490,354,584,848,749,292,442,852,85,329,875,435,893,135,364,259,886,710,152,452,562,755,664,654,635,100,575,610,44,723,451,593,853,904,580,555,141,299,21,616,686,292,503,932,779,807,317,4,27,837,437,95,446,811,86,935,125,111,763,561,924,336,540,715,133,596,806,884,950,51,598,617,332,684,736,970,699,867,428,175,377,309,161,257,84,818,607,460,482,198,70,936,548,846,17,818,373,318,192,893,13,79,821,455,624,106,901,432,793,302,933,787,807,627,998,668,175,860,130,918,729,529,216,280,148,142,445,143,686,437,40,885,938,414,544,558,381,286,977,671,754,957,687,776,272,957,480,732,150,847,238,233,902,301,897,728,238,493,999,171,810,826,840,815,623,183,950,109,15,322,552,861,432,713,615,319,281,543,175,606,388,863,98,886,20,253,996,449,890,800,700,52,193,714,409,756,726,980,331,4,429,773,30,157,996,717,37,317,600,754,933,927,62,185,561,215,845,974,24,591,875,381,445,508,617,632,217,801,471,373,315,314,905,71,969,92,425,985,481,242,904,422,589,243,527,29,882,491,930,853,797,628,225,942,214,269,326,816,272,249,174,440,396,9,6,834,82,945,820,333,749,124,866,606,866,493,244,743,888,469,988,976,342,508,320,339,746,317,426,878,748,885,942,9,126,303", +"58,101,324,775,396,248,988,520,491,875,72,952,486,184,65,340,636,749,841,906,469,212,597,603,703,102,470,659,470,779,30,860,473,534,602,816,496,740,279,534,885,283,24,297,268,724,878,0,954,597,947,566,935,507,285,939,574,729,932,68,722,984,385,833,142,311,526,407,612,932,686,867,36,634,818,58,877,334,932,151,520,315,194,554,915,579,450,146,852,833,731,701,168,826,204,450,367,998,372,548,419,242,148,83,378,378,656,215,764,816,245,342,684,289,397,792,411,968,855,884,684,279,183,459,105,226,422,140,800,934,827,590,63,814,438,398,407,4,420,889,479,727,952,261,61,826,742,536,995,996,737,952,156,899,126,664,732,947,223,986,931,385,412,749,734,237,299,512,992,876,89,160,518,446,556,430,775,431,407,672,150,882,260,972,854,416,83,692,305,396,578,85,196,939,384,506,310,381,901,980,350,10,368,520,98,518,761,690,462,476,982,979,752,821,358,712,791,998,415,221,26,613,23,1000,725,531,400,954,365,585,107,853,92,395,825,543,949,569,110,542,982,566,611,466,716,348,873,542,602,502,972,305,354,116,149,421,917,464,233,256,264,888,304,608,895,950,443,431,381,144,817,604,239,817,797,299,534,334,810,917,815,858,861,671,474,845,305,773,808,902,596,330,38,826,777,804,651,592,521,556,942,75,137,93,416,651,277,53,340,217,862,466,497,470,178,612,451,304,114,277,435,96,955,947,5,303,832,622,944,670,415,497,426,319,736,684,599,569,248,991,899,702,611,825,310,224,630,215,725,233,84,84,18,252,399,304,524,987,237,262,982,679,360,377,99,478,999,919,5,674,936,326,426,361,76,232,250,560,350,983,338,66,992,149,237,16,183,475,41,974,886,424,647,864,203,437,361,608,123,834,137,925,273,100,6,815,282,175,30,839,512,806,845,375,303,197,354,339,544,949,34,917,361,179,605,55,644,475,550,632,618,768,203,116,111,148,622,261,173,190,695,771,287,429,45,489,758,882,410,610,677,631,367,803,94,898,894,472,374,950,308,795,799,177,218,194,523,432,823,138,370,868,806,193,943,39,212,975,87,423,579,189,440,516,983,690,568,740,717,177,430,624,494,611,494,771,651,894,642,685,668,974,877,904,590,979,478,469,255,635,552,525,221,963,45,915,476,326,962,298,177,935,537,909,928,651,221,251,367,393,652,750,105,48,863,611,883,706,620,545,790,138,374,162,47,23,787,999,458,561,675,454,994,5,11,939,559,773,703,448,180,205,23,653,183,749,672,185,586,411,661,408,93,62,795,16,794,867,319,682,266,181,931,752,398,53,724,602,922,847,683,586,370,57,86,634,88,86,906,908,151,19,480,807,142,825,71,83,24,50,153,540,603,848,459,654,870,986,248,3,870,598,727,325,353,153,19,45,669,281,493,761,579,390,632,128,72,667,344,525,661,164,832,790,549,340,690,805,572,490,184,516,196,62,242,784,939,893,687,968,782,109,971,506,544,790,865,242,847,235,954,802,595,289,654,576,788,539,785,916,287,490,991,100,229,83,814,844,161,237,114,406,333,982,756,164,112,885,303,545,157,618,726,994,271,660,444,826,970,746,584,443,120,254,780,726,684,36,988,671,904,318,555,714,295,484,553,386,666,424,590,782,864,341,461,186,149,792,489,376,808,452,379,469,554,292,597,348,210,759,283,993,56,152,937,675,46,966,590,374,247,293,556,625,877,525,300,664,152,737,165,410,689,643,665,817,701,928,981,421,44,256,369,741,427,397,978,543,564,144,656,693,30,207,511,340,365,268,258,940,235,127,676,31,439,886,563,929,472,646,866,15,355,568,42,723,171,750,666,46,866,769,194,530,933,828,91,436,665,196,504,250,429,948,233,337,794,355,879,286,605,791,404,906,297,773,23,599,76,912,384,747,575,642,444,937,771,404,658,485,165,363,161,234,310,721,630,955,935,571,884,685,136,893,469,380,13,236,244,337,798,67,73,231,534,98,389,558,603,774,781,870,89,105,679,945,313,494,937,703,44,524,125,828,78,541,982,949,618,381,404,66,507,169,402,761,250,975,789,611,764,928,624,285,742,740,917,630,970,14,863,932,745,536,32,783,419,798,174,153,436,786,424,865,423,447,520,821,867,776,885,886,124,924,959,304,184,451,339,638,986,798,592,849,144,719,328,693,193,955,678,663,214,380,599,842,61,486,979,21,820,944,498,370,192,352,388,78,165,133,590,927,905,281,352,941,920,953,292,665", +"145,888,59,396,915,794,808,62,962,15,529,8,9,807,908,312,277,512,59,787,118,1,499,543,763,425,65,525,156,511,398,740,398,857,29,240,790,713,299,649,211,405,58,213,830,543,543,954,0,120,144,121,842,607,660,504,730,305,31,626,434,987,994,786,590,488,994,505,801,246,509,266,241,253,644,804,462,110,628,505,939,917,615,522,916,142,64,692,7,564,438,636,305,23,157,310,414,264,472,536,140,26,562,135,169,18,185,569,721,704,898,581,825,663,58,9,535,55,964,816,134,606,246,403,87,782,754,184,906,604,751,336,486,51,707,915,94,202,505,370,381,289,748,509,34,584,372,906,718,155,204,894,159,771,714,320,299,540,518,93,458,639,715,140,556,79,558,551,220,544,269,290,976,111,624,591,566,760,742,832,63,553,889,431,831,258,557,70,150,803,700,571,636,126,294,112,88,141,825,321,789,272,838,926,308,400,825,180,751,665,81,165,100,602,429,488,853,977,133,732,598,203,826,753,878,940,763,989,427,656,660,44,230,999,754,928,751,504,772,613,176,893,745,410,886,589,86,285,384,257,129,242,495,412,988,699,378,991,360,767,492,160,396,227,996,350,984,165,560,329,957,790,458,140,571,730,568,628,259,978,126,421,240,713,818,649,800,443,993,594,601,841,134,705,564,154,849,331,417,3,266,592,920,340,124,989,707,840,288,104,737,945,843,605,352,239,469,269,609,449,107,817,568,439,440,509,196,224,229,189,424,448,27,308,242,409,212,109,462,954,453,670,253,152,159,629,630,912,989,578,349,299,65,976,58,69,262,641,999,484,981,255,424,745,432,161,823,965,843,987,577,133,498,203,730,555,170,266,137,937,278,303,359,116,657,231,618,343,645,923,469,63,701,83,197,379,140,656,599,368,109,14,46,453,825,69,892,414,112,815,101,837,15,52,955,935,885,534,404,659,909,748,131,756,494,836,448,474,459,46,332,522,813,827,38,719,990,699,97,89,88,369,926,530,618,268,900,283,575,250,256,346,46,875,177,132,31,898,478,849,469,259,207,770,705,782,581,702,250,521,6,784,18,893,249,653,95,464,34,287,128,531,379,160,579,408,51,598,52,535,251,748,71,910,669,586,401,353,182,912,47,759,296,208,212,414,739,835,713,23,407,73,529,101,852,655,786,49,838,352,257,148,887,105,10,346,286,162,305,440,989,564,392,447,100,626,777,874,280,185,508,193,659,245,212,723,397,735,475,558,742,432,768,196,557,435,801,139,630,217,608,993,825,73,243,429,827,481,319,43,561,835,672,109,661,344,307,437,839,61,618,739,215,792,836,108,894,634,793,402,653,756,44,683,696,346,82,233,73,510,378,917,67,257,733,359,110,269,803,854,801,967,880,225,847,355,182,662,84,407,338,789,269,830,30,755,875,828,697,22,723,403,73,729,888,60,556,347,316,173,667,145,94,650,491,307,674,941,760,510,255,716,754,518,228,416,781,643,844,447,709,942,590,691,53,513,109,658,802,847,409,782,262,741,797,826,525,863,431,75,441,703,669,318,917,762,502,887,171,422,888,572,76,304,796,607,718,784,852,341,251,580,233,390,833,976,521,411,667,618,237,796,521,494,23,618,479,343,751,778,299,382,393,458,390,368,83,200,467,363,302,356,309,839,276,804,111,870,734,670,143,455,899,13,974,30,726,706,68,455,962,738,768,149,131,206,616,729,533,686,323,489,454,381,221,386,991,256,595,683,767,10,318,772,789,354,655,491,574,179,870,70,952,32,435,798,213,87,742,291,555,154,773,428,201,621,398,769,412,398,827,534,359,729,142,202,852,783,624,543,261,333,215,871,782,448,860,191,783,380,7,453,608,729,477,60,284,642,28,13,384,472,176,414,496,360,166,816,667,305,864,851,244,592,982,120,278,365,860,646,843,39,576,825,843,207,325,317,489,655,365,450,724,496,959,655,513,659,214,721,865,827,369,282,13,441,115,514,622,204,746,867,896,416,799,631,868,329,923,828,503,428,572,33,160,631,952,909,793,763,387,463,940,388,590,360,736,877,542,431,406,126,660,399,770,355,132,608,492,387,836,656,834,112,50,937,516,30,186,965,893,699,137,400,331,144,439,102,309,246,591,239,705,2,973,454,320,62,348,690,332,183,121,469,676,104,318,960,332,500,476,636,293,804,660,657,642,763,273,712,16,489,139,103,547,703,217,953,192,522,152,7,779,96,191,695,413,562,641,722,642,717,325,382,535,137,924,388,888,776", +"304,750,349,520,102,281,296,551,786,187,848,600,299,183,547,440,311,341,565,718,909,443,229,476,327,306,824,153,464,273,35,164,771,147,494,12,304,401,800,208,143,356,214,597,946,988,871,597,120,0,676,502,739,122,757,469,633,597,41,405,468,844,833,882,61,303,311,633,845,962,279,929,861,321,730,239,620,591,602,637,908,466,279,737,671,976,754,190,725,576,536,503,441,352,670,428,548,302,619,309,10,575,299,458,834,823,101,191,568,444,920,335,545,426,436,481,814,122,73,153,324,801,623,257,410,506,310,232,569,213,115,760,311,452,267,585,247,765,765,436,775,745,639,254,760,726,697,517,785,256,652,395,425,136,977,476,578,360,284,576,977,693,578,37,529,316,369,319,3,254,767,798,511,921,902,641,84,477,72,985,107,594,931,776,219,570,402,912,86,371,138,484,350,953,500,393,719,414,481,903,234,983,665,641,354,314,461,384,678,319,658,566,896,539,551,545,464,928,908,964,81,527,250,529,739,648,126,785,787,483,607,22,896,764,778,574,188,453,589,4,445,477,536,686,14,709,858,624,656,28,661,59,456,376,917,643,524,6,219,789,485,813,513,120,622,994,11,538,477,303,877,192,686,505,385,606,983,160,773,506,796,884,883,297,984,298,131,557,58,991,133,298,236,369,73,367,980,391,937,87,155,677,719,276,513,495,732,614,960,988,185,3,105,677,718,699,87,721,999,948,427,170,5,253,268,328,151,349,164,43,246,111,753,969,566,774,757,762,441,330,262,625,702,419,168,311,198,724,516,774,36,444,272,943,157,391,454,109,107,251,936,801,796,547,295,456,200,992,40,768,948,877,942,706,327,424,856,22,21,807,80,575,927,770,619,671,733,304,623,340,282,725,375,71,441,631,891,157,309,783,267,952,396,963,806,553,247,724,14,59,549,942,110,880,558,165,415,626,222,91,943,507,397,427,856,183,238,392,330,766,552,68,766,558,211,994,491,755,494,583,848,805,124,379,487,369,879,180,385,757,762,958,347,124,477,706,673,710,142,131,146,260,921,918,457,55,657,810,269,104,533,883,851,944,671,296,821,648,625,648,530,673,465,474,693,38,887,508,395,940,197,678,443,755,363,672,740,683,307,607,152,472,691,793,167,994,352,575,693,153,526,444,954,287,358,206,204,151,209,972,687,246,262,29,737,508,894,813,244,731,960,127,194,899,943,924,599,490,542,646,27,691,165,950,802,675,390,680,827,631,981,301,656,778,299,902,65,307,131,106,249,53,544,319,228,527,964,731,251,893,671,283,241,719,608,497,244,256,268,661,462,639,846,112,337,195,563,707,592,712,935,631,11,559,509,502,363,230,211,56,966,319,35,463,489,3,227,837,186,939,418,312,432,995,268,116,871,344,922,996,430,999,737,827,866,986,452,818,646,432,519,411,747,603,228,424,570,749,837,607,335,929,205,12,628,580,921,177,998,359,22,565,718,842,563,748,353,631,772,273,376,806,561,538,218,8,756,93,322,964,304,874,790,495,918,831,615,380,428,353,467,1000,352,309,698,359,766,260,480,545,97,358,115,623,249,907,868,809,1000,409,26,968,687,876,495,233,21,552,429,254,473,927,853,967,976,665,306,923,34,884,724,416,296,899,681,543,708,657,572,249,99,117,784,352,564,804,718,890,781,835,316,563,897,312,274,436,953,677,611,191,463,485,814,143,628,54,801,735,307,302,808,720,190,751,484,8,984,773,960,966,579,515,797,897,376,106,321,985,2,376,167,212,317,28,670,400,180,567,548,542,21,951,435,937,954,155,906,244,86,319,151,357,470,538,670,747,607,349,867,59,665,491,544,428,813,582,653,926,53,29,575,970,253,886,899,813,649,899,500,940,922,184,222,425,445,285,593,409,591,773,601,918,39,757,521,935,513,549,466,346,148,493,622,312,644,990,680,769,612,73,86,979,608,431,988,850,905,597,779,67,657,82,107,77,186,941,706,61,156,241,674,195,493,115,41,836,974,342,432,275,251,394,572,873,983,146,641,312,404,407,74,951,898,857,831,30,847,776,340,528,337,9,755,469,985,444,711,340,966,811,750,791,858,531,595,813,677,718,389,273,272,288,338,251,904,200,98,28,854,565,705,292,46,140,776,701,943,153,760,187,238,750,247,701,849,896,228,963,625,320,112,376,124,592,207,550,674,930,269,791,897,19,694,326,430,852,912,594,321,611,629,954,332,602,139,566,402,164,995,963,961,568,305,390,22,101,101,970,958,407", +"133,550,120,652,122,805,3,559,155,802,167,243,597,471,131,30,413,949,609,463,631,810,688,937,234,970,547,516,66,761,59,145,379,130,890,690,743,891,601,203,367,594,419,810,536,115,960,947,144,676,0,62,384,383,596,12,461,343,664,102,343,365,762,658,710,988,143,26,323,707,419,205,413,312,821,385,819,908,427,461,358,398,746,348,821,91,491,707,481,765,919,488,5,641,215,755,240,300,833,932,391,724,911,519,703,768,78,257,926,504,237,979,530,521,793,444,684,486,812,16,956,229,834,673,1000,519,894,195,648,694,439,448,916,436,870,954,182,595,385,203,827,294,940,692,671,807,19,112,328,276,290,835,365,933,889,536,435,444,670,872,934,231,941,402,650,790,718,948,194,636,354,817,614,390,967,624,459,756,521,339,160,248,53,564,413,965,148,499,851,521,930,284,251,487,706,61,650,211,89,255,786,500,858,630,214,953,471,53,603,737,598,729,135,990,208,624,489,393,311,375,584,134,240,84,825,531,411,204,406,819,214,236,569,638,904,55,349,555,950,540,823,844,862,844,498,532,564,831,228,753,327,564,782,212,826,229,566,543,373,198,825,709,706,848,361,355,506,875,787,604,584,373,83,258,512,936,197,639,22,753,104,298,491,507,337,626,475,809,641,18,876,734,530,398,668,921,840,243,365,219,487,594,767,398,157,384,344,338,546,89,683,42,419,100,854,202,457,218,412,680,200,102,123,112,161,395,126,584,800,453,434,411,513,847,332,677,105,413,912,641,376,379,434,458,937,179,258,429,692,192,446,894,527,182,691,728,752,826,328,773,481,106,792,128,89,505,7,842,223,58,592,372,287,962,454,654,185,710,580,926,274,656,93,383,121,318,980,832,441,435,236,987,548,723,535,713,554,435,557,277,957,498,709,154,550,824,166,89,983,431,911,522,208,389,912,341,120,192,611,16,50,678,119,131,847,571,673,422,576,681,437,710,320,583,826,539,54,888,191,97,83,989,327,372,613,710,184,734,656,368,38,996,268,444,67,647,598,22,323,441,161,223,742,200,303,956,564,698,819,794,698,173,583,358,133,128,254,161,737,942,424,221,65,625,46,148,218,744,703,802,739,60,695,421,561,684,276,570,324,919,943,728,38,639,341,104,597,696,338,686,474,232,439,790,658,458,9,561,88,976,244,278,45,993,939,700,968,57,573,740,756,948,524,452,575,917,606,54,246,652,744,343,334,439,649,950,920,962,800,985,885,189,400,5,608,85,814,221,198,395,725,877,864,271,768,666,986,947,272,697,125,863,889,439,396,699,999,454,191,686,109,998,403,618,511,278,345,603,171,647,157,975,251,252,2,203,523,425,431,661,854,961,639,471,837,991,289,665,235,777,461,691,595,212,642,710,769,719,587,357,563,830,500,928,18,765,130,224,371,420,3,54,858,233,713,333,196,216,675,778,150,613,530,755,484,624,49,30,204,523,176,165,580,897,352,972,259,938,311,305,73,610,518,95,444,494,918,825,795,862,910,438,505,516,450,214,125,184,607,526,945,476,977,741,629,2,366,623,956,503,685,306,959,362,398,32,804,568,482,999,945,782,67,504,598,377,837,357,542,110,309,186,45,536,913,200,427,322,682,356,915,283,195,431,87,801,545,784,452,932,143,856,745,267,250,421,733,40,854,186,123,106,933,809,383,264,588,234,82,557,451,218,721,873,646,738,205,343,975,175,904,80,749,257,199,338,244,554,513,615,312,784,360,739,599,367,849,380,786,229,80,204,341,820,624,806,44,482,494,304,419,477,648,697,750,317,615,507,495,631,703,837,637,313,952,700,498,946,295,780,378,898,23,128,946,296,526,540,248,501,945,829,478,564,595,940,363,723,226,594,403,811,565,435,783,418,5,873,363,20,571,281,705,952,260,161,149,510,588,690,967,467,795,272,276,452,234,963,474,515,874,142,851,81,758,624,547,966,455,604,2,157,615,758,638,846,966,339,954,187,605,530,102,802,91,684,571,586,624,706,405,859,406,930,261,430,19,653,33,473,987,357,820,205,431,717,949,449,713,703,151,392,264,183,477,11,968,893,337,172,151,541,586,641,27,432,587,178,670,348,729,829,964,845,620,91,789,467,807,728,196,11,764,633,598,718,374,792,639,532,562,219,273,420,895,408,706,731,446,579,517,700,477,26,286,433,386,20,856,449,674,383,836,720,700,584,947,560,582,321,45,600,916,199,838,964,298,784,714,418,892,972,553,534,845,378,960,213,273,861", +"440,293,555,572,905,595,216,991,695,769,509,323,386,522,166,811,744,115,600,818,847,940,965,625,107,951,889,88,480,417,817,473,679,932,905,244,367,908,318,99,99,265,195,563,541,77,864,566,121,502,62,0,442,871,933,416,80,303,135,927,358,213,286,258,314,313,386,345,142,532,224,538,322,841,542,253,292,85,628,878,200,769,758,255,889,867,25,982,191,359,8,707,712,178,607,46,647,932,91,135,844,952,158,516,993,183,812,275,606,919,118,822,187,124,274,333,454,82,494,372,879,364,363,408,547,884,164,152,363,644,879,307,114,915,520,470,281,476,915,780,651,321,426,268,180,415,712,408,429,201,238,389,936,144,993,833,150,150,846,518,566,714,633,221,763,42,622,555,125,298,460,24,192,11,352,743,369,864,227,716,241,107,384,700,748,36,192,145,908,207,718,845,694,909,240,897,104,989,25,822,584,219,629,899,11,135,564,899,496,23,609,724,675,602,97,251,182,324,932,262,770,835,29,73,557,600,240,944,84,570,871,137,840,465,621,171,559,741,253,831,777,447,825,961,978,88,952,530,159,50,932,16,213,113,496,252,496,48,426,435,159,670,752,2,245,553,371,238,718,896,713,412,38,581,109,370,753,538,950,710,32,880,367,920,758,311,291,63,503,296,260,588,494,647,42,254,629,800,52,531,879,869,797,687,759,347,113,144,352,842,711,150,807,959,53,426,45,819,844,83,523,892,217,748,466,10,654,932,73,790,543,88,751,233,515,798,633,887,50,67,590,315,191,611,599,495,52,655,52,774,997,469,134,92,666,516,470,589,680,906,32,522,704,133,238,531,394,327,198,477,320,980,635,11,506,481,954,822,212,215,828,333,636,344,782,119,80,491,360,651,183,270,103,869,485,622,545,594,561,599,830,143,976,120,844,326,720,365,529,93,900,601,413,611,203,158,782,969,782,838,173,162,549,89,118,683,468,946,427,110,672,336,130,135,466,814,864,259,996,579,420,855,902,481,497,562,331,422,773,240,606,95,594,208,290,742,364,122,338,266,127,816,721,31,778,340,463,689,748,587,899,816,666,986,709,285,397,528,936,408,190,122,977,822,379,289,145,99,682,833,729,113,346,499,577,488,402,290,305,356,651,530,56,373,125,673,499,737,985,394,65,287,417,814,928,334,505,811,515,656,600,876,112,730,11,895,830,711,400,749,160,685,529,121,339,876,789,558,127,331,820,114,827,150,832,559,149,47,322,272,606,921,884,195,985,617,513,431,788,609,769,537,768,214,42,415,293,641,390,830,161,517,319,753,115,675,186,53,350,648,583,194,180,307,283,920,605,130,467,436,781,948,94,605,592,78,285,759,873,839,321,619,294,462,97,296,121,815,190,642,220,989,113,314,39,965,771,103,836,31,976,443,425,846,306,47,406,589,67,579,232,266,393,322,799,767,968,768,472,703,533,567,232,778,387,742,111,6,453,733,559,930,560,860,596,385,430,454,143,577,374,241,582,505,537,58,262,731,806,323,964,747,653,835,2,908,791,619,904,906,447,129,734,411,178,7,554,774,461,650,208,517,837,868,770,152,568,238,143,457,931,464,363,29,601,915,674,485,409,185,721,630,438,251,31,138,165,850,573,317,931,75,249,1000,693,811,400,982,674,139,261,752,148,178,211,878,120,681,47,741,284,389,23,997,646,869,280,651,524,380,377,638,647,958,134,591,165,629,420,472,355,915,417,281,756,615,408,249,360,919,131,852,75,743,428,629,915,242,397,955,495,533,853,322,30,696,46,301,57,501,331,33,205,871,220,727,522,633,660,544,598,292,292,916,232,914,982,548,934,52,300,277,135,737,78,691,249,291,639,495,992,462,747,337,911,907,257,282,440,620,870,430,906,166,85,373,143,96,986,207,391,712,576,887,673,537,11,448,633,781,838,603,639,456,758,451,882,347,928,375,641,77,912,614,329,961,48,754,120,920,443,205,873,366,146,264,568,826,159,945,736,132,373,444,302,402,486,274,547,556,249,120,638,355,579,437,410,173,700,133,990,724,575,189,74,6,899,292,679,267,176,898,216,688,781,920,63,455,660,205,987,614,352,484,366,935,551,872,127,307,342,301,494,913,980,595,960,391,563,775,358,894,809,694,416,627,675,119,32,362,49,200,822,550,692,271,4,721,481,568,140,676,817,711,296,362,169,794,815,579,632,435,313,129,875,888,292,443,104,941,339,624,115,899,179,894,972,122,56,12,778,566,91,124,87,84,738,30,799,136", +"159,584,62,404,891,59,197,725,926,214,840,748,352,274,475,652,988,55,483,851,359,799,829,980,613,945,90,746,332,813,89,502,342,814,937,765,765,530,951,308,258,179,449,743,953,57,898,935,842,739,384,442,0,805,491,400,320,458,926,37,841,201,449,112,87,780,969,761,667,22,215,841,437,264,337,332,611,854,102,911,569,467,657,663,370,524,753,228,668,354,939,477,394,828,808,285,999,993,305,439,222,138,98,421,19,816,28,657,449,717,880,445,896,366,534,247,565,334,375,372,734,723,188,809,72,896,447,560,117,172,75,350,945,334,738,495,44,115,538,12,953,45,613,321,790,295,762,274,309,541,51,993,438,683,949,169,414,981,438,385,851,284,904,981,344,92,547,68,413,952,730,897,592,480,212,407,758,996,166,423,337,865,421,229,167,580,653,349,405,622,650,337,361,352,784,846,14,996,23,234,269,328,994,622,697,77,134,364,993,859,922,713,939,786,952,392,882,176,426,295,37,103,969,86,251,247,492,815,802,825,88,447,726,566,270,493,77,45,690,709,514,405,66,737,522,247,692,265,633,504,386,81,65,606,733,278,395,453,781,804,854,66,762,734,317,393,90,213,735,305,179,820,764,338,775,74,496,623,906,405,329,792,76,900,634,67,180,569,240,612,329,657,148,513,51,794,743,850,484,388,49,141,81,513,998,567,269,485,710,695,538,491,205,325,151,542,983,674,589,760,476,569,860,972,882,725,778,997,339,694,658,392,420,354,58,896,336,224,297,714,894,959,56,233,658,67,113,562,154,708,696,743,44,898,414,87,412,492,356,19,614,215,843,734,804,105,479,94,445,726,552,367,44,99,667,530,95,392,611,163,785,212,334,808,798,723,456,114,153,966,788,436,786,236,802,749,950,79,879,936,294,934,803,963,887,849,127,288,565,456,92,112,757,642,533,139,522,669,128,647,905,633,491,797,149,106,429,560,416,252,199,135,996,691,34,576,960,39,719,953,524,311,287,460,714,335,173,57,969,753,370,632,939,784,88,274,429,187,737,974,687,576,968,528,375,119,895,635,371,165,7,31,805,51,587,65,657,732,620,267,604,797,894,877,717,937,528,728,796,450,968,814,538,980,506,526,337,631,63,961,743,890,697,62,290,834,821,390,122,148,540,217,655,462,187,911,980,510,641,904,256,247,831,645,966,55,234,656,363,350,64,790,760,999,736,258,943,713,134,529,227,773,151,2,352,801,676,236,421,904,128,930,829,681,658,991,773,785,207,458,747,77,939,663,173,425,887,64,57,76,201,303,488,794,151,483,416,685,818,380,487,794,12,377,436,522,173,222,576,219,262,371,8,542,193,771,169,749,31,115,510,802,761,36,942,40,427,511,554,305,226,522,503,380,832,811,993,211,377,647,305,405,450,644,171,322,808,147,708,802,8,638,152,458,953,568,685,265,189,568,545,121,371,109,603,475,4,750,840,31,840,928,536,719,261,365,336,199,72,308,312,286,964,583,351,404,453,437,543,566,786,907,560,361,33,48,907,165,868,290,483,491,795,912,244,520,949,247,192,308,124,767,428,628,100,579,874,177,988,677,412,531,45,606,659,776,742,347,714,186,160,646,159,137,62,787,545,978,531,95,176,598,569,142,325,463,404,409,908,376,30,684,817,631,814,712,704,870,738,563,903,47,292,368,582,509,12,626,993,683,238,756,135,67,655,475,150,389,540,678,180,181,717,966,868,245,96,243,819,414,713,875,513,915,277,192,16,900,473,709,368,538,205,473,159,110,589,603,1,896,884,501,291,575,527,744,187,624,823,751,90,541,29,761,902,877,762,220,170,222,446,318,940,956,662,729,324,528,804,756,506,475,475,63,287,836,857,913,776,477,358,741,593,656,840,642,127,798,660,322,89,214,538,336,252,592,870,511,481,8,469,683,98,340,67,682,2,352,649,159,258,756,193,392,335,980,972,824,660,920,538,52,659,874,511,894,197,771,683,813,184,36,140,231,663,470,839,60,115,402,12,515,482,275,242,892,487,532,884,847,659,69,12,995,371,783,527,846,52,50,42,361,973,80,702,569,832,794,355,864,506,538,218,724,154,774,497,736,570,834,364,800,776,363,567,812,660,384,331,734,882,778,25,407,94,809,662,487,592,954,533,347,914,516,250,158,962,433,470,940,642,521,418,123,654,397,582,126,295,605,363,168,235,755,42,313,244,829,205,918,941,766,117,635,686,460,958,237,13,529,652,711,109,889,90,635,992,279,287,956", +"219,254,299,747,296,924,192,857,374,671,471,412,938,155,995,51,697,309,562,42,805,698,632,128,928,636,460,365,55,184,224,670,853,413,977,408,359,467,884,108,196,605,860,121,851,895,314,507,607,122,383,871,805,0,163,331,865,503,804,944,606,503,596,459,776,297,349,623,522,408,110,605,863,62,433,646,421,750,220,541,746,185,989,259,256,280,732,46,377,620,978,557,766,803,629,444,916,625,52,511,181,689,100,703,894,812,741,741,15,551,426,500,432,35,24,912,323,144,814,918,173,825,940,300,552,167,83,102,234,572,23,285,771,529,386,469,539,672,892,398,978,343,171,585,413,276,425,432,548,741,799,695,227,197,291,36,747,523,340,172,476,688,964,976,693,794,11,869,107,94,525,732,226,811,34,78,222,381,923,707,62,263,603,346,559,956,558,11,60,390,521,144,941,899,572,266,757,944,127,541,288,420,479,519,851,362,735,333,82,101,683,697,2,696,486,578,241,201,89,146,616,67,482,468,251,873,266,671,650,348,21,180,635,40,431,813,807,383,728,290,3,660,642,958,280,73,337,244,431,5,651,214,644,421,472,538,861,918,703,355,222,708,650,29,867,90,203,767,243,434,434,534,811,378,511,91,477,34,697,726,534,495,987,650,320,581,218,586,964,841,929,207,178,973,71,318,972,818,539,971,524,708,201,465,312,865,230,646,31,693,581,551,52,865,224,114,224,62,586,674,363,171,808,202,77,543,889,934,419,887,541,391,736,346,887,511,340,513,904,800,452,2,417,114,338,276,466,968,91,283,827,445,324,676,274,885,448,746,685,220,709,627,587,697,39,667,521,560,603,208,224,8,578,519,930,647,919,153,723,989,648,819,132,183,550,843,888,928,237,596,59,921,993,880,472,860,107,560,408,359,464,104,410,562,301,679,840,271,18,386,559,861,532,891,565,879,755,389,382,474,465,783,530,728,164,457,420,712,769,54,74,206,2,812,936,388,220,558,779,813,552,602,35,306,451,366,617,742,763,653,669,563,247,14,303,393,453,188,404,190,505,566,477,688,31,62,137,835,178,106,618,901,515,890,934,320,883,484,857,657,597,648,995,849,898,143,832,165,663,538,972,830,514,363,390,34,324,795,733,911,572,272,3,292,474,990,769,183,854,123,537,549,913,97,763,496,236,939,643,412,148,508,200,930,365,930,435,108,545,399,219,63,732,698,465,566,360,68,63,164,351,855,209,646,480,256,55,283,737,978,935,979,377,574,546,196,833,272,6,508,203,524,288,658,984,944,179,611,565,208,303,644,461,985,271,684,477,196,209,149,127,353,176,618,710,817,743,564,850,829,874,105,606,845,387,914,137,181,690,964,928,824,262,3,862,528,135,559,547,451,607,367,614,826,436,539,649,106,139,178,868,306,909,982,633,266,881,288,560,338,452,947,111,259,304,761,238,894,528,869,821,853,878,851,582,732,431,922,434,46,805,196,72,13,321,693,876,899,678,754,149,420,451,626,34,397,563,678,645,727,914,919,88,612,299,54,223,532,84,628,469,94,566,821,919,875,588,825,189,462,530,956,16,864,820,315,134,942,127,810,937,744,47,894,267,377,729,40,482,391,529,918,807,224,181,977,802,970,19,60,961,332,363,36,246,757,886,506,249,267,69,582,630,409,410,971,501,952,780,162,850,244,622,974,958,122,380,508,971,172,933,59,777,169,689,222,643,220,35,453,106,923,180,294,867,669,802,72,866,804,845,249,761,766,435,492,415,384,303,80,401,842,306,595,817,127,329,85,528,479,866,611,515,179,875,535,842,592,313,335,811,873,270,472,674,152,641,521,958,491,669,351,833,353,979,205,731,245,44,316,510,407,123,590,268,801,807,355,354,136,250,656,562,184,456,342,686,853,565,413,931,710,713,800,975,615,217,380,496,492,777,20,357,446,149,12,546,796,768,611,461,454,416,968,54,42,94,91,596,944,512,92,86,970,664,326,515,417,223,316,799,421,408,728,345,266,176,835,679,467,926,38,521,808,433,987,563,6,618,773,825,252,871,809,451,877,925,523,27,703,793,259,848,784,259,391,669,254,997,8,7,385,751,855,682,113,78,967,225,51,923,911,37,957,334,50,83,120,941,566,960,351,191,850,205,777,846,355,787,632,764,239,360,649,170,370,696,88,870,66,735,568,821,285,515,967,832,169,951,799,607,671,829,279,418,799,679,869,153,748,905,112,612,957,469,613,770,972,265,308,295,595,459,524,763,790,218,177,816,895", +"300,732,840,304,198,109,807,542,383,331,851,46,893,496,10,758,463,951,234,296,622,861,71,910,57,924,677,255,412,955,157,332,453,613,346,961,16,603,884,1,77,753,328,71,468,461,371,285,660,757,596,933,491,163,0,150,664,288,651,186,9,900,286,411,567,180,129,469,148,152,858,30,862,57,327,264,807,795,478,700,724,145,811,360,138,870,301,672,109,702,864,175,15,782,801,999,828,740,342,527,334,931,775,504,897,339,744,323,703,988,920,807,743,674,780,295,983,25,575,424,496,669,414,71,50,652,776,781,804,494,628,856,664,315,163,399,551,16,105,936,178,778,287,305,412,222,4,602,637,568,820,754,257,474,817,618,573,563,11,771,78,587,430,987,392,602,14,829,554,981,945,545,569,437,385,431,134,941,39,985,247,402,735,473,505,278,266,668,186,263,520,417,898,267,715,126,730,585,972,732,232,115,996,636,379,285,278,892,932,116,617,739,98,581,17,81,243,190,405,995,787,399,566,291,216,792,673,503,385,205,185,491,535,191,43,370,628,544,83,915,726,42,392,241,934,907,739,888,720,429,512,872,954,188,619,632,51,851,765,535,379,432,170,444,161,463,525,623,4,4,316,414,423,120,498,766,630,605,499,108,953,255,494,853,283,403,568,162,261,888,918,416,2,90,990,963,84,399,915,272,117,762,979,304,63,19,618,833,670,438,373,333,956,3,138,644,295,442,130,310,539,568,925,176,110,957,377,521,506,688,462,690,786,897,55,993,650,174,993,402,543,422,930,263,482,316,182,234,262,138,86,760,528,744,443,565,845,939,176,289,532,883,476,424,321,976,688,935,76,644,670,102,51,498,691,290,132,167,970,130,627,532,194,732,101,385,425,564,511,413,689,466,681,426,474,271,793,794,420,934,922,382,345,970,320,771,342,961,300,954,709,213,727,824,434,431,47,63,281,217,146,578,943,401,412,326,416,758,809,971,898,385,155,958,831,393,618,833,405,737,340,917,563,903,859,688,541,431,160,559,92,648,146,652,533,407,859,17,260,628,59,580,804,504,612,524,417,664,53,597,606,624,549,645,753,387,638,116,777,831,366,163,840,10,700,997,825,688,631,427,171,403,201,101,406,487,751,155,769,400,122,956,171,834,176,119,682,552,508,913,615,3,955,124,281,273,895,647,325,832,432,886,693,857,192,362,629,773,355,320,459,232,476,563,740,645,766,794,704,160,523,246,267,265,345,674,584,51,274,91,112,894,946,231,760,908,163,201,924,121,976,43,354,876,809,597,117,393,858,628,363,413,654,781,720,494,432,50,243,752,426,801,624,641,521,803,262,81,406,325,389,884,789,416,803,643,275,111,520,688,275,588,223,311,307,3,261,914,106,975,758,847,946,621,961,503,703,120,879,192,321,466,532,652,822,265,840,681,287,388,83,166,969,452,160,389,263,337,479,331,108,240,56,921,210,211,410,127,808,380,670,404,130,274,509,564,687,76,288,371,584,20,129,629,271,902,245,19,824,220,834,40,60,515,930,206,878,729,11,498,253,403,46,390,230,979,881,260,23,19,989,169,408,974,187,993,919,912,220,324,762,461,573,420,779,688,193,658,873,845,730,834,224,738,860,17,183,863,797,133,170,603,659,26,719,681,929,324,896,565,851,345,869,16,935,682,753,853,680,428,963,641,479,684,719,108,561,643,592,562,522,431,839,462,389,939,700,136,664,351,164,308,325,466,172,114,238,789,166,266,334,120,701,972,132,438,642,590,61,729,837,664,552,304,104,14,838,41,812,714,70,856,982,822,970,702,664,141,430,306,719,474,145,359,303,420,343,163,67,285,868,402,896,506,414,61,48,202,817,37,813,614,473,943,597,434,96,486,707,844,942,138,648,850,494,541,801,361,81,686,310,585,897,663,706,670,724,144,920,201,582,512,327,706,686,118,686,173,275,880,778,604,112,726,603,704,351,753,653,966,71,687,714,17,826,791,200,846,779,263,52,543,941,315,662,838,165,319,490,735,491,664,235,703,385,921,733,203,846,261,691,825,439,599,691,127,146,414,862,355,315,444,469,804,652,509,817,547,198,857,18,853,358,809,196,598,508,972,376,116,745,477,84,365,927,232,869,411,747,544,735,887,298,169,408,178,102,526,443,393,74,2,508,916,355,101,382,482,639,66,55,425,472,861,204,344,208,546,165,395,296,804,857,798,635,424,78,982,815,394,700,630,313,336,154,119,859,628,382,539,161,423,636,259,143,62,791,574,199,714", +"855,694,451,949,736,36,627,434,406,611,544,140,767,90,529,529,635,611,912,9,712,924,116,71,591,752,734,772,873,183,955,922,121,609,35,959,450,945,930,202,706,735,109,497,50,937,263,939,504,469,12,416,400,331,150,0,645,237,340,118,864,315,648,709,634,385,641,168,699,3,683,300,596,454,693,514,294,442,14,178,55,462,110,910,160,374,113,768,315,491,228,697,168,431,511,321,34,878,703,858,635,320,913,668,439,904,625,105,99,31,570,868,628,182,513,231,699,199,348,438,318,999,24,584,245,895,739,641,503,469,160,448,214,846,391,894,550,629,26,351,426,935,519,426,551,602,129,131,817,634,212,145,381,957,726,789,470,880,752,8,962,831,300,411,72,419,857,28,198,297,203,109,795,960,305,689,842,760,658,103,810,317,494,859,828,176,9,88,288,419,617,24,500,68,502,852,211,78,912,539,640,857,372,153,545,59,71,29,398,614,767,681,338,731,309,755,181,256,837,750,299,864,136,904,358,982,867,437,681,764,299,248,57,538,65,441,803,644,756,978,606,812,319,308,163,774,496,945,715,468,335,353,765,423,463,167,632,144,871,698,423,509,133,251,86,177,295,551,644,24,611,644,642,786,284,190,90,974,14,276,147,353,413,252,730,111,742,833,657,67,356,965,854,295,502,97,926,775,403,681,128,518,522,844,48,914,204,127,98,994,660,434,844,58,744,620,381,715,365,116,438,332,158,37,918,397,712,651,306,342,72,932,267,563,795,917,702,965,885,223,170,10,667,729,142,361,850,716,516,129,930,624,77,113,768,254,550,770,641,591,178,934,391,944,756,916,250,781,786,704,464,16,575,434,35,317,279,845,764,925,210,61,797,272,519,38,509,110,845,960,858,254,798,760,164,613,130,594,161,865,829,696,660,590,61,196,722,718,572,116,665,216,186,901,911,256,483,36,349,711,520,114,773,848,355,550,43,174,257,847,518,298,80,615,106,213,60,407,55,597,559,410,8,228,462,880,350,167,230,370,11,147,620,757,795,938,9,754,60,931,422,730,991,96,713,286,498,142,794,979,653,273,978,806,931,258,127,722,814,508,533,846,961,851,560,716,321,951,572,233,35,874,472,568,987,94,26,258,18,68,79,715,665,183,513,671,307,923,20,16,655,213,851,193,724,305,195,139,115,971,58,481,920,980,231,910,593,928,698,724,922,973,173,998,206,603,195,823,714,593,92,327,410,1000,112,417,816,688,379,155,774,552,474,256,916,299,37,224,948,8,470,661,559,140,558,54,463,574,967,869,640,370,273,633,77,966,540,162,831,567,67,679,167,965,942,225,79,860,757,7,14,755,520,636,762,485,458,253,31,340,918,415,381,315,378,234,97,880,412,168,179,283,498,887,153,145,358,536,190,747,558,285,70,76,658,711,348,941,951,204,778,906,884,395,312,480,439,603,580,440,104,463,818,125,126,268,894,203,106,729,109,412,258,906,15,869,413,233,219,865,385,991,979,479,931,960,442,317,336,305,36,70,543,97,413,445,421,344,626,353,853,173,555,399,105,989,450,231,409,69,771,157,564,672,482,4,662,83,254,100,312,266,848,606,640,364,135,276,161,477,700,727,9,239,734,663,198,504,585,745,428,878,672,588,125,448,349,139,39,953,953,320,120,907,857,686,994,10,527,247,412,524,268,517,293,291,141,483,325,972,844,532,658,670,443,896,208,353,6,901,503,769,309,501,310,882,262,773,405,907,376,460,511,356,888,186,308,234,6,93,456,444,187,10,607,709,847,288,769,189,871,287,183,206,618,756,835,458,989,729,87,190,161,21,648,24,517,250,469,846,557,672,428,77,288,294,818,626,907,595,706,182,676,863,734,193,276,376,363,959,821,442,183,535,835,694,684,192,497,90,622,458,595,230,293,377,796,682,359,538,707,741,947,683,570,403,857,832,536,522,98,359,224,431,509,446,665,583,391,657,343,516,829,414,618,727,260,315,429,814,727,421,86,791,71,639,579,737,72,837,244,847,42,118,241,471,267,97,843,667,498,33,63,138,831,625,275,49,11,253,595,812,261,270,721,26,1,229,770,268,966,938,858,592,605,209,380,82,228,146,902,722,715,23,686,266,379,624,59,841,895,772,345,47,314,830,504,360,889,614,488,939,16,376,887,664,594,327,608,722,495,225,493,229,58,234,743,166,885,61,648,229,200,911,679,472,751,78,421,83,59,435,407,229,9,426,530,51,222,367,306,715,686,504,997,869,336,152,415,816", +"443,278,353,222,352,87,976,948,957,474,945,483,400,624,720,324,601,910,588,4,925,335,674,368,91,167,40,67,600,592,876,645,443,533,73,699,964,713,921,765,32,959,866,4,828,927,859,574,730,633,461,80,320,865,664,645,0,389,702,97,475,182,555,966,340,865,99,86,926,35,777,555,161,257,28,43,681,25,204,407,577,467,146,514,568,390,177,4,636,26,780,462,759,33,295,625,361,83,653,508,76,220,603,451,277,358,292,857,580,134,886,291,236,354,361,932,290,403,920,85,919,591,32,778,886,204,484,677,123,15,6,986,741,529,421,975,9,187,918,40,362,377,173,47,735,883,418,93,293,501,496,73,657,924,144,870,545,219,462,201,26,319,296,617,331,33,897,838,457,177,686,933,504,114,179,342,640,608,362,182,763,231,768,465,654,392,531,685,534,234,114,333,200,953,489,921,641,381,570,452,852,308,752,187,321,647,721,677,93,878,991,235,664,927,396,998,359,120,443,112,34,379,29,127,14,207,241,775,982,796,548,148,56,453,810,361,631,265,803,936,187,880,168,371,89,89,116,215,625,32,828,195,597,208,638,600,383,865,487,936,915,584,136,720,978,309,775,87,347,169,947,658,120,642,534,179,362,401,266,550,426,616,126,724,905,951,416,990,43,260,466,385,406,464,963,747,630,687,460,351,28,675,690,755,328,90,994,87,526,926,138,291,477,280,796,947,87,432,801,403,831,802,221,313,133,806,492,522,543,644,627,117,391,870,938,546,99,11,540,68,164,359,919,357,816,329,303,151,744,260,118,100,929,643,639,428,726,403,989,181,129,287,727,617,287,549,331,757,742,929,978,895,52,79,627,665,408,621,290,568,761,372,785,999,536,702,871,560,13,994,995,784,751,356,22,192,643,554,454,115,553,96,594,166,104,28,692,365,398,943,116,103,962,970,553,446,952,635,615,183,324,911,806,831,647,185,867,457,399,810,17,925,532,117,730,409,405,359,548,483,975,43,337,685,884,920,645,439,144,684,776,768,612,871,896,790,37,6,941,874,45,681,335,224,527,780,451,952,945,620,158,654,749,643,425,937,827,44,227,333,277,648,429,940,716,345,347,157,296,109,230,641,371,358,800,569,909,92,843,154,991,731,653,928,491,244,247,974,884,790,407,294,750,488,989,524,240,442,778,849,865,374,102,205,177,847,278,329,685,454,623,290,150,798,468,342,493,407,198,479,549,809,928,537,672,795,265,194,880,51,146,136,915,897,88,388,657,313,350,137,242,513,557,153,768,254,228,793,756,341,83,427,172,137,159,308,280,503,570,30,32,812,253,341,24,556,480,987,31,279,26,245,27,70,580,965,261,968,53,836,172,376,808,187,910,804,544,304,209,421,462,736,792,68,613,698,591,420,515,203,948,105,290,787,741,489,27,637,94,416,308,343,68,788,743,449,713,457,180,824,404,50,697,511,459,899,58,868,43,696,895,31,869,602,696,355,322,142,539,460,273,526,927,832,443,274,494,953,915,310,297,703,145,680,476,196,672,399,989,425,824,258,317,71,458,914,327,24,714,330,154,659,543,274,404,20,210,286,435,694,395,237,233,936,516,150,786,235,225,647,684,296,913,452,365,805,467,276,328,659,826,846,746,910,407,473,550,958,253,225,521,511,262,41,853,246,510,524,219,167,179,337,106,347,232,846,371,134,371,708,600,75,160,952,748,335,116,716,93,440,546,630,973,105,197,701,365,855,705,140,939,847,483,395,621,450,123,242,107,139,639,658,609,414,150,222,359,741,192,628,426,693,789,271,102,193,529,241,717,108,985,352,550,98,366,601,119,977,286,211,694,765,346,819,346,442,36,62,234,100,261,782,694,677,220,690,858,753,156,287,984,562,590,279,775,775,750,31,130,783,66,248,891,858,379,780,663,868,891,842,299,619,788,904,395,757,447,764,682,154,572,287,292,573,672,757,573,266,822,490,961,63,794,15,829,794,240,733,391,86,980,469,711,169,388,302,291,575,658,70,334,304,936,987,643,547,924,504,862,326,528,985,687,138,708,365,455,912,461,30,616,643,719,585,222,770,498,360,247,529,736,751,85,234,259,605,858,410,591,829,700,611,586,484,657,359,474,523,404,58,691,984,655,895,689,988,583,280,358,667,112,303,734,520,966,546,395,32,648,75,565,817,24,482,813,821,319,762,307,253,651,254,856,87,684,137,503,663,806,860,992,293,593,435,603,655,705,541,242,659,976,702,474,245,62,741,734,255,216,95", +"385,971,402,7,527,931,46,381,187,305,328,755,262,931,343,113,20,245,224,335,802,630,382,12,323,867,640,175,123,912,736,981,371,574,12,532,328,693,2,370,895,145,403,551,534,240,100,729,305,597,343,303,458,503,288,237,389,0,785,532,196,233,290,69,745,181,16,761,876,976,558,752,870,715,742,412,660,396,401,161,814,690,303,193,580,100,968,782,520,223,241,438,148,434,612,319,5,970,559,14,338,577,801,775,119,537,537,940,698,918,231,4,369,465,278,114,41,630,266,460,845,710,947,883,194,737,680,289,655,466,716,767,50,353,158,529,927,231,74,912,29,546,949,826,282,424,201,63,28,360,937,218,699,972,478,1000,307,956,988,982,251,114,969,563,977,939,435,850,323,102,762,987,653,104,14,310,711,565,201,144,570,386,319,237,197,544,755,652,992,187,478,541,39,464,976,774,805,421,374,385,29,244,420,734,297,451,422,453,327,941,864,641,673,726,928,910,411,97,571,229,482,349,565,222,366,126,166,515,403,795,319,307,39,261,680,175,420,318,186,991,586,835,800,152,346,276,314,40,11,495,183,886,536,5,232,4,731,706,868,432,881,587,141,262,258,336,788,378,975,375,756,277,940,320,768,459,812,837,269,760,55,654,683,812,510,443,841,381,891,575,451,689,563,218,588,39,477,60,728,664,489,501,532,560,321,206,523,773,541,787,970,271,770,530,225,1000,697,714,579,625,167,716,775,63,717,951,480,279,425,222,189,191,832,121,295,666,161,365,804,502,904,299,502,872,854,918,32,905,754,963,418,291,75,940,845,524,865,161,479,342,27,324,777,206,844,883,915,270,208,392,119,496,450,465,513,952,722,889,576,34,741,703,282,48,846,627,141,327,833,951,640,80,931,628,901,519,86,481,72,63,582,592,389,835,428,127,183,186,716,645,96,693,413,167,19,804,690,473,694,434,598,488,433,710,18,740,124,207,726,180,980,952,659,930,624,151,269,600,101,205,659,151,95,616,330,696,377,225,254,640,527,917,662,703,117,927,951,625,770,189,445,721,368,417,345,946,346,459,87,379,404,787,650,334,551,964,361,11,680,737,360,866,882,165,845,96,385,273,702,164,676,940,191,690,37,265,362,607,812,589,832,277,535,661,573,625,170,24,917,139,592,908,855,152,481,615,773,582,103,512,145,371,594,129,446,615,533,194,660,694,446,907,330,282,681,508,720,802,401,987,27,40,875,177,717,99,541,739,691,513,887,771,327,500,300,761,569,469,872,259,86,17,449,734,342,887,348,968,767,675,667,468,215,503,304,996,6,289,417,526,923,665,181,160,411,912,735,779,620,856,919,978,580,394,430,220,436,167,474,801,902,233,145,109,229,607,852,891,942,723,66,38,723,806,218,623,722,508,264,399,806,112,285,582,881,460,208,405,103,617,388,303,238,442,259,480,442,182,874,996,36,963,517,601,574,325,210,671,18,541,384,927,49,70,788,193,723,441,434,262,842,685,765,407,305,217,442,967,134,651,829,976,651,300,924,772,120,433,985,842,410,447,598,387,257,322,653,433,357,40,468,183,542,617,869,824,635,380,4,581,592,213,658,974,92,605,740,702,686,432,581,549,848,814,272,512,202,36,691,94,623,71,73,845,425,462,667,210,877,613,709,588,474,520,463,928,177,526,300,647,745,295,703,408,890,855,481,513,364,863,505,104,268,793,819,74,21,772,14,555,365,695,965,905,7,972,128,924,641,832,918,688,17,297,643,599,957,961,465,710,495,959,415,176,156,825,413,428,367,598,636,64,726,269,364,844,242,711,120,959,317,139,538,584,791,801,550,870,816,767,749,381,250,444,675,397,816,245,323,594,207,765,731,678,348,172,343,517,148,904,530,590,156,890,357,390,624,373,498,798,804,21,360,561,883,942,484,724,457,659,16,669,3,730,841,632,273,872,424,123,117,24,637,133,690,150,112,833,901,752,111,462,319,849,329,836,377,703,863,919,282,274,852,131,916,644,532,269,135,683,815,379,129,582,377,985,765,470,427,339,412,235,244,180,270,163,20,363,166,833,284,800,71,61,656,596,357,362,13,904,902,712,561,22,976,238,963,745,912,961,978,643,956,746,531,725,459,531,144,741,532,230,605,944,79,459,531,542,348,271,405,960,322,295,825,825,893,866,921,234,371,109,889,583,171,361,522,74,726,495,176,703,618,741,455,998,765,671,777,923,325,874,938,876,981,268,677,83,988,484,289,896,32,950,867,743,280,501,923,248", +"157,813,539,383,836,779,264,285,738,521,797,879,637,714,818,509,450,274,640,558,585,434,836,513,727,901,368,677,658,48,232,296,767,517,633,274,948,486,719,611,875,736,359,788,94,577,427,932,31,41,664,135,926,804,651,340,702,785,0,143,458,78,679,687,713,746,498,680,280,15,985,569,53,289,244,846,563,150,528,69,31,618,387,557,799,67,926,332,918,585,473,673,690,673,873,632,310,31,326,811,128,758,878,279,608,676,90,920,35,667,980,345,523,166,903,746,456,369,438,949,202,442,676,163,157,722,949,623,425,479,669,902,277,866,356,214,996,704,649,933,669,605,814,492,403,37,985,213,796,699,547,279,897,451,613,305,914,744,681,30,451,633,358,173,1000,824,160,187,770,720,510,373,629,818,486,526,803,556,424,880,303,925,880,353,166,948,910,6,627,541,797,308,103,708,910,423,208,46,606,399,671,864,233,218,812,753,765,815,516,521,779,843,640,515,157,43,564,251,732,151,641,271,816,689,352,964,229,172,579,894,756,763,25,18,241,621,344,899,391,412,770,860,543,209,185,116,377,703,702,403,387,845,285,113,349,41,380,48,779,558,678,266,987,139,953,255,564,850,29,103,319,807,180,57,256,935,71,830,766,360,81,890,44,48,988,19,951,209,925,815,465,680,463,171,443,413,909,940,135,698,759,82,96,884,447,638,773,337,618,978,964,502,947,143,526,805,615,315,701,146,610,806,511,147,485,6,699,213,343,28,184,827,692,415,608,673,978,725,104,107,821,169,120,432,147,101,373,688,848,697,993,106,502,332,399,699,258,208,464,710,499,983,986,683,547,17,486,41,544,812,903,212,286,999,608,905,135,59,652,650,118,177,524,580,441,682,165,378,882,517,961,94,388,844,68,179,780,412,50,21,872,430,109,948,505,973,918,437,14,982,566,196,697,749,857,669,49,470,132,456,920,319,153,740,940,404,363,193,493,11,198,950,505,367,534,464,130,736,145,487,270,248,323,77,11,827,62,749,428,828,547,878,169,28,221,384,652,32,469,966,677,952,656,548,140,441,808,420,558,18,415,906,194,365,883,94,674,721,956,354,92,126,707,154,986,301,238,961,463,303,946,492,716,681,276,383,99,24,3,682,469,569,587,221,856,527,379,905,998,971,71,909,803,527,721,952,239,70,339,230,933,450,142,788,937,571,14,91,571,794,164,425,311,34,726,876,938,896,653,94,336,331,376,517,46,983,699,93,290,52,127,872,552,874,720,311,913,912,393,921,94,550,397,536,364,227,1,777,442,527,334,106,361,895,876,101,78,337,531,255,679,67,107,27,135,272,208,941,150,296,951,821,13,855,347,348,475,515,617,187,453,484,838,822,112,75,786,152,955,918,765,404,948,912,874,392,771,162,740,566,704,71,923,852,305,397,407,928,608,150,289,947,786,918,302,814,308,417,379,878,166,625,560,17,846,259,342,551,137,452,295,137,315,291,888,680,761,726,723,960,632,860,993,236,86,831,676,359,899,406,477,983,89,386,929,295,713,473,640,220,670,726,826,716,320,419,136,436,867,357,557,512,887,843,441,130,81,672,711,609,754,387,162,494,958,475,651,502,537,814,202,499,299,393,590,961,773,483,27,28,10,716,313,653,514,569,701,16,893,855,213,342,499,280,833,59,920,182,554,195,836,125,956,730,354,36,166,64,240,701,271,66,555,322,861,724,10,831,305,797,550,782,941,807,257,804,645,643,460,156,368,233,44,49,68,4,372,476,134,470,423,280,610,255,382,825,328,722,91,338,766,777,286,968,952,175,265,926,877,152,15,832,645,823,587,431,881,830,380,987,234,955,33,825,88,400,502,645,940,994,400,932,10,466,811,696,312,235,348,342,34,592,288,637,49,275,243,295,210,324,114,562,472,920,227,966,409,78,135,146,462,128,482,480,91,266,658,287,278,706,789,925,81,234,868,851,719,124,238,787,926,135,974,980,758,734,120,869,30,551,974,484,827,482,111,611,918,379,676,660,511,458,563,914,364,611,253,307,288,986,133,830,932,640,916,303,536,914,953,452,908,724,810,354,549,917,529,18,318,806,722,977,233,157,624,597,958,20,775,331,43,276,612,791,134,749,203,657,660,884,1,462,508,606,851,858,124,969,13,500,334,224,172,850,605,927,469,70,489,292,839,759,956,405,424,30,151,757,820,626,83,601,683,789,202,789,726,48,834,220,116,2,54,465,842,240,251,866,319,340,869,566,604,518,645,344,942,898,67,232", +"770,730,565,658,911,556,139,492,930,745,300,204,281,44,8,431,955,827,155,419,207,265,308,915,210,265,168,690,25,14,567,286,882,993,805,333,617,424,23,451,793,685,786,167,452,446,343,68,626,405,102,927,37,944,186,118,97,532,143,0,474,892,778,882,708,395,346,463,227,841,694,961,10,49,672,399,236,928,71,180,473,892,306,831,264,29,999,763,361,632,201,213,153,805,974,866,539,707,391,398,151,192,917,7,480,743,833,550,700,76,330,951,566,957,872,530,749,306,570,98,706,85,929,659,440,155,281,849,927,539,547,255,419,187,494,54,144,326,924,665,858,450,500,945,652,65,639,161,24,853,336,434,858,166,199,835,978,404,247,17,708,443,595,916,410,122,444,446,408,586,901,837,837,345,101,284,373,148,382,192,489,690,979,340,702,940,449,585,550,879,770,639,867,840,264,376,6,235,726,376,32,470,633,269,996,550,587,183,730,856,18,149,361,11,718,303,840,219,20,933,653,790,541,869,197,544,58,305,79,289,223,576,572,944,536,478,594,922,233,344,512,724,78,639,170,540,884,84,778,79,743,144,453,898,690,241,409,738,836,389,549,893,216,675,498,452,438,919,594,886,711,391,831,884,18,407,585,236,688,215,299,652,25,739,890,939,66,742,720,541,513,735,782,370,170,511,54,683,771,313,861,67,1,81,293,507,515,683,133,148,497,599,688,950,561,194,587,297,526,847,506,452,104,132,972,934,438,501,628,694,744,366,299,12,306,770,507,679,860,349,525,895,677,47,158,61,91,261,674,175,629,166,459,459,580,621,990,31,665,645,920,240,297,166,610,219,784,882,184,6,993,640,18,294,126,442,286,169,597,458,935,440,156,34,650,205,982,338,947,679,348,251,642,100,658,725,286,775,645,46,677,473,186,569,98,590,143,912,198,15,382,543,125,994,166,95,206,887,823,373,321,455,571,759,265,161,507,476,448,655,145,956,634,92,636,303,461,723,689,43,836,28,443,921,286,664,68,429,398,218,907,171,22,292,367,48,706,293,861,618,679,503,309,443,788,639,720,866,62,748,583,505,851,376,266,621,542,590,629,389,957,101,666,724,61,666,437,685,833,44,738,728,83,930,28,550,622,657,135,26,335,570,985,702,69,854,395,709,202,841,260,606,442,290,536,589,310,494,617,837,986,914,282,679,391,80,125,699,935,406,408,574,313,848,227,949,587,986,597,409,626,789,174,124,390,808,373,177,158,979,631,530,264,253,567,880,804,911,544,649,288,59,454,228,641,738,592,964,861,445,806,951,880,819,526,150,539,448,245,669,111,490,925,52,65,797,608,396,247,37,839,525,579,409,739,962,766,409,355,200,462,947,678,954,833,605,531,537,227,440,706,108,395,555,881,556,747,28,263,536,652,867,231,120,658,333,517,336,906,272,318,904,127,651,256,108,453,951,745,980,486,246,138,770,701,614,14,686,593,503,410,994,304,984,535,648,84,50,703,528,639,155,400,378,864,862,836,654,891,997,112,21,541,360,701,239,749,170,74,327,171,672,374,711,640,776,875,832,918,418,903,209,503,930,274,569,300,422,684,244,165,505,901,102,998,72,547,504,309,67,157,964,822,184,879,513,596,769,728,38,739,162,782,575,777,159,73,226,408,527,717,731,112,32,137,199,129,522,978,505,159,496,366,795,442,369,750,57,382,271,197,777,223,749,672,133,411,151,682,843,675,514,163,676,872,988,236,751,244,703,998,765,736,613,561,100,817,81,34,35,469,819,953,62,865,888,833,73,245,31,381,428,173,599,698,633,202,658,244,551,779,98,425,368,16,861,818,688,914,898,937,908,473,571,59,205,401,940,866,620,518,510,65,828,691,941,802,66,985,475,792,833,49,993,892,630,369,234,987,896,546,733,236,374,873,473,388,439,963,967,835,420,728,898,81,304,148,924,607,848,700,314,965,228,351,837,974,672,351,509,248,932,497,659,22,690,504,437,491,956,145,110,995,50,265,720,391,158,662,131,520,431,691,307,170,859,402,420,614,621,845,237,148,943,207,656,748,329,189,61,29,841,369,265,358,645,948,138,498,555,588,311,936,253,293,352,928,111,343,887,250,814,440,194,285,770,268,213,498,327,348,22,916,820,110,330,821,361,723,16,743,338,776,319,132,482,779,879,891,184,798,256,256,184,109,562,986,385,781,216,828,895,374,174,91,570,830,490,15,951,154,121,508,769,97,795,583,799,502,649,530,360,652,332,788,288,468,55,571,469", +"29,589,562,89,443,782,974,768,945,991,43,434,979,118,865,992,448,124,46,182,301,90,277,810,537,581,156,544,157,777,492,786,808,519,541,241,440,981,701,992,422,678,574,73,300,911,591,722,434,468,343,358,841,606,9,864,475,196,458,474,0,791,289,974,149,803,336,442,841,606,101,621,223,780,507,550,948,226,847,820,671,305,898,191,253,860,864,652,188,85,573,33,521,341,275,682,697,830,840,928,603,740,311,26,8,40,154,952,387,712,211,645,321,749,128,313,142,513,590,839,453,376,659,954,989,346,859,269,978,470,738,815,818,264,490,418,411,939,842,240,849,430,735,475,377,300,149,830,710,577,574,535,923,772,253,902,306,657,561,137,842,603,358,40,282,102,813,684,227,268,595,387,453,75,798,379,404,226,268,525,553,79,92,153,310,797,36,523,495,88,353,521,370,545,778,318,504,946,428,707,711,612,85,81,571,91,818,344,916,724,356,520,863,77,633,446,606,867,312,884,805,358,243,22,888,986,405,332,989,912,80,274,441,727,416,7,783,925,398,65,885,763,419,660,373,769,768,452,887,414,301,202,34,240,984,800,192,44,178,743,112,576,988,924,597,684,681,146,778,612,342,667,336,842,797,943,943,191,739,897,815,269,166,4,108,87,992,781,186,279,121,534,291,10,942,855,140,347,280,316,908,826,125,374,308,116,899,527,913,524,25,965,164,702,362,778,159,859,728,494,473,893,400,916,668,409,57,437,426,570,914,894,468,66,673,391,297,913,149,158,118,514,866,280,105,495,594,718,732,849,99,398,393,240,575,14,447,94,513,359,615,602,633,578,152,828,19,965,623,212,301,199,849,257,306,786,241,434,982,311,795,947,249,764,4,835,48,563,574,611,951,370,769,877,750,87,181,601,638,703,474,905,808,116,450,676,873,258,575,687,404,277,693,924,187,725,334,854,210,579,339,884,282,336,653,432,627,906,13,791,542,494,688,298,887,132,103,611,905,246,406,254,696,418,921,310,395,674,978,776,777,374,982,395,523,149,933,657,400,559,842,29,525,162,867,872,383,738,32,37,814,833,489,788,15,927,979,932,170,249,323,994,46,208,376,890,322,241,181,874,855,475,97,246,816,99,407,996,759,477,293,264,428,438,904,16,260,600,944,452,330,68,645,180,151,93,115,811,962,375,113,456,634,320,119,679,3,327,678,589,410,347,477,17,138,351,108,240,770,65,327,704,126,552,470,887,304,505,885,850,250,400,354,464,500,150,647,971,496,98,289,450,182,167,76,604,434,225,875,790,192,457,896,932,558,250,893,982,941,47,738,512,300,745,684,634,264,265,632,676,730,880,187,142,704,383,255,101,195,363,900,235,549,524,259,835,961,983,97,771,253,50,662,880,309,582,308,493,216,166,194,889,610,899,799,735,506,482,103,373,711,71,503,744,765,229,9,74,154,304,130,563,271,938,449,669,431,569,957,53,541,879,446,351,283,531,752,578,332,527,513,593,996,137,637,603,308,839,341,850,797,43,803,96,635,111,549,481,108,865,649,878,191,707,352,214,43,883,430,917,316,230,580,944,65,875,503,358,665,92,528,29,731,252,87,586,462,730,475,484,208,91,552,144,528,272,364,328,440,848,909,163,329,681,259,122,34,291,311,570,860,521,187,685,566,201,882,761,293,722,434,883,597,538,173,369,725,760,604,350,552,944,464,8,280,188,59,182,308,345,675,284,891,54,368,938,166,600,15,968,389,364,718,286,946,223,307,183,387,571,996,448,183,411,263,497,405,784,196,576,211,526,853,657,287,115,262,114,785,860,254,674,95,245,494,134,390,748,430,830,941,768,590,118,477,278,896,500,737,490,303,528,968,648,415,624,552,79,143,241,591,746,681,455,361,759,197,15,59,336,663,515,736,407,964,503,854,549,863,693,323,798,648,948,479,51,740,384,917,685,955,953,560,385,787,443,790,623,366,120,911,598,181,919,42,147,6,691,915,874,669,110,499,632,271,464,717,672,945,320,937,631,20,645,8,546,957,392,269,73,986,98,49,843,84,181,401,567,338,959,860,860,459,731,392,333,546,307,413,458,784,859,735,924,567,415,786,779,985,406,966,17,830,358,102,527,831,892,353,711,834,557,534,654,465,78,101,619,888,662,802,609,605,431,92,525,662,841,461,744,619,516,824,268,959,560,511,286,960,489,991,341,850,307,181,915,545,831,104,881,536,930,317,579,250,923,301,296,574,979,576,931,440,165,448,186,299,796,128,342", +"97,978,424,188,87,393,339,785,404,195,899,514,87,891,416,697,809,507,208,611,445,699,187,455,641,739,661,857,550,968,30,838,573,46,909,510,43,809,861,42,661,902,682,421,576,730,541,984,987,844,365,213,201,503,900,315,182,233,78,892,791,0,234,465,805,969,292,980,982,742,792,352,781,175,682,857,549,758,270,740,76,280,471,374,415,259,524,635,97,241,677,866,824,905,667,952,341,224,66,229,902,333,837,99,49,565,893,817,58,819,769,1000,273,136,478,373,948,908,807,788,722,477,588,432,56,8,245,347,926,80,734,78,553,238,860,248,653,229,852,873,110,123,267,781,621,949,368,667,36,339,692,374,513,388,14,383,918,908,462,80,877,144,111,306,692,334,357,239,873,901,691,97,783,815,688,208,842,25,583,574,92,284,724,62,836,946,834,400,761,37,119,272,647,442,814,679,765,712,348,756,299,758,110,968,570,518,504,998,682,297,339,487,53,107,629,562,856,450,122,64,48,768,190,332,131,562,450,484,834,318,63,245,745,884,963,714,688,83,901,181,848,957,894,561,253,119,113,105,498,262,223,787,191,971,153,9,534,112,247,964,702,542,694,997,11,575,896,230,345,76,341,714,375,104,341,201,914,653,155,71,709,604,658,575,739,382,359,582,538,691,547,468,588,300,106,519,775,277,517,160,480,118,945,363,249,989,539,997,132,264,515,605,741,578,213,675,202,63,868,998,534,143,229,55,340,687,460,410,468,251,804,124,93,529,491,667,69,174,48,671,58,878,182,848,720,671,327,606,453,832,768,926,196,928,889,463,558,248,92,338,243,13,626,990,482,456,621,772,863,476,245,19,645,843,92,614,99,959,904,51,763,753,864,159,412,322,543,812,990,336,822,626,69,654,63,513,806,575,613,350,368,349,133,352,184,583,543,936,145,71,698,966,271,212,638,544,84,406,349,532,348,898,687,382,954,926,477,5,34,313,460,119,112,563,554,458,329,371,247,316,938,668,102,690,46,363,258,600,159,38,219,167,282,159,13,393,304,590,770,375,958,977,284,921,576,406,209,734,727,987,425,846,131,253,393,682,609,838,450,312,795,385,865,73,714,256,464,280,469,181,824,323,729,405,494,667,451,168,323,743,305,439,593,21,886,702,820,764,806,469,993,584,124,294,408,59,290,267,451,530,589,753,613,497,631,652,832,648,645,33,476,665,715,613,446,548,57,746,326,118,903,358,377,44,105,165,24,779,660,609,691,635,265,87,304,373,60,256,437,134,199,349,704,890,710,534,985,602,870,305,846,423,771,603,893,252,596,339,566,348,712,518,842,759,11,947,437,250,510,410,823,552,181,357,911,546,366,225,179,669,268,479,230,24,700,426,887,536,990,935,816,471,908,681,304,915,793,220,837,654,588,721,248,801,571,258,853,772,164,322,474,314,80,750,264,945,884,485,428,29,920,889,826,322,512,735,90,834,5,206,723,526,592,921,903,531,809,636,441,726,640,507,656,138,305,58,152,410,454,423,4,429,86,669,151,181,746,888,293,969,983,977,696,643,155,992,721,994,557,291,71,791,638,304,366,518,687,929,530,656,86,863,314,383,713,134,720,110,90,594,276,421,908,819,607,431,300,547,340,904,273,799,426,70,911,951,365,171,644,576,210,370,214,143,408,892,555,35,921,76,367,900,72,998,602,821,952,410,503,63,856,47,902,70,671,74,546,869,891,577,508,358,817,827,37,298,542,372,237,80,761,329,420,590,87,132,23,36,314,800,290,296,271,316,553,2,445,256,918,873,877,954,746,473,980,346,47,976,350,441,186,526,26,171,730,208,645,380,550,7,348,277,247,384,375,931,270,608,592,860,901,505,388,353,41,539,848,804,559,990,32,818,191,181,578,350,692,23,88,277,802,417,269,121,743,625,924,513,953,564,76,464,601,892,679,805,266,850,4,689,70,277,779,92,645,848,11,81,676,527,634,713,538,4,105,840,814,82,906,499,165,372,858,816,695,876,407,651,912,866,158,323,248,898,524,574,190,38,956,208,427,745,984,899,138,876,427,22,488,777,260,149,976,555,765,561,399,25,35,476,965,745,924,982,513,900,493,424,967,194,881,293,341,246,566,469,338,635,353,565,725,222,401,382,367,322,188,320,593,633,953,940,347,786,613,42,175,976,976,374,414,905,652,332,688,353,857,366,226,579,212,754,298,6,962,789,75,138,20,7,435,148,899,795,644,755,85,2,378,423,68,616,992,164,721,948,766,82,111,863", +"229,214,973,122,176,576,715,292,533,227,845,32,554,255,795,80,805,726,705,5,390,838,821,175,54,891,579,607,202,274,241,389,42,217,534,709,730,67,760,846,77,215,838,90,642,121,42,385,994,833,762,286,449,596,286,648,555,290,679,778,289,234,0,712,545,46,26,566,549,393,476,824,79,281,471,847,614,977,742,537,463,94,242,423,60,657,177,566,584,830,849,879,659,451,334,493,529,234,837,970,913,312,195,637,18,156,11,913,15,907,844,825,672,180,969,879,609,894,246,662,317,630,920,798,343,492,957,707,194,475,680,990,450,338,374,768,96,649,610,597,612,898,859,502,420,39,144,290,302,797,837,442,90,54,514,250,932,951,500,882,13,497,994,568,194,252,687,298,174,552,78,419,117,431,227,306,399,139,538,694,598,816,877,166,953,738,334,381,613,428,794,415,381,401,743,645,904,468,427,141,16,995,878,439,707,944,721,880,906,771,682,864,136,648,674,27,817,901,892,501,797,267,34,964,589,289,842,359,60,980,671,881,330,882,916,688,807,613,83,444,24,325,969,230,853,747,350,758,724,664,287,900,474,91,235,879,557,499,601,891,494,387,977,513,122,78,725,800,52,266,621,87,527,37,375,635,333,268,656,727,262,708,642,611,600,136,600,408,658,962,627,992,660,158,987,90,493,234,737,866,61,193,847,916,813,145,697,458,924,968,331,872,174,330,485,403,856,130,397,245,894,808,629,270,660,884,365,718,304,176,996,657,156,611,586,862,813,484,226,629,508,870,450,454,117,138,468,691,264,155,895,593,464,747,414,481,389,880,833,46,305,496,858,834,561,127,158,95,636,183,776,553,858,548,635,957,653,123,352,824,545,252,58,460,996,697,329,250,906,632,606,844,337,277,399,488,726,456,81,316,139,377,99,549,864,838,69,104,830,409,376,681,991,582,347,422,380,928,307,268,231,980,490,886,453,300,454,273,403,634,697,504,221,668,576,644,43,556,275,696,46,848,366,357,416,504,122,282,580,714,893,108,776,799,734,807,998,319,18,748,544,812,557,409,141,984,209,434,234,955,788,916,137,739,596,642,597,147,55,266,198,253,295,427,134,369,196,867,470,179,705,173,874,199,692,380,575,307,44,925,286,134,997,111,80,759,819,218,857,805,196,644,442,55,877,386,329,770,377,986,39,385,320,162,695,87,102,343,483,905,280,24,646,516,460,744,244,399,78,781,202,818,216,148,421,229,29,926,22,633,801,942,970,510,890,182,103,490,559,46,719,442,773,767,804,194,297,81,760,490,953,522,614,843,68,416,286,150,687,719,361,746,23,967,86,150,25,709,304,522,559,946,821,526,548,640,763,206,833,542,467,278,231,544,536,746,258,750,122,840,622,471,18,481,657,925,297,111,263,501,688,129,980,990,824,564,339,12,232,828,649,86,9,317,890,566,944,543,84,517,322,73,329,50,504,942,594,227,14,658,284,51,738,391,717,893,870,217,616,583,759,581,46,302,71,149,271,992,446,726,327,471,417,291,432,102,726,937,646,602,847,873,564,75,414,289,759,930,913,91,136,220,946,641,751,345,256,349,564,887,761,653,42,422,260,819,583,790,756,884,464,687,505,442,562,776,634,399,491,147,561,844,219,905,294,345,283,383,533,929,456,62,950,225,86,821,435,895,426,599,563,712,926,22,640,812,266,589,529,69,552,857,580,894,132,859,495,418,189,324,356,269,901,842,499,565,818,77,575,563,38,87,602,66,36,96,581,204,28,582,538,120,322,884,760,933,211,549,144,61,802,470,867,873,755,715,419,9,509,351,731,44,134,448,754,829,402,255,137,284,638,816,399,256,314,62,609,621,608,491,35,450,137,23,413,354,519,304,25,213,175,952,774,972,115,846,356,637,295,236,546,109,240,545,205,636,501,122,688,601,979,861,27,530,927,560,701,737,760,379,806,211,673,991,932,870,528,710,369,856,953,999,61,742,695,158,552,856,163,936,382,505,955,974,99,872,480,551,832,951,496,736,909,592,912,256,594,122,884,298,425,312,34,819,785,960,205,127,600,54,566,142,70,567,690,165,51,69,984,988,331,338,101,658,270,327,596,375,747,220,434,758,613,269,940,552,828,967,929,84,342,475,171,418,457,768,705,131,728,835,397,670,777,606,692,770,153,576,603,349,857,419,799,486,132,704,309,193,174,369,881,567,647,475,82,151,218,64,610,386,111,92,521,615,530,961,748,826,171,625,692,331,638,118,382,20,923,53,273,439", +"734,629,187,919,376,675,810,660,218,791,307,906,476,22,542,283,954,978,846,695,678,363,18,3,493,25,260,617,615,799,888,175,862,328,304,631,703,431,289,387,655,835,848,402,695,10,786,833,786,882,658,258,112,459,411,709,966,69,687,882,974,465,712,0,739,89,31,583,342,766,330,753,614,371,646,418,50,260,811,127,182,446,71,913,538,225,789,357,728,51,758,732,22,89,820,376,600,610,91,6,163,365,546,569,448,195,574,259,557,91,44,2,916,523,369,321,783,24,670,699,985,414,959,751,196,538,556,593,310,321,361,985,620,479,283,681,436,8,585,383,948,417,492,906,218,533,332,878,185,603,400,543,798,232,325,45,391,833,27,314,471,276,403,659,87,496,644,697,154,878,141,711,822,924,27,944,106,620,809,530,92,899,632,955,22,856,599,254,38,98,787,58,132,737,374,310,612,550,802,240,121,314,682,618,473,911,395,733,139,599,424,986,358,308,593,969,167,560,82,322,386,513,9,696,923,549,992,827,670,756,439,203,312,566,170,848,911,387,238,484,707,553,554,457,860,981,452,597,299,262,587,796,114,553,808,530,171,204,914,333,462,440,569,742,825,170,860,593,318,784,386,918,649,145,327,279,97,478,528,510,819,78,563,151,724,143,549,67,646,323,700,87,139,460,716,123,926,801,638,652,955,129,143,542,327,336,196,464,432,952,556,129,199,137,555,499,612,612,846,316,665,64,825,118,448,106,945,864,32,753,155,5,810,449,761,374,925,712,578,314,339,612,296,878,861,213,260,419,369,75,304,460,952,273,519,290,311,429,733,202,875,867,918,236,483,345,38,572,272,864,425,486,186,938,295,579,574,866,356,169,897,809,167,289,383,68,236,96,552,701,710,97,461,8,402,866,880,642,920,707,889,208,260,749,563,590,361,142,601,256,811,567,679,58,404,981,23,659,28,815,386,855,131,261,787,197,254,827,572,666,575,365,305,361,280,440,659,732,615,66,511,494,120,248,678,504,476,956,910,924,742,90,49,890,434,537,327,90,579,886,228,377,606,18,136,798,138,747,857,925,683,465,529,739,32,334,487,241,904,6,744,700,851,5,874,865,515,45,186,154,326,206,214,668,354,732,468,563,862,512,182,272,787,90,726,891,637,875,959,388,691,318,541,191,888,23,602,624,929,866,300,426,638,415,379,826,226,671,794,980,624,459,900,495,42,844,359,543,109,137,100,429,480,928,545,858,369,707,526,809,700,968,149,853,778,425,345,938,581,889,330,484,377,86,671,970,728,726,548,558,97,798,34,834,934,787,890,557,680,12,773,489,878,384,614,623,333,152,675,746,776,3,417,751,803,531,684,45,196,537,295,641,425,570,677,194,658,449,351,241,660,893,631,91,92,330,296,488,754,713,989,144,247,34,673,277,386,415,310,787,930,592,450,652,486,664,970,701,317,230,704,397,162,496,579,460,133,348,826,980,112,993,69,387,328,28,972,67,469,970,242,29,62,959,269,378,606,967,443,329,607,357,947,486,201,653,305,445,461,887,630,462,944,118,211,337,587,333,736,913,505,340,781,163,658,547,146,702,243,688,19,196,587,719,241,77,66,582,30,669,853,382,962,255,348,351,890,310,201,897,346,169,595,596,281,80,67,65,441,319,450,282,695,422,620,610,181,602,927,947,450,388,949,223,357,605,182,250,440,102,790,472,123,516,174,159,317,366,596,81,855,11,861,61,14,512,340,986,842,676,900,112,22,847,574,645,329,593,503,899,149,130,173,109,312,262,863,88,593,915,857,778,647,987,130,85,138,422,755,199,934,894,149,686,63,250,635,670,135,479,846,724,732,75,11,743,254,350,498,240,543,712,245,652,565,862,48,185,643,561,667,100,812,961,753,984,945,667,910,147,410,165,116,245,297,236,937,615,421,183,983,380,957,179,711,50,228,609,190,828,336,990,259,913,289,214,303,943,445,868,261,29,265,705,568,865,330,679,904,686,575,618,868,473,643,110,815,970,558,877,332,882,191,11,615,66,664,446,15,585,252,172,665,728,64,719,576,663,364,399,328,495,437,898,495,318,672,895,152,669,707,632,976,311,101,882,825,117,906,271,365,65,190,399,367,235,434,402,881,901,879,638,517,500,747,410,783,4,953,372,367,821,245,79,568,642,59,522,235,140,201,279,797,169,879,643,716,874,329,86,124,748,378,134,486,345,399,102,715,491,863,925,985,83,64,279,762,551,181,998,724,337,782,546,13,190,272,163,607,446", +"829,781,553,600,531,456,819,971,244,853,420,660,847,446,26,626,160,615,944,103,550,740,426,589,515,734,273,767,371,314,678,673,473,427,818,550,481,167,366,568,499,136,727,435,641,666,982,142,590,61,710,314,87,776,567,634,340,745,713,708,149,805,545,739,0,808,797,627,19,445,180,328,617,876,310,901,870,922,11,738,770,914,728,195,986,869,457,253,698,536,710,600,594,966,967,381,729,5,209,745,93,86,155,492,143,117,864,902,479,842,215,399,249,326,697,410,58,578,467,450,275,955,520,18,365,803,861,240,133,74,51,872,617,317,385,231,996,279,751,857,635,994,255,386,83,124,545,585,979,27,122,245,84,376,727,389,169,939,26,9,113,917,1,27,132,472,939,246,334,184,928,343,179,406,330,844,574,798,373,9,777,505,355,907,641,714,13,397,742,600,190,941,820,336,19,319,607,576,349,254,923,947,590,175,551,106,509,440,69,131,297,569,198,601,680,191,209,371,41,847,104,945,329,971,872,467,374,37,760,197,114,343,404,101,814,223,505,7,419,792,954,971,779,759,331,24,579,251,713,321,972,583,690,706,373,937,1000,678,413,242,4,941,625,204,884,372,985,696,4,15,983,551,984,632,352,745,122,667,957,13,769,35,539,288,396,707,7,775,365,410,2,351,127,998,415,108,954,693,523,877,640,63,383,354,71,772,772,607,120,398,765,82,590,170,650,441,238,995,993,717,610,564,350,246,850,815,181,230,554,392,685,450,180,129,92,86,914,91,298,352,462,111,182,116,802,59,139,68,62,504,603,8,931,549,663,886,730,789,818,938,556,301,83,208,692,896,331,46,553,722,687,756,990,504,723,6,906,879,877,32,772,154,39,321,111,227,67,366,462,212,29,986,741,976,209,115,992,136,478,637,757,930,57,505,784,213,735,707,910,915,163,896,710,7,651,870,637,151,967,712,248,791,47,364,453,359,865,303,979,450,901,884,759,10,863,260,235,119,454,134,681,771,520,369,580,770,163,516,58,44,194,842,923,987,425,306,210,114,387,345,283,632,406,769,676,143,457,75,890,192,73,548,574,815,612,365,717,779,191,984,747,313,709,55,917,409,852,858,210,78,904,757,943,278,488,386,930,926,472,3,528,157,245,766,754,326,747,907,35,624,841,188,345,251,911,901,799,618,955,437,382,233,9,679,129,519,859,348,350,625,415,175,6,6,330,468,163,618,555,327,971,498,494,948,320,239,745,278,103,509,945,773,828,313,309,984,845,128,764,506,625,255,865,797,323,196,995,390,36,308,24,258,690,542,759,461,719,170,347,253,590,79,349,783,249,693,589,222,802,679,23,90,704,361,450,118,194,391,27,517,375,461,527,562,50,783,792,286,23,406,183,386,980,908,379,558,415,764,950,580,692,330,325,83,461,66,655,509,129,818,571,439,598,269,344,848,275,456,332,402,228,853,769,354,73,381,915,774,133,360,783,670,101,411,794,951,149,280,113,555,507,515,193,39,447,488,787,980,589,643,703,383,106,803,969,401,982,773,848,768,865,683,939,793,155,743,673,970,168,533,106,70,743,641,348,665,389,585,70,583,469,104,129,117,991,843,834,310,235,66,597,300,82,809,322,662,233,857,441,466,70,625,20,177,418,380,919,856,65,269,554,495,808,584,724,631,952,407,870,773,388,706,809,374,846,502,769,356,802,720,579,52,910,918,58,468,575,85,806,868,199,848,879,767,76,451,681,476,176,146,606,942,441,233,548,536,68,352,445,908,234,244,906,948,624,284,399,218,442,441,104,572,526,138,397,344,501,604,168,166,579,213,808,139,227,238,813,755,297,363,18,37,142,207,554,930,262,601,812,654,621,637,699,825,972,137,811,576,962,40,428,569,725,481,596,476,394,555,887,188,623,433,851,323,310,467,467,417,946,445,294,612,8,704,537,554,727,985,263,158,362,114,181,564,339,190,753,103,794,11,11,993,507,31,253,764,235,199,965,638,483,96,637,933,382,896,92,764,127,295,843,82,649,384,302,687,694,783,382,744,571,527,954,113,409,209,219,920,375,973,306,344,303,297,217,243,193,259,988,916,404,851,547,205,408,326,819,490,590,363,263,831,973,982,474,176,484,98,886,380,921,120,591,221,573,240,522,569,822,280,952,383,710,813,111,860,450,828,687,157,920,923,280,146,931,891,737,538,915,718,571,277,632,377,845,609,77,6,773,213,17,522,473,770,803,376,396,559,826,487,239,482,130,258,219,554,335,355,584,5", +"324,358,859,45,656,939,945,74,681,739,634,831,195,569,225,159,645,539,668,414,584,377,800,602,412,46,700,644,574,56,871,803,453,435,730,340,131,780,519,305,786,218,170,989,548,706,982,311,488,303,988,313,780,297,180,385,865,181,746,395,803,969,46,89,808,0,405,196,872,53,810,342,341,40,31,677,390,974,42,361,27,624,334,893,32,603,38,414,588,33,126,437,142,337,40,161,737,188,374,215,817,33,532,37,221,738,37,77,498,519,129,809,396,904,92,642,819,199,920,900,47,848,2,564,416,123,103,955,907,745,929,297,902,920,694,47,703,285,905,226,977,449,73,28,173,403,620,459,175,227,52,173,37,67,190,54,751,944,813,23,128,458,988,340,853,317,456,55,538,541,309,465,466,107,16,847,675,551,109,906,119,971,551,615,943,450,617,175,900,639,549,386,39,350,197,552,322,14,383,904,173,889,443,312,163,53,129,636,289,395,362,485,934,96,135,393,50,827,660,460,414,88,253,796,501,437,67,662,968,482,479,285,954,587,479,312,983,667,366,38,291,333,818,158,201,658,546,915,427,737,744,612,694,482,303,540,84,740,442,330,812,979,976,12,574,887,934,135,526,349,149,957,399,891,429,496,178,488,619,91,965,669,294,561,267,13,414,419,551,784,315,767,34,591,284,263,489,228,619,684,729,697,97,324,696,715,386,271,251,17,29,186,249,642,241,320,836,624,809,629,538,552,731,675,693,76,831,734,680,821,468,916,307,743,142,465,551,784,80,302,546,665,408,804,738,134,350,429,600,988,527,827,279,197,543,7,223,548,828,714,251,567,578,413,272,600,901,333,993,429,995,750,936,341,261,546,66,726,995,682,755,225,422,306,106,600,603,199,808,329,961,187,403,725,300,329,635,825,676,133,545,938,295,438,652,458,891,900,38,702,895,748,758,719,769,248,32,216,498,972,701,783,610,753,757,734,426,707,475,568,119,869,525,455,652,695,228,381,409,878,218,895,427,363,825,791,655,454,874,790,791,84,711,391,242,294,921,650,549,908,774,846,56,69,633,334,787,22,610,814,682,504,312,581,16,988,318,331,571,909,124,650,880,201,554,297,439,285,978,550,723,636,692,188,617,949,742,594,49,826,354,616,365,662,862,488,241,895,857,436,268,813,55,751,89,415,446,579,626,871,787,862,625,162,54,324,141,211,420,728,104,695,182,865,9,871,645,439,561,321,752,452,103,269,836,1000,644,307,625,403,747,434,725,6,608,744,568,895,505,856,917,300,166,280,978,393,153,556,769,254,125,842,62,333,171,455,282,422,750,274,218,130,170,900,989,917,154,308,104,279,816,606,597,430,41,598,642,483,190,827,224,273,897,862,769,772,198,55,989,974,129,747,491,822,822,80,833,604,152,127,870,33,783,237,822,678,523,444,653,53,317,630,756,955,378,1,492,655,22,30,247,649,906,257,516,128,723,574,480,546,406,429,529,896,894,221,151,494,998,482,655,86,366,536,644,222,904,767,186,436,80,756,129,436,536,405,94,479,513,753,302,486,396,453,649,444,324,613,395,663,293,775,679,340,693,69,476,638,382,274,947,948,221,998,214,148,451,64,186,620,441,29,778,246,94,894,41,417,519,845,734,302,703,375,906,390,871,733,313,967,606,832,656,71,752,692,873,596,468,529,708,893,365,170,171,705,520,187,920,715,395,569,763,148,621,321,323,49,783,797,442,541,403,590,589,589,171,595,971,999,964,708,198,282,296,280,158,428,210,393,996,127,336,805,723,842,656,380,597,164,372,308,770,901,50,221,117,728,466,150,294,533,515,823,719,755,306,788,249,888,83,369,662,79,710,102,823,577,921,91,298,352,234,919,297,263,789,626,855,964,941,649,774,353,817,92,847,794,527,591,115,420,860,536,651,979,328,567,973,525,725,226,396,452,818,606,120,808,206,259,985,362,990,851,102,666,523,691,486,530,251,607,142,122,31,38,250,101,272,449,929,871,993,786,646,50,996,199,836,357,210,430,390,825,149,752,507,877,442,162,967,111,241,324,922,453,150,56,821,740,224,699,998,954,342,904,771,426,588,77,434,233,801,290,396,194,422,459,411,425,939,850,290,20,733,429,830,363,958,156,259,819,44,25,923,232,545,829,212,58,893,528,129,289,758,289,478,2,408,299,170,123,838,233,47,508,603,552,244,2,249,287,213,157,526,828,555,178,653,347,344,106,57,16,670,204,235,654,296,48,912,710,911,552,522,873,872,22,903,597", +"917,941,381,473,959,788,897,410,924,158,460,705,19,488,147,963,63,989,919,217,783,333,223,871,568,598,600,882,461,563,753,246,891,133,355,107,94,782,158,771,700,592,867,509,157,829,776,526,994,311,143,386,969,349,129,641,99,16,498,346,336,292,26,31,797,405,0,901,681,982,797,778,461,609,445,24,668,1000,786,31,410,833,203,120,723,521,677,28,567,924,439,754,263,437,888,956,152,439,258,274,845,682,987,559,160,779,729,819,155,609,967,641,706,669,285,115,458,522,55,249,966,667,122,267,518,546,563,401,291,993,535,876,294,254,691,616,284,114,706,585,921,743,739,139,732,215,276,420,388,226,346,586,186,560,598,54,648,802,956,273,165,350,929,391,109,121,570,560,745,388,323,461,635,561,989,519,69,349,22,348,725,181,447,115,579,854,818,700,972,305,445,253,163,243,904,595,850,814,174,379,627,401,552,42,171,766,664,132,853,426,633,258,933,225,101,686,715,984,257,343,987,755,704,732,392,271,513,777,275,501,852,93,32,652,873,314,247,212,690,439,786,89,297,502,375,534,722,826,224,764,302,198,660,726,805,186,589,801,158,89,564,432,437,624,589,181,916,11,601,415,692,290,893,347,810,607,917,529,344,531,879,443,606,676,252,993,244,994,971,843,22,946,801,157,658,899,731,416,340,802,742,278,606,241,428,846,110,584,269,921,470,125,203,849,406,957,663,995,980,112,342,783,828,448,605,956,439,564,439,976,32,198,109,310,648,985,627,995,572,574,560,385,166,239,671,481,431,193,95,684,546,507,116,370,301,831,780,847,747,651,410,904,184,193,861,661,921,761,828,821,676,61,980,917,729,324,42,952,516,321,8,600,941,245,376,663,186,320,318,886,723,291,986,480,126,492,77,198,787,820,672,95,353,967,792,456,924,364,951,619,973,205,434,194,131,228,114,965,57,33,876,259,965,674,806,876,461,191,880,405,20,747,453,13,415,946,919,496,946,357,982,507,392,697,558,913,442,254,109,973,7,495,657,675,846,578,447,726,954,711,652,815,444,187,890,744,165,660,112,910,713,96,832,409,417,312,222,832,227,57,364,751,43,194,680,120,712,703,655,597,930,259,755,478,829,373,294,548,490,765,376,122,167,328,363,863,351,502,801,627,100,779,498,939,590,486,185,407,260,315,723,871,108,593,290,373,253,826,791,355,409,143,957,806,381,866,246,563,49,847,606,201,957,502,976,128,463,223,797,203,785,446,444,627,731,379,892,119,727,423,877,426,968,767,854,365,125,138,593,635,436,503,318,618,38,421,988,852,294,864,311,624,724,281,310,262,9,908,193,633,630,467,20,523,100,520,896,149,120,576,791,392,81,640,90,722,9,400,875,561,508,98,968,106,76,980,979,720,788,634,77,314,107,231,601,479,872,478,316,54,893,984,219,143,196,323,641,382,992,134,47,940,604,800,488,498,98,431,787,335,339,233,898,251,953,321,78,696,617,770,393,8,3,42,160,982,142,264,257,263,908,894,299,963,778,244,565,523,693,652,395,740,788,3,986,597,565,422,418,887,569,842,421,587,324,4,781,922,523,411,73,380,968,232,869,675,108,239,456,650,678,694,151,388,431,286,880,264,646,701,867,214,220,602,746,782,325,484,756,426,927,14,456,958,152,967,890,248,564,814,706,312,516,775,269,309,798,777,528,555,976,419,29,397,591,556,415,810,514,847,915,295,364,45,481,484,173,208,761,621,675,246,217,629,332,666,526,951,348,152,505,166,310,167,11,603,426,694,379,918,623,485,111,654,361,725,88,756,272,491,699,365,538,515,73,937,588,685,331,926,418,57,760,825,471,308,868,317,481,75,327,73,633,496,299,175,195,537,305,341,820,209,424,743,25,755,889,789,472,340,105,943,855,252,478,191,431,732,600,416,233,801,16,322,381,776,873,528,88,76,758,419,350,105,767,538,432,21,819,713,226,975,894,239,301,491,900,316,516,793,387,642,942,193,59,140,364,940,510,453,269,90,848,772,660,230,992,336,878,784,481,603,54,878,77,198,779,978,229,98,755,214,89,199,716,45,145,961,80,75,779,917,661,657,531,531,742,593,347,365,660,79,182,574,727,777,530,248,374,663,369,496,405,43,176,193,900,679,857,742,659,859,196,237,229,529,317,22,193,40,864,854,391,735,282,519,766,761,17,147,61,754,801,871,314,294,143,123,82,563,686,781,224,901,570,316,910,753,139,65,389,624,517,1,597,717,207,795,919,578", +"380,962,51,37,381,887,607,654,640,898,995,293,3,980,801,640,139,338,230,81,111,222,405,700,605,521,204,454,425,488,546,587,955,32,644,628,972,171,114,189,126,401,525,423,42,350,774,407,505,633,26,345,761,623,469,168,86,761,680,463,442,980,566,583,627,196,901,0,99,973,768,99,49,130,285,432,649,634,199,608,892,124,598,771,776,991,346,21,817,628,631,866,240,494,698,524,84,656,669,941,532,383,606,291,487,676,276,622,680,360,192,60,296,860,907,891,980,683,410,870,635,749,279,427,186,250,216,397,365,393,108,219,223,446,794,78,197,723,490,374,139,234,850,634,662,85,882,951,22,596,268,18,999,466,681,165,172,212,507,740,123,109,302,141,28,201,973,885,993,241,813,322,290,181,111,738,68,426,727,147,411,881,9,551,109,370,873,168,576,551,91,423,241,605,399,321,110,14,691,849,588,917,350,115,605,282,137,950,314,872,955,958,463,467,306,686,25,824,150,24,875,858,251,128,789,637,171,521,763,165,52,556,847,362,586,730,447,690,595,195,264,896,802,257,955,378,152,551,448,594,422,753,177,500,916,379,49,780,904,397,52,836,432,857,960,793,362,881,975,144,27,736,848,248,819,554,537,36,258,15,33,876,745,301,29,207,824,803,717,782,285,579,830,71,512,815,667,637,415,805,90,852,569,440,114,466,878,897,912,932,636,416,568,702,174,640,533,189,317,702,883,126,45,927,977,525,240,499,145,44,99,746,266,662,669,372,790,939,701,497,209,697,569,86,350,794,614,848,166,206,866,403,805,638,753,983,800,513,288,229,346,548,854,771,434,87,948,641,870,564,356,600,307,329,175,214,652,548,900,231,428,657,537,165,809,7,599,872,453,760,354,785,483,245,591,489,242,209,48,582,476,718,462,626,947,942,785,921,147,932,621,596,641,171,302,879,308,803,94,504,147,461,347,279,450,491,321,160,116,181,798,13,796,325,356,732,458,106,71,479,995,267,961,177,205,599,546,228,461,448,611,970,204,628,522,468,957,437,741,476,760,720,995,78,725,939,228,23,82,379,685,637,264,57,726,585,860,848,544,594,812,901,187,600,855,884,153,334,288,483,745,29,949,103,550,637,552,828,181,438,115,259,88,539,425,868,77,636,415,91,714,58,822,440,889,600,917,634,843,668,122,759,449,271,531,84,965,701,816,572,917,93,154,695,580,49,236,216,411,69,296,494,884,983,45,422,586,418,205,718,546,591,90,70,445,275,354,520,804,962,567,378,398,681,889,83,50,201,948,884,477,847,886,607,740,869,441,954,738,801,417,604,202,758,215,959,261,176,700,625,670,920,636,440,549,131,939,277,834,526,238,568,629,701,274,373,818,119,326,51,360,745,135,143,368,393,849,63,288,986,40,717,367,258,14,711,870,954,309,712,216,677,653,53,53,819,460,905,222,766,255,531,343,350,223,708,499,692,851,415,810,878,753,852,158,628,284,897,88,224,400,148,948,914,27,853,627,543,706,492,299,241,794,165,216,445,674,600,354,120,251,396,742,137,397,909,545,760,483,196,823,492,980,700,691,139,497,958,239,740,141,2,208,217,721,745,830,123,181,36,186,922,48,232,704,206,744,807,327,157,440,603,999,156,6,440,409,888,70,485,548,184,933,545,597,205,247,656,583,650,519,343,847,893,410,591,968,710,98,287,446,604,392,834,768,328,72,567,480,977,642,510,390,826,226,399,126,565,7,618,369,677,337,156,69,986,65,664,848,540,530,413,955,705,845,232,659,202,827,474,504,777,156,232,247,740,596,333,553,759,635,263,165,655,136,980,740,253,290,216,882,566,600,21,953,933,613,108,847,615,130,250,428,201,616,418,736,706,171,43,973,912,869,149,576,673,319,394,31,762,917,918,760,405,42,929,290,387,354,736,598,316,283,448,677,837,561,822,916,933,101,355,963,509,549,872,591,854,501,421,242,783,32,981,426,415,662,385,455,499,291,104,168,128,165,344,544,305,547,705,647,387,692,699,871,70,960,642,929,713,942,827,859,631,942,484,970,904,325,148,456,851,139,420,10,439,756,308,885,960,679,171,817,534,774,156,761,131,524,787,239,630,609,301,293,872,661,36,522,206,852,443,715,33,831,176,706,646,761,890,981,808,541,771,93,878,158,11,423,86,983,861,566,501,687,829,730,810,864,876,981,809,261,441,827,66,397,813,211,624,745,921,762,168,605,64,878,523,946,351,922,154,527,818,35,245,232,514,272,554", +"817,144,696,105,929,922,144,894,849,390,662,929,745,299,708,734,986,870,828,545,805,86,95,319,121,348,844,293,659,650,449,725,227,973,826,666,304,630,203,985,53,512,171,285,105,574,430,612,801,845,323,142,667,522,148,699,926,876,280,227,841,982,549,342,19,872,681,99,0,748,373,915,594,615,822,710,140,285,686,590,99,311,556,166,61,351,269,859,142,860,475,325,86,393,89,160,515,331,154,529,216,379,314,6,458,323,227,961,113,624,392,583,254,411,107,182,991,492,793,382,239,354,602,803,676,250,62,252,832,979,322,16,276,681,575,624,191,399,823,47,126,63,886,575,347,855,181,534,44,845,679,64,540,917,551,815,207,765,238,88,852,849,793,161,827,437,427,17,8,11,488,851,841,172,628,747,645,461,346,664,734,849,567,117,71,591,278,193,20,811,760,408,875,396,401,303,664,843,868,296,992,648,104,948,829,37,15,544,44,854,58,147,945,50,990,969,734,258,776,616,881,240,355,196,661,554,267,621,570,924,843,478,413,971,743,688,317,699,676,236,301,171,614,845,679,790,473,458,677,628,755,38,657,309,647,855,973,826,221,299,458,745,910,171,258,640,854,424,170,739,426,31,129,377,399,138,205,196,64,957,172,375,689,343,234,631,196,658,402,883,919,497,872,701,499,835,694,469,775,326,194,995,866,840,369,95,189,709,848,449,462,320,316,314,881,675,226,92,390,585,189,897,747,697,928,553,834,822,28,144,762,325,40,244,773,335,919,27,243,897,856,367,732,820,565,513,875,206,837,322,264,400,498,500,558,218,221,440,963,472,218,888,377,999,615,93,438,726,382,7,103,998,411,503,99,857,41,594,531,835,900,694,44,139,585,217,750,179,799,934,886,980,255,299,722,716,848,694,167,542,440,439,291,444,835,364,447,719,305,833,59,620,432,126,445,979,138,879,45,585,737,331,172,97,818,898,798,198,248,390,83,263,343,118,106,990,379,906,795,462,226,219,282,831,197,640,318,278,248,68,529,32,106,698,302,23,757,828,69,720,299,571,658,835,680,407,351,763,650,177,282,413,516,159,487,175,800,909,16,975,347,239,744,763,729,189,880,935,750,785,420,986,838,572,511,410,658,84,954,627,541,435,957,384,633,74,250,258,442,901,726,891,325,155,300,187,456,893,926,778,559,181,646,446,309,792,304,457,26,767,150,460,543,224,300,371,921,377,677,149,550,955,653,812,394,961,523,478,802,323,571,579,909,526,888,998,219,901,238,725,264,759,577,509,94,281,17,525,911,686,386,557,730,788,879,325,701,970,379,740,401,507,974,366,843,68,113,733,954,633,191,10,713,343,447,655,715,38,525,145,955,43,783,844,928,201,794,832,803,706,561,885,782,900,743,249,596,74,408,561,874,482,609,791,27,618,378,715,889,415,276,841,1000,220,146,513,83,131,991,101,20,808,276,270,335,800,720,715,291,523,833,972,267,937,743,767,629,77,737,380,767,762,84,813,549,538,815,238,219,118,965,122,866,672,34,564,275,922,829,54,976,89,949,55,276,197,79,717,77,206,494,221,16,729,299,497,418,567,432,722,154,851,572,703,498,865,308,729,966,790,336,653,46,970,744,509,602,569,350,201,786,749,356,249,551,918,474,306,126,720,142,245,160,283,390,126,630,9,321,268,981,167,928,219,634,547,485,537,390,796,338,538,800,834,830,984,223,978,512,822,71,729,902,603,928,391,975,205,504,402,427,471,105,955,653,686,778,352,58,448,591,923,453,237,254,454,348,995,806,647,873,788,96,779,583,982,926,41,138,168,252,496,293,550,847,571,94,2,523,284,207,392,545,961,353,889,599,557,533,521,521,178,247,786,561,50,171,140,136,655,219,40,179,228,623,893,651,325,308,146,502,253,53,970,87,821,304,16,879,891,764,494,996,217,767,931,48,72,595,823,302,743,791,89,357,550,745,632,162,587,931,137,697,909,712,301,204,61,797,520,386,470,395,845,388,862,612,800,593,963,831,70,807,100,822,310,164,367,772,946,106,464,145,209,686,779,86,795,375,649,723,367,752,499,400,38,877,935,822,7,358,905,386,296,795,746,103,664,102,92,635,86,25,261,413,730,788,894,195,788,201,717,566,629,337,424,554,701,959,780,143,147,485,918,125,382,313,45,793,69,725,31,156,992,878,873,869,309,781,925,928,52,603,459,824,709,975,876,441,275,400,390,980,118,122,473,129,214,268,496,179,481,171,467,601,586,131,661,67,817", +"597,609,343,517,609,858,862,494,880,180,779,793,892,928,703,917,676,1,211,573,122,171,286,567,540,95,449,696,412,887,666,687,958,925,153,492,414,686,857,806,775,660,636,285,384,223,83,932,246,962,707,532,22,408,152,3,35,976,15,841,606,742,393,766,445,53,982,973,748,0,625,620,237,89,87,711,953,431,764,479,692,108,145,651,190,146,838,706,813,169,118,565,684,374,720,519,68,546,941,459,408,419,979,660,413,225,390,777,563,281,770,140,716,977,68,721,712,100,627,219,810,794,526,213,423,669,994,947,977,485,883,825,487,612,593,900,267,142,461,712,176,825,123,684,392,250,245,321,769,251,204,226,48,510,978,754,890,282,992,726,699,344,344,603,785,659,409,697,441,513,308,343,659,339,349,780,947,357,786,318,222,89,606,327,208,388,747,153,490,288,762,497,844,760,53,218,32,759,516,870,816,571,915,712,820,361,2,182,425,252,598,750,172,856,478,590,120,954,283,182,663,956,749,284,824,850,180,73,962,152,783,449,532,977,741,678,842,45,621,548,245,595,516,963,362,742,726,704,441,112,236,964,301,678,640,240,428,808,645,516,48,410,896,401,590,723,14,829,358,656,902,75,899,240,650,894,757,565,196,172,217,477,138,528,863,195,913,91,466,792,174,426,711,788,71,119,830,221,258,47,252,812,119,904,484,331,169,650,260,45,91,391,308,832,223,96,530,187,104,74,95,940,859,382,802,818,50,65,101,240,227,67,751,20,625,966,91,973,241,2,20,317,348,178,34,493,810,608,668,359,739,857,965,886,335,912,247,702,359,585,718,81,804,225,89,587,659,726,230,765,686,418,397,902,889,146,537,24,780,822,816,560,81,248,438,172,787,27,903,332,594,50,221,499,506,899,175,228,137,437,28,26,690,827,401,236,251,691,886,987,497,993,727,813,581,920,537,252,228,747,348,815,35,911,855,90,838,100,322,559,599,673,918,152,311,818,831,809,887,786,304,51,983,437,702,957,156,895,40,6,898,587,294,982,592,697,105,128,515,40,958,705,780,440,616,438,920,841,317,717,464,184,808,290,50,591,328,357,276,2,906,872,611,869,272,555,749,896,926,410,873,962,864,613,70,406,546,144,910,813,463,555,712,649,506,467,115,70,460,907,667,311,338,37,153,985,505,985,938,426,311,579,683,710,198,157,500,704,528,338,943,829,378,384,265,415,166,128,912,54,152,940,960,683,603,947,1,872,48,686,362,157,847,155,86,443,322,265,688,868,526,899,466,459,328,716,557,443,175,237,899,95,601,289,381,289,465,845,350,603,856,543,809,751,748,126,789,354,227,736,510,412,776,335,632,820,468,433,765,447,267,203,404,468,327,509,951,9,107,777,71,897,57,196,356,143,137,486,256,571,7,979,822,250,190,66,484,191,980,902,552,988,414,275,171,754,258,113,929,997,505,138,710,145,854,953,314,271,548,799,323,722,405,608,644,31,70,697,672,332,293,234,175,64,495,269,199,570,567,13,837,813,566,409,182,8,877,782,940,87,949,934,365,316,601,709,920,650,512,876,971,423,996,12,697,93,113,304,248,587,908,843,265,240,414,792,292,426,26,780,426,123,623,959,450,301,436,952,46,134,925,426,357,336,158,421,650,890,80,299,895,54,748,228,104,816,247,227,579,756,453,240,56,350,229,299,566,156,733,478,482,135,498,491,665,400,5,204,186,744,497,621,726,123,263,15,668,311,819,391,965,244,250,302,345,726,307,481,979,718,508,601,53,353,996,680,356,182,437,151,500,550,552,387,710,721,587,984,894,602,22,183,566,590,224,940,321,827,15,95,638,77,764,443,164,658,142,252,336,398,693,303,892,88,612,18,897,264,823,305,467,998,294,607,824,569,895,610,675,960,242,391,421,801,744,472,324,821,359,395,381,558,196,696,216,555,254,77,834,265,396,288,214,916,350,156,814,131,268,775,504,611,838,929,997,732,58,155,499,13,129,541,834,518,404,525,106,185,311,278,298,230,242,23,269,463,587,330,414,454,989,854,788,509,904,207,592,499,885,121,718,524,644,488,191,636,913,812,974,115,815,205,919,975,852,210,708,967,858,119,975,183,836,445,621,960,523,616,112,295,307,886,825,562,991,130,910,337,65,820,605,692,97,8,858,283,149,561,659,648,910,681,600,793,573,3,253,258,155,333,447,898,36,932,572,969,932,506,636,347,83,569,547,372,881,36,225,173,927,483,158,537,953,474,900,998,86,537,610,694", +"461,629,79,619,312,606,835,772,78,403,939,341,732,550,382,633,831,883,293,987,112,794,638,456,805,142,907,937,548,162,408,82,102,796,261,999,269,553,217,458,324,310,152,698,508,597,332,686,509,279,419,224,215,110,858,683,777,558,985,694,101,792,476,330,180,810,797,768,373,625,0,189,957,393,629,141,569,908,187,922,20,449,125,277,949,957,658,827,116,78,577,901,428,540,851,310,89,651,102,488,979,680,364,780,938,197,182,970,670,965,184,287,939,778,731,597,105,481,569,10,958,238,811,705,670,228,714,442,13,590,889,931,338,940,575,473,400,350,679,564,17,197,81,709,60,449,729,921,834,698,735,555,51,223,567,261,791,264,231,762,817,74,702,967,248,448,423,172,923,94,129,625,414,766,300,587,537,767,38,133,247,424,574,848,156,281,389,266,2,101,140,557,367,893,823,448,82,106,297,706,751,44,500,176,751,546,452,340,996,129,564,342,68,628,453,995,274,288,689,356,288,586,713,676,938,30,357,832,760,4,245,459,958,371,493,978,948,190,201,219,335,916,546,748,963,464,914,871,381,203,698,161,481,657,927,677,207,385,110,651,807,986,989,67,537,519,840,730,511,603,131,55,785,57,335,2,395,636,216,180,884,53,276,6,400,704,433,888,288,698,552,699,253,352,172,522,991,278,665,793,102,582,520,676,707,698,995,47,283,537,481,568,487,576,224,881,34,492,912,741,936,971,911,955,107,59,728,760,986,940,736,43,220,232,534,749,855,756,564,458,119,923,995,571,4,342,90,527,364,518,226,626,682,864,737,31,682,845,639,424,664,911,924,659,228,509,509,458,499,633,232,930,597,311,804,967,508,466,992,266,548,160,964,728,687,948,205,208,745,374,102,734,653,848,687,638,815,930,42,955,843,192,476,315,116,273,22,876,264,492,690,525,702,528,217,263,801,527,275,59,1000,747,519,136,526,431,148,12,151,777,678,489,97,253,706,870,658,536,367,458,329,229,965,989,718,468,971,911,401,454,813,453,932,185,977,5,196,534,897,898,82,193,153,857,976,714,131,756,148,793,621,753,921,100,247,359,491,320,676,139,821,217,640,918,431,482,182,875,385,664,708,604,659,65,138,920,182,448,186,999,666,903,791,647,323,984,166,311,34,961,274,8,552,214,952,834,50,216,395,78,568,348,565,280,965,570,529,10,588,175,380,624,880,532,354,353,172,466,29,404,598,967,508,43,680,282,521,224,47,805,108,533,201,197,908,856,104,833,772,492,232,651,646,345,382,115,575,271,312,501,827,935,144,569,284,389,555,377,805,331,254,136,501,441,903,735,771,295,276,669,18,301,485,255,673,7,683,24,334,396,946,798,667,797,754,596,320,726,719,536,313,418,753,685,998,610,242,428,638,552,289,253,88,606,137,776,621,182,240,924,250,536,554,925,748,906,892,973,624,846,59,190,356,727,35,271,639,951,329,618,93,173,863,564,145,170,62,627,452,82,870,241,398,918,501,690,86,560,107,41,990,752,104,781,695,739,697,849,49,931,901,165,40,969,166,258,837,597,355,470,564,560,175,26,743,252,359,610,917,421,622,936,632,145,669,387,330,955,679,153,734,704,319,365,380,490,229,845,34,451,978,183,79,693,679,144,697,373,475,940,846,515,616,170,242,693,349,529,744,88,300,280,119,617,245,144,2,157,551,590,862,69,419,339,67,888,201,771,152,544,381,345,917,479,31,749,161,120,454,725,655,946,623,334,294,476,862,648,312,831,17,408,962,683,408,461,17,961,693,541,734,142,706,349,720,87,154,521,858,50,879,748,416,407,157,639,882,426,24,510,536,530,445,875,407,292,892,709,176,255,809,630,329,393,892,678,375,901,273,714,286,879,510,731,303,700,809,139,250,150,994,403,984,596,866,511,617,859,672,477,994,180,632,690,306,402,344,614,892,292,833,925,402,430,332,980,90,434,921,187,844,295,971,358,205,257,670,232,982,940,407,209,452,475,253,9,397,599,82,480,950,926,939,669,211,514,445,574,492,144,908,690,820,820,278,804,886,706,783,814,443,989,621,944,455,221,636,130,979,338,540,464,754,907,530,561,488,119,901,363,423,345,892,833,18,500,855,6,699,475,457,928,278,468,937,59,779,386,253,882,856,984,246,518,616,656,546,978,394,913,34,686,986,239,379,452,670,111,371,60,479,864,884,553,575,110,905,263,134,811,398,218,250,250,32,148,736,887,706,327,766,122,924,206,223,285,177,48,989,280", +"386,25,63,545,81,22,899,171,395,79,880,215,862,209,440,332,656,789,675,608,989,984,630,140,771,667,905,892,161,697,803,935,81,521,98,435,165,631,823,44,233,625,930,648,566,242,530,867,266,929,205,538,841,605,30,300,555,752,569,961,621,352,824,753,328,342,778,99,915,620,189,0,229,571,325,263,461,650,96,642,619,352,729,871,940,605,502,310,203,332,39,767,137,432,284,274,560,549,908,3,471,55,162,499,440,221,702,518,713,407,62,649,410,272,768,106,373,924,600,111,154,596,911,854,126,476,11,181,115,749,811,482,754,512,371,580,835,796,327,583,524,799,367,8,643,346,56,795,6,286,766,47,120,418,367,730,937,150,625,915,850,906,478,736,15,746,790,90,345,252,969,326,761,986,823,492,643,179,13,371,195,351,538,380,110,637,258,731,610,198,845,467,840,335,860,846,961,165,774,813,416,301,538,962,518,710,545,536,963,450,830,655,934,155,727,393,618,85,295,796,455,197,200,180,865,524,498,666,425,572,846,78,644,441,27,482,751,746,390,79,448,713,116,400,624,247,627,368,594,573,516,138,424,4,353,92,766,114,333,596,670,985,680,582,210,59,391,773,912,238,904,941,842,626,775,753,318,88,971,162,583,836,803,961,424,588,764,678,457,166,926,348,676,431,782,902,940,241,913,301,505,615,661,57,5,19,305,406,445,10,627,405,845,306,767,994,321,6,600,110,174,812,278,93,258,439,645,806,12,845,488,748,862,483,639,265,673,918,650,131,660,926,651,295,620,572,386,760,456,532,689,773,450,627,302,991,857,29,160,849,929,189,680,413,918,78,545,622,372,239,586,305,907,527,404,289,960,41,507,70,759,755,539,705,691,328,670,720,460,626,648,782,954,133,790,700,662,870,354,660,942,724,844,504,488,817,336,959,5,10,892,351,356,89,70,932,280,20,137,839,879,592,161,715,161,61,334,388,12,192,579,310,246,922,570,491,652,49,778,176,550,83,910,312,823,581,768,770,537,413,596,224,401,196,467,20,56,100,943,252,319,675,655,52,435,219,71,195,995,455,153,77,288,447,349,510,622,679,171,791,192,648,566,123,528,158,724,698,889,418,475,249,665,232,194,494,646,994,673,679,782,883,577,660,793,798,282,480,438,771,971,569,983,112,498,729,712,40,812,900,78,381,726,125,633,215,735,312,667,431,464,224,476,52,917,157,787,660,19,451,325,27,492,996,494,410,425,398,366,544,997,578,507,37,538,882,636,520,423,661,344,494,613,207,132,980,222,453,209,346,288,208,688,881,222,467,741,312,22,754,949,434,684,525,258,860,126,967,762,41,608,473,194,384,13,752,709,931,599,81,514,920,708,157,546,841,805,911,677,13,547,257,637,368,62,145,416,951,435,692,619,840,77,36,376,517,10,89,425,938,431,228,339,821,284,84,611,596,944,37,780,629,642,686,742,622,587,408,235,19,575,199,285,153,516,516,63,958,885,541,790,61,960,138,976,289,390,684,885,288,66,964,40,974,252,420,264,885,852,868,807,409,529,934,251,645,749,97,688,863,518,319,738,816,2,49,963,653,996,324,211,518,513,820,956,781,857,300,100,150,132,503,81,934,950,858,2,424,443,549,349,180,463,959,562,96,209,873,540,484,997,485,711,800,418,425,599,645,744,593,240,199,806,185,69,546,933,714,106,953,411,753,473,297,316,508,354,894,368,5,15,65,385,583,410,293,189,1000,962,77,370,532,124,185,773,721,2,79,544,918,436,786,608,180,165,278,824,120,818,257,378,900,778,482,748,150,164,689,226,841,193,651,642,831,42,664,690,705,785,354,211,63,870,217,461,111,868,422,581,818,814,618,875,754,806,521,48,638,378,25,90,44,610,747,348,610,762,412,288,183,47,30,561,782,546,754,382,532,364,564,230,599,580,593,342,400,235,805,521,716,735,431,993,442,410,712,917,586,780,626,204,379,577,5,873,434,979,710,516,446,396,849,562,242,816,697,676,68,24,97,345,244,546,790,654,777,462,45,814,604,26,570,599,566,240,572,847,321,708,335,372,366,258,570,84,63,582,347,900,320,476,512,760,563,839,841,653,356,570,616,691,653,321,367,744,980,832,820,566,84,386,516,121,6,391,316,82,470,258,710,875,479,78,262,790,503,846,964,175,444,613,32,186,931,523,291,476,886,234,49,919,717,700,785,82,135,832,102,791,366,323,150,676,896,948,250,84,158,756,297,762,749,6,222,15,945,61,403,582,785", +"536,779,286,30,1000,943,562,721,920,812,64,442,901,256,35,458,920,220,498,545,711,907,998,54,506,357,134,183,161,487,937,486,139,262,855,386,66,529,727,833,156,936,705,871,880,84,357,36,241,861,413,322,437,863,862,596,161,870,53,10,223,781,79,614,617,341,461,49,594,237,957,229,0,797,260,378,75,345,635,745,625,589,222,699,202,107,479,392,570,575,530,3,128,717,293,742,923,351,79,902,417,755,571,303,878,680,687,692,678,610,611,574,336,34,921,66,325,3,38,975,135,330,507,471,831,242,905,866,736,810,667,822,176,375,282,556,289,828,992,278,744,63,637,62,673,275,957,745,29,202,592,464,668,705,665,617,147,197,711,885,337,87,749,692,911,270,265,755,497,463,683,7,43,328,504,69,197,862,55,677,445,269,352,529,786,331,239,492,596,739,646,602,532,436,285,251,415,753,528,426,127,636,170,244,821,569,557,965,977,754,371,499,40,500,182,135,485,207,650,345,49,8,587,631,796,725,472,30,833,700,988,665,537,77,114,794,938,150,242,238,365,914,160,427,267,38,912,288,599,745,858,416,227,149,231,977,151,201,209,720,72,892,553,819,323,641,564,258,248,28,78,618,512,280,592,149,431,972,33,639,937,374,503,358,446,939,531,77,789,9,237,838,367,818,104,57,279,139,979,590,895,935,78,972,350,85,561,272,512,580,777,872,283,699,514,269,414,894,250,457,44,987,674,165,767,44,544,126,200,829,3,911,829,932,921,768,67,764,703,783,814,303,380,966,56,979,849,169,117,35,736,702,841,111,114,302,102,650,726,277,146,998,887,940,63,313,47,870,570,104,903,113,202,348,561,836,93,294,605,394,213,861,602,596,664,295,555,729,258,673,923,233,356,600,828,530,698,950,545,272,883,493,334,81,67,462,615,869,763,597,408,99,535,379,454,93,480,446,928,903,594,929,655,227,570,754,756,78,614,199,169,751,179,66,533,710,739,61,330,233,718,964,453,703,685,860,553,986,828,355,786,34,792,213,70,914,126,729,176,798,314,195,726,9,917,378,817,653,805,273,585,650,53,604,51,716,372,510,860,661,4,241,720,469,683,619,65,486,633,651,593,392,169,487,428,729,78,224,348,243,631,964,404,373,154,888,570,872,782,729,828,33,294,368,286,764,89,151,805,888,163,906,436,112,760,173,151,515,702,329,551,580,180,560,177,920,514,21,519,140,87,764,747,522,395,907,783,727,858,663,399,741,441,752,644,374,831,578,631,654,145,603,457,28,851,99,393,69,913,999,261,677,991,868,340,690,727,670,725,294,413,921,576,123,611,493,730,904,862,143,882,808,50,771,663,981,531,39,101,270,425,710,826,627,12,332,199,682,370,994,722,720,805,771,544,775,843,250,834,579,524,949,271,97,278,676,645,246,710,912,981,160,963,280,573,561,555,718,445,720,679,666,198,45,832,325,834,768,335,30,975,640,520,98,365,195,556,303,20,911,648,965,126,358,197,855,526,558,710,973,68,480,67,974,272,237,172,66,691,624,315,891,363,971,697,817,52,690,394,62,573,408,415,289,962,459,926,907,937,130,979,627,354,85,701,788,612,376,393,384,405,318,306,134,605,724,116,901,196,997,377,81,147,837,850,511,438,713,620,233,879,86,220,837,336,308,63,422,107,913,376,948,672,886,631,975,643,546,215,314,259,734,327,353,424,658,635,824,161,252,173,170,932,733,848,143,318,975,24,506,595,35,995,649,845,53,347,866,322,85,233,165,855,770,431,170,191,116,917,976,479,569,232,500,128,391,721,110,39,785,6,83,932,996,361,99,692,752,773,276,317,629,483,338,232,837,59,566,455,380,785,264,183,697,780,762,35,515,397,84,554,326,826,456,71,138,911,36,866,552,636,372,258,580,247,374,335,891,758,231,300,830,734,348,98,20,187,86,717,914,73,424,327,595,49,862,135,822,398,770,712,406,542,529,344,980,897,702,935,80,196,978,386,579,156,146,559,88,918,688,947,943,909,398,761,616,169,570,448,711,93,209,665,314,868,225,916,736,283,3,777,611,235,664,821,278,316,179,634,733,610,49,775,719,99,824,991,835,191,807,937,397,744,549,601,695,678,238,378,394,191,908,526,103,42,426,552,327,449,373,16,524,55,724,232,76,394,661,52,970,233,722,535,963,665,872,314,782,12,742,535,888,574,640,283,54,828,338,875,681,22,782,57,922,69,821,318,765,512,959,256,624,611,851,117,667,676,583,765,433", +"942,492,499,163,453,781,391,50,72,252,655,575,991,703,368,82,827,534,622,100,106,268,569,679,967,879,58,611,287,726,332,615,887,915,894,337,350,221,126,585,651,828,571,1000,729,744,385,634,253,321,312,841,264,62,57,454,257,715,289,49,780,175,281,371,876,40,609,130,615,89,393,571,797,0,236,370,876,626,717,36,212,608,694,400,760,67,752,403,455,793,63,950,911,677,315,894,258,74,42,826,740,211,968,448,444,726,251,21,763,460,293,541,437,642,877,960,589,602,805,500,752,158,390,648,131,809,519,209,440,874,521,937,629,871,504,561,900,754,630,159,759,444,606,11,292,183,612,818,109,680,765,737,440,406,19,3,133,943,783,431,36,831,880,896,285,643,160,735,289,840,682,339,198,117,497,247,202,572,325,490,865,211,43,503,170,869,879,489,499,278,102,937,279,620,913,96,35,551,759,17,547,437,346,274,686,217,911,86,309,268,559,564,346,411,7,81,889,533,585,673,576,975,434,550,349,197,597,817,738,778,711,814,29,204,417,189,280,53,327,72,90,524,234,262,604,490,261,944,13,20,609,126,270,86,925,511,514,739,99,787,452,47,853,138,438,313,341,16,849,365,465,535,544,695,85,553,351,31,356,203,638,643,84,366,995,646,579,815,262,91,953,211,156,648,82,918,826,822,10,776,651,126,511,396,58,942,993,481,815,98,458,183,925,925,842,695,161,274,917,421,318,688,215,841,233,744,289,442,721,55,900,367,858,370,851,265,298,736,247,60,248,25,245,385,788,374,98,587,758,709,1000,402,586,598,831,895,976,493,409,610,290,604,486,950,169,273,487,231,756,150,327,722,113,791,189,559,630,497,10,51,249,247,427,192,820,272,771,396,246,275,109,974,268,231,457,761,642,801,400,317,481,578,781,990,638,607,458,322,824,862,727,373,874,942,23,239,674,605,828,598,398,736,551,340,485,780,157,830,481,57,99,326,222,663,520,698,29,37,320,1,166,151,883,121,884,670,750,744,406,511,242,971,377,76,930,612,545,969,719,484,91,495,234,623,866,409,971,517,157,808,399,58,910,741,369,76,990,591,731,749,274,98,335,352,518,803,986,126,985,751,330,853,399,496,25,929,274,370,506,56,751,189,15,244,42,173,934,446,67,82,630,501,665,848,860,794,476,574,314,880,753,264,251,692,62,883,322,66,304,144,939,330,984,752,374,989,128,253,262,960,932,627,902,126,551,410,260,280,923,21,814,605,690,722,411,386,597,932,837,940,994,397,32,88,825,366,804,127,875,280,495,4,869,228,433,368,460,399,974,8,893,598,824,514,608,638,391,21,868,890,764,218,237,393,87,149,692,687,678,452,591,174,890,845,316,639,811,388,100,901,403,640,882,184,413,99,106,51,321,824,67,350,79,267,145,975,128,793,817,614,380,88,271,223,844,264,732,528,119,772,370,114,547,276,753,301,52,330,975,467,242,457,288,226,243,771,966,786,116,926,211,901,474,842,937,558,361,490,72,604,30,844,634,163,507,683,377,900,687,388,123,128,207,994,150,161,783,405,435,773,244,537,711,250,756,38,311,57,432,93,126,53,273,87,485,162,795,530,416,483,811,592,466,940,712,285,152,255,543,428,596,215,202,351,725,26,472,783,446,49,616,656,404,822,658,165,437,245,377,783,279,724,900,255,310,46,598,86,55,567,399,128,932,761,556,753,669,958,132,889,758,204,516,539,733,713,63,469,712,920,992,225,909,75,47,748,863,929,146,541,265,442,503,355,737,771,625,760,156,908,286,261,211,262,55,790,604,176,216,815,832,483,672,198,395,154,43,148,619,200,683,944,394,418,201,855,549,452,191,479,298,717,424,562,75,353,561,150,942,199,253,247,528,498,923,842,157,402,355,803,468,299,494,817,295,713,955,161,365,234,727,688,239,267,657,205,497,433,268,113,30,722,457,879,751,299,633,265,778,601,469,566,961,622,111,457,100,444,799,355,584,415,488,717,537,782,941,291,158,249,502,680,115,160,165,287,966,744,237,132,539,169,704,720,20,196,756,175,856,991,861,825,943,201,136,106,297,98,161,875,873,302,897,746,376,418,790,800,645,21,430,490,194,58,721,54,415,957,470,927,123,226,662,835,254,329,118,961,704,402,541,28,304,316,733,688,60,999,655,35,983,63,186,442,319,693,585,128,408,83,483,315,855,790,522,277,415,522,525,328,491,450,939,729,255,381,938,939,489,880,586,703,456,729,521,705,756,234,601,895", +"533,412,302,866,659,129,157,30,272,187,936,543,990,953,104,736,776,777,456,559,168,979,967,382,376,30,955,575,160,431,314,778,666,817,863,618,577,534,677,442,39,67,804,896,329,143,245,818,644,730,821,542,337,433,327,693,28,742,244,672,507,682,471,646,310,31,445,285,822,87,629,325,260,236,0,465,641,299,197,778,426,24,692,716,22,1000,783,283,753,638,813,38,171,438,266,354,284,79,230,379,366,136,133,393,253,757,357,65,324,708,711,356,585,424,107,171,813,203,666,937,857,429,295,427,140,718,152,763,75,227,912,275,435,18,184,5,807,889,409,223,854,175,787,165,654,719,518,691,837,800,928,104,933,564,713,801,142,43,158,306,266,496,234,186,821,167,658,419,910,599,29,999,634,231,39,226,130,2,751,28,237,535,216,466,820,190,846,928,660,428,924,117,222,948,778,195,493,584,608,766,635,457,436,641,551,643,164,320,233,899,277,580,535,365,767,456,389,796,637,814,328,200,626,558,626,489,876,728,132,539,652,579,783,133,986,527,895,572,960,564,490,9,284,197,806,737,774,461,315,419,250,654,856,60,19,957,308,651,254,538,368,469,743,326,429,503,326,171,752,298,538,425,875,221,130,660,517,139,53,283,511,531,107,709,570,814,10,449,389,218,216,856,464,272,916,251,592,428,299,82,36,720,862,540,462,798,390,156,676,700,949,925,480,786,599,728,98,992,978,456,837,687,202,162,132,861,54,957,215,660,135,417,576,744,389,991,379,161,674,513,630,726,511,454,869,973,947,818,517,620,756,526,446,16,421,346,150,466,685,201,819,270,859,754,505,827,811,690,293,592,968,693,803,931,915,560,129,990,381,411,96,603,643,185,105,295,870,68,600,395,187,773,891,616,719,240,496,941,780,674,653,861,622,977,809,99,323,678,106,609,895,119,608,806,869,271,975,30,554,820,351,666,168,729,831,410,773,931,383,657,184,507,188,914,379,243,438,215,561,252,813,717,19,964,641,716,337,274,440,584,437,183,701,630,551,175,870,64,827,908,74,905,202,154,859,582,925,681,481,530,75,277,767,19,835,918,249,232,453,387,839,331,967,13,198,689,802,605,258,203,341,882,31,658,689,98,371,356,127,856,864,882,443,926,526,343,366,849,699,564,381,999,628,188,165,88,568,698,719,828,977,443,804,482,209,428,310,485,368,467,238,520,593,688,651,801,449,746,77,691,281,859,240,395,28,346,556,586,790,216,714,255,344,114,723,898,530,519,464,252,208,159,102,262,586,247,369,961,125,260,953,32,581,322,818,23,898,541,443,505,534,458,78,323,659,729,779,938,955,526,163,628,910,161,629,870,602,742,683,776,528,349,622,402,719,425,806,238,833,598,161,487,908,402,384,102,377,725,569,862,690,862,307,895,401,985,263,720,190,773,518,862,487,328,292,926,261,551,956,312,241,896,460,73,212,802,263,944,130,836,671,736,534,664,791,822,130,280,792,519,788,360,877,864,611,470,169,382,297,208,179,451,52,552,419,739,549,687,134,268,334,951,48,962,781,140,265,681,208,314,347,119,16,578,447,558,720,70,375,738,57,634,163,923,666,296,620,20,444,247,521,557,941,672,824,292,183,350,661,288,408,645,437,719,868,623,855,693,834,260,759,546,444,981,490,946,875,216,767,306,610,114,594,443,119,953,378,801,147,792,332,822,263,535,491,580,992,470,423,644,889,800,480,235,537,181,885,471,629,218,302,514,772,854,166,272,948,95,542,165,446,715,442,740,159,718,206,63,740,837,282,495,400,309,860,465,185,611,137,693,887,770,357,897,591,146,268,893,877,40,747,454,362,366,249,376,933,51,208,972,994,51,514,710,950,778,183,378,141,724,383,800,358,813,368,953,348,620,215,585,90,729,766,902,456,524,326,21,260,118,864,753,827,898,227,603,572,371,721,306,736,926,610,325,261,439,281,14,398,846,474,468,338,314,433,916,267,992,943,868,449,860,660,679,261,914,956,323,962,779,308,958,169,493,822,858,254,539,132,118,339,778,686,441,716,788,967,373,776,718,699,902,567,9,283,185,83,897,869,4,573,991,945,418,51,975,757,572,617,295,824,717,479,797,917,682,71,500,921,560,613,77,340,297,348,590,683,297,268,130,191,863,659,441,349,497,699,24,43,560,710,895,5,829,759,364,293,357,751,939,887,424,141,58,505,551,951,35,258,389,506,167,281,959,325,412,404,267,239,990,953,757,252,76,662,93,88,720,367,943", +"774,778,842,785,936,203,933,345,622,260,602,913,135,165,866,793,465,976,910,274,343,16,425,793,534,609,818,839,969,332,213,216,6,572,419,992,165,823,667,455,229,433,990,534,454,320,895,58,804,239,385,253,332,646,264,514,43,412,846,399,550,857,847,418,901,677,24,432,710,711,141,263,378,370,465,0,587,908,169,38,629,538,271,824,624,405,65,622,827,786,978,835,338,595,929,545,804,517,119,485,480,953,299,416,368,411,175,399,470,348,425,61,99,506,953,507,11,774,82,422,966,637,573,314,101,900,104,888,790,456,590,945,588,303,588,99,413,712,78,443,196,739,231,27,873,7,902,211,16,12,544,311,794,113,835,67,416,30,980,293,875,203,283,398,152,339,659,698,763,836,196,333,664,396,258,778,852,274,238,50,243,292,579,901,264,202,964,752,555,237,709,268,638,894,235,291,705,434,140,340,213,973,748,715,540,163,874,35,434,328,161,742,355,911,814,7,187,745,185,477,508,112,561,634,182,371,280,901,103,140,819,318,739,676,354,400,162,933,749,745,583,352,560,510,511,589,967,103,719,993,533,605,652,750,397,565,626,798,155,864,635,525,148,913,153,744,20,876,504,684,339,396,62,68,556,110,82,93,192,431,982,156,882,118,309,344,506,726,659,620,872,690,926,712,999,976,4,848,51,404,21,277,628,527,965,842,509,344,853,222,57,532,135,835,343,678,646,130,292,403,163,195,81,135,133,111,175,930,329,485,499,579,612,529,731,400,485,522,292,685,33,399,813,677,536,131,277,639,529,815,852,552,946,487,368,440,707,734,166,377,968,706,187,726,875,491,154,727,404,961,131,171,717,722,697,459,891,95,838,323,83,723,663,476,944,858,611,169,871,782,687,354,800,190,392,308,272,754,823,467,580,719,971,42,650,994,26,374,752,2,447,452,904,388,915,776,315,678,271,76,589,107,73,269,728,202,935,437,339,66,716,650,501,940,181,642,127,878,360,362,878,417,457,43,902,258,677,931,718,170,94,861,581,819,729,722,328,59,559,209,362,353,748,685,260,387,273,658,745,353,632,196,729,903,891,135,675,498,80,615,507,713,22,358,647,893,650,313,715,835,765,397,681,512,657,275,62,130,59,869,724,231,770,298,598,367,488,280,473,398,576,510,117,417,289,865,94,385,601,540,893,811,392,627,566,275,515,120,177,936,615,930,570,787,210,886,478,666,399,954,163,51,789,726,894,291,89,111,168,200,22,985,8,670,649,32,67,529,926,437,949,153,515,75,596,200,497,704,905,135,429,117,684,634,285,849,56,920,365,463,712,285,866,601,618,495,271,320,681,921,805,487,437,465,936,218,675,187,89,838,581,512,941,17,290,220,558,678,868,55,870,631,800,417,491,838,824,795,549,183,738,159,412,944,590,500,323,867,176,758,27,687,615,594,608,776,296,705,614,986,62,62,537,42,25,885,831,168,4,972,989,552,566,161,332,629,372,211,892,71,137,48,171,95,394,289,237,363,691,819,542,271,418,579,857,37,914,584,651,178,906,439,32,389,691,152,347,737,543,981,21,288,461,670,782,676,210,629,31,589,628,821,993,106,497,515,211,446,847,39,473,981,625,733,381,410,486,431,388,439,854,939,209,557,466,991,500,446,777,947,916,151,816,305,229,92,426,839,625,418,689,670,755,423,770,162,982,715,624,881,727,530,727,692,914,926,448,178,453,696,455,406,170,15,160,840,378,860,554,429,780,309,840,868,261,327,665,500,606,491,20,948,670,236,830,217,492,66,635,702,723,394,593,564,705,668,816,871,799,630,245,209,470,627,637,958,449,584,478,550,872,212,245,615,279,662,190,819,29,545,186,931,224,891,35,33,389,238,531,187,30,878,716,780,337,163,604,601,240,301,655,257,342,756,136,912,904,466,280,540,10,879,163,654,648,596,309,958,634,318,588,865,866,646,24,404,4,60,245,93,918,893,453,46,94,802,224,468,978,734,783,579,735,706,748,474,653,670,142,259,916,874,692,353,890,454,124,146,357,518,523,637,567,644,842,659,275,31,889,167,571,655,366,151,816,98,589,720,452,451,995,625,458,920,611,836,45,8,485,465,93,454,621,612,15,38,833,278,571,712,437,45,905,415,533,793,931,591,816,375,853,615,917,684,960,27,151,619,191,974,302,179,221,790,238,61,188,195,729,87,641,867,171,562,474,985,586,888,729,671,719,214,752,916,808,393,885,341,308,43,745,798,525,129,740,784,202,348,376,111", +"71,302,682,54,930,381,691,332,583,706,814,296,976,935,595,446,599,672,498,257,853,26,319,213,779,946,578,23,617,510,694,402,782,427,717,376,199,274,568,143,893,37,447,492,522,905,887,877,462,620,819,292,611,421,807,294,681,660,563,236,948,549,614,50,870,390,668,649,140,953,569,461,75,876,641,587,0,439,88,841,930,402,918,735,185,215,159,60,716,475,886,664,422,425,744,926,310,881,325,361,149,379,323,86,927,564,878,480,839,14,160,771,635,793,834,695,693,121,988,832,931,887,399,544,122,653,990,302,450,827,832,159,293,198,685,417,133,114,666,882,835,743,865,801,123,755,882,336,656,927,933,610,245,696,460,869,31,187,636,693,602,665,97,544,313,157,900,602,903,845,693,622,630,504,753,430,666,325,101,89,954,729,905,724,335,347,158,488,260,824,324,954,791,715,552,233,616,578,487,461,613,30,679,853,630,785,908,566,262,55,915,556,742,919,438,210,963,496,613,234,88,288,682,817,608,437,354,800,812,209,876,303,924,184,761,837,258,46,776,94,268,314,34,230,318,246,994,187,752,812,46,414,247,8,630,521,66,991,42,952,684,392,460,16,233,698,124,451,37,490,205,278,187,335,951,165,141,442,573,288,412,582,929,38,573,16,108,476,882,972,731,238,630,548,463,706,133,651,167,990,568,465,700,463,376,302,50,454,591,462,659,507,283,367,985,137,842,473,879,518,240,508,660,31,597,656,955,746,853,253,783,987,732,618,220,136,129,826,877,587,185,465,891,208,288,427,212,485,904,689,931,886,462,752,492,268,945,837,813,724,188,99,186,297,451,751,704,236,266,594,494,928,371,513,127,462,786,68,366,799,14,269,812,912,601,417,787,436,7,53,353,110,93,668,251,422,778,827,483,348,924,195,827,806,374,645,343,812,551,613,48,161,325,205,585,846,29,893,988,153,659,835,563,512,805,961,287,84,767,834,81,112,344,582,77,524,897,880,433,60,148,16,506,811,342,307,719,216,404,667,436,403,287,816,521,168,404,663,981,317,611,968,869,632,667,489,46,830,321,212,796,808,797,308,747,558,418,14,287,578,300,394,538,30,138,573,345,69,545,809,829,887,648,870,882,854,169,852,546,666,159,721,271,894,555,571,689,451,742,456,702,730,743,229,64,843,842,881,451,937,410,442,230,483,589,223,713,222,70,441,799,27,843,636,832,766,44,104,382,881,443,199,532,903,514,652,287,263,500,922,238,632,408,846,723,870,894,577,596,148,16,98,432,76,274,908,567,186,947,970,38,609,467,602,557,346,962,560,78,536,355,826,655,66,288,407,364,840,925,596,76,948,843,249,389,726,486,58,33,67,856,558,30,297,87,419,687,13,599,785,832,850,88,768,154,699,803,564,250,695,780,539,603,978,702,180,90,522,795,627,921,333,950,528,872,576,845,499,290,610,955,144,659,756,358,473,535,960,566,986,108,335,146,625,631,651,655,137,231,743,405,400,890,337,85,979,528,10,824,535,77,274,365,66,64,71,198,412,820,449,589,795,608,916,113,321,992,919,981,234,617,53,827,11,797,550,857,520,152,946,121,875,451,479,111,593,953,551,792,602,420,859,435,70,115,970,67,362,260,538,897,563,757,794,960,907,506,509,581,747,237,801,689,102,862,779,814,560,666,886,143,964,676,732,625,492,568,566,342,26,351,590,733,984,221,387,412,37,162,80,833,14,340,193,443,903,811,732,226,537,873,508,304,588,627,584,231,836,426,60,131,561,520,315,861,803,710,298,127,421,354,109,781,757,849,380,705,573,900,844,12,432,605,213,646,513,697,562,109,707,11,547,272,401,410,11,275,299,685,68,397,303,517,379,629,63,329,504,3,984,561,931,703,616,890,469,574,318,463,475,689,411,765,473,21,333,231,244,175,479,818,153,563,34,10,610,818,962,887,662,33,138,375,953,354,166,142,730,845,931,295,955,986,513,758,194,538,70,307,230,742,227,349,756,356,762,350,861,959,632,958,755,789,932,574,26,499,651,201,790,381,229,231,303,445,526,118,632,277,600,365,500,828,64,972,572,250,507,345,345,962,764,913,352,111,135,497,770,716,843,19,903,471,985,398,315,474,501,35,458,109,771,24,463,742,41,457,550,838,700,682,529,542,830,371,825,816,386,610,960,887,876,654,135,434,328,188,335,64,468,282,186,927,325,873,656,349,159,707,253,440,29,320,731,707,545,575,532,699,665,550,271,984,129,929,83,904,402,10,838", +"996,220,896,219,252,316,918,991,278,2,436,33,17,415,94,626,199,700,713,452,231,111,599,730,19,53,195,150,516,412,594,237,837,768,379,845,649,171,882,507,487,868,128,148,408,56,445,334,110,591,908,85,854,750,795,442,25,396,150,928,226,758,977,260,922,974,1000,634,285,431,908,650,345,626,299,908,439,0,663,93,765,747,893,926,934,768,303,683,174,686,133,486,78,892,504,527,668,587,817,859,969,191,795,525,180,886,735,650,607,241,510,53,305,639,865,681,351,265,84,924,55,218,37,66,929,995,123,185,976,19,405,169,775,772,741,670,390,700,602,560,38,791,751,947,354,620,651,664,802,575,681,567,865,644,862,59,833,559,854,468,731,199,864,971,370,90,787,383,820,60,437,423,552,707,847,782,742,574,89,992,311,25,43,424,808,728,356,640,123,34,727,104,483,21,261,957,308,622,104,743,938,813,874,800,641,794,530,595,950,744,298,564,397,72,448,81,927,995,944,959,27,949,257,235,8,127,193,398,154,254,434,672,209,580,652,314,887,387,43,25,349,345,249,826,408,176,472,59,877,647,61,121,3,503,140,346,434,902,424,43,812,107,325,960,413,568,335,185,68,684,367,480,559,931,528,282,675,940,825,920,927,946,487,71,228,885,94,150,795,386,594,305,310,327,155,137,189,442,459,807,900,944,84,292,725,686,299,791,595,897,709,397,704,608,417,521,8,605,711,519,48,58,190,905,676,946,779,540,977,681,928,86,38,858,73,625,924,873,768,407,894,23,247,667,697,834,385,297,929,998,79,824,442,912,322,283,459,514,66,311,988,477,997,62,137,475,543,561,193,827,819,931,246,696,262,493,733,283,510,898,150,472,599,453,236,231,801,921,159,741,627,377,174,305,807,679,845,402,415,692,88,826,861,576,718,375,149,773,555,44,965,665,439,355,144,113,857,78,633,238,579,670,200,952,780,246,698,203,196,271,288,144,524,45,611,313,801,431,715,571,626,956,583,138,781,94,985,312,269,365,22,372,600,533,707,257,25,791,205,283,55,573,710,620,34,540,875,260,217,304,549,224,467,864,153,822,561,702,124,29,696,710,206,999,580,716,855,777,93,74,872,207,841,44,723,145,45,595,487,679,411,418,188,123,773,333,33,508,676,435,410,612,173,504,560,952,19,700,626,350,372,595,753,213,962,171,22,921,82,831,465,328,988,967,714,190,674,272,539,305,175,618,251,645,753,858,933,697,391,169,34,18,146,947,46,900,125,877,360,351,459,517,948,732,439,635,278,345,380,781,239,336,192,559,229,175,281,231,264,838,128,818,147,670,307,508,537,764,247,274,932,854,64,42,691,553,184,23,420,358,877,513,219,783,495,440,679,601,468,414,629,914,718,934,485,138,378,966,302,543,211,904,256,880,881,999,300,611,654,49,643,393,558,778,54,24,278,138,439,22,211,422,775,909,407,927,30,107,495,127,838,699,35,277,496,832,851,968,620,893,886,271,966,892,647,791,979,645,986,79,849,559,174,35,385,521,597,970,925,93,159,31,552,697,553,454,943,243,432,889,989,467,159,921,527,628,316,914,551,1000,143,718,86,993,127,652,205,276,654,706,712,823,154,765,546,394,565,697,240,267,45,583,58,891,321,747,182,216,113,656,341,969,962,39,814,639,882,826,146,691,318,671,3,965,129,311,95,279,275,576,615,680,798,26,673,188,602,977,75,529,168,695,266,885,30,726,656,770,704,205,360,728,460,902,66,485,810,369,513,24,782,139,402,336,74,172,204,708,752,497,469,336,419,339,886,804,708,50,217,833,604,701,353,459,273,277,538,521,369,691,267,999,330,340,94,342,717,557,911,180,713,339,3,412,930,501,479,242,523,359,988,59,914,485,370,843,740,928,371,765,572,17,49,186,21,795,63,551,301,446,725,379,326,269,702,835,314,545,461,731,478,619,817,349,562,524,524,974,556,804,30,106,445,683,435,571,74,622,330,951,178,842,952,820,796,528,14,35,130,457,797,428,803,944,204,620,793,615,452,310,975,822,384,525,173,461,593,891,698,700,692,887,826,55,705,910,101,344,335,715,760,393,273,839,352,960,610,314,752,997,115,334,561,205,493,570,5,351,526,842,65,714,818,115,224,312,615,461,165,300,304,63,507,769,617,215,587,825,144,511,666,422,203,39,234,694,929,106,646,753,204,662,572,299,772,169,846,581,727,269,227,28,361,387,643,638,77,770,708,176,944,235,514,16,788,722,14,869,68,776", +"752,159,576,573,904,445,516,807,571,142,545,61,242,478,458,233,149,106,451,785,7,298,101,283,8,263,675,472,450,92,295,530,780,632,257,652,204,891,584,274,98,126,857,342,426,970,716,932,628,602,427,628,102,220,478,14,204,401,528,71,847,270,742,811,11,42,786,199,686,764,187,96,635,717,197,169,88,663,0,13,628,963,947,870,529,561,911,739,137,529,353,40,435,322,780,494,10,753,960,518,587,324,852,670,353,690,46,848,904,487,233,683,519,613,978,944,558,441,854,547,784,202,637,276,389,409,570,620,522,321,197,755,263,396,747,650,956,361,618,160,570,772,963,919,952,519,618,697,227,238,738,910,690,474,698,71,825,320,982,645,416,734,79,521,297,166,957,652,88,120,920,123,876,969,514,764,541,654,710,877,190,206,648,798,680,537,416,997,695,788,620,432,565,725,746,317,507,929,55,669,117,114,217,427,127,25,589,809,614,325,94,265,500,591,368,857,643,721,660,650,155,332,138,336,57,871,386,141,963,131,794,668,561,651,132,193,652,116,676,791,830,180,840,537,587,421,327,380,953,723,977,289,139,576,292,2,842,65,363,651,838,669,760,900,862,141,209,940,413,269,690,871,164,639,920,567,92,606,851,919,862,547,293,544,254,327,995,759,749,905,464,9,421,51,269,123,23,892,626,555,982,145,420,141,539,540,727,64,869,104,681,56,2,126,513,728,689,816,874,110,11,507,437,262,762,682,82,777,548,120,34,933,657,562,945,48,366,935,973,628,631,657,709,295,456,615,223,784,458,148,487,990,641,50,391,349,640,385,368,315,116,180,648,500,146,353,653,28,605,197,89,552,695,856,309,886,901,913,716,417,176,932,729,475,89,568,599,539,855,734,650,939,360,243,739,550,816,402,519,520,404,936,996,595,349,119,762,671,232,54,411,234,630,937,778,772,466,639,213,548,669,391,693,914,567,818,330,140,513,677,632,387,302,753,10,920,349,267,893,381,343,201,151,313,546,361,430,533,791,337,97,577,534,330,923,271,462,852,504,347,754,24,634,522,550,85,154,215,317,143,523,816,395,802,580,236,767,670,460,208,191,493,731,340,584,921,43,727,635,871,858,239,734,754,443,21,88,657,287,712,64,277,749,189,687,276,744,446,734,851,611,709,696,125,494,528,789,682,732,431,948,379,501,991,677,262,982,889,65,179,942,771,168,738,740,992,711,239,701,851,51,856,749,822,525,964,854,123,100,830,965,489,267,934,314,172,49,511,762,685,795,548,432,509,560,326,525,99,69,57,370,956,952,153,209,588,283,931,204,689,484,723,383,753,558,622,165,673,115,190,909,165,230,373,283,673,889,409,824,62,418,352,669,971,49,378,554,747,777,874,758,95,639,418,804,886,313,407,458,21,578,953,55,811,894,777,563,264,770,310,863,641,725,824,668,265,767,974,833,451,904,467,220,274,153,892,138,425,879,49,201,394,528,660,59,879,42,283,628,430,850,653,451,729,168,845,662,565,990,24,897,629,343,7,32,909,717,118,553,989,7,443,184,416,783,199,94,632,209,976,795,531,121,343,830,39,260,655,306,761,792,660,377,215,309,975,686,769,371,613,697,817,324,155,743,357,846,692,844,267,255,664,110,882,704,172,450,276,773,701,221,350,813,491,238,63,147,56,230,818,113,606,292,800,158,175,416,888,749,666,67,95,716,936,530,96,140,634,178,506,795,735,274,575,999,471,786,503,624,369,129,491,829,228,253,362,918,399,510,841,318,851,304,965,623,561,293,643,342,885,650,221,711,698,263,606,842,946,469,827,275,150,388,166,944,527,63,497,624,423,150,156,144,435,820,123,819,356,466,827,164,824,901,850,876,987,464,38,166,218,926,769,142,15,21,981,719,107,862,56,919,474,754,868,343,66,786,842,762,25,97,305,999,449,582,993,68,991,189,11,142,914,255,878,585,250,933,58,774,390,329,97,260,161,35,774,619,175,939,267,568,594,120,810,831,285,858,267,506,47,122,708,339,135,204,69,653,347,954,559,84,626,152,591,940,462,57,47,163,112,90,50,743,547,435,141,761,727,934,456,414,51,462,852,943,695,750,968,59,194,376,760,889,343,944,236,624,525,484,342,82,945,150,206,12,799,112,140,744,814,640,136,707,651,442,795,742,695,903,443,227,714,682,220,124,961,287,921,210,631,711,214,907,432,997,625,987,35,972,350,54,415,417,823,135,696,113,223,630,48,252,294,922,885,418,517,638,343,857,945", +"6,617,942,636,894,851,169,406,10,852,729,1,402,737,87,69,553,711,566,833,109,878,383,920,495,766,417,123,605,215,294,570,548,986,814,713,865,556,996,717,771,352,950,385,831,226,433,151,505,637,461,878,911,541,700,178,407,161,69,180,820,740,537,127,738,361,31,608,590,479,922,642,745,36,778,38,841,93,13,0,898,967,850,312,20,836,922,975,359,111,299,743,767,422,839,718,779,636,138,965,983,741,979,911,725,443,822,520,24,803,100,999,195,851,149,94,901,179,486,950,685,330,703,857,106,277,883,39,510,238,516,839,783,605,77,660,655,200,168,42,321,794,870,157,260,540,357,706,542,899,424,164,153,177,320,541,109,486,227,811,467,192,24,974,442,594,654,795,548,316,496,292,342,717,345,14,542,753,30,938,179,198,93,873,516,494,542,63,942,565,639,202,426,142,197,562,898,855,984,946,20,214,704,585,466,731,443,356,852,78,278,480,409,666,317,779,268,865,367,357,349,337,198,658,953,270,29,316,449,458,516,274,776,258,591,789,36,282,94,950,473,473,547,763,840,228,294,131,451,424,284,427,124,479,212,615,217,788,932,767,859,641,780,419,489,964,27,830,646,606,620,421,85,245,934,694,231,306,904,865,920,493,510,169,890,829,635,765,52,195,972,922,140,966,864,727,564,120,601,119,73,771,549,180,74,680,367,3,204,815,210,736,229,623,444,63,889,835,658,462,369,618,561,132,430,717,447,104,126,29,439,356,934,335,901,115,41,771,500,427,642,197,466,268,797,989,770,330,264,406,66,562,451,806,500,84,225,282,624,375,188,604,655,528,683,195,429,156,675,269,695,631,324,524,258,742,117,171,414,882,808,826,619,957,787,984,413,977,459,390,305,533,887,908,962,987,936,709,30,348,127,654,356,714,543,116,193,390,121,219,207,635,829,522,5,851,448,627,86,71,877,277,502,790,764,196,718,310,820,566,362,568,780,706,116,943,575,153,534,27,843,756,822,218,378,224,253,160,923,836,374,108,868,494,977,960,129,676,338,327,858,604,323,722,412,264,902,370,902,69,533,653,454,655,96,110,407,624,191,441,442,107,77,58,460,418,42,994,206,476,162,965,568,527,717,104,316,763,902,339,953,18,559,756,129,832,830,555,330,896,382,118,630,907,28,486,247,364,991,301,677,258,263,906,718,133,977,175,723,958,558,87,24,882,770,557,136,898,750,29,305,51,783,523,705,210,81,238,384,233,609,722,995,942,624,765,647,545,984,660,674,200,271,807,792,704,857,375,506,400,522,218,841,759,686,359,370,247,64,687,726,108,837,438,810,122,301,521,5,307,599,142,991,594,563,696,419,502,408,822,359,471,950,746,484,784,499,268,841,499,131,518,822,270,434,712,615,878,692,783,550,525,277,605,825,486,313,68,416,667,727,166,160,665,237,108,180,309,27,175,583,84,97,438,24,375,579,942,513,227,155,654,174,93,879,571,110,168,738,888,811,981,437,545,316,340,769,942,488,259,999,197,737,684,360,495,707,992,644,396,553,557,237,962,867,868,136,584,407,35,51,871,883,521,439,54,300,232,419,242,364,774,899,334,666,942,964,921,216,466,688,889,6,247,582,371,943,87,605,924,372,250,299,651,74,896,511,594,149,103,369,935,953,274,604,921,862,330,462,208,768,234,953,841,826,533,724,403,751,209,585,207,229,807,522,22,129,781,336,559,973,263,503,61,416,480,324,641,576,844,230,511,120,793,948,14,139,665,799,487,708,908,672,564,879,526,845,622,372,130,75,697,796,324,685,968,433,950,359,171,249,683,610,580,584,521,670,669,106,212,58,204,829,23,589,206,321,872,183,689,860,694,315,893,922,438,509,488,904,816,285,575,804,346,205,233,16,317,886,452,228,568,362,870,477,32,557,901,854,898,922,373,119,906,51,668,569,41,629,734,493,821,428,819,447,729,378,80,166,320,106,88,233,217,561,648,685,597,161,506,653,847,739,432,442,483,142,777,311,605,839,973,129,216,590,181,576,932,45,326,826,340,780,106,213,170,320,345,962,692,5,431,370,448,409,386,696,643,953,946,251,250,190,441,360,784,205,89,167,240,205,174,110,104,339,847,119,332,142,942,970,330,576,288,780,858,317,639,923,726,918,275,953,436,475,377,674,940,54,351,734,345,255,680,513,136,51,441,21,698,437,368,676,125,584,406,31,894,235,600,965,666,17,341,608,927,355,583,494,709,579,785,932,762,496,416,775,81,259,718", +"741,673,68,635,70,976,380,79,211,582,248,675,856,450,637,310,204,306,903,387,501,277,380,779,936,314,236,987,718,347,765,759,663,9,582,979,998,815,892,127,439,51,239,816,42,730,990,520,939,908,358,200,569,746,724,55,577,814,31,473,671,76,463,182,770,27,410,892,99,692,20,619,625,212,426,629,930,765,628,898,0,230,448,214,436,205,404,69,52,140,293,818,174,54,57,223,373,970,450,853,38,515,587,435,154,407,435,472,945,592,934,763,968,250,311,317,685,633,732,178,980,278,645,722,326,65,37,686,906,973,31,31,337,138,638,162,446,652,508,976,636,758,716,69,206,319,609,975,313,667,904,919,297,126,29,554,473,787,930,700,112,922,787,77,59,501,981,917,647,614,41,903,831,335,842,920,557,174,962,871,920,924,287,268,836,430,549,540,215,992,360,387,131,500,813,397,395,421,229,601,646,267,163,832,590,520,609,251,628,387,629,695,118,685,117,11,836,655,266,525,858,814,465,564,435,395,760,173,307,762,524,701,331,796,76,623,285,228,12,213,877,320,142,920,643,237,816,662,606,316,641,101,974,865,926,616,807,26,138,154,429,155,929,213,232,856,723,377,221,360,808,890,371,268,462,916,992,34,597,552,617,530,487,205,785,725,586,416,405,471,267,340,424,299,55,3,69,448,912,922,287,442,676,454,316,28,680,824,988,437,568,863,78,226,307,516,272,556,753,486,727,877,454,606,181,215,914,158,133,402,601,854,490,439,491,88,712,907,946,518,1000,6,59,1000,899,828,381,892,889,120,897,711,718,843,633,424,566,485,35,169,586,391,97,432,861,544,416,137,717,359,96,454,598,159,709,366,78,937,916,776,473,623,626,623,265,23,318,797,61,380,798,594,374,950,545,212,439,861,407,138,94,667,546,686,63,899,803,730,729,47,351,842,145,369,304,915,374,600,210,105,138,860,490,476,335,469,53,634,849,676,867,51,637,789,941,180,869,478,808,997,535,251,159,676,583,413,450,684,446,247,900,536,588,301,267,780,432,150,252,725,564,219,893,229,33,553,619,37,872,846,282,971,7,309,113,374,556,336,979,624,563,349,916,761,379,556,785,786,311,908,497,923,257,913,993,242,977,827,350,935,648,667,766,754,578,985,143,578,876,190,546,941,578,274,604,505,785,269,613,434,161,395,294,625,519,19,822,97,421,85,169,792,832,888,390,296,122,258,999,144,672,931,687,106,700,254,603,752,578,989,64,276,651,288,207,225,302,862,927,23,596,630,719,666,858,866,440,798,226,299,736,675,715,677,472,340,684,214,932,237,383,570,767,739,800,957,716,124,747,992,763,861,624,788,420,882,624,201,850,739,570,873,302,726,400,490,918,316,358,385,879,280,538,78,872,881,778,224,599,410,176,804,656,445,157,939,399,106,439,774,768,322,586,137,66,730,56,743,689,606,143,861,716,713,525,733,38,20,597,296,515,170,70,229,781,453,140,985,108,500,23,574,210,412,242,662,448,608,396,144,462,823,634,309,310,177,58,854,202,672,425,279,530,502,210,231,620,215,223,426,335,597,868,630,434,499,118,473,862,519,410,713,987,760,814,680,919,897,858,320,591,181,812,104,401,884,289,687,599,608,60,963,216,697,594,627,116,865,550,476,131,218,806,641,410,762,834,612,828,245,55,730,52,714,955,99,2,384,818,229,743,699,940,700,281,777,514,470,430,570,822,60,371,306,471,354,114,138,86,878,303,858,445,624,710,253,456,669,804,859,637,409,360,63,165,494,458,998,231,343,107,350,720,64,486,953,328,187,759,598,338,855,669,197,203,88,737,489,73,766,199,532,249,855,314,780,451,994,537,762,594,658,652,88,280,888,77,398,384,497,64,883,835,177,981,735,688,463,978,140,966,694,348,409,284,907,890,939,184,646,912,69,777,414,716,429,63,620,611,456,994,16,740,366,802,832,699,688,126,845,540,649,1,426,953,561,75,592,271,444,326,811,852,400,675,813,221,623,36,523,68,891,930,158,219,948,564,947,190,97,453,784,704,713,188,78,370,2,608,494,595,53,519,274,858,402,862,300,932,423,214,662,607,175,829,319,919,161,688,537,41,885,894,608,130,831,35,272,718,896,591,470,457,55,676,965,26,445,869,166,512,172,395,665,171,966,821,807,762,146,876,102,85,282,242,761,399,671,897,484,46,637,304,316,571,541,770,876,683,675,878,368,66,27,926,973,110,193,129,797,170,92,641,379,710,469,216,279,993,38", +"644,703,454,557,352,223,484,962,329,265,617,259,4,369,278,933,956,160,793,649,733,858,246,726,27,539,192,735,571,858,436,474,337,979,557,824,953,211,952,365,972,923,389,986,622,847,542,315,917,466,398,769,467,185,145,462,467,690,618,892,305,280,94,446,914,624,833,124,311,108,449,352,589,608,24,538,402,747,963,967,230,0,339,598,207,37,779,627,70,531,607,536,148,572,148,317,651,421,194,436,892,602,229,654,510,833,609,549,789,481,378,204,337,396,989,361,103,237,125,501,810,715,225,58,399,499,384,883,551,601,706,37,152,79,574,497,538,492,266,455,260,555,910,686,440,736,276,860,918,520,380,659,122,674,457,423,917,354,24,175,21,969,975,880,902,773,715,198,361,816,373,132,691,25,38,545,161,504,491,180,389,812,751,557,711,143,353,974,953,625,564,210,187,110,517,182,460,910,310,969,484,963,339,950,9,560,829,352,903,851,778,998,454,588,650,818,887,311,829,88,868,673,511,640,587,92,868,858,5,613,934,121,228,664,180,782,163,403,696,881,528,770,736,920,65,265,68,363,442,846,919,616,649,907,797,674,507,269,275,840,424,591,616,984,902,291,511,979,483,767,6,348,485,37,499,921,422,53,289,732,435,194,511,188,300,121,188,310,574,803,932,370,687,566,483,566,968,372,263,632,212,640,306,305,279,540,235,287,787,215,727,891,508,995,979,444,994,31,620,75,386,7,659,281,650,112,462,4,111,947,812,298,346,254,527,145,176,186,355,830,247,615,707,626,230,492,299,496,962,47,974,728,201,522,268,550,576,344,185,570,903,405,627,165,137,759,949,614,362,861,868,529,531,507,320,738,410,852,712,680,150,788,995,277,933,43,942,862,754,634,294,363,153,123,666,464,845,205,71,409,546,745,912,422,379,318,396,442,899,696,39,9,875,638,424,24,353,302,768,929,522,182,913,799,162,230,719,462,686,296,401,690,167,769,642,366,824,317,433,506,207,830,565,794,281,350,631,581,715,467,691,248,362,339,862,306,489,624,736,170,705,818,245,922,192,718,169,944,852,786,92,33,861,85,313,354,792,337,444,877,139,958,499,723,22,939,799,783,162,461,629,117,616,563,122,310,627,111,70,296,467,105,675,228,103,972,652,473,290,266,232,554,909,877,136,584,914,264,221,141,259,952,597,658,29,824,268,154,449,606,764,475,593,681,799,161,850,194,122,24,633,153,112,861,702,354,183,119,697,944,631,248,126,287,885,189,243,818,476,478,895,188,917,315,450,790,759,273,222,830,495,455,884,620,951,656,331,14,27,898,484,523,291,170,131,827,314,630,333,112,248,878,443,884,998,671,2,738,333,770,623,951,677,887,346,493,735,783,933,528,332,483,899,471,595,631,355,461,424,12,555,355,414,566,959,617,788,695,253,48,706,277,559,119,577,657,751,869,582,232,43,430,1,349,688,814,566,120,184,351,768,257,811,985,863,580,912,29,32,219,148,351,306,11,477,603,117,434,196,643,774,66,929,906,973,759,448,161,796,694,416,36,239,173,156,178,307,405,157,133,582,308,936,532,478,762,366,377,607,425,247,645,558,317,604,913,226,127,508,119,98,358,2,486,854,80,672,326,592,288,938,487,326,351,90,179,907,667,366,894,252,882,324,204,727,565,908,101,783,876,922,280,219,111,13,701,410,113,632,797,843,725,900,266,908,587,502,451,473,613,730,107,892,357,7,328,469,628,201,854,943,809,490,218,613,371,530,232,243,276,501,91,256,740,264,861,785,546,474,777,338,650,691,194,343,989,69,626,143,649,172,1,411,370,73,961,546,189,767,161,164,571,463,572,990,833,365,714,717,583,872,359,5,920,929,397,68,438,652,484,335,571,29,557,454,164,642,335,88,907,948,490,310,685,820,625,11,879,550,720,18,391,338,623,227,870,426,679,534,809,247,998,888,494,279,961,874,900,251,842,141,356,12,220,850,415,698,20,880,293,498,705,197,903,246,990,487,222,350,771,230,585,715,174,110,913,380,226,754,358,955,66,872,628,688,973,299,121,50,505,489,433,953,227,653,906,239,333,58,895,891,283,25,35,936,9,442,713,632,152,62,513,510,971,819,701,782,253,714,334,931,614,93,60,297,314,68,283,342,75,180,858,844,494,824,864,626,255,762,593,58,24,167,809,119,852,83,792,697,45,457,26,77,261,356,174,252,252,789,337,914,747,725,272,141,477,833,505,278,963,962,901,362,68,172,393,815,604,469,592", +"701,602,786,930,793,902,378,361,173,22,917,733,260,683,164,325,86,359,250,451,883,826,138,107,229,625,418,918,725,459,143,338,610,986,870,679,996,629,870,655,401,546,956,443,65,430,205,194,615,279,746,758,657,989,811,110,146,303,387,306,898,471,242,71,728,334,203,598,556,145,125,729,222,694,692,271,918,893,947,850,448,339,0,487,742,764,983,413,296,375,897,564,693,134,263,198,246,269,4,692,966,259,992,408,547,162,521,954,46,199,415,591,79,575,719,549,453,243,542,107,414,204,484,251,413,999,953,372,757,982,354,706,492,409,245,820,780,812,55,474,611,589,679,643,929,404,269,780,824,109,720,457,216,414,341,312,413,318,668,523,806,887,268,19,434,447,870,973,550,144,260,255,889,698,886,101,288,805,568,698,849,983,632,539,888,850,691,745,534,667,138,121,791,821,27,352,374,630,321,568,928,438,15,818,94,8,526,802,404,573,42,935,45,80,884,798,282,540,871,180,621,217,310,33,788,107,663,805,983,4,991,908,176,411,387,890,828,605,188,545,552,687,203,937,238,715,305,338,480,116,385,306,430,98,522,603,649,652,875,966,442,530,665,953,366,236,899,211,514,276,798,267,168,852,923,270,920,565,102,481,539,484,240,869,82,534,297,443,414,152,496,181,685,476,398,257,238,48,329,679,610,551,519,506,593,165,141,631,49,311,508,879,165,616,651,402,181,47,259,143,638,821,581,684,451,273,989,63,649,484,443,301,595,329,263,430,671,990,556,749,966,212,651,641,305,583,559,589,309,909,43,643,66,561,789,550,873,12,327,522,65,187,751,178,137,719,965,932,921,931,608,539,580,523,175,242,683,833,604,685,503,593,428,207,887,292,401,88,258,923,475,660,440,734,20,832,972,300,705,886,317,317,14,43,209,859,502,220,89,634,210,698,665,897,56,678,43,921,552,646,48,769,455,685,491,721,990,557,325,29,808,923,290,137,216,530,614,831,178,588,283,597,60,328,67,889,67,676,376,308,82,964,243,144,484,23,874,876,430,986,158,484,99,418,501,924,220,980,219,983,895,137,173,470,684,771,984,23,826,482,387,458,923,591,182,545,28,738,994,645,620,885,169,21,942,723,58,315,531,287,27,856,310,166,742,591,537,486,792,400,607,970,45,488,178,808,149,241,215,153,412,861,94,372,111,809,119,302,809,402,735,463,692,643,307,102,648,549,897,201,897,209,390,483,606,66,445,348,145,975,672,164,644,840,527,602,683,139,26,883,723,680,124,281,57,281,812,915,376,612,684,504,419,406,310,709,292,780,992,28,197,613,300,432,76,475,618,511,526,460,914,894,74,756,836,338,555,337,293,317,413,658,273,876,777,37,957,947,804,86,731,644,10,604,110,989,780,649,507,54,69,772,281,346,685,754,694,619,729,829,518,642,248,586,994,863,962,747,108,777,246,773,516,138,222,166,490,600,484,111,72,55,566,250,476,749,177,239,623,627,857,479,969,303,660,316,659,415,710,175,33,907,723,304,644,512,264,854,633,244,304,803,472,63,84,5,181,98,433,645,750,319,797,132,340,601,43,610,815,836,387,539,191,963,862,327,683,244,232,532,956,250,278,60,377,33,756,736,647,325,897,100,604,352,992,52,207,925,530,446,712,762,855,490,64,427,504,524,124,969,406,152,698,211,410,675,279,939,273,353,607,216,252,330,892,960,898,2,748,829,30,952,959,743,255,26,876,98,461,29,429,906,757,88,512,351,520,259,409,944,928,597,116,297,342,896,825,836,467,337,212,240,657,445,179,806,294,494,53,250,202,948,66,351,742,546,196,61,123,908,346,798,89,854,947,877,985,268,457,763,324,363,209,536,460,454,87,765,554,260,214,705,673,697,560,517,576,548,251,154,560,185,820,51,486,222,117,699,832,387,491,134,308,300,931,435,581,505,367,757,374,257,916,62,893,607,146,609,437,393,299,398,895,462,431,120,86,470,80,835,627,753,777,307,595,485,717,552,17,489,811,311,780,508,112,984,627,656,5,992,453,133,754,806,396,398,998,238,627,688,230,53,27,287,925,269,314,27,934,573,177,398,856,241,905,297,157,197,951,916,778,437,747,465,37,917,321,945,432,547,691,630,573,727,654,671,847,853,982,629,77,39,677,362,501,293,802,443,548,909,467,884,818,644,647,992,882,632,772,166,383,615,27,801,284,744,296,22,262,582,939,500,614,884,716,77,95,623,294,410,148,485,995,978,348,839,956,911,334,387", +"782,256,497,80,354,231,977,385,393,190,301,932,205,385,524,244,616,687,285,627,707,659,664,369,799,877,659,18,322,169,496,513,557,351,364,210,244,863,490,510,737,496,670,449,313,181,931,554,522,737,348,255,663,259,360,910,514,193,557,831,191,374,423,913,195,893,120,771,166,651,277,871,699,400,716,824,735,926,870,312,214,598,487,0,814,347,391,248,410,804,476,679,394,518,637,471,786,664,574,413,591,524,910,156,244,18,389,925,21,641,157,652,281,758,607,664,289,395,807,193,722,420,84,185,704,221,429,307,677,593,506,372,403,115,408,392,778,11,378,796,515,973,314,703,377,830,50,767,426,8,225,12,123,68,208,385,9,136,575,398,527,425,956,649,765,781,118,549,370,725,396,173,354,749,744,793,834,57,468,740,433,668,537,871,123,164,373,384,869,184,219,833,781,911,509,147,959,223,821,381,649,233,998,413,873,214,656,518,792,998,803,851,423,121,24,387,290,512,681,131,134,480,726,188,778,379,804,391,102,351,737,996,942,872,865,422,116,302,942,619,114,129,407,390,288,611,876,654,340,86,18,767,873,152,812,135,646,857,744,401,178,522,41,860,650,839,687,819,754,213,462,550,772,785,857,897,470,65,988,871,824,706,466,373,986,559,629,360,822,171,294,908,992,277,232,247,783,174,387,658,560,330,748,951,130,486,434,692,849,42,498,667,976,764,383,521,683,79,853,40,900,310,775,680,192,972,40,551,718,169,666,147,186,664,527,29,924,426,634,580,530,343,469,194,858,409,160,369,710,863,966,12,838,493,89,369,360,379,942,174,486,316,49,783,96,793,991,853,442,810,114,609,540,281,7,9,638,363,368,763,191,341,546,552,452,60,63,29,540,694,273,816,609,618,830,81,568,712,648,153,213,778,961,920,147,537,804,842,280,646,502,982,225,54,124,429,834,635,600,803,814,149,324,353,578,279,919,160,527,295,419,707,820,594,958,9,566,564,909,64,243,851,497,786,46,200,893,314,104,205,953,590,184,326,562,618,91,930,934,3,30,353,104,83,941,575,342,821,687,809,522,143,422,726,23,809,800,983,987,719,52,413,640,687,683,189,505,382,535,555,500,431,361,939,838,230,545,236,587,271,192,459,857,149,84,524,348,775,754,661,204,730,881,464,800,714,818,458,415,340,793,432,335,801,204,213,989,419,372,960,200,688,179,383,410,985,164,288,230,679,732,989,99,10,738,285,91,671,39,279,611,414,43,212,661,271,740,24,973,478,976,256,919,465,190,173,667,422,449,248,224,820,1000,638,67,6,117,17,387,712,833,254,794,872,345,546,155,210,404,336,456,999,631,764,613,818,72,735,938,818,46,321,574,143,268,646,243,109,936,988,17,153,642,351,299,518,979,430,643,522,9,663,858,477,397,360,787,391,178,454,328,682,138,490,790,874,621,620,834,330,636,259,123,798,787,491,895,154,135,568,15,488,579,387,232,598,145,335,495,805,862,285,580,2,240,119,142,749,21,585,284,598,3,974,206,267,518,838,844,308,739,792,925,263,312,938,367,98,143,23,660,103,509,133,999,592,399,774,673,846,961,544,947,290,437,458,16,360,539,956,348,780,229,87,6,69,819,654,987,360,804,651,239,572,225,940,179,25,987,911,953,410,215,54,598,225,235,422,754,689,293,382,334,461,18,269,967,511,662,165,895,240,119,328,125,688,691,450,811,979,391,197,799,189,56,512,575,76,491,636,355,532,972,432,492,1,131,664,666,929,527,136,988,16,891,342,632,486,428,628,474,804,707,256,207,621,15,494,649,78,53,614,463,510,643,695,972,745,627,147,3,362,422,401,281,739,928,70,601,504,485,927,798,633,421,45,576,626,437,565,916,856,804,721,260,25,163,291,491,911,389,707,312,97,143,678,367,816,267,902,462,963,434,949,673,464,548,172,673,522,770,36,871,114,484,736,473,26,808,940,625,104,935,705,218,963,247,269,286,703,75,825,259,709,459,96,883,38,316,895,99,419,46,9,169,968,988,993,449,888,139,325,179,510,302,545,3,567,625,813,377,70,490,333,457,126,174,894,878,768,850,399,535,419,704,280,598,840,897,291,566,66,79,688,768,124,982,51,837,7,554,590,694,566,621,405,462,573,22,515,451,441,321,829,222,277,256,680,899,759,918,187,669,979,900,858,604,408,919,104,982,570,231,611,132,33,691,764,875,780,722,516,560,829,559,608,189,920,949,826,644,952,575,944,710,98,995,848,191,416", +"870,997,517,595,862,910,227,671,793,134,305,89,751,492,254,45,803,576,666,727,20,272,836,208,819,111,238,369,222,208,495,217,69,4,557,388,239,411,564,463,425,508,67,219,472,909,693,915,916,671,821,889,370,256,138,160,568,580,799,264,253,415,60,538,986,32,723,776,61,190,949,940,202,760,22,624,185,934,529,20,436,207,742,814,0,557,41,734,603,383,164,529,579,951,610,703,153,651,264,727,585,487,127,223,634,205,293,725,464,241,225,809,461,968,992,639,31,686,155,147,447,276,306,952,53,490,554,460,187,840,849,356,270,386,380,309,12,582,616,847,271,493,953,28,446,520,630,114,343,309,366,305,489,724,736,317,488,107,219,94,34,500,625,333,628,951,436,494,317,457,813,536,320,540,729,849,654,889,210,56,275,677,997,620,403,612,363,813,942,620,434,762,361,974,828,695,873,253,827,493,227,404,637,237,53,7,478,69,276,284,886,635,171,672,783,396,582,303,486,506,928,612,875,334,513,313,649,510,742,368,337,948,576,329,691,238,511,686,673,370,366,992,432,810,133,524,20,741,150,275,937,380,78,876,692,509,277,367,779,454,797,775,439,965,715,534,748,390,801,540,549,53,350,480,183,4,893,404,84,689,582,930,19,980,433,740,666,104,56,472,610,992,340,756,962,8,53,58,351,518,698,511,912,696,85,411,174,645,374,733,97,539,29,994,702,879,754,789,387,80,303,165,927,770,413,147,900,320,831,254,166,692,258,499,459,778,416,694,24,611,477,143,68,16,225,474,871,933,687,347,611,118,894,830,122,459,865,267,560,628,986,947,700,110,686,636,367,501,420,635,581,228,954,624,694,329,240,741,807,549,619,74,93,125,435,358,456,815,985,589,390,760,371,142,308,531,453,216,754,912,736,696,746,517,191,271,388,689,370,1000,998,597,78,209,972,833,997,874,825,856,64,730,800,937,53,268,881,880,268,135,98,752,324,846,521,591,538,533,714,892,450,839,740,256,241,360,23,338,420,650,671,88,359,399,217,571,756,569,438,88,350,852,560,91,864,650,105,475,355,566,369,51,427,71,730,354,846,168,948,240,392,555,391,308,30,266,293,516,517,681,508,358,105,475,140,720,327,953,926,830,181,867,695,123,811,497,850,915,275,794,306,151,267,100,827,519,78,138,676,842,522,960,941,73,162,682,382,372,63,345,591,78,39,722,805,997,504,92,937,77,610,976,65,88,287,359,53,777,796,987,987,292,733,414,346,442,901,161,714,310,554,667,547,384,316,202,594,788,135,453,317,509,182,585,50,223,955,25,624,500,700,824,801,889,826,731,327,90,876,253,181,51,987,481,322,656,700,868,104,336,930,925,571,518,335,227,178,777,761,851,216,689,294,910,661,305,24,514,653,338,412,624,844,456,670,70,179,805,134,581,295,131,677,262,647,107,515,751,949,395,868,479,187,122,950,179,771,452,685,110,313,342,431,21,173,490,267,754,694,57,460,121,261,571,807,166,648,236,356,4,233,297,545,626,815,720,519,463,514,259,198,510,294,601,64,582,893,7,378,79,273,548,986,625,646,128,586,920,184,439,431,753,552,701,522,896,806,677,760,743,327,150,746,114,392,937,309,626,260,912,468,587,420,532,87,274,564,433,194,509,295,816,765,630,605,360,437,754,668,396,845,716,66,632,41,809,522,725,340,127,467,280,610,797,306,781,87,604,553,546,78,425,488,621,16,932,997,240,550,793,175,806,912,372,1,330,967,424,80,256,83,28,535,140,929,924,34,14,562,702,751,19,143,394,100,976,586,991,861,90,321,991,215,775,328,438,351,835,908,58,189,129,559,704,149,279,882,430,484,475,275,727,909,252,158,702,541,227,184,160,976,119,276,693,953,391,680,593,965,865,970,747,185,620,978,876,167,705,997,699,792,961,223,61,563,442,282,485,487,176,369,884,319,589,180,440,498,342,563,603,931,597,636,755,953,814,967,68,858,49,578,101,288,326,959,228,104,635,486,25,365,727,905,628,557,273,314,302,51,452,766,344,633,454,819,376,449,935,4,751,786,720,137,112,363,256,349,261,103,118,489,399,72,30,16,101,85,572,929,583,32,437,853,300,146,41,489,526,122,267,146,213,485,47,860,424,752,396,770,634,614,30,696,894,394,806,402,387,782,200,855,177,373,761,254,416,973,49,556,856,696,345,990,638,611,949,602,237,83,510,397,850,934,3,922,952,833,903,301,83,601,115,547,648,636,431,444,89,419,150", +"947,805,255,94,234,48,914,639,509,824,250,250,300,491,56,196,55,905,433,694,726,260,680,116,946,59,928,51,250,899,683,949,129,264,881,107,866,924,739,481,70,709,640,69,942,747,618,579,142,976,91,867,524,280,870,374,390,100,67,29,860,259,657,225,869,603,521,991,351,146,957,605,107,67,1000,405,215,768,561,836,205,37,764,347,557,0,746,13,869,856,879,815,324,563,728,771,503,888,338,275,133,422,436,385,586,533,188,959,762,684,174,234,348,109,7,327,315,801,718,25,312,9,853,623,171,317,12,502,355,690,561,125,990,936,689,226,377,380,77,936,609,597,356,715,890,961,831,91,344,685,913,515,485,125,390,706,85,246,604,99,938,800,85,692,737,208,988,445,54,307,806,277,761,218,97,300,8,194,254,494,753,902,734,945,16,450,642,528,39,998,181,19,271,401,808,762,123,802,70,675,497,409,285,194,707,518,490,156,777,885,438,136,852,277,732,106,854,573,990,578,481,628,672,479,971,388,273,238,84,972,358,310,413,70,260,861,622,805,317,808,47,5,637,715,730,347,36,183,231,759,911,195,149,232,881,75,429,101,664,266,51,275,324,324,666,414,743,376,518,347,562,634,19,25,707,467,833,928,661,310,260,681,833,868,809,563,23,206,748,299,544,511,783,444,103,400,519,410,229,416,559,732,910,685,463,710,871,519,888,260,158,958,889,686,239,368,517,804,792,650,590,837,594,478,423,628,485,85,290,301,159,429,247,215,786,696,380,271,656,518,730,430,79,543,19,531,233,262,805,280,843,179,702,869,951,204,171,732,20,729,776,313,369,550,650,744,667,925,4,992,356,850,590,886,353,859,258,607,279,121,607,113,852,66,358,831,600,392,793,800,834,686,281,396,233,104,582,579,952,874,913,168,393,722,434,693,149,103,455,328,149,596,821,842,231,494,375,174,122,533,858,754,107,921,637,20,315,741,162,969,309,793,373,986,390,404,77,161,25,578,146,8,361,253,234,279,15,883,486,460,172,52,917,240,554,725,484,278,546,935,666,914,889,201,686,738,29,575,601,65,447,604,513,300,279,372,230,620,705,817,869,694,668,956,612,832,444,77,730,750,875,605,568,173,463,62,431,967,560,85,671,685,225,509,234,474,301,316,171,756,942,51,829,715,940,53,289,924,115,503,678,913,171,488,992,102,394,544,174,186,585,913,6,776,479,225,65,586,900,985,326,2,150,712,822,697,968,448,188,970,594,927,257,915,548,622,115,846,352,959,256,828,854,880,551,899,542,715,146,17,373,231,523,947,560,693,595,330,683,345,488,942,289,587,380,730,347,818,871,168,984,515,752,142,572,304,30,213,361,427,991,583,831,993,84,70,235,678,373,497,960,268,669,131,785,204,958,654,271,965,467,509,371,923,690,751,477,233,396,380,453,701,25,182,618,737,204,415,451,922,110,387,227,825,838,817,221,404,22,642,142,427,959,829,445,492,735,619,684,435,33,73,482,925,756,735,687,71,189,971,110,218,744,247,483,881,477,552,548,26,812,264,708,406,998,418,968,859,70,744,807,903,593,98,632,462,474,754,552,859,658,207,533,460,691,295,603,534,118,341,822,57,217,547,726,704,988,800,528,933,316,916,64,764,211,619,594,939,467,818,441,815,545,926,962,810,724,960,933,818,444,79,816,323,414,536,933,795,820,31,790,672,183,357,782,208,643,350,198,904,750,925,612,152,860,846,951,148,188,612,259,237,777,859,244,351,447,834,615,685,572,661,250,282,109,840,872,453,151,644,349,117,658,355,937,545,741,28,630,804,170,389,293,169,722,720,634,507,813,270,457,788,734,187,957,229,457,721,749,161,667,663,262,960,141,36,21,801,585,631,661,446,364,72,395,613,167,25,280,490,845,488,567,172,745,109,27,361,995,474,378,32,117,234,941,636,643,110,493,583,55,411,619,590,83,713,695,52,28,866,383,421,162,494,674,119,684,601,799,637,382,440,106,46,169,993,630,479,845,273,687,589,955,865,393,347,735,433,283,879,483,125,951,899,60,729,85,31,79,790,414,263,21,125,758,915,566,893,982,895,369,823,844,992,597,610,951,631,756,242,523,562,638,74,171,410,456,114,494,842,434,572,769,430,527,884,940,975,473,358,548,250,917,237,924,396,706,225,513,655,289,887,993,25,816,303,258,589,8,130,892,865,792,990,763,559,146,507,392,287,932,407,906,351,376,89,984,657,179,763,572,405,978,537,329,186,896,999,993,191", +"159,922,417,675,644,531,681,703,839,608,368,531,780,299,414,69,462,598,188,916,39,606,607,113,537,637,360,589,787,615,463,914,488,190,950,151,203,11,891,928,901,892,751,990,656,484,140,450,64,754,491,25,753,732,301,113,177,968,926,999,864,524,177,789,457,38,677,346,269,838,658,502,479,752,783,65,159,303,911,922,404,779,983,391,41,746,0,1000,640,445,26,335,454,850,944,211,283,244,609,194,655,887,828,551,279,622,111,852,340,964,322,579,779,725,948,409,498,832,706,134,612,181,94,721,570,928,195,712,471,697,55,926,110,169,628,681,495,608,35,191,497,600,658,194,349,512,813,908,911,978,870,556,733,655,310,799,786,671,6,525,891,612,597,214,344,102,791,603,693,949,118,283,425,262,900,834,376,665,708,316,259,215,426,890,466,665,141,140,782,311,974,65,499,257,615,311,487,991,248,734,751,694,756,811,606,398,925,280,424,465,314,678,785,28,586,607,757,783,988,128,523,468,568,41,978,440,685,804,862,682,739,61,842,23,675,722,34,316,831,444,967,919,240,190,677,775,423,175,693,676,319,890,798,429,374,502,486,241,997,760,9,739,880,338,754,928,204,724,572,440,355,70,148,523,747,439,749,623,642,883,940,910,322,957,29,915,350,413,249,118,802,529,851,710,299,775,885,94,236,79,242,954,472,354,248,163,212,815,930,396,347,59,120,121,57,561,389,599,618,970,49,172,730,951,456,274,784,905,915,28,570,197,732,258,946,706,925,16,77,865,48,428,519,278,671,282,740,714,68,246,732,330,339,241,93,700,733,938,840,559,770,801,81,634,514,758,628,318,103,524,815,484,186,493,444,102,380,473,650,178,641,662,898,737,577,22,378,848,110,766,261,454,532,655,634,667,482,582,485,959,659,44,791,2,528,738,197,438,457,350,178,663,105,973,878,702,668,402,317,234,37,874,73,749,582,357,938,584,741,887,977,172,892,844,58,598,396,506,507,530,446,291,467,370,539,839,899,956,77,974,451,308,162,438,819,738,652,901,414,398,587,210,654,794,323,619,486,441,105,164,64,99,652,745,19,520,68,283,161,431,367,107,380,258,969,395,196,98,175,252,224,852,627,367,963,978,732,556,979,702,826,394,475,851,925,142,800,75,324,45,686,819,999,742,948,250,180,382,40,758,571,832,766,567,754,655,537,767,399,68,975,212,40,599,898,345,878,3,538,883,56,31,742,999,600,243,888,206,738,150,109,687,294,114,707,990,218,819,277,535,187,289,305,857,784,149,221,834,737,799,328,752,99,947,576,332,672,899,59,411,443,104,299,17,336,401,222,320,170,166,528,957,449,99,106,230,878,356,515,990,589,22,318,199,816,91,591,777,155,698,4,699,644,384,621,893,334,673,489,919,675,493,886,886,173,33,538,316,116,446,32,90,48,601,60,687,939,216,635,423,984,688,490,622,657,918,394,432,85,545,700,884,877,149,55,246,761,543,19,307,427,62,433,419,130,501,367,330,627,902,714,821,682,929,731,479,213,642,618,87,879,325,724,271,905,512,885,812,316,830,927,148,685,991,59,706,533,168,31,420,24,311,803,836,857,946,363,521,929,587,741,770,568,442,636,103,440,831,416,34,890,402,252,137,524,778,502,65,621,263,381,993,385,220,413,909,200,630,466,964,613,516,227,619,893,688,183,407,586,903,32,747,16,738,684,72,520,204,863,89,878,886,368,614,346,557,65,318,292,214,153,691,473,443,846,875,726,561,483,466,179,894,909,450,781,374,293,841,23,870,915,593,813,53,80,377,452,797,321,928,772,434,309,742,810,231,839,200,578,686,141,80,996,615,38,463,183,166,433,663,26,656,970,59,726,423,974,9,568,707,633,488,209,213,159,246,233,114,810,250,632,593,658,209,490,508,488,462,551,88,321,424,527,811,931,216,250,82,281,3,902,722,870,804,650,560,757,883,266,724,488,141,339,701,669,518,545,448,92,908,194,580,411,617,454,677,492,86,697,709,950,29,456,920,33,433,522,582,667,683,25,808,804,146,321,254,349,644,797,32,649,735,686,244,569,454,188,813,505,899,978,17,435,68,424,75,152,199,584,19,682,527,322,9,525,387,630,139,419,517,440,272,934,201,627,71,52,717,888,622,406,616,512,933,932,797,300,23,985,581,341,120,680,417,752,674,563,112,178,460,336,654,6,48,800,149,84,830,656,800,943,28,88,638,532,761,79,873,298,573,172,708,333,582,774,767,28,996,880,159", +"464,332,518,781,180,336,70,192,152,952,491,728,861,906,615,374,526,694,760,473,590,627,124,877,504,929,824,281,600,522,49,682,336,12,382,436,723,314,50,350,151,44,59,606,175,314,524,146,692,190,707,982,228,46,672,768,4,782,332,763,652,635,566,357,253,414,28,21,859,706,827,310,392,403,283,622,60,683,739,975,69,627,413,248,734,13,1000,0,865,273,347,460,77,449,519,11,291,187,46,455,742,425,387,426,912,666,274,793,580,830,847,214,342,769,820,661,156,321,473,79,25,995,376,585,491,481,95,255,202,438,433,642,501,295,217,810,834,466,380,490,658,706,242,241,891,391,7,947,405,461,225,927,37,385,126,54,643,546,280,611,681,160,191,480,682,520,436,293,321,431,646,962,40,18,32,155,471,867,129,117,46,60,326,585,627,752,368,436,965,379,620,896,118,40,974,908,963,389,800,952,939,515,864,895,667,669,559,187,458,953,19,581,264,983,984,349,959,805,353,613,64,291,283,18,632,257,859,595,600,678,274,570,331,147,825,627,218,704,478,851,686,345,42,398,134,80,230,680,382,515,904,584,844,821,723,890,147,802,239,668,680,255,34,562,148,147,521,435,611,355,775,683,708,140,535,934,778,699,274,722,638,622,683,274,622,850,203,94,344,946,334,542,714,887,451,356,513,787,78,442,667,373,333,480,944,848,640,471,632,228,48,348,480,585,418,768,892,278,380,856,580,360,928,893,342,994,718,861,3,913,33,617,355,722,692,262,749,390,11,510,78,869,171,327,867,238,344,260,853,548,573,288,886,184,105,321,206,675,742,630,944,378,796,799,402,867,771,546,625,119,110,315,3,914,654,880,742,999,866,75,899,357,645,680,108,47,534,678,531,173,76,602,372,978,444,112,802,242,768,321,361,287,105,737,445,459,314,824,357,291,130,11,900,237,929,465,926,119,123,735,954,449,756,290,595,112,421,160,792,887,396,285,811,24,494,470,387,56,200,585,422,893,974,432,692,287,879,343,33,1,212,204,975,94,353,806,903,625,289,2,974,366,139,870,586,880,625,874,835,597,717,198,480,324,664,21,616,388,307,85,862,917,807,958,168,844,836,817,441,291,714,594,972,293,516,919,137,205,652,601,742,798,691,784,864,3,850,219,767,326,568,784,718,856,213,280,167,639,817,136,734,355,34,736,380,915,915,508,749,40,252,489,670,954,458,148,592,581,795,676,211,410,481,850,538,242,407,950,944,938,539,365,476,706,447,775,681,853,728,618,280,634,792,515,112,624,389,55,782,602,73,74,343,699,389,326,575,550,776,94,149,829,949,173,648,682,956,27,603,797,352,147,850,82,980,44,977,248,343,879,558,989,263,105,189,752,190,550,901,999,496,80,340,867,999,215,617,969,47,672,709,654,99,822,721,527,548,766,326,988,376,853,422,526,950,812,74,739,804,262,328,131,866,751,325,33,878,736,314,942,562,386,585,59,640,151,981,177,469,81,308,660,187,647,190,49,936,984,91,208,155,892,103,351,387,494,823,508,408,590,531,696,261,647,364,579,662,619,419,516,422,697,960,700,547,466,644,931,910,295,961,447,510,76,109,513,9,20,678,476,863,574,829,740,135,510,599,650,448,562,727,840,559,470,470,350,934,692,896,499,926,528,280,996,736,507,707,510,113,150,68,207,288,444,626,239,572,574,72,972,327,126,541,722,724,501,948,352,26,881,739,837,698,674,716,920,365,930,413,124,752,857,249,945,928,543,267,913,287,958,860,824,46,672,109,921,79,526,827,696,762,832,326,130,472,802,72,342,980,616,621,261,114,710,347,6,957,724,234,62,139,150,973,975,207,733,765,843,223,369,351,685,797,729,847,501,971,661,13,880,916,974,758,728,761,107,922,943,546,35,283,588,14,777,144,664,369,483,94,464,214,182,257,446,34,16,809,20,281,812,737,505,500,47,347,504,237,687,903,1,559,541,748,552,21,6,673,399,515,610,43,207,726,934,502,276,808,630,587,691,132,429,424,984,581,865,748,812,270,838,208,662,855,443,545,85,406,197,799,997,681,575,525,717,832,914,689,744,164,92,440,785,553,888,373,16,483,847,88,628,177,259,134,581,347,151,630,453,427,110,42,41,296,92,718,715,613,696,278,920,461,533,333,474,454,655,784,760,783,20,180,345,15,465,758,293,822,716,4,487,898,83,339,398,565,740,265,119,802,442,203,731,767,395,680,774,32,253,786,974,664,650,783,251,183,250,593,112,459,679", +"412,116,417,143,361,936,970,930,287,465,354,444,242,31,330,264,701,529,297,544,303,532,624,36,789,336,133,357,606,322,574,736,920,482,499,977,649,622,532,52,837,666,810,903,217,293,813,852,7,725,481,191,668,377,109,315,636,520,918,361,188,97,584,728,698,588,567,817,142,813,116,203,570,455,753,827,716,174,137,359,52,70,296,410,603,869,640,865,0,67,85,37,385,208,26,633,138,113,817,670,650,808,663,434,194,448,614,770,258,273,209,807,214,345,767,773,167,876,887,790,317,432,456,387,43,974,629,652,105,532,479,197,101,126,989,324,523,180,588,644,202,666,102,156,536,833,246,618,58,490,216,719,673,841,974,981,77,874,306,390,840,189,696,535,84,341,723,849,142,957,270,509,404,699,395,309,587,218,520,857,173,744,99,23,415,648,232,904,455,204,922,329,919,631,917,474,881,575,150,843,102,544,154,927,98,893,92,684,738,589,766,680,422,137,277,192,362,51,249,212,909,272,843,44,539,944,93,832,740,933,483,501,316,10,863,380,798,641,925,354,298,181,533,566,366,333,290,448,590,287,650,545,685,198,252,555,952,175,622,704,379,623,86,179,356,783,284,123,177,829,666,396,814,775,611,544,913,550,775,191,1,96,322,956,334,469,906,465,85,659,119,333,673,31,27,959,590,505,171,663,319,306,764,9,84,647,760,33,392,359,942,790,42,640,622,99,897,919,197,384,996,181,20,351,429,554,925,348,514,149,540,393,786,221,969,157,533,711,380,48,665,765,48,468,166,352,506,204,730,383,35,575,326,123,576,318,174,544,901,619,32,3,948,890,206,520,319,902,278,733,155,895,392,904,847,276,740,127,333,157,624,154,273,865,76,837,689,796,74,869,16,436,792,584,486,278,563,888,683,804,856,717,993,509,736,50,783,562,81,921,743,636,116,781,19,905,328,600,420,414,255,226,165,106,495,36,831,560,414,837,710,729,798,229,580,62,169,538,934,40,201,718,977,741,142,990,423,394,162,634,205,31,755,478,885,110,580,642,61,165,234,755,370,587,843,993,49,387,708,626,146,30,89,617,771,122,38,692,388,881,621,70,212,189,272,977,510,625,485,768,806,832,894,781,354,277,277,913,768,230,798,758,213,885,523,459,511,985,665,427,88,972,751,279,786,277,55,461,798,103,916,989,420,926,999,859,631,843,450,519,774,460,479,538,277,541,214,266,173,388,337,701,864,868,544,886,272,629,683,288,787,863,354,560,72,968,943,962,1000,326,375,246,96,385,423,14,178,39,811,409,329,496,319,482,529,503,375,48,488,41,591,516,778,628,571,563,50,726,280,633,413,878,59,30,891,753,975,442,645,914,939,562,700,273,124,269,2,730,494,727,261,167,202,403,510,148,263,55,334,813,346,588,154,562,720,935,668,107,535,965,19,682,417,280,298,17,721,384,826,479,239,770,76,120,412,138,306,99,262,244,529,184,78,783,250,836,734,178,939,582,618,223,15,178,606,836,506,653,392,519,388,912,400,714,694,649,343,228,210,298,366,343,554,868,925,324,480,352,592,203,688,519,116,57,607,279,364,556,420,187,734,413,168,560,190,260,134,517,453,495,195,483,496,475,99,151,615,460,127,150,679,466,983,349,135,498,180,61,13,836,907,552,399,908,777,708,142,353,390,500,409,358,556,441,710,923,839,363,484,68,788,766,442,875,77,334,347,372,156,738,903,957,151,37,385,170,292,31,297,488,328,161,356,827,511,980,997,910,815,895,385,345,216,942,709,950,424,726,683,214,868,813,799,729,86,852,110,115,436,50,500,617,371,345,254,487,800,590,628,723,302,118,865,37,200,913,377,119,935,846,670,819,976,206,214,721,374,979,775,746,217,685,757,180,453,662,546,623,749,299,159,320,52,533,956,848,927,467,283,758,286,803,725,588,715,336,564,567,926,109,457,495,93,508,133,392,970,769,546,339,468,241,109,824,439,855,996,32,853,33,164,191,904,881,157,742,714,922,733,233,553,94,173,490,853,364,567,199,120,599,36,461,341,877,834,353,384,546,279,25,885,141,369,586,892,825,737,343,632,84,630,803,488,503,313,596,977,54,509,596,977,426,752,109,136,649,478,693,940,290,471,654,598,878,515,51,744,5,211,948,248,327,185,446,393,291,449,169,492,732,846,621,717,241,814,320,864,616,766,597,708,874,573,516,530,276,221,50,913,285,322,496,192,182,64,673,594,319,745,933,901,715,537,522,729,226,416,218,284,468", +"807,639,523,384,702,64,789,605,549,637,760,924,36,551,50,613,599,391,268,67,516,654,19,63,534,844,127,637,51,9,516,813,66,571,578,379,281,566,857,800,763,464,1000,788,421,88,808,833,564,576,765,359,354,620,702,491,26,223,585,632,85,241,830,51,536,33,924,628,860,169,78,332,575,793,638,786,475,686,529,111,140,531,375,804,383,856,445,273,67,0,442,147,977,649,230,187,505,727,302,991,432,986,946,397,83,839,598,202,723,824,448,88,490,375,9,4,804,6,914,77,465,983,909,333,830,101,987,999,79,324,44,38,56,473,966,221,374,909,682,734,681,739,985,249,418,224,440,217,274,977,287,830,977,352,372,293,662,30,735,479,234,113,933,712,689,147,709,515,194,925,961,725,271,227,231,834,157,684,795,812,328,943,911,114,303,641,893,740,539,508,700,526,805,459,696,827,987,470,647,141,985,609,644,455,372,540,148,732,38,300,76,647,758,713,977,984,482,809,664,495,423,653,644,935,939,889,228,991,835,688,679,345,124,205,803,81,262,921,642,997,168,427,717,110,99,12,12,481,64,10,417,345,840,50,186,627,18,667,628,245,424,898,894,606,767,823,804,980,551,936,29,110,60,187,985,818,727,206,496,926,615,515,41,261,616,273,374,916,994,124,151,635,285,749,733,487,639,654,591,294,232,204,379,639,427,135,23,251,719,185,840,691,686,693,504,387,253,933,997,842,157,943,66,140,644,824,744,102,750,438,431,362,503,806,663,706,783,577,813,703,921,511,714,414,156,393,84,430,520,610,238,67,752,958,633,9,178,425,993,711,719,970,513,858,721,390,133,180,908,52,782,815,343,328,17,412,922,806,614,157,855,779,474,88,65,385,387,696,191,737,997,758,848,441,942,579,525,333,778,325,101,339,106,197,673,413,69,149,327,745,710,152,987,854,214,200,942,186,866,959,776,339,499,782,284,121,107,107,591,68,28,385,483,766,245,539,590,180,768,811,779,699,909,295,727,31,31,272,424,28,281,59,730,763,642,838,152,845,874,476,216,339,640,94,579,356,576,315,686,679,841,819,758,568,25,766,595,882,802,421,18,939,719,939,485,705,133,463,574,650,503,719,514,767,859,973,214,416,319,922,285,516,557,410,657,867,233,839,859,638,735,492,851,583,103,182,604,417,615,758,871,622,898,278,303,171,713,209,255,594,320,55,258,512,814,80,282,603,977,320,147,372,629,639,607,15,75,901,35,861,813,718,343,850,400,207,848,665,110,677,326,700,192,546,998,678,418,596,337,944,584,159,68,580,642,925,545,998,565,289,503,202,589,853,669,556,728,880,631,851,295,974,997,857,51,918,390,200,214,653,931,520,222,554,39,357,704,275,149,435,851,696,305,86,789,238,372,306,287,408,260,986,879,336,157,754,968,601,636,579,850,971,72,239,43,649,412,588,365,818,459,911,409,267,910,690,657,793,980,349,577,792,257,449,825,154,943,901,18,745,367,57,738,933,768,67,383,723,282,66,71,687,342,208,251,548,401,107,147,582,901,115,128,829,908,207,688,518,385,732,684,742,847,218,480,875,929,190,254,389,365,763,222,23,243,115,669,782,192,317,96,828,258,47,227,386,257,256,523,66,997,108,923,860,447,217,750,433,629,461,59,248,140,314,734,801,513,111,217,326,486,428,90,923,776,379,997,481,24,192,351,950,374,982,232,153,199,118,983,418,69,360,881,374,697,856,358,365,608,223,504,683,723,578,81,823,318,490,183,954,565,319,468,951,565,855,429,887,629,718,581,106,480,717,394,898,358,419,297,542,729,998,16,648,17,747,967,65,575,376,695,836,669,602,682,570,834,198,134,37,712,953,180,413,75,399,535,756,690,191,501,784,105,671,439,827,511,35,637,994,635,612,836,664,750,14,897,170,949,878,79,621,594,280,329,350,778,202,637,518,375,301,341,728,896,876,271,762,758,760,486,519,730,106,350,974,790,761,728,864,659,846,983,434,732,340,976,686,157,221,781,219,96,287,381,748,841,519,338,557,748,989,240,129,781,239,861,146,97,598,313,294,437,962,809,971,538,582,683,445,804,630,491,722,76,871,808,509,728,670,441,274,812,891,498,440,143,511,97,350,644,887,937,821,523,217,30,208,34,358,619,346,411,282,188,195,114,451,938,555,987,347,908,836,227,954,193,298,479,813,766,109,313,490,39,877,732,454,738,391,124,599,364,641,269,443,323,787,868,972,288,207,241,798,276,420,727,40,628,640", +"765,333,896,363,792,421,910,515,202,875,119,356,508,157,373,748,883,686,318,930,457,119,911,136,434,653,584,359,898,663,610,467,463,183,939,701,749,267,342,134,490,693,851,753,684,145,204,731,438,536,919,8,939,978,864,228,780,241,473,201,573,677,849,758,710,126,439,631,475,118,577,39,530,63,813,978,886,133,353,299,293,607,897,476,164,879,26,347,85,442,0,929,376,392,925,13,438,150,507,742,513,151,798,81,984,197,578,445,393,945,658,896,841,904,145,64,179,211,351,665,704,643,147,560,761,639,63,46,981,298,463,24,374,567,135,903,831,485,662,711,686,194,809,979,301,87,500,673,719,660,177,498,469,718,124,987,138,322,780,663,664,743,968,663,954,654,704,367,905,883,106,915,953,990,589,641,289,479,58,248,592,267,239,469,390,769,769,288,825,550,674,352,246,237,218,989,897,991,500,95,840,886,142,781,976,486,666,308,622,48,3,77,479,881,779,409,707,462,886,806,261,216,166,295,257,883,402,301,204,17,157,369,162,905,457,115,70,891,563,905,767,235,226,639,381,188,961,886,335,911,289,963,240,611,152,593,178,32,634,253,281,97,47,611,407,634,340,63,29,349,318,832,704,456,573,806,507,732,917,670,249,376,813,824,378,998,74,956,578,981,403,983,466,553,34,190,458,92,631,366,908,703,703,200,925,814,81,500,873,549,935,792,134,336,207,865,314,866,842,843,868,328,551,462,702,206,28,133,859,697,447,391,504,835,729,374,689,86,114,366,214,492,561,733,599,981,248,728,190,334,504,504,934,991,780,934,667,972,291,522,73,215,807,837,464,684,285,961,808,771,249,36,607,861,465,43,7,523,404,840,948,978,169,306,873,304,96,81,463,104,168,549,498,847,406,888,39,969,338,277,883,530,723,394,100,152,610,132,517,428,588,770,650,88,29,491,306,611,448,616,456,636,282,691,470,947,116,813,384,209,396,434,618,29,271,240,71,108,577,300,231,372,853,8,416,831,120,564,412,829,734,44,602,655,842,664,125,754,944,56,96,235,226,121,439,410,663,456,175,112,934,977,717,844,341,158,589,275,75,89,540,976,677,184,188,256,460,728,480,964,408,215,178,309,631,977,208,24,69,821,125,715,924,968,347,829,505,581,129,290,177,852,440,388,140,440,738,354,6,42,882,706,2,393,348,128,706,721,620,912,518,839,938,650,689,853,33,468,436,568,53,787,648,427,897,319,506,728,826,242,131,246,51,454,305,982,383,356,155,699,394,707,198,468,546,114,673,798,858,34,244,486,70,696,455,258,444,451,27,715,33,397,698,108,734,15,565,345,512,134,637,947,271,238,265,249,42,294,9,90,827,388,567,490,559,481,280,422,938,370,803,732,140,763,300,659,927,766,524,497,970,823,109,350,967,490,224,378,85,913,295,282,981,320,588,968,40,513,699,788,886,359,529,39,585,202,978,163,504,61,226,578,945,926,732,140,572,487,679,398,233,346,540,415,618,523,254,373,721,907,91,507,861,511,796,539,117,793,576,926,74,963,622,302,716,295,530,270,221,76,372,567,848,138,872,5,771,732,593,910,501,947,637,524,239,636,408,205,27,383,252,431,37,311,628,433,28,624,943,119,722,968,166,106,954,656,393,655,939,946,691,602,971,845,846,92,118,137,967,995,589,542,973,165,982,877,68,398,497,908,149,204,408,652,61,700,713,13,984,330,557,445,123,398,620,594,54,730,948,902,831,429,831,196,325,159,984,287,142,58,84,155,342,998,836,737,476,962,612,921,402,377,807,543,806,731,328,993,100,733,549,413,930,108,889,323,902,322,774,838,539,131,408,653,114,324,60,815,758,60,815,550,857,638,602,464,704,614,302,821,76,357,587,919,855,60,577,706,460,79,429,724,940,634,344,599,613,582,802,80,327,465,913,128,373,998,866,428,360,814,152,691,426,79,285,308,9,567,609,901,549,136,546,330,242,842,964,560,875,397,367,289,459,91,826,230,638,217,515,903,142,543,821,731,844,64,417,410,59,641,842,378,977,19,401,144,327,932,17,255,464,770,88,487,121,140,2,312,945,54,204,738,861,466,467,803,419,402,361,902,300,48,734,656,295,158,876,959,404,788,339,158,113,175,175,564,297,721,666,356,130,393,118,229,484,744,574,484,734,169,668,323,484,709,356,938,33,746,509,71,479,310,626,854,129,328,398,311,244,90,436,712,347,857,370,751,509,51,119,7,37,115,459,426,214,880,506,711,498,82", +"174,384,784,838,312,685,187,398,741,648,984,253,58,957,616,66,75,503,403,143,206,843,747,148,818,503,722,294,594,351,266,541,93,857,193,759,77,49,273,649,232,191,592,132,642,787,704,701,636,503,488,707,477,557,175,697,462,438,673,213,33,866,879,732,600,437,754,866,325,565,901,767,3,950,38,835,664,486,40,743,818,536,564,679,529,815,335,460,37,147,929,0,457,538,364,395,890,820,290,466,187,17,448,822,359,638,867,266,606,175,88,392,655,899,659,516,503,959,560,697,835,697,760,916,841,691,315,676,17,830,722,918,683,610,298,560,609,924,647,556,932,528,923,472,66,739,87,363,794,210,586,706,560,315,605,9,144,13,44,328,492,546,334,57,601,670,468,252,234,918,816,680,363,365,636,376,175,979,432,906,273,525,197,933,675,506,149,770,636,905,908,259,818,820,750,270,343,547,380,621,574,304,472,709,287,521,380,870,756,969,679,460,999,133,234,169,975,211,762,851,326,770,413,770,308,751,423,196,881,810,394,571,495,930,780,499,216,648,124,209,702,216,433,276,330,765,944,68,598,763,248,839,596,627,249,311,519,367,966,471,284,228,619,313,713,741,334,586,654,886,712,276,467,763,628,191,600,53,61,582,397,653,615,638,591,408,463,539,13,335,918,11,895,448,486,134,382,123,183,976,658,59,573,509,963,362,292,164,581,39,207,791,741,308,144,157,705,770,261,646,113,82,555,163,600,198,802,137,661,947,927,799,976,310,664,162,243,281,948,362,569,403,887,402,705,43,357,223,278,683,609,814,608,256,815,496,545,612,369,526,791,804,256,888,119,936,157,133,829,11,201,872,378,381,716,561,393,270,531,51,813,711,946,940,458,241,131,148,164,521,980,892,319,492,591,65,797,582,293,659,501,63,75,752,355,70,713,902,417,147,520,556,547,898,830,370,525,735,85,382,827,215,616,268,822,206,702,573,500,686,360,607,258,323,708,914,207,857,595,95,417,787,277,726,367,56,323,678,658,282,777,428,45,889,353,262,699,680,685,858,186,394,769,156,457,883,578,161,148,196,93,971,524,805,687,539,575,828,809,797,430,408,122,614,635,57,336,315,545,169,346,780,45,391,521,902,442,475,307,111,300,688,4,646,164,935,763,583,372,914,143,939,616,880,390,488,401,158,601,860,116,795,508,337,308,850,329,551,322,162,410,824,255,395,299,368,838,172,47,191,426,127,159,205,329,481,181,130,354,815,298,174,175,962,410,116,286,398,463,540,294,646,470,224,934,312,884,509,456,32,713,574,820,676,907,553,716,866,901,297,945,642,882,245,303,567,559,247,159,690,939,23,219,975,641,703,587,618,84,728,304,230,995,549,613,324,346,877,364,135,487,230,155,83,206,480,787,499,716,559,936,64,798,117,63,199,113,914,863,296,254,616,67,266,194,737,619,135,192,429,38,801,462,553,216,693,388,627,84,760,473,492,552,100,384,830,675,448,488,956,690,117,796,35,510,428,978,193,765,640,441,780,52,528,282,563,62,377,400,85,776,12,85,69,222,525,762,74,371,462,929,724,915,83,552,828,903,36,824,555,472,84,439,766,404,30,23,774,947,945,598,8,477,840,489,573,769,832,791,679,977,381,711,367,124,16,284,162,51,362,404,378,894,587,690,844,555,7,7,30,873,768,501,572,802,715,496,325,169,418,534,131,919,915,866,719,154,101,124,652,746,138,595,663,573,947,727,281,30,859,159,862,878,503,668,553,225,710,758,410,301,785,236,601,329,274,758,325,795,63,317,635,502,326,813,333,21,46,58,109,303,270,130,708,460,291,900,803,770,349,1000,477,48,754,527,336,74,217,637,126,879,414,939,366,476,204,824,200,969,248,720,439,46,771,647,426,56,954,126,716,311,308,306,592,640,437,294,194,288,67,983,299,409,199,448,713,59,302,594,546,139,326,515,693,323,211,175,254,169,859,352,767,299,222,334,177,758,356,703,656,450,194,882,935,410,504,686,305,766,688,716,639,225,311,919,800,256,655,400,573,986,457,534,943,734,111,624,311,947,223,496,549,622,506,778,112,825,615,67,620,736,478,197,972,848,66,211,923,578,754,322,776,708,159,399,359,890,313,848,19,177,501,565,23,589,654,42,67,490,125,639,264,474,141,455,57,98,869,349,544,352,435,78,489,606,768,135,106,7,808,701,877,100,849,780,744,546,272,410,124,68,45,626,370,546,560,598,426,132,29,414,239,623,849,755,47,929,800,131,205", +"334,526,55,109,448,890,914,40,557,756,940,864,527,995,659,299,572,55,663,551,368,918,889,977,323,732,992,996,843,174,751,248,195,739,433,568,990,538,13,619,140,79,670,756,336,829,685,168,305,441,5,712,394,766,15,168,759,148,690,153,521,824,659,22,594,142,263,240,86,684,428,137,128,911,171,338,422,78,435,767,174,148,693,394,579,324,454,77,385,977,376,457,0,693,190,634,39,976,180,34,605,814,358,905,154,120,907,631,663,201,729,514,224,750,265,447,995,366,420,993,193,878,528,800,336,635,871,241,462,731,636,777,63,918,841,433,559,352,698,474,774,159,911,323,607,427,670,801,832,487,893,679,538,31,557,739,658,147,995,555,985,15,701,250,226,548,861,677,300,215,64,505,759,541,220,321,786,112,48,696,8,199,442,159,809,964,535,212,464,972,708,136,986,390,683,112,939,2,947,942,654,329,542,316,998,240,48,907,32,542,175,391,37,267,965,918,179,806,417,754,725,478,679,43,866,664,404,219,862,233,988,548,200,18,917,787,918,825,650,235,865,842,215,479,13,72,503,595,687,927,114,302,559,597,849,842,356,690,160,755,545,154,192,799,258,532,675,604,174,293,983,397,56,299,134,499,893,661,998,287,201,557,894,558,603,438,216,512,79,607,63,478,948,767,746,724,445,471,474,514,139,737,215,125,507,923,787,250,681,177,108,556,606,218,945,961,621,30,736,278,882,448,186,242,526,790,50,267,215,714,415,609,705,269,282,551,818,298,839,857,516,949,703,112,358,763,380,160,959,110,951,736,456,948,851,433,756,157,285,706,839,294,159,313,556,470,732,715,785,146,49,913,218,721,318,594,384,144,571,422,136,966,733,594,204,714,187,993,755,340,989,541,430,465,890,561,210,383,214,738,740,508,404,990,155,144,900,225,301,894,642,328,424,889,970,95,47,256,408,716,348,295,310,183,17,995,283,106,603,890,695,178,358,365,434,244,579,688,379,698,877,977,145,470,31,337,938,747,232,164,198,868,909,960,941,313,901,895,790,429,507,518,290,354,77,530,706,89,992,813,852,18,976,336,722,276,897,728,867,973,77,643,300,682,615,749,175,982,111,437,17,587,165,645,668,86,507,992,524,473,317,999,466,607,749,475,522,186,560,383,442,443,325,571,89,438,137,533,426,57,357,434,697,95,859,488,184,885,889,486,52,900,730,232,502,995,994,628,431,515,946,290,540,919,195,929,966,921,143,181,118,427,817,277,694,680,801,463,889,94,412,760,335,104,56,905,614,822,376,460,668,937,761,751,450,908,361,341,415,929,503,994,391,196,11,44,467,574,568,256,405,878,876,518,309,562,488,428,409,993,281,747,713,531,277,169,137,903,618,206,806,837,955,796,200,826,328,475,89,814,110,542,773,145,318,541,224,261,225,922,506,876,2,355,831,482,156,252,696,442,993,933,652,670,896,314,131,11,758,91,704,607,60,836,86,482,18,131,555,557,226,47,582,986,874,814,660,502,605,497,214,114,472,472,207,256,673,876,60,973,683,677,159,456,94,657,486,449,478,587,363,471,303,370,827,811,108,878,589,440,420,22,263,116,301,25,379,594,427,178,579,739,972,540,934,51,117,756,980,419,939,65,4,424,552,123,49,381,280,434,351,425,671,679,867,217,337,691,326,922,559,976,742,341,952,712,307,637,689,109,487,620,898,46,707,58,388,69,779,570,318,328,898,691,888,538,583,478,207,428,959,823,777,771,657,565,891,366,891,959,615,804,243,627,626,178,184,226,735,3,543,391,704,750,54,569,303,88,58,689,831,141,91,569,278,648,94,530,19,118,632,931,921,908,16,995,664,27,555,989,559,765,161,856,388,280,543,95,303,644,54,266,196,353,571,764,549,332,902,241,436,172,93,568,733,558,324,549,157,49,630,857,93,947,771,991,634,94,518,771,340,701,757,428,608,846,694,459,880,275,760,853,709,671,592,874,985,452,268,187,944,520,419,578,123,277,294,965,771,732,671,757,169,700,142,922,852,406,486,874,956,729,570,788,392,116,165,90,856,653,605,843,800,234,646,2,148,400,372,733,813,654,499,53,771,259,443,969,638,575,878,5,274,81,264,483,3,557,447,991,113,388,232,172,313,217,575,90,346,124,511,902,264,394,445,892,843,395,602,274,360,923,619,225,27,183,90,803,169,348,514,519,485,993,175,106,317,436,869,797,926,81,692,800,196,815,884,522,888,964,181,585,819,969,886,101,569,8,204,520", +"77,980,673,41,312,581,381,15,931,91,302,245,966,608,986,484,571,934,268,906,152,462,747,282,600,866,108,953,917,547,672,29,681,527,187,457,905,922,282,981,518,536,790,582,912,321,599,826,23,352,641,178,828,803,782,431,33,434,673,805,341,905,451,89,966,337,437,494,393,374,540,432,717,677,438,595,425,892,322,422,54,572,134,518,951,563,850,449,208,649,392,538,693,0,197,186,781,479,786,953,220,763,356,880,847,695,518,473,803,202,120,692,461,701,957,39,311,31,597,366,127,331,880,761,183,238,600,919,682,254,11,112,965,294,586,541,94,627,988,992,868,195,574,996,175,949,867,287,76,976,773,269,507,986,420,508,756,869,275,499,562,344,62,353,124,285,440,304,455,573,674,52,64,692,373,340,766,198,764,574,525,785,648,688,453,551,265,665,739,832,915,715,281,278,804,472,822,45,176,431,717,314,276,3,984,173,449,741,890,368,324,901,458,345,462,919,513,575,496,827,526,413,382,378,971,392,16,79,194,246,214,256,217,89,965,124,57,717,215,63,225,261,307,487,953,414,715,206,667,526,803,366,212,539,177,607,297,944,29,78,641,895,193,917,825,824,264,902,292,839,379,624,872,949,487,253,838,411,938,722,109,242,613,63,313,739,526,341,236,851,428,534,562,124,537,369,650,313,165,152,873,684,27,984,367,695,233,562,185,307,540,938,945,32,201,482,948,67,352,896,395,667,809,125,22,572,794,711,71,678,291,469,939,262,125,147,773,527,263,649,743,2,576,125,173,830,241,912,948,95,208,652,86,227,552,685,299,216,732,678,789,219,973,379,123,457,40,488,387,307,222,430,253,503,68,605,141,862,311,701,740,163,982,325,911,257,198,537,416,12,815,193,921,736,273,173,551,76,129,844,793,291,811,70,123,16,630,503,474,698,851,19,76,96,977,222,461,181,249,291,379,153,423,360,265,762,424,596,862,710,109,404,858,410,666,486,670,75,529,167,556,349,562,150,274,907,365,612,555,666,936,134,282,955,504,570,26,679,200,845,668,512,580,270,958,32,399,124,383,986,412,959,930,220,669,510,237,456,764,363,173,180,280,248,271,385,271,336,948,454,842,372,332,45,163,265,706,941,706,526,462,522,7,363,802,791,615,477,352,641,816,120,397,55,846,374,426,747,935,822,431,658,75,236,122,846,844,669,29,813,627,320,387,55,350,487,721,938,427,706,147,932,775,34,418,12,963,97,277,905,435,337,775,956,760,700,358,230,169,547,368,276,845,576,560,311,978,688,965,337,806,385,415,615,994,867,526,635,698,446,197,743,566,382,789,533,653,817,638,805,413,236,66,73,531,322,337,967,304,130,413,400,836,248,462,818,491,514,266,323,916,445,355,665,686,464,28,643,110,641,727,640,8,409,572,797,791,995,329,233,119,531,908,836,34,784,343,108,928,864,954,802,138,636,436,823,834,333,812,568,616,41,329,419,371,439,47,804,336,88,929,101,288,218,914,434,274,192,445,761,108,107,856,856,498,243,444,463,84,798,704,757,565,771,859,578,286,138,784,590,917,822,498,919,61,844,944,729,934,894,731,433,956,814,228,117,656,114,514,528,573,226,195,378,86,746,565,83,432,801,879,344,492,18,223,163,995,315,124,498,25,433,710,736,477,500,558,628,981,263,797,962,76,788,944,531,842,316,431,531,324,345,750,25,500,425,360,889,479,495,76,912,205,660,514,558,123,506,968,455,869,512,950,793,691,243,518,142,932,748,100,161,845,708,885,826,338,683,932,31,563,697,269,726,527,693,706,662,15,808,927,295,970,777,865,339,352,548,567,151,288,507,443,996,748,843,54,591,326,79,275,614,328,754,128,854,136,782,726,18,184,590,44,998,793,275,669,235,17,308,782,237,300,219,917,962,546,566,550,862,110,443,115,365,219,698,181,710,103,166,385,221,834,218,101,411,824,69,120,951,870,591,834,131,863,62,676,16,560,474,957,106,727,200,462,77,149,711,975,591,825,258,959,152,244,32,908,703,447,566,310,577,568,248,415,860,656,865,402,686,407,591,860,624,435,316,724,191,675,674,12,176,743,413,725,665,565,760,80,209,583,236,693,213,756,434,449,884,298,932,677,406,770,151,433,432,416,634,40,629,570,13,600,300,58,985,879,109,629,320,174,444,284,176,168,540,386,387,66,660,573,61,440,438,835,974,724,444,875,760,881,861,28,110,922,631,822,424,655,381,806,65,212,148,295,936,239,533,29,91", +"930,764,417,294,410,899,999,193,904,38,476,829,612,806,328,672,325,24,45,222,612,552,704,753,182,832,382,117,789,524,385,14,866,56,997,440,16,572,684,365,706,635,230,918,475,109,528,204,157,670,215,607,808,629,801,511,295,612,873,974,275,667,334,820,967,40,888,698,89,720,851,284,293,315,266,929,744,504,780,839,57,148,263,637,610,728,944,519,26,230,925,364,190,197,0,421,934,583,210,353,616,31,760,879,525,329,272,499,416,569,94,224,253,512,102,264,865,705,837,607,591,828,100,516,323,166,448,137,130,777,403,14,450,143,61,550,235,818,26,745,742,115,443,4,697,703,369,109,733,707,527,868,632,724,443,662,311,277,413,398,195,232,988,646,687,834,749,593,680,592,556,510,381,855,322,424,728,147,3,394,669,788,491,345,360,729,677,258,677,431,624,847,821,514,150,915,881,541,597,7,124,839,197,17,856,98,256,66,563,647,593,835,840,598,167,546,99,244,936,464,769,640,126,205,82,869,16,987,318,787,671,572,286,994,322,30,444,158,598,142,135,575,391,548,470,767,118,195,564,656,661,587,4,253,219,753,976,49,584,742,155,463,48,573,201,981,416,322,343,252,114,393,64,86,175,997,95,16,974,330,797,740,307,544,312,844,259,316,197,81,464,38,170,909,53,666,633,19,832,654,168,355,154,952,130,233,742,834,248,85,888,488,615,305,464,486,146,129,70,133,487,621,842,828,966,553,268,308,311,300,120,924,384,697,514,191,798,720,202,761,813,68,891,784,695,15,552,363,789,516,554,669,369,787,407,161,241,272,606,385,883,773,883,821,370,94,290,374,659,10,292,273,701,863,784,820,100,370,409,709,110,248,393,135,536,473,117,78,361,78,504,636,599,417,852,960,890,714,897,539,879,17,46,313,892,140,614,466,138,576,883,520,120,582,772,106,706,326,782,595,502,79,659,289,202,36,303,519,719,125,645,697,811,224,998,533,926,462,887,324,497,958,706,976,666,12,390,838,570,692,301,791,860,747,925,370,77,776,13,200,16,108,13,150,714,687,688,356,720,281,692,747,947,37,296,886,339,466,74,417,738,797,573,389,349,614,200,691,140,890,693,376,886,778,329,768,6,840,387,590,460,698,854,351,842,970,493,647,447,770,798,253,790,719,608,171,327,421,771,399,604,265,328,856,706,941,503,358,825,612,505,450,524,17,289,5,816,136,648,186,840,864,192,29,45,168,383,103,772,639,359,981,430,24,217,238,381,244,393,460,976,953,690,987,499,625,841,838,62,639,511,303,641,778,862,662,253,607,678,361,59,190,387,120,907,224,818,140,895,115,660,208,815,781,480,434,584,981,46,709,441,843,565,394,197,929,455,205,619,458,58,489,991,365,973,522,204,195,71,954,855,693,549,561,608,93,559,897,406,774,757,580,810,611,670,475,841,829,951,400,769,271,366,895,225,659,57,507,938,362,351,300,700,229,498,890,470,27,631,278,223,236,478,804,121,910,125,776,273,108,854,454,376,539,781,804,669,166,522,604,619,785,985,402,41,278,132,8,607,925,388,453,786,457,699,961,968,877,884,975,686,324,976,883,353,919,935,668,362,326,310,786,82,206,329,62,53,998,906,760,680,484,599,795,243,622,489,424,88,103,468,160,77,476,977,554,418,355,3,514,347,827,333,56,176,851,477,683,598,599,859,473,457,140,233,966,422,82,129,523,343,558,913,410,298,164,516,338,726,302,810,668,184,904,580,51,378,266,775,214,712,599,2,554,15,585,335,222,206,321,419,920,249,225,919,422,240,861,571,306,230,689,846,975,83,868,587,670,779,99,747,115,870,169,505,246,610,216,831,862,534,371,79,866,19,650,231,24,95,296,377,382,693,661,35,790,446,576,863,75,496,432,37,739,79,402,505,539,529,373,557,428,646,8,736,420,812,697,685,274,662,357,748,726,378,378,782,919,767,990,374,712,818,984,46,382,850,946,561,427,946,364,856,757,560,860,175,352,268,698,504,588,243,933,812,168,252,459,683,238,802,296,558,314,869,277,190,95,169,856,498,857,977,911,981,624,651,737,366,218,684,877,752,946,402,968,853,36,838,579,83,410,410,517,541,357,535,454,645,418,814,112,416,386,362,834,989,320,61,235,158,299,359,172,868,560,54,143,648,616,917,277,222,656,462,983,317,172,868,667,47,36,956,883,341,750,707,796,217,439,266,317,317,633,284,295,890,722,507,820,479,701,700,499,327,131,509,268,936,777", +"536,929,665,160,924,792,749,759,155,732,19,293,88,928,671,515,666,774,149,144,452,310,317,58,193,657,987,664,174,774,367,794,349,326,673,516,751,198,878,151,934,232,549,980,987,713,963,450,310,428,755,46,285,444,999,321,625,319,632,866,682,952,493,376,381,161,956,524,160,519,310,274,742,894,354,545,926,527,494,718,223,317,198,471,703,771,211,11,633,187,13,395,634,186,421,0,508,44,737,836,718,50,584,397,145,27,249,965,637,668,699,624,631,614,983,135,428,352,184,668,91,656,370,845,911,475,459,487,885,690,564,841,910,522,432,671,626,663,193,536,317,421,321,859,879,628,310,944,157,712,315,84,839,487,916,237,606,569,248,995,90,905,151,160,847,483,978,20,973,291,34,517,652,671,255,726,6,372,829,872,638,387,978,837,414,164,746,120,430,474,640,893,57,234,427,571,969,389,178,290,756,641,976,532,230,306,547,501,696,299,341,526,40,213,268,538,732,95,922,923,123,5,280,354,789,553,144,42,657,121,69,851,952,316,521,276,55,681,736,982,24,137,797,114,279,628,752,426,530,142,798,546,192,196,201,12,645,236,637,363,653,683,973,182,418,178,249,265,81,236,539,146,647,341,263,229,48,777,321,260,469,238,322,221,105,31,846,294,146,329,303,201,634,556,89,295,994,274,864,526,773,894,15,615,33,173,755,13,639,288,437,617,459,642,234,434,889,944,456,653,757,440,725,438,753,496,952,440,414,975,207,459,217,588,565,826,60,457,603,646,827,993,901,620,368,893,345,316,668,946,698,481,520,43,531,311,666,156,454,971,126,899,533,34,600,729,306,931,175,373,156,58,148,518,120,120,284,718,538,570,917,250,357,603,738,812,198,735,759,838,740,877,140,366,88,965,643,174,175,30,824,894,61,163,676,839,37,989,643,779,728,881,3,101,961,90,336,185,807,851,536,121,529,55,834,413,967,168,920,220,626,877,333,368,871,827,77,277,59,960,147,443,255,76,980,468,185,779,893,643,434,904,178,378,68,70,755,48,510,948,425,12,901,18,351,522,796,397,510,823,36,207,223,971,397,896,817,68,244,123,603,966,996,736,329,371,758,616,606,829,525,781,227,49,695,245,206,856,909,661,686,105,146,798,204,762,84,409,951,773,901,394,345,281,746,835,287,245,252,88,360,636,769,498,253,19,392,5,187,744,493,217,278,169,186,946,346,557,748,722,620,940,422,69,47,258,400,732,644,483,92,999,513,623,228,975,876,785,119,218,360,436,433,14,343,615,909,125,166,527,75,261,877,366,890,718,794,130,780,841,644,469,572,207,467,808,619,786,53,823,250,184,19,187,490,759,695,364,874,848,81,338,245,692,147,993,533,17,375,857,699,720,793,258,668,916,893,991,197,161,926,50,653,23,46,155,525,717,12,769,128,842,43,61,548,330,521,809,346,754,29,21,57,809,554,956,95,484,374,980,545,937,61,932,755,164,994,464,464,908,497,748,747,816,509,760,391,230,598,578,550,879,261,525,121,710,766,210,280,748,192,413,55,64,565,795,985,808,180,939,298,923,667,564,462,751,356,562,991,561,119,866,633,135,69,4,600,59,212,780,1,84,300,409,641,458,517,564,337,290,774,571,981,666,242,618,323,241,329,126,705,853,792,618,553,93,879,290,627,474,831,402,849,649,107,161,794,739,981,928,573,501,617,347,897,334,23,910,539,634,580,340,898,85,815,206,868,691,586,866,388,103,472,412,482,997,958,665,749,618,425,669,405,753,832,275,844,542,769,668,588,734,773,326,156,876,371,561,7,762,826,870,184,169,381,310,98,689,794,101,483,29,473,291,370,108,411,567,691,938,903,831,194,638,986,286,43,487,561,649,129,677,944,328,535,214,410,837,973,892,514,114,804,576,84,832,583,445,324,75,824,855,381,31,229,674,511,93,259,358,916,528,422,360,26,131,197,148,577,174,971,710,474,537,965,142,283,910,316,797,96,526,224,370,83,612,284,426,447,509,57,123,159,149,486,839,232,759,720,794,963,698,845,163,665,503,941,763,957,987,969,157,194,583,363,958,357,756,817,917,256,827,739,397,288,437,165,194,598,310,917,328,338,831,743,893,201,687,429,54,260,850,666,540,965,311,979,635,851,274,510,250,898,507,632,189,814,395,236,580,53,357,958,253,947,513,321,278,425,375,105,367,443,634,495,993,27,135,926,883,22,770,867,307,801,503,523,830,527,548,42,951,637,142,547,309,22,649,430,692", +"885,183,893,950,337,947,341,461,418,141,145,562,946,415,395,531,847,331,105,697,229,954,309,490,719,829,160,39,486,66,781,895,259,970,217,479,620,25,505,906,198,248,991,205,684,80,262,367,414,548,240,647,999,916,828,34,361,5,310,539,697,341,529,600,729,737,152,84,515,68,89,560,923,258,284,804,310,668,10,779,373,651,246,786,153,503,283,291,138,505,438,890,39,781,934,508,0,577,911,843,570,583,560,856,498,383,91,218,213,238,396,83,109,172,284,72,470,50,670,32,76,62,624,864,10,438,780,2,571,268,41,91,828,811,144,569,678,377,244,727,918,296,404,890,590,924,407,125,221,149,642,465,261,49,494,910,525,252,614,629,485,665,857,143,948,607,681,45,971,849,437,250,923,612,610,378,897,390,337,196,195,80,408,640,7,267,207,443,727,266,934,870,837,807,972,802,437,435,824,545,76,385,444,324,711,83,292,125,92,981,481,499,705,961,177,892,992,101,298,460,213,929,671,560,882,689,94,445,42,429,199,317,741,608,429,305,13,219,152,230,851,381,376,664,935,749,891,622,819,359,891,570,66,656,171,977,786,654,127,90,162,506,637,775,959,226,415,316,441,318,469,963,6,114,76,448,995,873,954,389,94,876,439,320,489,120,708,328,559,729,431,642,211,468,46,19,13,583,686,567,269,994,117,932,205,124,400,57,684,175,778,288,264,985,361,692,315,887,935,375,337,76,555,348,44,933,55,108,125,369,949,105,540,43,277,313,128,341,216,305,96,853,214,435,172,476,163,594,292,261,484,391,883,775,654,827,606,461,753,839,890,634,809,475,127,977,363,241,298,178,455,827,974,290,239,530,900,230,603,776,180,169,132,212,423,300,307,623,287,386,632,222,299,135,221,889,635,657,899,887,301,330,254,113,474,14,67,326,69,334,218,157,835,111,196,103,292,390,278,277,181,261,473,384,906,868,74,903,696,966,87,906,136,249,1,799,545,323,123,481,888,176,574,515,655,99,245,167,257,982,530,495,720,219,799,963,841,682,498,617,701,465,369,617,31,49,34,440,325,377,651,530,174,162,137,771,979,655,788,480,731,893,27,996,499,511,451,554,401,432,720,19,938,350,200,166,184,997,361,68,554,908,530,511,222,295,5,272,208,597,690,792,628,326,480,853,268,786,499,312,95,144,125,636,695,112,576,79,28,210,210,590,496,874,92,675,701,280,643,916,454,961,449,960,88,700,992,366,744,248,765,7,386,33,623,48,457,339,602,96,293,670,311,173,705,867,613,991,525,700,868,602,563,875,532,858,423,916,117,447,1,676,822,896,966,125,761,101,255,930,215,886,205,7,54,345,64,301,67,270,220,475,495,515,640,400,931,100,138,819,379,809,581,930,200,106,446,556,461,732,293,775,247,958,277,157,20,761,60,375,124,980,101,576,71,919,301,5,547,372,235,98,283,721,74,815,478,205,235,632,724,327,444,559,938,286,990,617,599,522,400,312,420,502,507,180,413,596,901,143,339,849,298,273,182,90,279,191,556,558,935,872,160,956,94,865,827,183,239,435,631,384,683,400,579,53,881,395,460,884,679,246,685,651,883,548,446,555,160,102,193,43,222,477,30,311,707,141,125,228,120,914,91,668,865,607,639,530,412,608,885,699,987,414,744,910,474,777,813,609,585,619,246,800,336,888,383,445,847,988,649,338,808,794,621,390,949,629,124,852,983,442,359,616,142,77,835,545,875,870,919,254,569,937,683,840,472,409,79,471,356,449,659,421,832,767,500,210,278,362,56,372,214,602,611,491,274,325,292,655,760,725,340,235,79,391,59,612,655,139,552,384,941,742,380,584,523,822,145,741,480,781,603,152,521,266,968,968,825,436,684,795,318,707,860,195,324,910,935,319,357,301,878,410,797,87,695,724,712,910,565,856,746,326,879,980,20,672,162,960,158,326,25,770,777,864,170,722,507,754,354,107,209,606,361,326,153,550,474,243,116,367,658,287,307,121,784,849,71,790,607,522,101,480,884,951,556,172,179,365,30,328,264,388,694,836,173,448,492,915,807,721,122,587,266,535,711,727,500,918,578,587,995,316,239,815,96,174,852,584,688,415,693,576,812,360,638,281,187,1000,785,516,427,599,458,851,14,644,97,989,940,883,612,641,737,938,430,170,162,813,970,903,772,444,351,965,407,524,344,581,177,306,38,109,533,86,965,452,326,943,914,654,961,859,436,917,299,117,883,969,457,31,801,910,621,778,316,313,52,275", +"533,987,870,754,720,188,828,212,527,802,863,126,542,414,473,836,750,257,440,334,709,895,578,62,736,413,340,792,914,935,267,66,754,857,108,236,756,996,999,251,959,99,369,220,399,751,337,998,264,302,300,932,993,625,740,878,83,970,31,707,830,224,234,610,5,188,439,656,331,546,651,549,351,74,79,517,881,587,753,636,970,421,269,664,651,888,244,187,113,727,150,820,976,479,583,44,577,0,993,710,382,712,174,507,466,271,779,54,912,942,366,637,829,240,993,577,450,486,356,812,48,528,589,534,466,224,599,96,830,866,233,594,573,102,621,468,44,469,242,577,686,202,767,507,311,772,867,584,973,464,554,781,236,610,403,634,875,543,215,980,484,599,133,290,15,287,716,449,725,119,917,430,578,755,914,469,87,507,399,279,468,787,24,639,998,391,74,967,166,430,535,401,429,72,836,859,425,654,256,486,682,277,134,694,488,671,677,85,736,27,391,62,557,465,516,833,323,505,477,237,474,581,451,235,472,34,691,191,260,362,637,43,117,692,579,729,755,439,887,997,93,892,317,251,236,294,116,882,641,515,540,18,821,713,946,550,112,459,303,120,188,473,152,832,896,531,254,306,397,16,202,479,133,7,737,469,697,626,72,830,470,141,279,455,282,704,865,763,358,499,777,219,970,715,916,298,328,920,495,632,66,255,19,708,890,856,967,575,28,829,361,173,410,114,917,555,678,358,355,70,623,433,407,219,408,658,815,229,76,635,754,54,50,925,651,829,302,719,13,113,378,252,943,901,897,218,732,117,538,423,563,261,877,910,908,349,263,459,196,196,235,922,961,802,790,348,718,998,166,957,432,878,453,486,904,605,258,477,955,830,588,267,459,166,993,648,109,442,5,619,214,402,235,798,469,69,187,356,286,409,995,181,660,300,39,572,71,43,603,322,970,653,334,950,564,84,37,865,318,925,31,175,956,921,222,956,491,284,27,382,976,144,684,477,607,14,965,590,307,458,159,289,369,606,707,294,924,421,679,339,890,602,947,942,402,545,875,533,313,789,260,515,667,978,322,998,952,667,269,429,86,214,52,805,368,156,301,526,77,336,497,328,147,114,763,519,726,171,288,893,615,253,588,538,457,139,523,340,950,439,689,299,225,433,252,120,706,439,316,356,128,529,573,263,361,337,484,450,259,66,561,730,395,152,493,760,686,386,539,292,478,206,228,268,325,578,81,896,304,752,900,881,265,782,431,463,661,1,148,991,336,522,144,486,79,55,870,533,545,834,119,869,271,253,47,145,839,311,598,106,267,773,667,731,658,613,509,687,883,457,924,707,835,343,625,206,625,920,68,539,684,351,475,104,849,598,82,419,389,38,118,776,442,699,856,146,558,531,872,119,61,468,529,933,293,782,276,639,838,940,66,597,128,955,218,866,509,604,24,89,614,515,632,946,308,337,167,209,116,477,810,958,43,684,846,736,796,619,475,408,257,300,255,463,767,219,889,619,981,3,601,552,18,413,201,752,645,424,703,173,740,87,115,891,640,933,702,286,889,247,422,607,931,18,93,112,939,66,792,450,309,882,177,679,501,653,343,838,131,974,890,521,837,723,240,490,984,787,606,25,912,133,690,755,358,103,374,91,703,128,154,274,724,152,378,630,257,348,177,628,547,380,927,374,90,71,321,714,130,478,452,559,306,833,719,574,459,341,727,873,433,19,829,206,669,875,216,926,201,251,205,434,69,918,489,962,652,432,716,260,935,503,104,106,872,507,106,833,374,281,115,697,952,147,76,406,374,412,896,133,245,907,821,845,906,682,70,227,607,8,552,840,545,139,286,829,257,275,995,30,387,552,991,551,983,694,923,805,185,982,320,761,281,518,657,145,821,402,988,479,331,448,343,226,533,820,679,175,251,941,588,392,407,305,692,749,59,325,543,718,284,261,576,308,224,36,983,816,829,761,246,653,467,29,737,428,90,518,603,528,186,709,897,880,13,673,537,902,37,761,109,757,669,859,791,563,338,989,987,406,997,382,584,793,463,163,191,200,385,163,236,368,241,168,400,905,330,372,177,428,423,619,271,660,382,946,717,579,261,794,283,680,782,189,966,731,725,755,929,482,41,171,948,499,117,786,385,861,773,521,617,961,985,87,884,534,623,456,790,591,531,938,924,439,946,908,767,830,676,774,817,445,976,746,330,108,175,65,170,735,816,64,963,792,50,739,304,30,694,177,125,941,946,730,380,190,598,337,79,845,250,6,99,96,867,419,324,229,569,944", +"202,806,4,224,907,981,857,870,881,664,675,657,398,584,566,420,26,348,737,527,470,890,799,174,367,245,478,786,698,563,425,34,100,851,396,520,142,101,515,184,106,996,500,484,958,677,700,372,472,619,833,91,305,52,342,703,653,559,326,391,840,66,837,91,209,374,258,669,154,941,102,908,79,42,230,119,325,817,960,138,450,194,4,574,264,338,609,46,817,302,507,290,180,786,210,737,911,993,0,701,224,422,111,754,310,509,908,865,478,422,924,147,32,972,500,125,921,4,316,624,452,246,758,650,335,626,62,874,638,383,431,294,921,770,42,847,888,671,803,278,369,860,71,564,66,486,475,521,128,244,885,968,408,640,151,289,701,538,279,240,321,162,299,885,463,531,15,526,177,68,716,360,732,973,439,983,834,170,723,867,393,854,214,457,716,798,612,652,850,77,788,637,491,319,384,116,18,676,629,595,593,250,522,718,163,286,571,473,56,620,585,971,354,289,512,12,305,195,335,453,364,596,245,457,302,82,460,431,934,528,877,306,748,623,659,539,666,59,824,763,777,938,878,120,328,665,24,810,2,561,272,881,872,428,72,337,142,618,862,985,496,423,978,608,939,409,487,23,795,355,276,362,723,15,850,255,542,56,437,189,726,627,923,914,974,286,87,31,426,927,741,806,211,124,533,95,598,443,149,129,114,739,246,224,305,406,194,2,172,652,393,464,64,437,338,413,289,377,139,197,743,171,882,945,427,231,988,564,813,799,465,899,273,158,747,986,216,819,694,645,889,929,824,886,142,84,387,280,598,964,265,234,963,557,202,815,83,165,598,292,294,433,61,844,661,773,793,264,255,160,858,950,534,128,965,120,298,963,102,797,518,144,654,60,805,673,335,545,448,46,471,51,466,230,741,3,322,812,569,611,929,63,157,263,550,522,542,545,149,598,108,827,186,557,347,322,860,98,609,528,365,178,30,322,574,652,795,753,384,925,985,888,215,388,223,794,838,220,585,502,916,363,590,14,836,551,863,722,695,710,383,255,600,217,833,532,449,82,507,658,237,396,134,148,31,433,109,947,251,629,558,521,94,219,331,157,516,269,165,288,473,811,235,363,567,585,359,401,814,596,168,523,898,725,350,410,293,289,837,864,583,383,265,448,368,65,861,76,967,247,219,668,355,371,987,504,871,813,302,584,317,635,358,211,641,303,986,315,789,34,517,855,963,746,511,353,805,838,518,453,790,63,556,667,414,193,533,143,942,825,595,618,763,545,945,968,829,391,145,298,173,545,896,159,124,595,914,294,624,924,681,81,686,842,943,88,552,822,329,786,750,141,759,974,925,89,871,611,113,437,184,841,357,210,653,193,439,392,920,357,681,199,821,528,917,393,206,151,329,812,115,315,999,476,186,710,397,651,660,659,274,859,590,463,808,439,372,736,966,763,365,410,199,988,955,321,860,682,599,825,65,136,671,519,165,485,621,847,639,302,432,338,909,922,232,919,677,157,976,450,266,81,841,881,674,138,231,952,498,498,230,129,782,988,900,212,429,884,24,844,595,824,499,282,131,288,932,862,57,972,297,955,760,240,802,635,381,35,919,772,846,543,482,231,463,167,710,394,937,630,754,764,58,421,395,519,431,630,486,116,342,138,149,676,423,382,892,330,803,10,572,343,107,532,422,749,790,832,94,116,77,241,817,795,975,778,937,518,676,265,335,515,749,302,950,978,983,743,375,416,338,209,565,287,877,943,179,463,488,799,649,489,520,61,31,180,784,725,333,676,611,399,414,514,859,327,420,232,26,58,306,766,186,984,43,905,495,514,249,821,749,645,278,801,995,840,243,592,92,293,122,674,651,697,837,823,355,835,424,594,767,996,562,284,79,75,706,816,98,123,355,79,527,758,413,73,129,660,860,982,820,994,914,950,163,334,207,824,740,508,190,465,962,700,465,829,229,453,709,691,553,793,648,611,611,321,426,850,315,413,665,356,11,756,676,796,958,275,327,207,614,541,746,66,663,297,953,276,891,363,646,832,394,819,109,527,248,261,549,788,786,136,194,748,185,19,804,550,25,342,650,726,149,209,4,67,69,653,518,117,606,44,174,676,867,982,149,602,200,276,799,910,429,315,659,380,11,278,53,140,457,556,342,442,60,565,311,922,115,115,737,937,647,804,45,581,840,349,93,653,642,276,732,19,388,535,116,60,557,909,681,330,381,748,662,252,814,272,654,778,246,821,773,129,772,576,768,701,739,284,32,968,217,452,519,293,490,520,559,185", +"191,519,795,659,222,373,735,888,546,824,876,764,439,674,432,883,949,383,112,215,799,622,893,879,835,973,396,627,218,511,123,549,334,762,427,525,673,4,939,675,367,562,465,395,719,343,766,548,536,309,932,135,439,511,527,858,508,14,811,398,928,229,970,6,745,215,274,941,529,459,488,3,902,826,379,485,361,859,518,965,853,436,692,413,727,275,194,455,670,991,742,466,34,953,353,836,843,710,701,0,887,566,273,185,811,311,502,841,5,179,459,929,203,991,358,869,573,671,895,684,340,257,896,774,637,763,547,976,338,595,170,57,361,675,483,656,285,832,96,447,108,508,330,842,886,127,545,189,28,556,849,834,54,187,523,197,317,646,372,562,675,865,928,556,921,188,57,966,153,708,346,127,813,633,553,509,629,714,302,690,133,453,786,485,727,61,968,312,846,286,250,838,455,214,982,757,423,473,199,714,51,998,635,266,891,831,237,280,247,572,156,32,459,647,700,987,739,456,256,503,478,848,44,297,138,747,64,268,450,161,549,898,643,245,759,946,252,360,479,894,729,875,782,835,392,124,628,776,405,435,413,236,120,230,288,101,537,51,103,519,240,360,841,914,513,910,535,790,484,322,441,708,537,81,595,123,491,414,878,429,802,447,281,792,39,674,159,460,3,350,817,689,180,751,795,411,8,364,470,8,93,318,64,443,235,650,545,168,311,983,113,762,335,388,905,746,929,93,528,129,907,100,698,669,417,314,70,839,429,503,926,423,879,803,302,506,440,966,330,572,892,498,756,435,42,831,389,47,963,304,320,284,343,966,219,311,409,628,184,253,832,368,92,354,197,43,439,262,616,350,896,865,220,133,971,307,497,771,946,909,737,755,58,299,380,580,822,656,917,885,974,263,699,662,407,292,539,824,245,736,623,25,33,592,789,394,326,160,151,214,879,546,49,60,459,573,40,252,934,493,887,190,942,698,809,620,686,767,926,274,134,862,178,308,940,767,633,839,366,828,602,92,60,406,241,551,4,401,199,760,341,735,405,739,314,96,8,307,835,193,76,805,231,266,953,54,947,888,758,100,37,282,149,220,978,557,256,828,176,41,659,294,397,907,654,791,340,531,392,567,283,977,276,758,70,672,543,218,590,9,899,433,576,367,948,303,585,92,126,91,700,461,698,114,994,11,760,171,428,575,605,148,597,123,218,518,225,277,694,958,650,977,45,470,709,812,411,772,413,420,673,864,308,366,389,171,200,214,441,314,218,626,376,433,733,217,933,729,978,835,593,36,955,583,8,420,808,712,404,793,504,209,420,617,406,848,958,441,793,616,319,343,789,287,542,59,554,287,336,370,892,234,848,67,848,335,297,166,781,232,801,991,992,491,547,660,132,352,3,108,304,341,943,72,242,980,908,733,289,642,108,462,83,272,140,145,433,164,407,839,12,389,659,942,269,972,439,5,685,81,666,936,864,596,775,710,819,418,332,396,255,338,561,480,244,932,464,372,67,819,17,945,727,810,254,475,640,280,761,672,134,885,718,339,439,142,629,964,512,25,887,415,303,650,366,807,368,19,752,903,195,461,107,799,559,6,51,450,377,104,395,858,465,633,239,33,369,274,235,58,676,375,798,370,768,654,562,633,29,742,475,311,386,580,943,711,665,363,103,560,104,149,495,591,951,499,982,370,883,914,602,644,810,954,80,905,65,480,197,826,579,181,654,611,485,621,308,352,862,272,258,864,55,977,274,128,112,943,59,246,142,312,264,21,876,618,63,102,799,976,206,189,663,673,624,973,939,926,251,869,759,493,796,248,577,90,508,60,909,453,462,212,927,385,801,66,701,515,767,361,34,232,568,35,615,284,654,94,979,872,93,556,45,939,489,163,708,375,649,941,74,943,491,258,14,171,976,398,736,872,238,25,3,569,74,429,34,262,45,552,403,453,386,383,819,95,863,336,250,599,957,513,41,486,633,73,877,949,53,926,160,137,138,698,568,608,697,557,712,44,933,303,618,366,765,553,561,589,798,569,326,923,607,53,410,684,526,20,221,908,282,893,412,779,187,38,605,657,945,403,286,760,766,536,623,708,1,733,644,222,575,912,149,837,990,251,486,167,135,301,105,782,267,898,446,323,526,790,92,52,521,294,33,785,116,120,380,611,798,51,170,168,617,632,180,607,57,45,978,593,482,774,200,605,195,326,484,349,372,962,766,61,464,432,55,230,570,109,701,900,967,283,941,943,125,860,837,263,521,993,607,435,740,84,949,421,533,160,3,906", +"825,293,396,377,319,819,438,208,216,107,400,376,223,887,162,621,367,315,30,677,404,179,894,995,176,781,849,720,315,532,737,523,815,200,46,221,532,709,392,609,958,90,173,473,73,149,965,419,140,10,391,844,222,181,334,635,76,338,128,151,603,902,913,163,93,817,845,532,216,408,979,471,417,740,366,480,149,969,587,983,38,892,966,591,585,133,655,742,650,432,513,187,605,220,616,718,570,382,224,887,0,245,334,398,718,57,632,534,465,827,989,513,226,895,73,893,204,347,983,826,904,208,302,533,745,66,746,527,775,389,528,165,771,138,303,675,645,250,78,221,562,589,736,308,638,481,326,481,880,198,630,994,112,894,678,224,487,911,104,18,159,890,945,498,76,76,432,317,151,962,87,964,171,232,860,800,687,972,844,721,31,581,471,42,103,836,728,755,537,921,975,1,52,30,338,672,437,995,724,848,734,387,209,460,214,640,339,985,673,378,311,316,929,981,2,438,978,851,732,285,609,365,287,889,807,132,114,178,623,246,447,572,867,78,26,866,946,383,751,998,419,752,911,244,668,105,659,371,690,186,453,782,406,552,160,174,551,205,710,192,61,974,565,579,551,166,550,957,904,3,424,237,135,93,823,425,535,409,789,443,887,306,424,402,376,348,866,827,774,930,84,854,506,90,435,148,309,695,663,571,266,867,81,388,801,131,32,577,442,960,606,521,723,958,416,706,361,768,100,591,206,113,319,578,811,507,663,818,16,714,393,571,645,764,498,392,919,535,697,672,163,242,946,657,526,871,838,184,636,898,218,81,446,956,897,443,160,711,280,197,526,834,166,748,903,628,94,361,260,34,342,113,172,238,422,87,755,300,328,843,566,947,407,928,551,827,849,596,430,590,439,718,449,771,482,724,677,391,453,2,835,857,319,995,193,554,829,95,165,296,968,102,192,521,421,666,229,228,290,654,768,604,148,982,723,140,108,297,541,465,45,382,147,992,327,155,637,485,743,64,814,895,925,150,840,165,836,206,404,31,743,289,768,667,946,473,317,687,247,49,588,366,882,347,185,155,886,366,930,417,631,424,185,240,886,449,704,957,218,844,204,63,765,398,548,892,111,161,935,629,740,806,125,136,513,878,758,409,17,622,829,348,792,247,584,281,235,595,117,615,107,553,315,193,920,363,232,815,463,493,954,485,775,102,575,884,158,938,666,820,308,697,380,193,842,384,286,37,753,449,443,718,312,948,377,172,155,139,810,87,439,527,760,562,739,22,303,444,635,622,560,885,120,648,547,342,413,164,678,877,644,598,658,668,29,673,418,820,952,400,434,272,430,98,649,607,875,218,69,855,352,212,669,411,339,170,237,690,454,320,939,281,954,854,456,200,506,139,696,964,841,294,324,328,392,939,474,521,394,448,32,883,783,943,103,863,186,788,94,392,172,265,556,98,73,901,860,607,745,23,284,573,13,36,551,252,707,881,947,7,591,988,98,280,235,757,886,975,825,137,273,311,900,245,519,704,443,162,377,157,336,484,831,558,429,38,572,217,99,52,848,893,112,190,57,597,718,97,26,216,428,147,900,468,108,283,727,250,854,138,949,301,309,833,863,251,58,522,616,673,53,891,14,245,814,839,63,338,335,910,890,862,112,357,622,106,565,225,291,888,593,905,290,739,848,455,635,140,971,235,7,382,87,504,815,643,141,986,428,198,979,351,607,307,687,798,463,988,273,236,383,365,356,18,778,252,886,493,470,914,65,498,928,177,67,875,625,767,222,122,739,505,650,86,706,527,715,52,531,36,449,9,350,822,923,834,609,490,358,924,514,231,446,594,998,388,550,495,844,347,2,667,631,379,901,974,747,721,873,809,427,693,639,379,196,160,430,378,770,624,285,576,850,270,113,497,91,881,394,542,456,544,28,719,84,669,600,300,50,263,10,567,966,855,640,692,95,867,791,206,339,575,408,235,580,808,13,277,1,314,612,178,658,873,659,588,554,492,467,292,763,719,567,115,955,853,99,21,927,259,642,749,781,996,91,548,276,662,668,375,625,298,500,886,608,964,97,772,462,478,39,557,47,533,584,780,330,704,264,24,492,516,884,450,787,437,979,531,957,894,794,887,616,498,52,309,865,275,25,905,812,911,740,917,180,106,275,222,110,399,538,276,675,321,741,516,697,88,970,395,19,582,421,699,384,989,448,55,889,517,616,607,595,466,600,363,439,985,231,444,820,415,821,929,139,158,824,873,407,613,741,630,60,494,246,543,941,914,860,451", +"342,758,418,26,153,114,782,809,551,364,435,26,254,262,751,429,617,442,34,180,973,331,585,452,517,739,486,259,589,816,548,545,969,813,8,683,525,793,996,74,414,971,35,318,115,465,673,242,26,575,724,952,138,689,931,320,220,577,758,192,740,333,312,365,86,33,682,383,379,419,680,55,755,211,136,953,379,191,324,741,515,602,259,524,487,422,887,425,808,986,151,17,814,763,31,50,583,712,422,566,245,0,628,271,783,867,605,919,650,657,864,802,711,26,893,945,559,916,630,417,38,274,383,66,553,423,42,539,797,358,469,925,916,277,836,211,18,594,763,712,610,146,809,388,316,668,204,839,915,125,365,38,128,978,923,192,812,787,564,543,994,745,706,643,946,682,417,757,437,659,301,8,996,602,776,655,536,414,329,18,69,215,876,64,284,75,325,177,848,563,657,642,476,742,187,454,324,547,687,589,990,996,501,490,591,676,294,143,53,162,838,967,837,33,855,650,83,648,760,457,944,564,539,175,116,243,419,756,706,17,859,706,473,764,112,580,456,131,150,616,884,613,998,580,111,589,348,866,768,476,792,166,352,949,886,49,947,991,404,49,460,494,973,982,79,332,612,523,812,215,324,937,393,466,293,958,235,842,207,572,28,227,784,2,640,13,468,66,942,786,885,933,682,506,868,126,371,739,578,439,947,828,887,802,80,733,754,20,590,790,177,484,64,643,923,401,741,220,806,558,23,589,358,227,788,150,292,887,572,665,964,577,255,311,603,413,953,644,509,355,548,203,136,289,457,680,545,652,581,346,428,210,846,878,940,457,76,866,820,84,731,696,259,871,602,155,498,981,578,524,195,676,15,912,295,970,826,409,936,152,975,285,808,477,466,93,157,634,619,44,87,421,15,916,746,383,604,414,301,333,394,354,346,311,404,268,564,638,751,141,226,672,688,790,298,426,720,861,594,698,134,250,550,157,735,850,309,807,805,75,916,999,804,907,184,602,340,331,388,40,29,587,325,121,501,431,117,927,426,777,494,746,913,596,190,749,267,658,547,483,696,912,477,821,982,280,578,857,321,239,503,885,651,336,453,847,877,49,816,333,653,111,887,985,874,368,51,344,448,978,490,970,296,260,568,733,88,719,428,614,1000,746,873,878,285,270,408,51,221,111,27,11,657,171,906,940,104,882,302,743,622,255,556,215,108,750,963,358,117,909,515,669,210,796,167,390,792,394,316,568,785,803,6,307,248,474,272,942,322,134,914,204,159,752,903,16,177,842,991,249,436,888,614,175,126,675,430,970,265,895,152,519,802,373,703,484,585,465,171,674,350,798,892,846,241,663,963,241,549,279,715,886,474,670,471,680,795,309,996,518,643,498,73,287,709,935,308,780,663,727,426,248,294,100,193,316,735,354,573,465,334,902,44,836,238,255,576,306,430,306,499,565,531,545,134,417,71,474,23,264,191,345,439,212,762,47,753,530,619,94,767,367,82,332,453,339,148,686,544,969,647,499,907,382,642,756,16,63,957,371,685,988,202,990,961,815,798,407,489,646,601,154,667,757,499,697,70,208,731,749,297,981,999,597,642,409,203,995,270,988,840,210,953,199,620,710,430,755,554,530,478,980,970,871,747,522,494,302,190,49,126,12,9,351,670,755,205,309,428,248,712,168,789,713,11,928,506,878,108,288,786,241,504,897,453,304,944,15,829,513,979,845,478,102,196,966,634,725,433,400,651,175,225,696,795,437,40,30,246,811,602,214,831,482,35,605,889,701,535,283,683,668,388,252,796,651,712,744,733,829,15,777,725,206,217,646,873,678,372,289,64,573,763,667,296,616,334,141,431,484,166,292,417,964,460,353,262,59,668,500,258,976,30,209,189,62,743,912,551,966,543,398,133,866,710,444,691,767,358,3,923,790,242,987,571,839,801,11,684,229,291,878,577,396,774,976,66,29,368,323,571,208,484,514,579,70,102,336,515,15,938,699,944,464,305,999,314,327,114,676,373,429,158,159,554,691,680,731,422,214,245,874,346,223,770,636,955,419,300,362,695,312,943,168,487,576,796,730,967,440,528,356,840,233,285,282,532,586,627,385,838,5,998,71,276,656,403,248,91,257,503,695,495,765,777,537,197,487,829,608,104,494,391,947,343,74,251,568,24,285,693,498,77,415,681,189,494,13,850,5,548,292,302,359,792,613,229,110,327,350,651,374,393,520,251,775,86,56,635,273,188,257,952,308,265,876,33,793,625,639,40,321,629,703,280,934,70,448,360,254", +"578,992,483,517,584,983,840,105,185,957,56,326,44,776,708,297,394,239,631,299,124,414,961,956,84,187,533,522,757,238,957,32,537,694,926,254,582,475,894,208,627,393,596,27,525,147,34,148,562,299,911,158,98,100,775,913,603,801,878,917,311,837,195,546,155,532,987,606,314,979,364,162,571,968,133,299,323,795,852,979,587,229,992,910,127,436,828,387,663,946,798,448,358,356,760,584,560,174,111,273,334,628,0,656,370,912,110,602,245,666,524,459,77,584,709,706,490,438,358,742,16,448,74,761,258,206,455,809,448,598,238,507,77,449,669,782,821,656,921,4,755,428,39,522,764,223,78,822,880,237,124,668,38,97,296,968,227,650,204,664,387,897,858,141,979,528,205,685,112,117,119,669,321,97,803,322,38,852,70,416,308,79,750,280,293,782,74,622,147,425,495,133,488,894,325,209,785,185,803,331,781,535,336,19,4,449,567,711,913,370,210,913,32,811,756,141,83,346,158,342,294,914,565,822,877,226,230,511,876,716,641,444,375,603,418,419,333,368,520,930,898,127,586,345,178,27,912,561,297,686,572,31,23,872,887,906,56,463,813,145,978,815,41,268,966,660,821,362,305,659,780,887,922,346,799,929,136,919,759,902,211,947,651,190,797,416,58,111,315,490,138,531,849,788,705,409,677,894,315,815,919,68,485,6,981,22,394,963,835,896,738,36,247,387,784,684,819,541,9,779,255,287,903,913,19,23,39,537,676,160,801,774,362,780,856,29,513,759,11,661,890,696,23,630,688,438,419,347,143,429,445,19,915,28,83,417,657,636,518,829,226,592,397,588,240,442,941,76,508,316,739,501,743,697,451,13,146,837,430,724,796,243,134,776,387,74,419,180,204,526,941,522,931,351,100,404,597,126,738,708,549,880,421,402,515,30,261,279,407,876,740,626,333,805,771,776,184,409,638,463,729,167,469,154,245,622,228,561,519,766,972,71,392,867,713,925,83,44,922,993,365,735,91,446,408,2,711,860,923,38,803,215,126,387,369,516,696,26,728,868,728,550,173,589,816,938,448,832,767,606,641,415,679,449,9,204,579,600,886,56,126,816,416,549,187,526,743,564,370,99,439,724,954,746,593,170,400,441,915,354,603,624,885,63,459,445,57,96,615,580,743,487,970,528,690,729,158,844,772,415,314,391,987,477,240,812,882,611,450,659,936,290,512,32,794,100,547,268,309,744,693,606,226,694,60,699,117,229,648,538,260,519,622,316,265,431,752,486,115,650,889,929,7,136,606,137,37,163,612,524,309,756,457,805,108,877,478,379,920,187,320,909,812,210,794,849,814,911,869,949,645,766,538,880,694,741,272,530,414,798,288,965,987,124,912,555,237,310,880,228,711,544,740,245,498,668,70,985,872,100,749,681,780,653,670,734,303,354,993,937,135,853,12,23,161,326,754,790,554,465,775,832,692,899,733,80,459,70,438,962,26,106,291,75,202,315,379,397,703,375,806,124,586,365,312,256,853,378,300,982,599,507,205,441,851,270,263,313,749,70,837,297,539,208,363,714,115,974,224,864,848,863,980,941,668,514,524,836,134,656,785,584,867,691,468,353,924,697,877,990,821,465,595,907,955,131,984,26,382,418,352,550,146,296,953,354,947,894,994,626,595,41,164,240,297,612,488,804,326,119,461,457,789,500,302,321,727,528,436,725,906,130,485,556,629,680,630,143,578,782,148,800,430,328,989,514,596,90,371,635,10,502,795,508,90,385,520,569,802,832,887,516,124,645,151,383,528,887,854,289,866,302,322,557,73,619,313,315,17,197,522,343,760,261,303,292,64,621,461,792,872,786,67,6,302,491,951,77,321,94,384,361,141,214,99,773,104,887,801,699,115,636,304,171,759,451,568,255,214,743,429,816,719,421,680,693,64,376,901,804,328,225,910,213,133,989,242,76,648,153,233,86,122,789,844,46,447,40,360,185,881,437,773,454,304,549,862,756,359,242,359,112,615,495,361,39,810,139,25,616,643,459,546,813,151,394,119,210,4,285,920,643,372,703,359,321,852,124,427,200,38,91,470,798,377,508,691,456,599,388,478,392,219,250,694,846,407,43,67,587,860,156,155,173,710,783,191,789,428,598,683,130,836,872,444,737,931,956,573,510,756,452,683,866,673,621,473,911,404,141,238,979,379,434,240,902,732,855,278,326,479,188,613,994,519,807,636,680,414,211,914,45,255,335,361,669,572,287,403,528,449,87,625,81,78,230,24,983,715,461", +"76,261,566,74,855,410,517,879,918,216,906,613,520,668,574,175,710,828,609,982,446,32,592,528,236,50,802,994,961,297,24,3,934,950,627,436,944,259,603,997,484,687,698,914,35,230,159,83,135,458,519,516,421,703,504,668,451,775,279,7,26,99,637,569,492,37,559,291,6,660,780,499,303,448,393,416,86,525,670,911,435,654,408,156,223,385,551,426,434,397,81,822,905,880,879,397,856,507,754,185,398,271,656,0,247,880,501,218,154,799,619,900,78,579,533,480,248,184,733,219,739,888,61,31,824,327,195,171,986,36,744,724,58,575,292,922,614,899,805,157,15,234,864,356,640,999,413,858,248,423,9,705,743,252,393,433,372,292,480,390,984,286,352,323,385,303,911,124,501,232,360,195,536,464,6,220,501,931,551,667,280,508,696,324,775,892,46,645,576,560,765,756,732,905,397,290,751,816,885,887,312,107,377,903,624,31,480,928,209,470,366,342,723,655,838,594,733,516,763,554,528,671,992,91,290,23,34,826,701,804,912,353,999,905,117,644,524,664,977,451,362,918,583,336,486,159,276,907,721,564,313,810,876,129,757,270,743,46,8,732,876,220,820,796,70,960,204,720,394,904,389,573,645,180,201,609,725,316,836,317,605,615,235,562,482,212,556,494,162,163,614,998,235,393,952,836,427,62,193,436,827,220,486,548,534,205,517,288,598,466,522,894,522,731,510,855,693,405,901,954,625,2,751,911,204,493,606,178,134,645,799,44,848,5,498,575,664,157,554,875,765,144,633,611,251,2,503,431,506,263,210,81,43,214,364,183,51,473,505,478,260,395,926,75,458,67,267,410,167,692,242,94,464,109,596,762,982,683,903,75,810,471,879,291,487,767,252,950,856,730,679,184,810,399,49,76,539,701,31,585,426,461,187,438,100,627,280,361,970,989,875,119,835,733,65,52,980,693,793,415,654,151,390,842,381,739,993,751,624,705,23,154,888,243,800,866,406,410,878,100,896,589,558,376,340,276,627,687,573,903,199,569,398,165,192,550,941,452,974,324,517,663,978,120,939,907,455,493,97,515,801,236,474,5,773,985,57,726,934,490,460,994,568,735,580,607,835,752,338,303,961,658,726,665,564,807,875,23,269,181,275,692,34,240,76,459,158,951,461,495,781,380,585,879,62,507,988,28,996,2,167,346,575,469,688,756,825,150,158,398,996,228,263,94,341,904,252,884,251,885,64,501,937,89,553,591,87,247,821,260,29,308,198,961,232,756,992,636,428,626,358,511,551,876,846,661,654,902,903,396,948,13,143,290,395,141,44,23,740,769,632,381,634,789,917,709,390,477,917,134,471,196,948,475,290,117,216,58,195,483,51,886,642,108,869,308,777,338,865,20,928,513,178,112,910,169,579,434,703,412,27,480,51,157,900,475,711,934,957,417,622,181,515,288,149,300,599,195,251,501,41,728,918,866,159,732,411,759,236,347,199,678,824,138,296,529,691,900,20,934,269,903,622,670,98,720,9,64,725,223,830,350,531,774,122,988,395,369,895,21,505,712,737,154,552,16,190,834,196,842,41,823,262,29,607,371,908,590,899,990,518,118,45,847,85,668,686,692,272,224,912,120,984,341,258,190,94,225,844,330,986,836,548,33,681,595,723,798,975,50,326,750,494,667,70,106,712,652,600,966,5,719,895,983,164,662,894,158,602,202,140,648,989,761,319,343,178,26,659,521,824,182,65,279,53,681,873,471,171,236,369,762,376,436,494,131,611,257,234,27,505,137,592,814,322,579,675,270,656,206,340,47,111,849,226,571,305,474,512,655,142,643,807,959,225,196,633,600,443,729,26,46,938,688,288,212,356,147,396,268,281,271,501,486,828,437,864,457,485,244,304,569,914,404,355,991,183,888,836,531,662,923,759,746,254,676,324,963,643,784,695,359,113,501,77,209,167,371,986,409,871,781,411,2,175,339,130,517,84,963,703,157,180,491,549,409,94,580,812,132,671,395,988,871,626,55,988,495,414,437,841,445,839,575,644,512,548,285,435,749,809,220,744,268,131,32,849,733,655,280,387,33,794,42,998,403,431,707,258,379,502,881,331,708,961,146,82,708,275,700,561,796,538,264,208,64,452,704,845,950,259,7,286,892,837,2,237,304,625,868,560,370,589,650,389,648,825,314,844,601,34,325,501,837,812,973,783,912,635,821,736,138,426,516,241,138,988,111,46,361,386,621,155,633,566,229,484,735,145,515,117,731,963,632,471,778,996,454,124,770", +"394,587,132,503,512,313,151,722,485,205,480,405,883,872,481,171,982,341,949,127,955,683,173,23,831,40,608,337,663,570,705,669,528,52,366,348,376,993,942,359,431,743,308,783,488,414,145,378,169,834,703,993,19,894,897,439,277,119,608,480,8,49,18,448,143,221,160,487,458,413,938,440,878,444,253,368,927,180,353,725,154,510,547,244,634,586,279,912,194,83,984,359,154,847,525,145,498,466,310,811,718,783,370,247,0,358,576,342,814,284,213,550,526,175,346,721,353,374,409,547,745,739,311,236,698,452,747,342,375,839,784,641,273,962,571,227,806,289,310,843,518,43,846,195,536,71,787,324,116,796,371,997,633,600,17,144,202,388,28,792,313,324,883,38,389,882,215,398,309,755,575,454,811,739,893,866,504,658,804,839,625,98,62,216,899,343,972,384,791,929,723,87,261,489,20,452,867,368,209,78,966,307,561,325,189,441,37,995,445,582,856,476,82,111,837,890,802,74,740,635,684,951,416,662,993,334,74,840,902,507,462,579,396,107,302,259,646,614,657,444,131,473,253,914,902,710,224,575,198,150,103,802,872,843,73,124,647,83,404,813,948,235,151,455,607,509,693,532,263,348,696,877,339,757,861,276,639,966,55,829,326,381,10,320,638,735,710,300,192,129,774,32,929,46,882,379,916,232,115,681,339,795,833,604,641,291,18,715,40,86,664,180,791,361,933,700,478,631,399,935,339,300,326,394,6,418,316,655,660,757,13,321,450,258,828,748,68,494,473,682,110,344,469,700,375,609,10,669,686,956,849,939,765,202,171,68,856,776,904,717,114,482,473,43,351,411,640,775,993,250,42,655,636,628,691,928,904,895,903,584,255,766,131,671,899,776,84,450,183,951,980,514,240,42,10,958,978,507,905,319,280,20,189,838,63,523,594,44,923,30,277,363,787,751,903,39,946,638,262,83,218,243,624,466,56,308,678,885,593,96,455,52,146,342,700,617,287,300,930,890,490,847,236,352,150,368,558,74,592,132,945,326,41,642,206,19,864,932,987,321,558,315,143,558,724,267,567,70,31,829,710,144,341,198,954,947,471,231,232,956,740,514,772,962,297,226,637,828,877,475,790,871,697,850,912,445,522,994,164,746,389,593,185,660,9,568,268,934,67,207,468,895,36,141,502,796,287,515,986,538,995,127,754,110,561,793,624,304,47,893,725,755,9,254,925,585,113,480,486,550,629,587,516,963,113,900,73,638,303,802,148,945,599,770,681,809,808,139,650,454,984,476,214,353,8,689,515,436,991,386,716,483,783,508,627,621,734,949,651,202,337,299,83,816,881,440,339,839,884,384,85,712,695,249,975,867,889,346,550,652,517,141,850,228,446,407,936,966,4,363,97,39,810,780,763,996,371,281,757,248,813,67,835,216,572,801,288,148,201,910,397,38,926,555,831,69,183,394,17,817,933,654,239,768,748,559,701,622,4,583,753,449,685,480,854,608,47,396,115,569,933,336,646,604,465,1,659,266,788,866,114,278,552,96,251,49,72,250,266,115,819,377,477,985,426,796,643,457,171,481,778,678,220,631,845,48,469,908,388,943,858,770,673,983,27,373,761,281,708,413,457,408,43,57,718,668,906,829,913,773,647,625,196,276,83,119,492,267,867,339,82,943,681,766,174,126,205,480,572,623,942,495,954,249,143,316,933,959,109,59,684,687,760,950,80,25,468,614,156,954,31,434,722,129,465,654,571,489,470,266,197,86,686,233,903,793,146,863,903,633,298,901,465,693,534,948,396,215,789,209,840,337,287,884,319,981,827,711,251,252,866,839,661,994,983,808,578,555,615,538,934,684,129,294,490,545,96,567,40,890,950,897,669,7,430,476,734,749,674,124,722,663,583,873,757,479,50,889,901,112,761,339,497,7,551,825,345,155,326,933,535,693,936,13,653,208,244,540,319,202,670,455,843,646,68,930,661,485,202,741,599,586,293,569,232,311,266,579,363,885,628,118,858,245,512,812,354,496,707,915,164,504,156,507,823,780,768,221,148,646,905,699,147,337,564,186,299,409,959,781,164,722,135,226,123,19,898,420,659,468,4,953,808,699,422,83,109,922,14,847,216,838,571,550,186,576,146,717,876,712,533,767,369,598,524,977,140,313,104,144,77,749,745,479,333,876,468,665,846,345,985,219,613,388,683,61,240,407,940,816,991,494,722,481,989,544,395,451,787,673,939,433,53,546,454,693,733,236,219,684,964,216,17,164,251,934,798,947,93,778", +"432,366,985,784,917,752,305,693,259,78,543,70,533,272,253,239,566,228,101,552,614,795,370,778,126,589,827,159,875,455,750,157,28,199,462,60,463,442,959,620,462,951,651,912,511,359,681,378,18,823,768,183,816,812,339,904,358,537,676,743,40,565,156,195,117,738,779,676,323,225,197,221,680,726,757,411,564,886,690,443,407,833,162,18,205,533,622,666,448,839,197,638,120,695,329,27,383,271,509,311,57,867,912,880,358,0,625,924,453,69,537,112,830,548,136,943,863,861,137,928,831,670,682,316,251,846,960,979,189,62,819,128,884,245,504,513,567,650,247,472,928,457,308,738,210,954,374,449,792,616,253,658,538,550,129,998,659,648,9,547,537,931,590,296,732,4,536,922,37,919,791,348,481,449,16,695,73,257,94,72,439,376,506,370,277,43,789,913,658,856,853,700,897,808,513,110,618,258,315,294,563,4,441,854,726,47,802,509,856,965,786,13,195,166,245,646,453,335,646,966,884,335,427,513,45,679,937,859,178,466,270,378,262,784,780,766,460,550,107,480,211,303,712,753,830,776,174,619,192,713,678,976,617,488,200,500,312,296,133,673,215,21,795,533,814,260,776,483,395,16,888,787,619,905,345,685,380,645,304,868,206,211,47,608,995,198,270,545,390,817,113,288,921,586,252,511,737,715,354,388,407,377,701,271,214,379,580,703,676,685,534,632,39,630,715,103,113,281,155,439,222,302,228,199,967,677,328,621,931,204,445,729,148,692,311,978,938,660,232,964,795,855,465,944,410,889,989,216,779,363,463,72,427,211,871,483,62,645,163,733,639,115,2,168,764,656,820,915,608,306,195,205,352,738,275,218,24,257,181,57,964,346,768,36,957,279,406,857,57,517,549,187,991,394,76,444,921,34,402,805,729,832,132,993,401,322,279,376,166,589,431,545,794,248,529,101,619,416,107,679,330,112,586,923,117,821,351,497,383,52,388,547,287,689,785,155,815,365,345,760,525,37,662,629,782,16,43,54,589,707,468,223,16,881,539,203,873,954,437,658,778,606,772,134,998,964,936,703,468,807,491,411,840,269,613,3,341,236,679,992,414,786,720,283,514,754,656,598,134,411,80,768,90,203,175,414,11,289,512,936,887,600,451,380,567,951,840,302,616,999,18,433,150,292,197,22,733,435,755,533,283,592,764,384,227,10,198,669,678,414,672,641,372,806,438,560,949,383,851,821,94,823,986,519,694,919,776,656,604,447,806,488,865,84,754,315,968,154,736,957,372,164,552,629,157,963,181,554,966,496,126,77,416,837,150,110,538,31,491,799,335,373,769,518,152,315,619,428,174,607,447,265,922,368,107,451,821,85,162,33,269,473,309,559,940,658,830,417,724,178,448,942,326,88,737,611,224,108,284,758,242,468,991,427,191,378,668,955,100,153,347,476,80,93,258,190,423,17,445,374,275,636,297,972,806,459,51,438,721,68,819,548,359,847,933,299,914,421,452,616,694,665,773,255,946,152,571,419,790,563,233,317,776,321,122,131,705,164,337,801,358,837,232,851,818,683,65,510,368,623,793,752,340,78,128,520,972,889,316,383,191,244,367,825,171,306,698,194,211,991,840,326,655,259,282,17,754,971,834,637,118,464,458,698,690,223,594,860,445,45,361,681,477,132,375,357,292,410,819,463,202,729,476,845,884,765,211,941,245,980,738,742,974,14,514,526,490,854,682,829,513,815,596,594,109,344,874,913,175,185,565,576,917,233,468,911,664,98,152,725,713,765,437,729,903,388,808,692,774,742,761,971,753,403,200,585,749,602,27,206,957,142,305,946,960,902,806,577,263,68,649,312,991,752,856,532,39,321,848,599,663,143,75,7,20,269,109,692,435,595,799,180,353,891,67,992,945,878,820,667,422,102,668,218,516,894,574,884,615,751,378,832,375,374,244,760,699,854,956,160,679,130,595,244,982,661,145,840,592,59,710,216,19,539,364,480,93,748,121,471,844,404,975,656,434,500,993,32,769,611,401,331,164,869,433,993,700,285,17,523,619,666,516,569,54,996,685,383,142,993,638,365,100,684,162,729,582,716,454,860,432,372,957,124,179,100,94,310,499,572,131,837,514,421,472,29,83,255,230,255,475,260,755,308,572,345,720,386,838,795,386,279,55,65,638,73,769,677,692,165,276,614,801,613,992,723,827,908,504,143,637,952,96,732,685,866,386,810,570,295,588,622,129,568,14,89,684,321,668,732,723,72,87,941,215,638,835,191,846,253", +"786,154,566,953,630,402,449,840,73,98,342,267,793,736,616,897,351,829,804,921,524,420,116,609,565,140,71,302,573,180,685,824,721,140,601,833,88,605,141,706,407,744,823,51,122,135,634,656,185,101,78,812,28,741,744,625,292,537,90,833,154,893,11,574,864,37,729,276,227,390,182,702,687,251,357,175,878,735,46,822,435,609,521,389,293,188,111,274,614,598,578,867,907,518,272,249,91,779,908,502,632,605,110,501,576,625,0,568,574,410,589,852,919,700,547,889,519,697,308,863,901,346,17,599,718,962,884,850,403,279,379,730,69,411,554,693,443,780,623,197,511,410,483,10,197,535,883,553,125,445,826,672,609,887,898,661,405,689,391,381,392,479,619,623,523,334,132,137,330,283,581,615,196,921,304,46,451,515,503,174,260,690,410,462,181,487,252,532,653,240,601,624,215,785,433,32,146,190,392,244,549,459,275,598,291,90,717,323,892,670,916,20,148,556,535,484,956,862,14,93,520,777,990,477,335,292,896,765,122,569,423,398,357,266,751,568,893,487,232,483,357,708,497,417,145,205,17,877,743,61,747,643,72,746,340,782,935,932,792,898,907,183,21,225,163,817,476,125,891,280,369,27,136,692,451,256,93,237,284,760,627,171,597,386,512,737,612,508,257,718,504,896,83,443,895,150,347,181,157,917,998,983,617,983,755,571,340,758,982,110,414,672,306,219,881,150,287,927,667,241,256,576,994,417,478,843,880,905,728,464,37,225,13,591,856,671,473,260,553,640,70,969,889,787,480,318,362,697,680,619,673,550,266,115,781,366,105,116,696,992,509,465,441,763,375,882,477,72,298,636,902,15,350,180,164,514,335,150,353,906,233,442,493,573,857,6,536,958,902,808,578,641,460,939,416,759,685,389,718,458,218,751,527,628,935,292,927,430,5,793,517,698,471,327,618,274,131,675,988,336,850,84,668,853,721,951,487,182,204,277,931,12,529,350,801,275,566,42,297,582,122,200,483,395,779,49,760,728,705,572,165,377,409,481,8,57,491,864,72,78,199,394,981,925,772,887,789,319,648,372,371,345,468,373,347,576,731,484,945,575,767,406,212,706,560,724,907,35,975,278,425,35,175,26,762,53,977,761,453,434,663,539,688,785,784,482,569,679,16,419,953,501,725,7,220,132,589,4,358,319,320,651,698,88,335,227,622,350,936,234,663,303,970,604,163,339,488,245,259,882,556,264,725,407,725,314,850,804,801,518,826,788,777,746,288,952,736,804,291,550,8,214,814,509,226,235,522,215,304,793,709,794,924,92,584,956,816,180,383,600,133,388,77,398,852,619,598,799,222,96,603,16,889,563,665,299,69,513,47,898,965,310,918,681,670,212,590,409,33,694,518,786,722,823,737,849,568,680,615,920,918,929,962,986,67,13,665,433,629,635,630,398,665,402,436,820,138,955,129,941,911,813,908,164,716,240,98,522,947,751,689,388,893,318,513,791,973,683,121,281,321,202,833,505,143,595,407,6,744,536,901,414,666,441,342,289,709,283,760,522,789,759,853,932,871,950,533,622,789,63,276,59,821,815,399,770,247,2,764,242,291,115,329,113,356,806,409,543,399,670,404,855,444,49,779,400,257,317,375,179,405,904,802,485,598,703,918,679,269,900,692,404,137,693,816,110,486,229,249,881,666,296,21,123,977,46,802,865,715,555,129,358,869,976,450,211,702,323,853,16,840,692,198,705,173,912,804,971,74,125,224,410,868,977,246,755,385,144,836,22,14,433,788,100,78,758,521,274,334,295,816,520,693,705,546,81,298,395,54,773,259,656,877,911,417,404,540,71,927,986,506,789,832,795,923,455,781,360,788,270,816,718,169,159,727,371,688,973,49,727,760,623,682,824,69,482,128,869,630,7,279,18,84,696,124,958,757,461,821,392,822,159,682,99,709,539,143,315,533,233,190,990,148,568,583,996,938,147,661,382,147,582,816,805,423,341,850,296,476,841,985,437,479,30,157,771,984,476,335,974,324,309,393,126,751,845,985,586,603,508,237,379,253,948,675,63,389,734,299,832,389,248,914,423,727,596,528,970,247,659,460,56,803,531,359,54,143,29,119,125,171,758,516,630,977,188,45,661,4,800,258,656,858,154,517,587,397,128,440,818,224,678,393,249,394,200,541,532,714,45,992,440,191,958,111,254,29,827,871,312,390,165,326,69,629,418,495,758,757,817,352,309,322,773,104,274,787,782,593,797,420,722,64,407,46,70,913,611,211,469", +"313,544,605,482,916,350,120,129,953,510,408,388,287,764,700,489,51,684,103,74,435,210,513,878,864,390,385,746,665,596,267,271,574,882,621,140,253,516,716,473,368,70,119,620,228,152,789,215,569,191,257,275,657,741,323,105,857,940,920,550,952,817,913,259,902,77,819,622,961,777,970,518,692,21,65,399,480,650,848,520,472,549,954,925,725,959,852,793,770,202,445,266,631,473,499,965,218,54,865,841,534,919,602,218,342,924,568,0,598,15,965,81,22,997,580,389,417,558,67,124,461,641,290,651,990,579,564,710,252,37,835,334,186,994,877,255,866,805,763,656,16,989,266,713,402,394,870,357,174,453,657,843,427,909,87,772,981,674,236,204,998,584,856,332,798,808,327,769,987,433,936,61,309,996,474,901,811,524,257,677,404,969,427,451,765,76,312,702,994,658,8,732,768,957,239,927,209,328,742,844,912,840,125,671,38,406,328,606,402,830,518,635,792,433,497,124,17,652,315,474,699,294,966,4,837,437,82,551,724,569,553,820,359,947,403,715,317,31,878,280,621,117,820,556,365,692,9,915,204,347,241,616,732,781,619,684,953,738,815,113,193,544,396,135,774,35,707,611,596,27,815,271,76,645,980,965,989,961,937,326,781,846,507,271,719,360,70,264,696,13,21,223,738,976,569,786,873,228,953,847,363,469,503,782,646,763,493,313,533,746,740,338,321,57,470,583,225,58,605,708,500,48,156,100,911,617,953,494,483,913,738,525,964,229,699,48,504,420,735,314,180,120,608,878,43,199,320,691,419,659,762,190,17,6,772,849,903,577,597,146,411,674,656,18,501,670,40,678,705,514,997,514,33,152,822,672,173,450,475,986,826,519,349,342,75,207,136,802,813,826,972,463,644,986,703,602,81,816,594,51,573,245,837,798,926,851,446,7,615,546,509,469,620,441,554,540,573,770,527,231,318,873,518,405,518,38,329,540,68,415,48,197,500,554,578,460,200,246,267,434,651,925,267,591,588,165,68,933,431,233,655,431,708,376,871,517,116,627,305,210,511,915,128,82,248,350,261,141,702,184,611,701,876,190,320,429,3,120,795,946,756,520,540,894,469,19,806,675,978,816,517,412,368,259,270,125,696,745,50,913,442,408,565,61,23,397,207,971,596,301,40,791,206,22,813,786,246,926,686,318,42,900,875,748,23,864,1,330,6,207,144,437,537,293,114,607,547,808,845,135,577,819,86,158,329,691,451,441,79,270,884,963,800,861,847,577,648,692,403,421,66,192,934,428,468,274,447,828,912,253,628,547,529,239,627,14,708,931,14,707,592,998,202,893,342,84,183,414,339,484,225,982,812,565,848,49,893,60,473,181,56,996,792,395,470,22,533,584,562,844,644,109,246,354,863,459,39,866,383,117,73,462,36,806,881,968,571,876,720,216,895,187,205,166,959,69,370,350,241,28,692,303,166,885,875,497,406,885,729,681,538,223,737,77,1,597,453,927,303,135,238,598,850,524,285,480,602,84,404,127,843,969,722,893,679,337,629,379,671,634,621,666,363,875,721,548,70,997,722,220,970,778,898,541,185,326,661,690,62,730,944,346,143,861,843,505,867,179,351,718,671,761,501,748,698,516,488,760,57,977,622,589,564,949,756,341,55,873,306,839,774,321,117,745,300,603,212,628,125,661,357,123,441,770,385,423,498,202,91,342,309,973,981,219,824,499,410,313,106,539,257,468,422,105,26,650,753,578,349,953,436,324,986,362,730,1000,793,656,334,770,394,767,449,291,163,100,66,423,402,839,171,254,672,674,30,876,973,724,410,972,236,760,983,712,385,251,104,946,386,538,65,471,621,947,232,210,718,586,489,654,881,124,635,159,50,221,547,848,342,235,689,292,221,707,197,609,463,744,287,852,710,905,194,123,999,501,924,779,35,81,175,815,318,742,45,388,905,710,217,659,115,211,49,786,845,444,955,23,820,386,83,746,473,12,153,799,702,562,687,794,856,96,505,216,935,642,598,125,191,689,94,876,781,55,74,241,152,971,948,453,107,70,456,464,497,701,817,440,582,171,321,809,899,747,414,174,433,975,154,947,488,695,810,950,850,496,565,364,893,30,353,367,910,738,886,772,524,579,962,732,414,382,430,725,892,563,150,648,263,78,398,856,954,324,672,666,552,271,280,892,242,474,754,465,772,114,595,289,452,302,988,272,89,215,155,836,667,351,268,767,541,217,21,436,835,816,755,485,660,591,843,155,673,105,984,103,329,54,291,419", +"693,480,837,526,484,142,631,647,402,295,906,239,467,135,446,48,430,218,980,629,668,161,706,237,898,967,471,35,556,541,550,192,947,539,455,116,161,305,709,770,129,989,288,538,764,210,656,764,721,568,926,606,449,15,703,99,580,698,35,700,387,58,15,557,479,498,155,680,113,563,670,713,678,763,324,470,839,607,904,24,945,789,46,21,464,762,340,580,258,723,393,606,663,803,416,637,213,912,478,5,465,650,245,154,814,453,574,598,0,792,176,44,491,467,855,18,726,457,887,925,242,201,502,352,386,906,612,573,908,36,801,153,136,972,815,181,934,439,757,117,692,317,935,103,719,698,475,444,413,771,597,954,511,467,308,910,461,562,915,22,354,919,72,555,158,922,453,191,417,378,32,217,812,523,151,880,72,881,200,56,44,335,491,488,40,314,406,508,730,500,152,82,992,1000,651,785,802,32,184,813,900,286,295,703,923,793,517,676,510,250,728,932,753,225,603,133,794,237,407,505,61,53,94,604,89,482,989,20,378,715,138,695,283,964,541,331,214,459,397,677,252,86,918,238,505,63,122,27,818,616,458,127,724,281,301,570,366,354,589,797,694,206,127,307,206,26,839,912,426,174,910,818,816,823,717,304,601,996,29,133,739,243,676,10,404,628,124,338,831,803,215,132,945,196,388,738,772,263,255,24,93,555,488,904,846,402,490,13,129,785,386,75,798,285,588,389,679,598,782,360,634,27,307,69,792,960,665,632,426,250,317,828,16,794,306,285,653,623,981,4,971,206,564,422,802,759,705,394,242,393,30,614,309,701,999,862,71,454,429,153,832,985,787,873,910,398,635,948,231,616,788,215,600,871,356,449,199,770,707,586,842,429,437,883,719,51,660,915,795,436,47,24,525,222,573,619,408,153,224,650,570,152,368,328,259,932,364,381,572,522,906,274,78,911,966,578,926,978,762,47,654,146,114,533,697,258,453,773,660,616,74,295,963,572,660,47,528,300,649,706,459,617,288,324,118,40,692,72,678,623,365,751,177,880,232,318,986,26,858,976,489,121,531,857,168,301,30,681,858,513,290,785,814,547,835,419,16,827,954,34,163,717,984,680,787,229,807,239,201,515,260,40,531,466,956,369,52,702,307,72,853,123,373,652,589,525,876,433,633,39,639,690,814,597,19,348,262,413,860,497,690,803,672,677,343,970,658,417,777,181,998,287,9,638,326,623,225,824,17,340,822,544,225,908,745,80,739,258,381,711,206,11,460,748,813,821,798,37,83,357,958,599,692,311,194,528,834,497,137,518,117,133,57,203,406,481,663,96,305,957,162,142,957,973,780,913,996,203,391,815,892,175,322,673,168,125,203,105,72,540,372,105,286,276,169,787,584,887,914,8,903,266,92,881,367,969,600,737,139,377,494,781,995,518,499,475,195,473,140,487,596,985,115,371,665,259,995,668,869,647,632,460,3,902,938,645,157,963,714,239,488,518,457,218,106,556,357,760,667,290,71,809,720,366,365,671,195,684,764,510,356,79,246,801,569,815,490,601,136,345,683,612,530,536,557,35,621,609,877,702,675,657,331,161,288,84,546,733,84,979,174,94,410,503,36,645,673,280,771,246,835,230,839,822,128,668,29,476,623,862,20,536,708,64,376,984,18,733,987,766,170,823,345,583,600,587,33,182,918,323,569,773,996,468,745,11,600,308,607,337,531,100,12,962,829,138,735,915,970,967,177,156,818,977,531,850,778,587,515,460,924,791,457,997,54,137,356,997,948,102,341,275,793,604,230,997,716,601,322,952,996,601,376,752,997,903,678,564,854,975,912,589,80,879,559,408,732,804,225,431,788,835,225,831,795,846,105,106,827,670,81,872,434,126,333,90,708,25,748,353,569,234,135,572,386,2,842,752,873,780,579,607,297,925,145,146,399,585,716,697,657,530,373,803,499,726,436,705,582,675,677,142,480,741,959,373,248,581,493,115,905,893,535,183,257,344,219,466,753,275,775,856,355,988,362,989,624,600,610,714,82,574,897,600,369,303,312,798,101,473,111,607,827,395,665,821,436,679,101,461,482,341,437,789,241,314,143,880,432,483,691,36,833,450,848,928,415,949,775,106,60,927,350,881,519,21,202,429,38,467,956,698,196,337,720,751,977,638,642,306,951,455,296,606,982,594,982,743,664,487,620,265,294,261,245,526,38,960,476,121,38,371,133,136,24,466,713,613,847,418,23,376,304,192,475,751,228,434,769,14,641,367,440,545,185,444,61,193,989,250", +"587,983,448,469,362,295,278,159,701,359,639,405,423,252,405,262,142,38,490,258,159,62,498,651,985,787,370,642,212,629,933,210,459,825,269,243,507,513,821,871,251,380,453,16,343,493,554,816,704,444,504,919,717,551,988,31,134,918,667,76,712,819,907,91,842,519,609,360,624,281,965,407,610,460,708,348,14,241,487,803,592,481,199,641,241,684,964,830,273,824,945,175,201,202,569,668,238,942,422,179,827,657,666,799,284,69,410,15,792,0,565,760,261,134,90,559,562,183,927,753,166,827,862,772,128,882,161,345,527,975,659,568,952,706,307,204,389,46,525,202,927,780,919,468,678,265,651,653,514,236,332,602,74,349,623,746,818,564,184,966,521,608,449,725,262,777,569,788,548,718,462,940,930,834,211,535,600,102,396,728,203,532,242,225,695,28,737,556,849,620,868,294,375,558,292,335,421,520,693,49,188,972,683,510,132,975,184,95,96,513,580,234,482,395,825,545,620,989,884,325,5,251,838,800,622,895,74,335,456,952,94,797,94,900,254,523,390,963,320,277,902,301,511,269,375,417,659,391,7,508,228,712,146,359,846,274,271,602,170,596,898,268,11,851,719,677,560,217,266,297,52,167,171,450,239,90,951,92,549,273,819,534,821,648,410,662,971,687,425,384,68,531,350,95,403,671,408,810,120,254,783,767,999,202,982,867,937,589,941,592,143,896,37,520,683,474,697,131,904,321,156,352,625,706,490,502,930,776,524,846,311,45,231,603,994,157,551,264,759,119,610,224,504,149,966,640,310,426,40,713,873,185,636,349,76,234,903,476,898,164,881,705,503,402,187,911,408,923,334,477,11,548,667,318,330,120,798,786,710,948,976,664,26,617,140,590,770,266,320,90,15,53,399,348,113,691,391,677,558,325,695,680,391,398,358,95,636,815,366,659,508,110,98,800,832,858,223,697,762,573,685,629,321,747,112,572,167,613,865,731,970,103,384,714,743,746,132,971,979,980,996,541,111,52,997,377,887,30,279,982,454,96,857,384,669,702,417,527,929,425,891,941,642,472,981,743,38,241,177,554,613,370,674,322,480,721,89,932,949,738,947,997,843,821,4,380,939,966,335,64,477,307,206,362,284,938,813,108,561,922,784,415,339,146,156,755,810,338,403,622,667,476,76,201,991,774,886,267,675,500,71,616,292,347,790,647,307,336,426,329,697,211,166,912,59,530,910,332,888,582,21,749,344,94,325,813,689,398,942,655,100,27,984,182,354,737,798,362,254,148,946,7,190,965,80,816,13,802,87,49,928,638,92,843,708,257,655,761,526,970,16,664,740,861,96,816,493,330,924,583,445,315,201,66,895,435,735,533,852,256,861,555,299,437,69,893,970,309,237,903,252,863,1,444,172,209,315,559,368,507,860,783,681,852,460,244,137,469,782,115,413,529,294,62,425,32,126,592,974,519,650,686,648,61,424,243,554,595,30,956,178,328,504,806,331,742,809,973,767,164,680,690,808,254,18,535,228,603,846,568,678,245,200,68,496,866,665,100,382,400,305,328,276,984,648,160,110,208,148,189,635,978,166,513,799,104,432,799,444,642,693,923,59,82,472,735,451,166,246,628,26,52,494,606,841,900,491,642,878,805,886,366,797,773,725,987,735,145,708,47,179,891,745,664,829,562,459,859,991,536,136,521,242,50,305,706,732,317,989,587,193,595,494,626,147,129,607,939,211,776,347,471,801,538,188,784,873,728,293,924,799,4,500,689,653,128,898,379,334,446,859,289,814,404,888,536,534,894,757,371,60,637,157,530,308,748,588,448,61,581,285,507,812,772,8,863,594,760,509,723,150,986,974,952,192,869,81,630,94,901,344,894,523,707,731,174,141,363,290,844,703,230,665,690,258,97,486,636,961,610,232,374,341,592,685,204,635,129,885,856,577,499,858,164,146,519,339,546,146,785,757,95,31,715,734,733,45,405,556,679,231,867,152,194,566,41,829,698,606,287,715,988,333,273,701,275,765,695,825,590,874,368,688,724,864,455,160,146,478,505,605,151,530,380,696,195,874,409,570,321,6,966,966,149,312,615,206,617,589,462,75,570,922,53,951,231,93,727,161,509,357,801,264,587,848,803,238,398,683,568,333,181,23,780,189,721,212,12,893,623,501,383,309,327,480,504,194,3,964,255,528,287,290,447,857,37,417,352,804,291,118,214,656,983,110,315,983,250,23,439,457,104,554,974,127,381,13,440,138,211,228,517,710,502,925,879,271,378,560,439", +"659,148,985,13,926,285,314,759,729,166,211,991,118,749,557,455,705,943,400,512,125,833,523,935,975,800,912,305,323,180,173,283,657,457,878,943,87,77,324,918,454,456,856,579,509,857,669,245,898,920,237,118,880,426,920,570,886,231,980,330,211,769,844,44,215,129,967,192,392,770,184,62,611,293,711,425,160,510,233,100,934,378,415,157,225,174,322,847,209,448,658,88,729,120,94,699,396,366,924,459,989,864,524,619,213,537,589,965,176,565,0,161,186,563,798,336,970,379,551,52,182,973,956,741,474,423,392,501,610,286,866,775,636,440,51,517,529,710,81,174,202,973,683,378,102,866,591,719,252,973,199,687,688,180,830,364,755,255,452,26,452,389,982,746,894,962,379,931,373,570,160,245,297,117,937,274,522,346,517,334,103,433,695,20,985,737,475,269,354,199,989,622,213,583,332,242,934,957,253,430,391,211,210,811,432,532,284,562,686,145,677,17,910,917,258,275,284,279,40,727,865,271,349,908,77,21,203,324,599,899,860,775,408,858,919,688,578,232,491,61,695,413,637,554,443,956,89,927,865,397,481,12,121,129,698,273,889,436,91,206,191,377,460,1000,703,483,757,605,565,9,570,367,659,787,139,582,466,604,863,987,309,999,643,622,249,4,206,269,749,620,78,958,285,434,792,142,412,692,432,211,955,817,758,898,344,310,864,137,880,19,84,501,664,735,449,523,809,178,159,948,358,375,493,118,857,99,122,63,652,375,899,693,450,201,882,532,101,461,802,21,82,204,303,855,64,976,122,336,731,244,800,433,387,658,717,8,227,110,182,343,172,36,512,101,553,163,205,752,147,560,873,166,768,506,222,215,575,990,694,546,696,890,91,409,287,413,190,925,59,337,416,926,821,153,323,904,878,193,614,88,583,859,489,5,886,775,471,226,363,609,558,919,881,860,157,366,300,154,662,626,505,693,632,672,316,513,278,840,572,774,782,856,528,621,800,282,31,404,513,292,610,427,767,37,111,18,725,75,975,20,630,211,43,81,931,537,971,907,30,324,995,930,256,123,803,13,817,993,496,635,373,939,83,845,248,574,362,629,549,954,289,610,749,847,514,433,254,774,402,648,642,36,531,461,161,451,982,205,120,774,126,815,785,329,650,989,824,321,928,983,623,756,721,122,470,671,715,151,437,94,230,401,722,914,671,433,30,71,315,909,226,265,996,107,923,549,418,557,206,234,408,753,386,870,222,494,308,850,297,88,80,673,695,318,332,575,901,693,483,688,887,717,446,617,858,289,828,889,337,326,806,485,455,854,493,655,784,284,133,268,951,46,715,848,499,281,899,401,912,134,929,106,241,862,836,491,801,783,990,707,329,249,54,298,754,529,44,538,318,548,412,864,318,256,657,651,349,819,262,322,885,5,75,261,146,411,452,573,470,136,726,91,393,25,355,862,513,377,465,637,766,402,731,874,95,655,465,801,314,838,528,910,809,475,309,660,964,63,337,896,826,631,16,113,32,381,500,726,465,496,132,331,459,894,80,538,77,150,664,402,671,647,421,802,389,220,309,403,997,760,961,575,187,697,903,349,323,957,748,381,137,144,499,850,660,380,773,756,836,647,922,405,159,528,214,726,188,989,871,402,661,827,455,228,291,836,253,826,237,69,878,984,900,622,950,490,996,125,440,105,921,726,852,283,420,13,876,202,435,798,948,976,198,945,750,2,469,549,729,936,963,892,692,642,569,923,516,151,346,697,335,788,203,817,758,259,498,779,326,581,616,17,642,603,23,743,807,662,160,248,399,493,46,487,522,982,645,689,609,445,880,88,818,425,768,452,767,106,693,947,89,399,161,550,426,948,827,434,118,360,402,25,405,511,665,166,655,258,198,20,935,140,93,117,671,378,800,922,376,460,872,585,359,543,414,285,648,557,75,38,218,145,235,431,560,327,59,418,415,200,127,695,711,82,875,886,28,328,898,701,19,247,927,482,793,828,910,203,72,512,952,833,133,302,263,220,870,797,103,126,916,305,577,214,662,257,145,80,302,586,255,252,129,561,52,302,716,578,120,61,346,534,608,903,535,37,679,567,957,21,137,652,96,540,781,213,41,65,370,623,847,370,89,958,136,167,236,698,395,828,549,898,63,328,70,124,827,530,789,386,524,478,409,708,456,664,911,926,172,890,403,547,62,423,687,753,246,279,969,217,593,173,486,901,409,514,235,167,746,138,346,684,458,756,266,141,348,154,151,777,765,195,69,297,46,369,527,32,309,573", +"55,855,334,183,942,2,880,668,299,476,571,507,227,734,269,486,697,866,985,679,840,199,688,523,186,551,284,488,736,169,285,324,232,959,474,938,681,733,813,164,698,44,318,327,211,226,349,342,581,335,979,822,445,500,807,868,291,4,345,951,645,1000,825,2,399,809,641,60,583,140,287,649,574,541,356,61,771,53,683,999,763,204,591,652,809,234,579,214,807,88,896,392,514,692,224,624,83,637,147,929,513,802,459,900,550,112,852,81,44,760,161,0,252,200,751,959,901,473,351,332,92,357,574,269,106,82,916,476,556,793,697,565,822,782,267,875,521,860,686,273,268,582,24,878,339,791,330,115,607,169,884,305,69,965,877,945,120,694,490,750,659,211,21,859,925,702,323,321,573,353,547,659,853,485,675,373,242,662,952,979,283,223,473,992,84,196,227,358,575,175,666,368,726,819,733,331,775,180,161,385,960,708,810,120,6,527,268,230,54,823,481,237,804,423,929,729,278,962,408,18,368,907,165,692,764,680,952,273,276,108,697,94,925,184,821,782,257,372,798,846,140,454,311,384,694,357,338,844,206,387,669,891,542,747,255,257,850,56,22,832,874,420,444,199,373,414,654,471,205,462,231,774,142,473,255,800,288,139,166,463,483,291,468,429,534,548,750,601,40,341,662,289,194,754,670,334,109,644,408,450,697,384,445,572,489,690,719,177,417,559,349,708,540,19,15,978,699,928,821,390,867,541,146,519,168,273,287,287,216,196,652,164,77,952,155,732,802,920,323,296,519,27,944,304,633,842,586,320,740,234,742,504,555,780,509,677,386,524,72,866,457,853,363,311,362,397,624,779,639,420,356,703,158,269,369,185,845,454,348,125,2,856,11,615,86,761,126,920,184,835,504,34,15,613,73,73,749,318,91,177,331,204,51,647,703,376,348,898,700,755,358,735,69,125,44,766,790,796,458,123,630,996,133,960,532,886,886,213,809,94,848,651,238,35,148,970,314,984,351,739,921,90,461,615,809,756,786,738,466,314,443,259,498,845,65,468,989,668,611,251,616,9,292,70,740,243,491,507,354,935,75,993,993,719,789,479,239,563,730,681,862,330,897,408,664,893,873,612,902,412,483,257,982,357,408,16,884,692,937,626,575,152,644,348,464,510,967,620,317,403,301,640,23,614,199,759,215,886,850,870,975,670,607,882,153,885,293,830,534,823,971,127,593,631,956,176,365,752,934,870,803,273,856,349,528,81,48,531,492,86,413,563,385,687,546,584,581,796,312,807,590,304,641,874,79,610,274,787,35,701,707,765,385,299,66,480,323,915,482,811,674,493,212,54,278,442,888,613,411,110,643,671,528,164,351,826,107,471,614,758,156,600,765,777,312,926,984,214,469,319,200,127,428,809,503,965,730,152,275,503,348,483,303,591,503,912,384,12,27,427,461,621,251,283,900,953,703,871,915,113,472,918,380,41,578,655,998,423,700,995,778,543,385,658,294,648,95,696,539,762,970,313,3,178,921,347,486,382,383,371,715,339,805,730,984,691,699,230,119,731,144,246,482,879,846,555,899,966,399,705,383,468,983,324,260,943,483,49,366,502,732,32,245,750,361,663,367,73,314,716,135,431,658,812,76,912,217,668,340,696,797,952,318,169,901,43,833,548,56,171,74,481,117,552,409,829,454,392,943,832,357,395,649,64,36,776,770,527,84,736,255,380,464,328,662,530,893,164,402,974,59,148,661,960,373,872,90,236,14,678,761,602,741,959,593,447,57,207,520,30,756,210,83,573,186,72,908,543,350,867,951,785,686,303,553,377,685,570,612,19,948,430,815,480,878,249,175,890,488,232,881,724,405,352,260,561,296,908,956,885,208,443,389,182,867,328,51,574,543,615,898,534,535,936,273,102,999,319,470,688,444,15,754,730,72,986,207,107,837,817,780,755,301,344,974,624,885,876,368,287,723,757,224,415,696,907,900,192,180,78,559,716,127,8,98,615,830,809,726,583,164,682,854,369,212,901,865,472,388,143,396,88,274,501,477,249,359,670,732,258,529,519,98,894,591,681,795,295,171,908,848,373,287,687,98,521,579,242,935,119,111,130,975,604,707,169,957,969,374,86,437,438,243,972,191,391,564,255,198,478,911,827,186,608,847,680,936,918,794,80,503,334,22,725,237,865,624,215,843,292,82,637,47,708,129,130,718,657,222,226,625,622,781,378,131,867,618,581,640,4,286,560,784,349,2,946,203,239,592,757,290,14,50,755,354,151,147,256,730,600", +"491,372,36,732,653,25,642,390,354,23,731,952,758,961,708,490,255,564,795,852,410,351,103,846,91,817,30,191,456,986,953,375,663,687,183,773,920,808,409,952,627,219,902,626,266,756,760,684,825,545,530,187,896,432,743,628,236,369,523,566,321,273,672,916,249,396,706,296,254,716,939,410,336,437,585,99,635,305,519,195,968,337,79,281,461,348,779,342,214,490,841,655,224,461,253,631,109,829,32,203,226,711,77,78,526,830,919,22,491,261,186,252,0,7,816,506,181,193,957,399,236,695,841,854,30,983,56,244,560,164,300,750,374,201,798,141,287,237,205,326,784,504,899,2,82,132,790,328,326,935,810,37,723,929,542,323,600,252,14,898,514,857,365,157,684,119,71,72,848,524,275,910,687,665,639,851,904,377,231,24,811,175,837,611,299,900,477,738,717,853,248,33,150,524,206,759,597,945,948,98,261,468,708,992,376,881,90,115,337,165,954,185,489,526,15,902,993,218,368,997,413,443,13,570,435,527,727,757,507,109,531,439,857,530,69,961,900,792,198,219,623,438,578,355,269,459,681,127,21,327,155,295,674,930,191,9,557,761,547,562,169,971,393,616,889,676,502,364,12,593,869,851,836,561,420,666,111,358,717,555,699,77,34,801,155,905,767,881,545,502,5,114,120,695,924,797,86,579,389,140,350,552,298,687,782,319,306,838,880,167,906,25,76,533,671,487,291,773,573,952,338,987,97,910,124,979,130,785,758,474,850,612,322,335,312,237,639,833,939,727,926,346,952,459,269,86,174,578,286,180,339,751,153,456,878,389,927,934,9,599,66,157,430,725,78,720,551,798,584,291,177,778,203,212,511,451,385,420,710,975,968,910,109,343,618,728,623,87,941,509,525,384,822,859,821,211,326,514,459,118,375,61,155,621,358,188,331,61,403,318,460,680,872,504,790,277,337,436,105,716,389,526,996,552,809,906,631,59,378,906,687,590,646,878,498,663,818,603,65,339,320,354,952,902,392,516,99,25,527,29,3,32,20,873,429,400,151,860,314,931,52,624,235,321,150,547,543,109,834,9,11,660,763,156,428,403,168,717,4,686,340,896,814,190,393,805,607,173,351,298,536,2,648,921,790,186,639,423,43,86,729,519,678,891,401,147,989,738,861,174,468,959,283,203,370,147,874,777,144,625,19,669,429,900,328,837,875,376,53,936,431,372,710,385,447,155,621,481,216,242,727,46,124,767,481,972,545,15,678,124,339,464,232,181,395,134,178,364,929,486,200,234,944,618,264,821,507,710,746,905,678,97,440,933,455,215,431,83,781,426,821,136,649,600,966,853,427,715,436,170,765,723,694,145,780,405,702,304,888,454,588,556,346,540,350,626,225,298,622,56,821,25,52,974,961,164,642,384,581,95,613,34,458,101,219,291,431,107,661,964,164,970,300,456,411,91,931,123,975,419,627,830,188,201,374,895,637,647,772,720,696,906,374,10,362,396,147,994,287,531,914,782,972,754,44,325,909,948,69,225,39,883,209,623,440,826,541,952,549,807,896,943,830,631,246,700,863,612,845,829,958,177,89,705,653,547,108,798,489,410,364,869,479,185,586,899,365,753,612,731,753,370,849,810,129,685,965,676,893,644,847,127,802,572,855,848,441,48,283,140,412,939,971,556,944,930,264,799,270,932,41,309,714,911,749,436,564,87,980,388,153,180,141,284,71,222,384,632,480,823,152,168,892,665,109,324,9,761,986,334,518,98,509,300,676,794,350,144,122,113,801,89,111,623,135,534,202,691,316,430,258,159,277,545,844,13,316,20,397,618,542,881,86,946,40,146,518,409,555,287,433,376,644,374,311,919,93,783,564,187,919,440,609,822,600,763,754,276,351,207,709,995,301,641,778,537,695,42,18,686,711,29,931,583,725,146,344,533,953,746,154,420,980,579,452,188,773,604,639,570,335,947,764,381,12,646,557,293,424,752,60,822,985,75,361,325,849,430,178,874,714,395,209,789,699,201,330,768,153,191,462,468,578,581,887,790,279,618,299,869,247,814,242,637,686,965,562,813,507,878,455,873,891,253,423,336,532,689,903,636,513,525,434,810,588,218,139,340,565,581,421,349,651,443,267,189,661,113,646,413,42,542,522,849,507,849,557,832,197,736,78,818,594,568,61,31,265,235,733,881,484,282,78,394,520,972,378,792,237,350,115,28,477,960,30,736,732,597,869,551,900,772,381,594,685,60,999,772,234,718,602,246,956,13,679,898,180,498,223,15", +"467,746,409,180,37,319,84,542,681,533,354,270,547,373,132,358,436,80,955,100,238,334,128,732,450,906,306,534,566,749,269,724,672,168,315,370,83,155,745,170,101,607,452,946,645,687,823,289,663,426,521,124,366,35,674,182,354,465,166,957,749,136,180,523,326,904,669,860,411,977,778,272,34,642,424,506,793,639,613,851,250,396,575,758,968,109,725,769,345,375,904,899,750,701,512,614,172,240,972,991,895,26,584,579,175,548,700,997,467,134,563,200,7,0,734,714,754,525,439,820,122,158,840,487,72,499,655,605,493,691,106,661,357,336,702,583,201,684,56,576,710,783,420,794,716,86,978,540,645,975,238,567,399,613,851,387,276,193,814,554,70,266,58,265,880,176,305,399,155,32,945,326,777,510,856,173,412,943,711,872,23,222,774,966,498,384,856,784,804,873,714,37,764,81,800,690,161,550,708,763,361,616,966,389,134,533,535,472,345,78,581,681,586,923,943,1,734,833,954,11,223,220,852,66,391,673,810,137,920,590,404,747,6,618,55,118,725,855,226,110,458,37,105,536,936,981,912,471,63,73,982,116,216,303,722,180,810,181,40,381,514,43,413,907,197,671,283,997,859,945,590,45,560,961,755,346,677,495,542,546,962,19,930,109,917,198,465,612,427,530,307,359,946,235,354,150,797,156,673,241,162,134,316,743,662,132,696,822,99,839,477,408,58,868,750,12,75,91,521,455,747,695,826,600,545,170,372,783,985,467,926,568,643,972,341,782,497,284,542,280,724,980,609,308,783,630,805,884,60,206,311,606,889,967,712,906,55,533,351,758,545,633,858,87,752,400,438,228,374,54,632,812,522,570,566,512,370,399,587,430,723,228,574,637,798,662,218,277,355,935,894,16,911,693,547,373,44,310,213,422,374,119,366,269,872,635,591,929,347,628,139,92,411,193,186,796,495,301,345,602,109,400,312,60,184,887,701,881,132,753,492,10,527,669,505,662,806,382,508,196,975,266,373,456,592,983,37,585,968,710,484,64,403,972,91,134,897,123,398,598,208,512,885,45,605,772,525,456,102,946,950,794,76,917,248,395,173,359,542,636,501,87,219,70,86,714,3,778,612,994,455,548,549,593,518,457,784,800,96,28,142,476,913,243,892,488,902,972,422,927,529,134,188,446,186,400,285,756,20,245,116,247,88,312,181,668,531,371,451,895,691,410,573,568,169,835,501,701,622,276,439,639,872,5,264,17,984,840,566,124,955,94,308,697,665,433,574,998,547,795,611,386,857,138,165,415,465,75,152,129,733,815,199,547,403,202,381,274,731,773,912,475,122,168,954,902,218,335,639,622,858,478,48,646,965,474,916,843,220,952,227,518,183,965,557,772,773,982,844,388,362,271,65,259,540,478,831,940,988,541,164,401,170,106,769,470,700,147,518,830,872,234,738,102,474,785,188,510,854,812,14,500,283,531,41,212,381,404,736,631,920,8,26,174,119,935,764,489,8,730,917,228,511,362,919,796,759,937,688,83,693,84,937,764,269,326,366,114,246,180,911,694,362,561,365,357,639,981,200,144,757,919,274,202,202,779,783,698,42,876,429,745,9,134,483,641,223,482,394,501,382,183,26,725,416,64,438,476,729,964,82,585,589,709,891,252,682,531,379,512,908,496,26,771,27,542,75,382,651,169,104,405,909,145,491,768,122,879,687,868,472,363,415,554,860,842,865,763,506,264,504,249,136,98,281,417,426,259,285,541,727,108,569,700,573,544,939,226,604,424,100,928,781,141,758,932,763,3,608,482,368,380,517,364,154,772,562,104,853,127,783,718,790,276,928,722,322,68,810,349,717,44,957,268,763,109,960,374,209,145,19,353,729,100,255,621,607,271,822,147,438,715,578,372,737,594,511,441,139,170,696,460,570,18,4,577,773,977,520,399,223,785,902,524,3,959,921,73,454,753,846,567,68,580,609,863,527,941,9,997,273,75,780,358,174,839,574,333,698,662,400,695,878,804,580,266,362,928,279,530,293,560,93,877,799,444,177,577,662,467,581,558,524,63,985,170,312,965,439,296,279,530,262,914,746,115,480,969,343,845,776,732,427,235,827,39,270,578,982,408,669,751,295,657,853,890,281,847,338,534,353,463,309,304,221,553,854,52,167,961,635,831,440,71,810,956,381,780,425,625,711,94,257,599,478,526,633,320,747,52,25,514,772,884,767,556,392,29,117,708,622,414,412,381,637,418,246,502,238,508,963,917,682,538,883,307,925,193,294,197", +"33,876,227,775,484,458,408,938,251,618,484,279,842,784,895,491,82,686,738,210,114,92,686,84,315,388,928,177,37,471,406,339,221,838,709,564,256,501,552,969,420,604,726,406,199,951,766,397,58,436,793,274,534,24,780,513,361,278,903,872,128,478,969,369,697,92,285,907,107,68,731,768,921,877,107,953,834,865,978,149,311,989,719,607,992,7,948,820,767,9,145,659,265,957,102,983,284,993,500,358,73,893,709,533,346,136,547,580,855,90,798,751,816,734,0,680,950,959,533,686,870,199,372,646,206,769,275,364,912,771,859,85,364,783,580,899,639,5,575,483,866,113,885,193,268,544,686,581,970,535,195,122,107,455,570,614,774,744,131,820,246,770,608,515,784,930,245,458,547,872,53,987,543,495,660,280,781,63,720,597,799,966,938,465,981,794,888,640,187,668,818,932,440,11,256,585,672,865,598,569,827,84,753,530,68,403,940,296,836,973,633,271,787,776,195,229,347,85,103,866,697,740,779,464,407,899,443,408,79,506,739,898,27,174,223,751,584,6,448,203,481,739,503,267,80,157,435,139,805,493,304,52,146,435,880,372,971,987,702,695,668,974,145,231,994,587,163,234,275,123,986,459,939,780,593,523,537,177,226,260,65,705,586,64,302,990,196,44,639,354,617,383,421,802,588,111,231,267,107,558,103,54,9,642,356,993,566,556,934,789,562,540,336,91,56,661,435,874,849,766,619,314,626,27,664,545,227,6,456,513,825,122,984,586,644,513,45,953,539,987,199,206,95,818,997,400,459,125,976,702,631,947,847,188,45,206,718,880,968,52,753,47,986,333,275,988,883,966,629,960,596,677,760,638,47,802,845,694,937,326,895,915,692,819,588,75,917,611,819,304,517,744,847,967,743,118,831,568,285,744,532,973,743,264,609,144,579,396,97,238,324,920,987,20,172,100,79,865,950,55,323,77,933,366,19,901,131,462,612,296,648,548,446,270,622,732,21,3,485,854,591,114,349,33,545,585,133,53,257,396,644,84,654,325,901,542,920,457,548,22,709,737,636,716,824,430,434,224,97,570,86,150,976,300,337,709,439,791,994,782,378,963,99,625,884,577,924,580,373,197,119,864,484,579,155,52,614,299,823,139,912,524,898,93,379,28,68,831,175,718,47,351,489,75,362,704,594,11,862,440,269,971,150,439,6,151,689,868,266,169,285,857,785,913,413,530,256,401,28,939,783,797,673,702,342,415,257,786,580,716,5,258,176,731,343,973,512,351,653,588,803,898,661,880,323,364,743,553,969,153,648,4,630,205,21,531,17,376,227,283,670,933,510,591,168,874,32,934,493,483,297,390,676,385,846,404,717,783,255,467,993,461,23,957,859,697,613,75,196,112,424,166,850,978,408,449,286,764,897,248,290,474,177,691,51,744,643,943,144,316,867,924,245,274,203,779,561,594,269,341,782,387,811,26,371,199,175,982,790,9,5,204,294,283,315,478,820,989,135,701,943,561,301,329,19,375,690,45,146,423,734,510,406,216,335,624,917,278,996,270,745,426,662,87,333,464,139,516,693,303,117,284,811,514,678,548,470,293,572,767,389,30,431,455,771,935,382,406,524,184,733,995,706,291,487,108,576,542,873,908,515,770,775,790,720,954,931,528,440,755,546,831,357,555,474,507,803,997,277,715,6,228,857,143,566,583,330,364,144,406,836,739,446,896,414,883,44,124,476,677,959,992,832,295,798,144,756,665,83,404,31,594,52,322,106,922,831,845,376,347,855,455,434,473,488,289,967,144,769,992,788,583,890,351,558,506,456,107,256,499,47,970,942,741,297,763,235,809,420,941,911,88,925,630,882,997,27,594,169,640,262,11,984,614,145,330,885,924,907,306,210,356,264,889,508,38,80,880,360,212,475,664,461,734,236,708,56,174,661,381,106,71,729,395,431,623,627,854,349,147,563,544,427,530,630,386,492,914,867,671,784,356,567,397,470,924,36,147,577,412,839,167,511,228,849,737,590,758,659,543,623,34,963,476,748,552,427,956,597,718,416,161,500,664,412,353,324,50,591,118,255,551,371,30,489,201,208,210,520,546,491,392,272,570,747,664,122,66,817,913,51,754,571,975,199,130,802,217,525,766,386,529,891,513,336,238,310,849,726,76,488,612,389,156,360,327,343,776,285,362,980,532,136,710,873,447,577,750,499,784,255,276,118,546,903,213,832,512,483,243,154,250,702,275,2,820,355,291,532,425,258,243,592,100,914,331,358,893,241,465", +"955,207,428,752,416,666,693,186,359,951,964,784,612,490,182,917,706,965,549,700,416,657,789,937,995,381,144,709,723,423,218,96,44,505,942,869,359,836,623,549,364,7,929,223,735,319,99,792,9,481,444,333,247,912,295,231,932,114,746,530,313,373,879,321,410,642,115,891,182,721,597,106,66,960,171,507,695,681,944,94,317,361,549,664,639,327,409,661,773,4,64,516,447,39,264,135,72,577,125,869,893,945,706,480,721,943,889,389,18,559,336,959,506,714,680,0,359,219,153,117,569,584,600,387,533,868,299,377,929,278,591,566,756,79,577,38,682,125,857,746,811,464,261,904,913,923,845,832,411,368,89,940,971,920,581,319,223,800,268,593,646,249,992,758,431,637,591,76,35,893,857,859,667,324,347,824,115,202,853,20,955,750,2,969,132,928,808,898,306,826,42,612,722,711,841,564,366,786,831,209,71,739,916,26,229,872,236,191,635,419,222,522,689,1,499,998,978,707,523,410,667,57,460,936,899,752,682,502,100,21,775,530,681,130,265,541,586,936,872,126,503,174,604,257,314,34,728,614,812,218,187,163,949,100,997,977,832,310,15,847,370,878,278,721,127,345,4,815,483,167,631,198,939,201,457,278,291,662,585,159,217,605,989,661,537,347,94,74,702,974,226,245,140,58,540,789,624,918,25,132,904,308,211,398,856,193,986,317,288,581,122,866,919,315,528,759,524,940,637,55,989,642,827,994,738,301,733,204,887,671,351,196,651,595,890,544,655,129,845,991,905,547,202,956,369,561,502,132,121,480,410,296,596,336,917,816,919,852,787,895,569,307,810,382,732,226,920,339,368,503,529,983,203,793,283,569,554,123,725,134,231,310,361,812,925,855,126,840,43,299,301,515,516,161,837,364,694,431,602,70,304,636,871,907,237,554,33,126,262,762,405,979,678,246,570,371,438,846,577,361,654,536,423,359,47,299,656,520,53,992,574,229,249,61,773,164,252,277,75,666,207,563,853,502,96,556,911,352,189,526,179,307,612,884,797,125,87,65,137,214,150,85,786,864,950,402,122,563,668,465,890,176,289,554,836,812,781,929,235,854,489,74,278,184,877,805,320,784,949,655,33,173,176,694,845,306,463,86,867,93,758,612,180,831,999,636,781,519,32,401,548,72,517,486,80,188,140,487,742,523,774,350,192,182,728,39,314,174,375,351,117,971,36,193,631,323,68,222,291,176,182,316,747,765,639,689,412,482,365,496,117,406,943,53,311,505,739,43,872,411,787,56,21,194,499,90,7,626,207,675,164,24,771,767,743,668,977,868,484,455,975,523,305,735,516,78,727,910,775,867,846,902,694,650,685,177,159,459,989,252,700,590,746,625,308,934,689,357,909,844,599,587,266,265,752,686,964,325,686,884,924,422,793,851,590,209,444,600,517,995,444,974,22,568,939,154,542,670,270,346,328,718,467,457,297,968,428,449,93,767,100,155,417,959,909,712,308,153,954,218,555,316,906,805,680,861,292,611,472,550,217,716,728,20,308,442,647,748,323,918,852,345,599,234,577,931,685,56,343,540,725,23,801,595,610,936,522,761,773,135,7,243,805,407,527,835,669,729,39,253,474,910,119,212,79,338,50,662,649,346,240,647,556,161,327,747,360,222,887,575,449,168,173,182,369,862,211,455,204,556,707,508,323,11,637,598,369,28,683,780,84,126,799,421,100,50,515,90,979,523,519,182,965,548,155,615,75,29,596,300,420,800,630,303,848,117,503,768,253,485,265,205,62,261,802,86,785,893,732,429,665,115,819,58,370,997,62,543,470,904,598,317,237,982,73,65,918,649,866,205,70,892,557,661,865,527,749,154,787,690,154,19,245,412,100,321,562,283,116,312,864,888,855,256,147,521,834,161,258,765,494,430,204,276,752,266,783,252,954,630,969,787,96,28,799,297,990,676,325,422,208,201,516,732,948,239,837,381,173,612,918,643,71,480,684,3,449,527,713,409,719,48,814,164,949,503,424,649,181,258,438,809,513,445,626,911,685,806,607,448,892,662,86,949,29,25,107,863,958,288,713,989,947,347,46,977,920,427,49,559,58,674,46,774,856,391,669,467,619,556,597,757,429,620,447,64,735,498,809,343,607,635,253,779,568,691,592,894,953,796,405,517,770,711,283,853,187,571,402,73,603,923,380,345,578,551,686,453,111,53,565,610,497,223,632,407,53,212,12,158,883,10,703,325,487,343,309,500,711,34,248,964,407,595,344,370,711,945,827,187", +"883,833,625,408,381,716,358,921,99,242,466,547,906,33,994,621,910,898,602,642,680,106,343,118,974,582,773,7,662,564,625,833,226,78,767,318,904,573,742,341,350,362,920,898,219,492,71,411,535,814,684,454,565,323,983,699,290,41,456,749,142,948,609,783,58,819,458,980,991,712,105,373,325,589,813,11,693,351,558,901,685,103,453,289,31,315,498,156,167,804,179,503,995,311,865,428,470,450,921,573,204,559,490,248,353,863,519,417,726,562,970,901,181,754,950,359,0,787,956,232,426,379,408,185,693,517,181,863,170,443,486,90,660,840,405,432,148,888,950,899,67,423,847,913,923,832,457,561,236,544,400,734,744,26,91,582,887,654,693,449,423,117,510,326,794,742,502,193,452,107,473,839,561,159,890,947,371,802,756,218,291,188,686,71,504,450,776,719,290,16,819,795,892,67,82,374,318,614,410,980,391,635,911,197,75,250,177,960,604,837,677,793,8,252,169,411,92,535,452,860,520,95,24,290,59,416,829,119,49,734,96,367,301,872,360,347,101,681,167,886,29,156,123,148,840,132,357,12,719,828,963,618,76,680,350,69,975,581,147,249,744,340,442,900,857,334,110,378,394,850,636,207,718,554,298,722,827,692,837,852,840,786,603,896,153,850,314,10,60,80,671,226,507,713,822,673,646,278,268,641,234,145,518,819,100,428,96,338,810,659,61,423,711,96,190,964,96,757,862,321,426,518,220,428,786,898,984,179,221,992,23,811,713,519,869,775,959,693,728,62,60,452,820,735,579,878,443,598,387,938,486,619,269,674,505,256,705,6,619,395,836,515,192,5,591,640,724,490,502,821,742,630,802,476,150,446,725,270,812,99,7,653,247,186,326,896,45,386,439,566,743,261,177,633,431,250,1000,721,218,235,432,298,502,633,377,342,151,547,120,253,760,860,358,393,340,593,803,61,806,815,981,949,614,543,444,607,870,64,961,860,971,575,263,861,698,372,634,868,338,591,30,908,481,998,165,411,813,375,67,338,322,49,586,122,16,921,432,328,344,730,232,36,595,268,799,225,97,650,957,125,735,411,810,115,687,5,956,630,284,237,747,728,395,673,359,913,175,105,668,121,641,255,405,330,319,158,143,986,881,299,761,931,359,553,521,429,677,40,883,427,895,912,142,254,717,562,185,994,356,333,405,963,960,489,1,187,6,94,706,296,47,943,121,921,832,294,274,984,510,136,825,354,549,624,966,901,253,699,819,32,912,658,622,370,287,464,608,193,747,381,310,723,166,127,389,79,504,52,66,674,735,455,494,351,891,425,847,946,943,845,549,21,82,840,910,703,781,556,902,181,306,891,838,461,333,908,817,675,665,529,755,623,824,834,633,362,431,851,587,99,977,213,608,41,423,651,775,708,175,299,15,165,582,959,567,492,713,284,294,163,219,493,994,212,94,704,883,54,579,554,335,593,513,597,36,423,43,43,845,891,221,740,587,61,639,432,299,320,891,729,702,761,37,629,159,66,609,605,622,180,510,151,632,816,465,550,378,814,485,585,250,97,553,530,81,410,619,822,533,436,416,607,766,663,984,530,952,292,225,103,945,908,623,167,83,474,658,251,474,224,577,525,148,532,534,648,989,646,297,941,738,124,562,646,857,209,705,170,684,63,261,322,102,285,582,138,781,435,473,547,987,781,404,78,9,734,172,195,549,183,840,575,774,250,581,866,541,442,159,466,515,875,173,951,784,723,972,623,49,358,189,960,730,362,869,768,858,728,937,910,351,696,209,445,894,662,657,985,935,200,399,673,977,955,378,466,785,598,114,922,398,274,174,707,33,296,272,948,385,597,336,639,40,308,138,909,323,278,339,842,907,358,850,314,987,141,947,979,490,253,342,361,498,127,735,892,493,137,367,676,92,353,398,344,360,618,58,424,273,377,694,988,476,751,200,478,699,687,484,861,397,305,126,595,760,7,615,456,429,725,763,786,3,536,713,549,499,519,884,793,719,659,415,871,513,749,249,698,760,48,336,18,163,6,997,833,767,46,342,56,833,238,653,338,264,867,699,358,259,12,924,437,348,77,274,129,982,80,45,647,697,81,684,790,321,15,608,444,733,694,549,33,173,52,599,203,315,997,439,72,870,461,186,72,730,636,162,751,529,571,433,170,898,156,643,371,906,990,913,367,966,347,655,87,471,784,489,759,355,3,927,420,574,214,375,971,853,738,913,101,329,129,327,725,135,272,440,32,893,385,690,216,476,27,958,450,81,200,912,269", +"353,719,275,597,553,671,960,931,179,228,734,601,609,703,518,68,302,820,81,531,41,126,46,925,872,245,328,718,953,10,702,252,805,651,277,236,330,553,854,1,759,876,15,412,290,302,353,968,55,122,486,82,334,144,25,199,403,630,369,306,513,908,894,24,578,199,522,683,492,100,481,924,3,602,203,774,121,265,441,179,633,237,243,395,686,801,832,321,876,6,211,959,366,31,705,352,50,486,4,671,347,916,438,184,374,861,697,558,457,183,379,473,193,525,959,219,787,0,183,781,719,562,779,743,353,546,274,952,546,371,160,283,630,698,5,277,682,368,973,705,276,377,533,644,688,70,844,952,171,278,988,919,695,119,909,26,844,993,184,177,712,651,289,131,184,364,773,255,411,215,512,31,580,906,791,956,508,770,757,838,776,417,138,482,341,333,101,30,805,389,488,758,437,161,731,392,694,183,46,395,244,766,806,228,680,79,380,316,845,649,272,597,622,449,758,765,447,355,663,210,868,49,262,475,237,832,812,266,500,465,530,447,919,776,426,323,38,816,726,514,577,267,143,765,741,240,123,781,402,793,298,977,432,19,33,947,937,699,725,976,216,693,56,346,853,113,275,863,7,494,273,962,61,497,170,666,541,234,867,687,449,1,275,752,895,547,263,37,979,417,149,263,381,41,702,697,89,16,647,214,281,542,712,194,149,760,976,14,604,75,581,200,268,586,62,274,249,948,146,946,856,837,124,810,416,450,133,317,71,135,553,712,762,118,198,828,311,830,602,294,515,242,801,296,243,894,193,383,994,494,888,899,954,856,18,293,476,663,909,234,574,182,881,359,3,175,508,75,259,994,110,36,515,260,556,416,536,449,541,924,376,116,268,917,900,690,217,360,37,307,665,314,708,909,341,504,52,990,254,41,979,463,624,969,678,750,867,357,80,32,209,57,49,474,392,12,374,841,789,132,500,966,824,363,127,137,373,664,273,659,923,932,902,158,52,469,606,640,587,6,675,138,321,795,315,324,735,804,175,660,231,908,53,979,646,508,688,222,169,454,49,482,826,307,472,787,749,131,372,794,189,47,93,760,698,651,734,222,312,119,722,566,522,288,486,311,614,713,637,793,547,679,420,478,754,714,139,501,5,83,375,186,258,544,917,119,220,939,268,833,560,800,131,503,855,998,273,48,313,969,845,928,169,330,990,291,838,387,635,712,181,857,224,271,256,235,189,599,84,841,182,675,227,375,266,947,261,471,614,928,584,88,940,118,567,193,856,15,507,198,7,239,659,773,628,71,529,233,562,124,209,142,446,525,238,301,477,821,604,924,719,288,873,959,426,957,61,770,768,856,423,568,521,145,258,136,776,726,138,512,274,807,470,52,469,651,674,494,657,991,615,939,617,643,425,362,636,530,284,446,441,966,557,348,656,655,251,242,916,449,414,833,675,659,320,787,60,914,891,989,402,295,956,740,807,414,160,925,186,78,754,35,392,520,214,220,263,233,72,655,480,645,208,700,265,618,426,563,422,69,275,667,521,91,4,970,452,154,548,972,314,374,199,719,520,901,549,141,863,309,11,682,169,803,544,541,99,956,266,356,864,59,331,34,394,197,789,953,671,901,60,874,153,668,909,865,574,248,180,385,934,589,584,215,468,989,982,326,461,64,621,880,683,920,385,723,159,461,875,908,63,315,133,458,182,440,254,289,852,714,504,617,995,581,76,598,562,141,340,427,582,284,88,129,397,552,657,313,473,241,980,89,728,31,985,322,440,911,360,157,950,960,981,714,603,960,410,18,857,726,911,405,590,333,480,782,644,880,601,353,992,335,108,93,179,832,844,410,177,564,336,546,385,5,454,679,283,542,309,934,225,381,928,373,132,566,740,185,37,380,795,401,347,293,354,782,316,613,499,697,989,158,949,420,347,779,858,191,116,381,499,394,487,76,620,759,278,729,481,23,717,196,767,979,225,471,838,634,23,634,362,298,592,229,892,537,892,425,861,698,244,161,607,220,660,998,478,323,775,461,501,336,92,636,588,381,656,855,992,603,755,738,958,994,219,260,991,14,412,339,380,3,226,12,589,649,623,689,806,851,670,649,445,151,196,815,752,913,311,388,225,888,577,366,111,498,334,911,893,67,169,428,808,859,916,285,760,591,693,12,986,210,551,141,959,662,899,264,851,485,754,524,794,238,62,380,655,490,480,219,390,756,944,926,63,596,408,529,980,70,189,14,750,229,540,605,503,604,501,340,581,313,627,81,402,307,619,289,23,872", +"452,607,207,866,441,842,799,876,420,42,815,9,671,725,499,359,52,698,464,578,630,249,735,814,463,543,959,443,613,117,726,15,953,860,967,340,606,460,256,695,154,613,6,360,502,645,800,855,964,73,812,494,375,814,575,348,920,266,438,570,590,807,246,670,467,920,55,410,793,627,569,600,38,805,666,82,988,84,854,486,732,125,542,807,155,718,706,473,887,914,351,560,420,597,837,184,670,356,316,895,983,630,358,733,409,137,308,67,887,927,551,351,957,439,533,153,956,183,0,667,459,600,223,840,142,263,315,93,953,535,498,515,813,481,538,374,153,376,220,128,756,144,629,718,111,977,688,179,291,489,634,494,535,330,561,355,651,511,951,827,209,83,701,729,893,974,339,657,459,21,234,238,482,490,619,566,721,820,534,359,272,579,849,315,467,947,560,290,646,931,752,34,578,810,388,56,468,136,905,389,281,507,713,507,998,747,944,313,380,445,916,222,918,509,320,46,87,62,603,158,567,70,407,289,55,379,16,81,89,459,395,937,250,282,537,242,988,412,320,808,609,966,978,530,184,647,427,6,136,866,107,593,850,231,425,424,166,96,288,867,584,77,523,612,844,256,892,58,837,970,42,550,885,240,568,258,364,802,733,45,245,735,586,698,505,535,333,476,876,723,171,955,796,778,536,948,974,500,18,972,424,513,84,687,107,518,358,796,477,111,98,790,72,138,600,645,987,662,178,885,953,662,326,300,770,250,506,939,872,344,816,505,185,347,220,542,559,413,295,111,135,318,246,636,372,68,317,278,775,676,542,666,75,60,260,962,910,593,146,43,689,875,84,656,157,593,165,139,944,519,921,484,598,391,730,314,203,918,795,86,523,436,232,251,35,654,340,378,614,333,390,117,975,808,8,231,394,412,784,127,373,526,428,193,848,935,770,566,716,410,273,84,888,1,816,627,408,556,144,600,289,183,640,728,233,184,106,569,355,502,772,200,543,118,100,648,452,580,536,200,233,137,602,913,365,642,612,9,931,509,536,997,133,85,34,457,910,504,11,674,385,624,276,449,175,445,537,460,328,703,55,36,515,115,548,924,472,442,133,219,882,343,439,778,62,822,412,418,138,381,779,309,216,429,490,111,115,482,736,36,200,534,31,643,214,352,554,807,930,476,762,725,130,886,123,517,913,73,16,114,538,450,434,806,503,210,510,883,624,800,346,302,128,328,177,884,989,189,774,931,299,127,605,748,638,165,124,750,84,824,492,830,754,755,816,103,695,772,935,985,391,623,971,565,56,372,670,985,744,349,628,428,355,794,581,61,69,344,195,700,488,18,104,241,833,148,952,515,224,283,698,137,944,12,657,153,86,612,157,741,335,959,126,697,873,622,153,856,708,355,826,101,45,471,173,28,220,142,442,629,327,268,509,192,73,312,454,613,908,180,499,356,131,398,2,49,546,665,829,896,798,848,815,553,937,181,117,96,491,57,756,818,323,302,211,152,986,3,987,885,65,403,342,556,18,823,673,518,221,277,662,762,886,384,430,333,124,569,441,669,641,295,354,997,518,55,218,583,168,688,565,134,428,329,720,926,460,715,217,214,514,187,476,966,877,330,442,974,514,819,503,70,973,950,363,593,170,692,969,999,570,181,481,518,764,830,800,121,585,918,707,652,469,721,297,82,164,972,746,167,287,756,353,507,549,838,600,62,299,999,421,179,870,740,256,348,556,815,971,24,949,820,623,397,51,35,597,898,349,180,784,616,913,489,690,870,247,941,140,290,32,720,920,367,677,760,909,22,117,23,419,572,866,325,41,548,27,191,992,838,543,664,138,939,711,796,170,785,947,666,645,833,277,7,676,114,493,234,743,360,912,592,711,552,560,623,258,443,291,516,755,409,358,803,283,875,628,141,360,194,275,523,75,964,852,441,924,586,334,356,325,999,62,295,302,965,236,86,399,206,612,391,952,2,909,677,531,594,239,818,22,855,448,875,490,150,681,737,211,425,439,823,856,919,326,948,964,22,711,89,974,70,371,679,989,5,532,631,329,713,941,12,50,680,639,605,109,862,463,338,199,972,230,85,525,681,842,322,298,595,601,892,937,624,264,719,434,441,745,937,56,884,447,24,147,655,293,937,411,876,358,635,523,14,75,434,756,579,648,645,768,245,208,69,649,98,111,647,984,802,780,975,591,76,109,896,334,83,788,354,896,735,612,920,669,244,387,660,90,299,709,559,109,881,849,351,683,585,491,383,54,708,31,757,788,391,444,98,183,433", +"60,546,176,425,433,659,544,323,502,758,262,771,520,50,509,325,414,4,431,329,967,429,217,228,308,981,458,21,751,149,258,311,195,995,502,946,681,908,787,160,443,569,886,848,515,746,267,884,816,153,16,372,372,918,424,438,85,460,949,98,839,788,662,699,450,900,249,870,382,219,10,111,975,500,937,422,832,924,547,950,178,501,107,193,147,25,134,79,790,77,665,697,993,366,607,668,32,812,624,684,826,417,742,219,547,928,863,124,925,753,52,332,399,820,686,117,232,781,667,0,312,597,977,269,38,42,77,513,358,508,510,497,482,390,911,58,245,336,933,175,585,986,509,648,83,254,332,271,223,400,457,387,570,38,327,560,237,489,426,98,43,584,389,573,111,257,642,859,933,630,384,283,771,431,281,360,764,240,112,976,466,404,89,20,316,923,876,808,554,596,461,533,393,710,885,684,55,597,717,961,786,545,521,966,386,901,996,783,226,169,905,366,768,460,531,969,477,284,603,396,994,520,375,667,473,601,329,94,674,802,972,314,976,437,170,631,501,614,973,830,845,579,120,448,746,928,21,318,361,522,48,853,899,545,660,91,12,374,905,67,682,834,273,233,493,143,834,293,169,133,708,201,694,565,939,257,401,45,624,136,367,566,296,957,34,890,259,311,301,927,387,786,610,571,104,597,463,517,104,557,693,577,387,691,686,395,722,550,620,130,726,415,469,371,934,695,958,867,84,937,393,829,994,869,939,62,464,186,465,558,796,262,802,29,518,15,785,805,838,813,484,995,893,195,513,608,362,843,267,102,680,197,674,46,662,249,166,360,873,247,272,106,842,197,916,479,338,87,19,576,477,481,338,99,67,917,548,652,249,613,686,660,335,382,124,408,889,265,123,815,475,613,32,783,316,950,338,547,399,485,675,696,488,393,903,731,547,564,821,292,226,925,256,51,536,637,582,191,968,352,997,961,324,458,915,575,422,880,57,636,36,927,536,757,665,682,917,367,658,753,658,332,158,516,608,186,884,735,822,273,559,356,393,581,735,13,234,138,860,750,507,120,456,141,790,682,843,343,603,810,116,535,412,438,697,342,264,555,758,24,693,472,62,801,19,830,292,948,810,798,42,325,621,520,240,541,246,638,332,906,102,384,811,380,462,215,455,945,666,511,662,254,730,801,950,86,155,906,238,589,503,471,493,392,482,324,64,58,352,39,37,44,623,987,251,65,168,714,431,165,668,973,987,796,500,731,485,90,159,210,478,840,623,541,726,310,846,545,670,973,641,58,391,525,285,154,107,557,391,937,340,398,751,135,161,161,56,79,68,289,899,494,665,611,474,542,436,997,326,457,952,553,622,152,418,17,545,847,220,996,74,283,78,697,116,533,142,765,553,340,903,850,736,667,543,893,642,420,193,619,592,342,451,579,496,508,19,327,687,659,191,221,993,683,47,316,91,814,980,542,873,127,443,748,363,838,409,112,591,56,248,200,847,73,561,263,180,912,320,651,327,194,427,308,331,741,658,918,985,571,213,34,984,198,392,806,329,547,299,158,728,773,10,262,625,687,260,187,706,537,679,777,69,63,914,784,845,531,171,831,372,297,383,925,722,117,793,657,364,455,120,344,907,299,225,326,299,886,908,277,99,712,895,684,261,644,854,151,566,652,620,3,758,555,454,867,69,66,384,214,252,288,812,703,745,929,599,420,431,839,324,784,576,673,398,208,425,477,285,500,565,941,929,890,783,969,621,150,940,256,554,752,440,379,636,597,838,134,269,770,307,162,263,466,617,291,378,148,323,889,357,779,153,919,197,871,908,746,124,405,205,162,209,3,84,509,626,463,254,444,272,323,580,26,213,895,37,77,240,216,350,835,179,341,577,787,219,810,304,993,575,712,978,528,21,768,322,746,48,979,553,798,183,946,545,767,719,931,977,930,904,344,487,690,845,666,151,875,873,237,232,409,743,944,24,788,155,55,332,928,250,682,9,833,482,140,314,71,11,146,480,682,376,317,37,428,384,811,846,524,29,47,980,797,430,455,322,845,446,911,683,998,547,982,99,627,745,228,97,809,979,648,35,548,217,103,264,991,172,272,819,638,351,898,187,357,393,534,948,64,319,677,830,927,319,74,720,397,496,732,763,671,72,664,652,937,36,3,763,106,197,453,601,35,923,617,694,230,500,379,62,661,343,875,924,678,46,41,135,156,806,426,26,197,205,775,285,475,692,293,125,237,253,905,281,93,448,289,973,341,705,261,980,617,421,324,362,307,403,387", +"588,124,190,684,689,288,434,98,390,301,678,828,52,816,225,958,824,113,306,172,818,978,305,708,855,2,356,734,162,858,854,587,672,598,698,633,744,702,946,119,210,155,947,981,497,643,616,684,134,324,956,879,734,173,496,318,919,845,202,706,453,722,317,985,275,47,966,635,239,810,958,154,135,752,857,966,931,55,784,685,980,810,414,722,447,312,612,25,317,465,704,835,193,127,591,91,76,48,452,340,904,38,16,739,745,831,901,461,242,166,182,92,236,122,870,569,426,719,459,312,0,723,393,838,654,968,431,402,678,605,56,110,64,492,615,27,187,135,42,207,8,848,785,751,838,49,179,504,884,110,481,559,697,740,69,146,130,54,469,978,282,845,96,847,216,844,30,398,196,35,576,494,833,368,541,463,585,480,636,243,925,821,452,663,618,973,320,446,900,198,290,56,379,363,901,928,604,741,633,982,691,968,410,997,381,160,85,882,521,603,630,860,381,2,233,885,242,352,518,315,688,992,604,590,5,859,493,328,467,596,815,274,265,326,154,360,675,577,727,661,471,176,775,952,142,597,885,576,492,517,424,218,694,110,439,565,791,212,856,654,710,793,38,533,959,716,483,478,235,123,21,668,200,636,134,300,756,929,884,185,701,903,60,626,803,811,841,280,382,621,399,5,922,866,725,880,712,22,108,424,221,412,591,59,857,792,885,858,629,318,488,706,426,29,105,273,665,691,259,413,37,969,333,958,946,370,394,2,448,781,709,871,179,195,356,859,293,348,448,323,325,259,645,545,255,716,746,631,216,304,947,727,304,869,263,63,671,238,259,133,589,268,964,831,822,189,479,913,935,2,537,29,708,783,628,140,23,426,924,885,350,816,380,52,60,566,765,626,405,135,211,453,659,853,654,431,607,679,597,770,828,760,626,861,77,659,667,41,194,14,905,932,856,997,677,37,140,922,677,890,171,636,475,757,596,156,33,950,617,349,227,338,2,278,89,916,931,728,51,532,741,87,856,893,850,993,924,3,993,860,743,440,225,462,431,369,155,846,651,246,614,435,148,929,176,951,366,176,572,504,747,132,354,359,794,52,897,339,921,566,735,47,72,336,14,178,358,805,576,188,48,188,928,861,973,579,727,183,834,815,954,236,200,298,873,198,587,750,11,973,209,553,848,565,609,858,210,823,578,636,247,123,213,911,629,21,275,890,214,19,217,555,672,123,752,107,138,426,934,696,584,56,220,568,868,283,739,154,430,343,337,964,998,111,889,305,901,694,446,509,207,574,758,389,415,503,403,377,681,849,826,864,637,936,642,559,79,632,819,400,722,733,612,716,274,608,359,240,389,392,410,700,82,662,255,745,99,492,70,612,645,585,270,255,769,870,520,139,259,808,656,663,699,915,524,252,899,479,400,556,982,499,303,199,548,645,887,655,508,483,103,590,693,66,30,255,716,774,677,190,519,419,180,3,740,342,79,695,315,203,866,685,348,998,637,704,462,425,56,441,461,873,803,449,633,826,757,156,208,588,781,528,683,40,699,153,483,446,378,370,779,641,718,636,936,424,103,925,336,608,754,682,936,142,770,722,227,701,479,363,44,811,799,256,391,346,493,55,364,991,680,700,418,844,737,676,981,771,28,786,745,732,16,86,900,936,998,507,493,221,927,409,725,870,659,611,111,891,161,352,227,706,157,181,716,26,551,576,865,888,331,839,185,698,138,505,125,895,171,185,7,426,108,78,766,834,109,242,944,88,514,25,489,4,794,336,286,420,467,88,303,117,985,717,159,503,402,975,473,800,354,376,389,617,363,642,917,571,631,899,445,373,887,166,96,820,50,263,185,433,277,616,651,159,222,910,928,185,121,356,253,631,619,592,917,453,609,194,846,550,821,305,206,215,292,968,503,985,638,989,63,161,965,816,411,476,584,596,77,418,891,918,890,502,226,740,571,210,827,707,101,828,166,992,467,353,658,493,872,822,979,152,579,966,323,341,196,140,235,718,210,135,384,8,846,584,164,375,446,312,207,317,546,382,85,202,827,142,667,864,899,639,809,129,714,103,699,332,730,732,152,179,770,956,134,828,526,285,768,409,80,572,306,621,260,158,111,549,400,467,127,672,353,754,827,24,397,60,405,126,941,226,39,889,687,276,680,477,46,820,842,924,255,964,469,777,616,692,380,122,537,709,638,721,50,474,202,327,250,919,598,748,812,523,286,785,774,463,371,133,417,251,951,24,216,735,707,639,517,251,447,906,940,869,300,23,163,74,517,560", +"87,719,881,790,677,987,865,161,842,431,553,645,952,160,150,922,800,969,133,337,424,814,918,664,342,372,211,858,227,617,738,663,191,567,262,363,702,707,953,462,805,380,37,544,80,244,256,279,606,801,229,364,723,825,669,999,591,710,442,85,376,477,630,414,955,848,667,749,354,794,238,596,330,158,429,637,887,218,202,330,278,715,204,420,276,9,181,995,432,983,643,697,878,331,828,656,62,528,246,257,208,274,448,888,739,670,346,641,201,827,973,357,695,158,199,584,379,562,600,597,723,0,297,730,890,770,180,605,699,195,299,301,38,756,516,733,610,432,590,883,318,471,770,820,952,545,418,663,525,399,490,972,261,605,106,913,457,675,97,236,594,116,700,208,959,178,144,167,393,638,964,890,248,915,746,971,441,876,11,218,770,410,850,386,502,938,263,92,413,271,179,252,656,230,650,913,609,136,618,970,904,792,80,622,722,257,906,434,625,858,71,363,615,437,461,953,941,119,618,70,139,64,844,537,729,538,852,14,531,489,518,635,179,941,5,217,150,250,819,957,693,333,423,209,385,375,820,310,770,851,409,102,743,535,611,958,330,59,75,99,614,547,660,225,577,487,247,820,372,682,687,207,583,378,44,744,287,78,543,983,170,138,265,486,381,485,107,324,655,589,744,294,163,689,910,919,338,387,21,613,926,297,412,116,516,481,947,220,78,619,226,56,693,555,570,673,158,350,568,775,154,476,789,946,437,204,465,329,706,334,100,930,488,223,534,204,843,31,888,789,691,455,721,895,741,248,546,307,88,572,69,336,951,638,432,773,299,664,146,204,104,405,243,652,866,350,466,416,590,317,652,646,288,422,84,780,609,237,177,992,583,959,416,994,630,112,657,807,894,945,76,362,600,787,842,847,793,816,940,890,278,625,811,64,450,279,936,223,229,201,7,305,674,765,791,42,945,439,466,346,733,285,310,232,959,270,260,392,863,206,754,991,468,157,828,546,370,801,635,82,50,735,411,133,653,412,931,814,447,991,87,907,41,132,503,45,836,691,439,528,796,750,702,844,853,36,253,699,367,483,316,655,647,764,882,933,768,775,776,975,721,863,141,677,484,725,470,127,471,773,531,512,546,587,699,561,195,845,261,594,617,85,105,592,948,723,948,643,13,313,362,656,107,35,58,975,87,872,101,344,38,346,98,589,34,917,450,837,334,166,461,80,357,948,611,930,778,116,484,984,737,776,567,22,525,237,102,210,370,521,169,504,141,932,327,194,49,94,164,833,529,810,822,983,95,727,304,707,146,167,48,733,411,48,863,438,802,315,657,6,243,430,556,644,285,184,813,438,17,561,491,832,983,898,947,862,947,404,592,339,787,526,854,836,11,621,405,61,301,151,531,355,328,153,465,466,684,847,261,453,531,572,110,546,932,497,682,381,689,990,359,67,381,665,668,970,793,937,884,780,542,445,222,175,547,509,130,693,394,845,411,555,565,936,590,857,981,999,377,365,814,202,244,507,289,668,372,927,809,571,301,106,742,691,785,629,370,39,100,413,816,685,318,642,237,294,434,384,66,742,185,256,510,934,178,390,177,317,639,24,731,537,733,845,923,714,228,111,103,843,529,986,13,278,384,171,177,89,284,70,720,253,282,466,652,434,422,359,128,813,286,664,150,175,687,992,661,300,609,497,161,826,538,336,522,62,510,695,523,589,342,585,636,610,602,742,240,100,61,814,472,541,394,65,833,214,764,793,302,868,131,478,973,331,611,29,850,296,894,92,157,718,617,975,913,473,881,102,916,67,880,138,390,625,237,634,935,334,827,298,403,516,812,157,582,829,650,881,402,595,844,64,2,623,68,783,699,160,154,203,484,598,634,423,811,661,202,125,865,368,886,663,9,466,250,958,132,889,242,726,323,296,346,666,327,50,134,567,470,282,717,908,115,716,383,679,645,773,54,768,158,345,524,145,381,494,739,905,967,870,874,394,960,947,543,272,849,553,86,333,674,324,43,269,846,266,840,231,6,41,19,82,490,160,851,253,890,304,182,133,216,158,41,430,397,678,235,950,675,8,226,338,408,212,238,271,77,650,392,394,89,914,433,235,807,944,789,382,442,969,933,859,724,244,505,562,71,48,670,129,78,892,748,834,242,957,273,424,368,777,709,318,61,443,337,764,187,32,370,565,475,823,557,630,822,864,132,879,662,798,11,322,285,479,839,270,10,483,28,173,430,336,485,443,252,177,73,365,490,791,55,648,175,528,198,644,139,141,838,262", +"109,555,447,475,393,558,975,612,589,961,703,421,506,609,547,438,383,362,576,815,474,474,288,236,277,612,153,543,431,681,383,328,493,167,332,712,713,778,811,297,254,962,423,83,938,891,134,183,246,623,834,363,188,940,414,24,32,947,676,929,659,588,920,959,520,2,122,279,602,526,811,911,507,390,295,573,399,37,637,703,645,225,484,84,306,853,94,376,456,909,147,760,528,880,100,370,624,589,758,896,302,383,74,61,311,682,17,290,502,862,956,574,841,840,372,600,408,779,223,977,393,297,0,984,986,109,878,308,384,926,192,425,187,55,993,393,374,862,550,241,372,922,641,301,468,440,844,72,577,847,938,547,10,406,868,329,223,919,991,90,733,16,694,119,651,436,817,257,639,173,831,885,51,938,303,626,936,942,233,522,425,327,491,916,238,671,977,976,785,274,451,785,240,691,939,501,905,101,698,96,402,359,730,291,622,392,783,189,27,771,12,528,681,115,726,728,936,841,476,41,339,143,464,619,699,604,359,878,370,406,211,287,661,521,553,463,363,326,128,895,200,68,347,164,947,379,784,23,857,712,395,579,720,340,514,214,23,880,645,261,333,707,64,175,234,325,20,927,82,164,266,564,851,54,681,2,535,468,573,861,709,709,981,794,123,781,704,869,240,893,687,447,897,120,893,419,168,280,582,749,519,880,382,670,618,347,933,275,342,840,544,425,687,958,804,182,176,366,787,747,76,903,934,31,737,56,208,398,618,961,926,394,911,876,851,772,684,504,690,972,996,633,736,991,491,780,654,259,161,456,345,369,700,608,694,829,165,538,665,515,618,853,333,399,665,108,399,964,989,108,469,793,454,256,483,635,185,577,1,780,314,333,738,691,424,821,537,263,414,556,860,347,517,769,375,500,845,694,293,871,531,191,382,176,746,801,105,716,163,820,291,360,334,778,890,716,141,584,745,996,831,48,387,678,670,232,455,700,668,303,227,728,16,927,68,599,551,996,858,468,713,917,983,999,686,264,249,105,87,361,914,494,554,802,931,634,84,581,160,896,103,293,16,113,250,277,980,550,462,823,86,840,799,714,669,890,636,366,702,440,50,951,807,8,830,751,793,816,681,44,335,640,919,579,944,765,89,224,764,322,346,566,216,538,100,835,118,167,303,657,670,975,805,540,104,422,893,844,32,464,105,257,192,137,471,663,708,496,803,187,581,49,265,966,73,406,535,502,136,429,899,394,700,677,982,840,156,769,216,216,725,389,474,693,100,417,970,731,272,107,476,756,21,35,784,189,446,316,970,135,779,104,647,443,813,624,552,779,985,264,17,831,318,283,169,99,334,136,322,970,980,146,827,94,337,202,343,955,254,212,470,28,73,356,533,331,785,479,689,524,366,511,27,555,285,708,400,459,796,631,627,60,392,666,364,862,914,529,32,559,774,712,435,584,917,965,97,713,674,938,969,972,894,829,77,724,517,436,337,541,356,126,166,540,351,578,810,896,214,567,362,200,636,356,7,512,421,213,91,704,890,99,475,640,999,201,492,743,830,328,134,955,854,70,220,329,45,481,917,389,674,465,426,492,530,313,857,133,912,846,680,417,872,499,811,390,674,497,952,951,78,746,501,300,168,358,345,386,893,631,413,740,15,655,534,21,92,164,887,903,933,892,550,608,730,30,928,54,923,855,244,278,662,609,318,236,111,118,706,829,275,395,562,809,497,51,82,278,104,49,796,334,751,616,495,793,96,473,522,355,340,620,183,494,873,585,927,882,446,269,195,683,698,802,78,961,531,426,623,778,400,616,789,711,840,948,256,477,496,980,89,806,32,777,717,322,660,640,487,628,791,633,133,965,811,947,107,496,23,334,133,62,416,568,681,103,282,822,921,616,355,33,60,205,657,993,934,289,181,352,135,302,674,566,787,212,126,821,752,480,313,248,28,181,168,173,159,117,738,433,96,92,606,894,12,197,993,203,765,793,926,159,492,575,132,687,648,169,183,100,165,950,352,55,900,910,301,425,527,797,805,384,256,295,893,430,793,747,252,483,458,468,349,385,61,628,801,146,874,230,961,686,701,22,583,30,148,995,80,120,573,842,368,679,81,538,290,737,446,100,80,184,36,141,733,472,606,170,296,679,689,921,791,5,732,991,321,165,512,710,920,481,770,292,278,650,918,996,894,596,632,121,723,210,399,429,26,118,250,919,827,282,758,491,630,542,93,229,943,360,519,683,586,929,662,252,282,33,55,226,553,172,649,723,993,404,353,583,643,280", +"473,154,530,48,767,590,997,366,332,245,270,60,658,225,619,864,176,489,436,560,34,243,22,756,978,111,743,945,233,82,193,258,975,307,135,745,805,893,33,646,580,718,766,625,995,93,286,459,403,257,673,408,809,300,71,584,778,883,163,659,954,432,798,751,18,564,267,427,803,213,705,854,471,648,427,314,544,66,276,857,722,58,251,185,952,623,721,585,387,333,560,916,800,761,516,845,864,534,650,774,533,66,761,31,236,316,599,651,352,772,741,269,854,487,646,387,185,743,840,269,838,730,984,0,820,71,615,595,871,917,404,610,181,698,794,213,924,499,125,967,222,858,255,284,569,88,423,611,237,35,622,210,741,204,564,677,514,945,65,949,687,108,926,184,889,458,617,596,812,187,606,992,903,95,511,926,151,854,834,288,732,770,810,400,110,583,777,133,502,752,715,494,435,492,237,25,910,736,420,7,802,145,788,97,965,75,559,886,348,159,836,802,626,146,650,55,593,727,148,623,12,156,518,753,958,489,7,819,31,836,642,499,768,368,703,185,6,457,382,648,954,921,379,818,846,206,469,283,868,424,778,397,240,765,830,865,168,319,311,245,348,548,478,447,813,631,629,412,887,494,408,618,338,246,584,118,258,657,749,259,489,281,991,146,488,931,316,353,28,671,727,58,414,620,238,662,560,955,351,874,344,579,121,26,413,697,723,676,676,169,940,549,907,416,567,207,917,294,18,510,719,424,32,676,256,453,993,230,800,787,209,377,36,241,926,609,579,623,108,322,601,524,854,872,466,579,950,192,405,915,579,282,100,350,543,140,835,205,479,188,614,443,927,19,760,988,217,92,23,432,361,284,668,126,643,716,967,667,655,612,328,936,606,63,386,49,50,238,609,577,521,938,921,982,973,674,483,566,58,973,587,396,111,556,237,403,545,765,649,172,240,569,592,968,955,481,869,375,774,790,620,795,658,941,805,41,425,541,317,893,735,843,603,869,920,884,912,633,308,52,460,894,731,718,738,571,146,182,866,160,748,708,119,14,644,306,99,264,98,973,175,690,968,7,39,906,921,316,227,413,184,799,550,311,491,23,667,469,227,910,128,861,413,907,827,701,733,558,162,729,69,66,516,974,362,937,8,779,312,898,622,594,188,430,158,159,140,681,952,948,953,159,640,244,808,490,673,506,351,565,6,566,142,972,640,876,471,541,876,471,687,680,766,895,896,684,21,936,204,443,53,115,411,771,996,340,423,216,806,29,76,565,37,688,731,361,224,594,290,531,776,370,533,705,772,927,873,963,458,118,122,939,691,613,537,668,841,483,593,639,231,335,796,816,367,324,928,85,950,168,655,416,837,898,187,782,980,724,167,619,44,676,202,484,751,10,508,952,683,633,904,56,675,923,858,599,70,297,961,109,865,569,979,989,347,987,451,955,749,855,450,367,44,934,37,741,518,238,9,355,415,557,264,829,193,78,984,360,442,903,593,967,230,713,620,38,856,809,837,643,660,391,765,762,427,962,32,621,897,973,382,749,290,997,833,448,823,643,321,290,906,919,584,963,247,507,309,365,517,712,520,579,640,258,816,599,488,43,683,296,294,796,774,917,525,781,110,172,753,533,240,939,753,766,979,329,125,618,642,334,718,469,295,381,342,798,750,665,536,433,633,681,56,361,626,478,931,459,276,203,994,316,171,793,203,733,556,517,674,508,170,960,677,314,155,378,189,394,946,339,245,420,590,355,982,961,786,836,451,779,976,16,754,171,865,207,327,348,673,756,458,769,908,226,205,674,473,275,726,684,451,3,310,449,968,245,583,106,439,818,149,825,336,927,168,195,415,340,406,772,751,525,892,938,289,944,342,450,207,355,155,334,915,121,298,599,284,726,984,224,281,495,879,270,810,882,459,557,231,766,469,668,265,818,51,29,920,823,845,373,273,221,518,452,262,825,389,954,180,647,46,987,184,852,805,884,37,470,885,44,587,643,783,500,279,418,716,50,863,239,792,989,158,983,26,721,186,545,222,668,262,471,974,638,571,233,993,63,39,956,767,585,593,404,285,429,795,38,605,347,866,113,333,245,732,283,398,783,33,601,635,210,467,282,960,611,79,161,391,608,708,721,767,765,386,730,686,559,856,457,590,976,183,278,101,64,594,253,938,122,236,608,201,999,297,332,550,785,251,357,739,363,150,694,878,973,144,444,264,337,253,645,711,875,307,933,816,102,392,335,133,381,168,297,915,135,519,640,649,129,400,302,561,55,886,937,925,483,101,665", +"66,264,458,839,8,853,6,943,80,778,455,617,506,428,820,471,913,124,121,18,894,653,68,535,960,950,702,661,863,534,523,236,262,42,385,39,780,600,260,396,759,84,88,335,168,65,153,105,87,410,1000,547,72,552,50,245,886,194,157,440,989,56,343,196,365,416,518,186,676,423,670,126,831,131,140,101,122,929,389,106,326,399,413,704,53,171,570,491,43,830,761,841,336,183,323,911,10,466,335,637,745,553,258,824,698,251,718,990,386,128,474,106,30,72,206,533,693,353,142,38,654,890,986,820,0,496,923,457,750,587,494,552,415,281,131,76,601,27,584,308,641,686,563,504,331,570,807,108,902,239,444,302,582,713,297,771,254,358,844,752,708,262,425,661,158,630,313,868,382,594,472,226,718,533,557,27,515,68,455,513,461,431,741,761,283,477,841,235,475,478,700,89,273,595,257,879,181,598,379,927,12,577,718,78,275,950,983,18,246,553,966,612,237,105,639,926,901,480,740,697,18,985,627,934,971,339,672,768,104,388,179,155,437,784,362,384,502,764,762,316,786,982,142,162,41,258,233,468,300,326,208,893,74,815,536,562,452,876,626,853,188,98,924,923,981,187,247,403,408,933,780,706,532,628,48,66,368,982,745,154,512,346,907,120,577,436,806,765,71,100,526,540,50,757,752,410,570,820,61,21,498,766,773,386,514,32,728,4,67,3,743,103,268,132,714,554,48,856,120,422,509,483,843,763,68,957,735,545,153,820,257,769,774,693,41,863,261,57,956,641,892,722,106,878,484,948,594,132,177,832,109,37,312,402,480,696,858,958,559,515,673,422,77,22,541,24,407,226,902,498,628,630,308,365,925,668,643,870,383,745,477,146,754,97,641,751,199,675,491,277,515,94,214,119,648,291,647,308,573,461,904,724,959,608,450,973,7,300,998,959,281,610,348,272,534,918,385,350,618,976,333,303,941,160,418,241,857,877,258,428,626,859,795,681,700,247,108,223,822,943,831,667,915,102,425,756,480,981,522,275,73,861,195,434,911,415,194,24,816,875,145,309,148,292,270,33,744,234,437,184,759,555,573,628,575,237,73,697,42,220,565,397,215,40,270,922,367,737,430,848,486,528,941,739,726,864,271,246,417,315,307,230,783,48,589,844,294,592,540,954,566,163,190,416,860,181,969,588,678,675,95,289,866,686,193,265,763,669,885,859,305,319,553,991,59,544,492,117,665,107,356,833,211,956,472,635,132,579,934,944,689,972,633,84,16,489,808,950,951,429,699,497,36,708,35,323,549,640,730,251,497,208,994,753,689,103,5,247,751,291,602,493,477,586,822,415,29,972,651,150,989,528,967,761,789,174,972,421,165,485,269,114,751,2,625,495,725,870,685,581,553,182,110,565,140,992,566,738,880,213,946,578,343,502,538,578,380,401,244,387,765,771,993,681,37,914,80,1000,548,730,766,940,362,9,20,362,166,652,706,72,362,671,792,499,260,406,589,522,658,407,475,9,338,546,759,519,60,935,312,48,721,329,896,671,324,111,557,341,651,596,693,383,181,735,232,942,23,491,420,269,367,272,596,559,698,737,131,506,71,771,131,890,557,472,196,609,974,582,748,155,710,69,956,972,840,962,325,748,781,244,451,941,329,856,519,694,363,427,356,331,200,710,870,895,473,671,107,449,955,88,837,542,591,504,817,762,188,614,381,377,809,270,503,807,332,933,764,513,926,435,845,373,566,13,522,649,883,686,42,464,98,118,913,598,704,890,924,838,887,766,340,524,542,755,940,142,432,695,733,588,924,827,477,171,625,313,861,832,988,378,617,529,108,254,440,609,624,24,956,526,589,85,554,442,62,14,271,440,548,774,481,91,143,177,271,614,758,844,129,296,107,539,258,570,246,173,908,111,742,309,601,120,379,57,883,346,565,870,283,359,603,844,168,871,819,471,315,315,317,857,369,230,711,779,414,164,650,201,357,378,654,472,712,493,365,910,330,594,329,194,675,336,537,214,748,794,636,698,982,766,931,227,872,528,682,30,669,428,141,699,682,711,488,499,246,741,919,702,518,421,470,708,234,881,500,918,833,939,486,182,187,602,905,915,90,706,280,614,274,41,617,232,608,650,529,832,314,945,660,244,982,824,49,839,34,135,246,810,619,472,428,729,511,393,963,521,16,378,197,327,937,759,501,695,635,215,257,523,907,827,515,372,652,910,373,162,443,23,540,565,673,796,329,104,849,579,267,232,686,593,370,848,260,626,753,959,634,925,383,741", +"965,486,382,592,904,878,484,400,446,830,894,643,736,208,705,318,630,794,85,175,637,979,526,434,916,837,658,111,595,286,879,328,485,810,23,94,289,15,577,812,791,406,400,423,764,314,300,226,782,506,519,884,896,167,652,895,204,737,722,155,346,8,492,538,803,123,546,250,250,669,228,476,242,809,718,900,653,995,409,277,65,499,999,221,490,317,928,481,974,101,639,691,635,238,166,475,438,224,626,763,66,423,206,327,452,846,962,579,906,882,423,82,983,499,769,868,517,546,263,42,968,770,109,71,496,0,188,882,148,202,857,516,659,943,349,928,944,876,69,211,210,949,64,127,117,701,289,364,164,257,423,309,899,608,525,462,571,892,909,153,933,50,639,518,299,564,957,511,775,769,915,10,230,810,227,358,5,289,670,590,171,301,885,50,794,639,505,956,980,212,932,628,64,876,270,111,733,58,27,854,781,532,994,727,984,641,953,826,7,391,331,221,908,230,515,100,159,443,207,745,535,747,415,467,186,940,799,234,667,947,154,400,891,664,266,717,631,490,826,423,814,298,115,181,804,149,251,938,92,25,41,897,795,945,919,789,283,484,568,848,446,431,723,812,150,646,673,589,760,248,200,653,690,958,131,404,406,113,327,204,472,847,668,503,992,682,609,349,432,665,649,18,17,68,936,778,164,633,384,851,743,937,263,356,228,668,900,55,757,881,419,422,789,408,344,328,330,577,896,850,774,423,927,644,201,946,436,328,305,627,664,721,855,143,819,720,469,808,673,773,864,90,170,485,241,10,528,735,72,330,87,560,812,345,334,889,831,396,972,211,933,813,530,168,741,646,296,260,160,107,187,707,67,390,265,458,310,384,183,137,670,246,658,663,602,83,120,367,324,686,145,994,336,653,412,376,51,860,410,540,54,172,368,661,634,590,820,453,344,160,646,402,144,950,899,627,91,263,686,893,665,6,261,19,312,428,703,803,666,546,312,490,368,591,577,458,129,598,127,846,977,55,684,687,47,917,450,141,430,365,402,424,288,739,579,517,162,987,559,199,780,582,783,480,951,642,884,626,624,449,690,289,895,707,320,74,646,540,736,645,50,76,155,646,6,976,635,962,787,717,669,308,933,451,212,764,110,350,605,759,927,507,148,706,267,790,189,618,307,644,604,788,3,518,149,799,358,855,765,867,909,557,115,730,559,804,372,650,478,287,547,297,360,491,910,916,439,630,699,99,664,487,88,273,241,692,798,416,604,518,865,193,202,852,883,442,885,823,799,371,442,626,289,286,182,522,209,235,778,281,852,425,980,848,734,323,411,444,11,661,613,411,926,147,987,206,805,698,807,60,545,599,921,469,530,955,616,545,284,10,602,820,894,921,947,510,948,341,886,556,803,882,366,774,164,174,405,663,966,263,263,139,930,200,21,339,87,95,444,84,835,626,155,671,840,963,300,849,943,59,617,863,594,369,319,506,294,383,401,277,265,680,911,913,556,168,348,39,282,647,496,318,225,475,63,840,764,156,783,167,89,749,925,945,75,16,653,622,791,723,949,445,960,34,168,822,231,42,54,163,413,780,77,358,486,486,391,606,420,623,379,735,920,153,587,826,523,404,802,32,685,515,727,656,21,398,613,232,623,56,22,903,231,618,147,499,144,136,842,181,637,35,304,918,890,75,184,728,683,754,512,997,920,96,855,75,962,885,730,812,817,798,290,400,920,589,213,11,384,116,395,210,154,735,758,781,705,3,219,590,102,761,543,474,922,172,702,661,569,179,167,363,402,28,191,864,80,491,888,963,925,683,569,713,843,944,382,205,173,553,112,915,905,688,620,949,980,814,563,888,538,57,99,592,412,519,120,706,217,371,366,237,631,296,665,696,939,769,346,524,225,899,230,83,945,354,918,614,246,959,952,670,501,721,652,643,683,8,838,419,950,247,653,852,388,385,108,250,347,500,550,366,576,937,733,856,95,352,506,152,44,194,131,129,434,992,689,357,460,171,8,214,229,231,510,842,984,163,468,960,395,556,468,606,978,316,509,634,27,803,988,369,672,350,358,623,339,490,99,56,727,959,666,124,451,352,823,984,998,844,653,426,395,614,397,114,319,633,903,721,313,295,922,545,129,506,262,199,497,707,831,553,598,357,538,260,256,448,389,513,330,435,835,65,38,149,124,238,173,192,128,466,796,581,74,537,61,384,577,552,916,707,491,610,437,758,881,625,152,602,195,966,257,16,797,299,379,830,906,41,483,204,569,340,654,779,237,978,292,90", +"973,643,466,379,387,812,873,117,572,396,302,832,465,796,884,771,806,684,1000,173,605,263,533,794,283,566,432,486,353,183,350,991,958,306,718,701,988,228,802,944,370,524,867,636,656,731,546,422,754,310,894,164,447,83,776,739,484,680,949,281,859,245,957,556,861,103,563,216,62,994,714,11,905,519,152,104,990,123,570,883,37,384,953,429,554,12,195,95,629,987,63,315,871,600,448,459,780,599,62,547,746,42,455,195,747,960,884,564,612,161,392,916,56,655,275,299,181,274,315,77,431,180,878,615,923,188,0,673,46,622,240,176,919,904,570,481,732,645,523,543,208,104,978,565,903,847,288,641,129,580,47,781,15,577,98,421,229,464,942,612,229,784,319,992,163,242,874,248,193,242,810,247,578,795,214,789,426,946,186,616,651,605,524,796,285,61,44,138,229,636,897,574,794,178,560,574,89,114,629,494,927,823,314,48,746,717,843,604,737,489,96,674,940,979,913,839,631,248,939,220,146,569,936,849,139,252,912,645,449,856,750,801,356,761,487,411,178,897,263,884,954,430,868,237,254,43,150,189,893,676,426,657,997,601,63,523,575,438,445,429,142,421,904,865,54,772,767,38,838,977,328,812,139,108,284,803,469,589,132,675,324,501,152,911,707,567,286,531,833,805,155,117,259,459,624,166,671,3,106,35,88,89,277,97,505,286,480,181,338,469,738,145,356,438,267,811,989,612,888,933,716,996,117,867,822,816,609,67,52,122,839,880,8,707,471,723,174,373,232,666,597,532,152,838,881,875,289,86,521,923,145,599,200,275,743,270,833,58,496,790,483,814,741,216,62,755,918,207,600,616,771,867,307,130,830,441,377,177,765,781,473,167,935,503,953,470,166,316,510,304,549,965,267,684,93,44,432,545,57,228,193,830,48,893,252,76,134,255,463,175,203,816,701,398,728,754,243,52,569,764,81,291,714,24,51,786,496,228,708,50,32,8,157,278,720,377,378,169,859,619,905,214,166,479,61,995,865,166,624,11,334,154,295,45,152,158,1000,671,263,478,452,13,797,876,308,542,672,601,152,853,953,403,63,451,217,897,100,612,810,192,250,290,187,793,505,288,9,975,715,700,268,310,80,209,990,783,598,232,422,96,19,575,829,283,174,214,297,662,712,957,904,936,338,345,238,450,583,647,44,160,165,542,54,138,950,342,838,839,952,925,62,291,539,980,399,433,785,983,208,45,360,742,32,500,474,932,354,20,924,167,813,109,353,120,101,900,430,485,177,430,50,672,636,781,469,858,582,796,869,818,912,803,626,417,156,734,860,305,783,111,929,652,844,922,46,795,248,413,719,114,892,471,107,709,81,906,440,417,595,998,496,275,802,756,213,375,437,699,123,929,821,740,738,237,412,411,752,422,114,361,499,64,541,618,409,159,990,37,780,349,418,173,282,581,412,429,296,373,873,757,911,778,705,173,228,156,931,269,359,303,94,12,853,690,948,870,361,220,400,62,658,732,7,504,330,354,176,811,53,821,447,315,841,980,329,163,986,101,509,167,94,898,237,353,541,985,691,803,480,154,41,841,813,121,619,690,901,327,652,802,69,158,863,929,431,439,953,375,856,790,432,889,51,281,743,272,592,532,266,879,285,431,654,819,984,782,389,319,173,336,383,72,334,657,598,182,997,673,458,50,528,112,945,971,232,75,383,367,754,270,716,294,73,104,631,406,68,196,779,286,228,372,585,288,122,164,826,328,793,66,530,469,491,2,658,737,693,664,156,443,336,143,502,18,13,554,809,237,929,667,920,873,44,535,509,119,143,121,364,288,127,524,810,232,668,878,290,522,224,642,200,230,420,658,570,980,152,314,455,395,123,876,500,985,781,754,419,72,231,493,364,599,83,298,536,212,25,415,167,412,151,726,601,425,252,988,139,718,638,308,339,919,929,868,245,746,988,747,806,520,37,820,219,823,53,654,502,832,453,158,593,726,822,117,496,706,29,418,104,882,82,550,90,436,94,545,914,982,537,240,773,125,281,790,906,793,440,167,866,596,279,683,281,80,14,739,47,296,530,298,928,304,156,3,22,536,228,983,937,497,853,387,686,629,675,859,236,252,509,164,9,389,166,645,219,325,868,662,259,500,747,852,666,121,304,697,918,255,797,750,387,244,577,387,423,183,613,567,893,103,761,867,654,709,925,576,414,42,983,842,505,666,965,105,105,976,287,725,662,155,501,530,722,598,424,159,829,45,937,957,302,39,794,441,613,101,730,311,366,735", +"950,437,65,950,965,337,206,683,19,406,697,489,73,654,841,14,788,376,477,602,184,732,934,929,517,659,64,209,53,396,895,407,683,720,503,698,740,458,76,339,965,90,422,969,54,612,78,140,184,232,195,152,560,102,781,641,677,289,623,849,269,347,707,593,240,955,401,397,252,947,442,181,866,209,763,888,302,185,620,39,686,883,372,307,460,502,712,255,652,999,46,676,241,919,137,487,2,96,874,976,527,539,809,171,342,979,850,710,573,345,501,476,244,605,364,377,863,952,93,513,402,605,308,595,457,882,673,0,668,449,456,198,853,327,505,808,227,164,468,273,931,342,625,285,616,668,9,595,209,470,701,915,234,747,74,649,839,414,913,814,331,518,162,931,854,853,7,661,6,199,269,628,269,174,481,429,962,549,821,916,309,857,341,305,937,231,948,276,84,161,309,620,94,129,725,161,419,210,787,753,609,681,691,199,186,220,466,544,242,256,709,220,676,416,905,47,62,72,838,724,743,434,930,355,584,553,277,95,738,828,322,977,552,285,495,815,987,586,606,751,635,115,822,915,791,984,713,469,72,269,740,611,588,724,19,798,251,641,219,170,17,130,467,797,497,909,70,262,139,976,767,833,744,778,894,496,870,393,826,324,824,623,666,18,393,100,459,198,103,620,765,891,799,419,456,566,602,664,334,611,82,450,583,312,497,719,602,462,480,714,767,135,596,23,109,255,2,893,113,294,500,967,640,867,470,101,439,947,604,27,998,356,941,129,14,259,68,444,656,241,829,919,679,382,34,904,934,332,117,275,837,249,534,51,109,208,572,454,298,576,293,413,492,500,210,762,782,460,67,485,337,977,426,442,385,5,833,834,119,102,408,124,28,948,601,158,711,382,853,802,259,433,368,478,287,933,109,450,438,636,159,461,554,703,813,819,533,670,716,145,467,406,927,889,641,230,817,355,110,901,871,193,346,5,716,856,107,55,83,941,344,438,148,59,282,366,130,983,906,182,799,729,15,880,650,106,396,179,185,829,126,708,437,397,151,151,664,847,220,96,913,267,949,9,59,790,482,193,104,72,456,796,152,872,712,280,685,194,911,418,699,535,309,36,536,250,77,521,263,85,671,458,949,945,914,219,662,274,340,851,18,429,950,26,533,295,712,527,559,138,636,768,508,642,760,60,194,912,135,104,662,613,935,793,21,563,325,996,38,413,15,624,788,598,58,971,50,792,942,463,700,945,987,628,324,7,202,63,457,173,563,939,459,561,263,155,803,338,715,10,627,771,11,846,377,235,501,689,16,522,249,10,902,172,836,874,613,273,662,38,950,168,942,329,340,321,47,513,15,673,216,767,293,64,212,27,312,260,348,978,944,718,599,779,334,330,272,513,651,251,605,282,781,960,181,978,129,435,568,436,886,958,60,268,304,560,202,532,151,97,962,539,320,866,673,346,43,488,115,177,896,598,196,902,719,261,642,580,52,168,762,807,362,103,442,547,47,543,472,423,492,298,610,429,122,463,360,749,887,910,33,314,927,404,873,4,905,965,945,401,336,229,337,181,259,329,65,59,977,728,334,58,123,883,409,847,462,343,453,128,892,19,483,718,470,60,936,414,543,509,898,70,284,345,395,280,923,901,339,323,338,875,972,736,974,41,757,275,761,884,136,473,427,620,340,565,815,502,325,113,387,342,519,460,481,30,2,151,89,929,597,86,449,455,274,26,399,785,303,182,703,99,131,784,332,108,62,140,467,883,161,222,902,574,83,332,834,427,241,222,513,559,871,351,526,430,562,615,713,364,856,981,778,115,407,145,690,759,892,559,916,469,101,875,253,952,444,327,407,669,313,361,954,706,429,680,88,124,467,498,629,183,809,270,699,60,478,17,874,33,73,689,25,973,168,127,199,193,729,365,651,220,6,487,63,909,720,222,224,944,143,247,432,457,700,147,412,682,466,548,622,947,302,419,24,299,641,922,733,714,175,327,806,662,63,68,119,367,143,861,915,367,73,162,316,782,534,509,743,631,993,207,843,440,536,473,120,925,720,684,486,691,627,239,899,353,138,475,96,694,691,354,874,542,609,180,777,100,192,909,105,674,266,635,745,189,555,259,151,389,965,126,911,560,326,862,457,109,728,866,578,361,458,794,872,69,428,856,393,479,865,61,589,989,170,153,523,544,233,761,35,227,464,788,717,273,591,159,810,220,4,835,965,514,268,590,220,938,279,994,304,11,72,963,609,633,669,884,607,139,171,54,619,833,919,215,135,473,712,233", +"952,828,16,990,540,210,860,948,331,618,499,455,739,70,302,724,267,808,79,66,616,864,201,188,545,23,251,496,908,404,550,19,395,862,671,464,714,223,176,6,916,82,458,945,18,946,996,800,906,569,648,363,117,234,804,503,123,655,425,927,978,926,194,310,133,907,291,365,832,977,13,115,736,440,75,790,450,976,522,510,906,551,757,677,187,355,471,202,105,79,981,17,462,682,130,885,571,830,638,338,775,797,448,986,375,189,403,252,908,527,610,556,560,493,912,929,170,546,953,358,678,699,384,871,750,148,46,668,0,158,337,173,601,624,124,539,513,133,320,77,748,916,520,56,465,905,124,842,97,221,369,151,316,4,371,616,765,236,376,559,115,508,925,135,774,885,266,644,648,299,977,805,454,553,243,671,25,892,862,757,817,629,932,248,62,206,265,800,233,996,765,140,301,90,950,246,88,112,836,883,128,709,699,787,244,92,41,624,536,359,244,440,893,562,857,708,20,459,290,153,642,533,223,951,795,464,817,345,25,952,894,295,811,662,333,819,76,543,95,741,844,845,163,123,662,448,457,439,226,188,267,339,227,379,18,232,886,940,814,433,847,225,812,896,353,881,755,482,483,278,273,350,180,311,206,536,765,181,371,820,961,168,770,571,204,707,396,146,26,364,546,642,291,590,629,390,77,452,656,267,572,682,262,48,839,288,920,536,284,107,757,582,115,661,638,924,591,432,629,277,237,590,181,948,603,851,57,547,866,492,990,591,371,230,768,399,212,319,369,934,954,859,948,371,824,922,527,382,218,401,425,751,953,673,36,659,30,779,357,104,930,278,246,200,423,413,681,583,689,18,776,176,891,664,449,782,193,741,251,655,345,52,102,881,606,344,901,741,297,778,555,822,246,9,970,446,614,778,750,503,87,246,467,242,644,543,686,341,480,983,51,840,628,956,845,510,257,915,22,640,255,279,749,248,712,90,711,514,174,237,259,774,923,38,687,25,213,619,652,701,973,126,714,995,54,328,815,6,714,851,382,266,430,221,737,75,942,398,658,993,261,388,579,798,557,934,73,26,937,38,9,214,360,55,443,801,558,875,702,483,716,350,684,800,370,348,601,219,386,393,12,196,542,655,503,84,657,634,731,675,547,568,260,171,12,72,967,935,788,528,755,724,274,677,49,859,516,611,758,604,836,811,601,728,954,606,121,412,375,629,82,782,533,97,708,32,345,758,697,310,686,746,361,98,139,85,527,655,212,160,609,227,889,541,657,678,316,413,501,282,660,566,942,864,868,834,272,211,152,945,402,102,221,249,477,659,415,82,455,48,217,531,962,403,650,689,685,475,287,662,171,421,899,474,633,373,545,317,994,484,554,12,821,651,569,288,262,255,577,550,387,795,970,189,512,739,747,352,721,459,8,413,372,292,90,180,969,677,371,973,636,421,385,188,501,104,531,979,111,319,115,379,833,754,910,500,621,228,615,175,204,176,914,377,727,628,952,507,3,404,461,55,72,836,946,939,732,367,151,456,375,600,701,829,63,901,856,244,831,65,761,750,802,239,772,913,279,605,718,768,999,483,875,569,664,260,387,552,293,501,306,681,738,956,978,451,697,617,898,495,584,258,664,292,389,358,766,742,189,345,20,207,67,894,633,735,494,150,383,588,359,776,814,947,747,148,996,665,398,276,287,270,173,881,908,165,876,283,421,216,541,95,575,113,309,902,995,124,891,223,426,600,989,205,804,491,193,48,466,11,977,82,458,253,240,935,966,316,675,643,949,48,307,853,171,397,141,609,730,617,222,135,569,240,560,662,366,54,290,912,997,101,84,359,991,576,341,971,534,876,72,517,84,272,824,947,879,477,548,548,604,746,515,489,629,129,519,562,441,954,962,632,86,311,674,682,426,916,194,919,329,877,652,133,612,181,654,943,527,833,31,698,273,655,689,635,313,560,519,677,374,519,703,416,119,176,954,728,498,338,122,475,25,559,387,342,432,883,842,74,450,79,312,629,306,262,415,22,763,529,356,517,944,718,162,310,978,829,671,323,909,99,458,896,572,665,713,119,436,421,976,411,258,663,880,813,68,706,555,591,136,950,456,920,685,499,637,562,962,836,142,870,476,165,401,854,908,158,309,258,800,554,214,856,918,247,531,960,258,688,967,316,77,774,655,396,604,148,766,484,180,928,81,958,476,584,326,311,100,945,384,611,418,448,107,75,149,43,961,288,202,866,86,585,7,16,155,649,107,687,377,412,67,64,959,49,509,959,313,103", +"492,729,85,980,463,805,36,673,830,552,126,24,56,363,64,71,26,848,861,193,844,214,466,760,291,679,741,426,645,986,279,514,507,97,562,121,88,735,417,665,684,832,686,865,108,72,117,934,604,213,694,644,172,572,494,469,15,466,479,539,470,80,475,321,74,745,993,393,979,485,590,749,810,874,227,456,827,19,321,238,973,601,982,593,840,690,697,438,532,324,298,830,731,254,777,690,268,866,383,595,389,358,598,36,839,62,279,37,36,975,286,793,164,691,771,278,443,371,535,508,605,195,926,917,587,202,622,449,158,0,13,146,288,260,842,352,144,636,590,893,654,669,967,99,851,342,578,178,628,81,484,353,972,451,695,557,250,962,228,222,161,115,812,288,467,414,65,815,470,739,834,894,627,929,588,74,559,881,227,739,163,849,609,825,343,733,585,489,916,101,344,899,159,210,976,482,574,233,865,149,330,257,659,510,262,222,203,594,96,776,100,405,397,861,480,342,41,177,995,42,676,68,413,856,814,522,745,835,394,416,986,685,753,828,375,991,153,776,972,424,512,247,642,277,341,116,24,789,240,963,319,273,560,942,502,181,568,189,5,815,430,192,224,182,617,204,10,560,885,758,833,848,774,885,15,76,630,92,963,850,356,100,939,506,699,426,304,167,907,213,650,23,969,757,330,434,596,830,389,173,27,482,394,684,363,875,835,326,113,855,840,692,2,844,299,640,532,834,296,54,106,906,899,434,429,521,374,810,474,239,226,574,463,892,844,743,251,927,592,660,883,560,115,926,943,748,925,922,508,26,413,389,867,12,536,561,29,266,605,656,941,842,751,264,500,820,106,325,959,9,706,432,16,583,795,827,575,561,351,467,5,121,477,355,635,540,326,340,865,809,530,480,743,490,383,600,447,984,604,129,717,243,695,14,889,392,804,663,795,156,877,675,777,649,98,460,418,305,83,686,238,647,679,664,226,869,839,159,419,585,812,525,221,141,186,230,288,304,784,751,322,810,679,27,952,368,336,764,768,66,413,191,501,390,757,132,895,914,941,130,737,123,112,648,629,817,191,458,378,110,98,255,452,744,364,153,598,93,353,184,677,397,845,891,581,169,647,646,173,238,282,331,740,310,22,453,826,35,51,583,32,622,684,155,372,699,42,150,795,556,206,935,317,879,935,640,188,44,49,205,113,266,957,63,32,444,928,17,286,845,980,788,239,325,134,331,702,144,198,134,410,690,104,641,533,354,46,614,81,756,254,208,771,44,949,532,235,228,700,853,721,698,468,150,477,19,249,730,734,744,271,266,754,568,121,896,435,121,446,283,833,599,448,273,375,343,233,807,317,33,350,90,222,731,265,900,852,140,937,842,629,826,151,642,940,479,912,801,444,838,779,829,721,678,897,631,60,217,823,253,716,519,178,180,325,388,33,915,359,793,899,204,398,222,306,948,229,81,753,61,423,401,748,43,194,389,530,702,28,90,330,537,285,570,783,119,546,547,758,844,547,604,470,274,434,967,744,86,155,783,635,111,847,386,12,186,646,183,190,888,784,38,696,303,940,513,589,791,681,916,154,955,308,751,192,834,282,622,993,967,152,14,919,184,165,303,521,170,617,175,500,93,67,405,603,417,49,692,140,75,403,878,950,555,399,466,699,532,859,991,474,893,819,203,844,40,661,114,444,321,898,1000,544,234,131,478,119,524,600,584,94,639,354,161,657,16,933,899,426,958,349,358,512,40,984,652,673,785,572,696,49,993,531,925,570,679,632,384,338,606,809,519,69,844,778,672,316,729,634,901,807,42,139,715,788,380,857,781,455,853,316,812,695,515,122,179,757,338,241,494,342,349,476,584,156,446,142,798,667,830,286,430,725,920,767,369,790,633,270,589,496,195,306,989,881,242,271,361,459,946,963,503,985,429,19,916,974,929,497,333,97,982,319,493,424,75,988,905,594,808,774,720,247,3,813,137,908,652,699,714,393,757,701,44,554,534,962,330,402,598,115,208,561,16,870,614,174,417,882,623,853,925,767,467,415,232,799,720,279,478,58,960,142,942,59,451,708,329,589,303,688,53,771,168,482,622,510,892,792,999,206,740,125,366,571,763,252,582,192,521,935,929,725,154,119,136,520,731,300,746,382,572,965,68,622,372,940,760,365,392,369,679,193,84,399,708,332,958,785,738,255,485,687,6,559,597,366,356,866,726,577,185,996,570,951,555,475,182,156,912,408,187,638,531,31,768,885,871,753,345,638,586,856,892,307,487,612,530,805,641", +"624,571,21,716,362,262,171,784,440,777,746,754,52,657,47,932,608,527,968,368,769,950,52,676,856,344,105,686,710,517,448,730,85,952,45,611,928,211,725,240,499,16,588,187,515,363,304,827,751,115,439,879,75,23,628,160,6,716,669,547,738,734,680,361,51,929,535,108,322,883,889,811,667,521,912,590,832,405,197,516,31,706,354,506,849,561,55,433,479,44,463,722,636,11,403,564,41,233,431,170,528,469,238,744,784,819,379,835,801,659,866,697,300,106,859,591,486,160,498,510,56,299,192,404,494,857,240,456,337,13,0,980,246,430,524,61,345,710,992,762,667,181,65,117,239,768,964,297,649,838,340,572,122,939,84,232,807,368,162,602,512,336,37,422,585,896,410,562,153,696,205,341,827,15,690,698,189,419,65,210,704,677,102,655,909,187,128,438,255,569,929,928,93,965,543,262,587,331,814,365,607,110,80,271,182,723,845,635,62,25,853,997,710,73,114,701,779,360,149,839,613,298,386,425,369,67,475,739,794,330,627,49,173,780,726,654,688,157,969,150,833,804,556,851,202,709,521,639,866,556,616,835,70,282,609,988,44,207,201,126,519,874,116,947,78,999,367,985,733,432,102,170,303,36,899,328,633,374,427,89,686,224,315,215,944,269,818,384,19,179,236,750,938,102,569,304,185,31,290,275,260,345,906,368,983,784,629,318,937,976,449,649,605,110,869,369,513,591,290,889,640,512,759,946,211,92,329,216,148,886,862,87,353,456,599,621,220,705,161,403,782,238,178,950,610,144,797,980,384,406,470,299,115,857,770,758,31,511,775,152,294,219,579,872,981,91,27,899,923,118,87,259,355,824,994,360,235,997,824,377,65,374,755,486,731,213,511,522,913,118,966,138,573,246,747,504,899,164,270,241,100,624,296,307,942,106,552,513,753,910,100,810,584,987,885,88,87,301,479,818,78,551,978,318,435,401,959,535,129,419,640,80,981,810,665,215,330,457,86,609,549,491,677,271,725,937,279,709,55,377,416,738,345,919,390,37,929,26,209,229,435,292,50,929,694,418,11,664,699,651,805,720,787,846,279,82,595,197,688,766,864,294,946,436,978,503,223,504,819,202,376,285,136,880,145,703,518,1,74,5,150,343,234,613,964,819,528,376,584,387,444,56,593,216,660,890,845,605,513,915,4,308,916,787,246,976,2,201,359,259,961,378,436,836,247,461,580,455,59,116,864,138,275,159,325,705,594,698,364,385,142,799,349,263,457,827,501,48,501,221,383,581,853,197,872,395,653,838,806,190,322,406,169,578,346,343,340,503,348,672,64,296,818,340,961,630,547,922,725,722,966,92,329,545,239,46,775,774,998,238,822,943,602,500,821,493,245,263,462,471,971,295,335,548,779,920,11,467,262,170,23,26,302,821,142,792,284,510,447,903,928,790,918,761,376,592,325,967,856,778,616,172,421,900,48,691,903,219,498,334,213,921,628,592,257,739,781,226,508,460,849,933,234,326,922,588,666,228,433,905,357,1,927,724,960,281,280,834,644,24,417,48,455,407,221,419,74,547,921,391,939,326,640,736,453,976,941,406,814,290,186,171,282,617,833,810,215,481,369,104,59,924,823,601,491,405,246,320,156,301,55,583,6,480,563,288,773,862,160,369,364,851,269,254,549,744,438,948,986,979,505,609,930,427,841,472,442,168,835,43,316,859,520,150,838,92,37,805,314,592,734,357,610,339,410,284,624,904,85,263,644,792,478,832,981,799,305,6,671,860,655,991,774,695,889,180,362,230,239,831,809,572,344,771,297,951,381,377,215,361,852,892,389,477,494,304,781,757,432,442,134,296,320,501,983,304,768,551,856,450,664,99,785,748,3,725,483,555,347,176,90,584,973,840,701,913,260,761,907,404,968,382,461,498,780,570,97,788,421,136,329,839,468,645,945,473,244,895,746,660,941,446,867,997,263,512,468,588,808,835,435,233,308,984,854,791,496,76,662,137,637,882,520,968,425,482,616,713,248,858,318,712,411,829,432,801,748,814,684,150,394,994,268,530,980,268,194,158,411,343,272,459,693,808,400,956,685,239,189,885,759,995,410,907,90,891,947,349,516,562,598,90,689,233,610,593,913,125,688,784,957,296,952,951,140,721,340,341,889,855,881,418,741,772,765,990,293,548,758,667,390,481,679,100,435,144,643,552,487,235,89,816,178,241,569,570,635,691,861,879,23,603,111,444,509,867,951,635,511,950,564,14,632,230,533,296,86,404,495,808", +"810,950,223,332,112,360,814,636,585,542,585,444,258,29,376,259,719,102,54,223,503,763,814,505,770,654,54,140,241,112,194,871,477,543,712,694,493,401,730,906,760,679,502,890,153,993,54,590,336,760,448,307,350,285,856,448,986,767,902,255,815,78,990,985,872,297,876,219,16,825,931,482,822,937,275,945,159,169,755,839,31,37,706,372,356,125,926,642,197,38,24,918,777,112,14,841,91,594,294,57,165,925,507,724,641,128,730,334,153,568,775,565,750,661,85,566,90,283,515,497,110,301,425,610,552,516,176,198,173,146,980,0,600,714,530,944,641,687,502,725,140,31,842,557,928,211,112,379,169,714,459,803,919,840,240,945,894,972,668,579,28,233,889,151,412,207,470,216,105,31,972,755,823,82,34,816,536,896,395,844,955,154,42,432,318,759,240,411,132,197,821,255,172,736,192,145,212,796,457,336,772,678,620,556,50,621,883,595,816,396,176,935,993,138,880,613,331,197,582,798,165,737,607,778,686,730,972,719,258,10,893,417,136,841,505,397,918,270,381,425,63,217,260,838,925,923,439,435,538,72,858,379,461,351,522,905,719,967,773,821,839,598,144,981,425,815,93,740,297,876,608,160,331,971,657,247,362,889,416,393,742,356,256,351,921,965,100,769,969,71,373,696,632,825,163,163,204,398,325,105,187,905,432,713,488,793,611,173,336,380,542,147,33,417,886,997,556,209,322,363,986,466,729,953,596,269,45,656,590,192,464,39,175,809,836,296,490,434,426,687,142,270,651,975,148,420,749,572,845,34,492,550,950,355,944,554,92,687,907,249,468,363,592,983,378,552,460,25,349,405,448,824,806,261,326,87,18,263,270,946,233,749,829,474,297,320,339,59,467,260,328,937,201,355,725,724,870,880,555,180,759,202,762,441,855,389,867,874,349,923,405,808,660,21,185,805,755,12,909,630,209,631,791,326,187,532,900,631,965,578,188,341,315,65,606,811,290,561,450,222,595,14,364,837,118,634,860,321,250,454,766,478,932,617,264,477,277,692,254,256,249,682,654,106,515,380,12,395,984,323,850,479,847,621,865,688,145,148,35,406,806,409,842,177,18,151,730,243,189,437,27,141,763,988,420,171,438,763,239,706,52,295,248,872,281,426,174,201,952,703,137,95,810,694,739,127,845,995,727,48,498,609,365,615,327,133,463,632,129,603,25,415,3,514,724,931,920,436,751,294,418,417,280,779,336,330,567,499,880,293,384,456,740,838,45,457,964,908,95,815,670,661,460,907,993,798,145,601,353,327,132,529,990,717,985,730,189,189,226,666,440,850,439,996,868,127,296,753,334,462,40,239,928,751,562,536,329,619,743,312,981,642,676,457,443,95,107,438,545,521,905,675,32,91,248,283,423,52,873,723,208,712,274,886,67,962,105,634,690,417,863,135,577,442,773,305,562,72,643,599,461,157,960,19,318,926,902,574,196,193,75,896,702,323,885,621,642,513,520,624,860,272,691,760,445,114,740,763,758,413,280,603,478,997,856,479,827,441,370,322,125,752,415,349,583,689,774,952,286,799,42,561,562,775,899,735,146,566,637,348,694,848,926,909,119,590,203,6,213,624,690,547,455,284,494,71,833,336,11,679,870,86,877,328,181,504,548,99,490,157,918,442,688,224,569,107,48,17,196,943,188,140,447,72,485,919,888,20,695,550,833,981,444,92,846,889,377,507,842,629,569,888,163,31,745,107,505,874,543,314,894,612,203,825,360,21,785,433,38,163,656,378,110,264,288,167,813,494,391,7,53,726,150,287,354,595,102,488,576,837,738,369,552,844,970,705,319,608,4,891,951,853,577,516,267,647,292,89,106,484,381,160,737,847,154,282,531,442,278,745,144,782,741,274,64,976,221,770,188,498,924,53,997,727,561,264,60,837,438,528,785,99,989,488,142,629,410,320,849,863,419,771,958,648,795,725,639,605,465,157,934,739,599,325,625,499,951,419,402,402,857,787,479,926,474,621,98,570,482,395,711,844,785,36,855,679,725,264,123,509,656,495,637,626,154,66,673,52,934,269,721,631,193,358,650,421,425,517,433,945,240,695,258,698,805,335,734,500,619,812,449,592,909,881,197,522,492,370,747,537,390,784,869,656,727,354,776,326,604,590,98,975,317,769,418,161,466,685,907,691,869,389,514,632,17,101,333,866,372,153,246,105,657,852,64,980,649,792,987,363,414,307,644,491,850,149,43,75,695,758,487,849,515,316,462,629,269,970,936,457", +"87,71,921,189,154,209,737,61,514,287,828,321,590,630,399,356,532,939,330,775,763,61,48,949,160,850,36,549,28,147,89,415,188,915,745,872,668,958,148,994,120,527,536,794,743,738,884,63,486,311,916,114,945,771,664,214,741,50,277,419,818,553,450,620,617,902,294,223,276,487,338,754,176,629,435,588,293,775,263,783,337,152,492,403,270,990,110,501,101,56,374,683,63,965,450,910,828,573,921,361,771,916,77,58,273,884,69,186,136,952,636,822,374,357,364,756,660,630,813,482,64,38,187,181,415,659,919,853,601,288,246,600,0,929,65,734,786,629,769,732,319,334,464,874,977,491,832,411,961,574,551,988,255,101,56,869,938,696,444,266,186,442,479,586,989,718,967,764,277,836,310,892,114,40,554,443,73,770,487,105,485,414,103,583,511,333,415,582,397,900,625,73,745,713,983,661,754,70,779,713,545,723,381,968,965,409,564,135,849,899,191,776,805,715,19,968,92,607,937,231,291,221,963,334,981,612,994,292,630,321,656,861,284,131,282,384,904,627,644,1000,124,841,668,586,10,282,582,151,489,702,304,182,584,173,548,819,781,592,997,311,332,226,29,872,334,118,451,5,265,19,618,673,518,107,440,492,784,73,494,77,492,979,723,409,598,512,238,926,81,686,513,490,309,142,235,146,752,224,630,2,847,46,116,718,779,656,547,929,956,902,420,852,337,793,271,289,380,600,824,758,976,25,717,204,960,329,366,509,124,317,528,604,745,379,199,286,692,588,469,273,634,919,726,12,57,144,809,849,802,621,868,399,359,698,346,155,847,509,911,297,845,667,122,575,84,149,852,163,906,666,564,175,846,906,96,426,632,459,955,83,139,341,980,411,782,368,862,979,104,685,615,458,895,623,468,531,565,332,764,798,256,181,854,490,258,15,142,840,974,211,782,135,367,637,167,743,821,195,94,966,289,265,269,698,725,579,635,670,640,844,309,879,267,979,247,122,842,141,361,155,275,195,686,532,407,994,699,576,978,104,222,624,261,126,684,913,343,865,687,995,559,850,881,127,350,495,808,762,661,177,241,963,480,211,820,9,419,167,649,720,385,409,541,163,628,435,794,472,511,664,671,127,209,709,313,833,355,927,560,691,493,374,716,757,117,614,723,481,619,823,280,269,809,840,241,115,52,162,846,71,152,375,903,166,684,874,906,673,845,325,939,567,895,12,780,232,117,332,209,815,573,799,302,323,528,985,453,997,104,345,274,134,665,136,17,975,536,938,456,634,409,480,619,593,727,875,990,764,748,431,129,929,399,885,91,789,162,538,782,350,799,463,163,298,262,950,731,56,545,789,592,448,354,324,984,365,640,150,395,712,116,572,127,384,636,275,369,748,580,52,891,614,571,185,551,802,58,219,589,118,217,181,187,257,966,693,46,484,429,641,278,496,351,108,904,178,758,279,700,416,607,867,649,474,444,644,608,281,874,926,323,376,964,860,260,960,182,850,376,283,517,93,598,298,467,729,382,204,12,817,712,439,28,584,743,741,708,678,323,480,948,346,639,223,482,387,161,720,170,478,724,7,609,591,495,940,154,113,551,744,92,344,390,981,198,76,513,451,309,565,246,447,844,306,417,764,773,971,196,546,254,34,713,610,262,271,79,150,512,997,831,290,17,475,502,357,64,28,25,734,844,272,763,376,698,678,543,726,392,865,775,535,323,67,631,436,221,121,563,221,415,667,834,204,771,138,950,192,88,968,325,481,620,876,877,686,335,531,365,931,770,974,929,976,348,831,531,328,807,629,848,233,647,496,425,871,361,516,671,987,1000,118,565,435,574,603,771,197,104,769,786,262,259,947,785,614,11,978,375,213,64,194,786,764,891,778,593,406,689,845,572,775,241,72,703,128,736,508,336,775,936,99,537,335,100,980,205,9,7,88,817,1,294,30,355,706,947,687,781,650,522,669,275,858,389,22,622,360,181,380,551,55,536,354,978,799,523,150,479,376,650,816,140,43,558,386,522,288,207,368,285,928,692,582,760,189,600,167,769,943,827,862,923,786,628,987,24,860,327,923,484,197,425,502,620,742,522,238,926,629,938,157,930,34,595,454,897,746,563,433,4,836,125,989,652,800,746,952,11,634,793,283,485,879,454,759,122,933,513,577,292,239,781,884,849,816,345,592,149,468,534,408,279,704,690,112,767,675,82,415,239,429,794,591,720,423,509,740,313,122,710,608,72,156,965,656,302,663,367,865,495,576,275,607,902,172,794,237,516,944", +"62,908,353,908,430,461,834,936,601,627,929,709,651,903,926,383,365,359,872,357,630,276,463,981,811,491,969,197,681,874,391,631,455,349,470,815,600,285,393,598,584,474,635,538,974,322,808,814,51,452,436,915,334,529,315,846,529,353,866,187,264,238,338,479,317,920,254,446,681,612,940,512,375,871,18,303,198,772,396,605,138,79,409,115,386,936,169,295,126,473,567,610,918,294,143,522,811,102,770,675,138,277,449,575,962,245,411,994,972,706,440,782,201,336,783,79,840,698,481,390,492,756,55,698,281,943,904,327,624,260,430,714,929,0,215,503,244,422,354,230,943,706,431,135,997,814,814,108,402,165,866,195,798,151,541,445,495,661,298,921,606,537,555,880,356,528,99,312,18,554,874,720,557,159,733,101,497,965,900,910,777,879,277,924,29,593,849,183,295,23,87,354,201,487,189,937,636,89,515,356,641,587,831,309,567,495,298,838,507,57,736,546,787,330,438,982,632,23,353,248,775,785,754,593,612,21,852,22,562,862,64,276,824,313,740,314,156,856,486,181,979,352,106,512,264,706,235,238,69,702,474,923,176,474,637,738,425,317,178,349,349,835,84,745,379,336,933,541,799,272,979,404,431,438,162,754,116,269,167,814,465,329,981,266,596,657,214,411,444,931,660,19,615,735,101,128,742,570,593,982,889,647,278,147,473,47,54,945,871,710,518,867,568,519,457,532,737,144,907,120,192,510,211,731,368,413,303,70,591,72,746,171,655,980,539,918,490,680,781,604,823,884,438,862,934,682,702,393,653,365,719,777,157,898,217,346,381,926,776,973,207,782,814,960,383,86,897,564,754,352,203,331,128,585,719,771,539,994,304,960,287,147,367,37,658,207,230,108,976,725,775,893,339,734,799,719,213,367,50,576,896,360,983,373,94,197,337,566,644,470,741,362,731,498,966,594,391,450,799,959,976,239,638,494,704,269,180,370,620,824,157,950,345,225,855,440,315,232,40,822,385,513,2,528,609,954,983,880,610,66,251,188,467,885,795,260,729,899,769,904,486,733,648,367,881,400,498,59,189,700,914,217,544,869,215,522,428,877,175,298,281,522,19,11,551,860,345,305,110,889,854,771,516,232,739,776,188,212,153,434,542,642,816,303,457,280,580,593,879,771,323,439,695,664,656,103,617,752,223,979,953,952,25,435,464,572,820,478,45,80,631,365,231,924,498,392,581,277,360,99,548,49,265,221,557,199,105,131,422,564,290,527,923,684,9,286,873,23,963,367,240,894,272,215,46,206,860,96,570,477,898,439,332,40,750,417,756,49,622,876,991,231,367,513,58,497,478,427,331,575,100,558,143,988,48,813,978,150,199,830,474,446,598,687,972,864,889,970,459,856,707,539,404,15,43,994,296,204,11,342,83,753,191,737,282,36,360,273,705,829,989,968,771,179,775,599,272,336,781,313,789,205,135,692,213,105,372,626,478,535,156,972,286,919,962,309,825,821,114,7,71,809,29,207,470,306,676,344,489,259,819,986,831,362,562,756,784,445,242,722,218,642,588,6,497,781,261,641,589,728,361,311,942,257,994,577,363,584,777,327,962,962,179,398,234,236,10,245,416,141,579,778,860,716,787,770,747,378,696,505,553,808,688,479,193,589,540,802,941,364,761,130,287,357,432,840,569,630,337,928,509,888,736,63,905,323,224,365,214,878,476,844,771,973,276,898,658,107,394,914,944,319,689,329,450,483,638,304,518,484,69,568,874,893,23,376,848,298,92,808,447,83,662,752,199,998,705,281,854,787,147,627,452,832,158,318,492,315,697,701,659,955,345,946,626,642,768,621,94,166,978,416,501,738,162,207,12,984,806,424,578,937,774,649,790,455,512,920,828,619,366,645,957,745,274,594,505,803,224,916,597,884,46,327,973,231,719,544,856,369,766,306,366,483,463,721,150,204,740,662,132,567,646,708,592,785,476,787,698,269,69,778,362,535,359,798,848,995,170,157,959,146,411,119,519,695,635,692,282,314,114,408,347,766,567,444,924,580,582,702,813,98,725,213,789,978,437,107,468,711,884,681,377,587,192,119,874,76,864,295,234,586,207,494,714,624,656,32,442,79,419,325,584,696,23,124,570,600,549,97,79,736,217,978,24,326,370,849,14,865,471,933,521,610,894,22,672,625,167,296,186,370,133,706,123,765,431,830,804,390,516,752,18,350,926,98,196,566,146,284,449,13,235,999,927,145,304,414,906,409,180,444,686,422,157,185,684,456,674,853", +"218,63,134,819,25,756,185,794,150,859,102,110,441,90,732,296,687,344,148,305,380,848,97,609,270,870,972,736,337,64,527,167,579,328,95,948,672,322,776,714,852,46,927,57,670,149,617,438,707,267,870,520,738,386,163,391,421,158,356,494,490,860,374,283,385,694,691,794,575,593,575,371,282,504,184,588,685,741,747,77,638,574,245,408,380,689,628,217,989,966,135,298,841,586,61,432,144,621,42,483,303,836,669,292,571,504,554,877,815,307,51,267,798,702,580,577,405,5,538,911,615,516,993,794,131,349,570,505,124,842,524,530,65,215,0,931,351,515,330,549,44,913,645,370,954,741,328,342,958,951,631,134,278,865,556,728,408,493,205,690,960,84,491,751,766,855,468,555,954,703,598,30,179,880,804,293,659,713,555,521,314,580,812,375,901,153,980,103,440,206,570,687,396,412,164,175,246,581,642,219,718,519,596,223,894,34,398,747,816,679,222,116,297,538,689,649,112,238,501,726,810,212,396,531,824,532,354,818,191,423,667,460,147,165,550,41,994,986,793,555,929,290,631,259,935,998,102,53,806,880,970,912,868,152,276,849,599,158,618,150,483,587,950,614,173,297,866,816,880,210,314,268,511,321,407,390,558,221,785,219,426,663,928,410,523,686,443,23,500,707,549,194,125,623,67,820,324,793,523,928,505,879,566,28,850,764,656,778,419,899,378,261,335,396,984,143,348,264,373,291,166,367,687,355,246,140,340,337,157,576,59,522,252,562,610,820,656,897,424,796,699,529,371,807,417,861,764,209,831,117,921,33,137,613,706,584,111,575,421,605,198,207,189,518,89,93,232,66,949,534,110,345,771,326,155,62,579,243,550,744,57,343,690,483,927,225,757,479,682,988,63,828,428,267,918,172,363,333,381,292,278,407,892,899,653,632,728,758,855,778,311,181,912,733,515,313,151,886,825,961,195,328,160,529,582,305,697,427,827,62,771,138,705,165,351,85,59,466,191,180,14,192,585,279,816,204,124,761,916,457,829,92,927,978,779,324,324,641,998,515,820,672,409,850,923,108,159,759,107,964,123,579,277,104,624,738,775,195,692,203,267,328,825,664,327,789,966,876,794,649,346,437,496,861,541,350,77,609,722,258,11,32,645,471,936,264,125,55,351,44,799,250,788,546,943,115,405,989,659,469,760,273,845,601,268,810,596,684,505,735,86,26,544,809,657,169,764,897,948,674,408,843,576,363,967,392,750,348,801,822,481,934,311,469,93,506,212,169,643,809,642,28,560,657,616,902,887,753,775,334,68,245,66,650,501,382,584,887,736,432,81,633,9,422,626,884,905,338,70,725,691,76,985,23,461,414,918,246,698,804,966,948,341,426,542,903,551,118,823,766,885,312,234,26,237,207,596,380,519,802,268,563,304,127,776,336,250,992,813,646,175,769,206,952,18,828,226,225,194,475,468,631,603,611,382,743,770,240,869,588,34,593,655,866,69,756,553,85,198,156,575,506,102,455,675,584,560,743,644,585,214,413,19,173,823,995,484,319,201,943,860,27,42,249,657,968,846,437,72,675,582,2,229,441,450,298,449,128,725,117,246,443,190,153,894,337,530,310,348,193,627,971,2,903,673,534,805,331,11,150,184,21,584,792,483,672,967,61,431,985,949,664,890,415,425,713,518,538,22,903,85,621,275,100,979,271,982,323,37,209,161,945,926,826,433,223,937,23,647,10,113,563,186,273,233,953,175,850,976,832,594,110,294,402,750,1000,926,39,640,977,208,631,840,318,621,748,366,225,174,455,636,984,822,289,237,274,427,527,100,386,571,880,15,99,376,194,864,928,564,496,570,864,176,776,143,713,101,86,412,210,190,909,478,645,120,335,207,872,459,451,521,123,563,658,727,527,312,270,411,380,51,911,943,437,132,227,126,59,453,716,786,837,316,218,512,657,821,672,711,876,987,509,566,318,814,452,546,594,991,880,614,82,787,739,470,469,911,948,453,98,11,14,109,634,282,844,898,935,967,732,810,616,436,376,349,773,566,726,887,84,461,135,413,451,46,535,787,172,475,514,313,398,581,591,19,164,649,575,472,727,296,95,847,803,549,736,144,877,996,424,323,169,52,516,841,766,976,689,974,988,363,715,497,847,240,969,126,276,342,334,727,474,755,894,289,330,61,449,183,951,975,572,855,453,92,302,671,948,329,33,234,499,866,555,24,16,689,255,302,992,840,941,58,317,464,6,928,483,297,66,893,811,762,23,829,197,138,835,383,496", +"435,125,593,65,850,97,148,170,845,457,782,178,968,529,112,389,980,226,631,854,23,868,340,19,899,237,388,551,661,542,118,986,602,260,706,577,907,850,273,433,104,422,12,90,776,146,47,398,915,585,954,470,495,469,399,894,975,529,214,54,418,248,768,681,231,47,616,78,624,900,473,580,556,561,5,99,417,670,650,660,162,497,820,392,309,226,681,810,324,221,903,560,433,541,550,671,569,468,847,656,675,211,782,922,227,513,693,255,181,204,517,875,141,583,899,38,432,277,374,58,27,733,393,213,76,928,481,808,539,352,61,944,734,503,931,0,290,797,581,57,306,783,69,761,741,173,731,570,221,121,834,29,658,994,987,6,974,858,663,447,67,280,327,536,769,125,405,859,437,871,230,967,990,8,107,620,132,761,877,610,358,2,569,171,23,217,199,180,602,38,452,235,820,538,174,110,151,111,653,603,8,255,417,922,128,532,903,983,91,699,796,462,55,838,118,229,143,221,696,426,4,256,479,258,940,299,170,889,287,479,418,909,549,424,739,701,780,920,733,124,637,496,914,84,143,542,448,20,686,964,436,802,516,765,330,365,982,432,445,921,718,23,845,243,598,332,223,473,980,746,859,23,728,350,253,590,414,202,442,549,537,850,600,252,385,865,660,349,339,631,373,899,523,902,171,86,64,338,7,882,467,434,815,901,335,459,292,507,730,900,955,175,957,255,462,303,481,824,284,232,273,953,498,225,254,320,968,254,79,834,698,102,660,479,246,40,268,511,276,730,899,633,731,301,709,90,36,524,213,864,636,131,602,702,517,256,444,683,957,668,540,385,147,322,778,802,731,249,576,320,818,917,68,93,312,160,968,794,837,75,423,826,671,467,117,609,777,509,341,302,122,563,371,24,880,283,590,37,413,776,999,846,382,618,870,566,904,378,54,934,762,368,619,715,981,238,467,560,737,307,24,688,741,388,548,290,559,62,219,889,42,959,440,394,506,441,296,661,404,577,354,652,216,661,365,861,881,975,663,803,574,244,25,80,776,742,718,842,712,311,448,116,846,443,805,518,992,476,919,172,299,434,374,397,508,41,758,527,426,423,632,684,462,750,765,405,896,18,141,298,847,317,794,3,846,892,119,917,172,882,876,939,789,652,67,104,269,498,915,824,704,390,971,172,3,713,853,183,21,841,608,445,162,419,538,897,490,559,885,163,885,166,921,899,257,185,765,611,110,409,437,762,124,432,781,738,274,409,309,608,782,695,146,193,217,463,901,885,228,272,584,730,317,21,221,257,731,641,925,479,815,94,541,312,799,111,825,45,426,417,515,567,61,386,259,494,752,58,200,269,137,751,600,576,188,444,585,716,34,953,80,300,847,452,403,159,908,719,114,937,333,617,806,895,458,615,462,734,703,4,864,192,361,679,951,697,247,553,812,575,939,22,255,618,367,876,41,906,247,839,114,821,803,917,202,441,443,973,476,115,484,304,51,431,144,947,476,777,476,814,194,893,441,340,919,550,837,310,567,613,108,99,359,774,33,19,224,450,960,94,147,958,72,174,420,635,556,468,292,864,562,413,731,108,4,594,975,201,852,95,841,982,932,155,702,632,521,809,292,684,482,472,120,573,319,70,42,918,995,822,24,215,762,450,166,790,277,207,1,148,52,82,792,67,533,818,452,68,663,30,249,216,879,784,497,712,372,117,217,517,506,686,747,533,296,166,923,516,438,126,343,309,944,234,792,890,408,153,71,457,803,511,219,453,96,544,863,722,807,666,166,380,45,952,877,668,235,225,793,853,126,566,489,323,717,895,652,185,435,137,203,155,878,971,849,396,998,673,663,935,504,41,308,625,158,714,804,897,392,825,289,188,341,376,168,60,709,660,501,273,546,797,143,120,272,120,597,630,499,352,904,186,672,889,32,40,911,108,170,115,998,871,117,658,838,638,733,323,398,656,295,683,293,175,445,14,140,858,845,354,694,407,642,791,669,838,610,846,800,27,879,79,178,855,136,335,231,28,221,304,354,808,242,647,807,245,152,163,487,680,318,500,397,627,140,858,599,51,755,983,672,998,175,580,734,571,128,258,558,126,922,381,502,686,219,8,12,907,410,161,397,485,745,523,551,148,788,174,626,685,126,560,92,264,476,482,384,443,448,918,194,862,416,142,684,900,464,373,604,70,136,173,940,791,715,257,523,180,829,442,720,683,146,391,690,420,256,598,939,98,212,153,40,282,539,894,870,331,804,63,403,985,155,386,563,129,753,201,564,38", +"559,560,511,555,374,523,472,167,943,90,766,788,711,456,225,651,278,613,773,682,671,499,976,147,145,203,874,308,356,323,51,812,732,888,550,110,841,236,776,448,556,122,252,255,316,57,932,407,94,247,182,281,44,539,551,550,9,927,996,144,411,653,96,436,996,703,284,197,191,267,400,835,289,900,807,413,133,390,956,655,446,538,780,778,12,377,495,834,523,374,831,609,559,94,235,626,678,44,888,285,645,18,821,614,806,567,443,866,934,389,529,521,287,201,639,682,148,682,153,245,187,610,374,924,601,944,732,227,513,144,345,641,786,244,351,290,0,176,575,629,986,230,976,364,720,474,837,698,508,369,431,734,504,626,141,85,861,569,301,319,670,817,32,156,619,998,893,255,156,938,209,272,328,968,561,640,388,765,457,359,181,210,331,412,510,300,795,399,298,881,620,702,872,326,317,126,262,219,110,143,562,814,290,10,353,222,619,743,857,364,701,733,954,543,802,493,20,816,13,49,348,405,123,876,237,731,60,552,832,564,121,274,99,309,631,912,23,444,994,7,333,241,38,896,146,504,614,378,953,685,104,111,135,790,758,240,763,429,565,178,321,12,283,36,711,399,679,330,801,36,709,799,123,773,786,192,960,983,122,779,152,131,987,440,191,637,292,946,936,106,204,664,355,275,566,375,328,444,264,212,617,550,691,880,573,229,677,652,71,309,693,727,947,249,652,654,152,32,980,593,24,366,489,994,588,403,624,73,718,814,138,288,420,204,745,258,193,746,940,502,740,563,889,765,360,712,908,551,488,713,722,443,477,615,129,912,281,533,994,687,133,768,465,928,63,755,537,86,170,248,125,301,436,652,863,883,552,282,418,470,633,158,970,840,336,182,547,380,240,345,516,867,854,190,75,662,930,987,330,53,757,143,281,158,779,119,407,51,616,959,34,912,406,511,592,567,750,633,128,910,584,365,607,705,984,168,900,756,719,324,46,164,908,229,852,410,717,672,193,600,622,14,138,311,536,820,346,651,666,131,455,345,503,20,495,625,536,658,407,199,630,351,951,389,835,327,202,273,818,60,403,106,962,892,625,733,710,682,280,283,425,615,903,527,712,89,611,757,400,152,120,264,525,551,694,521,516,96,975,226,809,361,278,473,157,201,877,631,60,376,777,355,352,448,352,114,390,235,137,921,532,740,360,713,963,361,350,444,668,22,366,104,452,151,833,114,53,624,1000,741,200,884,788,541,204,706,988,567,78,634,351,200,431,548,939,463,416,701,360,450,682,248,50,536,24,357,510,8,933,842,793,533,279,589,337,540,660,53,919,58,455,795,12,753,634,215,89,560,849,168,739,560,911,487,295,128,493,161,517,357,925,700,58,790,175,466,762,690,324,823,958,428,677,517,620,536,782,195,590,423,282,964,725,3,896,94,36,243,483,393,190,534,848,763,85,927,200,347,771,130,722,905,217,463,365,843,780,752,851,303,633,511,530,817,564,382,288,101,427,548,579,805,175,559,758,971,919,295,825,33,322,990,693,935,462,861,338,36,455,151,279,832,856,21,555,513,707,925,891,855,335,808,658,383,115,414,814,779,521,302,250,23,648,82,145,546,301,496,549,476,185,283,345,941,152,778,295,879,72,939,343,30,967,765,70,574,199,963,810,680,220,351,693,185,781,771,399,166,851,139,617,258,887,127,569,821,106,552,445,402,578,546,92,112,605,597,373,216,588,742,42,317,788,392,310,213,252,309,93,532,388,558,658,782,734,472,824,422,706,395,579,567,856,40,452,242,718,310,405,895,735,623,614,112,143,616,244,314,661,495,743,262,434,954,853,655,517,851,451,205,312,504,920,498,416,440,101,976,934,200,849,923,388,522,695,737,402,575,57,560,420,161,437,24,16,691,906,165,279,476,801,324,955,669,613,778,144,437,236,743,320,169,112,245,619,783,341,775,921,763,950,849,381,909,151,211,389,962,287,298,564,493,396,273,12,686,440,273,427,911,724,733,949,561,772,408,425,743,221,584,903,665,521,302,820,776,160,648,118,560,174,926,919,245,750,970,134,856,671,882,102,608,253,349,222,604,24,948,843,456,252,145,400,747,607,926,520,621,497,550,696,833,123,203,719,76,858,860,485,226,517,525,705,28,819,361,675,364,781,658,164,724,335,421,61,803,234,337,865,809,47,725,276,981,256,349,802,434,255,72,252,575,861,133,323,671,133,316,293,888,687,600,303,195,622,588,874,676,19,303,485,295,867,6,973,293,514,826,974,190", +"283,335,430,158,206,220,479,509,520,342,478,787,451,379,176,275,191,390,247,582,17,396,652,647,116,850,833,368,348,661,644,450,388,448,386,168,819,91,773,652,536,735,241,919,274,563,767,4,202,765,595,476,115,672,16,629,187,231,704,326,939,229,649,8,279,285,114,723,399,142,350,796,828,754,889,712,114,700,361,200,652,492,812,11,582,380,608,466,180,909,485,924,352,627,818,663,377,469,671,832,250,594,656,899,289,650,780,805,439,46,710,860,237,684,5,125,888,368,376,336,135,432,862,499,27,876,645,164,133,636,710,687,629,422,515,797,176,0,160,435,672,292,756,320,383,674,250,210,786,444,447,977,479,258,403,868,102,245,475,615,791,701,60,986,862,958,915,52,164,208,26,734,929,54,935,756,539,989,394,683,743,672,503,105,304,896,27,850,142,425,148,499,482,922,87,184,920,834,855,125,271,439,546,928,610,527,963,437,728,340,827,165,368,169,539,890,73,19,455,819,564,275,978,946,657,708,415,982,131,271,75,995,976,569,50,938,863,845,975,495,463,591,629,602,544,190,200,521,352,694,542,209,625,44,392,682,297,312,236,956,18,260,256,976,399,29,398,843,632,442,898,845,912,779,248,8,965,142,232,599,49,60,740,529,147,122,362,192,294,586,815,616,607,410,35,52,395,53,846,968,969,744,921,618,429,27,489,545,951,828,726,568,208,777,230,113,703,553,933,257,515,895,725,682,303,215,207,597,180,844,523,141,198,286,970,515,869,49,376,258,905,536,468,587,259,22,505,636,795,224,672,443,992,615,6,107,523,476,281,880,836,289,487,975,817,559,216,427,893,363,459,457,476,961,145,256,685,691,154,156,766,484,727,942,669,977,746,756,149,331,613,913,281,670,540,752,967,941,736,148,621,4,987,324,854,118,896,600,613,55,146,415,617,949,58,43,822,717,584,818,316,80,115,783,606,821,651,756,232,824,369,363,338,514,589,642,918,718,946,83,41,768,680,597,955,806,42,225,979,91,754,757,439,900,71,998,880,245,764,456,54,749,960,559,593,685,193,806,40,143,719,956,71,359,437,382,102,418,160,988,939,813,409,699,678,247,491,352,70,485,398,562,714,760,742,663,806,554,796,395,123,345,882,629,533,204,866,952,395,265,889,99,797,803,128,576,460,736,219,219,576,70,113,88,527,506,508,39,369,971,360,555,728,577,160,913,227,394,752,922,504,941,902,331,361,800,132,409,192,860,481,750,956,877,562,478,570,557,590,291,323,521,584,526,553,20,830,366,36,311,645,222,6,976,553,229,962,328,552,955,282,136,24,520,215,157,819,663,924,836,986,168,694,443,332,377,356,105,344,469,264,310,339,997,379,823,536,989,750,12,602,918,712,235,233,344,507,388,902,25,617,44,137,435,367,957,262,863,247,40,570,626,56,877,659,29,606,926,25,266,593,193,627,950,296,296,855,739,788,895,607,610,847,924,823,892,779,977,841,536,159,304,534,226,148,749,708,502,733,784,594,829,451,822,198,204,527,986,822,920,228,346,412,803,67,53,927,213,858,590,81,38,571,347,98,933,148,979,448,743,463,725,355,928,397,955,865,136,305,447,443,826,488,16,556,614,639,85,398,977,180,329,315,76,361,583,150,468,714,982,881,308,119,693,56,945,280,574,572,19,344,700,227,832,629,712,661,336,823,558,675,209,413,378,196,446,474,295,795,160,304,967,722,491,859,578,11,850,3,805,254,258,332,603,543,597,300,324,899,700,682,643,288,368,881,621,690,179,702,384,304,447,426,586,173,300,458,199,156,3,99,492,454,7,454,319,273,185,35,469,382,16,990,931,192,724,659,322,70,763,256,586,411,621,322,554,807,72,144,468,806,463,983,201,506,926,329,267,94,515,785,61,443,445,884,659,34,528,976,657,864,798,555,389,28,903,81,112,258,110,127,327,97,219,472,51,793,602,794,909,623,980,426,619,959,337,559,969,350,564,104,742,823,506,731,976,124,267,890,767,524,203,728,765,130,746,940,116,884,343,85,497,398,850,795,901,869,423,838,161,993,650,204,735,557,902,460,268,443,274,773,899,268,26,547,404,964,458,850,805,129,344,740,61,479,637,316,846,900,203,320,137,999,883,767,567,320,560,33,106,402,720,661,80,647,93,141,396,367,691,33,360,366,188,531,103,213,930,914,61,686,882,927,535,766,874,904,336,687,457,120,458,40,456,94,679,349,100,605,838,742,72,85,881,894,449,937,919,658,623", +"562,612,516,438,544,821,969,986,438,314,295,271,283,560,258,178,139,189,854,549,708,871,122,6,410,107,433,133,815,149,296,235,620,75,798,382,521,809,177,864,995,105,448,455,53,271,571,420,505,765,385,915,538,892,105,26,918,74,649,924,842,852,610,585,751,905,706,490,823,461,679,327,992,630,409,78,666,602,618,168,508,266,55,378,616,77,35,380,588,682,662,647,698,988,26,193,244,242,803,96,78,763,921,805,310,247,623,763,757,525,81,686,205,56,575,857,950,973,220,933,42,590,550,125,584,69,523,468,320,590,992,502,769,354,330,581,575,160,0,317,140,590,46,38,784,651,461,70,834,674,322,907,358,748,1,654,571,313,592,410,527,571,638,391,585,308,279,616,556,759,164,716,584,916,381,598,716,36,957,973,629,867,407,696,554,505,144,881,290,586,866,471,884,270,629,895,649,697,143,58,540,150,403,487,540,62,816,747,41,926,509,938,412,17,907,618,227,163,434,774,884,884,881,978,67,116,210,791,902,636,377,730,744,700,713,726,303,885,455,803,400,749,881,982,887,280,337,788,207,997,644,822,132,934,332,753,47,265,236,589,995,428,265,770,23,937,544,208,728,952,834,295,272,23,98,825,705,751,25,903,883,768,879,85,563,314,272,895,71,298,250,207,259,293,71,289,289,372,23,371,166,885,750,144,433,53,671,12,11,964,295,529,116,253,707,683,653,929,729,894,479,749,94,855,114,458,993,988,350,843,752,735,409,242,857,790,339,627,341,943,816,399,278,321,778,559,52,807,863,315,814,200,799,643,769,392,879,448,207,65,847,200,45,122,30,608,800,574,656,220,263,677,854,568,950,716,556,806,523,497,130,702,278,663,222,298,997,51,608,656,862,481,549,510,129,177,791,983,472,371,582,807,156,126,171,732,342,245,467,381,874,632,87,950,74,52,755,265,911,872,281,845,66,986,707,878,565,627,710,550,865,78,880,601,307,661,1,881,948,473,335,600,428,208,408,109,27,67,745,443,57,314,672,345,486,415,731,106,846,203,224,986,344,913,812,182,806,470,824,244,282,661,583,372,612,422,398,876,59,961,126,462,11,611,874,166,100,545,39,717,96,362,987,455,877,753,225,136,428,555,781,119,568,258,291,597,79,306,62,718,102,334,208,709,323,860,796,439,297,714,730,910,743,39,447,887,962,451,104,791,999,811,213,703,190,457,334,888,962,85,332,335,180,372,801,921,774,803,382,834,46,85,458,218,265,872,937,383,855,393,19,44,963,655,570,568,267,342,164,239,403,669,874,781,229,729,572,858,613,235,31,606,769,809,125,319,474,181,770,412,268,215,944,540,273,681,864,284,182,345,723,856,479,872,283,443,183,74,57,477,446,704,592,633,683,204,505,823,790,677,523,622,385,800,949,21,508,748,955,216,347,382,42,662,672,999,661,561,814,721,274,85,156,966,290,384,925,412,395,273,585,571,823,954,372,228,395,746,411,47,784,649,481,247,922,592,933,311,455,374,787,162,279,110,834,803,185,226,859,919,402,631,662,612,40,362,281,697,636,970,371,822,52,534,17,273,193,461,274,707,207,821,411,740,959,144,319,256,562,623,595,314,944,155,413,559,690,119,314,122,843,251,217,262,428,337,373,844,949,438,265,435,783,457,515,170,514,954,260,561,432,795,138,698,755,636,761,865,463,397,675,371,621,455,582,358,48,745,789,83,8,925,609,835,488,900,81,458,701,792,315,977,121,92,383,236,945,846,419,67,333,718,692,543,56,562,103,436,183,965,831,391,281,467,492,322,157,189,619,101,53,280,742,800,545,566,192,581,491,158,995,776,392,762,343,910,890,501,439,707,131,470,696,829,237,327,556,624,275,873,616,519,181,241,148,540,649,229,147,192,748,845,481,795,486,651,976,645,997,77,543,837,451,586,404,415,391,901,222,36,699,818,969,710,629,102,999,206,149,560,314,556,943,870,83,269,402,905,306,981,118,639,665,868,397,949,880,334,85,537,3,518,519,118,516,716,521,721,142,654,754,22,690,52,278,969,980,693,112,895,953,11,665,72,802,859,978,384,573,219,993,341,762,288,994,380,369,541,702,805,206,591,600,18,998,35,960,281,214,901,658,458,723,327,399,610,409,694,364,222,202,955,2,936,970,271,392,248,784,499,533,639,198,91,320,740,311,392,733,224,133,788,490,408,1000,830,144,352,126,372,396,742,527,808,62,324,967,995,402,441,103,427,940,311,188,901,161,551,339,124", +"798,16,646,681,833,140,463,13,947,568,512,923,906,32,702,549,92,327,632,693,154,87,182,2,246,327,970,666,438,88,715,902,822,824,286,121,40,63,610,113,770,411,926,310,948,613,391,889,370,436,203,780,12,398,936,351,40,912,933,665,240,873,597,383,857,226,585,374,47,712,564,583,278,159,223,443,882,560,160,42,976,455,474,796,847,936,191,490,644,734,711,556,474,992,745,536,727,577,278,447,221,712,4,157,843,472,197,656,117,202,174,273,326,576,483,746,899,705,128,175,207,883,241,967,308,211,543,273,77,893,762,725,732,230,549,57,629,435,317,0,251,532,19,465,810,839,90,742,567,459,333,780,36,397,781,763,780,818,769,728,391,641,230,32,999,699,843,476,985,734,829,350,86,65,481,673,325,649,623,710,328,331,450,158,288,605,519,890,809,122,198,16,225,849,886,667,496,800,75,692,794,347,864,528,947,734,35,143,568,912,94,302,599,270,256,942,251,797,189,89,668,232,429,663,50,511,293,19,762,588,305,889,158,886,12,701,326,993,892,704,301,392,292,306,68,405,6,545,803,352,489,330,127,7,898,624,995,73,814,508,40,777,414,561,352,898,401,282,867,960,959,688,437,515,548,520,279,994,88,296,121,878,734,722,678,754,225,764,940,511,192,12,105,192,568,912,785,700,242,98,292,84,848,149,53,946,820,60,284,301,138,579,347,302,500,237,294,564,715,437,424,775,833,536,265,54,687,200,972,775,992,438,801,363,713,476,602,524,172,488,593,722,746,130,751,352,161,944,506,213,35,909,556,174,873,743,277,842,243,220,349,264,884,25,792,803,239,568,352,856,368,251,660,740,790,816,836,843,304,516,741,218,631,660,142,442,161,575,27,480,54,547,18,981,346,402,738,322,858,294,702,812,652,807,652,624,118,686,44,816,847,732,549,562,323,775,869,422,805,651,845,249,209,956,9,633,765,582,6,98,59,429,334,887,879,174,826,236,531,703,669,872,518,255,326,313,585,668,212,307,77,998,946,575,530,250,631,926,219,6,496,15,520,25,325,809,528,480,264,251,729,787,733,484,517,825,226,960,872,921,596,622,128,929,317,41,209,303,345,104,19,19,831,954,248,61,979,848,886,965,126,395,379,842,201,698,595,337,597,378,951,554,746,88,23,103,564,715,459,130,584,645,563,746,645,890,89,905,718,59,700,513,540,668,739,703,630,93,630,686,766,173,961,437,418,58,726,865,429,236,130,187,237,507,545,604,371,448,70,861,914,392,117,352,150,481,334,843,557,462,127,206,745,395,181,136,552,486,451,900,451,358,413,695,621,401,826,108,586,251,833,691,774,676,437,12,763,431,640,956,403,656,413,523,653,872,977,21,638,948,433,492,519,704,832,245,643,563,456,518,718,694,924,301,98,686,927,265,644,407,295,703,619,132,796,966,247,853,693,63,446,895,716,556,872,331,832,130,736,199,196,631,827,783,832,863,658,184,87,821,476,228,745,929,446,868,881,513,347,851,788,428,987,739,73,592,530,702,52,291,880,992,350,897,232,213,64,762,696,543,608,501,280,140,118,860,398,223,547,256,166,567,226,760,68,833,728,989,677,334,503,906,129,682,199,574,583,177,638,53,407,794,152,690,39,522,738,491,781,427,684,340,276,513,184,575,94,903,172,469,127,695,858,15,427,473,563,106,296,894,168,480,55,435,419,443,156,980,786,249,278,266,483,884,763,958,581,299,237,551,694,141,93,301,454,198,82,544,197,553,98,4,278,601,981,409,296,311,431,506,601,707,562,306,635,179,974,620,34,956,13,234,852,314,599,491,665,78,217,23,243,318,256,346,518,879,461,854,138,605,681,212,307,791,28,441,95,418,713,601,706,81,355,35,395,644,192,871,279,182,571,228,600,953,115,5,685,907,92,717,216,992,710,374,662,366,337,912,856,840,389,730,348,504,878,401,863,106,648,258,462,950,445,925,103,879,861,159,411,304,419,811,505,356,287,65,191,993,458,88,249,412,919,519,264,474,589,823,346,853,945,961,909,116,234,682,892,884,193,823,112,596,579,45,984,442,334,544,455,808,883,244,332,270,353,866,874,902,317,997,792,653,185,689,317,776,891,903,506,128,955,854,594,778,971,254,894,36,767,13,514,575,555,265,639,19,77,145,234,794,668,37,742,872,72,191,121,254,836,828,86,949,413,653,620,442,863,970,881,487,513,806,81,66,744,78,448,837,774,836,58,508,220,322,498,919,716,890,935,160", +"349,296,640,78,198,285,751,375,309,326,484,880,890,748,647,624,852,413,999,373,427,15,203,568,271,586,263,48,444,520,523,804,788,971,634,790,941,12,671,383,834,810,884,539,669,419,768,479,381,775,827,651,953,978,178,426,362,29,669,858,849,110,612,948,635,977,921,139,126,176,17,524,744,759,854,196,835,38,570,321,636,260,611,515,271,609,497,658,202,681,686,932,774,868,742,317,918,686,369,108,562,610,755,15,518,928,511,16,692,927,202,268,784,710,866,811,67,276,756,585,8,318,372,222,641,210,208,931,748,654,667,140,319,943,44,306,986,672,140,251,0,63,630,532,985,622,807,872,708,650,242,242,119,813,133,869,692,178,439,756,728,444,711,274,855,130,897,882,922,10,341,450,974,359,230,587,332,547,771,499,157,985,167,397,72,398,31,491,153,860,257,976,432,764,582,764,712,807,76,617,581,947,631,250,184,115,95,518,669,43,232,58,101,582,534,363,834,720,527,849,679,574,679,482,968,838,807,449,4,886,932,457,760,194,148,80,675,292,333,945,605,353,209,549,576,772,907,122,170,221,216,464,703,278,114,985,120,578,238,432,392,339,153,939,342,695,684,358,115,592,321,26,614,604,896,202,306,639,287,287,5,937,214,159,83,87,368,118,975,165,876,577,765,118,550,223,100,624,37,486,26,584,273,246,79,370,758,376,159,662,248,261,17,228,345,502,90,547,530,189,115,535,524,217,981,679,11,499,694,651,352,875,612,766,431,655,936,894,368,204,73,615,540,390,29,774,538,417,104,344,313,249,107,946,598,509,656,161,422,714,478,4,240,664,678,462,448,586,344,177,724,225,350,472,18,922,162,852,474,171,928,213,253,767,485,447,975,910,243,684,351,748,699,451,467,726,961,846,389,555,807,368,258,467,309,89,786,906,227,157,652,898,797,217,732,625,371,685,542,608,458,183,899,480,374,861,460,937,817,614,124,248,556,437,598,560,452,182,61,453,965,491,357,89,744,59,171,158,100,387,699,945,575,293,442,465,844,602,974,32,890,552,832,494,645,254,428,592,191,883,692,856,72,952,686,198,885,863,947,701,35,54,961,257,777,817,112,901,256,949,804,709,989,366,420,413,616,812,853,865,681,656,453,75,706,641,708,621,271,484,761,470,384,896,586,391,44,580,159,670,253,551,986,572,666,635,899,843,416,888,998,330,145,991,548,697,596,481,735,652,518,39,633,946,113,416,775,609,942,964,359,604,129,43,393,693,294,457,245,782,915,601,979,105,118,429,322,429,714,175,871,392,760,648,891,627,446,450,882,244,241,989,192,617,988,288,630,809,385,514,285,593,549,981,766,825,634,380,61,438,717,897,985,687,725,22,483,824,178,479,157,556,725,870,275,118,198,621,79,275,341,632,169,753,589,26,704,980,883,889,457,950,180,950,318,300,747,235,227,732,629,574,180,747,125,230,963,50,438,20,518,426,290,345,73,471,514,384,439,599,808,837,250,249,632,86,433,743,71,744,789,223,831,50,83,17,900,496,678,656,528,124,883,672,984,672,71,362,173,482,871,437,155,444,218,450,141,637,528,302,181,71,874,819,877,278,887,922,434,797,929,932,402,545,284,768,979,510,653,157,323,927,707,149,211,583,358,623,757,648,951,49,55,234,208,581,585,691,535,611,421,5,780,192,747,507,171,860,466,305,522,546,910,23,295,618,898,267,812,127,505,913,486,880,957,94,705,825,366,547,289,330,319,84,510,499,262,666,860,122,750,74,591,301,638,803,191,813,919,498,298,709,361,630,21,724,195,882,705,379,1,252,646,225,743,347,684,378,292,162,882,202,549,554,145,606,785,399,769,801,841,48,152,845,406,261,595,592,916,342,652,480,319,319,48,815,753,656,315,998,946,319,50,368,894,70,420,435,671,417,129,124,367,365,671,124,644,951,895,933,467,908,122,448,150,36,881,982,983,83,15,815,942,60,843,541,539,190,880,883,562,709,634,861,104,271,856,619,244,997,620,759,667,31,592,141,965,402,345,473,934,944,885,778,668,943,141,109,83,340,238,49,762,3,267,139,473,469,374,401,669,244,33,986,488,182,581,482,918,335,817,615,839,552,870,508,920,210,974,838,539,412,954,36,949,662,171,782,157,807,9,720,70,279,28,764,156,296,699,442,870,288,76,720,605,249,374,902,495,374,271,189,995,798,274,832,955,324,692,389,706,881,974,803,91,487,779,465,560,46,710,825,786,273,223,33,171,168,153,152", +"201,884,294,447,844,367,379,779,441,952,542,858,172,629,849,102,34,267,466,326,964,366,535,709,696,731,582,113,860,814,535,563,93,592,580,590,558,129,35,317,303,444,965,738,772,245,694,727,289,745,294,321,45,343,778,935,377,546,605,450,430,123,898,417,994,449,743,234,63,825,197,799,63,444,175,739,743,791,772,794,758,555,589,973,493,597,600,706,666,739,194,528,159,195,115,421,296,202,860,508,589,146,428,234,43,457,410,989,317,780,973,582,504,783,113,464,423,377,144,986,848,471,922,858,686,949,104,342,916,669,181,31,334,706,913,783,230,292,590,532,63,0,856,39,725,224,18,943,809,208,35,528,659,158,264,408,951,665,958,42,641,782,53,177,952,184,147,488,272,324,57,474,369,747,643,448,612,623,683,628,936,373,997,298,217,770,666,540,247,665,62,105,425,14,449,93,252,169,546,188,702,505,497,551,379,115,224,217,871,173,176,36,571,942,576,503,388,210,808,22,802,585,512,787,500,604,638,404,163,171,652,639,105,818,381,459,421,118,731,391,178,772,144,210,907,254,744,376,182,58,60,891,809,482,495,129,37,260,192,682,732,10,413,101,224,433,940,425,536,967,891,206,870,768,263,389,640,100,833,643,999,560,212,311,96,359,720,846,852,198,581,319,508,53,707,288,888,387,788,505,489,459,212,149,664,963,361,713,340,516,459,234,852,112,755,157,949,317,919,943,437,876,291,28,533,715,393,456,129,323,388,478,799,83,935,953,422,410,604,754,481,11,408,173,21,74,739,229,418,254,456,989,46,966,600,74,376,281,841,510,232,872,980,580,303,337,684,208,144,418,338,183,308,249,121,632,17,168,299,177,836,103,834,459,973,865,524,604,795,993,770,554,126,626,472,825,364,657,200,292,326,357,462,428,788,912,570,545,935,304,245,951,546,434,848,172,339,40,791,890,397,713,205,309,179,910,308,386,9,403,286,173,734,740,971,97,451,834,829,84,176,179,703,611,108,321,621,288,234,409,711,543,563,64,296,313,161,532,724,902,618,213,102,100,945,386,305,907,606,108,945,991,881,934,458,523,414,201,659,199,546,971,422,582,647,720,964,740,386,172,772,110,605,590,754,491,701,139,674,277,583,192,519,259,617,442,424,736,184,49,260,355,652,627,856,128,856,670,129,862,990,125,679,113,468,299,393,688,202,67,610,924,694,602,347,171,797,447,568,439,713,404,532,945,754,112,279,492,794,786,320,477,43,448,350,467,702,529,529,463,135,171,323,761,693,631,580,465,870,299,831,412,865,467,945,664,577,339,729,101,429,723,169,121,624,593,944,458,588,796,55,642,381,402,973,259,759,869,259,628,644,57,110,476,841,25,44,158,300,597,610,409,145,954,557,17,967,377,289,20,522,487,285,711,323,401,914,390,784,437,386,797,198,433,486,436,56,438,280,717,279,96,723,132,644,750,396,312,607,726,629,57,168,664,589,107,358,402,28,406,393,788,379,953,565,41,357,485,868,901,437,132,69,97,312,196,110,549,880,804,300,491,929,150,762,100,73,337,681,135,593,918,633,43,449,497,406,429,863,446,316,245,691,547,351,535,770,604,103,523,25,299,621,674,955,849,587,449,578,222,48,268,180,21,287,687,642,863,392,996,737,657,835,359,305,584,154,357,830,388,718,120,481,472,462,759,739,995,305,894,736,81,911,534,221,200,922,181,156,335,427,519,926,181,101,847,493,923,564,81,32,987,363,853,189,37,238,881,785,770,47,645,405,644,846,106,744,147,279,769,935,973,991,538,603,318,200,254,709,996,348,320,734,523,872,640,204,910,454,154,430,474,58,144,572,21,426,448,581,315,23,102,361,545,678,567,770,287,480,685,212,410,996,305,433,512,129,910,198,939,727,203,43,620,91,951,701,825,403,283,482,139,871,919,650,798,908,448,494,504,625,131,407,897,26,778,842,909,642,100,134,51,741,735,721,855,685,290,206,463,961,784,37,607,696,496,531,234,138,16,219,696,884,966,962,545,584,568,380,580,654,96,983,336,711,580,432,716,242,42,369,471,502,929,767,521,359,347,220,376,835,157,246,515,310,672,592,791,623,331,400,665,753,88,497,134,239,509,926,186,358,706,220,474,984,856,449,179,673,568,381,722,404,62,628,570,917,692,968,448,166,234,344,118,173,468,775,370,235,886,859,32,471,664,963,474,277,905,985,513,25,102,85,906,421,813,139,729,683,250,605,774,397,359,51,880,627,461,458,872", +"383,446,623,931,658,287,202,478,43,541,210,213,416,629,288,291,768,669,589,337,446,261,808,661,231,452,365,317,570,621,731,620,593,958,584,779,137,170,338,977,239,357,307,787,43,753,86,952,748,639,940,426,613,171,287,519,173,949,814,500,735,267,859,492,255,73,739,850,886,123,81,367,637,606,787,231,865,751,963,870,716,910,679,314,953,356,658,242,102,985,809,923,911,574,443,321,404,767,71,330,736,809,39,864,846,308,483,266,935,919,683,24,899,420,885,261,847,533,629,509,785,770,641,255,563,64,978,625,520,967,65,842,464,431,645,69,976,756,46,19,630,856,0,667,592,355,429,3,166,141,25,659,435,371,389,179,540,711,358,381,803,46,795,467,587,740,523,41,381,831,641,815,301,225,476,690,578,162,264,390,518,134,218,552,248,720,940,486,453,578,15,517,702,507,499,868,785,245,261,495,85,391,133,434,892,986,384,125,914,148,176,274,444,718,597,865,252,246,728,607,275,877,379,123,420,958,787,85,593,829,336,822,142,256,233,135,412,461,372,571,771,641,102,174,757,90,450,313,65,660,500,875,349,825,121,926,670,898,844,87,794,368,425,888,842,567,868,662,250,234,829,475,536,613,294,165,367,974,99,297,911,866,531,197,653,852,285,353,31,52,997,361,980,433,961,957,241,766,604,323,337,933,270,73,251,374,67,877,511,718,182,742,829,188,41,650,345,422,140,15,324,358,730,374,255,9,144,206,148,539,896,132,967,512,835,811,97,254,83,77,846,716,593,394,412,889,291,334,321,531,453,234,861,90,375,729,578,5,423,635,313,620,983,863,956,786,438,348,284,917,801,382,759,703,867,82,570,375,717,362,463,743,896,194,793,314,708,803,558,771,765,27,481,149,33,115,622,460,248,819,907,658,948,303,824,816,202,701,495,530,705,495,20,224,812,362,429,747,472,877,975,985,941,423,798,932,994,197,632,207,942,205,445,166,590,699,970,111,90,616,105,543,932,876,552,201,120,187,311,13,790,604,597,394,89,744,558,38,464,492,19,528,998,809,739,853,740,784,290,527,506,451,974,87,944,645,27,841,31,399,826,415,859,520,689,100,839,714,744,379,964,944,696,517,534,910,426,185,201,618,246,346,289,404,7,342,458,459,476,618,336,699,675,605,898,799,576,214,501,984,117,673,807,783,540,584,457,839,14,855,507,646,63,905,766,296,993,883,398,462,958,118,338,156,217,676,948,154,55,149,298,755,908,254,656,320,13,318,568,380,937,783,35,645,220,400,276,810,39,560,923,153,244,583,8,463,425,905,497,572,599,802,961,317,580,58,920,945,345,280,551,250,13,249,251,321,412,545,826,83,880,70,828,905,348,995,324,838,642,575,206,388,109,987,547,348,154,42,504,923,80,272,501,614,277,341,266,632,450,844,412,23,318,58,739,199,69,278,40,443,105,452,124,21,37,348,936,212,260,787,6,915,171,518,541,800,52,590,8,186,510,82,239,384,488,914,841,616,660,837,502,813,598,849,832,487,499,852,759,366,200,977,767,554,47,464,508,570,414,695,787,384,50,965,174,766,986,180,532,372,71,507,840,952,575,670,515,985,238,887,731,875,435,846,846,413,307,712,973,470,390,380,415,469,20,523,124,989,905,356,936,642,878,939,766,771,486,848,853,925,190,995,481,167,878,334,710,913,778,549,251,815,103,105,97,826,347,773,425,460,651,919,835,962,202,898,909,454,963,125,674,57,909,17,462,936,718,941,691,723,55,86,210,794,292,876,678,430,91,366,630,549,311,643,800,969,506,465,471,508,454,419,839,53,638,872,26,120,879,752,505,807,486,713,386,221,312,886,763,303,585,677,407,886,539,208,270,49,272,405,247,143,948,287,979,308,359,491,892,72,563,820,22,37,234,908,449,488,230,476,635,880,526,989,92,482,249,447,255,699,439,88,981,669,819,753,660,388,955,498,698,318,124,928,811,545,713,733,554,460,980,683,411,808,697,877,689,695,338,326,892,259,52,582,838,452,386,396,906,947,189,831,898,368,28,833,32,526,175,260,33,154,710,233,748,523,242,492,494,920,424,5,609,71,100,362,877,180,187,444,828,342,823,862,878,498,211,816,472,735,217,294,737,185,613,207,445,820,500,470,573,999,693,602,552,768,735,442,351,783,795,901,441,519,80,602,855,251,350,339,890,84,213,69,222,98,46,476,105,919,519,603,154,155,619,153,40,305,367,181,146,157,935,430,691,574,145,932,595,214", +"249,530,203,721,692,922,58,393,680,216,58,818,632,795,149,911,784,63,948,706,436,986,108,704,914,550,131,917,20,134,861,192,277,582,596,492,9,51,150,628,335,720,455,954,730,322,639,261,509,254,692,268,321,585,305,426,47,826,492,945,475,781,502,906,386,28,139,634,575,684,709,8,62,11,165,27,801,947,919,157,69,686,643,703,28,715,194,241,156,249,979,472,323,996,4,859,890,507,564,842,308,388,522,356,195,738,10,713,103,468,378,878,2,794,193,904,913,644,718,648,751,820,301,284,504,127,565,285,56,99,117,557,874,135,370,761,364,320,38,465,532,39,667,0,192,766,458,641,400,831,864,772,332,761,540,735,643,978,580,409,489,299,746,720,982,241,336,979,566,331,809,437,979,917,320,112,970,359,613,338,448,841,518,710,318,50,168,452,496,950,385,205,707,150,516,533,205,790,966,250,529,893,679,20,559,500,13,93,448,935,339,795,967,127,184,74,966,262,74,318,174,528,354,810,813,575,641,1000,786,299,774,400,989,577,111,875,890,467,118,488,697,838,497,127,233,464,22,935,93,960,837,49,503,559,75,930,601,977,726,498,458,739,807,363,827,810,917,468,516,756,425,811,393,404,293,448,828,550,766,571,410,210,313,445,985,115,124,606,748,152,619,724,635,485,683,285,917,673,970,203,795,43,144,144,748,131,246,351,606,520,200,174,877,617,794,548,610,43,907,485,546,325,205,514,720,840,614,165,466,621,278,705,803,263,753,59,453,657,960,620,646,832,98,768,257,967,346,39,694,600,328,38,122,634,634,828,344,184,13,868,728,644,723,129,223,207,644,421,22,754,713,423,921,196,961,837,195,664,478,76,768,684,316,616,697,182,305,535,287,437,789,667,807,909,461,294,511,531,54,413,398,901,814,426,120,530,172,64,707,256,980,631,186,116,759,641,535,559,702,419,985,489,692,30,520,564,583,930,583,876,610,861,521,894,279,382,331,637,121,119,447,546,289,203,558,992,417,876,684,830,460,333,270,465,703,985,60,72,294,958,618,265,497,973,366,345,7,588,734,408,631,395,888,615,518,995,746,60,280,547,241,445,151,401,899,341,577,654,379,991,844,999,364,826,644,215,154,340,775,463,989,669,825,795,798,615,637,39,879,977,538,687,603,62,407,147,254,408,441,869,371,60,144,962,292,451,567,19,99,934,573,831,462,921,209,269,927,175,177,359,43,781,25,646,61,899,259,522,526,804,589,800,438,582,387,896,98,442,19,569,161,491,923,697,770,831,200,57,505,958,133,447,123,647,39,116,547,517,620,718,580,20,484,492,439,821,936,658,587,459,764,513,945,992,707,123,335,788,721,35,606,103,62,746,241,127,157,807,535,546,449,804,699,910,306,776,495,490,10,769,434,813,207,153,685,949,679,580,949,761,26,233,38,428,416,699,9,160,461,665,993,751,473,352,598,663,292,352,856,203,447,625,594,122,974,107,405,711,977,653,254,164,909,163,90,7,4,885,682,943,505,201,319,680,964,885,414,871,535,979,254,374,610,250,136,248,710,709,941,176,125,53,231,421,976,617,648,205,361,176,309,332,642,986,978,603,661,192,342,191,49,227,518,856,789,201,689,238,218,633,875,33,8,474,787,70,284,723,569,363,653,399,266,49,209,424,236,943,463,368,15,81,677,674,632,136,367,935,539,151,562,165,919,996,883,179,18,962,447,222,479,205,738,326,252,410,428,955,945,767,732,639,445,511,906,982,565,657,533,337,625,692,595,450,573,909,434,566,171,225,974,261,177,759,230,585,193,7,420,286,303,340,293,720,671,459,257,501,497,255,803,843,266,496,22,416,920,457,918,941,117,82,994,296,251,233,778,808,320,754,479,549,596,593,475,238,850,992,861,736,698,592,633,238,216,854,392,94,832,711,55,826,61,325,696,410,707,777,421,838,547,407,156,734,141,942,851,274,108,625,792,906,227,376,134,160,534,325,925,977,677,564,153,789,434,459,510,456,837,678,925,855,513,478,459,984,610,574,737,957,331,842,596,900,433,338,997,178,614,848,18,186,653,192,450,52,835,985,711,402,623,514,579,490,656,304,751,710,169,462,427,817,503,655,24,931,338,576,307,987,858,438,429,816,640,196,778,503,9,131,433,646,293,577,857,550,40,699,183,898,180,149,618,262,438,878,143,832,939,211,498,584,139,227,724,543,222,516,105,542,965,183,893,141,773,276,826,796,116,910,628,183,594,950,864,552,124,877,275,844", +"69,622,717,183,135,213,855,292,725,593,727,463,677,890,199,218,627,543,295,361,56,992,19,54,436,810,300,496,33,855,878,481,721,430,589,871,327,416,725,332,915,536,197,994,583,614,392,61,34,760,671,180,790,413,412,551,735,282,403,652,377,621,420,218,83,173,732,662,347,392,60,643,673,292,654,873,123,354,952,260,206,440,929,377,446,890,349,891,536,418,301,66,607,175,697,879,590,311,66,886,638,316,764,640,536,210,197,402,719,678,102,339,82,716,268,913,923,688,111,83,838,952,468,569,331,117,903,616,465,851,239,928,977,997,954,741,720,383,784,810,985,725,592,192,0,280,349,302,448,648,272,151,764,487,946,675,765,581,765,455,987,180,685,753,774,333,990,896,65,35,733,562,859,614,875,665,834,294,533,117,450,885,455,695,637,60,97,714,737,576,651,839,626,688,829,133,850,801,748,411,410,388,695,107,207,481,276,919,915,389,202,390,234,653,994,578,558,120,852,514,45,692,464,860,48,801,557,857,671,804,603,61,445,141,862,6,897,990,910,294,96,786,713,765,722,977,258,823,968,348,393,581,151,876,443,94,746,111,615,794,914,151,791,709,271,442,877,4,683,982,191,173,725,995,964,597,491,975,887,169,525,8,100,912,547,498,129,484,282,178,386,961,209,852,73,931,529,183,43,211,38,145,306,999,859,668,933,631,476,672,470,419,211,191,755,111,164,662,506,20,565,882,947,978,93,883,25,375,441,800,683,673,191,353,984,221,228,159,13,395,740,663,659,941,114,414,511,580,998,857,537,343,681,826,544,176,696,328,214,157,804,385,950,99,71,744,654,576,230,106,815,891,489,412,587,579,605,299,718,505,458,167,154,899,886,721,986,206,47,987,798,326,981,445,482,277,644,615,414,136,815,69,447,730,284,440,849,529,547,712,414,96,32,587,164,705,738,893,661,270,316,71,392,488,92,371,697,447,993,242,17,54,169,642,81,10,292,591,312,574,631,548,856,912,650,888,318,838,383,203,465,625,418,7,863,8,536,299,94,810,487,944,738,773,528,327,479,965,207,815,415,656,991,732,285,125,858,7,232,5,706,595,513,413,222,26,37,587,26,336,214,678,915,260,950,24,925,870,780,184,930,630,84,615,626,44,349,436,527,89,336,273,524,697,584,50,130,842,561,267,592,487,237,493,383,762,75,917,386,132,233,487,107,258,975,730,300,399,741,650,393,237,935,530,801,755,141,593,614,20,503,271,886,553,333,522,188,635,836,752,731,412,42,946,585,333,126,758,645,719,473,201,957,801,423,567,852,840,765,564,389,186,517,11,550,354,214,161,20,832,388,987,434,625,326,544,631,76,91,651,29,21,801,726,400,27,39,272,230,912,466,46,499,642,545,141,818,378,422,152,614,714,362,634,597,651,778,148,387,208,142,796,853,363,374,721,689,796,263,52,463,925,162,558,921,946,959,646,728,750,822,183,334,581,458,791,912,73,202,788,851,647,454,577,921,567,945,383,374,497,593,932,576,152,676,378,376,13,653,166,139,918,594,448,24,863,365,666,926,749,141,184,605,92,693,80,738,246,414,480,82,721,875,906,636,421,589,502,165,641,211,705,48,982,830,270,933,827,901,810,663,614,356,488,499,435,898,456,966,815,848,247,677,442,125,417,70,604,619,633,252,774,799,44,8,157,24,866,297,382,203,866,851,477,740,52,317,247,518,753,87,121,152,904,841,899,445,570,864,460,361,126,307,720,613,493,726,781,583,90,156,860,222,829,53,972,70,214,367,970,742,451,469,137,619,929,19,394,836,904,657,102,808,870,771,525,238,285,41,634,33,700,63,439,413,564,441,514,10,527,500,315,711,635,418,126,187,105,324,406,554,240,217,832,324,31,299,643,867,252,921,824,638,245,942,736,467,262,70,789,406,656,118,321,711,632,945,282,315,89,203,131,663,753,380,837,10,867,309,35,623,666,755,166,969,204,292,921,866,215,749,579,971,960,225,275,83,702,990,403,955,648,505,340,217,518,857,566,648,618,955,790,938,557,442,603,351,691,685,40,389,224,612,166,613,51,9,969,202,160,834,651,852,849,476,436,193,836,572,966,848,507,948,868,820,434,398,828,151,334,700,346,708,873,729,218,640,131,300,964,491,615,812,551,19,167,979,748,258,436,638,805,502,332,45,335,410,591,937,195,202,985,671,415,294,635,25,624,463,540,997,622,448,758,870,120,233,960,793,213,949,965,536,596,257,118,767,700,286,868", +"263,121,762,377,85,359,233,552,146,909,292,238,774,766,493,471,691,301,626,85,554,650,356,775,140,451,222,11,638,29,356,528,878,383,421,51,309,486,834,611,776,495,511,851,614,785,76,826,584,726,807,415,295,276,222,602,883,424,37,65,300,949,39,533,124,403,215,85,855,250,449,346,275,183,719,7,755,620,519,540,319,736,404,830,520,961,512,391,833,224,87,739,427,949,703,628,924,772,486,127,481,668,223,999,71,954,535,394,698,265,866,791,132,86,544,923,832,70,977,254,49,545,440,88,570,701,847,668,905,342,768,211,491,814,741,173,474,674,651,839,622,224,355,766,280,0,895,884,467,577,178,929,230,93,436,301,576,353,539,912,254,239,264,398,220,704,278,942,233,621,649,220,447,809,874,910,638,903,706,14,994,170,385,135,330,308,99,242,555,434,477,766,635,815,193,166,268,854,266,749,837,302,925,484,683,789,987,762,704,850,582,316,195,938,170,801,553,6,370,9,183,341,99,133,207,460,444,551,722,645,181,920,906,716,311,440,383,846,350,487,661,396,489,836,951,115,992,442,717,927,647,604,58,63,575,849,722,524,630,657,306,389,496,619,787,254,46,213,621,380,788,436,424,883,472,212,188,811,777,582,540,224,262,570,779,348,662,238,452,839,335,833,565,561,867,678,391,365,457,698,858,930,905,732,130,996,904,571,751,897,790,86,760,476,956,141,769,872,420,343,221,224,304,451,27,295,332,918,303,45,287,695,694,179,843,375,688,764,354,655,667,272,651,559,328,357,305,990,968,821,771,268,554,510,311,117,349,161,913,298,368,830,752,776,951,320,189,485,24,94,708,154,501,215,455,367,189,7,853,286,749,298,21,509,233,148,997,56,598,542,838,149,32,815,917,755,71,878,459,656,991,591,801,157,971,130,410,141,1000,99,661,960,782,1000,892,1000,247,636,507,338,890,346,132,658,713,126,503,523,40,363,633,988,985,759,869,534,399,227,162,377,322,203,404,51,676,657,64,942,358,442,53,196,927,962,90,215,790,696,144,292,747,840,222,992,798,368,261,367,80,385,725,305,554,123,677,838,785,521,894,647,401,975,12,484,466,909,282,341,752,737,730,291,99,350,732,664,834,641,393,335,473,904,625,287,110,66,930,58,865,760,46,992,620,942,252,530,800,354,703,768,569,636,946,402,369,903,273,375,633,807,362,622,392,225,549,599,774,929,427,959,386,380,401,884,814,513,318,380,671,776,754,552,381,652,268,671,606,524,748,627,585,802,616,926,413,404,405,298,661,253,452,90,775,563,947,856,367,206,695,638,633,992,588,706,669,21,247,760,437,5,720,932,952,589,911,22,597,296,453,56,727,87,622,928,179,260,805,510,994,90,233,821,654,18,910,177,194,674,78,83,96,377,643,536,755,462,676,966,895,329,545,106,504,575,916,689,825,179,981,850,69,136,788,484,56,735,853,879,137,515,725,86,725,59,698,94,506,446,986,787,466,637,754,179,203,176,63,890,897,980,888,530,923,738,718,831,830,166,779,351,906,310,994,503,409,232,78,738,230,747,668,108,129,240,841,416,403,376,841,10,450,67,182,112,346,898,667,695,484,314,9,994,616,54,662,902,260,565,360,809,122,430,196,782,472,99,491,952,247,23,344,22,57,856,917,905,513,769,12,989,418,284,430,78,641,903,514,356,392,713,463,641,266,33,405,369,979,157,592,404,790,740,267,669,739,666,303,194,506,875,483,323,33,774,356,207,7,563,652,756,237,487,91,470,607,244,833,314,905,238,372,704,414,409,878,107,576,166,739,325,161,310,776,37,624,719,508,690,72,891,229,231,359,305,716,673,121,645,846,546,305,407,297,750,921,999,433,372,744,543,630,183,604,790,643,973,388,472,333,446,237,715,625,267,165,713,524,250,503,763,664,735,645,444,441,500,92,673,295,474,167,474,618,111,865,37,638,412,247,960,320,662,752,11,663,164,208,712,950,399,700,893,672,564,175,511,156,969,563,632,594,128,46,467,493,305,987,681,752,140,80,922,117,34,402,845,573,557,236,122,158,173,627,220,816,889,398,140,199,939,2,719,60,355,430,319,877,705,256,858,130,703,812,469,114,503,858,858,320,698,413,372,934,661,444,990,224,571,117,221,171,431,561,294,728,377,290,323,948,983,801,826,624,230,879,162,337,482,906,339,32,87,583,263,365,488,494,275,944,538,250,832,541,59,992,936,20,641,662,534,930,136,765,117,984,150,282,832,97,835", +"415,742,715,333,377,961,826,119,201,164,704,241,433,557,908,841,447,230,680,130,746,515,898,311,805,167,15,736,322,429,171,470,758,770,815,506,302,27,274,740,781,546,132,803,853,24,397,742,372,697,19,712,762,425,4,129,418,201,985,639,149,368,144,332,545,620,276,882,181,245,729,56,957,612,518,902,882,651,618,357,609,276,269,50,630,831,813,7,246,440,500,87,670,867,369,310,407,867,475,545,326,204,78,413,787,374,883,870,475,651,591,330,790,978,686,845,457,844,688,332,179,418,844,423,807,289,288,9,124,578,964,112,832,814,328,731,837,250,461,90,807,18,429,458,349,895,0,175,750,29,983,188,116,316,807,870,591,444,992,889,661,255,328,437,612,137,461,95,195,892,296,960,917,928,256,942,355,680,931,409,881,424,797,629,172,589,384,29,33,28,207,577,731,486,669,485,986,158,798,649,540,132,806,574,337,485,951,837,243,988,346,370,128,938,959,895,135,717,502,930,666,430,389,446,488,316,804,822,133,303,515,646,512,786,67,260,50,479,873,466,517,478,21,177,502,870,462,105,609,802,749,79,843,209,133,538,174,907,179,890,317,81,315,914,757,251,618,849,425,497,179,442,632,155,514,4,921,516,773,403,765,847,855,386,300,342,248,301,304,199,172,906,541,430,652,609,273,319,227,18,722,301,757,362,544,214,421,212,373,876,181,375,992,549,844,361,699,388,70,412,150,965,543,387,975,127,264,106,853,470,549,285,687,278,278,604,944,741,718,900,683,382,708,60,976,901,505,369,680,962,879,594,528,295,389,889,272,299,327,886,130,990,995,752,918,467,658,74,495,966,566,45,750,548,175,95,948,835,910,931,57,529,341,512,286,929,592,745,968,287,723,74,168,468,379,694,742,358,567,755,443,142,807,677,126,536,538,530,222,141,688,80,76,760,50,640,786,325,125,26,335,651,258,167,899,160,760,264,290,630,365,880,204,292,290,685,546,434,965,826,472,564,148,860,69,418,123,782,515,86,650,82,191,625,550,609,139,242,330,4,215,789,413,491,611,112,58,818,711,658,922,351,477,422,409,640,940,817,884,150,410,270,372,77,123,626,862,20,710,317,487,613,296,62,52,271,18,539,43,563,752,44,63,325,904,915,898,481,163,76,653,728,962,539,769,510,257,10,788,985,774,888,576,760,675,9,670,9,842,691,467,153,825,903,696,73,159,405,177,215,749,5,99,881,771,322,4,859,606,624,29,948,992,796,348,357,320,170,60,136,408,142,741,500,838,79,334,305,301,190,175,17,893,696,564,420,468,677,16,918,889,618,238,484,862,690,349,488,132,975,454,706,54,246,205,817,400,426,230,981,561,157,343,929,551,869,375,811,82,98,81,477,588,215,824,16,387,891,812,595,56,952,909,292,613,453,561,983,991,516,43,766,727,659,625,724,934,934,582,542,979,713,569,33,797,816,466,112,361,534,764,654,864,186,512,687,290,700,726,348,959,227,142,785,197,320,376,521,81,745,573,570,813,414,906,986,538,498,628,400,414,693,294,146,711,384,951,335,564,714,583,236,418,864,775,551,541,112,190,994,406,772,138,667,207,994,204,570,419,410,209,80,252,718,519,59,933,432,123,639,762,702,125,498,742,212,570,230,767,796,427,296,680,488,978,200,445,663,152,395,661,998,116,470,204,113,866,533,119,310,872,477,991,852,735,250,84,730,890,899,305,864,779,368,570,814,984,587,820,868,912,805,241,930,510,647,951,144,595,121,610,609,22,961,538,625,71,854,779,838,443,580,329,76,769,458,337,642,614,185,397,327,762,373,901,362,180,283,875,286,591,378,98,49,557,95,114,851,819,873,664,738,506,369,683,241,329,28,216,378,257,468,719,445,406,748,76,195,167,398,115,142,93,358,162,163,175,64,926,693,227,336,42,424,43,579,631,366,458,10,240,688,978,557,862,580,58,95,248,529,347,701,191,104,243,828,591,344,85,221,537,496,818,453,850,36,730,62,695,945,475,366,642,493,332,615,759,440,228,205,507,948,277,304,364,317,775,175,208,242,196,177,382,239,384,977,49,861,163,83,881,263,45,847,993,811,98,599,38,372,922,109,524,255,362,958,404,1,667,933,585,855,682,913,324,509,577,167,893,570,433,727,636,557,400,396,277,449,404,118,334,393,881,860,652,199,188,771,627,264,759,395,676,339,664,529,424,372,35,587,609,32,503,353,768,909,920,187,792,794,312,478,348,206,732,7,629,111,126,99", +"961,378,496,839,546,319,245,960,407,816,596,242,108,208,733,909,74,373,535,39,643,2,23,963,679,72,167,489,717,127,899,403,237,18,548,48,913,919,600,167,703,589,303,469,584,180,674,536,906,517,112,408,274,432,602,131,93,63,213,161,830,667,290,878,585,459,420,951,534,321,921,795,745,818,691,211,336,664,697,706,975,860,780,767,114,91,908,947,618,217,673,363,801,287,109,944,125,584,521,189,481,839,822,858,324,449,553,357,444,653,719,115,328,540,581,832,561,952,179,271,504,663,72,611,108,364,641,595,842,178,297,379,411,108,342,570,698,210,70,742,872,943,3,641,302,884,175,0,394,34,634,173,564,256,603,255,767,381,672,971,116,994,782,715,168,710,459,29,719,469,894,808,590,477,140,281,477,452,327,602,228,927,942,746,922,815,928,695,394,57,670,103,610,282,228,503,263,961,738,443,814,234,556,544,86,390,40,734,394,635,624,888,966,967,203,67,473,795,901,888,695,525,949,677,257,21,387,322,446,753,727,249,43,699,886,33,916,179,210,416,521,390,708,916,194,106,379,361,146,943,226,302,280,188,212,729,613,170,697,328,230,266,411,288,607,17,230,613,350,357,988,666,49,958,940,157,330,772,782,900,535,462,460,214,418,993,961,932,707,427,757,326,232,26,639,275,567,586,301,221,918,573,809,316,928,421,832,223,871,860,620,297,285,652,817,194,631,9,810,197,865,495,172,107,274,250,143,357,361,36,332,495,347,63,94,409,244,64,759,55,420,728,451,333,855,216,253,346,955,730,19,833,865,635,380,501,488,691,759,910,702,355,277,105,281,382,932,710,821,901,343,936,381,898,515,394,448,736,448,818,30,59,53,86,423,425,820,469,494,342,206,841,6,269,257,291,240,471,808,391,91,612,206,893,217,399,976,391,159,619,394,17,303,337,931,697,948,870,648,136,238,126,36,153,625,985,205,893,227,265,332,952,158,696,835,83,919,920,214,291,79,441,697,502,414,45,892,207,156,778,145,142,187,640,529,541,293,210,715,698,673,840,187,15,658,802,313,729,261,830,838,278,230,4,227,870,605,889,581,347,390,749,136,530,38,630,195,115,691,279,971,767,759,910,894,582,903,571,866,279,478,290,537,944,667,466,432,528,571,436,119,68,987,107,844,307,17,598,658,909,884,10,981,159,883,139,994,462,401,103,102,136,616,520,505,483,150,969,979,736,742,40,225,80,807,922,38,982,523,780,833,95,77,900,617,813,995,865,551,698,317,657,181,680,213,821,341,314,591,738,582,565,787,157,337,615,933,409,620,553,648,867,491,679,814,575,706,358,789,694,194,190,744,257,347,676,855,392,450,90,491,438,260,959,483,107,792,459,46,739,291,115,948,915,553,305,614,663,978,414,776,467,661,788,902,774,887,854,975,54,964,937,291,286,84,41,669,151,717,199,688,989,221,662,280,85,249,203,639,429,137,206,66,536,143,438,761,633,697,16,705,279,313,799,326,157,961,988,527,540,274,967,900,615,613,945,665,97,62,404,454,578,436,675,88,474,354,291,722,933,20,186,853,717,906,883,177,146,676,532,94,846,933,910,529,634,431,1000,29,941,368,896,633,115,863,787,309,916,7,156,359,619,977,831,568,842,203,324,302,263,369,118,639,186,428,976,359,628,140,827,707,122,568,490,709,655,436,819,683,518,339,448,197,676,917,65,572,531,88,991,597,553,493,845,840,269,619,626,405,505,852,702,580,164,348,118,123,599,359,439,263,987,341,777,190,699,263,905,44,548,560,458,280,979,296,353,760,891,674,596,93,297,998,913,12,336,466,235,346,157,390,493,607,561,796,455,633,788,77,628,156,73,633,114,278,17,113,730,70,738,759,574,104,706,942,693,174,219,831,785,264,71,229,860,469,700,971,395,826,142,228,150,229,681,997,433,485,954,618,61,725,352,5,565,295,119,443,387,641,567,251,375,753,932,870,639,942,783,457,771,507,721,261,522,356,15,578,674,352,231,145,690,800,534,910,343,807,780,233,504,367,49,302,521,130,804,98,629,599,22,800,766,248,766,810,559,262,878,252,183,120,284,594,281,570,420,118,67,608,515,372,361,778,390,646,213,915,928,991,72,129,172,488,268,324,365,896,983,26,698,185,146,751,931,271,343,256,217,169,756,577,957,421,292,719,538,741,970,992,731,933,563,54,762,606,353,744,344,735,789,631,346,976,925,25,820,515,898,264,325,725,938,942,696,580,265,449,917,172,147", +"56,816,442,570,260,674,408,292,364,460,371,389,677,680,864,306,46,437,14,581,333,397,769,388,173,907,315,173,812,938,782,605,217,751,727,218,697,494,583,875,436,468,647,285,924,286,603,995,718,785,328,429,309,548,637,817,293,28,796,24,710,36,302,185,979,175,388,22,44,769,834,6,29,109,837,16,656,802,227,542,313,918,824,426,343,344,911,405,58,274,719,794,832,76,733,157,221,973,128,28,880,915,880,248,116,792,125,174,413,514,252,607,326,645,970,411,236,171,291,223,884,525,577,237,902,164,129,209,97,628,649,169,961,402,958,221,508,786,834,567,708,809,166,400,448,467,750,394,0,58,373,558,146,141,899,379,805,868,404,349,749,813,976,903,799,301,741,994,915,33,743,909,423,786,362,897,587,768,937,271,421,88,878,260,218,665,514,118,847,333,418,617,962,571,537,168,719,941,103,432,886,724,929,713,74,376,732,561,81,31,741,143,266,799,953,605,967,39,888,478,767,511,150,337,92,656,446,469,266,657,798,788,922,942,772,596,637,110,143,741,914,508,737,642,396,945,91,637,684,468,800,974,767,789,969,794,349,102,387,366,816,632,763,767,381,331,152,246,74,111,948,200,495,748,867,411,900,617,138,243,822,733,933,100,737,968,795,76,648,657,989,892,639,451,714,583,31,874,343,596,918,450,749,458,390,198,255,774,105,182,458,729,747,661,990,606,936,182,770,24,694,24,781,776,407,609,677,544,275,885,657,19,146,62,779,929,289,161,986,41,617,693,997,452,168,921,131,760,867,189,171,872,675,164,293,33,115,682,327,566,592,332,760,923,249,372,906,787,196,320,856,875,280,727,806,550,974,360,108,92,178,332,420,548,217,137,955,605,697,968,999,732,442,693,515,950,933,919,412,451,69,248,453,667,737,294,241,54,799,816,736,767,34,256,414,71,941,756,773,329,201,124,654,903,349,14,315,102,386,807,483,280,839,348,705,130,6,518,776,123,265,637,736,987,203,42,175,707,949,935,827,375,858,996,426,192,162,278,943,241,676,763,916,979,532,616,291,813,854,918,200,631,4,437,236,677,490,297,233,442,978,822,158,108,74,72,411,25,373,463,100,619,826,103,714,424,420,930,503,347,251,595,157,640,985,630,804,675,934,900,781,770,874,422,787,550,210,537,604,306,229,598,385,635,672,131,800,382,285,994,710,30,368,240,553,320,809,956,734,833,517,176,974,97,491,956,9,669,313,632,923,37,511,441,453,131,91,779,164,299,506,5,786,993,775,768,169,588,738,930,83,82,129,399,126,665,274,739,540,979,584,110,552,826,103,205,137,927,758,771,656,872,745,504,649,968,395,679,447,775,572,616,301,223,764,253,986,415,109,46,595,548,675,679,74,949,457,308,457,36,439,231,897,793,968,894,528,63,900,406,920,994,815,155,916,296,416,91,937,325,240,465,180,315,606,869,442,818,725,889,157,569,974,8,860,21,670,503,94,147,527,565,960,968,284,660,678,438,524,720,862,5,754,811,991,655,323,184,637,401,349,644,367,14,50,885,87,285,299,684,685,107,830,283,179,530,662,390,712,696,975,505,373,69,601,74,912,286,52,160,272,364,813,302,68,758,168,77,611,399,958,271,409,454,539,377,765,503,927,840,45,35,195,303,514,232,810,700,367,248,592,592,162,302,227,95,584,958,468,615,375,234,105,542,530,842,640,128,553,307,778,95,605,18,527,133,623,806,890,622,764,949,95,65,652,901,680,231,549,948,902,143,763,207,299,941,690,770,416,206,288,266,843,624,222,360,256,202,780,788,261,823,55,67,600,792,167,649,772,380,373,954,38,635,772,609,798,58,231,469,311,928,159,641,2,630,764,567,256,217,8,447,887,908,746,444,463,549,504,672,387,762,353,413,499,56,926,980,766,94,660,903,479,92,305,990,567,291,596,508,115,939,615,300,538,50,54,675,337,371,91,923,269,634,450,288,401,184,943,420,897,839,335,613,655,936,199,82,122,407,496,550,909,683,45,671,245,385,158,245,791,779,281,52,202,599,629,236,678,69,388,552,158,149,161,694,336,721,196,908,673,220,84,259,399,233,488,833,178,761,375,260,443,247,815,988,843,701,887,989,375,128,997,516,337,566,498,909,822,815,264,59,243,947,222,921,325,471,454,434,170,417,725,308,639,147,705,105,993,795,610,476,841,733,367,431,458,810,325,161,13,906,549,476,841,509,345,549,983,880,141,91,474,957,905,711,276,351,170,224", +"755,616,11,636,736,229,345,334,388,891,828,35,398,979,180,185,598,17,267,475,448,983,409,678,582,497,733,399,351,920,944,897,361,115,276,753,22,798,59,997,557,965,83,307,581,790,216,996,155,256,276,201,541,741,568,634,501,360,699,853,577,339,797,603,27,227,226,596,845,251,698,286,202,680,800,12,927,575,238,899,667,520,109,8,309,685,978,461,490,977,660,210,487,976,707,712,149,464,244,556,198,125,237,423,796,616,445,453,771,236,973,169,935,975,535,368,544,278,489,400,110,399,847,35,239,257,580,470,221,81,838,714,574,165,951,121,369,444,674,459,650,208,141,831,648,577,29,34,58,0,570,306,342,369,497,748,914,766,767,883,184,458,652,530,497,156,820,900,545,348,527,180,164,684,541,841,434,56,512,407,853,999,745,246,634,19,571,627,691,541,814,419,950,360,457,448,965,50,757,113,836,76,324,660,516,346,239,363,354,51,895,607,891,325,113,258,668,92,910,498,136,196,17,521,497,544,864,572,235,251,808,928,41,547,483,575,558,542,891,163,555,687,995,139,897,146,695,940,679,881,208,98,732,495,891,129,796,289,682,388,901,521,719,153,114,404,59,690,509,855,419,496,12,444,39,228,410,366,443,205,4,523,367,867,747,79,534,172,603,235,934,396,487,208,968,619,148,241,110,148,821,836,176,249,397,429,30,834,865,54,143,523,368,26,31,568,374,607,617,44,319,288,441,319,81,486,906,217,469,439,195,922,799,965,80,232,126,120,12,388,334,304,930,748,545,647,329,170,664,374,173,880,616,693,48,882,610,573,586,981,342,261,928,330,729,855,17,813,865,829,894,932,467,402,802,952,712,962,847,548,379,824,955,376,840,740,489,296,807,513,973,50,138,629,973,793,431,183,798,598,950,332,583,536,444,220,891,393,720,111,823,113,676,955,870,708,539,77,266,350,970,451,300,821,250,684,538,562,268,150,244,898,426,336,712,764,303,86,267,663,299,227,261,591,827,290,699,784,185,101,621,677,779,427,591,202,221,565,615,367,536,809,672,968,524,207,738,576,374,21,610,439,590,983,522,254,665,507,995,62,882,214,605,266,241,862,32,879,589,993,382,454,240,987,924,695,735,100,871,63,630,764,895,839,285,142,161,900,775,226,28,134,909,485,503,192,568,895,407,650,406,371,105,848,759,441,426,365,446,220,607,954,279,290,947,379,828,811,227,992,645,425,852,640,525,112,35,107,970,654,429,649,582,957,797,478,194,120,878,477,167,587,237,2,427,604,743,814,564,84,473,195,967,688,700,17,258,962,182,198,276,342,219,770,44,163,266,397,625,386,675,444,123,264,56,646,907,351,737,185,340,152,913,390,75,165,315,14,903,645,232,465,606,280,880,615,192,464,497,305,493,487,255,450,569,874,366,735,841,64,80,300,671,556,262,46,484,420,929,836,573,632,287,749,629,782,86,682,777,399,25,498,715,146,932,560,629,379,163,779,707,31,535,101,225,266,780,142,309,717,180,17,271,435,453,969,338,228,16,467,831,47,802,394,396,666,71,267,771,949,413,312,314,856,368,790,81,370,144,896,923,42,316,242,223,121,860,497,398,809,2,723,322,968,312,437,657,508,273,293,938,581,879,110,807,468,808,946,85,679,317,231,517,103,319,292,782,550,28,447,12,967,27,520,232,24,125,728,314,804,178,345,376,901,254,792,227,517,358,959,243,886,264,910,86,781,620,87,251,462,405,45,422,388,387,413,586,491,784,796,178,508,806,48,908,425,643,562,748,512,140,633,901,437,361,741,525,698,122,183,72,993,151,38,56,447,324,518,710,156,475,616,604,905,502,621,735,671,392,750,525,282,64,136,261,333,839,674,221,420,327,497,100,136,680,84,227,367,967,588,966,4,716,496,27,830,377,768,234,197,624,609,810,586,160,261,848,581,184,796,244,939,892,834,861,403,215,23,102,800,953,401,570,174,790,363,451,145,832,779,89,455,822,809,779,303,920,901,581,171,995,555,258,173,69,419,743,325,443,638,917,73,414,975,558,823,464,623,299,7,743,993,49,950,119,139,608,48,456,954,395,761,951,477,916,4,145,535,168,7,324,880,138,527,137,638,641,124,99,128,243,801,926,263,254,163,510,980,615,573,563,480,362,35,105,441,602,601,616,197,853,211,71,12,744,294,248,172,252,574,831,849,299,605,274,599,896,210,273,156,10,705,76,729,559,31,415,111,826,222,748,925,178,641,999,93,524,509,503,600", +"616,307,113,296,21,245,736,973,855,999,238,682,220,556,164,587,475,381,211,889,739,215,399,497,29,670,156,499,276,758,520,850,815,540,442,295,793,244,274,60,48,937,686,790,589,673,723,737,204,652,290,238,51,799,820,212,496,937,547,336,574,692,837,400,122,52,346,268,679,204,735,766,592,765,928,544,933,681,738,424,904,380,720,225,366,913,870,225,216,287,177,586,893,773,527,315,642,554,885,849,630,365,124,9,371,253,826,657,597,332,199,884,810,238,195,89,400,988,634,457,481,490,938,622,444,423,47,701,369,484,340,459,551,866,631,834,431,447,322,333,242,35,25,864,272,178,983,634,373,570,0,383,751,268,898,485,281,371,874,492,739,512,372,100,918,266,184,422,710,796,183,578,107,21,290,868,934,987,978,305,366,629,305,615,791,949,79,988,215,727,245,574,373,544,95,651,32,83,355,42,200,538,527,493,222,325,560,159,33,850,283,464,865,364,734,502,275,643,251,482,639,759,663,539,85,71,875,490,969,81,875,731,246,598,548,958,879,132,994,145,452,404,991,939,50,144,500,162,527,957,384,268,647,106,810,257,740,527,624,860,115,320,95,951,56,849,589,690,557,696,684,579,607,747,510,810,375,272,627,378,20,978,953,240,178,691,199,534,408,767,265,642,339,638,620,341,747,349,682,72,441,313,236,478,698,347,969,770,220,18,509,992,515,688,372,103,336,683,856,312,3,851,570,684,874,998,948,597,240,944,542,886,248,67,707,638,273,848,261,952,405,346,983,272,339,848,621,933,288,945,515,806,423,343,460,147,76,400,505,138,953,903,734,559,351,685,730,340,122,207,851,953,661,803,620,743,990,601,165,236,360,253,668,691,851,53,174,66,719,611,217,245,455,171,898,318,300,983,873,797,207,931,155,588,738,674,876,678,845,548,256,388,106,279,295,417,703,740,259,530,995,154,628,867,265,941,967,51,322,842,824,845,842,100,218,426,469,592,600,560,129,221,907,78,979,52,739,193,398,87,919,621,226,45,399,763,604,408,719,684,902,563,862,423,753,995,516,360,713,947,257,228,402,633,866,685,264,44,600,327,712,176,872,356,425,104,636,545,204,236,286,537,307,941,156,923,397,214,948,492,488,869,503,791,293,219,859,895,129,145,79,990,272,892,624,466,892,686,968,716,766,156,355,477,740,150,243,932,900,804,502,136,165,466,212,147,123,276,715,619,764,862,339,757,127,836,546,329,351,389,231,148,385,634,492,611,94,338,637,966,14,326,362,810,471,68,720,186,154,75,895,477,28,723,841,907,197,367,410,184,17,527,660,715,166,251,962,459,303,807,893,984,391,59,208,58,216,458,87,441,570,78,592,840,600,616,269,20,763,313,110,642,485,674,121,370,598,937,498,262,303,126,971,799,31,902,575,43,550,366,462,945,324,232,852,819,304,101,653,237,859,287,667,140,498,455,255,646,173,545,389,923,213,393,69,475,949,288,375,285,945,622,625,580,904,77,422,198,907,780,85,879,857,965,762,590,381,551,65,213,958,732,248,120,196,930,409,983,674,92,282,838,570,61,20,318,47,927,138,456,393,14,883,79,469,196,98,647,81,762,455,857,203,496,359,172,636,425,727,781,33,594,231,787,594,855,59,287,151,747,279,132,486,705,113,294,355,469,996,498,648,30,731,577,266,57,834,923,647,680,540,203,803,860,623,625,295,230,223,229,742,369,181,690,815,941,190,756,599,102,563,205,351,678,13,734,322,964,829,853,103,851,539,498,864,765,610,872,40,144,325,949,493,457,574,522,544,714,342,648,319,9,802,184,939,814,867,942,800,479,427,153,727,136,132,914,659,871,407,400,733,569,469,707,276,252,943,76,420,845,259,490,617,292,71,862,47,530,523,22,821,487,295,236,792,661,126,686,510,522,917,76,40,877,699,558,455,211,884,781,227,515,519,642,988,178,620,463,134,364,854,280,162,745,803,395,565,984,335,523,68,460,722,347,898,18,874,727,592,568,226,189,904,974,472,838,587,903,768,247,610,890,33,261,388,433,284,937,633,81,311,947,947,774,575,143,654,606,744,284,997,863,53,485,199,172,982,411,98,833,402,986,81,946,103,171,646,195,19,811,18,189,599,722,312,429,808,228,173,622,65,187,114,418,53,809,191,765,418,62,444,709,706,671,706,52,778,522,2,152,926,594,824,957,485,476,468,641,528,605,235,687,882,103,219,770,476,170,936,341,618,768,655,806,835,59,665,136,486,328", +"27,115,751,301,40,848,303,949,747,294,415,165,984,753,932,609,183,273,999,658,558,159,616,446,752,26,181,643,920,980,879,649,825,947,868,134,154,93,801,217,252,975,152,998,775,665,812,952,894,395,835,389,993,695,754,145,73,218,279,434,535,374,442,543,245,173,586,18,64,226,555,47,464,737,104,311,610,567,910,164,919,659,457,12,305,515,556,927,719,830,498,706,679,269,868,84,465,781,968,834,994,38,668,705,997,658,672,843,954,602,687,305,37,567,122,940,734,919,494,387,559,972,547,210,302,309,781,915,151,353,572,803,988,195,134,29,734,977,907,780,242,528,659,772,151,929,188,173,558,306,383,0,516,490,109,547,469,445,852,514,696,87,305,780,471,514,219,823,918,345,968,771,782,333,269,754,934,301,101,866,110,18,988,780,136,364,207,816,478,465,183,760,912,964,85,738,79,903,662,751,232,736,422,714,836,610,77,144,864,17,891,63,944,293,412,437,487,862,842,300,116,534,726,895,371,617,961,440,149,838,84,570,706,4,756,557,785,121,6,861,378,502,686,616,507,356,715,983,1,997,667,99,869,109,402,846,978,437,954,302,337,898,301,76,695,626,70,162,635,300,164,303,755,310,62,426,298,232,643,300,419,254,200,305,862,628,946,862,787,471,924,752,296,718,366,856,675,145,283,282,563,966,765,409,768,927,863,673,621,58,910,355,323,246,368,774,610,766,850,981,769,465,776,461,433,794,466,798,922,62,170,681,649,933,210,558,171,887,421,231,663,799,490,867,55,915,958,646,849,97,130,836,697,733,619,126,207,224,438,738,272,724,442,244,45,82,426,61,729,370,570,434,936,537,519,357,906,367,805,814,557,229,660,968,70,530,184,845,473,78,559,839,71,637,500,173,506,824,399,969,764,551,654,679,109,847,257,366,392,159,267,110,46,662,571,833,786,475,758,353,696,424,696,615,61,878,328,685,255,529,58,94,804,785,96,53,747,409,41,284,330,391,187,24,843,359,593,862,377,988,348,968,818,571,455,57,894,439,262,65,194,407,538,344,186,593,93,737,234,299,97,608,947,182,204,504,603,394,911,614,137,977,666,975,768,146,438,412,774,203,499,640,862,585,228,636,938,892,607,337,721,353,998,186,20,639,51,446,641,747,425,819,574,228,801,889,888,145,270,217,381,247,844,176,323,249,494,516,431,969,324,173,50,302,826,99,603,633,352,585,394,535,410,377,562,13,212,669,948,33,85,131,758,619,249,375,153,351,260,348,26,290,288,437,64,718,283,548,435,190,989,104,388,895,749,961,490,97,927,656,830,204,854,165,489,810,510,530,269,142,765,34,70,400,409,878,949,65,1000,290,747,921,59,555,339,974,739,765,159,811,227,141,500,431,336,779,145,224,888,621,954,254,188,603,555,903,180,70,551,482,559,500,843,520,866,791,66,330,743,909,232,34,116,227,132,832,549,698,676,368,194,526,830,171,16,613,983,92,410,607,316,962,7,129,454,918,602,551,504,99,702,634,899,788,549,450,732,801,463,737,326,211,331,300,565,370,383,205,819,925,145,851,34,410,280,432,319,827,229,970,102,567,700,853,683,82,608,101,392,351,862,628,133,95,877,822,252,334,240,312,627,103,298,996,344,693,152,218,228,784,760,967,54,891,57,392,318,51,736,219,573,890,88,974,137,983,542,433,606,728,745,187,84,977,239,67,71,124,246,106,219,871,868,529,817,186,121,654,922,602,989,33,643,721,35,158,543,483,717,744,113,86,604,490,615,9,4,632,281,96,467,354,302,785,37,55,158,705,921,29,861,433,776,531,17,675,278,394,157,262,389,170,227,505,794,743,679,195,48,447,996,136,438,14,858,683,235,862,385,320,418,915,161,401,77,763,294,998,757,342,199,308,980,482,247,9,859,191,735,933,732,756,31,477,520,374,288,400,772,63,243,208,777,856,680,166,626,326,344,342,68,454,652,742,867,964,620,75,163,366,720,876,840,885,103,324,201,139,378,313,794,986,728,893,485,487,290,251,647,504,490,494,180,328,280,37,699,985,952,778,901,285,575,337,752,426,702,486,969,169,232,151,558,886,40,296,887,733,182,600,715,753,972,560,895,272,592,412,863,194,678,164,95,409,246,21,333,408,209,140,859,384,612,716,714,827,848,989,299,935,748,894,994,239,542,805,490,588,839,207,888,165,417,473,13,92,792,614,659,39,438,673,379,669,977,125,853,250,941,51,311,605,940,620,868,941,65,950,665,457", +"186,492,888,947,309,181,16,25,933,884,730,872,888,93,363,154,584,792,598,193,711,491,160,71,740,554,757,448,717,985,739,213,378,373,760,349,909,879,337,332,480,150,979,121,168,709,155,156,159,425,365,936,438,227,257,381,657,699,897,858,923,513,90,798,84,37,186,999,540,48,51,120,668,440,933,794,245,865,690,153,297,122,216,123,489,485,733,37,673,977,469,560,538,507,632,839,261,236,408,54,112,128,38,743,633,538,609,427,511,74,688,69,723,399,107,971,744,695,535,570,697,261,10,741,582,899,15,234,316,972,122,919,255,798,278,658,504,479,358,36,119,659,435,332,764,230,116,564,146,342,751,516,0,110,771,723,429,472,584,883,934,724,997,793,527,939,577,482,995,318,888,110,188,75,493,537,679,365,902,42,957,987,153,835,218,772,291,565,568,294,331,696,461,31,231,491,220,518,602,656,740,594,222,355,484,637,66,535,867,891,615,701,267,478,218,309,218,942,269,592,294,137,268,277,903,123,906,278,193,759,834,243,136,903,44,485,888,418,170,736,197,958,171,475,729,43,162,292,917,127,382,335,170,740,836,196,787,840,994,241,486,23,93,687,183,673,208,328,224,63,122,490,516,51,627,105,290,46,861,295,399,456,179,153,810,921,408,554,876,512,461,10,289,521,427,94,837,506,385,693,583,850,60,175,512,865,59,791,229,724,151,163,991,685,826,1000,992,541,244,361,952,165,875,207,386,639,972,759,246,355,714,92,191,917,104,244,921,834,91,496,764,429,850,711,672,551,252,819,786,46,410,605,791,590,696,326,302,700,130,699,55,174,477,401,53,731,551,285,869,31,201,359,666,419,126,553,955,189,535,476,435,558,931,103,300,586,837,138,109,553,594,494,312,764,226,31,27,453,444,225,135,413,796,185,20,750,656,235,186,380,777,868,960,614,342,534,896,766,454,172,565,648,757,796,986,361,871,692,582,467,663,521,232,429,477,679,273,454,903,219,812,559,848,117,865,963,899,238,644,769,777,113,739,45,95,692,461,713,867,930,263,47,62,524,784,86,495,998,571,144,44,611,907,815,993,89,370,205,70,731,310,659,556,128,676,215,381,62,983,418,937,82,521,124,654,677,713,149,184,6,540,176,728,993,591,897,318,7,918,524,657,768,772,176,626,123,79,295,502,811,739,552,281,338,664,728,345,579,671,975,95,245,559,920,90,187,358,330,272,883,927,532,506,797,2,758,786,210,46,343,137,967,989,484,190,825,627,428,524,476,498,455,71,946,546,428,966,292,649,973,953,220,635,669,257,764,404,243,577,960,807,511,883,333,623,51,89,673,314,446,23,367,361,784,102,893,358,888,905,886,912,881,87,133,288,479,972,259,700,756,576,262,963,945,886,901,505,786,666,915,699,430,38,965,499,284,86,45,980,330,652,366,474,978,402,975,196,365,768,825,584,147,31,355,196,369,119,122,142,419,884,283,357,744,477,542,686,492,529,188,457,665,134,592,413,492,675,5,39,76,173,842,791,532,451,840,329,860,394,9,537,128,836,327,727,677,912,714,656,273,80,513,53,690,614,123,267,756,802,998,47,890,907,196,750,739,491,610,469,100,520,405,719,384,9,208,360,139,810,133,314,766,132,786,97,58,580,183,973,455,428,4,884,325,944,331,729,573,965,394,629,129,455,861,320,626,261,854,943,508,462,717,686,37,38,150,860,768,382,437,170,813,263,399,693,585,584,221,116,857,670,711,388,281,341,827,674,46,223,156,170,685,8,517,880,237,48,504,57,485,530,620,758,239,499,371,811,910,150,731,15,104,52,731,364,205,681,608,474,469,354,202,770,667,348,728,901,492,69,147,194,428,92,135,853,111,325,505,69,557,664,935,356,145,511,269,831,444,882,842,888,955,222,872,526,148,398,407,835,150,146,653,967,382,396,600,369,661,530,166,440,210,21,11,558,909,114,694,235,125,271,257,774,416,612,182,595,251,298,689,868,529,382,774,183,808,775,440,135,952,42,994,456,604,823,49,856,546,388,107,199,26,585,632,772,349,232,807,508,289,477,611,927,477,332,199,706,187,964,229,11,508,159,609,772,692,123,35,877,714,900,751,63,985,493,406,854,915,776,669,42,541,595,365,291,448,28,447,659,259,445,570,127,182,272,650,646,783,878,380,871,477,133,165,643,409,734,898,604,770,331,217,168,591,422,958,232,779,64,650,214,996,68,296,892,556,317,326,701,786,955,893,601,77,694,353,866,205,578,211", +"63,646,803,552,74,394,576,417,882,228,183,22,47,468,9,477,339,586,403,73,219,289,32,675,130,396,221,62,746,236,626,694,109,96,993,94,879,520,696,319,451,609,611,535,642,70,343,899,771,136,933,144,683,197,474,957,924,972,451,166,772,388,54,232,376,67,560,466,917,510,223,418,705,406,564,113,696,644,474,177,126,674,414,68,724,125,655,385,841,352,718,315,31,986,724,487,49,610,640,187,894,978,97,252,600,550,887,909,467,349,180,965,929,613,455,920,26,119,330,38,740,605,406,204,713,608,577,747,4,451,939,840,101,151,865,994,626,258,748,397,813,158,371,761,487,93,316,256,141,369,268,490,110,0,473,618,329,340,703,856,217,716,692,697,104,182,422,927,706,320,542,412,786,536,657,428,875,810,759,253,145,88,244,960,928,247,867,134,819,842,113,196,482,10,682,84,877,48,203,245,77,973,840,425,357,844,100,605,838,175,722,680,206,873,979,972,166,152,593,271,538,108,451,991,267,232,590,608,152,171,528,39,442,657,251,404,864,694,756,635,170,337,610,684,758,382,367,19,72,824,701,55,922,293,820,494,308,351,234,755,494,640,240,513,417,856,597,423,408,955,48,475,444,223,727,382,464,667,830,363,805,439,949,208,973,574,326,670,116,150,373,577,772,457,426,79,514,554,482,494,727,274,412,648,481,111,630,869,681,17,992,233,763,752,8,424,839,477,866,943,569,954,126,209,364,48,859,474,205,637,911,907,939,962,502,36,51,305,347,623,116,144,996,705,582,379,132,843,98,23,540,468,420,797,107,847,105,702,92,990,544,767,979,775,674,716,852,493,382,823,298,539,16,57,284,317,11,67,824,680,562,483,594,932,388,297,892,127,915,584,589,993,527,128,712,570,630,353,448,96,131,388,872,138,214,725,454,169,693,607,355,772,560,508,90,903,60,546,69,470,74,912,579,157,587,480,36,34,839,796,695,355,12,446,387,804,756,747,633,971,967,687,866,947,376,756,522,411,92,163,903,7,657,877,544,209,35,86,327,456,209,353,271,789,255,712,561,323,248,987,593,765,536,489,942,619,954,644,756,891,64,395,917,757,350,90,249,219,51,265,353,462,940,416,378,381,931,245,212,590,547,798,542,258,739,259,115,910,304,280,667,652,22,730,785,134,922,709,588,65,408,30,581,864,721,895,880,934,77,811,640,846,94,859,92,190,729,188,676,94,848,506,283,380,542,752,510,937,6,14,46,283,366,540,861,234,605,696,133,199,198,134,326,198,968,363,922,84,888,202,963,608,413,553,41,234,838,473,455,414,492,619,793,290,521,793,35,3,359,257,679,224,281,639,23,541,864,215,19,150,366,222,918,543,958,492,899,672,389,742,783,448,203,198,800,888,773,808,3,680,400,196,888,428,626,26,613,674,513,102,604,811,763,833,941,598,942,464,737,482,36,270,98,680,800,604,492,989,649,642,244,907,995,24,259,412,224,825,853,971,189,126,167,875,486,11,537,227,227,493,831,267,428,238,299,661,616,823,405,752,822,636,727,44,609,727,246,177,376,740,614,131,707,281,138,919,571,42,328,411,792,311,787,803,765,598,388,208,468,352,122,600,602,190,855,417,19,371,275,819,644,619,361,194,915,16,543,818,453,400,758,475,263,860,774,410,782,561,134,918,860,365,73,550,22,337,569,454,273,583,90,643,680,659,987,167,724,357,122,918,253,631,216,626,749,894,674,954,508,837,159,892,448,790,559,956,460,161,908,183,412,158,371,774,570,640,533,811,926,487,283,225,855,269,958,559,136,42,611,473,270,760,459,943,408,795,801,992,840,356,517,724,250,704,373,953,931,871,275,290,522,23,437,236,825,755,305,712,243,552,11,150,601,564,238,349,848,959,56,735,55,867,196,229,466,162,844,925,23,713,690,420,38,243,995,5,41,733,441,768,731,664,488,982,491,788,899,763,518,3,826,346,59,126,522,729,89,611,505,16,994,918,23,317,720,723,256,355,277,33,712,174,313,740,122,929,497,86,279,109,384,179,632,421,194,629,892,544,584,701,782,763,604,512,358,939,583,460,914,227,42,869,361,229,895,82,227,988,68,37,73,196,562,927,622,854,640,902,496,662,800,728,843,646,353,866,874,661,92,865,752,454,334,998,746,104,327,882,40,281,908,897,154,446,829,633,774,592,243,735,919,577,805,606,961,309,398,949,286,490,886,292,224,119,475,450,681,397,871,304,838,115,370,914,629,387,47,564,917,453", +"247,831,934,920,164,165,212,447,213,991,660,102,459,788,638,303,356,494,838,80,235,799,764,468,624,308,494,673,603,44,23,683,243,307,937,682,341,994,65,501,388,880,650,249,427,434,514,126,714,977,889,993,949,291,817,726,144,478,613,199,253,14,514,325,727,190,598,681,551,978,567,367,665,19,713,835,460,862,698,320,29,457,341,208,736,390,310,126,974,372,124,605,557,420,443,916,494,403,151,523,678,923,296,393,17,129,898,87,308,623,830,877,542,851,570,581,91,909,561,327,69,106,868,564,297,525,98,74,371,695,84,240,56,541,556,987,141,403,1,781,133,264,389,540,946,436,807,603,899,497,898,109,771,473,0,302,599,779,287,837,470,117,732,655,447,728,951,630,957,815,939,334,339,716,558,882,524,697,49,163,257,584,100,28,700,975,535,512,649,622,314,89,291,859,185,118,19,701,299,804,25,475,586,744,241,11,6,342,32,728,56,649,60,833,429,350,846,607,392,198,602,166,541,588,210,710,597,920,5,300,809,265,674,347,162,443,575,791,65,746,666,540,829,39,716,136,605,246,386,924,763,822,295,592,751,51,169,168,405,722,357,411,3,226,355,424,233,61,980,671,753,321,986,904,203,124,524,904,518,244,86,781,894,29,502,128,932,717,683,26,24,100,191,140,264,949,133,804,861,925,967,745,435,988,286,67,670,614,86,986,545,730,268,881,195,385,880,120,879,857,182,801,943,795,720,205,155,774,925,895,505,789,465,382,842,243,609,255,163,779,184,860,612,944,110,158,638,102,512,878,617,745,967,332,110,704,801,722,870,803,78,204,930,172,742,239,746,829,655,146,946,836,139,441,928,156,252,36,660,9,992,964,890,565,826,946,967,328,585,437,961,714,354,360,311,811,283,272,298,657,267,815,651,688,951,555,881,120,6,796,505,724,313,123,913,362,179,488,706,300,448,468,80,575,190,507,558,36,281,787,51,455,947,837,980,401,337,206,947,714,511,496,228,500,664,262,536,412,970,185,944,825,55,883,60,753,74,311,86,398,430,653,897,97,791,121,349,500,798,524,370,672,502,870,380,942,891,970,307,808,611,879,554,880,196,843,521,982,347,89,613,499,74,501,720,614,258,993,957,901,315,17,824,331,141,771,507,792,524,577,524,898,461,544,738,804,143,376,727,300,311,457,64,618,899,802,853,501,769,829,793,181,361,157,211,508,891,835,479,103,326,644,216,663,722,11,307,533,21,857,969,619,254,793,456,945,530,267,547,866,926,673,610,15,96,882,943,848,240,743,68,77,400,121,50,194,987,512,13,524,741,703,285,245,260,222,844,100,977,996,528,669,577,739,960,290,489,27,552,362,502,487,242,930,388,406,399,119,889,999,135,893,907,773,182,461,984,568,530,445,165,589,762,776,70,744,316,367,490,340,971,854,623,120,580,100,506,760,648,311,858,372,938,116,461,154,110,121,970,530,345,864,395,674,797,495,172,239,580,674,60,334,643,526,617,981,627,835,869,89,620,502,862,673,556,486,82,666,151,571,744,570,553,799,2,171,714,581,93,7,104,491,481,169,722,49,674,149,573,150,148,162,693,559,436,84,97,869,129,213,128,526,650,84,352,874,825,333,552,540,306,179,342,673,736,47,171,834,261,233,705,516,399,833,415,579,929,659,648,900,793,474,223,157,399,416,554,341,685,926,226,867,284,547,115,720,298,873,230,271,181,772,774,998,668,424,341,248,298,187,143,916,337,31,415,164,196,164,317,991,374,908,103,222,147,911,921,346,762,652,244,365,439,84,43,990,432,114,405,803,332,690,790,897,405,937,935,836,398,688,709,723,931,508,115,266,434,627,777,481,376,459,934,775,456,348,257,532,657,556,128,899,502,577,383,526,301,954,163,667,245,396,742,288,347,669,957,691,7,918,899,104,581,969,381,10,541,45,303,752,83,939,639,934,751,801,888,919,124,159,90,27,328,322,679,388,306,515,227,207,940,623,474,171,380,626,865,596,757,996,701,642,911,248,9,696,29,389,718,458,327,478,828,942,502,668,868,113,550,493,836,934,898,530,290,69,654,657,257,404,798,525,408,518,734,663,590,488,2,760,607,227,287,305,619,350,647,681,289,154,24,171,62,60,261,944,772,808,328,137,76,810,657,841,674,198,524,727,278,221,265,224,406,864,471,451,803,531,911,54,161,352,219,924,954,392,149,894,846,107,776,715,798,850,973,480,962,90,915,536,911,65,320,322,574,950,953,284,648,287", +"800,308,210,443,250,388,586,821,828,978,372,508,716,141,989,657,226,596,616,97,163,952,311,462,667,720,933,496,79,748,656,350,874,40,296,100,581,997,755,609,290,862,642,38,461,178,993,664,320,476,536,833,169,36,618,789,870,1000,305,835,902,383,250,45,389,54,54,165,815,754,261,730,617,3,801,67,869,59,71,541,554,423,312,385,317,706,799,54,981,293,987,9,739,508,662,237,910,634,289,197,224,192,968,433,144,998,661,772,910,746,364,945,323,387,614,319,582,26,355,560,146,913,329,677,771,462,421,649,616,557,232,945,869,445,728,6,85,868,654,763,869,408,179,735,675,301,870,255,379,748,485,547,723,618,302,0,430,246,653,638,447,638,33,636,750,172,207,292,758,825,767,590,292,457,650,989,357,91,306,686,486,501,326,737,896,792,884,356,238,669,768,383,705,304,731,980,258,567,556,45,716,98,922,456,843,200,856,538,43,603,866,854,314,713,345,704,467,174,496,403,927,234,229,383,487,919,637,160,384,857,182,985,563,307,749,863,355,768,167,718,773,984,99,640,777,614,738,993,343,649,746,986,302,168,235,1000,502,560,98,794,56,144,473,171,114,341,743,135,774,460,208,96,260,865,286,220,207,462,195,493,16,760,609,818,415,863,73,799,964,552,680,433,652,676,615,151,642,283,241,781,225,991,804,3,349,581,35,455,518,606,626,288,740,156,624,770,241,212,271,526,588,97,286,1000,593,776,484,605,298,890,312,553,862,70,607,147,835,872,363,496,583,215,970,554,735,669,56,383,375,554,723,214,834,959,6,765,947,364,768,751,160,674,370,591,294,115,670,196,313,985,573,575,251,248,59,327,50,282,966,533,5,417,881,448,381,755,246,598,523,980,894,607,692,325,830,959,321,629,102,48,400,232,424,977,343,877,609,358,475,895,17,398,425,863,578,29,485,457,303,963,863,312,308,40,832,768,849,635,550,480,880,526,582,124,657,231,503,710,918,766,340,584,69,876,625,748,896,387,206,150,756,461,457,677,9,940,958,987,638,777,746,876,914,555,289,264,875,585,200,331,849,969,257,776,330,326,640,387,384,316,123,432,58,612,961,454,7,223,360,862,686,838,725,364,703,100,249,397,695,546,827,945,239,878,618,764,80,751,546,667,820,732,964,828,529,214,622,846,493,640,862,491,579,327,340,521,442,982,420,822,656,740,50,391,24,347,560,438,807,618,391,742,174,307,215,770,700,491,481,763,482,136,115,210,416,838,973,584,389,386,820,845,673,918,61,477,582,729,553,493,994,703,116,915,319,916,541,202,608,310,669,93,856,466,188,213,995,299,824,89,465,311,367,870,606,161,524,843,8,880,943,246,739,665,431,934,188,540,744,669,952,138,606,791,326,921,891,746,148,769,574,491,378,600,240,911,408,668,907,661,961,380,638,567,45,435,435,446,883,432,753,181,810,512,436,43,614,950,723,320,106,43,56,472,860,886,770,517,832,307,541,860,912,373,954,599,249,93,75,895,739,383,929,490,637,242,124,78,554,989,607,848,638,840,579,360,470,554,381,201,8,220,449,739,798,159,716,551,597,543,775,690,955,410,231,915,394,227,230,844,360,899,100,583,820,586,568,616,849,766,367,948,259,985,740,841,170,825,251,777,820,625,907,602,779,678,969,969,952,700,542,732,404,30,620,181,940,299,53,958,806,382,467,969,564,683,687,417,145,982,219,865,761,569,516,304,772,149,791,468,93,232,849,408,122,397,944,71,543,62,292,491,295,606,265,260,85,540,248,521,231,691,14,347,193,675,849,106,815,527,608,24,644,392,993,194,510,926,804,417,72,229,893,635,783,713,344,901,958,457,400,646,878,986,95,74,764,565,794,872,148,543,705,28,899,142,203,688,755,906,138,470,219,877,964,256,634,715,544,476,801,497,197,342,738,31,11,974,927,373,113,453,673,373,377,135,164,808,562,560,28,846,666,692,71,848,351,747,57,580,837,414,718,963,866,537,767,961,730,865,646,448,881,323,303,97,15,710,454,879,748,25,819,379,22,210,522,363,954,837,654,38,600,975,993,477,881,966,533,713,518,775,696,730,564,714,974,493,10,299,563,796,511,807,866,597,533,467,909,567,181,175,880,807,274,815,283,885,98,232,742,453,721,572,406,194,516,818,589,988,668,615,951,165,465,308,907,497,484,12,229,700,682,716,293,388,492,660,307,955,604,227,687,889,745,239,381,642,167,672,520,213,735,669,96,269,512,101,123,716", +"503,254,870,592,183,319,909,398,769,487,459,436,683,686,563,544,73,997,282,446,554,668,244,233,115,307,32,205,274,730,643,630,804,324,929,707,955,507,931,557,354,813,609,180,176,251,596,732,299,578,435,150,414,747,573,470,545,307,914,978,306,918,932,391,169,751,648,172,207,890,791,937,147,133,142,416,31,833,825,109,473,917,413,9,488,85,786,643,77,662,138,144,658,756,311,606,525,875,701,317,487,812,227,372,202,659,405,981,461,818,755,120,600,276,774,223,887,844,651,237,130,457,223,514,254,571,229,839,765,250,807,894,938,495,408,974,861,102,571,780,692,951,540,643,765,576,591,767,805,914,281,469,429,329,599,430,0,986,519,970,36,608,406,929,997,46,186,643,123,282,914,507,972,81,3,740,39,207,769,157,751,641,243,264,63,965,949,217,655,290,488,429,915,332,416,598,355,304,790,630,679,227,728,20,698,899,214,220,278,108,581,182,424,890,194,225,65,567,432,430,72,367,699,798,538,351,184,445,43,377,542,266,489,281,113,583,658,989,301,653,144,949,716,456,496,811,336,937,885,588,382,234,139,343,994,642,147,313,11,858,850,41,494,572,556,471,392,362,594,902,355,812,755,387,412,959,182,550,396,463,573,16,867,15,514,450,407,136,52,820,399,642,302,77,924,902,651,281,261,862,597,343,194,289,351,172,110,906,992,202,689,19,478,702,616,935,220,310,922,336,604,290,864,786,168,13,85,785,767,301,554,453,17,610,904,147,699,151,342,794,657,112,212,753,226,684,732,985,808,260,221,523,827,528,478,736,322,429,313,853,102,191,52,804,557,329,253,377,54,806,422,834,836,998,372,516,742,882,197,481,94,705,983,161,875,922,492,783,458,711,486,426,531,955,255,858,879,940,688,112,702,203,682,587,22,689,62,699,463,978,482,977,88,333,446,363,570,426,86,314,228,936,277,985,405,142,902,902,199,945,729,263,962,549,729,310,232,393,220,749,465,167,295,696,841,792,824,167,285,28,700,27,745,48,849,713,832,850,70,675,509,694,394,548,969,487,466,842,151,439,2,242,904,180,325,512,843,470,877,923,122,620,411,966,926,404,946,303,309,438,424,128,56,855,861,529,315,430,406,987,597,752,380,936,944,624,941,854,235,303,97,518,133,646,706,695,39,799,985,234,416,908,512,447,866,294,806,242,361,305,412,155,227,742,458,533,457,144,881,515,104,573,844,638,379,338,558,856,54,385,398,177,192,676,739,770,460,63,910,177,38,915,540,667,526,720,190,540,289,599,893,441,908,758,953,511,597,251,226,448,102,780,811,343,515,245,981,732,812,46,388,774,986,990,446,285,684,640,752,768,977,56,845,187,452,32,546,563,259,412,41,880,619,224,666,650,276,465,33,920,680,270,28,488,634,892,351,443,884,91,137,937,623,898,405,417,711,590,500,204,641,983,333,56,565,263,557,791,746,243,909,595,658,9,486,495,859,980,710,384,720,965,904,781,916,237,67,208,465,298,582,544,603,536,625,338,634,562,113,216,175,262,844,76,661,379,187,893,711,736,337,152,436,247,123,118,169,595,238,542,78,704,17,620,497,171,956,950,504,833,687,331,237,800,751,520,66,38,278,912,957,965,910,167,701,45,538,780,885,268,639,111,229,470,539,395,919,826,624,591,734,555,760,320,300,264,338,543,486,64,241,82,746,353,165,263,306,360,60,920,720,529,160,557,810,994,759,328,823,625,80,528,698,7,591,530,459,250,372,999,505,744,737,981,251,985,661,558,245,294,890,420,306,614,857,895,552,128,851,432,274,835,622,921,405,756,774,975,682,553,610,52,153,455,36,364,258,109,524,76,446,316,716,715,388,129,34,92,221,109,865,969,720,341,390,247,919,893,512,731,432,975,892,461,828,537,916,710,861,556,925,381,879,75,170,79,885,191,280,189,683,502,286,893,865,732,196,857,498,823,917,826,625,28,842,228,280,117,925,202,371,829,45,145,130,12,902,525,308,806,583,642,768,220,926,588,69,360,931,540,37,585,943,672,144,827,533,807,148,349,318,427,40,481,824,753,784,742,898,241,585,940,588,691,613,332,704,559,592,713,521,240,442,251,269,423,381,112,103,357,589,946,803,639,186,539,983,521,788,278,300,821,828,623,518,605,446,86,355,213,444,686,577,314,112,621,323,785,342,817,51,581,411,877,777,619,904,462,532,963,930,793,46,679,790,832,282,810,349,896,130,787,769,252,129,389,761,787,589,216", +"767,860,900,793,886,497,532,782,181,168,530,251,93,944,182,821,709,68,315,415,574,60,595,29,69,199,537,352,43,783,121,385,190,99,126,856,732,324,548,665,259,554,75,235,515,435,976,947,540,360,444,150,981,523,563,880,219,956,744,404,657,908,951,833,939,944,802,212,765,282,264,150,197,943,43,30,187,559,320,486,787,354,318,136,107,246,671,546,874,30,322,13,147,869,277,569,252,543,538,646,911,787,650,292,388,648,689,674,562,564,255,694,252,193,744,800,654,993,511,489,54,675,919,945,358,892,464,414,236,962,368,972,696,661,493,858,569,245,313,818,178,665,711,978,581,353,444,381,868,766,371,445,472,340,779,246,986,0,660,672,169,523,8,989,516,631,811,243,572,668,371,541,301,163,9,868,591,224,437,338,869,778,726,440,615,39,965,954,964,494,60,58,680,644,55,291,123,892,326,936,251,706,989,941,828,347,384,734,226,192,440,26,334,375,104,606,502,80,833,262,71,985,703,45,937,298,935,221,706,484,886,761,931,32,322,559,305,107,172,73,827,850,135,890,432,19,978,843,953,479,879,928,619,942,424,874,722,580,691,612,894,280,296,500,247,757,953,600,796,965,387,655,474,268,86,975,948,871,220,36,787,922,910,687,629,428,901,541,24,398,924,189,216,737,621,360,538,921,482,602,930,59,791,652,29,35,697,771,36,171,264,176,986,555,402,305,869,685,658,770,528,788,517,860,284,679,960,430,2,81,297,4,697,989,613,612,638,531,716,798,561,355,49,342,447,678,619,148,26,905,579,739,370,543,64,224,479,852,88,730,121,824,424,246,670,701,350,484,748,436,437,241,440,774,971,700,59,600,938,913,33,656,578,857,405,536,344,110,883,517,482,405,367,270,523,845,653,54,432,124,335,533,379,288,501,178,352,112,82,385,152,503,862,68,971,584,647,752,421,586,945,871,826,634,758,700,655,94,382,604,405,696,160,860,629,419,539,661,966,245,1,74,520,685,925,162,783,431,415,828,688,908,411,567,933,599,617,109,385,249,410,680,656,63,622,807,448,889,735,959,956,886,117,897,584,925,858,585,950,211,68,410,68,679,32,143,781,703,368,725,179,282,620,516,8,268,35,561,828,666,802,398,145,284,470,29,132,222,272,161,219,599,296,772,951,401,102,854,631,33,500,738,460,752,921,770,82,517,317,930,543,728,17,103,717,35,31,870,650,438,746,733,527,790,134,583,387,302,721,135,351,966,961,212,346,767,204,180,937,458,3,676,620,721,451,34,155,809,635,326,919,21,993,152,482,259,390,897,779,168,107,711,28,248,495,332,546,838,311,16,381,106,171,18,926,182,969,54,352,34,384,705,478,600,382,430,441,476,362,826,372,454,23,341,336,126,737,414,577,9,254,424,421,345,920,794,716,559,651,265,969,981,418,756,716,340,295,534,109,688,43,487,512,691,552,778,263,670,173,732,821,632,886,498,188,578,60,3,919,189,347,524,503,388,890,33,991,110,378,533,46,457,294,68,467,655,120,42,351,810,716,599,370,342,855,199,733,569,752,702,92,294,263,126,891,799,963,250,637,384,563,961,423,67,598,356,711,653,721,643,739,185,465,14,916,32,518,885,589,198,400,673,617,923,396,472,692,626,87,216,317,674,18,680,458,617,988,964,302,461,440,763,759,107,482,560,287,338,912,250,582,876,883,289,446,311,970,745,225,993,513,985,958,384,808,916,518,156,328,907,827,621,123,360,977,878,952,255,315,24,306,618,343,535,7,52,397,312,273,790,401,580,98,287,258,985,860,293,494,333,470,71,974,391,262,475,810,648,57,442,838,922,900,215,392,962,877,564,924,925,723,60,302,772,139,514,188,313,139,920,198,330,727,421,977,511,836,663,827,755,899,372,209,419,612,644,873,430,610,374,326,108,183,220,977,545,581,31,920,459,20,498,939,673,298,194,856,343,503,93,787,777,221,346,291,887,590,810,604,689,769,517,344,290,852,564,274,168,373,989,281,964,538,368,657,219,220,168,541,712,432,316,640,943,155,245,975,893,411,653,180,105,938,367,826,284,299,170,314,634,637,899,350,538,39,969,375,519,424,726,66,257,322,775,745,841,873,288,951,614,566,242,248,782,373,484,287,396,553,458,158,658,714,211,740,899,858,931,658,789,342,381,438,372,407,343,450,281,209,160,986,371,454,602,47,128,345,478,906,14,869,636,158,747,140,811,686,912,299,197,131,372,804,481,213,943,384,308,861,642", +"869,338,656,781,464,690,443,166,777,649,857,254,360,305,88,302,953,843,903,668,166,676,84,798,303,654,61,949,3,915,318,311,232,655,256,993,584,867,808,68,936,642,834,899,136,978,120,223,518,284,670,846,438,340,11,752,462,988,681,247,561,462,500,27,26,813,956,507,238,992,231,625,711,783,158,980,636,854,982,227,930,24,668,575,219,604,6,280,306,735,780,44,995,275,413,248,614,215,279,372,104,564,204,480,28,9,391,236,915,184,452,490,14,814,131,268,693,184,951,426,469,97,991,65,844,909,942,913,376,228,162,668,444,298,205,663,301,475,592,769,439,958,358,580,765,539,992,672,404,767,874,852,584,703,287,653,519,660,0,760,391,188,157,221,86,893,928,185,128,907,435,536,526,919,479,103,613,45,340,58,394,453,654,825,718,297,598,25,2,156,522,986,628,16,675,14,719,188,764,429,195,421,930,67,227,129,52,475,599,956,798,628,500,787,856,785,641,35,467,647,992,984,792,553,200,238,346,391,554,471,895,843,41,591,474,452,196,223,608,24,235,407,851,884,111,468,245,14,507,514,812,921,940,553,12,899,568,461,564,645,866,158,886,759,489,105,460,757,640,948,359,269,14,954,377,982,818,324,376,166,482,526,704,144,173,96,789,47,908,195,104,641,339,276,745,504,210,857,877,145,400,313,866,142,904,209,65,949,340,500,59,678,762,949,876,406,357,622,298,890,552,278,78,907,332,975,251,218,669,771,810,151,779,378,490,784,134,390,449,196,153,221,882,197,266,228,220,284,289,408,757,377,102,885,211,642,696,280,444,439,956,398,653,828,623,592,593,579,121,496,455,595,669,134,716,585,158,264,941,112,201,134,302,401,99,303,189,428,583,135,681,142,29,803,43,501,271,116,841,854,452,536,285,582,548,564,862,461,950,71,657,552,117,895,488,463,387,707,218,509,228,6,974,330,828,421,104,243,466,440,961,57,768,444,67,51,372,16,509,359,944,282,794,941,331,280,189,572,508,873,78,595,888,472,873,703,303,354,156,693,678,534,762,677,268,99,257,122,738,832,350,161,665,600,597,324,877,36,518,927,76,465,212,393,383,514,566,445,83,272,998,515,402,389,18,931,635,175,483,108,349,966,353,485,839,174,765,298,833,35,547,360,162,781,895,3,206,505,587,120,136,986,587,18,189,157,95,186,760,896,860,380,853,594,364,901,766,245,810,736,934,766,58,596,376,749,83,341,216,607,495,492,174,930,695,33,267,713,348,295,439,510,66,238,935,737,619,94,707,950,839,362,93,839,555,487,930,433,343,958,412,186,521,434,446,714,729,38,265,820,850,405,387,847,575,541,237,976,163,509,917,539,448,324,964,225,961,769,142,116,646,476,869,357,454,171,332,693,26,715,93,804,555,784,741,957,313,294,275,689,401,692,858,802,862,250,585,902,870,106,493,324,205,591,643,841,371,848,146,815,535,725,225,153,97,339,372,314,538,132,623,396,258,936,108,683,907,76,494,903,993,34,74,843,577,734,723,333,96,810,275,646,783,654,889,177,85,345,667,946,982,744,766,211,329,994,279,123,665,188,835,722,356,137,919,43,938,768,787,343,755,147,588,308,755,676,270,721,786,580,653,720,255,608,478,207,476,830,207,856,317,674,44,619,767,986,326,160,467,433,190,286,11,358,917,76,928,175,552,271,991,171,475,990,116,773,960,744,731,756,79,63,543,461,702,349,435,923,741,955,656,86,733,550,801,837,800,94,613,325,215,533,843,383,125,204,434,712,839,606,404,925,521,585,267,123,809,355,551,146,484,242,394,473,775,298,968,314,347,566,673,915,335,293,907,896,592,104,150,651,648,481,800,87,673,890,380,207,346,120,246,377,443,396,499,451,737,42,290,558,350,322,585,416,810,838,893,880,908,717,677,645,49,345,750,626,119,295,714,461,765,22,321,794,376,534,635,126,770,991,397,543,108,264,28,737,54,625,486,750,660,656,436,746,648,856,553,406,100,110,308,772,330,638,794,119,416,899,194,928,735,134,416,150,563,930,913,906,869,517,162,270,191,22,826,891,394,73,362,102,771,868,295,135,28,845,231,972,862,330,958,288,608,773,447,874,888,196,419,688,53,323,635,959,59,427,132,226,643,152,701,602,801,395,290,984,290,245,342,34,47,21,544,433,473,537,307,730,736,534,496,819,50,125,768,706,298,324,296,318,45,562,250,539,762,437,210,907,417,201,969,642,726,364,89,656,272,782,968,327", +"13,739,780,277,540,797,1000,274,96,868,541,252,919,220,858,270,913,946,701,284,95,676,554,779,349,721,53,209,201,654,457,220,467,68,275,481,8,274,266,53,47,556,721,757,809,154,306,986,93,576,872,518,385,172,771,8,201,982,30,17,137,80,882,314,9,23,273,740,88,726,762,915,885,431,306,293,693,468,645,811,700,175,523,398,94,99,525,611,390,479,663,328,555,499,398,995,629,980,240,562,18,543,664,390,792,547,381,204,22,966,26,750,898,554,820,593,449,177,827,98,978,236,90,949,752,153,612,814,559,222,602,579,266,921,690,447,319,615,410,728,756,42,381,409,455,912,889,971,349,883,492,514,883,856,837,638,970,672,760,0,102,533,624,509,277,227,849,445,304,402,264,488,940,858,679,724,846,14,777,431,376,661,671,42,54,767,421,659,462,334,589,655,876,874,823,960,118,617,644,236,876,400,200,395,370,898,467,100,665,656,943,475,675,320,295,130,228,84,735,394,743,486,841,975,999,119,174,306,897,333,311,261,923,296,337,429,460,294,623,989,55,828,5,63,39,594,718,475,853,425,172,239,699,996,723,233,285,562,567,837,113,495,968,313,720,284,704,490,560,53,828,569,352,693,318,804,310,85,758,11,710,532,67,716,766,209,711,500,996,584,322,941,616,475,641,355,663,237,418,382,925,634,483,172,327,506,884,38,976,379,57,237,387,310,721,510,347,871,252,161,265,595,473,822,930,662,105,616,469,275,425,689,532,711,954,637,198,40,974,777,897,712,369,27,874,113,450,682,97,263,629,927,332,260,382,190,120,272,943,954,813,866,211,816,970,102,482,24,428,160,271,540,999,554,484,339,154,262,781,649,796,641,874,237,171,786,920,263,256,222,759,684,530,434,478,3,141,910,323,455,249,35,94,113,839,149,508,763,462,379,518,656,591,905,623,283,964,836,850,395,947,715,31,685,386,132,842,147,814,450,108,665,478,755,64,906,111,193,680,146,569,812,496,710,320,196,478,397,643,909,472,648,622,915,908,259,608,582,375,776,592,431,825,585,487,752,710,854,684,878,201,122,847,960,448,531,460,288,859,691,438,51,166,65,589,401,976,73,371,418,272,426,655,503,915,880,3,446,307,630,475,5,11,599,436,293,46,629,47,913,796,978,161,751,63,15,874,194,402,502,711,663,690,68,200,646,691,374,679,203,453,233,140,92,446,730,756,830,110,70,148,229,344,782,333,300,500,179,172,948,492,436,729,465,702,825,685,103,634,12,393,26,310,389,613,179,306,139,453,558,930,657,732,830,679,782,512,495,389,516,442,932,236,473,435,481,819,637,112,54,380,313,240,536,390,512,411,464,890,377,923,823,616,342,266,852,422,446,857,318,527,11,420,649,628,289,545,415,731,744,48,378,3,532,613,86,229,140,798,241,678,189,681,571,854,335,438,415,31,287,567,922,442,162,419,293,886,680,150,320,951,710,117,279,248,436,85,252,847,328,752,908,433,162,131,338,215,321,885,852,625,284,565,115,21,155,60,960,697,951,600,878,60,383,475,511,206,98,942,183,291,153,592,697,262,593,666,646,568,243,564,575,457,195,175,398,203,31,809,346,859,419,818,811,824,708,887,457,415,5,542,579,199,768,747,499,816,773,290,790,612,63,765,343,796,994,469,85,476,524,710,569,612,526,910,826,17,163,950,620,978,686,769,767,65,883,656,133,796,358,729,678,880,188,585,960,40,748,500,799,145,972,726,766,410,819,880,525,767,428,390,230,577,597,782,939,39,24,96,978,571,64,606,87,667,440,575,874,778,20,640,236,657,523,583,805,462,526,236,7,720,956,924,880,758,840,61,224,194,88,995,933,627,930,159,490,285,409,338,726,543,751,30,623,954,172,433,84,382,809,715,781,921,661,241,534,476,562,795,537,609,103,502,268,259,206,649,794,252,103,292,738,701,672,949,444,233,611,593,367,926,227,27,636,715,328,930,533,122,837,98,806,238,811,595,681,625,106,543,777,654,150,886,872,980,615,684,101,570,314,649,198,815,722,513,148,780,366,512,451,657,465,693,573,604,960,42,225,868,84,550,682,190,503,89,461,920,546,665,895,332,735,258,466,124,595,56,623,650,850,65,469,712,367,8,755,128,666,79,619,974,9,901,796,507,512,180,448,910,451,931,377,487,210,945,521,459,569,125,863,855,202,78,865,945,996,851,461,292,543,80,481,335,292,560,301,173,506,373,692,294,679,118,694,981,182,511,166,742,47", +"252,614,679,326,586,985,180,576,443,100,450,363,697,724,205,303,369,55,734,208,895,566,436,555,284,418,293,555,210,30,92,486,561,883,847,498,420,897,345,600,347,693,980,636,725,381,190,931,458,977,934,566,851,476,78,962,26,251,451,708,842,877,13,471,113,128,165,123,852,699,817,850,337,36,266,875,602,731,416,467,112,21,806,527,34,938,891,681,840,234,664,492,985,562,195,90,485,484,321,675,159,994,387,984,313,537,392,998,354,521,452,659,514,70,246,646,423,712,209,43,282,594,733,687,708,933,229,331,115,161,512,28,186,606,960,67,670,791,527,391,728,641,803,489,987,254,661,116,749,184,739,696,934,217,470,447,36,169,391,102,0,34,635,310,15,380,402,85,475,646,818,171,542,993,272,9,163,64,128,160,295,658,75,300,918,126,960,339,916,300,504,415,33,512,244,521,72,247,121,423,211,677,578,314,177,511,486,45,262,548,878,244,978,828,301,333,336,856,267,447,599,682,686,64,825,187,339,710,919,554,898,777,868,699,770,547,975,204,623,864,869,74,862,333,668,908,855,198,325,181,908,361,751,613,231,136,615,705,872,365,380,32,898,905,158,673,275,912,914,3,742,609,371,667,386,799,453,561,252,262,1000,526,167,376,971,949,821,602,398,729,514,39,930,69,34,36,731,970,343,852,500,996,754,531,35,521,139,890,978,575,766,436,642,193,356,760,618,260,909,41,65,223,683,945,4,338,444,927,284,813,977,842,346,493,904,152,218,995,130,828,980,746,701,51,643,118,143,524,334,460,991,251,54,636,973,655,309,36,108,938,578,705,333,92,976,929,217,131,111,211,122,165,41,324,946,771,674,721,3,314,624,931,502,791,567,919,173,309,531,992,466,424,783,398,626,248,793,429,991,739,724,760,376,986,968,428,664,79,898,979,991,996,809,524,643,278,156,420,24,211,200,107,545,60,587,646,721,960,147,668,744,755,679,515,264,150,517,470,833,515,399,405,81,71,262,885,443,998,480,700,686,348,398,565,223,702,951,898,662,534,998,97,593,955,69,560,625,427,23,290,47,621,41,592,775,886,629,22,92,94,941,999,323,803,779,178,607,681,235,17,168,725,268,240,281,643,502,618,993,305,356,505,784,7,584,327,57,208,676,675,133,504,81,743,476,983,944,142,329,170,578,316,990,624,212,550,533,321,485,630,332,524,56,805,368,748,297,105,625,468,132,43,399,987,360,171,753,659,971,667,760,725,235,474,835,570,161,120,713,852,49,522,779,659,512,449,650,38,978,969,963,329,355,628,325,378,115,366,877,532,607,366,248,157,999,779,560,401,420,691,193,784,474,576,352,437,143,767,861,91,551,5,829,114,405,904,561,390,164,820,158,50,150,771,488,435,330,175,271,288,174,484,857,934,251,469,598,472,239,491,573,393,939,490,615,556,189,467,824,763,815,621,54,373,937,894,14,440,653,613,989,92,210,237,923,216,975,351,141,486,227,271,667,474,332,631,552,826,786,403,811,268,824,991,17,897,576,150,839,72,938,485,624,719,139,246,14,513,216,841,14,104,276,62,183,109,461,954,304,785,209,855,511,180,223,165,219,782,813,895,159,557,29,834,756,217,48,674,605,413,580,113,293,840,197,847,15,387,589,768,188,5,183,449,670,541,545,182,628,860,137,302,485,992,61,858,436,634,57,862,547,900,125,972,835,424,775,279,344,681,48,942,630,993,438,578,871,509,403,672,223,872,958,925,446,856,841,555,459,58,529,309,141,895,306,900,889,712,961,407,78,339,162,981,786,534,573,625,948,594,346,569,831,334,224,499,740,875,854,186,189,353,359,182,704,272,446,964,757,679,613,747,927,590,747,127,756,637,162,920,832,12,684,396,989,943,68,62,365,10,554,738,816,466,82,31,733,683,410,577,21,836,362,841,929,524,44,407,599,79,33,529,279,728,122,52,919,417,318,124,6,78,849,793,471,633,280,563,575,905,442,66,878,279,742,633,859,551,393,531,182,247,887,311,52,733,139,694,433,692,365,858,492,136,111,426,33,12,614,453,928,918,766,943,747,771,97,746,499,375,472,605,368,939,712,884,152,799,464,26,514,965,284,622,594,979,181,896,543,107,177,13,888,941,682,500,66,973,542,653,259,397,886,210,701,63,482,105,475,382,676,828,683,500,268,882,340,246,488,143,666,236,98,702,969,974,91,784,151,31,592,376,459,563,700,772,23,497,498,548,776,980,46,13,929,698,744,115,283,738", +"746,918,147,971,85,796,352,392,927,979,302,874,416,198,171,546,331,174,430,499,323,918,483,662,384,409,784,154,758,800,152,31,715,489,6,351,183,852,654,486,750,362,235,955,984,586,680,385,639,693,231,714,284,688,587,831,319,114,633,443,603,144,497,276,917,458,350,109,849,344,74,906,87,831,496,203,665,199,734,192,922,969,887,425,500,800,612,160,189,113,743,546,15,344,232,905,665,599,162,865,890,745,897,286,324,931,479,584,919,608,389,211,857,266,770,249,117,651,83,584,845,116,16,108,262,50,784,518,508,115,336,233,442,537,84,280,817,701,571,641,444,782,46,299,180,239,255,994,813,458,512,87,724,716,117,638,608,523,188,533,34,0,302,3,519,341,267,34,787,923,527,155,245,340,768,390,30,670,290,743,524,607,682,903,696,5,594,810,640,292,650,522,628,333,530,849,288,662,527,426,923,185,27,530,543,794,647,727,22,408,112,52,417,956,825,477,589,398,868,270,707,285,798,761,320,959,274,406,353,772,464,574,394,385,224,292,295,937,256,561,6,439,190,654,241,646,423,380,944,515,495,847,719,480,756,611,669,65,140,198,431,347,450,958,438,349,378,971,136,909,750,296,7,753,660,719,189,57,347,350,394,763,398,585,177,21,606,104,552,904,861,641,266,197,46,464,957,827,761,715,770,694,988,999,802,23,372,357,278,510,576,224,72,421,18,443,926,879,748,775,760,768,304,104,86,314,195,589,133,213,421,949,655,948,277,823,5,279,473,630,279,681,7,25,718,192,261,147,275,446,134,785,213,532,55,660,745,454,321,622,835,128,515,29,646,126,485,973,896,246,530,964,421,429,791,546,557,566,731,50,17,823,229,25,709,768,266,700,590,560,944,569,182,372,24,802,200,19,94,59,427,713,400,167,175,595,622,450,755,816,753,343,644,581,596,299,267,634,344,624,608,706,459,127,224,152,232,787,690,775,804,267,43,118,732,670,98,101,453,588,914,410,787,374,349,176,113,918,35,480,816,482,553,280,841,409,413,794,358,458,335,786,163,962,812,874,328,850,469,594,693,674,532,549,913,957,624,511,548,391,783,620,923,874,816,848,937,67,722,150,852,123,546,676,539,791,366,223,252,409,813,487,617,222,515,718,339,506,62,756,211,729,941,603,296,560,757,605,20,951,771,558,761,106,124,901,140,608,286,366,578,17,660,906,216,159,221,265,432,298,714,237,993,906,328,308,502,855,633,259,606,799,15,74,640,786,320,755,923,965,205,39,283,756,853,719,459,236,758,407,114,515,636,320,170,365,765,202,164,359,839,216,239,593,956,135,35,536,915,562,980,267,668,617,835,282,780,419,860,892,715,159,655,63,480,246,174,189,246,731,939,740,242,194,322,986,289,481,500,739,875,599,867,5,457,413,692,244,552,358,671,751,668,550,501,124,268,654,173,429,551,958,551,721,243,920,442,622,940,27,415,782,783,212,234,513,390,783,923,279,894,451,878,201,822,64,8,383,80,709,595,698,484,672,383,334,324,763,429,278,878,657,253,905,767,174,529,177,863,265,838,226,673,503,986,580,872,996,130,510,518,470,887,177,980,41,444,201,978,722,173,292,797,999,867,587,343,907,392,969,480,732,503,778,720,796,811,937,383,141,702,986,237,269,701,925,914,928,958,904,864,470,917,897,869,232,115,607,123,794,851,873,909,884,818,726,965,191,266,974,327,21,327,53,877,921,94,56,662,901,809,764,165,830,150,38,485,16,894,99,800,215,273,983,481,809,442,446,489,112,782,901,930,537,284,427,722,289,766,382,614,421,240,674,240,808,510,750,833,339,331,580,493,958,815,200,226,471,56,55,823,485,326,812,241,987,135,196,505,921,806,304,120,139,70,328,732,74,197,346,263,416,106,965,711,49,545,819,624,837,93,819,746,888,135,167,410,181,706,790,292,146,131,224,968,375,808,736,615,495,998,144,484,531,358,547,128,721,12,140,284,269,656,491,425,22,831,856,252,768,889,532,650,998,128,895,415,624,944,65,97,937,644,889,850,468,348,442,33,302,569,528,276,493,978,509,3,20,170,830,728,573,901,891,768,971,5,927,865,149,948,700,841,978,52,758,448,679,386,218,497,735,399,639,803,782,82,93,66,162,444,628,335,804,179,138,917,256,244,286,850,178,652,247,485,145,161,424,733,502,744,740,324,952,154,727,19,946,183,975,180,976,244,534,558,464,583,953,296,748,47,61,670,534,304,124,491,134,460,983", +"6,21,201,673,769,96,740,929,478,942,879,2,372,262,21,429,737,651,311,376,257,86,95,992,126,826,234,958,436,768,794,477,234,571,247,245,193,965,507,656,858,889,694,498,818,216,666,412,715,578,941,633,904,964,430,300,296,969,358,595,358,111,994,403,1,988,929,302,793,344,702,478,749,880,234,283,97,864,79,24,787,975,268,956,625,85,597,191,696,933,968,334,701,62,988,151,857,133,299,928,945,706,858,352,883,590,619,856,72,449,982,21,365,58,608,992,510,289,701,389,96,700,694,926,425,639,319,162,925,812,37,889,479,555,491,327,32,60,638,230,711,53,795,746,685,264,328,782,976,652,372,305,997,692,732,33,406,8,157,624,635,302,0,682,559,170,179,793,801,913,629,503,538,884,480,439,249,700,769,644,517,31,358,480,272,87,45,384,945,264,68,806,395,974,922,984,640,451,124,382,199,886,612,79,145,748,999,963,28,564,900,279,199,587,829,989,897,358,528,299,551,637,413,382,174,175,146,876,602,426,892,385,4,918,237,649,401,37,286,698,37,91,325,314,230,956,795,374,948,150,488,986,408,724,609,353,727,536,676,100,547,666,641,650,51,755,874,259,206,718,723,810,883,635,963,407,150,247,137,222,862,494,922,372,240,528,768,970,79,292,600,459,451,914,725,615,102,140,145,263,858,271,190,331,901,209,646,856,822,601,123,998,107,413,453,772,817,608,215,261,716,499,775,263,144,864,271,468,732,729,821,715,450,206,953,913,811,892,687,772,920,442,447,626,645,930,614,44,781,81,922,419,277,736,289,456,734,959,310,727,218,522,104,627,354,406,169,787,171,70,315,280,738,562,864,323,638,507,374,162,540,275,19,192,762,862,763,945,658,499,262,40,17,385,163,676,512,890,131,902,526,825,987,489,350,745,270,659,384,410,631,943,92,397,570,571,220,509,923,374,563,865,337,188,941,452,485,562,675,926,163,104,763,813,938,968,178,805,941,999,864,710,829,817,586,668,271,103,746,757,354,107,360,588,320,957,76,294,332,748,358,27,533,561,943,501,979,958,553,180,805,299,65,25,770,653,52,580,471,953,358,640,991,18,883,871,835,816,523,872,359,910,471,148,68,501,596,608,96,369,167,87,553,5,792,541,517,779,726,427,564,874,5,987,674,135,580,665,38,494,711,382,172,481,406,847,612,405,754,922,587,224,899,581,789,365,730,343,340,519,715,428,177,719,123,657,512,78,103,934,767,356,448,881,434,17,798,598,670,469,953,989,862,1000,330,650,119,404,174,707,451,156,904,700,15,223,457,136,91,627,339,163,523,67,674,967,281,695,94,815,50,390,548,4,343,886,346,558,984,66,407,754,345,750,508,90,839,693,705,255,444,207,428,15,4,105,580,459,959,963,727,201,104,665,758,985,838,617,572,14,22,133,191,663,85,180,372,203,765,649,922,885,78,701,65,465,986,243,74,657,725,534,59,748,680,51,343,418,143,456,9,632,980,93,330,13,118,763,454,293,395,14,6,187,942,640,106,950,480,671,370,878,507,231,537,514,395,795,743,139,880,722,735,211,439,371,125,930,232,388,156,763,303,536,914,114,434,597,341,791,510,382,828,593,536,364,208,273,836,979,100,909,976,540,351,120,364,506,980,943,379,208,5,956,641,403,402,7,535,452,237,245,974,341,820,267,239,184,824,26,959,911,676,108,621,916,312,947,924,345,720,328,281,223,278,353,401,311,782,273,430,956,869,295,907,787,111,95,813,919,217,715,612,995,849,845,949,707,84,683,701,90,903,664,752,286,98,167,625,817,777,535,59,93,257,330,110,164,578,664,562,352,570,707,170,859,289,582,28,621,9,353,54,436,618,556,759,743,144,611,270,806,117,280,756,599,607,871,237,441,235,38,787,359,477,451,409,711,54,382,438,855,771,565,570,748,52,994,811,799,462,754,459,803,136,507,376,259,963,972,992,324,845,459,749,583,855,756,356,43,512,850,736,707,361,878,531,551,797,514,746,144,43,852,759,796,229,422,380,575,363,212,979,717,925,818,615,130,435,825,386,736,751,991,641,191,596,341,632,655,539,826,303,656,435,183,287,273,115,630,469,680,237,583,3,711,434,660,49,967,553,475,361,377,976,452,357,28,339,792,945,549,703,205,767,935,303,338,411,528,697,426,911,310,784,975,187,988,47,306,85,650,373,904,923,70,616,161,460,742,685,138,686,614,613,420,170,397,555,789,477,697,961,202,250,904,66,48,64,570", +"436,493,135,208,967,484,341,16,364,304,922,925,851,741,76,549,283,469,6,498,323,951,209,172,456,962,365,761,141,27,422,535,339,954,85,383,955,614,723,772,901,247,456,757,357,602,3,749,140,37,402,221,981,976,987,411,617,563,173,916,40,306,568,659,27,340,391,141,161,603,967,736,692,896,186,398,544,971,521,974,77,880,19,649,333,692,214,480,535,712,663,57,250,353,646,160,143,290,885,556,498,643,141,323,38,296,623,332,555,725,746,859,157,265,515,758,326,131,729,573,847,208,119,184,661,518,992,931,135,288,422,151,586,880,751,536,156,986,391,32,274,177,467,720,753,398,437,715,903,530,100,780,793,697,655,636,929,989,221,509,310,3,682,0,900,967,760,768,517,819,224,238,489,864,363,496,368,675,357,661,971,157,642,47,474,973,966,222,917,157,193,29,995,725,737,930,611,226,868,20,949,910,190,501,825,874,366,177,698,573,825,59,701,453,173,337,869,247,955,783,189,441,896,692,49,751,834,750,611,506,889,903,142,225,653,486,49,87,426,452,111,35,913,918,875,795,526,127,447,303,618,67,650,726,737,321,705,379,106,886,37,994,314,950,487,498,885,990,197,518,863,95,430,898,491,395,183,128,150,446,610,488,689,422,173,860,132,468,496,387,941,708,798,940,870,534,347,684,557,352,521,319,188,417,444,35,572,460,506,931,318,931,471,806,317,382,105,736,943,78,147,276,914,718,120,398,40,108,326,677,579,595,380,29,911,553,787,201,359,126,269,528,649,883,262,849,121,661,696,960,274,203,441,164,293,492,794,965,353,739,673,450,849,584,999,203,682,430,221,878,279,991,153,923,776,102,92,190,986,427,120,791,563,173,796,411,17,152,878,580,833,381,549,130,145,159,74,979,640,622,125,53,409,59,592,303,737,362,419,14,416,946,1,446,100,355,996,108,246,280,501,821,172,848,808,219,706,56,671,326,900,680,896,689,110,212,628,866,793,315,815,615,136,196,631,605,728,962,160,165,856,105,813,21,786,870,104,969,152,438,836,682,302,234,214,622,235,67,467,934,478,604,557,111,508,924,230,270,134,772,674,845,622,577,575,800,758,928,420,408,653,501,697,657,687,202,580,582,434,880,791,11,609,683,487,303,634,709,69,145,687,898,839,209,139,534,87,674,290,828,643,41,658,105,689,601,758,239,895,851,694,9,522,787,142,759,973,131,355,369,823,815,3,748,466,474,422,313,964,628,965,720,817,552,143,264,240,114,531,531,156,980,303,310,604,745,404,587,775,918,506,344,35,56,326,270,367,875,608,700,45,947,739,563,683,698,29,382,139,284,260,848,908,866,564,488,395,19,615,246,20,423,282,130,819,655,684,65,158,880,562,898,488,595,841,735,597,283,907,93,930,984,892,994,902,649,123,530,269,472,920,666,931,832,281,384,344,613,624,173,722,373,398,974,466,75,578,858,497,693,656,65,861,168,886,571,110,340,925,145,654,432,772,436,486,607,851,70,446,57,494,685,792,458,772,107,34,241,278,37,354,6,391,783,796,354,840,823,294,773,308,974,219,251,525,934,598,65,342,273,913,186,770,548,247,453,441,532,28,788,505,732,531,81,827,609,842,279,745,520,446,418,808,619,623,862,208,283,256,649,527,298,998,948,459,960,488,295,59,822,71,578,201,335,438,853,75,249,608,268,491,897,991,554,484,690,922,457,784,741,127,68,852,420,375,42,246,495,995,635,421,90,940,850,399,535,561,753,628,774,668,761,270,682,148,762,476,805,910,905,238,648,639,182,449,135,361,888,613,366,506,636,979,703,649,697,55,290,307,854,152,641,150,946,460,147,549,221,255,266,918,911,553,65,466,976,659,283,567,9,353,958,89,803,688,993,700,813,348,710,841,454,430,412,412,704,839,885,499,915,30,789,882,851,215,958,828,454,509,961,801,602,420,832,514,824,837,182,928,28,14,984,35,853,754,57,689,775,510,170,346,700,825,681,733,905,932,657,783,365,515,906,22,229,681,430,87,445,636,845,997,787,304,68,928,439,227,456,398,281,682,308,457,151,631,558,334,483,199,232,739,202,408,678,881,311,472,13,35,129,968,532,827,969,706,762,825,706,444,695,8,344,225,187,368,244,57,197,749,45,94,453,993,875,875,603,320,61,340,165,614,472,630,749,649,961,386,578,609,977,225,676,694,415,601,96,656,277,819,891,533,430,656,388,739,614,298,624,974,718,669,278,119,276,637,112,400,570,596,503", +"793,370,932,83,781,873,215,621,290,625,274,635,248,86,518,515,21,430,40,299,140,934,909,122,103,787,155,314,899,407,424,398,185,172,180,326,391,129,479,336,702,961,901,535,269,24,435,734,556,529,650,763,344,693,392,72,331,977,1000,410,282,692,194,87,132,853,109,28,827,785,248,15,911,285,821,152,313,370,297,442,59,902,434,765,628,737,344,682,84,689,954,601,226,124,687,847,948,15,463,921,76,946,979,385,389,732,523,798,158,262,894,925,684,880,784,431,794,184,893,111,216,959,651,889,158,299,163,854,774,467,585,412,989,356,766,769,619,862,585,999,855,952,587,982,774,220,612,168,799,497,918,471,527,104,447,750,997,516,86,277,15,519,559,900,0,920,614,201,389,800,48,367,610,540,845,948,891,237,721,11,563,543,668,942,938,669,157,391,591,194,660,899,49,409,87,623,831,588,420,613,406,157,750,392,999,352,23,363,738,953,772,686,763,776,800,199,587,670,731,398,769,46,621,701,445,423,253,248,914,284,891,837,810,467,412,600,446,57,944,607,250,21,786,338,530,276,960,228,262,981,788,443,477,179,391,668,302,543,691,485,525,494,214,297,497,682,908,894,289,376,89,900,8,973,232,260,723,130,262,475,297,276,209,957,416,722,170,249,81,731,728,55,249,607,821,992,571,259,789,511,637,907,516,818,112,26,899,158,173,787,801,486,675,807,783,740,226,616,383,367,761,965,80,913,512,231,684,354,489,213,272,261,584,274,656,30,380,341,629,566,975,475,372,818,423,722,191,269,409,830,936,634,27,677,565,982,963,529,978,449,537,1000,739,140,983,278,128,225,225,200,894,716,950,97,408,200,631,132,64,801,234,7,145,166,502,980,485,360,469,509,74,322,355,846,110,163,686,213,468,401,634,104,435,517,299,304,861,254,569,436,915,371,467,579,370,724,702,315,174,271,425,912,364,720,338,326,178,518,690,905,743,236,445,212,648,552,994,206,711,967,890,683,203,202,74,578,130,533,113,147,938,667,708,258,951,778,860,587,879,820,245,141,919,859,844,597,559,154,584,760,856,811,963,227,963,860,652,204,508,877,669,542,750,904,650,967,269,116,633,499,272,386,985,975,506,371,763,889,759,556,164,185,222,472,93,88,666,32,406,620,121,573,355,256,125,318,610,505,733,736,379,91,290,877,151,955,320,320,882,227,833,235,760,529,340,604,863,522,211,446,979,987,135,240,58,945,575,548,945,616,525,448,182,587,265,126,878,123,51,508,959,167,372,859,42,810,404,756,272,68,325,751,44,460,944,95,119,2,181,321,711,253,618,237,519,9,88,145,324,526,128,644,810,869,515,473,879,330,629,947,54,56,785,655,463,391,696,287,303,156,878,742,511,812,746,479,368,415,560,817,515,861,12,779,630,889,937,999,320,491,67,833,447,656,560,705,829,224,922,408,879,427,242,424,968,129,210,323,264,298,920,704,846,213,60,130,952,489,141,652,284,985,947,145,626,955,583,628,719,875,455,372,987,573,827,233,559,290,197,404,25,248,683,308,876,54,104,87,397,737,60,465,791,20,484,830,912,249,265,710,756,529,135,367,624,278,55,712,192,63,519,471,701,367,763,322,273,643,882,62,986,666,772,77,336,752,9,591,831,652,891,514,979,688,114,609,551,7,290,919,922,456,738,845,258,676,153,243,209,856,943,720,294,166,450,918,15,661,118,447,746,881,927,690,358,347,951,466,810,484,899,252,420,217,55,472,158,142,265,582,531,556,691,979,841,22,373,950,627,518,259,290,102,389,264,700,875,501,505,355,214,958,139,130,313,413,687,949,647,192,610,357,873,87,293,886,932,467,540,209,672,393,372,649,475,26,530,43,970,398,36,443,453,77,298,839,938,769,111,724,55,288,253,860,147,101,429,597,408,980,481,364,679,469,724,644,831,592,517,109,818,956,524,776,407,353,483,242,46,704,311,840,425,192,795,490,407,820,273,54,135,505,259,881,197,369,564,277,196,752,845,145,956,154,571,661,224,859,507,456,408,172,546,684,622,868,194,333,545,77,764,865,150,33,487,672,649,621,408,979,278,558,545,454,499,85,625,90,542,853,141,709,246,119,446,848,194,57,467,364,279,925,673,183,596,373,20,526,755,816,418,459,976,992,243,555,457,957,779,271,917,467,135,531,659,31,933,701,392,651,902,588,151,109,416,861,966,402,827,706,872,143,770,567,387,669,547,318,632,752,808,1000,349,897,705,601,857,838,789,554", +"189,512,785,916,41,694,940,938,121,552,836,866,911,238,828,122,749,871,969,111,264,716,473,388,371,729,388,477,708,184,712,285,150,58,320,46,79,719,467,431,412,61,677,215,433,14,541,237,79,316,790,42,92,794,602,419,33,939,824,122,102,334,252,496,472,317,121,201,437,659,448,746,270,643,167,339,157,90,166,594,501,773,447,781,951,208,102,520,341,147,654,670,548,285,834,483,607,287,531,188,76,682,528,303,882,4,334,808,922,777,962,702,119,176,930,637,742,364,974,257,844,178,436,458,630,564,242,853,885,414,896,207,718,528,855,125,998,958,308,699,130,184,740,241,333,704,137,710,301,156,266,514,939,182,728,172,46,631,893,227,380,341,170,967,920,0,566,463,969,959,505,25,843,751,884,228,681,395,365,984,64,530,538,355,762,602,357,739,601,93,133,676,364,625,218,891,269,627,145,256,638,990,297,210,841,255,42,144,58,531,642,127,813,162,690,152,516,342,457,396,647,564,99,325,332,501,143,546,429,79,280,592,819,675,246,943,368,558,148,85,416,876,142,489,878,752,127,18,463,16,333,60,763,936,892,407,239,605,460,448,936,110,522,107,85,276,779,968,773,128,639,887,680,619,173,678,620,899,565,168,39,670,573,110,44,806,27,878,790,387,6,750,403,629,323,570,432,664,323,6,424,687,720,600,992,657,435,695,957,585,513,94,14,70,119,104,934,810,35,721,97,685,587,820,995,287,399,956,350,639,310,675,824,780,268,591,369,641,374,141,971,984,570,193,748,663,373,993,469,603,890,804,434,351,575,398,839,929,510,724,773,859,863,617,689,355,585,306,756,193,706,580,197,780,678,937,716,837,457,459,61,639,828,687,766,760,691,135,135,250,828,831,736,898,896,534,898,100,54,664,44,142,848,250,659,775,931,79,865,287,295,800,333,911,920,619,152,415,851,152,382,735,110,671,941,437,104,13,80,379,720,701,755,221,103,742,473,836,644,896,428,948,393,6,627,247,218,124,171,979,185,188,521,385,46,201,482,689,166,150,195,499,258,968,353,60,277,658,190,755,821,353,328,679,710,633,690,601,138,592,461,102,420,624,542,931,386,117,115,588,220,661,242,114,153,939,163,439,11,629,980,498,571,760,532,898,432,465,646,696,343,661,578,979,665,194,190,199,919,801,16,158,689,337,788,567,385,188,709,825,43,69,115,430,322,698,533,578,45,567,66,439,57,470,949,525,768,893,246,121,53,152,659,807,206,241,522,12,613,150,464,823,275,815,103,478,365,402,573,601,957,505,125,67,382,981,91,839,704,736,856,870,271,611,533,673,160,640,896,606,968,882,377,233,62,773,405,247,156,387,817,708,804,780,547,287,137,256,498,387,717,837,416,312,295,353,469,903,938,29,942,337,441,346,692,445,590,832,394,226,410,948,664,737,308,954,714,215,391,563,831,365,523,445,995,624,884,600,135,179,279,339,189,318,540,521,4,271,243,17,231,222,953,619,510,750,933,780,145,237,306,399,810,603,823,766,522,110,107,544,837,19,33,478,225,763,508,233,811,106,234,941,465,893,14,401,723,689,49,382,385,795,679,70,627,239,658,944,673,881,218,459,615,166,586,851,551,47,944,256,806,978,336,569,668,394,748,797,805,705,66,952,281,133,910,171,777,533,533,174,560,251,835,145,276,837,773,411,334,547,474,770,570,106,407,454,260,23,252,63,897,613,148,440,767,177,692,552,877,177,601,316,184,158,530,732,280,689,771,43,513,268,71,514,457,795,581,538,743,243,377,148,727,50,81,709,764,843,570,738,782,470,69,378,118,410,370,833,648,772,613,207,279,144,930,27,808,52,395,430,507,142,718,855,180,193,541,531,999,751,562,177,297,253,730,68,65,306,837,824,471,95,155,397,664,393,454,392,883,513,648,535,716,33,579,375,752,984,983,123,700,635,996,604,915,687,50,543,216,663,70,891,370,768,797,174,955,473,44,808,78,410,163,685,525,75,119,224,688,257,662,210,127,215,834,629,829,143,390,108,994,368,83,177,848,156,588,757,363,46,543,747,77,825,280,418,460,851,175,258,962,161,444,491,105,5,422,142,138,683,925,295,607,205,550,56,356,785,599,72,403,217,796,710,691,305,266,174,511,548,128,875,363,443,885,248,153,577,574,143,311,33,517,258,242,479,152,288,941,130,8,331,305,356,515,726,430,103,742,460,606,737,435,492,810,772,811,423,355,272,856,37,234,273,467,927,366,544,116,235", +"926,817,923,373,271,607,618,983,831,300,203,371,958,844,597,199,500,815,578,476,48,990,713,677,936,702,439,278,979,641,858,688,739,523,545,522,970,958,222,27,187,195,505,330,177,203,678,299,558,369,718,622,547,11,14,857,897,435,160,444,813,357,687,644,939,456,570,973,427,409,423,790,265,160,658,659,900,787,957,654,981,715,870,118,436,988,791,436,723,709,704,468,861,440,749,978,681,716,15,57,432,417,205,911,215,536,132,327,453,569,379,323,71,305,245,591,502,773,339,642,30,144,817,617,313,957,874,7,266,65,410,470,967,99,468,405,893,915,279,843,897,147,523,336,990,278,461,459,741,820,184,219,577,422,951,207,186,811,928,849,402,267,179,760,614,566,0,576,135,254,969,926,409,386,329,276,349,849,756,294,801,691,618,48,993,177,619,347,526,303,188,150,944,494,436,916,586,389,112,326,358,943,107,342,770,993,679,472,767,629,163,564,729,977,33,127,745,922,628,76,204,370,111,126,129,424,187,285,102,891,129,782,318,493,595,217,690,885,648,243,137,890,731,327,7,397,200,569,580,159,481,201,874,520,280,562,756,329,8,18,655,777,453,944,661,997,493,618,793,341,773,214,578,882,623,832,515,113,143,204,542,948,197,446,76,264,682,339,155,733,225,140,927,701,136,566,903,972,697,905,627,769,622,820,49,269,432,80,496,246,659,449,450,904,402,992,772,993,345,73,887,419,270,27,788,106,848,23,352,418,19,206,147,326,57,237,774,979,558,356,282,593,146,425,717,630,958,476,940,460,603,681,24,695,696,124,799,458,250,254,115,777,337,593,547,752,773,820,873,404,843,636,512,985,244,989,683,671,529,938,91,929,461,201,281,936,967,620,693,62,171,331,749,118,167,46,438,474,819,423,685,91,263,12,496,57,498,739,705,261,732,438,510,233,339,175,936,30,160,854,345,452,482,578,660,914,588,786,336,482,357,46,271,934,854,691,759,69,732,578,421,934,179,945,437,915,382,691,663,989,894,696,225,271,571,405,46,739,300,866,299,267,796,559,434,16,238,977,637,861,40,667,434,92,166,326,642,242,417,905,432,702,423,263,915,689,511,659,320,985,461,214,379,459,628,780,849,296,605,389,688,811,462,171,774,182,657,850,179,782,64,818,257,763,831,884,555,132,792,302,449,45,150,577,869,809,765,126,464,969,488,634,805,944,697,2,769,662,9,874,879,487,525,67,474,340,954,793,138,956,204,55,185,730,311,117,510,732,536,594,254,783,275,877,722,349,656,610,703,71,988,400,56,712,542,785,102,366,673,270,836,787,160,190,118,984,554,654,337,199,302,942,259,237,241,328,12,968,684,933,427,845,619,822,859,147,328,658,741,324,509,221,126,269,259,783,61,72,524,328,757,913,938,804,948,216,141,194,712,582,979,154,20,655,875,578,99,583,532,515,330,998,745,408,84,162,638,324,689,507,987,685,467,166,145,790,233,287,591,892,985,743,107,550,857,753,798,71,870,651,764,280,935,535,712,182,927,170,947,528,48,839,138,506,629,760,419,246,478,183,201,329,909,773,65,663,588,752,844,141,663,194,756,262,53,897,640,944,73,758,481,368,597,990,95,584,632,173,516,81,792,387,985,3,983,461,758,947,671,564,89,945,470,696,589,732,213,31,296,748,785,324,474,110,135,769,221,851,330,170,150,553,187,344,775,907,475,185,963,548,653,83,775,514,729,654,299,897,575,775,41,449,298,708,774,327,171,898,257,634,459,891,584,831,714,36,87,561,262,928,572,563,11,50,235,137,591,788,524,279,361,858,640,787,61,72,180,848,203,926,382,671,806,855,536,232,943,850,488,196,698,655,164,79,860,270,666,694,388,783,963,669,578,543,530,155,667,550,387,427,238,54,455,309,689,322,405,422,627,848,951,882,454,659,326,66,88,624,849,268,883,232,176,218,244,398,604,474,929,288,479,16,437,673,324,339,484,244,728,691,883,479,14,770,12,878,630,364,20,598,509,720,737,956,663,490,284,836,38,586,143,185,874,569,424,401,943,223,363,462,487,802,703,332,37,380,109,93,879,447,690,647,292,964,620,491,476,116,202,913,184,1,546,202,843,61,599,354,759,79,527,928,519,68,274,829,842,780,198,136,604,182,484,852,616,396,662,55,790,71,428,212,13,29,437,62,624,226,530,799,969,539,779,486,745,902,387,650,691,729,643,657,39,833,850,528,616,461,722,605,894,482,47,717,821,83,981,42,173,52", +"442,584,240,413,412,736,140,853,447,340,712,982,927,624,754,867,570,958,562,811,38,924,662,157,329,906,16,213,627,90,906,98,861,476,200,660,229,315,179,552,114,6,281,428,910,459,888,512,551,319,948,555,68,869,829,28,838,850,187,446,684,239,298,697,246,55,560,885,17,697,172,90,755,735,419,698,602,383,652,795,917,198,973,549,494,445,603,293,849,515,367,252,677,304,593,20,45,449,526,966,317,757,685,124,398,922,137,769,191,788,931,321,72,399,458,76,193,255,657,859,398,167,257,596,868,511,248,661,644,815,562,216,764,312,555,859,255,52,616,476,882,488,41,979,896,942,95,29,994,900,422,823,482,927,630,292,643,243,185,445,85,34,793,768,201,463,576,0,198,972,269,468,73,915,300,856,200,559,529,524,205,598,208,347,178,66,750,579,729,763,307,223,351,860,945,340,831,765,218,519,570,316,762,428,531,74,877,915,781,290,891,237,538,854,688,545,777,796,548,88,812,410,533,751,473,589,908,719,188,79,179,827,398,330,7,597,400,231,683,422,517,307,512,778,743,148,22,233,749,795,917,754,693,854,933,3,443,809,623,627,581,532,93,674,722,872,476,368,913,265,45,162,946,541,238,972,405,356,701,176,915,278,912,644,301,374,821,147,820,241,856,926,517,477,162,258,200,832,975,388,926,861,702,818,97,330,628,617,462,131,247,576,457,460,229,145,949,411,406,340,215,803,177,253,821,544,827,81,878,917,121,923,187,913,510,627,209,8,300,193,51,673,828,823,873,190,118,341,770,16,932,464,62,754,254,521,501,602,424,587,116,572,889,350,213,799,590,868,580,470,489,465,807,260,700,772,518,207,572,424,298,4,670,998,466,911,976,777,498,958,791,524,13,566,953,483,282,383,775,291,927,383,12,845,678,887,161,586,502,695,29,624,540,768,162,739,438,913,28,407,161,183,60,120,413,872,874,314,164,530,599,852,7,626,833,101,635,230,322,800,936,945,116,351,365,43,652,149,287,286,927,461,921,265,553,240,908,328,640,417,993,317,136,698,926,195,810,381,363,158,502,682,725,203,657,73,168,320,343,885,881,326,604,184,873,291,825,235,114,810,666,952,713,13,752,131,64,36,145,224,872,408,120,953,699,611,661,105,152,505,93,430,69,950,832,677,515,891,747,922,297,356,1000,230,319,463,881,68,546,47,496,562,922,302,324,623,418,867,336,368,192,615,299,127,115,931,733,860,347,209,874,220,440,87,219,380,179,972,948,746,257,969,390,123,917,443,462,89,284,907,572,143,81,25,37,432,876,291,521,142,554,254,515,21,388,618,842,664,830,818,930,631,358,30,447,746,202,200,323,675,37,917,462,76,2,454,476,875,569,196,794,626,678,383,894,898,685,958,260,355,55,637,710,402,626,231,491,437,960,108,148,253,366,365,737,104,536,124,718,793,319,680,533,631,831,570,594,3,351,14,851,752,297,91,868,948,265,787,645,742,795,686,8,303,869,915,887,449,438,440,289,775,796,116,787,558,886,160,321,325,464,795,381,48,13,808,583,998,399,862,734,823,753,156,169,427,820,137,506,975,382,702,918,943,155,175,266,269,125,144,656,593,474,722,442,680,970,899,421,854,845,419,458,270,566,682,40,247,279,255,764,533,18,620,995,127,304,471,593,730,513,931,916,947,937,155,50,314,755,262,451,742,928,487,71,696,75,567,259,686,220,563,59,101,973,466,772,577,433,342,336,982,389,784,930,719,661,331,496,953,354,302,473,124,56,356,14,946,815,351,650,444,275,767,690,414,209,762,757,671,235,74,324,290,363,177,521,801,673,273,939,144,880,515,737,206,731,694,999,966,292,86,695,969,742,307,526,929,984,18,22,655,315,570,398,954,968,591,481,170,801,392,492,48,674,255,777,237,595,725,376,411,275,543,161,496,428,924,918,193,718,80,81,176,173,483,505,730,803,507,189,214,175,798,453,974,92,608,408,733,389,808,932,99,485,864,637,123,211,544,133,944,163,410,919,771,242,421,820,610,731,741,826,965,898,823,127,983,170,585,76,395,879,264,38,659,865,880,157,598,886,367,988,532,434,598,718,920,505,930,168,897,438,672,244,837,683,228,801,860,229,606,221,524,93,738,878,178,696,281,990,813,845,593,312,523,397,464,286,290,693,56,968,192,325,717,195,26,834,753,934,66,644,200,127,149,292,848,308,638,263,715,953,432,420,952,257,583,936,938,191,22,1000,445,975,866,58,831,392,392", +"465,872,390,642,854,713,760,129,54,275,257,618,471,344,817,262,703,754,77,985,335,530,326,318,666,600,15,435,280,637,65,407,406,507,90,303,928,57,227,865,433,895,109,608,110,250,803,992,220,3,194,125,413,107,554,198,457,323,770,408,227,873,174,154,334,538,745,993,8,441,923,345,497,289,910,763,903,820,88,548,647,361,550,370,317,54,693,321,142,194,905,234,300,455,680,973,971,725,177,153,151,437,112,501,309,37,330,987,417,548,373,573,848,155,547,35,452,411,459,933,196,393,639,812,382,775,193,6,648,470,153,105,277,18,954,437,156,164,556,985,922,272,381,566,65,233,195,719,915,545,710,918,995,706,957,758,123,572,128,304,475,787,801,517,389,969,135,198,0,64,153,270,883,818,408,696,590,317,834,745,465,29,91,346,233,87,47,641,88,890,730,292,536,840,421,646,362,133,50,341,346,470,304,989,60,55,924,859,528,341,237,530,106,495,358,598,370,722,813,710,594,179,805,50,540,372,622,797,296,306,544,62,920,823,783,895,149,815,211,783,27,499,777,951,826,848,161,738,722,501,354,685,700,34,561,764,273,313,301,26,651,364,121,624,480,607,972,199,282,955,778,358,583,891,385,319,548,854,90,533,800,480,701,49,431,76,622,15,11,786,966,227,905,701,113,110,474,67,978,397,642,507,789,139,533,546,76,507,899,707,906,447,638,12,812,618,752,639,740,262,133,158,374,798,532,555,542,80,494,616,18,627,396,454,913,473,952,655,159,211,928,925,294,215,748,991,320,562,608,869,656,270,216,793,14,366,576,456,303,990,19,97,476,454,554,499,601,635,317,430,683,18,88,484,558,773,658,282,483,82,272,794,986,99,40,30,121,922,276,833,638,99,459,274,148,983,758,5,937,687,399,750,281,100,982,106,637,894,344,221,179,528,766,347,629,244,490,572,453,629,921,761,293,619,702,636,573,33,501,995,220,698,114,423,964,151,387,432,14,161,109,471,670,910,79,654,323,880,993,17,670,62,695,349,591,908,635,850,798,239,634,704,874,699,122,546,380,906,709,984,461,296,822,595,778,531,395,680,64,356,115,335,377,502,674,206,901,638,556,393,622,674,552,432,781,693,963,704,117,156,692,280,420,149,408,694,838,386,893,683,186,509,484,636,840,580,811,458,152,156,411,863,12,870,507,506,823,645,305,290,448,542,175,769,291,504,530,10,737,875,720,960,156,820,980,80,244,100,726,286,634,224,809,752,581,280,973,461,761,586,696,839,109,417,995,424,307,913,412,142,236,447,537,164,395,818,552,709,493,450,903,211,788,56,499,344,121,790,436,223,430,873,1000,352,637,883,134,408,544,466,76,364,23,895,104,106,719,226,88,984,920,920,235,149,934,344,793,370,887,580,263,8,328,295,885,767,453,949,233,547,544,663,474,973,656,450,845,150,897,366,496,132,429,747,265,258,22,899,786,242,190,357,458,582,58,63,634,957,831,59,523,564,287,390,889,277,145,616,45,443,131,393,622,913,942,355,348,687,501,139,318,347,830,203,505,163,182,585,275,608,260,281,924,304,880,146,977,694,72,895,642,794,216,298,855,156,351,118,683,458,175,281,187,855,126,614,645,394,300,254,69,74,340,955,423,204,457,694,448,345,400,688,90,972,18,967,800,884,638,562,229,230,615,279,180,24,994,485,372,636,999,825,320,253,482,868,216,410,423,770,551,723,899,962,545,971,43,630,520,425,207,865,641,888,790,26,479,857,808,516,130,870,500,103,631,98,33,535,698,737,807,904,531,180,630,440,5,573,282,14,355,564,83,264,186,828,907,842,970,491,273,403,950,394,263,896,889,312,985,275,825,250,508,298,878,938,927,219,727,971,916,964,111,618,111,257,789,715,600,324,351,448,477,67,103,997,490,45,630,552,662,742,812,179,353,458,61,339,798,678,505,109,447,785,661,124,286,66,318,253,84,120,977,605,628,428,146,850,153,476,740,320,230,236,146,225,551,558,107,850,538,589,215,246,23,804,575,337,864,445,956,728,245,744,495,745,396,527,105,443,206,250,176,6,299,519,997,82,177,15,998,318,590,226,610,471,405,632,258,701,916,926,321,545,441,14,633,871,448,286,423,279,881,463,173,833,958,673,98,512,245,155,633,850,602,917,920,367,248,335,448,869,345,117,253,918,331,407,498,514,920,656,368,99,820,218,443,653,847,443,634,484,733,338,882,880,387,400,622,588,684,226,939,804,635,577,643,983,788,409", +"225,221,636,157,961,371,427,116,76,986,866,354,818,283,721,296,271,652,279,132,333,124,509,482,348,679,217,600,645,653,813,710,895,247,84,37,217,675,619,545,472,414,478,139,848,873,649,876,544,254,636,298,952,94,981,297,177,102,720,586,268,901,552,878,184,541,388,241,11,513,94,252,463,840,599,836,845,60,120,316,614,816,144,725,457,307,949,431,957,925,883,918,215,573,592,291,849,119,68,708,962,659,117,232,755,919,283,433,378,718,570,353,524,32,872,893,107,215,21,630,35,638,173,187,594,769,242,199,299,739,696,31,836,554,703,871,938,208,759,734,10,324,831,331,35,621,892,469,33,348,796,345,318,320,815,825,282,668,907,402,646,923,913,819,800,959,254,972,64,0,327,944,277,707,5,885,775,158,501,181,734,532,787,186,528,83,696,875,230,690,318,45,349,650,211,844,735,173,482,811,370,538,724,17,86,333,116,12,677,847,220,261,373,912,931,506,910,999,621,17,124,729,557,186,224,234,532,427,901,747,138,897,730,129,933,419,741,352,176,202,641,416,259,668,162,377,606,573,87,824,530,282,835,635,654,146,309,218,340,314,522,998,65,2,399,348,437,969,461,839,700,499,247,480,865,771,899,99,885,560,260,893,535,14,622,535,638,909,430,487,662,371,849,27,349,361,151,620,97,732,419,162,95,352,792,434,96,689,542,392,653,774,292,527,10,86,982,331,302,158,383,260,762,253,612,30,875,535,214,296,474,178,973,582,637,817,227,474,730,361,781,428,100,825,523,844,802,60,832,790,51,19,325,995,811,772,13,624,176,269,941,454,967,272,927,863,879,799,230,852,222,233,484,646,341,215,53,707,657,372,255,381,855,900,157,725,690,313,836,937,621,337,961,75,152,797,583,420,931,855,800,685,997,47,598,863,548,72,44,60,903,103,422,212,605,294,591,280,251,21,105,499,730,433,509,579,567,769,144,800,642,889,481,944,636,523,302,670,964,340,501,599,129,86,738,694,775,770,436,886,37,421,138,998,33,385,136,200,981,625,528,857,852,486,321,171,207,62,949,81,515,893,239,708,169,176,26,571,563,796,636,625,7,738,335,700,393,515,445,253,714,722,180,153,32,198,639,200,670,127,245,952,779,289,858,994,303,552,173,839,76,560,702,77,202,188,81,656,938,926,635,575,539,546,807,176,434,9,87,535,644,121,840,690,381,133,697,757,34,710,547,704,25,327,537,653,635,12,708,577,978,494,813,698,149,54,518,514,153,899,527,907,998,577,763,563,902,183,558,966,741,36,449,510,293,527,148,871,64,931,296,280,601,913,964,194,785,666,417,758,134,32,382,914,740,850,879,710,694,114,241,243,321,958,16,126,450,733,973,199,15,327,152,111,636,79,443,498,18,334,623,632,837,562,35,473,26,354,343,526,667,691,685,101,115,171,609,641,194,187,968,157,427,510,23,444,693,388,348,71,935,253,247,377,900,660,811,717,567,884,844,175,238,610,615,605,838,134,680,589,504,998,762,580,796,194,388,278,54,198,491,470,902,729,235,788,491,478,579,161,175,443,162,177,368,344,508,949,968,647,266,338,141,69,144,670,45,932,455,124,678,712,380,145,179,966,928,211,856,170,760,846,513,322,789,978,10,47,965,759,802,551,977,841,23,980,926,210,64,215,182,150,989,789,668,85,379,869,775,383,646,569,340,358,528,762,575,903,180,482,573,568,368,350,533,165,66,494,129,493,610,41,599,410,200,252,58,681,530,599,578,255,611,56,519,571,610,379,391,493,989,664,216,342,580,220,632,299,919,943,272,877,393,729,378,684,903,70,32,79,972,756,761,664,793,405,196,763,534,587,40,317,131,675,747,985,699,57,526,665,138,55,648,250,466,932,658,28,333,242,145,662,576,887,121,325,384,115,171,3,928,816,493,553,615,74,331,412,941,848,442,741,21,275,327,166,523,892,793,265,711,555,788,697,678,96,939,604,144,892,643,152,713,989,572,827,316,799,681,635,6,623,537,272,265,781,474,67,159,449,810,178,880,99,84,982,739,893,144,433,160,727,760,533,10,362,170,335,977,74,100,538,536,109,401,874,950,946,425,913,164,698,234,500,14,35,700,422,120,606,460,959,171,506,201,90,961,556,73,153,467,563,239,534,328,724,104,815,13,662,910,760,519,354,46,441,36,252,504,374,907,989,450,804,234,548,325,366,828,453,777,30,106,929,526,301,871,676,483,183,846,11,915,79,793,679,401,525,907,532", +"573,184,534,212,528,559,228,868,45,223,581,97,648,813,957,754,59,816,84,844,148,358,370,881,667,643,974,339,784,291,283,949,234,765,161,222,238,583,442,106,868,687,337,653,188,932,94,89,269,767,354,460,730,525,945,203,686,762,510,901,595,691,78,141,928,309,323,813,488,308,129,969,683,682,29,196,693,437,920,496,41,373,260,396,813,806,118,646,270,961,106,816,64,674,556,34,437,917,716,346,87,301,119,360,575,791,581,936,32,462,160,547,275,945,53,857,473,512,234,384,576,964,831,606,472,915,810,269,977,834,205,972,310,874,598,230,209,26,164,829,341,57,641,809,733,649,296,894,743,527,183,968,888,542,939,767,914,371,435,264,818,527,629,224,48,505,969,269,153,327,0,66,476,45,857,582,690,849,521,462,606,892,259,528,798,798,616,896,539,468,777,173,756,839,328,633,276,50,788,441,277,215,288,947,849,443,643,360,867,305,348,239,527,508,548,553,399,319,719,805,20,766,835,536,395,55,101,776,98,926,23,64,704,624,350,265,659,546,608,975,181,255,461,775,549,694,427,65,475,162,844,666,802,468,793,214,449,119,588,174,562,835,158,660,688,73,187,489,114,216,832,184,637,195,706,989,987,61,60,204,666,201,589,273,592,569,598,570,57,680,891,618,324,993,972,574,689,200,762,143,859,552,456,53,168,258,677,28,884,716,157,716,350,708,539,68,683,561,476,576,146,427,617,722,572,873,155,892,464,328,33,162,700,591,967,872,554,830,776,168,655,350,88,84,941,869,825,803,56,757,656,364,132,229,345,764,155,57,76,635,95,744,676,290,166,18,527,938,405,702,140,522,818,679,34,342,354,539,377,13,443,201,582,883,865,736,729,638,930,791,109,447,227,580,134,807,555,272,264,95,968,294,697,426,224,344,376,31,349,371,568,590,375,713,197,486,827,393,748,82,500,431,58,922,240,706,78,856,903,50,630,102,987,132,744,418,528,718,381,99,12,398,750,357,274,484,376,101,431,498,215,155,933,700,517,785,9,792,536,124,761,722,173,904,194,805,438,495,695,176,617,783,141,334,493,850,901,798,953,817,44,831,782,492,430,319,878,61,529,390,457,186,34,659,989,290,123,828,425,729,521,348,989,512,953,566,151,701,727,505,417,787,526,515,453,325,788,756,586,58,773,843,339,100,248,489,914,589,190,715,64,707,334,612,958,856,134,398,651,962,658,332,723,631,605,10,896,66,826,410,177,791,244,746,766,265,945,686,449,362,503,450,939,117,592,32,88,320,498,461,523,588,26,789,648,518,279,655,965,243,641,537,153,935,151,48,529,798,446,219,968,195,609,702,569,74,542,627,1000,979,604,227,547,240,998,330,617,298,91,937,101,3,278,169,403,208,833,409,740,901,330,165,692,149,950,991,546,476,416,136,869,513,221,150,287,231,319,90,788,447,223,190,574,972,380,574,664,170,212,204,938,67,184,817,336,75,964,689,296,853,503,516,60,995,28,416,629,610,802,369,424,453,583,230,781,209,222,614,76,365,719,823,110,106,437,569,982,916,275,603,841,127,910,359,321,367,898,788,662,513,705,910,335,765,337,579,592,250,604,942,55,905,920,117,44,487,99,950,173,691,598,697,508,603,836,750,648,652,202,966,963,860,701,752,187,540,826,184,623,439,733,853,472,559,142,204,102,435,32,721,448,274,727,698,297,459,613,142,317,274,416,615,298,819,463,910,362,333,805,673,572,915,81,952,586,374,196,773,7,984,198,237,857,823,844,857,319,202,429,319,324,286,57,493,554,77,372,231,341,635,359,616,543,748,999,773,291,285,737,660,502,697,899,781,736,166,266,222,767,974,445,800,680,835,263,352,606,976,826,978,19,444,643,207,820,873,708,519,127,72,804,13,486,790,947,349,785,700,919,99,694,784,801,22,69,556,226,358,415,617,745,992,578,299,780,441,822,438,590,251,128,984,908,58,7,929,97,482,744,352,632,981,572,494,117,390,708,607,79,379,992,521,586,343,549,447,565,925,867,527,968,301,213,249,768,646,860,503,195,378,161,45,107,941,318,826,701,864,175,416,882,426,186,846,83,966,150,70,817,537,651,68,659,378,751,67,851,212,336,727,636,771,54,804,63,175,602,276,615,114,848,597,192,581,326,62,742,139,85,34,949,377,216,848,924,888,145,935,96,53,925,192,447,949,351,826,572,386,7,908,142,695,427,134,193,24,274,277,88,262,401,788,851,502,581,831,595,201,330,155", +"379,321,846,366,724,476,771,436,195,626,518,473,640,60,126,34,350,936,595,395,608,928,814,164,346,976,171,173,743,579,773,305,275,617,275,413,856,153,22,766,402,987,629,119,661,820,961,160,290,798,817,24,897,732,545,109,933,987,373,837,387,97,419,711,343,465,461,322,851,343,625,326,7,339,999,333,622,423,123,292,903,132,255,173,536,277,283,962,509,725,915,680,505,52,510,517,250,430,360,127,964,8,669,195,454,348,615,61,217,940,245,659,910,326,987,859,839,31,238,283,494,890,885,992,226,10,247,628,805,894,341,755,892,720,30,967,272,734,716,350,450,474,815,437,562,220,960,808,909,180,578,771,110,412,334,590,507,541,536,488,171,155,503,238,367,25,926,468,270,944,66,0,868,730,795,927,8,596,499,172,956,394,154,879,320,684,928,300,392,588,431,717,342,392,317,217,540,79,953,285,552,834,662,402,705,317,563,923,428,441,817,474,838,927,401,513,938,845,500,833,559,785,675,783,964,446,456,283,960,615,507,463,157,694,255,514,393,708,764,771,541,873,89,154,649,345,892,38,745,20,730,433,928,455,390,212,151,57,237,739,614,369,200,186,255,549,186,481,93,83,831,48,888,95,330,286,326,288,10,134,489,813,454,52,132,544,551,164,507,326,678,964,114,816,214,345,856,205,281,368,536,643,416,366,692,427,679,199,521,348,503,243,936,572,432,586,497,712,10,724,169,426,3,183,374,169,74,75,559,941,580,375,66,377,166,954,190,954,82,918,167,640,893,232,604,95,737,751,695,143,29,841,298,309,355,84,264,386,748,764,281,310,112,58,134,252,30,275,328,198,449,113,995,821,266,272,419,754,899,815,59,911,502,595,79,392,139,933,730,627,780,375,233,760,3,263,772,891,628,346,658,695,542,993,656,385,844,880,642,601,115,945,701,494,467,41,760,663,980,627,509,923,440,593,492,485,731,317,34,739,993,573,408,302,80,46,304,229,156,638,462,282,308,943,300,831,162,720,142,937,603,985,462,871,144,759,134,815,103,819,867,52,590,87,727,437,226,476,479,83,956,366,684,474,207,255,211,986,889,811,692,621,667,505,358,370,859,772,192,531,76,406,781,404,824,849,59,645,8,327,776,926,417,912,373,754,318,401,887,615,26,799,193,782,253,553,839,991,158,504,861,419,198,427,359,909,118,833,496,857,59,176,699,112,293,187,572,752,813,925,579,949,816,882,42,831,720,994,319,325,797,713,605,13,868,360,575,481,176,750,506,661,973,108,984,287,778,615,168,391,412,683,848,594,902,68,392,606,419,705,554,279,739,515,916,720,531,86,426,568,161,295,77,960,840,417,722,239,670,863,55,812,317,626,174,382,249,910,518,488,299,778,523,982,142,416,999,879,418,406,186,211,97,670,492,987,879,373,261,181,435,849,129,870,778,60,221,641,3,914,930,308,679,234,827,760,886,203,348,676,896,848,82,586,894,386,327,704,846,897,266,900,43,221,172,386,134,250,713,234,522,223,671,696,109,559,506,554,180,189,494,233,622,578,725,781,594,754,79,531,87,25,118,251,463,592,541,916,589,715,333,88,981,692,46,121,529,620,759,746,57,199,831,44,711,35,587,853,68,556,131,206,770,780,276,500,15,202,843,603,343,429,852,236,244,638,705,430,573,537,561,985,433,899,425,913,136,619,589,401,558,374,777,10,483,937,21,58,223,505,719,758,964,640,449,946,432,344,285,566,626,424,102,881,211,427,191,29,970,23,688,200,28,402,900,351,932,678,397,855,618,268,385,883,41,854,151,930,907,186,900,611,248,757,723,487,181,844,445,883,695,826,30,217,486,307,396,556,293,18,36,114,306,302,727,896,778,271,232,379,918,154,545,392,759,799,861,177,998,105,424,471,835,898,303,306,205,363,925,211,195,826,900,681,247,764,819,313,885,47,677,929,163,649,433,304,482,74,540,955,654,187,911,883,452,764,244,349,924,874,612,910,423,929,740,996,336,632,588,227,902,813,178,571,800,184,279,658,335,945,421,346,400,345,939,563,870,904,112,558,312,596,673,154,943,970,248,334,945,766,65,760,871,328,319,597,21,43,816,896,267,356,846,392,215,105,453,743,160,12,61,189,849,207,56,399,179,430,597,332,397,294,580,845,715,629,235,909,789,406,947,272,788,856,209,43,657,384,87,348,373,367,89,111,393,593,122,359,845,273,685,241,186,408,387,915,66,387,812,510,386,113,103,370,775,163,188,678,667,563", +"875,218,415,680,947,446,698,86,375,801,280,293,460,483,819,214,252,572,910,73,777,739,427,395,848,756,282,84,492,372,790,879,341,360,425,70,491,511,728,862,445,847,322,126,929,282,20,518,976,511,614,192,592,226,569,795,504,653,629,837,453,783,117,822,179,466,635,290,841,659,414,761,43,198,634,664,630,552,876,342,831,691,889,354,320,761,425,40,404,271,953,363,759,64,381,652,923,578,732,813,171,996,321,536,811,481,196,309,812,930,297,853,687,777,543,667,561,580,482,771,833,248,51,903,718,230,578,269,454,627,827,823,114,557,179,990,328,929,584,86,974,369,301,979,859,447,917,590,423,164,107,782,188,786,339,292,972,301,526,940,542,245,538,489,610,843,409,73,883,277,476,868,0,108,957,740,669,187,756,453,31,960,430,395,450,904,544,449,798,124,387,703,670,50,540,395,935,518,948,253,683,608,231,950,586,650,16,962,82,59,757,586,11,842,119,91,160,599,566,758,904,401,264,220,809,626,801,414,195,272,993,968,226,784,53,325,337,846,969,783,994,160,484,430,40,9,924,487,633,732,796,512,929,44,76,146,436,190,356,691,466,339,602,946,126,279,146,228,455,374,170,165,159,220,429,115,276,449,528,978,508,529,309,188,90,208,846,352,586,997,931,410,258,624,170,123,205,518,212,977,632,171,864,603,66,382,762,111,532,609,535,741,602,635,866,500,544,14,201,284,832,656,669,397,268,977,679,273,756,695,460,335,62,578,987,337,254,605,277,550,625,449,266,592,58,73,696,75,228,710,772,445,365,993,733,85,240,318,337,149,589,376,115,593,109,285,890,297,457,38,636,766,202,579,447,125,466,498,101,336,239,367,192,219,300,163,643,379,774,370,107,786,17,258,35,87,760,595,719,319,506,691,570,14,358,930,117,2,304,853,432,373,192,241,219,307,515,37,176,237,68,860,795,886,577,103,563,3,773,326,870,138,973,355,724,627,4,939,784,645,89,66,40,181,249,671,941,972,850,73,496,849,296,585,811,486,297,875,26,101,389,678,669,416,139,660,347,767,687,561,11,363,223,489,624,639,817,705,59,189,174,43,358,611,860,652,870,681,45,884,515,7,471,14,810,319,95,616,291,385,448,798,406,538,981,785,692,842,676,662,94,365,494,508,695,449,640,718,630,81,798,39,80,453,334,953,252,532,525,902,563,54,857,671,722,511,594,861,83,467,88,324,268,79,278,764,295,68,20,14,396,260,2,936,244,76,349,953,947,340,589,98,800,53,45,724,865,611,697,660,754,646,357,499,230,95,850,258,335,268,205,331,35,764,963,179,39,98,885,456,622,217,254,160,222,447,976,968,965,240,634,422,320,822,882,783,133,467,642,561,266,278,440,326,371,963,374,314,376,23,803,636,695,917,912,612,67,527,351,926,524,370,321,106,275,851,604,886,957,229,427,766,638,825,655,298,35,749,268,381,455,816,841,603,327,737,974,5,901,855,135,213,998,137,371,665,571,762,253,967,401,432,532,752,92,375,226,103,748,496,560,862,263,304,15,861,815,876,622,782,428,441,627,737,792,669,198,994,402,47,723,76,534,440,22,931,446,916,649,913,458,735,942,151,303,856,191,619,22,705,175,838,971,723,274,100,301,709,355,514,383,681,551,469,499,760,251,485,862,903,352,31,14,485,235,359,544,863,130,651,102,501,745,201,35,901,804,405,776,222,156,15,882,131,762,299,498,698,418,176,590,769,329,491,276,723,947,651,893,440,160,95,884,921,515,172,531,574,939,410,930,998,177,603,105,244,994,214,864,368,590,248,356,376,98,887,656,564,185,215,286,431,36,307,348,805,594,947,714,44,251,848,329,450,216,644,846,28,993,320,103,575,326,146,563,705,984,753,378,557,592,124,542,508,100,857,127,137,244,634,113,443,387,182,332,664,954,805,431,352,945,993,780,187,104,56,84,213,247,724,28,695,575,636,721,529,280,652,504,181,763,234,621,52,895,534,158,619,983,340,422,765,77,38,114,766,904,124,994,596,369,302,56,180,655,65,382,864,556,870,643,698,79,950,246,794,317,60,799,165,492,73,791,235,656,87,537,644,837,744,167,319,466,632,416,296,855,961,956,398,110,417,864,741,44,90,897,136,173,534,244,154,599,464,972,870,120,443,577,991,704,517,20,743,163,688,505,751,356,486,774,485,646,496,496,11,784,439,392,346,650,523,802,894,900,191,19,414,274,551,608,226,648,571,535,374,530,385,726,142", +"620,878,993,482,269,7,371,47,94,650,188,594,869,650,14,761,457,906,152,166,620,599,285,114,341,804,547,322,285,187,542,395,559,750,553,667,154,70,918,266,154,627,600,830,533,884,760,446,111,921,390,11,480,811,437,960,114,104,818,345,75,815,431,924,406,107,561,181,172,339,766,986,328,117,231,396,504,707,969,717,335,25,698,749,540,218,262,18,699,227,990,365,541,692,855,671,612,755,973,633,232,602,97,464,739,449,921,996,523,834,117,485,665,510,495,324,159,906,490,431,368,915,938,95,533,810,795,174,553,929,15,82,40,159,880,8,968,54,916,65,359,747,225,917,614,809,928,477,786,684,21,333,75,536,716,457,81,163,919,858,993,340,884,864,540,751,386,915,818,707,45,730,108,0,606,86,267,114,287,422,638,408,943,716,720,780,503,332,618,67,726,134,612,462,671,213,702,996,636,963,75,131,666,455,255,600,753,663,332,306,912,768,979,444,446,948,818,119,158,186,400,301,354,196,146,12,697,178,154,681,937,261,296,179,372,522,643,597,67,246,529,775,727,180,760,958,57,486,103,986,64,930,650,277,824,609,731,62,675,273,274,791,750,710,431,721,572,791,865,14,963,481,349,271,139,752,974,737,385,254,422,227,40,969,140,592,374,28,259,656,857,428,202,112,423,441,127,756,38,944,722,7,98,468,716,643,262,567,991,810,739,339,773,980,150,557,677,208,62,253,168,724,361,356,195,536,897,191,931,41,321,702,764,851,804,870,823,408,82,451,689,957,779,114,929,917,559,192,404,734,472,35,521,79,938,254,974,302,454,683,682,468,546,760,423,186,248,401,155,857,987,47,161,527,773,164,700,323,550,829,107,925,521,7,603,530,204,467,994,509,566,979,159,34,684,493,922,154,636,570,712,784,105,779,223,44,945,528,205,921,94,867,113,491,185,697,554,376,712,826,136,13,940,143,52,267,34,321,565,729,173,800,406,956,697,786,155,894,841,381,446,536,791,713,842,805,311,671,953,418,780,720,901,79,64,177,253,140,251,739,89,89,344,96,334,828,625,839,725,43,65,438,229,147,291,928,465,33,212,794,623,969,812,908,15,28,904,931,891,13,384,470,751,223,431,33,833,745,347,153,313,292,321,975,548,996,192,513,123,633,986,506,67,560,865,832,723,240,350,739,654,285,661,204,216,155,37,884,210,671,576,636,503,69,815,377,739,866,625,998,578,965,875,831,871,139,352,499,373,671,301,973,546,168,323,445,417,65,769,570,324,204,696,388,845,418,878,608,672,29,410,776,524,491,570,359,258,333,618,635,825,477,472,75,505,599,306,97,923,331,465,556,448,400,508,515,100,888,110,876,15,682,428,961,572,901,894,589,390,438,212,4,878,746,52,399,192,777,434,59,815,708,210,417,783,733,443,661,989,244,938,847,944,647,908,665,236,534,370,871,943,222,941,340,994,109,903,60,903,639,386,280,417,838,684,527,210,956,534,339,428,934,432,394,710,509,51,708,893,62,882,564,668,57,571,653,566,249,146,536,251,142,98,234,128,443,766,448,389,383,481,594,983,308,524,107,703,147,308,369,97,150,152,382,739,724,249,177,232,445,590,951,514,786,688,8,415,419,283,798,885,678,736,849,485,474,494,825,271,163,534,874,547,181,822,155,929,238,622,243,295,567,329,185,615,380,751,973,633,385,279,316,510,818,987,483,60,322,376,152,977,528,582,579,100,146,148,426,864,23,659,239,301,479,528,470,503,417,479,745,721,432,744,880,809,604,594,628,21,548,149,991,234,984,129,208,578,568,214,998,72,394,610,78,476,57,688,261,984,438,525,423,807,773,390,123,107,779,1,734,639,669,402,652,893,705,342,154,261,667,737,708,371,355,509,753,291,262,165,613,201,186,284,857,976,588,786,623,431,386,157,128,625,474,763,212,168,73,246,132,506,828,293,627,401,634,42,49,622,206,934,698,918,894,20,620,60,565,384,624,746,225,601,524,616,395,613,307,360,842,891,189,112,697,622,142,594,974,354,282,793,959,816,894,23,988,24,353,981,391,391,556,309,196,80,700,414,136,547,794,446,565,469,625,409,94,749,112,183,956,121,126,25,503,809,309,961,747,599,909,853,854,653,255,196,981,168,584,694,319,542,421,922,654,255,514,969,432,439,551,312,983,487,14,276,820,954,2,185,104,767,892,460,479,914,852,97,234,854,509,753,460,337,385,816,900,329,295,40,683,684,980,129,275,306,228,273,599,302,996", +"294,919,977,876,7,431,882,806,57,714,924,643,473,935,573,210,638,641,289,162,336,903,808,98,194,197,884,623,95,731,531,559,265,390,718,818,195,350,31,806,769,323,4,688,116,361,979,556,624,902,967,352,212,34,385,305,179,14,486,101,798,688,227,27,330,16,989,111,628,349,300,823,504,497,39,258,753,847,514,345,842,38,886,744,729,97,900,32,395,231,589,636,220,373,322,255,610,914,439,553,860,776,803,6,893,16,304,474,151,211,937,675,639,856,660,347,890,791,619,281,541,746,303,511,557,227,214,481,243,588,690,34,554,733,804,107,561,935,381,481,230,643,476,320,875,874,256,140,362,541,290,269,493,657,558,650,3,9,479,679,272,768,480,363,845,884,329,300,408,5,857,795,957,606,0,963,612,518,99,450,661,446,272,803,836,863,715,373,354,651,541,911,200,50,139,219,949,793,659,849,760,444,78,424,966,877,47,244,459,626,612,551,655,357,329,308,835,520,527,865,604,588,980,659,375,143,38,315,363,251,182,364,835,187,673,148,753,370,926,653,809,374,361,754,210,876,265,697,788,713,303,138,207,744,88,347,700,583,448,996,999,739,747,907,610,350,317,50,930,241,374,583,602,915,409,15,744,143,818,523,98,383,472,518,304,578,5,363,102,648,892,832,734,707,496,218,995,625,395,986,930,128,328,543,106,979,621,843,464,276,938,632,906,266,422,204,378,172,535,622,919,20,432,960,678,41,438,217,266,925,53,962,486,986,654,88,191,696,209,590,899,680,518,502,579,317,105,322,320,79,195,269,62,65,786,559,633,633,65,630,704,971,165,439,460,617,538,39,140,577,96,101,330,581,516,2,958,242,846,264,129,179,129,728,306,956,604,93,42,929,443,124,529,443,273,54,291,121,168,190,28,191,539,950,523,960,372,777,410,703,194,409,282,950,96,636,115,336,616,280,697,705,135,909,922,815,814,135,952,403,27,310,98,316,524,299,97,254,711,229,271,764,860,786,564,796,315,259,897,151,510,494,892,981,822,295,381,670,822,73,349,378,146,923,138,216,197,615,205,863,862,95,744,552,148,371,147,252,361,369,960,723,94,636,341,431,25,855,884,799,634,820,29,333,358,547,784,925,489,873,872,394,697,805,522,334,802,422,419,547,337,621,968,448,396,514,572,409,92,123,737,930,84,753,108,975,157,293,370,713,737,135,827,328,378,885,930,788,811,721,960,551,792,253,397,911,67,992,55,771,922,450,543,364,602,33,566,157,526,41,764,586,24,167,756,966,296,622,517,135,226,567,23,2,922,597,523,394,21,47,390,54,802,507,584,933,873,830,725,448,637,244,145,918,774,412,616,164,913,119,584,887,321,15,54,342,482,302,415,543,122,439,322,45,142,473,415,596,2,468,366,626,903,967,47,69,917,120,148,299,15,645,739,9,223,743,619,818,432,642,615,221,901,398,364,976,859,164,82,580,62,29,967,360,509,408,144,611,772,435,235,143,335,491,631,170,401,747,399,792,293,570,274,523,662,433,686,314,955,756,919,692,409,983,5,794,880,847,52,118,92,948,344,538,88,515,590,291,623,112,964,431,665,290,952,990,950,818,338,315,546,408,104,153,788,579,117,71,250,218,561,191,730,464,997,121,335,253,485,194,565,676,103,940,590,198,759,647,866,647,696,956,343,893,231,112,171,103,535,252,323,885,437,714,644,904,853,655,308,707,894,344,258,44,643,803,927,275,858,381,114,595,313,673,34,45,82,74,257,465,724,814,773,254,485,601,30,88,60,239,135,857,943,45,129,752,752,497,280,94,897,990,10,599,439,896,880,122,306,353,149,695,834,541,757,121,572,518,310,737,488,512,355,639,164,406,765,397,882,881,221,634,421,346,881,416,91,264,808,962,38,273,819,839,644,141,479,223,236,505,506,495,84,850,427,778,122,269,586,464,361,565,349,811,594,886,205,772,468,204,758,263,62,428,523,697,152,809,297,557,872,931,337,583,861,411,859,501,797,650,111,398,839,362,375,281,132,52,289,294,883,198,179,659,951,871,759,715,220,129,654,195,762,269,369,102,295,868,827,503,293,657,450,201,948,219,218,64,704,639,426,292,643,396,60,366,986,146,839,7,572,551,532,679,835,7,328,535,550,131,737,716,861,359,404,560,939,183,630,850,653,120,652,215,266,760,106,404,408,397,848,515,613,295,10,890,231,113,719,658,419,888,202,746,318,40,98,68,868,30,73,320,637,272,167,891,380,755,554,683", +"452,841,910,431,530,981,533,981,589,197,223,262,588,200,342,141,43,438,681,661,460,259,288,131,702,361,937,22,268,514,670,648,618,580,317,330,193,320,479,575,95,243,364,377,307,649,643,430,591,641,624,743,407,78,431,689,342,310,526,284,379,208,306,944,844,847,519,738,747,780,587,492,69,247,226,778,430,782,764,14,920,545,101,793,849,300,834,155,309,834,641,376,321,340,424,726,378,469,983,509,800,655,322,220,866,695,46,901,880,535,274,373,851,173,280,824,947,956,566,360,463,971,626,926,27,358,789,429,671,74,698,816,443,101,293,620,640,756,598,673,587,448,690,112,665,910,942,281,897,841,868,754,537,428,882,989,740,868,103,724,9,390,439,496,948,228,276,856,696,885,582,927,740,86,963,0,961,630,883,31,969,86,135,935,702,387,391,546,350,216,393,539,77,940,899,825,922,791,339,39,323,829,548,333,79,690,366,906,537,783,386,530,169,910,178,615,199,658,645,118,881,422,912,614,60,341,899,518,992,625,195,514,887,275,85,704,749,58,67,555,734,650,44,674,768,145,993,287,886,261,671,649,793,356,726,890,73,358,693,431,45,635,631,422,188,544,597,189,250,615,755,734,623,538,947,244,279,330,164,359,71,845,338,39,846,300,611,639,712,2,477,328,989,145,95,370,250,95,984,804,952,83,415,960,683,917,729,63,284,586,427,517,606,303,106,251,409,935,721,170,520,868,472,250,867,776,664,107,581,415,572,622,981,891,714,314,826,916,801,967,34,145,362,677,448,617,68,882,738,384,145,403,992,347,96,571,775,215,182,655,349,639,379,371,496,779,65,405,402,448,678,59,728,777,657,122,203,728,711,597,884,874,471,975,964,171,776,929,636,319,246,963,507,65,606,198,718,228,352,672,11,645,348,695,660,846,88,702,715,777,900,829,849,117,636,160,943,704,92,30,25,812,591,798,636,184,486,184,479,900,47,635,770,606,377,105,824,181,696,560,332,901,716,507,540,98,110,36,373,150,674,498,397,669,650,477,748,175,573,949,203,823,752,363,239,193,229,581,271,860,208,856,530,170,756,604,485,25,262,818,303,550,918,172,484,838,263,126,993,596,77,713,805,150,256,341,36,508,640,865,886,950,481,514,431,866,552,552,729,662,771,641,821,811,206,479,650,136,123,660,848,470,661,323,148,442,207,152,391,100,402,186,322,268,54,158,734,571,206,588,196,388,461,690,678,994,753,940,890,928,300,311,31,863,800,39,388,615,747,99,938,133,754,101,544,583,248,939,643,607,767,294,156,118,233,580,870,221,420,113,472,424,782,384,393,903,914,527,350,998,986,684,943,173,294,783,640,725,133,711,174,423,861,635,859,757,667,625,4,253,354,31,363,696,467,289,195,882,512,979,603,674,860,198,204,645,668,985,90,384,671,73,78,13,865,485,928,71,414,36,563,932,662,521,256,658,223,89,271,526,585,685,113,675,222,571,201,61,852,866,358,274,122,229,471,869,546,578,340,394,432,377,334,317,371,606,830,84,218,565,886,842,496,920,400,417,842,334,655,587,395,969,345,415,70,442,752,84,533,612,817,83,992,925,756,722,369,769,363,817,807,850,866,288,520,943,498,180,496,726,96,149,606,180,401,49,98,740,218,646,338,85,183,232,815,209,705,145,923,529,953,401,324,804,698,438,412,870,202,498,131,737,791,622,680,461,744,704,791,44,193,56,301,258,612,272,338,632,85,93,508,978,359,184,486,787,524,957,446,136,86,639,818,898,751,630,269,855,92,616,906,878,741,495,339,32,151,577,10,792,246,962,237,226,550,932,436,873,934,811,958,116,147,565,909,661,245,128,708,467,297,71,458,298,409,201,915,76,918,762,669,129,667,749,196,753,332,296,538,938,357,541,29,623,299,782,993,67,408,695,608,771,415,278,931,323,351,535,894,225,110,944,897,147,771,746,764,274,966,154,853,177,595,39,748,505,99,74,655,322,906,445,178,135,800,988,182,627,115,276,857,719,250,240,774,214,139,584,221,866,806,596,543,909,541,260,622,413,759,76,975,66,505,813,593,42,743,743,798,860,800,704,599,611,241,747,176,67,152,211,847,416,346,964,686,717,866,230,896,634,729,490,864,957,38,769,785,616,21,804,24,479,839,25,788,696,546,741,210,456,750,637,302,908,280,768,172,233,515,120,973,284,60,393,325,454,572,790,515,73,423,23,370,741,959,278,409,844,629,741,960,27,71,441,152,63,603,155,92,596", +"832,327,132,961,363,181,728,197,889,186,425,253,539,613,789,746,989,940,342,414,952,842,695,921,168,504,902,708,990,201,555,780,189,999,700,349,128,730,524,285,858,986,117,479,671,824,888,775,566,84,459,369,758,222,134,842,640,711,803,373,404,842,399,106,574,675,69,68,645,947,537,643,197,202,130,852,666,742,541,542,557,161,288,834,654,8,376,471,587,157,289,175,786,766,728,6,897,87,834,629,687,536,38,501,504,73,451,811,72,600,522,242,904,412,781,115,371,508,721,764,585,441,936,151,515,5,426,962,25,559,189,536,73,497,659,132,388,539,716,325,332,612,578,970,834,638,355,477,587,434,934,934,679,875,524,357,39,591,613,846,163,30,249,368,891,681,349,200,590,775,690,8,669,267,612,961,0,364,178,759,124,142,113,577,614,291,132,400,508,552,142,221,353,203,431,656,326,901,414,239,985,355,58,512,219,542,159,461,856,107,759,326,117,339,968,627,229,832,912,476,704,316,704,51,345,90,859,369,399,739,477,887,881,728,430,548,125,224,766,931,604,367,448,230,646,980,668,939,83,574,619,652,920,742,29,981,282,915,493,82,368,974,545,769,547,600,814,455,552,848,367,772,90,754,825,196,812,700,964,683,326,202,234,75,771,831,297,328,466,266,347,900,444,88,319,810,618,946,51,469,467,727,370,108,55,511,556,584,542,482,568,139,371,729,29,150,525,285,693,892,208,437,450,444,647,5,988,958,244,864,102,302,190,671,331,569,457,609,669,728,859,548,818,535,134,654,645,288,439,526,792,290,674,259,167,432,616,956,580,143,580,595,357,600,256,708,885,914,430,551,634,214,726,34,118,549,977,363,663,549,71,424,218,439,422,466,784,417,454,273,321,864,781,596,340,733,818,181,137,302,744,702,316,517,332,957,943,732,388,398,310,728,741,660,397,483,441,749,293,141,689,116,655,986,454,305,42,995,638,576,515,389,46,136,773,307,232,884,834,28,457,349,356,809,475,932,800,465,886,658,919,309,677,288,684,979,52,477,410,693,878,563,998,768,560,206,627,386,811,395,486,624,217,303,747,838,65,681,44,955,949,780,68,36,865,257,866,32,12,866,220,39,314,479,621,203,754,589,880,360,156,736,724,888,670,709,297,149,21,220,138,431,11,911,623,662,233,562,955,466,372,817,9,751,432,263,784,736,534,215,539,491,206,497,834,476,760,497,878,67,47,125,127,748,800,476,65,547,388,663,184,275,283,12,651,326,129,235,292,879,286,682,309,208,730,304,706,100,123,671,188,698,468,956,837,537,927,507,12,602,374,636,619,839,663,766,565,370,516,591,179,908,762,660,16,270,379,724,610,381,699,592,681,37,655,84,387,745,177,125,41,163,296,456,557,447,144,40,635,877,9,384,584,768,355,933,88,558,975,459,105,77,766,940,408,215,930,239,670,679,144,359,851,727,113,763,467,705,53,817,475,35,580,546,691,128,887,965,9,476,403,162,303,831,934,690,92,765,393,670,143,943,477,427,868,337,406,557,453,407,361,513,737,737,76,792,23,245,786,759,818,967,298,838,410,364,480,825,220,721,702,363,942,687,100,206,311,357,679,130,310,32,356,862,595,643,326,465,299,941,920,621,731,3,409,841,990,845,402,575,438,352,271,88,928,709,610,169,82,809,463,669,74,413,747,835,523,168,462,928,547,812,865,930,176,77,494,798,564,394,461,357,306,418,716,215,375,263,472,513,357,605,453,151,707,479,432,760,986,44,925,113,28,456,486,38,226,875,959,729,968,274,293,933,646,582,463,393,3,235,263,919,276,822,647,980,729,142,302,123,896,604,355,853,706,826,221,453,764,257,595,371,866,889,799,845,198,629,169,553,240,971,297,254,400,669,762,247,67,640,272,2,427,956,522,31,134,195,98,234,549,575,541,556,598,738,451,212,57,58,334,73,426,743,914,606,663,993,140,213,483,849,448,751,996,909,46,365,874,90,942,394,900,43,993,456,26,854,326,205,879,161,8,369,729,796,416,116,30,203,969,179,621,763,272,151,958,455,136,224,177,238,841,593,775,726,222,942,616,642,273,597,779,852,786,780,63,544,876,579,610,738,347,93,542,686,861,556,791,764,821,665,473,315,137,837,95,564,89,33,595,986,634,239,453,469,181,260,700,720,511,960,539,265,906,915,505,195,966,909,570,657,677,608,262,506,557,890,703,710,966,631,706,325,297,684,512,966,177,202,370,744,352,913,401,274,716,859,234,14", +"739,320,949,307,253,64,996,160,119,558,619,479,484,321,880,334,427,267,269,234,111,515,177,93,29,450,652,240,740,526,125,797,70,220,461,643,842,965,902,560,683,523,989,262,111,783,384,431,760,477,756,864,996,381,941,760,608,565,556,148,226,25,139,620,798,551,349,426,461,357,767,179,862,572,2,274,325,574,654,753,174,504,805,57,889,194,665,867,218,684,479,979,112,198,147,372,390,507,170,714,972,414,852,931,658,257,515,524,881,102,346,662,377,943,63,202,802,770,820,240,480,876,942,854,68,289,946,549,892,881,419,896,770,965,713,761,765,989,36,649,547,623,162,359,294,903,680,452,768,56,987,301,365,810,697,91,207,224,45,14,64,670,700,675,237,395,849,559,317,158,849,596,187,114,518,630,364,0,303,988,558,36,348,464,798,298,772,692,284,625,615,545,523,889,279,255,61,805,213,250,364,123,756,719,884,476,820,225,192,944,229,126,46,210,895,124,781,163,868,967,161,28,639,371,53,551,187,658,666,953,167,53,984,724,22,856,916,573,997,187,373,525,984,745,680,509,165,408,362,542,643,433,292,612,452,292,665,491,762,919,265,777,250,690,740,855,399,349,593,170,380,142,861,836,676,492,40,42,167,338,176,427,298,627,598,805,635,699,109,153,260,209,53,586,400,917,23,280,130,841,3,332,768,232,290,688,679,388,573,382,465,118,445,786,108,210,297,303,227,55,833,275,452,104,400,824,372,934,482,367,82,41,29,587,617,748,661,719,130,220,946,237,174,120,485,837,541,510,994,407,863,16,567,582,92,728,905,626,813,138,680,930,5,279,565,968,99,162,152,204,210,840,852,342,780,283,39,866,125,641,306,583,674,584,602,715,260,540,576,131,436,515,211,44,539,410,750,883,911,753,92,244,9,263,860,670,701,133,953,565,228,810,805,636,540,488,590,589,475,963,915,430,845,574,325,554,8,782,5,84,760,746,510,675,555,286,730,428,361,581,453,971,917,545,901,930,103,239,995,955,66,327,165,241,730,609,834,753,91,772,85,479,883,910,84,801,827,12,714,832,855,42,379,663,44,580,603,911,454,340,995,996,812,749,684,882,130,131,536,515,862,495,294,684,914,524,942,34,543,68,667,421,815,625,696,62,232,156,177,126,178,716,10,474,664,889,595,432,408,511,256,446,469,573,157,574,235,528,201,608,766,911,948,203,210,593,156,507,433,406,150,737,593,372,894,689,735,459,621,315,243,313,903,913,874,980,961,575,826,308,600,467,380,242,704,42,665,264,301,989,532,678,339,158,719,30,357,575,496,406,839,808,274,560,639,87,393,762,657,638,464,599,890,102,598,154,947,132,246,678,309,357,74,72,555,559,25,569,521,557,259,551,76,176,281,142,195,828,208,401,240,716,5,300,739,754,233,202,307,471,550,93,764,914,381,989,413,624,987,437,96,611,371,601,479,70,884,129,427,402,605,61,656,750,98,35,442,550,325,341,445,408,32,944,798,170,780,707,245,234,721,629,822,347,282,853,625,543,672,125,213,587,928,223,105,452,412,937,90,54,49,411,835,247,365,823,842,394,313,985,386,824,278,331,806,774,659,730,176,421,956,857,460,410,646,324,857,650,931,881,699,517,255,323,849,758,948,345,839,172,766,430,64,992,234,239,173,584,958,577,229,797,175,800,38,94,832,970,224,47,179,722,384,227,355,627,544,105,977,98,789,663,602,612,580,374,696,962,288,879,580,725,816,801,979,320,671,905,851,307,425,966,853,532,516,679,107,277,637,776,722,325,485,592,87,458,69,174,661,651,380,302,8,441,428,305,774,650,410,370,794,500,369,841,632,50,357,82,420,40,268,936,512,2,598,364,890,79,355,15,117,297,837,684,868,88,50,491,357,472,208,104,445,400,169,948,230,312,315,205,509,749,230,686,426,103,28,60,612,147,42,405,206,831,554,84,406,511,307,512,396,495,924,145,384,155,767,26,180,921,413,327,907,650,785,890,268,72,275,877,754,445,76,420,11,474,911,296,357,893,927,760,846,298,973,828,481,595,114,721,59,477,659,92,485,101,475,425,13,589,91,974,130,308,436,906,427,392,376,509,691,986,792,328,636,135,102,141,489,164,959,813,575,317,720,49,827,275,892,32,161,774,631,737,427,607,119,210,837,196,661,645,806,367,882,144,127,8,401,341,422,398,671,765,682,854,315,401,82,781,413,166,408,269,205,165,266,883,234,742,525,89,386,313,918,211,651,179,553,351", +"354,949,7,10,495,237,572,320,143,811,149,868,126,737,88,404,63,449,390,473,13,932,771,823,316,758,173,570,721,254,76,323,857,503,339,400,303,498,26,899,342,495,904,138,255,740,917,407,742,72,521,227,166,923,39,658,362,201,424,382,268,583,538,809,373,109,22,727,346,786,38,13,55,325,751,238,101,89,710,30,962,491,568,468,210,254,708,129,520,795,58,432,48,764,3,829,337,399,723,302,844,329,70,551,804,94,503,257,200,396,517,952,231,711,720,853,756,757,534,112,636,11,233,834,455,670,186,821,862,227,65,395,487,900,555,877,457,394,957,623,771,683,264,613,533,706,931,327,937,512,978,101,902,759,49,306,769,437,340,777,128,290,769,357,721,365,756,529,834,501,521,499,756,287,99,883,178,303,0,912,598,682,64,985,494,741,660,691,380,67,613,191,415,173,68,138,744,329,649,482,596,249,296,226,667,780,713,140,22,683,280,140,723,331,799,702,180,751,672,720,448,93,15,711,456,453,20,253,361,442,470,110,464,571,159,255,497,477,133,59,169,212,935,628,521,710,308,576,903,106,282,484,494,772,204,567,876,132,540,740,106,912,645,42,714,193,671,765,34,467,329,56,577,646,836,541,58,688,99,268,989,93,75,85,597,738,89,450,670,520,893,756,131,104,364,290,44,666,708,200,457,214,263,771,750,197,115,272,280,818,504,522,113,359,26,229,845,389,450,529,830,770,425,251,726,498,187,876,745,857,837,370,362,753,654,232,688,206,849,757,784,864,326,886,431,938,898,943,386,156,595,109,46,396,750,388,446,57,266,2,913,56,886,44,807,750,709,259,902,714,589,578,414,55,131,701,209,570,976,808,237,897,603,392,115,73,824,967,922,852,407,111,35,229,258,876,349,534,802,74,685,500,147,45,837,659,882,814,462,34,695,87,597,440,609,315,452,732,310,374,815,945,788,999,242,317,886,107,510,729,992,180,458,645,876,131,430,903,205,817,863,113,925,697,922,963,757,320,138,741,54,875,78,456,677,740,149,129,48,707,60,451,9,542,287,602,127,52,965,663,298,521,742,378,412,549,836,700,570,980,162,170,190,907,60,481,649,514,234,971,232,292,302,301,260,425,482,754,817,629,944,100,340,225,100,811,633,125,4,952,746,643,75,800,378,802,715,537,445,31,350,792,377,110,891,368,278,197,369,345,963,258,380,925,381,45,192,660,742,367,488,222,240,388,438,978,877,352,134,267,116,164,938,755,128,401,562,678,229,360,648,668,351,752,102,765,165,246,118,488,417,754,52,736,312,735,802,723,854,84,5,112,650,905,674,577,75,146,416,960,76,642,262,571,901,44,964,361,410,339,943,365,938,500,194,484,65,142,161,268,26,397,750,786,233,888,570,210,439,435,224,574,880,623,970,75,805,205,395,735,999,207,515,314,240,136,429,385,341,80,761,667,530,836,764,820,381,155,282,118,714,733,282,937,460,670,838,630,296,645,826,90,410,681,366,261,418,753,667,928,759,833,724,378,715,874,612,963,40,577,690,417,732,749,307,708,523,108,560,478,513,800,40,91,206,773,718,120,301,753,262,463,460,989,302,540,920,34,593,60,960,55,124,231,87,546,33,931,894,499,585,905,509,782,645,651,390,341,405,228,748,91,880,613,471,374,845,409,194,514,575,77,354,264,698,319,94,520,69,633,898,451,43,901,379,733,812,325,982,299,692,220,395,495,866,423,157,403,535,732,642,647,739,295,902,957,746,790,7,94,53,181,503,614,280,661,446,177,276,319,817,906,822,841,201,786,675,496,242,643,908,537,973,598,470,364,830,309,17,398,523,601,495,395,284,426,861,881,299,903,320,555,155,551,126,16,539,118,666,228,699,920,360,208,477,529,652,50,943,570,55,737,958,907,381,411,410,838,484,157,140,471,276,333,438,707,217,396,227,845,832,626,949,925,41,744,439,83,422,234,763,338,394,534,306,334,71,491,597,752,906,932,455,639,34,354,325,632,596,557,457,201,58,445,739,937,433,957,55,131,334,67,922,702,409,29,611,714,984,929,669,427,60,504,33,16,812,260,6,25,997,451,819,73,182,974,51,451,319,959,768,25,770,67,986,405,747,71,914,485,39,982,273,643,46,302,519,317,692,346,111,376,293,413,852,21,375,552,78,143,529,213,92,65,762,974,192,307,765,959,472,684,383,437,363,316,423,573,704,284,86,903,695,217,380,65,443,133,333,87,235,775,710,120,882,332,15,792,108,778", +"781,838,624,286,230,962,242,323,613,755,349,250,75,389,572,32,355,284,14,509,262,947,849,385,395,133,597,381,465,418,297,524,294,944,554,967,353,993,987,512,779,36,902,243,8,139,802,672,832,985,339,716,423,707,985,103,182,144,880,192,525,574,694,530,9,906,348,147,664,318,133,371,677,490,28,50,89,992,877,938,871,180,698,740,56,494,316,117,857,812,248,906,696,574,394,872,196,279,867,690,721,18,416,667,839,72,174,677,56,728,334,979,24,872,597,20,218,838,359,976,243,218,522,288,513,590,616,916,757,739,210,844,105,910,521,610,359,683,973,710,499,628,390,338,117,14,409,602,271,407,305,866,42,253,163,686,157,338,58,431,160,743,644,661,11,984,294,524,745,181,462,172,453,422,450,31,759,988,912,0,106,562,127,217,657,146,14,522,270,969,432,851,424,743,145,844,944,421,79,399,506,216,259,799,739,540,260,630,585,563,679,614,757,545,128,285,301,43,414,501,767,353,883,698,652,653,511,150,137,527,288,479,367,810,116,678,634,673,48,84,651,236,516,722,771,824,745,998,45,82,681,787,876,949,311,719,451,902,22,586,744,58,37,954,604,645,32,919,96,367,152,116,228,624,221,369,504,166,615,737,473,857,816,345,370,761,543,916,64,392,225,553,631,773,998,298,722,523,267,32,957,499,961,20,239,39,942,925,14,481,129,914,139,262,260,920,433,376,456,622,79,465,15,55,543,214,647,408,128,692,746,234,475,347,409,727,65,455,765,713,863,100,580,897,855,925,971,866,322,316,372,586,761,908,127,262,603,19,310,139,599,148,681,338,967,612,594,92,728,826,919,822,376,396,613,617,74,805,338,245,344,621,742,725,51,627,583,416,97,575,810,299,135,667,507,807,274,409,897,295,796,836,1000,85,155,144,339,833,147,189,43,666,425,88,600,294,71,63,44,720,632,325,192,390,33,428,19,880,512,217,143,785,305,766,125,332,200,844,839,470,31,441,68,805,301,379,954,468,704,128,759,399,174,393,337,203,114,641,290,783,902,703,192,192,523,210,24,86,688,808,601,851,133,615,974,237,278,732,160,687,104,938,38,757,803,377,139,338,229,160,980,184,41,414,264,673,866,838,127,802,614,994,432,800,466,783,220,549,933,25,29,204,462,384,396,460,338,751,289,406,297,53,281,185,544,715,122,392,42,533,366,962,230,484,943,148,598,342,212,449,469,374,618,554,561,907,530,24,80,273,200,382,585,251,754,150,616,136,685,287,282,873,593,816,353,380,226,186,525,495,279,984,176,474,492,970,334,412,237,834,324,609,158,195,328,621,398,548,246,779,320,649,185,517,54,640,799,372,119,798,457,867,672,380,757,941,373,311,188,485,232,150,667,886,358,688,880,257,155,613,432,200,703,904,335,577,446,727,826,469,587,701,416,88,427,902,760,908,821,291,868,187,206,591,870,188,519,583,899,650,388,536,527,836,878,287,945,175,628,649,215,620,539,122,844,885,292,685,463,531,906,685,595,796,183,786,145,190,836,244,594,758,625,714,352,565,648,497,150,453,55,669,391,793,105,165,809,371,10,929,195,913,586,613,512,248,554,789,152,878,933,2,585,766,200,358,715,77,925,756,3,20,12,373,286,308,272,688,390,635,484,15,590,183,678,447,459,217,945,309,29,361,426,78,401,210,932,455,886,682,681,71,703,182,82,381,958,329,11,886,764,297,393,611,525,324,207,840,944,666,910,240,165,509,488,807,734,582,700,981,673,783,174,530,894,9,465,521,296,892,352,532,728,770,816,65,786,659,612,526,278,707,582,817,836,815,407,423,477,74,262,790,860,302,805,522,937,725,951,72,274,317,293,314,456,863,435,998,294,418,781,28,856,196,658,444,220,681,542,464,459,854,863,372,827,782,491,161,582,420,342,293,460,306,209,39,611,90,876,715,553,634,871,859,810,451,658,572,856,181,717,861,828,213,834,636,322,87,811,533,116,752,851,307,353,654,686,119,741,631,177,182,547,316,423,954,932,721,26,100,173,306,571,452,981,996,123,382,422,651,518,813,966,688,299,360,43,552,912,475,499,786,739,208,453,383,259,730,445,699,129,143,812,784,59,829,914,902,740,773,161,79,574,775,3,452,648,852,11,413,190,341,84,104,859,42,146,698,637,927,355,229,721,307,479,473,936,226,334,35,509,603,651,126,651,952,146,527,326,692,668,248,184,561,759,314,678,322,15,558,882,104,594,764,695,786,106,437,110,821", +"348,138,684,188,683,445,143,721,371,44,797,430,351,657,621,807,4,739,386,500,131,918,512,789,869,998,564,892,292,458,277,261,457,673,759,963,94,232,938,614,77,515,532,536,587,210,35,150,63,107,160,241,337,62,247,810,763,570,303,489,553,92,598,92,777,119,725,411,734,222,247,195,445,865,237,243,954,311,190,179,920,389,849,433,275,753,259,46,173,328,592,273,8,525,669,638,195,468,393,133,31,69,308,280,625,439,260,404,44,203,103,283,811,23,799,955,291,776,272,466,925,770,425,732,461,171,651,309,817,163,704,955,485,777,314,358,181,743,629,328,157,936,518,448,450,994,881,228,421,853,366,110,957,145,257,486,751,869,394,376,295,524,517,971,563,64,801,205,465,734,606,956,31,638,661,969,124,558,598,106,0,5,861,288,818,753,486,750,353,196,39,471,428,85,877,502,609,986,413,746,32,18,925,483,750,382,760,305,764,578,593,852,54,934,642,715,287,958,684,165,161,601,222,607,823,132,484,656,378,31,848,43,42,300,466,259,953,595,775,337,169,355,651,826,77,430,663,293,392,952,525,450,560,595,664,872,495,833,667,130,111,936,869,403,402,771,431,7,481,76,894,691,712,226,533,58,793,447,193,227,229,514,879,659,357,770,45,100,500,311,745,804,507,793,721,162,779,663,186,162,981,642,289,445,227,617,634,106,409,651,150,87,193,961,138,352,227,542,958,855,382,606,29,502,709,619,530,66,350,172,965,580,187,708,459,745,680,74,482,770,442,590,992,873,767,950,116,140,562,773,750,700,746,746,280,300,986,707,732,115,392,408,276,535,292,218,388,331,273,923,570,69,299,122,511,583,491,919,46,47,814,66,94,357,319,261,140,498,3,655,44,829,461,208,426,380,749,270,220,386,687,88,34,762,170,389,481,394,234,633,275,8,793,519,85,502,810,549,20,448,47,300,945,652,34,790,211,610,763,437,572,779,268,608,422,594,56,66,940,951,955,377,873,443,762,824,768,429,62,621,308,411,414,380,307,144,611,681,638,904,725,516,503,590,354,94,140,434,790,528,917,212,304,12,319,328,557,28,377,622,620,648,605,106,146,1000,842,555,52,955,937,244,405,19,398,253,341,344,156,613,461,486,333,80,982,262,464,458,671,707,412,779,67,81,361,481,286,650,691,145,455,394,40,183,544,898,377,452,706,756,385,152,997,879,719,109,261,794,788,378,909,952,700,90,889,943,617,145,773,370,714,3,628,552,272,266,433,877,168,475,248,379,590,967,647,206,932,238,289,435,754,964,634,15,486,786,752,36,733,191,226,722,922,540,350,591,384,375,13,911,850,340,184,80,745,518,889,280,462,773,179,755,997,187,962,725,488,463,990,14,631,623,366,211,936,717,839,983,432,680,758,886,385,517,371,401,853,152,292,227,683,184,144,704,532,215,177,420,673,819,858,938,607,410,359,245,43,801,911,646,822,179,699,805,409,54,301,959,188,657,655,114,959,845,873,125,371,68,723,516,23,405,438,762,132,818,57,397,488,135,112,729,596,303,836,741,562,220,929,823,740,296,933,50,517,195,963,15,109,62,944,110,889,786,428,753,94,258,417,92,529,89,541,48,160,997,410,400,455,764,198,726,406,776,157,95,842,9,894,563,675,779,100,633,379,262,18,706,138,668,2,80,308,841,964,420,11,4,479,967,534,571,198,864,169,575,142,645,744,597,936,15,555,604,578,928,295,396,368,332,195,746,908,294,538,613,350,976,863,553,679,109,869,308,196,862,345,137,646,352,843,76,331,848,503,384,614,162,31,305,574,779,695,672,845,136,232,477,761,977,998,323,444,899,657,224,928,780,833,172,391,677,454,213,409,52,376,936,175,563,565,40,787,339,821,851,829,482,191,553,210,19,3,524,728,84,271,474,98,565,161,302,256,986,996,398,765,864,957,360,633,460,918,765,556,665,263,742,403,96,732,77,694,770,186,789,252,419,582,422,783,154,283,564,503,930,482,594,101,785,5,17,854,353,479,391,32,181,681,125,975,823,828,49,337,195,76,991,640,458,468,283,882,978,788,689,48,24,458,928,718,971,373,532,608,384,88,181,803,828,776,447,152,229,142,181,875,366,144,627,518,84,191,353,426,312,570,917,988,629,502,325,616,924,841,571,297,297,643,43,763,342,982,763,504,776,316,997,349,604,532,633,271,900,777,397,894,938,509,767,872,226,798,477,519,694,52,973,433,62,157,681,542,306,150,401,81,348,963,564", +"264,537,720,982,634,63,962,619,209,622,664,681,749,292,310,695,959,370,356,98,952,333,961,82,855,168,569,397,738,601,112,853,427,521,15,289,104,544,346,280,797,480,790,853,945,637,346,882,553,594,248,107,865,263,402,317,231,386,925,690,79,284,816,899,505,971,181,881,849,89,424,351,269,211,535,292,729,25,206,198,924,812,983,668,677,902,215,60,744,943,267,525,199,785,788,387,80,787,854,453,581,215,79,508,98,376,690,969,335,532,433,223,175,222,966,750,188,417,579,404,821,410,327,770,431,301,605,857,629,849,677,154,414,879,580,2,210,672,867,331,985,373,134,841,885,170,424,927,88,999,629,18,987,88,584,501,641,778,453,661,658,607,31,157,543,530,691,598,29,532,892,394,960,408,446,86,142,36,682,562,5,0,538,268,402,686,635,959,180,317,426,496,519,111,239,939,455,273,396,95,178,835,436,228,788,549,655,404,116,486,953,306,301,286,948,954,486,678,584,602,446,338,379,560,402,301,224,831,196,57,686,511,436,511,523,22,268,115,243,928,610,440,488,999,192,639,600,836,283,291,10,913,161,232,864,155,284,680,810,873,676,949,578,129,628,131,726,950,309,693,992,646,936,346,41,617,808,26,559,750,205,292,15,459,938,89,133,965,946,395,726,503,789,628,829,316,661,334,201,507,533,344,690,405,943,846,18,779,105,307,298,408,710,790,247,93,261,392,984,533,171,259,583,781,236,338,327,806,903,169,376,514,690,193,589,784,345,57,522,265,888,763,828,686,209,135,428,922,481,957,939,913,711,3,842,965,975,357,769,597,388,294,492,944,834,465,658,861,928,698,175,145,94,538,433,277,850,246,271,35,26,838,442,272,884,322,404,894,845,267,592,471,795,438,60,248,326,263,769,658,241,872,808,219,339,985,240,335,812,552,383,501,182,460,321,680,725,693,850,438,458,768,732,608,626,693,930,510,22,858,444,979,567,786,125,898,506,258,688,149,412,336,631,746,906,855,228,987,312,515,562,369,623,859,172,351,747,379,263,152,594,643,116,816,840,806,320,328,254,497,600,501,379,589,774,343,319,733,595,125,120,483,980,797,997,713,125,744,574,255,766,598,226,926,244,705,704,790,406,905,761,380,340,850,654,880,309,972,965,166,748,883,347,616,547,60,980,760,304,748,364,541,581,445,339,475,756,32,140,989,733,185,352,600,10,574,565,858,225,40,542,448,114,565,846,997,329,76,555,418,561,916,754,139,577,823,55,261,518,176,698,67,596,583,623,356,232,816,539,926,922,449,999,59,814,356,316,792,397,830,717,969,482,48,906,284,289,169,261,776,878,223,354,893,719,90,401,350,13,32,700,521,421,161,817,869,496,101,649,395,71,723,874,29,573,995,304,704,201,475,745,678,688,138,771,37,440,341,522,438,152,682,903,707,266,907,924,866,94,352,464,643,773,65,43,608,189,487,632,24,530,888,142,220,579,38,128,839,405,256,810,729,211,332,246,952,969,318,762,647,923,34,11,55,4,978,638,317,224,555,443,933,56,757,825,735,192,872,404,199,405,429,689,510,694,83,85,21,676,498,1,17,987,354,474,503,588,298,648,747,546,553,593,571,531,949,788,303,322,361,658,186,647,597,430,750,163,212,453,249,593,35,555,569,588,609,891,530,481,819,460,564,883,806,792,561,554,54,786,779,246,594,493,628,306,287,281,497,696,845,442,164,90,206,879,733,377,670,688,429,282,499,485,279,42,498,184,112,563,977,201,905,597,306,594,62,738,919,192,265,358,430,835,620,845,21,671,945,357,850,349,812,412,306,494,789,977,291,710,947,310,381,74,202,944,300,259,885,617,149,69,277,874,762,160,265,576,24,590,233,318,574,551,866,658,206,378,685,515,432,907,740,870,87,16,148,820,958,12,818,912,991,5,482,357,408,555,908,590,424,129,392,587,822,575,116,366,133,605,221,770,78,292,879,96,821,558,893,854,804,285,41,540,450,226,38,591,386,945,808,946,959,132,767,57,310,489,774,855,88,673,477,455,231,854,713,353,510,991,469,313,161,990,425,97,612,743,159,52,685,839,288,501,564,785,381,475,199,452,437,173,382,53,279,961,373,873,35,389,482,720,549,105,13,690,830,352,801,307,195,611,395,969,891,191,966,497,236,131,605,964,837,430,401,607,985,641,921,913,788,258,828,615,113,364,501,966,302,415,548,601,883,61,924,646,982,918,87,142,258,520,547,865,317,87,157,365,816,129,492", +"790,868,651,970,851,561,133,998,57,15,629,359,262,152,501,306,680,539,822,256,753,279,512,631,391,881,493,127,621,31,630,233,921,927,972,201,138,915,4,499,641,256,490,73,438,573,274,260,889,931,53,384,421,603,735,494,768,319,880,979,92,724,877,632,355,551,447,9,567,606,574,538,352,43,216,579,905,43,648,93,287,751,632,537,997,734,426,326,99,911,239,197,442,648,491,978,408,24,214,786,471,876,750,696,62,506,410,427,491,242,695,473,837,774,938,2,686,138,849,89,452,850,491,810,741,885,524,341,932,609,102,42,103,277,812,569,331,503,407,450,167,997,218,518,455,385,797,942,878,745,305,988,153,244,100,326,243,726,654,671,75,682,358,642,668,538,618,208,91,787,259,154,430,943,272,135,113,348,64,127,861,538,0,558,215,949,756,139,242,491,941,745,315,424,370,260,34,466,693,562,920,490,707,239,94,565,245,730,369,414,810,334,418,189,194,199,709,818,299,731,701,799,806,741,3,224,629,65,220,203,756,260,688,461,508,319,641,88,819,922,98,52,763,108,883,819,906,626,803,263,13,795,596,438,491,432,377,121,131,516,328,324,294,753,679,490,366,874,742,977,185,51,212,739,36,660,718,387,459,845,780,306,555,278,585,452,129,442,935,157,329,783,499,249,600,514,322,62,214,462,712,719,464,376,758,825,46,783,675,334,494,983,409,498,983,507,824,326,170,235,194,576,742,983,197,177,645,776,625,704,107,374,170,341,575,887,384,248,181,601,808,109,790,671,791,404,178,750,409,517,429,158,444,129,194,308,579,49,704,274,712,209,251,93,518,57,597,847,820,580,290,473,712,78,119,595,13,139,920,770,894,158,671,143,601,668,199,619,295,533,757,218,585,328,969,772,469,871,384,341,32,620,903,793,975,696,568,658,75,634,263,854,493,956,348,566,835,529,977,366,13,972,504,842,379,634,475,29,657,760,480,316,508,409,897,36,378,934,216,90,648,194,899,787,852,170,479,554,546,689,495,765,31,963,702,745,689,37,674,580,532,170,43,62,573,659,916,36,121,53,619,154,692,564,151,932,962,226,904,79,312,678,659,286,47,511,256,467,898,141,347,30,611,386,527,988,575,875,602,937,644,649,298,529,888,329,512,861,629,370,181,774,244,514,886,605,828,694,139,414,327,770,120,282,80,408,219,706,819,180,849,252,131,319,528,158,64,288,217,168,552,474,190,646,270,990,883,754,131,246,458,368,772,190,906,504,209,525,478,863,451,691,679,595,929,173,840,984,900,496,994,536,647,952,971,410,25,812,874,471,599,559,344,741,640,88,845,45,266,528,721,791,417,451,623,560,330,958,716,28,565,363,712,95,647,199,866,908,318,345,227,774,949,781,366,70,908,561,741,995,834,360,911,242,843,540,127,333,819,611,15,328,616,756,498,551,227,448,123,677,672,881,160,220,916,462,204,395,470,189,775,298,179,957,834,49,993,74,68,327,429,82,200,937,479,344,270,69,421,361,111,339,5,428,404,910,36,806,321,827,362,424,341,853,209,200,205,132,431,828,573,860,256,738,917,970,986,586,304,983,608,57,388,32,38,130,758,475,587,74,258,870,2,719,306,463,41,904,746,801,299,375,62,897,935,889,668,415,528,609,302,321,846,677,805,203,799,99,378,479,597,723,519,265,360,474,293,875,694,893,291,577,154,520,990,744,495,699,319,509,31,849,933,767,417,908,668,401,440,552,615,123,940,658,742,635,817,97,405,424,667,829,861,423,312,852,903,902,258,835,6,329,25,769,938,998,133,168,41,238,347,438,834,940,953,549,633,715,880,214,306,820,304,633,311,698,16,989,259,393,913,547,453,129,438,876,503,263,664,76,783,447,589,340,198,392,328,150,139,957,365,251,341,619,804,941,263,298,224,332,282,567,205,109,532,8,20,837,106,733,731,456,852,961,302,780,858,242,15,119,727,666,375,690,380,791,304,376,675,217,835,188,370,889,683,749,625,271,141,971,297,998,781,246,336,884,139,828,851,22,140,852,402,119,776,982,314,864,841,231,863,201,951,26,448,980,312,483,951,823,280,348,29,499,953,928,757,719,630,300,794,238,977,410,477,715,246,237,294,502,619,982,541,352,944,127,339,576,980,569,481,951,936,880,809,671,855,788,638,307,795,764,556,163,423,329,828,647,864,849,38,5,384,446,204,752,571,521,682,748,653,874,695,561,2,95,612,275,669,189,741,65,301,310,618,81,559,561,796,48", +"110,329,556,237,906,882,390,763,89,820,295,356,897,794,485,393,858,909,356,952,416,153,499,112,87,753,735,687,329,30,676,312,629,883,424,245,267,394,855,888,377,490,441,139,397,876,146,972,431,776,564,700,229,346,473,859,465,237,353,340,153,62,166,955,907,615,115,551,117,327,848,380,529,503,466,901,724,424,798,873,268,557,539,871,620,945,890,585,23,114,469,933,159,688,345,837,640,639,457,485,42,64,280,324,216,370,462,451,488,225,20,992,611,966,465,969,71,482,315,20,663,386,916,400,761,50,796,305,248,825,655,432,583,924,375,171,412,105,696,158,397,298,552,710,695,135,629,746,260,246,615,780,835,960,28,737,264,440,825,42,300,903,480,47,942,355,48,347,346,186,528,879,395,716,803,935,577,464,985,217,288,268,558,0,562,271,962,559,52,410,774,598,786,929,25,953,543,779,920,983,91,859,615,317,308,839,491,758,67,527,464,700,994,865,935,448,875,625,777,88,369,559,213,771,229,947,837,303,229,161,440,665,755,114,433,752,146,395,902,468,969,967,166,428,747,303,223,648,155,681,150,598,252,541,395,758,394,770,659,561,617,958,127,228,96,732,881,48,63,975,862,938,643,379,24,617,814,285,657,909,757,566,77,528,888,849,126,225,522,101,732,946,514,126,653,921,388,704,820,887,366,567,226,690,81,270,894,732,130,589,482,931,431,661,930,692,205,520,367,397,35,984,972,99,589,706,65,894,7,53,455,171,819,488,478,875,825,648,65,664,526,943,118,666,133,255,495,175,611,430,279,333,318,286,410,138,912,773,744,434,555,862,579,112,163,438,426,13,778,598,727,459,263,687,345,152,592,550,666,551,996,694,802,551,616,477,305,537,681,790,354,793,718,58,457,312,192,919,890,327,840,770,842,826,959,282,44,963,931,845,192,792,479,891,286,32,506,486,565,832,32,161,590,388,854,67,220,535,254,721,968,514,961,893,886,598,4,795,34,665,243,866,457,517,70,630,651,281,868,237,628,46,209,324,976,400,213,833,496,942,80,340,26,550,566,834,782,502,99,629,75,402,69,156,837,575,600,648,778,349,430,981,80,129,176,490,337,870,556,956,725,675,307,549,334,877,470,307,740,281,252,494,175,31,434,507,191,139,633,56,367,257,398,940,35,169,953,399,305,937,919,132,379,890,720,310,711,465,932,34,407,992,576,13,689,18,596,784,89,214,704,377,553,53,159,573,945,123,159,10,929,190,300,554,984,893,30,803,279,908,604,391,691,577,594,438,849,121,375,539,315,395,848,979,715,490,96,828,876,80,475,102,432,900,224,719,309,538,52,11,304,459,279,62,101,323,740,470,369,951,585,61,852,707,355,601,752,249,418,26,467,855,725,872,342,716,785,997,897,508,471,359,736,660,923,354,355,779,275,332,144,390,430,285,798,720,609,646,456,597,366,939,944,58,387,870,124,50,367,495,296,262,495,738,262,621,109,697,563,48,12,319,110,147,389,281,392,988,386,490,219,237,6,70,80,951,181,390,999,401,522,842,261,957,488,802,721,827,106,289,160,192,710,388,465,744,918,908,31,167,393,775,531,820,428,238,477,819,999,147,967,171,898,566,537,259,981,610,837,351,434,6,436,914,729,518,983,505,581,844,191,397,168,20,345,813,567,416,260,287,235,634,882,977,392,268,416,87,445,271,221,655,321,156,814,177,356,762,114,443,417,63,73,14,183,397,958,776,236,175,361,920,972,378,193,259,242,125,982,900,952,798,155,9,269,539,677,609,456,586,715,396,581,70,799,931,164,317,406,8,879,681,682,157,32,784,220,974,758,60,390,553,286,341,361,121,727,920,460,662,266,756,769,326,961,678,584,477,44,623,814,725,587,976,198,935,393,6,553,454,33,941,751,385,202,95,954,49,752,106,550,390,835,387,923,677,224,524,826,899,39,430,397,486,814,139,887,736,145,966,746,581,661,107,267,536,443,127,958,245,856,689,778,549,616,45,13,248,658,760,386,625,98,551,71,78,327,46,193,402,493,981,662,579,556,935,149,158,86,896,313,572,263,13,446,869,654,98,119,874,54,965,366,979,334,494,887,932,33,686,310,291,378,426,144,281,233,692,473,966,44,878,765,254,344,487,990,560,28,386,514,566,91,613,299,940,790,761,382,524,891,615,832,825,485,923,398,989,429,880,460,696,843,664,749,303,980,466,26,836,131,783,901,49,182,676,444,431,864,715,599,188,517,445,580,181,667,885,201,344", +"369,759,534,614,983,980,664,152,326,55,188,818,271,800,382,134,500,249,314,626,386,918,803,82,92,17,47,584,389,194,411,896,460,108,693,748,313,226,911,820,304,731,876,711,840,580,663,854,831,219,413,748,167,559,505,828,654,197,166,702,310,836,953,22,641,943,579,109,71,208,156,110,786,170,820,264,335,808,680,516,836,711,888,123,403,16,466,627,415,303,390,675,809,453,360,414,7,998,716,727,103,284,293,775,899,277,181,765,40,695,985,84,299,498,981,132,504,341,467,316,618,502,238,110,283,794,285,937,62,343,909,318,511,29,901,23,510,304,554,288,72,217,248,318,637,330,172,922,218,634,791,136,218,928,700,896,63,615,718,54,918,696,272,474,938,762,993,178,233,528,798,320,450,720,836,702,614,798,494,657,818,402,215,562,0,535,598,471,828,895,121,62,944,171,388,87,996,263,755,459,175,987,144,911,536,876,58,208,549,372,840,188,912,729,160,986,904,70,632,345,393,549,911,224,7,830,704,437,609,489,221,120,24,355,92,482,177,82,544,7,396,692,732,686,96,963,85,104,228,720,55,519,34,891,887,213,822,804,494,137,786,768,292,639,27,42,261,295,772,195,183,991,951,486,792,392,957,397,253,448,239,859,915,176,5,177,766,404,551,337,455,86,201,986,948,631,63,934,631,940,408,467,986,565,726,622,633,737,107,91,783,236,166,632,28,899,965,710,198,638,67,144,686,58,631,584,821,805,147,114,400,471,338,430,536,122,868,491,332,298,234,231,193,769,514,462,352,28,550,675,216,776,763,795,982,762,637,677,890,29,380,813,820,470,89,988,296,61,719,750,288,920,426,53,270,213,604,335,978,760,918,187,523,19,269,817,556,716,640,834,952,931,498,200,258,146,674,49,839,181,130,894,944,942,200,490,282,791,447,594,143,219,270,562,337,821,794,618,902,828,117,899,212,858,530,664,766,96,440,810,521,828,167,787,434,12,420,538,99,952,437,468,991,391,206,346,917,3,724,22,475,195,31,602,423,51,846,249,333,447,779,332,625,372,33,168,189,932,383,782,523,728,517,774,274,529,540,636,861,87,121,73,59,864,19,758,307,385,903,845,360,228,14,262,450,332,945,921,527,406,895,379,641,711,403,741,500,716,422,800,619,207,411,602,823,814,960,579,239,709,515,198,947,218,447,350,585,700,516,734,967,100,558,437,410,989,120,322,968,902,406,553,644,400,842,19,274,77,539,104,430,327,831,313,203,131,733,604,124,433,866,131,499,318,629,746,595,271,602,14,963,759,481,270,708,657,766,142,701,764,379,81,39,348,155,2,23,494,663,673,377,597,175,42,89,543,69,537,609,146,462,788,591,224,909,37,482,606,199,816,129,542,907,716,166,790,19,584,504,793,938,797,298,475,309,762,988,688,752,317,180,377,952,100,692,89,549,261,370,309,926,721,908,271,842,571,780,853,785,263,55,624,334,205,819,419,365,363,135,487,799,200,908,658,840,483,540,433,56,22,698,93,925,477,354,180,295,197,668,788,988,966,140,759,932,539,843,124,258,863,195,459,592,950,752,137,805,699,678,307,730,304,119,955,682,455,971,239,898,276,947,447,726,818,922,27,42,918,588,415,359,267,576,827,968,889,849,609,778,926,290,139,681,494,544,198,385,775,331,740,12,257,217,242,635,984,162,304,63,594,848,154,803,579,708,102,133,858,737,87,365,856,157,220,317,129,884,672,931,863,243,858,144,887,954,585,40,669,521,520,289,447,292,137,122,337,308,492,256,923,43,395,827,85,995,762,288,649,681,252,798,264,186,95,394,54,536,203,397,144,326,64,421,15,196,772,709,171,477,590,675,764,112,334,215,843,927,608,538,901,199,752,413,99,236,55,277,319,930,953,571,755,69,56,249,71,311,712,789,549,78,66,655,797,816,219,789,895,272,900,736,284,265,93,595,969,589,860,68,29,626,886,357,315,698,198,445,602,307,414,322,67,455,860,317,681,318,931,367,768,132,697,430,632,91,651,606,189,97,460,242,335,397,83,413,279,719,44,404,801,678,266,966,175,243,989,889,604,554,91,889,117,357,298,76,691,175,304,882,257,677,217,461,472,769,867,447,520,411,738,602,457,831,167,173,67,77,839,272,229,607,441,470,568,443,896,840,791,706,663,48,214,245,829,918,391,913,18,211,154,495,187,829,510,615,671,572,476,721,984,113,818,665,327,268,684,761,619,98,402,884,883,53,446,271,338,912,412,576,967", +"393,923,661,274,610,211,786,4,539,960,39,66,671,60,890,310,813,310,690,722,865,394,834,320,690,798,144,674,437,582,281,960,704,658,571,22,59,323,287,875,634,879,128,431,935,531,913,416,258,570,965,36,580,956,278,176,392,544,948,940,797,946,738,856,714,450,854,370,591,388,281,637,331,869,190,202,347,728,537,494,430,143,850,164,612,450,665,752,648,641,769,506,964,551,729,164,267,391,798,61,836,75,782,892,343,43,487,76,314,28,737,196,900,384,794,928,450,333,947,923,973,938,671,583,477,639,61,231,206,733,187,759,333,593,153,217,300,896,505,605,398,770,720,50,60,308,589,815,665,19,949,364,772,247,975,792,965,39,297,767,126,5,87,973,669,602,177,66,87,83,798,684,904,780,863,387,291,298,741,146,753,686,949,271,535,0,791,830,20,696,707,593,965,160,184,742,185,631,448,31,489,497,602,669,466,677,276,558,294,991,311,642,395,662,210,841,499,428,406,852,359,908,485,731,917,767,219,874,571,156,595,134,284,897,905,787,800,592,358,405,219,410,308,135,149,389,340,143,240,377,202,31,163,123,214,732,427,777,547,271,851,269,802,358,192,8,528,270,401,791,722,277,81,371,987,667,836,385,976,883,431,972,708,51,95,516,389,998,821,238,461,967,494,743,761,335,606,98,664,639,543,561,725,751,832,720,87,104,150,52,750,609,122,474,983,482,840,908,483,632,444,895,495,637,402,329,958,917,918,710,896,443,265,912,770,381,767,250,906,854,79,64,417,6,216,662,885,144,480,497,542,222,288,246,406,855,758,835,688,81,377,951,445,782,538,260,130,751,818,753,727,971,994,533,696,852,385,600,156,224,402,941,467,508,950,660,254,929,882,275,38,259,137,832,14,651,119,715,934,881,213,939,286,398,446,294,351,383,55,637,263,331,966,860,475,581,610,668,510,336,602,49,153,196,812,914,180,817,217,672,918,76,644,26,440,533,805,358,82,472,917,641,903,522,768,914,402,843,431,85,694,996,684,915,8,991,395,220,345,293,379,375,876,389,998,803,99,515,873,317,848,358,741,391,231,324,102,398,816,955,433,776,68,750,245,557,160,296,308,755,321,656,225,914,376,430,687,576,560,15,823,846,893,269,99,355,613,149,682,175,840,479,231,64,59,764,856,773,609,181,948,895,251,33,541,409,968,391,617,990,70,188,702,20,142,348,157,500,992,473,411,294,4,611,718,791,668,315,578,950,896,635,767,232,152,780,769,170,542,351,491,628,247,220,196,688,524,365,833,244,338,370,359,651,759,696,851,337,590,944,807,39,470,791,528,948,574,327,160,628,891,669,411,839,329,885,151,6,194,286,604,150,400,44,983,860,454,207,636,551,22,754,555,525,437,886,95,202,204,73,902,439,955,285,294,372,237,77,692,798,90,229,194,513,829,367,495,424,320,175,236,231,65,712,120,710,746,185,875,953,939,7,277,693,471,47,549,524,599,351,326,939,928,852,755,488,325,244,194,647,342,226,757,672,699,229,117,702,503,599,527,974,767,73,21,696,221,616,91,243,135,644,534,572,894,758,300,336,678,912,588,486,930,131,608,708,422,585,761,393,286,694,705,56,101,834,436,681,229,181,44,141,125,424,32,656,806,305,516,765,153,194,712,146,501,337,757,671,372,136,271,116,906,250,520,75,537,711,121,207,675,309,437,943,727,300,229,320,809,172,726,186,995,32,656,327,548,586,845,972,452,300,629,356,843,335,466,934,874,191,939,715,464,200,770,953,434,808,486,642,281,975,137,581,25,455,290,10,815,207,557,213,782,445,63,607,782,642,431,281,840,3,937,529,256,54,647,627,696,630,913,205,276,359,591,743,745,878,108,95,137,321,562,492,216,911,809,94,385,594,728,660,737,412,919,372,487,191,139,918,857,357,560,353,331,70,961,903,269,488,106,307,729,639,60,49,152,571,499,636,671,383,839,371,748,431,176,996,125,271,657,66,552,250,506,810,261,327,200,263,982,257,737,267,820,264,19,903,615,855,201,534,148,310,426,628,170,5,239,645,612,788,982,133,759,799,322,720,239,80,446,354,316,196,523,503,150,44,747,824,143,782,246,492,655,93,489,648,411,149,638,56,645,943,919,631,856,623,896,7,987,684,705,701,975,867,68,586,146,770,446,880,903,283,715,519,909,50,832,519,951,409,261,337,240,704,314,323,70,517,161,792,666,236,229,644,165,605,841,498,625,345,265,457,573,444,38,907,647,595", +"678,496,852,50,966,458,580,591,207,518,786,626,168,22,360,137,281,235,752,544,459,37,395,959,874,608,474,259,837,539,869,693,621,895,53,177,702,943,35,224,237,192,761,760,140,725,105,83,557,402,148,192,653,558,266,9,531,755,910,449,36,834,334,599,13,617,818,873,278,747,389,258,239,879,846,964,158,356,416,542,549,353,691,373,363,642,141,368,232,893,769,149,535,265,677,746,207,74,612,968,728,325,74,46,972,789,252,312,406,737,475,227,477,856,888,808,776,101,560,876,320,263,977,777,841,505,44,948,265,585,128,240,415,849,980,199,795,27,144,519,31,666,940,168,97,99,384,928,514,571,79,207,291,867,535,884,949,965,598,421,960,594,45,966,157,357,619,750,47,696,616,928,544,503,715,391,132,772,660,14,486,635,756,962,598,791,0,74,66,682,746,305,516,405,275,97,495,480,826,275,463,685,977,451,945,325,727,548,233,730,840,157,195,447,412,864,517,577,35,802,751,258,572,853,706,693,609,649,853,480,786,945,625,461,587,743,771,362,722,920,36,654,29,775,705,283,510,895,785,776,448,683,188,164,816,788,335,485,216,864,839,185,857,892,809,9,465,745,58,942,483,598,180,372,177,724,579,990,573,121,986,479,617,309,406,643,646,287,61,685,962,813,476,222,628,543,802,370,276,598,111,857,218,442,605,126,40,249,399,153,80,382,667,749,841,990,251,187,319,85,57,887,597,924,469,213,329,99,151,581,172,682,305,996,373,592,160,222,939,950,408,398,235,117,446,279,563,704,73,424,493,103,989,146,5,281,159,155,963,150,298,588,431,189,743,211,121,762,356,722,283,619,347,484,257,634,666,247,632,368,329,860,818,438,209,899,999,324,799,407,515,100,121,896,85,683,758,428,910,816,424,796,756,819,578,219,311,98,360,434,375,578,490,589,558,902,231,893,540,190,895,294,25,375,537,503,788,691,285,859,621,825,391,404,338,452,630,361,493,78,535,37,461,503,412,274,126,751,187,248,365,46,60,825,961,262,846,15,430,408,453,471,11,955,344,26,447,930,482,612,148,842,902,937,657,681,179,339,629,618,405,295,964,38,245,799,950,57,952,122,560,757,649,342,387,68,84,914,446,710,51,991,113,29,635,334,492,217,141,610,841,213,425,29,556,591,660,710,866,756,52,969,763,694,511,190,13,867,978,22,436,507,351,402,123,749,108,743,839,155,133,164,539,522,827,380,43,712,769,634,242,267,296,959,736,900,437,80,285,3,44,885,737,32,202,122,50,326,935,77,229,698,664,39,684,795,322,634,955,230,421,243,248,196,257,758,383,593,964,45,839,541,388,794,475,478,550,902,202,467,121,316,333,854,597,165,473,947,513,652,821,883,290,34,273,861,501,678,484,397,515,633,857,339,592,957,607,92,794,580,450,277,992,108,964,542,773,247,79,993,953,626,865,502,71,607,121,452,282,844,40,933,360,921,733,125,360,514,29,32,886,692,805,720,19,817,749,626,516,951,873,4,43,432,994,91,28,606,550,806,760,551,431,941,302,409,741,648,69,353,419,12,619,262,720,922,946,639,93,733,918,110,387,716,717,282,835,329,770,672,130,529,507,290,715,5,132,344,99,416,304,462,425,767,694,223,744,988,574,889,13,316,866,475,301,683,949,811,680,460,853,851,761,151,647,46,423,511,377,326,689,298,800,832,718,696,581,530,137,688,311,292,44,28,267,161,272,215,599,990,436,671,917,190,642,420,917,223,794,539,168,606,872,501,104,791,796,202,11,758,976,397,157,183,722,966,222,763,412,811,340,79,469,278,186,401,70,896,761,661,994,894,585,325,149,281,677,230,614,947,205,628,806,461,941,717,951,130,429,782,52,623,249,919,120,571,906,634,695,783,506,163,501,584,831,724,951,26,802,541,656,582,927,72,406,527,819,135,64,771,257,431,173,170,538,594,780,402,195,573,164,661,428,446,875,262,89,87,593,750,906,905,469,198,395,933,546,834,967,377,633,278,3,474,911,806,975,382,865,361,237,931,594,351,7,879,981,964,557,23,289,393,765,538,891,620,99,932,929,434,759,45,47,332,606,52,569,461,646,415,971,329,623,847,143,650,820,109,252,707,841,251,185,733,319,629,259,99,668,4,332,264,25,283,742,949,943,701,286,189,214,657,780,825,328,719,328,839,348,224,755,280,788,405,905,320,769,816,391,399,393,867,596,510,289,986,308,644,695,37,57,244,774,527,825,458,738,799,751,861", +"873,960,457,808,563,409,895,731,631,850,204,323,21,392,890,511,67,493,244,862,176,590,481,237,361,441,291,204,223,345,973,450,794,336,362,191,604,210,147,866,610,813,219,357,230,977,838,692,70,912,499,145,349,11,668,88,685,652,6,585,523,400,381,254,397,175,700,168,193,153,266,731,492,489,928,752,488,640,997,63,540,974,745,384,813,528,140,436,904,740,288,770,212,665,258,120,443,967,652,312,755,177,622,645,384,913,532,702,508,556,269,358,738,784,640,898,719,30,290,808,446,92,976,133,235,956,138,276,800,489,438,411,582,183,103,180,399,850,881,890,491,540,486,452,714,242,29,695,118,627,988,816,565,134,512,356,217,954,25,659,339,810,384,222,391,739,347,579,641,875,896,300,449,332,373,546,400,692,691,522,750,959,139,559,471,830,74,0,802,974,933,601,728,774,807,532,5,335,476,642,373,556,958,405,332,305,433,957,305,832,598,94,626,303,81,779,778,437,793,709,756,973,486,817,400,349,621,123,85,296,213,788,811,105,506,682,857,974,998,99,636,266,828,971,605,204,563,801,824,799,912,423,447,55,188,112,51,70,32,963,386,826,907,734,274,723,951,584,359,722,777,453,218,738,428,299,489,720,22,671,976,549,661,487,652,734,218,759,315,649,282,944,344,322,769,953,227,516,560,752,904,543,479,61,153,172,180,426,338,634,460,42,151,240,228,964,209,920,8,502,326,548,957,777,375,657,794,794,751,66,44,779,545,870,177,97,458,174,434,953,93,859,269,421,308,894,536,504,62,710,269,726,536,119,406,408,644,10,240,58,731,528,433,103,344,98,459,212,35,837,751,738,820,491,766,702,292,60,641,9,123,676,617,762,878,390,670,451,859,155,654,600,321,947,688,994,38,256,106,990,983,868,794,459,287,328,449,789,743,377,957,412,152,693,494,816,987,136,486,613,903,473,43,234,615,409,483,443,336,206,405,645,25,178,126,921,162,307,318,87,508,819,626,633,446,181,709,315,581,666,747,250,137,834,239,533,940,219,948,176,263,54,349,937,991,345,724,580,563,668,982,256,282,460,701,339,567,195,382,927,449,497,125,81,129,82,947,786,657,556,148,124,157,585,278,480,716,46,537,175,475,136,247,978,261,506,777,757,750,738,264,247,373,961,34,798,294,534,567,547,817,21,523,391,672,137,811,644,532,913,23,540,741,208,715,808,688,798,980,255,115,492,434,96,583,399,814,114,74,881,818,930,7,343,953,446,925,708,97,925,126,886,785,980,908,674,735,139,268,740,30,526,402,288,579,836,118,403,597,9,131,698,193,86,479,594,442,705,844,366,699,644,336,708,693,809,822,34,910,230,182,928,636,716,219,836,76,796,62,480,930,868,993,68,380,819,693,776,212,657,96,127,865,763,631,80,445,659,112,223,947,792,515,439,70,560,766,661,896,172,835,872,935,44,942,831,570,550,906,586,952,170,842,548,255,464,665,594,467,341,878,897,451,408,423,780,755,923,380,327,968,542,8,7,307,604,347,720,105,641,853,5,377,272,926,680,176,772,862,855,708,292,939,691,841,206,545,565,764,488,887,847,947,565,226,366,934,146,673,695,84,354,751,192,309,603,316,387,160,134,307,905,820,767,465,251,464,483,755,243,686,175,31,145,764,10,687,23,594,749,680,896,792,75,762,399,715,757,223,597,570,868,921,257,103,290,245,60,843,899,325,115,168,93,338,97,970,832,407,561,933,66,776,172,675,871,478,612,699,881,877,564,241,538,243,941,81,759,628,64,381,657,994,500,679,181,100,386,616,622,971,879,650,895,827,580,975,458,64,99,780,575,702,250,579,222,387,246,211,62,638,261,799,570,336,12,792,196,29,598,820,432,223,825,152,202,996,94,871,742,39,744,947,713,869,415,751,938,421,386,268,114,284,424,846,885,26,691,479,302,876,571,888,312,329,961,25,330,261,870,222,342,290,985,746,669,432,798,307,82,234,361,407,191,551,418,812,217,894,626,57,860,338,141,395,779,867,523,864,562,14,454,267,640,561,984,285,669,105,844,133,795,415,527,489,664,331,413,979,373,690,32,330,358,886,917,608,725,417,122,337,476,737,746,895,946,732,888,390,333,839,384,182,295,278,301,205,921,231,486,196,894,250,162,442,845,417,646,853,679,961,139,210,388,895,982,848,698,142,591,965,938,222,450,668,181,411,661,321,230,187,751,144,707,191,972,112,147,478,615,128,749,530,570,518,3,605,538,28,884", +"8,488,259,973,165,222,212,795,658,870,897,817,927,784,774,494,235,166,920,238,926,598,421,653,395,296,454,785,178,759,548,144,186,935,988,699,372,974,787,540,235,356,220,900,181,958,348,305,150,86,851,908,405,60,186,288,534,992,627,550,495,761,613,38,742,900,972,576,20,490,2,610,596,499,660,555,260,123,695,942,215,953,534,869,942,39,782,965,455,539,825,636,464,739,677,430,727,166,850,846,537,848,147,576,791,658,653,994,730,849,354,575,717,804,187,306,290,805,646,554,900,413,785,502,475,980,229,84,233,916,255,132,397,295,440,602,298,142,290,809,153,247,453,496,737,555,33,394,847,691,215,478,568,819,649,238,655,964,2,462,916,640,945,917,591,601,526,729,88,230,539,392,798,618,354,350,508,284,380,270,353,180,242,52,828,20,66,802,0,458,815,870,397,298,404,829,650,961,811,926,795,629,425,313,930,96,875,555,514,747,465,73,744,364,458,565,76,572,207,607,969,379,791,180,825,684,429,423,132,638,404,550,237,761,597,520,648,326,860,391,617,865,614,93,51,454,525,396,310,471,349,385,318,576,591,132,197,38,162,456,830,891,47,632,108,968,297,163,792,717,344,118,746,500,24,389,529,644,313,861,251,916,753,576,365,729,133,773,28,948,789,998,137,66,642,778,351,174,672,265,329,225,987,540,751,318,94,258,870,726,394,988,572,510,106,24,195,859,236,795,977,599,122,857,48,95,336,39,280,538,703,989,196,522,284,681,962,285,281,851,955,462,481,747,661,110,165,979,288,147,538,891,498,742,232,288,900,625,842,56,812,654,967,462,935,826,493,955,399,775,287,686,96,42,860,256,425,561,785,823,191,965,963,604,718,814,290,934,656,25,755,435,35,59,434,617,346,111,597,968,455,417,472,157,30,829,788,226,55,580,575,327,135,94,893,757,226,295,801,934,992,588,45,791,948,949,810,229,498,852,191,709,372,606,762,80,192,634,869,358,926,162,201,470,238,686,748,341,702,278,745,835,950,257,809,357,756,870,931,448,186,464,554,829,359,95,913,661,410,529,586,767,468,438,215,736,582,943,324,286,43,534,907,36,975,258,86,618,670,878,135,978,920,802,281,552,622,303,386,351,332,781,73,438,314,311,72,517,3,499,548,672,285,992,759,859,116,88,868,324,520,614,812,352,777,615,724,477,833,945,587,360,54,582,20,446,967,604,731,390,407,851,205,186,988,8,576,314,520,273,641,285,887,453,793,326,754,69,491,825,120,210,950,469,986,784,762,685,17,373,184,875,839,367,300,661,894,483,873,121,774,655,902,450,938,337,991,380,974,349,547,265,108,184,206,246,230,483,182,22,198,292,841,712,213,884,748,142,474,604,555,484,835,917,672,637,377,626,395,153,162,82,830,879,84,473,97,811,131,272,120,247,583,702,309,950,863,704,803,255,133,154,540,587,133,167,23,854,711,186,341,290,980,60,581,163,494,45,817,571,566,403,529,46,904,941,453,865,632,312,275,326,451,233,737,520,586,820,150,614,759,427,993,521,387,204,9,640,420,158,398,616,649,355,536,311,41,720,24,642,877,136,599,2,978,594,46,949,328,763,19,933,177,10,97,733,139,63,155,881,277,298,981,57,242,307,257,583,151,647,504,620,744,603,927,512,328,404,2,172,974,821,849,736,414,126,767,56,343,264,182,455,423,530,450,875,31,142,234,56,206,707,227,175,191,413,140,937,520,39,505,979,661,699,787,413,220,858,575,998,605,559,484,692,501,737,938,959,299,930,17,279,867,125,754,571,38,484,268,550,797,440,882,756,121,476,56,275,328,12,417,788,14,123,958,405,553,837,116,393,55,134,747,588,890,609,551,426,553,539,751,322,747,44,963,28,551,32,67,689,889,139,474,487,178,959,200,670,968,45,709,778,500,927,256,511,141,853,365,631,759,143,118,877,828,557,64,849,778,644,296,317,662,734,387,851,468,264,351,936,922,623,83,199,621,588,562,872,366,530,494,856,835,250,607,800,821,756,473,521,697,601,847,857,416,4,338,587,240,569,869,97,93,120,54,308,372,661,932,378,271,234,819,399,30,124,36,145,854,527,271,486,655,378,783,874,92,816,351,397,968,219,278,186,29,427,915,822,613,495,701,156,657,459,38,284,485,62,237,593,153,105,906,35,201,647,6,996,613,353,620,735,856,739,114,537,698,420,887,561,802,573,274,834,571,267,886,251,158,212,549,437,420,205,600,743,559,621,892,472", +"708,452,348,66,217,559,873,633,639,876,506,498,892,791,460,786,220,574,199,666,793,622,25,41,182,783,24,203,899,95,108,74,78,994,98,726,487,650,89,461,262,780,214,742,299,190,152,396,803,371,521,207,622,390,263,419,234,187,541,879,88,37,428,98,600,639,305,551,811,288,101,198,739,278,428,237,824,34,788,565,992,625,667,184,620,998,311,379,204,508,550,905,972,832,431,474,266,430,77,286,921,563,425,560,929,856,240,658,500,620,199,175,853,873,668,826,16,389,931,596,198,271,274,752,478,212,636,161,996,101,569,197,900,23,206,38,881,425,586,122,860,665,578,950,576,434,28,57,333,541,727,465,294,842,622,669,290,494,156,334,300,292,264,157,194,93,303,763,890,690,468,588,124,67,651,216,552,625,67,969,196,317,491,410,895,696,682,974,458,0,985,781,86,383,638,451,374,60,904,401,587,877,814,928,813,15,229,932,949,914,910,362,225,837,567,145,859,343,69,849,474,503,703,763,671,492,980,399,668,410,429,874,426,826,16,471,567,390,258,663,192,902,949,281,473,492,174,993,72,899,381,908,191,558,607,110,998,191,431,843,974,701,346,995,34,764,671,197,773,801,742,782,70,649,412,704,525,286,700,477,413,741,969,876,647,417,336,152,982,574,965,710,544,662,781,93,985,213,880,207,881,427,751,141,458,993,46,420,936,382,785,392,594,129,708,766,5,309,346,293,77,115,595,65,676,175,545,501,374,152,435,473,234,912,446,399,676,705,818,429,768,503,993,977,440,685,890,521,976,961,146,668,644,796,929,109,84,694,950,15,573,161,248,606,9,13,321,207,265,449,189,13,13,280,576,847,463,561,227,109,1,620,597,369,528,326,798,385,258,182,817,980,36,305,927,588,178,184,679,685,718,665,406,260,851,684,405,366,708,874,777,218,649,231,301,815,841,483,650,959,934,9,87,365,516,391,918,487,263,296,79,450,92,409,671,730,85,176,349,948,456,470,746,926,687,781,230,202,721,144,280,548,453,452,432,213,642,164,423,540,817,445,923,137,346,779,411,753,216,497,426,681,23,380,203,293,97,311,222,706,177,526,89,68,636,604,943,991,752,701,193,191,340,208,574,886,3,424,78,867,97,566,150,66,967,711,510,796,675,165,318,685,225,874,263,744,148,986,491,678,182,250,815,72,218,90,968,337,79,44,332,749,381,570,909,273,955,626,948,589,636,165,568,121,526,67,640,871,723,183,837,162,216,432,96,286,586,808,113,88,903,393,134,795,594,208,796,708,670,221,993,867,696,96,314,904,636,179,240,144,211,21,937,563,934,402,440,185,671,831,169,73,42,71,967,563,999,200,786,931,862,51,46,330,431,276,566,145,489,164,993,608,479,801,242,404,279,750,18,341,206,710,356,605,198,705,795,648,768,872,981,568,811,796,522,234,312,219,915,371,945,687,286,531,920,916,116,532,828,769,227,554,371,576,740,660,126,926,981,63,324,409,391,204,595,960,967,635,869,802,404,899,977,453,709,966,450,378,422,165,630,332,979,505,651,520,965,572,44,121,783,241,145,8,130,659,563,883,501,504,500,996,634,791,193,363,576,564,592,890,201,703,941,604,777,452,775,894,71,981,154,256,231,24,109,878,158,915,426,462,572,919,23,534,464,91,936,828,344,175,426,998,616,931,983,561,930,896,494,188,150,180,199,904,419,756,260,330,278,917,97,489,401,214,931,698,944,516,632,729,207,475,59,703,93,381,287,92,825,401,711,355,530,976,283,355,730,994,499,686,269,320,925,286,317,213,901,506,127,332,887,51,52,186,623,203,69,585,267,316,787,152,784,891,435,766,757,62,925,833,516,525,806,860,794,925,634,411,416,123,565,737,193,839,977,234,580,490,444,362,963,909,455,797,846,570,3,838,336,458,629,877,114,746,568,577,245,74,956,579,820,212,840,341,78,527,852,790,297,869,625,742,815,96,41,388,216,786,240,444,912,681,493,262,344,783,260,736,260,570,654,706,474,50,281,384,831,361,801,260,365,601,590,133,417,47,567,123,374,612,53,590,328,844,237,287,752,958,45,569,91,910,402,54,574,241,666,547,212,504,412,836,643,287,326,814,297,148,821,401,515,886,987,394,993,470,491,736,589,662,802,639,817,676,555,320,922,348,770,9,929,77,206,153,154,420,971,688,662,643,82,539,550,458,476,728,866,198,682,367,970,478,787,195,579,525,433,347,738,530,83,904,565,847,161,147,16,294,476,531", +"268,407,990,918,116,641,589,419,993,109,84,670,512,25,506,913,452,972,6,842,482,648,297,151,810,735,619,529,708,563,549,739,331,680,130,296,231,309,348,815,500,266,636,761,603,547,543,578,700,138,930,718,650,521,520,617,114,478,797,770,353,119,794,787,190,549,445,91,760,762,140,845,646,102,924,709,324,727,620,639,360,564,138,219,434,181,974,620,922,700,674,908,708,915,624,640,934,535,788,250,975,657,495,765,723,853,601,8,152,868,989,666,248,714,818,42,819,488,752,461,290,179,451,715,700,932,897,309,765,344,929,821,625,87,570,452,620,148,866,198,257,62,15,385,651,477,207,670,418,814,245,183,331,113,314,768,488,60,522,589,504,650,68,193,660,133,188,307,730,318,777,431,387,726,541,393,142,615,613,432,39,426,941,774,121,707,746,933,815,985,0,626,305,965,764,631,227,597,297,114,869,367,709,588,607,842,222,858,36,48,484,940,654,759,220,359,173,52,580,773,638,749,348,952,510,597,123,188,879,773,397,310,815,395,288,799,322,442,827,48,895,911,837,280,195,664,682,720,750,464,292,410,632,369,550,916,838,909,348,730,141,82,601,588,50,860,757,532,206,680,751,821,949,8,629,840,617,155,330,80,519,284,63,466,171,203,804,815,57,367,515,461,687,838,255,546,205,201,281,451,180,737,708,935,883,25,735,62,888,239,238,662,713,586,134,877,639,910,631,521,131,379,803,712,443,106,23,452,804,857,41,618,776,422,313,555,106,975,905,449,984,204,649,82,517,142,604,503,193,650,874,609,432,288,621,601,716,150,535,486,411,743,539,640,290,871,948,774,135,650,285,984,514,935,291,164,959,346,633,750,980,786,763,263,723,358,210,92,747,21,405,263,760,653,203,558,405,102,616,234,535,488,218,701,51,308,68,341,840,605,271,841,646,259,482,370,906,405,515,715,872,401,791,533,856,60,866,553,369,605,276,946,135,593,245,62,230,863,172,895,562,169,462,835,53,518,900,447,867,930,758,757,600,419,759,55,598,741,138,298,910,735,228,691,938,365,407,493,171,45,944,513,807,803,434,420,194,370,702,504,557,671,597,839,302,156,819,295,427,92,248,907,46,621,64,798,819,593,394,706,719,677,959,211,394,671,668,510,282,27,406,375,387,931,832,594,512,511,844,123,501,778,789,576,937,370,182,207,427,629,894,778,171,485,411,239,745,452,163,205,168,473,43,267,403,265,779,859,114,466,793,294,932,273,79,392,768,308,477,912,367,582,671,857,650,996,66,76,110,359,274,338,913,687,982,250,441,350,146,683,920,627,111,390,853,502,111,359,409,803,708,667,161,826,815,368,247,504,548,791,674,199,515,928,455,266,916,676,358,830,562,926,928,612,873,637,934,970,668,740,925,224,480,704,913,874,951,685,905,677,691,422,740,409,278,503,784,354,816,344,846,304,860,502,28,300,696,457,631,922,842,551,739,619,699,728,559,448,926,367,691,357,314,194,889,651,271,123,579,669,395,337,357,999,183,948,971,85,692,621,414,822,735,419,775,130,953,667,766,912,42,466,588,291,255,286,168,309,437,500,428,946,848,286,639,316,128,352,991,681,28,660,873,760,195,640,302,886,95,530,117,592,60,461,717,299,405,295,568,585,521,480,919,315,545,304,74,320,505,962,906,89,811,806,160,83,191,159,919,385,764,777,70,187,711,930,55,231,204,326,417,611,339,652,338,687,39,8,511,832,770,555,72,396,163,990,18,87,130,764,314,362,142,104,609,220,130,685,594,701,888,864,190,279,901,635,67,385,266,486,284,901,483,575,819,26,639,954,630,53,295,998,15,355,362,793,130,853,820,890,43,384,571,200,887,476,727,527,904,434,215,166,830,887,718,206,733,526,675,916,14,316,55,517,979,232,859,81,761,366,221,278,278,265,622,217,169,178,705,861,101,29,943,572,657,548,769,542,975,938,540,549,435,323,891,120,571,187,916,938,285,220,386,841,34,121,842,323,320,649,588,42,170,144,866,454,352,547,741,86,314,973,57,552,245,924,31,861,476,516,24,698,708,614,753,893,338,195,185,605,594,339,262,722,175,781,595,113,884,312,968,264,915,151,691,416,871,946,246,421,594,243,683,733,300,171,597,421,867,518,579,96,426,548,666,127,190,388,668,132,391,141,680,859,687,784,228,742,374,760,574,662,503,143,638,884,74,791,788,917,546,246,593,409,293,465,424,344,672,299,200,385,708,651,165,392,360,298,749,503", +"177,844,365,456,528,570,171,666,433,984,563,61,908,517,905,467,676,223,186,448,762,440,433,685,423,702,846,807,708,765,226,614,572,386,926,313,663,539,107,613,581,472,560,540,714,14,956,85,571,484,284,845,337,144,417,24,333,541,308,639,521,272,415,58,941,386,253,423,408,497,557,467,602,937,117,268,954,104,432,202,387,210,121,833,762,19,65,896,329,526,352,259,136,715,847,893,870,401,637,838,1,642,133,756,87,700,624,732,82,294,622,368,33,37,932,612,795,758,34,533,56,252,785,494,89,628,574,620,140,899,928,255,73,354,687,235,702,499,471,16,976,105,517,205,839,766,577,103,617,419,574,760,696,196,89,383,429,58,986,655,415,522,806,29,899,676,150,223,292,45,173,717,703,134,911,539,221,545,191,851,471,496,745,598,62,593,305,601,870,781,626,0,144,701,517,577,190,386,432,528,664,914,369,11,544,674,34,687,757,223,574,264,537,501,208,679,618,700,259,981,480,351,904,648,15,985,530,759,231,428,341,457,10,629,222,303,186,845,191,54,822,176,613,690,966,542,221,81,436,757,313,288,413,244,522,700,420,258,856,351,925,350,532,984,451,335,551,341,683,577,412,391,498,478,432,340,115,822,962,253,930,456,213,80,232,544,455,625,549,10,485,869,697,605,444,677,153,681,359,775,715,73,685,679,887,132,331,176,229,973,894,110,897,171,801,954,116,656,834,41,411,175,972,603,346,20,839,5,695,841,186,271,248,337,946,246,323,749,874,960,483,725,258,684,298,992,279,568,366,279,810,650,939,583,186,49,696,718,305,22,489,983,135,262,97,612,65,818,672,276,213,450,93,884,777,259,485,61,134,392,381,882,886,66,144,356,334,806,560,317,355,822,133,721,71,608,221,465,857,601,646,910,627,867,646,134,151,98,352,38,359,812,235,326,122,876,117,990,788,22,308,952,599,213,509,577,829,803,663,620,987,271,579,479,465,732,51,947,839,784,181,215,779,909,58,706,908,984,665,607,976,638,948,556,165,874,873,582,182,488,629,295,415,524,441,687,512,662,53,953,965,370,171,65,875,340,298,457,339,77,287,443,632,897,408,26,533,732,175,334,814,639,458,508,748,849,100,263,93,428,762,336,184,145,596,631,480,947,450,885,30,931,668,147,229,796,393,642,486,830,316,85,57,232,831,877,381,826,249,609,874,795,558,325,553,939,426,872,294,183,121,756,832,529,85,781,882,233,538,91,229,14,711,725,760,718,21,685,818,76,531,547,491,327,628,568,600,434,504,286,96,886,39,321,811,832,453,389,95,343,452,713,434,588,352,209,571,331,987,486,357,634,852,886,663,483,20,407,462,960,69,22,443,585,900,770,607,721,219,457,692,686,149,304,70,961,23,875,577,65,926,451,782,303,290,944,171,663,247,194,66,724,385,809,508,629,55,94,72,785,286,219,475,915,512,778,174,668,774,887,852,307,172,768,3,743,341,227,454,464,15,730,503,437,835,250,306,964,382,489,866,150,834,351,613,209,303,535,465,843,210,476,109,195,185,96,859,613,600,416,395,791,287,852,108,993,329,468,61,33,908,618,524,18,961,312,463,184,14,568,340,728,753,807,739,97,72,599,53,420,990,576,918,271,507,244,836,326,105,740,437,679,510,98,252,100,708,551,881,296,936,767,548,14,193,215,78,298,522,680,621,167,480,157,389,359,240,853,445,289,430,441,284,954,474,33,839,47,822,247,99,95,928,706,276,834,207,74,923,203,292,444,777,242,105,814,974,546,745,961,694,315,353,293,150,178,76,968,921,849,23,881,922,508,302,202,979,943,586,9,51,717,241,570,66,381,9,50,403,484,317,520,474,78,700,375,295,247,701,640,274,761,120,157,162,43,329,33,424,502,838,334,507,755,143,746,893,270,817,994,75,520,596,91,40,799,893,151,399,813,164,373,640,61,500,719,224,241,868,452,140,251,607,284,7,26,458,44,136,420,827,498,619,998,975,398,828,354,624,780,852,754,730,798,804,654,40,931,538,339,395,367,421,782,439,437,278,701,838,766,48,117,844,327,809,119,899,153,365,768,849,716,375,47,525,846,997,429,376,781,513,553,65,486,363,796,404,552,379,969,435,551,750,433,947,537,584,764,344,210,853,12,29,847,722,172,449,972,500,464,95,638,671,674,584,295,519,675,123,824,180,958,334,206,533,389,988,468,355,667,679,97,724,480,898,347,877,769,200,552,492,154,422,812,395,638,207,456,409,973", +"722,390,284,370,285,185,625,491,715,273,739,545,721,115,286,697,32,418,808,591,885,791,486,240,345,991,257,618,511,416,185,318,794,325,766,526,525,615,810,391,253,345,410,240,486,329,811,196,636,350,251,694,361,941,898,500,200,39,103,867,370,647,381,132,820,39,163,241,875,844,367,840,532,279,222,638,791,483,565,426,131,187,791,781,361,271,499,118,919,805,246,818,986,281,821,57,837,429,491,455,52,476,488,732,261,897,215,768,992,375,213,726,150,764,440,722,892,437,578,393,379,656,240,435,273,64,794,94,301,159,93,172,745,201,396,820,872,482,884,225,432,425,702,707,626,635,731,610,962,950,373,912,461,482,291,705,915,680,628,876,33,628,395,995,49,364,944,351,536,349,756,342,670,612,200,77,353,523,415,424,428,519,315,786,944,965,516,728,397,86,305,144,0,641,310,951,324,847,137,484,150,320,951,695,93,881,62,315,213,63,665,426,119,470,781,585,866,727,636,640,387,959,617,89,339,269,10,327,468,766,409,713,447,493,146,361,332,910,491,928,685,537,242,700,651,469,154,195,216,668,785,340,708,67,930,149,278,427,113,536,225,306,872,343,67,61,50,569,219,438,818,813,268,263,893,678,99,620,855,516,93,22,762,414,863,301,924,161,129,246,969,776,494,319,57,191,169,953,982,355,263,429,588,69,964,12,399,150,688,55,412,511,431,574,873,329,501,69,487,228,149,377,491,900,404,687,443,154,292,818,814,959,377,605,151,623,412,882,34,689,66,109,915,435,568,446,603,151,244,309,29,845,954,760,707,879,287,791,622,868,290,675,979,453,173,499,559,649,367,708,99,456,783,20,205,72,780,483,677,692,473,196,137,880,23,827,76,305,468,646,898,459,465,487,19,104,222,667,402,574,520,812,845,319,74,998,771,590,951,967,99,548,523,753,983,203,73,430,704,349,674,888,522,41,68,287,478,512,238,667,578,981,950,341,135,430,769,346,320,607,408,144,372,50,781,964,438,469,428,5,42,345,809,482,507,227,727,605,207,488,970,562,34,546,319,841,263,315,224,932,19,136,972,816,499,808,628,182,744,476,549,420,6,29,644,542,348,873,921,617,153,845,328,691,489,39,488,520,758,821,246,633,951,395,322,650,259,427,741,838,517,595,40,714,731,499,547,306,870,539,289,812,709,918,591,800,173,376,948,320,797,599,375,944,69,442,193,663,847,149,637,561,778,153,372,511,338,374,321,387,225,528,622,98,150,434,783,284,37,550,384,571,634,65,187,893,599,631,8,584,38,541,967,272,246,445,769,943,333,658,864,586,346,226,74,871,505,972,769,229,547,331,82,863,408,137,256,313,756,221,915,392,658,613,609,885,358,226,352,413,240,339,278,654,883,441,824,779,754,493,982,389,792,175,158,225,528,419,59,717,59,757,510,317,362,174,344,88,726,930,805,754,443,631,962,799,166,956,25,862,23,80,851,508,836,434,334,729,389,383,775,275,255,796,187,891,166,397,334,578,490,805,176,809,46,214,901,414,868,272,773,752,784,720,57,369,108,315,256,947,78,679,414,603,357,459,573,388,670,592,94,154,194,691,112,418,939,554,489,851,300,97,497,767,926,706,488,928,674,42,883,266,495,88,7,184,690,446,695,962,109,779,482,985,661,52,394,539,926,987,51,713,105,210,983,334,522,36,514,346,901,602,286,723,926,385,877,122,322,220,302,274,94,585,759,644,778,106,266,811,862,481,214,680,386,628,902,729,352,15,578,704,231,968,852,551,888,767,211,414,392,551,921,384,971,678,401,250,35,509,390,89,934,384,567,526,598,224,969,812,646,394,114,368,521,954,400,807,736,689,441,785,634,334,552,909,708,448,390,641,128,678,874,257,149,516,920,671,94,490,980,964,88,58,228,175,130,157,503,105,238,597,405,73,782,205,242,544,893,638,403,658,251,547,771,42,55,224,847,731,732,461,874,471,848,348,253,59,714,513,635,230,872,94,840,626,862,256,445,409,370,505,251,542,205,964,679,64,583,394,341,98,681,678,879,742,73,615,240,53,702,553,262,22,118,744,122,166,316,764,508,775,523,599,476,18,397,697,318,831,598,439,102,383,505,876,614,536,769,966,854,110,378,502,78,599,578,856,313,406,277,143,974,763,43,897,273,679,267,332,429,677,149,171,805,136,543,626,366,403,72,346,114,54,264,438,192,537,20,588,151,698,11,368,946,191,421,631,406,923,653,565,779,48,637,777,421,253,944,116", +"49,619,260,723,413,33,558,146,489,167,84,837,508,576,538,889,838,517,652,822,147,620,417,260,389,787,878,869,295,849,560,663,123,247,817,674,258,992,944,678,592,339,288,852,954,885,419,939,126,953,487,909,352,899,267,68,953,464,708,840,545,442,401,737,336,350,243,605,396,760,893,335,436,620,948,894,715,21,725,142,500,110,821,911,974,401,257,40,631,459,237,820,390,278,514,234,807,72,319,214,30,742,894,905,489,808,785,957,1000,558,583,819,524,81,11,711,67,161,810,710,363,230,691,492,595,876,178,129,90,210,965,736,713,487,412,538,326,922,270,849,764,14,507,150,688,815,486,282,571,360,544,964,31,10,859,304,332,644,16,874,512,333,974,725,409,625,494,860,840,650,839,392,50,462,50,940,203,889,173,743,85,111,424,929,171,160,405,774,298,383,965,701,641,0,834,959,886,542,142,240,469,722,959,583,773,447,624,340,352,853,222,488,680,131,191,90,344,307,448,899,640,40,760,188,880,466,606,138,835,155,179,372,348,842,334,930,313,186,189,690,346,548,464,532,709,7,543,989,925,660,425,82,700,395,695,517,269,705,528,784,561,833,51,498,958,378,61,549,389,226,415,573,876,658,903,160,586,903,897,476,202,808,376,744,473,888,75,785,98,660,527,588,611,946,488,18,932,891,623,625,498,132,547,196,773,787,165,535,734,777,362,290,273,102,563,513,579,916,317,799,740,717,884,198,207,262,209,866,82,331,494,800,685,950,908,411,988,878,698,748,931,810,404,747,611,286,334,925,495,467,969,506,811,61,799,240,144,459,413,378,229,807,871,273,626,80,533,806,760,82,416,148,954,211,734,475,666,581,516,76,47,359,515,962,99,760,358,647,913,956,178,621,508,926,838,937,414,725,358,497,312,103,416,190,783,506,155,779,123,854,198,860,897,79,54,170,831,219,258,694,890,56,233,89,800,434,398,436,590,182,515,421,266,476,652,824,491,235,868,217,714,857,16,111,752,195,520,770,52,83,425,266,626,269,93,494,901,618,68,612,927,987,666,739,578,181,278,711,374,95,883,409,151,210,300,391,220,363,984,252,489,641,283,173,827,494,107,993,226,364,430,136,981,493,553,938,313,703,534,471,665,678,99,944,468,329,532,840,947,262,24,353,992,837,987,464,871,465,874,94,856,907,133,492,20,884,729,738,164,629,770,536,240,707,294,685,397,535,617,62,402,730,402,313,288,597,254,780,810,211,665,163,260,658,868,672,150,317,684,797,646,47,644,4,822,865,516,655,459,54,414,96,514,225,380,909,706,637,713,499,555,519,862,604,196,968,992,943,24,624,257,908,267,126,351,816,637,638,19,842,948,904,345,459,895,102,766,926,670,186,919,994,412,609,852,100,384,695,352,189,903,343,286,953,364,194,561,962,36,126,100,737,891,589,899,16,583,731,293,44,38,707,692,905,772,22,796,175,766,193,896,304,418,474,356,752,781,320,935,68,725,594,797,341,119,325,452,416,190,755,119,117,692,803,731,568,871,482,512,724,761,15,570,153,514,388,721,92,810,675,576,253,217,922,808,106,911,247,411,558,401,186,920,887,396,337,541,727,8,925,353,552,880,624,540,371,289,983,59,80,511,782,952,345,864,714,416,670,159,399,199,215,341,279,606,595,959,80,107,371,848,294,333,36,516,262,819,327,874,73,485,748,865,440,679,944,375,868,180,642,550,493,261,484,629,789,905,905,127,936,332,61,944,887,746,249,718,150,659,385,403,501,737,548,396,657,48,587,118,509,784,765,139,823,791,16,331,600,933,722,449,221,848,928,194,72,212,735,878,610,154,718,871,915,996,857,974,454,87,9,390,794,855,430,99,32,297,846,384,853,480,432,333,32,772,192,442,927,115,910,974,611,354,541,660,699,745,835,950,839,592,353,933,713,740,78,463,139,760,883,202,714,986,883,29,499,993,111,35,254,661,447,200,825,855,289,693,598,268,902,334,640,487,438,649,15,409,85,156,939,957,679,19,112,87,95,829,456,240,784,730,935,326,506,683,863,894,877,680,121,243,471,608,560,531,71,247,974,738,985,476,687,787,369,438,125,713,218,248,541,909,156,220,121,815,427,873,338,264,933,49,780,86,198,104,683,800,412,399,661,908,976,266,751,328,75,284,827,522,543,953,207,967,342,713,300,794,859,668,574,612,525,572,97,651,242,897,641,175,682,193,159,566,329,913,605,266,787,822,206,720,121,30,102,937,959,314,486,541,849", +"448,477,652,118,431,389,770,905,956,528,710,327,346,414,744,413,494,407,82,228,945,963,202,169,604,460,116,230,101,512,344,82,941,744,865,299,305,825,750,88,167,742,828,239,737,23,879,384,294,500,706,240,784,572,715,502,489,976,910,264,778,814,743,374,19,197,904,399,401,53,823,860,285,913,778,235,552,261,746,197,813,517,27,509,828,808,615,974,917,696,218,750,683,804,150,427,972,836,384,982,338,187,325,397,20,513,433,239,651,292,332,733,206,800,256,841,82,731,388,885,901,650,939,237,257,270,560,725,950,976,543,192,983,189,164,174,317,87,629,886,582,449,499,516,829,193,669,228,537,457,95,85,231,682,185,731,416,55,675,823,244,530,922,737,87,218,436,945,421,211,328,317,540,671,139,899,431,279,68,145,877,239,370,25,388,184,275,807,404,638,764,517,310,834,0,255,610,623,78,329,197,729,83,868,549,921,141,431,496,976,933,700,510,358,512,413,930,750,517,371,283,276,751,492,624,786,400,829,571,387,267,836,837,742,19,697,18,765,439,728,990,269,354,375,396,376,439,544,438,342,236,462,648,32,598,911,956,521,859,488,805,473,338,401,585,600,629,227,169,321,232,743,519,849,698,627,78,512,868,886,901,457,206,692,126,773,991,231,430,368,508,804,471,335,119,794,401,38,66,853,366,421,467,613,704,135,668,39,662,815,248,541,523,541,366,272,580,123,607,839,167,835,271,185,716,114,813,8,839,14,610,765,554,102,230,44,354,304,431,731,300,794,183,802,174,76,554,223,865,283,382,827,356,750,512,155,971,258,876,391,320,120,394,73,865,472,373,559,875,37,872,16,826,193,966,577,820,513,335,500,779,507,944,869,204,84,377,782,898,75,385,650,728,658,920,287,730,24,634,958,363,275,903,55,12,459,493,678,267,613,654,21,547,97,555,373,751,513,190,887,887,590,304,325,347,627,565,549,513,940,883,722,194,706,602,258,17,977,128,70,266,53,455,532,141,419,840,813,183,658,838,882,914,109,17,108,399,880,742,796,855,552,162,122,593,650,914,833,790,271,343,356,346,269,169,820,546,250,595,731,366,797,625,576,629,877,876,699,755,665,671,915,337,747,861,284,254,129,644,972,172,280,996,109,996,831,805,747,655,197,273,376,896,737,885,410,150,973,39,491,284,741,749,536,142,677,898,43,741,690,766,960,843,273,203,809,554,277,311,472,740,130,857,213,595,91,786,651,431,228,692,711,420,269,324,275,750,279,761,633,348,282,645,966,454,670,408,608,395,24,845,28,895,171,435,10,176,317,945,2,55,810,858,349,378,629,277,431,731,32,504,366,119,814,392,397,593,771,497,511,197,544,766,758,429,295,400,101,444,848,459,680,907,254,986,113,538,891,57,325,627,343,798,16,290,108,883,55,896,830,417,9,78,152,455,432,807,555,753,793,38,678,640,813,928,981,360,43,585,182,79,387,272,246,542,245,801,887,248,471,420,486,512,883,326,362,909,27,159,922,67,302,699,903,235,75,100,778,336,525,490,224,823,787,491,370,40,683,677,607,115,595,771,172,947,230,479,981,964,592,762,763,321,997,569,527,535,274,721,979,423,249,662,885,513,5,758,86,732,447,805,941,882,71,216,500,480,270,753,676,205,104,6,444,64,322,462,608,525,308,557,682,490,485,151,152,920,364,261,433,550,161,671,466,380,767,422,361,204,270,312,15,291,333,609,957,277,912,608,175,27,694,459,727,266,800,973,591,843,74,572,737,748,603,567,312,47,640,569,660,546,128,201,355,577,287,193,880,751,26,830,815,630,345,692,944,532,539,814,999,127,355,326,979,646,650,862,8,609,863,538,970,243,927,554,812,692,843,461,715,651,531,859,773,958,346,506,82,397,941,728,118,546,975,378,647,485,916,17,145,671,534,597,2,745,631,890,340,811,95,69,508,150,791,734,261,855,802,536,820,221,627,67,727,957,230,72,582,54,121,696,779,727,535,992,933,386,865,127,682,831,833,156,655,459,5,456,562,890,564,342,511,560,174,494,485,551,806,81,177,632,809,516,231,914,236,836,79,19,680,41,437,237,188,461,485,238,861,558,844,233,845,984,504,328,34,665,349,414,744,238,496,779,198,401,825,715,247,31,4,291,306,226,146,361,860,852,613,956,856,46,421,356,465,898,637,866,704,383,821,493,400,508,123,493,125,326,939,411,397,351,704,704,723,741,431,173,209,679,8,539,859,780,459,187,398,222,332,637,500", +"849,822,788,301,736,435,356,454,860,279,906,532,279,831,307,105,375,721,808,692,86,244,606,823,306,720,512,337,580,864,760,781,728,880,148,123,723,645,898,782,122,463,733,91,747,282,481,506,112,393,61,897,846,266,126,852,921,774,423,376,318,679,645,310,319,552,595,321,303,218,448,846,251,96,195,291,233,957,317,562,397,182,352,147,695,762,311,908,474,827,989,270,112,472,915,571,802,859,116,757,672,454,209,290,452,110,32,927,785,335,242,331,759,690,585,564,374,392,56,684,928,913,501,25,879,111,574,161,246,482,262,145,661,937,175,110,126,184,895,667,764,93,868,533,133,166,485,503,168,448,651,738,491,84,118,980,598,291,14,960,521,849,984,930,623,891,916,340,646,844,633,217,395,213,219,825,656,255,138,844,502,939,260,953,87,742,97,532,829,451,631,577,951,959,255,0,852,654,988,722,437,98,881,954,366,958,448,123,908,81,799,183,792,697,500,719,878,658,299,605,13,352,458,324,722,937,286,913,932,782,36,969,528,803,65,649,489,119,561,533,813,697,439,480,679,685,291,965,184,804,132,348,325,5,763,366,952,197,407,100,846,950,169,145,517,671,464,118,755,350,58,541,979,502,800,925,922,591,82,181,540,211,92,793,657,288,263,855,530,793,386,467,658,188,263,48,60,540,881,823,929,919,579,684,699,66,869,645,411,991,99,236,327,251,508,384,126,498,992,598,120,743,290,840,548,14,664,928,643,716,438,912,900,157,54,711,166,897,397,756,805,899,84,73,374,36,761,501,84,817,280,578,984,458,682,93,280,490,644,154,45,569,449,563,83,250,743,525,763,334,212,18,677,560,904,246,846,406,719,416,360,807,620,769,998,385,725,493,207,648,735,806,262,601,780,904,767,193,200,288,101,364,730,825,444,367,634,187,157,324,947,2,506,127,89,964,985,266,429,868,804,518,64,328,9,635,257,17,936,526,954,698,313,385,537,749,419,662,326,121,771,509,178,490,737,52,261,689,953,31,666,825,85,264,726,290,500,807,609,749,334,459,295,884,170,523,790,844,882,886,782,304,154,740,118,420,284,204,559,582,202,92,533,410,639,905,291,17,165,421,641,896,891,408,418,3,731,418,91,540,981,489,815,631,463,403,974,83,24,798,150,376,945,146,514,112,251,629,208,59,35,670,798,930,857,620,949,24,219,267,78,64,554,179,996,832,770,421,882,393,932,386,767,227,378,634,555,969,298,65,54,849,512,34,443,728,217,647,60,18,121,164,911,84,513,768,439,337,183,919,434,630,925,837,199,555,834,618,23,663,337,967,645,243,533,912,359,281,961,285,71,116,210,636,754,793,641,202,711,168,766,823,510,111,701,654,603,390,591,642,764,266,128,393,720,290,703,96,768,69,227,940,131,744,511,857,209,308,901,105,229,497,280,89,778,916,47,337,744,424,759,927,776,709,996,375,222,872,591,67,986,24,888,707,966,705,330,275,829,738,29,332,797,167,80,548,139,965,403,898,496,35,934,257,312,109,340,173,500,420,481,66,892,886,841,217,32,940,596,545,98,367,637,132,419,287,421,612,713,530,585,881,436,498,789,533,104,291,343,981,309,659,20,231,624,112,323,467,279,214,901,138,647,323,219,956,16,919,874,444,442,608,862,679,763,512,599,125,209,808,327,358,484,221,450,902,487,191,493,351,561,754,421,798,345,712,722,111,67,664,640,452,288,853,992,676,952,398,585,728,660,530,163,672,890,583,954,511,711,603,412,876,820,141,790,326,122,516,405,248,716,767,116,359,431,761,411,770,708,668,725,676,351,206,501,787,766,745,648,190,471,887,919,585,713,656,283,971,800,448,547,668,182,534,338,231,269,578,44,90,12,320,347,548,619,18,454,787,264,877,476,606,139,44,881,825,896,633,243,251,289,984,846,863,473,990,165,840,937,860,684,928,935,25,282,202,972,59,450,419,309,673,685,622,845,227,443,369,578,956,760,472,125,381,698,515,331,736,73,126,1,370,942,910,26,413,60,361,820,498,600,608,595,873,806,879,594,497,724,57,776,835,245,843,997,254,171,372,505,74,474,867,530,213,592,941,130,924,519,893,746,473,407,331,485,627,636,829,271,888,650,466,291,61,90,254,475,450,421,157,40,406,197,787,124,642,577,666,73,575,679,231,723,221,620,976,788,170,603,300,235,594,603,883,708,361,357,783,985,531,804,652,954,773,298,546,278,307,723,159,332,411,143,115,588,537,673,942,291,944", +"381,968,918,412,366,961,535,658,812,578,691,772,119,724,855,49,622,677,587,835,376,582,223,62,727,392,131,705,504,221,491,452,555,404,418,133,824,251,106,656,347,639,576,821,923,627,197,310,88,719,650,104,14,757,730,211,641,805,208,6,504,765,904,612,607,322,850,110,664,32,82,961,415,35,493,705,616,308,507,898,395,460,374,959,873,123,487,963,881,987,897,343,939,822,881,969,437,425,18,423,437,324,785,751,867,618,146,209,802,421,934,775,597,161,672,366,318,694,468,55,604,609,905,910,181,733,89,419,88,574,587,212,754,636,246,151,262,920,649,496,712,252,785,205,850,268,986,263,719,965,32,79,220,877,19,258,355,123,719,118,72,288,640,611,831,269,586,831,362,735,276,540,935,702,949,922,326,61,744,944,609,455,34,543,996,185,495,5,650,374,227,190,324,886,610,852,0,614,537,417,146,915,864,435,269,742,489,323,986,529,498,985,216,566,743,727,416,608,289,897,889,90,858,134,190,924,824,894,528,251,637,171,154,358,348,366,432,585,691,693,540,100,79,335,660,439,755,828,485,883,647,457,992,762,334,598,565,546,988,392,245,621,157,316,296,900,915,241,46,520,215,89,525,321,503,806,906,437,800,347,751,797,44,143,302,479,43,953,819,713,267,342,892,91,757,934,393,600,716,203,793,298,416,280,196,822,513,131,846,482,435,813,212,640,85,540,625,462,278,354,707,311,201,675,137,540,121,682,107,966,163,678,902,782,874,522,54,313,119,380,517,973,547,138,130,479,829,271,686,693,944,979,75,306,728,901,826,523,988,92,660,214,902,245,192,922,665,32,799,516,519,848,32,72,583,652,410,330,571,998,795,620,340,9,54,933,178,90,117,615,491,748,947,182,790,741,751,527,817,578,491,952,38,170,102,486,76,733,570,135,261,452,734,902,987,421,453,115,84,514,738,609,443,594,922,717,427,403,170,210,815,79,35,246,917,191,136,609,845,358,386,125,60,838,593,934,5,819,542,405,940,881,111,699,921,774,432,97,992,93,841,540,277,422,228,24,667,109,426,198,218,194,349,101,200,670,911,60,652,673,761,885,831,139,125,278,231,904,699,861,917,803,717,805,558,745,957,741,730,322,318,416,340,758,726,109,876,725,455,834,664,555,227,688,920,82,194,836,730,514,915,278,972,733,347,396,356,678,319,33,227,532,955,107,295,760,73,374,461,118,220,577,908,905,105,193,678,19,415,777,81,15,584,481,933,641,497,962,497,862,784,610,41,164,234,50,737,981,391,365,788,103,88,455,136,796,784,196,753,910,1000,566,81,723,280,212,691,216,65,385,137,970,48,429,942,60,951,961,341,581,84,266,417,617,273,572,962,267,94,687,529,342,538,687,574,459,428,437,380,610,628,457,487,542,10,107,552,932,367,939,203,11,140,949,658,517,541,954,679,703,412,254,711,317,583,530,704,501,635,822,148,969,172,815,592,754,699,119,239,47,33,514,259,25,822,873,861,695,686,863,174,854,869,643,995,974,829,803,613,391,941,345,279,536,986,775,7,756,790,474,580,443,715,370,960,116,64,779,330,336,334,89,987,453,579,908,715,790,559,280,31,206,462,232,368,868,844,458,608,643,31,827,327,149,661,731,28,293,407,658,575,538,85,197,506,699,379,301,787,607,857,952,105,463,222,941,260,223,19,677,993,842,438,352,347,849,497,171,512,695,427,541,54,893,448,365,658,338,766,890,478,437,782,728,450,424,324,278,204,119,642,315,67,482,667,546,214,94,916,801,831,446,412,290,638,887,866,509,642,426,348,254,773,540,211,789,847,247,546,964,974,565,621,331,936,433,601,514,56,157,851,680,700,920,535,313,699,87,718,888,779,944,761,397,562,711,778,507,297,455,217,819,929,767,818,708,248,664,598,90,721,845,116,314,995,866,956,24,818,625,696,249,960,158,358,905,564,67,54,323,745,310,141,696,243,953,992,540,820,143,148,942,198,482,5,256,513,881,556,333,298,675,576,961,861,607,219,716,302,690,854,973,514,814,700,48,456,257,370,938,852,20,803,820,33,426,176,710,883,755,984,290,963,541,650,429,210,897,255,421,169,531,974,356,773,73,36,120,383,62,244,929,161,313,901,348,923,765,459,200,980,757,695,9,295,166,80,585,882,370,736,522,633,319,993,125,830,40,112,388,70,901,835,447,380,469,581,508,692,157,148,445,257,161,436,459,684,536,467,577,903,837,421,979,500,864,31,885,973,757", +"720,17,689,789,235,606,784,97,165,338,848,557,263,381,148,631,135,76,370,867,730,319,189,171,668,433,299,647,562,351,433,648,335,736,993,183,215,49,996,607,834,232,928,351,794,863,514,381,141,414,211,989,996,944,585,78,381,421,46,235,946,712,468,550,576,14,814,14,843,759,106,165,753,551,584,434,578,622,929,855,421,910,630,223,253,802,991,389,575,470,991,547,2,45,541,389,435,654,676,473,995,547,185,816,368,258,190,328,32,520,957,180,945,550,865,786,614,183,136,597,741,136,101,736,598,58,114,210,112,233,331,796,70,89,581,111,219,834,697,800,807,169,245,790,801,854,158,961,941,50,83,903,518,48,701,567,304,892,188,617,247,662,451,226,588,627,389,765,133,173,50,79,518,996,793,791,901,805,329,421,986,273,466,779,263,631,480,335,961,60,597,386,847,542,623,654,614,0,450,296,852,392,13,790,893,12,236,290,447,569,755,869,996,202,385,536,309,597,173,525,653,178,292,719,110,703,981,722,482,965,113,923,269,471,431,390,932,836,668,232,119,294,647,13,985,785,299,603,531,500,840,614,8,717,110,488,143,730,446,291,172,558,601,872,794,240,594,160,179,782,329,865,336,215,59,728,847,957,847,751,341,370,755,343,557,599,798,792,661,775,847,723,684,491,274,771,179,545,307,942,95,632,91,965,604,149,86,634,252,221,491,892,343,453,143,148,175,753,72,570,988,396,557,677,700,148,426,401,85,921,176,210,162,869,741,225,386,663,331,337,99,759,603,878,885,885,321,417,116,101,768,661,843,119,669,352,748,135,837,568,40,429,527,650,212,393,159,968,917,108,986,909,520,213,615,745,890,707,672,697,918,943,332,951,808,831,946,589,768,71,153,185,251,398,992,616,484,247,947,954,906,796,796,29,243,268,983,500,50,704,36,300,234,237,716,112,477,408,481,163,400,958,447,205,382,192,86,99,256,631,721,857,491,664,594,496,208,570,539,214,959,549,646,648,979,33,112,280,273,568,481,265,452,59,891,667,389,951,889,137,130,656,66,210,178,400,94,513,670,326,898,590,791,618,70,496,562,440,39,790,457,983,226,731,697,186,345,634,264,421,217,207,257,696,38,90,897,109,396,970,771,215,929,180,620,66,258,551,771,347,941,79,752,846,9,616,567,903,371,409,85,382,701,331,504,375,359,614,891,887,115,721,279,623,874,839,628,901,817,546,718,168,925,71,208,8,284,345,709,931,627,195,188,97,823,495,143,459,249,216,5,979,942,472,493,971,157,483,30,542,140,656,26,491,443,627,840,912,652,630,674,674,724,363,415,825,953,757,444,959,691,656,881,546,860,293,236,980,923,534,649,135,770,872,775,98,819,105,432,547,600,228,479,25,41,735,724,507,860,894,611,322,929,69,426,230,411,12,739,171,989,893,900,176,975,854,972,44,602,528,396,33,152,38,580,714,243,920,345,846,819,45,325,85,368,241,705,349,682,649,560,17,466,857,861,190,44,662,148,468,225,280,426,568,813,771,34,404,469,524,408,212,451,472,131,77,262,447,905,532,475,144,821,998,658,132,961,715,966,851,678,683,116,157,459,671,479,736,636,940,176,897,727,944,570,499,686,982,165,320,957,963,266,576,382,830,927,48,244,293,269,16,796,66,340,749,485,567,648,758,170,191,232,938,323,208,631,750,295,371,190,934,786,365,882,158,525,697,760,742,199,732,255,507,585,214,894,818,46,697,212,430,334,155,742,935,154,128,685,271,797,155,364,979,641,289,879,452,647,285,161,376,273,770,677,933,789,804,226,208,749,273,393,924,218,508,891,298,181,369,714,410,243,801,105,219,534,963,110,440,787,937,219,591,869,843,777,495,961,888,438,855,917,884,138,586,334,572,579,244,695,518,478,654,171,341,605,736,479,19,962,881,460,91,20,649,695,604,166,167,368,389,868,603,110,113,927,870,794,536,314,313,676,88,407,217,292,711,326,814,915,815,244,518,815,534,627,977,687,278,37,662,151,364,699,703,622,469,465,758,813,760,588,381,7,890,781,366,567,855,809,348,966,250,764,382,96,27,503,649,632,36,793,847,669,479,614,3,431,889,678,769,899,130,828,741,189,930,111,575,925,210,987,216,751,253,234,867,439,572,351,619,101,961,828,871,27,321,607,417,658,934,981,504,394,263,554,718,896,67,722,966,315,365,565,184,291,303,750,407,551,57,826,662,669,133,402,632,300,666,49,231,14,616,439,42,507,736,771,127", +"166,632,104,988,90,170,930,210,634,938,873,269,7,143,235,639,585,534,105,440,732,536,662,504,367,678,776,484,168,194,776,304,474,279,309,321,248,769,347,300,892,418,454,558,828,816,765,901,825,481,89,25,23,127,972,912,570,374,606,726,428,348,427,802,349,383,174,691,868,516,297,774,528,759,608,140,487,104,55,984,229,310,321,821,827,70,248,800,150,647,500,380,947,176,597,178,824,256,629,199,724,687,803,885,209,315,392,742,184,693,253,161,948,708,598,831,410,46,905,717,633,618,698,420,379,27,629,787,836,865,814,457,779,515,642,653,110,855,143,75,76,546,261,966,748,266,798,738,103,757,355,662,602,203,299,556,790,326,764,644,121,527,124,868,420,145,112,218,50,482,788,953,948,636,659,339,414,213,649,79,413,396,693,920,755,448,826,476,811,904,297,432,137,142,78,988,537,450,0,788,577,789,894,950,944,738,32,866,979,815,416,87,982,435,714,953,344,31,765,959,770,720,636,773,318,826,483,393,731,518,137,377,792,996,553,424,613,751,229,548,337,589,784,505,252,702,28,53,405,420,325,545,792,681,965,502,602,969,489,739,965,575,588,644,441,993,593,647,534,247,551,148,584,462,808,663,276,486,77,859,991,560,36,869,199,79,666,45,865,293,53,139,372,194,117,904,471,603,63,109,694,317,437,614,177,722,356,31,480,390,217,440,682,114,882,438,380,626,479,772,785,106,73,571,449,995,653,472,810,9,761,923,498,263,753,824,604,597,556,45,647,893,718,718,598,139,486,959,889,852,473,531,198,822,788,370,224,136,461,799,251,928,9,120,57,2,272,73,701,41,477,696,743,726,392,120,388,421,91,634,108,850,36,42,409,330,915,843,317,778,591,282,926,373,374,458,571,411,314,182,874,450,459,401,225,495,603,310,895,627,204,239,18,13,567,661,908,175,123,543,776,83,203,550,697,392,313,816,327,422,69,526,200,443,383,265,166,140,73,669,420,723,941,962,83,740,42,910,394,280,606,504,568,761,863,321,324,887,871,189,471,876,501,928,182,778,21,414,187,151,163,73,964,449,254,121,825,899,254,845,689,769,775,445,3,92,403,20,493,28,177,94,741,860,722,147,160,410,580,720,735,806,319,798,297,49,778,876,588,745,247,83,189,585,12,590,540,368,449,940,187,523,612,401,498,834,423,594,886,529,793,818,293,440,532,734,660,778,469,931,724,200,950,588,436,465,545,163,184,690,488,100,108,530,899,227,886,896,474,882,854,192,255,58,130,147,631,485,960,493,498,796,25,126,418,910,453,540,776,393,416,738,106,100,745,999,42,882,4,874,607,831,576,91,598,797,693,854,59,497,112,397,415,481,825,210,677,269,322,57,433,707,402,510,781,755,694,700,466,414,731,712,224,156,975,941,511,758,451,306,801,997,478,732,189,472,835,531,536,788,574,664,325,379,606,759,680,897,939,397,735,652,139,831,354,675,768,857,707,43,937,712,972,371,502,97,138,888,755,117,304,800,603,447,232,43,72,607,35,284,993,429,520,571,165,934,636,899,417,890,960,727,664,810,660,566,633,826,729,491,581,834,843,887,874,212,880,718,193,144,432,896,377,299,197,98,804,891,560,540,832,465,358,659,247,436,338,430,750,803,854,753,423,636,661,677,677,945,848,242,908,326,199,10,469,464,387,728,498,744,453,42,325,514,41,87,143,917,329,830,731,527,416,642,8,641,843,362,732,794,93,384,304,79,823,728,831,598,48,500,356,683,37,998,578,313,959,284,179,972,703,356,778,249,68,915,259,250,363,570,48,493,88,92,900,593,35,416,410,182,756,387,968,166,483,224,636,40,943,522,676,830,271,678,137,174,111,712,255,68,481,371,639,969,278,426,241,740,486,87,972,720,940,567,498,425,949,253,546,694,991,646,389,508,812,387,807,797,512,41,440,245,615,894,606,591,15,535,837,255,721,565,139,90,241,141,948,128,57,245,774,18,352,569,27,804,669,443,376,34,35,500,345,836,274,462,777,864,565,152,414,418,557,38,217,471,713,789,365,265,553,484,198,739,125,925,777,475,888,506,706,384,450,855,996,345,52,451,742,146,529,253,795,248,451,79,557,441,140,497,622,249,427,455,853,130,464,960,493,958,920,151,456,868,326,69,931,472,827,214,298,950,297,866,726,81,39,551,756,35,746,394,713,504,400,530,208,871,280,206,940,209,581,674,14,863,770,125,472,621,105,526,320,830,298,568,173,304,386,67", +"208,471,967,80,514,962,214,591,688,996,689,374,105,143,378,959,695,959,14,485,290,912,310,950,900,824,783,289,815,91,630,701,234,931,190,573,630,381,652,996,499,656,107,85,343,542,525,980,321,903,255,822,234,541,732,539,452,385,399,376,707,756,141,240,254,904,379,849,296,870,706,813,426,17,766,340,461,743,669,946,601,969,568,381,493,675,734,952,843,141,95,621,942,431,7,290,545,486,595,714,848,589,331,887,78,294,244,844,813,49,430,385,98,763,569,209,980,395,389,961,982,970,96,7,927,854,494,753,883,149,365,336,713,356,219,603,143,125,58,692,617,188,495,250,411,749,649,443,432,113,42,751,656,245,804,45,630,936,429,236,423,426,382,20,613,256,326,519,341,811,441,285,253,963,849,39,239,250,482,399,746,95,562,983,459,31,275,642,926,401,114,528,484,240,329,722,417,296,788,0,360,55,873,613,163,82,374,55,176,315,436,579,87,745,476,924,42,359,140,4,352,891,13,406,89,721,187,863,705,122,66,470,775,94,150,919,266,159,622,102,617,131,61,936,994,376,895,868,264,641,865,815,421,80,255,743,895,207,932,46,929,47,153,226,642,483,245,813,928,506,582,957,199,66,502,859,147,98,728,968,33,920,655,300,680,853,328,940,282,346,393,72,946,326,516,75,154,178,669,376,748,283,185,460,286,524,314,181,904,546,911,595,640,853,825,209,161,277,316,89,860,826,697,566,794,554,426,830,135,628,641,345,129,418,846,99,165,646,815,884,501,436,676,13,948,48,551,99,315,90,30,839,653,420,646,19,846,61,65,165,687,922,612,836,723,828,768,686,579,824,732,98,806,801,615,241,405,761,160,925,679,25,225,184,956,372,59,158,273,732,103,754,43,79,830,90,248,527,875,849,485,152,13,730,515,516,840,561,271,430,499,771,467,818,457,439,750,104,184,291,79,442,431,421,59,669,686,224,221,795,336,634,641,698,51,769,887,946,774,880,330,646,214,128,300,207,437,870,483,260,958,519,983,656,223,221,2,539,436,370,725,767,553,373,190,214,672,504,104,119,774,941,182,305,611,280,471,305,540,755,28,701,62,212,178,637,632,214,815,221,459,604,417,676,861,706,630,133,986,563,521,855,249,380,767,271,996,654,538,379,286,62,492,825,966,583,108,813,259,860,546,753,144,227,610,574,954,650,380,306,166,141,817,416,235,98,755,724,100,897,997,531,537,529,699,948,601,604,804,242,526,666,888,472,796,969,474,76,604,672,892,349,141,748,598,728,115,136,257,517,215,354,450,542,191,517,182,209,736,683,721,199,577,160,59,164,193,276,541,21,936,695,528,897,185,441,669,915,925,256,850,721,164,633,5,770,46,880,795,888,107,616,227,451,16,448,294,247,908,413,722,52,576,354,894,776,640,201,332,552,994,850,415,750,663,871,12,170,103,658,104,420,686,825,952,772,544,406,631,221,113,700,588,106,959,213,23,827,369,19,559,310,793,64,628,77,802,236,757,217,278,603,180,277,34,281,209,950,78,498,841,294,805,298,601,564,333,692,217,827,965,741,227,502,889,147,545,994,139,37,666,170,577,89,250,29,677,209,425,545,854,394,236,544,447,270,805,901,655,292,581,73,932,112,362,25,784,647,854,716,780,8,446,75,37,865,532,818,473,279,510,422,512,198,227,485,243,668,491,996,306,331,240,672,754,973,350,271,350,335,724,323,566,200,353,657,14,444,696,434,392,294,534,135,443,64,642,384,116,153,954,808,16,817,959,645,701,657,29,623,313,576,479,273,675,424,378,365,90,120,754,80,624,47,986,509,296,330,289,754,124,77,680,321,624,697,97,72,324,318,488,388,403,222,960,895,657,247,785,970,804,219,230,714,741,9,132,427,199,205,598,861,837,560,686,562,985,899,545,954,422,838,8,297,127,463,78,740,953,282,609,643,406,703,518,931,190,818,617,637,709,148,640,613,131,470,427,330,739,143,77,209,994,20,132,480,48,865,666,120,974,275,813,294,725,57,357,727,542,248,792,922,865,256,34,948,866,913,484,367,940,916,861,656,19,893,633,199,39,888,683,350,933,925,400,201,282,731,47,588,241,909,333,807,603,124,165,802,634,6,987,559,480,444,304,119,422,216,756,380,377,155,619,305,168,79,505,913,369,159,883,620,743,261,581,155,112,496,65,221,608,1000,639,970,767,553,953,901,332,636,712,760,396,290,838,256,498,239,156,286,389,471,249,765,451,222,483,438,561,48", +"178,639,837,886,739,72,210,875,682,663,547,38,905,498,944,939,691,726,935,352,88,419,670,750,215,238,783,555,471,375,574,798,409,757,382,301,949,678,43,520,342,991,106,74,141,764,665,350,789,234,786,584,269,288,232,640,852,29,671,32,711,299,16,121,923,173,627,588,992,816,751,416,127,547,635,213,613,938,117,20,646,484,928,649,227,497,751,939,102,985,840,574,654,717,124,756,76,682,593,51,734,990,781,312,966,563,549,912,900,188,391,960,261,361,827,71,391,244,281,786,691,904,402,802,12,781,927,609,128,330,607,772,545,641,718,8,562,271,540,794,581,702,85,529,410,837,540,814,886,836,200,232,740,77,25,716,679,251,195,876,211,923,199,949,406,638,358,570,346,370,277,552,683,75,760,323,985,364,596,506,32,178,920,91,175,489,463,373,795,587,869,664,150,469,197,437,146,852,577,360,0,661,950,862,414,559,859,161,219,401,377,569,233,315,459,834,494,137,404,365,768,154,629,496,538,207,504,494,271,67,608,26,895,539,110,738,57,41,803,652,250,717,930,214,348,338,341,238,78,217,561,116,331,589,850,9,683,941,965,527,446,800,874,140,297,287,59,969,988,506,692,199,128,859,992,212,923,618,125,754,511,577,836,300,195,169,75,108,914,821,692,479,522,502,594,252,432,13,653,510,641,530,610,87,372,597,742,373,66,911,440,383,434,147,698,799,614,899,728,444,602,98,949,650,661,830,45,441,983,324,177,325,764,106,787,431,463,390,835,478,668,895,146,51,147,872,954,492,172,179,562,304,501,845,456,643,941,53,135,423,181,974,766,110,568,332,663,487,999,385,356,887,572,332,635,874,667,988,493,406,886,346,706,44,727,477,631,453,558,643,781,991,230,657,240,732,854,343,580,595,438,636,614,63,68,963,329,45,968,92,288,487,660,413,647,699,342,228,429,214,338,149,184,399,933,403,436,377,523,542,836,604,618,387,751,86,291,140,853,979,587,783,158,160,157,613,294,752,722,46,134,862,846,686,648,942,542,574,788,880,169,89,351,306,402,217,448,497,767,255,48,741,349,839,805,34,390,862,585,481,825,703,779,19,477,507,522,470,528,663,734,562,422,151,85,479,997,193,999,226,38,106,120,420,37,508,984,877,475,977,774,196,856,916,616,897,14,952,788,360,105,803,897,463,470,240,520,592,606,282,429,663,176,202,44,286,539,394,753,178,127,356,580,547,855,593,837,921,328,769,925,323,828,691,104,336,115,247,519,148,804,946,841,864,886,920,627,699,294,768,323,194,383,498,185,575,225,545,765,705,716,516,703,790,139,309,854,577,985,309,664,747,97,338,334,871,915,869,221,536,399,416,366,23,238,665,464,182,622,769,438,412,273,881,248,130,263,559,884,319,943,604,217,412,294,798,495,428,226,872,198,144,216,713,518,130,838,4,558,4,434,775,800,533,936,750,516,630,124,742,676,404,413,978,201,227,557,209,607,699,311,548,940,377,470,240,554,255,948,350,632,139,709,339,179,268,525,395,40,311,621,911,604,565,968,489,799,347,994,230,285,382,635,881,853,348,314,748,68,531,824,835,187,159,336,37,783,761,954,967,554,601,794,815,864,84,203,467,511,770,257,87,493,306,436,455,584,965,867,993,904,630,892,642,448,892,155,705,151,360,293,808,398,558,457,655,324,583,612,453,636,348,278,617,985,811,283,994,208,71,999,278,28,301,550,937,132,860,782,328,141,616,753,693,728,467,590,111,313,113,810,574,343,753,47,178,906,450,116,123,568,668,630,485,868,813,248,568,857,416,565,783,111,615,652,167,541,907,879,247,86,554,995,859,803,664,692,897,116,405,948,254,980,684,336,557,364,713,670,670,867,595,887,402,423,921,296,731,295,784,77,907,369,845,880,837,676,961,79,416,652,606,324,413,732,992,359,522,457,979,960,790,177,348,227,308,591,875,494,335,943,488,772,804,539,505,765,671,894,372,211,19,980,273,798,534,604,5,678,916,133,791,130,493,229,948,352,838,724,77,785,253,10,571,980,823,854,853,20,663,221,932,479,192,45,817,319,350,897,780,137,53,543,269,543,702,946,584,238,131,661,313,542,541,253,166,81,586,509,515,874,116,318,710,459,136,812,324,532,753,599,14,7,630,538,292,549,389,656,164,788,249,590,214,939,754,12,776,656,909,648,866,335,697,234,577,691,328,679,469,919,162,31,997,882,341,931,981,858,880,488,24,157,173,903,175,215,492,792,216", +"634,273,653,457,357,777,51,959,306,465,480,735,122,710,1,628,642,319,1,407,866,73,459,577,240,91,307,867,841,228,287,610,339,677,445,709,831,640,378,831,628,99,424,195,429,504,134,10,272,983,500,219,328,420,115,857,308,244,864,470,612,758,995,314,947,889,401,917,648,571,44,301,636,437,457,973,30,813,114,214,267,963,438,233,404,409,694,515,544,609,886,304,329,314,839,641,385,277,250,998,387,996,535,107,307,4,459,840,286,972,211,708,468,616,84,739,635,766,507,545,968,792,359,145,577,532,823,681,709,257,110,678,723,587,519,255,814,439,150,347,947,505,391,893,388,302,132,234,724,76,538,736,594,973,475,98,227,706,421,400,677,185,886,910,157,990,943,316,470,538,215,834,608,131,444,829,355,123,249,216,18,835,490,859,987,497,685,556,629,877,367,914,320,722,729,98,915,392,789,55,661,0,973,386,208,432,20,809,860,287,431,921,941,842,689,956,69,856,373,968,131,174,179,160,340,966,636,592,28,410,150,580,40,109,130,181,844,1,46,617,379,212,862,29,42,823,553,399,452,567,797,950,797,832,352,393,745,230,830,866,759,472,470,53,643,454,166,833,701,318,928,617,996,615,624,739,214,403,559,892,817,27,65,301,423,70,173,416,793,5,576,225,17,881,721,644,616,77,434,290,643,944,769,152,448,243,744,292,440,774,545,105,406,205,685,709,148,157,755,682,268,238,268,377,845,202,99,852,900,94,792,400,395,481,10,916,650,578,656,427,707,809,6,100,844,126,747,517,527,76,751,477,301,925,262,772,941,158,542,602,117,715,199,654,56,172,379,120,346,857,348,466,572,123,722,3,152,126,472,466,419,649,503,846,417,540,431,237,347,434,209,55,364,620,342,925,577,558,161,542,143,905,729,873,859,423,726,831,183,54,318,624,14,392,189,112,482,672,890,165,520,517,255,247,960,873,304,545,858,839,464,212,785,735,205,208,985,843,184,567,75,159,629,665,596,937,64,359,252,646,610,520,173,612,646,362,53,456,246,279,84,216,401,573,754,860,329,416,168,623,77,775,101,727,202,73,659,313,935,799,396,454,451,881,333,620,976,667,455,818,626,891,131,203,844,728,710,398,861,577,181,798,852,369,644,888,805,575,398,523,310,464,420,349,577,732,896,168,212,450,91,547,776,977,543,287,583,435,246,880,464,993,83,966,975,350,327,197,945,820,146,263,634,794,418,345,603,529,884,605,478,763,337,100,273,108,989,691,222,920,488,434,280,246,832,867,475,745,480,709,579,57,937,668,567,268,680,131,482,487,278,639,62,187,852,829,490,956,859,253,843,524,949,74,414,914,818,707,870,441,506,777,113,192,798,641,510,544,528,886,136,773,558,284,480,460,620,721,146,219,360,647,957,754,906,99,311,990,995,967,582,462,131,550,118,361,731,780,725,370,34,221,840,457,714,80,769,5,811,319,223,388,428,589,602,813,566,104,155,262,24,948,196,696,293,406,379,451,291,400,598,830,137,719,676,314,184,127,867,823,293,528,749,451,442,141,840,50,741,72,590,970,322,402,565,223,59,795,238,587,809,721,549,835,6,132,866,337,823,929,967,685,369,808,14,362,894,836,551,976,183,671,159,321,981,699,685,475,308,611,657,717,647,276,729,229,986,268,123,652,783,846,569,710,420,845,371,298,735,667,217,500,986,433,338,602,73,969,954,231,444,304,141,439,390,212,272,952,779,539,482,350,837,392,244,182,610,155,189,232,409,186,273,292,611,578,336,841,252,550,291,963,806,221,341,641,798,70,121,697,623,525,281,888,447,345,26,976,815,677,79,185,578,478,9,213,33,679,512,488,723,708,809,538,640,539,704,241,344,471,755,680,765,591,551,78,427,559,883,894,289,617,643,400,663,51,808,392,501,193,347,117,981,457,813,792,593,19,987,785,505,645,105,895,159,776,737,712,706,919,786,395,747,540,702,771,315,101,357,512,420,52,190,341,445,946,352,709,508,346,408,415,235,341,340,287,840,784,664,246,44,720,707,490,284,311,610,307,372,480,338,238,194,424,522,390,539,435,155,966,360,643,817,865,748,35,768,749,355,227,133,85,462,14,40,674,664,684,921,78,339,817,149,556,705,657,385,225,676,166,401,625,895,457,572,578,227,553,645,137,847,173,38,683,374,930,299,52,487,138,683,862,137,332,718,519,735,448,641,252,429,329,574,194,304,240,668,98,463,813,233,392,103,882,883,279,203,602,270,361", +"557,142,656,333,806,127,932,158,567,603,769,954,454,458,554,169,220,11,695,319,181,73,242,281,561,982,225,940,151,424,447,89,81,95,750,258,315,927,825,400,922,735,160,682,953,221,514,368,838,665,858,629,994,479,996,372,752,420,233,633,85,110,878,682,590,443,552,350,104,915,500,538,170,346,436,748,679,874,217,704,163,339,15,998,637,285,756,864,154,644,142,472,542,276,197,976,444,134,522,635,209,501,336,377,561,441,275,125,295,683,210,810,708,966,753,916,911,806,713,521,410,80,730,788,718,994,314,691,699,659,80,620,381,831,596,417,290,546,403,864,631,497,133,679,695,925,806,556,929,324,527,422,222,840,586,922,728,989,930,200,578,27,612,190,750,297,107,762,304,724,288,662,231,666,78,548,58,756,296,259,925,436,707,615,144,602,977,958,425,814,709,369,951,959,83,881,864,13,894,873,950,973,0,385,396,95,847,119,938,339,315,893,101,117,107,512,914,910,597,842,787,396,164,169,712,150,373,106,636,305,94,11,478,191,694,262,6,94,578,831,942,270,678,736,849,419,387,662,582,585,371,963,144,570,147,847,614,312,567,258,856,908,706,711,124,787,163,790,166,806,454,93,300,222,557,40,341,872,879,733,939,927,233,634,851,438,212,988,406,516,205,816,743,619,613,156,330,37,506,660,212,661,970,902,87,680,690,482,955,588,918,444,863,315,925,75,157,195,978,286,186,771,650,79,324,713,857,792,348,449,814,909,905,207,287,701,275,612,21,592,718,440,771,711,953,78,883,564,840,56,764,303,418,505,59,206,867,980,591,146,50,428,406,768,363,900,481,989,491,415,21,746,5,106,876,20,479,301,626,352,439,871,235,484,243,318,496,727,346,622,586,803,95,984,286,307,414,701,691,286,425,218,383,346,852,375,589,390,239,744,336,212,368,121,103,584,819,713,653,970,177,669,910,151,681,798,279,23,480,815,483,951,948,545,490,255,862,89,920,436,570,572,623,691,50,260,504,512,205,644,155,834,415,279,908,806,377,244,935,823,709,759,128,908,844,548,313,357,70,6,965,854,562,20,949,570,793,417,569,749,905,106,50,107,841,107,764,847,458,263,479,283,100,346,754,792,650,499,300,446,318,224,771,925,171,380,71,626,41,772,670,946,917,387,247,330,781,446,828,434,866,474,72,690,8,763,917,328,422,122,773,820,704,768,546,851,631,212,130,581,637,73,73,646,106,925,926,795,958,277,977,235,146,722,282,900,442,782,713,612,603,704,595,421,978,347,316,654,381,807,262,390,436,796,691,392,961,653,73,837,416,83,289,481,191,627,487,524,522,549,749,821,118,668,227,296,494,224,701,80,70,618,633,839,952,703,30,57,322,209,791,11,130,199,150,299,505,519,492,80,466,858,719,784,639,818,258,180,733,33,119,522,626,554,5,897,688,145,941,959,443,825,658,345,287,189,93,105,718,190,498,936,951,555,406,677,483,303,328,967,680,243,179,492,775,577,673,562,594,979,816,558,167,945,297,102,463,969,163,508,132,531,349,87,83,976,410,457,441,44,633,86,19,664,211,43,284,937,883,18,549,793,608,878,114,133,931,261,386,946,465,287,375,344,61,377,234,639,30,289,179,532,411,586,808,677,147,200,445,118,897,461,629,256,533,199,411,666,843,999,999,450,635,198,554,256,660,398,884,136,264,474,106,364,276,226,793,600,885,538,783,458,195,95,937,503,872,210,944,968,810,195,378,520,820,717,258,908,59,403,41,460,6,48,894,996,631,247,66,475,882,547,861,739,30,192,501,640,462,690,605,66,476,234,362,978,845,357,113,111,860,956,395,878,77,294,338,31,735,941,621,406,710,132,892,886,747,10,882,558,757,531,252,504,189,504,163,527,396,732,143,109,674,417,641,167,952,421,336,679,7,74,597,43,713,923,596,619,846,49,675,770,568,456,465,530,757,110,753,682,441,671,289,846,862,164,922,910,719,587,965,990,714,500,758,951,933,256,28,313,334,600,765,568,710,110,667,135,541,178,798,477,346,69,529,233,543,533,494,241,111,928,328,758,670,334,584,909,459,658,503,719,438,992,819,279,915,395,956,244,305,749,305,628,495,294,347,867,891,298,433,779,130,828,907,898,534,25,577,102,812,902,126,388,845,513,243,249,611,238,410,447,706,988,250,209,158,386,640,224,755,407,294,16,199,610,371,65,933,514,161,525,427,174,966,6,791,542,739,394,496,637,690,871,910,246,398,639,453,224", +"595,763,465,603,963,261,163,278,447,70,287,340,331,409,368,732,671,963,414,955,887,53,382,887,30,872,187,676,337,983,674,347,620,139,295,469,331,612,968,749,211,228,158,873,311,711,295,520,926,641,630,899,622,519,636,153,187,734,218,269,81,968,439,618,175,312,42,115,948,712,176,962,244,274,641,715,853,800,427,585,832,950,818,413,237,194,811,895,927,455,781,709,316,3,17,532,324,694,718,266,460,490,19,903,325,854,598,671,703,510,811,120,992,389,530,26,197,228,507,966,997,622,291,97,78,727,48,199,787,510,271,556,968,309,223,922,10,928,487,528,250,551,434,20,107,484,574,544,713,660,493,714,355,425,744,456,20,941,67,395,314,530,79,501,392,210,342,428,989,17,947,402,950,455,424,333,512,719,226,799,483,228,239,317,911,669,451,405,313,928,588,11,695,583,868,954,435,790,950,613,862,386,385,0,545,543,777,614,564,616,341,976,426,969,700,157,892,165,269,147,975,821,253,602,583,112,981,823,956,218,122,450,126,143,446,439,891,462,366,68,717,215,899,420,555,197,11,602,371,856,345,375,988,289,321,527,82,815,845,985,323,98,36,875,89,108,365,502,490,98,169,981,830,873,945,9,334,382,707,383,429,991,368,651,860,810,243,43,808,239,702,68,470,105,746,561,445,401,9,309,608,764,744,962,600,541,547,780,391,156,503,721,15,607,916,131,842,383,645,462,677,546,128,685,65,675,977,985,93,910,185,996,474,591,810,299,257,319,264,906,899,696,497,355,11,464,666,405,837,906,216,348,887,14,164,83,171,79,74,439,666,345,712,665,126,194,860,986,264,181,402,73,138,920,373,138,507,732,204,747,779,751,795,3,517,988,427,300,612,634,842,36,94,210,409,847,85,715,709,447,872,179,467,20,644,682,95,993,417,300,577,433,552,84,211,16,383,195,205,992,981,141,165,429,475,769,646,850,105,142,707,325,778,759,291,124,720,563,872,515,652,927,226,304,302,974,303,84,232,734,226,463,678,419,705,445,797,771,124,903,423,108,87,530,823,649,295,177,778,398,916,105,287,710,770,952,395,237,223,60,345,433,585,894,669,702,233,780,400,93,649,683,985,124,846,299,439,814,786,850,745,979,200,253,530,924,223,439,742,905,703,268,420,981,226,18,154,767,437,19,917,534,74,75,434,111,277,594,504,591,744,974,183,250,992,765,261,332,540,887,460,884,606,80,488,178,662,762,461,820,676,875,408,347,950,203,148,357,824,591,256,915,207,390,696,196,237,800,685,134,55,135,770,703,124,715,824,942,383,957,78,687,728,75,335,467,552,641,655,208,787,693,707,890,508,278,212,471,526,57,110,940,922,259,743,926,875,487,487,47,399,372,10,9,466,736,871,66,879,537,880,933,977,402,284,368,670,288,799,199,841,423,252,336,401,102,359,833,93,91,894,484,11,90,149,998,275,539,979,174,640,935,446,792,162,734,139,970,529,522,356,573,257,431,858,215,319,577,268,299,866,95,226,480,67,457,994,865,549,234,167,742,494,788,94,835,205,981,100,252,827,532,572,34,816,357,74,438,522,713,62,590,956,985,2,16,719,984,8,733,559,937,380,455,350,792,962,677,34,391,718,121,988,668,116,573,160,729,428,264,624,544,787,731,465,684,362,396,691,57,269,851,455,484,712,54,501,436,819,916,289,754,257,531,595,958,171,557,526,716,147,358,605,508,656,591,32,959,331,205,421,114,655,63,353,96,451,957,222,291,463,517,979,201,30,981,959,51,420,713,290,182,371,253,179,434,78,971,26,54,76,109,429,289,592,371,757,118,747,48,570,299,780,266,128,169,779,208,679,42,142,889,677,631,607,883,776,146,750,745,356,222,842,400,433,271,580,131,951,342,832,814,763,453,405,778,363,211,731,160,751,623,248,188,861,467,679,490,727,926,530,459,890,180,355,562,768,445,304,987,728,839,305,488,851,118,580,422,733,59,35,627,695,946,500,449,965,75,992,955,631,107,691,631,25,519,761,143,507,929,454,480,834,852,283,781,883,416,942,673,618,832,532,531,597,401,640,27,450,195,606,875,924,750,297,872,386,707,815,599,843,144,381,497,224,632,325,145,710,657,686,308,828,333,368,323,533,978,883,882,214,708,422,523,758,41,506,78,603,552,947,377,840,996,126,56,299,582,5,927,336,260,70,68,337,355,413,629,804,334,560,270,656,914,19,862,979,972,929,168,792,537,975,913,43,476,516,682,691,444", +"969,708,154,737,754,532,617,218,804,140,418,158,189,623,718,275,755,27,904,808,163,50,273,713,661,56,724,333,879,388,903,821,450,758,760,762,65,933,484,815,673,384,355,597,264,465,493,98,308,354,214,11,697,851,379,545,321,297,812,996,571,570,707,473,551,163,171,605,829,820,751,518,821,686,551,540,630,641,127,466,590,9,94,873,53,707,606,667,98,372,976,287,998,984,856,230,711,488,163,891,214,591,4,624,189,726,291,38,923,132,432,6,376,134,68,229,75,680,998,386,381,722,622,965,275,984,746,186,244,262,182,50,965,567,894,128,353,610,540,947,184,379,892,559,207,683,337,86,74,516,222,836,484,357,241,843,698,828,227,370,177,543,145,825,999,841,770,531,60,86,849,705,586,255,966,79,219,884,667,739,750,788,94,308,536,466,945,332,930,813,607,544,93,773,549,366,269,893,944,163,414,208,396,545,0,437,431,269,511,253,246,956,560,974,635,221,766,816,36,952,958,987,740,583,199,121,5,126,736,792,413,671,576,596,347,235,635,957,746,735,706,158,164,760,144,649,907,138,736,313,293,478,223,675,855,295,385,521,392,764,173,94,736,959,986,645,937,73,32,274,262,897,637,751,721,943,561,420,992,663,285,47,22,890,258,885,339,556,309,412,345,343,312,801,55,67,72,996,265,271,624,237,856,822,868,861,243,838,225,776,957,187,844,572,859,773,119,625,499,959,694,951,543,732,237,907,802,456,847,870,535,600,350,78,328,359,249,350,374,933,800,90,816,516,206,847,528,180,314,737,268,664,123,586,483,476,94,50,940,593,928,193,491,889,777,461,850,320,898,89,632,563,121,386,577,957,407,626,859,157,390,387,557,785,107,869,377,205,392,806,973,99,231,467,2,769,392,813,246,363,54,923,896,889,631,860,78,693,159,873,882,847,651,853,230,302,184,842,922,831,243,310,241,655,783,210,672,707,511,537,507,144,887,392,251,586,806,886,929,207,517,708,253,563,733,518,662,385,636,503,704,494,761,835,857,875,515,235,541,905,709,286,126,115,417,920,522,243,632,387,725,174,267,102,874,363,892,438,805,285,411,153,699,334,654,732,57,846,840,336,225,250,182,53,586,216,471,995,712,763,605,859,841,101,78,697,556,134,931,914,416,420,195,29,928,530,167,693,981,929,341,301,377,445,403,415,337,71,754,715,565,547,96,156,598,594,141,678,531,253,830,311,132,446,524,952,330,796,61,723,214,41,515,495,394,33,477,589,438,849,573,837,975,24,398,221,386,202,362,752,936,679,198,366,570,800,171,316,130,358,562,154,7,50,439,359,130,486,466,650,151,800,780,978,201,40,777,456,763,160,650,598,919,724,927,525,555,453,901,108,416,486,714,811,239,606,933,741,537,774,365,635,933,930,771,626,514,871,343,823,699,686,153,942,76,533,574,636,643,969,193,46,609,937,516,249,630,52,51,261,792,877,589,841,301,712,495,769,744,459,452,919,354,674,20,339,311,799,102,299,634,875,733,527,388,669,105,467,959,173,365,436,787,189,947,962,71,520,382,467,499,248,281,804,182,557,862,376,70,422,396,403,103,243,613,835,574,274,29,342,38,996,684,529,453,820,99,39,773,251,915,459,45,943,691,126,82,238,927,30,48,665,167,192,78,587,46,407,166,720,296,624,648,512,715,312,899,740,526,41,518,364,464,552,881,668,868,403,69,839,353,911,774,478,7,380,59,561,190,292,58,857,5,608,697,930,254,181,35,876,238,753,2,512,212,803,283,503,246,119,538,136,215,951,753,967,578,224,651,362,890,591,159,293,277,273,658,376,424,424,721,484,174,764,815,754,244,847,457,463,470,552,38,975,264,15,653,346,986,205,949,104,300,183,862,561,557,665,679,329,545,567,413,170,455,788,106,762,735,451,147,273,771,192,210,901,112,384,574,415,925,372,372,200,189,647,254,407,963,504,242,146,926,759,799,28,602,170,929,364,867,12,371,580,220,338,220,231,879,755,172,742,17,913,965,230,680,343,417,24,436,206,330,654,235,525,968,556,448,825,725,476,647,253,889,926,304,542,296,25,92,989,375,23,470,178,437,536,561,609,193,502,159,216,851,692,958,195,431,399,92,341,697,313,300,214,86,195,646,824,486,107,747,770,199,16,202,564,520,912,316,108,296,509,425,690,782,542,381,489,165,8,856,855,739,208,331,405,227,905,541,540,959,45,688,556,118,349,764,161,808,417,112,68,860,543,220,147,807,479", +"968,694,321,985,213,979,662,106,698,509,185,99,635,637,69,248,236,20,912,426,771,140,883,454,119,832,827,552,442,807,381,538,674,125,32,976,978,908,7,615,46,443,273,107,146,898,686,518,400,314,953,135,77,362,285,59,647,451,753,550,91,518,944,911,106,53,766,282,37,361,546,710,569,217,643,163,785,794,25,731,520,560,8,214,7,518,398,669,893,540,486,521,240,173,98,306,83,671,286,831,640,676,449,31,441,47,90,406,793,975,532,527,881,533,403,872,250,79,747,901,160,257,392,75,950,641,717,220,92,222,723,621,409,495,34,532,222,527,62,734,115,115,986,500,481,789,485,390,376,346,325,610,637,844,11,200,899,347,129,898,511,794,748,874,352,255,993,74,55,333,443,317,650,600,877,690,542,476,780,540,382,549,565,839,876,677,325,305,96,15,842,674,881,447,921,958,742,12,738,82,559,432,95,543,437,0,491,269,650,228,111,175,380,157,12,322,280,462,838,991,457,500,812,600,434,812,525,773,450,75,76,885,857,901,848,435,947,313,703,207,824,967,379,845,86,312,812,278,940,421,196,547,845,765,578,414,606,7,808,128,499,546,666,57,201,915,401,212,164,732,65,910,574,723,135,948,356,210,493,504,195,446,494,740,233,37,401,392,928,637,739,402,815,577,340,5,220,282,93,475,837,687,488,508,584,337,319,96,877,45,659,647,157,254,558,501,372,825,34,768,28,527,667,703,520,737,525,841,689,371,174,566,363,363,402,812,340,493,12,536,958,460,240,691,54,198,240,685,875,730,318,690,736,827,783,958,887,88,289,644,774,804,209,283,34,532,476,994,260,972,279,12,14,862,859,611,622,588,279,964,305,16,278,722,490,823,485,830,126,516,951,891,942,352,880,558,772,432,510,25,624,694,773,665,346,821,489,145,817,901,68,437,805,5,532,266,18,603,622,855,507,418,349,795,832,495,912,415,267,167,620,912,355,276,937,714,378,15,954,630,478,267,267,516,550,98,384,197,906,268,249,43,899,428,332,713,839,889,775,210,942,421,278,608,523,402,559,212,134,164,654,358,977,440,730,330,86,653,298,18,147,410,197,611,250,66,739,659,493,354,73,48,650,784,794,155,524,608,423,581,704,74,548,944,643,791,61,799,734,179,499,913,960,529,961,861,982,397,519,601,669,980,55,403,333,281,204,457,271,198,131,480,572,997,416,920,8,496,705,184,979,548,890,389,734,279,115,672,672,281,587,444,26,482,428,36,414,728,673,474,966,974,843,582,426,293,316,663,920,126,936,634,51,367,833,340,828,307,163,297,819,270,423,450,833,310,835,18,905,963,795,772,769,9,181,116,148,990,224,911,774,73,609,191,457,127,158,962,390,508,452,737,337,213,426,903,356,834,777,663,660,268,887,116,691,475,559,130,815,907,478,269,278,92,582,243,611,173,716,817,409,782,65,138,195,905,187,52,985,129,586,19,636,75,906,334,954,71,501,48,172,354,271,421,333,890,770,758,716,820,901,712,499,591,859,704,364,413,356,764,985,857,197,954,935,207,913,32,545,642,268,261,807,10,913,822,781,219,145,48,619,152,898,826,557,169,111,819,898,130,170,516,793,946,685,830,481,346,245,826,360,308,829,914,456,160,990,317,892,183,744,595,63,886,3,664,377,408,173,491,740,372,915,443,605,775,561,426,910,211,226,217,982,330,182,251,494,124,563,313,834,72,504,448,647,520,928,471,671,89,350,609,970,971,237,108,626,790,213,29,730,43,25,136,390,19,321,258,237,172,788,796,213,102,704,649,181,742,233,515,133,886,311,666,958,393,759,7,28,129,555,41,770,861,596,755,812,402,227,144,753,216,921,683,215,150,709,124,979,967,876,665,859,793,385,914,841,171,696,97,69,419,520,542,241,793,230,870,649,758,380,285,796,500,852,595,987,186,888,236,978,377,28,872,922,379,150,482,119,65,736,749,734,182,213,937,91,324,939,966,893,83,346,732,513,914,597,810,487,932,245,5,608,204,965,902,100,401,308,982,685,798,398,565,733,15,584,425,279,324,859,619,469,598,149,141,96,493,553,481,901,858,676,593,510,888,520,10,957,943,560,589,389,590,820,188,828,353,528,359,707,346,316,799,624,166,152,232,240,702,251,473,736,704,566,636,240,402,769,784,567,98,445,286,799,76,532,898,127,461,950,981,134,869,457,586,422,172,637,823,663,788,389,954,289,466,508,879,768,755,848,844,796,9,291,955,68,672,808,733", +"384,395,722,546,427,344,588,749,943,83,62,414,672,56,96,427,832,694,820,552,574,490,412,760,906,729,310,727,650,279,747,182,217,471,915,309,568,489,720,93,837,668,835,172,938,568,731,761,825,461,471,564,134,735,278,71,721,422,765,587,818,504,721,395,509,129,664,137,15,2,452,545,557,911,164,874,908,530,589,443,609,829,526,656,478,490,925,559,92,148,666,380,48,449,256,547,292,677,571,237,339,294,567,480,37,802,717,328,517,184,284,268,90,535,940,236,177,380,944,996,85,906,783,559,983,953,843,466,41,203,845,883,564,298,398,903,619,963,816,35,95,224,384,13,276,987,951,40,732,239,560,77,66,100,6,856,214,384,52,467,486,647,999,366,23,42,679,877,924,116,643,563,16,753,47,366,159,820,713,260,760,655,245,491,58,276,727,433,875,229,222,34,62,624,141,448,489,236,32,374,859,20,847,777,431,491,0,697,160,124,526,624,607,369,103,534,916,332,50,294,895,140,285,186,375,83,646,469,170,505,444,247,587,424,773,267,457,245,653,62,828,795,918,822,585,257,920,552,735,582,84,308,910,150,237,188,714,208,989,646,193,977,902,172,428,536,55,961,597,102,137,299,151,11,399,852,582,839,393,365,789,907,184,528,166,224,940,150,574,257,495,842,896,263,216,871,909,297,660,500,290,459,344,858,643,375,139,370,953,30,924,818,4,947,286,710,271,735,44,895,534,423,372,813,831,452,569,666,148,779,477,382,968,769,256,705,454,653,393,125,612,11,770,674,85,162,829,778,810,830,397,123,478,265,143,190,414,733,950,412,4,536,795,559,150,139,40,631,856,828,623,883,650,196,994,812,859,562,200,344,411,132,793,675,916,230,724,288,560,960,788,498,995,151,981,212,532,590,615,964,667,744,480,607,15,78,367,790,767,902,263,979,917,596,651,600,269,811,520,881,49,766,353,288,783,635,548,434,277,732,418,804,813,327,462,859,961,596,145,944,161,124,237,394,423,692,564,335,56,491,510,650,440,668,117,277,889,167,113,75,505,142,784,635,594,147,461,455,13,960,717,576,966,376,970,825,637,206,730,644,83,350,47,376,71,854,206,948,564,111,361,175,955,870,564,902,725,507,60,728,596,264,128,956,485,317,959,257,801,86,36,409,430,641,812,521,780,714,502,383,191,502,657,338,931,111,208,957,587,749,397,116,693,642,85,278,480,700,666,910,511,578,791,274,568,661,572,870,209,170,265,978,27,816,265,98,386,282,420,80,222,156,14,141,779,497,229,960,184,595,759,957,954,217,450,809,419,205,805,730,550,539,241,318,292,102,169,137,471,435,814,866,740,69,540,732,470,451,43,361,638,142,910,959,744,459,693,446,985,62,477,799,589,768,342,372,64,718,477,392,414,884,186,650,98,155,654,764,258,338,654,370,11,147,750,312,333,268,170,189,840,542,866,413,722,887,406,55,840,149,58,720,150,369,237,208,445,872,81,684,692,338,428,975,430,479,770,416,992,227,414,460,670,840,49,914,963,12,745,99,444,77,858,852,762,845,807,773,248,415,529,528,340,230,760,323,165,943,874,759,503,887,815,501,719,595,553,660,531,577,383,227,723,901,710,150,332,398,62,482,358,165,348,29,73,260,414,218,338,825,691,52,835,707,272,103,173,86,751,983,248,858,76,644,252,264,255,201,488,847,38,335,437,109,138,135,104,917,982,527,386,959,221,90,121,318,446,751,42,255,945,990,179,640,360,99,851,322,371,906,681,128,971,769,14,560,823,370,61,789,208,614,839,540,182,730,61,906,221,217,681,731,582,546,398,99,643,743,707,158,604,863,783,583,248,425,832,549,24,815,107,139,699,478,377,819,759,621,44,564,597,418,794,153,104,247,363,727,438,465,970,273,174,406,599,765,616,546,245,426,24,64,826,231,998,657,666,405,365,579,27,756,649,134,397,108,185,986,234,317,576,698,497,133,555,976,886,277,776,974,966,635,422,33,810,425,453,180,5,217,260,521,758,87,98,391,53,362,4,459,956,941,826,417,269,369,957,903,218,543,620,402,263,231,730,155,569,214,694,864,39,546,521,647,864,496,988,988,727,891,138,112,570,38,231,110,221,844,640,775,460,16,610,628,998,847,89,239,354,907,654,362,951,720,860,508,861,137,737,220,324,465,587,573,380,643,422,854,226,334,916,167,728,613,959,84,721,755,427,339,549,597,580,700,636,13,256,912,365,262,608,771,132,773,224,887,389,253,246,503", +"682,53,553,479,819,263,139,847,273,122,9,601,219,732,452,593,486,15,662,722,903,319,132,113,202,903,341,17,949,521,187,102,751,719,148,719,978,341,551,382,822,337,850,561,416,459,354,690,180,384,53,899,364,333,892,29,677,453,815,183,344,998,880,733,440,636,132,950,544,182,340,536,965,86,320,35,566,595,809,356,251,352,802,518,69,156,280,187,684,732,308,870,907,741,66,501,125,85,473,280,985,143,711,928,995,509,323,606,676,95,562,230,115,472,296,191,960,316,313,783,882,434,189,886,18,826,604,544,624,594,635,595,135,838,747,983,743,437,747,143,518,217,125,93,919,762,837,734,561,363,159,144,535,605,342,538,220,734,475,100,45,727,963,177,363,144,472,915,859,12,360,923,962,663,244,906,461,225,140,630,305,404,730,758,208,558,548,957,555,932,858,687,315,340,431,123,323,290,866,55,161,809,119,614,269,269,697,0,328,415,304,305,870,745,836,77,393,364,899,890,90,613,634,242,925,41,604,462,461,811,948,373,330,225,343,105,441,941,308,791,285,576,481,636,219,142,120,322,289,221,867,913,386,838,529,6,887,676,736,76,653,282,298,110,445,12,244,521,59,153,225,470,599,245,186,776,627,901,989,551,870,523,421,950,554,469,155,557,219,543,832,798,106,873,105,734,553,280,445,598,938,948,353,174,582,69,58,620,140,153,456,824,95,756,233,101,431,695,82,599,255,132,100,623,840,245,825,604,497,388,733,354,800,185,718,250,752,229,826,414,512,205,222,66,556,250,420,684,455,802,809,555,111,416,902,408,596,996,363,967,779,736,688,275,582,934,990,480,539,676,894,859,963,293,25,407,682,669,545,378,650,957,233,597,856,444,400,322,274,968,325,584,166,396,169,411,137,669,15,286,308,645,833,59,899,623,456,527,897,215,954,635,516,540,19,616,956,269,812,764,183,971,607,803,347,272,306,530,881,754,231,826,473,627,100,339,509,16,686,714,138,605,86,186,288,357,292,24,882,104,979,345,97,418,533,577,771,959,44,733,458,834,483,786,492,885,194,512,302,221,359,34,396,957,336,314,582,714,57,565,27,865,584,699,933,410,356,403,21,500,763,56,97,656,99,843,943,921,22,742,575,938,859,494,113,26,130,367,585,954,362,78,594,921,426,166,609,433,287,812,563,643,301,585,102,345,707,320,457,981,998,303,478,761,682,327,562,846,624,487,95,872,740,523,402,745,388,189,720,52,801,813,830,718,234,940,416,349,957,496,283,636,319,491,575,992,696,437,8,100,235,907,109,89,630,562,787,514,601,920,651,51,801,709,768,521,968,480,278,844,379,618,217,298,592,522,863,562,485,992,792,778,152,884,939,821,213,834,785,8,601,395,550,849,735,861,257,512,825,23,118,660,727,600,242,937,735,117,1000,536,801,521,22,634,873,47,708,602,910,955,190,788,364,738,261,386,834,184,89,675,617,438,10,809,684,892,688,801,572,2,105,164,553,782,72,431,841,924,668,855,588,621,610,370,55,448,558,891,138,63,352,585,530,305,368,570,883,41,7,690,555,70,171,151,510,79,889,529,945,740,206,617,121,337,365,722,271,175,312,848,82,192,559,942,979,513,478,423,712,117,272,780,250,272,968,163,950,186,39,466,988,80,37,147,662,250,4,769,799,55,312,358,599,768,815,651,127,104,760,728,286,843,374,328,981,938,244,576,267,222,265,895,318,125,872,373,534,630,531,503,723,254,953,613,376,687,697,565,49,813,146,463,52,189,912,152,288,180,785,296,232,387,789,781,766,926,128,887,487,791,272,172,713,442,572,849,800,60,51,991,271,628,222,701,234,11,348,372,644,112,267,291,742,623,606,452,50,444,191,757,376,862,457,494,748,546,22,200,638,427,943,872,125,296,355,517,950,304,274,816,335,156,577,435,96,668,302,108,879,498,365,336,39,670,736,363,108,845,643,50,718,633,179,205,989,631,20,917,237,812,133,294,220,527,84,234,812,185,226,191,968,387,115,20,933,741,808,518,226,686,969,666,967,129,732,404,499,506,210,324,280,155,332,766,184,593,610,267,934,163,357,534,928,445,324,986,639,329,480,883,320,292,891,500,174,722,42,297,348,133,365,89,229,539,903,263,315,631,992,75,80,807,784,524,177,708,176,677,426,299,732,960,815,33,540,186,859,340,834,361,719,500,773,304,955,569,680,778,837,924,436,794,875,889,413,919,849,339,771,118,816,746,139,339,54,859,557,428,877,356", +"558,976,402,222,981,451,152,63,255,85,606,618,199,322,398,256,206,137,780,389,146,836,35,141,830,445,21,424,271,318,811,544,90,153,367,195,626,153,635,778,877,33,824,908,351,392,987,462,751,678,603,496,993,82,932,398,93,327,516,730,916,682,906,139,69,289,853,314,44,425,996,963,977,309,233,434,262,950,614,852,628,903,404,792,276,777,424,458,738,38,622,756,32,890,563,696,92,736,56,247,673,53,913,209,445,856,892,402,510,96,686,54,337,345,836,635,604,845,380,226,521,625,27,348,246,7,737,242,536,96,62,816,849,507,816,91,857,728,41,568,669,871,914,448,915,704,243,394,81,354,33,864,867,838,32,43,278,226,599,665,262,22,28,698,738,58,767,781,528,677,867,428,82,332,459,537,856,192,22,585,764,116,369,67,549,294,233,305,514,949,36,757,213,352,496,908,986,447,979,176,219,860,938,564,511,650,160,328,0,381,665,153,486,30,330,560,124,216,809,86,593,867,596,948,589,167,40,906,51,134,600,78,404,570,597,577,750,782,488,145,69,925,271,581,344,884,817,765,988,285,928,129,310,777,337,889,116,786,831,708,111,75,523,305,778,468,334,437,392,214,830,772,837,829,160,881,188,118,472,914,816,336,404,311,56,194,615,84,747,897,823,15,92,431,218,999,103,135,266,249,97,922,121,647,548,277,381,565,181,646,843,906,475,709,251,940,797,941,330,246,970,822,806,75,352,173,549,142,60,292,110,376,532,11,351,956,53,377,871,815,464,548,243,502,751,462,675,372,659,877,723,298,842,669,710,635,905,253,279,162,644,38,911,108,629,69,83,701,269,811,102,130,183,302,574,884,259,320,537,621,283,716,583,594,531,298,118,55,288,382,293,550,570,31,950,28,337,776,566,855,611,763,533,606,328,642,994,831,631,688,597,35,492,553,572,250,363,786,62,290,339,93,66,617,962,507,559,907,789,702,361,570,73,357,488,248,5,150,973,354,301,925,429,971,533,175,401,641,736,247,348,461,299,42,777,147,947,705,78,361,749,668,528,873,258,732,933,975,932,446,466,165,693,279,471,265,682,941,158,61,403,530,419,883,270,42,334,51,230,150,505,447,59,682,340,895,686,234,833,40,253,890,554,866,585,950,745,232,398,520,607,309,977,772,577,870,594,946,528,164,919,381,732,983,343,249,975,666,65,336,590,516,569,58,703,257,371,619,875,978,156,963,305,724,807,595,359,250,150,638,510,732,441,63,54,94,643,376,593,36,254,773,329,794,294,350,206,172,646,867,698,368,64,871,536,837,542,2,617,403,32,851,935,407,804,650,917,4,840,311,794,937,644,719,850,589,305,993,100,624,260,317,493,552,814,787,645,225,354,625,88,775,682,718,421,894,332,478,103,330,839,849,365,702,502,617,601,815,802,895,479,539,300,435,293,235,174,18,796,23,718,349,240,759,211,248,421,47,959,250,879,759,792,479,424,796,71,219,21,692,851,245,447,174,408,516,734,75,581,776,647,503,691,619,506,236,804,790,807,841,159,903,988,803,536,508,734,12,75,554,52,313,530,220,88,818,205,246,835,858,541,979,228,572,885,83,642,104,568,890,800,815,202,317,244,44,638,683,529,493,123,173,150,73,592,137,324,685,201,131,468,862,610,220,330,647,826,200,131,552,776,582,560,420,731,843,446,668,175,571,248,372,613,327,564,55,851,450,479,75,436,673,48,299,283,384,576,267,880,883,220,883,166,460,846,753,143,227,183,759,247,706,140,183,611,80,150,180,312,616,583,465,238,970,385,497,534,409,454,270,775,693,180,453,81,232,822,611,309,519,865,409,657,786,508,860,373,554,949,795,509,285,257,80,828,104,418,211,655,992,328,606,761,40,698,400,47,978,355,424,711,898,224,254,88,162,18,326,433,682,739,310,613,348,204,214,731,311,870,195,193,499,173,713,342,105,149,298,406,918,107,961,348,413,139,542,191,276,251,899,168,538,78,767,444,328,430,483,241,379,640,621,518,670,797,607,764,450,648,794,20,871,209,327,585,381,36,324,650,405,963,163,403,192,240,927,590,970,999,197,293,317,695,626,383,194,57,366,437,503,257,791,183,920,457,347,470,938,346,962,587,252,992,515,85,261,671,763,822,17,691,350,309,385,537,295,69,792,958,628,569,906,815,512,535,933,730,922,37,14,628,285,931,391,908,805,712,559,172,837,389,949,307,674,581,285,663,620,567,118,638,935,318,591,340,979,768,529,448,159", +"298,778,768,881,661,602,417,667,287,655,582,473,360,616,354,150,10,457,29,252,461,328,773,72,862,113,852,79,211,697,185,857,609,411,862,828,526,435,356,406,873,842,852,721,239,282,857,476,665,319,737,23,859,101,116,614,878,941,521,856,724,297,771,599,131,395,426,872,854,252,129,450,754,268,899,328,55,744,325,78,387,851,573,998,284,885,465,953,589,300,48,969,542,368,647,299,981,27,620,572,378,162,370,470,582,965,670,830,250,513,145,823,165,78,973,419,837,649,445,169,603,858,771,159,553,391,489,256,359,776,25,396,899,57,679,699,364,340,926,912,43,173,148,935,389,850,988,635,31,51,850,17,891,175,728,603,108,192,956,656,548,408,564,573,953,531,629,290,341,847,305,441,59,306,626,783,107,944,683,563,578,486,414,527,372,991,730,832,747,914,48,223,63,853,976,81,529,569,815,315,401,287,339,616,253,228,124,415,381,0,267,529,681,825,418,357,754,208,528,678,465,272,232,203,462,43,797,320,436,575,355,414,736,249,849,669,633,858,799,876,771,203,394,630,911,376,557,253,357,733,913,381,59,371,217,565,820,565,515,526,885,383,944,214,861,99,555,466,604,677,588,891,67,380,811,190,9,179,396,670,324,319,575,37,300,498,21,688,539,119,993,448,358,495,101,530,743,775,184,903,394,732,510,11,530,352,737,404,805,153,404,845,341,357,599,922,4,289,51,734,628,38,465,613,522,825,555,499,538,512,440,378,516,143,507,947,815,522,488,949,881,985,763,297,748,581,330,471,374,493,596,851,218,649,711,180,22,754,933,518,475,694,431,848,507,213,415,5,100,48,579,23,532,273,980,200,106,234,511,4,276,889,263,748,281,192,152,203,848,791,142,848,147,411,896,86,108,309,553,916,946,663,744,574,812,670,964,71,293,247,524,553,860,453,666,197,553,658,173,666,397,452,887,777,195,82,216,44,331,746,355,388,469,104,413,834,570,805,870,769,510,924,477,989,628,459,387,36,158,574,450,900,466,264,329,96,238,330,617,371,925,204,231,581,535,952,745,260,170,113,685,744,804,154,980,389,834,958,334,965,29,118,864,687,26,398,626,939,100,109,463,542,512,576,966,248,324,381,675,732,33,99,301,636,129,13,863,969,387,499,293,638,883,360,969,760,699,117,430,937,210,542,169,654,796,505,849,474,549,610,827,377,264,586,225,337,172,261,695,989,832,143,940,117,583,151,220,445,863,222,11,815,364,242,408,849,933,55,327,399,802,121,855,65,713,633,423,259,510,289,64,431,400,96,781,866,563,75,179,936,485,453,288,641,201,680,352,20,543,418,826,80,366,303,641,889,31,803,688,176,186,565,448,566,725,833,452,979,802,244,427,447,236,943,511,826,742,132,749,48,517,105,917,29,403,900,505,222,815,593,88,405,887,903,869,89,282,719,926,515,350,442,971,455,207,629,336,101,903,912,671,829,502,739,602,486,834,981,31,111,366,657,644,216,124,410,800,219,508,677,328,363,371,903,576,206,95,73,647,335,386,225,216,19,178,594,612,179,559,803,362,183,784,903,319,841,59,87,931,990,691,697,638,973,646,773,184,772,438,316,935,403,292,785,259,204,85,137,300,410,29,735,912,637,443,850,202,410,612,371,86,691,277,832,353,899,990,669,503,6,216,693,18,77,974,94,954,991,844,675,387,966,627,654,262,5,734,420,462,823,552,75,213,369,628,100,185,237,165,680,212,62,903,71,346,101,693,512,488,385,663,392,431,846,443,954,725,574,452,915,464,232,409,216,303,534,260,317,15,5,192,425,225,509,976,545,507,887,506,681,57,14,215,848,434,419,844,993,824,918,649,940,938,165,566,223,451,632,403,888,725,812,726,706,887,897,551,485,155,910,172,704,222,667,862,104,996,59,379,609,714,703,255,565,714,492,8,581,666,696,320,163,201,513,457,644,366,874,473,236,990,899,626,811,116,196,189,633,278,761,866,706,829,525,249,324,394,435,572,197,447,542,53,848,156,260,405,340,954,812,238,478,200,55,111,582,295,219,594,156,597,952,710,19,820,473,934,751,4,852,477,170,550,214,146,298,251,837,98,524,41,916,249,572,630,34,409,497,553,153,236,790,582,278,763,372,464,596,555,505,140,896,57,112,192,233,457,738,372,513,743,178,806,799,821,697,678,250,500,692,351,767,846,378,507,502,206,219,819,290,458,444,658,25,256,235,907,545,820,617,980,9,221,674,388,699,884,987,576,802", +"726,842,262,247,158,48,852,580,147,328,451,248,362,476,191,117,776,66,348,153,369,843,880,774,140,486,941,377,593,625,985,634,888,955,658,762,935,877,768,231,748,437,53,865,510,952,485,982,81,658,598,609,922,683,617,767,991,864,779,18,356,339,682,424,297,362,633,955,58,598,564,830,371,559,277,161,915,298,94,278,629,778,42,803,886,438,314,19,766,76,3,679,175,324,593,341,481,391,585,156,311,838,210,366,856,786,916,518,728,580,677,481,954,581,633,222,677,272,916,905,630,71,12,836,966,331,96,709,244,100,853,176,191,736,222,796,701,827,509,94,232,176,176,339,202,582,346,624,741,895,283,891,615,722,56,866,581,440,798,943,878,112,900,825,772,642,163,891,237,220,348,817,757,912,612,386,759,229,280,679,593,953,810,464,840,311,840,598,465,910,484,574,665,222,933,799,498,755,416,436,377,431,315,341,246,111,526,304,665,267,0,621,692,913,633,514,557,54,267,517,710,544,951,101,432,401,24,108,202,84,452,819,134,588,751,922,159,7,411,796,554,619,171,181,56,540,354,277,737,745,79,873,257,4,175,697,326,266,79,40,970,112,516,208,476,817,793,991,166,71,885,79,264,926,771,635,235,566,975,98,636,447,570,148,165,301,389,73,801,165,541,581,148,545,252,220,236,740,456,656,56,474,797,556,28,895,591,12,379,361,5,166,361,495,640,745,248,140,643,215,544,22,884,959,534,608,459,250,359,440,914,697,604,973,735,73,360,43,290,204,252,686,689,488,314,368,184,175,846,771,869,232,877,134,404,510,447,953,494,859,868,962,800,832,894,790,913,440,46,443,954,879,777,833,526,517,34,150,372,861,618,725,385,257,659,640,149,524,799,101,448,859,927,304,642,256,368,446,967,885,409,516,416,745,82,368,155,202,212,155,415,487,169,668,271,172,448,619,462,827,140,922,789,471,605,220,76,38,712,437,994,367,49,334,691,194,160,694,336,951,334,262,688,109,817,909,879,122,485,128,509,984,141,714,270,394,378,187,14,314,913,177,564,666,492,92,886,720,866,67,635,532,109,590,587,708,203,595,575,405,540,386,198,427,4,459,552,824,892,588,550,146,228,91,965,560,451,825,286,623,870,903,317,739,506,669,365,740,939,883,261,514,720,417,384,143,378,876,588,783,303,65,52,644,250,341,76,92,613,346,398,197,998,274,529,83,776,922,573,428,312,196,639,443,283,446,678,258,197,409,870,349,93,762,362,208,60,400,242,159,642,774,363,366,859,498,595,678,101,278,216,990,281,363,36,339,938,213,636,377,403,749,462,928,219,215,561,711,886,270,806,275,541,904,747,749,967,39,635,333,693,85,566,14,912,712,631,536,383,749,922,190,337,979,576,673,833,483,745,248,962,209,184,563,82,268,455,291,608,300,591,699,722,539,213,735,578,707,412,94,230,564,825,338,271,396,752,850,546,90,794,945,884,386,923,903,653,186,967,498,630,668,679,387,232,712,541,288,680,666,349,95,89,52,830,504,403,670,829,771,97,147,902,353,312,417,703,21,669,41,665,454,216,300,297,335,442,709,383,947,61,605,644,991,870,12,310,312,622,303,18,433,818,244,439,796,674,424,90,206,469,315,78,147,84,373,831,471,725,919,641,545,467,320,452,123,638,753,267,41,144,254,861,789,831,559,643,552,375,192,85,54,76,642,261,390,762,52,240,596,202,329,170,428,534,656,363,527,45,524,485,966,747,588,495,225,436,925,336,638,183,762,965,993,116,981,784,933,88,117,5,232,999,249,752,942,542,287,760,115,757,485,229,329,14,416,646,745,580,793,410,458,613,562,196,788,648,813,378,812,481,563,269,163,823,201,993,241,695,410,887,258,213,184,473,747,216,972,24,62,104,701,320,645,414,765,165,672,203,909,100,222,687,841,742,21,629,397,249,774,489,251,19,329,878,313,384,565,987,547,143,872,590,206,840,248,653,717,422,161,890,681,453,612,326,278,531,409,492,541,355,731,891,258,894,679,816,772,340,329,335,3,113,822,152,60,204,873,983,473,513,959,731,324,703,383,40,214,286,495,987,87,247,636,97,40,432,391,387,648,332,707,775,799,474,598,464,105,344,499,754,273,847,75,598,903,995,929,251,20,308,855,20,407,378,126,839,913,923,814,643,251,169,778,163,507,934,759,833,637,762,912,30,566,60,723,908,126,477,750,87,997,831,400,939,685,930,201,593,525,904,451,844,209,477,109,623,334,190,964", +"899,967,257,954,123,408,326,959,195,177,450,789,368,823,385,205,648,239,175,299,23,948,962,525,681,578,864,13,522,710,302,983,437,886,824,327,662,349,298,761,556,319,4,87,4,85,475,979,165,566,729,724,713,697,739,681,235,641,843,149,520,487,864,986,569,485,258,958,147,750,342,655,499,564,580,742,556,564,265,480,695,998,935,851,635,136,678,581,680,647,77,460,391,901,835,526,499,62,971,32,316,967,913,342,476,13,20,635,932,234,17,237,185,681,271,522,793,597,222,366,860,363,528,802,612,221,674,220,440,405,997,935,776,546,116,462,733,165,938,302,58,36,274,795,390,316,370,888,143,607,464,63,701,680,649,854,182,26,628,475,244,52,279,59,686,127,564,237,530,261,239,474,586,768,551,530,326,126,140,614,852,306,334,700,188,642,157,94,73,362,940,264,426,488,700,183,985,869,87,579,569,921,893,976,956,175,624,305,153,529,621,0,449,747,788,697,323,184,343,925,539,620,353,267,137,628,925,487,627,725,414,218,303,894,332,460,319,461,212,448,674,678,50,446,479,731,548,556,572,768,136,878,15,601,105,515,544,751,196,371,434,852,650,792,764,648,31,443,242,796,634,439,202,297,539,685,851,107,766,193,198,134,950,920,321,293,84,394,197,221,513,751,942,234,459,614,64,190,450,828,683,709,219,292,920,557,597,271,330,838,432,808,131,152,647,354,297,421,657,984,169,396,355,293,827,185,900,322,779,666,496,141,778,75,887,799,781,912,173,932,355,340,792,66,793,609,24,93,626,441,301,98,282,767,768,972,909,493,192,743,405,258,203,949,420,330,204,698,367,769,351,437,624,68,709,597,274,873,778,726,944,815,138,975,350,474,158,166,345,588,497,359,42,916,350,302,870,626,914,476,739,630,278,232,676,273,193,173,372,705,489,799,911,234,411,144,892,570,177,845,115,340,219,624,543,334,721,688,580,547,516,270,422,875,71,163,974,168,622,649,55,389,1000,519,254,433,50,969,132,834,633,55,18,499,820,512,167,371,617,336,596,249,957,362,277,596,814,402,993,123,287,298,216,782,665,815,797,500,644,188,724,879,359,305,482,216,448,223,543,158,51,413,150,397,954,820,377,190,537,285,792,848,904,98,44,595,932,839,462,699,807,827,280,539,342,761,449,746,479,582,951,723,621,419,320,3,753,650,232,160,546,332,900,197,801,861,32,592,647,650,757,205,866,152,592,570,611,968,750,572,217,533,960,307,258,879,340,548,464,872,372,29,620,374,912,339,554,357,973,632,813,207,830,551,625,820,354,753,163,285,369,539,451,163,224,65,927,888,118,880,222,966,691,651,621,606,932,575,500,603,920,445,136,51,924,635,927,152,371,860,690,444,763,780,18,192,272,680,353,6,703,485,416,42,219,532,52,387,950,149,362,918,5,814,654,610,741,844,480,21,742,89,641,53,767,61,288,367,366,946,621,443,647,973,650,653,986,722,703,310,216,531,905,439,164,193,236,999,718,124,551,122,730,221,265,342,512,868,377,48,950,517,958,834,957,945,162,823,579,713,404,181,717,129,998,908,342,182,978,546,556,774,149,974,287,327,860,65,908,769,293,515,919,717,467,795,906,326,416,568,887,901,367,278,192,337,805,419,824,312,555,939,648,28,364,553,499,862,264,795,991,278,660,788,24,75,829,860,901,27,346,284,544,579,247,183,208,554,51,329,602,819,667,856,13,404,918,378,837,632,741,751,574,919,330,748,666,800,343,809,642,181,724,927,813,99,732,661,662,379,167,81,224,460,88,856,519,679,422,364,95,140,9,878,389,439,176,635,381,184,381,751,573,493,338,661,527,444,227,765,850,818,976,976,796,912,686,890,297,79,767,666,331,570,262,3,860,949,554,526,232,1000,520,801,972,722,174,386,563,484,141,435,494,970,28,407,414,679,82,105,109,760,340,585,976,86,583,405,329,185,694,352,366,271,19,887,373,382,375,783,659,566,924,178,268,615,382,845,194,254,778,42,95,238,781,950,436,935,447,681,759,378,681,168,762,600,670,696,180,562,135,904,800,581,979,97,47,492,436,267,318,431,767,500,136,962,924,663,896,501,626,880,187,446,326,525,116,894,610,907,513,901,891,119,17,410,826,134,18,569,712,389,207,759,281,890,462,129,594,670,748,217,764,346,99,935,52,149,284,146,944,536,197,232,781,178,517,685,924,261,988,875,307,730,93,326,668,102,374,810,692,517,256,733,339,845,203,807,267,185", +"444,875,941,128,21,122,445,648,163,197,475,754,711,651,742,323,169,552,724,914,535,441,339,400,790,287,447,374,37,937,70,967,440,476,364,783,790,573,564,30,314,535,701,193,298,994,966,752,100,896,135,675,939,2,98,338,664,673,640,361,863,53,136,358,198,934,933,463,945,172,68,934,40,346,535,355,742,397,500,409,118,454,45,423,171,852,785,264,422,758,479,999,37,458,840,40,705,557,354,459,929,837,32,723,82,195,148,792,753,482,910,804,489,586,787,689,8,622,918,768,381,615,681,626,237,908,940,676,893,397,710,993,805,787,297,55,954,368,412,599,101,571,444,967,234,195,128,966,266,891,865,944,267,206,60,314,424,334,500,675,978,417,199,701,763,813,729,538,106,373,527,838,11,979,655,169,117,46,723,757,54,301,418,994,912,395,195,626,744,225,654,537,119,680,510,792,216,996,982,87,233,941,101,426,560,380,607,870,486,681,692,449,0,205,914,184,337,391,685,429,467,846,649,720,85,802,878,665,20,260,718,970,205,307,32,75,597,127,844,996,305,366,976,706,65,82,903,462,341,779,582,496,201,105,58,733,66,856,575,365,917,187,6,839,448,770,340,954,26,483,382,963,207,5,32,707,815,112,581,216,63,480,571,894,293,353,90,54,435,667,981,680,44,835,954,710,818,729,378,537,495,354,75,237,833,473,685,779,468,59,880,584,369,413,695,644,327,608,121,212,986,471,361,90,219,223,382,928,452,16,411,359,780,897,962,694,735,696,187,351,889,970,341,932,170,527,160,649,972,186,965,31,918,243,393,590,597,480,585,921,615,5,649,915,825,888,789,621,189,281,427,780,573,731,438,592,589,405,584,882,118,277,812,970,626,440,587,756,775,135,273,922,966,410,286,351,291,869,934,363,16,310,990,576,455,511,862,708,49,551,629,409,471,727,502,252,155,104,510,906,155,376,916,135,677,708,300,937,481,330,606,844,88,993,862,148,422,978,755,527,248,784,451,730,209,700,146,287,717,493,432,500,371,160,742,95,207,49,755,155,831,651,347,655,164,862,857,946,186,395,164,220,183,332,266,203,21,70,360,303,57,369,465,653,191,439,89,644,541,361,299,592,927,6,175,222,814,198,400,508,59,978,187,55,595,80,569,116,375,280,352,283,928,679,824,664,348,724,31,850,8,904,246,620,408,127,531,671,465,196,234,455,546,105,817,265,773,586,673,882,624,190,885,559,57,901,758,760,131,741,305,410,659,584,452,695,445,568,282,376,717,954,622,650,989,610,234,635,17,314,107,770,758,911,395,179,389,548,827,400,223,928,997,894,932,247,755,916,236,610,765,209,355,119,286,747,7,413,414,924,377,979,618,178,852,798,89,587,970,641,340,518,947,598,172,941,157,734,19,260,999,899,559,778,299,902,487,869,487,622,462,467,464,493,410,539,924,369,21,974,619,237,17,706,436,149,110,583,389,402,438,922,626,475,780,717,251,520,462,708,549,509,280,849,883,376,712,598,859,878,332,73,387,798,40,563,622,471,869,192,870,430,907,394,531,604,62,832,9,967,930,698,866,290,968,631,79,983,315,25,73,716,958,400,289,407,236,916,511,647,165,186,727,264,26,557,310,143,292,165,608,458,209,823,97,39,523,645,362,406,394,436,852,270,266,942,590,255,417,82,419,349,3,7,728,826,598,275,754,684,758,456,498,579,200,381,147,919,822,478,967,142,632,878,697,599,543,858,105,626,886,327,677,590,989,879,16,403,852,547,738,568,813,124,9,28,618,560,837,279,71,379,600,956,302,68,366,470,944,314,267,216,880,501,824,43,651,69,273,646,336,377,244,825,321,777,712,722,128,340,229,218,884,309,392,45,595,311,595,862,58,729,808,924,384,732,614,942,770,972,835,955,171,517,243,553,269,34,781,517,631,427,66,857,264,83,855,666,749,494,324,613,296,651,303,672,834,367,831,812,932,293,502,180,387,968,25,283,170,861,307,463,912,701,951,648,294,110,141,827,304,275,180,784,65,168,827,224,572,716,74,612,931,977,658,648,53,734,654,303,453,718,788,311,596,944,828,66,228,319,861,126,282,569,111,352,311,258,682,739,647,136,834,816,925,307,615,299,318,134,786,936,103,800,443,475,235,178,319,299,623,11,898,883,988,173,660,160,580,640,543,414,71,877,811,962,916,289,229,853,315,62,951,160,292,626,633,321,888,140,472,532,309,615,555,149,479,140,954,339,619,492,122,717,645,189,627,543,691,200", +"420,668,118,478,946,297,917,234,166,911,717,567,736,177,801,794,636,777,245,703,362,685,54,15,155,474,417,75,229,959,765,53,994,712,235,926,843,388,212,582,713,264,166,946,242,832,706,821,602,539,990,602,786,696,581,731,927,726,515,11,77,107,648,308,601,96,225,467,50,856,628,155,500,411,365,911,919,72,591,666,685,588,80,121,672,277,28,983,137,713,881,133,267,345,598,213,961,465,289,647,981,33,811,655,111,166,556,433,225,395,917,423,526,923,776,1,252,449,509,460,2,437,115,146,105,230,979,416,562,861,73,138,715,330,538,838,543,169,17,270,582,942,718,127,653,938,938,967,799,325,364,293,478,873,833,713,890,375,787,320,828,956,587,453,776,162,977,854,495,912,508,927,842,444,357,910,339,210,331,545,934,286,189,865,729,662,447,303,364,837,759,501,470,131,358,697,566,202,435,745,315,842,117,969,974,157,369,745,30,825,913,747,205,0,862,60,571,602,313,681,645,13,422,357,842,336,644,807,985,273,663,954,56,970,320,934,290,921,214,668,88,659,748,559,657,209,505,292,731,717,659,991,644,660,14,295,118,534,528,987,846,698,611,725,848,554,935,550,170,624,185,30,674,941,183,751,906,406,861,878,914,646,760,887,265,611,843,405,499,766,724,597,253,748,290,335,24,341,620,246,495,383,893,26,929,439,524,486,366,716,895,723,162,608,605,688,525,728,228,865,540,19,377,701,77,746,343,142,931,683,876,419,77,27,81,245,873,796,609,297,766,860,257,924,137,448,495,50,262,448,94,280,556,976,526,896,937,472,945,360,450,129,584,201,775,428,241,891,560,133,549,661,781,701,104,888,813,288,701,215,191,378,756,69,570,231,123,596,61,119,906,378,527,375,159,499,925,47,367,411,438,893,158,815,496,337,916,132,661,631,491,105,338,966,576,847,642,687,434,503,115,709,653,931,537,289,238,562,603,950,545,716,222,893,214,852,945,402,659,904,187,141,261,349,555,67,594,905,268,478,864,833,123,785,142,500,986,184,868,377,987,503,476,17,737,426,775,677,146,283,990,984,183,784,534,382,857,653,378,466,567,797,219,159,92,425,67,292,80,951,638,776,114,296,184,615,607,35,975,101,677,40,161,69,212,101,86,676,704,584,137,326,740,830,208,784,293,408,86,923,938,58,403,929,900,944,419,177,101,337,867,480,877,941,375,948,708,100,368,812,730,341,958,936,158,307,19,689,960,767,317,553,923,38,684,556,33,902,682,359,596,870,906,352,595,893,511,74,664,606,810,942,792,143,217,613,493,588,893,623,141,130,25,626,494,889,645,511,929,504,939,921,876,282,700,480,394,595,913,48,476,233,623,619,10,122,458,997,429,436,905,19,997,320,395,680,214,244,124,343,364,463,729,752,631,364,47,942,869,692,466,719,6,31,750,459,174,775,834,893,880,114,4,978,646,300,129,470,285,223,476,89,553,113,517,601,769,933,201,544,61,456,889,907,714,63,526,739,244,76,246,297,828,382,190,658,164,886,544,610,365,697,598,70,542,712,672,127,262,326,102,467,227,789,499,77,504,879,267,542,965,337,901,135,68,975,44,744,70,857,774,840,882,280,862,262,342,124,53,546,919,790,593,398,598,165,459,546,162,853,872,137,103,174,637,779,27,481,719,827,668,394,188,595,617,681,568,164,887,243,577,372,977,624,587,895,396,737,91,25,510,689,939,443,818,144,661,372,474,745,291,115,30,667,66,832,677,267,636,541,422,106,152,866,544,32,452,637,233,724,283,744,457,166,345,113,243,253,256,197,103,703,172,733,607,480,995,758,262,524,372,442,395,902,421,69,289,448,456,262,789,731,547,755,573,623,898,970,855,1,276,454,786,565,264,304,172,199,733,856,795,410,936,717,410,271,704,245,627,345,256,540,753,157,461,293,424,586,266,16,628,960,952,650,859,310,131,347,841,909,316,185,993,893,15,507,129,34,980,810,527,977,140,148,886,688,981,611,431,234,203,220,716,228,497,794,264,205,490,437,135,856,270,671,839,491,155,977,408,538,264,602,330,84,542,718,275,191,993,753,55,142,133,240,720,105,437,645,834,268,697,740,109,602,240,640,981,470,807,770,215,258,439,611,610,846,400,244,618,696,533,556,944,606,767,633,263,164,142,253,836,368,491,317,530,584,703,787,628,704,298,367,211,511,684,780,972,640,978,323,292,554,604,871,933,7,354,35,489,886,746,455,204,691,242,659,963,657,153,690", +"481,980,51,249,140,161,924,62,594,890,851,381,232,177,431,59,65,226,246,564,18,479,810,344,263,338,410,873,765,58,261,108,817,687,446,230,547,530,122,168,762,930,777,977,1,846,21,358,429,551,208,97,952,486,17,309,396,928,157,718,633,629,674,593,680,135,101,306,990,478,453,727,182,7,767,814,438,448,368,317,117,650,884,24,783,732,586,984,277,977,779,234,965,462,167,268,177,516,512,700,2,855,756,838,837,245,535,497,603,825,258,929,15,943,195,499,169,758,320,531,233,461,726,650,639,515,913,905,857,480,114,880,19,438,689,118,802,539,907,256,534,576,597,184,994,170,959,203,953,113,734,412,218,979,429,345,194,104,856,295,301,825,829,173,800,690,33,688,358,931,548,401,119,446,329,178,968,895,799,128,642,948,194,935,160,210,412,81,458,567,220,208,781,191,512,500,743,385,714,476,459,689,107,700,635,12,103,836,330,418,633,788,914,862,0,205,734,427,730,989,314,513,586,962,837,65,55,101,374,463,355,370,303,598,771,990,794,835,293,624,968,242,692,791,698,660,38,823,681,372,916,831,808,292,413,70,485,297,949,584,585,791,265,765,985,683,808,472,980,521,490,143,739,412,256,606,848,360,903,926,617,737,299,667,116,219,747,963,365,815,458,697,981,534,502,55,350,76,166,10,774,279,722,602,426,32,131,108,771,539,125,817,484,355,182,888,415,769,196,890,7,617,775,328,863,714,718,713,654,799,481,539,304,163,406,125,859,30,196,579,998,914,63,178,312,533,331,519,350,158,31,461,900,643,828,183,455,460,603,164,110,12,831,75,972,516,12,78,661,503,738,885,472,170,255,59,596,614,651,906,223,844,990,376,884,565,854,726,377,885,856,845,323,854,840,173,210,355,570,984,707,467,851,708,47,78,577,437,207,295,432,868,346,645,204,822,326,407,787,480,809,745,634,357,158,281,428,672,427,410,309,196,849,633,911,828,81,885,650,950,890,830,575,848,736,391,878,854,354,57,465,615,475,864,742,824,974,696,403,412,81,497,598,836,431,333,625,821,29,25,412,586,319,519,970,557,935,944,763,701,708,762,175,32,45,609,946,727,136,968,717,998,890,93,900,69,185,786,945,293,762,176,772,848,42,764,688,403,9,540,85,623,95,937,333,590,604,521,158,178,127,126,907,379,384,737,190,541,482,391,920,217,37,752,412,326,745,724,248,430,435,634,657,629,511,313,880,365,449,784,221,780,821,29,106,21,327,936,500,971,954,377,997,147,333,948,963,541,4,40,177,791,225,953,170,836,578,954,545,728,557,676,780,15,413,572,868,157,448,236,421,698,722,138,388,523,648,691,365,526,511,843,933,197,871,730,228,628,262,667,282,557,453,646,513,761,406,948,321,859,922,894,817,909,930,462,635,741,821,873,594,58,909,845,450,17,582,27,87,826,190,953,499,933,525,724,80,559,468,601,131,476,642,843,680,968,16,821,452,750,821,300,734,283,706,106,107,698,358,203,548,269,823,260,43,395,2,884,756,925,743,99,120,142,667,111,622,915,655,144,239,737,834,145,585,548,496,583,780,999,831,561,216,540,208,964,325,720,859,968,118,88,26,644,905,11,834,445,274,709,676,256,459,404,532,620,590,192,727,272,355,220,381,629,931,540,419,206,597,559,764,569,16,118,262,905,680,86,578,17,730,348,570,395,112,450,728,703,718,86,341,642,692,526,422,95,402,206,291,143,205,843,68,147,601,297,324,572,161,786,119,659,252,82,553,129,548,38,593,174,690,294,240,484,253,479,606,930,526,71,917,883,710,654,274,9,22,987,488,264,612,910,800,922,299,151,544,817,831,199,371,140,875,558,309,174,182,897,685,863,678,855,676,417,9,696,458,413,296,167,145,49,880,635,400,839,948,634,667,276,264,163,326,193,172,103,635,690,432,434,716,301,891,256,576,208,914,943,476,627,404,212,712,502,924,757,780,94,343,284,350,813,360,275,535,999,522,906,635,179,700,366,739,583,770,179,228,776,692,432,484,116,277,853,585,416,481,758,867,951,40,611,383,929,412,643,38,599,409,877,436,222,222,269,905,141,944,105,141,60,678,220,293,33,926,690,875,643,986,116,395,306,828,541,62,57,155,714,643,198,264,589,724,111,798,101,770,183,403,730,650,71,928,600,255,395,893,910,524,679,728,65,861,522,637,59,718,693,557,139,175,440,317,445,598,9,20,779,107,482,586,753,60,154,221,72,188,413,592,456", +"714,367,170,511,526,685,798,275,671,562,373,793,33,963,971,600,532,687,913,48,398,100,852,845,22,133,152,358,675,686,838,983,971,240,384,220,708,125,442,732,27,119,119,32,602,627,841,712,488,545,624,251,392,578,81,755,998,910,43,303,446,562,27,969,191,393,686,686,969,590,995,393,135,81,456,7,210,81,857,779,11,818,798,387,396,106,607,349,192,984,409,169,918,919,546,538,892,833,12,987,438,650,141,594,890,646,484,124,133,545,275,729,902,1,229,998,411,765,46,969,885,953,728,55,926,100,839,47,708,342,701,613,968,982,649,229,493,890,618,942,363,503,865,74,578,801,895,67,605,258,502,437,309,972,350,704,225,606,785,130,333,477,989,337,199,152,127,545,598,506,553,513,91,948,308,615,627,124,702,285,715,954,199,448,986,841,864,779,565,145,359,679,585,90,413,719,727,536,953,924,834,956,512,157,221,322,534,77,560,357,514,697,184,60,205,0,867,369,43,763,268,850,74,202,374,837,830,796,511,866,339,735,19,739,535,843,479,385,689,613,433,810,595,719,33,7,6,413,48,563,962,333,136,216,941,149,604,416,466,415,171,925,92,802,43,384,577,738,297,197,496,248,739,905,319,504,55,829,31,101,566,531,230,257,944,267,573,767,114,115,909,420,380,408,793,155,681,434,580,177,417,721,26,365,155,883,898,733,613,11,838,205,580,828,773,797,703,970,199,821,794,480,436,423,266,934,546,582,88,566,763,654,141,224,851,386,722,276,325,735,563,437,652,681,342,291,78,786,58,527,931,31,608,843,175,458,416,390,447,896,738,339,328,101,519,4,308,439,115,996,458,126,188,368,254,610,486,397,127,460,947,505,11,607,728,506,585,420,761,658,772,251,372,736,771,516,208,179,538,26,74,753,95,880,667,998,59,694,730,530,574,295,384,274,174,866,918,351,844,634,402,879,217,982,208,903,856,681,832,317,833,685,978,658,577,34,777,144,825,144,551,162,837,376,88,631,898,926,216,738,64,714,813,669,842,48,956,583,666,834,825,831,198,276,209,395,322,210,770,152,783,116,515,467,250,853,645,810,73,627,695,889,128,62,807,310,194,597,20,964,24,940,476,824,305,726,62,328,822,380,434,644,593,588,876,451,893,110,610,352,219,842,323,812,537,321,123,708,456,656,803,906,765,633,231,490,571,155,113,92,222,942,915,779,710,777,779,716,896,384,919,508,264,799,999,430,134,393,523,539,528,405,172,133,193,753,946,267,701,19,245,417,902,896,183,334,893,921,841,548,953,234,860,706,252,132,539,397,427,576,473,562,757,204,605,709,617,227,394,715,580,970,934,288,691,984,104,654,467,352,432,266,541,156,167,243,994,457,893,473,769,561,852,420,363,194,237,698,175,89,491,477,615,19,349,964,837,821,354,718,742,274,492,846,928,153,441,602,255,90,834,751,848,649,671,928,74,233,483,807,587,474,945,569,227,710,921,977,709,778,390,953,60,719,968,905,42,323,335,871,494,478,575,720,834,304,630,251,748,623,563,679,573,451,313,430,976,214,95,643,583,167,647,693,783,794,248,210,573,132,573,311,552,819,464,985,280,965,267,947,457,380,405,181,451,867,157,377,297,256,101,742,259,723,854,365,218,484,421,983,197,789,108,138,97,828,958,917,264,540,286,460,938,392,84,393,971,310,598,544,724,334,957,170,588,21,105,906,373,283,723,459,421,251,242,363,500,754,543,786,726,40,977,597,919,984,767,981,221,920,938,70,202,92,207,773,225,514,249,573,66,486,41,846,193,397,125,551,516,206,726,537,813,633,902,834,83,191,433,765,255,329,937,574,874,482,941,725,866,139,194,421,945,250,772,798,859,462,504,316,530,591,619,52,329,989,188,948,331,249,997,794,760,8,84,35,544,66,67,78,393,753,673,183,12,188,387,210,531,58,754,84,927,293,692,460,795,769,538,340,407,937,266,833,576,76,477,309,289,274,387,387,569,82,551,793,624,352,459,130,122,893,625,677,213,321,129,620,173,605,392,396,808,702,906,945,546,88,437,794,149,374,783,993,807,956,175,313,173,722,667,236,831,576,701,607,982,611,785,734,187,111,966,618,378,491,976,437,221,534,8,898,998,520,975,111,952,67,782,585,444,306,374,399,403,822,190,972,815,601,995,926,254,376,821,946,352,745,132,422,865,481,414,752,430,511,310,86,927,775,984,580,609,825,898,900,541,187,291,543,84,979,376,640,561,716,294,938,44,444", +"524,48,229,378,149,422,425,765,903,659,989,563,812,532,906,32,116,799,731,939,648,797,368,779,715,933,194,152,26,387,133,512,261,348,118,474,607,784,221,608,949,61,801,375,813,951,382,791,853,464,489,182,882,241,243,181,359,411,564,840,606,856,817,167,209,50,715,25,734,120,274,618,485,889,389,187,963,927,643,268,836,887,282,290,582,854,757,959,362,482,707,975,179,513,99,732,992,323,305,739,978,83,83,733,802,453,956,17,794,620,284,278,993,734,347,978,92,447,87,477,242,941,936,593,901,159,631,62,20,41,779,331,92,632,112,143,20,73,227,251,834,388,252,966,558,553,135,473,967,668,275,487,218,166,846,467,65,502,641,228,336,589,897,869,587,516,745,777,370,910,399,938,160,818,835,199,229,781,180,301,287,486,709,875,904,499,517,778,76,859,173,618,866,344,930,878,416,309,344,42,494,69,914,892,766,280,916,393,124,754,557,323,337,571,734,867,0,865,443,276,817,299,525,474,593,570,383,136,727,19,602,256,601,504,160,744,185,886,388,71,202,554,557,992,131,285,205,657,258,664,209,111,176,916,24,511,8,710,944,255,104,127,128,167,848,460,9,430,762,21,787,558,308,921,729,544,570,685,166,267,775,794,619,395,677,975,319,517,847,117,91,161,356,864,157,520,555,591,172,907,422,100,569,645,739,924,725,961,302,800,617,448,636,964,898,863,353,928,826,614,514,661,258,942,164,6,115,476,10,795,758,588,959,753,511,818,384,21,146,640,605,713,658,344,619,170,921,746,661,542,475,387,874,6,672,536,226,248,134,487,748,567,48,461,321,695,636,641,808,672,374,760,224,997,213,236,610,193,220,107,70,990,222,785,137,676,260,808,526,244,247,875,614,873,442,750,222,647,740,756,273,351,886,476,441,262,578,417,318,443,520,43,499,265,282,568,215,726,683,745,242,331,379,88,737,73,332,239,333,50,318,467,955,928,219,681,225,738,484,647,154,762,693,860,649,114,92,39,258,48,415,945,826,618,385,166,189,904,778,725,198,559,205,224,988,803,155,667,283,523,913,670,361,256,920,30,496,761,209,465,940,816,821,748,363,670,873,241,623,900,114,594,592,617,815,929,914,878,186,861,138,950,98,328,313,206,835,218,549,928,559,394,449,536,112,271,944,879,78,994,610,806,844,575,777,689,161,656,510,863,844,775,725,439,98,743,548,361,405,50,529,744,678,808,560,426,439,767,904,442,647,478,319,140,822,791,760,315,615,404,111,4,790,268,30,849,789,313,751,730,720,132,698,293,16,63,283,94,939,204,563,817,749,375,610,372,836,358,848,483,491,960,21,611,85,627,343,787,911,549,820,846,53,300,323,48,274,76,394,634,763,60,88,966,200,225,861,55,318,24,417,458,690,390,660,804,463,156,43,784,653,555,620,147,731,64,421,127,745,873,464,989,784,808,194,359,909,470,117,613,967,685,773,283,739,679,442,642,172,899,509,189,71,251,640,707,97,318,291,917,278,443,284,777,264,499,630,137,498,880,972,810,294,863,989,111,593,383,619,179,235,305,79,254,506,131,42,840,136,854,877,291,900,995,368,716,475,434,909,248,972,699,994,82,304,461,964,827,988,876,866,82,872,821,852,924,534,487,475,21,959,384,542,203,119,840,28,252,809,655,602,158,889,885,140,20,178,284,880,544,664,114,666,711,972,659,377,88,235,866,342,917,168,380,872,228,607,144,804,591,142,870,237,413,916,20,92,435,623,200,308,556,31,171,687,451,590,742,137,492,409,527,690,891,399,623,129,803,102,19,336,536,878,759,783,283,70,701,965,323,661,713,77,49,107,954,878,90,624,741,518,878,528,304,144,646,624,41,351,725,414,132,972,973,207,786,850,41,803,509,520,280,570,914,335,467,561,169,104,172,238,847,3,69,502,870,13,295,379,841,698,906,216,209,606,925,24,370,903,845,16,47,141,758,244,906,22,354,225,67,153,399,508,699,561,722,800,867,838,29,699,952,964,260,32,322,333,380,437,640,800,565,141,246,428,259,951,758,424,662,493,793,984,443,600,785,987,686,983,57,937,791,232,750,607,751,446,762,6,987,430,336,499,936,306,912,360,703,419,111,779,404,839,605,956,138,410,763,1,990,865,580,290,162,894,171,864,766,504,105,617,261,972,774,979,604,441,741,699,922,618,962,532,98,504,410,373,133,480,609,119,700,613,80,922,298,27,90,509,315,488,503,860,256,662,698,230,142,969,447", +"633,424,865,363,85,83,323,225,873,736,311,852,149,708,415,445,110,490,902,849,854,614,395,755,792,400,575,631,313,750,993,284,676,753,813,528,714,871,349,655,253,395,238,605,577,725,665,998,977,928,393,324,176,201,190,256,120,97,251,219,867,450,901,560,371,827,984,824,258,954,288,85,207,533,796,745,496,995,721,865,655,311,540,512,303,573,783,805,51,809,462,211,806,575,244,95,101,505,195,456,851,648,346,516,74,335,862,652,237,989,279,962,218,833,85,707,535,355,62,284,352,119,841,727,480,443,248,72,459,177,360,197,607,23,238,221,816,19,163,797,720,210,246,262,120,6,717,795,39,92,643,862,942,152,607,174,567,80,35,84,856,398,358,247,670,342,922,796,722,999,319,845,599,119,520,658,832,163,751,43,958,678,818,625,70,428,577,437,572,343,52,700,727,307,750,658,608,597,31,359,137,856,910,165,816,462,332,364,216,208,54,184,391,602,427,369,865,0,759,683,519,246,845,963,392,360,750,773,194,439,579,427,587,592,1,803,966,68,369,325,231,763,969,813,552,969,490,348,983,958,740,850,148,84,642,460,643,316,723,528,966,784,664,782,129,269,264,262,634,99,322,955,389,70,428,526,420,667,531,371,320,254,283,429,873,812,507,136,89,841,339,949,326,812,453,579,1,437,857,504,57,409,602,416,465,260,448,315,694,798,961,285,594,486,943,317,868,445,645,594,824,746,95,490,75,522,380,997,895,240,959,332,359,866,483,191,751,439,554,229,954,821,202,963,390,784,672,143,769,917,284,906,331,325,244,934,942,972,733,766,124,450,19,871,735,967,133,765,402,639,476,604,335,598,512,365,581,294,206,412,827,736,26,650,142,338,552,103,123,244,420,440,262,222,609,44,285,820,858,883,962,836,565,38,718,954,614,480,746,753,471,190,505,244,474,37,53,390,408,880,945,915,859,229,137,482,689,123,632,78,415,515,128,73,929,882,738,749,407,298,693,559,232,652,759,343,94,85,15,55,922,233,408,106,598,329,702,494,795,50,917,154,544,495,840,878,55,112,114,786,225,755,618,401,691,558,729,684,838,535,769,119,840,462,935,397,162,916,443,980,415,794,866,225,76,404,162,175,475,759,376,495,33,255,72,53,480,725,238,12,569,884,112,495,820,332,473,375,162,983,152,415,870,484,486,421,323,190,376,522,375,835,741,799,313,659,349,257,734,721,120,795,639,674,676,319,816,111,350,803,527,896,508,393,88,152,304,852,744,214,750,125,617,611,207,41,505,881,123,350,139,56,50,247,421,752,199,938,121,188,803,775,31,937,512,82,417,64,195,55,387,570,967,909,17,383,279,775,12,228,613,332,170,43,736,329,430,176,431,693,341,49,5,214,681,757,717,769,263,507,949,572,721,52,479,382,262,450,52,983,267,412,283,763,59,740,555,23,207,264,950,205,693,219,355,650,937,663,897,36,964,90,829,407,383,866,411,739,427,926,42,372,944,159,875,477,995,951,234,416,705,46,746,459,18,372,254,88,306,392,394,426,744,943,549,709,830,315,98,110,705,717,684,364,512,739,971,261,755,762,968,580,529,854,673,873,228,997,451,695,1000,656,819,418,202,430,135,8,903,86,429,536,663,634,68,798,236,433,937,12,767,672,213,674,379,28,693,627,644,386,262,770,329,718,825,626,538,850,740,363,211,156,311,686,947,708,754,36,517,252,654,510,929,499,619,956,922,283,963,725,693,405,281,706,610,209,185,122,719,616,852,708,191,470,679,471,244,885,561,319,56,329,651,827,311,64,962,366,446,608,175,737,720,872,537,643,476,815,256,290,580,116,139,150,343,195,55,728,86,108,957,590,706,522,461,633,792,350,958,246,529,136,188,614,871,475,685,256,76,466,533,881,637,633,366,963,93,998,843,585,955,539,594,953,300,380,844,782,396,634,62,420,786,547,55,148,312,808,965,351,685,164,428,937,825,399,156,274,986,395,986,206,497,682,898,857,840,576,396,976,46,433,20,430,366,837,800,831,934,909,775,638,247,994,914,670,828,381,183,895,334,481,627,448,840,564,664,108,236,548,809,392,316,300,501,747,893,35,66,850,429,881,809,566,427,310,643,327,550,896,170,370,510,405,454,390,513,944,998,557,453,140,474,257,204,29,760,804,608,4,428,240,440,160,993,506,16,255,831,660,141,378,62,520,885,849,373,791,277,196,587,558,388,91,535,351,738,522,469,501,535,347,514,41,102,367,866,543,980,123", +"897,692,45,108,254,288,297,714,660,183,731,151,232,58,345,436,549,316,406,414,501,294,654,564,177,619,265,587,895,582,275,795,25,664,456,833,685,603,99,539,468,576,284,205,738,172,533,415,133,908,311,932,426,89,405,837,443,571,732,20,312,122,892,82,41,660,257,150,776,283,689,295,650,585,637,185,613,944,660,367,266,829,871,681,486,990,988,353,249,664,886,762,417,496,936,922,298,477,335,256,732,760,158,763,740,646,14,315,407,884,40,408,368,954,103,523,452,663,603,603,518,618,476,148,740,207,939,838,290,995,149,582,937,353,501,696,13,455,434,189,527,808,728,74,852,370,502,901,888,910,251,842,269,593,392,496,432,833,467,735,267,868,528,955,731,457,628,548,813,621,719,500,566,158,527,645,912,868,672,414,684,584,299,777,632,406,35,793,207,69,580,259,636,448,517,299,289,173,765,140,404,373,597,269,36,838,50,899,809,528,267,343,685,313,730,43,443,759,0,103,322,699,699,192,907,670,733,520,891,463,479,200,111,886,438,926,147,228,488,438,639,686,40,327,795,939,613,852,212,647,859,82,890,35,968,806,165,340,911,780,125,50,870,131,435,887,224,814,301,395,790,671,459,555,846,332,873,716,10,578,214,525,421,302,520,187,360,928,703,977,665,907,636,971,8,63,462,550,512,468,332,784,577,387,235,258,462,488,532,697,654,145,117,68,365,270,902,944,643,101,477,216,49,745,443,681,410,561,803,188,851,753,578,197,500,863,304,25,887,498,831,100,536,765,649,942,181,953,471,83,579,535,783,796,440,875,983,752,253,760,369,726,898,884,49,944,972,723,802,209,671,241,478,378,323,999,489,133,852,911,588,303,178,559,19,943,668,932,674,934,353,719,450,682,844,354,256,291,570,321,112,226,337,143,242,50,798,229,879,536,882,616,173,44,811,270,625,423,854,529,289,55,471,486,54,225,664,207,516,463,671,255,371,422,620,233,862,286,15,348,763,893,145,553,300,292,270,401,965,372,866,763,985,704,978,350,139,267,373,344,968,385,78,599,63,558,660,354,946,799,147,268,782,643,357,87,681,354,655,494,128,769,192,680,968,615,712,47,51,141,164,175,281,560,427,682,336,82,45,59,894,827,456,214,979,873,815,781,854,632,169,238,58,664,42,805,776,89,733,232,280,711,664,509,273,180,280,433,313,335,328,914,274,427,508,410,693,791,15,555,58,569,968,843,868,330,162,679,611,548,170,639,596,322,643,696,75,202,281,39,198,508,688,719,368,630,786,782,558,569,923,665,941,457,159,443,86,556,270,213,518,836,718,477,258,702,677,265,121,133,833,634,811,612,760,87,413,323,660,154,791,817,86,743,904,44,37,732,730,886,797,42,790,711,732,253,818,36,780,691,759,109,336,120,722,192,287,486,391,37,458,985,551,388,27,895,808,958,913,956,898,960,774,170,626,801,894,429,744,166,619,665,900,132,626,962,995,696,231,84,463,808,154,87,600,299,481,168,943,141,953,625,52,419,744,473,403,638,209,500,768,853,701,2,712,599,290,121,566,115,881,18,901,574,522,708,277,592,22,711,724,718,603,867,164,287,221,873,613,14,443,316,539,488,590,916,810,459,599,234,793,550,778,602,388,78,881,545,541,251,749,516,33,828,27,695,821,562,361,440,463,712,811,884,291,988,749,77,756,855,101,821,568,158,831,771,948,56,903,23,796,699,259,179,149,221,679,509,884,654,147,987,95,51,825,747,884,929,887,461,42,468,780,27,427,510,117,118,183,801,37,86,543,763,711,926,709,358,523,430,10,458,474,425,907,248,864,492,784,757,517,21,144,11,171,754,340,460,763,440,575,364,796,503,201,673,81,786,354,245,410,766,213,354,58,797,235,780,754,562,15,17,763,457,346,162,548,276,365,90,55,329,528,764,327,139,441,456,238,143,396,642,9,182,84,659,360,22,664,541,458,964,418,220,149,795,875,60,984,914,513,972,692,380,52,481,279,187,711,186,51,949,164,5,978,103,950,765,82,862,863,387,152,957,78,466,743,175,641,312,512,783,581,692,636,893,794,192,12,85,882,619,800,289,348,985,758,956,538,869,359,707,898,131,784,653,181,343,456,679,599,938,664,983,776,139,983,578,871,114,318,575,686,914,787,103,995,452,574,921,191,785,454,414,319,209,53,197,402,549,282,712,390,550,33,705,470,909,310,505,986,683,161,99,70,801,60,700,76,452,918,79,175,526,622,743,768,934,869,819", +"279,958,982,577,710,284,389,273,948,903,911,66,900,356,560,272,370,72,635,573,436,137,756,36,732,809,747,875,293,532,286,128,251,919,993,292,983,334,539,264,502,639,687,739,626,456,184,221,732,964,375,262,295,146,995,750,112,229,151,933,884,64,501,322,847,460,343,24,616,182,356,796,345,673,814,477,234,959,650,357,525,88,180,131,506,578,128,613,212,495,806,851,754,827,464,923,460,237,453,503,285,457,342,554,635,966,93,474,505,325,727,18,997,11,866,410,860,210,158,396,315,70,41,623,697,745,220,724,153,42,839,798,231,248,726,426,49,819,774,89,849,22,607,318,514,9,930,888,478,498,482,300,592,271,198,403,430,262,647,394,447,270,299,783,398,396,76,88,710,17,805,833,758,186,865,118,476,967,720,501,165,602,731,88,345,852,802,709,607,849,773,981,640,899,371,605,897,525,959,4,365,968,842,147,952,991,294,890,86,678,517,925,429,681,989,763,276,683,103,0,5,491,538,443,848,849,402,411,348,806,950,199,914,187,86,343,770,846,893,5,987,623,603,854,62,430,203,359,504,342,693,773,252,583,541,432,823,157,231,610,72,282,75,823,887,412,858,479,253,203,347,371,315,900,926,982,537,15,971,25,744,234,203,610,896,276,829,18,477,45,211,538,910,454,748,116,401,477,231,402,334,543,241,775,840,235,846,750,876,40,336,133,921,440,766,251,736,26,409,774,140,351,983,15,816,877,556,953,379,631,812,907,474,708,878,88,322,957,945,699,91,773,210,186,962,601,52,861,684,652,956,355,68,760,410,939,356,268,902,609,134,200,356,744,475,625,682,6,20,781,334,116,660,131,6,365,140,882,949,128,997,78,268,649,331,442,733,856,325,443,458,94,893,275,142,732,900,129,45,211,973,310,793,729,706,836,646,4,132,520,302,936,713,552,463,894,229,485,864,626,27,315,31,570,584,478,372,12,856,355,78,121,629,158,621,129,293,231,76,959,955,414,445,928,706,501,212,410,314,429,356,852,741,872,590,903,470,273,140,335,815,253,241,360,316,107,233,809,776,461,939,800,828,671,959,267,837,440,568,178,178,804,112,386,610,354,631,252,674,242,799,472,187,100,758,631,759,967,246,282,865,915,776,772,3,655,722,787,338,285,983,565,933,211,584,806,474,457,998,450,429,343,917,95,960,750,691,930,309,602,344,481,400,645,494,382,866,303,498,273,487,748,187,425,242,277,27,173,942,881,46,816,671,821,478,808,663,392,213,359,936,117,728,827,459,403,712,767,460,780,903,164,957,670,411,80,496,744,955,446,382,765,106,74,648,765,987,540,334,177,623,619,583,894,860,718,801,787,968,213,16,399,204,460,422,581,461,873,178,533,436,645,929,163,901,437,517,783,910,247,983,330,54,308,124,415,251,855,174,741,810,49,561,427,138,213,292,384,789,131,629,189,235,585,217,247,145,894,215,64,545,100,159,863,764,900,213,190,404,765,2,498,750,228,664,938,929,163,667,232,119,71,642,614,246,656,543,438,689,598,671,99,640,358,686,299,462,661,344,718,124,920,607,697,604,796,611,71,445,801,594,921,532,188,852,171,658,661,96,505,515,650,794,388,53,77,603,208,842,836,762,628,362,399,622,146,268,173,771,666,265,61,344,703,560,509,551,585,66,462,34,805,336,341,398,375,576,835,298,705,770,406,96,198,805,620,398,911,2,734,219,798,636,56,480,898,934,491,764,744,483,989,895,566,418,718,741,283,207,185,150,518,186,605,695,338,587,757,779,53,663,790,311,589,358,345,499,304,98,316,475,612,139,521,910,609,398,300,913,866,845,777,756,552,66,155,314,716,203,758,974,541,118,607,573,467,58,945,320,579,593,205,421,257,251,295,688,672,273,558,17,469,62,259,742,349,275,969,360,541,95,227,540,689,991,450,51,12,343,380,121,379,948,510,443,710,716,136,426,689,513,639,220,814,894,299,366,636,581,495,145,156,245,811,391,443,347,120,943,109,206,854,926,74,716,358,641,930,538,990,764,209,894,802,660,372,612,951,121,994,82,15,247,488,709,986,116,329,549,532,985,623,359,993,739,696,627,646,643,516,251,229,672,114,834,144,139,638,970,232,339,431,819,258,778,722,987,52,489,554,899,530,642,545,521,771,151,283,293,218,329,319,988,867,971,759,809,273,156,986,872,771,886,485,764,976,363,149,290,798,922,13,392,754,117,726,884,926,567,603,630,582,537,58,33,614,170,805,99,784", +"760,223,109,932,100,866,483,324,695,747,300,537,183,615,932,209,315,102,370,193,102,108,643,162,551,694,529,691,458,433,461,880,985,163,347,546,651,853,146,286,269,403,345,714,251,241,432,26,598,81,584,770,37,616,787,299,34,482,641,653,805,48,797,386,104,414,987,875,881,663,288,455,49,576,328,508,88,27,155,349,858,868,621,134,928,481,523,64,909,423,261,326,725,526,769,123,213,474,364,478,609,944,294,528,684,884,520,699,61,5,865,368,413,223,697,667,520,868,567,994,688,139,339,12,18,535,146,743,642,676,613,165,291,775,810,4,348,564,884,668,679,802,275,174,45,183,666,695,767,136,639,116,294,538,602,927,72,71,992,743,599,707,551,189,769,647,204,812,594,124,20,559,904,400,604,881,704,161,448,767,161,446,701,369,393,359,751,756,969,474,638,480,387,640,283,13,889,653,770,352,768,131,787,975,958,457,895,90,593,465,710,539,467,645,314,268,817,519,322,5,0,897,313,104,322,65,378,243,688,959,947,365,398,783,164,617,630,229,680,232,475,778,388,546,242,606,990,168,951,473,939,611,312,42,658,586,384,998,774,89,365,108,656,596,897,348,419,402,593,864,172,838,934,386,390,723,580,596,146,81,23,357,896,576,81,458,199,773,114,242,148,641,536,951,666,268,822,364,224,814,968,370,124,151,997,133,669,379,138,723,865,92,559,589,248,109,215,142,533,779,648,224,131,581,248,440,57,666,698,288,773,660,806,912,433,679,920,465,793,689,1000,679,841,341,307,848,738,892,456,711,817,990,685,185,789,729,331,801,441,157,588,217,829,803,89,503,842,200,550,798,841,339,937,923,961,881,810,444,587,581,106,675,258,480,633,546,692,580,757,212,531,435,504,12,935,771,104,552,14,232,946,182,834,252,16,164,729,454,650,538,432,937,957,547,797,261,727,998,351,4,25,852,755,520,17,916,2,297,350,355,152,923,474,925,147,710,744,729,278,514,15,586,91,290,24,922,576,653,776,853,534,444,898,428,841,931,14,511,816,157,469,506,947,277,616,370,433,637,953,418,979,797,139,374,83,762,212,897,891,311,413,855,714,942,338,929,364,579,165,944,362,943,233,71,242,768,677,981,896,959,114,419,686,372,76,466,513,434,16,649,937,359,332,760,259,482,506,945,61,428,442,524,203,888,949,684,655,595,964,633,558,938,557,24,1,518,153,744,742,457,273,127,582,51,113,766,723,117,673,877,382,525,105,298,547,160,456,479,315,356,663,35,588,735,111,556,749,469,433,879,102,343,956,250,589,3,236,474,918,616,436,97,76,771,386,283,828,633,921,341,561,323,95,347,549,635,829,392,57,342,427,306,379,617,692,438,667,371,90,42,527,675,610,567,762,769,569,457,605,619,775,641,588,511,421,298,510,596,489,677,450,876,79,931,162,825,65,649,671,543,168,722,106,108,780,13,557,32,769,612,585,451,610,319,650,304,556,863,258,929,381,121,859,509,628,369,214,188,94,647,753,98,985,880,669,179,542,335,919,423,775,762,47,819,529,341,644,236,738,171,510,823,803,997,356,751,458,584,93,79,493,471,700,742,806,8,389,222,730,799,470,420,403,716,26,849,518,794,470,340,424,704,688,193,760,575,107,412,243,256,594,633,565,588,221,652,866,591,915,384,566,942,481,700,937,727,355,360,714,318,63,526,909,148,452,275,313,275,684,773,177,652,373,193,765,893,336,651,885,781,617,428,428,661,937,147,928,573,987,877,71,323,12,277,905,835,49,857,131,428,577,733,389,503,644,380,774,979,725,464,927,855,592,862,504,465,778,360,842,983,580,357,255,852,39,262,256,598,80,4,978,397,435,727,820,279,647,388,349,489,350,915,685,55,279,407,641,72,616,389,601,515,185,651,494,109,215,732,946,536,297,594,375,262,189,381,827,498,3,680,542,3,608,433,941,578,122,481,290,719,409,790,291,346,268,902,332,813,970,819,553,323,733,260,284,544,495,674,722,39,415,991,186,566,94,977,833,647,816,761,911,232,918,225,537,188,83,159,445,705,71,179,198,324,514,250,926,539,208,369,202,895,350,347,290,321,12,127,422,393,663,320,992,609,106,475,816,218,971,721,540,498,918,83,332,219,703,365,938,507,521,756,68,91,151,332,344,769,586,158,28,224,278,322,72,22,474,168,768,26,377,305,401,506,56,714,161,936,709,626,642,312,295,589,51,720,514,860,160,174,380,846,662,809,116,312,326,708,283,461", +"755,374,575,170,317,289,151,532,589,944,882,192,916,888,630,371,775,762,657,871,12,551,745,224,995,670,788,446,235,342,694,443,956,903,536,877,374,195,830,42,4,58,309,179,950,270,345,613,203,527,134,835,103,67,399,864,379,349,271,790,358,768,267,513,945,88,755,858,240,956,586,197,8,975,200,112,288,949,332,337,814,673,217,480,612,628,468,291,272,653,216,770,478,413,640,5,929,581,596,848,365,564,914,671,951,335,777,294,53,251,271,907,443,220,740,57,95,49,70,520,992,64,143,156,985,747,569,434,533,68,298,737,221,785,212,256,405,275,884,232,574,585,877,528,692,341,430,525,511,196,759,534,137,108,166,234,367,985,984,486,682,285,637,441,46,564,370,410,179,729,766,785,401,301,588,422,316,28,93,353,601,338,799,559,549,908,258,973,379,503,749,351,959,40,276,352,90,178,720,891,154,174,396,821,987,500,140,613,867,272,544,620,846,13,513,850,299,246,699,491,897,0,249,817,561,545,138,248,37,681,836,496,198,333,99,652,252,282,864,505,430,266,417,576,528,304,674,44,734,507,313,146,285,900,371,605,530,303,451,609,246,847,369,966,924,137,320,121,35,390,330,354,234,879,426,849,248,354,811,54,946,138,559,315,894,759,698,267,237,151,696,928,802,278,741,65,890,764,243,563,393,74,905,509,760,556,965,950,196,354,939,727,118,616,652,840,881,380,819,110,658,996,851,229,992,755,360,946,866,140,406,392,238,510,959,484,897,358,953,892,140,715,813,699,550,103,608,846,440,686,471,846,296,720,877,468,666,204,807,160,254,62,783,148,800,256,886,152,457,382,263,541,943,935,685,31,999,54,856,228,407,89,297,158,149,143,227,419,80,933,610,259,448,322,643,73,720,793,359,238,239,871,795,932,170,882,469,208,734,682,82,593,124,421,749,337,650,214,513,116,252,275,285,983,570,954,606,997,396,959,50,394,893,950,540,403,468,75,848,531,289,546,919,405,580,677,424,560,613,10,173,113,685,675,358,192,301,712,245,444,854,778,396,306,594,866,591,851,824,844,582,550,149,898,470,470,800,141,363,636,402,291,871,814,593,599,13,992,727,437,35,59,876,766,132,925,655,192,146,621,230,218,204,769,36,255,149,26,262,319,351,690,166,569,938,297,477,294,78,791,153,985,734,200,405,575,639,563,323,624,807,897,793,894,499,639,650,729,890,926,673,720,551,128,399,867,227,548,190,796,331,767,752,738,743,723,706,43,491,312,484,207,556,184,398,869,207,873,606,756,125,182,861,637,615,465,539,509,573,96,120,580,618,937,694,238,34,424,566,473,653,363,695,371,228,688,941,129,617,981,818,505,768,791,615,856,658,989,256,518,983,783,41,244,943,940,962,798,888,269,434,52,616,26,282,461,541,295,43,466,315,234,99,858,294,951,507,207,710,248,563,700,420,128,135,284,948,140,873,212,6,912,980,52,176,296,207,392,883,91,833,377,368,420,518,884,464,806,580,504,712,808,70,826,988,791,626,319,649,530,501,148,515,367,521,445,697,480,455,751,584,422,128,51,677,380,348,931,630,873,91,277,207,25,357,879,347,149,61,420,273,22,31,960,685,13,363,255,338,780,793,114,199,309,537,203,467,437,980,9,150,850,408,613,276,945,528,342,959,75,39,274,631,559,999,959,980,537,38,949,612,597,765,307,634,779,373,286,840,692,608,866,510,368,446,894,640,575,12,894,961,2,193,554,577,731,49,205,426,396,213,262,436,717,3,692,592,63,8,529,46,530,30,94,810,857,89,791,816,825,796,104,234,697,601,742,190,858,548,639,217,250,275,305,176,650,866,990,921,506,13,423,35,123,447,721,222,704,15,650,179,450,281,395,139,508,66,845,239,734,576,145,887,41,3,665,925,531,282,558,22,659,204,540,483,352,698,212,800,987,429,147,37,927,613,944,569,589,85,778,176,485,779,780,355,218,166,651,711,14,502,72,865,835,266,153,390,567,805,286,436,415,456,953,716,826,906,463,89,430,317,455,992,97,913,187,407,819,581,560,29,859,243,459,444,924,896,747,933,578,694,129,245,15,795,701,630,860,839,620,268,691,288,345,838,936,662,701,450,402,736,840,914,369,791,121,681,163,13,956,434,868,10,413,738,899,198,229,460,353,97,241,739,736,724,481,17,956,736,1,483,741,234,468,431,289,506,515,710,484,971,369,114,274,258,590,177,784,618,518,608,614,603,379,605,914,277,983,385,196", +"101,929,320,241,239,828,569,228,81,880,402,881,943,120,189,361,99,762,138,940,683,411,668,805,604,818,563,764,414,269,562,334,366,775,61,742,258,440,766,645,172,632,125,339,811,277,677,23,826,250,240,29,969,482,566,136,29,565,816,541,243,190,34,9,329,253,704,251,355,749,713,200,587,434,626,561,682,257,138,198,465,511,310,726,875,672,568,283,843,644,166,413,679,382,126,280,671,451,245,44,287,539,565,992,416,427,990,966,94,838,349,165,13,852,779,460,24,262,407,375,604,844,464,518,627,415,936,930,223,413,386,607,963,754,396,479,123,978,881,429,679,512,379,354,464,99,389,949,150,17,663,726,268,451,541,229,699,703,792,841,686,798,413,896,621,99,111,533,805,557,835,675,264,354,980,912,704,639,15,883,222,379,806,213,911,485,572,486,791,703,348,904,617,760,751,458,858,292,636,13,629,179,164,253,740,812,285,634,596,232,951,353,649,422,586,74,525,845,699,538,313,249,0,232,372,60,78,417,703,400,789,454,930,798,727,451,474,169,984,417,772,33,806,72,860,154,821,473,644,316,242,767,963,858,734,85,960,311,288,327,967,650,862,332,138,121,234,160,758,851,909,10,793,377,174,433,654,407,51,704,573,941,12,744,853,404,831,654,392,650,986,946,156,505,537,86,901,992,541,204,84,402,273,973,850,8,136,506,912,154,574,639,430,794,395,26,13,41,265,103,880,592,232,97,62,635,237,149,833,784,197,695,11,802,225,399,486,828,716,862,628,93,320,515,25,442,724,268,190,631,499,858,290,690,252,160,705,787,360,539,324,422,988,968,489,133,848,121,789,362,974,789,512,92,423,853,205,243,584,971,315,39,458,292,176,398,780,321,922,804,225,197,202,390,465,73,188,508,232,274,911,52,332,688,112,996,862,910,610,404,702,227,701,779,484,75,818,584,629,273,478,630,607,571,318,713,928,355,946,922,53,881,760,287,126,612,504,792,683,419,647,998,533,102,969,476,758,611,684,542,958,54,871,877,363,985,434,449,820,272,434,922,799,231,519,774,73,139,677,70,312,254,878,390,700,854,52,73,830,582,786,55,184,500,459,365,611,181,268,224,809,999,31,989,477,865,348,226,370,902,237,412,550,993,60,595,681,225,121,984,588,624,706,112,413,839,932,415,243,522,40,216,990,259,54,809,292,327,142,555,471,196,534,260,563,516,93,511,997,877,81,592,622,405,265,682,366,495,270,941,881,934,497,745,377,513,636,961,198,907,887,212,594,138,259,624,786,22,706,377,456,388,152,257,542,801,483,997,370,679,250,663,554,5,993,998,510,108,355,909,414,447,191,231,51,294,578,983,572,31,106,287,869,476,964,591,573,297,270,511,898,159,962,366,650,419,969,846,120,987,955,699,618,806,725,376,293,344,126,973,608,540,141,933,158,542,701,231,882,127,243,106,574,811,538,20,385,102,143,536,403,508,161,187,768,188,337,484,362,425,512,161,129,315,46,682,664,859,7,438,990,263,321,715,617,821,889,233,216,386,436,564,870,690,454,63,109,623,655,611,43,193,189,650,779,340,37,892,163,926,562,41,195,101,810,841,541,932,972,937,823,128,474,881,43,55,551,380,476,829,849,732,436,974,592,752,241,449,377,607,445,791,379,810,216,300,172,560,252,231,384,667,325,911,964,573,122,214,320,257,361,432,791,499,347,424,671,860,354,579,179,772,102,790,182,896,726,875,347,795,94,41,517,139,606,799,653,818,510,675,988,914,442,891,572,303,484,882,32,94,799,468,30,172,662,332,227,656,975,578,740,439,101,930,429,410,50,617,404,924,770,634,686,957,460,267,835,874,491,538,135,159,639,927,850,564,10,250,458,81,962,191,220,211,477,169,672,54,894,522,259,206,320,963,971,70,277,455,550,543,239,15,351,174,288,73,689,596,613,911,312,535,876,229,635,348,271,963,934,227,758,269,827,333,704,337,525,517,332,907,785,653,643,500,705,566,213,705,946,384,668,540,394,345,673,851,650,328,50,938,414,960,122,278,918,839,463,658,464,819,69,638,812,743,804,995,233,996,919,336,874,809,765,263,300,910,89,236,160,584,658,519,603,694,188,558,606,838,659,955,234,974,606,205,98,177,631,175,565,590,589,276,889,458,49,432,46,101,956,659,630,462,194,200,620,106,794,101,652,38,991,991,512,600,315,242,393,316,863,643,123,49,938,77,154,288,894,529,761,609,424,332,638,667,108,685,197,6,917,430", +"37,828,879,733,471,859,529,819,54,324,442,421,257,815,160,625,423,16,795,468,878,678,113,381,640,30,913,388,405,592,430,37,830,804,685,305,903,692,352,706,641,873,643,818,275,755,493,1000,753,529,84,73,86,468,291,904,127,222,689,869,22,332,964,696,971,796,732,128,196,284,676,180,631,550,558,634,817,235,336,658,564,640,33,188,334,479,41,18,44,935,295,770,43,378,205,354,560,235,457,297,889,175,822,91,662,513,477,4,604,800,908,692,570,66,464,936,290,475,289,667,590,537,619,753,934,467,849,355,951,856,425,778,334,593,531,258,876,946,978,663,482,787,123,810,860,133,446,677,337,521,539,895,277,991,588,383,798,45,553,975,64,761,382,692,701,325,126,751,50,186,536,783,220,196,659,614,51,371,711,698,607,560,741,771,224,731,853,817,180,763,952,648,89,188,492,324,134,719,773,406,496,160,169,602,583,600,186,242,948,203,101,267,720,357,962,202,474,963,192,443,104,817,232,0,420,462,801,385,335,176,146,668,367,652,931,650,645,740,430,702,308,186,453,492,326,721,20,264,473,663,882,778,416,357,244,800,936,98,221,677,145,994,598,599,4,107,413,887,127,711,80,599,898,181,704,77,549,667,867,734,639,779,388,575,878,431,181,443,949,939,236,33,878,13,176,627,259,188,722,216,951,263,704,258,911,41,347,814,272,255,678,770,851,396,774,838,667,631,994,906,628,819,354,432,414,334,795,169,229,972,985,814,305,406,586,117,576,598,888,476,118,208,477,375,306,672,18,490,748,41,2,26,934,407,409,869,135,384,396,235,986,326,920,492,80,376,328,543,767,399,546,750,296,912,639,157,59,166,48,549,104,303,960,367,583,373,888,560,505,382,177,109,956,794,354,465,73,339,941,82,783,353,300,314,853,987,677,958,653,931,439,542,125,723,91,964,309,896,875,712,767,747,729,538,944,688,197,519,580,159,482,210,109,954,869,657,487,319,482,785,852,63,853,35,679,589,505,126,521,222,264,767,864,265,593,617,714,298,762,87,309,773,334,574,877,178,272,69,678,215,996,307,469,26,175,224,656,869,527,338,509,878,653,898,369,75,498,887,644,97,161,925,585,567,224,252,417,482,309,303,696,636,898,454,880,76,979,330,403,201,298,807,479,114,127,74,907,880,634,196,277,477,177,670,218,840,994,121,560,884,840,240,96,383,859,65,233,249,536,694,366,103,850,315,110,770,782,269,338,860,246,496,806,394,142,331,887,373,412,36,776,415,420,912,798,129,316,209,399,261,276,820,130,607,194,169,22,120,766,964,828,517,725,919,752,412,456,755,657,825,857,253,990,235,322,771,816,876,427,84,239,481,527,491,497,829,449,524,72,819,750,273,4,712,303,969,322,88,627,677,67,599,303,346,899,190,372,811,884,304,640,492,347,395,15,134,263,577,718,929,830,130,666,139,882,126,945,550,797,894,902,737,165,349,432,990,836,24,394,595,191,390,461,642,796,430,721,234,524,77,817,163,118,636,265,723,220,33,820,61,190,217,174,231,727,662,29,352,701,466,892,153,589,400,419,294,71,25,872,660,731,792,695,77,421,205,309,783,6,847,968,160,414,80,202,719,577,339,816,437,56,977,994,769,863,848,278,970,434,231,368,790,821,448,894,461,907,579,383,471,411,774,677,659,271,932,509,234,52,777,649,692,501,502,902,530,807,573,18,628,994,865,962,762,763,291,687,756,17,851,515,151,832,736,273,509,818,185,397,749,159,804,919,62,342,221,834,539,591,142,599,321,729,673,27,21,505,544,129,99,885,822,817,269,624,216,104,568,643,123,79,237,965,370,232,222,650,700,847,876,271,122,603,670,383,434,619,485,969,180,755,122,924,982,241,724,892,168,867,289,365,333,459,235,618,515,296,711,242,294,249,162,689,571,130,236,148,556,977,858,196,772,863,367,555,120,113,829,622,479,627,114,32,864,347,896,550,373,559,301,61,665,382,973,405,582,578,8,502,759,331,457,718,879,638,508,619,67,452,308,367,35,205,232,99,610,322,338,723,40,362,302,712,217,553,475,1000,450,373,372,385,460,410,14,810,881,828,555,587,249,725,205,305,759,114,44,522,989,783,322,691,720,427,93,309,43,118,145,142,180,131,413,326,879,853,559,419,35,958,259,474,889,728,997,308,439,488,93,814,189,438,585,631,605,564,659,261,53,392,984,350,86,601,489,193,198,334,455,42,888,7,359,284,832,80,404,813,52,101,627", +"769,450,331,500,217,732,292,588,718,820,805,920,953,324,393,559,812,11,520,404,655,37,29,34,771,184,614,396,501,612,632,172,679,697,558,86,620,68,131,207,497,865,413,714,476,743,111,725,878,739,825,557,251,251,216,358,14,366,352,197,888,131,589,923,872,501,392,789,661,824,938,865,796,349,626,182,608,8,57,953,435,587,788,778,513,971,978,632,539,939,257,308,866,971,82,789,882,472,302,138,807,116,877,290,993,45,335,837,89,622,77,764,435,391,407,899,59,237,55,473,5,729,699,958,971,186,139,584,795,814,369,686,981,612,824,940,237,657,67,50,968,500,420,813,48,207,488,257,92,497,85,371,903,267,210,487,538,937,200,999,825,320,174,49,445,332,129,473,540,224,395,964,809,146,375,60,345,53,456,652,823,402,3,229,7,917,706,400,825,671,510,15,339,880,624,722,190,110,318,89,538,340,712,583,199,434,375,925,589,462,432,137,85,842,837,374,593,392,907,848,322,561,372,420,0,94,513,348,251,634,236,367,384,337,467,259,499,140,813,40,751,887,781,191,17,703,386,476,586,690,36,570,603,917,223,749,467,91,310,864,694,985,424,516,952,991,571,241,349,520,731,280,992,313,907,959,26,918,246,471,683,932,136,590,518,251,426,559,454,699,364,646,8,675,495,730,59,390,147,469,436,32,349,361,277,475,649,456,599,53,805,33,937,314,741,651,851,300,955,617,404,24,825,825,734,500,615,1,659,114,454,264,619,9,708,872,125,265,26,465,833,6,114,569,661,316,405,595,184,798,26,229,910,461,525,187,686,777,512,554,883,874,969,345,511,383,50,556,6,670,934,543,213,767,626,201,483,838,386,465,788,109,539,664,753,493,278,613,894,80,104,908,349,191,183,829,7,330,691,121,574,691,176,115,195,601,204,611,84,111,400,465,202,740,393,81,895,8,693,16,588,227,778,707,924,894,282,4,828,139,151,308,193,948,993,418,953,245,42,798,708,572,193,868,610,235,991,761,846,86,373,692,524,361,41,49,757,970,654,291,740,687,167,434,925,130,830,944,425,636,755,154,186,754,256,610,280,958,865,908,301,795,922,131,701,527,493,100,325,184,578,705,839,389,34,438,888,628,529,25,843,806,920,148,148,33,817,837,236,199,346,967,244,160,924,114,638,696,564,122,584,336,614,186,75,278,859,4,682,580,529,1000,335,125,782,225,871,610,319,359,361,976,255,715,229,529,961,11,495,409,164,830,320,781,168,635,655,781,109,550,481,351,370,971,383,579,271,278,549,930,438,477,99,314,69,376,715,295,861,665,251,811,493,532,260,63,508,585,120,982,696,653,769,274,689,165,99,289,382,846,339,787,356,931,487,453,119,936,65,79,418,362,321,660,598,773,143,665,743,979,779,2,759,852,747,602,898,451,341,868,801,610,17,108,815,640,158,478,684,604,343,541,622,754,267,338,191,835,257,445,714,527,348,214,792,141,636,768,570,472,361,652,290,483,809,308,254,235,448,623,121,655,30,842,790,690,847,118,259,452,928,166,732,555,831,518,364,18,138,317,997,616,61,456,247,125,946,406,252,415,368,328,407,289,746,294,323,713,88,734,884,186,306,204,829,643,228,181,289,125,265,755,867,233,697,381,580,489,621,987,109,581,516,406,96,149,497,314,433,776,165,986,549,291,386,676,307,533,390,337,864,175,88,354,533,865,653,155,510,398,851,337,336,911,650,420,174,715,55,452,454,128,134,520,394,86,26,698,765,585,303,687,969,786,109,759,138,97,760,43,100,80,289,997,111,179,499,229,273,841,65,549,374,567,247,859,800,390,16,707,112,908,400,698,312,170,973,592,396,879,149,929,386,114,656,771,551,957,811,744,478,404,220,669,734,391,836,107,565,995,258,427,594,818,215,903,891,361,278,469,44,307,106,249,635,583,879,883,995,824,304,908,804,440,960,674,552,345,965,859,842,777,452,798,381,999,344,503,274,278,130,448,109,514,589,904,738,387,322,761,523,810,503,943,623,836,245,908,777,210,980,528,615,284,775,837,466,722,171,925,354,834,741,193,432,100,287,265,954,564,240,331,193,667,458,592,605,232,468,837,506,420,819,602,930,754,115,295,455,825,188,477,158,808,428,591,153,117,61,377,952,190,151,886,985,815,708,207,65,482,673,830,126,521,898,227,322,223,324,835,512,997,669,865,288,19,358,763,247,305,807,64,948,640,424,174,740,666,607,502,129,617,883,682,987,755,845,532,20,883", +"460,465,990,357,966,853,298,784,408,773,102,487,108,718,933,62,864,639,629,567,324,51,129,873,232,136,94,712,528,84,848,197,913,603,930,445,565,268,394,58,365,112,320,334,945,73,129,531,940,648,531,600,247,873,792,982,207,126,964,544,986,562,289,549,467,437,271,637,554,850,30,524,725,197,489,371,437,127,871,270,395,92,107,379,313,388,440,257,944,889,883,751,664,392,869,553,689,34,82,747,132,243,226,23,334,679,292,437,482,895,21,680,527,673,899,752,416,832,379,601,859,538,604,489,339,940,252,553,464,522,67,730,612,21,532,299,731,708,116,511,838,604,958,575,801,460,316,21,656,544,71,617,123,232,710,919,351,298,238,119,187,959,175,751,423,501,424,589,372,234,55,446,626,12,143,341,90,551,453,653,132,301,224,947,830,767,693,349,684,492,597,985,269,466,786,937,924,703,826,721,207,966,150,112,121,812,83,41,167,43,401,628,802,336,65,837,570,360,670,849,65,545,60,462,94,0,641,918,470,870,352,375,458,867,675,303,270,407,350,578,746,530,678,198,588,349,334,122,532,325,340,724,729,705,994,157,211,45,980,466,26,992,538,120,710,319,585,108,919,539,158,23,948,904,627,165,306,102,774,493,706,679,871,73,769,563,586,934,188,616,508,924,675,424,761,195,957,329,619,965,208,425,894,50,2,438,508,882,137,404,35,264,473,126,37,151,212,758,108,575,706,563,727,735,360,439,161,291,969,619,104,123,849,144,816,283,24,241,901,848,612,466,975,883,784,164,530,590,282,253,508,815,875,868,7,18,626,18,716,739,910,352,314,9,409,292,219,428,230,671,287,3,818,840,246,162,270,720,594,132,656,231,139,854,975,400,501,210,30,279,259,982,814,189,349,191,972,268,397,528,955,420,248,214,786,720,788,685,33,276,358,229,195,100,151,982,281,95,111,591,841,747,855,133,481,258,893,627,671,437,639,412,214,264,477,377,490,963,343,834,97,391,63,917,225,936,248,617,893,361,784,509,884,733,532,277,110,304,184,704,207,453,381,230,324,888,20,670,110,827,636,316,529,187,29,490,215,711,341,9,591,177,550,35,818,444,988,898,141,305,503,218,481,259,923,772,244,131,240,362,583,672,469,788,32,138,995,881,499,732,601,529,442,889,863,748,760,89,530,38,274,134,275,505,123,767,393,934,29,947,821,441,464,141,272,237,691,359,115,42,186,907,139,640,374,475,639,840,548,45,984,59,743,973,820,246,674,919,137,57,824,30,272,857,303,484,316,205,193,296,505,205,42,33,241,208,706,231,772,989,910,524,416,674,659,898,447,674,205,474,219,18,455,647,31,985,198,7,61,406,566,543,281,791,529,634,850,751,625,730,544,77,124,44,185,272,758,761,165,463,893,266,636,236,296,531,772,377,238,705,204,247,975,978,285,397,582,106,748,627,785,25,703,408,159,83,761,24,170,232,535,959,602,29,393,723,689,965,434,645,468,444,525,452,320,389,145,18,672,641,820,808,849,135,586,630,637,717,866,216,603,557,167,701,313,64,753,569,142,898,816,191,485,861,834,8,232,620,479,825,797,599,991,89,887,949,198,147,683,947,191,789,57,802,220,245,693,615,567,77,138,405,352,90,434,743,496,329,324,609,384,328,441,311,336,703,889,210,540,740,915,2,801,365,543,743,833,950,711,642,412,798,140,838,766,185,369,750,312,664,847,199,941,272,793,896,787,844,43,871,375,992,32,543,100,309,441,85,59,287,867,51,871,946,966,590,97,565,491,10,677,12,498,727,273,699,785,53,331,217,829,592,160,430,561,765,97,847,554,263,874,846,41,308,785,921,733,154,581,282,635,365,549,778,581,32,627,574,237,933,366,207,528,614,682,390,248,468,84,263,222,302,124,261,754,536,96,699,551,744,824,126,218,704,908,337,552,969,86,948,122,739,454,370,670,223,525,289,502,209,388,804,103,104,523,968,822,54,365,319,156,302,203,72,215,653,18,851,783,838,860,524,568,844,109,981,791,930,464,991,926,846,549,670,39,24,983,672,224,688,934,937,586,953,865,431,587,679,869,134,424,787,369,134,388,4,37,922,219,252,988,977,821,338,349,871,544,984,204,429,103,120,259,160,900,907,527,777,778,208,890,94,692,43,27,958,160,618,93,786,124,290,501,980,526,583,860,131,801,668,511,562,52,151,435,32,944,973,384,423,22,825,728,887,957,246,219,278,195,133,79,48,426,128,71,958,36,867,954,260", +"252,411,887,200,557,816,569,99,135,395,764,354,750,333,371,193,837,957,133,675,242,808,382,417,766,955,80,211,377,80,334,561,478,107,793,870,614,496,547,506,168,499,278,678,447,551,89,400,763,126,411,240,492,266,673,867,241,166,229,58,405,450,842,992,374,67,513,171,267,180,357,498,472,597,876,280,354,193,386,29,760,868,663,804,649,273,685,859,93,228,402,423,404,16,16,144,94,691,460,64,114,419,230,34,74,937,896,82,989,74,203,952,727,810,443,682,829,812,16,329,493,852,359,7,672,799,912,277,817,745,475,972,994,852,354,170,60,415,210,293,807,638,787,641,557,444,804,387,446,864,875,961,906,590,597,637,184,935,346,174,339,274,146,834,253,143,187,908,622,532,101,456,801,697,38,899,859,187,20,511,484,224,629,837,704,219,609,621,429,980,123,530,10,606,400,286,824,981,483,187,504,636,373,981,5,525,646,604,40,797,24,925,878,644,55,830,383,750,733,402,378,138,78,801,513,641,0,624,250,997,676,415,49,673,123,168,613,760,17,579,965,139,670,312,777,985,380,105,898,268,695,627,520,794,724,209,523,92,111,415,140,434,990,152,167,593,990,351,790,956,650,703,712,31,528,640,424,273,946,871,22,402,611,299,452,990,168,489,156,160,970,952,83,431,578,65,137,846,121,357,419,663,277,80,209,57,927,827,665,447,152,760,341,926,460,536,712,761,873,998,757,844,232,716,744,352,60,81,944,712,91,313,44,404,585,365,51,647,363,157,295,761,690,939,959,595,8,70,4,27,147,215,879,797,210,823,746,811,182,171,572,670,940,382,297,881,56,50,478,96,559,224,99,443,193,161,406,910,631,415,520,41,459,56,855,658,130,998,373,882,52,768,292,64,15,762,130,61,767,451,256,961,472,57,853,501,659,829,215,498,109,713,705,73,489,537,824,996,523,360,422,432,734,458,149,909,677,983,380,430,858,271,122,258,907,555,606,218,300,218,267,270,917,878,834,734,550,792,125,158,253,645,76,532,210,479,206,356,954,730,583,383,951,743,803,600,517,833,475,949,4,990,718,861,922,570,347,881,178,439,878,83,518,421,143,784,184,349,149,423,957,990,971,715,994,346,314,326,31,20,420,475,767,224,113,892,286,173,134,277,413,920,197,337,268,259,102,287,815,529,658,509,513,237,169,114,677,695,331,183,991,606,226,787,876,608,901,634,598,162,744,946,220,772,367,44,253,666,761,858,915,770,665,683,240,557,727,491,875,512,147,639,228,676,294,774,454,675,595,709,722,570,714,220,206,875,409,133,468,381,132,507,406,966,38,332,233,939,601,328,947,164,240,80,20,383,161,407,407,3,70,647,194,9,278,923,965,584,715,847,948,802,850,826,452,794,88,144,91,461,808,518,291,25,170,348,476,177,516,298,622,400,530,806,917,353,183,546,325,342,644,220,753,338,474,136,798,860,509,251,931,551,178,417,811,53,701,978,289,71,695,992,476,889,445,156,255,388,578,290,497,438,175,858,343,442,700,757,782,306,681,444,710,20,14,369,466,273,335,393,722,578,88,892,608,198,756,545,149,694,911,767,951,276,387,861,780,536,83,17,893,118,280,206,726,470,96,716,203,347,676,86,785,745,231,181,540,536,762,468,784,972,232,991,501,999,857,399,757,31,132,198,90,694,322,778,992,91,547,839,10,165,956,762,808,716,878,73,333,263,9,523,870,158,738,255,101,552,39,506,186,903,779,825,537,11,333,640,651,312,297,333,459,624,293,452,321,143,21,612,609,701,639,368,998,425,400,544,962,150,486,344,546,283,922,225,811,245,692,554,190,191,666,907,538,805,939,378,26,95,670,40,771,541,542,899,502,580,594,731,190,819,997,78,189,270,879,987,92,419,825,267,577,755,669,709,319,800,52,74,794,131,326,99,157,514,969,697,55,554,356,622,717,471,37,21,882,174,603,198,890,352,598,980,462,112,300,19,915,782,809,435,260,738,653,953,496,486,692,109,950,252,87,19,372,46,878,851,38,149,959,8,438,705,286,21,604,144,175,183,666,69,913,319,587,867,373,77,200,389,415,678,175,680,331,984,828,671,516,242,199,702,625,411,188,159,794,332,972,961,274,120,697,594,910,144,260,91,323,413,858,851,811,589,653,289,794,903,80,879,16,737,553,225,644,382,860,519,515,486,226,392,430,264,660,841,156,75,581,583,424,555,679,659,128,704,156,987,186,3,607,262,487,493,718,108,588,198,126,956", +"869,75,921,713,263,481,270,727,697,676,89,240,326,44,856,825,582,36,864,711,660,828,424,500,649,632,148,23,257,683,163,663,410,962,500,917,43,947,387,606,648,835,208,294,702,300,920,954,989,785,204,944,815,671,503,437,775,515,172,305,332,484,359,827,37,662,777,521,621,73,832,666,30,817,728,901,800,398,141,316,173,858,805,391,510,238,804,595,832,991,301,196,219,79,987,42,445,191,431,268,178,756,511,826,840,859,765,551,20,335,324,273,757,137,408,502,119,266,81,94,328,14,878,819,768,234,645,95,345,835,739,719,292,22,818,889,552,982,791,19,449,404,85,1000,857,551,822,322,469,572,490,440,278,608,920,160,445,221,391,306,710,406,876,750,248,546,285,719,797,427,776,283,414,178,315,518,369,658,253,150,656,831,65,303,437,874,649,123,423,399,188,759,327,138,829,913,894,722,393,863,494,592,106,823,126,773,469,462,906,320,108,487,665,807,101,796,136,773,520,411,243,248,417,385,348,918,624,0,731,129,493,586,38,903,682,357,654,277,575,659,932,231,267,26,877,83,241,137,305,999,156,407,316,53,116,898,166,608,664,592,900,95,875,847,174,983,833,485,308,947,500,748,625,135,498,832,115,30,143,227,856,232,648,817,849,796,229,247,52,602,750,380,677,467,650,708,731,728,306,230,863,237,984,516,820,281,480,608,407,453,165,601,295,748,479,812,825,441,874,129,356,990,21,99,956,404,648,579,352,432,722,464,66,316,504,823,2,958,794,681,586,607,325,35,116,21,336,361,539,748,893,887,688,863,690,296,453,771,433,71,855,73,86,680,12,551,283,590,678,222,492,940,476,265,496,772,530,364,505,335,347,671,624,175,773,818,434,354,284,939,629,911,313,376,824,414,702,798,801,197,315,481,786,148,842,863,917,805,859,124,335,811,436,519,801,98,108,229,695,153,842,701,492,891,788,48,846,300,607,375,25,821,757,195,229,889,710,882,866,263,570,75,783,98,640,491,598,199,585,301,152,883,521,900,721,340,989,693,962,2,640,384,349,956,913,773,937,983,979,255,700,291,831,738,869,900,424,302,379,847,317,296,729,369,854,825,242,810,615,589,349,313,63,198,509,34,310,890,344,813,19,13,27,583,921,392,218,533,606,379,28,66,510,117,227,688,579,179,700,761,105,147,668,22,162,411,613,678,954,475,878,375,886,229,413,255,85,535,430,798,421,984,65,339,620,597,695,441,672,525,785,390,919,732,557,515,554,731,545,189,696,273,694,151,440,263,208,490,609,971,204,895,699,709,56,645,813,63,844,493,965,908,642,89,651,846,241,219,59,501,428,946,384,354,623,839,485,518,160,457,861,592,11,499,907,298,24,707,699,780,888,71,166,182,706,503,690,690,770,830,214,303,970,720,506,918,832,123,791,321,645,4,19,404,841,318,351,361,707,124,528,230,319,854,442,629,766,364,573,921,696,488,38,833,436,503,504,130,730,181,379,891,995,906,728,993,398,275,12,484,934,465,683,891,737,691,526,997,720,420,417,828,292,48,218,933,126,355,748,642,322,720,316,209,701,650,887,119,730,92,577,257,682,633,309,545,273,214,75,132,57,351,829,118,837,307,998,421,417,523,772,898,494,371,768,758,739,831,367,722,852,157,14,608,964,741,576,132,959,537,21,544,388,890,877,49,375,788,406,502,251,918,231,693,248,551,398,448,948,655,153,739,930,318,507,142,18,376,233,711,51,395,2,477,8,320,312,368,938,50,12,987,438,241,308,487,11,400,583,546,53,515,810,100,167,932,873,861,338,374,506,253,179,451,356,722,181,637,110,192,696,162,104,430,111,993,265,987,119,6,192,100,706,238,214,436,879,400,754,526,104,758,24,236,117,104,119,787,525,150,676,332,885,710,613,938,574,894,326,219,722,996,426,169,889,253,931,490,746,10,857,660,630,652,842,395,445,236,364,156,536,715,846,873,24,770,797,414,595,985,786,809,262,426,861,583,97,207,915,854,992,483,990,788,285,196,3,432,194,975,501,721,341,490,607,593,395,290,978,400,328,493,860,100,400,214,679,67,429,63,817,19,31,558,712,601,347,261,83,865,213,346,827,230,686,804,252,601,297,53,727,567,570,48,868,998,300,98,41,836,340,838,853,484,81,353,854,330,784,746,382,101,931,434,963,509,589,250,548,496,397,527,834,8,711,577,519,13,767,434,112,368,960,504,605,740,834,392,495,674,124,746,239,724,524,144,138,506,402,882", +"700,199,368,503,433,776,942,574,926,435,91,58,454,996,909,813,44,326,237,464,72,19,858,482,596,996,629,187,952,745,262,26,878,218,269,75,408,373,885,177,778,491,20,320,53,755,917,365,427,787,406,84,802,650,385,681,982,403,579,79,989,834,60,670,760,968,275,763,570,962,760,425,833,738,132,103,812,154,963,449,307,5,983,102,742,84,862,600,740,835,204,881,862,194,318,657,42,260,934,450,623,706,876,701,902,178,122,724,378,456,599,276,507,920,79,100,49,500,89,674,467,531,370,31,104,667,449,738,25,394,794,258,630,562,191,287,832,131,902,762,4,163,593,786,671,722,133,446,266,235,969,149,193,152,5,384,43,706,554,897,919,353,602,611,914,429,102,188,296,901,98,960,195,154,363,992,399,666,361,137,378,196,220,229,609,571,853,85,132,668,879,231,468,835,571,932,528,482,731,705,271,28,636,956,736,450,170,461,51,436,202,627,20,985,374,511,727,194,891,348,688,37,703,335,251,470,250,731,0,210,33,138,699,281,980,750,801,782,87,452,700,407,619,947,307,662,90,46,694,644,474,149,963,336,195,639,80,737,432,364,267,664,513,406,825,202,151,881,593,530,712,485,328,58,245,952,614,692,467,650,840,666,986,592,780,186,417,287,979,786,884,776,755,308,206,961,947,102,519,796,741,739,743,653,791,32,343,128,215,502,950,960,325,61,285,838,28,193,508,583,977,697,486,838,854,114,25,228,176,96,743,822,597,389,49,853,940,77,26,96,580,594,282,529,222,306,478,260,721,313,884,230,415,316,580,646,781,605,196,132,268,180,668,521,111,174,501,994,118,552,906,932,474,457,852,7,555,193,984,364,231,856,577,218,280,805,882,299,730,380,975,340,915,71,395,489,889,818,628,342,715,402,759,646,539,640,891,287,41,372,361,968,94,226,816,217,937,739,643,660,401,714,162,290,660,911,404,512,456,585,285,640,35,452,994,11,960,613,396,467,86,55,44,295,43,372,633,894,50,167,565,27,376,387,149,285,522,285,490,792,303,431,569,78,846,731,557,980,203,917,379,568,385,388,330,989,831,918,847,901,83,191,109,839,699,796,493,937,100,767,604,577,866,628,813,555,963,422,335,152,378,458,17,959,756,760,947,774,429,720,457,642,779,993,877,440,528,568,771,342,844,588,818,151,455,961,833,538,364,108,776,689,25,244,639,842,90,676,321,964,740,496,766,931,332,858,151,632,583,885,784,871,223,968,616,632,417,902,929,41,551,188,569,125,286,605,563,101,291,707,19,83,101,910,165,224,302,597,495,993,388,266,780,223,543,4,223,233,316,255,885,118,120,632,549,797,757,184,268,971,232,67,773,951,72,979,765,94,796,773,979,582,960,680,254,349,497,166,574,797,393,697,175,72,949,538,332,675,494,976,927,508,130,867,250,481,869,371,889,386,700,758,216,307,234,230,827,970,485,695,808,16,665,761,890,36,265,985,308,392,54,683,9,702,592,615,936,850,835,22,213,464,392,400,949,722,866,329,760,368,559,860,63,884,902,153,288,713,685,884,724,434,157,565,497,909,445,361,802,634,241,653,921,115,219,876,481,706,222,711,497,550,265,782,992,725,623,594,252,252,65,993,251,125,813,71,973,360,226,772,685,124,840,259,516,397,892,978,738,407,209,124,993,135,126,651,810,112,729,855,385,870,766,695,100,443,547,920,259,739,394,558,149,940,667,925,470,199,756,217,834,591,830,475,499,130,440,222,597,408,741,501,366,342,668,862,598,64,108,409,886,151,715,363,330,601,747,394,132,158,876,163,883,606,298,597,171,658,289,701,555,344,433,207,469,294,156,639,108,924,372,490,13,427,394,376,300,411,556,535,608,941,973,756,835,377,869,460,170,730,260,987,336,346,293,945,62,290,961,285,238,526,540,860,686,198,492,969,452,763,422,837,727,306,86,265,378,703,709,443,125,491,91,710,406,831,183,546,91,52,211,377,362,727,685,603,988,815,167,511,426,490,969,92,506,67,480,995,946,431,713,722,700,285,559,637,182,670,874,109,581,741,210,511,809,957,315,998,107,804,42,539,947,87,582,370,509,908,789,947,743,562,772,426,507,32,974,862,768,838,751,902,797,64,6,528,954,716,299,494,841,897,192,868,164,339,711,311,317,974,112,676,330,42,629,236,33,404,885,415,372,794,295,517,405,967,421,876,147,865,88,867,696,369,12,681,261,269,94,917,313,94,359,553,58,828,978,817,141,747", +"182,145,294,588,940,586,671,839,581,637,847,859,652,809,844,83,641,603,731,42,119,424,327,831,519,141,93,582,887,654,156,196,313,140,715,430,616,907,885,501,637,314,165,638,927,858,515,585,656,483,819,570,825,348,205,764,796,795,894,289,912,318,980,756,197,482,501,165,924,152,4,572,700,778,539,140,209,254,131,458,762,613,4,351,368,972,682,678,933,688,17,810,233,246,787,121,429,362,528,161,246,17,716,804,507,466,569,569,715,952,899,108,109,590,506,21,734,465,459,802,596,489,406,836,388,947,856,828,952,416,330,10,321,862,423,479,564,271,636,588,886,171,829,299,804,645,303,753,657,251,81,838,759,171,300,857,377,484,471,333,554,772,426,506,284,79,891,79,306,747,926,615,272,681,251,625,739,953,442,527,31,57,203,161,489,156,480,296,638,410,773,428,766,155,387,782,251,965,518,122,67,410,305,218,792,75,505,811,134,575,84,725,260,273,463,866,19,439,463,806,959,681,400,176,634,870,997,129,210,0,381,797,620,202,74,840,171,743,138,427,545,660,660,148,885,966,433,768,902,975,823,801,866,305,376,866,642,973,39,603,510,748,352,691,689,90,70,240,817,442,293,526,553,451,340,729,932,723,112,311,780,871,523,924,603,847,274,883,92,932,715,909,863,642,692,276,39,42,761,180,241,793,836,628,262,390,16,89,916,173,1000,786,5,898,538,27,1,818,660,785,639,99,711,601,694,631,717,234,289,275,296,647,26,624,430,999,145,591,794,575,73,631,559,999,468,640,570,495,608,999,754,274,936,950,370,901,140,257,599,15,969,302,468,19,833,276,4,819,678,719,94,363,357,138,998,180,269,375,707,350,9,304,671,647,599,239,693,851,428,758,478,388,468,27,664,45,978,685,951,587,212,295,730,572,532,291,779,848,880,897,828,190,392,269,778,104,563,89,158,763,648,64,742,917,694,120,434,435,210,531,938,86,767,814,473,89,677,585,253,220,530,637,276,884,541,208,13,145,895,434,478,161,135,397,399,328,236,81,485,225,57,325,887,228,935,578,815,122,961,322,577,201,550,162,576,774,139,849,642,581,734,808,618,311,912,580,224,491,835,713,521,467,450,249,727,724,754,607,246,860,246,439,177,868,296,224,513,364,217,784,149,713,386,231,82,480,178,792,314,122,722,230,108,891,267,662,352,600,163,972,768,639,419,386,725,324,998,491,740,513,538,445,322,897,791,335,568,816,306,931,69,463,1000,308,916,947,930,847,216,152,405,57,594,882,645,948,484,313,449,566,394,315,319,416,760,226,402,98,300,97,629,908,211,688,137,961,289,879,427,652,432,663,466,964,191,640,569,622,821,833,2,66,446,816,905,97,825,164,679,714,814,869,225,726,783,686,271,269,181,308,511,369,581,888,94,195,320,784,94,969,370,393,621,5,144,403,510,588,708,187,629,360,304,348,147,750,153,257,292,648,531,129,433,565,842,146,970,428,110,562,417,106,369,246,439,985,234,370,292,675,813,83,545,912,737,472,963,461,121,732,226,115,665,250,780,571,840,689,230,215,47,216,994,442,396,568,559,874,222,209,635,437,317,326,959,864,471,81,870,184,742,413,579,119,518,275,273,250,933,571,955,622,801,347,54,487,506,23,598,172,83,890,404,154,986,537,182,283,968,615,776,886,479,545,357,636,840,54,827,256,955,977,146,548,439,332,717,818,303,967,499,718,433,987,438,648,736,659,324,30,962,783,459,898,501,418,36,636,303,69,877,273,734,13,612,622,184,415,71,354,20,488,253,863,807,65,244,523,220,726,287,587,889,871,552,492,614,376,950,833,475,306,970,429,650,13,16,66,204,657,962,400,62,383,237,755,481,42,583,313,177,913,975,916,790,830,854,841,223,736,933,633,140,476,10,835,368,793,309,285,121,36,114,837,520,160,834,641,743,581,575,448,912,46,173,503,672,7,901,506,338,932,395,265,499,895,868,892,57,214,824,623,740,479,706,712,653,827,503,930,13,899,272,417,202,728,963,202,616,522,462,444,396,854,850,296,802,744,495,647,543,59,901,165,669,914,571,373,104,989,202,22,846,821,454,714,524,275,682,393,230,218,743,708,238,189,176,998,461,940,126,142,899,904,547,730,849,472,479,738,247,106,204,759,714,476,203,248,928,331,434,867,622,216,212,905,765,857,918,985,929,497,622,345,610,357,602,873,74,389,708,534,7,686,739,4,615,401,593,661,717,833,601,207,399,76,874,813,573,861", +"507,705,743,513,597,175,785,948,527,505,808,61,382,145,423,955,812,107,806,905,418,178,110,537,26,434,72,774,908,253,146,911,532,59,327,796,60,826,976,176,53,629,356,901,442,909,346,107,660,607,214,871,88,21,185,299,548,319,756,223,80,63,671,439,114,479,852,52,843,783,245,846,988,711,652,819,876,434,794,516,524,934,991,737,337,358,739,274,483,679,157,394,988,214,671,69,199,637,877,549,447,859,641,912,462,270,423,553,138,94,860,697,531,404,739,775,96,530,395,972,815,518,211,642,179,154,750,322,894,986,627,893,656,64,667,418,121,75,377,305,932,652,336,774,603,181,515,727,798,808,875,84,834,528,809,182,542,886,895,311,898,464,892,889,891,280,129,179,544,138,23,507,993,937,182,195,477,167,470,288,848,686,756,440,221,595,786,213,404,429,397,341,409,179,267,36,637,113,137,66,608,150,94,122,413,76,444,948,600,355,452,414,718,663,355,339,602,579,479,950,947,836,789,146,236,352,676,493,33,381,0,139,23,833,745,359,455,482,615,745,849,766,486,237,399,786,956,528,637,660,914,318,397,204,711,576,658,845,215,634,839,285,615,142,210,504,963,140,191,432,299,21,923,74,701,711,796,40,826,775,27,991,22,886,268,817,674,89,183,166,566,176,1,140,798,320,159,238,464,248,734,47,72,805,594,708,447,644,959,688,294,968,204,950,685,792,875,46,415,470,823,947,742,778,108,716,153,66,143,563,366,996,227,655,57,371,926,703,850,279,202,750,609,273,812,569,734,394,905,676,71,40,423,73,563,176,538,926,400,414,953,980,390,60,280,841,103,939,657,751,399,139,618,932,438,137,232,821,876,931,887,4,362,451,225,529,771,665,438,406,759,94,72,681,393,771,810,112,796,390,586,206,653,436,984,273,873,334,889,611,865,626,411,579,795,296,860,456,222,170,961,801,37,961,889,989,118,33,303,111,225,437,722,755,381,190,32,744,976,561,64,721,939,774,408,174,32,149,962,341,340,627,579,183,894,706,10,7,8,110,416,881,237,627,257,981,852,911,699,629,844,336,516,935,510,108,73,984,733,81,498,268,473,508,882,253,794,201,724,195,497,772,418,33,284,121,858,728,891,830,921,473,27,287,898,758,161,493,587,4,638,799,741,364,350,154,766,97,806,914,685,777,452,559,370,988,57,784,712,8,339,534,101,168,214,717,149,155,21,857,510,109,937,241,297,551,866,17,350,759,973,131,685,223,712,334,980,327,112,420,639,613,55,452,53,510,270,966,152,432,287,528,810,783,456,943,194,628,656,853,33,998,127,667,65,554,26,135,208,940,614,178,463,385,497,282,764,87,304,84,203,936,869,209,654,302,578,602,349,952,968,314,764,882,233,561,231,751,711,859,329,954,545,904,596,869,29,77,989,705,164,371,405,471,117,337,598,29,893,910,34,695,521,260,315,887,873,245,157,884,686,480,5,286,525,453,556,877,868,876,944,163,390,359,989,684,333,872,785,119,442,195,63,533,342,924,285,822,527,56,253,641,978,938,410,623,325,785,869,829,689,66,219,234,243,817,38,345,853,79,55,36,575,87,267,7,389,707,507,545,684,14,779,223,851,50,172,416,31,291,59,712,175,2,895,983,952,176,37,401,190,540,724,378,940,632,759,389,848,173,948,370,900,614,685,646,654,305,884,472,717,833,325,91,463,568,6,159,904,377,262,365,141,93,781,167,639,258,256,318,901,51,789,830,977,353,348,384,867,890,416,681,485,468,931,543,757,252,930,871,93,43,618,879,486,677,227,261,404,978,84,28,79,963,691,816,299,971,81,74,663,446,383,970,744,536,75,381,940,80,36,811,811,176,500,383,893,872,481,25,629,22,347,931,991,392,395,153,430,477,994,667,348,679,491,810,934,243,771,617,50,758,310,55,848,935,932,632,812,680,926,327,612,22,858,378,135,562,174,412,421,599,834,734,551,976,277,364,834,886,429,4,955,797,111,355,814,97,147,12,905,351,758,670,526,829,218,629,923,594,321,146,130,795,120,637,583,755,542,896,2,500,765,851,71,280,776,634,174,619,716,789,153,785,683,761,829,940,832,572,912,835,696,718,523,495,335,815,485,455,811,528,983,29,164,689,547,517,678,311,251,736,859,952,223,757,34,357,546,179,127,790,540,668,329,734,170,637,110,647,978,845,831,451,806,18,839,922,6,113,358,827,398,474,277,435,673,617,524,549,112,932,657,349,946,237,913,378,919,452", +"389,227,78,833,706,168,569,234,309,729,110,174,618,441,998,814,895,428,973,689,212,638,912,226,948,292,289,730,769,855,764,121,132,109,10,204,201,270,694,421,884,246,221,430,252,418,711,853,44,22,236,137,447,180,491,248,148,307,763,576,274,245,881,203,343,285,93,556,478,449,459,78,665,814,579,318,303,672,668,274,701,121,908,996,948,310,61,570,501,345,369,571,548,256,572,851,317,43,306,898,572,706,444,353,579,378,398,820,695,797,775,94,439,747,898,530,367,447,937,314,274,635,287,499,155,400,801,977,295,685,49,417,861,276,460,909,274,995,730,889,457,639,822,400,61,920,646,249,788,928,731,570,243,39,265,985,266,761,843,261,777,574,385,903,837,592,782,827,62,897,64,463,968,261,364,514,887,53,110,479,43,511,260,665,120,134,945,788,550,874,310,457,713,372,836,969,171,923,377,470,26,580,11,450,671,885,247,373,78,414,819,218,970,954,370,735,256,427,200,199,365,496,454,668,367,375,415,586,138,797,139,0,441,962,243,585,134,265,319,745,730,239,493,933,711,963,92,854,401,982,71,711,422,42,887,885,392,570,806,293,763,573,639,874,975,16,753,971,141,149,585,291,59,514,698,666,897,806,657,309,552,94,13,547,155,614,150,378,316,818,830,991,283,810,628,884,576,849,705,417,756,721,836,149,431,795,489,348,818,598,175,280,709,353,776,491,168,602,348,783,488,635,259,872,704,260,25,976,400,75,559,855,915,731,775,201,893,385,105,143,485,699,266,716,476,738,457,700,898,171,212,551,83,65,153,86,67,244,540,457,541,103,307,864,533,425,597,411,995,615,908,236,867,176,355,877,645,564,42,436,376,671,126,532,635,590,560,663,157,749,838,219,752,985,9,567,515,260,31,308,988,410,335,933,91,204,615,372,783,180,833,458,679,35,21,222,472,916,216,979,859,32,715,122,77,781,520,188,124,485,550,85,88,441,484,901,57,417,854,359,175,958,861,341,480,965,541,207,350,559,335,142,342,753,657,906,350,881,109,167,873,308,257,152,132,967,771,613,817,959,106,170,551,10,54,582,622,455,784,264,632,3,390,680,414,473,84,390,560,227,401,29,661,540,867,188,65,391,724,303,677,913,315,273,502,99,585,748,855,10,716,63,187,448,808,123,643,505,399,104,737,326,102,134,323,84,718,815,550,549,821,676,16,263,794,599,150,504,859,465,990,867,498,109,990,736,607,617,168,409,512,999,154,965,793,792,495,181,687,637,49,174,923,998,60,221,139,226,836,964,254,766,77,182,546,323,976,405,657,127,890,711,173,159,8,741,580,676,812,856,645,856,795,377,763,241,199,209,763,572,89,15,491,773,969,691,626,468,878,698,488,322,637,497,573,932,363,497,38,796,427,858,767,88,870,668,347,417,267,840,534,972,956,985,913,813,715,69,321,817,636,246,414,160,175,865,513,114,289,762,654,409,856,671,756,955,251,457,832,123,788,36,536,479,917,841,838,21,760,952,938,302,951,756,253,537,155,121,716,22,891,535,179,636,434,155,481,93,864,274,183,724,624,588,789,879,287,231,437,214,452,611,726,452,144,996,777,87,28,558,961,765,760,605,91,655,234,438,44,620,224,478,814,112,161,720,584,805,24,187,891,285,397,94,85,616,452,145,836,911,18,935,795,882,639,507,988,40,638,58,208,176,159,636,366,275,772,716,73,903,199,986,812,289,746,955,275,272,900,883,863,116,737,530,255,334,360,267,278,886,37,855,252,890,201,63,768,827,254,939,875,819,662,139,522,11,119,15,986,593,399,978,729,297,286,616,495,175,136,188,170,121,41,692,400,697,539,599,832,688,562,491,385,601,867,993,628,889,646,202,751,28,281,93,122,747,825,319,6,299,784,684,770,776,535,498,696,37,405,828,60,936,906,807,405,415,533,5,622,279,692,884,482,779,535,369,985,512,186,667,428,877,268,657,374,56,725,76,494,470,586,968,151,819,588,859,565,627,955,769,467,349,960,316,671,845,805,955,550,626,332,976,765,803,801,372,938,7,555,253,299,103,473,375,756,132,517,651,660,225,511,418,476,496,331,675,803,940,658,773,929,239,64,790,22,61,720,999,823,730,26,919,742,504,661,265,471,807,718,655,789,299,774,691,47,167,859,459,260,519,372,411,734,367,176,501,953,740,552,751,629,380,970,311,97,749,852,541,250,135,394,173,710,900,518,937,39,167,242,760,92,865,205,325,348,369,810,542,549,255", +"263,66,415,440,38,591,805,389,884,232,311,385,136,106,301,429,853,845,478,580,132,438,592,159,255,69,694,916,206,427,631,768,142,473,649,165,510,771,59,539,157,74,339,331,681,729,552,92,230,896,569,840,726,635,535,57,56,39,25,572,441,745,330,312,404,954,32,847,413,532,958,644,537,29,783,739,924,209,561,776,331,228,176,942,576,413,842,331,316,124,162,495,200,217,286,952,741,117,748,643,867,473,375,999,396,262,357,359,283,94,408,925,857,6,27,681,301,919,250,976,265,179,661,768,437,891,356,552,811,753,173,136,284,824,147,549,99,976,744,158,760,105,142,989,445,906,512,43,922,41,246,706,136,442,674,563,489,931,41,923,868,394,4,142,810,819,318,398,920,730,704,157,226,296,835,887,881,984,464,367,42,436,688,755,24,284,625,811,237,426,815,10,447,348,837,528,154,269,792,775,895,40,478,126,576,857,587,330,404,736,134,303,205,56,303,19,601,587,111,914,398,198,930,367,384,458,49,38,699,620,23,441,0,842,620,236,927,994,102,53,801,579,238,433,344,854,7,429,891,736,841,996,330,461,579,999,902,854,996,71,464,599,289,178,93,502,300,956,8,153,320,451,968,609,623,875,637,826,149,317,598,30,794,861,176,607,29,280,739,745,710,169,598,216,513,245,848,839,454,142,41,673,76,525,246,851,602,510,542,458,915,847,692,418,968,234,422,284,483,650,573,522,249,315,668,575,587,696,295,833,684,634,393,825,749,512,98,995,724,596,504,928,489,779,685,291,304,314,587,716,555,675,359,153,890,858,225,221,925,277,238,148,178,580,244,695,212,789,763,334,913,243,120,399,71,21,248,74,752,432,662,533,311,3,845,963,978,109,344,631,700,688,149,592,837,796,574,611,145,885,124,945,148,625,894,481,162,819,796,619,858,868,347,597,84,64,225,444,179,898,25,115,19,123,583,197,854,52,416,95,432,574,987,21,322,646,863,870,312,351,558,71,816,374,343,995,379,29,23,352,740,478,839,105,943,569,259,175,104,917,122,655,195,266,54,412,152,449,19,897,32,98,891,939,406,851,308,222,288,735,419,113,902,385,295,491,759,178,877,648,449,558,801,783,575,497,729,505,338,934,803,381,902,349,54,819,134,339,100,263,909,695,613,697,494,653,436,317,229,490,518,881,640,289,21,402,302,111,268,256,456,483,226,13,385,3,66,850,970,426,192,638,762,21,446,785,568,554,359,399,929,319,47,404,272,97,582,433,622,6,122,364,950,61,971,108,985,258,760,536,263,113,822,501,923,581,19,815,415,999,510,272,375,140,769,4,844,630,967,522,712,244,63,200,134,628,880,541,507,885,83,282,197,239,625,173,727,414,604,925,610,803,842,132,666,387,347,599,831,627,164,91,145,642,173,917,527,612,314,439,13,592,221,782,547,406,447,339,673,611,727,296,47,763,199,590,256,949,583,123,703,507,804,133,994,684,157,871,568,537,947,935,309,187,249,523,669,151,78,591,723,347,498,579,665,359,288,63,181,559,72,460,228,946,464,203,292,475,916,840,819,674,536,891,538,597,287,90,545,72,23,546,769,301,22,440,250,397,418,93,209,627,329,314,443,515,414,33,371,891,113,798,842,518,230,126,145,261,940,88,620,823,492,265,97,340,493,775,855,744,949,406,941,199,141,940,870,839,910,117,923,948,164,945,132,181,259,230,652,623,805,563,607,409,691,850,848,637,830,889,198,664,289,485,965,378,727,953,516,898,54,535,662,457,146,101,62,955,460,356,69,234,729,405,669,340,369,945,626,64,723,844,515,347,131,469,940,27,894,767,489,15,543,393,803,713,390,890,110,132,89,422,786,826,39,758,516,859,994,979,837,172,89,293,46,238,659,981,246,152,538,766,906,428,666,378,754,42,762,498,203,869,600,902,376,267,511,905,455,345,555,949,666,420,942,146,336,586,71,261,405,470,73,952,882,826,131,651,383,662,569,995,985,763,668,889,761,136,266,492,169,954,87,216,152,610,44,39,795,826,912,583,830,837,338,301,87,852,251,317,74,4,478,694,285,475,5,322,540,528,83,249,407,484,18,539,353,532,376,394,888,49,959,209,106,632,942,73,748,902,413,993,580,597,780,518,263,217,73,916,155,104,577,640,551,613,997,519,363,760,990,899,872,457,423,487,463,160,653,196,138,452,599,445,351,295,913,157,90,359,62,342,406,312,737,95,994,669,727,897,432,342,44,842,508,429,544,626,482,324", +"88,620,23,189,330,206,232,326,887,145,977,73,870,40,201,679,725,444,166,213,783,332,511,489,430,542,813,623,239,841,153,930,96,528,618,767,826,292,898,636,618,315,812,852,213,676,85,395,999,764,638,465,566,40,191,538,453,261,18,944,727,884,882,566,101,587,652,362,971,977,371,441,77,204,133,676,184,580,651,258,796,664,411,872,329,70,23,147,10,205,905,930,18,89,994,316,608,692,623,245,78,764,603,905,107,784,266,947,964,900,858,184,530,618,174,130,872,776,282,437,326,941,521,368,784,664,761,285,662,828,780,841,131,313,165,424,309,569,700,886,194,818,256,577,141,716,786,699,942,547,598,4,903,657,347,307,281,32,591,296,699,385,918,225,467,675,493,330,823,129,624,694,784,179,187,275,728,724,571,810,300,511,461,114,355,897,461,105,761,826,395,629,493,842,742,803,358,471,996,94,539,109,191,143,596,901,424,225,570,249,588,894,307,970,598,739,504,592,886,187,783,333,798,652,337,867,673,903,281,202,833,962,842,0,582,496,953,101,350,965,573,778,43,179,634,594,142,578,640,496,837,687,945,837,6,307,544,113,784,138,145,548,588,33,854,858,42,893,47,256,417,495,282,936,172,523,40,286,165,920,896,957,208,744,443,663,759,541,175,424,399,387,650,766,235,370,406,662,576,690,860,361,406,282,880,48,747,164,982,500,154,760,85,780,216,369,631,518,861,4,512,288,752,53,447,360,629,19,341,238,105,829,666,348,630,841,909,717,815,328,406,923,732,315,580,64,144,891,195,179,854,642,213,507,151,340,675,660,36,369,713,560,40,606,825,639,441,954,569,173,173,395,868,453,805,561,399,990,640,14,296,40,337,250,860,639,768,511,779,862,52,508,908,711,377,309,828,70,76,583,190,210,339,740,329,15,329,458,385,204,788,594,476,861,683,659,671,639,784,42,253,707,109,87,527,458,215,898,74,433,169,75,497,156,461,934,297,299,554,180,531,129,823,23,426,109,242,713,995,603,456,947,308,859,678,954,657,835,949,599,825,870,586,787,619,246,915,722,848,424,47,33,219,601,56,97,227,24,861,319,851,810,624,947,502,824,858,27,411,40,872,209,519,756,204,714,439,198,477,896,364,352,896,145,106,971,61,40,223,463,45,377,883,332,424,346,573,296,92,626,143,900,339,742,617,816,999,584,547,492,992,749,213,129,199,744,852,508,544,972,645,73,335,528,834,620,439,632,213,341,941,473,972,289,827,78,698,213,862,300,836,104,566,826,512,910,302,18,948,131,398,200,511,651,750,948,60,944,392,909,794,996,16,121,577,282,300,343,137,703,449,322,687,324,596,666,930,135,372,835,302,909,886,926,771,514,814,679,150,137,275,576,203,435,18,180,200,894,138,611,45,840,853,326,212,323,368,188,619,448,677,222,714,73,370,606,365,76,178,907,486,743,250,433,254,862,517,804,280,238,592,417,895,380,234,758,543,335,398,220,414,997,463,887,880,356,628,125,72,185,720,142,130,717,761,716,8,25,396,675,526,745,184,389,659,554,700,379,433,706,292,263,274,534,659,767,717,506,848,227,292,100,138,543,826,225,348,710,993,639,833,231,734,935,698,266,851,193,575,608,612,923,88,278,663,591,255,245,295,350,72,729,483,591,11,588,913,569,86,267,589,3,874,354,16,663,100,624,354,607,290,861,796,871,736,89,403,926,24,827,479,317,406,366,844,22,116,896,90,99,811,908,806,438,142,665,944,73,383,824,987,650,538,33,599,89,506,40,849,612,70,419,316,951,328,385,555,575,813,718,474,810,561,118,341,622,70,985,182,388,713,319,402,990,307,298,412,382,974,249,670,276,404,37,337,899,539,139,427,180,956,596,302,680,874,324,546,937,537,238,164,830,758,586,78,706,750,114,341,828,880,859,98,462,916,928,112,790,173,897,171,280,440,319,454,69,17,897,118,57,726,324,231,240,295,300,677,864,315,34,102,426,168,726,242,42,566,654,278,74,704,391,613,515,516,848,955,339,275,815,946,366,687,675,837,491,336,568,819,623,852,517,644,754,793,670,121,947,684,807,364,181,719,520,130,897,578,700,388,773,498,76,726,851,847,573,4,727,446,618,999,526,459,719,913,450,570,612,541,709,773,778,628,3,693,253,812,216,135,514,292,448,664,951,4,138,628,394,808,819,822,740,49,370,160,471,129,11,616,680,686,581,847,389,757,333,737,695,134,402,228,549,990,188,744,855,669,914,438,627", +"291,982,434,241,856,784,328,594,512,282,927,644,184,451,319,570,276,836,932,387,266,149,65,219,80,565,811,721,883,527,146,856,359,990,597,745,23,219,823,35,477,464,817,4,403,529,390,825,754,778,904,621,270,431,43,65,810,680,241,536,416,963,916,170,814,479,873,586,743,741,493,27,114,417,986,354,761,652,132,591,76,180,387,865,691,260,675,825,863,803,457,780,917,965,322,521,429,579,659,759,26,112,418,117,302,780,751,403,541,254,919,821,69,55,223,265,360,426,537,170,154,5,553,703,362,266,487,495,333,375,726,505,282,740,550,739,631,50,713,12,148,381,233,111,862,311,67,886,772,483,548,756,44,251,162,749,113,322,474,337,770,224,237,653,412,246,595,7,783,933,350,255,53,372,673,85,430,22,159,116,466,523,508,433,92,905,587,506,597,16,288,222,146,334,19,65,348,431,553,150,110,130,694,446,347,848,773,343,597,849,751,332,32,320,771,535,160,1,438,86,164,99,727,931,467,675,123,682,980,74,745,243,620,582,0,490,99,101,331,138,681,223,977,56,967,747,895,699,319,673,992,217,745,320,643,296,904,528,400,35,619,482,10,473,594,531,895,450,457,122,424,829,370,778,562,475,925,62,799,292,947,786,53,868,390,223,679,529,571,694,749,400,477,592,678,977,568,771,145,888,687,761,72,521,209,683,606,616,380,600,235,586,220,492,56,929,975,646,999,862,823,619,84,708,386,179,168,959,558,866,468,742,853,636,971,567,697,211,802,438,523,872,814,280,379,886,148,461,267,712,281,279,157,615,536,266,331,838,614,151,7,258,25,698,4,219,532,835,498,425,341,249,393,640,293,41,67,111,945,27,142,299,961,873,561,745,312,53,937,406,595,89,102,595,508,183,672,477,828,700,188,846,994,645,11,16,385,649,218,419,648,245,376,13,718,295,130,309,872,376,174,343,176,843,503,403,414,975,152,828,982,653,960,913,297,561,396,441,967,55,233,225,190,461,809,624,386,102,4,743,175,897,650,447,921,563,444,208,629,181,174,562,112,746,643,702,919,745,561,955,741,825,414,271,108,852,882,171,529,311,303,918,433,20,123,895,918,54,293,420,373,61,392,357,883,464,523,992,519,320,449,862,657,703,651,282,647,269,80,740,779,658,813,930,806,729,105,428,308,554,148,345,784,466,729,544,152,461,644,928,216,926,917,651,731,999,679,448,53,597,873,392,579,857,439,577,885,54,341,788,53,357,373,35,785,131,106,377,63,844,779,637,902,762,453,877,308,909,383,967,317,917,594,241,221,951,225,115,916,94,535,278,852,763,420,607,492,785,985,824,717,260,76,325,783,90,985,36,876,893,162,176,867,102,449,507,65,708,238,859,32,13,398,762,711,839,378,78,924,779,744,191,974,199,634,58,58,503,910,82,894,65,725,930,43,804,728,524,378,719,503,537,903,432,120,659,802,734,185,431,233,34,581,651,923,957,154,419,803,432,215,999,792,198,538,944,671,865,565,481,695,645,144,505,715,343,924,807,160,314,488,901,266,449,611,92,525,667,339,266,806,330,992,16,879,970,933,18,262,454,42,720,438,329,794,217,572,824,133,489,946,192,30,221,153,383,799,992,751,651,496,197,883,420,336,3,57,426,785,853,8,599,973,932,862,730,727,487,874,186,15,780,271,485,397,829,903,702,237,470,737,831,719,665,3,993,709,76,566,529,210,569,361,970,852,653,350,581,471,656,582,304,432,139,785,301,949,643,825,308,384,892,775,126,956,651,763,749,35,124,83,319,789,874,108,885,216,702,999,651,559,729,652,846,296,103,645,44,837,951,319,937,228,384,395,317,877,857,369,657,720,812,419,861,536,463,106,777,714,628,328,213,516,785,575,787,305,575,634,979,643,480,44,165,260,627,434,37,165,192,535,261,44,796,408,756,100,990,411,622,80,916,323,878,67,768,811,8,132,551,462,29,504,615,160,307,382,376,434,198,15,875,165,353,374,554,254,566,15,67,709,16,15,329,308,311,144,313,261,82,363,401,453,543,122,830,670,216,623,141,369,358,790,533,138,332,394,793,244,686,636,37,158,347,74,12,493,904,850,314,906,999,862,83,81,157,417,682,998,872,24,488,30,58,692,456,34,731,767,345,748,49,449,39,141,487,437,579,475,643,656,432,5,968,11,342,184,357,242,855,731,167,118,143,869,925,304,94,889,10,95,385,488,687,156,760,597,572,293,396,703,746,259,986,866,901,617,30,657,644", +"885,33,618,10,790,533,315,396,715,353,702,570,920,445,39,439,463,578,15,684,505,13,77,211,960,883,150,784,974,573,554,379,410,515,410,839,832,935,39,968,555,540,525,493,245,840,375,543,928,574,55,171,493,813,370,441,361,175,621,478,7,714,688,848,223,312,314,730,688,678,978,482,794,189,527,400,837,314,193,789,623,782,890,422,238,861,722,627,380,81,115,499,787,124,30,276,305,729,539,946,866,580,419,644,259,766,568,715,331,523,688,782,961,118,751,541,347,323,242,631,360,217,463,185,384,717,411,815,819,991,654,397,384,314,41,701,912,938,726,701,80,459,135,875,6,440,260,33,596,575,958,557,485,404,443,863,583,559,452,429,547,292,649,486,600,943,217,597,895,419,265,514,325,522,148,704,548,856,255,678,259,22,319,752,482,787,743,682,520,471,799,303,361,930,697,649,366,390,424,919,738,181,262,439,235,435,267,105,577,669,922,460,75,934,990,843,744,803,926,343,617,652,451,650,259,303,168,357,750,840,359,585,236,496,490,0,588,141,853,283,718,955,864,663,996,32,304,459,857,235,304,416,552,18,685,840,138,448,919,482,778,976,973,674,11,755,927,328,967,97,283,70,43,851,106,637,812,980,523,66,708,425,994,544,831,961,681,473,378,563,256,584,191,92,171,148,513,379,508,689,401,785,545,885,940,262,943,107,804,725,639,643,801,130,729,6,62,982,31,518,697,249,741,968,332,516,555,674,968,671,596,985,692,797,973,57,303,996,50,864,604,866,425,386,575,22,66,84,187,346,492,39,33,784,727,130,112,55,362,855,207,319,742,182,99,384,762,632,331,682,410,532,502,213,861,519,738,92,911,62,67,798,970,38,592,776,724,478,78,302,251,192,500,663,830,580,199,654,545,169,309,750,955,168,541,790,982,678,747,239,205,696,972,337,216,127,966,318,494,429,79,308,27,280,57,189,893,628,688,889,154,482,145,630,513,605,779,13,697,69,381,200,905,83,386,383,989,689,87,881,701,631,813,210,805,775,306,123,759,900,27,442,655,466,438,111,534,582,916,508,790,452,331,654,926,981,611,9,403,997,451,171,370,889,945,745,713,439,741,700,718,643,786,179,739,369,70,87,230,628,121,93,465,469,962,880,115,153,670,999,359,211,733,447,421,347,521,866,549,53,662,506,386,846,585,779,175,21,406,934,356,981,338,303,779,104,635,891,157,987,612,989,274,965,833,507,244,512,489,341,568,762,929,904,49,548,978,14,237,831,882,190,362,703,744,630,685,866,894,234,478,65,165,584,269,444,565,124,270,327,925,124,388,105,695,30,4,536,673,685,713,742,589,69,254,628,470,538,913,16,939,38,18,789,947,982,778,225,47,462,671,748,922,572,728,426,45,17,511,615,259,615,440,528,268,129,681,947,79,651,998,441,662,687,769,495,115,378,51,576,523,679,554,552,953,931,276,176,85,475,237,558,813,187,145,868,721,686,555,767,808,4,621,577,390,240,120,337,411,507,148,256,398,817,664,855,29,110,652,395,1,155,209,439,638,584,646,768,989,534,442,277,972,797,749,432,935,99,986,683,664,354,206,935,301,1,784,89,325,647,613,119,752,736,225,205,326,207,892,20,943,737,1000,102,520,374,831,85,669,641,87,620,946,549,862,798,521,297,287,273,94,913,348,199,100,293,567,661,112,314,607,103,787,932,422,732,913,986,907,824,80,744,828,303,791,907,434,84,282,535,79,143,430,699,227,169,885,304,665,343,94,666,109,507,848,851,917,372,204,501,683,138,861,9,348,132,687,392,812,163,473,188,694,103,772,179,863,760,533,192,869,253,466,88,726,208,208,826,134,172,249,371,130,498,927,682,279,266,381,378,909,722,47,232,731,778,986,257,373,745,703,678,845,74,625,505,512,255,881,381,403,283,19,67,439,440,628,685,312,886,349,980,252,11,155,516,887,680,211,881,469,372,444,435,927,206,176,421,619,666,415,128,723,939,104,845,156,792,787,186,250,635,471,642,808,672,743,834,253,595,113,16,557,10,289,461,731,768,848,977,574,486,270,795,269,827,242,365,641,786,586,306,586,911,764,452,496,769,704,476,815,794,121,507,330,405,305,653,39,154,78,767,676,150,677,286,287,160,874,204,698,873,367,274,381,13,382,490,949,254,224,75,785,761,258,911,839,87,304,956,737,940,500,784,630,605,775,592,738,512,402,571,676,31,643,59,911,275,411,326,487,605,528,835,233,365,746,563,267,642", +"106,317,22,210,509,541,966,467,381,322,260,154,194,450,14,716,212,744,569,704,225,665,645,732,514,925,393,787,383,818,860,87,593,108,785,513,710,158,786,200,641,832,439,743,344,799,715,949,751,188,349,559,77,807,628,803,631,420,344,594,783,688,807,911,505,983,247,447,317,842,948,751,938,280,895,162,258,887,652,36,285,163,828,116,511,622,34,218,798,262,70,216,918,57,444,55,13,755,666,252,946,456,333,524,646,460,893,317,214,390,578,257,900,725,584,586,101,38,988,501,675,150,363,6,502,631,178,987,76,153,688,918,904,156,994,780,23,863,303,326,675,421,412,890,897,383,50,916,637,558,879,785,888,864,575,355,658,305,196,460,975,295,401,49,446,368,690,400,149,741,659,393,337,643,753,749,125,916,497,634,953,268,641,146,177,800,771,857,648,567,322,186,332,313,18,489,432,932,613,266,57,844,6,891,635,947,457,441,750,633,159,319,597,290,794,479,185,966,147,770,630,252,474,645,499,270,613,654,801,171,455,134,927,953,99,588,0,652,314,888,488,69,750,445,988,902,322,126,581,453,244,236,546,645,430,549,904,574,938,866,745,156,605,444,878,246,543,117,860,654,787,337,635,156,391,918,228,307,9,85,47,101,13,848,318,602,710,510,440,282,280,317,516,370,567,519,521,664,442,784,422,712,330,685,120,415,599,338,781,153,469,332,868,133,355,301,563,805,113,265,72,99,220,560,837,516,684,5,733,189,762,171,738,856,626,900,488,940,14,731,352,554,8,453,584,168,199,429,116,759,777,79,559,902,610,747,831,344,689,325,267,299,519,907,172,532,142,720,443,575,867,331,221,827,296,96,756,261,662,797,564,772,216,668,319,343,220,738,19,841,375,881,208,557,817,394,946,128,695,433,838,393,318,916,935,33,608,25,594,680,984,133,101,260,216,385,715,863,836,303,530,748,531,408,498,327,718,89,443,971,735,277,139,458,785,193,925,155,646,798,474,805,886,731,580,607,308,517,879,545,821,884,358,149,683,363,105,709,284,667,761,375,361,327,740,115,265,857,195,12,578,461,4,870,373,192,637,35,201,157,279,224,888,469,91,476,937,81,744,519,140,682,674,46,907,995,307,296,277,617,666,815,389,240,818,275,125,271,771,145,412,562,634,688,283,925,863,87,651,939,93,51,375,589,58,257,231,403,99,422,594,500,378,391,297,956,43,971,237,55,204,573,220,223,595,677,576,27,449,937,72,680,68,955,374,636,643,462,581,727,326,495,723,225,261,295,789,841,429,301,863,889,600,233,856,187,129,547,78,49,660,233,782,388,979,315,627,912,908,527,504,314,630,233,171,577,867,580,188,870,549,253,260,132,976,404,703,141,275,812,335,647,333,329,630,206,36,188,244,704,641,277,986,300,481,192,755,423,147,373,42,583,989,787,677,907,862,967,673,504,384,549,279,294,178,16,462,208,3,362,143,966,185,992,596,685,451,393,770,3,108,683,379,593,508,803,834,590,690,548,18,902,829,288,258,487,894,251,663,950,801,751,99,323,38,473,320,63,732,272,621,88,817,906,132,288,324,239,885,767,146,56,590,89,397,790,955,94,707,810,836,657,640,2,299,376,403,298,473,418,163,600,713,319,357,805,134,730,818,327,209,720,219,343,367,870,707,903,580,585,5,289,737,197,744,768,785,596,796,511,635,651,192,720,494,126,394,150,854,550,475,462,159,547,422,509,401,457,600,792,595,152,764,864,409,170,475,39,470,217,131,114,721,906,691,667,690,227,720,900,367,594,548,936,935,713,386,12,563,184,616,884,234,543,808,814,558,655,692,407,70,580,505,314,148,190,303,902,673,511,94,907,105,513,808,389,820,249,374,182,74,622,390,791,258,340,320,527,702,410,523,465,728,99,604,161,293,356,27,430,689,88,473,664,443,451,756,300,648,468,25,87,374,932,545,883,419,761,40,841,464,314,17,760,145,998,899,597,791,719,119,463,863,480,62,888,88,386,196,756,454,318,400,456,539,910,80,83,1,661,587,453,718,821,779,483,347,134,76,303,771,114,200,513,310,185,156,319,853,975,874,999,131,142,241,356,561,822,821,46,604,956,259,456,76,244,538,65,313,504,569,192,947,856,582,581,159,704,513,848,829,167,264,695,158,596,845,880,153,875,110,200,211,753,705,962,199,49,642,621,49,631,697,528,903,736,880,425,205,370,420,981,582,973,723,613,77,412,166,171,918,160,474,446,787,977,392,644,914,181", +"638,925,574,56,460,381,65,750,960,285,517,570,204,204,815,83,295,769,160,814,670,3,292,328,462,46,13,705,497,1,110,866,747,188,703,495,36,992,396,91,500,907,265,435,789,718,829,569,504,453,555,741,45,383,544,644,265,318,899,922,925,83,613,387,7,667,212,690,699,45,190,746,150,53,572,933,46,387,116,282,228,403,605,302,686,805,316,704,641,921,891,648,825,717,158,681,219,439,59,360,383,131,368,664,614,550,487,31,459,963,232,372,792,855,6,936,681,816,412,614,577,250,326,457,764,490,897,586,543,776,157,270,627,856,986,920,444,845,885,993,292,118,461,467,990,846,479,179,110,542,132,121,418,694,791,768,989,107,223,294,204,937,37,87,57,558,885,231,815,352,546,708,846,597,370,58,224,573,477,673,595,115,88,395,82,592,362,974,326,390,442,845,910,186,765,119,585,836,751,159,41,1,94,462,957,313,245,941,782,858,7,461,127,921,835,385,886,68,228,846,229,282,169,740,140,407,760,277,782,743,482,265,994,101,101,141,652,0,810,578,14,257,582,40,696,14,172,574,968,681,459,564,728,244,851,62,583,511,486,158,301,52,12,318,850,21,302,387,929,798,717,351,241,971,803,208,199,745,728,473,443,988,970,226,856,295,600,620,697,739,425,235,204,568,181,733,730,155,291,714,314,22,999,527,128,300,866,76,644,440,693,426,744,34,829,162,679,701,866,294,211,347,723,68,894,236,606,762,337,97,792,261,954,61,83,826,520,384,280,765,486,696,657,106,98,220,984,710,619,351,169,928,94,958,211,456,243,350,714,75,588,141,221,616,193,702,797,6,603,353,555,26,308,28,903,21,256,590,796,586,320,87,377,564,512,666,669,591,228,652,156,909,289,863,678,588,921,62,578,352,928,420,164,234,27,535,913,751,484,666,866,343,65,164,173,745,359,314,26,994,22,198,157,230,469,819,870,807,480,95,571,579,668,702,192,171,112,284,474,731,34,554,568,287,508,363,630,534,230,525,902,770,546,110,577,877,626,34,78,999,217,58,627,838,517,959,125,77,984,107,966,380,434,806,396,947,747,132,805,887,238,331,620,708,190,153,476,634,162,30,577,70,167,65,989,342,514,389,313,248,92,361,454,516,473,606,577,713,214,851,650,407,120,916,723,63,137,943,632,630,909,757,809,265,812,695,844,301,839,310,255,427,714,702,872,230,100,249,780,269,368,326,133,971,835,693,243,34,663,537,578,590,185,988,944,626,733,771,334,776,773,109,925,292,211,45,78,234,549,79,119,887,505,817,316,955,905,826,202,29,684,868,439,436,807,233,552,827,614,127,927,528,325,59,198,109,825,411,507,180,243,45,52,247,879,805,663,159,887,81,141,637,760,671,515,181,396,355,16,788,415,960,829,486,979,387,955,823,79,903,764,351,605,603,797,139,851,401,501,696,407,103,670,442,934,78,298,118,289,942,612,80,15,311,288,714,604,908,266,470,328,411,467,533,543,509,613,509,832,402,271,975,674,729,159,951,586,583,737,880,323,876,640,70,101,4,94,70,153,780,472,418,69,974,242,963,380,437,443,127,406,449,25,423,504,595,453,42,103,293,565,644,593,803,427,433,150,389,203,655,417,101,86,454,793,445,242,989,11,525,935,253,434,365,562,579,828,668,601,771,908,655,4,921,297,55,510,929,456,161,983,569,751,97,721,436,649,338,120,204,263,44,865,332,458,486,993,181,107,279,594,185,556,623,945,473,853,319,935,739,443,885,66,847,937,552,259,824,455,542,781,790,967,325,332,131,724,611,897,934,966,131,959,932,471,590,772,962,479,863,10,729,385,286,689,172,438,681,8,81,317,624,881,931,412,580,218,128,864,699,139,845,434,145,859,691,724,187,719,649,855,311,695,357,562,852,145,949,409,510,515,286,809,618,270,376,412,521,867,214,625,962,501,457,462,261,18,970,252,989,338,32,274,279,837,304,670,535,586,836,279,85,925,25,521,637,250,371,11,857,152,561,992,102,645,303,227,53,534,754,408,907,90,142,441,264,698,909,444,111,758,426,509,278,184,469,941,482,176,447,821,702,87,457,245,447,707,126,971,172,177,659,397,47,479,50,604,98,435,921,241,360,979,746,402,157,1000,767,385,294,757,275,146,474,747,931,436,562,531,429,242,25,514,204,96,983,314,687,240,459,79,64,819,825,674,844,42,547,183,553,576,500,312,47,224,495,797,72,592,228,623,991,389,840,1,491,227,454,816,823", +"375,780,692,331,143,423,852,366,181,771,71,199,774,698,505,493,64,237,803,223,928,195,855,651,88,207,467,880,907,122,128,831,716,410,433,204,916,418,81,27,160,515,795,390,735,130,995,110,772,589,950,253,690,728,83,756,803,186,391,233,398,901,83,238,419,366,690,595,676,621,201,390,242,327,960,749,776,43,676,94,12,696,188,942,673,317,831,478,925,642,563,124,650,215,598,736,152,887,824,479,751,150,520,977,657,107,232,878,397,320,491,798,198,226,448,872,167,726,320,973,727,819,128,382,762,826,263,606,95,972,969,381,644,486,793,733,994,975,455,892,333,731,372,118,910,350,873,210,143,891,994,6,170,756,65,167,301,172,608,623,623,256,286,426,944,148,648,683,211,176,608,764,969,67,926,67,766,997,133,48,775,243,819,902,544,358,722,998,860,258,827,191,491,189,439,561,691,668,229,622,803,46,578,366,746,703,653,308,488,799,411,212,844,214,293,689,388,369,488,893,680,864,984,430,813,350,17,575,87,138,615,319,102,350,331,853,314,810,0,134,366,741,749,164,507,209,881,257,112,803,764,759,935,531,259,222,717,38,518,296,321,677,335,687,542,491,292,589,336,208,489,393,570,453,490,700,329,464,352,875,538,634,298,219,864,372,647,226,810,368,77,651,178,209,730,329,923,730,702,52,612,808,32,684,214,665,961,746,414,8,367,118,539,213,296,426,283,34,480,129,955,274,717,658,715,966,537,551,975,284,253,29,808,217,517,698,292,291,379,830,887,331,922,753,356,904,657,392,648,204,868,574,106,249,857,537,585,837,19,943,861,768,696,806,95,172,432,687,157,787,78,41,810,481,319,380,89,896,817,944,217,90,258,874,355,6,847,177,241,709,767,998,79,249,869,544,952,676,134,24,358,647,634,565,241,420,347,518,888,473,814,508,763,568,111,289,695,117,507,464,782,37,821,113,698,662,256,538,624,371,583,154,685,94,195,796,901,360,292,782,848,763,990,222,869,56,942,585,447,768,351,609,393,44,590,131,43,944,571,516,76,870,31,389,927,84,977,877,509,523,251,481,909,301,686,961,681,102,683,163,935,48,475,788,650,137,433,966,557,945,515,798,588,923,694,983,236,302,656,383,423,58,946,101,214,306,159,52,252,883,253,667,908,762,874,507,645,738,190,159,647,116,787,862,420,665,966,836,532,249,322,554,302,538,578,284,402,155,237,522,346,256,668,790,120,976,716,511,891,7,28,417,268,52,253,815,712,59,629,742,799,74,742,10,711,729,512,791,473,987,91,217,7,708,649,134,649,665,354,909,677,474,756,856,511,538,629,815,10,791,662,638,701,198,604,45,937,153,211,675,323,631,880,519,249,579,484,938,308,873,831,18,35,442,479,443,333,736,632,247,593,24,785,824,746,169,754,128,213,128,48,753,181,138,930,608,757,611,598,418,82,477,5,382,295,271,571,161,960,195,216,417,566,577,701,697,155,278,376,824,991,820,458,98,816,577,823,518,632,954,261,706,421,787,944,308,345,326,183,340,213,437,679,428,371,87,587,951,785,54,995,736,290,645,443,803,669,771,559,499,510,120,878,577,245,442,385,545,800,194,997,128,622,652,561,955,169,175,980,277,467,186,513,28,985,960,96,111,566,364,773,307,215,131,810,830,572,327,526,20,204,145,459,920,22,966,738,943,766,470,149,370,560,918,393,136,109,49,621,233,334,69,787,128,573,347,104,450,284,166,85,634,17,11,582,637,295,715,457,307,941,218,233,361,154,631,165,243,823,181,35,656,65,979,948,561,531,801,453,558,463,359,575,692,338,928,216,669,921,127,555,399,365,313,396,742,157,237,718,613,238,76,249,783,223,103,81,175,130,367,729,886,543,384,833,51,941,320,349,638,333,914,482,784,848,837,883,787,344,69,86,459,892,234,965,260,61,245,559,686,151,670,184,644,436,800,822,307,354,743,970,145,233,144,316,759,326,208,495,196,413,589,529,496,471,307,28,497,515,437,779,405,346,910,511,391,875,191,998,601,454,339,372,60,525,896,160,478,110,388,33,739,777,428,538,77,393,714,269,498,649,890,976,615,844,234,715,115,385,439,159,856,276,156,797,943,361,486,843,445,243,664,465,194,795,60,610,985,173,307,812,63,905,597,443,783,165,733,897,423,660,725,261,479,409,410,537,782,801,496,314,925,950,653,26,562,154,894,75,108,974,148,832,55,410,864,628,217,110,415,124,133,10,606,824,759,860,290,551,801", +"661,598,953,982,434,522,726,713,236,498,656,136,47,356,893,864,892,688,867,366,923,341,71,275,753,663,993,493,824,276,941,517,268,911,832,801,465,345,217,890,745,58,646,237,331,363,600,542,613,4,540,831,709,290,915,978,936,991,412,344,65,181,444,484,792,38,439,195,236,548,219,79,238,72,564,745,94,25,791,950,213,881,545,619,370,808,444,851,354,997,905,209,235,63,142,982,230,997,763,894,998,616,930,451,444,480,483,280,677,277,61,846,219,110,203,126,886,514,808,830,661,957,895,648,316,423,884,751,741,424,150,425,1000,181,555,124,7,495,803,704,945,391,571,488,294,487,466,416,741,163,145,861,736,635,746,718,653,73,24,989,864,561,698,452,607,85,243,422,783,202,975,771,783,246,653,555,931,187,59,84,337,928,922,468,7,405,920,99,391,663,48,54,928,690,728,533,693,232,548,102,652,617,831,68,735,207,62,791,145,876,796,448,996,668,624,613,71,325,438,5,232,505,417,702,40,578,579,659,452,427,745,745,53,965,138,283,888,578,134,0,144,180,22,805,671,861,413,634,238,523,184,688,977,168,283,81,3,487,657,208,82,167,621,760,890,486,508,139,165,601,655,430,149,491,500,47,729,319,719,488,474,73,892,992,371,217,496,244,909,802,208,683,17,981,932,333,14,38,301,247,325,282,170,675,215,282,280,584,966,775,235,178,676,478,607,350,258,485,618,520,743,230,210,900,224,452,531,771,587,861,186,213,437,441,156,423,800,463,225,30,805,217,596,22,391,258,892,482,231,420,542,96,95,54,690,228,274,610,62,899,891,495,226,508,42,646,629,222,557,949,262,210,842,731,246,225,686,136,570,135,194,679,663,751,155,118,159,637,818,685,312,191,185,968,56,623,73,900,910,400,36,405,272,471,295,679,899,586,932,744,133,410,506,842,179,209,662,295,484,665,238,382,972,90,48,812,661,237,124,861,430,560,365,853,205,356,765,418,407,183,534,472,783,481,586,309,150,227,670,760,891,51,474,153,11,64,477,102,440,559,704,782,670,84,380,863,916,796,627,396,61,943,160,865,557,369,590,74,430,975,108,530,409,575,792,623,994,405,297,464,292,375,2,922,31,742,830,23,710,785,673,610,603,708,936,238,354,517,608,962,800,874,685,526,270,239,165,616,537,46,195,466,243,707,104,123,208,605,324,948,28,493,225,370,382,398,95,81,80,313,361,797,236,677,904,519,828,484,66,957,718,612,501,726,714,369,39,654,71,449,745,878,19,892,910,957,490,575,580,506,195,283,773,814,397,159,582,434,690,864,548,594,465,382,177,180,91,184,805,670,217,25,546,783,228,350,591,161,406,885,134,707,209,607,207,88,382,534,246,348,803,795,109,603,946,585,250,813,845,486,927,129,667,240,378,909,721,511,706,152,146,373,630,334,628,299,963,197,266,159,845,98,553,916,403,944,353,844,39,566,284,839,18,391,265,959,830,37,305,27,497,421,836,6,466,624,149,392,906,21,922,130,839,290,991,529,624,127,354,123,808,178,167,583,834,732,860,922,6,53,254,956,593,191,981,143,581,908,735,112,264,666,475,11,657,652,613,207,629,389,656,769,548,734,497,95,492,413,452,582,986,217,376,908,562,545,283,912,371,431,270,889,611,656,377,250,54,28,499,126,448,146,91,212,368,57,309,602,387,218,544,527,933,123,972,457,141,663,394,584,659,494,801,534,108,846,370,869,573,449,914,884,291,346,250,435,893,975,240,499,216,137,318,548,605,452,846,448,818,460,932,274,862,905,110,245,775,416,439,794,966,655,641,157,977,63,333,598,396,871,717,50,804,693,451,213,175,111,634,126,128,386,586,924,566,922,593,623,32,407,895,648,248,634,19,443,395,738,71,892,972,944,351,513,588,125,473,166,295,450,610,21,79,26,335,215,191,887,497,535,527,652,685,908,38,540,257,306,435,984,721,882,250,59,344,865,510,659,339,863,110,41,42,49,485,937,368,189,534,743,897,33,836,275,435,940,990,69,410,544,271,488,509,693,314,2,60,885,640,477,197,852,431,21,575,363,696,257,593,79,407,770,181,338,125,152,842,992,483,708,578,626,874,762,85,763,962,880,683,419,723,961,241,781,726,196,793,701,399,49,894,671,731,68,60,640,569,855,700,855,597,995,924,725,560,275,118,951,299,330,660,242,517,859,572,758,105,597,565,126,241,544,337,803,919,797,861,132,682,355,548,48,842,161,183,485,514,535,321,167", +"375,712,154,572,493,148,788,4,39,64,487,920,642,912,233,879,770,796,207,284,217,472,431,976,597,611,102,544,384,141,660,489,932,601,943,823,853,42,511,359,798,561,172,298,672,119,237,982,176,445,823,777,514,3,726,606,187,586,770,512,885,848,24,707,954,291,786,264,301,245,335,448,365,90,490,583,268,349,830,473,877,528,552,114,366,47,967,686,298,168,767,702,865,225,135,24,851,93,777,729,419,884,898,362,131,211,357,621,252,902,695,140,623,458,481,503,29,577,609,845,471,693,200,954,786,814,954,635,844,512,833,63,124,979,929,637,333,463,400,301,605,178,771,697,96,661,517,521,914,555,452,378,197,170,666,773,144,827,235,55,869,6,37,111,250,416,137,517,27,641,181,541,994,529,809,734,604,373,169,651,169,610,98,969,396,219,36,636,617,192,895,822,685,346,990,813,540,119,337,617,250,379,942,717,706,824,828,285,69,771,554,674,305,88,968,433,202,231,639,987,475,430,772,308,751,746,965,932,700,545,849,730,801,573,681,718,488,14,366,144,0,84,863,965,871,786,401,473,56,340,416,173,70,175,524,650,509,23,680,20,883,283,549,314,30,238,357,123,9,842,584,52,562,907,681,697,836,581,568,60,849,996,100,813,980,854,233,268,235,328,125,238,867,194,599,388,177,931,18,93,796,34,522,29,93,122,503,573,90,236,674,760,475,486,965,510,313,287,535,167,640,451,529,982,491,244,143,960,438,939,919,801,317,564,895,960,940,985,124,997,349,184,565,476,274,889,572,744,911,219,681,682,307,175,247,903,875,394,63,236,273,686,678,417,911,676,869,171,368,11,447,901,843,710,640,334,441,421,846,620,626,786,388,451,910,265,562,206,169,330,781,62,798,340,235,994,140,953,881,777,75,902,80,877,51,399,648,884,28,998,970,43,10,158,350,119,835,847,499,947,589,895,43,676,582,654,124,660,585,505,708,171,909,650,139,231,832,338,835,99,864,798,143,595,893,686,930,657,562,758,964,32,605,452,951,471,725,282,725,265,666,9,545,509,826,866,631,502,359,543,63,947,426,207,140,579,869,412,253,787,588,970,391,100,315,799,409,330,719,294,741,514,97,81,353,167,594,642,436,263,845,921,406,349,775,849,584,710,22,876,583,681,952,779,526,178,856,362,425,700,576,822,219,387,576,256,326,699,56,704,725,736,490,892,617,265,777,306,770,89,950,466,578,249,876,189,396,93,98,826,98,135,82,107,441,159,563,307,456,776,71,52,272,585,444,602,233,223,122,920,373,874,886,65,327,712,255,345,640,782,241,17,152,663,957,246,112,622,530,618,317,650,65,550,929,109,276,897,932,777,770,700,118,648,102,294,812,579,148,655,708,756,177,397,973,920,13,108,61,797,865,870,178,61,671,100,755,321,72,168,568,572,236,446,528,115,383,989,582,564,671,61,721,154,505,189,357,212,334,659,131,245,201,690,36,498,724,691,917,139,734,75,829,386,667,896,198,606,330,375,306,164,857,42,2,834,998,36,466,409,210,926,903,543,653,493,245,929,992,130,737,449,776,451,251,846,209,595,356,113,887,930,686,59,243,315,570,442,680,826,959,137,405,641,427,320,634,898,73,598,726,456,959,115,250,608,490,19,928,383,595,668,137,175,198,726,159,984,779,127,852,371,186,660,376,287,774,216,873,406,352,288,938,196,692,274,850,824,264,52,130,97,852,387,256,940,544,697,465,882,438,551,457,685,491,720,279,486,80,913,730,86,602,133,688,296,87,782,792,607,633,557,909,847,384,998,354,58,485,616,464,731,68,778,808,98,649,433,401,734,945,229,673,356,631,210,743,774,870,395,58,229,690,964,920,269,437,407,392,617,651,343,779,892,758,48,610,546,461,977,773,974,586,288,176,426,270,890,403,380,350,638,317,698,49,524,689,622,522,799,462,422,80,375,532,415,883,653,957,599,593,671,534,679,101,424,580,596,78,482,363,321,156,812,228,148,207,333,200,927,363,984,503,604,22,451,406,642,250,333,600,457,372,98,884,475,925,214,382,458,784,772,926,831,422,535,85,424,569,536,33,19,590,845,77,575,882,989,893,114,885,775,940,110,722,593,269,479,634,599,247,529,352,746,486,214,198,233,433,286,924,80,659,513,872,451,367,604,730,251,954,657,618,444,646,476,525,658,428,30,12,655,938,32,466,531,309,102,376,104,348,277,632,477,854,869,653,644,776,962,853,737,124,505,63,71,395,687,637,366", +"941,29,656,675,332,569,349,265,358,112,158,70,203,827,930,374,693,70,650,118,784,993,759,432,557,381,885,768,966,377,109,332,303,722,281,969,24,884,149,658,892,790,696,202,470,937,803,566,893,477,844,447,405,660,42,812,880,835,860,724,763,957,325,553,971,333,89,896,171,595,916,713,914,524,9,352,314,345,180,473,320,770,687,129,992,5,919,345,181,427,235,216,842,261,575,137,381,892,938,875,752,613,127,918,473,303,708,117,86,301,413,454,438,37,739,174,156,267,966,579,176,333,68,921,982,298,430,115,845,247,804,217,841,352,290,496,241,591,749,392,353,772,641,838,786,396,478,390,508,687,404,502,958,337,540,984,949,850,407,828,74,439,91,35,21,876,890,307,499,416,255,873,160,775,374,650,367,525,212,236,355,440,52,967,692,410,654,266,865,902,911,176,537,548,269,697,100,294,589,131,717,212,270,215,158,967,795,576,925,203,619,678,366,659,242,810,554,763,686,623,778,266,33,186,887,530,139,231,407,660,766,239,579,778,223,955,69,257,741,180,84,0,58,952,424,534,493,747,463,699,431,247,888,286,972,916,182,49,1000,651,401,225,606,360,289,472,365,575,366,376,423,71,777,62,738,430,553,93,387,150,201,336,85,938,125,582,561,939,885,573,325,836,857,82,231,914,546,684,11,12,479,672,243,877,100,525,794,353,151,666,799,402,328,8,931,692,289,7,309,643,112,716,934,446,741,55,360,965,211,433,89,87,434,107,960,540,915,401,664,240,482,959,196,467,180,696,702,579,52,596,284,508,176,436,770,270,537,519,237,110,675,945,724,429,12,789,312,435,923,497,94,908,355,676,379,260,246,629,214,752,688,578,315,376,455,105,699,645,390,654,463,436,659,359,472,284,848,726,705,177,416,110,102,890,629,359,629,543,852,578,204,105,333,378,525,992,159,505,980,925,245,409,454,348,877,857,157,949,295,264,909,767,386,471,953,958,7,719,902,466,126,220,498,69,941,613,471,581,576,616,897,960,925,493,648,796,44,74,822,933,834,565,65,342,615,119,460,766,552,384,617,971,49,133,477,961,615,583,221,473,69,936,272,827,973,797,614,83,637,95,622,261,328,556,210,775,253,888,723,540,221,853,333,950,705,305,994,684,815,845,371,18,622,404,461,956,355,662,538,655,109,80,641,112,974,438,812,53,262,525,635,177,2,589,359,781,543,537,70,41,352,176,347,232,942,587,120,230,256,808,929,310,705,731,820,47,257,501,594,607,694,664,559,960,152,914,717,189,293,401,447,6,613,790,271,221,461,761,785,380,306,231,777,456,887,984,902,462,986,556,975,346,875,966,490,262,438,17,470,502,659,21,141,715,457,318,326,565,651,403,735,518,31,399,466,351,881,40,416,354,147,711,550,903,788,538,403,603,106,66,575,558,421,416,262,298,488,667,244,158,152,625,194,580,595,681,259,337,255,488,987,20,822,186,329,525,474,264,49,44,370,380,275,544,499,255,577,559,621,977,788,245,278,698,867,630,81,735,127,812,183,883,304,235,241,638,252,497,810,772,467,702,26,678,173,417,724,720,658,218,315,948,924,158,772,521,914,187,942,43,907,147,319,252,48,119,170,525,101,355,39,132,694,649,779,156,233,193,568,110,822,607,115,109,998,959,429,986,378,529,193,485,93,703,13,375,591,889,485,639,265,2,10,233,97,211,89,317,634,184,771,231,376,140,911,571,770,355,553,384,623,201,87,74,218,765,674,474,300,184,663,26,764,566,526,69,115,422,766,554,5,187,15,233,344,283,546,35,244,303,379,916,465,742,244,96,539,702,109,473,442,145,266,2,930,966,947,70,164,70,56,267,3,865,48,537,505,763,112,484,623,844,13,675,89,813,998,538,394,974,355,166,394,520,316,274,831,576,167,231,684,120,247,139,545,124,781,172,333,179,193,725,639,246,818,476,256,849,740,433,190,832,721,137,200,768,18,684,934,923,258,884,817,192,64,759,398,437,924,544,975,56,550,307,526,968,159,194,646,922,343,629,469,264,219,439,784,819,803,302,258,883,318,343,277,369,246,76,943,904,38,393,800,758,826,134,405,591,585,559,687,326,953,527,377,467,249,523,821,438,582,222,503,300,292,980,458,158,338,62,757,589,401,821,1,10,113,350,196,619,550,40,663,287,371,712,644,397,366,629,730,582,131,198,304,611,950,756,884,671,43,230,341,185,558,433,597,981,449,576,857,738,194,161,878,572,264,480,504,878", +"487,191,121,525,536,995,169,870,579,157,191,917,113,438,42,159,848,910,268,126,914,371,156,472,985,394,908,619,477,225,676,301,727,542,518,666,623,1,64,974,289,423,572,941,510,484,558,611,745,536,862,825,66,642,392,319,168,800,543,78,419,894,969,554,779,818,297,802,614,516,546,116,160,234,284,560,34,249,840,547,142,736,203,407,432,637,240,42,533,717,226,433,215,307,391,797,376,317,878,782,911,998,586,583,253,712,497,820,918,511,637,311,578,105,503,604,123,143,978,120,775,423,347,379,142,115,868,822,163,642,556,260,668,106,631,914,38,629,881,292,209,144,102,497,713,489,21,708,737,995,991,686,171,610,829,99,716,135,851,5,862,190,325,913,786,142,731,512,777,259,461,89,484,727,361,44,448,984,935,516,651,488,763,166,732,308,29,828,614,949,837,613,242,464,354,439,79,647,784,61,930,862,678,899,164,379,918,481,271,394,171,50,976,748,692,595,557,969,40,603,388,417,806,453,781,678,670,267,619,660,486,493,238,43,977,864,750,582,749,22,863,58,0,575,502,372,103,386,511,440,806,122,343,301,498,706,798,902,730,452,72,271,996,876,157,760,833,472,23,905,430,829,760,578,618,934,249,768,789,570,846,477,233,505,816,133,140,298,662,26,833,684,755,111,239,896,662,657,144,201,593,235,564,509,507,556,630,297,189,504,200,881,442,456,328,791,8,651,166,60,282,938,39,142,364,871,33,539,260,624,332,700,734,590,102,842,702,818,220,292,341,829,382,427,37,339,280,335,616,468,518,292,739,327,459,654,749,491,244,309,160,877,430,67,101,246,217,913,352,22,428,3,210,173,753,459,17,302,127,751,54,953,568,742,899,685,783,260,567,945,296,211,441,782,649,586,269,259,522,627,209,242,639,697,165,966,459,646,551,613,952,539,957,452,990,400,18,368,392,368,465,164,109,265,761,573,727,921,498,605,834,994,552,422,867,609,943,977,66,345,258,607,281,13,447,309,546,487,344,27,440,584,630,171,94,222,859,568,917,550,154,547,739,19,203,250,718,902,966,53,552,633,365,913,839,27,820,371,747,983,314,82,626,126,452,408,257,523,713,749,516,460,538,824,297,367,90,825,315,209,304,431,626,950,62,348,867,550,737,759,222,715,88,376,69,664,979,262,781,777,246,876,56,142,540,290,902,427,803,531,554,3,621,766,401,502,700,308,995,921,742,148,662,718,880,311,700,605,226,648,795,775,546,195,709,190,907,183,841,155,993,985,336,260,243,461,968,954,305,244,145,31,511,668,158,384,880,545,858,803,336,660,127,786,591,491,731,543,78,534,905,532,84,390,307,662,145,572,444,872,9,392,374,652,866,86,346,313,380,622,22,501,590,595,431,885,790,72,969,120,936,765,652,147,75,936,428,173,764,899,98,759,507,437,797,417,894,796,325,251,49,743,365,656,422,110,756,12,355,947,795,328,277,378,213,777,514,332,459,353,609,512,135,817,174,703,610,477,31,31,204,795,566,830,491,336,10,236,430,671,820,909,545,399,131,622,610,436,354,182,732,445,133,549,24,436,908,438,928,615,932,94,983,488,272,472,456,359,308,104,449,738,283,91,333,226,809,565,386,576,817,883,789,775,973,999,935,948,338,893,221,991,527,507,316,222,617,421,829,519,985,516,20,692,403,180,770,553,508,716,508,989,327,153,877,349,362,755,605,516,488,201,786,614,835,208,427,856,688,360,563,70,81,969,705,493,687,155,170,390,548,387,811,502,193,243,664,286,349,944,232,471,648,764,715,130,54,375,336,689,758,554,100,750,532,151,179,884,315,390,271,491,772,889,282,285,412,253,415,421,377,366,75,918,949,967,819,733,46,382,491,321,453,218,98,112,416,566,571,130,687,895,127,266,439,839,964,595,258,261,876,628,733,679,77,195,82,387,943,635,203,131,832,154,603,461,138,786,126,98,878,729,141,126,422,138,264,857,542,19,205,545,15,835,514,285,533,82,359,405,259,290,204,164,583,712,86,966,221,726,228,338,679,982,947,502,604,385,829,454,56,855,732,808,943,254,396,977,956,930,387,797,941,381,192,892,91,541,300,5,249,464,672,537,753,323,29,366,128,779,91,119,573,402,492,205,788,212,107,883,667,757,530,149,783,508,126,459,879,193,686,863,819,427,157,476,214,740,726,792,560,820,408,407,680,705,66,673,162,197,524,560,84,394,169,158,935,777,89,60,252,754,590,638,586,325,606,7,172,369", +"58,650,543,801,989,386,870,415,427,333,280,712,199,785,306,429,362,357,340,721,516,12,604,972,61,875,184,755,630,911,609,291,851,256,129,255,646,331,674,842,862,855,108,215,396,974,395,466,410,686,844,961,737,958,241,308,371,152,209,639,660,561,230,457,759,158,502,257,845,963,748,400,427,262,197,510,230,826,537,763,920,920,937,390,810,715,190,398,566,110,639,276,479,487,548,114,664,251,120,835,244,580,345,336,914,753,417,556,238,269,554,384,355,536,267,257,148,765,530,448,952,209,164,818,162,181,237,915,123,277,851,838,586,512,259,84,896,602,982,306,549,210,174,127,765,836,177,916,642,139,939,616,475,684,39,640,456,890,884,63,333,654,314,918,338,489,327,778,951,668,775,154,430,180,754,674,230,745,628,722,826,999,108,428,686,135,775,971,93,281,280,690,700,532,375,480,335,13,505,936,214,29,736,420,760,845,822,636,581,630,181,446,706,559,791,719,992,813,327,854,546,576,72,492,191,198,312,26,947,148,237,933,433,179,56,663,445,40,164,805,965,952,575,0,84,980,269,762,969,736,845,667,632,740,989,569,925,674,465,772,803,861,293,169,68,407,132,958,979,819,85,609,814,673,373,445,497,66,621,180,741,150,851,650,832,179,187,810,411,936,289,858,870,466,829,266,496,328,193,633,251,284,831,183,554,44,150,66,178,441,273,120,452,879,362,82,766,882,345,135,798,747,940,186,357,739,635,328,903,277,934,92,36,43,281,517,590,576,234,496,256,587,887,800,899,549,944,913,428,856,380,720,930,819,584,917,624,46,289,220,856,70,391,454,554,172,853,916,86,491,843,422,797,188,819,772,803,131,476,167,568,887,69,651,551,696,303,664,535,811,727,375,314,446,741,245,806,391,315,801,980,254,612,678,640,346,834,810,461,713,949,183,216,180,726,500,409,732,151,835,575,287,551,461,190,412,258,344,78,56,639,108,317,607,200,57,768,133,274,24,556,166,842,895,857,892,521,596,485,476,991,799,186,606,38,780,426,557,521,354,836,444,677,988,436,150,887,884,697,21,320,30,824,5,985,199,379,29,95,480,161,505,374,670,925,957,337,409,329,307,450,951,161,572,887,712,843,1,633,979,217,980,598,333,228,248,547,14,565,865,719,391,223,34,812,203,515,619,549,369,746,476,332,759,243,73,323,642,872,182,88,986,497,726,645,574,42,591,781,902,589,619,755,1,331,223,908,671,823,635,445,44,813,799,523,395,78,943,787,119,946,347,936,29,708,870,160,37,232,718,206,710,41,913,142,408,998,844,846,355,87,309,922,899,87,460,67,13,823,119,52,909,623,68,85,583,172,565,776,497,235,776,233,748,55,63,729,563,330,556,218,515,24,793,784,416,950,833,417,710,729,893,773,151,959,600,809,737,54,965,447,91,574,370,496,152,322,328,659,362,287,488,193,274,53,904,815,672,302,369,371,707,855,892,45,850,225,685,793,926,834,681,232,335,915,423,847,145,278,989,117,835,2,81,998,889,489,82,772,39,356,530,200,606,600,134,212,894,143,582,664,404,322,141,607,418,555,944,14,358,675,28,260,638,617,323,928,171,734,3,950,827,355,356,414,584,5,370,452,902,748,571,968,297,770,475,307,635,762,989,219,262,300,827,829,237,940,950,886,671,3,77,312,599,3,312,136,583,459,947,794,762,962,159,110,165,413,356,270,527,903,919,65,705,519,171,727,363,823,811,566,831,273,926,803,845,226,957,992,495,270,638,66,659,834,95,17,691,124,248,4,555,88,115,224,556,803,865,68,585,193,651,766,380,572,824,1000,144,653,621,463,367,614,808,299,801,929,697,322,71,148,369,760,540,396,926,324,154,286,697,316,452,367,585,965,134,864,122,428,62,53,702,953,780,726,292,786,575,263,352,704,94,919,505,938,429,186,558,8,737,853,545,159,240,175,71,112,732,332,416,97,754,761,805,829,440,160,769,171,930,15,746,799,286,248,839,244,518,457,351,19,238,954,745,426,309,254,571,680,442,994,362,785,476,860,299,798,137,810,187,388,829,663,325,489,248,566,372,929,160,76,504,478,677,273,421,297,201,410,523,67,93,544,596,95,843,111,421,456,164,747,66,114,374,947,475,854,175,113,662,956,595,793,21,517,621,366,759,237,937,703,324,169,823,647,716,832,874,714,532,110,55,400,633,305,171,704,94,262,529,173,513,448,433,754,16,627,608,866,767,718,669,609,17,991,341,260,588,716,792", +"890,287,160,546,647,382,783,442,377,211,797,603,514,49,780,730,535,685,942,741,712,636,537,812,60,119,688,299,958,804,187,340,891,423,707,978,481,944,959,33,659,127,177,422,269,572,736,716,886,14,498,978,522,280,934,163,89,346,185,170,373,253,853,860,331,201,375,955,679,362,963,624,267,604,806,511,318,408,587,840,643,65,238,288,133,730,677,134,366,99,381,330,13,953,470,279,935,236,328,392,668,111,178,486,902,830,145,365,505,375,443,694,269,936,80,314,840,741,184,746,142,385,947,846,41,804,254,791,662,341,202,925,10,264,935,143,146,544,887,68,576,907,757,233,722,951,502,194,396,897,50,507,729,758,716,777,496,432,111,39,668,241,230,875,530,878,7,743,826,162,549,649,40,760,210,768,646,680,521,771,77,192,883,747,96,149,705,605,51,473,195,966,651,709,396,679,660,985,252,994,348,42,849,555,144,86,585,219,344,911,56,479,65,657,698,33,131,552,795,62,242,528,860,326,17,588,777,877,307,885,399,711,344,634,967,996,988,696,507,671,871,424,502,84,0,514,180,485,437,259,232,106,789,503,148,245,334,288,640,298,762,874,775,900,484,530,690,780,26,411,951,676,432,406,670,653,930,314,449,922,453,877,212,182,478,537,595,240,944,910,73,336,353,514,541,113,187,463,590,30,129,227,819,695,409,794,389,137,222,897,434,442,257,160,511,455,426,768,659,615,430,539,255,262,906,278,111,229,710,309,295,769,466,946,403,366,654,1000,313,156,511,419,214,964,457,687,687,119,993,754,469,355,908,399,86,875,490,673,447,147,949,801,317,374,668,469,809,143,487,241,595,609,476,246,860,955,582,675,500,328,632,107,970,948,271,371,178,451,238,375,573,681,145,839,666,648,691,909,968,27,883,875,717,453,374,921,855,606,896,590,878,407,58,371,306,638,730,953,373,775,885,963,541,3,625,167,64,96,585,399,966,119,132,206,934,609,831,952,734,92,28,697,473,914,473,406,606,107,771,771,822,595,70,349,886,861,121,681,193,273,56,980,363,411,217,320,48,57,338,728,219,550,892,854,535,764,903,63,172,673,82,590,747,67,935,91,183,916,841,246,129,541,506,11,505,993,416,512,644,60,974,733,279,97,511,986,848,621,422,451,190,807,61,674,485,108,415,269,346,743,785,911,243,784,656,753,723,52,442,919,93,512,3,49,500,668,179,344,966,902,662,840,820,779,506,119,484,731,349,728,575,528,834,806,1,940,840,631,274,547,168,182,935,561,987,369,708,632,883,75,659,735,481,727,667,854,320,509,597,909,455,246,781,950,182,516,252,688,324,556,292,799,304,146,188,78,898,420,290,280,313,882,579,186,815,361,597,556,635,120,886,9,222,755,419,434,244,169,168,957,734,166,719,951,896,819,251,937,904,924,626,809,388,234,170,756,185,433,121,93,419,372,470,888,65,65,390,814,514,566,779,128,927,720,173,859,351,702,191,47,495,190,589,175,931,407,200,348,600,693,544,441,161,899,450,696,496,558,874,889,799,34,586,248,349,143,996,637,159,698,326,104,822,854,65,122,986,707,530,656,427,387,10,741,580,609,312,614,530,909,420,192,538,890,153,714,864,10,426,726,608,221,585,290,740,678,420,647,796,148,342,940,124,662,833,310,794,223,187,701,263,905,208,535,810,299,889,370,867,668,354,467,741,765,3,555,284,109,436,86,439,435,794,420,833,940,55,613,184,188,994,172,3,987,637,92,927,857,744,658,181,525,816,816,251,259,155,279,477,849,905,882,624,446,713,142,279,49,446,4,179,70,603,317,21,20,633,361,767,748,108,991,274,327,834,731,489,358,583,618,845,122,433,46,851,879,344,302,903,463,279,497,805,90,814,778,30,174,207,219,973,780,542,818,531,694,582,901,972,276,808,670,700,248,665,786,878,822,189,671,367,311,592,957,853,548,380,826,988,563,232,710,946,724,560,383,600,606,25,880,660,669,82,853,848,735,544,669,76,139,970,785,633,631,874,322,723,603,87,286,112,945,511,579,134,464,80,577,359,34,264,602,17,641,677,378,678,44,832,694,166,827,570,777,663,852,278,66,209,275,805,200,425,24,612,579,466,698,453,541,866,582,585,99,360,984,832,537,926,152,706,234,62,413,559,64,449,420,500,56,657,842,374,715,859,823,720,24,281,408,830,364,534,241,335,60,208,471,600,193,232,669,954,940,814,343,530,603,324,40,610,48,318,295,831,624,416,510,111,451", +"700,301,848,827,96,119,324,696,734,631,416,907,789,268,455,78,674,665,455,663,322,621,557,483,184,517,615,299,57,568,217,474,422,259,744,347,191,318,934,910,244,717,557,883,717,548,861,348,589,709,532,88,247,73,907,774,89,276,116,540,769,119,747,981,24,658,534,378,790,742,464,247,38,490,737,589,246,176,421,228,237,265,715,611,524,347,775,80,333,12,188,765,72,414,767,628,749,294,665,124,105,589,27,159,710,776,205,692,63,417,956,357,459,981,157,34,132,240,647,928,597,375,379,206,258,149,43,984,448,116,709,923,282,706,998,542,504,190,280,405,772,254,90,464,977,115,870,106,945,146,144,356,43,382,136,614,811,19,468,594,908,646,956,795,276,752,397,148,848,377,694,345,9,958,876,145,980,509,710,824,430,639,819,303,963,389,283,204,454,492,664,542,469,7,376,685,439,785,702,376,338,823,419,197,649,312,257,142,884,376,540,731,82,209,660,7,285,969,939,430,606,304,154,721,703,349,985,83,662,966,786,963,854,594,747,32,902,14,209,861,786,534,372,980,514,0,610,322,827,802,249,60,206,680,738,418,151,469,571,11,564,219,622,604,906,34,871,935,366,831,157,325,574,181,952,951,241,675,489,901,368,947,609,54,530,596,407,376,279,481,876,562,906,355,21,92,134,303,600,759,365,734,16,672,982,133,176,954,77,392,41,921,273,819,653,764,638,814,626,308,74,723,64,414,20,674,515,481,488,825,910,763,745,535,915,398,211,725,394,21,5,125,757,970,705,815,208,904,692,48,225,208,467,247,917,422,236,655,582,646,870,606,707,381,519,216,459,695,978,710,433,479,978,454,432,394,281,600,4,386,366,590,154,195,607,779,91,993,94,957,579,989,831,36,460,615,886,676,810,90,892,342,636,697,472,866,673,194,251,739,352,949,69,187,111,573,308,138,492,559,39,866,713,637,274,377,61,754,46,558,373,981,413,655,330,523,446,825,33,345,930,664,76,916,115,863,696,262,234,948,646,549,666,376,387,287,190,970,724,627,36,72,388,604,57,19,8,401,613,317,77,917,622,42,837,632,649,466,335,112,99,282,1000,117,621,700,299,431,844,93,527,827,939,41,846,468,822,745,4,465,815,127,178,506,365,978,288,280,879,922,445,515,476,622,945,695,632,98,259,52,48,875,838,267,632,786,955,899,459,123,676,767,4,743,900,258,208,216,714,433,334,956,311,674,726,630,275,338,312,164,59,576,262,57,936,613,774,560,285,803,636,332,856,517,8,848,724,565,679,645,689,127,316,63,577,60,267,734,830,512,831,860,146,47,439,914,566,548,552,959,533,490,407,926,409,6,202,932,649,308,676,200,707,533,709,573,354,118,987,348,981,454,754,556,194,849,70,185,709,878,31,119,472,600,238,869,370,113,875,89,948,852,290,369,364,276,934,980,100,861,542,9,38,301,637,119,486,965,766,539,312,91,656,463,483,971,72,464,583,733,364,408,111,57,254,183,117,352,200,451,281,806,455,4,37,407,215,153,854,761,79,666,377,337,697,10,503,87,737,683,175,557,695,743,751,97,483,897,140,644,340,70,291,160,720,895,516,985,945,698,593,254,471,383,927,939,409,788,46,448,728,289,262,227,112,302,951,542,827,493,320,116,845,285,231,422,412,273,166,64,995,663,378,90,442,437,131,209,345,76,879,196,637,251,47,608,815,643,177,923,466,365,250,164,322,997,157,655,101,696,891,523,623,704,701,144,752,247,988,245,91,245,62,712,787,334,638,922,763,959,741,204,261,103,623,31,373,27,328,536,140,395,200,60,388,253,356,671,46,960,345,641,589,397,865,264,627,399,624,695,119,568,882,943,947,999,348,278,727,505,72,288,978,381,8,767,279,279,591,594,498,974,310,379,859,529,929,685,155,520,5,696,444,871,916,489,335,158,338,521,254,321,755,282,607,655,465,775,270,306,614,460,337,405,26,959,56,345,455,255,349,221,990,764,255,273,568,811,950,566,8,767,708,984,302,990,813,359,714,184,207,157,805,656,600,889,316,232,186,67,937,691,991,969,165,885,471,962,350,120,559,357,818,495,748,449,412,49,516,847,208,104,878,997,58,958,800,399,804,601,166,527,402,367,805,914,759,289,920,96,455,965,577,442,215,62,184,620,701,386,585,559,672,274,608,82,441,208,902,545,473,343,313,144,936,994,86,567,347,267,841,433,811,739,803,486,531,244,353,424,11,769,308,106,125,401,184,197,322,561", +"121,735,724,99,247,123,281,720,814,751,64,475,31,600,635,782,31,519,325,19,859,985,909,217,783,327,357,833,62,952,796,355,139,140,391,578,343,903,459,526,34,71,317,444,282,895,198,873,86,858,564,952,692,337,739,496,116,314,377,884,768,113,350,452,579,546,722,152,473,726,914,627,912,261,774,967,994,472,327,294,816,68,305,876,20,36,423,230,290,12,961,944,503,715,118,752,891,116,24,628,659,348,912,276,224,174,17,9,122,659,89,338,681,912,435,728,357,123,427,21,885,820,784,469,233,251,150,713,457,24,521,439,582,235,102,448,614,200,337,6,907,744,450,22,258,992,462,379,91,695,500,715,162,367,605,738,336,978,245,718,855,423,795,526,960,127,200,22,161,606,427,892,924,57,265,993,668,165,308,745,663,600,906,223,85,340,510,563,525,174,682,221,154,543,439,291,755,299,28,895,341,553,387,11,907,812,920,120,817,557,354,548,903,505,38,6,205,490,613,203,990,674,821,20,386,334,380,241,90,433,956,92,7,142,895,304,322,172,881,413,401,493,103,269,180,610,0,515,379,601,665,136,929,878,157,401,179,409,99,85,364,369,725,214,180,115,548,846,860,614,992,621,433,966,859,255,211,61,659,952,874,381,568,640,921,96,127,599,656,280,740,925,493,198,83,139,194,719,819,323,563,852,68,579,791,714,996,485,300,25,429,573,505,506,733,416,975,886,375,292,450,439,89,883,820,455,725,53,103,527,494,613,688,670,358,754,352,995,125,506,140,617,420,586,924,629,616,770,275,276,427,144,728,228,604,206,941,593,272,412,967,228,35,573,394,731,798,339,496,997,208,951,185,870,725,830,877,998,618,252,999,9,69,680,533,417,16,192,666,679,710,954,631,143,132,611,718,110,304,412,671,753,140,673,896,777,616,729,167,875,37,428,84,620,444,990,589,271,508,990,618,570,626,278,497,190,420,114,172,642,661,351,838,575,733,200,466,985,959,149,85,842,529,622,672,461,470,58,387,222,548,893,203,919,139,684,901,930,725,398,518,699,649,401,274,185,59,329,770,33,996,556,237,557,31,277,533,585,189,670,398,101,862,815,6,931,406,35,646,621,482,891,429,882,50,102,318,985,999,460,375,151,927,889,802,555,917,18,673,366,915,94,326,690,282,717,96,871,10,21,214,868,240,808,26,279,596,95,278,125,950,255,856,797,916,249,908,697,288,131,977,90,150,566,165,584,196,22,183,867,94,205,371,327,175,706,281,680,673,965,963,184,844,194,787,112,342,191,927,365,170,621,437,924,184,512,374,62,825,949,935,965,286,596,344,404,410,270,755,722,816,476,365,435,561,707,926,295,773,428,245,91,928,452,276,758,128,420,186,196,920,853,341,310,929,495,913,412,559,221,425,455,993,841,601,705,276,690,717,718,202,725,696,277,130,485,865,385,303,141,545,520,122,633,903,842,639,796,468,430,176,963,815,102,512,738,301,400,156,291,100,48,627,673,834,817,111,661,521,615,276,982,809,363,640,1000,216,366,441,280,384,121,394,67,336,137,506,492,874,619,562,818,666,507,900,514,290,628,606,642,811,646,609,218,448,750,185,910,615,706,109,831,979,288,27,513,797,38,562,498,439,376,79,912,725,803,333,984,371,752,339,810,254,631,996,703,767,665,420,456,756,443,911,329,389,81,237,961,11,595,669,808,988,246,858,328,252,711,875,201,78,318,386,589,456,902,345,257,729,300,22,455,643,461,528,401,19,168,836,752,27,892,968,841,183,921,48,720,911,895,823,157,614,315,643,629,504,410,225,309,524,765,657,439,671,688,263,793,66,261,883,89,827,454,679,701,969,470,473,719,273,644,166,226,363,224,727,629,196,765,562,551,973,971,924,67,721,733,833,47,878,559,165,211,151,298,276,106,834,184,101,578,756,844,50,134,895,796,202,110,368,695,382,848,156,270,812,45,628,559,618,820,517,662,44,452,392,79,165,673,738,621,193,932,236,670,212,36,196,547,241,5,88,189,664,490,226,226,332,343,946,172,832,441,177,123,376,547,82,516,677,325,729,903,388,326,447,453,709,963,83,115,843,569,315,296,418,619,552,724,771,821,492,985,956,543,890,223,579,259,116,429,162,222,962,78,633,581,931,16,188,406,597,94,240,396,281,758,620,324,67,95,844,862,643,888,862,359,874,948,654,367,318,460,546,269,790,307,489,5,471,834,872,465,185,376,427,415,177,365,705,734,53,732,914,466,565,999,764,244", +"852,765,366,741,695,876,584,732,621,496,286,901,26,613,671,852,193,584,869,32,241,962,379,171,787,416,145,76,87,355,455,541,674,355,927,644,584,757,354,122,127,408,428,173,145,771,477,542,285,624,831,530,265,244,888,945,215,40,703,84,452,105,758,597,251,915,826,551,458,704,871,368,288,944,461,103,187,59,380,131,662,363,338,654,741,183,175,680,448,481,886,68,595,206,195,426,622,882,810,776,371,866,561,907,575,619,877,915,27,391,927,844,127,471,139,614,12,781,6,318,576,310,23,283,468,938,189,469,439,789,639,435,151,238,53,20,378,521,788,545,122,376,313,935,823,442,105,361,637,940,162,983,292,19,246,993,937,843,14,475,198,380,374,127,228,18,569,233,738,573,65,38,487,486,697,287,939,408,576,998,293,836,626,648,104,143,895,801,396,993,720,81,195,989,544,965,828,603,53,868,238,399,662,602,138,278,552,322,765,253,277,556,462,292,823,413,657,348,852,359,168,44,473,264,476,122,105,137,46,768,528,854,429,578,699,459,126,574,257,634,473,747,386,762,485,322,515,0,959,833,845,136,304,805,583,59,47,854,75,693,203,693,462,858,82,509,287,765,322,390,124,977,468,180,50,741,508,621,816,240,917,703,811,956,429,933,818,288,495,572,789,312,2,418,322,887,230,544,539,436,347,888,189,517,174,691,930,840,710,713,186,194,759,707,124,1,307,259,309,150,406,730,455,499,506,793,91,598,654,20,522,163,614,117,47,649,489,127,656,355,326,227,287,396,456,403,415,430,797,924,576,183,224,208,402,900,274,938,631,939,227,942,585,780,791,941,838,227,536,569,828,548,758,413,463,333,955,156,987,186,573,448,644,604,312,470,909,393,459,11,634,998,999,191,973,862,186,301,618,622,60,485,768,979,870,761,21,352,536,374,44,780,577,480,733,912,409,171,604,42,515,180,47,256,469,636,546,358,275,214,670,504,958,488,531,275,162,869,623,665,218,563,408,322,273,582,111,707,999,898,983,571,171,911,548,455,410,192,520,556,93,719,162,592,969,744,925,604,509,266,736,750,405,160,658,63,284,548,485,546,839,55,636,138,43,431,708,657,455,535,999,520,614,15,954,826,488,711,438,89,479,932,2,154,6,690,912,989,599,602,577,33,283,605,806,276,786,390,293,374,61,51,450,668,484,609,457,336,549,816,92,639,815,80,898,366,513,448,378,192,636,280,549,638,69,724,890,892,115,498,819,861,444,980,819,817,339,351,836,659,994,609,410,369,612,763,622,813,151,633,710,294,729,896,229,21,950,328,522,758,461,609,615,590,571,479,567,929,336,206,830,644,111,603,393,151,300,624,979,752,708,392,102,572,566,888,580,894,141,578,499,80,676,846,870,257,319,222,975,523,720,274,34,770,824,3,125,22,447,212,402,330,860,671,927,164,281,795,117,159,101,256,407,608,651,324,12,26,113,557,438,806,961,805,222,346,902,993,837,61,633,756,700,780,277,812,653,21,568,462,740,983,124,333,852,869,101,706,885,509,350,827,481,681,769,317,297,609,479,250,452,57,411,394,30,269,489,184,696,789,106,444,740,943,293,657,672,193,137,130,267,579,181,591,136,606,397,419,609,843,913,871,834,119,174,894,575,980,999,188,754,210,908,978,104,826,541,714,186,685,399,165,783,375,897,95,584,921,772,503,849,83,400,900,885,67,71,309,425,67,144,768,660,841,643,141,406,90,3,873,328,854,268,409,726,225,982,14,511,253,408,138,608,378,840,832,994,827,149,67,794,820,895,620,895,387,341,249,427,342,918,306,920,750,493,15,189,427,96,354,53,890,508,359,607,887,341,341,999,850,233,419,462,887,622,967,922,52,206,622,147,619,239,583,941,522,127,700,484,18,796,452,839,747,152,227,75,222,271,114,289,656,106,311,699,580,621,218,396,736,436,386,267,506,840,501,980,26,299,734,340,168,838,695,656,678,499,359,828,601,343,575,140,868,899,836,537,15,795,978,793,326,418,432,779,920,711,572,246,188,183,67,312,354,322,324,486,877,441,611,114,947,993,860,653,684,365,190,920,277,17,225,936,739,789,725,392,710,759,960,709,516,658,113,768,110,917,268,354,171,342,48,690,906,72,303,280,773,776,293,245,332,755,662,592,11,988,537,345,264,483,448,277,215,934,866,210,504,404,792,9,588,727,237,349,350,838,963,271,207,2,32,581,431,92,514,569,232,292,122,677,887,454,180,720,750,23,185,636,825", +"700,117,765,130,888,440,278,153,370,404,23,368,708,827,116,374,605,16,3,475,515,316,949,78,861,460,102,906,274,844,115,59,911,918,489,951,782,249,510,487,545,410,310,456,884,477,843,602,384,656,228,159,633,431,720,715,625,11,702,778,887,498,724,299,713,427,224,448,677,441,381,594,599,13,315,719,752,877,953,451,606,442,480,340,150,231,693,382,590,64,335,598,687,667,564,530,819,641,2,405,690,768,297,721,198,192,743,204,818,7,865,206,21,63,805,812,719,402,136,361,492,770,857,868,300,92,893,72,226,240,866,538,489,69,806,686,953,352,207,803,170,182,65,93,968,717,609,146,684,679,527,1,917,72,386,343,885,953,507,853,325,944,948,447,262,463,580,749,722,87,475,745,633,103,788,886,83,362,903,45,392,283,803,155,228,240,785,824,310,72,750,436,216,925,438,184,485,531,405,264,78,452,582,371,736,940,735,289,988,357,737,572,341,731,681,48,258,983,212,504,951,734,644,473,586,532,898,305,694,902,637,401,891,640,319,857,581,968,112,238,56,463,511,969,437,827,379,959,0,427,33,146,383,567,38,851,99,175,744,540,382,682,675,348,434,807,1000,257,85,313,5,863,941,381,953,840,685,130,42,66,384,568,128,971,513,191,451,562,352,251,840,498,433,473,770,482,966,212,485,627,596,902,997,624,649,402,903,6,28,862,174,544,188,498,237,305,144,456,739,66,955,456,344,816,895,14,911,17,641,746,608,982,140,926,235,400,275,580,301,682,123,156,759,47,481,755,453,496,177,985,472,93,868,352,354,308,387,2,780,223,974,154,472,808,961,683,756,311,785,217,693,615,143,850,28,944,110,473,240,667,249,823,83,436,764,452,897,770,819,567,792,264,865,847,356,811,728,70,469,534,891,132,810,911,278,504,887,65,525,653,627,500,548,884,867,61,418,598,142,517,264,44,323,477,281,336,824,531,932,929,345,249,774,313,804,655,131,199,726,798,173,522,185,270,447,967,488,52,191,904,161,75,541,207,646,104,591,615,723,695,784,612,509,398,5,55,589,499,330,658,532,239,980,633,126,449,818,643,301,664,332,577,814,447,112,543,509,955,214,949,393,588,80,223,289,558,415,813,280,695,760,213,370,953,191,447,836,783,181,474,640,142,852,382,770,408,323,983,918,981,356,938,498,89,891,299,949,811,772,861,144,384,401,117,252,206,241,956,853,661,825,515,43,705,592,335,519,651,413,90,161,979,96,937,167,710,918,410,29,754,733,477,187,256,779,422,13,674,194,383,506,82,938,21,753,168,553,755,78,816,341,123,451,618,906,941,482,188,208,721,660,375,946,976,364,493,294,703,730,145,162,807,104,466,803,712,589,97,286,728,259,349,787,62,364,261,261,47,37,87,373,925,152,746,372,525,485,679,580,502,299,976,208,930,323,264,581,986,600,838,806,611,521,57,533,737,237,228,623,611,547,517,613,310,760,487,43,55,971,796,131,288,991,359,939,321,91,832,407,499,614,635,583,751,524,119,779,119,650,570,871,666,907,713,90,37,581,222,108,39,424,888,195,714,270,881,614,481,823,877,413,868,902,411,604,237,520,282,389,53,143,570,855,150,448,900,473,435,880,416,644,643,128,307,17,452,832,3,234,268,638,364,598,718,563,698,24,368,228,887,303,156,349,507,487,523,25,120,200,152,985,791,614,202,147,18,698,55,304,427,508,968,112,243,696,444,181,386,738,330,852,170,115,126,730,434,354,859,960,808,951,206,316,188,404,155,43,117,96,508,59,431,633,320,850,6,9,426,150,631,188,403,394,389,540,903,246,258,430,786,957,368,991,933,927,539,136,171,685,405,998,42,990,743,113,252,697,723,131,455,573,566,777,932,100,694,409,210,674,818,677,997,662,540,108,914,391,825,746,531,610,611,104,683,439,410,610,640,435,561,522,757,855,497,715,4,388,249,89,720,537,156,426,298,395,45,129,409,582,297,603,922,102,540,296,570,371,484,411,27,305,315,387,301,442,179,264,908,365,699,222,239,224,651,186,368,717,535,746,38,631,139,510,162,616,181,756,841,815,504,779,300,998,123,761,586,408,859,184,376,868,86,100,251,190,338,724,30,117,562,767,53,973,502,47,450,469,878,14,713,89,629,837,30,853,955,873,693,906,405,241,361,681,124,356,583,978,22,721,816,364,742,959,185,398,742,467,914,429,712,815,430,689,623,478,844,736,13,277,92,336,404,709,623,860,549,649,731,539,81", +"888,501,598,337,276,695,219,578,279,917,26,40,46,643,194,237,18,574,35,4,312,226,444,440,768,766,64,372,550,937,707,974,312,41,711,918,737,797,399,237,346,144,509,828,561,444,470,502,257,28,753,50,504,5,429,468,32,495,403,79,414,262,664,262,321,737,764,594,628,112,203,573,745,20,419,993,812,647,723,424,316,846,116,86,275,759,676,515,287,10,911,763,927,526,656,142,359,515,561,435,186,476,686,564,150,713,61,347,616,508,397,387,327,73,493,218,828,793,866,522,517,851,712,424,326,25,676,269,188,963,556,72,702,702,880,964,685,694,997,352,221,58,660,960,348,927,802,943,468,881,957,997,127,824,924,649,588,479,514,425,181,515,150,303,981,16,159,795,501,824,162,20,732,986,713,261,574,542,106,82,952,291,263,681,720,377,776,799,471,899,464,757,668,660,342,804,883,500,420,641,217,567,585,856,313,421,582,221,285,733,745,768,779,717,372,563,664,958,647,342,473,507,316,663,690,325,268,999,644,975,660,982,736,496,673,235,453,681,803,523,340,699,440,736,259,802,601,833,427,0,252,343,286,849,186,310,234,689,140,797,599,484,667,316,331,246,933,590,590,610,385,979,260,924,245,260,809,175,921,669,838,456,849,766,957,684,304,386,514,936,270,437,813,624,904,1,184,726,405,830,222,703,904,507,798,643,51,654,891,325,114,242,285,189,449,908,548,745,940,545,408,677,988,177,342,912,837,291,671,496,790,9,933,773,789,902,806,859,930,855,185,86,152,428,658,915,861,787,634,438,985,586,375,761,812,746,450,595,711,478,396,180,4,708,278,211,781,338,450,553,870,780,670,396,131,403,364,939,804,751,331,453,530,216,725,292,545,534,263,203,7,49,605,414,67,26,997,961,739,903,189,697,757,916,841,60,530,807,719,999,670,450,884,519,161,756,81,355,60,549,452,144,782,590,191,800,593,720,76,315,507,832,584,402,847,466,249,713,780,540,702,387,442,387,102,492,141,588,884,61,975,345,78,681,430,157,946,939,448,903,917,200,526,762,113,735,110,944,910,277,51,545,419,185,314,782,327,972,161,208,46,642,123,338,821,371,95,148,366,977,885,424,954,498,795,32,805,281,30,962,265,747,388,745,474,701,694,4,492,590,102,445,524,924,193,358,657,883,254,176,798,414,449,989,370,970,920,841,149,700,271,556,681,671,261,390,622,582,602,376,204,173,894,20,133,789,704,169,143,910,448,59,709,742,899,734,600,485,386,123,908,149,945,590,497,176,177,59,966,404,319,814,935,413,248,297,909,810,260,70,141,635,105,667,1,10,456,676,181,657,304,67,519,150,20,381,907,242,312,433,965,792,95,80,532,329,159,104,155,938,654,233,423,724,110,322,975,842,681,667,391,491,355,884,711,240,970,995,880,920,602,761,481,46,908,58,926,322,265,119,762,383,69,770,342,562,739,85,544,849,902,897,883,861,454,424,284,483,327,854,589,488,187,87,146,923,7,816,956,771,940,511,949,254,499,341,455,443,523,3,222,137,692,319,184,316,34,177,807,806,13,443,336,69,910,42,204,684,496,394,537,763,402,663,772,139,854,730,948,535,149,399,226,752,202,554,131,678,896,442,117,733,190,904,27,330,637,683,892,514,411,904,856,94,48,443,828,325,664,397,789,479,790,649,619,600,577,305,298,256,568,884,119,974,60,649,999,380,167,404,701,22,254,956,132,836,285,538,946,291,986,39,827,606,282,17,564,317,953,477,978,76,134,26,474,981,803,661,690,426,357,478,289,191,882,443,708,582,184,720,769,213,940,565,449,432,925,852,441,805,654,599,66,174,372,904,543,164,901,398,198,328,596,71,921,343,194,685,185,792,369,857,950,256,898,94,285,169,398,490,255,918,671,672,936,193,498,301,730,874,81,591,346,736,317,436,280,205,794,197,646,698,271,388,795,558,84,576,338,835,9,635,182,380,602,19,919,671,507,89,591,511,406,649,672,180,685,576,153,375,96,192,580,477,69,351,667,823,167,333,858,990,389,457,589,272,664,465,487,157,137,829,32,973,423,17,387,814,339,40,508,841,815,255,581,308,611,332,490,689,304,6,212,346,918,97,202,225,897,305,703,3,300,281,100,383,663,360,982,453,440,157,843,262,383,322,827,92,919,61,875,714,16,857,934,155,682,448,111,694,642,491,929,658,648,718,981,894,762,476,89,532,664,637,769,526,366,678,487,610,306,662,373,903,158,910,606,210,185,905", +"814,324,880,869,684,838,120,286,218,846,751,288,854,647,90,901,604,502,23,193,731,67,113,452,820,296,361,596,963,441,514,164,502,463,761,584,37,847,98,501,116,14,232,248,715,416,255,972,129,661,327,932,386,651,512,335,828,183,387,743,301,223,287,587,972,744,302,422,755,236,698,516,858,609,250,533,46,61,977,284,641,919,385,18,937,911,319,904,650,417,289,248,114,803,661,798,891,540,272,413,453,792,572,313,103,678,747,241,458,228,481,669,155,982,304,187,963,298,107,48,424,409,395,778,208,41,426,740,267,319,616,858,304,474,970,436,104,542,644,489,216,60,500,837,393,647,749,226,800,208,384,667,382,701,763,746,382,879,812,172,908,495,488,618,788,333,481,917,354,530,844,730,796,64,303,671,619,643,282,681,525,10,13,150,55,202,448,912,349,381,292,313,785,425,236,132,647,840,325,865,561,797,371,345,293,196,84,867,928,913,79,136,582,659,916,962,209,740,859,693,939,313,242,882,36,340,695,156,474,823,914,71,841,837,992,304,244,459,764,184,416,431,806,845,232,249,665,845,33,252,0,138,796,155,588,131,724,556,793,351,295,831,210,821,27,398,215,782,96,499,784,131,721,128,410,305,566,157,750,263,30,92,40,228,618,747,188,171,5,160,861,990,311,605,402,391,966,870,575,459,949,260,564,667,513,264,700,523,252,394,495,329,976,489,990,344,445,807,483,505,521,852,818,688,404,466,698,228,17,278,701,456,631,658,575,86,921,827,643,179,867,952,565,682,344,373,910,805,813,488,618,415,742,563,785,487,48,968,345,933,232,743,798,305,928,431,74,274,336,95,574,347,32,40,463,9,858,90,946,869,635,650,888,41,863,49,332,484,243,274,948,278,26,303,365,564,27,720,593,913,176,327,152,334,875,427,905,504,418,264,133,289,596,703,30,923,296,266,198,120,591,982,412,751,369,178,803,63,608,680,510,140,427,852,607,983,741,396,699,164,384,694,915,738,648,539,484,514,735,582,633,713,549,375,330,124,935,684,295,299,583,407,500,642,575,61,152,496,639,423,687,309,317,380,872,128,148,332,498,925,324,27,258,756,716,659,275,417,805,433,608,827,955,616,569,823,690,473,615,187,74,421,963,960,551,645,282,715,372,790,601,859,783,566,100,640,936,590,492,943,676,891,842,955,713,352,358,391,617,842,171,380,137,875,608,436,62,822,106,365,14,828,855,254,335,752,535,440,435,849,547,210,216,894,17,16,19,676,723,560,835,579,927,356,577,576,544,97,850,695,153,541,834,147,577,234,685,354,24,900,414,639,166,648,400,320,883,641,279,231,286,825,670,925,921,732,947,791,454,862,854,997,184,206,763,545,678,644,714,969,625,232,46,305,861,42,112,870,344,726,781,6,62,699,977,352,593,763,350,653,350,489,222,885,951,188,266,828,37,1,518,334,825,17,712,827,599,830,87,454,676,985,814,612,953,222,903,649,221,288,187,591,446,201,506,797,3,699,122,402,599,963,180,539,59,925,197,737,345,816,241,735,966,867,709,286,959,724,619,744,968,559,92,375,953,134,364,220,751,306,998,317,242,282,648,625,323,301,84,939,471,797,346,34,447,436,95,347,191,736,950,558,193,798,733,114,11,820,598,890,301,900,700,411,312,414,448,66,180,97,696,548,493,575,509,238,307,785,692,314,621,644,136,929,844,786,240,164,387,685,439,741,884,429,541,499,417,970,357,62,412,731,820,558,793,293,339,683,653,480,11,709,596,420,508,387,149,898,420,525,433,830,724,573,34,597,955,631,338,753,798,329,348,9,742,573,674,708,361,746,468,817,120,216,327,908,256,141,110,682,149,645,660,742,547,35,603,612,66,584,413,606,268,432,474,712,647,129,262,524,32,428,68,920,589,906,806,189,620,591,82,877,437,327,62,842,789,809,402,207,399,896,875,672,512,430,307,25,778,865,483,980,943,778,363,706,854,624,466,306,367,740,936,866,833,852,434,258,68,628,373,81,157,711,512,556,354,243,618,228,542,528,210,465,194,755,64,911,983,489,214,86,395,104,229,225,231,604,773,548,230,287,42,559,638,631,556,168,729,741,720,155,802,422,550,534,535,773,370,862,920,698,239,5,840,213,506,265,975,769,327,853,317,938,703,908,558,844,432,699,852,238,988,94,656,758,239,203,187,327,317,743,837,833,558,382,630,978,895,866,306,465,913,364,461,190,413,296,639,824,350,688,425,727,826,309,474,2,167,894", +"546,264,5,743,916,940,909,636,107,328,700,313,492,267,292,587,928,38,211,288,939,381,117,939,732,287,316,289,993,678,199,991,898,354,698,75,992,74,571,742,761,464,672,750,248,548,945,305,242,59,564,16,81,214,872,353,195,886,845,144,202,787,900,796,583,612,198,753,38,964,161,138,416,126,654,605,414,121,289,427,101,616,306,767,380,195,890,584,545,345,963,839,302,366,587,546,570,18,881,236,782,166,31,810,802,976,643,616,127,712,12,891,295,116,52,163,618,977,593,853,218,102,579,397,893,897,657,611,339,273,835,379,182,923,912,802,111,209,822,330,464,891,875,49,581,604,79,302,974,98,268,99,335,55,822,986,234,928,921,239,361,847,986,67,443,60,201,754,685,282,666,433,512,930,138,649,652,433,484,787,450,913,795,598,519,31,683,423,385,908,410,288,340,82,462,348,457,614,545,815,116,950,963,375,478,547,308,913,129,381,873,878,496,991,831,333,111,850,82,773,611,146,767,778,570,724,627,407,149,801,318,711,996,687,217,416,236,564,759,688,173,247,122,667,106,60,136,136,146,343,138,0,375,145,248,372,887,401,463,791,409,194,289,200,223,259,937,496,353,153,234,239,838,951,582,346,871,497,858,840,887,323,558,248,522,997,604,35,787,61,937,509,630,276,690,808,335,564,448,988,564,540,811,280,426,319,548,621,863,131,682,880,516,261,881,319,348,92,708,666,521,267,268,119,224,520,782,560,580,383,177,466,794,258,460,595,955,366,771,835,881,529,565,252,868,952,240,456,239,164,252,493,248,343,15,58,829,556,736,677,444,922,450,457,310,290,956,838,149,674,893,89,395,791,590,323,797,986,308,12,756,394,389,335,496,595,467,351,154,204,476,76,569,639,343,604,769,873,624,556,133,891,646,730,774,884,662,457,560,433,958,304,602,527,671,694,284,334,698,574,509,280,610,38,435,813,630,891,397,35,11,359,879,622,368,934,58,270,685,16,501,441,99,170,147,308,270,975,982,967,641,223,506,584,790,482,494,320,128,97,587,308,399,868,542,808,130,780,552,432,840,23,514,483,830,75,928,47,159,839,71,314,327,217,122,826,370,931,917,960,610,55,34,879,501,409,852,932,82,236,797,62,435,994,802,391,917,996,27,679,969,37,169,747,828,513,49,519,976,148,667,731,125,801,361,12,612,395,156,531,753,511,817,73,922,252,786,830,568,224,812,955,675,823,511,69,621,363,174,861,783,183,34,920,311,638,363,624,11,699,418,576,170,368,898,98,125,284,690,822,10,263,133,911,495,311,552,615,603,544,758,437,131,206,172,672,85,364,963,173,645,660,497,854,341,259,573,301,49,818,524,55,381,557,752,589,396,74,920,835,617,860,690,697,39,276,104,273,575,554,483,465,484,819,806,647,596,968,892,955,642,144,704,12,387,739,494,873,843,966,599,300,435,287,9,613,794,19,295,777,166,357,304,891,829,221,465,443,490,968,669,696,79,169,331,964,18,690,596,828,146,580,551,137,954,300,24,54,882,188,518,964,107,589,555,794,759,682,706,462,117,545,416,403,138,783,216,440,604,346,159,979,234,691,645,201,423,416,742,388,277,13,716,223,132,635,398,639,428,45,423,268,52,239,471,76,507,209,753,982,392,985,615,452,526,432,659,153,748,312,110,299,989,673,920,989,246,47,864,723,743,300,255,356,983,705,94,758,470,869,791,223,406,290,938,123,234,235,128,795,918,613,623,88,883,33,689,199,322,496,928,583,547,112,173,966,231,292,98,70,809,568,15,380,679,13,642,650,689,593,844,874,634,860,582,789,960,15,94,694,927,599,319,621,4,844,703,927,733,193,376,71,274,33,827,91,641,790,7,329,685,114,462,388,718,259,367,585,212,958,545,544,640,359,655,256,313,57,65,750,397,482,916,635,143,614,765,162,556,551,38,610,499,576,454,407,836,782,639,296,806,751,230,480,288,633,439,704,707,645,309,766,540,965,136,935,889,236,908,645,444,138,917,559,607,580,719,16,521,688,515,993,436,235,623,619,552,112,271,747,853,98,851,303,783,324,57,434,619,535,281,469,363,99,884,235,85,639,332,355,301,209,187,736,831,921,866,798,835,204,11,595,356,9,947,480,36,206,666,678,410,458,635,598,542,667,279,135,42,820,749,605,741,430,683,140,895,430,489,720,753,822,445,542,646,671,865,593,950,214,142,354,263,974,805,633,738,445,178,966,766,260,34,489,310,971,293,565,474,612", +"374,10,389,702,343,338,935,400,442,238,179,235,577,626,11,499,56,975,983,265,51,510,960,483,91,571,468,59,71,129,383,851,551,283,98,702,12,408,984,576,826,73,3,343,498,839,964,354,495,456,782,213,65,644,954,765,597,536,285,453,34,191,474,114,690,694,660,177,657,301,481,424,227,270,856,652,247,3,139,124,974,649,430,873,78,149,798,844,685,840,240,596,559,212,4,192,66,821,872,120,406,352,23,876,872,617,72,732,724,146,121,542,674,216,146,949,76,432,850,899,694,743,720,240,74,795,997,588,227,560,70,461,584,176,868,516,135,625,132,127,703,809,349,503,151,58,843,280,767,732,647,869,170,922,295,302,139,619,940,699,751,719,408,650,477,763,874,693,700,835,802,928,929,650,207,793,920,292,494,876,560,161,596,252,34,163,188,447,318,191,632,413,708,700,648,325,992,8,792,421,331,797,144,988,223,845,910,386,310,59,257,15,201,644,808,136,176,148,890,252,312,285,963,416,603,729,520,316,963,866,397,422,330,945,745,552,546,728,935,977,70,888,343,632,789,206,929,304,383,286,796,375,0,558,137,689,748,837,530,13,273,810,660,773,242,72,2,438,264,31,333,960,223,985,721,458,59,376,730,198,968,861,320,281,38,448,825,872,63,317,320,598,625,218,326,491,176,356,788,17,76,999,129,895,162,149,986,337,379,569,866,64,670,75,296,235,338,400,206,177,737,832,845,453,661,578,897,47,437,299,160,932,290,197,842,243,201,121,249,483,480,383,845,361,877,835,865,561,239,309,832,581,668,326,654,180,46,440,367,92,107,492,584,399,57,683,358,623,949,805,195,902,845,106,965,567,908,869,923,655,900,82,944,292,711,429,913,887,55,485,962,976,514,541,721,748,951,568,390,872,721,230,857,57,20,149,894,806,143,867,787,771,523,625,672,235,892,210,701,570,594,656,747,151,665,697,909,479,251,848,942,151,400,914,20,871,328,426,761,717,383,177,752,325,946,135,724,678,859,579,813,458,778,782,306,488,594,19,27,699,386,544,986,745,571,83,455,774,693,791,150,778,645,768,548,528,666,810,708,907,56,441,447,58,811,479,324,635,226,828,401,691,81,976,922,679,260,135,496,746,361,274,303,322,869,579,877,446,282,862,184,962,154,997,949,57,530,328,802,131,307,760,933,689,497,301,603,897,414,171,909,601,247,237,711,269,699,239,287,838,579,896,662,221,211,718,730,2,20,366,570,1,688,290,87,669,474,811,685,850,720,968,221,887,373,688,101,743,933,944,381,310,966,129,232,138,749,209,290,385,196,439,306,138,840,745,408,375,812,131,347,501,213,655,967,99,455,31,384,149,572,4,853,697,199,296,31,155,547,447,134,995,989,674,390,134,156,49,401,88,231,864,340,519,642,651,229,48,636,199,9,663,836,490,931,80,902,290,550,82,613,527,159,226,68,643,905,171,342,264,220,660,802,110,379,99,439,788,749,998,509,376,560,652,103,61,828,955,987,443,268,916,228,991,198,787,607,949,759,406,662,195,210,458,480,188,393,888,562,863,517,210,306,811,286,188,701,371,29,867,809,509,438,144,23,911,66,124,118,436,949,923,520,845,331,177,741,882,613,609,17,602,205,779,678,655,331,620,614,112,975,900,465,775,387,484,692,373,842,811,738,418,791,819,850,512,497,240,616,673,12,8,280,608,381,595,556,666,539,502,786,857,197,372,560,777,757,471,537,637,856,150,926,512,564,313,313,318,421,342,1,224,352,966,797,109,172,955,463,281,609,561,522,627,38,930,388,489,864,905,297,952,847,739,562,344,660,120,358,567,304,875,627,825,291,500,26,366,768,522,113,24,708,871,850,209,807,555,338,55,942,873,731,48,490,165,819,288,855,355,566,785,766,127,714,734,468,527,590,523,164,916,298,71,955,57,626,895,600,738,458,97,47,204,886,470,521,720,793,6,255,583,300,558,96,43,178,645,560,545,825,468,301,400,887,18,880,611,297,240,291,759,121,861,196,673,307,779,160,466,88,964,550,341,606,700,931,925,892,637,304,478,990,491,106,319,977,469,888,205,917,303,920,888,614,161,833,854,68,608,785,888,71,550,390,988,199,867,752,184,617,140,732,841,781,383,755,852,180,93,249,340,386,63,338,463,377,389,247,335,187,637,664,758,217,460,212,575,148,487,522,663,650,279,305,334,776,464,145,767,906,714,981,581,340,475,946,339,833,625,123,951,728,245,296,766,407,251,224,576", +"771,538,660,585,55,791,557,68,525,740,956,770,582,616,418,225,626,705,45,37,219,554,45,679,471,461,408,627,970,128,769,599,629,634,798,125,427,107,342,322,202,191,349,810,439,866,888,116,412,376,212,113,606,421,188,423,208,5,113,898,240,971,91,553,706,482,726,500,309,678,657,4,149,86,60,750,8,503,576,479,865,907,98,152,876,232,429,821,198,50,611,627,597,539,253,196,656,713,428,230,552,949,872,129,843,488,746,781,281,359,129,747,930,303,435,100,680,19,231,545,110,535,340,765,815,945,601,724,379,942,282,351,173,474,152,765,790,44,934,7,278,482,825,559,876,63,209,188,789,495,106,109,740,293,592,168,343,942,553,996,613,480,724,726,179,936,520,854,34,635,468,455,44,277,744,356,742,612,772,949,595,232,438,541,891,123,164,55,576,558,369,244,67,395,32,5,762,717,681,80,589,832,570,289,675,765,150,838,777,371,4,601,105,660,292,216,916,84,35,583,42,900,858,357,917,705,794,53,336,305,204,42,461,837,320,18,645,244,531,168,175,286,301,740,503,680,878,805,567,849,155,145,558,0,262,561,162,196,123,45,205,876,263,162,342,258,47,748,279,620,875,132,133,443,21,155,975,649,988,72,369,382,567,429,718,418,161,191,484,237,754,190,322,43,993,783,581,224,566,296,496,574,231,440,79,381,125,892,531,17,338,983,423,382,102,670,746,14,322,541,386,239,752,545,797,824,332,960,229,693,340,355,939,278,809,816,152,512,604,190,670,742,943,427,527,234,786,194,816,103,225,985,863,207,860,308,229,145,80,698,735,685,263,425,956,213,16,912,653,172,783,72,714,276,355,511,642,570,331,382,982,887,846,431,472,248,43,142,921,635,936,327,94,87,585,296,249,866,984,604,687,732,786,705,30,456,596,704,371,963,648,986,150,762,102,971,594,204,767,277,924,932,836,722,986,22,963,541,696,681,273,671,628,442,420,964,559,848,494,169,244,49,490,166,725,535,806,421,651,104,193,208,88,629,937,894,642,682,371,256,233,563,562,373,176,473,759,204,302,377,332,370,44,18,233,686,235,421,115,678,753,213,520,949,795,783,128,414,404,986,865,161,209,310,532,126,429,171,781,612,672,205,868,861,364,777,891,489,733,532,239,359,241,47,75,236,272,300,947,835,820,523,649,766,644,719,790,794,791,462,337,781,415,69,933,314,393,823,315,712,319,950,40,312,486,740,18,111,902,60,508,50,896,434,884,344,564,760,680,321,657,572,876,423,882,860,398,416,228,861,596,409,604,215,242,44,746,418,853,670,999,426,93,221,613,656,272,902,996,617,956,324,980,943,766,292,461,699,284,216,981,944,944,20,820,421,861,23,484,773,969,221,939,181,279,425,75,902,258,231,642,658,356,57,444,909,365,629,390,563,165,291,100,282,267,911,6,382,435,520,546,136,675,530,378,535,679,591,987,918,75,454,587,609,304,876,358,150,174,234,686,388,914,489,653,503,657,122,986,780,448,10,520,722,927,497,869,696,337,957,528,646,375,568,369,408,47,887,16,371,114,404,253,146,483,737,955,627,372,807,903,565,704,105,970,379,828,897,538,595,35,320,791,162,913,11,778,934,431,672,124,363,537,972,775,893,42,229,318,220,809,766,852,408,325,337,167,595,335,502,33,566,423,426,428,305,48,263,707,897,62,400,720,591,489,892,187,50,105,487,860,768,160,911,430,472,693,812,735,59,932,363,6,150,762,750,384,464,28,110,200,940,987,134,928,973,835,193,11,453,386,891,190,413,708,937,192,260,554,418,32,585,751,747,83,3,187,371,446,544,255,252,226,230,932,110,996,737,770,231,660,104,585,370,361,472,483,446,476,793,827,264,235,217,646,609,486,33,357,56,75,840,569,162,612,993,291,189,899,892,161,884,529,161,239,678,138,241,618,583,139,590,945,194,693,634,810,548,153,223,16,94,413,799,196,40,94,367,647,996,416,77,177,47,241,53,875,952,542,758,303,331,719,333,818,71,968,680,791,380,300,609,389,751,147,173,538,61,723,599,950,190,764,971,978,314,915,768,108,735,36,892,43,433,442,796,787,544,906,145,559,943,974,416,90,636,717,740,710,121,588,895,247,785,643,499,888,649,57,690,825,410,8,377,110,297,212,130,127,945,392,247,972,533,167,330,95,102,604,594,947,297,476,791,167,435,572,674,339,627,155,238,528,414,102,293,83,629,887,910,338,80,922,740,691,507,568,509,707,432", +"683,808,481,401,767,594,541,607,533,853,955,101,701,561,360,998,433,388,108,444,103,881,412,563,868,265,862,265,655,813,488,230,994,215,263,561,905,397,902,503,478,728,767,538,673,944,883,149,988,917,826,496,733,472,619,463,638,232,349,690,984,153,235,808,373,303,805,916,647,640,927,353,231,925,19,397,630,140,292,212,926,797,522,812,692,881,374,723,252,186,152,249,849,177,219,201,171,946,72,288,160,886,887,757,73,200,340,619,301,846,698,255,191,722,880,997,350,33,425,660,439,611,514,830,536,919,63,19,18,502,609,522,548,637,276,330,758,392,332,898,114,495,121,75,443,575,133,212,969,891,810,402,836,820,751,235,994,424,12,723,231,756,609,737,391,892,280,933,561,654,793,390,76,824,88,726,29,452,204,311,664,864,491,395,887,214,816,188,591,607,550,522,930,695,598,763,334,110,965,255,850,352,147,321,855,578,237,529,337,217,175,105,58,14,413,941,24,642,968,541,658,371,734,244,223,994,724,116,195,376,711,887,579,6,643,685,430,851,259,283,524,972,498,989,148,738,157,583,38,186,588,248,137,262,0,733,827,26,758,389,468,648,45,181,702,24,274,539,578,589,792,642,883,841,920,875,73,976,973,323,751,735,32,393,512,300,736,770,788,621,363,225,794,194,431,55,989,212,880,905,729,849,273,344,643,465,394,125,951,343,892,872,849,653,447,711,555,932,646,203,528,801,941,278,401,180,866,610,301,217,903,585,140,156,569,557,271,718,103,857,436,577,5,641,886,128,615,993,830,491,759,82,439,175,549,650,568,963,132,152,756,67,778,104,939,160,964,629,306,688,118,272,920,461,573,172,395,355,147,529,944,33,402,99,466,76,470,981,798,556,948,745,79,146,88,319,846,715,264,994,685,37,594,144,852,326,656,704,356,544,390,699,325,73,999,468,412,732,487,162,864,90,38,811,87,974,273,564,404,444,245,432,974,270,362,13,599,929,691,312,892,678,237,16,340,652,347,823,659,997,684,163,803,216,848,518,309,675,169,128,634,842,954,994,820,127,131,802,535,768,990,887,430,523,623,646,106,384,633,386,16,423,428,33,943,727,433,846,45,672,240,101,171,721,60,524,582,520,159,288,592,323,670,465,405,306,183,58,368,120,472,565,475,903,126,960,761,335,219,587,708,639,459,921,776,507,569,96,470,54,837,874,824,187,601,74,915,287,999,520,285,385,420,355,111,12,770,47,617,39,259,313,682,302,820,121,502,356,560,450,445,97,626,832,89,25,286,547,286,910,418,346,506,69,184,447,32,295,8,824,703,774,990,6,211,828,242,383,569,619,418,509,288,868,997,538,449,564,269,438,55,653,702,8,334,602,108,391,835,71,301,553,751,265,331,684,295,675,957,216,12,189,324,588,560,159,484,594,801,990,828,179,641,979,97,44,40,374,998,794,274,811,442,339,77,171,782,716,157,77,61,743,398,330,178,359,133,441,463,971,89,860,124,312,365,190,255,670,431,223,481,147,836,897,272,911,856,214,512,294,264,885,594,334,726,226,933,46,417,380,412,899,471,208,25,369,345,860,157,112,617,905,525,757,217,554,41,966,465,598,286,841,545,110,228,218,222,45,906,155,211,99,168,668,638,780,938,742,939,920,289,293,118,843,900,992,856,546,962,475,65,826,953,834,492,518,802,824,632,117,107,820,368,864,730,412,483,840,720,866,728,440,39,548,829,424,111,739,21,693,13,182,72,501,304,547,129,465,6,534,221,235,24,616,624,525,828,125,85,36,699,789,18,672,263,695,435,51,866,110,246,949,443,906,143,602,987,153,701,612,813,658,754,217,752,970,874,409,570,890,644,697,841,54,904,228,440,57,312,494,671,488,839,970,7,693,289,782,964,166,359,822,159,932,474,124,387,560,213,12,778,140,996,330,921,882,352,809,659,211,888,271,431,129,918,755,980,141,446,667,211,898,925,192,388,24,464,889,406,312,700,381,251,50,689,79,446,617,81,578,460,923,994,500,645,869,243,550,559,915,541,956,341,178,321,466,267,663,126,271,804,913,719,976,514,85,931,48,168,309,385,733,280,287,517,455,388,50,617,526,879,626,463,833,605,554,852,847,651,66,116,318,363,85,490,279,946,862,399,645,615,735,284,404,800,352,826,163,752,99,678,155,653,176,766,534,322,593,301,329,262,237,828,765,66,795,531,593,717,793,361,365,365,164,246,436,101,991,266,349,492,712,907,79,301,841,151,923,913,169", +"730,114,221,725,754,427,706,755,416,596,732,496,357,860,293,418,382,729,421,108,57,75,406,544,790,655,975,909,724,688,440,285,328,675,843,408,986,120,443,444,521,570,589,273,59,507,977,421,699,643,229,252,278,538,632,167,600,4,41,241,800,9,879,530,937,540,186,379,855,240,677,92,977,511,957,565,521,346,2,615,616,674,603,135,509,75,502,890,555,627,593,311,842,607,753,12,977,550,337,101,174,49,906,270,124,500,782,684,570,274,273,257,9,180,372,977,69,947,424,91,565,958,214,865,562,789,523,798,232,181,988,905,819,738,849,365,240,682,753,624,985,129,926,930,94,849,538,729,794,129,257,846,196,494,51,1000,642,874,899,233,136,611,353,321,668,407,562,3,764,146,214,212,146,609,347,890,981,292,567,719,872,155,432,758,213,732,788,112,132,110,916,700,149,517,911,366,598,488,502,743,9,393,847,527,295,414,188,6,889,565,697,515,733,295,70,149,511,460,806,432,586,605,85,800,749,157,209,898,639,866,576,885,999,307,296,840,549,62,222,81,650,916,706,569,245,418,401,59,851,310,131,372,689,561,733,0,821,14,913,311,651,687,503,737,156,442,799,55,513,401,204,313,395,393,332,721,117,200,578,261,259,761,418,396,691,287,240,270,818,752,443,710,90,867,112,803,630,257,918,749,33,284,416,164,443,862,994,734,139,150,971,591,457,43,560,939,880,745,191,518,576,893,143,367,298,313,484,74,844,679,42,317,494,764,967,626,916,217,109,422,816,186,541,153,579,837,282,573,132,991,204,139,996,406,231,154,125,565,674,478,552,884,737,161,376,930,581,346,193,506,142,541,726,249,483,581,28,936,48,865,552,145,331,324,102,189,218,679,239,638,942,510,635,956,529,903,278,824,632,535,502,72,157,792,560,777,675,558,185,876,475,880,676,81,920,152,943,927,264,401,508,689,769,573,749,148,781,401,859,411,53,428,667,119,753,440,534,965,653,74,620,992,796,638,51,919,614,55,819,510,900,190,696,70,603,646,961,396,763,528,980,859,937,651,474,633,595,837,446,657,887,266,172,952,320,119,276,323,408,136,31,480,621,927,901,384,6,170,293,217,979,592,161,381,542,789,610,957,144,619,260,11,276,713,390,607,995,802,490,702,371,368,87,825,90,455,523,915,414,894,939,672,49,693,223,852,735,501,85,341,554,502,872,788,640,394,18,958,190,920,964,972,313,313,474,568,630,341,581,919,243,315,914,699,298,848,355,188,986,346,409,419,358,705,97,596,440,784,833,406,623,498,432,630,296,725,570,529,645,473,805,191,132,94,818,33,673,184,218,637,751,734,813,506,361,398,314,689,160,693,196,491,751,53,969,330,497,713,542,810,136,351,185,960,940,670,956,694,204,368,261,121,9,472,450,914,151,717,338,237,837,27,269,587,443,279,521,708,770,796,328,640,361,15,625,186,180,206,480,925,190,440,871,600,268,818,44,981,134,440,449,644,329,639,919,275,790,780,146,482,155,680,699,330,153,971,895,201,389,93,838,883,277,589,39,937,161,492,669,978,261,349,387,640,988,300,596,84,649,571,452,122,904,743,218,661,903,770,431,424,247,937,123,630,944,614,553,414,425,197,57,2,252,710,457,924,321,425,621,890,402,459,142,818,350,425,212,101,497,513,653,744,211,895,401,241,658,896,715,587,34,705,8,966,413,137,293,998,61,54,756,274,759,722,178,155,268,978,340,33,828,996,830,162,504,576,386,304,693,362,650,584,821,555,519,725,279,204,938,842,806,963,645,624,275,431,711,523,217,332,913,968,992,15,328,875,377,893,322,347,122,75,337,892,28,677,35,70,308,121,925,974,39,903,321,368,495,450,294,19,842,270,264,636,79,977,125,853,823,311,786,224,932,147,409,977,600,296,216,84,458,602,408,61,582,641,512,880,993,510,424,370,486,888,163,701,605,789,89,157,971,68,60,347,447,609,713,542,240,342,642,874,676,34,535,478,807,35,108,541,611,670,988,323,53,470,997,827,70,365,82,941,736,916,464,842,443,699,955,441,782,234,404,954,890,891,308,803,89,290,205,180,665,144,816,235,631,479,708,743,201,533,649,964,721,247,419,529,231,337,374,560,389,424,802,463,643,898,375,3,462,648,424,84,589,609,188,656,754,77,625,268,779,942,19,715,381,311,80,550,407,874,980,930,795,846,821,620,18,577,29,435,912,193,780,281,257,511,256,144,903,187,909,995,217,937,577,923,407,776", +"478,389,771,478,289,825,587,853,212,377,322,492,398,764,966,113,179,701,254,696,882,432,156,981,220,752,211,552,769,697,440,992,708,934,124,916,865,151,541,165,174,883,829,442,776,960,64,917,378,524,566,496,395,861,51,632,383,731,380,409,192,534,557,171,1000,84,589,49,973,428,207,766,151,514,308,626,66,434,842,217,807,507,649,646,277,429,486,147,952,18,178,519,356,297,976,645,786,112,142,537,551,947,56,743,647,312,935,953,366,271,889,850,557,810,971,832,975,937,166,12,791,330,23,168,452,283,575,251,886,568,44,719,781,425,599,982,763,297,47,995,120,37,670,601,746,722,174,613,349,796,740,978,787,308,169,502,147,722,568,285,615,669,727,705,302,239,756,443,273,309,449,151,436,731,700,73,282,665,876,451,495,284,377,394,822,427,335,51,197,998,838,420,278,269,956,952,565,143,602,895,683,745,614,82,385,606,714,887,116,820,326,544,66,118,485,604,8,643,165,823,384,530,960,936,467,211,523,166,80,642,658,392,902,544,904,138,904,583,717,3,509,182,798,925,334,151,179,47,99,234,724,887,748,162,827,821,0,200,760,986,329,255,239,178,241,427,567,944,233,108,831,787,463,639,86,888,487,638,154,422,608,355,118,108,290,864,990,331,713,234,559,285,697,179,497,579,919,729,749,520,874,759,696,578,264,540,239,447,252,946,244,4,269,760,341,812,979,902,524,317,83,206,344,821,545,744,357,295,161,558,270,189,902,500,189,973,822,590,551,919,512,808,848,214,469,993,483,360,464,523,680,500,418,956,970,20,701,341,639,927,295,906,714,707,62,82,481,492,982,169,89,930,472,333,171,111,367,453,349,831,72,875,105,923,980,965,174,208,301,62,54,225,450,309,643,262,325,721,378,224,790,480,782,338,678,230,951,607,405,241,200,230,425,376,960,621,948,314,622,558,604,901,654,464,869,371,289,129,393,759,936,251,112,300,753,67,897,311,325,829,382,602,45,815,959,297,248,255,134,969,117,660,765,207,94,227,708,796,361,471,130,103,807,732,84,404,184,827,712,889,912,125,906,156,9,762,830,349,933,61,650,895,226,812,312,566,617,304,350,376,854,184,911,306,408,576,748,261,352,349,320,658,754,285,616,601,576,14,676,848,710,9,720,493,222,171,892,385,883,300,347,711,157,602,745,508,347,122,758,757,95,547,768,42,575,704,395,741,748,30,491,632,348,845,540,697,209,280,50,817,741,94,809,206,590,657,17,556,452,674,962,194,54,933,584,14,411,150,873,535,200,220,233,961,798,813,496,788,109,739,213,775,611,134,283,744,687,775,676,318,684,52,685,811,648,717,629,326,234,389,686,628,680,949,78,678,486,325,994,16,190,866,372,205,908,577,588,86,5,9,405,749,831,373,607,96,927,210,768,477,813,350,358,989,99,968,756,378,10,647,879,954,105,568,215,16,961,142,243,581,429,225,207,762,409,505,74,976,324,130,735,379,493,508,404,85,852,28,816,655,128,171,896,530,886,998,129,818,572,19,627,562,501,473,618,132,164,531,846,347,364,282,205,213,321,801,869,146,660,450,841,87,269,347,503,250,652,252,201,421,214,633,121,543,45,236,197,352,86,248,287,372,188,396,143,110,108,858,179,618,572,741,874,582,258,260,724,112,291,543,961,473,362,808,250,355,35,841,507,512,525,149,201,908,235,711,273,720,418,956,39,48,168,271,31,461,80,867,311,564,871,142,707,546,757,476,827,907,593,811,814,750,943,43,570,996,592,197,493,536,59,516,349,707,841,908,721,261,250,236,982,366,234,285,936,401,188,932,125,827,236,927,989,458,216,644,306,286,746,315,810,196,815,55,151,39,103,778,129,281,306,472,110,526,616,332,30,348,674,482,182,217,965,67,668,278,657,152,946,856,786,197,990,577,469,3,730,542,786,661,603,405,781,79,573,884,837,624,623,682,51,271,347,43,520,23,917,720,609,880,383,547,141,811,709,740,294,502,327,868,384,131,23,653,916,642,999,641,406,228,61,666,58,982,221,503,311,81,531,199,811,637,570,74,531,58,411,286,67,771,396,894,931,432,720,742,295,635,475,558,22,420,574,517,988,474,314,65,912,279,952,440,204,545,69,748,549,387,372,771,56,995,27,465,315,755,124,544,835,190,801,192,766,724,49,231,36,434,469,999,669,814,384,737,301,60,924,757,753,886,416,734,599,67,700,949,737,10,657,349,169,235,947,590,967,514,58,992,561,105", +"446,563,398,889,190,688,419,301,222,188,865,7,928,38,373,211,458,76,540,496,461,219,899,381,395,716,117,131,247,438,5,158,347,700,800,843,737,254,65,695,217,699,671,502,307,391,326,464,991,6,543,48,453,918,851,144,865,706,48,738,44,112,499,204,678,740,801,780,826,808,385,114,201,739,651,798,991,902,65,788,26,269,652,857,367,101,241,802,175,667,32,367,690,944,49,236,654,459,618,51,205,991,463,46,83,296,932,738,354,602,436,56,761,181,987,310,581,699,96,374,212,59,880,319,876,484,438,641,940,189,207,967,592,317,158,432,429,312,265,73,578,260,898,977,111,524,907,170,102,289,527,437,840,351,168,560,313,580,461,562,705,65,536,379,543,605,329,809,313,218,119,57,190,62,583,358,915,491,132,902,833,680,121,770,804,777,485,70,38,191,909,258,427,705,521,197,546,730,969,207,941,230,312,815,521,7,208,676,786,565,266,751,856,534,297,416,710,316,340,157,998,303,311,98,91,45,92,608,737,973,845,570,854,113,528,448,574,511,38,487,23,49,902,674,288,469,409,854,175,689,556,401,837,196,26,14,200,0,927,900,446,980,911,143,822,336,526,99,129,885,446,621,432,317,196,175,672,124,301,539,523,977,924,118,171,341,448,187,81,87,798,541,947,398,872,754,758,414,761,842,985,920,141,542,351,388,657,284,503,968,436,87,76,651,10,573,617,656,268,512,761,850,55,748,799,376,74,771,144,189,265,544,84,772,862,438,544,387,435,647,770,182,245,732,564,758,824,264,416,420,9,484,457,894,923,90,787,571,624,388,233,637,995,150,435,581,565,180,642,990,835,1,532,265,464,411,722,654,606,880,207,406,962,27,877,601,956,807,546,57,879,139,897,443,883,390,936,160,724,387,112,651,722,469,623,345,519,324,988,39,416,981,188,782,230,124,645,497,391,37,816,559,742,368,788,74,323,107,378,110,17,205,103,456,352,628,983,244,712,577,325,502,181,829,624,288,541,751,893,40,430,963,903,601,391,609,932,989,353,803,203,313,135,159,95,999,353,97,843,940,998,505,857,197,144,90,309,947,485,469,721,388,895,651,834,49,847,40,808,379,280,841,656,6,709,990,782,189,572,641,905,429,86,921,130,561,40,965,251,197,377,650,192,407,842,118,825,226,156,228,451,409,356,862,711,54,861,922,120,589,339,824,832,660,703,772,391,981,991,100,466,129,497,185,629,996,321,884,983,64,675,833,14,542,286,770,865,905,657,675,577,569,11,836,426,448,354,820,949,288,32,270,180,11,741,319,535,152,648,33,696,807,233,492,151,458,308,479,291,614,666,608,109,560,692,101,242,437,687,194,203,411,529,508,352,689,83,592,191,394,379,319,768,281,636,857,447,425,773,853,429,575,291,902,787,553,538,641,465,143,928,140,339,633,702,836,616,757,850,700,384,569,551,946,638,830,9,760,376,768,680,25,252,210,967,691,231,849,104,967,675,730,138,216,663,652,642,607,300,236,266,243,78,295,22,964,709,249,719,569,689,228,959,247,285,555,246,665,132,346,87,665,905,588,253,554,702,752,239,203,404,972,541,557,17,711,182,525,43,438,134,229,740,486,80,137,27,120,418,120,667,1,912,742,64,298,226,273,811,427,547,456,960,822,630,646,793,319,48,125,382,189,629,888,919,739,514,115,78,317,654,724,106,882,936,832,941,142,112,550,609,331,708,832,473,698,363,273,612,259,107,486,604,277,98,72,898,660,974,279,297,65,173,597,879,958,152,461,87,231,947,95,99,838,919,702,735,359,88,661,168,401,796,905,791,296,817,367,773,164,603,845,350,113,112,234,908,879,67,464,456,668,617,909,353,910,40,896,534,315,72,878,476,746,468,47,276,988,605,340,679,241,929,511,785,594,908,764,286,708,742,962,311,167,565,903,588,471,10,569,442,471,475,981,105,616,791,273,728,407,268,908,108,822,385,934,426,358,26,472,934,26,846,953,681,559,388,403,26,507,823,792,460,278,809,78,739,242,362,982,946,728,806,841,67,685,648,66,400,452,38,647,681,3,705,29,853,346,824,627,607,635,105,960,17,715,96,960,397,119,868,505,376,216,87,456,161,911,676,326,875,787,810,687,716,751,181,463,982,601,390,922,513,339,892,424,809,615,526,35,379,688,854,576,819,287,958,129,979,907,866,243,226,256,474,889,359,776,852,579,783,139,460,893,987,243,553,644,416,832,746,418,167,566,435,730,463,919,413,184", +"456,375,304,796,185,535,755,494,225,313,592,867,755,459,489,156,978,538,947,664,591,443,873,809,550,377,918,62,628,601,680,858,324,572,41,515,268,307,240,466,732,746,994,130,379,601,999,233,360,219,373,426,781,703,765,871,487,868,779,836,178,247,601,914,413,442,158,904,221,645,110,333,209,99,254,155,42,424,363,932,138,275,875,744,779,664,997,239,622,628,634,966,160,29,584,637,127,303,862,103,710,404,813,8,404,133,792,815,589,170,91,22,547,40,702,15,147,725,288,905,856,75,645,311,626,568,445,219,814,5,201,773,997,178,618,445,565,236,236,814,238,192,844,726,615,630,179,697,387,682,624,954,994,234,405,98,11,691,564,567,872,140,676,106,691,460,8,623,301,340,588,237,356,675,448,693,493,762,540,22,667,810,131,659,494,547,216,32,162,431,348,856,113,528,859,407,988,446,489,932,965,830,567,845,392,808,989,736,831,515,79,196,575,528,949,466,944,723,911,231,774,451,288,221,310,980,111,664,432,39,215,806,996,784,400,919,938,486,518,657,680,1000,730,465,640,571,99,75,744,140,793,463,530,123,758,913,760,927,0,757,414,540,762,48,408,602,628,891,110,82,27,463,573,521,644,255,721,972,95,13,261,383,893,279,378,213,27,296,241,807,363,240,532,447,56,7,782,367,504,930,70,340,520,974,712,164,386,462,262,672,930,491,774,604,150,984,541,234,144,296,951,953,513,680,556,7,622,936,433,871,946,537,698,78,408,690,751,178,743,981,628,627,986,756,926,935,551,80,883,89,453,906,64,505,544,425,148,996,413,2,67,66,553,274,149,890,482,660,29,391,512,725,244,644,536,348,384,903,316,702,865,997,473,276,809,275,818,677,911,871,932,32,600,546,215,569,424,621,880,290,745,258,505,6,456,897,868,450,367,342,767,280,525,980,421,593,925,135,753,791,336,290,951,124,140,877,167,918,995,420,403,280,801,401,602,731,25,3,760,19,627,27,248,404,827,900,297,540,705,465,170,916,350,793,157,637,638,768,834,835,507,323,18,865,882,391,907,646,201,500,312,93,94,596,739,762,877,21,853,999,476,804,776,687,81,441,15,345,916,561,160,172,986,682,322,326,951,347,640,602,383,714,418,785,982,15,282,275,54,764,518,652,743,341,512,218,748,39,264,443,972,679,788,794,227,256,921,827,777,701,604,386,735,44,954,42,897,273,704,178,298,217,982,438,971,32,271,56,300,807,106,214,707,528,502,864,976,797,145,312,798,23,115,697,988,545,856,866,72,328,862,959,890,525,401,865,712,257,505,909,767,555,403,514,624,673,594,172,240,826,532,819,463,238,76,792,685,392,408,227,831,451,622,359,93,92,522,473,235,169,715,611,690,87,276,521,31,231,198,526,959,808,342,452,212,474,859,133,860,916,487,859,235,725,562,260,893,223,442,699,604,909,664,108,909,55,566,867,718,888,68,154,504,953,873,450,553,2,969,959,419,165,499,358,911,603,653,326,108,299,674,286,949,784,691,848,975,17,101,2,756,216,447,492,993,374,226,22,455,634,210,482,519,278,888,460,142,858,312,992,141,362,992,180,850,972,243,380,287,202,417,345,678,260,513,14,342,256,233,699,102,566,539,51,107,947,866,40,253,925,632,990,937,401,162,710,814,527,270,242,301,766,376,184,898,659,167,240,68,554,619,999,795,223,14,739,543,674,419,25,32,634,859,481,939,720,663,409,856,876,982,784,343,893,173,264,144,243,613,581,414,134,317,780,170,34,523,18,67,453,311,669,767,620,187,241,90,804,311,347,591,717,744,739,642,482,239,349,805,920,929,433,57,113,889,858,763,305,246,198,509,587,713,660,816,986,227,29,710,168,684,204,847,1,348,369,997,238,875,921,511,55,191,385,751,322,128,208,214,641,79,159,802,752,567,862,537,239,816,515,6,917,111,263,942,518,428,765,129,814,39,202,107,278,77,925,112,662,234,283,388,246,400,117,89,699,146,924,285,52,230,228,641,776,847,543,524,946,681,603,833,521,342,766,424,353,593,772,461,288,981,585,168,78,138,749,354,511,949,746,716,898,505,934,597,712,78,413,307,206,600,173,836,777,239,724,733,165,944,579,526,643,997,186,62,325,349,457,167,77,784,219,477,381,595,445,446,658,497,608,821,358,782,453,643,159,414,626,314,246,453,487,280,444,450,360,771,236,410,446,502,175,191,963,785,198,804,559,937,950,274,364,414,613,750,26,818,679,185,181", +"447,421,816,244,906,185,576,359,349,234,89,627,604,285,668,283,771,956,513,960,370,575,657,543,580,244,847,540,541,187,79,32,160,571,973,923,717,418,253,683,267,116,453,458,603,922,979,256,767,789,198,435,804,355,535,698,936,432,558,389,743,964,891,333,242,330,89,397,299,516,651,596,720,787,538,864,952,43,651,767,154,840,966,401,454,266,760,668,704,245,253,471,755,78,742,363,90,120,985,519,192,49,145,732,813,673,898,113,797,596,206,832,562,381,695,847,249,976,867,67,654,99,261,245,853,848,429,170,433,815,126,821,311,349,150,921,178,956,589,508,432,682,87,498,794,657,890,328,366,388,860,302,241,755,722,794,858,612,645,837,365,198,100,886,485,448,18,627,26,314,174,739,691,273,996,431,82,919,740,586,130,873,516,561,137,271,864,963,456,843,730,351,536,784,488,100,392,291,739,46,527,866,258,985,764,128,646,76,708,526,40,371,365,987,584,415,255,528,780,610,89,609,327,677,864,466,415,592,364,603,634,293,71,138,35,482,866,158,296,208,20,651,452,772,298,11,85,693,540,797,351,791,13,45,389,311,986,900,757,0,993,796,945,995,728,747,543,417,41,802,378,694,362,63,134,732,296,640,740,458,189,45,947,823,262,335,198,65,819,682,795,734,763,80,64,619,329,779,37,774,556,381,72,532,576,640,647,124,23,784,552,776,344,505,522,381,176,907,304,188,325,317,590,413,574,688,257,737,603,450,670,77,232,730,105,772,60,927,518,246,172,264,929,84,521,260,123,356,327,736,343,954,312,884,482,266,131,376,717,611,223,143,115,875,321,807,995,898,403,1000,374,29,109,31,788,29,676,655,542,35,885,906,102,795,848,240,338,845,952,412,102,947,363,827,464,328,898,55,219,943,459,270,783,395,858,719,885,863,319,594,893,610,457,808,520,192,97,379,800,75,944,857,396,978,463,799,870,56,61,400,301,689,19,793,286,444,467,620,316,867,591,548,319,393,862,882,684,607,97,736,278,869,348,463,378,98,916,868,190,499,527,898,386,689,112,614,896,686,361,438,80,323,699,312,385,341,497,223,16,155,101,995,615,566,852,97,166,884,318,20,902,50,73,626,264,120,565,653,346,77,888,303,323,799,471,904,460,146,146,407,230,440,267,414,700,379,952,905,103,707,584,949,15,179,123,409,452,885,474,878,846,642,463,964,378,629,235,690,909,885,69,613,365,137,547,685,725,182,7,963,339,501,238,140,208,217,934,68,959,148,420,963,908,890,567,265,207,680,95,701,868,79,597,274,101,100,276,914,231,994,849,532,389,425,601,666,402,260,299,263,971,315,878,62,211,164,266,539,594,659,657,458,217,545,648,390,26,365,916,914,855,527,555,124,627,29,260,959,790,394,796,515,957,447,642,89,754,322,137,318,819,809,909,206,652,656,314,489,889,108,637,930,107,382,732,2,308,33,463,681,776,230,507,94,847,380,733,713,99,945,945,889,581,524,464,390,976,796,145,944,208,925,207,48,201,391,708,244,275,722,616,874,747,686,627,903,269,164,741,450,546,652,925,114,313,352,747,731,273,669,49,233,887,614,144,926,423,189,317,186,336,519,837,794,208,345,258,39,374,149,703,945,697,739,733,172,995,549,670,630,853,104,614,462,363,990,362,36,932,96,449,286,286,874,30,137,147,591,127,943,974,691,835,982,509,809,262,372,922,206,792,696,383,522,465,180,730,419,887,391,116,802,8,380,896,334,801,888,261,810,746,580,946,207,907,331,509,522,950,892,978,89,366,406,252,631,679,559,562,985,415,489,322,242,876,437,194,31,312,499,106,200,430,97,484,598,641,386,781,851,72,507,182,916,54,916,192,170,345,91,999,19,630,274,148,550,341,348,866,820,679,367,388,256,546,374,507,872,814,297,579,568,34,144,64,745,865,696,283,439,221,571,527,984,570,573,959,416,386,903,265,765,715,853,984,252,700,603,107,940,454,220,502,125,859,431,174,310,918,65,386,679,476,775,349,76,673,383,669,145,235,80,494,120,259,838,112,804,650,857,164,827,943,968,990,517,980,907,879,131,202,438,716,573,277,228,42,370,907,261,90,662,137,288,227,201,454,396,356,292,472,182,454,868,962,133,126,563,499,445,879,930,318,50,717,866,994,900,365,493,390,303,144,308,950,557,729,992,556,309,393,928,314,538,654,336,452,908,303,685,129,343,580,359,22,556,585,989,880,1,464,260,336,564,744,856,547,448,297,572", +"369,267,918,310,463,420,642,193,213,928,131,968,890,35,285,224,671,56,27,531,74,559,179,455,625,938,34,978,48,154,338,248,462,374,341,773,245,832,367,473,988,177,876,568,501,828,499,264,492,485,825,159,854,222,379,423,915,881,678,549,112,702,494,462,4,812,564,52,458,48,807,670,72,452,368,635,684,812,838,859,429,424,442,178,797,51,9,680,379,424,281,284,545,641,155,653,162,188,496,240,61,460,978,876,948,215,907,193,694,898,191,874,169,514,668,370,744,216,584,682,710,614,333,348,188,446,142,17,847,430,519,839,332,349,483,718,321,18,995,40,392,732,794,458,914,306,317,230,816,901,115,337,486,494,357,56,850,894,866,113,380,431,547,37,525,936,655,581,651,522,562,614,466,274,999,45,368,265,106,744,111,676,328,617,786,851,839,386,830,974,141,925,225,561,805,846,245,172,965,929,446,759,856,323,173,499,193,653,111,885,970,434,917,846,585,171,104,966,125,72,365,246,967,145,694,26,140,900,267,510,839,763,464,145,619,778,745,301,321,82,883,401,72,803,762,564,364,203,382,599,295,409,273,205,468,651,329,446,414,993,0,64,942,323,599,683,840,432,789,447,237,293,529,378,353,886,859,847,23,363,562,860,643,292,484,244,628,689,687,752,356,833,545,162,752,577,56,383,470,417,964,308,310,351,778,756,85,7,700,511,524,407,338,614,626,874,677,878,687,303,252,191,284,965,535,7,151,856,757,986,857,169,760,657,281,927,799,541,147,825,581,245,406,54,690,95,88,448,267,714,657,821,940,767,554,864,609,823,242,68,951,818,757,104,167,535,626,538,518,446,59,298,525,486,793,971,199,193,334,55,313,936,117,155,826,42,595,248,271,333,305,992,70,402,674,31,572,759,459,836,340,954,167,793,248,354,691,956,847,828,286,548,979,491,301,213,651,325,461,629,166,774,364,880,666,303,943,788,785,273,506,67,145,800,794,706,136,30,524,961,597,836,18,833,659,344,789,924,909,524,187,877,202,913,101,291,178,912,595,777,272,141,999,32,227,107,186,323,915,705,741,74,199,550,489,53,355,604,227,344,692,79,163,30,424,774,115,572,923,284,308,293,952,879,87,352,761,358,560,833,27,979,646,229,274,733,391,906,316,993,104,798,487,543,807,279,17,690,702,976,698,711,889,407,523,445,458,513,615,644,518,167,979,322,99,392,869,112,765,69,579,566,611,67,262,889,77,859,816,939,684,258,81,177,945,85,672,134,825,834,776,938,835,338,224,496,251,64,418,178,527,727,673,392,299,46,351,591,969,102,481,40,619,780,237,189,487,729,865,715,925,595,741,400,151,410,493,542,183,800,870,10,71,542,211,829,180,202,268,3,696,84,537,324,776,983,493,607,907,234,889,547,962,858,984,151,73,714,804,809,637,596,146,812,566,730,780,261,364,940,167,318,436,241,988,269,442,562,884,505,942,185,783,735,87,68,86,596,486,287,48,440,397,113,750,876,297,95,339,453,21,411,924,47,788,400,431,721,424,869,935,310,708,571,15,682,855,214,527,442,839,245,935,722,473,895,787,507,943,201,545,411,310,477,802,25,984,171,324,597,988,194,140,253,498,631,654,517,393,125,671,543,176,449,845,248,944,867,263,192,830,273,782,263,767,782,62,737,702,628,86,51,105,314,803,735,304,450,10,954,521,199,445,542,569,125,172,472,785,238,928,71,367,818,42,450,924,575,712,391,603,677,775,206,980,250,201,15,87,592,898,668,984,213,818,695,500,847,805,92,661,565,301,727,380,393,780,426,570,166,732,987,551,545,295,168,535,834,1,886,303,655,335,439,516,487,785,607,298,655,969,873,636,854,396,325,667,94,390,218,159,659,482,557,777,965,284,22,999,712,604,789,242,936,355,80,323,447,188,287,99,642,451,83,780,600,334,812,725,3,879,976,566,329,173,694,863,466,344,766,429,333,581,3,725,443,793,324,885,121,174,840,581,436,768,418,944,95,384,903,69,219,739,83,869,717,986,337,867,774,50,599,753,706,540,348,873,538,634,431,826,413,904,833,20,830,881,261,383,775,814,564,430,898,130,375,864,262,264,944,991,423,24,743,37,701,697,856,579,251,36,323,846,598,298,993,999,891,661,875,745,740,128,566,866,563,399,768,960,607,175,127,545,612,713,835,315,746,635,611,145,87,91,433,381,242,35,398,346,179,337,138,344,417,526,89,6,730,472,308,620,670,280,448,148,607,623,650,85,598", +"727,265,372,251,10,307,363,11,352,472,242,424,723,225,671,672,749,207,487,80,225,892,933,305,11,404,210,697,275,819,161,793,870,382,396,262,712,407,778,104,502,647,312,779,552,419,268,888,160,813,709,670,66,708,432,509,584,587,266,893,576,542,387,440,941,979,432,836,745,410,986,985,892,47,469,525,392,107,669,641,155,591,530,522,775,275,739,255,623,898,97,228,154,895,463,683,506,473,423,360,974,494,815,220,235,21,183,544,206,268,377,420,971,43,974,878,340,693,77,834,793,547,707,548,98,431,421,130,225,192,874,598,226,835,587,23,12,260,428,777,339,10,368,739,151,389,81,266,632,521,320,898,23,640,411,144,41,280,158,495,32,347,666,994,494,110,777,532,364,998,835,369,339,791,739,635,974,777,912,58,936,949,324,958,768,269,185,826,891,701,82,350,306,833,473,950,621,558,575,47,800,472,908,98,94,546,977,282,75,383,112,852,187,698,791,925,127,784,50,282,108,847,650,994,985,992,434,95,664,748,285,573,599,548,482,976,156,52,677,167,283,225,271,861,874,219,369,693,682,484,831,194,810,876,648,687,255,980,540,796,64,0,65,338,847,373,913,767,231,340,237,251,387,735,693,981,356,809,780,741,999,33,463,765,267,160,87,734,549,781,257,130,94,20,950,393,983,4,630,555,893,701,124,970,208,175,561,925,908,621,898,796,635,42,194,197,639,386,667,665,520,447,457,137,315,10,811,804,705,570,562,764,470,513,908,206,659,306,735,966,500,173,401,952,434,886,776,444,226,595,740,11,580,340,472,482,793,293,805,873,869,342,453,190,313,518,738,550,369,705,585,908,620,37,54,143,458,430,317,160,294,683,411,59,970,925,691,738,482,542,92,38,556,115,897,741,617,489,900,933,221,827,520,983,899,649,468,172,110,543,177,669,529,541,782,418,660,938,246,54,186,464,724,73,164,995,539,132,884,125,419,257,799,989,99,755,113,822,637,787,125,671,835,71,240,988,403,97,40,590,640,594,959,419,651,780,468,904,180,520,525,363,789,772,114,883,102,929,726,509,715,319,800,251,259,952,652,340,556,854,557,28,81,603,631,174,370,636,941,878,555,904,717,738,442,781,210,105,132,969,810,7,704,16,901,896,406,79,133,304,895,258,99,611,245,283,778,796,280,88,497,990,97,670,306,659,721,428,962,379,226,70,509,783,941,384,310,110,96,715,851,911,217,395,925,933,585,274,271,446,278,52,344,32,902,13,724,162,128,413,42,683,350,831,219,628,815,414,327,588,926,950,574,137,837,967,77,155,300,398,929,6,929,560,128,508,630,792,294,430,870,517,228,220,171,976,669,286,343,452,147,391,960,587,652,227,869,520,676,698,405,463,404,973,103,247,406,797,228,193,428,54,678,246,737,597,812,982,388,795,773,986,875,575,542,746,256,68,695,178,438,764,45,440,83,732,61,292,881,416,342,862,624,607,677,127,298,530,916,151,448,707,652,709,278,896,57,962,290,179,398,300,746,500,926,103,538,714,675,919,417,903,677,826,681,951,964,278,517,221,628,395,346,56,528,312,672,646,916,33,982,719,560,536,13,788,938,421,517,966,889,825,783,638,439,600,509,279,353,832,96,400,304,196,985,847,174,148,193,848,433,880,933,50,275,620,830,821,667,303,909,195,173,32,195,985,848,933,450,1,960,443,572,420,528,879,816,157,15,860,286,990,180,995,470,198,893,784,166,394,262,928,48,750,771,985,877,487,996,668,919,716,69,378,486,129,874,661,27,473,151,33,48,314,848,254,924,405,542,19,127,819,859,692,15,269,448,871,275,858,931,511,329,298,739,801,501,622,928,510,287,832,171,413,333,79,968,279,767,237,521,13,459,615,785,728,252,238,577,254,908,475,285,546,513,843,802,735,325,833,593,941,271,451,931,174,191,283,176,241,384,776,890,341,765,808,527,557,572,256,566,351,599,536,351,993,786,906,164,665,224,783,697,366,449,527,986,169,804,341,953,481,755,29,56,778,279,603,576,40,31,93,729,844,805,358,256,637,435,817,163,608,519,89,502,585,93,105,305,61,395,862,142,328,546,952,973,272,557,562,119,40,942,995,756,574,573,984,923,256,78,469,148,269,64,153,75,900,188,549,731,726,621,890,360,353,888,464,506,1000,974,454,901,927,891,518,877,786,10,333,680,237,382,700,713,144,920,989,96,22,917,566,395,690,365,917,338,699,787,202,558,96,860,13,902,649,140,136,549,807", +"258,554,353,484,235,834,387,664,213,832,656,60,30,932,95,408,109,950,75,420,832,880,804,935,229,47,776,958,357,718,809,91,910,15,189,683,221,533,432,920,509,121,481,188,977,384,457,304,396,513,706,752,762,650,170,133,136,141,987,216,988,694,977,569,625,976,437,432,910,896,989,680,553,853,743,148,460,325,760,780,929,616,665,41,439,324,880,34,86,894,47,619,192,193,48,973,637,152,978,841,565,973,41,820,151,795,21,396,127,11,460,444,393,413,145,278,442,56,523,273,38,660,64,478,924,723,904,467,812,224,116,144,29,84,950,845,283,256,265,414,153,413,425,807,791,496,315,411,763,719,95,301,93,240,3,473,494,296,886,968,898,450,641,314,214,522,453,93,121,65,158,200,602,750,747,631,545,250,645,37,869,578,294,127,292,802,857,907,47,346,601,532,872,51,338,169,157,601,588,153,874,470,706,36,736,666,902,298,523,944,516,650,6,611,265,92,128,664,870,75,656,369,862,598,424,538,990,875,513,352,615,639,289,588,10,973,605,12,335,621,549,606,996,293,775,622,725,462,675,667,210,289,660,263,45,503,239,911,762,945,942,65,0,641,92,113,625,707,625,702,632,490,65,167,472,293,825,550,45,59,339,238,456,874,722,115,922,372,414,898,374,374,76,797,787,841,80,182,687,908,138,334,127,361,592,859,721,267,21,185,557,823,969,669,97,556,418,553,29,160,351,883,564,760,22,609,817,813,593,135,425,485,859,624,789,670,652,484,514,236,187,208,959,447,220,435,467,783,202,747,992,449,583,773,760,64,571,606,657,955,202,224,869,103,187,939,371,634,640,935,79,389,986,642,550,42,635,931,463,675,433,129,194,566,262,643,860,346,595,181,633,951,77,756,601,750,813,797,307,629,568,844,665,198,748,15,164,984,777,631,809,248,903,158,671,619,614,65,719,971,221,385,320,412,774,808,374,529,236,303,127,515,926,76,887,675,453,293,162,959,563,852,20,303,299,495,933,647,168,752,346,243,893,985,692,660,464,140,859,69,194,613,409,62,577,796,360,823,737,77,729,448,407,152,662,448,198,861,389,702,849,487,79,943,166,837,678,896,558,117,906,666,273,524,925,924,890,550,333,457,11,541,909,972,957,926,183,251,285,945,84,701,113,141,887,375,855,715,744,453,338,680,171,102,600,837,91,839,883,626,100,668,503,424,453,756,796,882,238,939,333,830,795,919,468,795,203,722,43,652,72,816,29,685,718,50,880,394,140,536,668,111,271,93,845,53,158,10,308,687,345,859,468,314,920,749,522,751,393,723,38,167,472,248,309,674,284,904,344,176,38,654,435,782,40,597,647,800,422,873,172,420,65,143,766,31,197,33,495,125,169,823,75,639,840,387,864,19,495,343,654,745,763,384,262,644,494,129,322,880,816,664,308,71,432,829,772,934,133,648,995,228,992,603,485,130,230,335,184,233,647,110,736,849,128,413,621,494,919,349,320,237,661,697,763,557,438,301,301,947,932,861,772,291,25,860,613,118,969,120,95,91,390,495,382,914,81,360,872,689,61,765,199,683,309,354,698,410,77,936,344,361,22,645,623,413,217,646,786,165,272,210,404,532,56,953,77,547,576,757,947,204,307,13,874,364,189,701,185,495,680,212,983,47,723,33,171,38,307,658,235,684,411,202,221,622,410,465,135,672,233,458,344,340,195,242,376,199,613,645,924,958,249,724,222,401,710,847,207,878,331,366,84,232,560,187,738,661,1,654,151,244,319,498,165,811,446,736,271,629,429,181,504,663,569,369,212,957,380,146,10,64,28,656,697,592,606,630,566,135,835,393,795,44,640,949,837,58,879,186,933,608,460,656,92,582,40,414,520,235,134,396,215,865,12,275,132,24,328,178,932,348,11,232,408,773,656,770,100,145,381,9,876,52,991,508,190,397,404,432,645,215,700,669,997,305,401,867,992,213,949,827,784,970,417,126,171,510,971,91,672,784,439,223,547,407,819,847,934,270,54,749,533,154,740,420,403,588,758,672,663,99,497,64,91,193,711,611,485,534,920,697,441,740,189,295,601,335,236,985,810,771,75,345,144,390,970,138,450,950,358,306,967,527,7,172,232,107,644,158,895,216,217,183,780,530,795,427,505,401,897,86,422,612,395,800,894,171,912,164,555,528,756,887,705,421,54,42,115,84,819,601,928,685,979,696,399,674,766,751,91,169,834,422,121,949,526,356,316,985,932,42,494,67,783,397,493,492,951,415", +"307,862,586,862,374,229,228,49,784,69,763,541,404,474,87,665,205,623,635,642,337,425,389,766,740,952,431,102,831,366,153,559,491,29,146,873,51,549,880,30,703,611,565,502,34,92,551,608,227,120,848,2,734,29,444,251,720,262,139,675,924,997,513,742,204,12,624,857,171,401,67,582,819,138,326,913,16,960,900,419,213,984,953,860,965,324,338,562,179,606,611,313,799,917,573,182,775,832,608,914,579,982,268,796,455,533,225,135,307,851,1000,199,616,907,231,721,900,346,612,233,533,225,175,447,923,812,865,797,896,182,947,981,872,745,614,243,36,976,770,561,939,101,888,363,709,619,914,288,767,153,951,76,687,513,226,171,572,500,759,313,905,958,650,950,297,107,944,674,624,2,660,186,946,710,907,422,769,690,42,954,403,129,753,228,639,358,892,734,632,995,588,984,343,498,401,145,316,872,644,226,140,53,711,875,959,57,172,110,305,214,208,792,839,725,765,802,167,782,131,823,596,966,332,599,516,120,152,847,406,691,142,874,178,33,473,674,444,318,687,760,314,360,876,169,900,604,214,858,348,316,821,200,773,162,181,737,178,143,48,995,323,338,641,0,301,240,369,681,332,486,608,817,744,871,759,721,45,234,579,975,118,284,70,856,143,323,525,367,647,136,789,999,267,893,782,217,628,512,663,85,485,289,74,987,393,307,540,171,105,967,601,579,28,22,999,675,389,822,556,650,392,280,967,236,915,792,289,458,542,116,177,840,693,30,967,31,308,211,501,270,182,329,491,149,101,669,314,521,832,765,916,526,566,934,858,147,991,595,655,149,604,712,764,991,292,194,847,979,276,237,506,495,718,267,198,693,83,892,570,662,303,304,815,374,325,575,278,29,319,692,282,656,626,64,33,243,697,133,349,175,7,451,778,595,954,454,997,280,938,198,477,436,186,250,73,872,77,852,968,586,964,765,46,15,975,214,553,903,225,243,726,242,458,212,192,465,706,672,592,31,877,457,413,554,268,811,439,472,436,467,686,248,627,875,259,918,168,835,188,140,510,146,746,1,689,487,687,254,868,801,126,726,525,494,53,114,919,101,42,710,744,164,525,871,359,544,873,824,880,341,662,640,97,535,801,818,833,325,377,656,287,943,658,96,471,343,581,104,395,236,30,689,261,67,469,694,529,627,680,34,15,745,601,901,826,224,1000,149,218,386,213,968,620,4,766,687,578,668,336,528,240,905,53,326,981,423,379,893,791,921,999,258,928,92,11,926,272,524,610,355,934,943,335,968,461,364,538,686,196,321,936,304,100,558,682,571,363,585,463,572,67,236,637,34,901,731,495,267,402,806,653,367,615,922,882,693,416,484,572,175,971,894,506,76,733,151,936,890,58,234,536,111,271,2,908,12,443,315,683,405,294,894,117,987,202,573,967,165,291,388,543,117,425,120,461,166,600,230,266,669,874,704,188,751,834,885,645,617,93,383,782,820,404,202,96,350,514,591,301,419,359,301,718,875,980,926,760,610,915,880,331,814,412,945,709,560,332,383,84,888,696,812,94,605,445,959,220,216,493,112,794,604,136,488,91,157,412,410,157,182,567,428,867,650,208,874,672,860,543,932,12,219,284,337,317,265,883,611,397,500,314,59,896,66,276,288,84,447,801,160,899,925,838,329,266,676,885,306,31,577,710,495,351,606,838,871,253,115,56,860,297,697,31,219,53,468,446,245,146,558,348,469,215,700,828,871,618,288,535,102,157,30,879,779,148,68,911,584,175,711,969,263,878,59,963,226,629,117,779,655,231,466,667,790,722,158,877,483,621,258,430,112,195,374,592,603,488,811,314,398,61,657,189,919,481,907,450,71,90,541,930,421,299,472,274,427,576,964,301,914,384,710,202,95,978,250,601,525,278,394,238,812,572,730,620,737,302,691,69,904,141,102,193,298,267,36,11,445,518,982,217,877,895,237,782,947,541,607,974,75,225,33,503,677,2,437,777,76,358,397,250,580,33,945,856,746,643,394,457,907,928,89,517,807,225,156,629,670,633,259,547,595,940,743,575,561,791,916,645,992,67,369,497,570,928,898,979,948,974,54,156,867,568,738,115,847,87,168,569,500,864,120,503,386,973,32,52,415,661,189,693,737,402,505,104,459,151,106,134,620,640,631,83,477,256,305,800,413,280,914,664,313,3,132,511,401,390,463,779,148,9,411,849,739,56,75,212,642,627,295,185,382,317,744,168,271,979,592,751,38,821,883,437,298,452,474,535,868,137,777", +"794,609,487,94,696,508,385,972,397,551,26,306,154,511,420,343,93,31,335,507,542,374,484,596,251,460,121,875,135,604,940,294,994,615,460,162,907,560,468,265,586,326,270,920,551,976,482,895,996,622,361,245,317,867,161,86,978,258,953,498,597,11,122,825,884,574,589,960,258,590,537,210,323,438,429,153,233,413,862,489,232,902,366,650,715,666,754,148,356,767,407,713,258,825,201,418,959,896,939,513,551,79,966,70,607,814,163,774,206,719,703,373,889,197,994,127,857,853,844,493,959,577,234,813,981,150,54,497,353,617,78,425,334,379,173,598,711,399,23,352,342,224,842,827,271,787,757,607,381,114,56,695,183,417,355,114,556,247,489,720,158,438,51,487,497,85,661,722,480,399,688,255,126,431,610,188,547,740,714,604,402,628,679,96,27,192,809,274,108,34,50,451,67,958,585,517,296,794,441,642,297,643,124,89,986,201,428,445,778,861,476,764,448,848,985,43,848,129,435,887,897,924,138,4,952,710,167,174,825,689,210,975,93,854,594,11,878,850,542,890,30,289,157,68,484,906,180,82,434,331,27,223,242,342,702,156,241,822,408,728,599,847,92,301,0,611,458,503,343,972,201,118,964,194,339,48,403,775,739,717,499,899,455,950,584,868,835,883,194,889,271,27,71,586,853,586,366,666,964,49,394,950,105,29,139,259,156,691,300,266,352,959,507,132,815,784,853,42,981,822,639,854,205,465,399,157,682,141,16,33,819,901,205,754,920,626,844,756,795,331,513,36,670,811,752,121,497,631,734,988,152,380,138,796,979,796,681,702,988,598,1000,262,164,304,185,294,50,371,675,243,960,92,561,468,832,680,868,906,486,688,632,428,375,50,906,963,191,311,124,190,520,897,88,400,975,470,330,551,30,284,59,346,682,540,618,288,151,840,745,519,964,8,281,86,617,757,808,894,629,597,243,105,712,536,740,589,417,995,250,97,398,42,503,146,693,126,558,503,142,4,44,246,90,704,667,656,209,60,916,450,793,205,396,723,787,525,123,815,711,662,147,407,506,619,469,65,948,770,708,225,388,480,363,77,312,766,148,137,170,127,340,708,274,981,360,833,467,661,948,800,135,35,787,275,604,575,640,852,839,719,488,585,10,680,436,112,364,220,834,2,112,342,935,670,23,223,975,93,704,476,342,928,878,393,450,15,576,989,96,327,333,100,977,340,916,212,825,339,703,672,109,100,7,917,183,818,620,137,247,960,209,22,116,483,351,422,937,965,263,355,137,874,300,778,244,60,319,518,811,643,526,634,20,916,908,907,208,507,742,588,977,710,953,959,434,976,505,980,558,670,47,636,98,204,207,745,985,488,835,656,187,595,899,848,712,547,277,587,5,22,180,171,183,108,397,323,228,305,477,425,545,78,814,652,932,908,963,811,243,972,491,766,461,830,732,706,453,612,486,591,247,426,313,908,108,609,787,654,575,277,829,444,715,88,322,974,121,432,342,365,86,156,38,907,93,466,503,419,224,816,617,298,191,912,264,850,305,266,229,698,384,955,556,155,657,581,128,317,633,377,486,2,357,74,485,734,149,284,933,13,163,509,469,238,196,753,450,104,504,345,28,83,194,541,21,684,693,667,622,531,634,437,830,952,701,470,967,285,25,995,342,387,793,535,455,588,283,632,254,959,649,137,44,878,999,909,584,554,466,682,262,928,838,922,376,538,694,10,433,341,531,528,801,596,946,488,855,13,326,129,339,506,845,808,668,69,331,334,124,808,347,201,93,681,706,999,807,484,702,191,380,898,587,534,910,140,167,536,393,279,162,381,117,256,963,541,599,109,456,164,119,202,560,47,289,967,203,368,371,179,564,92,616,602,359,216,660,429,719,529,357,174,66,626,808,103,9,24,5,276,747,578,734,884,840,458,628,668,790,669,900,308,268,693,956,236,419,83,651,409,446,391,489,568,990,85,214,512,783,245,39,857,972,320,239,359,447,420,950,317,388,586,165,685,260,30,245,839,935,389,260,129,766,636,158,235,210,144,645,370,595,468,990,334,606,500,62,190,161,73,776,552,932,603,362,598,607,190,282,768,511,706,189,467,725,253,362,794,968,361,357,698,391,886,243,536,490,482,721,292,819,848,899,99,729,330,807,212,408,54,230,758,568,847,816,52,32,846,675,231,850,566,84,290,657,434,365,682,115,108,377,270,416,248,292,336,674,134,781,498,14,719,292,819,295,239,704,935,256,107,597,709,730,351,690,557,978,493,614,188", +"669,244,698,179,742,748,632,444,824,786,494,792,321,864,807,858,232,584,198,711,304,49,126,417,439,338,598,71,797,189,125,126,372,839,324,14,687,418,561,624,23,743,28,786,304,986,113,950,350,994,355,553,393,90,463,177,309,336,255,452,684,575,78,170,372,887,181,793,640,723,519,59,641,313,503,744,698,568,141,964,856,291,236,839,534,414,928,147,783,823,634,741,532,824,981,178,226,531,409,910,166,332,660,960,509,260,817,35,26,677,483,414,676,671,587,345,334,113,256,143,716,487,325,631,187,646,772,909,881,204,999,815,118,336,297,332,399,29,937,898,695,433,567,810,442,254,251,17,331,404,849,626,673,856,424,341,471,757,105,284,673,349,755,498,682,276,997,872,607,348,73,549,279,721,350,544,600,855,193,645,771,131,490,732,42,8,9,723,968,764,860,335,61,378,600,671,900,240,993,483,287,454,787,108,645,915,536,12,468,99,817,648,770,554,683,384,460,269,887,412,348,137,121,107,991,319,593,983,202,90,504,16,502,858,531,755,246,21,491,486,238,472,760,407,530,34,115,509,807,246,398,259,72,258,24,442,427,336,602,747,683,373,113,240,611,0,755,265,373,309,695,268,625,348,496,787,882,105,362,904,996,457,279,811,651,809,913,221,904,158,125,921,341,230,866,47,651,86,937,513,244,341,498,277,417,967,489,860,379,867,169,778,116,894,114,772,796,299,6,197,873,730,149,466,541,850,227,408,94,298,333,376,133,186,481,693,913,216,888,340,143,561,687,86,938,722,764,871,266,55,192,785,866,344,102,856,506,427,878,32,706,406,244,286,382,438,974,494,551,545,530,923,192,936,549,840,954,188,587,567,305,979,87,324,186,554,194,13,492,436,90,965,523,312,994,914,361,87,674,789,673,189,877,553,943,421,522,80,335,592,435,227,259,256,599,45,829,61,649,224,72,661,705,250,685,116,550,986,294,184,365,791,66,262,496,490,42,878,346,630,593,164,275,836,624,169,337,464,186,535,612,969,323,119,598,829,694,323,45,990,154,207,153,607,75,557,623,170,715,771,930,265,585,722,936,995,9,752,83,687,579,565,428,935,370,738,761,979,103,622,365,516,683,796,475,306,238,485,950,14,137,815,135,368,528,862,247,598,249,923,94,239,667,848,826,223,407,381,531,188,504,348,119,394,998,198,315,596,694,872,64,768,471,427,564,936,705,570,29,307,99,314,955,718,149,195,736,304,857,544,25,559,936,329,769,427,375,928,377,985,491,580,770,605,844,617,310,275,334,781,5,566,870,213,744,57,294,588,241,601,89,928,987,781,203,523,864,480,365,760,266,207,642,901,232,835,636,236,840,814,234,915,702,599,642,113,30,490,823,326,417,830,818,635,152,143,400,169,798,938,863,403,17,654,875,569,323,788,564,958,75,809,680,697,305,608,98,467,74,832,187,100,883,175,751,728,899,450,439,272,641,771,866,825,840,813,516,197,411,532,332,463,858,675,875,496,117,335,568,852,694,588,113,360,198,53,730,636,138,613,292,411,299,467,822,403,569,526,837,836,689,397,810,294,912,451,736,540,29,406,167,331,296,253,942,9,773,529,135,587,117,585,719,796,796,188,165,966,684,63,656,292,840,375,72,970,181,994,969,551,344,200,492,462,224,364,876,444,19,855,636,609,503,352,431,874,333,482,180,809,22,977,120,943,669,228,63,405,507,867,404,23,925,153,381,385,445,278,847,607,849,218,358,266,799,855,762,25,752,673,799,802,547,943,428,426,263,161,474,940,453,15,740,985,859,762,464,841,848,129,916,675,479,318,244,475,653,930,136,175,225,282,813,933,966,155,190,519,7,905,683,755,386,951,337,775,320,352,705,706,752,188,868,968,25,348,801,454,565,2,787,435,455,752,493,881,855,603,986,341,310,227,632,707,603,682,798,364,376,314,970,102,543,118,179,206,344,506,105,248,889,744,263,230,843,304,305,79,163,122,639,493,966,32,148,364,751,716,730,469,433,163,983,196,332,514,806,473,475,153,431,716,328,979,754,686,439,408,959,531,912,129,563,761,148,132,650,137,444,88,412,995,78,574,378,733,531,707,89,662,409,673,157,452,719,95,88,771,734,192,654,710,407,716,640,345,629,549,912,871,261,786,47,460,717,74,598,593,181,343,711,314,948,83,879,547,841,373,854,711,611,517,36,733,81,470,465,956,794,424,452,820,402,696,991,680,700,219,151,794,943,446,98,340,531,470,619,351,769,358", +"438,662,386,486,176,502,2,933,381,359,927,486,978,284,702,85,159,751,317,837,829,602,726,48,745,771,541,377,827,44,290,893,999,873,176,29,40,525,626,864,333,94,863,224,222,914,23,443,984,11,506,371,90,203,525,295,775,788,564,438,681,896,725,860,985,934,916,362,854,14,840,391,564,341,326,20,124,335,209,27,723,511,899,687,748,743,204,521,284,804,340,334,675,264,416,249,415,254,487,535,550,612,821,204,693,776,476,707,839,560,757,654,502,283,163,4,110,275,892,834,483,247,20,629,247,673,767,70,755,10,367,93,451,933,866,223,679,398,544,401,684,940,868,917,877,46,618,230,152,59,589,70,208,597,233,743,392,953,460,704,275,378,874,885,908,779,493,476,972,437,187,186,146,572,317,597,814,399,671,32,431,726,366,881,261,528,465,951,297,671,757,551,50,61,629,464,915,594,593,245,59,166,163,365,937,401,55,244,334,555,793,31,340,935,808,577,9,264,224,858,419,320,234,413,571,585,990,833,151,70,963,753,300,42,895,927,543,302,292,508,357,365,833,132,690,871,548,287,1000,933,215,937,2,47,274,799,567,526,628,543,840,913,625,369,458,755,0,142,430,734,631,731,373,180,766,211,597,62,996,142,766,633,242,251,218,29,648,626,12,59,338,70,674,141,742,393,733,144,262,632,199,583,155,806,927,466,175,877,953,450,589,853,508,111,901,37,253,727,934,203,178,974,77,112,390,632,617,655,72,911,932,134,501,438,253,8,784,996,204,137,846,304,988,682,211,840,348,36,823,952,990,466,206,830,663,410,871,173,774,40,974,803,933,292,940,462,871,70,155,34,723,100,582,102,740,252,712,471,622,519,607,198,25,961,460,771,418,782,876,340,842,879,12,822,81,575,485,65,334,922,66,954,20,768,957,609,26,240,607,326,941,553,563,573,188,748,918,742,208,731,732,633,542,992,851,118,438,796,369,665,989,982,864,217,490,267,549,953,655,227,471,937,152,359,226,324,767,556,878,106,365,652,717,205,550,336,311,46,823,460,398,124,497,577,410,937,791,60,981,100,815,332,409,63,843,123,442,710,907,89,30,377,507,127,905,789,836,10,881,929,354,63,571,11,236,511,763,869,906,206,470,687,497,447,303,613,713,990,519,127,211,120,864,856,775,642,758,982,272,134,602,742,367,545,306,94,244,384,750,769,687,372,333,686,474,439,395,532,704,102,572,841,30,458,935,182,896,588,153,965,124,254,781,754,545,356,84,810,288,676,380,526,897,574,532,828,893,308,394,787,985,43,176,540,273,108,55,836,407,21,302,666,65,513,90,542,549,42,972,592,517,754,641,169,418,284,428,621,84,481,570,335,751,768,902,712,36,496,611,677,420,371,976,48,681,940,227,602,667,284,368,819,311,965,581,168,205,26,607,251,917,426,239,204,783,354,125,66,574,9,198,693,951,259,194,579,676,734,743,469,790,639,217,761,96,415,301,744,684,675,812,998,945,475,22,877,281,28,63,411,649,379,723,788,82,99,61,674,685,530,684,443,560,643,864,850,804,763,902,751,66,735,261,224,112,982,199,83,952,910,730,646,266,666,83,566,979,708,781,665,879,635,893,306,152,719,787,25,21,708,977,735,885,354,890,285,396,533,127,151,556,563,185,935,343,192,209,885,920,665,742,989,436,814,895,601,399,933,615,358,507,811,475,941,726,40,501,189,866,736,22,171,467,418,260,551,245,10,829,493,432,746,602,991,602,528,533,886,46,299,877,906,964,220,851,460,18,63,884,421,678,425,30,59,381,884,524,949,531,692,79,246,536,662,293,792,836,974,892,531,484,586,204,546,523,716,955,831,582,208,451,345,270,98,265,880,632,259,580,313,679,393,236,710,837,89,425,518,51,121,779,176,145,512,377,39,954,586,441,450,599,488,638,645,134,149,612,413,537,296,524,829,980,216,54,326,106,942,126,309,696,37,518,186,281,930,83,938,63,264,521,705,344,422,35,552,980,294,517,305,286,468,21,69,635,553,939,154,464,821,218,494,614,747,822,407,69,86,866,825,363,852,426,766,664,135,293,424,405,820,571,485,655,492,154,644,372,118,604,818,540,611,443,173,862,899,773,99,534,765,214,21,261,978,256,949,865,530,992,320,978,70,562,579,68,587,377,406,414,381,941,157,927,471,87,155,274,100,323,414,992,909,189,295,733,437,394,661,151,19,903,21,984,232,974,323,487,912,874,406,289,25,543,375,267,925,966,477,888,587", +"604,714,823,991,98,745,815,753,38,763,990,824,583,321,590,890,598,272,426,52,832,24,619,97,200,787,364,344,426,912,841,791,286,873,707,340,541,393,309,135,889,933,710,370,84,793,556,431,165,538,875,238,213,767,623,551,87,378,850,919,146,230,800,593,696,135,11,881,424,829,730,773,258,16,171,876,451,185,940,830,377,979,211,819,390,376,724,435,123,980,63,586,604,902,322,265,316,306,23,790,957,523,362,720,532,483,125,611,912,217,605,471,364,997,234,815,378,863,58,293,478,820,927,412,403,589,38,262,482,560,985,740,5,541,816,473,330,843,208,282,358,425,662,468,4,213,849,613,246,690,690,162,328,423,61,135,362,600,757,490,912,971,259,990,894,968,618,368,199,969,489,481,228,791,50,189,455,349,765,919,7,950,874,48,295,270,745,584,163,197,532,341,569,549,227,118,241,160,647,813,969,833,790,502,73,212,961,521,437,466,991,443,954,550,472,738,430,262,814,479,402,121,160,887,241,108,351,485,881,240,140,971,956,893,450,328,117,387,589,139,123,575,472,958,780,935,846,765,257,590,782,496,438,748,539,55,944,99,891,417,432,767,707,681,503,265,142,0,617,259,123,138,137,853,470,909,242,50,733,591,724,472,895,843,727,51,585,552,124,239,482,127,593,778,15,148,49,119,650,458,423,230,367,62,38,151,797,903,24,342,368,669,318,933,897,101,918,880,528,757,221,4,867,95,919,709,809,347,673,119,753,100,735,248,542,749,915,411,55,203,546,916,253,379,580,206,915,242,538,654,952,708,685,893,689,678,597,803,883,785,418,773,341,452,339,616,504,239,363,826,410,435,924,849,996,646,245,268,142,952,713,401,940,183,962,417,319,420,58,584,214,922,970,936,912,287,61,56,581,821,282,525,433,642,681,74,785,924,184,968,328,934,434,242,177,201,736,262,232,31,592,308,66,44,584,358,410,111,414,458,283,904,196,300,497,60,723,922,720,334,973,662,713,253,669,141,420,661,27,520,435,443,64,759,967,705,833,504,890,875,997,614,638,560,940,597,677,332,43,664,626,645,595,999,104,976,716,355,404,837,354,799,962,733,303,351,17,490,140,849,841,631,233,553,920,529,923,756,755,309,359,764,850,619,949,416,771,951,535,496,946,518,967,817,452,767,745,482,762,656,93,297,959,658,829,915,525,206,558,733,203,511,716,838,653,418,315,51,172,628,158,304,158,903,334,800,880,640,460,815,13,829,892,823,767,961,967,743,448,885,907,353,449,155,650,980,654,676,608,634,433,181,878,512,542,867,849,763,611,936,888,723,917,379,799,722,340,598,877,51,960,171,175,869,621,669,351,114,465,911,302,32,800,801,690,993,293,549,751,451,407,146,540,105,94,595,694,576,36,909,645,843,398,221,743,965,609,283,969,677,353,449,100,647,117,680,906,156,544,667,582,234,308,796,299,957,380,863,492,246,497,923,994,175,938,922,789,269,378,85,177,340,806,990,743,662,475,876,612,434,719,795,98,974,503,648,868,754,762,154,715,68,713,478,606,173,35,325,506,952,157,160,836,991,639,510,894,664,974,897,390,796,964,900,852,945,141,499,289,180,723,104,41,729,550,509,65,548,931,220,392,419,380,465,809,725,636,291,597,761,54,617,181,389,315,820,738,980,155,279,103,978,581,367,70,734,551,347,530,537,170,823,538,964,797,402,573,415,610,49,412,975,827,876,83,752,392,285,842,95,183,629,770,280,341,182,515,912,634,154,423,94,285,227,228,920,55,594,564,147,818,107,773,287,649,308,338,422,806,391,509,314,742,974,329,333,821,233,584,862,37,299,389,968,766,670,533,515,363,181,811,452,309,710,456,112,211,236,926,452,783,886,200,67,949,702,697,95,788,290,108,231,528,759,256,988,965,22,703,586,264,487,933,327,350,741,41,785,776,992,88,380,877,354,92,71,153,832,586,360,60,825,974,538,185,607,982,284,571,628,619,618,532,459,697,484,980,515,373,277,298,403,248,821,101,494,197,921,3,87,852,472,654,254,556,44,501,432,714,973,939,989,798,492,364,816,17,917,492,255,280,364,935,449,925,847,729,666,928,518,738,82,277,984,540,578,335,527,496,153,599,693,93,506,93,379,358,176,129,435,502,70,359,362,137,224,644,528,762,600,59,682,452,232,630,813,452,96,777,281,320,302,638,170,744,736,124,799,57,941,5,277,448,431,119,903,134,106,242,58,29,305,802,91,265,2,269,11,350,921", +"549,194,849,626,799,643,899,543,642,50,85,923,520,385,591,339,110,818,692,15,357,923,789,336,514,815,928,237,334,956,505,74,529,451,985,835,679,280,423,181,666,207,861,469,561,277,759,381,560,477,787,718,735,243,4,644,347,975,29,594,778,345,52,318,4,526,601,975,170,358,511,912,248,849,752,504,37,68,413,646,221,483,514,754,801,518,572,611,177,551,29,654,174,292,343,81,441,397,795,484,904,812,305,394,263,395,891,596,426,266,565,205,12,859,275,483,394,7,837,169,235,372,82,887,408,760,838,139,483,885,733,297,265,799,880,980,801,632,728,867,115,536,250,516,683,621,425,350,74,509,557,635,224,408,980,774,594,796,640,560,914,136,206,197,289,773,793,913,282,461,114,93,455,865,930,250,552,593,34,96,481,309,742,63,772,401,58,359,792,773,206,683,219,389,169,755,46,179,534,928,988,701,166,490,32,164,597,59,392,604,166,242,26,170,980,297,762,634,301,253,593,35,758,127,349,919,790,308,593,817,191,141,8,47,457,967,860,929,336,165,9,366,23,979,26,366,860,322,85,590,96,353,264,279,578,513,233,129,110,41,789,231,625,332,343,373,430,617,0,671,286,997,861,816,600,15,782,339,135,134,838,518,307,624,971,311,749,993,743,108,982,270,924,929,73,73,175,167,149,833,474,591,291,174,40,850,402,11,727,452,694,555,232,875,649,727,924,724,637,736,872,15,826,928,801,232,318,725,587,662,275,471,473,125,866,335,339,150,727,369,622,129,749,871,162,420,194,674,910,758,765,428,188,824,133,992,483,626,503,199,351,162,218,809,300,237,759,798,613,647,799,353,110,279,107,873,594,198,520,458,210,983,980,696,447,882,204,344,314,68,495,509,582,925,353,473,65,409,734,813,878,663,349,352,500,736,892,220,991,69,232,499,762,739,251,785,968,939,601,840,153,550,985,995,39,880,657,81,826,888,271,634,840,448,634,610,106,546,955,857,370,704,323,434,882,652,525,765,188,380,326,496,579,656,917,51,688,85,336,123,255,658,803,420,981,506,284,118,721,540,970,602,941,944,80,321,962,866,792,941,774,14,112,943,214,880,859,201,344,309,315,26,310,573,316,876,156,481,900,3,66,453,396,428,944,152,801,284,906,413,224,433,845,784,937,332,551,451,319,420,874,236,99,412,124,922,624,288,224,40,300,681,580,184,768,744,950,970,142,280,453,678,258,610,354,224,469,231,834,70,551,771,456,461,582,739,315,10,224,599,339,753,188,722,724,26,893,568,775,804,43,184,150,522,811,174,979,652,905,284,177,960,956,185,592,309,585,549,678,770,180,621,534,546,154,249,859,313,920,863,383,577,730,139,224,651,377,420,260,452,125,963,296,92,756,926,47,549,88,392,996,196,336,632,511,613,632,92,879,136,264,635,685,671,84,304,807,787,564,158,323,956,150,653,897,839,881,152,433,880,584,430,635,334,526,9,171,502,784,210,349,254,495,292,928,891,379,748,303,763,206,27,338,43,287,354,632,366,70,692,56,479,374,810,870,766,247,397,638,359,670,551,749,123,953,467,180,837,272,830,983,481,3,254,322,742,600,688,442,438,968,349,423,391,441,925,822,186,919,275,414,530,754,632,626,558,471,409,604,678,900,341,151,796,183,671,707,292,540,640,927,314,800,143,365,462,844,811,356,205,979,356,900,353,930,640,370,174,286,150,248,35,489,192,832,582,409,918,527,145,60,953,747,580,475,27,176,754,747,605,579,848,657,510,965,13,324,907,109,151,977,755,226,835,95,519,706,417,288,442,192,154,102,479,142,957,669,329,577,618,274,788,359,838,194,114,125,730,616,831,203,602,685,928,521,933,358,415,581,382,158,866,606,166,555,5,307,26,204,413,825,397,118,671,367,716,168,11,286,348,610,308,514,964,179,199,235,602,812,221,508,450,632,915,507,470,341,142,531,717,957,154,393,479,827,15,512,787,678,312,356,623,734,671,767,59,149,810,223,413,379,795,62,549,747,38,332,762,571,255,656,214,555,955,66,878,728,39,681,519,837,559,982,525,45,162,680,613,27,962,770,636,290,381,57,656,712,892,623,59,523,332,463,403,119,21,259,896,18,814,892,157,494,849,406,717,385,789,486,542,390,359,397,994,830,939,654,989,974,272,681,350,455,685,482,722,525,34,247,428,148,155,481,387,725,430,907,960,726,350,686,924,712,499,602,788,715,590,445,472,833,716,60,844,474,309,831,704,938,402", +"921,853,784,301,394,656,790,631,764,85,958,926,677,469,36,371,594,480,305,664,568,444,565,381,197,733,668,672,291,30,220,972,234,515,410,709,464,101,12,248,321,216,779,619,586,790,87,144,329,303,604,896,305,434,4,24,169,375,103,886,612,76,266,784,15,349,415,144,739,656,603,238,28,365,298,684,490,684,269,606,360,767,276,213,540,347,440,355,829,936,349,886,293,839,252,236,318,16,355,322,3,215,659,904,348,16,280,27,174,297,9,462,593,945,123,167,850,494,970,133,123,682,164,494,933,248,977,976,278,758,432,876,19,272,210,746,36,442,952,960,592,967,234,756,982,380,497,357,111,855,696,300,63,955,671,460,902,965,948,53,3,909,718,518,376,128,341,265,955,839,216,83,374,14,241,615,848,170,467,367,76,693,977,975,195,791,942,722,717,801,680,577,438,226,321,350,520,782,247,506,506,318,806,98,274,732,102,153,214,677,71,796,483,624,521,197,21,99,395,203,864,390,851,711,520,539,956,947,530,442,432,149,153,256,122,97,654,798,208,601,842,376,905,819,411,831,614,390,313,610,499,153,31,620,589,401,108,885,82,802,447,340,702,486,972,309,734,259,671,0,143,352,503,466,926,447,609,281,10,104,693,605,450,177,184,914,260,787,440,926,608,250,985,683,978,731,850,363,767,873,180,401,456,32,529,237,817,331,426,814,161,795,293,631,702,576,968,360,87,366,164,882,441,949,375,8,240,441,932,31,882,791,127,961,494,453,269,382,626,959,463,986,450,608,156,616,979,495,712,184,111,56,769,88,378,775,10,89,274,874,902,20,651,108,263,773,731,470,3,150,33,114,220,511,386,488,72,646,594,496,778,181,987,227,857,743,884,719,724,557,88,941,494,708,779,155,885,134,162,256,743,90,6,118,57,124,727,909,404,825,103,746,450,896,863,257,795,80,651,723,484,407,591,923,668,584,587,502,691,370,310,78,530,774,140,174,749,861,829,905,625,738,421,413,972,2,386,895,997,786,433,937,72,535,777,573,689,887,860,370,941,606,831,444,193,400,275,103,4,370,815,475,572,615,286,827,819,950,605,74,790,204,837,653,200,565,18,980,236,895,516,337,121,760,421,675,575,910,195,808,828,666,558,286,821,875,54,757,471,738,458,709,616,816,818,966,490,355,450,238,337,891,236,309,573,275,515,983,691,429,91,230,505,921,6,213,161,375,922,942,566,340,822,166,7,128,904,123,404,704,965,355,64,494,400,795,924,709,899,289,870,50,850,645,287,398,470,641,240,202,430,904,607,673,796,645,610,776,949,685,782,136,971,639,333,575,397,592,827,520,623,40,729,48,627,585,581,976,64,601,848,280,653,267,339,952,242,881,692,881,31,535,17,234,130,591,844,96,523,858,885,719,933,747,398,469,820,134,102,13,781,714,420,754,549,748,310,242,903,779,777,630,764,360,877,532,420,596,944,744,92,595,368,328,519,629,250,315,776,241,514,492,465,274,148,551,896,137,89,173,626,771,297,721,187,468,386,187,299,799,249,974,638,723,101,69,585,576,803,165,250,939,144,271,864,846,46,27,710,170,78,483,487,472,209,847,795,63,867,440,793,219,720,231,437,62,49,959,42,421,664,195,905,669,558,835,287,301,951,636,898,112,477,902,930,585,542,809,729,271,884,343,80,462,115,687,800,729,47,194,573,832,565,728,85,196,499,831,182,88,779,626,43,377,58,250,780,670,159,363,726,840,332,956,458,101,872,685,209,77,861,91,735,517,671,972,282,752,638,275,724,127,886,349,941,109,553,923,121,832,959,448,656,92,774,447,395,389,979,330,19,709,947,487,404,117,913,666,471,751,214,64,167,260,271,897,380,723,274,645,479,339,99,323,635,137,273,328,535,373,158,797,296,783,920,480,644,295,892,977,196,328,835,968,666,869,251,48,532,828,257,326,999,988,64,252,933,979,660,775,215,743,987,174,436,407,105,960,883,968,285,715,583,316,49,463,427,658,478,585,118,606,247,641,894,576,399,347,530,730,550,98,743,852,655,504,579,657,554,276,665,958,287,21,488,7,616,1,841,359,11,734,622,718,19,565,830,845,508,597,583,160,687,663,68,982,576,92,223,601,867,990,264,96,965,476,990,67,219,784,292,491,137,719,900,340,170,636,226,52,743,718,510,401,762,173,610,39,626,40,417,889,298,463,450,21,231,867,113,407,930,103,313,9,584,963,163,932,854,924,780,711,274,795,392,277,173,676,606,84", +"848,788,78,855,334,122,587,801,616,365,282,644,503,244,377,674,946,390,556,798,406,39,177,834,993,453,483,953,621,661,913,379,26,515,358,59,242,842,420,141,590,860,944,603,79,936,524,817,957,877,584,713,179,434,316,611,947,756,319,711,342,341,621,386,983,149,692,27,426,902,131,904,78,465,538,339,205,367,690,620,808,6,798,462,549,562,355,775,666,29,318,712,983,379,114,539,469,202,276,441,424,324,780,389,696,888,369,815,910,52,570,231,869,590,986,631,636,273,42,708,21,687,266,408,780,200,328,767,273,833,102,608,618,979,314,859,709,898,834,959,321,891,829,425,191,788,179,988,948,419,684,164,122,48,753,208,355,387,359,828,742,750,723,863,89,639,773,45,778,700,832,831,170,963,374,755,367,380,329,152,894,992,185,862,183,722,483,777,344,742,751,412,818,415,232,58,215,329,551,582,692,928,454,169,262,65,137,225,830,588,885,634,382,185,490,496,787,322,790,347,172,330,909,80,731,158,650,500,712,293,299,585,320,417,424,283,787,717,489,655,584,423,430,85,951,157,992,124,5,385,784,234,333,875,792,204,831,446,27,378,237,237,632,608,201,695,631,123,286,143,0,547,596,409,514,971,283,449,371,731,669,44,7,712,380,965,824,804,628,984,890,215,820,702,724,435,539,189,653,346,509,835,332,167,654,277,748,512,265,575,546,784,568,840,693,601,774,79,665,30,774,676,562,538,651,477,184,12,86,170,556,109,396,388,496,449,701,163,735,400,241,386,620,146,310,472,994,493,954,930,641,230,190,643,263,930,577,967,656,50,565,928,231,118,882,848,39,157,471,925,18,325,325,383,632,68,599,227,558,663,703,288,510,746,680,36,728,982,723,27,540,902,563,364,489,543,892,613,869,739,863,750,881,463,570,803,903,922,218,490,427,282,671,159,743,921,994,979,265,111,718,753,840,790,212,375,249,425,214,852,464,657,318,584,40,583,699,759,79,69,87,431,457,80,301,989,474,689,529,399,989,228,309,764,983,848,388,687,702,251,246,86,794,428,564,204,581,847,630,844,416,435,406,626,93,857,998,437,440,433,403,914,160,990,915,236,428,148,378,291,338,80,478,136,211,823,935,564,148,951,923,479,159,254,66,779,429,263,828,58,965,256,42,863,289,21,599,468,398,22,400,101,907,650,155,599,774,240,255,284,319,909,330,579,503,306,962,555,930,799,785,231,598,415,296,388,693,138,589,7,284,570,822,271,826,277,189,880,822,484,468,834,969,901,801,520,308,545,493,13,171,758,505,105,412,579,857,16,507,663,564,602,443,607,837,993,378,523,111,386,763,804,292,55,912,764,37,648,966,579,825,257,603,890,610,549,106,51,246,556,818,22,110,487,533,126,87,550,702,178,260,478,669,678,211,79,82,41,403,181,689,525,758,293,888,248,5,197,445,536,261,277,663,398,103,861,805,573,515,401,931,865,499,319,149,643,921,612,123,308,64,437,355,826,311,402,685,70,634,603,294,22,63,271,61,542,988,298,736,952,730,953,605,17,623,7,247,623,369,145,567,447,271,201,576,424,898,479,160,568,153,931,438,336,538,813,770,772,537,166,730,4,75,962,163,23,371,380,677,620,10,281,710,681,859,234,311,379,879,341,183,907,778,959,279,469,964,715,816,718,954,613,742,175,172,600,553,389,906,377,757,208,888,461,55,875,147,738,988,164,868,119,864,459,338,263,150,679,485,645,797,704,388,953,701,681,620,477,523,382,977,568,82,892,333,606,889,963,689,741,646,915,118,10,655,907,173,929,881,831,684,943,811,419,909,385,574,353,492,408,518,914,300,550,722,932,341,288,681,847,263,302,294,409,116,402,735,341,934,718,235,786,928,912,16,69,320,350,245,198,602,774,402,672,329,469,266,767,220,352,546,335,302,357,204,367,85,799,902,227,563,346,221,227,86,325,702,794,632,159,272,395,320,796,20,533,66,121,116,850,473,324,8,159,943,161,426,762,553,847,751,809,643,23,246,384,151,177,867,450,22,969,807,395,150,419,290,259,884,544,546,723,63,578,256,633,632,280,306,111,127,919,384,656,939,834,43,386,564,260,891,162,196,603,62,142,734,177,914,186,424,686,416,958,395,296,655,21,38,873,980,326,81,823,989,545,40,478,63,162,405,282,662,597,266,564,803,401,352,197,335,998,649,700,433,875,737,276,34,666,940,269,239,350,704,418,329,419,599,440,944,334,662,575,104,364,712,637,550,784", +"918,359,850,974,620,190,494,419,286,77,810,497,325,767,705,685,969,257,259,220,494,970,903,729,280,111,327,551,78,152,299,812,32,747,385,364,719,108,643,170,210,295,106,780,944,846,100,604,790,192,373,412,820,534,414,644,658,277,807,391,667,714,87,918,551,957,290,736,31,75,55,941,618,535,425,396,278,480,871,421,890,348,267,550,53,634,70,683,396,110,832,276,397,624,393,146,963,479,362,708,237,937,887,573,877,787,27,271,818,167,367,774,851,45,459,198,207,962,550,201,668,207,564,618,706,653,812,833,350,848,170,160,673,404,268,23,799,845,295,688,26,206,475,811,173,436,442,666,200,496,579,303,490,475,321,96,812,655,269,569,609,296,810,95,900,887,214,162,358,499,184,48,165,481,583,734,772,142,56,116,691,646,51,938,991,277,598,453,118,782,821,391,813,573,743,541,89,865,148,957,199,617,93,981,897,910,299,470,772,891,79,439,963,30,143,248,558,955,671,371,838,354,10,599,280,23,703,748,485,526,21,291,451,495,829,70,337,351,393,430,52,71,829,609,676,325,621,977,863,979,131,239,960,132,642,313,787,621,463,694,293,251,490,817,118,268,731,138,997,352,547,0,599,538,771,176,780,864,870,15,843,743,391,965,578,742,951,523,210,294,745,38,643,399,783,534,970,730,451,812,328,346,407,309,271,478,252,448,35,525,898,403,368,693,515,842,32,166,200,259,649,556,928,120,86,779,996,94,701,542,190,774,652,844,635,727,911,351,790,651,973,100,428,212,226,935,135,651,853,214,648,431,793,384,841,952,235,489,291,565,235,616,671,304,65,796,84,974,420,281,652,549,108,917,897,25,927,724,51,388,743,939,917,388,390,820,977,455,934,133,983,362,988,17,366,2,886,639,871,908,792,44,974,498,753,203,171,688,243,609,234,777,738,800,751,339,45,252,144,879,348,164,212,851,446,553,143,857,531,748,746,646,219,838,548,443,33,170,377,677,3,958,263,747,799,363,988,188,526,949,186,966,143,7,416,281,297,67,43,584,240,454,362,397,562,206,904,385,251,455,518,849,269,627,519,880,386,776,788,478,527,524,625,503,533,166,600,805,545,468,46,917,881,352,633,133,196,606,178,261,687,435,741,195,879,554,677,421,689,60,128,546,333,684,110,646,997,71,722,132,653,260,681,256,408,818,975,536,535,759,672,726,69,237,511,230,940,814,973,962,404,762,122,855,297,813,851,213,326,693,297,369,35,480,276,762,379,720,534,902,746,454,234,585,759,964,586,940,457,465,378,804,959,868,3,251,583,540,389,876,126,137,282,576,778,884,998,550,279,989,746,176,931,469,452,307,957,529,289,698,776,66,807,632,657,914,648,721,202,839,199,730,725,456,918,622,923,526,110,284,56,896,543,834,626,802,721,318,700,994,275,779,676,523,624,526,409,204,375,392,305,327,994,813,869,355,634,627,655,953,400,597,611,557,331,223,934,948,524,888,697,913,278,571,371,881,373,147,329,874,771,303,516,909,307,657,273,141,774,78,552,224,778,18,413,191,649,461,18,344,91,545,725,824,276,641,727,34,512,535,502,566,94,136,539,398,135,22,580,173,470,931,136,324,209,466,284,15,395,149,960,509,223,736,850,53,442,296,239,129,316,437,438,806,86,55,664,113,522,565,603,117,775,605,230,838,833,38,623,90,189,898,975,6,852,21,79,703,543,494,767,689,585,763,286,593,591,602,375,387,383,475,611,658,98,750,246,32,319,4,690,477,33,891,826,875,102,74,343,540,465,902,501,709,343,245,766,178,597,618,687,553,413,278,286,813,458,443,469,319,706,727,328,216,862,759,50,446,47,611,239,74,488,107,286,53,352,872,745,515,551,385,225,512,190,317,120,638,433,663,48,159,14,994,40,273,613,488,484,487,482,399,777,511,95,635,198,383,613,275,94,489,135,702,187,774,844,649,172,394,391,572,371,164,260,896,228,320,154,777,241,142,471,370,529,112,930,988,686,235,850,503,351,425,573,722,691,183,605,838,969,985,488,238,615,351,421,843,207,508,713,984,603,187,889,469,604,310,395,6,486,193,194,356,60,579,141,252,371,160,198,650,781,771,97,548,28,611,731,609,732,269,89,403,815,290,202,735,920,620,276,956,953,32,74,822,799,28,476,438,220,419,318,270,881,564,916,299,737,305,357,816,604,738,826,983,145,653,484,31,993,789,33,830,351,439,913,696,831,879,697,442,662,980,707,633,62,140,343,180", +"694,355,855,793,956,543,813,164,278,821,146,194,244,950,380,664,862,661,827,379,343,803,808,820,880,895,704,983,635,346,349,328,47,394,237,850,89,366,860,962,910,748,322,73,243,947,114,239,458,686,83,38,764,811,423,642,120,940,180,831,336,375,527,649,984,399,893,848,129,899,785,842,512,544,875,62,187,559,164,85,371,485,168,772,350,19,148,708,814,60,704,467,56,872,64,647,6,133,723,537,135,393,922,645,339,619,136,76,816,171,659,142,836,560,939,939,718,61,885,694,200,583,851,338,532,690,139,744,180,774,303,331,518,431,511,728,123,912,272,437,614,870,536,393,725,424,632,49,495,12,607,755,516,444,986,260,755,474,14,352,371,7,883,430,8,680,578,946,583,247,637,888,159,349,602,623,90,861,577,228,712,936,212,643,951,81,180,218,746,70,949,498,268,876,519,979,525,336,584,199,128,996,300,830,637,574,151,599,837,67,264,202,207,674,739,739,308,389,459,315,934,234,793,898,992,948,712,625,328,553,923,59,968,282,370,43,635,241,570,149,562,777,760,814,432,574,433,468,941,260,721,838,223,133,883,395,463,432,573,362,529,387,65,744,964,625,373,137,861,503,596,599,0,101,816,66,689,747,211,322,993,932,157,247,626,364,920,294,763,439,512,594,443,204,135,769,689,249,881,589,50,798,246,420,734,943,141,2,219,626,68,742,370,596,528,817,475,365,727,442,706,989,203,118,287,866,705,644,561,588,807,677,885,195,970,615,453,782,432,313,281,857,522,960,865,75,379,732,926,795,352,633,100,197,882,87,666,543,734,980,531,618,4,116,395,686,202,68,554,228,627,513,473,314,226,735,100,408,108,128,614,409,502,727,989,6,978,50,833,774,16,5,595,720,729,603,352,663,934,164,215,857,588,243,599,292,9,542,505,501,683,857,334,884,610,896,599,124,303,172,864,946,919,114,36,563,968,202,956,982,587,368,827,912,319,224,385,794,614,101,394,207,701,334,563,909,47,202,113,657,355,400,677,1000,101,901,400,898,466,36,671,499,96,908,736,353,860,197,28,2,401,183,162,233,409,989,286,543,633,131,849,638,715,381,396,847,840,107,973,704,238,514,243,32,634,26,447,882,523,962,899,836,159,36,705,217,238,765,906,38,593,160,105,722,665,339,549,790,174,70,169,481,390,56,31,430,473,769,204,782,728,287,799,225,698,633,234,640,645,747,984,452,712,376,51,740,14,847,99,904,340,281,520,803,62,849,937,668,714,479,75,505,816,384,824,36,68,581,164,749,802,310,206,946,337,555,303,447,647,399,359,165,447,672,988,814,644,427,310,291,382,863,535,381,787,865,399,864,492,140,678,722,343,554,168,121,448,879,353,601,521,132,83,825,800,714,604,325,962,673,990,899,834,998,584,186,776,451,9,123,931,735,168,250,524,723,418,886,79,333,545,433,835,943,631,24,818,270,607,604,364,353,881,162,587,872,406,405,411,24,848,141,602,709,667,843,675,404,324,808,448,999,140,966,781,846,751,849,817,193,970,829,423,606,927,784,497,501,403,715,78,282,317,592,339,202,203,622,161,186,504,224,385,941,943,633,706,388,569,2,868,636,654,393,467,471,971,915,827,954,98,295,651,365,237,346,285,964,608,548,569,775,592,619,41,557,150,500,14,266,882,220,526,932,346,874,990,218,887,679,51,209,639,908,637,189,652,544,938,78,418,369,244,255,925,640,349,782,835,311,553,179,208,213,326,907,842,546,823,233,724,788,45,548,163,462,169,798,315,55,215,775,812,106,441,218,745,104,122,611,807,720,421,721,515,605,303,66,857,783,886,232,338,676,438,79,681,424,819,860,759,19,841,35,345,400,846,352,942,841,644,239,622,579,811,320,844,587,870,276,189,581,249,272,31,128,925,251,608,180,301,366,989,717,850,648,585,966,463,113,991,953,965,211,184,397,798,709,990,455,12,871,614,705,983,118,924,314,173,38,939,461,849,404,701,515,634,986,712,703,731,515,107,878,642,502,382,897,312,811,198,729,799,70,37,632,297,643,106,594,442,366,601,13,521,316,562,926,237,644,397,306,327,992,375,650,497,637,127,855,154,694,47,56,883,161,45,123,278,909,8,868,909,382,844,1000,716,802,297,305,880,209,554,853,121,690,410,834,856,257,142,646,656,516,654,128,150,160,248,80,446,307,827,680,652,541,564,764,892,772,939,856,408,665,127,872,11,917,634,914,275,683,694,940,141,827,794,758,154,491", +"512,944,107,135,45,340,65,442,43,660,859,335,18,123,105,738,566,934,64,419,206,54,631,333,859,484,527,122,411,431,416,682,483,334,141,643,992,91,885,10,505,556,853,897,261,26,793,817,140,505,258,581,338,378,120,786,642,320,57,884,842,104,37,145,632,891,347,248,377,240,57,626,280,695,221,68,335,931,639,245,268,37,852,785,480,25,523,140,775,187,456,763,299,949,86,341,114,7,15,81,93,466,346,180,757,905,692,645,823,450,787,473,561,961,780,201,554,497,240,565,636,378,54,246,628,958,108,778,311,885,36,971,107,438,321,350,773,779,23,515,604,768,613,404,995,883,155,958,748,444,747,310,51,223,904,865,387,268,954,693,667,753,635,898,973,619,882,541,891,480,195,95,220,271,915,538,754,836,646,624,226,346,739,379,486,371,372,738,500,649,8,478,263,658,849,502,321,215,462,66,859,615,222,873,751,723,11,245,829,380,926,297,5,941,412,905,921,70,555,900,386,879,377,181,313,904,31,135,58,451,74,514,609,936,778,851,156,971,453,491,907,62,578,673,406,181,966,180,381,924,128,951,985,443,841,393,639,317,521,63,378,735,167,871,194,348,180,853,816,466,409,538,101,0,799,916,693,649,316,477,464,835,767,994,676,868,304,800,756,700,127,618,96,870,370,376,50,830,542,6,575,215,774,853,515,179,344,391,891,795,614,881,134,752,849,534,89,676,837,998,100,631,42,842,948,81,600,666,190,447,515,483,205,213,930,380,634,102,872,283,995,926,450,674,807,628,707,920,192,27,193,667,474,511,144,164,558,945,528,485,610,308,431,504,606,640,535,498,60,359,696,669,59,55,307,562,880,706,623,663,3,342,765,157,869,985,686,694,345,587,482,601,159,169,177,713,848,256,451,767,302,327,275,162,2,280,894,833,845,601,272,847,719,622,539,973,425,275,514,151,375,441,469,899,754,374,585,231,194,778,509,833,166,834,914,130,882,915,230,664,344,876,423,494,435,761,198,901,502,739,137,932,588,630,362,932,127,470,335,505,302,168,596,458,827,392,321,192,897,263,135,244,619,811,301,446,750,738,396,357,846,674,592,879,182,956,608,415,112,201,389,225,33,471,266,399,140,747,775,845,594,545,236,182,254,625,964,416,683,464,634,826,505,139,274,816,745,87,628,636,69,3,392,296,758,83,666,937,692,354,900,607,514,26,91,201,975,531,567,672,918,347,302,881,466,924,7,655,434,60,314,513,583,481,211,525,977,432,849,465,546,902,733,857,814,654,896,526,619,422,531,722,151,115,43,29,388,783,406,812,628,79,507,655,289,157,609,1000,827,956,580,133,578,369,934,529,585,864,470,957,912,39,359,533,530,461,204,399,190,184,879,276,931,485,396,557,557,910,140,557,936,651,817,199,726,97,672,883,62,963,602,347,933,305,793,176,632,9,809,895,138,558,629,769,727,24,117,932,569,607,498,942,911,119,815,755,809,297,632,278,98,960,924,98,862,342,758,533,739,708,431,184,304,783,868,486,682,608,535,797,280,634,549,962,948,175,216,91,624,320,309,295,435,172,156,38,593,842,142,584,995,107,983,755,785,447,301,382,287,786,510,304,976,526,2,621,847,635,853,510,416,455,105,854,768,305,318,115,430,898,645,627,115,484,365,668,338,378,229,874,787,545,776,598,721,524,69,961,28,525,909,909,476,977,176,831,745,405,529,602,85,830,745,397,451,357,366,316,807,814,607,482,173,308,820,119,708,912,17,862,679,496,741,427,76,860,354,98,180,818,755,852,272,782,635,503,414,771,711,633,634,108,802,482,93,792,418,885,930,136,251,72,174,354,952,574,139,276,949,279,527,908,215,538,343,685,616,901,729,680,388,680,262,65,38,830,987,440,829,466,650,676,867,486,847,748,55,52,631,376,13,187,265,9,637,713,265,648,664,289,787,479,560,124,868,791,175,182,430,996,451,102,734,191,644,348,701,159,724,546,860,154,829,545,570,331,832,793,650,90,123,918,549,400,17,238,286,44,194,769,480,535,70,900,191,12,128,955,271,6,896,695,765,82,866,135,793,478,396,754,377,899,548,264,516,468,762,409,270,483,350,873,144,847,143,510,763,566,798,186,916,675,493,590,201,178,894,112,64,324,481,238,162,684,708,793,574,546,302,132,814,214,874,532,577,589,228,163,801,699,664,330,762,848,584,287,90,982,110,760,438,971,44,700,418,132,962,741,916,822,829,812,242,693,696,95,537,856,840,220", +"390,781,868,183,119,552,477,419,471,782,375,471,482,635,479,867,224,137,367,846,323,340,988,304,749,523,337,382,988,420,545,815,958,660,939,463,881,974,414,85,274,305,120,528,548,911,221,797,571,385,512,109,775,511,498,284,534,768,256,18,797,341,375,327,352,429,810,819,399,650,335,775,592,85,130,556,951,528,920,934,462,499,923,857,183,707,747,535,611,985,573,628,134,487,175,263,76,737,850,595,823,293,799,201,861,345,451,980,717,239,139,255,420,755,593,457,298,170,568,939,134,44,681,584,48,131,284,894,206,15,899,657,440,162,407,253,786,248,98,548,896,263,294,293,964,472,514,940,867,39,510,62,627,727,203,286,412,86,377,318,386,660,963,491,232,173,623,238,385,865,706,330,429,139,409,947,825,676,836,221,533,41,36,24,792,987,177,428,24,412,629,432,893,903,698,800,503,59,808,502,992,624,557,945,721,135,399,186,160,811,771,539,32,183,256,319,729,428,846,926,390,426,174,704,907,627,528,498,245,340,701,698,623,172,562,106,391,803,490,500,681,738,618,373,670,952,859,50,953,245,410,582,721,21,920,332,86,196,644,134,353,693,472,759,339,496,766,470,600,926,514,771,816,799,0,551,561,65,793,333,190,292,90,76,737,555,55,397,628,196,53,701,248,738,202,575,903,733,988,220,815,122,163,881,838,419,158,172,32,673,431,742,20,978,258,692,459,873,681,166,937,193,182,499,909,147,737,484,643,812,118,598,982,88,4,944,212,36,378,460,59,988,360,144,823,799,874,96,878,707,490,576,812,58,562,866,831,611,552,266,931,82,753,770,120,866,615,469,934,397,668,925,713,198,905,195,759,857,907,238,494,359,139,171,435,806,338,282,2,700,925,925,750,166,975,198,145,458,772,375,779,461,661,582,476,563,565,97,941,991,807,412,914,532,479,691,406,95,138,231,578,373,987,762,431,891,143,847,410,119,302,98,80,615,552,397,710,22,56,291,833,752,670,314,317,291,953,111,778,36,815,922,721,721,138,489,841,532,819,746,26,412,213,63,232,158,65,835,647,505,546,224,792,189,223,64,889,586,155,15,298,339,997,910,713,879,639,459,30,331,922,654,237,800,226,517,62,886,793,184,328,817,462,788,934,850,848,526,483,218,204,960,492,107,915,240,697,792,738,54,960,645,880,399,210,981,766,28,898,479,697,876,137,520,742,368,791,286,617,312,663,706,674,493,582,295,341,996,657,327,697,168,996,442,371,983,987,367,289,46,166,901,297,520,697,47,312,419,673,216,467,249,547,398,14,896,308,729,225,802,747,281,123,336,358,213,939,606,745,367,559,859,652,371,160,445,822,79,870,316,452,221,126,575,986,99,90,777,836,506,409,915,895,979,843,356,557,691,498,283,721,187,585,324,512,470,74,976,63,581,213,840,824,31,327,545,383,889,852,346,848,626,120,123,627,497,316,657,583,586,911,143,768,259,742,386,438,133,874,442,486,424,412,630,600,926,817,858,945,987,475,1,518,847,282,665,586,344,306,726,47,325,940,693,203,772,489,3,279,409,655,274,796,185,320,165,388,92,496,458,778,491,180,841,561,465,208,268,229,102,567,105,221,882,781,327,150,92,130,792,468,872,341,370,548,291,410,317,81,214,512,933,220,12,872,164,59,570,1000,105,876,228,576,181,425,992,722,194,919,170,480,36,286,96,720,547,562,454,164,343,374,661,277,284,601,378,522,37,446,751,419,749,886,508,812,331,210,878,909,114,384,500,697,425,389,243,69,532,382,6,491,69,406,374,816,487,118,285,301,641,306,945,916,860,804,111,574,588,183,76,750,610,208,385,892,770,284,678,345,660,722,923,509,743,147,825,812,64,108,214,161,72,902,267,263,707,465,677,925,904,613,996,109,518,358,835,400,653,951,525,478,648,200,149,935,569,316,121,871,959,419,532,514,203,827,606,992,903,21,738,816,801,608,425,123,407,962,116,268,36,317,514,217,941,22,885,767,71,303,302,945,786,229,272,138,716,856,261,809,940,847,672,167,721,926,76,614,158,757,445,642,980,805,700,250,44,549,16,199,740,789,762,181,112,187,640,486,646,150,203,354,168,96,744,986,704,692,222,62,728,355,893,930,482,468,557,498,144,5,797,555,778,719,402,696,276,980,440,987,453,453,140,991,734,925,525,936,749,898,51,520,121,662,86,687,536,510,626,929,240,941,46,161,687,215,411,681,123,297,570,834,212,198,73,653,269,590,888,652,957", +"913,907,269,768,527,360,543,916,258,662,634,855,447,871,291,168,416,990,789,269,882,746,940,352,532,582,57,77,590,275,5,995,302,601,658,66,300,265,364,5,283,673,648,406,661,872,555,299,730,606,936,370,74,91,766,190,179,459,935,407,943,201,635,279,745,496,607,554,138,894,2,753,149,553,660,110,165,282,567,694,916,921,270,897,4,467,439,934,544,818,806,191,499,253,997,229,448,469,255,123,425,958,929,609,276,685,256,965,304,90,582,800,666,346,523,278,722,666,258,257,300,744,2,118,66,404,803,496,536,76,328,247,492,754,390,590,192,8,825,520,202,389,165,448,597,212,4,157,411,228,810,426,105,382,124,220,959,975,982,804,799,719,407,395,260,678,832,972,319,771,989,286,115,752,15,244,196,492,541,369,58,617,660,617,392,667,724,299,389,704,840,340,678,160,627,925,806,728,663,859,212,739,40,9,943,948,852,776,881,190,635,685,707,751,606,504,544,526,332,982,723,849,433,77,959,165,640,832,952,729,711,666,875,523,475,637,918,208,700,47,697,430,934,445,653,951,255,741,840,260,305,346,458,155,875,721,888,175,255,732,886,981,293,721,48,787,211,909,15,447,971,176,66,916,551,0,737,544,136,250,200,669,30,511,325,94,138,710,705,324,862,457,811,790,981,684,976,248,732,886,420,4,274,808,469,721,291,546,869,317,185,788,278,239,692,212,468,443,116,790,710,795,215,962,156,530,220,323,9,649,681,25,61,449,883,866,327,323,434,975,314,672,208,156,976,676,329,617,27,693,156,705,579,646,673,183,293,432,840,266,122,184,410,617,66,458,721,599,841,610,617,582,572,491,292,70,445,577,735,209,779,465,794,369,886,286,847,835,41,69,386,231,178,812,443,155,5,143,573,498,293,699,362,654,603,974,523,161,76,824,279,427,866,827,970,705,702,446,753,422,786,788,388,853,462,840,921,307,638,199,943,383,596,676,825,281,48,365,763,458,562,728,999,835,14,125,123,59,230,1,223,771,485,74,466,137,318,837,782,33,347,749,90,293,641,440,188,517,551,900,560,511,442,702,118,207,773,804,839,481,543,379,303,673,177,809,603,552,895,948,657,976,677,346,183,115,549,72,292,424,435,597,192,228,727,286,742,869,11,662,517,322,173,548,600,484,725,465,199,351,594,777,376,265,991,411,773,562,18,748,865,624,259,94,807,689,40,138,371,821,816,84,271,590,984,283,254,683,558,670,969,320,530,499,898,869,939,498,838,770,604,952,753,667,566,603,51,774,53,357,426,450,692,922,763,355,655,438,838,54,791,715,207,256,79,427,754,605,416,455,946,223,219,764,724,565,796,24,835,274,337,856,118,718,133,481,360,240,38,916,58,778,967,116,832,376,592,98,164,190,949,537,225,919,932,194,9,211,814,127,217,329,558,886,818,989,966,227,982,296,114,52,537,49,975,871,332,738,833,736,840,848,489,255,257,585,105,427,545,557,664,624,48,78,473,549,337,336,406,549,516,301,299,937,126,682,977,355,959,829,106,392,95,201,53,756,733,382,383,365,270,533,37,375,529,401,810,70,766,892,589,934,209,255,930,927,597,929,397,857,515,918,111,725,795,265,40,79,887,229,529,74,226,473,586,730,221,375,704,903,201,479,778,193,807,854,36,379,186,990,182,147,374,855,60,617,385,631,877,449,871,660,388,823,552,660,29,803,268,808,288,108,600,671,475,568,265,383,357,493,590,263,578,207,904,105,420,489,974,168,378,584,864,78,599,748,267,580,764,574,460,598,360,375,198,457,705,866,506,505,782,41,561,105,589,634,884,192,117,646,376,809,496,934,32,435,274,663,246,970,479,15,713,757,224,967,967,627,938,416,545,379,208,273,526,38,275,454,680,807,796,975,1,735,875,602,511,546,327,380,659,472,895,139,40,393,649,305,307,126,636,10,437,927,787,925,290,772,94,167,266,966,186,275,873,701,656,189,571,450,120,919,333,73,107,313,553,503,916,476,692,935,639,936,810,140,926,178,414,728,298,680,822,601,661,369,8,259,443,976,167,475,56,740,472,405,437,728,911,98,225,385,726,184,555,963,628,690,163,641,273,804,118,779,93,614,862,305,307,125,894,371,848,774,393,534,801,323,346,674,478,101,387,498,549,819,214,436,455,563,172,253,732,476,435,594,399,134,504,331,307,136,723,879,375,785,8,180,343,973,901,511,500,774,600,42,57,746,72,34,562,905,942,638,265,732,981,880,99,260", +"118,520,162,746,444,441,874,736,732,468,189,326,694,405,745,819,385,647,280,463,945,187,326,445,433,692,400,573,445,670,3,484,12,775,145,584,474,982,649,531,271,961,675,579,801,39,525,534,568,983,197,753,496,477,630,90,362,812,71,585,943,914,333,97,122,178,917,537,205,757,395,318,431,351,517,82,141,675,92,231,992,422,920,470,893,833,749,778,913,727,507,600,893,838,95,48,995,697,542,491,535,235,136,725,639,380,93,989,601,951,466,288,111,677,537,291,827,541,364,401,756,287,535,258,368,406,469,870,765,630,633,362,784,116,558,414,960,965,705,279,306,640,367,828,491,188,921,330,900,410,375,298,290,464,524,207,182,948,818,310,453,189,150,183,723,620,515,405,548,899,987,326,276,974,744,279,812,40,58,504,793,808,718,814,957,836,579,489,529,525,617,115,99,586,78,922,906,847,276,147,923,214,341,334,561,356,582,627,188,9,235,851,815,906,848,55,570,420,873,537,580,248,654,549,26,306,424,115,614,932,796,897,637,40,925,812,228,199,329,729,836,553,249,497,930,241,211,508,685,809,566,871,59,975,73,117,487,672,721,296,859,356,825,45,403,882,597,242,782,609,283,780,689,693,561,737,0,220,994,17,903,207,123,755,357,28,630,134,977,592,584,556,478,873,382,156,626,599,480,958,354,760,517,331,239,735,803,412,556,237,391,768,296,343,994,971,804,527,582,573,905,620,919,79,563,882,508,506,168,533,904,649,192,765,751,498,986,827,937,220,645,624,618,308,353,733,749,542,648,155,323,377,212,57,562,778,708,913,403,876,449,234,494,922,749,453,810,561,988,377,615,407,701,84,37,296,998,483,508,846,236,376,620,388,415,210,808,345,344,732,270,853,917,927,121,117,971,74,693,14,341,192,587,925,919,645,853,110,817,837,169,556,889,235,647,735,277,230,550,460,254,56,956,942,143,28,281,588,150,407,83,212,577,132,707,376,468,486,637,609,664,123,772,371,541,343,672,309,588,122,596,212,478,29,161,394,447,835,43,855,549,213,995,980,412,650,613,484,604,320,988,564,621,831,99,419,278,897,57,491,242,233,869,815,714,983,890,243,559,403,31,798,628,37,694,680,622,328,770,397,909,434,908,326,329,421,804,162,631,306,712,865,625,915,114,735,444,716,719,462,261,57,779,194,142,500,751,970,239,858,736,581,31,179,189,75,938,34,560,748,588,403,18,260,937,35,550,690,248,467,879,496,263,795,895,977,326,445,682,974,139,806,161,382,502,771,919,438,404,604,208,25,801,914,713,618,26,134,403,370,287,706,805,282,43,49,222,550,105,566,753,611,608,149,215,536,710,163,765,917,766,318,326,822,360,492,122,589,425,200,964,565,310,405,918,916,75,736,237,37,187,786,207,359,379,129,192,262,630,743,509,140,846,402,62,899,548,686,619,166,190,324,850,174,657,42,63,562,305,242,118,900,454,218,629,901,290,464,59,720,442,656,624,545,106,164,347,786,605,836,905,662,360,104,204,401,440,444,297,101,878,165,218,635,955,523,721,266,98,128,149,921,613,665,593,149,125,685,254,982,759,491,587,90,932,115,971,892,784,484,206,562,746,948,147,244,471,426,525,782,687,670,758,51,357,96,774,976,3,884,172,724,475,364,953,377,968,998,990,856,657,973,82,197,779,796,192,549,976,780,756,912,996,363,650,791,624,641,450,342,297,910,77,849,381,169,712,200,106,261,117,345,835,866,72,358,730,504,773,919,683,241,143,698,341,221,116,750,799,143,641,274,405,714,514,81,602,739,587,571,246,682,485,273,961,25,837,147,132,942,335,206,228,705,738,50,149,878,917,342,754,630,634,793,303,66,325,370,534,840,456,286,159,990,515,776,242,180,763,690,876,707,979,473,179,923,4,675,23,897,408,992,284,546,181,832,73,922,728,56,953,877,43,633,348,502,802,127,282,946,708,4,343,590,836,469,710,608,297,640,581,419,400,962,278,736,170,968,636,624,360,532,98,827,609,993,496,653,995,724,454,918,649,121,580,643,949,562,152,503,519,511,796,455,412,85,163,280,824,871,597,341,281,35,62,110,270,434,310,808,185,513,244,482,752,813,219,519,410,103,222,130,338,649,253,796,633,812,742,231,441,950,382,329,730,564,704,806,316,473,772,52,838,876,231,25,979,926,91,842,856,642,633,563,269,359,433,540,411,181,806,405,330,775,433,989,561,242,370,33,116,421,473,16,884,502,904,669,133,207", +"776,52,197,162,102,988,356,57,57,724,387,189,887,57,326,811,108,710,473,25,564,292,844,444,763,390,3,473,392,708,494,538,580,21,803,612,717,857,151,850,236,952,346,400,277,137,846,334,628,160,639,538,623,34,605,974,401,837,830,236,191,653,268,478,667,488,529,36,196,565,636,88,972,31,139,93,442,940,606,306,34,53,565,65,404,928,623,699,550,206,732,53,661,411,16,777,873,626,56,414,409,842,919,316,966,645,237,961,996,92,604,139,358,495,177,662,692,234,802,45,929,78,468,657,982,113,589,393,181,92,374,889,73,269,221,202,983,142,751,994,639,100,974,550,975,811,516,772,617,366,272,232,46,667,904,462,550,871,324,85,561,57,247,128,130,899,113,356,854,99,61,288,449,737,143,330,700,42,688,166,447,26,387,285,397,385,990,720,644,286,155,822,620,903,512,591,437,957,486,98,618,403,872,382,420,210,839,901,118,179,566,107,112,406,360,829,685,667,716,15,596,354,407,667,918,102,273,30,692,723,40,806,826,286,62,980,307,745,464,319,581,93,768,66,314,675,61,621,130,175,157,497,376,649,976,200,638,124,972,640,847,809,550,234,775,105,62,50,339,281,449,864,747,649,65,544,220,0,297,593,326,107,822,262,399,451,818,974,597,221,991,476,839,724,25,218,605,925,101,572,148,477,920,210,786,572,75,463,2,251,755,347,938,31,187,891,13,786,556,723,919,538,45,712,223,853,359,410,657,837,927,849,468,414,188,2,39,390,281,671,209,309,83,718,72,497,81,787,840,134,313,177,13,390,149,232,181,271,52,108,449,182,2,366,343,748,105,581,162,16,653,137,881,482,260,465,535,109,70,27,328,505,652,262,288,224,504,906,124,645,89,535,103,614,594,872,47,704,298,98,172,654,5,873,434,247,978,795,355,454,209,362,11,603,282,245,668,368,199,961,378,123,442,386,641,561,612,770,378,480,755,849,271,230,378,867,581,253,883,596,88,874,209,671,230,236,223,508,209,861,671,721,563,936,490,749,49,641,675,800,144,191,14,7,468,826,97,447,74,883,796,125,772,166,305,51,910,114,342,856,480,439,16,664,984,994,993,515,738,540,33,126,804,84,973,91,937,996,379,666,581,30,674,241,779,821,666,671,896,749,288,16,191,979,905,632,65,978,755,417,31,870,240,297,776,536,620,643,330,15,349,847,995,735,144,970,684,242,609,553,329,320,403,956,94,298,714,468,427,858,339,795,769,248,436,515,833,565,347,776,874,526,5,807,738,186,97,530,917,753,506,644,325,39,913,776,728,553,966,697,850,421,232,863,203,600,682,222,539,783,637,902,333,774,889,571,576,630,625,304,618,13,157,584,958,806,274,743,137,347,290,820,433,618,115,825,423,764,433,879,287,394,355,973,96,374,289,998,737,515,226,121,190,25,491,272,506,321,436,923,934,566,631,29,329,488,961,635,657,318,715,384,133,617,13,729,988,832,195,385,587,730,46,341,583,701,459,461,965,710,436,469,279,889,983,68,811,824,753,108,740,407,33,902,400,932,675,504,999,686,426,276,769,795,626,254,817,735,605,125,725,323,379,794,856,723,514,125,370,162,837,405,865,467,591,965,899,884,588,810,254,722,359,5,453,562,558,638,746,944,546,252,127,953,839,820,621,271,866,148,270,966,642,142,905,908,694,489,62,290,281,746,506,774,974,150,797,721,769,265,409,869,80,44,474,608,864,142,243,679,740,11,154,685,176,390,434,197,345,76,846,694,19,966,427,191,890,606,734,13,912,118,741,113,858,108,909,640,996,431,760,924,432,909,612,440,149,895,750,191,475,513,709,409,260,863,863,369,670,743,798,664,484,402,485,285,739,811,956,727,783,328,604,297,226,451,725,252,725,678,142,6,335,647,820,155,570,559,920,344,845,835,30,310,600,669,44,619,313,38,756,357,3,870,769,418,363,539,274,354,969,930,785,104,17,383,640,247,121,729,439,898,439,421,852,330,517,24,555,90,875,62,566,140,682,609,935,437,313,158,86,133,889,362,965,709,840,784,258,648,895,683,281,16,83,514,560,63,660,276,538,311,956,580,570,120,187,589,781,310,445,835,367,936,429,51,261,307,499,188,352,14,583,699,131,711,115,622,490,722,943,866,278,339,425,842,560,520,871,720,916,364,765,495,665,363,735,102,548,666,140,169,957,667,458,162,648,547,122,560,512,430,335,932,801,856,986,31,626,857,427,421,218,394,346,650,529,63,126,259", +"441,669,338,3,62,911,33,504,651,52,557,369,529,596,698,819,118,786,895,785,220,102,314,963,844,219,868,626,431,977,628,292,956,33,781,37,492,234,827,301,96,913,779,871,663,827,442,810,259,773,22,950,906,697,499,14,266,269,766,688,739,155,656,528,957,619,344,258,64,196,216,971,33,356,53,192,573,825,851,904,597,289,102,988,84,661,642,274,775,496,917,61,998,938,974,321,954,72,437,878,789,207,759,836,55,304,284,937,29,549,863,166,717,542,226,585,837,867,733,624,884,543,573,749,745,327,132,826,371,963,427,416,494,167,785,442,122,232,25,88,287,833,99,766,887,777,773,782,138,443,627,643,861,830,518,195,396,220,376,758,252,347,137,150,262,565,143,701,90,885,60,10,528,385,818,164,964,167,99,615,193,559,459,657,253,976,573,22,313,700,330,962,855,897,868,82,800,847,77,728,125,559,879,707,992,493,393,989,472,396,975,766,581,861,903,31,166,531,10,971,146,811,51,867,246,774,946,143,467,112,826,657,149,165,799,523,9,728,352,719,568,387,789,621,449,489,659,816,42,921,750,858,730,988,973,578,154,301,95,740,23,780,45,579,739,362,996,733,135,10,371,870,211,316,793,136,994,297,0,45,911,816,531,948,127,569,709,377,345,873,978,580,101,769,250,96,709,863,991,496,797,664,464,776,32,432,141,315,44,38,418,824,875,127,192,424,122,534,895,654,148,216,261,280,392,899,901,105,393,538,392,150,875,994,68,523,876,410,153,200,774,821,374,505,747,796,504,754,415,171,689,684,429,423,541,398,856,274,767,6,930,913,475,191,530,825,544,564,313,972,223,717,48,595,855,492,780,771,489,927,956,950,980,954,683,669,874,443,599,906,60,380,869,187,452,367,53,505,597,79,358,234,88,292,461,520,396,298,166,458,172,823,51,627,349,702,191,534,244,451,781,678,345,274,793,493,428,338,766,935,730,399,494,331,941,387,806,479,53,810,142,852,923,377,279,277,541,93,296,154,948,873,549,737,447,463,798,372,424,640,451,162,262,423,520,414,573,634,118,583,614,263,715,264,672,904,288,313,919,450,336,141,483,49,878,696,777,955,636,386,128,675,120,68,194,350,97,192,995,393,494,413,919,197,487,140,159,464,596,864,812,852,753,102,763,54,858,114,330,764,78,152,308,218,729,621,627,953,951,89,378,784,600,771,219,634,528,776,116,810,756,54,570,127,701,623,264,616,23,447,191,158,193,933,183,186,371,925,396,30,738,211,952,101,107,591,790,24,233,331,178,995,526,472,58,612,470,490,821,860,474,174,606,976,322,109,664,350,851,368,320,217,172,754,908,731,933,762,698,204,306,370,158,70,333,810,156,195,170,308,175,737,654,849,290,480,460,660,726,35,989,344,720,466,110,355,881,90,345,740,877,257,142,527,178,624,688,112,892,350,178,628,839,59,155,76,260,606,223,966,956,658,405,583,465,304,132,332,262,649,293,28,259,364,879,54,545,665,417,2,247,393,123,943,333,104,532,93,941,263,304,71,932,811,713,216,292,349,96,774,827,17,528,692,960,348,878,401,981,85,718,60,666,412,926,30,557,438,475,247,24,668,542,227,510,298,291,360,2,816,355,205,214,920,566,704,974,413,913,447,508,135,249,382,6,40,266,345,533,96,469,298,155,417,962,59,491,596,491,814,202,727,475,325,433,172,161,248,925,583,613,915,33,11,732,186,144,419,62,45,126,248,833,837,309,719,120,637,283,232,151,234,722,61,998,94,262,817,948,933,941,489,480,222,20,848,675,751,964,606,937,389,544,374,990,256,300,2,255,959,504,818,22,112,110,547,350,787,445,134,995,989,361,468,925,586,835,177,59,673,510,430,881,808,24,491,846,491,639,48,657,339,346,914,389,76,355,777,275,750,651,3,461,922,320,490,661,998,664,24,328,311,316,415,947,28,722,307,710,269,145,889,50,315,409,481,784,20,504,940,164,155,281,438,562,31,752,259,955,716,267,512,567,528,225,637,459,248,225,519,107,361,362,443,800,630,796,311,761,87,754,433,937,748,840,449,884,449,378,705,266,489,299,537,908,6,512,395,430,589,754,237,793,922,292,103,78,919,118,27,579,898,534,376,592,704,117,833,641,739,446,356,707,728,313,815,897,424,252,282,800,294,619,887,573,389,762,144,730,306,679,731,762,127,783,37,358,740,306,359,309,534,530,829,965,307,87,991,845,481,924,363,296,435,703,209,452,224,68,3", +"438,597,314,73,169,846,518,204,810,110,56,357,930,930,649,817,752,629,85,620,93,418,623,145,410,526,725,768,364,86,469,334,370,691,811,496,73,926,477,200,383,697,179,756,393,227,998,917,978,506,753,710,405,726,108,276,550,760,360,215,897,71,727,510,13,91,531,15,957,172,180,162,639,203,283,431,288,920,919,865,552,732,481,871,689,310,883,722,191,926,670,582,287,722,330,260,389,830,189,429,443,572,902,317,829,868,760,326,133,273,987,463,555,546,260,159,852,687,45,136,185,983,861,259,154,204,675,324,820,850,89,393,77,814,219,549,779,599,903,296,287,643,297,571,169,582,403,900,243,205,378,300,295,363,244,493,463,36,166,11,262,350,222,446,475,168,204,176,533,560,204,134,978,254,523,359,683,338,268,737,227,750,845,909,448,883,121,671,861,477,80,253,516,476,886,181,347,751,859,968,754,892,733,383,663,504,365,551,914,670,98,193,216,878,926,101,267,371,578,25,81,54,704,734,471,493,871,227,650,311,775,309,317,920,292,66,85,473,875,488,60,150,570,180,922,901,952,240,66,669,263,840,198,72,323,261,422,539,13,458,363,741,59,975,717,904,142,591,134,104,731,15,322,477,333,250,17,593,45,0,682,770,810,251,109,575,6,188,15,993,630,974,936,985,725,231,569,298,346,757,965,625,448,874,75,326,116,412,849,221,584,442,510,994,133,200,316,458,325,50,187,656,388,664,211,794,154,685,435,963,703,628,972,729,203,247,889,999,116,924,495,614,394,295,950,90,223,74,462,534,833,240,226,222,431,179,254,800,449,722,373,700,385,419,530,377,726,492,89,212,166,889,891,543,762,361,357,110,308,566,589,527,784,202,183,25,516,484,487,119,46,376,658,321,125,655,531,820,847,649,451,336,471,675,142,478,188,708,308,318,315,102,329,558,793,132,80,385,961,656,894,707,460,873,695,27,623,371,335,889,398,75,539,647,429,11,40,9,975,700,513,769,508,79,458,325,866,930,287,295,294,751,477,192,270,748,66,149,373,381,936,519,958,309,867,960,878,343,504,320,323,582,740,737,473,65,196,203,358,596,65,137,892,563,173,857,642,681,246,503,863,140,921,834,959,601,470,734,605,320,787,383,846,173,671,392,64,830,314,805,983,946,62,563,957,886,331,324,258,89,388,522,567,864,592,886,668,301,832,34,909,627,572,186,211,886,289,894,530,110,266,781,847,786,370,829,213,317,632,580,381,875,629,102,977,544,997,633,363,653,121,36,324,922,842,61,567,68,46,693,916,145,971,177,183,23,895,734,311,868,157,523,157,715,944,774,947,359,193,46,749,321,778,155,365,808,930,803,856,710,572,717,114,969,550,308,667,613,388,314,706,518,790,33,728,744,413,815,972,755,74,134,519,345,792,372,583,571,967,516,846,497,865,221,258,777,605,195,828,274,619,319,846,2,986,586,211,112,998,552,504,807,645,870,457,76,380,651,129,573,621,341,17,697,194,938,725,526,303,512,617,911,371,817,565,462,685,866,596,46,974,771,565,358,410,877,193,459,829,99,273,301,972,916,901,143,970,509,182,38,685,112,11,554,950,729,272,689,459,534,468,261,991,795,972,240,184,678,993,958,182,315,649,515,247,408,908,271,389,632,791,564,153,355,438,179,716,46,390,234,769,978,448,782,572,921,138,119,218,154,889,702,711,353,578,499,610,577,38,534,467,55,198,835,251,476,941,577,93,758,856,933,19,694,284,26,867,530,285,151,9,746,458,807,241,691,267,924,128,639,953,209,941,658,250,906,745,480,96,56,185,767,87,261,739,939,341,939,872,323,202,369,580,52,254,731,422,247,887,675,709,107,194,445,983,27,222,688,880,222,195,703,588,22,915,306,838,134,770,600,91,44,774,664,509,339,444,979,597,668,568,913,74,411,98,481,424,59,308,730,983,715,35,186,928,726,601,531,713,485,124,116,861,318,288,776,682,929,659,977,342,566,579,820,507,729,825,433,70,295,918,375,114,823,806,552,59,60,357,297,715,895,666,999,13,390,849,681,113,44,889,874,286,982,808,682,34,38,711,75,985,602,828,504,637,243,337,551,555,579,403,432,516,364,885,349,920,584,127,371,611,194,391,698,759,166,430,457,367,311,38,736,89,883,674,652,37,856,197,996,553,174,848,112,654,868,253,187,570,506,625,555,536,452,881,238,710,11,981,502,241,657,517,210,326,334,396,62,822,306,432,745,429,520,295,463,711,39,281,875", +"488,292,996,810,396,39,998,868,559,936,324,598,618,517,794,882,353,702,264,293,6,228,114,873,978,830,537,462,987,375,948,681,809,437,495,687,601,560,129,296,881,491,388,354,291,82,160,815,126,796,104,32,329,534,953,147,426,55,81,299,815,709,262,819,769,965,879,33,172,217,884,583,937,638,511,982,412,927,862,920,617,435,539,824,582,260,940,638,1,615,249,397,201,109,797,469,94,470,726,802,887,28,211,605,326,206,627,781,739,819,309,483,699,962,65,217,840,449,245,367,701,170,709,489,512,472,324,824,961,356,686,742,492,465,426,537,152,49,883,121,5,999,911,410,525,540,765,535,822,4,20,419,399,805,86,16,573,787,482,710,1000,394,862,610,297,39,542,915,800,260,666,489,508,422,98,71,326,176,989,473,229,205,780,757,239,431,986,976,251,413,519,930,93,202,901,540,751,341,991,33,511,817,939,429,285,195,789,870,816,324,636,198,63,914,617,566,775,320,214,744,23,946,573,639,683,706,22,856,840,780,27,552,598,896,947,708,47,443,538,474,849,201,846,741,453,368,874,917,384,838,30,887,968,369,751,259,608,523,261,189,562,999,339,118,499,996,766,724,838,693,669,843,993,464,190,200,903,326,911,682,0,406,283,870,599,348,147,541,683,694,935,25,500,264,305,632,464,993,379,342,450,476,655,974,965,87,511,457,31,800,904,883,673,713,490,865,554,969,987,133,149,259,604,641,643,260,830,264,549,928,423,612,521,64,327,766,25,943,98,632,343,638,695,30,193,494,266,493,238,173,804,159,553,593,46,242,38,357,140,789,155,60,380,100,462,775,26,703,122,616,973,490,801,166,521,199,970,467,557,885,607,869,794,62,895,730,679,75,500,246,457,714,52,132,532,287,685,517,368,499,126,416,479,800,91,771,393,912,552,151,698,338,47,711,264,658,105,509,252,104,281,671,429,754,514,674,858,320,484,739,983,103,79,703,108,435,238,529,820,474,798,178,846,737,898,420,677,880,169,305,621,745,172,52,67,783,449,629,318,323,7,992,867,463,583,742,801,552,458,500,413,965,805,828,16,454,927,914,23,61,13,727,548,915,888,353,388,443,599,615,157,240,666,926,818,652,855,592,137,618,931,737,3,828,559,11,749,569,990,929,583,581,761,247,150,787,394,921,297,167,948,415,806,530,447,599,222,119,73,81,358,405,398,21,984,688,594,178,63,684,788,302,150,859,256,944,263,299,778,258,800,254,120,203,881,644,524,928,14,966,287,290,120,313,642,752,557,873,711,358,627,405,792,889,545,372,294,139,333,12,742,491,96,365,632,398,26,582,843,146,528,742,894,622,965,665,424,869,440,637,825,477,691,508,982,412,937,790,726,949,465,923,722,812,124,559,115,58,436,245,464,702,407,416,953,319,809,876,697,510,326,69,700,664,687,48,441,222,903,62,247,335,884,434,396,508,208,305,923,767,121,135,190,244,592,434,954,623,204,488,874,803,314,976,274,502,802,608,938,692,77,456,496,539,323,716,547,302,84,37,369,355,975,440,930,514,340,491,724,464,324,43,738,466,422,596,291,337,662,920,916,241,84,976,591,192,39,831,232,966,710,358,12,690,877,943,889,41,50,716,187,884,637,325,863,597,266,768,384,268,389,209,799,327,709,863,767,195,85,101,790,225,894,794,334,19,846,850,90,240,413,88,708,635,830,620,338,552,799,521,901,137,42,521,354,32,174,786,129,121,526,446,565,769,843,39,273,885,60,332,999,266,265,270,462,87,618,304,771,708,71,504,58,33,214,927,119,932,616,139,938,575,501,660,438,298,791,954,551,480,287,973,488,394,727,82,87,161,919,390,491,819,959,384,215,164,712,733,960,419,78,890,998,61,190,430,577,771,516,700,496,500,123,856,584,546,580,760,182,381,265,219,953,470,752,112,807,445,449,292,298,487,443,579,966,479,78,744,637,613,293,541,968,450,756,934,963,155,371,320,480,951,530,18,390,5,360,535,901,256,743,951,893,153,705,438,684,957,97,672,699,594,740,629,377,928,16,518,751,743,616,864,4,815,554,566,27,828,282,480,846,933,602,394,484,34,696,872,26,804,96,721,202,762,346,398,189,576,359,812,725,948,423,317,843,298,724,168,77,921,201,145,186,157,364,207,83,156,340,851,517,474,367,362,807,870,954,833,454,757,690,425,204,677,391,671,912,321,545,375,674,719,309,917,340,410,201,613,874,552,437,282,764,572,586,771,641,411,383,895", +"187,269,294,559,806,154,110,692,307,392,285,119,981,297,94,715,225,650,616,112,946,334,228,557,814,227,687,32,338,749,741,381,329,111,613,319,136,188,41,590,293,397,934,412,472,664,841,858,421,884,298,880,792,495,255,353,616,654,890,652,269,604,708,78,35,669,443,876,375,477,53,836,374,643,531,156,582,946,547,493,530,194,484,706,930,681,910,622,96,515,376,653,557,242,740,238,876,141,627,447,306,227,947,615,381,211,171,846,243,534,999,291,77,19,705,605,786,1,735,566,903,138,709,281,346,847,501,623,168,100,224,356,979,329,663,850,131,60,768,878,937,560,866,210,8,224,847,462,733,523,978,254,456,439,781,760,16,922,526,532,526,763,494,488,276,670,948,278,480,893,201,813,529,227,383,845,202,427,93,857,514,292,306,566,859,972,479,549,916,741,284,456,22,808,457,211,797,370,560,920,577,27,927,991,47,446,907,523,336,319,447,134,480,646,737,531,794,254,525,234,357,138,941,779,932,679,402,232,666,871,991,94,30,957,786,425,101,988,634,73,996,336,477,150,877,947,381,703,568,456,92,323,861,382,735,761,355,977,383,45,860,33,238,284,899,457,633,472,518,605,44,743,932,835,292,669,207,107,816,770,406,0,98,44,299,473,19,134,524,823,192,565,195,659,885,772,682,85,565,141,944,725,973,216,570,753,922,487,479,146,241,785,522,130,773,631,484,437,273,270,414,32,37,293,348,724,273,224,136,479,575,504,153,863,516,661,295,127,696,219,98,254,76,639,873,574,164,312,694,829,721,606,395,767,215,398,402,683,590,517,836,842,738,719,348,1000,723,354,510,932,14,9,261,926,329,6,679,296,217,282,960,616,80,261,389,972,144,452,17,265,151,593,8,52,732,681,28,761,866,722,756,873,28,747,593,966,300,133,942,221,990,672,239,937,521,59,703,223,352,770,273,435,667,275,333,570,480,877,582,620,420,945,55,426,869,473,454,161,867,472,461,647,338,969,299,440,19,896,836,650,784,770,540,907,510,896,618,986,541,294,209,430,285,840,547,201,156,256,992,566,616,911,469,445,256,16,760,865,672,305,700,876,633,215,512,104,247,450,696,21,156,394,641,681,228,740,52,855,315,620,783,307,189,484,939,541,880,647,903,243,933,729,544,286,173,787,356,62,825,250,163,894,54,939,129,895,733,400,472,672,568,304,978,989,630,647,253,174,660,870,743,61,232,81,241,791,278,263,210,908,919,1000,483,921,747,933,185,918,131,185,840,343,467,714,757,59,297,160,35,288,74,183,299,12,316,56,542,22,925,853,672,907,244,434,835,75,512,349,882,57,291,907,694,463,352,5,974,132,185,762,335,575,551,384,218,873,871,552,705,790,132,117,399,269,486,691,598,95,280,790,567,936,968,81,609,155,792,736,89,712,744,546,980,354,631,856,149,760,978,177,228,522,720,2,487,24,69,529,70,683,498,359,824,588,656,324,24,971,336,781,673,917,376,348,169,956,631,401,971,839,468,972,613,150,909,591,759,676,53,346,134,398,221,901,549,216,873,841,420,834,643,514,109,162,796,966,738,845,811,564,222,82,365,671,496,891,28,477,840,19,635,584,915,717,638,148,266,736,792,80,861,410,785,281,541,944,714,176,658,165,587,181,215,935,649,49,712,742,119,426,474,578,113,819,50,522,687,612,159,30,812,876,23,286,442,749,215,536,770,799,262,881,253,373,47,562,790,237,572,432,2,749,481,718,148,612,414,72,839,940,64,806,110,730,813,707,957,660,556,847,47,185,329,627,144,241,191,575,621,789,365,809,762,385,299,362,74,130,309,975,71,559,173,535,65,465,696,594,377,870,865,944,685,166,433,665,156,123,774,494,499,813,187,277,257,815,912,623,663,784,993,666,374,449,999,837,191,909,309,110,175,615,307,758,112,273,328,655,509,408,315,821,246,778,794,815,607,29,383,47,757,123,368,175,718,771,683,125,686,183,912,821,817,565,235,294,248,374,232,862,174,371,589,430,720,999,659,911,778,99,505,486,146,161,153,215,833,309,6,803,350,499,930,869,226,985,735,865,298,771,929,90,873,744,728,590,818,616,935,356,262,20,771,444,961,387,705,941,708,348,857,92,932,86,985,295,559,389,127,303,509,374,593,58,978,687,372,78,163,915,680,401,142,236,597,56,526,585,56,479,298,91,472,452,647,607,528,167,644,862,859,847,419,952,661,378,475,469,444,818,183,448,345,747,595,111,273,507,211,910", +"813,463,133,822,906,10,306,404,586,778,579,848,790,949,923,941,557,685,786,807,890,962,538,27,686,893,969,419,468,344,860,938,835,989,837,736,122,850,359,358,798,376,904,728,52,862,322,861,240,883,491,367,76,987,494,413,126,683,44,25,166,658,642,563,539,294,606,745,689,138,276,803,503,84,107,882,929,487,293,510,487,511,240,466,19,833,322,683,322,41,813,615,894,613,307,322,439,279,923,281,424,784,651,235,10,47,597,507,676,821,643,468,34,930,586,989,603,275,586,296,60,265,981,991,907,668,152,666,770,939,315,256,723,981,928,600,987,740,879,734,214,212,531,313,100,262,855,460,933,367,953,200,179,949,894,609,867,910,704,67,167,398,922,689,209,573,197,912,701,535,589,454,309,40,472,338,234,298,75,816,879,15,555,77,915,708,617,661,753,969,63,213,762,376,206,92,44,755,36,655,836,65,233,368,22,494,184,421,404,575,570,950,571,760,299,230,619,283,421,203,896,559,12,388,136,871,611,648,986,523,22,13,794,208,53,994,13,970,298,892,100,85,233,851,212,609,568,811,128,849,40,558,320,567,32,418,118,924,893,947,643,463,456,70,455,279,242,895,307,450,7,391,157,767,90,30,123,822,531,810,283,98,0,529,432,506,274,139,547,795,952,26,414,287,521,260,111,832,803,405,215,757,457,29,293,231,504,135,24,781,12,84,401,262,487,512,811,231,502,940,446,551,827,832,593,297,733,946,23,865,917,64,987,714,237,549,780,386,77,814,681,570,558,859,578,546,788,719,181,466,190,891,938,213,667,409,310,294,928,291,157,610,485,386,453,827,918,365,341,25,413,348,7,363,437,565,458,670,186,63,454,406,393,105,880,199,761,654,520,894,731,104,346,714,68,240,888,560,412,420,992,723,764,565,510,993,6,304,422,550,210,447,814,779,532,650,799,113,435,517,492,92,371,72,478,338,370,31,995,879,973,611,496,480,384,730,147,73,987,492,298,255,269,486,380,142,16,113,940,51,843,674,713,979,584,495,890,807,223,622,998,845,603,512,251,554,975,152,270,310,248,313,51,745,363,107,265,759,423,511,210,411,661,848,780,769,550,299,678,919,136,590,722,208,734,619,279,948,419,678,547,836,980,743,252,8,889,328,455,954,341,735,854,176,937,347,433,221,545,496,303,335,456,681,745,831,828,252,965,954,613,756,771,126,626,831,145,30,950,952,275,325,411,672,571,284,6,399,936,706,67,943,932,74,829,748,111,481,815,157,569,20,538,381,614,446,39,907,646,869,220,452,130,332,490,914,861,773,666,142,459,158,139,327,27,386,718,366,995,341,978,905,588,960,682,884,626,487,795,843,829,189,180,583,993,699,349,471,864,100,376,332,349,72,944,45,771,123,513,805,279,814,788,375,324,34,420,865,523,186,408,753,908,848,267,751,343,117,55,243,900,451,809,872,270,732,311,383,432,526,113,884,385,270,683,879,436,180,707,781,905,51,291,494,158,713,631,213,442,152,792,701,585,943,665,821,552,353,206,768,868,21,797,954,761,958,881,307,154,34,168,361,885,976,276,857,416,764,257,613,290,550,68,902,107,58,211,844,604,247,387,751,936,12,826,37,367,548,561,358,522,316,338,706,960,341,903,721,736,633,272,126,202,109,791,770,174,28,663,490,264,778,914,361,567,515,130,887,525,703,372,86,379,739,503,342,455,981,276,459,100,43,90,820,109,465,162,894,406,412,275,435,508,949,577,728,728,824,334,928,772,987,826,55,277,243,316,439,841,912,235,636,271,19,406,764,657,839,274,78,974,715,135,565,349,234,571,390,697,197,822,532,891,671,504,610,283,437,626,616,718,464,929,546,101,736,299,227,369,258,872,460,967,153,870,155,908,302,230,450,907,971,166,233,829,133,943,620,406,305,170,636,417,831,794,483,783,526,969,550,693,907,703,871,316,560,862,998,935,259,591,465,865,7,497,178,332,276,703,963,404,608,818,828,710,377,51,564,468,71,81,147,97,979,518,18,791,595,193,848,89,601,100,76,993,700,790,67,426,811,279,343,939,71,58,947,847,875,663,810,788,307,6,395,345,340,490,976,545,762,556,240,218,464,397,833,686,902,998,597,633,47,904,793,783,999,944,328,460,813,486,440,514,80,468,34,35,730,504,452,686,60,251,99,581,414,625,265,234,604,956,383,83,671,179,149,190,879,192,305,994,773,827,348,697,327,899,582,734,711,849,589,603,634,216,134,200,314,481,605", +"668,378,874,836,889,577,25,680,80,750,696,553,196,388,798,429,522,460,207,637,448,968,491,583,329,881,355,639,173,544,170,460,167,314,713,337,261,770,957,713,889,702,754,608,707,470,986,671,713,297,507,920,900,650,853,252,724,812,48,739,4,575,611,151,288,561,676,301,343,528,6,961,358,366,709,118,38,71,544,169,205,188,869,373,980,868,957,274,956,261,824,638,558,63,544,221,320,455,914,792,402,2,190,562,320,608,386,271,10,648,622,429,801,109,64,661,896,752,698,957,626,486,794,146,120,503,911,18,571,506,215,351,409,266,410,252,440,529,85,722,159,311,197,445,912,570,386,214,100,867,240,305,153,208,29,818,15,687,144,716,376,585,372,422,957,110,446,644,49,14,273,52,188,969,518,39,75,627,85,345,659,459,278,528,176,51,309,487,576,876,466,80,414,744,692,793,143,343,869,300,300,301,634,651,890,740,528,950,311,37,148,920,894,887,667,257,395,429,302,610,576,315,744,575,590,73,299,817,592,924,886,547,861,744,868,544,848,226,219,992,813,938,505,650,182,54,640,956,971,766,228,248,281,429,393,396,108,118,279,823,292,765,874,856,950,811,251,843,624,177,712,965,247,994,76,511,755,262,948,251,870,44,529,0,337,752,259,452,332,840,825,467,700,795,123,411,996,818,99,839,482,560,170,329,359,510,602,861,388,359,771,297,131,804,981,859,581,124,789,368,145,561,178,192,844,518,868,446,62,410,409,410,682,381,319,339,943,636,636,424,156,234,152,956,1000,162,988,433,475,779,544,666,496,469,616,488,376,930,259,970,148,560,924,643,567,571,482,77,37,372,147,447,202,68,472,208,483,234,829,751,703,588,550,110,773,558,991,487,862,889,637,10,807,485,545,537,666,413,970,701,116,948,223,320,573,37,381,630,729,987,494,858,46,537,282,899,412,805,389,198,17,47,408,705,433,432,216,116,309,946,152,807,793,454,200,652,720,778,715,723,276,13,76,37,180,26,911,70,499,591,516,464,388,441,290,978,533,870,7,656,9,314,424,752,339,33,371,754,700,980,377,825,174,845,509,713,346,948,413,341,762,985,18,74,400,447,159,575,71,977,826,970,157,564,584,318,960,567,714,575,460,446,454,487,954,813,487,905,85,27,355,714,642,720,124,712,449,985,483,74,746,673,737,539,550,558,471,181,599,716,113,719,741,111,819,171,769,271,27,390,73,476,911,912,72,65,796,903,788,171,52,198,332,359,524,178,13,53,329,711,927,629,70,714,487,202,652,408,455,352,452,641,746,863,658,943,2,255,211,459,138,384,188,474,887,585,415,34,823,602,996,261,79,784,278,964,741,880,519,309,133,687,502,686,213,717,185,96,809,134,850,834,542,340,132,998,868,18,153,625,808,385,473,247,538,998,153,360,762,384,826,61,311,827,352,781,742,292,182,761,873,379,832,829,854,202,67,959,758,70,780,21,202,98,349,265,219,44,742,927,605,230,382,945,866,172,367,887,40,484,55,769,48,469,935,782,12,494,448,45,134,535,915,531,649,352,643,941,99,789,52,959,928,7,220,662,820,118,961,258,208,107,992,113,22,636,500,115,866,203,464,40,330,697,733,530,701,348,920,849,793,328,544,26,203,946,981,177,9,50,454,529,814,353,788,675,832,434,174,411,642,883,978,74,372,14,970,357,854,662,241,245,730,586,22,63,836,769,144,368,392,384,745,490,438,997,844,947,861,673,152,694,898,285,884,937,462,297,393,372,673,468,587,186,489,972,498,143,429,630,688,55,851,126,314,825,782,619,349,102,246,259,686,756,188,708,509,166,169,90,610,426,815,89,336,386,525,677,771,901,251,818,451,650,774,652,342,673,715,408,428,674,32,164,994,807,28,69,328,135,186,679,699,788,820,86,903,201,840,95,280,391,983,592,162,657,461,645,297,565,352,395,884,188,780,935,160,694,368,51,984,1,282,160,942,470,747,364,283,156,562,222,777,99,763,186,658,648,372,292,307,6,679,95,915,446,270,247,722,543,403,599,384,950,625,355,175,720,821,296,248,204,29,594,224,786,150,505,8,594,73,96,250,986,873,2,653,224,727,437,746,22,878,780,428,34,744,823,451,426,794,859,369,658,878,187,534,629,104,17,779,804,525,921,438,128,368,113,129,370,654,238,275,132,192,2,112,100,716,801,638,891,663,226,288,227,286,571,614,778,320,946,433,816,869,247,709,532,366,238,821,7,363,819,218,533,565,517,278,976", +"373,64,638,74,931,874,965,681,625,872,111,387,925,28,491,410,644,982,162,913,102,161,528,843,611,246,141,417,237,452,126,728,227,447,981,87,203,777,177,898,703,256,499,484,244,578,807,474,818,984,337,758,634,320,283,730,905,510,988,890,108,739,600,724,396,267,252,29,234,863,400,424,446,995,570,309,573,228,254,890,785,300,82,986,433,809,29,622,334,616,378,591,603,313,312,105,489,282,974,39,376,640,797,482,638,995,512,719,404,410,249,534,155,917,302,537,153,895,505,34,803,381,123,488,577,992,707,393,204,699,944,921,598,596,523,385,191,147,563,678,83,96,653,985,547,779,300,418,737,747,178,862,810,973,502,415,514,629,173,766,971,177,240,173,416,44,76,301,431,622,592,132,90,140,304,846,771,598,597,370,357,938,585,888,5,95,406,652,365,647,171,232,863,473,126,657,302,557,199,680,195,423,851,860,258,233,166,554,56,300,165,321,293,265,116,944,677,873,520,896,81,894,853,878,518,769,452,849,780,603,268,155,176,443,390,831,318,856,864,371,980,125,816,832,478,530,921,429,513,957,618,522,38,718,512,691,290,171,378,262,484,267,722,143,584,651,218,727,971,184,380,578,626,676,737,325,357,399,127,109,599,299,432,337,0,902,311,12,856,483,592,539,782,941,725,141,512,329,101,222,391,342,353,453,82,824,242,948,425,98,791,73,425,350,435,683,715,593,373,2,824,99,503,604,627,244,982,964,298,967,170,656,531,55,732,986,898,857,533,525,657,649,138,19,953,759,445,487,633,47,782,931,431,420,474,103,537,867,823,33,460,422,512,629,365,549,232,122,31,199,326,407,200,892,1,136,488,380,693,717,304,427,465,341,260,502,779,57,316,845,606,150,448,68,136,108,77,446,673,139,177,288,892,606,269,630,374,230,306,558,177,335,329,498,21,644,564,632,17,236,489,421,280,144,561,740,101,279,364,53,84,807,348,541,733,938,478,736,109,536,837,215,771,792,365,856,302,747,911,306,344,890,826,765,812,452,474,411,366,380,498,411,140,782,667,104,385,385,98,594,923,502,397,122,489,70,993,922,930,638,463,532,801,291,105,510,858,330,173,823,936,213,528,839,888,417,222,319,367,805,164,90,963,193,517,397,262,499,975,15,267,595,997,665,406,723,911,363,848,540,746,227,957,707,25,252,583,927,66,319,814,667,391,303,195,418,737,124,147,334,347,748,942,231,764,312,517,123,925,339,373,830,386,119,1000,356,62,261,431,794,650,17,778,134,394,220,686,926,683,44,285,243,543,843,55,654,313,804,68,172,414,753,342,384,818,891,981,340,989,809,17,886,716,458,126,33,203,634,62,93,542,50,305,801,558,57,312,354,419,11,307,725,238,81,75,328,248,357,875,638,549,144,816,883,9,928,137,939,719,951,446,26,226,241,341,226,205,911,124,387,680,510,353,692,595,756,996,39,960,937,137,496,716,89,314,645,589,413,261,764,47,986,592,852,143,48,924,342,336,973,643,660,96,554,550,495,722,858,137,286,242,692,574,964,451,308,587,491,481,158,275,346,173,328,328,79,449,647,681,163,903,158,659,740,706,80,876,385,370,635,114,414,780,301,153,690,249,642,758,975,381,192,613,546,435,573,770,954,493,35,182,431,838,840,561,428,56,715,613,491,636,273,240,54,266,607,258,589,974,287,158,451,762,408,537,452,510,770,750,161,605,570,675,140,8,499,507,595,641,825,92,247,612,583,122,435,452,393,214,743,585,82,462,407,53,990,718,782,719,847,52,265,3,767,802,304,904,161,41,147,693,366,58,706,634,654,578,790,136,954,759,199,34,300,671,850,747,462,133,860,487,938,464,953,244,932,874,400,784,498,111,774,778,206,882,637,502,510,427,374,546,661,714,287,392,766,90,82,650,884,323,367,370,558,604,645,478,333,820,164,169,869,307,655,957,804,896,809,450,845,562,503,508,1000,618,68,880,626,192,195,598,829,126,30,375,274,575,243,54,675,369,76,239,872,806,396,183,731,598,870,582,518,288,993,492,891,944,356,473,70,907,108,667,477,964,507,473,178,220,473,877,825,184,866,483,393,404,518,561,794,256,164,381,577,579,86,590,135,680,539,840,349,891,734,898,267,641,172,395,698,776,192,59,683,378,914,297,315,3,442,387,124,648,987,749,739,843,253,875,108,40,170,997,912,857,875,432,843,459,550,550,335,838,221,414,759,911,723,287,913,629,230,479,142,538,955,681,346,628,72", +"522,452,314,250,706,447,769,544,815,407,693,339,714,235,571,653,985,231,227,600,545,308,772,142,663,236,434,809,125,75,792,373,396,361,4,656,267,827,485,103,96,13,527,824,869,452,877,845,649,298,626,311,67,581,403,111,951,443,19,939,87,382,136,143,707,13,993,207,631,195,704,588,939,646,814,344,16,885,327,829,725,121,534,559,740,563,915,850,469,273,998,408,438,739,844,31,120,704,286,674,348,13,416,212,735,198,737,360,628,662,4,548,905,198,990,347,850,547,535,890,811,485,781,931,436,682,567,100,707,426,269,965,512,657,686,865,637,122,314,754,87,359,852,115,498,348,342,993,968,79,691,628,921,574,128,863,450,428,96,209,949,21,528,860,722,806,264,374,76,535,569,544,208,592,578,300,831,805,738,761,770,89,452,849,177,516,643,734,729,417,203,544,301,888,773,288,479,599,79,853,169,70,438,810,885,37,224,469,194,498,301,293,353,611,219,267,975,812,187,276,458,759,404,431,251,563,990,796,186,847,817,614,607,663,223,961,602,295,372,217,854,582,133,179,537,596,96,933,191,684,747,997,448,418,300,287,864,341,213,335,244,160,115,323,868,809,29,51,311,914,965,742,364,868,555,94,28,451,569,575,348,473,506,752,902,0,704,88,35,138,299,470,245,328,401,303,988,823,944,855,757,273,394,777,522,985,584,14,556,42,732,340,627,258,264,274,724,405,817,175,170,546,957,881,345,573,576,199,605,514,766,69,538,297,812,431,72,231,561,659,939,986,35,510,502,629,82,624,649,817,404,534,497,698,770,34,439,224,212,682,583,17,467,648,27,543,449,483,157,462,645,616,815,214,609,403,894,836,452,11,694,820,703,715,748,224,868,882,294,401,283,17,86,288,87,835,171,430,606,400,200,933,206,123,398,478,281,699,427,409,168,269,961,876,521,194,414,405,218,178,783,707,546,102,619,989,3,481,858,902,446,909,612,527,413,18,357,806,646,105,358,501,204,840,300,33,904,743,67,367,989,911,659,894,490,161,33,734,383,160,804,78,720,994,319,194,817,179,465,410,393,473,665,382,126,86,290,417,218,131,48,290,32,359,592,717,565,728,324,470,254,700,139,861,697,747,205,956,367,875,733,648,879,876,188,535,152,439,117,895,781,799,855,444,71,78,637,590,584,232,725,965,119,150,186,964,625,671,175,756,341,492,113,292,365,546,841,137,342,273,994,554,378,143,881,237,630,32,801,840,528,817,309,833,22,71,650,654,547,728,198,623,175,771,255,233,900,998,996,212,808,458,708,943,405,452,126,704,412,650,906,337,302,460,146,554,986,938,800,751,763,78,413,563,49,670,284,782,119,15,226,148,63,358,13,858,369,773,812,950,133,653,342,936,921,565,648,891,117,128,188,637,272,942,546,313,757,656,742,393,26,900,321,431,604,259,179,464,859,124,391,50,299,687,646,38,378,763,190,824,589,209,560,696,906,566,148,532,50,201,665,869,648,18,754,462,221,852,545,921,215,763,896,521,90,688,84,674,245,951,679,621,749,850,956,101,387,713,786,176,601,893,704,525,120,418,447,384,221,971,890,190,459,570,24,263,62,236,669,841,576,172,671,810,739,273,473,758,681,540,543,70,387,321,281,976,335,639,13,458,616,565,634,575,896,461,654,262,992,578,851,43,778,356,220,532,969,217,722,863,519,450,880,257,177,375,512,450,518,489,339,382,761,268,457,937,196,580,213,965,568,655,485,246,518,910,538,313,207,499,787,265,70,884,569,527,988,97,947,795,373,509,892,199,47,369,404,852,374,587,958,683,718,637,492,112,37,530,350,29,862,115,735,955,905,862,749,372,161,871,612,955,520,440,38,345,364,364,389,541,366,769,631,921,244,959,698,829,595,774,888,489,906,304,312,412,499,664,893,147,934,170,285,381,254,829,461,239,63,77,687,669,941,492,218,575,325,461,166,248,197,647,872,207,777,299,713,222,988,276,838,719,883,731,541,655,315,121,684,329,706,844,1,304,135,972,201,546,536,153,645,711,493,964,13,776,586,492,150,343,479,626,995,609,299,25,742,6,651,684,268,316,430,434,889,808,869,126,689,137,18,830,974,495,829,230,726,993,527,6,710,507,270,58,511,657,656,218,535,938,776,300,56,192,423,946,695,499,347,71,534,394,832,252,911,713,307,405,427,828,46,207,712,846,77,156,372,631,689,150,820,867,761,422,544,769,884,450,80,240,904,589,154,380,739,614,379,921,654,786", +"411,672,711,739,303,240,226,553,379,562,55,136,441,526,786,937,171,600,445,820,569,532,39,817,5,167,198,203,557,394,383,547,419,126,987,262,445,609,390,844,779,788,603,606,327,784,398,305,800,131,475,291,180,218,568,742,416,841,951,66,992,359,600,549,7,414,244,824,196,913,433,764,531,579,10,506,108,94,995,635,586,188,297,629,666,23,350,203,906,374,74,463,216,526,259,846,708,865,87,159,866,468,58,556,710,270,612,70,124,971,206,750,767,465,196,94,314,263,333,259,841,107,704,316,806,609,286,459,396,304,818,100,238,214,443,660,292,362,272,225,368,720,285,124,129,662,248,961,795,534,199,946,408,326,932,73,407,901,789,711,821,606,768,132,170,27,682,821,622,638,598,551,846,374,5,611,297,635,89,543,45,133,129,126,766,389,646,218,133,336,804,455,924,75,991,263,43,798,666,328,75,173,212,243,339,401,940,155,615,21,389,84,90,843,747,573,319,507,360,829,199,698,831,181,426,586,168,229,417,274,674,150,29,759,679,681,710,600,647,496,233,561,140,187,595,407,127,818,451,304,188,604,825,161,736,240,990,448,27,198,628,87,922,525,835,913,648,585,749,260,824,951,920,304,55,138,630,818,709,6,147,19,274,259,311,704,0,197,168,700,374,652,738,483,689,581,873,737,928,26,604,120,128,326,569,41,356,858,476,813,651,145,210,653,517,570,927,295,437,422,492,750,258,178,479,237,401,322,8,286,708,212,224,580,420,663,267,797,819,538,968,61,793,295,993,750,502,115,983,978,771,341,309,506,238,324,114,774,260,495,989,909,919,768,845,285,507,240,919,480,534,563,2,216,58,925,784,441,273,214,684,259,222,960,946,474,874,860,719,644,34,700,246,965,688,34,338,519,773,638,671,407,93,699,521,662,760,298,898,499,97,306,604,652,835,351,341,66,306,672,444,601,219,507,638,698,143,339,278,601,346,812,246,960,996,470,656,712,949,669,58,711,25,841,702,656,852,610,741,179,193,442,827,679,854,839,612,38,340,13,822,851,184,107,563,638,692,136,847,164,918,972,347,955,542,16,625,811,6,231,806,58,780,326,60,934,974,365,288,452,868,265,801,469,660,398,823,664,776,893,413,232,84,119,308,145,548,501,985,627,638,432,556,957,87,140,461,383,777,612,470,54,338,318,818,987,324,944,957,794,407,991,53,6,778,618,493,642,50,449,867,107,308,990,392,554,863,866,855,536,839,511,886,52,523,564,845,806,581,765,344,804,625,209,485,72,797,450,842,407,28,709,765,455,37,785,754,9,340,254,890,412,617,442,483,892,531,587,854,922,883,184,615,454,397,701,893,443,9,382,802,631,70,33,939,268,738,185,146,763,724,251,136,64,576,430,759,24,727,342,692,949,190,346,303,500,757,246,583,360,198,368,803,882,585,501,958,805,495,42,711,565,127,26,86,565,84,103,938,315,578,554,612,320,403,316,744,180,221,63,509,60,689,658,272,575,111,452,302,934,760,114,667,877,285,290,952,51,212,654,56,410,50,454,219,931,880,143,391,915,894,936,971,864,847,266,488,658,674,457,281,510,936,185,922,260,733,426,314,894,285,537,167,521,90,844,656,497,140,649,28,729,264,795,582,497,424,65,817,404,690,601,867,226,82,501,108,432,715,897,569,561,268,173,552,849,436,104,785,56,65,503,192,162,817,917,35,915,135,671,474,388,776,88,185,231,585,686,777,433,184,654,112,174,277,611,479,476,963,583,959,797,540,358,166,982,580,510,627,900,822,715,498,400,305,852,449,683,889,114,240,598,835,494,143,451,234,951,258,97,613,324,602,770,958,725,505,263,626,534,771,542,721,701,819,409,367,453,219,311,791,464,437,930,58,797,344,292,206,947,904,902,428,132,303,306,292,73,283,216,583,693,358,462,546,355,889,273,494,866,342,410,606,325,870,182,215,664,73,995,635,669,335,908,147,265,869,395,388,260,23,923,97,298,809,708,368,489,510,912,953,999,791,455,120,287,590,696,263,923,770,399,468,607,896,826,322,601,651,551,690,647,985,934,606,879,909,387,766,638,279,12,687,573,338,916,28,973,201,381,159,53,209,968,561,227,196,141,347,735,93,184,73,743,681,764,119,962,185,676,174,810,443,362,63,835,640,164,239,133,833,733,423,510,295,804,136,85,498,726,776,638,228,409,500,212,451,512,33,116,615,673,723,889,418,131,526,735,671,334,931,103,200,569,877,787,736,542,973,275", +"772,474,534,982,468,332,909,215,492,867,214,543,208,902,498,428,649,617,971,998,463,659,853,457,57,68,301,647,769,977,897,395,999,660,645,376,708,240,134,66,575,386,775,292,130,89,542,773,443,557,809,63,569,586,162,833,990,381,209,742,781,582,408,67,775,419,994,803,658,91,888,678,77,815,449,726,476,150,759,765,416,310,443,360,104,206,413,94,465,916,956,539,512,341,316,294,328,763,31,460,827,66,111,494,300,545,508,264,338,687,269,601,881,612,44,74,10,37,476,311,280,324,869,353,765,349,531,198,146,167,384,769,926,411,23,349,946,192,895,764,118,846,353,606,484,238,301,932,76,172,534,862,554,670,717,799,136,541,47,500,602,104,970,468,249,878,339,147,15,909,570,164,352,28,363,639,328,699,450,916,100,965,442,225,404,998,287,759,773,152,815,625,161,785,231,855,953,792,45,940,108,416,988,43,556,392,150,557,84,688,73,394,54,405,963,767,517,136,928,18,773,267,654,443,559,934,489,247,287,883,89,378,280,541,529,473,510,620,226,244,268,939,298,810,240,376,599,288,562,386,171,35,872,191,770,270,331,187,296,65,689,734,372,367,883,221,626,552,993,787,804,523,294,800,397,710,134,974,377,188,541,134,139,452,12,88,197,0,813,895,768,765,691,534,406,967,270,877,556,507,982,855,342,921,405,462,595,746,767,903,553,306,499,574,251,808,319,568,438,380,163,8,931,770,688,787,341,975,427,378,83,922,634,412,171,991,477,188,722,164,200,382,264,723,574,948,892,949,778,937,269,525,442,579,849,399,74,111,616,13,29,885,510,516,406,798,989,828,797,887,830,203,460,657,687,458,266,389,627,624,650,719,71,476,694,726,249,319,1,216,172,637,169,14,658,629,347,931,795,28,210,242,240,60,548,995,87,650,70,48,517,309,978,158,277,504,6,100,945,376,166,658,642,604,808,291,810,166,108,806,690,523,695,272,519,977,996,341,394,879,809,274,786,882,672,347,89,776,893,184,126,784,350,242,523,584,28,965,11,404,455,623,771,939,569,772,70,342,592,903,92,353,291,824,90,13,889,920,73,102,53,879,543,968,951,556,936,82,702,523,117,997,632,444,668,706,726,882,293,246,924,387,137,416,191,749,361,49,667,796,134,68,533,503,235,642,40,812,424,361,420,990,698,620,404,481,10,206,268,458,791,44,435,373,79,610,770,480,628,214,488,123,599,26,409,162,802,966,892,527,903,428,580,667,398,661,957,780,589,798,60,824,371,506,368,321,140,208,743,283,403,471,885,94,125,317,739,39,238,423,58,777,808,6,875,261,723,266,573,692,188,212,407,171,265,704,764,433,265,52,647,545,227,607,915,384,54,260,419,300,890,691,949,398,369,595,336,548,702,424,596,27,319,909,993,258,904,217,864,119,292,506,971,199,369,756,131,394,835,678,947,692,191,757,419,389,132,410,930,578,725,450,440,740,411,759,635,136,905,225,716,703,960,515,126,406,303,138,362,635,467,328,971,935,359,948,890,811,770,531,948,781,1000,443,993,281,508,641,893,56,945,918,723,871,464,822,355,532,202,300,953,230,722,690,429,983,688,294,375,57,457,38,239,411,195,955,599,147,98,445,274,385,264,495,703,967,155,125,965,467,967,402,904,288,958,919,927,80,829,224,732,932,219,930,756,816,585,185,461,463,467,705,79,706,735,314,456,905,573,388,173,934,596,508,85,866,844,897,328,949,206,24,465,101,911,584,470,712,430,488,536,995,45,968,436,494,30,881,511,360,115,950,11,123,309,558,186,520,30,264,843,385,979,874,543,252,832,484,732,51,855,621,630,844,108,739,99,923,969,292,41,714,461,833,863,652,650,263,754,838,360,482,587,732,387,610,577,334,711,375,202,280,31,807,489,166,442,646,170,598,505,155,468,430,700,926,160,505,176,830,942,990,911,734,390,331,618,203,208,104,643,479,179,313,447,498,148,606,139,743,534,67,669,41,165,373,606,237,370,542,63,336,738,768,771,134,36,585,196,45,310,325,725,954,736,269,436,229,961,243,394,64,998,808,442,176,671,691,225,772,385,260,578,187,887,668,423,175,110,697,88,909,463,412,235,866,53,300,182,742,790,677,563,99,192,610,660,35,980,105,155,490,582,168,557,635,535,993,443,156,864,521,26,825,245,330,351,930,584,149,766,517,981,250,437,314,815,29,562,21,125,521,276,678,644,999,186,767,557,831,63,982,285,873,70,805,532,953,779,350", +"943,660,132,336,620,512,535,835,101,951,439,111,772,135,357,188,495,994,409,126,137,323,280,577,794,566,843,945,291,705,27,134,552,930,121,186,866,25,890,519,309,467,644,902,569,205,815,808,993,58,641,503,240,964,261,657,43,891,925,720,186,538,658,646,365,551,971,717,402,466,288,457,789,262,389,659,882,795,749,52,405,574,414,822,56,748,249,344,85,994,578,13,79,236,197,146,559,358,426,3,774,942,315,162,192,390,257,696,831,425,749,40,545,427,639,702,60,979,876,301,382,655,240,28,71,432,833,103,26,907,19,969,81,444,500,339,936,294,71,940,975,852,31,748,282,452,304,707,648,603,408,787,876,116,683,964,52,24,908,996,398,552,79,496,81,790,155,820,11,430,57,507,586,259,102,712,466,109,670,64,500,946,935,522,551,821,61,315,28,982,57,549,129,98,430,530,819,661,865,282,914,793,406,808,309,928,574,219,747,539,801,197,435,499,365,114,847,89,703,477,114,237,392,949,454,188,156,52,979,92,183,316,739,175,571,378,440,697,810,909,235,885,662,411,944,279,656,495,352,514,5,787,63,484,788,818,713,81,241,819,687,549,414,647,194,904,12,124,743,440,628,210,763,756,628,705,977,597,345,15,683,524,547,332,856,35,168,813,0,222,755,956,879,777,58,817,325,835,926,864,521,677,565,456,680,245,775,96,820,218,224,772,101,59,726,448,592,754,538,923,518,37,257,231,45,402,364,318,952,616,479,790,442,97,832,680,753,152,448,342,995,659,278,790,978,321,978,259,332,972,441,213,638,299,68,836,722,673,412,20,446,667,555,585,256,144,498,308,647,432,696,344,604,867,58,851,925,845,101,342,439,831,358,17,577,75,207,612,838,534,935,405,873,935,37,31,159,100,184,290,994,563,756,54,514,91,225,812,614,323,266,697,100,472,776,472,992,979,359,362,285,508,20,656,111,52,749,306,490,768,358,136,587,292,616,846,141,311,506,213,149,627,281,95,321,616,445,551,962,959,268,716,727,522,531,38,134,325,159,798,315,854,438,157,229,94,663,913,898,304,271,839,185,272,725,557,10,124,542,575,413,274,566,341,476,803,317,201,326,671,956,563,647,59,960,608,947,924,890,372,799,256,8,346,513,197,743,280,846,592,942,150,75,491,63,51,139,833,89,22,754,832,560,910,19,525,566,758,81,655,359,772,985,947,389,539,595,105,816,998,565,49,74,29,621,859,240,823,558,600,235,515,188,868,843,366,596,466,920,765,612,878,606,316,182,801,508,671,249,558,266,972,114,989,209,869,48,147,558,221,415,236,418,579,47,595,537,977,345,229,290,597,772,111,383,200,355,30,592,339,559,748,243,573,645,739,813,993,174,665,511,589,197,574,247,580,579,404,492,941,297,282,157,508,574,652,524,822,7,356,210,151,144,452,916,488,224,470,938,625,853,387,618,154,799,929,318,643,858,877,991,585,601,141,352,656,297,869,750,361,119,339,847,243,780,288,948,927,930,702,613,524,349,71,591,997,115,850,826,604,224,555,426,429,16,900,785,249,704,312,19,331,355,139,222,359,884,136,702,125,56,205,359,794,719,366,501,797,766,866,860,178,412,685,13,142,827,597,98,640,8,469,569,628,682,424,275,462,63,743,345,165,172,754,247,261,966,886,545,723,834,321,921,230,38,8,82,361,642,624,783,93,512,268,253,544,664,329,169,90,476,817,983,471,593,320,680,232,210,263,948,634,508,620,204,360,113,739,327,9,221,8,102,826,924,112,760,765,284,257,916,563,198,732,783,780,990,645,245,653,566,103,349,616,202,906,239,323,577,661,510,382,503,488,45,440,341,778,707,860,820,313,308,701,249,224,872,967,288,597,195,565,77,850,984,943,512,107,668,327,536,930,887,195,4,244,677,7,342,300,286,246,239,909,311,328,150,262,399,762,915,549,37,448,86,25,476,798,272,891,792,524,199,24,443,78,956,232,678,946,652,568,219,215,522,256,266,786,777,687,22,872,103,685,968,644,597,992,205,182,797,707,828,830,678,92,767,720,418,352,773,943,147,868,852,157,293,122,749,337,903,983,242,203,410,971,107,833,398,942,362,984,789,553,672,375,983,376,728,217,88,431,168,499,277,157,500,3,363,345,408,963,862,557,229,354,361,793,810,398,783,709,732,996,103,467,870,455,889,193,661,43,323,718,268,25,348,789,975,912,89,601,501,603,311,139,232,280,23,933,948,765,807,806,162,464,38,732,591,858", +"183,455,564,284,208,112,597,276,148,404,339,352,568,336,129,822,555,915,769,760,29,208,336,406,946,194,918,716,231,329,497,300,202,782,584,64,339,740,966,272,23,299,335,47,302,896,244,902,594,991,18,296,612,841,888,67,260,575,815,541,279,691,962,323,410,784,843,782,883,792,698,166,9,91,218,620,972,386,905,195,471,803,152,171,472,299,118,946,659,124,981,335,607,851,81,329,729,499,927,350,930,786,490,163,129,817,718,13,803,384,620,341,502,530,354,974,80,417,723,927,621,589,893,671,100,665,805,620,364,213,179,71,686,931,707,631,106,586,298,511,165,198,52,152,178,839,199,427,657,235,767,471,512,150,26,552,820,398,195,584,729,904,292,387,731,387,733,241,786,487,680,326,997,656,648,2,266,153,520,392,311,395,157,101,337,238,685,649,948,574,367,10,246,660,368,793,713,775,293,346,821,5,516,239,412,637,257,543,897,119,165,221,667,766,815,115,117,841,977,45,242,151,650,939,699,616,160,602,786,932,166,818,745,424,694,563,282,739,368,802,328,573,26,936,910,481,280,572,251,936,160,61,317,237,621,752,234,87,807,682,752,781,898,136,889,158,59,239,108,926,984,294,439,700,196,324,592,221,873,993,694,823,795,840,483,138,700,895,222,0,864,522,319,559,518,92,683,267,205,311,610,593,259,837,679,874,828,972,58,932,261,779,297,18,586,449,404,296,5,185,622,787,789,871,943,37,403,537,893,659,931,767,129,43,132,182,166,594,626,881,311,426,703,955,453,946,365,454,1000,897,291,669,857,357,604,769,68,467,555,580,336,792,451,309,931,119,131,783,471,838,498,585,934,652,473,723,767,481,703,459,726,642,538,79,800,596,494,41,47,586,153,485,207,780,777,417,487,410,691,717,519,62,882,586,776,293,813,93,104,149,298,964,956,976,501,374,374,842,940,465,872,406,895,531,696,259,593,670,182,578,832,333,623,249,113,996,88,41,593,393,844,630,982,205,33,368,860,305,686,133,355,241,705,360,973,752,424,941,619,3,254,710,826,991,772,372,272,486,227,698,135,581,527,335,945,937,717,580,636,535,236,483,468,854,198,179,967,576,557,200,108,49,384,248,555,204,216,68,112,416,947,12,752,256,951,491,568,280,917,361,100,921,263,430,855,782,497,910,835,712,953,414,992,280,111,967,955,619,972,459,77,67,660,550,599,348,816,846,724,75,337,67,495,313,983,994,869,594,751,730,823,983,592,63,328,544,707,623,476,359,435,123,271,538,608,31,120,875,215,792,962,794,753,532,449,680,150,102,389,331,617,765,424,352,905,623,865,370,988,815,881,814,952,900,338,795,56,358,489,779,283,321,520,899,297,292,332,501,979,982,989,606,245,101,411,573,365,956,674,924,140,54,829,31,902,589,613,643,9,478,869,642,549,159,536,555,686,289,474,168,320,653,808,983,440,340,139,345,712,517,938,633,363,970,748,794,572,964,251,833,293,751,211,701,602,565,259,642,74,192,443,627,231,369,200,10,150,716,11,722,751,744,442,762,887,899,606,141,498,638,919,507,242,126,579,124,342,738,416,63,203,331,375,727,619,923,438,300,381,470,838,251,150,66,55,525,672,689,951,473,887,640,776,745,165,856,494,589,621,12,947,826,848,406,987,980,814,558,115,581,64,965,263,610,463,677,695,226,667,201,308,886,898,87,728,900,72,205,330,424,856,35,798,867,512,843,250,780,649,375,680,556,894,718,765,206,191,190,6,319,655,803,321,468,630,728,8,791,425,215,548,781,755,848,113,425,670,563,958,465,882,756,301,782,662,354,915,645,207,36,634,50,631,33,984,601,503,224,928,653,449,707,188,979,829,932,847,85,987,139,973,557,657,628,259,541,591,804,593,823,155,709,138,795,437,973,487,425,826,92,265,106,24,885,406,384,954,159,949,897,638,36,173,249,290,939,331,947,148,712,730,866,559,807,810,826,658,488,471,706,692,371,225,747,382,599,7,617,463,422,743,922,994,146,216,198,951,900,414,210,415,913,297,334,867,438,196,667,37,118,784,422,684,730,416,617,253,31,395,576,194,575,771,750,71,693,57,965,281,175,754,202,596,681,477,95,645,887,50,910,591,25,215,641,522,385,505,155,858,300,777,765,925,508,126,519,10,195,883,347,899,950,45,372,976,921,790,307,569,277,504,818,178,901,262,36,609,192,571,522,671,96,932,921,912,61,278,511,498,682,301,908,72,52,663,690,515,262,280,464", +"6,32,482,604,428,357,878,581,593,277,329,659,673,105,412,501,148,672,834,172,859,942,412,648,351,687,288,292,866,881,152,560,474,98,164,708,807,167,33,229,938,699,934,463,920,911,300,596,601,133,876,260,329,929,918,356,466,451,465,513,121,547,627,700,2,315,22,285,919,174,552,926,237,953,216,872,731,594,464,972,267,932,496,294,610,544,802,334,119,151,403,918,63,428,464,303,431,777,741,817,84,885,138,614,774,113,504,21,215,68,78,662,5,307,617,226,671,149,171,387,399,744,687,727,526,649,155,765,546,650,236,373,513,660,549,373,204,815,250,192,876,581,997,619,386,335,172,757,989,934,265,924,461,373,24,680,399,924,104,322,514,861,600,941,728,6,225,856,966,662,891,678,931,857,892,477,347,260,893,225,745,726,329,732,455,461,962,282,789,965,515,485,969,527,508,386,267,847,53,393,692,576,205,702,345,739,495,832,823,993,541,513,981,724,458,909,91,339,665,211,148,696,986,236,364,508,970,750,884,715,566,830,710,399,749,256,280,425,77,208,125,325,833,289,73,876,740,789,840,270,861,937,320,754,363,443,559,798,363,795,356,257,374,789,271,125,338,482,982,608,890,745,512,127,53,862,584,991,978,630,935,192,952,825,592,299,374,768,755,864,0,388,260,904,904,234,851,565,750,553,375,776,48,960,363,329,242,52,854,535,110,875,92,363,679,616,843,321,734,233,532,100,565,688,955,803,871,503,826,161,253,416,292,981,961,809,581,658,595,533,655,579,663,453,582,56,236,43,458,523,295,367,254,690,666,264,998,191,247,937,316,381,998,154,124,831,31,748,502,33,276,469,294,798,490,188,602,693,374,476,820,132,509,143,771,897,404,586,399,367,36,974,685,997,304,571,991,275,293,240,796,121,367,124,94,492,404,332,226,814,110,713,857,546,588,386,983,526,124,110,437,26,820,371,227,475,352,256,712,228,244,938,778,167,787,858,807,987,794,272,636,654,359,798,236,455,946,323,546,652,486,894,320,768,165,47,481,816,649,671,488,712,175,35,287,167,712,633,41,670,701,938,929,75,637,686,692,109,683,658,493,484,517,137,457,550,842,992,912,411,351,334,532,349,113,122,639,745,634,290,164,3,218,628,390,592,952,539,256,311,705,749,990,151,927,127,542,345,427,803,724,369,100,875,776,464,504,655,212,131,237,425,472,228,204,808,649,63,192,707,613,426,117,787,11,988,746,889,962,909,865,918,859,497,663,968,459,122,245,951,653,108,898,113,248,993,500,362,700,846,693,52,871,826,865,402,728,67,51,522,134,207,895,612,913,208,877,517,269,493,766,783,875,778,431,588,797,743,364,724,405,814,362,623,57,694,156,534,447,12,576,542,893,824,22,361,262,198,582,133,813,290,669,563,881,891,425,25,759,992,740,217,997,285,274,919,596,932,83,900,43,307,360,872,721,224,223,99,267,173,855,28,96,842,28,964,714,519,222,355,323,456,373,504,800,98,208,663,918,989,661,469,272,933,458,320,222,733,461,895,754,332,901,483,78,661,928,348,256,55,390,368,205,202,509,989,276,502,170,333,806,819,833,767,265,777,991,376,561,580,128,399,379,81,509,40,755,101,47,550,253,129,773,671,187,339,512,827,112,357,143,70,126,810,534,767,109,671,124,555,708,112,14,183,190,247,146,378,166,164,41,564,197,724,446,773,637,153,627,823,57,163,785,834,625,989,384,708,420,729,690,746,939,232,735,608,766,393,89,500,690,551,333,137,683,704,291,764,27,961,364,749,611,121,687,775,386,149,529,599,585,771,166,448,804,805,196,76,419,961,758,471,669,461,606,646,117,342,842,435,876,501,681,958,641,685,244,56,574,846,950,30,900,521,627,667,27,749,455,247,490,905,980,627,329,682,516,407,696,414,65,500,205,416,294,405,48,246,281,24,684,882,947,169,11,525,887,484,737,915,980,808,512,938,661,481,301,120,605,201,532,105,920,193,755,284,671,528,88,473,735,783,898,82,284,319,748,225,278,999,317,601,297,407,884,159,902,332,466,123,736,692,97,212,718,634,780,445,311,102,403,524,515,690,485,270,916,468,544,746,245,352,288,758,78,85,549,310,252,933,354,461,253,381,37,222,314,383,572,144,601,689,675,167,726,92,776,562,459,591,897,678,667,111,834,924,657,496,732,396,856,347,405,383,470,694,972,647,265,989,338,742,579,801,684,353,441,141,100,89,413,962,733,936,839,701,958,825,608,655", +"84,871,430,411,374,714,101,167,329,454,789,347,629,708,268,96,566,468,971,100,960,342,587,230,13,866,405,634,20,856,572,997,260,341,261,836,906,622,219,948,756,794,937,433,349,88,747,330,841,298,734,588,657,207,416,965,385,689,680,735,534,468,992,87,351,767,946,579,497,426,699,348,838,211,856,690,238,305,9,922,340,370,181,908,992,511,529,542,333,635,983,11,478,534,38,201,642,219,806,689,854,933,531,998,32,288,896,223,132,531,958,289,114,359,383,245,226,263,955,786,5,294,447,58,540,18,117,891,642,23,750,696,490,19,194,899,664,616,207,12,577,319,361,724,961,833,906,326,892,396,642,752,10,577,100,433,642,189,641,941,39,641,459,708,55,750,140,926,227,371,618,964,410,428,832,328,900,209,756,553,804,503,783,946,86,967,813,944,998,710,461,869,776,588,804,467,342,723,139,72,479,225,816,68,343,402,842,798,15,448,581,751,680,597,697,420,161,949,907,538,641,928,946,33,646,924,952,380,776,909,176,991,169,387,400,584,317,235,651,683,238,836,684,858,336,562,925,312,498,437,990,509,598,190,225,710,285,541,240,734,833,130,374,999,27,921,70,127,270,250,215,38,594,618,701,457,556,476,580,974,25,565,26,467,539,470,652,765,956,522,388,0,126,458,901,864,434,400,473,925,650,793,408,122,832,158,38,801,512,359,156,560,97,292,568,876,231,983,674,705,869,763,940,939,997,198,492,369,156,396,7,584,372,234,416,895,689,860,664,6,738,690,758,692,813,589,141,89,157,96,695,817,352,938,112,297,549,32,705,701,570,665,260,280,924,285,739,246,543,464,27,795,202,365,548,119,503,470,705,296,942,333,1,73,700,342,851,348,712,781,408,466,713,805,364,227,927,453,749,246,727,296,396,409,407,356,968,316,875,543,28,632,827,269,756,87,684,737,369,271,977,563,549,521,430,726,107,413,233,735,96,120,340,723,287,567,136,659,654,16,745,656,992,896,344,509,719,480,124,136,317,21,221,211,549,341,19,362,977,316,515,626,981,110,164,794,772,218,915,943,186,419,974,326,335,737,925,191,152,762,646,186,746,46,38,888,821,385,949,761,873,7,332,723,944,46,58,590,755,910,827,337,895,545,937,288,768,506,417,33,908,849,682,158,947,755,506,985,919,751,181,579,831,613,74,93,738,334,339,734,615,502,664,718,330,464,866,888,197,452,796,729,486,55,359,567,378,603,649,281,665,734,411,904,85,366,604,838,395,559,380,652,603,290,169,52,484,213,576,173,271,128,339,429,795,64,358,272,29,900,727,56,623,439,141,184,30,493,17,51,744,709,100,79,924,989,34,170,199,443,165,778,45,345,766,349,869,258,677,168,440,620,75,440,867,309,487,896,958,131,336,638,26,408,380,344,938,319,149,781,101,738,613,676,232,84,499,418,609,207,641,778,394,873,82,185,338,228,98,98,586,124,791,854,381,376,171,822,848,633,593,348,506,181,413,236,650,557,174,564,217,941,707,730,796,973,99,598,592,666,779,920,466,4,497,961,12,205,959,909,766,263,43,171,543,97,697,776,329,892,517,904,915,3,30,582,864,517,326,150,902,294,257,594,891,253,500,799,501,562,464,401,685,634,822,80,114,555,667,391,162,810,98,109,289,99,479,608,486,549,746,927,723,372,836,416,822,780,643,524,111,990,21,815,737,814,732,479,342,747,292,393,842,373,84,843,707,114,36,732,769,823,609,574,986,961,226,255,291,545,563,823,510,934,193,651,292,343,712,867,715,79,228,993,138,913,618,769,758,749,304,195,819,540,578,32,737,62,637,929,191,60,385,814,284,41,871,648,184,823,398,166,366,392,498,501,721,53,853,362,402,151,98,940,735,746,93,13,651,318,174,607,925,586,275,775,587,533,212,804,327,944,797,15,958,309,325,760,886,233,349,684,885,123,682,864,800,184,650,845,894,385,219,591,44,597,917,444,547,338,609,515,175,541,378,49,765,83,218,734,463,844,160,953,429,237,71,109,976,875,198,773,707,845,753,374,53,368,994,101,496,402,338,621,665,687,258,235,996,350,175,91,95,78,462,349,844,185,660,968,744,914,243,594,231,863,832,838,146,250,748,578,739,949,708,755,18,688,804,617,257,142,924,121,287,331,418,864,185,30,69,276,119,227,727,477,979,682,662,657,431,390,525,71,59,348,405,935,298,639,356,84,432,556,662,431,230,54,764,128,187,67,938,634,692,16,934,524,567,829", +"984,305,564,974,89,536,87,624,630,202,270,542,299,119,816,964,163,206,438,318,467,223,722,927,704,439,275,646,808,495,86,110,975,209,356,877,956,655,317,315,586,796,726,526,220,506,49,38,134,236,530,494,148,178,2,854,406,563,463,782,291,588,660,139,127,34,801,830,872,711,253,676,367,156,464,926,630,310,421,140,424,687,685,992,340,783,851,714,673,285,466,895,948,562,170,634,211,970,211,180,506,682,849,235,929,921,83,738,945,350,285,194,120,946,421,140,507,381,796,610,922,163,897,414,50,17,259,799,291,969,938,632,309,615,125,523,355,607,259,105,765,508,980,635,209,565,541,232,639,487,339,296,289,772,191,652,302,216,339,616,930,266,451,798,249,403,927,517,905,849,324,114,258,202,734,989,444,53,131,631,507,789,499,514,201,494,476,344,137,544,687,697,494,611,471,658,892,684,372,946,522,17,743,470,312,815,896,106,92,358,148,942,44,253,981,380,356,326,636,910,536,802,156,878,8,675,83,677,755,863,1,283,598,650,477,191,516,204,178,17,867,857,755,870,353,906,493,2,433,813,311,630,625,322,794,90,697,947,532,763,545,94,76,267,71,341,674,593,924,985,820,643,443,96,248,811,478,839,101,936,500,195,414,700,782,245,738,691,879,319,260,126,0,363,203,79,400,606,810,276,780,201,808,785,598,860,703,193,915,370,420,448,246,259,148,817,97,358,951,163,76,863,905,898,412,36,394,613,128,5,515,713,431,209,291,227,402,633,283,867,526,249,327,385,34,842,885,407,190,45,873,239,887,25,128,331,755,306,629,953,891,454,398,88,112,581,835,446,995,147,591,646,967,231,928,984,801,604,537,579,801,174,913,948,905,975,456,609,47,624,655,682,932,410,922,361,580,717,667,797,62,581,480,255,59,142,500,716,376,265,501,445,696,676,634,835,506,48,70,91,22,525,836,475,195,888,590,950,382,506,265,639,334,795,48,646,327,455,763,271,898,881,920,473,108,702,665,312,211,368,39,563,829,690,975,722,365,61,493,199,337,903,177,824,615,438,132,767,651,464,428,993,769,77,240,504,663,500,503,190,638,331,232,757,338,63,260,650,970,432,275,155,484,361,239,846,295,122,973,771,388,99,140,303,726,931,322,121,6,677,644,902,421,431,797,431,72,173,131,954,308,514,716,314,264,298,917,612,928,730,903,223,637,384,907,579,407,365,941,111,57,636,614,618,261,991,628,747,637,500,716,223,226,320,224,389,399,106,814,180,182,712,749,355,164,356,854,832,580,36,256,935,106,28,174,595,697,23,798,560,371,247,662,612,672,152,437,362,406,471,569,54,920,387,92,607,725,288,604,38,615,61,113,226,500,186,85,835,908,207,666,879,116,455,787,167,73,393,259,814,1,517,716,94,828,986,806,639,972,615,174,107,986,834,624,23,914,588,377,349,587,789,329,587,581,564,64,76,83,804,341,613,910,942,175,845,771,195,495,505,638,809,617,913,738,857,639,274,767,223,430,989,558,55,769,500,431,505,14,608,459,552,14,384,931,714,480,879,779,215,188,385,838,195,960,419,160,47,629,784,950,967,896,799,272,545,658,454,999,455,686,191,296,212,41,183,656,630,738,651,7,250,65,716,953,437,591,688,987,239,643,856,865,748,415,975,804,628,383,182,532,671,67,46,697,377,655,166,252,928,679,171,970,981,748,996,68,100,339,967,621,76,816,271,255,959,223,586,213,860,285,976,534,123,153,390,167,248,161,866,846,519,208,374,86,565,174,214,360,872,36,429,242,857,268,961,573,427,515,473,759,554,629,822,440,276,451,338,243,902,712,796,140,440,914,704,344,857,916,651,328,909,492,920,305,8,797,252,423,722,448,974,842,80,948,271,78,694,796,342,647,693,835,514,338,54,814,557,962,470,434,967,940,579,37,44,80,914,345,118,204,586,727,155,69,735,134,914,287,10,29,382,206,892,275,38,803,13,854,612,451,802,279,82,537,300,846,329,534,518,367,880,127,252,112,485,344,432,694,688,787,129,77,791,975,918,721,291,885,744,988,49,883,235,366,67,261,36,143,846,625,977,884,101,109,304,491,908,613,652,267,777,570,844,101,362,16,201,296,406,724,492,452,43,885,552,573,753,141,58,879,939,461,592,889,403,298,817,356,359,893,855,312,251,600,92,37,805,148,335,270,760,483,511,264,436,509,178,908,110,953,176,919,53,732,406,876,895,45,153,115,688,55,45,409,646,116,301,706,145", +"619,571,128,808,572,203,32,183,646,514,472,180,960,844,118,18,552,222,492,874,744,991,869,74,290,767,264,628,473,955,36,932,809,266,423,501,674,658,609,943,604,964,68,348,517,62,110,826,705,369,398,647,513,973,90,295,464,218,171,370,10,300,158,460,998,591,157,71,701,788,352,431,818,648,272,712,548,327,51,966,299,566,476,277,756,444,710,887,31,749,553,448,767,124,909,556,468,715,124,751,90,506,788,393,46,586,443,976,196,95,434,754,695,235,802,58,713,41,778,571,866,689,120,620,757,68,459,419,590,757,102,825,142,735,623,902,275,410,293,192,118,53,433,485,852,561,430,26,451,208,638,718,521,457,140,676,77,737,276,475,69,197,914,940,607,629,701,477,701,27,993,816,624,112,707,145,88,586,104,773,793,628,249,126,986,743,222,322,66,662,838,605,319,946,335,188,91,491,194,326,502,881,619,105,801,577,263,873,431,495,545,234,835,748,534,408,864,812,971,454,951,278,505,13,675,424,431,467,308,642,140,810,216,766,592,92,370,568,209,981,194,82,111,466,514,355,198,418,473,624,605,276,218,43,194,867,179,398,447,80,162,20,797,893,586,230,141,778,929,683,702,399,204,870,738,790,873,724,769,985,264,659,287,795,941,328,483,534,777,559,904,458,363,0,745,298,359,831,932,93,688,627,508,623,984,923,494,390,255,783,345,130,514,946,524,650,342,887,560,347,30,60,561,675,129,106,303,140,551,721,331,428,241,98,205,533,883,6,684,338,471,477,672,754,472,477,816,684,374,328,164,73,253,141,873,503,238,586,369,573,853,183,552,305,964,323,752,158,68,998,825,365,425,833,464,816,600,70,500,8,818,700,28,999,140,453,491,248,80,82,242,691,312,549,207,896,336,926,438,428,338,193,715,943,603,311,404,786,65,90,764,928,635,751,618,38,108,926,68,885,550,265,687,337,537,152,171,539,964,153,258,371,76,774,495,823,607,82,81,267,169,305,487,388,67,673,700,865,973,381,677,298,476,130,705,756,855,475,781,803,581,548,732,379,859,292,711,762,415,787,270,536,631,44,356,36,990,122,866,519,661,544,235,651,72,594,468,894,593,921,574,876,96,992,111,294,20,748,912,416,178,310,631,195,427,81,688,787,404,372,690,520,640,745,994,256,157,97,902,818,752,107,529,713,774,958,546,35,666,192,424,63,727,863,622,936,244,563,64,123,386,954,489,652,606,664,968,846,666,963,530,154,86,853,243,866,470,100,262,694,18,332,821,950,836,32,928,410,570,562,10,953,868,391,369,202,414,692,772,642,45,869,114,977,49,729,404,276,646,478,105,154,470,485,36,13,350,672,441,577,48,647,754,215,246,93,791,555,154,225,574,52,638,399,800,251,247,122,776,466,993,564,969,927,682,293,589,461,78,752,770,130,945,786,433,975,184,761,500,569,5,599,511,44,798,703,362,925,433,820,981,896,560,547,727,307,610,866,527,773,61,865,983,65,57,800,310,153,133,840,403,398,492,575,99,616,22,48,716,327,767,681,844,751,507,845,789,174,367,931,253,23,188,850,288,373,521,80,953,94,193,718,960,128,253,12,585,378,319,861,947,75,488,181,685,888,688,890,486,806,327,148,846,987,165,802,672,315,696,730,725,385,202,9,118,827,912,183,974,600,255,493,886,569,523,168,895,658,565,42,484,728,105,361,178,187,36,727,865,485,96,533,22,149,444,481,217,13,751,814,497,301,171,965,176,464,309,438,563,234,183,643,935,280,487,269,74,765,900,897,619,783,964,389,5,316,953,647,199,450,434,939,913,298,540,15,859,362,365,843,486,135,899,749,692,401,854,12,148,313,841,665,289,853,113,346,818,980,391,774,877,679,47,194,489,396,414,991,125,139,904,791,300,511,279,268,939,537,57,562,467,250,80,394,162,582,569,181,803,351,608,833,484,135,439,873,176,989,974,449,973,277,982,939,92,41,798,184,587,232,288,14,494,726,945,268,267,266,947,283,893,924,826,78,683,472,91,449,900,146,319,343,361,529,148,578,250,340,120,530,728,695,490,814,837,385,967,450,307,651,539,719,855,84,634,136,842,671,575,307,798,983,92,699,454,163,257,551,247,811,214,724,151,410,192,606,354,486,754,820,785,825,779,770,376,733,389,493,836,915,833,738,578,48,768,444,862,254,706,150,24,937,98,711,368,427,822,190,822,395,785,875,686,81,672,890,517,241,984,515,503,556,946,760,689,931,925,2,150,769", +"453,646,996,349,288,95,404,953,343,458,485,502,54,440,890,315,643,748,387,152,84,389,300,395,732,373,674,631,726,744,631,611,852,911,247,101,721,241,924,39,634,361,723,563,586,626,11,777,564,73,668,42,51,71,990,502,963,588,443,170,942,106,987,716,415,284,658,512,499,71,172,782,104,82,916,999,463,155,269,864,55,483,398,232,962,103,299,451,27,733,34,486,746,537,53,89,46,916,533,795,435,868,705,952,882,252,895,569,388,403,792,670,924,354,588,540,822,702,536,104,725,910,893,238,752,936,624,456,629,330,569,163,235,101,67,171,566,35,71,568,550,707,961,683,73,867,652,639,714,968,620,366,427,426,264,615,924,621,745,641,34,46,725,870,821,323,136,162,113,349,972,214,170,423,496,95,319,400,364,998,721,829,600,653,948,761,628,769,642,781,255,444,57,488,119,263,757,274,117,516,594,721,613,746,55,340,216,105,218,101,252,459,954,290,502,793,157,453,8,748,666,741,537,176,495,761,578,650,206,692,798,628,513,235,678,171,567,181,730,932,599,231,239,829,541,21,83,322,770,904,402,690,326,993,431,112,497,872,56,64,752,950,787,782,853,866,742,15,73,978,724,783,135,370,202,981,382,25,250,725,305,885,521,123,725,401,689,406,58,518,904,901,203,745,0,804,804,632,856,888,882,684,947,361,982,693,585,550,283,824,803,709,2,165,529,71,580,195,347,724,79,316,486,263,35,251,346,498,151,170,709,34,547,805,885,394,171,776,379,93,83,937,296,60,985,308,238,584,240,97,522,55,585,751,955,4,936,81,896,549,563,329,45,319,43,857,332,611,237,853,702,457,704,613,650,224,839,960,379,802,630,188,135,375,956,184,172,947,583,16,290,316,944,345,793,646,407,560,993,6,193,134,515,720,360,220,23,770,104,746,764,830,852,552,726,931,475,295,424,603,434,79,128,153,850,161,671,761,640,892,814,840,383,278,846,403,818,592,116,268,764,191,470,855,683,955,1,897,220,501,121,919,46,513,319,981,185,465,128,317,176,171,934,170,772,241,99,430,476,839,746,731,169,519,450,499,487,12,772,588,416,903,86,276,413,331,355,958,522,441,510,115,899,366,73,447,219,820,350,502,367,922,941,845,268,734,736,856,265,674,132,172,401,743,913,237,53,259,734,411,575,140,870,59,391,902,125,675,782,610,82,307,813,267,394,477,36,808,146,280,973,158,703,127,905,769,500,467,609,232,785,548,291,258,132,228,574,201,797,168,360,666,665,64,218,664,159,250,661,907,780,285,531,960,972,125,568,526,589,297,31,946,982,211,211,388,779,557,802,217,732,400,405,158,270,531,3,818,576,258,508,741,796,553,410,629,701,568,545,822,224,360,745,217,60,109,863,733,702,232,746,478,422,10,589,385,615,773,80,174,454,324,249,949,637,62,414,568,509,559,382,619,695,156,506,998,967,385,503,527,509,669,368,796,218,16,405,548,636,318,328,514,405,934,797,279,614,943,213,581,896,338,716,611,561,52,361,645,524,318,929,717,214,997,793,340,102,593,821,570,741,160,653,316,6,80,408,906,749,325,623,391,133,774,94,954,938,172,90,5,657,676,850,645,982,769,154,43,251,83,53,769,476,213,821,466,349,502,227,991,958,325,996,104,578,504,659,431,257,129,407,441,277,67,827,813,363,748,984,99,87,39,604,532,244,270,410,83,911,743,490,793,452,807,295,199,397,994,217,201,784,129,308,582,627,909,661,240,265,153,362,558,190,193,467,783,450,281,230,283,513,143,324,245,428,864,542,375,723,143,832,261,417,365,570,64,554,490,786,589,750,791,650,699,907,735,642,505,382,526,769,606,103,878,699,799,96,630,733,405,715,974,738,456,187,616,76,480,623,411,764,61,18,419,390,383,613,600,901,338,672,937,153,145,627,207,666,124,165,616,390,288,85,538,451,963,478,41,861,979,605,908,735,440,592,205,379,201,924,470,55,635,554,358,992,190,441,643,18,50,212,181,618,136,767,417,201,483,205,8,574,950,81,954,75,19,285,249,950,979,555,70,24,338,802,925,181,552,895,394,311,574,785,342,975,702,880,16,171,232,511,753,215,720,285,823,527,135,593,626,664,235,187,499,980,554,1,721,594,466,560,984,515,618,102,260,304,574,271,200,893,932,818,102,19,404,97,132,279,571,488,312,918,387,986,369,44,33,769,691,516,951,806,218,977,153,417,187,293,809,691,420,607,617,75,32,851,713,310,725", +"729,477,185,808,456,570,194,552,509,514,373,606,528,306,642,523,513,787,574,667,259,329,70,558,718,513,468,97,177,462,342,464,540,589,643,36,244,419,208,13,613,597,156,88,966,653,703,804,154,367,921,254,794,318,963,97,747,39,413,511,855,519,90,123,108,263,899,815,835,119,522,902,57,918,251,976,706,137,123,727,3,566,257,247,8,400,775,356,959,487,190,134,724,369,666,295,19,298,95,411,148,126,409,836,379,511,150,786,738,671,142,334,797,150,111,789,673,697,948,597,880,919,419,662,410,778,166,566,390,434,304,163,146,128,820,86,375,52,289,912,223,288,957,285,931,678,609,275,583,619,341,856,94,79,949,151,902,360,504,355,36,464,615,534,992,570,566,258,110,361,574,345,123,441,218,370,810,917,290,298,162,316,514,921,631,335,543,953,778,93,546,677,191,18,794,48,934,771,904,75,252,644,156,561,67,5,871,734,999,530,220,614,710,335,55,155,520,579,63,116,268,65,86,627,730,195,65,708,961,276,320,884,245,370,977,148,519,733,329,333,388,914,896,266,113,92,139,887,482,1,391,808,491,783,55,803,579,754,7,619,577,393,841,217,586,47,393,148,73,731,435,534,769,376,575,684,156,218,96,231,632,772,260,411,141,303,581,967,817,92,234,864,79,298,804,0,827,289,551,391,761,550,689,530,148,46,540,811,728,468,478,619,244,596,662,347,416,281,725,548,566,625,47,391,76,982,17,533,275,164,151,144,750,845,851,799,986,874,683,547,677,827,49,182,50,894,962,967,465,575,359,54,494,49,524,736,765,226,499,567,249,180,487,858,882,851,507,722,280,315,61,118,471,961,84,527,265,101,72,347,748,585,77,282,872,270,253,18,815,402,945,283,796,863,362,577,531,674,907,910,438,363,139,79,910,330,29,625,949,909,104,79,128,327,558,629,250,393,803,444,807,749,479,738,505,125,259,207,381,551,757,739,112,103,917,31,202,310,419,22,619,903,992,140,101,996,660,71,993,465,223,139,56,557,9,829,157,312,307,703,183,689,523,686,796,473,983,917,583,198,979,807,614,924,868,225,672,884,979,199,668,400,451,660,330,453,454,946,744,527,146,954,185,102,149,980,792,7,456,541,118,387,80,492,336,904,78,789,981,442,835,554,666,832,939,583,561,977,958,887,858,368,729,964,531,718,871,956,68,451,871,204,829,557,805,402,453,976,371,724,688,410,377,714,309,483,401,242,655,678,629,481,211,893,566,237,780,714,272,126,518,418,737,676,430,514,136,82,282,866,350,95,629,225,656,659,906,879,899,665,213,471,442,87,393,149,370,861,549,425,52,814,480,469,405,982,626,578,424,178,851,417,403,777,895,254,151,653,856,957,930,193,71,705,121,841,702,962,66,260,697,124,820,962,621,60,64,674,800,938,551,172,841,665,870,8,798,464,78,955,513,834,687,601,132,743,43,614,343,265,820,901,189,745,347,199,470,599,275,118,259,231,7,836,243,387,686,577,235,957,838,382,300,147,9,931,975,727,944,687,576,425,772,266,974,895,481,433,958,326,847,848,268,819,375,271,723,198,948,846,233,975,100,361,957,373,498,708,371,965,963,305,941,369,415,27,763,157,604,948,246,143,817,622,660,887,135,338,32,340,435,112,25,96,772,427,860,811,643,769,988,255,67,872,237,586,930,275,217,288,790,838,728,967,560,661,506,879,564,328,366,914,665,589,84,149,764,818,516,704,143,560,18,762,185,634,568,184,538,225,272,32,739,59,719,920,725,877,115,963,94,383,721,68,948,716,994,131,521,849,62,833,348,760,386,198,140,261,811,88,561,802,350,841,683,887,98,65,494,866,221,664,197,722,709,215,585,906,915,228,367,398,543,974,245,458,591,847,118,295,844,555,977,432,292,678,599,421,769,186,482,620,237,440,25,321,987,417,757,524,992,200,667,47,480,203,397,500,6,820,654,25,54,694,936,674,39,684,867,583,876,474,871,996,297,614,344,867,866,567,125,6,825,520,375,907,1000,460,576,804,123,990,569,211,894,594,594,257,661,573,439,919,838,59,685,143,311,909,286,876,864,964,162,291,221,890,539,318,916,597,320,446,874,714,692,946,769,501,452,308,379,535,791,450,84,307,295,209,964,873,994,799,522,19,630,930,856,265,51,313,372,468,278,793,249,298,614,551,178,867,574,6,124,671,965,482,577,301,360,431,720,894,407,561,514,357,348,589,895,264,640,118,503,459,799,333,500,801,682,362", +"744,890,345,688,506,861,555,245,647,958,67,996,520,102,197,954,918,30,573,380,197,957,718,264,496,85,166,774,556,172,905,675,737,670,234,980,510,147,952,602,379,763,794,714,907,887,193,651,849,980,840,629,743,972,84,926,630,477,909,54,140,775,493,926,954,489,731,667,694,830,991,940,279,826,592,4,133,189,23,564,69,968,238,783,53,519,885,513,590,639,458,382,445,650,633,994,13,328,598,8,309,371,677,427,916,737,347,873,772,408,412,109,86,797,231,624,646,89,974,463,712,338,168,560,570,164,671,602,77,596,185,204,752,742,324,64,328,395,289,785,100,888,241,917,529,391,273,567,31,148,747,675,837,514,133,642,651,538,210,663,731,957,102,347,571,432,903,200,474,151,689,856,205,127,995,250,618,23,44,722,779,661,322,388,63,606,802,227,351,985,205,153,169,932,401,60,393,179,471,154,432,616,330,445,72,220,909,553,103,743,236,64,818,24,350,681,555,1,462,401,822,890,901,259,59,957,137,731,947,39,159,576,848,406,568,513,521,730,923,14,177,546,662,496,187,134,194,230,966,184,966,335,176,581,989,630,919,758,782,329,56,983,80,628,366,651,733,49,175,850,539,970,689,50,903,976,626,605,709,569,464,682,111,996,512,988,873,270,325,683,851,434,400,359,804,827,0,172,932,869,948,661,650,639,5,608,391,121,882,832,914,644,684,697,635,657,254,539,295,204,321,952,714,649,929,376,218,759,66,443,660,905,127,994,148,555,891,338,498,101,341,869,592,555,978,716,93,369,545,537,453,566,190,930,969,400,896,108,470,784,501,122,364,840,905,430,557,244,465,761,238,19,450,566,416,682,282,937,303,857,966,153,471,468,341,437,646,179,208,272,735,987,880,21,373,140,764,210,853,813,279,49,798,646,797,331,81,205,753,626,755,246,542,964,240,450,953,839,900,820,994,203,732,597,56,621,585,215,488,586,907,365,289,840,21,547,823,42,932,461,270,56,582,36,429,924,715,693,607,270,970,948,125,664,82,166,881,316,740,534,396,427,499,211,932,478,80,923,658,268,871,366,249,995,679,877,320,485,626,942,807,288,977,978,151,807,962,410,461,981,840,33,423,492,428,261,249,28,402,316,925,371,586,181,332,513,474,684,175,676,579,697,735,122,759,25,785,485,556,98,203,817,24,865,60,626,247,759,800,438,561,396,958,916,393,916,20,160,406,757,316,279,382,96,419,898,840,304,883,599,67,949,991,176,925,449,892,543,468,278,6,392,324,880,154,388,883,177,255,240,435,903,121,100,205,7,203,289,525,731,175,196,173,152,232,870,234,643,586,503,869,673,10,974,329,509,227,457,468,323,885,571,892,53,485,983,804,463,285,738,846,372,218,549,120,386,924,507,580,58,362,885,902,656,740,921,116,398,956,133,808,759,375,891,285,628,44,667,30,722,722,411,136,226,884,523,943,609,472,246,969,525,698,381,245,312,501,129,202,16,475,514,386,403,927,512,761,885,371,251,796,675,73,742,114,196,616,492,741,882,941,860,13,631,95,386,260,3,7,508,195,886,815,657,700,425,849,629,264,948,780,431,695,191,142,960,865,945,925,852,500,138,163,652,962,336,237,897,75,44,374,847,650,435,404,251,162,257,150,500,639,55,334,723,542,585,155,81,95,729,290,767,802,371,673,523,396,101,202,445,239,347,850,972,328,789,856,737,827,657,104,334,580,446,295,541,463,134,580,126,769,912,45,463,798,487,625,70,264,191,343,962,759,102,881,472,57,480,639,839,559,841,235,825,18,884,925,973,630,507,36,613,541,848,537,356,511,562,405,579,876,148,534,944,220,785,663,59,442,896,791,782,682,457,995,38,84,781,82,81,665,820,805,343,901,960,141,217,378,758,446,303,629,184,929,113,590,302,949,379,913,438,727,648,72,446,762,306,704,824,739,629,177,62,338,987,738,684,508,777,548,46,909,379,587,42,232,363,816,684,31,86,872,212,629,917,188,677,831,641,442,528,378,907,475,726,231,523,181,524,574,192,144,486,715,672,750,185,570,45,716,953,669,563,69,359,963,409,42,574,838,640,23,633,700,140,691,387,246,768,237,917,576,930,78,852,227,805,978,908,712,418,569,950,22,390,300,107,114,504,787,216,344,205,708,614,382,243,210,237,207,168,114,310,449,910,647,915,346,340,130,382,32,968,449,723,98,808,414,740,566,861,483,719,71,682,80,387,279,60,291,963,677,485,41,464,600,76,740,719", +"166,624,714,280,667,815,544,760,892,770,4,320,413,914,471,520,666,146,939,796,385,554,141,490,906,303,327,556,349,34,536,117,561,163,150,733,400,441,34,338,21,173,32,465,225,498,537,592,331,391,243,800,850,818,399,775,687,60,940,683,347,277,234,801,693,228,416,637,469,221,278,241,139,822,428,848,651,442,892,120,448,372,48,174,58,410,94,787,505,654,92,123,471,313,19,274,583,920,443,364,695,739,894,62,232,715,181,228,263,810,692,644,579,156,267,918,278,16,500,517,22,387,280,955,820,633,3,664,452,830,31,398,224,570,793,338,444,53,372,700,624,387,766,673,183,365,319,586,874,241,349,145,506,554,804,283,281,921,857,237,970,827,140,684,259,664,972,832,67,620,200,205,518,756,625,95,946,280,666,523,663,334,62,704,934,98,370,516,174,213,201,681,953,891,38,540,600,545,603,178,13,77,37,401,996,282,297,280,135,775,740,190,729,341,76,434,591,437,550,477,364,764,992,188,390,329,846,728,102,42,238,849,839,662,771,379,664,155,730,38,931,684,657,328,463,303,719,544,212,726,870,564,356,224,212,257,729,414,367,779,383,4,182,512,666,86,144,119,167,363,189,730,249,830,733,248,599,925,863,298,993,85,832,818,329,823,737,877,835,267,565,400,606,831,632,289,172,0,687,121,424,12,961,830,90,915,508,479,351,502,463,969,774,426,927,647,170,50,342,809,926,26,836,179,837,375,669,20,442,764,635,110,929,853,863,240,186,417,798,980,839,917,635,257,229,298,152,26,856,211,462,875,712,676,558,960,637,462,393,159,433,61,109,889,3,90,367,148,803,660,321,503,866,325,311,129,194,392,992,691,514,36,386,225,140,672,188,641,227,464,484,503,131,52,884,976,746,740,224,833,8,723,814,897,177,597,361,299,167,936,214,912,410,123,338,86,589,596,201,146,852,284,866,276,125,207,609,465,473,903,709,379,822,110,484,618,659,675,316,355,484,249,684,328,379,152,867,421,422,174,372,380,385,887,835,499,23,475,471,771,310,873,842,281,135,563,672,660,209,906,950,3,826,689,988,464,638,824,981,379,623,28,435,360,136,918,783,860,606,845,943,574,511,963,383,27,772,124,151,23,300,271,74,559,927,264,566,539,655,276,299,711,552,786,806,414,284,787,423,120,884,527,583,207,783,89,441,425,190,596,56,646,177,284,711,110,98,409,816,651,52,712,146,369,58,981,221,412,641,91,839,823,129,388,483,130,303,976,959,20,417,904,18,98,779,589,226,599,234,250,114,863,132,933,324,358,998,261,142,724,755,373,680,844,974,581,419,345,588,735,997,894,866,856,749,278,809,451,736,862,570,865,425,913,668,523,320,195,642,776,979,20,371,542,677,274,203,881,834,33,874,536,857,818,728,359,878,630,480,428,599,404,809,720,309,144,103,725,704,91,401,239,748,964,778,292,217,742,757,919,911,924,166,43,990,184,814,756,353,672,132,686,713,369,118,425,964,581,657,57,535,100,892,400,915,755,503,25,465,627,194,27,122,312,853,868,786,836,196,32,635,415,819,819,694,993,984,955,992,772,613,971,504,370,155,194,900,59,919,10,997,856,389,795,377,95,721,427,195,400,990,301,41,272,166,331,179,222,165,922,917,703,883,224,129,397,839,840,271,817,216,872,412,348,505,13,803,277,99,255,82,969,901,792,513,812,726,845,456,520,657,21,625,807,799,902,20,812,48,720,564,354,444,176,780,534,280,316,759,424,661,934,73,204,583,768,256,832,332,56,871,257,167,241,641,445,747,810,593,185,766,193,677,750,128,834,680,906,766,655,808,228,815,186,834,333,136,187,895,922,522,170,862,406,963,979,32,516,315,386,456,897,166,655,610,143,900,549,97,727,239,272,619,609,516,845,98,206,71,117,108,749,837,612,902,105,203,503,485,768,80,896,331,52,963,165,170,724,560,16,456,386,720,55,212,870,577,197,127,61,481,362,515,90,953,803,749,558,189,813,770,810,359,141,244,110,862,204,6,39,106,894,819,746,201,180,788,510,509,202,922,893,533,811,638,93,866,855,19,678,707,663,746,366,390,619,71,267,254,93,880,894,616,359,816,583,126,900,744,52,18,347,277,749,473,119,525,16,516,708,759,629,846,402,906,287,369,948,164,722,329,574,486,74,87,168,752,331,910,134,917,570,218,36,877,356,106,97,451,317,295,423,197,481,269,437,989,346,635,14,896,10,128,639,495,277,614,841,618,880", +"880,850,848,743,725,978,597,305,134,505,98,414,911,858,557,502,503,664,850,628,671,279,152,650,200,665,900,581,801,12,217,396,573,146,519,606,535,83,150,14,248,105,388,462,519,963,161,521,417,937,365,52,484,539,915,403,460,728,135,771,280,517,737,638,523,619,340,415,775,258,665,913,979,10,299,51,167,459,626,601,912,263,329,387,351,229,236,78,171,591,631,183,474,165,832,864,686,495,149,470,663,578,315,193,115,354,157,953,255,120,432,408,389,673,107,25,268,647,18,104,108,21,582,351,61,384,106,334,656,389,290,325,630,593,523,7,264,846,23,242,37,788,604,970,43,457,227,301,343,110,682,283,385,482,861,241,261,482,877,418,343,761,145,557,789,323,697,975,978,97,762,281,212,38,395,984,51,130,708,267,186,201,214,820,631,664,276,560,672,880,281,359,982,623,66,881,716,307,63,669,653,434,506,9,265,93,660,445,266,184,456,450,378,620,166,580,172,857,512,231,224,243,541,722,147,619,121,306,519,761,464,705,454,576,145,508,442,291,702,301,18,11,144,193,590,600,819,539,485,405,575,448,788,566,880,918,749,761,504,37,470,630,687,663,964,937,262,650,149,767,653,451,881,542,988,732,480,101,991,346,379,565,803,99,101,944,928,556,926,205,750,473,810,932,856,551,932,687,0,838,275,521,323,968,802,624,465,12,665,698,838,123,36,158,188,404,904,944,410,885,859,622,511,857,73,283,358,752,938,113,611,342,377,724,806,539,222,268,908,25,983,241,877,944,320,871,587,214,44,583,67,700,856,115,268,323,807,807,703,210,5,76,417,848,466,242,948,631,591,821,13,286,406,96,525,426,927,694,458,528,6,739,306,618,127,185,365,502,361,697,731,514,432,388,443,102,135,456,822,473,63,4,289,854,585,760,660,494,698,22,465,419,374,410,312,572,17,644,553,863,280,890,882,924,976,299,813,537,857,704,26,754,831,40,820,153,3,639,69,721,755,277,679,373,467,977,998,798,36,342,796,989,365,401,142,796,634,928,20,91,529,526,639,760,738,664,763,75,830,391,635,339,98,324,829,811,376,461,90,199,198,940,651,64,762,986,558,828,596,735,812,619,704,2,59,323,626,558,867,247,832,736,591,856,759,462,288,891,324,588,254,984,513,174,203,210,65,641,335,664,216,406,645,312,991,246,24,251,101,290,694,471,600,660,791,694,648,416,199,31,220,933,475,239,362,498,452,475,707,730,250,333,922,435,653,148,987,560,458,800,120,914,482,106,738,138,97,334,443,115,234,8,704,122,631,686,581,30,292,709,366,727,771,175,155,527,255,178,672,661,302,431,75,914,446,263,917,327,757,95,177,691,904,485,704,823,321,824,243,114,584,784,756,915,520,133,105,738,998,764,757,112,886,680,165,65,910,183,519,299,309,667,462,552,850,666,331,192,105,379,844,935,850,791,534,33,364,574,415,374,405,332,45,978,434,287,704,856,27,822,952,309,994,500,106,220,746,590,955,858,297,934,81,790,548,57,790,56,7,266,207,601,307,461,171,865,690,521,86,773,290,617,2,183,993,152,921,66,750,869,869,945,82,67,921,45,845,151,97,829,695,824,62,130,557,395,592,495,746,991,578,413,365,129,79,496,257,77,501,548,754,747,782,321,483,346,986,252,687,551,632,114,755,599,230,797,223,813,386,14,357,733,189,699,974,546,142,771,747,160,421,697,767,813,667,538,200,370,690,670,568,181,819,916,915,938,188,324,461,427,813,970,371,854,660,944,607,315,560,223,789,720,280,39,669,807,481,446,290,745,406,308,565,222,973,98,232,521,760,425,269,814,494,263,448,703,103,921,935,85,615,355,256,310,411,436,533,379,935,108,612,487,749,162,899,26,292,199,325,232,278,595,268,111,329,864,255,705,248,225,419,154,809,850,751,282,990,473,643,483,116,750,498,918,570,554,63,930,247,465,632,697,819,345,411,663,57,271,60,546,760,982,244,918,802,625,851,190,8,490,739,117,470,45,960,97,575,166,456,570,785,943,22,821,408,960,662,767,384,613,2,359,579,844,114,272,670,397,499,468,969,529,432,154,549,784,153,546,537,776,100,852,157,737,565,91,934,843,781,464,360,30,537,612,169,733,368,109,232,405,35,60,461,105,359,955,511,551,634,441,39,202,670,428,363,824,153,904,344,278,49,846,561,411,188,868,511,58,760,271,874,631,816,161,875,297,740,428,917,179,435,305,480,427,660,168,147,347,198,941", +"800,69,217,824,392,287,886,58,194,709,868,974,314,564,835,992,778,249,923,94,899,596,935,814,850,58,83,204,770,296,474,171,989,714,627,332,668,229,438,919,676,757,63,91,921,44,655,556,3,87,219,531,388,971,272,681,351,664,698,313,316,160,866,652,877,684,802,805,326,47,793,301,590,776,82,404,990,807,555,119,922,632,679,658,518,416,79,442,663,294,366,976,514,152,654,526,567,632,129,8,571,439,815,436,681,388,917,847,24,254,211,450,140,241,558,132,641,214,972,557,424,613,749,874,21,851,35,611,267,173,275,105,2,982,928,882,212,968,371,98,486,505,323,203,211,698,18,221,596,148,72,282,693,494,925,781,862,602,145,382,852,715,263,352,511,6,905,388,397,732,143,368,977,944,986,804,469,841,200,32,162,507,462,887,940,639,598,752,265,207,451,775,355,625,853,823,203,942,109,376,510,290,660,309,271,475,500,598,249,903,656,828,537,246,10,177,907,504,468,402,814,563,204,216,469,965,357,230,796,180,248,417,142,690,888,689,784,714,52,247,93,12,201,633,30,759,323,436,627,830,459,988,17,296,905,749,520,842,930,774,417,555,908,85,49,513,632,458,833,873,346,812,589,6,220,886,958,572,496,757,342,141,405,839,222,855,26,507,864,311,553,925,276,93,888,391,869,121,838,0,109,141,119,717,566,881,564,920,378,444,231,278,924,950,197,908,135,101,482,98,262,961,696,939,962,118,740,257,958,63,203,691,286,579,724,541,133,301,745,275,230,503,975,228,298,180,81,685,560,509,16,87,773,593,345,497,662,865,223,29,650,770,336,335,373,701,677,286,677,417,474,264,361,62,925,394,214,607,768,307,136,246,392,937,847,79,858,726,529,930,102,233,35,202,396,444,858,530,241,384,827,803,314,751,470,352,83,38,917,12,805,201,991,843,328,739,626,886,671,557,796,904,547,783,322,672,74,489,965,584,482,528,114,565,147,176,863,875,168,699,737,538,958,41,902,286,344,928,254,615,442,576,319,478,177,529,692,948,587,926,250,18,734,385,569,921,953,468,727,949,395,5,613,758,55,793,271,174,251,997,17,337,78,672,124,30,614,574,440,644,509,814,61,112,147,280,804,519,107,944,663,499,953,453,63,401,272,753,893,390,318,229,952,455,189,887,536,623,614,133,826,410,69,864,592,636,149,466,111,967,545,943,431,374,722,159,851,986,368,831,896,97,279,651,300,871,780,557,992,665,27,755,975,307,607,789,145,15,293,214,915,212,780,679,201,427,519,461,892,623,727,523,668,812,230,738,137,207,582,993,241,999,128,245,80,946,643,632,739,133,240,525,312,820,284,642,914,79,218,638,493,556,542,100,41,471,739,530,257,151,131,664,237,154,172,447,859,912,869,481,771,39,109,239,159,30,363,591,373,741,146,634,17,577,31,230,624,143,65,21,224,574,933,901,940,952,194,241,730,983,978,693,759,955,715,788,312,630,976,124,163,579,850,756,37,45,440,939,716,742,150,31,657,879,840,306,920,920,549,722,629,537,621,677,749,451,606,629,213,268,960,769,805,211,222,904,940,553,823,921,742,73,365,197,766,198,582,813,594,662,696,132,182,781,195,586,650,86,620,963,856,323,912,150,829,265,851,471,912,418,340,553,251,307,967,183,332,6,485,484,163,609,635,275,863,280,827,789,623,565,727,462,881,284,412,366,310,440,361,991,565,586,415,435,801,242,629,805,794,614,855,499,518,941,466,238,653,262,66,491,110,670,443,431,29,851,386,529,162,841,74,228,101,127,52,242,945,586,184,937,610,329,326,511,355,201,398,455,153,694,379,76,261,701,884,46,135,850,343,265,341,983,495,28,223,446,52,754,987,589,242,465,354,355,413,207,491,365,670,729,438,275,233,920,901,272,829,3,451,13,777,46,386,685,277,20,74,796,933,455,873,588,330,418,556,807,937,400,957,688,436,590,768,877,875,596,349,796,873,856,824,996,752,525,734,331,153,33,107,851,159,587,957,146,625,202,116,229,377,145,519,846,196,490,950,374,315,682,327,766,870,554,870,418,787,783,301,847,611,948,365,97,641,590,932,417,790,485,756,681,290,153,454,109,890,678,483,769,493,767,509,659,853,590,236,101,250,503,838,93,912,614,997,783,962,603,368,391,503,131,409,99,378,18,298,444,444,707,280,363,11,47,890,867,27,514,800,49,755,879,96,205,403,249,62,337,193,144,458,763,755,467,152,717,45,518,817,17,845,521", +"860,155,648,396,37,31,282,657,988,114,871,388,543,738,712,290,486,610,956,2,754,664,716,270,739,885,614,742,712,139,603,176,23,786,800,140,949,352,479,208,642,802,458,435,608,929,223,942,266,155,487,879,49,524,117,128,28,489,759,861,908,480,61,955,640,729,742,90,194,252,102,505,895,651,36,21,568,900,982,73,287,212,610,560,698,559,242,667,319,232,908,658,139,873,168,773,269,66,114,93,266,947,919,827,339,407,998,363,93,783,955,697,350,162,103,904,234,281,424,693,221,926,519,344,498,743,88,82,572,27,260,187,847,889,505,467,617,969,166,292,26,489,337,795,38,858,722,918,918,821,441,563,583,727,967,225,597,930,400,925,500,770,858,521,637,424,627,926,642,419,859,536,632,722,930,952,467,3,457,957,981,533,712,366,408,543,111,904,329,881,180,715,263,498,366,929,793,95,694,748,641,643,212,608,624,837,290,938,97,394,56,683,495,495,774,417,422,57,332,334,968,393,84,951,436,208,419,863,741,241,734,756,41,860,687,401,422,314,612,325,796,479,593,251,129,365,563,347,596,222,949,564,76,496,729,33,874,985,70,556,964,893,138,485,394,244,199,423,474,180,509,328,50,575,815,420,354,148,797,965,450,944,215,482,391,757,604,982,521,610,375,650,780,688,882,761,948,424,275,109,0,34,607,626,447,824,752,509,244,895,107,172,516,83,480,289,5,691,368,628,315,274,397,878,853,300,370,635,341,45,800,87,835,825,328,61,381,139,955,652,861,565,320,909,952,221,64,832,883,429,512,891,194,182,357,325,619,344,994,841,711,985,279,910,81,858,588,634,834,998,234,705,370,391,788,288,526,457,871,978,199,94,921,517,570,894,882,887,427,748,735,287,107,910,959,819,518,278,420,911,99,498,877,704,140,96,861,740,41,960,716,942,954,784,591,93,264,339,375,809,468,649,821,289,254,21,888,558,12,669,477,614,545,158,5,919,847,475,481,896,559,326,38,303,721,22,707,184,809,233,76,181,187,305,34,519,394,583,197,90,677,1000,459,907,990,780,806,546,280,853,973,642,222,336,405,373,302,205,67,538,398,699,138,635,590,705,615,770,850,784,31,354,592,401,513,195,879,590,364,327,320,926,159,269,832,719,564,839,812,116,462,459,582,372,80,297,893,293,63,480,373,935,438,864,849,246,15,7,580,41,250,884,99,56,124,776,745,269,494,196,725,962,41,95,262,725,364,779,951,209,416,817,609,575,736,762,893,367,933,447,531,98,113,877,439,266,625,150,230,534,955,392,959,663,269,511,993,756,181,698,286,749,759,438,641,779,795,251,136,230,227,544,438,263,443,711,590,281,801,258,872,381,982,892,128,929,686,733,505,205,53,646,381,416,809,415,814,997,103,297,816,231,594,597,456,232,512,612,133,980,525,135,857,38,754,348,168,904,62,748,154,134,299,505,809,712,762,115,497,397,26,478,885,998,876,891,685,982,874,104,524,601,338,865,139,289,64,325,121,337,761,194,94,756,785,910,386,585,614,77,704,746,12,181,416,687,112,225,841,980,26,618,828,391,942,929,768,214,414,28,649,871,738,242,570,586,880,98,405,406,651,581,393,55,481,295,679,692,736,440,681,960,21,653,266,439,795,946,850,691,522,819,362,928,12,526,913,954,80,446,707,221,512,601,145,111,343,854,946,466,722,976,461,488,961,649,539,822,543,947,223,757,585,515,249,137,646,615,628,59,206,816,736,23,783,430,981,293,402,890,845,675,972,452,136,871,377,133,565,161,484,334,305,976,906,866,646,295,53,54,683,818,957,569,988,681,483,177,160,315,20,725,565,285,487,816,464,161,387,670,416,225,540,539,156,594,518,216,454,306,41,534,874,989,726,521,748,400,318,299,729,136,414,180,175,27,687,55,34,854,107,539,142,719,274,910,907,461,316,963,181,658,530,541,168,543,586,44,37,880,764,669,220,918,574,669,984,486,844,901,959,369,892,844,430,524,276,211,188,649,401,919,427,296,22,127,513,406,811,936,703,196,684,965,425,885,771,451,532,580,795,470,140,426,108,716,617,844,423,37,547,880,811,369,905,802,461,944,773,9,541,435,434,151,492,65,949,313,198,496,615,793,493,202,907,126,84,168,9,837,884,442,152,156,789,99,508,109,505,923,970,234,9,168,731,231,63,799,930,734,601,405,796,483,401,802,810,579,873,761,663,675,862,39,949,38,871,379,486,993,649,862,335,573,907,299,846,831,481,595", +"869,897,244,664,641,875,890,230,370,212,926,625,205,819,386,659,59,727,814,968,251,741,634,745,759,796,861,479,611,189,597,320,506,541,612,457,24,645,711,52,40,42,300,135,531,638,437,75,592,677,594,869,141,708,762,518,675,501,82,67,826,118,193,129,63,697,278,852,995,812,582,615,935,126,720,277,465,944,145,771,442,640,551,330,511,732,954,373,306,204,703,59,737,684,355,894,994,255,739,318,867,828,68,220,795,377,983,469,555,767,817,384,552,134,54,308,145,542,513,577,412,297,880,579,766,937,89,450,682,482,345,905,46,647,879,434,550,744,885,84,584,459,933,43,145,930,301,573,450,836,313,966,850,274,745,991,343,59,313,634,996,694,271,319,907,687,769,861,507,162,552,643,171,7,128,83,727,332,214,499,642,344,719,567,467,561,857,543,225,427,737,73,429,132,421,919,298,632,317,283,530,944,661,764,237,687,459,948,922,732,474,709,354,383,279,721,100,409,784,543,370,74,402,263,32,425,663,237,739,793,47,721,673,361,761,785,712,22,808,282,34,672,235,284,227,734,852,888,902,703,260,540,999,574,849,284,759,920,340,381,308,701,334,289,950,341,583,230,591,401,835,346,798,215,122,4,760,477,664,625,476,725,757,560,342,273,120,855,677,593,776,793,201,627,684,550,661,12,521,141,34,0,783,970,63,986,729,841,909,289,701,254,764,458,471,340,678,448,100,210,107,578,648,442,402,757,702,557,37,853,321,480,997,377,184,728,955,846,940,841,638,569,696,462,274,710,877,25,484,418,903,994,413,950,12,285,839,656,228,844,339,302,862,675,471,942,557,707,462,332,297,590,914,131,385,518,998,526,462,783,160,213,186,33,440,301,581,422,506,448,989,841,104,422,416,601,934,446,781,512,253,247,819,386,322,497,113,713,852,897,173,423,482,432,557,725,139,900,628,642,119,307,706,739,806,927,565,579,449,845,945,611,8,88,827,484,113,907,665,471,619,970,751,959,198,647,224,939,506,224,810,348,436,410,664,612,276,216,871,535,552,583,281,650,111,82,816,268,778,143,884,823,336,103,241,282,858,113,310,267,408,901,800,231,427,177,617,5,79,549,852,385,964,727,358,148,519,339,946,312,272,713,416,298,951,258,58,60,291,181,918,161,871,64,760,647,501,292,37,147,719,46,453,714,798,80,308,761,724,291,800,167,516,400,265,206,278,716,421,438,16,859,496,98,469,658,940,226,368,58,183,777,53,675,613,996,184,846,217,521,951,519,583,876,365,368,746,329,129,618,871,696,92,874,32,660,512,813,949,117,532,65,501,75,42,379,899,726,825,564,665,993,164,393,998,933,165,562,271,412,205,393,927,336,220,122,45,338,270,425,250,389,209,310,270,474,428,359,765,661,832,258,2,177,156,753,422,492,556,600,273,669,907,180,791,89,21,658,14,778,514,239,397,12,634,851,814,274,270,926,227,93,358,318,969,220,789,243,194,935,675,782,248,849,327,363,995,734,187,444,581,243,948,430,88,845,136,701,664,389,42,837,867,160,701,841,329,396,363,127,994,234,226,789,952,411,504,905,757,461,252,620,424,716,263,589,460,298,800,603,896,925,585,520,56,959,212,68,705,950,230,857,878,7,849,50,765,422,448,261,37,970,497,247,426,367,18,393,655,37,378,192,754,104,493,522,598,349,954,868,764,345,490,100,262,508,463,438,853,650,915,436,174,820,919,454,168,670,96,801,500,30,107,553,306,295,441,464,371,536,790,514,216,302,379,969,981,904,468,78,217,679,775,632,52,619,452,517,242,416,726,62,132,909,523,683,742,358,504,793,75,924,816,173,805,642,885,242,243,275,911,13,566,552,677,119,266,109,956,56,312,749,231,928,303,967,390,993,225,325,955,473,417,543,790,725,574,339,630,765,369,972,656,684,236,213,221,729,860,61,384,964,967,24,366,435,772,724,237,802,918,195,958,572,644,568,945,414,579,170,451,181,61,100,299,774,131,892,521,995,854,914,221,882,330,30,190,337,95,330,8,888,794,202,193,820,214,92,11,331,420,42,925,203,587,904,509,429,123,254,365,487,509,382,132,584,483,825,253,822,594,635,537,448,349,436,766,130,567,745,729,427,124,54,392,598,832,272,311,667,313,689,990,103,377,808,932,967,677,875,657,802,248,979,842,452,759,344,165,569,235,351,471,468,456,3,130,896,863,311,735,123,326,683,845,769,911,845,206,600,494,247,519,690,288,727,215,62,280,754", +"805,498,67,467,545,428,215,43,770,20,70,396,128,886,144,91,46,197,562,870,59,502,270,453,294,209,534,448,274,92,371,52,676,674,998,484,499,83,698,311,275,773,228,565,25,867,928,137,920,719,767,797,81,201,979,522,690,532,96,1,125,945,847,143,383,97,606,569,866,119,520,661,78,511,862,628,700,84,420,549,676,306,519,748,912,910,472,333,764,379,703,573,215,27,154,15,117,19,246,64,81,887,485,486,833,701,617,503,488,999,758,445,298,316,9,211,518,712,84,387,591,412,382,121,773,263,277,583,262,394,906,432,116,278,566,815,691,921,750,848,273,212,270,144,306,905,757,809,749,176,236,765,60,412,435,804,194,791,866,483,754,988,190,188,516,720,622,702,789,95,456,416,864,98,328,415,370,768,263,961,289,690,464,226,986,725,218,479,987,751,708,685,588,547,467,579,416,91,437,185,610,769,970,744,856,488,344,353,121,510,797,219,75,893,722,26,569,602,577,241,124,905,273,704,349,894,277,984,743,836,72,836,76,406,72,545,330,999,32,170,522,243,564,831,819,16,68,189,997,904,564,811,129,231,273,416,696,141,520,72,310,124,127,74,105,498,155,367,291,456,332,407,246,774,163,274,517,920,464,448,655,973,457,170,353,394,128,342,565,259,48,408,808,508,947,689,650,961,323,119,607,783,0,770,997,410,187,398,749,258,461,552,402,134,413,833,52,467,884,264,528,392,863,120,6,379,783,987,494,915,679,862,616,487,708,23,353,804,71,234,311,154,280,654,314,679,626,655,862,495,154,433,325,429,805,239,829,344,498,666,669,830,515,333,579,547,918,932,584,647,548,866,965,319,788,37,681,452,724,474,69,369,635,892,419,754,361,965,261,971,542,873,48,742,929,671,128,313,804,922,691,492,504,269,209,992,531,494,306,4,873,54,114,117,766,99,663,350,433,773,580,859,514,287,976,918,261,842,786,851,20,306,119,366,809,789,259,172,790,602,797,553,857,56,854,504,694,556,907,596,548,102,450,992,383,995,443,308,356,972,230,696,47,206,223,649,754,513,492,540,296,436,121,773,548,319,984,549,485,63,164,366,947,425,694,493,741,871,615,35,827,131,618,223,672,109,902,646,433,467,627,733,928,511,367,310,674,205,790,906,370,347,334,439,67,718,50,688,481,373,343,675,705,453,86,939,375,258,432,385,924,484,23,393,185,343,563,433,56,735,797,981,630,85,147,928,247,857,870,2,733,107,791,68,879,296,887,380,88,822,19,798,706,647,967,348,93,591,972,160,761,843,934,585,810,472,248,615,269,602,905,249,744,342,264,584,949,753,308,584,395,557,100,885,791,696,41,768,295,924,574,317,281,717,336,991,602,102,271,797,551,469,16,315,125,93,481,535,999,911,79,669,155,216,313,478,416,634,301,370,663,223,495,408,546,597,84,661,430,338,616,630,677,586,50,590,555,267,63,112,786,505,73,505,352,118,775,531,491,912,751,336,567,402,738,857,750,178,730,21,490,781,494,441,204,349,681,333,805,296,184,343,75,293,236,276,17,340,517,681,287,865,969,467,836,718,920,898,427,542,679,853,601,709,855,319,665,882,787,301,666,309,908,443,904,576,853,38,52,144,525,516,332,383,908,954,587,312,305,580,740,229,421,198,833,628,593,378,288,333,956,947,436,89,848,451,790,685,477,47,200,978,809,2,296,609,508,542,608,330,472,712,357,912,218,828,26,619,428,544,359,977,863,773,519,72,323,656,53,990,511,307,811,685,248,605,877,131,941,385,39,733,985,103,515,460,520,760,672,325,887,96,280,819,904,940,393,229,487,525,629,891,622,155,38,270,410,706,459,830,361,449,28,238,499,609,452,281,715,797,573,739,42,249,405,489,136,45,955,312,335,506,682,990,328,660,995,22,472,51,535,242,833,281,558,927,499,940,890,974,143,634,281,97,214,117,180,809,831,762,556,584,750,505,161,63,354,111,57,767,725,499,786,556,234,106,735,872,906,246,374,546,64,664,725,774,829,668,786,962,937,947,721,78,431,951,249,36,572,734,323,841,608,683,355,559,854,472,54,952,766,262,202,62,427,858,853,395,148,542,713,401,202,399,3,215,241,777,236,275,284,116,273,540,314,631,669,579,94,903,990,412,489,658,881,117,302,69,648,546,202,412,683,296,333,879,94,506,340,164,815,535,927,943,27,210,529,438,878,741,462,484,279,189,673,865,170,985,183,210,152,169,181,464,607,177,381,921,671,565", +"873,813,94,751,137,246,973,759,145,463,757,256,227,318,198,113,714,610,254,940,63,924,568,584,16,188,166,944,353,336,777,40,237,607,124,998,274,919,22,653,392,968,720,232,482,301,978,93,340,276,398,687,513,465,304,844,755,560,884,81,374,363,916,542,354,324,241,440,840,904,676,57,972,396,540,527,463,292,141,180,454,305,506,951,696,685,354,480,9,639,200,509,125,984,952,615,932,708,224,443,388,802,6,548,604,271,983,782,904,202,898,572,687,743,642,398,819,194,687,691,59,116,670,26,386,356,97,312,48,684,368,713,718,147,28,901,880,618,144,149,246,149,73,144,999,732,362,316,458,249,478,409,175,648,988,3,289,652,142,172,531,999,331,417,818,600,820,818,139,352,53,366,603,468,543,960,108,232,771,20,445,405,376,690,565,751,442,61,540,141,935,679,69,196,613,684,280,965,614,460,87,152,902,962,822,508,858,174,647,11,556,292,237,26,602,365,645,416,387,775,151,509,973,258,361,50,80,516,653,628,805,149,525,282,521,885,685,527,684,675,29,877,509,183,695,672,579,517,624,507,667,280,895,440,344,164,578,542,974,532,351,970,361,987,29,277,806,62,174,32,167,309,420,853,881,808,331,210,776,874,974,216,29,329,453,777,326,921,456,837,960,122,785,623,361,530,639,830,968,717,626,970,770,0,472,499,391,991,89,178,705,133,736,771,588,730,269,969,543,90,212,495,738,101,853,13,251,466,233,112,171,318,86,194,573,126,206,192,424,735,85,925,374,889,510,737,593,827,880,145,764,357,971,700,155,816,110,73,948,836,925,735,811,739,309,548,404,237,293,549,842,759,326,929,764,504,659,248,59,874,751,714,182,395,544,386,979,808,466,729,160,118,812,624,296,882,980,983,875,641,879,881,652,835,551,437,561,487,37,502,292,915,696,482,996,411,342,450,234,24,952,913,171,231,904,851,455,974,947,457,703,41,131,347,805,401,567,856,54,755,662,447,105,573,195,103,791,251,670,553,128,836,314,236,641,111,716,160,882,460,941,861,910,888,236,706,675,937,924,18,816,550,572,592,355,16,765,429,764,845,465,777,675,327,914,736,573,347,540,31,20,588,84,20,284,219,326,535,637,405,398,954,560,734,658,943,994,415,197,498,498,884,958,952,718,580,56,812,966,583,839,401,337,468,482,86,598,625,856,259,569,746,576,320,140,729,731,726,169,390,633,889,555,801,673,48,316,54,169,261,688,119,617,214,579,301,797,438,321,725,724,806,538,314,225,157,214,420,620,567,869,209,965,209,146,620,839,260,99,367,371,697,291,197,219,657,971,386,551,737,129,691,273,825,51,792,460,611,98,955,514,617,122,325,104,259,436,540,716,723,963,503,295,924,254,144,208,558,535,426,302,599,96,747,109,125,812,495,180,570,27,563,410,248,885,507,450,285,242,97,473,649,23,385,808,274,926,436,108,853,357,391,81,998,85,998,260,688,496,312,495,945,432,552,729,404,227,208,76,237,318,356,89,375,334,882,326,243,786,950,494,884,343,384,431,200,259,683,666,857,662,941,667,980,24,805,904,564,507,850,54,982,36,313,286,247,31,269,795,88,158,912,592,355,486,715,569,550,479,944,448,427,592,796,365,982,882,555,173,482,791,536,196,799,853,19,119,540,289,315,745,460,963,268,365,9,42,731,644,270,551,152,179,830,956,29,758,575,57,83,237,719,188,931,223,708,86,583,582,541,484,288,377,516,938,263,567,943,598,49,638,913,41,352,431,279,963,450,267,372,416,323,777,280,625,746,185,782,966,910,582,616,838,363,18,713,167,978,714,47,243,521,488,441,577,266,209,458,719,854,522,165,244,36,137,423,414,607,430,467,721,61,744,879,544,559,205,727,694,644,340,136,420,459,189,817,962,697,106,975,687,818,140,316,529,553,495,502,991,682,980,926,994,187,215,3,317,54,564,296,801,98,201,826,564,555,546,287,383,844,650,939,27,756,636,926,639,174,12,865,963,767,353,552,196,130,627,633,431,151,506,833,673,754,139,847,885,383,313,55,677,922,908,534,115,69,641,685,111,752,959,865,479,323,445,752,390,329,855,290,327,447,693,397,867,438,763,123,428,396,793,5,134,130,951,894,224,306,855,939,47,913,804,909,899,316,498,759,844,217,652,42,518,531,79,93,13,256,161,463,466,208,35,456,932,340,171,141,248,248,249,66,91,53,664,418,523,182,600,405,791,996,707,802,58,592,149,950,164,605", +"296,295,26,156,495,888,211,770,941,105,489,863,287,218,266,885,636,501,902,270,676,115,477,911,357,54,528,514,560,531,399,854,246,478,505,182,325,474,383,622,110,619,566,769,557,268,494,416,124,513,157,759,998,312,63,48,328,321,447,293,308,249,813,327,71,696,428,114,369,484,707,5,350,58,462,965,376,725,539,74,316,279,593,130,85,463,248,944,84,427,925,963,507,367,130,33,205,890,305,235,801,80,981,534,641,214,755,646,846,982,344,489,782,662,356,856,100,149,107,686,857,516,618,413,514,228,505,497,839,363,983,488,779,473,850,335,573,429,433,53,79,664,251,748,859,130,544,928,390,397,698,768,512,481,286,349,351,29,904,327,35,802,901,444,112,992,49,97,533,792,168,692,66,716,106,683,55,290,750,239,227,943,758,81,726,832,605,153,751,458,883,887,964,773,704,699,196,604,177,286,372,448,87,600,868,584,643,582,548,530,28,920,833,929,426,155,739,465,235,840,997,760,850,911,277,2,209,820,791,262,594,431,246,880,209,940,120,128,214,215,93,100,507,554,409,982,791,174,649,798,513,426,162,79,643,443,264,351,712,576,778,208,592,393,139,417,927,38,40,529,654,271,734,515,838,469,239,786,32,75,965,570,293,359,82,522,569,405,680,679,363,832,598,984,982,148,5,90,802,566,447,63,997,472,0,102,701,399,901,415,722,597,740,115,783,644,820,907,246,244,837,509,976,656,813,826,166,886,960,961,186,114,914,474,809,930,811,824,165,909,152,368,626,614,240,765,666,232,698,998,802,207,916,203,284,393,213,96,592,751,634,159,884,656,644,493,962,519,402,728,220,500,437,602,775,488,96,175,860,482,730,804,959,114,753,888,798,618,2,503,262,778,370,526,707,577,766,83,593,401,503,349,706,721,245,596,3,647,158,800,733,802,917,361,260,30,126,223,13,112,811,873,556,35,310,823,229,368,849,767,228,696,784,633,781,220,503,399,15,32,40,429,90,969,31,998,746,150,5,884,803,918,398,139,658,303,850,427,311,114,801,759,108,963,143,238,502,415,610,15,361,549,782,214,666,872,518,718,197,658,400,353,486,764,118,439,859,448,652,697,106,388,693,36,357,912,821,336,805,767,474,134,891,504,57,385,212,629,925,186,600,277,9,792,563,399,932,548,442,569,114,708,204,526,15,98,919,136,294,578,180,22,94,892,920,895,191,444,122,373,70,181,143,3,439,683,254,40,226,525,856,109,350,195,463,84,835,816,606,299,889,235,260,651,477,113,157,569,930,922,681,793,776,795,93,340,310,853,200,149,263,402,564,779,321,9,690,433,966,222,988,635,294,993,871,696,289,644,574,677,523,672,857,148,109,797,995,71,622,905,927,386,41,982,549,543,205,6,519,965,337,376,968,397,565,621,321,355,163,370,965,929,204,173,131,56,609,116,933,669,97,482,706,797,233,781,594,642,858,417,18,636,120,735,75,94,401,37,808,892,227,732,492,450,477,589,589,718,385,84,509,937,939,894,645,216,936,364,398,582,729,623,85,811,374,944,789,139,144,919,147,262,360,290,96,450,209,967,748,695,792,905,118,319,388,42,359,678,823,505,918,712,572,856,603,783,724,485,228,486,886,452,539,654,710,311,342,215,679,200,121,35,490,672,94,486,36,998,103,818,19,268,525,468,443,253,754,83,114,67,665,764,504,699,940,275,677,379,349,73,859,475,568,968,948,32,676,425,155,735,271,264,970,945,288,586,440,180,603,923,535,876,739,100,265,663,92,846,96,461,255,653,402,434,407,491,715,917,241,849,662,379,530,71,592,860,965,497,244,962,228,337,909,132,798,914,277,239,691,348,335,117,168,262,477,115,101,646,242,90,766,733,440,338,769,94,549,492,426,823,895,841,891,491,608,817,874,214,856,73,198,917,926,388,401,39,215,882,276,585,699,851,448,325,781,304,637,112,17,599,216,540,428,533,358,48,207,249,161,396,289,433,345,892,644,830,303,432,590,347,808,280,509,204,859,860,251,524,70,545,626,434,519,632,824,642,256,706,671,293,410,711,774,810,665,884,261,832,494,802,166,326,107,545,361,208,592,472,630,449,979,754,782,309,619,218,308,987,271,416,262,327,301,702,91,104,423,105,583,853,242,368,345,485,240,543,586,392,140,982,234,711,425,879,322,790,450,142,652,142,125,859,694,167,610,591,671,133,494,379,677,272,627,201,903,735,736,816,382,523,495,118,523,23,194,940,471,151,958,371", +"706,719,492,576,653,903,751,252,910,113,240,479,795,173,452,624,214,682,773,36,153,378,411,973,37,839,914,288,550,951,997,144,23,411,640,716,573,696,202,71,270,796,979,320,465,150,199,651,989,495,384,347,567,865,19,914,90,206,638,507,116,989,145,336,772,715,846,466,95,331,698,19,85,942,798,842,302,686,540,680,28,540,165,486,411,710,163,848,647,135,814,362,923,695,233,173,124,856,406,650,131,733,22,205,291,379,571,763,402,867,310,690,319,132,993,193,428,760,518,395,792,481,347,697,32,668,286,719,288,875,784,793,656,47,764,459,229,27,53,946,370,963,374,131,668,996,214,421,198,429,347,927,865,111,67,581,172,35,209,506,521,23,209,35,26,657,269,330,546,434,258,427,382,643,979,917,511,688,197,39,617,846,825,270,622,720,126,172,318,993,25,132,12,787,135,66,822,149,722,524,597,243,680,541,861,337,375,69,277,352,895,557,473,439,32,883,924,260,258,235,133,556,8,41,475,438,57,281,32,390,708,795,851,48,683,262,415,300,665,282,122,525,556,44,794,133,714,691,402,643,264,319,149,381,465,862,540,388,164,640,756,175,859,307,259,967,466,151,850,237,277,478,943,179,419,721,735,572,432,326,87,753,231,510,824,985,41,462,245,874,329,158,860,923,693,46,608,915,624,881,824,986,410,499,102,0,738,375,923,236,179,81,93,615,259,183,938,69,101,558,759,559,936,728,18,327,660,683,21,315,349,483,321,229,248,213,265,126,895,638,967,962,326,216,594,663,575,302,416,947,883,653,526,768,551,343,896,859,919,642,574,355,131,52,886,278,280,516,741,446,407,107,83,589,845,635,796,173,248,292,747,609,289,217,498,743,536,986,401,219,510,463,192,134,96,130,911,447,726,41,342,63,396,78,874,60,145,255,265,483,114,576,764,140,837,682,62,466,613,538,403,865,786,439,237,948,674,27,55,817,655,54,252,946,8,945,183,829,245,567,440,583,475,695,676,655,963,964,631,92,385,156,571,8,632,541,712,744,394,251,834,714,663,758,803,754,985,297,118,478,165,781,738,596,250,300,448,58,824,478,135,92,44,85,269,539,192,457,159,428,891,790,252,389,11,278,703,253,32,948,915,13,998,162,327,695,536,468,907,542,923,612,742,705,294,211,672,523,252,295,9,313,418,273,891,862,141,8,463,835,518,404,472,963,573,10,764,627,921,993,486,796,411,336,610,946,832,690,750,68,43,229,632,634,17,886,646,461,64,981,260,131,347,591,824,904,913,370,120,255,278,935,260,546,727,602,544,510,623,942,569,462,350,442,162,875,853,930,771,106,349,369,958,851,844,622,658,411,180,690,395,256,436,428,925,29,612,175,391,432,881,614,88,700,210,459,560,309,641,591,45,522,145,570,306,280,476,767,536,263,491,976,803,166,269,815,174,882,8,858,458,146,188,994,300,531,244,979,976,17,657,65,457,825,150,652,500,698,94,849,238,743,662,244,623,917,457,750,734,289,528,855,238,58,459,731,732,790,952,444,101,626,715,965,48,522,342,219,248,140,509,528,417,68,185,976,795,662,439,810,350,257,407,748,712,481,87,452,304,335,938,413,819,359,752,440,710,67,574,237,746,771,531,267,468,111,870,679,210,527,36,715,868,867,404,664,173,547,647,767,633,113,638,307,380,321,544,908,847,232,625,102,470,43,334,994,710,821,674,521,774,43,402,64,974,192,421,192,630,639,490,567,756,978,326,87,486,742,421,907,35,155,760,846,23,891,617,798,596,390,746,485,815,83,602,777,151,687,20,707,896,294,339,710,699,197,565,352,889,322,219,190,228,851,744,973,811,959,229,113,854,311,377,802,235,882,717,369,296,48,579,823,165,393,68,159,17,931,535,570,11,289,127,846,604,138,940,65,632,391,740,382,247,958,923,8,412,423,716,381,570,791,139,776,508,951,554,353,497,382,351,243,461,796,320,554,428,511,789,267,573,921,415,954,733,34,558,545,997,905,224,181,130,838,470,822,27,778,344,949,674,204,192,953,495,780,837,278,450,630,779,469,816,30,41,167,116,237,962,917,355,718,721,236,950,540,563,766,645,672,716,778,463,566,780,483,105,765,197,169,635,183,683,521,87,153,105,866,202,802,528,928,208,990,378,395,266,829,940,592,148,896,257,634,329,375,295,336,616,701,26,182,639,123,258,310,658,834,385,96,494,770,894,934,766,97,718,550,125,42,827,636,306,211,716,566,119,557,983,403", +"901,696,982,183,317,710,527,321,526,674,180,711,386,317,915,310,122,327,280,594,761,745,114,510,544,363,528,385,98,485,70,792,62,889,974,479,112,668,523,392,266,485,770,913,97,723,340,277,707,732,344,113,269,230,618,204,994,523,773,515,899,539,697,196,772,386,110,878,189,169,995,305,561,993,390,509,50,299,727,367,680,235,141,434,174,871,212,640,760,23,81,292,787,233,742,755,400,967,194,545,32,754,394,517,18,580,340,493,490,937,864,719,306,696,566,986,96,976,358,722,885,947,933,723,728,900,480,602,920,835,629,611,547,54,656,292,677,489,671,820,758,361,67,246,933,904,421,832,255,30,969,863,59,630,670,35,110,697,65,884,139,372,646,572,899,435,432,628,76,96,677,679,762,262,621,729,556,679,115,942,634,18,46,894,633,87,40,180,94,46,735,331,399,165,668,869,513,86,356,314,742,744,690,547,243,319,139,58,381,737,591,597,685,524,131,898,725,448,462,846,669,965,136,347,649,508,927,480,343,16,447,489,602,747,606,943,599,866,961,280,503,794,630,150,389,176,996,930,903,51,700,548,986,125,394,994,239,657,386,647,85,561,721,540,156,489,175,797,402,817,748,252,141,344,158,291,803,75,141,116,511,922,504,602,242,584,356,595,775,828,242,38,703,494,585,540,391,508,465,564,752,729,187,391,701,738,0,119,368,631,553,26,999,552,551,986,381,40,308,70,374,648,508,770,11,800,43,28,741,690,97,294,76,298,683,27,540,737,200,154,671,305,943,511,678,176,552,40,246,339,673,879,822,339,487,161,41,117,648,841,606,135,105,191,747,424,374,728,535,672,718,178,250,308,219,778,832,696,123,260,473,317,595,469,837,645,474,683,445,755,123,817,983,421,332,99,279,708,486,698,441,114,607,748,412,653,283,269,198,104,320,668,726,204,187,811,619,964,267,248,335,138,665,707,888,399,506,272,489,900,562,69,469,892,793,218,943,799,414,106,976,66,903,204,809,6,799,948,14,322,939,740,724,206,23,658,529,866,955,173,120,989,168,379,718,513,343,970,998,631,214,61,198,838,366,851,971,13,931,572,324,758,605,146,936,270,205,15,276,211,241,542,171,895,520,430,949,465,246,391,695,170,222,207,938,913,729,389,431,559,703,618,883,641,341,365,947,773,474,841,997,894,114,875,413,863,202,641,52,31,105,714,38,217,344,356,623,12,270,778,141,937,372,53,106,533,634,272,832,326,628,676,569,665,801,61,424,409,683,186,94,211,605,23,490,666,726,858,119,978,828,973,124,474,680,63,338,887,218,480,247,391,643,538,402,598,577,699,280,65,247,264,107,373,523,183,766,849,394,395,150,517,823,548,264,96,781,435,334,656,977,890,65,334,408,790,502,228,329,950,20,789,154,496,310,471,688,303,177,358,120,882,568,432,796,519,672,329,522,173,281,656,870,236,854,70,108,859,449,917,499,51,622,855,299,476,790,975,506,894,903,585,73,247,6,261,688,345,672,845,278,364,794,958,531,495,354,233,412,879,267,589,95,214,144,784,302,909,916,987,948,670,778,370,30,589,989,246,614,242,101,156,769,144,288,415,670,295,21,918,551,42,235,337,192,858,262,749,471,789,297,606,479,519,275,770,11,886,727,130,332,402,714,690,780,919,699,387,256,214,811,591,186,245,890,979,41,940,501,868,602,84,762,532,533,69,816,13,842,344,245,734,651,12,732,949,220,502,348,230,513,588,628,262,416,729,353,477,400,684,911,128,703,862,984,861,469,70,250,112,400,504,595,226,988,441,157,545,95,307,551,876,951,490,684,83,503,528,752,513,727,315,362,882,119,330,20,256,596,596,714,516,426,142,496,867,750,761,590,539,194,371,808,70,840,67,483,790,325,516,603,652,293,930,469,759,597,857,496,808,889,251,828,304,345,613,806,723,128,651,643,119,846,474,712,685,580,597,592,988,76,780,330,343,194,101,86,275,942,217,638,255,286,484,482,91,392,52,390,698,485,800,103,369,532,618,239,115,547,851,34,415,105,844,368,146,850,138,754,527,166,305,573,185,442,460,323,38,726,747,702,367,394,909,315,112,266,352,287,138,46,756,949,203,413,310,59,751,706,665,662,171,50,39,151,250,708,750,968,384,907,698,464,1,423,566,4,65,690,151,775,474,161,917,664,743,235,626,194,241,275,567,112,151,469,689,504,990,439,803,66,634,589,555,122,659,327,279,232,359,639,838,395,682,636,527,230,476,73,459", +"155,381,336,930,90,205,769,126,70,566,719,522,817,512,822,512,674,862,489,595,224,98,314,612,56,554,334,399,240,362,813,410,104,774,360,279,511,278,946,939,415,291,351,80,680,928,31,53,840,614,338,144,485,646,833,127,87,773,337,683,527,997,458,464,607,271,584,897,709,650,47,406,272,481,156,344,454,791,64,3,824,287,631,692,645,519,815,471,33,251,500,164,250,562,834,13,57,575,2,168,577,20,963,288,715,703,758,313,13,589,137,177,838,822,556,317,338,14,796,550,858,220,275,676,4,55,181,462,536,326,318,173,929,945,778,507,652,545,12,60,376,713,877,351,631,571,212,223,774,834,770,673,791,869,614,455,906,771,949,38,890,357,856,460,158,695,80,617,507,689,28,199,111,567,843,63,584,388,272,925,106,779,783,732,737,104,249,426,258,420,62,176,150,535,39,645,131,634,31,181,373,292,482,780,838,96,370,620,565,404,12,271,779,486,108,733,961,315,488,750,379,950,506,814,456,882,827,608,128,89,644,348,510,164,616,107,338,76,746,584,573,353,297,66,137,954,485,840,6,654,523,621,337,892,125,734,447,284,462,124,7,925,267,171,691,860,877,903,11,331,512,448,2,391,172,546,412,463,315,412,457,487,135,861,948,14,858,746,96,972,52,801,193,390,550,811,121,479,12,920,509,841,398,991,399,375,119,0,141,781,492,839,969,794,339,867,539,664,225,562,517,166,138,469,874,42,851,286,351,272,517,152,891,403,484,770,508,297,101,286,719,33,773,113,672,712,101,819,32,338,797,445,563,496,294,873,648,115,190,628,871,659,635,340,631,324,225,828,935,889,325,472,979,15,209,817,750,220,62,304,696,33,497,664,404,105,699,683,783,18,926,282,420,434,943,45,609,518,92,531,81,338,522,768,276,959,181,877,830,96,804,87,74,990,100,844,480,147,18,438,431,528,380,533,284,296,120,916,629,378,595,745,839,297,483,886,887,150,214,30,571,973,57,34,312,305,192,246,772,550,231,13,703,244,466,125,183,88,577,338,973,45,103,181,726,908,435,309,72,502,513,851,863,38,964,776,131,18,495,985,837,326,580,223,553,203,669,993,377,849,382,800,833,595,235,908,437,13,671,114,533,96,411,983,697,54,238,187,479,824,76,9,101,902,920,346,425,239,30,160,215,704,160,825,686,190,398,676,503,708,378,852,532,59,811,856,302,549,589,575,586,426,762,79,120,724,276,997,302,886,918,494,470,891,196,508,396,241,695,637,652,684,469,632,692,341,67,866,283,666,70,381,295,936,24,217,919,627,925,607,120,128,67,431,230,581,195,698,93,123,315,270,281,328,749,358,823,330,272,392,272,821,316,932,417,700,747,642,955,672,346,457,363,541,607,916,351,260,464,472,129,573,48,737,352,876,893,854,154,876,189,653,610,867,991,995,158,897,453,480,851,491,590,990,302,443,501,284,125,866,624,201,829,342,284,988,123,774,813,458,787,434,430,489,73,350,645,297,910,296,552,736,771,992,712,760,583,758,463,841,258,484,485,278,642,41,172,324,956,428,283,840,617,286,851,426,69,566,671,291,350,966,463,39,976,817,435,76,617,469,775,584,851,164,92,269,344,367,628,917,186,831,700,279,753,506,51,119,299,540,45,380,422,545,376,81,186,52,88,705,615,296,866,789,895,253,677,784,9,989,122,231,996,145,290,905,827,676,592,409,977,900,244,508,529,306,521,394,70,957,641,817,179,946,549,575,11,841,830,336,625,501,905,372,593,240,227,743,296,891,22,534,888,637,408,736,211,156,492,206,642,662,123,494,382,501,772,670,907,401,452,268,141,643,623,749,799,211,71,145,918,420,220,253,513,507,917,45,307,924,197,636,623,511,127,894,548,501,919,180,419,764,951,162,961,959,254,623,721,554,535,185,543,66,950,678,831,485,628,617,303,947,534,268,889,806,151,591,705,728,414,153,691,448,584,169,716,871,501,70,870,351,295,718,804,998,700,38,14,104,709,15,711,762,307,882,640,92,70,775,388,336,113,364,663,259,981,582,597,244,753,378,220,64,646,959,50,868,985,202,950,861,764,381,305,70,602,481,442,150,314,393,699,369,608,252,183,430,403,994,642,38,558,73,35,207,231,924,743,669,109,808,752,513,184,182,298,886,723,683,223,223,456,938,830,955,244,206,214,15,706,198,934,487,306,894,566,480,44,75,688,62,611,847,425,24,973,858,621,956,660,512,989,742,192,333,832,401,654,394", +"111,341,300,471,734,946,887,333,937,6,210,356,471,504,348,751,647,285,392,685,530,827,20,270,88,585,515,787,177,436,869,122,774,414,675,719,733,882,900,593,270,259,696,196,64,922,45,340,288,960,546,352,710,31,670,98,526,541,618,133,913,132,924,432,120,251,269,912,848,260,283,445,512,815,676,853,591,595,869,204,988,787,49,849,374,888,930,632,392,719,873,581,681,185,248,639,684,28,172,311,442,590,835,598,40,676,982,533,129,941,880,417,880,99,934,288,810,604,477,620,629,78,342,676,67,757,338,480,284,113,937,336,956,871,419,730,71,951,11,284,159,340,511,606,476,751,373,871,105,865,220,621,229,681,86,518,992,36,340,976,978,278,822,506,173,957,496,462,899,542,884,521,532,991,464,284,542,573,280,14,409,105,675,130,107,150,399,338,870,936,888,229,688,734,662,411,846,252,480,904,66,440,955,391,225,877,953,140,181,805,379,330,468,366,771,613,302,694,532,876,138,196,912,272,599,137,665,407,215,916,959,818,542,982,380,804,781,644,414,966,90,151,189,178,222,77,300,710,28,891,252,863,379,531,951,139,252,503,262,23,700,908,21,105,300,379,953,24,727,426,265,35,219,891,32,869,556,2,44,849,31,479,24,388,425,556,476,767,820,58,854,512,915,255,283,728,882,351,665,378,244,909,749,89,901,923,368,141,0,390,426,727,617,300,854,470,2,212,939,415,752,436,104,922,247,582,785,229,418,724,985,942,441,433,232,461,763,165,534,813,632,536,791,510,478,944,179,656,102,117,520,875,248,355,439,772,830,96,630,258,459,784,803,164,935,148,624,669,234,77,621,958,159,110,941,167,963,961,911,484,605,484,901,924,703,458,806,16,616,263,788,739,353,964,939,555,140,300,450,487,534,154,536,280,929,476,761,205,798,513,849,674,402,384,897,754,795,556,965,952,161,945,120,460,374,364,612,318,268,949,957,506,82,60,889,650,558,92,403,235,556,777,97,346,23,414,687,697,27,872,89,420,267,92,113,473,824,134,833,746,927,653,971,368,439,471,965,792,227,914,82,299,56,589,265,221,296,684,778,438,15,23,42,149,552,681,689,947,15,522,30,738,470,993,795,194,869,464,87,41,869,671,779,898,135,277,375,979,410,42,155,970,756,707,656,667,919,776,755,877,336,309,568,575,574,644,894,659,227,775,576,448,78,121,920,247,374,868,843,329,844,706,263,53,494,425,731,938,281,631,291,623,776,330,311,47,123,648,385,654,132,180,353,856,824,972,6,814,682,547,862,308,997,388,518,427,866,127,936,18,477,818,795,233,951,461,359,564,755,889,599,153,388,544,282,374,861,405,147,66,799,646,20,800,50,507,758,717,854,612,226,236,158,34,749,506,196,75,391,232,550,291,867,393,159,292,276,131,521,711,336,334,14,856,33,500,201,748,198,252,499,446,250,231,689,952,903,773,590,71,467,268,937,584,472,641,618,991,931,273,312,471,953,874,859,501,125,447,716,244,519,377,433,881,729,211,61,83,971,376,622,126,841,714,156,498,266,931,934,423,180,30,214,671,993,902,14,805,215,651,672,499,436,386,150,107,510,456,923,51,177,731,466,330,744,282,586,223,831,420,37,253,426,202,449,376,434,773,814,806,698,891,857,646,233,203,854,372,431,224,107,306,634,988,505,239,155,720,944,670,602,961,81,663,243,231,668,753,758,905,406,855,953,155,508,202,276,680,120,241,993,142,142,614,779,201,607,792,857,682,720,262,293,244,424,82,460,952,695,161,54,702,87,370,143,773,754,223,511,306,815,100,467,267,77,25,882,459,266,919,230,236,841,259,323,964,978,876,622,824,400,483,337,859,475,591,482,273,179,126,812,596,390,49,939,76,365,500,126,612,643,425,950,971,743,301,602,921,154,836,160,881,558,85,903,693,820,873,743,202,4,637,270,711,275,165,720,126,67,763,719,45,55,473,650,957,639,592,391,961,266,333,937,808,887,558,574,821,162,880,800,900,345,377,190,353,928,137,264,290,416,688,308,939,89,198,134,975,845,611,938,207,507,864,317,362,241,41,746,239,33,250,737,121,465,707,158,725,58,891,50,786,935,540,386,763,669,406,598,695,933,959,72,969,315,154,224,562,431,455,876,49,169,136,965,966,79,352,775,142,744,441,514,725,446,891,898,2,938,180,388,86,616,440,597,124,854,188,419,689,510,42,893,491,675,861,227,468,962,327,874,141,586,648,354,274,282,590,40,33", +"286,877,246,667,473,117,873,939,608,540,32,627,779,111,437,453,684,694,547,321,997,996,261,278,44,238,753,179,362,356,680,247,893,81,998,751,10,662,583,889,204,26,292,642,837,333,592,217,104,988,89,842,695,693,438,994,926,787,978,148,524,264,968,952,398,17,921,932,449,45,537,10,580,98,700,222,462,897,104,815,437,215,311,42,733,260,396,228,359,185,549,39,177,307,85,288,175,829,652,983,960,790,896,466,86,685,110,746,785,592,19,559,167,839,789,581,659,75,111,130,318,619,840,169,3,881,469,714,107,855,976,380,902,710,899,900,309,828,964,301,662,516,718,520,672,897,876,860,182,54,18,58,724,17,986,606,202,171,500,379,575,510,601,931,787,585,246,131,707,392,716,348,609,810,276,586,482,382,818,481,651,307,334,589,91,52,153,634,726,382,239,973,55,777,815,991,482,221,390,546,911,774,588,156,776,45,30,153,646,153,361,838,59,716,539,11,800,798,697,40,723,354,154,255,53,404,447,453,502,173,688,598,458,500,600,725,153,440,8,775,236,666,504,441,897,392,25,713,862,325,394,131,569,17,343,150,946,968,672,784,511,621,185,967,266,867,450,342,452,814,575,525,626,795,673,317,237,251,38,221,800,146,781,359,98,42,813,903,218,932,535,359,370,783,824,468,832,502,698,444,895,289,258,178,415,236,631,781,390,0,510,942,943,423,831,497,685,990,639,286,372,378,181,176,608,949,452,234,668,613,988,226,213,474,843,93,1000,333,862,174,392,674,783,539,896,961,110,9,908,959,714,128,531,844,214,589,948,320,755,246,811,836,938,633,95,187,808,570,832,393,527,310,908,747,718,142,406,813,283,877,7,331,644,362,110,69,727,611,906,161,471,973,361,252,329,163,23,365,594,724,389,525,448,539,144,926,518,159,581,449,451,71,220,915,544,950,510,809,404,250,279,281,849,931,705,575,923,746,178,879,72,441,240,28,276,10,155,670,102,936,880,530,17,977,875,675,716,228,518,990,744,92,875,852,930,541,125,407,486,459,478,939,15,407,40,797,426,555,29,699,924,239,295,601,236,255,896,494,711,955,578,355,189,58,372,612,662,3,866,664,421,373,490,517,149,689,708,321,943,356,253,235,745,335,39,214,297,323,590,474,18,747,206,758,335,678,233,388,373,102,690,826,840,801,438,817,803,701,405,602,582,498,629,572,31,665,110,716,560,897,938,355,19,342,500,824,418,789,625,473,430,564,121,214,99,875,785,436,687,663,722,843,689,906,428,827,753,848,325,252,942,576,342,299,871,528,306,947,835,623,862,230,136,172,718,541,935,499,37,956,31,327,812,430,778,372,418,845,176,32,800,45,998,27,294,326,847,357,859,621,794,922,832,188,754,594,654,51,272,413,834,31,67,110,541,854,964,998,115,69,712,976,287,630,712,710,93,535,307,952,3,54,171,17,381,319,613,340,473,952,703,926,820,345,832,482,399,191,883,487,15,788,932,227,559,609,51,812,942,756,740,850,633,695,505,388,606,147,537,769,246,803,134,749,250,914,612,723,569,394,446,132,668,180,833,512,947,413,438,449,354,372,672,3,379,144,357,953,859,625,163,81,637,918,587,819,377,221,356,237,139,765,240,870,403,363,616,463,975,183,183,244,624,856,542,253,709,639,420,487,321,975,149,878,79,260,592,938,334,291,80,942,831,845,66,668,792,239,97,511,742,919,358,719,135,621,404,464,966,400,260,316,316,395,819,594,223,902,546,712,604,522,817,856,79,135,134,929,109,864,291,645,603,742,493,135,242,925,530,214,800,148,465,926,268,622,296,160,302,221,191,597,629,796,120,210,166,437,765,865,983,704,902,67,257,777,593,148,703,164,19,168,733,410,72,244,762,41,126,355,226,493,734,255,944,981,500,762,955,102,134,231,16,677,434,826,171,896,13,330,861,464,85,54,43,581,926,609,250,348,941,358,647,820,812,836,987,84,425,768,617,423,220,923,808,454,799,404,16,813,793,903,564,852,269,276,129,708,99,857,776,647,555,914,952,560,723,171,292,323,170,204,292,941,524,529,943,371,60,575,729,640,617,260,503,181,888,868,777,15,458,996,23,498,137,44,407,305,285,576,791,358,443,184,644,746,508,438,669,391,724,908,579,635,430,284,76,202,904,515,617,782,819,880,248,458,945,774,607,545,46,64,58,662,344,879,407,97,907,332,594,600,838,699,248,932,217,658,113,412,130,211,273,392,132,715,398,59,998,763", +"958,30,275,564,599,457,704,937,253,134,484,729,151,840,343,873,625,497,349,732,694,101,561,646,165,769,812,611,209,513,408,91,180,225,396,548,496,475,17,826,496,106,589,796,758,41,92,862,737,185,683,711,538,581,373,660,138,970,964,497,25,515,331,556,765,29,470,636,462,91,481,627,777,458,949,57,659,709,681,210,568,727,508,498,97,158,347,48,942,840,935,207,108,540,888,437,778,361,393,113,606,177,738,522,664,534,414,740,386,143,84,349,906,477,562,122,61,581,98,726,488,226,544,940,743,419,738,767,757,840,449,542,420,518,378,955,693,726,295,138,248,459,182,200,470,790,181,620,458,143,509,910,151,992,545,626,689,264,59,57,766,576,123,318,801,513,659,247,906,653,157,503,535,739,938,427,568,465,504,129,150,298,494,482,783,750,80,460,394,785,238,894,412,362,248,99,435,491,217,911,440,545,918,503,957,659,924,456,843,404,5,432,880,895,125,838,617,961,654,336,865,939,574,678,805,35,152,165,950,1000,294,175,915,154,235,639,469,693,367,235,674,799,200,273,434,41,429,186,174,114,495,682,866,338,892,971,244,436,930,552,524,898,557,601,352,169,589,368,694,161,546,898,68,614,431,185,391,755,418,584,904,241,12,771,791,732,651,553,224,261,110,156,420,345,803,478,914,463,838,231,107,701,461,705,722,179,553,492,426,510,0,453,351,569,885,519,963,699,557,835,349,46,943,649,390,379,897,926,380,271,30,753,445,823,111,130,880,668,720,830,843,267,775,933,564,583,30,96,291,463,311,750,698,334,907,218,216,292,447,564,688,116,750,965,385,153,817,383,557,132,363,985,684,982,637,302,462,597,876,434,32,991,316,506,271,465,712,356,197,477,166,310,918,465,162,153,32,937,406,8,339,865,530,389,462,583,572,811,804,594,309,696,620,768,433,11,899,343,998,803,150,477,827,429,892,986,155,279,941,712,569,595,77,216,496,650,436,436,408,62,337,580,621,693,927,320,534,165,215,988,697,607,610,328,64,744,540,574,701,364,536,688,359,201,252,172,787,499,284,601,64,128,918,283,478,677,345,223,740,846,975,113,821,91,755,929,581,418,387,504,963,315,815,152,534,849,877,98,279,432,200,496,387,143,655,835,957,522,84,776,892,724,307,661,704,545,511,650,344,914,254,577,590,89,408,282,238,643,24,945,543,904,668,898,262,777,542,665,12,665,82,506,768,119,668,242,283,854,618,148,488,884,105,13,842,950,100,437,231,586,786,524,417,276,864,737,913,989,468,944,30,253,823,988,614,56,792,264,806,677,559,812,261,990,687,920,551,189,265,856,206,541,635,86,144,553,327,306,719,636,503,701,561,631,327,445,839,508,454,842,880,949,529,918,867,82,723,18,937,891,745,600,147,457,675,926,906,393,131,126,98,766,312,174,736,166,276,994,430,607,985,805,228,51,702,98,630,312,905,393,78,719,344,874,732,90,208,32,175,55,324,820,586,954,419,787,54,916,202,73,127,66,924,862,517,493,158,196,680,127,883,947,870,724,418,145,215,732,663,969,671,264,399,245,394,664,861,598,249,351,37,40,423,74,931,432,451,263,595,323,869,35,876,588,957,490,146,612,950,440,852,795,831,851,683,831,476,370,254,110,25,170,709,44,881,639,660,259,834,359,818,487,188,440,338,157,882,601,331,805,136,530,185,844,287,629,254,572,753,818,391,404,768,735,959,991,985,712,949,348,551,960,934,606,539,199,175,495,240,238,31,755,222,156,734,71,671,572,758,169,203,59,72,627,335,74,561,176,366,716,122,318,900,138,756,815,925,925,86,447,747,503,161,551,802,525,148,532,461,309,741,90,323,497,232,133,910,349,653,179,702,599,831,120,283,367,643,732,468,866,791,164,259,810,968,730,368,357,542,48,660,345,604,376,711,149,767,895,378,107,90,562,678,21,284,626,147,105,688,618,726,548,289,455,967,722,776,667,387,449,678,538,771,988,459,672,70,64,893,672,123,951,29,888,475,521,787,316,654,735,350,910,289,210,987,597,555,952,256,732,222,122,316,244,288,208,366,901,416,462,266,584,573,548,126,161,341,344,853,946,265,597,135,730,723,101,922,396,782,551,639,541,337,161,520,572,318,562,467,132,432,424,556,501,676,172,843,558,322,902,358,62,821,153,484,783,27,701,746,881,88,426,436,52,355,201,244,619,45,987,421,766,766,887,943,510,423,935,40,125,114,413,572,393,922,350,315,566,362,856", +"119,213,61,731,566,713,803,281,730,164,403,668,867,105,172,930,398,177,574,387,957,984,903,26,120,424,684,258,682,420,454,289,808,473,516,869,403,123,492,197,995,53,104,247,33,687,899,466,945,3,42,150,491,551,333,434,291,271,502,599,965,605,872,129,82,186,125,416,320,391,568,405,872,183,925,532,507,397,56,736,863,891,879,667,539,958,59,348,790,691,792,791,556,938,488,617,288,173,464,762,521,484,36,894,180,632,672,338,75,896,501,708,25,408,540,866,423,200,790,415,706,56,425,549,103,422,145,135,582,692,649,147,852,867,261,175,727,568,529,579,261,234,742,174,419,86,375,297,729,523,992,355,163,233,730,288,19,176,678,237,436,224,998,931,486,94,449,576,447,774,716,243,741,339,632,517,139,118,522,914,87,408,983,931,236,609,382,42,988,392,662,110,511,290,541,236,813,892,440,595,383,105,444,721,187,647,818,824,906,845,166,808,584,723,817,205,448,285,145,133,92,727,639,770,33,264,760,601,960,786,968,280,847,760,586,643,332,426,118,178,760,402,881,120,442,921,573,194,544,242,329,880,64,983,872,591,4,87,491,776,407,796,823,579,959,778,853,669,555,795,784,403,742,881,742,788,768,347,824,442,883,785,84,297,73,340,145,306,772,779,875,560,448,130,709,619,644,969,123,278,172,254,552,133,597,81,26,839,727,942,453,0,20,954,247,461,592,249,274,172,48,727,302,779,164,991,886,847,488,510,398,945,581,712,136,700,127,533,983,884,408,739,231,102,677,911,557,906,321,701,332,968,78,675,598,354,569,911,994,403,846,871,187,42,806,895,843,678,329,759,23,30,347,38,675,769,183,434,420,198,773,842,245,88,286,825,193,602,477,371,180,795,206,78,664,377,23,965,192,713,710,178,717,673,433,713,772,509,112,701,352,300,551,976,868,768,364,52,813,116,231,155,776,19,92,414,713,89,406,11,391,413,955,331,625,883,230,15,431,663,953,648,8,141,471,971,864,515,13,482,914,666,364,714,750,149,526,392,281,657,52,344,343,108,938,567,694,451,344,992,873,81,80,496,407,407,740,361,236,14,454,64,562,860,704,511,148,231,592,703,996,899,100,621,427,760,892,304,834,416,809,462,50,774,32,563,576,525,641,464,250,516,477,796,477,581,184,852,767,657,515,745,871,786,918,631,91,990,760,395,374,637,427,659,587,586,897,673,406,299,497,497,666,938,168,364,668,958,230,557,101,277,282,482,833,905,881,674,59,2,233,742,694,452,388,376,613,111,2,544,886,256,539,827,951,489,470,216,553,652,190,396,84,712,973,323,103,37,922,754,378,867,570,804,864,959,81,421,391,161,132,520,263,408,805,86,723,706,371,250,192,237,939,951,810,187,453,463,119,637,494,945,425,382,940,635,907,231,829,892,344,214,523,588,939,36,966,745,275,694,691,171,612,410,839,958,410,821,969,501,93,610,252,790,486,871,336,498,492,714,172,654,276,169,346,87,594,541,50,560,594,973,27,421,519,27,817,582,544,511,122,142,953,483,735,353,658,635,165,4,830,819,593,796,395,716,632,195,898,151,892,717,833,543,102,442,861,852,140,282,878,266,82,522,148,236,564,458,514,331,995,500,297,504,917,792,648,83,380,409,948,621,293,766,912,548,533,646,150,347,847,836,110,599,567,769,363,240,391,626,44,728,151,675,867,538,792,624,270,153,102,738,826,332,43,732,690,375,762,322,605,59,42,41,477,170,122,468,339,374,233,39,962,956,125,813,919,976,842,74,465,501,487,884,692,367,87,717,550,698,968,862,176,353,921,537,957,442,800,445,86,42,353,14,837,771,66,1,538,875,467,530,571,850,733,316,96,65,867,266,415,338,117,397,213,640,626,397,671,613,671,177,3,313,155,331,50,192,602,485,958,551,950,357,926,327,438,392,512,54,97,103,748,941,867,764,616,762,842,721,76,552,432,989,115,264,493,549,894,457,39,584,89,778,859,377,852,388,954,231,678,624,580,974,994,117,471,5,462,34,805,266,576,441,766,428,171,450,90,764,386,296,627,292,202,851,514,388,636,990,996,686,2,421,760,343,740,907,563,510,431,835,641,771,697,113,493,393,26,374,354,700,997,20,529,813,458,834,842,783,905,131,395,136,882,956,14,988,255,101,390,550,322,592,201,642,692,880,721,893,871,275,385,903,676,37,504,792,724,146,307,997,905,536,168,681,961,349,838,15,536,485,210,319,250,770,626,446,979,793", +"652,227,888,900,508,368,864,864,227,106,29,458,632,424,388,748,34,359,739,601,661,715,27,391,204,271,275,481,305,285,58,824,96,947,118,911,661,326,511,89,427,289,136,176,396,161,330,497,843,105,419,807,205,52,956,844,477,770,947,688,164,741,174,199,590,249,203,568,316,308,487,845,283,925,480,135,283,704,2,229,78,508,165,976,29,889,120,480,42,686,134,741,606,945,615,459,264,410,64,335,723,64,247,522,791,39,306,321,798,37,664,540,76,58,336,919,711,268,72,469,426,693,687,907,268,789,356,596,115,2,605,33,337,568,335,957,947,208,116,347,17,852,829,877,211,760,992,285,747,368,515,323,991,763,268,740,478,986,762,387,642,72,107,471,675,14,450,457,638,292,350,936,602,773,906,606,371,445,113,139,193,710,409,431,166,122,667,151,572,594,713,897,431,273,523,327,212,343,682,640,434,406,863,15,844,157,4,95,475,341,361,131,369,162,484,580,636,594,117,921,559,118,430,851,937,473,341,295,325,5,204,709,692,85,220,801,868,744,539,676,475,328,442,452,257,273,505,759,188,285,976,516,670,423,849,457,269,76,774,344,338,635,969,28,507,116,508,318,232,293,568,368,370,134,20,278,296,938,875,510,673,522,401,131,425,627,210,499,101,297,92,97,246,514,2,244,684,774,36,924,516,764,402,736,740,93,999,969,617,943,351,20,0,543,863,474,565,995,723,895,128,736,985,430,396,89,58,574,858,134,497,309,400,214,814,309,751,103,441,361,23,692,502,252,148,631,851,106,969,400,888,275,753,106,165,437,304,141,874,979,45,664,137,999,73,528,866,802,82,424,225,152,256,193,404,805,828,876,475,418,187,978,766,859,78,133,394,726,838,800,19,103,729,538,523,574,538,286,72,12,190,569,506,68,974,189,182,320,527,395,151,680,50,374,233,419,298,610,8,989,31,574,670,770,237,233,492,926,61,21,467,943,923,602,996,525,904,912,7,899,916,920,658,75,587,151,286,317,488,727,950,81,144,990,788,464,913,740,25,716,551,943,886,868,839,89,567,603,253,4,71,293,845,245,261,938,620,809,204,491,878,874,460,500,761,283,106,632,999,212,414,306,308,777,437,393,200,719,618,369,724,247,126,36,210,325,404,897,309,690,22,836,849,149,901,266,355,819,540,121,862,279,777,619,303,619,853,630,867,499,565,806,803,329,211,659,547,505,898,437,445,635,66,764,400,647,574,910,665,426,73,742,957,102,23,808,830,955,732,678,144,797,523,988,543,920,282,401,652,123,747,981,896,117,643,242,857,173,274,167,392,142,89,556,596,993,302,573,347,582,682,895,273,517,449,183,10,856,458,159,678,598,597,347,606,732,947,395,685,446,296,4,88,35,639,10,654,726,805,893,908,430,325,125,259,400,620,570,316,267,260,511,228,674,527,213,816,366,645,157,57,182,385,246,384,664,562,151,16,631,6,244,138,461,45,740,955,963,4,755,863,979,160,390,256,479,395,631,888,984,812,927,494,354,540,565,197,244,959,409,119,704,80,552,24,537,809,736,545,690,110,305,244,125,526,643,384,305,810,917,920,275,543,916,251,817,479,239,68,823,776,980,445,834,182,392,395,318,192,798,207,966,43,256,609,936,63,142,287,284,264,793,861,382,925,185,530,587,956,644,177,195,537,324,940,391,590,425,996,385,502,620,449,695,811,22,32,152,535,861,211,377,707,736,307,89,647,541,625,230,463,603,78,844,337,414,743,546,565,332,810,310,95,822,674,666,235,364,594,353,135,827,427,26,895,150,124,281,17,823,708,716,507,82,89,54,869,292,300,979,53,379,844,996,823,421,508,148,707,682,797,117,568,758,44,668,675,609,940,749,319,248,462,509,815,20,121,78,733,456,816,853,783,273,878,264,909,539,689,650,164,925,468,973,571,236,866,103,497,295,493,131,414,204,145,578,940,298,750,245,266,954,345,407,349,799,342,787,259,89,703,218,169,654,555,187,338,1,969,160,612,954,742,656,636,355,559,988,802,330,895,826,278,557,150,994,427,775,500,883,326,481,521,715,484,297,607,560,598,736,929,166,444,208,562,653,435,862,807,620,782,792,816,178,266,968,118,451,360,913,823,753,809,741,214,207,728,263,404,456,38,126,456,488,343,935,14,479,793,506,902,516,873,775,806,307,392,289,581,987,498,887,111,695,846,616,192,135,29,540,312,460,444,28,173,518,553,850,107,310,257,724,266,896,319,206,913,489,690,356", +"2,394,197,938,383,959,296,383,983,200,679,74,514,424,94,432,74,192,42,750,446,456,65,83,315,195,526,368,461,890,481,921,395,316,918,886,223,151,500,746,357,585,10,21,551,336,962,470,605,677,100,959,325,865,3,58,280,530,143,950,702,578,330,137,170,642,849,702,314,832,576,306,699,925,786,835,367,608,126,623,226,995,616,764,994,686,121,585,640,693,336,308,218,32,305,642,985,114,437,388,958,643,387,731,361,630,219,57,285,520,735,19,533,868,91,315,96,586,138,371,29,555,958,416,132,408,438,23,661,844,110,417,793,519,396,255,249,777,253,302,228,112,188,617,191,476,549,652,661,26,688,246,685,752,881,156,702,555,949,310,193,421,413,806,807,70,904,460,12,527,708,572,635,980,266,303,729,786,359,262,961,790,498,661,632,474,749,240,510,129,586,171,574,102,541,251,640,453,114,853,147,205,315,607,572,254,947,756,709,357,495,152,413,608,355,828,964,486,68,440,589,616,794,396,314,126,926,748,61,898,950,353,418,780,492,130,133,34,213,478,486,8,456,879,160,819,506,707,498,189,489,261,75,382,653,43,760,651,604,505,614,42,669,22,132,894,111,933,875,631,840,693,596,752,978,239,343,31,127,994,713,130,262,804,350,258,653,574,59,18,363,292,259,946,165,596,697,426,158,950,83,458,134,771,115,615,552,794,300,423,569,954,543,0,580,493,677,539,299,221,438,80,976,361,764,518,842,335,915,248,631,832,956,479,335,436,705,578,459,830,211,937,759,689,487,910,526,240,370,164,738,136,908,140,181,481,28,272,420,309,158,131,808,652,144,935,518,870,181,636,471,364,637,241,846,811,725,244,165,604,118,470,127,185,686,29,49,833,948,839,888,633,669,886,858,449,959,941,12,204,804,493,768,565,315,818,135,496,724,27,635,342,797,562,641,951,352,544,748,24,902,343,85,82,382,529,356,179,206,947,208,421,490,494,160,740,308,392,966,347,605,436,373,649,179,510,620,116,925,720,418,758,349,592,13,528,903,203,297,37,686,837,482,92,370,918,365,163,739,949,258,74,384,312,637,940,336,27,263,750,100,738,964,271,267,445,501,870,480,251,772,53,803,745,893,297,50,139,13,424,322,924,742,992,75,988,918,2,284,819,564,218,473,40,772,941,778,996,360,993,606,191,666,376,729,230,72,8,698,578,329,528,268,466,24,541,185,329,30,372,603,218,888,750,534,740,337,840,370,225,701,365,932,638,167,84,594,225,991,275,513,917,413,80,680,365,757,424,374,153,528,587,760,282,964,689,522,242,103,514,989,109,74,591,365,758,636,396,118,470,613,83,302,915,812,37,789,457,330,234,715,456,961,549,750,513,482,895,301,655,555,847,272,872,726,45,781,384,896,556,30,540,143,940,357,79,107,147,859,599,599,941,643,50,885,167,370,467,100,6,882,247,637,623,282,1,920,93,879,9,949,116,603,120,840,747,615,220,4,762,818,53,334,949,736,166,528,113,138,834,61,397,371,321,297,647,880,989,196,298,419,474,582,749,739,423,382,971,295,176,827,33,923,596,609,834,366,356,757,957,391,641,332,202,986,692,59,259,790,858,115,719,242,530,280,97,495,639,726,843,721,726,534,225,724,988,61,715,554,940,778,423,781,817,283,190,751,164,36,485,260,461,798,898,902,703,806,957,854,679,84,625,103,584,138,609,648,244,837,645,802,123,412,800,483,371,19,694,35,583,142,224,448,449,26,62,423,273,812,959,805,962,713,155,786,151,369,855,200,935,408,154,566,970,32,672,244,418,599,24,23,90,675,384,387,605,771,492,394,348,457,613,122,422,101,115,403,431,815,787,859,380,560,567,773,80,574,873,934,595,619,533,556,983,960,721,114,991,811,835,687,745,636,506,714,444,67,901,772,358,108,462,452,448,886,320,305,929,911,5,810,708,100,848,81,330,697,387,182,126,677,667,686,258,345,387,973,560,740,347,984,872,174,930,510,909,657,902,648,283,628,625,108,353,368,880,9,571,925,597,884,511,462,718,413,269,988,227,226,753,900,662,793,951,283,107,690,710,724,196,946,705,518,824,142,953,44,9,276,442,861,65,456,749,527,261,332,977,585,422,866,623,649,701,14,211,713,182,566,464,885,264,429,20,782,855,869,977,99,351,275,990,480,675,536,113,622,794,567,378,981,364,257,747,494,296,9,122,245,649,41,792,243,430,172,246,278,835,301,462,305,451,924,48,590,162,964,327,970,481", +"140,332,978,249,727,930,609,720,527,639,450,245,667,340,319,905,248,336,738,10,218,974,751,194,881,687,677,756,495,268,810,579,261,587,546,72,363,595,413,125,598,811,843,446,218,672,889,178,352,718,854,53,151,224,138,744,796,225,526,561,362,213,485,555,650,241,406,174,881,223,224,767,514,842,599,343,985,417,513,444,307,979,651,383,702,239,57,418,622,504,207,144,945,201,464,234,361,917,338,905,416,923,784,510,933,715,881,470,588,683,449,15,671,750,56,528,190,62,600,934,105,570,804,567,714,344,267,109,638,299,869,886,271,457,984,462,652,230,707,500,345,755,41,794,755,956,844,817,990,31,372,368,826,8,195,624,616,402,876,721,356,18,453,317,783,119,402,229,812,10,539,432,866,150,422,106,29,108,26,260,138,247,983,930,28,983,841,228,106,708,134,801,873,563,366,508,85,143,882,825,698,685,925,916,859,558,286,233,251,599,640,647,695,605,182,773,898,943,365,766,248,652,395,774,741,37,460,479,285,538,685,776,968,216,56,729,355,829,296,607,965,931,328,362,511,653,733,124,237,449,990,881,296,102,447,560,341,10,150,522,626,194,97,999,815,114,901,897,649,702,693,515,528,849,258,692,994,187,192,133,490,773,487,981,435,264,517,251,726,586,679,568,148,524,529,662,635,927,188,197,480,471,413,588,783,259,551,339,854,831,885,247,863,580,0,30,452,26,312,660,224,41,760,299,388,299,928,759,932,716,683,398,744,687,964,942,857,772,151,227,407,685,702,296,451,971,364,417,657,356,502,852,313,711,293,105,510,344,391,27,51,691,3,231,44,798,891,293,677,445,691,137,166,269,388,355,503,866,373,383,303,175,851,368,470,462,803,684,186,578,433,419,200,697,892,967,495,464,183,473,418,647,945,761,66,459,470,688,219,532,131,802,3,810,769,414,325,165,603,787,346,325,458,228,425,896,498,812,450,216,17,574,539,963,850,109,872,495,39,222,654,427,993,39,478,900,472,207,135,796,639,492,190,449,574,525,345,271,666,904,67,641,950,943,92,483,32,976,784,423,881,763,237,142,640,119,304,108,898,557,540,107,386,879,948,549,18,417,701,128,739,181,965,561,620,61,905,949,47,866,294,124,905,700,763,994,45,124,941,41,462,878,373,333,226,524,919,506,865,344,711,106,841,181,800,706,658,670,611,515,823,669,679,600,778,203,725,469,158,160,438,585,716,376,77,280,991,365,986,569,101,950,106,950,93,915,116,405,492,307,30,924,779,166,921,231,483,811,313,259,225,939,346,140,750,356,479,693,30,82,49,625,818,652,70,833,701,675,632,532,527,987,898,341,99,19,224,173,900,602,500,911,723,24,99,64,772,609,327,576,399,385,934,220,236,312,41,171,513,690,435,454,865,118,371,262,203,371,844,753,827,873,595,335,60,478,463,221,140,39,688,223,249,196,546,229,606,739,149,600,760,120,873,731,868,50,59,910,320,944,925,205,33,523,877,808,412,680,4,721,92,714,802,830,975,787,76,950,471,610,355,306,353,670,483,341,252,814,220,430,660,592,365,942,391,13,749,150,352,392,291,436,277,722,812,433,894,923,150,834,482,218,517,266,983,917,37,820,878,513,810,783,371,803,615,415,532,740,281,475,36,82,962,594,759,71,87,924,346,793,486,878,364,334,848,199,283,877,543,192,608,853,700,506,51,457,468,57,544,685,780,750,215,93,41,256,812,538,607,906,274,509,836,396,486,870,427,200,889,633,489,106,52,909,913,272,574,888,440,872,524,696,183,253,365,867,40,923,35,314,933,218,200,644,405,445,976,201,670,382,469,352,379,276,376,408,880,442,482,136,437,577,849,872,973,315,837,856,495,309,895,100,691,825,299,557,593,379,767,727,208,99,7,2,706,252,915,583,105,987,33,872,810,971,234,684,488,985,157,37,926,748,396,809,306,762,435,62,734,658,245,478,433,99,773,708,958,933,458,372,179,786,856,236,166,437,849,856,633,146,815,136,606,102,614,721,628,497,902,635,814,972,816,178,158,974,63,949,588,434,76,329,349,193,879,763,143,851,409,792,241,248,285,359,573,113,514,174,653,83,776,125,998,518,966,921,587,747,468,634,112,687,180,730,298,570,355,55,279,875,141,618,906,597,926,14,110,782,758,316,566,84,103,94,545,847,589,1000,451,382,953,886,960,176,995,939,166,357,677,991,605,470,736,862,621,45,449,735,680,405,76,637,170,526,4,495,633,386,857,16", +"248,421,191,300,957,361,396,204,889,839,658,311,356,847,56,132,555,568,126,410,143,452,393,310,333,854,279,381,921,947,735,532,602,191,511,497,519,620,983,365,855,219,833,610,715,688,10,612,239,699,202,426,542,114,644,620,947,1000,805,194,778,675,403,499,441,320,957,640,675,96,881,994,269,695,728,678,137,521,728,63,516,444,402,521,879,368,561,768,99,387,865,157,961,482,486,434,692,555,413,746,706,401,684,855,700,103,150,583,389,474,523,978,487,12,661,759,964,274,645,695,273,673,182,207,554,328,811,255,924,640,369,997,289,532,143,303,654,113,683,237,502,157,650,548,111,141,361,194,606,568,103,774,1000,424,385,770,935,305,406,510,760,443,772,382,740,104,992,145,618,86,68,586,500,557,204,251,150,210,229,920,352,93,507,692,899,482,990,964,24,766,877,954,329,513,272,384,540,148,438,209,799,709,75,131,773,501,710,101,940,922,745,354,644,688,888,797,863,317,270,251,109,840,26,838,651,151,536,812,838,27,792,491,234,369,929,6,301,162,426,350,510,692,791,82,455,764,416,1,305,908,344,319,235,670,711,939,812,573,984,381,874,197,556,675,784,772,37,101,727,576,601,842,817,534,692,212,971,891,424,200,865,631,512,859,683,274,570,808,448,449,616,876,817,650,71,347,657,647,404,908,289,340,833,730,644,183,986,867,470,497,519,461,474,493,30,0,360,510,992,816,192,293,77,336,691,481,495,522,54,154,371,851,415,448,629,200,87,270,596,756,353,867,178,96,368,837,537,84,692,744,99,849,791,681,365,436,982,173,290,946,243,35,711,312,341,358,683,494,655,578,68,804,421,393,102,348,234,805,243,578,64,320,391,742,563,409,726,507,835,698,596,807,131,276,683,278,964,235,598,24,773,824,456,696,95,878,558,866,949,745,94,622,577,835,563,795,450,650,294,702,275,815,767,639,79,488,278,733,595,857,925,649,29,999,802,513,278,227,638,270,967,989,694,862,333,284,790,764,989,610,298,457,819,811,491,107,433,864,767,935,761,936,521,882,984,430,19,621,827,275,231,190,409,417,874,683,657,205,114,719,243,483,866,785,944,686,535,177,946,130,525,194,103,803,648,991,671,603,353,392,381,215,850,39,637,203,282,984,115,221,511,969,137,527,503,240,190,441,357,938,834,212,714,227,851,60,858,509,511,727,545,80,663,558,993,117,249,677,945,312,930,237,715,815,725,688,943,676,234,486,786,94,479,267,858,568,301,122,940,480,381,12,494,574,658,476,665,368,740,943,276,745,381,850,446,99,15,561,937,830,85,574,484,906,130,599,85,632,729,343,590,988,724,374,59,126,810,441,802,80,850,941,28,664,939,103,654,979,811,611,515,312,656,175,384,992,578,741,788,425,405,640,333,636,348,889,231,733,436,846,102,75,98,630,636,306,169,887,826,759,935,579,122,326,562,15,41,897,191,782,24,539,907,299,130,919,996,462,460,24,541,658,775,953,602,419,976,722,785,800,88,959,621,450,344,431,477,662,724,980,299,319,645,354,235,628,916,346,839,312,604,98,726,929,461,289,283,107,948,223,229,577,334,967,663,994,95,657,162,621,506,582,202,285,450,678,562,251,975,534,395,679,575,582,770,674,561,712,402,991,272,844,511,308,921,850,817,533,405,238,952,454,528,379,543,597,590,887,36,171,113,539,57,550,45,891,85,528,768,628,234,600,144,481,949,345,348,50,534,186,921,846,73,916,543,416,56,823,934,476,568,167,636,802,126,712,902,304,89,941,240,366,319,18,414,405,323,431,732,128,561,817,681,542,394,513,704,9,433,575,747,782,921,529,936,166,828,587,904,150,134,732,172,668,179,569,856,863,49,852,409,379,711,457,922,908,37,215,32,268,571,447,626,856,234,270,71,950,634,787,316,509,866,339,99,767,597,747,649,779,191,495,359,81,319,45,654,707,593,1,950,956,623,611,176,446,299,340,34,351,633,322,423,298,72,709,437,893,668,371,893,729,34,86,431,132,113,75,790,487,380,487,344,65,224,438,806,379,756,523,313,473,364,481,617,104,331,488,947,508,313,455,293,329,368,339,664,966,102,869,233,558,847,270,912,572,512,813,925,956,445,154,719,789,986,639,736,63,803,508,231,400,170,460,484,49,142,321,495,801,763,699,693,239,958,297,766,857,500,702,957,849,655,300,56,808,429,756,604,766,46,774,115,277,384,678,734,466,401,731,456,836,807,61,119,820,732,103,821,297", +"809,924,448,542,237,614,229,137,952,382,80,369,151,438,869,849,429,63,940,432,15,902,735,299,577,255,248,364,581,852,377,971,508,139,493,764,84,305,739,958,556,968,118,156,718,647,409,451,469,87,457,45,983,224,295,381,87,697,615,587,159,202,856,612,238,836,663,533,226,530,34,321,414,161,98,646,842,8,689,889,272,994,181,683,754,517,389,892,897,253,314,705,621,948,146,889,315,678,289,929,361,741,819,693,478,113,287,225,679,697,809,699,291,75,435,524,96,249,987,958,665,158,176,917,48,330,989,2,591,532,513,556,380,737,348,481,152,703,653,294,90,949,345,610,164,769,699,631,936,374,336,610,992,839,880,241,220,869,357,347,618,926,817,105,226,934,772,949,752,982,683,497,544,677,378,409,525,297,845,433,227,261,824,205,965,840,251,209,195,5,639,116,501,579,580,126,625,175,380,161,614,148,157,842,119,372,271,431,797,4,248,297,327,525,415,703,353,868,902,736,215,881,13,667,851,212,712,825,28,1,875,168,422,631,975,62,563,679,283,258,313,289,8,766,426,638,975,307,144,548,445,348,338,746,555,880,979,617,541,176,677,639,418,389,853,796,253,918,924,968,774,32,475,89,459,468,804,13,122,316,554,484,811,581,715,724,927,319,592,404,843,231,97,342,580,416,254,170,904,135,5,678,52,269,820,938,381,539,2,685,963,592,565,677,452,360,0,848,993,981,996,405,309,967,172,393,914,30,581,828,953,788,387,929,615,477,611,851,248,194,942,674,291,371,314,828,371,225,97,193,176,365,383,751,172,144,32,167,236,853,201,905,398,538,577,563,61,397,552,928,215,674,118,767,949,157,874,653,54,917,781,16,74,918,862,87,505,812,582,380,59,294,375,413,872,808,618,39,400,373,14,305,139,495,362,527,187,730,65,805,269,381,665,612,351,938,445,906,467,758,454,261,801,473,457,469,225,655,914,562,813,349,935,244,58,509,315,850,475,845,422,922,661,150,909,538,648,845,532,798,677,452,374,109,590,152,356,247,741,569,40,132,702,246,307,602,170,764,748,755,289,530,925,735,743,995,77,627,971,883,18,862,595,834,269,861,730,586,610,393,121,737,726,981,871,662,744,316,262,781,215,648,306,635,344,771,405,141,189,440,538,155,185,174,585,846,470,270,710,322,269,758,169,840,561,915,584,74,587,966,411,475,704,572,923,55,424,775,116,883,392,540,840,43,884,820,980,137,363,17,813,486,60,357,681,939,215,2,63,653,448,58,907,333,523,370,782,96,92,259,343,676,670,399,537,24,32,236,479,922,471,811,662,5,767,290,423,291,693,483,356,693,665,584,524,90,112,62,927,386,999,515,513,649,345,792,215,403,742,715,510,495,816,584,796,383,246,18,514,200,406,114,731,470,906,326,966,46,14,49,468,55,529,664,725,732,295,150,234,822,6,642,554,880,455,407,75,868,870,607,431,50,791,662,889,93,739,151,340,542,641,413,541,662,555,521,142,191,665,226,979,847,169,950,230,379,815,728,871,734,852,420,366,545,990,597,643,517,553,996,45,615,223,989,467,749,30,886,471,842,638,512,93,862,125,23,381,937,784,321,477,394,787,400,921,68,707,586,117,325,96,201,456,43,125,619,400,991,232,682,931,166,682,734,284,941,856,896,781,660,44,519,534,577,288,12,263,37,232,957,220,714,87,800,305,313,637,968,997,450,784,978,225,158,46,855,657,8,703,179,831,135,169,107,647,584,554,629,912,608,227,63,741,328,142,203,835,440,431,474,874,744,222,814,279,597,818,601,281,384,942,738,276,704,853,880,634,996,741,759,130,436,548,95,230,982,123,253,27,433,22,665,547,410,141,417,849,762,731,699,998,773,738,940,929,113,836,63,549,37,286,173,111,73,446,487,690,701,318,658,198,44,246,1,127,869,605,697,120,325,414,82,209,465,210,389,955,193,247,360,495,191,221,282,365,129,380,394,895,632,792,186,77,806,258,451,534,867,582,28,693,801,153,32,64,498,20,560,586,738,557,678,542,542,996,540,112,222,388,51,395,59,163,93,620,834,477,149,104,732,626,235,837,742,78,999,366,235,38,197,208,310,828,533,267,518,670,138,782,558,314,583,363,304,676,380,844,436,88,833,111,515,714,245,225,164,213,955,496,626,534,898,524,542,418,594,721,61,250,985,789,830,926,326,670,827,207,105,443,544,330,108,669,977,410,435,102,110,274,404,446,363,793,402,971,894,166,531,605,974", +"475,385,747,745,607,446,670,198,220,227,891,780,152,403,596,674,577,293,601,792,421,862,572,164,663,490,853,425,61,555,813,379,643,512,64,572,579,241,188,4,395,572,679,8,547,973,517,304,269,721,218,819,674,62,442,715,432,714,315,297,859,63,130,612,995,624,995,189,92,187,492,6,894,274,992,130,473,605,816,835,556,31,47,79,789,804,599,278,919,933,866,770,30,67,129,944,887,358,377,93,768,220,541,405,631,281,927,58,598,131,178,928,773,91,874,940,757,948,662,867,691,350,366,294,856,577,612,893,432,834,591,209,600,144,264,824,32,553,929,564,547,317,422,43,662,872,388,9,182,607,683,766,541,477,120,212,310,685,622,871,260,879,608,736,616,810,993,411,639,331,561,712,14,208,172,935,285,303,389,376,542,392,326,520,710,908,187,920,859,309,910,656,69,916,123,498,462,753,626,277,899,157,195,383,625,825,735,695,941,289,140,421,608,728,769,970,928,445,944,26,142,380,41,631,300,758,761,441,193,818,46,602,284,518,646,982,805,701,34,485,287,7,651,882,768,814,886,259,456,745,807,92,400,14,932,745,902,656,234,907,878,386,553,822,42,299,727,880,724,360,79,166,365,676,873,443,527,786,534,458,969,437,231,124,593,405,295,568,754,296,321,983,358,887,195,281,539,50,944,101,691,448,467,969,907,69,40,664,212,990,699,249,995,539,26,510,848,0,700,333,670,44,430,69,869,645,455,667,707,883,246,307,778,585,192,885,316,40,501,212,744,383,135,386,44,9,348,139,686,741,326,45,628,395,278,566,406,514,953,674,56,437,434,200,804,94,572,669,483,355,898,656,390,792,134,598,134,920,83,415,418,563,448,635,74,726,301,205,554,141,462,735,567,750,99,110,456,103,104,530,481,336,364,546,853,189,980,601,642,986,701,569,975,489,387,598,360,153,739,493,997,493,51,723,67,313,973,988,852,338,500,20,237,462,389,162,476,653,219,700,15,127,804,128,772,929,102,692,83,19,436,370,447,406,433,409,574,610,1,314,690,712,562,353,732,219,889,117,271,719,354,885,432,726,542,52,873,543,345,937,223,96,676,455,228,42,210,333,225,896,753,788,923,997,50,256,560,926,619,78,594,331,870,218,298,285,987,394,336,860,914,53,707,194,426,244,12,887,876,988,734,975,29,554,49,892,129,503,751,247,297,159,618,208,504,450,944,24,444,715,281,174,854,971,150,385,834,263,461,615,864,545,936,581,785,162,46,426,368,554,684,713,999,927,821,384,765,894,332,336,592,748,85,147,579,946,966,286,734,497,576,85,424,589,716,364,86,36,809,901,571,631,28,850,157,936,212,181,388,649,741,281,194,88,108,44,321,358,188,505,96,820,108,529,427,401,841,870,480,508,84,801,124,991,699,660,424,284,359,667,700,282,282,101,230,321,109,465,950,933,290,245,410,676,477,3,530,828,664,486,59,104,919,695,271,669,406,749,32,855,491,94,591,226,864,318,142,603,875,514,659,449,417,306,961,886,229,433,994,88,908,395,803,885,407,372,323,721,225,383,735,839,497,999,489,47,405,230,365,364,868,151,407,217,30,913,717,873,393,939,492,575,982,625,835,415,103,308,239,927,368,178,676,298,204,618,622,852,374,852,424,321,955,835,197,753,543,254,119,245,420,159,847,517,236,232,540,876,45,117,623,488,449,800,802,242,453,352,949,875,708,45,476,692,68,277,419,181,763,77,154,296,980,337,878,61,718,200,328,707,129,608,539,698,414,190,113,350,705,603,578,444,34,259,308,981,418,932,462,478,139,687,984,946,658,694,306,351,541,877,229,138,935,794,788,478,996,849,226,451,913,516,345,627,313,811,333,393,970,129,337,218,395,350,713,712,226,989,534,493,591,372,550,950,419,366,993,81,241,287,348,25,786,858,422,508,591,707,67,943,852,316,103,444,23,191,259,190,464,317,778,951,558,732,676,848,29,209,436,695,753,228,307,906,831,541,130,669,722,732,241,611,49,463,841,691,303,515,315,847,599,231,876,828,606,673,36,881,464,252,491,199,737,456,999,757,98,913,393,374,543,368,846,414,840,86,484,657,234,69,195,441,169,187,267,180,856,140,969,164,409,782,891,537,676,122,902,80,472,95,715,411,589,823,382,136,278,141,387,911,850,374,969,856,312,620,59,238,602,169,933,812,867,499,219,20,37,221,800,254,757,517,578,914,739,824,140,41,206,185,966,162,718,961,652,842,155,976,623,188", +"752,405,975,24,595,575,895,413,890,91,54,68,320,74,183,454,64,73,425,493,541,267,419,541,840,906,877,546,427,176,644,729,909,728,917,907,785,322,665,252,561,22,32,22,741,201,48,114,609,999,412,844,589,586,130,365,801,579,701,526,728,868,397,846,993,809,980,317,390,104,912,600,250,917,978,292,879,711,874,658,753,620,259,853,387,792,618,380,197,997,842,261,736,352,70,456,935,355,139,528,100,806,9,901,399,155,667,605,782,904,159,821,573,521,849,637,862,146,178,84,259,568,787,18,120,896,888,113,629,296,290,322,824,907,373,284,980,933,729,715,530,919,140,907,506,420,70,810,770,617,856,850,244,866,879,271,922,658,298,252,909,748,215,943,383,35,345,406,740,302,476,10,201,62,535,721,693,227,450,456,958,984,170,367,198,483,319,8,236,346,631,834,487,317,607,992,278,72,479,316,728,755,978,645,499,34,44,82,330,51,643,657,121,228,196,199,826,645,643,409,533,819,265,994,955,108,873,874,508,660,415,348,483,861,999,31,113,866,480,618,535,309,166,345,659,626,375,309,739,940,483,708,206,322,646,191,524,268,144,304,687,667,29,556,981,6,934,528,637,87,665,200,727,837,681,116,582,556,895,325,987,273,502,789,373,817,437,438,538,5,734,674,951,560,347,725,295,342,410,482,368,100,884,543,246,101,308,225,939,639,557,274,723,299,312,992,993,700,0,608,768,526,530,858,157,502,450,319,152,750,752,722,163,822,105,970,824,766,650,894,860,580,439,798,648,781,145,234,109,281,564,817,157,70,899,217,690,57,218,564,713,974,986,533,407,82,617,911,623,237,706,118,862,722,579,796,484,380,382,247,479,170,246,481,519,613,719,283,945,720,571,7,968,104,725,725,666,162,902,670,982,842,484,457,398,513,992,562,140,334,825,999,865,791,123,240,188,910,610,529,760,339,182,103,687,792,651,660,116,962,539,860,190,858,452,863,231,539,615,446,477,740,323,622,160,931,770,317,895,67,881,555,137,489,75,427,737,556,609,879,482,877,22,760,75,733,633,634,227,248,648,907,253,508,382,933,522,435,27,3,369,440,538,888,272,515,102,623,39,605,398,651,664,893,319,742,878,59,126,421,146,818,416,985,368,999,434,128,658,837,632,64,968,589,959,6,397,185,768,294,492,320,997,297,165,270,914,868,632,100,415,156,22,2,337,411,930,919,119,987,953,743,565,463,348,676,184,33,401,394,856,518,716,803,245,21,138,700,943,148,368,354,409,704,604,892,620,802,708,24,75,204,236,365,465,728,189,260,133,133,411,479,516,332,699,818,797,589,75,94,271,800,29,909,807,715,582,244,634,894,268,269,122,244,327,351,317,503,667,824,543,741,573,691,594,421,681,775,714,194,589,714,311,299,688,770,135,230,810,181,358,995,593,19,150,613,192,173,72,413,566,44,767,716,385,333,120,849,877,283,815,670,244,157,599,776,788,779,903,477,93,815,555,979,322,709,809,485,390,465,693,231,173,762,456,576,732,245,558,685,108,388,317,180,46,863,979,353,32,286,203,559,33,346,375,578,623,75,916,975,677,680,890,410,890,685,571,231,776,752,64,973,513,580,167,915,317,304,30,189,937,644,143,871,32,676,200,504,467,364,825,809,57,48,518,113,545,642,119,250,581,481,919,82,902,693,225,771,790,778,834,760,523,982,153,58,524,565,41,331,696,359,994,914,12,243,902,285,478,375,909,299,561,95,88,393,11,891,110,647,649,334,83,811,659,624,242,487,843,406,554,61,860,518,356,155,348,858,45,425,868,600,482,512,325,413,427,465,621,380,614,237,855,25,852,301,98,511,172,131,421,112,227,835,59,29,616,878,9,986,581,910,768,894,792,626,624,873,216,81,337,468,528,987,90,308,462,877,831,139,507,902,878,725,265,544,34,454,584,745,65,880,246,502,343,138,140,185,790,855,86,775,753,584,173,791,694,211,420,881,650,362,740,641,617,433,955,304,312,421,284,461,345,810,981,821,194,674,891,765,342,691,590,260,47,244,462,168,446,943,53,533,32,239,461,159,502,181,961,949,436,660,555,532,473,600,995,562,761,813,289,836,179,72,251,614,803,890,134,411,905,728,393,90,65,275,420,647,392,723,884,843,37,78,133,37,337,539,496,595,714,169,508,938,346,28,833,529,995,918,257,202,290,523,70,75,970,276,951,341,707,710,5,586,614,6,846,286,101,485,138,276,114,891,752,455,932,817,890,248", +"368,407,182,119,683,234,222,911,762,934,654,689,631,124,333,874,650,776,112,43,640,214,742,328,574,524,341,885,770,593,760,941,185,112,442,124,889,4,438,362,897,275,212,654,70,692,994,277,449,948,680,83,760,674,310,116,403,625,146,847,494,998,245,316,717,629,112,702,585,74,741,110,457,421,456,403,518,519,110,462,486,75,143,40,80,650,970,856,384,842,843,646,278,896,133,653,375,70,197,129,591,558,779,954,935,439,241,708,360,321,948,390,952,455,766,55,321,946,885,937,413,775,747,510,422,850,933,294,277,54,889,363,758,120,291,232,593,257,894,437,189,943,15,485,20,343,412,197,24,44,312,981,361,943,857,526,336,770,890,161,41,775,261,78,367,721,73,340,262,158,576,724,284,253,622,170,892,55,529,622,855,533,235,397,638,632,85,502,795,293,521,41,228,799,839,598,354,570,772,89,444,682,286,462,959,768,895,599,246,734,215,984,212,865,890,821,614,594,101,774,779,110,103,906,617,575,998,129,583,785,470,783,650,4,862,518,265,294,129,520,167,643,60,135,615,308,292,150,66,545,505,666,177,541,203,518,317,512,296,188,303,665,160,650,822,197,203,757,736,366,30,259,442,998,166,790,573,723,654,50,133,270,940,368,2,175,422,380,923,185,233,705,163,347,724,548,204,809,885,98,628,210,264,90,244,558,70,562,415,286,835,172,895,221,660,816,981,333,608,0,982,708,138,74,628,102,716,398,601,704,12,118,693,38,835,52,855,811,958,698,392,397,443,705,539,806,782,236,579,652,565,770,569,615,700,972,473,358,364,964,303,326,828,712,799,384,964,255,355,645,65,468,623,317,403,982,802,807,725,16,635,140,143,107,111,216,14,493,549,24,840,608,120,720,92,641,57,894,519,958,86,46,733,375,904,436,567,427,99,341,534,838,238,200,998,296,425,868,880,217,307,941,612,465,551,123,920,707,854,172,662,480,76,993,842,467,793,855,686,633,322,409,936,879,675,788,224,987,416,304,356,810,745,74,126,591,319,891,956,865,729,163,7,326,519,901,547,385,722,59,235,535,518,802,976,553,929,427,143,176,664,732,663,573,133,837,423,656,453,108,980,672,166,183,247,270,104,842,929,958,774,411,624,281,81,268,690,221,370,902,306,614,147,298,936,193,572,305,326,934,579,902,722,721,136,294,725,863,281,150,488,558,1,890,778,33,577,589,732,210,127,464,56,846,211,615,174,628,172,348,820,52,77,63,865,44,901,798,183,560,426,414,753,457,678,311,113,333,702,527,750,500,543,832,122,626,795,498,819,574,611,639,517,508,361,949,370,810,890,939,468,513,612,721,568,93,422,366,927,788,90,602,48,538,800,577,62,228,222,106,561,7,682,426,831,374,824,587,194,625,319,706,481,664,273,35,103,585,675,960,75,471,287,943,880,174,786,708,249,670,840,314,311,505,58,985,233,531,497,752,202,655,547,474,501,806,190,353,266,398,817,87,814,268,725,146,806,253,592,626,262,621,507,521,327,622,367,208,475,722,613,767,582,591,65,837,472,486,518,559,575,321,185,229,358,537,569,144,211,32,571,68,555,992,346,666,87,754,980,978,162,938,417,852,450,642,795,22,7,113,497,197,199,290,233,484,378,401,451,159,875,261,10,491,97,938,353,696,693,171,561,311,535,289,152,501,696,904,802,149,818,741,324,265,430,102,243,953,208,80,963,703,485,577,523,216,968,628,355,763,28,900,467,523,129,141,108,130,158,743,185,719,386,861,451,492,764,502,685,80,92,483,780,207,758,547,557,671,208,975,321,725,266,875,377,542,876,200,474,342,691,575,258,933,291,945,703,769,695,916,280,545,749,122,109,858,951,116,193,757,747,101,456,443,433,592,146,433,310,187,418,597,788,350,612,701,800,996,863,295,560,50,867,264,529,971,645,687,404,71,199,40,464,350,852,6,458,564,574,864,11,516,935,568,519,554,444,586,454,25,314,447,241,482,699,328,880,37,520,758,832,401,110,309,104,7,983,755,563,584,166,249,760,260,888,736,813,893,656,590,525,984,390,821,730,218,632,797,918,712,794,114,203,430,482,223,292,55,859,763,984,963,734,462,650,566,428,677,36,932,390,723,559,573,932,781,498,255,705,190,442,489,918,209,245,901,339,529,740,309,600,69,785,693,819,247,440,149,966,308,494,297,143,68,165,174,54,540,709,272,294,336,466,760,925,235,812,18,484,778,739,213,504,67,646,904,449,21,90,960", +"924,486,972,41,954,875,739,21,86,918,653,124,943,609,734,793,671,317,244,51,306,44,6,277,941,669,419,894,238,793,275,48,854,608,979,971,362,917,223,627,330,873,789,28,552,176,932,435,107,427,200,523,476,363,539,438,831,167,610,506,473,534,894,665,610,538,342,883,189,95,936,174,44,318,837,163,240,48,11,369,727,386,638,900,303,590,49,580,996,157,868,113,882,395,487,757,337,623,743,907,206,23,255,625,339,222,256,500,634,156,358,867,338,747,619,989,426,856,953,393,37,154,76,719,509,774,716,500,237,106,640,986,976,192,166,273,24,515,479,424,115,437,324,546,565,221,150,865,694,319,3,769,952,569,182,588,604,528,552,265,65,760,716,147,761,97,887,215,133,383,146,169,832,168,919,520,208,833,830,79,382,171,194,35,67,444,57,326,977,77,131,411,149,740,167,120,707,988,785,860,602,268,186,677,694,28,534,255,970,628,544,169,986,540,7,794,514,824,477,140,648,658,880,628,404,706,757,356,977,639,823,488,573,512,823,697,72,211,955,743,640,112,282,798,430,74,450,406,955,408,521,521,737,386,528,576,83,761,951,325,252,520,351,392,639,873,178,221,872,164,774,649,706,100,937,710,905,919,148,187,149,414,446,145,824,170,492,163,518,622,532,869,76,30,79,566,321,926,859,262,315,107,528,212,837,759,374,517,752,372,349,48,128,438,224,192,996,670,768,982,0,888,15,47,336,318,450,436,350,937,6,202,93,100,871,795,675,766,86,855,969,152,291,927,904,246,465,592,157,381,574,561,254,325,31,324,760,917,5,224,378,162,232,51,323,354,277,10,935,338,44,281,395,534,591,526,753,217,748,137,727,405,434,689,609,541,928,647,562,122,658,197,823,726,828,475,595,863,207,998,66,540,535,599,154,101,69,93,82,213,236,213,396,809,771,748,580,39,243,542,962,894,144,31,269,925,120,513,168,167,397,622,611,60,167,492,310,568,320,66,20,114,448,782,16,784,232,468,558,829,696,582,467,777,749,608,802,299,716,975,162,758,133,756,576,612,404,144,681,618,971,381,121,859,445,837,588,505,686,808,382,799,991,274,389,86,47,186,61,861,386,803,189,3,379,226,535,723,550,89,624,382,52,572,653,399,985,425,63,169,185,273,890,37,410,765,207,731,17,516,773,475,854,259,214,255,2,437,932,289,360,88,562,539,821,179,643,843,202,387,206,879,184,714,49,295,560,975,186,212,970,835,849,211,861,995,104,855,930,933,126,768,310,641,508,854,175,332,56,509,474,34,447,723,256,66,111,39,468,578,964,369,375,117,152,581,15,943,215,779,363,165,504,915,828,669,839,322,535,328,19,334,795,422,894,997,257,614,489,923,763,670,989,979,764,348,39,20,784,319,931,512,206,630,706,148,405,530,395,999,323,929,519,355,73,913,839,160,628,485,530,176,524,743,158,117,93,301,595,938,140,282,272,724,546,428,553,946,298,929,916,36,639,211,853,611,420,83,470,928,714,421,126,491,933,310,261,282,980,439,87,785,883,478,560,754,200,656,339,669,224,234,184,974,435,354,935,118,214,277,513,196,36,810,630,973,505,483,803,576,354,581,269,672,587,614,727,638,493,292,221,348,887,88,717,717,196,758,5,665,776,925,113,819,59,127,853,22,375,43,313,579,384,657,322,793,346,961,972,743,371,869,767,948,627,577,977,523,295,448,2,648,531,929,59,38,246,298,924,540,33,453,740,452,125,592,389,450,231,246,858,54,210,193,654,792,339,930,559,232,991,756,395,199,168,891,828,456,315,562,621,553,297,168,541,362,382,742,763,194,574,393,688,854,307,236,229,441,925,781,798,725,56,872,784,997,847,73,175,297,32,498,286,913,452,597,428,589,579,369,795,541,719,524,777,734,929,35,914,815,928,523,80,476,827,685,332,404,407,861,573,801,592,453,808,718,917,532,293,795,443,175,574,360,346,370,777,818,693,195,972,609,867,9,497,479,238,323,919,961,448,249,515,583,957,23,41,971,119,42,327,4,597,200,398,755,293,962,65,372,811,13,933,254,161,820,484,107,23,314,915,214,599,686,355,578,382,802,396,516,132,834,251,246,824,541,518,345,92,862,721,243,238,711,359,349,440,669,277,661,965,122,72,410,495,428,870,176,541,9,744,669,716,520,223,584,886,278,262,720,367,581,871,403,972,414,645,340,317,922,686,893,894,116,841,29,830,62,323,892,257,1000,482,942,308,111,774,819,537,639", +"108,681,469,486,325,264,438,306,788,362,725,95,801,54,948,50,435,127,862,654,439,637,459,228,564,865,651,869,243,777,212,115,944,201,240,598,948,295,228,158,305,128,501,225,866,825,850,96,817,170,102,892,569,171,568,332,802,716,806,452,893,143,808,64,564,552,783,126,897,940,971,812,987,688,687,195,508,58,507,618,877,7,821,310,165,837,172,360,181,943,328,82,448,667,621,440,76,433,171,100,113,589,287,2,300,302,576,48,27,352,375,541,987,695,314,642,518,837,662,829,969,476,903,424,483,423,996,967,590,906,512,466,25,510,367,953,366,895,749,775,535,876,358,325,882,224,965,495,24,288,851,465,165,954,801,97,290,788,278,595,223,768,499,276,965,685,419,803,158,260,427,426,656,724,20,868,437,275,770,465,606,259,576,984,144,895,887,548,599,115,379,175,377,717,835,743,311,396,106,826,98,238,771,546,951,527,423,132,822,38,22,396,471,19,617,480,661,746,216,351,224,996,592,819,24,563,844,990,697,99,947,635,522,288,619,249,99,347,274,230,451,716,938,747,539,723,439,730,456,677,852,267,832,239,801,893,206,850,953,317,191,447,883,280,854,730,974,4,15,882,676,556,989,631,193,795,620,538,216,656,259,32,551,561,99,546,750,8,37,787,100,763,863,60,316,625,952,26,622,961,274,578,392,495,509,559,648,166,436,378,46,727,736,80,41,293,405,44,526,708,888,0,939,186,442,295,385,675,285,723,439,183,491,230,216,972,941,185,41,263,265,583,483,825,618,227,858,329,430,946,515,130,952,404,332,30,219,58,988,18,897,638,364,789,979,934,570,952,241,930,460,502,593,731,992,974,811,400,611,538,610,928,110,108,143,694,278,917,333,7,798,337,481,582,617,497,992,372,960,712,749,248,656,997,707,898,30,692,603,866,424,118,786,361,20,988,135,311,757,513,417,839,326,716,741,951,201,564,562,5,319,101,186,500,391,183,620,557,134,54,905,830,777,571,706,322,949,46,234,773,702,516,64,442,294,340,507,706,755,190,621,357,44,971,709,766,481,208,591,545,612,536,168,153,603,210,522,343,300,104,919,276,885,695,664,796,298,77,662,22,155,198,692,199,746,810,790,537,66,570,736,27,682,491,735,550,135,253,668,178,988,974,664,796,538,492,996,540,662,801,592,975,137,404,354,875,446,900,947,234,18,646,290,982,223,548,594,946,806,17,937,220,259,549,196,449,491,12,387,965,504,928,232,901,692,459,589,48,812,769,397,654,586,499,528,621,973,508,270,169,774,515,548,254,115,900,48,656,501,180,815,313,149,503,32,413,160,468,582,179,189,402,971,158,811,373,562,445,138,611,147,138,740,440,725,122,463,948,531,108,978,921,58,941,445,579,430,666,65,954,114,998,120,617,777,655,878,274,559,628,883,45,287,514,415,181,73,620,507,93,880,559,435,605,30,899,936,306,629,52,17,524,294,378,531,163,491,733,139,275,91,94,557,182,703,35,588,78,372,357,727,29,197,593,470,736,272,990,378,106,145,526,300,789,791,167,686,635,482,858,13,334,71,572,416,5,66,894,784,679,201,710,738,425,905,29,801,194,146,33,968,94,81,403,457,723,730,769,558,172,336,292,359,825,313,359,530,248,21,476,732,25,196,12,539,609,202,486,691,947,78,989,20,323,617,516,718,601,348,286,166,644,696,22,464,186,548,759,653,125,408,91,2,169,701,548,741,304,262,792,724,553,210,18,696,442,913,488,590,136,355,979,705,864,348,181,973,959,240,499,355,637,462,824,447,365,653,367,253,117,537,363,377,2,746,627,459,394,822,530,507,322,278,507,936,343,759,520,93,711,418,791,456,764,575,597,428,988,86,731,867,840,895,321,727,184,193,820,149,88,968,980,412,854,727,349,584,272,895,555,90,860,436,398,868,199,434,879,681,756,811,872,55,950,723,816,837,448,870,693,472,259,367,459,341,119,384,768,991,117,817,652,169,513,393,432,342,360,133,906,548,712,116,435,422,576,509,415,20,651,306,835,537,737,674,35,16,970,45,19,747,193,367,683,832,101,947,357,427,967,125,421,937,12,500,14,361,555,162,208,735,198,977,449,946,530,461,370,134,824,591,344,437,781,95,760,767,214,298,966,801,445,248,419,387,683,851,488,278,751,680,566,730,606,725,73,104,644,52,439,436,648,951,190,694,764,353,834,440,895,397,419,497,206,197,264,141,442,101,612,664,911,808,437,820,114,294,519,414,524", +"276,293,986,869,619,620,40,600,359,35,385,512,687,846,47,454,583,6,733,700,39,422,245,688,626,231,363,959,719,636,943,548,532,205,860,352,130,791,724,363,939,57,326,632,472,270,507,955,568,5,123,217,860,808,925,158,221,775,511,104,400,229,629,825,350,731,828,45,747,859,911,278,674,215,202,81,660,190,437,561,454,659,581,775,927,594,730,928,20,66,551,555,186,809,842,725,555,407,882,698,319,358,903,751,326,228,994,156,307,625,493,146,97,826,626,827,220,124,326,994,333,789,934,32,843,927,117,640,181,899,759,729,717,211,687,498,489,725,94,833,524,291,730,205,947,304,543,172,781,441,570,776,875,126,943,286,864,517,78,473,683,304,775,914,80,587,270,177,374,762,617,3,669,361,432,472,450,452,425,15,29,583,742,972,686,495,597,957,122,595,803,972,491,884,271,290,201,557,73,697,949,268,650,128,543,667,372,100,806,465,884,355,361,377,775,436,258,95,49,983,131,851,232,354,825,727,232,21,486,711,742,259,249,752,84,741,220,723,717,210,529,934,39,940,255,64,89,455,344,988,818,268,845,752,941,143,344,55,513,590,284,457,564,967,205,149,77,867,826,441,562,928,203,42,182,215,919,45,261,388,604,37,827,178,503,957,258,931,257,789,565,940,905,561,486,47,714,836,511,696,397,648,863,738,976,936,508,138,104,181,943,302,985,976,760,77,309,430,530,138,15,939,0,193,327,808,279,821,160,356,455,465,489,63,773,525,836,960,19,546,142,626,28,935,927,665,75,244,81,574,225,307,221,689,527,678,44,740,259,268,630,336,382,350,619,234,838,299,807,82,6,428,474,485,132,104,958,327,863,839,595,82,206,20,594,296,428,583,686,224,792,752,892,857,647,535,466,619,985,292,214,179,405,154,216,446,895,259,199,131,597,615,764,831,985,370,388,625,697,968,920,341,544,508,849,255,614,550,410,12,583,641,137,980,269,440,577,846,82,512,721,876,946,405,95,653,260,220,989,565,927,46,822,9,576,123,448,811,943,425,701,583,639,870,672,582,871,81,190,418,142,976,545,963,664,954,510,385,717,403,862,67,847,908,75,93,821,533,771,608,575,442,598,108,716,52,407,532,87,35,558,447,359,441,643,219,452,682,548,687,887,391,412,12,968,567,878,886,916,633,810,723,847,75,216,685,946,4,88,530,482,733,418,164,925,656,480,400,551,494,103,13,626,993,626,685,931,606,63,472,589,176,558,502,871,870,236,940,492,462,825,729,731,234,173,716,922,612,721,304,396,930,388,621,692,335,627,699,757,811,920,766,127,415,919,235,121,385,660,308,739,848,243,174,496,297,405,555,465,65,321,90,799,81,686,944,437,833,877,79,581,891,636,317,182,520,921,315,562,945,938,268,132,251,194,940,917,914,146,317,241,799,52,780,609,281,838,465,136,738,249,722,339,192,481,870,211,193,979,623,427,962,417,602,251,422,574,585,962,968,487,340,721,610,150,809,33,413,90,388,402,554,371,840,565,971,714,241,894,301,220,76,877,639,289,60,894,248,147,645,224,528,906,476,830,972,59,14,648,871,643,664,875,829,545,634,830,490,344,501,623,213,112,327,943,402,397,545,595,959,410,91,138,654,67,409,173,852,982,472,665,368,887,786,698,502,824,393,528,505,797,510,370,721,206,160,318,693,594,321,174,857,413,746,253,690,992,355,209,776,741,34,965,775,897,655,294,646,3,129,672,370,774,87,266,933,998,839,482,659,925,118,896,218,737,949,566,27,891,935,235,201,557,172,236,620,951,692,723,198,217,813,291,281,433,489,425,632,540,158,400,52,21,951,18,783,329,359,666,382,40,623,683,701,680,206,472,127,865,435,354,238,523,209,651,475,925,45,840,297,479,62,305,891,884,979,867,931,836,947,715,331,713,456,934,745,975,77,382,369,805,679,687,173,544,538,68,774,254,13,244,903,477,204,419,66,577,409,733,417,741,805,940,696,675,763,191,958,325,492,515,10,917,535,543,77,346,378,343,883,122,462,971,308,2,339,222,555,637,562,92,134,747,9,486,50,312,904,572,54,425,668,526,516,231,127,142,105,8,380,392,185,766,616,807,747,375,827,102,716,177,72,293,562,851,809,579,805,376,966,693,606,587,639,456,691,965,355,843,599,916,671,653,664,780,143,741,418,111,322,352,908,553,283,796,14,500,322,960,580,601,833,655,886,118,145,114,772,390,581,271,645,195,556,376,529,900,784,512,876", +"472,515,770,298,544,608,256,683,82,509,85,100,314,348,133,780,252,260,905,57,63,334,147,665,76,988,705,473,619,815,673,905,121,716,632,309,493,105,288,263,598,739,374,259,33,716,244,947,439,253,112,748,972,202,176,37,313,63,147,132,916,55,270,118,246,675,448,927,697,382,955,93,165,841,162,135,31,905,262,132,606,281,684,680,770,478,951,893,351,140,462,163,242,125,828,438,348,219,945,669,578,227,913,911,394,199,417,100,69,706,118,519,910,600,27,994,428,810,300,869,958,946,31,676,763,644,867,867,948,434,946,953,204,731,355,225,994,682,855,536,217,28,374,514,978,451,387,107,776,319,684,461,207,209,795,1000,786,860,907,822,945,104,263,718,913,820,27,253,798,253,722,183,397,356,960,250,444,104,251,55,502,781,983,99,58,637,924,777,857,65,712,603,900,198,185,840,675,677,571,566,650,377,79,685,732,703,813,623,75,613,959,293,90,701,328,423,942,490,745,15,581,229,97,432,825,735,716,99,838,601,778,872,315,53,708,968,560,68,658,900,982,446,142,186,262,414,883,499,816,177,688,119,453,545,278,367,821,748,680,413,965,137,760,236,465,466,112,95,928,949,538,120,118,842,499,962,79,712,280,664,641,293,832,192,604,881,178,770,231,871,688,939,898,675,263,391,649,179,857,939,878,442,120,101,656,728,770,469,922,176,649,779,430,361,299,336,967,69,858,74,47,186,193,0,63,796,469,753,449,934,549,720,558,272,428,253,212,380,808,304,560,678,978,668,777,386,678,465,890,242,624,629,328,562,459,952,203,695,621,482,771,230,84,361,255,598,926,864,159,122,21,278,639,970,153,180,854,255,813,44,843,951,81,536,364,727,854,203,92,702,653,683,828,950,547,771,892,947,693,668,95,688,218,994,17,302,226,207,996,941,184,131,637,958,793,159,154,187,351,228,978,356,231,145,166,269,754,122,219,709,620,473,856,976,820,407,628,221,350,126,436,612,529,822,848,83,781,147,257,734,77,11,373,544,355,114,599,379,273,155,56,440,601,373,164,304,301,174,240,198,634,543,74,319,112,821,550,963,638,851,42,220,43,516,843,659,795,260,485,882,857,594,887,339,801,979,221,108,353,139,7,371,447,308,195,319,57,215,978,318,165,859,284,866,524,551,171,428,918,190,640,470,811,279,316,204,685,958,826,565,205,658,432,751,939,275,961,889,447,71,401,18,270,713,160,668,727,883,878,228,881,825,660,622,782,698,440,786,987,815,271,491,449,386,567,591,843,278,463,515,864,402,921,821,825,7,832,739,362,201,651,794,20,352,609,998,198,358,156,422,854,953,563,254,457,537,337,349,785,683,754,716,229,439,815,740,106,228,952,476,357,79,79,790,776,791,76,768,370,369,101,243,153,593,842,351,903,112,160,78,92,96,364,3,530,442,237,512,351,65,83,588,393,739,81,567,896,977,230,709,568,827,445,917,326,773,189,735,157,310,786,782,236,3,326,490,848,905,231,535,9,170,31,679,481,22,278,175,46,278,619,138,39,466,102,280,231,890,160,325,138,501,939,424,751,946,182,410,337,348,249,849,127,17,393,285,715,638,285,306,321,366,221,464,629,452,914,661,674,191,342,849,979,318,733,436,732,941,310,379,68,8,189,989,23,899,280,862,590,721,692,298,403,126,466,499,674,163,514,652,556,685,870,460,801,545,369,209,212,517,20,450,582,669,186,470,77,218,328,199,276,445,85,716,565,702,615,628,415,312,624,498,535,186,383,116,285,456,938,155,239,603,321,385,34,60,609,516,864,564,779,611,638,394,702,491,934,549,354,108,269,230,371,123,430,574,896,637,192,332,840,157,265,297,236,677,994,16,980,449,98,721,714,556,374,89,866,558,510,975,631,394,322,138,386,504,550,45,406,2,979,134,852,528,640,424,294,562,608,588,960,551,376,419,901,409,618,969,525,187,978,635,309,54,700,975,480,359,26,676,18,93,319,673,561,87,690,69,449,922,880,615,1000,683,94,566,67,903,16,299,940,429,825,992,516,453,914,918,772,359,69,354,270,973,355,490,814,847,981,34,364,495,316,181,773,300,117,869,473,811,398,163,545,851,952,603,361,71,908,982,219,700,787,446,138,65,711,27,904,487,496,875,264,742,536,392,723,551,952,662,933,520,18,187,991,442,187,438,660,91,6,203,20,495,956,820,494,740,989,342,827,146,92,65,847,496,440,339,270,974,617,540,789,327,118,692,265,311,869,993", +"469,590,12,149,66,952,939,155,499,326,119,672,692,389,333,958,809,476,315,255,299,296,72,145,40,607,170,499,597,936,167,568,406,371,620,1,443,674,632,399,56,201,934,478,715,643,356,5,440,268,161,466,882,77,110,918,133,717,485,972,668,340,660,448,850,693,605,977,928,802,107,258,767,233,132,133,597,676,762,430,181,650,451,192,413,423,456,342,429,644,702,600,526,22,966,753,44,408,427,417,811,788,19,204,6,967,478,911,792,490,857,168,124,545,664,738,786,416,770,939,946,437,737,256,68,201,822,470,603,429,211,596,960,368,246,254,588,303,114,265,981,533,255,720,93,27,975,274,407,81,874,433,386,364,720,593,168,284,332,930,4,86,144,120,512,995,788,821,532,612,572,374,268,195,678,867,647,400,726,543,709,236,197,589,631,402,469,375,48,676,443,346,404,207,716,548,137,700,449,794,661,845,324,65,237,520,831,840,352,522,534,827,219,77,863,266,164,75,443,816,248,992,62,414,734,360,744,956,854,694,108,704,668,447,386,332,837,894,715,224,491,741,364,357,906,20,820,506,895,342,404,224,661,797,401,298,545,799,556,574,535,315,22,915,399,541,390,919,801,375,651,86,287,948,909,156,563,223,392,211,643,348,593,844,627,345,479,688,45,943,955,997,412,129,35,76,929,837,73,962,853,402,6,853,813,18,11,874,247,608,390,164,396,764,388,691,172,869,157,628,336,442,327,63,0,975,825,652,194,391,773,609,595,744,127,204,663,944,917,486,376,549,740,295,832,414,163,842,13,399,960,868,558,61,600,803,542,512,177,864,330,214,421,514,501,780,859,761,357,548,476,299,248,691,100,26,260,125,800,47,919,803,137,520,139,97,454,533,837,755,957,784,81,779,465,494,937,28,290,985,292,405,630,362,245,797,527,673,85,546,702,505,696,103,605,802,430,149,422,220,498,654,803,764,926,969,577,762,766,478,123,872,569,559,6,817,126,623,994,85,295,135,544,845,754,230,984,101,632,114,718,906,21,307,491,553,288,444,842,124,962,424,743,512,322,374,359,955,284,194,383,257,418,164,955,868,496,826,919,893,855,55,454,713,274,86,972,601,227,55,369,490,886,490,266,756,559,65,886,727,61,700,147,87,915,783,795,295,831,123,208,981,423,26,550,921,804,92,904,14,527,920,413,676,855,423,972,452,675,566,961,991,554,26,758,799,93,739,736,881,824,393,334,957,873,453,647,356,157,220,112,519,316,972,884,38,849,30,266,267,228,278,681,919,511,451,210,794,445,262,900,664,801,863,386,416,162,623,171,856,812,36,864,710,151,924,508,234,795,496,497,814,503,195,347,792,11,681,698,330,715,962,285,249,222,279,302,551,914,160,495,579,102,868,29,462,148,456,254,727,13,65,521,697,114,736,163,645,444,316,17,438,299,775,567,77,218,911,614,287,107,431,266,908,574,714,408,215,118,938,177,448,733,634,555,945,718,909,349,436,120,673,263,36,773,541,30,519,683,376,670,443,490,433,944,154,62,915,437,735,678,974,86,333,487,188,508,567,179,520,681,500,448,382,791,303,728,717,320,432,642,309,251,410,154,936,541,228,968,594,845,306,288,722,259,152,549,842,341,157,514,923,559,343,901,456,72,599,85,853,769,558,416,467,318,703,568,409,313,706,982,259,279,71,333,513,708,593,508,503,40,159,15,858,978,394,655,955,154,631,407,708,706,506,280,84,893,584,809,443,65,666,387,807,924,677,485,789,94,39,322,60,880,70,527,229,988,354,761,601,71,692,461,264,911,648,887,986,962,816,396,153,959,915,131,121,862,319,486,682,44,155,138,605,444,832,342,222,965,781,841,573,842,750,546,624,699,890,751,977,181,668,958,981,445,770,907,170,599,20,409,826,543,154,151,567,285,571,5,349,580,474,384,771,557,579,128,985,527,223,73,331,470,965,911,23,723,681,599,671,994,153,844,721,456,820,384,694,704,195,210,642,544,963,245,537,378,241,805,203,867,405,1,215,337,939,596,414,758,747,754,461,780,597,961,273,483,354,905,500,253,890,65,38,355,82,542,160,268,348,408,886,825,648,782,229,561,722,56,790,845,763,748,293,342,425,96,821,54,393,147,112,873,814,597,840,139,958,789,181,646,657,388,366,502,568,139,888,668,702,723,647,620,989,62,836,62,850,332,908,520,269,480,18,800,190,891,835,763,81,539,930,983,408,363,707,236,478,5,307,537,394,200,755,563,635,423,678,974,791", +"704,497,700,310,607,510,377,219,954,231,952,142,872,134,914,343,321,86,942,775,865,980,51,746,338,930,792,683,3,427,417,768,922,448,52,638,155,189,960,776,559,995,678,189,1000,71,695,303,509,328,395,10,725,543,957,397,806,951,6,934,409,687,884,106,815,76,956,525,553,818,59,439,44,744,861,111,656,946,682,717,215,112,273,972,147,628,274,994,554,824,206,198,790,572,553,496,933,658,231,314,507,150,23,493,418,677,843,617,960,502,99,273,979,170,545,301,898,450,250,62,370,204,56,453,957,946,816,101,851,521,92,269,329,413,140,320,403,215,458,54,679,715,9,840,883,295,127,250,609,486,998,794,639,48,205,776,13,679,975,662,338,314,864,398,231,287,106,544,555,30,873,169,977,536,41,776,5,824,498,214,619,338,177,706,584,329,213,657,95,175,106,20,687,262,114,14,540,148,995,554,830,202,713,675,907,737,452,245,173,825,608,185,223,746,714,934,6,522,681,877,440,755,635,334,500,439,352,404,114,631,716,260,575,360,179,516,516,236,966,452,244,55,871,739,278,674,455,793,14,912,466,520,578,824,180,313,744,376,7,688,7,10,609,792,157,850,632,709,232,8,477,779,866,81,147,530,882,853,899,794,260,724,297,518,244,573,237,787,402,37,803,198,36,106,251,982,376,375,283,118,300,757,379,13,826,327,800,42,582,949,379,991,89,518,299,481,393,645,502,102,318,295,808,796,975,0,70,172,92,519,640,398,759,674,133,701,729,781,413,792,280,334,710,451,87,734,130,203,719,30,393,107,147,936,822,754,857,187,701,377,244,742,274,697,294,324,442,561,404,950,232,420,841,107,479,572,888,328,824,920,850,824,338,349,869,273,607,78,823,607,553,642,601,494,253,766,215,623,251,240,336,908,258,818,618,894,647,977,239,719,528,791,752,903,56,88,427,918,318,89,626,34,992,357,740,491,214,210,78,480,420,447,666,26,25,729,425,893,368,624,463,530,411,707,962,879,532,242,874,347,303,681,353,352,871,51,914,658,35,674,487,235,391,21,939,867,773,400,244,186,391,582,727,746,737,309,52,883,588,414,16,950,359,962,212,198,481,963,983,876,284,21,321,322,486,412,15,383,525,756,228,577,533,411,669,859,144,750,440,583,587,47,919,645,53,448,171,572,826,608,167,144,473,352,426,793,912,995,958,88,15,404,694,64,349,494,535,246,570,839,497,889,104,162,942,197,431,896,951,242,630,869,599,155,192,380,647,341,887,155,158,200,498,517,696,916,718,472,39,596,933,378,955,952,562,966,48,252,978,170,327,946,77,323,105,174,755,473,400,98,211,571,622,663,216,603,516,610,985,613,630,418,375,300,586,246,990,22,200,434,266,41,535,763,410,30,104,930,269,877,811,676,821,687,661,826,550,939,646,804,738,101,705,973,273,21,731,188,742,674,515,4,38,482,371,167,280,243,214,891,788,943,72,389,222,59,344,769,490,330,768,403,5,989,459,551,352,808,956,284,886,323,185,423,933,601,135,45,483,368,742,276,739,40,560,360,258,242,383,457,370,605,368,829,852,495,953,723,886,689,743,285,698,278,247,330,894,749,55,191,774,866,128,600,87,509,327,203,808,661,368,840,789,956,470,502,187,486,950,563,332,703,499,980,894,517,845,565,977,730,36,662,257,101,980,545,751,99,483,323,143,1,338,681,546,83,418,502,327,154,778,986,727,843,392,542,281,975,400,871,48,881,379,758,392,974,971,267,189,473,440,213,168,290,493,63,329,954,314,271,964,899,996,368,285,57,258,96,687,230,609,969,512,542,558,920,66,438,128,709,149,578,5,456,72,43,286,979,566,814,214,557,735,934,713,881,818,440,428,81,794,873,877,541,176,947,226,702,760,641,654,55,112,897,226,635,924,880,975,735,117,61,366,878,904,262,919,781,597,930,977,457,449,2,651,932,852,286,232,15,759,938,611,318,583,820,51,774,91,928,426,3,308,63,978,178,406,329,586,689,744,377,55,617,951,446,294,436,56,238,16,525,69,237,905,78,777,559,247,351,226,960,453,826,25,216,658,308,288,964,722,516,148,290,942,969,901,748,123,397,863,770,304,781,348,337,800,793,360,871,174,467,59,325,305,838,423,131,418,502,340,334,882,822,181,39,999,441,853,366,571,118,659,489,843,142,353,555,914,460,291,345,269,10,454,111,502,417,201,784,955,39,767,412,706,112,922,621,729,725,98,504,516,46,817,236,541,536,956,460", +"92,657,977,350,614,256,256,280,120,284,38,650,406,686,393,247,931,503,371,735,147,238,538,991,251,36,887,729,330,309,936,651,77,893,827,190,863,971,732,951,916,176,84,240,899,241,70,832,196,151,126,654,778,889,377,712,492,480,699,438,57,460,365,945,181,831,439,240,834,50,728,645,544,289,54,175,955,779,82,447,914,462,989,40,900,485,784,718,925,744,28,802,50,794,268,952,55,815,988,70,663,292,39,606,316,328,880,953,665,930,122,287,130,372,227,733,984,133,506,464,394,465,208,993,735,436,609,439,57,374,329,45,366,303,340,968,624,207,993,687,11,393,144,614,25,332,264,143,677,906,948,466,972,859,155,484,85,960,251,105,444,195,271,40,684,399,848,827,542,875,155,74,679,897,438,664,988,372,187,647,530,327,645,65,821,958,329,794,336,545,23,839,443,209,813,664,121,426,653,426,45,99,857,977,802,525,569,825,549,555,459,900,382,343,718,546,115,380,410,556,57,360,237,795,615,161,60,648,25,717,153,25,587,629,168,555,684,606,537,531,143,360,33,635,111,515,725,91,911,837,698,782,897,332,866,484,357,74,622,257,151,811,817,289,682,227,617,809,318,240,184,996,705,600,737,220,508,359,901,154,830,273,733,868,982,576,401,341,364,403,871,492,394,303,346,17,218,669,358,740,370,702,783,251,166,660,43,851,785,452,897,886,58,842,928,495,914,455,450,716,450,385,279,469,825,70,0,846,801,49,241,47,28,320,274,641,715,457,900,588,795,488,827,409,410,400,176,778,142,471,899,819,505,625,597,548,121,452,148,237,664,646,267,3,108,167,433,367,442,358,974,753,97,778,375,846,984,847,978,307,569,751,603,85,728,322,58,649,365,798,570,868,763,61,947,811,460,942,493,344,487,438,36,749,915,948,856,252,579,293,113,23,799,473,979,603,972,38,63,959,171,230,189,686,917,578,97,619,428,109,111,303,949,508,861,162,249,799,939,361,799,600,358,161,723,537,378,257,23,836,56,768,67,62,814,787,940,933,590,188,842,951,22,242,903,995,910,76,674,124,562,679,304,503,98,978,805,417,651,977,629,526,56,979,923,719,900,180,262,447,54,769,659,355,668,71,648,920,262,398,767,669,982,262,955,574,334,502,256,572,890,782,632,74,301,760,111,193,372,76,138,847,443,884,284,550,348,842,169,1,542,544,723,73,779,214,989,982,787,129,272,257,829,760,349,190,362,468,47,940,341,492,533,288,794,236,755,820,591,892,69,523,626,113,439,162,187,193,761,909,859,198,394,256,555,622,364,988,194,792,348,326,750,642,22,378,482,970,253,70,809,819,244,571,348,821,778,830,400,524,676,718,636,497,571,165,48,538,163,575,655,650,186,784,133,635,275,884,8,826,28,86,898,576,657,904,106,364,143,4,467,862,581,881,837,863,411,131,176,704,586,489,117,965,517,188,776,620,223,110,426,975,638,417,850,97,487,720,939,75,232,853,189,508,646,675,370,171,171,922,498,848,881,478,201,366,309,395,394,21,65,412,241,986,950,388,663,460,76,776,692,241,318,782,919,352,942,183,892,567,200,578,426,526,723,498,488,597,167,1000,889,297,381,819,642,412,199,820,325,75,203,472,376,630,58,846,381,297,342,411,721,222,629,42,767,381,157,556,605,436,307,611,132,889,93,153,89,201,767,662,289,531,233,894,456,969,778,625,873,187,950,639,729,516,324,693,646,917,846,688,32,109,455,375,932,396,895,280,854,183,153,419,7,739,807,242,566,905,690,999,833,121,853,771,920,808,242,33,788,828,482,702,228,240,402,161,30,190,751,129,159,611,587,296,842,744,138,278,677,823,61,728,375,551,29,415,121,256,872,849,303,89,470,214,811,437,430,298,291,221,101,12,202,21,981,927,922,613,100,15,480,348,662,935,188,576,851,96,202,682,206,288,514,834,564,180,439,658,480,622,800,525,760,491,220,707,508,701,150,215,315,678,912,5,992,328,372,922,614,710,827,940,974,70,459,101,416,302,491,886,74,942,429,38,331,522,730,919,489,870,411,388,706,839,776,86,186,692,955,881,488,917,721,869,129,808,482,975,365,646,562,875,178,307,188,339,721,53,253,46,761,267,54,412,461,636,112,132,243,386,933,341,178,399,376,977,706,896,869,865,140,360,145,637,6,934,803,271,430,48,841,260,16,503,287,276,907,245,33,917,798,15,867,261,632,766,420,499,674,992,999,63,625,465,698,761,204,79,719,136", +"680,130,216,146,236,966,512,959,843,753,817,243,647,913,496,313,473,831,961,355,696,467,737,984,501,384,621,884,825,218,424,582,571,117,569,449,116,434,626,324,737,752,943,705,816,974,62,622,224,349,584,932,997,934,521,651,522,279,213,501,437,410,718,864,230,734,564,499,822,65,760,806,126,442,957,930,746,540,777,104,158,4,63,551,320,85,905,861,348,102,133,137,267,711,308,440,108,229,564,839,818,887,537,178,655,621,905,494,632,776,63,287,785,783,6,204,179,317,939,186,2,329,398,230,545,328,67,947,547,810,216,656,509,70,337,254,73,597,988,200,499,456,206,165,375,918,106,357,544,217,597,798,759,474,774,605,785,430,218,616,927,589,468,108,354,956,23,81,80,535,892,75,273,191,217,107,958,934,876,408,66,806,776,894,805,917,99,794,39,501,452,5,154,866,8,928,682,401,472,830,441,852,792,985,456,841,666,604,142,499,250,322,928,142,713,582,476,997,561,953,666,946,149,169,1,291,81,579,228,234,66,976,696,19,959,674,5,762,551,771,960,965,539,328,229,481,53,598,17,291,228,560,47,960,610,74,295,771,936,737,856,804,813,458,141,408,655,347,725,441,12,94,644,666,484,323,506,410,105,685,264,224,946,446,964,199,322,975,318,537,503,369,613,140,498,533,759,20,752,257,635,557,987,466,886,683,28,286,229,234,926,847,574,335,759,522,30,667,319,398,436,675,821,753,652,172,846,0,463,42,186,57,601,795,622,651,6,88,977,505,983,305,596,982,728,228,597,475,878,348,930,559,592,484,653,525,667,670,198,301,791,639,103,508,434,420,368,839,701,492,375,884,391,366,899,882,559,670,756,260,113,111,816,879,667,280,643,980,289,339,26,680,455,56,456,47,639,205,610,893,278,80,510,294,899,253,661,132,653,41,869,96,522,402,554,968,429,731,571,917,625,359,233,39,921,568,265,89,970,708,789,809,741,14,253,584,872,366,454,544,59,914,349,217,994,85,672,33,573,964,179,462,585,968,260,804,404,504,103,214,313,741,944,572,87,134,295,851,626,628,432,688,162,400,377,219,986,553,140,759,495,181,954,753,90,788,253,291,627,641,957,265,282,676,814,445,657,801,173,616,784,834,447,213,441,1,70,599,970,995,71,851,152,623,987,876,536,70,694,469,47,834,284,114,505,392,639,80,658,523,60,497,806,124,194,348,787,908,91,518,783,188,235,159,128,160,935,603,739,230,526,754,729,96,427,860,303,667,240,97,49,387,162,663,360,600,441,760,125,454,672,958,188,643,461,5,476,241,371,412,892,654,931,543,897,970,756,174,821,203,117,348,781,665,40,799,585,908,956,571,269,82,561,106,263,370,456,426,320,539,90,448,45,912,50,671,541,636,771,956,596,891,127,899,576,690,955,974,567,107,187,401,950,718,161,769,579,86,802,809,226,823,932,83,618,806,919,829,578,403,181,40,508,803,256,521,56,125,379,370,914,769,777,214,207,214,150,885,38,681,318,557,868,701,898,83,844,176,545,475,800,315,454,971,589,916,736,874,297,840,178,944,379,755,498,371,178,959,618,705,626,136,427,886,864,635,85,672,241,754,312,66,48,632,415,274,59,730,192,266,488,546,370,228,128,153,203,627,55,88,866,70,863,142,403,174,866,462,962,321,412,945,653,377,653,241,486,243,158,16,738,419,306,653,894,265,143,65,705,737,403,590,935,188,987,902,222,241,420,897,944,276,492,451,944,532,433,78,781,747,734,521,518,234,15,636,607,112,240,316,303,503,600,973,393,460,334,913,256,793,419,399,581,987,425,953,888,168,356,113,908,606,426,607,353,266,150,319,93,708,77,64,568,429,378,403,851,47,691,520,565,99,624,552,874,132,741,189,150,742,932,915,236,618,134,360,146,831,842,116,378,52,494,815,262,169,505,336,254,387,382,227,419,428,777,51,720,921,35,96,881,852,154,719,322,918,787,30,204,186,879,841,755,235,415,783,891,190,71,361,770,501,682,924,758,133,985,890,957,179,372,792,698,280,365,350,896,849,190,149,355,904,24,428,807,272,28,108,255,727,435,757,767,55,751,31,727,234,982,587,762,371,495,89,721,904,891,381,244,23,118,665,518,78,906,38,558,536,661,281,396,250,569,694,944,213,379,639,221,270,928,730,921,185,618,237,935,135,292,367,40,579,846,759,638,361,427,890,975,377,792,438,202,917,434,484,284,835,205,239,635,750,468,411,340,25,50,250,282,83", +"374,680,324,568,324,191,335,67,213,833,466,104,143,262,894,567,881,271,881,200,917,290,674,629,410,247,743,902,232,149,391,808,113,704,388,534,966,930,379,775,484,863,38,768,371,881,397,944,229,164,800,73,339,419,506,306,543,425,343,628,426,468,304,32,554,680,439,145,28,101,986,12,200,721,215,329,853,977,548,126,133,111,649,718,831,290,915,3,514,750,859,661,215,71,311,414,125,76,813,429,16,572,676,134,660,931,728,483,426,524,652,216,758,985,456,887,221,71,872,465,448,706,618,800,153,305,52,604,866,474,148,590,124,591,157,79,718,180,350,972,694,129,148,466,441,303,853,361,275,469,240,922,246,205,925,298,767,2,669,469,284,133,732,326,489,350,352,878,494,214,464,559,756,931,266,581,244,482,745,128,350,903,625,7,147,918,151,751,280,374,804,695,292,82,839,643,107,85,810,135,983,900,348,93,847,689,148,497,60,538,359,779,452,931,654,88,10,895,803,379,698,866,833,229,659,969,944,352,176,289,143,400,295,341,558,968,733,337,975,587,438,211,260,903,710,488,103,654,641,671,17,580,437,229,301,844,161,144,433,603,757,705,593,542,16,94,72,673,587,932,86,701,561,190,643,9,168,657,393,435,549,136,23,62,298,605,8,427,952,893,826,156,128,551,151,275,66,442,938,958,341,37,494,233,960,21,741,351,418,668,380,488,858,915,932,54,581,707,152,601,350,285,160,449,194,92,801,463,0,893,782,197,133,26,969,803,636,13,927,975,112,802,801,9,435,832,845,267,158,535,766,600,649,392,528,428,857,697,290,244,609,752,346,100,348,986,712,367,152,824,327,767,191,895,858,705,388,520,688,122,999,934,137,535,373,166,52,457,779,904,776,202,866,979,199,115,998,836,309,633,341,814,917,664,549,548,662,492,157,32,633,152,4,928,90,594,294,597,688,656,774,650,123,738,803,884,129,801,819,233,480,462,694,441,292,497,44,451,419,790,742,147,421,595,671,137,934,686,308,6,112,537,242,30,437,710,986,974,789,784,566,875,873,44,824,444,121,966,369,896,916,640,245,451,734,514,636,632,467,291,194,376,859,925,271,274,915,185,84,395,465,67,191,837,332,622,152,438,601,932,348,744,252,20,106,39,769,3,255,340,616,643,828,142,297,268,602,241,295,670,525,919,58,135,920,377,521,621,333,987,446,503,988,222,504,178,371,69,956,601,611,637,938,391,660,427,936,387,246,393,824,91,811,72,837,20,406,787,620,116,690,150,236,945,880,84,349,239,846,746,647,839,582,584,333,647,681,659,644,598,178,401,428,277,966,719,156,485,821,635,404,584,542,640,996,46,907,498,940,458,223,530,654,337,924,943,930,3,727,984,136,104,10,535,124,761,955,869,566,403,844,664,809,877,651,441,738,648,588,850,255,981,639,564,593,43,339,803,877,167,873,424,391,440,710,908,253,630,952,575,921,143,775,584,451,206,571,967,117,291,417,24,589,246,931,463,457,920,542,930,716,844,581,868,266,659,939,157,58,17,312,551,840,817,321,510,469,117,677,899,890,147,151,250,670,131,708,203,23,326,620,829,55,858,570,889,554,888,358,727,703,350,964,164,679,337,23,151,717,146,159,618,223,325,859,912,529,330,483,588,692,660,392,413,355,870,301,553,160,469,221,431,310,521,141,728,494,165,834,360,11,236,478,81,448,662,400,332,358,755,834,259,76,619,697,223,611,474,943,693,546,128,100,822,874,808,95,423,634,995,1,841,410,178,155,353,462,617,406,763,948,14,135,270,686,238,967,684,623,124,787,345,677,465,600,335,879,646,872,304,528,920,232,474,897,910,458,493,343,567,276,943,212,353,680,490,224,889,691,828,616,987,89,170,662,804,162,453,11,778,467,485,295,65,452,198,435,331,298,192,55,528,909,10,343,481,881,219,32,419,776,134,992,117,969,971,550,574,555,784,377,360,146,828,987,558,561,576,985,523,516,981,642,705,835,167,881,109,860,483,482,933,727,651,785,282,530,17,758,889,180,467,813,691,412,161,727,218,486,852,561,138,438,135,524,737,9,168,995,93,835,310,893,244,226,696,985,761,580,987,75,943,887,134,337,325,800,894,232,943,208,81,751,359,22,930,643,362,866,415,82,940,734,965,960,207,203,906,652,324,65,851,926,778,615,67,301,737,388,101,357,857,139,659,575,195,438,681,990,565,641,805,951,173,566,491,540,56,730,34,559,796,780,934,66,229,465,628,308,783", +"473,535,839,159,201,610,850,655,731,627,633,153,726,21,901,850,905,203,976,527,56,974,471,65,200,965,119,523,424,695,169,505,530,411,514,81,870,896,392,212,620,354,311,958,490,835,723,670,189,43,453,790,694,887,688,342,644,222,28,694,570,251,176,753,392,821,976,44,144,240,940,845,829,55,660,485,253,681,120,29,402,947,484,169,254,301,28,913,149,438,697,947,714,678,300,975,369,635,799,503,714,665,160,645,757,204,464,913,250,846,375,196,474,467,513,671,992,135,344,558,781,334,961,787,820,627,122,27,492,239,886,192,317,72,576,834,814,844,843,775,651,323,539,621,800,45,470,36,885,439,944,62,355,637,895,890,301,81,771,275,813,213,729,677,213,639,418,917,616,296,328,941,695,41,925,415,864,367,857,692,172,169,704,53,114,710,581,66,538,152,857,841,818,331,14,716,966,921,9,628,324,94,449,910,870,371,779,388,292,512,440,666,16,683,799,566,795,240,188,631,288,140,784,972,114,619,712,432,96,275,563,75,833,238,866,671,189,97,284,861,939,433,624,277,309,825,527,20,746,496,278,383,299,693,217,679,558,189,871,450,986,570,135,116,33,298,911,119,662,31,170,542,588,447,812,649,533,837,538,963,928,479,865,410,967,514,286,378,616,659,161,396,5,721,170,164,443,764,113,63,45,853,915,112,961,315,690,272,724,613,271,510,134,248,716,154,828,883,750,704,937,723,356,934,391,519,49,42,893,0,72,221,765,129,588,846,190,246,991,445,171,836,411,320,770,999,704,778,401,897,678,325,196,915,978,56,839,915,53,167,974,592,929,294,896,69,746,879,964,396,260,39,963,239,977,603,914,759,331,481,472,136,356,237,779,693,371,852,620,389,799,956,524,559,725,976,824,447,297,289,995,984,191,405,426,778,168,373,721,485,438,21,664,359,315,884,487,689,287,911,135,120,180,674,58,842,855,484,146,485,315,674,439,543,733,451,367,805,318,214,550,452,172,696,646,793,949,304,593,246,197,849,302,452,272,2,50,583,149,976,520,843,849,500,242,79,38,345,178,530,933,815,425,454,410,189,580,941,995,774,653,48,433,739,105,787,946,515,263,449,724,309,601,860,341,683,282,358,634,695,669,522,822,234,833,126,813,681,716,467,514,64,730,947,419,812,821,10,599,971,964,552,676,84,551,475,376,872,740,297,945,351,162,794,396,715,936,912,23,70,279,880,32,868,330,33,668,936,358,65,738,545,787,945,660,498,490,464,137,594,897,842,833,538,672,428,458,655,509,187,166,885,110,441,930,724,838,753,132,532,634,627,135,524,751,498,929,77,502,446,488,279,107,758,13,797,684,304,129,350,658,442,941,576,3,718,530,334,923,753,979,29,933,561,67,949,872,571,176,37,588,223,658,598,747,94,751,228,655,946,391,789,537,712,937,753,377,100,706,972,415,217,282,950,756,177,349,110,707,376,877,676,610,322,935,81,945,578,335,50,560,666,574,258,211,910,737,995,863,554,90,895,404,569,407,236,270,682,970,798,776,54,867,891,63,710,3,659,946,629,946,612,286,515,942,966,471,881,880,859,853,148,654,480,209,856,837,310,464,511,473,639,416,273,965,667,997,150,369,481,33,527,16,450,400,213,172,400,449,79,28,447,309,875,498,225,760,618,868,999,619,632,12,281,294,789,320,936,622,611,814,7,534,854,830,53,211,964,754,757,883,114,5,321,190,128,212,13,363,657,808,129,816,232,343,360,896,765,101,81,441,664,328,63,622,374,459,733,604,693,714,518,6,139,590,872,495,539,318,267,246,811,762,962,465,361,355,579,559,936,931,130,547,812,223,178,909,17,483,535,537,184,372,138,803,85,490,336,843,778,309,502,776,215,676,374,305,801,8,37,29,121,286,603,748,776,897,827,821,630,926,62,830,276,228,937,103,569,676,377,244,452,575,51,905,569,353,847,779,56,823,250,385,271,502,159,858,401,718,492,648,957,842,961,10,549,350,980,170,37,355,859,729,283,708,242,62,738,865,494,268,39,392,248,238,834,963,847,497,871,729,178,663,919,393,842,664,84,775,465,707,606,610,58,957,473,952,187,45,323,604,120,803,9,624,572,456,319,13,502,372,222,691,467,721,406,342,720,48,994,215,792,514,812,781,414,492,987,195,104,43,12,12,105,885,72,806,251,721,204,205,202,879,595,396,420,195,416,521,782,1000,492,963,458,494,435,765,731,760,992,725,374,5,68,717,152,554,171,835,834", +"372,881,723,209,96,786,182,926,440,620,222,296,114,141,147,609,668,679,908,490,705,362,474,2,510,283,701,494,107,874,502,641,624,212,238,9,620,850,514,427,937,981,59,9,251,551,40,415,424,246,434,543,658,541,462,72,627,189,184,744,914,804,996,155,685,468,32,99,762,227,736,488,3,900,135,499,783,928,34,439,601,812,443,666,166,159,570,33,540,431,447,927,415,291,120,207,949,754,465,926,393,964,801,799,13,445,37,738,317,311,899,652,850,926,825,351,23,553,816,796,709,100,926,209,257,664,839,998,990,226,862,464,528,746,59,698,138,523,752,992,352,388,896,278,683,287,549,332,657,195,542,170,714,911,505,312,554,297,810,425,977,421,821,579,272,310,19,121,18,474,33,580,460,321,53,572,102,82,837,746,965,376,107,455,400,896,172,44,703,435,41,186,814,494,610,438,163,176,761,641,177,792,814,185,535,174,477,733,110,440,914,496,411,876,481,763,758,959,851,812,773,406,197,985,454,104,91,722,743,296,366,559,684,105,468,596,762,792,253,186,919,89,332,934,295,910,494,522,608,790,701,177,160,340,903,42,270,265,946,670,857,562,425,177,819,333,932,753,275,882,556,190,807,515,118,681,904,927,392,703,423,575,917,409,170,766,708,83,479,931,253,7,515,331,709,151,660,635,611,203,800,321,679,171,186,349,97,517,985,988,30,398,497,631,683,371,953,246,752,12,6,439,455,549,773,640,241,186,782,72,0,388,790,942,738,147,656,294,314,839,107,128,924,781,864,529,123,45,435,593,572,284,942,461,319,767,257,646,565,214,640,272,877,658,511,879,285,217,30,398,106,102,710,633,454,96,749,713,152,66,193,227,86,960,984,396,689,744,115,415,389,67,935,131,585,111,519,238,200,146,992,702,57,642,712,588,14,862,997,19,324,738,32,444,234,385,414,647,822,780,850,453,449,225,975,565,68,309,694,264,841,705,673,134,840,705,709,997,513,68,107,337,943,719,356,431,748,489,377,609,915,601,752,166,866,390,939,279,277,836,369,235,498,153,718,989,376,268,864,320,698,996,213,684,794,312,918,151,393,329,322,957,963,635,548,260,132,177,501,250,467,892,314,669,380,320,585,105,776,872,912,852,359,653,184,907,3,693,475,122,597,670,627,637,906,848,842,823,660,344,558,4,172,339,147,917,341,612,153,710,569,216,133,178,552,553,893,498,661,129,286,600,351,359,628,357,483,873,569,446,304,714,236,491,663,33,81,593,797,399,133,826,650,521,81,584,894,98,336,432,208,965,236,783,71,588,316,637,826,141,287,275,651,378,709,903,803,751,131,530,205,905,525,394,103,490,672,685,99,423,711,754,760,556,817,858,295,225,599,622,743,478,75,976,676,353,480,564,726,688,675,537,154,470,905,603,811,376,319,352,536,134,146,564,808,992,95,656,947,72,462,757,809,331,372,114,325,604,670,376,741,874,236,374,901,986,970,229,168,443,440,926,304,537,982,669,508,447,927,297,478,145,602,557,825,797,92,517,5,437,38,622,907,391,375,252,794,322,492,491,443,401,18,443,579,301,87,566,717,785,239,274,139,906,273,885,251,657,470,989,478,867,446,161,326,589,684,571,488,294,188,172,97,374,562,565,423,710,810,30,260,882,108,704,650,404,100,763,90,845,649,263,543,940,641,737,76,718,973,794,275,793,616,668,434,246,168,429,589,730,989,350,795,617,839,929,463,711,667,343,502,205,538,522,438,864,661,934,216,994,279,161,971,987,181,981,867,283,76,573,736,629,380,712,534,973,40,343,607,226,42,972,165,931,657,425,612,20,561,6,214,156,5,710,145,951,32,555,287,18,352,105,494,134,701,192,748,235,205,181,459,693,602,117,294,364,53,509,747,399,260,60,228,204,94,986,105,142,177,368,584,785,12,5,279,128,57,121,237,911,250,250,373,675,706,940,176,45,67,729,686,406,464,574,964,507,879,930,201,877,221,364,250,830,734,393,529,578,39,107,864,32,213,973,273,943,497,38,116,635,766,150,871,145,115,348,471,441,797,525,77,432,623,296,549,445,989,970,552,918,305,467,817,604,151,205,136,659,131,589,3,873,154,507,370,442,956,796,347,668,655,438,998,87,774,797,854,210,270,865,709,383,805,490,56,170,318,454,482,596,239,690,379,224,629,678,936,471,146,484,813,831,938,623,629,253,650,34,49,532,785,207,180,954,853,829,484,182,66,38,329,242,464,504,484,189,581,43,705,165", +"607,478,259,243,373,661,404,355,107,407,661,149,183,764,755,254,984,271,415,123,64,48,742,123,348,422,275,482,799,585,230,205,868,199,678,506,533,358,114,480,229,954,190,929,208,747,977,497,448,111,411,88,392,391,690,932,117,191,827,366,894,124,657,5,450,916,198,746,325,67,43,748,911,367,417,579,987,86,933,356,854,298,301,147,692,429,197,617,393,362,391,799,609,469,924,459,105,54,899,423,571,577,774,44,321,729,225,525,828,45,693,164,612,568,122,196,811,712,505,262,871,930,394,377,769,721,880,356,591,574,87,39,604,171,522,102,288,141,735,438,875,478,132,705,673,695,285,495,19,922,886,681,92,907,789,553,453,4,151,689,842,949,715,595,261,675,206,923,627,178,162,375,335,702,962,622,302,41,370,234,580,514,374,171,471,443,682,779,989,473,618,271,959,800,765,912,678,210,923,345,325,400,909,996,600,566,382,354,376,378,697,141,359,419,539,654,588,332,753,907,660,392,695,814,264,123,313,464,822,647,996,855,634,829,742,985,171,261,29,213,801,87,700,92,769,763,613,163,982,9,456,466,932,355,585,317,189,544,537,77,169,764,485,840,901,376,134,100,471,791,109,774,677,483,598,25,649,849,150,628,612,504,64,410,656,69,212,922,790,767,416,584,713,428,34,144,905,110,342,691,87,480,862,318,114,483,294,152,942,226,753,945,309,832,398,851,788,307,722,118,202,183,465,720,609,398,47,57,197,221,388,0,544,916,714,431,471,936,479,774,291,560,954,907,709,577,110,682,132,798,713,335,479,304,321,57,889,58,730,708,332,506,826,799,795,423,193,882,381,797,246,579,692,696,115,706,413,509,201,645,40,409,431,5,537,734,184,96,981,173,130,299,891,666,58,177,596,123,119,450,730,548,257,531,227,235,287,56,312,487,155,27,364,389,810,400,509,725,925,915,719,919,56,107,355,884,729,673,525,885,786,675,633,569,366,570,772,920,732,849,160,100,299,106,562,291,504,946,66,293,790,347,793,896,696,170,945,503,400,833,197,630,311,224,589,935,662,331,592,888,157,343,28,942,906,600,798,78,195,704,452,691,259,141,570,995,372,51,641,323,899,688,190,309,122,238,611,67,949,311,953,396,40,254,527,870,399,343,721,387,989,539,143,642,214,99,353,7,22,833,963,744,753,11,886,930,498,570,696,169,235,604,523,806,171,117,522,529,823,679,285,766,234,232,377,671,502,78,832,825,861,170,468,450,184,630,803,205,182,28,175,821,275,876,266,26,814,809,302,293,236,675,488,270,449,802,745,395,389,937,126,410,110,117,823,936,554,697,81,365,295,498,866,750,702,156,184,803,99,736,594,512,962,984,147,34,789,684,943,651,560,887,357,593,714,282,701,31,938,252,695,255,278,73,342,729,864,757,749,816,926,197,19,499,232,795,110,996,796,516,314,273,408,97,412,33,278,298,328,859,747,352,447,864,855,209,486,192,307,277,526,883,929,877,767,297,969,581,51,187,688,335,242,2,871,652,667,973,871,860,461,69,954,4,357,175,527,690,51,182,453,274,617,6,326,815,407,992,235,317,264,493,681,788,637,520,906,234,235,323,415,641,433,397,397,449,189,129,957,891,612,210,742,699,858,178,101,293,147,875,142,615,801,349,244,443,790,511,865,353,393,787,154,846,677,756,198,123,596,647,40,830,328,194,154,76,584,224,973,203,590,876,278,678,629,429,223,533,616,802,105,165,303,430,288,767,427,532,585,301,277,828,761,207,685,653,653,897,129,322,333,300,505,722,257,526,203,448,465,541,289,215,698,622,236,68,202,314,239,868,246,818,98,473,815,655,419,93,645,514,166,898,603,433,209,437,548,930,797,474,466,994,285,77,598,751,273,722,619,187,562,200,519,44,587,277,810,800,222,253,339,764,352,499,795,617,151,503,793,527,683,501,23,392,709,490,383,360,944,835,964,131,236,337,454,715,225,180,262,956,376,666,779,920,687,898,472,406,921,762,75,807,614,335,671,206,875,643,746,951,723,276,207,482,530,854,106,829,555,187,471,62,675,446,390,688,37,239,218,473,792,356,451,793,205,675,239,42,908,951,638,275,468,197,262,760,606,286,464,542,662,612,75,717,410,492,344,643,523,645,231,959,293,605,881,405,445,615,498,132,792,439,163,483,249,373,343,889,575,530,702,834,721,486,402,280,627,628,875,286,869,245,994,773,353,812,726,405,352,319,216,591,274,458,385,585,210,838,715,358", +"251,474,101,164,275,45,680,280,909,116,480,680,905,28,232,788,673,356,33,766,451,93,943,973,923,542,52,241,332,731,727,399,520,337,977,810,914,927,895,528,74,188,78,172,34,718,731,426,27,753,513,751,420,736,786,267,391,832,692,299,468,93,156,810,180,307,109,266,40,751,220,862,829,858,576,612,732,38,657,934,490,346,595,186,258,247,732,355,786,503,504,976,705,939,384,217,540,50,273,879,645,255,362,848,450,148,13,964,16,231,450,77,322,643,984,651,713,762,185,802,179,488,911,36,774,855,8,941,371,463,353,175,745,655,252,660,420,198,409,801,612,799,967,803,191,694,687,347,146,799,248,649,191,939,465,862,17,697,779,532,346,655,450,380,584,824,147,187,396,973,700,66,62,764,486,981,190,29,362,475,187,690,170,819,338,265,305,545,196,234,776,248,377,685,554,900,902,162,498,129,764,395,905,474,350,363,968,800,532,516,604,778,780,77,304,141,959,359,578,474,806,238,11,305,619,849,44,66,597,26,227,915,393,666,853,692,738,954,808,437,317,434,734,36,466,745,688,614,140,933,631,794,290,939,140,494,902,84,698,232,760,470,859,693,205,133,501,735,473,127,396,652,885,205,982,61,192,468,875,972,521,153,987,682,531,538,224,634,442,129,292,372,431,241,547,750,127,929,377,286,835,997,616,86,914,321,76,891,441,213,445,581,400,956,744,415,387,778,163,693,93,491,489,558,595,759,28,601,133,765,790,544,0,290,625,425,799,385,699,747,563,577,731,905,666,53,927,218,653,727,365,545,472,715,405,611,839,147,199,209,290,270,736,594,264,771,853,139,771,71,833,633,256,430,136,992,996,927,938,169,615,379,348,754,735,434,440,853,886,325,569,876,887,542,701,321,41,669,41,466,717,243,566,481,159,113,850,986,759,769,297,31,394,804,856,446,793,290,758,641,403,576,919,401,780,383,971,851,39,579,873,180,367,115,247,789,268,138,237,835,316,575,340,408,172,175,21,872,153,654,175,261,171,69,620,241,623,120,614,572,51,100,635,73,95,971,793,378,62,579,659,76,48,552,59,251,5,716,779,594,898,119,469,439,469,60,782,935,706,834,724,412,384,840,636,377,994,587,744,444,324,981,16,539,303,416,120,861,722,680,182,953,81,895,962,381,225,887,83,668,543,576,197,563,94,815,731,848,14,72,949,269,979,864,175,43,998,1,295,449,922,713,985,319,191,396,248,628,509,313,890,184,673,723,985,994,995,638,581,133,402,102,224,366,620,554,344,740,109,886,440,591,108,978,95,950,476,493,975,443,612,389,922,58,868,451,541,760,628,227,925,437,595,746,941,147,229,995,405,977,974,680,851,599,884,320,722,594,53,707,419,402,431,464,363,114,465,327,951,485,778,341,598,882,985,287,816,331,648,35,905,594,85,385,226,149,789,440,300,764,227,527,143,80,491,274,695,4,730,602,533,44,411,888,73,458,328,253,560,912,590,939,504,967,824,694,683,14,49,411,677,329,316,197,97,771,952,900,223,947,712,217,770,600,913,236,261,270,978,1000,770,131,993,312,281,731,959,434,189,129,75,519,456,295,689,739,268,365,93,460,381,375,68,277,401,24,585,531,270,156,248,463,377,450,29,165,57,758,875,730,283,830,487,675,388,25,463,957,57,557,306,61,803,398,797,654,465,216,504,946,767,136,823,748,481,213,689,959,148,197,606,680,51,483,552,528,857,637,731,279,480,717,109,657,979,839,570,8,706,17,951,642,729,380,395,655,175,647,838,175,51,276,830,671,560,477,466,677,396,442,395,31,973,671,870,696,763,567,609,162,39,401,944,988,524,683,658,291,504,249,381,858,394,737,275,846,550,639,658,920,947,181,626,883,875,57,237,817,34,481,571,856,578,390,671,736,698,700,390,189,701,582,113,794,564,741,285,718,520,560,273,221,575,374,537,534,145,661,441,815,763,622,829,735,176,73,482,690,687,847,199,358,25,675,324,667,818,688,786,138,3,166,429,661,737,620,644,150,653,685,116,282,606,325,212,211,722,895,400,837,860,881,626,578,647,649,544,514,921,604,776,872,478,62,586,825,151,832,702,561,288,44,249,303,26,84,51,580,615,428,424,605,436,287,592,601,299,217,387,591,9,528,484,305,988,789,214,136,259,548,207,857,749,334,611,855,189,800,154,344,171,803,571,343,556,666,16,65,335,53,764,881,409,15,191,836,894,763,891,82,628,637,358,65,551,512,928,461,736,377", +"454,541,875,575,738,108,529,663,448,261,560,654,195,221,433,711,348,340,265,537,425,861,372,465,437,124,517,552,867,441,813,607,285,741,989,628,414,934,574,584,827,488,224,99,327,705,652,319,308,969,847,233,354,346,897,563,870,121,415,12,66,529,611,449,129,743,310,662,244,20,232,483,932,370,744,529,618,858,562,335,439,254,329,664,499,215,258,722,221,806,835,310,269,262,697,588,43,925,158,803,764,311,780,5,258,692,591,229,794,603,201,952,335,972,586,595,519,118,347,29,195,223,876,241,693,143,707,129,230,892,456,809,379,980,562,479,204,286,242,363,766,83,512,263,353,179,278,63,62,965,67,933,917,962,382,70,610,989,378,711,493,948,206,29,274,780,326,913,454,582,591,377,578,851,986,891,671,587,753,347,708,193,341,488,430,912,996,870,522,912,422,337,605,950,102,157,782,869,263,418,106,481,207,591,78,363,769,185,11,143,973,75,897,27,163,224,753,866,197,708,912,510,802,406,9,144,404,316,389,624,655,731,825,348,636,797,856,61,217,441,564,107,590,43,946,535,670,117,926,773,658,258,197,278,156,764,500,772,78,730,657,513,624,30,754,186,438,248,125,961,388,844,195,213,88,449,765,414,994,729,64,863,714,381,55,297,580,412,97,43,981,234,209,98,805,845,994,853,724,579,825,377,487,194,474,229,298,403,433,474,823,712,214,479,687,448,929,585,822,38,100,230,63,272,744,674,320,795,26,129,942,916,290,0,546,725,584,310,287,154,330,648,648,494,703,6,172,391,855,389,909,127,561,204,451,54,203,303,904,837,488,654,703,782,254,525,428,692,180,547,62,598,516,168,544,80,740,241,836,701,264,529,28,639,137,9,510,374,599,380,32,506,758,533,273,623,855,726,715,738,10,208,288,966,753,962,296,987,558,239,671,439,80,352,629,211,725,228,685,53,172,95,301,48,490,182,508,357,816,851,76,429,731,508,931,80,538,621,92,80,466,124,608,416,23,312,530,185,207,775,550,460,647,487,640,913,950,686,872,402,4,557,3,458,469,234,605,876,833,583,678,678,388,607,251,176,500,569,997,376,790,845,255,573,960,774,546,191,230,763,698,943,425,667,212,562,982,501,147,426,771,81,238,957,763,504,672,61,349,221,737,610,344,647,495,442,256,439,258,797,835,871,114,6,703,341,971,674,361,884,673,695,873,923,236,417,917,277,391,56,600,216,169,759,147,159,584,31,387,115,547,506,879,817,948,61,951,562,910,649,185,401,625,232,775,509,531,766,938,822,264,598,684,125,963,756,770,298,743,618,129,690,358,834,616,757,917,508,584,819,92,346,886,521,665,833,252,449,18,890,671,665,655,529,784,773,700,446,774,337,75,540,575,510,857,860,154,228,134,408,106,403,201,266,60,255,644,67,930,134,835,695,393,659,299,17,27,72,730,601,144,74,838,159,743,434,536,596,897,981,387,625,674,648,158,481,41,771,421,652,323,931,915,52,805,524,901,955,181,964,516,274,31,383,354,115,615,446,323,780,455,390,102,311,768,130,560,21,163,355,968,736,113,253,248,389,8,477,363,197,625,643,41,265,38,63,72,986,519,30,838,979,651,661,636,670,644,660,993,89,55,111,985,620,158,803,478,978,691,786,574,662,407,433,679,675,492,948,618,435,206,737,762,202,78,921,582,18,923,539,173,185,649,54,505,972,136,631,65,851,595,92,862,602,906,695,490,36,84,322,34,267,602,463,447,206,547,265,966,583,520,94,779,930,867,512,985,273,528,717,41,375,953,455,470,499,277,273,927,157,594,611,586,638,126,928,709,913,834,602,531,290,959,149,121,650,370,72,389,560,533,230,537,809,477,624,972,159,386,719,588,823,314,338,750,121,238,941,90,870,500,688,310,525,219,956,366,707,624,13,677,658,701,470,959,682,874,510,513,416,948,683,251,500,392,984,753,77,726,383,661,918,601,672,198,243,937,442,115,753,848,500,901,766,479,74,212,325,937,657,662,814,975,59,680,48,83,781,158,572,66,469,504,788,252,33,489,816,235,413,874,681,256,255,901,607,748,880,596,123,233,542,333,838,976,956,55,236,766,459,648,346,250,28,380,17,685,703,361,162,262,4,8,658,320,693,799,723,470,561,63,856,939,635,565,583,863,305,967,241,701,105,419,821,224,367,418,815,352,852,927,29,930,849,635,835,913,16,571,685,579,384,105,935,699,311,82,711,569,749,300,588,906,804,55,249,754,889,792,195", +"718,522,823,305,567,333,297,80,105,421,181,304,554,963,258,811,917,756,542,109,115,158,17,916,939,88,618,410,424,458,745,439,478,942,499,304,989,105,15,79,35,144,544,163,176,917,768,736,242,566,332,515,58,887,55,795,938,295,608,306,673,491,586,761,92,142,648,669,773,625,534,639,921,851,389,731,220,73,945,901,491,527,263,527,459,786,946,692,969,663,729,664,282,125,514,565,277,651,747,302,498,603,856,498,828,311,856,699,306,994,882,155,312,341,644,890,869,198,220,518,356,534,851,926,41,819,471,14,768,844,599,836,199,539,610,246,745,970,857,713,431,935,835,753,984,843,278,94,779,80,707,210,104,502,842,607,904,613,490,954,904,277,953,911,656,268,57,510,913,637,967,166,987,804,654,714,331,617,654,409,459,589,575,478,536,770,373,177,284,446,313,946,151,908,230,54,874,741,753,846,787,10,287,810,328,402,256,718,351,507,735,887,962,81,406,851,511,483,500,878,433,959,225,586,708,816,585,504,49,430,57,775,749,630,971,973,626,83,517,156,895,960,102,281,403,915,358,47,235,789,575,460,842,809,569,967,189,862,408,105,281,908,789,967,920,481,253,542,866,494,496,635,970,930,4,883,751,188,68,203,327,516,237,319,732,812,420,171,832,132,961,416,291,205,885,851,148,863,806,724,328,184,708,573,809,248,683,484,232,843,111,136,814,335,964,629,615,192,105,835,871,216,773,428,127,133,274,622,969,588,738,714,625,546,0,359,86,334,27,808,551,387,715,509,200,695,948,270,561,23,215,210,16,865,133,815,544,791,190,623,146,616,897,373,401,111,810,699,11,733,706,410,831,499,518,725,39,577,534,831,537,244,455,618,313,632,641,136,280,641,573,968,473,323,963,843,211,331,421,456,488,717,482,483,696,826,942,357,869,633,563,781,64,32,711,957,688,52,690,185,914,661,83,936,251,148,215,300,989,664,661,747,547,215,121,566,599,303,154,188,546,76,587,888,485,244,526,624,399,501,359,950,206,591,216,109,313,713,72,521,384,636,903,399,981,841,786,394,834,187,438,36,629,722,365,249,212,333,160,45,656,526,266,490,783,590,887,324,667,67,947,754,74,223,296,779,305,169,562,194,111,566,502,987,831,870,347,824,313,784,26,630,356,70,847,23,264,178,886,728,472,636,176,532,576,138,420,693,142,805,870,291,997,74,459,434,975,841,3,702,669,158,397,542,792,293,400,779,400,925,835,863,691,143,249,814,290,580,100,955,473,239,474,955,531,917,453,448,192,547,858,43,326,595,225,758,732,437,115,844,510,592,33,791,537,699,269,874,752,909,399,368,692,95,557,244,690,722,638,390,855,666,306,946,123,749,295,70,216,155,365,314,289,960,480,494,364,18,754,227,316,161,749,288,65,112,361,290,25,456,605,249,657,557,592,936,448,212,533,441,215,550,591,276,658,252,908,788,795,470,534,947,473,109,637,870,714,870,788,916,585,885,475,374,954,594,50,868,259,373,127,256,491,181,643,435,931,204,587,144,283,716,739,427,124,792,457,280,731,317,765,728,806,903,187,323,61,539,574,805,668,847,64,384,580,634,479,681,596,716,417,132,871,662,682,218,273,879,431,725,786,237,610,511,205,351,303,298,89,67,846,464,877,612,222,147,755,944,508,182,72,116,944,420,688,863,411,364,851,613,970,270,379,352,10,386,865,136,710,972,842,326,409,609,810,477,439,624,584,984,998,256,821,940,357,336,843,829,88,63,346,779,92,408,321,144,901,844,676,67,969,478,838,864,271,809,566,446,111,343,447,470,829,489,480,772,964,819,739,353,659,3,231,46,40,662,464,75,559,345,769,148,934,861,92,179,193,310,390,63,24,59,801,534,326,687,784,457,654,938,268,691,974,215,242,537,784,884,244,7,262,696,688,82,877,2,74,80,477,814,584,411,410,88,707,543,882,285,457,536,633,73,452,988,704,837,733,9,314,469,14,298,59,883,328,353,750,439,845,556,514,675,244,231,398,132,499,302,274,704,147,314,474,522,513,676,135,512,561,701,431,360,627,819,662,970,608,329,654,452,470,357,632,439,165,885,544,637,617,69,316,749,926,343,904,953,91,485,807,110,146,176,662,124,158,924,692,239,631,398,904,715,296,415,355,599,530,934,76,749,496,640,468,436,193,487,927,273,520,491,850,60,774,768,393,192,248,209,244,927,452,308,871,943,775,855,339,626,57,824,599,92,6,577,364,382,766,161,758,873", +"228,135,242,881,516,399,362,404,167,775,364,88,923,203,77,438,419,652,60,504,384,562,58,141,335,406,729,42,907,924,855,138,980,10,574,816,670,218,785,338,789,303,179,411,212,824,698,684,409,774,677,798,896,511,993,917,546,666,673,770,391,667,862,374,86,465,985,372,335,966,749,265,768,265,991,400,136,625,48,115,88,145,430,29,778,696,706,262,157,706,374,162,551,147,191,826,313,829,986,506,392,413,29,575,748,978,671,48,285,157,532,732,237,782,513,544,775,828,542,15,859,204,772,609,863,720,723,259,399,743,621,296,286,918,820,40,258,515,790,476,655,953,811,59,221,375,604,409,929,232,638,558,244,36,243,147,147,612,784,637,152,823,913,553,30,591,237,627,473,817,872,954,337,870,88,314,569,748,232,727,745,784,887,875,122,381,592,97,681,399,555,246,623,411,44,711,522,225,824,99,431,916,701,299,359,812,705,250,956,947,73,799,694,245,125,386,818,191,863,88,679,484,399,117,872,283,365,823,853,999,371,201,512,841,567,57,900,826,698,423,960,540,842,517,366,398,754,649,400,902,86,595,243,816,557,626,973,438,690,772,927,206,670,31,626,693,8,749,335,453,449,727,615,380,944,866,498,2,523,247,766,661,549,339,986,431,663,991,680,182,809,895,227,533,394,799,555,240,539,541,61,728,23,126,930,213,27,770,461,93,130,700,309,436,942,200,477,885,970,52,795,972,525,253,204,701,641,651,803,846,147,431,425,725,359,0,207,108,220,673,881,749,439,212,662,658,609,362,922,857,62,587,571,798,580,192,497,46,870,715,137,511,661,622,887,472,179,440,767,213,378,644,208,686,149,317,734,73,984,892,828,132,416,196,36,358,138,676,875,317,802,729,654,707,969,871,742,247,894,603,129,871,511,650,592,819,700,830,556,888,85,133,730,86,433,666,291,107,355,338,135,649,843,107,262,57,917,245,327,442,230,4,993,88,919,498,339,475,220,833,901,733,311,336,794,83,318,220,562,869,672,138,538,492,545,404,617,87,181,489,40,308,289,922,407,206,268,25,385,683,509,913,763,608,914,757,736,171,71,152,583,346,598,245,809,126,907,867,209,267,500,185,125,585,67,260,865,527,59,801,992,125,623,62,551,213,82,931,773,401,206,509,381,956,866,849,268,275,311,797,316,502,927,789,442,914,476,820,219,485,520,296,209,280,43,870,170,190,907,58,883,296,489,408,925,388,63,251,792,487,133,37,107,239,201,825,357,147,524,997,747,126,115,805,226,532,396,975,437,874,913,605,812,491,89,178,278,908,807,788,493,92,854,20,606,554,736,665,848,385,974,387,361,946,478,414,727,153,265,513,851,125,457,367,45,613,944,153,409,579,540,750,720,440,128,460,974,855,852,622,595,458,593,769,197,101,514,186,931,350,827,266,923,290,74,122,906,134,515,485,45,902,983,16,942,488,292,455,801,920,946,544,869,756,38,418,780,273,877,603,666,747,272,905,994,182,671,380,228,718,819,711,161,878,168,597,806,897,99,704,739,699,415,983,760,948,262,343,644,463,295,405,703,326,265,633,143,173,504,738,103,737,847,786,928,492,377,130,798,423,945,528,386,643,503,415,74,589,409,910,92,742,818,177,862,861,855,142,605,240,334,261,92,30,499,676,736,449,566,727,550,912,61,166,637,11,233,208,316,883,819,698,380,499,714,998,149,169,510,737,972,757,324,727,573,114,634,102,711,224,597,554,142,615,769,27,988,995,453,459,492,3,204,627,63,911,302,122,293,782,833,523,510,711,333,863,449,425,160,516,69,607,851,496,327,794,190,69,338,649,975,763,336,162,47,821,325,22,315,141,278,228,708,933,597,940,377,166,657,888,976,899,196,992,356,756,935,19,437,418,753,524,722,932,444,635,25,393,49,296,915,762,589,528,849,606,598,271,522,766,33,705,171,793,255,923,633,348,45,813,855,639,552,222,404,649,215,230,905,605,461,166,761,674,573,879,82,85,280,953,172,931,123,258,317,20,479,71,583,661,244,462,99,745,189,962,159,483,834,689,848,891,665,417,903,491,853,942,21,520,548,614,880,667,416,469,499,178,275,517,573,784,443,195,414,640,324,508,369,654,498,61,136,132,445,23,656,630,724,873,918,222,954,577,56,909,139,763,739,309,300,417,296,265,952,881,15,112,2,184,434,967,389,855,352,905,299,539,808,421,237,724,774,901,12,197,109,123,330,734,371,392,255,935,502,865,488,147,663,773", +"252,163,809,528,698,371,801,474,971,292,52,529,626,50,772,183,322,323,148,947,932,223,611,534,672,255,777,645,274,606,109,354,276,63,336,563,149,673,373,425,581,599,984,619,578,908,485,599,212,757,105,633,336,340,650,702,99,161,978,507,297,69,813,925,914,551,627,790,919,91,855,673,67,298,379,485,129,924,366,41,712,176,671,924,416,380,925,749,533,783,689,243,818,773,798,60,128,302,216,440,919,953,513,664,68,938,473,504,653,551,101,802,639,497,45,655,959,311,559,785,293,843,684,579,261,469,174,68,212,251,220,490,692,490,656,268,193,869,339,602,936,422,97,453,228,688,944,244,289,126,273,171,921,51,609,835,699,638,134,198,218,5,811,787,380,369,774,209,952,227,554,190,254,823,191,826,457,661,688,65,680,345,384,825,868,767,160,458,962,676,106,323,412,988,354,166,54,386,604,165,463,650,275,257,249,340,454,752,53,815,360,781,735,873,859,722,384,751,304,322,920,897,486,576,125,24,51,2,940,145,926,893,98,909,697,303,488,520,292,800,940,915,702,590,654,211,352,489,275,806,921,955,201,152,271,916,822,544,751,60,799,659,652,308,844,913,784,915,339,269,701,911,453,634,212,327,986,39,876,889,25,295,780,943,898,72,267,477,753,166,581,689,402,883,171,986,891,186,222,133,381,955,353,206,811,265,540,508,763,1000,880,127,751,705,857,87,611,316,824,855,675,941,836,212,663,729,715,6,636,190,656,471,799,584,86,207,0,152,532,843,213,448,714,348,126,50,251,715,287,593,200,313,32,171,859,216,429,837,587,991,641,755,271,281,680,582,6,118,692,632,671,231,626,416,577,360,851,985,490,265,925,721,308,927,259,216,825,741,796,95,226,783,721,423,186,338,478,137,72,150,707,275,38,301,80,956,889,552,747,294,248,866,69,15,661,224,641,140,181,316,1000,673,985,935,639,606,750,238,552,96,484,717,135,333,102,244,23,875,204,110,901,331,712,558,40,808,264,566,455,355,99,243,714,433,413,14,131,191,861,243,72,179,49,545,884,775,973,751,79,923,157,951,189,700,344,289,341,534,592,480,459,145,886,241,809,964,555,76,556,141,658,626,672,826,791,457,597,155,760,418,748,141,605,621,973,909,370,955,292,275,867,905,173,116,266,698,112,347,60,395,9,791,939,627,982,6,486,243,561,905,505,54,661,443,98,675,899,638,135,31,208,730,781,730,996,438,143,767,105,948,350,802,688,557,291,252,36,698,180,204,793,232,911,903,933,397,419,949,3,350,450,865,823,193,453,947,916,808,155,949,79,845,861,858,253,278,810,599,625,751,31,854,399,248,944,658,886,730,374,312,856,378,753,431,703,757,735,850,103,882,202,204,336,759,724,696,444,899,940,630,565,861,246,901,429,786,860,713,637,451,785,890,130,360,721,760,658,976,466,395,559,217,278,40,937,169,183,208,595,528,474,383,14,969,768,459,647,883,318,906,960,425,283,428,603,933,924,566,741,629,811,204,499,558,349,833,675,557,244,350,335,699,923,195,166,348,139,517,302,632,57,517,470,788,932,637,930,595,538,504,992,843,857,5,360,830,260,457,4,327,188,211,246,147,172,652,74,947,41,808,269,61,154,633,488,967,868,250,510,741,787,242,232,485,205,438,143,671,800,277,937,207,257,731,554,723,785,460,192,482,871,809,882,43,603,29,781,334,206,21,817,645,137,32,513,678,199,41,347,374,27,886,325,193,905,867,46,396,881,252,784,246,862,682,423,466,788,877,315,280,433,800,908,45,460,681,68,542,801,171,879,597,502,586,480,500,320,147,325,877,567,604,29,189,957,526,475,921,453,875,27,358,511,210,11,707,899,936,177,299,20,604,511,113,304,204,921,534,660,16,156,154,34,411,768,539,160,290,74,446,700,308,677,44,681,863,238,150,685,265,636,695,867,756,695,443,993,624,71,258,31,920,862,892,444,969,997,932,260,816,41,367,966,35,82,350,717,724,665,347,885,493,169,503,712,987,852,649,229,476,355,381,799,63,697,888,40,855,18,80,571,983,372,361,482,484,499,588,509,750,22,491,176,310,730,488,327,636,739,989,18,855,495,377,493,297,519,941,161,187,435,511,392,354,738,470,758,728,639,674,910,320,16,868,111,187,37,140,174,488,6,128,470,166,17,586,520,510,466,35,201,958,142,747,752,907,486,362,137,354,622,794,60,683,180,673,891,255,86,602,237,329,602,257,436,117,241,714,613,242", +"116,180,249,618,89,971,53,647,462,441,213,72,181,354,142,294,258,849,427,537,751,443,142,376,379,926,228,10,805,592,563,836,447,613,78,957,404,794,489,874,358,328,988,28,242,286,725,569,109,762,413,887,224,513,174,965,11,365,725,679,913,174,484,712,91,784,995,939,27,973,756,918,764,736,161,522,826,873,935,771,907,186,990,426,694,271,16,390,711,577,86,281,298,527,720,457,341,719,819,966,535,644,759,157,494,660,260,420,623,264,461,920,833,284,953,129,693,830,413,805,348,31,504,623,57,808,373,444,319,927,705,434,588,680,897,511,746,49,627,524,894,410,254,657,159,764,741,64,161,120,848,887,834,305,255,872,151,531,390,40,995,279,892,201,341,641,979,8,655,474,830,954,605,408,696,916,609,719,206,455,74,57,248,648,491,250,222,174,285,705,975,749,882,878,304,897,313,663,597,646,390,578,612,319,350,493,653,229,377,522,43,912,696,796,30,276,21,439,25,957,465,358,828,598,265,241,647,958,77,591,703,385,995,717,211,996,940,384,291,463,985,401,818,576,1000,725,995,127,580,859,827,366,121,512,718,217,590,387,178,927,541,306,484,211,756,216,996,411,150,382,163,351,782,102,36,323,827,390,410,999,943,127,386,636,857,231,797,188,152,594,658,860,633,6,776,874,338,417,268,301,139,846,804,192,824,126,737,297,165,333,668,533,103,578,772,270,851,40,766,811,766,185,960,380,944,781,457,88,13,246,294,936,385,310,334,108,152,0,223,33,721,860,662,819,522,63,641,875,789,600,472,636,533,361,984,642,857,352,457,477,169,371,145,348,435,899,179,291,858,437,681,477,825,75,450,443,366,694,139,435,861,854,114,333,524,742,850,449,829,827,739,314,917,773,90,682,315,529,344,601,404,815,77,212,364,901,117,498,92,667,237,749,741,745,77,906,34,274,257,421,260,966,424,291,133,923,452,970,904,152,893,825,518,714,163,255,538,2,411,886,417,891,579,770,563,131,274,19,89,8,107,889,227,604,853,224,963,716,286,247,497,683,435,487,230,961,372,403,954,874,409,56,858,68,303,57,83,670,834,997,974,885,625,775,613,340,39,725,770,648,410,374,796,391,45,590,28,479,452,107,24,755,594,292,298,484,568,629,313,583,346,930,768,990,786,542,317,621,179,236,155,68,917,61,379,594,794,48,910,652,45,638,604,676,522,702,324,891,910,902,987,433,4,534,407,100,548,120,900,28,832,466,29,825,197,859,536,713,654,875,166,375,127,962,944,812,766,445,103,352,750,222,456,733,740,415,532,596,106,831,107,356,370,326,616,358,844,363,466,872,861,296,606,770,189,157,551,612,354,31,419,21,890,447,771,535,742,189,198,55,594,100,380,304,77,24,483,5,705,372,358,916,101,711,641,180,392,428,126,813,278,935,754,835,825,168,382,641,797,905,506,51,613,662,83,483,219,160,130,927,717,85,171,707,282,716,194,104,233,900,737,913,408,101,877,778,799,791,40,618,392,562,321,766,146,161,669,992,322,456,739,324,7,660,794,382,229,640,836,361,65,125,724,959,269,589,139,741,512,541,866,704,18,70,650,128,174,410,771,903,684,486,58,460,427,678,307,314,86,76,861,483,443,70,138,921,547,746,379,210,39,316,483,946,149,230,879,32,614,440,662,539,948,869,218,288,984,730,128,39,742,31,838,786,636,301,78,354,601,995,860,329,548,616,847,90,26,80,465,550,769,446,4,453,72,379,800,34,341,558,949,958,82,255,993,180,433,954,723,388,546,19,802,518,881,85,765,729,912,622,828,352,879,730,455,335,928,989,805,669,854,21,170,209,927,939,644,525,970,607,700,764,824,137,889,304,174,766,402,88,521,537,624,467,78,72,994,734,360,179,216,837,271,355,450,419,158,946,26,734,821,287,562,986,592,776,735,18,136,861,906,345,429,917,34,785,874,356,316,104,613,406,387,436,528,551,818,19,318,614,449,809,398,622,491,706,822,940,812,591,737,603,818,843,634,747,619,268,476,2,996,112,686,576,452,248,601,590,749,779,953,551,159,375,423,237,899,204,954,310,212,415,585,284,903,22,38,754,483,84,838,537,105,965,268,441,377,752,503,657,974,248,75,536,49,204,941,567,438,116,496,623,813,964,592,940,158,826,265,133,781,645,547,903,498,169,523,997,162,162,826,413,474,318,95,429,674,111,984,380,230,151,119,498,646,992,982,730,500,152,302,701,606,45,845,826,977,685,964,297", +"812,442,681,755,387,354,607,558,604,923,503,214,558,646,970,950,872,49,825,775,211,87,434,825,563,407,495,736,929,763,711,276,439,229,199,424,44,874,592,430,252,128,625,492,211,391,92,248,462,441,912,50,297,904,993,885,540,804,104,860,149,48,226,578,298,80,572,701,243,241,564,650,703,247,674,292,877,768,973,500,946,355,556,634,24,656,77,11,380,813,114,948,839,263,202,603,216,13,694,330,697,509,11,554,473,232,553,735,981,759,802,323,939,542,539,845,728,602,295,838,448,888,690,108,956,673,232,656,369,592,161,426,469,781,424,276,940,376,341,172,368,604,83,960,13,354,718,759,986,12,261,421,91,347,163,363,342,716,449,974,130,473,687,359,629,374,558,300,159,730,776,82,277,82,209,801,669,130,849,765,482,522,181,65,332,906,939,434,281,818,905,874,34,698,431,397,119,331,556,815,835,656,21,264,374,12,393,826,871,488,290,173,187,609,196,325,146,554,887,945,793,953,716,888,26,901,363,794,26,794,850,105,724,815,802,50,14,280,379,225,124,664,220,234,313,394,125,656,301,930,643,771,249,604,103,109,551,435,743,518,147,735,514,501,795,888,204,55,727,626,735,790,432,872,378,434,937,281,153,116,98,696,77,636,533,561,819,722,448,626,595,664,283,684,379,683,498,798,908,745,955,940,71,424,165,895,200,101,534,862,720,983,441,459,151,596,248,501,650,958,86,41,19,808,917,413,900,977,927,991,314,479,699,287,27,220,532,223,0,311,402,756,440,279,175,727,187,156,840,582,108,951,944,709,280,492,21,861,770,983,644,264,808,985,833,695,649,893,303,605,441,910,565,763,475,198,425,835,216,803,617,541,142,315,137,852,234,120,404,607,866,447,709,292,940,80,628,976,765,386,389,891,790,495,201,817,10,823,114,986,728,349,992,112,828,276,379,436,561,849,654,961,958,719,32,321,10,523,225,384,559,477,926,576,312,525,701,984,595,963,702,573,113,785,760,959,130,746,22,466,958,719,349,700,654,336,325,703,92,72,427,616,220,965,32,408,72,801,850,543,949,353,496,512,974,786,956,406,812,286,252,355,878,412,765,197,364,614,442,342,926,770,476,699,468,54,445,521,343,518,910,990,747,655,667,78,320,603,3,491,375,596,270,37,363,884,237,297,723,264,565,990,914,809,946,216,871,872,605,451,184,783,594,930,21,373,808,187,626,785,994,938,465,927,886,515,234,214,300,257,130,800,324,820,601,745,955,699,805,549,394,865,634,617,497,942,526,579,291,899,221,150,798,947,606,813,566,230,264,988,760,148,934,368,306,930,638,947,293,570,609,456,118,94,396,358,114,74,154,91,677,596,963,33,61,552,242,267,584,878,141,915,895,960,38,939,444,534,614,881,418,340,448,343,264,728,828,206,318,781,187,317,871,700,881,131,836,507,552,761,528,783,876,119,279,544,543,256,295,17,782,766,187,461,659,438,67,671,339,158,685,312,22,416,385,526,30,238,594,216,571,95,768,85,713,34,696,724,290,956,578,757,993,242,632,431,167,395,770,245,407,793,659,643,635,884,741,564,596,277,39,276,669,250,417,761,695,205,153,710,885,716,725,547,259,352,405,23,159,429,999,604,982,995,97,681,912,92,744,90,271,749,91,17,262,237,819,144,556,748,209,210,188,687,439,347,388,915,412,161,729,533,298,648,123,595,651,957,233,828,47,428,620,234,513,806,750,301,747,39,529,684,857,556,632,985,518,710,430,179,23,694,158,992,244,225,591,104,874,342,482,447,656,605,89,644,751,314,727,916,504,892,439,482,251,594,772,369,344,300,18,668,538,145,549,646,938,655,954,462,291,347,556,233,548,908,90,609,835,55,832,664,915,513,330,858,548,144,418,712,727,844,634,402,45,867,689,881,119,604,805,164,313,546,615,870,191,848,239,934,691,610,877,717,158,549,484,159,220,372,854,297,448,435,180,586,870,361,457,529,956,465,236,306,852,469,306,306,157,539,450,704,802,817,870,688,911,158,211,6,242,476,685,628,922,492,579,226,189,599,451,429,536,474,36,309,746,135,725,661,114,975,288,358,608,33,29,805,979,535,711,86,802,292,664,751,987,303,797,114,906,238,599,760,593,692,399,33,583,190,719,928,392,781,262,905,608,50,224,303,235,397,694,331,689,505,419,280,304,98,482,388,157,577,7,457,158,174,260,540,302,522,584,251,519,244,973,395,938,271,619,266,218,581,967,744,401,410,469,711", +"561,380,417,484,14,102,385,732,806,764,431,49,300,924,621,273,781,539,27,572,251,8,94,296,764,586,751,7,534,653,33,6,918,445,673,408,923,580,802,342,947,192,953,818,100,905,317,991,954,330,641,67,714,800,402,223,68,502,107,349,158,671,629,314,352,302,574,497,897,2,458,131,783,60,513,685,587,407,628,427,518,830,749,580,611,518,865,510,48,703,366,362,857,649,761,646,305,113,645,572,672,355,661,875,682,964,640,314,4,119,21,296,727,280,987,991,62,294,111,813,323,789,972,322,641,773,666,241,934,660,403,687,273,604,796,730,502,258,943,488,204,754,77,620,395,655,900,55,41,388,952,231,496,623,779,496,794,798,196,777,828,630,772,126,566,141,356,193,211,361,168,918,550,451,590,967,728,220,757,713,770,265,601,664,298,854,950,953,851,429,449,960,689,748,731,756,380,337,45,884,478,427,592,906,933,536,125,414,815,949,204,932,351,297,579,735,640,229,498,699,689,892,862,476,465,848,157,681,96,575,279,143,596,328,438,864,731,765,830,30,997,240,292,496,156,21,506,355,682,855,179,835,483,190,857,422,919,647,981,246,825,966,236,270,331,340,137,203,369,959,400,651,313,283,460,975,220,671,200,924,632,219,814,424,525,659,538,164,342,881,533,6,867,338,93,547,101,980,25,275,652,841,234,735,909,638,154,286,813,174,830,884,361,830,227,756,194,212,894,698,855,263,546,304,486,792,588,505,975,445,839,774,747,154,808,673,843,33,311,0,117,713,969,430,196,204,940,494,578,948,616,608,802,10,244,630,954,720,564,946,649,709,724,361,941,261,48,107,670,95,345,115,640,685,795,139,629,742,241,821,101,736,626,790,984,908,590,629,739,673,140,394,721,268,396,107,262,886,469,513,942,708,471,202,118,586,585,607,612,416,724,762,833,188,284,82,225,961,233,820,652,365,701,139,741,999,692,933,212,691,309,136,50,515,580,961,706,205,410,251,298,909,376,119,799,100,10,286,133,551,454,596,42,627,184,505,631,769,640,742,456,623,708,414,428,216,304,198,263,164,740,118,553,79,32,117,769,889,771,760,827,641,365,394,243,867,599,160,545,411,691,21,414,130,369,526,484,440,466,126,958,178,131,456,694,716,696,58,422,754,749,342,114,308,559,840,621,114,283,646,483,389,288,972,14,570,115,699,941,650,522,612,665,901,332,190,420,338,326,965,967,470,739,30,847,492,142,237,37,314,747,551,537,368,378,446,626,893,980,184,178,442,839,702,975,130,645,778,946,564,514,744,709,945,878,222,980,715,618,442,347,817,314,528,301,254,417,980,238,529,992,363,309,26,997,274,986,297,187,8,587,348,228,76,641,60,883,627,804,551,872,901,828,970,949,764,288,892,898,256,518,597,563,342,805,392,5,422,836,48,380,658,330,865,109,533,628,445,182,15,17,757,35,701,261,919,636,183,889,729,856,511,791,321,895,107,680,619,914,655,775,670,966,568,650,674,500,462,946,348,560,334,236,852,210,53,284,611,666,979,847,611,516,194,654,895,471,539,557,126,312,479,400,182,135,582,332,870,637,190,944,158,738,228,309,867,318,423,14,744,599,220,386,400,559,112,945,241,320,534,402,223,42,172,204,268,253,694,781,330,466,173,268,821,634,434,940,797,329,926,187,789,504,34,886,979,488,36,888,242,544,187,483,149,269,549,86,250,141,914,64,298,284,196,430,551,964,633,171,794,163,831,656,549,320,577,620,783,702,280,640,137,647,155,162,751,386,866,776,360,850,576,45,171,12,947,338,914,611,447,279,187,744,76,719,494,404,284,610,625,441,558,274,637,504,666,479,315,396,726,904,392,954,723,449,610,114,783,935,258,971,208,531,861,91,858,798,233,913,733,564,379,270,217,969,980,628,997,882,354,509,406,674,116,47,413,757,257,420,864,886,812,661,795,740,426,534,520,189,170,132,372,370,489,813,79,486,811,902,226,492,985,213,556,645,762,408,910,457,831,269,817,548,802,158,377,315,700,439,221,812,544,314,133,716,932,65,596,767,581,344,897,33,897,17,425,590,8,723,558,87,27,359,643,143,600,957,859,452,919,968,9,375,770,407,997,458,604,672,601,323,398,900,456,60,248,795,233,908,540,440,701,929,670,577,812,665,971,278,557,349,171,433,336,196,39,529,445,194,478,666,91,759,467,87,276,821,416,155,995,182,840,114,821,989,620,414,23,790,416,921,758,467,763,949,801,655,720,911,232", +"49,478,257,103,354,382,80,377,910,249,117,866,429,388,307,254,695,976,441,527,364,969,996,978,857,87,616,921,631,504,555,914,247,164,325,691,966,507,821,861,154,194,31,327,44,854,532,899,453,262,376,590,894,452,543,170,164,904,821,525,118,58,508,339,462,546,560,209,856,20,119,660,814,248,630,33,185,894,631,642,1000,247,966,530,477,730,48,78,665,921,214,569,516,743,813,827,96,378,889,892,163,548,890,765,110,795,70,180,971,610,82,519,926,724,199,905,60,515,135,484,325,691,996,601,892,864,597,829,954,883,782,142,634,823,699,899,740,905,816,593,73,481,846,646,740,667,683,420,617,334,405,663,764,116,184,583,657,561,153,897,980,279,920,269,975,971,282,51,928,781,655,167,625,689,899,34,859,946,784,863,442,888,808,526,234,79,408,93,955,768,984,483,66,931,300,805,517,99,647,501,668,707,718,899,800,958,612,512,464,881,252,355,889,766,998,563,605,954,831,91,1000,140,628,118,833,612,295,586,580,73,202,485,504,406,523,604,352,486,887,805,349,482,341,256,511,5,140,326,123,185,867,881,480,670,436,816,512,770,628,172,581,500,187,182,513,143,846,546,622,463,241,973,281,995,59,314,645,209,774,495,343,98,681,156,657,939,968,200,995,311,655,738,526,471,83,677,341,839,983,230,861,638,311,85,152,967,671,719,632,392,843,408,23,211,407,353,942,744,860,392,969,265,142,560,376,280,795,983,112,171,107,291,563,330,551,881,213,721,402,117,0,803,293,796,132,734,294,873,327,831,442,466,961,242,860,59,628,609,749,4,762,523,709,134,777,18,761,209,104,741,495,716,409,235,173,114,480,496,549,996,728,341,159,698,23,774,897,595,682,365,621,680,736,496,685,329,109,706,172,90,961,265,844,837,806,362,999,796,809,672,887,512,78,454,685,465,289,251,868,26,777,260,115,117,488,4,696,95,985,833,377,533,64,551,566,909,475,950,658,602,671,155,165,590,615,876,187,721,932,64,178,140,856,910,62,605,890,141,523,884,651,47,618,186,911,353,854,967,483,362,937,47,22,341,767,155,543,43,151,765,838,851,529,463,619,751,874,461,93,344,336,215,974,603,276,551,946,421,845,157,579,483,409,892,581,424,891,379,367,980,905,485,679,528,804,650,863,941,712,433,22,485,809,888,230,93,801,576,545,110,409,290,380,131,130,841,52,646,513,709,222,199,318,492,20,269,753,333,966,401,574,167,339,335,343,812,448,59,727,368,624,157,129,859,448,432,600,833,97,663,901,230,743,343,885,963,728,216,845,84,430,75,136,325,858,178,160,136,281,954,706,785,860,691,592,449,514,937,349,548,319,97,123,185,314,151,498,362,579,96,830,561,813,718,352,381,534,903,593,612,31,915,937,119,331,525,914,534,795,801,352,433,624,995,545,874,966,803,247,443,238,86,298,72,184,738,218,283,823,872,889,407,908,746,633,675,245,48,132,103,513,525,198,453,826,135,866,184,137,354,335,684,739,192,132,847,313,403,897,672,792,704,663,226,936,99,568,38,612,709,805,217,335,661,308,426,873,165,754,970,902,491,87,563,753,948,228,556,658,570,753,435,812,550,173,236,703,234,191,415,576,314,791,971,577,845,334,67,210,852,939,91,582,714,97,713,967,800,163,278,489,493,336,336,172,612,588,697,439,258,150,150,375,268,541,77,969,595,744,692,705,78,38,592,767,754,340,725,66,804,653,50,750,506,905,549,208,670,151,862,957,547,744,787,450,782,752,839,454,167,936,671,185,823,102,715,21,164,156,424,27,562,626,384,46,970,821,857,482,270,151,547,236,669,959,633,690,590,66,968,800,430,893,413,565,302,747,594,985,548,645,816,486,198,6,871,696,479,793,386,928,708,242,448,826,485,526,411,696,302,230,300,417,960,868,958,286,968,829,275,556,907,340,305,297,926,860,55,448,636,341,616,235,737,725,857,564,44,820,100,63,692,537,84,57,74,271,454,162,696,737,593,622,274,581,493,718,122,224,410,183,297,858,733,49,70,733,933,993,970,384,709,767,340,624,233,829,287,593,812,704,375,451,273,880,332,190,280,326,265,157,274,464,416,363,116,757,67,504,262,859,916,331,392,959,888,349,36,464,369,886,521,887,351,180,955,147,704,886,672,336,747,426,872,575,764,997,775,185,214,777,693,478,412,809,557,323,26,415,661,381,257,202,444,142,961,826,248,843,937,340,833,689,352,228,438,488,826,107,711", +"248,682,492,720,780,937,880,821,349,734,206,885,354,955,621,976,520,420,441,193,15,946,801,102,880,906,786,939,159,318,651,995,131,317,728,302,365,211,351,441,96,149,987,342,562,697,165,702,670,625,379,315,959,2,422,10,359,299,169,895,514,878,870,612,111,665,385,697,367,317,923,926,303,25,726,399,465,23,657,197,6,615,212,343,143,430,428,869,765,511,492,403,949,2,68,993,853,252,929,498,242,203,696,144,344,855,969,120,206,224,204,27,346,980,206,547,452,242,318,995,259,455,633,524,722,90,532,919,859,560,238,270,919,884,529,633,563,536,399,722,615,11,716,832,663,272,382,728,693,304,346,799,429,144,860,215,112,355,221,712,746,681,442,528,475,984,593,673,925,428,350,640,449,957,680,145,548,237,864,100,590,763,109,943,231,64,398,859,462,503,204,725,109,810,794,899,973,759,893,436,895,809,440,696,90,460,11,205,548,985,686,340,970,860,914,437,713,821,100,773,679,715,93,208,6,466,761,607,594,631,750,699,928,923,872,866,554,696,331,217,184,959,829,587,419,125,617,227,156,86,952,529,383,742,577,186,808,182,627,264,245,173,208,329,36,561,304,916,129,986,386,100,857,926,988,672,624,309,821,614,638,254,570,234,649,986,61,382,659,426,579,690,249,477,937,827,869,917,241,503,565,569,154,925,368,962,305,33,536,674,267,739,692,937,685,867,674,383,580,397,152,583,626,678,549,334,488,305,802,836,128,560,577,648,387,749,448,860,756,713,803,0,333,936,619,544,877,927,734,309,927,157,124,428,942,6,277,799,239,802,218,774,109,786,152,566,742,317,476,227,190,122,557,408,458,949,908,368,454,197,62,342,11,471,553,983,543,726,952,142,417,110,590,380,737,629,832,437,289,297,656,502,620,278,819,990,795,491,577,178,215,597,221,728,399,288,508,863,863,747,228,387,562,711,71,205,19,933,776,352,561,779,660,409,828,734,216,45,774,626,361,910,125,387,844,73,206,516,866,103,78,407,96,916,588,719,978,651,346,648,603,815,350,162,528,279,920,743,260,878,128,442,720,821,665,341,113,800,386,156,307,85,403,645,438,670,685,147,194,433,563,507,876,212,724,282,425,804,176,995,914,248,260,646,536,33,764,427,219,256,208,301,989,719,822,84,449,736,794,39,574,934,982,532,571,963,694,238,38,953,585,581,522,147,255,20,92,951,890,500,533,678,361,687,624,741,763,384,697,362,474,424,278,668,697,620,305,897,339,167,185,205,152,983,364,12,787,106,86,105,466,817,658,700,731,459,340,381,458,542,522,970,829,740,231,856,316,844,908,972,199,517,263,828,168,543,143,689,547,372,110,772,31,249,218,940,978,262,726,973,536,123,137,309,608,466,769,798,933,343,43,923,177,198,884,705,762,786,459,110,825,9,720,857,499,875,855,171,429,114,353,741,404,924,753,203,112,918,711,570,535,541,41,402,729,465,560,680,686,237,567,319,686,285,908,687,958,52,77,706,412,651,803,415,560,802,613,483,538,967,698,46,326,262,678,59,998,424,168,39,345,126,582,784,889,99,123,79,371,177,346,972,329,470,751,153,792,140,942,507,808,164,429,876,986,117,647,827,469,528,863,865,943,704,485,965,502,659,870,956,468,191,890,662,300,446,858,538,328,497,870,366,408,506,246,470,326,968,109,75,300,295,436,162,542,727,617,678,306,381,888,914,202,193,284,491,624,319,503,901,881,945,44,942,653,664,778,604,738,213,944,52,874,309,375,938,975,994,627,727,334,770,674,467,151,290,226,147,111,296,889,341,198,200,698,111,564,895,231,44,315,629,20,402,316,820,290,329,146,115,927,935,691,121,908,676,968,973,199,298,307,567,614,938,247,426,467,205,478,846,698,147,923,426,423,473,335,208,653,875,659,772,587,780,193,671,988,402,223,17,645,545,230,150,940,955,72,80,861,551,802,531,34,728,612,672,148,946,810,818,485,194,441,243,925,570,831,947,759,563,905,152,216,391,389,483,810,902,801,775,677,808,129,498,847,868,72,199,153,916,706,169,289,985,234,817,96,235,963,30,7,945,939,336,730,4,728,800,468,409,432,682,436,551,57,10,892,850,922,450,697,166,703,972,603,44,164,929,249,227,706,697,945,996,76,362,977,823,376,491,965,617,411,715,960,739,500,86,629,595,197,596,685,2,489,615,378,699,35,63,616,27,320,354,623,853,163,816,420,700,917,527,456,846,653,349,342,360,653,208", +"826,218,881,541,507,739,586,462,365,52,295,244,760,933,903,671,351,244,25,962,874,29,267,151,333,390,920,248,841,313,599,468,690,653,466,990,645,284,914,731,924,920,876,303,236,123,133,611,253,702,434,191,56,417,930,667,919,502,120,677,866,182,450,296,182,408,166,569,732,348,995,651,380,245,511,813,891,247,709,466,59,707,651,469,68,79,519,171,48,714,561,887,703,576,891,901,214,943,824,756,946,136,23,633,469,465,889,608,564,504,303,944,952,609,95,202,820,801,246,893,645,721,736,854,106,170,152,679,948,115,178,651,726,438,371,731,889,468,278,746,540,408,593,98,659,651,708,451,997,930,983,490,850,996,612,970,212,49,882,369,701,7,447,649,372,570,146,828,294,100,88,893,266,779,518,362,818,174,326,580,992,828,790,118,193,417,235,269,481,993,649,258,915,404,183,84,547,603,718,676,146,6,771,497,816,240,770,222,243,763,689,792,341,257,63,652,658,202,536,210,841,813,320,477,114,975,690,325,282,559,609,266,489,732,814,425,8,657,922,596,565,196,382,887,214,757,420,287,759,152,565,565,845,943,5,541,848,245,986,929,406,401,959,491,670,687,988,253,749,450,620,428,522,450,360,208,618,83,374,394,695,76,558,152,138,35,793,264,278,703,663,758,327,672,296,49,592,635,877,975,320,696,280,374,626,326,943,773,791,783,775,231,502,759,702,178,291,135,439,443,291,483,28,978,740,710,827,596,801,411,924,954,731,648,715,439,714,662,440,969,293,333,0,16,801,658,763,9,983,913,740,506,919,236,922,630,591,878,823,877,816,684,137,9,569,409,173,143,919,710,140,993,133,340,505,325,511,831,453,409,420,663,379,54,635,276,73,878,215,305,28,871,75,826,409,172,243,698,628,190,296,662,534,119,188,595,663,414,484,653,497,388,314,60,664,891,367,886,434,573,886,655,811,729,963,262,152,757,579,527,558,773,206,469,518,428,817,465,996,319,834,179,533,866,900,476,566,432,301,530,443,681,184,912,273,173,356,390,513,247,881,294,690,195,790,533,511,931,536,689,264,84,605,327,699,320,146,203,257,989,124,849,213,919,108,92,471,197,194,236,181,577,158,138,76,37,624,645,145,101,221,371,762,430,551,862,357,557,723,508,24,798,431,422,89,155,974,585,321,351,328,349,166,231,388,162,300,472,144,759,710,399,151,281,16,509,688,675,55,304,904,305,16,405,289,611,626,313,600,133,938,299,498,740,243,792,722,156,641,450,801,609,253,190,723,816,711,932,793,708,445,287,430,804,763,805,627,452,343,898,480,981,267,412,38,638,138,105,396,913,310,674,419,304,781,967,63,913,927,81,21,350,761,185,288,152,532,480,958,35,242,190,254,880,623,328,512,552,474,485,794,462,416,652,805,705,751,506,189,878,586,18,603,205,423,200,741,747,247,822,135,552,862,210,857,191,583,249,944,626,23,820,493,484,451,662,282,705,855,540,417,533,894,405,523,120,53,234,827,100,920,438,994,67,529,778,641,629,815,645,193,596,418,42,618,434,610,144,111,376,680,504,546,829,92,945,655,624,795,502,635,109,961,832,911,256,473,456,84,19,767,689,282,297,776,213,255,509,900,83,687,829,326,291,778,719,482,653,973,896,480,757,454,803,973,764,886,886,949,777,609,139,18,295,889,776,156,665,990,58,988,643,61,719,833,501,238,364,468,918,334,845,762,245,118,166,377,782,594,80,356,216,844,847,180,73,939,742,313,158,392,549,415,252,288,563,964,734,237,998,596,552,275,510,44,771,453,783,529,5,408,308,650,681,267,806,852,719,135,346,378,342,830,641,36,561,56,23,134,498,574,826,208,313,596,883,296,343,623,151,468,965,923,55,363,20,570,853,204,674,149,501,575,589,311,563,972,37,237,365,659,313,682,358,883,894,33,778,865,62,358,404,412,806,765,146,646,984,542,182,996,271,112,227,79,672,924,56,533,851,349,520,633,576,456,198,54,338,658,200,528,219,723,173,541,169,652,929,386,101,871,952,370,871,243,545,30,387,880,2,490,999,884,104,738,955,876,786,907,398,295,221,447,345,34,492,573,422,99,737,630,161,887,393,519,996,110,531,108,46,382,586,193,218,734,355,724,343,732,23,274,612,748,344,736,736,231,702,197,826,682,878,425,849,269,837,388,356,567,385,986,711,447,16,457,11,523,446,144,398,459,102,862,350,256,400,616,179,162,808,318,785,271,798,963,164,473,776,508,201", +"682,350,511,355,305,149,930,46,911,37,637,411,809,773,917,937,158,243,579,295,138,147,775,264,905,971,129,141,762,438,866,721,564,137,684,253,337,759,592,87,965,741,239,241,635,46,481,825,152,419,458,611,233,114,263,729,357,872,432,47,280,848,454,878,116,804,239,86,820,178,571,295,966,385,454,677,208,667,295,268,1000,626,641,194,16,543,278,327,468,414,733,402,112,125,784,620,435,901,886,435,657,289,630,611,700,944,787,878,422,149,855,304,459,308,818,956,735,296,636,195,545,895,991,872,878,485,838,382,371,926,950,975,12,862,807,301,765,587,321,130,390,173,394,768,941,559,60,333,452,748,272,867,711,705,944,554,753,342,197,27,51,25,626,883,818,193,425,823,215,825,84,232,592,114,502,677,535,120,886,897,873,686,671,666,769,6,117,421,747,977,82,684,435,747,802,73,138,878,718,13,51,100,711,355,516,691,674,66,502,297,488,66,932,924,178,681,344,963,765,186,341,699,515,375,569,883,939,35,529,999,273,716,779,315,280,386,453,106,753,22,476,467,427,800,964,970,586,396,47,428,682,252,361,427,641,153,214,732,756,84,54,952,447,149,811,86,682,379,871,608,146,212,960,674,144,156,308,718,505,295,30,639,859,956,19,510,295,723,790,955,453,692,385,754,60,182,555,257,944,228,909,462,654,889,614,216,511,113,510,539,933,102,252,689,296,96,371,386,798,705,927,825,935,668,295,451,409,982,9,320,781,907,905,494,509,212,348,819,279,430,796,936,16,0,947,743,742,67,593,605,623,635,454,577,921,595,637,946,765,268,483,719,588,570,838,646,552,53,298,786,412,135,230,826,782,796,73,373,766,126,745,687,287,916,404,298,255,946,580,965,600,31,96,188,5,726,219,749,645,928,134,113,597,128,672,455,375,929,537,863,889,123,969,787,36,733,747,127,587,800,989,203,165,774,332,143,787,64,194,885,505,224,298,480,319,635,487,623,317,609,675,735,234,72,670,448,223,59,665,923,836,71,863,238,621,931,358,256,440,455,330,392,118,283,232,242,100,838,761,17,138,715,224,814,496,931,847,742,319,198,998,88,414,547,598,776,919,396,74,946,330,378,152,357,840,302,570,125,376,998,659,872,806,235,330,331,705,599,766,227,453,68,170,920,413,365,599,26,40,609,364,91,724,70,104,365,715,359,42,10,424,466,638,369,287,154,922,126,465,997,127,811,331,996,977,441,261,816,79,704,402,170,185,941,355,478,795,382,307,719,567,70,925,545,298,832,709,395,645,402,413,665,977,429,321,899,977,882,416,666,941,259,931,244,276,461,712,703,948,612,630,197,25,595,68,151,679,556,596,755,197,391,676,998,735,792,730,565,175,307,773,412,342,327,209,429,784,725,828,714,851,873,246,619,598,363,615,912,637,579,940,138,119,552,262,89,779,296,73,453,622,742,599,725,848,448,308,175,859,40,761,163,235,702,643,189,930,847,187,44,66,952,95,625,7,936,232,552,915,838,284,344,915,76,614,540,154,258,723,541,343,486,248,182,12,317,102,996,945,713,102,165,89,944,482,508,418,495,662,110,442,604,732,426,145,400,230,940,907,125,212,196,627,821,550,920,672,952,491,833,151,272,208,101,228,769,812,154,225,36,22,357,236,470,333,273,681,221,220,613,900,266,483,743,741,611,516,545,323,985,800,888,189,654,736,739,619,878,681,476,345,26,170,1000,58,259,660,512,205,902,213,491,220,764,668,293,237,332,284,235,388,614,560,184,626,608,236,813,419,221,566,656,148,758,622,570,74,287,302,259,729,387,530,499,241,619,81,885,763,48,772,658,542,736,90,41,218,339,425,501,867,943,915,940,497,30,725,730,548,747,442,989,390,893,586,851,448,858,564,667,272,71,157,102,846,443,878,89,654,480,156,23,688,240,241,327,526,391,472,783,648,293,482,138,403,11,268,686,243,978,776,363,954,899,53,371,102,393,562,282,559,173,722,315,965,548,874,782,276,723,585,237,776,631,368,838,612,510,443,72,112,367,238,956,148,309,89,816,164,293,175,714,391,451,735,349,922,6,163,912,490,811,744,971,5,934,530,652,553,875,229,959,995,561,651,640,800,539,121,818,826,649,294,106,200,127,479,629,774,243,195,18,624,749,284,678,15,195,390,961,24,452,842,921,690,117,212,366,210,685,850,660,889,128,368,341,700,274,244,742,477,118,963,179,557,306,849,953,504,776,681,131,305,799,267,942,371,963,680,18", +"598,355,86,467,462,732,860,327,363,886,815,123,272,856,606,89,24,847,272,794,439,449,739,224,985,359,966,909,688,859,879,97,334,952,48,950,161,737,894,886,563,864,244,205,55,506,807,310,159,168,937,599,658,338,482,142,816,854,147,158,105,720,117,861,802,738,671,350,565,34,4,620,56,788,869,536,288,697,456,797,899,230,305,858,225,19,671,867,166,156,599,705,358,173,695,368,172,897,142,42,526,457,688,251,375,410,480,43,802,966,64,633,269,783,997,369,579,243,372,513,255,741,491,466,484,241,881,34,824,943,610,148,57,934,417,709,360,259,778,751,29,21,412,257,114,328,976,855,168,545,339,55,672,582,110,735,226,447,266,874,643,718,645,262,423,748,717,873,748,523,941,604,58,929,579,448,134,485,431,855,767,209,791,133,514,216,446,308,661,440,517,298,568,611,174,374,130,885,598,948,147,844,953,11,206,54,85,556,751,748,314,793,170,137,312,342,619,390,649,962,307,550,25,306,661,784,959,116,222,468,812,476,685,580,379,575,584,98,356,391,274,180,37,899,457,705,924,456,481,658,344,868,877,527,886,579,469,564,926,521,690,434,220,101,752,938,211,580,162,156,310,226,865,807,823,976,353,72,747,950,193,873,578,1000,953,502,993,574,978,453,582,813,34,472,985,50,978,229,320,298,952,274,314,510,240,594,678,672,478,896,564,677,148,487,451,368,314,44,648,539,904,618,927,777,832,87,410,728,435,770,864,709,666,703,200,662,126,522,175,196,132,619,801,947,0,620,111,197,137,359,422,53,34,690,138,856,998,458,70,99,142,75,672,175,711,991,890,767,26,640,216,988,550,611,688,739,531,217,788,311,214,630,220,427,352,745,225,151,504,84,812,687,505,689,225,223,955,889,963,205,259,673,398,608,636,256,544,194,895,900,793,349,595,412,566,268,902,144,815,515,174,41,310,485,71,879,209,68,984,732,537,166,625,383,586,715,172,885,323,964,888,305,936,346,640,52,129,886,645,222,415,506,17,298,486,352,125,279,465,156,640,269,179,934,570,775,442,803,716,963,793,32,623,991,112,797,84,620,296,76,115,737,372,788,150,862,610,38,382,823,725,400,989,462,746,372,334,226,347,72,678,331,407,5,630,933,415,729,68,287,883,90,963,751,828,72,718,257,300,839,513,386,846,350,977,467,708,435,267,448,812,856,833,716,754,961,786,766,726,444,528,449,927,844,946,573,915,654,262,823,19,608,499,895,683,501,445,190,257,512,639,256,447,591,86,868,658,945,351,902,190,882,12,299,543,30,91,454,370,311,921,527,602,153,363,924,71,434,738,750,177,646,395,94,399,379,176,13,405,129,19,326,920,653,6,115,168,727,458,850,980,198,448,4,737,771,112,596,496,533,468,93,559,222,753,968,899,857,150,913,295,169,105,899,616,438,134,688,679,460,595,256,979,622,159,373,617,866,486,295,2,284,524,720,384,244,195,194,872,569,955,659,887,617,400,660,207,674,769,38,52,280,237,755,50,915,297,763,588,954,381,912,493,347,650,742,471,927,439,73,67,128,694,645,796,647,227,620,636,433,213,507,167,28,318,533,962,944,150,536,945,840,375,278,966,330,111,127,984,138,205,697,33,965,398,636,399,726,546,618,447,205,949,605,619,263,945,354,125,412,776,675,944,825,125,682,126,269,169,668,240,169,843,272,177,405,110,832,702,788,910,152,150,609,436,126,946,296,375,605,266,505,553,426,228,114,315,914,517,938,960,104,551,373,225,876,775,749,879,374,521,412,318,410,671,306,937,532,341,258,222,533,489,571,749,111,837,901,218,697,150,535,547,258,30,975,367,265,718,719,292,609,911,422,284,615,295,28,479,158,410,496,948,251,959,569,407,141,543,209,336,326,205,527,797,891,625,928,292,290,820,888,211,198,475,908,677,804,731,823,316,992,320,185,198,98,487,894,334,58,633,41,501,771,708,609,297,534,869,18,716,527,594,768,588,21,242,857,76,135,257,278,149,602,324,219,505,125,350,604,879,248,677,987,19,556,683,928,32,203,505,264,816,491,33,451,861,87,328,845,146,385,852,452,424,10,867,356,579,593,550,614,141,382,438,269,376,173,707,784,444,599,743,157,640,515,903,618,800,310,829,424,827,884,926,207,482,895,957,666,465,640,975,784,301,319,691,54,524,177,256,671,584,758,932,941,410,729,679,913,616,478,943,276,351,318,212,57,36,22,917,285,567,343,430,421,751,653,591,154", +"900,533,105,478,897,597,162,46,539,981,756,105,102,796,585,567,649,36,366,1,552,396,345,627,62,313,949,754,780,956,586,884,511,697,929,167,741,241,67,421,968,414,111,440,703,470,137,224,629,311,179,495,67,276,316,361,329,918,101,61,495,671,138,213,59,134,481,794,513,493,342,572,979,374,973,131,427,834,615,989,828,492,583,409,474,531,282,238,352,393,981,43,763,830,15,893,476,218,84,831,871,680,438,2,609,889,318,199,759,640,976,842,86,630,400,561,878,894,68,608,716,248,780,579,948,10,875,904,922,748,144,420,144,682,861,90,712,22,559,352,774,74,889,967,414,357,901,216,921,647,848,915,551,379,158,669,684,678,228,113,118,192,930,849,722,663,630,190,991,844,869,95,73,917,317,617,654,837,938,925,950,135,404,255,462,662,279,894,110,685,142,992,446,286,76,36,479,885,139,48,872,126,78,464,847,198,162,250,462,581,368,609,527,448,533,291,170,784,942,601,848,103,442,672,316,164,595,21,306,640,569,738,291,64,886,22,168,220,904,258,889,696,339,549,687,815,629,403,755,915,373,952,835,234,128,837,993,758,935,260,95,886,435,669,121,722,840,206,420,616,472,935,75,628,799,676,733,497,796,90,494,574,546,162,759,629,750,948,321,946,56,589,842,477,308,894,716,298,871,180,221,710,679,737,765,663,176,712,944,961,583,911,631,910,971,837,828,9,781,806,246,227,665,386,414,734,400,228,832,999,529,577,53,6,695,658,50,63,727,204,734,544,658,743,620,0,894,397,422,705,954,921,322,307,520,654,619,161,594,769,712,590,918,825,945,787,505,486,839,87,427,112,405,997,191,142,450,736,317,632,177,913,819,9,218,78,942,468,858,163,707,567,806,650,367,383,577,496,941,375,543,822,528,182,772,685,356,815,87,608,671,313,815,712,924,975,421,852,766,745,257,590,459,233,770,621,259,65,70,788,813,740,911,893,433,873,390,393,327,353,158,986,72,789,363,182,17,859,795,978,803,41,14,171,361,452,546,24,113,671,526,894,785,564,636,890,233,98,631,768,397,732,107,575,332,485,216,511,563,213,300,973,234,771,899,178,186,356,399,962,299,332,789,527,627,790,399,955,108,915,77,201,618,615,854,212,119,883,704,305,122,716,518,35,757,229,842,231,11,237,864,567,600,553,970,680,547,330,865,767,443,257,467,310,644,97,479,135,577,965,978,935,618,904,231,514,244,716,125,192,679,113,826,493,290,703,761,287,109,248,752,895,713,968,62,979,795,725,854,513,991,436,602,860,624,444,430,715,240,308,804,766,612,672,963,488,619,427,235,192,635,201,602,42,944,96,464,108,119,631,69,708,101,30,423,108,113,356,529,962,746,66,928,127,570,513,714,595,260,577,420,628,958,473,800,317,618,262,984,289,668,713,246,69,394,190,803,466,128,593,361,900,45,680,304,618,945,568,42,522,575,618,832,551,771,286,629,379,797,116,891,243,340,123,314,956,859,127,355,140,565,549,229,348,735,824,665,523,941,246,206,63,242,103,693,487,225,836,606,545,557,184,303,732,409,359,870,231,485,594,998,129,855,583,785,312,56,480,192,893,513,992,937,67,954,854,782,700,514,911,156,643,209,828,414,340,877,140,98,905,266,722,146,22,758,111,278,678,690,798,773,441,254,566,498,500,622,501,78,587,141,605,301,906,580,954,599,995,289,379,833,532,206,557,222,212,598,832,858,435,361,500,884,401,339,495,461,595,344,815,107,895,980,514,243,369,997,541,498,585,957,420,736,200,102,216,611,969,992,278,156,989,584,416,416,640,473,435,272,156,506,626,193,863,112,381,664,518,806,205,383,269,707,663,304,585,279,72,200,668,807,733,655,47,944,781,327,49,575,995,137,670,868,112,90,145,85,758,285,308,743,816,856,713,542,984,263,821,71,140,511,161,156,359,399,505,869,250,770,7,110,602,890,897,924,108,596,341,896,251,361,73,125,376,976,411,49,995,195,881,518,421,753,523,36,612,88,298,217,892,481,213,790,847,54,982,513,25,782,162,42,968,429,331,377,708,511,97,334,422,756,889,627,254,144,768,890,780,734,564,517,714,667,237,456,87,376,178,299,470,625,65,363,115,749,599,407,803,554,311,821,270,790,693,780,201,414,938,369,64,66,146,219,336,993,715,643,578,937,271,589,452,431,417,297,641,975,441,191,3,843,532,532,205,831,371,966,289,524,828,803,975,35,987,393,932,767,796,76,88", +"239,870,262,787,623,236,509,1000,768,178,216,565,948,209,913,348,587,477,28,396,488,146,528,538,971,318,560,830,131,904,61,853,416,641,662,122,79,86,429,254,900,829,103,614,600,522,592,630,630,198,258,52,113,466,182,850,303,32,373,91,594,327,468,260,139,350,431,614,875,810,90,386,849,98,947,277,212,385,223,770,381,299,559,160,871,233,740,344,506,84,248,357,380,241,552,345,163,732,387,389,838,545,419,503,10,989,362,320,705,310,122,586,174,805,459,502,443,193,317,362,746,546,654,950,594,528,289,934,527,925,797,749,809,702,764,36,908,505,52,161,538,739,291,346,511,305,505,253,131,329,621,958,252,132,638,56,732,619,220,450,143,261,614,121,191,373,958,118,320,802,825,737,696,559,105,68,645,541,898,971,116,428,178,495,352,885,563,536,165,890,604,279,603,334,554,761,829,321,486,551,954,747,883,666,528,240,829,420,675,330,184,24,160,495,331,78,921,672,181,52,738,608,724,18,405,530,8,336,478,570,734,457,304,144,148,66,199,984,657,892,572,702,280,944,687,208,616,415,453,861,910,240,865,786,615,282,483,824,551,123,88,776,467,314,497,764,348,915,194,979,994,135,379,707,874,329,749,81,504,223,266,164,788,988,445,82,502,892,978,365,236,141,885,816,238,962,93,152,587,81,64,877,626,593,666,575,552,101,179,110,30,557,851,526,364,537,371,348,145,782,465,858,75,678,163,130,176,597,845,704,123,110,927,172,948,609,251,641,187,940,294,877,763,742,111,894,0,664,816,189,659,335,599,61,630,115,869,990,699,686,142,301,564,995,711,378,583,615,175,785,537,352,341,418,784,111,782,415,880,295,731,908,890,488,335,479,129,979,208,487,266,581,380,842,115,974,750,933,277,961,63,969,925,599,271,816,393,302,31,271,522,856,126,251,314,316,347,961,392,252,666,336,588,681,755,777,508,724,172,485,984,154,988,944,619,475,791,719,483,76,26,523,751,966,594,893,308,128,246,128,763,554,376,632,443,482,741,299,218,917,190,400,801,66,481,446,246,622,826,655,847,304,468,324,680,698,587,705,568,845,678,431,942,493,112,757,897,184,220,520,255,915,348,745,967,26,252,73,654,720,616,76,106,320,616,394,596,696,664,341,643,299,236,86,46,945,474,175,721,150,884,431,398,859,152,370,361,434,171,192,423,589,769,778,300,922,298,908,148,31,957,960,301,809,256,543,244,359,540,788,767,671,849,316,105,258,915,535,621,881,651,259,311,323,911,61,101,752,909,241,992,14,676,371,76,486,142,267,924,902,355,804,538,212,35,704,658,552,484,722,541,259,231,70,507,735,884,81,939,651,577,634,951,834,35,577,255,351,895,781,680,841,68,217,882,256,287,36,39,379,788,969,437,224,235,902,639,107,297,500,808,80,449,149,424,191,369,955,794,499,661,348,440,484,404,232,226,855,912,466,490,978,601,122,130,339,286,339,190,307,680,935,358,835,840,593,891,571,638,543,680,274,715,109,835,89,362,299,724,34,661,812,465,284,545,953,662,617,158,517,210,189,412,35,950,592,538,623,291,469,573,610,550,688,577,316,20,193,73,962,265,609,634,620,867,318,951,276,764,208,798,536,40,937,718,14,21,191,236,117,190,582,681,497,74,360,955,173,725,773,430,890,387,899,546,130,829,532,268,105,93,144,803,63,482,685,780,792,946,492,952,464,774,945,423,354,257,564,372,280,629,273,623,987,59,602,810,172,795,468,419,262,879,34,366,830,325,882,250,315,581,587,565,714,21,97,798,373,875,702,23,541,183,144,54,871,965,48,94,700,963,152,661,874,54,240,479,251,621,192,896,266,517,90,20,671,807,969,611,721,770,775,233,325,580,293,954,556,39,262,505,244,430,755,855,648,327,544,458,256,584,278,368,703,28,268,119,491,312,244,853,741,865,6,17,728,389,324,636,961,858,859,518,845,436,205,707,671,630,50,813,58,863,837,303,4,423,500,39,866,774,915,732,504,278,983,48,595,284,740,579,36,980,580,556,995,454,60,147,926,436,815,344,438,791,34,509,173,642,3,560,465,426,41,56,288,359,605,328,243,829,771,511,259,99,263,501,663,432,786,760,950,257,489,400,807,258,671,413,427,42,848,489,989,722,28,762,420,818,890,826,485,654,767,904,185,978,490,695,194,217,416,218,845,52,908,512,147,987,762,3,306,591,473,942,58,188,315,231,808,399,322,262,977,388,163,711,466,429,983", +"652,515,641,937,397,703,899,936,415,845,965,701,52,839,78,251,172,578,650,118,346,584,380,151,214,155,98,708,725,258,269,603,825,955,425,302,642,482,260,77,938,384,281,55,533,883,103,215,912,724,429,655,562,968,234,716,151,905,688,261,718,606,691,419,68,429,193,848,206,608,527,760,169,587,818,639,485,297,784,330,892,496,589,369,933,262,714,260,204,430,728,223,160,912,363,316,594,117,280,47,184,652,347,431,669,216,697,691,394,426,336,320,578,884,125,132,598,383,278,843,631,307,259,192,132,735,86,332,382,922,980,572,849,393,209,524,551,636,807,944,417,229,334,39,580,990,369,346,760,170,933,646,819,843,102,383,985,148,284,682,524,147,44,661,269,993,476,341,562,60,803,751,75,192,322,882,288,510,943,866,140,922,750,175,28,144,704,504,979,521,503,568,151,925,223,501,271,417,959,99,492,517,564,405,180,685,778,684,372,471,175,93,649,50,519,786,746,143,953,861,892,846,268,490,595,590,70,361,260,495,394,700,314,891,461,84,429,710,392,482,744,579,335,913,119,904,770,430,496,787,805,456,561,194,993,573,360,264,80,356,448,444,783,521,631,871,36,242,674,495,493,651,732,920,96,617,542,787,754,74,493,312,719,433,487,624,115,949,259,454,43,89,407,684,584,967,369,26,214,685,832,25,655,827,232,302,40,819,656,9,96,906,106,240,417,84,225,139,234,236,592,329,244,465,842,203,778,475,267,778,45,682,218,391,270,362,715,875,156,494,873,927,9,67,197,397,664,0,267,905,469,660,50,750,618,323,615,696,528,158,615,545,398,128,484,98,879,959,944,619,529,931,637,416,578,320,793,135,89,538,930,440,560,969,344,778,862,566,346,493,341,233,631,789,224,100,560,997,342,335,83,898,220,175,435,375,116,529,789,500,946,892,307,36,578,460,159,713,690,755,600,938,172,382,354,1000,807,6,528,943,611,17,408,226,762,184,394,930,971,570,224,179,259,665,689,43,67,680,914,124,686,993,403,651,561,519,336,23,572,199,439,51,9,603,669,574,334,12,847,383,906,604,875,854,776,778,693,172,405,586,917,129,790,962,879,861,764,375,369,66,841,686,975,513,745,767,304,97,111,865,75,31,150,510,956,265,64,216,607,506,910,40,513,867,181,4,109,973,194,368,98,139,244,825,324,482,577,788,809,953,425,155,585,39,892,92,748,914,675,505,992,405,546,702,732,820,584,794,734,517,61,306,820,140,470,983,59,697,728,802,151,829,666,818,204,515,513,54,231,583,706,651,899,959,913,395,58,808,867,55,787,598,496,158,480,246,984,182,468,696,400,100,649,15,940,159,23,283,221,489,262,122,372,526,682,842,499,750,96,974,488,729,368,2,802,10,361,866,464,704,372,343,902,873,536,77,562,434,625,301,573,25,721,792,453,18,190,500,398,840,220,996,218,163,856,297,554,816,493,328,809,374,139,890,409,455,154,158,896,838,70,397,465,645,693,236,311,268,292,322,697,772,827,871,183,586,156,800,588,48,126,153,991,288,19,789,301,594,128,550,902,591,76,608,499,450,207,641,29,214,6,55,240,256,777,939,185,294,33,781,735,894,531,879,496,653,448,42,637,99,827,229,64,360,303,255,555,853,95,334,501,17,942,67,65,956,919,115,450,403,197,20,65,197,427,849,488,188,555,948,228,115,768,780,796,918,618,5,726,111,415,248,270,398,228,754,854,906,771,821,884,72,474,689,27,317,922,191,166,653,987,651,352,684,82,851,959,508,964,921,86,71,597,404,155,618,198,429,917,147,938,760,926,386,896,351,551,912,160,912,581,512,667,672,362,211,93,826,160,849,225,556,709,182,183,194,179,856,344,200,347,991,72,47,985,506,869,316,934,399,591,331,937,627,945,958,812,687,277,138,452,98,5,963,430,812,486,263,243,54,973,845,727,17,618,807,372,194,747,585,150,258,464,263,329,773,166,245,833,371,228,113,143,552,934,432,773,27,20,358,218,532,953,472,361,311,707,234,400,183,105,894,221,922,806,985,385,240,616,309,99,739,518,961,738,959,753,24,923,661,288,570,119,148,891,607,532,157,234,902,610,23,44,652,36,7,981,537,323,115,502,395,226,422,418,128,306,631,797,378,613,323,31,846,54,768,440,196,200,71,500,235,812,258,728,398,76,333,315,352,72,989,134,181,708,555,975,382,564,642,835,438,977,370,203,621,347,282,937,350,726,599,355,723,235,329,367,295,766,592", +"367,757,977,241,247,633,464,412,102,796,396,256,325,188,516,360,110,211,613,371,451,740,628,169,530,102,81,795,798,917,926,295,150,221,96,487,227,99,989,631,774,535,858,713,699,70,263,725,989,516,692,52,154,91,262,516,744,754,848,674,732,453,264,369,62,600,95,166,837,668,364,456,117,758,517,529,904,929,458,264,889,962,309,710,687,805,68,853,730,520,190,278,959,948,789,668,292,538,598,963,636,581,143,506,686,779,680,419,242,40,731,740,286,60,976,121,387,994,775,267,216,88,161,405,177,72,521,117,218,508,384,845,802,653,831,213,488,795,863,506,104,418,321,694,998,968,680,955,867,664,288,849,786,98,512,375,808,26,289,97,334,275,781,696,409,469,940,770,608,832,56,695,228,404,320,738,439,994,386,322,562,481,409,611,550,480,73,62,288,976,193,366,244,495,865,84,686,116,889,315,172,527,840,837,314,875,810,455,659,374,846,626,972,262,350,58,661,769,471,684,456,440,190,748,184,282,4,539,721,608,905,898,587,195,267,187,116,619,648,231,911,52,616,428,993,692,275,797,177,634,813,239,239,816,830,132,464,416,883,327,267,226,202,832,734,266,823,538,910,712,954,853,926,192,878,27,648,840,415,462,238,694,181,475,633,649,983,778,332,1000,458,157,190,374,240,465,545,856,44,560,883,484,862,880,698,416,246,32,102,908,291,321,969,370,657,692,97,686,109,579,157,430,81,890,13,719,142,878,158,401,435,132,653,855,561,922,287,789,840,578,327,734,983,593,137,422,816,267,0,742,473,134,98,486,126,685,948,331,260,412,990,80,177,192,661,794,929,735,94,631,555,311,42,594,651,153,510,466,189,767,622,873,800,949,369,911,396,161,737,270,540,238,8,477,662,669,449,525,76,809,623,924,568,558,688,108,828,112,801,793,40,218,987,62,288,120,905,483,388,578,153,716,948,385,775,290,596,861,103,476,409,126,696,104,634,887,509,463,653,634,978,456,553,194,332,111,242,463,890,574,541,660,924,789,620,690,829,509,347,101,386,989,768,999,743,399,75,113,209,762,595,123,49,150,889,157,957,195,711,851,532,402,32,578,783,819,971,781,988,38,645,733,18,766,657,67,903,614,610,254,748,817,704,23,846,904,669,584,237,760,143,595,758,734,524,474,111,360,935,737,489,529,403,840,292,215,61,846,74,971,89,67,640,961,38,670,766,461,641,556,743,428,626,773,885,560,778,503,914,194,794,439,287,327,156,24,321,712,834,932,803,105,423,495,450,705,887,781,923,927,182,985,260,831,177,925,824,954,584,605,151,833,549,213,3,354,87,854,328,613,710,72,112,882,536,274,974,433,861,987,196,899,85,658,106,964,1000,2,481,210,433,32,789,239,129,907,214,921,499,118,74,788,686,794,172,974,566,478,61,373,113,986,486,192,561,684,577,219,486,542,195,664,814,502,357,296,850,805,9,781,661,148,888,540,592,374,706,21,946,146,597,608,515,252,735,968,199,254,466,197,243,872,793,136,296,678,658,987,519,48,713,112,748,55,680,100,333,448,653,897,984,261,504,520,102,905,638,628,825,135,221,617,628,678,720,166,217,286,775,378,386,26,655,530,727,864,349,851,89,657,77,871,724,458,907,449,674,870,998,644,576,24,803,181,673,512,89,519,570,87,13,393,562,472,436,970,974,788,534,650,380,56,132,431,460,914,13,379,487,545,893,598,957,749,411,628,613,445,544,150,227,817,720,145,659,324,123,473,850,996,500,294,502,987,451,305,322,792,233,847,635,473,496,93,425,986,171,657,348,769,434,980,890,623,533,60,308,159,491,56,898,653,681,750,762,369,260,162,25,749,509,858,349,645,444,426,545,209,87,430,355,229,332,465,930,41,993,477,992,653,826,960,462,206,403,546,591,414,333,906,258,949,407,598,130,183,163,522,523,837,998,273,817,560,920,18,11,718,320,25,882,325,622,175,953,506,626,596,212,119,952,89,244,506,486,947,865,189,333,727,1000,956,206,463,947,339,878,619,535,794,954,690,513,416,725,501,735,33,275,52,723,696,35,578,274,662,314,681,80,244,230,355,14,350,280,587,730,233,458,573,42,278,550,666,268,986,436,467,575,73,761,807,37,289,955,770,409,936,856,674,815,371,985,874,600,662,164,256,922,134,508,686,505,748,654,460,499,824,707,583,319,65,278,895,644,983,763,290,713,746,607,908,384,30,694,387,576,657,626,52,987,427,439,561,881,970,15,365,673,35", +"293,740,257,812,241,191,917,585,508,670,748,382,171,679,365,823,252,681,770,114,666,449,853,783,717,517,883,862,287,192,260,519,551,760,953,797,918,505,846,331,56,149,659,517,791,615,820,233,578,774,192,774,708,283,138,129,260,963,697,175,849,832,155,75,504,988,684,206,322,359,518,532,35,709,620,815,689,998,148,406,120,47,909,863,347,280,246,548,383,610,334,683,110,95,516,946,261,423,964,304,898,346,429,263,956,363,619,659,393,713,244,234,180,206,702,480,938,494,676,102,304,572,456,915,832,330,923,275,401,26,406,34,621,365,117,864,713,224,315,213,344,254,531,600,857,821,962,730,189,374,945,97,46,23,878,554,260,905,408,263,460,446,81,960,830,603,460,16,869,790,757,143,710,734,79,384,526,407,156,316,773,957,517,430,675,497,424,710,147,961,650,279,309,467,283,817,693,101,852,90,179,76,56,906,737,730,830,802,877,493,771,441,186,448,158,527,542,917,83,652,711,686,631,41,798,253,27,748,313,999,676,171,716,179,712,346,759,351,204,420,219,596,468,856,754,48,276,924,985,438,488,164,309,103,491,991,523,420,89,736,714,595,747,765,988,55,952,654,758,184,930,214,795,27,707,693,155,134,171,534,173,829,466,779,47,817,978,937,972,897,523,96,45,328,97,575,537,211,583,509,429,418,495,145,998,947,339,338,117,959,463,701,400,164,356,744,193,741,281,652,381,946,574,242,399,30,471,348,535,897,593,798,727,389,23,857,593,600,582,948,831,309,913,605,359,705,189,905,742,0,993,910,915,842,554,65,106,500,341,848,490,599,612,116,140,739,923,890,213,602,405,182,559,164,336,739,104,266,873,483,164,964,15,180,427,707,594,710,118,462,566,417,535,583,811,44,66,807,654,601,390,622,228,841,802,857,106,810,825,111,547,395,229,81,320,184,43,85,41,837,385,60,143,718,798,380,276,600,150,650,879,454,348,205,226,339,275,929,184,479,636,303,718,429,903,668,839,192,848,1000,964,293,564,288,841,28,262,827,899,577,451,750,285,975,213,283,103,275,888,283,567,785,732,56,859,535,813,331,740,324,594,949,998,891,617,893,571,748,206,992,737,205,43,919,8,216,580,210,969,90,585,70,41,417,266,756,88,915,422,817,1000,429,569,810,147,590,450,961,803,520,620,754,232,505,859,616,978,894,634,251,879,821,167,215,462,95,878,621,320,534,363,730,574,251,490,646,985,588,945,885,913,448,357,575,79,771,144,512,761,118,244,624,100,804,292,542,274,887,439,722,137,972,110,78,247,555,128,340,658,320,664,308,511,793,200,35,602,301,880,997,865,619,464,681,835,116,283,655,4,362,349,277,704,337,924,773,58,4,147,84,488,214,128,463,924,640,476,229,237,169,607,935,372,628,795,89,137,139,210,665,992,443,506,928,913,60,295,116,746,99,149,231,996,564,529,37,382,140,785,18,777,679,648,436,820,615,562,619,625,162,854,937,171,527,542,585,698,410,265,695,259,271,230,387,632,478,424,892,943,708,946,199,337,78,12,943,129,974,814,113,726,594,524,926,32,583,226,778,226,380,318,26,597,9,836,54,251,694,896,447,656,861,266,832,292,501,982,419,340,675,391,91,179,230,281,533,759,799,524,687,148,191,775,859,286,471,310,979,442,864,300,870,419,724,8,321,141,883,717,644,722,12,738,32,824,118,355,95,782,201,802,510,212,53,614,823,203,27,467,576,580,443,290,921,752,682,690,809,265,593,818,656,583,21,250,629,574,235,83,468,102,367,568,433,177,393,837,439,852,375,271,714,612,736,68,876,884,546,110,55,575,294,686,380,140,430,812,812,455,747,138,75,335,901,455,614,380,868,601,558,459,786,766,391,799,152,263,658,804,12,898,384,645,558,977,45,540,679,920,501,847,920,614,975,192,339,381,703,700,151,728,110,55,313,116,392,110,432,170,106,188,624,155,575,187,734,379,238,969,465,299,632,794,438,108,102,860,437,566,74,739,392,123,910,211,528,864,929,20,42,118,549,180,562,687,998,250,822,994,805,317,344,618,751,218,430,192,545,450,972,853,383,444,220,472,806,252,861,520,77,157,898,379,359,607,619,437,197,740,709,758,849,618,97,951,606,863,191,118,452,588,656,135,54,17,107,924,91,660,912,365,630,936,651,161,293,697,288,596,528,834,715,655,119,510,912,454,549,405,306,206,39,489,334,228,466,533,8,585,949,873,697,599,732,633,108,181,997,630,102", +"196,73,182,835,442,512,31,804,501,917,843,804,426,662,918,160,938,279,956,856,10,562,429,754,558,98,815,698,766,118,468,958,554,90,768,307,879,816,956,535,892,112,426,262,952,972,618,84,349,36,446,997,696,827,86,930,118,418,993,629,99,768,895,304,603,527,546,866,264,739,226,689,736,1000,756,852,931,79,487,66,897,974,43,966,611,843,732,573,35,238,504,609,951,208,554,698,484,563,265,320,218,428,445,210,849,463,673,762,30,873,800,742,339,311,631,410,486,888,542,680,947,69,345,579,109,87,145,837,425,413,470,492,868,719,921,636,722,672,814,35,313,456,453,328,537,771,879,19,171,173,515,130,410,540,617,723,221,579,757,629,991,134,922,274,936,890,603,932,656,51,656,29,772,472,195,145,792,863,595,372,750,939,429,279,216,542,493,269,538,146,874,810,29,969,382,280,944,768,473,30,562,751,764,216,268,318,397,809,723,596,869,301,965,94,31,931,475,284,579,956,817,471,499,2,26,508,147,893,884,754,71,212,555,854,281,492,777,169,868,542,681,284,518,380,469,225,427,576,472,985,618,252,832,225,759,204,680,9,453,343,657,740,992,916,152,192,990,952,765,111,641,648,352,193,490,156,323,313,689,833,804,721,190,544,782,404,771,269,441,291,295,695,873,164,522,359,453,462,67,16,512,903,154,764,802,883,673,797,520,714,311,332,888,738,502,99,176,326,564,565,574,515,225,624,960,393,899,930,766,678,572,713,365,909,215,62,200,472,108,616,442,927,740,623,422,954,659,469,473,993,0,841,306,390,97,777,25,255,121,30,230,808,668,881,969,909,889,65,441,367,362,745,804,715,929,255,346,379,126,650,498,53,986,153,207,876,875,751,101,326,860,730,241,966,558,799,256,691,511,563,989,844,802,248,642,265,44,266,598,517,256,22,398,716,245,990,34,282,822,742,891,42,606,260,14,222,895,33,578,144,983,981,979,951,751,747,21,157,35,286,699,855,783,935,404,875,578,301,943,940,841,714,914,806,274,46,693,79,787,189,41,461,154,885,479,788,126,492,845,223,262,453,594,217,837,729,597,2,108,435,885,251,654,235,919,569,129,699,831,341,101,895,642,612,327,231,22,269,684,399,476,279,14,956,829,325,661,443,747,852,529,849,423,626,813,85,804,738,393,365,889,750,268,444,909,17,427,800,779,319,44,852,340,582,696,715,996,370,916,721,882,718,176,889,398,781,776,425,499,226,646,52,523,21,587,622,263,40,644,574,558,102,977,806,930,473,256,121,986,456,526,653,218,636,728,383,236,72,419,911,688,970,731,368,375,874,864,910,216,766,938,514,845,167,272,219,255,327,464,616,867,425,56,532,964,707,763,44,866,590,453,515,962,43,442,541,811,370,272,896,232,832,65,705,905,279,490,330,417,447,412,500,530,579,387,788,811,343,875,886,237,759,703,606,205,50,959,761,408,716,292,315,952,995,62,563,29,594,236,878,306,432,798,311,548,621,921,951,677,202,628,709,803,979,438,652,951,613,563,772,9,49,310,860,895,510,103,11,872,698,233,972,530,87,439,29,618,297,973,614,855,135,445,469,966,855,806,914,644,27,689,725,531,679,877,311,893,431,660,323,18,731,764,518,380,5,88,217,793,717,275,629,934,678,251,967,952,857,230,372,939,958,560,90,21,32,636,832,488,731,472,662,60,386,86,345,973,927,617,960,30,742,328,770,862,421,876,201,874,720,547,435,230,972,518,117,317,624,235,783,55,898,738,62,326,761,797,829,141,158,93,523,859,510,340,439,96,862,448,527,791,91,103,260,798,884,390,645,94,861,565,793,297,719,558,766,562,727,978,288,691,594,101,680,944,443,83,244,113,464,891,245,715,382,774,550,378,123,356,4,68,315,525,833,62,529,689,602,560,545,365,502,61,282,540,960,667,74,191,536,146,30,840,168,893,601,319,582,414,484,631,32,667,280,10,641,40,816,192,941,351,579,439,198,6,749,317,677,457,438,875,360,110,162,979,606,638,95,424,32,518,509,966,412,980,999,305,650,942,108,72,733,671,263,409,598,488,531,299,758,181,887,511,626,157,346,57,326,103,482,961,974,839,870,980,720,966,32,181,49,943,790,915,283,355,747,982,831,176,608,473,437,560,371,497,296,874,851,327,502,563,329,169,774,835,789,596,307,393,570,373,615,236,150,57,287,770,276,361,265,230,815,778,889,947,393,296,612,440,246,629,616,276,187,312,412,276,585,599,83", +"868,837,126,148,888,569,743,956,509,277,896,444,986,768,323,509,812,34,745,463,126,383,192,731,764,238,103,602,115,809,713,344,205,678,50,634,816,212,750,364,960,790,331,398,800,501,84,84,299,444,894,469,743,445,760,624,100,291,106,166,398,926,593,460,8,827,507,403,400,857,626,773,702,402,526,552,886,824,990,562,711,728,643,12,118,179,330,288,575,67,504,814,736,652,669,481,391,261,234,284,81,210,19,81,939,72,550,190,614,185,433,504,751,606,947,296,619,899,666,197,727,336,369,282,37,560,599,249,751,389,299,550,399,777,33,131,443,443,200,909,249,989,234,38,343,268,594,833,872,880,806,836,605,468,745,214,523,739,377,927,251,785,419,203,634,804,681,464,270,19,364,841,445,35,269,403,290,16,109,586,700,913,158,333,776,222,103,726,891,668,609,650,845,506,827,578,979,661,531,839,304,477,303,348,664,690,123,555,298,851,232,98,31,280,461,31,387,906,535,355,990,846,858,26,229,815,215,887,230,274,40,551,675,642,279,39,79,928,574,96,682,508,292,720,355,208,144,183,93,586,415,493,581,985,82,139,500,484,906,954,821,11,449,526,380,785,466,708,428,56,230,431,633,667,576,705,377,177,684,240,159,606,891,666,931,534,341,525,213,669,367,817,239,73,55,54,566,875,700,87,891,994,433,357,207,653,879,445,875,128,750,968,275,136,852,849,365,45,817,770,561,130,307,629,868,107,819,559,600,325,284,335,545,127,210,587,313,636,951,608,466,157,506,635,53,921,335,660,134,910,841,0,414,749,343,307,867,366,246,784,260,2,740,480,988,42,113,494,569,474,643,791,820,873,605,771,673,253,96,604,879,777,702,148,63,498,810,215,884,791,574,371,888,27,402,338,646,151,996,101,490,302,685,440,64,831,418,838,293,306,177,881,939,321,304,656,530,470,291,138,269,314,832,338,344,762,529,116,261,438,339,750,842,352,263,130,434,807,439,765,212,552,220,789,768,370,481,687,633,469,955,453,292,819,357,376,930,749,465,232,972,839,871,886,84,135,812,672,281,704,236,237,823,507,638,311,876,189,588,802,374,105,88,817,754,786,467,516,756,432,792,750,927,844,702,421,460,387,116,537,373,19,510,791,329,917,914,807,160,811,234,978,401,211,292,620,576,41,207,447,441,93,964,409,105,66,906,224,826,391,788,237,515,10,456,811,664,430,955,739,141,292,313,380,58,123,627,639,648,292,203,782,689,154,53,48,938,231,404,411,982,685,598,803,408,200,272,51,910,956,646,105,739,700,205,113,8,958,995,418,534,235,267,201,829,309,143,806,237,899,90,732,456,950,671,819,33,356,839,105,208,293,647,519,886,774,85,237,968,527,230,935,451,728,405,854,440,791,40,738,103,679,295,725,327,206,836,619,851,327,941,931,542,970,399,281,990,217,517,470,705,220,976,200,854,886,700,881,105,610,997,114,744,546,806,848,658,684,1000,755,730,467,397,1000,212,268,926,268,657,381,177,338,51,138,107,498,20,495,535,925,283,463,133,542,878,993,974,595,951,971,743,128,314,73,494,207,465,751,22,819,173,886,882,238,891,305,162,932,182,604,773,65,932,682,670,265,966,926,495,489,917,98,2,361,707,837,624,868,88,849,144,823,92,313,242,672,623,889,260,967,263,672,200,106,719,848,88,83,915,7,202,801,44,102,194,508,230,558,718,739,451,780,182,480,908,969,144,236,703,203,80,171,436,175,360,729,891,527,768,830,653,152,124,691,804,222,920,483,322,983,841,13,742,898,189,201,288,573,148,378,214,673,714,221,789,477,962,545,429,610,555,958,237,987,936,221,744,103,159,669,279,934,613,482,527,198,783,786,335,611,78,554,508,562,429,129,363,408,873,216,648,405,460,665,789,20,569,301,858,593,536,493,675,999,828,692,374,360,584,117,333,831,238,879,903,889,65,494,659,526,532,493,484,457,318,166,947,843,542,627,694,91,398,188,295,51,598,214,149,636,819,610,608,699,609,160,412,890,777,189,15,642,366,370,673,595,481,834,934,850,839,371,888,703,656,631,249,530,553,46,869,114,258,796,549,601,946,137,800,478,432,52,451,33,332,974,146,452,406,814,373,736,500,851,764,463,3,76,269,426,75,374,758,533,971,185,485,621,281,715,639,629,542,673,409,633,691,689,885,669,897,142,604,591,688,877,508,873,335,856,818,271,666,462,216,805,747,256,103,850,999,971,42,301,873,428,501,180,740,696", +"18,600,672,453,513,328,275,239,624,905,953,503,253,161,623,618,137,303,353,70,341,940,291,63,955,888,493,616,46,524,845,625,891,421,600,310,210,143,138,285,807,466,234,974,945,869,799,18,65,272,527,134,44,324,528,77,929,75,502,459,393,196,464,952,931,279,116,805,498,965,682,450,841,586,446,946,462,442,641,451,718,201,66,838,894,702,339,886,326,752,934,608,456,86,369,520,883,877,963,343,446,846,915,43,765,427,266,17,309,636,387,555,153,889,847,596,269,954,75,674,304,951,700,100,312,812,200,534,953,867,115,950,359,157,137,602,477,992,799,556,107,46,861,122,681,554,528,865,675,616,423,697,791,420,967,834,827,370,102,332,54,213,277,441,27,434,24,62,216,325,132,298,365,521,62,992,674,567,46,761,746,711,444,318,763,288,989,536,498,644,432,939,954,811,356,984,75,843,198,653,501,301,418,887,123,736,478,111,842,218,877,282,918,556,900,608,874,331,783,68,685,296,290,934,910,875,879,688,415,936,423,83,359,213,157,33,559,94,106,95,307,176,739,930,908,467,728,224,868,375,742,248,668,863,439,996,418,457,64,312,940,580,583,566,138,866,206,685,188,769,190,793,100,474,812,579,212,13,429,226,553,395,938,496,431,497,309,442,638,857,254,352,887,253,585,494,190,712,856,773,194,413,325,971,916,526,822,563,248,531,698,78,753,908,313,791,383,628,157,569,254,952,221,328,558,147,505,592,649,196,942,479,472,561,16,571,32,533,944,802,961,124,919,454,34,322,599,50,98,915,306,414,0,631,157,172,955,710,109,159,480,652,266,151,664,155,940,750,627,228,937,287,52,107,184,311,443,240,631,245,81,327,81,492,81,706,19,477,702,715,167,545,93,910,933,469,569,273,510,757,200,862,671,546,320,36,938,459,559,613,442,618,839,919,153,232,492,904,964,900,633,13,871,74,573,550,209,57,117,394,153,553,995,105,177,752,860,630,772,735,860,948,242,239,641,382,404,542,126,222,160,479,436,665,194,632,261,460,562,264,69,801,183,454,351,876,634,740,78,6,652,605,964,258,480,952,190,986,914,186,865,922,475,108,191,249,355,873,619,439,999,961,431,216,865,326,24,849,101,575,749,126,648,456,949,848,106,190,332,673,625,293,26,995,158,989,59,347,928,468,262,7,428,426,721,70,886,126,515,659,272,862,480,91,497,10,834,780,218,801,696,266,688,29,734,586,32,351,343,671,778,739,753,870,278,178,588,915,343,985,905,36,180,917,706,571,864,902,181,326,486,977,928,941,48,84,847,800,236,211,139,22,411,946,732,794,785,32,675,685,942,687,851,161,225,243,421,766,78,13,768,885,382,549,608,332,550,602,842,135,569,760,122,736,627,285,427,690,316,482,513,10,780,282,784,668,354,66,557,363,905,726,576,981,98,179,186,316,282,733,591,241,834,165,421,16,234,868,995,458,37,172,404,436,936,480,659,945,448,869,148,392,103,461,228,160,884,130,378,401,464,251,659,657,961,638,441,396,626,453,784,280,512,915,137,546,325,330,611,632,419,299,508,959,98,902,312,177,869,134,391,879,673,817,715,594,904,171,208,924,838,83,276,709,413,621,925,581,242,934,782,465,653,634,323,205,694,112,916,978,192,678,915,422,812,377,236,632,403,492,698,516,770,233,919,640,509,890,562,82,548,322,882,472,661,736,100,549,559,700,447,473,523,958,891,962,751,9,655,339,675,240,480,544,980,644,190,831,290,252,290,467,281,622,305,305,469,559,136,13,390,497,539,878,466,499,648,415,989,346,751,92,581,284,610,768,486,964,846,272,636,177,504,463,495,928,925,41,795,33,475,373,847,633,870,949,735,953,66,402,751,806,637,746,575,714,32,183,251,116,404,838,807,748,964,357,437,381,660,650,283,117,515,878,991,671,294,509,677,719,455,841,794,607,667,396,544,371,581,507,118,223,484,367,442,763,982,189,856,560,548,358,842,346,629,426,384,538,791,208,812,917,122,480,634,573,966,848,500,519,149,868,892,901,359,122,579,440,754,877,148,655,905,668,308,301,719,530,312,269,114,918,584,572,482,609,649,67,265,685,255,393,188,18,661,414,696,907,3,820,147,799,525,424,365,477,352,472,453,752,976,526,968,394,802,351,125,900,680,514,928,634,867,537,484,35,180,67,784,670,65,61,448,861,709,767,58,436,518,352,359,538,838,101,276,866,393,541,116,304,449,505,833,280,633,467,411,712,244,522", +"555,762,693,881,754,903,381,61,812,449,608,406,884,566,901,345,790,268,303,707,793,506,428,423,940,284,53,514,664,157,394,252,258,426,806,558,804,949,327,598,262,975,693,607,377,404,557,252,976,943,182,92,898,676,744,113,643,940,332,459,240,928,747,273,549,197,370,638,500,886,864,627,111,598,16,487,752,912,50,806,843,522,561,493,830,869,241,184,123,958,991,256,948,227,787,43,775,910,557,966,956,878,28,214,202,211,115,6,701,349,658,780,456,967,188,336,674,856,60,46,869,638,608,350,402,345,275,51,673,12,857,355,698,898,613,702,615,615,643,174,946,966,90,634,826,510,295,635,164,693,343,733,590,797,332,959,528,543,885,260,636,532,736,164,677,351,695,754,793,995,229,309,993,79,65,347,259,582,396,908,746,3,129,286,795,246,146,119,742,796,288,583,760,61,750,458,306,119,822,420,845,925,505,14,586,827,265,416,669,649,134,767,243,976,643,843,6,325,796,760,185,720,690,407,461,868,797,863,316,950,73,65,153,507,615,784,902,958,249,54,175,436,327,819,399,247,228,208,352,761,563,343,326,207,175,406,956,894,505,884,767,340,773,934,796,344,830,893,824,88,643,384,197,511,58,646,57,390,423,222,593,767,213,469,420,698,506,579,299,357,690,938,25,141,751,49,930,676,115,593,182,950,429,700,203,768,339,496,355,844,334,675,106,140,711,681,751,395,70,615,325,404,689,562,61,936,625,484,392,915,461,304,715,204,865,798,171,361,709,10,242,428,236,577,690,307,61,750,486,842,390,749,631,0,73,574,388,291,90,718,210,74,448,922,648,588,549,702,876,485,742,844,737,907,828,123,864,894,46,940,926,827,500,380,437,937,436,249,508,356,264,416,164,684,506,357,319,255,725,151,909,62,756,512,169,471,762,294,595,181,713,964,578,393,976,924,403,470,859,665,837,300,128,674,77,848,906,749,729,756,330,156,494,330,755,829,595,962,186,76,940,789,792,646,373,265,32,479,433,45,903,720,349,872,561,565,189,116,998,294,291,482,42,127,117,347,969,181,897,851,635,990,551,559,24,337,760,766,790,512,148,388,87,219,533,726,946,193,851,453,208,691,945,649,970,508,225,808,290,171,921,733,415,886,580,244,697,259,17,313,784,414,305,309,542,965,340,651,659,431,90,71,81,752,262,840,300,503,492,966,692,695,705,401,597,766,254,983,114,767,406,862,980,120,59,549,541,696,247,437,190,640,536,732,626,689,200,28,53,549,50,648,293,409,774,571,134,525,446,549,944,646,825,569,834,345,534,16,535,785,153,967,531,767,964,487,271,958,981,788,384,778,754,616,512,842,498,828,439,549,347,227,964,991,858,915,9,866,758,602,921,301,76,239,367,905,446,183,329,563,657,541,886,192,837,518,491,881,802,707,621,826,592,3,963,278,361,247,794,950,583,53,406,20,754,786,763,536,312,115,877,276,771,517,222,214,130,156,664,594,7,738,660,778,205,398,204,645,650,899,519,573,309,400,175,44,986,826,149,146,723,232,440,622,524,55,857,103,545,903,709,977,502,605,344,71,706,542,774,936,660,729,231,276,695,293,1000,609,408,948,104,642,433,15,972,62,729,256,744,46,6,17,157,675,992,25,552,337,527,905,267,86,833,541,837,622,97,166,335,443,869,784,76,535,137,151,182,860,595,106,887,97,338,10,435,886,643,847,980,547,735,270,757,115,611,943,175,658,581,780,917,300,519,664,73,168,236,521,262,263,881,58,109,883,112,442,4,954,80,661,181,546,118,685,183,81,671,339,718,382,347,882,738,642,929,35,923,249,553,743,96,835,887,644,304,892,206,36,427,241,26,292,717,703,488,938,770,799,745,641,268,638,508,998,69,158,92,613,970,145,868,939,924,71,981,177,273,676,725,392,624,918,48,422,508,684,449,674,173,563,465,734,979,811,731,431,49,155,57,661,936,100,587,982,309,670,420,832,343,64,449,538,423,278,398,913,15,878,50,877,411,636,483,972,284,550,142,746,959,640,759,895,421,611,949,108,446,994,671,687,606,646,238,444,348,831,304,511,610,133,123,620,432,398,498,631,388,192,547,157,652,32,91,664,689,191,540,209,900,617,255,268,947,177,31,964,616,132,956,188,762,823,17,998,807,849,798,906,99,73,267,245,740,229,594,739,424,615,145,560,474,860,252,311,675,458,175,711,845,251,899,542,632,619,655,407,879,692,852,644,144,93,989,196,713,397,597,547,645,215", +"746,337,864,774,614,32,874,384,288,777,7,877,52,554,566,147,77,165,182,533,422,583,804,816,735,628,764,528,509,912,651,297,140,471,449,64,360,549,39,120,663,898,218,928,615,331,194,399,58,157,691,666,414,274,443,768,639,845,399,580,575,889,414,519,663,543,301,753,558,335,737,302,114,831,421,368,492,322,391,500,633,268,789,89,122,951,93,105,576,633,780,815,851,552,407,531,654,908,202,219,897,940,83,364,171,871,781,772,999,76,717,509,878,712,45,917,505,18,260,662,263,432,694,543,480,334,743,109,36,536,770,944,346,217,706,517,129,6,769,873,598,600,375,634,544,311,389,380,293,48,460,619,696,107,110,6,478,64,211,382,973,55,289,293,565,575,696,254,14,811,345,355,733,938,786,96,167,92,750,127,280,842,194,410,982,406,5,406,232,929,621,186,707,799,512,682,728,669,788,646,456,262,59,164,483,783,143,902,710,711,404,768,393,526,828,175,672,244,440,410,789,877,252,409,525,7,210,690,580,370,563,153,890,151,536,727,610,211,857,690,247,770,459,584,86,917,604,402,354,812,785,15,654,860,549,231,970,923,544,482,554,472,760,858,979,102,663,689,133,378,263,841,882,144,562,673,562,149,541,431,46,215,667,616,474,770,238,849,68,604,666,112,128,873,955,524,969,558,268,345,357,12,805,155,284,551,487,294,439,214,907,598,165,181,293,365,172,278,899,700,31,332,527,459,600,822,597,653,528,978,319,321,405,451,133,580,859,984,280,244,860,942,922,921,138,520,630,618,126,554,97,343,157,73,0,33,849,675,66,952,204,733,315,618,953,925,414,317,927,977,124,302,690,933,169,91,975,408,671,457,437,145,908,626,869,690,891,80,761,944,938,4,186,851,231,797,70,119,394,646,765,994,557,124,681,667,684,737,939,589,242,130,808,218,329,273,839,703,863,235,279,738,976,422,736,928,379,702,120,694,802,41,247,38,197,920,264,241,566,410,153,784,295,239,43,970,765,279,535,942,354,410,693,991,934,94,952,996,671,586,788,489,654,40,659,4,448,622,568,176,386,232,816,267,765,925,14,517,269,198,410,876,259,72,861,521,506,204,513,564,608,508,230,468,581,205,257,69,234,351,255,588,362,953,78,31,996,265,944,330,721,353,575,349,86,655,400,587,502,678,420,664,243,127,984,832,166,528,205,120,993,538,815,800,519,188,983,646,370,102,324,646,82,448,64,279,404,148,447,15,859,741,323,490,279,194,427,597,819,365,389,284,400,953,105,703,720,333,682,627,51,350,311,117,71,893,278,568,842,773,715,515,996,813,960,520,648,532,948,458,222,103,840,854,766,255,779,744,772,97,911,149,54,500,456,759,636,24,129,521,728,991,858,727,494,525,968,981,422,602,126,717,743,88,767,318,441,590,420,467,541,86,336,277,567,527,462,609,620,304,114,882,363,970,532,831,247,198,191,353,302,553,598,311,836,343,933,491,382,504,177,749,630,617,596,351,668,74,159,801,789,552,200,180,840,950,648,287,508,218,684,858,791,23,942,413,127,635,310,819,870,473,823,792,133,306,863,912,948,588,874,850,255,971,996,936,83,43,825,10,111,454,717,710,381,402,669,597,332,724,320,13,706,193,699,232,855,21,406,660,379,851,86,952,566,776,766,125,238,386,414,547,474,894,703,589,802,932,367,970,949,413,269,86,824,451,672,473,393,97,97,192,574,69,512,405,735,338,154,213,890,402,695,978,359,461,300,47,652,277,5,219,776,138,578,127,945,102,954,659,369,893,268,907,582,952,926,743,725,544,472,310,873,194,57,761,463,908,52,166,550,736,186,124,672,960,602,786,290,742,674,74,718,690,198,91,66,63,937,886,507,601,897,367,170,747,655,199,52,504,973,727,547,481,552,404,457,389,572,448,332,457,958,144,899,240,20,273,455,850,487,249,161,388,90,153,140,907,232,394,525,52,612,360,707,987,483,232,491,652,934,94,174,42,419,289,214,573,148,180,524,224,454,41,981,809,998,912,625,705,679,117,870,427,191,355,416,183,49,936,898,538,856,158,414,859,577,140,915,320,259,570,635,423,48,116,419,955,146,896,988,495,915,213,227,855,581,785,994,542,324,599,421,718,863,62,609,578,60,744,480,778,161,884,646,995,70,534,761,783,889,433,982,110,896,902,867,428,466,610,958,511,626,689,710,502,505,193,867,576,672,423,156,295,615,33,89,457,244,846,948,836,404,588,112,953,864,455,16,404", +"142,555,252,126,277,657,906,489,262,206,311,729,651,647,953,788,499,867,874,213,994,362,561,616,337,212,188,624,882,268,806,619,545,996,974,621,986,42,756,612,172,855,873,755,740,689,527,304,69,391,728,516,87,885,565,254,428,524,699,621,14,463,481,290,886,7,831,983,218,912,31,991,302,895,346,440,268,283,349,84,424,550,550,369,459,204,700,321,318,9,934,496,433,685,161,311,827,349,815,311,443,457,417,183,68,483,366,849,862,234,8,677,389,906,206,816,256,293,962,249,63,773,829,140,696,889,270,208,659,561,758,554,155,346,584,256,912,107,392,743,509,74,729,828,176,117,889,501,33,882,147,126,326,847,704,765,736,224,642,190,655,660,456,492,982,398,124,521,366,772,764,84,85,254,559,571,432,728,388,262,300,965,308,138,762,855,281,408,288,109,601,49,879,240,155,93,901,352,370,19,643,772,206,83,476,958,190,408,635,180,510,972,590,896,183,458,536,934,875,939,729,468,160,869,187,18,823,296,646,901,176,86,858,340,266,130,747,456,537,228,903,270,654,917,875,422,206,900,308,746,487,58,180,308,650,154,20,90,425,266,864,482,64,147,796,856,410,678,992,775,930,952,87,164,866,183,778,232,398,179,242,398,409,488,103,34,324,399,836,769,264,297,331,503,4,736,400,960,323,497,325,285,239,816,393,343,161,873,772,589,218,354,437,481,105,436,144,566,217,972,324,30,678,952,803,754,548,525,428,56,767,57,611,54,815,192,216,642,492,630,59,6,630,595,856,654,115,323,685,65,777,307,172,574,33,0,494,168,816,590,708,379,714,560,630,662,473,743,120,357,770,959,156,693,545,489,67,452,787,796,116,96,336,141,915,190,525,73,404,472,280,741,728,460,53,938,764,563,803,600,514,206,312,471,959,886,50,849,14,985,872,584,131,619,620,464,492,827,524,524,199,38,60,441,695,341,975,686,706,588,576,693,896,314,883,916,772,814,73,208,352,886,894,889,766,702,410,505,457,987,256,635,762,574,273,493,818,450,762,447,790,618,916,792,339,203,489,205,999,39,416,397,492,649,398,284,245,250,592,261,516,272,873,919,472,223,567,390,420,571,196,140,981,789,177,177,419,106,409,929,286,444,109,298,814,566,496,870,813,976,546,486,442,680,60,924,532,988,809,326,187,787,649,50,296,344,920,703,476,647,789,780,153,135,104,708,905,655,605,344,217,581,679,633,950,657,124,812,531,123,899,585,348,232,38,562,86,701,225,106,942,217,330,727,891,283,315,216,762,522,642,282,62,477,59,240,894,994,128,928,8,404,309,661,718,323,716,784,125,468,213,796,859,117,935,835,687,583,623,398,640,155,633,405,213,129,639,813,215,64,940,145,151,934,403,560,790,570,3,613,973,138,71,331,921,240,151,429,439,529,265,846,502,722,412,146,416,509,969,309,938,400,821,343,790,843,719,53,57,883,396,917,573,428,998,704,989,662,144,148,730,561,855,562,672,70,68,457,464,179,244,71,262,474,251,373,114,917,327,709,505,180,257,454,963,67,18,11,586,386,97,224,440,524,632,633,793,693,454,721,68,88,242,906,344,94,567,318,459,703,631,382,297,146,261,662,629,244,733,561,842,329,622,91,457,544,591,898,362,191,261,417,675,301,209,651,533,382,976,909,685,563,69,690,524,307,169,918,286,293,338,793,427,628,902,263,52,259,970,37,794,137,664,174,504,88,617,131,723,354,989,21,615,67,729,462,322,232,733,607,963,628,270,551,644,344,860,979,753,726,175,640,906,573,334,284,65,35,863,14,749,114,149,210,727,686,220,469,763,120,165,375,373,231,808,122,264,867,859,877,551,348,995,653,944,42,42,282,62,588,184,625,555,820,276,982,900,146,849,758,897,609,975,6,210,930,928,438,710,364,876,832,10,184,558,737,843,148,6,144,809,306,524,536,998,527,137,384,231,152,405,703,96,981,162,113,852,750,360,816,243,166,957,584,667,163,629,960,704,819,664,482,481,958,556,932,303,35,172,254,458,63,921,277,65,697,824,569,478,241,343,787,711,489,719,47,496,185,632,932,359,289,728,698,331,149,773,828,92,24,1,206,408,882,553,971,166,181,889,537,701,789,203,184,872,502,49,754,690,413,987,35,952,533,295,891,428,661,633,538,884,913,996,527,551,557,167,659,906,804,635,290,972,338,149,673,208,392,902,35,568,729,579,877,625,764,450,172,872,1000,993,807,400,569,201,664,874,419,146,315", +"170,950,424,782,764,890,921,226,73,819,690,542,725,267,59,767,26,503,824,964,782,837,797,963,205,860,935,480,310,627,552,412,402,570,935,113,177,611,643,782,888,179,341,628,849,719,872,524,262,454,752,470,412,448,845,550,726,865,258,990,447,558,389,311,730,223,780,800,221,247,682,857,102,976,150,707,945,459,640,225,566,576,873,360,865,171,733,206,174,178,667,545,756,299,241,666,606,263,83,409,160,76,657,51,856,62,105,903,71,903,227,386,927,55,718,919,705,476,910,166,671,299,165,835,858,831,833,572,30,29,31,92,847,381,111,444,281,523,879,277,656,376,578,344,696,349,272,488,115,610,76,207,302,105,801,947,322,479,696,120,309,745,734,794,963,839,799,501,576,13,155,264,240,974,633,775,616,905,446,603,986,975,579,912,637,758,159,644,900,84,716,696,287,144,971,280,826,748,224,846,941,941,867,171,94,887,414,596,905,22,447,909,597,937,455,416,226,942,983,356,331,666,705,135,686,626,746,453,781,140,538,67,225,675,331,112,831,243,585,274,875,537,749,624,490,236,941,274,387,450,48,829,46,229,568,125,701,787,148,131,609,793,571,991,681,506,871,597,483,10,577,235,666,558,831,293,708,181,856,254,38,402,310,376,537,439,114,74,722,68,998,549,755,238,936,765,896,637,807,662,619,839,829,110,213,896,41,648,830,948,216,569,304,28,510,982,32,406,690,473,760,219,44,203,542,857,121,667,857,839,257,889,839,203,544,497,429,857,21,954,628,277,591,637,998,619,869,615,948,106,25,867,955,388,849,494,0,937,585,495,201,557,920,347,213,476,756,489,171,853,933,839,739,750,898,766,916,702,656,685,83,872,562,582,35,822,26,684,673,529,623,273,358,7,60,167,133,502,458,222,284,565,791,587,288,549,400,124,117,712,895,549,975,58,904,428,354,733,315,925,909,598,831,279,145,232,154,360,181,447,611,748,208,731,829,534,498,845,613,864,606,799,179,796,744,595,205,206,549,695,976,698,710,628,187,946,847,94,719,80,658,527,720,655,80,759,165,17,372,609,465,559,134,122,505,457,258,247,406,902,170,748,110,93,121,292,999,500,991,416,592,216,530,871,826,277,39,460,206,945,107,926,911,100,26,242,247,982,76,864,679,377,969,666,307,592,66,356,251,167,446,966,128,265,285,362,694,445,768,417,991,57,154,633,112,937,427,551,131,386,157,619,348,258,386,303,498,309,855,259,545,156,169,94,185,400,461,60,349,931,405,161,499,804,361,593,24,876,663,391,992,768,960,522,445,185,840,460,619,248,96,43,926,625,643,926,640,610,545,909,773,812,632,583,380,756,399,443,326,477,147,126,861,678,856,373,397,531,209,80,632,648,636,221,14,276,820,594,606,284,63,527,966,80,525,281,984,862,114,70,240,232,453,397,933,132,345,331,441,508,197,487,522,157,956,181,698,792,280,531,976,377,827,570,911,429,232,255,385,407,43,349,524,829,934,928,29,91,728,320,853,498,561,929,319,128,709,304,804,462,35,637,929,860,533,377,429,633,943,701,211,816,223,791,576,52,714,409,259,569,101,324,815,679,779,136,358,710,822,540,861,998,714,15,463,552,212,763,408,128,565,563,71,620,269,306,454,163,165,801,538,5,627,816,959,644,449,746,181,195,218,422,456,27,363,361,992,988,182,338,337,14,971,12,303,883,414,367,514,821,312,151,301,847,654,115,847,457,212,616,265,547,665,227,170,610,662,117,684,381,447,665,362,816,914,230,4,819,681,384,699,636,696,122,961,402,783,36,499,286,73,689,845,986,815,254,897,190,570,120,153,698,717,517,746,675,772,445,447,281,334,281,500,833,117,96,225,421,257,90,690,912,427,916,110,856,480,554,237,838,806,276,987,911,660,295,578,283,431,341,885,701,630,934,974,544,507,997,391,645,794,285,452,935,958,490,535,935,362,480,524,385,488,644,64,995,747,801,757,558,864,357,534,688,650,213,352,851,485,957,580,657,833,189,228,211,861,522,912,448,182,452,364,59,522,223,207,857,784,436,201,589,301,234,97,626,509,302,881,626,182,101,39,124,173,48,901,167,222,230,560,581,923,870,421,659,725,235,37,980,196,616,42,945,628,532,403,269,962,205,675,733,678,365,43,233,899,21,602,299,62,407,105,161,2,27,48,184,435,810,658,557,817,454,376,782,880,786,63,49,904,768,586,665,141,333,148,82,2,74,43,64,105,606,242,78,883,200,45,66", +"75,316,351,884,716,789,596,356,464,542,903,11,460,532,252,506,72,318,565,350,34,81,825,90,157,206,859,988,55,79,948,211,334,502,895,664,222,385,153,593,922,785,559,308,476,306,459,987,641,109,826,589,492,746,939,770,403,161,208,31,94,248,880,429,789,548,847,513,440,702,845,29,650,493,466,734,837,514,385,282,485,344,12,379,267,732,938,675,544,425,972,612,157,216,272,156,461,459,165,628,711,866,636,473,776,645,116,577,454,476,110,524,934,533,880,852,6,663,593,360,238,664,538,205,958,396,58,454,779,266,511,687,509,926,575,683,533,476,448,842,161,281,5,184,328,161,299,691,682,573,400,224,700,702,722,364,429,852,280,272,36,454,959,965,529,929,458,602,456,624,57,386,318,302,633,215,956,626,57,19,707,357,49,773,677,835,155,10,625,694,150,718,791,459,258,490,523,135,136,61,53,158,980,79,50,88,733,996,253,754,953,493,480,472,460,390,248,972,752,268,801,204,787,384,777,18,811,771,605,257,926,244,221,660,838,55,344,350,837,610,394,519,491,46,673,655,593,938,2,595,968,556,440,145,963,565,341,571,996,376,823,293,606,595,702,427,173,803,626,89,967,489,543,945,611,432,913,271,274,800,357,683,294,930,867,224,774,111,673,467,191,32,306,586,81,226,108,462,807,865,344,656,344,73,96,859,117,115,96,320,292,911,141,272,344,173,167,514,57,358,917,58,740,695,512,187,452,670,697,915,646,58,147,303,791,46,837,352,861,720,609,799,878,946,458,161,990,696,331,500,255,366,710,291,675,168,937,0,549,562,735,518,523,452,833,284,619,798,505,354,51,867,270,659,600,386,155,501,934,161,261,324,190,576,307,165,205,355,446,331,456,458,354,144,155,174,723,955,938,772,549,979,547,940,607,122,693,776,368,921,404,8,179,491,632,46,935,88,368,309,904,787,664,823,947,229,904,263,555,385,988,780,552,559,967,602,283,437,829,737,585,277,116,391,376,148,664,134,569,297,993,496,304,787,810,931,83,557,297,124,55,744,552,348,418,103,338,55,271,797,915,66,546,585,851,201,248,830,681,341,920,645,906,866,718,470,818,858,749,496,732,523,79,767,423,419,814,500,275,432,984,549,592,267,702,916,31,908,538,497,747,474,323,792,257,148,268,590,48,246,436,972,530,510,370,56,215,192,700,240,83,621,224,108,355,250,462,639,149,840,19,658,592,836,45,889,361,953,409,11,766,553,682,165,610,91,564,245,3,156,688,493,462,466,936,774,883,894,822,465,922,86,732,206,382,622,332,341,152,430,548,206,705,998,436,934,593,23,930,230,456,582,516,327,782,690,285,987,25,827,616,685,238,577,784,517,134,179,77,760,386,331,130,891,955,325,698,443,224,635,641,613,19,461,48,275,521,218,262,179,577,321,319,612,445,417,295,563,760,79,779,723,466,800,778,388,870,473,263,219,692,428,169,711,915,672,708,684,935,364,83,300,753,577,587,197,255,682,644,129,609,746,638,251,127,486,564,443,192,542,837,425,611,275,972,977,949,715,295,838,539,936,754,333,202,252,316,663,594,606,344,832,807,741,399,616,231,107,787,508,188,601,975,943,555,599,447,347,522,522,994,53,833,401,95,444,455,711,762,972,593,826,401,291,747,253,862,345,874,568,474,189,752,265,270,400,854,216,988,657,135,341,559,653,537,648,667,140,723,12,162,287,805,77,179,423,828,152,125,558,151,249,695,712,451,18,510,452,602,439,727,137,860,41,193,354,896,777,797,210,757,549,928,53,441,298,814,195,502,747,229,764,318,156,245,570,430,385,374,250,112,322,755,245,364,570,681,550,355,275,492,986,689,64,978,816,395,86,692,723,184,875,187,483,707,583,894,577,198,569,623,531,425,12,128,7,728,781,69,330,829,674,731,738,375,712,210,955,949,956,213,38,726,999,61,781,182,496,870,130,80,767,456,412,687,227,768,691,96,990,976,598,535,530,235,935,43,192,747,363,257,660,980,550,810,530,232,773,68,990,770,873,8,81,653,138,837,510,865,635,325,437,893,874,791,407,14,874,689,224,227,32,743,487,81,982,400,466,113,408,45,962,270,389,673,987,857,240,646,159,460,785,857,326,151,727,676,322,320,209,854,411,839,590,537,504,797,247,489,504,987,208,830,121,220,145,468,760,4,773,968,203,770,452,333,90,76,650,688,728,482,699,876,92,976,878,931,917,5,648,15,293,998,286,642,747,126,838,216,673", +"788,235,634,518,100,873,405,638,930,236,664,212,707,122,599,486,631,75,184,480,248,998,497,137,218,461,758,433,670,49,899,532,556,912,105,804,746,303,316,834,835,150,913,396,444,861,100,237,999,107,328,680,356,685,176,641,989,479,464,665,513,92,833,733,818,828,747,288,963,359,639,160,726,409,685,166,813,66,368,624,35,185,327,942,560,20,840,742,901,993,291,369,285,732,606,454,753,196,598,184,280,820,518,505,904,163,696,597,429,898,182,72,9,351,968,787,619,909,146,873,259,146,665,479,559,972,496,298,357,605,775,907,911,776,421,957,994,281,207,243,422,841,423,13,214,913,327,759,327,586,505,438,130,92,870,768,313,88,444,943,108,321,310,353,978,510,250,424,303,176,76,748,337,454,65,182,580,813,266,310,732,769,704,744,890,688,963,240,842,950,535,305,622,413,876,644,988,837,461,65,135,542,591,74,940,289,950,363,279,933,494,192,585,945,603,447,134,733,253,902,441,807,360,396,512,716,182,433,196,599,400,540,925,36,614,362,689,714,19,62,63,237,244,289,447,582,272,631,780,711,345,736,367,80,132,674,639,624,413,717,242,805,657,655,988,878,774,883,503,274,656,291,734,528,552,840,403,52,767,449,140,590,928,259,823,212,260,616,412,555,247,705,629,369,896,499,470,393,703,223,994,228,498,948,592,919,648,190,630,755,447,994,874,420,391,290,236,953,218,364,5,988,259,621,177,701,148,198,290,53,565,730,199,904,190,870,587,457,770,564,749,239,823,765,70,594,699,528,260,341,121,246,109,90,66,816,585,549,0,740,432,444,270,385,241,553,924,244,964,142,365,537,6,224,243,201,663,303,569,717,88,221,87,266,657,540,765,656,910,134,514,923,947,361,602,570,602,779,343,622,214,469,385,952,79,966,446,484,829,938,714,618,115,227,893,445,686,837,244,528,733,601,246,491,378,333,801,161,532,21,928,112,88,448,374,613,643,109,891,209,659,791,685,282,736,629,612,345,687,387,204,71,377,267,311,784,695,258,842,146,749,796,174,747,434,560,829,654,835,81,608,772,330,732,225,857,977,440,94,372,60,764,822,488,683,347,476,616,560,416,587,415,233,480,525,928,533,7,867,654,932,844,864,353,318,63,378,318,858,947,280,716,563,346,555,862,504,206,223,354,570,914,657,213,149,148,32,883,773,891,118,505,949,565,96,370,467,887,528,98,600,678,66,378,817,499,994,529,852,461,999,740,421,540,802,986,404,703,417,507,271,45,748,874,828,645,927,4,719,870,690,166,720,616,30,109,975,522,423,365,34,657,1,820,458,258,861,924,732,54,452,240,82,189,35,557,636,729,7,976,73,573,657,84,516,261,241,288,355,985,524,990,188,269,700,206,449,49,645,251,393,600,423,26,958,785,229,62,290,429,915,497,706,333,680,859,254,955,301,984,843,996,559,903,225,177,353,56,604,776,593,390,437,421,171,739,628,494,408,368,149,445,491,926,298,339,943,828,284,971,116,25,59,442,767,473,416,372,820,901,551,583,16,781,681,435,15,951,542,341,196,388,493,392,59,411,26,287,427,984,742,66,584,569,567,581,316,969,199,658,406,102,134,430,226,918,948,975,797,694,237,427,871,916,399,300,255,606,943,216,742,333,10,70,999,210,817,581,584,5,137,699,569,844,948,970,628,866,236,115,151,899,639,436,474,495,975,771,561,543,515,687,280,729,859,173,597,427,707,101,674,254,972,363,311,964,977,223,666,887,871,447,735,838,6,502,857,587,72,896,627,381,877,554,417,628,593,464,460,751,893,374,973,700,555,307,754,207,719,343,110,926,478,137,527,378,256,103,692,373,876,775,913,104,602,802,420,587,85,285,365,81,243,671,993,355,498,448,880,22,312,422,210,902,877,846,521,92,517,324,656,729,278,182,30,900,321,55,829,660,130,208,681,945,825,51,284,256,928,132,247,488,666,764,854,306,331,36,411,527,397,730,520,208,658,969,50,584,359,988,384,192,514,991,987,123,598,372,677,527,231,178,236,338,905,131,847,758,506,148,600,156,743,628,651,910,794,479,135,592,735,28,266,504,839,941,323,174,328,480,665,704,319,202,148,146,781,653,959,352,254,799,918,272,62,457,167,947,322,759,450,184,792,941,722,777,301,248,76,155,125,751,838,580,905,854,588,653,345,771,309,516,402,232,107,805,595,49,339,302,607,838,152,599,808,494,297,640,654,467,239,583,996,229,514,831,652,26,641,651", +"675,236,190,356,162,258,75,990,953,609,116,86,654,992,719,833,587,296,139,877,726,472,493,660,594,598,539,250,512,449,307,287,171,16,568,348,740,779,118,29,834,412,494,408,750,678,968,262,484,251,773,906,19,220,289,591,181,342,710,645,359,338,46,202,938,714,651,229,472,585,424,849,277,610,201,377,724,311,315,375,169,570,522,174,628,729,559,630,619,711,522,526,706,678,385,971,839,196,292,253,197,84,829,478,717,733,992,146,153,164,343,866,599,758,52,895,395,234,43,247,133,204,515,188,515,211,790,576,104,656,152,249,297,973,605,668,687,880,65,220,714,510,635,868,157,298,886,910,566,981,138,738,699,990,803,751,853,730,439,954,938,622,727,739,449,724,254,587,990,269,635,764,149,683,630,655,143,138,2,139,115,597,274,434,29,81,150,58,56,15,486,22,868,378,391,154,92,568,799,165,423,602,146,439,593,644,412,967,162,518,859,743,921,360,164,896,487,766,760,609,157,160,539,235,554,739,171,71,132,15,414,457,277,369,151,855,325,75,943,899,236,110,309,220,147,646,412,939,223,478,933,677,92,698,152,478,927,388,2,611,68,873,955,149,598,32,40,785,199,874,50,565,980,485,266,266,876,108,6,722,789,517,291,970,33,682,495,13,20,580,937,701,953,573,549,567,784,159,210,29,841,844,666,836,751,642,841,628,258,246,564,403,979,309,27,946,853,674,564,964,224,18,268,482,864,377,237,301,244,167,214,708,209,837,623,715,991,477,983,946,4,802,877,268,99,769,686,158,412,848,30,784,159,718,952,590,495,562,740,0,951,586,612,126,601,705,340,51,767,787,237,28,940,370,663,561,364,204,910,718,196,477,613,694,20,442,693,348,802,645,453,260,977,441,228,713,822,857,755,792,715,610,158,940,957,550,202,304,497,130,723,149,102,56,981,418,278,962,232,528,521,753,460,805,775,347,607,346,338,720,532,955,779,407,882,253,347,53,813,996,825,462,70,181,791,870,518,621,479,348,131,772,856,412,425,419,696,579,57,546,156,833,650,703,43,518,379,279,614,513,93,613,161,607,337,924,842,884,562,599,316,521,148,554,282,310,964,911,74,174,725,544,308,214,763,948,703,548,778,795,100,698,556,653,89,971,708,436,90,969,98,386,123,928,631,868,513,291,466,818,703,152,56,174,367,159,648,297,542,925,730,272,422,102,68,857,550,438,877,901,399,133,88,340,459,417,112,555,345,372,411,823,228,186,739,451,31,46,977,408,931,224,382,383,452,616,499,86,777,261,933,996,736,217,350,493,562,29,875,65,810,391,74,282,82,765,237,759,618,753,641,568,10,467,178,781,995,36,296,762,513,746,484,111,949,196,200,844,392,999,19,788,587,535,572,307,927,271,862,424,105,347,697,469,934,440,580,328,862,379,483,948,763,950,115,812,512,748,871,793,559,5,385,560,622,402,838,260,609,374,36,134,756,364,749,553,426,285,617,974,357,988,637,826,342,556,927,228,272,583,56,280,844,778,36,140,610,457,481,138,785,199,186,691,598,864,901,960,327,599,908,417,516,698,690,673,51,637,107,509,224,27,908,819,355,142,698,876,257,575,264,628,539,464,168,654,352,675,104,314,94,982,506,401,854,516,173,159,294,441,60,674,925,572,76,248,275,996,740,222,836,133,253,500,756,478,271,392,316,904,372,63,770,683,182,688,895,320,38,326,870,254,44,86,584,246,285,125,800,57,241,9,299,48,33,291,627,705,21,481,65,389,783,98,673,948,37,264,51,915,715,484,156,119,363,924,526,466,755,244,971,399,988,128,601,872,755,992,987,174,152,154,277,42,899,600,418,177,411,648,641,436,701,197,162,206,408,87,871,304,827,296,655,183,692,964,918,441,333,596,1,896,308,973,974,819,154,670,318,337,28,51,88,373,712,36,174,827,630,796,811,804,815,428,235,260,658,843,333,237,213,201,864,321,343,617,756,256,204,174,116,266,451,162,429,280,452,76,764,625,254,742,687,55,575,800,575,107,842,738,303,437,189,719,806,517,984,376,36,568,460,31,42,119,104,681,684,573,666,184,868,623,277,667,939,522,958,787,812,604,562,263,444,536,880,358,606,809,62,889,984,792,962,185,105,496,774,555,548,984,872,38,720,297,747,879,263,740,585,115,699,875,664,913,31,409,627,535,697,545,63,538,484,931,227,374,480,298,110,531,389,699,513,585,81,90,337,408,71,873,339,737,845,23,257,983,39,89,931,235", +"661,786,90,981,636,187,522,527,798,518,340,766,316,263,473,365,67,866,148,284,895,418,1,926,254,320,659,540,464,840,698,829,330,899,894,518,587,930,617,287,879,84,923,723,445,27,916,982,981,936,481,32,614,709,532,178,129,27,499,920,615,243,305,875,556,251,410,346,218,718,664,929,146,290,819,968,188,988,116,188,586,903,65,486,986,776,770,944,32,719,73,791,839,789,883,126,890,235,294,832,526,731,226,260,114,639,509,411,832,881,172,457,66,545,753,569,836,574,689,272,589,104,618,614,673,933,483,293,930,941,294,468,845,207,198,540,133,836,847,349,478,232,313,728,804,368,130,702,592,342,953,272,55,544,78,160,102,121,956,813,578,835,218,673,537,773,115,116,19,941,95,281,589,682,704,349,580,680,913,599,392,388,712,555,380,377,298,731,812,573,411,489,290,229,320,45,660,40,251,687,181,117,50,666,928,774,4,779,644,475,868,405,615,450,110,738,748,124,369,134,588,254,324,986,883,910,572,855,268,969,953,541,238,713,7,207,267,588,861,891,273,675,160,856,949,870,967,227,974,396,232,444,107,735,756,552,295,233,67,223,951,869,202,604,1000,706,974,418,351,902,565,235,531,610,931,122,449,449,930,373,155,836,157,148,460,583,989,29,446,336,316,570,891,853,563,249,501,433,5,650,711,339,669,925,634,574,606,871,459,811,688,846,45,158,51,243,201,56,713,303,378,897,630,771,330,244,664,791,609,974,640,332,290,488,146,137,641,169,644,649,762,218,816,483,142,712,142,615,990,490,230,260,480,210,204,708,201,735,432,951,0,100,389,748,728,290,352,501,563,88,962,516,822,323,65,99,841,671,258,576,236,247,127,994,231,676,640,235,209,768,813,156,216,999,642,650,27,676,901,881,559,83,834,652,167,695,622,348,377,421,205,27,188,919,850,843,449,562,744,613,731,775,975,172,199,110,749,708,201,793,890,873,885,779,726,528,608,697,433,883,696,766,489,292,157,475,539,947,59,184,359,825,627,362,560,113,238,839,899,760,583,420,984,965,302,180,201,401,985,326,277,304,509,332,303,133,192,904,491,244,267,677,718,168,64,105,939,375,957,332,402,223,776,947,908,246,765,324,949,237,901,947,691,3,981,146,871,120,378,451,137,342,411,446,684,523,327,641,737,239,28,981,504,434,732,674,593,519,715,353,464,548,87,699,624,63,86,57,792,158,700,360,362,161,513,160,841,849,850,977,130,179,358,923,25,58,289,814,667,802,596,803,276,170,847,915,923,694,702,567,110,551,847,550,812,749,337,104,276,303,300,198,24,340,790,867,853,130,252,322,735,298,907,252,270,619,109,419,202,889,429,235,323,953,476,268,592,180,313,626,627,181,616,999,354,599,236,396,170,631,237,306,845,284,319,737,950,882,306,821,796,234,606,37,676,336,170,662,156,336,221,660,318,705,534,618,675,604,316,884,964,292,443,191,495,297,555,388,316,264,775,995,228,61,878,452,57,161,894,316,618,879,112,559,829,967,168,730,25,465,838,591,584,37,407,806,298,542,975,170,728,165,44,781,774,507,832,383,413,418,461,997,218,562,59,873,607,821,422,961,3,922,368,496,201,646,164,561,897,281,558,428,921,50,864,412,150,945,451,832,980,871,619,427,999,816,598,63,35,42,244,42,90,617,582,876,659,324,38,855,468,696,13,290,988,590,599,391,389,172,138,472,92,71,174,15,557,249,695,250,836,280,556,476,3,340,49,37,263,546,65,296,297,169,435,300,170,231,328,261,30,718,834,862,304,736,862,56,53,447,672,661,136,373,751,595,852,245,878,592,397,166,168,431,115,667,555,995,665,802,557,715,929,529,212,295,360,335,239,175,751,476,808,166,447,493,986,829,212,555,469,24,209,87,737,730,833,477,436,55,137,111,465,554,367,870,244,488,693,247,359,691,556,435,74,391,853,164,862,811,163,49,351,38,197,840,949,731,59,823,116,292,634,692,319,729,578,65,601,452,624,849,107,592,606,645,832,602,728,502,915,418,627,972,320,895,399,638,107,357,537,311,915,493,489,719,679,363,192,46,312,800,840,952,595,759,416,698,999,832,730,182,662,46,823,136,911,461,60,68,790,26,59,839,827,488,225,766,59,685,225,995,85,981,407,714,187,722,484,903,185,319,373,877,702,37,934,845,732,907,277,907,334,114,189,256,787,810,509,740,827,750,855,183,329,280,201,654,212,280,514,482,560,845,300,713,353,515,925,397", +"697,502,507,248,592,634,322,670,736,117,956,903,922,149,21,206,26,245,84,421,403,220,414,864,264,147,38,804,951,727,718,847,222,404,613,842,989,105,54,71,92,461,213,264,425,942,110,679,255,801,106,522,215,627,883,934,287,324,983,240,602,13,496,867,301,567,904,548,888,81,911,189,998,604,270,706,99,477,180,604,391,405,187,316,947,313,801,378,3,970,215,804,294,219,773,899,634,922,433,368,834,696,592,395,482,115,465,674,985,705,36,853,157,633,47,307,515,182,875,106,268,405,853,443,422,813,814,413,278,842,219,363,667,782,207,385,768,289,200,264,4,872,620,644,385,830,990,355,332,261,903,724,174,767,204,674,191,824,398,866,705,128,522,450,1000,859,777,572,97,454,744,310,376,468,971,639,595,930,56,148,408,294,209,862,813,951,588,528,654,161,743,983,675,807,120,569,214,429,928,922,974,715,428,345,193,804,536,736,38,694,962,258,5,129,12,339,567,450,726,200,217,62,422,326,874,352,670,73,180,302,980,103,148,560,258,319,299,141,768,495,686,945,877,70,801,606,228,942,154,180,743,922,492,685,67,884,906,637,66,143,818,342,224,712,262,406,803,773,162,20,928,616,618,308,82,184,234,182,913,700,60,842,610,560,422,17,909,885,667,792,381,665,454,183,329,180,122,61,76,770,985,302,830,735,159,355,135,659,784,836,116,871,664,131,691,35,905,437,974,326,162,638,336,230,214,742,646,639,752,592,272,506,270,654,616,511,755,371,264,709,523,774,684,719,75,590,301,545,80,599,808,2,652,74,733,379,557,518,444,586,100,0,794,627,898,388,172,88,171,879,904,284,558,476,274,169,617,250,690,814,330,555,652,402,628,151,655,88,228,747,266,366,661,5,986,627,204,231,226,893,387,302,999,15,798,602,196,994,296,42,91,799,436,440,975,226,890,624,360,724,720,674,191,813,225,925,989,847,98,827,160,256,670,711,480,364,17,957,286,436,251,610,225,304,597,114,413,345,198,537,94,873,561,273,325,937,323,132,833,613,37,168,156,265,527,211,325,646,177,460,835,440,996,339,120,711,286,283,407,228,758,579,467,450,343,573,946,747,951,648,173,618,391,339,916,852,812,879,786,783,984,412,83,702,178,550,778,330,911,294,529,94,235,972,289,123,214,138,15,199,183,475,107,12,284,422,794,558,707,206,950,627,99,874,130,845,244,321,293,453,835,389,622,50,233,253,52,953,832,539,655,541,941,493,541,614,46,349,963,609,287,432,885,836,556,212,941,144,311,161,759,189,613,111,850,602,711,149,888,447,519,517,520,769,343,563,271,769,199,708,417,368,224,245,94,219,664,287,238,410,18,772,681,577,251,404,64,425,201,881,828,569,358,184,88,395,271,673,781,372,895,507,704,504,864,129,963,461,594,919,391,815,994,55,215,750,975,331,858,786,437,492,953,689,118,57,965,945,209,655,545,244,171,660,598,120,674,99,977,807,828,92,769,576,446,183,462,938,647,476,619,416,304,991,66,124,805,677,715,178,904,76,744,638,415,577,933,59,55,218,317,672,829,724,45,861,75,91,299,164,494,922,639,489,791,419,498,14,854,203,555,440,375,569,454,124,340,706,529,286,707,875,988,703,943,335,669,411,81,332,954,140,498,692,730,383,874,698,201,92,633,60,14,119,461,668,318,518,913,146,712,526,119,960,353,298,426,365,861,455,968,908,955,524,618,472,263,474,990,623,258,210,42,969,823,613,43,124,351,844,868,899,351,925,403,87,505,382,23,998,414,489,256,140,401,169,51,348,497,373,400,984,649,643,601,998,430,262,709,312,605,300,734,677,93,967,90,31,613,964,484,778,694,610,720,139,538,133,176,780,224,877,578,633,373,732,949,753,647,889,161,684,778,285,679,577,574,438,26,701,720,159,185,11,370,213,222,714,100,657,172,8,577,186,208,645,952,37,35,869,66,351,988,523,854,203,318,654,597,79,527,578,582,748,793,788,601,997,142,618,561,178,814,99,382,993,140,471,58,719,632,450,264,591,153,469,465,183,552,370,928,112,508,955,672,198,82,541,646,916,86,113,214,258,289,26,500,677,86,471,94,649,925,275,702,820,736,197,750,754,389,442,390,590,736,41,622,859,817,71,437,899,168,298,805,163,89,105,703,216,169,865,120,576,419,179,717,228,577,134,917,968,755,15,65,349,656,193,913,588,587,68,443,61,122,234,28,554,822,237,186,290,139,965,853,476,947,416,912,271", +"632,476,122,862,792,205,838,763,960,1,819,311,996,387,919,471,498,490,45,485,963,725,626,880,501,383,220,185,4,781,595,452,781,663,653,327,21,329,524,255,415,96,280,883,66,66,209,360,424,796,792,704,843,587,476,391,727,777,986,297,633,626,858,918,83,578,184,854,377,804,924,680,887,486,859,187,186,997,648,655,97,627,751,49,700,369,81,796,948,513,807,256,159,973,883,533,809,961,61,92,166,259,397,926,473,2,441,656,787,503,512,363,430,858,986,810,192,881,84,842,964,243,333,927,77,530,741,492,246,751,579,592,122,814,189,147,465,487,45,884,240,980,983,723,950,752,995,277,760,928,734,442,477,979,930,370,52,424,653,211,333,515,104,849,739,863,337,889,476,967,676,112,115,546,165,379,357,5,886,681,276,492,251,579,820,445,431,433,967,248,539,135,979,871,394,449,902,527,9,612,766,199,406,712,491,209,795,688,911,431,800,203,649,584,831,328,48,19,898,356,829,783,988,920,969,314,940,86,668,468,390,307,178,40,25,742,519,221,696,226,678,724,430,391,317,707,35,585,472,4,798,450,584,263,778,737,714,995,553,115,757,453,869,764,164,244,933,341,218,651,231,671,4,431,753,410,494,2,475,385,380,738,485,924,512,467,919,510,555,451,998,260,398,552,45,487,364,109,417,336,279,862,515,811,884,131,105,635,803,938,750,187,137,808,3,711,398,434,986,828,232,364,382,84,421,274,267,103,346,929,877,826,736,703,897,661,271,145,808,724,709,109,137,588,672,918,564,398,177,612,668,740,266,448,315,714,920,523,270,612,389,794,0,333,256,616,150,165,822,748,720,735,920,161,430,475,536,553,824,408,524,250,947,279,743,499,99,249,242,679,870,150,886,328,421,906,7,331,929,168,143,211,952,912,535,644,90,510,244,890,940,76,903,138,550,170,601,721,323,334,71,843,392,96,283,161,621,227,39,701,887,87,464,199,458,312,560,583,152,916,358,277,633,237,874,192,889,204,721,265,499,314,96,534,438,268,899,755,443,636,400,340,150,495,22,712,473,246,247,106,138,35,310,40,86,227,304,35,992,249,520,141,371,879,947,952,638,817,886,876,239,173,482,372,668,796,257,872,499,491,494,237,922,353,926,487,763,15,453,294,197,550,747,156,829,503,158,485,400,91,697,71,348,287,421,235,249,884,401,87,407,378,339,203,600,798,714,488,410,118,95,159,5,809,26,398,744,98,250,275,835,202,39,817,381,946,167,621,653,536,391,923,242,186,125,550,176,639,323,481,376,83,745,294,805,613,338,543,309,421,475,189,839,500,639,340,77,274,974,573,124,322,274,168,224,164,356,643,910,526,640,659,221,94,642,494,136,517,162,750,1000,2,184,259,604,826,778,931,168,781,224,245,969,185,342,940,90,802,532,493,509,156,905,829,183,959,987,913,905,119,377,321,74,542,233,240,638,141,770,935,465,881,86,95,899,727,272,465,605,311,858,860,153,687,526,324,443,830,739,950,278,147,386,935,99,173,573,178,737,488,33,991,126,160,815,741,604,742,701,390,425,498,605,169,184,195,992,878,240,740,521,333,15,868,64,271,266,365,94,467,664,327,712,806,275,89,167,950,680,531,247,894,1000,716,915,310,399,164,2,930,840,889,668,327,902,755,128,72,670,361,122,359,941,875,223,520,52,518,847,548,463,749,455,71,563,699,219,565,101,787,328,981,471,480,677,430,474,125,907,179,647,519,485,135,256,540,315,877,712,115,358,392,54,887,510,873,29,852,148,993,162,280,468,126,68,150,211,621,886,706,734,418,458,529,170,698,155,882,752,959,975,647,40,693,946,393,811,693,570,666,507,204,115,595,798,991,860,640,455,874,298,333,426,247,784,133,747,814,48,646,817,913,406,925,623,873,555,43,89,65,293,353,320,841,796,906,804,893,384,379,273,189,968,881,915,495,725,240,547,479,97,126,888,454,858,77,772,412,153,691,259,85,923,965,417,714,706,345,373,39,941,474,954,895,480,263,181,665,956,324,843,794,62,128,264,937,264,617,575,58,672,947,651,590,185,936,65,921,312,633,445,705,85,348,860,819,571,611,707,877,126,112,926,980,182,329,918,386,145,81,49,471,532,564,471,241,484,35,34,732,73,759,886,291,595,63,850,478,179,472,245,568,275,206,664,183,104,158,218,377,535,652,441,73,154,732,819,712,350,970,383,661,525,44,517,161,646,737,706,552,403,404,635,684,996,736,586,370,384,588", +"185,804,398,177,827,397,198,73,740,202,17,204,342,670,603,271,988,768,327,657,857,491,873,921,781,90,825,223,409,514,312,612,926,509,396,119,610,376,676,345,309,960,241,84,2,603,18,377,745,547,128,133,734,697,424,944,617,206,683,166,578,990,834,236,208,413,193,771,999,225,659,413,940,950,754,726,297,62,500,528,432,165,178,783,110,550,634,799,890,858,837,888,313,379,821,34,475,802,844,354,748,871,588,75,43,168,763,18,873,402,101,311,725,87,333,382,5,359,656,197,831,652,399,19,22,168,216,500,200,264,872,983,575,960,518,322,928,975,122,25,664,580,863,129,99,776,752,105,923,330,559,244,401,775,172,591,804,246,828,816,92,29,627,584,140,617,593,350,454,272,290,58,593,760,439,371,600,279,44,338,535,944,93,112,470,782,189,103,462,606,640,262,453,273,73,563,245,650,120,836,110,654,768,665,889,283,559,275,108,848,832,949,915,201,75,101,461,871,884,744,803,148,968,492,345,9,382,680,521,19,60,864,580,606,698,182,907,616,806,508,417,429,67,454,374,381,573,780,808,708,305,457,399,425,104,161,707,150,274,875,104,190,103,991,304,286,292,452,809,108,118,304,116,504,770,617,922,366,191,419,100,719,386,643,629,648,768,516,585,309,154,280,88,305,319,858,840,889,848,335,910,675,333,739,656,52,191,340,164,633,965,42,999,652,231,312,538,200,533,712,51,789,350,361,514,697,3,508,100,294,658,799,594,782,373,622,281,348,985,361,134,786,9,570,175,825,995,128,192,116,881,480,151,922,618,560,347,452,385,126,748,627,333,0,41,291,632,201,719,34,357,396,980,166,3,467,509,257,805,353,901,294,612,203,17,28,131,134,775,489,16,61,562,650,209,976,991,213,407,998,960,582,586,964,518,701,581,774,136,335,322,257,406,44,964,488,449,76,766,299,343,946,254,236,879,660,902,196,486,426,867,286,85,966,415,431,647,605,556,395,98,922,438,239,975,268,26,765,103,752,280,101,725,698,595,697,388,334,523,589,302,83,182,951,58,503,857,643,252,723,699,348,548,413,598,183,563,92,563,840,406,680,984,12,662,657,982,479,659,402,366,621,153,177,342,990,6,924,202,275,855,532,440,527,129,894,296,148,98,928,555,84,445,509,518,927,980,165,567,86,283,429,258,290,476,569,93,749,870,618,425,782,721,542,356,52,761,543,447,995,154,602,732,10,949,317,721,970,168,833,328,485,183,660,341,954,768,508,81,833,235,667,730,195,300,884,371,158,122,242,892,687,704,595,443,640,38,151,388,586,726,228,108,440,969,958,327,839,413,804,942,739,909,533,860,412,548,149,451,408,443,703,330,420,860,60,865,198,436,143,573,340,732,72,355,256,491,837,961,472,173,135,226,25,300,485,200,649,740,744,884,97,524,153,611,774,379,757,413,719,520,827,335,674,301,534,329,849,350,702,847,727,514,424,198,24,913,796,284,901,409,254,308,821,454,121,685,737,660,512,481,952,845,360,574,789,979,161,273,854,773,8,149,379,100,232,890,780,314,387,577,832,77,598,913,591,729,608,230,721,30,701,897,633,529,4,515,621,459,598,475,219,299,41,323,74,577,691,810,164,994,324,672,619,686,338,80,161,688,652,201,202,961,549,65,462,301,885,47,581,781,944,737,1000,894,33,16,26,1,476,342,153,214,830,871,165,23,986,324,779,297,921,494,632,942,3,761,335,362,190,95,629,705,112,947,302,877,183,879,964,55,247,95,480,449,42,983,624,18,833,606,292,516,159,896,146,536,627,412,132,262,152,187,897,33,449,883,93,192,93,939,741,433,370,23,427,853,879,928,440,374,539,38,46,148,745,44,818,879,415,611,386,556,98,954,226,724,748,312,751,698,380,610,966,869,409,680,62,440,300,570,839,222,8,833,616,109,219,435,604,188,224,898,271,674,699,641,677,873,377,807,500,430,667,117,96,764,702,628,497,46,104,122,824,528,296,702,255,709,306,701,897,382,806,788,509,962,476,828,142,973,183,826,446,531,758,568,254,381,946,405,725,297,574,860,527,628,465,430,903,139,587,264,905,343,34,235,180,407,336,746,919,509,302,710,107,48,135,147,424,260,647,329,735,559,391,98,53,4,521,81,230,517,746,224,102,303,687,710,767,897,118,798,265,76,681,591,414,331,857,35,424,373,904,897,231,78,625,818,280,609,129,989,168,833,951,113,91,618,667,5,574,1,878,436,73,65,574,863,54", +"283,44,763,472,181,870,354,270,835,725,26,340,585,554,781,831,772,948,479,180,630,982,221,448,168,516,865,884,320,349,807,50,112,589,334,226,344,98,88,973,290,682,636,699,878,514,793,99,432,295,89,238,804,39,321,756,287,844,547,610,152,482,561,483,692,272,861,434,615,89,228,918,63,169,505,875,451,137,146,683,861,137,137,96,686,650,514,402,206,721,464,119,556,123,370,600,127,790,661,197,903,602,240,458,351,764,375,501,910,187,553,362,78,752,275,732,591,3,157,916,822,866,665,760,541,741,62,210,423,500,981,378,84,383,89,778,63,817,30,792,678,303,956,223,71,951,918,281,249,729,351,45,53,674,742,294,557,670,623,970,976,646,354,999,983,689,547,213,554,927,166,134,109,423,460,496,256,565,807,967,292,834,518,163,89,538,743,344,935,9,290,97,173,626,865,83,192,212,57,723,568,56,363,126,777,34,150,582,629,507,894,420,825,775,972,519,321,735,49,475,89,800,489,80,511,409,297,12,111,833,280,533,244,825,4,99,172,193,95,42,911,12,101,554,668,519,394,791,961,278,928,310,57,956,939,376,62,435,149,321,167,313,187,292,185,382,940,339,300,263,882,65,395,606,120,66,749,343,530,530,462,348,453,567,365,27,845,406,256,931,124,924,112,964,43,882,905,3,466,373,81,471,579,309,644,886,747,631,935,95,385,806,73,144,44,341,577,804,407,799,323,979,619,255,501,294,108,434,348,896,511,795,264,254,401,887,680,435,833,941,777,152,569,838,711,945,711,484,661,140,969,988,664,648,953,630,213,833,241,601,728,898,256,41,0,655,565,838,551,9,248,955,803,937,279,29,260,346,602,426,82,479,47,231,736,277,369,18,806,155,899,827,892,142,778,798,978,251,755,406,281,298,915,801,864,226,85,94,895,480,561,178,129,157,722,349,599,21,383,300,861,18,963,251,230,724,464,249,807,25,587,187,4,107,217,354,480,586,958,642,909,948,498,886,866,749,214,230,649,146,372,837,935,719,303,452,3,787,295,178,865,870,930,924,171,254,376,580,701,345,348,834,480,615,92,663,803,220,979,583,999,485,95,868,79,482,933,639,53,543,775,857,927,480,139,4,17,843,202,723,333,300,129,825,841,701,680,461,636,831,269,39,648,499,196,937,820,53,942,346,897,721,415,444,804,623,106,861,194,762,173,245,864,394,690,442,10,408,806,170,807,907,439,574,54,94,277,729,261,680,534,265,986,274,874,914,181,923,64,923,336,375,159,746,700,994,956,898,598,766,74,755,76,572,178,274,744,978,927,600,379,578,440,32,355,642,659,985,673,323,232,924,962,241,254,369,856,88,884,534,504,573,447,183,852,285,224,667,923,776,508,435,875,312,87,56,75,94,911,554,995,238,389,155,336,59,692,916,32,355,265,855,404,573,736,55,301,791,796,13,313,163,696,130,180,159,913,244,59,73,590,330,322,434,619,994,359,669,895,255,621,541,350,586,483,59,548,528,583,519,311,632,238,606,856,893,738,715,670,356,423,17,254,35,691,191,743,614,114,558,656,602,894,537,255,15,810,167,368,249,375,47,641,41,265,737,324,906,720,284,86,801,721,474,14,288,761,679,76,729,924,227,150,773,349,180,853,827,880,894,252,430,531,786,863,216,70,18,750,648,240,609,318,214,949,737,688,929,266,221,510,780,792,737,704,863,632,338,470,651,736,869,102,438,284,866,436,410,958,63,175,827,510,167,278,635,932,434,105,344,940,635,590,81,575,93,358,138,817,26,390,657,598,692,498,375,407,111,295,280,954,225,26,400,876,639,269,914,682,29,854,437,96,429,568,578,768,633,953,16,476,530,953,76,681,394,426,759,659,134,913,233,591,948,458,235,514,243,315,231,330,87,169,996,830,705,637,267,126,18,188,65,547,351,268,440,321,479,19,185,768,315,611,52,613,972,417,434,88,584,450,284,13,126,703,483,925,52,983,945,848,842,331,974,529,662,718,727,500,559,645,736,41,578,152,387,161,119,207,202,256,731,339,869,581,443,136,265,302,129,912,180,825,432,613,938,922,532,501,865,434,247,255,967,308,564,529,200,241,927,486,824,27,770,271,830,889,89,517,612,27,51,742,47,960,625,531,269,702,566,334,589,592,379,359,916,752,364,995,92,241,977,282,271,316,11,746,356,818,286,58,131,135,105,483,405,551,813,2,198,788,228,705,477,947,224,727,724,170,612,838,28,878,814,695,329,945,583,152,143", +"838,717,207,490,620,895,885,807,891,710,846,354,843,98,454,279,250,718,81,953,75,506,686,990,893,660,466,42,742,25,849,729,473,684,226,971,127,29,912,98,862,936,308,231,495,645,777,478,161,456,505,531,105,667,976,916,549,883,17,219,828,456,127,345,896,600,661,87,93,587,509,78,313,273,827,491,751,475,353,195,544,759,719,793,636,744,758,867,520,390,684,936,470,457,94,729,977,348,773,43,628,155,442,67,411,656,882,670,398,911,163,397,720,400,988,226,640,175,593,479,189,350,108,988,24,646,755,762,413,820,91,552,149,86,93,802,755,559,608,803,462,337,786,207,744,320,467,382,372,855,685,82,731,716,239,115,329,701,592,102,929,126,406,203,278,355,752,799,499,863,18,252,285,186,617,779,708,968,750,612,218,465,57,438,988,260,211,98,826,13,871,612,499,80,472,250,922,393,2,828,332,172,900,194,461,532,139,934,69,213,790,330,888,428,516,4,695,967,944,625,503,256,133,376,383,292,881,551,174,276,841,425,695,639,219,384,532,702,172,646,676,789,246,172,469,216,731,941,683,211,431,290,683,213,160,930,82,581,890,807,535,518,939,194,294,438,462,616,237,773,848,796,686,640,866,458,453,748,825,377,775,1000,827,571,549,543,285,798,144,119,831,285,581,323,857,851,430,90,242,701,858,942,547,548,493,278,424,324,148,187,153,895,528,935,798,358,563,94,82,384,354,934,234,598,780,324,167,420,986,69,879,423,771,525,111,472,582,899,695,261,18,566,409,646,991,787,378,98,794,739,909,42,155,588,925,662,476,284,553,705,290,388,616,291,655,0,72,94,768,947,706,141,139,546,224,88,636,864,760,194,177,272,227,857,112,459,811,395,625,164,332,853,164,668,932,169,587,30,107,899,55,840,505,654,449,100,870,259,519,577,524,388,372,59,964,596,58,47,761,191,180,623,272,233,738,904,814,355,401,798,278,376,304,922,577,403,85,626,733,107,562,374,951,452,194,239,307,831,432,889,940,100,539,834,545,399,805,173,708,324,79,180,354,698,737,853,574,181,844,233,666,666,319,455,170,378,424,364,665,656,532,204,325,84,644,205,535,500,628,775,831,739,201,585,564,287,824,855,514,946,520,541,334,96,716,41,543,62,166,5,640,684,73,61,302,674,779,235,49,940,461,814,40,804,713,293,119,922,781,601,25,599,325,43,321,595,423,553,890,917,571,618,170,212,525,452,377,552,848,907,345,589,574,202,519,828,217,745,761,498,271,32,958,968,969,794,752,180,265,575,968,693,540,461,145,475,826,668,297,17,527,739,474,341,318,106,218,197,399,37,358,214,689,497,731,787,229,146,266,143,145,883,166,667,300,623,957,526,395,627,714,587,492,810,127,39,558,607,435,508,829,178,908,402,912,351,285,611,913,612,936,1000,79,379,20,954,102,531,724,373,782,527,242,384,911,835,271,546,946,92,484,882,493,190,384,950,785,413,463,83,426,252,168,819,354,138,26,727,366,702,671,748,432,289,13,920,531,936,599,945,58,327,681,134,24,244,71,484,364,110,630,52,766,954,649,153,794,953,296,361,161,450,22,471,340,529,554,112,522,166,742,227,633,627,267,509,443,907,746,10,265,505,611,431,751,145,537,389,330,678,689,659,457,543,374,209,106,962,775,755,352,818,412,54,249,867,652,767,365,143,875,462,626,757,826,193,979,222,584,174,423,213,382,402,661,766,844,512,926,976,18,615,238,964,602,187,804,380,612,301,423,970,120,693,310,397,592,73,326,671,335,997,30,33,347,203,24,793,79,525,776,904,522,772,826,84,137,953,650,486,473,50,934,270,725,432,966,407,305,645,315,303,649,905,531,160,20,853,342,861,147,96,165,337,736,493,581,62,908,718,924,289,252,970,983,343,697,103,175,831,191,456,907,646,804,644,268,167,238,143,782,325,764,810,471,366,611,261,934,830,180,814,942,483,77,870,259,171,232,303,73,91,648,911,135,204,740,843,728,580,939,155,34,378,389,409,177,157,824,235,623,387,607,499,522,664,665,365,774,314,952,314,720,839,426,382,218,212,967,183,695,470,68,432,614,973,631,158,660,329,731,400,610,400,883,483,559,769,780,54,763,657,823,529,667,693,365,337,611,326,676,78,99,742,230,226,766,816,272,784,673,738,671,589,653,642,143,896,793,926,159,862,896,584,780,915,60,639,731,647,781,162,782,893,813,193,866,169,960,387,143,789,826,106,105,821,22,764,457,940", +"509,793,252,194,758,344,657,180,268,812,453,518,895,736,173,297,858,541,550,889,250,288,168,895,866,2,212,294,843,282,124,683,547,600,308,623,476,258,741,15,464,278,693,684,665,533,503,999,823,200,7,394,479,521,688,250,331,915,486,784,19,621,158,38,331,901,921,948,438,659,509,545,47,487,811,154,704,543,653,429,416,949,965,991,367,667,628,771,319,133,285,157,732,40,290,306,363,718,793,439,94,498,941,267,640,820,477,40,635,408,205,624,551,438,883,920,724,508,165,338,479,466,399,217,407,296,918,782,681,106,27,460,852,897,232,731,537,216,800,239,448,684,438,644,654,189,658,932,906,17,730,426,551,852,746,670,253,350,593,482,217,485,169,682,128,585,773,590,601,879,527,30,890,248,538,65,885,99,709,594,388,658,597,426,296,130,121,459,493,321,948,65,559,533,373,743,665,159,272,768,663,379,481,860,850,476,40,990,83,415,913,204,789,241,12,308,636,133,972,682,842,886,848,328,50,219,56,283,501,4,103,597,212,441,532,762,142,797,432,629,869,312,217,853,809,459,798,838,756,781,74,956,358,16,964,581,481,565,482,995,626,738,371,847,50,974,871,504,759,731,39,84,202,535,615,721,810,105,544,726,26,723,918,482,232,449,507,989,498,131,31,739,835,752,332,507,557,367,948,677,588,557,918,404,962,280,374,225,624,808,817,843,866,518,891,683,61,572,617,964,277,570,838,926,859,442,433,368,712,746,285,193,853,428,810,179,6,179,649,48,761,742,173,552,890,505,583,879,929,923,889,113,940,549,414,473,756,619,924,340,352,172,150,632,565,72,0,621,462,269,492,150,381,596,118,212,931,655,661,892,925,463,751,339,685,915,214,600,457,801,443,908,770,322,580,502,861,882,132,52,954,904,710,165,713,371,648,871,268,452,234,983,242,949,425,785,726,374,330,175,342,600,950,5,535,288,857,461,797,322,528,586,291,367,877,610,21,891,952,687,911,514,661,283,723,846,327,857,183,358,912,273,22,862,405,978,878,985,911,482,681,674,984,584,306,290,81,984,579,946,380,934,126,811,78,431,572,928,179,258,28,150,384,901,97,752,561,26,840,549,652,188,757,697,102,73,44,230,224,298,630,570,631,590,402,163,116,208,165,756,893,422,674,166,777,392,867,592,423,275,249,676,458,426,146,887,774,206,668,138,997,970,248,582,740,885,928,338,656,932,997,904,642,923,253,482,831,237,517,874,330,925,315,227,170,668,800,697,908,234,840,293,568,384,612,167,221,804,457,868,814,343,749,597,818,929,855,186,837,826,398,101,627,373,9,73,917,291,374,129,277,943,725,103,464,397,740,923,79,724,559,534,534,928,913,404,841,102,391,719,577,853,278,943,270,548,766,872,597,122,742,877,2,427,51,710,207,687,664,899,381,200,761,663,831,599,131,786,702,217,113,455,22,837,495,651,669,114,847,574,758,767,502,141,103,658,85,495,584,791,316,419,887,146,512,921,58,253,120,658,662,92,405,341,307,148,740,487,589,965,28,141,655,241,910,652,591,881,54,225,755,399,478,45,876,73,980,515,275,260,678,203,763,539,802,21,692,89,33,955,18,749,540,937,612,460,525,196,915,350,778,158,149,24,621,59,378,883,582,458,270,896,931,268,214,10,998,559,961,70,183,155,196,990,349,770,72,962,892,382,266,833,632,173,266,45,916,805,270,514,295,604,603,769,619,387,146,203,51,220,215,886,261,197,509,649,339,846,266,865,796,428,135,125,722,677,291,2,723,670,942,861,563,814,644,85,204,568,436,728,942,549,346,746,247,54,287,115,703,845,734,984,708,26,69,276,658,619,368,676,929,506,434,297,631,234,299,450,827,224,746,377,653,145,601,242,75,866,729,513,632,649,862,60,94,983,742,141,74,896,415,518,552,122,813,791,846,246,267,712,177,553,635,897,37,692,876,724,413,147,311,644,963,335,817,76,470,586,304,26,590,581,512,844,633,72,466,374,38,727,254,78,174,109,908,63,205,102,11,159,999,291,192,739,340,709,801,657,327,976,856,263,920,966,550,731,304,527,914,226,933,7,847,717,561,788,131,790,773,83,827,224,326,46,344,119,519,254,861,181,899,184,342,419,838,582,434,641,621,707,110,26,418,847,762,148,11,245,45,960,452,513,840,184,521,215,893,879,410,58,878,682,248,971,844,936,420,214,421,75,188,338,23,806,509,153,568,91,243,269,785,561,282,880,392,113,668,580,20,689", +"843,688,209,179,118,448,580,821,438,678,259,180,8,617,660,116,282,112,542,249,118,586,11,449,40,934,892,104,919,764,860,995,816,975,364,173,9,248,884,82,525,326,417,975,638,337,242,919,965,992,842,327,94,560,935,781,757,270,41,882,965,772,95,572,46,333,761,641,726,726,458,622,870,231,690,727,236,561,28,156,137,614,932,853,501,925,318,546,902,180,961,133,715,488,374,931,241,998,264,262,361,981,76,410,775,915,72,678,948,923,752,779,798,228,966,339,490,75,139,87,913,416,964,92,226,260,207,460,583,325,899,25,163,564,66,249,86,427,574,568,586,208,348,421,576,485,74,710,787,813,340,61,285,493,829,196,377,484,579,24,131,973,787,430,225,306,820,868,635,799,938,275,297,401,39,405,914,162,259,92,331,861,847,13,61,751,762,212,955,207,774,818,649,806,559,525,32,968,73,686,487,120,989,986,320,994,631,480,701,5,440,698,621,891,78,439,641,765,723,6,200,152,121,543,556,428,50,590,994,819,939,411,789,954,835,632,720,6,687,222,171,435,913,916,143,695,339,227,311,338,274,838,623,912,629,346,492,180,660,898,538,550,634,979,371,494,70,239,798,470,157,974,68,498,469,599,561,581,564,492,703,354,365,77,122,483,240,828,308,783,748,246,446,158,611,722,244,148,631,286,634,707,932,237,519,516,728,828,669,570,383,678,802,870,293,494,397,669,911,255,10,952,299,864,761,561,367,839,367,879,217,882,139,692,699,440,118,291,893,107,209,317,143,53,767,486,615,959,735,890,65,494,750,702,317,743,489,798,244,51,501,88,165,201,838,94,621,0,137,687,716,740,48,780,271,847,816,333,958,501,531,295,928,663,24,364,366,41,829,311,79,676,667,471,975,244,755,265,114,123,988,166,964,932,255,791,618,991,631,844,715,723,689,774,827,915,890,875,316,779,303,180,500,163,759,387,994,830,575,80,214,75,933,954,855,216,122,88,172,414,106,254,591,621,411,102,236,253,514,563,824,173,374,542,7,701,405,654,315,575,921,74,657,347,794,996,963,818,634,735,893,315,585,992,202,97,21,111,66,80,143,148,404,868,731,183,903,170,523,268,148,175,734,543,428,259,175,832,453,762,517,305,119,58,378,686,156,739,701,708,887,143,359,301,1000,215,379,735,347,664,210,767,848,226,223,92,340,559,677,487,529,55,339,187,227,560,830,548,613,815,361,59,334,285,170,819,569,135,815,197,578,87,824,142,726,425,943,979,633,606,453,990,902,434,601,805,992,167,129,718,763,190,276,779,370,424,965,385,60,186,718,922,47,192,776,742,159,869,704,291,528,387,777,736,14,890,328,544,992,251,126,190,861,502,488,227,528,495,651,207,816,483,245,630,753,706,580,276,549,52,880,9,302,737,895,8,38,898,46,307,747,797,512,683,737,614,773,297,881,339,437,674,819,974,661,121,928,857,22,984,437,801,450,315,21,416,982,432,126,341,863,177,983,930,242,755,722,713,953,234,162,277,231,887,552,158,552,381,143,154,646,23,752,325,718,596,74,741,960,77,16,505,498,863,528,396,716,555,262,652,773,924,248,120,971,106,419,980,96,891,129,968,368,894,253,727,861,575,60,253,366,987,602,73,236,163,179,772,892,328,835,662,887,304,460,831,631,943,758,89,239,872,803,322,880,442,410,944,802,747,57,244,973,144,616,432,704,758,896,240,152,483,958,147,409,207,160,908,124,770,433,541,386,154,56,564,912,309,373,304,995,236,715,894,714,831,966,952,818,637,261,187,663,13,998,571,52,737,671,958,25,781,161,253,257,309,777,214,571,53,856,140,626,153,545,612,250,763,708,179,659,507,586,990,230,410,478,290,243,388,932,613,564,489,284,302,475,10,142,579,510,838,89,954,38,329,586,866,367,651,72,365,617,374,240,955,848,498,384,670,116,492,833,904,994,777,973,442,391,651,983,662,492,343,60,144,904,720,817,33,199,887,854,12,677,261,758,486,435,364,695,509,195,945,837,998,843,19,898,106,524,340,645,364,422,698,836,890,69,497,576,668,385,264,721,480,918,138,846,376,297,246,245,371,671,60,850,663,665,808,685,733,156,185,794,10,934,156,356,38,64,661,246,61,954,349,432,560,417,109,991,554,432,120,795,366,460,362,904,119,374,968,188,223,116,437,254,902,313,277,949,40,219,756,813,812,607,616,330,516,897,279,700,569,811,618,154,771,40,752,923,945,109,406,456,232,199,157,479,584", +"222,246,561,788,311,910,519,786,611,179,905,854,291,550,431,335,594,619,340,772,325,546,349,703,89,640,322,983,13,971,788,875,166,62,240,11,586,600,340,4,232,932,653,765,383,44,297,5,843,40,223,198,445,603,76,786,742,208,544,184,623,863,636,272,553,993,828,870,382,230,499,372,570,756,293,404,266,193,605,675,717,362,921,442,420,4,103,625,278,908,808,829,785,387,659,175,298,166,255,616,260,578,508,167,993,608,298,705,231,334,147,639,584,374,629,368,502,259,944,19,935,590,989,23,902,160,600,67,689,959,923,349,906,754,949,576,170,893,656,352,344,144,284,22,230,24,495,821,196,865,122,729,869,382,655,313,54,748,121,428,111,896,171,221,225,756,873,580,317,230,405,328,457,155,140,402,430,152,902,728,273,928,820,778,719,818,356,35,399,265,135,672,367,760,875,763,799,917,701,579,999,346,491,264,898,260,856,539,269,100,46,367,189,560,661,115,808,402,802,20,550,457,789,767,6,230,478,678,118,678,657,995,763,569,498,331,443,603,157,557,368,923,352,86,487,978,496,536,785,450,336,149,949,653,306,193,982,642,29,403,518,369,640,276,675,551,155,363,613,3,471,420,554,60,934,841,988,162,313,89,122,510,341,37,31,157,919,797,647,471,502,543,995,68,237,280,465,803,591,677,834,462,584,293,402,741,535,935,234,832,557,329,82,181,677,655,552,483,623,355,935,241,807,159,357,404,442,701,152,964,30,381,771,180,11,767,692,858,303,670,104,476,919,298,26,839,175,944,94,213,441,569,627,876,927,120,171,505,964,767,563,171,822,719,551,768,462,137,0,183,166,526,222,63,867,175,773,698,360,405,855,401,306,566,526,996,13,168,520,103,637,66,103,125,218,255,481,770,672,625,101,816,50,259,370,441,744,671,44,822,856,946,329,163,861,786,863,891,185,94,885,894,586,77,811,708,506,20,919,797,170,878,23,130,197,272,458,331,734,767,962,284,447,12,791,721,756,501,837,527,847,979,803,552,8,312,227,127,427,460,828,381,284,246,855,829,260,24,970,534,85,765,391,468,801,823,151,817,232,958,276,614,626,551,707,290,288,686,536,707,388,531,41,422,811,123,481,286,793,607,946,676,172,348,816,383,716,190,638,755,383,925,992,158,630,93,510,588,876,700,511,420,446,447,538,29,86,993,808,38,997,8,421,868,903,28,965,876,850,876,948,150,32,699,473,400,56,651,560,528,873,830,72,57,956,403,742,784,635,727,743,411,884,952,519,365,573,268,256,642,940,76,518,739,666,765,2,253,798,400,461,857,870,755,608,652,926,932,861,36,415,759,181,939,710,200,385,996,319,271,123,964,276,884,285,701,43,951,472,652,986,133,958,747,749,489,288,659,167,929,458,828,665,282,167,284,776,88,942,440,431,953,306,719,296,301,934,106,999,52,141,82,454,855,553,296,531,866,32,368,407,463,111,620,905,824,216,215,39,284,281,996,287,328,877,22,681,508,649,781,697,333,468,846,613,910,369,489,570,803,880,870,699,233,351,858,263,87,858,873,889,205,634,26,210,662,259,667,194,170,983,642,610,631,628,443,257,481,247,229,576,761,419,221,974,483,604,941,909,479,752,615,793,329,418,139,273,631,961,971,400,321,272,172,947,341,694,679,774,701,537,89,677,47,654,178,271,622,415,828,130,753,443,681,968,903,151,867,594,793,275,647,358,4,546,748,624,559,39,546,819,717,133,477,206,555,953,187,792,429,755,296,117,372,149,919,897,216,486,281,53,296,362,693,323,349,654,347,504,18,159,580,915,49,564,94,960,597,811,55,291,615,480,68,158,811,173,723,49,344,755,777,87,887,986,557,84,270,823,867,39,42,5,287,66,660,337,480,676,841,317,480,15,368,737,16,399,988,6,200,249,990,790,928,105,708,167,745,979,898,352,765,188,931,393,992,884,503,334,62,588,263,104,967,619,247,499,634,811,317,985,346,460,105,932,369,522,104,613,997,226,466,31,39,721,579,715,120,192,133,959,748,454,595,607,930,122,717,742,279,22,684,536,959,751,898,776,839,995,173,215,546,650,535,131,584,168,165,587,643,90,232,508,589,293,487,695,730,609,153,536,430,886,62,101,526,50,458,657,999,726,410,709,524,59,33,126,809,290,720,2,936,450,212,634,141,722,450,184,852,153,749,933,166,994,59,503,103,401,679,364,482,880,68,820,144,503,396,413,110,951,395,161,238,973,676,600,337,980,573", +"690,854,354,663,525,415,588,832,174,352,635,131,654,693,924,507,854,276,210,28,948,798,73,640,218,238,992,979,896,740,911,365,341,465,107,423,892,901,288,963,804,561,837,110,402,185,588,674,987,768,58,477,726,208,644,704,929,392,812,6,212,476,183,864,722,429,821,564,7,765,633,239,104,150,592,961,594,827,197,269,359,861,931,810,635,992,524,119,733,52,771,11,146,307,10,373,178,957,160,350,34,524,316,692,250,306,636,514,616,477,560,420,291,54,960,503,821,994,519,576,2,317,108,432,498,107,616,485,18,9,118,405,666,352,534,320,248,363,220,856,177,418,917,754,106,94,966,901,320,829,207,370,31,823,146,985,806,436,496,160,211,246,70,878,200,193,404,470,430,852,702,198,38,857,577,448,551,204,714,826,923,698,580,598,750,753,722,837,775,449,650,276,708,82,37,334,516,108,41,824,385,857,415,181,89,972,828,676,811,48,443,769,281,133,503,996,672,639,209,781,798,382,362,399,670,671,96,222,552,719,751,615,334,173,425,682,575,353,787,949,11,497,22,491,241,710,997,569,217,553,95,674,805,172,688,506,169,990,391,1000,446,705,935,237,243,545,34,826,647,150,925,281,228,359,397,610,377,16,972,212,616,932,25,372,199,462,480,887,432,838,33,464,147,998,853,315,761,660,821,417,998,332,647,549,728,446,672,889,77,393,132,759,424,636,445,578,928,355,237,645,338,930,82,122,548,950,358,492,824,396,398,797,71,547,733,213,632,437,605,95,741,227,710,786,640,87,785,619,631,602,367,474,228,485,977,357,853,354,142,787,88,879,748,34,9,947,269,687,183,0,590,223,139,39,728,693,568,923,34,732,965,33,337,297,894,200,511,204,502,697,295,453,6,432,47,471,105,278,800,192,174,912,615,831,156,594,25,553,852,677,236,11,109,914,109,313,531,893,186,966,894,57,126,39,558,329,263,52,139,426,289,815,492,808,538,941,763,389,357,255,13,398,591,927,297,234,631,117,799,778,267,678,193,900,495,674,547,358,240,944,981,770,921,396,545,437,430,366,384,428,604,870,365,944,647,493,592,462,672,460,180,786,870,564,47,146,239,482,334,974,337,404,698,844,116,995,436,171,666,887,767,538,244,179,130,414,362,256,124,65,342,22,623,680,951,177,195,911,82,451,87,215,793,970,673,496,214,355,817,152,394,865,281,391,510,340,846,498,429,172,273,457,141,204,83,234,558,429,53,8,101,906,402,74,700,326,948,835,394,971,879,234,569,694,474,803,393,744,994,807,305,270,199,568,440,952,875,762,92,904,371,539,574,250,251,192,947,499,47,778,439,63,349,9,985,67,680,654,99,895,162,274,794,841,276,390,405,756,128,616,3,123,32,730,632,166,516,256,965,857,632,185,942,438,66,32,984,107,989,160,669,890,861,583,171,776,389,128,59,196,941,820,812,103,607,656,994,425,148,415,958,588,216,331,820,822,27,878,610,147,104,705,298,58,831,473,250,521,219,925,883,894,341,590,550,537,287,914,257,160,798,965,999,5,771,187,966,616,831,333,20,339,877,888,576,594,382,835,596,245,580,130,601,295,796,158,24,767,80,369,883,634,380,124,130,234,362,785,756,474,97,545,615,390,902,129,964,725,96,159,674,762,837,465,619,744,693,516,88,597,983,355,450,683,287,73,432,363,506,221,200,533,252,41,934,69,565,573,921,518,820,964,674,697,628,613,127,475,57,71,206,335,457,430,175,417,813,101,902,792,850,807,618,65,162,461,346,179,140,855,918,393,947,507,247,890,339,874,371,438,337,840,733,431,782,263,160,511,219,767,395,636,477,133,913,591,169,937,4,781,359,385,197,189,25,309,10,722,441,241,18,216,84,604,633,986,161,152,753,489,809,214,483,120,959,675,666,450,432,470,743,206,3,833,355,976,301,722,908,531,311,786,173,623,870,84,801,599,976,279,420,238,630,809,761,555,455,919,981,655,977,894,912,852,694,644,251,911,698,195,124,46,830,457,850,961,305,714,873,156,670,358,255,165,686,126,560,824,498,779,218,925,599,950,134,548,749,943,792,228,145,343,572,121,949,50,875,256,121,393,688,855,924,217,876,561,122,280,243,221,595,770,166,877,749,224,635,586,645,869,142,842,898,751,724,68,265,944,283,487,571,980,686,240,478,444,822,419,88,855,59,505,755,44,519,31,504,666,559,311,471,699,856,319,641,347,530,412,123,867,899,737,507,897,953,721,899,771,836,505", +"783,85,206,855,676,595,224,877,520,713,185,904,58,1000,737,778,769,988,878,361,503,622,988,907,624,315,334,69,646,351,742,882,746,780,331,61,830,109,406,931,893,136,685,513,73,681,671,936,577,948,592,320,552,224,670,464,978,119,903,993,301,245,776,425,687,995,676,356,103,686,232,586,903,327,968,131,494,819,89,695,96,868,608,114,581,356,815,110,155,782,249,201,49,222,292,156,455,432,858,896,342,195,739,242,42,195,902,997,788,11,873,356,177,632,596,529,742,110,921,477,537,652,469,361,628,187,771,337,776,706,87,448,564,203,110,818,125,459,263,368,724,338,801,713,815,708,566,343,856,894,851,570,201,298,946,573,422,437,455,271,122,530,315,279,894,706,843,489,683,222,140,449,636,987,96,678,634,210,589,919,570,175,290,727,288,727,283,751,287,189,285,213,99,416,872,212,519,986,477,732,356,348,21,402,632,279,623,894,102,579,954,351,427,549,738,458,374,476,671,334,841,263,974,546,934,287,559,492,906,94,399,908,913,173,341,410,867,555,78,262,447,94,428,843,595,433,208,828,693,870,574,893,195,783,118,142,89,835,512,374,59,585,79,506,960,530,723,410,799,33,18,652,627,696,668,617,615,653,223,166,973,14,413,147,326,645,534,830,696,498,276,27,591,825,702,61,238,321,13,474,234,297,548,842,220,407,718,325,621,527,363,23,225,471,691,68,215,898,706,65,44,460,6,21,476,232,974,375,327,260,106,246,833,62,706,378,671,681,441,345,495,190,140,412,216,427,537,529,555,405,362,643,937,742,124,770,933,51,365,237,962,904,720,357,248,706,492,716,166,590,0,429,432,34,99,503,861,33,69,45,947,631,542,410,55,171,135,311,865,799,278,147,528,804,157,144,964,380,595,204,679,862,242,297,75,66,746,730,363,291,86,883,674,182,302,459,591,576,450,476,801,846,967,866,466,81,47,11,371,220,799,841,256,796,943,75,571,658,573,472,318,575,992,204,956,864,675,353,900,845,532,241,962,407,646,336,652,780,989,24,608,455,150,594,571,991,578,510,57,868,921,568,893,114,704,654,652,782,831,980,250,176,457,945,339,672,408,888,114,561,765,765,677,759,573,473,413,16,152,256,784,185,576,106,925,912,236,704,216,654,484,296,739,546,675,614,391,212,402,259,705,74,202,948,279,751,54,216,136,757,253,405,269,715,324,136,630,923,459,846,76,746,258,493,134,967,346,240,17,151,459,2,185,595,438,316,377,385,667,865,169,544,215,908,762,791,508,533,472,289,966,800,777,50,889,1000,300,723,656,307,103,443,273,27,863,210,821,474,790,212,686,397,478,28,943,109,713,765,530,858,730,29,99,388,92,544,259,66,413,996,747,603,517,711,161,420,809,573,299,239,904,766,103,602,51,786,217,313,932,36,499,592,294,118,749,561,724,477,272,226,95,109,447,855,553,669,410,206,629,611,410,323,259,352,996,637,518,532,660,575,618,657,163,450,548,71,851,11,748,426,968,890,398,673,493,126,301,584,121,710,937,295,656,440,703,421,974,655,87,569,762,393,77,571,258,640,834,830,28,754,576,71,754,545,359,624,854,796,895,681,8,35,895,168,359,169,569,220,792,314,495,631,982,335,637,535,100,894,438,87,811,680,495,349,771,545,555,317,389,469,877,7,507,29,669,19,804,8,142,63,461,134,823,286,491,321,722,546,509,720,235,347,245,421,833,111,909,555,423,744,994,423,457,734,732,261,751,614,586,391,499,147,16,719,165,980,856,813,208,227,855,42,802,542,955,66,635,877,861,306,869,240,92,234,881,490,620,667,158,197,421,437,563,897,265,843,300,185,180,299,879,575,448,546,256,78,620,501,696,429,306,731,839,485,885,688,170,648,722,951,533,446,474,962,52,272,438,993,758,547,849,954,917,59,187,485,982,475,76,154,519,415,53,94,303,551,325,488,414,679,396,517,984,200,405,830,159,705,621,406,183,748,892,594,144,950,218,222,203,323,488,192,329,354,802,994,662,834,237,57,473,830,9,552,257,801,920,736,309,183,289,812,26,959,342,446,300,825,339,355,429,571,697,828,625,151,203,460,941,112,461,389,235,144,437,746,863,652,98,533,330,696,685,816,779,979,669,605,655,30,682,493,942,738,330,905,576,375,427,678,95,977,888,839,150,624,128,245,772,534,389,567,670,83,156,764,770,330,756,916,631,133,698,585,131,680,613,996,121,276,470,676,272,638,492,552,517,877,165,210", +"963,476,829,673,765,81,156,433,824,136,368,615,99,768,425,646,6,324,857,139,863,180,86,155,239,187,648,32,958,307,703,886,495,881,696,428,689,510,695,818,755,628,18,53,420,156,948,326,133,877,372,980,367,8,102,16,895,496,212,640,199,19,553,486,756,750,61,600,998,418,930,305,113,722,693,171,928,931,552,631,454,529,539,609,228,850,484,315,895,815,36,872,913,430,273,58,827,878,950,865,113,676,501,94,655,205,15,514,215,548,166,703,778,812,677,983,630,36,484,481,29,646,793,284,630,707,867,977,176,432,259,824,175,331,345,917,301,457,677,251,225,183,382,423,891,154,45,936,875,932,953,434,359,539,836,575,834,241,595,540,165,964,280,991,716,580,636,465,18,233,522,113,766,47,101,59,214,840,578,822,69,145,473,459,920,971,619,738,686,13,984,450,456,148,16,18,848,909,696,98,887,466,746,73,563,12,883,859,130,23,879,437,780,661,885,126,760,604,241,116,339,541,789,750,543,3,224,940,932,363,139,236,243,395,249,532,331,26,41,210,901,908,3,422,609,479,951,548,615,780,347,89,902,72,272,541,930,1,725,29,298,908,389,495,92,923,100,435,353,114,325,549,513,669,925,582,407,137,717,889,490,9,348,447,407,616,563,203,344,585,469,795,646,365,457,118,19,503,286,264,705,590,866,759,500,107,178,472,958,310,985,30,152,364,137,804,674,656,118,468,281,502,428,278,299,420,753,884,767,39,102,579,633,598,410,644,231,477,910,115,716,122,993,135,988,112,352,931,311,182,745,791,287,844,302,959,839,867,537,28,516,284,735,396,955,141,150,740,526,223,429,0,553,859,464,269,76,176,164,743,161,112,630,224,382,558,235,747,805,821,803,194,864,670,376,445,629,222,538,338,209,832,459,748,117,280,280,848,751,787,726,237,504,115,417,397,727,91,925,974,197,636,889,216,996,983,361,640,717,122,360,170,185,899,36,193,887,212,494,852,1000,595,319,85,397,988,188,653,26,931,634,787,807,176,267,694,574,591,569,637,631,395,870,225,430,681,599,763,725,524,419,249,23,20,689,500,691,111,709,316,941,516,470,475,861,509,851,903,971,938,820,383,825,720,856,322,801,998,773,286,169,542,202,719,71,275,191,176,860,984,798,747,118,328,984,984,836,578,196,307,832,339,706,77,594,540,886,301,684,728,404,714,28,429,683,907,454,736,918,202,26,42,554,767,315,223,459,685,938,288,273,865,554,931,135,189,806,896,155,764,902,420,35,433,49,701,842,484,167,897,895,332,273,941,350,488,828,138,203,785,629,223,91,15,712,758,537,414,81,883,904,195,600,195,901,260,730,497,583,20,80,634,65,885,999,279,149,92,706,117,70,955,645,780,516,666,663,830,55,290,578,762,280,333,240,516,226,768,484,740,65,57,260,73,878,448,496,485,954,301,909,968,853,219,699,75,764,655,396,638,345,827,135,256,857,186,289,147,764,279,532,34,856,784,415,96,408,320,480,834,126,721,283,181,863,805,978,403,497,898,467,206,98,766,583,549,800,467,548,696,870,796,820,575,400,927,178,471,636,489,663,832,254,49,370,228,794,773,302,123,559,569,819,847,157,576,276,309,45,153,631,898,336,38,289,974,430,213,8,813,808,691,533,980,960,562,643,490,7,46,945,888,991,445,761,415,744,67,508,263,748,162,599,173,399,851,467,932,135,374,28,277,675,23,545,855,595,695,854,953,366,566,767,662,568,238,583,411,407,129,659,690,641,446,442,325,55,730,716,806,199,904,816,999,597,787,795,429,648,480,489,470,674,973,991,819,378,315,542,144,403,271,167,187,625,504,823,189,95,683,168,202,848,751,667,881,965,423,238,223,785,886,459,656,114,637,947,876,466,995,455,447,184,301,937,29,333,519,299,282,754,504,167,698,258,866,2,420,729,816,339,855,198,790,701,168,924,237,123,752,584,880,873,82,246,582,423,533,60,158,655,945,393,692,909,795,959,916,747,972,542,961,959,993,243,965,261,595,276,111,346,157,321,560,706,571,857,878,96,140,884,547,397,32,414,339,178,761,563,268,252,514,404,185,543,660,779,584,99,41,748,15,671,429,851,639,719,630,609,157,927,165,367,695,860,692,800,103,675,997,892,629,473,140,452,371,201,2,60,42,19,993,120,680,242,272,302,231,526,419,520,398,988,137,184,340,609,832,331,659,453,695,506,439,161,589,556,27,745,256,764,31,499,331,882,326,999,360,443,293", +"550,243,537,728,933,977,745,468,452,383,174,956,536,159,428,887,896,596,72,31,525,132,144,247,8,586,727,907,260,315,828,919,168,407,44,402,866,351,728,616,320,823,16,399,451,292,464,426,498,942,287,635,44,578,51,575,52,450,286,18,849,645,858,186,990,936,980,307,411,397,597,907,202,113,803,717,371,246,695,324,598,531,580,540,954,590,186,3,392,343,607,378,218,253,701,148,974,453,534,220,172,15,743,464,636,352,350,33,600,667,768,158,203,522,760,203,802,515,598,338,708,288,454,668,308,67,307,426,891,16,355,806,846,128,771,68,436,476,854,660,350,308,759,921,489,501,750,381,280,467,661,936,666,16,139,251,836,440,669,999,41,421,738,153,950,197,512,807,88,484,818,995,202,161,330,728,726,852,414,376,299,94,712,263,426,994,347,820,96,13,514,93,783,954,826,677,32,520,743,806,572,572,5,138,121,14,650,963,183,532,777,624,573,781,472,188,224,335,478,660,937,943,512,296,213,818,99,476,474,357,618,867,120,868,393,502,221,308,810,842,843,355,210,797,476,978,185,758,143,670,32,395,845,714,920,726,472,532,244,109,525,620,986,718,561,192,582,924,110,220,325,108,473,59,713,572,701,881,48,891,801,261,7,202,200,815,2,460,604,934,294,202,967,425,704,471,450,866,406,361,370,914,965,326,437,83,250,979,159,908,684,347,256,637,166,421,118,390,862,623,395,593,474,639,248,841,97,391,191,963,710,692,256,516,831,208,626,825,565,640,409,557,133,230,550,405,341,637,42,559,804,820,52,737,690,156,739,270,6,940,822,558,920,980,803,139,381,48,222,139,432,553,0,189,779,510,327,598,116,383,91,433,4,642,430,817,567,978,688,176,253,823,69,185,994,337,235,421,488,871,172,685,923,98,458,579,619,813,417,999,71,285,917,439,255,54,158,816,919,610,263,345,595,762,612,799,247,181,80,495,456,750,469,961,198,319,878,863,967,640,2,936,83,637,595,355,569,43,291,268,906,630,525,275,643,168,946,588,47,799,317,632,449,785,953,259,48,836,395,974,979,375,550,559,336,758,855,636,130,762,959,468,808,330,765,466,600,404,372,403,564,625,40,10,876,126,597,924,766,392,818,910,562,295,73,870,384,865,896,838,636,770,888,844,225,993,479,518,528,56,18,182,664,363,245,912,895,666,661,498,520,556,711,700,628,884,118,556,421,60,47,204,875,866,145,532,340,616,885,885,77,634,848,46,748,336,736,996,455,338,98,393,457,725,703,140,10,857,876,620,227,44,402,883,570,93,453,896,308,398,533,348,861,944,53,580,147,912,321,195,764,114,797,648,525,870,763,725,115,749,913,480,277,313,812,154,162,132,727,553,758,101,924,367,138,706,659,533,817,684,807,999,574,956,845,473,498,26,167,880,301,307,591,372,76,759,943,83,626,782,270,479,533,858,360,617,573,373,925,707,913,208,871,997,274,793,992,318,668,383,507,339,73,204,927,549,698,394,981,13,441,61,765,70,944,564,891,260,235,746,142,486,25,517,398,249,151,264,638,340,492,937,243,715,560,9,811,353,138,856,62,853,243,333,334,556,670,936,728,49,959,585,946,308,152,608,324,709,464,527,243,812,153,268,993,320,849,789,33,25,706,759,409,342,804,886,243,213,862,717,712,586,425,711,757,812,299,585,61,28,129,216,546,315,483,341,995,973,101,562,967,733,824,457,831,79,947,943,257,617,396,835,246,957,14,494,245,352,802,704,109,581,891,17,51,481,967,622,645,588,682,643,290,466,836,360,278,128,795,183,355,423,944,47,774,538,896,637,820,580,394,748,575,391,545,725,792,301,747,686,865,47,910,876,61,46,454,336,6,201,731,178,467,841,123,848,153,272,278,642,908,734,126,235,162,575,648,177,144,145,636,499,85,489,980,698,44,961,688,43,186,998,988,348,161,964,777,778,743,258,70,938,559,885,690,411,486,269,630,500,945,906,124,398,644,210,646,997,114,48,733,312,606,730,526,965,707,685,890,170,943,367,816,44,76,930,432,666,956,415,930,20,341,654,527,643,957,401,495,410,718,299,591,793,600,873,926,652,623,730,989,311,506,618,170,666,609,783,453,761,347,308,800,790,903,479,672,101,804,17,703,873,778,347,418,927,369,684,937,316,639,437,129,283,510,448,678,60,463,127,266,172,108,935,84,885,912,607,352,686,370,796,806,77,482,601,769,129,980,121,446,835,824,200,925,459,860,579,212,418", +"621,513,510,479,298,659,834,532,884,896,505,834,353,673,33,364,140,822,454,494,619,741,336,549,802,603,828,237,256,782,607,93,403,864,561,15,25,601,500,960,442,898,723,395,153,251,638,361,203,706,962,11,99,519,498,434,79,465,999,294,257,843,548,938,504,341,917,329,503,902,311,527,348,791,931,722,513,696,856,524,159,507,523,281,624,886,493,914,904,328,861,381,721,503,863,518,290,486,128,133,238,912,697,109,628,738,180,152,871,318,506,269,212,570,638,793,476,260,391,99,783,422,256,126,365,390,130,442,664,583,824,261,906,585,326,93,652,961,568,740,472,249,703,196,412,215,548,898,727,402,803,537,419,57,441,248,998,774,134,554,324,429,562,923,97,780,985,260,484,646,679,821,579,527,581,777,34,342,55,396,122,538,78,687,53,533,484,491,42,280,935,884,20,211,193,560,72,213,726,801,332,123,106,920,386,862,196,293,302,273,833,68,731,701,170,368,997,598,378,131,923,935,92,912,767,840,443,265,457,138,932,176,399,453,640,213,827,28,481,731,710,676,173,188,246,454,870,413,850,396,40,791,106,276,461,249,333,265,644,31,486,37,642,267,468,936,102,849,279,511,383,917,314,55,198,491,84,482,595,543,166,926,363,68,892,214,216,657,867,652,798,365,231,833,613,961,566,325,96,62,391,131,319,929,602,589,308,15,110,747,982,38,193,241,269,393,767,792,722,317,534,731,485,970,691,107,778,366,895,239,633,696,430,168,499,686,416,75,763,685,235,408,340,826,611,997,418,416,594,164,715,873,107,907,933,693,750,659,224,370,323,476,161,166,937,546,596,780,63,39,34,859,189,0,528,254,892,796,935,694,127,11,209,199,326,888,865,985,468,88,704,47,589,156,285,262,980,555,208,537,709,212,2,59,563,886,50,368,92,168,171,246,681,596,648,426,335,419,367,572,871,759,385,218,807,24,93,227,329,887,195,414,532,283,898,985,160,689,22,15,760,777,311,935,51,221,790,928,481,504,171,660,603,829,317,611,915,386,650,955,661,775,332,423,795,505,106,993,438,214,280,11,74,845,564,452,186,817,39,89,891,775,356,625,805,701,40,737,486,6,807,285,683,919,546,769,904,871,646,978,380,480,374,470,268,714,24,845,243,511,447,690,84,770,494,593,550,535,872,536,209,187,705,203,386,615,712,441,88,630,228,339,300,274,11,254,740,187,364,816,357,935,763,830,964,350,631,328,478,409,533,253,26,982,256,685,164,943,16,582,752,229,965,17,788,204,499,673,843,965,107,172,289,522,876,786,561,272,74,78,336,772,633,941,13,513,561,14,453,218,718,610,49,781,481,998,818,950,156,857,510,137,196,692,516,751,959,37,994,30,343,701,121,470,814,965,282,936,550,969,515,153,223,83,161,528,109,540,508,732,536,945,551,398,462,533,131,431,4,511,321,944,672,7,403,544,887,344,975,296,72,549,575,901,188,938,883,405,125,710,983,647,562,257,426,635,117,905,282,255,852,979,644,962,377,114,108,326,265,935,126,94,235,272,511,99,603,417,8,511,371,815,176,969,947,431,575,709,756,639,481,119,246,776,187,493,119,434,176,447,318,13,302,724,102,266,349,421,810,667,777,686,802,284,676,84,353,191,357,296,856,156,316,203,699,964,174,480,175,413,680,134,414,435,877,110,982,587,668,336,603,698,26,713,787,531,234,482,806,495,47,1000,57,438,70,676,288,420,932,761,844,258,776,128,336,920,791,727,541,88,448,289,702,655,357,577,465,261,926,310,425,930,327,484,438,338,237,861,358,955,761,587,690,887,649,486,960,925,929,288,788,634,573,355,224,485,353,583,683,121,83,468,978,65,212,619,713,984,398,209,112,850,425,17,910,828,114,979,838,210,331,355,171,454,42,253,620,954,59,876,185,393,197,156,920,754,346,349,175,347,997,874,26,340,877,403,185,813,468,439,711,553,461,41,301,28,472,773,346,181,150,472,526,519,679,185,689,55,311,262,496,662,596,322,10,437,786,670,276,497,289,157,719,689,440,654,337,519,923,365,931,514,267,98,679,33,305,855,523,999,953,614,421,8,44,610,403,137,359,600,15,183,782,199,31,545,124,160,796,808,861,503,212,505,171,463,145,718,862,146,210,595,18,502,604,249,71,877,538,130,529,844,25,168,242,127,602,84,548,514,553,926,855,315,345,776,472,973,737,337,749,955,279,223,291,848,386,128,201,281,941,667,989,942,718,187,720,381,346,471", +"211,895,279,937,257,648,34,438,179,582,573,153,44,292,60,977,296,397,491,86,717,453,627,118,824,642,481,890,341,236,200,23,816,162,153,546,972,313,259,441,496,354,623,535,280,534,590,76,730,327,454,506,667,930,691,35,627,513,608,126,306,92,635,295,723,261,729,175,99,889,804,404,561,189,915,697,127,262,309,258,709,320,175,7,694,353,444,654,847,17,465,716,318,68,784,120,239,904,965,971,422,295,451,596,691,275,164,822,356,330,222,369,511,566,47,283,150,556,730,67,628,84,483,643,925,265,830,385,449,795,994,326,96,719,155,312,863,145,950,790,18,121,867,961,587,455,175,515,806,802,620,519,126,284,928,59,372,971,716,484,946,791,864,776,408,678,244,700,558,341,34,266,447,773,516,657,118,780,131,613,511,433,119,345,270,696,257,766,860,576,291,777,205,734,966,904,583,615,392,615,635,722,876,373,577,859,994,25,574,980,526,709,438,104,255,254,213,512,323,6,961,685,423,639,626,246,193,496,852,998,438,355,71,805,293,861,296,903,319,246,640,379,753,819,860,432,725,463,28,131,463,590,965,355,573,483,171,464,536,788,793,54,550,198,832,549,740,996,107,386,632,897,226,307,905,292,37,260,855,762,521,329,437,472,1,609,58,687,58,473,490,548,928,464,650,84,416,311,525,925,788,385,788,764,775,845,219,209,941,718,637,675,404,846,388,102,949,134,579,403,591,992,132,153,100,479,375,899,858,977,454,115,136,544,518,149,577,450,475,795,173,458,505,782,688,191,784,578,651,336,929,605,184,828,169,545,898,600,243,663,65,274,430,3,279,224,118,271,867,728,99,464,779,528,0,147,672,70,877,609,198,131,189,703,18,392,579,107,913,951,911,916,269,60,540,364,969,537,956,813,380,672,909,986,950,72,913,519,582,960,291,827,33,401,338,91,972,127,122,571,965,557,454,247,642,641,222,87,642,971,893,77,287,58,308,846,490,891,500,362,513,422,53,619,799,298,952,521,398,924,448,540,562,942,875,62,649,866,217,830,813,862,281,962,404,498,819,118,276,829,25,562,685,592,910,198,595,195,864,167,93,399,704,101,891,187,495,962,777,618,741,61,651,584,610,287,622,896,379,872,957,545,630,571,51,767,959,799,415,24,732,132,585,715,65,883,452,481,19,674,894,403,316,415,738,595,822,854,860,431,861,870,124,368,689,121,134,331,670,935,364,226,780,925,388,996,801,260,548,988,123,721,54,363,76,560,471,297,661,201,524,476,17,564,228,530,607,20,164,759,625,404,161,863,787,733,858,342,88,621,141,637,7,864,924,48,62,197,893,30,308,817,305,769,879,551,412,286,106,531,222,639,897,748,189,685,50,361,19,191,864,597,793,574,948,149,93,867,243,82,938,868,513,667,54,126,241,809,128,18,104,191,964,837,793,872,742,255,761,712,589,230,909,283,361,672,193,970,101,7,740,262,76,485,372,700,502,900,781,976,667,384,880,392,832,227,434,764,918,229,797,968,750,748,98,363,202,755,388,692,412,239,847,865,212,858,496,774,378,586,775,209,514,550,349,42,591,480,190,579,290,165,896,194,425,34,292,106,263,768,792,880,522,988,877,614,590,816,756,917,861,124,842,463,317,774,789,512,808,935,849,735,161,258,765,994,434,395,648,609,216,865,182,995,124,540,213,897,944,201,884,145,698,778,128,457,996,788,983,949,315,439,797,684,484,175,915,105,729,10,119,648,774,527,883,945,65,231,401,733,968,674,879,468,325,496,749,438,348,377,537,233,764,394,644,152,832,61,659,641,608,846,291,669,674,75,894,829,634,173,587,191,875,416,270,385,811,554,578,767,473,969,473,464,431,764,592,339,227,851,775,365,578,431,601,248,64,205,238,398,867,240,654,344,76,624,312,799,892,761,231,131,708,244,442,775,486,680,188,655,276,828,874,525,543,868,24,120,227,651,562,829,353,995,963,523,245,895,347,175,731,520,958,8,53,208,165,294,985,452,528,801,436,615,246,326,88,149,891,357,203,974,951,389,305,861,156,215,882,34,476,816,568,678,991,124,119,349,899,5,175,338,30,824,797,145,464,851,598,957,335,672,357,787,415,383,220,45,956,265,241,260,414,386,532,757,214,798,39,829,287,363,40,881,747,958,635,944,187,979,374,348,4,83,869,557,350,891,841,216,210,331,679,976,567,638,548,216,378,318,562,202,347,661,411,263,302,581,264,447,460,57,815,773,336,517,71,451,377,887", +"276,569,277,890,668,742,768,276,255,749,423,54,999,163,264,784,221,586,649,739,642,857,149,15,688,511,556,613,772,742,870,141,395,8,757,569,822,49,85,303,979,564,74,712,489,834,629,232,555,424,654,481,530,647,290,317,665,952,905,442,786,614,957,579,6,546,324,214,857,146,967,289,836,559,560,459,462,493,886,742,366,738,242,9,329,859,102,880,276,412,43,561,594,605,820,120,530,605,120,307,87,970,13,762,928,218,514,672,449,120,215,185,451,512,802,569,446,416,314,917,140,780,635,716,668,458,441,5,782,827,360,87,426,771,62,160,883,256,716,816,922,632,82,837,579,367,95,394,550,952,743,357,553,317,156,327,516,700,585,339,771,546,323,102,200,937,989,772,773,215,342,272,125,164,2,122,549,283,701,617,583,277,595,152,213,852,634,702,256,847,164,259,72,475,577,246,652,745,120,241,874,3,20,138,957,611,812,407,884,200,517,597,592,888,59,610,236,365,999,365,881,31,853,157,201,162,161,772,7,180,137,877,21,561,41,519,96,21,380,225,334,260,459,772,955,394,830,333,944,403,9,323,567,511,172,581,111,411,348,29,971,143,42,693,680,840,252,646,873,488,68,25,735,562,195,70,296,465,492,361,199,6,565,208,136,403,925,458,851,723,188,119,984,816,224,527,682,129,426,394,288,518,37,504,488,635,778,817,167,142,302,769,805,811,355,348,157,598,796,982,526,974,104,180,26,572,846,882,705,603,96,706,992,80,725,317,360,443,198,139,114,949,325,796,739,142,111,320,153,739,255,771,311,123,91,489,766,386,201,561,99,169,475,467,29,88,212,847,175,693,503,269,510,254,147,0,364,277,672,212,814,167,685,806,36,695,319,747,687,775,366,592,684,968,891,446,462,874,485,556,602,449,611,686,955,993,594,571,245,705,9,217,382,795,975,149,579,871,892,224,259,210,440,834,973,479,935,139,887,890,693,230,639,201,379,320,417,677,153,775,766,754,776,190,222,234,533,176,603,753,958,571,975,90,745,701,459,554,294,419,158,517,712,614,218,406,64,829,216,245,267,738,772,248,405,638,676,665,507,997,638,666,469,134,837,327,315,45,783,873,464,707,13,367,729,84,405,764,969,132,104,267,100,184,142,229,407,685,116,461,592,239,345,717,43,382,90,247,181,52,489,811,337,185,705,928,767,221,813,731,905,17,28,613,825,698,986,143,446,761,224,933,618,522,382,6,259,763,817,867,673,965,846,210,180,829,314,148,44,64,173,274,944,687,721,115,952,498,181,351,119,123,66,496,718,169,427,65,483,782,487,792,526,114,477,94,993,898,324,794,225,600,761,900,788,141,387,274,290,246,162,799,580,62,521,169,428,80,706,645,851,624,640,685,655,76,115,917,201,921,861,244,715,406,97,776,919,477,914,567,594,910,97,730,495,783,864,960,712,575,784,668,757,273,18,123,301,917,579,38,240,659,241,496,204,27,111,901,164,181,869,774,272,447,391,63,162,459,865,456,211,288,214,348,806,64,719,944,499,478,49,444,242,5,297,293,257,98,576,258,299,899,573,3,534,203,194,386,327,524,137,644,743,563,97,255,484,322,870,128,873,928,74,639,325,644,978,648,785,483,198,620,211,788,79,574,767,436,683,483,223,669,392,56,79,22,487,159,68,77,45,13,195,625,809,749,162,213,814,512,26,264,785,958,604,521,273,493,971,929,795,624,84,665,656,300,730,294,547,798,450,378,359,744,364,814,894,377,873,542,64,31,245,913,455,68,724,884,697,163,473,534,887,572,678,183,759,569,425,768,782,63,262,828,832,387,228,592,301,489,369,223,801,637,907,672,190,32,763,612,358,948,331,869,156,40,196,383,181,102,388,515,690,394,284,512,672,856,869,125,579,664,689,942,374,635,614,642,370,804,99,166,850,916,867,929,159,901,639,125,866,458,702,23,685,59,841,317,29,210,113,212,881,675,69,210,807,327,15,723,893,608,749,447,555,511,140,523,625,598,594,358,18,186,294,492,527,238,576,882,559,853,296,745,995,694,146,963,490,83,737,682,412,482,861,274,907,826,87,702,816,419,193,232,611,781,437,197,645,221,341,168,446,210,775,237,849,42,143,144,638,466,259,714,247,476,708,2,83,363,98,760,419,798,390,535,946,537,475,887,530,879,77,481,801,39,269,927,763,415,997,65,429,200,371,101,128,314,143,855,245,877,696,988,196,792,593,272,358,760,872,512,198,185,737,833,917,868,494,961", +"133,29,316,328,939,463,258,544,894,340,922,142,944,117,699,836,669,381,580,838,632,684,701,156,329,85,54,203,61,138,662,94,441,680,905,780,15,874,586,642,576,399,891,386,892,388,577,250,170,856,185,954,95,919,132,279,408,722,135,286,241,99,653,574,906,66,42,652,41,537,508,960,93,630,129,891,786,733,901,117,78,410,683,638,240,258,380,742,740,922,7,393,384,141,100,284,900,258,298,497,755,826,146,982,904,24,335,173,199,798,575,845,385,370,845,554,725,536,203,548,23,609,185,967,643,310,377,833,193,575,235,18,632,539,579,968,552,685,556,836,162,17,570,195,605,189,948,448,974,712,990,906,955,11,252,50,742,59,158,154,674,557,638,92,631,716,683,518,658,53,354,419,466,700,958,203,977,39,209,74,491,850,13,592,604,385,666,292,425,463,959,485,780,666,820,846,410,890,388,405,667,152,479,507,407,622,859,682,259,106,34,274,589,813,596,486,610,581,489,140,810,999,205,59,483,270,406,530,555,269,232,645,248,399,67,738,756,256,89,686,441,246,17,803,582,281,877,955,110,364,858,797,908,642,395,28,367,722,384,676,199,458,635,83,868,954,712,245,594,72,599,927,100,880,759,445,998,535,780,357,970,679,458,483,488,894,784,266,925,767,602,503,801,600,839,265,282,194,927,214,526,998,681,659,96,796,832,750,963,406,462,183,828,725,503,234,874,134,484,802,753,811,958,854,260,888,984,559,388,914,749,413,996,740,39,734,851,366,425,629,480,908,511,73,531,450,782,793,510,104,346,673,443,864,975,67,916,155,663,364,841,617,536,509,260,636,931,816,773,568,861,76,327,892,672,364,0,137,428,278,315,376,954,315,273,399,241,559,830,665,817,491,308,952,839,244,14,13,280,749,922,360,105,111,423,605,527,837,132,435,582,774,727,695,569,27,150,533,294,535,385,343,985,794,226,908,903,888,607,185,413,419,322,870,596,609,869,786,963,182,669,134,979,578,497,852,170,309,726,487,356,462,95,201,324,166,496,917,733,983,748,503,334,701,658,477,95,636,419,359,408,628,343,301,248,983,176,624,266,2,611,538,814,412,720,703,97,488,699,300,871,325,898,440,557,494,10,480,581,301,787,566,797,830,593,158,100,873,972,391,471,310,124,552,889,30,856,396,682,91,685,837,47,503,914,625,696,232,29,44,125,627,518,892,718,248,632,301,219,876,31,911,988,108,942,494,183,593,141,411,125,371,630,46,992,3,376,256,85,19,94,446,28,274,570,978,422,618,191,715,685,699,568,871,453,144,227,921,205,994,82,726,804,321,409,966,978,632,276,101,408,206,808,161,41,878,48,307,912,288,401,748,448,971,74,363,860,488,940,654,736,652,907,405,714,486,785,268,747,29,851,858,519,90,124,82,747,953,872,654,943,572,204,496,402,479,170,391,33,319,80,946,714,507,339,997,377,383,217,510,35,602,819,639,968,164,16,771,244,709,843,867,923,117,435,743,659,671,413,957,181,18,708,725,753,712,453,172,988,472,100,520,522,103,597,426,133,987,227,656,616,705,772,423,696,228,670,382,530,245,370,330,685,461,633,475,312,47,529,646,57,371,501,213,532,399,301,482,568,946,661,310,142,686,831,18,786,825,902,85,874,42,675,876,111,857,530,572,342,511,457,506,476,958,58,940,170,470,355,409,251,601,913,738,523,976,936,243,785,833,222,394,540,63,338,297,234,880,616,22,13,118,829,889,600,746,193,834,105,809,654,426,968,206,922,890,801,496,833,981,472,183,808,158,632,64,709,756,532,501,118,906,344,206,876,312,396,3,29,781,428,476,782,682,934,411,41,42,750,865,719,913,28,455,693,175,599,886,478,933,24,567,246,661,901,461,186,75,905,377,449,600,188,693,678,467,743,349,811,498,591,423,79,407,696,631,657,732,134,508,112,576,373,113,391,545,591,160,728,873,608,377,831,643,183,275,426,855,494,520,487,532,541,85,99,127,931,114,909,580,203,194,803,505,703,327,419,223,450,822,880,546,498,913,438,267,143,892,199,819,135,34,26,872,716,435,287,329,755,7,92,750,942,87,399,40,701,301,850,1000,882,713,509,821,896,719,661,530,369,519,893,846,622,933,567,566,713,691,762,802,678,740,302,459,374,446,516,89,435,911,867,618,320,715,140,568,633,512,891,948,469,107,440,789,74,396,526,530,477,338,820,435,655,789,703,7,195,714,325,232,796,160,729,406,47,952,614,715,57,185", +"303,561,143,961,971,7,68,53,19,979,923,423,470,157,919,656,276,438,293,182,480,436,143,338,157,794,259,25,846,362,955,345,411,639,382,232,193,910,755,211,982,693,62,27,842,763,494,560,266,22,710,822,392,153,167,845,621,889,59,169,434,959,123,866,879,726,952,548,594,24,466,41,294,497,990,95,68,283,913,171,937,852,833,363,741,607,473,999,127,806,523,270,144,862,370,718,230,477,963,771,300,409,837,683,895,257,150,450,770,786,990,454,420,399,694,123,270,449,918,652,426,237,577,667,870,384,177,834,741,561,997,263,459,994,243,794,282,691,806,843,852,168,375,664,299,7,835,736,360,962,601,367,189,67,36,282,882,600,264,262,721,566,507,190,132,837,671,207,282,707,539,754,498,323,242,728,363,866,570,805,919,246,139,550,335,600,247,60,561,561,346,61,483,581,513,406,330,707,421,761,988,126,301,732,626,588,562,669,320,234,150,873,405,288,614,397,193,294,133,882,444,54,243,166,838,720,910,364,193,375,821,564,74,990,111,92,261,590,896,136,421,629,302,131,675,600,998,156,473,939,90,986,869,570,355,936,453,654,903,655,193,430,931,892,906,188,471,268,198,646,227,724,408,706,857,577,483,109,771,110,467,296,670,234,380,836,441,389,845,481,693,470,604,70,960,101,937,392,694,607,457,526,452,248,175,173,696,220,961,813,597,434,876,244,866,805,653,920,380,807,217,400,327,255,125,328,847,670,520,759,713,509,927,241,577,73,985,694,835,742,496,368,831,373,217,736,415,135,466,266,379,253,240,894,408,452,702,501,303,204,671,250,553,257,346,864,655,333,698,923,33,176,598,796,70,277,137,0,478,437,353,627,952,879,947,298,509,135,10,75,416,352,680,757,370,682,586,282,444,174,482,555,224,481,599,359,630,395,402,185,25,858,322,355,235,107,241,580,456,957,941,555,4,807,895,265,466,507,314,58,406,410,326,154,932,853,91,269,696,605,149,890,655,891,883,370,33,750,839,985,155,138,385,926,655,538,126,625,90,551,777,662,510,750,427,323,453,775,354,566,247,941,427,392,744,360,721,511,865,466,552,675,524,96,313,138,470,252,979,868,445,320,232,22,596,250,133,334,957,737,526,729,864,345,523,311,449,113,261,452,123,767,476,338,560,658,150,455,198,143,909,200,335,151,328,109,102,258,323,563,919,748,701,165,352,998,48,190,64,626,594,281,19,367,729,364,809,51,262,918,628,665,254,806,743,338,228,59,885,621,910,655,931,274,359,906,481,865,317,311,867,33,479,615,900,248,893,510,722,21,16,209,413,898,943,319,865,589,849,343,378,512,584,279,165,789,299,334,101,522,735,35,276,508,674,478,439,934,489,472,423,139,325,419,836,136,575,516,229,265,695,693,621,370,955,6,950,374,649,351,830,492,372,703,264,761,106,448,417,329,326,12,818,331,243,596,268,366,867,336,261,413,657,167,704,260,221,944,63,84,610,529,364,635,881,355,930,730,597,908,36,448,226,687,459,510,193,149,57,206,573,744,745,525,916,457,349,254,566,640,763,139,947,482,248,905,820,11,478,700,89,191,892,560,316,700,229,600,646,888,707,366,321,199,287,139,63,340,145,611,619,294,321,645,259,69,181,669,336,27,37,295,106,330,499,460,690,174,461,908,165,383,799,567,565,448,611,714,886,658,27,882,167,51,275,428,134,590,814,902,453,239,555,973,10,107,782,400,140,574,552,409,718,522,532,625,812,955,566,427,429,280,497,382,752,501,84,280,475,207,180,325,794,946,669,32,517,932,201,359,410,723,896,198,429,516,796,892,558,335,103,891,259,400,454,485,654,685,4,834,647,370,446,18,50,290,867,413,95,808,223,397,281,644,982,508,616,679,454,291,817,228,109,284,539,857,418,44,735,634,761,711,342,130,475,928,937,223,692,262,766,511,862,762,212,825,745,547,683,694,473,637,7,602,112,594,83,171,823,430,458,932,601,129,81,287,284,573,292,620,235,713,112,771,40,899,476,639,673,270,113,303,42,431,605,879,447,496,784,349,875,762,567,589,601,52,69,853,934,68,452,281,752,75,60,82,512,644,728,698,380,996,703,533,608,524,582,149,910,332,935,346,555,202,496,281,738,891,173,4,533,43,116,116,597,907,877,641,644,432,923,615,257,504,369,964,937,111,635,693,353,33,617,858,560,42,327,194,799,282,435,23,29,680,88,464,658,868,485,121,545,861,739,908,574,896,864,255,970,724", +"695,528,32,91,661,65,722,47,553,70,425,861,197,893,369,129,262,67,805,684,9,214,352,818,250,58,461,463,186,516,93,428,122,350,908,425,366,39,261,91,591,678,614,977,973,890,680,350,137,21,580,212,611,723,970,764,290,576,652,597,982,904,352,356,877,995,516,900,531,780,992,507,605,10,381,838,366,510,716,414,916,712,604,368,807,279,650,866,333,614,404,531,571,311,409,538,603,955,102,946,328,936,430,903,903,181,353,475,707,710,694,348,710,587,937,725,812,541,795,249,924,177,1,655,383,183,765,119,251,351,824,270,955,304,550,837,418,154,523,304,474,299,717,478,718,853,910,448,108,847,165,805,535,824,660,966,197,938,941,781,3,731,374,986,64,457,529,572,483,657,377,899,101,550,846,711,663,125,976,338,46,271,920,666,978,156,632,641,785,227,633,134,677,516,335,719,571,672,91,160,493,472,626,204,859,279,200,545,537,511,372,778,584,701,651,127,220,206,852,949,587,856,584,48,386,594,631,505,984,707,876,42,752,640,945,911,662,796,817,570,846,214,127,476,500,4,618,987,240,804,946,308,923,331,147,48,349,606,316,542,334,317,463,570,486,587,622,142,520,594,558,51,108,623,907,735,508,70,489,308,557,217,186,829,693,452,273,627,101,703,374,705,537,500,379,72,303,992,458,768,871,462,724,59,860,248,123,62,911,283,876,420,475,165,373,243,54,83,382,725,748,611,863,813,800,824,978,756,688,331,152,201,938,836,534,984,490,139,216,241,549,454,453,766,788,317,880,89,189,873,126,96,631,46,671,787,656,934,569,910,258,690,824,805,602,760,661,958,360,34,69,164,116,935,877,672,428,478,0,991,832,802,225,667,552,577,913,497,564,945,318,877,832,140,785,431,802,162,735,559,176,483,824,211,131,250,303,719,617,843,59,693,176,973,184,701,610,349,379,464,340,281,212,317,71,331,683,914,100,784,735,200,177,459,18,556,819,247,866,627,54,303,8,400,788,179,254,572,220,668,406,101,920,661,708,58,800,769,850,706,364,4,844,873,377,747,125,975,722,705,168,505,767,58,448,456,633,570,860,187,767,50,919,509,693,54,68,682,603,233,414,828,523,490,499,249,132,653,417,454,592,134,38,605,926,591,857,945,642,476,888,949,376,205,867,958,389,703,518,356,678,93,615,576,473,479,577,634,847,598,714,231,712,813,672,702,997,582,266,446,268,85,869,405,308,547,970,180,477,572,722,694,254,369,289,966,891,599,956,69,196,143,467,872,834,440,116,930,135,563,363,341,774,140,619,242,637,10,275,700,405,669,66,776,486,571,331,228,597,706,431,639,538,501,526,27,284,543,370,72,726,278,153,97,348,665,67,185,793,688,33,611,984,415,528,758,251,801,646,53,983,784,945,690,103,566,895,185,366,115,174,393,903,726,953,106,909,373,99,832,546,691,667,938,625,287,304,189,431,990,204,80,780,418,417,474,822,493,248,800,629,774,675,91,563,889,750,777,936,472,163,967,833,572,656,535,556,118,571,337,782,512,914,896,636,172,677,403,18,5,121,85,121,931,467,259,404,815,476,514,299,692,834,368,324,674,63,321,10,896,90,128,433,174,579,232,714,522,291,730,184,146,737,77,593,591,98,763,403,601,992,889,516,408,108,959,198,697,13,977,814,540,289,175,418,837,353,165,358,26,489,25,313,592,692,836,604,339,531,780,288,807,238,271,694,448,754,818,233,420,148,997,464,575,374,290,663,371,819,834,397,683,948,381,260,802,413,775,45,238,815,992,981,162,775,442,516,103,247,675,514,512,351,300,977,396,531,523,637,150,44,43,171,479,588,914,185,20,850,436,961,150,78,335,254,15,486,432,231,564,949,63,623,515,419,315,487,66,843,774,495,345,170,546,317,862,974,710,668,550,827,90,179,960,744,5,741,13,215,990,110,809,802,85,94,957,87,717,239,225,737,25,380,878,991,268,666,292,886,271,833,490,522,790,570,45,831,615,554,554,673,654,451,559,373,324,936,316,107,480,443,299,104,851,995,760,33,509,558,309,720,336,184,857,644,540,957,523,199,457,979,278,868,75,649,315,783,857,775,7,663,383,148,271,450,384,991,601,764,875,9,872,71,373,243,450,634,739,351,599,224,921,53,81,57,658,562,340,181,29,620,623,376,157,598,537,548,303,318,503,358,718,768,392,576,173,600,710,476,5,990,246,723,719,107,963,102,421,670,31,805,206,336,316,924,900,863,940,323,361", +"211,525,948,311,4,572,727,372,936,588,339,961,564,890,763,558,509,776,24,460,685,309,684,49,762,958,276,166,528,306,194,741,71,961,983,465,829,881,408,77,856,512,630,203,579,530,560,983,937,807,926,215,163,989,130,925,568,34,650,458,311,51,824,169,32,682,321,231,835,822,266,70,394,51,411,323,799,898,417,882,776,680,685,763,549,121,178,75,157,157,840,51,422,701,709,570,776,830,797,909,843,152,724,75,584,57,906,986,586,948,546,125,975,430,326,134,99,924,86,613,885,992,780,612,745,137,781,102,655,467,377,946,83,960,744,75,470,156,497,516,171,177,362,76,505,286,931,818,92,548,236,814,476,680,9,533,481,913,112,649,314,50,162,427,801,459,938,424,82,372,13,815,336,829,264,597,549,641,808,245,47,35,770,551,760,224,368,9,823,109,750,392,692,76,500,416,998,697,634,925,406,466,352,747,157,964,344,378,621,4,861,726,882,215,906,460,107,412,911,128,581,228,971,549,465,132,415,335,364,350,931,436,432,14,27,62,797,586,944,135,620,752,751,167,328,386,252,186,667,751,869,12,655,382,529,865,831,880,702,35,55,160,675,662,688,567,519,952,458,496,663,388,128,663,238,209,846,27,927,566,885,282,63,751,717,11,214,624,342,459,476,296,579,8,802,347,857,691,528,307,978,783,474,874,482,292,260,304,484,877,434,198,418,604,383,578,917,415,247,16,137,538,839,44,47,920,307,260,122,481,66,645,169,701,831,892,265,435,803,821,996,197,409,126,311,632,295,538,767,483,650,604,245,940,457,796,685,161,717,718,576,814,408,353,426,194,892,501,405,732,45,743,383,694,609,212,278,437,991,0,808,114,207,395,95,82,47,332,462,367,210,426,193,201,630,770,756,511,690,74,828,866,245,262,992,163,316,174,253,341,164,374,650,510,766,618,185,249,908,801,60,56,310,475,16,904,199,721,114,290,582,298,873,688,226,4,395,785,438,873,445,955,491,119,832,246,234,529,83,909,496,311,278,374,425,425,875,443,644,498,532,786,930,877,526,36,257,167,621,407,979,489,998,348,435,391,741,992,232,72,748,627,137,673,148,940,618,930,952,89,961,345,469,104,332,556,548,48,968,814,495,317,851,745,835,749,685,106,897,962,127,303,436,214,40,94,992,224,847,79,85,824,775,392,927,599,901,611,724,793,121,226,801,905,976,968,682,580,440,353,660,100,226,87,407,863,257,719,36,598,678,736,411,917,750,502,423,780,205,923,587,30,174,702,179,138,167,992,399,756,143,332,524,741,296,679,564,355,413,317,505,464,335,683,558,72,890,387,66,600,971,237,726,811,160,613,942,5,178,346,510,460,665,419,110,673,889,579,877,368,674,720,975,818,663,206,935,443,22,907,203,853,312,886,750,883,426,460,973,50,192,486,230,645,738,619,489,177,993,972,346,790,315,434,923,719,76,12,673,355,941,964,437,845,123,34,657,404,58,431,712,400,441,531,695,648,149,826,59,161,364,427,801,243,569,814,445,645,110,577,674,180,514,182,917,34,79,783,820,938,54,66,277,108,817,210,243,299,954,451,766,856,472,401,655,686,858,605,328,635,322,70,492,555,976,481,490,320,227,864,531,101,530,825,829,380,8,827,99,211,681,795,426,646,170,419,899,611,340,622,424,234,64,826,289,770,125,63,481,540,807,389,243,271,911,986,277,863,4,945,733,282,621,236,912,989,946,568,558,431,75,18,539,690,299,650,574,563,463,446,992,70,164,762,336,581,317,115,336,340,136,782,999,995,800,753,875,15,406,291,254,749,308,153,117,176,392,950,647,137,978,286,221,423,28,175,574,695,811,917,311,140,478,164,572,996,313,53,862,728,610,860,829,643,706,210,592,100,245,677,758,838,248,236,408,94,730,814,957,498,405,649,139,248,832,317,815,159,141,505,922,397,197,200,768,594,302,600,679,417,366,426,47,84,962,422,594,880,817,691,989,418,185,62,778,831,161,918,617,48,106,67,114,185,130,729,203,439,647,925,150,707,391,257,260,525,689,950,933,419,857,935,486,919,936,298,54,847,227,506,378,871,467,706,349,464,385,62,606,512,526,378,663,410,299,861,229,344,83,16,861,114,153,378,141,989,93,936,458,848,920,605,35,442,672,95,361,95,504,156,532,310,681,431,639,15,428,105,370,258,955,334,694,984,849,94,224,224,574,806,413,241,115,812,167,181,507,969,456,671,941,389,484,305,449,460,325,641,660,77", +"957,333,772,494,853,807,255,257,616,389,481,231,525,558,863,169,66,289,69,166,609,774,373,85,789,520,273,48,391,588,559,530,955,597,488,387,85,576,250,320,537,509,300,694,625,617,681,338,278,80,274,828,785,648,627,210,761,741,118,935,795,763,545,897,772,755,8,428,900,816,548,759,213,249,96,83,14,150,176,808,473,150,503,191,619,607,641,899,624,855,948,813,136,740,110,917,180,588,518,737,566,975,796,810,255,964,233,826,842,976,696,2,968,723,895,231,7,376,523,686,350,583,314,328,477,670,473,408,345,5,65,233,139,287,57,423,633,766,130,741,928,836,463,768,458,749,57,30,178,379,360,557,435,562,992,5,94,33,201,796,624,17,540,120,234,61,91,298,272,255,443,59,239,107,129,884,71,306,237,344,814,26,894,996,918,402,329,123,191,1,980,381,473,47,779,360,795,918,108,679,886,419,439,779,390,305,411,650,283,276,618,944,118,191,223,947,70,827,588,997,106,407,315,104,788,656,520,347,231,9,887,376,662,296,142,67,564,320,217,194,626,688,54,568,632,366,999,573,249,331,635,756,900,982,944,552,72,207,865,885,313,294,433,303,632,305,607,713,210,778,703,743,614,3,494,779,236,328,956,589,607,960,454,703,304,694,684,650,439,726,820,942,801,818,630,748,966,514,6,136,199,160,69,751,730,747,473,696,605,7,32,773,187,118,303,64,781,418,479,635,727,610,595,843,919,850,569,113,999,472,193,40,615,264,537,828,925,861,617,101,728,62,420,745,214,177,731,930,622,164,498,879,81,926,437,116,83,261,88,196,236,330,524,901,82,177,925,531,855,965,947,161,91,127,198,814,315,353,832,808,0,708,164,420,409,99,253,631,750,630,177,22,740,669,288,277,915,804,817,980,278,625,49,374,777,572,488,667,108,224,142,871,111,332,741,801,16,574,412,48,704,382,33,951,789,584,576,226,172,933,525,341,638,694,167,280,606,888,529,916,915,576,126,609,335,226,50,828,166,105,670,116,657,839,822,921,628,84,540,705,611,242,754,486,896,796,515,590,30,647,333,711,259,219,804,465,206,162,668,739,152,197,863,784,727,194,719,211,99,955,339,551,312,136,654,706,725,120,272,828,236,404,412,821,321,600,374,687,469,769,99,672,352,725,256,168,653,376,963,342,423,533,948,139,497,702,345,750,285,282,332,667,514,960,854,254,23,840,766,787,634,223,216,892,47,166,200,728,997,187,800,548,121,718,527,10,613,976,975,212,877,862,485,650,727,175,427,11,373,527,147,438,490,383,441,296,397,620,485,636,2,681,387,401,241,734,761,545,555,782,591,729,34,663,616,263,636,382,295,394,20,672,402,53,762,366,299,364,468,430,78,551,785,510,788,52,424,128,931,637,592,896,573,25,888,271,90,220,598,670,937,929,583,646,655,475,920,431,701,136,981,68,822,708,816,668,693,220,561,297,352,402,739,613,35,604,35,154,738,229,443,404,821,163,506,956,611,207,798,450,873,93,829,347,860,752,190,595,978,339,557,496,973,113,889,381,624,292,262,884,191,678,828,187,93,362,829,592,203,885,542,376,4,942,836,724,190,21,776,409,24,9,223,935,252,634,653,532,170,908,869,940,856,11,135,690,742,897,742,754,726,48,837,222,133,782,599,287,4,857,346,998,331,30,318,128,824,857,24,262,204,976,915,932,304,26,956,414,622,288,123,114,314,294,539,516,342,642,280,68,569,710,685,203,449,856,508,794,709,661,378,317,469,778,547,34,788,235,659,392,706,485,61,728,296,417,797,108,759,96,424,82,861,648,443,903,53,411,664,266,553,835,380,845,684,482,649,992,493,568,431,403,770,874,373,926,402,530,568,999,549,660,171,319,973,505,274,60,36,691,183,420,807,294,24,630,44,956,33,447,392,916,611,209,431,484,334,574,224,935,158,705,101,981,225,357,660,767,844,301,975,204,211,222,525,42,114,443,2,117,6,159,134,636,365,455,591,164,275,95,126,234,885,798,95,860,610,389,640,237,729,433,699,617,515,368,22,456,821,959,657,899,914,683,447,270,318,203,461,795,721,571,410,556,100,957,9,404,666,105,421,842,297,291,398,858,683,458,571,824,359,959,446,249,742,519,710,923,401,661,217,280,493,119,876,630,609,258,395,931,29,443,846,263,848,738,452,373,821,337,829,156,985,948,833,275,783,560,512,931,129,988,715,607,194,857,214,774,253,748,87,283,686,840,888,908,886,110,444,587", +"685,986,901,25,257,967,819,43,104,826,426,126,137,844,479,931,358,111,447,550,194,34,835,165,919,936,708,860,983,40,271,619,796,694,808,2,666,475,248,862,185,992,735,629,204,827,393,66,303,575,656,333,212,819,532,61,372,703,177,440,947,753,252,809,154,225,600,657,694,560,160,755,861,247,603,723,269,472,932,826,623,788,593,341,74,113,662,357,154,779,978,711,966,163,248,250,169,267,144,755,947,285,243,471,766,346,442,519,429,664,890,856,910,228,915,310,653,116,436,660,816,959,333,936,146,246,167,124,52,121,374,749,341,147,343,826,158,484,702,218,213,103,743,684,167,298,529,59,332,824,253,229,558,483,964,417,705,656,134,641,931,823,275,791,7,639,929,4,794,381,201,911,367,925,179,874,424,583,897,621,66,838,158,694,187,941,860,676,965,620,786,882,196,359,507,807,620,943,850,25,346,649,871,751,387,16,132,957,716,889,725,815,277,378,844,505,990,736,303,78,675,89,39,303,109,231,41,671,856,304,4,671,533,40,299,798,772,87,90,679,786,578,953,887,107,590,9,448,823,453,650,394,82,887,33,145,875,406,997,906,936,683,129,304,428,979,198,401,983,181,288,939,409,342,359,465,376,505,950,527,869,616,406,588,427,820,259,719,831,642,132,333,174,700,188,585,153,36,739,246,94,213,369,714,804,609,317,33,484,331,991,842,978,470,175,320,16,563,170,140,405,928,82,951,803,824,751,111,934,136,227,409,379,529,244,132,721,854,541,736,341,342,663,687,630,913,908,440,873,964,53,777,327,827,145,96,872,324,221,477,247,555,250,294,479,272,463,295,401,33,631,112,433,11,131,167,376,627,802,114,708,0,749,561,681,455,970,836,584,84,272,456,738,40,181,765,899,246,142,49,721,214,313,810,93,854,87,74,760,225,463,320,108,590,685,711,257,256,405,51,566,198,180,568,740,544,683,836,231,914,85,548,623,881,435,314,383,361,625,767,870,207,390,340,332,900,214,514,287,898,42,965,849,65,525,435,647,523,862,238,411,298,472,657,824,508,771,912,681,894,250,249,815,191,935,579,948,948,569,338,265,238,94,97,724,878,444,509,876,994,835,920,293,758,603,361,841,790,432,544,57,734,225,574,44,884,205,171,459,912,287,136,836,857,9,969,941,789,405,609,549,585,706,213,369,9,703,627,800,702,486,399,492,499,985,274,402,744,964,658,487,896,685,970,1000,163,536,53,438,376,587,531,807,915,446,747,721,894,20,157,125,719,20,199,237,620,568,503,235,707,631,71,490,42,965,907,552,328,484,530,653,333,409,260,855,243,37,562,153,277,297,938,340,467,89,718,561,81,469,586,168,773,211,676,285,6,703,523,903,427,251,430,379,469,213,829,540,479,53,793,82,675,338,308,674,92,768,636,50,551,539,802,285,600,697,867,162,462,91,376,258,734,674,432,348,550,154,994,432,759,523,490,206,634,460,790,674,149,13,392,52,409,591,85,113,623,198,278,141,571,271,933,709,399,124,69,137,169,296,999,645,147,16,484,527,259,754,356,775,787,60,989,968,762,530,912,717,126,204,609,230,546,734,645,449,878,922,643,682,660,768,266,531,370,268,75,440,335,498,303,511,77,428,369,568,190,591,863,448,464,771,559,939,290,86,237,775,771,153,571,541,531,907,722,13,511,613,836,787,220,744,583,361,328,928,197,226,550,810,195,316,738,773,416,372,529,805,453,17,286,84,796,989,869,624,359,98,650,651,773,467,762,657,942,628,505,363,986,41,814,608,453,509,968,404,352,594,903,442,953,34,112,545,12,653,475,837,166,216,688,243,452,20,751,609,390,14,941,312,315,165,197,775,553,625,707,248,654,495,101,522,208,996,531,156,812,505,408,832,814,459,52,112,887,460,735,248,606,694,229,644,494,95,173,601,91,581,770,360,53,796,194,847,450,302,601,298,83,503,385,191,67,952,511,589,536,374,427,278,322,994,666,890,751,303,301,245,652,23,434,724,438,447,5,685,654,25,92,785,37,20,823,656,676,180,789,50,450,562,609,729,278,462,196,36,171,193,995,13,279,826,841,422,508,195,526,159,971,704,621,772,454,463,452,695,583,108,84,987,418,312,962,684,781,494,157,449,240,806,972,987,223,286,54,534,255,417,36,360,572,816,88,5,706,576,672,326,345,897,357,290,116,757,713,736,690,590,305,925,468,201,615,139,424,375,851,646,614,87,345,20,580,631,796,237,561,223,935,78,699", +"686,829,538,587,935,221,521,765,673,430,487,765,683,217,163,228,670,329,152,841,973,349,523,314,304,712,517,297,291,996,332,490,490,421,496,459,102,451,268,975,70,105,638,286,228,800,182,992,359,927,93,636,334,132,194,797,785,282,524,156,249,864,58,167,39,422,941,537,44,81,964,539,602,427,643,663,812,599,729,619,626,995,428,546,93,852,898,645,273,474,169,946,733,982,393,357,132,459,654,58,407,808,134,879,131,768,493,349,437,26,91,11,109,574,692,361,247,268,232,335,380,416,738,606,754,658,935,28,102,477,755,829,980,367,690,671,970,727,278,631,253,834,896,316,154,21,341,53,420,955,668,660,931,594,890,881,983,578,302,874,502,229,19,563,145,828,461,670,986,855,582,502,192,521,129,471,218,674,603,742,94,442,671,802,523,467,818,617,963,597,763,886,137,515,944,620,340,332,36,225,706,503,235,795,557,278,793,233,583,263,385,138,812,756,990,11,222,26,178,268,258,297,458,960,539,139,459,624,577,671,362,126,311,337,961,970,216,377,258,663,388,315,568,69,970,154,69,644,83,530,888,389,944,846,402,331,105,962,473,102,117,411,194,815,375,87,25,940,980,987,510,917,502,765,139,794,620,652,980,784,794,80,393,550,465,703,222,71,358,538,509,1,913,28,135,77,471,386,306,392,921,186,635,182,959,289,595,497,901,644,316,245,766,127,851,391,74,448,246,143,434,110,206,81,137,338,603,816,137,356,86,431,348,28,455,416,308,114,142,626,159,11,379,287,220,819,890,560,800,15,986,702,81,500,908,336,562,190,87,613,127,652,947,612,47,227,751,928,306,337,542,630,4,209,189,685,954,952,225,207,164,749,0,170,1,423,712,470,17,453,330,924,552,950,349,119,950,169,728,902,586,545,995,344,230,374,228,132,49,730,461,117,728,818,905,84,767,805,562,703,574,55,53,731,657,990,345,335,871,214,229,997,467,980,592,969,902,247,523,811,738,193,411,909,992,930,24,28,913,720,28,354,190,992,819,68,473,509,651,513,469,12,963,782,264,90,280,51,749,778,920,84,409,584,730,841,270,140,349,865,462,42,674,727,494,581,303,52,359,157,453,955,493,738,602,445,117,799,925,248,689,447,978,258,115,211,499,349,139,366,742,151,343,141,183,226,818,458,968,379,455,29,440,274,725,198,22,675,441,626,216,521,25,606,901,907,942,729,583,418,142,800,469,42,945,197,581,848,137,366,656,914,471,397,736,545,257,648,815,942,941,883,436,74,640,113,855,259,523,140,911,415,991,399,421,13,158,598,777,475,977,440,886,459,199,966,46,889,681,987,137,150,692,168,317,195,250,846,619,660,597,603,513,442,121,701,915,792,283,611,846,85,795,642,699,544,871,487,269,186,166,122,710,603,8,326,890,996,941,139,53,659,814,537,93,463,502,157,822,346,596,424,696,459,854,741,823,479,4,585,428,775,212,216,368,492,838,6,191,482,633,439,257,519,91,175,212,606,429,382,539,431,254,96,213,874,708,14,467,94,953,704,333,347,532,899,615,137,473,367,734,814,243,970,112,801,808,830,8,979,25,271,128,941,916,352,396,382,599,459,380,317,774,12,995,694,169,249,926,237,174,363,707,418,840,69,402,242,637,136,413,375,761,454,170,248,714,729,778,278,127,585,760,358,62,887,269,245,580,976,722,232,14,977,919,47,442,687,267,846,472,895,713,912,170,822,7,424,170,218,231,370,405,335,807,106,176,576,365,395,771,824,457,468,680,476,892,721,722,309,762,351,455,965,829,762,231,525,723,211,507,91,608,874,767,720,966,90,572,353,497,173,38,661,677,417,631,294,53,855,46,441,171,336,237,462,806,250,601,800,175,329,308,949,895,4,770,119,805,872,813,998,187,918,680,933,808,958,578,661,623,150,958,83,328,764,679,988,80,434,279,234,561,650,672,326,188,330,715,172,736,792,352,217,78,737,442,583,345,724,898,797,949,129,765,190,69,976,478,822,41,746,746,400,462,527,537,727,358,47,49,763,846,684,896,687,801,270,91,457,638,85,948,105,744,185,599,368,618,962,396,937,546,450,122,202,51,677,296,638,600,338,972,998,404,692,468,966,578,74,775,452,370,316,74,362,245,478,363,251,252,252,664,790,983,576,901,293,509,371,524,672,528,704,488,222,374,30,764,273,577,974,340,606,905,251,134,538,11,85,869,348,450,703,788,573,968,96,459,485,106,336,940,751,368,538,529,23,999,702", +"98,680,930,780,245,16,605,652,92,288,26,160,450,152,73,133,409,895,629,386,865,945,826,695,919,345,69,714,16,835,303,12,912,100,215,88,160,130,915,238,584,250,883,772,170,151,551,149,116,770,383,344,808,183,732,272,999,48,580,34,764,159,460,289,321,306,245,165,139,248,728,705,596,192,185,476,912,453,475,957,623,277,207,552,125,66,737,680,865,88,306,940,594,325,135,603,212,166,60,299,928,477,776,291,671,36,573,342,883,617,409,615,343,637,819,812,186,917,251,382,52,994,691,63,97,663,503,948,881,355,486,474,411,37,483,467,840,942,663,660,767,459,194,616,899,509,512,86,548,376,691,968,103,932,565,448,161,857,401,237,791,25,192,173,166,687,201,998,99,900,883,595,219,7,728,975,439,584,392,725,357,272,143,551,19,508,438,762,604,369,263,66,880,962,869,769,9,951,42,184,44,846,484,3,785,722,675,597,594,748,257,975,970,69,376,607,785,650,559,649,480,158,292,367,664,854,56,175,218,647,451,532,3,250,873,38,668,564,874,751,451,376,742,651,948,195,680,604,436,216,41,335,292,431,99,324,923,27,276,795,155,59,566,374,50,324,961,183,696,227,746,388,727,157,171,369,388,262,954,202,62,261,105,110,341,715,960,476,17,79,143,73,948,999,375,282,468,225,618,937,517,33,892,395,114,217,469,664,924,362,506,88,859,185,368,742,918,635,481,107,689,108,20,536,520,349,85,879,535,237,960,5,754,639,618,196,927,333,315,790,698,471,54,916,427,9,488,969,949,180,153,148,492,380,626,141,582,576,266,694,994,402,279,203,231,857,339,663,566,297,410,224,642,199,703,806,315,879,667,395,420,561,170,0,695,201,204,129,339,659,329,857,417,996,830,713,219,31,939,853,348,941,93,782,303,293,333,79,921,41,228,486,78,673,643,366,308,682,497,574,954,788,617,532,273,701,269,900,860,871,340,128,20,347,22,137,419,412,919,493,46,786,263,21,313,352,38,23,638,562,565,748,685,310,952,932,869,251,352,475,918,739,213,868,523,18,997,920,949,150,333,236,84,41,952,479,630,266,607,638,89,297,367,268,815,928,655,342,809,338,620,743,888,82,407,880,525,403,396,958,997,792,850,881,299,905,331,969,970,487,197,494,367,23,248,562,105,61,617,308,745,218,212,514,8,763,196,438,280,49,411,782,829,848,727,839,976,16,277,824,793,685,578,772,647,953,45,25,113,3,533,898,7,902,909,392,488,399,640,249,443,117,601,505,126,653,784,169,613,229,1000,36,724,56,446,725,258,623,445,189,591,798,118,418,56,781,151,411,59,103,241,701,389,802,210,173,777,48,606,146,3,731,798,94,456,78,288,22,254,539,649,92,470,828,29,454,647,558,942,661,401,907,60,34,372,903,299,495,514,472,808,729,313,208,913,191,577,736,953,634,494,285,119,422,455,317,622,935,930,509,267,638,931,780,880,982,448,91,994,737,153,995,158,507,2,521,904,887,977,201,671,844,484,806,942,753,354,304,95,926,647,52,330,824,509,928,886,932,704,400,550,54,716,261,45,541,486,260,523,855,482,839,158,834,968,851,413,955,401,412,173,791,189,842,657,17,844,341,762,595,127,197,351,425,602,182,277,419,846,805,663,509,974,164,602,91,424,656,168,954,920,486,235,876,221,57,226,465,745,818,64,237,613,493,163,164,449,883,136,293,431,821,980,158,853,281,98,387,953,539,942,29,868,188,785,980,944,531,490,650,246,758,19,791,795,663,220,194,886,563,103,875,616,707,506,479,871,696,246,460,740,564,811,674,957,515,140,381,778,545,264,876,223,170,785,457,441,940,233,314,563,626,712,56,867,464,411,366,914,682,955,863,72,640,289,404,144,591,578,771,556,2,98,254,95,740,34,92,475,667,437,338,901,470,575,527,815,203,948,85,669,6,619,826,770,44,211,345,368,67,21,384,114,994,889,739,848,419,460,571,148,743,284,55,692,203,402,374,907,603,92,715,371,483,777,678,50,657,571,433,760,627,530,101,15,682,46,845,554,534,703,456,731,135,816,159,105,341,263,62,546,946,38,993,626,559,289,183,78,658,470,360,414,37,237,816,80,570,895,636,894,676,647,783,552,378,210,739,278,888,486,355,901,17,925,680,235,504,699,812,918,508,895,433,542,724,359,820,599,711,909,160,799,192,632,971,158,74,424,551,815,624,441,639,645,216,791,282,546,586,825,64,260,604,133,650,70,726,256,220", +"902,587,299,924,552,131,886,81,234,898,374,710,148,464,322,632,287,621,771,440,313,265,582,13,373,763,224,799,776,153,320,545,744,196,446,943,8,314,37,397,812,78,917,740,611,226,57,237,657,619,121,782,798,550,101,519,536,846,441,650,4,412,996,383,111,106,376,809,585,438,687,691,664,820,105,944,601,236,89,787,265,933,887,452,435,358,577,108,76,65,873,458,204,911,536,738,423,993,805,380,551,466,387,487,899,957,857,75,719,140,287,86,618,798,588,925,326,900,35,124,60,630,424,386,641,602,953,601,606,635,731,297,782,658,927,117,336,669,222,142,485,973,793,697,886,233,286,423,217,840,851,70,300,388,826,381,875,405,99,171,567,709,762,796,502,766,281,466,40,157,865,79,300,603,306,964,422,602,115,51,319,884,601,616,269,950,209,878,718,528,723,144,23,99,204,998,54,808,409,956,727,417,243,517,107,490,916,856,531,281,659,350,626,570,884,728,137,142,19,331,633,149,176,583,753,975,855,773,280,599,225,635,845,860,561,592,319,512,355,155,910,455,899,551,271,607,533,312,764,725,863,496,711,472,466,102,980,877,809,848,826,970,262,325,906,186,460,962,447,857,680,390,989,869,435,886,415,288,683,183,895,389,880,773,260,748,946,694,577,800,771,700,905,140,956,872,341,140,127,847,570,440,419,544,753,498,837,404,703,110,271,286,78,686,470,563,862,74,519,111,609,143,594,364,139,869,728,667,373,779,984,537,735,137,313,36,259,524,137,984,23,553,635,404,352,218,335,344,369,427,207,63,81,437,869,915,35,307,657,20,231,628,743,17,736,112,685,24,526,894,55,382,430,326,18,36,273,947,552,95,409,681,1,695,0,490,706,683,184,435,357,267,60,471,612,324,612,627,842,459,594,610,381,362,20,672,547,573,642,473,31,572,432,474,260,827,54,398,487,766,437,836,819,215,599,964,90,685,750,833,698,850,302,831,168,668,974,198,363,538,694,225,320,36,698,500,614,972,115,659,545,127,664,653,595,504,829,221,378,82,956,202,241,249,858,979,237,726,90,497,755,351,358,902,329,992,813,486,432,784,162,899,493,432,842,566,872,347,630,126,375,627,803,465,898,405,352,699,254,838,663,413,906,959,922,821,646,566,79,241,909,531,268,941,863,772,653,243,901,609,134,97,61,906,681,426,344,97,158,43,775,311,397,801,561,757,795,413,719,444,484,947,59,455,405,309,830,347,909,259,994,235,526,358,97,400,40,711,789,485,540,315,148,826,682,748,47,418,679,619,911,687,524,64,406,903,896,868,810,574,971,745,920,162,226,495,18,228,695,423,337,779,102,816,519,610,29,835,503,200,743,51,878,892,112,166,355,465,174,413,106,671,236,874,64,736,322,661,620,612,98,394,611,244,686,240,47,895,859,971,342,824,378,865,893,219,725,253,845,256,385,953,590,46,629,25,852,810,30,116,125,83,792,54,91,957,702,813,447,208,283,851,643,262,200,551,963,861,293,475,262,208,741,644,543,709,138,513,967,372,437,244,280,595,787,550,507,83,570,545,960,862,499,391,20,277,131,396,254,116,254,616,313,838,946,101,403,474,863,714,14,428,391,26,354,367,267,639,553,95,337,872,308,445,799,983,795,935,591,541,58,693,927,232,684,159,125,252,82,511,990,704,633,682,350,919,471,797,592,605,692,111,222,730,975,864,766,199,959,395,193,197,565,739,824,441,195,682,286,142,348,915,396,478,831,263,519,204,451,530,28,865,817,869,400,757,507,818,406,787,460,320,44,466,184,465,274,405,936,804,850,833,263,681,499,56,912,237,347,392,933,795,392,925,349,682,5,446,629,832,755,845,384,157,472,126,343,382,214,763,973,841,875,89,767,164,3,217,531,801,329,409,813,161,729,827,186,304,387,940,771,838,345,977,972,130,556,845,208,478,268,684,188,154,430,103,789,499,313,967,976,487,80,968,888,970,499,363,27,605,238,648,735,748,435,519,917,137,691,833,832,334,964,621,768,429,347,544,30,115,88,266,851,156,232,405,774,686,871,881,408,666,156,494,448,582,378,755,40,157,75,566,897,544,918,135,698,941,799,652,602,279,545,656,78,315,342,814,574,680,914,394,333,737,850,927,538,182,400,915,667,340,379,798,110,517,792,517,936,609,557,651,506,779,27,157,98,686,278,176,315,92,18,492,457,981,719,727,775,576,851,157,756,49,369,218,442,423,816,927,683,140,323,859,853,817,302,393,696,394", +"725,336,181,897,766,72,353,518,454,467,839,299,161,967,2,785,352,944,586,750,270,95,816,785,326,234,193,871,805,746,323,165,391,561,204,291,833,923,592,47,282,375,144,899,683,335,125,16,231,671,318,119,723,843,385,38,702,627,682,205,835,322,697,68,227,600,663,7,217,172,948,328,295,272,295,858,417,231,568,984,23,43,292,60,358,831,22,47,837,385,304,241,714,257,473,812,300,648,673,580,827,93,74,767,776,279,6,207,51,590,413,761,728,662,75,855,896,690,654,408,566,112,821,49,751,83,470,158,344,540,213,320,368,207,225,609,182,977,298,442,447,865,314,182,721,148,929,425,137,740,53,530,586,297,946,755,922,536,303,786,919,768,862,411,980,760,936,911,30,725,736,392,163,530,956,171,466,715,73,627,261,322,668,477,817,660,899,390,814,326,358,356,827,760,84,385,933,831,330,372,477,540,318,988,869,823,230,444,298,192,640,474,440,231,565,506,676,338,943,442,546,143,398,373,493,400,658,818,805,239,529,590,963,639,745,776,343,666,6,118,265,105,685,696,371,779,417,470,452,292,49,595,429,248,76,189,965,601,275,240,42,925,643,575,963,554,771,417,882,743,36,820,6,985,806,286,210,224,669,25,730,972,199,558,502,224,474,726,75,596,897,342,975,453,184,270,437,672,185,79,894,301,754,386,888,743,645,105,458,69,465,825,133,29,462,409,87,726,613,216,541,694,296,727,97,273,322,280,166,693,396,734,434,9,632,358,216,742,852,908,774,983,276,298,745,78,479,778,911,707,876,498,706,937,690,190,822,165,540,442,676,151,499,28,277,459,915,364,996,200,171,558,817,888,392,695,399,298,577,82,99,455,423,201,490,0,737,551,584,320,98,120,322,575,858,700,161,817,754,255,483,705,668,555,962,370,587,851,263,294,276,685,928,670,56,239,922,410,942,833,186,589,544,39,131,184,963,341,204,426,251,748,842,592,433,515,504,475,946,290,459,195,324,165,592,534,277,890,443,601,748,890,411,602,489,152,5,799,739,87,279,973,844,358,129,697,825,117,124,361,950,883,529,240,577,775,681,81,61,39,305,796,113,641,236,409,673,175,250,597,596,592,942,259,522,5,798,199,945,831,144,39,485,85,227,558,684,609,585,913,971,689,103,661,89,162,410,205,792,511,608,564,536,130,73,762,18,955,354,629,440,273,62,754,816,304,175,360,734,733,256,158,19,244,193,812,754,757,515,78,713,25,557,643,531,206,638,400,677,159,101,929,688,923,268,802,245,19,675,533,619,665,270,146,508,551,24,798,510,626,677,173,291,654,623,250,840,863,185,70,777,20,61,542,917,97,257,101,995,37,507,389,71,985,254,396,88,180,625,220,312,958,358,607,750,769,352,780,688,31,700,326,348,212,195,853,338,861,727,966,823,864,780,951,334,266,204,307,151,921,465,156,390,8,912,937,551,45,362,156,722,797,430,212,957,420,136,660,556,36,552,346,936,527,953,441,654,399,230,988,333,63,528,241,989,824,288,784,100,34,624,74,471,559,450,684,185,138,563,613,649,596,933,209,499,641,60,170,489,567,111,253,615,286,872,161,275,488,890,358,739,367,673,823,301,759,553,226,821,968,922,550,429,936,889,243,663,65,557,518,635,473,752,778,89,236,941,237,305,4,410,361,137,250,456,227,81,23,194,29,266,810,607,217,878,317,497,335,778,60,241,679,543,9,705,230,934,803,943,139,774,155,893,703,273,521,195,456,449,483,694,737,453,351,831,616,486,769,166,731,498,495,192,239,471,17,287,817,561,524,423,415,433,454,398,77,978,166,239,62,883,72,115,682,800,934,854,173,758,519,889,320,385,512,453,520,186,373,264,834,109,868,775,367,216,871,251,827,469,628,369,501,192,749,441,32,262,879,66,991,896,23,257,943,353,898,5,426,188,452,136,14,914,43,256,330,634,287,803,654,94,533,128,156,348,991,242,357,521,732,608,481,642,670,648,694,992,364,177,79,894,872,670,838,841,406,595,555,878,458,528,376,824,636,811,108,914,966,373,14,280,436,58,7,618,275,534,935,380,517,992,492,139,910,631,809,970,861,478,6,357,442,685,796,416,824,967,249,859,235,389,781,839,790,450,839,359,198,324,874,494,893,313,885,183,73,602,308,497,195,798,398,202,772,252,900,400,89,269,117,202,689,474,516,168,569,927,36,498,364,688,605,600,199,642,729,212,309,427,270,38,379,42,671,493,210,86,850,482,838", +"707,182,886,532,465,635,937,314,653,637,319,41,608,55,176,648,482,125,353,517,570,235,981,294,845,345,625,621,49,713,813,42,248,36,532,774,792,657,510,422,510,811,515,676,510,884,933,183,618,733,980,80,456,888,425,509,871,141,165,982,48,543,329,236,67,603,186,599,750,787,205,670,555,771,870,611,787,801,599,413,318,942,401,63,456,600,378,534,689,387,96,131,187,198,117,198,307,109,335,822,849,157,419,252,84,406,536,136,660,770,190,126,623,218,917,126,45,217,340,889,765,657,537,50,199,120,166,711,901,326,511,339,862,230,757,777,547,746,997,161,975,524,708,305,986,997,592,820,955,489,174,184,837,892,967,246,492,344,189,920,173,266,763,17,485,691,967,976,121,690,729,139,643,204,604,776,784,260,824,583,140,404,199,305,556,254,999,670,290,798,210,334,76,358,377,725,178,946,915,59,631,431,496,427,377,485,724,400,118,152,149,158,587,123,854,585,260,552,668,733,692,227,780,888,278,501,130,434,882,693,771,560,978,768,312,724,220,669,847,159,562,699,783,303,178,91,16,909,897,545,332,467,913,43,470,218,174,956,818,338,595,691,860,278,191,194,418,319,204,884,728,977,978,686,338,847,808,504,874,516,679,144,761,991,779,868,874,249,207,494,404,851,456,491,172,253,646,188,365,858,882,581,361,979,798,536,474,699,806,727,712,193,394,49,803,726,505,301,719,14,928,278,428,854,454,607,58,643,52,371,689,184,440,510,641,138,825,850,234,590,897,543,73,255,225,942,129,862,396,594,875,810,19,436,891,525,26,205,765,693,640,655,99,131,369,811,214,366,13,511,135,235,567,865,579,319,241,509,913,47,253,970,712,204,706,737,0,960,852,701,593,538,927,491,27,396,951,111,406,870,806,929,937,16,161,151,82,339,671,657,350,617,243,910,863,741,129,293,395,33,460,291,387,620,226,350,284,605,534,617,656,422,419,467,830,993,866,39,321,727,130,725,776,140,8,654,828,67,650,42,936,96,570,976,461,926,18,376,303,469,130,166,17,45,883,719,711,525,317,928,203,641,855,498,957,578,269,690,113,858,306,707,301,281,516,690,910,320,424,791,452,290,910,931,572,327,785,689,581,557,554,779,366,600,692,760,916,587,733,113,737,123,894,977,442,389,993,249,457,557,29,800,416,612,571,467,50,269,309,686,31,573,558,918,185,351,43,140,846,333,67,656,38,161,924,407,535,955,185,154,408,855,853,836,278,490,296,760,9,419,809,786,439,303,101,117,449,16,310,841,678,858,47,645,925,620,812,565,454,64,659,122,142,495,597,963,483,518,462,880,222,201,671,502,510,237,602,665,392,309,621,199,647,800,996,772,594,56,675,611,641,284,197,754,203,827,354,64,334,424,273,417,429,327,330,540,750,819,731,232,831,970,192,445,551,564,951,861,347,238,227,487,510,989,313,258,414,9,181,296,364,641,950,566,73,967,28,940,124,935,745,939,895,34,421,80,228,414,293,112,113,748,2,284,709,998,677,470,430,866,814,855,519,666,365,568,964,400,158,24,314,906,581,220,711,111,401,928,661,972,775,618,504,534,105,966,617,483,144,492,787,266,557,11,978,221,551,666,773,454,889,363,706,997,617,813,921,677,726,214,121,865,110,675,94,672,824,122,791,289,253,902,400,490,109,170,123,490,298,993,197,139,445,22,586,982,678,77,847,390,614,118,30,858,42,902,24,980,220,398,867,728,402,926,391,88,912,106,2,528,874,981,865,949,618,634,934,228,500,4,413,680,474,537,771,769,732,732,231,681,167,265,487,685,508,867,687,352,564,53,241,956,624,786,596,935,530,85,17,942,736,353,11,467,433,692,954,473,259,258,949,92,993,203,609,943,109,779,635,95,697,311,658,853,899,928,91,407,851,451,505,613,649,152,436,392,285,81,181,859,201,728,515,907,270,254,989,324,6,333,749,660,94,311,568,616,275,546,18,700,672,938,28,739,60,182,217,644,947,817,948,893,832,959,49,789,296,48,247,146,847,91,773,465,664,916,56,72,282,292,716,180,352,808,623,753,563,727,798,731,583,753,858,888,158,982,859,683,768,308,595,484,457,37,883,561,636,898,501,693,514,659,707,605,572,800,928,675,83,28,755,270,63,852,223,498,9,420,400,586,576,743,514,569,816,31,927,709,938,837,508,731,738,978,827,549,844,313,218,700,498,947,849,87,478,397,853,58,383,760,597,666,839,844,773,7,356,342,607,526", +"758,909,162,749,922,394,657,145,442,462,795,656,698,64,939,519,85,324,309,242,671,216,518,734,422,798,951,451,715,705,550,174,535,928,127,639,834,839,201,735,389,706,948,382,364,395,753,475,343,304,832,491,114,928,564,110,560,327,378,338,563,812,250,96,366,199,320,872,179,27,208,720,729,396,68,169,436,921,539,977,797,862,88,29,815,392,848,678,796,696,81,148,993,537,78,735,623,442,545,656,596,634,180,950,450,857,958,802,915,266,925,920,87,277,611,840,386,360,378,265,626,807,263,238,675,367,316,382,741,340,522,59,979,108,479,509,380,756,51,575,910,604,803,535,206,56,745,469,605,296,66,845,138,127,328,598,783,110,428,263,309,700,945,152,360,135,620,777,922,313,638,933,379,467,93,929,417,540,967,416,498,894,619,537,716,929,324,451,934,385,92,806,305,647,782,493,90,589,843,158,453,237,727,300,205,830,288,322,55,203,524,166,756,596,726,420,808,103,932,856,580,419,321,560,613,210,998,354,299,851,665,663,109,511,53,478,738,591,177,637,206,645,260,664,451,993,192,393,770,534,484,351,887,142,981,679,208,807,677,845,248,738,346,29,311,13,782,420,344,719,982,455,50,694,282,835,345,906,443,484,75,452,654,487,57,882,860,319,612,41,586,348,609,248,947,18,179,641,502,726,887,422,965,808,618,986,683,683,16,611,356,602,726,833,684,507,812,205,283,493,647,917,583,203,533,78,649,980,457,852,744,96,853,374,136,676,741,449,120,629,595,726,878,946,151,468,979,566,161,710,751,215,477,249,80,73,684,355,656,348,235,88,249,134,18,395,600,41,168,204,311,747,978,985,107,747,559,135,497,332,631,836,470,129,683,551,960,0,915,359,895,973,553,126,20,82,966,929,129,745,922,585,841,437,823,430,215,272,501,433,789,222,403,471,706,314,251,67,589,852,955,461,630,24,138,282,278,802,832,873,196,932,235,904,115,528,924,807,517,244,181,484,965,123,193,420,252,128,254,87,329,29,268,434,137,214,965,77,686,357,74,414,692,143,246,252,838,191,401,238,623,884,600,75,612,798,660,413,631,208,147,667,366,935,255,596,92,482,309,648,22,11,344,880,381,281,891,501,385,208,699,119,904,873,976,825,640,276,847,144,782,247,666,535,444,41,410,503,140,929,626,73,282,528,64,520,2,240,750,496,363,860,412,564,749,974,479,538,618,495,289,285,692,792,190,900,892,728,693,177,355,810,245,282,294,952,794,222,68,531,353,843,150,104,972,958,695,529,346,681,272,936,7,964,242,72,865,443,194,610,936,407,182,223,309,735,442,610,605,165,608,399,949,81,974,331,530,106,716,387,526,685,609,926,371,262,80,671,836,343,214,231,502,642,328,97,380,667,210,311,476,764,579,279,617,224,365,198,291,313,322,65,352,675,193,928,664,804,239,711,755,183,247,659,696,919,663,949,908,131,715,775,514,448,7,578,876,59,760,751,864,894,908,40,305,417,884,244,498,998,404,574,401,619,195,231,750,814,124,914,566,717,322,624,956,855,588,5,80,953,689,471,312,86,923,597,48,525,281,484,257,613,358,112,494,595,11,158,813,889,325,615,37,937,711,850,323,233,163,816,285,106,498,138,819,527,923,113,270,233,573,393,419,461,811,308,802,25,497,804,835,333,819,263,105,2,362,626,336,72,732,783,493,423,440,881,1,843,423,692,916,575,770,110,265,117,572,776,278,91,37,140,899,878,371,638,472,187,688,49,546,972,272,101,429,115,394,613,743,499,276,11,933,146,978,196,204,549,437,460,557,862,517,669,145,641,524,818,932,949,91,16,601,223,957,76,535,812,721,808,624,159,260,634,934,136,826,79,19,683,510,450,845,154,22,680,218,759,521,707,435,92,539,264,892,337,35,892,142,382,188,786,26,910,881,549,199,645,368,822,974,652,251,395,783,139,226,476,199,266,490,740,37,456,641,963,28,36,121,904,731,344,931,636,475,935,15,327,660,894,554,386,384,695,702,821,302,17,529,732,362,38,102,588,322,964,886,332,725,200,131,656,268,943,182,657,372,914,132,997,171,740,968,658,363,389,434,104,746,604,30,290,744,305,658,198,976,446,113,403,503,83,407,131,261,354,662,428,277,782,165,333,782,328,83,255,477,408,75,654,575,624,83,228,550,63,904,177,975,101,195,391,10,746,6,556,508,743,146,856,356,874,827,332,677,369,674,189,598,575,581,794,202,834,589,948,749,893,86,560", +"194,196,473,460,650,389,340,923,939,179,63,592,61,537,292,330,328,370,421,716,352,447,548,579,864,194,54,937,639,855,234,67,864,462,642,914,503,580,432,51,663,200,643,495,637,86,268,41,645,623,441,360,153,237,511,845,13,833,882,947,574,990,906,552,462,808,318,453,799,903,745,460,258,246,600,871,7,159,855,459,61,754,258,540,985,793,110,531,74,191,463,164,755,416,361,759,287,5,448,917,430,619,204,856,183,57,902,813,795,320,59,184,941,355,819,43,439,37,614,123,405,894,414,609,491,324,510,853,297,865,913,467,104,976,682,341,240,149,608,27,243,795,558,287,47,598,968,494,697,807,719,473,109,915,585,523,458,883,583,256,531,590,658,878,469,135,693,498,276,836,930,730,774,994,42,636,454,576,922,97,3,845,295,681,640,882,799,859,656,258,747,560,468,913,898,207,117,768,317,273,558,347,346,612,392,126,560,274,288,848,799,345,775,61,377,761,526,123,674,325,757,80,922,505,894,30,373,284,730,428,438,157,344,779,937,78,19,228,241,818,169,390,567,535,238,94,666,459,819,263,243,154,55,921,798,239,301,546,911,952,271,482,595,319,124,492,876,58,314,724,723,934,833,345,2,41,344,124,599,487,500,17,520,862,316,294,719,1,838,47,399,712,47,80,583,815,208,227,361,529,427,506,261,466,2,401,445,783,616,906,197,477,838,948,186,835,582,554,945,549,562,333,686,92,837,823,365,289,779,620,115,981,886,599,280,875,796,829,404,739,682,952,215,580,504,858,208,346,737,118,101,884,702,508,761,404,673,446,910,802,209,228,242,775,806,625,457,829,520,502,865,805,688,468,913,687,830,10,564,462,750,584,17,339,184,584,852,915,0,965,819,308,25,120,838,40,182,317,258,686,767,103,897,400,229,291,899,630,40,133,590,546,459,405,735,574,645,241,507,873,50,449,390,54,307,701,763,251,931,447,125,512,403,646,288,886,902,208,370,944,60,750,42,723,370,835,635,123,144,983,659,743,132,179,636,659,789,148,833,557,968,77,124,441,766,784,276,74,320,655,436,113,785,2,169,490,641,160,383,867,924,618,333,804,933,165,346,274,741,953,177,240,949,167,62,878,377,974,89,818,677,256,860,354,772,155,740,849,244,565,389,473,841,870,112,570,129,537,830,862,669,397,335,374,923,155,350,853,432,249,482,126,678,597,816,758,687,851,815,397,760,943,8,110,575,752,338,902,547,346,808,853,428,343,74,460,275,466,53,333,377,25,710,14,769,538,816,166,503,145,90,276,735,517,999,137,333,743,108,684,568,779,104,425,219,561,462,719,483,784,274,646,950,163,22,490,502,35,782,787,844,949,390,64,894,460,827,771,298,11,741,380,262,624,171,905,669,341,411,797,208,891,583,109,297,483,11,880,705,728,836,336,87,832,248,229,827,490,527,539,838,203,20,603,739,864,863,135,551,77,608,402,538,249,954,249,235,57,68,610,31,847,791,615,448,847,874,415,117,321,521,596,782,527,586,197,146,138,531,821,689,636,856,389,560,757,855,481,227,386,174,334,279,283,123,737,668,46,506,896,460,281,442,627,494,680,325,597,637,46,273,673,551,200,307,57,401,763,170,609,506,881,242,150,690,399,380,418,802,796,542,235,420,171,539,4,442,163,105,919,79,252,855,199,289,847,231,986,797,713,437,755,363,442,933,223,62,102,769,909,379,688,718,838,683,818,574,537,40,446,959,14,89,229,856,342,564,582,235,112,100,787,750,17,251,28,412,75,794,119,559,868,844,131,720,343,598,424,902,567,352,867,175,893,973,560,736,902,317,786,176,671,812,569,152,12,331,223,103,914,65,778,727,20,473,97,628,403,193,192,796,701,378,29,769,46,518,548,53,402,374,810,961,660,664,689,189,106,152,231,542,783,222,857,794,728,420,570,295,27,193,800,646,112,631,584,523,442,162,491,267,863,53,233,176,747,990,8,412,388,80,984,41,699,685,935,620,93,903,381,69,989,219,405,600,228,812,443,650,503,984,368,845,144,822,488,567,2,355,405,144,157,81,866,689,66,166,99,385,107,498,224,994,232,296,924,480,125,326,172,206,935,765,412,354,951,626,563,342,561,328,399,704,13,770,390,172,899,406,821,590,663,481,449,319,420,335,717,385,398,254,224,871,375,581,926,527,530,854,646,942,151,465,942,413,297,980,129,75,307,677,711,331,470,856,165,633,879,571,7,784,4,440,688,220,379,943,148,351,286", +"461,614,446,8,824,609,105,466,476,299,663,432,758,840,526,413,705,208,846,532,651,777,906,908,699,447,204,556,965,624,961,232,612,345,182,785,912,286,790,489,46,69,730,300,890,101,456,974,923,340,435,651,966,596,413,960,994,951,517,679,611,336,632,701,212,329,886,760,934,332,374,626,673,275,395,782,53,741,734,390,380,634,923,694,589,800,766,173,869,737,104,521,340,12,78,838,386,619,46,885,590,44,526,730,951,517,808,826,436,90,337,835,509,935,304,299,566,307,333,815,135,945,556,577,277,686,304,802,778,809,118,260,685,725,988,302,345,331,656,480,684,993,771,437,987,542,287,342,968,513,611,78,553,584,437,980,711,517,135,222,992,560,499,580,509,250,62,958,833,937,791,627,370,509,929,319,273,131,852,575,655,267,533,790,834,275,407,155,25,182,21,317,646,956,75,648,615,71,778,732,643,434,622,634,806,516,960,968,382,791,101,588,135,119,885,658,244,244,934,443,212,933,804,382,80,279,882,939,380,758,406,749,631,862,406,302,841,652,709,685,330,654,945,811,375,957,679,11,567,203,274,204,485,635,556,638,62,57,871,412,333,542,181,692,190,436,340,584,68,557,27,133,774,587,700,69,732,645,906,119,246,265,894,889,845,401,644,216,534,586,367,781,624,82,16,402,272,464,697,930,748,448,971,729,503,219,755,18,263,161,477,371,800,839,578,698,380,141,720,24,122,7,224,702,755,607,798,339,904,389,415,173,325,380,641,317,95,827,607,673,365,142,305,965,84,163,487,493,270,462,326,791,715,356,944,472,529,331,134,645,768,747,679,489,155,164,801,311,103,697,799,821,176,88,951,775,665,75,945,367,630,84,453,659,435,320,701,359,965,0,678,182,459,606,97,970,987,779,657,202,554,331,912,664,488,604,871,878,187,732,27,719,99,221,481,137,790,497,534,448,716,871,152,296,651,685,884,764,772,893,486,927,665,956,149,285,394,166,70,734,791,255,836,737,787,803,667,140,763,818,698,72,354,322,370,471,469,845,564,506,536,118,464,896,251,386,644,48,289,211,528,273,999,344,500,953,229,268,298,832,521,561,685,595,496,80,869,875,707,202,887,309,997,29,815,231,588,765,87,703,708,110,254,491,68,385,262,549,82,854,431,91,331,283,809,951,917,611,518,156,614,458,883,31,195,312,5,579,38,4,967,607,27,320,753,25,869,332,591,896,749,16,237,305,808,691,38,316,210,912,522,974,121,632,66,964,728,575,699,720,952,800,607,105,206,470,380,26,781,309,315,695,55,632,895,190,353,445,416,541,45,51,221,71,873,839,804,752,216,740,572,678,414,878,299,64,145,204,675,39,392,188,268,750,107,89,77,146,149,710,174,317,785,727,525,331,282,788,693,761,706,848,949,208,971,705,150,47,229,986,124,651,441,542,278,845,902,600,531,1000,284,751,381,111,596,576,49,197,807,143,9,209,226,845,151,241,490,927,474,483,13,777,192,253,727,29,949,159,964,577,583,130,153,988,925,322,471,152,920,333,782,607,364,321,28,372,511,76,928,651,108,687,146,90,230,712,569,599,527,615,411,711,190,510,608,54,886,393,158,617,48,822,18,47,34,713,279,357,751,151,980,164,975,470,414,669,591,820,412,992,510,891,984,466,248,711,970,123,80,55,483,498,425,263,229,829,136,412,264,418,566,245,971,663,836,772,707,619,802,193,703,97,218,997,178,265,755,365,696,712,220,757,305,698,94,819,611,278,321,99,262,380,194,722,176,358,58,709,414,60,900,63,340,294,270,475,110,707,914,520,971,236,898,647,379,209,37,279,733,846,98,896,8,765,611,655,63,36,874,822,588,188,586,883,776,818,263,531,414,491,237,89,364,11,914,574,143,661,618,384,357,311,476,821,720,676,594,594,948,885,950,45,254,223,264,52,503,234,376,858,353,861,476,525,378,75,301,64,140,504,476,713,159,671,463,373,580,553,489,311,726,4,496,341,986,571,33,118,983,890,426,792,418,687,724,478,722,17,391,471,990,247,899,627,453,409,62,636,974,152,477,745,327,297,536,517,143,155,662,144,426,589,215,630,48,441,196,515,546,35,425,749,499,180,821,333,328,889,734,964,613,153,264,173,827,674,782,341,935,152,428,813,30,821,170,813,638,958,21,755,387,479,118,445,607,243,925,56,644,430,929,448,551,102,476,423,240,351,371,459,802,200,968,509,804,254,889,722,951,408,285,211,886,444,803,567,940,399,145,325", +"411,118,210,857,706,382,332,908,470,471,21,82,209,224,890,286,581,149,380,605,148,709,822,461,946,194,476,761,310,34,331,249,358,929,721,659,35,516,629,170,289,968,535,870,607,871,126,886,469,282,236,183,788,59,689,858,995,640,961,348,951,822,606,710,29,961,723,354,886,594,102,648,923,109,187,687,353,627,650,305,798,294,475,273,390,834,261,76,16,997,168,980,989,815,504,740,632,214,471,974,439,87,941,679,980,549,578,972,47,15,416,504,525,894,517,301,743,665,390,475,211,76,860,521,515,145,549,259,555,530,966,328,615,775,63,122,516,613,862,54,351,770,765,789,798,838,723,206,999,973,217,559,594,589,961,894,486,482,681,759,466,944,262,833,74,828,171,791,638,621,109,780,107,566,443,246,321,436,407,810,44,592,757,354,952,38,515,654,755,817,405,355,898,178,385,735,491,153,591,103,781,209,586,842,973,951,788,325,293,142,448,497,273,906,856,772,247,420,353,458,531,610,225,177,104,259,52,629,975,478,759,838,700,52,595,251,375,156,767,312,781,463,296,727,573,579,710,634,792,7,948,476,962,936,948,942,54,879,932,102,305,92,633,282,520,90,842,214,495,88,540,983,16,482,925,386,270,89,60,46,457,151,731,637,606,283,34,172,935,153,36,408,655,242,290,945,735,484,731,102,735,989,542,160,262,510,123,926,788,471,166,180,19,888,433,596,59,462,571,840,658,798,792,653,957,553,570,26,776,799,389,130,569,32,573,802,226,739,866,140,621,417,28,600,812,707,266,341,540,566,860,574,167,264,938,280,623,456,514,453,813,266,870,16,899,332,443,79,637,295,278,803,253,704,911,366,817,416,318,210,177,272,330,329,357,98,593,895,819,678,0,910,411,381,776,248,302,108,39,398,61,87,117,25,786,773,225,169,366,562,237,873,26,814,782,462,309,542,207,51,967,432,646,571,268,96,818,79,80,26,54,888,276,943,841,7,383,16,771,55,881,869,257,422,495,421,537,491,955,239,606,750,10,385,512,382,262,293,266,885,593,434,242,707,968,595,950,397,592,875,84,578,444,760,865,166,458,796,25,946,589,489,12,260,560,883,533,157,288,540,390,558,582,181,306,925,390,857,504,684,613,398,591,536,331,449,292,76,112,74,262,8,74,726,931,186,941,67,450,720,226,370,851,736,389,289,240,268,135,526,965,745,801,531,710,65,921,245,200,261,995,517,691,1000,684,439,222,70,247,388,205,242,231,787,830,97,444,561,814,810,689,224,851,728,772,310,602,73,806,444,980,518,402,793,861,921,115,471,942,178,3,805,322,735,451,357,771,260,93,271,971,470,332,836,724,617,529,103,165,53,856,26,347,81,111,265,482,197,707,54,878,417,751,727,588,787,309,339,845,606,775,340,126,789,833,708,481,561,38,640,372,477,400,627,385,186,890,623,563,490,671,509,504,595,54,15,541,329,567,617,942,609,475,163,965,486,895,405,999,78,411,467,971,207,914,279,767,697,784,942,350,435,635,752,978,605,755,162,148,938,831,853,222,758,30,310,715,999,823,473,370,18,72,175,429,329,298,377,54,609,940,330,389,818,586,153,20,369,421,60,454,353,589,59,208,600,967,41,402,898,277,823,417,257,695,542,622,9,808,496,995,853,818,6,891,582,69,794,672,452,264,825,140,636,391,523,358,498,853,299,814,278,923,401,884,196,485,17,489,399,996,772,943,683,581,367,760,370,291,856,142,775,574,41,727,302,5,498,611,566,900,794,755,149,115,920,277,395,788,500,217,719,705,265,195,97,721,420,501,905,28,131,239,347,710,276,521,837,296,302,715,185,448,939,548,910,860,478,190,717,957,371,227,413,512,534,637,326,358,721,598,6,581,512,945,967,689,18,609,309,16,657,607,83,95,295,273,812,621,420,478,97,40,619,485,743,926,588,70,63,979,7,197,986,51,359,132,510,220,269,16,322,541,176,398,368,513,355,101,647,894,339,680,692,307,902,987,658,262,288,393,649,696,51,562,708,169,376,739,54,397,586,310,746,323,400,413,901,785,554,240,529,320,813,657,902,554,897,181,898,457,407,915,243,674,289,293,158,223,297,799,906,81,451,181,693,610,291,670,306,498,972,845,706,53,599,929,75,688,603,88,20,788,515,454,309,704,985,40,318,596,435,780,303,464,597,198,909,38,454,535,189,367,192,249,154,566,431,406,419,489,960,561,980,82,37,330,86,90,899,122,836,542,112,950,274,864,657,471,612", +"177,198,8,632,553,805,240,757,249,503,433,387,726,791,449,932,906,966,39,532,885,757,330,736,743,323,743,381,344,877,56,203,178,670,834,465,650,329,823,340,583,49,790,554,502,366,557,424,63,725,987,270,436,921,466,254,784,80,94,251,370,626,844,97,986,187,291,785,980,50,734,782,233,974,773,354,110,377,939,533,594,363,660,816,760,686,454,602,436,758,549,892,541,193,636,877,222,402,51,263,718,421,522,184,514,187,641,463,24,53,926,34,384,16,744,515,261,314,117,613,453,362,347,938,94,994,965,433,822,480,138,937,458,893,828,563,867,913,481,547,748,554,27,667,326,149,74,841,732,50,245,839,494,993,714,607,426,405,142,684,424,569,40,381,322,831,331,524,99,337,447,375,786,979,124,963,864,515,111,299,829,471,218,793,931,259,100,600,435,980,263,822,459,621,650,806,748,185,282,754,991,55,803,36,99,891,498,584,550,848,859,359,922,378,845,251,875,440,719,94,435,259,197,109,908,982,768,911,340,388,94,219,688,508,89,192,881,909,998,191,62,436,211,375,681,989,954,998,264,49,278,76,976,327,745,510,225,139,32,947,992,38,951,656,897,965,879,922,509,941,902,362,5,601,925,231,853,535,380,376,714,593,104,10,150,17,700,637,405,485,974,466,682,691,316,283,987,503,514,233,287,841,873,118,778,463,817,282,739,973,310,795,103,633,419,807,294,735,7,608,197,337,752,683,784,642,868,680,202,956,67,299,876,506,968,729,783,314,447,394,680,110,871,31,687,567,581,233,238,417,730,371,545,416,4,741,273,458,923,260,156,366,150,61,827,853,908,676,66,453,147,194,823,47,916,592,491,352,877,426,22,456,924,857,267,120,538,973,308,182,910,0,226,340,491,414,747,655,357,89,60,646,316,340,963,288,897,732,743,397,807,865,830,649,893,916,480,852,326,636,104,893,885,315,57,477,514,579,817,826,908,59,441,923,445,688,251,848,962,820,443,518,320,445,166,756,966,737,991,102,151,292,624,304,740,90,614,834,135,288,519,907,55,206,854,814,14,986,311,822,764,962,169,499,217,323,244,961,972,461,355,772,182,716,846,470,548,285,132,598,474,558,202,228,354,645,301,29,76,707,744,850,676,153,963,436,99,151,846,355,579,556,838,421,562,400,797,527,453,991,854,844,299,228,628,447,482,565,709,455,118,698,814,402,808,178,126,355,155,991,721,348,63,796,424,182,424,509,745,190,425,335,195,325,337,535,84,453,654,327,939,808,566,478,864,947,414,667,111,890,318,793,554,839,273,875,919,41,13,91,929,616,247,444,487,74,808,853,107,968,579,588,784,658,509,151,656,384,669,933,285,603,457,670,865,549,381,650,367,307,404,681,499,273,227,855,265,372,262,532,777,131,697,43,662,341,368,683,101,562,148,22,487,323,411,498,269,291,940,633,436,248,743,315,242,942,550,194,166,97,163,57,867,316,913,654,184,127,552,543,469,839,521,110,908,251,106,325,617,304,943,573,441,975,651,551,491,315,802,305,794,403,21,196,683,871,575,603,933,349,387,36,797,748,648,51,941,536,845,326,533,627,345,55,426,585,712,760,198,401,513,543,418,10,115,369,281,695,746,856,338,704,258,269,563,358,522,547,650,796,485,168,56,840,821,615,485,851,401,954,156,86,453,206,760,84,976,911,971,64,894,86,401,469,559,584,248,939,896,21,351,917,701,842,26,897,700,675,252,195,789,622,614,120,948,573,401,185,95,122,450,314,515,439,367,836,11,498,554,648,183,316,426,952,296,792,644,619,372,249,406,956,312,552,408,58,960,656,94,759,157,822,415,657,272,175,974,718,670,612,541,715,485,457,658,33,468,826,36,43,47,727,752,81,158,285,17,276,525,866,859,275,97,425,155,173,165,753,156,544,988,52,860,166,103,667,584,793,702,826,108,126,488,541,352,589,625,123,304,443,714,258,860,849,393,462,927,472,272,463,124,46,735,207,789,25,868,753,893,107,483,476,81,665,799,459,666,530,548,427,627,123,447,356,372,503,193,914,719,153,439,282,439,791,318,820,590,326,59,218,90,4,120,318,458,953,236,709,521,115,417,95,170,488,370,48,644,886,353,363,58,517,920,654,973,300,740,896,688,418,756,79,236,320,580,811,586,104,923,918,7,942,972,81,109,314,75,399,604,724,662,819,212,184,909,200,430,338,499,729,414,699,965,90,570,691,618,336,967,275,80,919,480,149,653,719,682,235,424,826", +"912,700,431,316,75,632,945,846,130,301,777,69,580,530,596,351,680,437,82,825,996,665,350,307,841,920,687,206,358,251,594,33,613,627,31,519,764,688,67,623,851,559,308,734,3,23,891,647,701,375,548,103,786,993,681,798,751,931,388,642,769,69,337,461,741,403,986,483,255,221,653,954,356,268,891,800,93,174,360,887,374,153,440,609,371,281,532,372,792,848,498,319,430,921,599,140,299,235,466,699,449,15,931,810,240,991,460,644,525,399,821,15,822,911,847,516,177,708,975,32,659,600,517,921,214,336,267,368,246,743,573,201,895,339,428,371,854,281,549,18,699,126,481,807,981,32,168,6,442,138,455,71,312,527,354,692,531,367,29,530,783,182,17,549,355,736,749,13,459,961,227,233,17,159,529,507,781,211,35,135,461,795,585,718,498,137,121,321,35,36,760,133,465,508,728,262,947,251,926,43,230,364,95,94,231,942,995,166,570,147,927,42,966,527,323,372,614,262,450,893,504,448,202,956,349,814,292,313,915,468,72,752,149,908,102,500,208,289,79,185,798,659,441,314,145,831,631,999,865,605,26,569,514,94,79,635,450,897,600,363,70,556,77,626,88,523,12,970,582,494,563,988,595,159,750,178,917,103,869,658,52,8,346,807,448,86,246,169,873,207,685,713,932,312,944,796,880,131,432,35,107,104,48,812,370,192,983,420,353,361,918,206,729,669,200,131,375,567,968,120,823,481,892,828,81,601,763,455,866,524,935,891,887,758,473,654,721,917,709,721,736,590,75,96,505,806,380,631,8,535,241,888,93,164,186,728,358,354,947,977,216,661,886,562,892,164,770,667,103,6,528,864,69,589,269,684,308,680,832,193,740,738,552,417,60,322,927,553,25,459,411,226,0,294,879,726,251,952,687,630,536,750,226,364,692,299,33,227,730,867,733,977,958,524,662,25,338,47,585,757,531,67,611,578,12,87,967,524,734,428,949,32,794,195,355,508,14,579,215,657,577,863,557,865,197,927,18,921,459,321,285,542,841,654,291,520,937,875,939,257,72,977,566,466,968,632,349,342,508,647,45,210,388,217,187,109,862,531,277,582,270,826,233,138,556,281,999,802,863,491,866,420,522,188,939,468,193,760,358,667,496,847,906,849,575,163,724,625,912,831,226,301,797,172,87,718,875,59,306,315,685,329,936,844,694,946,461,730,142,649,268,766,441,447,255,467,773,713,215,759,69,415,616,57,614,182,358,382,133,605,253,384,987,319,514,161,920,3,418,359,461,996,667,392,924,266,863,455,669,415,763,113,30,491,75,872,772,425,407,188,391,160,642,92,960,960,756,398,830,163,197,687,906,423,790,560,329,985,499,276,747,4,390,222,533,629,37,269,279,866,912,994,49,625,273,444,637,127,443,215,273,773,399,455,741,748,549,850,387,995,840,389,678,767,753,376,513,85,129,280,435,64,172,492,589,25,966,332,959,185,785,871,988,638,990,629,520,747,405,628,590,938,639,984,820,52,477,203,493,925,20,126,434,777,431,444,63,585,242,696,379,742,616,161,677,1,587,732,302,994,216,921,604,61,689,37,431,347,557,209,662,53,330,295,305,35,803,865,770,415,333,586,169,455,30,973,110,426,804,654,400,186,546,918,59,964,13,860,509,247,134,898,961,363,769,646,918,877,493,750,200,254,236,985,16,55,865,175,2,560,863,178,580,482,823,991,83,870,313,515,937,836,978,114,414,771,547,608,245,688,504,471,64,88,58,617,135,802,359,461,355,750,972,99,16,271,184,42,611,887,673,806,981,172,340,485,610,768,792,308,187,953,822,70,99,333,345,576,547,342,526,679,776,770,209,208,11,947,724,317,566,751,437,702,576,18,985,479,111,21,423,183,798,356,935,244,574,587,221,947,856,639,440,551,329,945,984,30,130,710,609,905,247,686,750,450,697,53,767,667,796,658,246,603,519,896,946,388,172,565,798,824,819,31,199,441,106,895,970,136,70,472,153,517,936,523,803,552,89,792,776,771,62,740,58,856,966,642,157,747,329,387,606,445,371,39,64,36,202,739,806,463,942,146,380,991,288,916,965,911,864,189,687,386,477,158,187,163,960,47,162,226,721,730,906,195,809,270,270,436,804,278,411,605,42,827,366,322,9,157,594,939,923,585,678,39,294,51,274,527,224,373,877,160,81,789,409,604,896,868,245,625,992,80,64,797,384,493,311,391,762,640,35,15,942,31,116,188,525,717,310,359,253,636,782,897,756,774,245,280", +"818,94,161,271,185,55,437,365,772,433,702,699,698,709,241,476,526,910,287,732,794,788,879,792,422,932,55,338,732,350,260,936,651,787,300,393,380,352,594,94,181,731,632,919,767,359,444,864,83,71,723,869,236,880,426,760,356,628,844,100,877,654,277,8,976,725,480,245,299,499,848,133,600,231,616,190,668,305,243,908,950,123,734,618,142,396,655,978,584,441,847,492,465,736,417,366,135,798,230,662,771,916,351,399,42,394,939,986,222,348,153,613,859,693,967,161,633,909,808,783,853,787,769,982,119,653,684,478,9,490,246,355,623,734,267,24,190,670,510,981,451,626,149,909,445,815,468,269,693,629,171,637,764,128,360,325,955,270,803,434,398,372,385,130,846,898,118,566,274,75,580,760,258,34,443,65,596,44,229,667,208,438,328,58,200,832,896,947,59,305,653,721,487,926,658,601,182,398,373,79,657,620,984,210,467,352,151,396,31,411,304,916,410,375,854,736,873,222,682,275,12,322,390,794,191,189,64,376,71,27,681,985,592,711,595,663,557,863,249,968,340,359,782,446,839,36,143,191,847,414,303,639,541,87,146,956,309,443,546,827,402,115,756,64,400,312,822,936,925,708,364,17,720,169,166,812,927,614,187,321,132,52,714,485,68,288,965,14,935,780,997,805,410,549,345,863,21,52,388,202,910,422,742,624,526,134,421,434,964,252,465,78,538,886,697,276,413,750,104,720,726,582,857,950,779,494,61,56,979,559,131,666,542,533,323,707,423,773,292,268,496,380,826,188,689,650,842,789,477,583,966,27,910,684,851,460,7,144,361,441,999,5,328,650,142,668,322,471,125,432,804,670,185,156,60,968,952,757,140,201,669,40,950,996,471,575,491,126,120,606,381,340,294,0,31,585,857,493,636,613,310,848,191,514,457,746,815,797,627,662,204,835,142,140,685,211,15,595,286,859,957,673,226,951,181,132,394,601,647,466,51,241,789,876,352,672,708,554,104,930,154,294,752,129,30,181,970,318,468,560,65,357,768,81,609,522,60,396,985,129,316,694,893,852,504,479,131,640,190,455,924,524,521,612,237,409,322,739,730,79,896,786,367,134,519,207,892,674,749,347,224,557,649,889,713,500,953,44,200,733,350,500,247,927,108,13,807,86,618,281,332,418,829,658,559,121,119,302,723,87,71,52,814,819,550,46,439,125,796,868,996,932,53,795,189,939,244,939,737,387,920,480,607,559,656,545,436,760,11,370,66,693,338,236,339,887,462,808,292,707,623,353,473,663,858,47,255,15,551,72,421,625,9,303,672,5,812,212,194,97,248,914,801,776,788,849,701,129,468,854,384,584,776,626,264,695,503,584,966,101,981,944,593,305,871,992,54,744,647,580,236,237,211,117,301,81,632,395,872,603,419,622,846,562,303,335,56,760,331,677,152,448,285,424,114,824,990,323,489,828,151,42,532,164,506,544,648,501,906,695,912,604,519,425,433,74,413,576,259,192,381,628,403,279,341,515,460,461,601,968,91,183,842,61,810,882,235,747,995,118,838,184,482,785,5,679,734,254,890,71,907,175,398,771,144,246,150,425,185,24,987,963,497,653,336,738,795,455,268,401,698,231,147,732,682,682,954,664,897,315,421,736,9,809,33,152,900,145,222,686,597,444,94,659,861,475,316,980,910,878,258,603,572,785,182,380,237,68,606,720,715,673,25,779,272,625,270,484,531,26,997,80,120,983,566,279,660,455,902,977,762,103,717,767,312,707,33,539,331,33,140,152,949,14,202,192,937,280,399,788,225,130,585,334,603,803,368,251,18,559,788,48,185,882,706,23,711,590,277,25,174,306,956,606,430,112,110,811,478,678,131,612,741,447,482,27,718,584,441,347,721,100,172,638,455,704,516,240,619,223,188,138,158,562,683,129,891,912,505,165,239,718,861,902,128,446,9,825,37,117,419,726,925,448,420,736,240,160,70,407,15,890,302,290,766,270,710,767,4,620,314,172,824,633,462,424,334,259,836,703,23,403,497,865,12,850,563,877,888,10,176,123,791,772,684,759,658,424,225,792,67,598,930,694,329,487,742,429,531,209,15,346,342,204,23,836,9,215,830,922,991,756,902,666,38,620,473,760,733,723,289,175,743,875,266,276,54,105,758,105,841,540,875,150,767,725,720,680,655,29,883,332,657,774,655,249,417,326,138,909,278,128,689,742,372,697,546,487,447,624,316,496,590,274,730,530,264,663,446,211,645,315,278,648,781,566,710,685,973,881", +"92,100,747,872,901,538,260,626,156,701,414,697,668,18,922,455,835,113,249,399,771,420,962,509,109,988,507,939,190,261,658,489,646,918,590,763,44,606,109,652,804,110,114,98,646,757,401,203,197,441,535,485,802,472,474,164,22,901,68,658,750,63,399,402,209,300,126,591,722,506,687,790,828,457,719,392,251,807,739,962,545,666,20,830,308,233,634,444,486,942,406,591,890,273,852,88,221,469,741,407,482,746,100,49,10,76,416,703,573,113,323,73,821,547,743,837,431,341,8,316,654,842,375,973,648,412,93,287,970,383,747,725,468,799,918,880,75,540,129,346,467,472,33,461,482,917,379,257,515,973,898,500,226,712,311,830,255,523,43,478,626,24,163,145,110,896,167,953,148,152,134,3,35,684,273,606,340,539,258,507,426,60,969,457,258,14,85,688,434,927,203,71,19,838,920,780,790,992,374,830,240,342,286,409,2,880,981,169,950,896,642,350,286,159,840,771,442,609,844,142,935,643,465,354,183,349,15,824,395,664,393,9,837,377,508,830,817,678,869,56,235,472,649,741,666,460,132,973,356,67,365,343,721,585,88,529,643,883,215,464,674,897,601,33,975,994,81,912,353,779,489,366,729,177,975,443,121,594,452,125,532,732,68,545,136,87,688,658,37,777,304,364,922,207,793,362,373,884,443,396,959,416,929,296,707,96,332,943,939,329,162,664,523,858,892,683,872,99,725,92,828,617,647,547,465,253,947,456,199,725,585,58,701,273,963,969,186,90,940,396,685,737,409,5,225,367,115,224,662,811,558,402,933,506,231,53,60,155,602,228,642,986,421,209,778,932,580,975,218,47,157,376,994,285,540,891,839,370,785,630,288,181,349,830,612,858,27,20,838,97,776,491,879,31,0,888,33,730,656,521,745,155,894,941,174,842,982,631,576,617,837,575,926,273,175,911,525,437,838,572,415,967,652,830,13,700,99,625,302,522,160,858,631,787,564,896,763,628,953,813,406,256,591,104,282,109,612,591,671,593,497,917,876,70,773,76,714,898,309,677,514,608,821,694,555,526,540,226,965,300,53,554,721,652,760,805,657,826,751,382,691,996,304,389,304,329,87,109,716,495,510,420,32,883,799,913,157,721,717,818,241,72,862,598,846,707,498,350,223,393,410,183,921,178,295,935,133,747,964,807,982,423,855,72,115,538,371,367,274,820,415,541,148,584,66,911,241,784,126,738,945,642,285,574,730,352,92,311,379,534,142,472,880,23,372,566,690,552,322,525,293,706,246,884,942,464,827,782,227,952,193,449,476,370,973,865,17,375,122,870,472,499,776,616,742,901,288,338,744,177,486,782,41,367,994,2,657,16,360,438,718,828,129,221,623,852,478,812,975,252,983,515,57,135,965,417,917,152,592,469,519,44,580,441,35,486,554,346,129,392,416,848,28,988,336,805,936,210,480,230,241,448,199,750,867,411,369,647,474,951,647,620,913,596,13,721,675,282,837,463,748,392,936,501,442,271,647,186,129,199,289,802,159,553,540,213,698,594,13,45,971,452,539,54,412,353,487,246,625,27,606,882,296,107,969,385,923,33,384,621,312,910,257,797,621,549,953,269,578,158,36,666,519,51,267,911,451,134,339,640,375,390,301,977,626,753,803,462,104,873,419,94,392,797,421,843,315,997,533,303,341,835,101,720,564,334,311,435,865,629,443,498,273,299,919,286,633,589,791,229,55,553,283,52,977,643,461,229,829,647,499,718,261,751,513,370,933,484,443,309,7,339,683,735,219,609,285,40,465,658,954,68,194,258,214,382,870,762,97,953,994,373,345,21,907,848,17,612,18,689,80,232,158,735,220,763,634,687,432,680,333,662,678,764,234,595,383,670,917,550,195,927,225,920,770,852,140,253,523,697,918,678,94,180,9,288,432,43,508,952,319,105,152,177,730,814,818,179,219,839,234,640,661,987,619,344,522,6,944,310,751,344,606,407,805,189,289,881,398,224,585,653,874,348,761,809,114,840,630,753,581,76,870,167,205,924,340,553,578,279,624,733,997,668,631,29,878,510,968,487,529,110,654,951,220,706,178,231,413,246,183,702,270,100,205,327,439,764,490,505,72,332,347,728,898,741,169,917,418,313,443,936,303,248,237,56,456,786,605,130,494,10,521,656,670,357,374,634,380,274,957,107,768,585,968,361,257,3,1,250,607,132,592,131,995,594,420,319,197,950,653,879,809,289,844,573,989,831,953,953,16,526,158,651,827,103,122,899,853,80", +"512,29,529,797,342,92,398,919,414,553,112,143,37,274,314,481,782,345,337,897,992,820,778,567,454,26,567,912,185,816,232,596,435,246,974,641,714,10,316,683,999,526,897,669,161,174,659,437,379,631,713,622,749,860,271,613,192,519,179,725,87,513,488,866,115,329,492,489,716,899,638,700,530,761,240,308,422,679,550,987,212,464,832,81,531,104,667,112,278,579,888,65,561,173,960,965,889,69,3,292,724,383,404,76,958,444,759,602,619,691,904,73,211,373,118,364,250,504,231,950,431,847,500,674,291,376,44,933,446,600,504,724,531,719,172,283,662,752,177,402,726,825,115,294,277,755,694,291,950,793,318,173,31,570,811,959,858,845,501,3,248,802,676,159,163,534,46,483,983,797,807,263,87,493,54,198,733,410,876,807,380,248,772,312,146,651,683,994,617,588,558,608,104,937,287,904,741,616,458,90,732,925,307,847,769,558,212,411,28,86,256,302,351,499,173,516,750,44,354,732,771,73,73,465,829,191,762,414,489,45,771,567,796,309,183,580,394,588,544,623,994,284,586,245,648,615,611,862,811,26,564,604,748,296,319,903,262,390,569,328,31,741,750,243,470,914,575,287,473,155,543,2,603,713,198,155,117,872,367,655,287,681,240,537,108,835,34,629,31,417,571,227,361,896,646,577,140,976,102,444,819,601,671,882,577,130,99,45,555,163,153,377,574,449,967,278,808,110,725,641,475,497,535,771,494,766,811,47,115,976,111,177,321,623,843,871,338,682,80,107,329,629,172,726,223,383,974,100,669,44,799,338,469,357,797,938,167,174,570,713,650,627,906,976,798,169,502,244,255,471,144,445,337,262,364,446,244,682,431,770,277,765,119,713,324,700,396,82,40,970,248,414,726,585,888,0,797,337,846,94,502,438,860,319,892,280,4,336,62,45,723,163,570,869,114,101,312,55,391,109,425,795,419,960,221,155,952,179,743,904,57,78,521,854,716,210,21,36,605,800,914,597,770,405,737,383,982,538,694,220,84,507,301,101,921,515,726,183,570,40,370,437,232,198,916,935,92,927,2,821,800,188,935,406,742,344,511,677,380,326,94,801,864,893,953,707,863,106,429,499,663,137,368,97,240,671,801,197,518,198,947,740,607,398,648,7,254,83,88,44,921,698,508,519,932,512,637,626,137,328,120,527,439,363,288,859,457,95,147,907,594,90,779,643,562,224,997,837,746,948,523,27,526,661,510,227,66,351,365,304,276,823,829,976,925,485,792,926,214,347,851,210,365,53,249,273,190,279,49,660,731,875,711,907,480,203,349,35,808,868,233,354,408,867,413,344,853,539,65,778,17,998,134,490,984,209,356,291,101,664,330,271,381,298,702,54,537,211,420,271,260,222,927,164,735,534,935,244,681,359,660,252,577,415,364,54,282,196,613,131,667,727,547,509,30,831,525,652,648,546,993,378,266,560,156,558,368,587,966,519,732,556,83,183,292,599,932,753,755,227,481,812,176,927,7,680,723,759,888,489,705,518,673,491,558,635,349,749,163,897,797,931,740,69,842,99,746,411,213,928,763,264,950,85,452,205,287,573,599,126,427,101,531,101,835,39,826,708,584,268,371,552,803,11,284,366,125,418,260,987,685,974,74,457,79,80,46,593,335,164,101,131,708,457,285,227,132,294,205,241,57,333,925,177,405,14,202,695,658,316,196,528,359,701,897,664,76,283,927,435,393,404,798,11,942,140,203,297,965,27,839,645,514,973,7,155,919,466,667,367,252,473,452,903,538,433,482,344,320,73,327,519,592,542,250,892,787,844,580,310,974,286,40,500,993,728,652,450,53,860,654,962,372,48,66,645,247,18,780,306,301,205,719,317,764,654,125,556,687,726,16,198,113,935,531,479,933,887,516,29,629,953,988,886,314,864,687,874,790,244,923,881,45,756,223,786,887,2,534,38,292,569,528,398,103,264,37,589,289,362,130,988,175,931,241,177,480,959,785,284,117,429,91,752,40,375,226,47,426,590,277,859,359,825,651,693,582,348,394,856,21,485,316,343,616,153,257,465,615,118,246,31,182,980,205,538,920,224,370,361,988,288,534,126,257,690,160,556,165,441,136,576,770,66,552,168,500,9,164,782,85,814,538,893,792,124,974,178,94,885,646,130,5,598,206,717,617,258,323,948,517,138,314,398,280,352,804,431,45,188,517,523,75,908,703,350,758,444,99,764,262,88,140,628,364,834,90,161,624,151,812,970,206,297,43,138,15,491,114,804", +"480,381,206,99,892,696,945,875,695,759,381,935,820,298,195,608,611,63,433,261,471,47,390,241,953,122,222,675,75,486,856,139,479,765,107,893,831,358,71,901,988,472,148,457,260,811,158,361,140,891,554,545,950,107,793,130,643,86,780,286,181,806,726,880,992,635,77,242,848,175,815,662,698,642,496,272,778,845,816,936,439,845,972,568,453,582,482,802,563,525,39,797,210,551,890,643,635,187,322,539,677,604,597,539,978,921,685,81,408,391,878,749,326,44,831,694,1000,52,394,338,607,793,845,483,647,51,432,109,614,447,899,870,565,213,363,590,930,967,791,738,961,364,622,511,644,71,742,240,933,431,300,506,27,630,283,321,879,653,271,141,793,200,512,74,686,898,438,282,758,583,555,772,760,922,291,718,818,750,349,274,749,326,469,192,674,119,758,38,346,178,405,221,222,414,730,767,751,484,571,248,854,577,414,85,392,772,532,137,337,108,368,870,291,925,210,208,222,285,256,900,104,720,188,73,7,972,130,702,889,978,810,515,574,828,672,199,946,921,952,73,140,848,269,806,691,886,718,186,728,997,27,769,951,249,846,278,325,936,424,898,572,617,813,697,330,361,485,61,65,885,892,886,352,848,145,5,971,47,53,531,685,28,888,666,77,171,338,347,159,487,991,927,580,336,407,531,764,746,135,858,518,934,128,980,766,911,279,609,140,23,32,23,538,959,495,964,618,456,666,57,595,992,466,892,937,215,460,639,998,824,519,596,41,855,211,742,478,315,628,262,109,832,243,219,955,577,750,560,449,66,256,646,569,319,70,764,133,723,602,822,27,204,7,991,978,587,861,755,481,105,964,629,235,980,969,462,14,586,802,756,915,899,950,219,612,161,951,966,182,987,302,747,251,857,33,797,0,23,711,590,691,22,557,468,403,991,646,753,658,670,742,478,254,202,924,738,87,308,938,876,710,10,406,478,69,294,370,80,404,271,249,830,160,915,511,57,171,685,198,359,718,157,442,985,948,533,891,592,665,714,309,826,207,528,316,611,515,495,854,134,73,232,725,559,41,314,440,540,987,105,97,640,465,630,455,243,788,466,869,767,156,686,226,370,845,183,387,9,696,98,797,916,717,681,87,591,753,269,898,309,482,354,743,221,686,160,37,604,466,958,428,542,210,666,680,779,392,487,94,907,520,934,677,637,489,996,66,853,146,605,608,79,713,818,681,981,578,233,815,917,40,68,986,119,905,262,623,485,186,526,114,822,826,256,522,410,981,434,480,121,422,318,499,543,788,230,943,12,4,663,660,726,84,888,367,718,126,438,840,405,155,651,784,75,473,686,997,248,170,91,424,350,292,527,126,103,20,212,381,672,666,454,255,440,96,912,187,337,125,259,519,185,650,422,331,225,210,797,544,959,36,20,756,473,739,176,811,97,648,364,803,606,481,672,314,137,899,709,942,211,261,64,786,701,924,579,948,632,884,417,736,675,579,114,527,410,239,841,117,155,581,780,510,299,813,488,118,292,722,495,873,992,93,467,540,442,952,167,24,518,981,798,658,537,867,474,982,492,732,428,726,930,265,509,621,464,186,750,686,129,796,29,232,405,654,338,892,951,524,502,249,60,69,346,500,188,967,30,279,928,582,221,799,60,421,476,632,943,655,672,584,243,453,386,673,649,994,766,218,584,135,191,52,542,563,238,138,233,89,491,551,298,6,189,710,991,494,63,356,663,599,348,958,997,809,914,447,256,735,560,539,998,535,658,168,743,49,4,264,291,693,906,206,112,405,235,262,909,456,390,322,580,88,167,921,412,804,47,776,668,1000,120,351,972,705,616,141,422,468,571,597,234,219,792,212,397,902,952,655,532,750,368,875,190,506,382,767,112,955,809,516,949,301,107,938,916,985,120,314,507,170,302,41,567,127,397,310,49,39,61,914,719,453,337,487,676,110,654,182,836,618,939,139,243,203,163,942,133,796,872,678,462,571,177,361,862,102,860,217,725,226,528,907,693,847,740,391,450,548,993,756,573,509,399,796,329,7,942,902,840,225,872,894,801,414,483,725,701,892,225,518,448,342,479,775,967,863,240,246,169,566,108,469,719,887,175,669,108,491,963,893,889,316,887,757,27,335,265,731,685,46,750,720,988,781,947,878,532,469,102,638,949,239,991,43,416,168,740,746,303,95,28,454,28,150,775,460,359,204,110,409,190,758,493,34,528,138,133,44,511,967,900,636,318,989,697,483,994,608,961,515,791,782,187,4,571,685,103,260,184", +"795,933,568,729,859,452,948,274,314,861,396,143,215,227,576,152,777,259,36,660,458,960,868,563,397,923,155,659,798,686,806,435,798,792,297,447,428,913,675,414,833,824,355,539,909,828,24,608,656,157,435,594,79,560,794,594,554,481,412,775,601,575,456,642,136,825,198,209,694,228,930,870,950,801,941,754,827,402,402,709,861,205,300,712,216,579,582,242,888,333,969,582,383,76,714,174,657,356,812,824,391,414,126,701,507,34,389,816,153,677,193,318,514,310,568,431,721,990,412,547,679,816,694,566,308,860,545,450,778,984,164,880,332,367,333,37,987,941,983,322,846,657,460,531,615,878,358,471,919,183,983,824,453,353,272,629,940,54,116,910,429,19,890,979,213,100,474,383,5,420,272,891,595,154,121,228,181,883,534,409,270,263,871,919,49,715,428,256,111,184,102,465,667,725,24,193,527,247,411,527,343,558,701,715,813,432,590,669,776,309,446,626,869,47,355,179,647,820,291,129,552,793,508,339,330,268,61,798,818,685,112,260,611,70,477,654,128,62,676,900,953,726,259,391,909,676,110,301,70,961,720,873,568,866,715,824,721,160,621,55,759,489,797,133,551,87,65,56,409,134,613,639,663,256,458,143,74,704,505,820,517,761,560,413,446,430,519,931,100,410,275,453,717,926,560,674,210,740,456,530,278,446,313,983,83,447,708,518,300,365,937,965,286,941,464,235,39,103,162,894,863,372,619,947,28,623,942,205,836,447,238,123,669,726,331,247,137,529,976,886,706,437,698,749,889,496,933,997,525,807,691,151,273,255,119,563,502,955,779,857,676,231,331,213,251,30,882,265,770,278,380,222,421,555,537,874,13,282,162,511,804,246,169,31,627,817,111,929,317,779,108,655,952,493,730,337,23,0,492,211,868,133,992,252,68,771,698,370,323,352,864,569,929,188,368,890,224,888,600,193,842,719,825,808,320,496,594,879,723,670,506,683,829,682,193,28,706,531,267,533,966,894,908,9,509,390,708,716,861,312,495,334,700,663,25,764,839,170,906,50,859,463,793,923,98,579,955,25,845,68,171,696,90,9,101,386,789,456,285,712,302,761,243,755,270,880,446,913,757,97,441,855,877,914,940,352,605,516,612,368,881,10,602,33,796,295,225,816,304,590,215,37,461,365,354,587,796,604,454,36,946,859,850,599,522,832,612,495,832,603,849,745,254,236,628,313,905,602,935,732,501,706,534,433,387,489,688,874,961,776,221,294,913,90,844,990,954,877,719,163,22,902,281,293,19,746,432,22,909,199,214,839,852,87,408,29,816,115,119,22,155,403,173,232,289,138,734,645,197,750,933,550,217,738,695,882,863,575,403,448,316,715,945,236,331,860,587,312,478,270,143,225,371,763,947,588,799,676,131,467,218,186,792,315,992,873,761,238,133,846,12,836,458,860,722,245,451,948,945,98,17,751,333,593,717,728,586,14,715,809,885,921,469,297,974,848,123,949,159,209,528,783,315,920,462,414,26,517,888,852,667,154,772,780,893,217,476,159,117,655,40,592,740,322,432,118,833,264,946,737,800,41,230,817,147,227,834,149,509,928,759,850,703,740,571,896,825,261,663,196,200,254,411,10,983,150,606,112,675,970,33,645,901,223,507,358,955,216,596,778,163,759,994,173,98,122,717,858,787,804,368,916,955,326,263,114,467,410,31,112,234,41,561,424,70,65,214,450,377,480,574,294,510,985,427,49,515,489,994,167,706,314,449,333,914,760,177,384,170,448,641,384,432,523,871,597,798,547,919,805,649,462,958,677,661,224,948,357,565,208,773,275,376,746,407,654,61,909,567,635,655,506,124,995,385,199,549,712,53,75,322,978,610,596,329,591,125,761,885,236,366,188,627,304,552,230,406,679,775,374,364,608,380,381,650,30,518,920,856,616,545,538,163,281,64,118,895,644,885,641,859,850,921,84,564,874,610,497,227,508,272,235,533,483,416,2,369,299,152,409,209,127,268,463,958,83,302,767,924,779,296,248,672,485,486,697,803,657,148,478,454,328,333,84,197,366,184,210,600,783,635,549,911,277,206,88,999,616,176,518,436,688,370,96,210,571,725,172,651,989,23,151,699,29,282,364,665,435,784,321,306,335,928,418,479,780,266,263,550,73,865,618,470,165,282,414,865,498,220,654,329,794,791,500,810,879,735,990,646,770,643,749,510,580,920,400,26,192,163,526,253,829,473,655,746,697,427,780,794,90,961,624,245,164,843,845,740,992,836,866", +"586,46,758,76,356,703,762,927,152,224,791,736,276,504,857,674,594,757,589,805,1000,87,386,798,48,856,372,989,907,657,898,677,597,497,976,73,94,564,558,244,975,38,198,609,403,361,392,123,599,309,557,561,879,408,420,161,454,72,50,645,638,613,81,920,478,676,787,48,167,137,42,354,545,400,780,823,483,415,519,30,407,71,705,648,754,952,485,768,683,778,338,293,214,129,897,175,899,286,569,245,453,301,738,31,905,402,718,594,224,558,614,91,459,213,285,602,218,254,784,399,597,940,293,58,573,410,57,438,750,604,270,555,764,50,381,413,330,736,472,858,389,200,248,54,414,459,567,808,412,798,873,399,444,448,298,102,688,432,841,323,991,94,131,640,468,54,819,775,937,931,264,628,719,636,168,352,137,911,802,897,220,769,384,890,839,934,910,106,597,679,616,857,402,358,634,200,817,947,314,875,580,161,691,709,246,510,615,15,566,553,967,914,934,367,570,538,740,858,570,45,14,359,232,941,691,397,767,801,628,951,796,31,145,76,828,545,695,578,134,910,881,705,522,315,968,810,304,618,469,739,593,624,390,984,264,632,378,724,880,219,459,900,307,349,30,674,334,581,734,162,869,871,934,451,772,573,693,298,597,847,368,866,412,970,673,606,773,795,184,691,293,749,667,438,993,907,853,224,822,241,420,781,804,875,593,726,486,92,450,594,406,192,72,12,183,598,400,104,902,519,207,960,985,693,290,251,493,610,309,297,200,119,41,715,421,894,72,344,765,469,172,289,628,645,963,941,277,342,76,654,511,996,510,725,394,803,458,938,343,755,901,226,929,407,755,107,132,114,672,800,595,538,488,208,956,485,280,444,735,690,817,142,728,939,842,754,406,129,258,657,39,357,687,636,656,846,711,492,0,751,705,565,273,418,734,243,239,419,610,925,325,222,135,472,126,513,759,439,615,438,340,886,738,273,497,32,738,796,899,881,622,389,315,636,192,480,894,449,563,520,811,470,68,62,740,643,3,894,718,728,657,662,347,938,503,185,363,130,879,365,971,545,506,253,278,774,800,424,772,745,212,856,217,114,742,892,324,202,293,227,421,956,453,171,149,204,808,641,392,887,326,79,716,643,690,387,852,891,959,194,335,470,602,19,178,285,391,195,649,739,612,453,707,285,105,818,868,29,77,585,234,297,974,659,874,965,999,486,233,136,428,769,250,950,650,517,440,500,199,757,874,553,216,517,302,15,247,641,288,787,308,639,149,1000,23,211,874,791,637,315,148,71,683,517,351,630,233,973,201,810,715,299,280,515,483,649,927,631,96,380,953,522,234,99,878,806,747,892,456,744,976,240,491,694,270,261,286,986,6,599,859,424,814,862,29,8,918,886,516,633,994,279,34,487,676,445,162,763,726,142,695,942,678,973,278,946,78,15,119,303,711,841,951,701,503,540,677,108,160,336,295,4,289,713,839,327,830,735,314,34,783,922,984,375,892,584,718,993,981,457,778,58,187,538,422,727,124,282,97,991,488,586,157,919,71,916,675,142,954,798,735,502,89,905,723,717,680,29,638,194,30,326,128,893,600,85,408,980,934,788,363,592,137,939,481,139,724,925,231,782,556,469,6,358,266,633,567,394,404,135,559,247,64,984,609,743,418,58,185,475,505,434,328,691,718,225,192,487,189,817,849,989,429,600,86,212,68,311,49,596,954,387,345,860,233,454,561,485,64,174,211,110,977,149,825,971,259,12,549,912,737,47,280,620,80,648,528,409,117,642,92,931,85,268,560,498,137,777,516,403,934,636,844,184,161,336,748,190,569,121,553,590,120,353,451,86,482,239,854,855,763,978,979,389,793,168,51,859,472,424,177,547,904,172,568,931,81,737,773,364,248,675,396,988,146,601,980,225,748,13,807,747,228,357,821,118,254,527,96,126,527,398,982,328,672,766,756,437,36,557,661,105,846,842,323,349,464,874,288,586,902,184,382,817,98,162,550,558,23,458,397,604,216,811,804,820,549,877,48,926,189,736,578,647,328,428,859,702,789,566,775,236,320,5,470,605,911,837,850,26,139,663,935,1,362,817,238,960,939,560,433,816,208,355,480,569,569,70,115,674,435,157,922,832,842,572,699,382,974,253,91,142,253,537,656,526,106,327,796,181,524,668,894,955,942,240,271,333,581,327,255,946,575,209,944,979,276,488,696,832,502,5,517,756,82,367,734,564,267,80,37,25,897,173,365,945,786,12,499,740,75,759,502,453,210,407,489,792,115,403", +"161,32,752,585,312,891,39,242,662,387,10,872,651,799,608,53,410,86,71,283,273,163,326,176,791,128,298,312,697,940,31,83,6,951,478,615,956,463,522,196,337,596,476,416,641,53,551,834,368,783,277,599,936,359,934,865,115,63,21,46,703,350,316,707,637,133,820,582,542,437,955,660,272,317,674,467,348,692,520,348,138,409,886,153,912,874,959,321,804,325,277,659,738,844,539,30,887,409,611,736,2,333,708,585,319,805,458,51,650,325,88,177,118,422,744,70,235,41,127,485,770,890,871,973,461,540,228,636,503,129,241,180,798,576,292,776,53,148,371,294,555,292,819,413,136,656,755,391,451,598,797,969,225,96,657,48,112,124,854,455,739,59,902,622,401,664,423,291,687,855,95,346,319,570,190,672,302,753,74,295,386,658,341,327,181,881,816,990,968,685,234,601,574,497,958,288,578,954,182,849,595,542,286,447,363,25,964,286,855,916,885,476,363,411,984,26,756,883,321,211,232,238,274,82,121,528,451,197,342,587,390,308,885,583,700,169,433,352,24,400,777,177,627,801,27,90,412,622,534,903,913,556,872,604,994,535,224,387,290,943,836,933,629,175,284,789,922,821,813,256,739,908,164,767,375,498,14,98,79,649,499,722,420,701,139,400,638,28,290,717,240,246,797,428,6,910,813,833,473,384,911,512,922,641,401,41,698,531,487,724,8,713,12,204,473,24,373,530,670,958,998,712,292,668,985,240,344,893,633,289,146,450,466,738,456,603,150,601,386,513,90,297,190,928,205,375,961,335,809,601,563,101,757,151,646,600,222,772,622,792,881,893,168,998,406,899,52,123,625,192,204,338,871,537,813,556,749,174,559,74,980,49,902,853,459,255,870,745,686,202,398,89,630,613,521,94,590,211,751,0,947,219,98,717,10,807,619,476,967,19,690,779,807,126,8,833,113,787,615,601,563,102,309,278,999,534,693,500,793,707,121,807,721,777,901,641,665,534,770,845,890,597,866,981,255,816,829,559,550,82,912,428,343,614,206,924,998,907,136,567,534,942,549,209,667,874,35,507,323,999,23,598,947,279,16,596,841,472,939,547,207,847,504,584,376,207,859,533,170,913,675,684,255,841,826,64,186,817,857,85,740,606,71,250,979,517,260,827,447,188,579,131,507,431,642,742,102,516,41,495,356,545,529,775,815,464,514,520,480,32,343,81,101,990,102,614,565,547,805,646,649,102,819,246,279,205,754,572,627,551,384,690,813,628,999,157,774,681,512,699,227,402,259,668,104,194,402,636,181,258,137,312,5,405,152,490,261,72,514,116,200,871,269,120,919,273,709,800,611,921,625,604,386,225,99,468,740,273,444,131,681,558,920,184,621,436,98,940,285,840,506,635,787,738,456,283,481,721,977,771,441,384,736,639,607,904,740,230,273,265,807,173,565,339,377,150,182,549,223,947,745,295,862,184,549,421,893,340,529,570,997,523,865,736,422,376,602,703,809,422,87,26,958,50,31,75,423,252,704,435,799,589,612,433,511,879,321,371,925,290,140,258,959,950,978,297,808,485,513,39,471,938,140,547,708,803,935,996,548,842,919,734,173,876,682,28,579,697,466,338,263,862,54,833,959,360,890,399,304,693,832,623,979,330,300,118,237,207,554,606,146,302,304,366,118,659,608,673,89,154,266,488,517,822,200,652,237,634,352,386,55,951,893,605,808,547,866,530,54,372,460,584,562,897,487,527,992,504,784,531,739,136,869,327,277,423,819,883,122,465,236,192,852,435,373,587,699,95,252,202,952,307,975,261,515,945,646,295,793,712,557,546,35,285,388,678,501,431,980,671,199,723,785,905,674,195,118,943,12,800,818,343,50,915,364,808,905,580,122,93,940,78,157,350,634,651,839,201,623,867,534,162,73,700,473,674,753,721,891,250,820,424,255,144,518,823,917,583,775,900,918,369,797,559,857,934,168,317,132,173,337,462,310,933,223,722,801,668,412,977,898,972,979,905,185,975,69,684,629,876,795,557,284,797,646,882,863,818,468,17,810,206,521,379,635,229,896,387,780,883,243,506,219,968,436,995,464,456,856,950,251,463,190,717,460,609,328,14,577,717,150,800,185,975,323,29,53,304,61,340,717,468,556,650,882,381,300,172,679,693,380,70,471,612,444,314,135,237,713,298,175,27,880,569,755,674,65,648,746,607,776,764,641,288,577,601,179,92,151,134,956,347,645,642,594,379,318,78,805,763,846,639,678,768,706,292,418,272,246,404", +"962,920,346,832,803,218,474,716,621,451,780,11,161,684,80,567,245,357,940,238,784,299,188,841,507,908,592,106,577,466,394,612,638,110,346,484,759,574,693,292,755,103,148,62,342,21,523,137,109,267,957,830,294,464,922,829,553,582,872,677,474,368,139,889,757,545,672,476,440,28,843,942,883,481,653,580,924,88,404,127,94,546,317,213,736,913,659,361,856,101,883,501,740,793,879,824,301,995,929,623,835,394,549,426,280,729,218,573,570,695,583,331,375,374,532,304,432,979,373,675,828,278,531,587,904,54,193,159,87,717,100,759,256,896,278,999,757,621,582,702,807,326,907,398,815,991,443,91,69,950,207,764,135,131,267,400,702,335,452,249,724,427,526,125,634,44,685,927,399,800,968,658,506,712,28,11,744,92,685,796,687,241,32,840,130,213,424,983,455,718,535,646,520,312,363,101,491,906,874,485,438,143,425,872,54,624,667,308,611,946,409,739,16,438,707,74,273,962,112,973,946,239,911,783,574,955,256,315,715,212,586,988,124,190,188,309,838,928,358,36,75,416,209,980,883,892,671,60,891,189,176,133,721,687,685,502,790,112,745,459,340,221,568,7,59,673,66,282,878,743,863,792,215,302,779,293,341,172,358,451,126,756,992,116,177,200,671,210,994,519,796,727,62,338,193,438,279,8,63,827,99,253,691,879,503,342,441,81,534,389,339,710,190,804,418,773,14,481,982,86,66,749,214,95,292,336,487,278,341,995,992,730,717,10,488,129,707,404,389,942,961,656,296,134,259,543,63,83,623,390,989,490,200,909,765,514,284,549,214,715,559,387,143,960,281,55,954,988,101,174,679,209,172,709,380,602,922,482,176,828,278,721,586,348,594,483,806,922,767,554,61,60,536,310,745,502,691,868,705,947,0,113,154,48,186,457,305,71,888,299,637,877,904,663,503,522,47,497,109,626,14,890,793,412,774,229,82,718,380,108,574,86,803,10,539,535,907,270,568,574,467,764,570,926,652,866,808,115,781,23,322,876,890,628,723,247,625,418,635,540,956,29,822,983,551,120,290,938,421,226,487,959,293,679,837,507,313,586,107,582,257,875,132,345,932,399,395,129,289,740,512,825,364,219,817,221,646,657,265,658,16,927,940,756,306,975,143,943,971,586,561,990,380,511,386,705,390,196,590,318,410,224,970,541,589,617,600,389,889,486,35,953,506,567,933,29,495,2,652,854,860,512,547,47,369,381,606,770,553,991,444,826,979,209,546,766,321,429,151,982,643,667,67,391,515,585,37,102,611,616,45,222,656,172,283,514,201,394,583,41,551,697,841,163,443,192,868,826,886,719,947,680,597,967,761,838,955,672,553,661,159,504,950,321,193,769,235,264,941,172,996,433,799,8,762,948,33,845,127,746,837,574,372,773,28,248,149,261,711,144,231,762,309,70,919,718,901,581,279,43,113,306,731,145,733,294,351,924,530,886,339,287,189,707,618,297,854,965,51,285,718,223,807,711,123,260,616,602,252,698,196,685,566,949,422,896,988,55,568,901,536,186,144,696,550,599,682,104,743,921,218,955,194,900,579,416,70,957,387,919,306,231,585,666,680,231,560,807,141,338,799,112,183,544,178,381,369,70,629,916,456,129,447,975,350,46,609,256,88,883,846,650,322,215,108,775,775,986,406,842,8,931,999,926,493,764,707,226,717,36,751,792,81,675,628,744,657,643,393,850,628,568,874,292,280,543,430,866,106,692,705,668,763,918,160,946,782,965,659,693,564,904,547,80,401,761,481,245,871,169,216,230,935,194,694,812,116,576,460,333,203,666,203,279,750,629,893,867,457,924,618,93,248,923,47,177,991,238,977,285,467,970,84,634,526,394,226,363,775,746,28,884,850,593,95,304,503,577,663,652,707,332,146,430,597,310,961,383,570,306,175,206,796,484,534,945,707,408,713,614,787,923,609,969,859,168,684,356,238,271,236,712,614,279,434,192,450,877,587,793,863,963,986,358,39,773,271,408,633,914,387,526,461,214,580,29,77,978,169,82,426,638,244,884,193,203,274,877,237,38,482,909,622,797,759,960,897,881,476,471,277,913,990,348,168,539,502,615,178,126,75,89,437,587,26,203,113,470,824,890,647,956,913,403,944,604,335,925,644,692,461,56,634,466,23,766,714,96,124,947,243,336,459,315,992,350,498,758,459,673,975,59,941,490,772,829,684,315,695,918,386,495,809,766,795,548,644,708,634,640,194,427,273,972,49,497,331,872,213,250", +"546,646,738,837,982,502,897,829,132,624,563,716,914,824,300,217,675,325,54,32,982,948,496,32,766,793,352,979,924,222,445,186,941,712,809,922,35,154,200,611,660,933,445,236,303,988,437,925,14,952,498,143,934,104,382,696,96,592,430,473,905,349,377,208,930,938,95,718,439,26,192,724,493,578,861,719,195,826,936,654,667,745,317,778,696,168,44,287,717,339,530,63,508,291,17,894,330,181,63,25,857,354,880,461,20,832,751,245,152,680,859,204,61,119,973,636,298,463,526,696,760,625,191,396,724,172,830,461,246,243,624,202,181,360,407,846,143,4,807,812,368,357,658,901,69,591,142,612,248,332,931,551,413,388,815,232,203,533,536,35,760,713,825,53,104,142,91,383,750,685,294,695,691,784,191,645,702,244,500,836,88,872,620,770,894,939,796,868,417,665,488,910,812,103,275,364,952,796,450,152,636,905,218,179,923,694,744,645,763,663,516,630,310,893,467,753,351,836,226,310,182,871,52,353,691,420,961,481,402,295,206,410,945,210,846,750,393,420,647,405,902,110,242,254,875,342,753,485,132,697,327,891,230,732,37,72,480,651,258,270,954,827,844,451,346,189,954,525,663,90,750,44,857,327,461,699,192,654,234,336,416,873,723,948,288,933,407,242,563,62,121,296,581,193,134,363,49,723,4,803,498,247,492,881,349,63,114,338,154,525,865,178,569,493,647,824,305,336,842,46,540,248,179,688,405,908,438,80,814,984,702,548,243,208,717,871,275,815,891,708,265,502,662,113,673,822,969,898,924,622,844,302,862,62,994,206,565,979,469,610,83,302,211,582,298,840,904,166,816,912,862,832,685,212,672,449,360,555,483,866,625,214,545,941,610,705,929,585,103,331,87,646,750,848,155,438,22,133,565,219,113,0,868,971,864,425,483,979,260,76,245,122,772,940,796,381,255,117,371,731,935,875,835,795,448,350,505,440,771,712,764,613,518,948,508,670,5,357,257,272,422,390,313,14,707,946,187,894,879,153,459,249,544,39,44,169,546,664,898,489,73,970,73,506,419,689,791,258,21,568,260,232,546,164,931,449,547,767,95,575,698,106,781,963,519,437,522,360,760,744,407,2,396,83,87,113,185,371,731,517,200,208,925,392,32,816,851,174,131,971,47,371,104,802,225,918,545,840,351,401,820,453,587,499,21,850,22,473,287,955,441,92,730,975,553,906,958,801,47,973,673,383,872,115,916,73,564,847,528,92,195,24,428,727,318,968,376,959,282,234,617,435,113,179,850,573,618,438,871,723,526,99,335,493,532,566,716,962,210,527,758,39,741,985,608,9,475,550,943,484,115,353,45,737,902,512,609,375,655,692,225,742,107,63,154,708,528,509,92,929,631,824,938,343,735,970,388,932,385,860,561,240,258,553,168,688,690,515,349,414,854,444,329,602,309,959,584,806,116,303,623,517,859,175,380,972,735,22,958,827,260,876,628,491,799,487,900,286,164,438,128,266,531,333,553,777,561,691,825,780,220,827,3,70,509,361,196,914,279,795,682,187,516,352,228,942,897,839,23,297,935,117,697,205,843,759,311,613,264,716,200,823,258,770,325,526,370,65,543,411,763,613,716,273,751,438,249,384,8,604,176,690,831,772,90,717,310,849,773,905,559,116,866,116,134,217,729,990,625,104,390,909,125,130,62,955,745,928,805,830,246,721,44,194,414,815,377,155,25,304,559,570,91,456,834,421,915,893,51,540,844,519,709,487,7,512,236,525,217,214,68,270,168,134,611,161,437,346,122,418,843,25,329,176,474,414,948,263,489,726,186,439,686,97,280,514,959,743,166,769,956,270,620,319,795,263,141,483,711,970,140,930,316,942,927,838,669,193,680,273,901,379,598,984,533,32,11,120,581,353,112,242,611,621,327,11,611,785,323,548,716,857,592,100,295,511,560,133,581,593,691,994,155,899,522,569,655,891,423,53,531,182,259,172,340,329,270,30,969,449,280,912,626,776,546,824,174,753,990,12,895,342,328,209,423,346,593,916,449,325,24,889,64,625,465,893,895,688,26,426,439,599,792,488,849,170,251,505,705,848,14,286,671,38,658,709,732,972,449,396,955,215,173,366,343,173,130,352,168,710,943,888,480,11,583,404,41,427,655,774,708,282,943,590,288,402,748,455,305,311,94,828,699,16,422,838,494,121,567,589,969,84,495,633,868,47,561,370,327,689,618,138,339,271,43,700,784,308,6,402,124,722,44,34,213,588,505,626,442,682", +"891,46,131,838,221,645,604,145,970,833,851,975,587,204,880,375,884,149,626,710,153,654,653,949,85,394,767,125,460,255,462,188,559,312,368,41,270,977,591,735,62,219,483,627,641,910,550,273,46,396,709,976,803,410,345,660,594,389,109,186,808,133,99,260,57,295,353,462,291,690,476,844,334,781,622,971,827,861,996,356,546,912,14,961,746,393,791,105,993,106,723,75,404,811,46,61,254,660,157,33,319,346,421,187,189,132,527,837,368,391,489,51,155,366,743,871,502,624,428,488,626,811,382,111,959,368,48,554,467,695,296,762,854,983,892,382,281,987,156,652,258,462,948,814,447,801,807,206,453,583,155,654,796,872,651,424,682,379,285,94,376,400,987,409,435,848,263,12,281,997,697,542,570,105,539,348,316,9,147,1000,34,808,903,842,944,286,756,794,472,406,218,627,845,416,903,730,38,796,459,13,614,729,383,467,896,773,480,833,533,744,416,278,990,158,851,95,886,565,337,793,834,795,332,300,176,248,472,786,759,730,653,335,148,339,994,955,318,164,634,272,80,102,639,612,717,636,140,768,810,757,152,646,857,786,594,157,782,722,505,783,167,520,665,778,682,877,20,433,349,6,881,974,588,275,661,362,587,5,88,471,479,28,764,223,892,206,93,240,756,882,367,396,480,715,515,139,798,814,289,314,877,819,504,652,706,396,607,522,536,448,530,717,506,768,945,456,139,364,484,733,535,656,405,218,630,258,36,510,917,191,57,257,566,288,482,511,38,77,790,471,844,620,534,597,398,528,925,220,568,228,802,685,671,756,557,312,791,547,385,158,834,999,952,586,915,505,710,964,50,615,242,459,923,2,909,611,105,224,824,245,49,313,995,93,381,668,937,841,897,912,117,316,226,191,894,860,557,992,273,98,154,868,0,358,78,103,531,641,594,614,386,651,881,156,241,680,568,379,710,140,743,79,208,613,438,955,425,108,488,701,852,134,708,546,463,536,943,992,480,904,226,106,207,950,130,668,896,65,612,569,183,498,404,805,674,510,642,962,878,882,263,581,186,777,578,65,408,975,56,424,106,87,223,875,916,617,305,359,643,203,213,307,973,519,98,503,673,239,638,169,613,240,484,636,643,698,706,90,88,164,903,18,945,40,733,589,842,193,324,172,94,210,866,46,330,991,793,440,494,19,775,509,854,442,874,654,196,949,467,725,833,22,231,710,103,215,165,627,848,906,670,442,793,145,170,127,292,558,403,646,601,180,775,137,816,575,589,586,617,133,432,507,51,325,457,641,359,469,359,538,989,720,79,663,941,861,712,316,323,231,652,41,396,389,639,414,574,352,430,57,891,842,351,328,873,84,323,801,404,41,63,208,754,335,785,878,233,774,361,866,615,417,662,726,106,217,1,832,962,284,927,909,407,214,520,848,756,924,774,128,143,231,390,752,338,118,402,511,103,422,594,308,869,738,355,462,67,132,581,277,115,675,988,510,974,626,548,153,825,395,637,376,642,910,946,357,788,902,97,852,513,761,623,951,256,901,989,140,648,600,392,132,519,82,229,208,996,130,320,411,187,335,894,299,447,424,187,135,751,410,802,50,904,336,732,9,203,31,192,815,71,465,547,679,660,770,919,666,634,81,206,719,90,288,729,575,905,389,388,530,777,746,336,11,505,178,638,428,717,607,329,711,724,79,977,937,696,994,440,896,113,17,210,435,163,575,470,168,726,638,651,777,669,547,748,594,278,346,388,408,641,207,589,971,434,573,925,767,905,680,76,245,996,743,877,271,291,651,226,911,8,895,974,298,804,3,336,468,633,373,916,597,356,69,47,676,913,138,246,479,997,881,497,21,201,111,150,111,33,532,899,5,150,824,31,662,437,11,78,127,626,345,481,493,744,272,381,13,833,141,456,882,296,434,542,517,931,214,929,918,127,692,451,854,756,840,886,14,177,466,659,516,615,615,381,443,906,406,597,116,470,615,861,4,661,896,772,623,934,634,678,955,919,80,209,889,894,968,530,64,263,404,618,290,257,306,87,444,952,77,687,104,267,153,765,791,44,682,805,949,972,667,711,209,366,828,983,485,201,632,955,467,620,926,938,885,840,117,712,737,138,960,2,551,463,253,960,862,78,675,951,32,993,165,740,14,328,354,23,878,98,111,918,842,410,181,644,384,871,48,565,904,394,127,696,416,41,615,548,902,797,659,98,618,432,44,454,691,950,423,167,132,671,81,700,691,580,263,758,32,173,147,648,497,394,115,386,598,959,522", +"223,482,601,4,565,815,11,68,341,83,835,987,155,114,65,929,783,884,712,603,933,264,803,567,402,593,383,399,446,419,491,450,775,276,320,962,509,833,750,939,17,648,273,168,63,802,796,100,453,963,154,120,963,562,970,590,166,835,948,569,116,352,549,749,505,438,967,626,444,827,315,504,81,990,977,42,806,576,595,714,686,422,43,920,517,722,2,737,509,197,394,752,990,70,313,163,113,300,263,592,995,311,402,438,838,993,628,798,328,398,5,647,621,269,264,907,633,969,193,393,861,64,176,556,608,661,893,703,242,14,307,441,490,373,899,618,158,324,126,807,467,428,303,426,730,157,677,893,667,536,588,679,185,138,688,977,587,288,582,113,986,167,489,59,517,250,12,845,100,47,426,993,14,779,950,695,517,263,45,85,762,219,793,826,942,398,819,459,157,260,701,867,319,190,55,825,170,29,401,730,63,873,346,20,889,665,607,59,606,574,745,232,576,815,708,880,476,38,143,729,252,932,688,314,115,214,57,148,646,572,436,933,625,740,645,168,916,234,565,471,877,890,697,678,453,697,673,979,911,916,334,730,57,705,144,792,338,469,6,395,793,983,198,595,540,553,768,642,352,118,463,498,243,162,582,654,925,873,292,675,800,747,565,320,606,123,699,60,54,586,124,409,255,943,720,79,646,897,854,751,704,386,269,835,721,78,748,768,280,539,389,673,68,565,761,696,495,546,457,375,599,997,154,994,362,818,749,294,664,405,642,531,481,966,483,650,301,212,495,202,837,278,119,128,608,182,599,175,558,841,248,440,546,512,124,471,587,940,952,940,652,15,912,964,801,654,165,932,259,831,297,748,98,59,986,686,111,481,211,262,374,810,344,782,362,555,16,437,400,664,25,340,364,514,941,319,468,252,418,717,48,971,358,0,457,60,891,658,957,358,743,474,913,296,690,870,795,995,416,920,592,298,774,592,907,344,911,324,201,914,828,490,636,557,567,509,107,492,144,630,88,375,576,785,508,302,359,855,682,917,8,989,303,857,838,758,148,674,827,104,950,535,664,768,672,113,900,338,72,444,964,655,40,637,424,339,55,957,733,345,354,624,982,845,552,99,274,225,348,67,793,460,304,309,622,845,984,119,173,668,727,90,936,935,3,676,162,79,517,932,505,575,312,809,78,859,668,647,594,249,298,720,186,6,639,267,452,904,637,276,533,95,596,785,881,602,141,496,16,220,663,629,595,608,223,725,201,149,120,22,711,262,336,178,334,103,342,415,469,602,348,419,272,296,314,561,558,871,189,98,6,890,777,897,242,878,736,271,50,736,877,63,511,649,504,38,122,83,777,286,333,809,14,962,204,438,926,594,726,481,917,785,855,373,108,751,336,571,503,257,377,870,117,4,783,450,529,211,233,369,902,885,677,878,627,784,363,215,362,481,638,846,474,153,50,221,827,591,611,316,251,418,917,813,727,932,532,155,206,67,338,148,344,357,53,261,848,459,800,224,570,470,780,719,92,723,594,10,546,701,308,519,668,841,615,645,71,926,76,377,558,579,37,138,588,207,840,294,939,25,809,961,964,552,69,384,520,893,169,680,430,426,655,898,707,935,89,527,303,955,994,112,940,17,60,960,467,520,602,905,483,387,202,208,7,663,3,838,309,879,140,591,442,937,467,530,888,299,88,158,29,238,32,750,344,37,598,691,775,833,398,213,180,866,51,914,228,323,135,643,629,960,185,97,936,210,544,600,346,850,911,245,64,566,444,209,839,20,727,400,808,927,471,521,262,975,983,905,252,418,727,853,297,304,251,595,650,311,407,241,988,324,825,717,60,727,78,796,826,821,667,67,815,301,636,38,46,939,82,259,135,469,973,811,927,188,946,8,617,348,221,423,928,613,598,690,110,604,757,204,195,730,785,701,985,195,250,141,823,194,587,83,975,628,742,257,484,731,972,491,842,579,450,41,631,66,51,227,277,290,353,690,236,371,259,789,750,107,283,467,237,62,66,246,650,327,950,339,180,75,841,769,909,51,102,654,470,242,484,98,526,82,347,101,118,311,478,153,196,200,280,789,924,847,690,519,872,728,902,266,929,895,586,948,984,538,967,759,340,562,352,659,741,880,551,669,825,196,923,988,12,160,6,120,493,152,884,956,959,301,529,187,128,524,675,811,386,331,762,471,667,300,245,680,773,245,173,401,262,171,120,923,880,488,379,810,233,651,874,649,492,986,798,231,750,801,248,225,214,818,753,427,11,982,964,77,246,403,593,953", +"476,479,827,777,799,611,965,911,732,911,224,366,479,723,203,469,723,459,646,914,356,884,352,643,262,536,351,541,130,823,705,533,933,593,29,48,112,977,748,365,569,321,693,188,765,529,244,6,825,806,550,844,887,301,320,61,104,428,505,98,450,184,864,563,784,652,792,947,835,401,116,488,67,638,809,650,374,718,349,543,63,379,209,147,191,434,528,445,736,673,100,355,155,123,892,676,474,39,550,789,193,404,515,100,63,401,935,926,259,358,886,703,358,872,609,237,377,678,848,903,77,450,746,237,450,634,252,813,644,889,942,855,258,94,653,870,779,854,171,652,309,788,824,120,284,971,126,217,737,444,738,109,20,214,951,343,22,501,548,839,968,175,350,592,299,659,496,678,982,598,224,656,358,223,523,660,332,860,837,155,170,339,975,959,200,446,578,287,30,851,51,646,74,783,12,444,102,243,225,515,68,859,852,644,631,346,15,899,328,812,82,676,455,496,47,667,441,718,242,706,16,170,112,853,195,786,853,842,539,532,984,91,894,329,11,541,935,27,241,295,51,629,165,640,374,472,896,870,278,841,875,774,20,30,852,560,678,623,456,858,248,899,748,954,618,943,957,681,500,57,570,753,599,2,476,603,919,434,461,142,91,593,510,573,269,398,521,548,514,776,94,407,59,603,360,910,797,177,585,470,140,322,209,551,245,874,412,276,929,144,462,433,974,315,66,95,362,853,398,904,154,707,216,17,245,618,915,899,549,426,712,227,159,753,696,592,80,364,201,118,806,819,188,672,636,772,271,435,688,802,642,64,320,169,681,959,288,607,79,957,167,798,535,518,864,449,713,255,370,156,75,117,458,563,950,955,423,599,131,992,777,93,230,303,20,962,161,823,229,488,786,963,692,457,174,892,403,68,734,10,186,864,78,457,0,524,653,992,330,570,992,356,125,866,360,692,121,912,924,372,476,540,780,454,207,66,819,590,714,921,337,475,190,559,290,641,273,223,390,263,42,865,385,133,878,649,694,397,600,803,428,580,529,150,959,845,385,69,803,858,897,88,495,904,479,393,792,746,348,734,107,377,971,305,353,831,571,292,882,927,797,400,591,865,227,463,297,454,586,52,272,652,704,38,611,698,263,567,673,29,618,732,114,975,520,641,827,786,66,996,515,59,424,617,693,690,658,294,817,646,369,897,698,442,74,17,756,647,536,727,486,786,596,515,889,65,486,453,541,594,79,429,861,810,44,591,114,233,899,686,15,153,930,590,763,218,513,458,748,393,687,978,504,786,938,970,644,639,13,438,881,638,361,304,714,538,535,908,853,75,140,791,753,117,450,796,480,272,867,915,567,721,312,944,775,799,358,296,135,761,928,970,537,400,667,179,741,865,3,967,392,144,739,515,583,660,76,810,259,850,974,753,182,421,267,782,288,226,364,354,719,477,40,371,199,428,556,524,565,602,426,608,212,460,960,740,176,564,479,287,794,353,994,569,459,88,60,178,352,178,703,266,556,291,720,328,708,826,782,638,861,945,986,63,113,287,839,846,992,10,217,531,530,474,823,42,165,733,276,164,585,458,189,790,363,890,758,286,535,325,89,257,184,23,254,705,265,317,61,819,925,207,468,184,459,143,85,287,696,348,876,192,849,632,846,565,272,658,819,704,514,653,334,287,118,808,683,515,956,286,195,469,435,827,551,212,563,895,579,789,442,408,1,93,595,614,482,892,141,621,959,117,942,700,8,931,248,469,740,666,503,719,784,936,906,504,418,588,655,784,786,594,317,844,157,415,246,614,641,824,367,875,488,638,467,84,999,683,16,629,60,625,818,19,942,275,451,466,777,229,732,298,269,864,87,979,902,395,317,218,264,839,596,907,966,721,881,679,955,629,904,962,299,440,452,803,409,518,60,370,123,731,30,888,111,287,820,701,981,66,505,587,300,655,305,110,947,61,780,809,211,472,657,833,296,162,191,390,213,183,734,429,164,468,205,630,401,549,332,632,922,75,99,755,175,851,455,558,428,712,465,907,190,248,434,123,227,27,471,272,978,432,959,590,330,851,187,417,367,686,171,712,130,185,194,955,734,860,769,53,157,929,677,330,926,881,291,394,438,42,124,121,848,916,773,216,574,481,887,295,327,136,205,385,180,27,498,773,195,621,588,726,31,597,952,705,61,564,699,514,38,216,415,142,737,102,812,161,463,696,518,262,637,100,22,141,391,253,71,658,650,784,321,548,464,685,223,198,805,515,709,267,76,753,73,15,682,685,136,408", +"937,588,22,300,161,696,945,884,562,305,150,742,670,863,902,709,540,802,59,629,460,225,38,87,535,591,102,887,107,944,113,194,469,616,921,447,347,973,211,474,741,415,331,246,167,834,289,815,69,553,824,326,849,679,771,196,28,127,973,590,676,583,838,590,213,458,456,942,364,236,273,817,462,607,99,994,645,375,119,116,899,318,859,537,271,693,738,459,50,413,152,70,144,16,140,839,14,572,522,394,554,268,30,627,523,322,292,851,932,95,775,376,188,635,144,554,342,750,935,731,659,279,801,403,973,590,76,819,543,392,106,389,15,197,632,566,119,118,732,624,89,912,816,530,440,130,536,399,294,220,674,847,750,725,555,877,689,178,564,149,428,595,745,303,304,775,57,887,106,863,344,385,930,44,960,846,957,670,659,144,389,985,696,282,490,294,219,328,829,684,308,134,998,506,459,367,486,268,495,516,963,423,375,682,860,821,78,623,642,670,368,273,511,337,78,998,262,954,50,836,164,882,996,987,601,720,501,863,640,291,273,204,481,15,16,790,33,535,420,679,399,359,966,346,921,866,777,761,504,60,427,884,149,456,326,777,230,345,897,719,354,649,15,454,288,421,609,74,736,124,803,203,292,280,563,974,645,247,520,478,771,966,993,37,630,478,662,995,91,293,492,356,142,311,220,330,331,597,760,352,96,497,992,437,596,60,653,959,476,926,583,713,189,818,459,878,527,189,513,436,101,898,446,302,797,894,948,253,548,778,588,235,113,962,826,819,956,901,817,586,362,990,595,455,256,685,816,375,108,857,265,831,36,471,667,886,549,122,966,550,695,602,644,701,226,100,371,791,441,594,66,280,579,886,72,993,605,359,250,163,572,854,374,293,672,370,151,430,291,604,773,288,299,746,842,280,991,771,243,807,457,425,103,60,524,0,486,199,405,424,571,9,128,198,124,346,421,795,859,395,248,462,247,889,805,790,263,401,38,326,824,450,910,78,273,16,594,846,583,709,802,542,485,201,950,802,862,642,428,772,648,626,850,306,427,779,102,961,608,559,320,237,298,974,113,454,280,533,109,419,524,947,644,279,286,197,22,349,497,649,512,20,984,247,331,698,850,205,714,192,691,148,652,706,250,650,361,927,285,540,742,201,93,418,790,726,876,469,618,416,312,276,778,261,410,441,137,854,965,624,736,73,110,656,604,857,652,999,858,908,997,367,890,806,828,605,228,521,460,297,486,961,65,276,662,520,214,555,737,929,611,638,44,699,509,124,65,801,419,298,808,889,368,175,956,58,357,728,927,295,790,639,803,996,196,640,569,109,381,37,279,70,732,44,612,15,703,107,876,357,772,10,300,905,547,977,123,288,7,552,799,611,41,655,133,509,40,414,939,152,809,534,743,138,931,646,988,392,829,245,883,907,254,170,482,861,749,889,316,812,538,405,195,620,859,177,216,34,950,471,409,579,319,516,55,377,182,356,798,203,191,236,494,863,473,790,111,816,486,988,849,106,968,391,478,1,480,294,577,960,655,695,581,255,674,185,319,214,147,157,526,687,66,104,957,108,266,853,152,583,832,808,647,823,89,227,324,660,667,297,44,292,724,177,518,786,896,486,542,736,57,474,286,871,939,609,475,680,526,536,914,566,510,776,205,930,726,422,418,501,397,184,189,548,901,539,446,571,762,98,966,439,706,826,630,149,108,993,993,323,616,455,835,803,465,103,683,295,183,337,642,48,671,39,274,294,270,487,164,690,206,461,390,660,238,69,944,15,685,249,710,404,755,865,17,392,486,598,110,199,767,630,676,899,397,336,491,69,198,797,81,528,494,253,196,461,628,317,527,590,753,411,551,305,921,695,428,590,880,239,169,188,741,182,476,824,137,967,541,339,319,974,957,666,573,638,230,106,23,8,717,362,248,960,278,145,133,854,968,271,934,597,281,985,409,567,82,481,110,18,416,244,417,286,514,858,811,608,5,301,260,5,384,784,21,296,453,676,323,149,770,871,353,164,600,47,429,388,99,366,466,850,371,651,314,415,464,883,210,173,988,550,327,819,726,411,918,191,336,968,341,909,133,975,267,125,682,514,900,514,938,921,778,765,608,799,385,668,971,396,859,356,207,985,450,994,508,114,594,986,138,815,132,924,780,877,359,274,81,654,321,828,809,52,754,575,513,133,763,899,78,810,868,862,18,309,936,103,763,700,110,467,392,981,292,565,130,79,586,604,428,989,987,148,742,617,677,475,918,422,656,28,387,578,16,302,439,295,896,199", +"669,596,448,30,557,310,709,352,314,280,552,145,998,320,949,335,989,915,401,698,483,529,886,133,412,182,679,802,874,226,857,711,391,264,721,918,174,255,678,677,710,95,486,791,790,831,355,282,892,247,166,720,127,840,342,722,692,183,918,143,873,543,69,361,735,891,924,785,447,251,22,336,615,458,323,26,343,149,762,193,803,396,502,804,388,149,197,314,783,69,610,713,900,630,614,37,67,71,542,326,829,564,261,280,594,279,927,446,364,636,471,348,331,591,579,33,151,867,770,547,667,936,105,545,7,820,134,533,686,804,552,867,142,337,728,904,407,896,342,118,786,570,202,172,849,410,538,976,241,891,876,257,656,454,881,609,62,352,862,508,664,622,270,737,861,931,498,161,637,548,376,844,117,945,372,88,943,701,882,339,481,240,568,44,282,351,311,449,788,405,68,151,771,155,493,634,76,983,603,840,329,726,589,95,78,489,367,456,994,964,155,193,862,916,577,59,578,614,798,646,729,469,862,677,204,788,659,917,891,779,873,615,162,329,385,982,608,913,347,899,648,629,459,834,855,673,616,21,887,530,905,662,894,596,656,675,951,519,868,885,691,468,164,997,151,522,26,785,892,727,903,171,9,894,565,523,853,978,396,188,393,300,6,381,374,281,760,87,225,813,404,968,500,404,23,29,81,361,660,83,861,113,531,561,3,145,283,181,761,518,572,772,182,135,470,558,187,980,992,567,69,30,895,226,527,647,856,661,662,168,14,287,850,296,942,700,889,117,10,585,999,795,663,375,544,356,393,116,828,106,44,418,938,762,684,50,400,693,446,202,622,196,90,581,85,870,648,618,744,25,746,280,619,50,913,594,527,630,303,316,488,87,228,333,547,587,82,215,899,871,225,897,33,815,982,4,646,698,239,619,305,483,531,891,653,486,0,171,653,234,671,931,399,665,408,872,854,888,67,347,963,345,424,169,949,17,234,788,971,368,669,995,2,273,782,31,614,757,189,454,416,522,295,538,285,124,126,918,199,432,808,914,241,506,33,278,269,299,388,838,214,289,877,312,520,784,955,827,701,721,821,311,788,23,306,521,59,397,399,183,911,98,903,754,951,284,97,314,834,742,701,160,218,850,365,389,705,824,2,114,931,916,737,3,931,327,46,509,673,275,99,998,309,575,973,162,310,122,737,138,512,886,120,285,926,418,642,535,238,447,655,235,505,961,942,472,884,973,418,756,729,302,122,593,562,894,734,60,583,165,948,12,293,111,491,807,666,960,212,342,995,95,258,746,324,63,705,899,663,81,665,179,918,246,924,236,33,921,774,748,509,817,908,726,701,259,992,802,639,191,249,125,834,298,134,812,883,530,689,251,107,313,632,986,198,941,306,562,438,632,779,114,522,625,879,952,936,669,598,924,278,298,620,871,867,225,703,926,937,263,881,337,857,247,398,65,919,772,396,756,683,846,529,360,956,33,771,286,147,436,390,48,692,507,28,915,395,141,66,302,404,716,75,443,666,675,598,947,145,504,527,944,887,891,927,46,121,407,214,634,50,278,371,708,69,42,195,680,98,591,577,810,872,545,378,507,955,446,160,60,337,951,616,658,645,582,153,358,929,407,318,336,988,22,872,507,506,498,830,72,899,437,305,929,672,464,668,350,85,259,545,78,60,731,472,733,84,952,83,785,185,643,281,403,343,149,520,759,905,513,553,757,471,138,420,540,62,830,808,737,467,822,793,628,27,91,628,867,424,480,962,288,597,152,612,449,720,697,992,97,145,363,967,663,4,223,273,941,569,401,673,35,498,640,387,730,42,665,789,497,21,881,450,89,944,964,353,310,665,578,64,981,335,981,65,425,518,373,126,607,439,433,706,790,72,918,539,867,264,220,33,563,694,366,838,603,382,341,801,756,387,836,242,945,921,336,362,353,827,161,123,574,234,576,227,498,369,41,304,448,494,966,272,742,791,842,244,556,482,496,989,569,465,109,685,301,197,542,706,506,402,66,476,488,973,31,444,461,584,555,818,776,876,418,973,497,751,615,559,513,454,674,991,781,395,267,844,7,980,765,30,589,1000,500,732,196,895,873,884,842,487,936,851,661,808,83,899,100,752,221,195,148,537,948,360,918,408,742,967,888,906,268,186,309,965,805,657,139,992,82,40,191,702,294,27,864,790,896,681,111,508,484,793,163,901,192,537,499,280,223,787,701,939,980,956,252,76,811,320,179,230,447,436,405,302,447,735,56,423,581,241,813,279,931,681,895,365,234,326,189", +"938,263,216,78,185,328,705,766,607,247,634,838,468,934,389,187,954,917,499,252,509,154,295,811,31,682,635,77,360,74,518,371,388,7,470,786,799,786,625,730,158,210,615,697,488,833,556,175,414,724,89,365,288,271,961,718,365,186,437,912,258,936,104,142,707,900,364,921,719,691,876,959,869,322,678,374,812,773,671,390,730,442,220,842,689,103,438,824,562,149,132,902,225,503,466,989,326,43,545,160,95,638,279,361,44,376,430,7,381,815,226,898,61,929,396,126,547,357,566,564,41,223,716,765,300,453,255,670,341,663,513,874,840,566,758,378,51,600,245,686,906,545,701,64,529,141,530,391,54,393,678,366,235,169,120,358,699,112,461,763,79,450,659,362,254,79,739,586,894,72,31,880,2,528,777,702,732,133,814,833,394,335,658,963,791,383,98,789,226,366,341,98,590,779,678,187,733,500,310,561,45,831,390,993,693,145,790,527,831,71,202,173,708,132,437,694,417,480,229,4,454,208,910,958,611,685,829,805,287,848,334,372,819,458,649,678,25,751,518,586,884,543,646,810,606,194,729,352,65,807,504,457,806,704,704,558,607,324,450,863,956,172,984,280,840,80,240,924,220,909,922,688,542,833,97,161,110,795,298,708,912,133,304,630,230,699,298,650,812,93,332,316,716,786,770,625,205,299,494,38,740,713,494,487,647,255,269,877,205,159,811,509,320,496,688,866,730,601,562,427,93,692,259,207,673,977,252,132,492,373,862,56,986,987,357,830,552,498,823,607,796,491,414,929,194,815,302,529,112,810,266,838,459,294,737,849,124,776,484,304,348,994,510,774,94,259,871,991,671,553,730,848,813,368,519,571,837,395,719,174,667,74,132,79,573,851,339,272,630,878,169,732,227,797,631,336,753,370,419,476,71,979,641,658,992,199,171,0,598,862,731,485,429,131,745,216,928,407,15,219,720,96,281,265,627,513,854,973,826,309,65,276,558,472,211,131,129,330,60,883,796,606,314,614,49,488,39,284,640,921,366,116,379,800,631,407,292,335,100,320,187,549,641,891,379,562,186,86,37,674,462,3,30,553,128,621,528,908,655,977,837,968,21,793,583,282,207,289,968,516,509,207,459,1,609,94,627,593,432,126,439,362,114,534,590,419,536,820,511,824,773,307,984,807,381,186,426,877,403,626,791,825,629,425,457,993,69,498,907,451,826,193,831,699,782,127,416,990,283,815,740,248,778,454,949,647,303,442,736,781,563,226,879,441,771,832,491,434,442,391,167,122,680,387,891,772,125,490,503,320,924,433,736,351,740,184,52,454,217,160,914,164,24,121,351,12,625,149,312,21,227,75,494,834,682,477,397,672,17,125,821,169,531,293,881,371,982,857,818,182,749,477,634,161,57,122,274,619,385,946,957,200,501,856,23,749,711,206,155,875,992,897,375,552,647,334,631,817,489,216,531,492,176,551,52,879,863,206,369,747,428,721,616,521,542,11,831,334,437,12,849,678,763,54,678,158,76,927,166,388,275,156,253,553,960,916,940,893,250,45,691,929,116,495,155,762,293,353,884,120,188,606,169,264,514,595,602,455,789,452,814,348,428,59,523,82,313,288,6,570,532,137,523,179,369,46,756,864,37,411,783,891,999,4,211,304,190,961,160,819,277,30,331,789,78,454,985,758,964,890,882,369,798,974,274,518,369,688,404,213,554,532,184,524,376,653,993,802,772,218,346,257,603,829,742,334,904,371,554,745,210,327,242,158,664,754,223,14,180,312,807,950,651,338,419,322,841,789,484,178,482,89,35,632,379,432,656,351,470,855,773,966,446,813,760,74,850,178,915,783,407,548,560,157,425,171,226,807,984,860,516,18,535,854,230,631,878,114,956,940,282,591,192,331,385,412,126,424,562,994,744,477,239,329,762,190,895,334,150,244,729,767,683,966,712,78,500,883,148,198,396,344,144,698,583,943,349,243,740,522,994,310,351,490,71,264,49,713,917,673,770,381,708,440,492,111,724,980,453,820,460,859,293,933,427,678,658,275,864,688,312,225,639,524,689,304,862,251,837,154,253,746,574,686,785,202,615,440,905,626,927,9,418,346,531,402,71,192,103,924,505,330,146,613,594,393,51,622,133,53,689,114,307,195,580,76,854,820,389,573,112,205,655,753,717,966,328,383,734,952,80,30,4,247,477,520,607,495,504,746,646,153,404,444,126,750,134,864,30,449,281,99,898,79,835,908,627,82,488,843,757,937,798,666,708,856,950,591,873,127", +"516,550,892,656,453,129,151,704,845,796,864,686,167,53,567,460,20,191,879,635,61,97,430,412,684,562,841,322,912,916,862,341,950,105,810,928,930,425,291,108,969,303,490,283,276,108,906,30,112,14,983,529,565,18,300,572,398,716,14,198,575,145,830,601,910,38,951,147,305,886,264,5,763,824,106,752,551,555,232,121,729,899,89,280,370,455,457,357,81,327,517,417,301,474,138,643,69,603,149,151,165,751,407,970,923,166,5,615,572,366,363,700,403,347,97,262,120,80,716,821,194,229,163,649,998,344,463,716,480,795,753,349,974,644,855,54,616,613,467,44,227,935,495,707,547,1000,222,159,799,720,845,392,186,693,6,475,463,82,950,462,898,755,384,419,569,865,705,502,344,44,349,642,304,205,410,715,388,953,462,147,234,812,75,931,447,55,360,743,55,708,840,352,951,123,267,157,570,50,895,271,968,183,239,417,159,817,767,897,631,293,212,372,49,661,207,730,318,746,879,132,650,734,610,653,84,33,215,859,41,880,889,783,796,385,218,747,594,484,888,932,28,852,551,461,896,251,167,536,525,719,418,560,143,371,356,185,405,988,367,319,847,110,777,938,745,335,607,184,991,404,218,243,505,845,941,76,817,355,166,308,552,942,422,729,306,427,898,70,614,104,226,875,376,65,104,949,753,167,698,917,41,852,306,37,158,265,198,830,798,581,804,112,527,724,219,949,65,642,140,99,82,603,199,996,85,239,579,653,157,721,997,312,759,558,869,556,747,92,114,612,809,577,484,537,895,87,31,789,801,825,598,293,559,595,939,14,117,368,829,497,377,296,244,136,895,519,268,631,44,852,363,751,417,92,582,245,132,402,617,253,108,760,49,921,642,263,671,501,40,187,366,743,730,627,576,62,658,323,610,967,888,260,594,957,330,405,653,598,0,154,543,493,439,173,32,159,173,536,445,517,764,951,463,258,822,80,623,566,235,217,767,202,761,172,893,685,503,316,4,38,609,662,116,531,474,389,51,350,352,951,400,436,308,473,279,648,199,989,226,303,251,353,887,169,77,488,374,949,1000,739,636,170,739,476,478,540,556,820,67,709,289,434,968,11,773,454,105,966,432,386,857,277,212,414,28,109,273,872,564,894,950,528,852,457,185,165,764,112,839,473,502,99,118,848,349,50,864,536,309,848,153,731,535,125,514,756,969,977,419,893,924,986,282,120,363,202,272,907,879,265,589,399,199,243,950,990,62,298,1000,412,228,904,950,558,137,454,969,792,678,741,505,125,59,644,154,355,96,365,925,799,887,682,702,646,176,173,907,830,696,997,393,542,149,115,438,415,157,748,438,251,616,417,642,460,135,927,822,397,806,89,477,175,311,973,168,142,654,920,924,833,372,347,967,319,258,765,532,259,12,390,364,958,917,224,333,642,814,234,56,988,864,409,822,666,744,333,890,780,542,515,978,573,670,354,386,887,523,77,917,105,712,29,949,725,174,563,253,105,779,309,11,707,515,82,805,526,243,910,37,353,797,751,167,159,149,285,838,982,915,608,518,358,728,238,641,210,850,678,648,485,859,920,231,533,201,438,273,240,590,669,146,86,478,157,959,855,175,422,280,162,551,489,818,321,526,294,200,105,867,980,919,86,888,622,931,949,760,298,124,664,770,524,329,432,776,487,773,571,416,230,557,884,278,144,257,137,95,320,749,991,871,442,770,428,437,790,956,114,246,143,976,670,621,102,211,472,788,249,823,304,241,43,868,996,651,506,207,67,204,87,543,15,194,156,438,622,284,369,408,941,963,740,907,179,706,591,105,331,966,873,3,362,247,862,255,677,308,787,997,341,820,232,830,214,322,977,635,926,572,592,509,777,853,589,81,53,152,257,841,374,113,186,958,879,100,843,758,351,438,163,809,24,193,213,628,441,879,507,593,875,386,278,966,48,422,597,822,442,272,437,391,824,238,454,811,198,200,237,821,765,696,951,946,14,175,857,263,346,981,678,286,532,982,600,571,475,745,767,91,897,24,478,716,801,688,730,606,475,421,34,681,818,445,732,785,652,133,582,948,257,540,235,820,509,973,519,177,774,197,240,233,396,114,449,129,145,670,390,526,985,695,3,472,404,437,978,712,280,253,914,181,98,608,592,659,584,60,126,255,700,584,59,917,719,494,858,688,239,793,413,579,492,393,315,34,981,637,793,316,67,820,970,237,977,67,880,240,295,70,526,949,437,930,96,425,313,557,440,439,422,365,764,155,341,279,85,536,32,51,477", +"247,902,617,867,164,186,240,419,84,112,437,651,486,455,438,52,481,113,893,852,969,880,155,330,982,769,199,601,84,916,349,715,924,844,240,451,62,946,819,639,863,552,508,945,414,560,173,839,815,59,431,93,456,386,954,116,943,645,982,15,687,71,409,256,915,702,619,932,833,987,492,10,597,862,609,2,613,44,54,219,47,696,634,646,1000,328,350,291,921,745,428,147,894,698,576,779,334,322,598,214,296,141,876,989,30,589,793,546,522,659,609,755,318,628,238,762,253,32,410,292,14,201,820,172,959,160,175,145,983,156,910,923,211,470,778,934,959,55,381,816,157,304,530,256,712,99,141,619,816,111,548,159,380,607,796,895,978,385,71,379,979,816,410,14,436,287,261,695,221,60,371,601,853,921,703,777,398,565,34,189,633,552,634,845,594,637,434,377,580,874,605,38,967,854,613,324,135,704,627,430,92,54,744,300,873,901,902,215,688,247,155,705,551,631,295,530,443,753,536,520,538,682,404,931,111,276,498,124,372,897,611,180,619,204,419,239,680,666,473,744,998,578,613,713,590,739,875,374,653,999,264,433,867,963,544,876,241,39,342,594,828,543,631,198,519,592,326,968,69,825,490,609,501,601,991,824,837,454,458,318,151,221,550,987,558,409,499,48,323,149,814,543,265,90,746,909,626,936,22,12,960,897,4,502,800,483,104,96,513,449,594,701,395,27,532,745,805,986,334,341,213,866,131,941,546,719,293,41,32,485,19,487,769,239,633,888,294,667,986,416,672,178,653,863,900,608,271,500,793,111,517,306,613,181,589,985,712,921,938,130,421,42,890,335,480,577,452,844,822,677,291,787,999,168,960,705,435,185,843,341,224,225,730,41,473,294,657,433,133,732,562,397,867,662,617,45,670,352,925,19,299,76,614,358,570,424,234,862,154,0,722,465,357,853,853,191,145,519,32,295,726,459,205,454,8,122,650,796,574,837,849,967,696,558,136,336,76,477,773,878,284,397,6,984,881,116,66,202,920,971,786,956,210,904,631,536,681,8,194,161,725,298,354,11,980,280,936,275,851,707,790,844,878,246,384,944,939,160,559,642,679,579,802,560,241,611,526,448,786,636,47,31,20,95,747,816,253,368,811,722,986,303,938,101,294,627,95,511,240,784,507,63,930,262,756,90,39,435,281,984,72,399,769,83,934,825,81,397,685,481,864,612,474,726,80,186,54,336,136,181,124,85,194,472,318,664,243,136,42,850,842,838,328,941,635,297,680,534,806,198,110,612,606,179,10,815,686,667,834,907,480,794,240,262,266,269,34,194,123,98,413,935,187,992,262,837,552,939,687,396,292,491,427,591,522,495,714,312,270,85,111,837,182,941,136,568,377,542,85,364,868,697,251,783,840,287,385,175,850,797,962,681,586,591,314,879,585,467,360,433,523,321,75,280,590,282,500,108,708,322,258,667,586,524,590,477,339,305,316,290,495,44,918,959,279,222,275,448,581,545,698,276,176,859,845,991,664,708,556,790,199,482,151,338,543,465,955,640,541,24,599,693,524,75,245,387,46,489,728,167,777,301,435,370,544,734,829,557,643,633,936,511,859,155,296,350,54,881,4,613,6,463,56,293,332,493,648,321,337,100,503,85,184,64,193,542,648,886,480,505,441,903,552,958,287,820,32,980,856,693,156,27,299,993,461,761,787,739,751,623,39,206,550,389,652,351,827,686,163,723,272,94,335,861,192,488,331,598,19,675,148,489,766,904,509,100,264,29,114,592,217,394,254,141,976,470,525,739,153,443,605,992,135,647,578,559,206,806,830,165,275,537,568,78,731,74,627,125,236,761,430,791,558,66,681,157,246,106,117,441,701,32,261,272,668,156,626,770,425,873,155,866,214,796,515,294,19,805,179,896,669,961,400,939,780,888,925,141,40,392,367,238,631,329,951,519,654,407,238,282,263,399,272,2,263,329,151,464,197,3,372,293,809,602,904,147,922,512,870,209,708,14,189,227,369,101,530,771,336,47,735,55,624,819,339,133,488,515,421,800,727,976,602,51,454,583,70,296,382,182,14,410,70,852,919,204,913,198,817,10,861,531,793,45,49,393,684,220,492,164,217,106,396,473,294,964,97,224,741,21,335,915,623,313,582,652,658,703,717,151,261,4,782,632,211,791,534,560,565,456,291,106,826,552,292,14,461,761,435,328,135,485,906,997,759,435,154,742,808,748,667,248,601,84,435,851,170,682,959,834,777,613,904,303,58,679,877,890,413,132", +"668,261,622,583,931,275,772,589,235,742,954,383,40,505,268,500,303,208,101,137,992,129,826,525,673,886,677,550,286,343,328,927,763,959,944,630,963,432,892,944,979,215,607,285,873,317,208,512,101,549,911,900,92,559,709,665,116,96,566,382,404,698,376,811,163,895,973,621,59,497,690,892,408,727,895,447,48,965,411,207,351,39,210,502,998,149,178,130,743,710,588,520,642,851,883,728,218,970,108,879,968,226,740,875,277,431,517,509,906,508,558,358,460,139,324,405,760,209,273,226,905,7,291,240,281,646,203,467,51,877,100,405,782,741,311,762,34,146,874,847,652,245,705,980,414,661,688,394,736,823,256,267,777,355,505,17,482,152,657,518,991,753,631,416,915,295,732,29,179,903,568,115,432,94,194,900,310,228,695,43,275,383,263,192,143,263,375,957,575,777,271,359,99,198,654,947,261,36,204,499,288,318,336,577,882,68,263,954,597,524,415,489,629,491,432,574,520,471,882,302,432,82,702,439,400,358,109,335,361,828,865,833,858,788,648,205,984,866,814,133,970,204,952,949,878,352,37,44,627,670,133,958,787,648,390,475,200,416,767,893,286,177,809,477,964,435,941,328,232,103,427,234,683,272,807,279,169,209,172,315,698,990,210,494,177,168,97,517,266,298,110,28,501,764,764,104,755,214,465,805,716,173,873,292,733,114,320,804,849,451,309,352,151,635,131,94,269,701,825,534,236,424,597,184,702,528,113,869,633,438,324,155,297,671,563,85,248,237,728,724,887,215,497,889,793,671,522,946,40,547,256,177,442,713,242,872,895,404,714,723,205,91,940,322,561,524,234,715,856,236,86,726,71,171,291,9,582,25,59,164,142,463,461,228,31,276,350,789,590,27,237,807,733,204,837,723,742,864,325,690,637,245,386,743,992,571,671,731,543,722,0,928,65,615,117,52,798,82,413,389,722,301,771,363,880,118,393,342,993,49,400,232,978,199,387,156,886,12,186,291,908,371,830,951,729,741,32,617,213,461,585,818,474,237,26,136,145,639,589,420,363,94,527,629,879,894,326,646,642,491,112,599,733,108,58,86,919,215,410,788,306,942,461,494,867,90,680,770,197,420,258,799,61,840,982,942,432,689,430,373,918,704,898,357,425,376,67,788,365,501,359,95,382,196,175,439,802,249,477,78,621,921,635,216,372,465,113,884,400,889,123,858,51,512,278,920,832,2,538,786,143,634,460,900,97,606,608,551,909,624,238,853,637,116,824,619,785,711,256,946,758,706,774,487,190,638,299,692,625,384,261,946,155,927,1000,280,760,723,645,593,593,33,496,468,934,993,231,805,77,71,317,360,626,857,372,362,248,236,749,589,21,767,354,7,523,317,47,112,878,485,321,875,26,153,624,194,63,689,10,538,53,514,110,416,618,560,426,415,973,749,970,173,858,433,349,17,308,809,294,753,356,449,514,207,561,558,17,971,822,28,607,40,651,942,414,76,814,309,458,721,817,471,287,283,661,285,850,686,943,511,193,424,354,215,165,600,296,857,506,531,928,985,783,606,904,154,599,542,488,805,327,796,996,421,354,898,650,756,878,767,307,620,795,302,79,54,227,580,794,513,878,809,692,287,991,36,456,62,442,460,999,152,667,126,626,648,839,871,966,835,116,848,712,535,526,11,728,709,601,132,430,604,275,95,422,404,383,976,587,710,799,750,310,874,652,798,51,477,987,909,679,617,219,124,781,892,52,230,710,403,160,308,240,691,476,733,525,276,367,708,4,686,364,228,289,148,40,438,895,269,274,418,807,455,106,816,39,861,709,537,343,681,508,557,407,162,650,950,334,163,442,866,36,522,539,445,66,127,22,239,125,802,52,406,418,715,656,211,583,136,178,225,47,678,602,485,162,745,72,497,195,859,818,143,741,118,806,798,817,988,893,470,223,616,778,552,527,427,692,632,263,623,606,699,911,590,177,607,272,696,77,473,337,51,463,995,22,530,698,70,18,462,590,757,791,555,796,159,125,653,257,232,689,4,790,906,559,470,623,563,963,226,838,514,510,39,754,222,963,999,472,819,711,348,143,355,770,616,434,298,508,879,664,744,577,965,303,5,538,149,406,552,29,361,168,846,716,882,243,110,358,323,402,868,214,665,999,534,104,91,678,44,541,178,409,752,563,351,189,688,410,802,653,907,399,310,604,707,936,785,569,947,479,334,134,804,737,489,465,312,985,681,348,380,29,940,838,505,668,181,131,849,985,873,80,371,457,283,536,386", +"751,326,39,57,35,164,682,351,645,398,164,400,974,933,946,895,625,488,434,352,315,543,594,137,78,953,882,81,33,118,550,767,283,106,232,483,558,169,797,833,315,991,254,472,389,917,782,806,837,942,522,601,112,861,213,216,103,693,196,543,277,966,681,567,896,748,205,596,620,993,525,351,99,373,119,452,161,665,234,635,842,9,698,982,597,596,663,11,636,152,770,556,328,19,520,881,157,653,827,546,102,672,626,119,363,545,698,469,274,110,919,735,680,92,920,979,860,57,84,925,932,305,360,569,610,402,816,406,840,675,810,808,135,362,181,368,912,415,632,732,898,951,495,631,96,960,80,17,767,113,388,110,868,772,724,398,977,503,552,656,996,343,943,946,371,800,438,624,528,103,590,945,373,867,409,829,728,810,87,666,8,501,854,792,219,331,578,412,327,218,841,812,548,860,21,2,452,300,239,771,487,624,212,433,847,437,979,635,35,553,487,799,409,105,868,295,43,190,616,936,937,593,227,542,465,229,713,811,968,190,626,458,868,594,245,696,133,343,508,410,43,105,539,183,407,949,428,780,500,450,289,304,771,986,699,880,230,981,280,610,548,669,248,436,8,227,553,934,499,746,282,777,857,847,412,427,556,362,823,102,338,672,447,858,335,269,306,309,697,964,713,632,445,928,830,79,246,912,419,201,942,423,54,915,802,576,668,87,674,71,696,300,680,342,802,622,381,569,999,838,213,118,615,131,505,791,23,96,152,21,738,27,31,439,781,133,866,749,349,762,512,597,388,123,349,313,856,892,218,395,22,881,618,964,130,584,549,8,618,149,27,799,76,257,178,388,983,723,946,11,883,237,285,246,827,217,774,858,693,374,871,320,117,486,572,685,617,222,546,719,873,865,977,835,575,163,478,569,222,779,877,122,651,474,356,9,931,485,493,465,928,0,917,662,304,900,677,307,183,742,570,952,284,63,7,885,830,474,550,768,662,802,451,505,865,853,961,210,242,775,831,820,366,762,952,445,600,152,551,365,239,385,302,431,456,604,222,543,273,222,236,80,75,672,177,591,484,913,633,715,659,804,950,194,889,318,523,543,842,276,424,882,41,256,765,703,146,801,627,993,883,132,554,460,318,346,524,723,479,90,431,831,892,851,993,392,937,631,314,571,471,173,403,584,322,41,388,132,543,180,547,825,12,999,622,270,786,693,192,49,889,234,120,741,51,997,86,522,390,444,73,717,740,704,992,616,981,217,240,160,106,877,691,153,424,323,371,392,544,696,319,141,723,670,464,87,673,256,972,997,346,159,630,688,486,90,765,95,222,277,724,732,959,362,630,468,246,61,775,959,743,404,43,242,882,215,731,741,469,591,805,52,160,828,266,310,656,497,128,997,619,248,655,402,454,73,928,798,338,274,917,334,173,320,281,360,160,905,360,382,279,739,813,553,809,284,508,833,374,507,24,458,145,980,466,481,95,63,807,403,427,928,220,573,512,448,810,478,949,137,313,71,788,226,170,110,232,227,868,693,347,28,724,308,144,39,9,994,882,504,718,462,781,781,876,858,35,583,869,897,794,371,128,161,259,167,76,335,973,239,717,442,710,517,302,894,980,267,261,383,912,446,725,131,438,222,251,547,368,452,932,116,465,203,178,892,124,930,244,531,799,464,989,577,467,721,744,988,717,309,145,65,829,466,135,271,217,457,950,893,360,473,332,838,512,557,331,743,676,24,667,475,505,637,665,486,791,372,820,203,214,718,922,708,141,817,124,220,468,63,117,760,762,740,891,455,104,395,41,828,752,866,211,125,790,694,602,445,347,729,676,114,342,640,593,132,326,560,415,218,739,705,357,574,680,565,192,103,816,610,651,331,893,378,842,839,766,758,151,815,722,220,907,602,458,65,501,98,145,362,391,534,224,807,641,672,989,469,933,951,755,593,965,236,473,268,650,999,790,462,313,516,59,841,933,886,758,271,704,508,106,429,843,264,525,322,408,69,190,287,852,879,81,250,988,888,823,265,546,64,426,840,915,105,119,461,75,595,898,246,399,458,191,963,706,996,729,69,621,106,638,868,580,484,533,608,714,186,136,538,134,594,571,647,205,722,602,804,362,677,612,472,636,879,806,847,73,911,688,259,212,485,520,832,340,404,322,169,63,13,283,968,931,934,596,303,265,859,428,913,987,52,846,204,927,12,640,260,677,448,176,485,822,525,295,538,340,135,334,471,536,798,506,460,664,120,263,794,426,325,254,391,418,939,638,308,885,734,781,648", +"195,272,447,407,304,28,688,5,375,55,398,185,795,643,672,602,132,579,46,812,455,842,125,51,211,798,262,474,726,692,841,217,930,258,517,387,790,782,304,101,701,562,260,95,500,453,801,845,15,110,208,413,757,532,727,186,962,413,697,125,693,271,991,679,710,758,434,641,432,727,702,356,535,874,608,904,325,439,630,829,145,875,665,225,78,821,105,900,116,987,650,547,424,76,120,3,835,334,186,49,192,688,333,835,787,794,471,620,78,98,881,69,872,411,987,678,358,49,888,256,856,674,334,592,348,144,701,927,628,777,584,660,367,731,912,619,406,617,87,549,797,546,20,186,32,782,76,303,34,676,106,46,960,560,313,425,88,862,117,591,809,644,92,1,467,333,510,540,766,422,375,701,192,113,282,849,741,805,597,425,793,182,493,479,270,966,490,152,135,649,646,235,523,897,547,506,734,234,18,467,660,14,368,552,651,805,917,516,492,860,169,911,471,338,346,384,499,505,173,713,957,124,701,125,202,195,705,436,94,392,411,679,347,476,376,972,101,65,763,506,10,333,957,216,58,69,84,577,548,884,596,602,523,150,325,676,425,188,525,457,979,529,903,186,281,259,563,434,762,450,671,738,334,719,914,866,889,11,51,329,47,239,814,46,329,961,604,978,100,956,857,827,696,635,852,128,542,410,374,991,954,482,114,696,917,764,726,74,402,220,620,551,50,797,3,577,665,975,865,238,396,786,764,637,696,752,799,522,4,664,32,364,394,80,64,730,69,741,992,833,78,221,314,969,595,815,126,307,987,229,398,939,839,578,808,131,975,179,115,102,188,436,903,406,129,372,242,689,329,109,674,504,917,681,33,382,727,322,176,650,111,108,728,78,432,928,243,403,459,99,26,830,958,142,926,570,254,929,135,807,904,772,881,913,125,128,399,429,439,357,65,917,0,825,139,994,370,739,3,19,742,140,346,559,919,698,949,891,186,737,722,189,472,724,903,130,469,787,593,529,86,523,334,715,181,436,349,916,220,751,784,196,834,86,953,991,161,482,585,647,157,959,104,473,222,946,41,230,457,472,637,429,874,814,782,44,702,455,457,761,466,35,382,597,839,308,276,454,712,376,748,959,620,715,136,780,607,689,461,154,473,343,385,481,885,49,773,529,541,784,674,316,705,319,38,489,841,429,662,185,237,650,723,641,62,42,429,880,359,338,604,595,6,321,198,624,577,889,15,641,612,107,855,749,941,518,176,391,4,740,291,928,675,941,962,672,252,98,208,53,427,724,749,427,948,441,531,667,870,94,191,838,681,878,644,787,784,346,646,593,107,545,14,382,930,496,10,973,188,633,83,340,573,104,216,861,375,470,578,136,357,776,272,439,860,160,368,442,369,833,308,261,930,564,22,455,755,11,108,652,827,930,941,42,111,910,842,440,185,312,632,556,37,756,974,691,950,428,745,901,66,451,222,953,242,856,917,618,182,245,890,585,718,291,733,895,318,459,298,705,920,374,85,992,951,330,897,152,117,645,521,124,386,677,583,948,745,453,495,119,443,211,34,631,723,765,790,212,789,552,490,691,677,332,570,243,21,699,581,355,529,110,51,386,235,330,906,920,8,695,478,746,206,784,920,955,337,677,77,214,707,55,947,754,994,647,505,677,375,52,94,850,359,330,415,236,660,403,111,343,496,681,419,117,592,81,945,861,767,32,73,367,122,381,687,1000,506,767,970,343,733,751,697,376,826,539,55,37,465,30,982,483,339,413,745,421,768,664,136,163,322,687,674,993,910,470,624,333,612,384,487,410,27,308,775,611,54,710,676,541,857,328,637,408,384,546,889,73,216,550,285,26,71,777,111,808,454,170,523,749,279,580,618,443,594,342,939,68,778,463,174,329,582,105,589,816,448,303,997,961,995,171,739,239,207,847,765,261,773,115,730,635,950,992,190,176,636,152,830,770,909,445,264,119,722,469,472,61,396,597,781,308,43,7,692,819,63,768,462,194,3,457,376,198,49,576,427,113,237,441,641,754,549,782,182,49,460,561,526,758,488,307,606,280,227,627,953,567,916,192,616,98,729,614,150,861,955,835,988,545,724,961,976,960,743,429,470,529,164,825,43,764,823,780,911,316,920,171,506,201,795,384,995,926,764,208,345,483,856,518,595,493,745,813,428,816,618,40,49,771,525,500,451,55,911,926,235,773,121,120,301,107,993,372,591,859,89,750,505,210,164,118,614,774,505,328,207,102,197,185,451,918,991,197,780,286,830,586,398,404", +"678,780,898,584,724,379,692,560,135,211,629,859,968,159,968,94,704,420,695,100,260,911,477,459,747,464,530,310,102,965,860,566,39,184,351,285,299,678,444,916,351,775,930,749,227,305,563,375,52,880,389,611,642,891,824,901,970,167,749,994,924,212,582,58,7,719,194,171,126,813,528,89,379,942,806,388,205,355,937,522,369,638,897,54,209,842,973,237,781,854,88,898,889,96,582,101,111,950,557,60,521,790,805,733,751,248,327,441,911,800,860,125,504,193,20,246,393,474,1,51,997,765,778,968,272,950,398,889,956,649,987,21,637,498,733,715,511,949,950,562,217,434,224,116,587,1000,760,337,256,955,279,662,614,508,123,863,333,68,895,905,524,581,397,446,579,911,233,768,347,212,713,494,241,491,950,117,660,636,440,88,519,460,956,891,562,860,589,693,94,231,259,326,753,79,97,127,902,237,13,818,413,392,121,84,853,5,596,540,553,453,668,234,727,966,645,274,265,244,44,552,547,421,779,723,740,100,73,519,226,269,579,35,597,861,13,337,260,164,568,842,158,378,452,180,371,187,620,480,884,519,703,527,625,762,73,81,376,782,980,808,491,541,158,250,86,256,573,242,739,896,159,800,884,622,532,827,235,603,627,558,711,937,779,537,498,876,652,158,472,976,546,269,676,751,552,327,964,123,410,843,784,432,117,482,361,140,204,990,384,915,768,976,374,562,810,835,612,489,791,200,809,361,831,958,103,903,473,402,928,359,444,389,804,352,32,86,15,745,112,188,454,728,60,787,412,712,251,36,62,81,716,321,919,393,218,619,58,491,227,56,919,440,138,44,157,59,949,774,163,914,182,115,439,596,401,795,695,355,973,510,332,590,818,673,474,670,910,471,405,221,814,649,524,140,273,869,202,188,472,126,663,940,156,296,866,198,665,131,173,853,615,662,825,0,241,803,64,363,199,60,650,868,480,70,207,37,348,690,595,601,276,864,267,616,458,555,9,16,401,910,275,585,744,265,593,672,404,653,183,426,89,727,500,814,468,397,243,576,87,938,509,794,486,958,251,497,2,668,69,137,323,807,178,847,887,402,632,289,58,789,794,70,265,268,705,190,735,446,769,573,395,807,749,957,559,780,906,458,811,313,203,524,938,235,600,205,371,648,209,700,291,374,196,901,741,122,795,858,499,709,224,853,142,976,477,506,20,188,463,138,405,597,763,641,294,923,869,560,137,698,681,99,39,884,813,680,824,269,766,624,270,723,118,608,859,156,311,423,887,877,587,927,395,255,35,613,679,445,443,958,362,181,606,855,252,956,236,860,150,790,225,210,862,171,709,976,462,688,31,786,525,541,616,973,632,899,89,190,593,138,457,359,261,724,391,428,89,563,505,221,598,27,385,398,494,688,505,118,702,879,231,996,388,752,913,740,209,190,877,779,899,888,860,478,250,554,185,144,174,491,330,925,656,165,395,273,901,749,402,658,363,96,621,343,646,252,671,719,315,920,285,657,578,478,824,977,531,95,421,323,924,632,953,170,836,172,272,741,896,342,720,632,729,260,345,677,529,568,462,46,690,836,95,961,724,462,653,717,79,508,806,932,464,922,647,457,424,868,707,48,967,474,579,737,601,112,346,533,720,393,703,249,527,311,743,338,200,459,434,980,506,786,380,492,373,409,775,186,624,256,841,266,691,12,77,538,929,931,194,146,492,525,811,128,359,667,256,895,621,718,548,537,522,521,198,828,196,59,873,216,602,807,83,349,10,657,121,189,291,883,427,137,918,877,292,700,596,342,377,460,598,421,223,837,243,800,57,628,565,620,716,257,332,511,668,437,555,353,60,714,861,552,111,231,782,448,274,19,117,215,953,173,322,157,85,598,377,188,654,856,465,576,453,755,450,244,150,888,879,113,161,206,297,264,365,318,924,13,593,990,921,245,597,461,71,517,148,481,347,180,64,723,506,966,373,585,205,98,655,333,75,191,915,103,353,590,652,888,657,43,99,198,106,968,101,558,669,244,167,894,387,979,119,716,24,457,662,163,368,174,119,133,692,73,930,536,289,559,224,434,376,867,756,945,673,340,361,436,221,721,509,972,239,118,896,744,874,313,37,76,485,875,223,336,926,117,34,886,328,946,819,306,637,943,724,93,220,865,143,493,450,561,863,251,967,601,480,955,146,274,92,405,705,781,586,332,349,42,171,761,682,755,950,476,593,253,433,772,960,1000,964,705,884,384,453,804,738,926,954,520,687,974,413,561,128,999,528,779,859,585", +"848,568,759,442,451,136,676,146,284,326,624,801,514,360,366,252,669,545,471,153,997,886,457,631,396,492,412,345,919,501,618,750,847,763,754,280,654,383,433,326,296,991,169,97,746,148,173,303,955,558,912,203,533,565,434,911,553,19,857,166,187,638,347,404,651,769,131,302,445,581,217,70,454,23,869,915,585,144,778,5,304,424,56,124,972,231,878,929,19,214,29,830,970,977,772,961,196,564,347,459,421,298,771,65,903,529,618,554,966,832,157,44,790,186,172,570,340,392,816,536,677,791,890,955,534,899,728,641,845,98,885,185,167,966,515,981,592,58,74,323,732,848,812,759,164,892,50,931,414,870,295,571,342,90,913,578,446,971,488,623,643,596,570,100,370,920,339,162,629,605,197,467,219,185,96,636,397,540,609,600,85,321,348,286,337,475,558,494,893,301,482,122,983,54,555,89,987,716,567,457,647,189,103,211,230,532,651,19,572,666,271,411,502,576,204,174,282,474,811,463,797,749,484,91,393,151,489,801,816,778,795,21,84,683,718,216,216,173,111,179,350,525,990,726,306,111,444,733,867,161,30,671,672,102,999,920,960,230,421,520,301,782,671,73,617,599,188,177,251,863,743,751,610,539,479,970,647,282,349,793,264,521,532,282,21,521,835,277,776,501,588,756,634,618,726,558,240,338,312,328,591,557,766,996,260,837,187,100,897,544,433,868,233,641,769,563,351,387,123,998,771,20,985,793,605,56,979,554,90,315,234,810,856,629,711,433,661,77,828,284,685,399,664,36,566,924,314,578,288,320,245,304,153,976,329,620,904,632,893,981,850,975,550,964,722,964,425,827,861,109,302,417,255,648,338,975,569,235,184,766,741,685,905,643,260,56,863,706,735,481,782,893,662,685,175,114,924,368,126,8,503,796,241,690,360,124,408,745,32,853,117,304,139,241,0,495,316,761,389,297,22,454,851,316,241,594,645,579,716,8,922,398,919,444,545,356,682,27,952,525,185,278,901,822,818,266,148,297,509,485,272,197,681,703,335,163,153,869,107,725,859,972,282,329,702,527,88,196,423,34,613,537,46,683,288,147,560,755,607,966,653,403,786,792,456,511,315,933,114,589,309,697,80,402,903,360,754,991,184,993,793,541,968,180,200,12,756,539,427,630,420,836,739,757,60,909,86,129,864,36,220,764,598,658,202,796,951,938,837,862,718,163,387,32,742,709,498,48,282,979,394,707,440,755,496,777,139,516,859,358,161,773,897,212,588,145,741,28,597,261,636,340,110,896,590,382,170,121,199,13,757,729,841,363,375,776,66,342,800,182,219,753,122,803,575,590,951,124,36,103,968,162,497,644,691,786,890,741,292,364,840,201,402,991,659,695,89,371,959,604,369,360,907,192,568,357,787,320,451,87,628,446,735,944,409,751,371,650,766,266,655,50,745,397,441,881,901,975,907,535,627,66,777,330,638,595,575,414,726,533,35,676,439,713,557,312,975,839,48,740,148,146,104,94,92,286,81,316,582,173,745,850,402,282,614,811,670,710,7,68,23,101,915,267,140,455,850,419,265,195,182,61,99,660,446,539,71,718,500,553,633,375,170,85,989,83,697,197,379,524,502,582,806,948,647,441,479,167,244,722,388,603,336,7,15,636,80,748,776,161,826,224,708,664,68,169,83,797,442,674,804,492,637,575,192,504,651,518,411,673,396,485,467,80,696,955,661,143,320,664,360,806,816,950,739,498,197,555,63,845,898,718,520,947,266,91,870,423,976,595,819,656,533,251,68,169,87,533,975,823,162,428,631,788,922,726,785,14,333,616,850,82,722,797,274,854,189,244,659,236,182,127,902,40,12,283,57,215,833,772,272,465,935,301,542,172,573,724,112,278,608,210,5,459,233,963,553,884,194,883,356,405,254,845,141,765,734,846,297,658,478,246,714,784,331,408,277,936,157,871,440,467,265,865,100,183,268,827,53,14,386,557,302,869,439,102,952,12,241,990,725,622,461,483,726,233,40,24,514,664,770,550,843,986,897,735,587,579,359,522,342,592,425,104,116,879,190,863,441,60,882,466,181,814,992,474,19,373,976,384,667,6,856,896,152,605,337,148,746,352,311,204,740,913,771,951,455,312,625,301,158,509,128,942,857,675,936,765,950,607,365,400,291,249,394,833,148,292,538,467,65,190,213,595,414,524,965,786,127,74,420,857,720,2,45,60,622,269,797,121,530,67,231,392,399,958,978,151,477,618,904,715,735,517,926,595,872,242,606,177", +"764,295,749,766,305,194,177,226,242,388,388,740,310,731,739,165,805,219,700,431,245,498,844,72,835,840,428,120,910,533,330,46,898,869,450,76,955,177,699,754,446,722,462,423,74,917,254,197,935,165,341,158,139,879,431,256,446,804,669,95,725,544,422,981,870,248,228,879,979,920,263,932,93,239,271,776,846,113,772,851,915,24,678,429,833,494,702,465,905,200,491,370,95,222,106,90,103,84,322,573,666,426,776,52,39,101,274,540,578,858,366,766,277,796,100,371,593,12,627,637,37,42,716,481,918,627,754,230,510,460,88,805,743,594,313,238,567,43,52,775,625,172,362,641,705,1000,640,697,71,708,417,833,534,903,362,29,363,584,463,283,278,299,571,355,724,619,175,739,244,294,486,41,307,697,636,160,483,488,315,294,502,680,566,32,821,581,902,816,757,815,370,876,203,170,373,964,421,112,661,439,699,112,584,16,302,266,600,616,250,197,172,144,252,847,822,866,568,37,270,894,261,337,75,964,81,982,537,98,217,104,296,222,64,659,295,127,385,745,289,209,119,992,400,500,638,573,990,912,61,756,923,694,235,971,468,152,621,124,593,192,213,418,619,872,757,45,748,201,785,257,921,339,896,973,691,705,735,245,702,132,658,59,650,899,644,194,351,504,472,374,386,87,835,38,931,629,450,86,572,739,93,725,99,411,30,682,811,844,754,950,11,768,419,951,414,795,938,598,240,296,748,988,370,159,802,88,603,968,594,884,385,400,446,211,957,666,224,906,276,82,465,288,891,733,268,975,316,460,120,184,990,656,232,924,273,464,428,46,445,418,843,226,170,488,349,596,785,915,786,313,459,397,54,426,91,149,27,107,701,618,801,711,84,366,827,239,741,314,574,137,462,916,25,211,911,101,738,890,513,833,522,381,680,870,692,346,872,216,159,191,52,900,994,803,495,0,740,412,815,242,8,838,861,942,545,349,195,888,683,216,934,851,16,650,178,280,562,396,261,627,538,550,559,102,21,551,526,757,433,436,142,241,558,866,300,86,628,503,529,432,483,542,261,443,174,869,845,195,794,268,778,625,471,504,792,639,860,362,961,300,143,540,163,729,252,147,655,394,630,503,95,249,549,939,129,135,592,52,760,292,584,642,345,517,130,896,835,679,640,565,827,892,325,666,991,698,94,767,798,443,829,706,62,22,146,836,484,952,791,112,392,227,377,389,620,835,703,896,681,53,223,833,926,419,284,338,154,390,847,794,346,174,557,201,732,824,450,702,128,204,468,651,483,863,458,859,69,728,606,164,483,452,301,450,146,782,753,751,781,284,635,910,112,266,732,850,317,626,804,281,789,194,750,523,214,35,556,701,536,824,697,754,859,724,470,765,550,478,820,276,658,702,22,664,728,286,236,575,315,239,569,57,988,718,881,868,768,221,244,70,120,618,581,783,336,556,864,216,873,283,194,694,492,111,584,745,582,799,771,716,751,228,614,934,979,539,383,678,891,275,785,897,251,11,378,48,620,19,171,914,191,687,445,644,539,47,518,663,860,997,171,651,994,448,855,685,671,450,66,512,778,863,627,751,719,609,61,63,346,786,720,520,95,17,221,284,385,696,817,447,895,107,350,729,222,366,738,701,543,643,565,527,52,547,23,722,394,744,82,845,305,88,731,865,416,452,690,618,938,798,523,449,594,625,303,495,926,599,54,710,637,315,533,82,434,42,722,817,106,16,105,523,43,359,915,127,727,11,60,320,861,923,384,665,842,948,837,404,200,810,234,503,811,782,229,9,653,958,955,60,30,365,491,626,822,813,793,48,46,359,909,67,480,850,303,737,822,794,743,920,719,959,172,840,715,664,41,868,918,934,214,437,237,244,770,930,562,882,74,148,382,1,519,127,236,996,341,873,222,778,140,218,126,938,480,47,821,914,849,459,562,98,283,149,404,999,486,422,462,883,714,72,70,38,610,104,943,64,956,204,623,612,928,282,928,924,823,695,113,123,748,968,232,442,829,467,905,247,16,510,117,246,255,173,225,701,688,796,562,399,827,661,657,324,524,904,227,198,335,973,856,507,8,493,757,244,196,206,36,240,760,672,932,118,182,535,238,996,450,531,51,81,886,233,146,892,106,938,402,600,256,431,732,478,748,550,915,674,764,648,507,166,764,717,182,997,782,473,244,678,550,171,251,431,907,473,650,63,316,90,636,554,236,983,738,852,731,656,195,553,414,515,55,203,27,452,700,806,149,650,511,202,211,598,873,513,128,660,532,356", +"888,597,103,895,491,322,308,139,533,669,530,171,426,251,986,947,695,237,892,882,368,721,58,37,216,344,664,156,306,737,998,632,416,341,900,319,715,868,911,777,569,998,545,665,166,733,515,354,885,415,120,782,522,755,47,483,952,690,49,206,334,84,380,23,637,32,114,308,138,537,801,280,480,674,975,315,29,857,466,448,374,353,43,834,997,375,668,926,328,942,306,525,47,461,706,336,292,37,860,40,229,720,184,980,946,619,131,573,926,223,300,790,337,495,79,438,803,374,408,582,140,945,141,869,385,91,243,817,257,418,87,755,821,391,151,467,750,822,755,869,371,339,429,535,738,247,786,948,941,539,703,786,896,60,179,485,570,647,387,964,156,267,220,996,702,152,936,438,490,591,827,760,515,554,115,943,441,590,452,71,810,725,835,506,794,610,231,987,226,841,906,117,73,831,751,985,453,477,908,750,342,482,819,383,184,18,269,956,363,553,448,892,155,642,326,918,215,53,625,229,727,650,818,309,895,281,824,108,937,563,860,472,225,671,130,966,715,359,695,662,835,159,18,409,730,308,589,409,418,81,296,284,892,594,412,943,948,645,925,97,651,660,614,77,808,829,918,736,968,795,994,45,599,425,406,702,277,668,191,80,105,703,799,412,564,414,341,6,992,374,983,684,506,108,475,250,953,589,17,626,264,139,663,342,126,62,619,480,795,510,899,364,298,352,325,450,445,360,188,425,580,135,388,154,430,427,972,429,294,487,414,509,793,725,688,291,641,34,379,225,289,508,367,747,902,421,347,159,905,43,34,530,492,403,839,492,354,935,686,278,449,890,601,449,599,58,726,890,863,531,591,727,158,335,972,579,150,241,610,185,16,257,767,308,54,922,129,251,645,790,309,480,338,15,525,312,87,224,759,113,47,255,568,795,121,421,854,928,173,145,798,677,370,64,316,740,0,66,355,711,156,891,555,817,477,517,413,927,712,427,50,409,355,682,32,685,412,888,291,456,483,744,47,281,745,331,630,941,583,88,814,757,40,465,660,6,409,2,59,178,611,349,998,821,261,536,506,993,342,786,418,911,178,653,283,972,357,987,185,567,700,564,413,149,642,475,216,370,488,900,301,537,375,549,539,560,162,841,689,970,788,548,949,805,314,253,733,862,713,46,848,758,494,697,927,27,199,348,958,500,231,691,759,467,142,828,322,23,719,92,977,45,944,223,25,323,874,28,535,36,953,152,522,45,876,967,207,118,313,994,62,213,463,290,48,931,105,522,41,267,504,994,231,211,883,528,261,341,568,874,504,385,84,36,927,784,5,239,313,717,145,773,182,474,90,284,956,523,558,349,230,753,829,546,865,957,564,747,874,42,167,145,975,317,83,620,230,549,268,874,142,982,563,349,763,686,87,434,102,287,836,322,245,592,652,903,538,929,7,94,525,560,44,137,836,527,521,431,774,247,759,799,805,51,195,252,249,927,279,882,447,969,383,756,708,139,513,824,606,975,309,77,59,268,364,111,464,321,198,521,249,942,778,901,807,472,756,342,718,173,222,478,831,391,456,912,994,227,345,851,234,2,815,484,749,109,703,32,653,178,898,220,498,283,914,740,422,585,106,50,590,567,876,974,457,57,55,589,951,574,127,555,646,470,44,26,48,303,233,939,456,96,859,324,998,95,79,46,358,43,229,937,886,216,537,17,7,41,78,910,835,786,531,303,271,84,616,586,207,792,571,262,585,379,326,661,706,642,445,405,952,863,862,419,932,773,838,844,714,597,100,836,836,610,158,446,588,829,835,677,242,833,114,427,464,413,83,167,868,150,108,545,386,295,577,934,454,907,814,125,719,972,876,610,608,73,148,774,942,785,926,635,243,492,973,808,154,169,934,430,276,708,552,258,417,267,90,391,190,631,130,343,579,464,541,577,38,939,126,333,168,851,411,916,518,498,430,63,74,473,495,732,197,489,392,825,992,323,158,931,350,504,421,282,506,992,698,574,683,542,241,458,651,497,223,111,589,977,414,764,204,633,450,512,62,678,27,486,637,800,587,510,473,808,906,656,944,99,743,436,630,627,264,41,38,623,235,888,938,921,129,599,722,768,123,239,585,283,898,80,758,390,249,990,200,960,658,841,651,698,413,739,840,86,315,387,242,299,33,15,45,487,692,21,60,912,445,32,337,642,597,920,588,207,774,989,365,317,81,499,771,750,871,415,697,821,465,831,976,50,743,659,807,426,983,380,985,92,480,37,828,80,679,549,984,406,738,630,515,603", +"40,704,341,420,572,483,504,8,184,331,579,975,439,782,160,205,592,325,140,246,792,572,905,800,882,838,233,917,815,32,414,113,37,793,519,769,521,988,311,431,475,361,711,321,966,36,57,339,534,626,192,969,669,389,63,36,635,473,470,887,854,406,928,659,151,216,965,803,879,252,527,20,446,605,30,678,893,78,639,627,600,302,921,635,874,174,402,119,600,186,611,735,256,181,326,185,390,865,98,252,228,861,409,693,638,416,675,770,978,697,154,796,436,301,865,846,61,841,556,191,922,439,584,375,350,263,52,355,915,305,301,12,195,450,886,560,633,717,265,422,685,40,747,559,893,636,325,870,756,77,740,475,766,546,488,457,426,752,707,836,420,634,509,108,315,415,30,913,572,280,393,663,37,376,336,704,749,589,732,63,549,693,529,486,618,668,893,136,295,483,405,990,430,219,513,266,115,408,175,104,228,672,713,195,842,603,811,269,786,658,619,570,104,687,407,351,726,390,423,485,998,214,584,896,8,95,996,229,739,89,456,916,444,639,309,318,863,314,117,295,847,505,368,732,953,138,271,171,598,355,266,334,210,204,732,927,314,497,135,379,325,938,65,852,894,61,742,262,939,80,979,252,124,275,95,446,230,368,534,385,509,223,113,805,632,405,66,100,979,842,526,737,48,926,295,393,839,596,644,886,339,900,350,450,223,466,964,147,556,809,343,52,610,544,165,650,906,153,910,868,39,311,625,187,149,918,38,731,597,689,647,725,290,228,52,107,140,274,436,961,251,863,886,127,144,852,961,713,483,85,282,470,904,470,703,827,733,88,837,962,562,624,721,76,21,47,374,875,891,893,576,91,816,419,127,871,533,580,349,249,574,256,805,682,398,410,293,67,241,497,542,852,47,595,437,55,308,888,439,787,497,117,379,995,912,795,888,407,536,519,82,307,739,363,761,412,66,0,748,693,712,258,425,617,923,505,490,846,516,626,182,778,601,251,417,126,360,432,80,725,672,373,377,121,539,542,256,309,795,826,372,9,661,317,68,216,73,202,616,854,500,402,321,457,534,856,283,804,261,379,332,545,881,533,816,574,465,284,145,727,816,958,710,930,851,967,127,205,521,606,451,162,3,280,722,400,440,696,349,85,220,869,826,561,44,603,532,751,998,233,714,792,965,891,277,479,545,82,652,412,935,518,406,922,863,404,357,532,257,969,162,170,862,625,362,726,907,899,728,734,458,864,123,248,997,899,509,307,829,82,181,784,930,264,244,858,564,647,845,980,707,612,236,799,576,963,961,563,834,557,349,550,346,311,334,568,369,733,957,420,395,701,288,959,154,41,30,867,559,355,123,588,217,938,937,443,119,908,463,718,403,704,102,468,735,614,41,692,828,895,884,692,623,516,511,954,520,12,792,454,342,426,754,932,15,985,973,481,166,718,200,884,167,968,872,536,661,735,835,592,322,672,623,768,747,135,952,695,817,88,223,121,598,429,98,406,102,128,943,153,952,604,237,758,360,971,151,996,448,686,163,517,407,456,613,201,271,855,189,494,964,460,312,36,970,795,635,665,805,458,591,465,743,267,740,384,480,204,404,389,190,85,728,629,167,344,543,762,884,521,515,516,92,91,539,747,327,418,352,68,410,927,852,843,113,812,46,637,489,918,718,146,238,118,492,976,651,190,367,357,131,471,264,104,112,456,423,619,152,963,178,695,902,375,112,125,402,876,472,106,845,219,773,439,470,455,498,47,43,587,742,558,836,535,892,526,371,267,513,121,280,336,91,124,460,449,994,262,421,788,341,535,315,67,53,257,487,463,934,635,487,321,960,123,606,530,56,269,512,747,587,552,66,242,846,833,208,22,658,287,902,238,258,467,140,414,773,273,740,62,731,135,870,476,339,36,427,671,995,562,505,221,845,652,379,789,80,398,875,656,284,986,272,31,972,955,332,520,549,143,587,609,735,759,678,378,798,657,539,915,985,479,800,202,635,200,845,191,174,10,16,564,949,784,922,242,739,120,894,965,242,230,789,53,419,476,584,116,146,846,165,85,533,415,335,778,867,262,477,209,276,845,207,698,912,804,291,319,493,442,74,171,857,611,235,429,530,457,527,147,399,291,236,671,680,589,499,462,973,398,238,871,492,508,514,140,674,606,575,503,869,630,994,875,36,197,541,503,588,990,294,817,31,258,532,859,420,636,531,727,298,56,826,845,27,423,635,514,939,382,143,55,782,321,939,507,817,350,623,360,231,230,458,207,492,465,716,87,551,523", +"291,46,435,238,297,572,586,984,334,536,497,7,872,210,245,187,950,390,501,920,772,584,368,213,734,450,391,37,860,156,400,729,802,262,407,902,196,270,905,61,652,902,889,446,541,260,487,544,404,222,611,782,128,382,281,349,615,694,132,823,210,349,307,28,967,498,57,94,45,228,275,137,928,828,554,271,988,633,213,86,210,768,552,600,825,122,317,123,420,866,448,85,408,249,782,807,278,318,609,934,290,594,638,793,262,107,988,527,762,762,662,458,105,345,950,577,806,789,144,968,677,466,745,774,618,686,569,110,22,83,479,909,94,799,825,737,128,584,911,805,542,791,472,702,661,507,125,648,773,266,259,758,454,69,706,303,86,421,218,850,24,344,923,246,174,851,160,28,453,251,748,980,176,712,616,92,293,475,310,44,20,850,977,565,902,510,540,486,801,650,515,788,704,258,190,429,84,481,123,184,429,890,653,205,922,622,520,812,62,173,462,177,510,434,787,844,683,408,854,864,351,513,629,875,693,111,523,695,643,158,222,216,179,784,872,494,836,26,507,484,499,980,392,151,373,492,508,604,142,60,198,698,701,767,487,264,622,391,753,800,461,246,719,968,629,649,208,232,601,651,265,144,303,514,138,753,550,199,244,961,252,352,435,389,17,218,306,945,359,940,124,369,70,68,424,803,900,201,553,671,375,628,433,234,13,613,267,18,965,404,998,813,8,748,603,294,467,739,610,880,243,757,697,351,422,318,63,571,688,287,822,925,758,685,690,355,181,257,561,233,868,863,434,587,815,766,392,690,388,41,822,291,964,859,863,524,315,368,244,232,744,360,323,766,383,761,330,316,185,186,450,925,919,367,122,892,294,456,379,908,412,405,562,497,487,942,395,589,507,534,207,326,585,286,838,391,938,600,615,615,109,371,710,416,924,859,67,15,445,32,413,183,3,199,389,815,355,748,0,338,411,82,158,835,457,840,752,348,670,7,715,880,217,460,252,393,81,237,607,548,885,424,740,418,247,872,952,43,676,165,7,887,461,236,847,417,290,316,17,948,654,120,222,172,426,474,221,243,52,706,388,693,825,222,579,690,202,106,720,566,182,440,337,716,396,750,440,914,14,273,365,213,114,370,779,680,100,514,370,951,433,837,379,314,55,584,162,701,872,306,541,673,931,282,349,735,451,355,820,288,303,225,853,200,583,572,142,841,698,797,722,85,743,338,983,771,257,546,95,587,811,623,85,749,88,373,952,175,631,857,805,169,790,805,2,107,449,555,342,325,469,604,22,431,786,384,451,402,204,975,94,27,647,380,44,888,55,633,33,591,888,195,272,870,210,200,145,565,812,338,929,101,502,113,566,602,475,127,825,655,89,496,623,925,639,726,451,831,657,401,112,200,950,33,973,945,33,172,710,836,981,318,908,3,735,567,57,266,893,990,450,393,395,849,412,416,896,182,595,233,352,104,549,367,963,937,72,694,429,934,458,943,43,398,187,235,564,779,747,689,376,339,933,760,303,309,577,387,489,674,420,332,808,399,272,395,599,149,300,303,840,508,318,39,96,86,242,666,518,531,140,539,653,851,409,435,178,422,135,863,378,147,698,440,494,616,641,735,711,114,417,845,513,652,575,305,687,125,742,253,373,148,228,807,489,979,95,918,471,605,501,172,16,927,788,493,875,670,25,389,930,690,892,308,699,836,742,624,578,485,980,755,501,388,270,466,119,872,842,251,380,299,418,93,752,639,985,173,168,668,409,870,734,184,800,97,344,773,888,235,986,206,660,47,520,859,253,910,311,830,281,307,499,709,974,404,979,957,620,962,678,318,906,999,638,636,196,877,650,317,546,855,550,456,347,745,745,205,277,872,58,629,832,419,959,297,597,458,622,296,115,234,638,323,742,397,154,873,86,630,287,70,353,106,341,955,245,249,942,454,115,50,256,141,39,352,866,626,485,341,180,286,483,51,135,514,118,242,289,956,841,802,907,990,999,898,987,841,891,893,704,688,857,233,980,869,229,435,108,927,694,387,901,863,173,846,455,311,676,520,694,26,688,957,389,594,959,447,996,543,650,991,359,337,733,302,169,370,79,65,8,884,917,7,764,290,801,638,974,767,751,763,171,423,128,845,617,215,607,779,194,323,410,934,91,784,418,105,870,209,820,718,684,412,927,413,318,166,261,164,657,687,988,603,997,801,314,388,215,254,262,816,920,389,797,438,78,856,536,356,795,469,887,158,335,187,377,431,192,338,8,298,277,896,47,259,340,32,36,370", +"456,768,900,492,716,630,118,354,573,181,945,124,339,339,339,787,914,4,586,407,50,523,4,707,419,499,490,238,942,671,939,983,971,912,847,47,924,776,934,223,49,495,291,497,331,498,603,949,659,91,16,838,647,474,217,711,183,434,456,373,579,532,268,815,712,972,33,504,585,747,59,839,903,598,820,76,153,238,548,71,105,929,646,803,856,533,234,735,414,959,616,382,716,291,595,851,277,925,528,493,654,698,463,415,83,679,336,231,47,573,626,123,716,602,55,361,815,132,600,352,890,346,996,790,976,893,764,901,640,686,818,630,966,959,961,307,910,818,872,651,608,890,877,419,270,338,26,136,329,350,530,353,172,470,300,963,314,586,509,395,211,624,374,280,271,152,854,407,629,21,82,627,237,826,280,30,141,963,374,720,448,438,366,832,828,336,190,613,934,959,715,22,349,694,887,868,514,163,543,291,214,165,970,992,831,855,881,764,290,666,827,845,906,503,480,634,745,880,529,626,4,116,273,712,16,591,360,153,660,763,170,979,898,42,376,429,303,994,464,665,947,925,368,835,775,559,990,42,517,549,120,574,570,277,162,401,558,37,791,75,629,54,971,586,597,224,731,31,840,723,111,879,172,151,231,422,460,961,451,656,104,770,517,198,236,178,672,376,362,465,110,271,91,885,603,444,820,146,863,557,809,642,773,24,112,538,248,438,952,250,803,116,989,24,787,702,758,493,529,217,542,513,968,228,220,89,959,917,656,911,780,915,641,53,185,338,316,421,849,820,26,747,573,800,515,745,252,755,578,837,742,138,900,665,235,524,925,309,528,528,613,724,334,299,300,191,175,779,94,966,476,974,610,572,571,224,535,957,464,801,48,51,703,574,766,833,33,852,873,448,51,636,757,859,572,109,876,193,438,601,626,731,140,920,372,395,347,219,517,295,389,742,19,60,297,242,711,693,338,0,360,767,467,582,599,92,678,916,373,940,784,561,36,329,193,643,40,63,341,813,679,319,646,191,164,706,585,613,25,984,314,994,562,195,416,318,458,348,13,778,476,369,819,119,861,657,719,264,733,148,732,447,943,837,626,204,959,704,10,487,694,886,872,450,324,381,260,834,594,981,366,617,619,302,85,855,280,29,92,925,71,408,892,11,607,17,177,799,148,740,219,113,952,230,726,498,947,619,728,396,273,211,368,850,177,2,890,837,852,485,836,849,638,316,974,167,697,358,444,478,80,173,944,35,196,86,94,906,712,312,390,547,950,399,780,276,967,512,918,509,78,877,292,414,443,824,127,215,672,517,995,813,42,810,620,884,441,481,37,746,581,366,142,537,12,683,418,922,856,476,101,192,425,533,961,268,244,823,735,61,825,242,45,686,822,938,266,764,314,6,829,385,504,381,902,581,127,174,971,427,20,998,639,934,515,256,898,770,296,405,945,59,123,439,875,565,132,153,544,210,650,205,920,246,2,717,721,573,248,428,86,621,539,86,866,626,176,170,979,741,198,886,689,474,951,390,742,353,303,90,947,517,334,421,456,60,45,396,423,381,620,409,781,97,5,78,991,860,977,159,560,621,113,760,574,761,421,750,851,446,747,915,752,282,306,447,663,749,586,637,642,577,618,737,521,972,266,207,629,651,702,267,316,261,996,840,2,749,1,669,492,491,7,437,939,198,313,738,318,651,219,981,629,156,382,777,301,372,46,648,231,457,717,227,310,281,434,489,198,518,314,92,185,241,880,52,950,91,382,857,178,207,994,760,742,274,694,362,696,712,132,817,729,362,835,900,804,809,903,149,805,139,513,361,320,699,431,895,469,143,452,327,346,411,996,507,207,208,500,950,865,977,168,98,155,611,406,182,648,504,569,267,477,697,898,97,492,297,463,654,47,619,818,877,580,298,998,703,890,991,187,878,714,581,581,55,627,163,710,806,724,398,555,626,950,966,733,859,132,991,874,554,786,118,775,315,633,84,427,769,450,99,356,44,514,324,36,100,817,56,920,990,207,72,781,789,154,349,928,639,29,420,337,488,239,534,601,342,690,637,958,462,916,476,585,469,155,890,247,123,179,306,246,856,910,497,491,345,51,624,260,989,828,310,234,229,465,791,605,90,406,675,483,834,384,449,679,697,865,148,361,334,359,457,955,987,9,138,458,822,719,310,217,426,213,364,97,152,502,252,820,954,231,695,654,686,142,7,56,854,147,666,30,453,263,284,967,217,840,102,835,668,366,228,276,534,447,184,110,910,546,934,435,754,724,56,644,188,424,555", +"710,76,113,552,348,357,109,384,70,330,746,402,781,645,215,463,649,28,783,127,53,411,594,88,699,475,620,933,789,220,353,283,346,869,610,631,822,486,285,337,738,539,244,692,686,913,234,34,909,943,50,173,905,465,146,520,324,598,920,321,339,348,231,386,248,701,876,147,737,348,1000,879,594,398,351,589,659,579,669,877,138,522,48,814,64,858,37,954,255,776,456,827,348,379,502,536,181,31,365,887,768,134,729,654,218,330,850,318,654,685,505,630,389,109,323,654,981,500,289,997,171,733,831,620,333,665,81,871,255,238,78,209,289,976,195,24,584,316,281,845,458,397,975,985,316,890,335,238,201,970,995,696,565,74,448,863,228,945,228,947,200,608,563,501,425,382,345,161,921,105,500,509,68,136,697,25,689,915,815,632,47,458,13,32,117,602,895,903,992,934,872,308,674,890,887,804,738,400,776,79,338,520,177,981,243,507,49,183,339,397,140,115,155,115,809,402,242,945,289,27,25,252,478,767,588,841,422,842,401,648,961,859,25,253,174,79,530,22,782,238,589,245,465,575,885,39,618,515,264,452,591,509,594,924,864,508,604,816,336,944,166,186,221,964,243,72,732,592,153,484,718,348,864,375,578,786,254,378,781,894,281,273,492,17,489,783,444,166,285,872,437,977,22,550,434,807,994,852,280,796,468,119,580,952,811,403,335,431,161,279,150,231,31,902,346,275,454,997,760,307,962,417,920,978,498,626,171,625,774,135,850,719,403,172,914,135,1000,260,654,652,777,228,886,989,174,257,666,600,153,385,891,269,633,837,279,199,909,904,733,521,731,720,71,343,861,180,342,303,885,894,801,197,263,871,965,259,385,941,340,60,704,566,574,954,437,186,460,955,50,716,967,104,531,957,415,425,710,842,340,563,14,935,743,592,476,248,963,720,764,726,722,570,742,650,22,8,156,712,411,360,0,180,685,470,766,469,843,881,45,248,801,10,162,658,165,988,75,641,168,308,500,906,928,118,763,61,25,129,466,931,323,576,230,596,969,527,692,409,925,960,815,5,716,328,81,643,109,407,922,791,938,508,500,828,167,978,422,840,61,288,500,689,324,701,898,366,821,863,548,601,697,156,854,29,224,310,20,537,411,435,565,30,359,242,809,175,630,448,478,510,675,50,491,975,559,527,552,543,285,682,813,99,173,809,323,727,21,979,214,668,927,583,941,528,950,608,643,879,446,58,456,759,743,351,586,385,995,431,730,200,622,827,125,491,195,254,405,125,603,376,862,752,451,376,870,70,209,43,41,577,934,261,553,963,840,776,774,129,890,131,98,396,99,953,823,125,484,178,890,361,23,287,716,603,658,29,124,255,227,624,332,252,396,372,704,834,309,78,216,634,671,996,934,636,132,779,540,996,740,125,247,158,350,199,560,396,391,696,148,761,41,39,343,506,575,681,955,632,519,26,187,291,354,280,574,897,179,432,734,573,988,327,624,394,527,933,237,279,392,822,239,7,850,867,281,987,472,706,392,124,532,799,499,153,952,856,478,885,766,195,464,937,387,878,338,113,511,945,333,912,53,301,780,867,103,728,37,507,264,105,900,296,811,193,592,53,377,762,758,208,329,11,661,901,281,27,416,924,657,488,752,411,631,343,916,455,968,287,351,610,824,626,16,947,396,199,842,166,110,732,244,213,638,724,617,806,520,96,252,391,779,849,687,191,370,209,570,338,438,617,17,663,91,662,882,251,275,258,924,549,207,18,572,801,234,583,836,182,934,639,76,348,602,128,881,238,657,404,953,621,372,338,337,729,800,293,182,737,231,888,599,887,570,454,812,32,820,157,889,672,116,193,663,38,281,565,504,306,165,988,720,636,482,558,783,92,186,631,61,955,632,927,128,905,47,543,639,189,566,144,349,313,521,666,109,979,904,262,387,486,686,170,173,40,552,253,358,435,924,822,559,685,316,795,854,671,56,174,64,860,57,361,810,142,950,891,2,815,528,893,339,717,866,510,770,954,853,290,102,300,176,202,987,388,478,364,285,628,639,265,28,210,250,777,859,986,630,135,653,433,581,143,683,825,75,398,596,685,253,569,843,711,493,27,393,858,857,575,533,674,548,156,152,126,307,724,418,598,645,381,773,945,207,218,42,49,765,830,689,287,980,207,639,171,224,354,712,599,990,502,815,633,394,92,159,897,216,710,939,905,559,780,252,565,920,220,580,224,968,935,7,652,849,761,617,491,787,593,263,620,558,967,541,598,934,955,350,961,574,398", +"685,731,994,379,606,673,445,369,659,645,770,916,979,921,43,994,394,597,982,4,381,226,862,9,384,874,626,108,710,666,994,559,896,817,755,969,245,848,522,91,275,766,104,893,447,757,524,917,748,507,678,162,633,783,578,114,911,488,319,455,884,898,980,855,791,783,259,461,331,815,747,592,929,736,666,107,835,670,391,277,860,182,769,149,730,754,874,449,226,339,636,215,295,153,79,121,261,175,178,190,604,250,167,151,243,112,84,873,146,629,693,996,526,400,77,536,949,966,183,961,636,285,48,795,303,6,291,193,279,647,551,631,265,239,328,688,365,80,845,249,183,713,985,489,71,346,651,126,124,451,154,424,648,912,468,312,936,871,6,715,107,706,865,821,912,735,452,183,761,499,431,923,860,13,705,812,116,430,945,325,300,768,972,161,899,49,294,473,588,9,401,952,888,56,590,518,609,958,83,442,149,517,669,141,310,418,766,971,93,452,922,340,376,709,745,879,331,915,55,315,852,275,630,747,227,747,432,701,714,64,801,32,115,707,343,308,748,198,37,382,895,409,164,287,963,866,570,180,44,144,982,280,656,932,90,689,901,559,290,857,774,464,385,765,105,661,633,308,550,407,753,164,946,441,373,788,56,123,678,707,671,435,92,47,421,707,601,658,508,406,26,563,525,265,79,749,203,284,890,904,649,307,859,913,873,865,138,528,945,281,477,155,574,343,325,815,261,493,339,941,894,839,341,356,654,34,230,359,650,120,453,919,576,95,661,649,673,966,961,365,260,387,655,203,41,590,336,938,716,60,42,314,13,300,738,38,598,787,601,753,775,674,843,946,18,623,600,180,894,57,846,636,345,759,557,210,343,555,281,56,382,198,55,788,836,589,291,461,449,871,432,893,67,673,967,795,10,719,886,102,890,875,79,298,540,462,345,96,951,459,301,952,140,868,454,838,891,258,82,767,180,0,644,621,350,104,76,34,380,733,309,145,535,532,516,815,85,616,369,952,246,634,639,646,849,969,548,960,36,639,117,597,629,88,831,618,952,42,799,152,152,262,410,552,356,209,238,491,410,506,845,129,898,489,711,825,935,998,596,814,525,602,490,980,582,20,641,33,738,484,296,978,864,172,189,625,680,774,695,20,906,729,134,36,959,453,179,128,464,760,967,598,973,269,821,26,37,424,673,413,960,853,848,597,268,53,358,629,329,670,508,347,45,517,539,950,984,415,725,208,355,347,941,817,481,732,211,618,326,663,604,70,790,185,266,270,533,786,202,331,768,88,841,919,419,547,780,839,539,881,85,887,958,220,283,137,555,345,577,383,183,265,746,233,709,557,50,356,506,376,943,471,828,671,920,826,92,336,277,998,744,212,173,490,349,858,665,825,234,224,577,685,568,796,818,933,145,511,535,54,423,784,781,879,737,454,172,191,195,999,156,984,374,959,61,226,228,887,29,365,531,467,263,124,456,842,113,598,845,491,558,845,864,130,751,239,973,923,592,568,83,992,47,330,376,349,945,883,214,882,551,507,190,682,351,348,907,135,762,769,650,104,517,449,223,732,561,429,982,43,165,933,749,325,907,452,369,150,897,487,889,137,797,334,113,718,509,748,654,384,792,465,711,960,309,493,436,731,289,202,89,966,80,536,837,82,81,735,138,684,728,819,236,836,33,107,728,38,559,370,881,362,945,168,363,274,471,125,488,234,304,903,147,612,684,486,619,829,472,808,676,445,247,286,850,893,876,643,301,40,936,720,688,575,296,306,729,321,114,323,632,208,860,871,275,5,841,533,54,542,788,654,220,120,411,123,509,43,751,514,20,656,907,450,865,504,109,835,999,406,677,270,271,636,801,498,116,709,263,67,346,803,185,628,495,514,743,741,551,71,34,593,109,548,928,603,744,264,841,224,872,210,16,561,780,977,619,28,544,562,798,765,831,253,139,725,615,113,666,704,449,378,398,572,492,503,963,968,724,579,756,112,33,755,209,665,619,393,657,313,649,166,871,857,340,65,614,616,111,905,873,915,270,237,698,162,417,322,811,935,48,793,535,463,790,944,458,446,51,840,140,875,476,785,862,277,10,528,210,252,581,901,959,389,700,716,889,621,625,444,502,699,779,372,203,287,813,810,441,545,796,196,396,684,80,972,5,111,669,635,327,617,128,48,683,150,330,552,554,654,493,42,697,502,868,589,90,791,652,50,92,481,594,303,770,771,554,161,111,777,159,170,318,372,44,852,555,918,487,516,268,822,874,468,140,101,954,85,558,670", +"129,369,760,572,789,216,610,149,922,935,922,231,282,179,347,443,559,484,973,752,288,441,783,968,210,874,354,485,545,551,123,192,662,816,710,35,220,110,543,66,709,798,790,428,207,319,196,361,131,397,119,549,491,530,943,773,806,433,153,571,282,687,490,131,47,610,965,347,172,35,519,161,655,551,168,73,563,200,693,502,490,913,455,324,800,107,73,756,165,499,282,616,310,423,659,529,473,956,30,942,148,550,469,390,624,586,668,518,114,321,632,133,996,312,933,423,614,824,640,324,475,310,387,658,941,261,714,346,749,679,978,791,269,638,160,741,607,115,66,209,899,205,941,692,392,132,258,36,654,300,628,696,757,579,80,308,277,826,974,31,545,459,337,172,364,110,482,60,293,730,58,440,795,940,135,591,655,845,788,192,945,732,504,590,212,153,25,43,45,87,791,599,522,233,304,64,443,447,203,431,184,255,910,165,241,349,353,607,66,887,789,219,916,653,634,217,379,859,471,31,755,285,607,729,778,855,734,492,162,742,37,715,19,109,176,27,531,157,821,972,43,454,109,551,541,713,626,47,323,782,412,610,747,836,38,769,654,742,951,396,364,724,320,46,712,705,542,66,985,591,840,212,919,469,987,388,956,442,345,460,429,667,371,408,280,546,219,642,20,895,820,549,836,687,128,479,732,866,882,547,821,706,514,171,556,786,665,380,120,849,827,776,670,85,458,767,801,51,182,612,144,326,544,231,803,992,189,233,123,180,449,56,919,301,83,843,985,424,958,701,115,562,811,165,310,459,588,172,948,143,606,832,871,128,976,60,831,664,246,460,975,191,392,254,963,272,950,500,586,126,967,889,595,385,454,440,985,4,212,310,33,180,53,617,819,544,387,630,390,152,646,885,611,226,652,419,406,825,738,309,793,835,208,774,780,247,424,281,463,205,771,284,346,480,851,861,555,425,158,467,685,644,0,6,511,529,843,898,166,419,758,296,137,573,230,1,696,7,530,791,55,632,944,782,578,528,965,155,964,508,14,87,267,108,208,856,15,995,712,680,836,745,969,326,522,119,396,179,725,146,390,225,18,857,374,606,184,485,516,128,216,573,739,960,859,867,737,443,828,907,510,814,910,65,835,10,829,406,711,498,180,686,170,258,651,812,11,338,842,476,79,480,49,902,312,266,791,348,183,947,715,319,853,321,822,898,382,34,992,576,702,303,645,743,682,850,404,241,608,129,529,494,790,714,807,238,929,248,222,84,690,113,918,245,588,860,872,419,159,952,215,661,82,106,396,988,617,289,317,19,645,801,720,470,987,207,738,692,465,600,141,907,126,206,444,506,262,370,143,241,469,879,661,863,885,831,659,646,335,980,221,548,895,617,464,102,516,241,535,18,614,520,217,279,961,381,864,583,447,264,882,847,931,338,132,865,317,547,787,280,643,245,19,409,887,262,968,207,411,420,906,53,129,441,630,175,673,590,466,881,151,380,50,698,331,206,978,461,266,435,834,235,238,59,211,716,98,960,648,332,733,316,759,779,643,700,124,625,804,89,113,359,418,765,708,968,924,137,60,69,657,217,236,954,667,318,859,935,918,219,910,893,208,59,436,971,28,983,716,268,103,955,658,241,490,209,35,952,548,86,875,722,702,795,965,610,317,127,477,742,47,71,681,718,949,894,882,978,320,4,348,949,928,566,47,198,579,126,472,834,670,305,485,524,760,349,199,532,783,638,534,766,714,466,35,74,475,298,109,607,794,561,110,697,871,682,733,611,723,884,685,397,254,905,707,819,150,145,926,501,413,376,252,644,788,147,607,219,163,830,227,891,170,39,766,475,880,392,752,702,667,1000,308,657,342,61,364,560,837,623,758,711,868,9,215,380,452,920,279,967,664,541,76,931,668,703,917,28,861,903,135,874,746,396,420,517,60,975,492,251,114,797,432,566,404,431,518,237,884,618,814,152,620,857,409,474,218,371,937,781,544,959,64,48,119,400,263,464,724,226,440,232,103,181,6,222,233,568,409,712,549,466,657,472,806,511,490,858,540,105,63,683,464,296,430,200,856,123,631,497,730,614,249,214,936,271,463,74,281,140,769,754,949,668,478,134,219,425,469,517,495,105,519,202,326,595,75,178,728,636,824,50,559,146,734,556,867,986,431,451,496,213,825,716,158,634,36,121,16,785,606,902,788,644,657,964,956,211,447,919,496,134,473,242,847,631,555,613,359,956,405,304,598,219,506,955,345,761,6,331,183,606,582,480,306,780,811,954,291,832", +"637,25,96,399,268,738,344,993,577,158,945,750,376,314,579,71,456,268,579,995,243,645,386,338,673,231,625,351,369,984,992,28,68,801,559,68,538,79,33,553,181,754,824,728,69,87,770,179,756,427,131,89,797,728,401,848,831,710,740,759,336,382,886,261,364,753,674,279,97,911,136,715,227,340,729,269,512,952,914,790,476,799,685,353,937,921,749,290,106,782,691,268,183,360,289,55,384,921,322,698,982,157,154,842,466,923,853,405,533,747,672,960,552,60,366,359,543,363,728,458,757,232,678,941,160,19,24,5,248,664,318,326,698,494,529,388,705,783,986,956,480,309,423,30,488,658,167,153,903,821,867,615,796,157,575,40,985,634,330,685,60,127,188,848,720,671,578,120,619,433,922,593,886,143,909,798,986,574,999,390,652,608,842,388,858,196,375,234,791,365,533,213,41,89,325,328,594,205,550,421,399,247,151,429,655,795,288,803,617,777,471,624,135,931,357,982,88,229,486,570,520,983,571,538,707,133,458,891,290,917,961,122,123,87,843,280,408,230,113,90,676,348,265,461,3,637,278,256,477,590,751,38,151,722,811,573,464,368,124,978,880,73,412,15,536,250,992,44,995,923,790,851,114,899,762,853,942,386,274,873,754,275,72,705,144,102,507,604,656,531,371,521,475,337,153,738,597,276,924,783,289,739,287,231,35,439,707,533,460,931,429,19,770,82,228,639,473,723,103,465,31,716,508,145,764,357,686,39,738,674,225,107,401,48,936,107,935,291,719,139,117,711,729,774,485,233,681,382,385,718,260,338,74,674,422,441,279,823,491,805,172,813,96,236,251,233,5,163,77,39,866,216,762,218,247,834,794,807,317,475,951,568,731,532,215,39,620,24,54,296,571,315,578,951,830,960,478,808,273,278,412,795,613,592,454,889,169,265,258,454,363,63,559,70,316,942,817,617,835,582,470,621,6,0,469,440,731,47,743,302,374,231,121,19,632,942,591,849,161,419,486,5,992,798,180,493,941,240,897,153,469,427,328,216,210,919,212,240,783,640,746,156,828,32,395,841,525,803,616,803,161,485,855,966,986,64,608,984,671,63,333,382,761,505,734,588,993,552,941,35,294,92,134,806,545,647,267,141,7,340,455,766,636,845,550,803,359,523,140,448,346,165,914,188,625,970,171,416,683,689,952,252,16,628,95,949,473,657,288,85,771,965,983,576,587,8,559,345,721,310,33,733,4,383,862,279,23,803,827,712,824,398,750,662,114,651,505,638,193,423,76,899,956,765,924,771,91,57,957,468,228,660,775,388,994,966,723,860,226,498,500,3,636,426,112,590,658,222,89,789,260,677,797,943,841,685,547,410,335,956,927,145,480,333,635,666,889,134,253,762,518,644,921,211,300,117,587,212,409,895,426,977,725,83,92,430,76,867,951,670,572,391,134,280,235,25,784,222,149,464,353,705,243,668,16,339,661,511,421,63,868,702,426,774,224,309,680,457,652,74,128,89,22,478,626,750,897,808,660,164,192,177,68,315,669,241,101,61,687,546,220,340,772,898,43,956,130,206,791,50,771,656,869,986,789,390,670,294,322,41,753,271,265,904,637,96,866,8,696,883,639,74,97,228,851,58,985,953,243,60,174,2,210,521,795,128,581,104,469,197,39,353,443,979,28,560,373,461,695,36,5,95,322,468,164,425,606,145,499,28,877,482,812,498,753,907,956,89,50,543,750,502,266,115,131,186,333,186,154,217,597,522,220,395,923,532,463,171,609,615,609,425,569,520,990,706,394,977,166,297,76,238,533,604,966,756,731,11,866,434,19,957,577,394,795,475,75,963,280,565,754,690,302,192,933,419,146,603,304,403,952,490,911,30,236,872,439,49,482,854,43,339,948,268,179,527,244,758,24,855,770,770,934,418,107,172,968,967,679,518,690,926,875,147,673,430,443,7,1,188,211,607,95,424,205,614,308,173,251,24,251,240,746,908,202,255,331,837,887,110,712,899,173,387,68,180,233,807,997,73,739,404,238,834,165,10,75,313,80,172,523,942,269,423,663,268,995,469,60,115,307,556,66,77,949,860,697,511,769,703,542,124,334,235,831,1000,542,95,81,468,151,291,199,989,901,254,393,390,196,696,473,839,174,48,182,199,795,388,959,973,254,480,522,696,223,567,134,65,116,895,685,311,218,211,821,796,315,865,684,867,381,234,797,731,370,872,40,680,160,416,533,621,772,761,151,301,133,257,24,270,367,459,735,69,632,49,480,898,493,533", +"876,421,410,353,887,994,751,511,634,519,364,195,438,363,318,760,689,562,852,210,347,489,969,931,584,285,997,985,34,613,983,674,425,443,502,894,171,279,447,123,849,986,38,613,152,203,505,605,494,856,847,118,149,164,412,355,647,18,940,265,653,954,453,787,453,757,806,450,818,855,526,161,570,485,831,728,805,780,567,764,335,162,491,578,53,637,582,595,495,284,470,822,17,265,202,834,906,222,574,809,723,735,245,381,56,117,721,518,697,112,316,532,809,184,19,47,444,127,233,915,596,959,670,805,418,312,51,716,712,226,435,187,725,704,582,548,984,606,707,9,374,179,798,520,92,713,899,625,349,250,265,61,986,587,190,832,405,758,828,386,587,224,941,808,338,941,660,413,702,509,240,492,577,52,922,636,454,325,242,33,34,626,379,854,530,812,537,615,948,516,856,509,68,800,347,9,922,382,697,59,933,960,681,475,783,832,783,347,962,195,605,543,677,537,158,208,737,137,54,584,17,570,318,944,924,481,149,788,660,694,889,77,583,527,503,57,498,469,698,48,582,877,761,190,625,274,497,469,281,191,369,435,665,986,87,749,869,788,140,463,666,164,774,975,740,685,851,584,39,668,212,446,36,754,431,462,143,641,793,695,514,333,478,433,561,619,638,808,111,696,227,430,195,537,850,505,56,125,976,322,254,806,976,904,310,237,888,284,374,705,892,92,237,382,425,79,457,67,687,551,269,741,849,166,926,740,917,921,803,58,975,355,780,490,251,262,639,133,32,741,488,71,963,332,71,770,755,354,775,798,14,344,573,77,736,695,145,947,378,775,199,225,283,879,230,738,535,759,811,558,466,996,612,807,642,973,226,895,71,16,789,740,657,273,599,131,226,138,307,651,268,57,12,181,13,221,69,320,497,999,774,448,438,907,207,805,949,627,822,8,880,7,919,207,241,545,477,923,457,599,766,350,511,469,0,362,248,846,188,177,654,497,367,260,551,794,451,637,909,283,341,748,333,411,672,570,791,656,113,453,623,765,173,895,851,30,802,402,751,884,398,834,389,628,783,832,310,642,416,207,425,732,717,658,902,200,509,11,214,962,31,515,668,475,925,235,29,808,399,845,23,895,922,817,888,930,111,962,863,727,80,913,866,463,746,211,368,478,494,869,672,92,53,724,280,702,816,56,372,292,56,491,449,124,127,920,282,533,525,229,363,897,761,632,17,293,623,984,714,937,407,547,266,223,111,210,710,815,942,746,15,586,860,750,459,700,906,181,264,405,234,731,317,147,645,251,242,324,677,489,827,16,208,7,199,918,766,403,29,83,980,431,109,240,345,118,216,822,630,628,799,372,632,435,861,987,969,770,113,313,767,524,997,637,801,366,195,96,596,263,565,879,153,365,236,888,123,473,648,23,119,207,945,466,623,983,218,426,951,904,974,10,102,59,130,101,590,972,685,276,268,780,24,295,972,83,438,896,186,88,419,253,344,700,984,167,512,486,442,289,572,474,276,683,668,818,142,272,117,972,313,486,859,420,307,853,695,936,109,962,939,456,659,539,473,355,148,304,591,30,413,158,371,461,476,529,944,760,917,965,945,535,364,887,62,251,16,188,296,679,100,481,207,565,174,643,294,418,806,517,694,998,105,727,294,356,252,97,367,982,483,151,297,931,770,525,442,114,741,683,135,894,37,860,772,446,789,94,174,927,663,221,761,989,116,162,93,634,530,134,252,217,444,393,376,357,625,753,368,282,774,861,612,757,659,529,340,325,673,203,808,232,948,801,693,809,90,220,5,86,249,327,375,544,864,496,723,14,786,477,951,823,282,130,705,162,243,721,477,690,94,585,6,543,405,866,802,94,599,909,936,579,604,415,737,407,59,263,544,624,893,306,369,615,290,994,463,367,214,34,508,538,675,383,692,852,108,502,275,539,184,980,608,554,655,715,209,312,509,721,418,581,704,396,453,622,364,171,788,736,265,321,542,820,930,649,856,831,733,758,628,387,994,221,676,818,600,694,477,48,927,119,405,391,358,840,397,405,802,292,246,575,329,821,516,77,970,376,466,420,508,291,692,771,218,398,347,321,584,485,467,606,876,572,864,51,549,35,366,311,388,515,507,902,530,11,501,205,824,269,283,612,221,167,501,498,452,473,863,440,92,82,356,61,782,588,762,244,288,295,988,631,718,384,272,48,7,865,895,201,947,708,151,877,962,361,471,643,791,884,308,476,16,139,47,616,146,514,847,435,766,908,374,450,767,603,165,525,801,481", +"293,622,175,828,224,171,510,918,401,881,507,347,168,959,85,65,189,740,98,52,157,219,829,610,803,874,105,113,659,308,906,955,714,909,796,669,76,221,785,325,306,556,663,490,396,304,716,55,836,183,571,683,106,457,326,550,185,740,404,161,432,926,300,197,359,734,876,491,898,90,431,61,754,780,410,202,961,246,818,196,469,230,721,279,268,20,357,112,36,121,947,206,995,762,36,413,868,956,652,620,140,850,622,739,308,821,951,38,258,572,513,886,906,887,901,299,607,137,184,575,156,270,232,41,241,428,786,856,90,869,401,532,579,269,305,290,168,821,878,633,861,910,932,564,371,126,160,985,14,684,941,878,361,480,507,768,142,700,421,132,646,152,452,219,326,437,914,872,636,579,706,485,103,267,815,184,305,554,317,428,790,693,634,67,664,914,503,409,949,391,60,577,287,434,627,635,717,192,392,669,403,873,798,769,210,495,635,272,507,82,220,334,708,289,281,903,73,482,225,478,916,954,713,688,894,258,909,48,911,120,989,781,197,458,403,189,327,819,662,812,654,857,573,412,167,377,190,636,336,800,178,813,697,22,974,148,371,74,877,799,303,995,808,214,589,116,118,358,880,584,375,553,563,374,891,840,28,561,493,27,674,570,338,432,740,989,698,291,52,259,475,726,888,152,161,125,621,207,299,672,21,927,918,851,823,948,399,296,364,575,986,414,233,529,896,488,469,313,792,123,925,951,255,269,969,491,578,568,884,842,565,884,383,182,148,57,606,923,321,999,4,205,262,143,879,621,777,1000,290,380,222,762,550,848,928,341,232,229,333,347,110,925,161,660,724,904,288,387,708,329,81,983,799,24,641,479,908,265,331,904,584,544,990,701,964,184,350,282,701,685,96,477,87,132,700,155,294,496,32,534,229,350,955,344,66,790,17,513,80,122,118,885,698,37,594,349,517,505,840,92,469,104,529,440,362,0,796,362,397,198,904,315,849,690,509,226,120,293,100,438,349,432,985,815,39,568,166,403,222,377,65,29,473,574,917,50,698,194,157,729,918,744,655,657,468,349,850,534,507,352,909,225,177,847,670,415,129,984,639,912,618,933,977,9,406,618,349,507,600,752,9,424,371,45,219,860,733,812,728,563,196,137,455,440,694,601,926,838,111,105,946,532,417,804,650,270,130,719,813,892,440,967,596,414,209,368,733,349,537,350,936,700,213,70,606,643,941,212,710,904,802,310,341,406,485,987,272,877,50,78,254,50,108,117,214,507,168,316,569,51,385,39,585,122,315,509,340,907,830,872,497,954,877,907,2,95,707,379,619,189,851,229,55,321,879,142,455,175,106,761,858,152,465,22,402,170,452,290,678,277,4,401,54,143,404,849,399,722,390,426,861,301,136,86,645,279,391,962,448,23,771,754,526,730,398,423,452,937,711,966,279,386,999,933,698,853,355,339,110,58,133,284,977,793,70,985,707,872,283,75,310,757,331,126,655,947,163,184,308,25,423,596,305,362,388,676,209,560,964,517,876,19,89,347,345,150,527,245,929,816,289,24,791,718,279,69,918,771,332,498,368,743,563,472,89,175,610,95,214,685,237,590,575,791,295,421,678,42,809,472,559,467,200,495,93,89,850,205,644,153,297,528,292,468,45,358,32,391,393,343,181,740,829,911,306,581,884,293,272,128,685,650,267,186,578,661,772,863,732,986,554,772,119,134,13,831,56,767,22,69,363,916,448,83,241,589,918,444,399,228,392,564,651,638,964,651,931,5,369,298,329,228,251,761,508,216,816,241,394,299,195,974,921,453,286,699,785,837,658,769,39,280,974,61,826,527,666,230,689,685,169,811,15,869,291,109,294,993,434,175,39,467,514,770,289,750,122,435,900,785,912,602,104,274,724,157,829,25,452,902,446,452,938,251,70,417,129,927,209,613,540,334,977,306,580,446,730,300,290,883,649,882,976,969,888,248,133,55,485,685,745,604,565,544,681,176,647,611,285,383,477,505,762,469,737,562,820,374,373,409,782,433,411,398,529,898,364,61,754,714,948,971,130,431,177,513,76,894,600,324,64,802,869,971,966,409,135,678,526,383,282,550,465,519,873,460,373,732,241,343,38,494,875,843,266,370,115,267,869,37,317,674,590,85,194,250,773,329,186,255,330,147,391,727,616,696,924,385,183,869,22,599,346,979,752,962,225,623,708,423,314,464,944,174,377,714,138,808,482,108,821,457,443,959,22,777,463,377,104,283,569,804,509,848,658,587,9,86,800,796", +"194,846,731,763,574,174,120,356,917,517,932,194,75,641,86,523,414,571,81,831,767,409,420,825,205,90,326,804,893,306,631,315,855,601,846,527,567,83,204,7,608,715,464,75,958,311,240,644,448,238,673,468,429,420,416,43,867,124,363,507,627,477,454,254,865,426,461,321,798,838,148,334,756,157,773,935,287,698,330,718,53,719,990,919,881,315,938,421,831,107,116,702,283,424,303,967,74,491,795,686,108,309,228,993,678,351,487,329,453,167,278,886,631,701,131,656,870,373,106,422,33,260,455,425,857,703,496,107,711,839,959,900,635,180,697,559,900,651,565,765,460,308,994,583,697,503,760,205,315,538,967,328,871,36,558,849,902,655,104,842,721,232,485,706,178,104,588,874,573,567,78,731,563,34,814,486,42,8,886,19,211,930,475,220,766,180,788,483,810,918,866,829,478,398,565,257,427,86,313,686,436,304,279,646,672,912,548,306,559,216,76,721,300,238,428,856,332,689,664,372,2,606,928,197,282,893,677,846,404,434,118,520,854,215,414,893,718,870,256,661,124,157,727,258,64,61,420,546,824,593,803,630,909,963,273,781,289,323,167,870,943,539,374,553,417,550,438,410,657,587,249,143,968,585,143,921,281,612,428,623,858,480,370,216,101,3,143,810,749,593,352,107,590,171,671,259,585,609,813,74,888,565,261,455,229,674,506,120,612,923,155,713,492,356,498,278,225,973,651,920,120,201,614,754,577,214,97,265,129,855,68,729,971,508,215,917,750,452,10,692,696,19,152,787,209,259,508,807,596,276,895,529,209,906,379,975,154,904,801,607,749,989,621,902,464,814,857,994,506,263,47,361,247,93,222,935,903,466,683,199,576,683,345,269,90,963,284,278,763,884,818,514,967,394,99,952,370,594,738,693,82,505,425,911,819,263,234,854,623,650,393,830,949,348,645,195,413,490,752,678,843,76,843,731,248,796,0,519,118,846,874,842,487,752,700,144,661,380,15,236,215,872,742,786,943,160,739,508,535,522,720,854,94,590,852,77,535,45,76,277,218,730,863,386,962,484,259,745,914,474,565,155,196,328,395,792,888,343,404,253,916,308,602,40,738,320,246,257,456,869,279,709,254,14,631,678,220,136,890,841,450,294,743,562,662,408,685,966,967,463,44,932,678,61,507,754,299,854,79,89,410,398,28,844,109,443,132,489,686,613,874,108,157,512,537,622,615,364,200,56,819,283,697,121,605,241,205,15,126,897,269,922,858,401,373,368,560,354,33,472,357,891,7,360,209,724,599,585,221,278,182,546,540,665,748,517,814,434,540,229,431,266,26,896,49,211,62,627,90,677,708,969,756,568,488,188,983,185,667,596,257,234,269,913,303,118,679,571,516,647,11,650,214,19,937,520,40,336,233,914,352,215,588,304,406,206,274,397,781,632,432,530,796,16,611,738,31,288,431,337,390,586,521,799,236,905,694,901,765,109,68,852,569,887,396,786,506,957,811,207,938,490,395,977,59,452,937,205,694,780,239,155,102,946,657,192,106,492,272,623,618,732,677,674,290,902,248,541,940,697,875,123,468,899,892,720,958,218,755,507,454,595,714,237,549,466,734,68,626,538,441,306,879,146,922,835,554,114,40,733,524,462,545,848,3,622,709,547,357,388,529,138,331,114,62,687,747,566,731,657,23,693,294,597,401,1000,134,736,840,383,881,91,817,548,967,868,549,411,269,290,707,843,373,875,242,182,287,510,225,379,838,921,32,689,408,52,449,878,378,262,73,269,197,459,766,15,120,292,165,262,612,391,27,887,808,455,994,702,532,35,630,312,16,112,877,512,547,684,560,176,342,899,715,93,24,59,611,889,701,154,355,258,762,829,406,64,227,108,123,453,331,777,96,322,894,523,564,180,26,721,119,496,842,660,34,118,790,116,529,234,43,455,111,415,292,792,810,495,146,784,208,944,101,757,571,906,432,348,854,878,669,834,575,286,618,686,245,419,110,762,670,378,782,103,10,895,944,906,398,659,919,109,840,689,372,609,432,674,69,519,37,833,666,340,737,911,280,436,636,864,731,122,920,259,437,754,35,365,42,925,338,705,626,669,844,626,271,825,939,377,489,527,3,823,14,186,550,965,497,191,231,952,157,568,961,747,759,688,221,720,767,528,154,343,549,230,136,430,205,686,309,162,974,589,875,972,760,739,426,360,555,844,450,691,237,269,587,639,483,271,464,773,495,580,29,703,945,644,500,773,743,336,438,525,375,777,371,177,977,966", +"102,756,591,588,308,216,104,447,341,629,164,552,439,231,951,667,558,176,971,492,88,80,295,864,110,359,479,109,797,308,971,285,698,538,708,248,917,848,490,603,561,911,676,627,3,955,974,475,474,392,422,946,560,712,758,174,457,207,193,476,906,5,273,827,303,707,191,160,198,100,12,388,78,830,931,437,84,203,140,310,634,462,557,160,880,741,584,160,560,107,813,573,106,596,519,168,903,284,753,767,297,807,561,751,885,497,182,540,773,613,840,213,59,881,462,520,64,664,569,880,950,392,700,541,877,803,228,55,514,159,535,631,670,370,427,62,756,756,627,582,937,386,197,930,447,523,264,893,102,562,51,685,692,34,36,635,902,94,243,147,960,787,562,56,518,13,786,314,33,769,856,317,3,321,135,184,995,782,107,880,610,510,29,535,96,817,691,443,229,487,553,803,512,436,549,17,403,99,816,224,377,545,23,850,707,415,434,530,907,44,38,688,937,562,672,681,239,123,207,12,297,997,355,519,4,627,983,300,512,435,33,188,52,898,975,628,89,807,538,237,660,949,921,344,96,754,114,358,531,720,63,891,479,541,564,401,129,107,918,56,788,132,529,903,995,986,796,111,81,502,425,857,202,231,847,307,588,770,338,371,320,877,31,116,279,481,339,166,306,670,256,413,950,539,761,207,215,465,537,489,558,579,842,974,368,27,272,916,318,746,279,89,926,179,812,733,655,988,660,707,513,564,550,122,762,210,619,89,801,484,309,673,851,357,300,245,238,970,523,933,95,933,757,64,68,65,724,6,861,600,33,116,57,749,702,686,360,263,161,346,708,847,227,196,249,355,461,830,20,52,11,640,181,227,87,139,888,507,914,721,226,836,335,900,685,341,605,802,251,764,79,579,524,601,625,179,80,879,796,500,718,440,108,324,590,401,788,973,566,796,342,474,891,690,579,888,927,846,348,916,881,34,898,47,846,362,519,0,100,50,292,828,163,884,179,374,949,357,268,812,536,797,856,357,745,984,879,482,556,91,507,492,643,878,715,565,759,729,167,623,447,56,128,856,221,367,724,527,435,217,747,26,304,224,178,900,50,758,870,620,521,944,422,766,208,60,161,105,661,748,676,617,698,498,599,674,247,519,937,497,71,436,356,684,86,923,465,189,123,780,526,707,370,672,312,309,297,368,416,924,580,45,786,629,335,543,765,165,558,387,253,22,901,395,313,688,83,558,529,530,813,929,24,216,287,254,672,554,706,319,424,159,84,486,439,744,455,714,22,378,834,294,239,674,717,730,132,597,841,438,967,806,48,345,202,800,237,690,63,527,477,844,564,285,135,42,608,771,64,389,281,308,828,603,711,555,582,500,486,122,423,912,284,669,806,718,524,65,900,866,139,615,880,628,754,420,671,68,213,732,843,751,244,75,777,729,374,633,517,462,408,109,167,842,861,826,525,16,108,405,704,593,866,807,779,746,220,402,633,386,334,65,82,470,517,330,347,841,21,846,672,777,323,453,516,449,669,494,766,391,971,331,948,363,165,557,601,239,966,49,616,41,529,508,377,956,118,657,894,965,487,316,877,851,603,542,128,764,397,54,225,640,898,464,677,845,528,573,57,411,861,206,960,794,364,817,796,619,534,563,705,88,588,779,642,812,250,369,388,21,3,197,92,881,296,682,670,595,118,730,401,779,905,644,244,948,686,232,979,420,239,56,787,206,135,513,359,334,967,519,371,84,475,692,761,927,418,967,121,470,589,116,663,6,830,368,313,574,26,757,943,115,338,296,208,790,898,402,243,106,537,383,780,511,101,375,688,401,964,891,532,794,851,229,772,940,313,297,76,450,116,423,406,137,43,100,263,130,846,570,594,126,269,116,322,991,996,531,849,612,325,621,170,32,859,721,618,586,684,176,469,21,611,9,923,681,612,925,390,887,404,48,74,306,400,628,30,604,762,634,176,366,26,122,573,667,162,216,323,615,630,468,530,574,490,891,137,176,814,122,721,809,327,946,291,248,634,109,60,242,265,252,773,705,654,326,975,519,638,292,59,651,100,532,418,248,907,863,257,505,748,218,987,714,245,511,328,886,790,945,399,275,310,40,395,854,551,306,78,199,952,237,830,991,332,254,618,393,726,167,459,682,832,82,12,705,957,779,342,499,73,254,799,513,848,829,284,666,206,492,845,734,512,423,523,997,147,517,131,124,100,855,592,924,599,860,334,287,472,498,553,150,782,256,490,211,757,35,588,444,589,214,403,350,810,313,304,455,627,30", +"153,686,318,735,86,51,959,999,552,451,869,823,314,604,627,99,490,631,50,514,316,519,115,69,506,560,811,599,879,873,188,919,946,462,589,281,745,590,757,143,106,88,3,23,190,708,827,550,459,330,576,427,416,769,809,257,399,726,493,448,13,34,403,572,979,475,880,116,248,322,151,12,614,481,383,339,767,196,513,820,849,686,325,527,268,162,741,792,414,591,384,500,603,862,719,920,696,27,384,926,541,805,519,624,593,383,204,68,660,865,572,809,378,132,612,53,961,273,355,57,617,863,668,317,258,666,708,83,174,419,129,965,640,620,827,219,719,232,710,6,817,9,632,583,993,40,290,227,386,268,322,255,582,839,281,550,199,382,466,814,147,690,675,671,690,80,336,164,501,144,903,34,773,565,952,479,638,5,510,512,763,22,657,254,440,217,285,336,498,263,369,663,238,590,513,936,170,256,327,221,523,858,480,105,511,267,277,881,789,331,712,580,481,603,427,832,333,632,516,856,350,396,946,580,828,671,380,607,456,210,303,124,416,74,152,688,443,480,624,124,585,295,498,78,585,46,172,275,932,76,608,397,251,696,404,859,393,378,995,61,785,884,236,225,250,294,369,414,826,691,214,531,956,194,410,638,150,378,766,335,484,582,995,309,364,858,278,108,490,182,712,233,382,964,640,381,488,473,857,965,12,449,786,947,849,55,489,629,268,178,941,406,61,206,450,595,914,852,116,854,168,562,410,219,766,78,428,970,819,146,694,525,39,816,989,327,552,904,225,212,985,776,579,194,984,70,172,528,103,150,578,261,117,729,120,706,181,555,532,338,201,98,39,486,807,401,797,575,919,139,371,717,80,329,642,887,607,314,100,114,172,231,871,860,750,204,534,832,931,772,80,817,734,647,302,743,404,723,899,793,380,771,488,201,714,38,971,826,235,574,993,550,186,595,716,683,712,516,670,373,45,380,166,743,188,397,118,100,0,254,565,946,777,482,625,377,70,305,802,735,152,358,962,486,156,807,493,195,832,874,285,921,774,604,116,207,404,677,212,429,964,803,371,996,662,365,710,671,255,855,702,86,251,407,805,655,414,813,985,688,89,524,171,126,683,859,429,341,441,511,997,948,978,668,543,186,779,592,545,854,308,821,635,667,164,962,681,84,350,520,883,791,711,524,184,526,382,212,352,446,874,429,413,779,893,981,553,112,730,957,756,906,810,104,299,8,460,843,792,188,76,6,534,349,849,495,609,894,565,826,420,102,205,734,554,774,206,14,938,732,148,467,99,722,76,176,210,72,385,263,56,233,347,702,689,718,639,418,529,311,176,822,955,202,112,806,533,846,231,824,721,556,958,944,999,811,909,130,560,629,722,995,102,957,226,874,28,601,303,301,745,534,253,251,408,183,273,86,771,32,104,681,663,875,86,684,929,5,975,399,233,114,907,825,525,336,518,598,846,155,166,750,924,699,299,242,58,256,505,982,433,507,964,716,332,696,680,947,935,996,469,318,379,355,606,953,31,298,491,177,923,883,405,85,339,71,137,456,476,585,262,629,372,322,26,31,81,648,281,973,743,915,608,784,495,408,592,133,181,109,688,90,558,795,248,587,403,757,6,481,951,748,363,982,224,863,82,153,779,316,986,235,647,565,331,717,148,474,495,11,487,171,655,691,67,596,287,915,826,466,817,545,520,242,971,443,202,930,330,451,130,934,358,734,358,247,541,774,39,647,604,357,618,99,668,689,553,608,60,863,401,432,15,389,233,587,814,210,873,244,350,5,787,876,918,327,601,432,885,535,630,291,544,362,546,445,640,285,799,391,595,276,300,361,255,561,693,548,596,330,711,120,720,741,630,953,367,711,65,300,697,934,62,168,888,962,522,845,280,914,136,884,892,772,520,246,659,186,70,712,116,116,894,450,838,441,95,186,931,288,583,6,14,571,736,376,220,339,898,328,529,111,620,592,888,377,311,863,3,735,175,64,338,675,674,385,423,777,989,349,762,462,821,218,203,984,325,831,398,645,346,656,59,857,449,597,1,864,696,433,895,755,989,735,899,535,148,582,332,912,260,118,226,226,717,621,287,84,853,993,480,316,380,482,834,773,865,209,664,332,328,735,367,809,264,465,932,139,227,294,84,795,636,118,502,863,405,574,99,63,671,910,605,928,997,414,668,964,560,366,363,862,805,230,439,947,593,117,627,727,147,372,46,349,172,423,876,211,848,245,509,363,673,496,44,822,434,255,665,279,26,332,29,226,764,247,193,663,551,718", +"903,176,731,331,348,175,131,173,404,427,183,598,507,131,479,818,601,377,457,213,639,904,490,283,419,382,465,901,517,274,875,980,564,42,582,199,305,3,59,434,315,953,91,991,17,388,309,632,46,766,681,110,252,54,971,847,810,180,11,655,791,313,634,666,450,568,405,181,390,559,777,192,199,57,657,66,834,271,677,566,676,296,29,295,135,969,887,887,837,68,209,686,890,710,125,220,966,382,925,274,465,75,766,705,96,52,277,415,616,731,774,94,906,753,296,992,860,659,502,636,349,206,303,893,428,546,50,941,237,585,419,578,844,824,62,889,324,824,550,98,614,403,207,876,242,363,630,265,807,150,842,529,467,796,787,480,945,604,440,450,668,775,926,326,905,379,482,530,995,800,50,739,326,729,403,900,576,84,729,217,437,858,760,721,810,672,859,206,852,296,605,620,667,182,940,526,210,631,422,795,542,839,815,142,537,167,732,754,702,746,437,547,330,950,410,317,50,78,463,355,355,959,922,159,139,437,430,375,585,531,111,485,95,433,828,889,971,95,371,861,505,264,605,56,399,558,642,214,929,315,680,35,848,681,444,411,759,110,420,400,273,125,303,243,97,184,665,458,888,370,852,748,982,778,119,199,407,480,935,889,739,620,879,946,53,902,601,806,768,578,228,735,506,153,892,551,586,903,704,584,669,845,851,457,767,817,900,378,949,879,712,11,21,947,216,857,562,338,962,172,167,5,12,709,478,480,109,708,233,485,264,885,579,851,664,442,96,152,384,691,833,352,527,885,732,788,485,943,476,650,144,438,394,756,694,588,447,385,21,720,793,827,701,426,25,798,322,80,797,426,220,122,495,887,971,890,185,58,784,290,933,914,214,871,833,426,617,873,447,893,26,826,428,466,522,904,271,670,881,707,108,712,701,914,921,326,368,309,217,837,49,768,737,601,8,216,427,626,7,940,248,733,419,302,177,198,846,50,254,0,123,8,27,437,594,126,14,469,462,171,792,792,990,68,816,382,535,760,929,285,509,41,33,579,452,868,664,974,652,835,788,467,39,58,900,380,85,798,162,588,712,204,409,136,81,118,831,840,132,59,539,878,431,802,44,792,200,950,92,354,263,763,634,410,938,450,416,904,595,89,313,833,60,65,479,700,868,958,836,638,165,393,368,215,652,434,893,850,22,941,563,432,327,643,488,863,59,432,210,245,930,468,733,139,521,523,283,727,428,752,224,294,251,678,251,474,200,318,773,793,291,773,828,496,845,582,759,145,339,557,33,663,137,71,422,663,835,981,826,287,96,636,819,301,949,784,814,705,458,236,834,503,545,355,409,41,903,431,786,348,981,226,220,646,417,532,631,595,308,538,428,186,513,820,380,917,700,626,648,208,670,360,995,116,601,854,890,793,379,394,166,682,374,918,411,422,789,492,218,158,881,603,451,246,112,487,241,468,814,716,703,928,602,521,664,803,280,510,906,910,174,889,782,925,849,288,476,602,201,61,968,701,867,406,791,172,545,694,47,52,238,275,588,70,427,156,121,246,253,357,763,686,21,540,652,594,392,41,251,6,880,763,237,74,101,321,750,985,864,254,30,292,741,759,32,345,45,103,732,213,929,323,519,318,945,800,336,459,409,523,949,599,332,399,864,292,758,467,415,196,500,803,367,469,288,119,854,838,328,286,305,716,661,710,262,612,273,628,701,755,556,740,327,503,443,385,714,793,820,985,210,79,942,612,703,995,646,360,309,668,605,525,512,255,591,21,592,39,764,685,926,338,922,261,271,50,972,769,104,536,312,654,113,191,637,961,453,290,474,609,805,118,318,133,146,742,678,930,365,647,116,99,478,673,923,291,342,469,749,799,810,269,841,927,311,24,498,483,792,895,919,560,881,155,392,882,501,731,691,95,883,955,128,264,380,763,947,286,830,801,24,529,147,364,458,687,499,903,293,852,854,715,933,538,426,131,213,649,58,244,707,837,574,194,144,200,199,477,866,431,344,624,422,660,647,307,796,233,183,920,996,744,830,424,449,903,674,469,462,958,817,848,121,741,780,469,221,325,147,602,561,841,759,577,911,49,595,826,635,924,839,473,841,738,858,149,623,502,728,209,422,908,510,864,287,35,546,338,48,77,711,670,570,74,519,429,443,388,15,499,60,347,921,679,475,819,5,670,112,998,617,153,617,382,26,101,978,339,3,648,512,613,941,176,157,155,901,811,293,242,420,419,849,863,807,387,899,90,128,998,601,986,531,843,268,22,398,976,409,178", +"414,583,431,837,942,878,925,125,197,619,839,251,184,973,628,974,424,683,708,777,341,597,22,837,679,907,92,844,967,321,34,398,763,192,225,251,202,546,9,378,317,981,93,267,386,739,678,618,332,552,437,672,199,74,898,518,17,980,198,145,542,460,697,575,901,119,20,798,83,599,678,579,169,99,184,716,81,288,632,362,867,401,808,419,98,309,977,396,710,28,396,360,695,109,645,626,87,976,985,134,45,916,972,23,455,388,931,48,74,970,782,848,687,492,648,574,971,923,772,36,227,754,227,735,626,312,32,344,259,812,640,188,309,157,771,42,46,369,865,59,124,286,942,610,17,633,365,332,483,244,824,58,663,695,51,880,729,405,961,108,744,804,163,900,743,720,357,599,220,642,630,993,870,173,27,47,515,760,992,143,572,444,480,968,521,918,621,405,191,79,276,987,578,515,883,954,815,721,69,336,836,464,483,707,507,620,418,231,361,355,994,516,606,545,309,833,318,415,671,78,152,50,53,482,151,639,858,25,285,938,225,550,432,169,982,154,735,571,583,430,708,909,834,639,966,373,661,670,345,507,510,11,942,273,245,53,936,17,403,301,506,419,127,726,398,365,989,283,271,310,464,746,587,509,302,943,83,755,730,398,983,420,973,152,84,446,346,690,358,832,244,96,265,258,814,757,907,709,26,482,477,945,20,703,228,655,562,595,957,72,569,391,467,208,17,925,813,500,539,662,397,319,583,620,123,420,111,789,480,315,841,786,873,76,661,230,484,893,559,309,377,561,558,505,537,813,984,611,409,879,983,339,153,330,802,576,611,988,928,532,890,160,887,867,587,278,528,214,170,289,799,360,456,195,893,693,413,406,735,582,525,85,229,340,698,251,656,196,125,486,54,908,949,51,160,57,249,506,622,121,574,764,852,828,337,824,669,65,767,849,400,662,722,276,922,934,50,182,715,784,801,309,758,374,654,904,874,292,565,123,0,727,229,574,451,30,657,239,717,25,936,727,574,67,177,655,20,218,685,882,756,818,812,80,726,864,611,801,444,225,59,191,347,875,81,452,772,676,361,263,569,879,403,127,456,565,625,544,421,70,765,658,242,217,61,844,701,636,44,917,471,399,346,365,150,890,110,905,406,202,285,162,839,426,79,656,929,923,497,403,553,876,22,296,731,682,836,706,235,517,514,67,243,760,170,612,233,836,101,770,306,85,341,888,345,411,400,684,38,627,94,313,489,161,630,702,691,101,628,182,903,897,937,415,393,69,706,670,526,913,894,930,502,109,685,102,486,373,989,504,51,743,238,848,725,205,817,551,566,644,8,840,904,236,411,86,895,521,145,184,717,83,824,846,399,300,854,158,12,953,36,100,705,528,532,276,59,125,468,885,928,81,604,69,236,286,523,801,348,554,363,436,750,279,248,162,152,862,188,88,448,159,722,61,878,708,939,865,280,355,922,955,225,501,867,609,177,238,512,275,232,295,848,151,529,619,393,655,403,384,686,123,492,463,151,637,966,154,437,341,715,95,951,525,836,719,720,111,39,619,173,511,913,807,182,740,473,270,769,967,420,175,988,714,420,318,109,753,123,499,413,36,998,562,745,416,150,41,544,260,761,976,617,324,464,995,929,449,35,81,631,547,890,42,431,271,249,464,376,915,949,938,612,93,914,126,462,209,411,636,974,694,901,786,935,439,218,303,409,448,821,659,111,82,566,38,876,252,80,360,196,954,448,388,684,848,11,963,993,480,177,413,665,831,661,684,215,216,775,912,485,857,760,905,462,925,18,433,465,68,516,322,257,784,869,919,869,235,220,271,667,491,828,168,159,196,12,193,983,502,579,598,955,397,741,410,298,799,875,981,501,867,316,73,953,802,466,825,695,778,494,18,166,653,64,498,356,649,204,551,779,519,700,370,612,384,631,168,797,194,519,570,524,328,33,647,596,673,670,562,830,422,599,123,81,609,231,180,916,974,973,415,784,135,845,231,357,252,68,422,766,759,498,736,2,399,555,30,316,329,857,34,979,741,81,69,249,977,419,387,19,481,823,745,815,228,776,802,872,40,171,468,920,810,804,429,704,593,921,856,858,596,355,845,855,437,316,599,274,471,156,190,999,44,131,706,824,63,989,657,721,215,904,190,180,197,570,997,940,358,285,558,141,591,617,443,480,666,733,393,742,736,33,766,838,744,936,324,793,824,415,472,101,655,811,472,475,201,23,360,611,750,520,181,807,572,125,824,440,641,511,926,339,402,63,669,318,641,347,308", +"766,435,338,551,839,821,680,654,67,771,943,666,117,433,302,661,500,280,450,265,445,486,507,852,253,266,526,540,13,532,717,518,435,64,864,344,999,972,848,740,734,769,263,474,205,641,598,768,522,68,710,336,135,206,385,298,925,952,950,956,494,119,504,365,884,869,747,13,263,673,489,310,751,326,507,650,112,144,387,568,51,690,923,707,752,793,172,285,729,385,434,607,178,404,697,877,906,144,888,862,382,999,71,154,52,547,12,197,295,103,856,651,590,10,548,229,575,932,200,927,338,991,728,843,859,490,8,438,774,525,80,341,879,950,138,959,164,363,78,429,248,173,205,861,54,988,880,952,280,898,845,94,521,355,455,526,263,696,57,665,755,267,104,680,236,701,46,852,698,889,102,573,138,800,310,635,389,746,180,785,779,979,316,514,828,76,825,645,709,450,946,271,981,421,722,698,79,857,526,634,604,212,951,325,144,912,804,826,570,388,367,270,844,716,196,685,467,515,255,121,923,394,881,210,308,412,271,821,640,86,437,85,574,75,653,482,277,579,154,560,171,767,994,108,119,981,351,504,249,832,140,359,151,671,432,428,251,205,280,689,67,257,515,242,42,791,982,904,634,78,657,646,368,833,98,383,212,849,399,75,103,945,611,807,807,909,812,523,136,333,938,120,639,371,840,739,365,379,754,528,614,611,306,41,696,54,69,745,506,441,595,413,943,421,574,649,349,20,860,480,622,101,641,473,872,447,303,809,462,674,705,675,180,429,747,4,717,825,477,136,533,779,773,224,166,740,154,17,126,454,981,750,553,156,41,693,748,780,112,955,873,256,87,286,187,376,586,75,878,815,841,170,750,414,77,230,419,410,200,298,341,548,997,128,850,748,422,932,512,927,888,59,32,241,858,78,830,683,389,807,86,613,134,490,475,450,995,276,202,967,232,802,189,864,398,851,409,778,880,561,10,145,296,231,497,315,842,828,946,8,727,0,633,718,61,454,338,50,719,432,194,675,478,89,79,115,623,283,178,397,63,706,760,219,828,289,774,948,590,614,835,660,727,286,584,969,868,564,899,893,43,455,301,735,864,550,78,14,83,362,234,764,47,50,298,908,423,819,979,830,803,937,734,375,285,971,704,149,830,261,999,860,225,480,55,279,518,870,38,654,79,292,810,3,806,599,295,185,168,615,66,910,640,796,83,771,640,607,616,816,295,158,455,676,241,490,581,962,993,421,246,186,417,589,657,215,491,348,715,290,93,413,412,180,123,538,563,492,24,494,296,685,673,356,903,961,251,941,844,903,128,635,233,736,428,720,268,516,259,648,57,558,723,785,276,57,621,885,317,706,263,849,673,493,784,42,554,755,494,769,400,596,566,954,59,915,188,126,194,856,472,568,960,830,651,632,973,69,132,59,275,445,208,455,300,924,973,783,743,837,755,80,958,214,271,347,932,273,221,416,504,546,430,754,517,354,502,693,856,935,7,738,956,168,823,585,589,136,523,408,624,571,660,285,160,612,73,23,348,932,180,186,405,363,673,817,721,957,677,442,638,46,985,257,795,277,661,383,42,230,142,63,698,184,324,15,13,250,686,106,78,348,861,1000,58,576,321,879,725,45,648,39,367,354,380,905,914,76,102,960,91,581,604,584,222,98,229,573,686,766,47,3,465,603,764,351,651,401,772,357,66,967,500,812,731,136,733,99,194,213,388,550,755,857,391,925,776,975,383,456,123,394,311,972,939,486,730,703,365,958,656,331,40,924,978,347,599,728,637,818,729,160,760,959,744,211,383,966,93,181,367,882,309,758,415,918,875,705,75,991,732,534,290,367,979,383,33,458,533,962,684,690,965,96,971,884,779,655,843,878,852,594,333,173,632,947,373,646,280,602,22,232,682,279,496,973,169,702,293,775,212,953,969,569,203,150,55,183,625,272,753,941,841,530,438,801,839,989,62,644,283,216,382,798,885,920,324,446,933,479,28,240,771,610,311,426,319,255,834,152,815,708,383,11,434,762,742,969,593,585,639,683,847,839,192,491,577,773,771,231,696,180,573,417,641,812,591,278,174,697,815,984,76,942,9,766,951,322,153,668,863,770,61,812,372,409,822,588,657,121,856,977,37,330,349,782,517,346,54,498,881,299,832,89,789,595,620,640,814,168,92,674,357,924,996,675,273,426,355,87,149,666,60,591,425,167,206,217,687,841,396,690,147,366,543,834,837,702,446,343,937,62,128,245,156,112,833,37,710,636,235,982,42,990,918,845,460,219,302,351", +"368,364,476,855,86,883,736,494,713,557,467,440,90,927,938,774,890,988,337,848,608,789,602,966,635,918,601,883,946,919,77,159,102,288,681,457,414,871,631,668,306,487,263,83,744,126,165,203,813,766,320,130,996,2,155,80,532,659,505,634,688,112,221,305,759,525,453,796,343,918,97,246,179,222,188,501,344,524,302,780,637,167,290,820,324,373,892,811,798,483,618,258,358,858,811,333,136,684,215,178,147,804,392,888,146,287,529,500,963,384,528,238,646,527,446,249,263,902,543,536,2,468,16,603,795,368,157,148,923,221,981,315,267,345,705,440,908,338,880,334,556,734,445,521,169,985,204,158,839,426,842,804,232,12,947,582,962,160,768,478,679,43,763,896,445,755,271,7,114,481,987,408,973,406,98,770,46,510,458,305,268,567,508,961,167,644,391,25,372,92,135,579,950,266,194,313,35,491,200,641,618,785,948,778,887,355,813,473,73,469,49,422,88,222,849,978,955,128,371,629,474,893,760,109,193,214,122,757,35,767,722,88,987,497,960,145,139,668,685,365,909,386,552,317,132,413,838,958,774,584,427,879,400,628,974,667,112,103,801,19,145,799,926,458,503,66,864,196,840,530,318,219,827,166,80,596,577,271,494,539,79,55,496,793,348,612,246,695,587,623,778,340,334,76,383,112,289,822,831,114,545,8,119,131,784,252,469,839,82,240,77,955,923,490,539,29,935,237,190,76,611,186,137,856,569,666,949,741,694,439,673,633,367,731,547,993,135,518,926,50,64,660,206,298,625,911,988,408,696,348,979,842,995,494,247,896,208,552,88,779,885,670,464,85,4,304,291,933,23,492,256,185,469,532,287,639,322,326,177,873,638,623,467,20,302,842,419,235,403,665,276,441,794,789,631,521,160,829,315,721,803,518,708,636,190,910,2,558,761,696,978,451,472,267,919,16,355,601,217,36,162,535,137,121,367,849,487,163,777,27,229,633,0,78,28,988,169,859,996,715,462,898,609,101,425,972,5,891,250,357,593,976,459,293,486,857,714,420,962,530,487,757,453,519,785,774,510,644,921,463,373,309,80,797,462,739,584,473,113,376,847,796,414,539,680,436,210,492,967,584,143,583,387,979,79,370,994,699,817,836,845,486,597,75,205,893,895,399,481,534,548,742,733,480,95,487,41,889,6,711,248,81,548,54,999,708,936,542,848,481,489,99,379,996,657,485,348,615,614,806,318,506,995,912,233,792,585,530,205,877,110,553,284,272,661,779,62,417,587,553,976,557,764,232,999,261,232,588,246,442,311,716,582,782,838,719,956,383,444,990,184,348,909,851,540,893,646,737,978,729,457,583,528,550,467,795,153,663,264,902,590,178,680,343,565,996,658,565,711,585,95,513,269,799,697,3,223,141,966,311,123,121,562,676,131,669,826,266,975,766,922,21,530,123,902,598,138,432,915,981,412,836,454,728,429,831,240,640,596,40,736,864,801,477,855,113,952,537,398,992,363,161,564,977,120,305,884,988,419,596,996,544,78,726,959,969,215,366,799,102,259,479,614,289,156,922,44,236,206,397,25,742,757,692,660,316,717,565,531,120,291,454,30,677,71,284,224,724,796,726,97,242,639,437,989,162,733,278,646,970,944,30,452,506,50,150,584,172,231,522,966,615,795,398,755,586,112,86,220,17,945,90,32,384,558,372,888,47,818,470,565,42,932,443,752,939,470,293,936,674,151,517,130,274,580,9,453,124,533,150,593,562,993,38,453,83,375,740,908,23,475,377,539,373,555,466,745,742,570,213,579,966,180,477,78,712,761,127,146,306,504,714,488,604,986,46,614,270,847,997,102,516,551,862,565,966,827,686,336,745,955,427,927,758,288,842,981,515,20,182,606,697,4,342,805,863,981,56,887,769,918,604,137,118,50,129,250,893,145,278,139,636,199,585,655,271,319,383,182,161,587,61,211,275,543,180,690,857,988,590,469,836,354,56,976,845,757,166,38,672,675,819,759,907,673,834,985,947,180,785,886,845,591,959,668,10,878,224,744,106,290,325,189,607,910,906,695,157,831,811,897,183,102,237,249,730,609,954,744,963,628,87,356,122,451,565,716,819,848,756,763,688,828,502,895,339,409,549,838,80,288,427,908,543,527,601,421,254,439,374,685,841,854,180,183,66,621,805,905,139,582,472,637,910,685,166,676,310,117,642,284,297,35,850,151,41,315,548,809,347,649,111,433,392,277,40,406,365,649,689,7,592,809,730,283,198,351,465,905,863", +"31,415,193,570,52,356,812,491,260,523,271,747,153,515,320,29,574,889,621,874,363,569,267,48,378,93,79,807,361,266,693,894,386,941,624,65,830,697,997,780,891,993,895,75,746,124,188,116,827,558,583,135,691,812,958,615,117,930,367,92,298,563,668,361,10,455,13,325,118,152,253,922,66,663,914,940,582,45,753,706,789,769,137,594,846,986,844,24,229,766,29,323,365,410,224,368,249,477,388,308,992,907,867,243,342,689,350,554,572,714,621,35,878,669,270,61,861,158,118,757,278,157,927,869,681,591,278,59,38,141,810,65,979,225,165,394,229,514,601,887,437,740,166,894,642,759,292,696,348,336,100,785,429,446,837,124,549,860,444,755,515,118,813,689,212,221,934,626,423,944,132,302,355,956,316,606,136,675,645,766,608,786,409,893,787,26,404,178,606,409,593,479,341,476,706,385,246,664,443,698,387,735,545,759,392,276,327,627,357,104,334,875,993,893,633,658,928,73,422,158,925,950,287,954,948,264,258,195,452,814,755,441,21,156,913,630,458,702,94,853,650,471,422,607,206,655,575,488,313,402,852,622,914,442,270,119,300,456,401,793,800,989,76,212,146,262,217,300,448,774,584,838,912,834,615,676,132,230,331,647,703,426,480,454,541,527,960,272,292,249,167,723,795,774,278,103,840,110,40,565,158,88,366,347,633,946,892,297,60,28,216,331,602,494,963,999,244,462,858,993,60,500,980,976,559,26,508,14,441,543,134,569,115,508,215,88,333,714,576,515,551,409,469,480,383,893,944,226,104,205,951,352,105,330,38,314,731,559,448,407,779,711,199,966,107,922,367,954,130,808,796,899,961,283,58,201,870,154,459,688,694,881,980,347,831,592,467,904,646,956,943,923,195,876,787,854,915,682,636,777,10,948,546,557,559,78,273,472,172,558,199,505,724,616,444,650,682,251,460,329,658,532,573,19,260,690,752,884,482,437,574,718,78,0,445,971,637,627,875,265,105,307,212,908,688,910,948,823,735,581,616,93,465,197,511,421,644,887,774,304,966,175,864,115,21,931,883,280,686,170,607,83,356,651,110,818,492,340,549,380,589,615,452,441,654,114,946,936,318,665,741,328,460,277,576,452,862,529,962,184,510,588,438,486,229,204,750,49,424,57,546,4,222,891,298,656,631,346,952,920,643,221,46,924,837,255,233,68,752,925,456,6,819,480,139,357,620,369,22,367,55,903,810,755,654,359,659,947,399,678,504,298,402,747,11,909,280,832,172,506,309,788,441,664,465,164,718,796,338,373,54,771,827,384,517,443,67,362,753,806,58,857,585,951,478,336,132,357,3,425,765,527,580,461,471,814,591,251,26,937,272,905,910,478,141,109,574,957,386,133,732,883,328,930,721,52,463,8,65,430,411,30,968,429,636,661,753,52,577,462,977,299,514,553,10,898,562,101,882,267,750,929,562,999,717,688,2,708,87,95,844,257,661,49,824,457,15,174,548,447,907,564,745,804,151,146,976,358,630,609,113,225,786,557,733,7,815,852,392,153,188,298,980,714,529,192,753,595,710,130,749,926,611,653,982,46,490,348,779,898,461,357,110,215,458,416,221,647,158,771,180,765,654,747,384,915,660,918,592,864,561,559,267,478,117,449,75,183,478,207,236,250,568,735,606,83,647,331,622,361,333,360,479,401,147,718,25,341,621,420,13,279,689,158,778,588,112,31,369,25,132,435,486,570,608,248,968,204,200,168,978,778,354,71,153,610,348,880,348,304,764,636,969,532,798,750,208,309,466,416,96,958,871,32,681,543,752,528,396,380,702,692,494,330,726,647,351,755,100,929,448,176,711,727,335,260,95,523,214,763,544,411,743,561,480,874,28,188,231,291,467,113,169,592,712,385,219,230,431,185,791,992,116,37,759,880,304,31,558,946,115,325,679,567,576,9,123,179,406,706,825,824,644,638,999,399,696,559,887,302,918,150,239,266,839,654,270,714,146,342,65,322,989,30,613,469,69,720,483,539,408,347,414,132,303,173,84,686,435,498,510,314,532,784,932,959,870,869,243,841,695,287,314,274,196,120,375,403,208,28,29,269,54,601,308,225,300,36,726,251,94,924,94,453,151,818,637,790,774,904,799,811,718,672,887,718,419,46,348,975,562,935,776,875,102,34,52,85,640,494,320,56,29,790,307,358,752,218,877,572,836,190,650,64,280,160,591,860,158,678,990,234,572,180,363,373,598,715,393,359,341,142,46,452,911,701,750,985,190,796", +"561,614,735,15,523,825,763,878,556,353,948,400,956,741,643,45,787,589,301,445,933,502,975,238,995,70,249,934,652,311,559,358,94,736,8,439,723,387,673,347,530,44,335,637,517,16,60,111,38,211,826,466,34,936,831,106,730,624,534,636,887,554,576,280,863,652,415,356,106,311,706,570,533,520,379,181,77,611,10,116,941,642,216,958,521,390,58,494,580,245,271,708,434,666,998,871,1,607,223,940,327,184,713,800,700,785,801,578,660,743,800,148,498,505,622,773,698,52,100,665,89,828,68,920,700,577,720,282,687,186,665,606,247,855,351,506,852,589,307,879,598,971,590,279,81,869,290,835,705,712,218,96,477,387,980,657,729,629,67,64,264,732,938,110,648,103,854,833,964,636,744,80,724,697,524,377,773,555,876,125,422,125,897,886,434,440,338,126,762,671,245,465,135,652,602,537,917,594,383,51,751,205,490,291,251,937,462,100,488,413,691,71,862,214,911,577,219,929,620,621,147,540,126,869,993,477,907,229,994,473,381,484,322,461,297,513,785,192,195,205,139,953,867,200,934,330,733,531,804,847,607,368,20,420,362,753,753,352,602,286,794,99,887,192,693,496,490,497,634,140,40,548,319,914,552,825,707,378,941,429,108,869,384,200,733,413,996,519,616,113,787,287,48,495,846,917,21,484,820,147,5,827,809,805,781,8,793,483,889,276,496,625,996,160,850,802,58,389,452,842,167,391,269,820,6,25,861,253,292,733,840,366,247,931,121,919,102,163,312,580,566,828,518,319,586,433,619,762,634,226,751,263,177,755,197,883,829,967,374,882,726,480,458,415,217,577,877,855,197,538,943,36,198,898,308,379,596,932,18,226,167,435,592,22,168,433,830,115,288,149,841,445,355,352,564,716,511,193,192,901,539,508,463,567,290,273,782,211,893,136,387,865,903,458,545,178,32,417,252,193,165,516,230,632,551,509,700,179,625,594,451,61,28,445,0,869,873,714,695,82,510,566,91,289,791,994,455,220,27,96,129,348,546,638,785,807,404,274,780,604,159,660,840,327,463,849,996,624,179,42,71,418,923,217,791,369,466,913,746,476,756,837,798,544,969,87,974,790,763,969,242,605,247,219,753,767,58,23,110,945,134,327,709,69,911,831,791,79,152,973,608,622,617,281,571,58,124,602,665,50,11,698,874,815,258,790,585,953,509,734,454,843,153,129,653,160,617,494,931,440,351,691,340,950,858,442,929,648,806,503,781,254,97,922,462,655,42,636,447,988,280,576,338,161,713,716,862,777,755,101,50,579,758,780,448,245,366,106,736,768,726,463,729,881,280,666,164,806,703,936,262,459,17,98,55,184,909,925,588,146,274,604,819,685,556,522,398,844,528,92,431,911,425,153,907,689,701,71,832,16,550,255,403,4,81,914,346,207,485,369,326,403,95,145,949,179,893,616,146,581,605,718,831,503,571,639,261,226,752,988,600,753,573,821,919,508,111,134,688,986,109,250,19,429,648,146,882,506,389,525,132,253,58,739,844,989,571,938,870,162,862,285,968,894,556,26,172,940,841,952,365,463,169,172,342,471,274,129,233,268,310,701,904,142,821,733,148,764,534,152,33,104,853,996,216,334,853,894,357,215,552,881,840,625,972,191,888,782,922,780,945,33,609,595,380,381,289,151,747,43,893,206,409,168,60,204,64,815,967,957,783,705,440,207,453,459,886,950,756,911,389,57,561,715,934,167,413,523,485,431,464,886,841,855,462,95,392,894,107,229,287,50,797,458,273,770,640,770,29,924,434,38,681,21,369,121,834,266,895,931,342,736,769,616,202,678,541,791,97,392,408,809,911,934,209,640,702,752,957,141,363,234,469,365,970,782,35,845,620,662,30,879,686,709,938,938,29,594,658,256,474,209,478,417,494,592,714,719,169,174,909,180,678,584,181,949,498,984,512,777,293,387,390,92,424,941,653,222,439,458,78,631,611,523,166,73,12,656,378,112,100,177,240,462,601,669,88,162,812,587,195,562,319,671,331,910,910,765,905,816,210,448,367,845,297,503,621,596,749,127,366,177,698,41,500,626,204,657,280,636,300,870,149,894,103,409,429,613,259,994,306,358,555,141,163,890,877,440,787,980,681,402,682,132,390,309,966,270,61,40,20,520,93,296,268,636,684,15,141,834,107,853,522,36,773,284,383,338,720,400,577,714,28,4,23,863,117,65,702,520,916,175,532,774,126,976,539,958,541,489,514,570,812,491,60,318,739,989,778,188", +"537,571,106,700,396,69,985,548,943,20,753,724,392,195,859,711,667,718,823,503,267,558,245,562,983,854,399,193,296,596,790,595,475,266,177,888,906,190,431,680,629,315,960,390,132,706,389,148,719,994,539,814,576,388,393,213,409,151,464,303,132,458,644,440,260,695,946,732,990,818,870,491,710,698,243,642,524,313,920,943,180,366,530,9,591,404,598,470,62,539,240,914,244,486,533,827,799,14,794,767,155,602,925,866,617,155,275,460,47,746,282,970,663,662,732,164,372,469,648,682,916,546,599,884,247,458,377,366,25,230,215,811,122,440,85,441,410,642,661,174,560,97,699,382,10,534,685,83,130,764,426,53,679,804,401,231,310,419,51,906,150,670,968,212,552,742,691,101,151,523,418,46,627,786,299,105,307,286,131,332,594,898,36,598,12,533,452,921,80,730,62,732,430,824,258,749,191,496,265,769,86,208,255,124,586,714,859,339,248,834,194,163,148,852,828,34,681,882,233,129,710,403,612,657,418,377,555,889,11,89,190,901,646,934,561,605,193,171,796,356,231,958,609,57,609,523,200,275,655,466,983,934,871,964,13,440,67,628,731,444,706,755,675,465,126,490,267,60,610,174,583,443,224,130,397,281,376,867,387,11,435,473,730,652,938,18,470,977,846,996,858,567,646,823,403,31,547,618,153,176,919,484,789,401,220,945,218,886,650,10,650,883,525,740,109,513,509,162,863,467,492,183,440,407,817,729,162,584,497,451,705,570,789,80,566,498,244,255,525,961,909,734,428,635,715,873,475,184,887,339,747,130,752,829,920,916,534,602,613,253,528,364,312,431,354,403,610,216,272,941,75,193,319,985,846,320,609,853,556,4,280,314,969,137,668,515,993,528,886,285,7,688,508,672,896,210,57,28,480,641,535,670,536,509,641,16,31,131,685,336,156,853,130,555,356,280,685,126,393,643,988,815,1,942,794,226,144,374,377,126,30,454,988,971,869,0,490,495,430,48,404,335,436,772,538,544,376,714,443,281,103,214,854,752,267,644,331,273,349,112,675,465,448,434,621,200,767,477,865,192,170,136,577,285,913,782,188,197,379,804,834,421,480,523,295,22,246,192,710,698,674,691,442,125,649,313,502,834,645,278,213,910,150,768,75,807,866,161,427,817,293,765,891,217,941,988,20,650,418,894,81,39,349,744,773,371,403,202,786,532,940,942,121,40,329,670,879,151,376,648,604,342,870,518,894,956,939,43,335,116,726,209,470,263,577,640,390,397,213,537,779,305,13,589,565,719,984,437,293,808,252,526,909,381,275,723,986,959,869,904,215,561,507,976,364,172,328,980,207,928,594,617,718,501,695,434,490,920,987,236,678,956,204,384,403,754,749,239,225,76,262,710,573,740,454,179,844,69,284,755,803,924,696,493,179,31,767,371,647,660,820,715,376,377,893,528,792,247,617,801,985,331,525,713,413,730,299,735,202,299,729,881,652,462,915,606,62,813,479,867,375,978,797,348,18,986,429,405,541,677,5,722,915,148,617,32,333,722,138,924,707,611,586,960,649,428,858,356,68,939,611,757,819,436,401,558,209,587,557,867,644,316,487,213,181,519,719,848,786,688,434,801,235,434,151,275,258,340,182,598,9,960,654,841,21,611,682,980,115,954,397,869,294,519,456,884,147,349,4,926,200,35,767,110,542,554,628,636,599,81,541,374,588,571,632,295,649,635,23,264,696,949,344,481,154,537,439,187,482,208,699,518,718,994,122,757,682,862,805,788,356,424,728,756,183,739,958,646,631,79,815,397,361,779,666,677,139,148,792,5,881,7,761,332,870,665,977,106,230,365,578,367,934,444,695,473,602,953,648,248,533,961,93,590,515,986,78,475,592,588,323,652,911,987,276,58,894,211,568,423,802,334,330,395,816,757,514,91,272,241,358,120,593,708,614,830,975,993,32,976,960,613,576,133,502,112,234,58,609,253,769,37,967,480,865,455,912,583,213,249,467,786,810,40,977,964,546,746,25,652,908,418,107,510,32,141,634,869,792,752,598,103,894,568,403,80,435,478,493,6,529,243,217,420,149,518,305,80,456,338,870,250,93,836,338,67,242,112,980,394,663,947,124,53,449,701,14,748,546,650,719,427,338,365,828,11,450,762,515,910,8,163,607,270,796,289,274,245,761,246,364,618,796,850,895,357,497,759,878,845,149,261,149,547,598,732,315,681,881,601,586,41,955,689,882,309,503,865,621,595,388,488,39,325,489,940,898,452,766,132", +"962,145,716,400,839,512,268,653,617,368,334,922,710,680,995,372,220,338,717,944,474,395,190,898,831,406,11,515,738,171,725,539,586,124,770,801,477,819,929,845,16,765,35,130,381,582,180,622,990,491,54,864,960,220,618,60,405,269,130,461,103,329,43,659,235,228,919,458,379,831,658,652,739,29,438,127,897,801,349,575,869,824,614,566,538,77,396,387,169,590,71,207,579,670,926,77,545,965,838,633,637,340,83,406,287,815,566,200,528,132,31,314,818,806,21,252,634,606,452,917,931,370,551,912,108,129,378,130,213,288,330,290,842,315,59,296,717,918,1,826,452,451,970,331,292,399,546,919,6,303,469,747,273,756,337,503,232,539,372,111,517,98,178,628,994,473,759,635,387,302,528,304,4,155,97,824,232,730,430,200,56,506,378,4,420,805,630,162,192,85,230,51,769,491,17,419,136,208,166,887,291,985,862,720,806,378,961,509,5,570,160,974,422,945,81,777,225,738,862,293,744,468,504,487,953,490,606,710,960,677,32,57,863,297,396,779,925,112,901,765,832,7,943,768,831,446,466,162,131,249,741,58,328,559,599,534,897,983,25,467,136,113,453,706,558,42,549,723,106,749,699,33,385,882,710,48,468,581,806,40,238,454,147,720,478,357,656,996,141,88,807,136,327,607,818,202,823,659,3,863,847,113,259,567,503,183,943,887,558,155,436,230,904,308,872,278,315,476,231,793,310,620,577,628,126,425,249,872,44,367,709,772,268,538,599,339,23,538,701,706,475,216,817,487,172,390,791,394,509,275,21,434,860,595,264,772,498,283,643,347,608,17,560,647,480,85,21,122,458,763,571,887,878,160,490,417,869,91,819,395,606,383,902,419,974,504,866,924,902,394,383,251,14,708,763,21,171,706,894,665,907,5,943,107,273,594,614,129,503,76,886,961,469,9,682,562,412,360,81,40,75,85,696,591,451,120,661,949,70,14,657,338,169,637,873,490,0,343,898,655,389,556,98,607,926,415,216,665,68,275,478,925,149,10,907,783,734,963,155,290,836,75,245,708,676,341,608,541,181,471,662,925,131,705,526,811,84,564,134,786,309,273,745,58,787,717,910,316,619,61,442,342,560,659,269,157,814,705,234,105,244,28,76,780,898,487,503,899,75,329,691,554,241,277,986,111,563,670,364,661,820,564,131,255,770,654,153,205,747,894,858,249,929,48,646,325,353,552,318,622,60,403,659,300,669,813,561,443,848,670,588,419,611,404,136,234,966,136,463,525,539,615,837,663,369,832,474,650,241,710,1000,470,118,889,782,706,932,322,525,883,396,111,580,484,397,650,81,889,687,589,879,361,73,452,785,327,826,180,598,841,4,20,383,398,486,592,287,111,27,106,496,829,822,982,283,921,739,906,371,196,158,353,81,833,740,941,494,538,853,793,379,58,751,55,887,930,739,634,203,200,751,52,970,500,26,100,149,421,747,879,756,779,251,363,565,84,639,740,196,332,41,433,131,795,903,250,656,346,803,318,517,658,617,822,509,437,880,591,266,269,669,736,979,682,116,388,781,920,810,657,730,621,757,379,902,265,936,463,869,497,900,837,141,476,13,89,490,558,468,182,55,527,229,788,578,646,527,167,418,912,43,974,174,602,140,709,345,333,179,901,850,335,455,192,107,11,826,699,779,649,67,228,893,425,836,480,18,945,660,840,15,226,180,642,515,7,471,140,134,60,956,108,310,898,586,760,286,671,399,777,597,146,351,607,942,682,395,556,962,987,593,730,1,738,16,864,917,58,317,231,392,745,955,578,1000,244,24,72,806,621,269,993,57,586,52,12,890,933,732,907,968,631,650,418,367,818,453,135,583,813,216,795,946,986,588,254,290,802,899,301,837,137,212,852,446,804,916,752,224,650,555,604,164,362,659,36,485,498,918,563,312,110,692,571,994,823,403,266,434,211,770,892,353,499,886,106,708,665,995,778,129,244,136,549,350,725,262,836,350,482,112,456,603,649,695,303,374,677,733,87,49,911,255,331,526,568,625,731,818,512,233,171,154,981,251,628,703,995,516,806,682,43,428,575,646,636,712,851,103,272,48,326,921,425,961,50,993,802,3,675,530,751,53,654,452,842,961,630,918,482,816,48,420,673,800,391,493,574,354,449,573,921,597,903,402,57,313,97,187,365,503,307,768,807,620,359,91,522,228,387,255,725,5,830,554,846,771,85,825,266,296,265,584,947,199,979,776,387,418,721,73,528,795,217,176,439,535,948,564,289", +"873,888,479,897,841,984,815,600,164,699,585,24,193,902,705,518,960,350,387,837,42,605,680,597,986,70,505,741,975,68,225,967,20,523,924,478,34,684,197,451,531,701,326,512,750,60,167,261,699,755,888,259,39,558,833,407,359,600,736,723,611,371,556,732,119,381,496,106,906,809,536,49,61,37,215,878,880,431,267,153,478,317,831,564,533,161,506,56,538,180,108,857,688,75,462,277,323,590,220,839,485,331,44,410,300,365,42,246,300,971,404,984,603,382,3,277,868,640,580,367,728,801,996,633,223,598,169,983,619,304,457,561,141,232,466,661,672,718,881,236,182,834,111,637,591,227,434,920,518,86,592,409,454,747,206,710,393,661,16,193,470,101,805,866,206,836,69,230,432,670,718,229,939,894,254,181,884,428,903,844,66,258,934,795,538,358,361,307,634,176,863,947,346,235,977,662,609,570,140,946,140,843,89,563,886,15,596,16,150,805,694,168,978,402,885,144,738,749,286,231,729,75,792,319,245,963,218,882,613,585,744,417,870,299,441,13,155,284,360,418,338,719,977,133,952,825,985,869,199,713,396,270,426,848,929,965,311,244,3,620,30,822,293,672,503,878,953,922,546,861,759,170,794,915,22,365,486,253,479,9,529,161,73,778,736,806,712,341,311,41,987,659,455,82,592,310,42,675,639,875,475,907,172,856,399,829,799,150,92,670,436,15,912,392,495,227,850,653,539,855,568,557,846,221,623,893,799,366,451,805,997,920,138,621,303,475,875,2,984,205,950,45,465,623,885,393,719,930,463,929,157,807,630,962,241,814,845,437,109,53,697,957,583,605,586,626,891,88,331,389,658,212,863,689,891,677,786,269,247,785,888,361,247,412,198,475,39,807,208,166,16,848,579,554,628,36,685,531,449,534,270,357,992,492,223,846,757,330,316,477,12,210,787,16,27,396,888,432,237,63,641,616,7,849,637,293,380,357,305,469,239,50,859,627,714,495,343,0,694,577,754,56,626,976,219,649,513,247,109,744,465,243,242,328,640,120,604,784,696,423,895,628,14,145,144,254,626,983,733,326,626,970,790,70,719,583,823,179,577,847,120,679,834,511,48,988,829,142,89,369,483,447,476,176,1,643,166,319,56,658,585,584,721,945,904,848,876,16,675,768,357,865,540,141,207,396,451,113,766,906,877,449,8,200,848,532,689,973,987,528,778,849,321,308,724,808,789,961,202,298,847,703,97,315,404,904,810,649,952,992,821,314,384,751,22,143,833,708,659,210,35,44,372,170,834,924,997,505,218,827,751,726,192,178,958,925,233,960,647,741,50,466,870,232,294,203,546,507,788,896,32,620,269,868,735,484,295,338,424,433,734,738,913,925,137,260,233,246,410,78,181,211,302,59,527,511,353,8,935,620,457,322,98,636,798,6,790,74,839,307,165,890,579,360,595,499,242,61,687,860,599,882,388,248,172,671,79,232,187,68,169,938,543,921,950,314,648,943,16,382,140,170,531,889,154,734,534,563,693,842,374,26,900,446,371,812,686,908,180,991,726,834,217,290,501,520,310,583,462,841,14,50,644,844,4,244,890,697,574,494,299,998,455,461,225,138,745,484,814,521,346,105,710,659,284,983,34,147,125,656,325,315,294,379,566,109,885,518,110,133,45,241,85,593,288,287,149,277,848,223,299,814,574,687,974,358,834,118,989,325,198,441,471,527,222,380,804,276,98,202,479,636,304,460,322,557,559,188,607,606,670,318,106,296,680,887,307,333,340,182,580,757,6,363,578,414,810,886,773,19,117,837,544,977,510,600,890,590,557,774,226,115,441,649,794,34,521,662,178,308,697,656,498,218,569,583,57,319,458,454,82,243,407,383,341,329,800,103,141,710,718,804,469,847,274,980,280,361,147,529,303,430,189,480,887,409,740,951,441,641,850,542,120,653,85,498,207,911,447,603,797,437,822,848,442,473,353,393,811,102,808,83,515,629,96,493,338,341,185,287,208,88,291,675,621,849,822,960,724,280,528,440,41,563,23,683,647,447,164,349,958,277,53,952,954,252,582,927,832,42,434,165,339,166,550,669,145,251,33,623,431,220,352,350,816,934,206,205,370,977,533,49,585,793,911,674,76,850,510,688,454,280,383,226,12,150,315,886,190,923,69,273,754,445,177,873,718,12,596,374,601,570,850,875,96,364,782,862,732,215,408,49,482,81,486,551,518,820,109,408,894,204,676,476,122,741,904,524,184,384,230,593,895,694,720,987,852,670,645,588", +"902,999,344,800,707,694,64,912,336,795,97,760,713,547,319,700,613,753,276,139,84,413,260,170,674,277,886,515,512,757,499,828,660,187,524,293,256,864,453,193,139,478,877,133,412,24,842,173,97,494,191,996,719,779,405,55,548,101,145,689,905,247,275,615,454,409,946,71,795,887,367,778,330,320,561,360,433,715,893,534,808,433,178,909,714,25,507,200,934,768,577,595,379,529,887,59,123,307,585,366,743,388,922,878,930,345,297,267,649,979,513,351,65,508,485,75,338,587,536,658,51,635,858,308,822,127,859,906,652,784,86,450,361,40,191,404,193,946,948,531,61,829,90,121,312,162,965,214,776,267,600,41,903,633,947,918,220,966,509,680,833,453,941,793,711,644,732,322,14,964,381,156,784,841,711,696,834,361,205,839,940,688,216,34,99,82,493,318,869,349,172,839,320,868,128,326,845,539,73,774,853,184,920,872,929,954,145,686,973,870,336,622,755,659,650,825,484,407,15,76,278,848,683,482,42,343,300,866,396,253,976,854,312,554,967,697,646,474,292,407,835,902,66,274,734,33,959,623,726,780,699,685,761,494,691,653,325,712,760,316,524,637,162,592,142,346,655,720,955,829,79,377,614,230,56,763,637,883,53,975,820,867,987,715,109,646,949,394,506,593,794,654,763,81,116,419,932,316,69,168,481,665,790,54,15,245,414,214,403,102,408,431,7,966,39,638,475,219,615,686,320,134,82,350,994,368,939,454,419,318,513,732,237,92,154,220,204,411,595,410,658,774,996,317,323,327,483,971,653,184,35,439,772,186,566,73,613,829,891,813,433,286,152,556,958,733,952,172,734,357,573,494,967,22,500,153,963,696,866,438,529,625,523,919,363,946,321,517,370,70,771,962,215,104,953,605,198,267,563,770,568,257,480,144,390,583,189,60,4,773,186,242,593,401,952,261,291,80,607,341,168,369,530,161,909,100,15,268,802,462,717,719,996,875,695,430,898,694,0,396,468,449,24,220,31,701,784,748,197,659,637,397,486,323,829,593,376,793,77,988,443,572,381,201,637,457,510,514,180,586,593,967,580,856,720,725,613,8,508,75,523,149,126,805,834,751,381,988,571,898,946,403,600,994,985,310,477,702,706,477,876,25,372,950,108,964,410,276,567,405,61,63,40,550,176,425,505,401,469,441,199,553,659,40,825,446,649,492,298,368,157,603,948,201,781,878,956,455,25,8,863,350,529,545,222,933,791,844,563,404,471,365,331,99,217,943,685,821,527,427,539,389,582,69,735,348,701,75,616,985,985,636,679,382,640,433,283,606,341,469,636,570,282,350,401,509,547,293,271,451,296,147,152,439,758,44,893,481,355,359,57,398,799,801,819,366,104,610,506,26,486,496,823,76,459,395,444,788,993,97,506,78,844,521,530,381,901,588,296,698,310,643,511,662,48,374,700,750,867,552,470,238,83,100,492,745,881,628,948,188,772,201,105,829,142,531,18,606,61,726,484,708,330,486,752,566,574,526,815,386,355,559,852,488,490,313,68,341,56,775,738,536,256,241,688,196,349,847,605,95,34,589,687,869,822,772,49,495,914,265,451,118,371,840,608,426,475,366,264,290,435,457,304,129,389,242,78,955,364,531,340,312,426,357,41,549,482,154,960,30,674,522,29,821,758,253,966,673,152,510,47,750,911,601,339,466,259,159,585,687,417,655,507,198,574,527,192,222,947,46,447,768,685,126,225,151,838,634,405,751,952,735,974,221,653,78,75,509,565,121,354,221,484,603,83,546,289,37,588,741,809,477,649,865,148,809,639,114,999,891,692,873,5,298,76,735,819,405,527,959,711,421,176,169,809,718,200,31,743,102,603,138,84,815,705,38,125,887,219,260,92,958,99,797,814,202,149,259,248,5,176,659,873,8,120,153,232,510,453,588,624,771,27,433,758,982,62,494,484,904,954,526,394,913,208,688,43,574,827,969,102,184,309,830,401,774,294,811,213,610,60,502,737,796,16,113,471,815,883,101,754,602,757,375,454,129,594,147,232,363,59,374,347,952,214,541,622,521,881,772,103,791,226,233,912,763,776,928,73,27,164,844,874,311,444,667,24,586,236,168,896,573,831,493,119,503,77,724,170,137,12,935,936,146,410,555,198,803,447,61,352,912,992,83,193,119,352,814,416,628,527,758,191,971,174,795,277,425,46,787,519,131,112,351,770,90,246,46,227,60,39,762,101,143,499,171,55,915,766,12,6,121,156,539,909,573,706,654,324,713", +"529,235,571,53,919,394,714,977,723,229,238,925,359,98,903,104,681,457,904,350,271,935,154,337,68,635,573,2,394,949,34,329,310,905,52,622,674,867,554,517,677,819,98,846,908,904,111,190,89,583,97,579,953,813,737,597,483,205,487,43,246,316,696,66,134,878,357,479,462,786,458,176,233,1,252,362,60,571,381,27,997,506,588,64,892,578,530,585,40,811,300,95,698,167,324,960,481,458,502,828,64,40,993,100,890,760,582,434,706,980,292,739,339,196,854,666,591,6,200,753,532,82,468,52,943,846,619,182,701,751,609,222,155,822,180,577,600,83,473,703,453,84,616,119,574,377,826,291,123,663,560,284,219,971,714,766,749,245,359,146,515,588,999,315,967,896,578,800,161,340,99,638,645,381,229,560,28,581,817,470,951,149,90,665,952,472,78,87,358,948,895,784,607,217,70,121,358,214,669,880,979,567,436,515,207,630,944,714,354,769,951,649,527,904,950,144,647,298,348,959,514,531,419,785,798,834,218,263,467,220,561,359,351,180,55,69,798,731,782,183,99,466,345,24,92,345,149,665,798,540,164,16,717,169,312,74,829,577,19,867,961,787,959,31,4,630,227,334,857,905,69,677,101,664,291,458,609,596,810,700,474,472,492,723,536,105,669,879,213,393,272,16,271,267,268,22,461,355,721,699,896,471,602,755,32,567,106,30,235,936,62,663,899,347,222,270,845,700,446,633,66,54,512,126,85,624,361,544,790,214,68,849,835,80,188,833,110,886,963,251,602,626,319,609,964,353,76,570,634,479,286,765,735,76,410,208,864,737,209,996,883,436,916,395,642,107,687,414,767,255,472,852,640,15,362,775,182,605,627,873,916,767,811,493,538,290,727,244,944,734,55,820,657,930,813,800,359,533,520,845,574,272,904,630,263,709,454,883,38,878,291,775,529,910,525,627,456,725,548,813,308,952,791,419,283,438,236,812,735,171,25,432,715,265,82,48,655,577,396,0,867,796,340,220,293,322,881,986,460,682,693,72,989,63,79,958,196,876,389,531,760,41,149,364,486,374,856,594,313,117,152,169,764,850,280,796,474,186,275,674,662,847,16,489,114,451,325,884,773,199,500,298,412,580,340,759,694,492,771,158,932,787,899,547,532,827,383,527,42,273,145,262,406,184,543,931,497,894,807,301,538,51,884,626,566,259,891,347,507,420,494,695,428,40,386,215,751,951,59,208,162,84,745,804,862,717,863,539,284,658,540,217,882,592,218,961,542,764,484,333,43,703,164,568,13,741,299,677,386,739,711,904,625,516,860,174,33,503,624,107,832,365,114,811,815,627,478,413,330,968,188,294,866,476,481,704,38,602,974,708,668,419,151,994,438,581,804,994,468,60,265,814,191,574,279,622,716,303,430,35,675,734,691,514,33,667,711,460,855,503,189,157,602,7,243,121,280,847,102,246,566,535,566,410,42,811,545,960,762,949,970,855,593,205,298,136,457,145,848,592,226,493,950,209,446,844,895,179,550,671,726,287,723,316,450,252,961,341,454,210,119,724,184,144,492,977,461,598,114,275,423,12,819,723,476,955,917,269,152,797,946,127,857,121,61,949,835,771,659,561,824,687,49,818,1,940,189,8,135,777,952,908,605,703,56,148,697,144,408,484,426,967,535,652,946,512,879,999,186,338,591,557,555,450,380,336,797,587,764,269,579,581,747,176,992,49,477,833,372,174,589,360,863,339,960,248,410,14,582,382,667,233,155,510,363,734,248,950,571,136,679,582,310,298,995,640,710,467,152,94,102,616,124,641,99,211,519,136,91,378,139,268,44,945,460,867,924,648,935,42,969,242,893,347,249,441,589,53,1000,36,685,838,279,531,787,288,856,954,880,531,306,376,892,443,715,84,836,693,59,236,2,273,211,984,151,820,712,479,453,560,810,858,784,139,390,141,157,541,562,931,837,897,868,469,575,33,199,703,406,79,255,853,212,466,344,50,520,394,521,367,709,899,708,235,551,348,7,111,254,5,163,108,621,499,621,996,752,502,94,303,485,253,8,855,576,666,616,556,272,364,448,370,829,978,621,744,685,554,206,559,394,825,772,881,104,529,160,13,133,514,725,123,189,42,161,848,649,919,374,289,26,618,590,512,781,620,951,307,485,705,218,781,218,695,343,257,84,515,597,713,682,737,229,126,879,15,873,559,444,993,178,823,892,402,451,717,121,427,362,511,297,658,945,627,487,669,226,663,502,57,987,138,824,400,146,633,226,657,455,47", +"362,727,294,800,348,477,482,584,740,873,555,511,76,616,79,741,992,942,260,39,142,914,733,176,130,294,919,624,88,483,400,980,985,237,190,447,880,15,16,743,932,595,494,223,183,846,310,695,88,848,83,420,524,552,340,559,975,659,270,836,406,938,46,511,681,218,982,995,226,304,329,550,718,166,813,878,148,626,343,843,535,207,283,243,450,146,446,422,201,779,231,417,877,556,497,147,888,159,916,602,814,29,365,896,490,525,122,651,459,996,610,921,320,975,591,207,30,675,233,658,741,50,713,460,831,977,905,799,973,322,549,595,275,385,14,354,622,41,335,669,965,176,105,447,631,322,472,79,265,299,129,330,812,967,511,340,465,1,944,569,399,914,864,815,890,428,421,936,109,501,12,462,89,446,271,332,457,453,863,31,955,412,648,243,437,917,535,508,926,456,562,181,408,714,266,771,386,959,420,330,587,75,570,652,517,478,161,138,301,510,334,55,248,187,890,551,154,693,763,955,15,289,647,852,708,97,267,570,86,530,64,175,558,531,233,381,474,34,848,534,864,126,258,556,28,930,85,218,173,702,384,501,383,244,892,620,382,325,627,591,597,125,563,877,44,593,471,973,370,625,87,3,394,344,833,562,664,88,142,513,798,461,298,276,837,358,58,809,149,844,636,745,898,169,764,619,270,484,755,737,559,619,797,662,40,440,976,571,556,880,337,953,916,605,654,967,422,15,477,322,20,905,721,436,295,463,799,59,742,550,107,160,316,466,546,901,901,417,702,298,671,361,834,675,888,158,26,224,978,636,699,212,860,940,153,352,606,585,659,825,696,251,358,98,909,562,911,106,962,13,318,1000,2,760,513,766,669,149,54,445,915,870,738,46,694,459,130,181,60,791,881,443,577,154,406,914,718,966,811,890,467,422,226,88,42,802,416,796,609,284,908,831,86,275,185,538,483,672,885,679,500,246,55,486,341,349,215,536,152,792,936,194,462,105,510,404,389,754,468,867,0,194,43,801,13,718,210,541,234,577,762,32,681,343,57,713,659,355,468,563,765,387,362,955,436,258,532,837,837,391,150,702,218,215,17,76,952,499,127,554,108,495,186,268,811,201,847,80,36,233,588,699,897,80,842,89,868,790,416,529,326,522,301,605,410,585,283,442,602,567,198,287,764,996,623,718,512,708,463,400,703,100,936,215,55,689,137,669,9,367,318,368,925,479,991,781,84,84,732,710,488,166,407,212,82,294,699,873,808,904,953,154,416,730,292,331,864,903,110,795,391,531,122,998,603,729,396,658,843,988,319,550,829,932,672,369,600,795,897,182,230,554,754,914,152,795,906,415,540,728,802,280,261,525,50,108,414,897,514,76,47,90,622,342,137,58,143,998,424,29,998,569,413,780,30,638,152,457,488,660,278,660,291,794,936,602,322,782,752,984,141,748,104,393,332,416,199,600,855,32,100,458,450,359,917,464,643,670,231,712,730,420,662,845,322,74,820,925,835,38,470,61,730,303,268,409,142,558,426,423,121,432,931,411,955,416,49,470,84,730,297,493,780,560,161,867,186,281,151,856,769,23,146,945,158,523,25,701,858,790,360,862,72,782,277,472,52,543,833,247,772,599,816,801,82,502,24,354,868,324,135,382,759,621,201,210,457,704,856,181,569,225,249,217,203,616,160,678,725,355,700,46,818,822,486,872,557,80,539,60,360,893,829,124,524,820,384,476,364,397,130,340,618,710,902,523,215,24,351,652,578,512,687,25,317,24,748,853,718,863,7,640,631,909,171,214,520,831,213,194,179,302,861,447,428,640,485,487,517,715,961,306,149,78,947,638,537,596,347,269,721,895,785,914,110,579,929,124,663,382,693,388,955,757,162,18,277,131,914,294,344,983,964,410,234,602,491,659,665,223,910,546,939,333,201,432,862,502,516,818,350,515,223,751,656,974,759,190,387,65,73,822,387,118,209,531,801,127,254,434,723,209,836,32,279,675,428,730,165,638,41,773,920,950,288,907,619,894,552,169,78,347,206,593,575,253,619,980,585,831,720,633,454,582,57,185,723,609,27,619,147,533,611,923,986,352,715,220,842,206,20,907,469,419,697,761,573,173,566,97,177,683,494,668,924,165,621,75,611,175,490,919,927,522,226,450,228,542,620,902,711,363,306,187,127,399,934,691,809,248,21,52,31,379,225,792,428,64,943,892,752,18,659,362,259,469,927,936,394,177,329,517,334,713,371,676,891,336,981,879,363,533,499,186,892,23,946,159,932,140", +"225,913,498,860,140,145,886,199,579,787,486,448,713,616,72,120,219,343,990,764,766,814,754,750,311,313,564,781,192,22,662,831,637,254,303,929,813,161,845,716,640,114,574,72,945,820,631,771,369,805,989,855,311,602,917,410,43,151,248,28,254,668,848,494,771,895,507,267,219,51,229,83,964,151,717,417,16,956,201,756,251,830,597,851,839,8,291,893,718,699,372,787,977,349,958,443,176,289,363,92,895,587,735,589,847,37,200,925,617,541,427,90,354,266,114,563,908,138,137,332,87,735,917,894,667,55,214,729,126,810,491,14,195,513,192,652,14,768,600,872,491,179,543,546,548,203,564,441,637,227,221,391,559,687,496,584,167,74,282,812,405,410,710,615,683,948,934,945,471,599,398,282,66,536,764,901,349,971,113,441,377,336,194,866,468,641,37,819,162,470,169,215,144,857,53,509,125,549,723,646,783,159,572,927,708,267,124,605,925,924,262,389,784,141,830,162,762,559,893,414,586,546,998,63,572,391,270,75,55,637,721,958,71,129,225,200,805,554,763,472,798,220,607,166,697,664,842,563,522,387,694,441,177,49,678,992,602,502,27,548,836,671,852,457,246,164,937,662,704,738,431,958,207,876,752,728,123,874,852,769,178,647,255,13,215,501,711,274,627,630,654,656,881,305,191,903,56,249,277,538,326,970,553,447,429,583,66,973,777,530,580,648,920,436,427,989,922,127,740,409,114,830,876,612,135,530,600,914,147,452,337,100,575,124,76,733,331,891,573,909,155,910,179,735,305,986,523,179,456,303,855,552,948,789,784,886,799,277,791,462,766,610,277,922,948,374,514,254,284,398,575,595,936,777,422,754,134,890,303,955,576,207,193,786,225,195,725,484,750,255,869,518,863,294,256,597,157,894,470,597,764,390,106,375,865,542,522,606,662,397,371,820,523,585,278,550,744,373,424,319,906,634,632,5,748,432,872,797,358,792,727,675,898,307,566,335,556,56,449,796,194,0,700,356,364,379,739,778,17,380,471,417,455,320,840,738,87,563,171,75,97,251,288,300,287,43,973,998,22,345,871,950,251,950,679,446,219,574,165,421,180,478,853,806,693,63,528,313,399,699,317,295,362,928,827,116,383,655,622,468,100,675,681,950,762,915,42,647,139,665,232,264,643,747,209,290,712,112,621,286,423,702,210,182,110,433,405,991,618,663,267,697,739,318,521,93,474,875,286,873,655,287,357,556,550,765,254,483,614,950,382,209,479,832,989,792,395,346,617,826,846,468,816,942,692,714,209,791,194,768,99,592,948,472,906,164,640,170,69,133,464,642,666,635,580,477,202,285,858,274,950,856,986,616,743,577,468,730,673,895,908,424,442,642,199,907,53,520,797,49,11,854,889,778,293,772,43,777,694,647,975,226,137,273,157,615,159,695,84,971,679,330,72,4,14,519,969,871,568,294,175,952,905,907,730,695,95,222,25,943,200,571,186,34,952,166,488,512,293,85,471,74,673,423,619,490,443,216,190,284,96,13,709,248,68,404,894,330,664,782,349,5,31,374,12,853,882,276,643,361,581,499,926,765,226,321,459,229,895,363,700,380,120,390,27,85,717,579,705,582,249,851,178,905,312,624,503,289,992,831,659,97,306,104,763,353,813,223,616,929,341,326,251,868,131,629,477,581,308,801,528,303,55,841,407,79,838,860,941,787,906,102,595,417,978,162,834,28,995,891,672,195,670,280,580,154,99,886,544,404,626,772,801,125,412,254,139,465,214,805,642,562,348,301,289,692,867,38,814,402,535,150,169,670,903,839,33,212,199,328,845,16,925,115,743,362,738,972,784,360,308,95,541,747,311,751,407,134,545,123,504,622,249,866,700,547,779,514,989,191,440,184,627,265,166,299,696,449,243,398,410,570,209,298,21,180,535,526,642,791,126,2,773,226,736,966,373,377,797,668,192,223,782,633,26,735,442,987,662,166,547,908,554,310,633,779,944,547,509,124,499,751,771,861,594,4,756,813,468,672,494,369,919,25,455,338,723,331,909,875,397,243,628,81,758,461,157,989,193,924,90,852,773,133,387,60,474,795,410,991,413,669,805,701,382,70,901,789,12,31,894,110,436,804,556,470,652,37,78,556,631,422,603,614,366,754,303,756,542,376,507,479,64,244,756,374,141,723,328,358,493,225,730,302,355,878,984,584,427,180,972,931,160,936,893,690,826,338,425,438,856,894,825,853,725,252,100,53,777,758,363,703,530,156,731,957,336,962,633,785", +"936,128,719,105,44,115,439,75,975,984,813,858,275,622,214,558,594,322,447,721,715,413,385,749,437,363,295,138,61,446,845,117,470,207,787,855,403,927,156,105,295,568,801,448,813,606,451,287,926,124,327,902,287,35,563,8,337,95,323,443,696,102,366,120,520,427,392,961,282,983,965,910,453,883,19,457,506,583,151,822,159,565,60,497,740,361,467,974,977,909,853,277,145,562,706,255,574,369,590,60,925,325,91,558,236,662,483,267,288,111,767,461,952,373,349,853,481,321,602,158,856,411,983,731,915,684,166,15,714,679,677,364,686,2,585,216,138,680,428,518,357,703,932,289,856,404,148,697,736,261,907,187,848,866,228,69,295,520,794,496,81,787,829,136,203,393,179,116,670,129,750,308,40,791,860,716,356,917,925,68,873,631,899,457,991,903,461,626,201,746,462,779,372,16,455,178,60,646,941,214,158,629,623,226,253,267,237,86,429,477,688,1000,451,261,575,837,693,232,145,445,91,919,533,853,193,63,917,783,44,276,939,861,816,823,190,905,886,568,990,783,143,498,281,842,473,76,529,408,185,442,915,99,752,490,237,796,45,181,248,319,18,835,20,413,90,275,152,713,323,421,457,263,701,423,670,999,772,209,923,508,846,338,269,76,771,204,25,786,281,982,359,992,920,487,470,992,582,684,679,958,38,751,857,105,90,475,903,57,97,17,621,8,658,373,993,694,661,804,323,936,448,777,946,529,544,411,358,349,421,172,943,299,340,608,587,311,712,579,113,376,165,125,533,234,936,72,751,259,553,718,783,220,242,792,295,894,179,116,685,70,489,225,633,438,498,951,661,591,447,591,992,319,83,311,53,776,979,655,8,491,126,390,411,263,320,324,776,965,42,836,257,320,557,752,591,770,442,908,68,866,570,313,207,576,385,485,295,314,116,6,830,366,334,744,901,559,47,377,740,646,928,639,944,992,333,985,742,856,962,990,574,478,609,212,91,436,98,626,24,340,43,700,0,350,674,663,869,983,224,714,513,730,571,99,957,879,21,778,12,848,517,109,962,774,3,214,349,873,995,202,254,735,743,363,915,31,701,133,343,771,166,641,248,130,331,790,922,681,100,124,494,389,151,959,95,150,192,121,412,175,177,166,493,97,364,358,758,934,60,129,849,853,674,315,225,796,66,72,711,137,951,920,30,261,17,461,279,522,645,705,508,63,856,993,99,838,36,480,161,308,734,707,954,292,420,792,523,908,85,933,630,886,928,850,770,230,695,2,817,227,60,383,959,808,837,296,56,269,783,657,794,384,457,316,636,772,222,109,378,1000,859,311,491,518,373,345,895,454,424,392,709,905,26,253,826,512,384,939,652,179,151,932,390,966,599,9,483,759,826,695,778,479,103,232,707,977,674,680,502,866,713,639,465,66,436,593,869,948,41,222,604,119,538,735,721,630,525,985,804,309,43,694,884,994,106,631,100,848,391,569,649,977,207,285,411,697,502,365,411,55,795,94,244,156,726,31,87,146,928,116,866,715,903,629,97,370,624,317,899,491,900,607,559,752,871,82,977,431,33,47,944,962,824,943,383,977,776,171,171,443,262,288,738,587,478,95,621,400,70,667,770,175,595,254,654,166,116,914,51,765,517,205,63,313,761,286,133,873,992,614,292,942,232,153,574,816,12,105,705,408,65,689,878,840,721,651,363,979,175,505,645,640,374,545,71,927,936,466,573,811,589,276,953,243,538,439,641,520,330,461,582,201,580,586,869,24,444,254,720,424,542,986,985,126,634,834,370,131,224,219,612,504,280,893,218,238,615,113,928,488,618,62,926,741,732,239,135,354,286,264,890,476,443,850,698,644,277,406,236,291,363,205,408,671,9,789,25,292,483,39,112,43,908,389,984,882,619,647,52,853,610,547,711,491,729,604,902,207,659,548,70,202,948,645,621,167,657,849,895,938,762,597,882,736,265,483,172,263,353,762,926,132,373,253,794,20,781,73,396,632,450,729,784,192,363,98,273,269,18,773,353,520,456,946,106,650,283,701,384,271,595,31,199,990,938,102,86,891,873,383,595,160,259,525,672,341,878,655,905,120,764,375,409,405,797,107,736,308,369,199,884,477,728,957,117,71,657,147,292,107,562,805,954,233,2,535,902,370,463,127,558,259,294,452,446,729,417,934,332,846,324,580,585,925,896,131,460,380,486,314,771,400,917,194,151,931,663,905,769,187,678,273,306,786,723,801,306,461,884,343,283,455,471,393,63,240,764,37,372,829", +"743,904,921,1,526,292,496,817,13,501,567,429,946,750,260,335,736,257,206,410,160,443,447,86,172,313,911,883,655,251,734,945,124,278,78,54,780,222,885,129,527,874,713,84,902,823,231,429,530,379,372,481,460,306,903,228,685,616,77,921,418,690,357,248,369,363,697,177,831,437,989,312,703,121,964,43,811,138,313,218,676,794,328,786,256,253,370,432,741,295,8,726,470,150,976,76,515,606,14,406,150,121,446,376,352,629,395,591,324,52,37,615,902,456,33,502,998,795,913,516,893,133,999,718,102,687,479,880,995,27,271,837,532,528,279,661,311,597,208,255,89,611,876,203,912,51,860,502,987,591,78,24,117,947,500,876,696,685,941,710,71,374,817,196,202,6,945,351,910,86,357,943,181,713,786,507,809,545,697,805,443,746,787,517,391,522,503,633,470,926,835,909,50,111,532,490,838,648,962,128,160,665,691,304,563,516,394,186,971,989,109,519,730,349,848,376,860,652,553,928,290,405,102,35,868,917,878,98,295,884,774,341,374,23,461,83,731,287,222,481,595,69,13,895,914,916,622,322,270,387,738,170,325,166,16,638,815,829,404,393,833,71,303,554,704,836,359,253,434,413,80,747,334,494,314,835,371,671,377,79,737,969,486,37,792,840,841,882,95,205,798,896,473,388,855,140,36,328,373,41,303,959,56,573,969,695,204,34,346,977,693,141,75,649,39,862,150,128,622,879,782,571,405,822,845,707,161,217,595,696,719,106,408,416,888,336,558,770,785,119,590,387,866,72,346,789,966,665,194,429,935,789,239,646,239,889,796,391,282,181,292,304,237,239,886,452,283,621,12,927,204,85,637,935,619,190,578,891,400,119,609,340,909,21,36,165,140,123,723,737,422,445,865,129,104,405,985,9,62,981,926,14,950,785,133,201,538,614,531,984,951,762,715,265,822,102,281,121,418,191,118,646,782,798,411,815,786,357,486,68,67,89,101,908,289,772,607,976,220,220,801,356,350,0,483,874,287,758,117,482,460,195,731,317,209,322,150,986,410,319,629,622,589,998,964,148,392,170,325,577,997,727,359,201,205,854,382,640,473,937,838,987,980,294,702,926,520,264,368,77,941,166,569,607,559,257,620,284,503,629,732,570,557,458,50,780,95,901,98,845,974,77,567,829,742,791,228,149,584,361,268,201,541,841,123,479,51,435,720,307,54,79,122,553,831,250,56,878,222,13,814,252,695,9,791,946,511,758,31,648,534,919,713,421,304,869,436,13,666,401,335,337,604,232,669,756,580,368,154,890,789,309,591,622,361,542,301,869,491,746,260,825,532,584,166,321,360,379,751,100,169,938,15,673,735,828,2,547,682,293,343,593,384,829,841,575,364,78,731,225,370,976,137,251,898,440,278,928,665,297,818,663,323,799,206,154,549,776,212,921,176,525,819,767,298,842,533,167,436,180,483,143,923,103,449,419,238,748,514,865,360,222,306,879,313,873,444,909,309,489,50,51,636,836,372,822,805,541,862,197,287,359,771,558,366,815,602,9,345,847,321,195,680,818,805,81,364,550,776,317,843,503,634,190,512,731,307,673,42,644,612,89,663,569,934,49,707,555,652,739,848,268,585,506,618,419,377,801,693,254,654,292,575,147,157,559,288,439,215,452,478,137,561,309,626,275,347,484,635,276,203,40,962,474,704,219,61,928,504,204,96,959,188,508,731,285,671,671,809,991,607,827,566,980,41,207,843,283,700,487,971,570,483,822,618,709,436,77,543,962,867,931,148,112,427,1,125,284,526,509,452,83,220,657,561,302,109,519,304,837,967,829,333,252,487,906,921,482,305,781,449,697,606,539,727,513,742,135,349,177,923,330,416,40,499,354,505,798,978,35,6,48,906,328,113,743,313,239,260,508,620,845,120,399,360,470,497,720,244,703,763,569,814,922,940,206,386,37,614,906,389,11,177,266,272,838,244,891,205,123,888,540,841,965,322,528,519,346,338,761,855,433,143,238,662,860,256,34,660,862,926,668,23,30,47,844,175,127,368,744,93,397,670,740,502,290,227,981,57,661,48,1000,460,198,594,3,543,447,41,454,216,690,967,277,911,284,813,801,10,55,996,251,502,113,281,682,915,104,18,776,423,461,890,146,689,127,994,103,717,955,228,540,12,104,887,528,313,711,453,986,845,915,765,565,400,300,600,121,415,977,734,925,968,540,400,311,609,171,692,453,659,242,808,763,588,287,317,310,792,450,290,441,53,7,630,96,975,704,773,719", +"782,57,571,616,636,971,496,60,488,554,603,305,214,982,770,835,275,564,878,100,759,263,31,969,266,846,852,355,382,860,752,789,127,134,93,440,280,973,490,321,504,485,285,957,34,932,969,45,618,487,613,497,714,451,859,462,884,330,11,286,921,46,416,678,580,825,558,205,197,702,718,823,685,884,641,902,342,781,546,378,583,281,67,46,241,234,539,692,142,727,416,367,31,274,666,980,655,707,836,241,840,501,408,340,150,782,779,588,118,997,111,809,392,592,545,96,165,315,365,608,850,653,686,738,425,47,61,650,54,952,725,118,407,609,816,365,536,955,408,326,744,108,552,558,650,676,69,414,203,827,979,843,865,376,664,625,841,925,331,320,262,349,586,631,74,627,437,365,79,738,274,300,249,842,564,540,475,901,922,301,762,906,852,70,206,768,412,446,238,687,53,58,781,752,141,737,593,979,83,300,157,596,50,302,733,550,423,288,533,628,817,254,209,555,736,88,649,759,300,706,24,580,969,679,610,225,834,640,43,541,408,480,343,426,809,386,580,508,869,586,893,941,447,857,473,115,672,273,447,102,648,147,946,725,340,51,959,624,827,862,659,240,299,268,667,624,226,669,882,972,301,799,563,435,317,14,541,230,279,458,898,299,380,180,365,300,702,672,321,33,236,344,108,67,683,101,429,379,467,902,721,198,854,195,31,676,809,312,23,875,927,471,587,179,478,333,909,772,160,675,16,706,95,848,754,962,723,994,671,646,356,562,172,23,485,794,40,563,760,799,615,844,900,670,640,363,594,689,332,903,404,768,641,373,43,766,744,376,736,791,157,597,874,975,866,194,723,411,791,297,956,397,595,51,799,222,497,883,788,832,335,332,992,313,698,592,8,193,370,787,495,166,197,30,282,737,948,509,740,255,652,707,130,508,878,950,285,49,474,881,729,952,181,593,818,21,745,539,247,164,763,849,578,180,672,39,943,745,156,816,177,79,425,688,791,538,926,219,31,293,13,364,674,483,0,464,874,936,195,396,824,423,949,938,628,842,483,804,430,761,88,539,67,875,15,820,426,248,112,508,615,518,180,920,232,985,272,656,946,530,208,388,860,840,731,436,862,976,213,681,212,353,783,8,942,431,120,837,950,424,939,552,351,454,257,737,835,304,625,930,599,816,120,196,853,71,915,774,425,415,47,68,485,397,356,370,540,947,929,357,524,991,126,923,20,600,284,137,781,624,160,836,500,890,2,323,921,185,7,599,843,610,571,57,668,11,907,247,340,906,528,429,524,300,650,829,268,71,623,487,683,142,337,87,388,635,606,797,535,226,839,3,250,398,332,438,823,344,652,623,497,316,682,840,642,783,757,89,683,881,338,242,160,384,416,108,205,595,749,10,603,981,575,965,958,247,740,757,519,359,254,729,962,250,631,466,70,340,450,763,750,772,465,464,836,214,516,811,608,67,395,360,71,716,408,999,846,999,544,610,352,177,994,276,748,78,89,946,431,509,419,53,622,50,950,927,675,759,422,258,766,901,479,409,765,877,851,558,200,534,692,363,684,280,948,972,601,342,548,965,569,916,81,767,292,394,162,237,861,617,462,591,622,67,552,539,726,103,3,931,781,342,96,351,351,348,779,177,526,582,897,991,310,737,514,809,826,16,889,714,154,294,920,672,561,326,768,308,237,714,115,323,198,498,430,830,803,697,631,508,166,125,23,603,752,217,842,882,329,388,410,161,481,999,155,501,604,635,962,143,117,859,546,308,688,74,47,6,222,240,409,421,521,72,485,306,316,407,6,242,849,636,301,293,881,862,590,758,971,253,184,247,925,974,930,910,548,770,579,283,197,544,329,271,211,468,574,45,654,317,640,47,155,786,625,661,538,659,260,267,160,963,270,673,154,767,712,867,32,93,557,314,665,611,891,689,276,18,788,144,855,218,876,456,534,7,522,800,586,659,772,834,550,732,277,984,406,295,404,270,749,174,918,362,520,573,58,343,466,805,587,996,896,146,477,894,53,598,309,986,590,907,63,639,987,462,416,344,889,392,834,114,616,373,911,905,198,792,952,575,676,985,486,658,406,648,444,988,188,704,926,798,681,452,687,622,654,34,925,647,334,278,519,940,67,844,384,302,680,973,820,860,521,272,497,847,107,619,800,798,786,245,160,635,730,390,14,848,688,676,940,284,622,831,984,196,295,683,38,836,996,586,759,699,770,47,137,56,780,9,965,647,986,851,262,554,678,840,671,411,775,2,292,197,350,207,941,933,784,796", +"307,300,881,56,479,911,11,55,468,308,219,249,615,754,616,795,889,20,601,184,557,107,376,54,117,943,934,373,885,519,537,194,534,83,119,136,315,851,915,88,180,460,332,401,357,6,164,489,268,369,710,562,335,366,688,880,920,696,827,664,310,363,504,504,770,791,913,599,640,957,468,581,860,670,716,258,307,94,361,224,413,350,889,200,360,279,839,287,990,31,831,56,337,907,12,468,99,294,551,551,165,431,2,276,368,16,49,165,40,377,18,756,516,983,585,556,411,324,642,186,993,412,264,571,756,917,995,106,328,368,937,634,994,954,204,861,820,806,109,313,59,321,201,992,888,657,418,45,42,290,52,359,963,756,262,748,792,162,280,196,885,176,668,605,578,247,915,43,654,694,484,831,671,805,796,98,932,930,963,379,824,855,170,630,346,914,274,181,686,781,518,706,964,195,419,52,934,33,740,207,613,937,260,974,518,98,692,357,175,459,909,433,700,67,391,631,114,343,292,501,922,677,476,589,235,936,734,491,372,208,174,965,995,109,624,383,607,363,56,309,686,613,309,892,406,863,461,582,967,492,539,308,135,535,652,919,297,288,900,882,344,988,495,811,656,169,324,141,652,2,989,363,909,761,291,125,343,236,277,325,420,440,142,26,856,33,656,347,616,368,455,509,702,673,955,996,924,152,977,286,22,647,504,103,998,655,6,305,414,675,320,971,151,510,900,284,538,929,931,788,784,322,653,83,230,879,537,85,137,793,431,291,175,312,244,83,808,131,959,100,876,73,476,448,52,182,893,43,111,668,875,370,382,265,970,702,595,148,629,870,475,114,192,268,749,239,846,102,721,234,864,988,355,221,298,234,852,370,179,246,226,900,930,352,500,534,654,420,835,803,421,756,927,181,109,383,533,390,643,816,866,946,668,302,649,802,124,488,389,116,741,445,436,672,266,551,331,542,872,706,61,969,528,493,570,568,160,984,807,382,655,115,972,910,994,544,415,649,701,322,718,379,663,874,464,0,644,851,595,711,827,319,936,265,974,986,23,529,566,549,777,870,833,552,691,169,900,342,189,387,33,116,410,180,679,726,862,893,643,284,904,82,140,395,332,734,784,222,772,848,777,878,100,222,805,593,84,664,31,500,942,531,714,761,899,461,811,146,776,470,551,21,600,128,201,840,532,132,9,226,460,233,287,925,762,58,749,459,336,484,561,651,357,912,887,300,911,168,420,352,467,907,520,636,494,385,745,613,561,897,651,558,13,681,224,595,675,498,780,577,909,333,337,128,308,854,594,285,23,55,824,389,604,391,4,146,644,300,647,778,290,909,832,255,424,987,618,771,372,794,869,882,995,35,989,707,877,767,243,155,524,807,342,534,710,706,716,188,393,856,639,680,495,980,592,392,393,290,230,925,591,970,237,896,745,641,665,285,138,885,802,532,945,336,751,854,278,506,227,961,495,2,884,691,997,337,229,518,896,17,261,235,44,220,888,458,257,15,962,109,93,247,530,634,625,162,764,814,390,941,241,114,12,67,564,349,620,945,230,889,529,767,261,354,414,310,807,866,585,665,299,940,117,587,275,296,119,568,950,169,179,368,759,874,242,922,112,938,286,551,750,270,10,269,580,668,393,595,553,254,173,890,503,961,319,741,177,287,169,404,920,485,762,681,379,473,781,161,927,409,958,85,15,538,200,465,430,650,167,391,26,301,781,64,401,869,627,958,252,776,802,763,804,438,693,825,336,105,377,747,535,786,471,383,278,306,752,494,54,353,844,777,185,699,171,577,472,561,54,804,491,11,440,289,146,390,316,814,409,964,399,482,21,242,895,753,733,191,273,794,71,849,518,569,230,662,769,20,373,354,374,534,136,201,619,513,628,975,45,923,485,300,980,23,984,608,963,952,436,138,933,515,446,252,833,919,501,27,800,633,282,856,989,1000,447,371,938,574,642,637,809,913,744,129,228,351,213,232,586,464,33,522,96,568,637,191,244,762,419,246,474,768,165,721,439,50,502,912,145,436,671,530,289,105,106,881,994,173,415,685,242,682,864,184,487,853,258,972,554,135,771,648,12,38,469,785,960,362,370,350,728,998,101,58,549,527,364,903,993,163,304,185,724,457,265,588,603,494,684,871,171,801,791,191,683,785,585,267,998,212,791,745,888,791,483,710,912,750,290,667,49,648,228,924,773,500,278,239,791,214,743,556,996,662,602,541,883,200,498,879,167,279,971,55,725,268,136,600,141,98,714,412,547,758,627,618,505,381,777,601", +"217,25,136,840,5,75,736,644,882,765,116,866,806,830,285,476,782,282,181,760,90,810,337,190,569,782,587,63,355,992,269,17,111,776,559,573,45,618,233,411,579,646,652,497,341,935,150,758,900,879,184,331,173,617,541,350,645,377,62,68,395,258,122,476,163,655,442,546,318,156,971,768,553,750,337,677,719,985,430,253,450,631,67,893,23,15,899,879,423,31,120,323,938,365,390,185,245,924,863,4,836,117,711,627,558,43,760,68,692,887,725,786,99,37,133,911,813,735,612,884,924,931,249,146,480,450,865,396,815,336,279,860,699,983,124,881,346,42,27,585,171,621,120,417,318,64,123,892,175,699,739,593,899,522,536,896,824,783,189,478,443,113,271,728,130,218,382,652,323,775,376,162,941,311,315,110,800,103,757,954,768,228,479,651,917,402,126,709,748,230,900,908,438,520,840,261,5,112,42,437,294,64,504,303,662,384,564,292,401,387,879,50,146,594,878,898,92,94,270,212,576,424,758,505,991,248,550,598,633,13,32,541,379,242,386,989,308,630,942,150,930,471,546,521,606,696,470,111,488,141,484,270,724,806,347,614,248,541,297,684,789,403,933,439,209,337,767,420,525,386,474,988,47,198,953,123,672,223,541,866,677,19,16,911,302,904,852,89,445,860,946,719,665,700,1,660,715,867,998,344,707,224,694,791,746,963,799,192,687,716,534,864,286,620,472,790,648,102,770,224,232,949,260,781,984,532,378,672,934,949,748,504,21,530,526,318,264,274,130,10,187,206,566,223,129,17,308,67,242,839,578,481,404,32,765,410,205,664,612,518,539,413,889,26,214,307,327,236,756,631,675,188,569,790,952,533,170,33,254,234,50,214,24,38,614,277,828,252,635,667,537,966,18,970,612,982,891,708,3,829,808,187,896,359,694,862,126,39,51,66,32,600,349,404,148,526,630,256,952,585,25,548,965,941,791,166,739,879,493,535,20,623,5,948,455,376,216,513,784,881,210,739,869,287,874,644,0,243,887,707,355,670,883,133,106,303,488,887,246,440,460,976,831,439,118,5,623,562,499,427,683,869,77,583,919,219,653,75,801,108,423,457,166,239,755,95,575,153,356,817,770,25,869,58,628,299,124,824,823,277,410,392,296,136,944,136,5,501,248,895,549,57,724,957,920,88,74,363,428,990,65,832,291,372,902,447,646,240,852,468,879,737,20,346,45,955,484,457,994,357,860,704,134,11,354,714,103,414,915,661,409,85,706,752,286,40,928,46,545,417,454,115,619,872,218,61,592,148,929,915,382,762,793,914,52,977,278,365,291,677,457,6,491,488,826,662,586,305,703,259,842,211,815,586,179,541,555,797,680,913,997,283,154,996,134,194,44,574,50,110,862,989,575,888,181,851,948,21,897,446,986,52,853,810,937,189,183,127,749,348,107,979,104,666,616,274,588,554,11,8,480,59,812,919,36,870,143,186,335,246,517,357,455,169,657,636,480,284,815,455,523,945,939,961,757,816,391,906,358,615,792,103,960,894,626,132,582,87,515,628,590,295,664,940,559,486,784,845,750,833,621,460,272,287,982,162,831,988,468,393,921,183,267,742,350,177,787,485,332,437,599,43,271,989,358,613,744,880,730,670,67,502,697,314,61,925,108,805,949,964,960,985,325,49,388,604,548,153,84,901,775,731,454,67,807,824,85,623,156,727,990,888,391,428,103,385,914,225,857,753,915,624,935,211,745,136,251,697,702,906,713,546,444,293,859,93,245,826,835,382,518,509,939,924,184,799,957,57,757,470,140,582,500,309,595,818,64,113,287,383,818,339,526,381,484,375,189,863,139,797,484,276,218,80,484,625,116,53,352,537,684,191,546,170,555,192,903,596,550,419,664,372,314,638,59,574,976,149,705,97,234,117,790,52,986,548,347,575,471,834,586,709,332,695,953,867,583,846,360,88,627,150,850,729,992,150,98,75,598,248,580,164,706,560,614,630,194,782,449,353,596,226,900,34,224,435,576,500,245,884,130,582,822,570,415,976,962,243,538,372,713,218,566,533,265,953,969,386,64,878,207,610,45,680,345,57,93,683,826,948,849,900,469,78,890,380,857,423,34,337,689,274,55,732,582,614,881,451,496,224,724,240,544,404,828,80,50,158,868,342,312,201,319,805,621,294,162,510,250,369,828,866,871,907,284,406,299,456,988,881,393,396,324,60,783,8,520,28,143,286,923,451,75,154,956,375,799,383,729,157,709,193,935,16,529,701,757,938,113,487", +"300,764,929,279,507,372,304,75,55,21,700,917,995,347,53,438,111,239,67,948,236,726,941,765,848,4,181,426,856,431,534,71,140,666,730,551,946,170,310,666,823,646,723,954,915,715,917,882,283,180,734,422,57,742,431,167,439,225,749,429,674,600,282,956,516,454,254,228,278,895,911,770,986,744,274,931,216,312,533,160,684,581,676,314,338,883,956,343,394,272,564,678,747,612,838,779,167,421,722,401,206,927,860,687,74,54,728,933,72,30,75,738,25,585,53,352,375,804,9,735,3,814,105,182,981,141,166,179,6,764,709,321,576,880,761,975,651,225,67,668,158,288,187,876,838,942,782,207,707,784,193,862,238,411,412,387,167,431,572,397,998,918,103,962,533,124,691,149,880,770,101,720,972,671,259,36,465,239,320,468,429,987,554,281,3,843,751,315,341,202,447,984,469,770,813,689,819,280,910,870,752,359,512,84,385,197,335,24,641,36,122,969,287,905,854,926,39,85,401,410,653,560,611,126,761,617,792,199,894,145,149,207,29,713,102,689,517,534,585,227,657,581,487,596,107,262,58,707,52,588,514,975,678,421,823,55,255,751,540,607,924,97,647,472,60,464,556,661,765,895,689,188,202,901,111,59,309,508,93,930,880,896,113,70,747,743,610,776,551,305,323,480,312,865,897,71,693,421,798,928,184,939,556,251,150,964,948,246,697,228,165,515,317,116,207,764,845,692,317,987,468,46,220,147,101,242,257,33,686,304,489,946,872,185,624,220,566,19,746,286,721,516,432,59,886,859,128,680,463,192,301,687,542,479,279,505,206,134,345,621,947,345,204,765,230,831,857,253,501,117,353,653,43,928,521,176,309,750,572,529,828,514,28,23,972,890,67,128,123,140,491,737,921,318,591,538,592,716,894,559,115,894,65,855,397,642,918,284,350,202,617,152,916,653,297,757,941,309,43,613,129,960,155,240,656,403,508,482,195,760,218,283,891,823,220,714,665,247,748,986,541,778,983,758,936,851,243,0,273,132,575,545,444,13,957,917,128,842,218,73,640,966,639,127,251,95,334,987,822,368,828,305,165,63,421,614,169,235,41,419,828,802,937,116,789,56,23,963,672,671,798,683,583,312,994,546,585,980,352,313,272,242,460,442,258,884,545,824,66,526,434,805,995,267,946,179,674,450,915,111,682,763,458,319,864,397,562,132,414,261,795,441,809,433,647,114,221,864,68,830,340,250,373,993,984,959,711,509,616,625,749,702,125,917,247,868,896,432,341,691,159,463,126,957,610,516,798,306,571,90,577,266,627,550,991,65,696,215,338,550,145,933,832,974,270,468,618,415,921,789,923,372,42,787,777,725,340,835,889,143,409,269,935,878,485,983,806,685,701,291,127,629,386,784,89,452,733,910,215,160,399,415,503,327,198,198,983,407,335,511,493,295,286,527,415,532,128,402,857,319,684,688,815,480,445,33,954,430,554,885,121,869,530,624,2,55,950,347,84,239,219,197,448,186,160,326,168,24,313,275,36,422,429,696,229,967,788,278,215,74,8,56,425,669,990,341,444,513,902,122,366,582,402,955,410,400,989,241,125,226,977,605,934,325,761,989,741,379,651,638,945,570,256,334,708,751,957,474,911,814,803,722,602,750,571,120,723,49,425,218,332,671,299,2,577,297,213,206,721,437,75,241,55,728,9,456,51,259,679,522,328,934,411,789,986,921,413,210,332,791,309,626,474,194,988,522,529,130,871,633,265,637,616,26,232,587,47,376,12,471,952,179,770,172,636,234,110,284,341,440,250,772,974,945,111,335,562,224,183,63,419,612,571,54,62,536,793,672,529,516,194,992,579,476,571,751,536,817,960,874,957,511,110,692,566,99,470,576,282,440,874,775,56,704,219,192,111,364,169,171,602,505,945,173,883,369,670,53,524,616,846,795,650,542,326,739,734,129,660,639,247,823,723,979,593,456,384,815,638,938,609,288,45,308,938,467,884,330,364,884,89,490,917,429,504,733,844,190,642,567,129,379,181,136,882,651,131,917,305,162,827,185,280,790,836,201,494,249,449,533,947,99,181,176,161,89,731,665,942,27,651,7,959,840,801,122,142,617,32,228,718,938,340,618,686,34,781,831,627,814,294,341,486,985,171,35,27,647,739,846,238,5,557,973,819,422,890,445,367,572,744,25,262,333,655,456,311,161,957,886,911,7,996,302,347,922,302,804,535,204,37,28,661,226,437,131,874,739,989,487,656,878,258,393,360,603,14,188,290,497", +"921,822,603,360,903,893,833,828,957,90,81,643,342,307,328,863,513,124,392,417,31,401,164,333,29,9,150,759,482,249,749,346,94,238,577,512,498,822,207,622,552,736,774,711,969,705,757,410,575,385,656,773,969,763,160,230,144,254,428,398,978,159,580,910,58,874,109,461,248,40,401,537,828,406,440,718,404,269,791,923,446,715,376,104,420,486,77,33,162,424,412,658,232,555,570,893,257,679,695,199,404,426,923,573,592,589,705,431,678,279,975,466,527,968,257,189,67,175,931,822,993,447,87,866,522,430,624,185,714,768,55,250,978,610,916,663,666,979,745,212,100,234,311,684,383,358,515,156,949,185,398,377,644,92,970,206,285,415,508,643,480,35,746,160,113,171,663,287,993,436,431,142,850,953,897,373,886,995,138,704,62,312,546,868,724,431,187,581,702,721,867,665,428,52,183,953,542,273,394,483,722,252,205,232,636,906,56,882,736,158,485,132,717,268,354,216,258,15,965,314,776,613,684,521,846,893,125,585,50,895,962,350,23,995,4,87,879,230,447,670,562,576,344,485,771,234,387,999,191,884,735,982,859,651,659,819,134,893,705,97,909,40,168,436,916,186,878,27,188,997,529,526,113,502,778,230,588,209,296,287,169,836,940,499,911,67,741,893,962,686,546,124,211,973,220,993,607,422,36,254,809,506,907,670,5,631,14,772,27,518,215,13,488,925,135,989,532,83,895,416,558,234,989,257,632,874,23,573,308,593,377,66,153,207,399,562,455,89,22,133,932,866,301,665,645,795,246,914,890,848,943,633,126,433,535,457,549,569,687,479,59,198,721,103,649,432,183,514,837,799,900,26,291,481,398,603,726,839,220,83,166,287,913,638,115,443,650,254,144,763,955,991,459,468,671,694,665,861,718,550,781,879,612,682,600,428,199,640,352,920,213,551,220,183,509,433,583,795,676,25,466,36,964,897,113,222,535,556,832,929,685,178,250,735,27,443,68,109,197,460,234,17,224,117,195,595,887,273,0,640,113,257,734,359,849,616,392,167,369,181,754,28,812,886,493,24,693,302,884,690,225,480,750,30,180,657,392,484,368,809,599,561,207,857,634,367,371,796,82,688,980,720,150,584,308,854,723,249,703,370,116,758,948,28,448,635,880,494,901,324,465,283,176,735,887,236,245,314,913,807,771,922,533,257,674,692,631,759,395,599,447,588,365,572,744,746,983,698,515,124,396,260,163,34,142,855,995,406,786,688,983,109,986,968,986,7,812,501,503,129,948,383,620,968,325,723,398,818,454,395,824,859,368,107,439,522,741,585,931,983,186,785,586,190,857,955,562,256,969,593,439,467,813,111,979,279,771,712,62,952,356,690,757,295,840,821,459,694,174,8,361,479,68,583,789,652,345,93,561,471,433,95,93,475,694,172,629,625,40,430,369,330,66,459,189,887,230,187,489,134,808,175,905,467,265,965,742,242,874,42,428,146,636,929,141,370,515,8,122,85,777,489,762,122,894,186,588,371,207,120,3,234,473,629,443,472,532,171,648,294,786,803,293,679,573,115,511,880,711,98,976,739,499,434,486,472,550,268,961,538,575,864,740,128,791,877,46,599,376,787,357,962,911,60,354,916,932,84,665,675,621,631,989,735,672,122,662,951,300,408,532,655,948,286,855,864,977,872,61,664,32,663,816,521,474,407,760,930,197,679,137,711,813,71,9,488,617,997,789,935,935,533,796,802,508,953,788,127,148,518,126,939,28,225,803,898,252,63,3,242,665,252,886,417,474,992,577,721,203,943,68,123,293,771,255,909,329,864,355,841,431,695,913,693,23,508,120,464,795,568,977,30,472,271,495,74,134,608,701,19,678,306,803,315,863,196,686,48,233,468,499,816,930,290,845,737,438,478,439,188,436,901,515,683,574,473,142,456,766,903,454,322,28,609,827,870,814,270,906,700,491,948,151,577,900,729,953,794,654,516,712,646,806,811,200,380,558,744,170,814,386,104,96,972,718,20,372,716,404,849,647,970,134,778,656,66,894,4,89,291,246,410,69,422,868,203,512,159,227,396,327,503,255,575,453,378,816,808,157,688,438,484,120,216,138,501,531,802,886,517,746,424,507,28,183,175,175,289,251,717,753,250,868,581,806,146,104,284,820,822,594,507,33,607,572,640,63,811,100,623,214,424,617,787,446,636,701,34,503,722,687,829,494,348,812,552,867,97,15,504,399,977,421,78,171,498,468,384,134,804,785,845,666,199,639,671,75,236,199,605", +"699,924,541,881,582,645,818,940,676,896,797,376,454,907,586,968,612,132,420,32,662,701,970,29,912,250,108,41,935,153,690,433,763,476,305,121,696,343,709,516,797,920,525,560,325,142,801,610,250,757,368,240,753,653,559,370,684,640,828,218,776,38,714,924,44,790,973,448,68,6,454,413,355,511,584,170,667,365,337,836,247,467,308,205,650,460,974,1,634,28,829,282,164,666,692,643,982,339,710,760,31,777,38,903,132,707,572,233,623,982,20,314,29,710,396,526,338,660,509,273,860,991,361,160,275,365,11,829,851,66,377,454,104,66,457,803,131,91,443,307,387,409,13,830,203,442,86,778,935,101,87,988,769,163,185,150,28,828,873,909,700,480,757,165,147,979,989,286,17,886,498,937,73,418,151,150,658,955,741,128,621,515,689,237,22,85,248,666,278,144,930,607,5,83,658,31,405,568,280,260,46,646,644,734,503,268,491,104,247,574,128,834,493,478,57,738,48,55,372,429,853,10,542,222,86,361,158,301,167,434,341,559,352,603,743,881,545,525,768,760,758,616,27,476,771,948,222,898,904,61,582,967,579,104,997,510,969,40,465,736,524,590,752,467,450,535,106,520,380,786,399,949,657,739,36,1,122,861,154,295,305,650,51,591,306,367,179,184,959,133,652,136,368,381,501,465,270,174,342,615,233,224,596,553,884,92,322,550,872,990,988,482,727,720,796,610,798,19,67,304,829,773,565,734,114,347,836,964,6,246,609,293,654,775,501,869,355,8,466,551,64,103,530,923,222,978,128,124,574,1000,940,469,222,45,942,987,695,297,387,348,184,537,265,752,146,889,358,563,527,778,845,931,268,504,924,753,487,985,668,909,105,898,720,562,659,601,42,87,983,818,239,102,321,560,593,220,714,312,728,82,23,153,569,917,803,772,432,921,951,971,461,365,751,426,485,436,88,826,165,984,931,639,508,153,453,377,522,91,874,285,882,397,357,581,96,281,275,744,659,682,577,380,714,482,396,711,707,132,640,0,644,651,491,933,168,845,866,419,93,555,108,127,957,795,804,576,632,933,72,205,952,678,383,621,825,249,426,159,911,558,133,783,346,664,169,143,466,436,930,2,508,64,369,520,176,421,148,537,679,68,787,292,784,38,845,367,811,802,480,728,219,999,376,978,115,881,529,91,567,218,583,794,341,12,392,569,854,168,976,425,274,39,296,852,570,936,889,554,17,464,675,955,30,764,405,278,219,517,168,492,394,453,817,220,943,480,873,943,997,156,179,769,563,233,424,402,734,547,512,36,24,547,787,22,887,199,120,727,160,670,965,324,235,302,895,899,55,947,840,214,139,970,177,627,576,902,342,969,611,141,789,88,808,389,780,224,621,529,409,400,292,441,525,60,707,345,741,116,438,785,113,290,984,793,341,988,712,449,629,147,491,932,165,793,209,799,107,616,649,434,959,555,634,699,354,881,847,288,309,886,507,270,273,168,987,874,190,97,210,407,464,266,485,510,12,661,548,523,6,434,570,171,88,377,773,800,38,471,649,782,847,939,952,444,604,824,125,473,667,398,118,62,67,924,614,633,15,375,866,547,48,765,377,499,451,246,956,130,966,494,759,884,200,69,23,172,175,816,266,781,35,396,674,163,624,372,978,876,524,989,321,36,378,94,1,90,387,111,283,974,600,918,954,331,981,507,738,438,11,528,140,521,690,106,374,457,226,27,850,598,939,453,676,563,751,458,176,885,496,927,747,382,884,928,896,750,650,454,725,534,820,617,215,944,957,428,158,370,346,148,496,428,977,498,144,196,341,773,863,406,751,151,667,468,717,434,783,250,712,430,242,648,439,798,932,518,636,984,513,576,248,902,725,821,510,158,931,545,616,565,439,498,601,690,601,973,61,936,751,896,803,395,694,17,753,271,724,108,314,629,614,760,388,672,572,780,319,726,28,816,569,479,754,142,653,765,786,488,121,746,385,132,162,993,435,81,610,390,841,4,86,380,973,500,822,590,106,909,696,730,67,277,232,436,562,909,108,829,717,285,724,234,36,919,606,875,822,222,676,891,42,340,949,940,868,752,730,697,712,14,795,812,368,734,495,619,482,846,764,47,93,348,571,792,205,234,221,761,734,810,145,711,889,321,343,656,654,63,245,241,300,22,135,868,641,469,649,281,467,833,343,15,986,226,63,301,774,278,745,957,895,583,745,700,827,698,228,425,824,230,675,510,926,483,516,207,510,49,624,469,108,473,220,389,633,437,625,878,452,474", +"664,415,608,322,708,46,393,472,962,523,552,830,80,272,148,418,587,854,237,105,587,386,893,140,235,699,327,484,310,479,798,920,234,108,271,319,882,784,536,927,640,528,275,608,606,41,354,677,256,762,38,606,370,669,92,11,776,527,547,907,777,219,893,742,194,791,7,611,529,898,813,596,786,242,437,94,436,22,97,374,900,691,82,953,671,172,451,212,205,281,734,777,198,936,301,434,530,890,383,341,743,494,803,199,945,468,165,655,365,454,630,443,3,484,644,179,322,231,536,559,743,87,914,748,73,402,334,126,382,413,416,766,222,251,829,574,455,754,57,77,699,711,790,460,465,53,650,145,827,621,919,348,777,903,944,756,700,688,78,472,686,816,354,856,938,185,894,927,670,37,215,603,496,780,510,674,919,66,54,759,308,562,495,628,475,694,365,747,745,280,758,976,42,425,838,666,940,481,606,958,134,610,155,226,704,249,510,979,348,450,509,633,432,864,465,64,415,922,866,356,534,173,958,264,373,784,253,152,565,478,340,335,740,456,175,701,821,902,351,891,964,897,440,991,822,646,548,983,161,975,633,641,813,193,684,900,117,430,170,278,187,640,346,686,793,612,365,435,326,433,989,186,355,137,815,223,596,671,948,294,621,784,843,516,344,989,193,126,268,355,486,317,39,677,121,223,970,372,796,442,76,810,548,128,803,385,939,231,89,744,697,914,950,418,639,298,677,436,881,356,696,702,927,77,718,303,56,179,112,197,915,790,175,550,359,672,99,107,958,454,178,78,443,836,415,803,763,686,541,964,841,955,160,903,354,256,976,993,204,131,359,94,499,280,372,940,912,824,847,267,532,634,906,171,448,958,356,155,406,496,670,42,28,565,545,748,936,329,659,698,606,151,285,65,497,84,309,495,657,912,322,459,183,8,428,648,808,366,400,786,585,239,784,89,272,142,814,372,7,314,323,117,14,469,623,65,720,507,285,509,756,63,593,616,129,103,478,465,637,693,762,471,513,460,824,827,355,575,113,644,0,425,713,905,330,179,301,756,670,437,365,795,517,16,261,666,483,922,19,904,611,37,974,694,30,509,206,429,572,158,645,155,744,123,343,257,890,666,894,227,417,619,429,71,460,50,138,310,280,719,457,508,951,678,426,92,678,525,119,42,426,227,80,942,800,827,492,193,834,425,677,594,630,166,679,36,29,68,452,391,43,993,634,392,181,302,522,621,954,231,527,246,162,874,292,507,51,277,228,773,384,463,595,274,118,929,972,689,285,910,408,583,474,823,731,370,352,19,1000,652,891,748,670,457,946,44,486,797,501,420,536,359,93,88,248,161,16,798,191,744,521,171,470,808,113,270,957,344,127,729,104,968,8,289,248,289,265,224,825,569,429,851,715,305,869,306,50,466,461,112,733,205,758,128,484,540,267,971,943,71,929,323,659,345,63,923,264,514,556,757,632,649,23,310,420,467,532,419,240,90,138,988,613,207,514,467,84,682,716,438,306,928,324,80,486,433,160,865,779,752,212,862,179,299,413,159,374,132,853,711,635,985,150,771,549,192,652,636,572,623,950,109,419,40,813,554,839,337,280,900,222,483,30,962,771,403,515,861,52,441,936,389,510,641,740,821,82,286,484,426,479,704,727,699,308,111,871,605,51,710,348,403,810,789,753,542,343,436,599,229,112,507,685,551,599,178,94,425,371,574,499,167,480,58,107,704,574,617,196,676,129,781,556,363,373,956,382,636,352,779,295,655,238,7,740,259,583,796,379,576,348,984,141,608,637,528,759,864,673,220,855,824,68,535,614,373,31,396,509,463,136,912,358,792,608,413,275,150,281,235,391,261,152,925,331,429,917,494,805,755,362,5,390,675,204,480,414,727,879,658,713,81,638,7,449,620,663,865,315,48,50,161,475,80,160,458,507,968,672,409,542,50,599,494,776,179,356,626,782,622,211,180,106,848,329,244,557,798,876,562,960,629,906,970,747,950,670,259,666,181,237,47,753,953,121,524,625,337,664,731,242,981,596,403,950,223,275,610,578,553,127,766,382,303,266,507,153,70,664,439,803,77,850,387,256,381,720,710,238,994,929,843,287,949,904,257,325,890,401,30,327,414,874,438,147,259,150,20,802,186,803,138,386,222,53,699,933,794,426,488,516,523,570,778,564,862,123,450,863,842,695,90,214,554,438,427,517,65,703,574,137,700,301,355,730,788,557,466,387,495,767,569,655,69,884,704,783,152,750,596,175,479,816,53,838,334,613,280,621,298", +"638,526,192,51,988,588,83,291,686,627,261,70,419,5,573,596,75,215,683,936,896,504,714,194,107,235,810,671,228,16,523,377,412,940,3,114,50,44,635,196,771,84,310,849,24,143,808,631,346,958,996,95,632,563,648,147,768,917,878,171,374,167,108,90,842,84,495,970,32,587,453,224,34,971,183,861,403,372,577,108,536,248,964,590,88,52,308,204,31,59,44,428,868,134,791,904,495,602,255,735,289,746,215,569,326,223,377,431,751,96,211,259,32,64,84,307,49,908,997,356,440,907,494,708,861,424,154,708,266,191,738,478,624,188,92,244,345,757,314,998,945,543,604,333,625,196,82,142,375,677,621,968,113,7,825,461,27,908,595,648,348,482,107,105,667,188,696,461,62,421,155,985,849,720,494,498,309,327,875,399,411,369,765,46,195,996,46,250,835,548,757,638,345,266,882,825,881,265,504,519,862,520,834,463,494,43,650,345,461,900,984,55,500,833,615,714,945,233,763,852,444,113,54,767,692,509,645,883,27,161,627,142,478,947,897,631,884,770,609,51,32,960,584,799,595,549,893,571,75,345,713,223,458,208,163,190,660,963,916,869,877,594,243,248,205,969,652,443,496,937,228,966,400,932,922,771,212,721,873,751,745,770,674,464,890,911,442,784,716,241,894,21,563,298,919,139,948,380,989,576,181,348,102,836,918,156,740,13,420,92,607,666,81,758,492,457,452,370,555,810,582,516,46,11,906,681,768,462,537,849,601,347,261,460,950,138,243,889,719,596,140,407,681,71,506,41,554,993,660,293,714,453,479,720,410,635,698,496,71,772,825,873,314,101,837,100,273,173,979,678,241,787,630,660,540,571,462,138,101,311,116,965,354,748,127,890,96,29,743,72,750,292,542,357,917,507,826,334,662,428,876,249,498,989,580,626,914,116,436,956,818,385,196,727,197,241,757,9,887,994,576,597,87,427,765,29,854,492,921,41,818,706,976,93,348,214,925,243,397,72,32,417,730,195,423,319,670,545,257,651,425,0,782,771,246,820,976,490,899,697,447,279,332,434,300,629,644,500,160,842,464,507,998,610,281,653,484,910,961,46,777,667,440,842,827,914,835,20,687,903,380,83,47,16,937,977,377,707,936,999,729,496,705,820,880,801,896,209,756,504,770,626,199,445,524,471,200,902,553,969,253,813,210,519,361,5,176,375,83,149,966,697,487,360,515,481,917,938,248,18,811,905,702,173,890,319,205,960,425,559,354,942,193,116,617,547,15,727,40,777,581,268,383,218,123,568,337,822,648,397,19,591,360,60,436,54,793,550,531,362,649,344,75,631,424,184,639,493,595,907,35,201,953,40,390,600,522,19,518,177,72,851,980,716,32,314,670,860,753,346,556,765,741,870,347,314,746,867,241,901,308,835,960,88,731,219,803,897,752,316,208,271,11,133,153,696,491,129,324,530,416,353,382,275,937,640,666,776,410,989,33,270,115,295,116,663,407,735,590,566,202,194,348,651,720,212,717,967,452,759,503,916,755,840,924,1,467,54,791,509,555,62,692,85,826,194,115,805,969,87,818,350,812,778,110,506,707,855,28,430,578,570,265,835,983,360,115,698,648,171,838,983,534,999,305,585,999,805,450,298,785,6,500,375,148,523,398,479,980,454,379,50,888,429,24,430,968,339,476,485,730,91,503,618,714,2,495,894,223,117,462,78,48,729,2,23,918,762,131,181,369,535,528,743,500,338,345,703,720,14,279,878,349,321,935,720,574,463,428,87,658,894,707,160,70,758,47,721,818,4,433,107,382,337,742,761,137,435,356,344,169,960,15,378,162,339,867,752,858,274,326,485,110,839,100,412,687,447,295,263,673,345,447,873,673,819,927,671,207,710,779,328,368,710,55,528,889,805,765,659,969,44,588,753,417,663,904,930,610,409,678,285,594,449,786,617,96,928,423,188,418,114,901,241,466,202,635,824,487,772,80,24,875,834,382,978,932,410,956,526,416,148,406,713,761,325,329,144,114,780,827,356,370,596,369,657,368,189,890,320,157,380,679,38,527,83,274,361,783,190,237,255,779,980,91,130,535,749,855,84,386,764,144,40,177,248,178,816,387,673,463,803,557,552,758,447,893,552,813,413,683,562,356,15,761,738,305,854,830,731,315,590,94,452,703,527,555,730,631,892,890,19,434,239,540,760,13,96,236,348,260,556,468,553,577,392,146,956,76,453,876,143,465,508,18,690,395,879,552,342,756,814,772,581,427,314,664,568,413,1000", +"862,689,118,34,190,209,161,410,734,549,428,754,980,844,76,620,509,617,27,276,571,103,880,802,968,357,440,616,455,948,877,243,319,181,842,682,969,664,64,441,42,867,23,432,257,419,319,367,46,347,268,594,939,247,146,620,612,662,169,22,982,282,776,49,923,711,657,204,106,294,932,401,792,377,701,581,287,600,534,868,588,362,243,184,359,917,162,975,755,730,602,45,909,282,860,178,720,947,600,405,768,913,126,398,41,16,409,708,177,857,43,498,20,403,654,612,586,53,133,393,225,41,554,119,195,288,295,437,430,501,345,932,261,467,927,25,503,439,672,946,575,563,597,270,418,927,191,187,858,779,226,818,739,657,55,457,745,411,888,622,398,553,360,813,708,521,225,921,695,138,933,462,296,901,892,397,677,165,78,174,414,623,31,209,31,684,60,137,950,453,600,948,809,626,914,85,111,452,568,983,846,173,415,678,761,899,440,97,299,466,141,18,371,123,475,813,826,408,985,741,898,685,871,864,524,884,76,521,376,135,579,342,839,308,650,813,358,546,393,474,605,925,630,186,70,666,203,171,541,78,549,506,778,88,803,696,765,903,350,348,202,959,893,627,396,323,717,64,579,72,309,143,677,588,721,485,478,563,549,477,172,540,713,388,826,659,827,350,727,705,320,221,829,476,46,56,125,385,365,319,187,436,450,314,398,571,724,703,267,875,610,364,144,349,190,819,374,447,137,745,467,64,822,373,21,353,67,585,242,302,752,793,171,647,206,538,714,227,349,42,856,96,184,863,17,14,376,403,924,564,914,292,436,349,693,762,710,304,377,856,627,561,96,725,935,539,22,374,803,193,962,807,525,603,562,975,95,385,920,278,657,849,190,685,664,411,570,268,132,354,10,624,841,768,876,301,207,700,347,343,890,544,404,303,529,850,241,379,308,210,474,302,834,500,681,558,40,661,461,562,230,629,267,328,173,473,94,643,774,33,812,760,459,465,546,854,149,242,486,989,681,455,571,731,949,936,883,444,734,491,713,782,0,491,316,550,702,383,413,197,565,560,382,670,397,645,809,206,682,790,176,546,976,330,151,977,666,197,926,959,743,544,422,242,553,432,803,700,841,6,415,119,812,184,978,164,739,855,507,830,395,609,901,116,291,927,897,515,929,988,630,449,253,582,508,866,912,469,92,996,771,716,509,893,115,632,410,209,834,732,838,715,262,210,933,156,656,823,454,675,363,551,969,517,602,959,543,579,14,993,632,879,247,7,557,7,232,614,418,571,800,582,193,312,928,477,135,745,996,933,4,112,765,472,592,146,541,481,198,668,668,316,968,59,835,645,467,963,646,820,811,693,972,279,151,990,223,627,827,893,191,36,423,839,421,971,533,533,373,52,827,199,820,199,767,177,976,331,202,438,757,21,443,286,237,935,889,796,643,885,505,473,657,815,534,147,270,906,119,504,112,569,132,787,642,526,560,984,89,523,477,201,933,101,841,524,922,236,618,218,894,769,450,859,973,176,864,46,989,657,405,625,460,694,438,4,719,637,637,476,493,275,223,40,216,857,553,645,94,635,390,676,934,776,514,947,429,748,781,905,844,303,800,96,803,506,21,887,502,793,88,6,189,952,519,332,306,677,78,917,636,741,216,617,246,676,952,204,376,141,586,219,596,141,642,12,112,388,178,891,751,325,261,321,627,127,248,252,134,682,581,447,510,545,307,376,797,601,680,573,238,705,349,533,166,465,704,638,55,709,74,535,187,613,787,765,362,287,508,286,879,709,633,205,925,562,68,289,172,631,863,112,145,684,571,945,847,896,876,159,778,756,959,646,241,962,890,132,141,726,54,815,200,602,230,623,328,566,360,797,246,493,2,547,896,720,155,305,79,560,671,647,708,413,414,887,740,710,290,714,506,277,784,708,861,302,479,201,976,352,421,720,346,792,772,293,3,409,127,306,469,221,298,622,428,11,864,626,258,670,135,993,346,439,452,123,26,591,979,302,790,699,291,34,172,696,828,919,784,913,268,207,260,464,328,825,659,432,593,821,306,647,104,614,570,632,420,858,775,661,870,718,436,300,753,668,789,188,592,654,248,356,603,846,132,925,7,8,795,404,895,903,525,50,31,133,649,89,723,275,119,490,908,548,731,225,566,949,122,284,785,73,762,294,707,297,855,377,617,527,286,118,992,751,267,912,327,180,281,421,801,889,579,992,715,635,720,468,646,615,475,513,111,553,248,716,131,637,694,696,871,194,136,926,342,672,67,911,698,948", +"170,858,36,810,983,681,51,912,491,854,759,951,771,213,600,669,178,730,591,696,647,281,498,274,266,954,692,187,288,542,712,644,61,651,960,131,282,491,620,735,432,598,322,352,858,373,590,803,875,124,444,208,784,14,652,757,871,703,28,292,395,159,799,890,987,391,675,628,698,982,185,196,213,76,630,819,816,533,330,494,301,339,144,326,399,240,438,94,478,763,655,889,960,955,747,378,219,942,217,739,667,596,387,165,642,881,481,376,880,384,81,845,873,972,325,884,122,979,85,581,462,132,802,14,434,739,45,397,221,390,919,617,126,885,978,80,20,900,345,575,293,64,394,465,7,962,625,640,996,427,45,571,45,877,883,677,48,567,472,915,565,280,588,21,258,385,271,265,349,998,700,871,585,79,981,669,288,241,456,393,380,859,963,324,602,915,825,834,257,452,419,556,482,269,109,264,699,59,761,656,686,612,279,419,835,428,668,418,42,264,714,499,160,785,864,669,618,106,704,872,428,675,877,265,361,733,532,900,387,397,183,753,105,859,447,210,149,110,44,153,452,493,171,606,349,376,919,911,207,681,375,584,782,629,216,70,207,601,793,463,913,419,985,875,723,119,205,759,656,535,764,7,1000,630,721,74,29,936,737,192,52,907,979,441,765,894,679,242,522,360,768,211,690,130,513,557,664,887,401,478,305,410,992,236,139,8,206,244,92,852,328,714,990,592,449,811,109,406,489,74,777,442,9,544,307,352,62,968,30,452,166,896,69,487,591,492,433,604,700,627,910,916,912,238,298,171,632,651,789,288,806,819,665,872,991,574,628,787,267,412,362,273,534,698,719,834,862,542,552,900,407,176,275,829,942,90,201,926,661,374,839,65,992,310,653,602,976,434,179,322,385,304,654,81,70,101,528,663,938,614,628,39,805,857,150,306,506,800,473,904,237,431,86,814,703,866,465,317,236,195,596,88,108,216,895,574,590,878,604,579,80,219,293,197,638,752,10,328,323,63,343,320,99,317,938,265,133,13,359,933,905,771,491,0,979,458,901,57,246,893,973,525,892,405,8,743,912,319,725,237,924,864,407,769,635,299,199,472,569,926,718,470,64,863,850,846,455,149,512,994,317,641,628,223,156,125,821,779,438,822,86,593,946,277,831,113,807,661,439,729,219,989,86,171,661,349,481,492,26,120,140,501,744,843,900,980,317,19,614,673,774,829,456,366,470,702,69,748,354,458,542,68,487,182,247,940,559,513,487,284,36,181,879,717,39,791,828,679,442,271,886,175,444,119,313,240,242,949,826,67,874,596,178,449,826,901,609,228,383,197,589,914,205,955,166,867,653,273,946,476,339,242,822,945,60,950,296,293,681,417,186,966,511,347,198,882,9,24,135,70,489,805,941,375,973,84,221,782,164,104,780,232,840,209,6,889,708,271,894,795,188,939,612,857,180,917,997,841,201,836,27,771,335,417,867,523,203,412,90,347,375,42,126,660,619,230,956,146,103,879,752,553,832,244,152,802,234,510,535,476,104,580,546,61,584,800,13,318,526,6,410,66,905,12,947,362,605,219,301,347,268,384,4,645,360,221,527,348,616,654,256,129,551,697,246,752,625,537,291,154,896,580,769,498,539,869,599,274,199,25,836,443,344,393,331,690,382,575,615,561,789,754,273,951,94,56,573,351,565,556,616,788,379,261,98,505,615,116,581,696,511,964,488,608,410,29,422,808,880,987,657,356,770,874,359,816,776,779,608,141,524,659,734,390,713,505,354,611,599,860,269,457,497,27,144,291,421,916,960,501,494,876,137,268,821,806,23,258,247,992,701,899,70,261,677,718,426,376,107,58,27,581,568,666,255,677,694,688,991,21,757,956,420,343,716,171,379,51,781,561,105,419,358,662,920,719,972,527,703,518,391,752,778,382,455,620,63,102,404,991,441,884,532,107,792,991,35,657,115,93,186,879,905,797,792,243,117,493,219,831,979,190,723,900,617,479,155,362,463,638,151,973,28,707,925,832,983,670,75,959,792,226,705,422,672,132,280,343,427,627,569,189,1000,597,359,441,673,934,78,96,345,196,735,222,32,26,510,616,329,253,941,249,654,824,247,264,651,226,966,388,44,252,499,962,846,840,925,896,511,932,947,137,914,915,628,959,89,833,152,932,501,262,311,198,672,285,632,524,545,208,801,700,162,762,167,488,773,362,13,838,33,583,342,284,674,445,594,398,157,660,251,769,613,298,786,421,29,585,838,289,413,556,197,129,372,898,562,184,507,417", +"916,224,921,143,55,247,62,479,108,544,522,305,985,812,438,157,542,98,242,482,653,230,424,811,17,275,178,969,92,301,568,26,622,858,873,84,608,418,763,660,829,775,346,271,721,992,560,94,177,477,67,290,88,303,533,795,896,117,221,367,523,13,734,434,425,242,846,522,302,592,977,467,70,930,551,729,521,707,923,977,267,862,484,562,217,554,819,353,885,642,842,353,941,504,925,68,799,402,833,314,946,190,369,192,206,539,8,871,232,669,931,65,429,91,901,797,16,646,34,735,431,503,931,644,911,579,152,151,737,757,390,264,684,795,779,776,495,71,486,530,442,296,89,703,863,90,550,529,426,591,399,455,95,544,60,9,849,933,873,908,223,841,320,786,951,46,571,553,591,33,517,144,811,64,822,650,684,730,677,337,307,172,702,976,423,8,961,239,809,432,759,165,507,93,17,726,921,891,863,223,648,646,908,705,857,332,117,533,777,329,270,820,742,142,742,842,385,598,978,590,841,358,363,593,41,532,210,721,149,399,894,657,943,678,921,805,683,577,590,11,951,648,94,38,886,387,139,548,646,430,330,790,306,937,848,603,94,391,157,378,101,651,692,259,787,598,550,967,917,777,983,416,101,362,138,466,161,490,447,270,67,510,584,290,812,490,854,523,531,973,165,549,975,705,319,9,82,835,142,177,34,664,383,641,658,632,23,466,113,930,64,750,788,13,574,491,590,433,75,126,749,294,576,355,491,871,814,260,437,272,866,696,620,640,216,545,413,853,654,184,62,588,273,621,486,361,443,561,620,841,274,357,194,561,934,273,187,810,311,425,560,325,438,595,303,545,405,7,8,495,646,267,643,317,875,745,324,655,708,425,822,525,819,952,595,489,461,137,636,370,512,740,291,609,773,921,316,25,503,206,723,44,674,838,959,427,33,631,279,631,26,456,953,468,335,300,660,68,847,416,969,831,208,210,851,917,852,715,116,452,726,828,486,511,785,267,907,640,829,79,57,840,957,209,628,974,106,957,849,168,330,246,316,979,0,721,671,98,248,100,764,47,659,918,453,540,633,256,108,827,54,320,981,630,26,491,807,45,503,653,569,131,976,625,397,971,683,132,742,51,794,49,995,729,32,725,214,777,450,321,511,36,218,938,858,287,440,444,523,904,737,419,678,339,126,161,755,365,616,2,717,424,922,876,684,218,677,210,474,300,49,186,316,804,756,256,198,758,78,61,272,763,769,87,662,510,866,795,540,290,507,460,838,346,753,712,449,799,772,367,566,787,655,232,799,681,979,934,380,925,796,752,462,369,179,879,429,194,510,704,100,103,613,928,518,893,728,537,378,944,7,804,240,486,541,742,428,493,530,764,171,744,441,256,409,396,149,110,250,450,700,191,899,854,583,151,525,135,174,537,514,157,690,51,992,367,433,392,210,719,490,472,68,284,970,461,806,554,104,307,669,537,60,468,123,210,670,261,216,5,117,419,378,639,635,15,630,242,470,532,44,983,961,937,210,146,398,321,630,242,271,494,46,473,515,432,532,536,730,190,932,138,246,781,677,367,289,22,300,759,416,712,618,225,912,469,630,878,161,997,277,206,279,196,58,322,352,786,239,173,826,453,72,970,280,999,135,22,969,242,897,684,55,768,409,429,846,517,153,357,155,467,655,689,125,745,864,695,375,651,372,87,251,391,326,641,452,944,37,635,947,884,541,100,60,344,909,972,194,996,34,373,353,129,381,221,159,193,635,892,843,193,676,289,886,779,270,612,566,917,818,495,113,984,125,934,611,725,510,734,42,234,373,543,191,430,583,132,148,711,659,867,936,914,423,861,508,762,900,330,561,436,743,864,896,222,817,457,203,896,452,899,143,562,511,78,762,258,761,446,706,783,186,66,928,602,550,240,39,272,275,325,405,696,443,824,454,367,95,470,345,763,916,843,831,206,308,89,433,718,995,835,806,167,376,259,674,874,929,892,210,535,47,425,408,782,423,901,842,746,120,400,434,196,862,485,187,864,421,964,38,124,261,741,665,21,511,77,463,328,283,511,920,235,580,274,235,587,736,370,393,772,109,854,593,46,547,743,637,485,898,122,612,264,908,728,922,965,114,643,318,695,803,570,346,3,398,178,88,715,284,185,488,329,250,719,476,3,871,685,113,500,310,905,753,113,496,718,504,34,307,676,685,497,72,274,340,945,242,918,97,709,315,914,421,721,181,933,942,677,106,912,535,825,171,707,217,521,57,268,604,856,844,732,867,606,961,976,357,957", +"806,381,715,908,243,154,419,684,990,896,373,431,972,192,195,331,836,61,469,292,620,803,219,687,420,797,707,408,721,326,635,38,516,330,171,880,339,37,28,169,855,950,194,916,145,13,27,898,132,706,647,742,274,393,407,938,790,927,384,48,149,393,807,537,306,294,578,468,23,697,5,20,914,612,175,722,168,257,271,960,780,306,23,618,571,725,738,806,110,838,664,262,313,570,370,70,963,545,532,96,473,749,516,550,19,203,57,517,318,702,537,468,400,134,542,125,921,508,457,13,369,45,634,306,415,517,158,151,75,132,37,477,913,260,324,742,625,998,415,250,465,313,744,985,8,215,609,541,192,202,763,57,692,209,753,940,713,599,703,259,702,409,957,870,778,201,405,240,908,385,785,759,486,177,295,477,979,609,740,203,144,351,745,400,51,991,262,533,357,213,55,874,227,494,108,290,774,667,321,221,942,362,806,445,875,713,277,577,147,96,394,512,95,500,824,48,166,329,350,903,931,192,985,617,49,277,479,340,285,328,706,906,569,954,563,775,363,877,131,64,471,796,222,780,861,287,684,455,104,157,124,482,488,894,518,646,227,609,637,98,291,780,660,918,525,829,336,705,51,573,848,281,901,932,489,137,394,749,463,748,783,896,495,978,452,161,839,584,38,752,47,341,722,756,981,829,166,499,796,529,519,612,995,111,303,541,658,125,473,541,744,149,464,528,525,107,152,409,427,591,608,340,123,114,553,51,787,804,710,2,390,170,241,913,109,404,14,224,336,505,605,719,173,931,352,452,482,519,690,28,46,376,632,565,94,493,946,931,784,419,113,937,268,697,452,399,978,701,312,674,336,694,168,611,62,701,166,538,58,425,921,435,68,932,504,152,926,214,659,471,382,90,520,522,76,515,611,764,185,924,247,169,510,758,845,779,278,407,648,536,136,604,991,397,163,86,6,216,417,318,527,618,856,919,30,50,77,565,207,868,864,289,857,421,807,644,783,120,593,958,713,738,879,322,842,986,303,917,616,845,179,820,550,458,721,0,850,666,101,883,860,41,361,94,577,772,163,166,673,532,925,879,37,411,913,800,206,145,936,902,902,247,584,452,357,89,752,970,13,131,339,944,851,44,962,251,687,674,734,179,212,512,321,472,6,617,780,987,729,399,538,560,517,45,481,318,21,612,790,945,105,719,936,82,166,572,419,781,961,162,759,966,55,277,558,163,747,887,773,835,466,987,411,298,86,776,945,915,563,909,407,991,96,697,729,375,25,898,756,819,39,729,476,369,945,231,180,352,111,36,738,530,988,312,315,579,866,984,849,700,201,534,505,482,678,481,77,119,729,994,365,904,132,723,21,510,242,509,8,534,290,909,430,978,208,282,494,59,213,614,610,965,300,941,178,497,570,875,473,622,520,574,712,136,141,320,725,732,628,202,284,915,491,633,941,248,198,8,113,280,846,360,624,904,251,480,222,483,175,957,753,104,985,994,872,376,625,828,981,660,861,98,713,677,828,673,163,777,895,14,844,55,565,78,51,372,849,209,572,503,126,931,346,638,613,713,431,749,491,503,967,239,562,926,586,792,704,713,655,787,494,51,750,255,424,713,485,621,306,613,715,346,13,545,777,640,30,136,277,624,195,842,628,670,546,452,706,701,492,614,321,84,630,615,111,689,557,636,346,514,260,291,612,95,583,106,798,447,34,12,32,903,734,789,844,668,3,271,493,832,948,146,416,877,106,696,302,791,828,259,21,832,8,990,990,920,174,350,705,89,277,642,216,970,549,486,963,568,603,855,656,110,20,555,455,612,244,600,412,920,67,209,596,715,191,498,534,283,58,171,438,265,498,21,42,22,306,909,965,41,957,845,92,874,984,418,784,516,68,200,465,806,392,428,791,363,199,756,899,199,711,304,380,62,932,100,277,697,684,522,811,681,845,362,393,588,382,270,308,956,981,338,71,23,779,328,806,722,713,880,288,723,445,670,956,363,329,636,192,235,571,505,160,959,908,929,327,285,735,411,746,174,913,849,204,125,270,157,726,350,672,722,670,377,590,164,885,195,925,392,591,670,337,23,798,760,94,578,43,230,762,327,675,200,632,132,984,781,931,708,616,964,322,478,512,957,16,635,19,57,348,982,44,45,929,90,577,411,837,512,236,130,106,223,778,115,612,997,699,280,537,573,2,671,105,47,819,418,452,483,496,147,986,754,758,987,656,90,62,605,700,53,124,318,919,331,347,497,340,710,795,497,416,945,114,662,430,625,822,463", +"721,526,831,482,621,105,496,837,355,12,608,209,855,958,819,781,193,831,630,325,746,994,9,601,108,5,908,160,14,166,197,538,212,418,618,872,501,207,243,96,569,389,41,682,776,617,349,894,31,673,598,364,429,453,859,9,37,951,652,706,933,304,998,327,210,921,447,957,757,105,196,56,126,545,870,328,404,25,462,129,432,489,874,91,756,484,652,903,580,152,125,699,901,26,77,755,841,875,449,8,317,267,696,941,864,873,491,116,986,417,971,989,151,897,920,87,432,688,910,234,155,836,84,99,194,162,1000,664,942,895,929,277,343,729,324,718,536,880,731,631,844,161,558,60,536,790,139,293,162,221,604,894,461,35,74,958,832,617,303,608,951,413,76,104,860,482,46,908,635,136,9,134,297,253,381,748,52,834,149,114,611,747,689,213,846,395,846,940,756,642,598,873,727,901,399,500,432,389,324,2,542,53,377,797,515,839,889,771,947,238,378,167,207,986,974,956,189,702,139,470,14,301,434,714,757,110,206,989,522,236,10,350,259,657,444,306,105,626,43,477,725,44,859,426,121,190,901,410,591,946,935,494,594,642,309,961,708,932,638,916,178,468,464,168,123,694,311,833,688,689,388,297,400,127,841,318,447,49,798,66,449,618,890,533,474,33,612,28,134,424,481,19,365,855,185,157,881,23,634,692,394,276,443,716,850,712,529,183,824,125,540,526,913,903,345,433,356,574,737,319,802,507,448,599,288,914,940,404,986,50,939,945,623,950,313,617,131,963,325,631,890,978,356,358,125,546,741,336,829,262,693,930,261,189,952,818,847,83,695,696,238,323,899,388,3,805,878,405,227,547,652,574,946,915,649,459,496,126,800,875,628,647,473,869,829,5,18,965,789,469,262,614,937,60,714,726,515,839,363,998,625,546,642,148,385,102,269,292,199,681,145,222,161,243,153,628,409,73,290,458,692,952,15,212,802,698,535,759,404,664,611,774,714,644,404,331,734,604,376,196,659,87,21,150,483,23,488,128,392,866,301,976,702,901,671,850,0,109,63,537,332,616,105,132,860,50,271,848,235,266,123,297,1,798,527,85,595,535,308,206,222,723,69,144,725,626,753,461,448,65,858,403,922,908,184,648,286,296,775,471,970,780,367,9,574,307,705,478,781,48,447,760,440,615,914,364,553,780,856,1000,690,104,164,930,171,729,595,881,87,744,104,290,602,139,115,145,733,737,849,419,904,862,911,196,832,249,650,33,208,181,353,98,104,217,115,118,35,974,276,935,663,936,823,274,726,889,565,45,387,476,376,26,894,589,445,819,700,214,422,84,797,820,766,435,287,587,2,366,32,730,121,989,678,42,796,482,809,964,70,340,93,34,655,693,764,745,272,247,355,11,369,77,649,201,417,450,892,426,567,900,665,275,191,30,235,728,413,936,535,659,667,193,78,285,865,197,399,526,858,985,608,778,727,919,352,204,253,927,211,934,577,705,691,746,958,153,557,716,68,683,568,871,765,401,557,806,167,823,333,588,681,53,24,222,881,409,412,111,974,43,39,792,848,739,816,555,584,901,667,981,331,860,746,748,454,86,994,595,762,645,446,124,710,654,259,969,962,281,946,975,872,842,513,913,847,36,479,126,588,749,290,6,1,49,299,146,252,244,896,994,372,891,100,161,15,78,71,101,314,33,582,673,225,733,744,288,652,448,681,358,815,380,45,460,746,515,101,953,55,535,19,695,97,420,447,135,745,701,80,9,271,791,296,656,470,584,111,375,863,546,980,798,135,361,998,700,885,873,24,21,262,468,776,7,373,399,549,444,706,77,532,605,501,147,513,356,569,385,733,541,899,709,514,507,710,931,548,111,274,437,612,726,6,148,731,993,455,904,222,278,88,778,834,268,961,765,255,766,103,730,403,850,760,776,523,85,662,152,771,631,813,850,204,586,150,342,427,219,562,459,889,913,265,958,751,837,849,562,68,285,919,653,745,640,752,711,430,600,922,929,683,921,39,619,214,409,578,807,159,428,781,964,620,455,702,619,708,251,249,162,205,853,351,713,633,3,995,461,159,902,508,280,19,320,728,752,220,933,585,595,79,623,371,98,11,645,251,778,747,635,627,327,305,221,300,613,974,466,453,166,269,867,26,486,521,406,834,176,878,225,530,435,455,929,651,652,958,386,13,40,480,617,400,512,834,173,173,610,234,25,791,950,337,483,81,496,304,965,313,710,43,61,114,852,493,131,759,575,943,435,113,641,520,738,666,782,189,603,28,123", +"100,607,958,932,141,619,372,639,658,168,847,352,710,659,685,552,569,264,347,93,728,9,3,804,286,933,999,790,329,685,789,546,393,882,981,85,875,932,433,792,432,936,635,810,449,518,676,472,898,710,22,122,187,188,17,754,6,625,32,293,657,590,319,90,114,650,726,437,828,128,534,100,729,969,64,59,663,791,852,676,150,624,876,930,569,278,901,625,642,845,754,680,895,679,776,48,682,533,82,307,687,658,26,452,932,954,864,627,26,527,907,668,860,123,457,65,328,222,504,138,846,691,581,264,24,987,671,847,398,914,26,692,865,899,641,842,658,245,106,926,602,532,38,72,299,696,242,210,278,565,408,439,713,86,311,987,850,109,354,582,898,794,294,969,587,689,739,328,850,200,792,815,875,140,670,175,477,753,129,641,681,379,37,833,249,220,15,219,870,164,741,582,605,618,880,807,97,951,887,539,574,456,244,771,235,889,167,959,705,330,187,371,49,184,696,583,904,494,267,273,511,712,449,298,970,304,356,693,285,81,7,881,175,835,208,123,709,34,944,102,282,74,568,557,681,970,930,192,615,939,684,320,19,682,675,396,796,989,768,868,912,904,140,835,815,323,46,504,85,887,687,67,898,470,532,837,835,641,372,149,629,986,807,870,411,734,38,965,325,941,816,362,61,475,465,312,316,475,928,948,583,216,308,160,427,744,866,88,134,407,574,392,740,203,271,864,247,610,556,891,299,706,811,379,444,658,933,504,974,583,279,503,120,686,713,87,191,716,703,769,141,651,390,256,279,24,299,23,509,827,79,749,460,116,996,450,94,557,258,579,839,132,755,334,787,173,985,654,127,358,780,591,588,386,866,554,917,625,769,443,84,523,509,251,221,799,376,77,148,845,293,834,875,396,898,183,495,170,130,907,418,664,962,674,69,961,299,335,989,8,639,543,482,576,869,503,2,202,316,348,409,42,995,240,402,194,45,729,677,974,801,948,420,887,274,273,963,784,793,876,355,563,778,986,804,529,887,842,167,419,756,490,383,57,98,666,109,0,760,282,627,81,555,988,681,471,985,660,925,16,590,380,183,977,920,823,288,58,547,406,693,422,3,97,583,303,243,575,122,25,993,108,675,709,111,955,626,234,603,536,309,75,567,666,864,537,551,553,598,438,213,641,476,918,53,815,997,512,832,794,408,594,970,271,124,582,864,614,518,505,11,726,723,525,981,91,841,628,308,913,323,987,320,485,424,875,985,155,294,249,145,175,360,340,555,495,394,954,626,105,879,43,525,692,412,802,555,938,346,765,96,820,803,16,584,393,831,40,430,724,272,387,278,806,36,570,930,743,649,438,165,261,637,941,370,379,631,414,419,173,751,167,787,622,94,294,211,378,745,332,336,692,151,467,890,151,174,879,575,256,588,428,649,203,444,548,49,192,797,352,595,918,442,610,432,925,537,685,122,309,773,320,148,432,798,155,931,138,654,775,994,126,353,300,491,726,481,258,566,9,73,420,659,934,385,347,347,286,419,242,166,130,538,696,644,913,340,979,148,709,961,943,250,566,123,973,512,215,407,33,23,238,635,665,901,427,252,240,265,842,205,869,713,952,391,632,835,734,849,143,366,568,660,470,56,593,936,587,370,596,907,3,836,396,441,963,498,713,631,89,793,549,676,681,634,540,348,424,397,799,872,759,683,214,361,229,2,447,654,313,939,390,510,443,82,115,739,583,804,10,951,513,856,230,914,882,141,669,900,628,870,646,410,635,493,616,989,619,258,772,459,473,70,800,570,710,795,987,415,617,154,476,70,226,409,331,851,457,793,802,765,212,34,580,440,337,16,547,986,81,596,154,455,307,624,600,178,217,854,26,101,801,934,308,159,617,104,951,32,439,975,151,666,89,562,117,426,335,830,902,993,469,139,189,448,574,167,349,427,345,692,892,747,820,99,305,710,529,534,711,414,798,880,674,528,335,444,823,665,328,383,37,662,948,948,604,561,495,12,701,367,610,753,376,226,930,723,141,851,838,87,380,847,214,848,83,870,720,800,514,902,107,761,690,20,114,670,169,574,32,340,553,191,188,169,451,857,903,299,20,925,656,600,797,341,281,43,578,862,124,815,435,293,50,764,670,131,321,319,928,247,690,183,440,904,403,246,755,401,743,357,879,181,451,358,189,515,492,782,702,843,307,363,246,469,546,600,821,774,501,642,672,948,54,376,874,713,417,531,458,177,175,984,709,755,327,886,212,315,775,614,74,567,608,592,183,321,511,208,411", +"395,119,774,521,25,319,810,560,204,159,401,947,948,136,852,628,923,702,749,623,673,457,89,403,410,542,69,356,587,132,294,601,663,256,177,623,805,881,609,898,988,565,190,805,35,148,314,374,478,142,323,338,737,404,260,60,941,770,469,861,400,770,18,579,387,549,954,741,69,515,897,943,176,719,827,559,981,205,504,338,252,736,430,934,438,546,414,289,61,874,944,685,790,200,13,510,498,313,507,835,247,547,728,974,987,437,72,305,858,929,30,611,314,398,548,137,344,169,11,860,651,439,160,98,816,559,263,220,658,941,209,254,687,769,998,712,407,764,846,219,974,724,464,294,94,144,330,715,943,615,719,262,867,327,86,638,70,385,156,375,662,358,332,152,879,166,300,640,798,981,536,103,26,251,822,573,410,91,48,290,638,263,674,496,333,345,430,948,931,423,138,182,207,68,742,609,992,889,871,436,788,246,935,124,541,775,113,44,78,617,14,617,755,868,403,666,778,795,373,140,816,245,820,762,654,184,954,962,490,485,8,109,104,949,629,759,284,78,571,440,725,822,917,521,193,724,725,520,723,448,295,128,27,371,169,763,361,353,834,190,595,180,859,188,711,45,823,890,336,860,702,43,466,335,819,782,43,675,424,373,318,541,223,7,366,383,340,11,159,619,649,977,493,781,128,307,740,471,20,587,197,871,356,882,311,394,955,577,833,486,701,281,25,297,666,767,741,1,609,956,716,755,943,273,842,35,590,103,789,149,277,400,614,872,72,181,861,286,92,640,523,346,513,440,465,113,218,572,347,899,787,465,562,998,671,762,719,297,842,57,899,833,443,523,295,708,911,315,427,240,989,569,47,650,217,294,733,90,850,644,540,862,651,352,378,739,303,686,833,564,266,135,939,985,309,570,854,906,879,136,635,898,878,827,803,608,388,100,226,194,589,273,585,87,107,529,59,616,17,13,925,799,712,783,751,157,76,167,212,652,444,590,962,774,780,349,155,696,77,389,468,171,12,410,430,566,246,218,369,93,670,899,413,246,248,101,63,760,0,272,828,520,792,384,525,36,666,632,30,364,405,463,562,62,587,328,77,815,637,388,108,333,127,926,695,903,992,80,641,450,495,959,728,761,415,52,84,871,276,331,61,269,12,62,694,716,651,417,305,264,334,687,237,151,797,502,430,400,690,374,367,615,730,68,740,962,272,360,611,233,813,218,904,263,124,823,489,523,168,191,156,510,84,10,110,781,539,40,340,240,905,273,816,834,418,705,242,510,787,494,935,619,930,397,667,502,717,546,996,585,836,729,372,438,64,923,4,749,736,822,532,720,598,394,273,499,887,805,655,666,767,742,430,225,523,519,931,620,411,638,344,355,910,821,919,675,377,178,663,194,918,266,735,724,174,300,457,871,257,118,958,870,216,251,601,251,231,533,377,339,964,45,60,913,894,195,673,448,969,176,422,20,138,67,259,985,430,635,777,180,81,30,507,736,928,88,490,171,860,678,324,999,372,800,137,736,486,141,57,395,63,573,173,442,606,199,387,995,907,996,534,826,186,39,194,149,85,667,909,459,305,389,856,17,752,520,504,719,84,653,429,650,685,21,462,256,725,642,736,912,531,14,635,687,64,117,552,683,648,596,534,252,69,826,806,576,925,530,275,935,285,686,428,306,780,654,869,295,16,291,517,870,431,202,596,590,407,642,37,893,280,452,705,866,496,154,597,8,655,42,405,969,125,669,210,819,355,429,158,61,226,77,825,854,973,694,821,798,806,186,504,253,194,140,996,615,365,160,862,769,727,385,256,148,830,624,594,808,636,499,25,182,901,686,204,262,985,788,700,804,738,508,343,737,497,767,265,725,839,242,314,297,675,439,826,765,237,577,301,388,457,768,614,50,921,626,377,18,546,371,270,690,127,955,310,487,945,107,667,423,739,690,98,515,525,125,632,121,207,927,930,394,629,215,448,1000,176,468,393,607,552,214,731,818,881,746,66,733,190,120,218,657,103,897,88,900,989,525,517,464,669,498,483,621,870,871,435,634,237,929,663,175,471,587,739,956,614,835,558,415,122,658,512,391,297,978,225,725,938,435,961,148,718,980,496,946,852,480,392,547,739,191,11,542,977,575,720,993,883,737,754,228,346,62,166,727,227,339,221,304,706,997,66,58,339,396,838,390,267,508,306,216,264,200,880,122,821,472,724,650,559,701,117,409,464,842,602,437,454,755,620,890,6,486,783,476,578,673,598,969,422,381,613,649,993,676,207,526,379,636", +"800,646,933,535,64,272,953,723,597,342,199,541,213,665,231,693,664,416,650,278,865,973,583,686,995,117,39,29,928,858,809,682,305,491,344,859,108,812,159,118,8,891,968,761,513,624,960,950,849,131,441,266,974,190,628,931,874,189,966,618,559,375,748,886,345,908,711,476,720,40,898,252,798,484,908,209,317,283,347,327,725,170,986,3,88,935,398,2,165,476,56,858,429,845,200,948,617,789,658,193,49,483,868,324,321,658,78,210,976,425,324,251,931,598,22,214,730,454,674,750,246,528,896,973,875,199,478,96,993,130,229,256,995,904,515,311,199,456,203,6,32,902,492,958,810,292,4,698,241,367,684,65,930,456,398,777,675,249,693,776,534,458,748,438,820,150,866,417,239,625,124,819,101,739,73,949,693,772,707,783,904,152,580,942,447,293,408,176,448,540,298,488,488,612,796,749,93,137,189,370,880,279,823,903,905,210,75,733,361,371,314,336,155,377,412,834,725,50,344,335,157,444,272,87,291,704,730,2,792,225,110,167,917,599,181,900,667,999,516,559,265,933,550,354,273,627,398,556,695,903,299,97,699,256,128,528,471,803,835,499,777,520,69,140,662,990,460,875,123,370,251,584,36,505,746,33,855,800,640,381,323,294,622,656,380,160,13,404,798,3,671,316,199,803,317,703,534,771,91,926,90,535,972,460,114,251,173,338,746,459,364,657,716,37,904,935,569,314,879,865,975,190,425,155,124,674,188,214,784,976,836,833,572,402,521,489,243,247,72,742,884,648,247,455,156,671,917,199,101,577,189,232,264,294,586,447,80,124,146,546,760,613,636,589,178,324,482,575,460,944,24,637,799,955,830,419,983,551,706,498,705,238,513,475,82,87,469,357,557,506,885,288,257,129,677,40,134,50,365,567,540,489,882,104,858,559,838,320,303,161,420,222,647,938,725,432,178,854,948,778,960,152,680,640,884,729,277,623,429,835,225,614,530,304,604,112,290,423,988,531,563,75,848,319,761,549,440,73,181,555,437,697,197,893,100,883,537,282,272,0,463,399,354,117,844,469,786,528,801,380,773,195,205,21,319,654,241,688,78,626,591,426,383,445,934,206,958,714,430,747,801,195,979,505,30,726,46,610,705,638,128,700,261,98,234,540,362,193,564,930,142,354,329,102,846,196,658,376,154,848,531,970,713,636,340,506,58,104,332,929,97,558,469,654,195,38,818,994,450,462,22,117,216,669,709,376,628,419,25,11,433,337,493,643,648,237,29,19,197,958,366,498,493,847,215,59,205,35,503,446,180,443,850,464,320,985,801,214,411,122,537,67,84,580,761,235,432,66,401,296,961,201,901,295,796,432,526,838,791,681,682,879,344,500,921,770,113,988,832,173,735,414,62,425,821,856,309,61,597,175,557,477,727,209,558,954,347,232,708,955,445,670,571,63,830,770,732,724,89,800,973,958,919,910,27,846,757,734,624,398,256,13,693,934,975,431,338,270,511,986,756,845,796,446,452,961,650,745,261,538,432,820,774,215,872,53,419,438,849,179,668,396,343,611,579,885,395,302,870,441,700,398,703,318,822,562,826,931,955,838,185,899,502,356,302,224,141,703,841,230,629,913,105,83,714,254,696,625,428,176,151,549,11,247,279,508,775,917,86,596,617,805,534,713,758,838,20,993,563,508,12,65,794,110,580,293,435,7,933,927,375,635,595,517,508,575,942,83,975,846,459,191,768,678,700,721,721,589,208,745,777,410,312,67,536,797,533,902,284,785,602,231,206,360,721,965,711,532,231,334,177,323,412,918,113,971,791,436,321,228,211,699,61,395,29,457,252,220,974,167,238,420,850,768,531,399,616,996,775,214,830,720,448,841,91,420,313,557,460,306,166,525,489,910,361,426,950,28,965,253,947,986,547,378,786,333,442,505,21,155,119,84,833,733,797,730,822,919,468,670,909,591,238,676,541,680,851,555,796,510,576,663,701,656,306,83,395,430,523,875,516,527,396,559,579,162,113,432,427,182,589,476,246,193,247,197,922,106,752,676,184,181,613,929,962,672,310,253,255,819,46,685,802,22,298,565,503,900,560,960,613,205,499,810,48,191,235,561,59,759,780,124,299,474,21,751,77,870,616,924,275,159,329,724,77,55,341,589,540,953,822,156,356,596,463,727,448,248,332,589,645,849,528,155,497,2,260,313,248,652,253,419,826,955,687,386,867,803,586,830,385,72,993,324,156,649,938,258,424,586,463,478,15,159,738,769,46,756,830,420", +"244,544,473,174,537,501,368,704,733,133,675,28,896,156,608,639,93,678,793,289,853,572,57,112,510,687,340,650,78,635,710,986,113,466,361,882,584,274,839,53,924,382,597,330,65,292,774,308,469,146,161,127,687,505,59,422,45,445,677,679,842,958,544,228,283,774,652,760,299,958,82,319,314,91,74,362,611,55,754,858,564,705,158,30,350,666,587,974,234,216,96,186,507,668,16,425,701,260,237,76,588,696,728,517,558,778,199,511,489,891,995,616,52,208,709,150,232,49,385,507,614,796,103,175,145,780,452,913,261,737,435,249,559,486,820,448,630,54,224,496,890,618,19,618,487,747,215,673,676,536,902,194,263,209,430,746,509,410,678,592,998,335,358,836,245,195,299,993,634,528,761,867,389,89,349,203,878,85,60,902,725,594,532,80,779,379,453,263,186,817,910,629,970,927,855,334,841,130,471,725,169,84,709,423,709,942,505,458,749,925,913,596,831,987,81,825,198,917,968,815,469,854,434,309,740,207,583,640,303,57,416,873,122,825,174,27,761,217,76,704,666,834,154,836,56,36,518,93,784,917,583,587,386,233,634,980,130,203,507,527,272,525,194,510,147,154,398,997,255,941,246,240,671,302,26,347,549,144,451,936,7,209,998,9,498,804,822,455,315,254,488,515,337,581,176,183,396,310,529,250,677,552,230,941,801,834,120,973,927,478,536,52,551,686,67,761,40,690,482,729,162,621,701,56,962,487,842,313,566,520,369,197,51,4,384,40,72,497,427,456,651,603,881,330,640,526,190,439,386,451,41,972,69,291,788,790,658,55,749,156,583,37,400,302,865,79,681,921,828,981,608,631,317,661,813,158,748,777,364,532,611,411,469,918,956,279,130,74,968,536,593,519,72,316,514,370,73,859,971,534,956,73,263,950,897,320,214,187,251,725,363,236,157,509,859,483,611,500,654,476,815,152,836,746,398,918,218,447,964,788,59,835,487,966,159,675,836,895,443,760,765,97,517,629,88,777,460,640,754,108,365,447,565,973,764,860,332,627,828,463,0,469,711,191,793,386,466,766,825,756,546,173,533,543,491,82,308,60,929,404,801,89,123,925,5,949,400,104,274,547,669,455,201,257,478,286,363,964,270,244,658,387,873,614,681,987,951,667,982,746,662,890,939,133,780,392,426,835,580,710,528,448,93,10,644,731,17,543,437,415,788,746,972,747,338,634,288,815,316,498,309,991,871,485,477,820,651,835,130,223,969,209,718,514,833,373,856,141,522,367,135,91,412,629,930,310,876,14,113,641,534,980,977,202,895,674,526,540,525,581,475,82,341,856,106,766,279,457,798,595,392,237,199,27,989,577,863,315,955,819,54,640,763,119,878,96,676,286,880,954,96,449,916,682,387,857,131,45,458,813,161,206,148,965,972,432,879,983,591,621,257,580,141,285,356,438,240,62,868,61,729,350,396,583,763,160,967,119,530,407,783,344,678,194,721,447,695,622,708,786,310,362,986,461,211,763,417,526,231,854,532,557,15,124,232,908,285,667,475,676,804,441,469,129,668,311,379,439,502,191,525,64,604,219,221,838,69,670,671,520,519,880,507,982,176,27,857,117,398,345,588,99,838,445,1,319,958,459,438,262,428,253,615,397,374,822,290,839,847,954,972,520,238,480,244,474,596,767,951,487,106,851,536,966,863,307,332,314,298,792,754,404,823,75,824,183,37,143,728,580,605,54,124,791,997,474,342,341,853,578,784,245,444,417,881,305,313,479,935,689,748,115,940,303,582,679,156,367,133,299,991,952,103,376,679,293,45,2,558,350,974,685,614,671,94,644,789,455,891,677,876,271,708,742,158,656,153,59,368,716,859,115,519,482,425,628,499,47,612,559,444,798,582,982,587,527,802,288,748,565,609,584,874,559,497,480,660,399,314,837,952,492,19,189,297,469,614,76,278,142,561,92,217,326,374,784,586,877,654,856,761,782,359,166,952,970,745,573,266,325,29,249,761,321,436,468,607,382,505,536,539,865,282,516,828,212,3,253,443,129,988,78,714,579,11,180,777,395,522,805,612,297,940,453,958,953,544,713,234,565,762,592,922,246,943,412,829,986,760,599,606,909,185,99,473,876,872,555,161,580,242,825,99,824,533,445,712,192,631,192,536,972,199,91,76,566,839,136,46,457,453,36,683,507,468,183,940,720,426,359,981,413,417,421,539,884,702,232,116,690,742,897,677,160,106,733,920,463,621,416,608,990,696,190,905,492,796,136,482,379", +"50,202,588,560,171,367,171,300,88,800,723,442,515,522,585,350,977,830,925,401,320,462,932,509,260,790,662,525,162,789,752,643,168,401,963,929,241,727,903,479,538,799,10,912,34,293,562,795,259,260,223,816,576,566,580,730,681,721,952,503,29,977,812,377,632,846,815,720,571,705,193,675,195,495,905,353,968,573,24,604,219,818,484,353,852,914,210,366,755,339,235,394,518,512,108,12,465,515,396,805,366,912,550,663,315,606,394,915,121,941,930,9,624,512,737,85,36,482,624,120,435,750,293,690,309,582,13,267,388,123,292,682,850,733,672,116,351,749,986,15,552,213,528,265,944,840,789,840,763,809,563,407,47,353,653,876,694,680,534,431,97,786,27,682,141,499,267,317,704,857,722,52,678,89,378,823,563,479,451,703,516,643,170,340,332,375,471,54,464,445,735,295,562,987,552,459,540,656,876,767,89,216,759,108,286,421,142,834,668,204,177,249,651,503,497,831,559,154,385,253,506,778,922,773,687,453,383,384,431,325,881,308,655,870,562,442,375,58,870,782,9,565,547,444,980,72,699,719,612,200,407,308,544,563,842,859,103,313,323,898,141,363,613,146,407,207,124,614,658,606,86,454,499,168,412,749,213,191,162,519,992,430,845,314,411,78,851,623,854,710,712,626,903,548,171,689,427,873,526,18,1000,583,696,861,759,714,989,45,653,939,688,344,943,837,641,936,132,712,877,163,758,357,583,440,424,235,951,741,875,843,235,630,100,557,636,308,179,683,616,623,47,815,294,392,269,894,400,51,989,750,461,839,801,482,489,618,527,744,796,833,420,168,340,83,870,180,674,74,381,770,455,395,632,775,862,517,503,662,4,786,242,298,12,739,202,973,166,414,77,118,434,907,977,694,608,437,232,463,545,942,29,970,581,535,88,237,289,549,353,298,94,80,959,794,972,542,349,402,120,369,5,262,745,156,834,744,730,56,803,467,191,660,757,175,660,465,75,628,572,41,387,251,109,622,539,870,976,966,28,127,795,279,560,525,47,41,616,81,520,399,469,0,39,747,211,339,627,904,519,59,284,727,59,821,368,687,890,189,975,283,695,546,20,50,170,864,608,291,426,676,271,227,83,77,580,111,568,891,259,822,291,447,277,134,273,131,405,355,139,808,253,733,252,198,505,346,859,205,197,749,301,371,547,904,880,680,682,842,596,138,834,497,435,826,218,64,740,3,939,941,411,671,727,47,647,599,416,524,525,846,498,478,677,954,348,936,293,48,439,200,748,86,18,92,743,583,669,616,129,391,628,834,891,353,459,124,876,556,603,968,690,148,862,878,443,607,226,864,114,181,543,731,720,228,448,365,844,114,35,767,882,370,526,186,156,870,804,520,362,57,921,309,155,447,426,290,171,659,693,711,391,254,118,189,405,587,923,519,990,61,695,593,291,724,311,923,920,834,827,645,163,79,900,909,520,936,604,586,190,771,444,649,975,267,961,5,657,340,460,887,830,623,948,476,487,106,850,49,973,4,218,113,212,681,329,823,179,270,18,753,639,454,721,424,832,735,221,794,250,328,349,792,836,600,326,48,154,56,505,645,297,193,847,488,843,701,178,234,435,597,531,553,44,512,170,321,730,195,817,375,655,542,389,226,327,751,180,897,565,453,105,900,193,940,131,973,515,873,771,517,696,472,761,645,863,8,391,200,378,979,17,578,894,720,398,386,16,374,617,269,419,311,723,600,515,766,987,863,39,211,57,202,359,944,407,692,337,239,783,48,369,807,927,18,344,7,966,52,249,619,109,713,61,151,24,886,888,299,350,933,524,631,942,417,153,423,839,532,8,463,995,870,278,94,461,285,846,875,93,93,790,353,442,216,746,794,741,475,443,40,991,620,317,574,84,402,784,149,644,322,190,207,746,738,577,655,263,353,509,160,984,317,790,93,506,781,418,593,869,333,765,642,43,96,16,36,385,753,660,306,826,830,363,108,556,571,628,348,846,690,121,854,976,274,980,859,943,753,14,293,166,141,600,7,389,642,390,438,382,104,553,562,798,376,214,837,74,820,890,10,495,500,87,561,155,121,923,896,628,747,900,634,495,398,924,764,25,144,661,309,505,491,661,269,483,183,885,530,665,179,922,929,852,289,803,361,637,377,348,47,896,195,303,383,746,337,924,4,301,626,836,915,173,627,305,92,991,125,159,663,100,715,571,299,501,260,947,863,938,289,388,341,958,865,262,166,483,834,47,768,333,170,339,920,183,386,511,842,166,666", +"746,365,207,208,714,219,439,499,994,164,134,306,692,97,293,713,978,635,298,34,435,854,746,554,59,854,45,52,9,789,404,700,797,183,800,135,446,735,403,778,801,217,132,313,261,459,790,799,207,921,742,721,968,477,804,991,335,368,656,309,525,284,557,606,406,56,444,995,658,780,153,655,726,234,202,748,869,710,634,323,893,245,99,104,560,889,654,139,370,640,226,769,290,580,13,901,369,667,134,231,882,477,173,978,143,772,981,128,531,642,256,292,235,885,636,786,595,826,276,456,148,702,16,968,148,783,797,949,579,112,50,654,881,648,409,846,951,960,344,520,832,102,998,497,738,222,413,187,916,672,862,538,62,271,897,914,394,656,762,825,593,163,533,302,919,258,796,136,874,852,173,590,669,344,146,752,998,883,9,192,503,116,43,26,625,876,11,349,554,923,228,415,34,666,162,295,277,66,501,553,351,401,128,87,126,278,784,483,528,231,564,957,347,476,598,198,205,544,78,241,947,396,799,334,167,381,951,349,569,887,237,257,195,586,112,655,361,627,31,670,545,65,739,677,363,388,649,162,509,526,500,399,986,562,954,937,807,135,18,386,999,789,409,746,506,153,497,638,803,831,794,362,96,596,213,90,995,14,262,958,867,285,603,424,140,720,184,771,438,826,175,981,177,732,934,523,499,842,639,734,459,281,47,910,108,663,168,103,971,15,359,343,886,482,950,521,702,562,22,7,133,44,639,601,743,391,22,944,873,849,498,311,635,3,903,289,49,435,220,708,618,350,690,118,179,785,801,9,768,285,154,871,183,42,654,916,720,552,174,650,984,156,150,182,930,354,984,657,284,921,150,870,449,332,281,712,334,510,844,930,754,472,963,213,241,844,17,692,124,464,242,55,566,893,821,232,725,793,506,549,822,73,186,664,495,298,877,641,887,354,527,75,104,486,282,261,998,321,222,819,716,410,969,828,389,655,863,128,371,39,347,727,453,864,840,448,245,14,381,149,362,288,962,589,67,833,831,639,812,957,517,332,382,892,659,361,105,555,792,354,711,39,0,714,920,7,558,683,258,775,895,208,591,571,581,515,347,473,551,396,797,677,197,445,904,428,347,664,165,154,961,402,652,870,553,404,242,710,270,370,606,628,339,896,318,731,74,861,31,613,411,101,827,369,832,530,656,840,369,618,175,899,669,274,113,95,275,592,581,515,899,98,502,417,702,771,649,185,20,563,766,816,493,856,986,225,98,474,442,221,613,380,770,416,302,993,71,111,147,820,815,709,879,102,726,179,887,962,354,170,80,12,116,889,952,657,638,497,104,992,550,448,583,392,150,225,819,752,470,564,600,366,9,466,214,633,482,763,82,677,759,147,69,29,736,149,249,624,819,600,255,252,23,985,672,141,289,601,195,609,953,485,926,880,396,496,526,247,61,845,387,596,639,209,569,419,685,261,68,356,807,725,260,746,446,359,96,812,455,674,539,172,720,708,827,914,56,611,765,540,815,133,916,617,412,698,136,546,495,817,713,742,946,13,986,156,116,944,881,897,273,817,486,805,659,345,830,700,441,940,261,376,708,329,345,891,901,903,813,466,337,562,276,984,968,393,810,383,686,473,51,635,779,92,582,1,340,800,398,400,794,359,975,200,978,261,831,359,749,324,559,749,667,766,827,697,767,779,449,434,10,287,107,124,507,848,446,845,906,508,258,88,474,87,527,136,658,178,490,457,497,895,7,479,466,83,539,659,593,224,228,207,99,184,53,705,786,34,250,358,444,9,837,64,827,700,292,777,556,551,306,978,688,467,689,434,7,409,598,566,355,71,280,605,898,161,757,580,877,838,224,847,649,391,176,2,31,892,518,580,229,934,258,385,814,383,939,239,449,206,141,447,675,244,912,699,210,10,392,803,779,244,613,807,300,384,621,541,916,123,726,384,179,807,4,214,897,933,807,628,840,902,807,28,249,567,172,442,514,454,914,136,483,306,120,595,706,874,887,96,694,967,508,882,876,388,81,899,750,602,267,197,589,227,585,931,166,665,789,799,610,948,187,222,185,350,890,654,198,774,215,368,59,218,515,961,996,10,76,272,85,381,286,759,797,303,180,217,94,907,669,350,480,369,61,676,839,491,385,828,188,28,605,386,609,581,36,737,555,912,632,925,895,659,188,987,1000,712,574,603,201,320,484,534,291,106,609,346,427,169,713,396,328,941,532,296,670,981,739,978,662,586,250,419,756,928,555,592,422,825,784,810,321,342,409,561,668,545,803,804", +"500,277,107,277,685,524,698,717,188,413,382,207,364,160,351,400,439,441,923,932,144,197,422,764,912,895,64,529,117,112,784,396,420,178,255,394,249,600,246,872,243,27,406,456,453,640,139,177,770,918,200,31,528,688,504,96,224,417,548,443,162,921,409,18,769,69,187,78,835,440,857,52,9,623,154,685,632,620,522,722,229,922,418,83,91,201,794,870,587,94,121,156,354,270,150,18,617,978,148,266,347,821,589,120,558,134,925,82,857,472,123,70,321,45,716,864,268,307,449,141,929,844,113,7,292,480,876,9,798,648,929,106,127,367,850,443,389,559,913,25,494,100,809,973,773,992,491,15,979,968,423,344,524,789,97,555,548,63,677,585,955,962,561,234,859,968,559,698,699,486,904,87,416,96,923,363,768,910,542,192,590,816,62,550,372,389,955,937,829,137,691,524,546,739,122,884,422,210,928,373,306,573,908,530,115,608,635,786,873,581,666,362,655,17,836,276,224,495,599,360,277,306,231,574,434,230,743,956,78,228,627,152,266,787,746,466,327,838,389,84,509,342,19,988,411,604,401,592,398,762,642,868,745,373,994,651,732,159,865,689,32,772,62,1,619,607,577,560,420,444,428,397,908,458,63,293,980,7,423,309,463,840,512,752,782,994,107,939,157,991,35,110,824,379,170,686,211,281,760,385,907,650,206,888,963,758,379,181,368,407,201,108,868,92,943,882,246,353,760,326,756,971,870,373,512,21,242,572,44,500,153,224,73,458,399,922,545,487,965,414,186,162,195,283,934,564,66,603,999,975,885,886,454,127,40,792,655,348,747,703,965,265,495,951,924,698,584,347,246,396,594,225,785,423,962,614,701,750,873,877,486,657,782,868,249,358,45,143,441,896,707,206,466,852,694,198,559,923,253,209,983,506,777,768,904,974,312,891,169,11,629,672,473,958,329,443,821,457,172,119,328,552,326,32,628,657,386,856,996,58,875,286,519,115,327,434,708,145,201,364,955,300,774,998,875,552,439,127,886,795,16,434,670,405,918,94,132,988,384,117,191,747,714,0,792,989,530,749,863,444,709,183,825,783,467,631,560,613,89,11,205,821,136,662,48,790,979,222,399,566,221,740,100,505,446,403,674,122,208,340,759,826,729,71,999,91,967,28,669,198,715,199,707,355,673,381,70,364,175,373,881,588,358,122,937,5,989,877,39,946,138,900,349,751,38,5,860,709,904,178,17,957,914,597,407,176,515,494,425,890,305,554,382,785,39,360,603,545,168,872,118,844,211,744,145,356,256,295,368,469,585,166,366,929,859,322,581,541,865,937,157,491,16,205,770,174,181,347,823,753,631,141,94,268,389,811,639,30,787,674,449,721,703,837,488,381,167,313,175,585,880,333,890,981,651,630,921,690,928,64,872,510,816,976,602,875,280,553,600,715,759,835,198,630,500,442,474,288,276,706,167,865,216,336,260,584,833,304,648,615,421,623,952,395,698,294,169,375,475,25,29,890,911,202,328,673,533,107,651,784,501,87,987,50,996,701,479,875,182,77,677,520,88,554,226,244,27,301,416,999,402,122,489,336,239,928,43,526,19,295,768,747,145,721,525,770,168,55,132,389,747,201,566,958,906,450,229,474,716,139,606,358,487,439,952,955,440,585,746,671,688,599,721,718,393,819,691,848,546,996,886,259,777,795,248,780,42,567,145,79,324,976,584,494,999,435,752,612,447,994,585,439,885,56,510,29,967,364,634,23,292,453,59,649,326,45,481,383,617,641,908,173,940,26,511,862,683,880,389,620,83,35,811,391,562,35,575,172,642,766,914,347,676,880,767,952,546,903,28,526,545,348,310,273,707,629,946,81,151,872,763,925,503,232,157,503,245,697,555,978,443,108,311,460,711,670,339,957,71,847,372,460,114,46,368,488,956,42,932,399,526,772,202,292,593,161,543,879,757,800,480,892,661,384,35,68,12,511,230,6,385,592,980,608,983,454,924,676,859,308,715,262,704,560,118,769,147,744,903,786,544,328,962,467,43,924,300,499,471,161,77,983,693,332,999,219,746,422,522,526,607,625,565,51,66,415,618,279,666,517,495,30,295,652,882,899,580,233,905,151,665,205,64,419,24,463,414,133,440,60,709,816,762,21,15,127,960,494,591,896,97,422,389,500,657,738,819,749,780,223,335,106,191,188,232,363,516,996,344,300,963,364,666,98,567,349,40,780,673,370,749,657,506,583,334,889,949,328,906,395,84,880,638,246,850,836,912,720,666,772", +"962,556,864,693,820,797,939,614,879,634,672,631,527,951,888,112,471,927,476,152,404,925,584,914,629,686,526,7,948,884,461,510,358,897,569,333,448,288,122,178,198,248,116,894,571,59,564,218,705,457,303,778,375,31,612,713,527,345,140,788,867,576,141,136,676,633,890,725,680,616,976,435,917,866,859,260,667,34,550,412,33,192,501,941,864,686,323,586,843,579,439,457,77,958,714,351,31,322,31,953,185,982,816,939,724,998,772,248,168,981,803,740,150,605,824,950,799,472,175,790,176,853,250,39,270,951,308,59,557,629,694,515,350,881,923,805,835,593,812,325,645,945,739,366,528,798,611,658,532,524,753,186,784,255,791,289,969,622,268,487,69,812,943,214,844,353,434,926,122,321,194,727,139,334,138,239,560,84,287,523,354,840,573,566,33,998,344,991,359,346,938,441,319,578,593,170,228,178,182,190,402,754,844,823,417,523,594,492,258,535,492,277,164,737,431,209,988,840,63,316,616,594,519,877,925,324,803,913,846,935,257,132,54,619,643,438,740,517,927,380,826,615,203,436,217,57,274,969,5,113,575,542,571,176,820,474,84,95,882,112,227,114,577,689,469,75,410,940,981,193,564,562,736,827,232,641,412,468,520,867,583,547,251,339,667,319,563,569,229,772,287,164,615,859,772,796,932,135,738,569,990,111,223,236,143,803,718,726,439,40,252,938,839,370,92,984,307,732,75,519,576,709,672,164,322,939,903,87,824,242,718,589,95,469,981,407,884,230,32,428,911,528,790,232,570,636,481,669,743,213,479,84,351,117,659,339,80,418,434,43,302,527,22,58,171,737,306,794,855,545,571,430,953,795,404,218,658,427,377,526,896,824,264,523,858,129,883,246,766,251,968,854,968,504,555,916,41,98,278,667,551,419,578,672,479,113,520,379,77,980,879,177,222,251,702,174,261,534,426,861,81,356,522,395,783,468,962,221,662,900,81,584,785,21,463,621,676,144,637,486,436,287,3,964,15,691,118,251,493,804,261,300,397,8,453,577,860,681,525,844,793,211,920,792,0,116,10,925,656,766,845,54,895,275,185,59,511,883,491,510,546,79,960,297,20,277,80,947,102,270,224,722,954,499,876,225,814,232,607,999,531,630,782,291,568,537,172,331,609,281,835,553,65,821,760,536,753,427,682,728,349,331,249,205,335,275,243,446,53,896,221,418,10,548,888,935,125,571,24,277,571,648,622,542,533,950,624,195,638,919,679,375,305,686,800,83,967,282,673,735,111,456,794,103,16,215,263,304,164,459,927,94,691,222,464,616,135,166,197,483,911,295,230,204,13,101,930,765,986,313,760,679,184,109,378,501,791,562,41,396,164,202,476,885,922,308,698,869,90,419,327,215,993,892,496,927,45,95,518,344,530,839,311,702,528,407,20,86,650,575,776,41,967,534,130,218,629,286,156,358,299,786,207,168,686,965,639,861,522,254,292,852,525,205,603,996,481,815,99,966,650,544,256,207,437,978,629,154,149,478,785,126,39,617,688,564,449,515,740,360,175,980,245,572,176,504,678,812,323,532,987,666,161,301,649,368,601,426,726,363,451,506,644,61,463,486,4,204,89,417,264,659,11,935,750,314,705,812,811,916,362,225,225,556,168,95,164,484,870,579,365,269,679,196,816,220,353,363,768,419,597,53,243,159,408,63,287,212,175,174,286,613,633,496,662,79,927,53,508,855,553,990,121,115,459,432,857,599,719,824,975,651,632,911,964,40,90,752,428,892,350,793,580,418,322,265,547,488,996,756,371,415,365,178,234,526,920,158,485,817,260,233,472,221,722,761,996,797,447,749,259,572,778,544,162,571,38,244,749,914,894,915,930,151,965,670,695,205,744,416,69,269,760,632,56,236,558,641,234,37,138,993,756,1000,710,111,189,446,903,60,630,558,972,52,968,800,491,125,371,453,874,594,319,851,107,906,999,618,481,239,745,290,926,639,703,7,534,395,947,700,226,309,142,92,206,411,281,603,213,799,259,437,33,919,478,923,254,634,531,645,50,822,916,241,441,288,831,422,427,854,297,164,778,952,921,544,948,144,763,899,268,716,408,931,73,36,175,819,475,917,27,186,696,911,87,978,577,337,678,830,837,742,582,681,416,778,321,321,52,443,155,779,402,862,879,474,954,597,144,457,139,771,382,530,163,185,736,38,540,318,926,388,901,425,295,509,340,187,355,383,543,106,710,20,834,621,180,33,376,652,914,178,398,683,326,777,281,938,82,375", +"753,681,34,95,43,253,370,535,432,517,915,274,415,395,129,318,389,38,953,822,987,338,70,372,209,482,967,196,526,340,443,524,764,885,360,397,744,708,387,641,262,521,220,583,922,644,939,194,782,55,956,340,119,62,524,286,780,946,441,639,872,406,984,798,143,334,744,939,407,438,714,219,378,409,582,387,489,540,85,264,553,718,924,575,650,738,619,880,993,356,410,883,530,32,687,522,49,998,433,54,155,280,938,907,267,964,887,350,301,743,13,243,547,772,430,402,225,787,445,682,951,36,277,906,33,642,542,790,934,817,418,380,495,400,108,518,327,685,182,809,254,386,853,345,327,368,112,802,616,207,995,593,86,712,121,264,487,807,99,752,560,874,501,622,597,60,16,195,546,171,805,437,660,828,216,193,206,801,602,210,94,806,659,834,168,803,26,345,95,779,365,687,841,181,650,523,24,400,778,214,217,860,548,649,920,402,147,885,732,952,92,596,862,426,333,395,803,878,558,107,370,866,774,178,130,888,600,773,731,578,981,967,412,246,702,111,115,959,84,863,866,119,250,150,320,19,185,744,55,735,61,808,83,473,127,633,404,999,391,614,107,883,796,487,65,557,937,597,506,400,204,206,353,392,158,440,650,826,414,960,742,201,554,33,104,194,638,772,94,372,167,794,438,292,241,473,478,563,664,921,780,82,649,706,238,754,513,908,471,797,172,567,89,918,483,430,602,219,733,901,612,766,582,304,374,867,995,134,444,79,989,935,971,234,841,206,775,961,408,216,353,279,533,242,775,890,446,574,399,283,788,135,876,347,4,203,759,103,560,518,180,211,712,503,254,853,290,996,829,437,991,681,259,505,498,406,477,323,747,36,796,508,90,18,979,697,719,252,784,386,595,814,632,479,526,935,314,579,774,874,120,689,65,113,393,454,784,562,488,280,894,591,946,497,527,869,536,856,474,657,643,209,119,841,832,349,484,367,365,380,452,969,774,931,849,200,341,254,457,374,258,43,214,148,820,169,5,95,24,576,666,629,645,743,540,772,50,471,36,469,386,339,7,989,116,0,859,526,768,16,714,44,478,780,981,805,815,951,542,928,487,350,238,206,153,111,406,86,812,267,18,799,466,942,579,530,159,128,144,684,989,398,38,782,530,862,919,104,89,702,772,449,347,930,887,539,816,482,494,607,691,141,893,11,440,334,738,496,822,593,63,379,201,984,600,805,594,114,282,953,10,674,63,248,487,269,478,822,693,560,456,950,137,719,265,487,334,234,299,825,657,43,486,254,821,91,848,386,219,729,803,692,919,379,722,327,904,564,647,952,863,614,431,576,321,13,827,701,847,348,694,988,256,146,619,39,462,206,274,186,225,124,247,112,260,770,128,411,685,851,765,854,691,376,541,386,586,309,234,100,104,102,388,258,291,123,592,688,189,759,118,722,507,220,569,485,37,309,518,400,650,500,400,716,519,597,390,469,414,832,328,986,900,250,629,203,787,473,178,796,609,267,495,515,922,161,329,234,189,575,311,867,255,891,993,797,776,652,642,783,329,512,106,840,326,949,731,243,932,544,890,287,172,156,333,413,1000,346,82,855,205,42,899,542,263,168,370,923,970,357,355,885,632,933,228,568,352,377,154,941,41,3,427,11,704,295,481,755,452,252,760,98,979,626,998,940,407,104,217,119,963,293,803,196,727,71,634,70,955,287,785,412,359,294,632,926,542,464,143,912,694,50,363,346,656,775,245,338,255,552,648,684,304,858,750,858,434,170,430,698,577,121,513,463,272,375,104,796,399,89,137,120,728,200,967,450,67,338,919,722,475,333,722,486,291,391,703,421,788,68,599,195,629,359,74,754,159,840,298,700,283,797,315,839,800,971,873,521,524,207,199,807,648,867,119,67,316,466,682,516,367,858,934,802,154,985,806,172,743,453,802,579,200,860,564,778,975,91,74,573,999,811,180,986,137,301,487,299,177,728,198,750,924,603,736,280,381,939,63,491,33,485,290,353,647,679,568,633,648,195,807,192,194,912,329,621,936,183,158,246,886,577,63,638,712,587,254,831,562,9,79,429,532,517,806,173,861,552,42,223,473,247,776,424,701,929,960,731,113,968,987,809,74,478,888,414,98,270,937,973,980,999,131,443,180,537,415,533,379,103,591,432,745,460,119,556,537,1,106,688,263,616,873,461,734,653,956,75,229,725,448,320,170,969,738,100,987,248,54,584,680,563,307,616,513,205,470,493,875,364,450,495,321,153,720,286,1,952,959,714", +"547,668,556,928,323,589,711,190,637,524,721,337,155,629,948,692,221,809,666,406,606,777,926,842,943,794,446,461,348,637,894,601,23,803,467,963,985,606,368,577,632,254,845,725,1,23,992,523,581,657,564,463,895,137,417,498,451,346,808,720,383,209,209,138,457,787,165,228,351,920,131,71,817,971,925,273,46,875,154,902,619,169,220,342,105,29,486,625,49,576,663,578,706,399,688,796,34,952,109,947,886,578,448,455,567,936,789,261,30,38,817,491,543,525,434,122,97,749,537,843,366,253,980,921,744,884,672,482,73,191,11,12,808,498,159,992,202,193,806,528,428,305,740,7,479,261,58,313,291,738,516,93,495,561,349,875,466,448,257,710,625,328,979,235,559,277,238,810,380,207,438,226,347,625,197,229,627,827,127,24,140,320,916,782,189,99,447,724,913,411,407,512,263,278,914,790,667,94,21,672,448,329,313,295,522,559,461,194,933,745,886,814,857,775,625,322,155,55,660,233,433,591,73,272,830,20,517,937,557,815,852,771,152,915,919,534,265,125,977,916,631,460,718,887,48,8,59,925,589,110,152,130,455,759,131,595,184,353,907,896,186,102,360,687,948,623,791,677,284,275,581,904,860,321,65,188,613,97,573,878,801,156,975,371,385,817,692,70,663,272,712,772,132,711,99,983,80,672,763,953,806,816,754,675,502,985,343,435,965,426,787,694,567,365,32,19,170,889,633,547,404,481,871,301,359,773,910,295,121,38,376,662,793,605,786,268,973,372,72,304,854,920,511,100,442,233,246,334,75,103,126,812,634,969,448,489,165,338,829,379,201,325,473,857,376,574,81,963,260,430,578,599,48,106,819,64,95,453,125,257,515,771,280,997,237,825,711,838,276,644,950,14,349,131,540,92,440,955,800,35,290,791,408,900,792,280,955,186,374,936,326,484,41,2,88,845,506,283,221,719,109,238,396,525,310,850,259,724,710,85,772,868,510,883,996,767,608,626,510,856,532,973,349,392,426,900,623,334,693,632,483,644,809,912,633,163,271,985,666,786,466,627,558,530,10,859,0,577,478,76,268,269,377,982,383,699,418,231,263,107,505,336,260,177,555,428,973,270,901,911,90,82,252,553,366,155,647,44,492,966,59,221,331,838,335,713,226,431,720,131,97,650,476,15,335,454,553,251,370,202,928,801,337,875,454,80,5,707,746,346,844,642,107,893,42,42,507,714,273,398,232,274,819,633,617,423,164,839,774,344,81,890,249,783,396,903,12,794,103,867,424,11,76,296,432,566,704,297,230,676,872,720,408,606,759,89,32,23,113,524,868,912,317,464,94,639,560,102,375,388,675,578,833,434,857,599,88,779,602,611,746,224,28,434,525,890,632,832,397,399,811,660,431,6,723,257,47,277,222,178,488,860,895,948,619,372,317,675,384,753,56,750,212,9,527,780,268,656,105,490,92,613,907,569,286,280,233,886,862,109,121,982,402,252,24,799,501,387,127,122,526,988,584,250,692,497,294,726,974,806,809,997,813,254,326,22,328,297,538,656,352,867,265,385,638,877,204,353,743,541,208,394,274,656,810,111,987,105,152,34,892,72,296,911,595,375,891,140,250,941,307,156,963,827,781,243,105,965,700,292,659,361,164,87,8,710,397,553,994,986,941,980,666,663,275,418,474,375,468,996,794,215,81,21,35,925,873,380,476,231,128,296,432,679,918,408,509,328,823,287,142,836,933,741,988,484,503,444,96,397,366,484,235,407,88,228,88,842,362,140,820,576,880,185,429,233,126,939,581,472,543,369,209,428,299,543,828,454,627,428,440,652,828,752,273,242,294,41,303,187,252,204,696,137,891,481,71,775,560,771,946,415,60,62,324,22,813,604,283,433,561,149,358,280,586,52,793,783,954,590,407,104,26,787,411,654,35,11,812,628,492,324,251,955,302,752,800,604,358,374,911,790,306,607,714,678,527,342,171,850,292,326,965,711,283,209,478,723,561,949,436,690,967,645,726,387,61,491,50,582,347,386,405,717,945,67,620,899,132,745,761,560,23,878,164,639,623,433,663,298,586,517,253,820,828,366,419,114,543,187,454,70,800,704,986,744,3,347,387,945,171,226,121,389,921,155,518,667,166,478,885,884,262,185,882,893,309,236,622,843,638,399,678,959,91,184,175,902,724,873,488,159,352,39,38,753,331,219,205,271,478,390,415,300,515,497,106,669,40,919,201,507,401,483,768,897,485,849,901,569,85,751,183,506,944,377,874,226,925,64", +"889,350,490,461,800,699,482,302,23,198,762,130,801,62,469,181,301,540,549,720,591,366,544,654,654,835,564,174,979,958,53,48,404,772,194,370,335,387,481,525,714,144,217,875,828,176,803,432,702,810,698,689,635,835,664,142,952,459,420,866,738,734,434,747,75,22,660,23,763,841,756,195,653,517,681,658,830,260,215,370,37,944,980,821,475,575,441,874,387,315,456,161,89,124,356,397,440,667,947,888,366,857,832,493,70,703,319,141,681,241,993,507,109,456,224,563,650,131,460,343,176,699,550,316,234,626,601,193,26,458,664,395,762,59,759,476,273,806,470,480,592,907,784,588,965,367,818,729,813,576,360,737,998,323,500,585,842,889,122,854,427,850,958,67,154,658,977,381,906,62,495,476,767,839,615,581,386,12,52,86,434,328,36,502,932,515,930,580,661,753,493,662,315,711,833,844,109,513,414,504,497,416,357,177,243,212,455,512,975,260,720,402,946,677,821,210,667,112,354,809,637,851,139,69,944,670,833,983,980,122,911,613,449,722,745,582,857,77,877,796,502,766,902,884,57,401,329,604,499,944,496,780,774,204,802,837,827,97,646,686,323,929,823,254,770,170,60,332,118,103,847,385,197,192,835,517,484,447,634,343,552,256,152,754,385,179,136,342,913,486,633,218,767,762,430,917,923,660,75,468,546,268,513,937,415,297,970,309,792,555,499,451,603,163,976,621,764,117,634,385,144,208,81,174,955,400,76,851,966,345,268,331,378,876,394,25,751,403,801,198,967,743,931,838,803,98,622,12,113,275,492,672,740,181,622,205,17,55,654,279,401,646,246,643,580,181,984,818,24,366,510,763,836,993,118,829,636,775,975,167,590,912,51,920,726,117,525,191,74,48,397,986,342,640,226,927,540,25,424,507,938,258,975,338,746,533,827,86,949,275,646,913,230,668,196,195,993,804,243,264,407,491,179,803,642,534,745,527,671,798,676,564,644,280,624,477,541,983,514,594,837,998,873,170,248,342,562,987,302,933,922,500,206,319,256,166,848,660,632,528,766,904,683,749,925,526,577,0,947,743,529,765,944,868,94,709,348,94,819,17,444,556,719,421,492,360,517,759,301,529,635,162,963,840,868,104,62,606,521,283,839,122,522,577,252,879,596,680,210,876,858,833,271,555,135,687,823,511,610,673,97,456,161,149,76,404,561,923,818,626,681,800,380,937,697,520,443,942,403,376,366,965,241,495,891,675,300,141,87,639,246,298,158,274,108,936,743,224,781,263,472,383,514,967,17,960,485,171,638,270,44,6,661,833,711,396,112,843,510,343,808,197,461,559,500,179,337,809,945,852,676,470,293,641,812,161,553,74,451,665,906,376,559,904,277,135,590,340,773,269,471,880,898,104,568,925,513,601,159,952,350,856,694,464,238,745,988,365,701,535,435,892,125,76,582,69,152,91,83,903,705,28,507,444,44,20,904,174,426,346,235,474,90,591,120,23,406,222,156,481,488,360,169,663,566,907,50,102,255,852,848,823,653,10,152,88,487,446,525,739,181,683,412,415,2,368,438,899,120,624,840,560,607,258,546,260,796,428,987,998,740,918,627,769,579,616,743,72,869,173,194,921,704,763,501,163,36,390,998,50,616,39,646,189,362,664,830,393,907,651,633,470,333,251,3,23,439,611,271,853,39,880,719,553,334,442,863,125,875,58,426,549,375,711,61,469,147,241,642,786,479,662,658,434,317,271,431,859,950,149,312,676,228,521,389,968,953,924,935,327,430,163,303,422,550,270,285,436,261,990,264,575,633,186,444,782,371,482,151,980,839,486,288,840,908,277,835,856,573,285,511,797,435,710,386,680,724,108,396,160,286,894,281,572,180,223,653,644,509,111,888,666,494,424,701,577,628,847,716,833,593,262,571,129,762,606,298,646,202,20,311,768,867,412,212,39,160,568,489,471,291,339,221,322,609,690,749,205,984,462,408,699,463,568,168,632,504,695,372,982,770,927,240,97,970,712,72,796,1000,205,321,835,377,275,47,215,331,890,972,190,776,858,211,994,659,831,32,801,630,594,191,282,715,761,69,677,968,106,245,451,307,208,352,154,101,26,101,346,509,1,751,902,753,42,168,392,320,426,877,920,819,854,797,722,355,364,868,828,250,827,895,901,703,467,725,622,494,159,348,515,560,642,349,531,630,683,142,526,615,830,979,612,829,767,836,818,700,819,659,766,161,392,45,384,365,126,312,420,333,655,102,898,572,111,233,562,126,135,990,75", +"199,496,890,747,535,340,106,770,527,33,488,265,586,957,477,95,623,66,104,785,322,624,319,824,154,999,530,612,107,394,696,269,17,334,798,311,303,200,4,846,824,88,729,878,775,109,684,823,250,269,819,748,371,178,53,794,945,87,558,62,32,727,234,857,890,610,112,82,650,317,148,995,805,157,481,745,321,217,317,902,872,852,219,687,355,601,105,835,708,686,175,148,992,383,720,510,325,269,251,758,930,321,767,97,31,468,648,702,858,177,496,354,834,102,97,668,957,372,328,603,572,367,462,227,437,624,152,104,937,378,699,984,661,189,107,919,818,40,824,264,191,606,290,734,207,80,711,261,854,374,713,234,571,248,798,200,151,735,738,684,23,469,553,467,584,190,637,363,709,949,695,479,687,725,205,271,811,714,965,688,790,254,121,99,383,873,482,563,410,216,171,53,224,374,790,882,426,670,187,104,767,168,70,778,632,134,13,302,932,170,866,993,186,146,29,770,283,114,946,776,953,824,677,678,425,110,475,979,203,961,699,817,19,848,561,916,195,984,509,627,359,552,966,697,338,613,770,509,330,910,639,552,693,302,535,446,712,843,201,361,915,726,737,868,708,715,981,43,721,4,630,251,28,897,647,551,604,74,118,504,458,992,270,700,98,465,847,592,898,227,41,915,651,415,476,583,658,209,830,727,280,778,492,924,610,118,998,72,227,29,284,344,253,739,784,827,748,271,227,722,681,591,190,240,284,244,674,626,369,178,864,592,62,833,834,385,79,954,850,263,483,260,536,761,716,631,826,847,209,888,845,281,78,897,568,999,372,271,835,614,985,177,247,252,701,844,579,634,970,384,57,725,395,438,276,216,419,354,722,621,30,681,749,949,90,124,317,401,320,289,592,311,508,190,965,2,987,845,772,323,421,21,56,72,348,109,701,37,1000,851,642,633,457,69,423,794,342,261,52,733,922,410,725,616,416,507,914,435,255,162,361,899,921,686,179,865,181,733,180,313,837,22,995,325,112,189,499,822,884,72,19,160,682,725,108,673,235,925,30,801,825,519,258,863,656,768,478,947,0,343,506,891,981,618,911,48,682,195,440,72,421,813,331,208,410,209,280,995,265,285,58,331,908,137,304,45,422,763,32,852,473,492,924,371,706,212,518,72,950,536,531,24,608,832,541,572,742,748,377,93,796,889,31,107,487,7,180,376,981,33,873,329,678,99,269,401,476,888,328,667,629,26,921,413,825,512,127,800,79,849,717,281,957,169,679,889,142,421,280,601,900,537,340,243,978,156,952,556,267,124,728,866,824,493,187,994,140,109,135,784,854,869,257,203,561,886,34,849,474,377,852,244,368,393,81,829,178,7,817,453,286,505,667,303,153,936,548,203,630,430,375,157,146,324,715,259,597,614,929,339,112,7,155,423,789,366,491,435,205,484,321,832,978,754,41,91,979,75,883,377,676,720,666,816,770,828,332,504,910,134,737,459,400,455,829,945,434,791,125,14,570,128,660,341,986,592,630,916,392,860,428,829,333,373,570,347,847,208,855,785,716,867,561,66,523,26,406,918,409,922,158,347,429,565,715,527,614,239,126,92,41,189,261,138,859,927,104,126,13,701,466,473,839,896,736,532,589,211,97,52,361,274,619,201,634,233,646,640,718,404,218,43,844,494,366,356,109,991,613,861,884,488,457,291,190,628,604,176,809,378,824,602,454,569,800,944,854,718,779,662,181,460,641,72,146,705,834,651,684,815,70,59,492,336,954,650,489,653,414,936,359,539,729,512,772,579,389,812,411,643,637,518,629,647,858,526,278,723,794,290,894,72,143,830,352,549,982,291,698,678,607,147,128,304,365,135,260,425,902,700,744,463,506,597,302,259,4,772,982,463,782,323,969,222,71,202,829,650,751,997,411,342,601,168,886,974,672,582,86,750,844,689,700,411,983,608,672,635,192,267,814,808,733,775,733,518,509,981,519,90,990,634,553,780,383,182,729,625,148,279,656,703,396,640,424,977,568,764,625,91,712,268,42,565,656,797,429,90,887,341,103,585,380,519,900,266,105,567,726,547,592,813,845,957,846,647,44,932,699,638,313,417,599,184,110,947,23,669,423,152,311,371,731,929,718,376,355,516,70,855,116,210,548,444,520,886,71,704,45,157,113,239,662,164,175,622,318,299,914,8,953,130,364,135,490,650,397,898,672,97,254,259,406,985,709,765,769,281,349,312,387,11,828,194,597,891,430,297,982,909,994,493,630,14,7,135,966,51,646,905", +"743,113,874,762,249,421,925,874,699,193,497,246,939,688,650,30,159,72,629,98,985,299,265,427,52,120,4,561,932,433,550,598,872,154,769,254,997,244,185,293,679,586,181,412,464,381,149,138,521,104,794,587,165,106,597,979,620,379,18,748,37,987,955,925,192,814,910,379,177,717,793,455,273,808,530,353,212,304,143,69,846,786,983,809,566,65,164,597,626,679,112,196,813,986,281,823,377,429,629,100,417,239,606,515,829,807,372,184,513,554,635,935,9,946,570,465,125,794,703,810,504,483,823,413,184,449,853,72,38,110,651,323,177,700,964,172,60,143,244,251,883,108,527,408,815,385,658,830,918,21,947,299,144,987,524,331,439,959,832,878,290,594,180,934,760,755,861,158,984,81,176,83,561,43,863,860,395,832,663,808,528,497,53,629,782,317,612,668,529,497,45,953,932,95,271,886,198,326,151,119,255,623,6,398,387,164,960,221,446,113,67,123,395,283,25,152,523,786,799,461,418,844,70,215,636,827,949,255,917,322,629,959,897,424,955,508,12,107,523,396,543,384,53,21,728,317,33,266,658,277,423,432,791,377,768,657,889,940,500,438,705,509,77,801,225,771,100,664,540,370,844,455,2,263,505,900,320,883,583,320,500,566,310,980,594,410,164,903,304,698,670,943,464,787,839,198,268,906,391,949,853,143,540,18,15,478,631,502,914,699,601,992,4,949,423,275,755,719,248,59,618,545,418,198,194,186,124,628,896,530,320,888,579,583,187,683,923,874,543,164,362,878,689,17,963,768,655,383,762,283,223,704,6,851,176,39,609,797,81,513,326,460,106,723,345,233,946,735,534,428,868,524,974,214,829,245,359,566,705,407,647,894,778,150,497,361,928,238,655,211,875,822,647,455,300,821,105,68,745,999,226,568,424,444,734,419,721,674,739,707,491,715,472,137,34,268,786,379,706,148,791,506,146,803,207,352,474,217,855,588,263,893,463,170,42,192,471,326,586,117,391,345,202,577,508,387,427,368,690,205,904,842,790,237,827,532,266,16,364,380,756,59,775,444,766,16,76,743,343,0,635,162,631,364,981,807,184,84,881,389,515,200,852,55,446,713,607,865,762,539,277,236,438,274,940,459,996,248,182,318,555,739,590,302,118,469,759,454,37,267,531,572,630,43,432,94,383,136,828,678,708,568,383,199,662,241,395,979,589,936,830,573,921,961,997,613,448,76,689,657,232,57,175,625,266,235,178,468,799,447,268,981,187,632,454,153,204,949,891,247,579,428,31,425,525,516,650,701,219,563,825,467,278,49,473,320,608,605,576,369,918,251,279,269,248,566,969,538,567,690,195,472,942,751,814,921,653,825,591,985,81,569,484,930,310,295,584,530,320,979,235,191,197,859,555,109,114,349,288,375,228,582,787,433,30,795,784,583,524,905,438,780,240,847,853,645,796,775,131,625,780,227,788,894,490,661,368,429,98,319,698,688,906,137,215,242,154,532,13,663,710,553,773,436,746,104,195,294,416,760,453,686,701,830,157,189,684,441,113,718,671,412,551,711,670,62,470,219,502,866,182,431,144,918,686,865,610,702,58,481,172,567,720,130,295,484,737,497,85,647,910,997,927,907,5,9,158,75,823,579,669,990,778,443,462,58,368,151,906,666,208,424,904,866,630,901,869,501,472,35,370,903,834,665,318,126,388,247,916,957,200,925,797,606,160,72,595,941,75,915,754,894,547,74,836,183,211,463,34,957,427,319,7,463,277,415,600,970,536,814,331,153,245,965,794,438,80,937,90,574,344,750,813,795,20,835,985,455,583,915,220,354,208,407,803,545,870,591,477,843,418,933,909,732,270,708,483,732,274,94,463,960,190,285,310,887,239,438,106,47,500,546,788,932,719,171,141,201,361,811,986,809,139,406,535,251,819,889,368,128,345,738,205,216,19,576,902,674,233,968,977,836,129,509,47,856,422,735,439,494,420,96,932,520,81,778,713,456,382,412,630,26,75,923,296,188,954,63,469,576,639,858,803,269,214,898,351,185,698,122,364,449,416,664,56,905,225,115,512,266,981,887,400,663,240,162,189,249,93,241,213,549,703,367,516,166,106,117,333,343,872,643,146,511,816,779,77,928,599,10,814,712,77,685,264,330,660,170,639,748,830,360,22,837,944,983,418,534,136,569,728,29,550,50,826,799,303,391,277,457,466,885,976,747,864,663,416,34,468,408,987,266,355,106,330,114,298,731,296,626,398,303,232,568,250,498,512,256,210,710", +"611,14,642,718,92,192,562,740,195,514,103,287,529,78,898,620,423,236,185,476,74,708,498,625,351,18,552,1,406,184,835,445,874,355,957,271,173,484,535,37,898,544,825,54,68,43,474,370,6,533,698,899,7,618,606,653,158,404,415,583,814,425,788,683,73,682,713,685,282,464,621,153,585,399,75,632,796,549,523,533,282,92,895,522,369,447,64,717,146,841,934,93,852,412,692,36,651,86,558,37,631,503,641,801,710,491,371,611,290,613,373,75,11,950,86,890,735,189,55,116,747,316,86,184,759,690,953,456,9,98,805,850,241,914,123,299,403,719,282,729,692,945,506,631,415,725,922,838,200,610,257,97,44,593,370,849,2,956,350,201,47,693,805,478,856,821,40,502,461,515,617,956,11,65,862,208,486,855,298,601,917,600,619,75,523,848,148,982,586,426,944,965,19,883,343,782,218,898,163,774,48,77,965,916,725,654,717,359,466,685,635,287,164,990,412,783,913,225,147,939,979,582,312,996,755,636,4,700,379,577,844,106,32,47,741,790,578,966,251,61,63,617,552,320,219,77,996,736,532,51,687,840,150,332,990,887,912,998,312,80,741,715,729,126,388,930,815,626,970,815,416,518,401,135,546,560,988,796,614,323,413,616,248,377,923,393,918,92,271,135,701,186,428,270,746,979,871,950,635,395,973,884,296,816,361,165,214,513,82,924,64,873,71,258,881,231,289,354,648,235,971,612,142,634,383,391,562,432,916,933,698,157,659,678,438,509,157,409,949,740,937,128,264,138,793,397,847,906,595,567,262,236,652,635,386,416,465,915,608,93,277,835,138,699,348,666,380,893,85,604,921,419,979,280,25,267,408,247,168,979,333,250,920,333,755,950,203,623,436,528,84,764,45,924,53,800,97,171,212,23,487,260,106,964,107,524,821,462,636,790,112,659,637,323,613,778,418,332,388,732,938,845,390,161,425,909,565,747,702,712,569,43,373,607,71,170,662,626,593,152,150,871,254,997,615,33,683,828,225,952,611,464,176,924,54,925,123,590,405,773,546,284,895,709,845,714,268,529,506,635,0,616,765,740,224,285,898,13,80,845,991,309,21,683,851,547,371,642,93,958,146,727,638,874,760,888,1,374,926,569,407,369,102,617,785,928,604,969,58,26,472,207,761,151,513,251,139,763,350,612,136,597,14,746,22,851,657,835,303,985,334,613,314,326,404,809,38,243,522,620,919,873,544,402,747,655,406,595,263,484,816,603,64,116,680,630,112,979,845,274,727,600,9,537,601,496,147,449,245,813,636,859,819,747,353,404,843,34,898,68,847,798,56,636,664,377,303,338,320,715,99,887,800,421,61,604,530,771,49,638,766,148,302,649,130,273,558,129,967,787,192,617,986,771,727,588,85,901,13,862,344,939,161,527,856,244,51,439,402,646,450,117,484,987,532,363,750,171,933,514,523,73,316,643,984,611,78,219,803,735,352,49,93,87,987,823,462,850,791,39,123,489,77,247,601,421,446,761,906,605,854,321,13,763,147,892,182,338,751,782,913,611,87,372,421,244,429,564,633,172,325,270,6,238,885,715,682,591,808,459,223,44,714,178,299,140,93,216,283,387,665,338,145,342,392,465,863,768,589,359,914,444,503,33,956,124,920,132,554,586,91,973,933,90,937,453,876,163,54,644,921,276,533,821,824,967,358,889,512,574,189,619,255,669,397,884,502,6,384,782,151,663,254,555,766,22,708,613,1,411,847,587,436,41,254,718,986,383,641,26,2,122,433,663,753,9,792,524,275,260,371,885,848,859,611,774,54,560,338,870,550,254,789,412,243,623,271,349,289,529,825,248,511,587,724,656,349,742,914,209,911,789,94,691,952,480,257,283,93,612,790,773,629,288,886,217,343,422,989,38,926,132,37,584,696,356,831,99,813,50,188,971,452,910,59,701,383,499,10,325,858,770,705,273,628,833,848,121,443,587,162,541,149,619,696,91,42,524,881,447,878,933,560,295,953,178,704,891,625,403,404,520,863,148,573,74,556,186,116,628,780,401,797,233,536,862,364,854,888,569,832,470,857,612,283,292,934,496,417,44,266,753,480,210,488,217,145,915,799,958,884,310,353,149,269,706,723,224,282,3,909,511,410,559,231,822,80,622,667,541,994,250,903,26,698,79,23,750,228,325,255,726,97,606,939,923,749,718,11,838,606,836,729,238,324,433,561,312,55,744,67,284,352,321,569,510,674,21,531,388,794,334,737,907,266,709,780,316,630,621", +"357,914,256,635,178,999,341,459,214,909,69,983,88,299,983,46,780,558,153,542,387,523,326,808,411,160,170,415,107,443,310,496,459,42,986,885,520,923,625,19,166,609,315,145,332,142,404,868,784,883,173,816,31,901,624,273,654,787,906,505,833,846,916,465,548,504,96,637,413,184,753,77,650,58,277,196,808,224,816,653,971,33,137,143,51,604,99,198,30,819,977,971,18,959,747,207,530,214,521,282,424,885,415,236,144,411,345,701,785,370,939,993,660,794,150,176,411,47,36,535,132,655,840,799,555,289,403,796,214,255,720,479,963,217,579,434,106,956,661,787,856,991,451,395,656,305,351,278,631,439,228,608,611,765,672,969,242,886,161,122,621,674,299,604,811,353,667,682,296,893,783,366,363,438,95,856,624,42,521,851,212,501,154,402,728,358,842,256,767,681,513,370,136,409,356,304,194,590,73,941,741,775,854,105,174,358,576,34,165,744,532,298,220,984,586,116,670,755,268,800,797,550,254,307,154,316,990,291,568,201,336,170,98,33,825,452,461,380,481,943,947,971,633,30,550,917,556,750,239,545,309,23,778,370,887,266,125,505,93,323,74,319,448,726,480,265,332,645,602,475,435,849,183,244,224,511,564,125,263,582,965,911,313,825,502,473,972,353,839,581,938,419,993,536,731,807,366,3,339,5,642,823,436,550,549,781,61,851,299,239,128,81,293,74,763,190,530,885,907,535,381,536,976,543,257,582,679,688,640,815,996,343,76,678,36,913,951,56,353,118,47,442,84,715,32,732,304,604,123,785,453,237,605,990,232,397,559,66,772,613,304,440,35,348,834,666,934,315,765,870,568,249,375,11,562,738,628,941,505,489,711,249,84,236,351,883,641,884,113,273,578,962,210,524,554,188,640,696,856,598,959,232,87,655,377,947,311,3,170,844,599,804,429,807,537,625,911,545,693,447,508,129,225,485,732,225,155,26,86,204,879,455,309,83,418,136,925,970,967,169,702,950,735,727,518,116,869,305,480,678,37,507,546,864,320,879,297,380,463,195,173,727,208,183,54,44,269,765,891,162,616,0,237,302,501,367,799,838,100,874,331,690,888,265,371,518,630,712,980,505,334,429,787,7,139,476,793,682,618,567,938,80,975,905,665,605,374,690,301,671,260,653,496,504,1000,486,618,927,161,391,352,609,646,409,216,248,451,704,983,215,995,821,342,249,98,372,997,321,614,291,495,442,948,284,409,477,159,26,227,743,263,967,763,638,889,595,647,574,333,903,621,923,731,684,734,620,562,88,515,276,861,450,376,17,468,783,664,484,814,866,534,318,13,701,12,38,711,72,144,995,628,18,906,473,638,369,8,367,92,348,419,593,128,449,700,247,974,864,461,506,622,179,532,892,865,476,816,338,376,490,906,228,557,218,893,402,918,657,329,351,182,111,517,864,726,109,694,384,836,978,548,233,484,139,80,742,52,433,628,893,57,408,372,691,877,192,903,540,149,437,759,429,787,407,649,110,881,993,904,694,378,998,94,877,215,537,138,97,994,926,156,706,278,257,231,662,86,641,304,776,467,174,866,261,872,726,572,105,949,331,174,602,728,702,515,827,958,466,910,518,262,295,514,999,878,282,663,532,74,451,690,523,734,308,822,499,663,451,8,302,552,88,912,72,384,994,100,753,331,51,693,102,407,586,946,256,611,491,176,50,557,489,57,960,793,714,777,561,983,5,128,36,413,683,831,557,78,875,154,382,74,239,747,644,287,220,510,340,481,731,321,723,606,245,94,722,104,416,571,831,975,51,798,460,890,979,100,980,853,633,803,788,841,204,635,264,751,223,744,424,426,484,245,332,883,425,698,728,291,114,982,842,817,439,796,147,606,156,909,757,183,897,730,934,800,113,715,420,315,636,346,689,940,865,38,823,761,878,353,231,138,185,702,371,214,697,545,548,487,991,838,939,765,870,91,602,684,470,859,384,974,860,465,581,380,390,885,768,772,934,674,950,284,709,26,136,224,328,236,992,773,923,268,556,448,63,409,634,611,572,743,31,330,313,538,825,595,989,118,356,153,124,834,8,782,748,17,369,289,467,543,621,114,773,57,101,970,337,251,784,792,181,569,287,980,628,816,50,460,719,29,601,986,976,713,150,722,680,555,49,938,74,528,827,184,348,712,412,1000,567,361,907,961,236,642,668,795,531,661,938,479,800,102,133,170,464,183,511,113,678,495,390,452,967,729,19,665,111,438,934,806,554,561,623,945,770,728,245,164,839", +"952,813,945,225,146,53,529,430,941,285,325,457,612,668,178,124,892,893,355,830,939,754,449,231,660,274,169,182,59,901,291,37,499,231,759,520,10,732,827,351,705,552,937,826,874,36,159,806,18,851,583,666,805,515,549,978,749,650,194,851,489,131,137,529,574,312,832,264,516,808,921,288,53,910,767,729,797,467,395,454,7,861,173,422,427,513,652,480,89,758,717,524,976,930,947,223,174,52,94,149,185,651,679,474,341,840,468,876,814,674,83,993,763,76,976,289,810,93,515,412,354,647,799,550,573,895,63,152,360,452,787,847,480,544,277,374,962,71,583,733,72,881,974,888,991,554,477,230,4,590,402,947,907,536,502,257,904,117,665,847,41,532,65,557,963,328,434,725,822,239,141,684,223,229,744,530,217,379,742,133,304,379,692,69,517,741,902,282,468,23,807,171,972,151,346,154,349,791,964,182,349,101,562,287,267,977,966,396,693,804,109,216,183,183,319,515,361,618,782,828,139,149,878,469,186,529,718,831,385,550,516,551,891,219,414,331,4,434,909,160,426,49,365,824,892,622,237,405,980,419,317,514,645,44,430,172,906,857,94,699,199,800,407,525,363,585,409,595,941,572,406,269,162,619,792,442,621,772,715,740,805,469,51,174,397,665,347,291,185,527,929,974,769,631,169,614,249,826,98,613,222,336,121,572,782,738,198,863,56,295,918,80,845,384,237,409,925,432,253,518,121,168,545,74,418,727,304,162,245,425,213,28,48,388,629,763,189,858,496,553,22,720,605,224,623,107,468,875,49,732,594,823,964,551,816,492,134,546,330,161,509,996,310,548,480,319,126,585,391,365,893,23,550,74,685,772,343,427,767,998,259,815,409,84,358,529,855,600,785,999,444,169,388,521,721,935,465,90,217,947,293,546,223,40,971,644,788,30,739,878,733,950,874,178,46,471,178,881,825,943,500,898,18,855,717,177,196,304,251,409,403,301,80,356,923,577,131,790,580,764,218,251,743,359,180,410,77,165,750,383,974,998,976,407,981,37,1,183,562,205,533,59,591,825,895,478,377,944,981,631,765,237,0,418,214,446,129,919,203,104,9,99,705,75,687,476,184,184,46,513,254,460,609,82,70,293,526,596,109,55,98,377,273,557,311,111,84,316,763,862,729,886,748,789,340,133,979,541,68,94,281,838,98,500,60,343,416,219,666,38,58,211,879,138,479,23,563,290,735,40,162,826,898,333,294,432,612,751,476,103,354,920,709,871,57,411,399,228,11,147,73,854,574,692,237,239,553,632,94,977,906,101,392,726,246,218,957,553,478,820,302,200,411,377,901,433,330,861,417,165,115,883,893,674,17,227,961,168,908,973,786,621,512,935,527,607,501,722,777,862,722,120,410,655,183,925,255,571,616,446,76,922,98,401,727,115,968,272,138,486,100,570,187,947,107,897,168,229,959,277,51,570,961,177,778,284,978,942,419,232,24,818,992,675,538,783,585,148,968,12,680,386,477,275,170,847,927,532,684,756,869,857,805,613,737,14,456,960,2,278,347,72,171,264,722,630,170,972,541,909,122,274,574,818,891,734,134,892,764,458,799,95,97,922,894,182,872,818,63,527,800,894,873,545,78,266,94,996,405,384,488,165,129,194,779,878,468,765,587,922,385,212,328,906,400,934,770,208,665,196,661,350,919,465,194,809,399,223,267,686,572,152,84,7,843,336,973,114,687,464,880,242,368,791,13,623,994,562,240,186,971,783,426,822,519,933,810,454,172,896,583,291,488,253,241,117,341,713,479,679,414,247,571,126,359,374,745,811,773,920,224,298,254,175,607,199,797,644,805,386,577,651,31,303,715,191,85,522,203,700,613,193,838,232,656,95,414,568,277,662,36,234,288,51,499,500,372,465,556,916,642,471,448,589,757,913,260,997,667,559,29,20,906,938,374,34,8,808,642,556,498,269,657,783,705,70,344,752,999,401,503,598,277,861,642,664,706,975,98,968,376,433,676,806,450,234,353,866,770,979,228,157,460,55,501,277,34,241,43,587,735,594,900,592,856,153,34,599,211,83,334,16,984,869,659,733,950,713,913,847,130,500,738,335,396,299,924,62,990,15,283,689,30,399,82,592,618,77,712,762,136,91,358,361,957,121,198,573,474,307,455,786,943,348,81,275,738,707,85,615,183,582,881,354,837,792,807,690,951,683,854,275,792,434,461,497,722,166,463,857,914,517,830,860,952,997,370,891,716,472,578,727,988,327,267,555,722,96,842,758", +"781,974,701,458,125,339,829,217,756,608,282,568,731,803,465,840,408,515,701,807,660,986,507,168,642,855,408,129,861,821,704,279,624,463,257,301,881,80,837,7,380,938,518,114,174,542,63,193,893,944,358,986,51,890,645,806,643,334,365,376,788,253,739,739,815,581,409,57,159,290,100,447,604,741,19,903,308,864,802,655,309,85,470,726,71,300,745,324,617,568,844,805,336,220,37,971,162,805,219,220,240,336,449,5,198,269,373,190,547,322,845,719,156,917,300,554,115,760,115,438,359,764,714,311,628,707,451,872,55,744,846,621,211,869,104,397,892,359,372,484,952,934,87,615,732,123,422,4,437,983,633,182,815,489,870,776,180,897,600,960,592,549,25,111,227,679,92,203,595,708,334,474,489,147,552,170,303,663,378,615,12,589,564,156,774,391,937,460,438,380,803,65,816,210,269,740,101,618,449,305,839,727,20,710,102,440,376,957,279,154,590,782,332,784,519,467,256,401,643,671,374,898,390,26,754,187,861,738,388,162,935,10,939,601,271,654,870,806,301,865,207,133,913,5,854,42,557,160,633,185,380,483,768,18,523,952,156,197,596,312,550,251,152,494,77,722,63,999,944,615,626,627,233,811,189,702,831,166,264,737,828,445,745,845,122,382,955,824,272,335,75,326,77,44,519,924,995,689,324,758,336,103,773,592,214,596,838,38,589,601,283,496,245,312,142,417,735,726,508,802,859,153,963,319,164,746,503,400,451,454,684,942,552,607,722,608,700,68,512,79,341,821,327,814,991,575,324,854,150,56,217,507,258,559,267,649,122,585,732,607,332,339,40,413,615,455,811,992,468,944,114,20,559,845,592,248,301,392,58,348,219,191,584,41,902,240,498,75,2,344,760,499,217,612,652,406,630,9,114,279,679,164,875,637,305,279,23,553,476,246,108,194,814,847,683,504,653,533,222,837,828,489,857,966,658,847,328,224,407,136,127,735,797,651,217,285,705,70,856,850,215,950,363,201,920,180,583,63,30,621,694,610,330,769,630,411,798,977,62,21,543,821,571,783,275,780,982,868,618,364,740,302,418,0,828,386,27,151,851,976,689,271,36,387,24,539,3,972,935,571,732,205,686,937,797,273,119,329,198,730,458,937,24,32,626,568,338,465,78,130,991,413,281,910,5,303,513,159,113,626,324,837,766,111,797,241,826,920,886,18,551,170,875,54,214,794,796,824,772,231,308,737,392,493,355,846,5,230,582,400,183,111,464,976,476,751,707,427,335,575,997,238,571,5,298,177,872,51,549,193,776,964,120,818,403,173,809,98,58,526,798,799,564,842,894,321,496,409,930,190,858,919,586,300,696,163,555,785,969,525,270,582,554,312,53,146,472,1,48,783,378,923,442,557,733,343,656,93,902,833,176,727,444,797,803,844,378,32,438,811,490,931,866,766,392,452,481,591,229,942,305,931,921,4,670,859,737,382,642,221,423,852,362,14,713,483,951,402,27,56,552,868,669,490,716,508,69,796,133,547,964,403,539,626,273,852,307,360,11,383,62,666,672,57,399,803,72,628,296,516,491,444,976,40,919,512,187,749,267,463,528,523,670,238,617,436,787,25,440,92,431,418,753,327,580,380,322,809,864,802,858,890,768,698,73,499,412,867,301,188,329,427,416,834,204,202,94,849,20,336,517,975,712,984,521,765,29,293,822,718,102,431,344,110,17,669,728,248,167,49,652,250,331,394,365,121,638,109,723,599,314,201,790,991,685,540,35,92,725,960,188,926,806,785,757,990,974,785,416,854,728,311,466,186,719,854,188,783,357,868,973,507,851,20,682,718,707,785,872,198,299,411,584,925,177,569,458,850,764,693,705,181,114,570,502,648,789,87,178,920,844,547,720,601,800,363,427,579,795,153,112,816,797,352,521,105,225,47,605,42,184,445,112,880,624,84,272,107,168,651,167,353,830,299,805,37,189,62,990,852,398,176,20,157,786,156,554,159,652,893,141,355,547,994,181,634,71,225,514,426,140,627,963,8,501,184,92,791,331,188,64,572,485,396,992,952,184,343,653,280,973,759,975,222,477,402,966,136,378,407,529,745,566,54,34,147,882,920,139,485,365,447,342,463,738,580,125,701,329,96,211,8,168,234,476,612,961,226,312,860,928,144,533,193,460,146,817,207,498,216,524,567,302,298,606,378,368,728,955,567,630,635,461,99,158,47,506,993,48,955,540,422,57,625,167,225,611,451,795,156,992,765,937,317,690,398,761,313,381,927", +"899,528,214,617,77,250,260,242,230,755,550,370,246,426,947,961,656,978,403,146,84,346,291,792,739,119,482,876,793,699,560,210,718,912,31,240,488,613,232,229,664,205,539,574,474,61,228,943,249,671,133,709,587,934,753,931,425,551,883,266,15,393,596,32,612,16,417,726,487,50,247,349,51,369,835,891,747,153,580,96,113,313,684,23,730,279,19,664,771,25,341,687,722,669,296,397,137,368,331,978,886,453,9,773,954,613,347,320,835,480,248,789,428,248,337,836,687,698,548,697,794,882,669,491,575,320,217,712,443,364,279,865,820,215,624,508,625,437,612,517,686,458,944,518,285,677,409,227,236,522,866,204,993,942,380,330,325,584,597,448,775,913,770,508,963,710,166,657,778,169,493,207,624,291,148,756,747,44,412,974,319,774,151,837,274,231,657,701,215,203,434,875,499,300,169,118,200,70,254,611,805,202,949,770,874,730,970,336,471,980,587,665,266,534,970,250,920,691,357,959,83,470,700,175,256,29,922,869,330,576,510,54,406,56,108,926,373,396,686,557,140,477,839,985,535,837,31,658,126,314,872,830,548,233,623,320,9,144,739,385,489,259,662,53,312,936,843,104,80,286,93,519,409,301,223,118,99,305,672,473,16,256,363,509,489,126,542,90,725,945,637,335,240,356,450,868,679,988,829,55,405,241,548,355,666,250,366,964,265,236,478,407,261,637,640,874,743,542,382,976,445,603,664,112,955,737,98,377,734,410,794,906,59,251,365,914,344,303,974,32,767,665,699,496,112,332,680,776,889,859,837,638,480,24,765,398,505,851,225,337,303,120,86,598,92,170,78,202,801,647,704,689,336,564,910,405,248,744,448,435,804,935,730,952,329,577,957,612,169,500,865,217,187,237,760,742,455,101,742,16,837,931,916,424,353,286,306,128,478,384,58,889,782,887,288,792,283,816,579,626,167,711,374,986,902,670,395,178,805,81,456,864,462,110,791,913,526,719,720,280,17,679,915,205,232,679,919,421,180,825,30,281,151,635,26,913,527,920,587,319,491,368,581,467,185,981,383,94,911,981,224,501,214,828,0,161,708,143,796,802,662,875,680,508,243,827,73,930,993,924,717,696,261,716,229,13,987,872,508,861,909,752,491,585,119,165,857,321,505,124,362,545,629,391,613,726,261,225,484,324,39,560,415,280,872,324,351,414,435,58,862,209,410,214,95,967,374,178,514,340,85,652,21,598,113,427,208,214,424,807,152,755,396,281,669,593,401,698,193,219,788,844,350,481,814,63,34,30,77,594,413,299,758,400,39,39,332,722,181,924,465,175,83,704,206,210,960,861,365,250,32,950,959,600,361,692,587,807,661,252,63,810,639,758,690,48,312,806,188,898,14,283,593,134,218,959,249,675,445,455,152,609,413,427,561,86,410,326,502,469,602,569,517,851,411,859,919,387,206,370,627,484,72,441,139,243,277,223,986,46,710,687,233,467,423,26,449,504,930,913,920,40,715,214,850,855,684,401,58,118,860,749,935,595,334,92,532,174,81,53,518,345,778,953,860,425,868,738,532,20,311,230,263,796,877,706,828,36,18,376,534,430,639,728,841,831,679,145,33,457,50,765,65,973,2,800,21,75,636,620,610,371,940,873,907,590,547,953,900,174,88,674,480,960,96,330,949,752,182,980,124,929,744,410,612,667,842,386,950,846,336,660,805,797,187,708,469,729,59,632,913,501,435,719,960,395,48,282,787,934,133,900,596,954,384,540,77,247,809,280,507,154,607,210,224,642,694,567,383,274,399,525,750,851,291,174,815,341,920,157,269,834,430,27,955,642,958,126,91,30,348,317,523,694,324,236,785,184,34,783,895,698,678,668,380,360,34,502,325,805,272,487,911,695,752,517,165,712,403,93,49,922,295,672,490,641,582,869,346,799,29,387,147,975,361,465,455,261,107,536,665,561,353,536,143,117,116,213,298,109,166,502,992,781,345,421,324,532,364,794,968,272,686,380,343,375,100,528,38,450,310,552,95,544,175,572,904,898,97,457,345,165,148,625,485,659,111,422,191,642,393,395,614,787,786,281,686,705,211,193,506,59,910,372,999,411,301,600,892,99,636,194,1,237,630,394,620,96,350,498,720,107,614,912,379,395,549,849,399,180,875,741,74,649,713,52,79,344,37,655,854,70,980,518,295,882,596,231,36,927,750,325,723,155,3,301,572,22,736,583,993,341,306,73,272,512,537,955,22,964,722,902,461,114,830,476,812,243,320,97", +"548,389,45,128,374,510,941,923,726,137,907,266,649,934,918,822,234,280,234,430,252,908,854,158,892,84,71,583,165,174,895,15,238,600,595,697,16,176,886,390,134,97,130,338,273,990,43,39,653,296,128,285,65,320,387,258,937,964,94,621,927,682,642,334,365,988,312,585,175,591,359,510,716,76,918,135,558,822,236,110,374,354,771,809,354,372,520,21,122,766,158,539,276,510,886,896,771,156,157,557,449,847,204,985,947,3,576,429,419,721,574,479,403,395,709,812,5,651,924,342,52,933,890,23,237,74,897,280,801,153,82,688,9,522,738,41,733,382,422,825,198,523,645,995,125,838,640,870,677,254,685,504,89,619,942,326,512,925,324,531,886,957,653,924,860,633,326,73,531,176,850,255,639,928,371,604,838,580,549,237,328,343,932,575,529,324,681,339,736,293,420,340,808,391,820,420,670,496,121,280,34,73,570,952,363,330,825,314,265,389,708,815,203,382,557,853,30,558,87,267,762,470,854,224,610,490,570,900,989,774,108,582,851,97,852,981,192,947,961,369,579,961,27,199,764,632,277,63,449,782,128,75,528,686,646,119,762,90,762,341,53,952,448,114,766,995,123,976,321,827,857,880,989,446,64,207,419,51,904,65,454,16,107,713,70,86,16,13,557,937,686,737,504,36,499,225,877,464,811,793,373,282,319,16,872,300,851,776,221,255,677,407,938,940,119,683,995,52,933,553,837,210,954,821,868,309,978,219,514,189,312,600,251,176,249,757,289,57,786,117,155,341,320,931,797,485,698,778,157,535,729,311,952,337,925,284,457,201,857,924,133,711,227,183,663,378,431,97,823,493,654,500,758,452,198,638,983,360,456,391,465,579,841,479,992,775,578,798,490,953,166,323,109,409,805,344,243,386,892,596,507,449,617,339,831,197,521,621,540,944,86,318,44,402,147,639,972,574,690,204,978,825,606,64,200,415,792,900,655,118,565,550,739,818,369,782,811,583,725,796,76,446,31,854,985,726,219,614,657,249,509,653,977,299,491,800,85,823,328,654,82,687,515,631,59,805,699,709,48,807,285,367,446,386,161,0,367,764,158,165,807,869,398,484,730,245,315,468,445,884,847,99,372,848,796,122,618,40,554,992,627,797,626,354,575,208,821,276,740,236,340,25,511,281,332,221,17,366,847,830,807,121,809,268,629,728,518,544,792,967,459,145,694,919,111,699,752,558,514,862,884,136,654,206,252,632,961,732,65,159,288,365,929,413,428,174,970,268,532,929,413,198,725,264,262,978,340,168,851,151,123,391,909,588,823,580,727,505,463,123,495,599,992,534,185,688,307,490,915,783,70,124,467,129,331,555,634,286,299,163,998,405,932,79,419,357,438,168,385,531,809,44,122,162,782,626,391,533,102,63,189,629,100,128,688,27,723,458,333,973,62,22,830,31,722,87,476,180,426,535,916,675,208,216,804,729,795,420,394,542,656,272,480,242,928,438,894,990,755,328,30,332,467,962,657,32,266,268,226,236,446,359,930,428,681,291,894,810,677,534,267,885,385,446,70,268,434,802,755,286,631,810,218,882,80,354,903,278,41,661,338,71,971,503,854,737,596,408,790,653,262,79,137,869,593,818,253,834,110,154,54,474,325,548,695,960,761,149,633,593,411,493,642,45,99,2,712,31,298,613,376,339,382,131,285,759,711,681,172,193,565,882,279,510,352,89,986,51,589,947,885,4,878,202,110,965,111,93,723,827,34,722,297,610,300,813,926,802,967,254,419,672,873,198,691,121,139,416,42,401,998,997,724,363,320,582,311,868,69,507,555,631,448,813,164,278,645,472,627,897,433,270,830,402,980,18,919,461,325,136,678,450,314,695,98,581,710,248,922,276,124,943,299,755,215,904,668,230,865,632,167,114,322,791,785,359,814,248,538,924,875,166,636,430,855,905,608,40,618,356,494,787,55,762,636,89,598,798,509,903,478,680,7,775,620,837,540,780,41,617,376,757,306,720,62,975,609,812,637,8,516,947,278,555,127,464,155,174,705,790,699,737,143,849,308,661,671,227,576,954,152,336,361,495,190,188,943,966,802,667,984,800,943,254,588,265,153,254,117,174,515,459,454,700,819,332,345,340,649,343,636,549,432,502,82,967,51,946,609,344,131,84,994,294,281,581,574,649,91,357,394,397,632,265,353,977,218,537,286,29,223,657,739,821,51,990,481,267,660,352,749,640,669,796,552,445,638,280,15,793,575,295,830,104,566,32,263,438,364,210", +"507,490,937,272,432,284,279,541,559,931,718,152,829,877,768,321,454,746,829,907,665,264,591,875,10,519,641,697,811,596,36,446,994,439,52,162,297,458,591,397,959,579,436,389,18,153,879,212,95,821,254,397,657,883,638,127,827,361,674,542,979,609,597,487,717,318,222,860,800,328,491,622,372,990,249,675,418,561,767,407,556,792,984,800,846,230,68,616,38,595,589,575,897,237,339,817,979,301,516,256,704,877,579,57,471,341,731,3,16,89,362,239,168,173,439,781,956,734,472,264,897,768,636,667,73,646,100,685,558,598,595,145,419,428,775,758,710,102,398,226,885,414,27,746,858,785,940,605,490,665,264,603,370,954,891,640,843,858,877,460,629,624,52,230,652,690,642,168,395,26,901,211,817,465,147,485,65,603,836,278,557,319,962,600,540,102,179,567,582,97,194,298,628,220,546,284,911,562,825,471,390,659,793,395,892,86,637,582,682,834,203,797,21,857,935,645,496,729,681,837,212,800,52,656,280,215,347,424,831,139,73,622,308,227,882,611,637,747,681,590,869,615,820,379,903,649,533,284,818,327,148,928,666,235,106,276,830,309,877,497,355,652,198,919,148,9,442,716,962,819,998,386,286,750,889,773,278,910,288,196,927,760,265,346,993,290,625,889,10,717,692,925,663,990,487,672,320,638,376,271,302,858,984,765,518,448,971,131,296,896,345,740,620,336,304,657,77,873,522,929,588,522,510,550,496,52,805,986,636,580,918,798,5,500,212,736,341,83,956,769,543,113,146,847,84,216,587,693,957,813,597,876,190,760,14,245,258,248,977,842,192,286,304,563,803,424,572,21,151,592,652,691,855,186,595,676,176,721,633,741,206,948,270,630,813,681,269,660,641,229,458,244,862,322,657,511,788,789,324,841,313,547,305,55,571,22,59,528,556,939,919,523,702,632,560,860,357,465,202,959,422,935,184,608,509,129,888,50,414,831,625,78,584,492,466,188,84,823,613,474,952,219,701,382,272,862,653,169,392,426,206,484,666,199,807,206,595,288,77,241,308,890,347,560,511,815,418,348,682,184,898,799,129,27,708,367,0,35,433,854,338,514,482,998,193,205,876,160,897,805,651,319,115,899,288,642,60,455,239,233,505,795,537,918,652,636,301,815,259,690,832,268,316,905,947,519,194,956,864,407,973,696,599,115,297,38,325,608,876,4,715,468,587,496,3,41,466,389,961,966,500,19,19,767,599,686,772,217,943,65,249,8,186,626,850,26,198,715,994,559,597,741,652,300,663,268,33,183,41,953,446,246,802,913,669,359,223,217,700,711,43,477,59,333,909,742,856,150,495,702,333,520,552,464,727,549,577,980,478,537,963,596,521,694,489,32,700,597,49,540,573,784,403,307,959,954,581,46,251,353,887,240,745,69,637,311,826,79,697,799,796,88,182,522,416,797,344,526,402,597,669,209,858,951,907,68,404,363,449,386,882,175,777,529,911,495,905,913,479,982,528,19,141,458,814,479,536,61,640,231,610,792,345,624,999,22,926,174,754,791,341,88,431,605,958,487,155,838,324,319,492,412,804,631,62,288,276,35,243,556,163,671,531,177,371,961,140,850,23,450,835,987,67,261,636,614,245,250,963,39,982,658,598,994,349,527,13,741,977,239,892,87,412,683,691,848,730,454,75,587,825,642,24,752,279,750,31,788,957,5,900,840,542,721,508,601,521,227,776,176,800,848,250,849,562,723,357,223,938,505,384,581,824,886,35,20,113,41,494,330,74,891,811,643,532,388,437,539,406,831,485,879,136,231,834,688,544,834,829,142,509,554,52,319,378,829,866,231,488,280,603,276,447,122,984,929,761,446,232,250,565,100,386,323,664,435,107,494,369,897,697,295,847,679,863,689,919,61,75,924,334,456,39,507,575,595,509,166,895,216,533,465,418,307,693,553,941,511,250,556,135,176,129,715,700,127,678,727,62,556,648,341,515,80,853,497,905,93,793,885,887,241,710,178,463,915,890,494,204,373,520,534,95,911,694,826,649,883,528,680,774,672,832,13,713,528,958,472,346,607,142,476,325,219,202,408,803,426,666,348,409,747,344,125,993,583,206,601,520,156,120,45,633,579,735,597,322,341,569,769,994,258,990,701,351,518,933,790,962,981,48,880,986,834,852,189,972,471,695,666,284,585,137,951,250,119,286,237,607,468,174,761,428,346,246,577,353,209,235,949,63,715,626,721,599,987,223,287,285,283,110,448,941,694,302,765,860,849,411,543", +"875,491,929,463,388,43,925,619,17,425,851,738,917,743,422,576,79,663,203,207,329,308,170,661,390,800,988,194,539,648,98,698,353,411,145,920,88,50,948,857,224,796,38,712,835,414,334,975,464,648,161,528,732,484,116,722,44,11,721,590,932,838,147,241,779,331,832,848,909,357,320,679,510,591,232,498,14,702,670,624,336,337,23,983,168,620,283,388,692,882,275,828,728,456,466,68,655,526,269,828,957,49,600,726,231,236,484,120,827,932,629,563,717,359,791,929,630,222,442,555,339,775,366,469,697,540,612,194,875,93,197,148,167,877,195,527,682,418,876,960,863,201,841,60,7,521,817,889,297,507,44,394,205,644,970,387,470,585,36,288,22,511,580,270,204,601,242,320,680,571,798,986,705,33,252,25,681,911,700,732,28,733,226,648,636,398,339,195,943,311,370,457,182,363,250,204,60,440,899,305,862,313,417,237,438,653,206,714,941,958,595,500,70,653,944,810,761,684,354,440,897,141,73,869,958,711,881,302,918,849,984,455,222,24,171,9,35,132,102,74,412,583,371,29,63,466,585,548,643,972,332,47,810,421,384,323,349,947,21,223,604,340,861,101,137,752,710,355,866,950,437,776,543,738,586,804,897,114,313,203,914,865,759,948,922,417,811,920,124,580,109,191,500,122,12,884,485,824,461,174,205,113,549,429,718,58,13,18,684,494,223,361,809,27,108,205,627,543,435,427,505,343,385,963,826,883,417,553,632,941,151,78,716,569,333,171,534,670,406,889,43,800,203,742,620,511,705,172,195,331,2,189,986,766,517,250,247,830,440,884,904,283,35,92,220,364,928,111,817,462,782,111,636,817,195,665,624,511,570,992,162,948,140,266,486,81,690,413,160,268,796,961,531,739,826,677,466,456,202,472,586,767,359,957,292,349,397,908,820,160,215,543,455,289,755,362,987,284,106,704,840,998,485,984,11,984,343,758,813,840,544,14,473,340,913,197,564,179,8,186,499,574,133,640,656,893,75,235,484,159,429,910,197,472,45,145,535,58,815,688,60,189,473,613,883,951,231,94,195,84,13,838,919,151,143,764,35,0,484,662,942,882,617,122,416,858,310,713,754,185,941,536,384,907,71,923,202,810,405,227,315,193,287,64,656,384,296,515,239,322,881,768,42,740,691,715,600,522,929,454,514,235,344,369,678,916,783,274,698,774,896,790,742,680,144,788,178,689,270,529,250,550,562,246,589,991,836,400,668,483,860,459,608,51,550,665,845,565,131,330,469,104,711,26,290,732,605,744,230,173,121,734,814,471,924,879,230,131,486,730,672,346,362,576,982,34,374,574,616,577,286,419,208,133,787,756,744,145,296,373,238,493,797,86,888,688,809,329,940,728,551,221,806,684,345,176,726,583,109,856,229,314,334,858,612,504,529,12,921,623,320,640,367,433,606,212,285,282,993,86,395,699,756,770,862,197,908,790,829,428,779,403,950,176,89,940,646,514,289,28,370,956,319,841,327,213,395,908,81,283,299,359,463,84,724,559,853,379,31,344,692,62,510,635,774,54,631,661,813,885,512,722,465,357,258,766,536,708,168,528,438,337,854,978,392,556,239,947,625,628,606,260,44,115,833,440,671,709,859,708,25,494,934,840,658,387,913,69,595,888,437,628,400,778,519,774,975,307,849,626,208,661,388,565,164,551,622,857,753,434,32,137,415,98,453,999,996,971,431,424,974,655,991,19,262,969,466,352,427,132,920,929,268,470,777,747,249,48,146,859,511,128,587,132,890,872,960,533,22,622,228,953,577,645,942,247,143,889,9,543,578,430,499,424,471,22,770,52,256,340,571,984,700,473,961,576,280,303,681,141,562,639,691,281,84,763,951,892,853,530,616,137,548,581,829,205,988,751,451,922,191,175,692,45,485,756,914,460,76,51,835,710,319,869,114,814,111,772,61,551,47,810,25,233,89,183,901,531,218,886,517,520,1000,98,164,142,790,659,20,805,890,280,209,754,791,427,899,559,241,822,741,145,8,117,206,924,951,412,833,565,831,754,738,661,807,328,239,106,380,245,224,579,645,353,842,441,476,156,988,489,432,217,111,17,807,469,876,38,458,480,347,686,489,757,766,219,868,736,916,369,365,301,958,326,862,62,914,810,446,311,761,594,938,813,64,122,605,207,182,469,257,34,585,198,372,161,99,431,244,432,446,541,496,942,397,297,489,713,449,695,219,615,201,295,182,157,953,864,962,427,798,207,113,286,997,93,846,172,959,57", +"434,550,415,260,758,354,327,92,113,410,888,824,937,344,274,598,553,999,235,495,479,124,475,720,819,573,276,610,344,487,569,133,194,150,289,105,665,278,547,898,577,158,583,913,218,969,771,87,34,625,737,936,620,857,777,814,227,680,956,629,170,450,55,904,191,571,227,544,16,276,676,171,860,731,453,80,287,124,460,191,979,444,826,987,948,705,161,307,388,802,75,809,867,764,74,244,788,77,165,176,218,816,886,934,232,679,945,795,954,949,549,730,4,542,994,235,284,312,133,758,921,776,702,227,42,736,810,911,702,353,688,35,649,175,692,426,280,160,59,872,947,659,31,280,232,894,884,581,233,995,600,911,70,756,307,384,877,950,518,859,92,548,471,134,508,138,417,343,64,563,953,889,59,212,361,262,44,454,570,160,377,595,904,778,861,816,629,382,324,222,702,339,744,984,595,559,652,39,254,540,585,935,569,223,805,298,730,57,158,334,575,644,360,378,763,73,209,838,655,568,891,363,830,527,865,341,178,379,847,642,733,784,288,861,529,403,201,805,683,430,253,221,747,95,172,335,189,485,301,161,498,159,708,115,633,408,933,485,853,16,227,556,389,42,170,83,907,404,792,605,440,788,633,396,155,839,57,342,919,358,23,672,423,413,930,218,6,73,542,636,683,152,503,866,772,979,626,981,90,251,67,310,485,764,197,824,931,495,778,711,740,236,204,263,898,114,971,345,27,143,686,300,717,638,919,588,651,140,467,995,393,195,779,997,160,71,592,834,812,771,151,386,257,319,296,563,568,405,711,740,108,588,914,790,269,592,406,681,94,562,491,407,992,563,979,665,179,66,232,672,831,709,130,39,864,507,266,865,860,232,668,569,349,607,432,61,113,631,383,298,25,972,277,730,751,380,869,285,293,939,107,95,643,733,882,497,399,655,67,559,410,842,457,58,607,961,185,145,720,10,61,596,516,671,214,639,404,870,985,132,421,83,113,549,746,379,134,577,508,275,127,165,343,473,946,643,801,41,368,911,572,961,926,569,503,936,308,547,637,78,929,975,551,89,491,542,263,819,440,881,80,100,203,851,796,158,433,484,0,725,862,762,257,624,850,692,4,229,466,125,634,472,56,119,6,883,153,314,626,804,779,720,105,444,403,599,207,412,613,838,737,807,438,74,531,333,566,192,429,187,768,488,677,580,588,521,659,623,728,270,917,905,818,89,37,55,377,802,41,195,111,856,435,85,998,761,15,915,545,518,997,696,177,286,237,551,546,899,103,622,469,97,909,468,464,397,148,58,275,93,118,551,554,342,628,916,132,410,523,112,383,357,22,601,913,114,738,738,128,949,209,357,879,151,656,727,230,183,248,752,768,448,610,413,241,993,287,241,575,756,378,214,795,366,532,650,403,996,785,521,664,773,116,338,206,676,801,346,587,268,234,578,661,782,86,390,535,7,445,19,567,632,610,673,520,760,450,555,34,651,716,372,763,627,98,885,81,806,396,466,249,608,818,650,778,825,823,794,670,551,778,969,319,100,549,394,96,190,249,102,363,362,489,487,967,111,723,797,403,336,346,936,278,121,810,744,224,201,60,953,250,635,176,834,423,330,117,383,847,662,461,121,166,646,978,310,267,606,897,801,661,193,997,126,269,36,623,708,474,170,458,165,470,390,225,604,602,864,634,445,169,455,382,45,12,70,510,550,534,249,450,987,503,82,495,823,509,408,183,596,777,572,731,199,39,420,84,872,947,900,602,949,211,332,263,361,33,574,102,992,978,306,814,477,15,259,922,859,475,810,930,239,273,848,851,186,297,906,865,119,531,563,163,637,661,546,214,624,625,944,780,961,865,12,335,580,196,20,93,82,68,346,111,757,7,979,620,446,774,686,697,242,482,862,206,68,107,519,606,588,11,112,264,989,891,981,14,897,590,779,242,967,860,854,936,761,279,861,567,132,602,765,781,11,788,442,802,435,51,695,131,377,297,708,761,327,682,263,566,908,593,831,760,877,905,315,113,563,134,576,732,21,909,724,244,137,730,21,560,548,604,431,390,300,210,69,581,313,783,579,668,156,377,48,786,849,949,214,174,494,247,457,809,307,829,265,562,828,181,412,609,939,823,9,206,160,421,564,233,475,564,327,649,989,871,49,754,382,224,564,630,268,322,473,590,598,502,526,338,739,962,201,11,247,434,493,480,9,462,61,919,714,529,239,959,114,926,68,359,310,512,987,17,255,145,898,721,355,260,482,712,352,830,819,418,675,551,517,142,130", +"702,983,221,74,158,49,901,105,670,805,424,383,302,918,489,797,182,39,319,629,684,293,269,976,950,207,463,346,377,977,542,4,454,565,391,14,628,198,671,210,157,576,428,208,562,190,82,423,287,648,942,408,267,657,831,508,333,737,354,389,249,312,266,6,984,909,57,594,975,2,139,791,661,749,387,615,578,29,208,441,624,877,482,719,240,817,431,85,881,421,89,797,973,363,417,123,480,336,288,41,844,333,56,490,956,992,575,946,34,738,954,681,686,636,782,854,237,119,219,24,566,975,440,910,220,645,192,418,483,184,766,406,720,298,203,423,283,988,961,921,701,199,399,547,5,647,150,347,442,62,327,614,731,891,808,316,923,211,927,691,94,391,953,772,877,592,905,885,356,796,817,811,189,794,369,818,955,340,980,687,622,125,79,349,87,955,618,927,286,706,504,77,476,252,731,582,673,790,845,755,481,799,749,60,285,18,644,565,61,965,405,188,303,466,701,627,465,535,494,178,311,636,582,338,908,9,439,847,901,581,81,264,735,319,311,997,157,887,163,975,787,473,983,480,673,112,670,546,664,208,925,839,907,678,386,136,61,469,999,155,344,854,702,710,127,687,89,837,941,74,433,478,131,357,15,481,491,856,450,596,61,305,511,341,638,131,231,102,575,535,658,762,190,519,588,199,942,379,199,997,538,267,63,845,658,478,572,985,438,955,846,14,491,750,557,719,883,937,3,176,808,104,403,851,893,414,977,759,291,774,329,704,594,376,45,152,480,997,286,760,765,156,989,198,76,213,845,586,851,324,435,802,186,512,198,261,902,341,372,599,244,228,249,840,583,656,258,80,958,460,980,316,762,89,167,997,2,466,187,72,739,338,865,638,784,39,858,208,867,832,946,461,582,79,382,326,767,712,227,547,582,575,203,345,927,649,183,977,709,642,788,276,761,789,966,300,567,727,566,487,288,814,128,63,962,912,253,620,688,59,70,362,376,380,476,804,786,847,75,674,554,421,771,937,530,284,108,419,809,558,158,46,959,926,653,902,206,406,388,626,404,283,396,11,510,928,107,17,72,389,845,874,104,976,802,165,854,662,725,0,164,484,953,819,498,779,76,634,843,217,798,930,616,863,230,811,105,552,476,101,381,444,327,510,238,132,727,305,956,841,211,778,205,361,869,684,285,962,843,232,493,975,891,193,268,411,846,143,288,897,74,895,126,517,37,789,711,926,879,584,808,244,334,269,405,835,411,521,660,965,676,322,505,865,875,46,88,535,77,649,593,849,347,438,553,363,594,126,401,774,212,834,118,915,404,709,461,353,250,248,336,416,830,695,30,496,490,400,769,714,500,187,846,98,437,157,161,366,805,210,634,198,262,856,571,429,197,63,476,122,943,772,55,405,876,183,876,156,847,369,417,913,635,259,762,858,250,884,275,217,493,826,405,510,639,19,910,534,928,882,452,282,289,169,992,571,349,141,47,704,390,457,409,118,997,361,738,646,81,232,975,847,777,598,465,823,713,769,175,246,352,285,679,642,368,332,786,662,658,749,567,100,268,734,928,567,850,279,312,613,435,933,61,439,495,982,705,873,349,684,772,318,424,842,893,614,193,688,343,494,185,782,148,140,210,702,398,368,74,57,995,970,719,124,154,389,723,222,337,551,29,783,338,512,627,17,540,139,806,363,102,188,619,594,464,781,12,960,363,272,8,220,927,454,4,233,157,355,249,370,688,381,804,619,622,860,450,305,418,902,298,769,617,153,615,321,698,663,291,915,172,278,80,200,232,71,535,791,461,38,926,571,27,420,414,360,749,641,913,83,662,124,583,806,966,328,604,317,317,424,272,736,112,40,12,591,747,762,231,200,481,196,706,564,707,626,18,696,287,344,354,674,962,970,299,744,757,555,831,144,343,338,325,581,310,759,744,293,332,216,356,668,457,555,634,887,129,21,247,179,209,222,640,909,25,920,218,100,395,917,878,231,122,952,363,288,920,411,953,55,440,878,768,128,969,183,214,15,338,569,737,523,512,663,843,404,112,168,750,417,286,872,839,134,952,173,770,841,554,940,501,143,339,881,594,663,977,65,389,933,879,738,964,604,178,230,976,133,996,849,393,535,132,668,660,164,936,753,500,219,714,296,132,780,327,681,777,718,392,427,750,313,473,169,206,935,95,10,809,782,328,759,265,729,307,997,950,384,182,20,125,498,754,243,869,639,327,76,788,540,860,568,594,216,733,12,745,344,508,320,60,655,582,487,518,604,733,203,199,917", +"109,812,6,531,121,389,56,976,354,829,482,670,998,895,283,292,827,629,385,331,394,418,184,822,899,481,460,764,394,845,92,745,142,153,795,113,720,209,348,184,428,967,430,840,993,255,970,579,128,530,424,190,604,597,366,533,277,360,92,957,323,795,198,744,747,124,364,812,347,906,821,192,4,274,839,507,300,696,191,442,563,139,387,52,392,869,367,862,621,18,540,430,77,173,738,603,731,497,473,659,204,653,126,460,740,414,767,756,163,947,289,862,340,501,378,489,747,722,882,693,735,721,50,128,565,50,250,699,716,677,864,806,385,281,267,632,425,939,126,596,35,546,826,241,706,401,410,390,978,882,712,137,310,64,611,123,122,68,76,438,941,783,358,674,669,461,432,881,115,636,44,692,174,623,960,303,949,995,162,104,620,120,312,430,121,433,405,449,43,177,557,287,549,489,366,202,761,457,689,28,825,396,905,345,411,147,83,27,403,29,540,724,57,567,708,695,940,769,128,178,413,402,786,509,301,591,878,317,83,734,498,632,419,851,303,451,279,238,935,108,588,69,314,161,82,99,398,839,332,46,324,71,56,753,16,31,650,721,476,101,692,557,849,744,340,579,30,354,774,790,403,527,849,846,298,543,242,480,336,65,13,700,210,762,463,48,806,53,413,236,493,646,638,661,416,668,807,623,198,17,398,408,164,465,400,135,324,837,15,578,975,454,878,100,540,243,18,223,369,664,382,919,862,42,855,16,629,495,194,653,322,452,898,790,656,583,459,974,252,827,838,307,124,998,115,300,678,917,532,594,885,374,865,148,410,516,170,920,60,316,267,758,520,406,999,532,28,143,276,180,250,941,959,891,93,638,611,552,767,748,152,265,462,89,162,305,306,147,924,521,589,355,270,896,691,94,156,302,421,207,257,698,213,354,797,512,911,837,289,679,306,424,466,794,653,143,700,816,182,694,500,525,216,333,31,618,916,521,89,539,765,234,847,589,756,834,309,120,523,662,108,180,166,838,208,904,423,828,599,133,645,777,743,718,569,902,222,693,108,591,801,695,797,205,546,487,505,444,421,515,991,331,9,689,662,807,338,942,862,164,0,651,598,219,578,526,387,850,63,751,696,732,87,839,866,34,447,159,238,509,151,46,39,977,95,74,552,834,151,5,327,439,383,839,86,971,856,64,788,227,679,516,882,719,554,34,834,317,359,334,705,227,863,551,991,597,381,839,632,908,549,949,612,858,197,17,458,792,739,346,419,488,884,931,870,412,4,377,958,222,201,663,858,455,275,680,419,68,681,608,313,644,559,340,354,918,937,908,271,824,334,14,730,477,694,305,303,607,881,908,897,862,191,334,863,619,806,411,156,584,630,401,601,916,401,608,883,18,772,604,942,153,474,418,969,732,734,210,511,520,463,460,716,433,33,952,865,241,85,499,360,506,384,56,218,766,543,483,581,253,352,184,568,236,513,708,92,984,86,275,191,662,830,371,462,475,61,787,943,165,768,383,171,677,902,841,765,153,356,386,586,258,352,909,516,898,677,831,117,111,578,767,512,421,813,433,542,480,53,385,92,180,18,381,70,631,664,46,436,701,370,897,912,352,237,205,816,463,635,48,261,274,204,336,701,690,898,789,709,55,207,966,9,55,66,394,706,483,300,129,911,570,297,189,900,279,620,342,189,8,96,831,82,69,749,854,742,660,874,62,123,411,404,850,807,681,452,672,620,614,899,716,717,484,469,722,907,726,752,916,968,33,840,367,738,561,900,726,435,85,672,482,913,616,327,645,622,743,360,991,101,684,154,736,96,865,761,736,586,877,74,407,166,64,257,725,21,723,306,326,516,495,801,523,253,684,211,7,191,237,712,326,906,997,895,421,584,940,165,347,311,847,141,854,477,185,923,123,933,806,365,569,698,963,899,216,568,706,352,135,382,81,974,696,291,353,432,526,445,850,275,377,976,627,559,317,68,422,161,11,857,229,913,615,221,245,200,749,918,283,480,416,937,413,563,188,827,601,171,9,353,699,373,307,69,379,186,77,405,411,103,649,499,850,333,56,610,333,714,548,780,902,678,51,440,515,316,88,399,161,686,256,320,177,415,646,979,842,546,20,164,948,713,261,927,558,868,995,678,830,875,78,187,656,178,800,564,65,245,901,186,152,58,392,596,530,399,242,445,390,733,373,617,606,469,804,465,714,908,597,759,534,359,233,636,424,783,258,136,770,748,214,201,684,518,71,313,696,517,332,990,935,378,413,411,165,217,229,375,285", +"32,652,666,726,868,606,528,429,685,990,735,201,954,12,610,816,290,427,527,877,966,839,332,942,374,68,428,14,439,781,399,457,6,76,891,25,850,949,779,272,453,68,173,159,267,554,595,189,531,673,221,122,797,648,163,846,648,866,126,101,994,385,253,700,313,650,751,901,239,872,217,648,241,98,331,713,394,710,493,107,349,958,458,413,555,694,107,917,70,939,976,408,643,180,797,966,893,328,811,294,63,111,816,994,514,786,406,520,717,997,610,330,896,87,963,74,728,566,343,472,47,863,951,861,397,76,290,535,350,397,294,409,409,522,328,684,615,813,462,622,54,971,415,445,595,975,270,749,822,214,176,977,659,395,879,432,620,410,465,51,999,620,640,845,542,102,702,326,335,625,831,621,43,969,723,550,780,996,170,938,648,483,678,981,73,776,295,497,534,526,671,443,420,641,797,92,885,983,769,701,703,454,106,433,153,410,350,865,530,118,386,879,369,797,762,889,816,119,769,804,855,291,55,878,795,177,83,296,191,808,268,3,113,810,918,171,224,331,48,530,970,936,82,505,590,282,101,55,577,642,27,314,441,213,423,480,895,388,804,995,79,28,487,164,708,565,377,799,14,204,914,524,638,674,339,379,233,439,141,137,727,876,411,985,532,290,58,879,274,483,484,186,331,544,903,400,288,28,940,337,699,901,366,777,353,92,758,326,23,355,113,64,874,738,107,483,862,96,440,732,799,276,67,220,55,950,526,181,376,48,957,691,119,845,526,346,145,885,355,641,851,85,849,88,737,973,431,129,402,949,251,105,922,388,876,272,748,645,764,521,677,579,141,680,485,204,150,148,614,786,176,516,468,775,399,666,538,675,50,627,197,238,42,297,899,796,707,667,618,561,489,772,826,786,996,801,686,761,956,847,875,106,307,624,400,20,98,968,434,579,942,882,35,70,403,540,564,958,440,886,689,602,573,382,515,933,308,944,524,878,658,764,796,615,837,421,273,679,149,847,495,478,641,987,388,82,457,802,561,783,155,667,544,470,131,247,723,422,333,426,89,546,677,821,79,350,336,556,813,200,309,690,99,271,875,869,514,882,762,484,651,0,683,27,33,475,531,561,702,316,53,393,643,389,246,448,823,636,265,108,429,656,935,77,956,881,709,605,884,809,667,244,53,938,598,89,857,401,784,367,471,40,636,203,369,727,95,677,169,634,770,209,346,224,435,40,77,777,106,920,380,73,646,121,554,594,717,149,585,361,609,468,182,853,62,668,677,726,370,790,483,49,882,205,59,479,760,512,747,939,820,522,371,794,577,367,86,687,159,340,659,276,465,886,827,642,835,650,714,611,444,488,126,680,686,133,795,801,673,524,298,132,510,141,856,463,993,143,197,931,549,629,980,186,372,193,255,917,967,785,1,135,438,822,458,197,603,298,311,280,464,780,34,708,696,874,99,460,369,464,513,444,860,552,265,118,274,375,616,840,752,25,717,31,959,642,313,381,135,51,775,858,911,479,930,509,788,298,374,577,509,323,884,34,960,266,785,806,843,707,249,793,895,552,282,894,983,441,753,558,68,116,974,518,136,819,448,747,513,474,104,83,351,650,392,396,319,386,726,150,403,544,518,945,493,433,714,602,733,54,117,500,464,670,586,290,346,118,600,883,599,727,322,912,753,336,721,65,198,333,532,313,153,312,296,389,688,432,228,166,419,768,920,535,421,524,231,357,467,188,212,208,362,928,630,824,416,386,48,213,201,810,619,127,540,585,71,256,309,47,765,120,610,764,46,966,894,836,64,612,98,252,797,671,444,496,764,826,597,95,533,577,575,19,755,615,478,161,736,569,413,494,586,902,597,186,309,980,624,552,716,898,424,674,741,118,931,999,564,174,149,208,531,33,787,430,876,373,186,721,247,809,956,842,304,11,200,994,113,236,914,883,566,801,157,393,819,266,454,672,643,715,543,306,594,1,201,209,899,620,419,509,717,462,623,289,697,507,558,189,435,195,733,353,379,412,135,508,521,311,226,332,806,181,129,233,760,346,61,381,847,963,639,767,846,811,487,248,866,957,190,976,305,734,225,515,340,263,643,760,530,149,433,860,12,479,266,810,971,185,243,950,253,879,747,297,869,641,972,76,366,998,251,100,287,504,359,603,808,174,954,124,12,994,184,277,334,927,565,230,727,871,756,374,571,984,393,15,269,158,975,676,478,213,689,190,698,571,551,657,516,678,70,638,67,934,407,3,941,795,102,804,852,69,795,657,624,487,741,456", +"835,170,263,822,961,522,113,685,345,72,637,572,290,409,876,757,790,306,599,737,887,427,945,816,841,789,958,935,812,865,986,31,716,796,686,345,983,966,442,551,468,611,865,346,329,767,872,440,379,465,65,977,894,995,840,961,429,882,707,666,46,865,295,851,709,880,43,187,744,611,640,566,720,335,967,22,538,206,731,77,916,499,923,640,391,668,380,807,212,719,677,122,300,280,573,996,27,147,235,397,765,887,416,568,772,720,212,540,984,843,749,897,814,219,99,278,395,522,439,62,72,141,807,413,215,155,187,309,684,845,946,842,541,19,825,462,903,409,11,128,961,422,859,151,513,12,372,136,158,605,872,666,556,917,554,58,411,68,212,166,323,923,991,622,750,420,423,604,377,7,782,667,358,812,94,918,68,812,190,38,605,980,659,80,59,68,964,125,907,89,597,632,6,283,625,533,831,226,775,62,779,451,50,585,699,197,47,584,419,864,198,359,465,219,175,128,821,840,192,112,714,871,184,653,922,550,518,729,109,618,473,390,902,624,433,370,888,620,475,409,391,272,626,374,747,1000,862,636,814,123,258,327,447,520,428,621,226,895,776,615,163,81,79,525,274,428,507,962,112,837,160,625,715,592,997,303,869,16,483,892,548,633,661,18,801,32,780,543,566,468,517,746,232,235,86,451,977,435,651,78,138,800,947,675,486,44,605,580,42,189,821,562,460,964,386,866,595,676,538,663,991,885,847,43,454,359,56,954,859,433,963,259,469,255,266,598,886,625,878,365,529,403,213,414,372,234,942,790,32,998,654,88,475,87,259,873,110,906,822,148,718,467,371,984,95,325,384,404,626,870,457,470,808,356,704,469,814,524,919,137,863,94,674,367,493,113,301,366,333,685,12,182,233,367,304,864,226,243,453,504,132,781,973,982,591,984,903,21,968,802,461,41,382,265,786,163,413,710,337,872,324,490,739,761,668,977,602,422,171,431,242,47,414,452,798,480,745,834,126,16,186,853,248,980,860,140,166,937,207,346,744,440,422,64,976,584,69,3,127,383,123,20,197,136,960,238,260,719,331,852,21,888,705,36,680,398,482,617,257,953,598,683,0,999,824,378,716,784,647,49,687,564,8,301,995,309,991,884,413,869,962,582,820,201,251,815,404,179,580,400,774,157,235,187,409,719,638,615,135,758,383,392,211,284,696,407,913,840,868,445,799,110,650,186,271,742,403,302,335,129,972,509,298,831,805,550,809,421,135,613,156,954,80,669,413,840,730,950,396,299,732,89,570,440,750,449,736,472,403,684,995,419,929,10,18,764,201,544,390,317,502,356,772,27,844,663,41,24,333,274,669,497,785,150,835,333,657,754,624,820,494,460,764,807,980,557,337,132,488,436,61,850,967,165,489,42,2,818,904,983,442,864,713,377,556,818,429,469,416,122,746,642,428,245,672,201,839,988,228,210,756,757,657,512,847,579,923,892,393,843,312,785,189,94,748,726,913,632,586,221,570,834,483,985,392,284,857,880,288,361,635,670,909,347,585,598,453,312,370,873,366,379,106,760,491,363,280,309,277,73,268,70,744,699,561,818,767,845,582,771,105,270,459,8,475,590,533,379,249,152,870,635,551,111,921,549,987,871,58,749,471,734,996,74,731,427,374,400,590,380,310,515,785,171,249,473,726,792,85,993,209,177,331,831,731,605,875,882,111,343,656,980,919,292,344,339,618,737,745,513,22,867,294,601,833,803,817,962,155,636,959,392,195,271,242,113,920,258,727,514,647,611,974,823,744,466,240,442,48,965,287,641,376,894,431,773,321,389,646,640,344,925,676,455,200,276,781,573,542,141,495,908,316,528,472,175,230,604,694,59,664,361,7,758,935,748,669,758,201,671,193,499,14,811,170,437,336,517,497,823,353,686,744,897,201,942,598,579,521,879,249,838,809,362,118,434,483,784,433,632,448,702,222,959,828,285,963,865,831,478,379,18,229,255,145,94,728,588,815,303,311,818,470,964,414,62,13,506,229,809,756,105,57,615,798,514,10,941,348,542,122,707,564,751,347,549,107,153,928,155,211,759,151,312,101,42,975,689,630,749,483,903,278,54,418,506,773,695,415,610,633,887,188,402,89,995,670,140,749,515,518,922,207,704,150,329,824,605,780,854,649,172,968,656,697,594,505,797,761,981,156,817,826,381,242,270,914,476,159,992,771,69,220,591,344,341,431,170,203,900,486,558,533,201,931,804,652,655,792,732,985,89,379,428,423,184,734,320,732,36", +"788,618,1,622,959,695,289,303,20,191,656,667,304,851,567,995,736,848,301,577,605,602,930,84,140,927,86,692,441,32,379,462,114,807,365,466,505,534,431,792,96,64,208,359,294,523,870,516,160,474,625,822,877,849,10,851,940,165,154,724,208,73,427,5,55,201,194,600,763,869,918,123,469,352,13,358,30,999,340,58,761,723,591,687,308,956,258,958,189,939,184,614,682,248,389,736,996,114,363,907,398,985,549,735,962,283,706,894,680,821,847,408,190,70,625,184,673,288,778,801,336,677,8,907,40,646,793,36,800,891,436,177,163,11,664,750,527,699,611,929,257,582,520,401,413,484,77,530,108,266,356,975,128,757,880,612,966,679,393,65,803,874,18,577,904,624,263,184,502,738,492,505,611,908,636,172,36,749,907,757,106,797,286,129,864,750,38,81,36,68,839,897,29,173,576,410,139,731,445,212,19,881,107,894,334,611,376,699,883,687,427,305,653,159,32,62,748,462,680,386,942,814,500,898,131,35,421,369,839,311,508,680,385,947,20,889,469,708,788,575,100,827,126,670,67,117,815,138,447,338,756,217,58,949,33,927,812,651,687,566,30,603,943,871,981,935,127,733,943,653,990,503,381,879,910,673,815,664,49,563,915,215,848,74,291,359,326,968,341,854,137,46,757,651,276,660,978,360,64,672,635,231,425,327,764,85,146,223,149,58,91,860,500,271,879,785,834,455,888,573,274,695,908,516,713,962,979,753,925,739,635,141,439,573,490,245,241,775,412,394,463,645,919,547,788,771,493,962,578,891,235,817,108,219,72,919,93,866,488,554,168,450,879,12,868,84,901,868,551,564,945,475,330,625,101,134,412,96,509,673,784,97,727,268,432,641,281,935,804,595,260,716,138,134,389,893,370,755,171,584,345,963,519,845,865,247,754,793,11,560,494,256,597,268,792,729,149,930,716,450,701,980,960,505,475,9,40,766,126,802,217,50,539,441,544,523,58,511,805,489,268,806,130,294,840,395,239,116,857,664,123,842,242,863,625,452,144,97,926,445,925,50,445,662,297,206,177,421,208,55,683,265,75,387,508,484,998,122,624,819,219,27,999,0,94,357,476,440,356,966,728,319,762,242,815,962,315,529,777,203,224,934,356,954,476,239,763,24,210,447,952,721,579,268,47,387,231,79,987,968,426,954,554,332,996,841,176,512,190,81,169,904,989,819,765,434,775,784,686,582,699,194,183,435,682,950,178,759,217,94,667,92,850,213,593,821,394,554,871,699,662,648,340,439,886,382,345,707,792,856,778,917,93,167,916,139,736,852,495,177,563,4,386,506,502,800,980,207,20,482,198,745,808,885,650,300,603,436,863,429,606,171,863,99,286,226,808,934,140,715,430,365,75,306,60,9,711,116,385,874,328,422,658,197,144,873,306,889,465,336,55,837,984,355,637,365,550,779,466,195,216,356,664,347,111,598,88,279,52,87,499,792,521,294,204,484,43,258,696,693,659,358,983,530,889,221,702,164,95,536,529,509,413,278,957,164,313,98,961,56,296,126,581,904,268,881,960,837,411,258,371,201,900,556,471,903,679,412,308,629,515,58,977,55,473,705,368,122,90,652,684,804,571,725,525,7,352,297,521,613,217,550,303,454,51,176,588,878,855,444,13,547,691,626,143,113,32,21,428,771,646,926,250,934,875,278,618,909,555,38,659,555,128,386,558,97,298,756,324,981,655,848,667,583,545,842,939,476,601,457,319,148,7,946,789,593,936,706,777,527,154,27,42,805,26,275,992,106,902,163,259,309,869,87,797,656,780,733,157,265,663,568,132,994,739,343,691,517,244,369,210,604,117,377,294,157,702,832,225,909,943,27,817,464,205,192,597,41,284,617,387,307,7,866,502,158,321,342,8,218,396,26,324,928,678,971,68,75,824,970,376,490,585,426,500,366,30,78,521,348,469,108,346,448,684,613,805,425,352,469,597,678,228,678,108,541,157,705,217,470,162,984,282,295,41,599,677,529,149,75,790,784,205,193,386,845,523,188,887,809,460,29,248,170,765,148,810,522,989,972,508,924,967,821,747,404,183,233,182,149,671,68,727,547,565,94,417,789,366,886,278,467,814,706,143,779,765,537,19,802,767,893,308,21,273,920,439,711,723,721,986,744,476,777,289,787,622,858,864,309,680,416,25,421,171,604,264,878,872,615,664,393,546,581,858,301,45,248,790,34,312,739,404,652,766,716,624,130,496,197,572,754,121,214,941,741,640,179,714,479", +"108,665,314,831,641,531,780,453,78,607,43,809,473,271,960,525,740,669,980,184,298,819,430,901,303,670,100,867,992,343,596,146,710,287,206,803,753,198,423,276,801,938,967,892,940,74,932,983,579,693,46,379,717,898,700,560,716,845,986,61,376,714,134,874,917,554,680,855,729,272,431,528,683,518,198,647,138,580,584,460,379,22,182,683,30,612,969,168,272,485,188,635,615,271,349,329,499,763,567,654,548,874,187,580,297,514,560,469,787,4,514,664,393,86,884,877,359,486,62,19,14,484,830,827,270,6,505,536,370,581,978,18,628,551,327,765,712,678,874,317,777,647,689,899,222,466,123,38,74,241,425,768,676,350,196,961,926,32,383,589,779,816,883,575,650,542,915,873,674,335,430,358,860,15,341,484,865,684,60,803,146,997,47,176,19,245,245,129,975,636,302,408,644,827,629,639,125,697,3,178,477,333,841,669,654,250,71,933,270,26,4,482,191,92,45,807,363,935,968,610,338,593,459,369,701,818,143,854,699,912,882,414,295,502,123,945,91,190,650,792,315,973,452,925,935,621,6,43,112,821,716,122,811,795,943,901,312,834,81,852,424,631,166,359,360,370,905,303,214,200,915,533,396,182,713,177,714,984,878,173,888,512,780,400,105,592,60,951,476,198,457,38,338,72,413,330,151,136,762,124,590,427,694,914,118,269,936,553,552,372,755,704,761,267,948,944,269,228,272,133,389,664,75,843,274,212,923,90,271,105,548,570,469,960,783,809,809,613,765,243,619,438,108,598,150,899,112,879,783,617,919,754,191,533,861,472,121,718,683,282,64,343,947,662,79,644,97,731,707,47,339,861,765,805,891,837,720,313,693,148,727,724,494,815,842,236,516,255,933,496,560,846,556,519,304,953,845,270,149,376,932,519,98,552,227,331,951,583,773,241,867,765,839,705,456,252,642,851,396,324,898,582,859,734,925,406,738,208,683,44,61,298,680,654,969,295,787,48,834,114,811,693,331,702,731,332,755,789,634,169,343,827,553,850,397,357,725,583,695,934,5,170,904,48,20,153,555,492,410,446,851,371,687,24,243,730,193,416,850,498,578,33,824,94,0,604,921,347,428,598,728,657,950,224,576,631,926,429,986,153,638,49,996,66,53,179,441,461,175,905,988,501,385,823,47,150,955,393,449,59,345,400,684,745,660,720,471,689,451,341,733,695,415,197,804,169,771,666,570,274,108,587,492,165,351,35,5,506,337,839,662,681,453,514,261,276,65,252,111,702,220,947,884,940,390,407,703,972,979,645,225,509,38,877,528,894,696,411,232,851,920,881,174,511,671,464,570,884,545,395,226,487,582,987,324,371,133,590,906,75,605,754,320,981,889,34,253,590,451,273,542,717,149,373,496,312,17,147,743,112,764,993,92,841,776,158,143,275,243,834,298,852,20,442,988,189,855,860,541,3,969,159,978,572,658,895,568,911,309,717,885,675,918,208,937,584,470,880,969,227,22,835,555,634,822,33,158,576,465,257,508,644,286,544,404,368,876,595,775,144,673,60,671,34,142,970,931,598,339,166,967,530,14,829,695,529,821,807,8,476,451,839,59,613,358,577,611,585,644,798,791,725,244,15,790,152,410,512,475,113,176,400,571,744,32,743,855,89,70,836,133,972,519,579,552,266,496,293,51,695,917,205,556,635,697,157,949,413,759,574,147,835,878,945,814,233,750,156,295,822,451,861,360,390,963,936,41,242,486,182,929,229,387,781,29,426,569,503,396,800,604,116,513,789,394,887,518,157,713,505,524,369,254,265,810,612,212,794,596,334,718,971,503,253,696,72,21,558,259,337,912,635,886,79,235,457,944,804,484,10,355,380,320,361,101,198,200,859,102,876,459,915,142,239,857,823,905,351,382,639,133,165,135,923,378,127,373,634,485,621,483,296,931,88,389,178,970,396,643,846,436,235,992,775,455,323,539,468,848,158,378,858,767,964,295,599,230,307,874,361,645,440,469,13,123,71,593,567,81,695,838,412,229,27,662,57,739,535,246,949,192,524,917,977,718,569,493,650,215,250,971,475,419,625,473,820,637,782,43,669,29,448,105,854,542,287,768,180,399,53,30,414,571,79,356,31,203,645,673,211,249,780,668,642,403,756,808,493,544,634,709,654,859,191,743,427,229,251,205,322,124,30,664,205,286,900,262,902,739,247,627,712,192,580,929,639,835,207,485,691,382,596,672,428,379,155,450,30,928,565,50,411,598,490,75,862,194,494,159,789", +"469,439,643,442,370,805,181,302,248,492,281,265,492,295,254,728,896,223,911,214,197,391,650,609,867,741,220,513,969,177,586,459,947,65,223,571,952,21,349,288,192,769,169,476,976,259,481,690,408,38,148,289,937,143,997,716,345,96,301,666,890,256,369,865,409,297,120,884,189,555,482,158,619,803,689,893,573,716,921,418,556,939,545,189,266,832,395,844,977,705,256,57,749,385,614,371,511,519,585,791,892,368,526,607,226,754,724,19,229,380,433,893,805,714,577,805,913,311,822,830,178,725,751,701,922,976,288,250,348,169,503,151,435,860,789,405,89,247,166,41,817,720,100,341,26,909,626,630,72,862,104,146,215,90,843,454,404,143,514,401,178,848,871,800,967,931,689,291,206,700,319,370,652,28,431,838,257,882,481,377,1000,713,511,490,758,557,799,82,258,604,156,26,542,494,877,905,278,186,92,637,507,620,107,702,732,66,854,410,42,398,459,216,439,425,609,310,670,397,615,354,929,599,365,75,527,444,784,825,796,580,253,473,491,824,895,745,476,153,137,623,799,797,408,957,91,700,931,431,543,371,659,826,479,783,727,384,566,49,441,97,774,174,837,544,833,738,789,351,880,565,236,166,847,956,879,809,983,994,696,857,353,104,769,447,510,717,934,556,803,179,550,888,63,594,331,453,807,918,986,30,705,177,493,736,439,539,270,203,681,612,929,511,283,445,549,686,861,42,515,837,86,796,93,659,86,198,719,788,274,787,260,995,60,774,590,126,964,340,197,867,751,670,92,776,862,178,757,861,819,893,569,786,249,726,521,223,292,470,347,310,105,573,952,657,482,205,752,183,290,146,672,509,466,701,187,327,703,138,54,940,194,878,581,928,566,409,690,596,165,80,883,470,281,207,329,707,183,880,204,207,399,437,503,99,463,698,284,282,454,611,90,703,308,190,511,147,475,967,750,381,366,20,867,588,235,618,320,60,859,792,844,908,436,114,87,22,717,988,751,451,201,63,790,926,436,734,95,56,367,143,257,914,432,846,971,89,626,303,903,206,949,864,428,790,277,111,428,360,209,713,547,518,476,539,827,245,205,858,692,779,526,475,378,357,604,0,629,87,673,282,287,505,507,440,363,718,785,369,883,544,944,626,167,579,175,390,130,537,515,16,734,121,308,683,478,482,526,716,767,499,56,18,77,659,168,294,531,542,689,823,843,966,831,347,341,350,808,519,963,62,855,397,569,209,556,778,619,364,637,219,180,572,960,276,657,908,389,6,235,840,321,288,439,863,425,778,80,516,427,222,986,622,702,913,391,138,213,667,597,279,409,794,75,509,959,992,903,641,987,19,857,298,678,748,715,126,760,538,192,810,470,581,389,798,355,664,154,776,489,121,965,644,691,419,769,676,105,973,721,550,235,178,809,904,355,830,978,913,41,23,910,643,787,776,199,658,67,530,871,371,305,796,61,411,73,464,808,978,631,809,390,717,167,429,780,254,872,444,86,136,979,129,309,254,847,940,172,852,165,167,361,685,381,666,27,490,363,461,770,922,299,245,824,526,917,888,202,528,389,542,56,232,471,251,372,573,432,155,740,65,43,173,887,678,214,750,858,812,945,726,164,288,109,145,127,283,350,449,341,157,915,757,289,376,709,432,319,598,399,250,896,16,225,82,902,384,991,216,949,949,761,373,443,760,196,177,108,126,678,512,960,953,458,236,172,558,407,478,785,792,124,58,123,41,258,414,875,399,17,208,704,135,351,886,981,151,524,127,832,687,104,804,887,445,383,360,532,312,243,211,795,558,981,36,959,21,608,695,34,569,592,556,209,880,339,438,846,465,294,645,346,228,402,316,430,812,349,714,175,29,551,386,110,433,416,924,814,905,781,994,169,163,736,937,385,791,501,576,696,113,350,670,333,805,236,733,696,312,119,390,464,153,604,998,875,568,502,516,297,490,445,530,751,428,554,389,443,716,283,653,117,664,538,765,792,16,586,708,339,888,383,217,974,209,275,312,187,390,17,844,765,158,182,49,760,468,921,271,28,800,975,188,323,557,12,995,303,301,182,331,345,643,314,189,446,328,162,928,811,908,624,748,534,383,903,289,67,211,725,116,61,435,485,746,367,281,545,119,239,311,881,866,63,701,612,185,11,884,187,663,430,162,803,33,528,464,377,669,222,805,90,606,68,299,92,68,875,38,898,760,655,369,609,483,482,449,768,912,160,328,524,525,564,53,231,732,445,789,994,757,491,48,230,6,235,385,647,978,712,144", +"171,966,299,410,164,144,460,219,12,910,529,732,733,650,230,907,329,323,81,119,995,810,637,883,625,803,915,710,160,823,114,425,6,722,921,931,501,849,215,578,409,658,321,689,875,501,165,568,51,887,218,145,528,832,825,321,347,385,238,437,322,464,196,515,852,439,712,153,880,749,182,724,65,986,802,650,345,855,43,42,785,799,28,505,293,444,196,836,510,133,460,336,175,271,200,758,451,726,359,340,111,51,743,835,637,656,907,806,807,939,254,873,607,3,924,320,175,614,412,292,358,470,793,733,367,635,9,77,601,647,223,730,794,345,966,896,611,491,100,209,112,964,839,577,37,282,862,195,411,32,636,438,381,249,521,7,946,781,566,976,607,937,835,758,269,386,511,825,901,393,878,859,870,904,25,263,866,130,649,139,842,125,256,337,307,160,950,947,86,943,819,533,348,107,876,291,231,345,403,632,522,976,764,233,57,739,206,356,334,626,552,448,89,67,946,194,873,162,712,631,364,13,611,498,493,988,184,242,493,224,794,84,759,858,918,713,937,476,433,994,409,614,257,337,183,299,406,708,509,95,275,370,324,128,433,6,617,847,15,166,115,370,678,873,467,761,836,17,859,18,428,600,840,608,639,603,890,993,777,642,388,247,550,159,858,565,974,936,317,967,842,821,260,468,355,454,962,783,558,614,615,617,741,573,859,192,205,669,689,662,581,148,106,501,18,535,730,210,102,423,47,298,821,795,972,481,900,253,915,946,132,372,782,546,887,907,555,39,364,599,874,685,471,919,610,186,897,764,971,571,129,467,355,946,506,567,999,818,476,964,939,946,638,982,933,535,561,903,288,239,408,851,600,40,495,315,97,470,68,618,719,444,303,655,872,673,910,92,346,869,533,548,999,892,87,863,387,446,808,859,395,522,673,274,297,850,97,207,105,526,680,146,276,735,315,655,216,127,440,260,821,641,737,993,29,349,246,161,429,200,701,423,210,946,974,246,910,829,381,325,847,528,922,520,862,784,575,23,371,466,890,835,803,455,683,752,753,243,992,958,400,608,347,979,80,406,973,517,280,607,371,630,184,3,73,315,876,310,4,76,387,531,716,476,921,629,0,506,705,890,534,482,796,254,111,644,493,95,485,728,549,634,502,312,465,656,531,57,858,670,107,658,318,339,667,269,841,689,291,81,142,76,60,602,86,621,632,168,636,499,906,498,839,67,168,76,404,158,683,860,547,455,282,944,988,426,820,736,320,635,115,518,441,437,886,109,693,48,660,328,575,235,22,160,374,176,15,136,682,10,686,781,754,818,670,605,547,435,790,954,878,921,995,58,621,266,989,82,396,487,701,556,961,801,15,87,778,538,766,917,70,893,516,77,46,756,748,138,290,950,796,664,659,491,582,851,298,766,650,691,377,563,723,832,269,413,918,874,966,959,59,599,746,43,623,823,698,899,407,527,231,698,91,269,355,224,315,795,274,131,986,618,253,271,344,668,98,673,194,899,341,831,415,378,296,990,444,839,907,686,127,170,845,274,885,656,229,721,346,458,221,566,526,973,45,659,683,241,894,759,376,430,445,815,344,241,62,286,733,818,338,951,931,132,76,286,453,361,364,994,302,16,567,385,288,966,473,325,900,236,792,54,658,602,694,376,985,946,483,832,973,994,440,274,110,306,374,213,129,308,737,160,652,338,109,713,280,240,34,753,33,420,695,917,641,912,299,175,178,749,974,275,89,802,311,969,654,507,687,941,531,265,421,604,196,256,219,812,743,52,264,929,346,212,46,271,965,662,738,101,980,70,969,912,4,960,787,144,58,666,424,181,970,260,724,242,273,498,401,925,623,603,98,319,374,541,280,356,561,50,549,234,318,886,772,703,243,793,710,56,472,214,847,739,125,378,727,746,578,77,167,864,821,584,629,807,54,517,145,366,698,332,967,756,599,942,568,750,108,147,638,86,484,606,908,181,959,998,534,963,412,268,790,11,841,652,589,805,677,323,441,29,142,683,138,142,909,174,499,57,472,778,250,904,836,255,817,861,703,613,352,60,883,899,6,483,710,251,363,831,491,913,729,300,621,838,811,80,449,198,823,790,122,80,16,845,960,613,87,397,282,11,317,450,336,687,165,81,913,718,823,907,575,23,327,509,556,609,474,50,444,352,635,1,591,526,963,388,306,144,822,789,263,282,902,495,716,405,165,163,562,756,926,911,710,621,162,967,234,291,345,650,855,118,419,870,897,526,300,213,388,566,493,151,518,794,24,248,450,517", +"993,386,857,74,925,140,640,812,455,410,839,313,921,790,324,334,929,842,319,277,408,814,301,274,776,47,797,726,562,115,946,962,215,403,540,104,602,161,311,913,321,410,814,264,499,118,100,740,598,508,744,99,728,165,688,951,157,273,961,685,241,280,867,45,858,285,703,334,935,896,875,698,486,126,605,313,69,777,727,994,786,783,738,382,516,77,98,817,625,463,728,315,982,336,691,616,554,171,401,531,161,344,564,752,828,598,35,675,239,966,774,612,173,778,580,784,105,713,418,948,805,127,816,558,737,962,975,521,219,646,504,243,472,305,876,18,757,352,545,303,901,740,714,654,587,341,20,115,25,879,545,412,62,219,982,223,303,703,445,73,681,67,816,928,116,117,659,235,638,515,61,772,681,931,855,126,32,131,514,338,555,744,467,870,385,296,57,786,618,991,295,732,873,993,699,17,904,634,20,214,470,667,847,780,846,659,948,403,51,939,824,223,644,292,727,597,241,916,47,252,579,992,181,887,100,898,349,810,937,491,201,390,178,27,54,439,81,634,966,405,330,83,523,409,916,431,35,657,955,148,417,931,635,414,846,170,304,40,345,884,572,636,896,824,661,979,10,490,201,980,148,805,107,415,459,552,243,515,955,681,443,450,299,575,330,728,365,82,201,576,992,385,650,894,958,946,410,860,828,574,770,5,871,347,448,457,15,993,947,3,418,231,632,870,417,177,586,333,623,656,186,77,533,260,601,963,180,291,185,515,177,51,935,191,324,867,76,725,614,160,461,147,197,396,38,356,184,375,781,748,699,516,873,193,204,390,500,858,616,911,375,747,817,479,639,500,26,170,686,482,888,903,404,737,962,45,488,252,682,930,211,509,52,342,347,175,320,482,274,875,157,285,802,674,109,106,9,913,641,533,129,360,239,225,454,205,314,289,966,448,770,801,454,446,933,394,370,205,914,834,863,33,443,552,808,507,257,105,341,950,636,819,492,936,790,192,316,142,988,884,80,313,681,264,976,222,153,963,796,436,666,20,700,149,132,970,461,575,80,714,104,291,664,222,947,86,270,759,995,865,642,712,184,972,930,468,160,713,229,634,850,561,784,440,347,87,506,0,855,994,148,573,199,288,440,333,38,60,324,873,640,83,142,774,530,603,474,100,117,112,486,16,563,890,976,444,188,929,933,574,107,835,871,960,745,346,180,5,931,307,378,523,94,614,460,541,592,805,935,994,538,829,512,18,489,258,702,915,935,322,135,862,808,505,489,205,241,285,984,77,262,677,952,611,406,980,547,52,280,545,911,877,839,839,972,504,158,591,765,139,148,115,945,784,618,105,802,688,23,975,270,251,394,696,812,732,208,565,561,141,544,964,608,490,861,750,670,755,823,645,863,974,225,624,240,706,742,763,165,847,164,834,936,454,428,47,721,85,117,342,80,140,676,354,684,986,639,325,515,939,772,772,588,624,918,869,709,266,520,190,990,42,754,451,779,925,514,345,58,772,191,722,715,512,743,985,716,505,28,448,190,44,232,166,617,225,372,844,712,955,228,132,914,231,946,257,860,41,23,262,436,201,5,470,964,829,585,3,562,534,983,381,136,852,921,816,98,802,263,671,396,547,359,240,454,759,294,649,127,591,964,977,440,758,22,486,660,535,106,206,579,973,144,667,736,783,803,926,11,849,632,672,210,606,797,749,713,633,247,83,862,852,398,205,149,156,718,509,527,301,150,384,870,64,142,194,431,850,247,316,57,795,397,793,884,210,651,652,711,620,349,168,288,647,432,683,436,539,284,275,900,367,687,288,952,511,229,854,682,786,152,186,86,683,731,462,120,624,82,892,911,627,848,431,711,561,808,309,770,136,28,172,953,2,207,892,663,932,360,745,252,427,874,322,31,284,215,842,707,334,813,67,97,411,238,865,262,687,226,825,85,786,673,947,256,287,29,723,389,962,407,226,215,37,456,17,869,13,359,569,207,908,852,370,267,803,485,268,23,134,877,35,986,568,400,692,156,360,912,932,755,709,446,730,598,658,169,368,752,600,542,181,394,608,181,483,143,821,752,674,5,231,138,412,410,174,483,252,801,472,377,842,715,552,19,549,192,241,150,859,213,832,909,573,132,652,281,783,691,306,555,21,291,746,348,798,796,677,544,794,826,519,90,37,290,998,526,175,855,444,889,761,149,271,811,830,353,875,365,196,46,304,117,869,901,335,601,780,813,511,60,882,469,670,938,632,825,655,875,50,982,370,928,947,342,548,500,85,290,730", +"886,512,539,411,454,433,557,514,171,432,90,38,274,368,176,722,462,920,741,717,118,550,562,111,350,279,447,610,24,461,758,251,791,420,689,202,364,343,182,392,334,187,262,537,783,735,426,717,52,395,703,682,796,663,631,572,296,702,463,833,181,469,470,186,210,978,655,288,750,926,385,889,633,985,258,715,545,93,635,206,311,162,994,535,517,730,175,441,485,574,480,545,111,948,140,606,401,288,814,392,935,448,370,338,877,134,975,978,201,335,402,902,351,612,373,949,668,637,138,810,576,471,681,162,430,787,715,263,386,173,819,189,511,110,794,141,400,70,39,345,256,386,744,379,26,752,710,691,373,589,204,774,983,51,347,360,309,368,83,371,235,722,523,420,633,115,320,114,556,445,529,192,45,891,884,993,12,536,234,229,52,574,898,556,903,308,952,657,670,752,427,175,921,226,755,165,699,264,493,815,528,455,458,400,840,493,564,21,230,100,892,543,541,80,136,20,623,443,51,674,165,727,268,644,325,141,149,615,100,835,724,560,877,411,293,741,744,162,557,297,719,637,713,329,841,844,646,455,214,366,805,917,226,404,45,293,350,808,916,318,923,941,558,880,948,103,881,140,344,236,378,545,973,112,30,895,559,738,636,246,599,696,678,71,173,324,288,702,326,557,912,949,970,593,522,744,461,606,596,440,850,79,615,540,652,159,276,377,15,866,387,592,999,480,701,946,610,225,39,453,61,662,771,485,227,983,262,627,84,263,501,641,706,230,667,209,556,770,442,545,93,194,194,74,382,399,220,369,988,206,831,756,619,851,513,420,991,749,560,74,957,951,886,659,53,628,840,523,536,334,114,971,372,486,777,783,699,979,603,952,99,876,359,809,630,250,424,309,741,707,288,132,863,749,716,429,696,757,392,170,289,760,638,348,586,714,834,968,432,786,197,627,712,769,114,630,488,521,14,594,548,738,828,941,399,600,456,661,441,92,44,979,967,318,763,710,619,89,571,773,36,399,100,368,213,772,356,672,82,930,894,687,841,512,742,13,448,122,641,430,274,426,165,399,102,812,901,301,265,762,93,980,46,935,993,445,897,754,466,843,63,702,647,356,428,673,705,855,0,807,952,633,333,999,974,44,916,499,927,540,590,467,467,371,862,407,526,670,423,554,736,199,586,337,705,408,633,550,548,179,402,680,158,640,967,506,139,258,641,557,63,466,389,222,164,544,14,275,382,180,867,191,217,839,615,856,102,970,931,798,961,644,149,326,191,453,140,716,701,456,144,239,628,265,211,781,776,178,254,519,522,550,536,420,671,801,564,63,415,495,284,255,987,116,531,966,524,278,521,286,533,553,490,988,294,111,644,551,805,155,230,54,525,116,507,444,626,20,300,800,933,983,206,930,400,914,332,740,424,188,341,842,221,810,256,348,713,304,306,958,731,548,916,22,361,311,183,14,620,388,526,626,676,997,961,299,121,71,524,271,133,486,439,479,370,76,988,730,217,704,957,122,477,210,50,407,704,231,615,574,167,43,36,807,811,549,203,591,802,439,52,373,574,172,849,218,69,317,1,64,370,965,205,38,788,251,515,18,168,456,959,690,447,742,768,839,464,296,86,374,568,946,869,916,447,754,397,809,481,73,376,361,647,477,574,130,723,674,699,825,810,283,814,126,986,36,482,93,577,632,401,411,422,905,282,384,97,313,812,98,911,286,616,696,209,669,505,705,422,70,477,992,574,28,779,558,236,796,621,981,174,52,575,829,340,30,815,149,955,960,432,243,806,922,467,405,282,462,265,74,8,220,894,150,405,960,376,649,127,770,912,237,642,854,645,851,903,222,48,815,529,316,292,321,537,358,997,441,365,573,277,610,40,831,632,709,447,653,26,861,813,972,530,795,306,883,581,137,632,260,471,407,258,543,321,458,832,180,931,387,283,620,496,923,174,212,405,241,586,163,568,284,282,107,235,88,440,900,882,417,500,923,993,494,196,477,229,661,24,33,646,981,478,987,365,880,661,356,470,483,772,678,330,923,501,317,399,980,835,626,982,18,918,362,589,944,790,44,541,393,951,242,390,852,395,648,401,33,549,187,989,495,556,716,297,907,397,527,737,783,845,590,20,426,694,549,292,661,629,59,810,227,159,585,9,21,796,324,253,628,521,685,110,974,314,372,146,575,632,496,401,822,287,709,150,322,801,668,365,793,262,76,155,222,49,792,869,487,818,759,721,655,696,162,715,690,492,797,166,891,986,117,503,945,813,198,523,329,66,647", +"130,521,210,459,333,396,566,256,23,339,670,963,280,859,738,565,104,200,516,845,931,72,898,661,165,216,827,520,386,780,613,452,151,204,87,946,564,474,896,608,55,28,266,986,101,874,482,177,535,940,802,833,450,538,427,233,109,164,303,44,874,181,179,154,78,550,597,483,785,410,664,418,651,751,203,835,809,74,871,476,908,461,645,555,681,750,252,291,768,650,964,169,437,454,890,829,432,893,596,567,629,978,99,303,475,411,278,816,515,64,648,412,298,994,197,655,121,793,381,798,188,773,44,729,848,717,700,85,393,238,202,437,664,889,649,298,152,485,717,104,949,172,379,991,336,737,317,279,463,993,236,203,418,265,89,862,438,725,272,418,17,150,872,408,499,588,985,810,393,253,390,531,884,13,799,596,866,515,971,160,955,255,141,956,845,755,122,556,878,701,92,334,617,364,665,421,861,421,28,221,663,818,263,93,336,354,111,500,150,109,588,158,361,951,968,964,900,980,141,242,944,437,224,97,184,305,423,589,767,713,195,227,648,40,420,700,519,30,945,464,294,95,749,307,246,93,621,535,949,977,433,960,828,986,672,217,376,379,561,20,284,878,117,341,800,622,929,849,309,895,291,468,704,201,331,948,403,540,386,503,615,21,919,977,823,470,452,523,671,200,411,761,432,921,441,527,981,845,735,644,784,549,35,31,697,428,211,849,522,664,504,703,212,251,128,130,393,896,605,108,861,22,608,882,55,876,447,641,395,449,250,323,834,763,67,267,141,648,342,411,344,433,236,946,823,962,520,66,38,992,341,432,439,453,564,571,416,496,416,174,332,648,876,402,543,775,549,268,707,974,561,938,403,6,618,873,300,868,233,89,955,994,157,338,126,597,791,648,953,202,540,598,491,347,495,499,98,97,887,913,740,744,169,67,52,192,742,516,386,636,420,993,376,573,589,503,900,606,273,981,601,484,907,35,845,752,869,748,511,354,917,830,584,665,969,698,61,369,898,199,233,699,124,77,681,848,817,671,688,2,227,903,6,994,51,131,65,25,450,747,547,676,154,566,270,267,911,529,285,539,958,505,513,571,924,884,805,185,125,217,751,316,49,966,598,282,890,994,807,0,761,662,969,35,332,598,50,674,910,873,904,21,287,656,143,923,89,244,326,84,127,55,968,299,285,304,34,662,491,934,978,790,361,650,270,822,926,97,232,182,618,988,619,107,761,971,299,942,863,273,773,525,862,591,894,12,435,675,117,396,528,970,970,142,230,771,510,623,347,171,34,820,921,639,716,832,16,88,356,212,190,159,742,901,232,966,717,888,820,227,884,507,708,322,216,812,672,204,122,773,577,411,135,145,366,986,783,618,365,292,381,931,585,605,342,91,539,213,8,195,855,916,397,723,955,610,306,479,869,265,192,116,626,494,504,104,213,760,423,452,665,236,340,819,780,609,741,704,937,207,603,400,24,31,646,971,81,887,573,157,329,296,101,173,60,243,913,461,851,484,320,454,24,448,872,465,389,847,208,628,257,823,634,957,511,94,689,379,758,96,161,597,735,444,739,824,739,474,951,53,122,690,95,973,244,506,417,294,642,196,876,190,290,324,326,163,785,709,966,757,171,197,371,254,593,690,428,276,701,886,476,760,964,684,212,612,426,145,387,952,821,17,634,90,633,815,263,826,19,169,25,954,919,120,967,89,449,27,291,457,912,366,139,662,334,785,235,706,214,192,965,82,109,885,672,678,220,359,505,818,10,290,311,560,91,592,652,904,591,113,798,751,495,910,995,137,726,693,311,1000,543,680,484,171,671,203,2,60,72,617,475,588,954,820,3,614,964,80,468,74,286,325,436,867,640,137,39,263,904,173,447,810,105,886,653,782,196,819,428,682,944,755,557,812,932,392,847,155,729,1,292,846,734,300,957,342,498,919,691,237,408,786,438,644,903,571,675,72,690,573,438,186,978,504,546,314,937,59,37,347,249,569,202,204,266,979,347,295,887,124,307,776,539,880,61,211,956,354,273,131,823,850,547,443,130,678,288,406,39,93,304,564,927,71,657,866,196,888,213,461,839,266,660,658,793,815,659,991,477,612,969,688,967,544,88,71,538,755,559,738,621,735,95,918,914,470,868,922,24,764,677,121,281,909,177,342,933,384,919,709,546,918,151,709,111,143,65,604,597,129,97,193,429,400,964,930,710,475,200,855,553,840,363,735,800,22,361,778,480,598,249,546,940,779,581,554,886,783,604,272,952,513,121,887,719,417,972,486,589,100", +"871,589,559,89,458,516,9,41,770,627,442,361,796,246,720,18,230,735,940,197,894,76,669,778,393,493,681,78,911,548,303,910,428,795,933,168,26,373,523,320,247,156,33,249,809,261,383,430,251,197,739,729,968,972,171,35,230,676,946,738,855,824,705,326,904,723,930,745,420,873,708,475,593,330,341,765,829,872,858,162,497,629,620,500,508,875,224,714,806,503,408,346,17,842,693,525,720,615,168,283,740,490,439,961,790,80,425,517,260,477,642,483,536,455,119,33,641,547,779,42,48,531,335,69,486,669,268,671,12,282,376,27,671,854,346,847,120,398,96,19,804,772,964,844,214,730,487,971,100,382,286,499,937,353,613,686,424,179,998,272,168,852,359,653,272,220,461,666,622,714,457,76,515,384,634,77,220,862,232,980,937,766,347,725,360,321,560,148,135,193,248,814,153,430,671,641,917,217,177,459,734,626,479,649,225,73,361,763,505,463,550,51,299,638,717,24,114,415,164,799,362,35,809,161,578,503,957,349,604,521,497,401,449,872,373,718,140,577,515,292,741,622,516,450,129,527,482,999,393,885,608,610,401,865,240,979,854,280,160,902,308,555,906,662,135,365,354,841,315,516,338,46,238,389,922,657,31,33,128,863,157,156,136,826,936,254,868,117,956,108,351,873,275,574,510,146,840,943,812,509,31,852,827,20,106,891,241,382,30,421,963,996,414,772,739,525,121,753,398,980,386,155,575,857,369,284,54,957,465,724,467,899,724,698,947,500,658,410,926,691,336,563,181,330,725,299,255,841,645,737,101,792,999,208,608,196,592,732,587,725,402,173,239,366,775,831,652,148,388,337,765,820,564,807,741,464,871,445,414,961,339,835,453,620,375,596,452,22,177,887,390,474,866,224,510,663,797,441,326,675,512,407,613,793,272,691,701,509,857,47,258,883,748,395,309,95,301,451,365,366,697,296,510,294,23,9,279,676,997,263,471,803,143,741,242,674,442,483,946,500,588,317,494,941,212,777,770,798,980,508,417,380,415,317,794,339,858,993,495,801,669,271,961,221,224,18,90,635,58,277,146,334,254,732,717,847,651,941,634,798,696,53,687,728,728,287,534,148,952,761,0,515,999,694,134,280,882,746,15,294,56,448,451,650,616,6,391,524,456,124,473,963,348,686,216,592,901,178,715,890,354,46,691,173,840,798,512,512,898,305,319,553,845,28,138,668,16,361,31,424,644,825,565,597,485,147,927,293,551,660,911,154,105,584,636,299,51,420,559,411,607,577,414,271,653,635,247,941,56,349,443,727,920,787,559,424,460,164,972,835,220,19,702,533,540,84,798,233,521,562,310,481,491,428,614,345,753,474,554,993,529,917,167,414,603,585,123,873,175,647,899,203,757,840,284,124,184,599,14,501,896,841,903,831,537,343,86,424,655,233,837,336,961,74,121,787,87,397,484,589,53,630,667,994,32,822,433,268,67,961,431,599,285,351,385,136,513,767,97,171,717,826,479,785,450,712,838,334,603,963,465,27,384,518,403,652,901,675,869,520,816,985,776,589,881,272,396,853,571,319,161,602,251,494,708,618,903,689,216,162,816,648,14,632,261,244,908,179,179,548,589,71,921,919,986,406,929,243,862,201,452,34,219,440,359,20,672,144,839,131,659,469,987,257,5,246,236,780,652,523,411,556,91,664,227,376,321,476,355,251,16,686,684,372,898,110,64,561,668,978,338,592,241,665,903,756,199,575,599,557,50,544,548,421,387,669,105,635,949,970,834,70,614,324,791,9,480,790,168,314,550,969,779,791,972,669,30,723,829,348,908,98,277,580,602,927,509,537,452,149,397,424,843,776,879,613,448,669,567,941,734,591,11,630,828,205,906,624,937,582,985,291,979,249,717,383,480,232,824,796,960,746,895,599,534,902,469,158,312,236,349,161,707,818,339,361,689,527,435,917,638,128,344,485,394,327,173,368,227,504,841,128,149,72,859,494,66,285,237,924,263,544,659,876,783,213,26,679,328,20,249,214,191,845,426,118,112,189,304,49,515,268,237,520,135,693,396,402,402,102,1000,713,404,885,89,178,277,411,225,816,481,407,473,403,588,889,212,720,361,789,917,438,500,971,941,934,964,396,159,132,708,139,478,62,210,807,262,92,788,597,400,38,544,330,632,581,866,850,542,236,955,603,504,22,135,849,900,738,209,464,491,937,301,852,162,1000,757,161,104,558,561,314,148,477,624,171,814,679,978,970,500,992,844,72,504,537,19,601,986,889", +"752,218,670,577,739,367,235,821,940,935,842,431,541,106,472,895,358,751,520,513,293,829,697,222,431,222,707,530,550,268,879,986,919,296,764,940,84,807,460,978,134,573,667,947,497,643,579,624,748,678,60,113,814,830,403,874,641,940,492,728,475,323,173,206,757,636,259,29,986,962,604,249,392,853,882,397,887,207,239,965,923,117,885,431,358,605,852,594,832,719,215,780,587,372,376,781,19,253,523,977,806,970,724,658,871,768,35,412,40,307,36,257,2,548,864,173,255,679,309,325,188,512,640,66,528,308,310,458,196,331,285,141,127,771,437,317,264,562,362,19,709,110,944,999,678,291,613,767,619,454,537,640,82,462,499,838,128,282,515,426,725,123,910,501,386,661,214,952,674,722,186,406,7,470,820,713,39,495,292,184,244,598,30,675,228,656,757,124,978,191,907,639,845,136,915,896,803,207,94,604,562,891,283,683,250,48,175,56,447,542,146,413,592,776,998,940,594,794,175,472,943,59,999,925,705,218,990,313,577,467,772,29,558,209,61,643,682,70,798,375,514,261,460,951,541,827,891,520,588,424,827,55,691,161,101,592,184,841,172,50,293,904,666,640,35,516,63,631,26,337,80,917,514,225,654,976,798,126,675,140,240,394,590,970,213,700,265,997,563,49,334,7,155,876,115,954,33,574,619,814,354,385,131,588,388,790,542,800,738,373,315,899,306,53,181,194,737,788,651,672,803,198,442,594,490,21,769,265,67,309,892,688,412,943,754,185,626,374,770,21,215,507,577,378,400,332,915,686,733,205,895,750,961,691,508,140,216,523,415,544,223,618,173,621,857,739,188,175,531,404,765,383,625,285,61,707,325,320,828,345,551,920,955,743,627,592,290,11,240,309,558,558,420,557,420,137,916,855,79,684,825,2,240,460,652,148,160,207,277,31,799,132,959,807,697,249,537,162,213,617,156,978,814,92,895,424,709,617,948,763,399,937,583,328,605,691,342,447,403,298,699,295,389,166,353,878,25,683,720,64,619,83,119,641,49,944,403,108,959,195,455,227,402,740,722,799,82,162,331,236,727,429,460,205,696,99,319,536,472,930,732,393,564,319,657,505,482,573,633,662,515,0,152,26,905,884,949,669,486,273,47,585,529,59,66,743,98,589,698,514,125,882,130,686,536,364,320,771,947,694,162,975,578,837,727,872,325,910,730,344,749,210,984,938,908,307,693,177,339,754,242,459,339,443,812,446,452,51,468,937,151,712,224,720,184,14,263,797,815,482,853,581,271,646,460,120,382,484,440,49,561,93,337,764,589,19,347,805,732,10,46,756,691,328,31,937,770,253,672,233,101,488,746,661,893,953,884,616,983,125,726,184,322,491,57,306,699,221,373,761,323,677,625,607,773,504,624,763,498,992,399,787,270,293,772,133,581,810,307,493,129,940,363,473,222,548,462,323,620,861,223,940,551,696,278,459,198,801,266,423,476,67,25,20,487,44,502,934,873,191,886,941,292,657,215,133,196,172,795,102,728,866,677,429,722,616,886,82,538,155,31,195,208,418,330,666,688,327,764,397,322,567,428,677,810,66,647,199,433,856,968,148,131,723,65,94,894,803,591,562,251,202,659,401,456,426,333,510,73,792,809,12,46,769,99,238,416,616,817,604,454,62,13,563,733,883,874,563,20,477,345,383,594,294,142,930,149,496,171,41,902,506,694,656,116,742,47,250,471,877,733,169,699,493,149,539,274,655,76,765,589,298,280,556,711,820,412,870,486,833,504,546,838,589,400,716,128,405,610,483,967,408,997,877,560,608,769,774,219,410,995,21,173,707,569,264,878,960,172,604,601,416,279,549,949,791,972,592,916,590,721,258,953,164,62,868,878,509,112,67,722,636,201,635,952,432,692,570,223,163,695,307,615,448,379,387,728,553,301,336,168,781,926,197,549,696,179,88,260,440,543,591,902,85,799,708,520,249,118,84,425,617,162,81,547,822,253,221,907,176,657,103,326,493,431,627,899,331,311,916,54,778,636,422,533,829,592,855,721,12,815,693,822,298,636,739,874,180,851,18,12,403,880,799,392,632,643,362,522,85,553,92,313,319,374,769,195,778,783,810,608,6,919,505,562,966,581,276,246,893,118,352,124,113,315,937,657,408,453,432,917,209,717,686,667,37,579,681,61,792,502,529,788,618,202,675,652,319,100,184,732,616,108,717,386,359,503,313,569,502,778,807,552,364,222,777,638,396,184,511,765,917,479,241,863,619,165,30,99,114", +"217,481,477,969,15,764,410,398,972,499,65,537,402,15,523,851,485,438,758,892,65,69,560,674,915,238,923,684,299,83,753,451,539,447,262,466,576,225,422,695,618,746,89,947,703,629,803,494,71,443,695,346,538,514,201,472,371,191,716,83,97,729,874,214,943,692,755,949,838,864,659,665,169,399,31,681,648,841,734,568,257,616,169,361,105,568,627,972,894,514,178,45,165,332,886,227,938,588,898,276,125,296,954,726,697,90,175,368,531,206,531,982,648,549,484,176,405,420,216,621,928,546,919,516,941,933,80,949,542,740,136,763,209,516,496,794,525,714,987,831,989,605,696,364,915,99,296,759,826,240,307,862,521,940,74,725,56,620,402,655,268,546,471,697,985,242,379,713,552,180,34,781,471,751,29,805,314,294,302,41,405,226,611,307,14,225,649,157,920,340,46,458,328,981,337,891,717,257,741,417,422,131,100,985,182,650,955,97,59,512,228,150,927,114,890,476,592,866,281,187,233,876,31,585,839,481,971,63,866,450,418,661,801,519,392,786,674,167,588,2,97,328,538,161,506,939,429,614,80,954,955,34,81,209,171,161,911,656,986,73,952,717,273,97,787,683,571,233,310,121,478,881,243,33,237,677,628,804,120,921,666,641,722,157,528,139,801,632,647,384,532,332,484,96,899,185,423,511,704,61,592,964,618,84,693,252,171,833,470,490,815,100,308,803,965,103,726,923,664,166,189,692,598,887,886,321,659,282,191,601,314,190,384,425,74,125,672,796,476,414,974,876,158,152,989,789,348,975,18,43,642,927,431,945,230,981,530,79,233,308,776,391,482,153,927,201,757,734,41,698,677,825,40,683,651,13,898,232,523,469,312,293,493,888,803,942,910,344,949,997,582,202,522,649,32,368,717,877,716,255,364,396,484,304,704,652,218,459,212,20,61,554,620,749,80,549,375,3,114,619,854,864,910,134,922,371,254,698,978,634,346,734,387,460,247,442,560,476,600,412,897,362,151,569,783,100,869,583,150,369,429,47,812,628,995,851,922,675,728,979,201,83,652,100,954,466,252,963,908,438,638,787,609,686,261,372,115,384,56,616,87,643,8,762,950,507,796,199,333,969,999,152,0,398,432,353,692,948,729,813,649,679,1,615,25,946,173,833,6,186,175,948,735,360,952,507,247,18,539,885,888,760,924,895,783,859,119,143,260,471,262,462,900,31,390,910,619,640,440,185,631,862,413,159,985,348,773,236,590,34,882,738,271,729,549,379,499,658,146,289,198,19,367,675,279,848,299,218,930,412,928,559,12,967,834,868,790,342,156,405,601,265,746,474,967,370,111,810,584,684,583,950,274,772,498,936,25,659,474,706,473,678,691,588,768,84,854,989,93,771,102,636,858,525,722,511,813,944,501,692,388,304,727,199,360,724,209,875,413,175,419,782,358,641,458,177,376,22,461,593,500,191,872,629,841,544,567,948,979,66,730,116,795,393,16,920,265,55,350,859,441,358,33,931,372,222,957,179,725,242,242,356,898,550,256,878,821,619,372,263,781,314,381,916,280,588,592,55,610,460,989,109,395,974,104,106,8,63,86,671,836,277,549,261,655,503,536,529,281,873,138,855,573,138,720,423,121,200,606,317,804,53,43,646,565,233,141,117,898,46,341,823,225,800,395,808,748,268,870,251,522,647,104,536,42,467,971,595,425,382,767,699,564,310,755,34,965,976,764,989,350,701,327,783,344,771,197,768,154,824,68,86,535,466,81,94,154,844,612,664,997,257,46,23,978,718,414,507,468,312,461,546,721,870,10,899,363,354,344,212,36,337,64,120,220,883,386,958,24,263,931,501,311,79,355,670,869,53,55,481,759,806,137,987,836,651,958,813,162,361,309,459,416,277,910,988,211,481,585,247,878,900,160,32,722,317,381,547,345,726,414,633,390,62,623,385,510,442,642,698,839,266,650,180,239,633,296,376,867,260,313,72,587,968,157,701,280,345,75,808,294,956,220,110,45,207,329,7,854,526,597,547,183,11,276,145,359,594,937,572,373,915,134,389,977,928,317,919,874,201,923,992,744,42,870,836,775,826,124,14,646,800,420,397,141,774,682,291,484,993,721,91,577,717,309,167,4,554,763,910,767,21,310,922,502,306,186,994,462,164,499,545,590,334,809,384,682,586,352,108,929,303,873,97,224,592,303,864,490,314,381,235,189,958,21,671,37,614,316,650,610,367,884,674,792,720,878,675,795,647,681,973,569,279,717,917,22,49,180,922", +"896,288,766,74,856,935,959,717,368,73,520,418,456,694,221,479,190,435,257,527,706,311,28,328,840,140,745,515,547,458,437,919,207,948,436,648,301,685,874,44,180,346,934,17,437,478,147,611,910,755,421,499,980,363,101,568,358,690,681,930,246,405,199,668,278,188,478,103,572,613,65,232,487,496,658,512,870,44,754,527,913,563,21,939,475,173,367,293,781,767,309,391,645,45,778,49,350,538,725,758,136,260,746,665,850,203,26,259,466,362,461,357,921,593,579,694,330,478,429,520,861,587,579,974,739,451,209,945,655,310,880,988,709,232,861,3,551,760,455,954,366,590,517,826,260,350,62,910,103,987,941,585,124,416,501,364,855,516,389,503,240,676,148,657,975,114,459,13,432,153,659,404,14,223,333,150,479,684,301,414,19,926,386,549,262,914,342,585,802,208,621,508,691,493,747,408,805,696,860,676,151,203,346,124,53,784,870,656,682,576,91,397,6,296,93,824,617,225,560,100,71,766,989,567,389,259,715,198,628,249,33,540,783,756,357,179,46,65,923,922,81,556,824,572,11,41,882,15,223,498,616,879,976,310,721,381,306,6,682,626,879,738,524,535,275,796,11,553,573,760,136,352,32,471,800,346,37,84,68,834,926,681,208,564,839,861,469,444,59,248,349,723,361,992,366,102,492,963,2,112,401,727,223,20,36,389,895,595,993,517,152,621,777,745,561,803,981,997,893,183,3,199,108,339,490,322,355,676,837,860,669,309,840,667,223,585,826,391,699,130,603,212,138,357,462,527,745,513,766,919,612,844,216,649,468,789,871,767,480,214,947,339,372,177,480,585,697,543,422,844,759,720,10,919,584,367,440,22,490,104,136,758,738,82,465,259,931,880,167,29,181,228,188,889,883,97,681,914,643,841,219,83,636,309,38,706,850,1,414,95,840,460,715,957,402,939,549,280,370,302,29,172,65,806,817,45,14,498,668,410,365,375,979,277,219,125,659,176,994,580,80,928,959,607,8,222,58,312,584,520,71,16,184,223,729,44,908,709,761,505,257,77,870,505,499,942,553,840,137,274,874,7,82,937,716,848,899,907,119,863,839,389,301,242,224,440,254,288,999,35,694,26,398,0,528,534,101,683,861,371,811,467,992,245,846,654,817,789,774,815,269,721,860,71,733,902,508,207,88,150,745,337,796,105,623,483,938,13,383,716,564,805,154,138,159,381,534,476,339,927,976,76,466,672,420,693,231,993,246,214,465,380,300,148,579,426,336,951,983,262,603,260,239,486,242,106,961,679,854,969,374,544,623,553,686,783,692,572,47,152,717,717,94,356,219,818,415,917,424,64,885,649,712,535,325,995,316,23,502,334,568,597,773,342,624,165,362,205,877,896,186,865,832,34,194,810,608,844,234,472,423,849,711,962,908,484,182,479,355,894,851,243,594,398,71,111,484,320,683,916,895,234,923,580,97,673,807,887,134,355,349,261,751,646,995,914,490,526,775,819,326,930,193,556,21,650,158,558,525,1,429,253,331,153,389,634,102,201,314,12,569,595,163,483,207,792,848,67,303,685,231,404,482,995,693,19,560,366,11,412,595,818,429,233,743,318,809,512,814,39,316,655,810,158,342,712,935,559,192,91,424,576,984,718,815,170,99,967,846,445,213,653,828,968,414,712,627,721,60,205,715,236,207,911,74,837,27,320,683,199,800,980,33,860,848,944,863,512,545,860,51,226,795,388,452,219,885,31,857,71,880,374,995,584,72,203,392,706,823,445,820,938,636,724,3,274,834,845,837,894,816,901,122,139,774,999,73,146,287,748,887,227,78,397,216,796,884,46,248,819,639,121,816,3,781,664,818,4,980,194,27,896,191,952,889,211,432,566,212,264,597,631,216,938,718,833,410,645,203,950,383,573,582,368,64,287,909,994,189,596,450,784,405,652,244,849,907,36,555,600,640,464,87,590,870,523,371,703,143,555,48,927,935,190,913,156,741,270,332,563,5,786,537,491,397,538,439,926,232,528,45,161,777,957,280,608,463,7,658,837,937,439,257,409,648,133,784,954,883,811,280,626,48,128,535,945,391,362,881,790,816,5,826,913,545,9,691,446,569,55,331,433,161,262,845,424,589,964,144,922,910,530,925,640,563,697,12,261,861,815,70,608,203,17,961,493,110,50,410,278,700,618,80,413,140,541,428,383,869,485,834,254,573,171,344,556,797,921,917,826,320,135,563,989,356,14,2,253,451,880,781,924,788,513,661,525,961,811,536,473", +"446,995,400,672,35,892,527,885,53,507,320,275,110,233,609,225,164,788,316,20,99,31,841,499,351,447,897,761,189,468,631,429,910,562,585,199,786,310,523,130,603,42,864,634,539,483,310,494,669,363,561,577,506,390,406,987,800,37,276,28,816,494,692,354,488,617,829,550,511,70,138,194,428,25,689,657,882,723,443,717,993,122,942,838,140,463,963,516,354,859,631,521,668,163,329,695,200,457,350,70,513,568,593,564,912,175,762,270,956,284,161,408,790,518,155,845,319,754,490,240,973,699,944,362,726,212,990,914,503,22,145,420,313,739,541,846,694,742,877,248,420,754,534,644,950,732,52,894,714,924,156,228,654,378,720,703,861,8,18,915,281,539,68,687,506,153,628,752,781,32,989,824,810,431,358,256,621,914,260,264,398,244,527,334,450,376,387,278,281,574,64,748,489,553,861,418,558,38,722,861,85,844,754,846,586,794,564,99,340,966,965,954,175,184,900,305,815,76,427,758,242,132,477,224,34,923,994,509,813,727,284,867,575,204,883,739,907,989,694,31,353,210,297,887,505,846,50,954,289,795,569,501,922,532,60,542,408,709,322,264,87,442,925,801,604,475,236,920,316,421,211,633,634,266,226,183,694,973,194,959,818,228,734,584,888,697,660,668,960,555,113,944,239,111,73,149,428,383,59,147,513,358,672,284,357,11,520,235,795,149,534,427,437,893,620,648,871,50,319,247,379,746,716,801,266,486,668,814,332,341,380,122,636,212,296,67,791,45,468,369,276,724,76,840,746,627,967,745,657,8,327,702,865,970,581,177,826,423,525,763,908,916,668,342,139,564,102,428,811,116,573,856,876,546,610,729,557,596,499,332,654,603,602,407,898,522,572,381,62,815,306,354,939,713,799,240,87,940,690,826,817,87,643,622,611,250,365,609,28,747,982,318,136,559,903,129,539,722,779,85,224,189,835,545,888,219,631,599,543,938,150,285,79,576,753,649,269,1,985,340,842,827,95,559,942,805,628,994,308,176,460,937,978,156,32,962,184,111,415,30,478,580,553,446,876,579,366,868,304,940,760,139,70,797,229,796,288,71,6,230,866,246,995,815,576,363,111,440,974,332,134,905,432,528,0,471,930,18,631,955,144,507,121,277,884,450,516,370,834,693,856,237,676,241,730,903,264,755,610,697,974,523,798,172,992,63,608,262,615,187,424,173,512,960,779,746,890,434,438,602,984,923,950,618,178,948,724,73,358,584,283,671,46,78,637,234,381,848,885,627,50,10,17,795,997,595,716,419,832,562,927,71,635,912,615,506,246,439,855,782,443,843,504,99,463,852,37,323,221,28,92,878,396,424,576,245,618,827,296,447,852,914,468,576,983,238,627,458,116,381,381,344,362,168,793,933,211,771,707,241,945,331,427,235,46,500,837,648,89,903,656,134,343,965,743,888,961,525,800,598,806,936,254,558,129,406,164,148,975,571,675,663,860,743,119,139,615,616,388,121,674,89,522,432,675,406,128,576,442,284,566,590,195,50,794,725,93,464,710,129,424,393,10,394,125,62,465,644,444,765,723,903,113,117,636,998,9,827,542,272,898,173,180,9,156,961,876,501,493,143,393,503,275,910,206,842,717,476,18,743,215,972,617,738,122,731,873,903,754,648,439,537,676,327,617,812,409,326,629,411,922,94,528,734,201,28,794,767,677,774,165,381,230,149,782,898,644,611,255,376,258,366,132,926,288,706,654,472,750,671,736,110,950,520,618,130,928,9,466,808,704,289,694,693,128,136,655,225,547,139,19,6,532,557,582,341,468,955,767,383,661,97,71,669,595,258,891,796,790,209,771,538,501,767,294,960,521,657,292,768,103,526,940,409,232,495,606,914,143,119,153,620,986,126,742,349,45,265,399,746,868,766,841,81,69,471,46,861,294,937,380,635,785,162,416,74,737,903,24,706,254,148,143,740,417,234,677,225,609,357,856,46,863,696,409,362,173,358,558,895,970,302,359,996,404,991,663,787,191,559,641,564,709,32,480,335,742,296,289,524,101,242,523,572,257,297,326,861,501,893,738,125,887,798,555,141,816,219,18,121,864,760,546,895,939,68,100,190,213,511,549,4,243,691,363,150,162,548,937,881,225,760,583,625,416,871,121,275,921,949,592,604,455,550,904,57,486,600,673,46,519,508,392,831,32,548,448,948,791,952,445,449,993,689,764,353,618,681,204,780,706,946,128,461,793,164,951,282,417,511,924,210,919,357,318,353,711,356,482,140", +"66,791,17,930,467,78,370,940,785,421,513,295,256,331,45,102,810,290,813,410,577,66,790,811,424,447,663,378,499,349,702,387,184,238,30,6,361,117,139,283,503,343,29,974,554,32,193,771,586,672,684,488,526,34,487,94,569,265,383,550,99,667,380,732,386,949,373,637,410,406,920,494,729,929,98,275,854,145,21,104,242,310,723,230,720,62,978,919,277,973,977,902,86,265,768,245,166,139,410,672,878,733,170,807,445,414,53,125,369,938,451,16,186,457,52,306,158,714,111,541,579,561,765,937,864,764,783,219,84,453,703,171,833,776,350,892,521,663,753,61,413,491,910,215,24,664,271,582,424,695,923,636,677,381,614,100,529,268,931,880,643,791,501,202,371,939,780,131,693,198,290,849,319,33,547,341,203,524,425,673,253,705,988,877,332,430,68,480,552,886,798,849,39,938,284,3,745,90,147,706,479,728,792,299,216,155,902,843,895,248,560,820,222,615,69,726,929,404,682,631,768,925,865,252,438,772,346,34,555,724,121,188,497,714,464,369,995,342,983,742,167,775,367,712,993,468,102,826,558,32,823,409,679,126,524,789,576,990,326,120,352,781,924,818,575,306,511,529,876,675,823,133,26,399,517,115,680,91,350,601,652,740,619,318,417,747,398,706,608,204,122,46,846,294,447,980,261,27,323,280,195,148,109,219,912,278,430,908,194,689,849,760,393,297,61,991,662,256,742,270,226,810,52,979,756,412,71,445,622,683,320,238,377,562,779,260,457,590,54,526,551,282,37,302,372,790,26,767,67,216,231,421,326,508,205,177,277,419,928,948,246,852,796,990,4,287,73,259,123,995,473,322,126,769,287,84,494,250,249,556,706,361,445,880,405,5,327,281,878,231,925,645,468,500,913,671,591,352,387,64,221,113,698,845,698,650,389,94,109,816,942,346,780,780,360,135,560,400,680,855,310,625,10,647,930,860,678,674,186,450,890,971,370,452,767,313,157,643,310,759,89,116,150,257,431,593,299,546,854,421,50,977,164,125,725,251,648,955,52,726,286,111,404,403,225,530,155,104,45,459,888,476,293,273,13,122,642,923,883,811,34,448,309,962,631,718,644,333,44,598,280,884,353,534,471,0,303,518,747,519,415,859,190,398,374,738,662,388,954,544,424,860,530,393,553,87,708,111,889,241,493,231,705,896,85,645,676,436,859,766,216,574,25,489,561,650,644,313,103,395,166,978,108,241,13,724,183,902,135,455,689,522,117,700,860,836,858,486,812,278,216,835,729,71,33,23,257,952,182,274,241,967,94,320,722,221,989,440,814,195,712,229,720,738,725,544,26,613,758,228,591,287,727,735,515,70,427,955,880,604,349,788,843,315,759,464,88,373,369,906,152,506,448,740,118,561,380,829,243,44,127,410,212,204,170,55,409,631,726,785,676,47,738,536,599,796,832,776,575,610,440,222,143,652,609,845,246,397,257,850,948,864,830,792,924,321,859,611,114,640,478,596,30,780,712,369,534,571,432,70,363,762,201,537,962,4,342,246,926,306,410,195,463,351,141,990,444,715,976,965,200,652,495,682,174,570,447,130,467,993,649,943,607,972,652,515,532,818,653,439,489,300,674,214,770,461,451,763,688,329,873,410,830,846,744,802,943,527,802,74,922,17,920,178,582,905,721,589,709,912,549,624,220,380,11,328,27,54,705,920,861,963,318,990,62,173,355,460,81,500,412,602,160,308,532,70,339,819,549,359,199,914,347,171,932,385,935,492,192,937,942,638,351,70,361,708,232,713,84,633,238,27,771,47,844,987,4,322,549,697,489,919,181,356,731,254,268,465,266,596,189,85,758,396,925,87,362,540,385,946,204,401,853,913,409,580,455,525,474,794,471,972,394,699,360,591,388,657,499,547,107,229,193,527,215,922,974,989,781,560,74,913,929,921,316,877,241,116,653,29,180,353,904,288,772,448,555,524,148,601,692,590,243,239,330,253,179,88,401,311,656,159,183,707,430,209,112,280,610,768,835,951,684,329,257,990,177,743,29,433,439,27,211,135,907,516,8,182,955,332,732,930,710,436,624,696,618,562,498,3,718,32,396,909,488,429,227,567,59,485,42,627,119,309,963,346,501,408,207,55,780,515,406,833,388,430,190,939,330,364,254,229,512,26,784,601,749,720,46,589,359,468,606,940,836,327,396,90,773,574,213,462,489,97,875,764,446,454,978,789,51,422,23,615,684,277,697,567,721,429,784,897,987,737,43,477,667,617,888,145", +"223,791,869,663,465,8,646,801,928,693,663,836,983,590,958,368,583,714,569,938,355,298,909,618,951,995,645,859,412,591,779,151,366,121,37,878,68,701,19,524,960,800,870,225,605,2,881,651,401,740,276,402,337,324,751,26,909,362,99,622,407,451,575,468,930,742,294,552,658,546,182,646,78,274,371,62,169,45,88,316,977,627,58,545,327,431,732,137,277,214,208,442,507,706,6,206,184,523,293,543,758,88,400,875,522,11,977,696,52,813,982,884,639,784,614,463,143,139,115,246,727,195,89,8,271,110,598,662,657,826,518,438,355,188,77,119,516,806,225,979,616,701,426,154,925,834,18,903,420,735,397,938,713,931,258,249,315,35,635,3,502,366,596,580,763,163,849,64,963,639,123,59,95,833,784,36,754,942,482,866,341,704,575,470,945,687,84,716,622,3,819,100,488,313,254,731,957,897,160,630,997,710,650,439,471,524,725,943,686,324,451,377,814,607,185,62,914,162,336,759,677,655,348,417,888,244,314,310,963,754,858,65,729,439,523,70,307,514,236,830,594,253,90,843,416,822,318,488,415,805,690,852,260,429,582,610,748,782,951,565,761,210,890,833,640,238,763,923,156,575,935,196,447,140,62,549,622,937,97,470,855,52,279,960,222,205,823,726,947,216,639,58,295,20,219,792,249,772,626,804,879,519,902,326,821,703,949,437,869,708,877,892,200,50,905,671,744,560,878,104,535,790,407,221,559,15,648,657,152,282,585,611,994,982,305,865,597,28,445,484,946,425,624,570,334,399,252,304,903,580,22,460,24,225,257,419,39,814,533,703,765,812,257,6,17,824,44,175,481,436,413,801,597,904,622,405,10,133,132,548,725,841,117,525,352,798,785,891,377,588,390,301,193,953,157,801,753,605,852,186,646,185,706,984,263,361,705,627,273,253,432,524,607,906,754,592,162,440,100,280,20,680,829,267,111,733,220,247,779,416,110,704,994,862,58,502,814,166,477,694,868,383,192,620,120,84,124,585,723,148,138,377,739,821,214,687,286,626,84,46,363,568,242,674,814,159,647,62,422,996,1,793,526,119,987,618,60,202,153,105,447,823,991,315,926,785,493,38,916,50,882,949,692,101,930,303,0,657,823,937,238,616,157,702,982,827,537,36,103,953,527,953,192,248,237,104,447,480,686,479,730,159,664,597,789,45,278,181,818,74,381,527,186,927,52,622,511,315,972,352,284,599,416,371,235,281,856,1,783,355,728,975,26,252,151,105,3,62,427,635,772,630,862,515,211,663,372,270,305,471,713,386,73,412,172,34,182,125,763,206,448,761,861,459,7,636,396,777,377,317,264,528,435,463,498,693,142,491,237,673,907,865,361,795,28,389,601,90,16,976,237,453,52,200,256,773,127,961,55,417,55,990,737,431,415,771,529,975,196,710,905,550,439,878,865,950,48,293,128,955,884,392,219,527,864,469,812,713,451,777,484,229,890,655,783,723,999,249,150,150,46,462,872,918,772,473,114,283,523,582,332,329,969,633,475,384,46,71,92,934,498,793,194,45,685,291,813,565,60,17,528,967,878,397,456,974,331,307,125,808,963,255,816,433,351,642,397,37,649,727,255,513,759,741,653,226,8,571,752,350,878,841,646,792,560,443,365,723,498,29,257,131,279,10,85,568,269,874,282,340,754,823,733,11,448,114,974,736,609,272,632,995,913,542,744,973,881,706,183,238,468,538,62,960,105,98,440,92,499,431,683,424,965,58,826,332,474,703,487,535,717,136,175,234,923,551,407,999,133,411,874,795,371,912,702,360,438,748,264,406,777,162,168,645,197,275,271,305,59,965,141,548,118,102,751,175,798,561,679,756,936,669,461,93,258,617,321,535,315,780,440,563,144,92,183,428,932,452,953,932,62,290,638,530,847,511,300,466,427,12,629,636,53,127,879,125,775,464,746,485,350,586,576,862,547,925,692,925,214,166,331,997,99,28,880,155,137,445,750,724,230,872,685,400,742,619,27,775,4,185,955,938,323,742,323,681,956,910,412,72,369,459,335,601,913,618,642,618,824,316,461,297,873,115,434,5,41,462,566,952,237,206,988,710,343,884,443,439,558,726,174,897,734,450,510,808,451,118,328,891,176,957,807,202,651,216,581,68,438,28,186,459,293,548,804,921,457,276,663,352,296,205,201,547,682,84,569,129,306,302,414,151,899,429,52,92,558,19,10,538,807,550,405,4,423,105,330,983,717,54,208,694,495,187,351,386,670,138,972,699", +"648,674,915,387,404,306,257,971,700,258,396,466,678,181,411,492,943,782,722,793,79,973,836,703,739,200,538,19,351,705,788,655,818,461,711,887,561,77,322,844,394,597,801,540,879,729,372,894,353,683,570,290,631,795,155,258,92,607,24,657,996,168,307,563,926,594,548,828,84,144,448,994,224,370,356,130,852,595,657,763,827,111,315,236,953,967,556,205,913,416,24,475,992,941,840,856,997,340,289,218,409,719,441,23,994,289,761,745,702,108,205,692,423,800,299,86,986,501,482,638,183,845,224,779,246,350,232,274,634,35,1,763,927,212,609,917,96,554,136,848,812,139,185,340,870,641,539,571,930,100,214,892,149,245,993,397,430,561,175,446,618,223,608,582,889,439,296,36,704,200,828,645,616,745,925,508,589,34,754,838,344,790,875,307,921,576,914,46,303,424,593,263,520,703,129,418,741,109,410,133,193,398,499,814,995,608,507,921,234,381,825,190,198,35,786,328,878,175,82,967,981,192,226,482,628,131,326,890,422,607,728,391,505,198,992,87,296,389,302,23,642,888,825,1,512,745,985,711,813,281,473,932,135,171,520,957,261,189,347,653,358,105,550,325,852,485,869,756,481,910,564,606,882,747,886,72,328,996,192,734,592,855,948,567,319,956,664,882,924,68,745,590,122,748,820,7,28,124,558,519,590,339,646,535,336,253,465,13,464,321,98,304,719,139,949,603,316,926,59,842,723,537,532,108,65,383,920,801,438,358,105,67,587,501,169,527,155,479,521,440,421,804,645,125,226,955,73,97,614,210,269,387,849,808,69,106,460,500,7,548,324,879,872,924,843,855,230,832,286,171,16,998,924,871,896,764,480,334,653,48,120,790,799,403,699,199,689,501,974,765,857,29,760,44,721,197,269,516,891,817,657,371,90,119,567,927,824,593,872,368,689,723,689,458,991,52,841,696,514,29,537,774,406,141,962,812,136,519,592,904,905,149,699,529,23,834,705,319,702,492,790,655,121,284,837,664,824,980,249,537,310,707,855,779,777,674,296,234,871,610,964,891,710,122,232,128,44,606,763,248,374,682,596,329,872,40,455,810,314,552,159,636,884,529,429,369,95,60,499,674,746,669,948,683,18,518,657,0,422,110,303,491,104,320,951,442,961,498,417,326,399,255,792,442,824,291,179,549,346,824,137,426,956,37,357,118,639,196,736,27,451,825,344,429,127,541,901,759,654,884,17,112,236,494,956,968,927,285,960,432,920,452,996,106,387,365,496,971,17,637,15,57,93,881,719,930,324,246,912,738,833,908,774,326,640,591,414,739,316,868,482,806,707,525,317,841,398,291,59,452,66,514,515,172,658,546,241,33,621,96,792,151,414,570,723,630,477,462,390,814,897,890,580,87,996,634,961,5,399,21,685,933,200,914,745,124,78,908,453,230,535,867,155,66,638,325,835,915,561,364,599,79,631,739,379,62,379,166,280,266,670,204,178,543,7,107,817,32,727,153,826,604,157,452,807,276,464,966,889,68,60,343,343,306,524,556,227,885,252,593,479,487,736,661,941,419,614,354,685,91,73,618,264,750,948,461,813,626,156,955,2,969,986,894,332,677,596,265,360,611,474,509,792,413,568,38,37,820,730,509,274,39,32,637,104,505,668,268,740,632,469,297,527,552,394,618,787,547,81,104,350,476,3,308,336,618,222,66,166,273,950,408,751,286,205,100,571,903,629,864,148,367,811,77,674,628,66,925,115,325,587,63,583,745,537,45,935,572,949,123,739,744,77,248,943,994,550,201,654,373,466,625,570,845,907,638,64,232,850,729,117,471,221,734,75,825,728,391,257,737,263,522,438,298,938,119,265,723,156,307,241,264,42,510,684,935,834,240,550,185,123,964,381,380,374,94,745,922,258,264,100,658,260,252,482,316,672,886,866,826,275,844,187,532,415,902,163,240,651,500,971,901,553,861,918,529,3,387,189,914,471,579,551,863,132,83,627,888,559,616,207,178,545,359,487,207,214,79,888,709,289,768,389,335,89,448,877,74,696,435,880,327,804,179,165,191,588,662,32,13,596,895,527,471,554,491,66,473,823,802,581,634,253,866,182,125,236,423,781,284,212,463,896,421,186,71,612,251,986,462,377,712,795,534,792,5,765,303,941,57,821,497,445,455,778,481,856,743,606,591,474,493,477,370,234,576,453,171,421,884,428,305,478,189,50,315,196,605,476,280,684,937,439,647,192,899,356,858,316,965,603,79,412,908,175,167,631,850,524,775", +"352,582,361,973,29,72,43,791,666,899,949,365,392,694,265,405,399,725,314,992,293,440,664,420,504,253,208,856,921,689,712,323,445,40,347,219,850,950,585,415,165,94,96,441,992,440,840,642,182,307,324,305,63,733,769,18,843,812,3,135,759,323,44,862,472,49,490,181,954,910,186,673,348,506,127,59,546,487,287,902,350,70,531,587,926,560,979,652,768,319,69,307,524,706,387,909,361,950,837,590,17,428,915,269,164,512,453,50,307,561,120,937,43,96,823,867,881,5,736,332,834,261,764,312,417,605,422,340,731,51,74,239,560,153,722,172,975,796,428,886,853,674,201,775,780,393,43,866,503,871,948,607,184,212,957,695,406,828,483,307,993,252,96,434,759,11,605,145,117,670,425,8,291,347,489,640,880,543,817,127,156,406,602,740,527,560,446,537,386,78,394,93,758,534,644,91,730,396,580,986,999,861,300,786,712,423,60,22,833,675,286,537,400,975,945,822,186,475,45,246,896,146,370,309,529,240,31,344,335,246,891,724,338,477,519,230,277,313,656,710,436,723,315,633,644,4,999,438,280,30,615,82,496,781,159,144,352,572,640,346,560,132,333,377,839,950,906,755,900,195,148,178,523,775,793,292,770,379,995,605,137,315,419,714,367,367,776,293,890,112,634,755,973,912,350,456,402,151,867,107,364,946,433,637,805,32,246,671,87,943,279,834,618,13,47,353,262,619,126,929,550,66,87,353,886,525,262,173,601,634,776,949,744,147,562,59,760,452,343,466,845,176,145,376,347,108,654,111,610,969,684,116,101,290,234,409,206,275,867,778,949,786,499,202,202,514,224,453,793,666,152,773,766,646,379,969,581,957,417,968,272,432,925,396,254,945,581,385,89,87,504,76,358,200,717,518,898,612,959,857,265,731,88,173,673,285,2,432,564,811,430,479,461,811,184,760,689,349,370,92,411,695,711,7,863,728,890,937,545,595,406,830,817,962,110,645,234,56,706,771,416,622,412,503,950,31,823,352,703,679,280,936,507,438,450,734,775,603,276,705,270,259,270,208,607,144,492,521,32,182,926,618,109,198,508,554,239,405,626,476,238,265,413,777,986,883,485,324,927,910,15,486,729,861,631,747,823,422,0,505,724,179,433,363,689,917,555,581,234,385,915,673,810,787,125,427,288,865,728,23,856,139,90,6,842,197,331,44,687,437,478,643,467,41,207,743,472,58,871,560,398,557,688,821,470,617,511,564,164,998,59,685,111,731,92,401,454,180,731,921,554,223,583,328,128,456,82,92,271,755,113,33,608,729,325,83,544,80,167,259,716,566,431,427,983,528,192,115,363,84,784,433,682,317,98,368,132,508,813,569,103,379,231,146,29,489,576,355,809,423,481,984,234,570,22,305,405,750,801,204,499,836,879,36,419,536,185,892,339,84,83,554,319,627,658,828,78,960,400,401,48,314,404,823,720,736,336,441,493,108,579,109,217,327,550,186,172,552,935,683,929,6,498,384,760,670,627,903,166,706,772,351,593,910,164,906,812,385,363,447,10,121,937,658,427,260,466,546,304,312,856,789,153,690,349,908,406,919,726,4,49,754,294,623,969,621,113,940,220,34,387,280,769,3,91,178,207,413,779,2,340,668,807,897,787,217,269,361,84,778,873,669,592,435,265,481,392,172,784,556,57,516,818,924,194,163,411,634,639,319,397,239,906,869,138,15,559,675,391,31,267,270,656,166,225,874,122,788,687,715,809,649,981,187,931,85,64,613,566,74,187,911,739,872,797,107,320,589,176,894,360,321,474,701,388,409,523,84,332,370,808,680,136,149,177,91,917,804,433,106,701,738,833,961,398,598,109,211,467,987,456,740,229,405,885,150,190,788,956,612,971,611,774,60,489,173,431,712,182,656,739,647,578,574,669,885,676,130,792,309,996,130,441,684,366,874,271,25,665,528,47,525,212,20,298,622,897,907,420,578,20,482,675,549,635,69,815,515,149,710,402,63,632,872,903,85,5,865,684,827,59,617,36,685,748,614,657,908,490,998,103,463,358,178,638,326,438,931,685,322,477,134,586,651,782,46,79,753,673,481,33,160,516,46,945,287,726,987,258,442,827,982,137,120,97,211,410,551,13,267,120,420,171,245,419,427,852,655,501,792,473,771,729,336,288,231,254,356,675,284,19,922,945,453,533,905,591,826,901,172,409,563,692,981,245,182,367,850,122,79,324,382,887,391,162,937,546,102,431,608,71,135,256,862,225,207,173,622,900,338", +"497,593,882,674,956,130,710,181,684,381,767,567,730,329,96,536,454,167,843,262,420,391,697,295,522,188,70,589,282,713,537,106,123,726,442,433,416,555,917,30,574,998,197,289,124,431,159,685,912,607,919,356,961,911,400,68,154,589,682,26,477,743,925,512,3,826,765,438,627,813,999,679,243,56,856,869,666,679,712,339,935,296,287,271,830,85,702,601,230,922,821,111,473,526,590,661,68,439,864,9,622,614,354,181,746,936,434,913,72,922,774,626,86,28,139,93,299,83,36,906,815,594,322,898,315,759,96,851,675,583,5,706,691,434,258,882,226,395,555,965,865,277,618,463,184,335,563,279,347,63,492,337,6,590,901,546,987,666,108,630,305,409,369,880,556,629,389,224,156,127,729,327,385,153,873,865,360,68,629,802,613,905,937,281,406,15,710,175,351,867,706,428,821,471,972,540,322,970,720,563,226,577,446,850,763,581,728,742,40,732,623,285,508,101,293,380,861,759,59,282,959,621,902,303,25,362,20,813,152,860,830,303,934,896,320,628,617,248,383,785,263,540,209,979,60,465,460,89,695,962,187,236,746,612,288,619,349,641,602,77,833,969,457,656,719,14,206,309,3,808,951,261,962,845,184,424,397,666,393,320,618,620,678,575,805,875,893,246,372,416,290,910,771,416,502,541,316,23,247,944,327,312,467,405,767,948,391,114,41,356,432,416,369,424,866,392,781,78,421,958,89,570,35,139,727,756,398,616,932,695,872,311,444,426,194,801,418,107,518,126,157,995,101,998,72,915,720,865,254,90,399,537,575,171,351,929,945,432,654,795,237,783,491,275,723,946,298,762,607,887,256,286,392,978,872,132,301,737,454,814,828,544,248,958,838,831,557,208,818,703,684,707,667,733,818,198,309,368,194,85,658,517,164,668,29,540,114,126,894,722,373,90,154,313,993,292,970,85,951,925,435,20,498,340,727,563,841,497,854,89,202,261,836,184,945,278,105,658,477,158,529,468,175,629,424,500,277,313,370,68,719,999,830,822,321,179,471,536,331,638,244,822,370,340,999,684,966,283,852,318,569,567,55,730,861,992,233,227,804,101,509,108,869,203,153,544,728,873,540,873,294,273,813,371,955,519,937,110,505,0,216,664,581,536,832,316,253,966,802,777,490,649,430,378,532,993,584,724,319,533,648,597,815,672,404,705,797,550,782,906,990,661,261,249,756,15,326,451,415,579,567,635,413,658,192,50,599,414,599,213,237,465,686,245,718,458,710,334,826,399,143,44,545,346,958,446,617,668,744,473,11,459,91,983,25,854,291,34,491,606,918,198,20,282,255,671,764,5,885,29,856,663,134,574,443,729,773,262,392,337,487,692,224,616,348,741,121,702,971,201,186,302,383,459,305,509,670,560,732,934,930,284,421,663,629,635,66,384,530,686,525,337,844,614,274,187,395,828,224,585,46,884,296,596,945,30,216,567,292,114,451,801,89,559,177,868,72,887,11,263,146,799,686,175,994,267,518,244,337,671,805,675,589,508,796,811,810,289,205,955,756,208,514,586,544,340,824,84,489,792,241,146,131,384,328,625,989,129,883,578,121,454,720,662,994,114,145,814,707,831,443,475,322,558,60,815,530,899,707,636,888,81,883,868,32,585,120,785,620,113,627,357,803,38,409,384,57,823,859,434,154,335,954,85,172,783,309,38,351,135,735,567,40,823,752,568,335,964,457,530,395,497,531,519,951,499,705,381,248,460,766,740,442,419,344,126,818,964,404,79,152,183,955,201,593,992,965,7,427,867,387,823,35,692,870,632,417,315,315,679,754,998,266,973,733,516,922,159,93,829,717,889,8,849,183,404,197,575,289,710,119,292,165,925,529,870,999,244,563,26,807,518,987,314,555,408,373,176,836,605,666,819,853,590,475,353,535,745,521,218,47,89,118,729,667,670,374,706,265,355,768,832,612,245,361,965,419,587,265,663,55,466,470,573,35,932,310,93,930,34,826,467,557,894,955,475,63,634,679,787,156,531,877,21,501,263,791,799,808,362,287,706,388,33,539,608,735,993,666,801,644,328,737,806,560,195,983,499,68,994,47,864,373,826,64,345,552,863,312,848,770,736,430,551,192,418,371,427,940,713,590,995,115,567,535,674,603,340,696,596,826,166,123,669,792,805,324,721,969,315,928,910,713,108,53,555,703,889,353,940,638,637,697,613,391,957,286,314,927,442,214,818,415,31,214,845,133,678,212,784,646,196,924,845,922,541,154,287,846,429", +"782,29,934,275,215,215,408,38,803,276,15,396,542,414,573,839,365,718,650,931,334,233,149,632,364,964,124,143,497,603,997,833,640,368,608,242,56,973,229,500,207,347,407,202,978,258,820,668,47,152,943,651,743,572,122,79,991,832,469,335,293,305,286,182,528,354,376,115,541,463,666,782,631,751,864,724,159,411,64,953,648,467,27,192,181,671,826,742,798,285,125,300,317,462,460,686,554,689,583,899,829,1000,603,275,389,887,663,442,853,784,126,575,729,142,912,758,761,375,200,102,954,617,346,622,307,927,19,18,547,32,150,52,493,542,11,876,809,123,781,126,681,583,246,989,930,473,752,478,251,630,488,721,540,547,315,827,597,802,349,475,356,813,167,791,164,980,688,872,692,245,521,776,448,313,872,886,156,667,944,614,461,761,644,252,895,823,51,475,332,97,719,762,246,665,172,981,318,771,735,521,38,181,318,745,605,704,596,575,253,33,870,792,59,677,762,434,138,376,894,865,114,230,237,696,843,583,420,19,378,246,921,677,803,364,449,121,666,92,423,673,845,221,304,217,974,815,375,479,760,265,74,797,361,672,592,260,320,905,383,888,27,810,11,287,488,137,470,359,66,828,923,687,899,594,328,435,909,581,494,787,931,783,547,460,164,733,413,924,799,947,164,827,388,178,367,118,925,300,832,663,320,272,627,398,474,915,695,533,869,253,200,809,724,322,294,381,215,594,146,774,624,736,558,7,61,228,767,784,348,669,912,953,324,771,111,992,748,24,910,958,579,914,221,659,678,77,616,75,748,585,476,373,749,921,255,286,107,984,932,100,901,984,494,855,333,520,630,517,946,767,784,169,818,380,957,104,787,526,592,495,236,57,689,997,663,144,554,699,677,708,613,744,496,350,241,947,482,881,335,740,16,200,903,727,618,742,931,439,950,986,918,431,473,203,793,584,788,220,433,71,565,906,180,455,80,196,450,71,308,313,285,999,845,510,134,213,244,585,876,932,326,100,177,732,939,942,410,272,116,787,457,729,395,86,511,212,970,309,61,128,658,291,606,759,531,989,59,839,473,555,407,938,98,458,909,627,505,315,779,381,151,429,962,224,638,944,549,640,590,904,56,47,649,811,144,415,238,303,724,216,0,484,589,876,381,435,430,798,930,948,61,197,592,388,423,971,997,747,616,91,615,697,353,994,459,867,826,828,136,584,213,344,193,518,568,762,160,710,16,863,141,108,918,447,830,922,513,903,973,919,430,34,640,979,232,117,47,156,196,933,737,941,979,46,161,155,594,162,546,921,125,502,246,498,3,421,440,706,601,876,120,900,414,660,812,300,282,399,529,860,701,371,501,156,554,644,129,127,414,42,763,547,873,416,216,953,279,902,605,904,830,572,701,681,100,393,31,117,499,604,182,211,456,22,974,307,242,668,26,455,540,192,809,801,408,128,896,290,779,32,375,830,710,430,859,905,59,902,903,140,449,938,647,825,498,927,785,206,241,22,231,621,939,784,899,882,902,711,183,523,867,496,159,613,896,215,114,264,772,934,14,747,333,886,650,748,729,201,359,757,835,930,867,914,643,970,372,521,807,77,932,818,586,436,672,359,268,925,842,569,643,401,587,479,836,830,313,120,163,490,552,476,104,885,992,538,349,679,37,552,602,109,731,454,355,547,1,824,56,714,339,967,691,261,83,546,957,653,779,623,435,213,685,499,284,558,821,620,852,743,620,404,430,69,769,580,708,921,715,306,762,974,410,354,405,662,356,143,110,895,236,327,645,532,272,672,380,696,894,329,763,708,512,914,163,361,198,329,946,459,423,152,914,479,911,688,780,720,568,78,321,118,699,580,835,806,333,961,744,72,213,459,126,413,629,144,446,267,687,300,450,166,611,719,385,706,524,357,447,592,376,993,504,120,332,516,657,999,718,282,846,406,573,140,85,568,276,641,624,599,117,763,599,401,760,447,231,263,47,419,614,947,400,626,518,917,990,483,808,371,781,560,822,333,608,898,531,537,22,310,946,160,119,34,262,339,688,54,855,715,277,29,202,150,244,985,324,672,800,667,457,767,576,834,568,799,997,332,107,763,118,84,694,309,601,585,286,200,871,186,57,973,276,665,439,817,811,603,235,517,671,699,633,252,214,369,236,366,475,830,222,50,801,176,297,989,864,349,741,61,792,801,410,608,584,627,304,541,684,67,859,487,555,433,274,492,353,446,58,59,88,320,310,653,436,76,899,232,58,266,117,131,487,146,423,84,343,108,325,402", +"182,787,471,791,265,210,205,460,738,995,366,949,569,959,82,180,105,890,896,344,883,157,965,263,977,296,715,306,357,37,917,276,486,828,80,693,719,990,236,781,133,573,577,519,553,669,472,974,759,472,728,530,890,272,956,715,731,277,569,570,264,439,134,272,157,616,122,259,435,555,903,883,964,189,882,231,721,418,277,18,667,105,856,459,867,685,394,798,758,516,715,688,999,522,698,105,908,299,383,433,348,746,624,692,593,600,539,408,123,415,815,152,519,476,524,612,931,186,534,384,236,85,566,594,230,507,575,429,568,622,343,295,374,642,32,939,361,345,119,395,656,192,346,669,630,904,44,290,595,764,869,353,176,798,17,945,752,398,966,5,505,487,87,11,185,498,811,408,280,952,348,926,798,292,394,950,736,421,100,994,486,380,649,494,379,846,991,136,781,566,677,336,633,678,280,489,416,215,806,855,106,798,224,979,859,74,264,938,890,99,903,848,978,40,176,644,950,495,827,915,419,218,412,636,806,672,475,13,458,439,473,913,381,352,862,93,815,361,58,610,921,853,431,980,733,127,151,932,213,747,421,62,274,205,323,11,658,429,714,303,979,7,541,943,585,815,687,764,453,666,479,435,836,545,817,597,434,30,413,383,737,307,836,446,90,648,232,387,256,12,3,337,99,310,922,387,371,271,736,499,926,713,733,954,134,13,170,96,671,235,496,462,247,924,124,215,648,331,818,411,382,27,447,371,700,577,669,834,744,522,852,396,981,81,566,125,141,755,990,178,483,248,371,872,331,201,76,31,817,70,279,19,126,733,588,444,926,549,844,698,947,412,237,532,300,541,570,305,676,538,185,542,910,480,545,267,566,729,134,317,404,734,447,792,413,39,779,119,256,110,398,850,847,500,72,740,354,10,470,606,927,208,18,90,732,201,916,362,528,303,704,831,343,524,541,642,548,869,837,408,30,729,686,766,913,137,294,436,821,833,162,860,486,588,327,910,28,584,25,787,522,675,166,570,552,531,392,242,758,292,508,496,609,593,36,512,780,75,269,700,387,447,628,826,630,398,221,122,492,739,369,80,377,937,752,797,795,193,720,444,46,656,582,934,49,626,634,83,467,21,448,585,679,467,507,859,616,491,179,664,484,0,448,302,672,978,468,106,219,261,887,234,927,363,143,139,603,355,633,2,169,724,14,751,257,387,755,659,70,536,519,383,913,292,16,569,947,493,189,748,276,61,565,467,857,893,395,919,675,861,664,494,689,808,577,439,429,823,547,306,240,992,834,752,695,548,630,560,426,35,903,424,68,15,578,15,37,865,645,371,699,27,754,65,731,495,641,190,343,454,322,495,575,698,768,632,451,606,964,650,178,73,114,232,187,220,123,265,328,855,553,393,742,33,563,241,10,708,724,530,487,497,701,718,278,151,709,660,240,633,332,272,876,229,968,868,866,618,21,188,474,857,863,750,848,441,1000,283,30,813,557,35,329,643,796,745,898,688,178,245,46,137,921,846,151,53,116,671,108,892,227,49,182,460,15,28,235,484,106,996,454,92,309,758,805,638,526,510,491,682,475,115,941,92,412,606,245,807,88,770,510,27,915,681,601,58,363,20,860,979,506,616,958,812,458,560,722,918,854,609,316,20,455,952,88,813,136,638,742,107,161,632,164,301,951,490,761,915,558,566,381,892,339,88,759,590,156,655,75,154,636,529,926,177,967,312,912,344,62,996,652,621,262,69,317,619,443,262,637,465,525,363,311,106,69,583,250,850,461,439,814,182,806,42,442,196,679,124,320,838,602,849,827,214,274,498,590,580,184,4,195,213,668,327,374,451,167,127,365,561,291,453,672,290,631,738,445,29,895,964,456,100,911,304,239,734,383,440,729,638,436,657,747,70,303,793,525,918,507,350,520,778,684,577,172,921,782,909,99,343,118,167,858,919,90,361,871,416,118,202,91,928,571,806,20,63,235,140,463,933,549,347,236,161,72,257,455,875,7,570,787,851,233,517,105,475,926,299,831,834,755,543,230,20,29,546,421,229,803,46,336,657,313,923,127,186,94,300,888,855,615,12,748,512,922,703,860,613,140,45,144,936,822,596,592,205,234,424,298,889,578,838,44,696,47,243,668,940,199,257,107,184,352,217,298,637,432,548,296,677,975,261,671,197,21,674,836,291,241,477,76,814,695,249,13,819,678,228,7,526,475,892,185,83,567,285,388,137,586,556,225,303,409,841,395,253,398,954,147,448,184,13,349,889,329,33,782,574,321,563", +"463,687,397,723,533,312,74,713,861,86,975,529,286,801,493,677,605,116,722,805,200,336,751,770,108,598,535,733,173,764,716,145,369,944,3,131,990,639,149,137,504,56,919,356,679,708,2,877,296,691,38,56,697,3,171,665,653,535,587,985,428,593,997,787,245,365,167,88,957,712,791,577,404,15,443,770,271,188,749,559,766,675,310,857,695,225,475,691,213,557,924,4,466,7,854,146,530,225,265,576,792,873,885,34,185,451,688,565,373,339,785,644,678,913,898,180,359,258,31,811,200,105,216,188,783,148,829,950,260,684,234,248,716,816,645,789,278,882,568,379,453,519,289,825,84,625,63,537,157,895,503,998,728,542,824,239,380,145,353,11,784,617,553,609,222,571,462,120,420,779,989,417,406,321,697,481,724,815,340,432,333,340,298,175,641,893,113,247,73,150,959,184,951,99,996,815,340,929,319,249,120,852,771,200,841,548,128,859,554,301,317,904,187,161,772,593,98,33,456,776,686,204,550,898,920,469,767,27,17,177,27,315,902,896,657,465,389,454,946,603,406,333,626,598,279,178,927,2,370,388,963,435,303,868,670,276,754,86,418,323,646,704,909,658,10,135,497,850,396,558,159,741,159,236,462,192,908,674,919,846,3,189,980,454,963,879,84,137,8,752,218,895,140,631,941,80,586,74,591,953,159,416,928,560,891,998,222,411,779,745,387,50,126,742,905,850,306,870,416,624,52,682,359,447,147,533,982,447,252,822,359,40,16,238,502,623,605,594,747,131,409,260,762,806,407,618,106,150,704,41,14,510,648,415,362,109,911,592,864,556,691,83,922,440,129,334,631,119,172,244,576,202,562,374,630,100,797,864,38,851,412,225,978,850,906,485,366,904,860,254,591,676,906,247,862,607,743,602,602,71,940,925,945,936,114,93,737,114,852,938,898,892,385,938,968,345,949,826,379,892,359,134,170,636,866,455,743,356,635,60,839,225,597,438,709,150,76,721,372,899,301,681,493,557,351,714,296,460,948,784,951,705,901,946,218,321,367,567,12,261,873,277,339,729,782,38,331,522,924,590,102,975,273,24,491,626,537,287,105,327,39,935,820,356,996,167,502,142,467,287,451,529,1,992,121,190,157,104,433,581,589,448,0,941,758,202,38,492,206,350,432,990,800,46,97,418,327,45,759,304,640,734,63,712,456,426,740,676,662,806,987,546,422,490,770,409,868,137,161,279,760,134,360,889,996,449,703,745,636,362,571,809,360,429,452,426,381,207,792,631,856,115,685,174,589,565,747,322,558,491,468,74,947,808,410,280,674,639,121,562,350,587,947,736,299,847,509,152,655,681,444,562,197,23,259,951,343,633,332,524,949,416,150,308,271,568,304,600,302,724,361,857,514,674,252,10,406,57,610,523,467,4,794,245,398,537,70,710,244,414,309,444,215,207,134,554,643,450,11,107,942,665,978,594,841,588,841,829,446,245,838,874,388,563,214,532,386,261,816,20,888,761,885,882,723,347,390,1000,150,704,89,2,842,685,404,219,432,106,918,354,493,284,282,648,751,968,547,764,757,173,699,496,943,351,767,910,274,266,981,495,77,570,283,365,307,841,523,556,249,539,862,943,289,884,814,705,429,89,988,503,341,373,251,373,74,124,175,191,707,281,661,492,224,7,40,490,113,175,947,903,620,5,477,554,296,412,887,455,260,278,197,531,879,635,771,748,571,814,254,510,761,453,369,781,24,311,115,372,895,885,673,663,78,356,964,443,583,606,716,360,62,644,865,767,742,264,596,510,764,893,545,695,691,478,849,961,745,413,9,742,584,229,831,251,406,392,442,571,26,332,538,111,516,864,196,644,725,834,930,987,770,870,509,478,312,844,293,872,225,663,736,351,529,431,406,614,503,706,317,539,519,177,402,630,450,86,933,763,143,294,775,946,212,828,127,473,444,323,331,114,985,344,513,582,218,133,307,885,23,308,138,687,712,467,242,417,87,51,714,726,499,613,586,794,466,99,531,698,711,226,599,19,415,292,17,788,671,931,8,975,371,539,608,846,206,71,316,518,920,39,381,174,349,368,450,594,207,258,56,638,989,775,71,505,143,292,406,769,823,700,260,601,157,713,791,666,269,594,279,541,371,700,695,305,946,546,255,796,543,779,172,876,892,471,598,662,620,128,238,198,599,54,398,205,771,111,614,103,194,804,574,371,802,784,745,65,267,660,609,254,505,479,142,827,180,675,672,521,291,146,167,634,429,415,48,164,384,554,854,20", +"557,878,92,360,307,635,150,75,263,969,497,181,795,128,323,462,96,664,22,778,478,778,439,148,337,924,95,419,548,913,684,251,684,256,919,938,101,185,413,973,76,121,865,974,66,679,18,904,208,793,639,373,62,292,834,183,928,661,221,702,438,21,111,90,766,662,328,539,384,649,647,660,373,244,926,298,894,123,189,756,754,228,166,149,123,509,851,784,885,410,968,646,607,363,351,798,511,433,448,367,247,878,63,240,660,380,785,61,652,146,329,348,891,243,93,831,553,544,643,380,298,592,538,430,48,706,283,26,171,155,613,872,757,303,471,652,473,629,258,842,75,259,404,795,615,287,325,944,640,839,791,186,993,258,331,878,936,284,485,599,7,222,5,683,472,760,171,953,149,289,512,912,538,975,805,514,888,625,225,800,80,850,529,31,711,269,29,978,438,66,211,145,395,944,109,631,758,180,798,380,420,369,925,253,101,944,956,494,866,636,739,98,55,69,848,588,328,255,214,772,372,769,993,454,148,788,224,583,959,868,287,273,349,145,703,469,240,516,101,708,349,950,950,333,97,506,889,154,953,745,960,994,322,861,465,713,285,921,785,799,229,16,972,96,680,368,447,619,428,286,254,195,36,182,788,228,326,241,197,173,828,484,743,487,193,876,119,416,346,256,628,545,303,195,845,492,181,559,856,453,269,298,511,734,504,162,207,983,898,335,143,774,36,992,700,39,635,218,985,281,572,491,441,308,87,411,262,213,20,234,653,254,539,957,987,62,621,292,655,456,892,646,430,235,5,615,320,510,23,417,956,791,456,886,953,298,100,267,353,653,3,702,353,527,825,96,590,58,348,179,106,719,295,470,571,184,830,345,605,745,821,574,258,881,959,85,600,873,354,491,536,153,849,927,598,398,221,33,19,250,756,392,40,935,975,418,3,534,457,101,357,851,481,235,180,517,805,561,314,11,242,36,258,845,463,440,562,684,667,65,426,480,75,486,69,768,780,945,950,547,605,950,97,458,454,761,136,442,28,38,678,820,116,277,938,472,9,666,62,98,614,134,896,71,291,782,838,577,371,302,617,905,557,32,585,354,918,64,444,510,977,77,201,954,66,579,312,774,371,656,650,59,615,245,277,398,702,320,363,536,876,302,941,0,314,400,799,831,24,745,317,699,992,233,419,28,758,673,604,412,642,527,75,683,215,172,603,609,948,551,373,323,273,364,910,23,75,549,547,176,246,172,121,659,737,548,996,167,16,896,404,483,680,753,423,988,994,580,183,618,260,946,70,414,302,315,877,578,734,883,605,517,816,570,627,654,813,797,896,556,553,999,326,76,20,844,706,439,833,946,711,292,874,304,509,622,534,887,70,826,933,426,670,525,409,583,382,121,81,822,163,649,858,244,101,605,668,887,142,90,376,944,471,402,466,887,238,850,772,236,514,881,809,586,804,752,546,933,982,384,493,821,673,636,186,444,388,245,386,358,789,480,258,813,732,919,45,764,17,4,764,982,988,102,702,210,152,370,72,986,343,395,346,948,278,388,944,240,431,130,745,51,348,724,22,576,88,294,97,468,848,22,592,156,858,466,919,623,212,620,111,978,231,19,500,214,495,716,541,814,703,987,465,498,135,727,104,900,494,524,861,826,769,956,656,600,605,250,28,400,901,888,344,774,22,534,27,771,627,235,459,107,369,179,177,263,569,410,490,472,503,841,111,134,446,916,270,929,325,632,105,985,467,859,630,582,134,428,530,352,721,676,470,865,199,746,341,815,164,320,349,607,68,17,947,776,815,987,41,303,709,56,753,334,210,860,399,404,309,903,100,776,934,674,707,57,938,835,597,325,901,412,109,105,310,98,798,262,728,615,361,219,116,238,471,424,210,393,765,64,803,82,573,256,77,247,88,743,902,10,432,550,192,790,612,650,715,917,874,152,195,612,593,596,905,671,511,288,806,438,603,730,397,133,256,648,840,18,492,831,29,643,595,613,732,705,123,434,909,41,242,76,62,201,116,311,987,737,636,989,31,290,739,218,285,260,416,394,188,365,447,168,347,434,265,340,472,924,634,687,4,310,946,871,434,168,846,232,677,229,125,117,688,121,823,33,366,317,998,183,684,891,920,464,276,325,410,198,998,59,856,545,775,698,671,747,407,505,304,965,212,501,772,195,109,960,117,858,935,474,196,967,996,281,680,501,663,551,467,387,947,167,214,124,297,77,140,134,167,909,28,254,947,605,292,849,2,779,492,43,968,526,571,432,311,945,531,709,458,413", +"20,640,714,238,424,595,496,367,3,802,685,303,596,170,461,2,81,303,237,701,663,712,286,99,92,849,408,348,815,18,159,950,601,604,35,278,697,490,996,422,983,283,455,643,338,559,810,590,212,167,341,125,290,474,176,513,491,573,856,69,904,886,80,726,754,862,363,425,633,506,323,793,154,42,526,598,555,773,687,129,578,103,742,84,811,234,925,864,523,657,347,164,749,802,842,204,222,252,368,948,584,285,459,76,9,567,784,23,589,156,650,464,401,892,379,999,521,917,214,462,873,948,100,158,589,267,174,533,12,372,964,281,117,457,936,67,157,533,291,201,706,617,7,798,626,110,904,667,985,285,293,20,591,739,141,618,944,470,839,436,584,515,792,487,93,532,774,699,408,858,953,373,981,548,522,431,670,696,100,466,982,654,888,434,403,99,635,261,314,967,394,596,322,468,996,463,726,620,297,767,37,644,171,530,78,643,485,113,585,129,506,44,595,212,42,876,313,72,979,3,76,36,60,880,148,32,113,921,756,296,898,502,54,106,651,962,818,473,214,936,775,705,62,228,511,365,802,6,191,474,551,802,869,364,405,390,616,130,982,471,274,901,957,471,436,528,303,949,944,821,66,879,705,254,934,727,329,779,487,671,559,939,252,954,517,188,308,191,513,951,390,937,726,427,268,336,332,927,759,63,832,951,367,658,57,327,938,697,135,39,655,32,210,75,763,637,344,298,368,81,653,735,643,195,915,669,955,441,106,833,184,527,303,763,831,551,973,298,667,694,581,536,551,330,630,854,616,956,846,266,829,329,949,580,78,814,26,702,318,89,981,178,926,129,841,716,402,378,816,130,925,71,73,268,51,142,593,523,926,835,321,44,115,299,922,227,692,976,772,68,331,963,575,108,846,648,686,796,178,979,306,32,733,3,520,790,931,590,185,294,425,993,885,600,200,130,314,44,55,607,809,959,651,550,746,694,662,86,164,479,79,55,205,229,911,75,898,904,108,532,410,762,364,50,257,899,944,258,448,845,426,880,291,831,858,6,574,864,694,234,681,273,318,999,568,530,335,252,706,118,785,665,311,626,119,575,652,656,403,238,95,956,251,476,53,175,465,530,862,143,616,66,25,846,884,374,982,951,689,832,381,672,758,314,0,703,515,886,407,726,29,833,923,172,600,772,853,889,6,50,407,553,661,860,561,878,53,773,318,922,451,940,948,54,716,430,230,769,5,249,732,205,811,767,788,313,909,20,37,776,148,762,646,108,630,606,130,692,188,934,285,539,115,15,580,354,455,364,374,493,276,546,248,221,256,747,721,594,717,306,788,200,275,825,832,56,951,967,538,776,713,599,518,355,623,582,186,288,918,384,768,722,652,886,551,763,680,764,100,707,291,769,57,523,636,377,693,46,460,873,452,124,464,79,230,969,774,478,345,180,449,279,608,170,646,296,720,288,665,843,325,454,741,114,853,15,185,790,88,853,194,58,8,281,885,947,819,335,105,676,513,6,65,582,507,201,267,195,481,139,319,473,754,38,921,474,948,347,580,262,341,963,30,994,606,638,291,522,899,977,921,653,969,547,6,182,540,939,826,659,453,383,731,394,449,387,773,87,342,615,112,592,843,451,525,583,365,811,98,228,491,245,629,652,494,433,490,958,804,561,277,827,47,440,579,714,684,75,105,712,843,914,683,384,949,283,407,133,23,440,820,201,25,756,714,633,251,935,805,919,820,39,863,275,664,341,250,343,507,758,501,22,562,233,554,730,146,514,140,995,757,114,120,502,872,420,372,352,969,949,220,390,697,430,125,119,747,875,973,146,274,548,33,181,290,502,756,361,498,886,522,291,208,453,506,553,495,363,270,660,906,851,165,744,181,660,666,525,184,983,141,147,684,560,328,261,826,577,619,454,302,233,324,569,140,102,76,571,505,863,383,192,785,70,755,892,557,302,416,51,211,55,514,201,888,138,582,400,580,96,448,745,279,361,562,90,119,496,81,975,75,239,429,213,882,199,165,590,413,218,739,241,516,247,6,406,954,376,587,365,754,823,555,59,946,895,249,22,815,720,443,324,739,454,107,329,238,714,646,590,536,409,911,677,222,68,192,140,645,3,690,936,209,132,540,200,639,207,266,172,167,603,589,168,512,671,83,852,825,688,819,829,171,630,706,925,916,349,348,732,704,378,970,9,729,666,928,923,526,606,144,615,275,461,997,947,712,954,778,350,787,325,439,462,596,603,836,2,383,459,35,863,212,260,61,338,912,990,747,257", +"849,11,569,270,501,79,805,249,893,410,160,627,11,390,942,494,746,521,768,373,469,450,223,702,80,303,578,39,778,698,748,884,394,438,161,511,699,990,42,338,851,795,185,253,463,336,762,979,414,994,104,673,834,990,119,671,244,625,527,854,16,702,759,891,326,488,863,868,74,467,984,798,888,173,343,367,571,333,276,832,985,972,591,524,497,474,142,3,459,867,829,935,475,791,970,762,295,120,65,303,281,270,445,459,568,951,482,397,525,755,989,510,147,488,28,636,429,119,352,215,198,723,835,159,844,790,214,295,72,699,819,426,614,280,264,104,201,204,597,698,641,442,342,615,44,66,915,466,630,142,219,639,897,259,771,764,624,29,174,293,327,718,541,303,88,898,182,611,694,994,566,754,785,996,334,866,709,62,811,783,262,880,329,507,741,355,334,506,311,711,671,631,650,329,831,403,109,66,49,271,508,888,380,924,697,791,317,26,950,13,669,595,80,101,764,451,206,53,873,655,466,255,595,76,33,138,892,392,760,224,758,99,819,971,282,880,275,606,306,238,849,305,348,248,986,978,555,690,447,701,645,391,579,777,306,607,601,561,15,904,733,896,926,343,112,862,613,416,152,875,779,554,217,625,850,286,421,821,140,392,11,541,8,813,397,535,145,749,197,491,592,288,931,81,734,904,513,264,462,401,719,258,310,943,385,695,913,54,277,214,835,563,325,988,994,203,771,285,999,268,399,550,219,319,783,859,574,1,39,126,907,870,416,504,870,213,909,484,78,716,424,33,862,331,933,212,394,265,904,756,325,917,848,244,31,566,242,916,63,971,146,550,487,894,701,41,163,686,383,414,912,275,870,714,767,229,158,311,591,749,600,884,211,905,821,558,760,825,155,385,449,436,163,13,707,7,160,295,285,517,975,816,589,676,641,726,327,419,165,627,376,392,49,205,12,896,253,603,584,17,175,453,812,803,211,601,408,923,962,700,656,279,893,204,831,807,487,848,964,827,585,915,358,780,737,461,136,884,635,367,92,801,927,113,287,617,307,537,716,540,987,131,731,91,537,862,713,879,212,469,928,605,111,568,165,208,636,384,599,132,74,881,815,239,179,390,656,603,407,923,6,743,946,654,450,738,827,442,917,316,435,978,202,400,703,0,687,976,967,484,894,2,264,813,843,89,291,591,127,499,490,564,376,668,871,835,720,467,64,619,342,886,365,422,588,518,25,124,625,784,724,989,974,573,99,487,787,617,427,357,477,465,120,759,81,251,651,412,156,738,599,509,836,623,459,721,449,871,546,371,606,141,704,204,17,268,351,906,436,826,651,739,290,609,237,247,212,289,397,158,306,785,851,915,705,116,751,507,103,862,745,408,865,156,951,496,506,985,479,353,548,86,178,374,716,954,598,954,610,680,958,404,47,309,267,318,571,919,916,852,373,948,433,946,63,765,121,543,545,53,8,147,240,672,442,251,323,816,921,67,934,305,472,207,217,54,381,71,702,390,263,737,165,575,958,305,560,884,599,267,44,621,707,335,143,261,927,176,192,761,100,189,2,974,297,488,30,757,634,900,883,250,475,994,609,85,584,476,190,663,746,36,912,25,820,661,489,909,755,108,78,821,48,113,163,286,692,931,877,329,474,445,150,377,876,207,505,782,520,478,238,324,85,742,322,303,419,977,189,580,967,797,745,331,639,700,370,384,784,636,425,6,145,777,816,609,23,797,914,646,328,855,755,232,602,562,875,813,40,226,450,706,574,850,234,803,552,251,630,139,179,427,617,894,92,401,302,203,363,161,448,29,403,561,65,149,14,377,506,972,83,793,310,969,323,62,838,966,475,986,77,656,742,144,427,738,720,97,76,896,153,679,238,185,566,473,292,540,39,522,994,68,667,394,200,797,130,704,666,823,645,158,362,440,440,695,676,263,83,60,159,912,611,325,51,523,54,600,392,488,725,306,33,257,746,122,968,770,663,355,437,589,883,532,377,62,879,801,547,230,893,146,984,676,411,290,387,458,537,657,357,50,319,353,544,235,319,31,243,727,260,55,821,148,721,620,126,774,536,624,726,969,406,975,465,542,696,118,538,541,422,693,302,629,821,68,858,540,213,127,568,77,486,952,590,622,606,394,243,96,211,995,934,341,798,324,723,294,919,224,535,462,38,660,513,883,73,102,981,973,26,829,429,818,955,858,607,716,76,353,87,777,937,286,992,741,476,832,603,728,433,475,432,557,371,688,167,859,284,477,420,664,896,371,786,71,525,61,649,214", +"685,883,886,588,166,226,363,36,121,411,766,738,713,227,589,456,828,848,34,377,426,229,125,681,819,846,985,635,657,282,176,156,636,552,375,661,248,886,468,36,819,212,864,989,321,384,624,478,739,352,597,499,821,769,682,307,247,170,379,395,260,820,819,637,747,241,351,77,250,115,166,282,570,934,366,488,689,33,744,830,143,652,537,348,850,301,800,850,511,233,505,763,522,615,493,84,5,706,861,585,235,408,57,158,268,840,569,207,876,810,824,967,989,902,68,781,677,220,554,455,587,948,118,140,294,189,297,712,967,42,528,174,723,580,125,269,877,866,79,595,708,424,458,637,349,930,898,432,804,161,859,51,318,115,507,80,941,132,765,46,57,339,517,634,666,432,657,661,838,303,151,318,692,192,802,552,297,232,633,220,464,309,512,191,500,613,492,777,72,510,668,480,259,532,805,974,876,258,778,996,984,805,71,223,556,61,959,130,745,863,365,932,569,86,688,893,835,480,815,722,513,149,681,979,817,995,286,218,947,513,161,585,134,61,647,115,125,577,159,354,584,994,867,547,848,288,917,912,836,694,282,917,877,891,183,995,576,40,282,460,391,406,183,581,364,247,713,771,801,54,429,677,238,964,848,742,804,666,159,64,749,880,889,487,262,152,548,361,743,568,952,768,322,688,736,78,474,566,288,272,564,58,674,994,212,536,729,238,375,297,957,576,404,918,45,282,405,987,434,690,985,135,452,57,795,144,334,70,769,813,3,399,120,672,347,82,370,568,320,696,891,764,357,705,415,119,596,64,669,88,661,914,106,697,996,496,247,31,378,708,871,778,763,296,680,543,116,156,716,362,236,191,384,24,959,407,100,449,857,685,374,205,499,331,646,684,916,640,740,262,292,99,724,807,498,254,37,225,391,260,143,851,842,162,827,876,46,536,764,95,67,937,773,371,756,835,733,532,162,177,630,179,11,359,368,926,685,465,681,868,929,518,895,750,791,866,503,876,410,383,283,42,758,95,835,811,5,545,880,811,678,896,897,807,440,780,705,551,651,362,951,405,74,967,172,919,226,596,518,759,604,374,84,338,857,821,301,296,207,727,552,709,404,763,441,130,531,474,526,89,391,98,173,817,516,662,537,961,555,253,430,468,38,799,515,687,0,272,742,752,953,434,539,690,733,187,63,342,875,876,716,263,589,396,428,866,83,904,663,922,37,583,150,449,622,449,8,137,288,634,950,497,25,677,533,465,231,44,676,511,337,550,269,907,883,464,193,526,415,15,583,948,935,3,766,619,882,444,424,355,123,737,556,873,481,353,585,208,958,34,707,995,437,982,543,719,818,635,168,968,441,695,477,9,934,939,238,103,373,129,612,751,255,521,132,455,142,317,947,84,662,369,514,905,615,518,994,764,390,911,961,181,141,254,263,148,668,11,536,995,425,57,953,352,222,976,927,328,841,974,107,284,510,314,633,899,701,629,276,230,311,330,685,982,331,434,584,774,526,430,179,612,120,891,43,633,747,59,901,610,167,520,867,747,169,840,712,827,408,748,472,48,152,973,681,692,20,460,313,688,77,303,978,922,93,775,37,788,283,429,368,94,871,158,566,965,921,616,517,478,161,401,384,712,368,487,934,816,72,53,829,161,393,571,912,422,29,748,110,307,233,701,240,51,285,716,794,624,860,846,718,556,82,881,389,576,787,549,248,935,461,35,732,625,372,752,271,138,378,970,842,237,635,288,134,101,583,364,144,519,855,451,16,289,647,116,66,886,421,818,973,596,330,815,730,188,275,112,292,706,935,346,505,758,200,574,424,234,671,304,683,878,525,213,566,945,670,404,293,7,756,570,89,755,183,132,822,39,432,123,866,288,720,288,379,444,601,455,660,31,629,225,925,39,107,833,391,131,486,580,906,881,377,93,617,238,27,684,794,70,704,451,999,522,739,8,626,939,711,715,475,932,759,935,771,108,624,328,281,92,24,858,906,724,123,948,478,45,373,453,569,637,68,65,256,696,849,991,654,299,145,24,683,510,586,545,17,444,856,300,110,892,88,515,268,12,72,596,394,324,431,897,129,579,526,950,815,290,199,368,748,473,35,606,551,909,90,453,14,992,989,450,740,893,431,671,984,317,73,482,251,735,902,972,880,408,997,221,590,225,300,173,224,247,62,714,508,896,529,674,482,329,595,52,396,717,49,856,539,385,958,30,392,138,904,227,954,342,785,985,225,801,95,203,604,703,135,283,727,401,55,49,486,861,756,702,55,392,542,274", +"956,827,133,401,501,990,333,64,402,77,906,486,601,191,453,835,962,809,401,837,838,728,669,995,639,943,557,824,720,10,151,25,807,296,253,246,45,377,610,406,904,25,747,422,494,487,731,469,835,575,696,737,390,183,552,923,974,24,905,709,600,764,218,875,907,895,502,636,258,70,311,480,872,446,849,280,451,508,446,555,578,473,486,775,915,316,75,219,985,839,581,583,186,477,647,409,272,439,76,92,595,51,96,951,934,302,679,971,433,338,321,620,738,972,831,519,40,939,807,945,750,643,167,681,592,618,662,527,935,150,376,201,481,593,55,498,631,952,306,337,621,736,459,39,436,58,481,528,675,900,895,446,7,910,792,751,854,222,298,629,208,506,779,709,32,465,850,105,386,552,701,401,842,513,422,552,149,156,125,549,458,972,861,139,716,149,217,757,517,796,510,947,427,840,747,83,725,551,876,654,877,575,626,439,134,799,257,367,232,969,740,839,116,676,403,110,218,725,781,787,434,26,225,330,837,881,173,533,774,364,493,748,339,40,269,153,271,713,52,517,710,684,550,14,621,280,18,989,783,4,715,996,446,489,58,802,14,965,275,146,906,79,251,104,220,598,990,951,284,757,263,421,765,416,526,869,162,671,464,830,569,647,328,905,499,439,501,49,280,280,539,506,121,787,856,789,684,539,891,753,839,60,205,415,629,468,389,187,979,323,522,525,897,2,124,984,141,394,128,221,425,253,682,215,295,750,502,599,3,681,693,343,861,61,824,931,955,629,603,58,379,427,557,599,729,883,696,216,584,915,443,807,190,259,265,870,982,908,318,436,120,330,15,148,461,62,208,739,190,256,704,176,865,845,799,685,873,113,945,106,687,171,349,969,566,609,587,276,849,549,76,151,625,86,350,83,604,816,195,827,943,174,193,79,786,469,509,820,112,511,788,631,529,648,539,679,862,751,701,799,448,128,338,523,478,838,966,189,84,958,923,870,399,49,79,161,899,16,276,527,442,647,934,901,304,146,501,824,494,802,525,209,515,661,444,987,478,553,417,193,667,355,861,28,331,104,431,680,72,454,969,690,316,465,321,276,815,515,412,305,834,605,179,24,461,537,57,100,670,244,524,589,833,789,370,388,36,498,581,966,798,106,492,831,886,976,272,0,68,408,565,311,29,364,697,890,50,692,215,115,856,194,574,331,693,818,226,948,634,813,681,249,134,141,878,473,228,857,370,340,946,363,19,740,850,645,251,714,68,57,614,327,520,823,7,250,348,549,915,272,283,569,879,575,403,520,430,613,682,327,9,550,421,800,558,93,322,139,525,116,220,883,623,474,100,429,392,916,652,641,664,613,850,106,499,527,981,628,355,678,294,904,916,889,128,682,905,64,983,383,115,790,28,783,693,378,891,697,470,409,693,588,995,62,215,129,815,940,954,308,365,273,640,55,747,71,180,788,329,501,986,130,471,251,168,585,72,124,405,370,208,158,865,742,684,230,434,767,891,293,606,182,888,145,594,3,266,166,260,73,531,257,29,668,733,112,976,35,294,264,445,292,27,347,718,909,218,568,242,644,470,885,294,43,456,979,312,233,319,815,564,286,66,380,871,806,459,4,190,691,375,552,498,829,186,206,419,275,716,487,115,607,681,892,551,401,505,121,793,524,776,329,658,938,469,933,110,183,146,929,633,603,879,14,521,258,862,192,424,463,675,642,38,62,650,438,165,923,112,924,218,817,83,51,49,140,165,588,510,387,45,224,815,774,829,355,475,304,984,607,289,774,177,13,319,228,523,133,810,25,857,53,132,820,116,569,670,529,743,565,885,836,468,479,609,923,628,368,664,683,927,297,523,474,730,274,892,975,189,742,222,259,860,826,390,239,541,142,938,779,195,685,294,734,12,587,175,421,791,759,897,972,898,612,926,567,968,378,172,714,687,674,200,581,462,334,396,862,208,142,568,586,111,346,645,95,312,981,585,119,764,259,272,414,365,529,31,701,789,981,243,569,338,587,620,789,908,356,763,815,315,284,201,990,426,666,299,577,249,651,654,141,734,851,16,620,762,585,325,691,790,642,137,877,701,541,839,867,802,330,864,362,187,191,162,693,773,912,851,681,137,787,469,38,621,55,82,227,194,241,878,800,673,347,542,50,474,514,644,489,903,533,855,411,789,444,720,866,571,893,814,74,954,512,305,759,469,92,222,298,255,676,62,220,425,454,472,517,536,283,384,276,387,142,715,831,361,874,456,102,898,490,139,415,362,193,903,388,672,151", +"834,723,47,704,87,395,577,734,932,203,475,281,402,157,269,454,63,334,475,362,928,922,870,343,455,845,689,383,956,557,496,798,633,302,510,642,681,228,665,597,221,581,434,141,190,400,287,255,713,693,338,985,122,854,508,20,884,917,998,202,944,806,857,959,35,857,801,415,442,460,34,438,782,67,699,473,742,676,734,330,876,290,792,754,275,171,324,767,665,859,129,372,560,352,447,951,208,316,967,126,117,221,615,461,67,616,16,596,633,403,928,317,861,422,175,32,883,268,930,666,11,13,303,952,540,307,712,559,788,795,584,952,619,879,351,915,60,395,62,597,271,184,476,879,527,865,163,571,934,775,129,641,918,304,524,546,235,272,833,47,676,62,726,69,406,646,179,152,893,173,727,887,676,123,419,729,21,177,4,933,671,965,629,633,422,682,141,750,3,675,282,450,741,947,655,24,455,771,588,538,475,398,41,742,931,734,801,585,398,387,939,462,375,704,9,610,549,238,854,338,16,262,121,403,236,499,134,606,429,217,587,855,100,223,80,670,771,214,252,608,22,815,737,565,422,879,673,599,181,492,372,27,282,733,368,490,676,251,54,146,316,133,285,395,834,249,519,535,906,471,828,689,906,683,483,11,631,896,596,314,990,903,455,85,975,117,985,667,846,917,256,417,6,404,265,981,175,655,324,893,812,291,790,197,925,907,431,479,410,590,84,641,309,284,941,115,189,336,658,370,63,668,548,978,831,440,256,970,255,716,475,721,722,349,313,773,292,313,3,422,367,219,723,766,68,704,664,607,237,422,747,160,332,17,944,813,76,538,858,90,378,911,453,98,636,166,165,701,638,124,216,860,896,243,415,116,972,261,642,897,469,459,139,970,79,585,733,847,244,82,112,846,912,618,223,88,466,304,649,447,971,131,324,517,66,618,673,511,839,240,365,314,541,209,427,640,713,998,872,148,478,464,842,140,494,111,967,123,350,836,497,38,481,424,152,427,75,675,567,42,602,139,60,98,625,776,248,66,901,480,119,756,929,439,523,729,781,598,305,564,982,139,31,669,609,89,720,210,950,37,58,301,763,78,505,740,259,239,613,956,151,884,580,210,175,515,858,117,423,326,456,698,6,774,834,954,103,417,234,802,930,219,206,24,407,967,742,68,0,269,602,270,504,720,796,156,458,851,336,522,435,361,605,128,145,303,461,922,478,650,384,539,547,461,633,409,798,217,430,834,41,495,865,468,323,200,113,899,545,286,410,574,15,709,144,214,495,585,28,850,948,64,64,180,136,111,400,204,105,259,103,799,914,126,159,129,51,199,62,394,355,262,89,581,725,765,842,554,437,925,815,510,988,714,785,208,161,731,135,851,56,596,464,912,509,759,437,220,464,272,826,408,912,100,384,843,855,370,848,711,521,684,505,375,616,778,353,464,45,77,594,182,340,806,280,826,952,815,122,181,845,119,218,983,456,376,379,310,821,266,783,571,122,922,33,907,843,270,770,184,927,976,8,769,200,690,167,335,411,194,174,675,40,656,843,430,631,423,13,256,362,943,526,603,474,506,869,999,810,292,12,147,125,371,333,409,609,85,673,146,717,591,906,723,328,646,399,180,482,991,300,359,142,992,20,717,594,107,372,373,323,695,190,495,741,830,704,67,581,64,343,616,895,573,889,400,506,118,150,171,164,154,969,314,355,550,738,819,956,466,635,342,80,842,610,330,183,597,554,323,196,447,936,547,922,606,46,118,776,800,611,722,389,951,338,57,859,505,491,565,362,592,9,227,346,449,78,626,882,385,162,142,461,955,170,344,932,746,535,99,50,50,860,515,809,100,167,218,923,299,480,687,711,729,441,45,590,300,597,865,588,250,902,514,734,957,898,761,628,161,578,577,736,173,444,325,21,438,930,248,970,672,829,986,866,331,542,548,351,154,59,633,203,561,176,193,343,676,879,104,910,405,567,58,67,116,568,470,450,943,858,704,275,30,726,482,841,526,367,675,194,57,345,183,444,446,938,435,465,383,720,775,523,258,793,580,582,297,785,494,892,816,893,845,449,228,163,441,948,652,901,523,509,736,294,617,358,144,264,554,466,730,196,297,938,896,377,929,665,500,350,789,660,489,651,921,548,971,275,770,894,855,915,988,500,736,626,717,419,311,259,657,612,448,195,509,60,96,1,489,421,764,788,120,722,985,839,811,181,13,445,873,5,871,454,48,721,475,531,953,558,900,651,310,436,238,499,603,887,160,464,482,486,625,813,501,24,702,977,256", +"676,884,370,258,268,307,154,534,644,991,725,897,589,208,158,190,61,87,511,468,57,360,674,66,413,701,219,234,57,932,90,302,189,690,732,527,575,255,188,48,728,678,923,621,209,510,293,635,23,153,686,394,148,123,913,16,790,139,971,841,452,469,805,388,624,436,627,91,901,907,961,771,729,82,564,398,456,435,851,896,190,266,400,661,794,756,45,326,427,638,290,914,383,641,770,773,597,356,247,91,615,111,580,495,207,999,419,301,39,622,983,403,174,927,718,401,427,833,476,511,973,313,657,948,954,644,957,138,528,556,387,703,823,771,44,824,376,265,718,378,484,49,618,977,89,760,76,436,900,226,145,747,524,280,577,667,303,161,35,913,675,756,427,145,620,696,782,505,683,839,505,615,662,633,547,662,220,126,952,25,707,166,370,56,800,175,610,738,499,165,27,885,838,262,197,798,834,347,745,379,977,523,772,905,914,179,86,954,520,499,883,699,280,584,540,352,928,12,632,285,649,319,984,201,199,732,277,379,720,784,4,10,263,463,740,999,145,851,883,962,876,845,759,865,451,922,366,602,474,590,790,679,862,532,120,702,848,197,764,407,993,304,945,236,2,923,127,496,413,738,58,60,38,464,218,662,306,749,864,805,929,243,954,27,15,895,627,796,592,361,311,33,677,372,674,442,676,276,588,390,116,181,906,498,186,542,559,824,42,474,776,464,690,819,41,221,440,860,837,902,169,178,687,318,123,583,572,995,340,467,122,387,680,221,784,401,275,583,491,754,980,256,508,227,287,305,341,506,760,817,852,811,673,313,330,976,864,497,947,969,451,294,294,928,831,5,756,708,755,65,654,984,838,511,24,461,391,452,476,962,769,912,366,487,241,913,113,144,565,854,74,355,831,281,393,44,958,590,739,188,586,971,172,932,996,416,275,824,473,784,501,571,784,700,630,565,46,233,306,740,510,760,476,448,869,105,463,780,520,638,403,654,534,57,973,817,329,768,405,273,567,665,129,845,930,470,895,526,324,728,42,504,988,729,904,399,48,438,264,930,746,808,613,198,281,702,131,876,536,267,26,671,862,130,124,236,690,322,838,841,5,809,400,447,905,16,670,112,554,84,124,514,186,815,693,544,953,326,385,777,948,261,350,745,726,484,752,408,269,0,481,242,134,219,871,278,87,484,251,607,826,268,82,654,355,487,380,912,216,743,160,887,391,114,693,447,510,698,910,532,178,678,626,506,99,751,645,991,432,414,159,728,188,212,961,323,395,704,558,113,53,625,709,450,368,487,117,175,729,25,675,790,928,769,462,495,829,215,995,337,206,794,392,623,220,454,305,367,522,257,827,624,744,697,538,806,131,585,995,702,334,596,678,366,109,433,455,627,55,170,390,148,884,50,940,943,441,550,606,206,273,22,275,465,475,810,390,643,394,844,66,518,848,792,820,55,362,11,390,603,35,351,45,125,465,174,163,452,153,462,944,658,563,923,732,825,193,528,886,65,228,110,9,6,706,19,742,453,328,190,17,680,878,596,865,561,529,802,723,957,976,602,686,593,864,95,141,848,413,154,443,200,254,321,640,986,643,593,331,849,389,433,904,960,83,362,721,738,536,844,941,630,906,460,580,914,769,994,432,370,459,340,367,822,925,170,629,945,777,708,699,854,247,288,690,544,686,962,935,48,87,777,623,444,194,252,414,39,220,198,809,603,542,397,225,23,920,549,100,724,235,140,262,938,968,406,342,489,637,165,442,405,771,669,264,183,378,378,921,478,670,330,741,114,284,244,597,625,602,458,417,278,189,613,101,161,857,586,349,983,234,594,658,56,146,575,555,636,364,29,201,733,129,108,216,843,987,902,104,188,111,968,983,543,272,866,958,35,76,462,694,939,328,928,246,403,942,117,664,408,819,229,560,144,335,1,615,213,349,58,145,946,436,914,246,354,261,980,555,407,79,567,649,741,198,672,844,940,203,632,201,579,195,800,143,784,221,812,976,817,912,747,77,457,811,98,335,397,736,64,890,106,322,942,797,154,336,823,393,292,547,356,721,591,391,868,51,723,242,55,801,346,414,615,950,310,189,811,234,445,435,223,194,402,993,956,69,547,566,304,398,946,751,973,178,285,985,550,921,175,55,113,227,735,457,246,341,675,769,511,822,606,28,935,104,582,939,272,685,170,544,193,812,502,631,738,732,72,418,190,120,836,660,294,733,372,61,354,940,272,325,812,784,797,628,435,636,730,939,818,165,489,657,446,779,545,158,990,266,226", +"28,670,801,575,363,630,471,8,444,625,906,858,23,708,463,697,342,579,519,704,460,584,711,125,218,542,977,450,526,44,700,432,813,570,489,296,314,489,238,61,187,179,155,362,841,910,642,552,407,526,474,65,540,537,615,655,407,592,71,260,330,993,196,691,841,268,100,714,726,667,274,971,828,630,381,576,702,410,611,382,546,232,607,204,306,942,686,568,88,735,177,143,442,816,798,901,690,128,219,700,107,27,743,781,468,18,953,40,639,667,623,301,468,529,47,548,895,560,762,662,209,362,670,953,566,604,904,636,755,206,444,137,280,323,799,704,777,889,102,951,761,260,336,538,336,46,653,119,781,28,79,425,657,667,524,820,97,219,547,796,133,211,564,687,121,343,64,93,186,76,417,26,94,986,337,771,138,178,746,29,412,748,181,367,619,840,841,264,548,318,406,30,517,24,273,150,664,941,247,286,774,310,670,703,416,499,36,362,607,293,261,807,352,137,85,219,559,569,169,983,937,351,588,298,346,601,413,28,457,149,638,716,909,45,779,359,412,650,253,800,583,371,222,719,190,445,915,577,640,102,601,969,184,239,472,371,710,377,518,230,104,895,84,30,112,94,211,946,224,458,965,128,593,634,204,517,712,288,812,983,583,933,341,355,267,781,638,134,942,100,705,908,644,690,132,835,579,299,254,318,462,918,370,498,600,923,703,76,155,18,892,250,22,564,462,511,538,914,632,306,185,988,887,165,208,587,890,71,616,514,597,989,182,737,26,206,867,346,375,749,905,208,24,453,883,122,643,910,143,1000,529,234,625,784,721,546,679,747,280,98,137,529,197,555,269,640,893,887,383,342,484,798,636,447,732,592,471,123,888,127,99,287,742,197,909,971,737,782,389,431,262,579,226,332,410,921,428,215,612,579,561,47,94,505,515,312,99,773,502,507,359,471,674,291,420,827,848,714,541,219,675,967,79,346,672,946,44,526,883,165,553,79,548,546,608,293,691,357,61,145,198,232,849,974,599,551,549,434,465,219,426,770,630,219,737,538,447,213,334,142,662,253,411,715,835,772,97,858,531,531,472,260,729,991,362,340,832,881,737,211,327,667,774,952,988,734,107,486,736,127,473,125,175,269,856,424,527,399,915,490,61,887,432,317,29,894,953,565,602,481,0,937,294,871,547,228,784,998,421,639,760,589,68,401,27,674,28,779,242,160,936,1000,581,964,670,57,450,104,57,367,239,963,49,971,97,749,255,823,367,602,513,559,683,133,158,664,810,654,720,893,257,511,890,507,312,96,727,983,989,912,362,838,432,16,224,259,537,692,157,423,416,59,115,481,916,239,64,632,16,615,685,133,453,953,280,917,449,682,475,536,788,982,422,369,400,830,768,571,470,24,640,493,427,590,909,536,892,456,801,616,42,143,456,707,858,285,647,613,219,594,907,348,188,219,50,856,426,822,860,228,865,362,810,169,252,328,267,40,606,881,583,218,406,309,73,945,705,845,464,805,738,964,755,137,336,905,808,466,957,654,618,332,121,520,910,45,727,286,557,226,919,756,781,652,384,958,828,96,474,216,156,614,405,543,861,417,71,992,612,433,780,527,555,253,682,314,792,199,76,795,939,411,291,586,160,98,82,227,865,494,317,152,272,158,452,390,801,724,784,962,962,382,351,390,279,856,72,859,753,550,564,40,56,665,2,186,833,986,712,800,510,699,14,607,375,810,443,370,492,374,854,27,225,846,399,850,131,774,713,295,942,972,198,192,489,970,22,892,235,481,376,703,615,558,534,819,313,146,232,306,251,725,652,285,292,348,611,414,123,329,186,766,284,456,327,775,40,586,353,668,251,478,5,367,675,942,869,66,948,787,659,848,458,184,790,993,902,989,767,996,473,671,695,785,695,653,832,382,193,926,749,488,951,422,833,114,612,897,296,248,183,113,971,26,591,671,653,794,122,997,970,430,631,259,74,828,517,839,953,526,140,958,428,674,523,33,805,573,612,904,351,865,507,178,1,849,342,486,796,778,542,602,640,372,254,865,748,596,296,659,651,430,761,843,898,978,649,971,33,327,333,691,175,452,452,817,942,260,514,75,652,26,423,759,714,230,470,142,820,430,89,553,600,295,302,510,333,660,587,186,485,991,779,573,603,327,625,499,619,581,404,298,189,51,895,201,224,990,462,741,248,688,592,818,544,349,446,891,395,953,325,674,282,533,102,69,461,354,433,246,487,104,554,445,250,490,59,589,213,789,487,283,780,87,114,201,8,19,748,297", +"533,129,455,407,134,279,906,291,352,843,948,566,810,670,987,473,837,245,644,59,408,107,976,131,132,670,765,382,264,763,437,640,588,927,298,886,405,42,395,925,297,858,642,707,413,700,366,525,73,444,232,287,217,549,3,213,294,908,909,606,68,584,644,318,188,813,779,58,891,311,8,569,33,501,999,510,730,612,709,118,941,554,970,730,151,51,819,784,972,492,852,939,443,120,253,394,792,529,668,461,553,11,487,380,895,433,501,791,690,476,756,640,959,134,351,72,912,800,725,254,553,656,975,159,163,788,936,768,724,935,56,95,269,439,250,390,355,99,334,554,470,355,699,687,273,992,728,68,770,134,990,819,768,652,898,732,518,599,360,978,504,729,874,898,573,661,818,430,509,560,787,799,365,506,621,641,431,716,643,204,779,883,774,257,207,479,213,247,672,685,375,931,595,353,376,376,555,79,83,62,196,464,946,268,420,913,409,78,309,638,514,827,283,326,623,842,394,884,238,565,359,690,624,807,967,529,920,66,642,713,799,63,695,377,658,211,562,407,667,874,681,18,715,391,807,515,94,33,142,445,859,37,962,359,565,368,9,650,652,440,798,258,701,689,342,239,120,518,433,709,256,546,160,826,960,322,865,16,852,946,581,729,735,714,595,799,432,68,150,921,749,849,902,520,172,554,697,711,984,229,459,161,347,884,277,612,618,9,970,747,724,516,836,218,878,969,155,53,64,614,273,974,391,859,981,47,782,851,643,64,670,539,953,610,630,509,905,930,596,342,485,301,798,68,90,716,299,40,595,429,849,978,293,414,353,486,377,474,716,386,342,94,550,84,39,684,422,143,925,22,296,747,770,690,132,239,310,767,949,303,672,136,151,494,531,689,123,247,473,91,8,556,301,418,183,698,542,37,453,131,990,371,210,575,59,276,998,307,99,63,95,173,316,374,836,892,758,792,673,113,50,598,480,165,92,532,932,707,791,393,876,292,742,4,622,765,554,865,63,262,287,264,853,77,816,21,57,805,283,999,227,626,449,989,419,560,760,641,687,354,890,733,101,199,553,449,650,833,24,572,207,653,886,413,545,25,268,768,807,778,439,244,157,721,501,121,658,16,199,55,963,882,948,721,237,860,953,255,673,649,197,234,990,699,833,2,434,311,270,242,937,0,995,176,681,577,43,983,117,832,629,252,582,880,619,994,331,909,879,893,729,721,993,591,326,852,501,698,164,898,938,853,284,694,566,460,412,393,317,8,290,822,636,826,526,888,565,229,80,795,297,696,969,184,340,112,171,564,976,543,357,202,716,858,645,428,339,443,974,154,832,237,952,761,158,829,13,97,762,640,268,913,249,555,125,555,130,229,566,359,929,515,341,649,250,495,265,68,27,540,846,598,844,537,578,276,57,399,945,107,886,722,486,925,892,312,668,863,283,911,522,787,265,352,569,942,155,840,814,365,488,380,759,240,431,517,30,865,67,16,268,438,116,785,342,33,56,448,967,922,308,841,782,338,217,69,57,321,316,721,48,365,308,489,856,826,742,300,705,82,12,106,932,650,539,509,512,352,298,2,10,71,189,430,340,595,845,101,762,443,778,565,319,343,319,460,419,606,766,524,625,571,474,892,405,267,989,818,428,942,407,14,284,2,12,37,279,194,607,679,186,609,20,142,296,557,933,602,99,703,640,673,149,266,702,477,407,911,850,755,64,65,939,458,681,72,108,144,785,24,555,169,467,791,949,884,996,184,183,802,529,256,690,935,682,91,591,223,691,94,592,556,906,135,146,246,49,262,216,107,969,124,147,731,806,24,323,125,876,33,46,26,998,235,467,628,411,339,461,223,729,264,424,225,380,285,434,977,699,300,147,761,442,844,923,434,319,239,232,347,581,330,657,40,974,635,327,522,79,540,528,692,160,384,475,616,150,896,601,330,722,735,666,130,33,405,707,909,602,966,259,712,549,312,895,547,611,973,718,236,352,920,288,515,960,852,456,839,663,985,59,601,194,604,985,706,371,115,679,14,470,66,291,268,197,219,320,976,389,787,569,700,763,1000,842,737,610,69,312,844,489,924,224,276,792,741,549,778,340,840,486,473,959,555,396,428,933,64,675,936,228,234,781,516,647,232,638,107,573,125,573,347,771,807,922,371,767,221,887,173,363,536,974,336,598,171,876,634,424,438,477,816,760,58,380,118,728,87,750,925,964,837,944,400,217,928,728,596,693,57,83,238,486,315,859,583,937,667,244,360,177,863,142,24,621,473,769,551,924,293", +"256,831,849,823,415,938,921,254,652,538,145,569,440,742,353,499,586,2,443,136,403,425,507,263,13,765,189,684,925,326,723,914,842,586,120,414,478,709,152,839,979,362,153,940,269,704,485,221,529,954,439,417,655,913,955,851,750,855,803,442,645,124,442,541,345,55,498,822,325,338,552,983,294,665,628,117,743,173,696,630,578,909,45,881,267,829,999,718,751,851,440,616,325,397,790,345,628,573,355,698,315,657,970,585,36,150,725,206,814,76,721,23,283,188,489,517,142,131,130,730,848,107,805,640,190,3,338,508,274,317,593,810,809,695,788,971,352,797,208,746,384,652,675,603,524,620,962,987,874,909,272,574,772,22,461,964,133,296,162,161,81,941,5,839,355,578,257,69,484,702,526,193,494,67,968,821,11,10,75,462,67,347,244,398,411,231,425,373,285,225,387,668,40,992,896,945,227,752,189,492,856,420,917,420,195,960,430,594,977,883,720,280,928,740,95,323,449,112,58,933,332,166,706,479,244,442,197,510,779,386,741,187,613,883,813,733,634,120,908,685,952,622,88,223,61,476,326,283,852,524,783,169,154,241,475,87,720,192,743,267,487,99,113,261,935,667,864,967,845,616,42,333,105,505,492,173,625,191,753,62,761,544,854,642,997,855,556,533,75,263,990,682,421,640,401,666,735,552,513,952,582,871,334,958,9,742,883,101,756,206,307,477,849,473,373,137,185,707,968,147,890,664,412,284,423,919,632,152,828,730,627,143,81,344,356,381,173,768,270,114,679,989,431,170,963,518,236,513,758,569,423,401,26,305,575,442,969,323,563,123,411,235,747,445,648,73,674,359,992,623,739,118,888,84,585,345,124,476,376,436,352,836,343,367,268,103,894,666,841,331,74,838,797,829,921,508,210,461,707,507,380,104,866,312,424,778,309,984,118,930,382,403,705,196,739,325,494,965,931,952,491,973,49,914,53,417,678,370,711,368,22,810,733,222,617,891,241,540,40,406,764,643,674,567,120,600,724,995,176,376,80,199,253,86,678,517,440,476,237,329,939,252,827,707,65,347,476,271,608,630,761,496,748,281,629,511,316,42,438,205,383,53,235,579,385,308,318,563,586,968,348,130,735,860,676,530,192,792,810,430,592,927,800,992,923,264,539,29,504,134,294,995,0,767,572,993,931,420,17,439,709,538,586,284,529,540,828,716,866,792,535,863,475,257,122,268,576,14,813,539,595,709,524,78,895,879,915,264,174,314,361,724,426,416,71,60,225,489,857,962,284,217,665,46,617,62,943,259,669,836,378,589,929,185,723,950,292,449,707,910,478,956,786,553,8,772,387,978,779,761,144,670,325,212,800,644,828,756,874,66,18,64,586,106,546,730,883,45,267,107,694,490,231,614,905,381,649,282,312,983,823,583,566,492,377,751,65,865,797,313,430,197,713,445,178,691,962,669,399,328,788,605,764,10,666,61,668,221,788,990,158,735,102,494,837,898,649,120,776,220,998,488,40,910,273,202,673,656,659,793,506,647,336,470,831,681,221,291,810,152,497,118,336,697,668,682,330,34,979,562,790,869,448,810,216,652,730,918,517,397,337,340,352,921,764,296,615,867,664,802,172,149,731,448,375,466,261,14,248,793,806,156,540,806,487,276,540,228,904,472,474,645,342,79,886,796,922,225,562,168,968,632,441,637,750,690,973,591,386,261,524,375,274,43,764,607,215,62,760,347,598,532,698,962,147,679,13,207,594,578,291,183,987,9,95,253,131,639,166,39,309,464,692,755,505,581,826,856,867,770,261,299,810,453,199,151,929,761,729,234,694,368,102,533,978,276,894,955,191,673,199,740,356,853,881,865,824,715,646,307,702,230,408,942,650,902,532,436,110,363,793,131,792,542,912,351,256,913,928,395,668,434,131,959,761,844,530,291,834,248,883,634,646,830,985,521,458,499,97,984,221,990,731,454,21,459,448,874,456,833,237,702,742,602,213,865,533,593,913,404,214,343,642,936,130,794,521,695,745,617,192,403,780,304,604,388,130,346,760,548,915,871,399,12,551,876,756,194,340,307,683,664,985,49,494,372,458,784,27,166,353,287,774,868,379,819,172,34,551,845,266,664,419,850,658,132,677,505,254,297,817,422,555,81,614,89,955,183,798,700,237,447,223,189,405,885,358,691,803,99,311,354,483,137,454,105,733,410,779,606,198,314,211,837,906,324,861,836,761,908,989,212,507,232,76,959,163,575,506,514,559,744,890,488,28,893,158,51,752,920", +"904,500,326,406,175,203,504,471,525,103,128,834,126,219,581,987,807,243,803,190,748,45,32,228,178,545,480,309,647,892,272,458,580,202,885,44,365,648,61,641,662,168,614,356,769,346,718,963,101,287,790,814,462,97,124,193,488,152,527,290,180,294,55,191,251,751,939,440,155,37,214,112,368,848,188,417,229,504,125,907,274,877,488,464,100,715,742,856,279,583,388,880,571,55,719,281,326,263,371,114,193,171,528,879,141,292,7,22,597,201,122,614,203,446,75,486,254,503,886,801,565,35,540,244,416,518,345,642,677,879,216,694,840,664,546,172,448,803,709,88,896,627,605,62,697,942,539,107,422,485,892,228,176,730,544,828,646,772,781,751,743,603,987,209,256,979,763,950,636,77,515,782,508,560,448,811,911,474,800,384,81,616,514,940,602,64,29,961,992,874,931,147,714,837,737,146,688,846,585,825,916,349,387,981,29,529,641,921,772,360,417,539,679,830,937,812,536,495,664,211,760,569,112,114,160,889,337,117,993,231,364,448,697,332,930,447,688,916,762,526,779,404,376,34,674,622,690,605,382,924,566,747,997,47,903,825,493,407,341,414,543,611,141,67,670,848,856,817,784,816,863,684,722,139,107,548,915,979,102,563,247,286,176,720,665,444,957,503,491,430,151,158,431,745,743,832,122,786,174,455,372,64,439,952,792,705,641,902,707,758,661,796,149,40,333,527,174,194,589,298,37,796,12,866,26,645,74,623,142,947,637,642,895,647,70,956,116,990,37,308,528,719,422,920,751,35,86,867,734,810,626,211,995,309,349,680,666,792,346,928,446,972,156,509,499,61,166,301,158,680,546,328,844,770,715,717,552,338,205,214,725,857,141,23,941,661,977,535,870,283,726,421,172,658,178,519,666,365,285,431,511,802,46,809,617,261,575,807,848,262,196,584,319,901,757,666,697,891,282,230,975,269,902,188,724,804,61,672,524,215,296,3,480,891,281,217,277,141,550,184,996,747,315,829,196,128,957,267,735,978,942,445,582,171,339,45,615,918,151,102,133,198,369,355,821,930,15,555,832,43,151,504,789,910,391,281,905,740,74,361,839,938,187,268,823,683,339,890,337,299,686,686,360,71,241,393,248,442,787,378,388,363,46,233,172,813,690,364,720,219,871,176,767,0,207,610,547,836,702,954,90,892,123,667,408,138,496,222,911,14,981,370,955,196,280,623,257,627,476,153,24,892,546,173,823,371,265,715,99,251,758,812,167,443,53,425,467,503,711,130,928,841,224,819,741,360,710,492,584,228,579,613,732,367,703,535,271,835,135,156,771,530,829,956,588,878,425,574,5,668,373,847,378,407,82,469,851,461,318,181,177,587,684,131,159,30,799,29,10,826,286,14,74,350,870,619,70,95,107,754,472,105,783,715,972,193,77,970,629,286,898,198,989,393,871,535,268,58,594,826,736,876,311,37,248,915,990,558,689,34,396,954,266,437,362,936,124,428,111,615,110,150,57,974,230,845,183,155,343,431,936,743,739,707,479,880,889,531,816,66,739,904,483,401,624,392,442,926,978,133,401,812,202,334,231,362,527,242,271,89,271,635,395,181,815,484,908,51,851,319,648,933,714,434,472,831,570,121,143,292,70,691,811,632,264,813,683,881,742,807,164,163,51,376,663,494,863,413,943,276,26,572,648,180,649,584,4,723,438,241,774,572,270,83,449,533,527,291,330,510,327,540,825,784,811,533,747,885,819,121,211,974,387,226,601,667,506,924,44,506,857,697,295,459,631,524,514,997,667,632,30,857,570,344,898,891,746,212,98,978,529,663,707,532,550,700,169,52,513,190,337,911,290,179,242,108,626,748,879,259,865,568,86,104,372,144,616,206,178,614,88,465,169,892,133,54,237,71,776,111,350,997,129,73,194,135,850,405,300,246,922,742,420,228,768,928,359,579,496,26,113,925,226,894,446,848,93,990,182,287,422,294,905,193,224,475,210,21,259,276,274,734,762,465,491,842,921,87,354,761,332,286,786,36,749,48,12,232,380,846,112,511,781,982,560,454,99,654,317,507,673,723,211,566,589,107,711,325,501,81,218,995,189,266,656,811,783,861,442,285,627,539,790,735,991,766,337,51,943,826,266,821,292,500,115,655,596,583,690,790,947,123,472,695,307,72,329,656,286,751,70,79,110,374,773,351,694,601,688,704,147,753,871,53,922,412,785,168,961,537,14,864,700,479,153,30,224,944,914,978,838,68,644,528,727,809,560,623,701,272", +"606,422,32,50,483,728,752,879,215,736,281,860,430,755,448,704,190,306,359,843,715,243,339,148,815,716,811,622,612,557,943,172,332,28,481,649,291,267,97,108,460,504,316,929,158,686,836,45,852,358,658,928,187,763,281,724,989,481,721,536,151,408,877,888,911,89,590,889,300,153,952,498,286,860,165,289,64,560,494,28,604,136,178,800,827,940,948,213,786,103,140,390,89,846,608,746,480,361,987,994,920,906,690,62,502,197,220,813,19,991,470,199,370,186,362,80,717,855,123,950,609,58,104,808,860,149,238,760,49,935,660,739,241,656,943,3,352,128,323,23,586,856,898,407,584,252,769,844,787,503,624,801,626,785,738,529,706,951,895,63,476,296,674,139,125,665,831,832,840,202,453,253,695,865,396,206,623,664,378,396,361,547,886,35,823,59,556,34,759,263,832,229,731,987,885,514,920,9,12,966,616,577,247,226,928,961,812,426,577,969,384,342,824,208,333,537,112,820,42,584,259,938,413,127,924,863,268,227,877,82,350,808,494,424,806,421,283,723,874,270,526,461,69,812,485,945,282,806,770,193,100,828,949,75,126,90,222,842,512,700,807,245,887,469,23,826,775,452,937,818,289,110,665,274,915,600,114,905,763,957,150,173,937,124,406,71,87,235,63,855,927,947,797,994,913,939,759,806,203,189,80,760,67,718,563,294,341,920,656,335,704,477,901,772,226,503,585,426,959,936,410,538,968,524,550,53,301,987,297,419,906,214,962,495,847,866,266,786,363,559,804,822,89,413,828,757,46,181,524,147,813,292,158,542,86,60,307,257,555,631,684,289,829,518,196,302,777,1000,630,951,675,984,225,494,65,43,889,560,867,40,256,9,183,248,863,89,442,444,112,809,931,562,87,559,295,932,680,354,105,642,386,225,330,78,693,410,973,381,349,756,175,322,38,741,60,991,927,277,349,726,559,821,312,625,280,650,507,312,184,652,731,806,95,298,571,941,986,207,176,543,623,209,225,742,853,201,920,946,887,115,800,524,508,661,126,481,914,53,797,846,780,505,832,673,760,887,335,135,541,432,513,1000,340,5,613,332,947,691,531,869,86,598,409,47,47,478,667,976,705,285,216,536,952,733,730,553,237,824,125,532,423,143,97,419,600,843,733,697,796,871,547,681,572,207,0,333,392,947,883,662,738,790,663,556,119,217,310,295,91,119,962,307,89,752,311,334,222,687,929,650,237,999,559,529,539,660,502,218,693,148,144,121,238,427,437,441,505,229,935,70,295,871,441,304,344,807,682,280,746,915,669,262,107,870,327,965,440,57,709,550,359,885,528,166,852,450,494,234,154,468,843,874,414,12,895,178,301,526,993,225,708,381,679,800,206,99,630,611,878,505,189,466,100,768,854,168,698,230,975,555,283,531,733,252,82,443,587,821,799,889,14,662,934,230,593,332,572,92,982,272,755,940,696,812,105,27,518,482,868,916,202,346,444,155,344,773,34,894,819,204,567,259,852,826,727,919,888,196,133,583,858,424,783,988,672,433,650,147,456,974,288,13,85,18,611,233,479,629,769,682,351,515,342,132,626,163,198,178,682,118,666,195,92,875,991,793,588,819,935,410,895,133,899,328,286,780,854,615,211,963,50,558,550,11,168,393,626,641,388,339,821,79,246,168,146,208,145,69,885,503,708,210,171,564,206,744,191,836,466,582,78,149,243,232,852,902,961,574,320,885,265,51,947,797,388,251,15,383,843,118,872,101,525,686,692,21,479,69,657,880,183,75,779,373,862,666,765,95,569,904,708,85,360,304,424,528,87,684,602,179,784,493,148,652,551,264,651,448,69,689,498,800,189,353,53,979,899,891,814,626,744,974,865,875,668,788,304,287,244,488,522,974,305,973,756,162,705,930,980,941,834,286,295,928,174,87,845,772,367,720,244,318,699,273,883,929,785,215,913,763,692,573,336,812,598,6,270,631,165,917,332,981,876,874,953,96,793,552,599,31,340,74,199,674,603,620,514,562,721,701,232,557,500,13,139,616,633,896,858,110,741,124,678,161,248,985,200,369,911,179,389,430,429,718,803,17,18,49,6,394,351,312,96,348,125,83,303,807,738,646,617,396,292,657,480,577,584,489,52,116,810,310,830,21,260,436,581,832,370,867,420,801,172,435,312,41,922,677,266,120,421,443,41,447,223,995,578,60,159,179,587,946,911,1,144,960,63,994,611,707,312,650,325,831,179,275,973,12,211,435,663,799,557,747,384,918,595,953,69,366", +"334,196,329,451,103,848,302,91,90,200,19,576,20,156,850,618,765,466,783,623,545,254,68,299,739,807,682,671,882,42,188,671,117,798,831,562,969,39,608,198,86,503,925,499,50,953,135,915,655,206,458,334,911,496,273,305,524,615,952,589,93,59,386,23,901,415,486,600,187,985,834,729,764,794,88,865,843,952,528,486,505,584,808,714,519,53,250,280,277,182,440,488,438,374,171,835,853,337,504,11,363,940,729,507,796,22,132,786,348,774,671,759,147,400,704,188,562,998,517,86,858,975,422,490,181,799,450,60,859,640,890,127,115,103,115,713,114,576,860,103,391,128,799,147,50,530,510,307,550,192,466,889,123,134,804,214,695,401,3,15,983,560,135,534,318,194,884,677,580,188,325,553,449,832,514,479,662,889,802,460,481,60,605,169,814,764,591,798,859,744,594,796,499,464,410,112,82,616,590,583,897,732,330,18,530,861,521,166,870,760,143,761,664,784,590,321,271,332,805,806,482,297,839,74,114,748,259,688,440,480,154,123,653,346,729,347,925,63,507,239,178,956,664,203,108,695,717,276,408,358,640,513,57,236,960,455,171,118,218,379,279,283,375,694,223,223,642,767,332,966,21,646,339,816,240,484,735,632,54,886,787,787,347,712,723,78,140,642,51,782,127,755,431,256,237,583,25,414,210,887,297,647,718,580,399,211,365,346,667,678,545,581,266,941,524,240,846,244,6,193,765,492,567,551,921,448,760,876,268,812,848,99,381,442,23,849,698,542,884,840,650,84,155,365,72,229,945,4,474,590,85,620,989,965,655,924,592,148,862,868,523,123,503,927,937,674,392,215,93,177,614,984,993,593,883,382,30,658,958,94,168,969,226,562,772,162,389,41,570,951,186,400,718,121,935,512,779,587,818,742,705,918,991,859,690,441,162,186,50,90,439,41,489,122,909,698,27,479,735,498,527,26,266,970,702,270,754,309,526,434,682,599,487,656,58,988,111,396,425,931,718,290,796,791,71,840,88,179,236,881,827,471,866,349,161,318,364,815,502,196,392,346,530,381,536,539,454,687,572,94,251,486,133,303,726,221,519,715,333,684,971,89,719,387,150,482,269,444,408,304,592,364,507,902,903,87,104,291,427,993,971,139,418,28,772,89,187,890,156,278,228,577,993,610,333,0,459,523,824,431,168,46,883,294,577,518,344,201,401,941,910,653,866,77,748,188,541,557,795,305,107,828,409,229,155,232,693,710,618,634,240,638,236,894,87,274,234,706,633,426,84,320,44,875,624,181,130,265,61,97,839,587,39,396,995,173,635,268,836,412,738,119,240,270,104,51,198,931,424,181,95,837,230,777,881,671,664,850,67,922,769,718,861,452,810,296,729,585,44,292,78,863,899,415,945,911,340,645,731,798,388,694,284,8,618,973,278,529,841,359,289,714,224,399,470,305,997,159,917,704,703,974,544,734,955,224,712,735,373,962,510,358,286,797,838,542,504,486,325,555,489,833,661,465,16,236,877,7,357,956,804,728,177,312,440,725,713,870,634,273,610,617,471,693,496,109,382,886,268,405,834,509,366,56,500,578,590,438,851,250,414,656,276,825,538,556,986,403,925,389,157,136,962,394,72,26,683,533,937,467,203,54,221,47,208,381,841,910,135,839,46,144,584,507,560,947,528,450,143,249,820,144,491,772,16,747,475,434,62,992,595,167,179,601,203,781,810,416,972,59,480,45,128,588,605,100,312,104,387,329,946,149,920,448,253,337,69,733,143,746,632,580,579,530,198,286,700,686,704,202,519,159,44,412,892,551,136,818,403,296,754,443,209,504,595,273,6,109,588,551,485,205,420,364,721,178,549,977,516,871,952,398,31,519,178,963,592,981,890,80,539,639,134,461,538,543,86,993,403,895,774,449,783,387,769,222,271,317,2,860,657,254,242,854,175,771,561,678,981,146,609,109,237,135,214,758,618,237,184,91,871,675,94,337,490,152,206,54,897,449,580,673,647,3,835,277,515,937,331,751,516,970,838,867,235,673,407,834,50,835,334,292,66,742,467,870,289,837,914,325,253,494,62,385,794,719,158,93,471,139,251,523,137,809,721,519,66,741,7,127,562,409,651,578,335,308,757,81,986,104,499,236,201,564,433,535,148,326,931,999,796,774,733,370,797,474,276,986,211,238,510,219,591,344,877,597,525,729,759,927,584,619,368,653,576,726,912,321,865,368,213,106,671,406,341,760,107,526,119,747,145,538,444,278,670,600,948,990,693,627", +"472,936,750,566,983,258,415,435,757,601,434,244,858,252,215,420,575,455,698,580,504,905,753,239,375,434,579,68,470,863,670,459,169,346,283,614,748,706,945,271,693,127,266,193,825,944,584,476,786,204,9,505,980,236,895,195,240,773,239,310,115,290,329,602,799,446,185,917,456,505,50,712,89,476,568,94,842,19,789,247,785,914,149,818,78,289,180,167,55,604,738,401,137,426,327,287,268,484,871,760,232,104,158,988,287,733,589,246,262,886,715,215,874,285,594,140,185,273,913,155,210,87,893,673,969,358,583,194,516,188,845,845,52,617,405,853,390,460,796,564,44,856,576,254,130,800,257,17,210,568,892,888,79,922,143,622,39,102,206,874,944,757,580,87,610,190,555,515,811,81,788,839,640,723,572,650,233,595,715,338,286,980,828,953,960,856,660,294,116,148,512,393,547,871,150,251,194,567,540,108,14,896,781,154,167,982,780,609,594,699,378,449,348,293,604,123,944,473,776,474,506,477,932,907,638,760,102,579,528,178,766,643,436,573,105,521,863,137,645,165,856,355,979,515,415,632,96,786,323,657,936,49,530,272,761,523,892,825,748,952,17,778,855,529,975,407,758,745,551,490,599,997,549,745,697,725,444,65,858,331,394,356,433,449,911,637,461,40,139,497,542,506,72,157,53,561,785,284,65,536,893,501,50,56,932,672,947,425,919,233,511,184,355,778,919,190,470,12,397,572,207,996,878,171,804,171,111,536,602,821,842,353,225,256,264,268,112,317,237,621,863,449,974,599,718,842,474,109,111,450,804,576,59,340,400,532,66,268,504,513,327,214,158,980,820,779,867,379,510,195,391,836,479,550,452,90,856,150,389,992,653,941,818,105,653,410,993,410,129,917,941,797,875,119,133,637,392,796,868,102,390,545,793,668,658,137,310,426,864,39,802,388,841,795,86,94,199,545,451,947,552,37,791,171,816,130,299,297,382,893,836,295,41,631,124,20,563,451,505,497,512,712,66,228,915,532,74,674,245,529,492,200,912,481,755,21,553,997,430,658,426,859,656,70,753,816,553,823,742,383,139,618,979,513,261,17,194,600,566,285,856,857,638,231,955,526,841,188,633,34,901,320,247,508,264,708,447,179,288,584,997,603,327,758,853,291,63,50,458,87,784,43,931,547,392,459,0,508,452,920,989,977,328,51,613,476,517,681,773,289,3,999,282,928,118,588,803,202,657,792,595,972,23,779,729,539,210,542,703,834,207,288,230,909,438,859,761,344,219,672,491,368,787,495,166,15,627,637,488,465,18,156,804,322,25,617,317,488,556,211,393,523,35,431,65,992,635,199,481,169,987,425,349,222,421,135,869,236,869,916,92,196,641,489,141,157,838,563,502,334,799,972,683,416,162,267,865,582,659,898,525,3,999,188,94,237,914,963,554,909,460,69,223,449,65,872,251,597,506,411,373,323,418,492,831,283,158,660,671,646,711,560,516,97,978,317,181,44,13,164,475,986,248,340,484,405,652,91,414,574,249,186,450,756,453,92,464,114,710,879,7,346,134,613,574,941,573,263,935,971,776,410,760,50,608,393,872,461,183,747,308,163,572,966,738,232,821,303,856,678,267,106,584,323,618,244,161,362,727,633,879,420,451,119,665,957,508,548,942,967,832,405,888,252,405,473,14,565,200,228,208,780,883,595,223,936,267,179,969,938,167,136,541,743,216,838,190,738,840,108,418,221,989,574,695,701,498,514,545,791,567,747,360,159,761,649,902,295,215,243,275,205,418,999,134,122,267,282,594,63,882,296,189,129,502,528,829,764,916,603,212,498,587,226,128,256,156,104,864,601,408,14,55,150,607,437,277,180,135,894,784,372,756,475,668,156,822,701,393,416,413,345,775,954,492,790,33,818,904,949,518,873,584,811,385,851,943,530,564,973,545,512,492,945,847,764,671,609,559,77,876,950,976,294,586,899,125,950,205,783,625,329,89,266,123,668,512,72,349,613,910,507,970,29,819,873,794,56,274,9,47,800,770,965,113,6,333,255,380,795,547,634,296,94,44,612,347,111,572,86,525,647,606,557,605,584,104,276,104,675,706,977,357,112,467,504,903,370,493,677,369,458,186,627,561,146,115,77,584,8,165,900,63,903,622,585,443,358,976,438,561,179,839,39,200,790,767,688,618,673,568,455,605,924,168,995,646,882,304,449,282,291,759,206,536,248,561,389,706,77,482,232,995,591,596,310,228,334,756,987,124,696,855,953,561,952,992,430,535,587", +"206,719,458,20,327,574,329,325,863,453,451,613,964,403,832,879,97,116,824,747,928,322,938,303,222,707,611,859,248,136,239,682,773,962,78,652,374,265,291,578,114,643,626,751,458,617,154,326,49,151,561,811,510,939,647,139,442,582,70,494,811,267,770,624,618,579,407,634,893,985,216,40,151,574,698,385,881,700,682,364,269,264,241,458,138,924,382,639,461,417,354,158,533,747,421,245,786,450,813,171,815,882,844,28,515,435,4,926,413,267,151,886,777,756,11,487,994,48,73,906,823,872,844,506,588,855,647,912,611,44,605,995,162,752,989,183,235,736,439,715,580,670,214,408,842,354,10,598,537,895,686,145,295,709,376,846,799,854,505,194,142,605,665,674,505,199,132,891,458,656,756,991,718,240,409,136,562,432,537,751,650,760,694,399,579,773,710,534,88,986,511,642,306,465,973,629,836,903,368,813,952,168,446,767,693,397,714,433,946,117,876,746,724,408,521,708,879,375,89,457,945,294,415,880,696,89,287,179,568,792,97,505,317,296,428,866,87,943,738,616,362,662,262,619,269,98,871,390,983,883,590,519,328,300,335,915,385,226,39,905,690,796,715,627,93,381,982,482,451,355,468,71,790,87,792,465,716,978,114,324,921,62,221,985,363,590,383,812,833,910,345,985,173,97,259,977,485,787,641,623,293,292,688,812,548,523,773,239,776,388,650,852,819,996,506,441,270,887,185,305,731,540,886,428,92,572,193,70,241,10,823,7,887,439,178,275,347,621,297,114,941,736,585,26,257,231,175,973,360,961,738,41,347,651,587,988,356,590,206,291,641,138,485,165,53,235,592,735,588,911,212,578,518,535,481,247,396,455,703,224,376,789,458,61,243,205,249,503,537,611,67,527,59,302,747,626,487,604,29,516,196,840,440,647,294,854,122,877,536,435,249,132,429,858,129,767,348,82,355,619,543,424,348,416,56,719,854,368,212,850,706,185,889,346,602,650,670,113,401,894,708,112,72,149,774,132,363,450,314,91,193,902,469,492,365,612,780,512,400,376,835,205,840,364,427,482,251,511,748,136,763,927,541,159,225,366,956,522,192,962,64,401,615,79,393,716,689,929,550,662,178,771,18,207,755,111,480,549,865,724,747,355,45,673,889,591,342,692,851,484,998,983,420,836,947,523,508,0,421,953,495,566,535,433,459,33,669,108,501,144,220,470,345,608,67,996,958,526,109,47,787,787,316,373,232,323,463,916,998,275,923,509,532,87,653,513,94,664,304,844,832,767,673,897,104,425,496,516,392,948,366,293,264,799,716,691,756,579,564,433,724,545,491,364,308,309,593,936,802,631,636,805,8,287,708,374,658,351,480,413,14,829,439,341,570,736,183,756,925,863,34,332,690,482,529,645,60,320,955,291,421,790,789,426,852,583,633,526,887,388,509,531,746,494,962,590,795,178,744,364,131,759,306,373,832,911,977,690,456,588,313,789,638,180,967,574,575,669,380,28,663,864,932,315,184,146,677,425,501,793,200,263,751,487,249,634,930,471,651,180,763,337,544,762,406,420,201,507,303,935,781,783,427,183,791,902,590,205,129,16,71,897,50,353,246,639,964,60,872,77,563,831,980,629,65,884,88,218,448,147,803,368,627,649,654,351,294,491,579,655,614,864,538,406,27,499,604,757,549,501,362,689,180,56,203,623,796,949,310,667,903,619,24,344,341,856,215,613,555,293,370,943,103,975,448,641,434,339,625,954,226,11,134,795,827,338,558,511,473,266,75,18,498,168,238,757,864,464,182,245,46,9,959,323,476,408,458,205,591,82,378,102,715,648,587,892,235,902,895,183,811,62,581,557,928,382,563,395,703,256,329,724,883,258,894,228,453,581,513,575,69,155,860,105,24,547,416,742,666,496,945,137,177,211,120,764,328,675,35,82,844,40,417,266,128,393,180,161,211,833,115,705,95,35,241,243,441,262,686,178,252,708,356,5,252,801,174,968,459,85,716,733,630,414,452,804,529,106,834,54,964,830,401,410,351,446,539,5,918,543,81,723,803,894,495,928,760,262,712,483,681,333,138,459,468,569,871,347,519,93,195,283,941,146,186,313,727,973,665,923,121,93,84,284,834,906,107,860,710,654,982,635,820,10,473,419,891,203,364,911,901,957,485,14,35,525,458,346,897,97,538,621,598,898,175,104,267,787,76,614,421,13,343,655,965,78,408,136,967,714,503,938,232,132,417,187,3,499,330,176,112,528,993,836,445,854,302,253,990,622", +"942,10,445,547,45,425,592,501,604,834,809,746,379,367,968,746,725,189,266,412,192,499,450,396,36,247,200,39,628,680,294,767,477,602,575,291,217,988,31,863,205,329,12,506,281,935,729,962,838,209,88,515,641,643,325,115,778,103,339,617,962,451,377,929,955,626,260,843,926,938,395,812,805,314,719,601,451,626,732,991,613,221,215,415,676,115,40,817,798,615,6,601,426,935,771,252,499,259,302,428,463,302,772,996,986,755,358,686,860,675,437,850,144,20,862,742,356,313,16,238,578,101,32,351,678,765,44,135,758,49,513,727,846,223,659,21,137,219,297,459,159,129,501,441,561,703,788,658,604,407,968,270,502,588,727,493,985,631,587,402,329,20,38,290,733,919,792,747,152,938,586,158,630,350,92,123,955,408,445,289,691,304,139,305,239,609,866,567,868,491,844,486,870,874,39,208,730,371,449,259,788,212,828,437,981,519,502,287,528,430,588,479,31,86,158,456,78,162,733,998,61,78,243,634,564,530,815,700,771,314,806,399,229,92,308,549,651,632,190,537,425,538,781,549,346,259,10,293,918,254,492,976,802,947,219,414,883,156,264,103,702,280,744,680,704,531,272,762,319,450,398,722,174,628,738,199,719,755,330,258,297,825,545,483,848,584,777,424,89,835,427,919,131,902,734,958,556,423,335,614,63,37,481,966,442,252,474,30,755,373,344,767,540,360,865,357,710,876,768,326,17,662,916,918,904,826,372,694,295,599,660,22,83,258,886,311,60,179,723,283,712,794,321,40,300,11,721,194,935,803,393,207,928,659,502,809,251,48,223,466,737,15,400,567,942,49,423,347,876,82,402,196,528,872,19,181,682,198,518,847,963,405,968,617,901,792,457,140,830,518,450,453,306,723,964,137,94,454,77,41,590,351,494,594,817,965,737,403,309,281,477,543,662,499,864,798,958,652,820,728,285,673,183,683,372,813,79,416,352,22,235,168,6,952,665,418,364,766,469,807,463,621,711,584,425,9,428,915,913,567,834,553,92,26,616,790,856,832,690,154,580,197,369,175,682,494,370,610,377,828,350,161,68,113,484,847,864,929,429,843,788,784,135,987,449,767,291,933,548,491,715,947,539,88,610,889,686,346,728,319,616,633,759,604,6,127,875,215,336,251,421,117,17,702,883,824,452,421,0,880,450,309,323,977,204,65,562,262,574,288,661,576,640,884,558,476,678,348,359,99,6,609,403,962,561,303,438,254,193,513,340,757,837,61,919,248,781,668,284,625,592,585,164,295,508,198,567,824,298,902,535,325,373,788,928,971,569,174,17,91,434,171,326,817,427,893,438,251,32,388,368,782,486,861,592,499,820,238,814,620,255,26,480,775,778,501,775,252,495,528,50,984,373,876,666,200,492,100,55,958,980,453,580,200,953,5,509,772,237,607,753,525,476,9,220,157,537,694,802,110,43,375,376,807,656,310,925,921,280,603,340,280,909,831,34,363,624,504,374,772,213,469,645,854,478,56,507,230,157,5,111,63,364,733,368,379,319,939,16,674,364,238,209,150,425,625,633,28,525,791,644,957,325,83,912,203,590,705,24,217,294,228,464,442,415,562,62,892,628,747,287,529,980,632,299,236,487,350,827,233,629,91,632,718,351,876,451,390,319,253,944,166,639,512,181,840,524,122,481,76,319,727,649,447,673,287,447,417,119,417,154,402,576,872,902,206,765,615,50,218,285,174,751,139,108,303,91,461,53,37,80,284,400,852,241,150,500,200,92,783,173,184,212,367,932,155,872,479,140,26,807,786,164,44,288,819,888,584,298,185,303,685,57,559,524,209,953,300,412,436,621,704,268,58,890,86,885,9,32,476,471,240,75,56,94,546,278,89,829,177,627,957,852,150,294,400,773,516,767,562,332,264,420,544,249,73,817,674,572,20,339,143,473,595,515,500,226,743,480,391,940,342,15,152,951,592,228,291,380,705,9,280,492,29,502,368,665,421,738,105,915,734,240,877,109,64,446,639,558,905,703,901,179,746,493,479,110,844,894,129,955,709,92,578,919,206,81,909,734,43,606,710,908,850,737,859,207,169,611,685,602,204,390,819,820,66,286,535,331,474,386,728,425,932,784,628,228,378,93,990,740,549,374,683,646,112,588,260,455,373,698,931,353,336,446,500,908,778,406,535,692,740,619,437,367,918,358,812,924,881,6,788,844,534,193,445,201,485,729,562,883,410,801,194,146,217,550,215,569,446,222,241,768,599,983,573,571,50,568,542", +"166,736,665,237,527,63,628,301,762,216,35,887,2,968,425,517,257,281,659,426,597,583,856,792,247,326,450,41,239,592,195,144,244,177,290,583,260,788,781,40,284,791,600,427,507,448,142,298,352,972,976,656,904,412,832,971,849,512,230,837,375,530,986,866,437,871,315,668,778,426,78,900,888,880,828,540,937,350,431,301,434,141,153,340,842,503,758,136,103,758,42,860,57,822,399,88,312,66,584,575,493,743,415,2,538,533,319,318,497,500,94,870,625,245,440,523,333,969,114,589,636,344,464,565,675,867,160,104,604,205,915,48,71,979,469,841,921,219,714,130,670,862,984,869,267,768,985,909,306,650,716,217,811,65,300,640,234,33,120,502,170,951,494,828,736,801,302,922,156,926,58,504,81,739,123,660,466,511,31,406,145,748,414,937,709,181,756,547,324,678,123,830,539,94,491,59,514,409,940,860,360,450,434,19,929,601,383,812,164,937,783,582,850,923,178,656,994,983,232,450,428,791,522,196,122,38,529,761,342,122,914,104,490,626,554,53,939,630,159,46,700,655,777,369,743,52,21,374,981,176,943,148,131,835,587,894,300,228,443,707,976,88,453,34,476,188,134,656,420,238,22,132,70,636,54,351,462,417,764,89,167,250,496,74,540,232,612,361,22,712,803,751,954,818,411,887,98,120,664,133,480,147,373,583,569,295,841,160,877,102,914,657,121,993,344,938,322,988,294,934,516,801,633,190,14,608,76,469,670,971,344,833,668,797,728,797,395,236,264,646,433,39,351,609,839,237,150,368,737,520,365,447,468,431,678,326,167,246,354,818,239,199,91,86,346,940,275,664,700,451,259,307,56,536,674,52,91,143,356,79,342,609,379,308,609,511,557,929,862,156,720,991,315,87,807,328,907,36,585,495,318,401,19,249,646,624,138,626,848,984,78,180,185,709,36,443,500,412,288,396,682,413,947,689,292,892,89,924,446,941,517,615,711,920,50,894,661,906,441,301,400,286,137,361,415,226,990,111,807,218,425,969,996,120,2,945,1000,794,374,848,710,749,618,373,728,607,202,673,93,678,612,391,94,626,324,830,407,454,187,232,227,367,758,968,59,499,81,574,179,934,890,694,885,150,697,241,479,824,23,533,91,2,304,412,50,499,876,115,522,607,639,832,439,954,662,431,920,953,880,0,920,96,520,32,281,254,504,8,917,297,712,258,686,922,192,734,43,229,570,935,949,209,167,277,150,856,986,720,788,244,466,679,209,567,860,642,3,586,813,773,92,445,758,867,792,998,242,674,115,729,489,21,948,371,21,158,328,462,364,604,858,532,430,539,554,604,924,159,292,720,577,941,173,767,47,414,445,705,647,465,301,283,969,724,742,99,462,821,794,338,20,601,762,221,70,726,106,917,307,973,608,218,119,357,450,828,673,7,5,935,853,956,38,572,665,35,968,123,823,953,78,370,675,325,650,421,444,393,867,506,956,700,105,461,168,765,800,993,148,57,455,195,957,378,819,48,716,902,690,993,682,18,129,679,701,191,792,706,114,939,404,589,693,816,153,418,889,230,237,620,413,19,580,713,785,970,851,939,129,36,392,393,635,127,421,882,337,683,477,978,344,300,778,348,583,642,970,640,873,287,992,962,218,610,183,546,298,846,609,361,445,988,823,816,340,721,477,690,217,623,169,341,541,142,33,375,847,517,243,802,20,500,436,47,935,833,136,183,892,962,224,917,410,437,20,920,163,304,882,286,28,174,386,662,715,380,948,340,802,606,435,459,719,428,120,270,30,271,253,848,795,950,457,54,647,833,593,367,607,532,440,988,661,362,730,487,341,115,100,971,840,159,322,729,319,924,369,453,986,753,22,346,909,59,944,218,403,178,188,286,131,707,985,490,120,938,257,748,165,936,542,629,913,842,734,268,663,285,298,145,360,494,542,540,173,359,927,171,331,631,944,616,323,328,461,209,82,139,392,305,997,395,164,269,650,298,555,473,832,674,634,231,881,724,18,581,883,240,620,981,109,451,348,426,964,207,186,29,350,884,437,131,272,568,812,685,112,518,909,962,356,581,796,951,861,465,342,751,862,741,879,952,861,291,550,156,461,397,54,734,57,229,448,857,653,134,436,892,295,201,378,813,731,494,981,463,321,152,64,330,768,976,722,417,176,646,590,857,18,237,422,90,122,72,763,595,122,854,842,418,106,979,419,807,755,228,569,530,568,128,219,161,188,390,486,380,560,146,297,827,533,713,701,393,358,845,697,752,170,910", +"38,641,420,307,311,396,305,586,915,490,439,759,471,97,507,86,6,989,752,127,886,61,33,523,612,772,144,348,133,292,410,217,476,814,47,792,343,791,322,135,300,743,644,255,207,263,987,177,257,687,244,600,256,148,432,58,865,145,933,986,113,589,39,300,382,787,723,122,559,311,568,78,163,753,977,893,410,372,948,677,161,259,412,793,522,678,571,734,916,871,882,116,357,431,604,360,95,561,317,605,954,622,314,167,995,283,320,42,690,71,230,975,19,116,269,774,405,845,538,503,247,38,105,6,95,909,165,662,836,113,4,498,152,953,760,608,532,576,730,584,253,990,117,371,592,569,774,884,229,406,766,381,739,408,311,862,416,500,136,711,578,771,711,643,379,16,449,297,411,635,773,861,798,654,737,848,372,256,350,297,455,364,327,919,515,948,52,817,520,182,501,316,289,856,284,35,915,85,187,546,105,91,866,917,341,669,191,563,919,210,303,951,8,938,127,803,610,152,280,429,442,153,40,277,584,274,658,105,844,722,685,737,518,143,148,662,93,909,647,195,576,109,246,746,785,48,214,61,356,798,676,667,307,820,708,939,347,451,972,584,698,497,338,15,342,504,602,93,874,337,400,653,169,69,960,594,261,31,78,388,948,163,303,746,746,725,470,420,754,953,724,181,308,752,575,858,203,884,216,826,373,719,343,839,114,9,997,215,336,690,254,515,862,606,711,834,269,734,492,579,773,592,810,640,527,167,138,47,525,964,558,963,543,835,472,316,9,155,565,483,22,574,328,364,513,864,884,98,489,620,889,441,262,90,420,187,446,436,570,703,28,183,697,283,897,461,249,210,511,87,705,832,18,209,894,489,685,909,678,85,423,549,455,745,134,608,29,626,669,614,226,854,685,71,982,120,520,946,234,356,410,820,775,298,369,736,512,791,153,72,621,547,237,224,220,829,231,935,303,273,813,960,715,952,56,440,410,580,874,563,514,66,248,643,11,81,820,877,199,538,703,423,951,268,47,460,65,682,771,583,677,253,771,140,717,105,690,408,367,531,528,301,175,881,349,691,928,97,796,708,136,352,281,324,39,807,973,514,768,493,679,471,383,426,345,56,142,107,402,978,354,162,888,745,974,493,730,137,856,648,615,169,640,642,407,490,716,856,435,826,760,629,709,90,738,168,989,495,450,920,0,158,432,394,651,106,536,328,164,651,539,939,386,683,445,41,796,461,562,956,864,270,747,315,505,75,302,691,92,760,721,102,485,226,266,540,876,792,531,396,827,588,535,610,884,722,752,690,115,488,444,410,650,264,821,423,5,782,310,197,677,808,465,389,352,858,791,594,976,675,170,545,518,918,556,937,194,285,553,700,435,460,914,252,76,174,898,658,864,94,443,422,917,651,347,902,78,744,996,385,934,9,305,571,921,826,986,967,566,454,54,26,220,891,681,770,812,877,348,906,159,58,775,836,353,520,122,17,707,324,481,189,243,13,913,103,104,718,193,886,958,508,375,418,280,542,996,222,535,423,7,317,337,175,707,534,958,970,454,932,942,715,768,863,996,753,249,386,845,534,277,281,1000,832,486,551,579,575,312,530,762,719,871,120,305,965,874,153,368,801,155,366,385,731,967,386,260,647,578,701,519,274,39,864,829,544,447,517,550,524,574,800,685,505,217,57,107,329,159,867,429,213,912,200,790,583,971,15,765,259,773,195,13,89,229,203,163,914,645,189,734,379,106,455,142,521,852,311,311,881,802,333,672,976,470,211,874,281,877,115,387,108,186,406,460,410,56,704,401,817,376,175,133,548,539,808,428,767,925,334,741,517,90,292,623,719,208,395,202,600,827,958,505,952,314,192,977,525,481,106,700,842,565,219,153,85,585,413,870,593,505,329,138,132,892,263,215,660,128,898,928,600,669,144,102,463,175,113,316,486,586,140,254,433,402,156,59,573,539,681,288,341,391,156,863,774,563,490,855,524,599,941,776,526,563,58,414,213,882,424,896,199,584,565,402,713,655,556,986,385,776,337,929,972,42,174,552,359,688,314,29,959,509,993,279,937,750,544,480,995,911,757,561,992,817,409,76,533,150,895,958,93,737,346,358,925,375,786,655,558,882,528,212,588,110,634,640,568,939,579,470,352,890,546,900,960,877,267,381,986,578,149,833,874,163,354,653,870,391,359,127,849,329,410,106,453,461,35,762,116,479,192,683,871,632,437,610,315,164,58,428,96,430,691,11,466,355,568,938,190,231,646,943,609,597,102,732,527,78,23", +"203,227,613,430,248,478,919,186,527,821,684,772,786,18,900,426,150,455,313,725,251,578,118,842,77,49,762,971,729,232,105,440,961,935,287,61,198,149,598,222,401,749,441,792,610,935,601,935,148,246,278,876,247,508,886,481,374,371,450,914,456,753,385,426,233,862,871,759,181,579,348,381,906,264,443,811,442,595,379,258,395,952,861,432,960,913,832,355,989,622,706,795,434,658,265,636,144,730,635,148,485,255,391,346,127,592,651,900,803,616,401,670,669,247,971,350,963,928,450,471,123,346,257,566,289,557,542,613,811,266,308,609,375,952,273,445,740,70,910,645,551,125,673,60,487,636,888,10,598,371,156,247,552,30,457,491,908,738,986,663,316,558,382,41,91,158,45,356,863,575,843,419,39,285,930,470,817,446,792,53,394,541,770,132,198,895,969,21,614,250,778,85,812,907,741,670,278,382,523,753,803,547,474,534,301,980,502,643,381,542,65,723,904,58,126,906,806,415,711,343,524,985,216,477,336,134,509,147,588,230,777,326,881,900,345,506,51,757,116,466,822,80,876,476,911,875,868,51,938,414,891,731,760,523,639,672,711,409,679,949,711,990,680,745,928,348,742,297,236,891,101,260,481,3,645,777,57,870,152,522,415,894,335,673,227,965,54,990,832,414,369,579,514,107,140,368,817,527,406,410,935,46,675,401,708,313,894,704,309,826,577,745,279,191,106,212,758,975,320,902,475,975,723,470,920,144,847,834,919,552,4,744,576,871,636,502,791,68,990,389,485,934,349,91,386,567,431,139,529,754,750,93,7,71,664,787,966,972,914,152,981,475,71,429,721,814,676,767,420,215,74,339,182,187,403,811,837,200,93,824,533,585,29,218,97,564,800,73,397,458,370,844,329,52,423,527,934,859,297,545,224,453,509,720,897,73,886,825,731,399,921,825,650,853,764,706,691,518,225,211,99,853,319,252,491,967,398,45,429,432,67,910,81,221,698,39,564,449,553,51,100,702,920,201,68,233,832,763,922,794,594,813,716,501,424,719,104,594,615,970,448,371,899,588,331,141,801,456,889,568,597,609,838,837,560,121,696,235,488,975,516,40,392,954,400,18,76,835,680,790,46,975,760,337,523,231,159,426,139,597,697,724,734,527,553,564,263,194,361,268,589,252,538,892,790,46,977,566,309,96,158,0,637,802,438,326,570,719,887,277,94,40,475,519,476,597,183,25,91,854,984,291,580,561,323,680,106,929,246,312,212,772,79,150,800,141,929,925,924,433,704,887,639,254,426,499,103,970,462,132,133,199,212,998,871,121,587,796,104,316,506,291,944,310,667,527,773,227,709,165,798,186,145,448,566,304,377,354,935,944,369,249,818,154,191,660,539,55,509,263,761,190,220,647,676,381,588,699,61,878,890,266,390,931,927,321,65,269,738,601,929,827,132,326,363,760,762,886,322,22,321,479,472,136,336,303,193,750,921,982,11,938,31,690,477,679,70,160,170,718,70,798,3,30,635,894,733,427,755,899,454,866,342,102,466,18,96,993,35,729,209,958,837,142,962,279,855,140,301,274,38,587,641,93,57,29,52,93,829,874,547,888,934,609,99,207,866,577,242,444,171,152,250,413,822,522,87,970,518,434,704,20,326,729,299,890,99,720,725,133,928,73,704,594,22,600,305,71,925,751,365,481,447,772,47,519,639,231,292,268,484,920,283,441,703,730,96,983,318,833,76,856,671,854,233,719,574,90,188,797,332,699,378,140,848,33,71,312,13,830,351,797,772,964,922,25,995,175,389,42,235,774,611,757,853,689,915,97,356,291,412,848,244,220,485,806,919,861,535,339,969,370,15,932,519,300,656,984,88,499,873,977,271,440,612,186,326,885,393,330,306,323,100,967,701,113,28,609,574,696,374,214,42,407,141,6,946,229,870,778,965,64,774,3,804,767,95,267,411,126,1,934,762,848,649,127,350,502,558,376,310,27,718,766,677,41,723,736,890,681,160,810,672,920,283,242,524,664,789,346,810,726,355,624,111,420,395,19,979,859,316,221,585,521,742,866,708,168,339,174,579,284,144,241,702,606,386,294,913,289,921,352,991,163,756,921,26,246,658,219,823,263,252,679,693,768,133,541,326,750,26,545,807,993,959,489,554,783,407,885,46,402,988,544,405,576,521,728,854,954,868,667,68,309,574,574,804,741,97,931,551,636,432,368,895,696,731,331,138,636,204,951,419,97,265,281,339,886,23,13,696,231,171,448,191,38,637,946,564,487", +"953,538,596,331,973,171,521,747,478,323,251,712,759,933,227,169,771,791,159,339,211,979,398,385,461,679,238,251,281,65,784,397,866,621,829,960,768,613,146,962,72,417,198,283,504,77,281,537,887,262,45,112,831,200,693,920,102,594,142,282,634,613,320,638,9,625,108,449,646,683,565,726,436,251,804,392,230,753,501,263,294,597,94,335,941,171,766,34,420,898,2,508,697,75,328,769,125,395,358,597,775,556,987,575,754,764,698,875,672,292,722,607,429,88,150,192,960,169,434,493,213,98,192,142,866,115,54,935,601,957,916,365,903,25,845,162,360,113,743,563,986,679,807,144,237,946,576,981,385,105,355,844,281,581,64,579,512,460,587,690,990,761,172,658,290,689,150,1000,12,539,339,198,80,661,84,661,9,469,377,281,40,581,120,379,947,251,763,523,812,815,789,57,709,133,749,798,972,701,612,144,897,776,72,74,377,55,657,301,732,169,52,621,246,403,907,765,844,870,664,917,203,734,990,177,614,275,513,668,818,108,452,102,640,339,784,386,375,809,787,243,219,641,56,332,243,838,240,450,498,449,842,125,933,649,459,49,157,356,788,15,889,97,171,601,878,119,367,959,99,236,907,681,390,392,880,376,779,240,308,567,806,54,456,737,957,119,338,698,560,992,100,831,716,529,870,729,24,583,645,69,438,453,705,337,204,418,114,160,568,840,590,871,777,666,841,714,169,29,997,722,854,137,847,811,413,473,443,284,58,676,172,753,197,114,176,927,939,917,914,288,809,982,166,724,846,600,398,244,403,232,268,964,428,81,243,649,128,530,657,56,504,107,348,258,415,40,458,848,446,793,202,706,664,705,316,337,47,335,615,775,948,706,440,212,61,536,416,282,335,883,851,299,936,814,855,439,677,850,974,529,970,587,854,186,698,110,120,629,535,769,635,12,723,142,598,62,759,406,853,368,173,848,853,16,449,596,28,786,413,327,243,640,548,46,874,349,131,8,659,884,936,210,30,541,485,287,291,458,533,341,630,210,509,744,922,936,164,970,730,713,93,547,669,358,249,893,337,161,31,383,14,646,98,766,415,809,599,344,677,891,882,636,211,554,684,77,60,871,158,361,691,578,924,796,798,705,664,956,90,815,353,14,63,75,661,376,589,574,605,82,68,582,586,123,663,883,328,535,323,520,432,637,0,220,942,387,247,148,227,228,650,470,313,414,770,309,921,340,888,957,696,644,947,254,193,300,285,740,277,7,229,711,199,265,584,795,868,179,116,663,886,553,979,951,552,222,442,889,699,761,993,501,20,467,410,787,639,151,654,596,45,217,736,50,608,436,243,19,780,710,454,57,784,169,617,769,286,260,924,368,185,243,428,982,362,537,808,719,98,76,539,406,237,905,934,287,467,205,561,154,209,33,891,846,588,360,136,877,373,302,300,650,526,341,83,954,803,599,904,933,788,372,791,892,819,153,974,157,12,598,930,758,442,803,330,305,808,265,890,56,131,219,597,107,311,410,496,790,7,44,426,813,666,52,654,431,569,931,452,809,998,113,572,853,96,355,824,709,445,603,534,284,627,527,693,619,801,949,577,660,102,918,83,537,981,850,211,103,488,404,14,309,37,704,643,132,575,63,286,8,132,570,885,159,81,330,70,296,435,379,25,210,950,430,481,47,711,381,416,864,795,650,439,864,353,981,348,498,31,151,718,570,640,85,728,800,801,943,812,828,946,636,473,704,987,436,739,896,357,180,824,709,505,42,791,831,120,773,862,64,919,735,753,97,33,183,913,409,754,901,542,767,791,291,747,784,976,434,226,310,487,627,652,984,306,269,412,235,374,651,715,537,991,536,41,886,243,25,308,162,798,5,585,216,345,78,823,462,266,568,743,935,705,235,412,370,146,596,755,518,517,722,31,446,999,479,166,524,124,970,985,811,200,951,898,632,751,921,977,38,915,5,680,928,48,69,688,59,85,139,80,455,500,19,868,738,629,731,981,682,369,191,237,769,26,601,718,381,918,608,986,566,396,706,545,339,29,450,82,718,683,226,614,311,239,598,719,165,312,632,487,454,2,486,406,635,323,920,961,257,177,258,297,42,815,332,795,905,102,239,911,391,904,687,367,627,210,424,944,989,556,590,812,777,515,763,945,363,341,365,687,847,471,755,635,722,585,247,890,728,611,271,975,53,717,936,169,817,336,881,254,86,215,208,962,234,85,237,828,788,350,36,522,689,687,396,357,193,604,856,830,213,934,208,543,772,197,175,941,766", +"201,609,755,176,862,348,285,745,960,760,242,463,810,516,126,861,923,37,505,922,101,660,228,418,459,785,125,57,530,788,402,185,768,123,332,102,905,690,748,807,222,609,37,414,120,915,54,909,105,29,993,730,645,930,857,980,205,129,788,679,320,497,162,415,679,162,593,271,446,710,280,125,112,692,482,627,483,213,991,906,625,658,372,801,73,488,567,736,926,278,393,337,95,236,856,498,636,152,211,123,102,215,477,469,110,384,88,748,677,347,914,882,900,312,439,182,489,330,806,392,911,589,137,972,686,730,138,793,728,63,787,615,166,435,601,419,713,88,39,746,572,113,783,962,493,402,760,159,635,848,477,176,338,864,618,327,447,752,18,68,624,106,481,105,877,337,577,230,870,546,100,427,453,204,753,323,751,573,110,185,183,445,282,890,218,33,694,391,352,72,576,232,918,492,536,930,733,331,401,227,463,977,690,75,445,403,338,585,983,654,644,419,620,929,379,633,575,484,509,95,888,200,259,670,186,505,237,22,151,891,559,134,289,742,466,846,589,265,862,707,387,112,142,759,784,267,808,668,89,989,955,801,689,766,921,693,602,862,794,179,407,670,102,901,393,394,545,658,412,309,650,256,56,296,399,265,194,297,218,864,530,939,681,539,707,150,318,620,910,280,875,613,314,713,59,964,865,207,312,864,864,714,453,468,526,273,875,825,575,801,89,786,619,376,181,227,840,554,297,721,259,404,75,279,676,352,884,114,135,84,339,11,563,6,532,789,627,61,809,972,888,532,231,70,350,553,859,825,840,505,444,409,426,752,127,50,265,510,213,174,434,12,287,290,444,804,426,226,447,970,948,77,363,203,415,185,503,151,576,392,139,213,274,514,906,130,612,528,374,31,736,228,844,819,72,363,637,599,659,775,541,499,442,6,442,656,285,425,125,83,216,999,641,976,658,22,467,922,200,850,809,597,321,628,124,414,844,629,779,643,760,796,54,924,815,744,255,200,40,626,215,182,261,841,397,925,372,319,257,12,166,519,893,843,876,82,930,271,68,636,10,904,274,122,205,11,875,149,107,199,746,409,500,111,280,268,115,369,580,193,719,203,284,332,745,659,602,960,640,650,173,837,895,105,172,896,597,37,6,672,994,751,712,683,860,668,396,331,128,654,401,880,284,667,556,294,51,433,977,32,394,802,220,0,204,366,167,466,707,469,335,936,752,224,137,430,835,989,321,268,920,691,595,89,710,377,635,714,686,965,928,585,682,573,714,455,602,767,227,971,740,425,352,559,565,974,986,247,242,564,789,543,403,471,603,293,475,311,691,843,226,81,846,122,452,396,138,606,647,480,383,433,802,498,822,322,230,682,599,134,44,828,482,612,971,883,359,477,29,103,430,775,765,879,158,604,438,752,57,597,185,350,571,636,840,393,63,234,491,31,989,922,361,544,224,8,274,67,444,302,23,941,522,800,432,957,192,371,108,247,586,872,766,140,263,158,362,633,347,224,5,855,421,235,947,509,873,749,131,54,523,333,305,866,361,557,975,896,88,964,722,808,959,230,86,562,414,465,901,750,342,383,418,706,536,586,355,430,524,272,884,952,524,704,508,186,654,564,332,640,354,246,317,583,714,28,43,343,562,84,757,664,36,347,265,552,772,697,344,738,920,494,454,33,991,295,986,157,645,716,873,889,164,34,364,577,923,195,126,511,273,630,974,61,493,997,390,749,448,159,216,569,802,81,748,859,395,694,247,224,273,577,581,535,620,683,442,422,190,659,766,736,448,794,16,287,123,845,44,401,516,383,912,341,525,471,975,854,188,876,858,172,597,425,76,970,344,918,327,763,277,501,730,968,468,895,10,796,31,880,644,320,916,853,275,135,79,854,586,244,281,599,292,822,681,901,972,272,590,729,154,593,501,477,650,198,839,238,768,107,569,775,164,929,844,494,987,558,672,751,85,614,619,478,615,456,228,144,159,63,822,38,48,253,541,446,632,594,152,462,41,896,781,318,369,620,978,748,457,846,736,752,112,209,392,546,574,297,405,463,407,316,760,999,697,242,632,530,826,787,669,659,905,57,696,119,138,701,549,10,812,595,211,273,440,16,381,135,99,388,612,83,298,50,517,623,447,865,330,38,747,573,283,158,141,208,521,849,895,140,936,866,361,560,284,212,897,413,767,848,986,168,818,944,757,971,751,82,168,121,760,5,40,168,820,870,52,719,596,234,226,439,907,903,363,56,777,674,963,996,959,269,913,659,163,912,514,957,278,340", +"566,954,870,121,683,37,545,731,288,607,84,781,104,203,9,106,602,968,545,900,277,28,348,317,911,893,861,109,143,146,149,581,510,735,559,516,960,224,585,500,357,59,268,319,975,74,42,928,10,737,939,11,966,365,192,231,177,446,937,391,119,631,695,379,129,54,290,531,309,198,965,633,760,62,209,566,589,962,677,718,519,29,111,204,162,992,754,380,999,303,348,308,859,122,706,253,695,493,641,218,575,108,240,688,561,227,335,23,343,790,671,153,328,181,6,728,1,990,503,482,629,34,471,640,193,559,950,21,954,32,246,327,684,464,268,538,963,527,447,645,666,468,540,292,383,369,675,883,672,759,740,323,664,721,899,340,866,921,189,200,212,124,406,689,151,788,869,319,507,807,248,359,334,216,108,148,432,157,891,544,544,339,80,720,447,541,511,672,777,218,937,831,591,20,142,857,347,504,498,610,470,543,8,434,403,333,931,102,343,796,250,320,408,900,384,231,777,486,273,960,949,405,54,218,75,123,169,162,455,267,370,323,21,617,729,585,58,812,420,104,576,974,540,243,656,632,26,484,891,370,713,361,497,644,776,223,745,711,227,123,523,306,600,826,450,998,306,829,124,573,155,408,31,758,210,991,142,776,729,592,447,129,745,550,25,186,818,404,19,111,776,74,264,774,391,531,60,783,991,592,849,798,86,482,15,891,413,686,574,438,408,918,303,729,800,851,561,49,165,136,214,354,216,316,855,426,284,505,920,551,147,886,94,703,576,442,982,379,946,14,230,571,388,104,977,970,152,324,292,859,909,105,721,262,984,296,285,370,149,367,732,284,421,476,804,713,146,223,538,673,279,594,245,386,738,705,914,328,473,927,497,369,725,8,681,73,571,64,923,195,389,628,694,550,115,288,489,522,874,815,589,21,874,639,74,604,926,457,514,934,372,622,62,477,202,146,142,863,583,177,323,268,822,95,127,209,109,335,893,488,170,83,999,837,258,773,770,848,825,566,55,110,17,123,356,762,902,864,674,392,679,361,115,900,684,166,171,124,740,340,644,880,113,937,335,440,454,76,487,662,22,216,60,797,872,629,297,678,588,268,554,369,696,996,660,168,86,745,967,270,840,727,783,623,992,85,789,357,842,404,459,257,456,215,561,871,428,693,145,355,27,619,529,408,119,577,613,459,204,281,651,438,942,204,0,654,26,740,850,328,326,957,693,878,912,875,33,643,44,965,834,126,117,345,241,954,873,422,93,859,712,290,994,694,231,246,797,489,880,17,151,501,568,673,866,634,3,530,415,93,816,278,690,212,743,365,136,547,279,503,744,248,120,902,492,973,517,200,438,277,939,663,270,787,141,214,474,798,777,903,758,567,501,210,781,378,857,571,845,533,25,372,866,186,404,202,576,191,717,527,776,516,330,975,715,591,921,455,590,413,126,230,572,122,847,591,57,516,310,423,604,470,279,585,785,652,876,583,360,571,562,844,672,171,548,811,65,952,234,388,672,951,554,618,19,154,875,987,917,302,314,79,412,923,92,516,145,666,242,659,877,692,341,740,118,490,23,852,367,564,332,165,306,240,543,750,444,236,922,514,670,956,385,527,281,140,13,491,447,474,743,827,617,962,470,42,557,637,342,34,114,265,544,947,117,852,335,27,826,5,203,319,938,779,479,346,985,241,581,248,55,100,377,474,157,873,812,242,66,127,389,499,452,527,474,99,836,643,747,874,605,722,215,43,45,809,820,160,597,265,123,987,848,147,976,512,983,128,172,714,233,641,48,346,88,758,398,481,308,122,654,673,998,825,209,704,549,927,387,412,949,347,53,490,435,975,236,1000,631,537,497,879,11,121,884,831,411,514,966,316,398,352,714,672,808,962,20,351,446,592,96,327,371,98,666,924,601,387,964,570,103,785,726,792,62,989,675,624,226,415,132,173,24,258,588,291,94,6,942,425,773,287,660,847,223,254,546,972,255,829,800,126,149,761,578,383,6,742,960,694,123,663,421,59,216,648,454,144,594,779,412,901,357,70,433,848,842,517,966,710,981,403,628,236,205,714,964,59,985,641,286,65,32,964,901,676,679,944,45,626,821,160,521,733,212,565,723,350,855,446,884,361,313,835,944,549,446,65,810,549,870,341,712,94,406,530,266,147,16,622,688,10,831,982,675,384,180,711,151,520,610,554,501,185,348,91,277,346,477,521,263,232,382,68,903,739,378,51,777,16,561,453,575,184,98,395,461,462,408,757,51,254,697,698,814,428,66,804,446,918", +"409,84,406,682,951,64,342,715,649,431,503,529,222,475,488,57,350,551,333,127,492,65,470,93,4,685,232,956,388,283,737,733,121,108,637,947,29,701,219,544,101,694,662,82,448,441,891,651,346,508,700,895,55,930,362,910,847,615,571,80,679,652,87,826,519,324,373,84,792,157,570,215,173,883,428,275,223,171,262,133,19,824,809,213,682,102,655,915,859,171,128,850,488,846,941,19,112,760,303,518,884,750,812,756,793,10,227,864,970,647,433,885,837,668,151,39,187,291,210,324,21,917,663,876,265,804,342,563,606,444,976,133,874,572,810,897,361,506,887,890,635,299,584,451,762,903,9,139,131,441,150,249,728,895,802,521,294,770,157,646,550,901,847,601,955,567,809,463,506,176,489,909,953,155,975,442,263,574,368,715,898,475,408,310,350,409,190,137,615,90,370,877,800,884,677,620,396,375,834,574,240,287,763,111,415,281,111,345,249,505,341,3,127,944,737,490,689,421,180,750,684,575,809,840,278,767,114,411,961,662,988,84,402,816,544,779,257,695,665,123,256,438,290,73,753,786,279,609,299,970,352,12,301,719,507,852,508,54,256,409,445,659,837,224,15,198,94,915,922,275,599,818,430,83,981,411,500,536,621,886,599,895,831,558,252,964,987,481,525,967,464,93,298,958,902,718,626,89,246,636,246,80,939,86,98,862,863,190,644,817,282,631,619,230,706,60,915,892,270,294,255,875,685,204,423,793,550,392,377,475,917,930,815,341,138,914,6,594,216,570,93,963,162,365,467,680,370,482,215,616,17,66,70,840,832,344,362,56,148,159,674,422,235,569,623,293,887,92,29,496,751,540,912,615,595,928,625,109,479,599,702,9,198,763,426,762,467,520,155,312,289,447,946,46,538,859,996,832,965,464,617,850,654,267,17,857,418,993,756,825,465,270,42,506,796,836,828,404,572,2,727,53,898,949,920,368,443,543,981,863,612,771,708,255,790,371,654,532,446,259,689,433,461,479,370,58,447,397,692,569,36,5,632,980,218,572,729,582,962,506,731,680,95,5,275,334,80,404,7,241,851,248,343,241,324,728,38,916,521,411,34,727,407,841,720,294,621,346,506,822,798,872,859,483,63,645,45,118,197,705,867,387,426,172,878,835,866,818,303,487,674,994,540,138,217,518,476,33,65,254,106,326,387,366,654,0,47,173,91,142,347,549,41,448,525,900,17,345,887,272,521,540,205,496,872,596,915,288,967,631,808,886,398,924,166,342,972,970,197,997,515,814,245,351,227,233,704,222,227,645,67,152,413,503,176,264,897,873,258,364,24,10,390,393,391,90,929,63,938,306,555,663,366,600,262,184,143,241,445,262,587,240,239,68,794,451,607,772,36,155,931,630,513,447,328,956,420,794,698,922,659,892,511,204,231,454,682,781,163,357,593,209,447,229,353,883,965,651,504,442,170,184,590,397,820,763,91,141,353,121,417,418,250,174,414,707,692,812,103,259,908,412,937,475,718,984,73,548,641,698,134,604,682,379,908,185,800,43,368,238,576,190,878,41,796,412,928,360,370,933,402,799,730,30,789,76,646,946,181,871,546,87,41,877,169,601,28,536,706,338,702,150,537,271,478,876,80,577,944,887,251,638,569,688,876,585,627,122,521,969,556,481,265,910,21,716,342,557,149,83,16,356,63,830,943,810,272,461,906,368,992,549,146,819,254,789,194,215,430,81,273,324,136,893,711,731,233,978,446,993,402,272,35,6,653,918,351,748,889,869,268,3,706,185,984,80,622,480,156,734,152,248,874,809,533,567,229,589,335,929,888,974,785,169,657,99,378,925,319,582,641,376,639,547,310,202,235,620,377,701,294,29,2,91,472,686,54,633,191,266,815,89,215,514,38,286,620,626,846,457,262,651,355,681,948,135,492,838,305,758,283,397,315,719,90,96,631,551,950,200,147,779,671,212,279,648,184,371,557,626,597,113,590,535,74,30,920,128,902,67,488,855,350,813,892,301,279,124,103,627,947,677,778,648,438,862,199,684,249,183,372,304,742,255,209,299,103,366,866,889,896,551,535,251,202,614,478,627,713,552,622,482,394,210,764,238,702,29,657,109,131,265,294,201,194,690,223,790,348,907,760,16,615,398,751,760,94,842,937,904,381,471,753,175,654,400,920,730,613,84,786,816,701,823,348,42,998,210,330,812,747,881,136,207,303,574,610,323,573,938,553,955,495,384,200,143,632,962,125,519,148,64,200,114,603,129,578,840,35,898", +"64,304,727,696,91,461,934,762,899,439,513,397,127,112,335,412,810,392,286,435,552,230,676,724,487,261,753,127,433,331,29,15,701,333,308,991,283,954,225,390,265,637,779,446,193,870,614,221,286,894,968,830,234,435,629,593,278,533,14,125,3,832,102,226,859,141,253,965,304,500,529,735,151,322,310,515,713,22,982,977,822,268,119,989,382,394,537,915,631,713,706,329,184,844,503,392,576,686,986,225,158,963,882,825,624,198,622,1,658,307,30,293,875,531,689,314,6,838,510,64,275,450,708,471,763,372,838,325,121,928,2,463,906,820,596,490,350,508,962,89,899,393,457,567,75,273,670,994,800,426,243,494,345,880,853,442,806,82,95,691,533,140,612,758,320,385,765,881,823,434,914,118,252,37,157,207,784,235,278,122,377,756,219,711,585,968,13,811,724,968,182,381,173,729,898,949,356,359,423,954,520,583,917,277,337,204,208,707,975,849,76,753,531,419,190,571,161,323,280,691,655,639,292,994,859,393,677,613,833,352,57,718,302,999,152,175,231,844,966,208,326,812,902,323,723,955,596,457,949,920,358,612,603,790,569,735,347,861,921,452,458,721,91,1000,576,315,244,525,624,515,774,975,473,666,766,773,751,620,627,668,222,733,828,471,583,625,324,10,566,955,504,738,917,546,125,871,247,441,24,149,15,308,375,598,919,141,202,398,894,803,238,91,853,72,658,858,584,129,914,725,2,446,946,685,972,912,348,639,521,376,341,498,731,971,420,476,486,794,871,115,801,694,300,715,708,547,361,577,61,978,427,906,886,300,166,920,694,215,32,648,593,794,249,93,106,119,774,340,86,214,54,886,895,712,822,767,696,102,577,901,345,703,22,196,344,18,50,2,350,5,240,482,461,439,371,457,66,612,999,514,600,22,196,452,756,652,642,69,969,81,113,786,429,20,951,484,322,357,142,890,21,358,382,473,282,733,132,765,553,59,233,640,936,233,585,403,153,689,649,891,137,405,279,51,540,749,646,562,631,854,29,176,410,317,677,419,595,864,272,58,17,682,275,989,243,738,5,561,180,395,657,451,416,826,351,518,325,783,659,846,834,95,913,176,471,531,632,180,139,926,512,325,119,938,608,676,278,639,331,797,826,755,740,603,53,720,83,226,461,380,28,331,828,496,310,344,517,669,562,504,536,570,247,167,26,47,0,219,175,673,51,840,463,113,648,208,795,757,36,625,350,10,433,855,121,685,703,389,741,183,817,731,935,683,330,782,693,183,920,558,611,672,544,664,387,277,470,594,297,925,410,651,157,512,427,621,5,242,361,407,284,556,393,797,882,578,866,590,159,153,756,767,541,411,884,798,767,171,839,422,621,434,876,798,649,50,70,658,992,428,75,988,639,955,8,947,898,577,708,693,449,577,974,731,963,347,315,781,561,339,448,680,31,963,6,107,712,635,730,644,539,105,732,731,296,808,997,603,236,850,52,649,140,581,876,506,964,408,779,271,128,859,1000,628,960,815,733,583,748,958,297,342,270,654,778,549,899,897,381,576,954,423,871,103,297,312,177,394,282,187,319,335,848,782,396,412,458,863,273,337,546,649,299,329,991,307,235,900,454,182,551,50,665,299,934,41,85,344,535,473,706,483,9,414,896,834,354,647,120,997,684,401,218,131,31,987,630,561,539,585,685,220,237,70,238,830,863,326,32,946,399,805,136,765,468,549,240,528,104,893,932,631,710,961,343,113,483,585,268,16,424,605,717,762,555,457,531,961,380,832,582,301,541,397,985,147,708,269,454,982,669,286,229,120,164,974,716,873,901,238,207,393,140,368,413,543,828,897,786,593,217,216,205,833,109,330,388,135,610,914,86,822,127,11,335,459,953,844,529,187,928,746,343,120,677,734,993,843,822,102,943,646,588,788,476,822,505,625,702,581,825,634,152,577,292,387,746,593,751,478,11,367,246,877,655,354,178,631,459,233,116,1,286,674,10,604,529,8,931,299,442,983,46,744,589,891,269,310,696,179,701,753,18,748,633,430,366,24,250,387,95,141,532,659,281,253,517,675,967,661,796,750,858,177,896,728,548,986,907,773,830,523,498,640,588,685,362,321,758,569,697,512,601,385,76,549,184,733,853,177,517,950,503,849,884,447,404,310,759,700,439,170,183,818,177,604,774,405,237,86,909,209,238,380,50,321,241,289,5,471,767,241,690,492,374,742,109,840,332,681,92,248,194,604,55,379,424,460,249,639,414,948,199,648,641,469,551,859,214,703", +"833,961,935,25,681,50,653,349,269,767,511,242,521,211,839,535,873,28,359,957,689,600,423,122,793,373,930,985,628,512,904,204,218,269,413,161,866,22,107,40,527,365,618,302,826,110,815,251,162,813,57,711,656,108,773,928,329,194,91,699,327,648,343,671,348,211,826,701,457,704,10,312,515,66,485,120,222,921,889,175,97,154,302,419,372,544,767,508,843,209,721,551,885,669,358,5,79,386,315,277,938,358,611,150,304,669,350,330,417,336,71,830,376,371,868,174,94,387,883,58,890,837,496,541,669,650,839,996,412,17,201,632,673,478,684,559,444,39,451,905,843,688,839,19,917,375,9,462,382,365,932,516,579,934,501,982,242,517,186,374,321,608,405,239,320,188,126,68,645,9,589,833,532,884,293,152,736,528,197,392,452,32,706,465,700,391,867,644,477,337,207,826,376,738,43,24,678,614,594,650,592,435,328,594,71,457,957,320,666,474,92,650,671,177,541,155,656,190,433,930,595,563,327,121,4,934,695,678,538,600,784,815,111,584,461,21,403,301,836,605,699,53,427,642,52,899,95,336,811,841,391,395,897,794,96,501,122,922,827,885,513,428,839,149,989,596,384,206,288,983,240,536,769,937,28,562,970,643,953,301,119,400,252,181,927,671,944,206,758,619,655,334,612,35,675,956,759,425,251,466,7,761,258,625,136,8,641,676,659,701,643,990,630,8,670,509,74,503,868,863,437,900,4,958,452,995,842,80,621,872,612,570,848,674,693,820,243,48,872,699,576,238,472,359,435,330,434,788,846,894,800,224,126,503,528,703,445,192,883,297,519,558,884,749,861,922,206,559,993,355,216,301,666,441,854,221,232,258,634,611,750,627,675,438,97,955,269,240,853,579,268,565,730,125,367,95,853,495,486,520,389,473,949,904,647,999,535,498,977,397,884,693,880,188,938,952,23,532,841,837,979,629,34,657,533,349,489,165,112,432,836,607,542,68,953,202,205,973,492,347,669,991,522,435,947,459,240,132,759,168,68,375,209,19,210,781,881,614,360,104,543,842,592,877,446,496,707,923,376,979,835,704,219,920,414,544,608,274,623,143,317,677,840,512,689,542,168,5,258,97,512,910,143,13,262,436,181,196,44,550,828,659,676,609,773,467,904,948,922,912,779,909,716,222,295,201,681,108,262,8,328,719,148,466,740,173,219,0,943,466,945,151,679,66,204,981,8,909,86,14,696,363,803,650,989,298,826,139,996,285,253,293,732,2,397,337,228,286,208,536,806,853,872,711,301,331,901,419,888,599,871,135,233,606,646,751,550,529,483,821,731,736,450,926,914,173,962,361,22,754,608,431,966,886,514,430,202,64,586,799,717,435,874,254,967,39,13,878,834,596,961,59,771,272,351,316,945,891,226,864,6,946,873,711,603,724,209,326,985,220,675,887,707,977,808,912,469,795,970,135,729,853,825,68,125,146,196,94,745,250,267,681,225,845,613,582,890,768,579,885,176,344,171,921,568,218,961,237,154,197,275,187,344,92,492,38,603,727,373,92,877,134,584,224,330,521,294,472,1,449,755,843,970,811,217,58,645,383,821,437,193,172,828,973,629,407,661,910,525,891,292,612,278,556,675,90,790,494,325,573,408,151,110,825,954,480,312,634,758,272,832,260,42,533,579,116,602,790,331,416,43,392,91,935,9,623,497,287,200,477,800,422,916,90,155,468,237,890,745,261,430,224,576,909,104,697,803,354,816,208,230,921,183,603,476,110,190,683,819,445,475,92,654,190,686,909,399,980,126,73,66,515,658,254,121,996,442,464,159,153,714,10,369,157,943,92,355,771,978,767,934,431,873,913,444,136,828,572,541,210,768,27,464,931,973,22,683,446,210,14,372,994,864,780,758,37,75,579,276,596,303,221,149,332,425,263,112,347,244,794,504,412,363,566,748,899,137,23,154,784,294,681,65,306,861,11,931,374,179,541,529,359,126,268,909,432,595,259,312,398,939,6,97,847,757,334,436,178,980,558,538,47,718,550,590,97,201,229,523,8,325,928,545,522,554,219,109,908,418,885,26,975,653,687,906,825,303,690,887,839,140,108,701,423,623,652,889,328,234,575,595,487,603,155,185,746,399,933,650,752,343,929,309,860,321,816,735,432,250,35,607,390,94,347,30,858,936,445,157,420,434,790,582,324,628,610,895,569,99,854,465,877,444,826,29,315,720,391,753,909,833,609,180,272,699,758,75,760,193,394,685,826,358,192,79,364,751,600,103,215", +"958,667,530,379,381,753,696,608,961,210,728,302,897,518,724,479,81,34,467,681,951,825,812,869,994,960,35,560,768,291,593,253,405,602,585,560,863,795,464,391,715,973,537,671,978,28,3,367,305,244,573,400,363,545,355,698,685,660,571,935,678,645,483,794,350,420,791,816,26,528,588,667,702,304,368,177,70,82,65,723,421,449,809,372,63,174,399,749,450,255,620,322,889,29,825,187,28,539,789,694,666,117,450,158,47,678,936,6,777,426,315,534,53,451,266,375,706,635,624,352,214,334,803,876,885,478,952,38,375,286,359,129,845,45,505,885,668,369,104,718,416,202,14,99,386,633,842,401,285,446,900,431,671,77,769,420,361,317,760,679,485,286,754,895,882,709,464,546,305,87,190,496,525,210,370,391,534,201,369,42,706,140,819,932,516,617,978,532,833,79,427,249,948,164,741,219,319,891,886,380,606,246,422,504,754,271,587,457,65,549,613,232,465,101,482,113,510,376,313,309,964,323,142,560,682,29,331,954,364,163,712,550,268,547,644,406,99,839,532,324,56,262,803,872,442,459,278,549,772,149,617,156,414,791,470,85,758,120,777,474,615,962,883,218,96,694,750,558,224,691,255,535,204,692,898,18,239,330,951,832,73,472,965,599,66,175,957,268,81,972,212,339,928,666,782,68,800,190,101,111,580,724,432,856,294,463,52,503,227,405,24,760,867,698,611,511,587,751,632,281,932,947,88,826,675,958,169,658,333,740,153,696,14,361,142,219,561,910,605,941,545,38,144,42,267,865,171,809,74,634,779,826,515,492,205,476,768,700,773,542,715,707,401,870,194,781,668,677,808,817,136,684,661,88,860,813,29,323,847,724,285,800,441,280,158,354,309,750,432,38,135,709,142,796,274,147,146,832,233,480,889,287,467,637,536,858,238,907,419,685,400,192,359,463,837,791,719,257,698,852,214,329,992,288,525,537,686,558,730,210,101,616,848,752,509,786,747,987,298,507,9,618,645,720,929,336,852,414,395,976,452,83,834,614,474,961,87,518,611,332,437,596,581,39,53,822,746,818,981,589,303,983,666,886,435,792,876,698,728,288,359,169,868,190,451,689,636,931,641,232,898,730,260,383,615,859,818,736,687,782,136,70,662,948,318,64,663,634,478,216,242,879,866,911,91,401,773,501,574,917,164,887,227,707,850,91,175,943,0,615,794,96,351,251,572,362,679,452,384,448,839,335,867,646,231,139,863,926,98,304,822,737,233,614,239,159,942,252,378,475,524,279,9,722,308,193,110,480,410,763,167,213,727,354,486,984,75,772,451,5,307,342,106,646,5,72,698,329,632,876,383,600,620,84,115,269,551,132,780,33,839,127,638,402,26,316,186,226,707,422,889,409,560,593,20,774,143,534,515,861,671,750,136,161,969,275,185,172,155,766,327,179,9,103,448,534,445,880,725,231,365,566,621,739,29,553,607,484,438,12,342,135,729,538,145,456,996,567,226,817,320,295,976,724,359,274,410,646,28,974,118,719,88,265,494,554,858,387,450,407,84,382,298,365,104,98,15,285,702,773,513,926,329,89,289,925,375,82,987,918,990,981,649,778,980,460,630,390,452,50,581,483,282,288,468,805,829,768,270,181,38,214,853,49,209,47,309,336,669,339,599,221,651,540,692,66,90,696,640,246,88,185,123,10,133,242,267,457,632,151,667,862,329,226,318,976,838,61,864,774,17,976,317,199,804,41,301,91,506,5,988,132,537,737,534,491,241,433,588,349,440,342,486,884,374,399,143,247,267,395,754,316,581,896,732,739,283,723,398,520,685,578,769,970,624,412,47,330,963,495,12,72,42,822,509,913,331,792,807,810,665,6,275,914,964,689,182,272,948,892,266,39,756,497,337,780,221,33,982,637,181,549,224,2,462,38,172,700,835,759,281,271,677,102,350,585,163,45,373,17,328,343,3,593,142,871,706,340,872,993,42,150,606,226,737,518,231,434,410,525,241,620,335,314,304,834,641,385,234,159,66,156,775,65,960,73,452,129,370,372,981,575,783,101,921,732,951,484,623,446,326,666,837,724,522,215,709,987,433,231,552,667,608,445,202,592,421,135,324,876,999,590,961,383,680,183,594,644,5,779,540,490,196,208,498,975,343,245,114,134,918,444,336,617,161,431,806,204,919,755,237,57,421,989,446,47,821,671,198,810,861,188,699,65,89,326,76,515,734,581,629,77,201,744,483,82,239,583,331,905,71,82,8,182,199,394,67,634,136,182", +"784,781,366,450,923,587,267,775,876,165,502,445,426,484,907,928,755,857,568,354,537,864,567,8,900,156,504,773,294,640,240,552,686,887,567,858,137,443,251,303,388,685,110,293,134,878,144,393,440,731,740,749,350,399,320,724,454,694,794,406,589,33,905,980,625,728,355,572,767,338,175,431,329,144,467,936,441,831,179,958,85,606,402,960,345,186,68,40,519,594,912,162,486,813,612,744,210,292,34,958,820,909,659,398,893,414,234,207,181,329,909,823,936,895,169,351,296,712,800,39,19,166,187,471,859,287,925,413,629,845,259,603,325,80,735,163,22,971,791,59,888,67,855,934,132,807,691,103,994,220,804,969,975,811,829,822,305,930,896,203,630,366,922,851,227,825,969,47,290,535,715,857,902,671,713,100,215,608,345,533,756,989,180,34,734,990,22,913,945,44,629,609,320,629,690,267,33,887,529,306,282,880,122,591,715,198,749,981,336,610,346,160,196,337,391,92,863,522,335,602,633,624,555,884,580,947,183,475,108,972,8,549,256,492,928,934,422,310,249,948,704,525,531,182,919,123,125,816,861,700,842,531,171,462,54,341,757,589,701,878,644,379,626,386,327,872,769,733,40,429,284,759,782,354,479,748,858,15,89,34,81,672,954,716,319,756,794,458,655,459,131,734,730,192,610,451,438,596,290,967,41,291,385,259,578,835,31,708,775,602,945,395,499,578,515,727,966,247,100,150,289,234,530,565,566,88,1,523,987,297,710,169,72,884,805,485,905,652,451,650,110,953,759,10,448,767,192,953,971,251,319,391,659,966,120,647,417,240,891,925,353,206,87,618,762,601,138,487,38,152,757,728,498,630,431,731,44,563,598,793,282,702,626,49,43,629,686,496,249,4,526,455,649,868,820,907,605,603,136,32,486,955,725,276,727,908,447,451,893,481,889,49,338,138,862,112,92,969,797,485,668,670,576,85,229,350,613,387,957,245,770,816,481,925,734,532,894,528,368,420,367,663,705,307,357,484,468,261,599,425,391,149,732,673,300,162,744,505,233,929,415,138,515,946,896,593,346,626,33,936,985,215,38,18,58,967,4,774,270,897,334,634,445,81,341,823,499,307,557,182,305,344,471,716,187,766,74,27,437,906,584,536,806,551,922,619,922,813,650,743,160,893,792,14,119,941,289,144,288,297,651,277,228,469,328,142,673,466,615,0,645,479,730,550,573,161,841,490,415,861,827,667,753,158,333,263,34,41,540,60,681,18,373,87,424,789,146,252,471,768,954,905,112,871,380,880,522,143,310,711,360,441,511,548,743,103,587,57,331,844,588,799,322,932,825,592,312,481,314,858,431,681,446,460,17,752,509,911,628,697,783,419,357,886,537,296,824,656,21,362,86,357,414,221,694,491,867,576,986,241,202,465,168,431,737,625,299,320,69,39,708,521,14,14,54,29,63,605,732,51,274,173,240,570,3,52,206,575,194,223,21,212,929,458,583,10,395,551,600,710,738,7,81,656,15,342,962,452,143,998,986,507,636,870,48,158,453,562,353,609,100,251,271,275,880,890,57,163,901,656,184,507,296,284,107,10,517,175,386,410,887,716,215,772,837,719,95,213,295,435,973,862,729,827,19,456,755,277,307,725,105,409,700,940,711,323,194,620,281,207,795,407,171,289,990,720,168,919,658,744,273,457,995,688,133,485,651,361,346,956,400,792,718,886,162,276,518,770,471,474,212,648,996,366,965,76,819,452,634,218,769,263,195,374,924,987,728,548,615,908,827,754,193,800,105,559,267,544,265,844,113,690,887,107,280,621,994,904,419,11,702,34,347,312,579,51,79,909,39,814,410,207,967,352,663,835,397,135,501,777,218,411,196,107,342,285,765,75,149,997,979,680,86,712,225,768,175,232,885,933,573,855,466,325,515,911,133,213,995,822,219,793,830,156,418,964,29,821,157,9,425,622,547,359,392,810,419,253,649,892,244,716,739,16,381,743,805,490,110,213,696,842,210,765,905,79,215,538,630,258,553,74,283,556,481,361,380,568,612,206,364,76,744,361,528,134,591,810,587,990,6,976,455,526,257,778,92,856,872,979,97,922,662,318,42,77,284,459,72,3,701,776,344,386,398,596,908,32,954,572,877,412,407,215,817,845,992,349,707,306,656,322,871,944,656,386,519,593,677,107,959,657,32,184,535,519,232,646,816,240,323,295,173,266,661,589,553,31,84,584,629,128,68,530,843,420,154,298,515,383,531,912,116,247,565,332,389,555,675,878", +"852,137,822,458,869,751,167,367,862,664,794,175,222,331,442,227,33,853,13,604,567,347,134,244,677,325,572,651,724,613,679,543,573,586,324,923,860,741,79,620,354,509,77,346,687,962,31,652,989,960,756,160,64,219,459,922,623,446,164,408,410,476,280,624,415,104,409,917,150,943,380,464,551,939,238,615,799,465,942,558,169,764,735,200,591,585,975,252,774,320,518,410,52,627,505,493,210,478,517,650,308,515,936,996,725,672,663,144,998,697,226,971,431,691,285,117,47,181,346,37,217,461,581,687,305,547,62,15,82,980,961,25,939,631,86,885,366,360,999,700,998,610,507,573,233,362,467,102,710,607,502,324,95,640,793,656,412,543,860,453,332,578,587,694,833,43,488,496,448,644,64,59,563,576,737,402,539,766,963,366,385,733,849,407,967,70,436,23,587,332,894,874,797,770,766,78,227,115,793,166,429,464,773,744,565,131,397,998,590,827,398,546,234,867,920,222,844,375,328,344,558,807,471,840,529,821,991,878,776,768,339,821,456,992,216,356,594,255,322,28,725,635,554,88,93,676,950,92,144,271,171,753,909,337,837,554,95,339,604,846,518,226,100,213,333,64,687,203,300,91,319,672,728,900,697,865,736,349,378,909,358,568,613,113,814,341,407,791,359,77,237,615,903,424,82,871,561,56,694,545,250,800,924,569,180,518,105,378,576,582,543,374,565,329,823,545,411,297,415,488,360,18,482,205,961,15,542,60,446,945,569,235,949,673,870,520,505,45,184,522,409,585,710,424,812,443,423,425,89,879,44,788,272,692,993,789,991,83,118,730,464,950,407,425,173,25,997,529,997,394,253,404,520,228,861,905,125,919,714,121,332,486,216,411,775,440,31,363,482,967,965,118,268,996,415,594,608,849,428,343,35,441,833,533,486,997,655,826,924,864,123,889,604,405,718,392,977,162,722,836,927,508,702,771,363,936,874,253,756,930,306,295,489,456,454,940,858,778,157,494,318,267,508,54,524,561,879,795,447,274,43,966,838,774,49,759,104,11,813,97,788,834,899,138,221,63,844,681,873,830,334,995,58,551,862,459,715,896,917,74,705,770,799,169,733,843,906,378,63,618,319,749,262,564,424,216,381,451,478,990,213,519,987,373,451,342,37,681,384,160,936,729,535,981,962,910,3,220,661,712,539,94,650,335,326,347,51,945,794,645,0,872,446,196,137,175,1,451,576,18,965,900,104,723,394,660,942,634,606,927,668,739,444,468,481,918,786,997,796,415,724,748,636,665,164,721,789,361,746,3,876,455,885,764,231,208,107,375,501,226,739,455,233,94,557,386,399,509,740,300,943,483,707,90,773,790,305,921,749,658,865,556,335,896,871,735,909,78,568,817,155,774,677,424,911,745,405,733,462,447,220,348,625,14,348,364,394,448,291,11,496,661,107,954,478,454,385,660,593,469,908,695,469,508,71,297,236,572,127,316,205,264,483,750,897,222,671,574,726,967,515,913,407,500,284,97,579,19,251,875,926,978,508,336,161,987,994,519,851,202,426,820,236,841,820,387,486,760,190,745,742,170,894,608,447,187,704,913,606,594,983,67,377,49,290,453,415,410,659,691,65,400,686,451,150,992,424,764,642,186,23,855,158,643,501,982,367,117,791,355,272,246,925,882,571,143,856,490,691,628,787,152,987,593,70,13,484,664,258,894,117,714,116,312,746,889,71,424,333,527,895,168,582,679,387,816,861,379,933,959,469,141,503,481,884,528,208,926,262,233,522,126,50,491,19,258,697,800,195,801,746,882,638,761,35,447,49,2,764,429,251,21,769,479,153,746,633,221,775,497,329,593,747,528,455,336,325,694,62,715,306,730,217,852,764,941,873,880,886,149,693,422,953,832,187,396,36,714,187,713,353,94,326,604,373,34,620,647,548,524,554,5,343,952,9,172,912,994,698,61,438,137,338,184,635,724,358,983,973,933,50,364,398,490,507,887,324,436,868,777,882,894,805,484,755,640,66,292,640,385,96,558,670,583,260,557,973,234,107,76,648,656,343,102,530,563,763,534,68,245,661,399,900,723,599,584,967,104,361,244,366,111,894,423,247,204,931,986,847,690,669,450,834,682,110,872,504,938,201,417,19,749,151,744,103,469,435,22,65,842,864,721,940,38,338,852,65,989,969,222,903,556,156,937,816,543,595,157,736,686,154,719,264,409,766,650,118,181,266,67,718,332,4,327,771,218,763,873,137,950,238,29,806,661,413,407,457,364,282,273", +"817,842,203,28,307,573,699,320,100,770,618,155,366,633,618,802,447,663,201,166,632,937,460,960,503,215,440,444,213,593,428,773,583,4,943,219,501,369,5,129,462,24,297,881,283,180,700,750,564,127,948,685,790,63,232,973,290,907,425,574,347,665,24,459,175,695,143,93,460,829,624,224,580,330,520,930,27,328,771,87,792,475,463,688,78,913,212,489,460,55,839,824,900,320,450,217,590,206,855,977,697,669,290,228,755,641,303,437,287,211,265,127,372,410,857,971,943,857,302,44,555,80,49,680,319,297,291,624,782,788,378,415,567,365,26,166,104,555,811,513,330,924,646,831,487,622,153,136,30,954,136,173,245,846,181,740,155,728,380,233,524,17,224,9,235,69,634,562,542,121,707,176,54,636,135,186,491,911,258,962,152,185,252,992,100,188,507,540,360,749,778,795,599,536,960,64,532,721,818,141,663,993,820,974,547,480,116,303,516,377,197,332,455,480,217,942,775,835,914,481,938,897,196,240,1000,441,606,375,689,639,534,676,483,749,926,981,500,427,554,493,736,177,3,986,512,767,255,639,384,556,380,511,601,781,874,502,547,824,386,642,167,70,668,968,100,768,372,511,681,230,909,726,287,607,876,624,581,847,784,627,405,304,756,719,667,492,991,44,772,67,425,502,223,63,307,204,396,646,471,943,884,167,484,746,22,404,714,852,448,498,904,637,806,528,669,80,475,159,156,558,88,646,733,658,991,404,544,497,503,351,216,604,269,695,291,296,54,638,783,612,290,581,399,466,856,257,589,155,67,821,852,237,862,695,538,780,57,621,505,272,548,627,378,782,245,599,970,55,8,865,405,714,556,339,870,17,627,748,231,226,667,399,521,782,311,273,573,860,126,607,745,698,766,932,541,90,79,745,769,81,953,92,22,95,786,367,235,193,986,612,858,234,595,597,163,227,45,170,85,849,583,347,303,965,897,700,108,22,906,468,85,158,99,6,843,942,249,849,603,695,368,697,63,79,991,651,737,441,588,39,993,697,715,829,186,966,290,726,218,558,746,497,98,900,418,379,642,800,329,573,613,821,211,170,209,145,468,790,905,895,227,209,110,904,695,966,498,523,466,988,553,210,462,805,173,574,527,825,643,661,344,383,546,323,940,886,583,249,539,887,1000,721,863,370,307,653,999,470,576,258,939,40,470,936,957,549,840,151,96,479,872,0,325,582,647,98,590,508,660,346,897,764,885,664,947,774,498,708,765,437,158,310,883,988,311,998,778,727,562,662,900,402,145,255,799,612,830,459,266,602,164,991,225,819,309,606,795,454,166,672,321,632,605,719,344,133,560,491,368,469,826,356,501,914,273,502,841,623,483,80,71,772,264,347,191,303,307,243,764,690,965,650,190,860,714,606,206,398,968,400,100,210,616,957,750,989,435,312,679,827,945,727,709,572,520,941,583,460,106,968,797,148,499,684,478,136,264,478,471,971,493,133,498,215,971,673,821,867,727,942,803,832,371,960,165,403,973,456,130,33,483,783,186,92,289,555,293,941,982,218,983,748,366,696,729,220,302,462,522,681,893,897,325,290,170,663,837,446,250,323,356,508,266,760,619,675,91,592,116,939,778,374,20,841,439,953,702,684,250,904,530,457,352,899,99,165,109,426,627,694,508,196,632,928,648,984,631,811,377,549,808,31,839,369,246,107,818,489,902,973,392,832,957,136,645,411,438,57,603,319,485,186,230,437,133,211,208,612,382,527,115,592,542,209,312,233,187,447,972,869,730,223,476,368,23,439,634,320,516,96,220,716,666,974,614,927,63,855,613,648,591,727,190,478,342,278,305,660,564,856,821,514,128,850,420,576,208,346,365,345,106,779,189,201,541,793,993,400,183,455,452,671,28,332,918,647,730,694,952,388,590,840,638,912,969,233,591,826,288,495,938,395,255,472,200,961,555,718,771,154,146,268,938,183,328,149,200,526,621,649,494,513,342,117,150,289,903,210,309,241,139,847,453,20,866,404,41,832,124,210,943,411,172,385,128,913,411,852,708,23,455,756,477,402,970,986,807,205,98,822,421,58,619,480,811,358,903,446,147,491,232,22,950,264,271,348,206,966,108,625,361,669,928,988,118,906,374,954,712,444,298,569,22,496,808,123,521,886,74,601,412,289,110,947,573,439,994,964,91,701,151,977,646,293,787,24,463,857,480,501,846,360,367,220,102,598,913,143,324,611,837,892,217,677,114,223,994,785,851,503,134,892,42,737,986,775,913,154,550,645", +"835,79,704,899,21,947,775,980,417,60,915,588,49,920,311,604,575,936,581,286,690,378,857,367,399,958,733,748,945,845,335,718,657,130,239,118,839,188,711,459,268,929,889,557,740,203,75,105,392,194,524,529,760,732,476,173,150,330,311,313,477,715,646,900,6,182,957,154,543,378,880,476,180,984,593,570,843,988,168,24,832,593,692,179,39,6,40,670,479,258,938,255,730,387,524,278,496,228,963,45,380,210,512,263,9,372,970,537,9,166,996,593,710,573,785,36,121,224,128,623,672,357,265,766,553,360,539,788,533,239,436,3,895,231,544,921,452,728,213,540,145,694,63,462,107,392,825,616,368,279,165,50,559,94,361,50,227,17,853,140,56,660,899,522,760,115,805,922,175,840,334,699,857,503,827,322,206,948,380,230,997,352,131,576,558,702,351,741,54,381,171,558,375,240,843,554,955,279,293,817,176,83,704,183,96,572,693,478,569,264,998,900,546,877,37,915,725,741,274,400,557,793,534,96,335,464,226,886,25,419,101,16,226,213,917,338,378,714,302,225,490,2,621,497,3,4,856,815,401,681,137,817,247,415,824,872,768,832,735,463,979,509,503,620,977,471,333,716,580,505,330,69,799,514,137,259,31,995,600,572,398,978,771,741,391,113,53,435,985,660,472,664,637,727,813,829,958,177,600,431,99,516,23,576,94,472,38,532,78,629,668,427,803,268,679,663,704,618,22,1,562,290,418,432,554,694,723,806,988,162,133,523,979,873,997,209,661,604,594,665,380,522,151,638,833,467,769,585,640,167,340,515,480,705,815,153,154,224,949,422,87,99,339,721,864,325,248,339,421,281,269,28,711,300,124,28,518,701,712,801,514,492,25,829,397,62,558,412,678,27,801,814,441,53,148,779,713,254,250,101,506,730,231,596,596,890,505,831,282,474,51,120,6,763,387,377,944,862,743,638,941,45,645,983,761,213,157,901,810,733,341,455,379,819,153,121,929,321,948,428,925,739,856,122,126,357,20,809,365,296,634,487,262,456,316,55,602,723,904,469,972,435,502,349,10,201,107,380,678,921,314,342,879,875,410,694,587,742,818,126,863,346,650,989,415,831,839,94,389,619,845,984,900,154,512,25,186,344,467,261,193,913,422,273,948,365,150,134,547,391,581,993,475,955,89,866,282,345,640,686,386,475,313,752,693,41,463,679,351,730,446,325,0,298,614,702,376,468,14,553,744,586,465,383,522,582,532,653,744,184,183,199,246,295,65,338,705,348,793,632,989,295,726,598,901,584,633,754,375,343,927,431,924,426,586,552,177,213,929,947,62,203,957,713,964,212,129,561,773,277,450,865,231,87,937,275,682,708,351,672,893,397,28,76,805,484,517,151,280,888,697,400,746,420,546,163,932,1,180,742,331,928,845,426,817,599,125,3,725,926,959,218,467,583,796,147,125,484,77,482,57,558,563,878,615,836,897,449,634,179,710,259,617,623,133,529,642,96,7,726,4,694,525,41,995,398,104,31,727,408,800,990,762,555,148,897,854,421,857,212,75,430,286,655,629,369,161,352,122,439,681,369,914,39,346,874,789,33,36,431,966,848,230,151,320,617,976,610,34,170,561,36,130,459,456,853,717,163,286,125,583,838,153,623,325,475,205,99,198,310,773,496,557,477,552,721,181,209,85,205,493,179,929,705,366,970,148,805,546,462,53,614,380,48,140,961,80,404,595,578,13,980,351,396,705,8,685,980,245,525,725,989,528,50,960,67,39,485,647,990,623,520,639,561,698,904,306,54,742,5,528,403,561,717,756,460,651,226,280,168,623,369,715,974,226,386,924,484,214,457,742,196,92,789,776,138,436,17,507,730,713,550,489,322,125,619,151,967,240,423,312,51,259,848,227,922,845,543,223,43,725,629,885,376,475,470,564,530,417,508,398,384,538,111,364,422,847,726,732,485,727,359,948,949,771,690,766,734,590,268,191,201,298,42,661,331,609,364,249,476,501,406,897,643,492,804,938,273,248,189,884,358,465,571,841,553,326,142,283,808,34,179,490,614,834,233,714,482,427,325,116,781,339,447,52,281,348,35,386,970,541,287,444,976,565,864,259,44,726,750,858,163,877,348,20,620,629,739,781,490,545,278,475,281,19,971,238,164,343,908,398,831,488,177,33,131,906,55,635,45,154,936,202,32,899,898,364,76,771,838,896,367,191,324,943,805,76,3,975,157,927,330,876,350,204,163,283,472,811,848,265,829,311,415,913,229,458,398,690,126", +"829,937,449,169,469,221,723,478,548,884,205,718,177,226,106,479,33,943,520,724,213,754,130,870,296,101,812,881,145,729,862,918,485,454,976,641,585,978,819,516,485,890,830,386,768,776,618,48,447,899,452,121,999,698,563,998,798,282,34,848,17,613,516,495,6,865,806,695,224,384,532,52,560,752,688,787,636,967,738,882,888,681,643,383,722,776,599,954,538,512,650,395,232,55,17,169,874,268,746,470,193,796,32,94,254,806,604,293,638,912,107,631,385,568,913,193,921,271,328,987,123,948,966,895,991,491,980,598,97,325,836,514,12,924,809,899,151,577,703,668,991,602,905,921,258,225,903,520,240,290,466,302,920,859,157,391,742,103,594,92,805,906,581,787,529,430,944,302,769,690,612,112,671,69,328,268,497,203,925,484,879,600,319,13,437,20,402,208,582,570,485,325,944,707,273,179,107,623,440,416,202,966,768,250,156,997,642,761,58,586,274,197,105,941,752,779,439,799,427,645,24,894,260,383,125,141,787,229,244,386,168,263,13,129,651,303,391,702,538,370,892,589,766,726,49,743,797,80,117,671,875,73,237,69,187,788,42,660,44,964,322,783,424,4,340,427,686,838,184,921,579,237,225,26,520,94,179,735,771,186,21,989,126,111,303,292,6,373,947,550,228,718,384,863,267,557,916,284,660,374,56,400,393,320,892,963,217,59,121,572,898,659,329,466,600,558,572,208,2,890,539,982,164,751,26,64,73,124,222,794,178,806,864,923,74,280,443,676,930,901,131,147,281,369,716,310,778,39,961,215,582,10,91,401,800,135,633,108,565,102,699,874,203,542,394,43,582,187,868,391,715,429,700,274,368,613,892,165,813,905,960,499,606,848,801,754,918,564,597,320,531,402,447,795,584,643,818,236,950,990,567,975,710,785,515,806,961,699,120,726,512,741,321,641,32,389,223,625,338,316,528,517,743,576,632,70,512,395,104,139,888,676,996,480,129,40,48,308,201,40,479,318,993,553,923,912,346,433,572,852,392,360,210,366,804,277,139,525,263,654,747,826,417,751,548,984,893,937,99,961,326,249,138,54,214,919,496,680,89,517,551,224,186,819,197,347,67,614,222,107,28,938,31,138,960,489,927,429,41,249,518,292,490,364,54,422,449,141,461,114,964,591,257,196,752,77,928,608,884,922,683,519,414,224,878,448,113,66,251,550,196,582,298,0,906,575,457,953,32,225,383,157,725,882,707,633,858,153,219,408,707,729,88,466,545,991,235,734,336,781,542,128,111,560,592,968,72,200,340,511,653,260,928,643,568,663,916,574,288,325,86,591,706,876,189,807,255,623,250,47,304,164,572,783,674,470,375,765,355,329,696,241,37,849,111,403,490,780,275,141,845,625,521,169,688,268,369,512,687,518,455,124,981,8,382,807,233,988,374,108,34,4,8,904,487,167,919,397,476,630,940,906,810,489,219,245,267,271,775,149,672,103,262,405,99,219,936,974,349,272,701,372,211,610,141,968,301,534,243,183,526,677,387,345,953,671,542,993,935,503,883,566,29,560,8,567,785,752,390,767,801,965,116,370,797,264,570,663,700,562,355,353,263,468,78,35,664,623,54,940,284,199,449,627,714,445,24,511,794,741,734,895,144,862,600,614,832,589,781,206,396,405,348,556,583,27,520,782,387,702,456,857,79,949,234,656,523,431,585,525,667,211,263,222,588,638,312,581,175,589,242,686,171,979,871,403,587,138,865,248,839,477,177,274,299,361,28,867,464,279,15,897,200,248,756,2,783,625,484,389,757,503,887,645,193,488,642,867,422,928,370,481,610,76,268,816,738,542,910,581,289,575,365,434,793,868,871,219,549,170,168,581,628,432,477,731,765,865,355,485,850,436,298,875,582,568,893,954,790,253,626,909,527,418,101,937,663,229,51,91,720,471,336,963,425,880,643,216,70,449,101,929,673,521,45,77,245,878,940,85,904,964,271,992,887,297,400,346,351,472,304,168,91,426,383,707,38,606,165,280,576,487,794,803,563,68,393,271,640,953,293,571,821,975,326,695,612,753,815,178,588,949,848,981,576,573,562,628,115,20,969,862,177,587,695,702,849,671,303,193,568,58,357,221,960,416,539,388,752,803,630,381,694,774,285,747,958,972,233,852,792,223,871,142,270,797,559,521,535,987,646,116,395,489,223,11,564,31,77,475,500,36,287,918,317,54,649,689,261,866,529,934,161,816,532,327,123,944,69,8,786,667,685,251,243,252,542,980,680,619", +"911,810,665,627,992,624,274,217,423,394,675,803,177,766,321,222,422,410,811,206,675,475,818,755,255,385,832,704,885,272,126,713,886,403,121,852,125,576,411,879,875,335,980,961,835,773,281,863,100,943,575,339,736,465,740,206,468,681,726,227,138,446,460,42,330,9,381,580,300,265,354,917,177,374,651,210,832,714,740,770,390,799,307,410,805,479,898,458,277,814,689,299,502,350,289,186,92,325,511,709,842,167,794,341,925,438,163,114,326,59,923,956,447,169,413,631,832,256,177,251,752,611,73,896,59,910,399,58,708,134,247,724,780,498,657,257,833,160,190,739,548,347,766,209,975,549,696,505,553,947,212,826,90,92,211,24,458,717,364,446,368,216,789,142,340,322,697,324,291,381,958,293,722,815,378,54,834,210,381,943,719,10,528,689,410,142,123,715,20,909,411,553,69,294,203,996,295,874,532,235,44,975,546,992,598,416,85,682,703,225,529,801,817,375,412,710,98,313,508,494,1,499,563,859,782,272,876,413,639,725,214,794,385,199,731,779,297,872,578,382,617,359,401,645,500,900,916,898,252,261,608,922,711,933,601,640,575,703,954,378,99,941,453,766,916,564,474,653,768,6,503,511,698,91,742,807,189,144,219,211,984,630,626,819,195,365,778,79,389,599,204,330,907,622,394,805,393,711,791,722,124,265,185,140,920,573,344,811,920,31,262,587,211,24,778,993,923,504,337,778,821,223,925,939,758,349,779,194,504,396,552,171,175,236,459,43,98,522,21,332,130,255,16,287,754,644,300,892,38,462,696,456,497,597,519,104,112,355,96,68,624,130,600,356,690,321,740,227,903,510,324,683,628,11,689,825,718,352,672,976,854,985,901,727,561,816,185,749,816,753,710,808,255,189,66,562,681,628,650,102,933,553,103,881,889,828,942,782,363,80,278,51,198,294,742,620,25,362,983,974,950,539,682,587,17,606,537,313,299,521,345,241,657,139,653,329,646,724,781,386,991,521,99,831,20,887,45,647,744,570,181,515,933,470,756,558,115,981,124,195,338,218,702,38,888,600,42,697,269,997,404,98,479,214,95,111,3,144,37,37,991,435,271,765,804,341,168,460,164,761,138,908,390,159,779,561,52,127,207,756,568,16,770,910,716,588,622,878,633,693,670,326,122,280,311,748,118,67,558,192,445,476,770,137,912,525,648,204,572,573,137,647,614,906,0,370,984,879,702,29,931,78,991,190,832,402,398,647,64,289,47,96,185,907,383,487,251,504,410,350,44,686,1,765,471,767,770,188,355,383,871,519,934,56,795,661,616,711,507,625,252,980,613,36,741,784,603,921,181,779,552,627,424,960,102,581,168,608,34,626,143,8,790,847,267,813,702,153,789,800,498,992,139,150,530,332,598,41,445,351,73,280,812,573,9,652,570,352,411,18,76,782,741,643,687,976,572,838,187,386,831,527,840,257,317,821,144,84,307,400,746,400,937,911,604,374,119,379,215,424,244,63,433,647,715,193,729,870,898,497,542,918,552,698,388,902,375,320,732,546,627,642,56,491,223,469,373,756,596,932,427,7,676,122,869,853,189,978,278,183,174,207,354,336,860,838,377,768,117,246,104,35,535,953,585,208,535,254,701,588,690,336,446,703,153,645,106,964,926,389,168,238,214,74,868,651,437,853,801,980,365,12,299,545,917,125,791,893,466,485,971,710,874,381,806,756,922,647,309,273,36,874,377,547,450,999,560,310,621,440,943,87,553,370,83,997,397,26,781,526,331,509,584,205,136,659,964,882,989,228,619,354,238,175,482,23,619,526,960,810,136,638,216,123,232,935,615,895,831,846,402,813,605,453,432,327,928,615,268,341,799,593,737,862,882,178,508,605,949,509,221,675,117,237,575,205,616,137,798,861,739,95,266,726,535,716,302,450,151,626,404,898,372,188,627,694,239,608,858,866,994,505,717,555,489,845,236,120,335,21,611,863,371,582,791,292,111,901,908,759,260,495,371,490,483,351,4,770,589,359,296,16,143,882,395,258,234,169,408,716,193,713,595,806,274,37,930,190,258,256,950,431,58,581,396,333,649,726,668,661,289,330,279,482,413,782,1000,471,920,486,629,364,551,322,247,299,100,565,77,837,389,460,30,752,726,756,854,321,746,888,720,463,470,412,186,964,208,547,3,360,81,448,267,107,308,945,946,402,9,355,800,898,211,127,136,242,455,493,336,683,821,541,153,45,577,574,271,485,681,558,293,811,684,185,983,177,740,512,308,628", +"254,56,158,879,196,363,910,344,462,127,682,615,907,981,849,758,915,480,100,173,76,130,230,146,806,530,11,951,239,870,921,122,271,260,263,753,170,577,893,752,650,472,191,933,810,609,424,611,626,924,917,876,258,566,645,603,342,508,876,949,351,548,744,844,468,871,866,49,371,415,353,157,920,989,801,886,766,190,992,557,296,161,102,985,997,225,345,148,541,80,853,368,995,487,5,946,675,578,353,812,384,390,100,904,585,560,339,607,623,530,549,176,155,835,530,323,294,235,884,65,107,930,406,684,544,916,433,971,32,331,461,931,232,392,169,185,114,913,457,703,697,171,296,269,730,599,73,483,320,379,147,99,187,190,508,347,533,35,901,730,748,159,365,759,604,698,2,623,504,133,856,187,511,377,885,158,476,593,45,148,109,574,158,18,989,348,749,808,446,273,239,939,442,685,809,832,760,839,734,98,286,350,851,765,594,920,278,327,257,337,83,861,265,948,326,777,743,659,410,382,518,639,516,65,225,237,608,255,842,324,717,599,3,744,999,104,956,230,284,398,265,781,502,574,668,258,249,366,206,390,436,252,269,314,74,394,704,772,42,629,392,384,756,687,212,936,439,418,744,213,306,230,633,201,368,689,75,970,634,886,688,647,831,171,418,546,618,610,539,348,808,464,579,936,477,402,916,110,694,159,776,206,343,729,895,10,356,856,247,665,777,586,659,541,203,117,55,450,411,33,179,548,656,275,799,494,214,348,178,715,553,117,43,417,434,870,675,702,373,190,841,20,509,154,961,97,922,92,670,95,715,811,10,766,188,708,937,250,370,857,63,845,798,52,442,595,885,560,28,340,136,907,884,254,121,698,248,998,702,968,254,274,907,839,757,304,351,974,758,25,65,178,467,939,911,224,981,313,517,614,29,906,215,602,65,605,472,127,202,186,920,997,624,923,709,835,323,726,771,167,608,950,850,8,293,643,622,688,8,523,411,490,485,357,160,670,325,808,878,215,781,93,838,250,600,300,955,114,746,936,302,481,156,702,256,163,145,91,823,38,634,64,771,5,935,805,42,520,401,613,809,372,23,794,967,699,41,788,55,789,597,40,742,434,169,350,76,541,544,971,668,307,910,381,746,650,622,541,743,15,762,569,409,23,430,518,449,473,409,447,57,852,268,623,334,188,588,996,476,734,41,597,309,430,875,900,208,981,362,161,175,98,702,575,370,0,706,986,332,592,894,705,252,715,406,936,735,120,674,106,231,850,25,145,435,160,923,776,568,143,628,33,429,790,859,144,918,782,610,923,506,463,460,765,371,523,393,363,747,493,436,50,948,972,372,129,477,942,655,808,243,968,437,374,643,930,292,305,710,722,934,17,387,78,499,44,547,608,487,460,314,539,856,185,373,589,583,372,608,289,631,558,416,505,420,56,763,966,199,426,566,857,970,890,431,50,506,189,276,285,645,347,519,992,559,867,362,598,94,879,764,901,45,10,836,932,987,405,336,539,90,390,717,485,398,411,949,743,881,203,655,713,145,119,498,728,663,843,502,887,972,188,462,907,343,852,206,862,412,849,553,410,400,18,368,206,419,303,55,457,860,436,5,992,14,435,714,36,836,684,702,455,948,347,26,747,570,854,896,581,880,960,453,498,406,532,884,377,764,852,560,611,729,447,227,397,29,112,717,237,898,712,745,926,959,132,114,463,34,756,979,393,602,815,510,106,64,188,907,866,857,990,435,359,206,223,466,159,939,955,949,635,775,826,737,222,500,262,334,793,772,879,758,519,157,370,682,596,275,567,167,476,931,571,961,39,704,894,222,466,487,410,183,248,641,458,934,7,218,956,624,328,19,77,682,356,214,197,896,939,820,906,412,225,140,230,287,277,772,387,728,163,236,703,125,309,955,318,421,250,272,547,739,885,155,8,538,741,621,498,125,918,519,906,797,858,703,974,364,638,980,610,937,749,398,291,406,926,822,95,889,72,578,93,112,466,235,937,428,680,926,685,106,797,359,812,121,796,302,89,81,520,670,131,864,64,129,627,523,721,654,593,543,184,17,739,316,546,460,396,734,66,272,210,542,354,752,982,186,296,577,634,746,231,656,474,683,196,279,429,440,54,690,534,274,691,568,194,247,725,643,675,789,71,317,698,275,767,944,316,422,534,112,428,800,206,694,372,708,124,51,695,142,198,347,293,213,800,97,168,773,149,904,260,330,707,364,168,965,449,242,224,279,626,805,39,844,875,272,957,953,800,126,450,117,759,720,81,68,35", +"917,179,322,97,617,693,535,820,298,512,134,292,649,422,156,618,215,407,152,169,9,76,476,727,411,164,913,940,150,953,511,936,884,980,217,808,46,433,762,776,101,775,263,292,531,6,450,883,777,599,606,789,943,360,766,195,493,720,938,587,108,57,244,359,163,645,246,236,921,166,172,787,514,128,449,478,44,674,711,136,122,850,648,164,504,65,878,592,214,282,33,838,994,721,816,346,701,81,805,411,286,792,547,252,113,949,488,547,225,910,418,365,621,501,256,68,274,189,989,168,138,778,535,21,492,439,785,50,345,702,580,920,117,581,764,765,53,227,334,630,596,797,993,927,300,774,159,150,809,828,123,603,358,729,891,560,457,31,766,756,297,221,730,973,863,533,769,418,530,697,134,572,594,739,930,734,760,156,192,598,261,565,64,596,120,157,108,688,967,955,745,426,193,397,554,770,73,628,660,755,539,327,631,261,141,8,480,562,371,172,776,32,773,708,745,779,548,349,693,866,153,650,93,233,871,691,901,85,90,998,149,150,66,852,679,635,43,100,402,95,777,543,700,42,179,208,908,513,241,622,62,786,699,393,915,18,395,391,897,235,869,310,796,578,825,705,395,315,950,161,962,940,234,975,791,40,938,684,528,289,594,253,145,769,737,841,493,770,595,816,649,866,407,244,36,453,20,98,648,851,745,278,563,731,191,764,623,302,374,110,542,897,547,185,725,249,424,944,930,577,643,594,480,961,93,535,989,787,371,936,893,522,998,917,975,170,899,324,808,420,52,92,688,922,786,479,298,748,766,878,996,664,834,254,983,905,427,462,467,550,86,244,714,761,10,423,928,830,965,846,630,454,118,740,134,986,632,48,997,682,23,402,942,976,795,175,43,479,687,869,921,126,773,244,241,997,578,905,440,565,495,958,165,141,486,228,884,416,272,54,832,86,577,869,498,703,874,907,257,697,643,984,404,559,623,941,615,83,460,283,400,581,348,620,617,879,353,789,956,751,84,474,36,56,284,911,484,221,983,889,522,917,656,69,198,747,733,841,489,818,288,740,649,860,125,594,507,443,476,448,38,997,563,796,374,752,466,178,377,711,381,77,403,775,771,808,404,592,14,299,16,693,619,534,890,644,511,901,472,326,160,947,868,75,230,25,8,228,798,510,450,501,576,257,222,541,803,958,678,43,796,183,921,835,33,17,795,8,679,841,1,590,376,457,984,706,0,178,535,19,672,827,664,783,158,89,178,914,934,664,80,575,119,606,551,787,993,827,484,76,59,854,922,589,606,557,452,922,436,597,445,743,329,271,961,352,983,544,469,110,481,801,893,371,729,83,578,293,328,564,415,421,782,171,266,677,528,266,441,328,941,310,253,17,500,482,907,912,524,266,46,939,318,762,250,97,382,637,244,273,52,854,156,667,801,78,46,86,809,67,384,650,959,156,40,47,276,143,942,629,423,2,53,757,241,83,871,877,952,336,215,1,364,531,962,618,139,841,310,270,777,449,50,110,325,399,838,893,766,288,284,340,54,248,440,201,532,486,888,85,116,373,232,613,84,529,196,716,151,702,828,360,177,634,246,716,665,117,514,467,888,750,162,656,127,823,192,334,285,982,350,737,727,295,181,265,705,441,593,978,714,532,478,751,952,372,647,226,442,532,474,858,703,205,530,4,585,564,667,440,420,874,295,135,196,407,320,277,671,216,242,736,302,508,777,323,575,984,85,845,947,895,816,578,488,868,655,145,23,141,683,556,369,254,776,511,141,520,423,551,353,278,994,527,989,346,446,981,776,967,844,766,956,682,398,48,969,876,332,985,598,476,787,799,996,799,737,437,760,636,378,76,21,506,788,646,23,828,334,899,337,357,618,703,923,730,906,842,502,38,445,205,735,672,728,546,487,19,483,461,417,598,101,210,12,531,170,874,367,327,770,795,909,638,945,621,238,368,765,802,262,367,513,96,727,461,794,216,698,19,510,707,480,943,352,486,715,393,660,136,842,116,986,995,282,769,274,875,650,476,237,417,950,439,429,701,861,788,480,104,876,593,549,170,958,157,560,518,215,927,211,57,993,703,269,650,516,793,936,746,469,949,44,593,35,675,516,778,85,718,268,298,355,338,830,188,318,253,223,677,661,193,590,959,575,884,672,459,923,357,758,823,286,335,570,442,803,384,653,61,558,808,761,661,617,750,165,197,932,128,758,203,56,953,372,797,467,110,330,188,64,485,876,866,112,910,222,514,285,631,40,471,861,948,381,542,682,360,952,405", +"706,335,293,84,598,442,893,636,834,403,82,686,653,821,307,20,331,296,797,759,169,148,79,867,991,236,675,30,305,298,293,35,669,7,283,303,277,906,885,647,224,455,42,22,652,405,624,706,874,490,54,558,713,68,794,823,407,802,896,986,240,746,399,543,618,439,563,216,377,128,466,660,21,253,746,666,104,272,239,898,258,194,549,288,92,586,3,581,266,603,468,172,628,938,136,557,280,896,838,772,37,394,268,884,480,383,245,808,824,332,557,752,481,701,401,222,984,599,189,714,426,116,502,936,117,630,983,792,758,144,455,436,332,277,897,611,624,394,888,93,481,447,883,175,399,929,405,969,956,811,276,633,330,188,835,438,144,870,245,830,105,265,343,131,522,578,662,867,10,757,398,752,861,866,788,571,497,507,660,342,794,858,288,784,322,500,743,798,604,626,452,872,663,535,277,421,374,901,778,724,394,197,212,332,678,496,700,846,619,261,922,592,586,100,724,716,361,257,791,303,744,729,511,249,610,359,634,535,676,491,155,504,850,508,448,891,971,249,155,81,306,537,308,591,344,216,697,448,956,582,822,830,239,823,287,958,741,981,273,690,112,110,882,668,339,570,532,51,970,375,555,814,640,531,286,138,34,242,776,894,178,174,30,271,124,137,642,480,105,846,63,888,365,563,808,976,160,409,416,986,269,716,433,726,444,627,12,549,868,716,665,673,505,329,469,677,775,24,919,589,843,946,400,889,739,246,982,908,69,912,498,529,1,277,841,190,638,891,187,338,646,951,675,126,766,135,908,914,461,621,370,430,780,983,646,655,551,639,887,438,57,321,488,543,408,553,338,548,876,498,923,736,556,187,331,143,301,190,582,580,840,744,729,16,413,360,140,538,851,332,245,355,713,939,784,837,233,602,500,547,2,801,627,496,453,521,973,990,907,336,2,522,889,560,48,896,28,899,546,358,879,415,241,345,984,212,364,558,843,727,684,962,615,369,494,151,552,961,455,951,84,875,480,878,137,168,457,864,698,554,621,938,823,748,758,887,737,628,523,994,815,3,185,709,571,114,714,942,888,76,243,321,290,824,178,558,389,689,802,926,839,777,302,784,666,519,158,805,275,942,361,177,640,476,434,313,315,759,58,451,710,493,137,549,769,124,137,857,217,698,104,698,14,627,687,557,202,526,348,229,461,25,340,989,643,345,757,909,452,490,451,508,468,953,879,986,178,0,501,570,791,120,644,646,281,842,489,621,670,320,759,150,752,929,456,740,727,158,546,38,32,460,196,981,297,745,297,233,183,163,302,221,695,799,511,757,438,989,627,931,827,280,264,459,152,56,155,502,803,243,660,511,398,458,658,719,954,183,90,110,49,98,275,856,649,587,468,275,376,739,559,726,549,460,430,992,958,80,987,28,54,366,455,96,822,38,720,652,583,502,507,773,555,134,561,614,894,815,866,286,484,526,479,54,66,693,490,305,877,169,83,463,147,673,832,902,498,448,610,2,554,593,179,720,653,46,21,514,84,648,992,587,730,346,987,702,688,883,687,344,393,182,260,495,414,180,816,678,808,669,534,250,484,717,580,617,475,262,826,875,872,464,52,45,433,797,759,853,486,580,395,567,833,367,402,13,471,852,775,224,141,334,827,605,771,446,758,52,613,430,877,172,31,742,532,685,150,929,751,107,621,156,698,200,325,445,807,338,820,559,216,769,403,925,780,89,178,663,274,300,999,507,614,561,583,324,572,308,621,439,843,871,970,245,449,943,432,970,885,178,207,277,47,172,178,923,494,663,625,509,344,59,530,732,588,512,832,525,559,988,387,838,757,99,93,331,794,515,27,622,306,32,556,946,539,107,805,876,910,201,820,782,967,840,750,722,595,606,116,947,85,481,970,454,336,553,540,200,519,144,152,722,193,528,548,434,853,99,199,698,284,997,732,900,506,712,699,629,297,600,4,487,369,813,961,586,101,90,307,482,375,308,803,306,739,682,665,189,638,855,772,719,305,183,988,443,35,202,104,463,530,600,933,425,213,724,204,990,55,734,670,920,986,506,259,196,29,914,371,192,603,56,819,309,270,404,573,954,3,893,966,724,42,286,471,879,945,99,706,693,233,849,102,961,911,113,365,468,446,952,391,781,947,157,318,477,324,250,163,43,57,843,347,214,327,592,62,469,594,895,9,988,650,99,788,948,964,376,110,48,129,796,621,825,670,611,747,274,29,748,932,683,701,301,156,986,946,34,37,403,993,493,740,552,562,21,156,216,938,846", +"681,760,927,702,60,41,644,555,146,270,307,184,881,494,666,385,340,118,321,735,886,341,982,587,371,696,306,765,315,223,556,406,423,102,269,272,209,848,177,932,406,721,498,619,380,235,602,620,280,542,246,127,134,63,704,714,198,401,653,597,770,326,78,109,555,561,49,411,677,912,29,19,519,262,77,399,382,539,701,750,999,122,897,230,937,900,538,795,173,977,436,47,431,427,648,748,643,304,518,413,753,316,309,251,486,851,259,845,17,888,206,934,216,622,28,291,510,84,774,431,934,484,136,204,665,699,208,942,697,198,59,751,209,360,948,110,1000,752,962,630,735,568,398,177,741,427,177,979,734,227,715,352,272,676,479,807,881,650,810,110,625,432,340,355,211,45,9,336,737,34,651,813,83,625,811,206,878,433,742,212,788,225,217,89,968,992,839,980,731,948,163,294,847,617,311,882,461,817,469,100,753,945,130,540,531,705,666,624,875,695,573,647,673,368,248,896,405,734,15,498,742,890,997,536,319,115,598,430,321,740,21,859,970,544,53,157,237,780,237,80,770,70,995,781,966,714,288,378,853,602,106,568,287,315,999,190,748,991,704,909,765,96,238,336,703,29,704,172,142,922,930,973,645,567,617,371,560,609,116,530,63,660,950,27,147,342,50,628,816,724,192,197,941,64,146,371,406,816,199,368,494,421,56,169,122,921,270,589,843,560,12,406,898,30,158,945,116,444,119,732,202,806,551,447,736,570,787,91,956,23,661,823,295,391,3,907,135,910,626,326,513,890,55,465,726,577,148,675,641,320,916,955,218,114,370,605,131,149,528,877,792,293,410,447,806,890,656,613,850,429,459,918,421,364,670,446,219,64,266,440,766,964,583,277,719,734,846,618,815,591,200,155,215,737,126,746,815,935,199,805,652,47,848,16,541,460,418,283,879,136,538,390,15,137,282,681,535,728,95,444,446,725,608,721,714,710,200,529,792,428,38,993,614,22,931,376,318,202,25,59,732,286,161,222,781,420,994,68,515,17,954,248,454,354,78,773,849,308,168,450,316,939,20,904,24,282,273,403,328,689,522,614,735,772,514,514,961,270,41,879,632,106,335,686,570,963,683,935,382,863,31,339,440,339,438,103,972,654,871,415,16,189,161,547,5,625,288,370,430,910,57,164,813,476,929,795,657,109,359,570,562,91,888,321,44,887,36,86,384,415,576,660,14,32,702,332,535,501,0,706,432,563,906,977,161,183,264,250,15,582,91,451,221,108,179,463,501,18,227,47,364,658,220,843,954,658,614,276,87,306,614,857,70,960,353,491,763,49,254,667,777,279,644,243,517,437,794,837,363,894,595,314,26,775,633,830,154,593,406,62,617,405,40,192,756,902,563,965,126,211,535,197,901,542,557,580,402,938,248,230,545,119,230,35,542,527,989,910,444,431,635,663,760,859,870,979,887,412,742,342,514,366,969,822,117,557,453,360,818,811,548,532,222,698,438,617,183,4,876,956,347,917,795,831,720,399,794,789,182,117,86,719,583,767,870,545,441,81,882,551,461,107,983,570,526,872,360,101,592,786,882,411,144,367,380,724,530,555,453,41,49,688,195,834,657,230,889,908,719,414,489,670,112,190,629,924,370,370,614,297,238,463,412,164,864,59,808,456,482,504,809,978,414,152,769,189,286,1000,404,361,658,684,294,427,136,296,651,27,896,963,846,444,85,582,563,492,196,387,619,94,216,637,394,666,811,22,24,493,939,562,262,784,484,1,441,550,517,591,995,332,482,73,240,229,410,288,203,223,991,816,164,209,998,488,736,698,852,602,635,303,266,857,172,661,948,824,400,114,502,177,768,995,753,445,692,987,746,7,508,428,377,747,870,260,110,565,46,732,298,92,255,972,4,732,14,442,643,643,511,538,927,699,843,627,269,544,859,124,846,775,656,88,117,53,466,720,563,615,921,426,512,171,622,902,84,926,311,818,645,407,603,139,403,844,920,519,989,189,126,390,300,619,983,962,849,707,686,824,662,836,343,562,610,45,215,738,749,400,781,724,139,366,183,564,355,998,916,365,736,224,328,285,396,898,597,221,396,392,939,148,13,717,268,724,478,374,187,284,739,364,662,793,476,73,262,465,672,187,20,504,405,933,976,774,301,895,439,612,40,879,510,475,878,786,151,533,547,856,436,701,190,697,361,166,969,693,555,872,811,729,360,827,149,679,10,477,825,198,592,679,277,397,314,738,726,596,710,630,333,247,548,26,658,759,235,894,677,311,665,938", +"35,197,98,720,70,858,818,611,935,641,695,896,894,408,315,207,503,985,884,694,274,385,437,835,578,178,101,88,932,351,191,931,756,398,471,836,346,81,334,764,467,908,21,313,383,168,829,545,185,646,652,331,529,164,160,593,479,987,94,409,65,118,781,137,327,321,847,69,149,54,404,451,140,960,691,954,881,305,851,29,144,24,201,679,77,985,883,676,388,320,568,191,515,706,186,722,916,752,453,420,449,568,744,885,550,821,882,135,340,582,234,870,242,276,939,176,136,841,931,165,696,984,429,443,107,99,45,463,310,134,116,294,815,99,674,409,741,922,85,686,652,439,462,359,650,959,215,736,833,992,619,585,883,94,103,618,515,438,736,70,468,298,519,369,446,567,874,368,875,710,962,925,467,998,721,588,67,406,367,449,378,40,168,214,902,473,155,255,390,589,205,183,149,62,472,393,118,546,931,897,178,820,581,887,253,184,910,487,978,989,428,650,882,812,430,384,50,721,555,273,457,926,877,694,359,42,162,798,964,513,857,465,426,972,597,987,55,269,522,313,89,41,921,902,902,433,131,192,661,376,365,224,838,712,520,920,30,100,178,885,69,715,939,528,672,307,102,628,280,942,799,962,747,672,312,821,748,553,810,110,684,870,952,390,334,273,449,214,998,75,707,452,111,123,280,724,757,651,31,831,196,438,735,390,373,993,778,575,329,897,665,299,437,372,160,312,883,715,987,210,387,17,494,71,881,839,129,518,601,70,129,679,449,56,702,58,31,902,785,965,709,500,304,997,444,965,31,505,556,534,721,739,801,767,102,344,386,840,98,901,158,453,118,995,170,917,932,815,876,172,846,202,60,816,935,761,876,626,446,353,787,658,418,824,444,733,333,495,397,896,261,991,759,387,738,948,917,732,757,646,854,973,906,220,594,297,756,815,265,181,786,444,641,698,979,53,36,734,587,478,58,208,129,310,937,904,56,530,188,752,627,421,806,367,440,648,622,298,8,208,710,873,308,13,624,352,357,830,124,464,231,18,675,458,61,835,419,913,191,462,498,941,563,178,277,953,398,376,667,657,620,291,40,231,340,862,966,529,195,584,908,920,129,582,274,62,860,994,180,273,424,754,185,927,602,395,352,884,560,579,863,748,279,176,249,784,634,340,834,532,367,898,539,153,650,305,792,47,99,935,956,854,957,268,965,272,625,14,448,861,18,346,553,225,29,592,19,570,706,0,250,244,479,991,860,492,526,435,590,619,447,912,389,278,190,456,914,137,99,322,267,928,43,464,682,705,95,437,163,681,451,626,914,738,378,497,499,311,422,40,829,510,168,466,302,766,573,945,596,548,23,361,212,325,15,62,34,229,200,875,779,978,579,325,764,312,15,383,49,67,375,94,212,45,98,84,193,449,441,493,432,678,801,205,875,809,80,111,862,99,663,256,160,155,18,974,179,927,796,550,147,246,96,628,396,74,708,230,948,963,846,254,501,258,441,427,857,372,465,349,678,97,629,153,497,747,746,434,53,160,756,229,215,943,581,625,983,687,155,958,132,345,63,394,427,221,916,256,742,979,387,542,483,341,129,745,128,915,188,222,375,469,110,51,140,525,667,405,569,889,622,896,844,255,344,422,306,382,808,859,884,152,59,557,816,762,75,901,889,419,456,769,372,922,210,183,225,391,187,675,214,876,408,795,223,219,959,882,990,992,984,6,345,192,717,62,951,158,363,463,516,385,106,613,792,762,703,227,575,507,858,690,392,411,383,222,227,172,915,714,314,694,419,834,682,19,89,815,947,416,183,534,445,428,456,248,483,567,240,525,131,224,190,123,616,139,965,647,419,30,229,809,264,281,255,466,305,220,926,693,920,948,200,954,261,776,114,779,432,926,661,783,626,172,257,796,922,963,885,57,63,44,877,174,453,167,169,568,284,710,8,3,719,413,400,738,587,860,818,905,194,275,476,266,70,829,777,409,109,971,443,862,189,143,456,883,666,548,805,675,809,985,920,332,155,294,823,818,677,466,465,625,442,126,567,582,14,913,515,579,384,311,278,222,908,471,630,695,299,85,302,36,657,372,281,864,29,56,922,491,301,137,800,899,719,451,89,240,164,773,710,143,82,634,659,540,744,311,203,683,768,186,682,72,914,251,132,115,906,881,616,695,139,197,394,7,822,521,723,242,180,44,224,288,34,232,638,433,180,267,677,507,969,871,872,235,204,423,497,691,633,736,475,895,115,542,859,562,18,726,669,838,365,447,647,600,571,560,499,200", +"456,991,165,820,57,767,917,932,674,497,390,213,930,776,434,402,207,68,830,199,147,734,679,303,768,634,848,588,644,493,526,614,749,218,654,830,128,226,545,254,708,530,120,819,172,80,752,790,508,27,744,820,227,351,523,92,549,27,336,626,327,903,202,100,971,752,606,296,550,152,598,325,87,932,281,163,443,175,51,305,672,633,897,732,610,326,56,211,337,147,53,426,946,147,840,620,454,900,790,673,443,785,693,64,629,94,556,577,822,21,408,803,727,439,783,182,825,182,299,668,584,737,899,53,356,664,360,700,686,410,864,418,573,548,408,437,200,504,332,766,518,713,958,43,393,386,749,742,517,645,764,394,927,848,326,391,104,746,934,148,132,714,715,823,979,66,879,192,720,547,658,579,88,578,960,196,47,150,488,469,909,542,552,704,406,411,133,115,407,636,168,121,637,402,740,932,220,718,724,997,127,146,637,460,830,979,511,95,156,832,312,757,624,730,435,919,529,120,58,487,273,673,81,366,361,186,744,421,740,538,510,990,192,645,873,612,204,368,346,361,950,352,742,589,662,334,977,636,825,204,14,812,579,319,285,964,491,466,298,69,579,851,333,240,109,99,572,158,453,566,785,404,984,918,663,816,588,329,756,266,788,743,275,73,347,994,867,488,565,337,613,796,57,386,973,688,316,52,220,896,725,16,797,633,70,486,141,586,844,938,82,497,445,603,438,930,392,281,953,127,206,937,103,401,824,497,272,783,611,279,286,285,922,600,669,883,208,987,994,967,222,533,904,127,528,978,957,992,743,363,882,141,696,406,324,217,157,19,600,399,700,835,95,154,807,571,997,361,948,273,76,26,47,357,364,224,31,594,268,660,634,487,142,793,484,256,67,289,760,749,995,721,69,920,945,523,40,501,874,649,860,673,670,663,79,486,729,740,589,124,143,73,612,681,394,223,953,458,811,80,456,355,529,33,407,802,819,813,76,224,94,246,318,55,351,604,60,847,863,162,488,655,734,814,160,467,860,340,396,675,527,811,363,542,272,466,904,323,156,22,309,411,766,17,571,10,232,366,629,232,919,495,162,308,85,884,500,250,111,808,549,380,972,699,108,855,547,538,867,773,644,242,631,976,984,166,284,17,398,567,141,276,760,246,732,724,950,946,41,178,239,938,595,24,237,107,595,787,6,949,864,984,696,920,834,521,350,696,839,827,965,897,744,383,931,894,672,791,432,250,0,488,335,158,712,37,781,197,895,433,809,612,499,902,841,186,224,489,172,468,143,63,973,772,611,743,49,337,491,111,820,828,781,989,350,77,96,579,422,590,327,81,740,943,530,931,514,473,796,248,54,685,451,459,471,699,658,556,710,74,810,829,904,376,831,716,639,512,76,987,501,461,927,301,76,944,112,30,435,955,430,838,663,86,469,292,164,431,433,917,420,443,251,587,495,651,730,914,925,225,983,414,210,168,796,146,349,358,653,67,642,515,351,936,807,504,25,291,455,11,616,736,119,109,18,593,924,184,828,268,54,495,511,28,143,803,202,530,220,301,701,343,728,452,732,423,948,118,648,672,944,693,819,909,147,992,353,253,751,400,389,682,751,611,96,730,137,744,203,307,649,513,649,197,226,376,569,219,827,796,77,963,904,140,685,819,159,226,755,212,298,763,182,655,548,162,64,518,444,592,986,636,642,181,512,948,959,491,510,693,815,312,943,777,509,807,424,65,276,833,792,897,818,441,946,547,611,775,708,419,144,508,92,611,642,31,105,510,489,126,512,953,100,706,854,213,327,950,602,815,260,720,81,362,761,395,107,274,508,371,791,761,687,376,459,441,351,586,828,992,736,432,282,965,120,171,114,347,994,602,569,553,408,84,741,266,878,610,764,823,905,497,857,287,932,189,580,292,600,436,685,827,128,259,891,511,636,420,712,629,662,978,516,575,842,669,677,429,490,779,430,686,6,50,426,694,373,518,207,497,784,437,265,53,526,119,976,516,517,374,114,758,60,418,602,391,199,987,627,643,217,108,519,684,24,539,916,275,727,921,835,579,38,577,945,420,439,475,790,758,92,383,323,16,740,736,454,142,33,812,378,881,32,713,73,125,317,344,26,192,743,227,648,831,919,456,990,417,831,7,498,287,409,491,769,20,17,853,679,690,877,80,630,231,838,768,946,63,463,457,808,200,852,272,350,536,257,270,136,746,648,534,585,657,186,257,529,207,699,852,170,113,830,407,670,398,526,293,364,381,546,71,983,594,788,906,888,26,106,259", +"795,995,409,766,62,632,306,505,536,654,385,558,890,625,966,862,705,42,556,604,656,306,185,288,436,12,978,720,726,762,215,884,38,323,658,479,234,19,982,918,947,438,148,231,171,848,235,138,193,691,343,114,773,855,246,327,809,40,331,789,704,358,818,429,498,452,201,494,955,940,967,27,764,627,859,51,199,618,856,51,931,153,209,989,976,2,31,410,701,372,787,127,290,932,864,940,961,881,63,864,718,803,606,501,587,823,264,819,544,749,753,273,46,639,797,316,354,675,127,973,56,776,394,115,833,487,742,945,746,690,138,417,799,49,843,762,884,941,335,173,39,404,118,781,237,380,5,40,176,425,862,535,532,506,644,742,573,733,766,229,43,237,428,815,987,439,487,615,960,704,332,949,324,965,551,388,125,737,222,374,952,448,474,377,553,294,164,492,851,165,473,756,561,730,130,386,577,168,200,531,356,263,73,884,311,548,578,872,963,143,196,205,190,341,634,508,744,795,569,748,127,720,592,103,976,907,946,984,496,445,109,867,638,73,392,989,573,326,256,797,466,176,148,619,840,956,90,280,515,173,828,955,896,950,385,972,632,129,217,613,566,911,830,905,100,314,841,304,678,340,231,762,452,347,706,84,403,320,54,781,302,61,325,476,748,554,107,123,49,67,426,729,636,954,158,410,279,712,933,97,962,859,981,889,181,796,937,426,706,355,506,497,635,218,585,237,540,174,743,464,879,220,13,18,393,889,257,188,637,880,600,766,713,216,158,296,730,433,938,470,199,678,305,811,449,935,960,405,428,730,718,292,266,862,646,581,619,658,678,133,360,389,159,602,907,618,904,59,150,457,746,42,204,935,226,933,911,281,85,100,223,896,800,685,947,158,656,285,943,16,517,348,415,480,642,27,68,706,553,102,512,383,442,629,429,961,302,248,399,85,634,717,107,99,707,833,152,864,623,173,759,347,494,733,547,310,283,929,6,294,313,186,506,903,691,342,403,703,350,84,166,287,707,252,836,907,704,250,260,955,246,905,551,68,763,987,862,987,510,117,991,671,816,957,648,674,274,965,26,57,873,442,826,737,652,136,19,550,856,244,949,73,509,194,587,397,455,829,191,525,825,459,862,76,923,978,599,112,557,635,108,61,134,172,205,989,497,363,495,678,963,853,709,892,999,828,972,787,609,209,270,291,644,691,126,540,10,363,335,667,900,764,586,157,78,705,827,120,563,244,488,0,208,312,161,360,128,782,129,806,777,423,819,445,123,954,881,627,419,771,941,913,177,215,177,690,484,651,563,451,824,580,664,381,534,774,979,974,54,215,774,824,477,258,73,123,93,447,998,492,794,196,206,139,693,69,720,83,49,246,147,145,118,369,818,755,333,247,773,769,144,539,104,283,654,655,787,707,285,655,685,335,237,534,172,878,565,322,988,434,852,577,463,306,32,25,616,251,479,394,322,595,723,160,55,133,302,416,165,975,806,530,270,49,374,459,958,747,520,854,720,529,716,378,909,884,500,778,262,250,653,601,562,375,345,935,985,337,212,366,597,475,847,673,757,878,293,262,635,449,653,644,144,394,316,211,622,909,212,178,18,98,6,826,444,332,306,786,686,960,440,89,410,15,576,389,349,307,930,316,848,290,778,219,7,512,490,197,561,417,572,32,484,933,151,945,979,22,153,318,306,100,857,793,52,682,917,264,276,19,493,999,482,685,464,88,654,127,737,977,664,374,145,131,522,2,587,96,418,298,127,766,120,26,189,111,556,672,307,384,723,5,235,942,614,718,425,187,721,339,58,588,927,103,584,654,731,146,574,567,277,736,606,884,984,243,546,364,681,976,543,795,98,366,507,773,997,425,77,542,42,117,541,47,735,602,744,629,652,882,461,511,844,724,212,941,830,565,386,826,848,727,588,707,267,682,354,634,970,116,191,494,83,743,396,955,746,904,566,411,615,352,624,618,710,616,729,559,589,904,753,917,902,61,359,656,15,395,531,90,629,571,523,493,267,942,624,182,328,701,560,317,678,940,265,37,258,698,431,79,424,377,959,90,469,620,774,628,634,611,778,887,644,826,334,319,513,597,604,150,568,786,96,46,453,184,813,494,582,140,754,417,521,394,19,221,454,725,395,341,57,157,633,830,392,952,299,273,29,638,823,222,338,80,821,857,614,797,299,861,387,338,277,84,890,284,218,756,940,414,592,93,562,537,977,893,581,849,629,225,245,816,865,150,742,29,419,147,139,264,679,79,833,500,986,705,512,458,524,282", +"615,876,238,328,893,994,400,746,660,658,848,157,128,24,203,935,568,497,257,829,891,312,900,782,444,466,263,310,97,841,769,774,900,826,559,769,357,564,416,709,874,27,273,293,818,211,428,374,659,165,334,827,151,209,267,410,928,875,376,174,126,377,216,480,494,103,957,884,653,960,508,492,747,902,240,789,532,251,749,783,687,112,390,99,65,150,742,481,864,629,648,159,540,775,192,422,449,265,556,308,312,6,226,937,516,986,725,86,225,344,386,856,124,872,673,747,549,227,605,987,220,567,700,411,211,88,32,987,361,104,275,280,302,265,576,124,788,902,180,961,633,532,338,25,935,401,99,225,974,852,339,410,506,283,216,174,844,527,58,344,399,993,177,3,135,57,525,299,156,25,723,816,268,875,792,461,127,593,240,618,700,114,190,553,644,4,539,434,205,568,43,832,778,402,857,767,908,925,950,537,580,634,73,606,132,890,791,740,305,940,639,866,885,958,657,264,678,639,968,187,582,551,622,850,255,139,220,65,766,322,937,498,762,335,579,274,220,133,668,236,578,347,662,755,820,311,150,549,43,894,855,675,662,40,420,313,348,497,982,365,611,217,795,53,7,955,30,158,258,822,598,122,712,302,674,271,18,403,570,847,150,232,411,911,942,378,308,599,74,495,117,486,614,489,703,377,382,146,475,279,41,496,630,555,143,411,372,762,263,19,768,666,66,888,716,715,840,854,565,56,184,259,626,270,334,104,829,235,938,32,351,234,985,169,397,489,781,4,465,739,318,361,16,331,927,618,301,546,626,574,176,313,688,980,82,679,348,592,66,88,362,622,5,732,439,170,642,334,32,141,258,554,875,763,780,618,988,19,869,226,216,685,469,578,59,19,38,692,8,237,691,63,616,607,285,526,986,534,216,819,547,872,793,595,861,65,122,778,199,194,460,740,855,39,440,926,522,123,85,944,743,941,790,4,266,341,697,24,534,251,489,417,995,810,340,870,659,97,529,745,407,357,954,695,500,520,134,373,163,30,162,702,969,487,769,411,911,320,84,216,871,727,493,914,622,63,819,241,921,175,544,948,898,392,21,654,19,562,435,334,612,646,298,183,492,569,282,512,217,862,565,339,413,466,950,108,416,236,688,413,918,565,360,121,811,974,25,19,865,626,49,284,524,546,559,409,23,316,403,167,747,580,947,595,117,205,433,803,867,753,104,885,465,725,991,252,664,644,906,479,335,208,0,867,755,227,498,218,81,79,986,338,911,824,477,690,772,862,304,48,641,789,691,565,455,209,816,882,746,613,656,628,275,893,151,513,167,753,298,551,705,477,133,429,20,564,320,180,870,10,742,441,577,256,186,607,193,138,719,992,779,980,332,218,783,681,647,352,981,341,463,136,183,509,104,652,459,461,555,965,172,702,932,247,205,468,713,684,946,253,454,445,163,391,528,272,788,1000,655,288,119,389,462,889,561,924,933,217,402,529,793,155,582,9,603,190,928,797,614,381,323,695,150,296,250,712,468,233,35,557,899,602,485,36,346,546,627,528,259,525,567,75,129,720,843,755,486,850,389,797,126,214,712,56,711,674,946,914,479,161,534,970,910,598,582,128,727,914,705,678,976,618,65,619,694,523,529,708,994,646,171,686,77,657,836,870,19,504,358,832,465,664,99,998,850,936,905,389,35,637,327,113,883,684,764,490,454,47,662,607,598,819,394,500,34,875,985,92,962,197,592,932,9,95,417,85,907,187,739,298,907,273,817,485,577,604,866,564,590,645,42,931,395,444,306,67,287,40,652,731,325,304,861,631,595,572,511,345,864,120,104,753,450,904,448,524,426,309,297,231,188,18,898,979,654,954,893,85,893,917,88,356,517,78,934,632,966,186,34,708,122,129,662,751,100,909,435,625,696,29,278,257,651,445,913,30,648,965,695,538,133,272,89,790,184,259,627,82,548,463,403,526,862,682,808,619,675,515,585,346,134,674,726,548,872,692,420,224,111,585,275,770,841,540,186,388,136,196,590,846,718,876,633,282,431,942,848,801,258,157,395,633,314,874,803,611,82,384,553,351,259,104,606,984,161,425,573,343,942,120,263,84,840,337,985,591,20,519,727,695,461,749,124,594,691,110,94,476,257,500,221,355,973,446,836,178,790,542,731,824,314,209,228,758,957,872,722,250,873,965,437,320,885,614,321,309,101,750,119,500,745,266,898,170,886,218,83,878,450,884,70,608,259,84,924,282,398,221,414,267,427,684,26,675,277,460,558,626,70,839", +"349,5,94,198,315,759,694,334,640,987,126,171,196,845,313,250,307,97,302,468,616,7,751,750,457,918,157,242,671,306,255,195,163,295,393,557,355,38,71,190,932,120,316,710,676,782,331,162,245,950,439,150,2,646,265,1000,537,177,517,124,552,44,148,928,948,269,502,983,812,683,43,996,522,126,395,726,903,645,822,523,106,861,483,10,88,712,999,850,868,639,427,205,919,34,29,69,960,782,667,366,948,307,694,89,963,519,407,158,908,94,870,349,767,5,702,765,624,375,748,796,568,22,677,771,956,273,500,628,98,641,159,779,323,221,363,432,541,331,372,437,946,945,156,646,530,884,881,80,97,640,757,377,797,380,663,307,638,790,596,782,987,906,719,748,240,470,67,127,820,327,631,882,79,831,253,690,748,372,388,554,90,565,646,53,400,611,522,96,186,121,267,529,153,313,213,227,905,71,588,529,547,794,646,80,446,389,274,523,724,117,443,152,559,936,629,799,808,674,843,425,51,128,405,315,715,640,772,339,931,897,241,109,21,528,857,965,223,971,790,677,249,232,718,1,779,674,566,638,705,20,254,823,221,312,355,313,845,185,438,137,67,395,919,326,917,718,458,903,610,166,415,855,376,881,493,590,260,956,127,786,859,81,672,912,231,143,990,26,29,313,787,55,618,652,127,714,96,369,239,651,95,98,85,801,3,336,53,79,53,342,119,938,764,750,376,815,43,971,463,846,714,549,993,713,957,162,760,159,391,868,359,232,319,759,542,408,730,534,927,30,492,687,405,996,844,904,809,702,773,251,889,380,29,120,448,633,258,836,378,340,161,50,809,10,574,212,923,285,699,204,493,767,866,830,925,522,108,367,405,87,892,970,42,772,455,244,161,792,110,305,1000,796,57,559,574,661,119,433,517,246,47,115,145,608,810,276,593,454,243,472,900,704,749,884,755,419,45,248,749,35,351,817,714,383,223,406,121,216,349,678,161,589,912,755,950,518,300,315,545,804,212,556,292,9,890,636,11,993,34,764,874,173,517,182,87,298,196,485,10,669,485,47,856,597,542,248,633,495,413,625,402,284,333,493,598,206,767,246,85,269,858,121,831,435,165,209,944,18,839,591,597,443,159,672,618,241,371,494,821,658,447,467,889,659,767,573,677,740,468,506,971,694,78,173,529,229,779,373,962,277,315,561,254,89,345,496,855,650,646,158,723,664,383,882,190,715,783,646,977,991,158,312,867,0,496,407,696,884,338,487,451,842,636,182,233,855,283,556,571,729,523,814,851,448,469,868,609,973,465,692,726,220,678,20,618,195,941,58,897,256,773,788,117,751,695,457,751,258,712,542,253,138,966,771,308,227,47,398,210,531,95,852,560,94,918,202,835,519,988,839,316,506,461,736,772,720,124,572,634,396,465,886,38,218,594,449,190,985,970,43,300,240,890,546,807,419,384,855,572,997,643,938,989,449,25,217,230,168,930,254,984,999,102,621,143,643,704,62,41,919,916,891,736,408,471,670,274,177,295,742,15,96,246,643,191,304,595,397,106,26,770,965,738,494,719,245,992,709,798,678,275,140,731,762,183,893,860,815,699,757,808,894,883,72,430,415,86,769,878,379,423,376,258,224,30,370,826,905,548,693,614,194,790,112,571,839,945,310,897,760,736,341,294,760,607,375,707,457,617,486,930,515,971,77,397,561,263,179,692,172,3,967,221,247,993,205,830,885,975,921,496,341,202,578,519,730,939,836,48,273,375,453,288,906,918,415,66,607,105,52,737,294,974,321,951,915,168,101,214,978,835,545,845,619,418,255,223,417,825,757,355,526,622,228,987,773,128,953,493,462,6,602,290,873,483,435,727,104,168,615,434,876,229,243,702,530,628,393,89,595,804,2,924,841,627,284,473,839,233,979,837,130,709,474,832,527,52,50,496,661,928,313,900,581,420,498,196,836,9,559,308,991,341,225,861,213,432,285,459,86,437,165,55,522,142,149,707,812,886,980,201,206,188,936,361,657,444,796,534,45,629,808,786,318,336,113,613,828,909,377,13,840,797,371,715,40,73,809,886,742,496,441,772,8,327,363,104,530,69,444,313,855,359,792,922,949,381,822,651,596,441,640,356,672,631,771,854,948,397,377,213,976,688,847,621,691,39,764,95,369,455,57,928,21,395,378,205,383,697,960,31,689,467,538,809,786,765,393,470,327,699,558,298,919,147,275,416,307,569,704,703,627,249,694,769,32,259,294,523,78,468,947,587,705,651,791,186,957,827,349", +"597,342,442,794,76,462,43,864,843,812,265,583,55,930,835,621,922,430,546,174,664,966,96,964,592,606,693,896,381,925,421,94,268,341,600,331,24,9,822,241,630,603,427,47,578,282,660,47,212,802,649,832,352,480,345,112,672,717,46,390,470,105,421,545,320,836,976,45,394,603,680,494,395,551,28,894,514,753,525,705,700,702,606,738,287,822,600,538,544,607,897,329,195,418,45,47,88,431,414,389,377,248,60,553,113,694,725,329,745,325,222,528,481,264,342,639,966,266,638,500,868,525,982,996,472,241,474,324,139,533,325,336,528,557,967,781,204,361,801,418,113,754,217,61,801,814,771,807,491,525,127,562,2,542,722,215,379,134,376,333,360,328,123,466,58,949,474,115,980,537,605,42,278,871,397,678,800,894,438,561,889,846,270,159,842,718,827,583,988,526,403,85,372,288,595,378,105,208,436,699,855,418,106,488,524,734,568,402,807,583,283,592,57,158,511,999,560,676,868,242,113,399,265,110,229,374,367,620,332,791,297,990,446,834,439,833,595,835,120,904,876,942,880,331,506,726,165,69,592,133,335,511,211,486,111,474,540,629,971,547,262,925,468,981,183,149,935,334,354,7,296,297,51,466,582,984,937,94,701,370,256,241,571,72,764,881,392,409,621,983,11,359,261,606,905,309,419,58,362,300,262,469,147,673,439,610,106,120,494,500,668,168,400,534,77,725,884,150,348,211,49,196,626,160,873,942,349,128,660,330,628,377,191,147,792,925,996,407,886,847,20,624,289,977,946,231,256,732,885,490,398,58,734,59,64,950,386,45,817,459,513,233,26,949,54,525,253,170,473,83,134,315,145,964,388,382,942,729,308,407,47,1000,945,647,405,193,924,190,575,808,684,424,614,656,730,510,905,387,302,279,369,916,170,223,44,662,562,949,950,318,97,992,941,813,496,284,876,997,88,196,586,481,807,862,111,485,605,287,849,251,630,657,233,654,858,894,669,404,222,862,82,550,420,791,2,494,354,984,142,405,292,890,602,247,662,86,832,424,110,709,477,647,986,407,533,487,617,891,825,266,747,409,294,355,113,252,599,589,998,405,197,554,805,682,351,556,988,489,615,894,485,812,985,420,178,13,235,956,470,192,830,857,996,737,788,99,533,850,323,99,97,566,895,823,539,155,729,232,561,150,505,323,193,710,241,872,121,989,231,333,394,947,522,707,832,406,158,281,161,860,712,161,755,496,0,975,514,598,748,696,24,902,914,850,276,530,712,801,13,12,723,359,617,817,746,816,210,3,800,446,965,64,553,621,316,235,220,104,505,486,461,941,709,584,216,290,278,652,806,456,684,876,606,839,347,778,568,949,674,45,634,660,618,295,108,660,612,381,252,335,171,622,311,809,664,740,710,467,952,745,34,421,992,197,767,69,621,851,428,288,21,175,978,152,944,470,791,738,257,450,123,87,471,934,136,655,503,657,183,430,440,60,371,16,706,159,672,127,257,474,223,129,981,148,32,975,511,344,492,799,920,150,685,663,972,857,286,595,705,66,954,68,822,224,229,225,659,833,801,400,193,958,140,610,933,707,385,43,179,22,734,496,523,73,524,694,108,858,818,820,81,804,71,776,589,475,536,813,97,37,402,838,240,462,14,485,124,878,633,325,23,101,174,970,775,408,541,686,772,563,884,114,98,485,881,942,945,851,491,614,135,674,795,523,358,807,616,397,677,267,65,249,716,700,119,502,529,518,592,678,898,307,568,467,619,222,960,326,457,807,546,36,962,415,72,491,703,728,304,843,617,177,239,457,526,516,236,697,546,404,684,257,37,788,486,550,968,232,715,65,51,96,371,335,452,508,267,923,476,620,840,661,477,452,919,707,109,259,679,722,598,876,921,89,941,895,794,987,115,717,508,755,459,514,61,958,423,641,83,443,943,175,16,121,477,573,496,491,96,737,18,740,342,229,652,825,934,691,487,147,936,604,381,878,414,191,815,479,79,188,149,504,616,230,907,818,979,980,664,93,892,937,687,79,755,892,387,541,268,179,278,984,583,249,558,704,989,888,804,140,615,793,887,303,474,839,746,478,439,632,693,218,34,655,535,826,835,792,570,919,109,861,304,90,859,969,708,801,82,953,568,178,28,316,603,140,373,43,129,394,376,387,545,523,84,218,56,83,131,456,748,816,889,891,110,246,682,905,317,682,984,513,190,626,870,461,713,81,846,306,411,884,483,426,236,503,876,57,958,895,517,352,60,571,307,474,972,948,254,225", +"198,379,877,41,635,559,679,711,880,875,341,437,870,893,948,260,537,780,736,289,267,73,460,881,427,280,829,607,431,16,337,854,741,980,558,832,451,726,673,827,81,397,725,311,207,716,512,23,723,675,950,559,801,256,674,417,795,99,983,808,887,165,229,858,239,1000,128,422,961,947,282,410,907,410,346,291,652,858,964,210,254,354,66,285,359,697,243,242,886,15,319,481,929,12,168,258,700,463,193,171,172,474,699,591,900,919,314,691,80,813,494,81,972,17,415,689,901,947,165,731,283,237,840,340,635,692,932,7,85,354,705,330,985,199,392,738,706,800,921,58,416,112,676,899,755,513,322,922,956,112,836,13,758,752,11,770,338,583,749,300,171,308,657,474,945,525,340,931,80,653,10,831,764,139,911,994,476,689,978,907,943,997,990,573,19,791,380,399,8,67,265,781,511,597,91,634,193,8,465,948,593,345,925,178,952,279,661,745,595,151,446,570,901,307,313,430,426,319,330,277,766,867,682,770,529,475,44,597,858,335,551,736,785,620,577,507,677,693,976,519,189,587,311,223,119,630,584,724,335,789,752,69,718,740,12,568,697,996,32,685,889,933,795,423,818,195,182,800,224,128,388,813,740,924,295,283,35,298,623,829,944,791,284,65,312,237,554,162,859,994,988,567,991,664,769,483,898,981,498,871,725,658,928,48,683,946,533,724,425,824,242,364,647,740,280,688,820,385,676,615,295,449,685,668,453,197,190,160,427,33,357,671,396,159,293,388,438,100,515,492,269,741,611,441,573,514,543,820,560,646,781,123,586,549,279,657,303,889,499,417,160,253,398,317,94,452,482,819,400,234,967,223,532,350,996,6,494,364,547,863,166,163,197,953,309,812,407,900,752,691,439,182,182,545,352,227,262,489,15,205,381,73,127,725,591,520,894,647,990,664,606,616,518,680,777,338,967,899,373,86,385,732,238,279,210,987,241,254,495,474,702,215,792,359,442,956,813,904,933,717,294,765,792,946,323,385,714,959,855,278,507,319,959,940,510,776,249,875,781,376,820,599,225,176,950,269,423,675,512,235,655,477,432,846,427,632,686,991,761,835,17,594,550,950,35,778,426,258,856,12,147,446,348,693,948,724,281,968,617,50,922,893,449,548,313,487,465,645,200,751,749,460,879,371,660,232,539,323,303,856,75,680,300,377,954,596,685,298,139,263,660,774,582,633,402,936,89,842,183,492,37,360,227,407,975,0,695,382,813,605,692,431,424,760,13,754,906,806,272,929,184,32,76,819,737,4,442,292,14,641,298,599,130,250,171,750,577,645,812,422,866,549,300,401,407,413,770,234,822,647,884,735,171,35,329,832,405,64,130,989,880,984,622,137,182,916,759,200,153,800,762,516,181,729,58,246,611,868,176,297,415,5,142,226,940,273,593,111,747,290,880,889,354,471,618,429,422,22,837,592,765,282,549,858,839,308,730,495,414,751,345,678,633,524,925,297,600,553,154,931,237,192,966,208,765,517,402,569,999,246,737,646,689,610,588,243,15,819,442,209,565,721,748,126,874,122,24,855,495,235,829,917,848,700,396,509,639,798,740,750,212,546,811,364,164,825,509,1000,696,36,889,167,318,113,824,676,245,659,942,966,530,869,651,867,227,115,763,392,468,675,971,408,810,438,419,715,974,698,485,427,340,106,40,645,973,168,69,964,433,27,720,538,443,18,35,21,641,567,218,454,749,79,204,586,109,317,377,975,371,899,49,728,896,565,457,599,537,190,562,882,973,792,168,64,407,977,706,933,979,289,323,859,698,706,485,780,5,400,870,761,470,570,955,728,400,561,656,189,289,614,223,416,207,899,591,724,636,438,836,883,496,808,912,753,239,403,31,431,744,810,650,265,740,462,358,911,843,162,396,372,430,146,788,37,856,26,708,509,879,768,548,252,426,896,28,778,162,606,343,440,242,530,969,77,495,611,826,530,461,384,420,221,525,708,91,298,221,564,514,480,586,5,252,988,147,929,98,259,189,95,769,84,863,285,830,468,837,354,347,72,448,124,321,975,106,145,135,578,739,898,952,68,430,442,681,192,436,239,735,360,458,36,675,900,888,497,802,70,81,934,920,180,892,272,790,199,523,295,437,137,429,24,586,951,418,724,807,981,713,861,240,268,977,229,763,343,601,903,257,399,682,633,390,35,426,744,321,428,441,536,394,151,222,117,38,84,375,606,526,507,275,326,295,592,905,587,985,473,686,54,882,361,221,645,14,372,644,594,159,397", +"643,132,445,970,477,678,826,840,180,528,492,629,167,992,182,655,349,207,619,854,653,245,185,654,446,887,505,367,354,753,521,607,795,541,466,256,908,881,450,818,126,528,830,453,447,656,841,787,397,390,920,149,676,55,584,816,265,541,699,373,304,24,29,369,745,644,463,586,523,1,521,425,783,260,556,89,287,933,854,81,603,183,445,91,53,968,888,407,272,75,506,181,966,963,383,400,992,661,533,200,155,272,117,87,73,776,850,451,739,689,308,48,545,984,257,412,253,261,124,485,739,102,156,423,132,798,354,202,527,46,594,567,453,105,750,274,988,132,774,726,775,279,948,259,141,318,4,38,9,35,546,212,786,510,307,700,558,387,83,500,753,502,512,422,575,768,954,733,244,635,896,720,295,352,67,753,65,735,877,530,617,329,883,945,274,668,43,814,576,640,779,882,338,254,786,555,678,284,545,601,837,603,926,662,330,115,572,388,359,220,678,611,758,19,880,134,439,816,162,27,723,227,366,782,961,639,253,695,151,568,866,607,568,439,885,244,576,243,716,828,396,120,700,908,484,275,196,890,519,704,535,621,730,18,770,630,209,321,271,725,77,585,203,379,620,736,896,880,469,904,693,851,14,7,341,254,550,714,264,213,263,278,6,796,517,630,863,802,240,869,746,378,628,968,500,401,840,221,452,780,364,940,247,316,254,832,634,276,731,418,283,668,574,337,991,943,980,834,184,174,560,491,931,727,647,431,362,935,936,668,483,502,248,584,400,63,143,548,234,142,753,763,626,261,915,244,244,584,778,985,776,627,32,541,404,124,498,361,994,112,841,52,744,721,277,377,831,569,56,558,346,459,340,631,801,259,183,809,970,257,200,536,581,45,830,754,535,892,338,38,222,424,358,436,92,66,623,688,247,754,606,564,292,201,114,214,734,303,62,243,608,981,176,824,139,154,207,509,952,94,995,211,929,23,710,272,205,672,609,200,691,491,585,659,929,939,561,810,791,863,699,254,523,511,921,745,103,711,995,219,51,205,543,559,866,945,650,985,539,628,651,416,98,515,624,478,164,300,127,178,406,159,612,5,208,961,772,836,15,411,458,717,809,178,5,619,820,702,102,435,927,452,773,231,724,183,856,927,511,599,513,395,703,996,909,787,231,251,113,645,255,412,915,265,502,693,210,463,438,986,302,106,285,635,873,915,703,826,863,34,942,498,532,858,398,735,178,489,264,526,781,128,498,696,514,695,0,817,988,167,668,142,765,156,259,529,518,239,503,541,755,546,256,685,965,523,850,93,632,391,882,760,812,606,5,24,177,826,179,100,270,728,938,157,835,172,91,76,475,53,452,292,194,627,919,509,553,426,640,380,738,523,383,987,179,673,645,852,312,137,689,365,827,448,12,362,454,971,568,268,220,35,999,539,361,392,414,355,293,238,569,726,689,58,594,487,572,152,779,727,604,265,663,249,250,829,493,264,854,426,256,774,920,20,796,244,885,710,245,809,564,100,597,811,488,949,4,107,44,473,547,618,192,665,844,638,6,4,27,626,917,743,668,458,674,321,181,953,870,249,97,991,549,324,899,900,969,86,894,77,66,201,608,955,108,418,373,554,86,954,747,157,751,932,901,444,835,724,687,759,572,514,722,146,496,945,237,485,687,693,162,567,676,683,257,980,429,766,27,276,526,999,401,24,686,124,470,717,747,625,984,403,955,95,434,114,136,385,542,644,59,385,717,366,215,167,482,674,903,909,874,851,303,425,223,92,134,438,814,559,544,736,323,656,147,114,215,139,494,591,834,63,894,917,114,930,775,29,942,56,612,741,843,256,756,266,549,142,339,350,346,818,566,115,708,970,375,590,429,132,368,734,831,276,207,447,986,453,101,705,334,147,929,470,395,326,554,326,687,537,485,507,169,904,951,892,499,455,47,514,393,739,989,198,897,443,602,951,926,506,327,343,420,835,545,151,912,988,906,52,648,950,287,45,940,444,844,52,959,727,402,89,825,426,447,375,179,27,707,801,144,952,15,410,676,876,877,544,944,544,449,848,356,332,178,730,73,923,849,268,469,428,7,917,771,454,959,195,616,922,93,709,442,772,841,122,777,582,803,427,565,676,351,526,61,300,696,94,466,191,461,594,632,507,619,954,743,165,442,328,434,157,87,249,129,267,175,367,144,71,913,95,221,586,925,760,564,57,19,725,985,878,646,848,677,224,544,875,373,686,317,180,494,478,421,906,412,375,45,41,157,984,892,45,966,572,481,356,364,940", +"18,231,266,978,538,625,866,680,466,948,686,184,669,331,395,196,556,142,894,691,628,607,84,379,462,148,492,894,17,271,368,840,236,378,825,255,182,152,618,366,217,615,937,678,469,956,376,999,735,680,962,47,236,283,51,688,194,739,93,177,505,779,926,707,278,307,223,418,478,872,224,398,727,280,586,111,263,697,123,238,752,119,348,671,777,448,206,950,629,901,728,130,921,97,103,732,366,1,143,214,139,942,229,247,638,656,804,441,258,398,850,531,15,840,786,482,699,471,750,90,154,210,769,216,579,416,20,63,655,614,698,499,997,131,348,409,567,409,803,865,609,492,154,522,593,380,859,982,669,107,329,669,210,937,533,491,856,302,341,179,659,855,78,313,548,893,793,860,100,12,66,994,68,499,992,940,547,459,352,24,145,76,754,123,77,315,712,114,314,871,859,233,374,780,651,969,19,345,163,604,921,529,795,762,796,672,870,189,250,445,258,968,760,689,365,393,767,111,679,173,117,548,495,269,11,840,666,441,632,816,17,617,554,632,54,512,27,34,511,484,93,230,605,671,731,338,22,892,651,169,440,363,2,111,47,341,280,884,56,182,859,274,722,893,137,304,588,640,231,123,138,213,847,655,996,683,690,468,616,317,299,263,399,903,123,32,866,966,823,594,889,603,747,846,467,242,304,412,475,557,779,226,857,54,40,690,272,997,938,789,854,958,910,840,365,676,137,263,33,628,975,12,606,883,356,896,468,603,387,936,873,78,628,31,779,251,767,120,214,237,333,384,313,816,654,716,359,794,503,588,425,639,351,696,148,812,309,953,529,555,849,953,98,970,729,552,237,135,651,429,240,685,616,328,260,763,593,51,180,719,728,53,848,25,347,757,955,728,902,316,70,509,382,760,311,351,485,874,641,572,770,847,558,149,233,555,60,442,298,136,551,217,391,269,516,390,118,307,175,906,431,618,248,803,815,877,15,554,894,318,101,348,530,947,648,43,443,649,844,539,873,483,908,758,185,613,414,509,406,517,277,960,579,513,795,915,33,155,40,419,835,524,474,494,195,822,839,141,800,468,595,26,751,230,214,732,217,400,915,521,792,149,421,759,506,364,736,915,970,675,293,51,236,993,73,902,1,285,564,414,903,919,745,167,20,617,44,714,899,991,823,393,264,715,218,710,542,916,254,720,691,929,740,714,422,288,389,139,926,41,634,708,653,153,647,120,914,621,250,435,197,782,218,884,598,382,817,0,140,963,850,444,325,560,361,950,301,433,117,784,381,114,674,925,573,115,85,772,335,651,198,424,289,628,164,575,269,240,483,702,381,863,323,177,315,862,674,745,369,630,320,830,614,861,197,477,662,541,901,254,292,755,656,931,192,13,611,451,700,379,278,934,845,69,56,266,403,907,281,898,942,25,316,686,591,271,154,720,914,589,932,951,150,602,189,24,34,979,324,115,109,609,489,232,887,537,986,824,682,409,221,102,728,982,307,916,555,532,634,344,387,571,394,862,869,222,190,724,998,647,973,389,371,929,532,506,302,467,159,129,758,558,856,676,56,64,282,652,592,577,130,339,693,945,886,21,493,463,471,714,372,314,220,25,713,460,246,393,673,109,940,76,770,603,742,776,3,179,273,861,269,625,566,213,896,901,12,946,998,233,374,427,232,248,595,373,875,553,803,217,85,950,320,245,680,112,828,953,872,567,743,127,562,966,540,255,926,360,541,684,116,432,120,109,465,490,257,78,573,63,444,509,165,799,994,794,613,379,790,136,37,483,245,327,475,659,491,595,588,987,435,550,608,208,68,28,782,660,598,904,479,645,886,77,910,200,817,78,958,637,144,479,693,365,206,26,775,832,759,948,252,7,469,913,923,250,195,82,213,119,515,327,382,95,696,162,485,753,458,890,48,925,240,410,671,825,668,716,389,645,433,194,200,236,22,973,154,570,289,90,357,694,244,196,799,111,964,400,897,263,183,688,518,289,545,400,188,420,390,796,946,776,123,181,887,800,747,422,948,526,749,355,645,889,791,38,92,499,849,64,614,354,500,936,329,567,825,721,350,779,54,51,312,108,403,388,977,857,158,353,543,794,628,845,646,152,556,607,137,966,928,711,616,877,526,920,118,413,306,433,669,244,720,115,867,771,217,864,480,951,320,668,277,386,107,861,998,463,439,287,929,149,301,83,79,414,468,895,420,37,779,736,729,891,417,910,198,861,547,459,635,532,45,590,143,824,86,629,917,165,228,433,140,304,693,770,651,954,960,177", +"955,783,706,175,938,692,837,945,994,782,760,445,509,267,213,941,739,574,229,903,209,959,916,187,991,189,301,887,278,323,526,22,772,905,413,228,508,201,462,170,764,848,127,459,787,360,789,458,475,827,800,322,421,737,274,379,880,691,290,158,885,660,22,526,103,625,797,205,802,48,47,366,858,923,790,168,500,391,100,384,578,697,145,39,796,188,738,944,683,35,826,354,143,277,772,644,744,148,942,441,810,322,648,821,303,604,801,79,381,942,297,492,678,566,580,365,819,614,84,159,430,370,216,806,934,604,924,457,212,81,364,880,104,422,801,309,78,192,382,429,942,794,55,526,614,671,606,523,313,970,351,948,46,6,21,481,54,721,216,172,971,633,103,964,945,246,138,347,726,708,826,319,20,373,55,890,388,621,134,80,773,555,131,159,539,578,769,74,520,723,114,538,321,810,431,298,415,709,184,804,328,884,958,461,61,672,209,720,150,863,197,750,131,960,449,523,904,350,611,942,673,190,270,338,495,548,761,672,583,306,350,168,359,213,341,489,449,663,891,66,98,256,226,823,349,312,183,115,413,143,435,174,20,902,617,581,50,983,300,7,816,271,43,791,247,857,153,460,834,404,589,326,99,434,657,558,248,427,23,632,778,210,936,788,925,801,855,892,558,751,962,649,637,666,609,655,883,641,707,992,951,368,870,169,226,750,832,302,281,625,618,230,665,370,986,234,363,461,401,172,186,387,63,878,157,951,47,739,246,358,569,832,509,387,400,792,105,900,300,37,966,697,600,79,262,125,540,734,914,945,499,648,343,247,447,531,855,409,852,345,850,832,250,168,261,848,517,815,560,53,17,938,885,478,548,817,141,262,477,36,997,438,137,113,909,515,185,693,547,210,247,745,133,11,379,365,186,961,288,627,553,528,403,120,899,737,583,736,1000,42,909,240,4,766,859,847,313,829,631,712,730,326,222,827,942,50,126,706,565,773,628,715,205,399,806,335,848,952,563,284,808,614,85,31,7,561,915,616,786,168,228,425,14,487,540,563,208,294,340,25,130,525,442,425,638,693,774,87,79,799,263,227,476,582,424,65,943,668,545,660,739,585,135,217,337,637,320,935,931,117,551,468,590,246,358,135,783,960,164,599,973,675,636,16,37,427,676,68,545,432,367,317,174,99,693,618,703,998,193,788,92,246,277,686,93,967,741,996,98,540,606,765,744,219,64,674,934,670,15,590,895,129,81,338,748,813,988,140,0,600,305,793,940,783,502,283,390,581,584,689,342,872,714,584,692,378,983,247,284,803,895,512,653,807,505,331,926,550,155,716,849,9,533,456,505,862,157,630,919,337,707,306,222,344,67,99,553,212,289,779,16,86,229,664,522,129,207,367,191,502,528,959,867,618,361,195,81,678,155,454,110,379,941,545,652,712,311,268,246,346,661,724,849,512,331,662,495,880,921,494,153,357,533,585,970,641,684,958,367,962,672,225,796,79,365,924,64,557,477,988,695,774,654,116,379,357,379,812,492,342,714,943,600,92,997,339,724,775,415,91,392,586,326,663,832,836,244,320,626,767,92,139,994,766,94,825,510,217,985,613,786,381,732,758,260,485,458,235,302,881,296,625,335,770,917,596,206,994,479,783,660,13,363,60,69,37,305,96,550,535,710,11,460,810,804,964,84,69,563,704,225,230,905,749,709,608,816,433,49,7,106,49,764,417,926,651,284,396,822,892,586,619,276,278,637,27,139,852,465,819,872,692,95,548,685,68,628,365,187,494,455,560,423,222,714,308,470,651,965,406,169,802,397,398,88,658,971,194,736,571,293,381,390,588,54,997,62,479,708,541,806,784,164,348,370,570,170,194,572,79,526,854,683,180,787,719,896,327,368,41,179,849,512,362,670,585,738,145,344,192,785,70,632,514,69,488,90,925,612,208,731,21,990,657,78,117,85,520,754,59,576,809,60,340,961,23,45,129,55,50,294,495,668,190,473,975,489,904,171,908,349,717,837,424,208,392,485,535,546,911,966,402,266,686,801,621,800,188,332,843,720,949,580,770,993,974,584,762,793,883,717,403,549,629,328,15,963,817,960,25,64,813,60,752,330,340,388,896,947,934,930,867,463,966,886,457,965,506,713,212,228,489,725,525,604,686,26,160,192,14,703,376,629,756,416,835,735,761,713,215,285,34,914,348,206,448,91,643,301,894,129,636,204,760,587,617,470,244,710,405,982,860,383,395,365,933,350,312,621,489,479,698,912,897,912,846,750,591,565,212", +"531,59,312,847,757,897,311,8,894,713,525,787,715,642,237,112,366,680,388,562,656,143,529,646,666,416,633,569,940,13,496,834,489,532,150,668,877,219,399,847,44,576,241,935,326,886,999,561,558,631,985,272,904,978,91,155,51,513,52,979,850,609,633,809,509,403,203,718,323,686,805,544,663,21,216,200,922,169,830,233,989,944,975,279,987,970,150,938,288,861,242,815,181,905,639,483,248,991,825,314,87,134,538,260,802,447,518,270,711,655,88,86,124,124,716,496,32,928,824,210,343,521,216,29,944,518,167,173,160,756,385,293,345,564,822,608,634,860,834,236,964,786,149,804,20,776,624,780,632,654,389,33,343,14,857,763,385,135,607,948,667,259,934,628,616,121,956,209,286,577,410,325,14,671,771,928,663,315,267,273,370,418,246,10,104,950,634,881,273,183,466,91,387,211,228,65,777,931,690,242,769,605,277,820,723,281,170,52,638,222,409,572,741,767,784,539,442,803,548,881,877,796,941,860,409,45,858,525,885,931,759,409,399,341,788,341,937,537,7,957,826,808,648,635,728,164,867,498,90,910,849,861,366,60,39,919,817,64,807,963,939,446,652,921,960,544,965,815,70,704,7,693,904,60,327,670,467,858,447,580,258,908,706,171,339,840,536,527,600,730,909,281,500,963,232,678,599,91,730,665,209,58,2,261,525,68,326,886,631,473,148,557,426,225,569,486,17,615,394,348,212,965,472,228,220,242,940,230,393,65,446,825,313,115,925,487,948,28,257,314,401,362,133,704,823,192,788,517,194,885,226,292,671,437,15,123,259,11,461,372,977,539,275,833,680,907,874,197,528,8,151,288,885,409,988,867,411,918,572,598,187,376,366,3,259,78,154,177,346,912,388,190,605,370,534,304,526,776,787,551,991,92,646,22,686,929,165,781,412,850,624,160,740,624,358,794,994,82,857,312,200,663,84,712,746,78,897,319,826,793,182,290,877,678,503,116,670,992,404,658,904,950,933,648,599,897,661,625,688,492,773,559,993,284,290,909,181,249,240,11,223,846,221,890,919,560,344,639,849,447,484,743,103,400,807,159,65,483,518,965,346,361,613,94,839,219,635,322,798,396,660,937,34,214,584,455,355,432,998,213,919,861,362,896,776,357,511,57,286,414,602,8,314,251,148,634,834,275,513,244,760,312,7,965,859,631,183,285,304,60,927,437,184,408,289,106,664,320,582,619,433,806,79,487,696,605,167,963,600,0,594,970,990,664,76,43,309,3,208,818,900,978,896,887,556,701,261,880,362,110,76,558,360,915,739,525,580,961,732,604,648,834,123,690,689,575,162,969,412,131,198,988,867,493,586,171,588,308,782,633,122,515,857,878,56,462,716,321,285,139,529,405,768,99,972,265,367,9,714,564,527,343,456,206,181,469,574,587,171,272,102,249,660,427,170,706,468,191,872,161,345,245,259,807,758,94,414,644,875,316,961,670,428,540,807,536,646,779,357,538,630,755,81,291,315,935,280,250,133,422,989,127,311,223,487,677,514,108,630,34,994,654,142,116,612,575,152,698,398,604,771,430,935,491,29,690,178,829,300,669,829,328,797,460,67,496,238,912,826,180,895,261,29,250,606,499,8,332,642,875,717,882,787,959,364,437,241,380,693,803,335,106,916,729,741,114,66,105,355,439,752,703,146,531,142,385,431,983,542,965,623,911,467,286,735,275,681,779,345,398,125,989,603,742,179,960,190,76,71,837,244,500,239,866,260,373,191,122,431,257,246,956,461,410,6,823,514,106,797,194,641,139,808,240,483,27,820,973,752,910,29,603,550,431,883,656,203,883,932,239,559,63,656,799,542,682,6,942,1000,183,622,631,36,344,642,936,240,164,326,963,502,306,124,269,559,34,460,825,624,688,563,590,436,260,433,860,23,682,26,191,764,485,136,810,548,242,636,289,267,814,720,591,902,458,434,832,916,378,423,246,317,220,840,160,350,92,301,154,786,355,834,181,985,614,915,657,945,986,416,177,51,509,379,553,876,413,882,224,856,245,834,571,164,659,119,498,7,276,725,85,402,498,814,693,679,171,193,246,271,159,449,20,887,74,895,89,218,401,467,484,777,898,393,997,829,52,873,995,292,503,801,947,282,438,189,742,623,634,913,79,317,979,120,17,86,13,108,380,913,772,887,24,5,952,438,967,994,896,257,896,482,801,100,623,572,774,458,6,586,654,574,231,437,167,104,875,285,764,567,206,47,166,662,851,38,284,977,268,839,571", +"431,459,712,324,911,51,263,478,12,878,118,697,482,104,773,815,199,518,105,116,910,335,346,792,920,142,362,440,498,435,81,396,536,535,355,871,430,187,944,20,965,752,966,191,649,94,979,675,742,981,885,606,128,935,112,774,146,887,127,631,250,691,801,700,945,747,785,546,571,362,108,997,399,814,714,22,238,34,965,609,64,631,672,611,987,594,109,539,787,813,131,298,118,435,359,92,765,336,595,218,439,914,260,29,148,806,826,884,206,100,80,413,339,955,5,117,912,584,492,478,337,169,725,76,689,865,813,563,609,254,142,384,274,290,481,782,351,481,46,130,359,320,298,589,503,754,29,833,923,429,231,85,137,46,969,482,398,351,495,492,760,606,767,965,525,53,204,874,634,978,177,797,396,301,922,300,184,243,116,200,714,561,458,929,430,896,242,818,641,837,793,229,225,665,692,54,81,627,488,526,925,478,977,676,214,587,265,801,510,11,870,217,305,317,221,528,647,527,170,46,382,331,881,246,164,984,915,785,784,69,973,512,929,941,53,568,72,578,28,718,98,929,795,445,575,59,94,819,161,448,547,783,570,508,259,243,741,675,106,339,684,278,72,999,209,25,124,13,551,965,284,297,340,314,697,969,879,339,191,381,800,919,67,52,373,528,839,903,235,823,865,665,716,530,785,629,67,839,250,27,416,183,733,688,856,43,628,918,291,430,488,101,73,701,101,786,813,864,856,820,970,504,589,881,112,630,341,526,824,738,304,861,890,547,835,133,350,832,130,747,574,474,938,402,19,679,767,61,794,913,646,203,778,190,859,899,545,766,999,411,130,655,835,328,534,345,330,578,873,101,459,273,77,533,123,673,125,628,722,678,800,587,656,533,994,713,408,355,808,522,205,425,253,66,142,276,114,221,308,384,444,195,601,711,15,611,948,563,228,842,238,106,291,270,161,346,62,181,805,390,622,604,690,824,15,254,269,424,420,291,903,93,110,504,781,726,588,821,471,540,953,382,630,534,843,651,409,749,983,394,384,354,632,36,507,407,353,145,905,433,969,498,613,305,679,456,81,246,717,268,816,263,354,183,152,288,249,860,997,676,419,609,156,667,662,180,115,135,961,528,911,151,882,465,283,689,728,920,59,237,430,664,571,404,148,477,337,614,410,159,513,290,361,758,144,240,207,923,340,466,721,212,229,928,712,808,817,253,822,681,668,158,183,707,47,231,80,759,91,447,809,777,986,451,24,692,668,850,305,594,0,415,246,758,266,733,806,556,794,581,55,114,982,808,470,479,528,64,28,432,959,771,246,982,6,706,32,479,878,769,851,669,502,446,157,353,342,705,425,678,572,512,111,925,604,16,655,294,551,130,31,533,527,209,79,310,149,170,817,558,964,353,114,177,691,228,787,480,85,352,679,73,804,358,3,937,321,146,715,617,410,463,604,926,89,855,580,235,163,534,923,631,430,739,685,682,925,494,436,776,561,692,393,964,191,565,919,555,735,990,695,330,151,432,952,625,531,718,621,942,445,597,288,142,161,660,367,761,71,13,378,821,839,616,126,419,737,297,957,791,180,860,364,546,895,251,285,897,98,428,581,542,142,430,127,670,232,864,772,906,143,975,823,860,101,560,870,734,525,179,418,73,585,385,515,434,997,796,618,24,17,216,387,427,136,835,542,749,647,689,979,777,454,739,52,338,245,727,531,699,631,23,99,522,587,501,854,224,367,986,820,554,245,846,89,862,749,877,882,176,16,142,495,235,873,409,472,46,988,192,468,26,603,982,57,250,461,759,851,852,171,525,784,224,36,782,599,967,551,777,214,974,456,780,783,734,297,178,386,442,896,742,269,33,796,208,625,61,405,542,941,456,771,616,662,735,734,324,592,345,937,148,101,463,251,358,957,366,221,872,536,338,20,676,162,379,616,986,329,947,838,376,375,7,688,715,155,331,309,938,330,944,407,506,986,354,237,482,693,766,70,650,413,729,301,707,45,837,300,202,350,441,637,981,516,374,399,715,473,768,630,258,327,295,925,972,403,911,810,960,593,644,154,427,672,332,275,845,360,533,704,723,519,189,770,571,144,8,745,96,825,204,28,486,798,827,399,235,487,873,985,875,229,162,433,699,175,886,742,507,813,93,307,57,724,610,695,380,601,569,119,612,511,197,162,14,886,80,467,168,985,296,944,743,502,66,544,411,530,273,616,807,319,804,965,494,973,726,839,871,669,879,295,722,570,865,225,473,760,5,912,400,49,713,811,563,897,92,450,600", +"49,932,321,706,414,425,568,40,388,184,32,248,891,444,29,79,642,382,594,241,701,436,645,66,509,418,810,333,460,622,747,917,216,877,575,417,195,337,884,26,138,353,96,230,348,469,452,454,432,301,189,921,930,979,894,552,136,771,872,530,400,635,942,968,773,434,446,591,579,157,533,578,741,605,255,985,632,18,489,722,276,248,164,414,292,927,687,365,863,718,246,174,427,337,981,999,7,522,618,626,527,204,519,308,945,488,788,963,11,27,673,563,464,94,258,406,658,88,830,840,964,504,389,565,972,193,109,939,227,208,799,456,134,527,934,695,200,750,85,187,604,477,755,800,271,552,948,95,37,649,148,131,967,283,619,136,177,966,492,436,725,799,356,720,448,152,55,220,224,494,791,713,260,973,450,311,275,313,164,382,3,916,368,190,327,635,267,930,285,162,294,14,528,163,711,849,15,195,100,666,323,763,235,875,41,444,978,813,732,815,349,533,410,553,780,405,478,896,639,816,525,767,934,496,830,59,770,390,871,463,131,999,319,473,357,762,680,590,417,612,135,310,775,44,528,576,205,861,979,59,210,183,1,50,313,315,94,833,214,501,258,52,816,258,22,559,254,829,771,355,570,369,281,513,168,320,496,795,158,875,254,1000,943,198,830,817,511,428,515,983,918,734,223,154,548,481,949,823,333,755,817,777,107,119,109,229,676,494,623,564,884,277,742,365,950,94,486,545,518,52,835,928,176,825,519,869,492,754,91,545,714,170,184,506,863,37,802,466,800,551,167,424,299,170,608,113,671,306,439,448,52,782,739,640,741,585,156,553,740,823,179,541,202,485,265,589,925,87,830,906,2,865,634,253,721,965,371,665,694,736,548,531,914,898,235,25,855,810,853,974,242,335,384,693,472,823,822,294,639,690,826,24,180,262,153,638,12,226,904,838,853,877,928,723,773,174,213,784,169,547,827,70,113,398,586,50,922,159,102,773,897,413,553,298,254,209,419,314,365,217,154,209,886,919,610,558,85,702,109,453,463,942,879,181,460,991,98,175,273,337,209,478,380,554,375,950,890,298,281,981,603,967,920,111,755,365,8,459,696,322,488,468,954,92,681,572,518,862,644,970,154,712,738,380,671,522,975,452,685,465,34,494,809,483,762,465,550,327,574,728,559,822,724,812,121,638,288,509,757,679,102,772,711,585,290,886,731,293,737,18,739,310,199,729,96,850,575,150,451,912,612,423,338,842,902,431,142,444,793,970,415,0,81,628,675,433,187,120,313,875,239,429,756,962,850,537,656,458,986,789,247,445,711,337,226,35,755,293,517,312,597,634,859,11,235,469,459,138,7,341,507,687,518,823,582,898,822,284,352,943,775,193,20,960,514,723,295,782,433,664,576,406,407,26,914,696,633,409,108,157,576,925,713,31,742,797,255,387,59,812,159,485,919,181,977,718,438,713,216,892,173,86,539,761,83,153,507,544,337,682,459,352,239,638,119,974,106,89,136,101,906,142,284,708,393,429,980,156,265,331,573,743,150,606,216,995,342,816,572,487,629,29,36,368,239,647,722,627,657,796,344,553,649,343,388,882,467,1,65,384,859,884,823,584,393,640,166,31,681,540,618,843,504,785,404,415,515,88,993,98,448,203,472,455,823,963,153,654,244,337,393,304,788,44,629,287,560,466,908,582,186,403,977,892,434,855,469,622,647,45,16,927,816,794,412,271,824,10,644,964,963,118,652,705,42,75,867,896,188,527,516,900,559,505,649,598,195,925,608,164,539,933,749,722,114,635,536,693,729,289,274,197,646,953,841,925,729,436,510,136,331,759,371,632,26,607,888,640,643,186,681,596,669,754,169,866,720,922,394,321,620,265,571,67,728,309,510,853,811,765,262,507,204,756,565,254,841,331,677,652,624,86,725,78,100,906,92,595,665,231,963,992,799,171,664,648,27,749,828,234,533,471,998,159,697,994,127,829,53,847,617,454,877,302,376,460,55,157,940,371,330,441,870,238,133,572,337,268,889,31,799,671,761,621,140,969,247,969,826,974,306,913,129,673,693,711,584,937,855,614,970,889,318,261,839,483,433,928,733,236,217,459,548,734,439,771,394,191,451,389,163,849,164,568,511,278,251,511,449,105,973,344,661,202,462,407,104,585,264,774,212,819,848,865,76,604,606,545,20,543,562,196,325,302,404,114,299,470,600,979,78,751,278,232,924,323,516,121,703,480,22,259,134,909,147,464,678,105,319,596,946,959,652,990,244,119,216,242,616,517", +"80,907,65,885,700,119,957,823,51,588,35,440,536,89,876,973,366,873,4,284,618,931,215,290,57,748,857,239,56,392,457,315,596,839,33,370,96,250,373,831,506,145,153,220,138,941,767,994,768,656,400,884,829,377,946,474,915,327,552,264,354,265,970,149,828,725,444,90,909,847,201,507,441,690,344,8,408,146,267,995,651,126,644,43,733,257,294,476,354,343,51,175,817,775,430,513,386,144,763,376,760,159,622,198,599,865,777,800,460,984,695,385,232,308,176,943,622,940,754,623,998,141,474,37,633,202,353,459,889,771,349,740,665,923,311,146,431,956,458,237,129,43,908,438,886,381,992,77,511,582,385,758,989,366,254,115,192,961,174,729,235,15,448,817,182,659,185,440,809,813,244,605,2,546,543,31,283,903,938,585,628,754,772,300,831,767,296,7,887,216,932,711,622,260,420,512,584,188,108,888,828,337,146,408,515,26,27,830,441,364,93,960,659,923,821,172,319,508,596,671,105,752,497,806,320,743,665,919,223,1000,685,154,47,972,373,929,68,185,268,501,82,705,546,813,834,262,371,444,96,709,216,34,688,896,682,914,809,14,707,238,81,344,29,928,116,936,781,892,456,64,822,35,520,583,996,530,263,769,193,629,120,483,932,332,386,309,886,580,188,592,859,411,226,86,291,211,991,129,922,975,609,53,791,617,350,632,569,470,776,121,105,282,957,932,106,479,60,936,716,77,849,232,558,660,316,599,533,729,811,787,236,468,673,879,691,107,688,29,324,537,339,278,498,185,499,826,849,820,287,357,523,689,753,536,323,348,169,682,421,228,358,941,39,183,986,574,315,824,72,402,185,554,848,26,54,846,630,254,254,411,121,807,471,7,526,557,853,245,428,121,231,195,987,338,880,829,826,913,149,813,979,428,775,336,930,44,293,879,950,328,637,691,675,118,897,557,463,930,790,950,125,790,918,750,860,108,858,84,205,828,937,412,284,402,97,470,611,384,331,882,416,479,928,713,571,13,706,125,986,817,595,193,247,879,838,96,104,360,816,493,718,677,770,382,305,137,249,158,957,187,64,763,709,464,396,929,186,608,177,505,884,182,80,850,453,960,441,808,149,970,105,224,271,300,46,117,26,996,111,686,640,689,360,680,646,120,269,520,15,188,683,636,426,167,238,236,230,532,837,209,485,79,199,682,994,398,935,732,233,373,444,883,246,88,185,25,119,752,221,389,499,819,911,636,914,424,765,325,940,990,246,81,0,37,483,221,366,311,527,612,586,305,192,60,860,185,68,680,687,593,454,93,546,48,810,820,663,749,273,557,245,532,222,857,647,538,347,924,260,899,789,389,66,457,919,775,200,173,137,390,749,491,6,691,893,132,335,532,834,39,93,273,175,869,336,434,945,390,482,133,774,747,480,442,596,694,933,389,385,720,587,167,869,129,760,904,848,992,562,939,409,297,570,278,397,903,741,811,235,669,62,314,100,934,607,108,225,562,439,809,325,242,277,560,134,971,437,72,716,131,397,177,459,766,472,643,562,394,480,356,520,937,75,807,63,464,824,131,537,336,220,651,914,590,690,256,487,457,680,561,284,144,565,317,521,569,205,516,991,45,955,917,685,550,599,874,933,303,308,417,130,716,966,231,274,823,650,864,510,865,286,794,39,162,230,626,759,638,485,163,235,598,614,946,622,129,813,312,495,16,261,213,719,681,337,148,283,408,389,576,349,45,768,922,587,659,520,135,266,374,161,920,461,765,536,347,488,325,916,994,830,371,124,616,271,15,115,712,322,609,217,447,460,389,653,232,620,754,86,483,953,457,173,785,658,550,460,874,242,548,873,532,949,607,60,834,207,556,210,102,376,133,547,817,56,169,201,214,682,486,775,555,846,593,434,683,244,190,893,666,487,62,237,46,169,493,426,973,207,316,394,265,310,795,396,158,843,564,356,225,110,944,940,816,999,478,977,945,2,48,794,279,482,469,828,340,973,741,240,488,523,721,24,934,7,41,509,391,977,301,238,682,839,198,154,409,673,736,449,488,655,165,204,379,598,162,116,862,335,762,165,959,146,70,93,522,511,714,113,721,949,680,964,325,3,388,3,21,767,686,466,806,793,251,103,316,109,158,386,724,147,307,846,344,562,523,968,670,220,143,57,19,97,857,690,798,777,59,69,351,833,851,123,782,575,660,517,218,872,322,353,264,650,463,395,260,61,302,969,911,296,483,921,62,764,95,512,736,637,794,206,335,103,401,647,146,496,39,143,678", +"699,612,914,931,648,567,63,823,106,193,990,908,934,46,195,423,166,826,840,430,126,885,830,933,595,619,272,825,919,477,488,536,810,849,599,441,368,854,129,820,717,41,509,464,116,188,733,5,196,778,5,195,681,574,231,256,897,500,874,253,464,87,510,853,313,6,627,70,526,155,197,37,752,722,114,670,846,947,934,942,288,287,840,212,414,915,114,706,560,850,454,962,277,956,24,623,33,486,545,433,562,752,316,961,770,84,746,861,748,182,318,687,181,697,731,53,370,118,755,541,111,932,693,688,84,852,120,561,541,44,263,838,136,684,469,193,548,877,218,507,43,448,254,582,553,652,796,900,441,957,634,619,484,540,793,210,676,212,930,465,474,74,881,552,587,807,730,87,752,698,746,13,936,168,364,863,12,913,755,251,552,139,190,554,313,232,959,343,453,432,273,725,98,658,269,34,481,97,530,472,691,100,722,347,495,482,816,718,63,242,762,307,584,38,29,133,140,393,322,821,298,738,745,394,781,973,683,732,968,308,223,965,404,289,35,904,955,988,52,726,107,731,195,799,806,57,327,980,937,742,894,920,290,434,302,699,206,542,528,140,177,32,685,92,483,329,754,823,461,494,271,480,803,481,442,499,795,248,933,102,203,921,74,359,119,833,52,667,868,63,497,904,320,853,258,893,176,388,435,307,575,675,68,214,195,634,665,891,330,214,13,482,102,638,950,267,357,581,803,63,211,901,502,622,972,155,288,96,72,945,491,450,723,817,143,239,557,825,820,368,335,668,740,941,895,493,316,140,327,575,21,154,870,732,490,232,94,165,540,186,923,493,817,660,274,202,227,142,57,74,595,931,46,982,363,210,46,806,369,917,718,915,397,902,358,643,836,282,343,632,787,325,319,236,23,976,256,90,1000,628,209,727,137,178,590,699,111,441,558,941,116,153,941,608,212,201,290,264,805,399,491,185,245,662,750,117,401,486,734,496,415,180,272,747,922,263,404,751,99,592,730,832,850,421,57,681,752,917,968,220,274,116,7,717,346,697,217,340,834,643,514,954,416,785,686,719,783,274,169,632,116,638,871,976,281,413,626,51,286,865,931,853,669,213,514,276,437,505,326,142,584,720,729,148,78,700,252,106,731,245,979,808,429,753,108,759,907,823,709,212,133,826,416,443,427,894,909,87,61,567,226,150,265,573,694,924,683,2,614,87,468,988,295,466,907,145,606,929,108,278,902,445,824,182,850,760,156,560,783,664,758,628,37,0,990,423,916,380,567,673,955,541,670,509,84,65,189,989,661,387,178,895,516,234,230,120,176,916,212,915,599,684,491,847,931,36,979,518,151,162,273,471,725,831,800,474,210,232,988,999,734,134,545,382,224,772,377,428,239,500,296,686,397,540,147,110,664,53,24,429,184,892,586,439,277,360,945,238,435,147,452,313,448,215,587,602,553,733,18,285,892,198,37,635,822,459,188,528,817,220,193,361,993,840,544,704,46,415,306,846,560,295,153,732,447,343,550,630,924,455,296,109,459,919,926,182,554,502,844,698,736,874,709,352,552,263,454,981,578,607,440,569,632,31,899,792,876,16,185,266,699,893,308,265,367,756,144,364,477,127,713,417,198,478,879,973,941,386,424,119,834,790,139,196,15,644,662,416,945,30,730,904,791,435,286,387,882,75,230,304,718,969,479,448,28,137,866,678,763,648,139,796,104,187,150,852,91,297,767,311,237,429,395,811,92,756,22,897,61,681,118,451,452,627,692,463,910,532,92,885,276,252,398,759,880,565,541,9,812,26,169,530,955,99,227,928,463,515,5,696,88,726,848,350,789,798,602,925,741,204,356,493,642,210,105,905,218,744,304,59,828,995,794,422,226,360,487,40,747,301,324,675,719,505,946,34,630,884,239,236,859,430,677,25,490,414,178,694,934,275,121,622,835,991,497,50,955,617,107,937,464,354,442,782,173,15,738,424,592,490,267,439,795,579,984,899,14,897,414,744,781,303,62,697,352,311,432,230,427,238,545,765,233,208,632,976,179,483,377,522,130,91,318,249,130,585,94,231,837,129,163,568,515,329,470,519,617,593,632,972,363,378,85,602,744,535,877,302,338,953,124,443,734,477,338,105,937,439,100,567,854,489,633,644,792,78,79,983,9,772,58,446,672,730,229,520,743,786,119,333,420,686,186,32,453,965,708,857,698,190,609,79,664,155,719,292,994,571,899,605,192,612,929,134,288,627,918,364,81,218,904,308,628,688,61,750,557,987,887,318", +"35,40,962,724,266,895,260,141,569,129,752,327,483,416,86,852,547,157,736,271,561,532,999,270,823,638,764,794,455,835,912,371,941,1000,909,161,373,948,248,351,862,201,951,354,591,673,243,11,557,299,608,985,658,546,760,916,88,300,720,567,500,304,890,778,309,608,731,445,888,86,908,538,644,411,723,649,723,46,314,624,207,885,527,661,346,548,707,447,72,400,305,410,694,760,217,228,623,79,945,733,739,903,265,232,681,754,288,847,813,354,332,546,395,665,343,311,287,567,816,726,889,327,100,731,16,883,101,263,657,949,457,45,17,9,93,217,939,562,265,545,393,350,656,387,333,268,348,617,453,797,492,249,190,861,456,416,739,346,695,702,835,640,434,143,265,206,311,219,581,149,766,868,244,323,602,800,651,874,128,754,272,577,906,984,203,152,736,953,793,96,79,760,150,868,324,443,933,823,899,796,104,273,282,950,394,428,265,234,54,408,362,258,452,684,106,193,822,88,643,478,547,743,377,142,168,820,240,557,616,916,712,793,272,827,785,49,374,944,253,714,441,820,709,523,1,936,175,819,167,899,17,311,87,884,820,298,590,286,502,208,945,902,718,11,351,769,545,767,582,400,826,276,62,211,371,898,895,436,183,977,881,747,829,524,1000,22,523,398,843,328,663,85,224,243,132,566,925,483,653,607,736,613,879,579,463,17,801,196,311,99,842,833,23,167,93,858,681,785,245,865,861,692,871,782,884,192,794,427,837,660,663,184,985,948,249,201,291,197,601,378,343,697,243,355,683,290,105,470,156,79,587,53,278,626,279,38,185,610,802,739,25,541,381,341,874,519,170,726,956,700,438,135,748,256,76,180,992,743,289,750,527,446,736,909,97,531,278,294,74,66,830,337,514,339,372,925,522,844,23,999,546,318,816,334,763,509,491,771,137,635,824,424,962,859,588,732,48,244,2,780,195,266,588,114,459,214,373,439,554,845,393,123,661,11,462,577,136,22,217,218,292,989,770,304,668,224,286,247,986,943,118,617,557,39,753,729,115,555,418,648,833,348,302,39,800,265,396,108,679,454,680,889,57,476,669,428,850,550,237,875,870,62,413,593,261,657,886,489,191,230,636,184,549,579,637,860,151,387,92,718,232,577,452,423,630,81,883,7,144,961,158,526,71,53,437,87,438,653,919,860,266,800,584,714,231,166,330,397,239,424,481,311,65,545,383,435,551,456,179,190,841,123,477,233,276,13,259,361,502,76,266,675,483,990,0,722,888,250,324,489,938,476,536,32,251,740,598,458,962,56,716,972,343,550,461,251,978,806,455,937,734,63,799,330,916,553,110,162,979,668,844,715,511,379,793,520,149,446,989,524,909,242,984,912,994,174,796,327,336,383,850,569,162,23,668,609,665,943,422,422,732,328,324,843,506,263,231,695,277,125,180,568,448,348,971,947,415,38,657,170,111,166,273,134,369,911,19,937,563,943,329,920,871,194,823,570,193,139,535,142,987,88,949,765,230,791,709,279,804,389,587,985,309,38,678,398,478,195,53,448,941,942,411,308,257,777,817,628,671,807,660,692,54,206,78,980,626,906,621,283,157,987,535,744,633,538,85,277,729,313,959,300,159,775,248,166,262,146,856,166,736,650,352,40,885,673,752,735,537,406,772,39,577,343,58,527,658,839,569,667,952,556,823,938,418,874,644,499,528,800,670,841,756,437,555,9,60,63,860,507,389,9,778,897,894,897,398,233,974,183,11,169,437,673,741,743,755,470,425,850,765,609,632,84,7,493,763,56,52,962,12,161,76,713,634,225,478,294,29,369,445,572,54,483,35,211,23,230,204,805,801,435,528,884,965,4,375,985,165,275,551,403,279,848,358,308,651,665,777,107,179,524,151,988,401,15,363,597,103,982,942,493,734,640,478,715,863,8,502,824,813,499,687,844,299,663,506,663,273,483,802,912,858,646,414,65,771,394,679,462,510,470,729,428,236,722,449,763,968,675,977,315,501,387,302,311,598,323,633,20,881,346,109,398,278,763,565,846,328,749,791,297,642,950,169,503,777,308,986,984,100,949,942,495,623,27,426,574,733,686,429,648,109,388,850,204,230,448,149,139,339,940,828,205,817,815,203,345,778,447,920,768,603,685,289,841,406,101,753,151,728,764,882,185,349,240,871,961,333,745,369,792,60,493,490,601,612,23,494,866,771,687,482,974,291,444,188,643,228,30,36,932,562,286,650,277,460,947,712,864,383,998,972,818,85,609,50,270,894,494", +"345,138,71,124,682,664,523,401,90,681,752,558,749,589,826,983,941,915,105,119,466,295,839,559,487,907,392,211,491,367,557,943,945,677,440,32,279,990,385,116,967,754,171,753,271,968,742,939,435,902,85,617,991,196,908,299,388,761,311,880,150,373,182,425,984,744,379,275,998,443,856,882,374,386,898,32,870,900,172,765,225,189,602,271,442,622,990,775,968,207,982,116,680,700,238,975,48,55,968,217,22,16,431,756,809,315,952,577,821,737,575,584,134,433,973,505,464,193,103,310,305,194,417,361,489,442,900,155,678,532,827,457,975,286,506,463,463,478,872,604,693,467,320,896,522,671,357,813,131,478,611,375,825,234,945,838,770,767,33,825,570,786,17,264,126,241,117,380,280,54,265,360,76,445,33,39,326,980,401,150,266,823,504,893,131,780,900,446,326,286,392,718,434,672,275,728,641,495,227,969,336,108,900,203,33,36,98,940,94,849,208,879,695,556,21,753,791,152,696,808,160,723,513,331,635,246,557,515,632,947,334,792,97,78,131,548,636,626,815,369,159,47,190,395,940,613,706,817,710,734,16,638,669,344,121,848,657,770,864,217,85,13,50,926,422,427,356,961,739,795,277,762,849,525,983,869,977,515,186,544,644,933,748,178,356,71,564,661,366,544,968,366,389,866,228,237,449,130,148,789,762,996,296,301,84,886,61,508,47,875,950,905,808,84,915,568,939,162,21,44,995,459,870,698,38,380,236,860,20,498,33,630,994,61,814,825,252,859,745,446,812,620,792,478,501,703,258,983,24,771,622,48,178,689,194,562,400,91,986,451,58,614,946,954,914,828,668,425,403,326,316,189,336,685,560,829,3,338,966,502,10,747,545,392,400,206,490,952,460,964,97,535,161,887,566,485,410,990,211,157,766,968,575,103,218,124,807,832,454,297,619,323,672,156,145,824,931,858,107,276,254,270,860,651,700,507,368,744,774,582,69,538,779,909,655,640,234,143,943,961,331,792,230,869,11,595,40,868,7,480,929,547,7,791,712,375,118,495,705,237,373,936,993,360,83,487,903,936,889,153,630,595,411,751,593,174,26,665,551,46,412,668,840,821,276,908,109,205,453,771,299,14,379,426,234,836,105,365,401,458,117,439,426,988,606,251,464,250,214,323,664,888,60,425,441,274,859,513,248,642,540,141,795,455,246,342,782,337,159,789,918,998,338,991,487,160,787,740,463,456,186,954,690,855,530,754,529,950,283,43,733,433,221,423,722,0,958,214,878,59,585,303,765,405,676,827,707,43,167,164,469,350,449,151,650,305,349,236,498,788,729,913,162,232,126,436,231,23,574,405,402,906,851,780,973,127,281,945,805,251,846,886,851,573,264,303,331,219,974,951,239,750,732,600,16,167,954,993,589,955,325,806,432,829,567,204,601,558,552,646,704,925,55,830,534,734,169,881,17,765,709,410,924,231,957,839,342,772,880,881,522,272,215,36,857,888,276,689,819,34,87,301,297,282,590,489,210,56,945,574,789,511,998,694,472,193,128,206,59,376,184,639,630,646,442,942,30,179,882,563,206,393,431,128,140,995,23,13,730,401,524,344,427,848,319,945,253,873,982,708,215,826,67,327,516,2,915,260,858,557,225,894,17,689,144,574,858,784,986,421,266,56,673,568,897,589,658,159,998,977,108,137,339,873,756,497,163,668,319,850,565,666,774,703,408,637,242,449,28,278,369,201,791,117,164,367,325,795,401,263,327,566,298,284,239,60,394,610,240,697,806,359,82,543,796,120,40,184,870,11,13,271,158,109,186,579,265,156,615,54,6,529,322,336,37,602,263,496,184,364,651,203,823,595,336,231,241,811,847,293,825,780,789,544,150,111,247,90,254,800,338,652,224,87,750,760,459,40,968,594,32,191,957,570,359,916,8,467,248,889,658,147,569,156,634,528,681,382,460,934,642,769,32,234,755,246,126,516,81,914,924,635,347,708,377,480,830,737,423,570,832,631,926,383,662,542,821,496,260,118,178,585,423,207,425,178,458,926,766,945,733,390,395,430,52,164,576,11,419,854,76,671,713,377,155,152,996,301,178,287,781,327,495,107,315,74,192,473,430,309,681,727,896,181,100,907,468,356,751,612,328,540,727,133,521,643,487,835,618,235,202,416,407,541,525,316,427,51,436,468,391,451,91,564,364,20,953,498,401,774,552,175,912,4,698,77,139,501,746,62,699,984,52,867,390,672,818,501,883,622,340,252,576,499,959,98,91,886,760,246", +"830,857,172,423,578,536,834,352,572,980,690,310,466,278,335,101,176,51,10,206,650,774,131,293,308,911,741,569,1000,20,597,43,122,920,753,892,614,181,986,143,172,366,268,987,564,298,479,559,801,65,814,513,773,833,163,37,657,569,913,804,647,60,103,345,845,568,892,354,219,322,104,636,831,597,530,67,894,125,49,647,302,243,683,740,901,115,218,681,943,848,383,286,801,358,381,876,457,870,829,933,303,177,752,992,808,968,736,648,798,798,901,581,178,574,512,739,608,856,695,846,901,49,970,224,808,885,430,803,316,235,501,964,536,873,212,901,416,570,937,371,294,702,13,98,188,606,320,995,91,194,94,153,627,605,530,973,460,204,267,685,161,320,798,240,878,522,510,179,973,518,945,575,349,417,566,388,129,961,562,616,433,55,209,30,733,769,437,925,754,586,768,21,783,150,750,217,497,143,886,474,115,989,442,148,477,414,386,416,643,933,60,340,445,33,327,946,760,304,75,663,456,706,636,887,655,674,727,554,417,930,980,495,582,698,106,978,643,733,712,39,563,257,907,78,840,774,281,339,918,600,19,363,474,564,502,355,17,865,976,934,672,724,880,272,937,375,84,967,315,924,189,379,937,977,987,939,326,833,371,997,524,185,111,13,62,650,845,957,596,707,459,604,399,470,574,780,892,303,987,145,893,184,887,797,835,646,424,396,123,785,100,881,830,594,116,301,215,46,138,901,104,589,236,440,849,647,755,303,406,490,81,803,995,951,290,357,36,536,955,626,448,305,722,795,445,761,915,59,321,144,263,938,588,200,427,86,461,564,404,31,289,46,167,768,181,217,800,943,742,948,377,806,736,164,471,314,376,228,891,423,613,721,257,488,40,638,296,794,275,728,444,84,920,462,690,792,981,954,874,774,321,376,589,342,513,65,666,491,969,680,785,371,252,311,741,450,105,564,449,967,405,533,872,505,906,168,560,455,206,759,706,563,62,280,42,390,966,833,685,542,864,395,695,436,907,675,928,896,812,873,972,15,232,828,449,25,35,394,242,29,856,293,71,603,967,334,12,743,142,204,112,647,399,707,401,970,198,845,546,88,4,677,730,394,65,389,693,241,140,510,51,263,499,336,381,858,3,496,454,710,47,429,381,994,130,651,193,348,495,395,810,565,225,467,505,234,761,94,781,3,876,929,868,602,797,972,693,228,942,146,786,778,705,235,251,923,993,727,501,914,224,881,772,283,712,906,518,301,390,309,806,187,366,916,888,958,0,668,956,755,383,104,191,627,444,43,364,501,642,460,498,394,144,941,549,768,368,871,6,52,500,650,721,207,258,511,776,922,675,493,471,471,860,639,887,598,94,941,626,56,971,44,729,174,404,336,845,384,862,89,43,97,51,729,227,886,309,445,388,121,39,763,93,629,992,448,727,344,286,55,410,835,30,325,724,674,566,987,123,363,432,730,854,281,623,885,24,754,399,327,815,957,161,952,832,551,841,323,8,596,877,233,41,861,539,258,323,755,715,542,122,181,421,468,164,433,361,625,866,227,588,577,132,61,39,590,459,297,488,654,193,504,772,986,796,660,920,552,566,232,119,553,122,708,697,496,532,421,777,888,576,398,544,205,123,216,767,58,268,243,551,781,50,853,502,690,794,872,270,46,327,389,880,723,271,315,980,282,472,432,11,904,294,577,756,159,398,429,811,498,931,916,38,871,193,189,956,80,945,897,321,549,185,119,408,929,198,421,913,167,48,135,813,481,808,180,841,12,220,144,911,327,538,54,906,244,764,448,739,301,75,399,585,288,407,699,70,270,194,528,341,131,138,335,58,170,890,730,173,976,5,82,645,722,690,266,713,730,867,508,877,356,879,356,147,515,937,556,64,487,602,629,439,345,806,967,768,538,113,472,314,610,562,592,468,137,514,802,428,686,200,469,404,450,208,597,534,381,520,734,512,388,517,606,241,873,283,307,640,364,129,835,542,556,204,964,305,770,40,115,546,907,702,387,545,973,215,574,237,693,808,844,40,372,184,746,540,902,344,937,796,451,904,550,105,493,304,73,340,543,755,721,76,773,560,660,86,17,65,733,775,825,401,702,337,730,312,42,937,458,318,434,728,766,667,376,759,380,919,203,453,189,541,561,553,292,191,438,34,149,796,641,386,862,123,263,552,394,896,80,327,990,313,815,539,424,530,179,502,507,777,955,490,781,334,456,948,112,22,496,601,86,642,46,982,834,437,603,151,982,344,366,545,185,688,410,736,516,105,835", +"687,958,795,731,597,207,747,426,66,786,13,806,521,230,679,62,338,582,207,64,141,634,90,19,453,366,18,774,744,293,277,496,662,946,400,672,260,622,786,459,390,233,188,689,397,843,149,773,139,307,221,431,785,272,201,224,313,469,912,911,971,256,490,938,128,895,119,520,901,265,833,520,578,932,519,529,577,877,511,545,862,818,139,24,161,846,819,853,962,665,356,398,463,230,244,785,339,533,391,729,444,842,486,636,139,154,804,692,37,362,693,796,364,998,351,43,193,15,772,545,694,94,731,594,950,823,485,338,413,228,48,908,938,23,169,885,701,557,383,448,457,529,318,442,635,524,170,865,779,120,338,351,428,696,267,584,63,180,713,103,120,755,598,114,123,12,732,972,461,514,686,481,953,65,157,615,235,575,678,136,877,261,525,803,604,170,80,708,69,808,308,685,284,317,279,647,962,459,896,76,247,691,782,357,589,728,282,349,376,55,400,548,568,902,936,267,315,852,202,392,479,43,961,373,781,919,491,731,902,847,327,181,433,213,377,14,462,771,59,654,307,501,183,943,631,560,680,351,410,485,676,624,811,760,356,188,556,905,797,68,134,162,394,524,965,928,810,743,10,709,880,720,668,432,367,498,445,565,925,633,928,918,481,53,261,654,806,780,466,623,122,838,106,100,201,714,543,976,560,15,367,846,380,438,816,461,409,241,648,436,437,674,955,225,405,122,2,426,700,798,855,48,940,786,30,341,820,667,787,464,593,205,638,562,580,147,698,713,699,893,59,897,156,382,190,287,535,697,712,512,40,231,915,28,597,701,60,245,703,46,814,349,621,508,923,745,697,979,784,835,385,896,996,943,297,148,256,59,599,780,976,894,648,399,711,400,760,222,466,575,561,453,3,808,552,926,434,877,791,681,429,959,586,415,458,801,960,434,792,534,711,392,98,423,28,702,522,647,555,512,125,786,419,638,181,316,354,714,14,145,670,492,417,832,636,397,136,708,821,764,903,346,2,13,247,498,46,432,501,943,689,727,614,679,799,898,974,954,510,19,141,48,111,545,282,234,794,224,421,949,979,574,228,427,698,268,715,565,899,535,377,726,950,554,252,6,48,285,716,623,420,797,658,951,848,486,62,971,180,334,156,823,207,580,692,412,526,549,585,704,654,229,489,503,229,706,344,664,668,586,792,925,179,767,489,970,183,286,252,252,997,727,348,734,504,776,827,158,18,137,489,627,862,556,801,806,239,433,581,3,556,120,311,380,250,214,668,0,882,69,887,921,992,387,436,709,238,704,730,179,760,68,304,91,493,10,993,856,512,545,884,800,266,111,688,728,651,638,875,293,745,41,176,203,751,85,289,779,691,902,891,434,609,78,865,589,830,495,831,876,576,996,335,731,804,36,200,994,624,301,887,945,46,841,808,397,867,825,110,13,414,702,140,136,900,622,978,291,192,170,118,195,703,338,251,422,957,169,609,209,523,466,874,853,599,429,2,291,947,854,390,241,411,712,375,140,694,787,428,939,977,169,126,52,692,65,617,232,64,236,112,444,26,696,990,106,730,963,457,77,787,633,9,903,733,394,300,798,634,42,208,193,203,76,443,813,280,933,818,637,606,499,588,992,896,732,288,142,144,251,682,270,33,774,20,696,288,690,229,166,619,243,246,314,348,853,58,562,160,169,453,174,425,752,891,493,731,267,123,580,714,324,158,333,620,81,518,420,680,331,917,512,396,35,48,720,999,992,680,201,663,511,968,928,368,755,724,538,405,840,652,154,401,163,356,705,80,254,505,62,768,384,425,379,598,415,546,305,980,98,235,115,445,995,276,905,71,825,502,387,745,906,102,423,968,865,634,380,891,147,617,706,543,890,564,18,757,495,391,608,511,917,885,440,822,83,89,526,837,178,602,471,32,858,467,755,489,184,462,750,862,328,527,555,920,326,282,745,32,861,463,802,437,118,601,787,829,392,700,550,625,508,566,238,470,21,948,797,42,85,490,552,164,285,234,208,472,436,841,333,985,377,716,637,691,551,861,920,834,879,669,272,175,336,499,321,615,443,258,804,311,949,801,80,114,521,170,153,268,46,29,522,308,313,51,642,441,720,54,333,923,391,855,398,992,101,830,988,207,222,575,359,691,875,337,74,668,953,193,439,206,541,442,377,228,693,460,199,575,40,884,842,239,42,18,459,587,955,481,993,328,417,738,482,244,713,29,461,522,433,390,398,721,74,52,776,922,821,241,758,540,707,265,863,133,653,661,388,386,382", +"406,614,973,15,447,162,627,905,622,667,746,334,745,113,233,49,558,79,158,116,910,218,389,232,201,288,591,986,32,912,234,967,55,491,468,294,326,753,191,645,485,190,386,362,416,892,598,703,630,131,198,788,207,6,924,948,350,872,393,544,496,437,559,581,764,505,727,804,238,688,772,423,631,837,464,926,596,360,762,984,927,476,26,973,714,352,277,728,1000,110,155,463,889,169,393,119,602,545,145,978,635,991,115,428,650,736,291,403,83,254,483,312,929,547,653,872,747,507,935,670,446,164,272,290,951,799,177,715,501,700,501,95,456,963,643,228,360,590,855,70,245,529,568,19,836,748,60,551,164,878,637,260,524,133,547,389,910,937,348,634,713,923,670,531,51,613,536,948,761,153,449,176,947,769,526,747,292,826,229,685,168,518,478,279,124,542,285,97,491,113,477,818,37,684,761,60,497,249,474,604,519,222,713,824,438,673,420,957,593,327,242,464,282,682,500,701,615,744,281,213,315,491,198,412,109,137,875,545,929,216,112,687,622,862,63,237,581,334,629,71,456,594,841,787,274,285,673,836,29,386,723,11,685,680,560,986,452,657,145,959,825,128,140,610,263,377,288,448,224,899,822,534,714,849,289,838,682,347,396,363,14,131,815,329,431,547,581,589,920,476,245,395,814,262,797,272,468,959,458,293,933,217,88,321,606,64,683,695,385,687,231,59,732,991,492,940,63,368,943,183,930,812,492,987,266,887,591,240,620,137,797,182,581,910,100,524,180,654,805,980,727,339,641,307,257,109,621,728,834,761,644,404,343,53,819,225,349,3,417,977,667,963,653,81,64,761,908,633,635,394,667,155,455,16,661,44,85,885,956,205,975,20,815,640,789,677,9,68,53,699,814,654,418,292,322,214,480,719,637,512,151,282,617,469,748,419,212,442,678,806,256,544,208,887,597,128,41,845,342,918,603,202,159,193,264,569,33,22,938,339,526,24,587,172,447,213,463,659,527,484,110,617,817,666,340,780,545,341,503,997,285,40,418,442,772,756,276,626,787,197,522,439,147,168,673,299,103,781,280,891,845,333,11,335,193,532,994,131,103,77,958,370,396,871,111,235,660,984,701,347,559,815,146,983,885,812,427,17,731,826,196,547,792,183,188,156,415,915,28,558,720,80,857,711,935,633,219,304,284,813,531,924,116,227,880,197,920,208,378,471,796,562,793,336,410,568,484,546,227,99,172,419,304,571,13,272,503,117,584,208,794,313,527,567,324,878,956,882,0,136,377,151,77,385,321,651,94,681,69,827,642,455,808,651,41,340,347,315,807,369,987,519,69,140,21,628,525,357,649,260,459,259,795,700,26,880,176,512,819,424,483,506,158,324,475,655,661,827,496,632,265,50,216,616,581,662,410,54,437,356,513,574,836,480,217,872,290,582,599,209,382,305,149,914,304,848,639,704,323,87,808,86,690,16,662,432,255,173,888,432,17,286,945,187,159,169,123,946,509,871,206,95,430,780,532,619,24,606,937,813,314,701,344,419,325,294,414,374,979,437,27,519,227,261,443,757,11,725,333,607,425,787,296,485,916,701,438,581,92,730,573,233,721,305,960,191,488,837,903,434,477,7,373,441,439,632,821,280,502,101,71,817,435,159,584,906,800,633,558,984,138,569,697,848,973,68,110,614,221,178,967,261,505,20,348,49,410,244,394,337,959,947,232,209,7,413,245,900,283,32,757,425,387,725,815,907,739,661,725,816,210,326,888,769,247,124,428,359,85,411,24,632,330,817,267,287,28,999,127,913,914,294,352,126,795,56,589,98,442,23,74,984,47,958,274,340,137,913,866,866,299,971,71,724,220,2,316,492,916,279,123,883,728,853,598,234,700,668,187,591,281,639,639,231,16,272,43,191,815,16,192,226,190,688,548,38,979,109,175,719,725,154,382,49,898,132,236,16,839,663,95,586,695,272,763,676,803,796,664,391,715,347,107,825,625,632,747,916,619,898,612,101,313,717,237,514,89,802,891,37,558,619,47,282,324,420,66,533,765,969,206,460,118,970,21,88,484,355,585,506,356,79,589,831,629,929,428,862,646,34,627,250,905,293,348,268,407,965,915,382,965,377,52,658,652,703,732,416,690,658,394,401,901,857,921,451,75,473,788,169,838,601,683,589,757,406,709,826,552,881,652,663,448,276,572,875,610,468,562,895,884,332,506,648,547,779,237,47,806,744,779,872,674,178,83,704,838,641,19,610,972,436,159,13,319,564,333,266,974,245", +"605,164,430,553,734,841,863,647,101,71,626,809,358,281,344,336,718,432,283,937,235,358,929,353,176,658,618,818,349,857,600,71,800,34,759,746,192,756,330,824,244,133,223,632,882,363,694,448,217,106,395,609,458,508,121,8,137,259,921,649,98,134,46,889,506,856,423,962,725,868,492,661,654,940,252,437,148,351,685,660,23,478,883,478,310,959,535,618,326,677,699,540,94,547,460,218,96,834,298,835,622,249,650,626,454,957,550,421,357,148,688,807,486,795,588,411,381,198,985,973,509,833,107,531,429,371,430,10,282,853,221,815,634,367,809,272,450,291,393,861,782,463,380,569,752,627,136,698,299,477,966,348,476,199,866,386,177,458,295,12,852,965,469,531,508,150,594,746,586,899,362,750,340,570,41,99,879,308,360,287,475,176,863,908,433,351,3,925,825,88,912,76,550,797,633,18,862,216,882,672,148,920,612,591,849,474,80,496,36,399,159,872,376,359,971,19,404,214,39,359,356,312,907,36,550,57,512,189,41,152,420,637,6,300,844,831,727,776,742,449,776,607,155,119,547,803,965,659,754,123,560,699,850,321,450,346,674,675,312,148,834,413,536,355,355,985,676,885,599,289,484,902,479,465,46,770,974,776,30,653,966,185,157,711,794,728,765,798,765,359,951,559,180,694,168,126,278,20,800,214,447,521,822,725,299,981,186,637,654,663,586,2,678,275,307,480,653,554,148,560,933,769,462,815,267,155,892,97,116,594,399,28,133,649,955,997,204,875,549,184,368,167,450,719,512,248,881,802,932,118,574,411,985,549,365,106,931,156,507,408,802,609,536,833,923,498,234,606,727,971,865,764,338,582,201,64,19,621,69,923,212,157,942,249,485,159,419,531,333,720,810,327,359,707,525,347,121,163,315,699,982,234,133,602,393,298,342,391,741,198,946,696,53,877,261,204,267,980,325,509,376,331,952,423,405,51,472,378,732,557,913,494,553,506,988,537,525,210,427,333,795,826,227,401,906,577,417,691,129,156,910,777,571,271,367,819,935,105,494,958,367,200,820,872,735,825,867,263,601,247,274,903,147,575,219,929,559,330,622,649,222,790,299,699,702,840,328,77,456,171,411,482,289,262,627,278,635,637,921,399,933,306,631,618,934,738,15,272,850,113,893,795,962,130,70,426,672,844,625,773,396,433,663,971,17,997,558,536,475,768,415,662,632,781,350,143,76,38,47,322,468,771,48,729,12,929,541,784,689,818,581,875,612,673,489,59,755,69,136,0,789,494,9,623,573,325,596,825,484,626,349,254,239,237,188,691,444,52,496,630,623,69,260,750,649,655,666,990,598,83,476,517,222,881,901,623,327,229,48,464,841,563,248,47,459,602,52,583,928,115,155,734,390,363,591,755,292,879,554,288,174,64,522,271,221,752,180,908,63,408,972,70,217,648,65,99,335,28,247,120,598,794,868,731,577,116,74,944,952,498,427,693,948,303,627,929,602,774,238,232,849,808,662,129,487,10,887,289,812,714,591,986,2,51,395,650,572,277,451,149,166,303,501,355,591,669,886,388,816,363,404,900,902,796,265,909,721,567,290,769,54,963,841,893,678,570,692,753,712,80,61,59,415,796,960,311,476,761,637,96,298,389,540,352,125,924,89,716,634,328,215,170,114,625,617,231,821,977,571,869,434,489,732,297,419,201,30,249,507,865,123,972,75,756,310,923,266,784,561,450,603,94,239,174,860,121,353,335,760,82,829,227,476,123,452,229,138,732,287,480,729,550,202,572,719,604,450,937,120,409,388,729,921,316,634,548,686,412,161,273,487,171,138,739,510,135,408,180,988,949,603,907,166,797,502,20,81,236,321,841,50,243,184,728,908,931,949,953,535,185,173,972,392,532,251,272,216,310,931,551,955,744,420,458,91,22,146,301,236,319,650,824,517,977,139,924,643,931,497,506,710,347,203,825,494,173,574,24,55,311,104,687,981,702,333,499,912,517,495,475,650,802,321,304,652,867,305,418,830,962,628,803,561,726,521,390,635,341,167,894,49,298,711,363,968,796,201,890,504,187,612,905,386,508,308,747,453,5,915,59,422,189,933,879,14,567,959,987,492,424,135,148,18,878,147,27,918,843,487,993,679,122,636,334,434,214,443,877,898,70,837,735,579,553,524,846,466,831,489,628,770,226,492,494,161,29,129,62,650,325,485,48,180,638,951,542,166,38,995,698,524,409,931,650,210,787,137,576,915,116,464,327,627,345,404,117,291,552,418,292", +"872,338,355,949,570,227,691,757,335,666,492,494,538,107,808,613,53,84,238,663,548,387,211,796,27,528,809,262,529,761,390,971,918,73,824,106,551,267,398,562,743,704,150,867,938,710,774,180,608,249,725,769,747,203,976,470,242,86,94,288,289,199,719,330,625,917,877,567,264,526,232,344,145,994,208,949,16,459,795,674,596,895,723,976,554,256,187,280,375,326,394,294,412,368,976,360,293,119,173,593,560,436,889,358,984,372,8,66,958,946,887,590,200,611,803,787,310,7,391,641,207,529,476,776,699,442,50,627,660,721,383,670,409,240,642,584,682,323,19,914,915,135,937,161,731,585,408,317,506,167,14,26,498,198,926,820,38,3,439,393,49,205,953,156,959,464,254,257,696,527,503,506,589,324,764,938,286,600,648,282,248,698,451,604,866,491,44,126,120,903,367,531,384,646,348,121,784,5,854,892,804,488,603,256,573,966,222,283,254,802,642,372,717,596,954,245,111,750,198,936,663,484,887,776,481,824,147,696,551,405,639,49,122,836,779,882,326,773,799,745,71,694,993,946,168,636,963,994,733,908,835,418,720,657,445,409,962,577,798,420,776,42,668,934,137,491,380,907,339,870,468,746,75,546,166,604,139,874,738,121,287,840,569,927,650,198,344,60,612,435,653,380,182,18,360,518,6,417,120,915,531,951,19,724,889,260,94,652,132,722,786,233,144,513,30,381,448,684,368,426,126,397,825,271,228,158,69,49,690,897,133,175,402,185,473,747,793,166,394,178,624,185,801,567,639,752,651,151,803,244,558,982,905,50,389,942,405,688,271,931,596,287,391,235,336,271,840,453,743,879,169,902,98,752,524,173,94,910,196,587,877,125,941,443,540,101,809,353,377,952,689,939,461,623,293,851,422,22,148,227,643,617,432,348,687,808,995,167,505,110,758,319,427,587,636,468,504,707,469,78,862,768,215,76,234,385,357,834,148,33,894,296,976,309,280,779,539,35,539,43,391,846,60,335,528,909,454,159,948,179,408,581,800,886,566,39,663,879,935,366,135,748,815,118,111,657,424,472,900,579,727,621,73,997,788,413,597,469,469,593,201,483,732,662,220,321,575,262,144,34,607,853,198,603,50,216,772,15,554,143,737,240,856,260,285,599,583,283,948,53,257,297,284,928,295,84,491,832,592,92,827,704,886,740,151,515,611,806,524,954,724,900,989,542,44,628,59,32,364,267,143,941,641,523,723,184,755,381,342,900,55,239,586,955,938,585,383,887,377,789,0,665,350,405,16,221,70,153,35,905,464,424,200,572,795,592,344,417,323,864,418,864,409,69,722,187,586,518,315,287,557,280,912,827,237,284,395,390,717,850,83,808,444,616,119,792,937,199,937,250,292,701,396,244,937,265,265,508,502,697,77,600,865,110,87,584,171,97,121,801,666,854,933,963,124,830,749,317,150,841,553,449,388,321,586,154,46,743,162,50,407,348,500,119,905,277,967,350,796,248,533,30,55,133,87,645,322,73,899,879,423,321,693,738,395,587,4,291,969,779,838,855,534,837,521,80,899,266,641,307,116,999,67,50,768,995,473,452,966,696,60,472,465,670,295,76,243,512,485,852,117,993,86,26,568,802,437,385,124,572,468,509,272,582,629,170,267,545,796,551,236,728,913,216,922,167,960,186,838,655,130,576,30,96,325,303,796,711,594,978,266,636,642,304,214,549,90,812,985,566,388,967,8,858,952,145,861,47,610,652,493,461,731,305,927,804,738,923,664,145,599,704,147,267,158,384,173,181,153,305,394,887,698,811,869,391,208,470,153,347,982,831,646,690,116,693,697,945,478,587,183,235,186,247,655,496,863,746,91,372,749,873,848,415,685,870,793,246,793,128,747,850,382,246,316,151,80,530,913,343,852,578,497,12,788,484,715,413,910,300,762,651,104,17,142,512,686,284,940,524,830,623,417,178,204,145,834,162,961,194,727,691,352,729,79,156,849,498,327,671,834,816,417,131,37,882,48,528,234,472,401,153,891,534,563,405,30,953,780,868,3,229,773,390,790,9,941,538,491,772,474,202,502,568,539,204,141,244,708,473,883,252,741,845,740,720,977,128,13,295,394,572,882,289,450,867,870,977,789,611,951,481,93,720,401,733,668,939,263,305,437,870,695,318,219,690,748,441,506,776,671,344,696,188,888,484,250,823,927,167,895,390,317,572,808,37,757,961,311,172,725,865,371,449,98,232,187,250,446,972,331,540,617,191,73,547,455,600,199,24", +"293,5,969,79,236,760,192,950,319,663,320,601,815,962,105,505,407,182,872,149,512,407,534,554,962,939,270,832,121,294,994,101,179,680,491,524,61,603,298,229,134,154,318,174,798,400,13,205,993,53,877,537,77,524,43,661,513,17,550,59,450,349,442,484,255,300,426,378,759,899,651,494,603,397,159,153,98,517,548,200,630,188,680,256,667,828,289,634,246,700,707,646,760,276,953,436,670,869,545,36,885,888,929,511,476,164,214,192,599,7,717,304,234,386,898,56,723,239,623,58,574,810,756,370,497,626,672,771,566,698,581,661,480,894,28,730,248,521,44,392,601,171,783,491,412,802,142,657,5,587,326,290,455,134,673,845,915,676,510,26,522,39,989,980,167,823,783,969,839,907,450,661,98,204,586,133,682,467,668,873,379,67,691,391,131,628,885,886,210,393,582,547,571,47,282,164,610,979,192,349,946,434,704,915,837,974,156,636,773,121,774,29,954,870,377,417,4,125,508,117,35,207,212,415,351,30,639,273,188,57,613,174,364,104,637,190,495,109,74,878,52,664,985,347,182,332,184,609,477,149,579,576,968,572,97,419,194,569,23,963,938,683,111,943,874,580,526,353,753,50,834,454,505,902,901,952,806,526,211,36,290,343,20,629,17,623,804,824,878,123,108,652,712,332,666,418,392,904,914,212,98,519,798,806,235,131,211,684,180,843,524,742,797,917,924,12,58,713,354,414,768,654,729,491,278,200,523,387,150,842,826,821,102,401,239,126,232,375,865,442,157,205,609,70,256,895,259,829,105,624,102,685,36,648,284,217,161,493,45,224,803,432,923,667,375,32,293,990,411,234,544,420,393,229,476,274,446,655,143,30,862,719,883,117,315,929,786,843,25,800,224,808,996,353,706,210,318,902,71,402,667,435,507,419,978,889,95,122,125,612,706,141,724,927,340,651,994,612,604,877,752,88,661,899,731,39,891,294,467,663,930,685,557,788,576,305,615,44,389,703,531,468,383,337,429,333,115,463,383,769,583,268,582,175,787,729,936,43,619,498,91,86,709,844,456,43,11,383,537,428,600,923,854,238,844,198,741,104,97,849,663,49,89,648,947,288,235,677,239,820,577,581,19,260,10,835,630,57,223,44,941,992,115,946,539,509,948,569,64,625,511,696,217,841,871,320,368,767,585,445,588,887,553,425,501,814,672,853,279,905,748,402,295,128,686,33,854,460,658,928,63,913,789,814,359,32,546,114,872,978,114,429,305,541,476,303,104,921,151,494,665,0,863,645,876,269,967,978,15,621,73,180,401,562,449,350,457,666,952,819,878,418,658,48,433,786,325,726,100,386,330,367,660,631,702,792,685,792,976,920,171,125,457,361,833,517,546,571,289,521,54,339,378,886,725,716,667,332,268,141,62,110,417,831,732,746,253,135,704,802,841,949,283,944,252,833,720,906,555,134,45,977,2,574,330,534,479,696,595,103,31,821,66,921,781,669,51,317,879,440,89,863,390,296,188,751,876,469,952,863,125,13,740,547,878,251,477,90,44,423,859,654,497,776,599,244,593,879,377,974,306,734,795,175,224,306,225,656,307,588,163,63,410,300,809,97,373,458,804,794,302,489,303,131,392,766,270,248,554,955,406,29,784,321,854,176,972,503,817,734,656,835,277,512,16,914,377,429,285,263,525,137,148,165,272,974,722,673,843,777,636,811,731,823,398,841,181,205,810,291,583,284,998,668,583,187,472,74,394,403,256,219,42,234,479,704,507,547,875,40,862,380,482,588,335,244,561,333,381,728,877,922,279,403,347,471,236,492,441,276,822,685,162,392,749,714,670,537,608,80,993,566,51,163,187,768,307,777,705,166,672,293,333,395,589,847,911,542,125,41,77,713,486,243,201,50,780,852,571,933,444,406,553,38,185,343,776,570,401,266,438,973,130,470,31,498,544,890,443,301,711,921,109,862,505,777,770,53,480,809,891,489,495,524,32,15,644,321,888,990,462,947,431,177,15,221,506,566,522,930,324,485,303,948,65,280,521,972,786,984,740,986,181,778,997,676,564,643,902,415,324,841,774,706,929,817,81,186,904,319,745,616,719,471,345,831,521,124,520,811,636,225,714,319,475,47,857,809,495,108,518,722,575,602,362,378,608,974,355,59,204,638,586,272,185,135,913,919,337,345,303,169,690,585,614,398,344,509,339,201,382,312,192,526,214,67,243,993,750,536,161,55,454,148,139,786,410,25,947,421,344,498,728,648,949,92,42,749,710,849", +"697,467,510,979,559,143,189,351,528,909,526,503,396,560,482,617,250,444,8,612,707,298,568,170,981,243,950,466,238,302,438,271,611,618,926,246,933,892,495,301,931,839,747,919,491,378,582,23,825,544,864,768,939,288,354,559,557,449,397,454,182,704,773,377,865,166,968,398,577,466,646,613,457,32,102,515,432,948,432,271,719,917,124,919,547,854,305,792,96,192,198,470,335,845,690,433,311,271,896,955,120,614,7,551,214,552,814,934,692,190,446,641,944,857,661,21,166,659,971,391,758,822,21,533,36,289,636,11,942,468,853,460,619,272,560,317,50,584,963,117,979,323,35,923,42,616,741,181,786,237,362,288,71,326,610,673,540,620,66,310,779,283,862,303,372,275,275,390,109,998,939,973,800,696,24,754,309,380,351,593,590,596,679,691,499,247,737,785,950,134,671,491,634,644,645,911,41,942,255,141,841,280,595,207,975,843,14,319,329,855,363,620,622,906,997,902,790,617,688,728,588,556,594,420,370,272,228,694,569,594,55,923,950,566,902,362,723,925,742,19,272,559,336,936,935,856,844,410,187,945,927,170,221,876,626,358,54,11,115,908,835,350,271,335,300,770,897,449,188,850,969,234,816,733,297,753,161,5,952,324,120,467,538,70,778,175,625,371,606,271,898,603,749,821,665,737,324,18,482,780,113,583,706,538,260,347,605,469,353,689,417,694,523,413,779,494,907,999,409,753,310,586,731,449,681,498,626,162,236,833,650,275,224,625,474,115,911,127,634,839,129,152,253,925,447,713,311,666,423,100,977,598,180,293,400,330,499,462,748,382,276,885,242,730,159,958,568,902,884,569,215,35,457,965,17,944,28,931,467,174,485,20,436,601,148,688,439,150,710,607,851,566,667,473,246,365,499,281,683,259,67,113,51,272,504,368,258,680,59,606,774,723,749,395,110,483,231,236,22,292,451,841,82,956,317,585,7,239,99,137,502,673,764,441,338,13,837,372,582,164,122,816,959,604,524,337,619,126,620,563,474,383,193,444,655,476,823,525,930,493,412,18,879,211,794,486,76,514,340,31,9,731,574,571,350,725,652,711,909,347,858,882,570,340,884,439,22,952,628,921,414,271,367,239,17,729,862,93,583,545,979,834,685,70,115,836,935,879,64,709,890,969,665,224,441,44,787,673,164,758,535,639,979,352,568,245,544,872,9,112,636,145,726,111,1,429,922,196,220,43,973,177,691,851,617,76,256,674,714,896,982,756,192,670,536,765,191,992,77,9,350,863,0,117,652,697,443,55,905,214,198,425,937,103,804,28,828,537,140,891,658,513,628,270,522,535,667,936,124,973,257,524,434,430,201,716,503,351,54,176,70,584,636,530,152,359,23,990,785,31,478,361,504,615,747,17,223,850,953,889,981,41,830,728,741,375,484,453,685,47,465,196,80,110,380,127,57,954,763,727,371,796,885,223,62,628,336,943,879,463,234,132,267,220,851,45,981,313,420,445,316,573,188,54,981,480,89,877,599,558,717,546,585,453,415,352,476,503,999,811,701,3,198,715,379,55,553,413,316,184,92,561,590,720,242,985,296,737,636,46,77,681,14,120,696,481,631,259,21,372,887,855,512,236,520,749,488,121,715,415,262,428,105,370,24,997,200,489,298,935,3,707,880,992,988,534,636,831,683,931,312,797,529,918,373,550,369,97,464,213,496,140,783,218,581,607,594,157,439,691,79,446,250,77,58,486,841,634,683,530,837,469,77,18,5,402,565,359,248,402,978,894,95,467,447,111,88,835,19,74,189,896,822,226,544,580,500,148,63,863,131,522,468,27,525,964,111,581,849,39,719,370,604,299,607,811,557,221,308,993,675,505,476,88,263,233,225,341,247,25,252,880,407,428,981,711,714,439,298,772,83,336,320,417,969,373,957,167,440,331,733,595,185,272,598,194,904,605,973,724,418,138,242,635,975,146,993,779,102,321,647,929,193,937,862,908,450,929,973,452,436,191,610,280,462,185,119,138,911,667,378,416,150,330,593,416,124,777,975,465,954,323,879,411,480,931,808,328,948,43,274,54,830,919,397,713,499,321,675,729,992,513,218,218,280,884,117,958,472,775,180,987,862,676,31,6,347,432,434,155,803,658,248,954,804,929,564,830,301,237,104,46,375,766,915,57,591,498,985,112,246,280,16,887,44,364,702,479,458,513,166,139,614,968,449,862,24,151,24,255,685,811,779,827,988,766,156,235,912,161,161,379,527,76,19,353,151,611,928,446", +"348,894,610,134,417,956,555,926,878,411,666,797,147,815,603,348,925,530,111,297,329,161,685,784,265,450,881,910,690,35,872,55,854,78,499,578,128,731,811,194,241,993,838,355,609,477,325,653,73,319,271,214,663,658,876,140,153,734,536,228,167,890,767,86,797,280,767,681,509,459,345,207,28,88,262,75,76,732,509,807,666,315,281,465,384,880,857,515,385,546,468,224,104,576,987,14,173,253,159,583,648,175,136,876,353,629,509,428,311,965,617,874,618,138,880,194,127,773,565,525,389,983,35,705,708,286,781,846,864,150,197,907,593,215,657,21,536,526,655,352,105,761,645,697,946,926,500,680,993,2,810,437,946,198,15,918,667,721,238,389,659,756,1000,310,859,815,877,123,417,577,117,108,53,388,167,101,208,242,752,816,967,583,595,577,318,220,32,980,469,795,857,327,65,4,966,84,164,472,58,748,864,246,421,390,24,582,141,491,794,65,366,374,650,352,147,896,268,611,719,827,735,184,138,912,971,857,676,151,125,882,452,998,61,826,762,703,225,292,10,892,585,960,260,29,561,517,194,369,256,590,356,368,887,423,832,705,933,836,697,890,338,831,93,968,778,605,574,155,722,645,901,585,384,857,520,667,382,807,101,922,313,714,381,714,134,771,209,506,316,538,113,290,355,950,64,676,880,98,106,679,877,876,647,314,651,591,23,632,856,906,276,452,988,80,166,574,333,927,704,457,641,499,234,386,919,517,113,663,945,538,521,876,366,232,955,805,903,962,617,702,859,983,190,545,591,968,323,818,495,804,806,803,917,409,953,727,804,466,874,383,170,836,186,195,746,968,384,434,952,694,908,433,725,17,564,687,274,274,872,702,650,199,74,505,826,923,303,104,14,105,728,478,392,663,884,53,543,293,517,668,391,179,325,296,786,175,746,387,644,179,487,670,427,255,896,863,211,799,431,414,376,919,106,765,147,122,360,674,722,71,109,356,232,664,161,589,663,170,69,568,998,942,808,232,300,128,872,957,968,233,823,218,312,119,232,369,274,692,397,847,629,92,102,744,103,254,296,967,243,425,537,684,692,5,481,264,300,26,468,438,455,205,440,439,940,863,160,611,265,639,271,646,675,486,795,71,515,881,328,346,46,752,174,414,15,623,3,575,180,450,507,184,46,819,304,875,495,897,295,867,610,254,951,559,673,351,664,711,722,871,665,255,598,560,765,790,589,981,843,464,772,215,565,448,817,819,685,925,584,887,808,962,60,509,32,405,627,387,385,623,405,645,117,0,896,203,883,544,286,954,764,382,231,34,576,827,839,835,151,442,768,934,818,905,89,831,646,66,25,191,67,835,447,705,554,798,182,568,312,938,446,778,425,481,92,174,630,856,371,564,799,116,477,33,260,208,60,25,281,826,108,319,916,211,536,423,728,158,563,143,419,18,943,115,633,46,840,136,653,362,937,561,243,827,793,798,682,838,181,355,360,818,974,926,739,302,102,834,251,393,285,144,265,945,836,321,754,358,318,999,971,486,960,940,463,583,750,204,346,627,989,494,907,898,262,508,411,327,568,653,892,379,970,200,271,793,887,983,380,606,417,10,590,206,400,781,550,471,679,638,41,586,966,914,887,188,116,690,724,195,307,785,716,804,33,57,143,409,757,5,776,863,748,204,262,545,628,997,882,127,758,522,794,126,525,404,719,152,240,536,846,541,237,756,587,560,582,414,204,785,66,950,413,95,419,636,710,698,203,133,51,103,143,59,548,531,432,993,573,567,555,693,595,253,496,197,490,650,603,650,408,762,315,405,438,183,362,469,420,31,660,513,352,997,728,445,995,219,873,254,715,886,857,359,263,20,617,64,103,60,456,470,999,265,557,410,930,73,664,974,994,369,761,50,358,589,153,485,3,506,770,359,986,503,273,782,670,305,286,862,245,630,387,26,998,328,439,153,811,845,378,162,593,448,698,244,866,775,440,469,610,701,115,379,323,509,155,287,934,490,7,355,668,909,187,742,369,557,849,434,356,523,998,207,590,531,20,159,973,76,983,824,957,289,941,130,109,374,71,589,209,906,757,852,833,896,36,740,960,150,606,885,657,139,566,931,637,201,645,384,449,702,525,107,147,577,236,95,325,529,820,847,883,906,432,229,366,626,822,622,685,259,950,814,30,537,500,412,207,834,349,630,267,212,677,731,808,507,934,202,141,222,783,32,288,965,433,703,669,633,926,692,135,867,215,43,721,559,414,735,317,117,829,208,729,158,5,943,277,972", +"296,513,957,926,419,426,88,400,751,221,551,247,807,936,189,339,411,614,454,273,597,306,473,238,223,766,789,144,184,706,960,126,791,936,831,783,670,658,908,746,639,81,638,702,869,71,570,183,243,228,768,42,173,984,809,558,768,342,364,641,76,710,804,671,323,978,854,889,94,328,382,132,851,825,586,596,274,439,560,792,858,450,57,190,316,551,784,112,423,998,546,934,56,560,499,343,705,47,124,8,547,126,606,846,8,157,226,468,194,80,858,79,264,165,323,499,389,628,56,285,415,95,784,772,35,182,469,377,868,477,872,993,727,46,616,221,24,553,570,150,118,693,220,770,585,413,838,213,775,427,471,64,546,968,96,61,526,451,935,613,512,853,330,604,42,103,722,917,995,763,592,984,45,845,756,544,730,704,102,353,647,623,929,594,629,196,202,908,986,594,650,628,187,822,454,513,234,493,130,598,886,832,978,696,398,426,779,575,294,713,859,912,989,595,333,183,30,207,368,459,111,398,259,798,383,303,294,440,286,645,53,60,971,512,453,744,261,211,711,910,444,152,243,708,987,8,787,612,779,497,577,898,373,882,89,97,584,426,988,567,224,219,845,461,244,844,532,650,724,287,801,759,824,814,697,566,502,738,107,842,642,757,614,487,394,255,485,368,182,608,248,169,164,836,218,430,154,779,738,201,439,365,967,225,477,824,490,692,824,428,864,388,543,680,921,658,523,821,604,678,508,528,173,567,511,696,439,360,880,672,81,266,620,775,531,226,933,944,497,975,448,364,723,298,86,62,911,204,450,292,930,408,706,774,105,891,361,936,828,452,847,556,125,300,700,969,612,601,519,474,762,49,703,788,228,721,570,359,834,179,727,237,640,126,682,268,101,972,769,206,772,864,924,858,942,249,788,19,351,104,515,850,457,314,938,956,324,891,154,10,190,464,948,35,590,458,883,576,786,443,870,419,396,924,645,315,209,717,76,422,685,903,999,465,713,565,369,834,735,13,603,692,837,669,650,308,218,610,325,424,731,123,928,313,799,945,726,412,667,215,930,743,726,145,16,821,432,17,978,525,601,734,237,298,814,262,663,290,464,553,275,59,750,886,390,425,374,406,211,716,653,460,279,242,997,33,211,719,128,958,161,695,589,302,580,459,766,403,136,368,312,340,617,741,344,624,166,104,508,792,884,426,552,565,866,227,387,301,308,380,164,799,901,592,471,859,606,297,954,682,611,177,455,469,746,737,965,573,692,556,470,850,860,84,251,676,444,436,321,573,16,876,652,896,0,113,972,954,50,558,584,635,879,203,157,861,995,771,670,510,171,17,387,921,551,104,639,861,562,111,632,123,716,457,65,952,245,833,869,896,622,349,883,217,606,689,500,121,938,563,744,870,650,831,998,975,23,51,527,314,235,50,724,692,968,855,602,323,548,962,128,68,829,767,700,157,613,710,658,695,219,546,226,930,71,967,370,981,511,895,898,719,833,518,751,687,468,187,844,19,806,106,999,594,844,957,886,113,700,308,762,775,788,890,652,227,155,111,702,651,302,940,149,376,628,412,895,619,577,679,464,155,695,39,292,188,709,875,867,952,494,299,107,125,905,897,423,160,955,126,890,885,301,430,41,614,961,735,780,297,935,211,748,863,454,661,489,329,395,727,832,347,721,861,830,382,404,130,51,124,74,660,854,886,980,173,84,862,60,30,736,649,565,928,377,832,125,974,103,459,971,575,963,947,608,989,939,117,930,926,675,865,52,964,942,812,627,268,538,277,980,127,642,391,26,836,937,424,888,724,74,575,24,411,197,790,268,69,608,296,366,357,999,231,205,995,746,798,375,121,304,78,48,707,139,108,338,329,877,468,902,994,974,671,947,274,831,809,70,986,848,805,231,447,58,279,373,655,235,190,99,659,896,431,203,884,220,300,710,705,368,318,703,670,415,311,627,793,234,278,54,457,578,615,29,289,71,109,551,221,329,716,204,88,430,444,3,91,510,321,518,910,268,804,432,749,811,97,252,800,894,150,516,322,582,741,491,592,362,622,604,395,797,72,161,481,486,138,795,481,379,28,338,949,620,34,181,988,291,785,439,979,237,287,10,662,289,477,914,251,854,253,275,832,418,326,794,373,702,747,824,591,520,592,989,415,857,477,310,749,241,922,143,782,67,180,843,64,154,533,891,658,166,466,736,295,81,724,784,974,932,465,868,58,973,312,528,236,498,354,410,438,160,642,575,322,490,234,271,214,232,912,628,917,695,336,413,109,108,551", +"472,352,696,103,971,241,41,169,825,23,158,352,230,460,487,469,920,208,476,733,724,831,48,248,598,23,820,655,611,520,168,426,102,480,942,511,546,875,116,14,300,670,790,499,21,656,976,749,429,527,666,415,425,944,597,54,254,887,227,738,604,534,194,970,196,393,365,83,281,716,115,980,99,366,247,200,908,635,326,704,866,790,281,173,202,899,149,624,14,678,114,312,905,311,625,615,867,145,595,420,342,675,137,661,689,963,235,274,528,816,289,610,821,415,364,90,79,71,372,154,503,727,189,927,323,522,858,235,834,19,395,798,875,206,902,257,357,20,568,481,429,631,400,831,333,404,79,821,768,604,68,718,428,363,882,477,720,34,737,179,449,719,650,745,810,478,349,443,424,563,32,287,724,418,966,583,304,42,765,380,206,356,173,438,746,688,122,674,784,208,996,568,893,865,670,768,50,971,147,728,920,867,347,196,221,293,497,992,350,633,498,339,610,893,948,334,849,41,630,403,556,869,624,129,579,484,774,263,605,948,510,221,108,910,877,630,295,45,729,957,602,914,461,870,369,848,112,763,422,176,576,98,688,860,25,596,14,448,545,265,496,628,53,364,60,617,828,980,26,398,520,964,36,654,47,603,771,186,591,61,752,59,446,202,220,233,72,321,801,31,993,52,356,32,664,514,388,589,138,427,266,368,348,157,113,904,666,341,972,827,737,376,920,365,231,476,370,384,892,311,854,621,716,591,451,916,162,600,84,428,584,26,554,509,917,532,397,812,942,130,432,12,816,832,868,979,61,515,705,542,473,200,571,571,703,283,593,774,645,616,915,212,550,884,994,794,167,805,365,803,791,701,140,204,530,115,978,906,440,138,175,620,113,653,748,802,117,958,538,470,310,947,266,47,464,273,230,746,630,194,585,573,641,561,970,58,63,772,355,815,638,87,441,613,382,859,528,963,384,824,70,547,988,771,251,509,724,730,176,663,102,961,261,164,716,719,832,924,348,741,729,714,296,756,829,854,61,516,723,402,370,568,477,240,681,231,889,802,502,59,310,583,179,356,215,91,566,960,156,516,496,620,239,177,63,978,268,732,397,363,680,479,449,382,407,778,176,980,781,832,635,120,848,106,595,23,663,930,456,446,155,548,565,315,354,721,619,520,111,487,96,112,62,360,807,181,15,425,198,998,722,499,222,974,634,233,277,331,193,880,721,612,584,968,767,144,557,745,658,705,743,690,209,868,816,4,523,115,378,701,479,537,185,65,740,827,43,709,651,325,221,269,697,203,113,0,264,58,864,442,855,756,308,941,567,604,633,109,973,583,259,591,12,496,365,608,518,614,672,381,763,782,372,914,697,319,228,271,114,524,124,374,92,534,242,80,832,867,893,356,477,115,442,62,910,944,931,873,354,735,364,942,421,995,281,3,77,26,729,219,621,841,73,661,428,810,314,334,253,131,4,830,285,93,169,108,924,789,921,318,17,942,138,925,526,651,860,664,517,629,615,913,695,283,699,579,372,250,74,802,418,783,592,95,934,709,712,730,822,64,904,521,442,102,631,274,692,640,331,714,962,704,241,50,1000,362,481,831,646,813,689,73,722,874,936,478,342,694,454,593,208,399,239,355,96,677,293,523,946,943,600,145,195,418,70,205,888,142,332,867,868,250,914,825,664,550,463,161,610,804,669,619,287,297,185,313,10,684,441,791,874,481,859,372,874,494,450,622,602,930,328,761,161,870,546,820,435,887,756,489,337,481,351,269,919,109,757,178,991,370,335,144,6,996,557,392,339,404,382,57,452,529,23,793,301,260,72,852,463,466,163,627,15,264,412,928,606,31,235,243,630,425,872,68,588,561,518,898,53,966,530,640,368,194,538,628,804,402,204,549,970,273,960,864,892,851,676,876,701,281,615,564,811,104,904,425,873,10,451,59,741,766,954,64,496,630,195,198,651,435,592,383,277,508,168,733,490,747,734,106,702,786,407,675,763,166,554,21,14,713,218,392,590,858,440,513,134,311,344,556,193,180,921,82,795,316,352,72,238,949,400,714,180,745,429,338,317,890,303,4,826,112,69,463,570,682,203,648,165,649,286,397,255,792,424,841,320,531,81,7,98,492,92,359,894,829,222,772,398,439,92,673,601,47,179,509,825,370,168,604,366,664,315,685,756,171,260,993,501,93,717,211,578,389,119,362,344,575,612,991,658,900,880,623,928,800,981,908,201,44,848,292,722,985,491,276,950,859,359,369,635,8,428,756,427,623,412,97,418,486", +"951,630,505,578,269,20,663,612,756,829,72,651,875,313,510,458,674,823,201,132,591,386,891,108,249,793,165,415,386,574,349,82,504,436,994,699,646,259,852,236,164,918,164,140,483,610,19,672,827,964,986,293,887,179,117,463,228,348,1,592,434,985,297,728,995,153,125,50,17,557,575,222,393,804,369,497,567,278,525,857,440,759,812,667,594,542,221,389,178,418,673,884,614,978,841,909,613,839,914,808,413,430,37,654,515,181,522,447,834,13,828,274,507,465,743,7,504,529,670,107,403,304,446,873,549,209,582,501,272,249,653,145,990,860,887,731,510,830,267,334,322,580,276,200,126,405,334,341,169,743,720,283,966,922,943,582,190,155,619,306,650,459,119,404,404,365,656,462,307,902,88,778,865,878,296,248,706,665,165,226,932,232,840,849,595,524,50,735,762,796,66,600,599,516,408,439,737,157,631,115,627,475,316,237,386,316,229,696,206,423,595,554,234,511,963,893,789,505,786,712,749,207,786,316,271,316,454,208,563,484,270,139,985,302,308,685,789,78,512,490,233,717,968,160,708,724,342,622,13,177,544,125,101,398,286,440,411,354,856,207,251,815,158,538,319,310,893,654,893,470,308,586,68,896,312,51,919,97,790,567,557,297,39,652,686,900,797,140,508,120,500,484,854,928,159,136,883,226,97,519,625,746,93,214,157,913,726,67,6,753,913,613,282,757,483,665,782,765,620,113,175,973,922,843,210,718,187,441,349,458,894,814,344,531,453,396,419,766,526,645,600,787,711,709,658,795,101,513,887,274,256,272,864,134,720,315,24,883,927,499,923,941,176,371,956,752,221,992,573,393,508,842,10,499,607,952,422,481,116,167,427,568,855,784,47,245,449,695,816,380,602,414,863,255,827,190,943,432,233,402,37,618,359,558,644,357,705,125,96,686,299,673,531,679,170,69,261,961,451,127,209,780,617,91,242,340,599,132,210,835,486,251,232,718,862,984,474,997,701,299,396,209,56,580,268,594,592,798,398,734,352,337,135,242,979,180,565,555,717,205,876,669,887,256,263,848,704,485,952,650,147,562,553,872,34,340,33,605,148,594,419,760,736,345,703,80,15,547,776,16,247,382,299,961,716,257,372,324,82,617,594,630,747,877,455,449,882,430,400,117,727,171,943,710,682,130,627,496,567,242,752,103,442,986,3,704,470,901,110,522,789,830,633,72,770,918,452,297,614,95,49,484,816,609,210,442,850,85,983,261,528,656,68,189,598,707,364,238,94,596,70,967,443,883,972,264,0,93,76,850,220,96,750,521,393,618,268,500,39,335,943,656,71,703,362,806,858,212,848,573,602,248,105,987,630,528,124,693,693,24,566,148,425,314,775,606,233,425,926,516,62,301,883,945,456,73,536,707,240,470,254,160,926,703,825,122,581,792,425,798,102,227,387,157,941,332,154,526,978,836,355,600,151,893,744,621,628,460,670,562,248,34,965,550,529,69,724,164,252,244,288,345,866,655,957,741,85,945,815,334,603,887,839,375,489,628,580,280,949,437,733,353,411,783,467,506,73,487,886,204,802,462,382,833,912,697,144,838,444,47,212,245,760,760,760,38,444,401,676,936,285,444,610,387,830,930,301,116,753,120,40,463,308,57,341,726,266,283,55,804,639,580,898,693,544,526,579,99,849,61,285,923,634,340,6,182,612,716,184,114,175,795,29,396,671,621,380,795,134,214,128,498,877,686,122,680,691,402,251,536,640,183,667,176,754,511,921,793,523,765,11,580,372,205,405,112,511,126,262,377,430,440,289,208,662,581,746,950,59,438,807,544,21,120,240,55,185,178,815,515,977,856,934,796,773,113,818,540,939,103,364,389,912,210,18,976,600,885,862,644,633,691,208,546,436,653,931,766,362,125,841,318,529,37,662,696,514,606,327,40,847,454,79,320,777,307,421,256,907,422,569,335,310,223,770,322,309,852,687,168,453,439,298,908,589,407,721,605,34,356,983,772,342,211,206,619,738,950,191,236,709,288,438,48,714,199,751,381,75,389,670,99,94,368,667,235,933,318,802,519,376,249,850,863,112,914,768,325,783,266,684,694,907,679,688,107,228,395,923,365,109,850,780,821,488,450,146,967,996,806,185,89,413,274,673,9,615,244,859,752,87,500,575,497,141,793,762,507,508,326,903,13,601,291,633,821,824,316,543,541,325,936,677,121,678,68,202,800,132,507,973,824,765,470,61,77,772,415,595,29,947,825,374,339,531,456,108,76,287,13", +"117,460,533,97,858,569,150,600,957,125,20,104,996,990,380,602,411,908,110,468,157,128,652,228,949,838,14,601,817,896,230,616,718,932,702,267,742,629,167,380,580,152,560,405,175,427,950,185,481,731,947,641,64,611,393,574,793,968,777,964,225,602,81,726,390,556,138,201,525,443,271,453,69,127,961,704,186,345,99,375,798,273,915,422,788,715,834,55,39,596,798,509,822,688,838,125,991,311,294,712,164,970,163,902,436,554,215,828,497,802,889,787,710,75,553,626,52,233,985,557,377,707,316,963,640,235,796,689,211,730,838,601,764,96,753,641,8,366,342,843,429,465,810,57,758,298,305,314,588,814,186,548,292,84,848,729,540,809,94,139,38,236,404,587,756,402,610,89,913,183,320,615,611,608,622,939,100,264,246,186,238,816,984,121,271,365,326,139,685,708,76,434,631,655,608,337,981,483,485,136,699,745,654,800,202,663,960,437,172,259,678,357,635,74,541,921,313,881,782,767,469,873,22,209,278,205,675,490,101,313,966,226,258,18,909,866,841,234,791,575,223,189,954,37,632,565,191,813,674,59,97,284,743,416,547,784,150,820,866,680,64,414,10,686,518,275,308,676,568,641,545,940,581,526,419,774,438,530,24,68,873,160,907,408,926,998,450,208,671,875,362,213,832,410,250,82,177,599,334,461,150,329,591,420,569,370,858,866,814,848,989,111,401,424,811,368,96,894,802,333,332,508,612,278,794,472,193,760,239,655,98,809,740,766,448,975,949,445,579,778,833,106,932,395,945,725,752,54,781,887,121,51,902,525,333,216,876,894,4,86,694,144,639,158,898,180,804,167,268,744,533,484,857,673,20,498,618,865,930,992,11,503,259,169,418,19,16,529,166,26,73,667,455,15,782,279,12,22,973,636,102,438,469,871,639,728,899,490,365,667,692,256,667,445,121,728,341,563,402,215,43,839,289,57,324,907,585,597,72,981,373,941,588,796,777,437,650,505,75,677,658,791,269,368,71,285,148,306,818,547,19,822,745,949,934,352,45,938,546,35,14,616,962,295,304,386,297,171,556,701,449,88,632,51,30,168,183,744,58,126,68,512,472,707,972,516,136,52,178,88,941,484,218,679,419,952,270,246,92,668,162,560,322,578,364,871,444,613,204,175,983,564,259,492,280,265,637,516,824,674,690,970,889,247,530,222,594,419,480,143,361,459,754,200,188,782,922,233,276,437,337,651,882,973,3,292,93,772,247,880,64,458,680,989,458,43,501,704,681,825,153,978,55,544,954,58,93,0,55,698,856,36,443,109,404,864,991,13,327,212,854,535,823,21,115,504,842,415,396,827,202,413,342,532,777,339,167,166,975,272,175,964,416,599,824,206,886,244,681,899,408,401,427,984,555,796,525,648,488,635,365,14,747,427,61,106,160,180,168,736,388,30,370,303,759,830,888,551,833,655,82,744,87,588,225,74,482,341,302,447,460,799,756,277,236,59,504,129,556,392,798,11,310,278,352,634,865,282,475,476,558,26,240,699,150,769,259,205,262,755,281,622,860,823,563,24,846,902,28,107,216,987,947,186,164,762,501,448,456,772,44,709,633,854,951,776,283,566,654,257,775,49,246,671,489,543,361,4,124,725,806,489,814,668,7,457,954,879,428,730,539,909,117,315,945,329,768,690,844,658,84,66,688,356,738,558,442,865,908,527,33,594,534,269,519,477,35,315,203,15,66,963,574,583,93,319,495,102,832,845,562,577,867,866,721,268,139,776,491,61,136,444,372,820,596,622,735,50,138,445,683,567,629,863,45,462,308,155,106,48,180,740,357,243,449,737,969,156,594,28,491,110,267,370,168,943,965,471,444,529,416,453,380,462,75,17,83,469,382,376,176,445,273,851,274,41,610,992,707,85,44,126,344,58,762,549,847,333,280,130,571,464,244,717,907,667,162,866,353,384,669,102,39,210,494,490,621,795,95,501,456,231,377,319,742,8,831,922,544,976,934,157,187,247,272,418,874,568,642,836,448,425,295,453,995,549,152,192,807,185,691,235,294,267,888,499,533,936,273,927,945,682,795,704,966,537,78,705,570,886,522,982,117,232,508,509,683,732,674,838,146,236,706,622,919,355,78,146,218,725,349,876,788,877,151,740,935,13,722,940,841,42,216,671,173,319,278,382,68,576,509,273,389,274,87,93,785,264,615,125,80,43,877,235,259,54,962,178,547,224,612,181,818,633,52,927,163,357,552,145,795,337,4,300,770,816,813,806,142,629", +"464,511,884,905,28,828,13,322,821,549,631,462,189,157,658,340,169,547,299,710,445,163,412,498,436,862,198,118,209,259,946,61,392,323,441,596,320,757,859,892,92,955,476,273,944,635,172,586,319,251,272,390,57,565,858,967,756,767,442,861,875,870,760,548,36,769,593,948,911,175,312,209,913,875,125,905,947,380,69,506,226,222,376,449,135,146,737,782,811,337,858,456,376,965,62,166,525,598,624,404,678,265,612,903,991,966,304,912,137,87,337,35,746,152,969,207,66,562,744,391,681,146,970,458,730,778,869,16,152,734,806,353,748,570,775,925,933,36,164,557,714,870,39,505,645,661,301,591,738,564,154,435,649,888,240,553,289,635,707,453,978,758,174,775,272,573,703,284,412,558,498,168,697,672,517,643,123,301,118,525,289,539,900,375,602,833,935,268,17,670,110,504,8,459,395,183,391,30,960,257,294,480,381,685,362,920,184,8,646,510,101,973,17,664,4,841,751,123,558,460,433,606,706,399,549,193,595,609,291,449,152,836,760,948,383,894,429,549,473,580,122,293,305,232,883,679,927,151,194,966,850,690,933,228,286,833,873,949,72,95,418,327,308,196,811,334,394,608,775,240,493,457,164,619,673,53,404,917,233,46,711,35,646,455,683,996,842,743,249,215,700,576,580,570,661,282,255,234,443,892,230,129,972,620,930,120,119,283,682,325,468,2,652,374,313,740,92,332,708,702,56,270,721,463,445,39,761,125,846,509,336,302,109,938,192,437,3,103,291,946,97,86,793,645,351,854,909,231,923,439,986,910,181,446,682,762,663,822,719,777,702,311,323,122,598,265,457,129,256,994,472,167,876,843,164,181,191,317,135,399,373,235,523,613,679,675,310,346,503,781,806,111,669,551,227,49,4,909,201,181,611,871,359,189,13,927,663,503,925,834,625,972,870,443,199,606,568,834,204,672,41,539,317,957,677,830,221,841,385,826,989,844,246,338,755,293,241,218,616,386,843,194,783,154,623,23,929,571,454,512,1000,648,996,826,380,111,387,346,996,503,113,129,354,368,164,219,230,638,267,219,245,515,94,549,77,851,41,230,275,401,681,747,403,792,979,427,682,280,254,356,56,440,930,854,832,182,305,912,271,744,546,426,558,734,374,546,424,682,105,729,989,976,669,584,746,61,488,392,298,115,115,462,699,242,415,227,297,888,410,310,746,266,375,340,355,610,436,183,87,163,491,563,746,465,800,14,632,335,284,362,28,986,687,661,962,167,642,730,69,484,35,15,905,286,50,864,76,55,0,482,19,958,571,324,25,29,249,561,240,725,349,257,624,914,93,706,626,582,963,552,264,490,24,450,741,906,645,671,997,762,553,531,268,191,166,572,324,460,806,424,690,866,46,252,995,603,790,395,84,331,281,572,677,194,459,715,410,496,14,204,66,972,781,412,312,194,505,250,106,701,549,83,437,361,644,300,729,241,976,98,699,205,925,819,909,997,347,67,666,903,13,42,50,961,171,641,632,977,22,611,59,163,52,965,104,974,69,210,44,560,98,564,175,11,874,788,275,500,689,764,112,525,780,498,691,565,341,678,995,390,372,236,48,913,241,985,787,367,926,617,257,642,323,458,196,27,468,224,506,197,839,576,726,135,491,901,34,774,775,241,167,700,447,58,257,793,407,225,968,353,117,316,185,738,701,909,592,356,791,111,842,306,347,327,476,325,603,705,477,378,679,857,938,498,974,582,122,225,774,801,691,227,197,170,600,613,199,485,843,34,302,478,971,33,37,253,942,392,633,824,406,45,869,923,546,548,548,268,861,292,565,955,580,994,708,920,940,59,6,191,445,300,388,254,454,395,651,171,309,59,665,960,8,733,600,706,915,73,342,167,213,577,114,735,545,123,392,662,275,29,298,191,941,876,471,958,44,889,184,811,158,52,356,609,189,706,794,96,56,626,837,600,529,764,333,274,61,943,206,534,6,965,96,241,746,674,770,917,688,449,390,35,102,260,423,596,252,660,276,659,285,625,126,160,221,662,721,950,213,476,227,828,343,206,595,943,284,607,917,445,407,514,651,886,729,52,443,350,989,664,448,386,395,634,839,800,660,819,623,440,992,73,235,789,55,192,134,216,470,561,889,342,209,94,866,171,629,427,910,607,955,431,466,257,242,132,247,350,668,909,586,734,131,169,235,590,607,77,142,378,641,501,977,585,280,410,797,525,33,102,887,302,517,245,552,780,826,633,44,858,132,396,111,549,455,527,706,91,586,649", +"843,179,754,866,151,373,367,451,500,323,751,920,557,398,387,538,633,116,913,80,470,471,144,337,759,322,405,119,114,367,945,263,651,306,811,914,410,78,439,395,412,464,69,426,591,946,454,411,43,893,697,830,76,208,628,869,341,675,527,445,790,305,490,558,308,254,635,884,686,237,501,346,999,280,260,135,970,781,57,400,299,830,612,248,453,17,799,602,409,944,34,32,460,337,639,527,700,106,924,793,877,895,524,396,386,496,793,253,518,49,326,701,905,129,153,675,674,124,349,937,849,167,135,118,251,281,818,522,945,744,190,327,431,477,334,479,842,311,239,462,175,299,560,958,719,253,190,738,930,84,75,190,973,202,743,493,599,326,950,558,969,407,707,918,68,601,71,907,142,966,461,391,660,29,135,607,671,989,488,495,435,926,496,539,14,244,77,740,373,221,359,286,584,54,24,919,365,542,493,517,768,709,807,134,752,126,595,100,867,289,278,632,314,606,40,548,730,350,569,780,879,756,377,261,930,296,709,971,707,566,432,964,536,131,967,234,301,79,987,506,920,401,244,718,75,645,365,633,383,404,695,822,944,861,910,406,535,288,328,701,178,588,687,321,643,781,787,634,804,202,13,465,749,422,216,357,604,753,331,693,358,288,869,352,44,212,407,283,558,792,846,173,36,562,907,866,240,250,115,623,534,618,160,567,922,255,978,666,547,252,944,544,123,153,259,943,259,336,24,527,509,169,304,515,262,596,909,454,746,187,432,293,886,822,547,874,350,352,899,564,663,105,708,402,902,513,241,583,927,722,456,956,326,549,627,522,391,465,870,261,567,161,481,242,766,575,868,718,642,807,289,897,620,965,759,351,715,311,563,756,527,707,140,229,619,533,841,681,145,309,444,890,415,72,952,660,663,199,810,258,616,723,538,98,438,295,81,320,799,907,384,997,94,958,13,164,874,557,975,517,577,881,19,468,489,872,278,438,263,287,504,903,442,373,101,808,710,827,985,739,988,768,657,890,487,55,915,90,395,36,652,397,933,67,925,36,476,765,585,446,641,391,170,469,459,729,676,270,124,563,813,276,977,193,594,151,953,173,93,774,608,939,684,856,645,222,10,545,519,212,349,49,412,969,562,274,471,738,755,473,921,35,491,883,493,371,355,327,259,25,912,543,836,228,915,97,465,948,902,729,488,132,761,564,93,645,925,599,763,711,3,602,343,511,383,923,597,163,306,681,111,451,613,692,446,641,391,651,803,110,432,789,593,387,56,164,460,179,827,626,905,621,214,954,558,442,850,698,482,0,989,42,987,341,757,112,143,220,800,624,536,355,325,630,168,635,702,873,577,617,881,224,949,834,152,249,336,847,386,866,278,265,493,585,851,946,256,21,746,182,131,587,901,743,375,472,489,705,989,909,757,338,491,466,538,53,773,961,544,411,397,657,790,736,143,868,336,765,288,383,504,926,820,152,811,804,104,640,757,884,732,944,318,323,253,958,761,807,734,759,59,788,436,448,9,244,284,977,641,748,562,274,484,58,368,814,406,752,711,677,29,285,501,292,46,57,846,167,241,454,512,245,894,802,436,638,352,970,270,913,8,987,64,431,513,468,95,534,158,382,291,334,630,344,504,820,290,360,267,910,372,397,167,436,307,429,963,457,69,977,79,679,816,713,327,130,78,992,507,353,482,146,543,941,188,794,814,47,878,865,876,694,973,118,892,484,411,204,962,780,810,649,992,607,592,398,394,448,560,968,384,815,875,2,261,88,221,828,404,707,988,849,789,251,904,478,109,347,84,626,85,893,157,901,666,223,932,153,966,3,370,549,335,437,665,44,787,626,244,694,185,476,259,547,452,799,385,615,890,567,928,71,834,662,493,30,56,235,430,397,960,247,616,402,591,226,448,153,422,204,547,529,695,800,510,302,199,523,175,720,565,999,507,971,932,167,702,34,591,803,91,34,647,694,148,292,367,831,465,686,922,816,426,351,913,77,688,31,974,923,432,802,601,818,726,873,56,961,685,78,206,821,228,474,814,948,789,134,267,149,633,184,586,400,515,324,848,201,974,372,280,827,224,743,766,299,525,587,215,340,401,207,817,630,68,970,10,587,148,908,289,465,728,997,361,850,512,1000,704,31,902,189,497,951,598,292,878,288,605,294,551,581,738,491,583,981,94,287,988,217,902,726,574,765,748,537,503,557,525,221,989,790,281,273,600,398,210,631,601,261,230,726,647,124,278,80,206,184,403,956,836,53,807,661,701,861,957,515,579,769", +"96,419,968,443,504,843,747,321,192,190,43,821,149,678,774,551,900,922,395,408,648,525,371,609,498,454,968,470,104,527,874,498,838,117,71,227,70,873,736,785,187,108,121,337,765,521,831,661,561,671,125,161,201,303,363,640,83,667,334,806,192,846,953,97,24,125,436,477,386,899,827,288,261,495,953,429,38,239,370,522,736,495,684,224,317,373,328,73,329,584,244,713,668,806,511,75,868,267,681,504,644,152,309,948,716,126,709,628,117,928,806,707,678,733,648,164,735,209,628,340,826,48,779,122,497,852,912,249,402,271,322,132,129,898,68,815,793,645,403,127,871,831,923,133,473,452,175,582,83,473,895,989,953,963,68,994,893,919,839,930,963,114,451,506,325,957,988,572,236,741,523,412,754,410,226,767,188,532,417,279,754,922,994,315,963,338,229,30,184,993,274,96,38,414,845,434,788,140,498,215,323,579,262,55,936,936,759,235,698,64,216,813,107,810,177,953,720,139,923,903,102,125,456,276,438,505,722,204,19,394,287,254,263,398,317,478,863,119,91,195,373,447,145,206,659,689,170,710,506,319,153,10,381,596,418,623,200,32,862,868,527,926,345,936,526,5,985,433,43,430,171,378,802,531,467,426,208,506,178,916,627,74,220,452,285,808,28,403,266,962,693,271,256,10,780,350,435,114,234,727,955,871,761,869,681,278,828,70,862,942,30,886,747,528,225,276,343,592,75,750,474,774,396,864,900,933,859,672,647,166,208,236,440,264,858,913,450,750,221,514,901,466,445,413,190,991,992,706,182,137,526,646,486,944,51,642,992,922,690,933,110,759,376,892,74,968,814,763,940,305,966,895,227,107,625,119,685,867,363,143,147,631,911,1000,911,619,678,272,90,315,980,318,763,421,193,731,660,214,715,137,45,526,989,6,881,790,665,924,887,480,261,346,191,362,757,483,504,349,94,995,934,85,645,228,827,497,182,967,56,96,51,128,311,54,50,252,1000,751,985,711,319,99,794,789,683,824,382,577,824,24,891,19,4,874,796,738,376,96,836,180,534,628,80,585,927,803,872,44,728,825,636,861,906,776,413,123,446,121,118,212,313,820,995,778,225,986,686,911,522,190,443,561,928,374,927,241,713,833,113,11,125,903,468,605,276,606,123,9,103,675,362,357,378,579,669,839,18,366,535,489,444,133,993,789,816,67,410,871,167,360,876,164,927,653,871,506,445,302,614,451,820,824,656,726,965,298,882,198,895,76,959,247,454,178,716,469,498,760,642,349,464,73,198,764,584,855,220,856,19,989,0,449,969,248,763,642,153,981,88,784,257,296,426,362,193,49,952,113,935,509,535,950,811,530,432,62,120,948,702,943,471,878,956,576,399,984,231,366,952,269,226,248,653,802,738,977,325,532,990,183,321,444,38,225,508,191,246,608,99,73,296,325,373,996,598,39,111,401,441,289,249,837,466,457,386,430,569,360,792,383,829,406,308,735,846,539,836,466,964,361,297,977,614,432,829,570,377,22,363,73,814,32,728,720,338,264,176,439,61,253,931,469,462,585,685,623,152,47,843,804,96,989,680,427,668,189,545,256,329,737,35,105,724,140,39,385,550,927,10,428,554,457,32,325,294,301,954,282,199,103,963,79,484,7,237,492,560,720,976,737,416,149,325,679,900,7,177,141,274,13,779,721,878,331,99,788,10,845,943,955,986,466,801,751,776,322,164,421,44,426,55,841,462,543,640,827,687,238,386,684,796,155,489,69,356,463,12,29,638,953,359,251,672,950,925,188,888,14,248,610,712,228,922,459,47,68,575,507,307,716,725,80,434,834,681,781,714,162,469,314,606,499,934,842,673,673,713,681,623,367,48,263,556,310,450,863,981,758,515,637,474,936,595,649,543,9,652,829,416,211,109,714,153,357,32,932,574,515,727,973,256,824,710,15,374,616,60,986,202,616,699,560,96,379,297,816,339,652,784,621,556,702,8,617,275,924,262,82,659,674,998,710,47,44,916,598,839,60,428,470,75,155,662,477,536,36,959,806,183,29,601,610,164,250,671,566,649,414,305,948,90,78,473,825,724,860,83,511,448,515,773,691,704,598,764,728,960,388,855,563,656,411,420,246,854,140,70,52,577,926,794,509,921,787,794,889,462,501,686,663,472,860,261,529,677,676,491,490,532,285,316,99,705,494,624,832,156,660,684,123,200,78,171,962,544,751,384,22,741,564,890,306,469,333,408,979,88,954,110,719,781,73,391,661,732,339,113,897,670,60", +"359,826,998,885,236,870,765,604,755,433,417,839,112,602,581,351,320,556,645,313,505,559,340,561,687,516,908,559,750,423,999,640,406,771,596,977,555,97,234,622,562,32,756,661,301,363,487,408,835,283,863,517,303,644,413,370,427,468,106,951,457,423,522,798,258,842,503,847,557,95,935,208,677,4,32,117,609,336,956,218,675,455,504,820,509,231,752,74,496,159,486,574,937,385,303,261,602,773,81,209,598,519,756,13,483,77,794,547,133,638,485,765,97,815,4,24,455,142,428,398,864,733,104,939,208,425,803,10,102,266,406,529,929,439,245,94,533,222,669,206,392,412,153,447,201,90,17,565,82,195,477,104,220,608,77,703,441,21,362,657,329,515,156,344,751,505,400,143,447,36,588,683,646,776,567,294,698,678,754,984,964,449,536,395,759,370,698,526,875,867,338,886,541,96,28,630,103,656,796,354,194,57,390,135,679,634,957,907,368,431,990,207,770,942,791,234,132,56,665,164,343,182,388,820,477,205,570,895,83,315,528,766,113,200,917,65,889,887,217,283,874,6,31,710,735,127,621,294,82,814,541,263,310,409,346,498,220,270,959,79,727,950,859,304,634,566,43,181,184,904,758,804,310,722,249,450,25,644,995,145,405,183,452,641,243,458,709,471,972,794,52,128,935,953,285,95,903,863,8,523,392,696,843,209,793,935,973,381,308,576,253,256,981,587,939,745,676,748,204,500,34,515,930,402,664,378,198,958,839,885,965,675,591,598,43,605,865,222,150,744,230,817,287,665,882,436,14,651,985,972,653,105,977,646,350,282,768,86,166,996,551,189,83,687,755,693,343,190,76,270,800,332,44,172,404,123,699,33,341,332,438,71,415,36,687,665,858,936,276,695,518,793,113,625,449,875,726,839,299,312,222,99,720,890,638,639,179,433,682,794,946,159,838,181,729,452,385,550,27,813,261,887,801,660,16,954,546,806,233,636,743,635,716,771,579,526,470,726,636,904,550,592,384,309,142,389,762,266,859,547,748,591,112,596,752,530,26,820,729,443,980,834,12,166,94,692,720,6,866,467,859,450,101,964,299,391,246,734,551,834,644,522,419,917,509,622,781,877,550,159,727,93,559,544,71,967,386,908,33,459,502,424,74,517,546,141,737,550,799,790,838,202,589,613,262,587,156,293,325,21,410,199,501,543,278,152,651,135,213,441,455,991,431,260,519,463,743,221,857,626,828,580,628,220,64,599,760,424,512,558,771,445,93,895,972,350,394,68,455,254,424,180,425,382,635,756,96,36,958,42,449,0,699,220,948,15,75,559,919,334,974,823,813,746,556,709,428,906,829,869,420,184,342,137,621,881,206,214,160,995,433,891,443,963,898,373,111,230,685,234,823,635,583,777,793,964,974,954,707,984,193,346,424,409,479,522,275,205,129,873,706,149,591,184,573,921,119,864,382,249,410,107,758,834,953,800,293,592,969,38,24,922,939,132,419,793,789,804,953,381,961,661,926,191,536,462,522,662,388,348,187,125,873,138,982,453,334,600,944,990,802,851,24,871,598,903,145,365,729,200,637,256,11,4,667,957,808,930,392,969,582,853,671,825,120,879,450,973,474,753,253,128,524,760,290,309,64,848,519,361,77,125,151,568,907,450,442,428,795,497,572,729,628,969,42,315,52,362,373,577,22,38,89,66,362,159,93,769,291,272,349,825,554,958,602,591,197,181,46,348,776,440,876,156,293,776,273,454,236,73,181,323,472,359,994,549,375,864,866,872,649,896,310,525,941,633,741,733,197,868,959,553,853,979,139,946,778,713,199,730,756,51,582,561,370,701,54,439,229,576,843,557,26,910,184,976,216,79,241,865,546,580,697,706,374,729,817,254,114,714,537,899,622,729,346,837,565,562,434,108,910,201,966,690,252,116,985,864,128,860,978,814,917,862,623,505,212,542,640,290,860,706,393,136,894,803,289,984,114,852,679,184,971,341,421,618,112,305,630,927,877,428,740,599,412,452,535,552,253,183,709,89,640,898,619,716,563,697,233,38,355,532,866,957,40,795,686,606,168,508,870,478,705,926,977,606,149,555,446,322,328,916,115,7,282,153,257,991,401,903,461,745,756,511,802,908,370,855,149,373,251,647,771,262,293,337,30,535,204,595,668,981,361,779,783,502,383,831,340,726,832,967,790,584,715,967,40,144,24,79,71,994,768,424,189,231,963,799,700,712,498,991,785,439,162,778,199,311,246,549,250,231,695,495,362,534,568,354,345,159", +"945,155,994,11,19,284,810,201,582,957,60,926,359,814,252,450,953,811,329,768,820,730,384,604,749,90,921,500,810,781,22,987,764,400,95,995,689,37,936,200,509,60,53,551,737,873,146,93,672,241,889,319,488,461,654,273,172,215,361,880,896,771,614,34,690,62,318,886,730,601,144,688,991,869,581,684,467,192,952,841,715,884,419,1000,182,523,99,343,319,68,70,820,761,415,641,877,563,667,686,420,658,802,457,143,783,416,924,529,57,92,455,385,440,199,630,771,494,446,355,751,637,411,647,691,994,980,626,902,221,754,169,990,399,332,66,541,279,6,874,745,760,865,244,123,957,775,893,787,129,967,28,388,635,413,400,116,908,993,93,732,355,636,904,35,44,125,56,81,537,449,26,848,357,524,23,156,468,339,52,176,634,999,647,848,481,359,664,402,839,696,913,39,967,514,895,925,88,26,25,450,383,937,436,770,198,51,954,109,64,400,281,830,758,792,225,860,698,50,941,957,956,861,152,130,99,42,714,699,101,319,810,77,822,511,594,165,600,505,7,773,886,613,511,41,481,316,437,729,938,935,834,133,966,604,506,432,233,180,890,597,673,574,468,100,20,870,176,878,150,607,505,959,206,151,547,692,801,325,526,971,792,299,130,746,543,708,765,885,114,753,871,339,106,868,531,629,121,132,704,668,959,92,934,965,776,260,124,295,997,342,823,539,896,760,346,381,670,85,236,543,447,548,388,921,801,955,394,188,582,110,236,488,108,684,326,812,823,456,798,709,743,658,430,977,12,602,676,899,260,110,218,739,928,825,311,62,960,732,720,736,847,613,745,704,76,540,749,276,518,199,777,273,402,289,161,66,568,479,774,524,490,490,991,724,524,270,47,7,735,55,402,554,30,9,476,711,84,852,280,5,656,335,79,777,361,803,918,736,702,240,155,630,681,606,841,301,84,346,647,42,553,958,720,775,208,877,540,48,347,819,238,233,582,827,758,909,118,192,679,625,829,948,457,591,337,604,793,627,368,787,670,360,765,178,462,988,894,803,372,850,977,891,116,366,691,919,408,661,824,278,819,376,392,120,758,909,802,814,554,118,559,371,929,93,38,702,754,839,536,742,920,337,12,623,635,94,73,774,608,91,246,68,947,816,248,704,556,421,914,928,432,716,929,732,107,39,804,264,373,948,650,212,20,403,690,413,157,233,727,511,885,225,924,928,934,460,329,695,70,914,781,664,275,678,553,130,812,289,653,360,246,711,546,516,343,449,144,304,808,239,200,401,937,231,879,308,750,443,571,987,969,699,0,866,342,498,246,401,276,365,906,650,10,756,96,344,25,779,512,300,552,817,726,155,190,822,933,76,4,622,36,124,648,548,407,555,996,310,200,203,686,737,105,368,549,376,756,298,898,227,405,870,811,533,456,936,511,618,983,783,241,286,461,878,932,628,925,438,564,743,679,506,555,100,747,296,86,140,127,758,698,542,312,644,72,780,7,508,554,534,177,929,228,166,259,74,910,734,990,56,5,248,141,95,657,631,364,306,312,87,59,810,452,249,298,559,270,110,195,542,696,71,846,1,499,224,759,896,504,287,464,798,366,861,914,277,231,840,15,618,567,132,112,709,114,997,578,306,792,240,908,412,406,195,638,885,207,633,880,515,400,318,848,804,387,841,15,753,949,204,387,502,911,299,318,93,52,544,591,499,278,324,241,675,200,679,180,678,277,774,904,388,380,447,354,163,208,310,234,178,775,63,795,847,281,718,965,217,676,416,64,761,959,733,166,757,809,801,914,621,811,884,968,290,14,502,256,344,956,485,673,966,856,613,734,300,43,270,508,311,638,137,533,836,614,789,980,934,215,312,788,702,176,17,124,217,874,107,194,560,133,338,639,869,187,319,62,446,784,29,145,352,727,662,245,26,97,159,475,861,344,331,276,113,931,388,837,665,727,602,717,749,500,270,97,949,642,353,4,267,64,397,842,100,163,6,443,144,660,826,358,996,455,981,504,760,621,725,922,190,374,457,918,87,116,501,657,708,284,665,438,293,81,448,11,201,343,459,541,183,840,223,130,436,319,733,98,945,844,520,757,770,779,912,594,371,584,819,531,628,877,94,346,644,426,413,413,344,23,558,680,35,529,590,907,54,304,154,738,13,171,555,761,996,750,298,889,222,302,652,431,202,116,898,988,26,283,695,764,484,600,668,497,221,956,511,678,124,823,957,803,130,940,636,189,134,74,127,871,463,928,496,917,110,473,267,217,108,567,421", +"388,584,214,984,941,246,952,733,653,530,954,871,521,881,192,417,777,866,580,384,454,179,759,176,51,960,869,161,599,387,914,630,28,187,586,513,298,817,457,19,790,243,385,794,252,144,646,62,109,719,439,753,794,985,781,633,137,503,895,819,932,603,843,834,542,333,618,607,788,289,569,881,868,228,322,634,602,559,153,759,677,620,406,638,585,947,947,699,482,580,696,676,751,615,778,366,875,731,842,617,668,373,805,290,508,837,92,239,203,843,854,299,933,547,205,767,351,525,794,135,936,48,443,613,753,848,417,172,249,568,578,717,885,40,650,312,589,976,781,395,648,467,583,647,801,563,696,157,399,688,723,895,669,553,121,915,758,152,839,830,628,320,700,56,460,67,712,25,164,510,789,594,499,491,2,118,956,158,736,474,15,59,952,979,270,651,39,288,367,96,687,321,272,225,171,837,455,491,126,542,498,668,796,703,366,367,217,89,871,96,363,551,911,143,953,706,293,247,457,670,250,637,257,607,314,33,220,709,910,416,783,182,501,651,241,584,233,817,708,814,65,790,668,913,727,63,924,896,21,413,147,911,129,215,69,630,961,11,525,274,392,137,314,558,916,213,540,512,522,673,105,868,946,115,398,922,914,39,472,177,889,12,332,863,843,943,455,94,989,532,826,429,28,391,960,225,100,933,122,812,663,874,585,209,795,546,474,936,388,299,988,827,117,282,140,850,399,147,365,832,723,254,621,821,863,952,256,643,584,441,783,270,978,125,595,491,193,733,947,945,343,700,804,429,299,860,371,959,831,78,636,700,941,569,117,477,522,206,616,217,550,111,294,595,572,461,597,779,739,568,50,941,883,522,863,496,871,615,140,741,383,42,399,56,64,146,645,964,517,632,793,839,491,303,370,907,888,87,515,405,172,493,663,897,304,996,246,351,646,262,927,688,878,855,363,450,36,311,380,810,963,220,470,388,7,907,665,345,702,301,848,736,782,384,780,381,889,178,382,516,932,472,316,622,87,391,914,550,107,22,457,60,472,449,369,312,589,16,438,464,202,353,889,929,222,379,606,833,493,49,747,17,726,818,400,588,913,471,342,915,340,794,10,167,877,913,818,839,420,901,787,764,967,553,912,320,412,326,729,983,498,15,808,570,221,204,873,800,126,769,16,858,185,367,870,396,322,799,788,371,264,998,467,471,212,503,512,606,354,548,764,819,426,643,56,765,271,799,960,738,989,381,893,20,621,250,606,628,807,915,982,337,48,234,550,151,941,91,651,237,572,562,103,34,203,941,521,109,324,341,248,220,866,0,788,477,767,731,705,795,813,918,886,608,344,450,381,81,494,255,647,800,706,639,515,940,725,697,967,772,811,314,636,922,396,982,363,17,749,648,488,839,519,390,432,871,993,795,710,40,637,334,86,399,147,54,919,240,454,229,833,534,983,811,360,590,762,100,976,950,309,392,357,553,545,682,815,478,716,456,318,304,33,953,961,349,549,449,582,483,894,91,827,396,303,290,578,769,614,140,468,357,533,161,731,280,542,118,393,373,120,933,937,427,630,605,207,116,316,939,206,945,840,856,587,318,676,750,115,603,67,139,21,41,855,585,362,652,834,846,286,230,806,432,349,156,855,506,296,554,263,144,836,461,145,898,545,346,676,448,982,933,130,797,515,294,844,836,926,794,379,323,95,743,213,117,166,687,135,866,932,83,711,431,452,639,974,114,357,983,148,953,181,348,928,882,304,622,698,830,678,368,298,754,23,590,733,265,690,265,544,630,923,395,628,531,84,211,873,439,29,673,276,671,917,457,556,22,31,349,575,846,515,383,731,960,216,124,407,378,628,437,273,80,55,470,190,87,232,145,348,483,947,602,219,887,853,515,299,768,815,280,215,128,705,5,673,862,289,298,309,12,39,114,683,963,596,788,390,169,413,285,158,596,981,634,510,561,908,297,63,222,611,828,637,910,463,131,559,261,61,699,511,643,168,283,547,116,972,753,715,852,624,318,804,930,116,510,147,629,253,542,393,30,911,876,227,399,115,503,81,748,866,395,953,376,206,770,571,82,158,637,542,59,976,221,566,48,512,644,796,143,528,461,951,296,930,619,502,424,531,850,4,773,413,712,400,940,325,309,457,784,808,433,817,537,916,44,719,288,136,908,670,382,432,351,840,792,453,779,640,101,229,94,935,923,213,729,655,205,987,796,221,689,689,573,222,671,898,755,668,365,533,672,484,636,316,607,22,125,255,50,913,952,357,904,683,315,542,574", +"226,448,388,698,499,152,697,147,834,270,53,482,701,427,531,108,204,321,774,383,796,274,312,639,626,743,509,967,631,233,194,145,204,485,173,464,769,938,719,260,628,793,207,218,541,176,625,795,661,608,396,115,151,271,720,77,159,304,876,526,558,893,68,934,759,171,38,740,879,381,284,222,340,433,818,285,557,229,209,686,472,951,310,67,50,560,576,389,529,642,455,907,450,994,862,890,532,658,943,406,29,703,108,395,627,150,584,627,406,708,493,66,455,403,21,743,891,238,581,161,642,863,813,537,689,734,156,836,477,121,346,985,91,750,501,799,337,553,229,181,891,945,8,39,423,947,564,337,126,700,841,749,257,41,50,319,953,482,555,679,325,170,15,326,944,382,542,37,395,293,648,902,230,570,922,233,837,719,312,492,486,814,971,715,708,759,684,579,300,314,982,811,246,380,435,199,136,443,418,191,185,567,691,124,570,833,450,630,536,781,36,625,395,217,170,252,16,421,159,411,589,615,542,194,69,241,206,56,165,760,456,546,923,750,221,269,856,316,649,397,327,271,158,142,667,577,184,229,753,248,577,495,232,242,184,296,798,741,401,101,299,837,920,682,908,744,273,542,811,796,412,3,337,43,14,763,713,913,58,183,545,316,490,658,55,405,37,125,209,449,865,795,174,369,972,656,205,324,631,230,269,32,810,146,93,727,680,24,518,871,614,951,643,964,750,446,537,579,465,122,256,115,692,825,386,562,555,461,333,930,71,449,95,963,225,89,453,740,606,878,885,731,763,321,543,624,76,913,177,247,728,205,48,834,71,59,445,382,30,350,812,850,805,443,178,145,818,370,666,440,889,350,570,876,787,718,453,900,619,296,441,965,421,446,406,508,925,242,999,895,861,273,75,672,973,480,367,408,483,152,283,532,941,242,714,196,924,740,176,266,1000,486,644,252,375,146,927,334,44,620,840,283,987,994,199,2,748,202,689,949,725,428,838,517,448,275,782,958,640,860,672,906,636,361,388,4,52,991,439,887,946,436,592,826,179,315,445,584,64,320,895,459,952,859,464,722,759,711,187,473,353,468,246,403,39,823,669,924,628,404,354,577,18,916,528,391,670,972,671,232,559,589,834,686,615,722,172,640,325,25,3,578,410,627,256,17,481,558,159,462,224,645,723,703,327,995,25,716,928,21,821,871,410,603,743,176,427,646,486,743,231,309,586,568,795,371,961,511,353,378,350,534,151,618,316,171,5,164,505,739,6,226,810,230,461,650,549,493,41,188,795,449,804,576,157,567,393,404,25,757,763,948,342,788,0,993,216,449,73,831,90,26,240,398,879,766,761,835,6,100,362,89,456,81,293,576,640,619,503,125,248,674,596,436,607,39,869,256,456,470,284,139,321,412,550,296,38,265,770,657,299,934,170,931,375,842,581,310,439,433,961,829,448,496,399,395,480,200,678,630,86,434,949,350,582,723,395,68,973,12,603,868,80,1,496,693,334,130,572,489,805,140,483,948,23,712,220,45,44,662,191,763,221,613,520,617,406,333,226,268,132,81,575,597,58,554,780,30,738,673,278,870,976,125,24,158,650,129,686,35,687,709,628,728,270,318,742,463,791,568,189,416,274,450,532,553,715,107,566,530,283,519,979,7,299,171,126,425,861,485,239,214,327,617,385,665,902,391,429,720,52,517,230,161,209,649,768,574,608,146,404,236,460,156,392,650,896,625,69,702,526,198,836,82,388,984,954,889,888,187,812,546,789,948,229,716,781,389,911,827,282,673,803,980,524,875,494,502,259,707,605,735,794,261,270,283,229,268,304,477,53,198,61,706,307,17,191,135,170,103,934,505,858,778,366,280,520,996,211,94,57,733,427,862,658,748,610,441,354,826,480,654,910,660,248,275,898,728,507,670,18,964,830,675,555,955,122,579,446,882,68,828,289,522,434,35,32,725,815,52,27,532,851,523,119,423,164,493,64,17,807,567,321,19,448,373,462,903,494,43,354,316,777,937,807,22,88,78,502,281,334,173,573,21,889,278,394,929,969,950,235,125,116,877,387,215,402,363,563,39,546,716,405,7,727,943,567,496,820,799,733,253,282,910,42,726,604,982,176,793,904,546,972,190,595,354,841,981,157,810,245,556,616,534,318,548,313,560,936,864,797,463,69,255,238,784,299,342,142,471,919,957,921,787,607,88,340,114,961,205,105,474,780,708,61,225,689,147,566,659,862,866,692,936,899,296,799,576,407,215,522,59,698,545,834,256,339,416,849,95", +"338,16,509,613,760,87,811,459,552,933,106,172,214,237,838,863,382,130,987,360,277,196,415,268,564,797,33,259,394,260,503,162,364,762,47,540,237,718,515,970,716,608,830,658,226,939,869,16,344,497,699,675,483,684,494,966,308,996,101,150,250,252,416,787,461,455,421,869,325,289,389,467,690,368,23,849,346,175,588,359,340,656,709,6,223,693,332,326,503,925,258,553,908,867,662,718,858,613,88,848,673,484,877,141,621,110,956,14,481,257,655,480,215,202,531,668,425,301,61,161,559,438,624,668,103,323,734,874,659,896,343,730,789,417,382,111,540,229,729,136,627,664,463,116,567,856,420,615,665,17,907,961,764,234,194,916,511,259,487,782,378,365,223,270,95,981,785,432,818,527,518,68,95,359,597,580,537,30,735,970,786,356,410,490,657,696,795,836,661,904,250,832,445,909,10,555,796,627,910,517,575,268,392,715,800,340,809,562,837,866,339,820,179,613,836,132,63,752,443,80,3,465,801,169,376,208,875,645,224,226,943,323,581,948,951,444,187,955,134,159,712,221,384,408,854,60,512,21,168,297,234,311,138,44,447,725,813,319,865,100,46,967,749,571,907,57,108,867,174,645,579,251,555,29,896,355,618,776,612,23,372,56,914,943,654,452,785,317,869,680,402,64,595,202,125,659,7,358,686,738,511,660,472,620,340,602,63,217,427,528,56,489,242,689,356,99,24,946,728,626,66,900,335,7,416,966,622,5,647,724,588,802,950,756,758,178,947,415,813,222,963,459,805,899,30,444,486,395,925,555,383,113,84,345,893,240,185,622,109,493,749,602,613,640,274,475,929,424,765,952,1000,488,93,786,733,169,144,248,242,679,296,907,13,725,903,551,620,72,137,190,921,875,872,5,865,203,718,29,649,490,514,566,861,878,538,640,236,184,173,269,280,90,787,956,776,782,784,568,888,884,776,137,207,966,918,95,517,800,718,784,205,720,719,443,245,723,706,925,433,174,369,164,772,542,635,146,977,65,522,199,44,54,146,901,879,579,819,393,923,985,674,124,657,322,616,327,89,396,994,320,404,783,218,173,39,580,359,879,916,709,918,367,764,139,894,138,605,504,801,966,424,19,868,783,506,221,34,591,83,854,421,15,280,654,747,268,353,93,129,495,259,428,950,535,965,173,617,691,971,158,423,121,787,293,365,264,621,751,984,103,208,606,552,663,661,523,352,757,491,497,77,774,513,195,235,750,24,575,331,525,706,35,820,120,251,305,768,10,340,691,592,350,28,827,861,604,618,864,29,112,642,15,498,477,993,0,316,111,989,632,36,318,222,283,52,521,859,183,94,768,298,427,894,606,238,187,203,204,226,752,154,773,162,59,253,484,861,163,36,327,671,893,775,759,432,281,733,495,348,541,116,545,457,664,994,859,976,606,432,624,356,330,872,471,108,329,104,76,212,357,414,771,777,679,96,283,339,702,724,343,754,759,598,923,165,156,248,562,670,772,631,657,853,985,128,973,457,122,225,634,97,398,512,232,408,149,87,80,836,266,461,881,33,859,318,859,175,862,309,161,50,802,540,797,79,492,664,556,909,901,42,3,876,418,8,104,19,976,329,116,522,264,405,792,846,741,292,929,318,79,618,952,433,876,988,688,594,930,13,631,631,960,394,404,240,994,767,485,561,193,919,799,445,605,51,835,259,455,563,210,910,779,757,910,715,337,910,64,204,410,166,488,134,451,946,731,614,494,544,169,886,910,60,946,835,455,135,873,988,933,34,831,213,226,757,443,784,141,378,5,547,100,147,941,965,513,834,163,960,566,673,228,411,196,476,605,840,222,955,714,869,742,520,70,456,10,721,90,160,829,719,555,452,655,682,258,312,773,656,334,121,973,186,505,562,453,812,499,238,400,602,388,585,452,532,555,748,643,127,28,205,96,799,402,158,727,587,6,910,370,448,53,342,304,753,497,432,687,738,43,10,528,37,601,446,756,881,899,186,451,331,981,523,205,408,380,826,390,727,6,55,33,452,370,474,701,838,974,834,692,117,247,373,357,291,297,713,355,276,925,448,952,490,836,388,473,645,259,67,866,133,94,348,542,460,271,741,105,986,960,685,213,689,343,575,956,276,416,307,532,934,601,540,412,814,620,386,998,584,474,753,603,434,69,621,37,426,611,457,823,709,116,455,670,472,913,928,85,962,781,642,1000,778,976,238,349,341,875,901,274,613,373,799,947,702,644,307,608,818,207,541,159,688,833,139,747,634,472,954,550", +"41,82,980,689,963,106,909,106,272,601,133,571,503,741,762,226,478,867,96,536,332,531,921,583,236,841,793,34,774,727,808,811,614,900,945,274,703,840,208,841,276,162,533,973,442,11,909,794,307,244,999,186,416,477,432,540,280,6,78,539,893,596,286,890,719,282,988,441,701,465,555,741,727,460,898,56,962,281,283,370,684,331,292,117,955,595,672,575,375,545,444,716,361,526,253,794,423,509,552,958,418,585,478,44,734,538,816,708,663,655,784,323,431,381,17,977,847,477,69,56,79,802,552,841,5,411,860,613,415,435,340,189,162,756,584,825,660,962,572,552,446,577,425,547,852,367,468,933,274,258,197,490,404,838,987,541,597,390,930,512,115,765,457,367,119,91,102,876,552,148,279,392,850,258,523,870,927,357,802,334,752,316,25,96,766,851,322,118,894,636,441,453,769,706,176,834,784,840,453,182,225,680,961,824,171,828,419,787,542,563,938,354,389,493,578,539,283,199,86,496,236,539,483,22,715,706,409,813,302,402,194,976,19,60,225,565,129,905,649,582,255,461,880,998,320,267,374,950,553,909,685,552,749,746,32,570,496,535,712,276,351,77,522,363,208,294,55,849,979,610,857,583,303,388,308,655,26,728,470,895,294,542,861,2,313,126,754,739,48,150,728,358,697,414,568,906,203,998,581,137,993,512,248,839,310,544,338,919,866,306,792,470,857,522,479,15,32,966,189,795,111,48,627,832,162,48,364,476,681,838,316,745,476,770,732,278,916,532,566,980,728,340,627,977,91,430,142,58,824,128,236,8,847,534,278,894,840,332,975,562,337,711,338,38,744,826,855,965,2,875,300,828,453,561,858,427,227,893,637,564,397,552,158,258,896,24,812,865,333,353,115,919,772,812,17,349,126,816,927,261,201,716,712,736,535,569,33,52,907,34,760,765,784,236,66,753,5,369,55,441,774,555,738,723,766,707,814,237,639,814,817,268,956,67,366,986,932,233,283,33,600,640,222,301,606,644,278,696,741,120,486,793,541,609,429,866,700,831,4,801,526,876,638,581,135,904,32,112,140,608,843,664,957,809,332,727,223,230,132,461,937,86,201,736,696,213,547,158,564,717,460,347,790,692,246,989,182,414,544,291,440,37,674,813,721,351,585,322,51,829,537,339,292,271,440,635,317,756,569,328,5,587,639,475,136,897,5,550,75,587,107,795,177,916,616,393,983,438,763,499,96,979,167,941,220,577,177,269,926,580,32,755,663,176,978,349,368,993,347,444,344,457,828,839,995,633,268,991,249,143,153,75,246,767,216,316,0,390,770,182,857,251,337,839,823,1000,990,421,668,913,958,330,269,973,245,304,293,795,272,319,846,163,447,8,988,495,682,751,141,277,72,211,396,174,348,705,302,165,377,896,847,281,31,981,612,603,898,630,799,173,444,84,778,242,658,450,427,858,23,516,955,480,530,765,429,576,628,268,837,249,52,582,880,998,544,343,272,410,139,402,693,893,186,728,106,317,409,983,588,239,216,343,130,571,183,957,485,94,463,422,759,295,697,916,708,236,421,939,867,256,493,252,918,142,364,105,864,749,518,502,285,71,317,927,764,649,479,263,251,333,508,433,237,264,101,852,774,122,906,388,267,863,960,117,732,349,731,449,822,794,389,422,49,979,750,13,464,268,707,67,46,758,805,410,895,586,871,998,52,641,129,503,440,398,303,411,848,904,133,292,907,733,224,660,574,306,354,29,626,915,271,168,170,249,234,296,443,844,24,664,451,591,334,273,510,350,366,870,635,638,398,471,307,476,227,470,570,183,297,165,206,34,164,740,452,71,902,529,89,621,360,49,588,322,647,22,578,149,813,671,66,698,675,394,405,832,975,484,699,48,16,828,140,288,880,747,553,490,911,882,380,915,353,474,184,165,702,569,260,20,781,909,205,473,865,827,27,987,665,601,610,806,326,153,914,364,545,799,798,199,939,381,958,410,140,957,745,444,393,871,791,315,735,512,892,419,361,115,382,512,650,672,201,61,800,935,351,60,365,67,524,237,257,399,28,630,311,322,313,920,789,265,514,713,397,803,983,329,974,702,421,687,851,172,59,904,2,258,278,694,795,226,455,670,185,940,852,477,644,580,844,825,805,150,151,963,219,328,936,913,639,653,433,141,164,585,770,752,600,411,677,183,10,906,82,74,497,36,784,723,185,287,905,677,598,703,284,337,221,311,689,534,839,306,178,622,8,427,688,266,11,508,953,220,219,95,656,671,675,814", +"429,909,622,931,163,801,895,271,661,243,261,164,807,270,913,67,870,937,200,586,172,787,516,479,400,407,384,141,44,224,755,472,430,182,996,595,608,464,291,482,323,377,250,800,286,58,378,867,437,256,454,53,685,196,50,162,503,289,337,448,982,339,150,557,170,422,852,954,970,845,377,312,670,399,541,920,560,231,931,247,214,14,780,17,25,330,899,550,48,998,451,866,341,635,607,130,916,687,822,441,820,465,379,23,949,31,180,931,96,761,284,915,83,274,376,868,946,821,344,79,632,315,779,483,247,444,305,273,82,121,503,189,538,49,887,45,53,328,858,486,450,339,905,517,840,206,677,409,739,962,367,97,243,473,512,202,251,897,433,495,366,202,136,875,2,839,366,291,709,871,655,606,258,333,394,221,507,575,723,412,36,792,812,828,142,337,634,403,483,179,350,389,943,637,317,618,196,912,540,209,545,131,653,942,316,307,205,514,2,75,213,753,548,588,954,397,94,938,556,744,474,509,997,120,295,231,133,63,597,98,628,405,815,944,115,124,547,826,665,434,345,761,545,844,509,734,62,328,755,810,354,615,209,418,295,529,788,152,257,914,591,155,751,585,507,588,836,763,652,776,16,540,447,783,729,438,134,553,490,734,139,22,773,255,804,704,9,39,147,102,67,272,23,692,526,879,289,261,30,207,756,813,615,260,853,510,887,627,127,947,264,216,173,242,693,561,236,286,260,498,39,656,699,739,623,252,988,241,659,753,637,395,493,298,437,908,808,596,230,715,216,381,452,882,454,715,267,808,954,340,72,958,800,16,568,994,460,341,522,29,104,149,543,151,978,668,186,385,253,762,723,138,896,272,342,65,921,510,10,355,620,328,598,623,868,798,565,443,743,445,471,41,425,212,375,35,438,115,631,72,394,962,316,271,908,109,921,454,830,194,723,95,346,860,342,751,239,733,633,481,129,345,692,860,403,379,434,690,418,705,551,516,383,362,106,959,322,960,606,503,795,170,109,869,797,300,365,215,585,727,797,550,481,228,194,984,214,40,749,214,540,556,497,541,166,564,23,843,109,605,34,484,553,98,722,505,217,131,410,353,908,687,544,852,411,667,435,591,63,888,164,805,342,572,439,440,125,739,80,34,706,865,639,797,594,906,208,139,199,215,692,443,449,835,57,268,488,579,174,462,782,796,151,311,547,873,242,529,772,57,375,454,213,574,711,363,544,989,49,311,579,974,753,58,104,645,826,240,550,961,479,293,749,916,806,236,871,856,315,52,417,666,537,835,771,109,500,13,561,220,981,559,401,731,449,111,390,0,351,691,67,231,933,950,42,428,261,121,543,755,6,873,477,692,607,47,263,223,397,986,223,274,769,866,178,518,74,572,216,50,394,613,842,902,918,442,192,246,796,576,435,241,226,978,194,708,849,428,600,965,852,784,141,836,277,529,808,370,5,933,320,28,966,793,263,926,241,836,159,183,298,572,613,165,125,518,361,518,824,204,700,691,116,14,409,533,640,704,32,120,745,724,440,114,693,763,491,408,764,93,806,62,644,792,101,913,19,174,726,164,254,360,412,641,932,435,275,393,514,298,615,479,895,106,432,118,25,80,705,16,618,946,355,489,764,821,545,650,761,969,270,668,891,345,577,50,249,766,452,205,544,134,555,73,643,359,961,79,564,8,775,226,623,551,643,313,270,114,927,816,829,12,677,614,333,497,687,655,829,787,82,673,513,505,751,855,855,476,836,565,205,934,202,203,372,574,955,137,214,737,252,782,886,747,673,226,83,918,279,81,893,798,997,58,346,511,943,353,262,721,206,517,400,472,310,359,128,848,169,28,607,623,371,490,52,967,648,620,496,734,410,193,939,249,258,28,824,96,926,628,742,544,358,701,502,574,354,515,172,15,180,878,649,669,90,61,556,384,999,340,275,559,644,751,115,269,198,846,670,633,580,143,561,964,894,470,715,181,601,17,31,283,210,208,57,419,425,564,890,206,92,297,106,871,967,579,429,534,527,260,87,228,510,398,237,783,80,275,696,521,454,879,129,806,980,110,444,359,903,896,423,737,223,474,197,994,421,965,426,915,712,789,860,471,368,413,738,783,221,433,937,671,536,449,57,828,9,873,401,467,160,903,872,371,300,154,350,557,819,199,455,537,202,323,380,115,977,967,812,922,391,425,828,438,807,935,438,265,57,914,199,604,865,443,764,588,364,445,327,586,778,190,419,419,306,448,666,458,744,613,411,511,274,65,791,939,78,411,591,910", +"367,104,353,623,332,876,375,562,312,429,812,85,865,825,128,386,742,667,459,393,134,859,519,671,802,370,899,594,240,255,761,101,904,335,901,482,585,638,194,389,807,238,992,185,932,150,772,319,839,268,191,350,818,209,243,831,570,417,531,245,941,566,687,680,347,750,294,738,379,350,805,22,725,974,443,365,78,264,204,64,932,27,992,387,624,683,59,776,488,565,27,901,415,698,678,780,117,883,329,793,952,171,920,740,651,491,383,14,305,526,133,482,781,731,227,484,943,604,195,68,819,657,985,593,751,11,783,662,455,446,348,226,782,622,736,426,919,552,613,451,882,729,497,620,765,695,16,620,540,182,410,927,577,455,13,608,226,779,343,389,877,164,91,608,181,704,673,521,493,64,965,419,335,618,21,420,12,496,854,237,733,397,874,876,701,590,955,597,873,240,146,95,333,713,945,23,753,652,776,736,765,482,73,383,130,163,805,601,617,179,636,163,827,893,545,427,939,121,270,955,918,573,370,766,861,772,468,844,495,300,656,657,415,392,916,270,78,202,354,690,640,785,858,846,597,830,825,522,78,260,24,603,290,853,8,645,109,648,505,231,969,300,393,463,742,241,407,611,905,949,507,389,647,406,225,838,403,966,821,311,333,925,666,211,68,412,340,238,558,389,51,29,798,772,589,899,525,142,292,582,181,949,269,99,200,623,218,925,936,835,806,553,274,103,30,937,479,734,133,819,468,501,757,362,171,978,194,371,644,132,826,389,975,743,115,807,155,106,264,618,845,458,343,416,370,240,924,867,584,658,419,995,236,535,842,128,619,152,423,875,276,888,309,388,927,297,837,60,798,92,656,203,308,74,88,483,205,722,275,413,485,484,777,445,810,510,454,194,108,416,942,13,407,194,122,808,840,119,96,514,583,210,323,50,853,381,774,217,696,123,645,222,646,150,800,781,313,957,33,37,890,577,465,226,29,619,540,63,529,458,566,259,444,753,736,869,525,647,341,624,897,69,378,491,535,647,291,338,931,160,501,531,198,383,510,849,422,430,736,411,525,603,104,865,197,647,113,510,135,576,898,814,478,58,181,463,700,486,523,250,271,159,390,495,232,597,790,765,415,820,972,732,156,47,855,814,763,316,167,491,601,645,121,896,717,436,958,525,62,995,157,974,707,135,709,836,556,564,17,364,310,104,654,691,279,258,361,483,451,331,501,166,929,288,507,747,469,627,254,422,422,54,298,897,505,812,179,483,155,732,878,517,273,212,455,498,6,512,807,496,323,952,140,151,670,973,39,327,240,800,88,919,276,705,73,989,770,351,0,431,623,116,806,988,914,79,644,570,672,546,576,80,130,50,185,909,868,695,840,686,628,808,340,694,654,90,959,422,606,443,452,41,108,14,772,431,239,110,319,20,403,106,849,893,715,322,961,897,681,108,391,585,638,447,706,250,504,507,340,988,325,7,240,670,145,940,849,316,883,441,241,751,792,889,937,302,68,341,844,792,127,872,383,152,205,756,276,721,360,939,831,710,315,59,175,299,721,521,596,332,439,64,941,503,856,494,407,825,711,744,355,756,630,840,528,418,1000,823,945,161,942,528,710,565,283,223,428,21,682,417,194,385,938,136,885,103,482,681,481,792,676,10,43,598,170,172,271,922,660,28,396,723,198,192,371,931,987,453,754,354,783,956,359,771,898,578,576,669,767,948,416,982,385,313,909,105,12,799,213,573,374,891,314,990,40,481,563,430,206,962,139,26,197,301,781,526,613,309,761,924,33,430,252,832,36,49,913,906,478,961,602,711,606,378,813,62,630,14,415,688,897,745,698,54,737,179,971,752,946,784,913,236,3,588,116,155,250,87,992,657,197,853,828,344,986,619,786,638,995,406,997,918,432,864,224,380,190,589,301,849,602,749,184,212,26,700,250,332,258,508,297,744,471,537,148,120,24,688,873,221,524,534,123,826,517,299,618,226,664,308,23,661,627,657,817,636,519,660,57,14,711,848,498,37,385,886,897,453,606,496,348,983,291,348,778,575,749,431,534,579,704,869,788,494,142,862,139,915,160,740,565,664,777,803,346,132,167,662,229,21,632,587,434,275,539,732,707,613,525,154,350,151,700,861,553,860,924,876,941,257,425,920,521,271,392,178,104,3,458,880,392,984,711,153,876,128,51,825,652,329,673,408,372,414,865,426,558,667,239,287,865,323,857,151,606,597,406,963,583,565,392,284,818,512,56,404,465,171,207,660,844,750,108,635,558,469,299,127,453,383", +"940,608,233,390,910,249,608,518,470,208,379,333,752,790,642,654,907,311,665,51,905,307,705,203,577,468,810,903,351,422,543,365,895,468,560,685,923,666,666,767,270,957,478,105,425,564,806,682,61,661,686,648,380,149,752,567,30,526,255,669,47,348,719,12,253,274,864,801,740,603,331,754,294,8,505,463,536,838,689,687,237,898,28,712,500,345,411,94,41,289,715,297,929,446,361,841,447,457,786,616,400,674,187,769,202,799,600,707,957,970,268,811,426,773,283,455,845,924,700,289,400,6,264,639,291,661,111,38,48,283,672,666,350,876,432,417,58,955,235,900,244,101,572,718,564,638,918,553,979,198,184,656,960,414,524,310,448,168,958,516,532,359,627,700,321,736,270,142,450,931,243,705,268,635,47,113,602,406,84,834,191,830,471,80,764,944,230,9,121,144,683,343,658,499,2,663,910,630,393,683,705,487,837,957,358,297,730,920,403,936,377,285,400,623,728,576,204,188,213,446,616,96,679,964,665,989,381,493,993,97,853,127,999,909,94,327,49,29,909,864,782,380,803,355,909,512,949,758,816,70,900,544,385,670,824,473,739,33,909,994,102,398,723,572,588,601,21,936,284,685,663,876,399,812,802,54,370,697,860,868,12,853,142,459,172,650,254,423,221,331,522,900,560,642,297,665,731,724,709,993,698,117,602,367,149,942,480,607,18,623,677,652,167,514,82,830,922,497,133,574,578,180,811,201,856,170,792,412,598,532,141,937,443,618,844,788,949,831,988,442,84,542,898,666,311,308,902,55,605,320,911,418,211,785,773,928,248,430,365,65,303,447,421,586,600,17,826,186,400,904,307,785,398,78,621,782,994,21,700,317,636,530,475,189,574,626,64,610,684,541,178,91,188,97,870,868,405,22,380,116,41,527,231,736,75,37,748,160,997,98,593,277,593,790,182,284,717,420,591,746,131,383,600,498,83,189,229,527,311,236,644,648,990,806,768,904,883,741,469,107,182,133,1000,746,226,778,677,550,983,670,420,362,668,197,704,700,84,724,822,122,581,968,992,937,483,952,524,343,784,369,68,866,820,526,924,123,711,730,112,248,824,340,317,177,851,279,954,139,495,227,835,10,405,152,782,195,206,868,259,606,876,371,562,556,306,826,34,116,394,337,423,154,910,156,550,412,211,433,91,604,197,316,596,843,503,364,407,821,5,844,226,672,947,325,625,493,110,931,667,40,590,215,551,256,486,422,100,702,716,604,769,312,557,915,937,788,52,545,369,630,864,819,891,442,510,583,335,212,725,624,784,334,365,795,831,632,182,691,431,0,395,79,129,319,650,9,300,394,754,738,681,505,681,675,235,99,751,701,453,402,817,13,989,398,920,708,860,717,577,400,475,280,803,49,802,546,509,181,29,586,472,425,368,640,919,817,820,513,333,197,902,506,654,702,945,72,816,549,653,262,171,315,320,867,917,592,913,53,622,638,623,375,453,816,607,711,187,381,365,455,751,358,777,217,749,577,647,865,167,769,6,198,986,129,174,630,430,622,660,103,871,536,190,939,154,45,306,379,925,271,680,154,495,828,209,369,96,936,813,771,355,724,396,246,334,814,177,41,128,20,236,704,962,559,789,533,758,294,690,509,316,250,36,761,855,621,553,221,336,513,270,637,138,124,612,114,203,218,771,543,976,940,814,660,713,989,960,95,83,456,663,222,984,762,680,498,764,834,577,290,447,763,917,769,500,922,844,840,579,457,41,665,701,196,170,892,399,173,864,68,665,573,380,15,241,538,161,375,679,835,7,340,392,211,725,464,917,158,832,532,737,705,309,886,431,115,478,859,764,888,450,646,861,648,802,496,275,373,858,675,904,942,278,603,553,255,9,101,712,351,627,258,473,803,174,160,677,325,14,892,406,170,429,942,434,79,181,814,736,226,805,571,373,201,666,740,105,47,932,823,5,658,968,559,797,766,521,309,116,683,153,89,692,96,802,703,478,181,17,71,60,10,863,716,519,763,698,564,766,752,631,296,762,241,92,861,971,323,781,632,37,279,933,865,764,896,440,716,557,722,80,798,778,904,698,432,944,104,461,129,283,664,560,132,609,208,635,621,706,182,537,15,172,353,559,847,586,40,401,97,697,746,974,875,376,345,974,317,122,195,370,618,730,583,445,51,656,975,553,892,947,32,898,233,71,948,932,1000,534,280,167,982,677,390,548,895,529,701,723,553,668,547,239,198,60,290,938,98,437,956,968,396,841,423,262,984,678,354,964,294", +"474,900,496,532,877,802,664,443,488,877,808,983,386,74,36,78,84,218,526,65,896,357,294,764,910,9,238,379,380,655,384,688,795,811,496,697,899,772,236,576,624,7,210,592,570,31,807,266,618,462,109,583,487,127,426,67,32,923,679,111,738,712,361,773,590,218,311,417,401,856,254,949,413,893,534,712,355,128,484,726,383,484,197,833,700,488,443,149,591,503,33,945,503,197,59,644,1,924,750,319,434,350,320,632,337,335,133,592,162,16,951,674,821,912,670,975,549,719,488,899,722,243,17,231,602,613,929,950,217,833,64,440,799,991,81,515,455,282,31,451,241,429,599,580,389,633,889,648,584,276,17,830,807,492,741,669,102,107,412,442,607,839,339,45,711,856,836,554,903,296,641,554,205,825,390,472,374,839,5,324,226,717,599,475,379,807,421,131,774,211,920,452,864,555,55,337,1000,674,416,721,716,278,416,78,562,819,550,651,32,485,403,369,223,141,557,473,563,803,518,382,436,120,250,828,251,910,132,965,388,629,33,890,510,794,535,925,660,684,677,548,241,306,336,87,455,831,935,461,341,141,414,758,196,999,703,805,213,696,767,849,481,929,38,67,977,89,302,888,177,782,564,126,359,628,747,791,287,850,474,157,742,672,459,138,414,906,890,58,415,617,134,727,371,45,31,213,175,755,366,241,286,532,905,371,263,569,247,120,477,862,559,190,392,989,49,85,471,576,411,611,964,815,920,651,812,327,348,892,178,634,287,126,612,129,510,493,79,107,760,347,430,522,480,941,921,804,355,787,151,664,688,534,139,153,715,8,96,548,34,810,300,519,475,726,379,527,398,718,461,371,103,629,533,336,141,487,82,16,405,505,2,653,977,591,971,677,659,936,568,45,3,929,391,248,472,233,155,155,953,200,551,758,652,877,140,279,509,914,393,413,593,724,107,225,219,635,145,395,888,581,98,183,141,500,980,851,431,477,176,834,8,57,184,58,726,215,396,50,636,832,230,464,859,260,839,290,457,145,186,965,536,649,668,589,100,201,797,272,532,537,475,690,550,157,911,863,868,808,854,918,847,534,302,798,465,495,43,672,383,336,334,659,502,563,920,409,878,148,284,884,220,46,601,717,443,712,448,482,716,918,120,699,350,553,788,651,707,220,355,206,416,832,478,771,359,738,393,724,434,858,677,506,45,226,744,24,284,731,307,588,739,321,62,86,252,436,481,827,777,829,327,774,705,773,461,866,270,381,849,648,851,597,245,599,734,729,500,884,987,623,418,878,658,768,171,259,943,854,349,536,257,974,906,813,90,36,857,67,623,395,0,704,460,505,879,951,65,839,560,276,175,872,717,59,585,146,992,265,817,632,436,22,960,482,977,53,391,567,689,401,136,581,743,914,745,153,928,875,177,250,617,724,95,947,170,824,776,115,689,174,534,221,725,834,922,454,702,31,164,70,56,513,730,67,559,367,658,826,717,899,109,87,580,274,330,289,834,608,832,141,541,558,12,222,996,189,211,395,222,631,81,302,93,477,133,84,4,313,862,442,957,994,24,645,28,488,129,880,197,804,946,382,392,959,413,897,706,661,25,917,83,354,77,534,115,633,754,420,661,671,306,362,116,793,177,170,178,922,925,369,894,158,605,188,32,967,823,471,153,658,646,364,426,220,47,583,431,376,538,363,987,330,487,541,473,191,157,132,428,68,28,170,829,349,312,817,179,182,766,718,684,487,472,506,504,963,121,438,820,472,935,48,450,484,932,849,900,878,343,91,700,916,218,370,927,521,104,504,872,233,954,552,375,96,312,489,407,733,176,482,275,157,533,330,381,71,279,581,564,370,222,602,655,548,78,361,482,479,628,293,245,146,140,672,931,971,787,147,275,864,374,489,151,792,581,674,299,335,678,95,257,800,313,27,302,706,415,379,406,757,47,285,508,795,475,623,685,124,172,381,509,450,889,670,857,603,732,899,669,357,400,682,511,411,212,984,674,267,161,994,650,242,571,605,904,338,209,865,875,151,741,865,942,502,123,581,809,34,127,370,310,36,293,353,537,789,647,116,609,236,679,224,583,688,681,697,537,545,658,987,890,746,473,633,734,207,495,412,583,257,372,751,143,650,917,138,748,351,809,550,283,481,839,523,32,937,34,951,528,347,574,475,535,961,972,706,978,624,284,271,319,380,522,871,723,561,986,313,530,770,821,480,869,222,775,865,833,279,377,172,521,555,619,659,284,598,978,957,478,150,243,880,681,90,531,20,155,106,705,405", +"477,971,178,752,116,529,496,953,109,786,600,343,397,222,61,181,154,88,639,280,906,164,935,883,762,176,77,529,493,126,530,931,753,991,682,873,282,299,800,318,547,986,947,708,575,717,815,181,739,639,998,194,794,353,801,679,812,665,67,490,512,518,746,489,79,130,624,604,507,543,136,434,921,598,458,285,826,818,723,108,570,523,613,254,824,942,104,829,516,202,397,642,994,743,190,469,676,707,141,343,272,798,909,381,299,373,388,998,142,664,46,493,136,475,933,523,21,288,18,494,733,430,831,335,493,411,652,168,531,599,296,850,463,231,633,567,795,136,606,358,989,723,802,20,186,992,618,867,110,342,527,204,511,619,703,93,780,711,186,932,366,216,163,947,253,870,787,254,211,280,537,279,331,477,54,424,636,808,112,609,722,969,559,102,81,39,243,698,655,21,627,713,586,519,810,967,566,674,738,199,516,639,83,687,154,270,539,51,851,453,749,539,928,130,676,562,817,775,836,765,97,580,663,517,811,524,507,908,266,908,998,711,272,996,278,124,233,868,474,594,17,231,660,309,246,860,965,609,123,635,639,437,439,426,774,191,775,807,555,532,40,6,167,236,710,928,666,723,960,136,602,137,165,79,281,715,706,421,174,523,491,907,158,384,753,337,412,777,236,765,207,56,247,869,946,471,196,373,727,999,749,65,249,697,402,462,391,128,818,230,812,396,142,109,625,574,811,85,479,639,369,313,766,794,36,946,326,654,401,627,275,410,389,690,592,92,845,356,148,817,75,970,981,259,527,766,804,598,833,308,970,235,22,967,515,404,43,206,657,391,198,517,189,228,578,739,101,922,857,539,443,223,348,772,637,792,726,209,669,464,681,333,440,798,745,173,122,407,779,51,805,616,160,914,499,354,651,403,522,871,697,39,41,63,791,70,817,164,542,935,33,732,545,210,753,910,773,701,195,366,396,265,907,3,431,229,266,844,822,503,840,558,348,857,463,561,111,466,570,365,554,642,311,825,3,909,6,933,785,324,359,344,316,914,103,534,820,387,720,67,82,148,448,491,295,614,912,197,869,251,798,318,200,799,175,599,477,346,357,416,14,276,356,4,881,794,921,115,255,507,19,756,265,717,843,229,761,806,566,198,900,27,587,999,200,739,995,883,262,794,59,237,956,530,885,119,523,545,171,532,808,291,217,81,248,10,556,736,342,799,455,632,203,591,980,50,801,280,279,510,81,824,477,788,941,549,728,863,9,834,669,634,532,684,63,913,650,800,519,69,864,418,513,934,17,591,656,535,257,355,296,823,650,918,26,318,251,231,116,79,704,0,707,971,80,873,775,450,140,605,922,690,149,265,683,915,885,46,929,420,776,780,735,103,264,475,199,82,14,541,458,920,880,604,910,563,885,462,369,679,519,707,552,586,552,896,855,220,569,655,616,745,126,845,266,592,478,560,580,145,835,177,603,125,424,521,583,290,932,329,745,984,923,352,637,764,294,479,400,368,813,23,154,9,491,752,37,232,816,742,728,391,732,691,81,715,885,947,59,565,810,96,230,386,583,452,887,998,976,635,311,116,657,779,510,290,241,907,336,926,580,632,396,23,612,18,124,190,353,663,233,788,16,996,36,740,267,534,488,211,218,668,125,207,56,764,164,398,657,981,411,777,204,901,636,744,862,974,494,912,635,509,587,508,990,755,625,663,743,659,648,955,210,972,934,207,607,364,374,675,794,256,600,909,927,52,610,445,711,417,209,9,834,35,409,887,39,76,705,806,233,720,318,948,143,734,594,889,51,176,875,941,744,189,516,238,61,486,561,324,881,329,153,620,534,10,768,643,303,31,544,938,108,201,574,82,504,542,609,3,594,880,868,422,103,721,140,898,219,736,505,167,423,581,590,86,298,41,585,94,297,79,412,714,469,317,440,663,681,356,919,912,124,694,897,292,483,843,784,451,942,1,33,496,658,491,4,188,189,612,434,232,280,337,84,593,395,132,782,786,452,944,163,601,90,774,154,787,73,243,268,115,819,413,145,195,884,369,272,170,172,713,296,179,895,901,420,500,540,450,268,212,393,599,780,539,721,236,196,692,803,703,273,388,294,853,888,909,352,772,667,719,240,413,927,968,112,120,274,532,310,380,203,236,845,988,944,804,881,375,547,280,331,283,821,229,432,467,385,569,101,199,802,35,647,841,228,530,700,470,450,850,289,187,558,532,445,457,882,982,802,529,876,321,384,815,766,166,818,663,42,439,596,89,601,426,943,777,701,556", +"978,763,988,456,41,722,128,990,516,323,452,591,293,12,494,231,436,18,101,341,747,406,486,690,318,160,612,277,806,666,247,91,956,825,853,89,924,650,656,396,419,286,516,625,188,480,923,931,215,846,403,180,12,176,624,167,253,181,107,925,300,842,23,878,349,170,724,202,974,809,501,684,576,824,78,866,655,147,383,837,767,291,300,794,801,289,299,949,778,589,698,882,391,566,387,572,822,835,759,789,430,892,812,634,83,769,77,202,957,740,715,212,649,122,510,305,82,873,104,665,612,556,318,796,477,926,844,942,962,448,818,439,163,367,9,61,12,24,769,413,192,169,961,484,517,588,238,491,552,219,660,854,883,793,285,856,811,28,521,236,248,239,523,739,618,271,160,515,788,601,153,739,35,472,802,782,619,274,650,158,922,482,344,432,39,470,248,193,902,937,111,434,346,862,858,645,81,724,106,577,703,62,289,728,7,423,241,801,935,288,462,451,997,25,780,757,749,31,718,106,76,618,554,725,493,416,406,642,780,211,127,173,375,16,852,388,782,439,756,465,152,777,127,922,781,146,286,615,451,105,166,131,306,93,990,132,611,233,403,389,619,929,472,637,953,987,65,917,956,971,443,282,447,507,123,207,805,232,606,157,96,244,139,188,342,302,617,808,418,424,895,623,662,114,982,442,173,680,771,128,759,501,744,291,564,350,643,67,795,136,261,84,89,74,818,484,662,424,516,517,375,149,127,20,864,77,750,931,428,135,651,110,922,358,33,854,861,370,934,314,136,829,267,931,602,612,538,496,549,511,731,267,411,531,996,309,926,705,1,74,24,520,839,108,440,474,627,47,870,574,273,91,861,633,7,526,804,413,66,335,387,409,886,118,920,291,142,182,104,221,322,247,642,801,776,408,784,173,234,269,841,741,396,511,753,732,908,24,149,187,496,959,14,862,122,112,182,288,272,142,99,746,126,636,109,55,26,564,955,545,904,723,909,585,729,507,580,870,282,114,754,666,491,532,250,832,491,832,586,235,93,75,968,205,613,505,766,278,598,84,341,862,583,16,230,431,317,461,257,279,56,13,411,564,83,992,59,362,22,830,730,465,772,386,174,75,995,945,987,708,702,691,746,94,504,720,861,707,431,20,414,754,947,326,275,290,437,623,89,392,115,952,786,829,528,240,35,491,326,430,465,944,736,846,120,390,393,450,106,322,233,605,957,706,613,948,893,264,644,168,740,477,133,117,709,300,938,323,533,123,502,859,222,491,799,162,721,266,69,260,409,658,628,818,387,12,71,823,624,325,426,813,10,886,240,222,337,933,806,129,460,707,0,905,769,974,74,522,802,38,775,984,801,925,775,544,443,174,66,782,591,495,681,389,59,388,654,468,178,262,809,192,556,76,457,661,197,999,814,577,690,652,90,976,839,427,851,707,3,355,723,901,720,376,999,486,919,63,429,274,301,420,831,714,122,112,769,439,656,89,476,323,68,89,385,792,744,655,790,172,196,945,696,343,957,978,100,437,942,681,426,396,464,319,418,598,848,562,24,110,779,558,723,422,257,218,378,726,171,179,793,693,273,616,578,231,407,789,238,533,829,37,489,822,988,885,26,113,444,378,456,155,257,756,827,884,47,407,927,848,44,276,466,914,161,533,89,210,717,864,13,534,231,667,908,332,307,868,247,571,206,551,532,609,666,289,296,23,226,211,762,704,261,455,327,50,923,858,332,238,837,536,727,557,481,132,634,308,510,881,534,304,782,215,868,298,119,766,692,35,507,186,635,909,40,988,45,924,729,991,9,782,201,964,866,416,298,909,967,967,936,874,929,891,442,214,176,570,535,357,19,938,758,975,403,874,609,131,832,69,243,372,155,373,141,272,379,101,693,59,388,760,879,589,770,624,190,590,389,502,721,470,58,458,971,92,510,393,19,477,903,761,441,605,265,295,841,386,607,628,487,419,287,702,980,997,513,140,592,811,764,279,97,839,860,759,403,917,178,467,102,614,991,649,273,237,485,723,801,236,729,676,847,491,962,286,299,874,105,533,315,580,26,843,690,906,648,434,188,199,252,933,856,824,1000,287,823,912,482,149,544,611,612,745,333,145,694,320,915,366,85,392,337,5,503,739,377,966,919,616,494,386,184,581,844,1000,524,225,114,524,752,846,638,878,940,170,550,673,385,364,159,613,909,66,88,646,277,567,282,562,400,89,53,564,8,509,713,535,112,257,788,798,2,112,931,196,409,949,672,575,95,654,373,257,186,581,575,992,427,329", +"867,98,344,497,128,154,100,485,770,11,899,287,268,29,38,587,516,880,935,691,130,964,733,606,115,568,223,407,897,465,225,195,643,438,622,742,853,349,440,421,361,862,808,201,493,300,903,752,792,112,618,307,377,618,641,965,341,160,27,52,745,759,967,384,783,900,281,758,366,751,441,525,123,514,323,601,66,670,753,438,739,170,432,872,889,587,17,173,628,853,108,245,196,382,120,207,896,343,974,287,98,846,210,789,816,518,398,893,973,861,848,54,600,168,591,735,840,959,241,611,716,644,283,816,586,147,922,329,403,273,340,996,298,513,422,386,753,520,809,695,617,121,317,492,11,706,484,679,826,770,715,165,333,290,245,466,343,248,434,473,157,593,67,563,237,611,190,21,56,913,935,515,764,75,507,384,839,560,905,195,540,48,741,900,348,791,196,86,450,563,390,588,226,604,349,243,723,363,100,160,790,187,481,75,50,450,318,709,407,641,928,163,894,626,15,204,375,937,477,74,771,937,5,919,532,674,966,89,223,688,667,159,140,121,763,105,388,436,856,382,663,456,786,899,950,47,596,590,618,667,648,206,138,221,6,94,134,492,514,425,780,560,248,34,959,781,513,379,185,639,607,576,672,655,336,256,282,863,976,715,365,434,327,474,384,460,442,6,579,352,612,439,612,977,211,87,152,844,175,245,438,75,342,197,779,442,538,431,233,172,990,712,556,591,652,906,5,589,332,508,117,503,415,352,710,323,642,543,277,524,378,117,58,834,791,20,858,326,368,528,325,740,412,244,153,672,212,158,213,793,368,201,946,767,813,661,625,998,820,282,340,769,500,440,32,341,373,192,755,250,27,15,944,941,864,114,321,898,776,683,401,260,459,418,162,654,495,223,425,71,735,444,92,776,616,867,75,232,99,120,163,985,389,649,117,44,726,121,115,992,468,362,382,171,803,266,474,959,870,537,953,233,206,426,240,321,896,285,202,355,236,785,851,951,881,976,484,232,350,811,914,635,518,584,398,255,488,974,190,302,88,631,59,955,928,482,435,806,394,580,856,878,392,205,204,576,464,559,203,269,636,701,377,842,704,534,333,576,601,695,477,886,27,506,511,509,58,784,116,322,533,328,474,356,99,738,459,525,427,282,660,65,736,76,825,609,982,474,581,623,481,761,553,956,166,270,431,364,817,539,389,310,50,122,902,393,797,926,646,932,94,719,713,876,36,972,371,459,243,466,943,258,429,751,584,401,157,177,456,690,446,11,857,847,330,232,207,111,140,750,69,48,270,905,921,496,703,21,914,630,362,746,756,608,398,283,839,950,988,319,505,971,905,0,832,633,583,515,310,323,29,610,424,912,268,793,567,240,904,905,200,273,745,866,969,137,203,715,300,672,108,799,567,770,856,68,80,931,915,570,280,100,16,664,663,241,154,644,480,411,185,163,843,185,518,582,113,680,946,913,330,739,389,504,484,870,748,436,696,96,481,440,433,919,493,462,658,650,169,495,351,919,442,92,248,488,285,746,728,840,896,203,207,490,298,48,172,3,951,632,893,701,213,723,889,219,503,679,171,875,883,575,370,420,891,130,949,75,547,24,571,423,387,557,169,101,747,89,770,563,797,128,489,38,425,264,535,172,122,226,786,625,570,144,562,156,928,453,702,544,70,627,373,783,998,528,442,902,516,471,652,54,921,328,499,385,805,391,123,411,595,522,421,811,611,785,975,158,127,860,514,180,404,368,418,282,293,831,538,426,405,784,812,976,218,416,905,657,235,536,648,635,157,740,33,978,364,269,969,909,558,312,741,825,152,173,744,892,858,393,259,734,237,88,86,834,671,526,155,276,560,703,605,361,606,309,467,197,673,806,223,803,143,503,26,837,335,463,804,106,783,116,12,59,276,326,468,376,928,530,350,729,766,733,792,218,743,631,472,520,969,448,396,53,499,901,390,795,606,969,124,458,220,986,384,51,161,576,408,690,414,812,127,307,153,554,835,891,823,499,241,671,209,273,863,843,32,827,629,48,58,787,7,749,638,96,546,245,939,886,246,281,962,7,894,206,913,668,691,426,935,884,885,566,985,646,722,660,760,784,424,119,269,230,956,991,498,86,116,804,139,640,419,590,992,67,892,179,357,619,569,853,972,116,852,955,472,616,120,237,832,106,751,982,834,878,494,519,836,974,323,165,610,325,932,984,806,941,338,114,153,207,278,220,32,295,580,689,853,81,234,141,751,337,68,621,6,711,22,694,745,744,244,442,80,745,882,495,46,983", +"975,464,445,438,146,263,210,380,281,234,75,3,339,505,176,892,229,154,891,733,141,408,268,247,786,809,176,604,197,617,685,442,393,554,672,490,677,282,535,31,498,280,392,198,112,58,511,398,836,337,511,283,436,710,521,942,24,411,135,65,684,11,86,614,249,989,310,215,843,748,903,258,611,608,659,618,288,307,558,810,800,131,76,345,826,380,336,648,571,669,734,303,11,789,907,467,966,625,925,542,649,241,794,917,881,152,852,342,780,96,499,278,966,954,168,516,910,426,833,474,274,285,169,367,822,987,46,340,650,375,961,868,262,58,626,259,634,215,125,621,988,624,580,439,550,669,862,814,103,44,166,489,623,521,260,188,515,495,446,435,999,956,674,683,519,533,118,388,499,964,151,916,963,505,584,393,663,639,674,328,350,906,640,224,155,528,257,479,938,934,853,352,74,196,378,533,280,415,745,59,139,852,191,335,439,833,292,768,804,201,219,224,932,494,413,605,610,512,258,648,386,694,993,752,260,659,38,651,543,137,65,8,769,577,420,695,979,807,511,177,957,887,591,87,182,439,344,571,906,1,400,172,840,613,211,818,283,151,624,601,237,128,309,901,434,203,90,799,592,333,837,778,988,289,358,79,43,203,322,944,632,835,27,887,818,146,483,875,47,905,913,141,672,49,211,393,232,974,155,80,641,42,264,219,321,162,402,230,951,718,687,973,596,365,70,130,767,716,699,361,152,32,919,609,151,105,22,897,966,751,709,823,868,616,537,606,253,616,306,301,858,231,38,276,363,963,35,480,3,200,375,829,732,964,960,718,643,436,458,82,790,343,639,969,355,318,9,776,608,251,863,712,53,13,924,477,409,943,486,558,241,855,199,56,226,623,597,309,219,873,451,487,960,788,742,413,473,289,878,919,443,608,639,504,450,612,701,351,438,262,934,630,930,709,575,732,90,154,210,12,823,709,444,112,345,879,49,135,112,409,411,276,540,478,280,364,397,294,401,815,152,580,373,166,332,424,826,270,857,895,248,424,835,166,518,678,287,36,273,761,106,443,150,770,13,321,94,500,561,248,664,12,901,894,206,185,909,982,913,30,694,827,844,502,671,959,621,618,531,216,540,31,967,219,463,725,7,317,983,255,812,731,299,20,832,237,543,100,725,220,916,158,8,588,852,104,65,308,427,554,352,667,608,452,492,391,882,914,5,825,557,344,964,189,741,372,729,152,517,302,530,73,20,695,216,407,835,315,505,689,157,235,647,931,916,126,258,688,21,649,722,433,522,89,551,365,362,115,93,168,193,556,96,344,879,52,823,42,914,650,879,80,769,832,0,450,871,728,826,792,59,209,864,650,846,515,346,946,378,511,883,816,922,847,992,338,793,418,443,187,12,202,791,510,388,28,845,239,161,98,215,825,817,848,512,252,933,294,120,707,605,659,94,921,318,156,963,12,16,387,126,637,569,542,477,511,570,604,624,207,230,280,673,660,294,40,647,739,625,328,488,58,583,793,132,375,625,656,742,41,421,940,497,774,523,108,862,686,363,857,972,736,361,103,298,210,654,720,585,581,382,388,782,756,470,595,202,592,100,38,920,340,182,879,476,969,725,666,192,867,35,558,482,572,624,823,517,485,58,603,437,336,421,531,574,727,756,808,178,94,441,378,979,153,623,699,277,253,297,393,244,405,12,388,442,679,53,456,221,635,763,194,839,397,669,744,651,347,316,882,19,359,577,464,952,643,844,891,251,164,356,479,317,198,765,91,652,436,928,505,780,226,329,300,747,651,697,818,222,199,807,164,16,584,577,580,9,474,75,198,456,839,839,629,515,850,834,418,372,853,162,836,348,41,824,795,829,416,421,397,292,635,134,51,254,567,887,106,643,398,547,514,668,874,215,522,478,580,441,664,880,374,422,427,41,42,870,395,850,240,627,618,162,274,577,186,783,305,197,133,609,700,388,152,226,393,35,37,344,55,455,204,91,953,721,256,341,878,624,772,781,391,366,751,99,773,758,708,807,534,81,186,13,8,902,652,532,323,185,319,556,388,943,701,474,845,887,759,341,930,59,835,75,489,349,511,78,719,879,809,326,404,941,324,969,441,389,781,861,368,505,431,478,468,692,34,733,223,129,719,165,160,714,236,48,579,666,933,390,140,494,296,579,177,285,30,37,217,465,424,210,839,565,539,301,318,162,611,526,541,437,19,211,764,396,517,845,427,87,281,116,95,646,387,559,529,620,617,641,673,421,945,668,955,939,791,120,875,596,382", +"632,955,890,363,582,891,631,723,224,71,474,652,351,311,278,95,525,335,925,290,852,43,731,555,401,752,442,198,708,554,674,994,904,298,660,511,978,743,817,31,177,791,911,600,806,722,361,53,108,195,278,920,522,817,803,225,556,912,272,797,634,947,150,623,693,917,262,959,68,126,735,860,493,638,729,495,407,508,622,122,957,827,475,546,731,730,401,682,563,556,15,567,44,533,224,808,125,206,89,59,607,663,849,709,440,315,619,84,913,816,281,442,853,902,874,78,703,957,148,542,608,184,99,324,415,206,795,321,689,343,630,127,950,497,884,494,215,157,319,401,288,593,58,821,354,21,690,575,205,163,251,810,51,793,222,213,245,332,714,481,779,135,967,698,9,673,984,618,344,194,48,720,179,599,933,903,766,87,577,621,591,284,88,719,2,948,758,594,337,402,502,209,871,968,629,912,212,825,999,164,309,829,627,467,359,310,102,521,650,680,215,65,247,889,572,709,372,82,702,765,283,238,998,412,63,898,332,846,4,961,554,741,4,282,607,30,315,233,538,180,246,984,491,460,516,914,404,479,941,10,320,672,745,656,828,33,744,458,673,666,189,508,674,731,976,523,542,722,309,575,993,884,814,157,213,427,49,600,109,774,398,75,386,585,891,554,892,261,595,623,208,184,152,729,388,149,870,581,527,946,779,379,584,657,9,875,598,581,461,541,920,323,993,758,833,599,290,364,818,949,581,413,235,998,924,174,378,970,719,498,903,936,451,757,699,554,278,358,930,254,178,856,638,461,924,488,704,246,354,35,874,309,794,487,520,323,926,934,258,765,867,563,340,958,642,106,73,742,652,192,210,758,580,513,48,94,966,319,571,72,734,243,966,781,495,250,963,735,561,839,357,74,960,849,901,344,686,138,806,273,192,9,414,38,796,15,259,12,415,837,993,468,496,976,590,850,284,41,200,683,125,557,506,590,118,142,211,42,806,41,86,57,893,336,666,172,650,203,509,627,795,477,345,321,438,987,662,468,955,899,161,184,645,867,893,481,587,570,499,235,766,607,225,174,101,13,639,179,886,566,377,38,433,321,210,688,742,34,114,496,305,642,663,800,464,992,266,105,966,812,84,937,370,818,852,544,636,841,528,671,300,495,847,844,56,247,719,429,765,454,239,829,772,878,450,51,992,309,893,604,858,527,436,396,973,90,578,173,72,592,386,133,212,807,784,129,83,56,437,766,931,123,564,457,290,413,172,862,862,575,353,469,538,36,553,436,511,728,628,655,187,786,535,831,104,608,806,504,706,635,49,709,344,450,766,521,1000,428,79,9,951,873,974,633,450,0,261,821,987,33,298,791,103,735,28,104,132,167,67,788,978,193,875,852,479,727,180,577,935,130,224,428,227,850,126,132,596,929,216,346,138,375,700,624,865,464,830,104,775,86,79,674,428,756,410,397,479,380,395,896,348,556,239,273,531,853,375,491,925,67,868,842,965,621,5,491,476,75,561,480,706,128,972,399,96,441,73,50,570,913,973,763,206,983,770,519,263,588,430,504,361,882,358,470,868,170,581,144,742,373,299,796,196,577,244,633,195,936,324,753,294,830,424,422,236,82,83,198,860,737,236,256,996,976,154,252,426,900,488,113,821,75,995,728,600,23,594,591,524,944,450,892,129,846,669,879,940,911,863,833,159,801,665,339,357,844,823,407,481,967,527,786,678,339,488,370,440,399,903,789,75,421,886,603,36,214,194,332,178,218,946,517,250,467,584,950,382,131,410,28,430,56,202,556,662,852,937,77,312,110,915,884,300,32,676,281,991,393,224,412,89,490,937,107,994,262,818,387,660,964,625,686,281,743,334,608,497,771,285,966,763,953,605,537,773,268,235,732,809,937,567,150,931,311,653,464,983,871,999,752,705,483,370,105,734,534,922,368,183,183,574,838,883,154,182,389,466,964,121,297,450,346,139,385,404,885,811,283,575,789,120,179,487,191,351,178,400,424,250,245,794,96,830,785,995,578,211,886,418,314,935,669,7,329,77,952,435,656,23,305,829,200,141,540,188,550,897,434,560,13,239,537,894,234,617,356,698,929,857,828,325,739,205,399,369,143,639,229,405,623,263,391,553,565,776,923,375,815,330,827,115,733,112,938,236,60,660,200,815,641,836,464,9,759,976,443,945,935,828,416,580,238,18,663,874,116,613,60,909,504,292,551,437,334,341,844,58,366,426,487,416,513,959,915,785,746,394,918,619,989,68,253,348,674,455,927,194,674,322,823", +"388,314,50,701,11,703,702,618,746,861,766,167,891,333,763,604,262,718,714,78,329,433,198,499,410,471,33,594,325,420,321,219,795,770,928,663,938,808,167,44,224,146,139,19,869,848,295,724,894,563,345,605,173,743,262,79,480,735,208,608,264,437,25,333,589,154,9,261,113,789,771,126,730,391,779,271,364,537,165,301,716,314,618,155,327,347,222,956,50,728,565,559,467,653,818,619,761,625,871,554,875,963,814,390,339,619,598,183,996,493,899,888,427,218,32,727,781,61,952,436,359,813,334,928,29,805,248,47,685,233,547,296,731,478,905,752,89,819,474,826,630,944,920,936,214,247,349,706,137,266,962,510,89,35,844,995,981,546,729,819,560,35,281,29,88,160,554,842,121,785,529,531,39,306,873,914,565,393,75,398,384,289,845,309,23,574,383,442,991,440,111,571,505,992,277,359,691,953,42,193,854,490,487,552,130,835,169,968,917,352,561,927,755,645,868,617,836,417,677,987,828,34,510,456,508,447,233,241,223,289,26,580,844,300,492,4,627,552,629,91,112,902,731,67,252,566,410,567,482,456,883,85,408,272,242,673,687,308,594,402,487,630,284,495,505,864,549,340,585,397,378,998,644,609,939,754,222,682,664,947,26,512,718,415,981,986,531,723,537,865,877,30,437,404,779,370,234,419,255,643,795,899,949,971,690,853,577,195,359,935,551,103,302,636,701,85,423,86,797,370,15,160,121,198,508,755,482,756,156,929,803,554,541,917,269,736,810,844,638,417,160,316,138,712,71,619,658,984,87,602,864,143,785,271,648,716,640,593,861,237,853,271,77,327,659,218,917,159,926,947,821,537,147,561,62,993,978,865,331,890,761,37,46,151,18,840,483,442,462,804,771,808,756,701,288,853,997,734,747,709,868,475,574,122,480,703,992,625,157,552,231,246,10,462,951,317,956,30,145,418,484,50,262,658,216,455,62,608,533,903,895,621,646,132,164,328,81,546,547,478,906,202,895,360,823,618,586,618,562,55,16,639,467,653,728,77,2,930,887,432,279,226,819,181,930,827,560,337,34,969,303,711,330,496,960,307,856,374,738,490,303,835,41,980,570,903,989,802,524,672,798,770,111,415,37,26,396,398,192,764,282,641,509,706,951,212,818,392,842,305,64,13,387,425,494,198,635,593,438,924,791,773,243,138,517,929,866,962,698,312,399,560,129,255,603,477,578,155,794,573,514,93,320,751,278,770,91,674,157,162,342,459,347,979,110,231,776,651,525,666,586,325,667,646,639,518,858,842,626,702,952,428,25,381,761,859,990,261,644,300,65,775,74,583,871,261,0,741,714,458,24,272,394,989,494,990,550,608,226,750,978,864,424,675,724,910,14,619,88,476,790,162,546,245,879,756,819,676,694,933,586,478,630,91,536,260,566,116,568,458,343,381,201,482,976,506,614,127,604,181,682,981,731,949,93,463,704,383,965,859,9,261,105,681,148,384,204,203,200,801,322,250,2,648,717,700,991,171,417,10,948,951,595,929,62,217,311,154,691,961,759,131,504,190,576,478,236,419,505,152,655,568,978,172,744,662,818,687,342,352,703,605,774,578,727,117,722,595,243,451,709,872,220,82,654,522,975,282,204,886,31,898,900,730,176,771,938,535,657,83,13,528,200,200,556,160,255,21,21,123,904,320,286,71,689,154,476,776,292,796,379,22,45,307,73,120,243,890,665,594,27,749,27,991,801,863,963,48,513,596,727,928,681,127,761,998,371,433,971,151,2,309,110,852,790,154,59,595,625,383,390,829,277,671,377,384,627,653,569,802,11,460,934,945,902,58,824,22,771,261,895,54,552,641,931,839,102,613,554,829,889,29,965,637,911,570,823,521,260,518,380,358,159,678,103,547,387,827,564,36,269,18,18,896,277,887,23,344,278,362,180,504,273,904,937,829,10,502,648,390,610,880,998,497,494,688,589,140,886,608,146,815,231,160,889,361,620,655,193,264,650,785,736,811,859,752,834,814,751,981,871,404,397,198,327,346,456,975,460,202,954,890,793,470,828,272,311,55,837,175,132,560,709,555,776,704,803,817,920,632,597,678,704,340,905,783,335,759,14,900,750,762,819,98,970,842,84,984,46,603,880,179,948,794,585,975,95,68,412,962,39,537,532,911,19,897,821,662,669,302,693,468,262,67,870,929,32,173,374,984,955,302,412,414,684,143,25,950,882,870,48,744,962,323,587,786,313,312,601,395,647,185,275,767,478,928,464,617,11,958", +"319,12,376,198,573,650,553,987,734,757,606,283,977,503,610,387,171,720,617,775,685,146,55,216,538,968,703,561,597,53,593,319,544,878,841,347,110,130,33,913,54,670,911,3,637,176,363,602,634,707,603,130,222,564,81,860,987,779,941,396,265,250,709,152,222,308,908,176,733,354,295,967,904,21,938,320,840,764,673,521,124,630,511,210,90,818,320,27,726,880,345,247,574,817,140,786,101,920,611,287,218,241,911,477,839,428,799,414,203,330,401,613,715,335,934,910,556,770,515,997,240,438,136,85,972,698,413,513,475,807,922,753,56,427,338,58,560,663,181,108,809,458,945,658,161,760,488,358,927,397,459,530,673,3,100,299,732,838,38,637,401,536,695,382,145,640,654,664,790,666,798,86,98,97,830,527,370,762,146,548,375,169,45,538,494,327,593,705,380,185,359,331,972,943,431,281,216,757,882,276,577,956,524,641,486,18,137,480,4,20,711,888,916,511,157,227,358,64,265,540,633,424,108,755,585,674,939,219,233,879,135,676,630,343,785,536,912,827,815,184,622,462,543,13,688,548,270,929,188,676,641,364,375,902,383,184,775,479,172,260,729,792,904,267,980,480,42,598,549,592,523,550,427,1000,606,605,550,222,350,359,582,349,366,34,340,938,587,266,977,370,517,493,362,276,557,861,643,345,178,632,251,726,753,386,433,930,699,698,564,499,189,37,573,396,675,632,291,36,589,810,943,468,385,358,234,473,970,174,485,77,751,697,760,508,874,665,599,363,947,980,136,844,105,703,434,427,552,182,854,301,910,806,32,958,532,784,610,23,924,759,130,769,274,839,985,197,291,869,932,499,474,414,912,14,197,898,632,589,228,387,545,562,889,411,228,863,518,610,719,752,260,853,398,129,338,539,248,645,892,800,826,550,352,83,272,107,802,149,748,939,805,61,973,688,124,626,523,867,565,922,178,356,370,222,822,175,627,771,846,431,521,885,737,357,806,980,889,507,293,413,415,285,454,379,344,771,305,415,256,947,798,493,963,273,537,119,366,743,805,66,457,864,752,347,765,701,102,809,849,538,338,72,861,409,861,490,150,574,738,400,607,650,24,207,884,641,82,688,278,204,233,253,810,917,323,613,777,291,115,5,399,190,152,439,967,289,635,916,554,367,632,97,978,574,234,931,199,936,251,159,594,227,19,606,200,63,590,361,329,481,509,491,561,623,921,942,293,502,837,945,473,447,180,258,652,234,76,745,630,969,705,138,924,518,162,23,922,638,357,990,518,726,936,66,861,614,212,415,582,873,113,906,779,81,835,183,421,121,570,394,839,450,522,515,728,821,741,0,707,377,861,264,34,509,929,817,684,699,958,510,361,60,965,360,660,501,529,198,5,676,848,325,484,332,320,545,671,403,947,386,459,889,928,400,615,441,386,642,896,776,91,721,665,147,823,240,369,882,887,358,480,930,233,441,39,633,838,938,286,909,64,734,446,920,89,228,802,29,393,494,409,397,930,824,773,559,170,494,366,566,479,801,599,418,536,752,142,571,327,183,185,60,538,28,327,577,621,213,846,781,431,413,177,503,662,432,766,227,157,551,154,901,954,184,595,671,800,709,179,777,943,112,4,853,812,809,240,994,272,720,161,516,504,331,742,243,891,839,791,362,687,285,496,415,801,737,598,754,297,128,430,146,454,17,536,123,512,97,432,260,398,361,458,60,166,878,379,732,419,760,113,751,320,836,264,473,659,190,408,700,737,512,813,64,35,62,243,846,760,193,22,277,323,385,960,681,145,289,512,443,611,738,194,71,147,71,960,747,138,428,938,611,177,176,619,638,904,608,221,426,976,158,651,963,78,649,579,684,108,81,20,801,856,736,744,94,645,57,560,725,209,166,539,445,299,582,13,45,647,329,367,48,544,682,360,748,236,39,769,577,478,234,330,614,228,573,974,292,855,689,6,755,745,436,779,164,67,698,683,203,483,687,865,222,603,206,582,874,57,790,245,356,704,127,3,151,160,396,83,610,549,183,416,581,556,937,467,616,863,349,67,797,46,343,150,595,359,545,600,836,652,494,434,415,482,464,819,739,465,863,857,435,998,575,528,779,131,62,609,570,616,59,111,384,987,191,255,400,508,683,274,397,260,277,758,527,598,447,196,270,216,319,67,830,201,117,776,99,456,305,435,675,91,775,440,519,3,113,988,288,820,61,759,784,248,900,236,959,242,343,893,816,823,118,835,551,99,599,730,685,458,121,830,573,169,458,24,507,633,271", +"999,618,620,900,432,872,779,457,822,141,792,156,536,347,342,518,539,988,665,556,567,706,670,508,951,735,119,129,474,670,175,202,836,347,77,110,726,236,463,882,662,857,157,940,968,89,888,922,793,592,171,467,576,850,406,757,31,620,150,247,632,510,304,675,802,104,193,700,954,227,276,762,862,868,955,681,925,247,115,5,747,333,526,404,876,871,170,603,280,631,512,159,568,638,895,53,255,68,113,336,69,549,869,917,884,174,222,339,391,924,912,411,436,639,493,775,902,768,224,326,389,17,322,950,651,807,719,15,287,317,725,334,545,331,70,200,849,924,770,586,385,588,345,587,20,437,132,789,758,625,303,269,314,359,977,824,812,311,265,112,420,915,94,139,324,896,337,830,436,417,446,426,885,923,725,350,516,657,416,246,13,261,266,52,663,160,964,844,974,671,409,987,769,24,731,961,65,444,4,541,985,859,522,655,466,905,471,278,840,543,886,118,236,929,448,394,848,195,121,334,921,566,355,657,120,205,601,59,316,427,208,812,967,137,985,673,908,614,10,805,530,986,78,823,324,552,755,336,208,181,279,963,812,996,569,218,676,291,240,299,865,294,344,402,558,365,972,877,678,827,111,279,310,827,745,416,105,539,851,193,843,882,995,823,989,800,854,573,345,988,269,17,406,646,802,549,586,588,672,739,136,825,308,551,966,771,280,93,755,37,265,922,347,118,632,729,693,809,75,890,215,582,660,156,795,400,253,821,821,502,131,81,628,584,752,848,625,466,293,238,281,908,396,948,738,235,484,468,328,880,216,237,675,981,948,125,545,930,732,618,252,199,974,413,673,399,374,704,861,47,790,81,321,453,893,324,276,849,597,66,555,153,681,59,695,185,462,605,483,216,93,107,830,468,744,65,170,197,456,611,886,943,430,777,867,876,639,312,438,687,77,775,188,31,36,804,558,559,812,856,890,506,143,89,630,106,90,64,231,786,145,317,978,3,703,207,687,788,271,330,540,858,424,751,652,372,703,921,969,840,191,595,646,946,378,729,32,649,655,401,798,114,470,823,986,847,375,945,474,567,320,144,417,930,365,915,495,616,128,769,881,714,333,20,545,987,396,23,521,122,521,672,584,424,221,758,377,59,363,885,529,343,655,833,538,397,168,652,437,522,16,762,779,5,154,424,481,802,32,292,976,709,780,647,438,938,159,22,632,314,740,368,773,250,181,655,328,803,363,596,796,998,870,712,806,822,475,369,919,412,425,7,260,151,979,574,675,875,649,598,315,100,124,25,562,672,848,396,963,577,935,829,512,494,6,94,668,543,672,754,560,140,802,310,826,987,714,707,0,359,112,492,128,527,713,825,799,860,605,455,544,459,115,696,20,135,961,265,495,36,182,887,82,499,173,145,111,504,283,621,749,306,509,535,412,129,639,703,98,476,508,732,272,970,983,238,325,506,366,192,884,585,837,259,70,317,717,529,654,89,976,910,319,414,69,390,803,720,197,393,302,375,350,214,288,769,622,160,634,648,852,18,745,912,18,587,60,897,392,458,123,783,479,130,142,748,566,860,891,779,908,576,106,761,779,377,870,154,679,537,20,818,764,306,688,338,971,938,855,121,980,394,714,37,597,303,269,269,151,325,543,186,760,95,930,539,904,523,156,707,198,829,104,551,892,800,614,569,695,920,927,584,393,402,498,385,752,545,762,345,1000,792,118,170,862,412,277,49,6,763,102,412,107,509,213,422,374,368,547,520,206,468,992,470,619,514,943,444,528,14,301,368,873,303,766,379,479,440,742,483,685,244,429,536,895,432,189,74,906,828,36,244,18,657,671,639,448,926,978,312,829,678,377,34,792,508,661,205,137,789,193,882,746,577,795,204,661,130,660,539,172,917,712,359,837,86,64,813,598,82,26,878,861,137,214,947,243,324,263,182,508,842,204,921,914,829,335,855,561,395,807,624,661,86,56,386,486,875,506,171,876,243,436,542,671,592,231,673,577,948,612,28,97,209,148,885,837,157,624,444,333,621,152,140,681,165,162,806,220,4,316,620,924,80,100,349,585,841,833,610,866,355,791,446,923,493,548,406,194,390,288,394,82,419,828,898,373,591,617,598,495,789,116,180,350,534,203,341,498,315,516,829,797,182,811,573,687,890,608,314,671,325,292,115,933,287,897,556,512,672,397,993,859,170,602,158,153,463,401,135,669,611,529,397,913,960,617,301,752,282,502,700,336,141,683,5,928,258,430,176,904,15,214,549,712,630,931,620,952,882", +"409,150,766,928,919,155,629,97,298,25,879,374,253,230,572,277,457,429,820,797,600,160,270,77,734,158,591,455,279,178,481,524,163,230,407,659,677,472,506,331,827,569,972,856,335,760,546,847,402,712,647,436,219,829,325,7,279,856,296,37,676,410,522,746,679,279,633,625,633,736,669,41,143,890,526,921,596,274,190,307,992,112,460,336,253,168,166,797,633,851,134,690,256,805,115,823,930,539,437,370,855,279,949,134,384,607,96,484,815,583,134,110,170,622,483,867,181,856,283,457,392,561,970,168,150,60,114,673,662,33,722,462,789,575,725,269,168,836,412,251,514,796,280,459,832,5,975,694,771,386,807,142,446,257,996,89,46,16,820,54,691,562,815,284,526,606,199,818,223,758,219,568,456,331,448,998,591,638,960,779,911,776,528,11,673,628,45,366,349,831,803,486,229,624,32,285,385,959,874,21,309,253,549,208,650,963,435,844,311,418,270,880,610,504,236,715,483,55,133,177,341,473,909,825,982,474,328,501,255,652,940,856,522,703,824,685,527,127,791,670,618,556,534,119,556,959,722,206,721,657,231,173,131,617,619,637,318,614,826,263,715,430,176,806,670,760,592,51,770,520,386,989,291,956,367,455,566,783,368,46,146,57,341,602,809,751,922,692,229,815,493,51,471,478,217,425,503,735,661,133,230,564,584,737,222,106,65,123,889,956,856,754,582,470,532,343,483,901,94,939,779,179,308,422,496,98,70,203,635,446,530,365,227,819,909,385,751,872,570,529,954,972,913,612,750,192,722,696,613,997,766,899,685,788,458,468,909,230,54,753,322,708,573,804,323,37,129,291,36,778,212,883,195,218,30,794,101,343,706,600,782,277,987,103,423,70,880,165,784,740,271,968,163,854,177,778,91,750,744,921,719,484,57,286,915,357,191,21,251,396,71,959,633,786,103,281,349,355,338,476,361,376,241,789,628,761,677,389,824,348,184,706,729,425,936,928,589,896,451,968,728,274,392,100,623,794,259,789,593,214,744,907,820,476,944,994,730,438,666,296,595,181,564,753,313,348,388,852,377,690,715,995,165,190,250,783,702,577,949,714,908,611,274,482,395,19,487,975,286,773,562,233,684,64,28,228,317,452,84,29,860,454,681,946,776,158,968,641,925,257,615,640,761,668,468,181,169,631,388,720,675,165,710,480,277,306,153,754,876,858,300,469,277,47,779,808,564,243,894,548,248,492,10,542,456,647,53,630,337,131,678,341,899,162,668,405,493,293,260,83,287,386,973,191,111,381,573,827,552,617,509,869,300,255,100,768,913,755,546,738,276,605,38,323,792,33,458,377,359,0,953,269,64,758,238,888,832,16,946,615,882,542,347,549,801,455,43,196,599,270,183,803,127,565,723,682,962,31,280,906,833,286,538,273,432,316,239,519,835,104,290,851,701,906,63,157,515,116,95,946,879,55,439,733,997,581,380,281,490,280,389,803,207,851,776,646,653,406,334,189,122,335,498,626,176,213,919,816,190,42,855,573,120,761,752,249,484,913,818,576,92,444,952,172,913,604,332,986,917,822,871,584,113,229,878,594,810,127,254,484,153,374,627,401,78,527,317,629,72,164,598,49,349,686,337,551,272,203,545,851,277,714,305,842,735,550,960,120,124,102,66,966,105,631,803,934,573,47,187,490,597,838,528,1,69,193,210,641,230,471,99,414,475,977,468,243,90,927,602,577,671,864,906,501,568,515,973,779,980,894,292,938,553,244,912,224,83,418,644,98,665,278,991,962,743,534,711,681,990,926,846,385,505,914,652,176,210,469,201,620,394,895,833,161,258,888,874,882,203,576,84,23,861,281,63,733,105,407,302,905,807,565,845,391,716,432,626,714,894,41,992,887,60,968,394,334,245,432,701,393,348,430,491,142,855,129,542,410,147,763,275,854,708,984,393,790,339,423,242,243,122,217,72,343,592,762,389,692,90,594,596,263,772,902,510,150,324,584,509,8,780,272,923,599,670,429,282,472,380,652,553,784,10,46,134,862,382,910,480,180,872,485,633,276,617,531,463,523,652,10,843,210,770,865,223,812,492,208,945,152,760,742,744,315,228,269,398,421,386,980,945,161,10,373,961,962,132,333,822,372,751,434,354,80,797,703,294,359,503,805,219,907,161,697,349,360,353,476,710,678,717,631,164,354,933,573,538,275,889,660,67,394,470,355,460,353,21,328,450,362,378,818,991,955,328,142,751,492,313,258,227,479,881,773,900,252,90,818,929,557", +"145,252,552,344,207,196,532,926,854,239,499,976,610,480,664,467,947,26,388,144,524,752,165,81,53,368,255,809,924,210,556,141,892,28,878,108,329,881,929,742,504,525,274,311,874,589,645,683,653,935,157,781,262,874,389,14,26,919,951,839,730,823,559,776,23,816,630,670,191,510,18,608,882,764,163,805,76,932,909,599,763,248,914,456,181,984,528,352,413,295,637,939,405,413,660,250,215,684,184,892,352,715,645,471,85,447,603,225,892,445,929,643,765,858,297,846,306,423,698,952,410,491,980,655,989,545,892,216,171,350,966,40,592,100,691,137,739,986,268,833,285,55,551,764,388,720,454,194,656,675,893,765,23,679,528,465,388,381,850,380,193,980,50,260,128,968,302,930,430,134,968,161,622,465,637,986,179,464,76,320,850,878,721,304,377,891,839,699,547,169,708,357,547,257,504,71,137,691,607,936,664,843,749,787,151,795,814,379,794,826,806,222,765,939,421,580,491,387,833,623,561,653,414,857,696,219,947,428,885,432,614,645,712,449,717,713,504,927,662,217,317,975,905,52,292,533,816,830,660,304,286,645,347,956,418,751,684,666,532,971,925,870,38,653,47,266,517,960,180,623,763,746,382,580,559,946,753,637,320,749,528,291,978,996,17,763,883,188,290,881,766,744,569,105,732,52,869,997,302,240,227,665,395,129,988,349,247,315,599,31,206,378,682,613,527,590,356,571,271,468,363,189,739,854,497,211,809,117,404,488,205,295,925,92,399,974,31,861,609,992,706,199,310,630,177,635,541,400,710,865,938,90,942,384,222,213,773,456,452,641,735,417,124,942,232,358,277,528,415,439,686,904,764,718,308,225,408,378,431,971,591,297,137,241,337,777,222,608,274,572,971,579,197,384,486,17,424,933,976,625,947,115,891,333,567,772,249,227,616,292,317,743,83,525,968,789,230,123,929,101,23,943,469,260,799,858,708,281,721,981,717,263,457,765,262,594,879,32,296,188,802,950,709,169,497,869,842,923,439,139,521,35,811,339,7,365,121,165,767,961,392,543,600,631,760,694,675,676,852,195,99,628,115,858,32,70,333,286,209,500,897,444,669,198,226,857,701,270,533,577,310,101,583,885,92,591,264,66,784,856,701,322,444,711,713,306,441,664,815,827,685,268,144,373,843,95,987,636,368,577,170,798,454,383,939,555,756,608,383,431,943,826,450,304,552,243,415,660,595,23,54,794,742,253,684,884,452,320,707,198,572,507,789,273,844,402,471,745,459,476,557,330,257,67,632,763,602,202,264,881,535,420,552,647,362,298,958,6,576,681,175,922,775,29,59,298,24,861,112,953,0,597,526,44,829,995,485,604,67,769,716,464,878,27,502,254,889,332,97,550,877,878,511,201,169,844,202,937,862,294,623,397,155,103,472,857,750,237,446,355,260,548,995,400,874,703,507,144,847,212,870,898,733,135,922,438,19,356,467,208,280,433,927,278,430,328,515,527,35,108,913,15,254,254,881,577,853,29,27,666,444,466,136,220,643,151,827,342,752,535,759,564,126,274,397,244,609,607,213,239,740,877,871,13,586,81,742,699,525,385,555,661,418,662,247,72,417,682,860,12,920,976,838,190,737,113,931,711,999,173,980,458,855,713,4,655,637,879,89,943,426,351,845,419,347,690,44,514,860,176,575,824,283,352,128,60,749,162,232,70,831,975,812,812,216,349,242,160,14,830,406,144,530,152,389,13,128,972,762,57,638,527,563,489,977,138,634,646,174,284,703,959,313,831,282,311,706,438,91,345,984,829,256,516,245,242,852,886,866,233,247,570,969,943,308,74,414,351,902,120,870,209,136,568,980,270,146,420,816,606,595,620,824,588,625,150,37,300,97,455,524,504,866,607,151,63,220,771,258,705,997,946,232,221,10,182,439,278,375,44,712,819,218,48,859,309,851,933,668,872,909,775,51,829,20,727,162,770,520,912,937,645,495,457,432,128,392,945,824,598,352,47,91,397,490,538,269,387,274,825,967,636,957,587,573,560,849,533,664,312,585,205,980,628,705,36,561,302,82,708,669,791,879,45,734,737,196,373,741,83,517,75,250,317,409,778,788,566,548,738,165,108,374,382,716,890,223,547,44,635,257,891,457,687,497,56,359,590,393,855,525,456,914,698,608,27,338,102,517,543,949,276,453,351,971,382,846,512,414,223,6,101,902,751,996,114,984,688,513,253,94,186,801,415,917,32,151,677,802,929,593,194,868,712,112,184,11,608,196,601", +"748,880,98,688,846,749,989,439,620,670,599,598,620,188,450,788,73,677,90,632,726,76,849,198,439,695,67,887,319,186,451,161,240,77,751,99,913,973,550,856,81,780,191,288,691,428,428,586,756,631,975,948,371,105,884,755,245,978,821,525,880,552,946,3,90,606,467,920,10,412,301,473,808,218,628,487,948,854,165,142,861,878,894,999,51,515,957,147,878,974,947,23,878,236,208,184,886,351,841,234,212,886,766,196,712,265,16,982,175,315,106,671,723,478,390,902,891,568,137,553,700,832,146,416,528,599,471,767,421,90,92,239,448,558,76,751,560,168,215,691,593,642,250,513,987,932,706,190,872,444,984,34,367,224,669,311,774,106,405,313,784,267,390,848,644,882,942,631,873,32,195,295,217,556,244,684,908,599,642,649,340,223,791,459,597,669,541,644,265,73,667,634,331,908,366,116,970,656,831,695,747,524,821,693,800,772,866,618,937,80,275,966,209,921,698,970,960,570,634,619,323,363,447,253,653,18,164,946,118,663,178,856,244,322,260,742,314,528,638,25,650,346,532,909,799,490,476,644,375,67,825,660,501,324,509,734,52,608,819,315,595,517,654,367,636,207,754,171,621,40,804,176,863,133,859,223,611,902,217,321,742,907,905,261,886,78,184,212,597,814,783,709,54,154,400,814,673,894,431,525,544,993,557,691,635,369,264,270,153,327,541,867,895,83,987,988,693,631,800,513,165,402,848,953,814,571,819,348,584,279,905,498,437,346,368,387,854,296,456,363,785,517,674,197,646,201,259,100,72,619,514,732,687,778,103,796,812,582,240,568,298,368,322,739,924,214,943,387,759,63,397,195,114,610,817,600,206,512,639,237,729,938,150,701,779,20,201,399,646,678,470,588,687,584,782,998,350,550,240,604,680,353,842,809,721,10,125,75,417,491,360,404,340,541,162,194,753,588,101,192,287,471,879,677,372,152,969,308,556,226,83,849,583,527,459,617,361,620,147,294,280,856,905,938,316,882,211,372,467,970,171,201,693,242,804,904,989,261,742,201,237,731,366,141,679,988,578,470,244,472,887,18,883,919,950,124,520,419,357,187,862,488,497,745,487,298,556,251,553,411,481,488,950,649,878,287,528,514,433,663,371,495,562,292,599,785,695,613,510,624,133,913,670,847,874,837,425,805,782,941,545,186,57,433,663,663,767,431,600,681,483,356,865,164,627,968,421,511,314,361,685,196,441,138,876,735,292,830,306,988,512,687,389,471,715,906,471,41,259,517,280,367,524,835,123,782,248,413,490,224,950,184,817,800,89,427,330,873,80,505,872,690,984,610,209,791,272,264,492,269,597,0,226,241,216,788,454,988,462,186,247,131,410,799,226,371,531,80,427,85,698,482,487,599,104,39,141,728,516,551,205,359,912,409,691,425,396,520,801,765,131,703,78,369,133,369,143,838,810,31,72,896,941,283,92,503,53,414,805,314,723,790,43,666,818,925,4,512,517,571,72,420,830,135,515,689,478,882,300,594,649,708,349,98,141,900,971,519,912,927,804,748,445,399,453,256,920,461,467,571,58,357,251,295,33,27,560,292,189,954,319,422,334,752,30,417,441,273,665,381,316,846,844,709,46,242,751,693,43,595,140,648,903,774,182,299,57,772,968,49,258,962,507,447,760,398,795,112,482,647,937,339,110,745,189,74,365,370,479,503,765,942,111,861,842,959,582,137,417,345,21,681,673,921,80,496,918,219,753,344,474,400,601,660,66,202,818,654,136,889,686,566,568,187,652,105,222,505,774,164,369,510,49,340,804,217,583,232,191,132,599,612,642,778,996,603,61,210,24,892,946,378,620,611,590,10,963,426,441,769,99,702,852,401,976,343,161,77,320,947,526,511,788,687,464,393,796,371,962,947,501,256,498,49,898,527,132,854,525,803,451,577,792,692,9,148,481,878,622,629,491,438,738,530,984,231,902,657,375,713,379,680,676,370,494,153,865,769,586,568,665,995,804,544,305,838,963,46,284,535,178,842,57,486,243,774,784,543,719,760,694,702,623,733,598,361,330,662,516,465,141,334,832,111,316,351,998,141,178,793,180,596,486,553,274,193,534,260,203,968,573,537,937,308,653,737,190,489,831,214,831,830,467,119,223,712,813,731,11,759,931,638,575,521,844,843,258,453,470,442,943,902,227,342,308,381,159,751,489,893,724,536,177,319,109,82,664,287,784,417,972,84,422,155,519,959,733,39,994,317,842,378,855,692,748,194,857,323,882,150", +"136,429,392,842,584,154,160,14,471,315,627,920,748,347,226,297,992,525,185,973,678,815,357,184,61,703,997,939,871,597,955,45,870,182,696,536,466,130,765,208,462,753,185,895,377,232,270,370,44,11,251,94,8,606,789,520,27,580,13,579,187,181,821,417,704,597,20,636,713,776,485,194,50,237,910,437,843,64,230,991,624,443,74,631,987,752,449,850,59,997,271,219,876,66,815,19,205,475,357,848,669,474,538,948,695,922,889,812,322,201,241,528,694,48,676,694,838,521,944,622,82,983,827,837,967,921,107,293,899,222,329,928,354,143,985,600,911,694,944,774,549,381,13,945,434,952,54,744,745,123,391,70,361,281,577,367,986,171,387,240,474,668,548,908,810,377,259,358,1000,382,609,77,254,448,145,943,762,890,262,185,184,354,417,279,175,411,388,336,108,42,161,852,82,267,119,210,48,881,576,528,97,949,118,707,780,769,740,217,644,366,541,691,355,876,722,934,21,967,811,583,95,695,191,990,769,455,240,384,120,466,463,795,63,687,76,589,630,325,701,546,65,875,84,623,304,407,365,111,946,519,670,497,213,980,288,813,685,109,463,878,741,228,435,615,98,642,641,175,534,729,292,931,535,578,652,219,608,333,172,778,894,694,588,79,716,413,615,407,772,952,875,100,920,470,405,480,10,866,75,312,438,164,100,273,294,958,107,281,388,812,635,570,273,302,898,724,665,28,29,612,504,971,243,563,503,622,244,781,542,107,525,866,595,886,692,361,399,606,118,309,860,263,419,25,395,602,231,649,112,464,845,456,851,754,840,859,632,516,82,10,907,224,274,909,962,689,725,777,181,349,478,600,797,49,305,761,808,584,538,726,34,340,692,389,102,61,671,949,950,414,332,784,906,776,41,134,292,217,491,386,597,45,351,14,312,300,834,494,642,427,626,43,573,616,497,750,829,217,502,425,716,828,661,797,632,465,756,828,958,220,824,673,528,580,17,718,73,269,152,866,261,986,26,15,682,995,815,42,813,177,470,953,972,822,240,132,678,637,430,901,199,720,9,94,184,256,833,293,368,942,800,906,893,586,959,467,552,208,879,846,191,126,785,808,582,678,961,394,490,135,491,746,274,712,396,727,435,515,682,134,501,575,197,874,518,851,477,850,988,744,453,249,325,378,414,230,349,8,486,173,518,145,784,802,270,366,541,966,620,446,707,501,231,572,424,437,782,398,26,212,451,206,577,966,606,171,194,614,222,867,111,518,66,725,511,851,860,176,795,222,912,660,434,447,716,372,105,342,24,949,811,342,726,706,456,894,269,477,130,681,717,149,801,424,864,103,394,34,128,64,526,226,0,20,334,59,94,894,836,260,435,466,51,866,814,726,403,794,422,304,471,182,79,906,314,418,469,787,561,579,396,875,957,728,993,187,629,99,768,385,459,868,95,204,958,275,932,415,220,408,644,24,773,328,311,198,768,144,610,845,392,681,635,851,748,928,15,496,233,298,807,240,449,162,967,679,968,237,28,211,938,227,473,342,971,679,19,164,835,900,623,41,13,656,347,755,632,219,915,592,234,539,63,262,149,411,705,190,733,123,648,99,989,476,319,964,433,639,207,199,630,121,316,993,426,350,210,352,244,211,917,13,946,789,196,185,594,561,172,944,794,367,60,894,153,317,929,442,708,290,694,153,371,580,183,770,763,998,472,868,463,693,996,319,497,873,835,472,354,548,114,610,252,723,760,695,51,7,490,782,426,406,638,513,637,210,94,680,32,131,318,229,758,501,942,681,287,171,979,156,979,978,470,126,938,628,989,498,960,325,964,418,356,952,620,466,168,867,672,14,449,476,468,753,135,663,275,871,375,175,613,477,530,71,870,889,692,339,593,32,14,718,530,872,412,975,985,74,314,125,531,93,895,279,563,625,466,830,493,52,493,777,858,973,151,992,415,22,229,143,460,111,575,835,950,168,354,659,186,785,436,23,266,580,863,75,482,573,769,675,934,113,371,376,356,803,798,961,98,761,405,237,198,188,598,340,709,853,393,761,632,963,9,417,391,6,962,583,644,38,176,703,613,431,826,959,877,204,102,55,693,773,631,986,15,343,437,847,733,695,908,946,960,491,317,653,887,567,339,951,472,660,548,574,459,836,137,249,884,982,863,389,34,480,111,174,891,278,278,642,418,245,80,71,364,32,968,981,482,286,88,820,195,333,826,56,647,23,296,546,241,313,208,681,515,215,242,297,968,686,482,694,46,879,122,965,137,436,71,159", +"226,309,700,506,704,16,198,653,312,445,991,966,379,631,67,7,980,852,179,558,743,707,211,304,532,570,154,705,57,186,570,862,803,54,236,757,878,565,984,466,12,772,265,749,610,345,618,57,683,559,252,605,542,845,416,636,70,394,855,409,142,357,526,751,361,430,523,440,343,335,255,384,771,393,161,465,249,42,373,594,788,884,756,764,481,142,99,82,30,857,238,975,518,73,781,187,7,104,210,67,411,670,880,475,249,368,563,565,673,66,862,164,145,646,385,650,461,145,12,152,662,898,94,898,761,469,709,64,474,731,545,751,324,988,23,576,487,443,540,676,981,402,249,992,625,589,246,257,504,264,59,400,784,639,739,870,990,18,847,536,576,617,4,866,869,233,237,30,352,914,702,960,160,400,918,173,660,102,571,517,80,893,451,62,42,839,794,708,184,71,826,886,863,126,814,636,429,546,91,897,338,74,668,890,978,9,69,298,719,303,904,651,119,282,138,288,611,909,612,894,347,371,231,235,274,647,80,354,632,964,385,377,200,324,325,69,233,59,198,783,550,966,390,68,146,926,435,603,976,150,925,854,655,943,868,506,811,560,238,62,400,220,782,922,204,901,169,869,546,48,55,469,381,369,371,764,149,774,754,155,622,463,960,784,458,563,454,171,111,900,778,79,387,485,158,469,974,856,914,820,263,393,885,825,993,851,373,328,544,430,86,804,517,915,341,374,584,850,909,721,915,158,174,254,195,663,571,665,640,758,394,750,746,521,95,946,248,770,94,26,691,828,304,595,94,42,70,15,882,681,167,950,161,616,854,117,583,327,189,467,252,245,168,533,241,497,103,736,939,9,28,195,648,781,769,900,161,279,501,811,663,467,168,802,816,542,502,81,163,878,836,658,423,626,367,490,527,738,694,225,967,737,328,962,944,905,298,834,460,591,857,242,104,973,644,523,546,938,113,533,603,671,863,943,435,22,568,603,944,646,846,493,550,461,98,501,452,868,439,476,525,616,253,673,840,35,586,787,111,627,808,40,279,945,486,723,42,941,225,295,27,228,466,268,109,146,434,641,393,751,421,473,674,300,600,129,464,133,151,98,334,680,150,885,987,748,801,696,988,145,428,661,772,535,424,735,463,172,317,574,156,698,23,304,355,915,9,106,714,697,953,555,212,407,12,777,222,287,861,767,918,448,169,498,787,600,411,886,84,460,90,914,87,783,960,374,171,458,775,325,459,139,256,771,839,35,627,861,344,493,925,823,457,831,379,780,639,203,700,881,827,631,430,705,457,914,987,532,450,834,530,137,155,639,81,606,973,692,50,675,59,265,925,912,650,735,989,509,527,758,44,241,20,0,581,597,504,7,641,722,567,373,745,952,593,768,614,142,373,284,968,298,422,355,563,534,807,769,425,915,874,100,251,952,961,797,816,200,408,710,23,11,191,807,30,257,167,674,412,138,385,719,67,420,668,244,527,234,280,627,498,38,908,195,882,800,303,964,886,267,112,96,540,835,20,942,322,803,429,104,573,313,368,559,762,436,29,466,18,296,352,678,655,240,367,402,620,499,744,320,509,710,703,866,102,355,941,874,323,111,297,784,756,521,472,455,333,493,653,344,780,675,583,603,695,293,403,377,482,298,835,432,500,104,929,809,151,590,34,354,4,774,525,555,160,608,494,255,593,713,939,297,84,470,767,176,851,321,474,548,192,699,8,391,379,605,309,454,506,992,829,4,805,59,393,648,574,206,486,192,390,747,1000,175,728,268,857,908,551,588,434,973,44,925,784,58,251,52,355,923,364,816,900,191,279,385,805,696,452,875,725,580,280,596,60,662,805,469,777,837,96,206,387,546,939,195,305,689,161,740,794,15,832,296,125,422,803,594,438,158,782,609,92,28,359,391,918,667,191,730,30,298,358,457,889,459,164,876,924,852,419,421,972,476,111,906,944,488,409,71,354,908,780,136,699,711,860,644,986,494,554,817,427,92,993,230,218,974,407,568,800,359,315,658,384,963,307,759,914,923,92,795,907,929,103,348,512,740,631,874,219,299,56,494,431,785,134,519,992,319,202,963,803,535,219,786,154,953,880,90,869,341,453,907,723,195,836,549,293,112,910,48,887,354,262,404,701,286,555,548,812,657,675,188,993,828,718,979,538,815,881,598,197,503,706,701,832,680,819,794,855,830,590,599,359,995,217,130,799,145,27,789,814,927,912,993,988,228,987,287,326,596,565,791,51,710,965,680,737,944,86,908,589,224,161,891,18,97,585,340", +"853,539,723,946,118,648,455,477,524,578,450,35,66,44,419,126,442,421,111,287,404,965,708,339,667,420,129,998,773,983,264,162,533,871,423,180,884,232,307,456,449,117,387,30,134,89,386,86,696,509,2,592,193,387,803,762,580,430,347,739,704,911,548,803,450,41,100,549,447,632,673,13,663,87,629,936,389,691,283,563,420,998,836,613,322,572,106,980,891,51,265,641,309,531,480,490,54,849,653,848,339,471,694,290,975,107,665,848,168,895,836,351,780,965,846,685,333,258,657,418,255,947,337,187,789,530,81,212,633,265,239,562,984,48,461,188,295,332,273,437,766,973,251,707,326,911,205,347,649,56,208,409,102,23,960,606,446,926,575,390,352,835,343,564,515,62,241,447,637,740,569,840,222,508,774,294,16,598,901,54,745,719,623,101,89,329,475,693,206,967,815,663,408,351,392,754,942,860,598,185,334,414,227,508,201,181,540,592,850,641,747,621,286,700,388,691,85,17,760,860,549,228,51,322,689,31,20,623,549,191,497,763,134,596,783,254,171,198,604,228,929,490,307,85,188,409,561,393,364,20,921,341,967,766,997,361,648,692,76,211,151,171,40,882,207,232,418,621,154,627,912,452,787,934,160,724,215,889,908,365,965,352,682,278,126,49,397,265,383,338,431,924,92,36,270,405,329,749,446,284,443,998,791,51,871,844,523,749,282,778,144,864,449,812,99,59,524,157,807,568,828,811,496,457,347,216,348,40,996,13,103,702,941,665,557,478,944,189,396,997,592,168,781,68,399,944,507,940,536,835,272,671,225,512,766,935,380,782,35,178,270,94,224,860,254,731,464,14,710,985,943,901,525,481,879,788,41,165,526,160,616,89,317,210,519,917,510,974,22,299,724,509,790,264,994,984,126,695,270,99,761,902,873,204,775,547,134,682,135,522,372,882,216,632,691,214,865,937,566,961,658,920,885,841,861,402,488,711,999,417,399,784,467,471,55,695,785,735,758,481,50,743,826,735,642,989,179,777,979,576,113,390,151,60,541,21,796,370,523,796,989,448,214,389,378,619,857,812,81,814,61,638,17,696,361,331,727,787,656,437,863,686,835,650,324,715,15,812,294,366,614,893,498,325,576,515,498,658,98,443,554,768,259,509,623,705,934,499,785,538,280,125,800,82,895,881,421,708,592,47,556,566,617,822,141,262,884,514,115,17,773,273,937,674,102,643,266,658,633,15,471,693,186,308,347,329,919,197,67,586,604,582,919,800,793,973,887,751,26,901,237,702,201,554,65,697,630,777,741,152,432,621,190,515,293,238,245,607,185,235,585,683,775,268,846,28,494,929,713,238,829,216,334,581,0,172,837,804,582,595,472,837,427,742,788,381,769,382,808,460,796,283,785,383,707,700,107,157,943,291,255,299,314,960,602,142,518,218,60,543,886,40,381,130,928,307,359,430,303,153,148,856,903,475,742,494,762,969,404,883,671,17,573,289,713,938,910,812,693,291,524,11,659,72,268,266,352,579,698,424,516,512,821,344,170,976,730,391,637,50,870,762,356,537,743,771,103,318,762,193,680,623,913,646,390,515,870,552,282,560,986,962,502,280,802,797,307,693,843,394,556,656,133,653,715,929,388,883,692,590,239,105,843,485,189,736,147,949,780,46,273,675,193,966,198,171,684,141,944,216,938,984,877,104,5,638,144,862,342,902,709,742,834,208,234,324,351,813,746,788,165,183,121,492,319,114,358,393,835,190,945,637,465,419,934,599,432,567,429,512,490,265,581,622,681,5,634,399,807,705,739,336,483,697,806,984,792,360,26,404,48,233,841,245,898,420,558,677,521,250,392,391,462,328,978,663,864,666,864,956,548,219,275,511,358,179,987,580,394,253,601,647,108,202,237,590,23,462,39,384,203,33,93,514,928,297,905,637,312,345,751,382,959,692,285,867,734,51,473,809,987,451,898,986,863,554,291,481,931,514,608,403,167,692,109,926,777,873,853,2,22,855,479,775,547,816,810,348,297,747,702,11,666,457,194,316,174,183,39,144,350,505,549,28,879,748,511,554,585,849,723,438,557,695,861,696,361,44,638,458,736,873,283,124,926,825,135,731,402,481,881,903,459,571,270,95,610,589,444,304,877,567,72,262,879,391,826,56,943,125,743,140,218,159,397,978,397,159,631,680,907,102,546,840,591,856,411,747,33,455,470,612,430,9,783,689,470,155,764,805,177,394,173,667,836,815,766,603,571,102,652,501,338,204,353,588,487,926,513,610", +"21,687,753,19,44,11,258,548,830,607,83,52,570,521,514,65,186,493,440,703,830,141,710,856,623,957,409,915,296,772,747,977,528,676,927,876,698,887,320,818,292,575,182,68,91,114,128,634,346,502,203,78,771,914,643,485,965,220,348,962,383,546,640,531,118,598,520,131,655,820,7,752,981,149,870,218,726,553,673,696,882,671,338,818,656,304,230,44,753,918,249,703,562,322,434,759,345,598,193,335,170,680,741,117,867,451,299,49,125,435,491,826,405,474,404,177,908,136,153,17,745,862,202,782,174,955,906,27,373,900,46,536,365,813,414,444,128,377,681,12,825,259,321,123,544,22,817,676,968,646,58,878,893,541,290,161,285,182,541,512,437,282,886,488,473,773,328,746,883,850,74,417,447,515,412,783,270,154,44,640,518,90,560,323,543,885,478,809,246,563,368,483,137,816,397,793,60,293,797,441,871,914,296,278,40,116,732,522,589,889,749,606,747,480,523,984,627,383,87,718,635,688,294,771,165,985,383,839,797,640,282,241,628,666,90,628,577,109,45,350,109,262,662,583,78,6,707,151,493,381,732,259,99,292,538,398,717,101,792,164,410,976,597,693,745,835,284,669,249,585,764,307,865,529,445,565,536,571,731,808,665,5,884,964,33,670,701,704,200,795,588,989,607,13,531,982,509,278,263,642,711,933,696,792,696,622,183,358,374,372,553,959,183,37,19,126,90,936,715,93,669,373,297,537,792,603,821,799,46,797,490,156,147,833,244,414,658,157,358,274,449,543,967,151,379,96,735,159,274,116,219,819,243,842,255,835,756,690,557,781,619,219,164,412,369,787,397,890,200,67,109,260,870,998,551,141,878,789,27,613,263,718,195,173,610,97,237,331,490,64,617,151,560,695,2,209,103,882,261,468,838,512,84,438,799,977,812,477,927,495,362,215,861,899,786,35,957,443,602,268,29,826,831,685,987,170,188,555,811,532,300,42,795,814,184,434,327,484,44,704,108,577,512,828,783,707,541,725,279,902,270,600,990,950,742,510,482,379,519,432,577,365,633,811,501,39,599,161,829,921,604,369,227,163,692,555,549,756,727,157,619,133,333,300,371,126,87,732,111,986,345,953,936,995,245,70,693,546,368,729,644,632,951,622,582,116,939,527,208,806,917,555,644,469,178,671,135,374,499,414,937,304,769,322,214,184,798,430,269,752,790,502,275,470,581,930,677,719,830,62,699,69,607,227,778,832,509,477,99,171,16,898,775,474,520,127,598,85,880,623,284,792,716,798,952,319,528,339,906,249,62,881,822,940,576,187,304,47,909,99,146,915,544,793,515,104,990,817,825,888,995,788,59,597,172,0,696,466,730,353,861,206,604,257,902,19,490,35,188,581,881,894,151,490,181,314,562,860,211,474,205,115,393,530,674,796,304,731,506,309,347,540,608,332,782,789,246,256,63,680,493,745,126,291,709,360,124,29,416,966,746,736,26,332,526,84,5,111,618,412,4,120,949,531,179,331,427,915,901,443,320,490,911,91,586,405,352,150,670,107,509,789,756,293,901,67,890,408,578,26,945,916,775,928,341,275,868,894,351,527,622,997,82,715,757,659,811,113,173,936,987,227,246,854,557,756,600,14,741,845,104,450,371,868,243,738,517,510,259,508,273,52,840,226,554,154,537,551,801,965,687,385,760,865,833,420,904,85,363,270,418,241,189,899,82,207,546,633,961,829,65,474,818,593,998,784,636,314,537,842,479,673,83,408,398,470,356,754,242,398,589,311,271,83,565,635,660,847,205,176,210,583,387,716,29,898,859,794,533,304,846,372,130,856,78,64,661,940,496,294,496,493,207,16,873,744,555,791,999,676,170,988,124,327,805,345,889,348,12,488,562,695,185,955,212,12,369,246,952,349,726,452,863,566,366,109,339,361,57,177,951,975,526,189,744,614,16,877,475,53,317,490,151,387,746,365,614,306,645,789,810,925,482,444,446,783,587,559,497,491,639,482,445,124,561,832,515,81,478,846,166,786,409,230,566,345,160,727,109,501,231,181,526,696,446,920,163,909,350,696,804,417,994,720,636,864,443,116,59,306,465,803,141,511,815,861,59,361,664,182,957,473,440,9,741,123,865,826,777,226,562,475,494,721,10,477,652,329,855,460,366,270,327,64,676,191,109,740,164,539,340,357,738,539,865,350,740,58,671,367,814,24,864,7,631,298,564,746,440,801,506,108,368,711,594,88,658,880,923,690,972,410,114,500,461,538,617,839,758,727", +"620,681,83,933,731,383,144,290,339,104,236,324,141,785,377,339,871,425,137,276,856,247,39,275,651,512,492,839,888,474,98,999,811,647,398,245,86,452,677,14,959,576,151,83,784,487,185,88,82,363,523,285,169,137,275,458,261,436,475,766,255,366,763,684,194,642,896,939,715,468,683,709,531,692,602,675,486,184,889,419,624,2,555,72,700,30,878,977,975,390,42,587,488,337,584,695,64,82,439,297,237,795,272,216,889,821,69,893,203,735,801,107,702,916,717,159,817,776,86,545,99,947,343,980,972,616,440,312,545,852,775,329,640,978,918,585,493,356,864,763,634,759,412,335,631,597,400,855,395,907,216,949,358,864,489,524,684,969,237,411,143,780,346,395,879,405,12,202,134,879,542,722,976,100,616,640,379,947,964,799,889,401,330,740,69,151,550,822,230,999,247,20,256,637,593,641,951,236,693,669,915,818,494,212,777,148,470,863,305,31,967,932,7,394,648,104,343,279,413,801,829,941,578,816,99,198,161,485,757,569,764,199,880,930,985,470,867,825,937,591,276,438,145,172,898,202,926,300,294,907,947,573,455,461,449,314,629,242,685,266,493,669,647,416,985,636,428,351,859,581,37,957,399,585,822,796,710,576,933,930,424,974,626,741,203,284,893,764,355,56,797,34,725,350,3,626,227,809,917,914,590,165,41,460,289,658,766,823,861,418,327,81,10,789,224,810,112,212,582,422,839,562,405,337,11,516,778,585,907,684,672,184,229,252,690,727,886,551,114,986,514,143,63,679,176,464,884,23,974,283,255,33,421,498,779,687,399,285,636,995,109,664,356,548,856,229,740,328,385,680,713,730,763,818,412,387,48,299,284,942,636,561,250,777,29,257,602,530,502,145,529,656,329,503,657,356,20,863,286,740,955,609,323,926,358,123,883,397,822,714,248,731,375,89,890,556,564,119,475,244,124,92,659,547,969,452,983,582,909,631,854,554,153,591,909,490,826,295,893,38,414,468,384,2,757,877,555,340,771,342,957,522,223,296,428,242,809,631,931,526,863,844,482,639,791,462,88,553,178,653,530,8,961,555,587,634,577,744,230,161,806,795,657,603,133,760,778,208,644,783,753,884,25,316,618,427,142,241,132,773,129,451,343,534,186,751,238,981,161,131,449,130,828,851,301,664,869,658,820,445,194,377,286,230,474,143,767,202,551,509,305,841,682,375,168,292,528,954,154,34,658,720,193,47,568,405,553,662,553,588,655,822,200,210,149,281,94,289,176,327,395,685,503,182,245,228,124,167,645,336,120,206,933,725,640,203,293,263,868,751,992,885,443,567,346,132,550,684,799,832,485,454,94,504,837,696,0,660,886,754,210,560,909,422,525,306,528,980,657,288,31,774,535,799,504,808,741,496,839,204,546,277,557,564,912,259,206,318,253,896,695,236,846,41,70,414,142,343,735,831,966,602,477,881,865,761,595,769,868,346,438,829,172,173,967,472,296,36,151,443,653,239,702,557,113,19,595,452,689,167,848,685,327,613,870,252,924,188,119,267,261,310,341,393,963,401,781,650,235,624,766,669,531,585,702,523,370,44,846,666,944,516,560,208,790,450,527,370,882,160,356,1000,746,598,902,430,773,263,620,577,786,685,154,322,793,49,197,671,751,375,874,864,199,972,200,320,540,130,760,45,375,557,233,63,650,538,457,579,377,920,567,207,359,791,899,994,567,905,864,32,527,219,722,975,346,917,653,229,150,857,537,219,592,905,749,423,29,556,806,680,169,53,554,402,57,644,130,46,551,360,825,911,514,978,61,332,801,968,121,407,62,355,247,134,421,166,189,300,514,116,655,967,672,338,478,442,426,499,124,606,597,153,20,278,782,473,337,583,968,257,582,437,785,698,7,736,912,957,106,462,513,698,888,3,555,579,775,974,750,777,911,151,713,216,321,439,68,404,156,587,733,866,934,788,316,589,417,789,177,22,557,251,357,679,114,911,381,401,402,205,407,961,487,625,55,737,119,367,938,8,643,191,628,309,644,52,688,313,618,252,653,290,588,325,465,985,311,918,148,972,870,992,127,359,5,903,765,163,443,680,178,882,280,533,364,340,848,629,310,123,458,409,914,788,31,198,456,849,748,657,703,578,379,25,277,57,281,979,182,400,573,242,309,639,365,860,526,150,247,694,195,378,717,784,106,622,777,635,842,475,205,568,258,436,26,979,860,845,205,356,542,707,218,502,32,9,38,869,569,458,449,315,768,924,831,36,116,25,218,756", +"89,883,245,650,780,482,518,458,453,109,868,884,53,376,364,430,218,713,894,686,201,352,584,981,635,854,252,794,438,690,470,941,122,50,710,310,862,667,307,873,991,398,531,404,830,655,287,86,233,230,425,759,749,181,111,253,968,167,515,409,101,225,206,45,391,483,149,277,38,433,24,931,39,687,742,187,58,23,409,502,201,738,337,735,868,213,356,248,442,200,294,618,428,967,981,364,301,419,392,166,690,309,530,58,346,85,513,60,105,533,783,471,304,843,783,459,675,726,612,847,492,404,955,724,421,545,417,260,317,140,774,619,150,150,246,716,161,105,284,431,380,869,545,788,76,296,426,392,679,351,458,65,888,215,27,843,640,54,976,464,767,419,558,19,330,247,968,200,408,710,627,239,968,888,164,725,724,132,361,372,280,350,958,470,537,6,902,34,483,200,504,407,313,638,771,202,961,980,854,915,869,707,224,471,456,990,451,562,993,803,39,575,413,595,691,654,787,775,323,787,392,129,983,876,289,7,407,518,184,622,87,209,541,135,36,538,580,411,153,161,897,17,572,565,420,932,295,624,703,242,791,301,31,699,564,689,326,437,392,539,542,286,800,484,488,236,621,114,313,976,648,529,864,864,79,24,163,630,762,803,869,132,487,880,634,782,443,433,30,358,743,170,288,672,818,578,457,451,327,79,281,562,768,611,644,411,849,330,405,845,306,421,856,457,173,441,62,181,244,366,322,445,555,349,681,610,830,908,498,304,685,803,995,449,722,153,730,612,74,297,937,689,913,556,13,108,81,283,433,655,327,356,766,828,744,583,443,987,729,36,419,287,643,149,88,146,923,544,996,654,765,497,725,950,286,274,307,334,543,5,382,81,846,48,835,101,665,106,35,204,103,384,985,584,16,291,212,575,986,273,672,375,801,594,296,288,530,672,397,312,236,741,470,190,741,701,747,908,127,823,255,336,646,410,770,290,185,500,130,595,158,755,663,251,925,920,180,338,481,602,897,730,939,547,89,767,797,835,712,969,344,19,627,293,493,509,964,414,620,838,315,114,763,30,562,206,779,74,7,825,771,367,168,785,807,286,980,145,183,366,411,801,754,436,590,538,538,565,551,618,474,616,659,23,827,955,491,33,508,262,127,606,633,887,288,507,103,628,731,585,682,229,756,461,526,850,236,351,238,705,285,354,260,682,798,241,171,64,132,911,921,623,708,765,608,305,266,183,593,229,556,83,138,398,949,64,426,541,212,308,294,284,173,232,446,945,941,779,512,229,390,792,351,568,833,271,693,166,671,847,948,214,76,697,619,204,795,223,695,701,265,46,174,240,946,167,608,699,860,16,604,988,894,7,804,466,660,0,453,687,537,577,723,421,675,87,770,60,981,806,239,158,685,380,515,450,781,608,896,311,988,91,685,70,791,906,130,981,688,522,808,909,722,16,808,650,789,83,356,266,534,157,406,325,755,72,155,609,13,703,27,832,474,464,91,604,860,661,62,153,674,229,962,281,710,123,512,352,241,647,516,721,456,556,156,351,253,873,519,802,711,750,248,144,394,172,277,331,280,347,125,627,958,217,988,151,512,234,936,504,833,289,72,835,436,806,674,479,531,367,574,191,970,308,94,36,8,393,180,736,814,218,999,231,100,554,753,15,43,419,165,277,958,239,309,668,918,278,291,683,353,701,471,51,158,389,856,493,607,87,944,882,849,599,438,544,303,274,78,940,147,245,863,627,484,626,868,442,830,798,96,603,501,677,660,680,963,786,662,278,494,650,278,466,329,432,708,484,533,549,492,377,391,220,757,249,95,865,131,698,591,300,962,424,84,964,199,701,313,330,944,287,380,427,410,879,675,872,605,779,580,663,571,475,626,985,356,531,413,563,942,825,455,897,472,157,637,249,531,862,207,511,608,837,110,83,667,140,914,135,271,282,231,92,628,30,552,165,620,1000,355,42,696,783,198,395,211,213,906,40,234,915,444,217,650,122,165,968,281,244,979,967,569,768,224,668,746,237,965,911,428,336,886,596,89,887,530,906,811,527,470,774,70,528,268,873,377,435,596,120,389,592,746,315,702,391,997,638,791,646,132,257,218,69,416,906,501,789,517,948,723,140,321,758,758,257,13,573,946,664,293,263,183,645,594,219,615,772,825,566,381,195,945,551,877,576,717,339,821,661,919,120,678,635,709,68,291,661,523,840,555,734,681,454,135,513,596,32,963,735,11,712,673,528,777,571,868,253,928,211,238,112,654,312,986,833,670,831,924,647", +"319,888,967,97,416,235,979,762,510,824,375,702,681,694,212,420,939,923,405,588,401,118,174,403,385,819,300,280,760,583,56,153,635,762,28,696,962,389,630,371,253,429,290,604,45,584,223,906,73,211,431,873,31,690,520,31,53,474,617,355,195,179,833,196,27,190,120,834,525,765,334,599,101,678,683,89,33,420,824,408,850,333,293,938,104,361,515,343,645,214,9,84,409,304,46,874,67,389,920,781,454,996,414,195,550,162,47,473,72,852,990,614,888,220,255,989,665,138,157,220,70,592,254,167,165,284,595,348,994,937,998,743,395,199,698,34,517,344,182,640,61,259,826,721,91,453,230,450,447,737,87,1000,905,19,552,8,752,352,163,890,861,860,984,615,629,156,684,323,544,694,1000,670,965,110,913,133,610,246,410,119,462,13,716,369,609,194,202,910,182,786,548,462,756,19,497,711,341,923,59,925,221,870,701,526,763,224,43,485,100,688,635,500,414,913,365,467,911,12,660,968,57,617,572,427,382,61,407,160,268,821,304,763,507,372,876,913,188,507,211,406,932,470,444,776,290,649,773,979,730,312,454,49,384,284,269,160,234,687,408,594,183,343,422,572,835,840,84,465,920,64,966,289,492,470,870,835,765,625,698,856,440,185,795,519,62,119,9,265,592,489,364,199,604,441,576,424,468,736,757,218,801,271,295,98,574,180,394,272,147,176,719,391,458,330,900,802,927,388,634,927,535,138,465,785,698,985,400,956,940,129,99,99,405,18,638,265,374,354,154,187,349,547,927,596,405,119,939,221,861,4,464,839,78,439,772,623,326,25,7,296,202,238,910,451,884,266,79,992,319,99,530,583,115,156,106,290,912,101,370,178,295,469,619,606,503,995,392,716,782,675,165,669,499,966,360,101,381,403,6,444,553,655,404,726,135,7,689,17,806,270,749,469,578,593,292,536,874,463,825,735,227,277,335,335,113,678,667,486,560,308,12,494,264,26,588,987,598,424,355,974,514,673,652,682,683,243,680,889,62,611,127,518,827,681,530,8,70,419,411,791,955,35,82,787,41,274,602,451,817,591,49,92,908,969,661,299,478,296,248,805,156,673,624,863,906,192,766,561,805,365,554,983,474,502,296,880,237,621,813,392,414,964,332,70,918,103,373,355,135,995,475,566,874,318,993,67,869,480,814,647,553,935,924,599,777,445,839,586,780,628,749,483,351,355,34,710,441,90,406,200,710,49,719,210,674,130,640,901,289,782,551,352,137,988,989,805,626,691,819,48,717,976,54,312,869,114,693,975,997,386,702,160,4,967,503,226,272,397,840,453,817,929,66,904,378,67,226,958,605,946,67,462,836,641,582,730,886,453,0,30,645,452,144,695,182,368,42,13,572,393,742,284,837,146,206,308,329,60,355,815,512,718,790,852,130,386,492,795,73,361,619,949,448,422,133,593,322,161,265,580,571,965,882,490,829,731,966,439,725,371,327,486,803,153,919,991,502,438,656,75,929,4,253,718,103,624,810,7,802,343,289,961,285,560,79,959,543,758,181,385,132,797,225,53,51,976,593,791,525,342,283,633,553,898,833,749,194,149,401,131,935,744,150,474,447,53,525,439,112,820,121,815,553,50,698,492,736,499,440,391,243,851,779,712,447,516,924,865,630,350,375,959,641,454,56,228,356,190,45,242,874,672,296,940,170,926,713,116,630,92,866,885,122,883,655,150,810,795,378,988,40,92,995,189,478,408,508,497,677,571,303,866,687,219,527,951,475,915,125,242,909,112,992,604,613,571,901,922,396,150,542,406,844,40,87,246,586,854,407,561,200,853,207,665,468,219,321,730,652,909,921,28,144,522,86,931,756,714,449,484,823,496,974,122,986,753,545,41,725,425,427,143,216,366,661,981,347,431,972,165,106,790,914,783,72,889,705,413,493,922,142,845,950,297,65,685,55,80,337,489,90,129,647,676,942,590,977,290,637,925,769,164,205,414,643,634,737,306,331,558,786,64,444,325,63,514,114,809,668,90,343,589,666,564,941,865,948,889,153,742,965,535,1000,822,344,217,630,271,131,653,345,519,339,286,237,871,442,395,212,34,961,830,821,963,667,569,602,103,885,36,460,197,347,992,489,430,701,9,955,492,61,177,896,665,907,441,708,967,617,962,377,955,669,790,579,169,397,365,314,291,383,471,942,547,47,307,778,594,760,47,681,517,652,485,927,445,852,934,303,545,467,996,128,708,515,557,767,843,807,928,275,724,109,255,119,159,474,185,853,292", +"557,13,253,166,806,373,486,361,86,523,52,264,855,912,820,553,80,568,87,71,356,203,529,470,680,167,205,819,860,802,829,420,617,312,540,405,254,980,469,319,865,34,424,359,714,174,21,908,510,56,661,839,115,964,688,340,836,801,187,200,363,669,542,537,517,827,576,526,145,447,396,81,270,452,776,838,67,358,62,822,739,770,317,818,336,427,990,879,914,653,90,728,993,130,709,848,270,38,357,232,320,518,798,483,652,33,898,181,540,256,707,758,454,952,467,252,529,512,741,996,612,339,212,619,485,10,998,978,484,842,238,312,712,830,804,953,357,469,345,956,438,628,83,35,651,56,981,90,775,185,441,290,886,150,362,880,768,34,509,377,91,892,66,246,947,387,933,675,466,114,979,863,240,876,119,711,381,678,339,798,773,32,28,951,146,286,467,230,22,931,791,960,221,842,511,168,581,534,497,256,536,441,80,57,160,911,361,992,624,176,333,603,924,48,526,352,549,228,154,213,342,981,31,84,846,406,3,457,971,833,84,572,885,835,893,16,870,180,675,885,777,502,872,497,280,308,428,752,145,433,862,818,149,216,438,693,389,194,227,659,800,452,873,175,656,814,481,911,863,601,579,698,140,957,316,274,917,304,204,710,637,762,843,309,93,15,382,52,339,779,724,443,38,577,258,178,323,862,95,638,258,412,924,955,677,690,395,392,66,32,636,161,159,234,602,80,386,649,894,788,328,611,65,683,330,613,524,571,458,350,423,736,977,890,390,513,312,31,91,8,548,372,81,755,129,631,651,489,987,362,616,105,13,549,97,398,477,827,976,762,889,410,526,408,534,143,724,251,271,895,858,20,749,857,531,246,288,522,72,346,394,586,660,146,200,37,309,387,787,39,53,933,276,101,438,664,672,448,599,131,661,692,41,481,761,552,251,125,89,85,589,591,136,138,364,824,42,718,655,61,624,998,980,956,313,277,596,122,629,538,953,769,902,937,146,236,841,433,359,708,76,895,179,293,881,155,913,143,952,141,729,177,893,417,764,534,340,173,638,681,819,767,677,674,396,186,611,665,453,985,638,348,973,525,252,163,537,373,752,210,584,524,820,429,75,810,917,141,155,292,993,125,706,334,447,604,673,96,569,337,42,650,524,826,384,862,129,678,851,702,536,359,66,181,225,922,916,413,620,465,700,944,368,134,903,262,422,799,33,697,658,80,672,329,626,722,328,110,62,875,74,246,992,531,45,989,380,254,779,633,130,943,390,999,524,251,56,902,424,464,850,920,176,938,896,524,24,272,762,866,943,995,622,772,125,752,319,986,686,402,632,420,782,905,511,788,750,510,455,615,769,186,260,722,595,353,754,687,30,0,790,62,966,786,136,278,343,629,778,861,844,915,460,459,844,929,925,341,655,977,110,639,724,665,761,342,41,496,111,739,990,747,682,670,308,749,385,828,368,208,796,983,859,340,533,900,718,235,132,219,753,555,50,560,663,129,125,611,959,258,230,571,692,291,654,140,7,733,173,934,252,814,815,857,999,446,112,161,228,640,340,916,119,371,708,70,956,568,322,614,813,913,204,530,585,684,679,792,825,401,525,209,606,7,735,302,454,75,453,330,669,896,109,261,409,883,260,678,298,243,379,333,532,291,520,565,512,562,393,678,973,719,517,391,596,990,478,323,738,904,280,141,748,571,881,747,204,969,886,805,937,685,522,9,687,949,191,1000,785,430,718,820,994,44,344,267,381,455,910,735,791,233,673,553,914,877,865,616,867,331,487,177,933,479,662,877,61,347,318,17,105,794,411,38,230,469,390,313,468,8,260,98,392,684,393,17,369,34,493,627,383,553,859,116,371,280,690,528,149,93,495,686,899,99,281,966,785,121,742,776,217,783,281,5,467,10,620,21,388,76,518,983,134,426,842,899,531,856,775,881,268,37,643,826,199,25,476,666,870,695,929,686,921,812,851,934,599,559,230,99,294,971,29,864,947,828,747,304,177,95,63,693,508,539,940,572,824,666,462,361,229,107,247,405,235,632,151,470,790,67,826,382,571,359,232,514,177,558,483,837,380,407,87,817,165,717,611,819,54,3,909,903,248,869,859,292,821,852,307,481,36,405,632,597,796,22,485,488,799,597,5,919,536,296,286,665,877,656,975,611,88,484,604,596,4,25,630,104,410,432,861,659,62,232,739,451,650,701,108,554,317,242,428,71,207,99,469,957,800,76,919,652,468,764,398,646,382,198,959,17,176,476,237,550,798,179,766,843,331,300", +"602,931,563,439,885,648,159,102,936,462,19,995,506,179,530,219,64,946,5,402,546,364,855,250,128,894,729,927,264,290,957,203,274,233,812,359,846,84,404,348,877,661,700,699,563,802,652,151,378,966,854,321,510,928,275,918,172,902,453,462,900,268,467,295,375,224,791,238,955,267,946,514,425,591,528,581,856,877,418,359,570,623,413,46,930,991,589,558,939,931,827,304,281,413,441,81,220,118,681,801,939,643,288,51,517,269,965,56,372,861,329,156,588,227,993,700,755,274,335,74,645,787,470,44,269,602,496,944,554,629,822,981,116,474,966,80,925,264,723,403,717,644,880,606,29,727,561,491,572,340,570,747,912,366,502,943,977,384,917,923,551,715,407,20,54,817,427,37,76,241,604,55,634,15,584,174,699,309,943,457,179,700,565,585,462,604,121,182,198,862,674,69,915,948,197,766,84,649,112,850,399,506,70,110,650,774,638,792,260,186,693,920,377,476,511,432,820,613,791,16,427,818,106,239,339,566,70,861,232,2,203,89,83,302,162,939,549,243,323,134,770,659,9,235,313,676,245,708,162,965,854,524,572,981,55,196,686,203,831,657,870,147,172,971,187,234,570,302,383,848,825,776,678,912,452,337,766,618,306,572,825,335,829,133,542,226,802,647,559,283,405,165,615,48,508,851,885,570,177,493,872,205,574,514,523,395,150,272,799,800,503,132,678,715,500,850,999,741,268,90,19,147,321,754,715,630,676,269,223,658,711,594,974,671,855,851,856,419,677,587,319,110,21,197,19,69,577,262,196,349,867,208,768,347,911,640,147,616,73,513,429,18,640,443,504,145,559,126,123,162,730,80,913,510,222,162,401,735,726,510,20,168,597,3,743,507,621,526,844,392,856,285,747,981,718,330,666,316,859,681,159,225,63,917,928,799,107,821,477,111,21,805,357,457,840,697,167,403,89,825,332,744,221,927,767,4,257,423,722,428,36,400,590,272,274,678,4,734,57,668,47,908,151,343,338,524,997,409,356,789,104,72,191,186,171,290,93,751,344,682,54,882,759,449,164,225,746,906,286,81,766,419,786,270,63,998,963,238,768,634,630,298,494,606,605,470,70,544,230,381,529,726,473,568,852,349,907,792,103,487,763,178,949,933,768,745,612,294,56,334,788,929,18,177,708,769,92,14,255,301,435,369,185,44,758,587,621,717,839,783,865,71,893,696,143,934,941,49,617,779,810,147,779,95,634,880,738,292,16,122,31,775,749,734,909,846,971,891,483,841,83,171,70,446,622,124,566,175,553,278,471,433,36,811,248,154,846,223,628,817,436,776,591,200,883,978,978,361,544,882,716,247,435,567,472,861,210,537,645,790,0,205,811,100,263,280,835,547,744,438,336,410,467,534,908,662,974,824,524,691,758,697,303,276,545,193,707,37,732,51,976,251,150,745,859,764,918,396,394,426,502,342,143,796,408,738,275,288,397,733,579,339,457,483,397,253,75,735,147,960,808,31,94,464,421,754,300,590,536,788,764,786,842,671,543,459,139,816,906,214,503,872,826,249,703,342,100,427,439,24,792,683,81,131,261,525,707,215,247,468,516,219,108,13,979,886,387,563,81,850,317,666,899,693,205,450,488,463,322,759,599,230,994,196,495,724,377,992,492,450,489,623,45,324,987,331,721,716,232,859,237,172,838,77,975,61,960,82,795,402,225,857,609,153,739,589,473,83,242,442,27,461,779,609,156,793,118,277,410,935,483,985,970,646,653,282,20,107,43,497,476,10,870,354,157,435,69,146,426,101,791,478,383,460,146,408,880,168,834,343,248,986,421,574,719,420,998,944,956,49,588,282,468,946,787,391,218,86,306,248,168,895,968,776,582,398,444,798,36,771,489,767,930,575,228,143,731,992,678,1000,380,14,901,286,103,577,690,420,771,754,202,865,602,996,61,355,152,929,227,555,535,925,397,242,13,715,901,115,102,138,940,388,997,552,586,923,36,929,491,785,974,607,131,92,990,650,664,919,887,187,856,480,705,856,629,619,973,526,455,813,867,530,993,517,7,465,743,484,111,384,765,858,890,953,307,725,396,605,533,919,153,54,727,63,731,290,134,851,474,82,896,453,553,224,265,311,193,660,313,323,906,529,821,470,127,949,318,308,743,441,322,631,124,437,537,425,18,128,508,391,812,545,96,264,431,684,81,747,60,929,772,938,385,11,387,34,89,109,630,674,692,611,176,169,646,910,633,630,603,844,658,581,177,411,801,163,266,150,53,637", +"206,804,736,746,332,206,89,840,575,792,495,898,410,624,428,722,193,776,888,836,127,424,990,869,34,215,341,343,889,49,678,192,742,777,589,871,92,799,240,421,898,756,116,603,664,543,174,19,917,319,961,619,802,824,588,415,376,233,484,947,235,479,278,641,461,273,392,568,43,203,798,920,710,174,349,512,558,513,352,471,873,951,658,321,925,583,22,989,562,520,388,230,747,400,843,338,475,776,199,991,281,498,965,886,141,473,310,996,105,555,249,600,556,518,461,590,623,807,959,283,585,526,28,676,114,820,275,718,12,826,943,642,572,446,948,300,700,310,856,656,897,57,70,103,21,87,157,438,616,152,78,921,881,222,487,246,56,705,539,823,5,159,754,423,56,708,845,917,364,243,227,812,422,682,887,423,592,357,365,867,755,521,363,61,788,150,316,928,292,51,199,22,392,904,544,823,266,135,397,721,416,777,618,940,598,73,142,778,317,565,85,445,979,233,843,266,846,332,817,399,306,505,287,481,787,543,647,592,67,66,936,15,282,909,176,38,253,45,631,707,700,21,392,776,882,200,91,392,807,792,997,55,4,944,653,491,628,411,451,458,10,391,420,894,595,915,335,32,577,280,257,66,722,39,221,856,318,13,370,717,477,575,189,687,50,148,631,545,748,321,814,778,61,647,741,417,571,865,691,556,381,393,317,617,672,256,517,821,646,45,701,520,598,456,911,941,515,281,269,602,334,138,90,716,962,418,718,82,530,442,754,512,680,665,666,125,378,21,596,348,97,772,350,391,326,708,634,122,899,277,425,293,885,227,149,155,126,685,573,746,235,772,659,703,573,883,534,190,964,274,29,634,480,137,639,799,748,35,278,460,672,773,603,731,51,389,199,685,949,188,26,603,4,944,828,271,454,715,424,558,504,742,208,785,970,611,313,169,175,837,767,52,776,359,201,754,145,704,496,242,252,212,548,145,524,401,234,912,995,186,100,596,178,905,604,956,20,738,398,419,90,424,932,593,242,807,283,269,690,88,968,851,36,966,744,909,34,167,355,879,640,370,147,721,202,124,224,376,505,569,148,593,621,582,810,405,596,493,448,198,401,132,460,171,754,581,893,964,54,931,917,184,678,597,914,788,865,151,379,692,547,73,416,426,722,408,751,904,596,596,982,515,64,587,381,718,196,829,26,283,460,249,243,828,567,240,434,435,127,419,556,772,397,241,8,17,310,98,405,978,829,145,980,852,660,984,523,755,86,515,533,193,491,134,242,886,44,434,506,563,808,125,584,778,349,374,148,964,531,265,878,891,124,314,674,773,163,274,808,13,22,780,495,273,816,193,864,60,459,542,464,131,466,373,837,206,560,577,452,62,205,0,441,217,98,295,178,986,709,755,837,736,521,888,313,912,367,672,261,366,237,513,918,466,376,103,856,116,974,676,690,617,948,527,853,341,877,444,231,572,414,457,308,287,394,943,943,70,811,449,654,990,779,119,327,195,362,247,881,866,452,576,360,778,306,413,22,23,753,758,3,501,609,346,984,413,635,58,389,688,216,414,713,796,996,117,510,975,442,646,792,485,297,49,43,990,519,637,66,253,207,502,366,918,464,600,979,245,599,845,567,775,375,128,340,54,475,105,34,405,526,392,456,568,400,328,735,673,522,110,275,142,411,604,594,26,940,188,517,993,942,40,853,134,856,147,120,6,631,469,515,616,831,103,138,138,771,166,84,243,912,140,266,927,139,621,28,868,454,186,499,784,909,82,454,879,771,701,260,814,595,857,717,970,727,710,689,136,808,255,400,825,144,232,302,209,369,417,571,707,898,836,244,675,582,804,909,283,914,407,510,62,170,705,117,948,891,544,643,814,733,56,3,492,664,798,129,662,602,124,487,617,857,271,773,50,859,346,415,77,626,406,818,725,174,737,302,95,721,16,432,974,306,744,268,745,950,287,695,218,919,16,543,526,330,148,892,991,217,215,210,734,666,604,380,186,692,68,789,569,991,725,253,829,882,595,173,333,537,918,11,406,128,336,18,505,272,210,37,161,419,822,470,171,223,362,361,451,975,759,626,235,825,190,657,359,125,757,625,738,450,811,208,50,283,255,454,398,374,520,233,660,732,9,792,140,470,145,312,28,649,668,928,499,700,596,108,149,805,481,535,97,427,270,425,624,937,84,879,879,628,596,360,453,870,971,826,428,976,602,11,44,773,648,616,674,654,943,471,898,741,656,382,199,871,820,280,445,185,625,939,184,973,922,309,286,642,909,151,299", +"759,158,880,837,663,249,91,516,882,39,503,149,781,802,632,125,554,602,630,374,483,151,665,161,806,527,663,172,384,558,76,820,306,858,532,853,542,406,844,398,162,890,410,991,277,178,69,480,67,35,639,294,761,262,223,381,808,145,838,678,549,230,231,425,527,897,81,629,783,404,667,708,826,890,622,941,30,219,669,950,302,677,273,574,571,831,318,263,700,222,567,995,713,836,565,245,495,442,821,992,954,73,987,642,850,309,918,792,286,299,54,765,346,183,23,746,824,470,126,78,270,854,73,202,751,894,802,599,821,151,602,676,127,598,341,847,58,339,479,413,985,110,828,62,801,622,343,260,301,913,592,59,87,918,242,739,845,478,448,616,829,655,345,282,785,804,619,462,23,321,547,317,320,428,321,861,681,74,938,672,997,421,712,852,591,400,333,636,841,46,515,443,658,345,766,510,417,770,415,164,366,113,633,922,919,609,910,152,493,448,566,136,618,623,933,541,53,170,86,204,379,768,869,527,356,281,194,11,773,446,869,491,197,886,867,18,260,52,880,209,118,141,374,233,579,707,928,102,104,95,184,381,853,944,702,751,680,529,622,217,71,960,65,506,899,702,751,800,730,653,603,807,343,359,126,118,326,157,158,114,691,551,180,502,305,63,70,227,243,520,362,45,113,754,796,403,892,425,904,542,982,927,281,122,857,436,823,316,20,998,561,263,597,961,723,28,513,194,122,48,795,740,799,229,285,375,636,561,654,941,760,962,851,655,306,457,753,890,963,228,123,31,761,676,920,101,951,372,85,704,56,647,382,964,54,633,861,238,657,484,323,681,221,330,447,166,534,861,276,794,99,65,277,196,897,580,448,276,153,665,402,211,513,798,878,71,647,609,390,268,347,457,390,593,129,381,255,945,814,920,950,107,754,855,537,41,632,531,311,182,354,160,272,261,402,859,975,102,623,45,396,173,895,480,997,54,269,284,102,513,705,566,680,910,819,204,383,913,799,151,622,442,390,384,160,342,154,935,757,808,8,980,423,511,441,430,655,787,910,344,763,526,69,703,476,247,28,559,667,484,302,128,512,554,639,932,521,797,610,262,601,510,764,863,320,389,516,608,525,585,167,322,691,773,468,843,361,414,231,224,873,114,150,670,652,865,255,916,464,678,422,341,586,684,679,861,641,439,480,969,914,818,428,482,501,239,876,874,638,357,335,264,28,37,790,387,253,275,40,579,904,118,332,560,618,622,383,656,229,857,527,20,6,545,984,851,729,609,158,248,444,457,636,425,883,92,425,416,268,493,956,443,648,636,596,162,447,769,340,989,960,735,681,745,922,875,424,965,115,347,878,410,51,745,427,604,909,723,144,966,811,441,0,630,155,683,288,86,30,888,515,160,790,400,701,45,872,594,360,148,72,92,363,988,708,591,136,814,53,926,295,640,730,634,607,374,790,818,434,151,622,122,182,933,812,538,793,203,735,981,368,252,870,326,83,100,741,669,561,788,326,492,958,547,27,356,366,41,633,766,556,835,252,526,452,465,606,169,732,52,584,480,88,883,814,243,636,164,345,598,549,242,46,7,616,304,944,25,178,758,62,674,289,459,377,155,414,555,882,90,225,622,433,849,927,263,219,491,229,287,17,979,365,78,666,896,443,525,513,752,731,498,134,22,628,710,575,372,758,890,71,772,654,424,560,113,920,90,175,772,564,679,771,374,600,431,393,5,77,982,233,574,782,193,182,71,208,488,100,252,881,837,69,913,893,439,511,207,61,610,231,678,989,583,342,58,1000,506,745,638,764,636,631,454,860,682,344,432,51,649,958,354,550,812,493,722,189,906,273,154,503,694,562,331,683,104,646,386,419,102,744,774,732,964,950,184,38,691,583,143,61,765,843,577,628,477,443,418,909,189,262,858,228,164,994,275,540,689,159,22,967,771,838,307,210,912,185,315,280,434,378,914,840,949,46,884,377,535,271,881,773,183,854,556,338,452,353,861,214,483,841,745,572,770,166,198,889,829,888,44,271,135,603,590,537,244,643,919,34,657,534,694,856,630,645,276,511,897,723,797,50,456,589,233,129,454,777,178,356,775,88,292,256,491,487,438,725,999,684,411,176,874,424,354,626,85,251,277,121,749,340,350,856,714,38,43,554,239,322,401,737,77,462,534,386,360,406,462,986,530,257,292,249,986,907,126,848,335,309,667,414,129,213,902,969,49,496,43,563,793,901,26,52,793,80,499,37,654,156,857,330,972,860,570,100,606,171,415,23,87", +"638,451,519,697,999,417,168,904,18,937,458,493,464,145,408,239,572,832,135,416,55,709,746,989,148,374,368,191,675,232,648,505,242,434,540,994,600,183,308,13,886,90,162,841,429,778,770,807,257,463,471,462,36,3,311,315,187,109,822,954,524,24,544,570,562,862,640,701,844,468,797,157,627,845,402,17,297,783,971,746,726,887,876,143,518,993,199,105,273,554,490,549,531,248,394,692,515,699,528,491,854,287,124,108,228,559,681,395,276,437,298,777,540,965,957,625,834,52,697,697,255,836,356,484,2,921,756,779,651,642,500,457,384,687,426,452,790,997,872,523,687,476,905,746,726,928,929,959,223,390,840,555,133,543,930,665,187,600,324,342,114,63,750,130,655,780,822,76,895,958,240,626,822,961,15,635,37,72,500,380,187,161,95,707,224,44,854,716,712,330,928,585,613,459,758,111,617,872,481,633,23,192,839,259,724,191,959,884,552,566,14,51,178,619,197,156,300,43,743,460,617,791,476,491,931,791,9,499,951,816,209,773,239,926,102,789,132,247,519,607,648,715,652,748,186,533,452,572,466,80,206,557,697,20,8,53,949,508,359,545,542,587,143,76,848,599,768,801,139,267,890,632,554,533,575,718,822,584,70,969,508,384,583,686,801,358,33,607,573,899,623,345,226,215,553,777,53,913,485,100,892,336,717,325,148,428,548,932,800,27,631,408,347,549,24,664,649,88,244,538,422,440,81,439,249,300,497,106,337,576,556,984,599,529,946,367,431,447,33,76,185,249,185,998,653,30,834,526,658,337,532,519,549,991,500,405,678,577,84,111,953,577,94,420,183,667,928,502,884,841,388,885,313,692,748,62,971,508,97,419,53,676,442,94,892,985,800,926,64,750,81,670,222,305,221,298,440,236,862,184,321,63,335,373,400,655,986,293,973,941,7,828,439,724,991,724,317,468,925,686,372,490,617,333,637,143,913,669,957,820,528,954,343,478,685,384,398,925,801,994,342,642,966,829,384,534,996,878,295,389,289,716,839,347,256,978,693,622,821,500,119,186,29,837,885,112,434,904,303,930,649,449,935,312,758,79,694,86,413,856,916,141,807,99,981,798,77,490,116,605,414,491,588,342,576,315,795,570,146,616,416,232,308,525,886,156,521,889,912,366,369,649,106,131,800,452,489,341,775,724,252,154,982,612,210,68,798,254,402,886,896,347,76,849,847,78,17,856,192,325,376,369,218,94,295,137,987,931,664,878,209,960,691,382,912,573,174,78,324,47,616,361,530,481,217,534,314,599,191,585,576,963,548,922,436,59,8,866,694,398,482,103,389,866,847,852,675,360,696,549,27,799,866,952,742,257,422,421,695,786,100,217,630,0,535,124,768,716,821,265,904,921,5,520,843,911,43,150,919,868,66,990,11,52,343,906,600,758,512,982,875,164,536,151,368,984,980,395,714,625,847,717,58,245,980,270,159,140,432,676,677,543,5,973,334,759,398,399,396,513,587,366,657,34,987,409,650,243,308,272,470,640,548,160,743,743,532,317,216,717,495,690,309,771,255,316,440,398,308,97,891,368,742,192,534,627,889,447,46,151,75,492,434,567,865,963,133,280,669,64,113,359,511,661,370,695,888,25,200,152,536,537,92,383,305,240,2,262,188,998,158,990,25,595,630,31,429,134,243,216,207,588,178,248,922,665,806,622,134,676,952,272,440,568,940,555,888,212,934,553,18,147,941,76,806,687,744,784,644,20,625,296,554,369,729,854,942,809,556,373,764,184,919,400,171,444,621,368,30,362,478,519,90,81,240,880,867,35,623,522,444,74,844,79,75,525,627,289,868,206,737,762,778,944,673,817,874,430,482,250,419,954,797,214,83,398,48,80,885,73,541,211,564,340,806,180,789,618,395,127,489,107,762,55,358,610,870,180,522,117,228,19,760,544,956,807,172,745,669,152,761,162,797,974,104,852,889,998,468,751,45,347,997,748,381,764,164,51,641,601,610,511,436,223,922,256,428,716,488,754,377,811,772,104,811,247,888,938,689,670,875,81,436,694,455,990,915,37,771,720,210,406,242,921,167,89,177,42,325,627,196,816,619,239,881,863,758,516,102,846,507,136,658,15,301,418,341,805,830,859,248,164,653,960,533,670,715,970,57,338,928,867,610,107,705,218,321,791,612,238,708,634,173,867,306,506,636,720,4,58,618,179,909,216,569,949,401,706,328,69,428,439,893,575,604,198,458,179,741,581,24,952,70,224,244,440,132,342,392,517", +"977,768,76,444,915,712,178,344,572,991,400,454,463,808,16,953,690,73,813,332,898,888,629,597,243,337,606,881,286,260,627,792,319,337,914,737,95,297,522,235,214,540,42,613,89,811,119,142,733,489,837,97,942,862,307,378,910,229,112,833,259,700,536,677,50,769,90,274,928,327,754,546,12,316,719,290,87,495,49,484,400,346,777,268,335,84,816,189,124,39,559,613,277,462,197,147,640,856,917,547,456,709,912,869,446,940,670,470,169,69,754,312,350,557,859,308,633,469,873,116,769,11,533,751,625,947,213,334,569,940,821,443,636,972,542,403,175,379,283,653,725,841,348,241,400,179,551,483,764,75,600,339,288,958,388,431,452,382,964,266,405,480,508,819,463,547,859,2,104,16,998,174,882,572,54,859,655,555,194,757,962,817,647,355,909,983,597,219,213,431,455,900,609,895,429,701,273,775,825,5,238,798,952,743,927,457,744,939,814,725,912,924,852,10,871,167,323,736,904,422,692,615,964,497,487,529,278,907,72,905,654,969,625,771,449,947,976,879,249,207,102,457,866,55,815,709,276,566,803,532,763,752,199,820,334,969,78,352,93,648,211,652,766,733,712,642,902,690,224,339,610,657,168,530,986,133,360,958,333,550,982,218,993,213,558,13,939,915,645,297,57,766,500,246,410,895,485,668,704,41,128,220,336,104,109,925,264,417,50,294,327,805,606,750,99,939,345,108,327,800,894,725,686,815,222,586,571,263,924,3,817,147,884,784,123,45,703,771,61,641,314,218,288,735,6,423,35,682,106,924,964,886,608,858,456,213,856,784,516,949,476,251,642,860,852,300,913,488,285,276,92,999,812,516,189,521,74,674,348,110,762,285,121,456,112,254,996,371,894,107,111,865,533,871,623,702,96,331,29,621,193,154,785,108,667,133,198,881,168,136,523,266,860,391,659,470,83,735,639,822,704,349,464,635,801,404,303,806,226,380,532,59,565,141,556,403,486,137,819,438,137,199,599,841,416,710,134,485,840,780,248,32,421,198,409,208,764,94,919,921,878,156,736,488,922,260,525,277,153,310,130,700,527,53,690,419,489,888,241,571,401,856,980,286,889,355,46,861,507,342,603,57,768,624,983,759,28,723,29,348,216,187,271,409,551,951,132,128,509,109,400,250,546,159,206,810,141,570,778,742,76,191,362,971,781,794,649,967,26,537,871,191,805,111,267,499,500,649,756,764,831,818,783,918,108,182,179,192,522,56,79,514,893,224,994,264,404,865,475,459,119,833,152,92,606,242,775,824,166,851,399,898,407,396,607,253,988,178,654,920,977,264,59,969,992,479,724,660,20,801,502,226,814,593,788,902,525,675,182,136,263,98,155,535,0,17,367,146,452,937,273,892,300,992,453,591,403,712,799,521,455,753,304,835,986,569,943,358,497,409,96,737,443,993,928,489,268,530,521,103,703,182,364,343,158,291,525,207,385,20,570,670,384,571,177,298,907,803,385,145,389,111,993,517,948,108,310,791,905,12,363,581,735,626,210,346,971,585,106,626,44,37,77,528,539,802,776,370,16,844,616,685,325,623,388,455,236,595,82,199,303,72,925,526,519,380,79,360,689,512,608,300,783,128,605,797,627,349,369,887,392,630,645,132,779,729,588,705,239,539,710,331,470,930,269,893,172,834,28,482,651,954,722,640,490,99,243,560,850,582,618,815,720,686,202,670,159,654,648,445,512,468,561,65,932,683,354,146,932,44,327,33,415,787,266,509,231,42,446,140,915,441,953,504,531,919,232,210,371,496,298,99,563,134,14,309,115,89,801,444,772,931,362,890,239,355,494,452,43,497,627,501,905,767,30,692,92,71,826,96,901,699,176,407,611,289,224,761,327,577,677,48,195,179,87,200,992,879,705,681,119,143,566,474,436,600,215,187,484,911,773,781,265,608,750,77,968,271,365,576,109,872,312,711,283,45,145,125,235,165,757,731,785,608,906,733,762,137,948,768,670,153,488,586,148,988,871,836,444,928,582,515,969,785,407,745,709,248,49,987,545,10,700,516,942,102,125,774,833,849,25,430,646,525,91,178,589,733,955,87,981,366,8,289,773,728,829,940,863,35,245,906,932,38,530,161,119,670,669,477,639,869,471,638,941,516,325,716,180,78,752,724,592,929,305,573,960,413,925,459,45,903,815,123,565,447,561,853,656,780,504,401,291,76,160,260,471,500,25,838,240,339,344,401,191,737,446,259,935,505,189,190,437,636,716,81,196,33,519,677", +"499,954,3,208,174,517,429,158,901,103,841,50,979,991,826,777,417,659,389,741,529,267,843,583,714,283,572,68,282,962,82,698,474,34,260,650,463,444,408,330,966,922,622,415,322,925,642,825,359,3,991,296,40,528,3,234,804,607,75,605,835,426,746,194,783,772,722,373,201,509,596,841,332,639,425,220,419,440,378,784,490,493,37,646,227,70,91,752,269,357,481,324,169,818,929,993,400,146,393,660,200,935,555,308,407,658,212,22,787,893,529,926,626,772,697,934,362,651,622,533,870,621,331,10,495,510,375,330,288,479,493,95,275,864,903,159,466,823,443,872,22,25,995,127,27,260,869,107,253,165,616,974,479,492,406,934,32,430,225,852,904,246,90,655,391,287,147,454,106,126,330,382,783,901,342,757,84,559,484,941,725,869,199,601,37,860,165,836,884,276,266,770,885,102,295,654,572,98,210,770,665,641,703,926,525,127,459,821,787,833,712,635,798,122,730,243,48,329,44,581,438,856,591,829,453,634,923,298,979,97,302,691,173,514,507,982,404,805,579,88,294,318,86,63,361,573,758,888,712,329,545,589,296,421,602,330,678,689,92,390,829,227,31,151,547,113,712,993,651,952,549,914,121,461,99,481,492,806,810,308,412,873,699,717,57,858,268,384,739,292,694,349,186,93,629,254,983,523,823,471,929,122,991,259,797,29,96,700,507,326,445,86,732,513,64,103,792,44,351,577,997,122,944,740,279,246,165,370,943,718,858,34,320,773,749,613,757,535,552,60,151,940,152,792,115,108,577,842,964,773,707,774,332,915,759,129,373,517,261,196,268,404,494,60,285,623,404,227,701,390,544,279,154,751,685,169,363,478,665,673,366,6,701,78,166,396,772,262,460,89,265,549,629,992,852,54,912,860,8,436,769,708,878,751,179,509,941,371,142,568,317,310,160,428,695,765,620,614,726,938,834,858,102,666,366,849,118,718,874,917,276,915,996,109,522,754,592,260,366,581,58,907,9,575,108,706,194,983,821,224,289,314,971,882,396,282,745,294,675,770,96,870,149,381,308,770,890,135,936,295,273,247,607,146,48,357,32,688,993,429,608,463,557,226,34,664,756,750,444,91,585,306,84,165,238,464,389,630,489,741,953,220,568,583,763,496,455,682,759,433,830,495,730,30,99,296,157,736,501,99,174,660,537,883,378,451,50,39,316,296,735,303,484,403,813,44,482,587,902,312,716,755,681,202,660,916,673,13,129,462,310,723,132,772,174,303,336,589,655,602,792,517,359,174,689,80,606,206,572,946,984,373,555,982,39,484,495,518,90,708,53,475,388,137,338,727,910,501,135,455,254,371,726,768,381,19,306,87,368,278,280,295,683,124,17,0,563,968,437,128,311,322,374,616,321,791,925,926,126,332,86,805,778,813,135,494,174,53,236,753,758,54,809,879,890,258,58,174,17,170,502,624,169,116,230,793,402,24,580,30,57,130,951,310,901,781,490,514,959,529,831,850,684,882,413,940,488,963,239,328,709,624,677,180,777,400,911,383,62,315,368,614,945,538,143,331,996,20,603,570,191,32,318,502,980,124,572,879,289,382,880,950,441,435,228,697,194,276,898,470,500,122,505,191,7,863,947,686,460,508,305,181,161,179,863,50,186,617,690,816,592,784,649,544,353,841,565,169,716,75,964,431,838,763,798,226,161,71,405,443,720,306,620,358,976,455,119,105,228,497,702,219,692,209,365,758,491,216,634,51,143,388,757,667,40,918,152,383,343,632,513,298,134,217,111,973,914,53,307,978,51,27,687,855,659,607,399,438,936,650,580,443,861,453,740,666,873,465,348,887,672,27,904,236,116,693,419,899,143,940,114,945,102,600,684,695,346,626,23,670,954,728,160,673,410,639,295,981,295,318,11,783,623,173,935,571,288,423,533,471,478,775,540,140,832,648,126,668,143,961,607,180,53,306,464,793,363,880,66,888,329,231,813,489,125,100,851,357,919,743,441,809,568,833,886,909,77,946,988,856,909,767,899,135,955,901,228,121,852,435,413,80,489,544,620,648,629,453,912,235,397,697,963,83,676,884,727,407,400,213,547,190,386,909,719,421,859,635,52,273,957,282,62,651,727,610,125,101,245,701,482,723,611,61,143,477,533,135,333,688,999,153,433,346,113,69,152,407,655,996,415,736,388,436,730,103,877,854,518,584,656,107,496,135,928,39,243,351,102,87,913,889,864,476,908,133,896,693,70,224,154,56,672,774,365,933,155,23,825,498", +"723,695,624,346,549,492,621,27,252,134,679,697,729,427,788,569,762,425,990,797,166,429,279,30,788,539,807,578,783,195,654,548,404,635,21,431,516,380,371,402,641,132,557,671,207,457,467,71,110,227,289,121,427,135,261,97,544,852,786,531,961,887,258,658,792,198,9,818,794,951,320,805,199,811,806,558,687,679,554,499,918,735,957,243,178,235,591,190,2,704,280,346,137,491,455,533,931,558,206,132,506,308,237,777,936,830,590,533,584,970,44,984,225,773,613,689,431,674,153,142,520,405,785,508,725,948,437,272,262,912,245,107,369,889,551,908,762,536,183,977,483,44,324,157,39,805,375,792,986,315,269,739,972,899,399,188,546,441,961,422,561,174,839,684,696,137,328,476,719,450,617,249,133,894,482,667,387,25,65,373,488,496,866,752,482,454,473,76,748,566,916,607,358,766,400,603,962,819,677,46,464,510,30,875,555,158,693,213,645,452,631,927,89,458,228,994,274,430,37,461,667,658,573,449,119,850,965,24,765,825,578,626,727,814,65,778,703,663,484,382,812,326,346,729,597,354,128,580,589,159,678,396,31,861,108,497,486,83,522,26,180,869,197,936,277,30,36,293,377,242,106,648,448,204,90,360,122,274,156,667,937,871,349,185,312,369,738,54,813,332,156,869,85,791,701,151,804,320,321,739,686,45,602,436,995,612,781,747,758,847,839,723,947,482,772,654,215,321,317,62,257,463,437,106,302,990,48,456,930,530,295,789,722,700,295,944,735,742,242,883,498,978,532,730,168,113,255,499,1000,58,763,85,550,9,636,639,397,134,241,200,592,64,136,865,224,957,841,528,43,405,259,149,162,959,50,428,860,439,67,889,299,703,915,288,355,88,594,80,827,77,482,381,37,54,478,537,187,587,918,98,235,528,233,336,741,40,306,982,654,377,47,656,368,89,89,550,230,41,451,266,309,665,516,889,195,399,679,524,28,700,59,188,658,574,398,749,287,233,104,804,143,53,483,364,205,716,44,806,459,621,265,670,533,9,149,494,272,211,377,113,676,804,249,167,698,128,632,590,548,584,558,974,501,472,312,438,700,809,287,197,883,993,337,808,253,154,748,670,626,539,123,699,854,362,627,88,601,477,576,121,279,123,304,382,680,506,142,905,437,455,768,265,883,799,630,729,838,183,775,462,898,539,808,359,857,607,70,13,186,824,909,307,517,490,702,547,907,468,563,15,639,333,647,835,612,759,645,611,207,716,149,295,335,377,796,331,845,830,661,52,937,546,23,630,500,832,233,886,324,256,231,111,996,363,869,861,682,74,959,860,391,199,654,203,793,180,14,529,961,43,889,531,403,614,769,490,528,770,42,343,835,178,288,768,367,563,0,962,80,650,331,66,498,645,871,537,732,742,942,301,169,563,190,470,415,41,940,875,596,325,691,880,253,24,807,785,260,437,530,129,269,273,644,770,940,584,269,906,615,143,30,663,595,35,121,292,601,395,7,726,731,651,906,690,528,911,859,885,188,736,839,818,350,22,399,439,775,730,330,966,273,698,39,508,571,881,2,601,998,978,342,711,175,117,528,240,453,584,955,983,212,803,256,58,706,461,10,16,8,804,743,198,420,348,159,513,449,680,765,422,286,973,697,881,200,216,204,843,847,953,668,137,289,985,631,703,671,289,587,414,928,774,474,140,382,398,186,329,887,473,871,595,675,317,438,688,353,725,747,169,603,488,451,490,541,787,897,841,124,470,99,816,586,81,957,997,693,344,765,717,546,917,92,179,13,865,45,959,197,406,208,115,810,686,115,930,151,291,432,309,480,477,508,299,313,345,118,324,578,497,999,907,974,387,961,111,417,62,646,443,111,462,810,827,735,164,349,961,917,913,835,405,41,412,993,344,948,274,288,353,537,726,639,647,1000,83,35,703,686,165,180,490,151,344,562,890,840,606,702,876,775,86,313,456,796,124,316,947,149,92,343,62,24,466,573,258,326,560,796,906,446,254,578,374,679,422,729,241,918,119,619,233,712,196,86,864,474,310,382,731,854,725,445,172,144,670,274,489,812,551,798,577,652,729,350,572,262,530,824,186,646,287,112,769,818,474,551,108,867,29,120,787,696,574,941,324,671,373,492,130,216,549,1000,416,72,733,882,667,935,905,829,912,237,416,177,403,211,6,821,71,316,69,663,682,339,70,5,774,635,746,531,853,758,478,150,718,297,368,563,903,78,671,135,857,302,66,338,658,477,911,710,743,816,227,421,556,536,856,784,672", +"381,751,102,711,545,251,286,158,131,271,147,117,968,645,766,394,572,254,98,650,98,157,728,587,634,52,801,850,781,615,721,17,746,577,177,243,373,404,870,561,902,731,979,841,605,322,381,83,269,837,665,815,511,559,914,880,304,891,152,537,983,536,750,449,286,55,400,119,832,9,726,911,682,388,238,678,13,601,747,268,316,783,947,109,777,678,777,550,730,275,422,877,903,514,205,17,100,531,151,352,139,780,310,338,966,417,409,584,887,309,538,214,298,982,75,357,851,494,856,765,139,61,479,952,870,341,699,513,255,801,263,438,748,970,118,719,690,989,74,21,824,158,838,807,272,510,811,459,415,14,20,765,259,672,119,540,563,476,769,446,390,189,693,65,287,256,658,875,226,733,298,910,467,589,302,625,745,569,142,311,463,101,908,249,606,207,947,796,142,145,676,721,226,926,101,390,267,105,269,880,182,544,57,487,453,962,446,834,225,979,536,152,587,997,628,457,76,176,732,873,371,989,297,524,936,751,584,707,94,164,602,468,414,679,708,225,141,159,938,534,579,565,313,563,556,118,420,894,97,104,644,74,155,23,391,713,325,592,473,365,202,520,33,890,587,490,496,549,420,881,51,721,879,399,777,240,589,743,195,613,790,552,471,96,354,773,185,260,993,501,534,258,835,555,568,653,463,195,824,530,733,338,102,540,71,175,435,642,717,357,508,706,395,895,609,979,403,358,503,228,614,948,833,228,551,22,538,426,3,334,225,684,594,446,70,153,850,189,267,627,362,262,480,565,727,356,351,750,2,4,44,237,602,866,24,813,531,179,288,844,180,425,517,198,667,526,102,495,951,756,66,92,132,37,361,80,488,934,185,579,364,523,792,22,465,180,56,671,771,146,197,650,269,744,812,211,337,312,886,940,264,509,774,571,865,414,562,857,920,542,112,497,442,563,371,478,549,692,831,764,78,825,241,134,96,722,571,65,601,626,125,126,565,957,844,239,111,246,610,994,998,520,759,78,595,188,574,685,694,529,224,860,533,24,110,59,247,378,178,988,286,520,624,313,869,411,832,340,203,530,129,864,722,1,806,168,597,329,241,63,18,143,132,934,590,776,138,755,20,213,873,221,989,205,458,373,90,462,355,702,902,265,600,121,764,985,317,64,220,627,571,68,45,29,611,585,563,756,252,821,658,55,719,477,571,772,658,878,226,656,78,243,151,780,153,608,912,275,965,383,512,247,352,519,381,200,852,451,367,321,170,782,532,428,327,219,384,495,827,583,199,571,990,856,121,867,425,244,460,21,366,230,310,17,256,163,751,572,422,717,567,82,468,715,418,577,619,198,265,196,332,80,794,142,382,35,980,60,13,629,547,986,86,716,146,968,962,0,117,749,253,767,636,850,62,290,434,474,586,244,225,470,82,334,136,990,854,751,257,858,833,12,281,980,673,411,619,412,571,248,966,140,371,258,289,708,490,454,259,523,850,719,375,504,875,214,996,8,794,925,283,476,977,905,294,241,459,797,794,932,608,792,356,783,162,922,805,140,274,669,947,949,417,183,85,3,543,853,392,901,507,950,994,27,804,46,633,318,596,590,316,152,660,894,394,781,282,610,122,960,826,849,999,851,136,847,495,112,994,493,431,887,889,940,697,219,902,173,81,160,947,277,736,302,116,538,259,394,139,673,675,40,256,818,522,318,581,140,815,641,222,735,642,68,889,506,446,98,627,42,781,114,470,33,329,401,92,212,580,702,758,348,169,949,505,716,361,590,884,163,199,955,794,232,514,312,521,139,150,317,279,849,313,22,449,665,137,440,753,82,133,302,155,936,320,830,416,452,618,452,203,750,441,833,996,208,466,976,302,844,562,855,103,57,297,565,808,273,32,306,785,895,583,869,416,449,712,560,738,293,762,91,452,212,938,488,678,970,268,551,530,244,966,957,246,426,772,501,929,129,652,269,382,955,96,899,132,102,95,940,744,156,527,671,624,683,988,502,301,540,665,15,529,834,143,536,154,307,990,724,187,250,356,159,519,380,552,230,581,530,88,429,304,937,122,802,819,300,510,232,934,624,723,694,355,544,719,586,96,456,351,255,813,776,143,774,281,35,524,638,683,676,868,849,136,463,343,922,577,682,730,946,621,670,910,959,93,41,496,615,328,958,567,783,968,261,675,825,723,272,885,215,598,103,908,636,976,391,108,902,759,174,143,432,268,283,889,290,289,174,416,427,470,223,459,787,457,10,358,12,832,545,33,914,611,994,559,23,978,697", +"223,230,254,674,430,137,95,786,135,408,416,151,492,400,788,324,996,712,318,736,493,911,249,306,274,133,518,966,33,885,171,616,381,545,99,903,140,141,669,237,828,181,74,970,405,19,430,24,803,186,235,190,554,547,106,412,209,942,955,227,97,990,122,351,23,989,875,326,803,107,719,677,370,100,833,868,599,468,777,841,358,933,804,936,761,373,155,901,494,149,938,364,618,266,619,375,138,872,329,3,696,663,880,865,4,724,33,562,914,237,318,469,622,844,196,909,587,657,708,553,259,301,689,683,685,886,123,651,577,444,462,545,580,459,823,114,324,750,57,638,178,300,642,535,230,994,82,46,109,903,763,159,700,389,889,744,259,362,142,857,164,246,705,158,303,498,741,569,88,973,91,518,642,390,415,4,177,521,161,188,990,649,318,418,199,636,513,62,474,489,358,219,352,670,444,591,94,432,322,795,622,528,322,487,901,390,985,785,354,802,383,371,970,429,262,893,394,431,730,178,90,256,270,72,65,625,715,699,796,679,349,878,604,150,238,47,275,887,308,246,148,651,380,330,635,987,186,141,286,155,714,920,547,484,835,542,994,191,235,916,268,676,495,58,5,823,611,751,260,692,246,202,353,190,836,38,425,137,170,388,726,705,864,809,419,812,146,419,174,979,447,677,908,154,545,856,285,642,243,257,505,270,271,716,622,391,334,955,854,859,454,371,685,301,327,811,742,188,667,222,489,531,877,952,914,200,163,320,727,923,599,943,53,774,216,409,103,198,584,804,579,726,958,175,458,529,895,96,481,147,866,968,842,758,129,215,209,77,355,392,313,201,162,436,923,395,391,651,472,128,413,706,727,994,19,706,940,489,793,877,468,903,283,254,174,625,675,836,298,149,707,367,279,647,975,420,125,478,516,285,941,92,361,503,3,939,438,818,924,85,878,128,369,505,959,820,268,828,657,314,216,234,535,253,596,390,516,900,303,648,468,194,711,386,528,225,27,410,506,468,424,797,826,731,749,393,50,701,174,409,825,753,373,135,250,213,355,745,663,832,880,362,819,175,90,685,397,773,630,320,967,461,777,48,188,385,49,940,575,476,772,197,488,140,451,489,290,823,300,8,175,373,93,877,116,369,16,390,809,971,605,328,302,81,100,479,947,983,464,55,470,27,267,10,878,44,502,925,495,794,864,509,98,29,845,36,992,834,707,21,568,764,280,275,789,487,524,376,126,49,76,773,981,988,252,153,312,700,191,285,817,433,834,239,336,974,862,831,496,928,937,289,785,371,938,893,926,681,806,746,952,685,200,749,456,36,141,216,606,577,689,14,178,300,443,935,88,5,495,599,97,427,422,373,808,188,657,981,572,778,744,709,30,821,452,437,80,117,0,274,672,161,177,303,179,805,294,831,82,199,385,101,280,401,423,621,312,267,946,825,651,614,410,987,502,304,15,143,157,250,773,906,67,615,760,937,156,380,971,936,314,891,702,365,937,477,538,963,895,568,283,919,563,338,376,910,743,461,342,17,770,455,802,785,365,952,156,10,631,527,714,175,820,703,675,318,528,366,243,962,48,895,776,262,795,744,798,968,62,429,130,997,336,823,927,547,55,152,154,935,551,290,242,779,466,944,851,703,740,277,118,425,385,908,485,236,707,238,305,534,181,269,572,207,136,475,5,896,476,596,312,903,706,194,886,46,724,29,32,712,230,796,815,557,261,555,204,237,982,985,859,428,690,462,612,202,565,74,39,851,13,789,119,27,257,263,687,756,251,325,53,908,365,914,357,295,219,212,109,112,107,267,591,707,437,201,217,726,933,889,721,781,242,800,578,131,473,182,831,558,452,813,357,636,48,338,710,77,394,480,56,678,790,553,25,654,157,246,492,576,484,40,303,434,297,301,5,963,602,370,566,492,97,615,493,723,634,466,648,381,269,208,442,380,46,478,598,112,445,369,653,197,626,188,877,349,249,586,23,951,829,49,694,409,567,703,853,859,830,943,147,683,269,251,367,178,797,153,365,962,142,705,719,116,127,45,568,263,848,34,500,16,683,251,832,215,755,682,279,487,295,402,415,693,837,201,644,102,396,102,201,526,255,885,21,912,956,286,81,262,376,809,445,973,988,130,81,248,768,239,100,486,22,481,727,532,496,125,925,131,971,954,924,504,373,218,916,718,587,478,390,166,88,140,367,168,645,821,282,603,171,481,417,185,128,850,541,670,919,192,10,921,97,693,201,242,749,339,483,618,981,53,484,373,456,523,973,972,53,749", +"299,61,8,198,738,559,574,24,146,120,610,868,669,702,280,784,427,563,358,152,305,944,131,484,265,715,135,399,237,799,46,647,853,469,811,964,103,330,629,608,446,142,705,851,307,358,551,50,854,939,777,642,305,451,975,168,421,723,918,440,771,935,840,241,406,974,561,51,706,777,536,13,994,901,598,55,785,414,874,499,385,528,86,988,851,497,698,999,727,435,370,135,206,323,458,857,819,119,812,108,964,727,228,20,363,178,694,844,8,903,548,319,56,388,112,844,99,991,355,340,808,151,524,633,581,556,929,251,550,838,471,521,52,856,766,937,823,12,477,948,479,597,575,546,912,90,98,739,46,645,313,811,756,742,999,669,412,826,116,318,820,731,255,880,156,387,324,196,984,199,937,488,561,438,543,253,125,557,268,485,14,395,345,26,816,551,652,480,604,164,830,457,413,186,848,642,687,547,57,888,769,886,209,47,108,508,62,8,625,244,749,860,641,436,667,473,634,693,886,533,42,518,511,819,79,730,847,780,773,714,952,698,925,137,859,462,812,81,873,348,655,403,622,556,120,348,196,578,728,938,969,835,447,773,71,810,16,394,169,914,3,698,125,234,22,326,677,451,452,881,556,839,601,184,506,916,200,347,308,314,949,790,100,134,11,950,763,300,665,982,12,168,207,225,822,957,738,776,114,151,205,425,797,723,905,432,656,672,612,621,842,250,446,655,576,611,715,505,824,106,923,108,79,476,160,434,575,539,984,753,622,651,707,337,155,579,882,55,878,551,96,973,35,307,850,962,781,974,210,84,590,527,135,602,521,64,80,760,985,999,626,881,750,143,776,627,719,207,652,616,996,117,553,30,191,645,654,472,688,368,430,427,611,539,413,220,611,343,11,710,54,307,866,580,252,271,259,270,633,840,172,929,866,257,967,152,632,182,833,364,485,997,833,221,604,276,874,895,401,6,634,224,18,762,263,426,647,866,301,208,885,856,585,133,92,76,106,78,26,60,29,49,695,225,10,856,110,291,8,400,569,346,52,70,450,614,11,332,194,173,954,57,600,585,419,851,399,269,430,979,787,506,862,783,898,531,540,728,756,122,604,931,436,715,273,121,950,645,800,195,647,761,771,896,381,906,976,814,423,201,904,855,724,822,707,353,84,383,272,170,24,540,107,826,505,292,334,863,528,338,94,263,76,103,533,155,428,596,422,362,817,690,888,141,800,460,266,739,211,67,987,769,341,839,335,800,137,379,502,139,558,664,39,500,383,951,89,876,632,115,250,521,31,564,563,356,516,899,424,182,269,234,203,648,470,327,277,50,443,400,401,541,262,672,187,130,476,676,36,270,550,85,304,284,460,581,288,806,393,861,438,755,888,265,937,128,650,749,274,0,882,459,580,148,483,330,848,316,775,874,137,145,708,466,89,910,425,685,220,584,428,327,180,224,307,718,261,579,543,238,180,67,907,358,446,416,68,437,330,931,536,925,332,307,860,381,583,313,557,731,782,789,520,992,168,314,727,115,505,54,592,115,834,234,212,829,186,537,853,264,925,574,859,322,955,957,565,575,299,700,137,625,592,299,370,726,461,17,907,39,2,359,76,863,534,68,277,239,618,707,656,859,150,653,352,55,70,332,107,922,647,227,781,338,295,268,749,103,804,668,211,201,578,791,365,868,942,261,852,671,654,554,5,469,519,219,390,325,86,125,911,940,691,972,945,352,638,893,374,969,500,66,742,419,548,3,664,882,586,533,419,21,67,508,33,565,870,752,91,740,62,295,266,470,101,627,749,121,124,75,661,157,431,390,187,122,392,333,439,946,239,231,207,730,602,317,437,414,62,18,435,763,816,814,556,302,903,956,528,894,425,568,164,216,133,607,318,323,183,764,360,810,939,110,581,438,971,515,501,618,302,17,459,596,410,893,567,582,253,532,437,366,886,67,477,395,932,216,541,265,647,676,495,469,288,217,584,296,987,395,858,980,373,752,836,620,970,620,27,112,758,370,455,179,656,89,578,976,979,581,584,25,652,266,162,93,644,63,265,314,816,86,384,614,155,217,795,9,640,516,353,144,955,173,60,261,191,584,258,468,828,656,145,202,85,857,282,8,434,744,270,944,298,907,889,235,324,560,990,717,282,547,419,130,147,612,341,756,883,404,282,875,297,260,736,12,155,382,681,798,862,779,691,754,136,442,695,372,751,707,553,175,402,843,60,582,870,963,513,826,41,524,499,112,968,605,291,617,726,930,859,725,290,684,821,261,128,127,566,659", +"298,834,574,784,797,974,949,876,616,672,890,292,538,111,362,23,109,111,351,986,438,810,935,503,983,821,646,302,827,575,133,477,964,949,630,273,385,268,580,332,419,688,891,846,162,8,513,153,801,418,461,220,226,607,758,179,462,66,765,706,253,816,622,660,183,129,508,360,561,71,313,547,722,403,161,870,832,629,758,131,879,332,731,17,216,960,4,496,261,851,803,487,806,916,58,699,379,61,115,304,841,426,711,928,97,448,518,644,903,252,412,200,821,362,424,599,977,615,826,903,656,531,366,904,553,803,821,605,387,779,971,905,891,707,885,333,958,602,446,433,157,610,206,449,466,233,81,291,595,232,110,227,576,783,135,952,41,372,646,527,158,939,444,562,878,717,509,794,920,15,101,299,266,212,122,354,41,259,26,232,631,71,227,467,129,22,821,930,555,993,562,692,240,919,459,764,529,600,433,107,438,136,791,399,416,452,477,601,88,427,922,690,340,905,282,769,763,341,797,436,527,983,898,750,418,544,948,888,979,814,968,488,610,275,32,671,335,141,831,803,708,735,22,218,886,981,920,499,259,654,625,617,134,969,301,136,190,379,715,855,696,405,169,536,180,417,420,407,125,31,818,199,521,879,409,58,964,290,175,706,465,132,376,850,307,133,724,890,511,989,576,440,666,574,224,930,846,979,584,131,53,250,551,963,927,881,977,346,226,794,880,192,296,555,399,515,510,96,543,561,763,978,581,357,495,266,655,90,136,979,743,560,419,75,365,540,202,594,141,872,830,536,242,773,980,746,680,488,433,488,453,230,569,921,728,940,632,386,524,19,627,828,1000,573,508,714,577,816,986,3,747,70,758,343,864,851,736,423,33,674,78,251,846,649,106,312,641,214,741,174,878,404,912,236,983,260,519,143,994,506,996,631,615,377,392,809,779,749,372,868,321,619,308,598,369,658,142,884,112,829,671,577,614,518,565,861,11,139,745,670,928,472,95,732,431,262,496,181,486,265,998,11,778,370,603,639,862,127,361,292,429,556,827,489,700,610,369,336,918,735,96,921,255,880,327,765,811,471,375,235,192,622,722,378,14,809,573,551,378,943,942,549,61,430,542,965,796,863,933,855,899,323,102,186,381,152,237,897,481,186,830,553,361,163,291,548,662,115,826,390,640,846,694,286,189,78,799,34,50,20,443,761,539,430,25,931,75,961,889,86,155,965,697,845,498,314,46,559,535,375,501,144,463,316,171,762,689,278,528,529,964,576,93,296,850,239,43,576,265,155,292,54,478,799,744,477,62,408,690,131,226,823,686,488,284,671,72,394,452,475,136,458,809,108,12,224,790,848,182,183,877,698,471,968,796,881,31,239,742,844,336,837,515,904,273,311,331,253,672,882,0,510,575,121,810,782,216,208,954,131,365,643,511,327,720,905,559,263,796,26,628,340,523,764,549,28,573,979,470,937,812,533,857,290,874,777,144,335,980,719,929,623,775,457,206,232,468,28,495,622,86,274,233,549,156,353,209,219,881,485,170,373,554,70,53,220,539,198,180,955,56,632,744,124,9,390,590,537,604,784,337,831,213,696,494,854,390,361,37,862,774,91,407,373,809,661,103,766,552,388,970,981,688,761,500,195,210,225,714,461,68,710,947,70,859,669,273,363,468,387,183,295,585,831,166,771,359,868,99,207,79,35,910,327,357,117,548,768,805,455,583,323,7,259,619,331,996,346,604,219,547,771,691,313,13,687,759,757,561,945,979,237,96,399,125,646,547,628,171,735,595,429,985,206,414,362,905,313,690,129,447,5,460,905,626,422,2,984,501,48,127,758,918,579,865,906,74,860,394,434,217,847,26,119,796,510,486,762,946,231,495,858,181,799,153,123,81,745,676,157,486,707,465,869,408,893,404,474,119,386,502,256,568,195,256,747,389,813,51,377,397,5,738,525,281,778,224,205,313,808,623,118,772,355,73,277,537,289,843,198,506,65,956,248,117,991,77,418,975,898,91,22,16,861,817,173,452,842,647,959,706,671,388,351,395,181,766,146,773,744,342,896,93,964,381,757,491,558,239,185,447,705,432,742,802,966,909,730,568,263,621,457,957,373,859,57,270,241,769,262,348,787,972,764,692,500,847,354,448,551,290,896,389,763,221,550,913,78,565,722,895,695,800,823,270,171,297,456,459,769,888,940,264,970,746,171,85,883,663,705,712,513,912,630,144,723,267,792,608,569,642,936,903,549,134,663,591,739,965,538,542,950,891,199,481,986,421,981,306,94", +"981,940,804,184,127,70,493,311,445,327,648,618,190,132,754,116,755,482,446,757,741,722,566,607,358,661,154,194,125,582,702,696,223,357,229,22,258,379,948,385,895,884,791,516,77,664,367,540,967,312,691,989,522,367,847,283,736,38,404,108,50,471,471,893,386,747,98,745,885,897,418,257,720,640,487,631,850,914,95,518,280,483,644,153,689,268,699,80,167,696,732,230,837,445,489,720,809,468,315,341,294,248,544,513,39,942,786,109,266,863,864,127,25,271,166,587,213,939,101,850,663,355,511,56,182,882,740,282,795,829,295,675,614,539,312,617,428,918,704,492,556,409,388,804,46,821,477,115,548,465,642,141,262,448,893,138,880,454,476,11,50,740,207,898,742,837,221,626,920,327,3,778,278,4,439,31,163,551,397,150,623,723,774,855,542,754,883,868,484,608,926,686,339,994,680,266,342,228,707,616,412,773,11,372,486,737,799,395,775,447,190,444,518,19,557,561,60,49,42,645,675,783,159,273,362,77,802,71,582,869,314,322,803,576,13,748,647,637,18,795,756,518,501,515,9,454,853,80,349,233,232,860,995,221,553,351,866,319,611,527,84,463,823,111,171,830,371,146,963,535,22,730,132,276,915,778,565,820,737,518,923,117,332,834,725,653,251,691,589,606,542,620,879,52,360,193,372,20,784,664,646,389,469,503,386,614,890,457,236,922,949,237,4,847,385,312,495,820,741,7,670,921,891,79,579,41,650,448,104,29,478,887,402,540,314,750,204,100,915,901,561,123,190,412,198,66,841,729,32,214,515,935,760,301,991,145,648,331,990,788,181,569,2,340,435,587,853,483,133,123,603,955,101,701,597,624,652,139,611,720,551,430,85,92,671,958,284,231,380,317,417,681,994,237,515,222,185,225,279,635,433,824,417,870,144,534,114,477,347,697,875,248,261,27,360,702,982,692,200,385,996,685,520,644,879,301,650,615,534,360,81,568,513,883,911,710,829,211,496,814,569,854,479,976,981,680,989,629,479,441,851,765,199,805,191,965,77,692,266,414,449,309,252,333,215,854,660,880,157,191,617,179,120,923,283,44,784,221,214,772,153,629,850,365,717,644,664,974,983,916,203,677,636,865,344,506,453,890,984,302,572,393,857,649,769,86,369,790,408,148,493,598,490,14,466,863,972,332,984,601,422,190,406,775,372,630,988,59,409,357,774,650,400,625,992,539,939,726,197,94,461,539,136,506,622,516,365,934,959,405,353,406,273,686,569,750,97,996,50,734,701,339,361,116,870,115,301,401,866,587,248,635,737,839,139,893,211,613,41,280,581,920,192,799,202,428,162,325,887,803,878,482,182,298,283,894,774,158,284,915,410,736,160,921,892,322,66,767,161,459,510,0,764,571,141,728,457,744,884,574,720,604,150,158,813,69,544,783,753,404,301,716,464,547,914,614,695,156,369,994,600,538,806,657,55,112,652,848,953,976,597,792,98,753,471,171,946,690,311,876,299,737,728,332,325,542,17,931,384,303,933,38,113,80,456,616,166,691,973,291,164,929,498,917,711,486,81,433,477,529,801,994,417,710,671,587,317,729,19,939,280,262,772,982,135,203,971,889,823,670,507,328,66,539,727,961,769,418,408,281,375,209,525,654,538,809,361,690,55,21,764,716,553,143,844,527,354,647,760,611,136,536,236,868,971,585,872,936,532,156,905,350,860,991,39,261,170,877,422,416,129,464,454,171,205,835,433,835,325,848,104,594,70,256,302,568,253,883,715,529,726,197,90,833,86,610,458,468,382,42,942,212,747,598,41,724,325,783,872,127,592,288,669,445,923,293,255,965,673,908,133,530,67,795,127,813,62,965,761,79,149,849,109,826,633,87,952,230,680,102,387,212,164,816,306,213,241,676,550,777,667,391,188,108,90,686,248,249,206,550,573,788,717,64,483,572,543,846,919,996,843,809,230,482,383,622,261,932,72,654,62,413,398,717,43,580,178,973,53,523,168,32,495,849,450,420,311,672,174,738,738,41,442,449,303,624,115,203,125,534,166,545,223,317,913,938,950,79,511,858,606,975,5,598,766,225,947,585,959,716,58,154,409,229,69,981,476,707,236,982,61,885,439,318,305,623,650,758,822,513,903,253,584,851,548,69,561,563,370,885,932,388,721,143,88,449,436,973,752,53,579,604,272,17,637,44,29,70,826,975,65,663,791,981,769,745,791,539,635,296,92,483,534,465,750,29,993,212,13,374,545,681,775,779,237,101,756,916,897,288", +"642,156,798,159,576,306,175,54,725,455,28,642,97,856,691,738,18,264,834,50,697,530,104,837,716,384,767,815,660,190,955,168,154,401,83,505,226,374,134,342,480,225,978,694,452,192,956,603,880,432,595,113,503,614,946,498,792,723,948,395,662,908,18,631,980,491,968,135,782,57,753,637,805,882,908,800,88,718,639,822,538,899,10,642,294,669,644,340,202,305,140,155,955,355,991,793,581,529,999,943,324,294,740,178,810,326,722,246,92,1,318,428,52,65,850,266,608,617,45,736,699,328,27,675,110,366,738,781,970,721,335,32,571,404,234,806,677,712,592,519,725,145,109,699,499,654,588,948,675,606,485,500,963,203,907,606,619,23,869,420,150,242,428,488,511,416,126,678,235,152,278,523,440,878,322,363,296,76,750,667,366,874,949,725,907,555,290,993,835,479,928,149,278,412,907,128,538,479,402,227,273,558,130,10,714,337,589,550,682,236,337,763,947,997,453,852,88,5,790,929,610,41,962,4,321,124,850,166,960,225,764,637,842,203,398,922,333,760,35,109,177,31,590,24,222,754,341,676,787,423,46,690,989,939,751,185,372,768,690,555,537,404,75,271,183,818,976,540,296,17,110,725,83,931,895,967,310,433,654,790,722,399,349,542,238,342,136,949,197,245,893,75,116,638,745,71,218,371,756,237,381,209,16,295,41,88,65,363,158,832,529,939,88,272,934,656,816,108,573,682,989,58,636,79,102,535,186,45,10,933,75,357,431,575,289,720,336,380,895,828,813,137,254,342,448,928,68,368,789,128,962,451,122,76,858,151,636,130,188,587,616,358,184,732,875,492,278,245,958,32,517,645,924,121,793,640,907,325,984,975,785,379,795,470,236,358,197,502,262,785,751,499,49,211,57,927,650,371,34,787,799,938,662,117,739,743,522,634,967,251,26,655,930,385,907,22,563,623,950,504,934,568,217,921,153,136,214,880,253,995,604,960,269,328,425,573,822,302,823,191,413,889,103,137,575,495,575,386,68,525,715,741,820,941,899,300,649,151,735,62,916,155,23,890,993,691,431,898,146,197,986,532,410,442,593,122,403,806,795,55,474,980,967,75,149,691,659,225,206,397,757,625,858,832,362,448,52,580,234,383,701,742,514,858,57,178,514,28,912,884,427,844,231,74,100,899,683,690,373,762,917,220,237,765,866,513,639,771,560,414,677,190,746,521,139,856,318,549,901,212,927,104,183,461,311,181,827,845,867,768,114,407,175,397,162,732,51,335,216,390,396,378,504,477,650,442,883,427,46,901,653,583,105,519,321,775,396,842,108,803,743,880,556,567,791,227,546,484,82,127,511,487,79,422,785,151,535,685,837,460,467,521,790,5,300,374,498,636,177,580,575,764,0,26,806,250,833,237,251,26,747,169,982,901,442,903,442,122,10,46,830,467,133,81,515,354,374,11,210,51,720,440,607,918,787,61,395,657,631,238,961,834,808,271,461,14,392,463,807,130,1,271,541,192,280,387,609,146,855,493,367,256,217,501,257,537,112,551,543,267,857,573,340,558,846,125,78,898,524,467,179,175,671,200,399,569,519,504,17,740,658,801,120,414,76,792,185,412,533,165,859,678,718,353,82,900,852,808,243,242,781,269,781,305,301,24,900,923,443,371,614,804,418,607,314,455,79,332,419,150,341,820,739,278,46,102,174,207,444,950,645,586,896,431,933,388,383,683,305,354,659,819,526,414,283,717,803,609,644,767,102,746,152,144,975,883,221,34,498,798,518,338,239,805,369,893,361,256,309,812,984,283,448,602,279,59,152,414,130,58,837,742,695,203,487,237,741,286,577,681,412,188,35,382,942,375,638,338,868,441,824,296,545,914,904,116,738,953,939,526,856,293,290,474,793,335,138,32,773,18,168,801,781,550,588,756,971,85,271,785,673,942,631,513,236,424,781,982,495,740,665,58,768,803,549,412,201,58,841,504,751,317,220,209,909,361,703,349,193,87,935,643,831,926,625,468,4,194,94,480,117,139,648,920,890,377,89,854,742,655,322,505,828,864,427,258,496,137,536,217,232,2,7,395,762,197,432,369,463,62,347,730,787,319,195,465,452,369,721,992,772,974,698,612,655,487,927,456,492,843,638,33,3,522,267,556,136,955,582,485,83,167,481,141,221,270,361,418,277,791,157,733,988,265,400,841,671,797,433,878,660,205,667,924,673,236,934,134,442,731,375,270,927,942,887,706,209,462,694,43,150,627,881,817,883,551,586,441,213,209", +"100,410,832,845,100,933,153,227,318,770,474,566,262,149,790,505,454,429,515,857,642,277,518,197,920,187,572,534,28,581,816,709,474,215,624,114,932,963,348,557,255,254,108,602,411,674,989,848,225,995,212,314,380,826,621,887,68,806,912,555,880,681,481,91,908,822,106,143,900,196,685,368,771,184,402,417,768,934,418,270,78,471,604,351,910,131,384,867,403,86,763,83,796,665,365,258,930,933,476,72,328,100,245,112,780,88,823,354,881,444,256,809,974,259,978,265,41,643,471,667,915,153,555,923,565,774,237,960,189,678,548,91,185,15,26,895,517,235,633,704,870,954,987,910,642,18,215,915,679,280,674,431,945,198,773,791,224,341,357,649,771,194,15,595,812,312,269,383,149,111,169,982,326,746,45,696,456,176,786,886,211,29,781,872,716,525,34,68,917,801,612,304,654,609,254,393,687,25,510,451,881,284,199,9,811,213,768,849,718,943,979,780,598,320,646,420,966,214,711,163,567,244,366,712,660,44,826,182,680,726,882,497,132,435,762,572,329,671,442,603,397,399,595,793,755,556,310,846,62,724,305,697,674,181,265,960,205,281,87,124,324,973,639,2,108,635,48,105,92,234,487,456,825,485,979,116,405,618,849,33,812,269,72,340,81,936,64,398,574,101,824,440,455,399,217,705,549,542,915,154,416,310,315,924,982,700,334,541,34,188,918,951,35,872,220,175,584,529,691,426,979,941,317,790,868,763,784,912,535,561,976,593,464,510,960,440,759,304,960,970,718,309,880,327,4,127,217,2,239,463,43,728,736,239,727,934,221,891,269,535,999,184,259,72,312,810,943,630,747,730,711,780,367,470,574,685,405,419,415,818,510,469,642,828,874,607,754,642,624,727,727,273,625,117,135,164,422,763,487,738,8,343,726,4,515,138,625,161,319,783,153,402,564,398,192,664,349,516,33,381,636,796,279,211,365,86,19,628,251,116,69,830,799,930,153,740,982,59,76,574,780,778,232,251,965,980,888,784,583,60,305,870,199,375,854,941,201,467,724,425,682,447,985,981,892,376,6,104,324,859,771,892,655,557,134,162,307,684,366,405,418,186,165,306,373,419,491,624,930,723,840,607,525,34,168,740,200,87,570,459,681,33,674,244,523,374,905,783,100,50,590,537,614,350,768,415,416,482,876,221,651,647,905,879,186,447,955,272,593,221,424,860,420,169,150,185,762,460,542,45,301,283,509,736,809,729,448,69,618,99,177,26,869,540,23,600,729,731,616,363,244,886,615,33,831,62,945,984,252,743,802,777,368,390,412,759,174,902,14,49,914,604,76,770,510,850,245,332,499,565,201,599,906,355,383,490,799,380,146,459,534,888,400,520,992,616,645,850,303,148,121,571,26,0,136,11,256,64,682,515,979,262,677,509,741,916,792,860,380,111,424,950,396,606,735,463,421,668,765,583,885,458,472,10,587,256,243,441,908,537,15,792,975,436,669,890,567,963,122,756,984,761,99,614,612,165,348,536,843,841,891,370,347,795,7,276,984,651,971,279,394,324,547,487,596,698,432,496,692,301,788,681,466,280,402,828,677,819,790,740,223,781,331,887,628,2,341,481,206,504,658,663,349,305,465,123,732,438,120,942,579,29,19,121,875,73,718,753,34,888,932,349,936,822,365,512,149,860,438,426,178,749,979,716,109,144,205,244,651,115,904,245,751,64,428,522,922,672,605,252,231,332,767,414,185,237,505,696,976,377,96,382,770,161,676,935,605,804,770,857,2,734,730,666,235,421,489,385,52,395,894,803,82,529,786,719,586,687,576,550,841,260,250,533,963,191,813,625,254,239,59,455,901,867,307,590,193,955,262,541,213,345,522,347,605,360,723,688,17,928,545,801,571,938,952,559,394,8,57,674,363,792,46,799,803,344,460,880,733,193,955,50,283,729,476,87,505,155,718,933,682,233,962,517,863,736,602,912,310,632,827,863,127,69,314,356,177,685,360,369,19,37,224,740,275,328,591,339,721,622,26,60,651,301,30,696,494,236,141,110,481,559,286,718,130,233,105,146,452,181,70,96,259,68,514,103,765,847,142,719,276,246,257,63,759,856,206,160,714,975,504,399,432,347,205,156,622,281,959,461,647,259,923,277,558,390,186,262,662,35,694,568,731,252,600,700,20,503,506,319,836,400,633,720,137,961,188,295,350,935,505,656,56,239,990,123,743,629,771,216,356,575,782,473,767,246,611,123,701,713,968,394,507,369,195,94,426,286,812,498", +"95,734,883,876,980,457,273,577,562,134,394,973,598,449,115,463,227,200,820,325,631,660,609,691,922,914,64,968,539,556,294,949,480,850,684,314,384,204,992,693,793,106,728,454,995,381,594,459,847,268,642,39,832,436,961,153,613,218,874,881,309,304,657,92,379,822,76,368,743,356,998,62,544,413,384,491,154,485,804,434,872,595,110,299,661,785,621,999,510,789,300,206,200,686,973,668,200,293,186,242,392,193,498,910,763,737,737,863,367,172,657,503,961,540,408,752,423,425,173,543,524,465,285,858,140,164,412,181,512,897,779,248,551,43,237,458,620,233,683,832,275,557,547,306,545,910,824,553,74,880,121,336,886,800,182,326,666,336,454,628,488,322,4,841,746,295,259,894,934,636,403,142,371,52,142,467,557,281,233,358,936,573,366,342,166,437,273,380,672,242,873,70,883,852,986,720,574,41,781,16,248,480,150,466,239,426,342,735,421,511,576,18,172,395,513,363,200,681,732,901,762,943,650,303,598,185,452,706,254,783,233,573,666,18,711,728,630,515,479,946,973,466,431,784,419,194,929,870,364,110,861,39,390,279,331,940,908,636,276,627,776,103,840,908,397,152,681,94,756,130,533,918,800,396,843,832,918,115,290,728,124,486,944,132,75,921,576,369,247,411,22,867,787,800,60,121,120,677,520,172,809,270,125,254,549,210,408,607,749,754,867,810,639,726,236,384,796,427,594,831,764,445,182,776,29,410,133,50,124,67,676,714,363,857,480,128,724,77,38,949,352,608,623,209,737,570,882,802,129,924,442,405,627,367,494,403,14,955,700,572,354,88,604,355,87,127,270,753,749,632,161,516,138,814,948,655,714,836,528,663,788,213,699,29,64,750,203,328,171,525,588,227,273,301,965,735,331,947,676,456,762,735,106,783,583,931,879,57,258,840,624,454,22,494,568,728,763,511,973,902,132,818,961,300,236,645,937,754,408,601,236,651,697,721,907,454,283,527,459,279,30,293,707,898,958,592,181,89,789,707,869,347,767,973,583,178,417,890,174,821,387,426,672,651,496,541,723,568,715,555,727,865,183,733,218,782,959,345,532,876,969,372,489,60,496,769,582,240,400,955,284,773,722,194,793,118,256,996,22,305,100,563,252,101,636,716,615,693,384,940,909,578,905,870,854,945,162,529,666,70,347,676,934,158,404,328,8,351,20,694,911,714,546,688,530,373,250,430,557,98,76,654,104,772,664,58,12,56,361,972,691,914,336,147,668,16,227,804,581,591,937,725,747,260,998,910,456,555,995,375,738,793,549,432,550,432,348,918,772,802,745,910,457,856,388,126,879,320,173,723,169,104,314,563,707,181,504,515,206,844,908,313,701,843,453,321,871,62,179,483,810,141,806,136,0,582,351,295,998,346,662,837,39,327,855,765,519,601,776,682,416,111,845,15,683,80,867,548,105,593,192,936,49,995,457,679,733,132,77,222,761,759,161,276,191,638,952,800,659,157,57,523,149,730,632,401,78,751,792,626,892,262,288,5,863,959,684,185,707,302,593,299,73,925,615,738,165,593,117,369,515,345,463,238,515,422,161,154,981,235,550,189,842,49,498,460,764,535,849,60,94,265,279,209,392,157,30,580,5,450,422,63,454,680,670,931,140,3,849,910,75,607,20,151,766,527,848,91,283,266,501,692,917,135,471,342,963,583,992,889,161,171,872,437,252,877,336,332,884,16,70,743,628,144,609,655,148,171,168,322,613,567,990,890,239,111,756,583,992,284,874,845,359,401,574,585,240,890,549,692,302,431,860,622,588,879,149,259,64,252,253,113,205,69,82,911,446,946,258,880,422,830,348,722,980,382,900,228,517,500,310,365,160,234,478,285,242,759,302,350,335,483,278,287,155,799,379,736,613,107,103,523,959,728,242,166,243,925,25,25,937,694,520,545,810,410,834,698,879,3,689,396,912,631,642,724,923,574,539,435,850,663,526,779,76,231,563,493,90,85,266,209,691,304,167,280,684,75,542,374,207,6,796,533,485,933,702,154,28,232,276,818,71,589,416,138,972,588,708,407,16,288,157,356,290,786,331,961,90,428,429,818,139,351,865,941,634,417,496,833,955,575,591,966,486,293,229,423,630,153,798,903,611,627,856,927,105,277,152,812,380,456,759,104,181,23,266,627,636,792,544,431,102,327,275,156,128,945,292,127,814,700,319,153,150,809,561,441,735,3,220,975,11,505,25,339,629,829,730,282,767,39,785,28,978,166,588,488,371,865", +"828,599,137,87,867,864,73,339,571,842,51,932,657,658,921,857,897,835,395,227,728,23,27,201,286,386,297,956,843,703,734,679,411,881,661,676,195,58,312,517,620,215,145,538,181,107,106,654,355,116,710,965,811,539,503,145,698,623,392,556,582,915,925,330,558,80,980,393,249,143,610,145,775,99,102,838,699,138,886,712,881,631,989,518,305,204,893,215,148,238,659,480,826,464,522,916,106,782,710,980,939,316,668,169,996,611,849,459,969,209,651,965,164,478,449,686,651,362,28,893,252,466,708,599,992,174,411,978,739,631,920,283,802,994,207,615,536,344,204,245,118,17,348,776,141,177,16,305,949,615,370,779,901,888,461,921,650,126,171,289,435,986,105,735,479,353,783,898,344,79,208,416,963,399,473,289,447,142,888,688,717,995,70,716,790,886,861,819,637,404,637,961,441,100,113,290,459,735,755,448,130,460,299,736,606,903,372,861,894,826,673,192,941,680,761,194,225,757,253,437,769,940,419,969,773,272,794,503,349,686,561,932,387,180,839,426,206,181,443,585,920,351,885,416,434,849,495,257,261,322,42,276,134,425,684,670,577,857,521,29,983,247,387,12,323,143,940,595,926,591,126,622,714,557,356,376,916,825,480,744,559,691,45,998,328,565,430,595,580,573,361,309,167,251,109,841,386,274,133,447,415,474,93,144,543,459,790,916,506,594,82,187,10,45,312,992,383,401,421,374,348,579,520,791,462,30,635,671,761,949,353,282,114,860,494,460,696,24,939,764,381,466,328,429,771,513,256,10,907,640,541,854,285,905,525,560,276,325,206,307,599,395,826,256,56,39,548,706,489,166,420,666,706,965,149,76,486,136,758,206,52,829,544,454,736,769,827,97,905,331,787,855,444,81,417,534,225,588,445,283,948,970,217,450,660,646,952,122,765,287,194,73,455,688,357,286,686,954,945,581,779,933,381,117,888,279,520,420,183,854,286,632,3,52,689,179,921,511,395,622,638,772,977,440,247,392,851,452,652,345,306,314,177,84,151,497,450,151,300,856,857,290,141,630,927,386,257,925,259,109,588,476,925,343,959,626,954,176,650,183,732,193,42,9,312,676,851,706,914,610,124,504,511,810,933,561,773,634,305,509,393,241,10,605,377,954,518,378,843,943,536,276,381,619,168,911,267,645,200,726,902,381,287,604,202,956,947,316,774,491,745,606,163,268,332,589,97,992,580,84,944,655,652,720,740,246,362,266,195,265,228,696,434,110,609,167,886,36,662,755,265,716,17,208,975,944,73,796,603,472,977,964,376,871,296,281,705,442,431,546,153,563,661,68,28,132,756,545,145,682,844,39,418,534,700,314,808,450,308,929,662,912,45,911,591,791,537,290,805,330,782,728,250,11,582,0,809,849,628,614,786,966,920,593,145,605,238,173,242,685,907,638,237,990,722,129,73,257,281,379,111,403,964,897,270,449,737,901,903,357,562,808,316,701,707,685,755,595,924,842,315,934,802,455,745,721,19,758,773,514,756,518,936,751,754,894,906,43,576,365,791,177,984,881,927,721,516,608,709,626,960,849,510,769,583,980,278,948,358,156,48,147,908,408,7,756,998,688,981,874,671,140,920,780,627,367,804,268,431,186,527,893,39,30,69,969,901,328,174,518,952,745,817,115,14,386,738,13,231,759,258,579,587,607,239,670,63,7,496,686,583,62,1,671,579,534,401,877,453,264,774,596,415,499,511,138,186,113,730,120,93,776,216,647,529,179,223,143,367,264,521,852,823,776,138,19,503,418,390,933,673,322,493,2,334,935,648,398,438,937,792,843,786,377,429,302,69,61,703,6,268,156,3,661,795,559,892,449,808,567,931,925,373,492,453,103,725,915,684,274,567,668,835,253,570,100,226,19,37,358,964,797,698,743,984,624,407,915,237,371,404,288,749,432,649,775,462,471,880,11,423,482,328,886,921,277,157,630,445,702,554,459,29,13,392,463,111,692,341,941,922,380,433,634,849,975,286,407,740,184,310,858,162,869,984,401,765,446,392,666,468,518,778,218,963,566,102,738,380,401,480,687,787,887,465,555,637,878,362,34,448,783,861,746,163,338,134,991,608,909,634,605,843,350,757,624,941,975,286,71,965,932,973,98,226,98,886,565,853,621,655,884,420,895,926,757,820,321,900,524,717,849,462,537,69,182,77,462,414,364,109,820,67,39,456,351,762,783,882,477,380,960,350,165,397,928,614,872,44,164,905,489,559,72,164,915,118,93,49,630", +"794,444,694,817,204,437,276,537,801,329,926,51,916,151,508,663,626,815,281,254,294,756,674,192,982,484,346,607,415,52,952,681,356,942,912,247,343,486,556,287,490,718,795,534,386,947,559,870,182,871,769,771,993,649,703,358,591,722,771,747,308,793,297,296,415,833,979,849,596,137,242,416,843,106,377,824,803,378,313,615,778,355,780,979,24,958,334,617,263,372,927,787,328,28,204,893,446,276,397,908,474,735,70,579,371,224,568,39,600,315,349,730,642,831,286,964,775,636,220,642,899,684,400,70,566,405,752,129,747,60,11,423,58,296,596,462,782,507,505,643,198,967,154,495,818,194,387,614,457,192,598,145,505,773,984,891,276,737,332,545,330,289,580,597,368,469,61,685,793,443,833,999,374,192,415,195,144,195,570,880,839,304,908,785,19,95,501,693,377,279,934,23,824,384,538,703,428,724,694,294,263,620,505,871,933,356,64,257,332,742,833,272,157,214,406,237,861,717,818,517,569,962,969,322,143,758,88,690,497,271,231,363,347,200,378,45,36,396,333,250,13,881,790,950,244,70,913,319,261,975,112,104,156,75,295,956,588,447,31,260,493,406,864,443,228,400,227,694,47,844,87,923,604,557,557,592,75,423,460,413,115,598,771,868,248,648,759,336,579,365,262,487,73,247,863,702,924,203,105,859,814,428,481,208,205,560,502,351,196,654,723,453,654,781,41,578,246,841,681,824,39,430,921,76,148,104,275,541,955,872,480,701,465,154,364,974,444,483,444,288,534,769,512,784,112,714,287,361,214,476,811,440,427,446,968,790,820,698,449,927,236,271,778,491,75,558,766,580,288,516,809,663,659,282,93,115,785,575,251,935,424,540,871,647,322,352,354,380,669,282,309,265,637,632,917,935,210,799,162,481,33,388,1,529,76,988,936,274,532,385,63,928,755,505,787,236,87,520,33,127,540,145,864,587,123,391,40,671,273,890,523,973,223,463,701,844,739,353,444,716,152,43,674,278,740,393,948,733,345,741,50,746,976,221,525,570,892,174,457,309,131,171,289,921,45,586,47,513,597,114,85,816,255,656,249,391,581,726,403,876,734,255,2,711,17,105,298,742,332,306,184,624,813,608,211,380,127,961,405,670,31,10,406,668,693,598,994,891,855,441,892,57,649,70,698,340,865,60,492,106,78,588,467,438,576,420,898,945,143,867,405,206,932,369,598,583,382,958,402,193,112,787,459,124,710,611,454,403,81,367,787,633,945,664,665,954,309,200,410,292,265,667,223,60,23,931,536,525,790,489,325,974,756,993,38,733,302,192,239,509,928,885,197,80,845,596,819,671,111,962,202,141,469,807,107,562,741,781,329,925,974,367,872,43,403,925,732,434,294,848,216,457,833,256,351,809,0,860,112,803,200,634,816,822,552,957,476,381,927,225,957,842,622,70,136,474,17,73,619,943,505,192,645,184,353,602,327,922,735,715,879,474,426,733,732,981,303,518,859,372,622,144,838,267,637,534,631,992,362,322,484,53,299,242,180,373,337,236,455,645,456,366,725,757,772,491,539,699,68,902,936,475,447,59,249,810,810,810,658,549,913,937,406,932,652,311,706,61,690,820,657,323,544,528,711,893,953,879,943,682,361,132,424,598,869,354,720,411,880,890,495,366,876,656,309,850,519,134,926,757,943,837,762,902,718,211,71,651,15,11,304,931,753,96,267,138,939,252,368,663,468,637,638,645,826,224,206,539,94,106,330,464,368,225,467,280,63,858,671,523,652,692,860,213,698,441,727,753,632,45,665,28,472,60,675,733,50,713,668,211,607,158,233,151,697,337,354,563,748,273,427,32,373,596,730,840,521,208,82,314,11,527,375,591,198,656,559,891,680,75,965,700,195,861,119,900,625,584,608,188,799,500,66,170,774,556,38,825,267,592,67,106,42,622,88,333,796,529,185,898,403,380,643,41,995,49,617,739,466,453,749,755,845,459,683,60,749,424,324,242,33,200,349,750,322,22,433,6,812,819,200,720,692,147,143,420,648,85,23,666,78,493,317,676,465,919,412,350,753,135,911,586,952,435,260,827,206,211,52,274,298,389,882,122,141,586,427,149,192,24,582,802,232,981,498,451,853,961,817,255,99,823,252,366,466,966,468,953,434,442,397,799,198,747,692,150,416,697,180,561,761,275,655,428,488,620,605,453,388,83,788,243,243,453,263,715,192,433,82,512,405,37,886,131,333,513,901,845,476,596,664,972,112,688,747,385,102,862,104,322", +"689,399,608,726,620,910,353,115,724,994,197,782,147,542,841,202,720,874,100,59,861,697,675,893,699,738,238,134,282,758,584,948,544,937,429,761,499,292,140,377,682,257,389,279,648,911,257,986,662,344,719,103,211,106,120,536,420,508,162,28,493,220,111,488,764,604,720,63,74,486,428,951,250,51,725,795,564,966,407,878,224,461,649,430,514,654,673,969,55,306,766,499,475,643,195,991,556,639,651,733,521,354,985,434,281,108,680,866,737,559,819,152,384,940,764,325,708,530,142,420,479,847,459,297,738,663,422,435,352,217,467,52,219,204,380,734,195,388,823,563,621,377,42,490,378,674,891,663,308,464,937,224,786,808,568,746,465,414,693,415,175,481,459,283,415,903,72,958,370,498,409,879,314,777,596,882,40,828,210,257,983,704,561,997,584,202,678,776,626,750,970,875,779,695,891,96,437,507,700,247,559,721,519,66,741,834,718,512,478,132,483,680,734,244,948,698,55,769,36,783,457,798,846,88,665,761,144,690,166,269,751,497,599,894,78,17,188,355,736,813,108,40,72,833,169,185,412,222,47,842,870,273,49,902,675,694,86,425,231,959,607,797,19,315,305,169,602,576,549,96,550,526,325,910,691,98,736,764,660,815,58,95,123,18,357,891,24,548,404,956,198,896,393,122,733,962,507,881,738,912,997,359,535,558,6,309,228,260,75,51,18,463,726,384,171,741,18,870,775,587,20,666,315,768,456,930,884,636,869,571,564,31,327,228,18,855,899,5,534,892,903,798,552,725,596,595,36,866,921,229,370,791,690,183,981,570,594,443,49,271,396,673,931,837,94,607,872,276,659,256,573,830,533,936,867,917,268,516,801,443,128,479,487,558,661,780,64,667,341,788,339,372,127,395,152,244,797,676,763,721,845,932,832,211,810,392,669,619,259,175,689,798,11,118,320,575,434,12,172,174,996,511,583,212,473,962,336,68,86,793,801,69,141,8,71,69,906,8,788,303,457,777,680,928,757,290,21,910,93,116,466,867,331,782,135,875,426,879,871,61,45,659,601,690,95,309,277,601,614,349,901,338,571,93,675,533,46,583,996,156,210,917,818,116,147,973,766,763,740,479,599,763,944,844,771,829,961,5,750,560,117,708,57,887,46,954,764,697,370,550,456,399,282,95,230,645,582,320,100,917,744,699,205,752,191,794,577,891,534,576,733,398,1,512,41,372,637,80,938,449,30,707,461,572,467,868,971,907,678,9,480,409,390,53,943,993,445,994,54,879,508,332,850,25,51,873,707,648,395,705,532,954,298,795,265,495,165,246,110,181,875,462,999,931,239,929,676,403,504,31,937,728,787,769,157,860,496,608,60,341,824,672,594,150,712,926,742,474,831,316,208,744,237,64,295,849,860,0,882,202,252,271,767,733,778,793,593,926,295,604,428,839,690,694,691,937,131,646,881,657,973,60,419,883,738,35,795,910,422,148,261,603,846,287,266,826,581,499,989,270,628,243,929,778,803,496,3,646,637,944,329,247,157,965,193,772,964,585,953,864,476,275,547,205,86,968,328,285,555,502,846,681,803,261,879,62,90,85,738,392,831,451,899,569,745,604,724,406,616,732,74,412,448,459,690,36,6,170,380,632,63,322,777,670,625,950,987,423,334,430,746,459,724,24,635,787,106,317,362,886,61,992,30,720,781,903,909,60,388,124,51,236,624,757,780,420,179,61,264,557,580,451,545,927,586,448,61,359,625,906,418,323,846,393,293,120,55,90,59,104,383,544,387,712,222,214,164,323,974,785,92,976,94,679,109,686,425,996,368,465,551,163,445,13,15,298,536,806,931,541,858,947,486,313,624,564,343,833,22,412,745,306,165,270,496,87,135,217,545,997,914,652,411,568,218,251,341,811,381,147,229,474,960,743,418,186,688,244,641,238,336,712,922,134,118,892,23,387,447,73,256,241,316,406,759,429,16,262,80,804,797,747,27,632,424,477,879,786,216,465,721,888,239,435,273,802,726,826,841,44,507,284,731,498,135,530,67,220,485,238,949,631,375,220,654,782,740,211,290,616,236,244,668,867,999,491,685,631,899,250,543,574,190,779,905,754,177,707,812,792,471,976,338,607,710,91,637,744,339,292,69,467,40,853,764,546,239,800,132,733,17,691,222,621,801,413,425,654,25,557,918,611,41,100,125,365,964,961,791,785,678,386,339,353,445,182,964,281,885,601,291,217,284,469,289,41,73,651,90,534,900,270,473,837,772,179,811,155,184,988", +"778,956,28,301,287,834,224,226,916,902,56,355,669,523,665,665,392,389,25,820,684,357,315,247,593,995,997,557,834,967,106,248,562,865,830,759,127,337,420,79,149,403,602,433,983,338,170,248,84,922,587,836,377,139,879,190,515,264,740,263,216,837,263,754,950,152,788,288,408,256,638,435,834,321,569,549,250,302,458,692,599,424,507,643,653,271,489,47,334,287,524,716,89,110,71,197,461,838,660,289,394,573,872,703,757,284,615,383,139,368,262,275,581,988,897,686,175,284,442,193,400,261,796,961,880,966,114,568,721,823,262,873,589,11,519,703,590,902,790,456,79,289,504,10,422,78,812,978,457,497,498,888,666,3,530,148,33,577,26,731,271,500,959,907,560,938,524,260,887,18,740,418,376,434,2,512,635,208,439,155,432,201,741,897,504,204,484,212,395,18,668,577,754,352,57,768,380,860,466,908,884,146,492,879,537,777,477,825,103,749,745,353,19,124,321,175,318,263,780,910,605,888,120,627,743,165,91,770,574,181,711,38,831,138,924,511,244,16,632,845,61,416,969,417,168,709,559,975,37,681,344,575,401,258,957,204,5,773,198,790,907,228,495,683,477,798,667,36,88,523,702,110,962,140,498,164,237,433,726,972,436,280,513,153,875,117,727,702,492,674,582,958,259,776,702,66,580,834,998,869,103,765,999,535,519,641,329,464,391,272,937,119,805,896,513,788,514,480,714,194,784,65,562,370,254,269,8,771,566,176,726,938,951,134,754,852,940,705,614,898,593,933,474,828,496,260,39,464,499,237,272,40,316,329,422,3,606,224,645,862,170,781,168,961,911,435,597,549,167,965,299,55,817,550,243,201,747,229,646,22,931,53,269,942,620,688,334,210,411,693,845,262,443,872,592,681,544,131,726,977,127,385,962,233,259,829,598,385,12,850,10,338,108,702,451,315,102,792,710,971,740,535,447,409,648,448,233,213,771,379,348,132,966,65,832,284,371,935,993,430,488,694,502,665,519,230,897,215,561,438,461,241,202,164,174,473,567,575,257,597,458,693,195,928,518,234,222,159,929,288,13,376,616,902,445,102,251,109,785,847,511,967,904,385,743,721,650,165,424,869,14,498,501,234,707,243,55,399,801,732,499,724,610,142,460,610,390,470,848,606,801,945,312,107,975,731,659,955,55,307,996,61,561,57,717,698,708,226,515,986,462,968,180,687,445,608,244,987,248,441,435,285,555,634,952,176,568,281,155,714,85,108,482,24,422,589,388,624,437,554,502,268,953,281,527,354,240,488,84,989,990,707,898,710,770,348,377,796,319,29,177,369,814,915,161,216,694,947,283,280,862,516,561,425,943,211,839,896,355,655,524,261,360,919,799,126,942,586,82,775,954,884,251,682,998,628,112,882,0,183,204,572,358,838,779,128,330,387,560,979,853,595,201,598,672,65,721,38,771,338,699,586,413,770,162,638,13,191,417,161,520,432,525,407,84,806,209,93,748,825,571,767,875,611,769,550,598,940,803,74,317,812,961,405,401,922,790,543,568,641,22,100,98,67,48,194,636,800,932,473,420,714,976,477,749,651,671,185,606,210,494,453,191,290,115,468,322,528,407,793,939,730,92,274,564,622,451,870,501,819,42,391,454,41,304,189,123,395,329,887,258,754,975,541,102,15,150,672,781,821,738,607,387,348,691,900,530,225,350,756,303,870,768,28,405,210,203,430,477,837,625,889,781,491,287,816,754,70,258,376,682,916,574,14,793,652,849,181,935,192,616,444,759,633,875,281,252,807,351,125,732,552,442,616,805,311,699,13,746,644,650,725,334,976,538,454,947,763,256,534,716,415,373,414,245,171,677,272,966,927,28,974,362,63,86,276,340,392,970,796,861,567,74,392,302,579,584,511,444,49,309,313,854,933,488,19,427,631,389,906,456,82,139,362,615,997,99,777,208,634,240,825,860,19,326,927,497,637,936,255,786,35,377,195,383,284,754,297,779,77,783,865,337,593,271,354,855,835,983,608,505,781,495,194,990,930,486,205,745,628,724,577,875,99,989,535,527,367,304,897,370,187,416,993,678,460,312,810,171,214,993,10,79,21,700,114,945,29,745,909,235,731,873,983,980,147,292,423,956,961,470,369,721,242,327,981,729,970,481,809,505,321,43,473,502,107,263,571,567,213,386,974,134,615,503,840,690,580,584,610,958,31,268,319,361,461,961,259,896,578,702,407,98,265,965,475,128,80,150,84,427,939,540,752,703,245,326,843,173,46", +"983,210,318,895,178,181,468,983,513,899,960,771,256,243,632,70,231,619,147,502,190,456,927,728,978,869,940,383,826,416,564,585,899,315,552,372,465,530,153,208,750,710,21,446,896,804,794,3,407,996,357,31,647,178,192,747,203,399,566,536,166,654,501,713,580,127,634,986,561,571,552,692,579,824,862,183,695,543,21,783,410,12,54,522,338,965,919,672,813,408,497,559,814,641,954,161,732,940,659,642,448,465,100,412,248,758,920,117,377,507,322,503,95,541,248,884,299,446,629,619,556,453,631,109,213,263,361,436,459,253,170,723,118,342,802,4,423,25,677,518,275,20,923,769,152,83,595,414,36,305,262,621,915,680,445,769,920,9,715,744,288,739,963,93,817,29,328,355,580,334,901,406,23,59,468,979,877,401,435,613,680,475,995,508,793,73,397,657,153,341,740,65,493,189,325,69,610,894,414,413,319,219,80,537,774,663,392,23,330,48,248,6,260,343,859,89,24,507,691,247,619,269,987,677,979,463,461,830,797,308,859,796,627,611,779,615,704,788,247,486,797,354,120,710,957,878,221,523,87,667,726,554,88,231,216,368,9,853,526,394,234,193,343,405,425,938,284,909,392,858,178,284,673,557,283,190,37,879,35,755,245,790,805,625,638,128,342,424,941,924,133,131,814,466,232,260,58,33,764,481,297,661,911,426,965,591,950,472,232,413,891,637,893,556,690,425,200,508,194,625,319,954,945,369,727,877,826,956,403,37,688,252,485,408,227,622,630,372,881,256,612,343,485,714,533,577,379,704,118,169,896,738,482,563,602,613,284,635,251,424,631,372,781,472,554,508,122,52,929,857,239,290,684,969,82,921,29,265,53,907,637,793,186,661,612,31,424,311,797,761,606,532,215,603,469,359,959,467,142,771,746,860,284,369,850,245,924,946,390,797,538,274,652,879,87,239,287,454,836,427,125,54,264,895,23,23,914,732,32,394,554,59,311,430,16,755,196,620,97,35,660,647,866,297,359,925,446,160,471,785,112,901,438,104,537,622,900,256,118,175,813,711,609,64,344,100,178,952,339,375,862,490,446,833,455,63,353,856,521,369,520,785,983,874,112,550,691,847,188,265,501,992,692,472,241,44,417,21,204,934,604,530,523,90,873,680,911,409,711,206,616,107,983,754,555,798,898,291,958,973,385,878,154,597,527,922,693,864,861,241,447,400,742,518,351,289,273,28,230,493,955,655,965,396,745,297,268,898,454,564,352,157,133,429,422,955,121,301,356,288,697,141,889,826,314,735,470,635,331,909,183,984,227,40,657,541,896,576,20,586,250,679,577,570,98,346,933,386,621,906,294,551,579,915,291,474,204,311,815,977,691,366,148,868,521,332,301,244,199,874,131,574,26,515,346,614,803,202,183,0,1000,927,187,639,416,761,795,317,894,32,79,640,896,461,90,309,768,631,59,598,817,643,215,18,98,509,546,504,98,28,137,83,323,321,51,310,724,86,255,334,534,338,52,512,748,499,608,164,357,382,552,438,770,834,299,991,795,72,932,532,372,446,475,139,619,653,659,362,362,303,824,237,305,989,371,739,355,583,47,815,105,700,755,709,577,973,766,975,654,457,180,962,460,15,615,576,771,296,977,187,179,925,339,65,756,263,702,919,704,275,110,821,102,473,158,292,368,767,287,847,370,102,918,830,870,645,797,853,798,569,569,614,760,937,51,560,648,162,811,590,562,782,454,704,441,670,16,899,612,607,745,280,747,499,823,481,902,679,233,196,622,326,340,747,551,131,147,826,108,7,656,870,652,902,591,582,837,291,712,628,817,672,621,224,262,815,908,607,764,977,938,953,169,881,886,247,968,327,644,639,720,443,429,831,907,49,411,460,931,455,874,398,82,142,908,5,119,615,213,621,924,271,887,143,883,655,730,15,698,254,584,81,54,736,932,255,587,140,103,279,304,807,201,766,655,199,4,680,72,585,234,975,961,89,12,880,601,936,244,475,297,672,475,918,230,252,267,774,402,47,509,302,174,515,655,408,21,580,930,81,471,451,811,532,514,245,573,614,683,60,992,117,830,721,252,762,182,164,790,49,737,595,924,555,791,492,671,681,352,423,897,653,911,847,680,831,405,44,989,487,84,563,131,223,50,145,180,730,282,977,462,194,522,37,128,166,704,807,692,698,323,670,219,839,34,795,698,743,7,987,721,529,914,236,383,947,890,495,248,634,99,370,680,387,598,386,859,774,87,32,351,657,695,963,134,119,750,795,858,266", +"201,290,326,295,803,348,914,481,758,116,330,275,318,382,771,843,512,125,349,594,688,121,325,420,655,166,369,979,660,386,221,895,117,861,875,58,705,748,405,236,874,210,748,285,684,908,808,870,338,430,563,976,305,868,321,558,948,806,704,652,194,588,688,989,692,870,77,40,874,7,289,619,524,67,690,738,780,211,578,550,176,555,69,9,412,467,675,709,346,260,970,936,110,727,855,926,293,66,274,108,32,334,749,27,813,242,918,73,494,860,885,348,613,164,290,924,15,441,327,592,982,531,627,865,946,263,499,886,8,716,23,208,217,83,268,864,282,617,523,718,341,522,80,434,614,96,56,776,439,493,303,954,699,400,165,574,680,254,93,48,174,875,727,930,515,942,757,55,263,623,330,186,803,815,366,603,9,240,224,432,758,745,834,471,938,902,515,96,162,206,925,926,982,903,627,227,628,611,731,722,943,360,466,880,365,660,414,118,839,517,962,703,999,364,922,491,417,949,759,983,775,434,955,67,779,893,808,214,393,511,329,427,164,45,744,259,641,415,593,927,865,147,936,729,734,31,425,720,373,391,781,483,231,642,12,261,405,429,959,796,889,428,654,294,545,863,368,645,996,885,260,56,990,936,721,949,187,287,989,74,464,567,279,808,549,188,692,596,297,140,813,336,1,993,746,697,362,874,757,771,816,832,79,302,337,45,20,129,550,834,745,494,908,30,435,405,406,84,589,319,931,114,938,101,13,811,28,596,844,588,675,695,778,106,316,595,565,358,418,518,31,43,794,851,468,420,788,372,74,607,232,103,513,657,126,973,63,641,393,105,237,895,224,173,995,829,742,880,458,632,904,578,807,515,938,861,851,695,983,203,592,82,166,401,98,700,273,476,208,706,775,777,273,419,519,660,36,218,695,441,837,561,927,902,974,883,278,957,364,962,53,917,827,231,628,569,836,342,981,20,247,423,882,426,119,771,352,843,104,166,363,275,123,411,550,803,158,457,506,675,278,975,713,818,254,591,986,399,433,113,733,308,757,780,514,520,665,588,958,557,161,391,953,872,530,104,488,350,112,228,344,906,76,176,152,189,887,229,664,417,463,1,442,328,764,235,377,164,341,192,896,399,388,423,945,127,55,685,499,930,182,487,467,376,452,958,961,693,521,273,42,886,823,472,283,388,525,421,980,608,934,890,209,185,776,659,449,6,671,202,220,100,331,455,73,631,52,54,545,432,430,685,172,465,34,415,220,942,110,527,679,576,774,184,732,325,39,887,513,174,77,62,981,108,235,364,254,365,281,757,321,193,405,637,299,116,847,435,403,472,617,519,690,280,215,138,586,459,749,833,623,205,396,874,255,205,546,988,512,110,758,237,72,66,455,86,169,225,385,137,365,720,747,979,662,786,200,252,204,1000,0,442,742,866,407,951,589,720,73,402,840,746,965,787,444,615,276,212,436,153,730,95,770,644,442,322,172,892,623,797,296,313,195,907,284,113,70,446,129,679,801,480,524,709,588,789,108,996,740,793,896,539,397,271,661,844,697,70,135,410,548,607,236,223,405,609,8,590,592,861,859,623,718,800,949,169,781,128,846,696,688,360,899,257,237,676,497,486,362,744,828,484,757,562,407,675,599,597,818,598,139,104,71,664,770,970,612,390,335,342,663,664,893,585,159,655,890,60,921,979,286,258,729,389,150,612,218,419,840,387,247,560,114,645,36,626,44,536,447,269,415,864,695,387,259,794,618,134,936,499,543,877,986,812,574,668,657,530,590,184,152,174,93,730,390,700,962,972,831,583,752,590,627,476,330,599,737,706,510,54,17,62,658,999,507,809,380,627,728,943,127,659,582,61,4,797,397,380,282,124,83,38,873,371,501,141,697,421,122,837,491,259,563,184,799,923,453,209,821,771,328,607,320,985,418,641,201,327,652,821,25,660,35,889,264,921,985,791,809,888,371,96,713,739,652,645,710,970,28,618,324,898,790,38,232,886,914,219,313,265,918,107,577,85,835,931,841,562,283,846,449,29,637,476,108,917,701,505,75,796,91,90,114,125,4,326,491,413,118,896,907,77,303,409,84,287,116,505,809,57,820,146,538,463,798,909,430,328,707,950,814,484,129,666,115,579,59,181,148,338,462,309,552,47,804,602,967,150,321,549,992,130,852,275,802,89,710,414,368,651,117,713,971,679,958,517,941,137,703,860,745,408,542,295,487,876,717,64,248,600,587,876,500,288,360,911,603,637,21,975,986,987,494,910,266,234,586,640,438,53", +"195,117,928,810,153,372,910,672,766,90,228,409,105,144,541,314,340,732,606,278,735,222,8,15,245,604,351,105,621,742,915,238,354,456,947,511,152,737,540,6,412,206,25,405,670,510,328,598,789,999,830,443,405,306,466,285,105,112,71,867,889,721,129,144,330,33,314,717,482,979,253,840,949,350,862,159,539,904,953,525,804,355,772,663,624,509,493,654,588,986,823,64,542,640,693,50,775,597,859,462,883,902,681,480,67,468,929,462,781,783,5,483,34,401,474,422,165,966,268,342,499,572,60,569,578,139,64,958,413,519,26,712,181,753,563,192,964,44,622,694,632,487,272,813,714,377,952,467,231,487,126,254,430,196,589,491,270,424,804,378,484,599,201,984,861,337,913,637,8,632,165,211,636,708,626,674,384,716,574,200,886,678,360,359,797,439,633,127,82,710,224,451,389,343,343,940,457,322,712,52,604,647,858,933,635,268,884,660,849,105,209,485,899,463,894,477,458,572,109,330,641,52,699,599,2,266,518,303,697,369,954,858,91,840,191,615,277,960,24,129,870,711,765,893,166,119,455,274,925,491,6,465,864,658,189,121,749,575,808,515,547,54,745,894,78,403,819,843,196,719,478,896,899,651,187,537,786,394,344,134,702,936,814,385,144,637,949,27,282,54,290,638,517,564,478,124,885,536,112,39,231,258,669,599,376,522,789,573,291,31,600,945,430,540,454,640,114,801,714,706,512,998,268,243,65,676,86,891,664,223,537,255,341,403,161,458,861,916,340,597,915,923,462,873,93,628,969,343,788,935,832,679,10,541,717,138,527,613,600,347,306,507,245,135,238,178,877,9,828,185,766,762,999,153,868,244,858,693,784,853,896,675,122,907,394,326,417,764,891,848,340,131,773,622,44,252,20,186,942,384,574,240,909,885,753,907,298,200,958,681,514,334,930,996,446,57,322,426,318,998,158,784,847,977,207,754,215,751,681,682,436,445,121,30,255,924,353,322,78,734,660,226,639,663,729,970,52,415,95,290,205,835,21,232,157,574,275,428,870,477,206,254,485,510,839,102,860,856,7,582,939,228,922,727,609,629,240,314,773,913,460,135,864,422,993,178,563,834,842,116,841,787,304,849,331,410,990,933,836,284,211,497,4,944,124,404,181,588,684,22,143,722,583,105,531,694,3,790,453,218,9,266,33,350,516,892,577,946,750,465,348,210,928,124,280,558,854,366,119,678,838,335,702,886,421,5,35,25,379,343,73,925,747,892,328,806,763,945,574,64,600,110,41,319,50,942,160,14,572,338,444,346,870,334,934,545,281,241,106,425,724,707,652,100,825,375,478,889,306,286,397,359,875,100,299,115,277,91,718,639,697,513,92,990,753,805,563,470,101,145,643,604,169,262,837,966,634,271,572,927,442,0,296,184,539,399,502,87,218,691,419,441,297,527,122,442,937,847,623,807,437,746,184,440,458,318,856,100,321,141,520,861,62,319,173,653,498,537,911,709,860,686,319,895,645,892,349,554,549,916,944,471,123,372,894,362,357,241,660,38,827,399,810,268,434,858,790,500,275,762,14,831,73,873,73,413,699,528,559,127,924,550,496,419,773,582,571,994,907,185,294,664,419,30,30,307,608,938,679,409,450,229,278,396,739,368,125,222,707,747,158,985,467,641,144,56,221,522,591,831,459,917,750,329,678,375,801,330,154,669,374,79,993,240,834,355,844,911,771,315,833,869,316,566,43,105,488,853,365,688,627,571,866,967,261,709,307,391,509,311,167,691,562,627,126,73,588,357,115,175,491,691,434,417,71,909,353,244,299,144,719,391,199,386,877,503,797,363,29,472,114,537,368,459,40,573,136,254,716,815,426,304,645,163,311,155,396,623,915,463,250,538,539,514,147,171,739,993,350,763,918,665,728,688,488,75,620,436,533,628,963,667,268,416,973,585,659,504,937,744,392,311,325,493,638,120,832,908,980,408,671,720,827,809,68,330,733,822,919,795,897,510,116,471,43,396,857,200,818,624,541,114,811,117,106,363,436,951,200,619,55,738,862,627,421,386,521,948,395,160,90,970,9,205,828,725,790,402,331,73,58,384,601,931,146,402,140,85,353,779,265,974,603,472,932,530,2,195,219,731,69,996,914,49,651,400,127,619,605,327,202,864,751,297,715,307,201,14,734,479,591,377,138,223,890,503,445,17,363,36,952,61,780,818,127,702,124,966,350,24,596,257,215,530,441,363,651,315,792,211,763,290,541,238,757,877,888,530,703,461", +"905,878,330,239,696,213,885,120,894,543,556,723,214,975,746,103,132,902,865,793,517,964,209,594,919,662,655,522,577,801,760,743,626,816,272,302,511,44,266,811,967,182,410,898,559,710,691,727,269,737,500,425,450,909,532,70,290,285,923,231,610,248,980,247,325,783,107,367,609,822,88,77,271,79,307,412,603,256,55,277,656,414,281,858,844,371,886,99,154,879,109,798,773,8,549,653,247,128,590,83,783,44,780,51,835,991,962,36,995,681,75,303,458,170,177,793,582,557,509,451,303,110,392,979,343,930,541,60,372,178,302,274,187,191,304,361,725,137,385,924,169,285,501,207,362,643,909,661,897,255,971,188,38,888,762,378,28,421,555,3,857,867,104,892,12,441,938,710,328,837,692,97,695,210,903,860,584,5,880,703,385,688,911,736,298,955,857,865,830,356,480,782,792,286,798,131,487,929,224,576,217,957,719,977,933,887,186,727,365,917,184,416,559,729,817,615,690,721,336,54,588,616,618,303,759,636,291,970,175,581,545,767,145,853,974,440,986,829,785,667,178,550,652,773,719,472,993,34,152,355,62,484,340,356,324,9,831,291,342,957,962,678,763,117,814,17,311,398,336,933,669,543,834,817,585,225,207,355,720,519,407,968,788,473,816,272,190,319,157,829,669,26,716,969,422,820,902,857,886,109,594,2,155,96,968,145,154,48,867,67,147,425,325,143,865,333,731,124,311,481,206,120,132,153,521,821,898,127,809,658,154,278,598,201,749,593,246,101,448,563,937,177,416,246,559,958,437,902,686,372,65,295,780,886,743,71,966,19,423,697,845,704,969,226,389,908,2,302,665,942,103,280,574,223,513,715,519,621,945,312,573,338,710,60,611,348,429,579,583,949,126,697,399,846,580,577,756,792,678,736,372,258,407,677,182,254,620,501,917,586,110,173,941,388,735,988,245,754,908,639,350,781,931,725,945,526,588,244,663,374,750,208,562,968,403,696,81,98,844,691,291,137,465,323,962,237,853,503,93,984,758,960,443,840,690,712,191,649,216,727,148,118,926,816,311,388,895,694,155,787,161,557,98,444,413,100,745,334,116,635,716,438,713,658,92,809,723,936,221,626,903,270,727,711,427,212,737,200,879,421,456,701,794,471,464,47,141,995,505,275,456,486,566,783,733,284,999,789,580,119,305,390,891,571,330,511,974,873,136,168,625,616,845,981,812,416,156,455,230,801,663,237,932,38,992,142,999,316,941,456,804,713,480,586,324,432,93,46,836,522,865,417,830,916,724,421,926,747,677,491,38,424,811,86,170,457,31,226,849,368,95,552,90,16,817,700,630,928,509,538,155,912,957,251,314,393,557,685,790,724,303,918,363,11,304,778,190,82,280,708,511,150,982,677,39,920,816,767,358,187,742,296,0,825,856,142,334,333,459,733,391,855,190,54,400,834,956,517,653,452,508,417,853,948,563,49,782,529,594,976,311,520,924,57,39,512,957,502,246,608,164,360,872,734,221,283,491,420,415,206,836,578,952,348,868,624,168,872,492,415,518,13,963,624,455,9,529,481,991,482,216,268,281,210,563,569,703,422,396,67,940,377,886,73,306,90,860,300,150,217,199,641,414,129,409,968,840,785,618,826,79,760,667,22,425,629,95,122,436,159,602,404,83,277,651,23,640,144,788,360,598,293,858,344,430,725,943,102,146,180,861,480,93,398,681,692,830,604,701,27,436,533,257,214,603,626,730,819,677,757,288,802,62,703,428,553,627,501,890,933,798,125,533,948,271,167,208,897,659,358,135,481,864,29,333,225,974,180,998,511,100,257,488,402,405,197,721,367,367,298,197,794,773,36,449,99,323,401,413,549,348,147,589,676,37,241,720,456,203,358,439,193,222,715,882,536,583,947,62,482,351,386,40,176,301,228,979,890,578,696,714,636,634,87,411,188,230,655,639,455,412,700,152,823,36,843,160,780,139,484,232,50,870,166,211,843,235,950,883,840,194,420,330,353,728,608,921,334,350,421,396,579,158,512,783,583,293,139,931,238,512,208,654,400,22,315,555,787,336,222,109,821,500,296,335,807,738,636,737,846,795,381,617,236,87,604,331,27,681,465,265,445,100,237,865,761,804,731,838,718,96,346,828,774,660,706,110,350,559,44,306,103,419,326,215,724,903,123,781,581,761,486,458,774,588,986,638,13,214,584,154,149,609,496,337,416,74,961,405,189,445,423,954,317,718,318,13,591,725,781,941,324,107,923,129,803,830,271,798,829", +"670,725,987,528,80,48,11,18,541,821,994,183,174,109,729,308,703,704,835,702,850,431,346,457,338,483,8,814,39,307,635,590,4,577,329,895,758,812,643,282,200,140,306,257,375,190,889,325,830,827,928,846,644,982,652,76,787,582,852,120,899,801,990,34,83,237,231,258,791,250,606,36,97,267,895,944,978,880,811,605,445,566,346,477,456,923,886,822,562,336,350,117,145,409,561,23,958,955,463,272,943,836,653,157,216,427,986,806,518,852,261,591,101,106,691,851,959,348,192,579,199,546,666,989,502,200,618,268,292,180,821,886,257,737,127,679,3,435,800,301,753,711,614,153,634,536,292,788,793,450,799,603,965,428,776,600,488,345,784,532,934,5,665,994,779,346,804,402,295,562,149,670,917,417,967,198,768,300,623,904,517,138,242,660,475,285,339,763,879,605,704,303,175,953,16,744,542,69,156,354,412,754,784,402,930,116,650,600,702,29,563,42,778,752,909,19,390,52,120,308,511,26,806,346,852,236,25,720,72,888,904,88,642,326,199,528,300,486,824,240,61,903,147,151,951,600,841,770,746,884,699,819,519,57,588,472,373,902,452,447,858,246,384,987,652,654,965,221,632,747,678,834,998,199,324,919,359,973,466,345,416,81,375,247,883,942,346,909,508,31,563,408,94,927,10,962,656,818,680,239,597,177,216,747,397,570,496,737,393,110,457,382,125,940,118,636,470,991,299,664,630,617,251,593,697,687,576,899,877,598,470,73,882,266,288,769,901,711,343,342,119,198,652,619,222,473,224,873,794,628,705,725,282,192,88,331,80,461,26,469,284,504,185,25,155,402,427,737,282,438,602,333,956,83,667,406,90,370,690,886,25,308,603,34,244,212,327,279,109,208,789,43,455,562,441,415,473,315,973,639,773,553,214,878,421,170,871,856,224,591,416,320,42,752,944,718,592,932,3,934,199,879,338,83,466,730,304,75,875,918,279,455,676,429,4,493,833,636,521,514,794,273,66,799,250,896,810,327,475,793,128,88,286,209,51,136,30,203,251,209,965,189,880,976,702,258,948,464,423,433,527,218,401,797,427,128,69,858,338,259,433,822,377,197,841,904,832,454,810,494,831,293,199,962,235,204,431,914,36,663,22,718,245,402,79,309,254,62,375,465,707,925,492,715,252,8,188,426,200,357,571,931,846,636,975,204,731,711,161,431,14,957,426,8,573,505,667,96,35,205,86,534,247,218,197,226,539,686,545,206,358,31,442,439,843,829,629,841,480,271,110,831,728,211,692,995,703,427,194,466,225,409,533,399,931,664,981,978,893,640,947,586,976,664,848,624,91,400,535,273,103,409,728,952,960,530,564,70,852,665,276,466,988,52,835,813,470,334,401,466,327,158,901,509,327,593,822,733,838,639,866,184,825,0,775,785,386,707,247,740,662,709,622,518,93,819,356,472,993,516,706,967,131,720,710,898,851,65,810,974,797,739,517,367,477,93,448,172,686,852,99,653,269,570,166,721,939,764,8,351,18,749,809,441,253,406,184,957,287,650,475,626,766,249,508,866,778,699,625,609,449,890,878,576,700,615,784,996,408,83,727,111,593,36,253,198,196,291,279,111,729,987,734,482,53,171,591,310,55,56,320,974,814,319,281,661,979,448,691,839,698,114,273,124,951,627,76,253,77,165,474,679,871,295,687,108,367,888,288,636,308,731,293,337,949,274,983,682,38,711,769,600,900,171,733,739,166,317,980,219,84,119,676,67,115,894,664,257,323,370,277,256,867,386,289,415,653,410,322,914,181,768,231,674,834,104,398,692,844,386,161,49,798,618,739,548,332,137,614,864,868,611,720,927,76,550,136,619,280,307,9,225,759,340,304,347,159,362,874,563,702,507,629,435,180,461,51,362,151,691,217,436,782,990,212,390,520,769,848,987,403,671,612,391,722,970,43,328,98,996,242,778,166,144,143,197,411,31,168,300,928,291,648,809,731,683,743,614,306,289,176,382,149,72,991,272,842,681,224,802,227,547,668,978,890,215,742,257,142,840,587,890,11,255,826,333,844,644,900,119,221,924,549,58,32,983,24,755,139,478,953,616,676,931,431,829,81,193,725,806,375,425,563,885,335,483,574,483,649,381,912,748,326,171,644,99,90,933,839,998,961,878,885,443,161,197,242,647,550,922,857,382,539,839,616,120,837,822,81,345,780,776,75,475,648,867,110,426,907,918,966,624,651,281,151,597,182,820,982,879,27,488,137,31,427,994,152,96,777,892", +"313,758,173,531,791,903,85,750,793,211,211,481,381,919,590,67,350,344,885,357,457,503,848,678,270,416,21,551,283,936,35,822,898,934,571,104,395,65,486,893,797,422,600,846,156,16,775,353,30,866,18,306,171,633,822,658,741,881,305,658,799,571,824,673,461,822,601,14,27,190,137,376,278,145,401,590,702,881,894,825,157,959,685,397,670,690,173,721,720,157,967,63,318,572,608,46,277,218,808,140,103,238,670,900,572,191,67,881,499,460,146,503,219,769,51,590,567,656,73,496,548,932,364,347,538,21,409,304,90,325,142,67,966,282,776,951,896,367,949,98,589,323,277,685,597,755,613,902,968,569,31,555,499,626,70,240,634,920,741,613,251,457,758,902,630,692,948,626,885,35,950,492,912,783,47,204,355,739,970,335,371,771,843,923,309,294,592,631,84,198,913,290,158,364,290,511,10,426,975,894,294,906,639,284,771,691,98,242,502,403,82,219,299,631,930,349,660,479,722,124,421,282,725,899,747,296,170,506,949,94,596,870,173,212,634,268,481,979,746,378,671,788,75,959,896,238,601,824,372,711,977,806,642,444,560,450,607,787,212,642,984,737,262,202,932,875,581,743,511,398,211,626,584,726,512,932,379,96,110,792,953,609,324,538,9,546,303,993,574,902,881,380,828,682,589,621,740,728,165,159,456,156,313,109,565,306,310,352,159,541,675,940,259,357,371,348,906,699,688,273,706,777,194,842,114,661,657,576,651,747,905,342,985,60,65,197,429,641,264,805,331,884,805,598,753,800,235,536,172,795,905,327,784,837,767,921,525,48,958,934,319,864,342,300,336,912,51,895,167,66,51,240,845,161,54,97,124,955,103,750,888,674,8,372,686,195,330,617,297,971,833,662,741,303,35,364,739,992,278,607,28,168,520,627,267,482,867,23,333,314,618,281,111,913,409,881,652,15,735,515,560,737,132,92,623,398,406,777,86,411,248,300,131,636,81,179,740,798,530,33,936,157,436,206,631,745,937,198,694,341,484,731,237,6,992,141,235,444,601,558,972,405,396,602,528,291,619,238,789,30,856,893,727,803,561,688,637,612,206,762,33,458,556,144,776,355,269,428,256,504,537,772,360,908,46,170,415,745,419,629,974,278,398,466,230,267,263,215,616,475,858,892,377,972,82,618,94,852,953,450,921,927,588,840,715,231,963,603,969,737,348,750,817,382,9,420,801,822,542,875,469,172,205,594,767,940,361,591,652,181,3,742,596,277,506,567,992,808,217,221,87,732,741,536,968,281,825,61,459,538,508,479,456,147,375,994,612,194,715,919,170,552,839,663,512,865,536,615,412,432,472,691,993,961,602,674,912,791,130,761,545,376,708,343,986,135,415,136,423,89,720,813,442,741,855,145,552,778,779,416,407,539,856,775,0,288,160,61,486,996,929,475,663,351,944,819,351,285,848,704,708,959,743,736,845,490,48,908,65,369,121,720,317,242,262,302,498,623,554,837,880,915,679,36,631,971,403,856,603,42,81,579,969,833,322,879,626,291,654,422,278,623,630,420,999,300,729,932,763,599,972,790,247,752,662,617,296,395,989,157,868,138,681,816,595,645,254,67,102,82,122,952,858,504,706,264,671,952,228,360,331,945,579,151,906,667,177,525,241,912,829,544,646,238,616,523,221,771,467,84,46,411,954,460,206,366,706,887,206,299,416,143,346,265,251,636,418,382,24,678,373,576,491,469,75,287,701,312,126,243,117,892,939,668,638,118,565,864,37,447,461,265,438,975,790,688,610,772,457,635,143,339,624,799,838,595,258,248,514,63,105,379,421,11,967,658,925,646,191,219,646,354,150,628,698,854,156,733,276,197,304,334,493,327,427,320,848,835,30,879,197,106,722,120,746,758,199,549,558,788,752,5,342,951,234,261,282,717,176,897,137,137,752,446,477,948,340,807,288,637,405,500,935,436,352,499,78,794,941,63,92,520,418,59,679,146,761,762,918,994,519,772,311,286,709,322,414,635,735,810,189,699,355,371,883,202,985,573,999,390,691,437,64,516,858,289,7,496,864,375,752,505,738,932,123,156,709,872,849,55,975,319,261,408,392,694,905,196,244,136,915,530,901,860,258,824,357,19,249,91,66,450,664,742,231,187,807,11,754,545,76,796,806,758,131,219,30,208,638,844,244,626,850,835,181,663,959,891,805,405,996,131,454,573,782,963,182,518,372,935,364,656,432,124,159,165,711,148,900,532,127,142,761,730,325,881,592,513,667,761", +"555,453,553,733,526,74,168,538,542,649,800,579,730,467,757,913,254,935,158,689,879,518,301,445,997,198,981,699,439,49,148,394,109,703,169,814,360,849,612,427,824,626,419,776,986,581,781,153,755,986,765,47,322,266,265,711,489,460,397,333,735,258,564,277,66,678,479,711,618,66,776,517,676,975,985,500,180,999,777,486,939,617,754,360,70,751,33,527,935,754,490,199,541,797,93,155,157,866,439,145,863,255,734,475,801,378,13,968,475,244,411,912,291,470,744,209,492,655,312,508,645,497,862,987,578,339,159,560,180,388,792,962,693,36,336,697,94,957,21,686,26,401,341,949,651,462,453,774,894,874,902,903,284,26,744,911,892,794,957,86,469,413,985,649,889,445,216,231,767,473,991,987,612,733,69,645,933,754,75,577,401,37,540,354,762,372,957,80,473,705,874,944,225,194,108,857,107,230,941,776,798,99,818,368,626,475,155,937,617,900,268,532,902,364,462,964,804,382,192,415,298,461,376,190,602,531,348,918,538,195,869,668,917,323,58,129,192,387,169,909,100,538,936,600,819,869,705,3,525,240,352,647,651,909,159,914,96,553,474,89,151,597,644,573,908,569,168,965,613,469,79,802,186,97,470,194,129,374,355,372,319,155,34,998,928,313,500,258,652,589,891,344,986,293,385,60,921,359,65,30,232,753,478,125,621,280,471,876,292,854,926,635,400,79,262,889,326,660,770,35,148,655,940,351,736,826,904,690,441,94,603,729,287,255,112,101,786,180,728,392,525,705,705,363,968,317,902,77,974,89,279,206,668,518,318,240,281,275,785,440,737,129,940,485,59,351,710,8,284,32,786,516,473,528,126,776,82,6,566,883,271,92,326,903,240,853,540,224,483,705,708,341,748,335,486,54,176,873,946,904,248,688,848,784,782,861,225,749,642,879,560,360,910,740,751,868,903,985,567,256,396,454,865,430,983,423,206,729,684,422,162,924,669,661,914,31,941,6,381,667,602,615,593,154,466,641,189,198,172,988,540,219,935,889,367,320,728,548,251,954,432,587,496,875,407,123,372,745,366,795,244,402,115,844,86,27,311,504,676,858,952,197,818,873,158,830,413,47,348,104,343,133,724,484,500,55,771,124,536,635,307,151,537,887,969,318,148,129,778,810,285,312,751,193,443,973,237,583,5,828,826,321,360,393,591,454,347,724,275,625,364,989,599,807,652,56,78,38,527,809,292,878,468,449,69,273,392,271,712,469,937,797,694,360,263,204,448,397,872,752,584,746,375,423,855,3,122,106,715,53,191,522,936,54,842,859,603,708,322,817,824,896,427,241,252,464,260,441,129,316,857,425,187,797,142,796,259,906,386,342,193,103,591,906,569,494,41,990,621,910,905,69,903,916,765,605,957,793,128,761,951,399,142,785,288,0,245,635,906,580,678,689,467,261,548,946,914,243,966,474,36,54,464,659,23,924,393,434,336,163,107,40,135,737,974,733,935,143,192,102,925,147,192,665,906,52,851,785,613,182,853,996,334,172,386,243,137,846,769,793,851,999,889,754,375,737,210,267,620,118,958,641,456,894,271,269,438,963,458,68,457,88,252,270,779,494,531,822,183,427,21,39,142,49,421,782,658,976,208,831,410,714,811,754,544,812,441,422,306,134,139,120,102,941,329,911,943,4,724,543,925,247,159,174,782,343,295,254,276,680,231,770,801,396,977,874,496,384,551,180,475,72,383,301,477,373,972,31,188,734,995,200,273,481,781,446,539,273,811,478,858,240,434,952,464,261,30,990,578,906,80,32,241,599,717,363,949,953,503,530,106,712,432,792,129,215,106,195,394,452,478,603,808,671,477,897,388,317,405,568,145,542,906,247,164,766,968,635,782,650,286,706,221,508,844,376,295,984,848,927,650,177,965,821,58,956,36,585,500,835,564,502,12,921,656,17,526,179,24,382,503,443,58,217,945,998,375,868,641,222,630,428,344,642,458,455,52,630,850,323,545,34,781,562,248,720,659,963,452,17,125,372,115,654,829,486,711,579,398,109,843,198,165,26,729,802,88,108,238,814,953,148,965,650,543,664,810,813,770,641,911,550,801,772,804,279,919,392,826,503,944,260,814,945,862,474,84,271,831,23,568,206,365,872,353,79,386,349,627,572,768,564,259,997,587,137,202,540,765,826,761,399,856,957,955,478,319,107,785,557,471,61,312,468,890,760,352,374,916,782,493,472,737,600,884,752,314,379,982,740,858,904,574,615,938,955,949,73,837,428", +"762,652,181,988,923,969,3,756,433,562,573,966,542,435,63,96,832,736,895,959,614,651,624,206,186,971,280,979,380,33,672,644,943,220,894,50,437,196,617,297,631,937,919,535,463,804,90,19,875,452,130,406,808,881,840,348,27,208,407,517,506,853,339,386,655,523,872,870,378,484,621,10,645,128,263,323,90,300,563,313,399,788,694,787,179,477,538,548,668,968,224,113,224,791,559,525,20,509,372,433,186,576,303,711,288,668,665,571,195,137,452,384,431,700,643,444,713,251,454,19,887,682,914,451,380,87,990,202,969,33,284,105,46,360,250,247,36,262,508,927,704,914,266,679,778,676,561,887,528,366,575,180,86,613,316,408,351,716,313,229,598,692,838,123,937,590,141,491,453,26,546,879,67,443,917,668,88,233,805,446,853,440,127,355,988,237,607,445,97,795,951,171,528,561,883,209,552,411,511,640,495,311,258,670,514,559,654,735,601,505,455,52,487,47,635,837,463,262,287,251,510,541,293,372,898,772,476,832,332,320,29,347,527,368,58,681,755,955,754,721,755,403,428,809,251,370,276,125,485,970,593,596,229,365,484,151,927,538,859,754,73,812,494,967,963,323,205,609,632,820,82,721,776,672,74,9,192,289,881,583,809,792,420,153,137,757,757,904,524,613,425,938,806,589,615,64,116,878,910,363,512,422,416,812,321,476,688,893,276,964,906,907,620,107,203,231,966,424,135,103,405,878,917,903,163,550,106,955,738,751,811,864,816,644,361,514,860,392,828,5,914,762,751,615,899,618,639,562,566,137,490,836,354,491,441,151,984,521,229,580,950,963,90,200,692,285,207,38,776,984,217,226,498,109,241,919,747,950,895,426,90,768,890,299,47,338,750,365,11,150,481,368,549,56,554,282,811,761,78,740,149,690,756,363,288,749,703,711,814,585,426,160,842,209,371,768,538,973,57,898,391,172,317,76,218,452,274,374,929,789,152,973,826,753,346,767,494,790,901,711,322,159,869,549,70,665,183,983,629,712,267,803,889,708,433,725,413,49,231,347,879,923,526,280,20,592,317,988,491,784,51,918,968,378,410,723,826,529,801,250,865,603,429,306,143,978,918,721,713,213,86,581,209,182,837,409,529,78,185,66,242,709,70,238,774,571,668,815,353,390,647,668,65,77,587,278,914,633,509,673,986,65,136,63,921,682,315,209,185,299,394,435,125,233,570,763,46,720,989,80,164,565,713,190,621,593,414,154,311,574,321,255,933,945,231,601,727,867,290,180,171,253,484,728,602,77,581,160,410,773,246,275,511,919,581,976,898,849,961,820,776,855,851,154,933,830,566,386,639,239,750,396,629,816,518,304,206,130,492,41,707,856,136,600,943,174,940,854,312,425,559,544,442,792,519,238,476,593,330,795,589,502,334,386,160,245,0,124,434,644,493,55,721,44,922,35,948,115,933,107,429,983,600,462,161,644,875,428,678,518,744,74,783,649,356,135,721,356,574,688,557,711,367,567,358,955,973,266,991,737,628,441,143,685,342,436,159,173,41,300,123,401,60,997,429,789,165,329,30,70,301,597,600,329,496,722,17,220,96,261,60,560,625,116,661,202,108,68,940,119,117,72,513,197,382,666,785,891,602,356,533,777,270,920,581,792,321,945,549,546,748,727,902,762,329,329,408,176,680,856,344,421,231,689,232,794,729,927,130,93,20,824,846,651,657,522,675,154,542,103,960,274,155,715,590,336,404,199,111,295,696,367,509,980,872,710,33,545,369,158,545,835,531,886,480,708,891,691,232,11,548,47,825,675,848,38,134,950,885,254,959,397,299,428,803,950,52,381,706,773,677,296,649,753,757,836,791,697,645,642,299,429,615,405,816,524,705,314,512,297,384,985,386,158,93,177,238,895,831,569,7,703,884,863,847,252,801,877,17,120,481,61,569,644,780,156,276,621,934,637,614,444,9,586,17,344,959,207,868,638,94,222,904,985,220,556,530,237,348,685,561,977,423,943,411,217,110,811,453,760,116,430,225,114,175,317,454,345,468,896,680,245,926,300,752,580,901,81,892,530,735,543,802,260,272,923,807,674,932,546,743,568,52,210,670,543,106,120,321,839,251,336,86,797,560,964,278,804,205,656,648,488,547,7,257,750,552,392,291,819,244,430,537,35,956,264,238,659,824,441,861,537,587,276,506,22,198,808,735,37,25,686,272,144,218,920,598,253,71,567,355,701,207,983,633,267,672,796,182,318,559,829,105,407,934,587,144,680,867,478", +"962,41,402,941,824,145,38,455,208,588,260,600,115,826,180,326,994,895,453,138,570,699,388,503,719,719,888,252,511,20,95,154,940,63,386,435,39,233,496,309,406,465,445,602,642,747,283,45,828,818,224,589,147,288,681,941,637,405,928,336,482,772,12,415,509,444,478,954,715,191,182,89,246,793,720,867,522,611,264,68,106,695,619,391,805,233,316,766,107,601,378,914,261,995,897,717,761,604,736,164,788,306,354,934,148,955,433,876,473,469,573,12,107,147,943,600,284,242,613,327,655,381,529,955,401,95,37,532,677,915,510,634,484,273,992,553,243,863,748,265,980,390,632,580,148,966,983,854,63,735,43,70,45,674,367,668,443,559,294,140,472,244,617,530,999,832,194,437,949,354,476,373,527,661,120,985,558,202,205,727,152,341,333,779,688,77,92,659,811,648,685,663,419,962,55,308,932,12,758,201,428,990,180,288,871,130,764,117,815,222,291,387,869,942,741,821,156,450,486,855,596,295,344,811,451,377,177,123,675,784,77,417,612,188,503,947,423,823,128,511,321,603,173,737,937,113,690,22,679,995,763,968,48,629,594,717,210,641,133,322,714,982,129,165,811,788,26,283,92,134,41,318,451,883,976,211,262,998,90,571,876,736,865,360,939,656,246,217,822,643,25,319,639,461,773,674,398,630,183,591,612,492,634,495,355,767,303,854,131,998,393,231,570,147,371,733,46,284,230,585,530,274,914,112,645,939,364,974,648,228,376,757,331,67,290,186,713,428,206,422,534,786,506,912,857,262,107,434,478,139,330,619,66,881,590,429,862,218,62,328,882,461,802,649,916,611,687,898,88,107,313,768,26,540,809,477,953,374,185,460,220,636,996,495,895,861,819,198,880,47,561,683,850,760,346,196,97,238,15,230,261,515,924,215,226,889,926,206,234,467,415,905,440,190,650,221,929,481,266,770,696,191,547,867,426,937,397,633,5,492,862,783,266,52,207,371,538,74,588,460,782,695,948,776,340,285,127,407,625,449,971,897,796,271,392,732,936,192,533,232,983,519,247,553,86,688,675,365,435,583,439,657,272,32,326,458,79,12,346,884,241,298,469,889,275,913,874,85,304,760,424,810,875,479,648,631,975,908,892,384,668,660,710,850,478,919,11,940,464,643,613,863,865,970,821,529,963,526,772,7,967,269,877,234,455,781,781,326,172,320,448,312,3,988,352,966,86,652,910,111,431,322,684,985,851,111,355,720,268,587,146,387,389,238,695,558,344,825,582,908,97,135,453,158,323,26,792,180,496,961,608,205,618,240,310,606,630,428,897,513,115,220,707,644,294,104,116,642,703,519,237,520,99,200,218,731,318,981,795,496,37,116,814,758,358,53,875,751,267,685,263,783,122,860,601,173,381,926,387,317,720,87,333,707,61,635,124,0,479,597,404,716,867,870,183,77,932,345,187,818,318,133,842,156,209,509,804,650,2,543,948,528,404,388,70,401,97,91,296,376,191,934,616,873,143,200,831,343,207,625,610,862,250,269,36,980,872,921,360,768,929,459,792,169,315,720,764,562,643,52,818,800,66,797,917,991,821,854,814,495,713,159,421,328,813,291,625,838,218,179,408,239,826,743,272,318,953,131,746,709,592,769,462,735,429,109,576,171,270,836,30,922,190,69,655,455,774,732,175,140,263,595,954,56,632,471,705,117,501,48,196,258,27,544,505,162,780,802,804,128,534,711,297,490,568,165,908,571,946,526,403,180,521,17,161,185,81,743,488,725,761,32,429,711,625,699,917,382,546,743,155,317,90,622,707,437,741,883,459,722,890,595,9,395,495,314,439,945,25,449,127,514,320,164,688,656,378,71,135,419,512,401,130,677,872,530,712,849,891,292,552,267,864,38,96,147,483,97,51,337,214,431,205,514,674,46,427,781,289,390,307,96,619,151,69,911,518,967,699,347,243,427,578,793,747,762,542,127,354,69,475,896,820,111,899,805,199,445,359,31,662,353,253,789,393,14,847,940,57,909,773,604,208,971,64,545,258,364,297,913,965,782,698,821,159,463,927,401,976,868,616,621,131,421,181,568,473,931,828,231,240,16,588,578,461,705,335,82,842,236,267,230,759,102,508,229,626,669,505,136,903,694,351,738,118,816,947,986,769,589,488,120,595,13,656,751,431,107,716,729,734,181,673,378,125,119,141,46,616,21,590,39,119,225,995,244,406,660,287,450,423,755,508,896,388,138,821,597,824,982,901,565,856,509,751,773,24,839,773,445", +"212,207,156,654,658,406,823,860,479,773,853,165,406,730,546,854,708,59,707,231,631,779,87,360,170,311,266,737,756,842,851,348,707,955,921,781,426,107,50,292,182,273,905,567,143,615,322,669,697,646,371,67,708,560,287,951,94,103,608,906,103,164,232,310,129,653,316,309,889,980,240,425,710,817,190,176,795,654,770,416,439,253,729,178,134,396,116,326,535,636,85,863,225,329,406,12,60,24,966,407,94,430,993,957,201,100,629,720,140,782,470,27,661,518,144,517,294,916,908,687,508,689,32,749,244,444,780,151,371,359,447,690,429,705,813,812,483,247,955,644,883,784,450,949,387,895,991,975,900,841,550,551,980,513,490,907,884,651,275,798,239,552,572,269,320,394,712,960,233,343,416,261,351,989,148,90,975,307,395,826,292,522,819,275,752,692,794,112,131,768,905,247,59,36,896,901,367,739,451,332,226,995,733,799,343,815,258,1000,802,815,608,950,487,869,821,354,43,52,391,174,489,43,126,884,341,238,516,791,494,94,989,267,314,619,910,79,147,79,213,706,72,106,764,54,904,875,717,447,580,880,350,892,636,390,801,338,768,465,860,137,804,388,322,291,243,564,607,969,879,102,403,700,9,62,63,814,630,737,345,967,697,89,523,762,719,742,583,864,7,9,759,149,972,78,80,800,956,480,519,373,133,556,301,180,163,536,177,154,521,115,131,829,316,859,844,436,14,359,810,675,395,559,146,160,444,646,143,567,588,655,319,749,648,930,25,931,637,126,318,836,795,459,189,637,150,984,297,625,61,210,417,851,557,802,420,439,114,262,290,862,306,594,532,740,32,913,664,46,942,989,932,484,167,508,128,914,872,649,366,973,598,50,941,514,859,727,731,291,705,229,38,101,387,331,129,613,648,133,119,273,711,349,774,362,364,316,937,155,56,360,973,360,185,877,766,244,7,166,893,296,148,195,787,951,951,711,781,517,975,218,188,743,975,577,485,647,853,839,296,855,752,84,41,212,450,138,749,335,40,629,943,752,643,894,210,628,535,797,377,708,591,990,61,600,650,189,384,701,205,524,402,329,138,438,502,333,697,921,587,275,85,311,416,465,243,41,966,117,306,423,655,307,413,355,89,726,196,453,339,530,26,240,244,772,345,916,536,954,45,394,219,283,797,629,799,841,554,887,237,5,566,738,373,491,590,163,561,985,155,69,291,679,725,374,411,199,809,583,444,862,433,988,946,970,428,747,293,914,246,171,715,59,385,435,277,552,286,110,599,63,121,704,685,563,548,729,425,168,14,544,99,129,983,454,439,432,799,600,681,333,689,569,3,480,120,775,568,896,98,835,446,801,768,408,60,506,253,688,73,111,732,974,53,512,497,236,596,257,946,220,796,753,10,380,776,242,927,295,560,894,73,218,459,247,486,906,434,479,0,944,317,820,87,579,373,487,550,478,461,260,633,11,954,152,76,794,938,923,598,421,898,310,163,55,88,523,32,987,385,733,423,647,696,489,20,303,918,852,574,120,931,812,635,552,754,441,727,850,431,78,468,839,628,513,102,140,684,872,517,233,823,170,754,726,845,313,830,750,341,664,326,295,922,692,208,62,9,483,969,167,782,168,464,546,120,274,961,166,128,161,764,39,981,337,142,529,782,951,851,687,876,337,946,578,421,822,42,393,575,290,829,798,585,597,46,522,760,768,893,85,75,973,703,785,475,875,114,103,100,991,851,714,758,241,254,568,166,489,262,295,910,780,463,672,667,686,341,29,18,440,221,692,339,851,651,707,593,751,256,233,281,564,531,332,791,124,900,49,919,189,90,338,404,422,110,227,577,736,935,857,553,104,212,276,915,951,759,575,648,20,778,905,401,158,291,220,334,531,208,847,457,4,945,19,183,916,968,748,302,553,423,257,901,660,383,884,361,97,39,691,183,401,50,333,650,316,778,63,218,349,199,953,939,432,364,494,825,791,808,561,617,807,626,635,225,408,61,200,787,941,610,931,552,565,972,371,673,529,23,893,359,912,452,267,820,382,676,281,443,273,323,778,692,51,173,198,342,980,721,736,868,957,406,692,938,241,603,429,313,322,537,672,158,582,878,506,860,311,984,970,759,323,924,998,460,367,515,915,69,727,580,911,880,99,652,267,829,847,907,704,297,761,872,203,803,559,631,423,820,696,504,958,174,491,165,724,737,798,124,93,411,824,304,380,111,214,158,210,737,828,462,601,909,247,357,972,123,622,405,354,676,273,134,592,951,195,557,16,870,759", +"311,144,163,334,602,485,572,98,441,349,513,876,813,142,734,224,841,258,658,585,197,531,480,989,593,972,338,42,856,935,807,454,610,91,16,30,89,810,959,552,202,127,900,306,433,408,78,281,22,432,420,579,802,338,388,204,416,617,150,272,373,322,828,787,818,53,54,712,415,902,924,938,912,614,773,758,627,49,310,667,774,48,829,454,581,380,446,988,965,579,913,296,922,233,774,769,375,89,763,839,392,306,937,417,910,153,635,216,487,115,136,427,964,830,316,995,163,449,180,659,483,990,559,855,387,84,349,97,973,793,903,417,641,829,646,575,393,40,216,407,889,437,844,761,208,329,516,54,406,64,366,482,330,102,340,661,91,265,689,241,491,358,14,472,491,226,582,108,547,526,136,181,926,244,299,384,459,471,735,469,227,438,611,332,317,798,580,223,272,872,677,194,717,126,830,105,939,171,306,552,872,967,33,199,823,907,338,536,895,593,300,149,622,692,873,718,784,983,37,741,677,466,973,304,868,705,298,321,976,969,705,840,439,448,82,651,373,903,128,152,168,66,899,965,924,89,718,212,502,920,653,955,199,563,990,237,477,143,916,318,809,795,880,388,972,958,251,677,136,13,181,994,123,963,581,127,743,515,740,516,510,712,186,384,951,393,360,119,356,478,992,781,615,752,174,938,133,428,299,741,980,600,370,570,370,263,358,876,711,69,126,892,267,599,753,846,49,667,181,960,999,628,317,78,316,804,4,107,850,946,352,816,35,134,456,350,451,813,781,48,801,110,878,579,913,289,500,301,373,665,447,327,363,707,467,529,70,179,429,379,821,919,493,744,355,612,899,307,440,160,36,740,880,732,18,567,654,351,115,50,670,551,139,472,971,966,232,313,728,986,640,562,995,677,392,131,364,846,303,265,144,414,128,481,354,812,263,875,988,433,749,382,312,779,266,70,94,718,990,405,761,999,280,670,904,966,632,462,399,158,88,837,766,462,369,660,793,307,698,503,984,971,222,921,763,885,348,511,430,147,71,316,885,795,719,202,659,352,339,955,621,61,845,715,575,759,753,535,484,905,646,351,486,811,469,973,799,623,268,217,499,280,122,336,834,23,959,342,958,452,233,493,175,894,903,785,710,230,84,686,455,633,414,236,180,852,995,308,77,844,594,911,313,286,889,359,909,388,607,935,454,601,302,31,413,357,339,220,766,39,11,827,926,108,18,426,67,502,431,99,917,434,253,43,288,290,238,589,346,272,617,812,720,147,125,646,55,13,209,408,801,802,47,143,962,219,798,736,204,411,73,873,783,229,433,624,173,965,108,197,174,655,355,411,707,86,458,776,476,104,355,765,385,710,543,309,896,522,361,739,51,676,926,982,409,753,325,858,825,584,26,404,46,111,682,685,225,604,979,32,402,691,733,740,996,580,644,597,944,0,264,589,983,43,887,919,142,170,775,727,320,338,882,427,496,818,217,330,609,446,347,789,93,524,644,312,651,376,990,359,1000,93,395,638,76,371,606,329,530,946,604,870,195,942,502,374,648,541,528,679,228,893,4,328,265,388,975,692,286,937,879,303,97,125,895,365,724,516,966,271,113,634,189,617,738,225,541,598,388,146,819,82,73,770,658,43,237,522,276,640,583,541,670,242,567,162,203,531,998,933,42,263,888,468,723,384,292,599,123,315,639,826,917,124,888,544,615,484,59,114,865,744,727,80,375,233,520,12,967,452,174,150,230,676,944,442,10,569,730,993,161,702,94,690,546,129,400,719,129,527,921,49,800,121,521,762,596,372,610,226,499,124,481,931,532,752,918,331,513,438,296,67,43,499,280,396,906,980,946,501,49,600,415,864,236,753,951,615,258,698,173,154,914,523,289,122,66,740,856,791,745,323,215,409,144,637,246,477,863,684,240,206,897,797,880,370,824,118,571,841,94,172,702,238,43,387,423,967,296,464,954,144,800,868,757,29,710,365,876,570,844,243,602,380,99,521,920,207,401,404,468,920,26,444,917,411,706,453,87,434,653,385,90,700,376,790,459,513,906,553,699,271,944,754,910,992,776,373,616,912,418,364,230,290,584,829,145,144,436,397,757,457,463,617,520,444,625,581,91,257,776,292,441,462,508,975,71,311,709,987,77,123,571,602,693,674,444,222,935,393,444,709,599,454,239,354,599,336,520,307,764,485,774,797,166,186,813,729,578,277,838,150,580,866,979,892,433,628,924,454,721,522,374,466,56,414,287,544,592,98,408,11,342,508,257,958,868,543,415,561", +"572,162,331,9,86,253,915,431,256,388,520,667,47,796,233,542,734,216,120,754,974,588,798,695,500,166,320,395,374,570,579,173,780,610,469,831,53,690,232,986,135,136,526,551,13,32,315,493,723,519,3,232,8,452,83,778,308,388,289,318,711,474,649,930,571,317,893,216,276,552,250,431,981,380,518,27,921,643,863,727,768,706,518,328,295,453,32,376,19,850,295,254,506,119,757,128,124,614,365,12,172,499,135,622,397,347,630,895,596,413,726,461,164,872,867,444,219,414,499,191,103,359,774,450,765,835,418,962,636,899,928,863,278,989,175,939,190,570,347,295,457,386,412,26,142,545,43,964,920,80,462,559,652,604,971,961,137,969,401,678,573,671,22,920,67,410,979,148,544,667,869,435,524,938,15,671,105,550,999,587,683,152,15,144,180,90,450,947,120,981,691,66,59,100,417,229,203,989,801,994,198,582,119,841,699,478,654,801,479,88,591,362,462,466,594,742,653,267,458,810,450,315,608,640,801,204,622,645,927,370,164,534,13,677,894,998,42,764,48,146,568,575,98,447,626,948,202,402,299,602,350,642,9,165,828,837,813,928,487,819,637,773,816,543,491,75,917,353,264,781,689,275,931,602,213,217,509,226,877,846,326,744,408,826,446,26,198,292,210,869,740,101,174,770,454,551,808,599,309,146,525,273,663,27,965,491,120,189,336,712,98,344,260,599,827,102,468,700,358,75,323,883,241,92,17,738,467,187,255,391,536,926,905,835,605,827,785,278,187,380,352,825,586,940,295,668,808,573,113,992,412,941,905,621,541,265,240,577,915,483,796,391,509,884,265,936,381,747,431,669,499,65,301,536,104,594,943,830,174,192,937,539,53,808,342,823,831,322,836,124,372,148,840,152,416,667,803,12,711,807,231,854,143,638,719,538,881,992,864,523,970,279,632,899,655,120,525,200,450,945,41,156,643,572,974,279,432,408,233,881,448,755,922,977,326,820,379,165,310,189,141,679,604,176,750,802,107,493,369,491,929,208,505,188,490,284,667,595,964,445,257,695,387,759,776,118,56,435,321,438,450,182,100,490,602,62,796,320,234,493,360,464,746,55,298,910,59,80,731,665,837,129,419,851,656,676,905,535,83,525,540,332,309,514,449,373,425,365,594,66,907,522,430,898,14,289,460,509,753,853,54,929,300,989,126,593,448,675,327,708,496,945,959,34,76,566,384,507,635,663,420,852,454,300,21,880,569,932,661,102,410,159,587,452,180,704,410,414,382,972,666,841,465,419,128,621,102,388,66,397,296,706,241,833,961,356,444,852,391,902,534,616,723,185,605,79,343,91,508,290,260,131,459,23,886,347,695,808,619,990,976,690,295,875,96,758,691,833,651,428,628,301,830,424,416,907,957,428,853,79,840,419,391,662,929,678,493,404,317,264,0,339,521,2,495,2,45,550,34,5,959,497,850,760,395,743,459,763,150,332,247,163,149,524,14,223,601,377,532,244,314,645,181,832,77,522,639,766,439,844,725,562,586,59,129,594,233,19,882,281,642,958,91,813,47,104,993,777,932,974,681,526,779,986,831,459,354,229,604,696,473,112,906,618,242,919,676,337,708,175,644,434,490,459,658,9,848,831,753,770,139,318,331,706,352,730,588,956,339,552,895,468,608,466,864,991,411,901,783,930,899,57,492,242,249,501,671,458,626,928,370,267,262,869,869,848,395,885,665,182,574,963,913,830,66,136,554,373,914,592,869,854,453,567,936,798,106,702,26,107,100,358,7,869,16,469,16,274,477,35,951,696,230,716,529,238,850,663,788,392,316,226,948,362,607,306,878,97,490,631,929,586,727,386,787,490,555,553,265,524,657,114,529,428,121,109,378,102,443,741,346,220,515,368,900,207,761,702,784,763,415,221,796,292,61,703,567,300,230,369,113,947,625,718,516,409,617,924,606,613,594,118,847,795,962,678,436,539,138,358,290,741,470,401,350,61,116,754,510,289,772,574,341,859,241,581,681,396,17,866,817,63,339,79,226,237,986,331,190,447,255,277,549,107,4,984,275,919,466,529,141,805,690,808,773,382,193,423,408,438,486,671,967,58,974,241,150,218,475,2,840,181,169,707,91,957,999,283,768,577,309,913,934,954,18,383,310,577,14,396,796,76,81,797,778,748,978,907,989,717,563,986,400,669,741,360,930,402,621,16,501,444,560,743,623,97,78,954,995,808,77,191,664,323,902,565,324,885,968,408,834,913,424,439,340,296,274,611,526,82", +"852,46,587,294,332,210,41,416,947,245,746,42,270,991,552,859,387,48,427,622,618,550,487,127,701,428,585,798,616,14,833,635,89,751,187,824,368,35,485,373,478,816,100,406,883,570,228,761,403,411,54,266,638,947,166,906,343,303,947,904,71,314,86,592,439,630,984,677,841,988,536,228,160,88,862,687,333,393,641,166,322,277,642,682,131,701,90,853,682,971,282,616,876,531,580,842,980,515,410,389,265,565,853,181,38,476,398,187,985,529,91,621,970,234,924,974,493,833,356,221,590,67,712,367,771,626,173,539,421,204,790,135,496,968,769,22,534,626,382,703,950,797,23,233,796,106,766,937,994,300,945,500,366,811,854,380,937,981,692,189,393,751,133,666,833,948,154,253,663,691,513,849,370,847,645,73,77,93,207,701,184,682,328,390,377,229,277,792,247,568,422,724,757,737,9,497,11,893,997,850,144,462,522,423,686,269,370,521,539,405,699,918,467,719,58,274,555,412,985,49,876,234,540,492,610,247,400,4,508,393,371,972,592,222,65,441,583,351,753,373,572,558,759,91,809,852,725,330,976,761,489,144,663,291,179,27,350,140,859,809,596,986,664,117,766,809,426,449,635,714,525,779,735,347,840,329,140,121,257,497,69,546,753,61,26,900,368,506,151,642,217,738,107,130,324,172,759,404,667,634,135,669,223,563,929,976,882,653,334,976,766,214,511,941,873,75,55,282,995,471,929,45,799,96,438,101,862,401,981,789,134,197,594,695,249,266,890,935,317,658,433,9,18,138,169,713,80,25,986,443,500,931,726,826,86,846,232,321,497,948,234,815,156,97,855,1000,200,797,953,890,592,57,307,945,191,910,572,492,393,486,929,802,659,729,824,864,970,65,336,651,477,22,389,448,848,727,606,836,841,173,762,444,231,846,477,405,337,897,409,321,173,739,556,888,50,618,560,884,393,59,39,984,245,391,10,386,530,109,114,603,159,80,21,299,403,715,58,890,643,157,748,330,119,525,772,532,979,295,330,932,323,271,473,939,472,915,193,918,45,670,580,593,596,835,41,722,750,892,832,780,117,111,570,931,569,22,88,640,578,826,506,780,642,837,852,643,599,140,548,236,336,940,782,243,134,47,550,867,554,337,192,272,444,881,279,948,57,273,182,518,348,787,197,198,662,714,69,531,525,956,26,827,650,922,230,209,680,887,179,521,661,727,218,4,782,857,650,773,663,256,443,577,445,240,175,889,726,951,724,249,463,485,167,313,568,925,835,702,305,70,854,949,196,18,68,841,227,30,972,657,325,149,286,534,829,330,84,784,585,506,221,745,901,163,659,674,381,721,732,851,548,703,868,11,40,540,236,909,949,747,251,617,640,164,737,54,880,12,614,327,340,716,467,950,111,638,842,839,595,640,746,441,855,709,475,689,55,716,820,589,339,0,349,801,783,821,561,891,342,754,648,960,680,635,584,119,684,465,695,994,164,93,401,10,599,412,475,657,947,176,449,789,39,495,640,64,806,822,921,520,416,46,16,230,291,79,37,775,268,713,17,901,493,112,160,672,289,465,660,133,816,136,248,299,847,311,156,224,609,72,99,419,867,873,902,460,8,878,541,928,524,20,71,280,241,937,894,867,541,313,156,560,529,620,913,754,144,216,504,991,679,157,853,229,445,545,275,96,517,691,318,476,881,581,759,658,212,67,670,328,810,216,265,432,48,1,605,719,141,690,876,416,24,436,688,135,423,759,49,138,188,446,274,687,70,7,267,230,407,954,901,236,481,595,16,712,855,348,519,81,514,526,122,574,893,817,941,425,772,290,523,755,692,177,693,97,285,497,281,29,232,774,788,262,398,160,471,923,700,123,460,39,37,597,905,146,805,485,818,713,401,922,234,505,650,690,223,150,274,148,826,2,768,885,870,458,980,133,319,358,741,401,423,808,587,272,193,234,379,942,807,128,376,74,369,959,928,13,985,728,493,142,69,34,984,246,386,2,985,676,792,543,540,303,108,186,803,562,721,356,687,716,784,322,598,77,73,665,201,538,203,555,714,607,393,142,767,594,820,699,84,802,502,475,480,183,27,391,325,656,288,839,245,125,806,575,671,795,105,915,31,929,269,989,803,205,632,421,40,587,901,607,529,775,481,788,319,749,871,380,977,248,50,620,858,832,770,433,657,765,310,376,592,820,309,657,736,525,375,782,642,775,841,252,567,11,373,281,767,744,584,278,184,377,842,574,719,310,212,430,932,695,85,172,623,192,79,816,677,196", +"657,689,771,441,104,338,817,524,998,748,711,450,677,32,886,351,456,619,102,141,656,560,49,403,155,115,635,587,368,420,648,992,110,355,321,930,419,855,414,450,378,717,606,216,475,261,539,579,73,747,858,393,152,111,969,884,68,238,786,127,503,80,9,450,598,756,219,653,1000,414,554,339,963,271,487,615,950,558,725,160,586,559,248,138,677,25,48,422,417,72,981,67,2,908,810,43,101,632,199,659,556,531,12,515,926,80,665,205,115,294,393,251,300,738,245,22,994,675,131,993,693,381,435,44,993,155,282,320,385,398,918,577,351,771,206,255,848,56,42,619,180,198,318,38,853,504,727,291,815,671,324,843,474,763,623,638,623,418,858,681,939,668,191,931,447,664,20,366,474,685,221,129,321,944,739,78,766,764,515,416,144,903,616,430,952,194,992,515,583,811,740,385,510,891,78,280,140,900,478,415,216,131,626,252,153,278,11,22,300,887,722,5,464,6,909,492,620,283,551,561,79,99,141,347,17,975,530,19,130,621,405,956,221,714,725,662,989,605,181,630,236,421,507,574,388,290,696,860,208,481,222,704,836,100,641,269,358,339,235,909,146,875,308,425,461,680,239,100,685,420,758,676,168,933,824,558,846,190,142,865,700,980,908,311,226,321,803,971,144,549,997,613,986,945,249,841,375,809,462,17,857,907,495,410,204,803,568,610,14,287,312,523,228,643,595,98,529,282,593,287,519,287,52,364,299,705,581,950,639,537,146,19,85,393,657,923,130,754,871,330,624,720,603,119,105,246,449,721,486,506,530,542,576,592,336,502,453,319,706,763,606,994,905,524,404,79,761,512,306,861,294,260,591,551,964,97,204,372,903,230,583,285,814,313,378,780,192,352,87,441,400,487,678,285,28,547,481,458,951,565,309,329,390,474,40,195,857,375,822,75,858,813,37,860,745,581,44,167,395,123,343,374,19,134,102,999,796,167,907,451,722,958,530,514,95,376,751,579,511,602,104,72,538,819,465,945,104,286,66,165,659,11,657,612,68,491,78,442,60,571,141,291,639,198,967,507,212,125,978,240,484,517,187,866,517,830,182,367,661,405,384,34,428,984,20,787,746,676,916,340,961,363,358,594,343,738,439,155,319,844,809,876,215,809,608,433,953,640,340,848,188,265,713,989,934,224,223,746,476,38,220,132,526,361,572,447,31,707,9,14,107,709,467,8,741,970,959,555,760,160,251,463,163,890,978,354,689,150,849,660,604,919,869,448,448,55,30,140,149,217,933,283,80,943,829,73,387,370,781,790,373,591,461,983,448,872,778,141,638,654,725,126,720,843,94,428,201,665,272,701,995,78,95,191,381,608,846,722,448,682,150,948,730,536,443,809,253,281,410,180,523,464,133,396,845,237,622,690,201,896,965,297,190,622,663,467,721,867,87,983,521,349,0,194,658,669,20,851,985,654,923,112,444,393,106,7,557,715,783,849,913,359,33,158,613,370,945,905,523,751,632,948,481,150,740,154,865,89,338,589,504,962,686,27,608,397,564,448,875,303,420,120,1,736,824,695,565,609,411,935,240,173,522,967,352,474,408,690,236,924,778,494,751,350,880,629,916,213,744,809,227,997,936,46,612,917,781,49,874,227,462,68,33,871,903,957,508,23,691,765,300,371,954,938,971,550,971,836,530,882,617,269,498,572,16,995,247,161,242,965,635,744,835,521,825,932,121,619,202,83,387,169,896,582,80,540,203,255,254,98,487,94,864,438,214,793,387,111,840,693,677,735,625,810,287,551,950,215,905,274,563,430,742,863,981,870,634,603,925,19,911,352,277,250,281,66,490,569,881,952,971,656,416,922,908,785,133,477,660,142,297,393,538,46,589,601,655,490,525,96,490,788,92,26,774,623,793,587,217,43,304,971,340,616,475,677,584,233,128,762,397,637,973,324,683,816,859,457,553,824,540,758,265,190,203,753,625,534,463,792,348,799,970,429,333,257,324,523,235,735,192,401,426,689,616,579,955,916,518,104,259,857,901,449,978,81,903,879,813,610,274,99,729,310,998,913,647,231,328,953,431,173,15,92,908,84,45,686,173,519,447,504,83,291,688,81,39,318,621,196,747,651,881,463,412,15,277,258,613,14,692,886,735,174,180,626,740,229,788,474,181,566,893,966,554,495,626,777,70,674,689,885,54,339,835,766,60,153,897,932,165,375,442,923,660,176,677,909,887,326,808,747,719,931,160,871,500,270,193,966,225,858,858,887,718,404,810,424,795,280", +"622,775,204,194,689,36,812,629,357,385,548,643,964,413,200,914,467,588,476,126,536,114,225,11,846,931,990,554,496,572,14,876,14,109,922,716,914,921,371,81,770,648,970,198,67,523,503,390,729,603,233,322,458,259,452,395,788,442,918,651,744,750,317,652,269,955,143,53,220,275,925,821,280,223,328,594,528,778,824,665,137,119,586,490,262,182,601,526,280,239,320,266,355,836,611,61,576,946,988,942,98,545,23,288,555,93,402,166,371,62,25,283,456,102,274,568,212,659,398,683,66,665,584,934,681,671,581,866,188,222,761,442,108,179,952,618,763,877,662,132,950,433,58,428,363,575,659,286,155,556,232,520,978,833,120,567,898,756,802,571,490,550,663,832,656,737,655,365,973,101,150,870,106,647,9,13,940,914,314,88,704,707,756,285,100,513,108,439,702,796,409,809,317,589,152,89,949,176,732,750,713,550,554,336,942,92,147,634,435,903,539,814,493,31,845,846,147,763,388,427,931,858,933,395,108,978,806,404,867,5,471,985,782,73,930,687,787,603,138,334,446,416,437,370,234,369,277,671,930,46,885,12,490,282,979,587,989,633,725,206,812,575,71,120,830,697,204,647,671,754,293,523,250,305,31,886,402,25,527,221,664,354,848,827,241,431,882,199,452,159,285,676,834,786,949,665,891,720,552,577,38,180,408,248,173,166,432,867,856,630,174,588,674,50,335,630,664,101,19,943,355,514,780,3,775,973,881,718,564,712,564,499,385,659,557,290,360,835,700,865,995,857,205,552,899,69,149,792,192,928,579,970,981,3,277,722,397,612,333,950,37,55,829,153,573,379,663,683,719,583,118,73,372,398,837,730,496,703,726,645,646,600,537,208,865,951,445,675,832,542,627,323,767,424,988,509,672,860,701,339,70,602,752,153,371,620,247,552,666,280,433,553,756,478,397,783,137,968,849,439,506,959,409,280,59,933,16,842,825,246,61,214,123,553,145,377,55,360,662,7,393,4,735,767,464,336,666,527,459,793,345,133,815,857,284,633,285,610,913,63,285,724,209,630,534,220,9,76,754,847,987,864,947,766,851,31,522,433,782,510,56,708,245,355,442,776,43,354,22,819,74,473,641,398,965,536,878,66,627,614,801,229,207,586,170,946,352,55,806,792,219,352,445,393,230,399,449,494,9,572,891,326,341,544,122,229,963,977,103,14,954,572,583,904,643,890,156,134,859,155,587,306,391,546,152,471,58,602,512,427,926,181,129,215,348,830,325,136,914,648,963,944,110,115,767,661,157,303,412,736,996,184,878,811,496,471,242,836,447,702,834,845,376,185,921,756,482,147,970,906,400,369,204,807,130,332,41,16,422,670,745,527,634,151,993,879,24,980,987,224,764,547,81,606,15,990,70,694,598,461,787,527,54,518,351,261,44,870,579,43,2,801,194,0,965,459,597,57,970,470,405,327,341,479,790,561,633,885,843,277,29,484,837,388,745,605,811,916,269,538,669,401,232,362,948,821,243,217,237,57,442,332,847,25,859,260,95,827,316,42,11,758,42,379,869,792,781,279,965,759,315,270,164,27,738,483,604,709,818,525,614,938,789,107,881,983,466,627,174,187,682,191,842,487,157,662,549,585,821,375,34,811,357,908,667,576,178,245,876,323,230,339,671,745,923,509,3,405,126,175,930,995,113,806,802,762,711,401,801,158,512,700,296,426,135,965,723,344,859,851,390,630,15,871,997,411,722,93,377,878,92,888,304,731,373,256,185,266,968,688,905,381,64,947,244,279,645,779,68,37,362,504,726,137,194,491,211,235,193,722,290,834,619,890,891,982,488,813,884,185,893,929,370,334,802,768,791,781,886,595,536,104,224,513,646,733,334,326,70,296,528,154,24,767,161,829,83,901,180,297,490,127,29,837,298,161,714,489,653,968,121,558,891,858,376,705,864,469,583,429,536,527,411,409,674,823,642,959,127,306,253,936,402,834,597,864,588,989,502,219,450,99,310,166,506,494,509,185,130,437,406,175,402,893,931,330,823,144,172,827,437,50,917,830,151,298,187,280,957,105,224,241,334,649,927,463,274,396,455,317,866,149,635,89,995,687,675,793,467,713,871,634,713,112,631,587,257,992,737,454,114,782,53,101,117,106,902,435,757,798,650,119,536,363,790,649,601,394,397,134,533,375,210,208,624,166,854,859,679,676,25,717,678,801,969,816,879,873,823,59,144,812,351,512,675,596,986,871,213,501,190,981,154,623,11,28,101,450,204,773", +"461,318,607,902,959,277,61,405,184,339,552,538,549,552,91,725,631,653,244,459,870,414,170,522,177,431,571,71,888,254,541,91,953,203,161,762,826,951,773,88,661,662,860,972,384,998,195,632,888,228,713,799,953,304,160,312,743,259,302,256,765,264,890,486,344,378,196,53,146,171,748,284,573,844,292,608,872,54,668,237,66,577,994,790,647,618,60,950,298,43,588,194,831,34,670,548,71,308,955,269,73,134,161,149,831,258,436,959,665,425,355,900,411,474,203,939,94,320,2,47,30,668,917,37,37,840,412,673,501,306,376,773,904,775,18,367,85,659,672,796,318,486,739,416,374,916,625,84,916,262,852,866,402,941,580,45,405,716,862,854,615,501,85,281,560,308,875,737,656,115,287,778,275,908,223,865,408,381,240,427,532,266,498,798,692,829,964,70,309,522,278,508,362,899,455,778,658,975,189,663,518,118,5,401,76,582,750,873,293,869,213,654,410,750,450,928,731,59,27,138,162,294,158,15,815,285,917,841,250,144,117,913,547,370,43,769,677,797,930,628,528,262,797,496,170,364,130,927,323,908,951,387,931,267,97,443,99,702,562,652,566,542,432,461,732,305,783,117,84,549,888,624,524,793,327,818,62,491,178,258,687,631,267,352,341,604,585,369,916,536,274,232,624,433,637,870,285,309,850,31,754,791,546,885,131,269,796,991,33,712,736,939,527,885,60,636,725,230,150,880,73,415,609,530,567,273,837,161,593,937,808,232,226,299,592,74,721,825,881,109,545,499,423,262,616,394,424,453,561,913,387,399,98,963,567,412,933,445,680,115,676,215,183,611,736,20,831,737,296,171,749,878,76,462,793,495,402,264,953,738,655,697,93,913,893,334,551,193,248,278,385,411,753,114,336,30,314,722,503,377,919,309,338,50,199,859,398,647,744,590,349,809,974,250,441,336,836,872,412,875,575,61,887,235,130,698,611,861,525,112,878,271,902,10,949,893,887,595,48,243,332,14,721,298,836,751,616,415,189,209,63,153,534,180,970,941,865,432,894,830,356,311,569,500,130,569,527,582,41,853,532,726,107,392,411,722,416,606,86,639,218,696,672,637,988,199,623,684,361,780,121,222,458,71,743,599,865,638,658,274,408,968,134,804,646,63,222,747,280,820,50,569,178,871,593,470,65,962,220,665,681,363,83,224,847,353,6,808,448,54,478,520,796,487,687,431,40,561,870,18,495,32,528,807,944,618,594,189,331,170,89,977,760,587,971,534,724,900,304,65,124,252,380,633,700,428,941,759,312,143,598,573,932,360,399,108,658,277,706,945,922,266,999,518,318,410,976,823,983,63,874,133,958,30,928,782,70,808,133,308,859,853,607,368,928,890,807,673,502,307,549,914,515,735,683,722,136,691,672,90,444,122,400,93,944,548,922,183,373,887,495,783,658,965,0,416,835,560,256,172,76,143,75,278,933,872,332,610,18,805,5,913,943,776,94,473,675,550,156,614,537,836,451,694,621,194,578,563,697,642,606,505,164,264,234,241,276,983,1000,707,882,117,20,250,790,664,337,678,661,791,412,314,645,629,161,713,290,902,239,695,254,634,36,281,652,829,46,414,800,737,211,92,600,793,780,254,270,582,399,517,859,311,808,609,480,523,992,660,98,968,964,47,898,437,791,128,946,460,930,547,514,419,406,786,770,692,510,290,614,831,567,902,783,849,344,114,856,511,174,841,740,724,46,138,740,410,404,589,363,620,117,668,350,93,941,662,124,461,848,445,576,928,849,603,748,626,647,467,146,950,487,190,385,286,504,621,575,667,732,881,977,580,890,94,181,855,639,846,605,632,550,892,795,9,612,745,518,238,971,698,118,80,852,75,611,643,407,448,511,755,405,541,983,607,265,586,776,707,561,459,345,987,624,894,190,445,378,508,466,864,139,734,721,896,686,607,172,521,377,6,370,997,346,6,562,93,576,32,231,732,375,535,692,176,265,240,160,586,500,656,720,611,805,989,726,425,957,491,155,989,78,332,481,787,798,128,726,149,821,371,137,604,260,454,912,501,169,420,444,976,65,243,142,966,362,233,510,116,532,232,611,584,966,764,177,34,985,417,798,202,800,679,449,864,956,148,122,17,39,890,36,741,480,703,55,752,805,368,599,799,563,991,968,91,207,453,890,410,575,236,844,101,291,963,738,393,525,62,502,696,206,39,19,811,484,22,313,226,439,915,115,596,395,109,293,452,917,543,381,986,368,750,197,500,791,397,841,941,142,149", +"101,311,979,117,217,533,730,827,771,940,964,230,884,785,87,144,783,159,145,112,96,201,324,595,883,339,944,529,884,307,58,676,126,272,335,462,149,821,696,755,229,650,918,643,932,181,117,128,60,424,333,767,568,761,389,480,449,480,814,108,229,945,566,664,848,1,323,819,513,754,906,84,561,264,926,776,576,24,265,108,730,657,863,874,107,737,687,812,17,649,968,737,482,784,475,330,919,337,321,972,901,417,326,300,69,190,820,69,259,32,862,953,91,785,779,154,704,787,49,316,255,970,965,741,914,963,429,346,104,948,592,305,178,599,828,876,927,29,999,966,300,436,199,699,721,689,724,41,296,46,819,791,975,598,100,435,417,340,250,335,556,124,180,384,705,954,578,104,450,171,231,60,851,665,743,485,215,989,136,902,215,907,551,720,89,367,542,560,950,234,503,629,174,16,432,916,517,854,472,871,130,361,897,102,533,243,312,47,235,89,735,610,539,459,17,153,64,740,895,213,825,951,542,134,640,397,353,318,481,403,337,813,406,606,804,495,907,139,608,299,115,298,417,152,756,276,485,164,264,58,188,739,80,911,44,279,968,836,260,656,730,746,829,166,706,608,354,680,304,748,248,526,723,176,545,989,899,272,624,777,48,856,751,781,226,259,501,756,488,555,919,84,23,975,62,8,628,144,666,230,348,89,597,507,56,815,519,995,500,710,166,36,213,167,478,306,732,321,613,174,913,181,281,442,77,21,863,769,43,753,992,795,149,17,936,122,760,168,131,533,874,875,200,89,438,190,191,18,684,60,788,281,179,278,527,146,132,417,859,812,336,750,959,774,55,954,599,614,301,776,561,448,759,533,872,783,479,761,106,619,475,867,463,191,219,266,564,928,229,845,186,498,376,824,805,831,137,245,540,150,718,959,118,221,428,177,65,334,333,282,17,284,691,554,881,556,527,536,416,565,681,226,262,25,101,853,738,826,336,487,708,347,598,898,179,528,930,499,374,121,416,519,630,842,214,854,274,532,887,799,923,696,147,917,461,248,197,925,195,770,438,923,419,442,218,485,780,69,91,645,363,109,897,452,859,87,797,212,390,19,766,874,201,365,189,658,823,986,311,609,787,548,177,111,888,796,950,325,828,187,128,868,554,752,296,765,976,71,826,55,856,942,691,535,332,305,872,590,157,35,770,760,954,8,591,883,107,912,534,29,454,941,147,167,976,50,47,614,979,974,651,25,272,419,470,429,487,24,662,706,855,718,904,602,947,734,674,622,848,99,830,833,127,46,157,810,332,830,194,868,39,921,628,590,395,329,450,529,250,72,454,592,486,582,156,397,506,240,238,157,703,369,275,257,307,789,414,650,593,749,764,341,374,984,489,258,785,411,304,718,28,614,354,463,80,129,474,937,65,309,615,442,834,819,819,946,35,77,487,919,2,821,669,459,416,0,120,28,43,469,283,927,147,956,966,63,687,458,34,348,606,931,380,286,101,243,428,727,937,252,731,601,820,404,540,67,407,338,130,395,563,928,774,86,523,509,473,989,302,566,119,809,838,650,419,236,417,586,147,817,591,836,113,394,178,577,221,779,516,603,626,309,790,508,33,45,517,515,748,917,936,920,54,120,343,744,1000,943,629,66,592,373,706,839,35,754,709,757,666,826,4,265,542,478,492,9,530,736,922,920,331,614,650,19,435,33,998,285,832,669,244,234,883,853,46,678,615,159,309,72,87,687,761,233,809,430,387,871,731,724,663,589,952,938,564,404,303,459,988,807,695,40,220,387,451,625,262,386,789,49,326,931,934,147,471,959,394,63,369,962,308,544,557,428,447,940,997,578,323,165,920,94,566,917,462,664,736,207,241,648,6,155,607,429,495,872,261,80,360,567,185,890,190,158,473,65,762,189,442,383,586,935,636,104,573,47,843,530,259,394,117,64,723,642,341,588,42,563,455,951,265,203,944,447,100,329,863,520,291,167,571,689,74,579,385,821,532,203,179,847,264,96,880,468,45,243,284,167,284,771,11,552,482,477,444,426,583,627,608,876,576,83,920,788,927,511,379,241,411,696,264,836,794,161,338,223,401,45,430,527,538,570,716,286,460,146,208,184,330,14,770,223,230,70,101,924,274,577,656,695,374,909,554,331,265,906,185,674,702,697,288,531,603,377,714,859,897,285,72,933,494,646,505,668,888,321,62,525,719,565,357,108,347,717,255,881,140,291,358,69,202,323,894,904,922,957,439,602,780,658,593,231,283,287,423,224,398,558,268,672", +"771,247,404,969,466,632,597,836,130,8,395,391,412,121,785,44,960,621,808,620,200,562,610,268,559,55,378,797,584,99,665,951,136,73,358,358,695,483,998,520,847,284,709,591,96,725,525,72,556,570,196,968,685,238,263,439,713,442,308,453,9,884,944,970,275,492,641,460,83,258,892,611,555,732,261,296,845,278,767,180,56,751,962,621,515,204,939,74,721,412,40,619,156,343,841,521,301,167,860,439,860,71,754,599,183,423,138,370,995,126,513,703,931,188,561,542,883,60,546,91,716,793,97,518,80,300,296,43,531,229,325,562,758,272,226,41,200,606,661,247,747,56,69,9,689,825,934,669,416,484,304,66,196,942,506,435,711,295,585,438,189,268,372,344,829,714,99,536,845,609,319,221,604,236,619,928,930,413,429,760,177,924,227,609,549,495,773,766,863,312,784,55,344,583,807,47,541,972,835,12,838,731,688,359,574,611,333,708,174,282,578,741,924,174,582,441,421,555,808,292,65,507,701,263,158,582,183,351,869,510,598,715,447,365,728,115,862,851,757,963,383,488,894,322,185,934,865,281,581,926,266,494,902,6,40,521,756,616,893,314,780,256,772,600,453,98,125,906,807,310,5,409,418,632,383,966,548,506,688,605,441,149,343,742,205,179,958,131,224,686,596,499,914,184,414,798,44,103,331,624,168,21,84,450,609,174,672,158,201,93,276,966,816,370,463,169,295,109,192,786,839,73,838,237,218,731,411,579,339,377,95,110,789,27,448,906,658,382,836,628,966,855,741,779,134,803,369,190,577,295,811,990,186,361,462,416,345,295,254,512,170,975,987,379,301,102,131,773,934,389,724,496,943,131,742,864,170,106,909,489,920,162,502,577,725,204,951,664,827,902,890,269,513,990,936,525,899,451,677,182,901,584,402,827,556,216,919,631,890,500,308,508,950,185,901,864,521,661,896,132,955,228,968,784,590,355,31,525,518,241,939,932,138,562,893,792,739,242,700,280,199,969,525,533,516,278,588,128,230,107,264,491,270,997,806,198,399,537,673,732,240,920,685,474,629,37,268,152,979,796,750,694,168,481,919,476,344,285,535,910,543,99,839,550,855,67,698,639,183,741,87,462,376,484,961,832,48,835,78,395,896,866,643,546,720,121,927,180,952,362,426,155,962,268,572,997,251,795,537,968,812,762,803,274,57,965,712,469,445,63,385,583,125,919,572,506,276,894,887,179,730,616,788,384,791,422,572,34,495,468,580,438,848,553,415,169,566,978,639,335,749,720,57,840,613,314,154,888,505,336,111,119,925,762,480,104,427,808,504,816,702,478,919,113,963,479,614,369,325,515,507,143,932,167,359,246,142,789,322,385,918,877,790,980,268,58,260,619,15,261,573,695,374,421,867,73,17,131,721,768,276,937,956,356,351,914,948,932,550,142,45,561,20,597,835,120,0,2,813,963,542,491,533,958,773,883,472,355,592,640,305,65,263,639,495,948,826,320,959,983,310,41,514,108,437,933,680,703,702,233,793,964,478,405,547,270,161,818,944,160,678,296,191,340,926,68,966,927,963,613,594,538,311,704,679,58,866,162,248,926,82,862,230,908,58,757,244,713,799,833,949,597,470,916,691,586,611,766,452,14,499,404,885,76,134,150,593,892,454,556,126,22,658,870,312,235,490,479,982,764,693,927,56,142,359,211,422,731,71,555,694,317,515,799,363,722,200,746,620,681,661,137,165,213,316,274,697,679,435,181,211,354,632,235,927,936,350,3,611,711,650,479,280,469,136,888,319,751,344,781,83,180,160,499,969,385,583,675,751,368,854,958,644,218,494,707,636,278,442,12,976,406,421,664,112,185,783,954,476,199,911,75,334,96,19,765,709,805,408,469,491,58,994,339,146,333,210,619,392,947,840,176,261,147,88,934,593,672,164,767,638,154,516,777,315,722,788,930,702,382,113,934,491,232,627,194,996,579,111,641,157,792,211,34,991,118,332,534,740,514,589,73,100,107,157,344,648,791,788,879,312,62,483,939,251,919,820,878,832,431,484,287,655,909,415,957,68,223,140,863,59,930,767,876,370,572,361,842,732,409,84,897,320,408,38,168,351,693,497,252,291,220,944,768,188,774,619,215,896,95,87,650,977,368,104,892,1000,779,161,824,687,785,291,123,298,801,859,122,488,952,792,541,885,703,840,674,723,566,766,991,7,614,528,911,638,600,598,557,308,454,202,484,909,484,707,449,3,688,126,253,395,254,739,787,850,368,173,909,447,298", +"644,748,137,201,184,420,543,795,663,126,132,306,750,952,657,919,911,909,55,474,422,813,921,296,525,839,448,761,80,730,80,880,940,466,306,755,727,893,160,21,448,30,928,549,36,396,670,667,347,749,216,768,265,894,337,603,457,182,417,951,74,485,543,701,456,655,382,905,131,113,973,596,718,528,551,705,499,138,974,309,743,869,747,620,751,415,216,739,384,588,513,135,252,108,829,809,5,209,682,5,607,474,790,195,394,17,955,350,668,592,377,871,123,510,594,670,54,914,665,814,774,937,713,238,1000,849,373,488,979,81,967,72,279,336,225,906,347,926,561,853,235,438,278,160,796,179,934,151,91,420,101,330,365,464,760,446,590,534,902,415,467,654,203,613,224,215,583,124,150,641,90,641,886,534,818,71,239,624,385,908,420,866,448,646,261,424,247,661,704,219,354,94,88,731,555,337,954,44,531,170,4,780,145,833,636,173,268,602,18,719,707,844,369,775,27,602,127,23,958,384,649,207,231,577,478,106,546,361,371,588,29,69,339,76,524,378,967,401,611,197,989,667,796,328,433,980,385,795,986,322,828,873,290,382,374,708,378,757,223,489,261,68,934,230,612,467,66,156,787,242,197,204,886,9,889,227,686,321,112,195,222,760,117,292,911,464,805,394,470,289,932,418,588,761,568,464,667,725,192,143,904,658,661,285,116,882,329,897,748,535,994,745,366,467,221,887,150,465,173,708,160,620,465,512,911,188,131,86,803,100,656,996,440,72,212,134,976,641,507,445,803,171,747,296,688,466,955,500,219,116,343,217,316,247,609,509,331,563,955,748,662,331,913,757,791,531,786,297,106,128,477,485,83,431,255,960,391,448,373,177,431,462,157,736,253,307,861,804,490,600,623,291,85,323,210,652,709,948,108,549,581,806,511,591,524,34,772,817,780,108,809,833,428,144,975,216,431,735,182,153,632,887,207,222,972,339,288,16,598,468,865,273,432,101,616,247,634,61,750,847,600,871,985,167,811,506,554,402,187,616,514,129,906,841,554,8,526,685,448,724,62,834,261,288,286,309,656,91,75,775,171,384,229,591,387,180,526,282,7,534,483,460,988,779,860,530,899,325,14,704,397,323,22,320,525,776,293,915,960,828,290,618,450,933,288,543,328,788,815,11,822,840,669,58,92,159,597,178,694,123,877,886,599,67,516,651,635,795,880,605,660,460,484,397,838,189,143,815,412,927,914,251,1000,855,738,22,152,979,880,191,235,713,992,733,38,881,987,291,704,28,317,906,954,136,710,334,526,551,250,765,401,864,438,100,200,76,858,370,507,549,31,560,63,680,12,380,127,882,506,116,144,838,415,674,430,256,343,83,161,828,396,444,818,395,530,174,437,412,143,579,979,156,11,668,548,257,73,646,38,631,212,847,517,472,285,243,115,345,478,170,550,891,851,57,560,28,2,0,157,992,949,225,337,989,594,294,660,688,345,913,834,401,454,813,470,325,130,377,462,451,115,664,628,165,601,437,411,215,430,436,677,505,817,595,378,13,953,544,349,332,488,654,281,827,581,177,647,942,647,692,489,436,94,952,831,457,919,245,104,883,507,619,793,137,827,265,236,137,390,785,976,584,984,484,523,7,490,587,809,193,914,618,156,901,548,203,735,897,81,83,510,317,787,508,932,920,705,916,391,995,266,424,493,990,83,536,230,818,60,401,378,728,161,59,94,963,863,589,83,781,655,929,400,731,714,578,502,527,962,772,602,129,649,811,860,756,705,491,297,253,407,379,757,947,20,762,438,132,931,76,42,888,763,886,571,384,371,939,997,539,667,825,726,873,775,590,322,800,346,720,670,423,248,783,575,167,312,612,563,403,250,92,563,267,33,233,147,410,896,562,376,401,895,217,463,869,271,333,506,129,382,504,764,674,197,624,757,493,691,202,207,882,32,34,818,884,519,3,687,22,75,171,857,607,838,848,302,720,686,62,116,989,705,567,547,798,664,298,310,745,460,883,10,861,529,351,807,428,52,935,279,402,780,636,990,178,889,510,208,153,515,337,728,781,909,642,190,478,149,410,204,318,398,544,575,492,664,367,885,518,116,491,857,123,18,697,557,665,358,506,74,119,917,650,895,56,288,32,537,293,62,124,986,554,149,540,731,46,195,399,269,328,296,724,538,927,317,904,589,874,377,862,753,340,873,492,702,537,901,879,855,610,415,573,948,574,725,368,899,886,88,560,817,547,418,990,728,471,581,165,159,964,961,37,890,644,909,872,351,188", +"925,318,688,451,313,213,601,122,498,996,444,929,109,932,786,60,835,474,477,9,355,602,469,976,60,933,768,684,610,561,636,617,3,395,209,29,206,768,512,208,95,410,105,242,884,920,203,344,316,837,675,472,189,528,479,580,180,874,379,745,154,428,84,317,332,22,992,222,991,929,624,944,445,119,956,614,290,439,833,27,689,582,108,834,949,451,635,804,826,365,699,192,696,928,951,346,547,116,599,685,745,23,554,251,17,445,129,241,869,974,465,915,975,854,269,270,579,891,829,980,677,884,674,9,548,943,873,115,111,753,856,643,700,781,194,247,771,25,814,693,227,280,40,461,263,981,582,717,937,929,653,743,768,737,648,883,500,109,870,31,824,173,765,624,922,391,532,718,897,194,788,3,957,370,432,414,670,987,341,821,673,94,123,456,370,320,79,896,803,915,816,72,726,293,753,744,679,602,536,103,558,725,941,93,643,716,170,910,796,926,412,480,21,834,87,255,745,207,913,789,671,710,882,718,684,748,325,707,889,708,893,321,673,178,378,51,673,501,598,266,582,244,325,659,121,100,303,117,600,265,37,843,550,435,998,770,10,850,442,889,364,695,133,266,486,74,574,544,564,903,445,375,79,809,852,982,619,436,892,828,903,978,55,182,124,859,495,835,938,474,83,609,377,500,509,78,30,704,105,65,62,14,430,242,933,8,522,453,198,307,430,275,645,100,140,826,234,950,72,249,628,507,136,351,614,742,176,802,877,706,947,796,300,730,533,515,466,797,552,182,247,429,247,73,679,128,794,398,486,746,875,517,282,794,620,969,441,760,301,871,156,858,905,413,796,724,702,881,999,59,272,954,626,4,761,712,33,417,99,993,701,91,822,953,845,151,347,239,527,531,563,940,129,489,480,648,942,945,160,223,279,116,103,611,565,950,396,489,542,708,294,374,745,174,907,873,774,835,595,544,519,29,411,149,685,110,431,108,846,814,280,221,915,882,146,617,203,687,867,102,855,568,804,436,608,227,11,857,489,649,556,324,119,201,104,113,858,122,969,89,868,827,68,276,156,518,105,83,883,131,933,836,959,229,206,426,402,993,445,928,581,369,228,466,541,871,407,515,620,937,484,620,461,683,800,575,128,561,400,224,779,21,11,982,665,545,841,329,122,390,860,814,399,594,982,917,506,744,802,823,348,322,904,444,310,504,730,970,725,732,593,106,77,476,187,276,942,866,742,796,925,479,655,572,257,837,779,324,921,872,163,216,562,18,657,17,123,192,323,247,150,555,763,653,658,253,978,833,106,288,441,382,564,976,678,212,23,5,340,653,164,580,429,946,16,395,604,887,366,95,847,810,220,412,303,63,735,356,265,368,394,231,434,714,521,17,530,571,157,543,470,369,210,765,105,281,619,881,771,59,436,623,653,993,848,966,933,187,461,775,34,342,985,970,256,43,813,157,0,764,721,377,80,949,853,851,99,570,634,152,112,484,929,785,432,596,146,218,732,910,648,67,671,770,405,697,915,19,38,157,185,177,68,392,961,343,876,33,968,505,448,459,788,160,415,87,74,827,61,992,92,868,990,234,302,950,336,912,957,95,251,989,295,621,59,240,964,507,910,292,277,751,452,809,280,265,495,456,941,919,144,856,825,50,206,194,556,49,81,280,562,880,773,676,433,879,973,545,190,114,640,526,128,155,711,341,870,209,298,979,841,39,90,14,665,702,475,458,934,929,492,959,583,753,401,205,96,155,473,321,178,606,930,768,94,441,326,959,690,162,899,721,767,902,718,631,852,48,752,128,383,383,49,487,337,187,957,533,520,228,552,365,946,809,1000,110,68,166,315,842,815,863,656,747,519,790,302,69,774,589,771,565,271,990,595,536,880,872,694,341,450,573,640,391,89,482,772,493,946,649,467,216,500,918,835,31,947,637,680,666,119,280,888,248,323,174,527,2,703,877,154,296,475,340,864,873,267,309,749,99,235,630,633,59,229,47,326,139,317,250,441,762,973,418,818,521,657,195,115,980,930,479,842,356,397,642,67,631,858,333,899,752,424,1,302,752,131,231,129,254,329,114,448,126,574,322,481,818,191,385,670,81,870,625,712,313,378,248,245,985,693,103,232,41,119,528,981,370,859,462,300,915,425,837,617,651,840,689,628,860,249,985,247,718,254,429,347,327,67,966,290,705,726,447,51,247,90,99,796,651,382,955,588,738,133,853,230,494,625,227,219,95,854,319,798,292,968,60,305,102,301,409,662,471,656,183,387,725,313,156", +"761,828,572,589,774,53,31,296,536,242,154,350,136,600,151,467,213,376,829,770,759,978,550,145,706,191,616,66,221,220,613,399,181,572,499,420,681,187,846,914,818,689,526,978,308,18,576,525,173,607,778,703,568,869,331,440,824,996,878,980,304,29,517,230,402,30,134,766,101,997,846,37,720,772,312,986,610,22,451,175,606,232,777,330,395,922,423,262,479,818,788,429,442,864,400,754,372,477,825,81,23,264,465,501,817,374,941,28,647,519,637,113,419,812,341,346,554,989,896,542,190,780,938,355,730,59,757,177,319,61,778,599,416,313,475,839,130,266,721,63,732,717,443,665,52,850,542,199,325,836,237,909,825,482,311,432,204,688,106,287,763,429,649,173,408,563,515,793,366,187,447,914,229,871,642,36,679,437,80,291,819,352,677,597,309,175,993,172,255,371,344,785,930,44,793,424,703,528,788,658,4,370,959,91,969,817,189,955,23,515,94,21,974,893,826,90,873,264,956,131,543,248,127,929,604,627,342,124,386,187,910,817,611,907,719,576,504,696,418,159,564,158,251,362,93,861,141,159,838,119,1,966,82,520,794,796,647,700,699,108,940,178,648,669,591,832,9,667,158,779,536,392,333,895,346,296,166,923,350,274,62,177,243,761,387,124,42,678,625,168,900,207,349,569,559,955,722,91,379,21,748,778,338,97,669,858,173,480,252,952,607,694,157,6,39,759,822,933,413,670,485,93,738,65,287,674,704,809,167,972,72,516,764,601,441,485,395,905,761,15,443,114,822,453,460,593,499,840,542,99,886,470,733,950,304,309,508,79,984,793,336,786,119,719,13,373,217,339,52,196,226,301,782,511,712,575,319,329,832,972,136,376,346,634,256,921,238,711,539,1000,490,633,280,828,230,546,211,98,336,947,43,303,422,316,602,471,756,216,515,322,753,507,901,491,535,283,247,592,233,210,26,365,420,464,276,58,337,405,155,716,355,416,981,267,581,801,200,860,552,246,32,294,309,180,67,961,8,319,134,434,757,530,504,836,307,280,985,309,176,800,61,645,356,706,358,400,490,903,377,625,514,978,277,942,370,535,597,86,19,882,253,464,210,195,3,371,527,939,388,207,589,861,593,916,598,610,955,364,401,585,32,188,107,384,843,53,974,501,181,603,228,365,328,826,272,704,411,364,110,953,906,22,933,302,423,442,644,135,231,51,469,968,482,630,386,285,629,286,342,550,225,394,288,997,450,592,727,115,494,161,534,892,939,285,170,765,363,170,87,120,841,134,727,362,695,131,836,655,701,383,289,249,743,950,630,357,516,933,988,262,70,145,274,913,387,896,181,358,192,946,212,31,408,138,153,680,831,266,580,208,426,572,151,625,103,170,129,248,250,238,937,994,51,583,593,379,943,657,338,598,153,807,452,516,704,474,107,818,260,727,5,754,654,470,172,469,963,992,764,0,283,628,859,464,747,825,67,366,825,708,538,6,280,92,346,900,471,373,241,473,707,371,843,120,881,470,669,986,450,320,332,360,486,99,741,203,711,229,808,916,51,75,491,268,157,422,308,61,831,588,155,450,957,70,386,105,9,828,241,737,449,112,658,216,288,674,679,888,199,640,998,419,407,453,406,295,88,1000,402,826,267,410,685,292,445,319,234,215,490,233,258,55,524,371,113,984,694,502,194,239,373,459,741,355,599,868,169,660,597,687,406,770,906,510,713,108,910,114,277,360,124,756,897,453,228,965,481,762,147,384,420,624,922,427,282,316,529,306,780,48,684,66,700,601,233,372,739,71,410,430,943,642,573,400,827,215,668,235,577,658,11,797,75,440,402,312,764,775,738,257,849,325,658,884,736,670,394,371,653,497,193,342,924,243,864,243,434,888,7,636,696,162,735,744,559,461,666,524,27,788,374,446,564,815,981,11,837,928,844,403,50,581,643,352,640,59,495,139,534,526,913,539,82,669,239,82,504,264,786,281,236,444,88,745,125,87,878,904,110,654,126,567,740,947,839,485,12,439,656,192,57,109,866,692,538,458,808,739,427,525,178,735,500,123,425,690,219,391,703,878,71,582,159,846,203,924,138,428,517,659,62,391,900,599,377,966,612,627,17,26,436,694,246,840,907,985,668,995,373,446,236,350,671,790,532,702,659,2,396,213,945,253,902,706,873,961,808,451,529,298,938,883,333,638,992,437,467,979,818,220,593,538,672,679,865,939,759,679,840,531,440,348,444,341,676,161,895,764,814,86,559,879,648,344,872,915,448,654,706,974", +"286,500,967,106,735,823,163,953,855,984,203,778,21,147,141,384,302,66,640,149,936,273,306,925,852,378,77,520,899,204,115,763,536,701,285,411,568,350,358,617,398,147,138,82,929,541,967,661,667,335,150,533,545,821,108,104,404,36,166,486,130,920,322,704,228,247,47,255,20,505,59,780,679,370,241,62,955,211,904,583,143,43,246,636,868,110,984,328,239,459,886,38,993,954,769,29,235,810,65,666,284,191,775,41,933,275,911,692,632,650,766,472,627,14,782,328,335,402,798,873,519,542,969,415,766,617,911,896,115,423,616,461,607,789,468,114,722,593,274,446,629,279,105,993,463,69,979,688,240,573,859,232,584,36,858,753,641,43,493,567,815,551,922,722,879,831,330,319,496,968,223,930,427,943,615,563,144,96,761,868,858,464,672,366,926,236,953,835,133,945,846,286,805,38,38,759,412,396,574,104,434,34,443,894,193,409,840,190,718,350,230,742,619,880,190,834,464,950,898,629,168,563,243,830,343,785,644,528,700,629,34,636,727,486,503,523,384,407,82,845,671,152,49,287,419,542,545,101,806,762,518,599,613,546,274,328,879,384,604,637,167,438,995,874,247,187,198,582,323,777,261,305,545,138,848,114,190,934,178,619,247,228,900,873,680,391,711,947,853,320,43,641,587,5,382,513,722,401,844,224,154,514,616,473,97,458,281,851,499,3,985,691,57,882,688,935,6,290,566,840,530,880,249,83,107,515,586,226,873,415,462,314,227,144,215,45,559,506,528,17,238,353,135,622,595,361,661,220,195,149,237,705,591,583,114,938,197,779,843,559,221,437,377,520,313,782,113,437,141,941,95,909,270,321,589,784,80,326,546,346,981,258,596,494,385,465,227,755,838,284,671,436,435,151,241,993,261,17,295,745,113,623,594,251,426,409,683,531,978,258,356,24,66,330,627,194,759,322,352,650,187,531,906,353,268,133,390,704,166,703,922,504,412,750,605,985,751,599,470,566,100,175,43,483,395,495,480,684,808,959,632,416,112,27,669,846,608,773,422,973,729,163,807,167,299,650,92,705,676,780,523,548,51,305,627,916,669,395,567,452,352,513,756,216,969,305,231,772,526,603,53,223,500,895,806,440,884,599,48,46,375,474,942,493,325,8,107,986,845,35,865,488,788,736,755,703,373,131,43,78,159,321,788,23,604,170,539,729,365,274,908,797,57,940,831,645,423,484,514,147,983,322,119,643,123,765,604,109,153,345,923,173,409,892,111,709,432,118,808,598,553,45,371,937,219,4,355,82,549,504,249,410,679,309,86,414,955,320,325,171,56,835,301,330,126,348,682,480,884,879,870,72,644,385,148,493,966,534,571,796,502,414,622,847,703,502,269,966,773,180,812,600,720,885,192,111,505,973,699,817,730,437,508,706,708,36,429,318,633,320,959,648,923,405,76,283,542,949,721,283,0,664,657,471,953,270,401,461,390,23,974,733,727,828,899,952,406,286,362,677,650,247,88,159,573,772,531,392,500,63,679,43,694,801,225,198,497,84,999,48,24,493,170,467,518,426,720,938,576,370,491,863,90,261,684,491,414,927,717,323,305,740,926,712,90,245,705,931,105,307,619,136,464,708,752,646,233,507,681,132,147,913,582,154,740,799,511,979,69,610,418,290,716,92,532,85,913,883,781,344,919,174,858,737,533,614,560,85,100,863,348,162,877,292,454,698,529,914,77,144,7,382,402,861,537,503,240,339,578,515,482,150,394,280,296,462,813,843,931,771,217,958,184,162,457,585,552,120,532,857,730,376,74,503,609,541,671,232,401,70,684,513,715,19,774,13,570,370,307,59,958,735,231,700,859,607,9,589,172,336,468,358,260,756,611,272,344,5,764,57,481,5,567,125,172,127,38,538,439,634,569,254,106,115,244,594,690,820,887,7,511,81,740,883,824,907,854,882,300,74,892,306,60,445,359,78,926,547,184,57,765,95,170,856,308,630,189,703,263,826,513,345,712,274,129,597,849,844,671,129,647,193,169,673,614,904,150,181,135,800,285,921,235,923,923,433,680,506,687,473,214,315,206,439,194,739,645,555,281,418,612,760,318,454,935,316,44,425,263,564,442,340,625,60,806,103,551,668,435,146,98,863,820,21,50,167,667,519,351,509,169,380,182,89,38,358,57,429,969,227,971,90,687,199,325,134,744,873,165,833,595,690,112,217,279,895,30,108,344,758,211,693,937,905,414,872,466,200,299,704,309,435,701,460,985,614,503,299,260,883", +"275,276,206,322,829,430,389,103,230,718,567,677,896,945,107,475,382,369,747,237,358,877,511,364,120,693,337,996,604,814,517,653,654,829,55,884,163,985,450,550,889,714,361,516,402,661,886,164,145,929,613,567,121,853,240,463,50,963,625,246,563,889,73,397,853,649,940,531,808,138,190,629,666,114,896,62,144,422,467,84,861,430,773,259,479,387,688,131,770,911,359,801,933,802,271,21,98,958,136,936,573,345,832,728,654,636,813,303,460,686,402,918,830,500,387,718,593,295,848,127,419,445,972,557,940,863,778,598,379,401,172,157,867,205,631,821,905,193,85,895,574,96,452,751,925,136,713,989,465,632,287,34,147,270,372,181,983,487,324,922,621,958,885,373,427,365,998,680,132,157,190,308,766,222,221,932,359,611,667,187,938,643,881,939,721,231,626,872,154,687,304,219,754,707,678,927,254,33,664,420,775,221,825,484,46,782,542,788,349,442,564,89,237,114,953,751,989,205,960,189,722,700,106,130,541,25,220,230,758,360,695,246,296,743,537,679,549,103,477,98,61,625,743,488,372,9,520,256,611,383,334,300,527,136,811,640,954,569,909,930,318,764,228,704,426,100,693,234,956,630,277,327,433,558,626,52,324,566,628,319,335,522,451,379,510,50,565,692,387,653,307,778,789,599,619,834,411,239,935,574,134,239,630,649,482,146,656,491,446,54,805,171,182,247,223,579,642,245,44,314,176,559,722,588,431,4,489,823,424,217,757,273,527,74,550,902,217,51,783,757,86,741,552,742,256,900,348,996,664,231,759,220,241,53,882,400,487,723,996,5,660,492,321,827,163,527,455,674,82,820,109,968,479,944,230,668,946,12,691,790,68,734,424,285,953,156,487,183,203,751,509,248,64,42,448,378,64,751,4,295,306,517,308,418,608,579,846,492,573,667,449,458,451,925,66,694,799,672,104,205,291,467,53,705,780,284,586,593,750,928,955,546,836,929,718,331,52,882,238,535,458,952,694,143,360,2,59,688,175,555,649,353,569,771,537,360,778,320,20,958,350,79,725,865,786,500,613,28,720,227,73,233,570,931,484,675,209,699,632,282,184,444,757,356,159,796,698,772,626,400,630,940,191,234,936,222,392,79,314,884,830,857,665,821,454,147,284,130,119,351,362,380,605,876,940,974,323,759,375,370,58,479,372,941,470,184,105,853,566,173,695,148,558,906,527,347,2,526,366,246,414,595,389,938,87,282,265,609,357,245,631,86,297,198,166,410,730,195,86,794,449,977,796,561,546,830,600,744,83,926,837,107,506,392,434,771,480,28,7,315,513,177,420,739,637,556,981,930,585,55,898,896,24,719,856,745,602,157,965,983,342,457,122,717,182,624,273,140,906,67,533,538,440,458,936,403,192,60,586,643,95,746,417,967,959,54,983,133,11,338,497,960,112,327,143,927,491,225,377,628,664,0,251,288,442,642,221,706,972,11,761,773,23,296,928,829,859,185,237,452,398,417,410,819,830,431,755,996,247,959,885,555,329,612,34,151,345,141,418,249,29,873,166,165,239,963,871,47,983,238,981,960,704,220,953,938,287,191,370,37,597,487,473,671,534,674,103,601,614,520,862,12,723,599,620,589,891,857,296,862,471,196,349,100,902,584,537,559,690,112,978,64,766,719,229,632,348,259,738,96,892,305,836,310,766,929,741,841,243,950,304,130,616,373,199,43,576,875,797,187,906,218,322,572,88,875,315,823,566,302,89,6,685,82,773,227,920,257,141,398,446,966,454,582,802,639,342,859,519,888,52,221,495,791,571,15,184,147,712,657,490,351,315,969,15,284,550,684,877,983,609,633,611,303,65,906,840,794,897,93,119,376,630,173,841,882,475,182,147,915,573,244,773,823,618,559,327,489,420,63,720,990,383,741,488,350,731,270,651,175,944,322,777,639,637,912,917,114,28,128,665,732,76,641,369,663,179,998,104,320,781,128,464,930,298,535,71,738,497,448,874,744,923,162,696,922,137,284,724,319,875,700,123,42,507,943,735,799,367,359,674,49,765,348,30,416,910,956,724,700,141,771,718,53,200,886,560,260,118,667,410,376,654,484,995,415,492,10,430,718,187,276,525,103,894,937,845,39,871,361,711,527,793,440,896,939,791,146,543,381,232,162,598,549,638,425,653,243,528,176,389,367,702,667,496,200,245,619,520,93,740,355,777,417,408,297,301,239,294,440,618,353,652,833,378,162,558,959,354,350,247,347,700,832,225,787,725,647,986,593", +"297,191,595,482,644,75,26,928,680,795,907,102,200,380,685,122,496,967,489,289,741,967,370,323,330,673,287,302,25,793,48,848,42,823,602,573,891,52,705,517,496,914,181,679,889,670,454,832,94,205,530,232,371,878,56,818,697,517,560,138,271,826,329,162,769,906,604,343,276,710,356,642,198,547,460,537,659,775,220,97,716,1,516,123,187,227,490,866,76,409,529,462,652,138,366,57,283,43,671,864,13,439,692,918,239,297,908,166,3,648,731,380,188,283,811,467,513,956,815,443,180,222,894,264,362,594,705,196,833,748,421,960,649,135,603,803,217,627,156,716,180,723,124,473,162,788,569,221,180,287,667,116,31,98,938,810,333,512,205,442,54,551,78,398,242,523,745,533,429,427,574,679,638,941,901,662,851,371,530,206,607,773,160,944,908,65,865,935,540,286,860,475,443,692,640,776,711,152,325,686,800,840,658,11,609,65,866,364,240,971,825,641,17,4,499,848,784,693,774,235,106,420,574,666,622,703,753,319,216,304,521,414,47,250,903,554,279,670,5,553,721,194,365,193,470,38,122,407,521,69,825,435,159,675,442,361,105,551,664,107,436,45,992,188,313,883,951,308,150,764,663,994,835,629,120,537,850,631,839,846,884,720,809,832,353,299,127,191,618,808,360,394,329,511,695,687,136,748,850,933,299,397,677,23,706,188,870,590,250,171,228,612,385,637,249,122,554,410,767,311,524,435,339,393,266,38,117,932,391,282,809,408,143,838,591,983,278,613,876,35,298,404,862,599,979,45,440,218,814,996,703,976,834,406,363,821,522,466,559,385,318,953,74,335,696,242,22,819,454,812,447,853,533,672,909,757,714,818,667,315,822,674,696,119,590,390,510,247,20,381,504,743,172,532,199,266,786,333,289,862,731,859,869,917,212,319,529,176,670,586,514,145,222,656,777,492,805,623,549,920,354,263,129,243,24,977,521,866,924,602,225,430,454,562,831,525,970,388,83,566,450,905,884,923,71,884,812,815,905,634,23,382,132,335,60,624,727,148,138,919,396,900,260,216,207,400,907,507,666,788,316,484,961,921,72,208,858,756,610,289,568,860,657,664,978,61,91,588,676,24,667,551,872,923,254,143,219,631,404,296,710,863,978,673,741,240,510,471,218,45,810,759,764,311,696,544,418,306,376,675,775,472,791,522,279,590,732,825,621,240,469,499,563,810,840,519,53,479,969,96,210,723,462,989,471,549,663,489,533,259,430,539,570,37,273,924,854,703,690,868,388,2,885,243,226,285,151,87,437,820,466,758,555,357,949,777,530,966,240,320,730,603,831,389,569,239,731,233,837,439,733,941,773,67,903,126,477,406,882,859,143,308,182,58,364,169,644,371,67,907,857,806,607,472,49,964,645,419,413,215,770,184,853,131,743,464,600,842,954,882,850,680,444,341,75,147,533,337,80,859,657,251,0,446,559,783,318,430,505,753,114,970,341,959,915,433,413,759,228,282,395,915,717,654,591,437,436,855,896,102,653,316,698,118,119,186,823,173,665,870,831,648,599,75,393,914,766,957,944,392,931,402,995,597,97,675,349,820,655,506,689,957,824,901,797,413,382,263,768,229,122,613,276,803,256,356,819,617,138,667,761,504,518,672,187,240,255,592,132,369,118,226,222,137,822,941,44,317,550,166,916,27,888,404,289,778,167,12,947,889,760,498,127,453,483,566,441,873,535,426,160,306,628,807,705,139,251,199,75,808,330,586,719,209,741,558,269,936,608,539,988,681,409,874,637,535,393,679,878,457,535,881,981,260,387,635,557,986,962,152,916,149,259,869,623,865,41,877,224,340,276,858,585,193,892,204,762,896,741,472,992,243,670,932,189,276,838,507,237,150,181,303,135,604,63,25,309,485,953,809,51,667,614,240,588,606,83,277,625,967,38,556,844,166,314,300,314,147,53,640,579,926,885,931,973,984,256,953,617,261,847,227,465,581,567,603,220,665,834,179,155,200,886,152,336,883,573,426,187,452,975,289,571,853,712,59,588,145,367,352,149,955,973,974,64,979,895,811,499,569,334,640,535,75,987,173,834,838,428,818,788,230,743,555,509,20,707,318,168,628,586,423,222,99,121,100,38,605,163,869,842,877,506,765,228,564,50,896,467,704,781,505,946,819,65,54,173,757,295,37,811,24,134,639,436,27,2,137,306,830,216,941,211,672,498,339,835,537,832,202,186,697,298,828,755,389,139,163,226,986,843,933,774,56,940,627,749,644,51,271", +"246,218,5,542,115,619,543,855,931,346,724,220,46,128,297,722,983,253,720,836,460,903,798,753,999,67,838,87,416,234,146,460,784,127,298,921,798,657,691,907,67,775,843,543,211,407,51,790,650,12,755,778,109,851,921,125,511,601,17,770,938,322,50,496,354,257,800,350,270,145,727,686,45,276,73,42,756,909,274,438,713,349,138,798,122,825,622,751,120,267,39,553,670,636,895,809,721,684,519,596,36,212,899,866,768,972,164,885,902,61,874,41,201,531,26,457,597,740,553,748,3,175,829,829,9,369,173,902,754,43,900,19,474,692,611,917,463,950,966,556,747,132,21,352,558,484,33,662,315,749,140,227,355,680,116,512,56,691,591,162,373,721,701,974,424,445,408,631,747,510,972,234,825,340,398,521,727,601,836,591,410,65,220,58,271,712,502,44,587,531,502,915,631,905,813,709,317,38,379,825,533,457,345,90,937,138,413,738,759,455,338,53,706,978,933,649,808,219,170,585,108,128,811,139,754,408,338,854,307,348,260,160,763,433,432,552,294,442,382,916,154,580,656,274,888,301,633,608,57,770,17,287,226,530,339,15,568,946,108,382,241,440,603,751,908,175,259,796,653,360,398,813,943,769,123,49,174,29,59,2,434,2,872,829,692,687,26,757,154,983,872,873,587,44,156,601,226,964,791,901,505,12,586,385,797,994,236,990,231,17,51,410,246,623,196,326,880,676,716,505,743,605,192,739,908,482,965,83,440,950,331,97,80,159,276,16,40,662,119,701,72,924,210,725,622,680,484,163,502,564,606,200,165,20,970,343,157,800,903,560,705,689,542,674,130,384,837,974,855,103,855,219,858,7,283,273,507,331,938,434,708,432,459,422,46,8,989,659,603,111,595,315,492,164,750,560,701,593,713,184,145,175,738,813,460,516,360,551,354,524,207,980,953,165,330,111,51,768,367,246,280,124,441,668,295,793,799,807,699,521,501,754,728,999,503,713,500,248,100,410,359,907,994,103,716,691,919,480,467,699,310,275,787,417,468,904,919,432,67,910,583,909,746,336,168,716,569,444,816,894,643,139,177,4,441,216,951,770,673,169,236,552,512,347,572,411,269,624,997,31,994,696,629,580,558,652,527,739,823,596,430,750,594,636,114,672,314,251,983,125,169,240,10,37,812,734,492,373,807,325,836,136,892,800,585,397,731,68,739,570,508,684,878,489,257,992,757,54,822,628,168,160,889,449,934,858,249,232,585,807,739,761,278,635,134,231,281,338,16,731,321,574,223,827,930,93,893,588,361,152,457,834,100,553,350,679,765,793,670,867,67,125,714,504,542,273,949,441,259,733,135,283,328,420,475,291,881,325,490,340,796,287,933,245,343,116,770,258,615,358,290,657,918,10,995,897,184,883,770,18,644,440,948,720,736,659,462,156,152,427,760,635,393,479,278,956,958,989,949,464,471,288,446,0,664,858,119,754,875,334,368,403,750,767,292,11,204,744,186,579,390,367,482,160,594,276,852,846,164,869,494,155,920,205,530,872,764,473,7,804,793,662,792,919,228,821,264,312,172,246,955,689,888,255,870,132,887,444,740,927,505,866,198,608,580,984,607,281,338,791,877,696,253,109,541,890,384,224,193,700,671,520,632,400,578,49,719,803,433,286,289,201,596,62,307,972,787,95,655,416,903,860,259,293,820,481,520,857,271,87,14,793,424,199,769,29,512,797,281,143,49,426,498,448,770,165,561,282,194,728,697,317,175,588,206,918,551,523,383,868,714,973,194,74,924,39,373,860,179,179,584,461,923,643,627,294,419,432,23,832,93,542,910,220,251,647,994,25,868,602,46,340,771,75,422,534,329,729,562,870,351,277,769,279,110,910,514,790,584,510,64,660,69,690,51,190,595,349,562,244,497,239,690,251,358,342,599,417,692,264,759,731,21,40,267,604,290,428,459,190,303,15,832,969,661,535,891,667,713,472,343,696,493,876,726,727,129,109,874,259,12,16,915,130,536,433,294,97,243,437,49,570,78,473,454,947,272,252,260,372,657,957,556,369,70,230,350,738,439,985,426,416,981,348,180,843,378,233,638,815,18,525,42,916,546,137,574,499,766,680,373,655,537,489,379,921,872,550,698,317,143,63,723,597,924,192,135,517,70,183,10,651,262,230,278,322,528,393,80,258,966,271,249,349,143,204,391,9,282,994,181,48,325,567,753,313,862,757,896,84,160,37,329,641,810,362,559,136,904,369,594,216,338,313,13,462,520,484,207,672", +"904,503,895,746,935,463,593,883,594,773,602,511,535,334,353,690,238,717,504,116,348,770,518,805,576,25,695,762,476,293,524,527,753,524,499,914,167,507,55,830,520,347,11,849,474,124,35,549,491,628,484,387,603,582,210,126,459,574,846,701,449,512,504,579,73,516,488,223,335,854,35,742,832,753,212,25,358,407,153,24,525,688,222,787,950,838,657,325,412,910,585,216,896,436,225,554,74,846,165,775,551,762,733,159,748,806,716,875,938,424,95,578,374,41,371,297,36,807,937,363,740,547,77,193,20,319,228,719,910,194,48,318,444,213,382,202,365,296,290,872,125,644,37,598,921,56,797,280,606,629,498,132,196,800,461,436,565,552,643,419,937,243,65,466,968,995,84,831,265,23,380,827,655,994,364,256,113,479,764,870,359,43,916,387,842,120,71,942,133,920,28,512,962,772,928,996,583,580,606,952,936,714,287,149,516,195,722,261,211,207,271,767,436,646,525,671,194,355,626,217,780,135,538,882,267,159,474,442,234,147,315,175,199,254,120,953,178,934,295,403,505,595,422,53,65,637,903,651,533,342,712,9,68,378,77,625,215,638,909,732,988,83,485,834,108,751,194,299,897,877,103,869,631,727,627,975,657,329,155,986,396,487,270,854,595,646,86,419,799,440,721,82,581,798,506,132,884,778,534,940,809,634,50,808,233,300,854,302,689,381,702,839,384,282,546,562,455,477,385,58,158,30,481,81,574,371,517,618,710,756,372,412,491,743,658,942,937,83,279,261,184,753,857,848,159,304,404,856,357,529,205,854,421,754,532,790,956,778,225,622,534,118,233,301,180,911,495,661,553,607,553,699,360,403,361,18,339,243,625,923,816,348,854,455,629,912,313,696,739,596,54,242,589,506,867,156,924,717,839,549,733,380,355,727,960,55,956,52,386,590,561,466,242,395,638,584,195,747,963,2,574,456,630,16,972,70,236,779,299,664,867,517,429,717,571,413,26,172,492,42,917,730,106,449,408,997,36,445,265,354,420,937,642,867,123,251,352,798,259,27,763,520,446,260,686,519,286,44,770,490,984,80,778,670,139,804,907,862,520,992,513,265,847,111,658,73,355,918,961,646,32,278,841,97,129,609,864,379,720,945,859,848,841,186,853,442,633,168,456,465,252,431,666,248,105,955,831,832,656,650,353,336,819,432,785,820,296,125,29,3,71,478,615,219,317,559,241,66,117,396,796,55,561,25,136,839,250,887,970,758,685,83,397,822,369,957,623,251,662,577,586,330,62,793,71,169,744,225,644,811,386,953,747,545,582,96,429,263,145,917,559,424,122,484,477,531,93,39,70,997,922,92,311,668,742,709,865,755,829,533,408,394,812,980,158,230,940,289,760,446,874,55,787,587,457,270,353,738,162,98,442,458,563,710,845,23,161,209,76,496,395,584,106,790,933,966,773,594,853,747,953,442,559,664,0,97,986,905,337,344,463,499,723,698,486,582,845,713,448,318,615,773,920,397,785,805,655,836,234,146,338,827,711,135,791,741,60,970,225,223,220,862,529,268,185,370,664,327,583,990,521,983,451,376,996,502,118,793,120,356,362,754,509,820,265,245,14,39,459,914,377,778,577,842,201,625,934,800,660,524,977,535,779,985,11,609,469,476,2,739,823,488,469,810,656,17,403,596,364,795,574,9,515,165,902,816,356,781,480,190,752,32,35,553,209,673,635,679,459,657,70,147,617,625,682,962,478,216,20,534,965,963,625,364,96,455,851,490,141,730,208,955,336,110,742,396,787,496,114,269,514,448,645,974,345,750,773,382,745,345,549,381,314,501,737,727,666,911,537,42,787,433,396,545,540,465,599,596,298,188,703,704,728,934,694,597,225,154,179,235,588,205,730,72,140,597,171,34,453,588,298,66,616,463,182,443,881,722,204,348,869,489,430,76,65,894,357,913,833,30,372,627,865,444,714,881,141,304,992,538,997,583,974,896,452,936,296,400,860,369,617,132,140,595,681,725,480,828,965,781,271,886,556,221,506,100,939,354,152,907,662,668,96,909,335,548,123,103,410,762,160,15,761,963,860,395,415,539,361,948,384,923,366,673,385,975,314,988,308,540,104,157,199,169,424,623,730,282,289,785,84,576,731,302,190,823,431,663,696,105,483,64,61,338,107,324,106,130,637,302,722,11,582,877,861,448,628,761,784,841,293,493,930,77,158,858,896,320,109,545,581,403,942,737,669,937,678,33,839,64,751,148,49,305,367,732,426,24,14,385", +"24,751,787,391,807,196,847,117,105,259,150,303,366,866,357,676,182,587,350,171,520,491,659,614,938,618,521,501,775,377,794,641,583,892,188,813,723,274,899,79,163,855,927,121,579,243,348,340,307,580,624,742,475,732,211,268,899,325,259,614,669,735,942,460,381,128,498,708,800,953,271,622,325,301,802,885,473,927,892,375,733,814,166,491,179,817,918,33,138,690,202,693,314,823,659,956,815,736,485,710,252,47,80,732,559,459,240,497,645,243,655,655,895,212,199,968,423,414,181,838,342,509,724,78,362,506,156,261,500,389,691,926,644,105,743,441,843,296,384,331,230,750,348,663,946,735,816,85,869,782,455,832,369,604,154,43,263,778,841,293,894,920,465,75,129,624,162,570,258,444,574,760,298,109,976,658,763,70,820,188,245,608,462,870,571,710,607,831,167,916,300,778,799,22,981,375,530,714,759,772,750,80,189,998,249,905,887,386,248,629,396,61,149,300,724,928,359,650,801,247,13,284,20,126,338,83,136,629,230,750,887,865,590,862,659,931,16,78,271,944,189,681,110,904,65,119,842,324,737,562,827,613,643,535,171,186,16,830,55,2,269,732,130,885,609,728,579,957,839,532,861,355,24,24,497,871,42,488,76,586,508,24,732,202,756,38,565,389,929,340,224,185,564,703,998,743,523,292,33,952,712,851,590,274,781,531,70,443,952,319,98,958,664,1,229,15,407,3,333,985,117,899,870,567,714,167,188,806,908,177,114,33,274,434,252,488,169,483,544,919,738,203,191,448,373,618,232,297,296,37,50,886,16,786,831,843,181,388,177,402,618,57,240,534,159,835,651,121,296,656,669,75,617,544,672,123,997,596,287,719,668,550,741,317,25,937,258,919,864,576,15,942,25,544,411,558,579,728,327,421,294,972,462,932,740,377,33,879,887,477,558,481,856,273,595,745,252,135,937,717,897,842,175,339,83,985,905,746,242,803,609,354,831,688,639,730,100,671,745,811,464,695,631,419,999,337,870,33,965,881,467,640,526,523,210,480,204,155,985,846,160,936,359,584,965,597,280,20,828,661,611,742,284,859,243,729,68,197,760,571,708,118,579,598,895,464,224,869,299,971,822,459,544,673,406,845,469,62,736,30,905,441,588,444,15,251,899,585,376,174,328,517,61,915,27,224,283,911,310,421,520,303,153,957,652,763,808,146,553,52,297,136,836,245,821,867,83,693,557,74,146,133,924,217,655,308,829,537,641,94,682,153,903,459,911,839,885,422,432,116,154,534,628,798,967,108,621,74,300,804,430,800,296,682,723,283,576,926,940,592,367,521,112,870,511,853,463,633,317,581,438,503,198,244,494,360,761,72,731,900,738,943,538,270,291,793,584,708,937,416,777,112,61,256,679,449,602,35,638,509,322,318,49,898,490,924,644,509,794,818,743,119,7,561,872,63,883,294,851,825,270,642,783,858,97,0,991,480,901,265,246,391,648,119,187,710,45,35,507,359,646,846,997,582,510,89,501,266,217,121,143,28,475,599,955,304,666,70,196,92,436,670,658,654,483,281,984,665,303,139,283,419,906,112,873,483,349,687,143,16,896,973,472,500,499,905,691,743,640,761,263,633,440,414,178,848,697,14,462,75,37,724,816,805,853,631,315,213,158,870,931,609,160,507,221,921,576,261,277,663,777,876,713,431,115,565,452,576,443,432,957,801,10,839,55,684,109,610,907,629,205,881,464,754,130,835,44,865,590,674,234,871,818,822,511,749,744,25,763,301,601,991,876,349,234,319,586,862,903,380,427,242,404,499,602,131,449,645,363,620,674,494,790,402,989,665,731,334,4,114,707,174,738,510,891,124,468,582,736,384,501,583,186,481,246,793,874,716,17,359,429,485,115,667,523,907,149,316,451,923,425,10,980,58,641,275,528,799,579,722,204,309,921,754,822,929,379,420,711,112,894,242,504,453,224,233,557,591,504,300,853,152,218,590,109,258,654,429,451,6,5,290,28,637,363,243,239,899,743,410,442,104,130,8,560,210,790,696,676,279,471,10,239,555,52,989,504,518,790,355,665,644,229,246,659,460,70,779,507,779,259,314,767,996,336,816,345,314,901,869,817,565,327,544,137,714,196,412,791,315,556,458,878,954,851,16,435,435,205,427,728,475,313,58,691,194,257,11,883,925,262,179,12,322,942,276,324,993,700,487,873,168,582,385,443,149,563,15,549,754,87,108,83,142,648,435,630,406,772,660,485,961,107,818,113,800,952,20,412,396", +"327,994,47,529,283,760,648,45,617,546,442,585,258,16,159,805,303,582,154,757,947,579,195,138,56,81,479,892,613,643,185,529,438,536,831,408,205,686,999,529,352,130,22,300,910,513,832,690,674,921,49,111,4,431,410,894,58,210,342,14,431,90,594,133,915,723,98,499,720,314,639,587,834,52,263,831,535,30,138,579,38,566,490,895,771,221,394,878,306,657,978,388,131,834,57,95,478,796,621,819,707,753,459,411,701,51,98,406,157,554,465,998,637,381,175,428,43,160,117,409,79,130,517,984,166,294,931,642,621,530,903,902,608,372,770,443,780,855,925,832,963,396,936,292,959,853,466,249,442,86,255,549,119,492,110,614,557,263,371,886,14,442,986,578,210,884,638,594,22,693,664,886,35,903,859,223,467,884,381,519,43,189,204,124,780,746,121,570,23,116,696,174,166,796,360,222,704,243,680,544,516,769,93,275,630,187,406,834,421,336,752,288,110,129,80,74,909,937,894,145,557,948,385,945,191,761,798,766,827,153,873,513,256,517,802,276,462,298,571,353,357,259,756,815,390,486,639,12,237,739,599,794,905,679,782,180,961,9,566,308,442,61,230,645,787,899,676,380,881,420,805,634,818,117,316,332,63,961,260,211,208,69,311,67,996,378,84,132,318,139,223,338,64,362,967,43,943,217,364,194,762,814,555,926,594,244,108,501,903,613,630,410,562,920,606,41,75,530,120,233,93,936,211,896,408,280,776,919,253,349,325,278,695,536,908,292,183,219,543,636,218,112,583,308,617,945,226,554,850,382,959,700,234,763,247,719,698,870,353,838,675,965,638,329,913,271,669,928,531,994,410,764,573,887,193,301,377,268,304,76,693,154,823,622,852,551,414,663,863,49,541,550,966,648,369,368,948,586,830,893,351,735,67,532,176,182,771,863,523,339,17,95,917,901,575,582,249,952,72,721,179,113,673,661,438,707,694,220,58,280,177,502,240,2,261,299,149,79,881,545,643,95,100,238,846,229,143,954,742,847,532,666,560,203,670,222,253,931,430,757,967,604,96,833,639,390,233,904,332,368,78,52,978,737,277,795,404,908,450,349,92,274,923,88,568,808,315,709,121,81,433,198,567,807,164,246,812,379,336,216,59,1000,841,388,185,323,701,72,379,163,267,30,668,990,518,712,158,977,925,444,122,193,974,192,876,91,997,196,607,206,236,264,897,267,144,362,871,490,453,708,349,302,933,230,503,730,493,986,684,414,925,507,741,188,19,342,24,957,255,74,46,479,336,682,370,924,628,482,729,104,569,293,86,815,395,339,628,241,849,913,658,583,769,748,570,375,704,838,717,380,19,53,768,527,762,124,595,155,966,718,275,943,793,159,525,402,269,490,156,68,144,652,395,243,733,737,327,795,13,546,172,856,782,851,48,393,875,804,938,217,459,684,557,633,332,687,472,660,99,67,401,221,318,119,986,991,0,581,985,669,360,135,140,232,42,748,995,874,468,866,312,97,496,92,353,400,598,559,357,126,906,908,361,902,266,570,438,713,224,968,954,308,400,178,747,247,366,300,335,379,363,954,109,440,664,165,285,255,150,470,834,78,505,328,9,731,700,387,160,252,710,989,323,19,626,680,331,421,233,348,467,939,300,707,689,201,411,726,651,350,440,781,673,939,794,940,118,169,97,783,60,921,402,822,324,53,747,810,665,814,937,801,203,35,257,80,519,457,59,876,204,715,244,83,298,159,577,43,431,580,547,680,236,199,20,193,357,935,894,854,604,874,605,900,360,474,643,188,981,177,862,728,400,968,724,513,502,515,6,740,495,854,392,978,900,217,534,50,899,29,512,143,128,239,761,694,484,235,406,701,385,401,484,218,820,1000,988,407,388,949,652,132,305,230,734,95,183,83,124,220,429,441,889,611,726,658,303,954,493,353,100,56,570,327,197,705,259,265,761,107,608,677,756,838,987,188,751,985,976,10,765,73,474,709,68,163,972,729,486,48,473,4,930,538,381,852,528,404,473,956,11,452,604,117,675,784,503,379,74,979,7,172,209,570,72,111,526,565,861,695,128,57,660,140,192,870,33,358,327,643,792,330,421,897,184,210,611,669,767,45,25,663,657,891,595,337,569,628,682,853,455,100,833,441,55,458,857,836,455,278,848,234,635,563,975,421,123,281,845,734,90,713,297,243,270,920,424,433,261,689,57,429,606,594,814,735,457,802,4,329,2,745,219,232,666,65,26,746,309,410,347,651,716,431,419,131,667,628,153,362", +"474,171,844,74,48,490,138,955,359,564,336,5,858,356,158,149,380,774,681,111,474,350,752,576,459,673,623,149,505,148,695,585,48,484,457,647,130,955,97,386,230,141,26,520,285,419,965,805,941,177,30,6,750,922,127,203,868,671,551,686,569,834,227,348,774,574,431,692,715,271,951,408,768,330,944,168,960,107,425,942,20,120,600,154,452,404,432,736,99,793,163,627,11,333,507,484,205,619,847,418,881,530,70,759,622,438,522,885,963,595,801,423,647,404,982,449,43,925,96,112,695,693,436,360,652,383,269,580,228,702,219,574,281,626,240,973,752,739,412,130,50,312,212,352,646,879,112,203,818,682,646,698,122,989,121,950,791,670,848,680,440,622,243,858,323,600,324,3,899,388,170,203,749,60,164,89,705,129,155,583,801,487,395,50,853,185,452,550,854,532,457,668,956,175,43,872,501,920,897,406,630,5,105,539,52,52,55,184,47,101,850,367,583,470,559,233,470,663,429,894,32,140,102,550,835,24,860,364,970,257,245,114,949,804,734,176,208,118,161,844,212,337,12,672,814,965,796,26,228,85,830,19,171,591,716,206,142,760,867,33,562,292,335,617,654,450,734,863,152,596,573,627,270,932,657,738,562,635,606,112,305,529,383,959,39,763,103,410,643,345,99,228,76,925,385,614,609,742,574,241,115,274,267,436,642,979,859,284,773,340,312,821,151,93,739,897,868,828,849,531,301,306,193,977,215,243,620,829,630,110,604,298,4,596,788,455,208,160,256,183,283,918,249,175,866,568,855,816,805,140,761,881,868,536,198,53,792,473,56,260,604,945,141,849,244,546,114,857,866,425,206,655,373,344,970,917,383,366,189,12,220,994,479,935,810,45,9,949,135,197,329,194,332,501,647,587,632,14,735,340,924,22,132,155,564,356,286,206,77,305,971,63,618,749,414,799,927,695,694,573,432,598,590,511,896,872,901,402,256,510,238,693,640,708,226,735,421,232,628,960,670,222,848,748,999,518,186,430,242,288,419,776,984,412,261,483,927,138,635,734,119,586,812,304,861,469,886,174,504,429,219,433,942,382,223,420,363,790,555,141,984,375,892,279,911,978,795,266,71,887,268,801,948,887,148,397,713,166,441,567,902,283,829,245,790,816,629,124,310,452,40,865,221,558,482,735,660,690,921,393,17,750,157,371,583,141,603,94,484,575,572,478,449,271,84,598,877,305,360,230,358,416,217,168,657,495,264,824,958,644,494,544,811,528,937,772,754,169,173,944,743,696,943,838,981,789,460,341,241,640,360,592,140,478,68,702,268,836,316,53,826,290,439,436,604,491,383,938,529,281,356,414,144,234,969,29,769,609,439,235,288,70,203,140,207,24,906,454,380,437,335,848,657,441,132,901,922,910,191,504,892,100,529,65,908,434,428,650,923,330,763,465,715,885,610,458,355,688,570,366,461,706,430,754,905,480,581,0,992,825,975,951,899,970,424,444,595,107,646,905,929,305,436,862,862,829,930,436,270,31,197,897,307,275,938,174,704,826,599,547,735,517,745,554,885,510,14,942,628,794,426,5,625,445,908,835,688,911,899,583,65,887,806,368,361,35,3,608,186,920,987,231,916,489,349,211,834,181,920,176,177,489,74,624,372,565,771,349,307,604,852,157,13,788,63,37,102,771,167,115,963,2,23,627,179,718,789,367,679,150,629,195,702,446,616,519,511,642,297,328,414,318,759,312,720,249,767,396,368,682,914,121,450,302,578,716,768,621,68,277,561,277,294,579,420,466,389,583,233,224,121,134,420,213,117,284,489,397,464,590,683,236,342,45,615,79,6,748,104,301,887,595,114,906,29,600,392,406,958,141,947,599,641,601,85,67,526,93,668,753,888,162,362,34,524,598,363,715,520,828,709,181,462,597,832,952,427,46,210,534,376,28,929,958,499,552,977,457,204,526,40,821,144,451,485,546,180,545,331,209,727,466,389,1000,480,603,347,424,386,839,209,451,910,732,366,805,739,716,755,86,731,176,52,679,413,27,883,193,304,669,433,366,198,6,983,897,919,870,236,492,529,977,190,375,816,461,405,951,433,518,33,94,129,344,33,531,140,792,381,362,45,639,420,581,227,558,565,80,558,862,127,165,761,80,98,749,450,576,820,885,975,612,830,331,261,634,279,732,138,117,301,153,994,187,247,655,542,217,173,424,196,649,525,479,323,695,223,855,224,817,812,268,2,641,671,520,252,979,128,284,46,205,33,55,445,428,853,462,612,94", +"455,530,458,858,38,338,134,882,169,265,278,109,980,25,702,491,734,382,564,272,371,880,670,778,822,297,694,11,133,207,220,963,512,235,598,646,769,823,395,768,157,684,972,33,499,336,291,572,760,998,204,453,840,434,808,106,43,18,137,593,957,5,14,826,133,480,787,851,291,548,329,235,335,975,130,4,566,495,879,513,597,184,484,135,685,22,85,314,262,980,504,84,758,812,938,374,235,475,639,332,947,619,438,236,4,721,947,729,714,30,314,700,772,736,790,93,845,186,491,591,315,394,337,442,706,401,359,52,615,28,498,196,874,478,869,476,851,788,395,736,438,607,260,856,728,137,361,639,725,777,173,676,142,649,970,723,746,173,146,150,653,940,74,497,264,135,689,351,786,348,212,348,268,903,82,271,53,427,282,899,911,632,470,367,785,875,282,906,711,828,631,774,25,766,585,591,635,345,939,631,124,811,718,979,51,985,840,89,959,903,546,366,389,285,468,483,117,897,744,215,769,873,143,797,257,170,509,573,485,292,157,289,583,280,185,85,3,289,960,39,334,255,355,302,514,766,468,113,623,544,87,295,342,987,157,480,243,376,718,463,884,881,184,93,575,439,743,492,433,944,515,655,607,569,583,833,305,657,223,998,923,70,432,758,960,190,938,930,858,712,267,98,83,433,503,343,472,757,415,730,497,270,63,108,858,976,449,125,590,473,905,969,16,879,149,191,870,664,877,497,595,629,979,230,118,214,223,578,952,707,670,328,730,897,795,801,595,130,295,889,823,711,944,859,486,42,912,493,9,785,408,105,995,312,191,57,280,263,604,609,316,209,770,350,59,946,847,22,32,148,629,396,925,975,101,579,217,867,431,673,561,432,4,930,30,362,181,908,551,807,567,166,959,906,474,966,884,715,314,529,530,958,581,206,479,798,147,369,917,316,822,807,182,402,726,771,279,817,429,248,734,845,466,421,186,283,765,633,505,906,512,856,596,87,752,202,747,187,948,762,231,25,391,514,544,896,335,554,874,309,240,410,89,90,216,175,211,654,777,624,530,190,455,648,522,414,862,426,910,98,803,628,419,642,986,394,449,829,34,47,86,616,393,52,309,631,274,520,524,573,67,266,979,134,975,257,451,280,493,292,903,30,446,386,88,921,276,405,821,153,606,67,788,689,868,373,671,456,280,867,707,921,12,108,360,353,236,745,438,194,127,471,634,775,307,94,952,877,818,948,653,165,402,930,183,414,854,682,367,875,436,337,235,817,563,880,399,609,888,952,162,595,879,181,511,921,670,302,976,757,792,969,127,716,973,724,837,159,883,622,717,932,656,696,624,925,965,286,654,490,467,805,610,280,404,416,868,13,725,132,397,811,735,432,385,580,615,259,971,330,980,953,631,908,77,903,735,422,417,98,623,321,594,810,65,336,678,2,598,609,150,695,783,843,18,34,592,345,634,825,390,972,505,875,337,901,985,992,0,598,645,259,344,174,360,120,725,837,451,782,41,306,690,220,924,618,687,732,118,188,470,324,803,72,271,18,914,868,438,36,823,716,447,663,422,195,976,59,338,187,532,784,792,200,356,719,229,573,258,320,941,538,719,366,835,46,323,775,892,269,525,51,297,703,490,691,365,18,723,658,107,464,962,922,367,768,592,886,285,318,179,468,803,339,241,70,228,609,383,11,663,887,244,816,386,548,750,945,762,167,68,670,160,708,421,345,272,464,320,456,282,675,458,187,955,198,638,442,883,174,943,836,889,750,488,349,941,839,395,572,924,85,827,245,609,926,365,998,867,610,122,875,483,970,576,261,308,650,164,207,493,349,716,72,747,881,783,982,596,911,106,519,365,206,379,872,550,908,217,757,645,728,498,67,950,957,293,924,322,532,644,281,731,879,748,780,671,646,904,200,831,625,922,200,848,727,363,560,873,969,273,171,956,333,951,233,99,933,186,732,947,379,336,136,813,457,259,548,536,844,297,752,795,864,256,75,581,641,766,626,252,730,825,976,377,620,363,661,940,475,384,893,741,386,481,252,97,553,774,238,334,67,736,499,589,553,503,412,913,731,294,264,203,384,422,605,271,373,997,689,933,923,721,400,899,377,657,915,490,104,498,811,7,486,122,357,268,145,887,80,457,695,272,978,459,980,935,795,257,957,637,685,902,450,719,176,937,270,937,664,271,753,692,750,565,448,807,30,939,102,482,29,973,757,700,744,711,129,328,731,723,69,244,563,421,204,991,796,294,120,878,398,42,873,221,681,18,226,130,186", +"395,884,451,355,796,757,430,877,649,928,813,189,761,366,42,613,349,154,143,479,60,406,763,897,817,243,716,2,40,415,391,347,186,460,440,687,321,903,197,739,492,149,326,19,419,935,942,490,510,359,523,733,31,46,380,729,696,541,452,503,53,206,658,980,360,546,335,415,523,799,618,19,30,467,836,972,986,127,49,227,296,351,111,568,110,642,545,942,244,349,61,760,91,568,362,980,632,408,302,396,7,94,962,347,583,68,751,681,239,956,838,995,720,631,9,767,891,78,57,56,203,845,541,903,72,277,303,168,175,90,334,193,926,535,588,115,303,895,273,199,20,726,787,203,750,515,534,429,889,399,545,368,419,642,530,320,243,732,815,320,613,27,657,693,298,179,507,14,242,71,204,676,381,639,580,526,817,402,118,650,646,24,189,495,263,953,844,586,186,769,922,887,862,193,182,67,822,846,397,221,742,319,190,174,261,129,149,675,250,912,90,946,402,223,601,807,613,36,166,64,612,212,536,894,445,232,251,921,695,648,884,762,123,238,431,475,362,942,195,566,659,488,947,369,566,539,430,557,611,849,454,777,264,918,77,925,581,768,888,681,505,416,233,383,277,272,469,246,880,744,401,953,604,607,586,736,242,318,966,552,767,683,526,70,937,824,315,578,877,517,173,98,804,820,527,265,246,919,374,983,397,926,112,853,417,17,917,866,71,952,393,501,631,9,600,782,607,486,283,752,938,52,623,709,938,891,110,403,575,376,376,859,602,981,470,920,528,927,17,729,872,570,626,40,295,522,466,328,781,18,716,610,458,115,353,883,531,219,776,374,884,655,935,702,73,92,574,984,368,415,611,638,707,296,7,38,510,336,990,355,297,759,585,509,116,156,296,131,77,143,617,97,185,695,951,519,417,809,34,570,886,827,277,67,287,203,436,747,105,290,28,403,245,658,533,716,882,88,934,428,573,491,881,63,88,75,109,386,982,910,275,935,40,95,988,299,879,68,188,949,712,943,569,865,610,17,246,885,42,886,90,989,523,347,5,957,934,775,180,398,407,771,674,615,254,832,109,346,134,319,735,893,232,221,46,542,386,428,651,704,275,840,843,87,717,809,131,190,271,157,961,423,66,355,571,850,777,266,108,114,140,813,245,358,853,67,230,370,266,462,881,16,990,34,916,962,646,588,603,506,324,982,598,247,571,121,850,250,12,223,316,971,179,149,400,879,336,169,811,963,67,975,529,254,430,751,426,409,962,316,776,682,669,220,943,881,327,209,432,498,50,103,463,355,895,318,562,447,98,884,383,38,758,456,12,343,249,183,441,638,899,329,89,96,207,67,859,909,89,280,208,314,845,627,883,966,346,703,371,219,733,449,981,676,20,30,143,523,936,931,719,976,238,537,222,357,715,148,161,28,797,141,976,974,369,163,518,543,421,446,332,994,849,277,805,348,640,913,152,708,23,11,753,334,344,265,669,825,598,0,452,785,665,467,912,705,662,638,355,431,597,296,316,591,675,499,596,615,833,709,118,86,877,669,902,130,37,245,938,536,261,580,219,451,146,135,451,698,416,573,241,297,593,624,980,91,502,240,276,157,363,6,688,83,182,478,695,700,30,188,61,850,334,228,491,64,401,507,222,432,307,151,613,708,581,865,748,299,44,514,266,607,137,235,547,987,248,232,133,103,150,357,267,838,459,595,992,587,301,807,601,82,953,36,236,543,772,79,185,671,658,488,578,657,757,178,19,649,234,344,945,276,351,342,85,798,385,145,115,167,132,523,696,213,151,915,467,546,725,159,927,982,716,706,280,936,18,835,577,668,54,422,746,315,231,383,13,253,494,220,391,318,803,639,654,537,489,865,612,287,471,624,535,548,984,1,209,284,52,781,382,751,827,88,932,428,532,13,721,808,429,874,566,177,102,899,213,232,436,679,319,652,742,222,725,479,430,566,632,309,973,902,829,379,18,119,234,900,760,140,267,321,190,518,33,607,701,663,487,17,714,203,155,200,926,103,811,482,329,342,57,802,746,66,154,245,957,315,993,696,556,73,980,32,641,923,206,827,527,164,460,77,316,413,141,78,430,996,745,588,183,657,521,75,180,874,90,920,587,693,789,258,505,477,681,718,930,133,673,462,459,933,319,130,590,575,307,206,572,961,612,717,958,934,116,831,514,881,906,331,561,292,782,190,455,884,168,359,859,260,192,155,382,505,606,485,910,167,374,429,556,539,184,941,657,891,724,912,460,713,241,771,636,59,950,2,415,130,718,835", +"148,538,269,46,924,161,266,718,80,365,709,859,407,431,715,56,254,261,881,695,291,991,144,621,165,678,14,200,758,471,157,474,455,708,62,834,437,883,779,999,302,56,268,343,445,965,969,184,255,22,176,559,840,805,670,109,895,384,295,410,541,723,284,112,783,406,339,810,833,323,93,575,975,242,671,989,108,838,201,155,515,768,72,15,313,142,700,562,529,577,226,473,704,616,351,545,724,257,432,255,591,767,26,199,753,819,689,538,488,178,528,778,696,920,5,100,221,754,756,248,866,411,356,593,362,265,94,762,204,330,213,75,323,156,34,484,633,607,585,196,518,629,6,447,822,725,764,137,157,25,389,194,884,244,345,106,909,821,535,951,989,415,725,656,920,279,987,851,190,935,938,896,455,386,62,585,475,605,714,388,822,530,775,296,55,939,40,952,341,227,842,852,23,896,79,986,148,819,735,113,676,223,498,640,792,586,58,617,879,671,794,621,438,476,131,587,967,964,619,545,585,6,403,902,714,535,931,696,808,531,686,654,703,592,233,237,143,612,216,284,131,987,795,371,779,312,176,438,547,902,676,166,220,75,61,190,429,680,68,776,942,342,647,782,829,641,790,497,584,92,931,400,364,498,911,840,118,715,956,504,121,498,113,780,137,589,578,725,991,938,855,586,341,981,509,820,969,911,405,978,26,227,786,357,18,657,499,624,467,703,78,93,6,949,760,24,431,59,815,202,140,17,427,568,177,788,426,181,921,877,741,747,533,387,534,946,474,717,782,856,889,535,23,761,2,575,490,809,661,777,292,997,37,877,302,396,976,692,593,36,964,545,465,847,590,484,758,437,407,958,410,345,913,72,740,240,35,261,204,941,352,523,428,267,125,722,364,715,608,9,942,163,785,912,647,732,736,885,783,997,339,260,115,338,794,191,390,428,712,495,607,427,890,363,35,751,447,223,458,86,988,558,151,868,419,310,68,334,433,174,232,7,736,844,600,729,756,169,772,970,730,200,649,360,352,261,517,121,428,507,138,33,477,375,117,753,577,994,81,256,783,444,539,421,292,328,121,235,737,698,352,57,24,423,710,656,882,779,716,390,191,752,312,499,885,390,986,990,133,329,431,476,730,349,675,948,484,670,579,451,449,557,838,789,194,934,311,208,783,944,583,268,158,396,202,510,711,313,340,956,481,11,930,586,562,417,52,267,342,21,205,493,710,672,746,764,215,83,548,846,642,806,793,984,440,345,256,221,672,961,561,459,62,193,329,522,815,523,17,427,407,31,234,360,898,17,248,460,699,732,829,24,698,318,603,754,52,298,241,623,109,745,476,481,230,868,9,64,976,389,280,723,392,498,671,746,438,27,327,753,579,654,368,677,570,57,30,850,314,536,929,597,961,15,761,562,879,261,520,137,296,520,311,797,121,107,744,948,898,347,247,164,913,29,5,606,305,834,112,538,974,761,114,368,463,246,360,975,645,452,0,323,434,5,671,212,159,489,630,581,373,397,372,591,681,178,671,654,931,75,19,100,602,990,922,446,621,349,850,985,918,820,789,602,556,824,407,571,702,458,474,31,792,349,217,276,427,315,689,265,573,574,185,40,388,6,217,971,548,606,58,548,776,483,165,448,952,498,910,777,327,84,157,608,971,709,561,261,162,346,488,422,840,897,946,874,168,20,979,991,883,112,805,92,477,843,608,154,465,148,523,519,714,8,795,730,967,161,875,465,803,657,266,631,621,779,490,412,722,275,225,867,338,666,924,60,478,291,419,375,796,445,449,957,857,631,279,452,754,249,347,258,663,116,751,764,709,789,412,49,761,460,879,332,204,170,36,232,254,266,194,634,532,131,899,611,244,212,693,960,227,978,264,392,114,574,310,627,229,44,521,628,756,946,772,581,586,964,75,731,573,225,51,144,983,645,4,366,523,540,70,408,862,432,164,797,849,451,603,93,934,856,407,354,926,290,870,296,501,169,948,777,935,851,429,339,870,120,870,182,736,249,273,681,369,976,602,277,287,84,383,434,927,404,795,687,968,866,190,841,404,769,23,350,553,417,515,38,893,988,387,310,711,504,843,969,83,564,554,908,530,284,750,471,347,629,440,139,730,763,473,207,594,632,102,498,427,628,563,413,267,158,935,786,18,350,644,688,621,121,210,242,976,229,862,650,35,645,139,95,953,286,821,642,28,221,55,661,412,293,893,229,647,182,720,393,383,174,173,691,353,300,731,775,243,510,791,819,382,379,801,191,180,920,864,649,894,937,570,660", +"330,653,716,530,559,64,439,174,20,612,766,250,951,587,917,281,965,897,130,7,60,568,884,796,798,272,607,266,363,398,808,747,980,991,621,968,985,63,293,214,440,808,10,964,996,684,78,516,716,565,165,930,928,196,404,412,31,927,137,994,879,526,51,993,670,429,233,878,972,722,173,199,640,457,736,552,335,699,394,654,170,257,55,488,342,427,884,386,184,792,578,492,607,41,300,937,327,300,338,338,988,367,106,678,449,548,388,223,518,328,910,543,906,8,204,155,740,35,818,200,685,555,126,967,671,680,12,807,176,537,921,896,376,972,593,304,511,610,571,631,426,57,915,625,183,86,654,206,569,498,923,526,283,907,864,43,595,632,725,710,92,782,534,65,704,339,685,752,357,253,67,848,816,280,29,685,35,61,733,536,179,888,298,262,624,7,933,170,290,554,551,307,80,304,387,24,969,45,652,700,404,388,936,935,877,19,720,438,759,829,945,443,922,89,476,474,685,90,665,100,451,912,508,737,527,959,551,488,16,129,480,409,507,417,34,558,966,80,417,839,245,20,328,707,128,91,963,806,517,897,985,357,660,454,743,440,225,25,154,230,185,862,110,820,444,771,639,923,430,595,865,597,353,942,143,848,900,384,658,807,135,359,884,21,496,209,554,450,585,633,28,124,613,896,669,901,525,924,332,693,478,93,505,391,636,65,51,201,268,926,719,610,244,116,120,539,50,104,670,655,282,524,962,827,448,943,975,40,143,676,874,352,44,625,947,544,383,85,766,511,407,541,820,163,284,618,978,374,148,679,315,114,172,276,553,917,377,428,390,134,292,244,881,727,330,882,767,801,463,588,323,827,208,549,262,659,602,413,80,964,402,490,775,638,83,797,641,775,402,209,609,57,871,604,620,556,675,921,922,523,287,876,675,148,353,236,48,721,29,44,40,928,585,96,676,228,969,121,943,621,327,845,380,702,253,757,852,65,507,889,295,738,864,257,753,881,779,938,201,855,420,571,977,222,177,235,357,869,146,270,988,270,201,42,419,104,705,126,30,13,344,649,172,623,852,986,982,474,459,688,49,408,818,852,687,272,175,403,372,457,662,25,785,792,675,717,618,42,486,296,599,67,116,261,663,864,229,204,109,801,938,35,874,480,58,305,330,158,571,658,218,438,735,954,346,358,560,789,280,700,189,938,758,872,844,418,649,681,135,212,264,133,259,103,400,901,1,463,532,254,515,530,155,999,60,678,774,102,225,670,692,352,314,361,920,272,957,466,286,693,348,821,132,818,719,942,34,799,205,944,406,922,542,304,868,759,582,572,751,375,87,984,323,440,280,842,261,734,910,803,433,790,681,38,17,736,829,832,486,555,339,990,252,543,670,130,663,719,891,925,623,792,834,792,759,808,474,603,432,83,313,861,520,739,720,40,74,528,310,789,163,93,359,484,913,931,65,401,484,6,733,773,970,403,499,391,135,951,259,785,323,0,892,537,726,931,916,80,609,332,905,250,118,363,955,233,777,267,89,405,645,436,525,971,644,255,451,640,326,872,371,756,82,930,689,716,732,264,721,631,353,168,925,389,128,392,26,918,903,563,159,881,428,40,60,425,615,135,519,286,959,39,611,223,141,980,410,694,672,193,646,590,181,764,200,292,485,820,779,928,77,989,115,995,91,254,819,247,737,29,40,253,758,868,996,348,968,957,865,207,780,846,617,327,88,895,665,286,619,463,822,199,32,823,931,38,201,232,536,516,699,232,983,898,684,696,344,700,374,51,582,190,805,607,231,790,464,526,708,287,179,995,284,962,917,42,83,52,111,341,73,557,224,569,103,195,48,957,91,407,230,277,933,723,35,195,744,861,340,359,361,891,933,806,421,286,126,900,603,381,927,950,943,684,109,924,895,686,192,776,362,257,913,986,830,839,836,882,966,512,654,158,474,277,994,572,735,796,846,289,262,60,494,645,516,584,668,522,699,456,336,491,426,967,442,310,278,387,431,32,539,535,834,463,169,586,499,887,489,698,335,349,92,337,584,936,647,827,463,912,615,897,449,508,646,51,928,91,558,703,386,10,53,324,244,958,270,283,907,769,151,97,418,574,273,933,647,813,494,513,398,999,392,382,583,613,878,727,555,282,778,958,593,105,406,431,645,489,775,246,73,98,137,997,220,510,657,758,785,93,381,175,106,937,626,905,601,248,272,3,636,996,312,890,727,241,272,273,923,102,167,978,499,789,248,733,675,178,231,574,587,761,406,891,82,395,222,868,327,735", +"919,69,260,200,160,626,858,536,285,390,238,387,425,677,832,49,224,383,67,550,809,158,764,791,116,330,185,868,632,400,322,577,972,69,857,110,527,234,213,905,256,930,34,876,286,691,222,196,754,718,580,560,536,72,130,258,869,49,315,304,446,592,738,69,101,529,898,753,267,405,863,285,520,288,534,566,146,35,528,174,70,811,566,579,431,959,877,585,78,257,945,552,60,329,700,61,444,255,909,561,98,82,291,824,685,359,893,737,457,504,809,385,374,26,294,417,587,392,323,847,348,565,166,230,792,911,853,362,914,285,628,702,964,286,655,51,530,847,823,827,290,168,171,594,334,725,864,66,974,715,213,830,357,995,395,56,658,886,225,117,210,783,59,861,846,189,467,297,458,247,184,82,841,417,967,113,580,656,282,527,699,142,179,495,334,277,360,842,980,371,739,172,851,418,272,888,172,325,139,588,413,428,951,446,589,636,150,10,792,502,884,647,626,553,642,945,773,829,900,159,610,980,161,165,348,602,178,38,665,433,5,856,804,895,581,813,185,15,566,18,201,822,277,855,927,656,815,961,613,883,814,304,802,587,398,871,207,252,504,507,783,624,736,404,715,866,217,994,635,368,499,611,881,911,768,489,454,133,405,645,190,824,385,202,716,560,612,440,601,363,96,791,910,560,368,189,698,166,45,759,885,358,73,81,120,457,622,829,937,820,344,252,138,603,873,907,791,919,244,547,272,294,417,445,733,72,638,508,775,610,236,447,411,674,473,869,14,171,187,791,908,41,493,235,524,832,601,139,888,648,952,744,404,771,598,573,827,169,437,756,443,171,86,514,322,493,502,450,111,216,259,135,871,575,76,241,819,657,780,437,739,206,212,931,792,430,950,514,538,226,475,867,988,519,913,83,579,469,984,865,189,628,988,344,994,494,692,616,949,918,651,220,718,621,439,614,383,598,43,539,624,864,50,426,344,331,569,82,964,782,848,956,801,661,573,652,251,543,105,593,662,186,207,306,994,44,455,530,636,273,613,115,933,126,378,985,691,353,507,693,678,975,720,952,525,900,402,90,400,906,93,372,992,362,233,480,777,950,763,409,830,717,189,521,918,167,253,754,439,101,285,25,795,751,860,830,890,178,217,89,647,329,388,258,8,472,685,865,122,563,406,116,102,266,444,286,516,638,909,105,243,31,442,766,672,250,140,225,729,929,483,498,617,262,937,45,364,147,222,501,351,270,582,102,371,633,920,728,796,428,393,239,100,993,871,215,161,874,945,948,500,66,267,974,833,138,965,756,925,318,308,939,312,33,80,598,880,613,792,453,580,923,68,433,673,965,105,446,319,207,927,43,635,908,573,26,172,474,803,50,457,779,870,5,384,951,595,375,702,332,775,98,808,975,161,316,426,846,525,323,195,62,924,517,317,135,783,404,163,93,149,401,33,837,943,380,263,454,929,280,727,23,341,750,723,648,140,899,344,665,434,892,0,930,345,614,26,239,200,519,874,713,564,423,237,786,418,148,128,795,282,64,301,908,420,334,989,964,31,606,119,614,345,458,582,82,499,227,638,866,44,251,980,125,666,983,507,192,247,467,651,206,462,349,66,636,734,3,107,17,996,64,466,410,801,878,987,986,733,18,728,897,350,890,949,224,561,950,690,891,48,77,316,595,995,256,952,205,983,657,389,882,170,276,740,210,843,865,420,12,534,88,508,984,65,29,452,612,213,382,686,535,170,915,287,34,966,584,714,987,965,51,725,116,902,825,971,953,213,44,224,632,84,178,385,600,518,889,743,694,958,397,593,310,66,6,895,985,749,876,562,791,194,100,325,714,534,215,957,601,987,938,611,229,533,916,304,225,26,216,686,144,462,680,662,535,452,938,350,368,805,58,485,516,519,361,711,521,467,990,453,489,273,522,85,976,642,481,347,940,184,99,513,513,752,626,22,267,282,524,788,529,279,899,103,901,126,842,77,224,19,930,604,239,381,984,29,300,505,772,511,638,565,628,846,931,653,268,30,176,388,423,823,886,919,888,874,838,291,724,494,789,114,517,865,999,227,695,204,452,803,170,137,133,820,310,58,349,671,964,452,926,715,281,743,663,752,825,54,817,735,782,790,801,650,621,399,267,781,786,693,832,937,665,212,606,775,367,15,89,819,729,439,614,775,838,500,480,700,76,337,36,364,184,625,846,23,939,40,563,109,991,86,662,710,805,904,557,372,930,324,255,682,997,796,750,514,117,335,31,698,789,397,210,98,942,577,982,245,961", +"710,728,849,344,206,395,20,461,548,795,895,921,622,11,59,419,237,639,239,860,822,141,427,617,718,958,675,568,109,963,717,501,756,633,915,531,289,398,970,576,204,24,262,503,897,299,42,62,518,842,897,860,719,13,274,906,602,70,291,984,351,921,391,387,411,896,251,852,937,608,564,153,98,226,664,161,625,277,660,93,229,985,250,387,21,829,149,59,783,449,926,100,836,419,229,932,559,463,922,480,280,332,75,138,480,847,318,77,218,806,475,658,10,174,283,959,61,520,302,73,998,936,540,713,499,913,690,103,377,570,592,323,860,919,866,431,817,924,954,783,345,664,518,122,581,59,186,536,8,146,393,171,744,24,674,472,9,498,153,279,237,212,748,168,213,318,166,91,582,377,817,586,603,838,360,675,546,750,937,836,805,220,957,738,205,693,921,548,60,576,619,768,508,474,246,707,815,85,831,106,978,589,555,792,841,75,369,809,479,739,386,973,475,113,843,569,283,407,132,863,319,52,187,349,214,29,417,833,761,565,286,671,133,380,651,187,992,311,577,391,690,186,378,892,720,463,102,805,310,861,612,891,110,609,330,600,762,210,953,94,735,607,849,202,88,825,761,175,334,328,319,557,162,119,259,255,218,617,583,870,244,588,270,98,89,696,320,740,141,970,842,854,942,547,796,745,381,43,978,955,998,318,505,998,735,825,855,342,584,345,874,790,461,120,731,299,662,695,157,474,724,378,602,917,634,389,417,803,584,322,374,864,888,648,109,756,969,707,461,321,746,402,484,702,720,551,122,890,540,436,995,546,436,517,311,428,570,711,421,364,191,660,95,424,434,190,141,315,620,331,352,256,997,901,485,496,639,167,418,845,613,634,216,780,54,212,566,448,249,845,163,316,638,425,596,183,114,297,375,736,707,491,510,357,569,863,507,521,725,959,942,573,291,343,713,934,756,429,398,86,394,130,698,774,700,126,887,470,716,925,151,168,477,49,821,462,363,921,829,205,845,34,285,879,276,220,169,624,929,168,207,295,101,660,639,994,746,300,736,934,194,267,708,395,205,250,252,591,455,137,87,691,675,14,467,242,529,176,627,118,371,31,94,294,208,429,271,451,479,173,351,20,393,646,743,792,655,543,327,559,825,643,563,813,281,207,982,742,922,923,309,785,494,437,155,797,97,180,831,461,13,690,803,140,171,174,581,845,538,458,750,215,623,405,911,10,531,673,698,258,936,49,9,621,16,524,20,982,79,540,964,638,934,840,194,36,952,853,187,303,119,921,220,926,518,925,550,277,819,323,735,132,644,953,1,923,998,165,889,816,274,352,89,919,660,621,681,920,414,851,278,666,851,195,289,332,173,464,153,560,483,119,326,973,571,310,35,504,365,307,457,753,271,436,276,701,733,287,407,321,907,319,57,367,242,737,649,388,55,524,524,10,158,388,776,286,639,813,785,92,828,296,959,767,698,119,232,970,174,467,5,537,930,0,867,565,127,291,638,1000,120,31,169,49,355,894,361,256,572,618,304,209,117,677,589,485,986,984,340,902,676,664,841,482,810,203,281,658,847,627,69,929,259,577,314,465,132,922,691,564,367,973,422,521,599,985,610,495,52,592,47,947,510,641,432,387,758,4,198,387,326,467,392,40,762,41,680,739,77,179,672,165,315,307,141,701,924,660,203,442,994,591,899,221,371,453,589,334,438,482,283,975,163,636,660,146,609,278,291,462,187,809,370,571,804,439,551,649,624,465,386,388,921,392,386,871,721,488,391,846,674,393,480,24,378,275,442,416,329,523,71,224,370,635,36,658,980,876,905,334,387,617,988,172,532,637,280,595,868,66,254,72,582,949,729,67,284,392,32,856,583,293,349,94,58,178,458,389,570,326,995,601,413,348,995,436,344,599,214,932,477,276,995,329,763,701,914,232,761,768,228,415,336,971,88,486,738,297,352,871,600,877,569,886,233,625,444,988,979,490,454,578,796,564,630,566,879,76,10,485,495,327,628,288,64,53,139,172,500,341,450,433,789,298,180,144,30,463,852,57,993,780,763,169,872,865,528,888,304,468,565,174,519,62,767,446,223,590,201,567,615,405,496,310,424,5,433,105,593,11,677,16,619,192,5,606,172,661,963,592,383,411,354,136,233,282,301,266,183,449,505,540,850,110,233,569,443,371,472,337,231,26,655,733,721,22,605,960,127,823,980,715,757,283,678,699,254,105,474,844,901,886,73,822,700,474,338,550,489,864,935,289,576,888,724,635,291,452,784,803", +"485,14,592,955,490,717,186,461,725,687,704,982,532,138,11,962,712,777,111,253,12,327,101,834,51,617,491,497,2,484,734,376,737,71,536,46,450,43,715,351,564,19,963,283,910,142,565,242,228,563,352,596,261,321,509,15,696,788,888,535,283,903,717,328,794,894,953,158,743,644,145,516,365,243,791,332,631,496,59,879,781,863,476,232,173,445,55,640,250,825,732,384,86,371,498,755,938,767,232,244,235,453,202,296,854,933,513,1,106,331,309,294,362,119,315,909,639,214,211,561,637,590,351,620,260,556,948,442,727,783,257,885,260,962,69,144,564,823,372,832,73,589,541,974,458,698,512,143,860,932,69,16,477,259,797,860,486,188,97,248,923,234,680,886,60,540,145,868,58,900,336,894,327,684,509,222,691,98,460,878,409,579,834,262,819,471,733,255,581,740,699,3,836,356,542,966,592,368,354,959,201,602,406,162,301,906,237,684,424,602,923,650,780,517,680,227,739,383,626,764,650,176,768,432,792,393,811,436,890,842,525,756,994,234,923,145,596,288,701,265,36,329,213,45,173,483,512,222,760,454,953,829,379,304,178,268,409,967,873,847,87,677,128,96,322,840,96,938,526,519,149,331,587,815,742,257,629,13,465,457,592,656,683,349,314,906,403,411,352,748,28,381,175,727,218,347,245,990,434,715,876,969,352,85,75,150,299,284,472,832,732,486,45,840,868,130,889,271,599,501,546,531,251,326,555,222,850,256,451,935,901,855,73,158,637,38,768,282,659,895,633,729,451,643,384,771,130,409,592,820,62,806,936,222,836,998,911,915,171,749,495,598,899,198,619,384,103,21,905,820,996,857,274,188,372,204,968,704,417,123,35,460,368,880,91,957,73,7,954,151,965,913,990,433,13,292,527,974,892,422,618,799,974,53,459,473,28,542,174,279,414,512,733,646,557,979,708,98,187,866,527,751,331,224,984,655,396,517,332,849,529,823,855,824,919,915,565,950,142,298,322,952,411,313,748,888,657,2,141,987,514,116,841,619,635,872,958,491,928,975,721,961,827,698,603,629,24,120,829,215,987,877,538,713,423,928,911,89,98,997,462,959,748,204,937,780,344,779,370,60,385,487,16,995,119,924,783,7,550,177,498,796,214,732,885,217,331,684,33,732,73,342,837,362,344,838,978,967,34,168,913,477,330,263,548,414,876,613,145,583,897,971,133,99,604,836,962,832,438,441,807,374,603,143,706,925,796,307,365,807,191,119,607,544,823,857,832,599,159,627,905,781,851,739,751,526,529,236,909,253,846,419,72,961,496,165,544,125,937,607,330,637,385,493,294,5,148,89,69,776,430,818,748,882,713,526,967,91,919,663,397,327,83,334,177,901,121,875,937,860,206,471,461,669,191,707,732,266,84,51,284,173,39,477,262,974,356,70,88,644,14,599,613,745,94,101,495,470,432,346,899,928,915,292,486,187,42,424,360,912,671,726,345,867,0,187,296,543,234,28,966,375,893,802,996,531,908,303,79,491,466,309,575,550,386,979,857,379,240,448,726,858,702,718,220,746,400,603,138,203,65,388,52,567,377,342,715,970,687,129,50,783,438,243,869,959,17,65,773,602,953,616,166,585,324,842,830,530,81,572,161,640,495,985,616,969,846,212,372,971,433,140,55,885,943,753,193,410,11,380,93,335,868,644,17,90,639,236,884,474,75,516,746,1,828,75,501,721,534,298,315,385,699,162,852,61,855,317,411,158,892,963,608,526,514,991,621,455,837,506,11,790,754,554,590,401,631,620,656,716,179,207,17,287,612,279,16,568,595,496,589,951,312,148,585,655,995,168,183,204,436,361,532,181,244,957,167,280,175,750,139,444,672,659,352,690,349,347,558,7,332,699,848,628,39,275,99,215,222,340,571,384,881,950,903,696,789,839,351,616,930,769,751,63,507,995,552,363,482,81,637,602,625,108,180,26,623,622,442,863,786,792,269,568,109,385,801,353,621,613,692,881,516,883,940,548,560,256,36,436,321,350,783,331,257,387,39,301,272,860,541,957,599,900,649,52,197,563,765,148,902,8,267,106,187,896,692,213,164,679,654,427,685,801,42,371,596,333,71,65,69,915,417,628,782,886,447,226,326,510,101,903,343,368,412,72,205,817,549,982,657,92,719,545,27,438,627,826,783,918,406,880,322,240,522,220,179,682,145,344,832,553,96,147,118,273,693,33,156,965,174,326,700,897,474,183,919,200,14,570,319,660,938,728,214,235,136,789,111,451", +"709,905,462,789,866,79,967,776,454,931,728,251,50,258,977,152,333,451,149,96,450,226,113,475,735,289,480,407,292,288,701,70,513,983,989,668,496,281,669,863,794,745,173,494,804,711,503,784,416,748,972,385,365,693,564,869,355,193,680,648,531,531,893,28,951,221,321,628,767,31,170,516,195,771,822,629,651,832,879,571,453,580,749,598,490,492,246,151,836,154,140,830,482,439,890,164,286,219,919,932,757,339,315,529,608,299,791,597,556,742,660,648,396,935,478,712,432,220,152,263,704,857,578,38,406,168,870,547,628,119,739,621,960,309,756,947,382,892,228,863,471,107,800,107,791,94,687,438,21,560,475,613,542,412,495,886,495,578,339,436,216,513,51,571,130,521,790,948,63,660,75,386,737,527,408,571,128,35,670,287,54,38,49,621,419,47,125,464,163,660,728,743,434,752,245,705,754,241,675,213,227,813,677,734,712,334,208,892,796,486,903,653,717,601,968,710,679,866,962,900,304,296,188,990,141,723,53,503,36,146,453,955,684,758,957,868,685,714,697,959,498,525,777,850,859,971,738,346,487,424,222,221,99,876,359,818,505,691,450,380,68,127,413,350,974,813,415,922,9,629,643,223,872,755,386,585,901,729,304,76,434,324,879,265,645,566,316,759,656,794,964,376,845,307,16,199,312,184,287,788,891,220,118,998,94,652,476,988,641,482,90,871,740,747,50,919,93,669,776,806,428,163,422,773,945,59,97,521,206,81,986,209,458,481,870,418,459,716,438,107,675,465,662,189,244,286,339,455,374,615,563,848,480,214,343,704,429,672,739,553,297,120,727,24,994,950,658,416,824,822,637,186,793,938,700,27,164,260,474,34,604,790,492,982,957,420,967,578,249,241,486,654,629,74,721,599,410,848,584,376,297,487,626,261,88,790,915,11,563,222,76,448,895,252,312,539,139,406,235,626,933,239,206,309,167,947,786,330,696,288,619,585,113,457,508,606,84,314,531,136,74,166,697,873,78,458,636,55,370,874,467,663,524,230,15,376,153,726,88,431,447,5,914,294,996,203,799,23,945,242,823,192,783,483,26,438,495,940,885,361,475,642,726,484,584,254,668,925,76,243,136,44,920,914,139,321,723,107,186,868,927,745,532,919,947,54,434,230,907,825,945,33,898,936,773,542,317,574,363,765,103,679,305,158,811,707,506,582,456,10,222,673,529,219,374,932,618,902,617,427,504,459,190,643,159,297,244,916,924,536,565,974,108,704,570,888,551,429,169,929,277,669,45,302,687,651,69,59,997,958,539,793,780,349,693,156,343,518,302,711,289,764,792,462,40,491,384,228,390,646,328,925,928,800,938,84,472,604,991,129,253,195,100,759,298,781,292,214,477,381,232,171,14,890,638,685,981,826,806,310,113,653,512,93,302,733,135,401,523,312,223,412,370,605,473,243,948,325,596,900,952,829,433,11,582,710,748,444,120,705,212,931,614,565,187,0,610,232,780,345,912,364,925,300,393,335,587,786,689,689,182,600,133,162,617,362,66,147,296,152,288,4,807,354,55,312,295,326,683,69,252,827,146,892,511,152,809,528,858,465,128,865,407,180,923,118,593,50,963,897,794,836,610,597,318,688,719,316,832,931,374,674,451,300,958,512,531,673,204,542,512,26,997,602,365,362,939,431,791,969,955,50,561,929,35,681,613,937,381,348,156,941,390,21,745,207,366,25,121,612,730,835,990,599,402,637,221,586,135,532,204,629,520,941,4,866,170,19,603,629,613,902,867,576,793,684,981,712,76,888,399,891,386,486,746,815,708,71,721,198,588,480,818,656,298,32,25,149,229,361,263,770,556,512,292,757,793,520,323,308,323,785,611,91,879,428,2,803,313,163,902,948,680,31,749,426,314,598,543,600,757,279,754,112,637,31,854,504,420,752,820,400,99,133,123,493,491,937,449,879,306,275,895,845,271,542,426,190,275,801,291,932,805,459,91,826,920,296,263,391,648,122,584,592,67,471,882,745,267,551,213,953,392,129,337,674,80,590,513,866,224,109,288,525,986,296,638,643,302,131,81,298,169,626,95,613,76,185,57,226,702,208,691,905,1000,175,338,336,450,611,260,120,987,680,461,785,367,156,664,484,937,33,816,507,151,52,131,372,685,555,640,57,19,348,990,855,182,747,666,66,13,324,974,737,371,863,885,281,696,245,676,91,766,330,466,62,212,606,6,789,417,77,455,670,192,347,771,228,477,747,939,975,812,387,543,240,433,156,649,387", +"341,147,850,221,432,839,710,643,985,179,335,547,64,135,227,866,39,497,537,744,485,517,507,710,168,912,809,387,431,4,893,787,8,657,868,810,556,819,928,234,755,409,312,768,90,209,400,939,781,353,259,430,336,876,687,413,322,723,761,84,752,809,870,972,149,151,78,284,629,70,62,63,556,966,130,372,655,851,42,110,140,912,177,145,267,735,761,981,734,943,572,675,18,47,470,994,990,889,677,464,886,148,379,691,47,914,973,453,357,809,964,95,147,764,820,308,299,263,986,180,462,981,810,856,589,348,361,47,952,546,781,642,182,825,553,476,288,779,395,658,514,358,52,405,912,506,290,761,670,629,949,983,686,224,172,770,859,60,372,85,975,390,343,110,952,4,233,265,634,811,964,327,974,210,144,201,887,442,838,945,301,128,993,109,365,549,360,665,494,126,559,341,334,781,801,330,699,705,768,23,557,566,483,139,495,954,445,688,71,834,653,986,251,769,16,921,442,411,995,213,556,207,337,836,636,689,701,504,265,970,556,251,157,543,154,721,451,604,155,830,724,474,514,225,351,72,301,902,43,284,903,465,439,358,133,44,74,231,553,733,86,298,621,514,121,516,301,789,171,250,921,934,406,809,438,105,290,988,132,380,954,24,436,219,589,148,744,635,297,572,714,171,771,610,405,470,501,814,704,312,685,789,775,260,401,500,790,123,618,399,208,336,955,615,59,996,739,406,788,190,553,491,574,189,718,344,487,56,571,945,970,486,328,41,714,780,647,194,67,680,245,560,282,930,195,629,286,154,706,562,29,658,659,130,933,989,232,708,628,426,555,674,272,913,359,785,85,982,216,27,518,289,992,883,502,111,16,221,822,657,35,674,838,448,702,136,28,876,235,490,895,184,520,413,675,932,239,123,718,602,854,900,548,848,60,111,395,831,253,275,814,810,318,671,975,383,513,102,564,176,237,973,978,680,512,163,506,347,680,476,393,589,952,15,111,62,639,648,18,457,820,488,502,444,89,257,480,950,515,190,84,407,922,956,630,625,557,481,490,338,695,657,56,169,481,787,501,406,434,154,462,903,585,951,449,894,905,646,81,738,61,313,913,43,470,872,98,514,988,913,513,502,265,490,615,859,999,817,172,72,785,898,386,45,819,381,584,434,843,193,705,56,649,124,34,504,181,575,624,800,104,70,808,362,65,692,964,890,996,395,671,821,642,936,119,987,139,498,183,857,25,958,928,704,672,600,885,555,64,646,919,106,225,46,193,276,841,2,123,602,967,51,981,102,468,860,724,504,347,761,836,789,7,549,334,248,272,361,68,187,834,294,744,658,647,476,204,802,803,653,515,4,15,303,910,5,296,860,502,125,75,362,741,398,907,490,601,996,538,583,468,946,392,567,952,755,303,581,209,724,70,498,957,448,498,935,721,97,32,651,601,475,945,811,675,428,826,130,146,471,406,859,413,204,845,45,995,595,725,662,159,916,26,127,296,610,0,952,664,183,460,876,619,429,700,445,510,28,175,317,269,251,981,502,933,699,985,589,254,343,974,836,939,637,612,822,722,745,278,819,49,216,379,809,422,436,722,989,357,758,506,701,610,256,361,148,601,121,443,709,296,834,63,408,979,869,378,612,352,194,321,872,672,580,58,86,136,573,309,846,228,134,574,905,381,750,953,791,864,170,250,863,787,505,434,721,689,158,283,963,409,238,528,471,840,887,436,531,937,116,622,572,612,614,323,995,469,706,424,753,64,266,530,128,82,411,468,530,176,433,583,277,902,720,73,652,674,592,205,507,580,670,965,391,5,33,969,394,764,614,400,975,897,685,497,629,157,34,538,835,310,339,715,229,735,578,154,709,601,345,335,915,344,29,636,823,648,533,526,678,540,12,346,918,223,688,268,399,853,902,881,530,109,800,662,382,140,819,223,445,454,784,965,139,137,130,597,207,735,140,613,216,251,852,852,464,283,895,955,346,186,425,469,456,850,168,646,297,282,184,27,981,99,774,501,525,226,10,13,432,807,796,173,537,223,900,583,769,244,443,537,359,82,699,450,224,582,718,230,914,840,592,883,982,241,344,509,548,314,901,507,463,688,757,61,402,25,533,977,682,446,305,220,759,457,171,413,705,166,454,7,5,299,595,862,330,479,773,307,641,327,442,381,264,25,821,67,634,887,480,330,873,672,899,71,400,464,344,621,5,962,767,847,405,776,443,114,523,998,259,542,8,891,284,894,174,810,536,722,583,19,547,486,279,787,237,42,231,616,162", +"871,88,840,131,511,274,264,762,321,767,867,555,974,354,879,508,86,329,554,875,872,806,598,291,712,775,942,95,754,295,740,383,331,685,506,866,567,756,721,616,650,625,422,742,764,33,516,893,643,631,938,454,199,899,76,233,142,441,726,50,578,636,217,67,280,494,696,897,77,697,627,958,303,786,280,211,137,968,283,168,985,29,239,335,754,619,543,177,178,901,487,448,131,804,27,464,617,619,157,372,975,686,397,900,396,421,683,927,760,973,63,696,994,489,989,153,320,233,3,912,425,999,896,809,522,39,220,543,507,547,226,513,850,821,85,777,101,977,746,184,384,402,590,711,73,446,700,633,503,379,288,92,492,825,239,517,980,3,314,252,351,783,418,340,489,271,287,787,957,717,689,704,5,956,611,61,965,550,630,175,959,839,74,697,363,524,514,594,45,926,448,227,729,320,887,275,119,349,857,827,209,104,303,970,769,71,872,801,219,981,186,722,520,933,821,977,642,739,696,190,863,392,484,24,768,965,978,130,985,428,877,457,871,335,419,686,393,908,278,37,691,264,332,685,702,464,400,993,55,483,649,443,788,150,441,981,976,849,2,713,596,530,494,591,432,197,744,269,502,315,612,948,405,297,133,427,464,832,332,651,623,971,180,44,413,532,180,136,869,964,519,822,195,866,548,599,129,756,856,630,982,243,531,688,37,698,975,774,991,191,32,498,963,220,910,462,151,749,779,353,946,733,585,735,909,769,720,125,967,578,229,192,253,771,870,273,883,104,671,619,48,680,705,847,194,379,339,158,21,619,594,684,945,156,491,662,255,684,494,285,388,99,465,796,669,413,495,432,215,878,532,147,318,405,900,901,771,944,493,404,154,149,6,91,813,660,940,59,57,927,405,127,747,576,282,753,841,949,993,703,965,286,153,459,178,816,141,334,105,448,309,478,459,719,839,678,824,128,779,170,279,923,461,457,486,184,957,841,947,602,655,136,537,174,134,813,740,943,606,145,925,512,365,909,946,15,284,347,8,97,682,735,236,146,242,828,716,258,171,270,622,340,611,375,815,473,387,222,791,532,850,540,148,402,504,990,913,514,806,646,787,381,632,258,880,444,673,345,730,461,767,934,55,526,616,611,249,32,552,887,206,688,261,764,335,71,774,767,270,528,845,448,120,428,894,486,44,669,504,993,718,160,265,633,952,812,408,768,567,551,574,867,96,974,379,405,841,448,4,372,291,747,797,62,127,553,710,532,557,779,555,89,562,415,139,689,323,291,946,774,350,317,313,834,187,664,164,129,67,807,466,804,508,449,130,562,410,518,341,381,608,479,655,650,739,75,203,29,720,406,527,512,496,964,812,111,36,661,438,611,735,247,669,399,803,514,395,8,963,313,28,690,463,963,800,595,518,499,93,86,446,537,502,172,623,143,356,91,987,376,377,657,905,916,550,727,320,377,218,373,286,185,759,744,713,35,874,107,837,638,489,80,239,291,543,232,952,0,631,259,884,468,839,17,673,569,321,610,969,12,539,476,233,62,857,541,412,683,69,451,18,630,838,128,57,768,712,672,474,352,253,222,341,540,64,290,932,557,134,216,674,105,404,86,754,172,693,86,689,714,721,152,792,335,833,617,407,540,767,913,263,450,747,788,936,881,247,814,873,881,227,895,818,457,270,666,617,56,746,817,753,461,114,343,941,473,428,156,356,16,119,504,822,659,647,130,665,295,648,139,296,210,262,498,271,362,229,143,578,818,906,527,944,765,172,382,724,652,904,136,552,513,268,439,342,768,928,755,933,105,289,190,70,948,178,476,418,882,963,70,944,388,870,394,498,763,666,410,119,326,358,330,436,277,63,75,532,517,670,671,607,505,469,534,843,847,321,629,328,507,670,425,603,80,877,258,779,167,781,435,129,164,267,780,772,477,461,77,447,765,887,49,640,975,918,573,476,826,493,691,689,669,22,620,293,407,990,3,912,927,720,367,511,517,718,643,786,901,700,773,63,787,676,28,111,758,762,835,135,65,2,356,590,95,876,571,358,490,201,224,266,572,459,855,419,32,313,100,790,995,299,277,850,699,401,510,136,911,3,104,977,369,215,728,658,372,788,373,276,451,256,785,381,87,254,564,256,292,151,57,69,144,984,538,741,745,191,156,572,919,966,743,704,961,14,838,869,912,537,296,39,632,300,999,608,937,649,770,403,18,220,87,693,948,704,921,448,856,120,654,636,876,734,837,888,590,496,62,592,30,442,404,743,78,279,71,701,907,798,513", +"669,291,359,555,231,903,802,383,248,518,393,617,735,388,797,937,205,780,191,816,100,584,421,364,903,550,228,954,994,477,834,675,137,973,323,234,973,992,563,952,548,326,521,876,962,826,517,687,844,772,311,143,72,678,288,219,539,434,723,703,332,441,616,469,113,998,617,88,737,672,452,885,20,116,792,892,231,620,628,738,108,32,623,495,694,684,19,469,939,18,679,488,555,336,631,464,599,981,976,67,825,544,703,20,115,452,121,303,667,767,337,539,287,8,135,954,891,72,987,320,56,377,214,837,658,282,400,472,3,758,508,520,376,114,198,476,427,841,411,87,439,28,8,977,202,986,726,697,94,163,375,410,529,853,580,832,710,919,538,847,141,923,143,925,141,243,591,645,831,567,296,846,901,534,772,852,9,325,296,628,188,405,68,563,135,599,29,467,817,981,926,454,389,935,248,829,239,682,707,369,607,155,328,529,744,501,81,572,21,31,967,703,462,201,452,709,172,427,231,404,258,883,362,394,570,434,289,730,308,110,868,832,568,398,803,555,770,266,376,305,917,49,459,793,191,583,156,837,971,327,221,490,749,174,463,134,324,104,969,99,486,916,919,301,342,411,684,378,784,776,123,524,411,632,874,545,59,195,262,129,204,336,707,742,261,50,221,905,750,251,222,848,495,527,636,275,202,353,27,976,874,194,491,496,808,94,506,813,931,883,175,492,4,4,320,460,340,32,903,266,298,139,962,157,349,490,939,379,117,335,168,307,560,421,788,877,318,233,339,914,132,686,855,187,872,797,190,896,946,625,236,1000,448,664,382,144,385,935,408,617,316,977,605,284,895,463,584,126,39,610,660,764,668,125,781,164,244,63,248,58,738,13,191,994,447,556,124,760,68,474,999,552,405,259,837,755,117,159,981,809,51,164,825,800,352,486,66,437,779,581,458,949,298,315,48,891,606,943,747,979,392,592,266,652,442,308,811,21,935,201,403,523,398,548,688,479,196,16,61,848,835,293,411,309,431,962,815,84,122,210,716,590,618,103,470,981,68,566,860,511,708,460,765,475,99,178,127,156,125,13,791,149,968,27,930,755,479,289,396,81,943,135,586,696,969,86,194,58,217,851,97,873,350,775,388,114,150,727,935,11,241,178,816,17,105,702,526,891,770,886,464,967,776,111,819,325,13,380,374,148,193,170,890,347,234,103,779,579,226,600,726,727,7,349,215,336,310,610,876,465,455,520,614,41,257,154,245,634,477,357,735,136,439,306,535,819,8,947,509,238,796,879,420,251,844,517,252,556,666,734,964,953,554,582,572,670,139,824,844,365,832,400,790,169,625,561,200,393,197,334,35,517,233,886,693,618,151,62,656,959,147,881,561,396,385,959,7,794,895,557,495,311,807,122,659,924,859,989,748,255,129,911,246,686,554,192,574,296,385,990,532,947,523,269,156,937,959,462,732,241,362,237,228,186,448,507,468,646,451,355,630,609,200,638,234,780,664,631,0,391,830,954,299,134,662,964,949,877,664,415,86,704,39,320,142,403,385,58,865,507,45,221,546,392,900,505,424,96,693,934,19,630,726,324,314,73,959,728,987,386,975,874,839,841,761,168,149,60,510,705,787,600,584,770,262,742,675,251,306,220,559,553,835,993,868,487,306,273,833,416,341,734,264,724,341,779,522,952,442,430,66,257,123,687,586,876,916,659,952,970,76,203,109,275,223,804,124,52,692,401,733,66,462,615,616,637,276,234,512,967,195,259,272,966,750,927,607,466,365,619,783,226,403,973,378,771,586,34,861,252,515,286,397,634,991,774,573,509,161,53,640,738,166,663,161,673,145,384,182,384,216,602,279,633,747,354,814,230,818,658,146,505,157,447,831,998,51,455,128,790,795,753,871,553,792,334,299,487,706,14,808,309,367,238,707,845,838,482,196,59,222,816,25,738,779,628,207,540,451,291,731,253,237,445,743,696,207,188,848,269,321,70,255,508,817,940,647,183,454,920,21,470,17,269,596,259,428,462,12,592,269,142,341,632,781,338,870,930,835,19,614,677,200,239,780,462,658,155,604,832,131,821,750,934,850,683,391,91,31,197,918,22,343,788,63,569,5,854,181,800,571,769,932,889,45,595,499,432,151,360,40,194,878,218,584,586,40,640,651,257,586,346,377,959,19,337,12,238,800,448,600,532,248,589,186,49,513,553,174,432,158,69,904,491,654,106,366,497,712,781,435,998,901,43,765,23,416,404,129,754,624,718,590,563,486,373,963,701,214,421", +"27,192,296,217,445,630,265,575,40,997,99,146,311,167,9,226,616,515,952,12,147,825,486,632,668,526,322,625,885,330,906,874,866,116,875,190,540,353,6,925,580,335,477,21,724,788,283,968,447,273,305,577,308,754,371,865,460,262,960,528,527,726,583,970,555,482,770,224,380,332,82,541,911,926,519,71,743,893,430,888,500,219,627,805,57,435,307,81,582,745,398,956,557,88,278,908,522,3,450,819,137,969,375,934,569,616,281,135,290,164,896,762,531,730,701,218,729,655,885,651,441,365,567,643,407,647,62,423,404,844,460,624,283,7,156,814,548,536,47,821,599,406,186,653,788,787,348,16,147,779,285,607,188,971,674,307,384,189,132,328,486,279,456,145,652,17,892,742,59,884,853,897,855,339,435,866,476,341,645,649,657,256,327,48,487,351,32,341,571,63,367,464,383,68,471,738,47,649,43,19,699,262,967,522,459,48,684,2,692,111,498,310,708,544,750,778,899,926,84,765,929,91,425,595,472,645,71,181,392,562,876,123,537,220,432,767,3,470,824,27,139,44,353,926,47,733,291,61,796,854,288,968,998,234,971,440,130,967,959,945,287,151,349,419,365,532,675,85,210,241,308,888,24,278,442,557,720,385,649,573,488,781,781,927,764,201,63,225,361,833,355,633,505,773,318,118,16,672,822,124,104,935,912,312,892,849,894,458,273,487,55,714,755,762,944,24,542,855,477,398,929,275,968,310,436,330,75,370,291,50,443,277,912,652,916,603,906,900,158,655,103,237,540,44,569,116,307,838,146,162,878,755,869,594,504,148,407,364,368,974,264,807,311,901,255,83,791,341,284,147,575,279,383,710,976,181,709,84,800,431,229,392,482,737,208,36,935,751,610,483,78,543,628,192,463,227,155,209,457,422,285,438,395,224,178,988,302,12,309,545,721,137,705,920,740,275,975,153,689,741,822,568,435,74,289,25,207,846,996,61,384,408,992,447,986,867,332,382,726,592,38,85,55,489,509,109,455,239,85,407,438,566,218,879,532,660,683,9,678,986,786,887,540,25,966,796,122,481,14,663,39,437,12,56,913,328,982,28,466,232,165,51,221,693,227,136,899,772,704,484,171,191,859,819,121,640,150,153,683,263,22,245,20,4,676,390,430,293,184,65,805,922,220,615,204,555,164,28,772,57,886,718,56,224,388,259,271,885,817,710,967,942,726,272,424,539,270,2,956,349,11,854,381,919,474,931,809,344,988,538,990,101,809,846,142,34,596,854,871,232,248,440,445,393,19,629,244,392,903,759,361,381,534,483,489,772,402,204,792,455,141,368,172,495,328,480,801,494,393,189,108,571,298,267,291,412,443,153,75,258,960,866,788,513,145,529,726,925,568,731,622,876,130,756,157,842,372,270,825,334,679,709,608,852,837,102,688,376,733,359,244,176,751,538,614,252,983,451,910,473,677,452,282,579,318,359,866,905,782,431,581,332,519,1000,28,345,183,259,391,0,948,769,346,313,839,140,325,356,795,65,355,381,924,497,532,811,962,556,494,526,401,813,765,489,523,412,901,78,515,815,794,139,263,683,465,84,646,869,532,356,932,722,2,388,445,916,615,440,437,816,519,470,220,152,987,250,836,652,469,827,762,321,876,717,51,709,625,621,458,152,425,797,908,42,698,336,638,600,829,933,300,308,998,301,833,340,508,691,162,916,791,681,468,402,855,986,850,267,977,290,517,28,670,629,593,183,198,931,663,710,808,500,944,367,265,367,250,395,732,668,670,479,420,633,472,620,825,384,87,143,373,977,901,178,792,1,641,950,980,191,651,887,702,950,788,384,825,656,638,927,363,40,710,74,736,300,799,196,284,763,945,92,909,50,492,223,357,254,827,864,39,614,308,288,637,996,195,948,627,55,235,162,346,709,431,888,198,720,859,323,688,109,271,349,419,20,391,508,33,948,810,181,66,493,894,816,178,21,303,9,878,306,318,343,927,41,114,766,629,89,790,91,439,644,324,219,844,927,798,311,976,903,117,93,274,544,570,419,564,408,825,413,142,936,32,912,440,140,666,518,745,707,147,330,887,109,457,248,895,876,762,821,521,268,282,435,36,501,636,200,104,336,256,8,733,968,475,521,862,411,803,496,783,143,409,505,915,611,172,317,777,683,933,248,336,453,688,21,835,556,626,906,153,679,418,460,444,911,800,373,762,861,128,150,676,211,2,964,387,426,392,704,960,514,858,645,400,690,236,617,248,771,254,869,764,745,72,63,324,687", +"5,669,830,275,841,282,317,503,661,477,942,817,448,186,567,226,689,313,248,249,414,624,917,56,910,187,67,620,65,160,48,131,979,802,484,602,545,263,107,91,532,779,888,284,31,798,564,782,709,376,73,374,312,149,584,385,273,842,632,639,513,640,759,242,507,655,393,400,767,293,870,790,648,211,788,137,405,886,850,811,23,148,857,862,460,33,427,308,618,367,233,690,226,929,223,497,400,601,266,17,273,647,806,269,933,694,321,238,71,680,826,970,914,917,943,555,702,480,65,327,461,814,362,660,475,496,658,492,461,547,849,860,517,71,575,194,579,159,784,476,808,393,510,254,851,466,959,705,527,707,945,316,457,189,60,541,720,347,623,752,227,894,9,654,284,231,985,795,523,844,503,266,135,428,235,358,403,445,826,215,655,810,429,12,799,326,886,878,566,324,691,15,775,725,420,29,33,560,937,559,311,24,680,356,452,172,692,105,851,366,630,216,549,61,821,390,509,42,463,2,381,833,512,191,361,468,695,379,54,417,944,788,947,414,215,808,108,328,991,497,734,370,609,834,495,364,100,633,131,589,187,669,509,686,89,449,735,675,419,945,48,448,320,359,86,332,812,177,349,514,64,697,848,98,486,664,442,587,293,621,874,673,905,605,47,665,509,716,119,293,323,593,638,61,328,259,475,132,952,163,524,675,751,495,227,238,903,787,312,15,324,172,863,818,925,541,641,491,93,817,916,91,487,786,120,768,232,914,417,560,440,526,590,323,585,666,960,737,685,775,513,567,417,66,955,891,680,70,597,854,306,730,148,7,177,730,43,83,149,357,775,828,858,409,621,426,316,863,281,104,618,532,507,983,667,869,843,610,629,712,443,52,633,153,283,552,745,864,31,13,411,469,590,381,748,481,581,528,778,87,718,128,637,570,703,849,404,849,11,698,817,313,920,285,148,785,309,952,376,198,239,83,834,128,572,423,938,672,469,968,686,624,363,907,109,375,41,140,484,226,470,471,795,50,419,93,523,219,777,464,306,202,894,752,44,861,568,73,324,756,310,830,815,29,650,609,526,488,570,710,123,759,680,552,920,30,528,370,249,975,768,775,570,659,22,979,341,191,957,320,717,886,441,326,674,478,46,826,929,146,231,46,888,764,513,263,179,606,927,228,738,308,998,110,567,489,475,663,213,455,958,70,131,5,672,908,128,176,320,738,515,803,4,701,244,90,777,554,347,678,616,720,323,916,223,237,564,387,695,630,695,906,325,560,987,87,877,390,206,849,533,89,316,285,806,615,288,798,13,59,297,961,177,894,805,631,693,700,127,751,541,813,196,351,488,706,322,409,302,122,913,72,807,112,524,4,653,674,929,230,808,452,326,587,389,831,731,283,283,782,86,299,1,984,57,315,622,628,571,534,801,860,164,99,880,925,557,191,423,1000,314,449,632,669,537,731,310,115,648,707,650,398,395,390,615,646,312,929,41,597,373,905,874,120,966,912,460,884,830,948,0,577,919,989,320,158,353,73,586,907,340,681,398,746,71,737,775,439,864,547,833,959,287,784,285,211,322,681,374,931,654,447,164,315,529,192,155,503,510,660,199,819,987,577,424,286,452,370,928,473,648,716,87,995,750,206,147,615,631,19,163,631,797,839,821,863,40,393,66,917,643,139,134,722,536,584,556,288,284,848,413,41,704,36,949,343,456,750,43,985,279,381,853,284,571,557,615,526,379,145,911,850,581,253,47,223,347,445,761,334,835,726,2,175,255,99,282,348,119,521,37,713,11,933,817,829,945,54,59,270,323,212,903,358,644,291,136,44,871,843,927,41,429,935,568,645,883,450,86,545,363,96,763,941,166,467,798,24,411,648,340,99,383,970,116,83,904,449,55,193,57,633,813,727,218,334,996,804,657,989,301,371,403,212,146,960,284,734,764,416,150,175,220,105,100,392,933,632,630,638,962,983,676,401,790,995,925,333,444,575,432,536,595,535,467,513,46,751,316,806,723,57,824,359,399,633,314,634,850,22,668,818,268,12,834,264,881,272,805,340,113,475,865,513,231,94,673,415,69,415,822,212,922,841,240,713,823,60,413,777,474,177,263,980,329,15,838,914,314,605,511,996,295,592,289,320,943,876,409,452,278,200,57,952,861,660,97,660,447,12,878,430,714,515,294,15,73,713,399,740,946,644,735,9,547,573,757,620,12,63,266,701,920,258,173,382,280,213,67,347,828,229,725,896,183,984,516,820,514,300,372,191,636,176,919,421,532,241,52,355", +"643,742,724,964,657,966,325,143,717,624,926,541,227,929,514,943,686,218,383,545,315,504,535,846,621,915,65,340,794,403,619,402,449,539,175,633,244,36,535,356,128,522,787,882,131,818,813,109,942,806,610,241,286,420,20,991,526,685,860,155,593,507,581,29,515,86,8,148,762,234,241,61,965,901,360,48,400,271,653,981,574,351,479,285,121,73,62,660,223,57,346,117,47,101,236,748,312,552,81,945,311,499,124,903,336,665,202,598,809,690,631,313,782,228,561,316,761,645,403,194,873,202,200,391,9,318,732,298,55,604,933,272,93,809,506,893,805,304,649,228,837,788,82,164,647,637,227,279,565,31,622,962,665,126,334,860,965,524,396,908,271,451,632,432,985,222,743,686,564,175,516,900,213,934,143,274,162,408,90,620,114,729,82,319,200,939,692,897,403,409,357,730,275,594,486,332,514,17,712,310,548,948,243,573,919,354,338,164,245,657,668,531,509,456,300,953,189,372,808,498,121,377,161,390,652,444,992,891,683,106,163,36,935,997,999,4,683,411,820,421,75,380,512,681,190,408,48,756,288,488,591,696,376,388,860,644,379,730,165,889,440,707,237,301,156,463,998,340,254,492,437,913,141,960,424,624,656,730,28,341,803,917,51,230,986,869,60,703,339,751,456,348,809,865,514,231,514,686,309,579,601,782,336,945,732,743,585,434,471,788,820,654,979,53,205,658,413,94,815,87,36,94,340,782,673,403,853,769,24,666,926,883,939,931,885,747,425,913,312,670,525,319,533,952,659,243,935,397,608,937,432,467,392,738,749,561,349,300,445,988,995,92,860,254,541,252,419,177,996,705,657,34,339,647,384,774,867,529,774,400,404,409,439,995,851,346,939,894,847,777,467,839,938,628,392,812,780,783,58,26,223,266,376,470,266,106,716,678,707,276,471,71,374,657,146,897,77,604,339,886,7,992,235,89,474,596,490,777,318,701,123,571,161,564,250,978,433,170,708,493,61,74,94,51,53,247,945,197,489,266,928,194,769,553,983,98,871,420,999,845,362,623,133,890,544,267,988,360,128,553,489,429,386,868,40,332,19,956,608,847,383,858,834,358,835,129,831,722,122,454,826,941,358,930,89,596,462,604,6,799,621,137,761,982,6,737,612,182,976,110,964,841,488,150,259,833,986,864,469,195,508,798,219,855,951,412,859,344,295,7,913,832,694,372,63,390,449,593,917,97,736,529,695,891,129,192,100,571,774,755,330,142,242,295,88,301,233,241,95,808,30,863,573,144,106,913,345,11,42,788,977,661,929,91,140,657,893,691,872,358,558,23,945,919,58,128,250,397,375,335,15,420,240,96,11,120,239,229,4,571,31,576,492,366,111,850,651,476,919,789,274,737,271,761,523,934,144,243,767,338,480,686,360,653,915,147,711,934,647,93,645,789,948,401,836,601,41,664,67,371,247,417,915,367,773,846,97,305,306,296,397,250,713,31,375,364,876,468,954,769,577,0,867,514,921,472,436,685,967,163,333,215,886,704,257,95,918,200,691,176,530,537,470,920,968,295,6,419,899,964,579,901,817,802,211,217,226,678,811,489,399,668,356,807,95,454,425,93,996,427,183,103,20,444,914,763,851,433,356,375,499,712,504,890,551,433,602,228,160,493,130,835,399,37,485,928,964,206,783,372,183,481,139,512,501,75,389,792,168,38,810,715,552,935,280,187,526,236,45,394,988,458,713,686,56,524,39,114,317,834,599,444,776,843,143,55,828,462,88,930,878,221,788,685,102,148,939,711,750,565,264,649,278,848,187,589,136,234,916,12,48,99,450,967,394,204,520,277,54,857,636,564,653,610,571,890,975,184,700,649,780,157,961,343,382,175,567,370,810,460,260,478,194,575,949,329,311,760,998,726,882,370,385,167,990,27,164,123,272,362,834,253,812,880,159,842,645,936,422,576,965,50,88,609,682,906,276,868,601,838,338,164,586,665,993,281,53,423,784,235,670,898,769,394,679,399,67,916,41,14,865,655,862,157,851,184,643,306,102,471,638,461,739,42,779,410,285,626,413,720,790,92,77,434,798,156,277,122,764,318,743,67,376,445,854,747,962,944,665,242,635,162,172,888,97,34,118,909,623,675,624,31,151,782,740,995,201,512,727,614,333,596,276,445,277,211,496,585,623,369,497,980,718,77,2,698,847,788,151,961,173,55,406,816,686,716,327,733,425,979,98,749,242,769,582,628,532,798,119,868,963,800,627,966,504,694,201,387,859,746", +"840,260,101,137,468,337,453,421,626,616,591,32,920,55,412,745,759,127,926,823,823,630,740,518,184,106,266,151,328,776,56,865,273,127,297,287,559,599,823,656,194,144,973,872,134,765,840,971,590,561,518,582,964,451,129,979,927,765,993,400,996,656,46,62,193,366,3,948,84,175,398,960,126,474,877,171,890,966,451,437,210,306,969,580,261,482,433,187,15,738,540,796,582,288,478,747,420,18,841,727,900,907,586,622,646,773,833,850,720,808,16,3,972,511,301,906,37,208,342,427,803,244,636,765,338,225,7,610,72,470,234,691,598,29,102,441,175,534,481,745,250,379,239,909,454,754,142,313,960,535,625,7,134,167,643,912,904,503,258,433,667,878,980,772,947,953,107,8,287,238,60,43,998,432,335,122,303,32,410,539,959,211,200,110,908,928,805,451,529,391,314,503,255,797,512,797,259,466,972,793,940,196,179,257,354,271,428,553,447,644,679,905,280,889,734,60,71,944,154,750,859,368,129,461,290,525,476,995,9,369,390,536,309,463,792,621,379,467,458,836,829,275,135,232,589,111,627,700,991,187,446,79,560,914,124,329,493,138,499,581,397,652,661,718,38,858,945,806,495,465,355,278,602,924,412,48,624,46,259,17,314,376,291,382,592,648,689,960,847,211,373,506,617,983,405,7,386,713,994,850,338,248,567,432,492,662,73,430,953,932,586,276,160,334,33,775,541,591,555,814,639,557,721,236,263,5,189,777,589,574,304,929,504,915,475,272,283,408,22,966,198,686,894,95,887,340,358,465,515,171,798,397,103,660,630,855,524,753,491,637,228,769,153,308,350,168,887,983,287,298,163,856,73,562,880,272,923,364,675,441,821,591,257,158,643,936,895,908,791,192,971,521,639,403,936,176,510,315,187,958,807,531,642,780,556,968,75,763,515,176,287,788,85,578,104,251,59,237,933,689,850,47,238,22,276,305,395,323,379,867,492,660,564,745,19,797,131,531,330,950,730,673,244,636,622,530,939,448,762,485,324,348,450,832,961,713,765,659,372,796,986,948,916,911,256,495,584,169,660,773,77,787,477,669,715,467,141,319,818,777,171,911,483,983,555,309,415,715,477,24,479,292,33,193,522,30,872,157,498,686,939,921,885,988,65,165,120,888,8,9,755,782,40,57,852,661,248,932,645,957,375,3,597,421,554,937,1000,171,976,81,407,371,525,211,433,717,50,179,795,629,119,716,150,736,981,966,597,394,654,81,151,284,277,153,949,297,41,411,430,662,55,390,188,265,999,695,866,310,50,436,614,926,228,827,483,853,186,116,383,777,12,154,696,442,583,972,2,930,350,498,254,830,449,540,659,949,702,962,253,692,94,360,958,657,993,684,906,977,563,520,233,728,541,99,149,802,838,929,875,52,524,319,872,269,679,192,367,616,696,395,181,39,481,232,451,820,514,628,671,843,88,410,717,482,920,997,496,436,690,316,372,118,564,169,893,925,619,839,299,346,919,867,0,453,91,72,252,777,985,429,108,762,132,849,959,597,915,926,994,337,236,191,944,913,69,571,609,606,935,715,644,192,610,602,733,161,641,376,779,641,596,435,946,383,607,289,910,555,290,585,725,279,857,566,108,875,624,484,725,326,570,103,447,38,998,169,749,24,924,603,25,545,691,147,314,138,441,335,101,215,612,731,238,265,26,763,936,825,671,555,366,537,384,437,551,134,390,272,351,740,473,550,808,387,195,401,758,714,445,561,260,499,275,695,670,554,915,97,693,225,952,752,999,26,817,135,543,431,245,389,105,420,829,849,754,915,134,710,321,928,146,795,627,172,777,22,239,44,184,26,593,912,754,743,30,495,794,557,710,478,418,41,6,47,706,733,988,779,590,793,217,799,209,546,584,170,738,438,40,332,405,620,672,774,875,203,74,457,459,322,602,650,645,774,471,78,526,997,945,976,669,861,209,559,214,920,11,384,180,197,745,499,391,361,865,638,707,13,782,94,182,209,209,869,303,42,519,338,654,876,505,889,409,546,52,727,938,293,302,798,890,816,949,161,484,7,508,341,201,852,824,94,487,548,865,411,631,555,831,526,155,634,82,756,959,738,640,714,362,384,753,266,460,948,686,561,760,550,329,884,943,725,95,122,129,514,945,180,187,409,297,658,449,336,483,178,882,47,383,748,921,99,149,208,122,405,426,740,943,566,753,579,162,670,426,80,820,217,146,864,27,417,428,553,688,811,517,42,193,936,226,515,787,472,258,489,836,353,578,599", +"999,206,730,204,723,290,549,152,203,270,929,541,685,408,979,85,401,269,617,994,591,866,337,300,692,983,323,704,787,537,279,480,817,943,409,437,182,155,782,131,408,554,265,639,741,900,677,506,691,538,95,505,583,626,629,479,832,407,236,378,137,138,302,959,39,536,42,914,813,64,918,138,358,842,864,95,337,892,729,545,412,11,303,2,571,925,419,647,178,933,415,35,986,218,804,816,502,413,881,810,245,382,365,670,604,255,505,524,366,254,113,178,754,362,329,805,629,700,556,308,449,507,356,762,546,475,504,429,836,274,326,760,298,207,455,340,559,226,247,929,249,953,384,163,577,179,785,799,968,101,580,129,592,875,526,373,781,388,936,162,474,201,93,436,145,619,550,303,390,610,995,221,137,394,491,229,831,944,681,122,845,332,937,147,658,852,720,408,46,204,194,437,796,341,883,167,25,857,371,64,377,696,492,431,674,421,975,782,174,216,387,439,849,907,283,719,251,159,87,228,509,420,315,642,483,452,889,906,702,246,359,479,187,887,198,577,593,533,98,6,386,544,817,335,175,57,673,780,359,87,201,169,652,489,312,639,508,216,358,524,113,709,697,875,907,675,475,990,292,274,826,571,709,98,630,78,545,341,364,697,976,348,494,945,852,18,658,515,243,701,504,181,913,65,934,836,403,369,500,756,865,849,402,552,450,244,247,489,874,227,954,169,390,949,523,953,662,226,979,268,211,182,610,3,36,989,508,214,246,258,537,877,967,52,374,905,428,101,416,568,453,285,405,625,617,123,835,645,252,527,311,1000,461,778,617,562,829,577,926,826,61,576,687,821,586,819,146,930,328,58,450,784,204,257,392,447,117,635,91,531,163,85,519,507,262,527,34,40,615,253,207,110,984,279,501,927,299,920,538,50,711,333,910,719,291,391,443,54,82,859,283,226,992,478,94,11,268,758,760,474,867,330,59,478,683,362,977,453,355,406,463,285,977,804,429,348,795,889,486,209,303,423,156,836,50,634,961,186,122,510,80,651,859,244,937,677,401,934,800,446,461,476,617,202,207,515,250,663,341,436,247,407,275,490,214,962,458,841,650,598,677,479,985,530,634,254,378,512,210,448,785,657,931,556,432,780,918,452,384,175,784,846,882,102,582,575,891,145,769,6,137,338,910,974,826,465,340,315,854,378,418,30,107,235,618,475,628,921,724,656,500,960,41,610,647,485,110,720,831,153,109,378,296,408,148,208,811,862,116,291,432,708,560,732,765,282,861,712,780,129,133,296,54,945,594,283,655,278,961,448,432,191,166,396,948,985,728,14,152,217,222,9,343,92,793,399,648,824,214,626,254,135,162,835,72,531,557,281,718,291,464,778,547,34,517,882,690,905,338,992,549,332,192,614,730,455,267,778,611,512,709,895,734,570,36,665,567,873,489,638,832,495,150,362,694,404,108,165,770,120,159,819,654,160,397,582,92,862,220,591,591,363,423,49,802,300,429,17,134,313,989,514,453,0,55,828,191,824,511,674,340,963,255,270,743,799,232,950,514,636,565,266,90,812,628,894,202,271,734,195,170,730,363,72,507,982,368,178,280,114,727,548,450,671,359,553,944,354,69,449,888,262,862,372,605,96,379,686,938,752,374,614,784,914,968,838,323,775,405,636,762,473,742,988,675,667,89,104,642,658,310,689,403,63,334,184,280,145,206,742,455,49,290,801,751,330,299,17,165,975,725,406,775,597,426,22,904,407,156,395,130,47,714,399,303,387,94,805,605,322,36,85,777,40,186,792,975,667,766,33,616,50,413,131,359,970,28,698,357,359,634,976,352,34,14,937,407,267,119,431,916,583,977,125,343,368,937,141,432,266,980,700,990,854,730,48,263,569,360,539,136,889,176,908,627,13,109,746,791,772,924,861,663,864,400,59,994,236,107,273,167,160,930,217,41,47,922,390,101,131,853,368,494,909,969,679,806,755,792,103,203,991,464,789,414,641,927,674,123,490,476,436,521,926,765,494,151,561,504,366,27,967,913,515,816,242,119,842,381,734,736,749,969,154,414,687,543,945,725,424,467,250,199,240,88,824,309,169,724,997,979,595,40,100,613,427,798,953,630,890,855,544,262,833,842,535,287,389,637,468,522,872,755,882,583,908,681,831,428,978,301,963,979,898,401,897,713,549,338,181,889,175,491,918,637,87,544,859,494,934,387,805,949,276,114,601,465,906,558,177,36,625,499,895,236,208,170,998,957,751,81,618,749,889,154,757,165,860,710,705", +"940,152,795,388,124,656,104,508,709,448,344,397,194,256,872,239,837,238,69,570,571,846,290,559,714,604,530,671,960,813,556,919,509,577,364,347,390,646,375,194,924,405,382,460,701,730,259,544,53,218,444,537,351,34,271,931,443,305,86,864,637,305,71,269,447,644,160,27,549,495,501,976,197,937,611,394,85,647,168,316,242,477,660,240,807,756,130,190,606,768,618,510,874,914,121,509,507,201,674,254,519,642,312,98,465,946,143,285,365,18,32,921,44,919,19,680,159,265,18,331,633,289,7,427,759,63,330,122,946,434,922,445,467,470,675,919,758,148,922,446,632,565,488,90,921,203,197,326,284,225,904,454,413,486,617,954,916,890,108,131,332,822,330,486,626,510,857,869,889,615,28,172,371,710,631,471,934,798,366,844,873,246,479,389,840,755,19,423,904,595,889,835,187,119,326,80,822,861,502,628,470,293,775,858,20,333,430,72,408,124,232,164,883,714,706,968,640,875,600,664,628,518,46,796,809,320,445,728,592,439,989,917,249,880,538,390,508,543,816,466,667,499,174,915,931,254,834,277,939,146,506,331,103,653,365,919,404,663,911,464,750,278,763,980,93,875,22,743,928,148,311,371,667,862,600,473,106,583,879,194,274,169,158,866,143,754,272,126,780,602,800,413,738,57,797,243,927,118,106,37,139,327,738,729,477,623,6,73,859,559,419,346,256,736,877,602,555,864,322,725,853,703,150,326,773,459,646,207,931,211,982,767,824,805,954,994,603,877,385,650,826,908,523,7,400,314,840,693,735,542,548,212,228,205,596,672,934,587,298,342,878,446,526,454,483,354,512,242,877,831,548,415,927,426,832,391,435,881,563,695,506,113,91,2,200,953,421,305,448,727,914,908,820,341,442,7,813,462,422,31,123,553,946,92,720,478,666,678,805,845,661,170,951,824,92,378,364,360,303,951,281,376,211,626,668,388,59,516,606,791,151,160,120,151,648,18,903,154,752,446,268,619,726,372,950,625,757,160,894,12,486,720,973,152,210,828,557,385,137,452,211,487,412,328,437,922,692,566,986,746,601,649,170,716,850,657,814,327,778,465,902,930,392,889,822,847,296,743,50,872,450,215,372,21,675,712,772,807,760,994,899,151,723,702,507,958,43,594,200,706,336,217,273,230,727,16,484,184,478,819,280,635,311,947,19,718,960,568,359,15,284,165,995,141,715,398,325,653,720,497,18,909,250,471,32,765,488,869,379,315,952,393,134,447,230,590,539,375,532,487,87,188,981,836,844,699,957,352,171,9,829,536,259,303,23,128,106,409,205,749,996,491,957,248,132,96,717,773,288,176,881,515,967,20,268,179,113,710,103,654,421,306,27,987,948,413,528,294,376,168,156,325,280,612,632,745,637,803,769,748,588,645,221,166,631,906,358,143,20,76,77,640,740,948,621,540,437,601,405,881,573,830,591,594,785,510,353,862,924,675,681,955,237,355,996,393,700,673,662,839,320,921,91,55,0,494,380,836,151,378,952,205,549,275,938,108,131,11,621,828,243,983,760,974,504,736,343,118,88,164,899,426,35,76,831,158,969,564,611,210,441,165,791,145,955,735,479,376,119,687,582,861,554,77,871,872,645,708,186,301,922,967,857,288,260,764,954,83,395,96,752,327,915,919,716,896,119,999,69,99,94,916,594,27,403,126,70,488,481,891,253,416,998,437,526,395,637,961,340,256,652,160,342,849,438,572,573,875,532,768,857,567,156,97,935,60,533,793,860,273,213,799,64,998,3,385,586,110,888,119,671,36,957,683,981,239,487,508,799,98,979,142,242,750,826,757,793,451,151,178,699,763,329,744,134,105,45,578,763,377,989,40,65,529,553,424,613,579,905,413,9,31,340,952,589,277,938,632,602,120,640,986,919,294,407,275,431,8,369,464,505,907,976,526,860,692,889,58,913,310,47,479,721,720,353,687,594,742,552,895,237,675,221,356,161,912,386,396,484,655,718,377,870,447,42,71,381,342,721,33,240,779,352,59,6,426,980,396,778,586,795,528,23,809,167,300,943,615,925,131,727,816,72,339,451,630,514,41,569,817,802,497,897,13,257,607,979,25,676,718,87,568,301,200,122,865,631,949,43,925,545,874,29,203,96,855,981,708,95,32,25,340,15,989,1000,684,70,88,722,455,384,950,835,515,656,359,390,245,672,214,836,633,495,463,325,728,550,238,787,986,523,369,526,476,971,226,682,389,714,25,435,415,103,865,764,441,652,520,864,137", +"489,419,997,96,940,166,412,839,679,468,523,839,467,194,579,422,417,508,939,767,391,347,452,421,624,768,38,724,780,569,161,258,219,53,10,958,357,865,486,848,710,551,519,527,291,261,273,790,513,8,494,58,404,397,902,960,274,217,831,862,603,58,149,378,488,222,982,853,538,269,690,289,855,558,470,289,979,791,845,340,662,603,316,119,166,735,501,49,836,67,523,428,814,434,910,760,180,752,138,475,704,756,256,720,1,152,595,480,671,535,381,347,325,796,375,861,66,618,823,741,826,668,512,962,519,840,354,463,939,967,588,114,729,306,584,550,971,749,592,868,86,41,914,7,567,176,320,157,660,266,77,918,492,11,981,599,237,33,683,338,631,64,13,607,955,750,753,915,277,605,416,386,665,509,170,869,690,170,261,885,125,952,344,281,483,488,817,780,941,960,651,250,891,325,362,548,873,190,97,77,240,406,577,215,339,890,479,431,516,410,712,193,376,63,106,905,707,477,299,938,369,884,682,430,308,389,156,993,615,985,684,841,523,356,944,240,803,509,577,624,896,255,703,423,407,183,817,812,321,923,797,964,61,503,190,275,85,652,603,390,876,896,557,926,466,496,877,662,891,551,402,881,843,342,926,549,164,701,54,938,502,956,713,172,48,462,575,406,288,565,98,236,857,800,279,387,512,425,220,45,289,363,857,404,589,917,261,350,501,609,787,87,479,166,808,419,521,318,709,146,611,35,809,490,541,551,675,214,463,910,669,297,694,524,594,182,933,778,526,674,135,687,120,936,660,956,593,236,968,585,621,268,160,398,351,70,928,197,339,556,452,183,324,121,59,138,921,755,22,473,71,96,549,635,227,63,743,355,889,648,956,623,175,521,551,441,80,417,847,29,279,251,52,515,271,680,488,414,727,75,260,777,357,723,328,1,675,158,526,991,285,110,330,977,286,48,111,971,309,390,987,349,716,750,818,676,452,449,953,172,637,612,305,146,146,986,250,734,566,844,409,490,31,822,927,162,816,326,186,661,433,212,176,802,146,673,806,347,736,961,763,106,698,673,978,161,497,907,592,104,421,110,847,508,855,32,479,213,825,823,841,509,284,221,33,940,990,985,407,465,712,133,222,650,406,369,473,276,670,267,882,53,347,210,201,305,633,3,690,19,905,69,202,845,919,236,405,146,56,48,542,894,410,509,154,984,815,218,274,342,97,403,398,968,193,411,399,46,399,747,593,884,712,670,975,517,949,222,357,935,625,429,971,343,791,489,258,140,619,10,645,751,480,321,957,579,741,634,641,244,570,462,74,290,712,973,317,533,756,577,189,752,978,488,375,441,700,559,769,213,577,689,679,942,266,331,19,123,624,140,754,413,356,409,108,940,911,241,910,314,353,542,387,165,401,721,534,496,550,499,789,892,283,721,971,52,955,200,303,371,522,64,154,821,194,67,933,437,697,470,772,431,437,276,805,89,400,829,618,499,178,233,786,894,531,335,445,569,964,140,158,472,72,828,494,0,25,206,48,729,11,16,597,323,704,898,300,91,504,908,249,9,612,972,332,926,848,986,592,192,215,836,237,72,624,552,255,18,363,569,393,53,253,921,977,887,265,623,592,365,772,427,626,53,303,386,460,876,991,695,58,9,258,935,177,850,264,557,709,555,300,26,549,206,93,86,567,291,276,919,58,211,345,998,783,614,331,228,243,550,993,12,409,746,476,76,438,318,373,811,406,533,362,845,833,212,211,342,342,597,751,90,460,359,656,406,551,3,953,496,855,861,940,990,967,170,381,330,465,50,652,120,140,256,492,708,379,409,913,299,534,685,155,177,58,136,913,607,698,273,887,113,613,886,696,430,999,84,904,713,243,470,587,596,490,906,143,532,512,256,87,44,993,334,231,708,95,131,90,843,176,434,198,286,780,655,311,380,891,966,130,34,336,609,194,237,868,484,488,724,395,886,460,872,667,534,365,543,936,729,429,96,177,124,394,219,367,800,737,301,530,614,530,279,873,168,750,608,798,234,350,683,287,525,82,925,500,844,260,560,145,711,38,650,626,558,771,376,186,379,205,124,661,162,251,987,395,894,131,686,448,914,264,729,967,178,978,656,666,273,395,751,375,727,159,689,974,601,421,764,810,484,98,312,36,795,3,322,963,923,21,859,356,275,487,372,755,373,17,303,348,74,150,321,953,28,195,859,211,845,782,978,565,444,448,905,219,918,40,348,572,925,29,856,624,590,988,269,268,476,705,671,133,704,339,668,323,831,276,55", +"803,84,795,121,212,637,156,769,367,496,601,568,603,869,630,607,468,661,235,916,846,824,132,736,66,750,889,237,892,762,426,951,174,21,764,183,130,452,582,243,830,454,820,219,864,6,930,865,109,756,918,262,453,563,245,442,494,442,676,836,308,152,271,606,787,904,142,627,815,199,86,390,526,361,169,237,528,979,662,769,448,117,659,142,648,687,367,936,506,383,254,978,660,274,125,391,413,645,231,640,443,16,853,9,659,571,407,602,195,228,500,486,909,759,690,292,609,426,673,658,757,372,421,32,60,764,176,360,732,744,666,740,382,676,560,837,919,708,933,881,433,357,841,4,945,63,376,961,678,780,422,602,675,537,627,249,67,991,907,215,552,8,118,851,583,933,798,887,145,838,629,134,571,51,401,546,92,780,418,292,371,969,270,392,540,325,749,755,453,967,271,306,166,452,909,139,861,44,138,802,554,379,673,319,311,770,770,841,734,800,541,236,712,526,107,42,97,995,481,929,214,464,664,721,254,145,255,398,936,234,333,838,669,628,671,120,834,613,823,149,198,577,610,847,200,117,111,653,91,7,3,18,828,657,255,790,852,642,653,976,297,57,438,760,503,117,281,475,379,896,685,373,675,758,817,337,347,459,545,725,802,631,631,367,924,221,111,303,948,259,208,650,639,310,614,686,761,964,746,440,64,995,750,227,589,457,688,645,125,51,54,594,395,528,412,976,142,142,809,806,420,588,33,848,30,352,370,150,457,737,508,969,683,901,50,671,924,799,30,500,866,958,53,232,207,859,891,311,199,698,921,926,884,204,668,68,29,255,943,927,57,462,443,685,548,26,58,722,681,250,851,408,698,117,434,162,659,930,750,149,611,198,212,904,963,654,228,884,874,949,767,106,477,460,647,723,118,26,124,423,616,561,788,594,708,480,598,76,243,664,850,232,897,531,81,620,464,151,577,742,472,945,98,897,142,209,937,669,31,545,966,73,884,976,882,429,656,534,574,895,142,443,87,805,675,764,391,168,588,548,160,717,864,234,398,163,167,347,486,650,417,850,136,533,629,329,294,50,630,195,446,881,927,69,684,266,536,395,823,713,765,788,857,702,158,172,444,716,704,389,838,196,957,158,128,534,114,464,627,518,902,116,390,152,267,560,747,266,167,742,808,57,673,183,888,877,652,677,507,716,996,733,496,873,875,73,733,961,410,962,579,973,104,301,729,949,838,21,794,746,924,500,468,274,511,402,4,190,379,280,531,980,437,550,709,210,323,694,24,887,322,876,89,754,886,372,85,865,632,284,377,522,910,578,220,457,409,640,276,647,211,37,100,285,625,73,991,170,622,919,853,478,968,322,352,427,595,512,810,7,300,22,366,650,310,488,859,459,743,727,209,17,609,348,78,19,631,3,598,608,108,349,491,939,403,851,973,831,918,606,639,806,865,243,578,407,680,411,915,669,531,755,436,852,655,501,598,930,687,596,671,777,418,361,908,587,510,321,949,325,353,436,252,191,380,25,0,287,95,373,497,341,933,514,779,911,761,693,485,832,104,875,617,819,127,956,513,282,222,110,81,929,72,512,103,656,133,390,84,69,433,436,39,731,526,458,760,324,199,41,860,284,37,226,554,318,769,990,253,235,496,124,240,843,184,87,10,734,759,985,256,560,389,167,220,174,603,439,527,185,784,138,458,210,930,614,372,525,200,94,561,74,676,594,264,635,84,785,733,247,224,22,508,907,571,895,838,354,590,702,818,966,52,130,329,585,621,871,419,451,272,776,189,154,838,961,593,379,487,885,15,403,861,387,787,407,300,229,214,326,496,889,153,207,839,228,386,715,680,305,939,724,804,318,172,911,150,278,6,632,863,718,681,548,830,296,420,79,428,771,948,819,917,826,70,116,344,614,815,657,925,499,290,36,372,201,885,874,571,306,58,785,721,602,106,391,848,926,659,497,256,780,370,811,588,634,984,699,90,564,976,397,811,56,193,425,829,818,383,801,556,662,432,924,932,937,527,357,255,479,380,762,225,446,618,667,430,140,605,669,396,533,692,602,871,147,776,785,296,445,133,473,94,793,80,653,102,50,143,188,194,450,539,951,854,344,354,795,329,983,280,535,96,978,233,642,829,89,873,332,862,631,330,517,939,72,686,734,106,249,52,818,170,321,529,175,906,572,614,953,268,211,905,146,316,319,763,970,446,350,249,175,432,916,178,823,771,133,225,57,341,528,814,48,178,862,506,62,887,600,717,142,665,380,630,677,391,779,723,292", +"164,814,415,329,387,967,54,581,492,102,363,900,838,16,201,799,183,13,663,754,264,633,198,786,746,633,703,463,834,77,81,136,844,738,953,776,668,797,328,828,721,698,656,84,372,907,958,242,658,93,825,731,437,678,19,317,953,967,359,654,839,410,992,967,980,767,264,543,238,570,560,684,558,490,382,363,10,645,565,942,608,434,415,749,236,71,330,984,653,723,373,193,502,192,776,230,596,424,952,280,162,63,378,64,266,419,6,84,684,603,726,382,948,937,45,611,605,563,518,918,156,927,213,621,935,156,811,749,367,86,228,763,204,344,743,310,295,502,311,513,743,485,616,885,383,890,521,988,438,142,198,551,5,227,835,93,208,110,76,321,826,383,763,70,628,780,71,449,616,134,610,250,762,708,747,578,765,707,753,685,68,318,69,988,433,244,626,923,865,635,123,964,397,416,27,965,695,662,888,236,255,451,562,577,799,758,416,924,75,219,288,999,598,739,698,323,318,951,168,163,188,806,859,234,235,18,388,275,850,370,872,21,151,125,865,337,590,509,518,392,606,559,477,145,348,352,661,21,832,816,699,690,955,122,670,780,28,607,326,796,95,962,301,610,419,335,28,876,748,137,70,147,404,533,858,336,786,461,665,526,608,401,213,887,342,852,452,138,927,642,663,557,274,153,943,577,885,581,590,939,325,734,178,208,718,750,345,297,447,812,916,541,631,113,680,722,191,603,485,253,83,78,413,905,519,808,171,885,920,995,447,581,14,955,868,380,566,791,238,462,184,52,234,552,674,127,571,268,254,410,951,268,130,645,74,457,91,682,828,228,161,938,830,737,528,727,253,713,508,521,11,320,394,905,764,459,671,730,777,826,207,278,606,887,861,399,414,244,415,159,697,325,203,461,186,759,292,517,282,252,602,691,902,10,826,294,947,927,910,708,686,227,152,95,316,19,321,996,387,353,706,883,960,808,272,560,205,494,298,694,154,23,988,358,506,405,346,563,526,179,558,216,146,541,759,814,906,24,371,523,865,967,46,510,321,777,823,286,141,745,526,49,546,107,154,234,726,102,916,294,761,993,532,796,401,268,61,908,794,769,153,298,880,164,576,852,839,505,231,847,334,172,179,558,576,571,283,966,903,244,711,671,1000,370,195,884,59,166,335,453,466,321,656,155,196,7,91,425,230,902,222,427,790,749,987,548,583,237,646,452,19,456,31,534,870,743,893,514,789,434,184,778,233,177,344,569,107,724,812,250,718,156,72,630,279,56,755,787,606,289,73,469,877,358,113,250,945,282,977,977,22,662,734,769,45,122,983,704,721,865,395,232,437,746,656,50,171,494,160,816,29,882,237,803,579,915,452,352,7,733,590,23,41,243,791,963,885,797,461,115,219,931,146,536,751,758,992,646,940,164,996,554,420,764,856,785,266,343,852,329,766,822,89,217,563,338,703,215,19,986,392,996,855,846,836,266,559,436,732,615,654,267,148,256,303,786,28,610,877,356,73,685,777,824,836,206,287,0,502,659,210,857,973,888,997,193,214,760,935,734,815,74,26,506,91,395,42,340,911,977,894,967,382,25,842,217,514,980,744,563,811,588,691,299,204,585,452,821,760,174,538,203,406,565,172,435,567,441,626,548,968,141,634,546,943,773,450,615,517,582,445,968,646,268,740,613,352,449,594,162,63,536,403,151,880,60,653,906,256,358,722,483,666,604,312,916,155,340,687,438,287,545,528,342,215,738,349,444,318,382,553,812,791,263,446,928,847,691,363,419,930,953,306,936,446,354,938,215,271,522,729,224,2,296,457,970,598,554,159,205,78,331,10,20,688,944,159,699,953,828,497,910,784,768,461,432,134,103,527,74,586,506,804,756,191,271,73,47,418,349,908,975,965,410,98,965,545,114,962,220,645,365,818,711,835,628,666,600,725,773,174,980,527,690,552,180,210,819,903,538,181,845,368,426,296,460,714,657,106,144,404,202,43,661,943,554,584,6,903,862,564,828,236,332,899,339,475,932,505,940,420,388,211,677,727,9,788,601,347,542,747,877,450,240,850,127,10,490,751,439,564,37,610,224,833,280,979,669,748,427,660,344,83,563,23,101,75,111,511,634,902,758,715,700,965,159,141,364,273,378,894,785,681,967,933,261,217,153,89,979,62,441,727,296,595,89,618,909,532,336,185,107,368,247,318,470,447,704,624,14,541,433,653,236,95,348,790,58,777,244,965,522,931,329,867,155,828,540,524,655,829,666,333,963,286,548,854,487,954,378", +"806,656,475,156,855,735,103,627,964,330,284,639,672,734,903,400,138,101,853,291,556,946,973,918,648,136,859,600,209,985,90,729,76,327,888,464,905,680,365,175,914,408,765,600,662,751,691,847,802,322,795,806,543,645,824,336,915,134,899,891,341,454,446,443,589,186,257,706,219,567,107,885,710,72,297,691,824,986,990,488,396,196,710,21,356,189,627,91,392,282,721,765,605,445,273,598,901,703,498,761,377,957,300,725,788,790,744,404,764,846,465,383,69,688,146,472,622,422,221,985,208,809,91,897,312,783,53,887,151,155,433,758,12,489,644,567,825,733,455,347,71,868,660,682,374,897,81,527,524,309,907,504,39,227,869,75,465,378,494,885,786,80,454,446,719,145,870,438,45,680,802,713,253,893,399,340,393,245,667,463,723,762,421,386,56,194,516,380,632,869,579,382,334,190,159,403,686,148,755,757,948,291,594,268,102,716,992,668,581,508,680,718,859,244,358,335,291,234,943,667,94,580,7,524,448,672,578,12,835,292,785,760,78,72,565,411,690,832,632,906,330,621,31,278,600,200,521,568,407,956,122,596,987,986,431,146,816,300,108,145,339,290,301,915,224,568,63,612,303,89,634,329,324,739,945,406,605,965,417,303,938,971,442,40,336,545,302,362,930,74,918,174,767,133,213,235,371,657,955,716,121,187,730,76,385,734,672,910,716,942,202,50,888,138,4,785,665,875,390,592,470,372,90,231,683,956,171,38,542,863,927,51,49,181,259,228,741,40,594,946,137,77,827,915,769,355,638,292,466,265,677,657,378,650,159,464,728,644,284,272,894,647,739,660,583,366,120,953,649,219,748,480,981,282,918,865,413,597,936,59,798,141,429,977,293,230,293,498,117,964,784,617,493,601,129,888,722,888,97,704,252,825,97,546,782,577,145,166,37,556,943,868,117,421,582,171,198,448,489,303,392,214,648,660,117,964,694,766,491,47,437,348,419,630,389,541,803,693,815,550,426,190,928,862,422,390,358,313,207,6,779,452,989,535,630,895,333,419,57,261,231,973,495,651,149,189,974,255,392,416,906,904,684,133,58,226,640,81,670,175,356,374,288,95,465,165,907,28,615,208,603,795,725,525,442,432,523,889,166,337,183,108,150,72,481,599,901,260,411,328,957,316,659,343,133,357,414,501,157,690,535,755,7,131,917,641,748,154,28,143,251,130,727,243,898,881,766,84,182,53,828,262,35,295,492,999,44,998,492,133,621,265,716,924,804,945,715,428,937,812,899,952,599,318,700,74,815,475,22,641,363,388,990,614,44,225,588,32,360,167,222,816,942,728,742,570,417,366,634,190,27,300,28,429,698,901,689,241,802,173,536,753,633,308,905,239,188,794,342,505,881,384,855,843,792,773,362,637,803,357,740,549,415,8,603,613,991,207,574,530,439,921,338,237,697,130,702,430,38,450,500,247,896,164,234,217,357,270,118,833,931,89,128,572,79,689,175,969,664,795,586,967,985,511,151,48,95,502,0,802,114,887,91,137,577,76,866,32,442,827,569,849,138,32,266,928,244,970,589,610,952,724,973,327,646,615,377,560,570,614,807,473,681,899,941,908,43,398,516,302,190,16,435,507,656,822,819,440,712,780,762,841,22,849,179,459,118,993,330,930,161,974,520,412,806,872,753,92,755,94,71,892,786,215,338,886,620,986,963,982,989,961,658,350,273,917,903,532,736,212,897,65,261,202,788,52,99,292,171,184,809,78,738,950,38,777,399,5,955,748,578,324,305,424,445,673,367,414,170,889,98,64,830,413,934,102,424,72,965,874,466,447,4,695,185,184,59,85,480,104,941,406,841,733,452,684,186,583,865,589,671,781,753,518,883,653,1,45,491,518,226,307,41,104,231,731,977,257,502,604,106,232,438,870,682,906,495,616,271,842,362,604,342,927,856,348,873,475,591,978,919,771,732,385,167,982,957,821,7,869,969,29,449,295,665,264,819,892,369,854,982,25,248,274,18,257,143,476,252,593,482,343,887,797,78,871,137,999,869,283,537,149,542,599,897,226,257,316,295,56,323,894,926,53,548,125,924,628,816,647,204,103,360,199,143,341,736,87,636,211,688,938,692,762,524,669,857,592,249,872,58,459,852,164,364,501,436,366,74,382,33,766,708,141,211,747,602,612,982,90,239,51,101,118,606,221,269,651,941,896,233,987,491,32,868,184,165,155,932,68,280,435,730,692,165,834,864,533,587,935,628,155,728,429,645,993,959,242,515,833", +"187,236,851,488,65,177,668,340,544,547,636,80,776,12,576,724,844,146,543,31,952,837,952,589,409,389,178,503,677,586,909,557,974,352,32,914,546,561,117,772,897,79,353,640,585,630,129,235,847,964,862,323,566,727,220,305,310,651,406,997,850,423,726,329,643,436,263,492,118,13,41,288,973,604,208,819,535,79,24,259,144,643,175,585,4,971,902,208,519,66,907,640,497,761,108,578,143,173,498,672,157,371,982,223,866,563,536,127,510,568,496,371,225,83,423,550,180,69,277,571,588,571,704,973,48,167,821,910,456,783,905,413,817,259,585,613,33,784,374,851,744,901,837,943,497,980,745,540,720,717,780,99,76,493,89,895,298,533,903,852,403,709,293,57,875,237,651,440,443,589,369,234,967,62,792,394,670,234,928,531,516,647,361,490,22,647,951,327,312,802,669,489,578,755,922,898,863,468,117,217,350,400,979,299,299,820,227,855,776,677,666,124,878,76,203,871,917,416,141,232,647,504,438,77,623,641,290,484,22,675,119,952,591,185,481,507,548,402,954,21,375,977,31,989,693,451,615,462,499,771,402,828,443,780,223,482,655,236,299,944,453,179,947,880,816,852,411,434,763,173,603,874,808,708,987,549,836,710,2,512,692,839,152,484,973,921,934,635,702,192,989,564,223,840,581,957,251,57,858,742,337,444,21,237,84,289,845,296,244,756,73,560,984,834,721,800,226,514,465,626,928,357,388,535,376,284,922,681,930,554,297,187,411,964,373,718,629,618,216,348,354,706,100,838,38,140,543,322,197,695,202,381,401,899,801,179,320,129,971,583,316,476,950,512,519,702,658,234,781,925,426,834,13,255,229,456,957,908,472,161,450,571,382,201,475,988,112,998,321,577,942,304,925,968,199,489,495,852,991,435,698,780,852,701,638,960,504,388,353,790,511,693,645,323,173,914,521,686,674,90,124,882,332,164,972,517,780,391,177,52,341,932,596,609,525,677,318,842,386,671,423,284,116,197,258,941,615,275,120,434,752,759,657,476,242,14,588,242,395,538,854,4,817,784,478,575,806,852,860,760,605,694,756,547,118,236,231,283,551,246,386,577,361,536,257,167,686,448,574,628,963,102,242,1,284,70,582,68,706,671,523,892,704,986,139,267,610,73,194,190,654,721,793,431,583,956,574,793,5,993,423,899,44,54,302,698,958,197,974,998,875,33,408,183,497,203,288,648,117,160,268,250,557,742,799,246,473,647,342,422,942,331,131,455,389,574,542,939,813,714,879,863,558,999,308,802,334,476,611,748,73,348,56,140,662,634,239,120,939,769,631,742,681,840,41,913,10,566,648,42,666,594,211,104,424,443,167,647,343,934,788,758,766,272,12,328,736,932,17,54,485,303,493,841,626,514,322,944,74,382,793,916,206,351,42,182,737,625,120,946,844,520,589,57,642,395,233,436,157,320,63,959,102,869,146,121,126,31,188,709,75,405,795,618,491,689,317,12,415,65,907,163,429,674,378,729,373,659,802,0,322,311,992,377,575,244,441,7,725,481,383,837,98,455,406,880,682,357,646,928,178,486,536,849,494,861,601,114,653,570,4,863,375,5,172,884,698,571,622,174,130,98,915,478,1000,17,775,331,91,283,207,522,425,284,981,26,311,244,36,896,69,847,945,517,503,146,116,442,739,198,542,68,301,132,151,672,336,734,487,614,935,393,97,159,157,679,319,784,267,33,12,25,293,709,605,653,724,487,555,355,126,525,87,579,695,444,384,56,134,844,927,748,446,393,843,640,868,555,945,909,176,474,435,232,739,822,663,879,943,897,871,674,321,938,338,515,320,582,880,270,786,149,955,576,849,286,644,322,168,602,767,553,119,905,535,695,702,292,836,374,144,419,279,635,514,338,244,22,955,165,877,209,38,901,411,693,794,900,576,204,848,343,888,682,603,910,660,527,573,551,280,854,227,759,552,902,466,743,838,163,627,288,345,283,102,748,794,223,921,93,944,280,94,388,974,497,609,970,276,878,723,816,562,868,184,471,869,677,356,659,475,77,190,619,133,185,288,796,767,241,3,994,539,529,600,306,427,727,673,141,952,347,79,479,594,731,831,293,544,149,482,658,795,769,460,643,508,183,737,873,467,488,98,498,926,728,443,466,691,874,440,633,966,665,217,803,94,522,511,869,565,526,168,603,116,401,574,481,251,130,782,40,484,99,107,802,516,805,636,884,610,726,52,957,836,539,857,875,845,452,379,524,397,381,342,862,887,67,646,63", +"989,262,274,645,382,766,113,686,852,550,445,617,937,131,577,628,56,208,491,805,693,725,16,389,108,887,491,627,431,341,816,550,566,703,502,928,792,649,289,786,884,654,214,592,625,334,964,954,409,304,910,964,786,914,834,36,297,829,477,112,797,4,327,607,703,80,908,299,965,837,990,66,68,30,179,542,77,849,897,999,462,774,33,284,233,110,714,155,388,71,91,441,214,108,854,550,339,740,230,134,336,685,599,830,114,233,901,843,356,678,132,715,39,693,734,217,510,275,662,213,781,301,890,382,721,89,447,33,375,635,357,280,712,819,214,108,322,594,787,788,789,437,502,505,593,888,573,274,862,180,85,702,173,831,620,739,582,46,993,625,811,595,395,494,455,306,764,289,131,504,424,522,401,882,293,432,143,721,759,906,23,923,111,219,698,342,873,968,275,404,395,866,490,119,67,496,174,225,304,278,632,598,816,866,634,901,414,588,647,328,349,551,332,246,548,494,278,705,953,119,753,712,990,817,121,820,497,934,213,813,442,938,723,720,695,148,18,271,261,922,306,788,204,117,544,281,276,740,614,940,599,146,268,448,481,155,128,266,674,208,21,398,932,331,617,694,649,719,206,626,294,771,448,431,475,516,905,436,247,617,77,468,792,55,643,215,760,467,613,443,661,217,430,403,896,838,796,535,297,150,761,581,490,318,509,528,278,552,519,740,127,594,812,61,92,88,979,659,693,262,714,727,402,9,670,886,498,318,716,90,478,688,677,516,127,819,811,392,571,560,335,412,920,284,52,565,680,697,243,259,628,177,464,519,789,244,853,609,116,56,618,619,278,481,311,671,662,162,697,883,968,126,441,852,797,211,181,36,163,364,873,271,539,671,262,333,113,404,521,583,350,943,20,91,289,705,873,667,488,799,196,220,513,308,861,655,527,275,797,199,193,347,521,924,745,191,249,163,420,947,532,551,733,192,313,876,239,971,923,238,715,180,996,113,132,5,517,374,355,726,121,96,866,287,766,241,792,36,3,570,212,503,405,104,271,844,681,166,63,432,532,218,713,501,785,311,809,848,428,453,854,378,869,964,860,446,610,299,778,352,586,509,635,529,508,361,127,190,167,257,465,728,242,429,566,363,332,60,772,805,867,227,89,343,319,44,167,531,174,17,618,48,506,936,858,804,249,200,111,682,7,454,426,523,314,134,297,275,118,986,926,483,800,526,542,655,284,992,86,756,54,653,899,15,920,737,547,973,714,989,445,573,397,296,587,789,122,977,314,591,423,125,717,971,762,418,603,558,59,562,814,187,5,468,191,97,216,745,831,6,81,728,426,896,421,973,948,479,852,855,444,649,938,573,516,320,848,516,289,252,764,3,556,470,363,709,839,608,770,592,170,933,367,891,892,756,484,329,317,552,896,944,836,18,81,853,628,610,931,604,725,416,504,442,606,563,793,677,185,332,679,885,653,494,338,143,906,197,470,118,19,645,282,304,466,182,269,539,86,355,340,333,108,340,952,11,497,210,114,322,0,246,430,989,897,512,380,976,550,851,513,582,583,329,822,29,988,726,163,15,166,426,645,612,93,790,8,195,41,626,989,896,158,541,958,83,65,139,156,160,631,393,956,976,457,886,171,896,974,372,393,939,872,323,520,963,936,827,423,448,853,293,529,943,968,947,267,396,62,509,313,708,937,146,708,409,409,863,821,614,825,536,682,101,260,839,537,315,282,127,128,344,122,704,377,452,120,337,748,268,495,753,407,424,441,281,364,803,40,344,139,221,651,46,744,812,621,651,392,195,384,366,912,560,306,963,833,101,116,307,951,923,794,394,870,518,132,819,824,12,621,122,213,801,863,813,733,169,969,288,868,858,353,216,868,34,663,641,273,683,88,228,956,462,357,689,399,24,639,687,411,793,946,84,662,609,901,786,443,543,233,223,948,619,522,508,828,888,306,166,751,89,540,645,264,858,855,556,93,805,545,421,894,312,198,148,783,428,833,495,124,881,366,978,803,278,738,252,877,393,381,267,675,159,860,591,987,221,742,401,565,51,477,482,963,765,286,643,524,489,848,119,11,183,572,107,750,461,765,116,844,200,143,104,628,565,340,324,745,72,705,173,47,790,863,203,379,314,405,269,33,898,680,413,469,159,167,662,527,759,154,497,391,209,475,779,475,174,159,464,887,742,391,960,116,478,136,459,108,357,972,664,541,800,913,585,221,46,879,858,8,324,461,351,406,866,567,646,483,761,463,320,464,226,138,455,667,789,842,71", +"178,476,953,398,504,349,700,690,961,336,850,774,989,794,245,969,336,962,791,537,847,391,265,591,285,301,439,851,359,884,802,127,636,250,334,931,68,500,822,528,389,73,91,200,70,473,957,802,782,874,438,747,907,919,40,70,703,976,983,21,43,429,471,357,383,756,894,241,122,813,752,964,480,844,451,271,274,559,629,197,823,66,907,598,297,218,821,892,912,687,507,780,114,107,454,879,849,87,129,885,484,988,507,350,278,317,414,969,79,245,331,339,883,84,510,716,151,667,762,34,528,106,99,749,329,749,315,314,600,111,1,603,439,986,413,99,990,829,162,428,223,132,813,201,932,530,570,967,5,17,879,634,842,267,502,383,544,457,34,284,268,698,14,685,372,399,280,775,393,998,453,223,432,564,570,377,943,629,833,685,405,34,339,237,93,226,4,542,326,899,337,150,805,117,302,35,854,280,800,603,139,830,558,95,875,712,460,621,503,363,95,122,73,297,269,478,443,46,625,71,98,808,263,163,655,808,438,465,464,83,195,302,347,142,645,256,902,975,706,130,164,245,795,835,441,806,982,983,635,511,963,580,916,10,147,680,171,243,286,925,411,300,861,814,298,588,379,795,27,771,22,303,999,184,1,301,662,469,393,911,456,972,701,769,660,763,114,328,524,627,469,941,989,398,338,382,675,100,934,31,194,243,781,356,937,855,364,736,377,850,66,973,927,397,714,959,847,449,231,621,421,29,554,170,443,323,848,557,844,895,145,335,329,274,256,711,204,562,95,334,684,651,438,344,280,549,274,772,872,271,709,338,251,573,552,71,498,746,25,280,879,416,147,952,632,748,92,277,333,894,890,721,61,979,968,288,18,448,967,427,93,933,431,844,208,63,748,574,596,130,435,573,126,183,802,518,992,154,586,589,685,827,761,519,945,695,944,156,751,482,424,28,124,632,850,687,942,517,332,517,799,507,316,177,486,19,155,331,883,275,95,186,544,225,253,722,658,26,559,287,432,13,715,359,901,114,103,422,234,171,862,916,625,580,494,55,53,130,573,820,557,113,742,87,126,867,997,823,829,686,321,998,857,403,749,359,792,359,969,285,258,323,670,509,644,685,170,44,43,823,27,866,356,253,590,762,329,343,351,675,496,49,2,395,473,621,520,257,675,680,332,365,647,743,424,728,186,263,63,18,317,866,813,333,79,604,342,187,719,507,978,783,990,677,918,713,340,587,719,229,495,601,602,96,150,646,618,389,943,127,597,743,177,109,985,511,181,169,701,986,321,13,546,486,775,783,887,26,163,274,32,125,248,357,763,398,343,724,710,198,302,391,396,203,940,763,951,801,18,573,466,708,227,313,512,490,685,721,961,814,786,501,835,640,581,624,818,792,455,115,373,38,256,370,262,518,53,247,812,438,539,471,578,749,579,996,441,862,812,870,562,46,962,332,505,928,964,505,177,360,43,555,316,155,827,28,908,897,324,86,100,436,64,209,309,600,251,476,704,381,681,215,762,963,205,16,341,857,887,311,246,0,327,831,912,280,418,605,140,510,686,125,38,226,614,705,969,378,326,158,902,259,759,442,444,484,78,410,22,653,880,469,868,65,929,677,83,768,35,401,378,743,434,833,894,948,560,623,888,844,709,106,46,468,409,100,665,26,558,114,3,876,744,138,333,324,650,473,648,591,783,199,900,440,431,456,802,139,475,155,324,273,789,829,44,362,237,337,152,24,557,24,204,905,391,171,961,626,445,601,428,903,101,442,834,587,773,184,455,329,571,894,815,748,472,564,443,931,402,433,799,505,645,916,646,259,834,991,232,770,991,146,64,411,873,164,428,109,147,574,547,899,709,168,516,9,920,139,279,646,127,554,278,783,736,520,608,426,523,783,8,954,588,749,770,478,318,723,420,272,61,921,497,532,764,281,637,932,772,718,817,283,888,590,300,95,98,399,346,218,675,351,77,518,866,443,726,581,217,128,563,675,717,600,253,942,861,684,298,241,795,290,806,587,290,498,927,62,548,223,405,264,16,698,589,292,736,68,694,722,609,121,28,782,721,861,660,330,243,602,671,718,282,493,530,733,628,682,417,187,760,773,996,661,348,879,569,635,716,452,431,963,432,293,443,657,559,130,107,19,536,257,880,217,967,706,802,252,24,911,808,25,955,777,262,807,369,451,725,245,174,627,991,124,671,353,887,147,676,608,530,689,16,496,470,4,602,680,706,693,24,116,230,139,712,329,475,116,439,978,792,919,728,379,453,879,145,710,499,555", +"257,806,899,23,586,119,736,248,608,70,798,145,62,153,53,509,354,513,738,766,663,38,351,714,472,689,347,258,374,371,29,415,22,261,990,772,105,318,861,82,573,317,983,345,224,346,349,595,262,790,505,653,560,88,60,543,145,651,89,541,803,86,417,947,106,129,299,794,866,566,104,40,67,634,52,418,365,174,343,737,634,929,723,3,545,744,682,103,400,342,861,52,472,856,376,261,298,115,782,718,831,202,205,531,552,776,666,722,246,200,459,805,209,937,406,728,632,521,886,984,683,742,475,290,896,925,841,927,701,847,927,478,28,831,19,359,693,451,279,987,831,69,598,319,576,923,813,900,754,271,857,899,791,428,862,929,603,294,74,565,824,484,6,792,987,810,935,796,622,762,583,671,532,668,274,334,477,822,724,595,438,11,5,6,925,757,43,8,451,977,357,834,176,692,699,934,869,426,603,180,709,137,167,226,733,499,670,610,691,371,89,730,387,828,823,575,284,746,52,642,985,70,321,118,30,849,175,683,392,545,63,951,498,130,144,398,829,674,421,839,857,278,566,2,161,455,809,124,583,949,180,551,228,520,836,699,896,78,949,207,924,746,772,412,191,113,723,98,338,297,63,516,140,304,518,299,360,279,123,371,496,613,585,48,96,896,667,971,349,231,272,707,558,492,716,300,73,892,81,657,94,948,494,89,939,238,794,771,433,633,924,27,494,371,802,621,169,417,173,507,126,197,371,31,490,185,881,868,581,404,602,242,316,31,491,161,499,321,768,236,739,803,994,915,237,229,715,827,793,230,803,51,659,309,200,262,561,638,59,844,112,304,386,845,238,432,405,231,468,341,398,283,765,644,750,214,708,226,833,801,829,709,254,484,741,528,2,401,782,153,635,441,434,842,159,673,93,772,157,612,566,3,623,668,986,581,887,253,167,151,354,724,386,953,402,445,778,407,808,334,499,190,759,68,859,89,102,948,405,588,951,405,78,786,58,915,617,900,852,723,931,709,903,771,479,12,960,429,473,88,179,755,460,546,46,565,24,538,173,774,15,212,946,987,39,255,813,653,333,701,13,94,805,539,935,930,345,463,319,679,352,884,909,413,286,381,845,232,36,634,384,677,898,331,195,201,969,343,593,589,159,182,842,346,754,707,867,29,40,878,121,308,336,739,783,177,450,751,364,129,337,342,666,305,412,682,270,344,88,636,508,186,762,387,552,145,54,730,583,215,511,562,485,246,685,689,192,371,600,311,288,150,459,459,309,998,421,126,344,2,693,740,585,960,788,592,839,240,52,484,728,873,141,533,221,512,130,440,315,986,93,732,464,207,497,206,595,599,745,120,136,349,473,368,821,911,327,456,285,815,842,609,252,548,735,677,350,356,802,834,554,113,217,347,288,936,299,157,961,770,397,123,952,809,969,334,143,250,635,195,586,16,686,847,164,774,478,817,68,486,694,329,698,920,711,475,361,307,803,877,602,525,301,117,575,133,981,233,39,924,398,886,132,255,549,597,933,973,91,992,430,327,0,256,439,969,344,339,851,315,372,219,575,898,360,512,824,103,829,936,946,599,795,980,691,216,974,403,738,666,448,570,562,631,271,768,291,601,746,323,424,93,517,930,946,851,121,640,965,661,830,535,132,752,593,353,696,295,435,612,137,766,875,220,795,529,416,28,836,889,200,417,101,111,347,173,388,296,342,151,828,653,766,883,734,915,628,572,799,169,722,926,190,136,184,563,56,26,255,694,873,122,878,332,147,586,362,648,766,913,379,400,376,104,291,232,413,230,184,212,850,901,56,543,317,728,341,686,136,858,23,575,729,272,809,514,461,382,470,554,216,877,98,883,280,993,571,932,744,841,461,496,870,931,794,102,390,259,807,64,13,931,636,181,338,157,622,926,229,395,368,154,179,281,218,701,489,216,692,438,720,551,174,557,230,881,319,991,59,504,795,37,9,902,818,96,400,611,217,475,787,302,683,598,992,312,405,837,580,813,778,566,937,247,127,155,539,3,507,445,787,128,999,440,453,6,718,64,312,20,830,940,633,633,520,938,83,736,398,473,918,765,126,779,559,964,745,967,286,723,432,962,615,798,400,538,297,781,582,653,290,255,94,18,666,560,994,574,933,976,311,658,241,51,364,145,639,561,114,316,401,942,283,754,347,191,283,689,541,853,38,11,675,395,530,765,951,260,100,783,847,192,413,839,585,879,140,69,679,822,870,260,454,912,572,716,991,116,997,712,24,338,155,134,818,891,522,976,350,667", +"835,589,29,214,70,493,399,880,115,555,516,633,850,315,764,761,963,566,757,543,171,712,308,825,470,586,168,496,694,381,514,282,345,93,382,932,912,667,12,576,772,478,739,35,24,846,243,289,741,495,516,835,361,612,515,97,680,300,386,360,96,669,291,486,803,436,963,165,672,409,781,974,974,163,552,579,66,35,7,684,309,906,304,974,626,247,929,351,714,208,511,528,472,856,539,525,273,891,988,339,558,990,441,774,96,321,441,893,801,68,894,730,623,764,216,20,816,91,384,198,40,691,640,997,671,945,980,404,829,386,724,997,584,362,173,774,935,822,110,739,50,97,849,680,152,738,414,615,811,435,965,788,532,238,673,490,536,68,843,115,991,672,187,458,573,603,535,116,913,580,230,696,752,57,523,317,427,347,378,796,762,55,428,70,477,672,432,7,233,453,999,351,809,803,903,257,643,568,447,277,339,719,945,480,527,591,840,370,619,903,52,221,798,382,260,720,777,459,419,614,880,826,715,636,842,135,858,891,400,912,533,756,579,717,505,817,288,729,787,290,42,698,830,81,899,4,363,333,751,254,539,137,991,722,897,330,530,295,784,48,47,500,291,945,912,360,788,974,43,721,271,909,966,783,847,937,104,889,943,817,539,150,943,469,554,521,877,935,71,369,933,730,55,575,611,147,742,400,790,879,756,430,441,375,894,58,958,992,881,695,862,421,354,321,830,450,950,306,762,521,491,593,840,679,433,423,478,701,868,569,557,2,197,383,181,878,558,766,85,852,192,415,67,76,755,348,109,871,136,387,979,138,657,400,180,474,929,251,442,778,559,991,935,360,606,289,341,887,846,590,673,181,70,962,748,348,725,687,572,243,347,399,96,806,644,241,284,619,527,988,752,975,777,61,553,491,467,780,919,433,949,70,951,841,63,255,891,553,159,338,215,308,677,170,282,644,901,456,399,421,153,682,779,315,420,347,946,363,85,70,525,363,726,557,739,148,822,446,488,316,411,248,629,558,409,67,894,696,629,377,299,840,694,61,473,78,222,696,442,215,124,681,13,50,617,891,254,10,373,830,763,877,613,626,595,428,624,84,100,642,909,34,347,278,544,666,274,166,807,957,518,429,550,153,50,537,633,306,910,508,613,460,685,948,38,335,747,668,656,596,520,489,470,707,988,312,756,487,733,679,175,102,52,866,923,379,654,92,265,870,336,92,555,345,698,119,248,346,767,943,28,375,36,643,663,610,665,929,92,223,142,606,766,919,38,694,468,52,419,51,738,547,453,940,890,95,375,699,965,58,720,138,95,161,613,232,571,114,59,129,477,691,319,490,774,983,929,418,912,761,220,98,342,559,344,91,613,556,560,857,671,346,526,160,626,180,22,783,785,234,70,80,501,795,5,751,242,965,405,834,271,372,348,441,833,172,685,269,552,942,59,230,27,25,264,86,405,595,392,99,801,612,118,205,135,599,902,275,72,669,990,971,908,677,550,162,502,62,320,497,746,704,849,270,275,323,514,888,137,377,989,831,256,0,583,194,627,199,452,10,780,664,353,660,314,507,29,971,96,743,13,991,577,441,399,951,505,643,357,434,885,336,734,433,21,310,500,784,618,714,419,612,398,841,720,853,255,426,229,189,735,329,270,48,453,71,82,471,485,23,68,613,811,536,635,656,291,619,201,668,772,465,808,429,542,318,71,727,209,636,607,580,345,237,661,156,691,124,666,140,479,769,785,77,672,350,710,478,498,774,256,472,440,727,229,633,814,280,515,429,289,278,435,349,851,614,655,143,479,766,325,474,614,951,207,20,989,352,172,242,436,55,248,799,50,46,624,245,383,346,627,382,377,515,580,181,115,599,74,338,912,560,920,544,974,911,618,927,132,584,992,868,186,853,476,291,581,904,147,203,123,829,643,983,33,552,474,253,504,577,453,103,472,990,312,961,79,498,566,249,177,790,429,622,674,465,169,153,679,843,990,726,232,289,749,158,638,529,854,116,889,166,181,584,558,538,787,717,711,963,114,968,983,347,29,299,926,152,167,65,888,527,12,401,113,519,981,603,3,374,533,40,554,178,657,762,2,407,112,175,829,173,130,215,95,459,73,732,798,900,868,328,419,409,253,228,56,929,867,573,110,747,479,861,784,302,207,110,723,525,500,968,824,357,691,187,609,320,441,178,502,937,437,546,508,792,806,236,902,956,851,739,501,600,791,456,860,677,530,29,750,77,257,385,963,675,266,903,691,112,691,38,315,302,390,464,132,204,793,343", +"516,155,442,709,704,957,458,878,242,305,465,261,262,454,828,278,915,770,903,61,576,21,22,471,730,705,876,856,352,300,883,501,828,538,293,339,88,269,589,959,335,519,990,174,693,184,783,654,797,918,450,2,33,299,930,413,476,924,929,701,635,151,432,201,969,536,778,216,34,182,695,252,272,507,419,857,64,385,32,360,310,973,644,206,815,483,731,387,694,251,796,282,207,498,781,121,182,640,900,439,429,961,851,122,251,122,342,679,569,496,80,984,440,269,335,308,465,4,430,392,699,785,999,833,324,75,329,873,63,12,960,856,743,562,823,33,462,198,834,73,83,312,832,964,676,718,906,613,991,453,762,549,451,299,556,637,625,467,577,21,17,383,942,772,827,823,712,787,942,796,781,109,92,571,662,371,868,282,715,183,132,4,404,80,354,699,994,307,737,709,183,613,46,731,235,312,995,813,232,34,179,676,297,67,388,859,49,55,506,576,830,265,40,190,43,834,264,18,744,246,669,988,617,265,790,586,343,737,949,737,342,253,665,761,715,664,258,159,944,991,2,867,491,998,450,37,640,852,524,499,59,954,198,927,272,153,886,22,691,201,788,926,25,709,264,198,82,503,287,187,61,307,781,868,282,126,204,983,333,565,323,909,665,935,550,90,285,359,591,200,458,796,769,99,561,9,114,915,548,840,785,88,204,334,645,459,531,712,729,505,517,519,540,297,975,344,230,961,456,327,933,470,565,481,944,933,201,898,266,407,825,871,97,354,643,168,349,146,713,210,132,560,529,614,50,735,835,183,296,632,438,107,961,175,840,251,319,127,767,36,829,66,99,574,856,13,307,552,613,550,493,863,944,377,98,806,753,459,656,569,860,124,213,942,543,989,709,195,586,925,978,651,431,810,540,558,540,893,71,511,422,509,256,615,113,674,927,960,149,543,165,144,583,836,614,539,807,613,272,456,952,351,643,669,307,345,657,165,339,427,836,673,959,733,844,617,509,371,490,450,955,68,97,366,765,564,626,229,443,773,413,924,438,584,515,51,881,644,606,872,232,329,986,996,688,993,326,152,570,157,147,215,737,273,334,681,999,724,549,368,516,960,585,957,404,27,885,617,811,511,403,722,256,389,794,962,475,524,164,796,896,15,404,278,921,143,169,733,843,865,910,856,831,479,672,440,453,249,368,701,707,466,654,361,92,908,778,492,494,48,161,289,148,953,388,498,440,987,870,581,143,345,346,191,972,588,844,532,997,487,161,216,472,926,678,472,164,692,325,395,395,878,415,463,652,934,489,150,104,368,338,982,657,731,520,408,183,693,175,174,133,81,418,298,523,770,62,536,18,752,643,141,971,762,170,586,870,156,79,999,543,984,452,743,210,777,399,162,365,212,53,456,257,7,863,754,180,193,401,299,661,894,868,253,322,386,342,36,754,502,129,291,608,859,234,523,547,378,961,741,225,34,119,530,791,955,266,938,271,902,922,644,420,589,386,617,933,857,142,532,71,257,959,743,938,704,779,997,577,575,897,912,439,583,0,928,993,327,530,432,605,823,25,749,716,782,640,85,710,94,447,67,719,734,634,10,715,394,913,746,714,391,259,607,253,449,929,350,95,9,926,329,150,616,336,65,175,823,990,231,962,1000,136,312,313,157,508,789,315,356,447,8,509,724,926,767,357,640,534,408,234,276,132,572,812,216,28,998,437,234,983,121,292,266,624,934,201,208,227,400,66,647,792,996,421,74,154,91,9,835,136,58,833,460,518,63,63,975,657,720,863,504,579,405,784,269,574,359,930,667,589,61,884,342,768,245,818,973,268,398,74,558,557,892,176,438,567,177,164,526,91,514,833,983,584,91,408,801,508,268,356,567,453,99,160,538,367,726,468,715,615,431,35,887,780,247,623,272,725,90,41,546,18,608,547,316,778,807,399,832,90,4,832,967,876,596,465,521,377,695,81,694,319,816,484,418,647,508,764,758,905,948,269,316,989,740,546,504,184,68,264,718,867,24,694,775,284,547,575,437,179,142,870,963,897,761,571,973,861,392,975,94,68,521,312,232,478,738,879,153,665,927,369,454,202,893,264,165,452,171,781,97,164,982,239,258,166,165,993,31,861,301,607,208,438,774,906,294,396,464,396,582,312,637,57,728,623,958,811,123,40,322,463,608,211,858,230,414,117,617,195,701,810,310,620,882,499,500,804,844,828,443,126,160,229,61,233,221,46,302,134,489,83,180,70,383,900,571,256,656,584,874,723,448,71,820,739,353,468,327", +"172,935,830,875,459,388,984,492,783,595,159,825,788,770,902,940,880,64,58,622,825,443,706,477,368,317,362,143,559,351,476,526,577,48,144,822,854,513,750,588,15,829,520,912,83,432,862,576,826,831,214,908,48,54,206,445,196,772,295,239,111,181,102,653,401,405,244,445,564,8,739,420,237,683,739,37,71,521,909,495,177,759,512,267,720,881,479,494,649,548,539,563,256,243,804,710,90,933,212,142,38,815,270,988,49,131,289,337,815,866,538,691,826,326,624,442,550,970,333,806,153,629,201,448,111,16,163,4,901,186,281,479,741,756,995,19,861,204,803,592,17,196,487,885,378,831,986,945,655,969,590,450,840,661,486,242,338,655,734,155,897,334,640,107,233,766,182,558,355,194,209,559,375,653,433,606,337,853,874,786,818,978,910,951,180,229,91,604,520,966,948,209,214,568,75,109,974,771,43,281,268,314,102,457,669,704,914,448,236,206,504,342,563,658,395,304,499,372,473,656,179,791,821,723,690,630,442,691,722,472,924,537,359,716,343,855,487,951,308,529,834,630,336,889,696,407,1000,869,119,341,925,300,787,497,911,971,998,964,848,391,400,103,860,560,850,53,99,648,354,468,542,657,846,486,665,682,401,68,104,462,716,591,821,782,495,688,290,948,997,10,320,973,500,616,52,931,196,755,57,306,910,845,349,882,216,731,495,760,211,388,493,27,565,647,787,431,379,886,576,622,310,736,971,22,154,601,366,83,659,236,797,652,771,115,435,597,833,161,34,53,847,802,778,540,915,824,89,586,678,478,652,498,638,44,950,373,128,486,473,140,967,124,173,789,893,920,148,158,910,537,126,805,564,114,363,64,712,510,535,814,752,69,874,753,709,824,998,231,197,322,605,551,444,882,213,635,442,217,916,879,896,361,901,645,287,185,46,916,285,465,600,39,948,172,811,47,472,201,395,60,856,348,700,241,853,150,192,557,71,156,719,817,969,7,989,32,437,812,313,252,416,404,370,815,877,349,132,967,472,800,159,1,4,800,432,372,409,913,199,53,908,823,156,701,564,797,22,88,347,189,892,537,14,852,92,291,22,559,394,332,898,266,598,164,368,490,656,225,549,94,652,616,878,634,725,4,384,556,906,811,215,28,219,388,474,261,840,112,430,561,45,826,681,880,433,725,92,634,379,191,534,18,431,557,516,185,549,38,554,158,987,555,897,671,902,728,201,702,545,625,803,935,546,304,857,243,638,506,339,677,660,995,643,182,398,193,433,65,294,650,587,251,352,583,227,709,628,769,974,814,264,453,631,280,617,149,957,763,299,630,84,715,598,48,108,519,217,752,587,249,151,900,679,436,976,405,252,351,959,446,459,413,465,743,346,400,439,922,952,829,220,616,537,276,959,894,373,772,922,991,844,362,624,406,879,243,436,980,441,374,594,79,397,260,241,509,270,13,343,203,198,151,186,872,741,304,570,174,18,130,446,255,334,485,979,362,699,541,403,811,737,95,597,799,108,898,911,193,76,244,512,280,969,194,928,0,961,944,494,94,469,721,644,896,841,923,647,553,708,957,752,895,302,787,572,856,281,980,982,951,894,853,300,77,592,815,468,751,82,120,927,744,806,482,784,618,893,864,384,803,330,991,211,964,77,537,160,300,75,515,234,114,7,784,243,875,596,341,392,909,53,589,156,95,72,354,487,457,154,330,197,384,292,227,498,510,963,235,41,521,544,542,444,324,994,879,177,621,766,177,820,8,664,295,712,701,935,257,142,952,559,891,488,590,69,407,597,126,553,978,898,415,100,820,382,700,558,119,406,734,422,239,280,79,439,342,572,182,80,306,954,920,607,729,481,317,141,717,517,150,627,973,192,469,545,722,514,712,924,78,665,593,823,385,258,67,372,940,352,282,425,66,807,713,601,966,261,477,358,765,869,770,26,996,304,552,935,231,314,156,705,547,405,544,316,860,884,895,15,469,868,382,55,532,746,963,741,342,686,822,165,82,860,279,33,716,110,866,731,707,933,582,558,757,633,981,371,286,772,198,280,872,140,312,988,150,593,603,459,862,302,111,246,593,961,423,175,857,794,840,724,4,416,851,955,210,286,212,448,350,348,781,875,435,885,134,444,585,906,766,858,888,257,364,56,212,264,687,754,519,357,603,233,901,571,6,634,915,789,454,217,110,391,162,955,952,426,301,160,769,290,897,440,763,713,709,135,482,78,945,462,316,350,347,23,568,275,201,718,273,431,183,270,505,394,324,804,821,77,253", +"594,197,374,129,831,574,689,914,664,628,259,625,364,441,88,591,802,314,86,366,111,872,327,304,195,729,751,625,9,510,391,907,731,304,243,865,256,742,524,325,790,887,55,517,555,276,360,788,525,615,125,791,907,223,878,421,672,120,713,749,549,746,726,305,982,94,565,674,275,877,697,264,172,377,549,914,198,597,717,707,58,448,264,518,519,477,213,823,343,401,117,62,673,444,669,766,279,702,429,629,572,798,263,395,72,705,709,629,490,665,77,699,541,366,917,647,378,452,124,329,483,370,492,823,557,653,986,905,856,646,280,827,708,784,484,224,338,527,185,530,900,110,499,414,376,830,538,665,323,338,381,732,329,616,82,124,634,120,723,60,576,324,106,34,559,522,927,886,348,388,222,506,226,566,686,830,406,625,612,145,57,638,36,181,295,117,28,347,586,450,971,303,901,871,100,340,829,34,72,209,525,184,463,994,105,364,963,558,804,95,403,512,622,164,2,630,630,254,403,543,542,626,889,220,847,637,700,526,866,963,285,155,288,8,924,29,894,586,345,624,998,81,10,489,496,215,216,101,779,455,197,24,607,869,856,895,129,709,975,708,431,538,613,332,305,730,61,868,632,386,988,273,751,682,586,977,440,811,532,685,547,759,552,12,722,84,952,890,115,150,222,99,431,22,361,975,616,503,790,920,386,136,681,326,936,732,354,583,61,606,158,817,197,880,76,477,815,229,732,367,261,272,714,278,62,135,309,844,939,270,92,667,952,615,931,806,675,669,696,284,313,613,641,154,297,665,362,156,658,424,951,20,441,986,648,114,709,564,416,610,168,805,573,979,738,531,740,552,369,287,301,978,891,108,202,719,453,193,556,445,190,137,708,354,138,288,677,750,146,471,755,491,63,235,698,349,952,476,675,321,988,196,989,71,839,319,121,940,838,955,296,9,745,272,670,518,756,271,599,45,478,907,124,101,695,527,106,601,137,121,720,721,215,815,571,333,880,686,68,961,49,894,624,602,851,620,582,788,532,38,374,467,719,13,532,849,412,340,387,419,285,179,116,479,449,776,328,487,847,684,182,138,456,307,532,894,926,853,96,786,677,785,453,313,876,363,229,372,203,689,901,886,821,102,93,342,46,227,812,810,114,235,432,944,948,927,712,976,631,529,727,742,221,889,650,713,464,930,319,792,958,96,569,975,145,800,899,603,858,453,994,293,854,542,375,663,532,688,441,983,202,985,627,595,286,15,6,302,724,514,367,342,562,554,478,128,361,617,414,572,4,477,476,750,155,712,580,259,69,406,176,334,364,542,406,87,485,491,721,430,4,885,848,172,862,263,311,142,60,484,827,971,19,29,730,352,924,253,543,112,139,635,606,532,971,911,775,805,156,186,539,166,112,984,684,906,337,964,790,795,697,357,168,184,626,137,159,872,727,648,233,37,564,95,276,473,161,953,876,711,497,345,823,764,60,666,438,704,914,37,621,451,989,986,857,66,985,412,385,962,775,918,915,232,131,300,761,214,866,441,380,418,344,627,993,961,0,636,315,563,979,592,620,68,79,309,469,22,70,723,656,517,182,312,116,391,291,249,144,549,973,391,595,405,230,71,935,193,856,910,731,490,955,426,67,620,187,764,881,974,944,697,805,723,394,640,733,263,853,662,172,931,16,583,92,377,343,119,607,987,693,302,86,392,127,31,397,551,25,913,696,80,546,685,885,198,437,850,604,82,266,27,588,655,223,305,498,640,314,347,822,285,520,387,875,69,702,278,345,169,749,383,49,530,582,431,423,209,3,889,668,157,34,794,792,773,801,419,195,913,215,603,405,113,218,600,57,689,500,631,124,435,411,160,176,844,674,73,294,366,572,103,188,783,169,847,193,920,360,577,193,434,678,623,961,454,568,297,299,846,275,856,954,152,75,693,207,647,852,841,912,664,567,388,692,3,832,449,709,178,233,202,310,908,596,642,367,480,827,575,895,993,465,924,436,450,426,360,420,795,420,529,696,820,278,364,662,620,924,521,704,980,209,279,819,238,155,815,722,500,902,898,521,913,460,63,225,983,647,868,614,935,77,967,309,655,206,85,65,742,225,24,230,816,6,252,171,515,881,62,637,657,486,523,100,767,135,224,287,9,13,79,570,645,959,578,832,136,112,180,739,820,997,324,315,997,902,435,130,748,746,200,843,41,459,142,186,520,66,521,499,105,444,784,570,946,696,714,817,292,890,277,831,268,248,225,302,358,489,605,391,541,182,445,816,830,359,960,272,705", +"661,623,754,491,492,422,85,889,917,115,551,821,290,791,631,482,672,836,591,820,908,988,49,448,679,656,831,414,246,902,233,466,164,6,411,206,46,963,234,740,597,441,543,298,878,921,453,539,863,380,184,619,165,532,729,344,399,433,473,170,481,888,937,445,773,479,523,600,922,782,849,885,66,900,687,584,412,970,118,992,854,161,854,838,463,552,642,508,228,107,793,377,876,463,166,210,191,286,884,964,217,407,313,369,250,164,283,379,601,100,150,230,952,114,278,748,814,154,569,547,446,39,743,643,341,622,101,965,244,183,834,441,678,445,319,450,36,986,226,702,496,549,852,871,13,166,498,97,184,228,551,801,860,823,666,78,562,42,333,960,150,763,950,241,290,110,170,160,687,278,614,554,103,249,314,84,557,543,963,190,397,317,806,390,197,702,606,720,820,378,85,535,414,482,778,173,803,404,607,950,395,127,969,865,467,413,12,891,790,73,670,868,471,886,884,251,137,88,638,438,335,319,233,33,118,717,757,997,329,461,822,121,63,25,807,110,251,583,326,127,36,735,236,82,558,153,366,706,119,443,737,54,949,696,214,201,818,249,17,244,721,714,118,383,266,636,674,754,366,187,298,141,849,608,344,355,444,824,93,866,302,676,353,494,858,674,51,811,850,716,733,598,505,48,645,727,492,25,56,920,585,701,333,243,364,790,233,758,83,147,196,582,244,989,950,662,728,433,245,208,282,990,241,175,915,45,395,176,157,682,517,973,900,446,204,897,557,992,724,611,403,483,629,258,763,523,299,800,987,892,613,495,396,826,287,917,304,443,372,457,730,677,178,161,715,936,487,381,489,914,584,403,260,326,755,944,172,149,118,645,595,169,14,304,513,784,470,814,138,152,162,315,585,747,594,749,167,159,142,371,55,914,140,926,846,214,407,893,982,640,857,994,453,741,710,663,342,855,149,396,885,135,625,61,936,245,492,239,456,246,111,957,366,852,938,722,591,908,341,341,470,330,317,9,558,945,87,278,171,471,132,54,637,318,536,209,111,979,995,438,667,270,944,875,515,652,297,446,208,441,338,97,960,360,174,810,174,379,190,662,831,806,312,98,595,461,721,844,591,379,675,82,619,201,464,246,71,885,385,289,264,484,106,240,347,176,827,35,423,802,286,300,291,531,147,870,114,471,939,706,970,993,931,896,666,43,897,727,387,562,519,941,421,993,320,843,486,883,81,687,530,337,528,397,595,819,4,467,775,108,761,816,394,502,195,206,625,232,374,277,291,90,503,204,111,730,280,205,210,752,439,600,306,118,333,80,94,408,521,622,313,947,562,3,686,588,154,571,897,913,342,519,164,466,391,150,188,873,758,161,816,58,169,317,585,383,730,140,10,537,198,691,551,651,185,43,236,585,543,72,70,241,872,957,291,846,173,921,850,541,19,775,448,827,983,989,818,544,33,229,84,141,173,473,970,70,713,826,868,245,349,640,964,984,379,147,589,683,58,556,439,200,926,950,11,91,693,760,32,7,976,605,339,199,327,944,636,0,158,113,573,413,295,163,494,656,488,626,329,145,530,221,392,224,687,110,259,508,901,595,821,282,267,313,852,328,498,110,482,949,276,724,739,656,260,494,39,857,455,912,528,569,272,762,578,583,934,19,148,697,645,75,151,193,328,846,258,6,71,126,485,272,512,231,940,688,533,615,58,907,592,10,888,261,694,794,523,31,623,427,432,674,952,563,863,485,595,913,826,936,808,458,419,755,327,172,124,882,662,598,943,223,843,126,496,571,232,572,663,972,805,314,324,272,272,230,121,661,996,257,3,931,295,684,582,303,436,214,197,991,349,843,71,250,982,663,575,472,524,338,344,483,370,377,589,166,433,764,587,145,911,78,544,736,352,347,798,730,745,208,511,663,759,515,955,904,712,642,928,743,343,935,135,307,302,989,674,789,979,114,531,515,58,818,321,195,434,962,469,924,945,4,790,923,733,92,999,214,304,312,637,202,556,57,742,121,620,684,924,624,491,457,42,264,597,856,51,732,559,379,48,639,182,584,90,837,35,849,157,259,771,376,246,380,186,975,158,877,984,945,728,295,804,233,291,747,895,823,63,675,505,923,96,254,298,672,60,563,835,942,829,698,538,374,730,861,816,468,264,430,16,193,872,291,504,528,637,403,78,460,462,313,218,516,816,955,674,130,995,566,351,989,177,333,258,296,55,498,518,579,432,638,311,585,883,799,337,960,85,2,910,961,678,828,915,332,90,181,363,242", +"77,546,622,668,220,513,738,901,134,522,656,166,783,347,525,571,879,24,709,265,587,14,787,276,15,611,296,749,780,829,329,108,602,929,840,633,336,729,670,986,935,670,829,996,303,908,996,785,431,428,607,904,868,84,11,626,989,985,640,74,108,293,646,461,848,513,693,354,829,940,49,852,691,687,134,651,820,925,553,644,202,796,633,844,514,548,618,408,210,147,576,400,60,84,522,280,556,889,24,512,99,489,749,895,266,337,760,671,136,382,664,119,549,246,996,323,485,548,441,299,378,100,830,321,651,791,509,945,831,190,644,370,323,242,201,960,455,822,859,52,678,880,759,535,653,779,628,62,637,16,65,463,394,405,151,554,113,351,96,697,839,429,480,278,197,107,947,321,501,54,76,180,748,146,955,218,453,672,40,836,488,224,321,999,668,503,550,105,150,422,692,465,868,512,336,500,613,469,35,78,40,867,163,549,959,356,745,138,807,647,829,377,869,544,756,748,498,306,209,689,919,649,216,820,259,866,782,720,760,121,527,716,181,396,160,652,663,737,183,354,466,127,430,772,874,854,441,885,650,523,345,882,759,337,512,389,572,719,101,275,424,675,969,84,229,138,685,762,70,299,736,774,817,535,306,959,297,753,941,596,84,53,206,448,137,245,212,770,826,11,461,592,14,716,524,944,741,465,7,549,614,664,805,786,398,952,412,463,971,537,680,544,959,196,471,724,871,994,558,475,980,378,894,46,437,483,394,545,58,970,5,871,223,323,587,99,244,322,290,666,897,538,815,723,588,941,724,588,519,943,563,535,626,149,508,327,804,192,820,481,25,715,737,273,670,599,589,143,570,257,121,497,235,265,388,499,988,57,571,110,978,296,467,95,967,100,430,124,531,920,148,802,242,995,13,163,24,117,954,925,568,279,648,76,992,147,214,250,915,541,506,882,495,896,7,860,718,189,300,423,766,762,804,687,109,929,272,966,476,253,39,677,799,392,870,138,266,180,56,454,84,664,899,345,200,230,515,215,648,649,853,791,637,526,730,572,974,148,907,849,475,18,881,182,740,642,538,525,855,113,751,994,2,11,81,677,754,31,249,658,117,843,370,961,775,770,346,712,802,758,869,538,372,314,710,926,92,252,363,205,772,106,918,431,580,192,408,294,13,723,557,705,810,816,456,634,710,651,16,114,454,35,452,88,242,368,381,373,450,353,851,982,857,935,732,502,888,687,882,155,220,212,259,106,705,442,27,159,415,630,71,572,480,844,53,59,866,64,979,451,969,44,999,346,702,822,949,262,44,711,61,944,312,393,226,836,463,764,596,660,862,59,24,951,363,430,691,327,392,818,752,912,835,18,637,670,119,519,181,228,906,389,732,216,106,62,330,274,631,853,180,973,543,971,707,576,455,953,568,932,135,660,492,287,654,769,41,360,431,528,882,268,875,316,1000,302,944,349,968,808,999,418,665,7,225,196,224,599,438,938,850,326,31,340,240,296,254,69,865,494,864,691,994,514,621,504,485,935,442,725,550,140,851,452,530,494,315,158,0,888,754,461,74,812,60,643,102,584,59,567,148,290,14,604,926,204,219,799,585,180,166,242,695,757,206,530,344,317,292,853,221,744,80,908,855,921,295,526,474,388,784,349,18,807,49,836,868,144,122,312,237,54,789,534,408,626,282,586,648,144,354,168,547,27,801,213,480,206,191,359,482,891,615,319,498,561,747,914,688,977,716,301,401,538,68,650,429,384,427,791,993,204,281,40,855,217,615,274,666,295,797,21,738,811,951,553,278,698,318,42,972,475,999,157,559,558,776,776,723,947,921,836,619,166,754,421,235,959,119,318,500,685,627,484,571,369,58,273,480,260,534,84,478,881,526,814,726,757,410,504,913,737,239,799,327,224,197,342,117,451,562,485,768,477,684,830,903,763,466,766,424,974,882,451,147,280,453,839,835,520,449,261,367,326,27,700,603,515,28,615,802,480,30,146,537,564,272,678,111,641,984,335,67,234,286,426,409,900,58,283,844,298,38,500,396,861,16,998,429,90,542,56,924,560,20,984,955,530,611,583,441,198,12,882,531,270,430,42,532,266,619,995,388,674,486,702,733,150,61,572,536,433,340,680,979,743,134,897,575,902,252,703,237,117,758,442,181,963,466,346,104,584,765,600,143,575,334,580,529,270,427,610,683,214,456,718,564,737,297,832,620,741,10,399,106,94,211,73,624,827,685,844,189,482,499,13,26,724,646,739,914,988,759,881,993,712,531,114,110,209", +"28,492,73,139,308,339,357,657,698,184,849,802,528,6,376,362,84,242,281,821,49,702,560,291,295,845,73,504,33,183,597,897,632,462,953,828,826,852,541,516,894,212,418,370,475,553,844,916,75,353,526,906,290,628,498,353,425,842,220,327,865,969,602,887,768,753,652,120,54,87,931,868,624,388,268,178,449,93,989,396,672,694,244,308,259,26,87,590,298,582,926,85,973,798,604,748,558,247,844,25,52,646,70,21,115,801,522,634,345,400,402,731,807,180,270,918,585,972,669,158,370,413,328,290,596,723,167,401,65,888,24,322,480,722,943,94,151,920,919,291,656,804,366,979,166,351,400,404,401,467,213,737,9,752,571,989,216,810,810,951,72,278,671,37,404,544,528,325,139,198,365,189,496,536,756,565,407,125,577,244,135,555,827,401,788,599,806,641,614,165,621,843,272,724,525,420,391,524,284,498,311,823,508,234,173,764,99,63,841,335,771,48,192,610,925,623,880,392,500,598,423,530,386,61,452,216,306,420,368,732,56,22,559,675,314,395,950,880,340,123,409,812,671,39,889,761,280,509,570,3,816,188,406,957,294,93,19,569,2,722,869,919,120,888,698,613,530,154,692,799,952,78,193,797,726,829,101,108,263,46,37,346,768,45,286,951,654,531,604,722,895,666,608,327,318,687,882,627,266,722,77,389,296,950,582,444,879,841,376,769,127,511,409,298,610,980,734,88,685,722,439,106,301,278,735,368,21,475,17,798,437,860,947,780,144,704,350,456,956,979,672,967,645,541,954,246,34,48,48,708,772,925,453,146,218,709,462,542,901,138,465,178,488,854,356,945,965,154,803,160,710,898,746,935,692,478,472,206,337,577,339,999,94,926,372,34,866,914,821,333,938,305,696,118,45,897,518,655,798,290,901,795,600,377,10,157,634,45,608,24,531,504,119,342,68,997,173,494,303,381,195,769,89,546,962,816,623,49,585,357,619,442,102,153,162,924,269,991,775,210,730,782,491,847,534,889,628,74,294,782,711,509,476,6,190,503,43,709,996,179,676,753,897,77,360,783,656,739,785,718,782,926,278,383,53,534,791,344,102,749,111,707,873,56,144,922,458,955,439,96,520,155,263,12,129,306,934,593,447,955,934,996,354,130,262,761,748,264,256,957,226,82,152,66,974,273,879,180,674,939,932,729,809,964,659,238,576,92,407,609,202,218,212,503,546,887,85,344,551,958,301,366,525,26,66,209,626,129,91,34,13,487,356,698,448,376,227,236,437,149,779,423,811,627,651,64,437,755,560,677,253,990,87,373,268,266,422,93,332,103,442,565,110,632,857,504,961,183,458,576,535,927,900,296,50,107,267,802,385,640,214,688,52,717,626,315,966,669,527,264,955,291,267,279,302,365,645,864,641,532,410,38,415,650,422,793,300,768,78,679,281,713,303,42,707,566,160,332,505,916,48,249,870,804,223,92,968,547,36,536,985,872,606,902,448,152,343,451,507,526,547,176,337,636,828,908,832,734,827,481,851,510,315,10,432,94,563,113,888,0,651,516,620,496,544,472,620,596,190,574,123,60,656,384,932,405,174,280,12,716,802,505,988,845,745,649,538,458,230,406,438,826,327,206,147,619,783,635,582,603,650,326,43,398,586,385,853,67,417,680,389,384,222,840,133,783,404,753,438,324,328,384,193,584,171,21,969,961,39,103,56,221,280,890,212,493,646,759,558,728,358,111,542,688,412,609,543,142,773,620,548,282,525,776,201,327,61,211,294,837,30,771,409,463,714,95,955,982,33,379,37,794,447,159,100,30,91,945,60,121,497,401,304,208,766,262,684,142,495,595,819,387,894,795,888,469,742,958,721,554,767,166,978,218,646,598,724,756,699,501,592,855,596,396,716,786,656,78,726,883,938,688,150,18,598,51,531,782,45,168,25,767,396,555,949,808,72,251,862,811,718,236,420,959,700,924,423,311,329,117,116,195,273,630,793,36,517,347,798,826,900,347,937,246,630,548,180,445,281,501,530,357,937,132,9,344,805,975,376,870,239,636,702,143,34,935,724,845,677,156,800,307,170,184,277,216,42,389,944,223,152,147,211,214,435,701,198,293,432,212,377,177,731,848,157,193,193,973,114,415,771,28,744,570,595,781,99,220,498,466,97,979,534,870,687,617,474,819,818,95,316,327,713,571,694,961,437,896,183,651,625,867,135,209,674,532,827,346,331,848,432,952,552,17,666,502,233,958,558,348,645,58,635,458,11,675,791,478,259,343", +"961,794,622,276,770,453,148,257,672,166,903,766,473,958,504,908,342,552,454,566,696,745,494,32,95,454,994,320,119,374,3,731,597,462,176,895,320,169,136,381,592,24,323,740,827,781,882,287,441,467,945,447,483,469,253,853,824,410,670,171,649,983,847,630,865,302,395,251,976,949,901,807,315,123,334,906,589,159,7,553,425,416,304,739,198,812,879,531,366,901,74,776,683,704,619,192,935,422,595,887,848,601,837,505,819,358,789,621,683,305,671,144,896,911,745,852,250,314,641,728,779,816,134,906,693,949,94,336,761,784,417,125,948,218,860,147,279,228,402,880,528,300,200,254,139,906,414,454,349,831,958,326,537,822,744,607,175,716,275,600,938,878,370,354,25,837,48,464,318,491,719,494,560,251,919,886,361,213,690,594,112,443,362,522,988,527,760,853,759,630,414,210,773,761,490,481,941,408,993,841,621,293,132,167,365,985,444,352,159,386,97,950,870,365,743,563,972,394,768,671,775,501,436,190,928,603,681,417,559,226,253,891,72,526,488,1,801,323,213,808,210,183,820,356,799,79,384,350,871,222,241,518,662,528,264,838,627,689,756,616,935,417,95,696,384,292,684,715,56,249,730,552,970,280,47,106,878,740,304,974,369,134,868,134,242,679,56,948,224,751,754,779,459,767,929,576,941,194,207,629,704,42,184,494,729,101,267,258,622,246,883,122,119,419,355,299,852,908,108,613,87,145,220,619,678,742,65,800,312,776,38,461,712,455,283,739,335,739,578,847,792,698,193,343,381,206,661,126,713,946,9,283,784,723,684,505,35,837,551,785,838,904,33,773,423,58,28,646,880,798,937,467,142,126,412,49,100,573,782,674,557,645,953,647,437,624,814,566,689,782,831,794,379,838,971,797,981,40,735,140,536,682,392,558,217,526,50,691,518,599,928,718,443,720,23,171,222,964,840,620,464,650,113,220,939,289,618,616,262,763,173,638,259,188,862,707,669,726,738,119,297,349,900,321,692,529,590,8,786,847,635,555,493,410,932,126,39,961,534,668,804,639,273,677,175,329,352,181,716,671,913,156,347,62,518,267,341,692,363,567,578,249,366,296,673,299,221,228,52,161,816,31,781,569,424,410,498,479,10,756,14,454,493,745,341,100,472,445,362,976,919,12,497,739,288,610,7,763,364,404,942,209,998,722,877,576,954,877,84,100,426,983,75,883,627,972,116,393,461,132,701,597,567,770,954,565,917,758,392,994,378,629,520,736,941,184,588,112,27,166,838,859,701,989,302,904,733,281,98,29,931,802,59,120,132,461,759,806,439,871,957,810,779,893,972,361,759,185,123,92,759,804,623,352,870,509,261,711,132,340,503,216,584,495,44,368,273,947,714,925,56,164,857,394,593,791,456,476,22,372,548,827,518,475,278,851,123,929,468,228,642,17,420,11,882,119,678,488,448,51,24,29,831,793,220,436,954,735,823,261,918,371,119,676,726,288,974,18,45,401,833,530,236,565,243,249,104,815,569,383,513,686,372,780,605,469,979,573,754,651,0,741,166,399,176,827,875,268,714,261,484,983,984,165,243,574,246,900,831,957,815,271,538,953,664,937,608,230,679,914,341,440,161,244,800,859,864,462,969,307,957,124,243,10,854,317,678,341,12,517,990,567,251,739,255,79,959,880,393,439,109,9,812,464,580,805,528,893,458,594,160,559,444,578,718,44,457,515,364,917,273,197,410,751,808,643,585,178,905,90,995,11,449,593,101,476,834,338,440,617,140,972,422,309,241,356,114,815,600,766,929,367,710,299,690,825,150,510,918,605,350,825,530,590,646,711,122,123,640,729,786,489,664,718,242,807,997,96,527,642,657,225,771,364,293,205,798,902,881,365,333,170,918,844,771,484,529,728,546,914,26,622,163,139,597,43,654,38,769,206,268,609,946,775,513,220,658,99,132,380,27,458,934,304,503,616,570,910,660,733,945,698,271,339,154,469,31,161,154,690,687,103,904,797,947,236,283,571,110,594,968,99,56,925,493,244,944,320,638,838,691,870,153,65,299,306,66,576,366,466,941,642,629,378,712,507,177,984,94,463,273,394,117,152,891,911,162,899,890,863,123,916,735,381,618,546,94,680,990,306,107,102,882,744,366,995,476,235,155,508,769,123,720,786,848,250,679,785,655,899,890,942,673,798,951,132,810,396,386,768,479,314,536,147,940,362,922,869,767,162,301,774,286,69,52,259,341,683,3,665,428,80,886,454,517,364,825,224,417,964", +"222,179,190,678,832,676,343,545,173,873,467,320,497,627,888,292,438,778,332,988,710,309,530,980,820,294,485,229,444,364,721,206,654,354,73,7,219,385,509,373,404,157,677,662,613,771,319,490,703,1000,476,129,491,94,403,173,258,447,726,672,878,977,873,462,683,486,740,396,89,934,165,409,891,128,951,439,795,31,443,557,279,36,803,792,510,264,325,696,343,115,963,12,677,757,785,413,872,607,824,415,893,154,297,712,377,837,759,666,612,328,647,246,943,694,426,345,97,374,295,773,641,685,955,919,383,445,898,229,750,38,48,752,346,642,27,958,832,346,631,992,124,491,977,374,918,310,693,578,644,47,732,211,128,636,570,848,262,599,646,878,485,657,878,6,248,19,839,795,347,470,823,233,862,142,692,842,513,587,417,758,729,933,424,842,966,974,551,5,427,332,822,476,752,15,224,66,345,212,429,294,911,528,531,742,436,857,77,585,903,225,147,517,430,697,99,679,810,426,853,99,762,148,564,217,166,557,444,828,860,115,641,535,460,745,901,155,751,876,437,178,926,883,909,530,34,666,121,827,666,137,735,964,195,646,885,883,562,228,216,874,310,903,91,812,955,411,443,68,479,974,953,224,829,634,325,392,165,407,71,771,355,398,21,535,692,621,410,781,555,744,332,920,552,681,717,425,860,27,601,537,746,837,343,884,623,626,589,484,126,803,947,142,704,474,306,319,420,395,388,767,785,526,76,138,974,276,412,315,551,54,622,69,217,390,716,699,699,324,757,611,704,46,596,486,912,63,812,153,112,199,49,463,280,232,858,180,637,425,583,199,591,76,991,8,17,327,141,23,870,965,295,206,486,94,239,444,520,744,512,180,496,147,704,52,244,74,855,717,636,607,853,403,742,184,452,931,798,592,502,258,186,187,132,579,531,687,278,929,358,693,985,462,211,632,101,651,478,460,508,409,937,104,359,340,456,24,732,41,629,686,511,46,479,298,285,611,736,834,536,724,493,5,607,195,363,767,295,56,803,939,985,62,275,66,138,931,792,943,826,396,441,454,817,520,980,512,867,683,867,412,611,706,72,666,345,885,88,62,362,100,767,793,379,126,60,245,566,132,373,597,985,195,314,595,393,195,793,487,121,208,747,92,284,51,963,189,48,292,943,602,756,106,118,904,13,617,346,337,238,589,715,958,113,808,692,190,423,134,382,251,820,748,430,566,642,188,373,182,107,345,343,475,75,965,68,721,743,558,586,654,821,29,937,874,942,639,577,444,519,303,855,654,3,494,940,521,353,622,564,285,469,851,810,933,81,881,295,62,64,536,994,96,558,701,736,882,131,60,783,444,564,748,41,678,762,789,310,750,797,916,872,414,480,690,37,614,698,949,175,574,632,929,573,324,299,177,366,275,100,446,607,399,13,626,623,999,401,459,839,893,958,901,120,758,117,809,296,654,459,75,493,873,648,662,862,670,308,517,716,580,820,756,614,664,858,4,836,630,221,813,959,537,191,266,983,9,875,74,849,837,582,125,219,664,823,721,592,413,461,516,741,0,660,127,33,35,173,815,839,711,513,806,628,933,427,293,984,208,195,118,90,625,636,933,604,104,231,493,442,791,211,484,740,668,133,399,997,242,164,949,276,520,827,290,514,175,62,154,190,36,647,622,453,729,407,120,863,744,476,410,591,927,935,498,605,808,754,97,499,266,956,873,798,309,515,354,442,97,833,409,197,956,340,960,716,890,12,341,137,251,480,293,81,899,700,874,898,763,222,823,742,862,281,354,541,459,239,449,270,652,376,171,507,778,126,496,426,88,306,180,473,819,554,239,537,78,808,139,159,69,133,992,839,639,466,935,437,217,450,515,258,671,612,100,518,202,858,450,456,382,982,367,921,551,149,243,633,427,230,733,132,10,797,549,383,29,450,89,429,850,272,82,545,542,749,936,348,778,721,173,285,595,889,314,239,172,676,948,733,243,715,626,785,462,264,88,142,734,653,401,558,365,484,81,537,960,534,114,221,262,837,631,689,593,461,350,279,765,25,182,679,593,845,868,485,524,90,75,805,644,204,5,152,658,982,652,712,883,756,578,969,400,942,874,378,917,7,473,701,200,560,287,276,122,506,911,198,689,712,593,351,966,435,946,782,993,992,449,548,718,255,923,931,700,283,455,782,191,534,531,148,632,163,291,137,978,718,738,282,629,963,986,445,850,57,602,839,946,825,436,728,784,847,649,55,547,854,855,195,998,661,1,153,875,181,682,772,138,516,929", +"953,487,271,673,239,262,992,813,629,566,175,330,432,293,435,860,351,487,660,460,250,975,348,667,90,12,859,335,710,527,279,148,128,741,13,57,765,398,700,702,582,969,96,706,825,148,639,991,669,352,977,734,795,566,46,555,317,598,826,374,191,696,564,944,939,396,788,742,949,365,40,529,363,207,48,32,608,552,184,237,530,239,472,925,294,708,724,261,554,128,622,85,159,565,985,55,160,931,499,303,112,667,539,737,477,232,853,363,530,276,421,482,830,362,662,599,553,199,354,10,718,318,854,584,181,960,237,337,802,696,455,415,639,588,42,72,856,412,662,350,883,929,767,610,594,994,294,436,367,802,248,331,836,727,553,638,844,370,783,60,624,253,507,391,683,33,138,381,830,902,110,622,263,98,409,496,737,928,732,625,596,56,341,261,140,767,431,377,993,979,735,109,784,570,823,892,279,451,520,805,604,749,349,494,787,197,858,530,988,216,902,958,907,598,120,573,294,744,701,640,47,515,870,174,732,167,710,292,63,665,978,179,228,184,266,209,99,640,679,167,903,304,545,200,586,377,394,481,907,692,966,107,210,375,594,277,501,959,447,747,708,677,390,94,556,299,560,713,374,638,605,778,423,549,940,95,218,33,932,565,975,221,797,915,574,749,50,1000,426,442,901,466,14,844,214,772,13,122,307,621,12,867,75,343,85,715,95,485,841,134,870,953,80,582,353,645,366,803,317,582,883,300,877,39,86,739,241,454,840,867,907,954,770,102,739,415,923,7,993,516,663,326,418,248,493,242,465,991,748,337,310,133,512,440,791,257,929,611,16,186,584,744,126,149,254,681,655,752,699,999,656,98,25,235,847,242,522,745,914,514,973,16,333,330,280,471,519,322,856,364,222,21,616,482,539,740,658,740,89,959,144,516,519,37,530,66,371,116,728,524,783,781,34,729,915,994,831,312,318,781,387,517,418,772,659,791,677,529,372,21,913,985,614,980,968,586,979,217,256,184,780,31,559,680,684,261,664,425,293,952,150,692,223,905,246,346,848,250,186,343,469,721,486,88,245,106,265,412,561,551,87,278,171,672,778,385,431,510,489,268,512,895,106,581,671,824,526,914,574,735,776,208,381,163,10,463,194,736,937,514,333,309,282,348,30,2,152,27,526,686,781,932,336,483,85,471,134,544,209,693,768,837,572,959,341,878,871,584,298,271,236,366,286,29,56,462,232,260,983,63,728,847,129,738,822,748,668,856,326,142,839,36,75,709,411,630,132,26,227,501,534,497,198,907,149,442,411,860,175,501,462,24,452,937,575,33,697,644,941,190,24,230,723,213,361,358,504,538,479,952,126,445,13,655,356,756,341,248,225,119,826,713,88,309,77,945,39,417,820,859,744,498,340,547,73,984,725,547,98,475,236,810,963,766,630,889,60,792,628,4,91,493,1,42,20,838,191,281,788,491,170,166,599,792,529,658,400,745,447,219,789,82,345,841,702,807,939,838,546,765,287,470,944,90,760,612,617,26,138,98,583,38,575,353,25,644,620,295,74,620,166,660,0,354,394,679,163,130,341,415,736,942,465,768,388,711,892,413,127,158,797,185,89,736,588,803,190,898,94,96,683,618,470,264,612,649,244,821,441,708,208,588,891,758,723,927,949,20,23,597,704,339,298,338,161,378,217,660,956,517,210,709,251,882,874,551,823,254,859,262,203,689,374,909,257,590,219,418,695,120,38,169,349,814,81,939,71,676,314,584,355,743,951,51,281,464,738,562,58,169,29,552,318,173,657,338,602,156,117,758,44,544,602,543,974,908,317,865,544,806,342,342,505,477,387,596,811,496,84,819,758,4,258,912,70,383,889,305,159,240,739,699,331,756,35,596,594,493,483,437,668,528,36,864,59,146,38,21,949,359,945,313,138,821,552,415,458,232,172,991,157,800,706,859,113,292,929,658,637,337,482,832,656,243,150,949,397,693,273,711,94,94,636,253,862,915,616,49,981,931,341,625,49,212,925,636,963,875,984,332,284,734,404,515,626,943,251,478,853,477,263,488,181,502,143,977,654,181,190,240,18,865,737,974,614,689,451,547,835,581,115,986,140,386,26,225,247,820,324,645,277,729,1000,890,605,319,146,227,534,841,927,528,752,979,752,459,683,296,650,589,374,577,160,102,879,833,317,920,819,432,801,721,873,488,188,275,714,227,18,223,86,443,664,527,475,260,435,747,86,877,70,26,940,913,110,988,851,423,525,755,250,989,750,502,272,591,101,155,523,803", +"604,555,412,94,828,313,903,949,359,122,883,449,853,17,612,577,217,22,947,84,303,6,120,485,68,393,654,234,610,80,397,448,820,621,74,957,28,120,375,551,471,20,516,736,564,295,635,100,318,309,741,411,912,821,390,399,71,387,716,711,707,643,75,118,793,453,3,137,55,316,969,934,971,994,962,389,916,697,416,962,502,173,63,263,601,406,271,647,868,829,302,69,456,771,402,64,956,18,282,650,190,757,208,154,985,851,932,875,536,984,802,879,631,561,87,234,530,719,997,262,636,642,70,963,735,34,353,181,239,303,407,349,223,6,249,174,21,803,612,897,672,150,554,250,448,503,146,675,14,394,120,300,327,44,799,840,76,342,654,383,719,905,231,783,308,478,506,48,203,729,106,578,304,234,983,920,737,223,749,714,303,757,853,957,759,73,941,272,521,505,419,195,720,153,787,886,536,472,571,298,565,451,87,788,189,954,852,305,803,19,353,834,394,70,142,451,863,943,2,358,819,367,690,231,555,701,20,48,884,250,938,636,946,389,449,439,323,70,428,583,543,235,399,606,248,337,67,681,713,319,867,589,458,568,334,589,473,247,492,686,571,826,495,605,155,467,643,478,810,723,17,18,606,962,693,201,635,902,811,358,440,901,954,531,964,850,454,443,429,762,483,4,384,751,997,266,631,312,461,677,181,160,293,384,811,965,214,278,714,749,724,483,552,749,670,354,545,885,180,591,478,789,639,466,333,40,986,971,817,891,391,4,600,311,427,983,195,660,242,194,226,262,42,182,347,103,284,288,55,78,860,542,915,622,23,454,860,275,781,691,37,638,160,379,35,134,241,325,233,5,440,766,517,272,865,5,103,525,896,182,113,484,347,824,595,559,666,624,389,321,758,196,161,785,54,69,537,322,905,950,696,352,82,138,474,104,708,495,238,75,606,781,631,260,267,448,391,36,39,97,878,449,765,898,539,718,674,508,322,540,807,257,289,714,894,960,682,290,241,144,560,374,752,818,280,354,940,669,679,444,771,85,40,12,781,638,739,566,39,611,129,424,805,554,572,840,385,415,66,711,372,257,264,57,953,446,605,635,487,734,421,552,760,904,34,526,973,231,172,444,589,418,916,483,394,351,45,661,658,586,886,758,648,724,994,974,973,347,603,593,652,650,697,401,18,693,613,762,150,816,863,142,853,230,740,41,103,224,365,275,841,696,655,560,491,907,613,495,570,394,452,673,720,494,224,126,458,676,663,116,616,368,807,352,308,646,61,696,261,355,837,776,715,898,376,102,783,823,11,292,585,871,249,427,597,859,916,792,503,939,645,386,422,723,103,470,190,28,130,172,274,399,656,240,537,293,393,144,53,371,249,796,883,771,528,538,508,183,703,322,124,917,558,487,925,881,757,205,67,139,223,268,624,249,420,754,997,169,513,328,813,112,736,379,250,650,340,827,160,268,467,165,75,919,268,654,178,554,663,451,602,930,458,482,718,354,637,128,392,489,784,920,913,812,974,972,819,506,32,455,329,226,898,660,749,896,68,163,812,496,399,127,354,0,871,732,190,651,707,374,543,991,165,613,875,352,20,365,295,416,241,468,689,48,244,642,847,991,243,512,128,863,611,417,163,237,348,186,910,594,531,164,372,120,739,997,644,180,166,866,840,362,614,30,429,697,200,494,918,782,29,218,458,478,846,688,558,133,713,343,161,134,873,806,585,357,782,130,108,489,788,223,305,690,316,803,58,821,435,993,693,22,978,761,49,484,419,299,961,242,85,497,568,57,425,341,91,7,457,599,810,136,730,268,233,986,994,808,988,950,658,879,239,981,739,12,268,617,657,154,238,908,488,719,507,435,731,109,324,243,128,34,912,785,882,417,16,506,510,273,736,865,247,457,592,500,788,589,571,394,882,164,573,18,900,820,626,332,400,796,792,647,864,176,169,483,411,259,617,345,19,309,411,667,592,268,594,607,721,739,280,73,184,705,512,241,814,344,578,107,28,756,490,247,320,379,732,210,462,6,394,655,103,482,992,591,513,822,44,242,585,27,997,654,605,661,287,155,38,451,151,880,198,351,748,107,852,988,806,69,240,918,862,401,178,426,250,685,82,237,605,232,947,764,113,318,513,655,244,372,149,559,191,315,867,25,724,785,562,528,141,572,526,532,384,539,719,877,948,356,45,441,843,839,565,849,923,67,698,832,584,760,585,355,220,720,134,197,951,798,722,880,652,330,46,289,746,942,889,857,680,282,903,229,636,5,254,469,507,292", +"611,710,275,764,764,924,916,616,506,490,697,197,146,672,155,532,942,288,296,859,396,275,322,377,112,562,312,1,28,503,262,849,185,481,31,203,502,595,441,60,201,993,856,312,193,613,568,229,917,698,629,178,244,919,230,105,458,257,320,640,352,155,414,211,155,649,986,397,276,601,166,251,697,150,781,691,113,553,783,867,210,156,84,312,64,998,905,364,925,908,716,222,94,859,41,565,94,93,131,366,57,499,363,552,426,818,871,721,557,648,389,846,246,365,333,577,81,520,518,625,936,237,220,247,232,168,541,259,772,940,221,583,482,497,657,420,555,67,40,232,984,762,47,136,24,409,711,88,50,396,196,565,727,609,2,579,661,855,889,475,139,767,537,796,876,225,629,13,505,235,437,725,15,128,5,400,76,105,307,352,836,825,209,488,932,21,302,926,387,651,775,185,57,514,491,841,986,131,165,601,968,442,83,94,947,935,762,368,536,178,312,957,531,542,667,313,989,549,712,686,529,521,454,727,831,313,14,218,902,780,410,434,464,659,611,638,38,101,371,834,653,241,131,600,349,697,336,769,90,184,709,555,480,369,726,39,618,285,993,627,15,681,382,445,657,822,864,606,870,101,623,413,927,948,203,53,955,400,713,410,930,549,761,649,451,956,219,993,16,887,78,497,931,507,793,974,95,853,171,749,416,701,236,431,374,48,144,642,156,250,418,735,24,739,483,235,990,407,46,65,560,791,289,102,487,560,950,589,321,63,375,357,913,768,124,760,166,794,632,654,936,678,618,12,650,693,545,19,680,12,895,878,137,524,942,963,533,972,681,598,407,415,815,100,691,24,910,718,351,771,703,583,398,511,212,297,597,916,636,917,889,527,532,509,787,450,365,956,560,28,30,683,677,5,412,842,867,432,723,978,550,228,229,588,823,957,69,155,641,245,904,876,723,345,140,855,456,970,96,5,338,223,708,43,473,279,290,377,26,652,182,795,156,529,556,649,116,501,688,492,161,12,871,805,948,414,559,990,573,604,549,826,216,947,677,613,816,123,194,579,668,832,659,226,176,326,638,2,523,670,421,231,722,399,860,70,958,774,967,928,813,282,491,268,142,917,45,946,849,739,881,330,280,207,125,141,685,941,427,544,650,805,751,22,606,297,681,718,474,864,384,539,668,624,611,496,574,406,425,153,996,962,96,86,118,796,297,330,104,880,820,729,629,8,223,343,84,414,526,427,732,757,843,719,229,874,674,56,832,612,126,239,63,552,257,442,39,990,443,591,521,599,379,262,628,631,467,563,874,46,685,598,298,630,58,318,708,101,856,154,28,583,257,889,298,868,576,327,142,913,397,453,347,367,743,901,963,394,51,708,703,996,814,255,539,143,571,85,675,955,9,711,846,596,615,927,772,86,48,619,405,434,455,508,999,375,429,315,102,265,47,160,824,869,790,419,926,581,415,157,518,239,393,228,185,483,747,885,422,146,556,689,582,810,220,55,612,57,900,523,285,968,69,628,504,332,127,91,266,406,822,614,360,314,716,841,79,494,60,544,176,33,394,871,0,234,445,156,134,486,742,833,331,978,503,557,369,2,621,220,377,528,154,269,53,72,749,68,532,478,438,412,667,881,931,577,730,787,678,619,868,16,805,247,244,888,326,369,200,208,436,148,878,639,987,47,965,343,225,110,978,169,954,810,667,413,209,409,427,906,736,549,70,776,839,97,394,836,521,784,577,991,367,888,464,796,723,705,8,608,529,760,974,859,521,522,262,99,93,110,4,812,104,199,962,985,706,464,839,265,982,478,855,362,135,841,862,28,497,917,113,678,709,46,736,907,756,270,510,830,615,439,2,742,824,647,767,751,254,498,832,471,712,460,757,485,646,551,210,222,968,897,642,682,989,15,329,464,777,295,355,285,954,743,986,192,670,636,299,898,553,869,827,940,215,245,778,714,426,158,756,703,699,395,832,194,587,92,713,928,668,237,59,764,293,418,716,255,208,721,285,5,64,43,824,211,256,276,560,437,739,307,675,7,978,135,564,116,135,309,447,816,285,470,421,262,737,206,738,79,819,730,572,304,286,213,454,156,240,46,919,67,809,758,876,198,664,956,686,633,820,72,670,734,506,86,677,715,24,884,828,657,754,468,755,15,268,17,330,997,25,188,593,16,533,676,101,418,979,716,618,951,197,447,535,911,471,268,951,384,566,898,239,976,776,593,404,756,765,452,556,172,110,747,136,187,244,418,879,535,677,263,613,956,271,736,274,547,691,506", +"111,215,427,731,273,444,982,465,410,64,274,832,909,771,147,685,273,773,17,345,40,706,961,884,246,117,414,850,366,938,438,507,737,902,911,321,260,408,622,167,786,29,46,728,60,967,911,83,762,359,2,7,520,875,979,989,914,322,419,776,214,992,289,337,743,444,597,909,197,709,258,645,817,161,140,152,321,454,199,868,231,178,5,938,582,418,512,579,324,207,295,525,657,578,278,795,865,112,288,807,597,697,714,16,796,683,950,548,35,160,220,555,700,357,464,931,410,901,55,687,424,294,329,507,942,822,985,329,913,513,419,689,387,781,968,635,513,53,362,213,672,100,464,248,863,232,384,474,885,666,930,370,677,727,171,360,379,199,177,511,246,174,514,354,54,763,760,808,163,788,569,781,861,443,794,417,792,452,708,565,741,735,200,802,539,696,409,680,204,520,130,96,369,388,370,217,775,77,934,564,489,141,976,835,962,207,845,570,508,594,417,945,604,712,111,430,111,709,599,299,341,445,63,662,518,64,369,933,153,571,623,155,203,554,92,584,473,4,87,732,493,638,622,134,143,10,137,317,37,316,286,794,188,408,226,937,132,555,374,903,682,951,914,959,581,403,850,173,766,69,7,191,784,175,772,756,523,932,216,877,514,216,958,352,308,101,931,281,900,899,661,961,714,845,340,895,386,868,865,451,687,841,276,200,944,522,784,41,498,914,145,353,537,423,341,628,597,372,863,837,754,167,60,280,188,360,388,916,510,710,252,175,236,130,792,948,348,382,431,895,99,59,434,317,742,487,953,789,100,943,510,993,546,55,413,67,377,977,435,864,806,577,741,232,191,244,652,596,858,187,421,549,249,99,858,293,426,457,172,34,381,259,899,928,550,684,568,855,757,372,310,871,1,679,353,99,474,118,717,297,599,942,208,207,42,108,42,762,210,387,154,858,765,677,455,685,912,795,86,78,113,732,968,956,355,69,902,956,31,594,740,277,922,192,26,428,388,520,196,977,867,853,82,81,972,310,486,341,115,824,192,194,857,362,367,713,555,973,149,885,311,735,345,244,504,949,877,368,26,62,244,662,630,803,425,268,487,54,111,567,433,894,363,881,970,888,659,257,218,824,272,666,588,792,62,990,291,419,260,340,748,638,968,576,638,488,692,909,506,95,958,509,682,392,233,109,941,420,625,418,753,279,355,562,490,412,312,521,98,890,387,220,369,567,469,852,529,180,872,221,423,878,755,245,225,122,321,64,836,575,419,647,464,263,777,942,590,106,757,669,80,244,55,508,412,274,506,24,788,57,623,903,559,605,554,859,236,913,494,45,488,452,218,219,210,170,478,577,748,604,244,256,755,402,771,67,401,172,976,70,342,117,243,316,802,331,881,3,318,957,390,486,125,698,738,721,491,968,194,653,609,858,9,866,300,737,789,720,140,388,104,672,695,792,664,236,68,177,87,422,426,963,914,821,370,281,247,510,195,135,824,716,82,203,746,312,822,768,505,412,211,295,571,894,736,926,956,395,928,880,29,705,512,507,782,923,309,656,643,472,827,35,679,732,234,0,722,648,156,771,224,300,317,801,960,117,791,921,383,833,283,221,641,979,796,469,396,475,595,808,202,546,702,99,157,735,597,244,484,554,361,478,1,519,386,834,191,561,269,442,230,166,248,971,788,469,388,234,505,222,509,150,856,719,457,583,130,147,504,298,810,473,757,42,760,819,437,180,974,540,830,776,149,283,42,106,491,821,203,383,249,809,593,482,625,65,729,198,861,59,855,365,416,377,47,125,351,480,855,676,800,873,158,995,461,338,172,918,849,855,775,809,761,371,813,947,554,260,720,387,78,431,39,358,428,16,114,511,792,121,73,525,172,572,46,310,366,967,157,665,490,378,851,936,864,443,14,859,123,133,361,871,262,80,629,857,364,924,273,741,281,363,63,967,583,72,374,749,531,930,401,220,850,113,856,325,877,602,591,790,281,989,82,36,653,206,858,139,87,440,784,240,373,359,885,952,281,514,680,306,547,916,252,713,217,316,218,6,818,105,571,221,192,4,674,347,902,260,298,975,105,130,20,193,785,50,299,668,627,506,544,129,888,511,398,753,84,987,871,482,93,130,996,240,627,238,946,91,556,288,794,398,875,665,791,361,470,525,592,916,624,898,522,788,606,311,695,501,396,108,292,945,216,521,69,843,710,250,743,198,702,652,29,365,596,978,595,437,382,437,528,429,630,746,842,359,980,677,596,755,793,785,751,652,322,335,876,948,728,117", +"296,94,398,778,149,115,428,710,86,682,306,226,192,159,401,844,315,870,926,117,10,165,269,40,731,90,386,518,156,970,181,26,273,942,893,944,446,619,508,20,918,690,416,967,601,801,520,814,502,766,366,554,949,588,881,450,327,653,136,875,43,721,759,587,673,324,565,545,79,920,837,749,52,783,265,347,992,943,94,136,620,307,181,367,893,968,885,662,480,688,530,762,486,286,132,985,827,939,932,368,718,70,115,190,643,65,533,70,621,110,309,899,863,639,139,685,619,549,218,260,103,434,45,309,23,231,691,65,279,589,74,774,161,261,846,556,707,927,281,64,71,73,508,710,365,78,951,354,87,71,409,383,912,246,714,470,187,733,85,206,14,529,395,840,104,508,419,583,182,491,982,594,815,766,880,842,23,412,523,648,562,192,205,721,843,221,741,176,9,965,953,859,108,721,40,32,7,262,636,333,799,840,410,205,71,913,807,883,734,612,703,162,62,672,622,976,593,830,290,462,644,697,109,29,364,753,466,126,288,840,325,481,292,700,525,646,320,94,587,860,245,252,610,212,996,503,506,297,581,34,959,759,393,47,933,161,164,246,226,269,855,964,81,220,128,569,804,35,247,585,247,649,497,216,489,733,721,675,292,193,340,873,881,643,587,387,880,508,785,606,928,12,480,789,102,481,260,786,690,606,112,329,17,259,789,342,302,172,266,612,215,658,809,382,252,916,643,323,979,472,200,686,894,231,508,258,663,736,469,3,794,527,261,560,457,262,139,229,167,471,568,998,610,102,471,225,662,301,333,129,103,974,325,857,127,18,429,949,15,901,298,933,604,890,743,71,591,74,263,966,974,800,151,603,496,257,133,349,677,79,624,754,615,886,507,185,964,588,855,511,715,575,587,734,487,746,982,833,680,808,682,897,996,840,165,266,195,293,850,46,599,35,790,529,850,671,994,635,242,991,511,561,924,130,148,918,248,118,81,392,473,661,44,753,172,858,781,310,349,461,186,882,977,364,601,807,784,444,511,125,652,115,553,605,289,431,584,512,85,395,379,221,830,27,678,731,204,438,406,470,429,86,170,72,868,434,155,631,723,850,542,983,280,960,931,202,683,860,69,739,396,688,592,848,465,444,813,614,466,824,729,526,547,88,291,30,20,218,869,141,828,512,330,442,479,382,573,201,633,889,249,855,824,414,23,928,177,294,15,57,486,302,161,785,373,206,196,816,360,916,948,293,486,992,659,24,181,282,244,152,737,722,824,454,817,30,459,730,11,886,899,593,553,411,895,692,73,846,275,846,152,145,270,207,780,175,421,19,407,306,129,887,378,503,654,581,236,621,566,332,609,920,632,620,103,890,781,277,593,956,100,510,636,440,776,996,2,543,528,565,590,81,78,432,165,516,539,328,636,659,8,790,529,778,729,210,165,764,684,975,993,289,565,781,337,417,966,647,74,308,720,871,766,264,664,984,366,14,976,451,407,732,499,281,400,295,722,712,424,901,322,6,609,202,343,848,513,42,244,682,988,969,824,29,640,647,469,488,102,620,875,173,163,190,445,722,0,571,197,419,755,493,192,774,964,846,138,140,173,247,164,609,223,906,544,688,582,612,803,517,251,884,78,112,627,709,441,724,352,165,449,9,640,585,226,58,203,564,932,470,754,76,224,945,343,564,430,262,146,876,296,581,596,674,352,638,133,491,179,157,225,460,755,668,565,276,312,130,575,416,140,308,500,867,929,143,634,853,77,641,590,328,797,172,292,552,855,430,494,445,751,278,449,825,420,649,153,974,552,602,169,326,876,44,802,588,35,953,566,159,587,910,23,133,164,993,202,656,752,155,4,29,151,850,841,869,875,236,636,434,320,170,79,438,546,794,515,11,959,902,236,710,932,453,273,557,750,977,570,55,732,922,643,598,312,838,753,914,442,650,933,224,954,51,835,820,381,162,956,840,898,736,606,496,216,776,989,177,424,282,491,270,986,670,656,708,951,917,664,611,983,467,250,582,403,339,428,927,460,869,378,401,592,100,756,857,957,560,958,533,219,640,19,297,252,111,492,866,638,747,429,704,928,21,294,811,931,238,114,796,545,144,780,181,635,407,505,881,992,119,637,136,55,330,550,523,87,37,89,758,633,38,861,132,276,589,484,335,14,276,233,118,976,236,24,785,778,229,988,977,319,60,586,219,811,545,482,719,503,367,855,576,527,41,748,439,696,6,863,345,725,892,856,593,619,489,162,51,50,787,961,231,271,711,700,986,876,261,482,254", +"784,707,206,196,191,895,271,828,648,794,415,377,965,788,993,409,128,339,182,890,933,461,437,896,598,258,226,286,391,149,218,656,726,941,521,720,518,471,146,279,951,553,335,567,644,39,260,844,887,260,623,774,247,825,260,231,24,433,436,832,883,994,930,333,970,613,422,760,717,650,597,97,690,405,681,737,919,243,632,584,215,405,98,98,7,859,812,619,352,518,270,74,449,138,8,808,183,66,862,19,97,208,974,834,457,510,622,997,609,208,403,966,612,981,516,56,822,141,583,187,925,384,481,365,491,42,803,59,605,791,547,952,720,641,437,468,925,213,697,762,362,337,570,709,666,738,335,291,285,267,983,205,714,177,581,554,893,569,345,98,513,177,795,823,87,233,246,998,585,478,916,754,876,448,847,334,245,937,108,497,220,872,132,827,124,616,648,772,640,572,667,613,315,92,683,940,756,447,899,692,347,50,457,981,520,32,773,41,12,179,21,823,832,127,915,214,383,315,121,661,236,480,623,352,18,569,273,355,713,689,785,93,475,379,667,768,63,70,951,922,929,497,436,894,637,87,492,609,222,177,724,682,888,887,46,492,531,665,22,164,214,278,360,216,317,526,763,325,397,576,623,461,501,91,3,382,266,504,349,459,491,841,307,941,491,713,143,641,249,141,348,205,879,174,593,433,3,836,521,629,225,396,340,683,139,219,909,324,931,723,732,635,736,971,814,346,517,721,353,486,656,635,248,890,567,242,460,874,117,659,322,690,270,21,280,343,517,640,395,539,38,424,144,996,927,836,617,594,448,974,11,595,330,103,635,11,633,715,951,960,542,59,742,780,614,484,881,741,87,616,655,467,264,417,774,98,987,254,403,783,292,356,137,932,83,138,400,5,481,76,999,603,732,254,246,411,492,264,29,485,104,839,130,294,733,853,680,353,678,489,542,583,212,568,419,450,227,665,666,860,945,429,137,206,304,771,541,657,648,41,270,383,236,595,940,356,920,583,847,598,281,276,431,550,342,866,845,513,880,473,636,805,645,219,22,749,901,215,667,302,439,794,700,301,812,243,353,899,918,219,564,641,972,628,738,802,838,661,797,279,480,441,309,837,598,528,241,41,317,474,853,327,55,67,644,715,565,354,546,84,201,510,764,294,522,757,460,568,999,848,96,352,34,926,629,886,263,507,28,230,386,140,709,465,852,360,394,472,285,163,760,462,352,752,756,862,716,678,101,256,118,262,850,709,833,855,953,652,320,698,297,627,131,981,628,179,297,963,725,388,266,879,413,327,619,640,487,902,500,167,47,365,110,116,30,862,939,174,825,379,880,998,726,679,720,144,419,213,860,986,607,461,219,499,318,408,650,331,791,568,427,975,164,398,370,20,601,853,366,575,537,433,898,496,593,608,699,285,800,362,590,500,481,699,932,267,329,562,872,692,777,465,609,279,678,586,927,942,827,61,938,47,957,312,327,665,300,942,59,698,571,264,227,658,603,326,745,672,96,78,681,419,606,271,118,986,282,340,970,357,726,378,103,971,85,553,22,626,584,596,268,815,130,651,156,648,571,0,75,889,357,845,729,982,678,301,522,383,276,657,164,535,509,477,235,649,366,824,872,808,590,61,871,81,441,74,715,977,663,386,750,633,184,785,239,912,729,424,836,561,606,591,951,545,840,400,506,931,917,774,543,526,325,933,889,643,747,196,560,804,56,460,10,961,315,167,557,74,951,715,751,149,907,537,540,186,552,667,696,12,295,795,7,48,812,125,62,788,19,685,673,868,79,616,722,705,500,148,644,725,51,87,328,657,920,634,553,827,215,515,884,11,810,630,76,245,504,557,314,87,224,787,908,444,165,839,405,727,120,137,120,180,823,595,197,181,262,583,573,171,243,684,214,864,720,380,740,571,303,567,786,651,125,774,915,764,739,33,55,486,940,612,849,201,501,690,566,599,304,187,925,641,763,96,738,474,991,901,826,296,166,138,876,589,425,793,24,734,483,940,516,701,386,286,379,716,123,934,615,208,804,749,411,4,789,192,789,668,913,323,424,582,279,331,758,659,495,745,889,332,269,416,316,547,105,674,188,855,143,836,639,888,808,562,818,334,832,618,821,291,511,647,229,299,46,421,300,21,192,623,399,931,473,75,298,223,795,379,458,122,224,49,745,834,880,763,469,443,310,656,813,304,303,31,760,710,779,797,418,778,101,201,982,722,639,23,845,118,876,107,371,167,407,361,896,477,403,911,307,557,122,164,554,912,705,3,228,878,979,844", +"967,326,953,10,607,53,947,209,22,925,728,350,357,111,473,482,611,916,898,236,92,644,372,359,769,392,544,730,251,977,914,219,213,177,828,362,430,301,106,483,647,664,881,767,592,375,964,161,171,480,956,461,192,189,23,409,714,357,867,918,430,557,913,736,168,395,418,483,77,512,355,688,394,435,208,543,981,432,209,407,223,157,433,143,378,70,316,419,592,385,221,371,478,784,607,180,239,792,57,752,26,731,224,196,171,368,789,722,877,148,997,399,845,200,693,343,533,863,168,706,336,66,917,517,420,54,480,977,718,681,921,286,170,589,72,292,891,858,636,696,173,681,414,941,926,230,564,722,299,771,674,819,656,376,93,381,711,752,667,942,216,863,743,294,397,811,478,399,275,579,275,79,622,389,52,655,786,90,560,150,929,404,431,106,258,91,69,862,420,44,766,600,256,810,677,596,790,905,417,217,994,741,441,100,382,545,248,7,75,559,669,579,9,262,655,95,619,98,566,344,738,455,655,701,138,142,335,748,685,230,869,864,916,433,339,989,732,153,785,6,992,810,354,143,159,737,874,479,108,807,619,706,562,16,417,669,846,132,455,741,527,517,872,493,633,837,902,506,638,803,369,18,403,624,279,383,98,999,96,829,724,420,154,99,481,786,391,893,704,498,256,959,779,367,821,958,7,196,86,213,841,363,517,666,144,248,916,956,934,569,663,165,545,295,220,839,553,225,32,518,339,482,147,160,179,383,76,297,677,946,492,51,978,163,731,644,302,836,770,557,612,168,111,945,439,606,158,128,653,814,872,951,611,545,310,586,943,295,542,327,975,55,701,314,114,364,54,960,858,831,87,548,638,8,378,576,227,566,18,820,262,775,473,704,570,563,158,80,227,928,823,933,302,890,625,213,732,946,638,513,743,23,320,939,276,152,98,884,648,728,488,869,789,462,265,66,345,805,518,977,333,982,60,791,591,332,940,894,281,251,769,42,206,710,841,68,810,462,605,114,151,643,33,776,548,585,750,902,711,667,572,969,94,301,300,491,667,407,909,870,502,250,441,416,323,932,743,120,409,502,633,304,541,296,532,755,324,813,403,312,53,753,277,411,339,389,894,23,1,951,571,764,610,303,444,976,60,685,304,489,359,491,757,97,899,634,313,242,810,413,474,298,979,978,769,268,935,303,525,237,845,301,445,901,367,370,282,1,702,901,190,522,122,390,596,412,151,808,592,742,648,635,389,798,801,495,870,592,626,398,957,657,537,578,671,882,488,457,333,816,641,377,316,568,577,331,886,28,689,241,843,729,195,316,738,309,867,726,711,925,197,976,171,171,585,742,505,846,891,917,213,467,915,744,762,578,235,280,525,322,439,442,345,308,16,603,998,392,243,299,604,477,524,692,117,709,68,555,932,362,592,275,991,625,763,620,30,643,517,286,932,660,411,965,661,147,963,647,61,831,576,983,944,172,583,303,335,628,338,416,702,721,638,847,138,683,278,474,693,515,374,899,935,734,88,592,222,911,589,646,163,326,829,96,710,708,70,329,59,190,714,839,341,707,134,156,197,75,0,758,835,185,321,262,422,550,902,685,635,893,263,371,951,59,637,858,198,218,920,22,757,180,501,789,681,925,661,78,203,523,929,824,486,232,9,358,842,481,920,659,644,83,452,871,297,265,481,186,848,850,249,318,5,30,314,538,358,718,342,181,424,959,456,684,850,343,214,37,896,358,715,888,224,112,536,194,618,868,163,89,213,63,38,766,480,753,420,302,145,354,766,215,715,382,429,287,857,325,664,390,706,720,932,962,636,883,669,726,625,971,274,870,577,994,126,663,937,831,187,49,283,368,735,752,244,738,261,848,918,199,916,448,361,528,373,653,104,103,821,303,838,542,407,821,9,631,334,506,347,564,599,298,242,588,660,782,321,429,232,793,971,481,366,953,88,146,448,917,175,447,909,739,53,194,498,822,817,101,116,472,917,657,809,672,212,266,336,542,882,616,92,443,606,531,985,489,319,165,391,965,223,60,65,964,38,682,30,107,304,740,9,527,885,934,461,362,622,164,740,204,13,147,630,778,404,726,792,198,374,129,429,21,430,621,729,29,212,752,435,505,791,696,506,984,221,769,110,289,281,985,710,148,535,814,643,712,857,141,113,274,974,646,901,13,903,376,474,547,331,982,153,615,505,900,911,760,213,399,501,104,270,307,98,115,926,763,665,525,203,986,365,465,241,892,854,767,897,726,518,256,740,593,474,564,746,497,507,973,152,165", +"175,469,138,87,382,405,383,539,560,557,344,273,529,342,157,860,416,56,144,166,405,560,307,528,969,96,462,803,259,453,4,115,286,36,306,974,156,862,828,245,217,989,911,855,796,36,959,237,422,545,503,650,308,462,19,69,330,40,357,418,917,291,91,913,533,663,887,196,206,876,470,863,62,773,314,981,234,889,976,35,426,133,645,23,79,744,830,516,203,732,76,462,587,590,925,939,435,450,972,903,216,749,864,842,481,623,63,220,702,189,760,705,829,144,303,540,436,309,688,537,608,742,389,712,269,163,154,728,768,916,391,799,478,728,675,864,855,590,970,543,482,135,695,176,749,747,714,933,684,949,92,925,273,740,7,201,736,702,946,183,841,265,139,773,737,106,183,862,608,161,603,531,782,383,118,587,759,54,478,453,823,199,828,289,863,243,353,855,158,121,912,416,947,675,607,545,474,532,890,827,230,72,44,252,467,642,415,690,554,803,41,713,967,326,144,643,179,110,115,718,171,751,611,466,317,898,393,642,884,215,829,274,840,706,266,534,272,780,54,53,130,772,182,582,698,683,619,250,39,806,744,462,863,371,380,978,347,346,634,450,442,221,689,112,377,836,751,952,359,165,145,344,715,320,409,365,128,686,774,99,464,834,34,789,158,176,915,56,312,638,55,909,215,931,570,326,508,32,773,268,980,127,681,857,919,140,987,428,423,394,969,4,690,176,430,312,996,383,286,559,669,858,645,325,520,457,776,840,899,629,491,182,1000,355,317,463,632,361,245,126,709,39,376,713,73,545,517,550,897,113,698,971,632,903,819,386,701,838,341,599,170,218,390,387,558,110,225,77,873,333,569,696,340,511,586,258,656,640,5,938,884,787,367,400,545,613,24,953,386,651,473,349,994,71,27,928,428,737,194,39,921,297,411,25,164,583,591,120,485,167,805,897,552,46,195,512,851,458,531,159,912,43,69,50,30,498,697,965,973,6,967,230,397,130,952,939,657,841,95,275,856,361,47,317,965,665,833,122,98,398,623,87,635,347,759,503,981,33,459,441,191,328,940,999,532,544,541,624,922,866,172,776,909,516,20,286,319,885,336,613,385,558,73,258,166,542,759,262,64,53,319,397,460,685,765,965,17,91,312,792,757,682,173,468,977,900,688,644,292,154,216,2,562,133,682,405,971,935,791,620,534,274,603,750,564,933,187,449,773,656,745,681,439,767,932,849,702,669,786,979,672,449,797,678,400,235,249,577,767,604,791,796,336,607,807,563,654,77,607,363,307,974,184,653,679,714,204,107,764,454,804,200,542,939,673,161,256,164,744,271,804,635,179,875,581,373,152,781,779,822,239,571,592,320,193,26,624,347,342,614,24,646,598,97,844,570,978,901,962,700,784,529,467,301,369,626,902,502,473,303,861,762,482,609,599,118,70,52,233,937,974,133,935,759,791,817,613,692,992,588,370,238,392,246,990,139,379,794,187,573,458,631,866,627,203,69,819,352,934,815,931,964,715,195,164,192,110,977,610,928,15,158,936,743,94,957,723,145,567,574,261,711,415,374,486,771,419,889,758,0,169,441,509,587,754,968,520,792,902,888,674,32,820,147,43,104,836,524,844,401,724,983,582,849,857,220,608,157,93,862,62,804,358,33,581,25,254,620,611,734,463,578,802,633,537,194,241,451,915,714,737,965,575,888,454,987,47,456,972,809,883,858,232,496,653,94,458,880,862,241,660,164,555,391,730,978,250,545,860,388,773,35,493,466,91,823,262,599,23,108,731,939,823,548,777,191,961,786,199,339,414,994,283,319,690,364,961,128,523,27,121,879,211,581,120,740,831,583,967,936,860,26,725,384,523,331,939,934,930,326,969,193,631,679,274,738,975,622,430,463,355,909,700,266,593,80,649,127,354,16,980,676,27,31,418,228,914,668,888,157,964,68,884,846,842,570,818,498,779,963,157,834,313,991,991,570,51,737,167,725,482,911,18,251,935,349,759,934,889,645,188,451,123,412,256,72,602,799,704,678,461,521,228,879,340,431,616,551,301,661,715,420,183,260,991,281,742,940,616,399,571,588,64,588,32,528,946,46,174,541,270,846,25,839,225,36,881,132,675,545,926,439,80,437,396,814,95,344,991,931,839,561,325,34,564,865,929,686,629,276,927,623,364,202,936,834,492,734,719,428,616,886,419,331,382,857,926,178,691,315,568,384,489,60,620,524,609,996,331,488,464,273,974,776,791,290,308,283,980,415,461,468,898,208,830,705,502,10,806,783", +"448,456,198,3,895,463,605,227,793,305,806,446,630,820,655,143,45,861,445,939,865,204,334,173,979,114,644,2,18,576,275,673,138,972,648,381,721,846,502,219,91,634,814,946,830,836,729,114,888,97,685,208,124,530,989,771,154,468,557,903,316,71,136,505,106,293,569,823,494,971,564,518,573,244,347,21,617,989,795,51,335,582,750,660,273,807,927,422,688,684,372,929,363,917,388,298,631,309,297,195,428,297,848,41,778,793,276,970,675,635,961,383,958,757,117,725,416,11,565,679,754,185,674,520,367,413,41,334,999,154,939,42,724,361,582,562,335,81,371,608,871,593,787,125,141,668,583,20,685,413,282,145,80,614,104,8,337,92,982,291,14,838,880,308,60,234,201,734,260,175,841,87,428,481,92,395,818,49,513,55,740,405,573,160,195,135,419,708,398,783,42,395,78,576,115,98,580,475,960,965,285,590,633,827,499,268,529,555,52,362,665,404,930,102,239,583,235,705,881,124,510,584,43,892,997,816,722,322,724,47,689,183,819,292,806,442,621,472,995,254,737,467,732,664,326,175,562,452,424,13,968,117,517,114,412,261,364,87,210,546,839,628,61,794,486,689,66,157,670,250,567,91,78,309,655,270,149,426,827,273,324,643,168,52,275,601,894,945,19,919,390,766,188,253,741,847,195,635,290,960,26,994,287,662,147,509,948,283,180,446,671,830,110,827,660,604,45,735,203,575,224,13,224,138,681,370,692,178,890,946,443,453,770,968,765,295,57,65,407,312,805,345,680,102,67,557,210,902,984,726,233,743,419,709,870,97,211,539,196,908,728,317,425,577,656,630,755,16,889,20,762,870,492,371,775,299,616,763,121,54,191,60,734,550,960,649,314,689,174,108,370,387,216,907,606,763,726,800,30,471,218,935,187,809,585,832,577,188,859,777,327,794,490,690,182,778,234,591,140,560,53,165,657,771,413,368,875,487,743,880,420,142,25,749,365,611,730,14,34,423,769,581,944,843,569,299,621,366,976,118,950,818,390,268,416,967,331,23,305,700,525,349,261,402,987,890,208,840,158,182,325,467,122,491,311,631,492,512,346,435,92,68,268,371,967,56,376,436,370,122,161,322,989,231,723,200,528,73,856,241,835,475,699,848,921,883,77,470,12,443,156,10,790,401,351,834,776,781,644,413,277,38,534,342,332,402,319,755,513,184,742,893,681,801,427,553,828,534,882,387,944,653,126,275,193,829,97,130,92,771,180,344,220,440,660,206,193,787,425,404,116,306,92,892,464,962,802,216,112,512,96,637,696,206,278,50,493,254,355,680,946,311,793,883,382,299,655,431,908,871,740,58,234,509,680,945,766,125,283,813,792,792,549,891,616,191,342,507,48,137,337,801,179,788,515,960,936,846,420,824,859,14,216,449,972,958,301,818,823,879,681,816,240,315,412,591,594,489,92,155,491,981,931,955,521,283,363,426,532,241,474,353,44,69,65,252,49,253,19,794,654,579,644,170,899,215,81,894,952,178,166,902,946,13,447,752,656,530,148,123,484,513,736,543,742,224,755,357,835,169,0,871,97,809,399,530,852,342,132,712,992,384,484,364,862,488,577,550,677,682,41,572,918,904,704,975,473,970,863,623,320,172,365,701,804,807,301,879,409,419,51,710,143,695,761,594,803,65,857,446,417,2,81,530,884,779,798,18,859,782,546,590,259,888,461,129,374,429,218,358,367,973,771,782,948,853,489,877,40,742,880,36,964,771,793,984,560,780,984,396,60,387,691,618,640,23,400,19,468,656,456,914,43,701,795,321,192,686,514,554,618,674,714,636,167,537,571,583,166,326,440,82,204,984,518,971,29,555,400,740,588,635,164,180,145,980,334,554,167,59,638,738,563,496,147,755,45,212,336,925,97,926,800,301,681,285,439,165,763,575,650,626,4,81,604,769,906,308,941,634,351,64,349,467,600,875,227,282,628,246,598,466,129,915,369,245,172,319,431,807,894,983,792,490,803,614,73,756,181,408,757,275,602,730,85,106,162,293,210,795,834,169,338,556,183,61,133,719,223,438,131,592,345,201,756,117,360,403,959,857,220,646,806,436,979,128,738,638,521,607,911,381,144,180,344,340,12,658,547,924,641,946,666,337,422,856,96,218,18,699,606,592,498,417,444,224,777,964,533,891,849,55,217,398,748,799,775,831,943,226,950,321,715,1,908,493,480,484,433,602,584,912,732,316,243,737,413,510,365,330,658,852,701,456,154,272,336,475,335,523", +"130,186,947,644,187,422,606,662,857,609,398,272,68,704,280,128,763,207,314,943,31,34,132,813,807,403,667,40,901,432,123,119,571,727,37,199,169,900,670,103,344,360,247,178,601,386,160,406,572,358,306,517,767,956,169,157,659,183,512,209,230,791,220,340,70,775,842,492,221,423,560,319,408,537,119,288,53,467,531,871,597,308,319,103,548,903,148,697,519,742,567,724,471,822,453,923,384,882,955,461,147,981,863,823,678,752,59,778,657,978,575,468,177,919,284,23,607,682,134,777,682,256,465,579,272,780,841,58,483,955,326,561,7,311,2,413,808,38,822,501,437,918,384,53,184,108,236,186,107,312,838,851,513,131,491,220,152,294,744,153,104,226,722,974,465,941,329,823,281,443,127,25,441,594,948,969,967,411,800,669,296,429,860,192,459,644,12,292,616,241,466,791,679,253,595,367,443,144,727,741,382,970,86,532,248,261,528,70,313,183,454,181,698,467,737,167,305,717,18,920,823,422,193,153,616,191,578,720,434,216,66,724,674,263,330,277,88,418,736,956,449,702,445,404,104,557,818,57,888,443,559,545,210,404,899,349,282,665,482,652,245,395,765,604,2,397,735,160,551,939,447,545,282,295,274,533,921,276,17,301,43,514,361,959,346,893,936,918,331,507,368,263,385,23,160,848,886,415,617,769,618,234,865,941,262,528,670,840,30,132,264,819,305,33,592,98,615,839,559,321,234,334,528,501,500,605,241,944,147,612,401,274,131,736,728,405,517,125,793,479,217,126,504,165,128,184,189,591,261,594,972,128,299,977,473,224,816,936,388,417,165,672,498,832,602,52,399,505,205,339,393,796,937,815,209,899,705,139,85,66,678,989,814,54,862,596,906,471,334,687,18,36,921,175,882,264,930,41,326,938,955,117,335,961,458,808,810,606,920,301,796,371,691,836,61,863,2,465,539,621,301,933,217,656,158,743,123,316,915,763,175,63,742,926,463,757,621,50,589,12,23,499,962,503,916,940,460,582,739,62,109,350,676,384,712,239,860,238,389,398,64,792,376,122,666,287,394,560,347,431,270,174,274,444,230,810,412,722,936,933,180,116,70,201,530,232,430,201,965,690,602,567,109,404,903,652,967,618,789,146,930,115,496,22,653,250,303,885,147,200,614,71,869,812,515,509,410,783,957,19,281,587,284,383,165,799,335,843,926,507,170,897,369,965,7,410,360,250,411,542,693,644,214,140,958,917,991,339,139,430,860,553,651,569,692,393,504,633,787,900,999,734,561,379,155,704,462,987,525,245,989,256,71,945,870,802,252,360,756,154,382,116,693,575,388,796,568,413,576,584,877,357,539,710,623,916,669,627,633,913,683,485,242,368,685,32,711,950,895,625,831,994,175,681,345,849,475,681,714,237,623,831,268,890,790,641,597,800,170,303,526,136,173,270,314,836,538,436,868,450,863,960,402,689,983,419,954,5,784,297,31,168,251,929,388,827,216,222,630,139,447,901,192,730,426,836,929,967,724,486,426,259,599,991,67,895,517,221,290,60,983,806,942,991,833,300,493,845,185,441,871,0,178,210,291,716,924,956,246,756,867,535,739,544,654,224,787,2,711,94,111,415,257,570,374,159,376,159,187,809,465,557,426,239,930,736,856,875,654,924,246,76,864,415,301,218,66,344,700,342,316,728,869,938,580,119,88,109,387,379,730,843,891,707,587,245,746,869,564,160,810,143,641,963,980,469,373,626,954,751,582,158,169,996,142,657,865,985,296,585,836,205,405,331,586,690,320,120,736,233,563,568,616,14,814,689,544,706,230,276,585,391,735,245,895,848,90,165,796,580,470,570,169,819,379,491,574,53,713,408,592,308,689,970,614,513,674,125,913,919,63,122,405,953,564,127,687,456,441,244,822,961,180,51,592,55,787,991,87,514,900,250,855,37,240,704,402,568,588,292,601,675,504,449,297,225,450,187,327,684,705,914,339,117,608,553,961,580,12,838,513,225,461,813,742,405,268,503,264,660,68,79,671,291,280,639,927,463,659,309,431,543,904,315,276,81,741,478,649,191,565,295,718,475,122,559,143,169,291,469,452,366,840,113,543,470,396,174,967,907,396,409,101,893,301,911,857,909,520,102,979,117,752,443,348,680,687,585,686,794,685,354,226,45,868,424,48,333,192,30,461,918,741,916,103,79,590,860,669,643,4,575,21,910,46,931,809,933,711,135,39,996,502,510,476,244,326,8,304,187,123,805,207,927,411,954,377,437,299,30", +"611,82,234,914,513,575,553,925,260,812,342,335,436,353,769,649,220,234,939,515,860,260,797,863,346,222,704,458,114,414,384,814,125,575,722,34,291,930,246,865,717,547,82,266,969,601,900,333,76,115,959,837,428,16,408,564,543,542,887,503,580,638,946,781,743,679,421,980,16,996,175,738,415,711,16,461,827,159,121,883,868,936,797,509,986,593,685,960,116,847,848,915,303,498,786,667,683,177,760,107,900,999,980,262,220,340,821,898,331,166,187,983,89,274,811,801,766,169,428,69,936,510,426,640,596,77,813,123,875,308,640,562,609,942,229,731,658,571,52,280,155,633,50,231,605,129,418,853,830,314,570,34,53,707,481,449,436,263,766,592,276,673,735,219,791,465,909,753,924,162,910,118,627,983,344,345,298,835,40,391,933,689,256,710,592,534,619,939,649,145,588,287,414,217,771,637,715,821,664,227,635,322,19,572,281,807,340,171,530,784,216,717,866,227,834,647,79,684,901,607,803,128,189,589,61,485,88,316,157,994,219,624,536,274,992,972,817,69,290,593,776,26,133,322,822,695,666,411,195,336,92,416,306,253,471,387,205,905,519,925,935,346,199,136,357,810,261,836,749,144,271,725,317,435,796,37,613,769,528,972,738,109,885,928,173,704,971,723,355,242,205,43,838,188,653,268,815,819,2,805,828,226,969,667,360,417,778,617,214,668,399,593,244,923,365,726,223,497,33,185,184,71,906,939,448,368,318,379,151,286,18,617,993,113,806,703,470,724,659,400,335,582,546,89,694,303,412,76,504,524,530,314,508,502,823,440,223,754,493,516,44,829,605,77,894,766,478,498,634,877,77,820,243,176,514,573,772,947,121,277,828,968,243,716,499,933,581,312,279,146,72,797,604,398,296,950,265,230,128,140,194,697,894,964,189,647,872,169,231,435,996,128,677,95,99,627,815,743,653,113,780,749,236,869,371,563,468,877,608,237,988,698,757,611,169,819,757,644,687,819,146,926,824,634,81,117,272,402,499,67,419,812,934,4,618,562,746,635,856,703,604,836,708,489,161,172,274,607,429,144,6,866,574,976,263,218,804,465,278,61,18,974,744,900,14,471,445,5,205,95,251,428,395,482,113,495,878,264,153,131,867,941,943,592,969,475,978,294,125,254,405,189,448,202,342,366,760,427,325,580,1000,641,627,418,306,730,848,970,329,296,894,325,914,116,676,400,177,484,144,483,819,144,712,731,140,848,549,693,994,935,364,649,914,632,54,431,772,9,296,902,67,795,590,970,695,241,382,947,780,894,680,11,846,840,976,540,918,412,630,495,392,657,273,370,782,196,978,177,106,113,871,251,63,703,913,775,531,958,553,204,81,297,46,742,325,318,175,994,776,592,213,417,671,466,463,510,447,803,976,305,718,73,281,878,247,456,600,66,754,97,779,248,522,164,645,113,311,94,990,957,90,704,995,888,451,906,109,625,792,593,792,925,980,259,52,146,379,341,726,263,164,817,610,363,35,237,72,382,973,536,645,759,795,577,719,302,182,392,14,656,984,628,465,165,331,317,192,729,321,509,97,178,0,532,914,953,118,643,725,879,582,837,796,294,819,60,253,516,29,454,900,885,385,153,756,939,30,224,524,732,601,910,341,86,451,86,460,722,310,717,607,422,398,937,321,226,944,937,403,543,386,275,266,13,371,620,372,105,414,102,102,557,503,658,553,896,525,482,432,119,670,375,127,476,224,826,702,884,820,501,213,441,968,34,527,191,591,401,102,727,419,711,158,286,289,930,96,892,555,100,947,693,859,602,7,389,13,550,270,33,87,193,8,828,55,475,855,468,842,143,873,212,2,317,807,620,677,414,348,374,74,100,130,146,476,826,495,642,403,887,496,370,467,616,630,916,141,981,867,908,876,445,93,929,56,770,236,391,78,208,35,557,811,176,726,857,342,904,242,638,545,154,55,827,951,434,998,769,973,366,137,778,376,641,140,773,909,611,915,420,197,953,992,126,146,590,788,440,10,593,78,41,586,921,633,344,602,899,993,208,150,882,219,193,300,23,164,290,916,206,613,836,7,801,607,597,805,963,422,575,580,261,477,327,76,463,568,77,315,287,147,640,991,903,280,396,977,548,231,343,489,96,44,461,329,233,26,213,829,409,971,371,888,702,917,467,574,454,912,681,316,227,174,637,985,498,804,878,847,655,605,174,901,361,75,772,911,833,103,213,407,851,860,639,879,48,905,829,855,356,777,763,850,941,995,568,501,418,667,778", +"998,830,745,500,554,2,287,69,703,675,750,883,958,995,828,239,745,994,95,688,673,719,650,20,820,3,346,457,83,756,950,693,195,893,471,825,384,242,569,950,640,500,128,518,960,486,104,982,304,623,362,868,628,864,974,672,274,617,843,930,944,304,641,163,641,340,587,700,729,12,26,816,289,250,578,670,11,921,343,521,630,532,132,133,625,98,991,700,57,218,138,83,370,919,457,564,400,679,240,799,468,597,941,29,631,78,815,541,161,513,697,324,705,202,514,595,663,803,329,63,142,934,492,258,559,358,121,883,569,751,736,775,591,257,441,108,383,347,534,140,444,43,965,421,92,240,864,717,283,856,61,410,690,281,169,739,247,126,211,697,62,503,211,251,20,893,773,156,304,177,359,251,737,308,538,415,838,247,91,793,50,510,738,388,950,572,262,691,355,8,291,852,603,922,172,132,370,998,810,502,881,402,664,34,804,10,230,151,220,903,300,129,290,789,145,693,254,364,574,697,997,51,650,400,456,861,892,209,565,442,234,588,891,534,16,797,906,974,645,191,451,678,549,141,854,743,507,394,714,69,375,403,811,146,208,640,213,588,278,114,722,56,683,488,74,294,224,991,123,271,201,824,592,172,185,375,665,795,692,916,466,162,976,7,328,525,864,871,139,126,202,171,195,850,316,819,657,819,183,211,391,789,467,980,290,68,370,286,671,180,245,796,125,596,942,929,989,999,346,229,974,572,476,424,382,829,782,755,250,515,443,6,312,253,903,326,788,959,643,182,661,784,829,944,645,732,35,608,520,926,87,73,959,605,792,524,791,333,392,698,781,724,169,598,537,954,45,863,26,888,571,575,715,969,550,3,423,482,931,108,187,762,970,261,391,209,220,86,283,90,175,748,61,771,107,85,509,817,893,547,900,205,299,552,790,823,545,264,533,370,421,161,332,961,660,751,484,267,851,760,867,325,954,986,461,472,899,851,784,74,714,184,692,653,172,436,379,844,869,723,945,765,943,190,767,587,287,955,434,924,40,778,776,645,225,926,748,665,17,318,219,600,329,336,301,156,656,258,565,918,238,261,818,40,796,882,631,357,121,439,381,518,699,556,829,251,815,470,38,973,494,677,974,995,117,682,397,750,690,384,914,92,351,156,547,994,922,43,371,321,543,430,810,334,132,56,50,183,83,713,832,93,527,706,240,30,782,811,89,284,608,290,39,370,122,18,634,717,367,341,909,394,56,762,610,700,324,945,766,491,546,343,590,31,206,128,986,903,485,796,50,175,720,200,39,50,833,186,498,802,427,4,1,856,125,797,142,641,840,828,959,779,616,420,756,577,172,503,761,229,13,295,262,866,646,928,585,217,898,530,131,49,7,192,623,502,117,27,262,299,696,710,200,280,238,769,59,261,477,989,800,873,210,576,752,894,329,797,726,125,986,299,967,27,629,394,704,952,234,70,261,220,597,255,376,112,440,445,200,624,349,389,125,577,567,892,809,540,324,683,315,802,602,72,76,72,512,25,327,849,612,442,980,441,734,787,312,224,604,384,165,933,768,613,978,801,774,982,262,587,809,210,532,0,140,941,242,770,550,313,789,37,262,544,737,246,672,477,431,946,106,288,495,956,932,108,932,914,662,342,809,443,148,597,636,709,661,383,342,158,11,369,205,663,668,722,61,525,60,895,18,281,57,901,175,350,512,272,300,549,454,973,141,627,389,795,713,28,727,727,956,457,675,215,58,250,831,423,72,789,715,574,548,781,333,401,507,500,434,342,154,484,949,677,871,964,72,696,273,567,956,466,487,551,653,269,893,477,821,65,724,765,223,79,180,571,459,767,338,880,270,974,757,819,184,341,326,387,730,271,230,553,390,171,662,646,285,245,910,58,415,439,519,320,172,938,530,131,872,805,847,889,588,684,790,548,573,472,235,199,96,270,531,679,200,176,424,155,869,759,464,758,500,470,17,116,81,201,922,67,970,293,458,398,288,824,835,494,155,899,781,218,239,745,6,103,166,300,303,262,500,843,976,698,235,89,578,67,130,809,138,390,695,558,662,787,619,875,119,232,728,854,746,429,59,416,338,955,823,918,534,667,579,166,113,172,657,238,976,251,693,247,138,268,723,403,248,360,984,361,797,951,718,776,716,166,755,493,327,410,38,675,427,996,387,421,453,329,136,26,576,52,973,783,403,876,721,228,39,839,505,801,225,511,739,826,308,386,145,137,966,605,137,198,975,198,915,929,804,192,526,535,396,607,394,928,189,424,51,284", +"669,22,669,643,997,386,511,78,849,201,525,706,242,512,297,795,871,367,907,860,552,53,483,88,886,428,875,638,85,543,97,726,459,970,496,75,564,574,203,584,820,373,110,30,571,26,649,756,796,249,398,770,100,820,187,482,404,869,441,274,65,366,751,658,348,693,324,691,299,697,743,2,962,756,447,782,797,527,830,439,434,478,340,999,646,632,59,547,607,480,872,552,827,61,699,462,579,501,802,559,108,642,668,607,845,128,399,185,288,799,903,260,653,202,678,610,984,544,720,914,770,178,530,816,698,486,619,409,664,192,453,899,495,994,450,4,115,98,17,118,218,449,174,976,693,841,775,906,179,368,20,280,614,138,722,798,123,891,329,262,183,986,439,525,484,14,65,169,880,368,321,463,792,524,88,70,410,365,206,105,517,694,917,465,752,894,720,841,536,130,255,108,357,808,947,419,960,658,660,889,853,565,211,816,182,913,760,510,88,319,297,998,968,499,585,783,506,512,522,604,356,677,779,419,247,834,608,701,497,396,243,789,538,659,879,749,132,242,443,981,251,173,24,607,65,751,900,30,270,910,953,138,286,483,25,988,321,253,888,313,473,528,309,91,485,912,112,639,953,864,576,276,339,156,320,529,593,626,960,901,422,796,276,220,328,120,847,464,222,579,509,543,960,288,6,375,700,694,993,222,942,952,836,24,96,185,30,851,993,833,394,395,526,609,391,461,467,489,375,358,435,416,830,751,791,852,919,498,670,942,579,326,281,248,187,265,932,269,635,135,308,889,92,482,796,409,950,499,102,32,439,494,98,344,133,632,576,202,59,690,774,45,184,913,255,649,876,528,210,576,258,400,560,947,349,534,696,248,467,817,93,530,112,45,20,499,711,923,123,230,429,648,689,144,969,452,621,147,600,708,579,843,447,69,363,89,378,514,201,544,354,259,570,724,446,719,749,740,409,574,103,907,667,789,476,89,892,603,495,101,420,324,660,982,342,401,902,4,822,476,158,226,383,512,292,275,982,410,486,614,813,110,514,360,912,586,454,901,752,822,221,326,345,239,649,333,810,546,715,686,885,872,891,919,877,80,62,258,810,495,70,136,561,471,695,372,344,964,788,244,708,810,104,693,636,174,456,948,349,328,643,412,767,858,6,609,93,456,333,640,861,340,216,231,626,500,608,791,912,785,486,57,693,536,543,789,396,217,289,107,447,170,346,797,869,368,246,580,380,129,147,316,711,183,933,396,899,886,94,29,895,388,690,899,78,140,796,733,916,265,768,224,242,271,292,1000,912,164,691,436,668,667,499,587,24,79,364,932,528,209,413,510,578,891,470,244,744,662,779,878,586,33,149,102,390,341,702,988,833,585,261,43,616,534,388,980,528,804,795,370,494,671,399,402,515,583,249,879,749,371,949,73,563,700,662,271,496,917,845,895,831,847,352,738,161,178,679,831,302,386,684,953,97,870,996,873,664,908,356,980,217,128,666,314,377,511,422,64,314,465,529,211,733,507,831,624,103,842,646,494,93,444,691,399,634,572,116,687,926,932,243,427,388,875,503,960,964,678,422,754,399,291,914,140,0,438,43,500,82,456,757,382,242,120,814,730,388,508,34,49,173,820,357,592,423,117,582,664,403,57,822,12,112,890,692,755,401,874,596,838,314,251,773,668,525,792,903,152,45,909,122,602,675,128,784,607,190,891,576,415,899,442,619,694,550,799,799,358,315,854,900,282,155,493,513,584,909,551,51,832,241,857,103,540,532,309,134,77,844,49,307,774,819,209,473,509,915,605,746,811,72,605,521,809,240,973,10,147,944,803,766,903,880,10,291,5,506,882,869,342,78,623,316,131,474,874,175,801,184,346,425,194,621,199,603,265,210,588,950,882,294,80,909,909,323,401,558,624,727,372,299,298,976,387,973,534,65,419,333,927,528,997,304,409,390,951,874,734,152,882,713,955,13,967,193,135,246,143,445,986,540,575,729,165,946,706,867,37,936,227,29,789,940,300,363,200,747,716,331,805,584,632,689,938,421,511,877,454,735,376,243,432,685,768,713,32,753,108,308,511,954,617,642,941,296,988,797,448,769,809,689,208,331,590,33,393,623,935,691,967,615,394,230,481,24,28,407,152,357,184,372,203,199,549,403,565,431,527,335,377,589,397,258,308,86,235,471,769,818,244,617,247,551,828,499,875,301,434,616,674,133,741,766,793,665,203,135,848,496,303,138,721,300,935,112,210,499,292,482,373,887,676,726,730,858,667,605,144,802,248", +"350,865,47,579,630,120,891,795,295,556,24,231,54,82,931,536,13,473,368,341,471,480,169,333,630,621,741,78,383,424,762,290,171,326,323,854,423,216,571,914,193,860,704,742,470,153,779,164,607,907,32,152,579,315,993,4,20,824,130,569,875,518,345,547,665,69,4,139,497,93,252,49,459,38,558,676,550,628,39,54,499,762,601,592,128,462,706,466,279,875,5,828,811,844,961,751,53,653,635,6,283,409,514,371,48,520,770,326,84,104,349,943,547,779,548,936,530,541,926,784,722,390,313,599,737,486,690,847,260,834,976,735,940,577,298,594,414,933,273,860,450,497,766,617,80,416,551,883,530,790,318,432,123,919,49,159,118,799,994,593,109,580,371,934,830,401,663,427,146,344,367,592,669,107,515,442,364,823,773,165,195,83,970,744,137,758,922,206,311,659,286,993,459,106,230,287,116,132,566,147,348,223,43,357,557,822,323,79,818,841,335,908,631,77,548,794,131,739,708,796,751,380,340,294,125,8,198,650,909,568,817,879,597,767,970,432,288,963,803,143,846,417,436,418,122,97,514,269,881,42,134,783,188,737,369,300,801,554,460,352,895,312,354,157,734,451,982,510,467,846,424,641,202,38,165,401,149,254,348,143,596,966,857,662,79,418,266,822,359,124,989,97,419,373,80,271,425,993,152,904,929,411,718,805,450,976,589,426,902,512,664,716,643,834,13,289,749,47,578,537,354,5,972,946,303,495,352,371,131,966,301,815,731,389,323,633,637,589,884,582,426,99,945,508,647,359,592,450,905,583,29,207,902,71,306,633,52,252,411,673,507,861,195,591,15,153,73,396,662,594,640,927,9,431,42,203,228,905,259,210,362,912,801,541,277,641,111,597,737,712,329,51,37,246,385,205,464,227,85,803,416,759,424,384,890,227,507,595,438,734,898,167,243,462,539,609,109,384,435,761,728,452,318,390,529,175,720,542,408,321,318,15,316,46,471,558,265,244,772,955,523,321,977,731,394,296,162,400,472,633,554,506,947,221,469,792,86,427,520,562,838,48,891,928,368,413,111,260,527,865,715,726,734,512,706,354,288,766,744,982,631,819,818,903,529,573,241,829,251,506,618,66,106,19,998,570,974,461,908,625,970,606,910,466,182,85,775,979,409,986,417,595,652,362,163,578,393,902,203,970,551,29,619,586,750,76,412,58,925,10,187,663,874,264,853,206,716,617,724,745,992,211,674,893,707,509,900,21,825,690,251,882,256,792,980,995,660,394,701,909,995,306,985,793,188,362,697,762,565,638,189,957,224,318,158,492,105,435,418,369,897,290,231,130,595,633,662,432,377,594,81,27,411,355,515,275,523,151,749,684,525,990,304,627,455,124,240,46,744,726,854,587,569,828,422,980,810,62,651,739,169,413,569,615,617,269,722,991,313,365,459,311,474,483,713,577,58,457,950,105,491,938,675,132,502,483,165,835,719,91,276,392,983,465,342,152,436,290,73,84,192,217,161,982,158,552,656,217,615,861,790,484,216,951,10,856,391,110,204,405,574,293,711,352,557,117,846,301,550,968,530,716,953,941,438,0,192,255,109,491,173,386,60,520,642,806,195,973,146,902,327,719,40,56,426,162,818,892,421,995,832,855,566,355,351,756,14,237,309,522,734,903,780,239,108,152,61,500,999,283,170,417,904,364,197,367,578,351,634,187,619,46,836,834,246,604,376,435,207,844,991,185,745,868,921,803,754,70,296,204,952,688,714,301,315,258,922,536,150,341,322,509,345,72,692,241,458,39,692,696,33,523,434,686,824,329,533,314,716,681,782,120,443,347,143,469,820,334,208,608,718,607,578,263,410,7,933,254,486,932,254,61,97,162,485,748,380,644,709,497,737,161,232,144,266,629,944,864,521,856,636,966,920,876,740,943,806,931,983,408,41,341,963,342,134,860,416,898,972,811,34,78,795,824,876,740,38,408,779,753,768,360,532,604,248,394,139,158,68,812,681,546,941,611,604,843,7,606,596,929,768,512,396,838,666,116,665,423,346,450,644,894,342,286,351,503,893,592,109,605,151,401,955,892,904,650,66,175,818,291,576,659,679,597,673,69,58,196,511,447,540,466,319,373,104,12,708,500,434,513,3,926,314,619,569,215,554,378,238,117,259,980,939,144,753,97,512,956,578,47,404,878,229,973,326,58,252,982,400,457,970,315,546,290,233,293,84,763,612,6,444,662,775,90,349,519,595,959,886,506,353,600,41,244,629,443,252,674,594,831", +"234,589,270,508,52,896,537,821,308,970,147,75,873,226,819,76,933,960,563,742,726,686,383,966,358,353,167,670,960,217,198,653,27,459,797,792,386,425,238,118,48,616,954,217,507,699,908,112,718,868,804,568,874,134,919,662,210,635,81,300,503,687,256,146,389,476,781,497,418,113,359,963,926,311,720,210,857,316,260,300,118,366,43,399,586,474,533,644,364,929,771,903,108,944,968,356,881,343,381,51,727,203,524,908,469,972,247,661,546,432,323,483,108,783,470,522,952,99,460,845,227,177,857,488,131,391,901,462,387,282,941,146,154,363,449,975,814,148,193,398,141,406,986,648,738,403,541,177,662,81,47,319,267,571,674,716,169,963,279,666,461,872,125,598,912,723,588,820,977,508,898,541,198,703,590,752,480,842,718,809,963,85,986,918,805,300,946,545,41,563,168,329,573,911,479,421,64,961,633,545,314,59,284,74,862,781,165,889,205,59,442,342,79,504,496,248,42,971,277,611,458,348,37,71,946,232,756,887,445,559,38,287,287,717,933,935,324,380,669,581,209,724,908,555,986,483,290,489,614,204,364,216,701,955,345,596,869,702,142,747,787,672,698,412,149,736,199,894,180,46,898,727,203,593,388,810,125,817,878,970,291,738,416,820,449,447,488,355,884,342,276,697,160,521,408,723,849,984,921,940,768,504,920,904,209,795,989,69,14,947,861,632,384,366,749,283,30,405,623,569,935,66,59,182,728,953,942,178,708,471,87,407,959,8,61,143,930,139,741,332,873,123,655,418,227,870,538,207,638,226,618,465,312,706,863,793,714,316,26,51,832,75,992,729,810,794,980,716,259,382,834,178,811,575,591,194,670,820,404,243,829,717,808,486,131,60,401,48,668,569,298,941,431,150,923,287,186,834,408,935,70,311,187,520,758,324,955,602,273,829,650,76,21,653,71,61,703,480,178,421,37,369,859,670,944,610,958,128,592,750,109,13,717,490,274,209,936,890,49,917,25,459,776,307,162,119,831,989,550,15,839,707,429,527,630,704,994,252,504,826,69,154,901,43,601,1000,987,796,614,610,682,572,134,187,828,903,276,536,224,705,664,448,767,679,821,432,62,585,515,417,903,647,8,560,9,447,331,813,406,989,372,245,274,919,540,584,37,312,609,643,71,845,730,527,198,590,872,590,590,851,579,52,801,355,444,646,458,645,375,517,704,837,789,570,189,419,665,475,530,128,353,622,946,860,385,639,969,493,510,178,285,467,487,876,626,23,920,300,438,721,473,225,296,887,709,481,144,501,341,352,545,808,759,676,650,664,864,275,1000,96,706,241,407,949,202,195,818,766,870,810,742,560,705,941,870,868,370,512,194,679,707,519,944,889,236,572,453,633,798,461,390,317,519,677,161,278,810,90,671,355,781,699,703,784,296,438,17,821,830,724,354,156,408,604,290,221,866,919,336,9,414,287,349,887,118,349,285,688,229,502,427,26,507,132,715,809,722,932,959,646,155,226,641,368,969,255,133,514,377,601,8,78,974,505,715,281,291,259,219,174,246,984,892,20,369,791,138,522,902,520,852,924,118,242,43,192,0,81,519,220,715,6,836,256,781,398,472,781,988,849,908,154,735,181,841,111,627,562,790,484,6,891,790,459,527,69,472,194,60,533,596,755,823,746,624,105,441,627,771,215,600,616,978,608,444,921,324,352,366,841,653,828,874,828,526,19,157,598,517,964,729,441,807,952,5,835,971,759,951,162,47,793,696,631,979,780,132,532,155,394,408,146,906,32,550,518,668,10,744,68,323,421,499,809,499,525,68,968,370,595,767,519,165,111,215,993,78,606,872,711,178,701,115,855,974,938,8,484,752,722,584,252,278,930,7,159,114,433,40,568,171,618,353,846,32,346,984,257,425,955,11,88,49,913,813,407,23,289,869,832,552,601,188,947,994,678,142,492,628,86,401,323,829,621,270,282,836,268,198,198,434,122,976,995,792,130,627,865,241,92,312,150,224,15,496,556,179,637,478,160,34,198,467,332,667,45,154,782,582,930,165,721,329,405,684,995,957,261,745,612,878,757,316,209,426,13,727,925,746,21,492,888,862,715,731,710,86,669,138,723,767,944,535,723,492,685,118,436,228,507,35,877,466,661,931,162,997,388,939,731,174,668,697,294,63,800,514,304,210,388,41,504,610,838,336,421,942,714,284,177,295,950,597,762,946,827,528,403,205,896,911,322,701,570,259,407,490,207,815,312,955,47,524,601,106,250,405,635,572,477", +"272,375,799,878,938,422,243,888,739,541,834,580,539,686,147,20,436,562,816,318,619,904,654,588,905,150,813,404,90,275,98,419,193,734,447,153,885,110,902,481,801,734,43,877,917,768,159,885,784,809,568,238,177,942,912,83,286,380,672,422,358,929,349,702,585,638,922,958,567,304,610,653,907,57,70,629,520,914,655,232,473,377,610,774,920,754,168,931,556,190,732,36,878,729,877,562,395,838,35,450,250,995,836,590,908,889,2,690,733,799,957,49,798,698,293,761,292,956,715,531,701,317,133,43,506,606,327,343,552,622,406,566,113,584,128,201,779,979,461,223,637,429,180,205,246,376,112,146,390,370,927,827,756,42,149,551,595,250,123,646,954,996,930,65,249,689,752,137,694,949,788,916,994,147,291,84,825,394,120,371,15,21,586,908,699,336,639,565,720,883,309,468,388,247,981,612,779,715,826,994,748,795,937,438,376,219,943,529,246,87,709,182,983,879,583,210,840,261,592,71,584,931,892,25,406,620,545,119,361,874,345,231,90,506,18,99,239,437,771,908,595,720,438,944,707,897,628,184,481,684,220,440,371,627,860,84,146,752,858,731,507,646,410,410,284,540,83,664,837,27,479,34,622,842,92,70,685,735,401,509,337,845,764,118,647,384,658,532,136,738,502,776,47,80,906,198,629,955,66,553,214,905,898,564,967,662,246,566,805,413,598,195,305,356,150,107,886,230,75,144,118,894,14,410,717,723,183,959,203,881,566,992,434,477,539,173,595,741,564,870,165,79,624,495,620,231,623,641,628,778,297,751,177,542,912,693,409,663,287,637,383,91,878,608,167,953,515,555,667,835,830,471,353,709,480,386,382,11,815,299,592,126,830,260,396,170,928,525,46,599,377,536,347,425,33,573,750,149,980,996,957,613,135,893,286,660,446,455,240,557,756,335,699,717,718,63,32,204,422,750,507,150,935,294,760,95,218,764,133,985,753,250,565,348,129,587,463,697,495,269,701,229,171,673,237,568,988,241,268,375,337,855,748,348,878,713,595,240,719,931,670,56,903,526,426,346,105,428,239,702,591,105,892,749,36,278,35,708,201,873,46,747,845,412,807,155,286,3,18,294,689,199,63,366,827,130,307,626,919,129,521,807,266,623,939,476,788,233,85,593,992,101,918,242,178,438,461,205,705,939,575,93,949,430,236,946,863,383,82,175,913,446,33,663,978,303,117,262,555,915,253,909,914,815,43,798,86,463,217,829,897,1,457,16,906,13,552,798,581,567,452,656,737,983,875,831,838,448,678,970,256,930,896,750,129,556,749,393,823,936,661,907,789,75,592,936,687,227,154,127,699,292,190,874,552,894,44,234,149,792,215,637,25,447,595,879,584,318,968,17,361,729,504,819,154,948,810,85,185,583,128,528,422,996,395,963,220,854,750,516,229,224,690,709,902,779,162,245,912,828,927,191,820,444,793,687,255,911,573,240,315,918,192,922,970,528,989,557,728,869,503,678,376,178,564,18,390,980,560,114,195,410,403,643,394,980,249,508,799,280,900,208,413,365,2,921,140,383,685,792,342,956,643,770,500,255,81,0,684,441,165,372,524,685,62,744,514,129,113,295,137,211,653,724,750,678,412,744,826,902,507,92,720,904,769,891,926,675,493,517,447,864,383,795,167,47,778,582,848,6,368,972,607,243,922,359,157,214,212,239,410,160,940,969,421,502,195,304,74,418,197,272,181,437,54,132,438,363,817,295,715,613,306,200,742,910,694,911,773,233,507,747,537,863,963,796,862,802,399,690,653,274,649,937,643,237,669,177,359,842,300,189,875,88,478,201,776,530,8,708,307,29,821,610,718,179,481,339,496,696,666,139,115,439,425,282,161,702,125,998,472,392,336,101,319,925,930,460,16,229,287,861,596,414,823,616,551,846,942,290,742,332,990,330,46,546,880,770,975,799,955,484,20,18,743,159,609,255,457,84,42,502,124,567,396,792,254,745,60,412,145,540,644,150,956,445,784,487,588,244,284,243,347,199,480,795,165,520,615,901,507,120,535,218,895,922,58,1,706,326,911,879,909,424,880,309,968,572,18,146,55,568,430,423,506,542,719,463,945,893,152,883,577,548,283,401,279,931,81,112,399,406,340,561,981,336,980,128,890,788,123,794,119,563,558,197,572,607,158,47,909,532,689,202,551,83,523,260,747,380,542,761,881,293,998,789,171,799,311,248,955,225,148,263,74,70,883,608,377,601,570,197,38,323,224,218,70,196,582,156", +"149,312,300,52,264,569,101,297,534,530,174,380,740,79,123,447,464,393,949,71,730,266,496,174,463,496,184,461,577,460,557,58,6,215,149,103,591,112,148,210,172,949,846,535,631,631,389,303,852,1000,482,143,988,127,220,254,435,4,711,684,665,530,564,243,70,382,523,239,432,248,917,996,937,432,375,31,152,551,306,419,862,607,815,673,184,552,31,910,420,254,593,824,589,934,884,991,460,131,919,377,854,270,134,899,388,316,764,62,84,444,748,366,489,42,572,773,225,266,217,171,479,639,912,683,71,420,652,453,293,993,814,637,551,777,725,852,521,448,274,547,528,863,532,361,414,841,190,676,712,144,138,229,802,328,573,597,238,637,665,568,304,130,232,342,265,49,844,506,72,968,662,589,402,308,623,533,220,313,301,10,109,676,304,31,678,678,93,764,24,501,437,61,670,411,964,713,330,966,729,139,68,238,883,522,70,145,874,945,835,931,383,978,315,267,780,573,136,755,22,445,93,630,163,872,252,479,149,730,802,222,853,437,545,848,262,986,885,443,559,735,356,658,928,14,530,140,606,696,823,496,751,604,29,372,157,649,660,239,312,273,943,916,77,157,933,29,952,974,272,710,160,512,161,142,496,766,254,605,981,182,662,811,257,961,681,221,674,202,702,416,170,329,629,953,749,948,264,992,750,823,414,757,427,507,748,439,614,671,215,438,249,898,810,757,352,948,471,365,916,211,214,784,648,337,320,886,892,618,23,880,717,235,189,363,574,504,538,512,596,637,754,371,795,662,636,485,291,29,825,226,973,22,869,774,948,454,259,594,427,107,413,299,240,230,368,296,275,262,194,596,28,636,138,756,190,327,530,478,476,954,203,204,8,523,254,489,661,281,506,527,54,845,557,185,384,599,686,509,934,548,387,264,751,169,535,667,160,789,590,643,878,973,581,79,500,346,653,404,135,851,264,897,918,322,917,214,755,397,181,864,123,686,531,779,233,557,869,574,914,152,858,895,171,42,861,950,468,125,961,866,280,28,781,616,161,655,762,265,84,955,671,505,813,19,726,82,152,987,126,58,808,949,764,267,18,41,243,168,60,349,436,513,582,308,8,740,733,562,168,642,216,433,86,11,542,467,125,156,726,883,807,88,981,212,826,190,283,319,673,331,612,762,517,271,682,851,183,129,24,129,312,829,577,524,922,181,273,821,987,386,606,250,36,700,278,55,514,826,453,188,751,212,479,699,179,740,894,471,985,300,98,65,680,185,621,730,566,634,92,290,966,307,636,380,867,646,444,456,995,270,329,392,504,115,686,909,518,514,945,813,25,336,238,547,100,324,342,157,679,254,525,189,733,323,282,351,846,936,401,825,247,66,178,46,82,289,955,596,62,907,37,19,17,790,981,358,658,738,606,47,846,559,396,408,989,458,96,814,341,966,604,609,236,818,239,516,248,104,957,241,717,370,655,740,120,143,150,899,258,276,689,903,247,691,687,858,357,134,987,532,510,811,779,280,611,363,84,744,570,653,41,22,738,357,913,982,144,901,585,12,831,195,127,295,621,383,173,276,635,902,132,246,725,550,82,109,519,684,0,320,812,967,814,570,997,285,342,859,378,441,410,212,328,242,845,82,897,602,397,654,874,966,858,598,102,616,440,900,327,9,503,275,428,222,814,450,816,419,770,284,314,66,381,204,770,195,252,725,288,172,410,802,662,647,568,164,106,424,459,574,896,588,799,414,447,35,108,763,393,866,404,976,329,298,17,204,452,489,754,324,811,254,81,742,529,881,872,897,780,830,127,263,910,347,845,477,20,912,884,354,618,816,21,468,255,285,554,61,306,153,459,688,306,316,732,327,927,491,535,297,927,422,138,856,503,720,993,339,907,71,627,605,164,935,517,252,419,63,502,394,68,461,282,646,491,537,413,721,204,722,293,216,137,430,650,568,411,480,292,992,147,585,980,936,907,669,415,888,434,810,635,390,801,333,451,826,562,451,731,696,594,114,544,860,647,774,920,305,242,871,228,55,196,18,756,764,623,920,207,23,162,433,223,299,616,954,422,591,185,949,256,628,997,485,420,976,299,298,743,902,867,913,37,272,198,748,112,90,264,272,600,39,473,524,288,876,383,579,310,68,658,305,830,530,971,233,334,873,439,942,13,32,508,221,634,874,34,485,853,328,988,10,146,516,30,168,979,371,8,104,911,800,861,615,643,408,201,716,182,255,521,733,628,338,81,521,542,998,974,590,280,50,983,716,365,2,423,268,329,9", +"714,626,67,830,872,189,532,479,559,354,439,835,864,511,723,182,457,705,501,675,263,979,620,506,948,940,549,242,910,280,284,823,603,936,846,827,98,144,211,664,885,944,709,270,613,653,887,545,341,409,999,457,677,810,324,100,694,581,609,244,92,656,887,688,583,274,411,740,722,587,421,324,130,93,738,589,946,1000,761,242,519,425,836,846,439,859,420,295,187,389,910,555,440,894,975,561,884,974,772,104,138,988,656,990,943,383,242,730,979,642,381,502,410,876,767,135,103,356,214,831,363,24,846,296,771,623,802,128,501,967,290,348,744,327,117,95,302,743,707,256,302,446,372,176,480,10,994,532,696,896,456,970,998,411,150,543,542,384,188,243,785,510,388,273,710,382,141,975,895,647,513,715,47,369,112,612,721,985,753,929,62,498,983,167,307,912,733,488,642,504,500,33,592,558,592,530,336,851,491,37,531,587,18,713,422,48,759,740,858,990,947,546,25,542,999,132,854,762,711,801,79,873,926,660,415,825,694,92,634,209,79,214,72,227,454,683,767,127,499,112,113,218,615,358,656,644,642,789,877,394,306,346,867,807,112,571,450,203,992,669,201,33,936,182,13,406,910,897,830,170,568,535,186,584,458,892,982,125,85,38,920,564,613,258,163,971,457,300,125,63,333,892,784,94,325,846,948,772,869,921,28,461,542,850,695,810,242,291,651,449,351,151,917,957,392,223,842,364,975,32,277,679,871,348,432,689,567,705,326,859,785,317,129,197,805,738,504,541,277,190,970,177,502,110,433,594,469,214,135,380,614,819,134,936,588,721,569,606,984,509,418,164,740,721,249,361,260,652,170,245,754,489,856,639,579,524,245,700,514,451,885,609,979,855,116,567,972,484,896,615,609,326,209,24,621,126,129,928,788,842,919,716,410,680,325,297,60,452,669,633,767,239,355,508,553,786,178,389,863,446,105,487,219,41,965,685,507,54,109,254,499,106,120,898,268,867,497,494,265,797,790,363,443,644,617,169,393,226,538,547,900,430,905,654,997,787,645,842,653,838,520,645,466,295,363,855,34,998,92,481,459,331,458,463,376,661,556,528,953,684,701,474,771,629,476,65,818,534,456,196,162,856,671,412,272,993,808,955,4,578,77,770,495,620,659,663,429,815,146,849,433,443,397,89,118,250,747,16,217,36,530,874,660,272,514,871,337,437,918,410,594,323,431,562,183,457,467,875,41,222,400,178,161,757,22,750,77,714,613,669,428,384,561,266,283,401,232,42,730,769,696,588,46,606,952,813,47,772,390,913,737,969,287,603,35,901,502,298,161,771,917,926,533,24,38,753,352,551,537,484,385,954,123,111,560,527,666,504,131,401,468,253,758,151,199,382,983,590,429,39,862,939,740,740,235,156,549,392,210,815,696,127,67,83,157,68,261,495,664,271,696,72,924,525,695,603,926,883,95,737,323,37,506,927,356,16,470,583,320,157,265,563,467,564,129,465,758,216,386,356,660,489,641,114,210,569,69,563,614,570,626,653,666,434,746,951,549,595,180,716,957,118,158,416,220,833,247,657,893,888,712,756,879,313,456,491,220,441,320,0,254,192,341,990,256,932,598,429,51,847,44,587,799,548,518,75,739,95,433,843,827,619,819,750,728,557,516,57,682,3,123,450,309,27,458,593,84,570,49,62,139,953,461,388,430,546,316,194,491,118,676,990,789,313,438,279,679,786,144,740,350,867,884,180,369,648,378,669,556,239,162,967,103,275,578,534,575,144,300,151,246,41,747,521,998,169,973,455,34,595,794,429,544,305,802,421,123,738,591,668,672,396,285,507,942,417,590,152,302,601,904,769,875,343,478,244,712,792,983,132,235,855,759,119,248,480,676,287,291,927,55,621,508,976,909,882,902,456,656,699,943,128,87,571,412,427,714,469,426,601,469,530,95,540,149,324,940,287,648,168,429,944,520,53,800,756,346,251,849,741,639,764,838,653,548,83,785,384,691,88,196,489,615,324,189,538,755,340,753,674,152,503,553,468,295,563,706,402,896,311,976,179,279,519,227,635,535,194,659,506,78,363,923,212,58,888,681,381,629,488,504,411,323,322,63,7,178,417,93,943,810,439,812,884,96,990,552,852,771,988,147,694,365,936,191,143,58,471,463,42,804,844,690,916,482,152,343,52,429,519,345,673,675,690,552,323,14,918,56,653,527,74,973,873,547,764,957,727,66,165,832,879,80,736,625,213,277,932,412,533,309,316,896,403,190,251,80,376,499,753", +"942,550,102,363,260,414,262,612,298,509,238,735,938,76,693,367,870,816,467,11,242,607,492,425,586,59,628,881,441,122,927,593,179,510,83,151,542,851,514,151,928,717,228,566,234,471,959,157,251,26,945,931,412,937,762,312,395,592,754,165,528,86,761,19,469,947,73,141,154,908,622,211,979,126,57,628,121,143,792,364,410,247,387,961,431,658,24,961,734,365,501,472,420,731,686,119,679,890,846,395,949,840,785,518,858,191,291,944,174,693,137,732,364,429,389,7,945,864,514,372,44,731,680,294,131,379,69,892,306,152,186,694,92,962,246,841,250,463,207,166,181,316,71,309,82,450,406,94,975,923,393,102,47,792,148,775,78,563,835,564,209,518,156,913,756,385,663,382,642,266,705,333,723,97,964,817,702,386,262,195,944,1,608,393,730,588,918,887,877,500,428,908,94,401,762,585,334,678,581,666,824,809,549,62,396,619,503,206,541,691,61,556,73,965,831,573,877,968,724,594,493,91,562,731,368,797,911,577,241,635,55,452,23,292,42,664,146,406,510,264,887,315,932,675,427,340,811,106,413,537,998,159,809,903,617,452,841,404,141,49,545,982,344,567,163,167,730,390,983,78,153,502,504,995,778,589,759,725,718,685,916,222,290,208,903,890,281,953,56,203,806,517,950,193,623,233,780,613,869,742,649,252,679,54,792,350,101,350,672,354,37,892,920,391,291,229,638,868,677,571,513,201,643,249,642,743,200,626,620,853,239,264,75,625,668,103,992,866,39,944,902,346,635,442,213,998,573,6,221,318,855,173,391,660,874,68,101,344,742,224,461,494,521,30,375,161,678,773,983,580,576,663,62,481,290,137,370,89,299,766,542,230,25,482,254,111,775,257,460,411,940,533,662,987,312,427,796,759,363,919,306,200,802,430,89,44,337,814,146,936,307,717,529,806,633,720,898,190,378,747,900,889,910,753,945,237,454,225,688,30,413,78,291,461,310,644,900,299,451,946,360,700,262,612,462,179,921,977,575,48,222,578,844,256,277,494,446,205,429,185,519,297,337,768,451,205,892,740,41,172,223,174,799,528,534,338,163,438,250,772,370,104,105,515,451,43,338,983,959,876,816,968,836,595,898,649,963,2,49,121,932,510,77,111,453,746,368,564,717,389,780,778,337,271,666,414,308,71,294,392,762,547,102,884,670,546,546,193,990,887,983,356,966,355,174,860,888,872,49,375,389,18,534,808,734,212,66,372,786,829,581,859,284,699,157,524,119,208,573,54,60,163,77,417,494,689,212,44,372,8,35,582,464,67,687,42,285,615,942,355,83,580,829,571,920,294,703,154,20,153,555,319,648,297,986,622,944,833,935,525,516,207,62,75,303,880,212,316,130,2,774,280,658,223,550,48,913,831,494,105,688,924,940,727,868,457,60,713,326,113,473,99,778,614,254,626,82,507,251,449,305,597,689,505,362,896,834,65,941,363,573,159,651,367,50,128,506,674,975,932,199,399,596,727,441,393,433,811,807,4,989,880,448,885,714,894,973,821,166,802,815,90,797,241,377,283,164,164,263,674,992,867,582,789,757,173,715,165,812,254,0,402,877,566,625,859,227,282,467,142,467,495,734,159,304,775,429,240,970,456,7,299,468,926,854,778,593,533,318,842,898,284,10,340,325,472,366,893,140,251,907,779,468,939,653,128,242,7,963,897,570,338,752,371,72,831,520,914,180,444,249,6,408,949,510,639,114,179,975,967,671,690,563,121,715,503,259,939,670,938,29,534,325,674,15,222,202,271,827,777,268,162,208,986,163,321,235,917,662,134,402,749,644,105,541,587,797,926,77,34,108,695,346,758,601,653,6,27,300,772,528,299,500,694,72,213,431,987,465,288,227,394,582,778,573,117,314,737,350,12,854,800,979,242,406,993,94,333,526,439,922,277,517,770,954,829,908,929,289,832,91,684,675,826,942,882,954,478,598,495,42,486,601,188,350,368,308,496,514,271,935,855,273,457,860,643,900,822,439,541,107,978,214,826,788,193,838,607,489,519,412,834,726,85,111,537,91,93,219,966,812,36,507,186,201,1000,200,689,87,484,397,772,331,882,7,93,371,162,50,445,939,114,860,654,766,974,252,579,628,561,164,983,935,451,411,136,365,505,312,169,935,782,276,676,539,750,682,871,808,716,950,320,693,623,309,455,689,932,102,287,919,99,573,529,487,899,267,363,367,566,595,108,701,387,44,322,307,567,177,425,656,376,269,535,978,219,805,456,99,184", +"501,221,566,921,187,596,223,716,623,949,478,161,301,183,781,39,176,133,83,843,862,601,118,737,816,730,714,20,575,227,205,241,198,724,586,544,692,180,328,158,973,64,792,739,814,537,857,618,580,968,782,464,531,744,461,266,237,213,387,505,29,863,653,196,104,948,380,2,851,843,936,518,627,53,634,821,875,718,660,774,713,645,539,544,753,207,311,447,413,763,947,84,22,433,324,866,246,521,543,858,301,210,584,118,770,244,115,346,94,923,144,32,869,745,30,243,908,59,187,297,811,537,417,796,890,735,158,19,681,14,171,848,344,962,443,982,23,725,821,567,71,245,507,332,721,67,772,846,505,42,14,567,890,311,162,690,704,961,722,575,855,470,763,186,529,795,194,702,794,338,910,88,76,150,431,83,363,824,463,913,110,17,57,775,304,486,110,847,136,996,946,618,154,186,763,881,89,683,834,170,835,721,793,590,403,152,887,617,979,697,605,774,716,337,561,311,291,580,718,921,471,277,41,792,328,599,767,257,653,437,36,611,546,100,720,354,56,449,120,666,930,948,94,28,387,70,646,444,868,763,317,979,509,565,905,122,87,972,362,233,411,719,361,428,509,331,646,796,481,483,931,566,224,107,491,934,491,323,60,112,241,82,550,107,158,190,510,230,205,331,819,904,967,718,391,975,431,971,945,73,871,620,853,982,905,257,156,966,499,372,40,717,275,641,436,577,512,151,680,68,196,710,664,849,309,285,578,136,829,148,274,493,519,643,847,737,843,704,276,158,491,972,109,604,507,129,610,55,617,26,135,886,879,729,850,88,324,832,66,27,997,922,333,701,47,450,203,924,642,130,71,832,853,119,165,644,330,191,692,856,376,546,271,839,616,253,618,613,281,711,330,627,53,963,910,101,29,850,592,734,231,823,50,426,257,292,951,348,86,511,620,442,110,932,375,520,220,85,147,915,296,137,893,271,535,590,595,640,90,292,36,348,454,357,701,316,837,998,118,127,862,380,288,89,591,368,183,605,864,765,483,570,303,129,206,51,124,869,650,899,880,193,562,747,506,42,72,918,189,567,44,602,95,523,430,71,671,337,635,318,897,83,270,58,839,173,951,381,690,190,648,148,277,818,173,943,255,969,754,454,818,27,570,978,383,36,94,286,591,433,527,565,340,635,195,656,163,897,228,393,719,888,918,952,956,87,649,172,981,716,67,508,848,353,207,436,750,464,688,469,682,98,970,894,496,546,201,314,381,328,542,884,144,893,987,344,553,193,233,963,472,63,681,10,299,73,245,709,236,987,105,853,798,139,709,3,71,479,528,724,354,632,37,423,340,830,605,901,818,374,661,422,99,784,962,997,516,289,744,209,219,502,674,492,72,950,803,152,997,359,91,262,801,781,189,147,937,451,453,700,360,550,377,111,138,88,560,159,295,634,112,419,494,938,634,309,862,619,989,112,740,487,957,866,754,973,78,887,538,6,574,881,206,973,783,865,701,105,874,722,819,668,435,548,165,53,436,588,473,863,896,469,570,336,391,853,391,282,242,505,271,625,185,468,528,221,609,535,371,32,384,535,837,37,382,386,6,372,967,192,402,0,318,890,402,164,565,344,813,410,527,848,498,423,47,915,363,494,433,381,536,920,337,48,764,50,690,511,230,455,460,339,685,491,454,503,747,88,534,241,115,202,930,175,394,822,547,13,69,549,8,215,187,14,963,77,568,338,925,34,193,330,619,461,598,618,675,430,675,774,242,481,406,290,170,333,69,275,944,286,256,780,972,542,237,946,722,844,642,37,975,243,130,149,524,447,464,824,258,992,206,988,250,724,575,562,242,597,842,91,526,12,124,417,552,394,553,887,367,501,248,429,102,261,828,266,824,927,681,692,704,564,851,626,388,748,464,683,582,244,562,772,558,561,871,648,552,67,198,907,742,990,411,347,112,426,753,163,583,703,154,19,694,508,700,424,705,338,167,98,995,705,86,705,619,711,297,679,516,82,551,65,273,670,64,967,896,446,626,792,53,223,498,327,917,526,316,15,385,634,486,298,787,759,474,530,879,433,658,295,435,292,77,181,418,870,49,871,900,92,805,871,938,309,726,406,107,366,474,844,985,73,552,339,211,2,157,704,74,765,471,492,607,428,230,980,24,751,13,181,713,439,282,942,243,481,936,561,211,133,96,523,872,460,51,374,703,992,436,856,523,737,122,55,440,780,623,544,678,498,246,760,280,302,817,841,401,312,438,212,661,561,285,272,876,717,529,370,372,104", +"378,670,502,839,911,996,948,409,816,266,142,453,983,115,501,144,265,774,328,184,640,898,702,349,523,576,589,345,255,140,87,36,360,233,643,580,618,377,359,538,739,977,227,428,666,758,352,726,233,687,67,363,45,47,573,848,233,658,162,901,731,314,42,587,129,221,968,208,572,265,632,513,354,273,163,993,451,86,377,899,987,558,191,947,552,533,803,510,168,222,637,439,263,956,976,633,685,837,482,465,309,953,867,45,673,367,329,143,410,59,499,245,479,9,431,805,623,331,476,383,799,733,872,774,557,920,863,483,738,919,282,926,390,179,190,932,648,355,411,226,874,691,840,642,875,182,138,933,373,316,883,700,907,787,693,955,17,423,356,457,511,887,303,770,135,679,756,918,216,141,335,981,534,152,665,992,942,278,460,586,889,987,388,531,119,930,387,947,599,634,848,524,194,920,321,436,987,116,843,577,187,549,608,956,103,898,815,121,228,638,644,149,958,901,216,552,900,529,603,532,700,207,195,695,407,991,951,682,921,317,575,726,769,138,438,206,590,25,878,475,686,924,983,260,10,291,609,740,902,402,242,234,438,704,525,904,269,541,992,887,310,560,22,867,469,296,266,964,3,487,438,94,385,983,180,209,587,379,666,11,84,365,68,992,659,459,936,722,359,375,833,915,896,960,133,100,695,504,82,365,738,424,601,36,118,407,769,463,436,672,423,833,543,332,277,334,93,407,890,555,36,738,875,127,251,698,426,427,55,654,139,681,456,41,64,847,857,18,669,738,87,329,961,732,167,855,550,240,628,597,445,882,673,231,255,242,815,807,584,908,218,639,15,897,641,22,763,248,610,601,754,254,243,246,896,743,685,892,834,472,4,734,128,158,313,615,504,358,442,190,389,345,330,497,257,531,232,703,137,173,585,258,904,655,184,724,616,428,478,859,795,710,51,464,170,95,498,728,698,752,811,797,208,265,364,575,714,898,558,741,998,861,30,110,904,487,141,455,371,857,72,120,738,663,622,759,267,934,740,377,30,265,800,551,279,750,710,713,685,502,507,847,276,145,644,899,296,627,261,720,714,728,97,670,639,971,531,854,176,424,912,351,459,977,59,887,931,136,447,290,14,131,549,429,180,607,816,986,294,720,586,915,283,231,731,912,871,66,906,904,555,319,352,395,92,276,572,50,464,635,871,934,83,524,385,41,299,828,649,215,377,266,230,263,354,5,162,52,195,110,751,6,910,883,523,811,608,220,732,797,142,823,565,308,535,427,122,203,721,841,465,410,14,590,107,722,760,633,48,64,724,671,366,21,628,876,317,895,710,396,77,396,489,387,182,424,774,954,764,627,418,334,989,756,502,82,560,72,150,606,108,366,289,434,925,441,256,660,336,76,407,772,120,331,842,908,406,899,191,755,899,496,886,593,681,252,625,421,922,189,906,867,751,789,36,790,230,793,295,658,926,473,824,198,509,472,505,806,719,688,185,428,462,422,438,407,610,404,839,2,987,356,946,450,791,253,39,691,681,375,158,868,562,734,259,300,595,267,695,988,538,636,89,689,154,641,223,509,951,820,484,739,796,262,242,60,836,524,814,341,877,318,0,811,992,188,669,114,529,730,420,124,269,23,896,805,128,159,996,970,639,877,615,766,155,300,195,924,493,990,241,469,711,195,697,355,645,920,882,275,721,270,416,655,771,391,291,7,130,520,726,241,979,24,110,345,628,895,754,746,966,287,319,641,667,50,239,237,157,37,811,732,563,337,133,936,929,294,516,897,360,964,442,204,781,321,43,738,403,805,604,941,916,309,241,67,881,367,55,531,606,195,147,765,660,711,859,505,436,161,433,553,420,161,848,277,627,473,535,684,499,541,636,555,898,115,957,349,530,495,769,576,132,969,958,833,603,121,921,103,266,20,768,917,650,194,372,546,556,481,42,679,656,849,40,666,420,689,266,269,583,993,952,492,96,376,652,427,372,627,804,617,701,749,912,818,840,892,987,963,583,476,493,970,584,633,977,992,920,489,466,97,44,780,620,49,186,193,51,884,115,125,561,389,921,195,774,201,156,940,380,949,629,99,902,814,206,491,779,535,987,873,857,122,514,110,100,556,378,245,625,430,874,190,645,791,146,844,195,60,273,232,240,794,947,443,622,632,453,85,364,736,111,40,965,685,278,886,815,784,88,904,762,378,869,597,826,675,539,429,300,749,893,445,134,715,648,603,287,514,513,148,501,529,811,643,259,539,462,163,37,60,128,830,587,495,511,727,714,420", +"192,295,796,113,918,4,859,362,200,468,983,545,294,514,35,135,545,347,592,611,25,808,4,200,122,45,785,199,901,64,432,293,909,307,476,395,880,300,798,986,963,642,337,113,174,747,560,994,390,876,504,29,606,894,420,606,936,974,494,102,252,383,422,719,117,998,232,217,703,240,145,820,85,87,923,106,479,993,215,334,760,317,963,290,701,460,836,76,560,23,524,766,116,814,883,135,651,723,231,633,833,199,691,847,983,825,113,861,503,82,850,750,185,134,455,407,167,34,966,925,256,845,499,917,472,153,929,718,956,184,617,909,981,398,153,155,82,928,740,760,819,547,952,986,906,112,667,910,69,242,79,853,196,803,559,410,620,67,137,195,180,177,536,548,367,70,262,943,298,69,765,692,440,382,290,925,687,331,989,613,786,354,32,820,955,131,716,565,2,791,286,18,691,887,997,498,453,157,887,89,159,835,878,985,243,826,501,337,572,973,991,974,400,135,540,819,995,854,867,188,742,25,101,77,289,89,276,633,115,326,87,452,301,543,329,935,89,423,577,11,59,158,488,638,741,160,218,943,411,663,282,691,144,105,757,743,347,557,180,614,477,536,645,650,238,253,666,900,254,472,336,136,941,755,841,255,90,794,412,554,976,671,902,113,740,570,185,690,794,727,767,3,799,128,774,361,191,370,67,197,242,716,709,313,319,748,144,39,386,3,74,543,916,202,722,967,862,217,410,992,810,425,829,17,410,278,526,886,858,480,906,788,295,265,384,786,5,70,250,228,563,470,832,426,28,583,688,256,678,9,469,238,817,276,971,906,679,741,569,819,562,489,868,633,41,471,539,120,631,295,545,49,333,776,194,563,461,560,368,401,942,645,941,834,838,286,534,112,627,510,818,55,295,653,797,101,405,740,939,876,666,770,336,898,23,177,658,59,157,155,302,517,386,922,85,17,283,629,440,282,193,334,59,904,887,791,237,464,795,759,562,1000,677,215,142,213,476,461,840,121,782,390,587,569,67,874,742,325,128,499,962,835,96,697,196,255,654,952,21,356,982,488,984,721,61,542,911,769,138,130,178,702,922,238,728,503,177,978,834,842,352,650,8,55,613,678,132,852,742,324,632,723,261,233,9,972,433,894,623,662,436,681,365,19,394,25,158,380,723,960,253,343,921,181,875,825,966,353,442,127,120,609,537,704,527,877,329,973,778,772,49,760,151,468,336,992,656,45,834,51,611,826,598,72,73,364,955,25,758,460,430,584,317,265,744,848,708,76,305,893,670,300,120,206,125,874,760,854,913,431,140,825,861,41,728,418,927,106,565,246,534,23,822,557,879,422,578,184,306,401,662,752,476,521,280,715,208,835,474,7,13,918,459,567,526,435,58,894,823,863,373,982,414,887,49,408,932,569,290,709,257,419,73,36,816,270,116,328,692,617,618,873,350,107,281,508,908,137,621,216,712,671,901,608,820,500,328,368,366,83,40,40,349,521,243,180,256,86,841,388,577,807,383,671,145,921,731,299,899,5,541,65,631,433,607,77,405,313,757,845,953,933,736,48,269,979,906,477,59,147,364,544,294,544,120,520,256,685,570,990,566,890,811,0,211,992,355,585,331,204,980,737,179,758,550,68,3,536,302,990,713,840,474,522,453,67,377,657,435,727,622,936,834,177,215,469,879,687,373,978,384,372,713,751,268,826,265,863,535,943,549,376,445,394,740,178,658,27,992,476,456,259,298,62,280,395,96,151,424,222,798,684,117,269,632,631,172,664,725,46,265,874,777,195,30,957,802,710,73,956,767,99,15,326,621,872,273,201,224,317,588,881,240,970,29,873,521,822,339,468,773,149,912,104,193,653,257,695,442,292,314,942,809,552,656,523,500,81,90,709,733,596,280,69,405,619,26,612,855,488,634,427,42,515,209,281,113,139,75,484,393,930,100,56,312,170,348,355,30,2,993,923,267,898,785,809,226,489,575,693,896,285,814,628,559,990,549,221,755,98,979,821,306,528,428,844,762,837,385,7,726,102,390,840,424,350,970,346,767,799,651,903,807,692,282,585,946,35,885,758,434,473,223,462,655,768,838,197,66,879,943,593,67,831,209,57,384,655,294,488,424,610,318,886,41,676,958,278,105,277,201,428,220,675,672,594,752,964,386,422,70,369,749,102,476,352,29,702,289,171,194,186,252,513,343,129,379,406,774,520,715,503,855,112,972,541,548,56,25,302,626,608,266,664,69,162,542,356,971,232,920,52,177,669,241,612,94,652,380,760", +"28,353,11,129,541,697,463,543,793,392,25,345,118,844,240,150,909,762,952,707,181,121,457,79,876,981,270,777,991,691,981,724,631,885,978,777,400,132,733,920,365,616,373,418,704,652,490,271,833,495,598,601,659,267,779,640,516,92,958,998,87,713,260,241,991,214,869,721,498,414,669,956,701,485,666,497,111,127,309,666,814,604,862,437,522,691,857,109,190,243,239,404,301,228,353,69,883,240,463,239,863,620,468,85,27,171,356,843,36,472,660,361,586,483,771,527,83,394,877,722,391,923,811,525,196,587,431,470,978,165,833,119,198,234,894,702,145,397,959,68,877,351,575,978,636,346,207,529,601,223,469,683,750,765,436,231,497,598,919,175,223,980,914,247,624,627,53,155,855,144,337,46,22,739,952,756,100,806,302,512,428,474,38,428,682,608,717,226,978,193,639,961,112,396,569,789,579,459,874,250,336,6,114,2,613,557,719,365,885,646,870,287,289,68,208,464,368,673,164,852,806,357,810,421,746,887,387,309,219,959,267,144,22,826,794,301,397,504,245,657,243,772,272,617,580,720,448,293,604,772,648,645,23,970,217,218,503,17,850,144,802,13,623,208,196,942,83,852,322,209,538,539,943,785,561,930,932,856,926,950,591,496,107,22,706,24,922,429,719,619,265,30,272,253,94,957,142,155,921,766,570,263,855,286,388,712,288,976,150,379,931,102,251,986,812,663,125,30,890,346,630,905,545,393,154,247,723,864,570,209,273,637,689,38,580,928,360,650,417,309,753,751,911,145,318,785,577,777,720,836,966,891,715,695,996,344,779,399,567,355,59,791,64,529,265,340,802,971,628,796,359,370,334,187,425,97,633,316,324,655,836,449,916,968,946,872,105,494,494,608,586,426,305,336,621,835,654,571,481,682,680,325,732,707,254,518,645,523,959,296,79,302,235,647,989,221,914,167,494,306,592,113,436,637,62,295,549,677,248,32,745,58,71,458,821,181,13,225,608,61,277,27,478,934,552,242,350,761,791,451,771,983,803,246,58,424,259,391,462,302,176,843,968,525,463,263,595,579,859,295,299,515,894,617,841,854,371,392,423,893,237,392,475,473,358,214,76,921,768,326,261,65,655,743,156,652,351,332,969,994,672,601,307,500,449,820,566,871,328,83,682,319,764,815,991,538,738,246,415,421,305,99,981,508,281,169,991,629,980,837,290,619,320,78,860,14,127,433,657,140,96,444,582,430,524,164,108,713,260,67,127,393,521,367,633,319,697,443,960,678,295,809,696,400,905,936,760,951,241,513,39,120,914,855,270,8,764,432,283,334,115,612,988,169,476,236,727,595,688,78,247,30,319,472,802,757,790,436,447,735,979,464,377,865,519,228,706,394,927,534,809,135,76,628,498,7,652,745,115,577,237,773,306,253,595,779,661,813,208,738,242,902,880,881,652,33,58,827,59,288,90,534,797,580,265,499,9,361,835,182,388,60,66,599,869,923,361,754,761,445,424,95,607,359,955,977,526,204,941,172,958,929,271,21,253,592,230,852,206,745,664,604,588,244,53,796,544,235,637,43,862,654,819,737,814,642,781,62,997,256,625,402,992,211,0,422,838,711,8,602,118,305,63,307,794,712,651,23,919,131,653,353,338,170,671,69,684,380,607,675,92,927,535,186,117,340,498,207,160,953,563,643,2,799,896,134,566,337,732,383,768,250,318,992,907,881,639,804,360,392,420,348,771,264,439,943,425,186,348,914,402,715,593,543,585,317,308,915,684,217,478,510,655,186,901,795,201,695,570,995,86,513,138,652,39,780,167,355,694,880,81,700,203,593,350,79,588,137,972,779,202,390,686,942,482,462,768,950,518,106,199,341,536,144,159,536,634,728,937,597,255,324,74,999,808,461,328,318,553,837,629,335,825,282,633,536,31,622,930,478,896,411,411,267,298,999,429,129,540,875,491,975,574,499,664,918,910,410,828,59,924,484,58,420,49,826,754,160,229,768,588,829,871,311,742,379,104,777,841,176,240,498,229,380,725,204,790,57,325,296,929,614,747,983,741,730,342,957,800,411,419,400,943,855,946,756,716,359,37,244,488,168,631,920,902,53,198,12,282,764,757,712,413,40,853,832,301,80,569,129,203,851,630,926,474,43,268,798,361,441,454,632,532,584,47,591,125,717,493,252,214,558,458,671,971,709,593,315,347,847,755,679,476,423,156,621,399,903,605,283,671,713,174,844,638,216,392,503,500,215,590,228,372,38,981,966,345,931,352,771", +"891,690,186,710,328,939,91,452,514,393,864,438,223,964,783,544,457,381,109,256,737,721,50,728,235,546,778,834,254,835,924,690,478,698,213,3,777,595,993,462,828,119,756,183,456,476,354,660,976,233,377,915,776,377,688,364,150,605,475,72,586,134,819,77,843,148,675,745,865,792,387,781,788,162,296,515,593,652,975,942,680,913,327,458,896,295,946,513,260,115,636,30,25,117,919,4,548,490,167,33,251,710,353,668,373,306,806,505,645,735,380,663,899,641,935,835,474,197,330,117,346,714,390,781,609,826,439,60,451,303,810,590,76,236,337,632,546,955,144,833,278,535,670,603,421,898,994,634,74,121,196,82,739,598,84,915,171,356,43,398,165,41,114,453,278,239,897,175,156,670,579,121,931,724,990,722,206,774,540,248,753,503,130,238,455,708,282,366,594,363,316,312,418,337,527,533,908,671,212,29,37,132,133,16,835,169,595,722,83,773,12,327,407,975,964,985,716,873,287,171,8,879,841,205,294,949,861,545,876,864,7,996,440,225,217,1,790,595,442,652,315,521,472,323,609,895,750,657,237,139,625,201,911,379,554,661,250,711,972,926,25,788,413,874,753,9,566,945,742,847,813,398,633,447,465,927,115,723,30,729,192,891,58,636,80,263,260,983,366,923,777,582,545,12,954,373,960,194,45,198,586,589,319,247,42,481,415,817,107,144,432,442,817,692,433,994,23,913,685,666,973,29,634,285,936,330,498,635,889,856,885,520,739,63,634,492,830,128,761,867,948,153,256,400,533,312,316,939,166,54,855,305,594,293,936,94,136,616,581,142,873,419,271,4,737,529,21,106,443,158,624,228,556,493,34,255,475,700,674,686,724,878,352,851,101,161,966,595,680,54,153,585,35,738,549,39,338,896,139,28,231,526,9,935,705,786,582,82,855,350,54,894,330,457,83,284,740,344,616,447,53,718,971,96,251,421,466,845,587,345,416,576,284,416,733,519,89,138,426,949,472,85,95,49,539,922,177,989,877,246,403,360,506,752,322,713,969,632,256,224,27,701,393,770,486,168,375,616,927,484,140,827,182,436,831,737,961,556,330,614,205,396,590,705,577,750,286,816,839,163,244,94,503,318,961,515,642,677,621,114,359,58,841,214,387,661,965,806,646,362,314,460,296,484,793,556,232,639,562,882,965,207,850,186,140,601,307,407,460,719,453,675,617,35,838,435,823,797,230,525,730,332,128,415,694,825,418,460,485,496,670,640,569,756,538,945,496,813,191,570,76,97,481,781,897,478,38,776,985,468,385,879,277,585,318,104,649,118,223,814,633,18,885,101,969,82,117,671,338,527,72,417,964,455,797,659,450,806,53,302,886,600,155,963,380,697,461,781,547,68,661,203,792,2,460,756,311,604,468,973,676,582,90,198,645,494,202,291,62,225,919,460,629,983,829,45,757,265,240,674,245,674,413,984,245,905,731,35,46,478,6,425,636,985,959,118,148,172,168,916,286,454,289,553,735,887,458,585,908,884,83,677,768,310,449,815,71,328,530,649,937,104,803,642,72,469,688,649,858,104,488,224,60,246,730,806,398,744,285,932,859,164,188,992,422,0,388,729,148,156,429,965,156,404,581,43,365,934,25,172,507,901,184,698,377,421,490,819,694,414,606,269,157,276,809,779,102,690,983,651,72,453,886,582,873,569,765,303,107,315,892,906,616,982,737,963,211,466,60,810,246,226,308,303,540,606,672,602,188,499,666,476,490,575,981,97,782,822,174,453,198,172,892,671,460,250,827,989,92,107,288,862,590,537,723,462,186,6,668,908,224,276,997,67,5,121,723,905,465,261,669,977,895,88,292,556,43,781,396,124,361,542,756,107,805,102,682,687,778,950,779,753,541,422,371,237,864,346,321,359,6,924,995,762,571,691,84,383,50,167,573,986,492,153,130,789,952,988,58,875,986,90,376,266,373,892,440,581,925,574,70,794,541,124,40,170,285,191,61,283,980,532,812,155,900,104,448,801,589,809,505,519,941,844,590,332,159,142,688,759,910,737,65,925,669,393,792,576,449,947,646,256,601,621,514,924,609,106,754,412,710,929,833,792,930,99,671,425,676,146,55,628,373,569,166,94,401,26,573,320,640,548,433,198,23,162,342,958,925,176,151,159,463,154,403,907,941,251,51,310,897,759,250,897,8,650,349,489,363,69,342,256,534,14,620,124,46,676,576,809,195,238,154,358,667,271,888,758,721,653,268,691,729,691,484,183,488,997,860,242", +"694,167,127,623,517,246,700,994,228,567,757,308,174,230,638,40,762,350,269,148,397,539,529,823,68,332,212,284,247,478,137,77,646,85,744,245,885,497,427,201,81,449,7,341,198,768,584,444,521,21,837,674,742,729,193,135,786,740,651,547,462,720,583,66,834,451,108,830,308,292,330,857,612,795,620,211,953,205,686,964,919,226,683,16,806,603,363,9,134,669,408,23,379,656,935,600,446,984,710,369,58,430,924,686,761,698,409,867,673,451,773,367,365,223,382,669,658,789,442,793,493,228,674,110,974,523,953,936,697,521,215,203,513,10,530,521,301,865,319,728,887,770,515,661,589,667,204,431,912,860,98,608,491,388,97,394,956,711,938,203,219,444,434,441,55,658,640,266,351,45,592,529,446,249,950,369,311,659,920,554,94,588,758,477,971,422,835,934,46,576,128,463,939,541,535,104,715,479,880,677,783,866,931,719,574,111,553,271,642,184,310,860,236,44,325,280,475,228,221,658,389,347,541,309,323,198,780,273,481,471,389,777,250,348,572,784,955,453,385,613,570,914,456,928,312,516,185,672,520,854,323,423,66,828,41,903,652,182,243,423,984,938,217,672,450,773,979,141,600,795,770,135,706,301,208,597,971,514,557,272,39,28,211,500,876,62,733,688,501,438,991,864,658,585,938,498,865,900,845,582,880,460,665,31,359,87,670,435,510,357,451,861,479,59,894,95,381,717,571,87,505,801,830,715,541,894,488,85,554,837,251,906,268,72,479,377,260,174,695,318,228,792,473,230,962,56,20,185,217,251,806,162,904,1000,83,567,358,231,316,698,607,498,266,515,324,554,692,419,257,24,854,794,670,119,292,484,312,229,63,858,190,922,396,413,403,275,617,11,325,886,20,712,803,795,953,826,892,825,724,579,560,370,203,89,265,896,153,313,175,54,227,980,906,424,697,385,422,543,641,663,377,509,28,866,16,678,734,528,403,45,150,321,224,221,148,719,490,745,475,835,52,717,621,707,726,112,787,741,46,956,515,115,21,625,352,485,962,835,725,141,857,178,810,168,4,370,891,743,104,737,93,958,872,787,679,596,140,239,117,193,816,319,533,368,611,858,453,98,464,785,908,894,536,809,876,532,397,596,113,145,268,363,523,495,773,489,921,459,399,721,792,419,615,908,588,986,821,964,62,337,874,866,211,654,13,28,235,661,630,95,415,91,976,664,377,714,192,759,889,667,137,306,727,86,108,509,373,246,458,238,232,166,205,144,85,253,532,280,488,692,243,373,631,550,423,342,444,283,787,95,550,450,231,362,742,19,479,25,428,177,754,124,26,747,725,83,722,800,971,317,417,441,433,333,307,811,527,674,525,454,387,979,414,133,79,194,10,282,55,277,103,971,185,341,764,998,706,724,322,766,497,571,860,196,254,531,108,625,9,541,676,8,916,466,46,517,244,236,964,679,705,103,382,607,14,691,700,3,323,695,217,615,734,610,17,593,601,693,149,615,452,425,910,944,479,265,760,452,43,698,65,83,291,500,929,468,935,498,344,538,608,231,190,847,749,396,582,366,198,836,577,787,253,672,388,195,472,514,342,598,227,565,669,355,838,388,0,26,619,847,889,425,734,677,892,188,230,32,471,941,499,102,260,871,475,639,658,654,98,475,175,63,403,806,227,234,296,76,655,129,170,167,428,551,54,789,613,180,403,41,345,530,714,219,195,665,179,632,423,333,921,406,203,315,752,536,401,632,17,973,371,975,591,101,398,427,652,91,666,353,916,602,536,193,385,174,984,863,154,257,635,524,962,57,443,178,532,919,104,47,921,924,584,522,924,537,488,801,224,877,557,123,149,564,612,348,414,650,37,319,369,477,868,105,257,775,249,682,99,803,881,302,426,29,164,133,974,336,195,669,7,224,164,216,357,929,7,836,221,556,478,108,566,212,728,780,629,67,36,472,580,53,546,835,4,217,832,656,518,16,184,84,379,906,518,997,256,681,264,637,33,978,625,875,748,425,44,546,850,996,248,673,771,628,481,35,353,808,286,246,665,687,713,750,667,798,209,982,930,40,145,966,132,251,351,659,86,634,374,920,127,840,830,886,227,908,583,231,574,741,751,472,749,687,723,140,212,408,418,62,581,150,626,286,877,630,131,881,128,716,650,855,927,779,415,774,522,906,586,948,514,971,893,561,472,387,814,244,257,255,684,690,293,736,244,109,165,301,543,923,306,540,400,797,707,953,711,901,601,37,779,314,884,493,410,782,160,450,671,791", +"37,99,426,992,743,41,195,374,687,383,810,381,333,914,103,411,448,170,5,906,970,685,374,582,23,110,606,863,577,117,14,438,604,577,342,723,59,955,7,496,484,655,605,123,162,612,848,826,411,552,357,485,347,40,658,276,235,702,502,504,730,110,790,582,310,64,239,123,729,426,955,300,376,530,20,446,551,276,769,921,897,127,244,360,677,534,521,20,517,782,205,774,594,114,668,59,555,787,394,274,522,755,697,692,281,194,543,179,280,166,756,73,753,482,406,729,251,953,974,657,55,111,497,172,582,404,375,414,617,170,481,6,451,245,310,809,496,136,256,989,922,604,985,192,502,695,570,1000,286,497,647,101,610,208,869,227,950,653,768,31,782,201,597,532,712,944,944,269,118,932,250,620,916,177,818,769,357,730,34,789,258,298,475,819,239,585,329,146,949,564,352,184,554,727,274,291,790,736,718,209,761,337,261,984,274,819,660,175,104,772,312,65,916,744,720,965,434,997,873,661,222,149,932,783,713,147,536,214,706,81,707,87,397,710,824,89,94,42,545,207,442,187,359,171,614,985,910,193,282,730,301,416,124,897,966,770,252,525,380,189,171,421,646,860,104,529,708,499,688,63,772,22,388,382,268,929,892,125,438,689,831,477,844,115,385,236,426,294,797,300,376,517,454,378,172,708,945,59,151,813,98,298,882,269,678,452,295,76,456,953,263,852,239,259,923,657,937,873,231,754,483,194,490,638,228,749,597,672,888,310,657,234,365,986,681,130,457,410,205,423,556,140,456,940,944,480,193,294,286,694,914,932,171,609,43,318,710,107,969,876,821,14,365,621,906,112,89,980,481,767,796,773,936,434,106,322,47,600,321,605,21,643,382,955,474,488,483,158,597,393,369,760,865,455,269,708,951,261,925,697,807,65,31,527,317,486,358,288,422,881,580,267,920,868,197,696,585,762,735,749,762,748,983,8,188,42,68,573,757,103,41,879,724,647,764,848,558,484,366,771,543,579,400,555,103,938,485,379,599,130,861,698,887,537,786,621,281,734,642,703,117,234,383,55,204,923,140,72,126,497,216,466,818,25,145,408,850,947,383,688,463,386,379,122,585,812,361,802,296,709,179,803,529,512,501,818,37,265,940,814,925,20,556,716,87,909,616,4,180,738,199,606,867,51,819,403,303,60,892,683,153,577,103,564,491,536,900,910,390,213,410,592,610,623,768,36,334,853,908,405,744,786,914,769,858,1000,554,393,235,912,864,31,516,364,277,873,421,933,837,753,512,458,259,471,160,694,401,566,367,534,927,973,840,652,463,976,263,80,21,41,420,190,113,89,666,198,595,709,938,629,682,273,639,493,693,113,370,479,439,75,563,245,555,280,360,276,16,610,152,239,766,889,412,481,535,688,61,406,528,975,486,994,300,291,67,822,68,838,483,598,337,878,213,627,414,515,713,137,507,888,931,601,263,281,39,743,387,608,775,700,971,135,3,495,65,50,121,86,60,440,370,93,555,354,376,623,324,821,398,571,139,768,601,784,350,751,193,110,317,458,230,493,898,991,68,475,612,824,218,524,550,2,516,477,508,973,781,129,859,429,282,344,114,585,711,729,26,0,373,430,665,277,591,470,740,530,946,255,98,297,776,733,701,569,597,379,823,562,717,37,778,100,15,830,654,605,902,49,270,244,637,878,147,620,785,335,291,11,886,616,656,799,845,534,3,431,458,189,777,224,400,555,661,290,204,625,382,1000,324,427,337,826,712,747,565,360,542,878,539,66,293,564,701,337,818,776,624,927,218,90,926,429,558,390,607,511,704,299,4,240,852,123,874,599,593,635,262,58,367,310,679,225,131,700,589,742,474,305,112,181,556,561,797,510,423,205,507,204,895,616,357,555,67,305,171,246,350,323,484,521,928,203,168,627,223,161,147,317,282,683,623,856,40,292,297,901,566,689,195,543,505,859,590,170,185,267,46,978,859,243,771,998,461,310,789,862,168,321,291,819,434,33,729,906,259,838,520,307,943,5,808,962,387,882,527,759,886,691,13,639,92,771,628,977,941,650,196,643,794,428,617,814,974,409,401,410,881,830,638,322,10,464,407,161,443,870,843,607,897,183,407,714,536,68,44,746,401,421,755,939,971,658,693,987,517,349,690,497,102,755,766,919,425,933,523,325,330,402,189,538,492,916,694,48,755,882,635,952,411,662,70,266,260,54,148,501,51,724,698,693,937,514,871,941,461,119,659,33,740,933,845,863,445,909,55,555,454,371,787,729", +"788,370,656,97,975,657,364,961,745,978,295,80,213,592,343,766,146,126,767,882,523,380,169,666,784,471,495,420,97,943,33,283,826,40,435,911,589,758,97,638,888,490,311,232,196,259,749,970,667,429,542,409,714,482,873,161,225,686,537,309,475,90,756,30,235,186,456,181,966,26,679,100,393,416,444,847,792,654,371,216,858,508,232,539,760,118,929,678,453,192,27,947,427,514,362,212,160,606,937,235,616,554,877,272,708,211,399,351,771,246,836,314,612,394,524,39,474,671,514,364,364,103,952,753,748,802,856,543,898,617,369,213,309,416,348,292,549,305,562,677,434,103,238,342,165,484,419,29,52,398,81,392,469,468,129,230,504,721,787,809,813,978,341,28,192,673,73,125,683,455,604,759,649,232,338,363,679,176,593,152,417,648,587,999,898,761,770,673,328,592,991,14,489,8,721,343,559,636,193,425,954,823,386,8,29,898,531,312,568,438,622,908,511,70,859,267,909,451,613,96,730,61,972,6,88,683,83,75,222,870,507,28,418,993,133,325,707,103,800,629,680,942,308,734,530,945,615,137,389,948,84,742,118,538,465,431,201,43,287,317,324,517,786,543,504,135,781,289,442,867,537,580,569,287,229,397,784,370,475,459,232,840,604,866,370,669,314,375,766,381,561,326,999,319,90,371,925,919,97,594,405,800,787,795,823,304,21,617,923,859,595,140,68,790,150,162,784,393,776,980,803,146,344,285,968,55,167,241,358,464,470,235,93,519,596,798,4,771,153,14,658,942,84,907,150,192,73,33,775,896,644,182,208,408,825,459,822,787,199,257,422,854,94,459,720,522,33,96,247,80,895,302,728,176,263,870,529,646,10,328,776,682,599,401,863,890,144,813,637,158,421,198,770,268,578,584,524,663,231,466,141,543,192,303,61,542,929,6,280,4,794,261,8,707,379,817,106,884,711,586,758,654,716,696,296,809,626,57,6,732,544,725,796,158,534,786,468,814,264,659,833,705,70,652,3,286,332,651,376,966,52,648,502,291,239,306,946,849,736,841,398,435,686,132,89,970,250,869,13,85,283,910,63,440,33,790,23,625,847,343,635,726,249,90,644,945,364,263,86,966,179,591,281,814,493,653,649,360,220,707,842,860,249,541,342,755,517,190,482,536,76,766,664,851,935,925,856,872,628,477,368,242,488,332,447,706,454,525,452,295,659,116,34,54,117,836,285,486,719,569,203,686,705,878,818,696,86,673,302,826,772,681,991,477,729,982,777,818,903,712,485,804,21,679,955,454,676,654,926,158,10,474,15,834,791,329,251,705,682,128,661,353,444,770,192,860,243,179,855,72,860,665,207,653,843,173,882,531,112,453,81,599,882,669,689,898,8,122,154,618,552,823,533,206,849,981,690,616,407,654,362,907,150,279,102,183,940,218,969,388,708,541,744,174,800,748,799,390,910,199,105,614,768,338,459,640,160,186,892,30,548,519,107,52,773,963,443,689,510,437,928,996,290,69,119,592,199,760,516,622,156,35,746,618,95,82,856,482,292,230,679,442,94,243,532,595,803,872,920,844,677,711,29,431,34,146,988,113,378,51,467,813,529,331,8,148,619,373,0,875,697,996,730,257,549,609,814,636,821,722,293,469,139,281,21,117,312,286,708,321,163,517,736,824,208,18,324,299,202,12,749,272,32,615,928,12,781,573,995,12,890,751,978,834,457,716,468,444,851,882,400,260,929,992,766,565,858,967,965,592,614,410,857,551,72,199,351,814,414,418,476,820,468,456,116,679,192,617,817,461,36,681,258,828,661,115,472,505,152,777,516,288,968,526,396,942,221,714,991,691,293,430,888,589,876,245,568,417,44,326,581,825,596,785,290,600,61,777,450,424,678,11,835,888,730,493,457,428,659,750,62,802,858,649,157,561,319,444,254,96,362,864,553,797,906,757,365,789,854,400,946,630,228,847,582,753,438,987,717,932,422,227,633,659,188,338,587,810,626,469,147,825,579,122,584,563,175,611,394,424,146,728,956,407,207,946,905,499,958,482,125,690,276,648,408,823,217,94,76,268,893,214,938,29,208,739,778,829,121,692,813,138,720,919,707,766,892,957,657,542,384,284,356,663,249,556,318,99,269,695,962,618,677,437,190,479,900,468,974,579,873,565,212,747,952,448,563,22,62,870,265,788,572,184,801,201,12,611,737,359,283,858,656,445,519,498,147,345,399,356,811,930,207,796,635,945,69,419,623,523,946,623,10,672,918,867,104,496,228,658", +"495,833,576,807,485,801,942,932,575,81,91,395,338,671,632,20,785,647,37,459,155,533,710,464,900,998,886,531,563,286,623,353,747,543,596,935,624,991,252,306,322,619,622,449,187,861,292,746,618,254,110,185,186,391,845,477,647,432,814,67,484,594,884,669,66,620,650,36,790,780,153,150,384,483,247,39,602,706,613,466,320,119,532,956,743,341,587,476,495,317,383,945,178,528,326,780,102,25,630,58,673,530,990,224,413,991,670,718,246,628,647,716,731,501,184,253,224,901,819,455,991,843,951,533,155,32,790,509,495,175,104,624,565,141,193,684,476,447,623,334,797,523,887,191,641,314,410,941,160,809,762,351,100,352,213,844,833,643,343,346,895,722,791,788,63,881,758,144,458,124,942,746,913,445,315,817,130,421,60,878,92,747,74,147,276,393,672,695,763,890,681,568,851,925,979,981,280,940,144,545,967,929,946,733,342,130,577,848,890,316,303,769,647,857,968,947,248,695,14,505,799,420,937,847,734,947,17,132,711,184,545,558,93,639,489,647,810,293,194,389,826,43,104,3,909,698,706,130,53,535,939,388,436,595,598,424,421,438,202,186,597,966,165,932,345,587,665,180,438,440,166,173,2,786,102,857,484,162,247,534,966,19,247,203,635,841,894,57,866,470,580,150,455,861,5,965,852,10,829,662,406,603,301,88,505,335,918,469,51,625,323,282,823,858,834,621,321,939,752,978,576,33,501,306,594,191,1000,754,727,511,989,323,460,30,716,423,327,903,710,744,570,507,19,125,536,893,962,781,378,447,27,604,924,948,10,703,540,508,658,575,961,203,467,598,284,166,955,891,229,369,681,123,49,447,768,128,646,888,896,635,409,660,459,412,714,358,492,889,46,617,60,401,415,401,158,268,502,196,782,338,338,411,815,955,819,736,407,570,162,613,513,383,695,48,524,447,50,521,114,637,208,384,268,883,679,472,538,411,481,213,260,45,726,771,152,688,182,521,290,561,247,582,667,739,931,551,437,638,787,494,441,171,793,154,173,613,975,143,912,230,345,597,473,389,417,357,941,173,701,647,387,518,527,92,457,653,450,628,662,494,48,150,152,652,798,726,994,671,374,757,548,562,873,39,143,439,727,611,34,831,569,979,539,814,615,108,478,691,991,844,795,524,802,319,410,389,678,77,747,978,801,444,404,640,474,338,182,891,50,435,691,939,170,940,246,684,982,580,414,889,307,960,678,379,820,36,954,109,881,180,906,540,45,127,313,708,888,637,434,80,852,794,372,638,126,593,936,257,617,382,428,753,618,846,568,116,333,16,417,20,671,663,378,563,867,737,451,777,121,164,12,381,199,344,394,936,160,367,820,330,850,845,90,64,512,470,804,960,935,707,388,670,165,504,60,874,820,732,793,457,744,185,217,111,82,427,119,179,167,146,175,928,809,187,737,917,833,785,292,640,307,520,229,791,914,761,252,920,269,188,606,286,17,592,602,897,709,714,705,816,473,427,585,449,687,365,41,174,302,174,160,401,323,714,9,120,910,949,853,406,914,791,96,512,478,808,517,808,22,401,682,94,454,946,49,902,849,295,441,847,142,410,730,204,602,156,847,430,875,0,29,304,907,968,714,895,504,642,320,163,522,283,767,728,783,34,966,437,398,760,774,26,474,257,832,536,845,277,293,71,210,333,898,968,681,982,237,613,37,728,17,49,305,924,705,986,132,458,116,456,348,491,127,610,76,867,182,321,292,664,27,490,868,191,640,915,879,503,796,150,449,54,976,774,287,345,347,427,968,252,132,682,464,66,740,34,880,672,555,506,520,21,217,733,670,441,180,643,300,990,91,893,635,248,892,999,548,221,162,381,776,527,913,478,81,514,190,102,556,353,264,797,496,121,173,92,615,462,436,432,985,686,150,627,717,88,889,361,968,991,976,604,560,581,104,552,37,455,193,931,63,739,371,940,273,438,537,985,992,435,942,771,250,126,598,812,857,400,978,12,345,330,183,500,589,481,902,303,784,523,651,443,955,66,303,167,808,980,391,763,670,26,79,665,451,809,448,490,711,63,886,949,804,356,109,302,386,655,653,954,704,426,179,401,508,860,203,840,27,806,425,234,631,348,18,497,414,831,423,741,772,987,49,433,572,207,336,12,832,450,10,295,620,85,366,575,115,37,838,751,879,824,328,978,412,108,45,669,720,437,308,766,21,950,310,362,261,280,418,161,421,110,662,747,440,343,697,157,553,25,27,345,9,342,287,687,328,180,766,984", +"961,642,398,906,967,12,891,299,547,927,113,927,419,196,901,687,768,114,839,186,562,285,888,97,479,623,500,163,76,600,844,746,932,594,643,540,626,164,706,806,359,396,649,508,311,398,442,584,237,473,309,721,160,529,730,700,684,581,202,157,208,276,464,853,597,441,678,186,336,426,734,132,405,811,521,473,420,712,697,688,591,98,956,348,327,822,741,863,195,96,252,598,579,573,310,1,193,912,754,676,53,478,821,912,457,840,404,671,835,26,922,135,753,382,733,474,577,60,503,120,680,529,78,240,710,685,432,898,584,500,59,690,246,579,627,482,185,443,595,503,929,25,731,49,211,9,209,368,272,2,455,862,520,122,128,360,687,739,755,859,159,173,510,505,519,218,481,656,175,678,55,57,458,590,546,807,310,956,960,933,529,546,258,967,947,286,130,84,19,201,28,340,300,353,423,309,31,176,432,854,554,967,465,559,38,170,383,82,800,935,18,293,165,774,118,457,972,1000,443,515,470,273,823,968,884,191,893,57,497,742,684,961,209,833,946,613,836,565,997,656,959,907,449,950,420,593,109,267,143,149,471,277,949,35,286,247,214,134,417,336,988,889,272,12,28,117,879,723,968,793,730,470,868,510,567,515,206,837,24,468,710,635,387,464,114,576,285,457,860,838,128,902,686,947,657,963,500,997,695,696,651,896,666,158,918,938,551,775,177,163,869,878,776,115,482,506,477,492,64,162,354,968,623,321,845,774,889,312,703,473,478,415,381,838,417,945,188,684,885,599,753,808,767,212,945,513,265,735,386,656,689,773,838,104,111,631,861,188,406,264,3,555,664,475,86,742,18,129,576,883,8,559,959,318,792,873,57,707,90,322,24,768,380,173,14,739,787,325,273,48,454,513,333,698,36,371,249,200,556,263,799,763,71,994,925,57,318,532,551,6,878,912,478,967,502,895,590,515,417,642,329,792,103,639,100,559,441,861,951,929,761,648,97,180,33,434,55,346,435,824,772,249,770,848,781,750,599,945,357,759,936,838,88,896,826,715,872,366,531,629,588,531,51,747,264,355,307,194,466,910,665,262,800,431,50,262,835,606,461,185,261,403,870,684,791,164,302,396,568,171,589,251,138,316,393,489,255,474,387,443,643,506,862,703,112,78,161,375,300,941,939,625,172,648,895,157,267,563,287,344,155,171,14,354,743,702,551,292,581,973,65,778,561,284,104,702,350,395,489,622,649,440,976,423,81,889,747,940,296,895,143,618,955,713,959,215,576,606,477,61,117,302,887,41,890,208,285,775,257,291,554,253,567,286,189,522,508,618,194,236,306,233,456,797,35,236,709,943,980,598,920,316,630,780,556,987,356,574,121,669,317,567,225,113,608,500,743,826,551,656,970,507,859,658,94,671,657,74,939,180,828,294,199,729,122,21,117,408,782,819,644,524,227,682,211,936,949,976,277,998,619,862,122,877,377,263,710,987,525,61,58,959,996,47,953,794,296,721,787,519,648,183,725,888,582,772,860,538,190,130,631,378,424,419,926,927,731,276,221,438,341,211,683,128,438,202,251,590,757,724,41,111,900,106,173,327,908,137,410,44,467,527,420,980,118,429,889,665,697,29,0,401,315,879,334,84,368,310,1000,391,458,472,276,295,807,465,923,814,344,818,337,796,298,803,156,896,245,769,739,769,586,589,40,48,746,705,215,46,912,698,499,329,599,587,957,388,730,387,532,354,614,536,407,585,329,789,920,323,523,959,201,660,396,417,374,965,424,133,939,811,198,53,408,452,88,143,696,421,856,290,921,165,629,698,447,959,216,7,873,450,130,528,876,666,943,732,164,592,397,349,338,151,462,437,270,978,620,469,755,724,725,824,499,765,884,321,385,399,520,831,774,917,674,422,202,157,852,231,369,220,231,182,887,837,598,429,337,345,565,787,341,650,395,212,918,679,574,495,927,405,765,865,517,28,8,509,900,613,902,935,142,993,497,332,24,40,68,309,813,424,757,713,817,124,240,535,699,34,228,582,127,708,451,911,792,312,2,478,943,93,262,176,545,677,757,366,315,503,50,490,2,713,993,418,745,639,161,923,132,957,235,174,696,281,553,81,475,23,657,219,270,56,166,627,180,417,282,152,775,620,300,604,860,833,804,760,78,955,972,599,138,161,713,812,405,608,196,31,781,435,951,667,757,798,93,239,259,863,242,739,850,22,116,424,928,771,674,837,977,488,536,488,749,14,999,454,30,172,365,560,279,781,427,112,156,170,592,664,350,539", +"770,437,723,592,608,28,411,864,772,817,812,41,732,794,548,867,533,986,482,408,814,947,763,982,592,187,63,985,854,458,471,70,156,779,789,219,621,649,129,638,331,737,863,859,984,548,852,443,796,927,186,630,646,918,834,727,296,549,499,964,91,421,687,382,300,29,694,922,653,123,704,503,318,592,557,981,859,823,817,889,181,358,250,780,150,57,770,574,483,828,431,8,739,226,786,84,43,133,764,375,891,980,465,120,408,326,855,761,230,52,405,431,370,183,995,910,525,874,70,344,700,986,746,939,69,515,889,70,258,93,924,547,447,778,971,472,283,826,314,906,932,299,875,227,705,994,80,896,364,723,857,628,405,600,526,899,331,185,147,419,557,292,382,732,471,459,368,593,281,712,905,199,735,951,408,850,32,857,55,2,89,553,870,171,447,694,529,354,933,703,660,728,97,552,249,659,206,897,896,394,601,685,287,937,996,516,227,192,815,403,433,515,186,840,88,380,699,656,316,650,420,22,128,160,186,789,118,351,550,413,14,765,627,231,192,119,657,644,128,769,137,147,738,827,192,254,831,579,570,399,797,13,923,320,841,937,633,229,345,519,194,825,210,219,83,585,635,104,349,219,4,931,636,304,105,918,562,405,668,261,358,584,751,40,414,172,537,38,178,251,399,294,191,75,676,305,138,856,824,132,581,925,309,912,712,413,42,584,731,81,35,266,980,719,218,582,394,575,973,938,581,94,213,366,306,866,297,66,350,639,867,641,375,979,132,528,211,486,716,220,435,164,689,196,840,992,609,894,26,861,725,65,83,642,454,382,998,601,102,628,922,440,327,219,801,227,749,968,761,634,35,569,585,13,880,928,371,366,128,70,9,266,317,791,428,367,266,615,673,822,353,543,586,231,666,552,60,254,469,862,112,613,465,112,207,474,336,137,489,463,809,446,746,474,582,107,567,516,845,577,11,465,955,74,481,467,306,206,748,323,976,39,242,765,104,801,527,105,457,687,599,851,175,268,342,270,43,570,962,884,389,983,6,580,453,346,842,568,14,913,99,553,635,201,659,885,156,921,473,997,338,295,894,418,765,79,987,260,121,782,274,544,635,804,725,288,16,547,946,197,71,202,855,655,503,300,513,509,280,475,401,616,943,987,592,821,401,552,359,630,411,571,149,933,133,136,106,831,529,300,366,152,309,246,827,150,50,612,483,862,400,374,36,199,35,455,737,567,670,896,513,89,618,376,804,167,157,76,625,261,975,843,917,417,300,826,398,499,7,59,993,489,855,586,885,399,444,49,642,334,457,128,132,230,416,264,433,946,385,704,362,788,155,128,558,256,872,112,394,49,976,846,121,675,656,227,1000,191,815,896,666,775,622,359,300,122,198,849,290,859,981,328,678,663,265,140,323,412,730,962,484,664,641,987,952,39,72,239,168,82,434,20,997,191,92,920,597,584,751,419,136,12,613,696,778,633,989,231,51,850,548,39,64,947,616,836,834,152,600,470,716,103,279,262,861,427,284,203,16,98,393,743,93,612,329,744,490,724,744,826,440,484,618,863,412,546,884,61,180,983,572,415,885,288,820,719,154,211,212,587,495,848,124,737,305,965,425,277,996,304,401,0,411,604,907,951,888,558,283,686,18,164,108,107,433,82,896,332,585,40,586,342,953,236,162,199,876,690,327,737,270,874,429,93,778,325,523,199,868,91,496,729,513,678,558,175,406,808,576,931,240,817,899,658,587,750,941,978,321,312,748,20,804,529,96,653,951,726,90,832,895,499,742,922,24,63,681,172,91,550,528,161,680,497,345,581,557,500,117,492,595,535,379,591,201,861,819,841,986,439,819,484,677,302,981,128,174,319,219,986,921,954,74,891,177,490,714,3,235,180,341,419,656,551,211,629,857,270,231,942,748,375,312,934,160,102,715,65,659,212,437,685,400,291,180,34,145,676,365,240,149,252,540,650,110,991,185,499,218,356,897,743,614,828,291,277,203,693,769,545,287,154,519,777,506,160,721,244,9,906,783,685,666,655,951,338,560,120,158,783,10,123,952,397,942,326,246,45,418,575,774,266,264,338,988,33,30,427,190,417,304,23,869,636,708,320,434,380,764,566,81,657,679,542,28,392,269,590,447,404,385,842,754,573,254,832,217,122,582,372,776,826,441,684,882,305,152,461,567,41,763,259,798,379,687,71,692,680,793,640,914,220,586,210,785,424,56,376,284,531,384,441,572,520,953,64,425,798,211,22,470,998,171,264,848,119,149,105,613,111", +"736,746,266,985,24,206,202,24,980,162,506,683,897,297,874,920,954,774,353,342,736,521,527,665,690,487,224,197,554,491,271,485,728,369,82,956,517,354,753,950,544,585,789,255,778,157,85,120,521,853,45,438,159,807,224,9,913,848,299,822,552,908,505,962,82,778,151,48,46,623,319,81,306,466,941,625,435,154,324,6,812,2,278,229,746,217,568,829,496,258,37,477,972,195,82,300,222,690,58,798,14,970,595,984,43,655,444,501,839,494,159,658,849,26,706,119,148,153,973,907,418,13,501,753,956,727,51,284,664,67,823,455,844,860,2,120,345,488,944,129,402,621,435,518,48,616,252,633,813,322,203,133,719,602,650,100,237,465,588,818,29,797,828,531,701,615,597,474,187,380,920,831,942,514,104,866,356,460,124,585,541,593,2,898,726,705,507,751,177,941,873,753,497,880,662,20,462,727,377,236,794,369,375,380,684,793,723,559,202,292,818,919,727,882,26,405,994,819,539,794,403,31,474,414,306,57,280,829,265,579,779,760,329,734,30,752,640,593,622,548,405,319,283,355,538,471,979,181,855,226,346,716,520,791,545,123,121,740,678,837,140,783,404,284,194,719,893,41,423,720,75,136,654,976,221,111,746,865,542,991,12,915,936,330,780,671,167,239,412,150,379,257,296,488,850,941,163,389,62,182,393,585,908,592,572,819,235,851,466,637,876,82,445,242,517,202,787,982,513,417,269,81,112,221,288,128,381,48,964,416,446,433,68,651,871,386,246,58,725,386,812,429,282,627,375,937,634,531,655,266,531,932,276,433,717,297,714,975,134,539,368,375,712,299,721,633,540,368,419,380,895,819,946,302,522,74,501,321,433,492,223,531,774,189,391,673,557,37,551,18,589,418,169,147,519,803,69,411,6,54,183,716,547,940,468,286,988,523,818,56,692,725,206,579,806,350,876,92,513,618,661,711,658,97,207,200,879,960,363,519,617,367,639,654,853,235,229,710,304,49,816,178,595,585,96,10,271,256,911,200,510,534,189,769,72,13,513,660,635,105,838,44,779,566,11,632,963,704,839,927,145,514,873,753,65,137,67,44,166,148,204,518,551,571,244,109,567,359,869,371,921,659,573,810,275,674,759,792,769,322,587,958,289,465,843,48,384,498,142,906,291,474,731,714,899,962,584,980,980,778,385,250,37,317,617,537,665,278,282,729,686,20,130,449,535,948,727,833,112,844,649,410,65,258,71,318,751,770,335,29,823,504,685,198,159,67,544,588,373,415,86,303,512,966,301,239,610,246,323,630,32,524,112,806,274,405,237,355,938,962,116,16,257,489,482,996,220,4,714,349,838,844,316,583,133,246,746,970,553,109,899,375,433,511,783,505,420,999,242,150,688,66,718,349,279,920,544,448,92,460,757,419,414,734,858,142,513,826,464,73,490,71,936,842,600,54,470,984,452,407,464,723,276,253,577,440,323,916,297,334,776,611,466,510,166,610,63,792,584,220,87,20,857,862,554,626,37,406,435,915,956,434,517,398,150,806,955,739,80,327,161,740,470,611,667,702,78,871,501,582,918,257,385,495,357,40,735,653,328,799,734,498,269,179,63,156,734,591,730,907,315,411,0,645,753,85,219,51,151,932,785,82,534,402,415,532,687,597,662,82,448,302,122,408,921,556,96,644,339,84,611,807,906,806,757,591,271,140,216,527,406,732,441,84,265,571,36,497,39,67,611,261,393,883,982,308,576,354,220,509,255,431,602,179,842,360,898,226,9,966,237,276,676,594,665,533,169,933,192,425,126,367,653,366,945,33,655,632,425,119,869,853,169,620,865,590,765,550,825,293,173,359,918,94,350,227,497,99,699,378,661,3,192,347,510,339,238,612,291,552,468,488,146,937,238,118,167,10,32,529,983,215,500,326,236,757,841,501,882,391,927,605,661,598,511,450,891,755,371,679,292,561,366,525,142,640,701,790,534,456,354,659,764,106,463,352,984,46,337,525,893,503,346,528,392,938,641,174,282,280,815,705,321,364,48,376,942,301,79,29,893,352,811,654,950,899,112,913,916,281,99,292,272,701,510,828,184,626,854,421,804,968,378,889,905,964,113,613,47,840,284,977,321,183,993,546,747,700,245,323,794,610,371,158,430,246,763,175,661,307,22,877,760,152,980,181,408,437,901,461,619,310,675,285,858,2,504,837,159,597,600,52,406,392,120,194,492,637,146,86,237,893,811,329,427,380,496,666,987,943,781,313,161,803,187,269,499,854,639,521", +"207,565,895,349,647,396,954,646,640,598,526,528,416,911,784,155,551,826,830,254,18,400,978,655,240,296,736,414,976,904,482,625,289,671,196,610,63,869,633,826,95,304,131,803,627,35,329,254,494,967,536,251,137,224,738,239,452,814,393,184,144,819,442,255,809,246,388,232,970,959,365,934,134,940,672,733,70,765,155,247,104,486,60,87,114,547,442,740,475,47,311,840,540,378,206,409,477,755,421,370,245,871,907,341,57,259,49,748,822,606,528,812,810,725,291,212,532,668,950,299,844,278,300,766,972,656,281,345,292,405,601,284,306,716,903,573,941,16,155,682,545,674,846,856,982,54,718,115,302,968,496,95,384,190,84,583,800,14,308,811,834,999,593,81,367,166,990,722,855,145,117,44,151,786,153,288,862,410,231,766,48,571,719,566,818,56,290,192,10,604,760,807,767,624,885,231,232,944,299,544,815,808,344,455,529,946,901,942,317,785,244,717,264,280,644,181,82,418,488,388,716,960,881,80,204,802,206,118,782,119,223,605,314,935,221,736,2,803,652,734,641,252,91,356,890,383,288,591,150,752,34,223,845,162,110,630,543,486,260,794,253,638,532,337,541,796,306,729,391,231,962,324,393,526,882,725,948,467,227,795,690,717,12,697,301,810,521,411,685,66,81,594,212,181,645,369,652,795,130,781,55,520,443,355,856,359,337,164,330,918,588,522,834,530,266,285,400,625,580,852,672,403,327,464,722,600,819,632,164,273,161,397,277,661,662,643,147,460,547,400,550,876,297,821,278,67,620,879,530,832,679,682,709,15,710,146,15,943,430,464,496,569,806,41,474,627,937,894,221,124,168,847,308,724,988,639,213,199,174,555,935,370,12,842,26,823,11,937,200,47,59,10,455,732,51,11,346,10,358,833,544,273,679,17,184,871,22,179,321,293,287,131,784,737,948,729,974,91,652,737,901,960,241,228,565,495,146,794,982,318,324,354,437,747,996,434,788,659,129,818,801,905,254,506,351,269,989,334,60,69,641,999,952,498,970,545,913,470,687,83,445,512,92,958,935,933,827,763,896,907,342,999,545,327,973,869,261,115,646,140,336,945,111,725,15,145,385,240,916,254,919,401,138,158,910,214,741,413,3,558,479,812,884,498,451,113,712,829,992,460,586,892,448,434,328,394,323,629,632,348,731,413,704,583,962,271,299,556,288,827,451,841,459,627,953,347,295,367,190,255,197,15,619,224,776,113,932,603,770,250,860,785,550,478,775,327,205,992,441,796,26,131,236,914,430,355,387,671,458,344,325,760,709,432,450,792,264,489,136,559,793,996,756,38,572,976,82,853,37,686,190,709,993,603,653,854,598,308,50,261,693,128,849,661,128,191,348,851,779,653,761,539,353,305,209,780,528,459,274,15,562,30,129,482,504,49,197,743,546,770,459,280,46,487,793,120,916,484,809,453,708,599,803,109,842,414,19,489,703,228,483,223,410,641,585,597,408,335,770,152,995,444,566,372,77,53,226,565,507,478,976,833,930,841,616,482,426,656,908,206,244,668,264,417,881,99,112,81,789,849,904,570,153,956,592,56,181,724,242,548,159,423,23,758,307,404,677,470,257,968,879,604,645,0,870,672,625,433,120,934,383,686,240,100,766,178,966,102,720,750,755,79,912,717,684,665,743,659,853,126,613,255,562,551,638,130,127,572,365,154,329,236,734,942,338,882,373,671,81,660,658,995,740,246,384,837,460,882,872,910,90,855,157,651,308,837,229,989,356,88,191,658,306,893,950,360,203,500,436,585,527,223,96,467,61,383,537,418,698,3,248,575,93,829,2,662,301,19,288,418,561,554,636,770,464,858,294,115,436,152,233,764,310,55,206,14,962,464,730,791,434,734,181,16,111,230,203,608,655,118,172,945,961,146,48,53,270,399,915,178,728,593,909,277,410,677,244,162,249,229,193,341,637,587,757,853,398,351,653,992,443,117,862,368,650,519,907,837,934,304,111,643,332,789,237,395,689,639,801,789,951,539,980,337,53,183,887,700,870,55,90,488,916,456,685,960,577,649,655,478,322,291,549,44,892,761,156,240,743,643,765,57,82,446,188,19,327,548,668,165,332,292,425,787,249,780,53,697,551,698,239,601,710,742,742,538,917,965,112,947,474,409,943,865,377,860,696,121,623,493,256,710,37,124,277,423,275,935,425,135,636,9,586,191,107,549,28,73,239,42,1000,653,296,163,52,573,805,836,634,437,264,632,447,938,102,638,16,462,966,488", +"903,23,899,872,760,835,444,476,105,792,282,505,890,208,298,763,11,42,722,405,597,913,126,237,512,26,940,58,863,843,749,825,743,446,167,264,547,309,510,690,847,446,756,813,245,332,875,780,23,976,913,31,62,181,860,734,365,272,590,879,528,607,562,348,322,94,431,704,744,450,380,950,605,712,824,381,115,546,743,582,401,854,377,6,392,726,636,135,99,227,628,489,934,86,329,641,30,358,395,768,814,747,955,258,718,282,779,698,128,841,214,76,129,416,487,79,534,909,363,225,737,384,168,979,840,21,743,395,389,603,491,494,417,787,673,319,152,556,413,199,284,955,846,789,830,662,519,863,68,312,359,877,9,855,352,820,751,916,755,824,756,867,536,827,763,586,95,442,126,179,44,711,303,688,788,520,595,646,87,200,160,531,306,537,922,101,715,309,97,777,195,739,926,540,513,624,368,570,197,447,864,14,61,350,453,685,710,979,244,259,439,467,26,862,905,451,304,202,590,53,26,685,43,202,829,220,726,837,992,518,851,91,443,698,153,225,299,427,561,497,427,48,333,414,153,927,27,136,448,202,447,132,331,913,228,944,45,80,513,208,498,439,56,317,21,796,152,550,441,437,163,209,467,2,781,795,147,591,510,972,877,638,826,733,153,739,90,195,13,55,509,891,41,685,982,415,962,377,557,195,481,56,904,486,603,752,192,92,744,587,957,148,182,280,983,450,921,835,167,450,587,457,943,629,259,87,642,415,679,965,326,397,401,636,682,503,172,427,259,559,173,986,776,550,966,954,867,496,727,292,877,670,413,972,381,261,463,555,226,168,201,454,275,323,14,267,612,253,974,130,359,157,152,102,877,325,532,287,579,976,252,268,995,657,354,301,978,711,307,34,208,115,30,682,267,284,500,983,266,959,178,751,660,60,459,939,872,369,526,332,991,438,920,601,647,222,457,539,575,521,281,309,490,851,174,93,922,364,224,945,464,380,989,384,216,151,578,284,389,1,82,312,654,618,351,580,358,708,354,23,740,305,519,539,280,777,847,56,64,714,1,170,582,906,750,228,781,501,736,5,392,878,78,580,2,593,636,833,978,210,701,493,921,525,790,127,288,454,447,593,986,456,720,342,206,770,653,568,91,60,836,458,814,135,525,163,368,186,20,580,160,405,375,472,286,72,618,65,299,583,967,822,643,714,470,478,934,675,468,19,150,439,456,714,585,26,181,402,629,344,226,576,694,30,589,824,901,742,917,606,101,404,599,879,248,516,123,896,439,960,568,392,520,887,41,96,830,489,196,504,294,290,114,349,532,846,101,764,885,789,177,36,827,425,624,154,654,812,597,337,737,46,426,695,715,557,902,94,698,409,205,340,927,370,605,7,159,136,466,352,500,727,82,465,392,627,711,690,564,615,407,30,409,53,706,421,382,272,120,658,658,241,612,157,780,343,691,523,280,406,752,620,256,541,201,178,626,349,490,491,165,141,801,432,324,318,979,833,262,987,750,914,108,605,871,303,554,172,656,1000,457,894,946,720,336,784,67,260,855,147,800,133,612,163,931,157,627,441,681,857,704,374,756,932,423,426,841,750,845,518,304,47,896,550,794,581,892,740,549,714,334,907,753,870,0,442,857,211,221,871,734,932,488,687,176,997,662,168,557,575,190,477,680,914,934,472,784,201,100,350,89,582,551,508,41,888,788,108,157,682,322,52,226,219,767,216,273,372,355,316,292,128,344,796,156,253,976,760,236,988,712,669,86,847,814,301,774,964,635,760,97,215,895,149,697,971,498,2,631,607,384,551,832,621,564,206,681,102,271,220,387,289,949,851,296,424,96,476,528,670,816,626,979,548,156,689,271,878,723,825,90,247,581,707,324,733,730,255,762,798,911,487,778,87,596,95,799,331,52,698,432,187,564,107,618,297,999,851,265,96,878,81,313,547,499,531,471,714,282,354,308,669,789,313,27,528,831,256,384,110,247,86,400,180,79,638,885,472,845,786,679,769,800,731,454,391,976,732,511,719,306,250,614,583,594,506,256,504,724,454,300,994,260,508,329,803,490,299,544,733,775,800,182,674,9,549,732,44,557,431,633,231,133,852,970,141,37,586,123,224,749,166,981,267,52,779,520,776,736,643,12,223,903,787,496,146,422,768,244,50,824,167,656,523,316,770,748,667,216,449,145,706,117,685,516,666,443,217,713,181,293,271,872,516,252,26,901,92,336,806,773,444,723,889,265,304,201,939,686,768,424,653,150,938,571,388,500,407,78,367", +"664,956,439,383,861,161,548,717,778,79,817,867,754,496,874,843,660,856,891,72,210,816,548,656,335,683,197,850,769,480,701,241,838,254,882,410,424,461,257,489,274,45,500,94,309,27,435,726,618,665,200,138,787,977,17,663,805,512,961,513,272,431,776,351,662,894,286,206,509,301,490,858,724,285,292,410,970,394,357,371,884,80,33,69,937,704,103,510,151,386,433,573,51,746,62,458,311,103,519,654,839,522,131,190,668,17,400,516,668,900,726,912,685,64,108,338,648,865,593,326,676,171,358,329,962,398,272,280,358,417,405,71,764,770,534,70,778,614,559,574,768,849,413,201,270,902,59,787,758,437,172,822,208,417,874,586,520,32,676,708,217,587,364,609,322,851,584,680,614,966,487,35,856,8,579,943,643,324,546,358,997,949,463,259,27,834,5,603,733,452,640,97,706,371,5,112,868,499,98,270,84,362,377,792,820,830,150,513,44,204,796,795,557,262,11,867,461,430,916,77,849,13,55,719,643,245,470,307,725,275,50,655,515,266,383,205,376,433,955,95,320,119,226,584,714,939,513,606,900,554,436,635,177,11,218,614,236,137,14,345,631,600,953,265,684,188,719,509,925,62,23,466,471,621,327,265,244,965,298,240,943,148,37,530,690,273,844,955,142,525,40,253,183,888,769,27,336,95,395,586,295,959,576,715,783,440,858,269,282,819,490,236,392,97,917,678,68,415,915,642,614,723,402,452,152,509,412,274,337,667,589,449,24,670,218,415,652,678,352,112,236,117,213,920,330,854,318,653,864,501,311,265,621,62,402,662,552,599,918,654,646,124,89,74,288,509,460,727,483,234,169,576,608,266,614,644,399,139,232,481,634,75,694,17,367,759,221,850,57,713,600,369,973,682,911,366,188,150,633,360,381,438,770,960,143,609,507,46,294,493,36,222,955,112,441,366,57,747,305,972,27,493,209,58,643,89,835,817,863,800,995,905,162,915,334,275,646,983,242,940,502,624,166,419,348,668,613,751,916,172,821,585,332,869,999,640,36,593,117,254,319,321,1,450,314,568,243,163,532,9,465,282,266,380,800,818,614,440,310,702,690,433,549,7,152,283,966,759,754,690,406,426,423,712,842,461,226,38,178,815,830,560,705,727,583,286,487,206,717,914,98,267,466,831,780,26,244,884,236,642,386,522,132,28,42,876,41,90,805,456,992,953,853,445,208,747,265,13,924,422,376,389,523,370,475,676,444,776,596,499,560,415,874,973,166,2,216,732,632,311,802,766,749,188,614,677,930,543,27,820,301,309,997,156,553,741,852,821,103,533,170,740,884,264,823,252,522,809,303,551,113,242,350,293,929,756,430,36,492,883,450,54,263,695,797,863,513,847,944,55,195,961,900,123,157,367,893,36,622,576,675,307,968,171,264,782,666,318,274,43,9,937,917,662,254,744,586,7,265,295,646,589,356,890,625,848,680,211,691,64,448,980,878,387,842,688,869,617,742,250,206,763,875,96,872,386,318,435,822,17,886,948,851,853,65,618,620,494,921,619,859,399,649,237,577,735,709,74,925,220,975,159,939,108,117,162,111,678,82,75,775,915,805,68,712,43,188,530,609,895,84,951,85,672,442,0,65,154,58,794,504,165,146,781,437,233,666,959,771,209,106,13,694,278,400,622,808,366,232,976,176,292,148,257,491,82,106,969,564,834,323,684,104,450,11,705,56,351,461,69,522,925,52,939,439,542,888,745,732,567,965,784,368,155,422,66,895,149,658,522,560,238,462,144,607,257,416,721,283,710,207,930,825,780,968,511,563,677,727,557,86,197,63,368,376,318,58,298,220,431,444,402,471,12,465,831,899,183,628,819,633,272,657,510,46,508,488,781,14,933,484,917,311,698,231,634,626,214,184,939,405,254,336,860,119,285,586,826,779,289,918,82,322,396,591,847,335,718,557,10,780,965,948,41,558,833,529,860,334,203,918,558,303,347,771,211,194,705,656,908,419,434,699,691,459,263,17,769,842,191,384,286,435,802,917,857,465,473,702,855,898,524,965,718,412,568,227,503,622,184,935,492,4,251,481,743,254,648,444,369,967,141,979,889,661,165,873,628,952,188,906,942,410,365,36,997,341,154,156,914,37,290,734,784,73,265,422,189,565,21,527,405,527,10,268,424,574,739,213,727,13,116,387,102,805,975,99,261,525,819,225,278,718,901,658,432,336,150,76,532,741,561,625,209,350,537,979,53,662,943,376,856,481,200,9,283,913,561,325,682", +"21,830,509,83,226,359,581,856,623,736,237,235,151,483,39,472,257,505,847,423,443,502,252,53,84,280,650,897,157,893,464,968,193,222,900,607,523,629,742,283,369,489,988,815,346,896,893,684,479,306,427,165,545,802,183,198,467,202,773,596,364,300,634,890,233,41,880,744,602,436,229,2,116,152,183,486,67,565,846,943,289,672,756,819,309,988,440,599,615,257,28,769,117,565,53,517,707,374,431,562,63,494,984,94,906,754,257,488,29,491,188,217,965,438,576,50,989,574,170,299,981,177,345,125,325,613,592,923,766,49,246,833,773,747,805,42,295,639,690,583,979,587,307,689,933,260,933,309,168,657,636,252,360,19,825,568,66,518,270,887,48,343,208,842,273,551,632,970,645,928,99,587,191,415,117,498,326,857,33,715,410,788,41,981,42,436,132,316,139,775,302,72,488,289,758,323,844,686,804,805,203,894,234,962,99,481,332,478,638,85,674,906,310,342,834,157,964,135,810,603,518,363,551,577,228,693,96,998,623,273,172,234,414,851,799,326,403,150,169,492,634,170,809,5,864,409,797,397,473,131,95,398,741,778,222,553,197,27,342,258,654,509,77,883,693,165,787,65,822,49,371,284,971,847,150,40,471,899,291,184,889,266,367,701,249,473,656,599,827,672,755,500,656,688,154,763,237,721,592,650,679,212,853,569,724,710,262,344,586,377,146,564,395,495,37,562,707,103,317,795,727,730,397,914,549,327,199,59,23,997,684,189,585,644,273,74,74,307,405,945,703,647,255,672,111,782,951,448,349,982,893,966,925,729,669,629,212,447,948,352,164,340,167,577,761,443,525,861,604,362,569,276,324,349,590,978,301,63,714,490,653,440,169,844,267,553,551,323,401,279,967,281,110,954,451,125,967,606,567,890,369,249,919,467,85,475,506,756,200,648,456,251,337,346,479,738,55,327,687,266,416,436,35,985,294,850,554,796,82,336,929,914,733,660,853,258,527,34,78,189,24,503,116,377,779,393,744,957,932,175,82,999,306,599,135,30,479,936,552,696,958,730,340,229,705,352,105,36,589,158,863,663,94,322,21,253,245,671,267,398,898,714,987,352,410,350,473,294,397,428,929,333,121,935,717,451,8,37,207,530,313,722,429,104,365,692,934,419,594,769,82,989,261,570,854,683,161,88,487,970,260,87,575,43,557,80,85,790,829,755,424,702,717,24,535,570,705,471,370,306,569,349,529,826,536,245,835,3,206,8,870,515,933,941,262,915,767,288,821,476,437,270,488,116,961,293,301,361,468,290,954,64,578,855,715,292,774,545,482,758,178,267,47,535,517,426,975,240,269,272,931,751,210,403,388,600,773,8,736,260,488,475,219,888,627,947,449,495,851,70,210,769,852,732,30,804,953,6,451,771,599,608,840,591,671,658,785,953,961,237,848,894,781,549,270,1000,611,490,495,88,233,891,819,384,934,697,331,834,365,401,952,410,987,758,830,719,378,407,675,836,147,851,624,379,645,460,769,567,819,775,171,560,121,255,175,893,187,39,295,783,864,997,244,348,730,597,441,715,661,608,473,376,30,932,582,818,627,412,897,739,429,363,128,3,651,365,230,946,814,504,368,888,219,625,857,65,0,529,507,509,824,243,264,524,662,189,184,475,687,366,474,634,375,401,824,520,185,392,753,308,436,483,921,249,525,570,926,397,205,383,200,53,367,904,201,298,28,494,931,922,299,937,968,662,566,466,904,980,436,169,700,474,799,72,101,505,520,830,988,214,339,29,236,159,402,990,461,26,215,43,157,254,973,903,661,262,822,407,173,401,847,532,194,776,877,377,203,107,971,809,562,343,397,278,967,361,717,782,362,417,887,625,54,536,152,690,812,314,99,265,544,727,198,620,389,695,843,895,754,657,416,506,172,977,853,547,954,33,223,910,228,582,790,18,794,926,796,501,666,324,861,602,108,538,179,880,513,462,357,289,981,243,795,987,329,766,836,917,184,610,90,608,544,513,261,84,460,431,77,671,205,27,267,771,800,784,692,451,74,217,958,215,229,457,649,647,126,378,760,469,774,271,51,103,256,976,825,859,4,471,200,951,447,54,738,301,225,696,820,757,221,151,476,818,374,205,182,126,527,121,295,612,312,122,922,405,682,538,665,66,75,14,27,271,469,713,222,211,73,97,346,501,135,2,139,309,374,619,476,750,952,385,783,788,538,607,28,556,644,968,284,993,67,813,578,783,709,986,904,414,901,509,729,331,459,863,269,86,294,660", +"345,266,1000,351,362,70,988,871,946,77,607,284,616,695,483,498,421,368,961,732,473,176,680,943,222,474,339,837,954,922,225,123,758,665,840,253,493,743,183,569,668,644,26,443,636,514,135,36,343,923,322,850,978,970,863,504,276,36,483,769,328,547,399,310,857,417,264,807,569,952,845,424,901,255,350,431,362,697,692,87,687,326,736,654,626,800,831,650,460,256,624,832,756,83,998,564,141,91,630,633,338,302,26,225,829,971,317,760,476,642,989,668,676,476,542,662,646,248,692,886,771,89,386,618,748,232,532,901,742,692,320,336,971,378,331,918,879,85,119,177,510,449,712,238,827,565,432,916,77,508,425,334,139,371,333,616,38,885,721,457,674,907,273,279,643,47,173,899,394,211,950,853,619,419,71,180,465,650,931,77,400,303,904,610,918,681,344,387,63,894,886,599,928,983,86,467,458,982,891,901,467,836,639,677,39,346,398,423,683,137,424,326,143,124,445,377,827,8,459,208,794,255,380,339,181,615,716,421,594,250,416,438,33,193,992,207,298,389,175,413,898,525,565,370,10,788,38,419,435,678,347,639,882,934,45,414,352,120,256,39,517,279,547,611,667,966,25,548,186,959,380,15,915,635,92,79,426,884,360,678,41,736,548,348,642,758,497,147,597,689,101,799,630,890,43,157,897,427,495,86,692,68,38,550,485,67,749,367,223,221,612,458,318,639,820,251,586,308,304,22,638,769,545,661,842,203,820,730,151,150,571,129,531,660,879,589,947,314,23,241,234,827,509,952,127,700,276,42,851,419,431,926,581,256,597,244,763,347,975,675,561,706,950,691,679,907,196,575,941,785,220,309,709,421,816,648,482,340,522,320,532,335,249,341,639,226,666,233,763,357,41,695,426,664,134,418,30,112,394,399,70,384,666,520,287,680,498,864,105,321,62,547,677,533,167,701,589,418,125,207,924,731,952,953,418,205,114,619,153,459,449,76,278,918,894,340,167,147,955,8,354,289,914,801,177,595,880,474,84,816,286,805,677,274,22,136,126,587,683,625,459,195,800,474,812,377,965,390,211,75,768,532,996,809,75,834,250,709,606,368,789,602,871,297,512,449,325,649,809,276,243,510,200,559,476,763,571,820,413,899,120,918,89,900,811,931,816,275,107,994,227,818,14,121,615,533,362,218,350,640,647,970,63,343,637,577,344,494,768,277,764,684,163,511,254,854,441,852,370,382,219,307,708,905,813,659,724,179,994,332,734,88,303,386,146,260,58,142,280,761,385,248,121,690,735,523,116,4,224,360,282,848,306,506,107,929,122,650,681,294,922,534,407,172,485,900,282,994,269,203,711,693,352,377,883,14,263,393,499,678,463,105,491,25,349,686,680,112,703,332,225,418,808,438,580,268,879,170,870,296,597,938,785,310,952,976,891,131,166,522,831,867,49,585,582,943,766,587,456,1000,507,857,617,224,800,14,421,181,18,507,498,694,986,4,530,316,612,540,251,652,615,433,484,686,708,876,990,441,440,331,896,623,640,426,823,864,764,857,526,635,462,242,821,186,787,244,724,977,78,157,970,159,224,914,664,892,562,744,602,95,240,494,159,536,23,934,32,255,636,642,310,558,51,433,211,154,529,0,74,16,621,717,790,327,850,379,468,976,961,144,421,274,898,102,641,104,371,257,506,741,376,488,497,944,806,155,859,644,293,537,349,315,325,167,120,465,845,539,592,906,110,503,838,485,874,592,706,264,838,666,487,437,101,126,846,287,798,294,550,953,469,345,176,428,879,577,623,763,148,784,557,838,305,273,786,464,546,31,97,997,383,507,245,561,663,514,895,824,709,294,143,164,697,176,391,400,141,242,707,4,183,771,499,523,755,458,798,209,888,800,182,597,219,676,158,639,281,735,420,810,854,672,450,838,154,6,230,105,61,135,761,314,196,717,896,572,532,299,965,101,396,200,829,444,229,214,898,488,360,655,810,548,174,150,592,549,785,850,811,135,900,282,280,369,646,709,405,308,120,145,327,236,78,904,851,277,352,745,346,526,551,508,103,912,651,277,722,867,863,520,382,867,437,101,866,511,203,10,625,901,558,406,810,640,774,297,489,812,98,663,904,692,54,981,933,68,326,932,753,611,225,89,340,58,441,449,892,298,82,310,282,73,338,756,751,703,18,673,47,155,907,649,750,11,846,695,727,716,637,472,781,924,344,330,676,884,694,282,751,37,91,223,249,883,461,119,47,241,631,759,514,476,891,410,201,604,527,110,440,964", +"480,866,517,431,600,493,562,194,247,212,367,172,581,399,118,518,208,73,801,286,873,251,922,390,70,983,922,462,104,44,859,962,80,137,106,896,608,652,436,662,853,595,985,297,439,736,364,988,751,34,682,573,531,19,797,585,328,691,27,728,440,340,491,201,441,519,646,327,350,46,34,443,196,543,661,388,260,240,844,605,599,592,647,987,260,528,416,448,127,523,943,791,980,432,906,337,125,703,486,29,335,190,382,844,913,834,375,57,623,878,871,340,893,729,873,649,297,180,969,908,28,284,893,642,781,623,266,339,189,140,156,11,196,696,11,995,72,398,314,638,653,578,973,218,901,360,123,7,611,273,727,240,810,275,552,849,278,589,786,415,605,392,836,745,882,944,516,421,300,856,173,68,22,283,250,496,299,931,894,925,455,322,746,837,588,229,99,160,155,71,95,53,674,59,732,279,608,165,560,655,511,551,30,34,773,245,62,712,529,300,90,416,292,53,274,297,988,903,599,842,470,338,476,816,289,567,203,417,252,933,31,44,371,575,751,892,473,203,980,452,73,101,386,452,426,46,562,609,880,896,191,428,613,431,906,425,86,418,233,374,393,353,576,397,622,684,21,931,919,42,677,395,827,853,130,887,525,588,2,993,50,792,561,920,758,681,140,98,98,951,47,501,738,486,251,604,75,195,746,620,736,705,52,479,228,574,471,628,831,356,950,514,192,726,878,975,117,239,30,7,493,558,595,674,341,808,325,192,717,369,488,957,270,993,431,409,41,86,159,320,191,469,900,491,984,514,764,637,89,340,660,495,242,744,332,733,408,522,797,104,897,529,680,810,76,746,915,60,909,756,792,45,464,810,756,785,568,145,291,227,170,498,926,762,553,821,773,163,170,751,402,746,804,897,339,260,279,675,404,304,629,8,634,602,696,526,830,37,867,337,442,368,77,720,244,543,951,352,742,629,657,289,548,243,806,644,40,534,779,409,35,102,646,592,357,182,418,125,364,135,868,992,51,693,526,553,730,911,665,266,484,450,78,199,969,277,588,370,648,428,438,817,398,716,811,154,700,998,97,823,589,74,405,864,636,110,963,859,897,74,709,733,58,521,475,341,900,127,481,701,862,73,606,192,18,688,752,730,779,707,163,854,988,494,98,877,72,716,372,432,865,428,248,143,211,937,727,448,827,873,578,518,286,562,342,944,535,325,270,307,642,250,286,794,701,896,593,775,614,808,827,930,994,548,97,942,687,273,479,642,525,993,308,424,856,858,268,144,502,637,124,554,715,724,780,946,753,124,506,267,199,519,792,296,566,318,906,761,481,690,925,488,927,122,58,488,204,272,151,545,999,43,244,482,692,741,620,180,440,298,322,34,229,200,369,460,765,994,740,107,714,408,243,120,5,431,943,380,501,977,818,679,618,55,228,208,602,746,128,276,753,541,874,821,399,629,452,809,941,402,681,296,138,193,660,462,233,920,723,222,910,672,733,198,81,832,352,767,306,469,631,356,725,938,186,991,253,626,712,91,974,888,965,229,990,384,881,455,474,582,969,164,441,910,678,484,352,663,203,93,863,187,524,662,403,421,790,826,397,433,970,433,996,302,919,25,471,98,821,320,1000,283,151,120,221,58,507,74,0,989,280,62,23,850,211,398,927,34,695,661,496,774,839,192,647,344,804,46,603,612,251,117,289,34,274,686,755,748,936,511,759,706,179,822,533,222,163,769,508,160,348,555,696,809,772,700,791,566,250,50,409,447,565,653,595,922,151,735,368,239,639,349,823,558,369,842,218,279,68,905,284,830,307,756,634,378,843,606,6,261,742,331,336,956,373,890,139,78,405,335,384,457,742,698,894,757,806,363,742,456,689,641,344,255,257,126,809,202,451,453,547,611,911,455,259,855,447,327,704,303,630,353,202,458,575,489,52,426,113,70,98,86,519,568,269,544,467,3,559,168,433,204,965,856,59,571,824,820,410,504,672,630,268,936,776,597,45,751,845,836,486,885,486,363,604,825,17,628,309,425,334,412,907,512,135,323,149,752,340,312,320,24,818,152,983,435,206,790,950,548,701,200,137,212,517,402,257,384,599,646,934,109,401,496,584,587,874,992,686,520,615,90,950,378,163,156,253,120,408,250,989,831,521,387,534,229,945,167,188,89,408,418,688,945,330,345,552,982,70,202,863,283,942,555,153,794,892,86,712,210,372,850,562,125,21,217,408,601,535,951,375,878,846,753,222,348,886,171,368,525,420,812,716,445,76,852,609,320,504,585", +"604,792,991,323,681,509,116,530,967,598,984,379,561,6,625,382,607,33,496,234,960,342,100,893,847,125,964,893,553,55,538,854,359,608,334,534,676,35,927,81,373,785,944,602,484,453,259,671,778,884,356,317,95,60,133,745,659,94,28,38,848,904,147,897,466,845,701,157,201,134,451,549,997,428,288,439,538,267,267,924,608,288,325,360,912,933,34,562,150,66,119,679,419,801,760,290,228,128,116,742,910,49,418,330,773,637,179,977,862,805,402,696,644,964,908,346,941,385,999,277,786,70,631,334,244,56,879,323,345,75,301,679,546,505,150,822,939,977,122,53,157,222,470,633,810,809,639,156,399,293,781,312,133,819,540,766,912,198,580,5,413,969,979,520,62,256,81,854,254,170,691,556,705,798,218,726,941,881,499,756,764,361,801,351,415,181,416,134,881,981,530,420,42,80,447,214,643,320,540,292,770,976,289,391,251,826,482,117,493,410,206,568,165,546,709,256,876,86,234,836,340,780,829,437,125,77,347,523,252,571,291,620,891,608,651,20,418,655,277,582,598,355,576,902,726,448,498,843,416,442,736,45,609,672,155,197,248,120,699,149,125,832,757,500,531,63,708,220,275,421,620,149,954,510,792,229,782,810,816,958,716,80,358,849,975,540,649,445,640,473,550,562,651,806,83,948,44,400,991,963,440,950,144,944,486,237,789,917,420,237,440,331,798,843,513,534,325,927,189,113,292,172,959,191,157,661,75,266,146,481,294,891,156,89,725,910,808,76,429,534,415,528,83,833,138,911,208,99,657,675,323,489,934,46,724,561,128,522,694,314,281,286,531,164,729,10,350,253,479,474,314,153,527,667,917,483,946,611,730,864,908,303,237,595,95,968,454,816,609,151,898,856,654,315,640,987,928,970,135,693,916,604,81,905,348,536,72,411,980,100,460,452,214,393,722,643,574,68,253,651,488,202,86,60,517,153,733,563,316,523,81,960,970,864,215,598,912,656,531,777,324,831,765,254,582,254,670,814,675,781,426,298,917,25,242,624,749,596,596,176,262,375,400,139,916,941,292,50,52,579,359,451,384,802,620,154,39,708,801,57,55,54,749,613,113,157,236,591,73,886,201,792,317,91,743,329,350,509,2,636,490,609,503,524,228,329,53,487,373,370,494,942,793,292,963,467,633,147,233,287,701,434,8,84,34,887,473,573,181,725,186,904,125,741,588,581,978,224,297,859,796,316,646,693,37,966,759,861,783,875,179,98,417,119,166,557,243,251,101,96,572,955,415,195,297,943,120,725,197,910,103,361,240,554,530,79,388,969,792,509,369,211,848,226,603,113,886,720,325,851,173,595,211,298,590,845,577,736,391,243,759,405,287,152,887,508,422,493,277,922,461,281,242,942,450,186,682,632,819,187,598,409,826,56,360,831,356,709,161,640,770,313,227,375,517,66,14,193,919,826,132,862,667,700,524,75,348,176,658,432,777,193,18,387,572,931,194,913,220,827,19,375,326,752,301,695,235,548,780,283,372,844,661,189,231,803,974,912,388,603,307,949,708,594,619,554,165,386,523,862,623,809,732,342,57,995,484,902,654,843,456,381,970,990,131,172,941,297,722,163,391,686,932,934,871,794,509,16,989,0,553,500,370,416,634,430,418,859,136,912,805,945,792,67,867,330,169,97,11,814,484,826,199,2,959,294,648,118,741,881,16,142,538,102,90,537,833,251,283,609,197,810,42,128,856,887,218,700,295,248,59,135,773,839,690,409,161,780,793,398,460,998,579,134,636,132,801,476,635,409,375,126,701,829,535,201,129,916,392,813,59,457,385,424,721,918,789,818,170,377,981,444,500,903,308,155,137,125,304,546,207,609,332,496,714,418,949,523,899,663,723,50,677,21,844,967,758,754,351,224,210,798,577,75,210,928,130,234,587,807,234,723,302,491,380,432,476,597,518,557,551,290,16,149,248,515,502,843,857,882,917,545,791,953,333,746,462,405,320,361,972,735,819,422,859,4,167,186,375,25,877,668,18,802,684,927,344,410,681,234,162,538,89,940,848,243,187,329,154,358,902,983,205,244,361,364,771,252,474,459,558,30,242,937,646,270,59,837,800,697,766,871,965,952,359,4,80,455,873,751,977,710,114,143,938,893,310,787,972,533,257,876,310,236,24,337,666,648,872,325,804,415,797,642,615,340,675,41,204,248,390,194,171,94,743,577,468,293,382,258,940,348,51,756,53,229,397,244,998,306,67,310,773,401,284,887,33,772,674,600", +"451,56,77,391,528,365,400,145,406,555,399,571,259,127,875,471,406,899,634,505,62,449,619,141,333,455,160,713,485,516,750,146,967,388,354,64,584,22,398,555,306,712,154,913,188,561,886,904,299,724,915,931,176,961,170,428,826,623,10,739,909,273,561,346,70,734,867,440,786,925,978,349,377,596,408,854,897,45,255,372,60,938,897,804,468,316,890,727,679,997,722,977,939,879,680,774,120,154,342,475,890,126,352,986,647,118,405,622,20,886,661,797,847,82,515,240,738,934,570,99,745,720,413,718,451,22,285,338,20,403,55,870,254,553,184,24,343,180,843,407,323,48,390,875,663,122,762,359,958,938,33,627,314,644,306,367,957,400,653,542,580,480,100,446,986,806,792,845,69,760,598,131,175,885,561,96,920,699,585,3,198,658,299,434,359,44,304,307,277,154,117,990,883,511,805,901,31,957,832,581,257,183,179,718,915,360,358,272,123,29,469,887,608,919,676,101,866,429,793,762,424,793,849,56,265,138,676,772,65,955,59,224,113,612,496,943,163,417,467,986,726,39,817,748,608,728,439,913,644,117,950,423,17,124,211,57,287,667,102,703,671,96,947,314,634,656,977,392,414,664,10,960,98,416,468,529,687,254,355,182,187,861,522,793,381,543,28,274,8,887,253,464,7,327,53,246,374,990,578,856,681,230,525,448,886,746,297,186,37,139,852,995,207,721,810,395,96,368,937,497,221,336,410,342,514,368,203,488,159,33,188,612,248,55,786,92,269,861,999,402,576,863,687,151,205,156,798,827,77,391,18,917,782,6,320,842,565,994,237,94,558,707,247,994,924,265,778,366,752,97,495,631,243,777,861,198,661,619,184,531,869,511,174,127,337,922,889,285,506,980,277,338,400,421,375,685,582,33,559,832,456,176,206,483,876,914,899,783,919,503,999,932,707,703,388,565,127,410,373,702,752,89,875,174,694,297,524,705,986,949,631,91,944,561,552,9,43,325,340,952,135,659,517,654,897,173,67,803,621,35,479,785,636,836,897,195,290,907,534,151,428,655,794,606,362,41,659,616,361,669,914,690,488,858,610,54,982,25,661,995,207,117,471,217,176,915,792,964,376,476,452,809,804,424,215,873,878,274,340,888,552,316,341,861,491,474,829,115,323,459,317,407,806,70,50,203,879,803,629,992,519,704,132,757,114,251,706,408,38,105,23,530,583,734,690,880,714,141,238,884,77,848,171,614,402,530,572,269,660,717,418,448,130,834,736,225,551,682,71,298,468,406,262,307,935,600,40,806,839,372,963,77,908,263,283,618,267,270,676,316,894,218,44,786,437,821,31,161,543,277,980,140,917,835,239,104,786,814,243,379,599,526,17,536,392,305,286,431,118,647,68,375,781,579,422,527,361,63,42,179,139,450,79,320,331,410,533,592,764,583,139,156,462,34,859,592,499,914,144,267,147,471,761,671,977,37,467,177,107,307,327,646,728,326,161,374,321,263,559,762,163,499,570,374,922,58,496,968,762,207,393,709,830,735,962,330,944,528,784,650,957,276,208,531,868,361,449,750,929,62,320,465,601,809,822,832,6,507,874,827,7,536,639,713,653,507,499,776,293,522,458,18,785,383,734,504,824,621,280,553,0,178,6,999,349,974,991,505,179,920,213,331,156,139,639,317,55,855,954,797,69,174,388,716,814,419,654,417,670,939,89,567,409,361,802,360,928,974,528,309,964,693,653,466,29,533,116,240,678,68,353,159,956,602,844,579,983,435,810,656,436,48,946,466,307,497,426,381,244,607,735,917,353,600,633,161,111,781,965,502,670,683,391,989,706,466,365,54,697,235,810,855,261,964,682,360,99,517,177,505,553,300,204,44,287,560,147,412,73,629,694,563,94,379,744,229,483,909,821,231,190,572,843,884,613,258,486,746,391,844,288,142,848,526,29,658,348,208,159,243,577,145,124,133,42,682,193,637,412,896,435,335,190,588,636,799,504,305,140,322,194,812,642,374,303,267,89,503,445,716,149,101,542,575,878,297,76,311,311,652,654,136,606,595,547,598,972,969,674,258,518,251,867,271,969,459,138,307,740,524,554,844,108,165,616,896,715,865,166,104,935,586,822,839,402,750,310,922,505,815,63,269,168,88,900,56,144,663,978,616,738,736,823,688,620,581,272,610,555,489,963,269,910,916,51,515,85,874,311,905,814,400,320,688,534,923,346,288,342,252,981,73,264,643,580,552,381,641,572,279,162,269,872,609,580,811,258,27,185,539", +"271,337,617,359,416,595,21,879,206,805,973,461,653,936,209,984,527,101,531,920,246,121,36,911,932,566,480,120,842,356,417,80,283,923,273,456,181,75,364,571,622,854,344,106,541,463,710,318,382,416,283,75,598,332,603,878,846,71,716,162,163,799,844,169,625,302,214,603,749,426,183,180,81,215,645,939,563,583,664,250,963,487,100,651,587,916,402,840,466,108,968,381,65,344,484,571,914,274,138,311,862,12,550,836,625,464,904,589,536,366,827,952,127,585,770,647,124,589,181,712,732,253,740,469,941,903,431,875,207,878,583,86,34,808,21,215,30,329,251,794,927,268,380,33,614,430,702,619,271,581,594,103,766,619,179,948,965,673,720,579,113,732,909,418,666,978,387,419,74,846,697,206,838,678,191,149,621,517,905,20,726,186,375,6,267,141,462,905,298,256,592,576,266,782,941,138,827,963,465,73,87,671,532,121,459,308,165,780,173,735,315,901,458,790,256,742,82,536,550,628,704,114,732,977,755,405,86,898,993,622,712,478,798,923,197,737,600,101,186,217,456,132,883,571,221,289,376,871,643,733,558,268,602,363,99,2,372,1,566,945,543,400,204,59,437,292,735,419,530,195,281,509,295,455,872,74,670,722,205,315,884,410,316,328,192,70,729,385,469,640,129,401,250,148,769,143,847,301,413,323,960,857,516,427,452,771,606,831,253,765,795,500,966,726,783,679,201,178,644,197,348,292,91,849,923,840,472,546,618,527,172,210,463,111,237,742,61,483,604,223,314,865,829,272,697,643,536,229,871,91,731,98,465,17,13,329,563,53,427,982,428,875,894,324,227,505,158,987,615,545,631,898,812,686,124,620,310,294,146,101,940,77,363,197,872,550,363,106,881,164,823,704,186,736,390,974,221,645,247,623,129,690,719,387,192,566,437,891,86,85,152,116,55,249,603,527,555,927,148,267,411,966,722,2,998,528,462,88,235,599,547,581,30,559,881,960,974,315,312,908,382,97,205,292,991,890,502,722,631,396,704,6,741,443,684,842,6,3,252,549,253,542,359,358,225,3,361,39,274,990,444,523,165,890,371,474,658,494,193,970,966,500,734,550,400,757,54,977,361,760,34,12,53,576,972,410,841,39,668,81,476,20,373,826,245,445,161,607,695,340,152,14,156,691,558,54,420,368,91,962,274,20,570,664,265,638,483,151,214,409,855,457,838,895,336,960,532,334,463,152,963,290,686,194,838,869,514,625,13,882,73,203,716,790,650,894,781,270,817,389,509,29,428,785,211,145,463,489,576,397,79,125,412,144,519,952,863,668,10,250,158,668,276,625,336,75,898,516,186,714,458,648,13,432,105,450,685,218,851,333,230,392,979,537,630,181,973,887,425,227,710,209,269,29,63,893,132,322,391,925,104,229,760,974,945,714,777,769,39,541,318,560,68,811,311,373,404,618,856,410,913,196,504,520,535,724,939,489,464,151,84,590,897,467,640,674,872,450,553,321,631,712,103,614,967,9,124,141,841,522,939,106,535,329,1000,991,697,569,349,326,124,520,588,164,16,478,9,633,824,804,172,557,910,443,12,855,891,92,966,619,299,920,877,840,353,901,102,733,469,283,472,164,82,686,932,165,243,717,62,500,178,0,797,584,621,148,726,386,380,532,473,184,540,237,917,659,647,879,682,864,685,356,275,986,719,32,562,647,575,397,801,724,64,380,1,215,979,792,519,392,693,15,6,876,723,40,492,219,164,604,200,590,860,223,385,273,914,394,847,870,48,760,47,834,268,161,815,688,510,957,770,184,960,657,463,291,944,15,493,918,268,68,732,381,816,435,914,783,748,939,142,895,559,594,844,315,76,689,898,920,121,541,128,20,516,86,251,849,899,742,545,110,170,662,755,203,547,485,228,38,678,125,167,62,503,916,53,74,370,800,137,207,554,217,569,112,351,724,705,456,804,77,758,658,608,42,929,562,864,453,105,471,40,805,484,473,94,362,535,590,623,38,886,367,832,806,893,670,336,837,561,441,157,640,448,80,850,949,762,798,541,610,418,875,69,523,672,568,640,839,358,662,57,133,553,376,751,520,453,992,953,140,812,974,852,638,462,684,679,398,636,135,216,995,100,958,362,23,79,758,168,336,904,528,290,919,238,993,477,249,596,42,300,677,116,159,985,932,632,25,485,719,330,264,630,192,185,448,158,797,910,518,900,738,32,31,621,62,365,755,363,940,650,177,957,113,648,410,289,83,280,597,355,65,758,622,184,197,277,320", +"99,424,659,930,971,142,111,578,370,173,458,19,951,767,762,876,815,790,252,668,3,160,645,652,359,966,824,516,334,307,963,200,699,958,37,533,623,809,605,45,514,661,94,941,655,958,152,555,393,296,195,249,569,363,659,672,746,73,313,782,329,426,219,595,20,703,220,999,356,357,79,463,147,202,437,209,757,58,110,299,216,326,604,239,420,64,252,559,983,923,166,711,4,492,599,981,91,724,149,386,112,9,146,548,196,458,802,564,708,797,455,318,802,589,775,556,562,584,481,895,16,282,15,295,329,231,654,972,67,950,6,877,713,688,584,762,967,315,217,152,707,180,415,8,356,196,125,977,409,879,231,298,132,361,342,259,910,617,255,199,293,503,976,808,772,336,985,458,340,513,508,770,971,736,730,606,731,255,509,12,406,647,62,436,576,125,425,820,981,231,60,918,495,952,882,647,327,266,358,932,493,159,411,988,45,829,348,250,150,912,78,367,209,593,459,259,872,663,778,362,688,199,436,994,867,352,785,494,251,801,175,814,842,88,883,1000,713,86,513,376,959,694,789,968,585,262,79,834,128,190,193,52,205,537,168,252,188,912,539,697,176,304,307,896,830,840,885,380,754,905,710,223,651,105,341,226,758,359,214,649,637,785,338,544,613,387,264,264,569,776,773,685,65,846,476,817,650,41,365,912,21,878,332,592,539,531,479,700,426,240,831,297,43,534,371,575,456,676,143,199,887,359,138,979,559,789,376,370,223,16,97,742,377,985,610,818,154,443,982,42,791,943,326,208,33,209,40,64,724,179,764,2,653,157,706,622,71,833,871,506,921,988,1000,672,150,611,149,602,793,615,982,336,153,802,842,211,142,321,737,530,856,428,707,351,308,429,706,498,242,975,417,258,546,9,301,74,799,901,64,979,447,831,90,202,849,510,305,999,888,184,667,465,947,527,336,52,646,852,228,316,631,80,702,210,105,292,545,588,647,332,890,604,452,267,840,654,174,294,426,605,759,306,63,575,310,503,697,602,989,674,727,500,216,344,55,628,1,836,69,11,615,389,975,487,225,427,164,646,619,778,503,734,129,768,940,325,598,934,997,719,9,464,996,303,571,289,658,440,647,964,219,46,43,984,617,830,646,32,807,883,104,455,251,769,629,150,393,681,190,367,272,284,540,811,550,221,451,627,632,218,39,326,885,36,544,569,9,110,853,700,158,352,153,144,446,453,478,827,412,59,904,778,77,790,240,651,722,566,363,787,585,472,966,139,352,17,50,33,435,540,272,784,105,716,748,195,308,814,726,167,484,151,406,836,979,433,960,891,43,36,605,125,466,570,421,995,900,504,760,305,855,903,946,500,843,371,154,999,779,532,994,456,365,92,645,161,697,889,385,781,947,525,781,19,454,39,424,777,454,339,71,278,667,814,579,811,270,462,981,670,331,529,33,357,808,706,885,156,825,685,582,349,518,632,779,816,300,74,962,613,157,181,350,392,495,451,672,747,835,876,797,504,447,784,857,258,240,634,22,425,872,46,132,270,136,211,805,272,18,43,243,827,891,372,805,1,640,184,486,358,365,426,341,148,112,566,790,720,858,819,468,337,615,474,338,184,260,701,139,767,276,108,534,240,488,146,264,790,23,370,6,797,0,761,350,35,495,240,758,552,732,238,399,642,288,804,913,56,728,542,208,192,34,571,649,151,523,145,443,612,966,561,220,939,419,365,477,853,215,726,604,317,872,661,306,915,552,969,793,736,509,231,203,687,966,288,49,349,882,483,920,458,440,123,25,273,766,326,457,690,717,333,729,471,607,354,697,668,492,817,830,289,155,984,428,305,102,491,308,573,810,581,503,799,312,80,944,542,403,300,738,879,427,843,672,984,586,123,96,882,19,588,597,992,228,602,895,456,625,283,113,317,691,93,832,858,556,550,342,531,746,587,22,903,592,313,786,519,984,337,861,617,186,793,373,727,879,503,560,932,890,744,185,52,767,259,541,823,11,265,303,349,967,254,282,493,227,547,584,555,347,470,517,783,788,786,623,478,176,403,439,788,722,850,849,248,643,430,816,988,308,603,26,301,234,856,922,95,289,379,957,312,633,691,359,229,272,812,10,808,857,886,470,513,976,373,460,957,785,368,152,39,580,664,21,313,47,60,59,155,874,727,420,441,591,809,344,298,577,490,679,444,925,308,317,145,940,306,700,346,832,503,177,148,628,91,10,120,840,739,829,331,998,540,954,690,606,582,986,71,936,258,728,431,502,901,508,386,820,313", +"81,136,695,967,781,234,369,52,568,312,931,506,485,509,182,446,100,551,553,324,986,488,728,681,508,371,347,454,808,463,459,55,962,280,382,112,675,199,96,244,313,428,586,268,444,21,452,714,458,899,431,1000,142,36,26,588,910,845,653,575,681,70,905,596,177,375,602,156,249,336,693,959,837,351,719,557,794,891,882,651,697,351,352,572,532,764,137,470,349,860,106,367,424,18,795,666,668,152,676,580,357,351,296,33,276,698,485,949,64,773,228,169,572,709,790,161,646,215,518,684,86,466,655,381,856,618,819,736,894,555,480,328,610,479,792,450,765,76,262,690,149,21,469,474,488,782,498,831,454,110,787,996,786,194,673,985,167,923,608,768,840,778,540,619,77,569,3,270,955,322,603,780,723,849,464,180,3,323,782,373,776,597,897,914,827,424,767,767,57,24,461,271,88,345,71,323,149,576,659,112,306,321,586,668,943,914,29,272,73,637,147,278,823,398,404,723,821,634,602,399,193,309,974,769,233,90,745,371,125,347,2,112,518,278,420,102,319,454,28,908,115,649,775,297,290,227,912,119,307,904,798,239,779,972,668,710,396,742,51,739,449,196,13,66,952,375,354,465,632,669,681,736,365,854,370,473,51,5,920,515,325,281,706,26,546,321,795,495,628,745,671,634,716,987,213,622,435,272,129,150,653,7,383,796,654,267,519,279,202,870,851,504,256,225,803,582,43,298,871,290,88,825,654,318,343,956,630,228,325,450,374,699,450,620,511,177,633,70,995,172,971,704,291,101,965,828,937,360,458,230,518,361,634,675,193,91,620,401,916,401,50,703,716,619,773,431,24,73,329,390,335,38,268,284,463,788,686,645,77,825,11,369,418,425,445,936,997,138,150,470,257,269,918,809,977,457,60,223,984,330,975,772,288,208,632,776,929,4,622,64,126,203,754,311,7,547,470,843,807,261,343,536,795,521,727,468,848,779,565,399,42,584,506,478,625,841,602,379,357,703,621,104,313,147,737,961,314,750,735,163,699,375,617,393,768,670,49,396,826,247,397,226,200,439,556,11,87,189,201,443,33,308,194,698,873,548,994,840,126,124,55,670,74,454,744,376,602,758,477,684,440,769,646,718,738,846,792,637,897,868,885,952,373,956,652,377,571,892,495,822,158,2,806,632,11,47,119,649,718,610,864,729,159,347,947,688,414,825,49,940,643,899,623,862,703,498,751,605,164,557,140,219,657,112,462,867,146,213,60,959,385,455,231,196,40,689,853,774,159,352,582,321,370,804,863,418,57,668,135,436,7,568,195,461,7,876,117,345,598,761,188,207,914,144,531,728,730,331,95,842,713,774,789,104,485,868,322,231,712,291,196,568,78,383,132,179,881,940,908,338,70,654,305,121,680,30,598,670,41,65,664,396,22,319,151,754,920,735,337,242,706,620,871,908,609,839,76,901,50,292,154,100,672,400,985,805,707,624,922,708,608,764,890,40,985,300,580,788,993,717,839,890,38,914,288,935,843,546,849,284,323,468,752,48,312,964,723,762,807,398,10,290,758,120,247,519,585,785,232,33,701,239,86,597,890,355,459,904,598,750,926,48,766,522,170,698,871,569,281,728,295,107,402,100,687,781,524,327,850,416,999,584,761,0,937,561,723,101,974,128,642,105,959,425,220,407,575,132,220,539,279,348,524,924,856,690,789,185,41,478,648,134,686,574,564,38,769,908,951,399,840,343,93,758,532,316,503,621,825,642,307,119,267,621,515,170,602,913,568,781,526,700,440,380,156,564,1,110,885,27,914,316,946,416,485,431,497,339,820,92,358,54,16,326,862,279,848,641,480,874,12,954,432,629,61,109,490,557,927,440,115,459,477,622,406,888,83,342,193,725,777,287,137,642,512,447,753,970,103,559,174,536,273,873,437,467,604,598,883,944,386,734,38,941,149,62,620,48,62,644,982,545,190,295,339,530,10,401,932,38,814,631,797,916,88,489,588,301,247,960,367,679,227,162,149,452,149,562,437,644,776,378,512,276,466,221,306,610,283,362,767,116,347,61,486,240,787,208,909,377,981,286,273,307,339,641,97,391,358,107,174,119,256,815,133,106,899,532,489,564,796,810,413,458,330,143,121,453,730,717,6,396,484,794,510,356,851,967,72,882,562,837,215,415,625,859,16,177,345,782,657,852,522,789,622,802,522,999,594,631,604,511,790,168,543,979,942,834,212,636,2,155,473,904,223,500,48,128,440,349,165,32,742,682,416,28,384,75,221,414", +"131,669,334,986,46,819,898,733,80,377,500,892,469,459,504,32,632,769,591,959,749,494,472,910,786,502,158,284,371,196,643,978,664,608,632,823,722,307,722,245,235,625,917,440,568,598,562,295,390,681,87,693,325,246,719,125,407,425,514,777,259,911,294,281,418,906,746,6,551,158,679,562,850,725,868,466,960,321,704,74,594,90,992,225,87,211,524,470,135,447,954,124,552,223,243,242,865,378,423,943,622,670,953,681,83,690,598,756,376,725,291,901,855,891,720,327,857,468,764,261,900,652,534,342,519,147,984,974,633,399,563,181,262,193,483,166,70,361,428,39,211,287,20,787,499,472,742,568,539,807,594,344,97,915,736,740,701,396,478,747,197,720,351,623,336,668,983,566,423,789,836,276,274,485,997,401,409,849,645,286,157,430,935,729,968,32,694,465,242,109,717,507,7,864,216,219,661,382,247,362,436,981,808,116,691,456,73,968,592,443,84,192,97,598,532,854,852,68,388,622,760,537,592,863,697,434,231,768,813,54,895,161,230,663,336,520,357,793,985,562,250,779,973,770,740,112,725,174,17,27,733,471,678,775,638,457,143,64,107,733,845,985,874,276,701,72,890,809,626,558,859,850,237,768,548,586,357,453,566,247,863,541,960,203,435,281,582,703,682,165,187,822,953,165,821,660,404,166,79,829,266,849,908,365,710,468,275,753,449,403,683,917,609,724,615,770,125,204,32,233,717,313,67,733,901,470,58,128,859,400,562,858,29,158,205,862,488,138,97,204,577,485,778,228,398,414,718,303,907,281,380,707,323,992,699,457,269,95,399,854,864,943,915,686,349,751,621,236,418,902,637,289,993,676,317,79,831,259,593,829,135,568,840,602,799,889,617,819,690,414,695,563,59,33,626,79,421,507,609,300,350,90,729,7,846,205,672,211,931,193,626,178,994,743,15,23,44,113,489,996,916,837,965,795,294,45,3,642,331,864,431,222,50,117,972,21,140,566,41,56,201,763,761,157,514,319,61,571,672,624,308,148,246,331,409,546,299,441,806,279,374,327,978,952,168,704,8,362,634,462,956,822,779,73,907,695,349,658,269,154,66,586,731,51,32,709,694,22,574,212,359,99,565,815,122,744,560,104,787,32,992,88,74,656,494,876,912,551,741,925,452,12,487,264,168,208,665,654,351,183,829,299,81,265,117,876,896,954,209,711,501,99,325,600,153,406,952,771,864,816,685,7,836,571,14,227,496,896,69,364,515,823,274,15,885,144,502,20,584,125,629,854,24,33,454,70,341,7,491,307,237,907,638,145,299,988,732,577,170,855,32,56,161,562,574,600,176,742,930,735,4,182,196,929,189,243,793,100,447,520,495,400,666,305,779,863,200,697,485,295,859,538,301,875,670,69,869,625,304,756,770,739,425,281,906,544,581,429,142,567,352,913,903,667,480,35,134,548,206,445,740,902,187,578,11,853,689,372,367,581,971,200,949,762,616,958,58,936,868,51,821,551,998,968,260,177,184,943,179,981,520,409,593,453,313,77,394,578,49,586,854,514,723,739,244,386,226,239,9,581,804,930,451,636,692,351,527,769,102,728,854,764,155,453,671,377,475,597,21,783,807,433,415,766,176,437,662,850,211,634,349,621,350,937,0,501,967,795,909,662,159,444,815,681,939,476,731,69,570,903,919,260,21,323,897,864,478,89,583,275,911,104,898,581,861,506,339,161,230,912,398,988,162,964,388,896,29,973,18,351,671,404,348,157,142,172,306,332,811,158,35,535,442,327,921,1000,911,436,570,76,514,474,574,787,376,896,666,110,449,127,65,647,253,53,299,468,577,917,557,254,74,441,221,219,893,175,388,868,259,175,789,376,586,896,930,71,619,620,373,790,221,286,293,358,751,676,750,539,566,812,748,945,210,171,243,428,119,984,393,7,115,458,11,685,45,641,536,430,32,630,910,432,387,414,437,74,338,562,757,900,401,574,975,534,978,787,209,51,804,150,67,721,520,240,398,843,209,184,502,333,965,559,534,597,820,108,701,420,257,992,417,318,18,743,188,166,571,56,598,139,151,808,161,845,214,581,321,540,271,188,469,365,751,462,998,793,937,638,307,140,907,315,635,625,697,898,56,625,694,858,921,871,428,117,772,44,93,227,754,177,81,151,785,819,619,268,582,557,887,999,570,938,68,224,928,114,417,486,187,238,423,733,37,900,98,963,707,166,452,138,855,566,783,903,784,961,562,855,293,399,15,8,648,134,660,660,497,880,778,175", +"902,2,797,306,230,305,20,158,790,278,355,978,195,894,185,556,964,38,746,410,66,126,468,822,982,835,643,721,726,364,104,830,684,763,365,833,525,298,121,208,202,218,522,680,935,333,755,484,368,543,801,811,463,757,681,448,473,462,569,159,122,951,345,80,380,390,782,440,918,421,144,96,511,26,623,991,907,747,172,896,627,179,52,940,274,619,778,350,498,217,656,16,123,163,622,618,607,630,382,711,106,755,354,595,119,223,703,341,984,987,836,43,848,252,954,747,209,989,830,644,936,434,21,798,694,499,782,41,735,466,288,504,271,589,672,790,574,583,337,522,583,687,523,70,435,99,212,842,377,468,855,693,58,16,47,841,45,472,207,499,847,796,120,862,752,394,461,682,204,978,750,500,100,474,121,49,841,758,651,308,95,750,889,518,889,656,223,251,307,878,299,244,184,714,500,956,731,830,436,25,455,699,677,573,126,160,260,163,137,850,373,337,39,165,620,365,924,798,78,146,575,203,752,848,381,743,181,758,71,487,983,720,126,591,3,374,805,445,960,545,608,156,999,475,678,302,803,894,452,330,114,76,655,893,780,924,110,298,947,172,248,847,364,288,470,970,285,725,558,835,234,53,346,305,291,730,96,562,704,408,597,944,341,946,573,976,497,967,424,856,339,80,437,802,466,887,251,331,496,265,439,50,954,982,311,111,770,506,376,363,831,792,936,988,415,674,619,618,676,484,717,359,409,436,456,502,846,153,912,213,565,178,165,803,351,861,967,921,681,268,845,965,719,769,636,340,14,255,449,533,5,837,205,25,232,544,306,444,300,516,412,335,310,338,180,145,59,163,139,129,535,974,320,84,774,574,18,69,591,380,690,190,69,182,983,243,813,527,399,669,542,358,964,152,753,80,476,358,743,118,46,717,575,663,565,930,464,304,949,542,648,892,647,338,636,722,26,812,979,840,455,82,610,128,356,358,622,812,717,292,271,98,150,449,191,611,709,109,549,148,210,353,286,559,809,741,925,120,122,372,111,523,676,690,429,452,146,963,576,508,822,751,261,955,95,295,710,664,233,58,124,499,878,499,590,960,527,387,36,389,394,290,427,176,743,432,376,486,130,612,20,238,233,170,731,802,443,505,217,585,538,813,124,600,433,207,422,401,830,170,390,37,276,813,393,381,957,351,876,546,544,890,330,552,852,585,834,480,47,323,982,165,475,614,645,532,372,446,59,762,819,512,870,839,485,115,945,901,37,437,434,963,823,644,673,574,690,696,906,924,170,176,997,57,661,205,726,457,901,429,492,450,885,898,171,688,349,50,172,621,967,764,533,156,727,23,771,243,539,550,655,299,185,809,736,738,49,554,516,565,724,328,896,240,729,50,216,219,236,268,669,809,24,73,931,969,354,950,189,263,970,368,629,661,667,812,792,109,529,162,730,754,957,576,523,754,150,203,194,319,799,584,240,49,609,631,201,565,768,865,709,292,224,41,969,512,86,881,487,709,863,433,169,838,764,850,87,773,459,26,963,100,353,71,157,537,640,583,836,385,317,175,927,997,888,834,58,912,358,25,807,736,86,709,755,756,69,891,616,557,778,50,300,67,69,421,639,379,117,34,465,82,532,178,997,233,189,379,398,430,974,148,35,561,501,0,255,63,776,647,685,703,364,449,530,506,210,382,743,8,675,260,551,833,795,554,701,15,271,849,802,277,24,856,742,458,818,65,311,227,388,644,622,680,803,670,690,651,636,764,691,255,764,528,776,885,924,379,250,949,675,78,431,421,41,31,54,733,770,426,596,60,734,380,195,18,82,809,744,211,102,729,973,311,107,875,250,566,441,364,450,984,474,850,854,754,801,708,465,842,308,471,321,657,905,791,994,331,714,691,358,164,215,213,511,768,599,372,851,792,24,322,105,693,500,665,13,267,96,943,377,155,190,834,724,500,290,881,60,292,34,346,418,438,62,941,175,138,843,567,848,899,41,884,465,806,568,373,574,438,79,927,805,666,716,512,855,968,608,391,539,775,271,97,856,239,332,173,768,918,211,845,586,929,783,921,874,177,442,235,687,758,319,199,249,453,523,512,701,90,680,257,894,841,784,849,870,294,801,442,77,229,638,845,945,671,753,694,357,324,403,614,608,141,15,893,211,877,730,957,202,204,399,743,866,583,411,831,501,476,434,124,516,660,69,767,459,619,415,609,792,942,243,434,495,104,519,4,929,622,886,226,727,867,379,235,800,718,770,741,970,232,166,868,639,758,748,958,123,703", +"314,568,375,796,837,924,653,218,262,78,119,606,814,986,327,752,52,771,734,851,552,142,303,387,463,19,632,715,625,36,183,794,782,336,365,423,238,386,676,958,468,540,588,14,696,843,664,553,83,708,545,400,404,886,929,349,550,667,701,73,34,365,283,67,919,871,325,409,474,650,697,209,438,472,855,500,506,182,450,511,116,907,207,179,564,594,502,934,180,750,393,284,49,995,489,323,639,257,892,665,565,205,947,723,492,594,918,55,18,735,253,833,441,682,931,360,705,982,800,854,998,422,92,750,363,144,389,757,494,699,773,548,79,540,967,277,199,150,373,738,358,642,124,284,898,491,570,203,765,808,59,152,580,543,171,170,538,692,476,816,15,811,364,208,9,748,758,40,457,10,648,15,301,494,335,98,990,948,390,272,842,163,668,983,849,806,744,464,257,158,405,836,690,416,480,16,28,927,338,784,584,685,147,160,82,990,414,950,324,202,831,805,523,459,590,218,534,236,881,268,107,467,241,278,580,496,540,739,973,506,952,584,145,255,57,831,134,242,96,283,490,233,935,307,420,951,333,575,832,637,11,507,331,42,938,321,108,226,866,995,944,174,189,84,967,181,396,636,471,287,311,442,285,318,410,221,774,558,974,908,266,714,903,981,770,335,424,155,275,494,512,114,591,672,349,135,162,179,257,851,795,765,587,882,342,870,11,51,434,616,476,648,63,61,532,561,400,622,200,378,196,530,173,732,72,187,381,203,529,172,423,101,57,478,303,855,868,547,912,253,334,502,482,812,399,877,21,555,674,759,88,624,694,552,855,591,454,455,255,173,150,669,399,80,853,537,378,179,273,964,100,430,849,353,789,767,786,181,98,8,742,591,402,277,795,663,921,923,380,591,622,522,13,900,803,46,632,955,418,237,609,310,905,3,272,726,668,190,760,648,839,124,505,200,80,394,48,46,95,2,968,81,317,581,252,32,709,250,148,758,249,229,584,75,888,682,345,885,482,697,457,813,133,288,826,177,108,723,662,978,871,398,952,382,846,706,252,498,925,775,290,180,831,440,164,481,397,830,646,368,920,663,468,412,547,761,13,913,623,723,706,346,374,588,855,319,985,660,723,426,672,416,141,99,873,943,365,668,269,120,349,136,175,605,490,505,29,505,704,629,801,279,540,683,626,841,508,294,451,298,447,99,70,772,335,627,354,312,309,194,367,109,205,832,106,884,647,758,808,75,159,490,19,945,124,763,237,12,305,241,997,153,650,662,752,858,794,288,800,89,267,972,200,143,489,888,266,954,34,963,560,442,207,545,126,594,731,249,271,553,823,164,89,928,756,594,938,891,904,960,637,57,594,151,147,517,197,753,924,512,377,735,443,2,588,186,204,902,707,749,273,361,900,718,140,901,720,987,123,702,612,125,95,979,177,441,321,576,782,203,588,144,508,178,992,709,593,735,556,234,511,537,255,719,469,315,411,771,592,748,561,485,561,680,846,531,136,247,306,625,40,602,749,323,954,264,10,450,118,311,936,665,696,82,508,160,733,934,868,853,678,62,949,644,326,191,203,729,842,254,301,856,460,661,401,14,472,926,440,516,593,690,195,377,684,490,658,823,312,966,923,896,687,966,662,666,184,468,927,418,991,726,495,723,967,255,0,41,935,909,571,156,680,901,290,975,542,975,351,558,493,984,172,933,822,4,910,122,118,852,409,862,545,788,128,138,838,875,327,549,583,61,771,197,481,798,949,541,675,429,926,570,869,696,129,961,924,600,899,586,735,872,130,985,866,664,768,445,704,254,2,426,298,148,515,242,469,179,838,953,363,202,936,207,429,527,47,783,536,450,463,119,591,832,152,73,622,844,626,615,859,399,493,408,554,361,339,821,740,436,355,943,911,77,435,211,424,729,715,263,815,618,904,515,32,809,857,539,122,809,356,450,197,690,141,803,554,131,896,366,468,787,856,622,423,31,75,593,594,756,343,338,596,941,679,683,444,269,404,742,986,901,759,884,715,36,621,871,747,786,443,740,523,163,384,870,866,603,576,210,292,566,944,809,716,293,278,429,517,38,443,981,887,260,615,483,500,838,114,474,836,587,203,364,386,157,694,754,563,446,67,94,857,565,440,822,550,300,143,464,903,429,766,578,969,652,640,712,812,147,305,220,493,442,658,139,299,888,615,603,725,897,11,945,2,503,792,381,472,370,986,130,808,77,270,729,607,781,7,531,45,655,850,765,502,441,760,908,146,213,751,682,679,875,36,312,35,136,871,438", +"436,584,721,625,541,312,498,976,773,33,801,285,112,87,232,39,828,890,87,471,351,598,907,959,380,706,528,137,465,291,459,143,598,376,70,779,629,479,440,111,821,891,498,982,464,906,654,386,200,657,784,982,409,506,324,139,958,210,16,226,291,171,383,65,856,733,484,888,306,890,373,873,713,783,693,446,509,216,276,594,865,667,925,25,433,939,65,692,61,433,655,162,381,315,424,241,530,348,330,363,225,309,894,798,267,860,679,873,733,145,826,548,48,531,528,222,170,326,121,151,507,359,164,665,427,136,319,275,150,532,862,99,150,802,61,207,963,468,844,491,623,863,989,723,456,952,230,324,503,946,287,218,183,818,834,825,780,626,830,773,387,937,506,283,591,797,947,247,694,47,652,202,709,825,253,740,845,345,341,688,9,212,415,505,609,305,988,483,583,915,295,326,446,670,270,919,293,48,430,647,965,475,200,729,238,317,218,186,685,410,471,419,645,546,192,484,487,433,545,173,412,437,449,970,489,329,536,831,360,23,176,805,261,245,426,85,730,989,111,912,19,193,948,635,647,542,984,980,3,683,820,209,620,229,742,425,858,273,40,549,867,148,701,447,285,994,533,291,409,301,379,296,964,115,317,375,976,638,413,271,768,176,721,177,954,639,65,125,462,589,827,555,688,315,502,338,257,222,77,471,946,422,312,555,215,679,886,119,773,463,370,83,142,715,740,712,991,852,504,401,758,248,852,941,599,486,297,627,330,400,710,293,758,978,298,142,250,746,92,694,67,659,653,154,726,140,191,853,870,799,217,868,112,337,21,898,163,711,606,159,945,411,164,161,827,389,883,772,631,725,894,213,789,191,512,436,825,669,763,827,897,863,242,419,935,65,677,113,418,820,9,547,860,145,462,593,943,216,58,207,256,849,389,838,658,422,350,961,298,886,871,930,677,459,748,744,303,637,918,749,287,735,127,104,97,391,547,369,474,467,464,573,172,183,782,980,333,518,154,144,704,223,873,439,16,287,805,49,951,876,605,479,204,575,517,701,244,713,530,917,839,897,359,585,484,755,553,393,640,151,132,451,765,867,953,149,741,69,708,222,483,118,400,878,89,598,946,535,674,145,144,616,117,967,903,527,723,268,361,785,679,638,191,250,958,782,748,121,67,945,724,194,228,881,641,910,548,491,390,846,517,720,296,697,27,122,647,634,336,620,117,426,99,589,964,377,226,52,456,901,226,197,504,310,878,392,485,946,96,380,796,654,864,416,735,784,872,690,633,716,545,503,489,409,329,142,283,879,774,457,720,428,633,346,425,930,449,766,922,221,471,398,210,453,808,591,535,839,523,120,879,772,561,590,949,510,671,15,865,562,992,673,525,262,705,617,843,173,238,103,363,690,923,753,3,328,411,423,395,919,390,222,122,448,525,422,945,171,951,531,956,216,23,245,660,757,892,897,49,215,979,559,592,803,476,213,726,349,886,299,261,820,950,739,212,673,573,814,273,621,393,228,24,775,83,557,734,615,993,244,827,26,295,471,789,300,263,19,144,67,341,154,20,180,369,561,564,424,481,620,879,875,722,383,874,237,194,675,900,57,533,511,924,657,380,819,654,562,286,437,814,332,597,102,168,959,475,976,34,859,505,386,240,101,795,63,41,0,5,696,262,580,105,97,732,754,413,378,586,228,741,152,484,314,171,474,918,79,826,91,869,189,56,114,906,171,893,456,229,124,12,904,602,87,257,408,263,670,715,588,994,377,316,817,83,863,671,727,166,998,218,632,23,426,60,884,931,607,216,569,123,427,115,895,498,933,83,364,410,408,411,972,866,513,756,782,574,67,622,98,815,932,429,191,448,430,501,629,55,232,102,758,548,522,374,468,605,14,317,672,515,598,961,272,323,523,586,324,481,679,532,885,400,247,214,565,112,843,285,471,393,584,603,168,413,282,108,773,33,809,664,128,438,459,578,178,549,22,716,858,82,893,737,656,508,632,179,892,378,946,996,54,79,262,633,447,74,213,551,357,540,601,254,629,610,708,528,920,912,225,807,323,844,298,71,838,105,520,8,271,296,389,54,621,920,767,521,619,150,508,202,706,158,896,60,726,35,232,621,573,660,817,402,617,799,900,605,587,154,252,879,288,745,936,615,979,237,967,535,970,404,386,782,243,787,43,420,860,616,330,518,787,209,141,54,786,395,17,671,315,574,216,689,229,992,569,568,649,896,417,501,996,7,364,700,579,839,791,49,761,327,826,763,719,545,555,397,475,29,484", +"979,294,220,65,235,678,915,574,330,570,781,534,512,578,742,247,162,432,355,629,802,420,175,983,168,454,287,119,30,965,563,402,671,415,627,136,649,265,147,802,954,252,791,215,849,837,635,666,467,572,452,674,908,249,896,39,253,877,893,408,311,644,533,441,65,313,756,70,126,80,475,540,620,446,834,777,581,113,773,149,550,366,530,987,194,467,621,896,13,629,939,51,280,124,88,329,412,177,803,103,291,428,994,975,867,445,269,306,987,708,237,56,283,379,440,887,684,461,585,566,493,128,887,536,356,842,173,761,383,859,160,490,512,941,431,1,810,714,949,781,757,392,905,569,966,247,767,302,927,85,151,228,973,453,261,251,885,87,207,290,589,383,980,256,831,805,671,279,448,965,202,843,355,271,485,218,402,839,405,390,894,453,528,581,778,516,574,755,151,426,568,105,695,159,753,874,407,244,750,854,867,308,445,428,927,892,338,39,201,612,725,824,362,162,727,421,475,937,541,771,243,980,377,434,621,324,762,367,226,598,37,24,940,295,785,669,818,11,566,371,928,568,338,762,796,827,371,999,234,892,598,753,614,318,939,621,179,811,253,670,263,193,185,801,25,969,127,597,604,951,879,239,608,430,81,704,3,746,913,389,384,658,736,9,493,13,817,965,63,621,112,667,987,696,227,32,150,165,501,912,850,448,305,173,679,210,727,299,814,975,254,380,287,554,281,402,232,374,467,451,5,21,982,310,85,950,342,55,483,449,810,147,875,691,89,605,510,379,744,781,210,870,973,225,546,98,236,95,998,524,793,88,916,527,406,362,165,762,943,294,451,81,2,688,880,330,582,892,961,96,438,8,33,357,808,683,902,336,403,99,742,448,637,846,591,557,726,270,802,412,808,650,509,222,104,335,655,596,185,554,88,773,388,309,819,418,85,160,124,480,966,244,375,434,776,82,233,489,471,1,351,138,477,469,367,393,357,388,495,415,376,686,231,478,922,115,179,110,960,408,856,616,992,215,889,169,949,425,300,524,51,980,376,615,153,492,896,631,275,86,847,565,749,746,870,452,994,907,718,906,554,8,587,301,900,633,977,595,474,337,300,600,590,855,70,399,483,106,699,387,839,817,898,846,754,802,498,740,84,620,37,742,707,28,804,520,110,793,581,777,784,607,904,742,388,135,942,579,319,609,550,725,435,344,826,521,120,758,669,281,791,627,198,781,926,764,442,613,482,889,755,561,358,897,633,468,687,998,550,693,618,244,510,945,537,986,270,229,558,634,796,817,298,757,395,332,55,428,775,69,976,795,880,676,861,13,822,452,660,336,153,657,717,702,178,524,657,791,156,124,89,968,172,34,780,259,751,43,630,393,492,522,513,188,239,690,847,81,305,804,468,55,443,34,849,174,880,334,329,704,335,707,436,691,241,306,549,270,851,998,339,504,691,876,98,666,454,81,81,490,69,690,132,433,2,158,651,307,285,44,162,779,690,77,372,204,309,873,833,458,66,160,924,405,395,709,759,517,330,36,423,558,435,485,315,75,853,148,122,417,12,190,23,166,200,269,932,836,920,611,409,654,310,342,596,309,60,493,327,682,318,230,493,435,607,694,98,717,708,398,344,585,662,720,557,771,687,961,695,136,179,380,758,974,909,776,935,5,0,816,427,579,357,939,840,280,334,814,500,365,313,350,208,747,760,600,592,813,169,351,388,42,664,261,522,273,888,156,409,607,666,449,649,771,970,509,138,950,4,60,452,470,675,617,519,873,370,893,915,908,805,433,186,761,531,411,745,375,339,109,422,575,458,999,343,369,817,897,11,193,631,590,313,323,855,629,645,247,946,102,107,351,533,875,524,663,841,826,235,56,875,874,222,334,860,346,118,154,138,821,636,222,402,923,391,928,578,265,890,306,18,247,484,852,308,124,550,908,949,801,26,970,737,625,731,191,698,709,463,656,37,642,201,358,847,456,231,982,352,986,161,44,664,301,363,889,148,258,502,762,139,864,817,399,697,301,324,799,477,453,904,148,809,743,543,832,578,604,229,556,350,604,190,42,365,123,3,644,139,160,578,782,491,561,559,276,515,725,693,915,829,218,671,257,742,395,388,92,710,94,178,773,433,30,540,898,636,327,371,45,37,917,221,98,172,739,373,802,763,696,460,788,328,929,287,235,7,904,919,847,588,254,212,435,463,827,292,594,345,859,433,101,856,778,754,502,229,904,475,548,395,559,381,81,245,743,751,691,964,578,644,253,609,381,299,969,125,331,391,448", +"634,362,739,379,391,123,933,134,839,440,571,717,280,674,702,742,171,513,260,352,515,614,258,278,1000,835,892,448,674,457,397,518,878,982,865,593,968,511,364,80,935,988,928,560,446,250,100,424,363,249,932,139,376,267,565,953,225,613,855,527,570,576,929,319,269,967,426,485,720,299,940,484,233,49,260,947,747,656,701,103,476,894,446,911,509,818,263,499,836,461,946,362,434,498,103,126,608,628,10,560,888,248,626,50,339,45,900,839,766,47,69,171,140,512,755,575,63,64,918,652,221,813,903,433,331,181,336,884,588,991,369,157,997,364,985,148,680,982,438,427,648,996,356,363,815,23,796,263,840,679,747,784,455,400,233,777,268,216,856,790,768,141,943,649,652,705,564,255,345,759,966,603,514,163,194,646,575,172,228,635,563,249,609,844,926,765,889,243,647,462,585,740,962,399,676,444,658,293,803,716,993,611,118,264,30,183,825,466,131,371,919,312,406,853,272,983,21,12,251,666,256,9,607,231,987,609,468,722,772,172,401,187,88,350,853,641,327,525,364,431,383,110,893,989,148,493,752,188,268,514,890,982,112,220,920,890,618,427,925,630,192,848,495,160,995,551,151,761,678,636,341,129,548,898,214,903,884,944,447,632,268,165,633,50,35,458,404,467,743,12,357,391,239,730,991,340,500,922,548,418,691,261,580,482,200,527,130,540,806,183,110,409,284,940,475,991,682,852,364,159,665,476,472,379,853,563,411,88,588,79,30,875,730,786,67,240,741,210,90,330,852,956,896,36,618,905,117,334,644,687,717,849,978,905,660,191,801,972,216,441,832,332,930,652,894,678,458,328,971,159,87,813,25,296,935,483,85,27,601,211,754,464,136,805,541,518,214,233,796,992,496,796,247,686,873,164,672,778,475,606,883,905,530,879,704,501,259,819,664,505,835,531,52,980,161,845,939,918,605,669,610,684,742,197,982,343,388,21,11,196,915,766,522,207,780,954,901,133,30,484,181,929,614,452,714,404,964,218,408,989,710,454,141,561,357,614,994,89,935,596,954,453,324,671,579,252,986,651,404,666,586,302,922,188,174,593,239,888,170,551,129,883,380,444,836,250,832,206,825,952,131,604,46,445,648,74,29,632,778,113,552,107,281,400,561,478,307,524,64,708,962,679,472,807,339,839,967,655,253,361,524,133,379,738,5,969,997,272,339,207,355,694,310,206,389,852,532,430,504,419,212,417,832,760,325,675,693,233,535,803,24,337,865,30,406,421,46,166,984,328,551,734,935,5,727,867,804,730,241,977,737,497,515,448,485,631,794,205,28,513,658,981,864,544,94,944,83,362,707,102,943,49,944,354,46,508,375,419,350,678,450,110,752,998,539,816,953,160,534,668,387,21,371,888,910,518,890,430,887,275,342,747,159,839,912,134,546,836,687,933,552,991,765,323,968,826,556,83,280,233,610,112,369,286,739,870,350,604,318,514,346,928,891,179,971,542,846,881,416,152,917,493,603,636,96,555,985,582,930,896,448,114,612,23,356,515,662,697,312,680,517,36,597,866,208,442,470,561,659,734,419,924,717,158,838,522,533,517,9,3,842,455,990,727,675,414,475,37,321,760,818,40,82,750,575,209,366,144,661,912,920,532,552,128,662,647,909,696,816,0,306,373,928,242,359,726,758,301,248,749,562,883,145,13,46,875,785,896,533,374,310,702,855,698,711,593,554,183,815,920,106,44,393,184,609,482,148,271,3,550,609,713,42,812,289,581,634,715,924,548,135,587,930,486,810,610,1,283,590,830,413,871,986,896,907,961,644,160,92,503,368,993,399,424,456,169,330,575,113,70,252,779,806,858,963,303,659,247,943,868,980,787,167,532,522,590,530,150,183,882,265,103,99,189,565,35,685,941,186,888,288,658,878,927,803,208,630,751,57,994,589,383,110,257,155,54,889,776,439,995,708,898,580,697,289,264,125,402,84,203,322,272,199,64,226,7,881,43,215,581,361,671,370,401,845,483,152,336,50,696,525,975,652,185,443,211,60,419,801,339,620,680,615,785,922,337,892,510,595,483,452,322,704,519,690,168,798,506,725,98,955,325,212,658,392,834,457,421,350,900,780,261,770,209,133,741,306,366,482,91,159,315,704,523,58,67,284,548,820,718,804,205,785,870,603,875,76,360,358,103,29,144,525,720,3,875,911,620,590,843,669,50,794,507,831,129,669,95,201,746,865,787,162,884,376,633,823,783,464,62,361,873,689,884,178,192,771,401,228,237", +"63,421,464,201,594,445,398,895,508,609,800,737,94,972,373,931,234,368,989,873,580,302,568,129,658,588,133,193,538,22,452,451,777,218,949,385,860,911,381,415,813,244,550,649,408,916,575,590,302,99,143,261,30,69,851,953,521,709,213,717,860,210,456,450,554,606,927,548,142,895,846,997,879,616,759,916,237,341,221,369,131,252,712,953,295,441,381,926,907,59,691,404,351,25,468,705,885,547,572,104,593,712,595,326,82,361,692,774,170,179,878,74,412,908,546,449,261,621,707,620,927,286,933,633,200,637,383,136,359,474,364,918,831,761,949,52,220,881,265,684,951,737,936,653,848,344,427,369,45,317,279,760,428,758,705,820,639,317,317,612,188,702,379,527,891,66,89,764,400,802,963,343,383,534,565,338,438,766,748,484,675,593,302,191,290,153,13,686,504,572,521,437,109,199,205,442,575,269,854,780,904,657,897,624,48,744,691,988,468,86,641,555,394,872,355,197,959,767,749,265,594,150,445,368,109,384,784,852,685,83,190,891,620,72,8,87,209,935,773,270,595,822,221,219,342,320,339,754,638,411,301,392,975,809,289,402,572,547,632,853,830,433,680,899,342,344,556,54,900,898,183,316,569,645,512,201,172,546,508,791,389,587,272,454,182,616,690,967,345,947,143,162,643,725,958,435,639,917,754,340,522,37,740,791,121,36,332,45,698,183,25,948,264,778,36,272,931,424,825,875,776,732,665,68,769,332,721,866,692,28,260,142,283,574,846,334,787,39,271,466,939,468,480,22,447,266,190,501,576,148,275,144,192,267,379,261,538,593,742,60,980,954,840,201,252,689,270,835,400,674,811,808,706,856,849,223,874,37,992,681,726,771,413,663,58,635,121,573,542,510,995,485,134,597,419,101,584,163,505,146,846,559,777,140,514,397,545,277,770,441,116,799,94,506,826,305,456,718,501,492,824,728,47,39,483,181,529,3,487,500,949,47,966,236,945,397,850,45,674,426,569,341,292,478,154,920,960,332,532,321,348,379,586,789,155,321,372,793,285,617,972,105,559,688,365,760,941,633,218,208,91,552,385,329,88,411,892,437,458,29,911,599,310,13,133,896,973,579,810,821,659,454,341,213,439,922,257,469,873,627,602,161,661,901,277,238,233,776,343,699,962,186,474,164,821,46,832,614,944,445,574,928,25,920,203,556,684,832,599,795,272,508,773,396,168,560,474,877,809,456,298,572,465,736,23,971,162,374,710,335,17,393,286,730,772,266,327,619,138,215,236,656,3,776,832,868,639,539,167,79,416,572,400,982,239,631,389,544,396,270,646,411,13,70,441,450,13,687,198,66,426,258,794,4,273,273,874,165,375,973,489,275,731,158,710,592,668,947,181,211,183,764,614,932,75,952,495,746,258,110,663,158,602,698,829,139,748,30,876,42,895,679,300,230,964,4,126,510,562,258,418,978,118,289,823,931,440,852,179,266,488,77,48,672,433,512,228,227,341,425,643,130,25,762,752,300,256,445,161,69,853,3,137,68,447,234,172,645,237,389,990,647,704,840,436,230,754,606,644,463,51,246,607,11,314,734,596,447,503,123,898,460,241,622,92,606,175,778,163,774,337,586,448,755,190,106,474,421,496,805,213,473,732,642,159,685,571,262,427,306,0,97,940,927,274,649,74,737,157,817,585,106,801,981,79,652,720,524,140,374,875,558,815,4,39,343,182,91,463,570,549,459,927,323,885,764,795,983,802,225,238,209,500,555,794,887,707,350,446,45,895,843,41,912,498,248,879,854,13,616,753,476,176,111,579,244,881,930,137,831,460,697,332,573,917,448,662,662,264,605,988,693,522,679,20,754,675,952,632,557,461,657,64,867,425,41,175,155,116,569,35,982,750,833,552,137,723,354,220,988,899,588,768,877,574,152,649,604,651,464,503,568,189,706,875,172,371,104,656,603,541,97,415,579,682,755,966,352,709,24,529,157,950,78,948,929,699,291,389,988,971,231,888,186,431,557,807,836,146,574,738,446,387,214,287,150,393,670,931,29,639,372,815,984,691,3,87,288,471,841,898,411,727,573,45,547,179,533,607,61,295,816,327,635,666,389,827,416,17,938,510,786,638,482,909,83,42,465,43,166,20,248,237,89,758,832,570,905,961,833,457,25,94,884,298,556,326,907,383,614,582,114,117,754,761,704,110,591,215,948,177,744,688,461,279,838,427,256,790,918,407,734,259,511,458,656,300,438,993,607,59,771,6,551,854,903,585,816,243,566", +"164,304,67,693,274,105,893,452,660,216,623,217,470,675,982,51,213,587,829,895,556,228,258,694,418,201,501,349,774,479,800,96,524,381,567,794,647,890,81,476,420,76,664,489,27,81,610,782,356,117,856,752,684,582,345,320,511,588,342,731,521,370,62,282,495,832,14,184,245,54,515,485,86,656,546,151,801,969,350,935,218,882,762,410,816,815,993,528,552,248,602,378,425,433,160,853,699,380,343,149,905,168,41,750,943,681,404,321,823,891,984,481,939,496,831,168,322,880,652,3,409,664,892,681,710,35,72,473,776,893,851,442,290,130,664,82,351,308,435,340,49,657,642,399,247,22,296,118,35,231,132,967,4,475,516,625,111,674,674,63,5,986,208,298,514,952,945,533,688,551,860,429,681,874,676,85,352,430,91,15,779,35,321,397,139,194,316,175,620,919,480,679,779,215,104,608,538,16,753,8,630,717,461,544,665,595,52,80,862,691,545,939,436,137,220,789,384,672,516,61,633,850,791,790,581,328,972,157,124,890,540,285,823,729,599,620,720,253,307,889,668,607,991,262,940,116,810,210,364,904,900,985,900,766,293,459,741,456,990,104,273,880,212,925,387,200,563,617,341,112,907,437,775,627,933,479,724,252,135,564,209,181,126,529,431,565,601,402,165,826,70,810,856,385,325,112,55,703,747,553,819,970,229,536,35,715,402,380,891,244,170,621,793,423,82,844,166,321,809,261,925,25,368,8,558,703,222,70,660,447,882,615,830,662,464,261,242,316,749,173,91,191,757,357,205,722,582,17,24,191,629,823,678,86,851,417,5,826,333,674,871,140,889,202,430,659,896,662,321,762,680,691,759,156,735,669,42,295,889,795,48,559,375,509,693,473,865,393,235,891,853,168,898,444,94,131,243,759,434,302,650,116,746,591,653,184,78,30,524,903,848,464,850,786,224,88,96,146,172,491,626,819,71,353,151,740,138,197,171,803,938,3,615,250,33,869,335,241,522,967,225,326,942,137,294,485,985,671,655,36,403,50,219,754,467,84,891,549,686,805,520,900,749,599,269,98,980,470,43,424,973,88,212,427,674,493,87,628,165,783,570,727,515,547,972,16,994,973,283,17,469,62,823,653,537,17,131,297,669,357,109,632,492,888,827,324,701,329,616,854,382,609,645,163,79,144,405,864,166,988,800,73,210,494,319,481,401,260,221,407,246,196,496,405,238,611,858,172,978,769,763,32,664,341,101,408,567,427,11,106,216,304,794,904,39,56,389,243,569,170,728,835,707,863,347,250,580,909,700,679,149,729,318,933,214,960,422,134,723,637,364,777,534,627,378,892,528,285,829,966,351,962,367,774,675,52,864,277,959,719,623,142,498,990,331,784,137,277,269,201,295,716,804,349,607,745,366,459,754,821,664,985,404,114,544,120,727,922,337,263,468,157,371,339,47,265,22,317,880,55,290,64,226,201,488,609,781,157,468,607,422,989,77,165,140,26,134,895,734,797,139,835,545,473,327,26,560,968,974,847,293,876,766,613,8,114,931,75,54,384,567,622,339,362,148,166,76,591,83,578,710,76,422,369,251,903,755,864,275,450,284,339,469,936,927,269,63,100,517,26,796,342,302,79,477,13,634,274,774,945,331,184,238,105,444,703,156,580,579,373,97,0,424,336,129,488,311,645,442,401,287,692,13,605,951,225,793,929,760,610,718,604,247,323,304,682,132,518,542,49,856,752,651,493,553,185,587,752,52,758,612,140,480,744,502,808,354,48,544,553,358,455,958,614,306,595,768,155,875,767,344,719,450,852,833,508,986,274,921,346,577,648,54,576,219,556,490,475,549,656,317,217,657,379,940,153,249,598,338,4,283,721,726,867,502,182,746,615,63,540,859,993,904,233,487,136,508,364,526,498,298,307,402,521,910,199,760,868,678,633,308,281,405,479,909,948,634,559,543,950,412,608,571,190,20,567,788,878,143,419,271,202,432,290,371,515,597,287,958,621,433,663,700,647,825,744,377,980,376,780,467,378,336,159,184,175,954,109,176,78,204,740,588,181,76,411,549,832,305,340,437,323,778,362,370,598,26,948,634,694,960,387,963,952,206,410,209,835,432,227,495,801,25,501,322,780,526,647,155,881,833,911,217,967,316,540,548,627,931,838,362,396,8,440,751,773,702,903,25,635,358,776,326,525,292,721,599,170,518,452,685,456,530,756,599,295,222,480,995,973,824,151,967,701,580,846,42,357,822,731,310,64,923,10,427,187,131,877,764,79", +"849,621,62,135,263,454,140,801,484,533,681,264,748,589,78,616,130,190,725,277,593,869,673,70,241,324,264,544,872,248,574,689,15,400,325,855,926,393,423,535,190,563,354,230,571,325,44,864,309,784,745,148,817,630,869,120,262,474,499,112,187,214,950,695,808,656,456,933,160,748,616,711,220,404,444,816,689,962,813,953,806,324,855,215,765,545,385,280,399,140,971,894,671,710,77,792,987,927,107,495,290,789,164,494,681,477,137,117,345,745,900,117,971,26,357,173,102,683,469,758,725,150,550,56,870,304,334,427,814,819,269,688,17,287,890,792,693,119,783,276,55,835,878,266,677,57,680,639,195,517,486,54,884,263,399,907,229,18,44,765,183,237,5,998,979,281,470,18,90,977,701,852,551,547,103,183,271,64,880,590,100,555,846,168,681,712,866,31,744,23,919,510,482,341,6,862,85,796,423,446,892,647,629,787,167,63,835,37,610,277,467,648,852,103,381,108,542,213,33,344,565,408,379,821,516,441,232,14,840,404,724,397,492,483,973,946,219,434,215,611,137,115,527,300,124,845,254,908,598,856,700,615,465,852,118,142,874,960,937,614,782,933,983,838,793,492,185,181,151,477,778,438,592,115,220,778,475,127,249,153,799,215,202,814,838,634,867,904,172,848,126,98,865,202,996,25,334,883,782,251,362,497,421,196,490,868,714,422,857,624,709,293,861,781,962,511,682,955,57,10,113,196,887,189,416,499,629,863,392,309,108,801,487,407,877,92,232,483,91,268,582,890,454,236,949,146,681,942,803,775,934,92,915,833,86,675,627,401,10,925,619,498,668,961,531,457,931,887,272,837,495,533,409,316,161,392,675,106,516,426,837,939,761,974,927,752,110,419,420,984,818,56,961,94,392,708,453,994,328,304,322,866,336,442,334,189,60,331,329,552,712,989,359,380,708,731,859,238,16,7,16,236,681,443,297,829,331,92,655,367,612,465,795,568,609,294,455,85,29,535,249,251,232,561,920,762,325,299,948,378,810,888,596,273,655,630,100,676,428,534,238,193,667,721,679,979,666,333,844,904,933,912,328,416,480,642,412,400,470,338,297,322,785,691,519,225,440,144,814,634,987,13,225,828,676,920,279,527,592,803,731,164,224,344,47,85,240,658,895,247,351,20,342,51,246,584,888,538,639,823,685,704,950,454,938,265,218,42,651,171,925,632,557,348,214,729,703,31,414,372,182,484,99,294,174,810,676,232,460,916,387,788,39,791,577,673,880,246,697,114,913,277,880,748,721,914,898,117,447,816,325,628,848,130,327,394,49,555,198,138,426,204,231,373,979,129,200,496,104,105,845,507,60,525,193,840,199,958,641,517,45,411,134,25,470,649,289,736,572,578,585,553,418,936,20,817,876,724,975,102,893,467,83,273,646,102,902,190,946,888,608,853,954,671,898,542,658,787,773,524,716,766,222,596,469,160,673,13,803,137,840,115,316,315,55,997,574,818,264,908,134,399,691,742,915,549,389,646,520,945,529,744,875,811,509,7,16,151,789,222,251,453,298,614,878,248,224,951,452,802,143,864,398,205,773,780,823,383,428,309,10,685,711,834,535,157,403,15,736,474,298,953,122,912,680,694,375,898,839,792,156,540,399,959,815,364,680,105,357,928,940,424,0,809,715,452,980,398,724,819,810,647,7,426,945,909,36,376,15,784,778,761,688,126,298,119,984,231,95,580,828,455,580,814,52,447,811,193,598,523,515,304,211,151,632,762,279,251,594,903,998,89,955,608,298,568,904,463,820,132,506,539,748,690,15,24,380,929,405,596,774,715,945,796,232,816,157,271,642,996,915,389,676,609,462,940,701,958,485,432,391,103,239,591,523,589,466,676,788,65,96,155,595,891,110,156,700,890,401,500,236,610,807,619,577,379,849,943,828,377,977,262,855,864,204,214,889,841,171,411,216,387,617,894,564,409,703,978,302,264,200,652,371,74,99,292,955,456,774,805,284,278,699,919,772,271,677,664,924,890,606,827,512,648,555,466,447,293,35,899,54,944,556,882,758,228,755,342,120,828,790,158,309,919,373,714,845,958,877,32,724,505,703,156,128,756,675,288,707,861,321,774,612,573,165,112,729,985,801,422,481,94,248,327,328,540,394,312,794,725,276,980,215,669,785,379,746,333,234,591,638,306,491,431,424,624,264,867,439,905,715,790,529,736,972,188,319,151,581,165,17,832,381,210,214,651,450,48,83,466,472,911,750,554,989,623,322,690,974,243", +"736,582,396,814,372,944,264,450,209,183,54,74,787,526,871,870,853,15,669,112,767,555,888,903,507,586,641,162,391,229,16,541,207,146,433,464,333,857,406,585,890,391,345,136,305,891,723,341,839,352,267,178,631,409,16,907,41,520,280,32,685,143,225,422,584,71,958,545,283,228,170,800,837,822,981,305,102,39,491,274,641,204,490,54,630,926,220,996,908,314,845,587,679,736,476,618,414,374,532,591,739,713,240,667,766,132,693,745,583,664,622,552,556,771,555,182,285,920,721,555,870,175,608,361,895,918,657,620,947,203,254,224,475,357,415,67,185,693,457,513,234,359,939,49,442,856,488,186,303,103,705,891,325,860,833,602,470,680,619,343,449,269,956,948,688,133,696,620,972,841,752,236,469,181,940,232,88,992,613,183,633,569,677,20,494,146,475,145,603,534,315,98,985,279,444,679,197,66,636,75,642,276,256,731,192,886,707,147,220,832,320,28,270,174,629,138,203,674,828,703,588,613,810,448,406,311,991,608,259,154,378,94,265,591,932,549,343,365,131,656,175,109,507,827,662,285,631,978,718,94,411,452,775,408,843,818,582,822,401,462,263,50,47,329,535,462,935,389,796,902,959,806,619,484,12,193,364,953,382,355,327,935,109,353,840,575,226,288,754,406,810,109,748,9,104,96,723,224,321,307,928,247,198,799,672,867,690,545,646,856,44,766,382,817,594,308,734,835,48,491,819,12,786,989,467,980,42,142,413,875,704,349,675,433,612,30,485,946,17,821,714,662,803,470,605,22,497,67,181,859,678,313,422,541,952,301,816,291,70,572,427,692,327,549,786,543,268,304,172,465,349,980,342,203,258,56,876,330,408,646,222,290,454,164,232,778,675,461,171,466,6,840,363,659,797,457,386,173,691,366,215,116,11,937,287,548,731,789,432,958,535,577,330,492,664,865,324,118,927,437,947,836,718,979,931,911,114,881,691,469,93,603,398,735,595,519,192,593,821,652,217,868,153,309,672,681,49,2,286,94,789,429,141,951,689,615,161,681,306,713,480,940,766,718,196,626,663,251,494,866,90,72,906,834,960,45,683,778,390,512,189,912,171,626,579,82,274,667,126,90,257,563,800,968,327,178,10,552,435,38,454,301,7,774,440,742,51,938,573,288,390,142,79,376,168,507,252,406,512,816,505,594,430,33,779,910,131,533,540,289,882,928,477,556,74,447,205,742,152,922,655,933,998,760,970,438,683,248,810,729,427,44,162,435,343,568,723,314,848,625,216,512,992,204,861,825,693,315,58,713,679,969,804,797,617,404,979,73,192,124,220,901,667,783,153,846,200,415,551,631,419,447,894,555,966,226,972,239,454,391,324,604,22,595,930,544,985,302,207,791,831,143,607,822,151,115,656,24,541,473,585,641,277,124,238,941,762,69,578,468,466,229,938,745,437,478,870,508,676,371,92,719,137,62,810,507,939,788,339,235,897,995,595,307,885,602,905,457,724,42,722,37,147,988,919,206,167,268,412,517,943,138,220,536,724,784,583,193,534,840,739,729,338,30,639,971,945,545,871,633,695,415,937,663,668,239,746,795,222,27,340,491,195,177,186,276,806,830,824,257,803,236,408,717,914,278,401,102,192,67,139,237,642,425,681,449,901,97,939,242,927,336,809,0,391,387,936,812,352,636,792,59,619,110,52,462,101,491,844,830,792,30,403,893,711,762,648,277,479,533,920,946,891,781,852,576,861,483,21,88,236,721,772,529,217,510,855,256,225,455,719,138,251,544,728,608,625,80,194,638,881,812,874,214,935,163,586,3,641,149,69,596,364,272,92,183,429,238,371,453,684,789,915,59,101,649,639,269,584,825,938,495,180,303,220,611,393,398,181,105,311,679,934,352,112,67,934,948,131,878,397,442,915,561,878,233,755,779,384,460,429,204,406,112,469,137,168,124,315,486,251,542,352,22,661,527,828,776,299,950,539,602,872,594,633,111,77,131,98,736,379,730,915,292,186,93,496,61,705,334,980,880,316,825,610,891,951,901,287,971,389,443,35,688,348,684,247,742,949,406,357,698,258,825,983,160,181,916,760,89,429,580,946,654,819,560,994,153,630,23,398,543,953,692,109,110,356,383,259,801,897,943,824,369,617,367,74,914,87,851,318,936,900,333,890,916,269,936,177,301,684,615,546,359,431,393,89,909,142,874,244,362,387,938,63,511,105,453,849,488,772,588,326,894,789,264,721,485,820,702,320,261,315,861,67,648,326,293,824,198", +"283,439,530,498,648,221,674,650,615,313,818,141,839,831,815,371,720,531,420,52,678,613,120,169,577,504,961,501,950,742,647,834,323,410,848,697,659,991,797,637,159,456,668,837,801,145,451,461,276,564,250,211,814,410,935,857,853,463,833,137,566,408,86,620,724,752,152,597,390,104,242,418,336,658,490,229,862,814,238,604,410,727,64,598,605,962,413,736,777,734,846,690,867,477,977,553,744,90,422,951,848,11,297,70,174,375,816,300,600,829,950,409,944,27,474,369,582,385,297,454,659,687,730,626,473,890,598,340,747,844,549,569,502,432,425,533,781,56,515,184,208,305,766,209,125,917,978,428,514,319,113,57,944,774,415,779,539,458,767,796,670,701,641,459,114,910,589,995,18,23,187,244,499,822,590,815,928,234,471,678,379,588,805,345,544,501,301,764,927,464,545,252,661,606,64,763,506,340,661,37,448,729,533,465,78,3,272,662,330,353,452,364,266,637,931,97,119,379,27,560,221,276,216,894,96,336,501,964,516,986,940,85,97,11,862,862,367,562,810,377,198,998,316,829,833,231,996,104,563,48,312,526,387,325,900,350,258,630,162,363,767,275,723,266,455,224,343,315,183,930,279,86,41,365,872,807,953,839,6,438,709,649,791,788,561,896,82,958,247,987,534,289,415,118,578,772,542,129,483,967,12,426,833,853,94,404,780,376,233,542,881,912,925,283,759,921,284,197,518,97,59,539,698,23,318,894,767,403,355,498,650,244,388,679,222,499,205,149,262,634,97,300,973,333,619,758,74,65,673,286,251,242,812,837,566,209,959,747,999,76,999,730,902,65,863,374,214,460,947,619,771,960,804,699,765,79,111,499,108,170,133,86,170,602,684,89,94,811,539,248,891,821,769,861,421,285,673,98,718,118,108,134,505,467,118,901,472,78,776,287,526,467,415,373,68,416,998,492,788,939,396,33,949,28,770,306,62,296,67,288,914,764,755,606,380,456,107,288,758,946,203,131,574,626,561,379,388,577,855,1,753,24,642,94,125,111,15,634,780,758,244,131,827,393,816,998,275,3,366,630,937,384,400,204,96,99,691,519,225,627,900,753,249,143,552,902,110,736,986,633,5,733,395,414,617,582,85,394,265,409,355,951,40,22,579,322,285,469,889,690,279,296,886,663,146,560,405,27,181,340,217,22,481,991,479,21,31,579,692,990,571,648,552,583,868,227,530,532,769,210,548,151,850,607,775,419,257,595,804,741,136,629,230,286,58,897,271,348,973,617,922,16,988,262,830,664,544,945,257,327,900,42,387,515,385,240,750,643,371,612,47,636,908,998,623,669,556,801,892,803,347,760,153,160,198,554,200,309,56,596,987,594,628,630,269,353,631,116,136,365,166,844,314,365,766,14,309,635,102,158,159,144,651,951,616,329,329,655,421,723,864,445,971,923,791,492,312,932,433,113,532,229,822,307,656,221,794,63,241,547,946,91,995,141,943,365,381,270,341,698,536,485,314,675,716,93,220,740,806,503,968,333,795,635,926,243,92,328,408,133,255,407,161,429,987,788,343,840,297,537,761,301,321,668,525,108,624,167,814,458,325,454,697,215,117,809,227,654,208,832,156,162,921,684,934,400,824,641,647,867,639,917,288,220,939,530,290,732,840,359,274,129,715,391,0,910,461,373,533,669,732,25,314,624,128,366,273,152,431,442,892,898,870,213,763,495,18,455,602,511,520,634,113,649,468,754,671,425,945,264,259,464,905,106,55,950,826,708,878,400,438,549,931,759,222,56,100,75,850,452,205,281,550,38,362,590,404,454,844,224,194,23,477,854,337,603,647,418,798,918,985,187,840,130,267,995,275,566,725,783,340,318,410,791,904,948,391,64,965,502,279,306,468,112,993,719,666,392,435,247,947,200,312,848,695,117,741,1000,823,393,702,221,702,414,955,951,379,354,281,501,110,171,293,766,587,723,82,743,569,394,29,33,285,887,524,493,465,213,619,244,257,813,716,742,764,140,879,154,485,899,668,244,434,436,737,196,400,30,764,252,505,694,965,614,85,457,894,874,980,971,314,799,883,465,721,114,51,688,328,289,621,933,993,397,651,754,459,41,608,103,754,670,605,748,711,222,996,198,271,356,753,617,579,164,609,25,114,955,821,502,38,437,527,281,242,421,967,246,346,503,278,853,210,854,670,799,628,699,312,228,913,712,362,188,575,753,932,204,874,51,246,33,306,993,458,399,930,578,988,767,753,552,47,275,807,663,546,252,348,831", +"210,825,888,358,593,249,221,953,649,400,365,954,117,542,48,140,811,971,896,805,268,712,282,849,112,173,187,501,53,79,611,978,137,727,737,626,78,155,514,767,191,582,734,970,96,790,593,186,804,804,421,878,712,971,682,686,246,928,59,199,201,892,821,610,631,692,967,205,126,816,693,425,308,165,946,92,779,639,63,921,762,565,427,225,360,810,909,507,708,801,92,844,217,500,554,93,910,71,749,499,455,928,612,106,126,357,110,603,587,562,490,829,930,542,507,862,138,723,82,867,611,992,30,478,671,75,182,565,148,40,744,107,357,840,713,818,771,945,170,575,581,584,771,424,417,905,200,976,232,292,294,392,331,410,579,678,395,617,986,994,541,925,403,960,609,171,732,127,967,980,540,638,760,155,198,209,709,239,374,447,262,609,203,813,198,337,683,10,512,91,304,100,52,595,322,512,699,749,677,865,892,229,199,684,587,664,103,250,647,899,123,553,942,779,540,828,840,28,695,509,652,945,300,461,149,703,999,741,397,537,632,616,340,588,730,798,870,579,830,250,726,959,222,237,310,422,703,826,698,443,414,432,484,337,992,425,260,646,710,990,782,620,33,676,588,364,192,820,671,585,469,55,557,668,164,854,377,820,40,179,863,49,770,675,428,461,501,919,261,980,767,99,975,827,504,427,585,397,346,183,526,367,628,19,486,664,919,81,203,253,639,548,185,190,71,850,941,753,113,938,127,609,502,899,703,517,381,174,870,225,404,443,25,675,147,676,438,230,237,434,713,446,764,273,263,111,360,956,512,471,967,672,377,622,776,651,644,253,210,248,816,383,755,462,216,209,10,831,341,744,545,562,886,964,994,22,857,460,959,419,782,237,248,91,159,236,672,308,4,711,582,615,646,475,843,227,649,122,225,659,775,217,178,530,808,539,733,454,487,820,11,721,236,409,169,452,95,976,493,198,199,107,894,560,525,581,687,682,596,119,126,351,586,83,381,884,11,287,253,512,616,629,816,275,326,473,604,297,864,90,542,430,12,56,745,689,78,540,654,838,474,973,697,819,220,940,418,23,356,901,453,994,934,202,330,2,848,774,604,17,279,336,473,113,266,384,306,783,36,815,246,883,808,712,812,905,568,618,481,384,547,490,490,534,714,303,716,933,400,544,856,557,796,494,208,947,473,499,840,721,57,600,47,295,346,716,987,116,66,720,143,984,721,27,651,397,4,685,189,183,162,945,936,375,408,715,980,373,964,114,835,287,626,387,527,589,315,853,68,231,167,914,534,545,382,550,526,329,793,130,7,315,841,294,665,994,13,359,931,114,583,744,332,528,699,879,160,737,800,934,690,398,317,608,171,154,320,668,228,990,331,26,710,31,893,841,703,538,475,868,771,527,455,512,527,386,850,787,15,292,655,56,23,627,523,911,329,455,822,384,991,545,550,509,128,9,235,920,879,984,85,632,941,972,17,921,940,37,70,987,874,254,256,701,753,362,750,666,779,336,584,928,138,667,896,86,174,613,872,146,947,324,529,656,767,875,377,846,626,783,79,120,378,697,47,469,564,400,265,194,594,218,226,722,792,152,105,47,450,593,472,503,355,469,340,779,234,605,18,536,896,199,556,665,472,622,520,104,344,330,317,659,804,407,476,506,975,754,280,726,649,488,452,387,910,0,281,157,635,504,853,384,882,791,135,427,123,232,204,66,812,867,522,621,155,757,269,700,151,410,398,889,407,862,978,899,374,488,132,942,120,257,234,388,67,328,248,211,861,120,371,830,712,849,122,383,773,585,664,783,564,153,796,901,597,272,359,317,806,8,788,480,260,530,118,990,413,684,362,708,836,149,971,998,353,656,548,529,185,745,94,47,949,393,110,50,756,375,747,756,873,494,414,573,908,437,234,797,165,293,203,936,575,726,556,879,103,690,11,363,198,778,358,284,142,35,40,987,389,665,628,940,536,550,712,454,632,931,775,889,678,724,969,392,729,971,778,307,235,514,413,524,219,742,355,388,330,671,313,865,634,231,307,805,825,43,674,80,64,670,687,997,396,672,269,124,401,654,982,714,280,425,311,344,231,85,10,185,903,100,967,529,885,95,881,805,653,466,248,503,302,942,617,831,315,726,633,623,742,91,369,127,569,648,221,934,315,305,231,566,760,464,623,147,349,633,931,401,230,995,793,901,217,321,945,797,290,909,591,282,518,966,777,119,673,769,552,213,966,821,313,239,515,596,710,31,244,984,843,328,956,235,412,846,846,3,263,28,404,761", +"5,45,346,847,792,131,426,13,202,726,675,99,404,226,809,900,519,729,948,200,834,531,341,217,343,426,836,511,127,351,125,520,127,359,276,268,41,770,441,41,254,644,718,738,546,621,853,149,111,718,733,120,704,501,753,994,510,177,920,129,882,555,435,181,952,873,890,247,630,247,349,599,63,437,875,426,814,882,147,862,834,908,504,235,437,724,200,707,142,513,118,555,337,558,418,879,474,321,790,982,635,506,488,712,205,292,486,212,33,459,996,454,264,75,803,211,781,159,164,69,111,661,928,931,107,184,997,815,996,661,438,48,64,569,518,452,399,280,514,94,585,154,486,236,70,513,445,359,810,782,355,318,729,782,929,969,919,988,326,469,545,914,402,488,551,777,213,304,800,926,826,705,251,929,759,705,610,173,845,459,18,891,799,567,385,757,949,687,328,936,74,708,394,959,462,599,379,485,677,532,155,986,411,362,46,377,173,4,826,990,638,499,590,27,419,958,28,693,821,551,866,528,172,907,497,889,857,576,892,182,759,452,493,913,727,521,707,828,572,54,159,429,617,940,794,412,767,541,24,828,448,659,692,167,856,212,724,793,814,362,62,830,171,885,283,876,209,738,707,542,964,664,150,338,59,36,968,621,266,716,767,712,174,832,56,654,108,927,966,814,109,479,804,912,659,860,155,839,986,332,913,18,593,119,36,173,699,186,854,709,660,533,530,751,87,817,856,543,545,353,853,202,824,280,568,845,157,866,301,760,100,790,463,492,755,736,143,879,819,940,967,858,886,681,945,278,955,919,89,310,952,623,236,97,766,533,449,862,817,275,598,874,128,301,70,106,998,631,694,693,555,643,243,174,434,487,530,690,198,899,599,775,714,424,125,941,824,802,442,970,69,485,918,316,315,132,994,717,192,608,775,729,638,888,683,446,84,985,773,32,728,744,660,775,83,690,79,651,875,313,842,728,882,373,442,884,747,670,287,854,462,651,112,647,289,147,826,149,966,879,160,477,12,347,768,781,548,213,977,387,343,968,112,573,864,557,71,348,869,20,596,515,767,691,353,407,474,439,109,869,876,100,770,94,949,712,730,975,602,540,620,721,726,32,496,991,374,803,482,263,236,874,748,627,409,721,269,787,392,57,1,761,113,27,684,419,794,110,506,686,72,933,922,863,145,528,14,604,524,477,107,305,711,986,985,342,630,602,90,168,856,631,181,520,437,29,585,150,286,225,64,979,905,707,541,974,429,875,84,66,542,560,759,882,658,658,980,58,110,821,960,377,636,628,404,463,579,768,407,78,177,52,15,844,902,767,464,961,987,203,431,862,307,442,277,940,255,598,614,573,44,795,929,494,684,537,540,918,356,478,721,940,575,429,172,565,671,259,5,942,359,354,79,149,848,738,519,106,150,368,890,221,640,76,221,943,408,774,42,292,411,275,971,3,946,530,490,705,973,694,913,348,44,787,403,576,118,102,228,248,168,819,952,924,193,939,953,617,522,638,556,964,441,89,119,567,603,352,753,116,267,650,416,291,357,596,343,258,282,404,959,863,217,200,965,388,430,506,481,241,803,66,944,61,903,61,441,778,816,84,366,747,645,879,498,102,296,902,324,845,245,876,96,743,784,808,185,371,804,169,55,647,913,575,731,210,542,413,334,758,74,311,980,936,461,281,0,123,968,381,206,969,391,977,916,490,685,396,488,359,242,383,867,699,259,388,576,332,597,209,640,434,449,372,436,663,171,818,429,719,251,772,230,920,863,653,115,178,410,780,31,500,724,243,805,266,306,191,959,510,294,448,223,963,386,14,858,393,703,585,369,209,177,640,710,630,692,296,817,989,771,930,7,606,269,952,101,148,187,65,338,760,171,215,688,175,680,854,575,420,234,810,723,896,164,25,249,255,803,122,637,429,197,151,907,66,246,385,305,355,400,129,878,82,465,627,746,920,51,691,588,805,743,916,203,350,171,230,279,745,656,129,984,30,845,736,498,973,659,236,400,119,110,986,630,500,974,670,117,802,741,106,702,888,62,20,944,841,689,777,969,536,702,694,125,550,903,520,159,93,975,380,100,312,789,465,188,72,843,661,553,270,838,890,629,18,307,597,433,255,707,621,279,361,365,560,614,7,542,595,687,589,132,651,744,452,378,570,622,67,489,333,812,806,253,964,910,921,322,922,568,443,560,817,900,1000,681,809,372,63,304,774,910,662,399,62,399,66,151,316,34,395,329,954,473,109,426,312,656,317,51,400,659,481,814,116,462,987,437,494", +"131,208,67,895,626,967,628,720,330,851,20,559,231,561,303,490,496,121,93,937,860,333,627,418,613,579,427,827,407,396,759,223,722,218,284,814,878,405,168,595,706,25,176,896,911,70,904,792,870,890,40,681,870,952,853,10,524,526,182,522,761,35,895,602,407,596,248,656,9,227,529,645,422,245,216,839,560,826,56,330,612,101,524,422,754,960,630,510,353,111,137,7,691,628,355,290,777,714,832,370,140,878,804,652,480,410,229,628,182,859,125,392,799,382,997,455,435,461,972,66,891,300,54,459,449,728,673,502,665,114,948,17,28,630,538,68,166,574,954,903,691,357,848,943,604,769,663,628,700,550,469,51,573,561,659,969,826,964,160,85,182,928,7,295,7,533,31,471,884,210,184,430,485,238,647,145,169,584,409,217,706,530,99,416,775,671,811,23,404,828,320,551,539,80,608,125,301,567,945,818,705,268,666,396,407,408,86,769,200,669,753,862,255,481,206,917,252,627,562,585,591,342,560,579,314,210,399,132,978,283,389,145,775,569,487,297,903,668,327,28,984,986,421,950,223,273,665,714,368,325,66,153,373,595,546,101,112,319,527,36,737,821,38,306,632,444,885,980,292,809,715,113,500,378,570,379,998,271,345,46,195,742,28,434,715,262,432,80,886,558,671,608,628,183,431,811,81,840,252,6,954,393,378,540,998,547,387,52,372,639,259,646,587,164,924,533,896,254,642,696,22,486,393,862,409,565,556,462,553,618,763,511,957,948,944,449,671,32,144,797,800,538,886,221,354,678,173,115,519,979,857,889,632,166,125,382,746,345,581,996,63,698,72,885,18,962,559,943,679,516,317,490,213,480,395,159,572,174,697,611,287,771,729,656,252,237,122,25,163,123,794,851,877,980,997,294,766,858,487,673,986,990,428,299,515,571,952,758,571,980,709,988,403,186,797,618,46,190,670,738,166,38,978,461,114,293,566,595,915,838,209,401,86,331,151,349,699,277,673,999,678,581,105,484,308,161,153,206,872,111,436,339,388,351,695,636,101,424,295,993,767,873,779,848,363,104,375,611,991,501,163,753,208,849,752,31,454,307,864,139,342,65,792,21,293,216,213,926,93,826,780,563,268,721,326,589,874,547,172,823,824,915,175,771,75,977,624,183,118,962,859,602,225,413,69,450,565,757,122,690,329,71,381,157,241,557,561,790,696,919,490,811,209,782,853,112,564,929,1000,391,518,22,389,457,686,698,766,553,69,105,749,466,638,75,839,159,282,562,614,977,186,429,831,997,130,161,99,690,225,992,141,362,753,836,391,485,268,79,453,218,376,974,868,902,253,911,21,754,569,47,514,112,442,255,141,551,130,278,190,323,716,188,372,134,834,169,289,394,896,261,868,647,332,860,91,13,134,317,672,767,60,522,144,253,771,4,176,732,393,599,901,96,836,405,460,736,479,916,545,502,883,259,317,95,596,261,169,771,609,232,20,247,205,660,410,431,791,56,952,600,288,206,335,104,999,291,439,449,92,442,396,473,28,619,640,341,119,6,586,753,880,744,660,494,343,234,262,931,186,451,65,344,937,525,152,500,627,582,419,570,893,88,920,687,207,690,76,49,299,277,769,690,644,659,201,366,392,257,46,97,855,879,56,132,69,382,975,378,814,301,737,645,398,812,373,157,123,0,807,406,263,205,826,509,393,724,621,312,164,183,3,350,168,532,122,765,522,519,190,2,665,533,804,282,6,291,271,998,461,957,498,663,371,712,819,242,178,226,983,583,718,498,633,829,77,101,807,916,186,632,384,211,429,698,659,957,734,581,172,408,832,46,755,261,118,466,330,734,42,174,313,373,184,961,181,476,311,710,966,481,340,882,458,421,903,684,459,751,742,805,82,821,46,660,556,754,704,926,884,408,383,686,220,853,104,366,711,70,385,831,404,125,218,557,62,972,950,185,579,747,479,252,963,488,174,872,266,57,64,61,675,752,791,796,703,465,622,585,932,738,395,514,695,866,198,678,704,400,238,272,797,158,583,566,303,87,475,559,572,586,422,240,938,655,304,296,389,480,228,692,707,522,411,903,896,733,457,276,557,521,986,306,577,27,766,636,769,470,291,538,573,548,574,457,228,89,701,176,121,60,164,297,504,639,742,724,831,328,382,320,243,691,776,842,211,702,281,51,726,449,584,106,176,380,651,759,547,361,837,536,626,640,765,431,986,620,795,875,384,764,415,155,986,954,708,197,570,541,883,417,973,890,233,355,2,189,345,113,172,12", +"117,249,264,906,755,433,639,726,118,599,981,36,260,954,293,456,62,769,572,568,70,938,168,665,827,620,287,837,734,522,656,554,63,920,809,595,497,690,51,837,415,626,800,559,474,577,580,489,734,781,854,47,738,780,680,527,219,300,554,978,293,921,426,927,870,468,564,583,321,579,744,744,107,377,767,625,666,146,230,462,828,783,124,754,668,933,466,113,390,217,967,7,326,981,3,627,813,130,94,883,971,108,326,600,572,819,249,125,918,991,440,943,270,651,277,204,473,875,746,384,161,609,923,276,955,683,458,325,398,444,986,196,25,337,22,663,851,572,260,172,535,830,853,463,619,12,152,140,367,28,996,736,965,134,648,952,624,302,467,476,628,958,535,59,290,533,296,593,638,64,623,573,862,622,866,923,82,958,194,945,138,481,378,260,331,372,680,594,2,344,505,881,926,107,525,209,787,648,848,473,151,123,843,691,166,173,751,799,131,503,267,264,417,719,597,264,809,644,361,66,915,959,252,383,433,540,757,959,738,968,848,836,855,86,874,287,580,601,526,499,779,378,829,886,187,166,420,186,228,664,180,748,842,335,962,497,291,48,270,932,702,667,307,31,254,19,920,155,540,729,816,522,14,229,1000,186,990,866,533,390,85,119,663,174,613,992,715,829,545,115,124,486,383,974,257,643,95,271,687,485,80,655,288,289,103,647,256,88,431,420,834,150,956,36,346,405,781,119,119,693,375,691,528,590,313,977,605,962,160,868,90,865,57,618,508,566,800,614,556,329,163,328,949,220,125,690,725,450,570,442,230,260,403,335,238,976,181,874,584,740,35,201,670,47,750,775,961,758,774,88,389,7,862,175,648,68,342,461,13,340,4,153,778,168,82,305,791,497,105,80,672,401,493,910,533,205,218,787,189,89,406,625,717,88,956,762,83,964,416,856,601,717,111,624,442,938,358,367,25,318,110,559,320,695,741,272,731,118,826,328,411,772,220,622,747,4,779,848,152,186,725,308,705,635,237,927,84,721,61,283,599,476,178,565,375,346,314,397,16,563,951,771,449,546,768,217,468,271,613,472,54,331,665,20,182,298,75,849,634,806,189,198,85,428,51,949,129,11,577,19,652,20,870,60,629,709,282,81,784,859,56,558,947,627,105,189,860,146,150,935,753,99,562,943,885,143,200,549,481,217,159,925,416,645,581,149,539,331,640,658,691,377,85,387,801,717,667,751,404,187,444,153,35,617,772,485,27,803,563,355,647,908,485,230,569,998,472,160,221,571,838,285,683,882,51,610,849,844,968,507,274,373,949,926,429,561,707,564,754,771,538,494,247,516,297,863,21,297,695,187,860,482,708,593,944,801,760,291,45,738,232,517,758,243,28,716,587,139,476,852,99,760,419,438,283,231,926,362,781,287,921,591,788,77,467,724,680,175,575,123,783,517,530,126,930,922,982,391,190,194,781,738,550,655,364,277,97,167,383,133,979,737,983,203,11,791,864,746,442,829,284,783,101,642,69,276,527,594,755,739,62,648,836,201,534,392,607,71,648,438,393,476,956,918,225,505,146,917,848,915,857,700,403,60,45,999,771,848,770,49,140,534,882,373,160,983,655,270,202,293,739,327,339,853,100,232,753,506,603,11,954,682,728,220,570,743,351,586,500,248,157,442,724,352,533,635,968,807,0,17,724,356,336,602,119,170,145,191,247,382,973,400,570,80,122,267,436,300,128,747,96,263,145,368,233,631,592,359,834,942,572,551,503,216,137,833,527,171,945,834,683,209,374,78,941,49,519,850,238,864,913,440,23,200,987,824,125,464,951,808,758,82,680,989,518,885,804,272,448,919,738,899,47,274,410,260,127,992,442,762,123,545,150,621,943,147,782,197,668,866,789,155,615,473,390,606,813,587,48,287,354,318,71,59,306,732,16,469,528,320,824,649,771,564,282,731,195,215,710,167,128,238,859,808,709,253,219,201,694,605,45,39,752,732,580,297,562,606,318,362,489,345,954,277,24,532,36,394,351,272,570,661,410,966,825,763,371,126,686,869,813,259,851,800,241,392,454,107,357,201,466,583,302,939,530,805,268,210,687,786,396,381,455,203,333,899,104,884,246,838,831,556,388,768,86,68,450,730,869,902,126,748,255,623,122,908,267,225,264,632,420,396,752,902,984,323,346,514,162,652,816,355,50,771,199,377,276,921,906,692,675,793,776,160,709,805,930,493,882,828,516,626,343,84,351,659,219,536,785,210,624,739,627,854,388,303,278,273,798,62", +"978,63,744,570,535,694,467,657,847,931,762,988,465,499,187,753,151,307,527,523,466,631,981,824,19,481,694,350,258,335,204,858,532,378,674,500,966,842,667,799,987,858,233,460,592,219,555,376,670,835,186,741,563,162,428,247,167,647,195,505,722,76,599,947,773,529,814,650,268,756,88,593,913,783,306,418,886,691,818,208,245,876,969,689,396,818,964,150,500,326,995,30,922,263,514,474,609,478,116,914,235,288,119,966,623,463,881,661,323,536,105,832,932,169,715,556,547,908,167,214,352,497,855,203,88,754,50,113,276,321,979,943,734,928,903,30,139,19,561,469,611,388,925,368,633,989,395,827,248,447,498,219,394,918,900,700,591,461,433,524,860,904,452,822,919,174,748,730,562,215,439,537,903,243,647,529,809,577,514,309,668,819,479,287,740,136,460,749,172,175,962,296,987,371,308,808,607,758,242,279,360,652,999,57,720,491,983,55,552,6,41,795,82,827,559,540,655,386,440,462,384,75,231,471,776,740,31,537,407,615,173,911,744,267,186,273,585,771,20,126,127,529,519,671,701,64,456,685,887,397,97,312,811,502,475,513,543,125,242,96,628,303,658,577,959,855,665,279,640,271,718,565,266,874,105,990,856,148,96,234,101,426,490,411,491,578,897,224,723,581,555,549,182,600,129,769,729,817,551,484,446,37,333,315,818,767,214,705,224,487,359,347,644,485,793,238,660,245,250,171,43,947,505,721,706,730,436,321,469,999,845,353,557,435,182,727,277,440,748,926,278,497,777,613,412,798,773,403,87,864,372,967,492,443,386,909,195,568,5,222,42,92,361,581,648,755,70,89,701,597,469,46,717,413,609,77,511,908,977,622,857,571,278,954,511,4,289,804,919,55,452,954,750,878,303,241,584,804,817,154,842,104,607,158,286,98,785,890,230,693,132,309,343,256,674,798,43,357,389,651,732,370,4,36,683,128,657,730,466,286,636,357,17,361,43,926,649,223,510,338,355,801,408,276,714,409,901,437,664,974,229,485,891,556,651,514,33,799,291,508,487,517,434,996,419,119,996,853,861,35,644,51,196,336,980,613,587,626,445,363,8,333,993,771,695,949,308,849,632,169,523,477,251,205,411,912,340,104,556,434,714,566,903,235,712,580,846,929,171,48,550,703,168,276,503,249,228,501,76,623,867,751,864,716,248,83,585,416,246,744,628,549,205,702,980,237,440,107,361,675,592,318,637,486,563,427,276,217,704,439,689,582,163,304,667,977,432,169,178,869,655,263,931,127,124,804,61,658,353,353,13,577,204,794,720,193,67,8,354,543,363,912,571,471,393,833,123,128,920,490,176,647,290,713,216,965,45,683,242,904,859,993,890,216,482,75,414,673,596,671,207,611,150,426,266,759,757,886,821,847,979,831,360,165,84,543,856,140,290,315,930,691,882,175,547,920,764,995,114,239,344,96,166,416,795,663,783,115,11,103,991,29,657,442,380,969,170,817,430,933,848,372,215,658,99,919,185,162,94,198,509,591,889,668,408,909,987,126,144,324,439,410,517,782,110,222,876,774,850,714,446,342,543,895,909,283,215,6,284,62,251,241,275,978,953,651,129,244,12,71,769,737,84,126,350,976,308,741,612,814,797,864,542,539,903,8,558,228,365,749,817,401,819,636,669,504,381,406,17,0,192,371,858,652,158,844,113,478,721,419,991,212,875,405,798,613,665,583,722,671,951,12,984,963,200,400,160,918,995,81,683,416,632,633,803,718,331,586,465,79,699,818,920,239,262,193,463,685,66,914,776,164,627,428,305,464,536,423,564,737,292,329,630,509,55,440,719,147,132,491,622,176,971,888,804,717,729,220,370,99,84,370,152,649,195,174,546,742,659,789,483,408,805,974,703,189,699,668,374,810,784,249,731,700,857,57,682,549,880,775,318,517,490,801,818,30,717,932,54,167,793,602,5,340,675,833,927,160,654,460,394,989,907,389,555,652,634,356,397,494,846,860,295,11,194,556,568,946,616,608,69,435,128,471,400,410,971,140,463,421,926,455,828,878,532,425,504,897,629,690,191,686,586,696,190,24,826,719,698,641,509,968,46,800,610,90,26,978,347,346,962,457,697,958,551,391,325,778,41,167,347,172,338,951,795,701,193,886,545,358,429,830,818,401,420,463,74,594,317,734,821,958,754,107,450,118,439,572,176,705,290,35,268,566,221,217,500,437,712,874,95,117,160,31,951,323,269,581,33,763,824,285,258,724,840,952,469,66,681,169", +"379,468,772,936,235,240,614,950,346,269,557,550,128,269,894,896,841,964,742,945,267,967,7,759,37,969,390,347,913,716,433,632,139,716,690,594,869,49,173,931,587,392,610,140,32,858,141,808,143,316,123,284,903,850,963,412,179,745,836,159,434,367,563,450,388,708,706,519,981,453,300,240,376,279,610,689,143,318,113,768,55,922,406,293,845,444,613,68,409,486,589,873,559,797,347,831,585,452,77,602,7,786,461,5,942,202,666,357,569,136,921,357,41,104,6,707,987,63,287,252,227,161,244,994,837,512,528,387,287,898,505,188,844,509,85,249,617,344,432,127,421,718,190,15,252,418,661,707,592,12,648,573,629,860,793,542,734,440,190,710,137,864,237,71,922,560,785,513,229,182,733,561,352,295,696,953,463,229,575,29,2,460,597,235,12,271,853,680,974,426,906,936,51,848,557,327,857,170,908,510,293,783,999,269,296,740,248,312,776,216,144,991,419,668,764,286,602,262,463,34,566,39,384,411,165,915,132,21,209,776,948,18,949,589,15,94,5,908,204,448,852,193,985,3,263,995,756,399,303,789,696,110,738,33,65,653,961,382,301,449,86,909,235,710,649,636,742,103,927,884,954,603,882,787,876,182,657,270,469,769,790,474,264,642,636,851,569,732,834,64,708,746,532,255,407,988,290,216,632,163,707,378,956,745,19,633,811,615,107,321,818,847,177,260,486,952,44,420,581,561,313,78,797,692,982,36,307,412,221,619,649,393,306,206,72,550,937,662,209,187,489,870,609,900,776,773,430,197,13,300,939,263,698,869,414,685,218,474,137,836,244,633,122,781,240,352,183,239,537,983,877,945,712,680,216,45,457,165,814,424,346,541,127,920,990,410,253,835,79,483,264,156,200,258,341,57,135,368,849,266,8,390,329,29,195,966,185,882,557,156,430,145,496,841,804,523,229,131,930,219,244,881,348,5,135,685,23,401,817,305,974,66,945,333,893,200,67,299,47,591,700,528,65,203,115,958,775,75,32,600,112,730,751,616,372,260,582,872,517,12,106,696,10,886,597,963,794,39,884,370,921,693,661,517,124,376,825,208,169,102,96,532,209,646,917,761,737,632,401,25,411,345,522,715,922,549,754,350,57,154,339,381,620,459,843,967,718,633,164,87,564,640,968,26,708,820,208,362,319,169,429,365,795,873,55,16,685,43,88,273,787,808,493,456,365,898,420,621,658,214,986,306,327,930,884,340,526,85,225,752,979,186,235,718,952,108,11,453,967,434,130,525,312,758,74,669,285,84,117,482,779,22,387,379,52,919,46,775,783,976,987,635,206,652,244,159,904,430,927,597,575,937,694,939,938,687,375,353,874,280,237,942,71,207,651,964,928,675,312,654,79,136,341,178,501,258,943,61,738,370,286,459,598,474,46,925,344,263,829,639,899,318,617,930,514,331,693,266,640,373,919,892,916,903,574,777,60,963,663,150,883,40,389,994,93,955,250,753,66,300,413,183,612,310,94,58,784,63,71,542,313,783,200,772,234,53,693,485,354,328,109,591,210,29,978,509,296,543,249,737,417,316,386,18,122,170,600,368,314,139,907,115,721,384,563,72,170,637,749,210,586,270,611,613,89,176,436,376,251,484,69,685,208,279,919,675,493,741,313,562,585,287,810,792,732,853,206,263,724,192,0,904,9,643,139,76,794,738,905,430,909,683,645,250,888,721,638,80,838,147,371,171,420,879,328,948,251,80,26,738,866,768,873,562,270,167,189,693,419,908,580,289,263,810,239,48,323,246,909,561,559,431,733,300,178,197,228,58,110,816,550,138,605,762,888,244,710,969,173,885,72,530,722,367,920,498,779,137,608,48,351,77,992,391,551,416,766,999,672,722,747,403,953,863,50,448,343,621,983,748,70,926,484,658,161,173,225,86,231,940,165,464,751,539,439,606,439,597,819,304,216,652,309,172,459,823,673,618,263,142,886,196,826,671,172,520,503,876,517,97,654,37,426,517,921,558,627,105,565,384,330,539,548,598,977,424,34,425,850,354,311,480,82,549,423,752,480,213,517,312,65,545,535,860,394,444,631,890,548,702,850,715,251,941,469,651,661,776,926,445,814,836,668,312,252,279,665,490,115,362,839,573,356,281,163,855,738,739,212,26,636,339,388,672,526,676,140,163,708,420,235,737,275,678,673,184,364,670,60,611,796,644,450,5,718,796,97,615,681,739,795,709,173,389,998,991,236,494,716,224,826,654,555,400,684,640,503,53,871,395", +"488,764,726,826,739,856,480,637,913,213,244,603,517,969,446,874,880,473,953,941,523,989,14,65,222,526,810,427,817,509,823,484,989,527,392,40,301,599,711,997,578,253,313,549,840,240,299,452,455,563,106,389,47,244,641,524,337,295,125,496,883,900,712,388,706,893,312,343,167,240,280,199,948,724,114,670,964,671,606,234,730,280,152,382,716,79,516,207,358,428,542,768,976,962,827,402,619,559,241,644,382,241,457,719,495,729,296,123,773,521,726,395,309,405,228,508,781,315,756,288,706,826,278,316,542,997,112,342,270,1000,609,140,272,888,621,216,258,700,795,695,5,120,995,81,774,284,998,122,592,967,30,890,129,365,474,732,555,763,286,569,302,470,245,578,456,251,324,931,230,150,853,985,31,567,956,401,669,797,77,361,80,564,723,634,257,116,851,896,821,998,89,767,713,294,682,358,952,191,326,422,808,846,450,851,624,372,858,358,582,693,254,278,349,394,569,460,158,770,712,805,942,274,667,774,986,2,198,544,124,886,370,935,406,3,780,913,289,655,145,146,371,485,516,77,905,663,443,165,156,479,548,299,418,566,826,744,473,189,766,286,51,195,684,495,137,609,989,978,314,343,613,117,220,545,228,147,973,966,298,978,225,578,778,883,273,43,561,932,321,965,112,927,671,493,441,255,767,872,114,609,221,192,947,460,268,113,591,296,306,975,487,836,195,461,878,454,519,159,481,311,579,989,510,298,259,662,611,945,431,632,263,787,61,737,116,912,207,539,210,789,493,366,139,266,675,441,890,20,393,870,958,672,516,784,547,563,422,189,699,133,42,60,359,944,609,818,155,872,89,355,7,888,586,134,865,13,506,383,540,234,998,531,585,486,704,361,902,333,252,498,825,86,254,603,835,333,191,916,989,488,931,909,711,238,469,439,643,369,884,27,604,65,681,266,492,449,937,471,690,981,213,362,949,95,894,650,693,779,545,716,694,967,90,360,206,35,228,814,750,557,46,303,689,40,323,85,731,241,663,918,507,91,325,788,87,291,673,759,870,65,851,472,287,259,53,293,215,880,488,903,276,102,350,975,929,339,642,661,455,188,831,313,177,926,205,373,160,672,411,954,556,383,647,236,94,624,823,476,516,335,967,892,5,107,914,797,556,603,154,777,40,673,632,572,210,144,780,689,727,341,213,481,650,889,100,356,220,392,185,457,152,31,179,857,12,712,874,156,684,876,636,100,113,515,114,106,999,950,230,703,777,403,598,969,556,137,904,174,261,489,576,137,797,522,660,619,923,66,316,146,721,38,502,323,517,799,758,226,956,940,330,509,551,54,405,801,320,146,584,838,824,339,153,297,984,385,557,701,672,141,172,40,772,588,954,431,774,40,903,554,35,536,820,749,692,579,837,992,607,102,258,917,293,679,411,247,421,595,798,826,57,476,269,995,419,614,927,424,526,459,174,305,27,860,9,876,921,2,887,357,112,253,882,591,335,50,863,461,257,308,41,481,731,689,916,211,138,536,892,68,708,199,417,465,276,589,302,272,168,384,9,927,709,218,169,150,581,526,318,965,2,728,275,281,602,417,616,972,66,953,779,202,270,372,643,453,167,878,272,333,589,874,807,255,582,292,483,488,117,826,174,356,192,348,260,260,984,152,350,883,106,692,647,59,25,384,969,205,356,371,904,0,970,457,205,774,60,826,819,140,949,879,388,870,390,103,234,430,755,51,10,972,568,878,728,137,422,333,104,633,359,419,962,324,596,888,225,511,792,675,307,201,529,148,302,943,475,750,189,651,255,922,688,584,445,838,122,120,617,882,885,491,776,73,734,151,63,590,650,332,836,586,391,450,907,102,914,142,770,905,570,107,786,423,369,460,277,514,179,371,926,855,508,734,381,703,165,66,161,746,115,623,20,628,52,200,627,914,481,912,473,410,189,950,476,490,580,221,299,262,325,986,682,442,172,871,728,858,394,833,114,202,697,447,298,603,66,78,151,129,430,702,157,133,311,571,639,590,33,653,860,78,531,768,748,377,710,945,407,822,905,743,667,805,757,909,850,458,129,480,35,547,457,739,967,767,468,552,575,774,402,517,560,152,666,519,513,818,832,931,4,72,966,670,993,726,502,727,928,376,27,138,576,967,417,187,259,605,134,774,106,275,82,934,895,809,781,748,29,192,311,187,336,691,525,56,942,282,4,899,562,483,344,691,801,460,979,120,777,564,713,446,846,661,847,463,191,69,519,351,472,787,600,394,340,987,964,947,888,501", +"392,594,838,397,8,553,89,591,649,940,362,81,464,163,463,504,375,790,672,932,233,416,820,316,735,65,111,400,117,712,183,794,34,566,519,189,28,339,945,304,402,759,777,346,716,911,21,379,899,897,933,23,292,622,479,268,106,703,956,366,597,72,926,949,809,365,516,847,928,56,119,806,672,900,594,755,676,3,292,953,52,219,698,334,66,816,227,288,556,90,973,501,742,76,333,849,246,306,817,810,87,504,789,895,954,476,21,441,996,242,852,649,714,909,857,323,404,133,353,812,157,538,662,171,591,920,945,519,173,544,930,447,763,736,275,879,887,227,138,858,780,481,481,677,799,430,116,568,162,27,731,88,455,73,223,404,760,759,11,612,485,917,974,201,738,835,474,916,615,989,472,433,14,329,343,324,74,175,354,426,308,883,519,882,217,906,761,792,849,616,811,548,105,333,490,484,105,232,199,512,398,569,635,455,648,915,76,599,560,18,861,660,3,188,16,938,889,329,811,336,481,631,325,677,549,801,90,388,993,479,900,795,941,874,271,348,737,4,459,91,186,93,20,312,208,378,911,783,349,790,493,989,791,423,953,211,362,629,376,286,105,173,411,351,44,503,436,581,800,80,742,775,526,776,576,374,82,642,155,448,894,113,914,978,240,778,268,219,921,263,14,723,67,886,277,67,802,412,755,635,512,754,436,963,525,638,186,866,634,149,188,110,537,798,364,528,534,847,919,535,384,20,370,403,279,257,132,653,310,12,543,154,803,762,944,61,257,948,188,504,336,408,18,483,944,254,387,65,562,419,560,200,770,76,474,69,456,752,569,253,90,14,941,737,318,412,196,803,677,450,507,991,425,414,182,195,476,799,289,64,331,907,760,235,633,137,400,819,855,425,140,453,236,572,101,925,52,955,429,517,999,125,724,32,435,706,281,798,278,299,275,829,419,691,637,594,886,264,892,629,638,945,928,322,37,267,294,905,520,661,901,500,32,479,409,767,893,574,911,555,818,55,878,962,198,15,454,55,816,954,685,503,261,379,251,612,225,683,431,794,536,761,107,777,243,803,81,719,457,834,533,407,919,712,744,382,24,388,382,619,82,153,331,250,556,443,652,210,422,919,91,594,104,207,528,220,733,3,818,954,691,339,477,369,683,745,82,879,969,623,56,149,441,648,171,491,883,180,649,541,912,447,439,164,377,63,237,91,123,995,987,839,929,79,299,745,295,698,294,408,642,857,883,971,98,40,401,320,905,146,454,977,614,479,823,339,294,425,505,732,30,148,529,794,854,287,634,688,185,543,878,89,911,95,230,445,805,623,359,814,487,587,532,921,12,665,286,454,393,528,283,110,371,84,877,760,233,471,296,748,838,853,654,178,722,838,474,256,706,5,910,236,739,979,917,587,762,30,387,918,729,750,858,871,954,159,231,954,585,917,492,881,498,113,406,650,56,493,128,741,858,836,888,259,515,713,402,23,244,267,805,758,170,899,868,561,787,114,123,998,704,139,238,403,594,345,458,403,786,301,937,900,101,808,132,156,86,512,547,193,812,935,251,458,954,856,596,325,5,575,81,869,266,57,675,904,978,607,381,461,468,930,416,713,2,886,428,147,32,898,40,429,906,562,551,148,921,497,289,199,388,275,34,524,21,551,172,484,208,145,801,13,7,619,314,882,391,826,336,858,9,970,0,409,985,603,386,636,111,155,543,363,712,228,41,626,563,445,362,695,2,714,657,544,116,503,509,646,15,689,65,106,23,853,513,546,236,411,188,88,829,425,990,839,46,22,459,783,709,558,417,431,920,950,869,69,573,640,608,87,411,910,388,492,292,637,958,282,714,861,973,86,711,452,911,494,661,542,490,284,73,304,790,675,880,714,242,225,681,25,549,23,719,635,215,771,475,599,826,405,907,231,659,243,722,147,54,822,717,273,574,605,526,136,364,961,25,764,304,705,380,264,191,184,945,666,179,569,616,155,778,758,82,854,409,64,339,350,265,283,722,995,640,540,520,212,718,203,829,300,358,548,895,82,446,400,643,5,433,196,155,717,566,26,535,178,727,396,617,82,25,743,947,8,128,249,919,469,848,202,291,352,949,784,751,748,86,323,218,187,585,223,284,197,23,350,656,851,465,430,212,306,74,538,506,353,942,314,465,663,891,430,940,532,996,891,301,960,526,664,113,714,307,345,913,120,968,319,403,622,935,860,168,159,475,696,188,366,661,343,652,31,729,41,471,456,363,389,622,284,264,728,430,415,307,746,191,120,351,251", +"649,90,590,333,808,22,777,669,780,984,998,497,783,133,364,445,881,746,625,612,760,700,596,262,199,958,781,230,969,648,237,152,862,387,654,182,483,674,113,693,944,512,332,762,427,675,616,469,13,312,809,997,368,974,684,517,347,408,730,795,538,998,22,223,374,170,775,893,219,350,617,185,886,255,443,423,732,965,800,841,714,111,211,461,632,323,619,444,441,923,165,572,341,788,56,649,800,833,795,954,504,897,500,983,249,845,123,770,468,50,283,64,911,145,143,11,78,458,507,703,181,336,609,793,504,96,971,460,881,234,427,72,376,63,100,784,127,832,698,15,192,472,167,674,44,78,470,490,302,520,577,974,861,550,157,30,320,107,358,526,992,897,341,335,845,145,110,947,279,789,559,899,485,185,893,804,413,800,264,78,841,806,265,977,242,250,151,75,736,931,806,14,210,36,485,221,463,938,10,198,558,710,198,484,512,443,644,768,420,77,789,788,7,595,118,392,885,718,884,341,700,559,911,659,291,365,694,890,135,545,614,882,199,354,485,199,197,921,920,212,660,703,692,599,535,90,329,375,507,649,575,673,819,426,834,895,808,888,184,874,314,32,202,606,878,352,814,367,143,462,175,605,932,598,181,855,197,142,417,782,794,819,361,74,54,356,173,930,230,610,183,372,46,569,67,872,371,348,599,275,601,104,89,268,468,307,245,789,988,878,440,599,324,898,334,379,577,517,82,289,657,323,721,126,71,101,889,377,521,281,940,846,398,202,420,166,731,869,687,34,336,506,295,743,825,566,899,197,472,724,90,106,233,535,894,690,27,265,844,500,617,119,875,1000,214,54,990,322,47,683,29,445,711,435,995,625,958,567,175,826,30,722,358,876,682,250,490,263,199,263,636,206,985,785,720,177,542,326,600,822,926,130,79,750,827,826,403,974,144,993,95,466,117,12,575,625,216,104,308,156,724,168,566,468,860,186,597,644,242,710,786,812,384,401,168,110,425,687,601,450,822,841,840,474,498,538,67,728,521,331,551,618,321,261,391,95,733,214,202,110,966,645,124,795,159,196,21,553,291,665,821,586,465,984,410,131,752,565,45,594,69,312,831,934,635,760,338,606,905,120,664,294,536,911,734,380,11,308,924,85,261,88,554,179,384,331,881,14,314,444,665,266,637,180,564,772,595,56,447,142,200,772,864,34,474,830,70,935,10,688,593,369,705,949,545,926,135,200,427,795,181,793,684,77,485,645,24,245,749,531,739,892,946,448,938,873,577,752,20,297,96,165,918,126,886,297,340,356,738,941,331,66,299,743,161,605,410,551,771,660,541,508,609,328,388,339,71,17,402,1,352,745,580,470,104,865,63,51,940,571,77,134,424,248,640,763,140,818,194,469,327,868,278,716,135,607,902,720,348,830,389,329,344,295,460,174,689,56,597,124,242,581,572,806,786,19,142,990,155,355,737,310,404,293,165,431,822,627,816,838,92,868,276,221,644,929,505,343,687,301,36,512,265,63,27,998,210,151,215,132,146,440,111,429,572,95,392,231,27,584,464,498,882,478,810,719,674,933,30,888,530,938,13,901,128,364,608,243,204,388,939,175,655,751,799,582,551,620,615,968,48,93,806,551,508,257,249,944,34,2,716,986,571,924,323,833,933,314,747,13,981,605,426,110,624,791,977,509,602,652,643,457,409,0,267,437,522,149,195,215,790,463,479,854,722,315,110,593,836,78,342,485,282,642,855,287,4,113,679,625,914,739,808,476,37,867,293,144,647,683,957,851,278,164,517,904,398,327,420,410,599,94,862,807,307,451,454,167,864,812,348,329,658,505,338,633,52,662,200,649,853,865,742,930,309,153,972,182,624,412,300,316,693,342,848,599,63,904,853,139,981,689,146,164,145,979,77,829,1000,743,722,79,475,600,647,864,26,618,694,272,522,726,117,450,314,835,923,36,48,561,263,703,683,298,103,652,782,952,382,631,178,728,368,137,641,932,434,561,447,128,977,657,959,454,29,174,684,956,230,455,662,702,998,78,145,463,304,945,504,755,652,969,342,575,333,910,53,379,114,66,26,345,200,62,769,861,478,13,62,863,435,723,254,154,273,230,622,689,150,820,250,349,834,17,910,672,584,306,902,101,740,521,157,699,102,117,348,561,394,195,147,660,429,572,563,564,826,819,877,296,968,872,48,410,681,927,845,261,335,281,680,121,659,957,253,100,935,910,512,288,150,759,40,825,179,79,787,862,327,967,234,899,772,46,11,614,628,440,752,627", +"951,745,964,62,65,91,903,814,750,133,915,495,577,937,395,969,578,751,463,88,456,352,569,605,106,14,677,451,761,912,143,392,489,218,697,813,801,805,425,687,428,258,358,735,302,450,686,554,974,274,383,646,582,958,719,293,232,890,354,442,173,602,640,357,846,171,269,410,634,229,245,69,631,310,119,770,625,129,158,826,955,13,410,18,41,414,893,626,710,776,982,802,952,944,176,107,336,719,975,80,815,453,302,164,143,884,977,385,745,305,420,36,749,491,566,637,9,182,549,745,716,522,318,203,817,855,232,481,908,131,841,485,698,905,979,497,569,629,755,427,747,462,878,632,8,641,204,709,227,232,266,137,320,22,399,620,300,482,917,910,61,869,820,438,258,276,135,937,180,668,142,425,235,615,231,698,747,38,698,401,964,792,360,392,635,520,647,762,414,983,160,193,983,516,151,450,222,323,469,227,457,420,554,712,715,605,252,815,731,974,831,24,728,617,262,84,140,825,291,398,937,999,964,271,386,543,322,877,126,357,685,639,141,16,397,100,744,297,22,368,376,13,403,3,810,442,389,897,487,619,509,920,850,428,492,401,250,919,898,30,803,195,221,838,999,431,895,70,365,115,172,230,346,721,425,60,779,905,962,572,334,50,567,372,266,220,552,756,38,463,190,836,697,523,827,237,673,505,230,863,145,493,848,365,443,380,890,895,505,79,338,567,940,902,848,543,288,236,902,152,322,617,206,466,333,980,93,653,141,294,641,677,797,78,688,637,554,218,439,886,172,246,889,741,125,498,546,427,436,8,21,719,919,137,703,524,363,270,948,756,582,461,223,894,949,249,349,880,654,287,669,761,757,877,124,809,58,565,418,289,318,13,62,221,350,456,109,105,289,229,391,760,16,182,564,405,563,263,86,200,493,62,977,344,551,630,343,274,257,461,422,135,592,77,192,303,537,112,699,382,617,363,47,164,772,578,401,244,971,262,935,731,558,147,60,542,836,974,339,380,486,407,721,704,430,200,807,9,474,981,599,714,627,98,326,583,744,361,596,580,863,863,507,248,408,727,35,334,190,318,824,946,194,521,612,285,279,164,12,464,749,296,731,875,697,196,109,797,282,967,227,142,42,74,201,11,448,336,194,172,83,759,296,177,949,639,389,521,355,194,2,702,750,649,206,16,223,203,673,33,790,47,353,364,157,943,238,9,133,133,70,246,366,234,917,959,196,325,136,223,512,52,764,397,881,973,686,680,709,142,52,434,622,28,418,756,756,891,348,419,325,272,373,525,980,185,6,738,701,188,99,362,318,213,209,51,895,643,898,713,473,990,666,499,442,357,689,536,498,69,128,189,183,767,5,833,650,158,170,881,975,856,560,922,490,798,382,522,886,519,357,971,46,109,471,239,718,781,691,870,150,678,430,687,206,782,232,632,46,888,249,759,16,802,770,435,359,83,711,599,533,766,289,820,902,115,324,179,386,459,477,996,740,371,17,35,434,941,586,833,949,501,26,334,403,783,930,880,338,151,708,431,347,542,812,72,127,940,801,171,580,605,874,846,667,457,352,889,314,454,884,580,371,175,784,197,444,922,770,430,653,394,771,268,896,873,54,785,928,681,746,778,757,638,41,491,525,806,274,959,814,719,649,856,897,795,822,171,760,46,79,951,945,52,128,135,916,393,119,158,139,205,985,267,0,399,866,918,359,226,207,214,960,735,198,264,236,317,946,434,563,889,604,320,147,231,882,403,920,520,297,770,240,509,174,454,318,957,937,102,653,157,838,145,251,799,558,862,52,242,240,467,994,124,556,909,29,384,913,505,568,996,973,194,728,711,544,941,404,20,434,953,304,611,415,968,128,265,475,225,628,684,320,333,10,132,683,598,807,811,557,742,176,877,152,213,879,199,480,55,922,18,24,739,545,19,596,393,358,482,413,734,462,184,216,898,805,268,543,811,8,803,994,273,735,251,599,99,156,679,430,947,674,527,389,241,977,627,955,994,572,798,268,920,228,242,515,269,770,488,409,435,295,119,423,95,805,324,400,180,188,567,37,485,355,350,167,590,843,455,483,865,249,848,978,81,613,7,601,680,596,809,61,525,747,810,966,78,709,817,694,98,461,363,597,129,216,709,713,610,804,443,335,110,506,151,291,935,615,647,917,243,543,450,455,669,517,421,946,170,411,179,623,370,426,814,71,568,791,845,247,103,425,477,44,706,247,71,200,498,20,632,54,206,690,759,209,286,818,762,65,44,311,827,530,866,391,211,123,44", +"927,7,760,296,759,684,861,827,454,838,243,342,739,939,791,529,545,484,353,599,652,193,104,541,17,582,867,678,935,428,530,80,777,935,978,239,869,810,599,802,926,333,650,165,472,774,292,292,30,436,264,869,509,122,108,291,846,855,36,369,369,821,812,605,502,705,309,591,547,299,144,546,975,46,953,162,492,311,175,533,99,701,675,269,809,536,688,239,923,379,877,715,712,531,851,161,888,574,778,905,643,304,321,662,316,765,46,423,11,706,13,776,436,768,583,598,734,440,838,929,26,62,236,733,762,75,75,30,165,478,472,919,678,323,271,712,821,712,636,473,507,759,334,136,157,903,113,655,95,24,57,983,626,337,416,181,264,560,76,826,858,232,267,853,676,837,769,155,24,85,204,913,359,380,112,438,835,94,319,210,420,561,474,268,984,75,46,399,126,561,83,215,334,262,152,902,941,208,464,485,655,845,256,54,312,775,264,651,843,94,559,75,826,681,905,393,20,626,988,375,727,959,573,932,676,743,778,49,651,636,646,507,940,663,829,293,768,55,966,57,287,375,180,312,299,437,81,95,523,600,238,989,512,305,518,241,355,739,659,137,735,985,622,871,909,874,601,734,462,687,600,838,874,524,992,617,796,908,59,921,19,522,515,14,607,532,849,816,8,677,247,416,377,168,813,586,523,13,797,280,111,522,451,9,253,321,979,253,239,260,157,769,391,703,199,597,12,232,693,501,793,516,160,499,513,545,153,241,728,789,737,756,654,921,863,11,723,288,347,979,612,470,776,611,682,500,130,849,970,321,32,848,640,151,589,307,361,400,970,478,876,668,520,33,737,867,770,442,178,73,19,415,812,110,540,749,940,448,837,770,128,511,887,57,919,227,170,2,847,829,523,84,55,380,334,14,238,114,212,652,764,955,937,37,212,149,149,518,137,761,404,271,81,538,504,495,17,456,836,777,806,274,198,425,446,661,1000,948,443,612,439,136,372,718,204,554,480,358,466,336,872,79,651,219,830,465,824,456,407,507,178,2,127,505,641,106,288,229,590,293,307,8,848,780,63,71,925,442,628,126,967,256,809,765,667,759,750,551,70,781,854,389,605,278,157,177,713,749,384,89,376,930,467,837,28,328,114,618,163,783,546,590,412,263,283,700,576,258,550,252,186,477,690,584,744,747,936,623,287,375,583,519,981,577,873,810,830,623,242,485,13,107,970,656,125,132,407,445,296,219,948,682,490,561,942,168,124,112,608,385,338,855,129,137,874,497,159,493,49,201,303,974,550,404,173,313,182,558,909,794,788,159,93,117,649,835,586,313,578,989,191,755,289,385,679,844,154,123,385,193,60,74,770,176,638,420,538,389,926,747,61,147,113,665,99,226,398,318,46,219,117,585,102,144,342,670,211,903,900,645,612,375,725,108,366,343,794,471,522,544,501,658,995,762,692,33,211,536,341,868,614,929,778,481,816,565,53,718,548,595,843,348,210,453,90,681,721,473,876,340,343,75,763,184,126,614,614,60,886,672,409,456,173,318,216,354,31,688,213,21,805,808,551,688,413,583,638,643,538,987,779,119,620,350,607,367,921,359,195,546,128,822,391,826,134,569,789,335,12,982,705,325,591,130,888,82,570,155,686,294,419,32,151,690,864,554,4,474,600,875,652,225,909,462,366,427,490,724,170,844,76,774,603,437,399,0,647,715,908,540,536,483,667,918,797,579,375,855,560,991,599,268,31,662,193,229,831,914,974,238,360,276,947,6,243,224,910,397,408,850,503,704,125,287,704,252,737,305,888,609,189,914,916,511,331,162,786,971,319,515,590,405,140,40,918,228,826,407,548,394,509,612,339,992,730,294,950,809,431,769,25,636,462,869,940,648,132,316,52,534,405,611,161,274,627,669,943,395,464,903,531,838,8,735,314,842,982,305,124,810,413,489,576,38,968,677,600,279,384,472,396,76,585,463,969,946,278,328,69,872,420,564,493,682,5,409,591,411,947,881,793,990,760,91,929,26,312,30,489,273,517,146,153,150,716,582,330,848,951,333,333,439,464,865,415,504,56,973,502,555,39,407,327,157,264,125,479,35,103,267,934,269,813,155,185,487,511,801,994,500,751,155,575,98,952,183,519,466,465,399,265,75,981,322,559,236,805,394,665,863,613,153,395,921,342,563,446,964,794,251,88,935,468,591,176,719,188,805,563,599,816,550,726,222,218,349,279,408,972,446,673,192,835,814,692,711,21,529,352,651,752,392,661,520,996,934,957,813,212,929", +"757,24,201,431,13,191,457,582,705,320,509,392,675,488,222,623,244,128,432,273,567,620,281,765,928,145,14,279,685,601,799,389,855,315,96,928,160,716,915,671,993,590,109,361,600,538,503,597,726,953,588,280,12,380,561,141,371,481,166,750,725,952,266,182,769,520,798,968,485,566,2,933,643,598,378,982,568,95,416,724,2,410,279,967,522,933,183,572,839,997,68,496,307,842,477,794,383,459,937,65,141,944,727,894,933,211,802,498,600,732,876,770,564,122,330,369,172,254,600,599,551,510,111,556,188,962,383,2,876,119,442,888,543,224,982,372,106,661,761,563,171,739,710,367,24,514,866,436,584,125,834,542,261,569,554,940,338,287,928,17,436,115,239,75,153,773,221,50,994,379,102,136,544,751,171,412,523,832,94,932,11,554,293,416,162,537,423,715,767,930,191,78,522,819,920,487,260,631,387,243,324,371,660,501,899,561,255,127,446,954,643,829,598,568,680,971,178,538,749,576,355,980,122,509,307,833,992,375,810,840,654,988,870,100,903,567,785,510,738,309,774,591,770,136,889,131,237,584,25,577,307,246,497,48,802,658,35,514,167,147,304,848,410,253,584,333,399,551,844,800,553,833,990,69,722,385,192,694,491,138,846,687,130,970,258,969,436,585,82,695,146,822,655,895,363,930,396,803,223,827,343,598,790,42,754,544,41,677,155,592,882,363,590,806,283,590,263,540,225,696,346,718,318,674,708,751,89,486,494,320,76,198,465,582,411,233,785,984,388,488,588,326,156,516,126,622,829,488,974,141,636,88,509,182,802,169,992,854,628,271,659,318,52,16,688,652,72,410,271,432,804,744,299,982,213,162,170,611,353,125,824,613,269,226,471,81,123,362,231,136,358,976,865,237,311,202,138,467,68,237,707,745,696,598,563,108,520,369,95,787,383,217,945,929,651,926,7,423,742,301,520,471,579,606,789,772,134,686,202,273,218,733,888,25,64,628,18,834,259,797,557,838,363,61,803,430,85,51,760,738,94,495,248,615,452,798,652,2,407,435,332,391,446,42,287,634,873,863,604,388,358,611,399,29,842,711,31,622,510,12,742,688,875,618,949,108,280,713,97,449,321,149,971,27,794,27,974,222,411,309,957,156,887,569,407,370,787,862,738,414,833,407,973,4,191,475,267,796,447,847,971,639,348,923,812,272,863,497,267,651,484,818,148,523,791,114,320,807,651,959,959,917,454,263,945,69,470,828,816,431,245,469,813,866,644,163,398,731,410,30,796,722,369,719,84,10,612,442,592,814,10,93,52,166,768,259,871,270,576,960,157,625,296,805,53,823,476,512,752,210,749,365,763,851,144,904,457,856,713,204,960,120,920,806,243,161,186,581,724,390,548,872,174,205,963,63,71,909,530,797,218,801,943,367,706,295,729,705,760,615,671,212,247,711,510,998,422,230,870,169,560,741,167,520,356,452,747,789,750,992,608,968,843,589,639,613,689,428,916,508,456,389,936,280,70,331,372,653,620,336,409,802,388,71,28,487,397,533,480,969,528,754,823,558,209,130,133,747,358,47,798,88,372,512,190,578,324,157,252,316,242,547,291,265,566,765,613,291,781,237,215,523,271,127,788,106,926,859,755,648,654,562,523,789,478,701,910,918,592,785,720,793,36,101,273,123,685,621,145,113,794,60,386,522,866,647,0,463,958,71,17,838,122,395,522,237,904,480,773,646,399,180,698,36,455,701,765,710,685,482,379,216,205,882,765,755,265,198,833,437,266,534,232,79,305,68,469,612,919,684,191,194,780,922,592,549,146,575,708,931,758,779,33,447,414,718,123,387,675,279,90,622,247,44,552,543,298,233,653,710,653,202,946,976,715,770,351,714,429,48,938,485,461,778,90,905,49,750,443,273,351,603,904,396,567,532,84,579,20,877,788,710,575,572,119,619,840,94,243,660,739,334,65,242,958,81,710,268,734,551,229,219,801,225,399,530,394,711,742,100,448,510,346,71,495,884,203,549,115,307,643,898,643,725,409,469,826,687,354,48,497,609,916,340,130,608,332,779,379,866,68,342,809,452,56,495,378,465,664,669,880,753,696,244,893,423,182,72,630,982,42,440,93,223,710,978,529,68,473,498,569,170,920,432,581,220,180,718,328,939,691,756,166,689,792,74,85,170,39,706,335,288,433,593,157,87,922,428,916,975,83,515,48,508,225,521,614,3,62,910,805,62,862,220,100,126,155,845,244,852,189,47,341,754,513,356,459,265,710,531", +"835,252,16,960,59,882,133,892,780,835,381,329,748,37,877,351,911,566,629,398,264,401,402,876,910,282,56,716,398,710,241,578,737,253,725,684,724,621,959,33,863,279,609,495,908,126,932,348,706,677,234,651,626,508,643,483,134,513,64,57,760,410,589,250,356,187,777,710,537,156,157,714,546,86,801,715,566,279,888,403,384,113,939,511,725,795,407,574,363,481,398,325,637,316,683,739,445,341,518,480,986,15,528,158,959,941,865,202,308,317,202,527,87,879,364,28,195,289,62,420,576,695,118,517,614,885,367,151,283,524,168,20,726,365,323,117,552,336,865,106,860,995,913,935,866,356,533,819,958,728,923,433,854,454,341,299,543,338,175,163,634,607,184,249,243,411,851,314,485,869,435,619,863,973,103,870,168,970,520,455,4,54,875,87,304,711,511,757,56,896,159,298,36,327,364,191,223,750,728,668,583,298,398,436,740,426,201,104,668,991,552,860,275,164,86,310,284,850,77,835,360,537,214,234,533,950,91,788,112,54,305,40,839,624,702,661,596,929,943,602,216,889,553,583,370,209,961,921,120,305,785,47,240,263,824,896,841,115,240,591,450,933,465,115,554,482,933,347,811,729,389,38,218,961,194,631,549,489,596,119,850,612,887,357,589,217,104,185,361,226,378,780,166,658,748,275,101,277,813,789,854,349,685,731,83,908,940,784,720,938,601,240,425,957,877,887,37,876,771,904,961,601,693,163,593,99,201,243,165,936,718,123,216,18,364,208,460,730,915,36,697,968,665,545,269,501,532,188,788,883,832,83,890,860,932,918,988,216,866,392,324,518,518,26,929,767,962,944,622,363,8,67,585,587,897,213,470,714,165,63,857,836,245,465,797,23,490,626,986,412,498,911,175,68,435,695,233,410,311,634,226,928,994,691,895,993,759,688,320,739,976,457,861,931,518,599,41,619,624,372,96,125,126,145,94,863,736,232,930,628,303,99,47,341,815,636,945,118,159,587,80,860,979,928,697,650,623,259,930,438,425,894,252,116,944,447,448,447,642,7,314,200,845,567,212,70,380,125,176,247,889,491,223,293,386,681,788,857,550,960,660,432,882,909,413,126,240,633,313,27,476,496,595,320,767,54,736,66,634,38,653,655,455,410,133,384,549,192,819,39,986,911,591,723,836,434,179,949,417,517,15,231,498,195,242,461,326,287,457,361,664,489,805,431,893,463,277,338,27,882,491,264,47,179,851,964,717,953,433,983,727,622,312,678,499,668,429,267,244,249,711,673,97,152,862,684,716,865,356,47,845,769,544,687,574,455,998,114,669,95,132,663,23,391,456,407,776,97,545,641,162,370,998,321,862,85,579,493,116,969,82,6,90,622,560,71,329,140,29,325,768,936,207,244,583,7,651,60,225,853,419,330,102,888,887,254,927,117,768,484,458,67,161,401,290,285,731,818,209,660,85,841,12,857,781,576,810,367,945,587,154,957,865,334,236,937,158,156,659,691,750,792,825,145,488,228,525,906,986,734,863,139,296,727,998,457,551,615,206,961,893,97,254,133,409,147,491,196,718,456,18,109,105,272,891,351,352,214,725,194,7,13,7,863,337,303,180,11,573,613,46,199,140,572,108,969,397,644,748,118,417,647,145,185,89,15,122,79,813,896,524,929,376,491,152,232,396,312,191,478,738,826,636,149,918,715,463,0,275,860,309,694,179,608,355,193,588,578,898,321,253,119,881,84,988,840,346,853,301,314,64,647,451,282,399,206,755,495,861,579,624,371,323,903,683,332,691,840,527,391,39,134,4,381,241,393,1,261,803,427,368,152,917,649,794,320,20,917,228,375,70,177,29,738,379,314,570,911,4,621,419,396,307,808,439,201,315,57,394,475,800,286,421,435,554,619,440,536,492,176,242,645,619,659,437,835,855,467,751,311,754,656,870,420,875,660,596,218,149,709,454,605,214,298,283,88,670,621,758,19,118,829,313,852,547,842,103,803,613,61,723,523,134,429,371,337,865,653,998,306,827,634,679,754,962,37,520,421,503,238,535,361,52,819,949,540,164,409,646,524,445,743,279,162,590,51,379,830,281,117,288,779,460,708,406,605,262,472,106,480,255,626,972,498,107,239,3,590,106,617,828,570,774,109,171,455,270,344,350,823,850,886,93,161,869,584,18,810,218,638,71,639,50,115,548,335,610,136,950,408,54,389,221,558,345,92,394,604,478,870,320,849,104,118,392,641,122,968,868,615,288,270,520,676,133,965,389,714,603,699", +"567,528,9,424,364,530,711,200,998,760,237,404,729,929,786,773,723,761,494,280,477,775,486,919,754,343,431,821,111,210,584,397,494,741,232,490,411,329,329,963,81,507,257,130,619,126,779,210,68,611,82,524,993,971,592,325,371,364,240,382,604,503,529,440,802,920,528,98,390,733,551,106,215,55,147,624,342,275,749,751,818,632,273,662,340,820,586,72,484,24,497,169,689,431,598,981,847,727,676,197,428,829,436,602,109,245,715,91,607,989,435,84,980,687,144,683,549,852,299,431,865,523,706,674,381,730,754,89,421,600,835,695,392,214,37,217,445,823,463,296,466,305,778,539,297,392,119,683,468,314,647,606,943,273,685,53,486,912,552,950,57,123,824,608,209,334,330,755,372,775,32,589,130,633,535,202,462,224,69,886,479,786,694,445,63,121,377,223,343,494,919,522,514,874,261,493,19,295,498,491,612,735,884,819,526,910,488,760,175,844,375,901,754,887,578,598,880,740,756,298,714,38,320,52,390,711,547,406,729,827,884,638,910,354,237,112,796,456,766,387,873,485,508,459,867,345,11,772,200,298,692,864,616,707,632,715,507,78,68,127,10,450,135,56,466,180,615,530,356,47,906,623,887,28,919,877,976,62,491,218,90,159,525,854,974,722,785,461,642,667,166,643,252,565,984,217,202,99,386,623,946,954,477,644,114,847,501,9,944,334,331,391,996,854,543,36,232,45,790,802,972,348,594,514,508,483,767,158,834,622,973,596,504,923,851,316,192,128,412,888,439,109,990,323,169,78,268,555,534,717,488,915,562,595,367,286,182,988,236,316,38,913,847,1,266,365,892,802,415,506,142,508,61,668,944,814,355,886,358,481,24,787,580,745,592,194,298,336,797,264,853,971,2,606,865,658,89,31,49,352,717,805,440,775,579,993,905,404,749,751,587,950,767,194,411,54,78,152,578,46,252,488,472,499,174,732,840,979,330,701,409,194,818,621,967,599,660,989,585,764,539,941,175,504,631,167,156,679,197,11,371,223,134,581,37,34,681,654,37,933,298,378,906,145,175,955,476,875,809,916,512,176,267,822,950,172,957,753,534,363,874,228,111,555,759,678,34,247,812,291,355,171,425,683,677,705,609,166,639,351,779,75,260,490,23,784,248,424,956,220,712,850,386,438,466,62,969,310,119,243,765,292,31,126,66,906,32,200,632,346,258,902,546,585,466,34,671,820,896,990,510,276,662,692,491,433,747,872,49,542,531,647,495,763,528,319,811,123,394,507,594,843,464,240,60,441,184,908,791,878,943,291,591,135,608,563,52,927,767,83,428,743,226,123,221,481,292,432,762,230,232,479,472,474,342,363,377,607,630,886,795,631,175,134,850,405,887,815,32,86,805,532,444,651,992,496,15,388,350,798,840,154,146,288,206,276,130,501,893,59,626,670,242,801,614,832,71,60,298,597,100,243,947,271,480,443,665,679,762,301,465,865,420,438,884,381,283,356,952,162,43,168,671,206,481,243,200,256,963,487,821,475,342,209,437,154,25,58,191,39,458,499,859,713,427,504,179,560,342,972,859,387,414,300,576,634,366,212,288,491,963,69,130,535,732,107,403,886,995,37,912,868,216,365,157,564,205,293,936,741,670,575,443,41,583,271,118,826,169,533,140,760,15,844,431,204,488,164,247,721,905,819,111,195,359,908,958,275,0,205,540,920,552,803,163,669,332,727,4,986,103,277,520,294,219,280,184,20,766,587,655,218,301,266,163,478,434,21,597,740,885,388,83,203,369,344,513,11,904,10,275,449,793,171,277,980,764,36,434,70,934,539,945,842,665,770,745,9,772,221,664,389,331,211,110,845,714,563,764,261,662,746,88,379,34,866,516,153,417,979,660,339,194,449,446,897,396,515,543,406,423,701,919,245,589,672,61,530,964,691,112,784,658,216,460,7,298,760,89,475,263,158,832,115,526,901,113,55,159,958,469,134,486,208,202,604,206,617,663,512,252,977,297,149,937,544,839,521,376,7,631,738,60,534,64,544,992,677,538,569,971,817,4,156,739,57,349,941,764,320,296,321,683,794,535,424,958,490,68,723,905,92,628,321,197,720,879,609,276,82,396,609,550,538,482,269,659,152,78,478,488,195,116,837,101,745,232,618,548,898,988,16,234,10,603,43,693,127,361,649,64,213,544,923,591,598,439,97,992,538,479,494,129,164,985,575,395,792,58,709,446,512,655,956,247,344,178,291,74,501,794,398,705,835,736,253,956,775,264,38", +"472,973,160,916,50,691,487,473,761,288,662,424,364,259,614,635,714,637,555,265,608,954,745,583,496,744,599,879,566,531,952,119,895,378,551,896,411,974,972,768,603,427,607,756,846,14,807,759,455,191,557,380,683,172,562,972,708,863,701,271,350,63,69,102,720,715,555,287,796,478,590,953,314,567,792,881,26,576,666,209,229,797,353,165,127,31,903,972,68,192,908,418,109,531,599,928,988,873,265,826,198,513,725,202,59,980,555,342,337,587,798,736,388,868,406,780,183,714,999,839,888,589,829,508,377,812,270,929,216,584,43,550,865,878,209,517,402,558,397,894,305,894,549,151,382,713,310,518,615,804,680,728,508,583,926,958,64,250,271,620,862,794,26,268,856,547,170,262,636,383,721,401,651,385,252,498,928,47,633,682,967,779,893,271,594,207,326,597,264,188,385,680,346,73,433,351,677,371,744,996,453,667,136,916,41,211,847,728,571,675,192,27,684,243,17,544,544,363,855,705,318,949,257,777,337,642,839,502,855,256,472,58,117,607,470,314,511,161,470,218,406,639,716,947,668,76,595,503,152,256,314,723,673,897,117,587,512,317,554,943,954,1,672,860,682,809,358,537,205,194,377,90,679,525,170,449,780,290,814,154,240,30,703,662,287,863,56,463,624,201,164,524,928,42,99,288,445,255,14,565,466,868,47,270,67,232,868,989,670,291,805,626,385,679,192,171,957,117,778,149,743,286,321,652,503,323,662,16,360,611,794,647,946,539,613,883,482,39,161,242,258,75,58,985,668,587,105,948,650,644,731,7,82,106,970,293,338,657,115,904,855,146,548,476,221,143,382,747,828,221,63,263,28,336,201,512,409,658,26,540,262,220,976,818,605,29,993,72,713,418,299,64,560,720,629,316,491,112,596,386,36,830,896,833,789,323,513,213,991,623,710,893,32,146,673,710,910,963,485,648,391,234,834,28,927,986,383,420,451,755,448,213,470,420,957,81,840,325,687,269,60,787,505,204,508,391,727,522,679,528,574,117,682,696,635,12,358,313,893,927,792,979,508,79,174,287,231,58,378,957,574,50,686,718,846,193,5,434,249,272,62,166,343,38,574,512,753,83,98,457,251,41,382,199,774,920,272,273,319,135,623,154,278,472,440,636,935,463,466,198,800,755,261,241,582,992,938,667,417,802,259,268,151,511,127,368,946,477,151,956,894,973,462,525,485,756,216,559,963,992,693,19,607,172,614,27,625,567,7,965,699,45,16,648,800,850,498,580,337,865,978,777,213,536,30,791,114,527,111,865,955,272,499,866,146,210,641,816,948,456,68,659,211,411,635,967,796,260,345,471,70,503,868,548,902,270,920,87,92,805,402,469,772,676,582,443,473,641,712,125,455,156,950,115,889,686,11,124,756,569,387,669,180,636,299,680,93,48,85,114,928,328,965,158,831,669,555,401,979,687,863,950,889,87,190,432,814,150,167,807,148,207,12,482,474,348,963,16,970,916,985,38,555,742,891,550,94,358,982,614,614,155,151,636,234,330,913,907,359,103,594,266,262,343,906,298,157,804,181,809,782,379,102,549,415,187,841,239,172,118,897,549,520,943,383,315,41,616,12,728,698,91,527,154,682,834,383,537,511,881,939,397,612,478,275,849,852,91,351,374,374,610,784,830,442,66,359,183,382,419,430,140,155,215,226,540,71,860,205,0,497,718,909,24,506,662,662,536,471,421,482,309,343,131,992,815,217,553,957,926,924,430,540,418,655,996,11,343,2,268,93,228,116,2,606,836,185,7,966,677,145,892,70,528,637,663,985,643,649,463,984,799,759,94,550,253,247,653,19,712,469,271,377,285,512,239,372,96,928,105,105,126,844,219,391,391,385,860,894,886,430,314,464,616,717,581,728,510,520,965,634,372,144,797,852,754,850,784,552,612,894,971,263,905,97,155,33,863,891,745,318,629,711,324,317,642,985,479,49,249,721,794,28,339,18,88,789,972,279,704,557,940,446,123,519,541,103,510,101,980,769,455,820,603,275,895,135,876,569,531,670,69,813,625,714,735,75,461,579,736,162,524,884,518,246,726,805,491,869,94,819,452,527,917,464,38,67,994,553,976,416,134,283,346,829,154,658,529,747,95,507,299,21,411,366,791,649,741,856,639,76,649,517,429,680,302,536,101,983,115,636,266,249,30,944,617,170,998,95,10,895,355,376,850,527,6,726,575,728,394,356,365,182,127,185,540,880,79,700,598,230,953,410,101,389,83,204,347,133,462", +"530,117,868,47,485,712,708,946,392,775,818,309,625,598,348,906,940,251,354,785,772,167,49,692,257,570,115,908,172,2,591,397,63,411,387,128,351,130,399,610,746,830,48,876,420,258,317,283,962,463,451,377,238,933,522,844,600,505,271,197,552,856,552,790,579,395,976,446,338,482,862,411,259,399,332,727,351,615,67,585,743,843,607,895,467,790,32,327,788,351,149,534,487,324,859,573,649,433,335,579,979,979,906,140,684,738,129,309,531,193,948,255,153,472,836,84,840,504,421,324,331,342,275,170,809,817,716,597,541,94,316,833,775,476,161,506,578,675,675,168,522,736,251,562,203,463,872,339,375,178,540,745,462,90,226,806,241,582,991,978,547,851,959,491,943,474,150,451,999,646,448,558,102,279,323,131,547,179,898,681,534,246,291,221,848,675,689,570,182,150,764,621,901,485,550,561,993,190,453,306,636,217,264,289,518,226,38,286,248,387,85,346,758,577,730,724,664,211,101,770,63,612,361,649,864,412,10,251,385,955,717,208,923,290,737,607,635,983,149,544,352,265,508,794,354,879,669,849,985,568,621,743,12,62,107,34,525,654,619,974,521,960,233,297,262,22,507,170,979,573,757,189,51,909,480,871,756,281,202,889,413,812,372,241,158,519,65,467,783,308,41,111,679,484,87,790,239,82,357,727,722,764,200,551,665,625,602,122,602,80,136,44,502,84,608,113,220,623,834,818,371,166,174,556,40,143,289,738,11,814,275,40,767,173,970,819,871,742,729,544,150,300,988,800,240,141,93,228,380,722,472,202,548,887,949,338,337,135,151,372,468,712,463,342,510,875,266,57,130,200,461,748,129,603,884,26,251,27,489,807,204,744,722,64,692,266,197,732,437,566,814,894,863,715,443,196,551,234,954,55,751,246,113,398,442,616,553,554,871,39,799,360,73,492,396,637,835,178,980,231,779,304,670,877,663,554,881,239,130,556,821,388,565,13,783,541,15,198,417,579,360,906,645,96,166,26,990,328,137,140,499,462,581,511,947,32,815,939,280,375,754,17,258,324,286,785,128,426,824,200,189,557,572,102,336,565,900,32,450,8,123,419,656,659,147,960,33,862,911,912,16,902,767,800,165,861,632,950,397,735,435,636,197,503,820,425,461,675,635,809,510,64,524,774,78,595,167,903,154,20,773,484,718,273,389,992,399,800,667,400,117,392,53,667,971,979,242,216,846,984,815,493,598,3,135,720,984,743,106,623,631,16,261,139,670,565,931,714,959,123,266,636,496,846,736,874,175,33,842,876,986,349,278,932,404,910,129,829,416,663,28,648,762,595,763,527,379,398,1000,99,831,765,463,192,709,418,567,944,866,937,225,515,564,952,618,720,871,222,230,911,583,905,645,904,161,583,304,51,303,569,247,374,861,308,416,231,20,196,75,865,370,810,635,512,567,244,694,378,841,406,348,304,760,14,752,957,937,629,68,601,523,780,534,283,75,156,409,119,76,791,279,810,366,455,253,993,561,722,989,935,825,324,828,607,983,197,696,592,482,56,160,956,203,161,736,810,225,56,424,883,546,730,102,454,899,619,653,410,410,676,570,8,726,549,768,892,345,656,890,17,499,496,406,329,322,323,200,349,759,16,89,801,966,648,911,802,409,869,388,310,875,718,778,792,892,812,242,3,973,991,909,949,543,790,207,536,17,309,540,497,0,126,482,448,328,401,497,926,793,371,492,317,239,428,853,573,596,322,842,395,112,130,617,515,136,818,49,461,874,280,607,287,483,288,910,830,184,981,722,777,786,604,497,411,690,533,102,31,143,783,73,679,550,751,207,642,734,984,390,811,117,835,55,399,458,547,757,970,53,273,14,186,426,985,67,84,858,304,679,712,666,1,780,875,14,881,724,770,48,402,967,117,500,62,713,368,700,515,399,23,840,128,833,654,225,304,387,295,223,48,435,363,424,964,952,108,732,5,902,652,690,706,247,254,518,17,363,604,363,862,476,137,519,318,472,71,556,688,24,298,154,740,31,436,197,953,649,711,330,103,159,162,897,39,360,914,788,757,596,597,972,354,990,208,478,573,849,6,583,373,190,945,434,388,678,732,597,930,195,449,387,217,356,184,582,173,649,939,562,642,68,213,393,946,220,571,141,575,6,710,272,407,808,316,172,450,517,152,363,104,938,472,125,679,742,907,329,246,417,735,900,150,841,281,349,8,192,933,680,51,154,738,485,370,728,762,131,160,884,391,13,69,664,707,879,991,328,720,591,849", +"589,290,124,52,393,446,677,765,96,52,814,3,568,775,7,910,659,734,631,678,522,63,787,171,638,299,341,773,873,992,989,490,833,765,221,287,575,257,643,228,269,883,557,508,77,50,4,993,738,485,218,638,756,59,431,532,75,104,66,777,944,47,857,472,52,569,419,604,538,135,69,753,734,128,822,530,590,680,95,207,699,725,216,240,280,672,747,126,766,950,204,131,620,345,473,501,338,19,515,181,351,845,130,648,687,742,358,973,100,595,976,380,180,363,739,126,575,617,179,784,839,585,395,960,270,798,294,86,95,639,859,981,535,844,945,686,546,209,371,480,546,81,815,165,866,641,477,448,234,345,203,187,717,643,867,382,82,876,171,686,900,873,911,897,720,770,553,742,825,569,274,374,501,316,885,737,812,722,451,71,571,594,577,655,154,309,298,868,455,180,777,167,602,748,161,754,842,934,42,331,348,500,474,754,364,217,335,843,372,966,54,284,456,372,348,334,114,156,821,406,526,597,432,692,175,798,165,918,870,977,833,176,948,861,831,103,651,569,370,527,288,2,989,762,467,196,808,83,791,884,644,300,8,400,820,705,149,724,999,691,199,443,458,697,928,977,811,823,356,832,208,898,209,909,36,660,912,746,727,702,88,876,86,245,451,450,503,705,93,886,564,990,171,728,39,838,347,969,733,462,976,345,978,152,764,102,84,231,961,942,530,728,620,625,853,539,714,488,760,741,869,644,857,685,159,1,531,419,236,7,793,830,136,185,270,698,809,31,533,187,150,295,643,888,169,605,144,115,56,12,662,801,322,97,413,793,14,341,899,63,696,526,749,153,780,462,833,244,753,533,134,162,216,698,145,264,601,882,25,389,976,583,232,237,111,810,139,783,755,245,278,86,178,673,498,528,298,41,387,951,792,721,17,213,408,455,757,532,442,206,750,473,367,525,485,315,786,695,755,457,849,903,305,482,221,772,91,56,934,740,659,550,42,279,705,374,226,441,655,581,893,102,640,959,125,301,888,934,711,521,167,78,447,964,884,903,380,390,452,635,404,578,88,976,613,412,296,549,602,925,619,489,152,431,660,882,840,137,987,220,411,768,980,555,835,953,420,852,286,366,686,506,699,980,381,963,995,408,239,567,213,529,531,841,201,6,35,642,342,603,699,65,375,572,149,167,136,619,402,500,195,920,570,630,499,549,805,422,862,792,714,832,614,211,710,393,736,769,444,6,312,999,819,967,674,538,403,127,49,911,23,927,213,796,841,666,916,324,947,972,636,811,140,541,649,481,795,594,306,694,466,825,324,83,236,779,503,12,982,222,170,955,704,522,194,786,22,361,792,414,975,942,693,699,742,241,207,882,885,685,857,616,679,272,815,306,595,735,796,940,323,350,586,245,171,62,931,236,870,614,560,79,480,731,143,770,824,258,973,744,267,216,744,700,902,234,317,728,39,770,162,130,498,793,32,801,801,195,670,82,519,846,88,975,516,941,238,504,203,681,381,715,537,49,416,12,74,483,961,393,536,273,653,580,121,384,80,10,891,221,559,873,689,134,549,473,460,460,959,858,590,843,557,973,442,46,828,160,802,990,338,215,241,376,250,906,530,799,751,49,329,729,732,236,52,684,53,315,706,142,567,724,561,134,104,277,862,189,42,702,558,604,761,30,898,867,383,350,400,212,683,879,363,463,214,483,838,694,920,718,126,0,103,517,164,891,156,903,120,877,289,238,757,88,112,221,375,142,62,863,984,120,910,714,836,904,970,243,849,532,830,265,703,425,416,902,129,153,904,310,84,551,882,79,810,214,479,710,371,833,220,194,924,347,225,311,786,652,196,517,594,500,83,79,185,22,433,939,744,689,825,185,599,86,61,892,652,151,551,503,591,312,278,351,295,757,125,993,377,420,785,443,338,120,787,402,340,498,178,728,314,451,901,772,842,156,322,829,363,167,256,751,216,979,118,564,50,378,882,198,686,884,495,425,31,246,984,432,948,959,566,722,40,878,854,485,536,173,686,738,332,349,744,405,413,101,362,30,113,746,483,301,391,740,767,683,512,831,300,204,524,449,100,131,274,721,660,397,261,905,887,699,831,614,737,680,237,10,941,446,307,817,512,601,315,31,203,808,394,578,209,240,34,751,160,602,417,975,783,988,421,868,603,513,195,641,93,257,772,869,642,503,336,156,103,592,519,534,813,953,197,251,51,829,880,221,496,922,503,388,900,262,881,209,88,753,346,17,868,834,737,975,830,593,168,363,107,781,711,383", +"959,548,267,69,960,837,428,598,468,170,156,330,575,991,772,521,217,798,217,158,506,3,363,139,328,529,786,30,591,289,148,514,438,862,331,16,388,598,112,932,723,10,520,980,68,909,27,56,768,814,721,647,135,777,839,658,160,268,555,223,464,902,580,123,910,763,29,392,800,498,419,473,327,932,263,727,733,798,716,229,940,900,252,119,610,183,16,541,442,374,408,919,898,750,457,617,808,829,749,654,607,478,485,989,760,974,869,981,12,494,198,464,141,415,446,799,774,995,870,576,185,636,562,677,503,290,73,449,575,354,520,444,323,771,926,747,92,413,621,55,910,911,103,919,851,266,991,197,105,376,803,84,686,680,284,467,746,883,475,769,125,909,676,991,294,570,187,928,320,340,727,777,745,510,437,791,865,384,43,703,198,493,154,321,803,437,800,921,423,199,70,480,286,865,671,421,438,786,325,240,278,986,106,257,464,982,437,374,613,627,76,544,498,977,570,957,666,311,568,96,909,765,791,501,88,140,956,231,766,146,325,159,164,796,719,787,192,751,560,933,938,10,327,962,741,637,988,400,614,119,136,255,280,720,368,8,201,106,795,835,445,572,344,31,838,120,475,538,900,565,888,975,639,476,286,388,996,506,475,711,708,23,379,730,762,880,192,79,512,898,197,21,970,105,604,728,850,901,189,881,461,490,809,179,504,470,762,996,81,831,185,151,449,103,700,57,87,449,523,324,767,696,413,870,15,338,233,306,478,534,616,328,823,649,379,380,882,838,298,483,375,436,61,189,843,301,803,768,132,738,60,44,882,338,269,427,971,559,639,770,13,119,455,214,792,626,632,973,443,252,823,599,546,26,698,785,913,167,313,243,915,361,14,613,222,607,445,493,363,971,923,401,580,25,273,359,6,561,345,893,81,44,210,180,1,835,471,184,770,550,310,332,122,811,467,533,531,902,501,717,687,147,485,812,761,119,817,787,358,327,111,755,932,689,440,588,180,471,507,747,829,595,374,188,23,781,391,411,813,690,480,48,510,488,541,734,45,510,705,595,823,894,474,584,633,359,432,375,454,797,255,57,84,344,805,279,542,415,503,927,404,920,919,128,878,458,695,398,616,139,684,694,564,33,230,318,913,751,906,40,685,926,879,111,25,145,732,38,80,542,14,939,274,270,243,179,541,24,576,436,13,283,640,974,452,146,136,916,329,718,116,957,380,263,874,602,302,403,85,345,943,482,394,221,795,443,955,562,764,467,99,816,719,104,756,774,38,158,232,75,642,731,783,237,565,859,29,534,347,973,801,554,241,711,460,757,440,677,385,984,829,210,261,421,839,678,45,458,118,475,812,111,996,8,834,189,359,849,122,522,609,831,771,440,720,620,675,642,815,691,7,860,896,751,872,1,753,624,768,760,114,993,93,293,346,801,846,27,703,727,262,265,835,296,783,883,515,161,90,906,877,616,127,424,35,10,203,702,160,953,714,617,508,163,746,390,528,822,109,468,853,552,384,290,998,409,676,666,658,97,682,789,766,345,292,292,546,888,615,280,444,798,374,873,70,757,755,10,456,232,259,891,503,141,619,836,874,940,662,789,752,187,979,445,318,616,714,845,978,305,599,513,441,734,226,104,367,325,179,538,409,64,220,686,898,24,545,56,664,855,815,247,688,403,870,522,867,168,570,875,645,388,712,479,960,667,122,179,552,909,482,103,0,958,873,179,859,500,301,252,290,223,893,18,878,156,519,478,629,152,653,546,452,394,130,678,938,177,280,722,700,120,938,912,978,421,471,597,80,505,390,734,322,377,952,165,289,912,719,524,894,436,801,667,948,444,309,377,767,705,533,522,76,82,777,151,970,870,846,446,963,37,411,741,305,42,442,533,497,176,22,82,660,13,52,529,714,719,658,869,691,827,752,873,850,921,469,800,490,726,639,808,956,977,857,455,445,136,87,446,369,859,387,396,846,91,7,456,104,128,824,41,544,699,743,518,836,737,124,603,168,458,898,848,522,408,373,811,774,66,545,189,717,619,640,329,690,556,220,791,555,113,291,630,664,943,208,743,540,791,468,827,492,160,37,549,336,838,605,697,465,74,349,559,801,983,148,337,780,701,216,462,8,677,457,353,94,403,16,95,188,269,803,273,396,752,794,689,494,383,973,424,728,969,374,272,228,222,489,702,268,275,637,122,267,662,917,810,623,981,915,912,699,741,827,144,961,211,172,142,842,132,415,881,762,2,398,475,99,698,130,122,981,814,45,577,394,745,750,193", +"213,202,460,164,972,726,159,555,305,422,923,828,473,797,229,365,923,929,888,509,359,572,18,110,461,989,990,268,407,246,955,535,985,474,559,233,232,807,709,762,697,138,54,765,430,486,837,152,149,143,873,958,67,169,462,670,952,793,322,749,8,70,894,516,918,148,397,834,834,491,339,297,353,761,535,692,984,26,936,807,700,266,330,328,797,357,738,722,875,982,652,915,46,25,140,347,794,206,302,611,307,102,556,761,950,14,976,219,962,626,945,328,284,554,896,421,250,581,740,673,698,610,809,314,807,400,104,455,113,161,150,92,67,973,826,533,112,378,455,435,23,534,105,996,477,33,852,676,542,901,860,977,37,659,547,969,353,289,990,767,972,884,108,554,166,106,344,487,253,358,698,10,201,818,714,622,930,227,901,182,864,628,520,156,579,943,832,257,530,904,187,157,723,440,466,798,352,365,514,672,617,433,364,531,552,330,109,328,327,654,642,579,579,624,395,170,711,686,158,198,148,307,499,502,354,838,762,693,695,548,91,636,945,871,665,932,720,97,918,123,196,233,153,159,765,251,246,900,202,974,929,356,608,591,864,966,908,882,223,982,542,420,340,219,922,943,941,964,353,728,461,6,908,977,96,823,363,774,325,353,635,286,739,586,408,257,162,706,268,87,724,815,981,361,532,967,972,792,699,284,488,100,2,830,699,43,532,145,663,845,844,675,695,584,506,550,800,800,982,265,948,22,746,460,858,681,894,653,81,854,668,194,748,54,352,499,43,786,648,149,268,162,719,654,272,906,63,780,431,32,386,102,472,10,86,628,12,653,436,683,290,960,71,830,737,757,173,144,681,41,286,173,315,713,778,958,738,51,592,271,932,328,977,493,730,217,22,423,442,663,401,469,482,779,299,701,189,424,860,605,675,194,435,866,93,803,138,524,428,389,874,838,381,128,80,82,303,375,388,227,191,612,524,498,989,134,548,206,734,503,82,857,443,158,207,571,642,527,198,176,124,417,545,508,603,64,428,789,71,106,58,729,545,608,100,789,460,443,866,517,75,720,87,494,496,294,679,711,569,606,669,960,7,110,797,510,721,98,82,454,850,535,292,386,945,236,917,205,696,662,372,656,310,860,149,990,542,286,869,823,499,177,635,134,756,777,625,62,842,397,607,458,43,83,232,601,743,344,872,47,89,441,85,61,527,819,765,90,226,886,312,136,48,222,381,815,508,925,582,192,777,685,500,247,523,18,95,966,417,286,522,794,681,187,437,703,871,333,209,756,304,823,218,756,928,372,396,269,327,118,751,958,675,431,156,910,398,614,313,762,349,972,455,811,397,339,307,60,170,977,812,861,319,391,208,899,791,599,883,9,153,103,374,568,686,358,317,68,557,972,259,991,431,64,437,671,96,757,28,937,645,240,398,337,265,396,651,544,785,80,869,432,521,426,849,853,799,59,14,510,292,373,453,199,553,839,35,446,708,36,8,327,984,636,1,21,471,659,275,402,284,935,437,801,437,746,594,604,350,159,101,829,883,237,266,227,685,261,319,890,578,309,909,806,776,42,668,961,684,496,888,707,658,627,694,834,828,969,647,313,371,14,24,394,992,982,219,534,834,924,587,678,84,942,219,450,904,167,822,102,361,380,939,574,581,856,788,114,261,698,4,323,126,893,213,621,699,532,80,405,250,870,228,854,735,918,395,608,803,24,448,517,958,0,923,454,292,728,667,713,222,38,798,451,457,780,272,543,487,831,77,178,619,521,142,710,465,899,833,379,783,925,923,287,72,338,569,724,388,653,257,959,457,397,975,155,66,944,661,28,73,352,686,942,316,127,476,213,433,586,232,408,182,437,479,579,497,911,659,833,659,90,515,100,204,324,46,457,135,267,251,725,634,356,5,66,984,820,883,300,374,729,893,246,945,16,887,164,584,784,599,289,999,34,616,133,676,109,144,285,733,100,638,676,133,739,173,95,189,137,343,320,447,12,21,63,597,71,257,298,488,791,238,858,379,847,998,558,7,34,812,536,340,769,167,360,405,3,633,570,366,725,164,422,263,154,487,850,946,787,271,597,870,650,131,87,855,766,491,22,238,855,149,480,946,109,783,412,430,373,510,105,270,519,765,57,28,118,648,24,275,353,474,347,473,569,857,903,955,651,95,893,738,658,25,532,602,547,166,899,473,958,797,859,202,245,829,102,37,466,80,142,733,665,431,623,753,381,457,770,123,535,368,864,35,553,626,358,955,644,566,568,266,723,382,51,700,929,683,902", +"74,264,928,479,970,790,468,503,384,830,657,434,671,321,78,356,877,729,303,186,954,222,526,574,681,449,884,855,814,230,36,556,321,606,466,858,60,857,204,727,278,779,85,382,280,560,437,937,131,628,646,134,655,689,389,443,748,819,861,672,280,671,132,174,58,621,591,768,830,665,67,316,424,556,491,914,221,673,530,522,281,908,892,125,306,782,684,724,77,232,61,866,707,500,233,897,621,669,950,485,687,196,629,319,80,514,450,824,829,147,750,662,71,860,414,100,581,76,256,398,138,602,497,155,332,920,631,274,309,657,838,846,631,276,433,296,605,196,582,419,295,221,97,883,740,405,735,917,530,254,623,239,38,987,115,564,165,446,116,65,835,818,621,484,450,407,775,71,482,528,297,483,35,987,644,680,176,355,379,82,169,306,990,814,708,727,718,103,450,419,711,389,926,679,380,345,347,882,41,754,985,338,276,595,881,182,138,981,564,262,261,247,200,587,112,588,972,947,831,805,452,634,347,902,533,766,808,248,100,439,463,366,132,736,3,422,494,721,393,972,692,97,877,110,3,47,858,885,147,60,844,983,381,489,730,413,235,936,14,509,569,528,195,53,376,669,726,797,930,85,55,852,637,176,720,552,650,974,433,578,830,442,503,22,537,177,817,735,253,728,446,737,748,178,244,560,328,513,974,412,961,262,296,956,940,334,533,290,243,66,287,867,811,138,51,45,305,802,153,430,627,464,253,801,978,546,456,894,448,830,434,154,481,505,10,714,603,636,123,269,541,542,833,736,177,580,482,796,460,824,86,194,661,435,824,902,303,537,474,182,988,353,563,871,704,826,266,616,968,934,491,399,483,787,128,604,523,275,692,911,304,928,919,163,975,878,586,440,933,836,884,559,823,272,919,897,710,70,233,808,628,414,163,51,595,465,420,376,437,652,652,512,687,359,696,434,271,112,270,310,370,684,760,753,116,13,967,135,358,443,566,391,752,778,453,632,515,222,574,992,524,978,71,731,752,401,103,986,9,374,107,2,307,410,60,844,746,82,496,508,824,398,527,999,662,632,918,61,800,160,397,793,843,17,187,352,508,453,495,4,807,421,344,558,814,172,641,149,209,334,898,116,755,848,782,62,744,205,138,752,284,967,771,446,714,816,372,650,610,225,375,681,764,449,852,203,216,341,902,935,229,703,728,493,474,254,468,155,318,162,746,645,140,588,806,510,777,780,563,717,509,464,34,993,358,35,434,540,926,735,587,412,337,150,555,408,193,620,7,310,214,398,581,587,377,874,671,519,476,892,776,602,200,452,392,715,303,333,909,680,312,934,327,611,669,488,73,166,862,468,216,842,497,379,234,82,899,438,655,687,739,138,600,940,202,976,438,889,261,945,619,39,933,428,252,579,267,780,405,51,36,834,681,949,251,977,657,505,475,375,869,48,825,135,344,46,363,94,665,713,454,199,483,769,209,55,257,616,421,236,795,88,65,660,828,745,840,647,223,855,571,280,551,751,526,476,264,312,273,157,260,44,734,661,624,498,885,694,498,212,718,515,257,585,839,760,565,315,850,653,461,587,553,389,550,246,526,421,568,438,72,963,110,740,907,737,195,3,457,705,957,558,265,338,767,11,201,120,533,90,802,1,419,564,861,742,128,906,522,711,39,304,298,711,763,155,259,122,122,798,888,390,41,722,198,797,522,355,163,506,328,164,873,923,0,118,136,898,567,180,749,866,101,363,534,679,950,286,324,776,11,550,881,344,355,766,27,943,785,900,627,590,366,446,933,242,392,714,326,43,937,250,284,464,62,297,663,833,333,884,152,681,774,516,734,531,546,330,114,342,592,287,9,841,699,373,612,121,139,405,704,1000,815,187,900,482,537,899,128,224,239,616,371,231,52,985,552,363,809,342,936,331,834,468,307,609,593,812,142,125,226,122,921,336,423,495,446,479,981,97,348,659,408,640,75,380,862,240,555,16,379,342,622,33,631,91,309,444,421,400,494,273,208,854,115,260,435,965,162,711,136,981,332,121,983,968,915,361,104,55,772,793,991,836,72,190,250,774,950,889,256,43,571,814,622,365,159,634,170,866,290,682,727,530,8,956,108,581,92,768,941,184,638,514,798,136,201,944,196,959,551,29,601,992,479,354,628,667,79,285,737,224,62,521,19,554,25,843,563,781,447,34,222,179,479,869,837,833,87,929,513,525,931,981,932,208,228,784,408,235,464,600,202,181,375,317,693,947,682,816,673,502,182,353,602,181,157,950,756,599", +"904,831,316,380,967,197,675,111,698,998,900,537,924,247,409,389,951,348,738,762,63,471,696,792,569,709,630,754,980,759,259,569,307,340,249,298,342,629,783,844,697,917,153,146,591,706,95,675,206,54,738,591,475,222,939,896,335,74,724,133,188,74,859,159,468,321,556,328,984,400,888,508,658,753,580,926,387,188,96,22,777,587,960,688,781,208,72,501,334,153,700,719,58,425,966,334,390,875,978,621,798,966,680,343,25,526,211,499,138,129,2,530,222,842,883,50,866,598,348,208,505,742,51,378,933,589,406,26,902,16,92,889,436,898,223,166,597,446,358,443,618,200,826,179,52,369,250,65,842,792,625,67,150,167,720,683,263,311,773,883,424,726,916,690,918,454,907,696,868,762,459,937,901,483,904,461,77,627,733,381,575,287,744,177,102,300,696,290,875,756,930,359,385,944,767,712,849,158,87,973,811,602,226,958,668,251,135,938,55,5,390,183,381,895,450,21,659,708,771,620,275,779,424,530,865,185,716,551,443,332,568,275,181,89,993,732,126,436,136,457,274,211,349,165,555,608,328,67,18,649,786,705,595,892,412,137,711,832,739,809,125,879,242,468,538,228,40,402,640,196,875,21,189,831,547,660,791,150,172,499,620,749,342,63,452,375,917,314,544,900,773,814,996,187,270,661,789,812,546,366,649,508,609,29,275,994,69,905,231,668,629,538,22,609,457,891,313,242,58,102,577,186,690,545,394,83,969,265,662,53,246,76,213,972,386,998,29,301,595,549,77,727,501,739,405,954,685,918,914,118,345,508,736,886,451,263,883,648,495,688,590,298,699,165,863,193,45,432,903,69,321,851,341,531,457,521,976,428,836,986,26,197,47,164,864,317,982,881,223,772,196,584,991,625,286,664,991,65,454,547,744,815,575,914,614,103,540,653,790,351,798,557,1000,667,955,42,84,125,466,281,209,486,349,907,162,831,868,513,247,385,38,925,939,588,459,295,7,380,527,49,820,162,927,285,217,869,385,921,488,457,704,23,376,29,344,668,515,115,154,575,183,386,136,435,79,926,408,469,944,72,884,714,336,669,708,89,601,999,823,233,681,524,339,97,233,558,912,156,669,785,110,742,34,944,898,173,973,100,15,568,558,312,748,916,633,609,752,438,330,23,810,72,607,533,902,781,838,856,206,833,203,730,800,997,99,789,549,468,976,276,889,411,961,638,756,106,323,89,492,62,807,88,875,205,807,21,114,255,651,275,501,271,148,852,9,637,189,81,413,923,549,841,607,560,832,494,621,477,325,484,322,591,679,639,650,337,411,497,105,498,817,207,50,785,744,370,120,878,412,243,349,959,873,605,324,207,994,544,150,949,589,138,431,555,670,455,688,506,555,352,331,261,388,522,877,534,138,420,210,560,626,355,692,274,636,874,522,162,875,233,848,1,932,965,114,678,722,963,702,108,698,43,566,29,673,684,80,519,345,543,730,895,29,146,75,207,887,130,804,986,557,187,134,330,395,76,635,916,917,679,839,362,915,156,934,510,198,794,561,493,44,354,590,357,97,819,276,167,343,94,129,245,896,795,799,604,19,502,164,279,831,77,345,178,881,963,665,431,716,986,388,175,571,882,216,705,298,465,222,537,360,215,365,38,506,458,138,171,273,593,343,682,119,762,495,757,388,765,267,613,721,103,626,315,264,579,237,193,669,662,401,891,179,454,118,0,684,412,100,163,777,819,815,268,580,114,617,49,838,241,919,458,526,369,35,831,114,625,152,516,518,871,237,45,3,147,639,724,823,21,519,324,519,737,530,944,179,259,351,889,573,558,365,806,999,419,895,120,442,680,793,911,322,380,208,914,440,989,434,275,616,531,116,715,287,489,369,76,784,193,27,111,595,468,595,489,269,263,773,258,614,15,126,811,349,796,699,675,568,423,962,816,376,817,62,593,894,839,224,429,256,14,695,121,351,789,55,555,580,204,734,385,105,991,352,82,494,812,100,870,324,918,100,668,125,358,490,736,579,665,52,383,697,68,141,208,539,275,874,253,974,928,5,312,38,329,709,99,611,430,540,875,16,498,630,477,867,352,929,289,381,471,876,729,272,98,681,983,320,623,861,252,937,626,668,837,980,682,532,660,477,962,415,919,237,241,404,21,773,486,784,436,798,709,218,833,230,784,238,784,70,670,438,267,779,328,470,423,837,786,413,317,182,153,653,813,80,962,227,995,835,81,794,238,725,867,488,247,499,628,253,721,262,464,698,988,356,43,715,521", +"270,235,325,496,711,263,927,45,777,692,533,392,279,332,538,748,248,231,935,565,216,468,896,100,49,245,896,596,469,98,831,826,491,256,280,532,818,835,833,285,114,441,345,249,108,254,446,46,616,801,205,165,150,643,700,208,116,21,10,411,59,546,495,317,575,323,415,72,223,5,201,354,635,669,992,448,412,602,140,129,514,502,898,691,87,643,520,948,347,199,713,154,388,360,422,23,949,216,983,308,463,634,630,178,468,490,702,410,735,607,469,893,384,865,44,515,541,562,556,425,125,240,82,189,764,213,68,399,995,933,37,377,221,658,937,923,373,474,48,156,898,922,347,18,317,979,84,572,640,227,295,71,860,724,298,687,306,970,960,656,775,965,312,922,15,260,475,75,216,575,613,21,804,60,853,744,494,544,812,958,142,281,495,356,133,229,581,245,31,260,55,240,877,375,422,722,497,525,143,350,283,73,793,171,868,494,104,244,851,734,762,208,147,396,728,105,377,754,948,398,313,373,671,807,653,369,878,398,547,717,6,772,259,403,709,913,394,649,109,141,850,89,362,413,284,815,252,71,698,999,240,94,556,187,483,293,273,941,543,262,172,816,376,446,694,63,501,573,370,499,147,79,652,745,562,29,624,797,161,610,338,215,455,836,510,512,35,456,664,72,637,732,68,36,410,506,856,726,142,310,539,463,508,758,677,710,816,827,668,792,254,792,32,648,468,85,637,453,524,243,977,548,992,369,655,418,778,143,400,211,168,584,689,136,865,149,781,78,651,86,969,617,238,619,110,599,780,618,13,355,973,230,100,643,672,52,414,667,975,895,599,426,219,23,632,979,916,704,151,565,722,467,995,234,996,273,936,134,604,277,956,226,442,449,766,497,678,1,62,707,485,248,83,270,633,76,494,214,561,866,657,377,470,228,482,683,62,993,956,827,51,331,506,256,661,722,616,402,119,434,570,619,199,956,93,56,549,359,541,714,876,776,470,112,886,649,471,804,192,477,384,834,936,671,842,627,914,413,617,226,574,918,797,422,909,3,101,739,597,942,37,16,658,752,927,542,509,147,854,595,502,777,973,728,469,986,521,996,509,157,452,231,618,298,750,407,299,718,505,235,64,47,965,863,644,355,881,571,559,335,821,912,571,270,251,23,271,165,183,920,443,108,215,527,961,810,190,215,765,136,163,96,801,390,836,194,240,237,838,518,71,438,80,312,922,64,575,178,196,951,424,654,985,830,616,641,136,926,284,681,854,824,283,91,60,242,956,518,245,266,90,181,594,582,125,450,380,35,603,411,164,197,180,974,896,910,848,687,12,764,179,607,923,975,651,440,243,379,277,90,242,582,835,309,351,546,567,303,810,191,473,771,393,888,159,119,353,446,204,638,996,170,383,922,336,401,939,179,203,648,44,844,830,983,418,496,675,780,114,520,395,605,121,723,856,615,200,863,475,910,529,576,441,512,635,109,519,511,272,772,967,665,452,609,501,366,436,665,124,850,615,526,390,299,637,438,84,155,903,319,537,237,628,691,201,963,437,523,747,646,457,442,219,782,394,437,312,557,214,458,374,746,525,713,799,376,157,195,106,679,520,568,628,658,639,211,179,458,468,132,730,406,36,373,273,56,28,845,163,833,928,979,477,769,339,818,838,893,888,554,182,132,984,648,18,269,576,522,436,665,638,234,563,110,236,375,904,588,332,662,497,156,859,292,136,684,0,248,460,208,768,804,772,171,554,226,694,748,996,504,774,380,121,364,269,925,629,40,552,742,37,277,696,320,584,313,442,943,736,637,379,646,246,225,442,608,511,409,297,882,404,708,131,482,567,14,766,692,15,480,76,146,738,728,468,26,502,814,432,236,904,216,190,254,688,736,415,412,330,569,596,592,566,407,170,105,345,202,339,185,446,194,737,173,121,756,242,37,660,727,540,993,141,864,356,952,315,546,830,839,783,656,536,177,67,340,192,115,95,155,201,55,580,290,260,537,876,21,826,566,429,563,571,399,195,436,514,46,198,778,645,406,699,15,152,716,732,449,647,404,479,527,929,387,574,68,602,334,925,759,816,469,290,757,66,218,889,552,579,857,376,377,529,91,651,322,3,430,728,907,929,779,467,543,944,231,741,404,915,71,301,481,375,129,961,582,586,229,754,627,15,776,720,946,697,934,337,801,901,714,606,93,497,94,191,571,926,404,711,265,224,605,382,346,334,264,643,705,143,682,574,27,786,242,139,596,918,73,537,914,58,799,89,3,588,780,291,148,143,597", +"677,162,173,455,876,511,897,553,635,788,32,273,950,302,924,268,481,842,85,457,103,968,732,992,31,807,20,701,239,438,896,208,1000,907,759,824,362,118,297,731,57,412,170,968,46,906,811,966,729,735,343,629,389,220,136,353,716,772,831,151,182,869,418,366,85,49,810,567,978,204,771,894,824,958,470,178,37,977,634,781,470,451,2,450,604,350,204,352,372,118,13,101,69,889,82,910,629,926,743,352,988,725,143,26,614,854,323,313,915,939,549,164,632,763,124,90,442,141,815,477,895,100,278,394,513,11,196,785,124,899,805,507,121,107,23,516,216,295,745,980,267,181,773,962,247,157,730,531,128,517,230,124,768,357,873,417,360,745,744,133,279,191,947,457,661,23,185,567,410,903,142,58,405,322,655,704,798,105,325,329,645,497,699,762,858,320,530,60,142,330,231,853,122,868,361,111,171,697,917,271,994,969,600,557,403,124,917,576,450,420,52,554,919,737,703,906,88,36,56,911,275,286,860,573,155,750,73,448,920,818,159,716,230,926,76,986,150,338,49,663,824,317,755,356,109,643,711,309,55,380,164,758,666,50,840,998,720,142,674,372,472,157,199,245,10,405,189,415,174,831,738,703,544,405,454,803,641,721,248,577,552,536,981,769,770,450,915,905,329,205,153,479,100,727,83,879,737,845,771,440,822,438,542,575,379,821,13,676,753,239,572,624,152,244,57,528,968,352,565,953,523,759,355,209,955,502,625,65,332,964,429,224,959,631,136,169,334,354,957,250,595,678,364,878,832,995,792,5,379,95,927,558,549,847,473,259,367,140,771,320,391,365,565,986,338,222,805,758,867,573,546,932,973,482,788,493,243,590,339,863,414,550,687,883,199,335,77,843,102,619,17,939,870,484,589,283,63,450,485,530,643,155,168,323,892,295,830,802,114,686,477,743,767,895,143,817,586,876,872,489,338,829,532,89,634,767,411,334,774,793,252,975,293,31,950,635,140,276,222,833,476,28,466,671,882,958,225,210,997,27,617,762,601,808,972,271,953,583,8,83,143,374,178,612,53,464,328,241,718,941,6,561,114,248,729,51,227,971,408,355,672,357,737,756,156,478,175,509,705,706,561,250,976,512,611,460,706,903,675,964,620,344,814,929,935,797,138,923,597,549,370,144,62,291,574,416,738,613,615,183,914,983,943,749,643,215,528,890,61,770,424,57,404,581,647,188,984,663,387,158,65,127,92,885,397,567,385,360,396,779,224,10,408,297,63,449,80,420,900,784,812,205,157,414,974,622,795,315,705,204,421,181,678,114,625,64,904,655,799,834,182,364,858,158,347,399,890,732,49,927,160,137,472,454,813,633,905,274,795,1000,83,166,5,212,654,105,725,98,237,893,346,877,683,672,332,877,252,61,430,162,536,911,604,682,382,384,154,802,103,12,885,719,619,344,511,159,746,589,458,114,914,875,873,797,679,610,457,642,464,79,161,286,612,278,721,25,531,295,52,267,526,236,272,17,961,318,785,340,532,784,315,337,572,124,208,235,850,31,914,759,515,97,418,130,836,180,130,74,37,880,429,869,482,28,358,435,598,304,424,786,914,338,895,27,804,466,632,189,444,458,387,808,497,671,372,351,494,539,769,251,974,792,853,908,161,65,875,456,156,183,91,518,231,277,455,700,332,519,300,583,80,430,445,593,317,855,480,578,727,536,926,903,500,728,898,412,248,0,488,845,71,653,857,366,915,231,8,333,294,7,637,182,982,314,847,581,942,661,6,408,114,748,158,896,560,794,178,880,442,537,928,43,870,216,436,495,998,230,756,209,974,605,727,986,619,397,151,202,866,805,976,226,973,377,671,174,614,377,319,580,588,766,249,636,300,161,705,844,64,708,960,950,136,40,394,820,508,960,479,345,52,682,490,99,583,715,159,588,764,759,671,337,107,172,507,2,782,486,546,400,81,74,395,47,759,749,134,605,678,571,715,948,347,309,424,28,570,304,525,182,38,644,719,587,460,848,820,267,309,421,647,567,223,756,997,485,262,978,185,991,549,937,675,941,727,703,937,368,16,473,576,170,723,981,513,869,717,712,992,834,342,916,735,130,801,544,256,521,337,229,712,154,755,548,160,803,824,970,685,30,46,537,903,727,505,657,240,42,917,815,831,273,70,901,930,773,700,184,885,467,964,9,778,863,533,903,681,815,315,528,442,288,505,440,959,448,203,96,915,434,673,742,853,539,674,908,742,12,674,230,172,250,572,614,194,524,953,558,106,176", +"787,683,52,615,786,936,216,782,548,113,46,789,482,927,89,585,978,926,377,961,460,719,6,431,828,665,201,557,10,59,981,741,369,767,843,88,742,972,564,449,353,809,350,936,76,653,86,590,533,307,975,420,540,35,664,6,93,14,305,682,308,891,189,596,806,783,514,480,512,186,152,368,161,132,423,453,162,75,178,336,430,473,748,811,553,198,863,26,156,983,984,124,779,479,129,539,124,201,375,862,273,433,578,659,156,682,853,106,970,211,729,402,480,506,476,979,159,340,971,285,171,61,104,946,926,384,779,303,891,426,314,842,563,394,647,438,588,795,789,786,812,156,425,447,518,592,890,88,553,358,223,246,382,122,230,145,60,225,731,796,344,266,924,784,118,252,963,259,423,180,317,223,776,376,308,791,564,977,982,11,744,696,319,114,737,809,137,843,234,278,204,445,322,180,204,67,512,760,329,350,208,954,885,526,69,563,982,267,479,462,240,51,822,91,718,373,235,517,903,2,684,840,354,18,510,312,333,948,259,303,904,73,652,24,566,907,854,120,621,394,264,634,605,270,436,177,875,425,304,167,387,470,539,105,720,61,418,112,419,922,785,15,613,146,433,507,866,610,286,182,988,543,938,529,164,268,450,769,925,38,799,770,276,144,750,518,135,573,169,330,627,342,339,865,911,564,827,456,747,361,543,853,608,57,349,674,842,592,758,97,753,270,535,837,544,768,997,949,41,208,295,653,209,212,154,327,873,705,358,754,589,973,148,65,710,510,206,601,233,141,744,306,468,681,702,289,946,726,487,782,617,718,559,980,393,970,514,723,561,38,389,861,101,324,470,584,270,896,594,921,509,135,101,806,983,971,785,814,531,4,622,810,267,136,959,778,847,423,769,802,489,896,313,531,791,927,356,377,64,54,393,25,726,135,141,183,808,772,246,163,987,676,970,621,320,106,207,472,842,198,438,472,783,50,530,22,269,967,39,820,80,383,936,369,756,23,134,98,947,372,364,995,573,809,329,252,857,332,789,850,196,131,680,880,194,493,55,804,655,975,728,617,490,447,508,143,823,642,779,75,384,983,687,167,59,589,776,431,183,249,620,467,745,324,295,785,178,527,422,214,668,471,764,545,255,81,183,629,391,457,852,62,254,325,805,914,378,112,554,100,492,785,760,330,320,972,840,555,50,892,645,318,812,448,747,430,104,745,864,471,333,603,595,175,309,907,85,274,619,363,276,737,962,975,677,218,542,541,822,345,367,644,389,767,860,28,945,680,283,561,985,810,439,204,103,602,134,203,477,962,44,46,277,357,69,204,133,829,213,577,766,374,332,127,316,903,665,419,6,602,14,417,354,506,746,961,864,78,378,785,242,84,77,934,648,228,747,627,982,374,604,422,305,605,884,453,368,264,477,811,447,771,701,38,24,551,542,804,100,967,665,141,202,859,174,309,620,83,934,277,77,797,535,281,459,907,59,297,320,185,875,619,213,291,534,121,937,648,692,977,379,45,351,165,340,373,733,687,736,267,282,152,799,666,227,41,604,623,688,558,364,833,695,108,521,974,575,951,896,862,218,564,432,727,315,207,517,74,459,144,180,925,754,992,360,60,423,777,851,116,532,576,39,81,355,461,931,592,508,283,528,519,215,951,230,311,327,229,409,815,463,542,95,479,602,151,597,190,128,722,838,755,362,836,946,560,773,898,4,471,793,120,301,667,567,100,460,488,0,836,651,694,84,72,350,358,847,342,10,201,418,742,40,883,486,530,494,530,371,418,589,290,265,862,356,20,946,737,685,976,618,913,62,927,428,816,127,544,347,28,479,152,998,420,230,698,293,84,393,892,518,480,301,798,650,939,98,101,598,937,643,671,315,666,124,71,678,20,190,687,252,830,668,748,112,807,25,420,604,281,938,66,729,506,691,689,587,194,57,99,930,209,529,335,605,312,322,455,486,439,627,963,531,721,9,616,442,768,119,361,734,701,577,418,197,425,189,390,985,547,850,738,554,210,581,571,418,803,954,916,254,685,551,82,715,728,892,427,88,634,478,374,901,734,141,727,388,191,796,981,622,577,799,259,583,226,778,729,569,362,600,25,636,58,386,909,768,887,240,656,357,563,742,37,299,199,304,288,885,462,394,332,3,303,501,670,51,867,463,759,962,945,458,931,934,230,386,163,276,222,732,15,154,193,154,868,525,839,834,77,365,945,527,166,267,704,838,845,379,401,229,946,965,341,913,127,94,781,428,772,98,132,131,92,601,768,154,481,647,112", +"884,648,820,750,423,938,734,755,783,410,190,263,725,556,600,119,408,261,766,107,335,352,66,787,438,279,295,713,635,113,436,276,419,644,142,252,102,277,533,470,629,611,908,821,993,320,935,374,686,302,175,472,678,453,351,901,440,555,797,843,345,577,324,81,868,797,847,977,822,744,544,5,252,889,644,696,80,529,506,559,570,613,829,979,546,904,89,881,738,418,330,652,570,495,523,634,852,251,416,272,236,400,782,521,954,829,16,539,967,776,936,974,823,264,677,523,466,427,24,500,185,814,49,339,435,116,286,182,223,958,592,629,221,914,10,126,742,160,83,249,127,335,460,222,753,404,899,991,307,959,229,106,437,918,271,982,920,993,756,358,681,974,345,741,447,63,548,686,770,482,274,505,222,152,707,44,394,98,299,886,597,845,509,443,87,172,688,899,56,917,326,289,220,642,270,664,695,742,830,335,71,231,538,716,839,313,527,222,75,823,596,329,478,25,86,283,866,252,23,734,773,692,579,628,398,664,263,655,739,967,377,903,623,827,529,824,550,204,233,584,52,184,516,527,86,923,201,67,427,404,685,869,502,487,866,54,956,550,25,206,238,860,645,558,341,867,736,49,150,88,164,494,78,602,343,808,342,265,583,534,521,799,459,368,161,489,671,388,90,424,823,747,967,485,743,328,657,520,160,991,947,650,330,83,73,521,344,409,905,511,818,153,861,645,685,628,450,875,331,80,448,125,776,517,631,154,187,737,755,757,730,203,197,851,972,737,21,995,828,914,692,381,918,476,788,379,492,111,545,201,960,739,700,547,97,37,821,12,543,326,172,455,787,779,651,174,514,240,793,518,720,374,562,495,949,929,833,902,780,945,288,195,846,293,395,60,390,692,909,193,399,21,515,26,229,435,663,480,174,372,850,304,638,643,621,337,737,218,143,723,909,24,343,718,664,16,792,106,251,518,617,808,638,543,134,69,290,519,647,985,360,456,674,25,911,264,60,202,46,174,397,891,811,991,388,776,753,791,935,598,676,181,573,987,996,832,535,10,42,846,580,269,457,994,855,912,287,786,662,915,782,5,464,49,632,947,176,424,596,370,614,188,513,981,822,792,749,301,70,192,978,877,989,860,376,500,238,864,31,530,743,996,510,632,919,646,970,924,323,724,374,24,347,510,885,59,108,293,218,962,189,833,828,159,874,81,893,261,774,474,527,319,578,589,273,866,845,300,94,463,833,977,197,921,267,454,644,684,892,398,986,964,576,311,507,278,897,331,32,450,566,291,691,785,459,930,214,15,378,780,426,348,774,983,702,410,292,787,573,290,718,675,238,860,882,789,594,760,763,577,830,345,548,992,788,829,32,940,988,430,442,243,982,553,445,497,169,42,985,969,219,416,354,252,16,264,663,557,837,590,269,315,27,711,678,180,103,128,991,452,182,690,83,851,841,72,681,781,929,360,144,187,426,143,657,629,876,328,456,671,465,463,382,462,298,612,116,139,401,290,145,394,740,975,256,811,247,438,212,33,127,24,169,140,400,521,82,427,977,728,917,409,120,489,784,540,416,715,358,241,358,160,119,727,854,844,964,418,574,740,444,34,746,476,392,810,333,224,882,456,354,931,67,660,316,69,922,906,160,609,309,392,726,399,912,227,549,124,607,920,570,49,580,533,511,410,209,2,747,671,147,51,695,78,434,991,646,321,986,421,371,877,252,713,180,163,208,845,836,0,760,274,486,45,726,791,227,240,602,452,880,123,166,44,840,749,259,651,238,215,313,510,438,77,434,849,769,53,461,999,170,587,635,251,994,284,414,793,312,202,773,648,685,838,55,140,511,78,259,924,291,179,720,679,80,250,331,445,559,345,750,158,799,426,724,56,830,528,781,639,714,843,123,583,481,288,143,368,398,586,634,868,703,40,363,847,99,25,493,324,298,163,56,633,97,295,420,802,504,873,748,652,293,780,653,939,629,845,509,426,635,510,236,649,554,388,847,995,167,100,895,488,462,251,222,398,677,950,632,604,836,817,284,43,838,406,315,836,460,869,223,233,569,902,881,126,358,773,566,345,505,195,258,71,493,326,701,350,949,884,690,546,52,508,628,487,838,428,651,417,542,319,816,983,314,216,798,934,931,137,932,212,88,152,611,85,735,634,51,195,919,622,977,916,488,21,292,335,574,273,780,192,84,498,647,513,449,543,945,72,80,983,927,295,984,734,692,550,966,251,398,165,674,382,911,747,136,535,486,575,443,866,320,120,619,252,385,60,525,469", +"287,530,394,957,412,427,162,233,382,24,617,151,747,960,101,907,276,440,114,822,784,895,194,528,395,830,655,952,339,778,858,790,280,760,504,142,387,654,37,578,273,601,304,657,272,758,125,247,323,808,904,355,180,106,164,503,546,365,550,675,675,508,356,855,199,442,915,642,71,497,381,15,173,758,889,455,833,168,795,973,822,730,30,391,78,750,878,739,903,69,557,746,318,76,343,580,983,205,338,258,383,651,148,824,31,513,840,257,177,347,963,59,152,504,959,519,515,582,949,565,7,472,796,245,845,395,228,703,426,349,734,569,415,944,113,343,42,304,8,278,505,427,651,479,87,790,305,597,778,243,742,219,170,253,181,219,720,513,79,729,48,327,720,127,746,897,653,220,551,573,416,719,156,977,894,193,461,789,692,764,936,442,31,417,365,726,311,325,206,97,417,430,302,550,312,640,427,199,731,724,999,444,783,147,353,834,386,265,436,552,202,602,967,510,341,723,342,654,796,219,177,608,179,994,851,847,9,153,394,499,262,199,805,479,210,80,475,263,334,659,130,771,488,903,439,466,78,144,508,701,439,791,786,860,728,756,39,609,32,792,928,286,924,348,531,404,22,412,248,779,868,767,418,85,374,288,297,409,613,467,901,262,100,392,605,339,474,173,476,856,57,292,621,96,490,366,104,657,421,565,223,915,472,237,859,774,245,977,406,742,391,102,211,802,780,234,784,708,696,963,2,408,741,20,407,778,950,403,834,883,989,590,606,595,842,972,817,860,47,64,705,888,334,345,910,833,952,415,893,802,30,451,447,735,97,794,312,162,515,870,138,968,328,297,736,423,295,152,275,820,235,28,967,47,315,795,222,453,288,733,123,316,472,431,193,241,614,916,379,703,996,351,937,997,55,393,599,574,211,460,628,559,651,629,959,642,467,346,976,272,679,667,733,548,360,105,571,845,380,314,17,676,534,750,252,363,707,371,604,210,196,123,151,132,389,696,956,479,447,589,130,672,589,607,410,802,915,309,935,939,129,369,238,657,34,948,19,951,405,459,605,419,497,585,553,694,142,479,181,754,151,128,880,652,913,885,800,974,777,688,899,212,22,655,451,124,974,150,477,965,338,733,350,51,258,412,468,148,267,395,620,652,761,105,820,328,842,218,196,235,854,555,598,327,265,480,418,370,285,224,734,76,946,216,605,273,932,430,17,212,895,485,13,242,36,857,947,999,216,516,792,664,592,496,65,749,59,116,586,125,820,963,349,237,389,369,321,917,757,603,388,583,79,66,971,328,128,66,679,810,55,776,904,148,526,166,907,82,374,447,684,794,837,514,19,75,27,113,102,671,406,21,114,829,165,65,527,147,40,718,27,912,233,18,512,702,603,781,859,500,547,129,659,231,70,774,468,580,625,562,415,833,436,769,373,475,960,534,851,174,574,876,387,390,740,87,661,655,492,124,7,906,160,49,70,205,204,414,282,658,803,822,686,187,315,730,622,296,733,517,911,988,473,725,652,406,224,287,897,12,128,557,722,479,66,544,266,432,716,358,273,197,38,788,577,830,140,751,715,660,367,810,670,956,900,991,729,197,896,350,249,193,966,456,420,246,921,400,400,348,614,240,611,658,292,522,299,110,348,197,964,693,604,840,398,388,583,12,666,106,549,856,828,920,520,398,640,665,96,951,371,10,2,342,563,599,399,253,103,482,492,289,290,222,749,777,768,71,651,760,0,873,225,831,755,896,919,403,631,230,749,10,929,382,845,931,75,71,663,278,555,424,297,677,19,926,463,889,621,657,735,557,294,503,892,449,696,392,169,743,273,912,67,458,54,155,865,9,926,759,42,375,746,160,947,278,912,509,591,978,97,606,730,413,408,479,396,873,624,446,690,830,147,779,780,946,805,26,823,101,447,261,91,502,310,352,55,316,815,895,622,221,460,337,748,721,163,278,337,275,313,808,880,38,750,232,341,885,881,229,914,871,882,249,401,680,79,165,671,199,680,812,202,521,513,968,512,674,178,547,301,818,19,780,683,690,73,840,527,849,821,827,319,585,427,352,196,404,83,800,566,377,570,452,526,717,901,195,635,116,687,503,54,459,579,35,789,266,62,939,673,71,736,284,846,362,860,378,499,893,137,670,494,632,579,878,287,919,294,547,171,490,357,93,282,940,676,736,535,131,338,795,234,155,535,852,502,862,820,567,257,91,737,669,39,313,775,266,132,486,546,484,4,245,457,228,688,16,237,489,367,258,868,364,316,995,397,598,778,267", +"569,873,410,397,254,718,769,493,713,303,775,513,700,264,773,598,404,145,966,19,440,859,639,321,484,450,253,932,245,760,117,291,522,238,265,327,855,904,980,644,993,720,874,492,107,310,111,293,489,720,80,915,181,923,308,769,630,695,782,514,284,358,269,11,848,541,295,510,729,621,345,65,170,204,800,406,14,695,735,263,60,107,952,197,425,925,886,837,957,360,445,138,328,912,558,340,442,434,209,864,365,175,800,182,434,815,692,468,156,471,892,148,168,249,992,182,875,284,820,941,426,541,334,420,373,210,372,99,600,358,357,888,667,319,563,309,317,967,925,266,913,519,919,205,121,740,864,553,95,886,369,871,813,631,772,865,529,985,63,678,942,21,328,68,881,613,83,563,723,568,615,758,15,528,344,56,357,663,220,297,15,164,849,63,856,186,292,115,707,489,611,441,274,493,15,452,541,732,527,323,278,304,458,358,911,72,959,895,673,75,329,819,142,689,642,459,917,510,699,798,652,866,772,865,337,199,523,739,558,718,365,986,563,317,569,744,462,44,69,494,97,231,201,919,435,365,318,768,968,22,741,223,857,768,440,274,48,331,634,696,71,990,958,469,528,23,171,975,35,626,119,689,369,830,661,108,910,869,915,55,137,881,43,384,570,382,388,934,817,35,163,393,76,533,793,914,334,21,697,586,757,436,712,719,475,43,734,900,855,919,404,738,377,123,750,600,978,45,359,703,648,91,34,450,708,986,639,590,259,114,350,876,680,92,326,757,645,329,428,298,78,914,845,26,152,532,464,248,598,510,742,780,473,270,192,137,151,287,687,254,472,908,981,921,869,213,604,483,647,964,347,277,733,1000,439,624,394,239,807,282,114,738,895,821,197,679,118,575,688,97,772,917,836,80,553,404,348,294,110,584,568,570,777,960,117,48,822,257,670,94,617,475,751,537,806,523,262,219,299,92,663,445,766,502,217,916,843,84,357,79,954,394,517,435,57,949,108,636,768,360,340,195,276,827,161,763,624,626,533,453,781,535,705,356,373,146,695,513,969,191,54,311,895,439,990,50,836,662,460,894,663,36,242,250,501,4,848,655,572,381,716,208,867,848,861,58,275,384,992,82,592,169,701,226,366,602,538,367,270,497,404,621,453,985,39,855,237,817,447,140,27,169,532,540,51,45,221,943,174,917,379,856,636,569,722,324,631,224,976,648,168,186,980,686,874,990,895,507,637,385,897,374,932,341,249,79,385,432,619,989,554,118,45,429,9,201,549,512,425,94,967,284,446,950,575,761,498,963,857,649,841,440,388,953,198,488,733,673,891,763,487,256,536,180,359,421,749,751,412,864,144,681,610,4,183,474,219,245,92,820,461,140,574,147,468,219,488,114,428,66,771,464,819,332,743,596,637,451,889,782,864,869,533,600,576,72,274,711,714,150,963,416,169,630,724,687,137,929,959,756,382,218,306,426,147,881,715,318,675,488,657,199,535,809,385,835,572,210,66,28,850,458,550,406,160,533,22,545,65,25,344,24,926,769,647,542,27,674,301,111,197,956,169,223,991,776,308,149,888,164,973,143,375,457,282,185,441,272,588,867,6,330,287,259,348,226,406,555,260,491,536,817,261,995,128,925,937,503,555,810,693,15,317,343,988,644,61,904,449,44,459,752,455,946,634,889,434,533,263,12,171,972,714,485,889,268,180,119,277,309,317,238,223,38,866,819,804,653,694,274,873,0,829,940,849,655,856,157,43,931,324,106,653,924,970,869,375,178,832,227,182,470,671,510,871,160,641,900,373,513,7,492,981,39,641,19,689,482,934,370,830,662,302,427,313,388,479,513,240,203,342,894,428,467,374,164,363,456,86,782,554,172,45,308,108,13,577,272,994,871,578,271,429,833,201,584,991,77,538,588,69,235,575,70,131,210,616,831,701,330,898,394,210,729,62,186,587,243,196,263,633,181,320,941,77,513,515,858,273,946,462,64,113,341,263,653,316,359,196,563,853,932,242,546,519,158,465,438,883,310,607,120,61,664,664,437,858,43,530,872,866,369,910,330,256,871,938,124,775,913,896,411,644,555,727,151,490,754,182,962,297,85,943,943,167,748,950,70,735,216,742,739,286,682,302,389,365,986,22,612,953,787,655,936,109,747,959,797,93,536,567,589,658,294,15,857,361,59,551,949,784,999,269,371,585,683,812,166,678,672,150,373,790,820,787,808,24,532,113,167,577,819,630,686,342,626,797,152,292,312,251,457,602,855,428,393,977,517,574,460", +"182,286,759,293,107,186,996,939,672,616,959,605,732,756,834,879,892,354,575,773,390,733,16,122,641,319,281,386,892,622,941,78,496,278,397,132,712,497,448,799,456,401,699,436,868,195,763,556,454,190,749,417,717,180,325,309,973,965,941,163,891,817,901,861,879,403,364,390,902,726,917,385,932,516,480,170,340,266,274,503,371,892,959,799,488,612,368,698,151,881,123,595,898,205,913,898,359,69,565,55,356,225,430,65,722,596,198,422,818,801,692,661,892,136,832,965,173,88,623,929,108,394,751,590,566,154,585,131,989,512,610,163,834,689,186,944,788,722,609,483,486,926,835,738,152,267,779,493,605,264,181,868,263,216,774,761,160,958,543,880,630,327,281,852,927,148,775,59,899,368,298,964,882,582,258,301,306,602,395,393,555,90,933,73,157,995,44,168,227,401,339,284,94,261,291,288,54,255,416,566,28,141,195,605,774,504,221,318,48,213,170,667,632,939,692,421,168,929,259,636,373,510,102,962,336,941,870,930,149,433,141,812,607,406,361,828,159,865,787,801,852,376,786,65,794,250,386,660,112,254,884,406,197,160,39,759,168,708,859,383,367,180,249,215,801,925,467,827,489,43,864,585,244,745,277,600,77,80,33,198,42,253,90,745,675,761,776,596,983,798,785,842,816,22,452,665,580,625,767,415,585,174,357,188,568,402,651,244,953,358,768,826,707,412,215,144,225,476,994,485,531,2,965,582,706,727,729,935,76,5,795,278,51,862,409,324,137,548,620,284,38,202,762,170,150,206,774,270,957,212,328,182,523,757,574,664,301,805,280,44,92,955,471,494,102,382,603,958,358,674,245,675,824,57,797,84,540,555,238,621,314,773,713,980,565,543,30,770,718,218,943,701,978,120,283,798,958,510,977,562,874,91,669,185,942,671,793,603,621,335,219,505,697,522,816,43,585,773,418,185,91,247,714,266,444,448,373,475,618,942,448,311,130,486,561,344,310,304,685,863,618,670,953,566,481,804,935,474,796,676,556,528,349,770,353,416,97,856,125,768,124,723,7,885,121,363,933,658,641,547,254,413,368,331,435,878,250,991,731,804,717,362,294,667,360,123,89,870,574,109,241,699,327,795,132,160,62,811,656,531,430,262,369,467,863,755,635,83,936,262,225,467,698,825,947,128,989,103,751,410,106,671,473,802,215,136,710,576,317,996,582,230,351,171,377,435,816,614,394,106,818,145,9,202,716,204,717,120,276,603,245,652,768,395,778,791,185,396,387,239,8,998,250,413,963,161,877,574,938,992,462,876,380,181,836,134,224,513,314,917,472,600,727,404,577,886,27,320,107,906,530,673,252,805,121,818,722,863,995,994,779,266,782,941,561,692,451,470,690,742,691,454,526,767,628,415,638,545,781,454,695,316,257,900,491,383,155,297,758,230,913,24,896,15,46,761,165,400,583,897,402,322,628,498,617,464,244,759,458,578,266,32,170,370,699,990,612,262,462,670,581,713,808,775,342,362,508,528,261,293,122,204,190,785,792,444,588,952,401,542,410,340,349,305,367,149,500,907,224,555,771,641,127,675,155,745,807,181,799,884,408,619,319,298,771,308,203,661,929,127,407,899,393,740,344,52,968,838,696,42,653,6,872,93,162,622,771,602,649,393,927,651,580,891,113,407,449,804,145,984,420,568,657,282,604,31,698,881,520,343,239,757,893,798,101,815,772,857,84,486,225,829,0,365,955,84,986,196,977,739,120,613,84,789,928,61,855,368,178,879,903,873,641,864,747,943,451,296,637,396,756,83,457,648,580,849,237,262,204,137,664,755,636,981,932,606,443,421,519,110,587,570,706,893,478,519,326,467,580,775,797,785,518,726,689,826,230,791,917,415,612,262,752,656,875,396,330,497,794,555,11,169,984,852,255,477,951,675,47,855,476,436,103,378,574,12,822,305,736,699,600,863,823,460,181,939,978,239,700,598,674,263,933,445,582,174,685,362,611,575,56,348,101,899,520,53,999,488,378,881,153,967,482,859,801,948,319,166,996,311,696,829,559,648,158,118,870,523,754,90,767,73,790,945,478,861,147,627,984,145,181,417,139,958,137,936,383,781,609,523,138,269,112,251,787,542,324,791,762,828,482,337,156,327,330,641,75,765,350,250,866,76,716,905,126,341,906,454,178,764,748,83,963,471,261,779,633,917,795,412,474,254,624,841,220,826,458,930,683,267,704,664,182,756,149,544,539,663,153,23,229,327,438,633,467,394,33,667,31,374", +"11,333,46,645,395,141,168,716,75,926,627,336,1,769,891,821,873,500,987,62,525,323,135,731,306,46,370,11,900,298,209,793,930,68,671,959,306,707,157,133,103,84,849,746,188,663,561,625,381,751,257,281,966,294,466,501,105,905,807,676,54,827,842,61,767,590,45,826,603,123,479,583,733,539,235,15,193,885,575,61,306,357,743,189,621,152,614,674,37,374,398,663,691,660,410,85,616,918,287,977,18,696,328,279,129,594,705,105,977,538,642,960,665,98,295,548,951,129,397,890,78,65,616,355,13,735,288,784,205,40,339,31,204,329,273,234,392,491,835,884,880,181,962,326,904,669,368,845,18,910,690,529,399,626,998,569,557,384,461,188,993,53,223,420,690,440,514,101,962,350,819,640,131,579,44,258,418,612,495,611,604,206,767,14,220,32,28,93,175,214,652,954,585,484,333,853,893,507,642,200,301,439,95,508,478,448,90,125,299,369,428,856,878,443,526,251,380,499,179,56,193,368,790,762,911,272,158,318,940,987,93,289,409,366,970,303,547,332,128,534,387,140,614,705,420,164,589,841,243,956,429,290,372,911,548,722,271,832,481,522,818,995,724,700,596,153,418,876,192,377,459,763,255,397,284,671,849,44,11,835,521,373,820,490,140,268,88,508,471,867,834,373,271,149,807,589,446,807,813,435,515,820,912,931,968,64,12,508,155,719,735,332,736,800,93,481,158,692,914,577,929,169,775,669,506,843,516,188,619,321,617,678,483,602,609,727,32,616,234,196,592,193,245,1000,609,557,945,398,749,53,770,480,958,115,69,174,847,77,729,86,71,524,480,632,438,402,769,147,4,697,421,23,457,438,684,665,63,973,271,236,294,416,912,158,739,9,858,110,838,997,683,842,114,983,52,11,997,985,149,897,292,456,547,97,700,39,628,829,102,861,124,637,376,521,950,359,379,439,93,241,662,286,466,115,393,83,875,692,99,612,388,972,274,570,715,481,898,460,126,339,710,280,243,980,999,438,211,194,802,563,363,743,533,874,129,877,420,230,669,678,791,600,479,56,115,346,741,434,72,74,555,683,791,394,719,202,849,19,199,619,484,928,601,583,390,41,802,64,28,885,665,493,783,388,926,308,960,77,166,519,69,69,781,859,275,232,288,51,547,938,846,791,962,784,797,588,574,975,139,437,455,854,704,81,43,893,961,909,199,366,679,437,396,979,547,359,578,561,666,613,441,131,95,578,700,586,366,109,278,742,846,705,922,811,897,117,119,35,725,174,858,668,77,95,947,870,686,583,498,607,543,156,447,348,82,451,660,505,990,769,506,909,557,368,464,603,991,836,509,501,152,921,723,59,492,593,975,627,189,44,609,927,193,76,65,209,490,33,462,419,313,171,414,414,144,499,645,927,491,704,387,566,214,171,469,301,715,490,241,676,830,436,582,871,138,233,213,731,753,453,861,572,807,448,625,754,83,312,187,657,631,823,915,571,162,599,614,498,615,629,253,686,387,597,849,845,907,342,202,709,704,905,136,77,996,324,655,563,538,688,751,960,814,690,888,283,867,537,112,391,782,963,476,215,493,868,952,437,414,180,949,461,641,62,264,303,315,290,992,610,585,658,883,246,796,939,662,485,809,128,466,876,661,758,964,680,197,87,771,184,323,493,814,781,649,862,372,282,368,963,879,878,544,642,320,662,36,84,294,131,428,88,18,451,363,268,171,366,72,45,831,940,365,0,66,228,213,691,718,657,528,412,756,143,316,321,544,780,356,790,523,4,980,775,249,347,366,710,49,829,472,161,169,935,265,299,253,306,308,348,653,381,806,249,296,248,557,576,32,640,353,30,382,198,500,417,350,617,168,467,521,924,483,680,641,664,862,482,413,80,261,798,500,802,688,711,387,619,376,888,933,238,874,504,368,819,306,799,577,933,159,800,943,960,600,967,512,122,53,339,770,551,484,798,3,322,858,809,687,892,696,139,35,951,668,925,729,822,104,831,965,265,297,211,564,366,600,158,671,420,699,550,182,173,637,510,740,598,180,463,782,161,582,787,88,679,86,890,160,363,796,505,616,111,375,579,309,945,911,34,48,814,355,960,43,432,824,188,392,428,439,115,567,501,432,85,530,491,293,194,31,588,382,497,74,64,160,90,547,999,952,31,910,255,285,604,460,915,172,18,679,30,455,103,559,898,48,103,127,672,305,523,264,163,862,436,909,590,563,198,436,264,436,766,234,299,531,958,101,519,788,354,855,248,84,18,193,940,348,613", +"604,221,246,50,785,274,859,583,73,951,376,329,511,472,714,316,520,551,152,756,609,530,997,643,97,428,281,682,654,308,31,606,923,388,319,220,944,377,490,300,696,525,929,641,675,85,924,877,221,484,199,756,868,867,172,310,197,7,257,872,368,37,499,14,76,589,481,226,928,263,31,410,848,733,537,160,443,30,999,416,471,7,255,56,16,860,346,716,385,697,620,573,888,514,298,815,142,489,877,274,778,795,989,53,465,109,173,26,531,188,569,373,109,281,798,155,784,397,51,783,766,833,495,982,522,758,122,332,804,984,410,745,771,450,233,792,310,859,488,763,957,101,202,252,841,739,570,840,527,86,815,817,693,749,668,516,810,808,702,585,438,877,278,375,358,767,729,973,545,533,463,449,762,100,643,612,716,580,866,525,578,879,417,183,317,656,267,338,191,931,338,474,759,629,609,992,448,585,8,353,550,390,937,656,7,647,121,872,283,628,534,13,697,818,422,242,872,619,149,480,765,446,182,763,650,793,738,507,667,438,781,746,691,844,852,791,422,458,573,108,256,911,835,519,833,322,456,643,696,132,541,938,560,430,829,178,31,473,939,465,42,470,222,828,946,381,260,83,832,58,338,286,925,451,601,475,381,474,732,251,354,47,109,438,8,457,185,85,593,512,625,84,255,444,295,84,295,799,667,801,249,919,218,223,948,974,732,529,508,135,959,43,307,483,41,949,46,68,12,523,59,701,897,186,280,392,324,987,697,190,839,629,552,906,810,573,513,847,513,430,767,284,118,58,436,222,423,228,411,614,862,908,891,611,512,504,654,179,859,584,174,618,677,942,284,661,619,409,546,628,833,545,831,70,484,656,338,10,694,912,539,372,170,853,824,705,42,265,683,178,581,26,414,566,977,942,809,427,825,487,280,834,748,936,8,274,27,742,211,192,781,665,826,198,739,915,326,470,752,880,882,850,35,131,376,241,242,761,668,703,684,939,580,608,934,154,586,322,225,960,902,580,538,41,155,693,745,988,508,751,373,500,166,359,381,106,447,914,210,700,997,515,466,510,459,656,988,317,146,836,766,831,13,365,960,110,562,262,39,622,469,630,833,545,963,258,311,142,779,672,903,149,344,452,288,532,105,674,225,951,769,317,24,630,664,602,134,49,922,968,399,949,147,811,388,605,695,448,108,20,142,233,987,748,45,711,343,104,804,965,387,133,705,871,450,206,488,583,811,792,946,522,417,519,119,109,215,465,637,179,89,42,587,92,894,164,408,48,815,860,952,583,58,419,608,546,122,93,974,592,640,293,354,928,388,946,574,751,40,500,504,927,481,418,952,36,801,264,213,568,389,80,760,393,319,998,346,484,478,344,156,139,182,806,932,365,541,329,612,548,13,205,283,185,609,511,826,586,287,441,259,43,603,733,75,477,590,568,254,944,66,688,80,997,740,809,316,714,401,228,537,88,705,770,682,130,298,720,955,757,621,931,287,804,852,402,323,271,616,593,47,56,195,426,438,833,571,215,788,605,377,391,184,672,421,994,223,863,68,412,808,716,81,316,464,42,929,540,536,730,948,980,224,58,513,921,5,54,447,369,510,598,667,280,439,540,752,204,766,76,329,587,982,384,156,439,566,874,772,856,29,723,306,532,388,803,481,257,970,609,885,553,52,852,468,978,436,6,233,200,328,728,116,855,147,193,455,988,219,992,853,112,878,457,534,580,554,915,350,726,755,849,955,66,0,614,983,167,813,659,567,203,869,353,188,138,352,669,155,570,366,30,197,479,729,848,47,133,915,414,838,298,983,700,472,411,894,721,879,878,743,128,786,486,219,66,685,721,620,477,962,28,504,676,761,556,142,265,422,14,44,906,568,819,940,885,7,82,820,164,85,744,217,608,933,367,410,574,7,972,215,671,901,679,513,145,907,545,794,601,891,126,69,217,430,386,328,570,700,464,824,422,649,40,906,549,663,234,67,825,54,951,179,818,781,670,531,147,975,677,354,691,726,641,859,156,584,457,824,684,176,677,191,275,296,747,286,396,805,263,123,857,236,519,706,863,700,853,968,561,752,148,194,359,907,379,420,633,694,852,895,17,93,23,502,687,819,416,270,565,529,319,550,255,36,388,638,892,441,818,696,350,185,130,91,170,98,853,651,585,865,874,783,22,517,985,29,923,78,945,464,566,597,481,941,795,316,45,381,674,564,146,45,572,76,881,218,936,782,777,423,631,847,475,331,736,533,466,271,575,959,846,541,320,617,100,348,594,514,331", +"384,223,275,469,784,981,901,922,597,760,440,6,369,270,123,835,500,933,629,270,734,981,20,138,115,840,988,919,313,996,904,72,144,156,925,758,486,434,442,159,987,994,223,418,704,801,336,525,386,8,338,615,245,669,114,882,701,972,804,988,938,298,565,512,451,589,484,399,391,15,749,293,143,713,181,840,903,726,471,480,354,328,26,512,932,846,557,920,170,856,594,947,538,558,164,206,77,962,943,128,252,437,514,681,654,344,912,650,850,784,923,872,324,417,144,615,723,552,35,969,834,214,793,961,649,781,164,108,491,652,284,107,138,483,953,890,213,578,900,958,94,847,898,410,899,666,814,269,133,781,941,186,585,894,424,304,994,916,349,960,578,921,353,42,347,177,654,466,971,165,910,946,299,146,803,272,215,374,423,324,928,733,908,397,129,327,161,97,413,698,687,33,644,789,957,676,365,214,641,657,937,212,503,591,380,520,318,373,384,100,656,404,599,144,95,363,228,956,221,898,893,894,896,291,420,896,255,142,925,648,167,955,850,22,653,907,509,486,347,846,940,571,208,171,940,997,902,141,444,836,499,123,777,472,424,155,461,698,720,180,450,198,401,871,488,385,551,752,582,250,263,593,640,357,378,568,169,608,186,476,32,562,465,997,499,937,231,866,320,843,989,843,959,481,199,149,541,902,538,242,137,454,828,708,32,192,949,306,202,621,991,732,89,371,256,345,855,277,243,216,38,548,655,470,84,542,693,902,223,128,929,429,528,695,477,114,678,90,806,551,754,491,166,259,126,212,354,754,628,823,421,969,962,943,405,88,115,423,173,246,15,472,430,3,866,766,387,207,748,613,111,855,79,676,175,300,297,107,448,989,516,529,822,281,441,230,902,117,818,265,367,897,771,279,643,140,914,49,971,527,543,421,594,210,931,294,91,334,472,488,892,486,539,828,498,127,661,455,639,52,251,893,74,186,357,589,182,927,689,995,848,486,9,248,167,537,760,557,151,248,523,154,439,207,501,825,136,522,953,458,956,338,465,816,221,696,135,882,819,721,474,766,83,29,432,775,484,271,705,183,22,557,623,121,395,965,723,969,420,860,722,824,803,842,936,414,969,194,558,678,756,539,771,219,706,70,98,628,874,499,580,619,311,582,341,562,101,140,606,406,850,884,679,533,251,100,701,641,303,920,521,719,436,859,809,731,113,697,41,76,816,211,8,403,999,223,868,324,22,762,547,2,85,730,502,317,167,490,27,960,862,75,659,756,897,367,929,720,907,121,145,187,486,636,989,820,680,319,582,398,827,776,163,882,984,731,306,855,481,922,963,52,132,282,643,214,863,473,422,515,13,496,695,648,114,784,917,626,408,267,793,621,71,687,683,758,787,401,202,3,687,835,717,237,655,138,224,448,816,670,794,105,626,739,287,373,336,165,568,442,136,135,540,411,410,430,274,578,205,965,503,875,139,165,962,835,159,249,198,178,779,38,34,439,61,637,995,362,637,183,223,524,401,22,572,212,895,738,52,653,452,171,563,350,74,879,305,485,650,609,643,890,939,803,796,106,143,186,194,978,853,469,826,250,584,803,835,132,35,648,639,618,50,395,943,606,536,625,565,867,789,750,308,837,253,542,466,592,700,887,533,40,915,316,896,670,798,408,509,482,764,185,447,576,754,899,663,291,631,400,948,137,503,287,231,229,701,840,280,815,573,221,156,780,679,114,226,231,358,791,896,655,84,228,614,0,788,530,780,861,698,234,666,471,165,679,982,311,225,85,758,5,494,44,437,30,455,360,458,692,81,139,526,54,653,275,522,879,404,72,21,154,139,986,56,879,511,91,503,200,115,686,601,608,826,222,167,870,867,466,286,677,430,123,683,717,17,787,627,206,929,8,607,230,881,949,206,169,724,174,689,431,299,176,178,239,998,68,602,392,630,382,344,926,634,616,623,513,914,698,428,185,12,881,301,93,774,228,444,982,93,365,686,973,606,973,305,916,668,912,910,710,417,685,910,167,303,657,93,393,621,586,111,185,431,498,984,363,952,73,755,853,915,117,26,532,961,718,430,531,857,573,197,929,268,911,732,186,493,339,866,983,918,181,256,793,269,226,616,151,886,71,593,767,556,494,78,898,207,504,483,187,586,93,587,423,885,442,373,526,181,852,900,685,836,795,178,607,410,771,646,928,62,559,506,490,296,104,708,493,115,47,352,768,739,986,764,196,841,848,355,76,624,900,132,231,314,359,265,600,972,95,625,765,599,843,162,283,269,823", +"440,95,400,67,220,777,93,471,599,904,289,28,346,248,955,275,220,376,58,601,337,543,882,393,951,695,567,178,910,302,388,445,496,383,688,649,887,844,209,767,843,54,998,38,894,444,540,300,991,984,244,408,96,802,238,262,365,128,645,236,166,542,818,340,681,171,173,126,975,668,161,189,318,63,885,378,811,656,786,324,114,469,876,575,997,951,65,365,292,358,54,727,583,123,516,868,835,652,179,112,886,40,596,873,571,874,804,753,778,873,516,90,9,426,756,75,972,657,597,621,109,764,96,786,883,705,826,62,193,673,624,505,950,638,175,408,252,11,81,581,705,493,909,428,445,303,984,619,623,620,190,121,584,674,341,772,759,518,435,40,871,94,401,246,951,692,299,772,43,66,362,432,498,148,927,338,375,696,157,207,295,377,668,958,884,548,272,970,140,944,39,839,778,905,277,952,658,894,843,14,132,272,872,32,59,928,446,534,576,185,363,918,543,661,402,500,607,922,679,934,336,640,726,687,174,787,101,18,470,736,639,275,848,116,350,434,401,993,104,370,544,770,427,727,55,157,345,406,181,285,417,234,757,693,111,268,80,363,663,730,924,893,710,618,855,445,245,392,409,780,150,591,349,366,522,265,712,864,144,941,174,790,162,844,507,196,585,844,680,250,384,707,223,217,397,764,463,20,200,629,646,168,26,86,676,421,220,521,276,404,985,690,647,19,812,348,657,419,902,968,246,741,294,77,893,281,646,222,611,212,463,223,857,490,439,634,199,26,750,964,340,624,377,660,946,598,257,854,613,203,876,144,751,175,735,617,847,828,597,285,557,263,474,761,436,844,146,160,624,127,909,595,947,288,915,730,234,782,754,946,342,805,7,98,195,934,24,572,574,755,760,700,547,660,461,203,447,515,259,992,430,915,278,544,248,270,628,904,788,331,52,791,55,196,197,727,706,498,985,950,275,876,475,333,625,918,287,418,553,646,11,730,453,968,413,439,286,559,838,410,215,99,641,843,604,336,251,529,788,176,382,345,704,776,159,302,745,141,355,721,342,987,539,967,857,245,503,431,834,211,708,78,994,638,48,111,357,466,84,450,907,416,817,939,41,875,654,431,236,220,199,274,197,885,654,339,440,66,122,705,708,443,115,134,250,875,583,165,46,342,131,996,13,747,15,312,498,434,91,163,852,574,739,395,820,233,483,803,301,819,861,208,685,587,560,466,655,572,24,703,611,587,907,939,529,377,482,257,139,190,749,867,520,22,398,325,198,999,739,353,861,472,841,710,939,435,691,495,122,394,687,273,208,304,954,614,354,855,563,844,121,610,634,293,844,194,963,659,374,973,128,918,51,574,358,636,653,868,508,381,118,28,208,744,354,491,897,92,565,664,759,433,803,505,148,186,206,61,754,16,618,488,730,166,701,972,404,908,166,10,554,423,203,722,404,387,697,502,96,481,240,315,251,561,478,44,577,767,638,19,490,201,966,551,855,221,469,229,276,198,347,39,758,904,573,211,838,349,99,724,120,961,56,710,154,177,498,595,429,543,585,12,71,58,723,491,634,552,618,250,489,373,702,831,909,754,971,438,108,378,114,675,239,96,425,672,401,382,858,182,920,941,576,460,976,888,904,706,791,218,116,492,552,503,29,690,949,263,138,148,795,587,811,861,671,374,171,271,592,160,251,422,509,4,882,831,765,346,184,217,596,375,519,272,950,617,694,8,847,227,919,856,986,213,983,788,0,443,710,851,282,283,859,603,69,616,335,520,963,198,31,91,388,352,906,981,802,771,730,204,190,440,456,433,127,890,545,765,403,335,332,942,921,552,892,424,236,534,463,697,776,879,620,614,706,326,213,149,417,274,479,672,886,266,482,571,960,910,708,322,423,888,98,452,763,21,654,940,430,602,192,610,604,619,683,986,560,935,321,40,285,18,863,330,732,840,680,358,712,272,520,381,737,590,498,754,601,753,288,885,244,827,61,588,505,664,391,492,415,346,389,735,400,126,233,404,318,697,368,66,350,90,50,620,114,983,657,736,965,845,278,362,976,349,548,999,574,407,311,977,102,572,305,757,375,463,675,233,44,976,976,209,337,521,733,890,817,421,619,715,157,488,923,707,139,762,526,986,483,278,861,127,903,561,178,399,371,692,403,937,415,814,604,977,751,310,737,769,603,641,176,940,713,688,731,695,956,617,690,744,27,174,904,764,241,220,293,211,278,842,87,391,642,862,919,635,27,465,738,947,498,345,891,320,76,762,599,11,36,113", +"914,665,664,923,876,558,630,365,951,408,173,906,444,216,852,625,182,235,31,71,213,671,713,130,937,710,629,535,602,17,782,200,365,529,141,68,735,886,86,954,893,977,896,168,291,861,715,664,256,773,554,249,243,72,789,773,855,924,643,751,600,372,77,986,476,595,208,565,205,311,120,1000,975,469,471,860,732,770,503,641,138,628,98,76,240,148,318,930,31,365,730,281,478,506,338,691,545,432,463,943,493,30,90,471,489,913,971,578,587,728,151,236,761,259,665,29,623,313,898,150,242,793,473,836,686,3,328,140,48,785,904,874,192,304,850,153,309,850,458,299,825,923,454,955,570,194,587,626,806,87,756,654,221,954,248,149,328,156,923,748,509,56,311,495,466,552,897,577,630,494,333,344,698,426,275,632,263,962,403,840,396,670,401,776,672,586,215,832,937,516,8,47,106,905,912,398,338,818,362,444,860,952,210,959,561,471,751,630,267,237,527,378,858,372,206,754,144,283,509,491,651,575,875,756,715,844,552,376,199,659,258,272,637,896,581,84,457,181,450,869,697,355,856,363,613,655,257,90,386,538,970,235,471,812,739,978,867,273,409,419,575,784,847,288,13,278,10,285,918,670,679,602,782,316,37,383,200,142,419,577,786,237,894,947,595,580,686,897,232,780,708,114,586,13,994,818,134,812,370,805,615,670,619,583,425,192,502,394,680,464,712,375,541,694,538,50,8,181,285,628,298,304,646,218,584,975,917,241,474,13,711,533,637,36,624,102,41,80,301,633,725,319,782,512,296,832,564,906,445,27,201,236,9,658,338,131,457,152,427,125,249,474,125,335,410,512,203,908,559,475,555,695,943,420,105,294,880,400,818,568,642,453,424,387,682,803,980,776,537,365,370,675,608,455,229,297,256,489,12,504,866,893,346,600,469,487,867,371,249,598,230,372,37,59,555,11,642,47,173,91,258,643,298,186,753,444,510,967,608,360,963,703,124,204,523,187,671,188,634,14,24,886,520,283,635,105,697,130,127,885,636,703,638,779,193,791,701,669,429,589,341,863,659,364,599,338,444,859,651,463,613,875,562,109,282,93,223,352,872,305,726,386,962,476,242,399,507,850,796,359,575,655,768,31,472,819,92,925,788,381,921,262,372,428,343,813,364,588,118,489,774,184,207,885,383,104,514,339,461,304,311,90,896,694,160,978,585,354,91,452,379,612,980,138,310,159,145,308,493,227,775,96,187,836,518,975,674,78,852,76,877,896,135,897,233,795,421,992,661,335,47,74,634,698,117,887,402,102,225,448,238,454,310,622,889,494,29,476,430,840,438,445,308,831,891,332,48,190,368,779,972,219,7,206,393,314,229,442,497,455,277,868,488,784,146,216,841,212,74,882,757,835,609,696,171,113,539,359,70,899,134,853,819,317,312,31,199,571,489,569,373,759,255,93,589,871,679,527,155,762,339,823,199,282,216,865,43,396,442,649,412,232,584,649,317,586,706,143,234,931,445,114,714,407,875,342,354,444,292,487,337,626,26,478,91,621,640,913,384,142,178,341,676,821,705,821,853,667,868,545,877,626,884,423,551,70,759,363,763,669,179,430,237,151,186,602,632,1000,967,321,323,978,354,882,760,745,980,264,566,700,240,219,969,621,973,651,541,670,950,271,983,752,193,483,425,488,818,998,359,918,80,333,646,113,403,914,710,853,20,553,322,142,478,543,286,49,748,333,342,240,403,157,196,691,167,530,443,0,114,148,993,745,979,132,149,74,117,84,435,844,37,267,853,19,945,140,555,696,618,64,951,69,424,444,569,791,721,239,59,627,68,140,791,169,407,344,63,88,790,395,949,702,51,651,493,321,899,791,796,529,993,712,242,245,880,330,554,250,850,721,988,652,160,337,38,638,494,750,650,162,599,198,120,658,467,528,76,188,745,523,902,295,615,106,269,458,766,81,297,726,488,836,43,415,148,920,258,588,793,543,165,249,225,413,716,334,984,466,941,622,478,978,828,309,711,536,304,220,10,159,335,266,14,912,71,446,170,307,16,155,387,491,305,154,236,837,733,913,720,76,263,835,926,443,519,4,159,171,691,931,381,226,462,497,339,539,682,131,836,396,181,185,149,102,98,706,487,66,429,924,563,766,545,149,171,837,600,89,706,46,941,224,125,297,496,181,49,639,749,376,425,787,315,527,54,575,87,398,436,151,113,446,339,435,526,115,800,721,371,929,740,241,66,495,887,370,390,862,846,538,613,103,61,667,873,323,853,185,181,10", +"286,884,787,552,21,152,989,919,499,508,646,258,695,402,209,484,63,593,951,117,37,420,438,112,422,496,648,102,511,899,982,158,130,114,94,480,696,548,751,540,650,709,725,977,117,193,133,152,595,960,513,360,819,866,166,405,705,641,460,244,15,237,575,842,176,971,761,7,504,819,454,962,24,712,629,554,226,704,624,576,86,201,461,491,550,188,292,413,297,608,948,30,207,968,726,586,875,716,488,59,470,246,371,171,470,175,74,349,515,293,346,14,986,285,83,596,49,473,349,940,944,302,522,451,42,219,793,467,466,572,85,543,88,518,976,71,93,3,701,237,366,564,963,945,864,506,820,405,890,251,599,922,116,508,298,791,823,328,741,500,403,662,782,995,810,877,575,433,520,129,805,285,418,864,858,85,472,288,535,944,368,688,440,236,931,845,599,407,520,632,511,822,266,127,608,585,766,46,732,696,782,779,944,331,190,671,42,531,880,165,45,837,105,474,291,543,804,963,884,764,885,12,347,17,55,43,39,233,756,324,256,900,830,90,471,282,600,107,284,573,465,553,688,823,184,101,729,3,738,946,357,128,537,735,21,340,311,612,856,887,712,166,207,535,326,847,829,842,527,159,485,375,835,807,446,357,106,243,62,93,129,572,406,861,641,213,777,328,210,649,420,36,213,751,217,516,580,48,690,794,628,96,428,582,155,630,348,70,120,966,949,762,625,35,607,534,703,763,478,355,924,262,3,328,809,400,846,420,943,363,667,616,731,84,584,711,347,465,747,171,66,503,594,205,375,858,372,771,544,467,874,703,655,581,154,723,212,125,707,800,695,990,907,362,958,926,51,124,39,57,423,854,257,932,729,547,616,140,233,558,280,17,170,953,286,943,220,278,40,696,291,252,245,902,829,965,735,994,549,784,106,51,388,346,740,164,424,554,823,19,710,820,465,873,63,60,445,43,168,382,924,301,109,154,368,399,225,121,60,309,993,365,533,200,485,482,399,607,405,582,351,544,330,700,962,377,702,871,148,496,352,720,55,608,635,828,80,900,158,208,853,39,593,634,719,255,96,950,684,34,1,154,240,723,787,723,938,427,947,418,752,48,155,601,486,17,687,247,621,505,599,76,154,857,750,549,499,115,687,248,715,637,895,530,507,40,144,510,776,637,713,183,594,819,843,387,545,625,53,882,311,188,357,247,597,446,268,816,506,634,933,382,245,865,621,939,23,621,939,575,708,418,739,48,592,371,903,573,465,71,882,188,266,61,974,401,913,680,725,760,610,394,683,203,930,756,251,832,774,560,386,236,234,698,888,544,626,836,206,579,820,711,510,538,251,178,513,408,547,980,762,753,490,486,835,537,150,830,677,910,410,454,100,644,932,634,124,580,39,586,561,325,644,976,168,730,94,625,258,612,936,365,677,980,126,188,111,946,262,730,914,49,254,377,363,731,435,962,473,147,578,566,75,194,20,590,431,368,883,234,722,536,714,624,411,135,424,578,512,663,761,317,445,156,532,342,590,318,171,555,748,445,255,498,9,766,314,826,427,773,905,137,314,435,8,203,77,696,163,860,40,954,820,72,51,296,951,817,393,556,975,675,157,424,348,188,17,324,965,292,523,321,220,872,236,732,436,838,250,295,678,164,793,825,18,636,675,715,4,3,802,52,598,21,945,132,429,461,834,995,26,104,15,679,920,974,685,301,766,957,842,62,629,487,324,838,996,294,10,602,631,43,977,718,813,780,710,114,0,418,868,568,504,326,743,549,246,592,669,724,260,916,953,362,470,30,151,279,434,143,299,611,372,638,359,969,664,298,3,974,921,165,834,528,98,176,873,778,989,316,792,575,427,101,353,719,900,285,830,25,161,111,645,78,324,562,400,695,954,783,927,97,265,137,188,246,525,886,662,400,302,187,787,427,169,530,812,673,740,675,901,831,225,824,586,857,575,900,639,45,803,507,948,26,194,902,33,60,369,160,845,242,37,237,302,611,362,756,38,553,302,636,867,36,229,275,337,66,414,950,280,21,171,819,392,291,190,567,210,156,345,761,369,295,857,200,631,792,619,197,419,783,943,605,732,56,287,422,921,618,265,231,957,529,93,244,968,46,512,75,971,898,755,27,512,631,310,519,182,167,575,355,808,33,637,99,649,955,127,24,379,573,18,209,607,603,591,135,803,812,825,838,137,390,267,703,502,335,425,815,512,596,513,819,424,99,903,299,655,78,495,656,320,144,405,160,485,490,592,516,220,550,712,548,172,103,679,587,130,67", +"110,235,817,198,6,635,343,736,649,516,976,75,742,197,946,251,931,560,76,220,393,904,770,185,97,445,430,827,483,541,365,997,878,439,829,953,318,495,806,446,731,347,101,575,485,108,596,737,683,966,615,919,414,804,266,907,140,832,156,703,968,80,563,676,146,999,621,618,402,391,725,77,506,920,218,429,537,205,369,844,878,854,29,636,793,612,214,124,488,223,902,859,428,455,302,866,870,260,799,246,914,811,635,236,266,185,125,953,460,924,697,678,334,541,404,300,358,241,180,256,88,868,355,779,464,590,66,883,11,696,263,314,968,484,832,457,532,805,792,551,547,81,125,767,460,875,868,505,622,462,102,602,857,837,187,468,625,907,955,799,672,901,273,635,484,177,775,342,425,493,673,566,176,23,381,93,513,879,732,666,332,429,552,175,863,972,990,561,39,729,832,247,811,936,175,728,890,697,794,434,328,539,968,205,292,89,255,503,883,680,524,632,626,745,143,786,591,725,654,744,781,894,795,851,452,871,506,711,217,30,318,883,889,99,656,535,792,279,166,449,882,384,360,811,188,696,300,873,330,291,62,795,637,59,693,33,564,259,876,391,391,394,878,102,129,607,493,95,145,363,645,387,311,814,751,493,261,679,45,758,121,432,412,673,825,965,433,949,263,375,729,732,860,814,201,704,126,720,670,614,59,801,544,541,735,639,230,957,241,400,348,322,230,583,906,186,179,77,375,763,540,792,129,199,443,871,688,897,693,657,343,802,279,322,984,224,374,550,39,794,804,901,80,902,605,435,280,821,150,576,720,203,339,780,213,354,616,558,101,57,250,623,179,190,63,976,220,770,546,71,744,953,617,761,10,798,22,574,420,431,68,286,218,539,142,139,398,91,446,712,856,195,688,977,647,27,560,167,912,531,692,540,408,850,666,690,480,745,304,675,403,203,30,216,845,320,405,587,668,857,549,40,607,217,282,228,379,470,863,668,480,958,150,168,431,208,777,606,751,382,652,404,461,487,143,747,906,633,518,927,779,14,709,141,892,259,9,628,61,745,578,211,224,23,824,552,397,149,815,957,411,382,186,599,934,827,505,132,900,902,916,213,636,457,182,208,941,316,981,818,557,765,824,71,671,359,431,325,715,460,306,465,885,352,758,226,519,387,800,165,295,802,578,121,118,329,791,954,37,286,881,797,180,224,265,993,16,208,5,218,959,527,525,248,440,955,141,439,562,507,419,298,298,273,678,899,909,63,819,837,176,527,374,681,183,263,167,201,816,82,652,403,530,133,926,489,536,845,801,968,684,73,178,830,187,169,915,565,962,457,472,417,881,426,164,218,596,700,520,894,57,344,782,192,190,842,857,798,571,735,935,186,252,20,44,51,470,702,851,533,945,848,767,377,322,120,106,906,376,607,499,688,757,219,243,734,295,526,295,993,592,138,98,878,620,724,181,772,321,384,515,302,808,728,534,674,580,682,174,344,275,516,987,465,158,532,753,818,967,710,334,834,561,395,768,597,702,382,184,355,268,601,694,774,835,177,347,936,791,620,90,251,584,993,608,383,641,12,89,388,742,751,501,789,832,204,162,295,866,239,967,774,37,222,914,499,973,427,592,664,959,312,509,910,988,567,169,666,50,248,68,604,736,642,351,764,429,588,60,550,225,758,523,88,264,942,719,957,942,81,738,633,689,625,520,238,482,314,587,926,395,863,152,831,776,241,504,7,201,452,230,931,739,657,659,861,851,148,418,0,107,9,953,737,790,642,66,35,642,884,164,355,317,521,64,274,400,560,868,331,556,894,581,519,402,987,79,308,849,33,891,450,889,480,637,789,143,263,186,663,303,727,18,918,684,235,184,604,755,776,538,603,928,745,656,212,936,950,996,661,359,573,447,386,381,35,279,491,113,969,569,932,94,874,390,978,160,413,737,64,245,33,816,771,202,802,269,340,624,505,194,569,527,999,209,607,850,706,957,671,698,411,565,414,696,40,663,777,344,541,545,722,721,772,887,811,764,871,830,601,17,506,616,824,549,184,839,931,949,499,810,667,893,176,420,546,140,263,387,252,574,702,96,972,570,463,61,505,987,653,791,843,956,938,464,548,358,122,226,785,293,416,611,399,18,853,4,590,294,625,981,172,444,314,721,873,240,747,435,916,608,431,495,295,245,801,745,858,292,834,212,762,970,199,809,989,200,461,987,813,503,428,650,578,655,706,541,288,756,310,183,321,650,964,241,973,403,446,694,185,921,976,963,935,798,424,976,876,789,333", +"760,8,860,698,904,279,85,251,928,547,201,806,365,460,392,450,212,60,470,756,691,182,281,644,429,129,591,908,326,618,254,623,812,561,49,87,691,352,879,970,460,701,392,271,781,288,806,165,767,579,312,131,713,845,334,376,939,918,368,998,389,761,38,900,606,964,675,369,427,965,655,370,595,992,302,780,873,360,129,230,303,943,429,355,175,259,153,752,328,504,831,159,959,869,810,388,919,935,649,142,65,602,10,369,197,565,224,436,924,799,335,761,518,727,31,420,189,980,784,554,514,131,340,976,98,102,530,161,977,49,644,894,325,69,594,803,388,254,315,694,289,32,674,732,361,483,912,852,764,405,563,989,670,159,143,93,80,827,656,145,223,809,430,421,899,601,41,336,207,610,572,626,590,659,114,508,357,580,642,910,195,282,615,361,243,452,436,933,505,207,770,99,862,332,27,660,478,212,93,392,141,482,810,421,58,350,945,723,220,212,485,741,886,291,205,726,142,693,147,483,617,961,94,515,454,375,186,51,834,962,901,863,198,811,582,79,595,594,85,914,438,623,563,566,994,891,22,328,852,986,412,918,856,932,13,828,871,107,982,116,603,262,331,157,339,849,432,183,60,726,797,383,553,607,419,590,117,740,126,856,526,2,275,152,92,568,184,206,948,680,690,769,285,497,784,143,769,564,568,855,206,500,359,484,271,490,513,641,993,260,551,605,463,142,274,921,831,154,909,28,33,724,672,276,65,48,32,944,546,808,502,105,480,34,998,597,27,769,529,163,653,881,356,213,266,361,629,884,227,580,547,80,675,917,890,989,265,151,674,241,836,258,647,95,175,18,215,433,819,206,994,366,396,844,119,450,13,552,148,75,569,84,231,942,348,774,867,37,959,220,142,789,504,762,499,839,539,706,737,739,705,844,641,911,503,206,962,210,241,148,160,214,982,602,898,861,952,742,409,178,207,936,794,597,774,392,838,589,401,605,177,656,593,978,464,699,597,670,952,667,578,626,582,971,117,535,713,265,126,747,295,279,74,524,843,21,271,870,226,777,784,57,228,292,975,648,366,312,70,427,847,74,971,314,133,34,384,920,602,298,968,201,959,319,929,704,531,57,174,10,50,589,68,880,736,199,683,587,809,766,762,525,673,721,501,450,855,45,611,442,942,529,291,211,872,946,567,226,80,28,802,332,824,273,123,402,424,230,988,769,469,115,725,839,943,949,683,843,262,858,144,127,907,375,898,49,874,444,872,244,16,516,161,118,11,327,48,663,210,829,493,256,837,51,675,337,640,562,691,384,796,181,775,678,812,886,271,205,139,41,935,209,534,405,356,946,727,737,206,292,638,474,426,390,945,479,537,96,303,791,483,499,881,625,327,143,99,758,13,419,979,104,102,96,613,93,330,418,682,745,543,627,288,84,117,995,696,403,910,161,869,188,487,92,117,663,211,602,178,420,482,89,330,697,965,234,547,914,943,945,225,699,965,386,892,204,64,906,195,808,835,599,260,130,857,751,818,553,809,126,495,428,873,256,136,820,822,808,993,548,995,480,355,693,529,249,590,295,213,773,880,582,213,715,241,952,47,715,404,162,671,242,811,798,402,666,371,337,614,27,201,748,255,90,712,965,700,487,409,59,353,200,509,307,671,691,926,994,452,609,238,612,515,236,259,120,251,498,572,683,866,359,65,914,297,360,379,64,655,924,112,984,653,77,11,919,774,637,418,880,749,324,120,528,567,698,282,993,868,107,0,367,196,370,375,68,905,151,607,392,568,182,433,369,523,434,327,678,245,60,272,572,66,119,310,285,644,521,733,670,607,177,145,68,67,574,758,554,385,503,235,284,423,447,617,724,465,12,433,920,405,371,716,393,641,133,485,783,529,707,37,24,435,311,618,684,786,772,78,689,545,452,813,798,414,894,115,505,968,965,470,703,22,192,173,456,419,792,343,290,885,351,56,303,297,743,582,212,660,188,283,572,100,374,927,324,116,89,693,399,478,119,860,747,541,677,331,585,899,130,888,459,472,285,5,130,369,965,3,215,879,646,567,477,506,598,804,840,564,426,165,507,781,342,726,710,897,898,45,390,787,261,654,324,57,240,392,358,780,641,86,268,565,602,655,844,780,651,909,991,767,863,222,788,540,242,552,765,486,674,550,366,847,212,426,290,593,602,687,779,823,322,405,918,17,919,691,149,254,862,457,769,220,705,118,726,873,876,538,299,48,82,263,6,624,986,486,146,220,552,658,342,312,296,10,510,645,289,133,833", +"639,839,333,698,304,862,575,655,252,458,856,145,121,468,151,982,507,281,44,333,438,196,447,997,148,343,624,988,778,43,394,249,261,673,630,846,258,754,222,902,900,765,887,288,145,307,884,410,10,515,784,852,875,249,120,460,847,688,233,765,364,329,87,112,942,708,246,677,471,244,946,532,35,225,514,309,508,728,491,511,858,809,906,532,806,237,691,857,161,683,429,862,823,512,668,103,254,503,489,312,498,214,502,762,86,576,410,324,791,4,788,602,98,108,594,800,960,89,616,752,25,478,620,16,118,761,469,222,82,993,792,612,481,568,110,511,558,258,977,141,330,987,57,639,126,323,805,702,949,45,205,33,711,892,916,232,528,621,86,972,872,764,956,90,252,316,449,982,865,41,915,424,769,239,595,978,605,725,647,240,746,499,123,920,858,300,671,66,979,475,555,95,481,61,694,530,437,430,384,294,616,350,195,114,857,609,990,254,883,62,966,751,327,115,843,40,870,405,987,989,428,2,41,151,128,992,903,395,591,783,51,116,664,908,304,143,152,185,634,884,551,201,70,831,172,523,455,854,170,39,731,613,150,363,182,996,142,486,784,802,677,928,366,30,506,218,746,629,953,840,704,475,179,482,749,263,345,11,248,933,446,749,435,694,247,655,654,24,634,556,746,823,976,301,129,560,912,354,181,499,816,30,977,288,264,567,588,817,142,316,960,59,603,224,509,846,135,296,299,900,453,553,370,445,666,881,109,276,128,129,205,165,717,267,256,554,886,446,684,831,50,945,216,491,505,500,273,72,817,443,435,171,240,300,402,21,547,249,254,9,280,210,519,629,827,615,886,541,717,335,423,566,835,258,648,378,118,409,997,18,710,796,370,29,915,155,728,140,14,757,775,622,471,103,718,645,998,314,47,136,668,519,207,245,719,461,288,327,43,489,308,718,483,807,718,923,863,558,870,207,18,720,561,522,861,564,921,116,432,525,413,331,562,778,886,518,146,318,735,233,512,772,201,570,859,786,546,637,939,382,655,878,535,659,193,832,791,646,77,410,245,202,207,453,651,684,484,676,59,319,587,239,783,201,900,722,581,929,949,769,33,810,392,148,229,135,265,795,52,290,544,298,86,374,110,914,424,63,649,740,974,363,663,676,22,706,451,224,722,405,972,256,183,974,101,149,747,11,284,174,333,699,709,577,987,272,605,921,132,263,141,592,989,477,87,635,556,871,784,690,508,766,273,453,307,728,851,509,692,500,142,900,920,451,169,566,135,511,326,227,461,219,469,103,865,481,183,577,227,815,155,323,63,368,546,910,168,934,26,665,48,9,304,784,479,517,928,512,468,938,527,400,406,747,637,673,219,603,866,233,985,784,837,296,33,388,816,348,789,21,237,594,746,382,567,776,464,323,916,280,877,571,802,119,892,200,367,180,780,702,854,446,94,888,668,589,354,129,606,624,150,6,586,317,963,871,680,121,836,276,867,232,51,388,963,629,266,527,259,500,726,444,499,47,567,90,966,812,78,525,753,903,122,472,58,8,285,458,204,282,11,293,743,22,760,809,328,795,63,35,36,158,441,574,857,688,793,613,976,967,690,481,732,684,715,476,975,826,410,490,660,20,431,855,669,784,474,437,447,135,159,590,231,119,404,255,570,377,470,713,209,140,304,721,464,257,772,663,551,416,768,419,106,739,770,276,216,647,218,430,130,120,546,178,550,458,380,182,742,123,10,106,613,412,203,234,283,745,568,9,367,0,385,342,488,690,752,784,609,972,418,99,494,367,674,863,847,176,120,23,734,859,617,605,624,868,761,389,975,174,396,507,174,757,10,646,905,635,435,948,526,780,677,890,624,817,926,224,911,166,193,344,431,21,751,56,609,63,743,645,849,627,521,319,31,401,386,428,17,909,775,414,651,968,440,421,987,79,319,397,921,57,956,187,125,447,527,866,714,902,809,918,9,413,681,942,375,963,436,597,682,160,397,934,11,886,938,866,53,27,612,213,259,982,997,480,390,974,918,656,953,915,500,966,851,371,365,585,363,734,410,809,6,806,893,133,522,389,252,106,800,142,92,748,702,62,849,14,150,8,52,919,375,205,398,166,411,686,567,567,588,653,724,488,2,744,588,69,117,85,992,191,62,260,623,62,837,529,385,648,142,160,203,944,507,728,168,197,128,525,627,301,884,884,692,73,402,736,699,979,705,185,81,38,985,307,174,378,736,32,988,415,957,586,347,415,141,868,447,352,515,855,509,253,202,92,534,175,784,280", +"284,225,452,741,305,988,415,422,127,473,567,735,332,144,357,547,818,808,439,791,954,381,866,213,368,749,613,138,487,675,936,992,709,342,657,589,614,990,680,349,180,765,661,20,781,959,950,689,318,797,360,75,513,761,701,511,483,17,44,736,718,420,602,22,441,198,217,337,105,250,623,124,995,909,772,840,304,460,829,120,445,490,757,972,912,777,473,249,356,723,831,878,777,950,184,472,569,104,520,264,928,831,795,376,686,917,868,986,457,500,203,741,509,569,52,630,730,728,913,440,489,973,183,754,913,543,491,902,458,531,478,203,620,874,294,219,658,332,121,93,319,363,909,445,307,33,241,580,95,422,351,643,388,448,337,849,698,123,733,726,958,165,869,940,420,184,298,389,641,599,81,102,329,301,313,359,453,816,739,165,908,485,940,972,144,629,917,776,661,59,72,928,214,944,459,163,782,334,304,534,753,837,378,655,5,970,179,953,166,903,747,574,677,30,68,977,237,281,95,895,428,193,517,832,134,32,779,2,830,459,789,737,289,806,432,430,764,556,17,291,457,87,81,273,3,623,643,268,115,827,820,623,926,6,72,830,707,604,343,8,775,48,84,879,845,358,602,770,747,332,388,611,208,173,886,578,835,154,833,19,565,481,508,898,612,485,112,465,508,894,939,609,534,171,308,18,45,444,819,518,736,107,863,377,970,756,628,179,142,316,934,42,78,448,836,73,169,980,561,467,740,210,774,85,387,379,455,492,100,816,538,303,109,602,821,142,325,4,857,656,750,44,844,220,553,884,623,474,720,290,230,436,480,519,695,615,665,695,972,299,556,42,485,705,510,238,261,386,133,457,457,767,246,776,774,359,829,718,464,539,685,989,405,868,396,893,402,899,89,305,574,614,64,717,261,514,535,449,280,869,763,709,589,64,784,390,597,242,868,766,240,922,339,83,520,384,862,836,734,994,572,688,110,220,612,651,32,663,15,512,665,40,993,354,841,718,351,106,974,155,687,801,580,483,546,471,444,616,28,884,238,349,187,734,676,8,296,410,825,312,444,359,99,59,632,304,235,228,492,7,436,747,426,790,596,297,824,268,211,617,840,619,195,7,387,351,421,397,575,311,548,280,535,995,950,347,965,583,981,442,410,311,78,470,562,574,16,815,389,771,198,690,987,387,525,920,360,134,400,386,672,378,505,581,848,35,717,183,537,195,503,542,528,177,553,775,369,970,484,392,92,120,817,288,568,896,303,165,95,239,495,559,461,452,437,298,813,968,888,476,731,42,77,143,52,351,667,867,197,875,489,472,795,298,789,60,170,202,197,701,450,834,782,812,317,250,681,813,992,553,563,601,638,1000,465,83,592,501,687,673,970,909,69,554,415,757,586,169,119,67,96,70,152,770,990,216,368,846,574,747,986,866,62,676,939,273,509,521,463,94,453,274,864,304,350,952,632,649,930,922,394,685,719,175,625,818,236,450,889,351,338,983,725,921,608,520,530,944,272,944,2,776,275,714,156,460,52,791,738,87,407,101,878,440,833,664,520,419,281,525,449,81,951,978,974,593,797,7,38,493,964,169,968,548,103,714,696,306,329,103,563,406,563,117,593,490,591,712,857,868,396,804,602,157,86,368,799,101,565,773,956,860,203,267,348,764,869,316,675,42,500,480,211,772,905,234,230,371,503,632,873,962,23,808,240,947,205,451,301,540,617,910,452,619,881,526,121,982,40,166,929,653,84,756,869,666,859,979,504,953,196,385,0,636,107,735,823,947,627,677,332,86,767,542,746,711,831,586,901,31,912,831,164,381,830,683,957,388,312,728,522,934,829,29,335,975,359,609,484,864,107,443,327,4,334,944,395,884,263,394,998,479,380,953,946,928,42,628,157,697,364,376,145,419,785,69,627,420,21,679,575,421,799,523,828,792,307,390,634,944,850,689,658,957,421,765,3,915,122,246,28,279,413,94,997,51,402,898,96,355,290,228,418,173,554,532,935,400,398,316,14,996,289,656,617,143,730,665,268,684,25,524,593,498,698,804,72,801,856,682,485,849,218,88,645,118,420,481,758,17,890,855,793,313,420,789,589,324,815,927,865,853,138,296,164,851,558,603,661,176,824,67,492,578,127,694,32,109,496,724,430,513,503,510,317,297,512,918,993,470,797,627,18,30,929,253,757,770,270,227,679,242,496,293,828,771,61,193,332,893,894,304,722,539,221,953,607,796,133,916,998,67,416,178,41,346,408,935,120,986,615,304,511,674,229,198,656,940,13,779", +"3,756,897,676,809,779,907,606,872,702,104,959,343,404,927,253,745,676,587,715,309,711,34,225,576,926,117,203,623,83,381,491,687,211,953,399,269,567,107,185,670,217,737,261,124,796,51,643,772,897,739,743,915,766,972,356,395,297,49,613,286,590,66,847,233,282,629,156,955,302,334,185,649,75,854,868,588,902,228,793,624,218,88,432,372,859,443,945,827,578,196,503,771,793,904,412,937,106,61,21,177,482,508,436,233,233,977,362,997,689,817,959,300,700,322,303,362,31,489,379,4,331,494,171,598,474,2,574,253,925,832,825,876,893,402,453,782,603,92,301,84,853,17,511,720,774,930,164,65,388,678,721,281,790,31,408,7,360,550,766,925,830,295,850,217,158,708,784,888,410,952,881,491,479,673,184,151,801,295,509,294,279,658,378,887,356,190,172,699,703,396,706,680,887,727,672,728,155,79,135,693,392,520,63,608,971,640,613,460,71,588,919,590,667,147,597,413,706,51,566,661,554,139,736,520,543,825,477,475,898,830,530,485,438,139,699,864,623,11,346,685,74,969,926,987,704,461,409,126,606,558,88,512,150,501,162,546,277,893,380,206,750,232,779,808,266,991,280,580,956,953,658,213,308,508,207,866,685,837,694,769,718,949,285,583,246,174,101,620,718,232,574,123,965,582,762,463,176,916,941,23,553,773,516,945,978,262,946,614,395,606,41,844,449,396,916,107,337,95,523,452,18,87,716,807,758,375,451,822,232,522,430,657,463,940,615,193,453,556,549,506,942,847,764,426,401,987,689,145,921,972,175,544,664,978,67,227,712,363,48,476,969,135,112,167,964,197,154,477,430,734,662,957,128,527,744,889,522,575,690,203,869,335,188,478,703,926,878,229,698,41,120,88,767,751,973,658,333,620,327,918,487,971,566,936,660,152,158,996,904,691,708,413,349,947,665,419,535,184,760,801,575,697,395,757,638,689,6,389,255,831,924,38,71,855,994,607,296,221,510,25,125,586,822,308,383,293,26,225,928,7,321,613,390,289,990,656,635,854,67,417,944,184,649,911,858,407,521,336,463,41,644,822,991,954,610,886,470,332,153,367,127,271,946,781,886,604,793,829,560,421,556,466,584,520,171,58,745,187,419,354,106,356,865,233,850,289,774,951,669,192,935,9,226,686,448,159,795,852,662,976,140,42,535,147,6,762,603,737,374,481,209,50,274,370,826,254,245,1,411,611,26,485,906,467,565,425,799,548,866,235,505,765,627,673,284,481,928,769,123,305,234,18,59,964,269,176,866,170,2,69,359,847,754,948,946,249,203,301,196,484,35,215,976,198,467,127,64,470,244,489,660,513,175,419,408,905,677,219,553,646,82,913,369,787,667,81,949,27,508,399,256,144,161,890,647,225,393,14,499,812,967,703,67,668,481,980,17,672,690,567,687,438,731,93,938,235,811,768,427,280,82,209,588,364,822,199,302,750,342,666,898,116,392,526,941,128,765,966,367,175,843,695,399,97,359,130,263,950,579,424,442,332,727,460,295,387,755,40,776,593,899,51,761,859,482,172,48,766,466,771,996,34,781,540,301,631,200,298,275,121,290,337,269,543,575,101,747,551,191,417,529,179,651,847,155,72,126,653,839,602,223,687,621,157,528,696,817,617,812,555,744,151,529,106,388,920,712,216,633,562,324,853,476,509,6,882,282,266,418,515,714,394,521,344,369,364,314,883,44,382,924,789,143,353,471,603,132,326,737,370,342,636,0,675,707,408,295,385,701,16,945,480,891,207,766,525,473,992,418,466,920,298,680,902,58,474,912,126,153,478,561,521,4,629,422,634,737,570,737,898,124,249,579,100,166,730,590,385,672,552,865,818,274,308,457,652,423,926,211,846,889,535,834,982,426,847,635,381,992,973,853,834,561,317,104,810,898,159,42,718,809,566,687,270,503,553,955,629,458,447,786,447,575,195,236,168,464,281,129,749,629,251,947,604,225,391,905,92,393,178,623,768,385,779,456,850,858,6,733,603,928,934,369,547,865,202,589,527,660,302,401,576,624,54,74,524,764,170,561,609,946,279,192,91,846,269,517,286,383,351,975,714,759,479,124,309,747,97,889,341,884,211,447,65,763,114,785,40,837,11,390,707,35,35,884,593,110,139,61,78,185,443,602,285,831,177,948,650,133,567,88,392,204,162,416,429,556,927,60,543,371,188,352,890,303,547,378,656,217,554,169,734,298,708,973,632,742,29,36,65,907,960,429,313,6,853,349,738,900", +"523,840,618,831,359,683,24,133,913,850,40,754,245,77,847,425,614,741,789,433,294,152,459,70,256,31,479,267,448,191,581,967,766,989,417,430,133,696,192,615,665,798,740,526,287,215,598,665,789,376,599,428,277,435,132,888,621,643,68,561,946,87,36,574,548,296,332,69,653,345,294,773,845,47,166,261,627,66,253,948,710,613,512,492,1,244,846,928,511,81,325,668,657,691,580,482,683,872,31,876,67,35,90,494,903,468,246,730,54,653,758,593,676,573,106,848,869,985,690,636,794,611,873,865,704,922,658,83,240,570,981,360,877,23,750,96,734,543,383,454,510,189,462,906,613,356,510,348,652,387,13,35,341,559,415,122,591,977,801,410,446,150,907,399,55,530,774,930,790,200,586,211,276,528,34,486,707,979,902,488,538,42,742,193,954,843,642,675,787,93,163,276,386,746,266,890,450,742,823,443,728,244,820,353,697,237,360,376,846,346,495,330,989,66,601,919,916,610,825,418,937,577,606,273,394,100,537,8,499,501,977,255,965,142,785,227,409,945,582,250,491,218,705,803,637,701,528,726,730,282,793,883,564,762,304,504,757,98,173,896,980,771,560,148,668,799,602,341,475,458,701,98,326,820,812,904,72,176,309,284,843,148,577,884,122,518,277,911,204,765,735,986,153,176,627,185,798,780,915,466,783,306,519,938,288,326,416,549,779,819,539,477,337,26,486,543,647,878,88,129,125,696,266,565,924,392,932,944,874,343,438,288,979,447,357,769,905,72,632,320,905,653,180,668,228,339,59,27,659,752,518,360,980,73,359,729,170,451,311,33,3,823,256,947,278,602,509,56,206,175,732,568,14,336,883,364,600,532,374,299,449,624,807,785,831,273,391,371,856,94,727,948,58,312,513,7,168,914,80,277,160,7,434,444,906,238,612,664,651,509,476,141,745,10,266,842,932,892,800,742,234,296,871,923,659,964,408,830,233,591,661,978,453,153,462,122,942,680,653,363,317,412,869,618,688,278,859,232,803,896,740,935,787,713,886,990,470,493,973,536,881,407,53,326,964,750,88,389,954,277,254,287,519,685,384,300,35,777,263,615,738,540,242,789,29,981,196,884,340,91,387,711,81,72,618,932,826,537,931,344,405,69,964,199,554,234,647,829,338,264,489,682,95,601,692,253,761,827,241,715,470,848,791,620,976,653,555,476,534,924,884,312,960,299,83,737,776,449,441,383,642,189,577,918,619,457,223,994,685,260,873,649,536,692,741,239,808,368,247,452,927,479,5,548,942,919,754,721,600,261,356,994,281,23,229,835,234,372,781,170,932,409,868,218,765,584,761,35,619,912,977,66,637,728,934,398,749,660,527,914,653,454,893,729,266,40,957,505,257,33,125,302,975,676,239,529,467,293,793,823,574,261,428,115,638,781,872,161,667,546,936,70,214,373,941,564,927,860,94,282,296,773,741,206,96,511,20,578,488,85,924,684,902,386,514,4,82,172,750,265,255,143,670,303,935,656,329,446,38,695,441,834,147,229,518,712,875,327,855,201,101,700,281,49,521,625,292,812,480,91,793,142,527,333,532,315,979,742,17,578,715,170,133,632,585,981,398,565,72,640,374,96,842,308,814,422,101,846,595,690,844,385,966,515,142,776,129,83,519,289,794,502,632,217,55,67,863,819,137,803,270,596,513,37,174,243,765,399,163,655,136,836,130,142,355,35,269,847,486,840,845,970,928,316,188,165,69,149,743,790,375,488,107,675,0,784,560,336,845,376,656,301,870,540,63,541,380,540,267,975,388,263,374,346,979,183,122,768,668,286,176,536,764,60,894,766,97,278,298,391,296,349,946,134,359,837,805,97,209,206,138,603,245,919,165,482,467,735,781,504,590,771,454,488,777,490,522,894,911,73,627,984,820,906,399,884,993,865,269,811,585,441,955,565,165,954,589,860,588,745,999,964,428,763,822,376,725,760,840,622,995,59,478,536,368,656,259,447,203,948,726,690,45,251,21,609,470,7,619,5,886,307,952,283,720,988,67,426,616,771,776,90,798,447,803,802,240,375,142,384,60,882,1,897,205,931,259,675,671,570,602,959,829,245,331,526,782,621,888,399,363,50,665,652,167,499,480,485,127,706,823,761,584,264,315,695,927,517,177,626,273,503,316,382,222,809,250,461,355,549,797,196,64,811,698,4,484,790,949,695,129,803,545,574,86,442,168,469,954,311,139,205,553,363,369,309,674,816,786,505,879,593,506,380,557,787,708,833,139,428", +"275,748,760,92,276,555,35,710,713,807,914,481,609,729,290,538,298,169,210,860,957,580,159,877,992,484,587,766,160,949,179,223,3,540,788,76,706,267,837,362,465,331,391,801,505,4,617,817,354,106,367,629,192,492,438,186,450,599,4,100,223,132,96,645,536,280,666,986,686,726,476,721,53,748,272,327,584,485,362,14,253,371,351,1,330,351,875,543,980,823,159,553,565,243,51,997,840,507,180,618,875,605,385,131,793,911,755,1000,137,128,259,447,794,544,922,117,768,322,870,597,336,29,585,207,890,172,737,332,935,679,799,21,686,376,1000,544,472,597,236,198,499,37,936,982,493,207,647,118,901,413,734,158,827,956,164,397,530,878,837,819,856,38,787,535,472,732,327,719,26,252,374,427,723,470,45,787,479,320,957,807,613,498,635,259,585,335,420,871,413,381,990,834,628,249,800,583,424,935,728,64,467,182,717,96,930,108,99,687,753,101,225,748,879,832,297,984,20,209,747,718,147,731,799,509,86,309,11,320,130,418,353,334,378,665,301,169,170,473,637,435,720,765,493,845,92,144,401,225,434,17,293,33,313,750,547,576,476,72,264,334,250,985,187,68,69,855,528,182,27,101,681,750,907,119,331,105,358,390,719,26,39,612,728,937,435,910,611,584,360,206,608,961,390,464,909,634,487,534,938,238,430,295,72,263,586,87,729,575,201,594,199,170,414,62,870,416,584,61,393,141,592,442,933,702,677,974,396,532,808,360,864,767,839,206,336,27,867,379,985,577,549,664,73,293,114,495,602,317,324,682,117,729,644,168,461,462,610,18,964,291,340,613,540,302,635,187,649,564,555,417,261,238,494,920,945,814,746,625,290,650,856,359,106,980,263,521,88,638,342,819,302,573,617,707,370,155,743,760,648,423,946,512,573,209,504,69,449,754,506,100,733,817,421,657,91,948,773,526,97,274,583,306,682,532,529,651,52,368,587,21,684,347,83,610,95,757,682,887,78,734,24,254,24,709,74,306,93,587,898,750,259,720,765,505,779,920,584,616,694,797,305,692,705,45,40,858,228,968,650,415,718,220,933,540,540,813,20,747,361,321,561,585,113,593,426,151,256,210,30,592,669,820,94,203,130,385,332,45,85,126,662,583,443,746,730,803,116,355,57,183,970,91,253,667,21,337,649,338,150,380,211,33,831,683,512,918,457,110,491,987,528,233,67,361,997,222,511,943,550,222,31,111,604,415,222,599,92,794,68,373,409,598,347,463,743,60,180,755,124,229,804,704,402,531,812,109,511,268,613,88,463,549,718,590,716,455,296,574,526,892,849,887,298,416,91,950,998,62,514,224,138,202,210,268,599,470,423,680,951,877,282,879,439,854,509,918,997,716,263,565,646,568,883,935,111,179,280,120,652,481,668,709,553,894,118,446,710,185,686,129,798,7,793,256,662,404,936,756,441,316,462,227,558,918,455,749,193,716,349,798,60,696,825,871,991,866,411,382,927,367,99,55,554,387,60,406,585,928,777,444,281,587,586,633,63,701,69,172,217,327,476,874,464,484,522,65,552,125,753,823,984,657,191,401,309,258,780,910,204,534,503,333,936,631,317,97,427,360,199,915,965,653,360,837,301,66,505,287,922,409,579,273,288,170,172,885,961,863,873,581,887,808,762,510,950,328,653,242,833,718,167,888,546,867,454,224,755,206,478,996,818,904,678,710,766,831,925,581,530,749,931,869,61,321,138,679,616,74,549,642,68,690,735,707,784,0,401,946,634,265,46,321,584,544,728,218,697,478,363,437,881,777,458,322,982,75,65,679,667,287,352,332,96,990,793,349,823,175,855,210,145,43,773,436,417,251,290,861,46,840,211,876,329,704,302,85,884,83,350,652,376,406,796,150,169,758,422,72,399,633,118,352,429,997,799,469,518,125,417,531,866,408,501,925,54,291,248,409,692,653,802,896,107,524,555,352,365,200,144,75,48,189,410,263,734,250,516,69,546,446,186,187,466,598,751,40,25,260,297,820,522,24,956,835,859,791,488,765,362,166,151,492,382,737,587,487,777,408,750,600,79,41,741,850,401,456,451,421,624,434,717,660,496,951,593,693,112,171,105,688,790,917,785,211,212,877,428,412,338,176,49,347,835,657,441,385,100,888,787,788,93,566,425,886,536,697,877,245,34,981,284,639,817,288,599,876,770,247,975,191,598,493,555,618,319,242,431,542,890,287,23,728,750,627,494,704,645,978,967,630,162,197,780,361,203,934,41,673,74,264", +"968,901,943,846,533,710,537,763,304,79,983,890,918,585,718,733,792,701,827,994,279,406,796,882,258,676,876,994,229,946,105,994,777,985,630,785,65,522,729,43,359,895,764,364,981,731,332,701,655,321,849,915,16,415,642,308,123,957,372,817,307,23,581,329,68,158,526,65,778,307,862,2,347,863,948,665,231,810,918,139,456,530,520,131,967,447,726,267,997,318,984,225,891,518,378,958,472,106,784,63,625,889,520,611,146,664,385,793,356,898,498,57,350,939,831,503,858,440,247,838,286,850,927,327,924,702,693,834,966,632,305,785,335,848,926,863,824,300,945,82,262,238,718,565,726,7,951,123,680,586,322,543,674,460,196,944,459,952,800,880,841,485,111,561,158,280,171,661,479,58,196,191,947,503,82,524,432,671,746,734,350,184,817,242,40,466,917,478,220,287,18,207,902,718,973,954,324,154,831,642,590,610,258,451,254,626,851,697,143,693,436,666,16,677,324,767,92,185,884,741,928,49,653,818,26,441,333,312,440,36,348,360,727,944,949,885,475,853,295,893,279,674,687,226,927,752,19,982,354,564,339,689,313,384,129,386,827,898,144,801,201,877,738,911,331,762,533,515,176,872,620,246,842,708,210,420,730,434,120,867,273,414,728,462,452,538,479,470,113,191,766,226,167,309,661,568,625,280,188,653,981,441,323,567,440,486,353,11,607,223,175,122,743,423,427,56,554,718,11,108,389,913,998,615,485,971,895,433,95,896,661,427,570,547,843,988,46,800,518,620,208,778,939,237,315,461,810,922,123,690,317,891,190,236,300,322,662,510,977,627,49,43,315,877,932,804,339,912,953,813,751,583,245,791,65,894,193,812,663,574,508,98,176,944,519,195,912,472,564,611,5,401,135,33,933,919,49,177,528,819,782,236,925,839,418,944,720,223,207,264,525,124,768,121,870,837,838,371,344,694,836,729,733,463,340,931,449,313,814,592,215,599,375,348,392,682,395,307,75,248,748,139,444,436,47,752,245,47,252,650,583,574,362,354,270,174,111,989,821,533,313,337,786,481,90,434,88,953,489,600,986,510,810,35,77,926,113,249,33,698,900,71,920,936,569,524,219,651,815,652,105,412,154,392,928,935,474,935,64,818,356,250,583,341,146,552,66,475,859,378,22,591,131,506,479,69,902,558,500,948,874,71,120,442,983,351,531,190,241,728,208,187,39,28,397,500,141,432,517,227,105,556,866,66,960,537,134,613,628,191,472,195,488,910,755,394,841,724,428,138,738,507,565,432,627,757,921,139,199,221,12,375,965,733,781,135,443,955,613,399,900,39,119,905,652,382,371,243,943,83,634,818,94,857,432,356,29,963,475,865,20,771,511,942,231,152,693,361,687,870,547,253,221,605,756,223,63,55,849,902,657,307,627,664,565,539,33,81,341,400,106,267,387,185,124,303,350,705,326,529,813,920,269,551,851,744,357,768,941,385,478,344,971,721,621,170,468,724,607,250,282,828,915,94,533,551,621,847,399,384,364,773,362,814,63,935,702,124,615,61,834,898,738,419,262,729,855,62,420,262,560,865,591,507,134,922,132,694,452,575,259,69,929,172,308,782,652,542,351,879,424,951,898,229,774,895,520,798,151,161,983,914,49,602,306,924,924,671,370,634,707,354,279,855,826,248,115,178,527,331,189,225,236,293,318,910,265,755,434,11,49,970,938,465,27,114,629,942,494,259,75,375,855,544,352,982,335,117,246,66,905,752,823,408,560,401,0,589,411,925,807,370,702,826,46,561,277,157,348,978,472,517,893,906,917,588,706,953,581,786,623,53,235,414,543,430,239,582,947,969,138,407,513,463,51,671,482,379,189,972,563,638,612,59,588,500,451,841,859,328,478,594,271,618,970,714,409,775,259,424,151,569,154,883,16,312,941,397,348,890,693,395,419,963,554,880,483,396,486,300,565,626,420,774,931,500,719,479,223,200,522,133,493,553,105,966,130,625,125,751,304,754,193,826,912,213,122,117,18,796,754,648,358,468,360,223,335,578,785,734,741,35,427,249,140,238,245,819,454,675,365,718,833,40,906,657,170,136,956,160,564,47,366,304,682,816,397,497,319,971,342,314,147,388,699,839,142,617,69,457,458,532,150,315,913,191,60,294,378,831,846,234,714,371,64,511,989,517,534,723,353,166,471,492,670,217,104,127,460,446,620,107,773,773,318,285,964,45,335,558,680,152,490,589,972,916,505,59,891,325,885,309,108,281,901,34,177,462,880,501", +"342,385,24,775,921,68,311,302,195,891,394,916,317,36,777,775,616,869,471,143,714,149,499,172,448,432,554,547,898,365,101,909,711,379,446,223,652,254,121,635,233,585,190,228,928,332,684,928,491,985,380,242,900,384,590,234,242,961,476,81,183,36,204,593,352,428,951,664,352,481,648,79,866,929,95,500,836,369,399,665,669,232,259,664,424,834,561,913,910,490,287,710,366,142,266,665,409,833,725,102,767,701,569,257,863,98,144,656,997,379,779,207,144,226,845,768,728,911,941,134,420,296,882,348,838,661,664,427,316,384,6,433,531,298,39,722,422,324,846,544,666,881,941,657,781,563,144,599,231,491,964,483,46,161,164,71,250,255,94,525,555,16,95,753,142,689,898,331,857,681,773,29,651,417,74,957,760,905,790,582,976,112,97,125,669,934,223,612,858,92,87,74,729,150,591,511,278,128,598,384,111,155,908,957,181,790,322,565,227,512,925,800,403,267,572,981,435,122,929,283,573,205,818,185,698,85,640,368,222,636,384,267,953,73,643,304,39,319,715,975,486,474,155,957,857,247,168,14,859,317,683,199,318,464,465,304,907,660,243,888,15,487,661,584,334,25,886,912,754,685,477,32,546,912,878,489,504,197,637,530,885,72,824,297,393,313,476,712,739,190,393,255,248,438,240,184,70,316,324,262,293,464,656,943,180,742,477,841,792,902,495,468,546,273,200,823,629,200,891,130,450,488,839,628,789,267,280,78,423,765,934,532,8,265,829,995,396,34,710,783,670,604,742,332,914,595,172,191,473,809,624,527,831,521,47,232,117,452,223,705,37,124,877,183,434,380,846,309,187,101,614,411,352,727,231,377,834,955,371,563,794,650,576,531,204,456,106,187,582,278,498,185,802,539,484,466,4,384,409,883,965,525,767,20,588,15,697,14,67,29,276,220,664,189,423,404,844,267,773,362,182,321,611,171,325,5,878,574,210,39,216,728,740,880,894,862,556,333,509,950,853,465,254,77,6,494,826,376,63,454,796,463,287,611,612,350,375,619,798,902,479,239,34,383,752,170,842,924,653,970,383,340,454,92,247,802,41,48,574,663,726,256,258,706,503,127,812,652,149,904,635,870,844,706,9,492,703,572,613,964,143,850,606,815,514,251,886,304,505,378,892,223,639,924,69,733,295,511,200,340,281,312,773,422,128,748,961,683,433,548,926,447,485,867,26,262,520,970,591,172,510,672,564,607,326,190,438,379,365,122,46,925,325,532,470,610,12,538,359,732,923,547,359,993,268,178,793,776,485,828,29,864,217,265,389,873,844,137,309,173,878,76,766,657,436,131,433,846,444,418,646,654,680,908,567,754,556,786,915,616,107,701,207,809,42,383,344,590,756,752,628,883,34,804,583,143,858,90,181,679,530,391,501,257,864,273,545,743,29,719,702,230,111,266,461,459,3,491,959,306,843,257,936,523,490,25,935,621,839,145,291,700,953,488,455,19,530,652,466,395,348,462,97,805,793,3,871,691,5,56,803,184,648,280,975,257,278,882,274,211,338,763,562,299,99,198,430,788,302,599,780,985,401,500,77,536,532,911,489,144,939,275,294,664,915,822,91,878,814,503,133,726,226,989,964,149,830,294,735,780,435,394,349,913,332,379,600,727,893,715,350,48,251,256,708,211,178,226,171,586,693,511,411,144,957,397,198,495,21,343,461,243,177,899,943,625,40,661,530,651,71,178,368,780,669,311,520,84,592,35,151,784,947,295,336,946,589,0,881,276,232,839,80,618,310,64,357,204,468,499,81,536,197,404,246,642,598,364,448,40,168,706,45,770,709,150,269,18,154,798,271,966,92,502,382,222,989,148,373,417,513,507,290,644,993,688,646,521,362,501,930,124,964,369,471,790,226,522,786,476,974,999,88,453,603,556,680,964,499,326,137,334,486,563,857,707,127,765,750,354,156,261,175,541,157,695,507,22,825,289,332,335,144,361,161,347,614,82,468,553,869,372,315,927,29,723,135,25,338,782,239,11,254,734,127,877,387,228,523,202,970,698,774,863,394,31,560,121,151,929,289,223,543,491,704,886,945,49,478,236,664,177,982,546,515,920,340,930,152,463,217,546,763,11,415,350,246,649,341,127,97,246,108,808,194,9,526,931,718,535,364,873,951,297,162,724,994,266,427,887,375,775,50,683,6,6,473,694,280,800,110,929,293,509,398,110,538,722,114,263,827,28,956,59,985,349,790,734,637,418,201,377,493,921,360,141,22,655,540,260", +"759,514,834,142,150,186,783,548,235,683,939,648,355,546,714,857,755,274,946,741,886,731,448,942,66,961,219,699,343,756,270,303,382,248,319,305,693,874,584,150,895,877,75,229,29,14,736,981,574,2,786,397,473,303,61,6,107,465,134,34,387,314,28,503,445,210,348,848,58,979,312,544,322,146,542,606,426,513,510,799,804,243,409,666,80,615,483,287,815,183,142,758,891,932,775,749,79,374,333,799,222,535,802,234,903,152,836,334,948,334,326,520,122,604,376,253,937,360,140,269,467,894,446,673,887,569,156,241,675,338,671,38,365,92,640,807,706,899,419,197,860,785,691,533,583,652,595,359,549,784,829,717,223,908,317,543,372,315,613,767,459,894,813,628,265,771,257,496,808,530,7,970,893,479,257,446,986,851,7,700,863,563,405,982,521,874,794,699,575,825,130,923,352,659,843,711,204,685,48,116,313,189,59,222,35,213,371,49,183,488,336,343,852,636,161,221,623,719,887,207,987,426,510,397,765,59,651,938,597,303,867,278,516,383,825,665,470,935,457,240,80,300,170,992,744,988,836,511,960,953,653,322,421,28,6,693,593,974,613,261,87,996,1,175,124,752,46,634,747,209,523,319,823,17,909,974,773,345,283,285,60,839,334,393,214,207,963,430,327,6,89,291,161,563,265,538,264,759,461,66,402,371,53,598,603,421,400,830,857,546,240,339,565,812,889,934,912,328,110,158,231,590,482,415,94,189,854,781,634,101,216,585,706,966,88,453,881,341,430,702,151,738,313,284,517,344,795,166,850,265,235,768,290,262,652,733,684,602,666,21,263,351,712,879,105,612,266,373,792,902,586,407,802,541,401,873,105,566,819,463,709,651,365,490,451,449,2,688,235,321,611,95,359,331,443,667,264,170,117,122,659,217,905,727,655,685,992,180,204,114,367,468,136,291,976,200,714,513,888,696,934,114,723,609,673,369,378,26,873,764,775,637,908,348,107,805,962,340,565,571,718,214,720,543,222,54,835,12,3,725,379,428,508,599,566,705,863,258,806,284,935,783,250,617,428,430,362,935,414,536,641,481,172,725,809,967,494,146,102,291,435,309,727,777,396,832,743,711,955,591,949,486,612,823,466,192,487,949,566,404,110,461,716,164,140,630,421,984,491,921,235,691,166,44,657,143,215,473,92,802,877,13,862,190,172,889,380,819,588,615,262,972,647,464,781,334,423,885,995,915,489,307,590,105,457,562,814,790,187,431,988,608,916,92,425,240,220,405,85,287,664,875,248,573,538,991,523,491,843,404,638,866,676,690,911,988,24,214,761,864,343,705,692,235,928,410,971,760,528,644,174,136,32,551,429,242,806,662,125,867,43,260,61,556,446,343,765,884,251,91,171,715,498,770,992,367,671,59,935,233,590,509,890,323,37,811,369,488,18,129,26,407,840,968,848,988,611,297,690,780,931,141,608,383,141,763,894,68,395,115,419,374,213,391,837,603,176,904,365,732,119,88,693,605,860,953,419,363,955,134,40,455,766,515,657,142,345,662,666,294,440,222,58,961,93,861,494,19,145,23,984,296,102,434,844,150,155,773,754,300,670,944,516,725,684,174,666,539,414,796,939,90,9,356,635,658,988,550,368,793,810,847,882,568,811,250,899,166,915,924,446,544,594,225,878,861,410,983,945,465,419,792,188,647,937,408,833,861,597,2,874,849,280,833,785,152,552,6,371,238,663,832,178,356,155,225,963,435,669,642,607,609,627,385,845,634,411,881,0,411,475,716,354,563,855,856,496,999,949,672,22,714,265,530,880,321,792,44,435,922,436,620,2,291,501,58,710,975,13,463,557,974,897,282,648,4,163,67,774,343,629,232,903,322,619,915,371,677,695,395,667,18,720,422,106,582,194,501,293,321,694,220,789,115,633,590,265,830,527,758,585,169,345,594,162,231,49,132,284,165,528,994,78,756,781,650,997,531,171,771,579,548,88,418,723,808,207,640,769,83,227,704,511,839,326,382,548,482,815,539,863,905,612,848,652,686,474,995,728,459,147,556,754,12,657,705,950,201,453,247,815,3,245,466,637,261,999,98,571,600,212,668,503,950,852,215,575,769,796,268,662,733,794,603,546,484,904,797,897,854,501,440,535,286,479,763,352,980,156,553,548,654,256,551,83,803,330,301,11,148,317,185,261,657,272,765,769,820,542,350,806,164,490,88,604,241,166,350,309,633,206,110,128,105,35,402,473,756,76,359,620,512,282,336,935,488,527,276,446,813", +"765,720,426,839,496,640,799,843,708,448,358,678,222,154,154,98,650,120,997,320,892,308,354,934,102,205,607,702,94,599,582,833,671,3,555,893,438,612,84,266,22,818,266,104,949,895,970,421,179,376,229,955,709,80,729,93,139,710,470,35,571,800,582,899,908,393,152,540,448,718,831,918,85,541,165,491,60,24,841,487,859,276,944,929,256,685,466,958,895,954,58,410,959,748,214,618,471,281,676,976,122,283,832,27,633,725,22,770,102,446,581,30,113,424,347,485,910,157,290,770,88,92,269,756,766,179,443,222,643,606,860,163,931,808,977,666,395,700,67,553,122,770,723,337,90,756,121,439,948,796,853,744,156,183,991,62,999,24,325,428,58,99,919,774,582,43,634,953,516,599,984,23,440,745,465,136,44,307,94,981,553,977,424,900,520,191,539,881,998,401,764,203,15,385,74,603,119,271,500,153,113,232,403,291,876,29,906,813,759,385,638,809,547,541,786,920,200,616,461,185,877,396,675,749,585,287,312,50,408,69,890,886,898,824,308,343,217,739,307,499,913,184,390,495,658,245,752,253,808,477,480,496,342,110,534,362,811,279,581,810,592,668,654,711,808,673,299,154,605,77,382,4,233,862,114,168,919,76,232,151,332,940,928,372,743,499,583,488,9,319,500,545,866,234,153,225,191,424,427,491,890,536,990,49,923,907,684,336,682,712,238,374,332,959,633,476,608,707,647,743,246,136,659,312,39,473,183,747,995,81,994,301,17,583,63,459,252,558,179,280,862,213,158,235,938,815,468,653,996,593,783,830,252,263,277,607,381,439,887,481,546,844,115,964,344,301,865,304,429,792,391,129,704,88,733,542,809,427,834,446,661,773,395,650,530,483,528,49,112,99,566,122,461,33,309,367,291,448,642,465,693,214,680,400,784,249,97,312,87,592,708,63,163,883,595,810,597,121,235,712,639,323,884,615,203,298,262,757,244,685,912,818,23,304,229,788,987,182,121,136,863,805,424,962,240,353,382,471,242,534,576,87,286,860,917,89,546,772,186,785,689,48,358,641,892,698,140,327,936,814,26,731,896,960,280,254,330,859,992,915,85,47,514,527,800,687,52,620,960,113,970,833,664,445,808,937,535,123,74,79,895,439,360,320,995,139,818,607,565,478,481,94,39,506,880,746,243,266,783,606,115,830,64,659,714,869,832,445,349,908,233,869,990,279,526,793,551,178,332,714,126,384,645,52,807,882,559,136,494,257,192,164,994,885,850,697,144,840,411,480,145,40,402,567,277,370,765,61,34,707,953,872,416,265,827,933,664,737,924,68,91,806,35,536,505,28,151,193,14,98,284,889,131,588,512,398,680,278,242,331,497,814,610,373,140,632,717,163,325,740,735,529,798,857,284,264,523,104,192,196,184,311,933,370,447,478,158,725,440,527,107,954,693,688,445,807,711,253,162,48,771,398,539,868,730,301,854,277,572,167,375,51,44,846,506,629,433,136,619,668,521,930,225,322,273,496,451,419,748,844,344,329,913,429,720,952,169,598,295,837,617,823,169,242,110,59,445,685,354,108,396,585,727,342,49,341,394,233,324,151,938,286,897,46,217,453,353,66,418,150,811,832,966,88,760,522,214,953,239,398,656,870,483,781,158,949,586,998,908,548,45,553,903,455,400,120,780,583,834,79,908,675,88,683,102,850,437,579,740,268,280,532,722,379,900,516,742,408,418,215,278,227,879,790,570,85,198,844,724,884,392,972,677,701,376,265,925,276,411,0,509,899,855,439,140,882,829,266,310,397,280,183,994,996,338,878,531,256,172,910,847,163,696,19,685,710,507,607,600,314,45,722,737,114,935,753,705,5,637,68,981,245,988,922,134,637,230,804,712,182,708,149,545,384,331,370,402,946,698,44,451,350,763,744,126,401,927,735,120,742,672,570,411,24,220,503,886,569,838,326,117,768,503,465,930,986,750,437,969,256,384,101,17,377,307,188,523,817,678,175,818,671,632,309,115,977,489,778,733,639,437,468,535,11,542,922,468,721,838,757,277,38,30,523,338,521,601,907,312,726,857,364,319,313,513,617,845,97,110,212,354,795,383,81,485,209,841,963,500,569,206,440,660,2,147,765,278,959,284,63,525,356,127,140,264,898,101,563,215,83,414,394,816,46,716,845,500,365,604,725,969,526,407,634,352,592,973,932,13,594,106,137,390,116,824,773,343,125,865,645,760,665,963,518,279,861,316,22,602,669,631,70,934,138,704,76,634,706,530,872", +"907,113,894,268,606,200,657,55,176,559,665,152,572,983,628,12,655,37,228,625,9,71,566,288,100,547,348,266,474,479,995,868,344,824,31,44,44,228,444,398,248,663,720,132,835,604,699,44,870,167,80,495,368,401,837,456,639,495,423,469,996,290,538,149,234,996,505,530,591,508,17,436,233,265,446,20,131,782,318,708,637,501,928,527,83,572,179,860,385,565,84,301,615,100,712,425,356,115,611,206,739,683,887,505,298,713,14,394,341,859,616,756,801,100,855,265,351,950,32,307,303,157,195,458,340,167,336,513,949,809,655,656,770,447,208,166,579,682,333,98,750,47,55,625,156,237,610,263,902,178,103,113,170,412,374,292,505,306,215,390,529,800,217,668,531,513,459,354,130,578,198,688,160,721,724,86,925,425,53,673,679,201,667,952,289,939,168,877,605,711,314,292,578,403,572,412,642,797,356,954,810,409,41,463,238,730,681,146,247,663,183,642,738,422,119,938,308,852,42,150,71,213,988,159,303,867,297,12,741,877,416,37,54,987,384,94,131,443,941,216,730,663,548,270,181,91,27,408,951,978,11,928,1,200,221,650,814,297,414,746,898,919,151,969,347,799,877,423,579,861,977,690,724,679,384,378,683,846,151,9,999,64,772,673,585,787,959,536,221,655,690,563,846,183,362,272,343,661,813,110,845,790,511,638,535,35,911,625,720,604,31,233,810,805,489,568,227,129,649,185,858,355,925,624,322,440,153,734,1,441,279,277,951,520,346,492,784,949,23,640,957,944,392,388,960,107,419,987,500,818,55,653,290,881,5,963,447,727,871,65,65,868,358,55,940,423,796,995,755,850,499,659,109,448,968,64,654,429,397,992,378,467,771,246,28,694,874,546,100,262,900,450,355,140,7,252,693,641,92,236,564,68,76,808,786,710,145,807,543,217,4,117,322,427,819,234,100,280,986,132,76,632,685,609,808,329,73,943,350,926,485,729,475,764,287,356,593,580,354,679,7,642,542,867,409,844,518,952,665,820,348,658,879,269,818,277,980,459,504,602,748,369,444,908,350,577,820,430,359,331,2,321,583,188,507,419,74,511,978,172,672,765,647,154,604,104,264,349,432,798,834,504,997,820,704,942,717,739,187,152,236,814,62,349,757,179,973,289,362,670,376,592,309,857,183,632,275,75,173,435,387,351,919,766,233,268,582,475,440,827,522,730,623,15,331,772,353,207,482,314,512,723,42,737,546,973,544,37,455,246,468,539,830,276,765,806,911,652,24,729,599,862,978,555,980,335,11,136,302,988,359,649,64,544,282,34,451,252,33,665,700,233,507,648,780,430,2,22,301,665,703,686,318,434,490,589,169,494,909,487,476,595,231,764,915,513,546,199,53,62,595,726,518,2,874,521,652,383,616,622,152,167,798,277,461,858,545,761,221,921,100,901,677,905,576,695,650,407,899,684,217,446,988,714,208,601,604,561,924,132,796,582,224,674,11,613,583,552,783,670,37,878,952,36,213,855,272,930,578,927,139,571,379,289,863,559,749,943,797,30,140,742,29,85,4,855,751,673,766,731,60,836,419,154,307,322,408,507,811,246,29,256,360,265,478,198,916,293,476,449,198,895,237,191,97,560,339,469,639,460,436,48,920,526,35,675,735,218,805,135,895,358,998,719,438,371,31,718,683,699,580,307,829,957,653,503,266,624,885,93,607,830,700,783,627,518,37,114,589,313,555,182,903,523,366,758,31,37,260,164,568,418,332,16,656,46,807,232,475,509,0,170,397,926,292,766,59,81,706,440,38,598,460,705,773,859,637,211,451,975,643,562,609,509,356,837,344,60,154,727,891,229,582,769,889,350,492,204,377,42,752,95,639,8,699,952,165,466,395,547,975,646,20,4,78,16,829,588,887,231,809,137,82,660,282,817,745,254,930,378,455,546,220,239,961,860,142,920,7,443,675,428,940,809,976,858,202,637,380,970,856,826,136,162,546,449,4,113,929,710,822,358,776,488,861,392,682,12,851,89,955,634,847,183,311,136,987,410,469,233,254,729,759,708,113,890,87,758,974,706,682,989,553,657,398,918,776,590,372,619,874,610,746,659,110,799,607,635,194,734,627,839,285,360,21,341,880,998,913,460,663,594,141,441,227,605,601,761,563,622,187,439,601,420,500,764,118,907,514,346,340,488,259,482,928,604,115,210,691,160,743,986,479,806,797,178,977,670,852,411,787,78,187,670,204,92,305,382,454,949,337,461,919,8,107,684,729,428,991,796", +"624,972,126,538,147,301,11,568,495,195,474,116,437,58,885,11,430,958,312,567,911,206,103,446,864,314,761,424,734,931,180,381,845,731,517,840,232,775,41,405,237,727,258,680,5,178,867,256,70,212,204,533,538,842,664,444,658,959,280,819,448,296,120,130,244,127,166,413,923,601,408,786,165,442,715,948,561,139,851,908,409,91,597,136,28,661,894,824,345,319,155,785,804,161,599,669,449,697,399,189,505,668,516,137,901,765,433,767,275,289,17,210,89,928,455,205,696,960,720,162,117,718,683,769,524,363,143,559,48,519,991,378,974,83,631,380,567,643,718,4,74,645,86,692,860,487,609,987,143,508,851,86,685,158,908,491,744,618,533,230,309,215,715,761,556,268,891,302,870,255,237,200,95,432,814,639,113,966,181,783,109,905,829,798,447,715,606,564,559,355,362,444,704,501,737,876,315,155,683,808,574,186,460,517,753,43,128,463,706,392,762,181,568,106,659,70,556,708,468,518,323,262,914,804,687,51,333,987,501,273,681,855,535,650,892,666,114,885,218,137,86,26,387,638,525,245,892,138,206,76,709,583,224,940,235,584,750,65,134,580,668,716,244,263,201,802,906,94,848,91,568,477,788,496,500,584,241,694,234,746,266,806,987,468,82,265,797,995,8,803,551,823,519,643,558,32,962,934,970,670,675,514,307,913,876,155,128,501,262,522,755,39,310,962,106,167,63,608,334,719,54,979,118,498,60,213,419,521,841,664,161,828,642,94,779,3,246,958,694,137,547,52,549,614,104,895,262,651,294,656,898,152,467,58,219,628,665,137,447,389,296,899,392,247,635,970,428,236,296,807,147,690,581,289,674,31,426,280,683,70,317,762,824,758,865,737,981,972,787,380,794,314,750,152,339,473,906,384,931,192,904,270,245,927,594,404,363,950,15,394,686,760,687,137,656,503,836,336,206,817,348,208,397,425,232,228,269,115,5,338,857,160,377,636,50,424,730,757,221,582,640,562,986,931,421,777,509,179,252,617,984,894,709,457,495,642,798,473,253,231,115,807,9,173,793,121,576,163,539,153,122,723,291,926,154,672,891,128,306,278,482,120,611,27,116,804,929,168,243,751,70,546,257,938,289,638,136,744,911,183,327,182,644,607,114,427,596,774,592,330,703,556,464,697,75,580,205,18,184,459,108,797,735,736,641,3,301,92,342,754,126,223,520,897,509,879,278,277,73,694,953,5,931,294,36,792,736,483,560,956,26,933,371,252,609,359,327,154,632,550,704,380,894,693,127,144,580,444,478,849,251,896,761,630,673,831,591,782,430,573,916,720,186,635,226,56,309,277,368,278,959,566,229,973,265,311,53,650,112,177,10,857,678,184,441,298,917,955,908,295,429,197,338,734,845,852,692,544,444,326,174,691,125,256,265,240,835,32,692,49,358,236,735,381,928,40,479,379,721,66,958,966,681,973,955,991,874,277,85,523,445,190,632,393,790,902,277,513,226,479,713,221,752,85,799,861,776,953,324,748,221,894,400,278,504,891,383,223,21,771,972,862,552,497,812,365,278,868,215,939,387,205,711,484,774,509,146,747,254,41,534,780,964,874,510,172,602,564,820,54,53,499,276,658,215,238,29,345,349,998,48,760,458,700,535,78,872,632,433,587,843,455,89,138,549,830,500,498,209,818,289,201,425,851,157,704,534,371,388,228,287,265,120,925,590,871,277,748,290,510,424,470,873,4,30,5,91,267,916,355,182,99,86,945,301,321,370,839,716,899,170,0,781,177,418,404,167,543,607,136,121,548,119,395,578,343,632,667,101,259,495,103,194,568,52,95,152,98,54,940,825,891,182,518,713,823,553,280,342,119,105,800,844,657,854,44,108,663,143,855,261,387,978,159,399,331,86,651,802,561,167,60,626,690,349,668,283,482,307,484,536,756,232,334,645,463,567,647,616,355,524,97,713,327,993,522,843,710,144,66,64,670,956,370,373,409,329,820,210,163,23,976,894,585,188,42,427,730,240,324,245,984,660,158,966,204,836,399,638,368,943,907,200,784,198,538,685,394,944,95,211,195,95,451,509,472,779,866,876,570,613,604,753,652,983,145,748,938,833,787,715,50,973,344,182,59,280,458,767,325,281,726,954,394,153,608,155,723,268,145,108,786,203,51,203,110,277,888,172,499,334,815,624,898,203,822,749,203,938,470,378,683,798,520,764,554,117,297,10,696,375,298,207,924,835,515,731,781,539,729,394,44,672,299,427,414,265,898,61,543", +"468,196,413,803,111,599,792,560,552,184,512,432,188,329,360,688,514,970,12,574,423,995,986,848,696,171,396,206,916,682,44,336,529,685,717,324,30,364,439,371,226,719,916,833,16,401,428,369,952,317,341,853,205,306,552,187,609,415,610,953,183,271,322,173,906,336,310,955,453,53,962,608,855,503,442,670,520,402,304,672,360,256,116,988,535,250,909,46,216,468,342,236,243,845,2,405,659,952,414,663,650,388,124,592,465,437,788,449,793,814,642,83,111,781,434,62,209,981,920,263,985,617,698,908,542,402,502,871,307,69,774,110,929,662,840,45,856,288,692,278,591,405,210,595,222,91,22,341,763,806,539,604,8,371,103,295,737,343,843,577,141,273,612,270,691,71,584,473,500,611,857,28,884,744,773,818,28,853,503,174,869,597,861,155,292,464,872,241,484,530,142,777,231,737,748,820,67,364,37,16,343,273,6,979,2,25,971,52,140,431,965,724,813,152,252,202,31,191,780,186,12,436,442,919,969,871,459,438,366,734,485,252,662,538,775,109,721,66,233,318,602,764,811,66,816,62,968,608,316,134,596,547,352,987,24,821,943,173,317,946,984,69,319,878,93,547,964,285,657,735,82,33,45,741,697,864,143,19,722,458,265,110,826,587,462,70,540,45,102,321,333,510,208,935,190,739,759,73,371,443,972,216,811,41,739,760,703,905,293,817,222,962,95,713,52,636,741,539,83,386,210,705,896,535,880,168,7,518,410,328,971,761,729,779,92,204,862,82,158,647,744,874,415,560,551,980,879,352,502,583,738,124,281,109,776,270,362,860,735,783,297,351,54,95,590,120,135,715,117,618,16,641,891,702,879,245,968,497,948,164,469,657,457,19,817,453,865,272,750,194,755,515,972,949,683,452,206,432,85,852,547,168,996,471,317,755,967,651,194,254,364,762,674,918,533,811,836,91,660,729,602,860,254,569,948,251,197,338,787,922,760,760,539,969,797,728,1,6,484,310,631,348,985,148,521,185,939,770,886,215,141,707,633,497,113,216,135,70,194,206,940,927,837,940,580,513,880,303,729,245,433,606,488,806,607,873,811,587,814,80,913,610,974,42,513,887,346,288,806,495,614,838,46,636,694,351,175,77,739,955,645,806,865,68,120,617,330,177,9,741,615,906,692,295,779,579,418,498,212,719,186,772,753,448,48,706,541,654,486,193,50,476,639,200,584,758,994,47,240,419,100,235,395,974,962,168,323,245,423,461,603,749,124,398,632,82,538,401,330,202,147,482,95,595,642,6,372,372,971,789,672,310,959,923,803,213,334,886,252,380,218,318,635,157,329,202,110,323,873,991,313,568,758,44,581,271,554,278,992,933,870,717,989,919,953,134,92,794,365,266,985,90,239,730,359,823,860,387,759,340,93,562,533,867,438,434,531,429,339,800,7,481,625,64,849,220,280,757,767,700,184,454,409,194,336,876,605,294,827,696,449,805,84,480,754,867,902,268,403,420,11,788,999,777,64,940,189,306,305,446,651,815,376,435,579,488,49,843,738,409,422,281,318,568,104,416,449,79,715,823,691,405,158,949,819,345,906,537,81,747,325,972,442,777,655,892,536,701,468,976,408,742,676,306,895,462,236,176,823,579,946,47,440,440,442,431,130,23,186,930,41,958,955,251,931,712,724,633,374,920,263,529,990,278,838,125,232,323,83,116,483,703,938,923,366,237,696,158,265,438,297,671,641,980,197,494,388,853,953,317,433,494,767,480,870,584,702,80,354,855,397,781,0,955,551,720,549,171,844,769,199,758,266,485,139,69,909,399,215,228,167,8,529,467,819,469,389,480,257,449,731,789,721,837,966,861,919,169,246,879,434,474,144,106,636,112,118,243,989,142,484,987,112,390,431,29,92,138,386,119,329,361,963,273,121,79,136,525,600,278,447,420,342,882,971,658,540,588,442,272,98,601,524,391,807,61,843,149,841,274,318,78,917,712,61,794,576,419,713,170,509,556,614,339,819,367,66,141,260,159,725,728,632,282,263,349,528,216,976,929,30,442,275,606,455,246,51,376,22,964,843,596,630,767,429,325,525,122,730,519,31,408,514,124,316,573,45,138,700,730,102,460,421,21,846,498,228,619,81,885,926,21,251,265,539,904,649,159,849,9,244,493,468,963,113,271,257,66,927,344,296,936,227,684,178,507,800,444,108,179,106,393,129,984,58,464,530,536,698,717,479,846,781,46,579,579,59,457,875,899,77,788,947,967,937,767,940,832,115,855", +"674,509,484,695,541,320,52,640,809,424,946,497,745,522,705,482,388,195,699,55,489,956,925,314,336,109,963,263,155,667,249,230,443,407,894,399,483,101,236,669,101,386,395,457,598,389,175,741,32,28,820,322,473,595,304,10,414,176,255,62,411,316,884,109,948,805,167,705,237,353,683,180,770,355,740,236,315,336,965,564,63,740,297,16,140,282,450,672,942,951,998,601,627,708,554,753,421,147,514,673,86,252,645,814,693,729,100,291,604,404,603,573,623,141,473,261,445,714,367,466,717,975,802,226,755,28,18,351,853,844,695,264,976,752,318,952,40,368,543,601,301,644,794,450,829,470,961,777,207,48,498,490,517,774,222,606,981,535,383,597,895,983,995,682,979,514,831,124,103,56,823,402,921,880,254,898,456,532,614,530,308,306,423,9,137,200,501,538,692,976,104,242,968,548,603,141,482,979,998,817,753,292,48,201,512,136,769,189,183,846,993,927,124,866,82,92,171,470,27,605,277,717,891,62,786,946,624,241,342,13,468,890,457,33,126,507,906,847,361,548,133,566,502,659,816,712,841,378,188,26,420,112,966,134,616,555,43,597,780,207,213,378,498,59,681,943,220,227,510,517,892,891,548,427,425,78,698,966,61,807,270,730,55,186,407,884,358,968,826,468,137,934,374,280,193,59,102,204,854,431,452,302,685,352,100,846,862,372,244,856,156,956,822,155,909,802,328,698,811,861,193,864,218,186,70,290,739,234,178,63,987,207,380,930,408,627,682,255,992,155,787,309,252,184,373,514,34,684,987,21,62,691,622,883,138,551,816,41,838,98,169,925,887,480,81,693,125,894,372,65,719,446,17,655,468,913,206,382,381,762,778,942,468,791,869,351,949,101,17,722,149,439,99,14,735,903,112,523,268,435,80,134,743,521,844,865,663,338,156,141,228,740,993,877,251,782,610,124,47,362,128,871,905,520,801,761,459,296,876,261,905,959,373,532,458,756,738,363,603,298,909,301,126,112,72,699,924,172,417,944,608,160,205,27,984,970,361,800,140,360,303,18,64,26,418,463,185,422,512,965,663,245,253,785,210,198,643,132,477,200,616,764,823,805,789,445,212,647,922,910,324,589,23,724,693,70,234,248,872,201,532,42,767,17,502,894,815,13,227,114,558,135,755,459,373,530,999,168,367,428,406,964,97,794,346,185,397,190,884,800,491,368,561,248,205,519,527,172,229,834,706,942,444,321,415,64,656,327,222,410,982,722,616,759,84,543,54,163,817,572,267,588,467,253,391,996,205,820,33,251,950,525,733,395,980,226,273,747,832,15,370,948,909,740,300,556,852,385,303,962,831,187,501,925,622,83,402,466,604,479,354,970,583,400,504,217,179,232,914,470,206,833,805,666,401,776,213,712,633,747,730,627,948,386,975,952,886,711,851,121,869,595,810,947,603,387,469,947,902,601,162,582,874,74,110,349,900,579,245,213,957,607,178,24,554,576,720,439,973,633,933,685,26,40,998,990,154,936,424,393,46,748,104,349,405,590,530,126,811,463,309,354,173,57,199,377,825,616,382,548,618,331,286,677,209,72,32,863,742,521,674,542,204,195,186,671,193,337,456,774,452,922,594,893,149,144,159,428,558,134,466,834,123,380,327,421,985,426,761,486,912,614,608,544,759,849,243,829,78,239,810,148,839,164,145,287,79,903,203,2,288,425,912,287,446,45,320,896,862,77,677,510,864,775,479,44,352,19,362,521,369,367,542,891,540,544,826,618,563,439,926,177,955,0,277,413,204,583,533,985,797,688,816,942,221,861,462,92,821,48,352,458,590,61,430,973,652,664,119,242,171,621,878,733,614,504,611,230,466,845,783,891,860,900,891,281,666,254,442,350,834,141,413,14,104,740,621,97,295,768,110,559,966,860,985,164,561,285,349,641,175,623,311,633,122,418,147,104,443,47,773,218,246,970,599,642,901,759,887,116,767,960,186,186,484,404,310,535,506,119,991,576,145,373,41,619,101,14,363,959,14,325,823,632,155,816,602,435,273,402,249,380,201,90,722,995,427,444,680,480,142,852,93,332,626,260,629,318,616,984,469,235,197,189,894,445,982,762,694,472,860,304,528,465,345,678,589,702,689,951,108,954,835,216,905,165,604,310,18,538,471,92,377,942,922,525,723,482,503,614,722,517,942,750,340,468,27,429,829,523,696,45,54,59,668,998,27,290,278,868,617,776,863,467,321,840,190,786,9,214,586,649,913,673,964,458,492,563,276,876", +"891,601,412,765,85,466,935,778,188,857,936,580,371,833,656,43,797,1000,631,133,773,808,765,409,78,189,682,785,372,366,439,186,211,187,734,742,492,213,206,192,612,367,634,918,706,38,377,427,435,670,624,30,159,817,104,607,150,156,382,865,263,553,760,312,624,723,11,845,254,996,408,165,431,737,159,830,861,74,623,879,165,264,342,891,929,109,781,109,709,565,836,329,626,885,15,832,832,76,859,624,706,796,151,322,534,903,78,163,230,888,23,186,135,758,488,802,894,603,677,617,159,913,78,205,940,191,13,526,171,778,889,288,348,199,621,877,452,881,56,981,638,846,292,573,53,607,538,190,299,908,864,615,880,570,147,265,251,7,125,782,306,481,849,148,841,457,714,56,631,519,844,900,515,809,485,751,486,516,280,894,196,594,312,269,122,770,104,243,501,283,609,105,852,396,567,790,667,641,578,959,47,611,894,30,212,390,14,912,611,443,116,813,9,544,553,207,687,679,427,695,905,3,572,342,109,966,293,308,668,612,931,201,146,599,956,848,691,937,154,605,688,526,193,834,251,787,183,840,404,474,508,173,797,928,624,519,570,879,170,907,818,486,165,963,706,428,851,228,965,671,333,826,163,76,389,599,341,427,998,241,462,813,277,489,53,569,166,436,924,630,683,193,86,487,467,719,881,583,660,29,136,379,248,431,265,23,984,593,424,79,734,125,674,786,913,126,142,414,659,451,654,348,737,383,527,493,807,15,155,622,181,685,395,867,321,63,423,993,244,162,450,375,288,626,225,243,366,82,451,250,326,804,305,112,578,644,914,193,6,673,435,403,510,449,575,310,722,714,149,162,165,442,51,357,325,455,922,752,260,336,547,628,680,795,400,831,618,429,251,176,115,367,16,202,219,538,405,871,560,373,401,611,877,262,157,17,4,419,438,976,289,891,910,292,68,229,158,460,520,835,881,275,707,990,693,508,766,208,918,271,462,744,555,798,273,183,16,578,83,995,171,289,634,427,485,171,184,636,474,957,637,70,925,144,125,549,998,570,996,721,582,344,827,511,322,272,429,550,772,794,753,94,241,757,224,691,532,890,15,232,327,46,744,26,394,383,46,432,467,995,791,400,978,3,128,361,923,943,797,593,272,442,742,947,872,92,730,319,346,284,534,146,505,631,862,198,134,238,932,120,460,922,33,16,88,984,985,686,374,105,19,23,698,756,136,157,989,178,410,682,854,614,306,951,72,407,147,475,714,6,57,114,271,880,7,796,906,356,267,719,158,335,447,496,26,557,405,596,37,904,925,941,166,628,524,757,510,673,36,241,927,143,40,33,747,662,790,960,766,743,282,652,942,784,681,565,57,329,613,662,157,727,342,171,531,111,13,514,357,101,414,86,369,235,574,138,698,222,875,551,390,126,271,289,790,464,480,625,651,521,16,16,287,244,748,451,136,20,718,233,457,802,637,924,742,234,360,420,609,151,857,231,385,378,590,793,73,342,378,472,817,102,817,186,3,967,838,446,445,843,744,472,291,851,784,69,582,496,951,714,241,541,657,425,962,47,420,722,429,777,640,586,289,871,473,692,550,963,529,998,15,237,781,30,901,460,385,818,116,287,88,24,665,950,697,607,402,879,369,636,307,268,25,156,921,41,866,60,531,810,498,306,298,728,222,122,805,77,941,262,239,302,46,517,251,704,305,683,369,606,910,416,978,72,933,3,584,560,356,434,19,871,747,249,729,437,906,945,470,64,523,674,746,207,63,728,46,310,855,140,292,418,551,277,0,283,830,386,640,578,214,177,523,831,929,954,631,598,916,433,653,699,136,960,626,2,90,933,675,714,736,365,904,191,387,146,884,671,469,880,610,296,815,200,221,399,723,19,426,338,606,636,790,667,756,216,100,927,297,286,645,490,442,294,399,691,680,333,773,931,184,295,345,684,725,203,969,753,462,632,670,931,969,607,563,437,587,838,41,308,40,258,889,811,95,482,876,764,893,491,276,570,19,796,772,969,57,678,150,882,143,975,388,128,660,224,66,852,838,552,323,506,425,93,30,716,902,611,291,629,245,49,922,441,882,61,268,935,228,98,534,370,269,278,773,271,236,646,55,637,397,82,981,456,233,245,692,48,289,238,374,809,967,294,595,64,343,182,32,544,306,789,753,129,499,752,554,344,427,360,717,331,734,72,987,212,417,471,750,892,911,362,650,902,213,439,159,100,930,400,364,945,857,781,113,794,118,340,223,94,66,837,854,839,669,515,262,350,781,710", +"81,160,769,125,646,344,669,249,428,108,313,301,737,822,72,583,834,130,578,861,399,645,423,169,755,766,184,316,978,644,833,289,249,622,757,891,979,241,506,50,884,913,347,939,735,787,309,397,798,400,806,696,110,127,14,709,222,825,825,888,497,2,933,262,284,842,603,232,454,680,461,278,170,771,718,217,803,172,561,526,494,861,896,342,924,840,374,921,950,855,737,274,178,826,585,275,767,406,327,973,527,651,383,579,948,388,758,100,997,536,743,72,534,932,289,86,662,960,760,291,503,473,961,674,142,864,554,430,397,672,180,167,831,998,748,668,242,621,562,409,803,106,876,909,972,244,625,699,941,425,765,9,237,640,911,260,985,52,204,939,900,809,845,762,22,795,36,356,98,571,857,351,172,604,601,630,38,679,661,9,862,62,852,539,337,953,791,941,737,355,220,814,551,657,312,326,546,289,313,645,178,578,996,981,803,19,560,152,80,954,981,99,28,32,129,773,451,471,510,338,835,692,303,221,759,590,452,487,862,622,543,63,101,89,651,851,667,552,631,452,296,69,243,95,259,334,921,832,155,981,387,966,109,973,525,725,996,958,34,331,695,129,811,226,999,426,460,920,13,972,606,875,462,860,243,748,221,191,94,691,87,707,243,972,990,527,982,494,112,728,704,651,565,269,783,920,472,768,944,851,871,969,605,279,663,891,861,240,82,135,71,813,666,151,272,712,203,190,624,492,792,181,949,116,229,63,242,636,353,374,981,653,655,512,144,911,466,180,225,751,782,938,563,608,876,369,830,851,305,629,761,222,305,442,127,344,230,354,502,948,300,87,873,42,93,397,677,831,919,461,980,325,481,577,496,68,890,501,802,581,34,505,476,663,757,616,634,115,28,358,920,836,271,192,609,433,235,597,498,587,761,161,271,975,415,392,223,322,622,470,148,455,470,700,169,9,446,449,859,900,238,5,819,706,809,216,15,790,327,50,925,211,466,750,770,739,864,414,546,640,214,692,834,1,306,577,799,234,992,428,528,758,562,291,934,486,700,710,615,965,679,7,700,862,265,375,233,270,579,438,9,722,117,990,642,121,388,872,259,71,645,966,466,275,887,360,271,683,405,137,9,716,718,274,136,708,551,994,107,992,672,196,264,776,420,401,188,228,449,244,819,246,581,524,666,286,122,757,155,270,410,25,183,287,758,80,147,909,399,559,258,439,904,2,659,370,346,923,288,19,213,718,67,915,491,977,114,659,308,823,250,635,15,565,493,120,244,705,287,604,384,244,111,197,836,392,112,622,253,478,188,633,757,531,875,443,350,226,49,538,521,734,988,978,651,852,154,681,379,534,311,105,681,58,5,635,644,432,571,877,435,710,58,444,919,973,865,312,295,627,362,610,893,421,585,19,441,214,281,131,700,73,167,415,688,261,708,699,707,762,469,712,551,279,626,625,888,762,631,372,585,639,535,39,396,319,474,466,926,915,631,790,600,275,401,684,652,768,771,620,829,148,135,792,385,170,961,354,673,640,812,564,232,614,269,407,431,571,553,95,356,459,338,341,985,125,649,705,287,191,23,690,930,964,509,241,518,796,881,169,222,946,321,957,795,250,174,776,679,345,143,63,533,360,971,257,990,577,842,132,497,161,273,564,1000,31,664,884,411,610,248,595,568,608,56,383,266,101,49,193,48,943,22,904,799,252,68,332,344,836,830,902,421,338,242,147,313,794,20,849,926,160,943,347,848,30,981,140,30,274,434,863,711,766,541,218,561,64,856,882,766,404,720,413,283,0,120,612,459,493,914,690,739,635,123,247,176,359,756,9,331,794,959,425,245,486,389,945,88,405,33,544,418,73,874,321,724,791,888,809,674,57,866,616,300,76,782,308,39,871,722,156,903,201,498,813,928,70,577,103,44,860,152,734,445,791,40,253,874,644,745,822,788,380,984,471,801,457,378,764,790,165,76,972,607,970,583,266,292,822,189,87,840,958,267,327,895,927,357,250,546,169,703,236,838,427,378,183,981,775,863,107,524,614,106,190,1000,578,270,25,662,414,15,876,377,375,766,8,500,48,89,313,232,854,785,247,340,694,19,81,585,105,729,125,46,402,944,812,10,416,163,947,939,97,253,466,639,459,331,68,572,28,136,548,331,716,463,961,523,890,731,75,607,878,883,62,248,347,92,753,696,26,666,740,607,945,891,806,873,990,921,385,905,299,327,649,815,653,534,785,736,164,310,866,712,33,467,635,33,34,17,864,68,607,329,547,305,12,94,282", +"205,133,301,263,710,123,542,485,171,226,897,105,506,184,26,935,703,68,583,485,648,526,85,754,986,969,108,782,840,543,307,918,699,425,705,256,954,799,560,841,424,2,403,335,234,684,161,978,213,180,44,46,589,329,838,847,359,413,328,833,405,445,211,863,399,656,426,659,348,356,17,824,191,625,206,492,710,204,293,845,458,785,825,632,34,872,293,79,424,429,476,758,184,338,335,844,500,374,420,939,715,712,528,675,396,808,521,66,716,534,807,908,202,763,967,785,657,410,909,378,402,881,531,473,432,80,809,562,141,316,362,813,531,705,366,235,718,690,103,296,191,744,678,434,70,833,71,263,690,643,610,4,48,533,921,85,661,397,434,39,889,442,949,476,373,581,87,14,33,610,319,932,531,594,30,269,226,107,446,465,345,738,903,677,308,434,796,81,938,730,130,974,888,48,47,122,214,879,959,701,906,336,631,959,283,321,823,288,150,725,784,732,618,452,548,225,590,244,117,587,49,592,484,834,138,97,321,11,598,184,757,768,62,506,763,917,690,259,165,846,87,115,664,17,155,638,48,994,43,803,149,231,172,835,828,279,592,152,523,509,500,874,446,629,807,263,18,55,324,282,889,102,169,354,69,267,116,890,262,267,618,957,316,498,718,988,580,30,760,8,291,292,174,74,450,725,57,256,607,386,377,981,877,963,92,617,469,227,460,134,671,919,235,369,574,902,835,113,242,764,339,973,566,285,988,329,566,607,462,459,867,653,175,985,901,302,788,433,591,386,752,975,964,236,775,997,325,959,322,574,797,920,469,4,945,860,4,896,857,37,170,505,29,983,358,592,291,966,897,346,856,55,967,465,749,724,801,84,413,317,788,363,892,220,507,486,934,394,412,58,277,11,184,937,285,482,262,798,137,699,481,437,291,983,246,486,273,841,284,525,40,104,624,596,87,653,588,994,253,804,657,841,150,394,90,816,120,898,601,972,18,383,745,208,640,958,917,810,289,710,520,867,370,125,316,472,957,110,577,158,759,47,68,421,611,963,885,795,365,711,156,966,292,683,547,104,126,285,389,80,792,104,341,974,694,139,437,960,922,535,622,894,240,992,518,532,965,436,282,726,480,128,414,834,655,232,407,550,320,965,380,679,596,815,372,302,275,523,78,597,313,49,826,514,765,700,267,864,872,30,56,995,913,123,398,622,708,399,143,267,697,634,306,783,964,682,446,494,203,89,327,425,287,168,703,706,215,491,470,514,461,536,115,541,763,40,764,80,28,450,173,561,88,490,937,339,511,735,942,109,888,741,809,84,494,784,366,83,913,161,104,594,45,364,697,937,59,145,479,711,706,222,287,251,634,660,130,708,901,61,69,689,1000,621,232,914,45,521,219,749,905,458,361,489,240,503,727,164,252,147,962,588,208,653,610,30,891,917,593,596,16,855,950,645,647,262,319,438,852,739,552,342,393,373,787,586,643,389,365,467,279,464,518,442,631,981,674,928,586,825,945,939,543,975,586,381,593,938,367,868,621,443,413,655,574,597,423,232,278,955,114,239,602,91,706,351,153,500,857,961,400,320,96,72,915,458,668,862,872,973,202,722,43,802,201,827,984,624,192,347,696,681,169,203,498,416,461,623,218,801,426,815,766,1,911,54,768,931,745,1,879,768,904,625,100,773,306,807,519,463,323,475,459,398,558,737,469,691,513,185,184,129,471,569,392,639,442,178,946,769,463,641,451,366,47,455,802,555,151,400,327,847,831,525,380,697,277,357,496,829,59,167,549,204,830,120,0,288,538,585,736,960,543,697,114,240,933,733,142,71,603,511,252,319,169,559,917,500,446,912,345,50,692,771,923,823,304,430,989,907,459,576,318,921,591,271,475,228,697,271,123,36,470,870,332,383,431,581,903,326,834,690,627,46,518,327,27,645,583,176,193,200,561,661,386,480,690,398,984,540,612,568,99,76,890,252,466,465,109,746,50,901,764,994,419,437,710,948,261,652,174,270,275,145,965,516,8,635,898,680,182,760,865,416,448,316,221,847,158,202,113,171,185,909,658,237,348,610,738,376,994,562,68,464,193,932,402,784,45,190,201,52,97,311,330,822,66,843,553,963,196,494,423,632,526,901,737,674,541,317,734,600,987,302,488,520,424,812,463,193,527,373,114,528,381,772,421,192,392,901,162,715,751,455,238,625,385,564,974,610,288,722,199,449,886,916,501,767,883,21,864,533,495,424,519,617,201,912,304,818,2,536,477,264,958,784,215,680,775,654", +"226,350,349,627,749,342,311,294,804,359,450,922,32,255,186,601,127,503,210,631,940,828,604,894,251,851,742,335,684,858,495,304,772,269,835,424,837,938,452,27,611,326,504,342,205,902,257,543,87,567,482,301,603,85,41,288,741,428,722,73,784,256,549,88,218,380,694,202,995,182,961,120,116,760,63,66,298,708,643,622,998,546,836,486,14,453,841,526,726,887,962,325,226,683,222,542,210,412,232,926,52,744,887,270,215,692,274,423,601,894,662,543,691,3,144,893,985,18,22,148,975,102,426,275,695,491,237,615,609,729,230,494,328,281,225,225,310,179,436,311,813,147,430,566,214,314,854,905,770,562,872,632,504,811,346,540,558,312,712,24,712,446,707,805,950,538,561,946,535,379,202,678,574,628,88,855,875,277,177,521,137,919,902,609,492,808,202,759,959,994,685,546,767,587,640,516,94,452,284,657,450,841,247,51,503,258,370,180,180,574,933,661,560,637,38,514,742,885,118,757,857,63,882,539,97,565,143,400,64,415,252,827,955,40,749,372,227,824,243,448,782,422,286,691,279,922,720,827,117,661,898,292,955,193,125,204,197,461,18,522,847,661,736,117,484,161,63,594,907,752,963,74,798,98,532,580,750,606,817,924,304,660,439,143,782,97,510,881,765,791,764,343,214,765,281,877,480,832,315,529,133,904,131,450,846,798,70,743,952,929,572,976,364,855,888,304,440,350,487,502,930,959,27,456,354,954,905,112,617,733,283,897,647,273,844,122,877,954,104,866,839,994,734,813,749,541,882,508,792,235,829,483,559,954,102,979,819,777,587,264,231,382,852,624,138,73,2,952,216,179,813,730,622,261,438,884,496,280,775,115,235,986,721,194,818,769,228,613,75,709,395,498,42,280,40,344,909,547,777,95,245,346,651,905,614,598,941,789,369,739,438,395,333,342,533,958,829,262,910,809,404,533,145,977,220,241,292,402,432,769,433,966,742,309,770,646,58,886,37,467,831,38,131,284,407,561,57,284,721,370,864,721,289,916,725,568,873,987,160,532,367,52,777,880,488,796,939,436,812,937,524,416,713,785,567,416,539,533,859,791,743,836,442,106,157,312,662,539,462,693,790,405,507,845,225,713,999,201,589,7,696,124,510,987,352,203,112,133,626,625,146,262,856,997,95,686,282,464,479,271,704,175,409,845,481,480,269,980,247,544,800,320,54,625,882,596,981,663,223,815,950,187,40,101,728,933,139,595,651,106,759,693,712,9,56,184,448,254,999,937,181,333,835,650,424,404,126,50,392,347,14,733,801,211,502,141,870,918,906,375,504,889,924,269,818,77,595,289,440,681,438,505,171,52,399,847,46,484,922,347,146,136,506,368,210,53,959,139,212,121,313,468,256,385,890,418,753,323,807,826,972,357,897,410,772,990,691,382,751,372,274,348,215,779,467,386,751,132,48,71,120,859,679,860,496,862,188,583,998,546,452,526,889,416,620,712,592,755,34,384,54,711,431,667,110,330,379,215,414,555,651,931,230,143,359,126,209,572,698,982,815,449,156,7,464,480,974,148,325,786,19,120,892,696,605,39,10,802,897,455,271,844,738,710,695,989,863,927,617,427,421,172,933,500,2,721,26,763,279,476,381,688,326,110,436,733,445,607,375,283,854,155,463,80,75,585,191,916,850,685,246,750,783,327,862,305,612,840,11,7,981,153,597,724,714,724,943,880,737,53,889,900,296,710,133,360,771,696,279,560,678,176,586,473,540,478,157,204,999,266,81,543,171,583,386,612,288,0,179,567,133,403,41,135,425,460,64,902,641,706,826,339,209,923,239,926,915,797,236,949,428,978,320,977,798,306,568,629,444,772,135,763,55,849,568,879,503,693,879,262,648,418,505,965,750,106,640,647,555,326,932,943,846,153,44,974,840,724,123,816,155,361,630,555,219,783,958,682,541,499,208,908,186,150,396,821,48,316,203,648,238,493,382,456,750,821,473,646,98,154,200,357,619,779,832,607,532,8,366,941,847,952,864,82,149,985,259,613,239,229,220,524,453,221,582,916,413,836,602,683,715,955,689,624,901,286,319,98,254,281,472,804,473,417,1000,873,569,846,354,457,364,909,946,874,119,411,401,970,595,650,744,483,787,265,296,582,62,169,101,885,326,960,768,411,281,556,111,857,53,620,89,439,227,323,972,310,261,50,664,904,260,562,781,152,901,538,648,461,149,38,683,727,261,262,437,357,717,817,736,530,648,932,247,84,918,508,26,865,337,734", +"907,444,973,877,708,449,687,495,703,900,881,128,54,433,107,797,949,72,49,292,959,141,561,152,328,952,890,834,257,362,434,288,577,774,858,384,915,284,41,25,610,50,297,709,48,638,84,564,742,548,494,57,1,528,812,769,192,367,91,245,196,918,144,593,442,597,379,827,806,437,693,818,917,156,740,635,127,752,342,372,231,474,467,428,562,151,23,827,683,629,612,795,735,932,206,769,278,896,26,251,531,733,854,656,789,774,334,402,322,757,160,350,316,608,769,732,935,857,117,323,473,916,623,726,733,888,929,713,730,634,239,391,807,854,174,793,405,702,183,431,919,279,91,171,367,905,779,44,416,748,40,281,57,926,762,248,245,273,839,96,961,489,84,910,627,743,262,815,698,391,429,397,939,21,60,92,959,637,276,296,646,192,258,456,256,486,11,628,299,499,594,745,211,118,569,405,916,647,179,29,116,252,66,420,246,237,61,785,312,452,88,662,837,233,593,249,137,561,183,779,131,8,32,591,760,491,21,583,108,71,930,254,460,849,35,204,720,455,823,818,792,766,349,124,477,763,911,149,96,690,420,98,463,11,85,938,493,87,67,950,805,27,271,779,702,474,884,564,109,638,689,343,315,180,382,764,799,734,948,128,771,556,841,429,719,947,627,511,284,425,27,712,360,900,230,115,639,332,560,162,565,468,941,267,96,596,250,296,695,109,758,842,594,200,440,89,431,705,843,685,559,240,891,938,761,314,690,240,406,604,76,129,838,528,676,293,315,723,874,776,454,627,237,419,879,498,250,964,233,83,141,322,136,80,954,753,681,797,72,51,328,23,148,18,817,326,723,818,486,140,208,716,645,926,348,697,833,475,45,336,659,41,722,886,406,166,500,743,794,414,788,554,611,399,465,320,456,919,516,252,871,122,226,252,641,110,569,484,408,153,895,41,612,377,975,955,835,421,311,903,953,54,926,166,5,394,165,243,885,104,465,93,570,466,29,631,317,773,588,152,213,814,224,526,6,54,757,341,203,346,673,818,172,960,510,603,24,415,862,231,133,249,556,389,996,399,581,261,411,90,275,571,479,416,383,42,406,22,475,461,360,64,48,902,713,243,738,284,265,311,168,610,468,837,547,84,133,654,176,427,894,320,764,41,969,363,292,810,882,602,232,216,867,667,569,704,594,182,140,253,401,389,754,44,308,156,454,126,267,265,195,516,742,484,989,275,776,625,991,947,602,721,652,214,304,979,494,588,965,797,851,729,322,812,52,870,739,505,127,120,153,381,19,603,888,382,262,138,633,84,248,197,914,873,259,378,635,279,478,679,872,51,729,969,222,312,625,512,742,990,91,774,979,355,807,205,551,533,396,318,426,808,745,30,371,307,197,150,109,124,690,382,309,52,549,390,632,974,351,108,831,115,659,322,457,578,232,546,256,610,477,519,905,68,146,789,344,931,752,410,532,519,878,179,114,903,981,233,867,725,754,708,743,329,656,76,205,933,861,87,59,750,245,766,888,465,487,271,170,945,392,402,184,479,930,553,3,663,318,33,600,270,117,457,839,855,552,644,664,199,468,736,555,273,746,692,744,399,780,34,827,642,403,73,570,92,154,218,817,968,856,91,192,436,631,283,215,148,68,635,244,510,457,885,570,770,704,216,339,590,13,875,820,194,850,664,959,186,238,66,909,189,709,420,52,888,919,527,904,966,722,904,80,388,326,823,736,442,685,461,621,373,637,49,915,458,730,618,434,868,245,120,901,992,267,363,348,468,949,310,706,607,844,533,640,459,538,179,0,332,254,37,327,853,844,614,945,599,746,813,358,93,592,741,800,518,825,219,420,287,748,750,801,440,556,974,780,99,206,331,650,994,987,234,818,364,113,384,886,989,775,721,428,551,141,866,760,999,402,953,176,942,391,457,832,714,40,397,713,820,414,807,700,710,540,147,192,514,487,389,933,460,538,852,433,932,236,899,97,86,110,755,935,894,766,569,307,829,509,821,300,182,643,85,323,575,749,215,876,717,575,844,690,543,72,738,322,197,464,556,426,329,587,522,270,508,668,138,873,887,616,566,902,422,593,655,12,80,614,979,289,997,554,395,128,506,78,12,388,489,616,64,692,536,678,15,760,52,818,578,411,61,127,201,837,509,407,586,953,421,20,422,97,480,529,766,639,85,482,935,212,779,741,318,445,475,995,991,219,444,905,304,630,987,636,816,570,273,534,829,822,241,410,19,516,328,983,70,588,545,330,1000,684,147,648,438,786,168,286,156", +"158,846,720,119,357,638,757,598,346,558,979,194,73,301,581,113,248,185,624,685,129,754,869,860,279,492,634,521,295,487,812,847,656,379,604,225,112,669,27,45,216,682,517,609,794,104,818,144,291,542,304,501,896,479,714,189,628,598,338,31,576,873,61,915,441,164,918,474,647,151,541,257,976,908,837,702,421,497,885,130,343,777,337,628,702,644,870,696,214,718,921,63,3,31,321,668,362,133,58,869,36,829,289,206,209,742,295,839,952,371,248,867,430,482,992,429,200,726,23,889,800,67,778,684,588,963,667,364,617,901,831,7,629,787,455,853,895,384,965,506,498,769,366,225,970,238,838,548,206,512,144,96,485,487,652,521,294,790,606,978,407,112,683,905,518,243,928,351,737,493,319,855,410,548,239,616,729,776,319,892,352,265,835,586,923,642,758,64,930,686,701,961,414,509,660,248,801,285,972,623,123,550,475,713,119,172,789,296,616,915,117,379,279,724,174,573,492,319,801,53,428,529,94,142,43,10,612,546,409,354,871,939,356,612,124,501,900,542,181,460,607,554,944,248,849,959,895,67,508,426,525,70,281,453,36,842,536,231,453,892,92,473,629,655,191,940,421,147,151,275,741,540,55,818,6,574,143,13,933,639,708,847,912,630,847,795,900,360,257,215,961,867,872,897,283,963,839,56,223,841,161,78,385,372,461,390,112,891,161,864,169,74,353,935,872,941,474,603,406,80,232,499,935,155,601,271,999,316,763,693,573,322,175,717,67,782,280,388,342,360,167,727,998,221,374,585,315,921,847,468,158,983,13,661,659,726,384,210,896,915,261,998,993,833,26,671,670,637,281,855,227,806,588,310,377,163,981,207,238,340,392,814,309,563,787,731,4,499,119,60,500,648,887,788,658,73,390,805,403,202,169,418,911,418,824,199,401,178,941,443,269,828,384,460,823,60,677,788,830,149,621,542,501,297,86,299,262,106,535,536,68,181,213,416,924,79,231,19,741,94,194,402,219,509,242,804,470,440,943,148,220,4,631,501,734,855,21,617,769,334,299,619,551,620,756,89,472,990,643,574,260,831,679,854,274,401,831,622,810,38,991,612,965,163,505,211,101,275,74,1000,314,483,312,894,139,633,411,373,894,867,329,838,893,303,949,161,706,25,385,458,306,107,770,632,904,202,63,245,26,848,817,42,901,401,122,734,982,73,395,844,801,96,5,389,228,567,967,509,816,416,815,339,731,978,843,289,591,987,406,194,852,289,609,26,962,11,301,62,913,409,305,728,74,650,724,57,377,445,824,626,610,868,621,439,707,5,638,81,961,835,233,176,991,909,199,110,383,443,483,926,345,164,156,923,705,176,360,549,150,17,101,255,638,362,496,978,406,317,112,75,129,42,812,395,692,933,45,785,125,7,583,175,358,914,635,906,11,743,233,226,35,81,274,37,950,49,781,76,128,430,857,888,457,179,269,380,177,224,610,159,249,287,694,523,716,888,507,105,252,143,270,565,389,33,119,50,885,522,889,909,195,433,212,766,667,978,889,972,42,379,766,652,758,599,265,676,602,725,390,339,656,233,100,567,811,696,68,690,830,595,777,37,805,956,995,107,257,90,461,252,290,550,425,585,607,710,43,784,905,409,607,957,690,27,76,426,254,569,109,830,616,767,132,638,452,783,510,632,864,914,561,651,558,410,242,609,684,391,10,677,777,310,505,653,43,21,637,537,976,999,657,513,396,829,414,692,204,64,143,331,60,23,31,418,975,437,978,499,672,397,440,136,769,985,578,493,585,567,332,0,247,508,576,375,89,458,277,881,865,291,569,987,158,78,247,814,13,710,416,712,450,845,824,896,770,979,261,572,707,739,113,142,256,573,752,661,628,198,846,921,913,547,827,126,318,643,939,921,355,690,840,876,932,309,216,525,834,467,920,101,717,905,108,124,407,242,238,796,141,767,380,551,693,214,275,849,142,254,88,912,512,70,49,73,518,572,238,123,770,567,361,122,227,699,138,502,41,427,875,875,14,312,882,510,117,369,9,658,298,850,769,21,980,126,293,765,769,877,176,424,607,53,166,506,474,470,248,520,316,429,566,160,715,619,146,823,222,658,779,10,589,458,92,257,884,848,825,419,386,507,846,37,883,346,199,112,131,752,670,603,854,858,247,826,734,455,528,509,606,471,728,378,101,515,696,726,56,382,61,281,858,636,700,220,848,945,772,903,230,525,838,343,888,865,691,894,616,796,156,986,927,97,636,592,793,955,232,135,582,114", +"473,464,343,195,354,124,47,224,613,474,117,728,780,573,430,41,438,288,408,612,401,902,950,577,646,373,231,898,141,569,253,444,417,364,264,136,349,922,687,301,534,167,939,743,346,562,607,656,555,21,419,331,884,866,70,871,426,636,766,381,211,877,802,857,104,372,623,504,873,500,734,378,479,286,282,723,354,469,650,75,107,338,212,474,751,349,915,762,868,581,402,317,543,563,419,588,56,245,306,759,449,15,866,340,840,761,816,171,996,60,399,951,258,368,788,665,399,911,419,357,354,880,400,451,924,925,920,856,222,807,809,53,848,147,636,126,735,304,831,601,298,935,630,974,742,372,443,560,288,140,325,467,530,283,244,231,890,401,404,571,78,782,701,238,259,377,572,650,807,989,324,618,930,149,135,906,968,722,817,352,843,358,6,715,43,281,976,381,17,269,888,694,392,784,546,716,831,161,703,313,568,291,882,290,538,788,208,232,583,464,5,167,71,283,690,66,409,56,37,663,577,46,799,599,100,677,609,53,886,20,93,875,69,70,83,683,367,781,35,932,633,5,232,4,905,741,823,794,59,357,433,809,609,386,699,806,59,947,311,978,661,151,429,231,380,453,678,818,977,724,646,465,215,755,491,460,641,912,941,953,71,47,235,688,52,373,822,115,916,548,364,715,36,619,513,94,559,871,789,74,484,217,39,416,255,746,400,22,54,291,203,465,135,408,524,240,874,578,554,92,991,355,235,239,71,964,833,303,948,714,736,333,51,41,969,833,433,546,482,850,936,334,596,566,521,957,581,86,635,102,93,841,390,181,369,175,699,757,627,715,30,414,162,606,390,335,942,261,53,918,855,199,682,425,537,473,472,180,815,136,706,608,762,103,460,498,413,276,559,900,217,183,673,225,954,327,322,649,934,952,216,843,8,727,367,767,673,482,963,605,274,752,487,598,162,30,242,341,281,805,372,788,413,76,249,195,612,537,630,312,516,367,579,96,434,815,392,117,809,102,179,535,612,452,849,491,140,250,68,496,855,433,863,494,42,656,262,154,727,177,991,109,306,83,371,137,543,264,637,344,371,975,414,728,399,998,485,228,930,926,101,98,287,259,524,795,980,900,8,543,550,967,461,816,19,238,874,466,360,387,763,602,545,709,220,448,935,857,162,417,251,969,261,30,708,519,882,46,807,795,376,235,542,516,654,152,669,66,754,113,746,220,528,757,619,167,844,344,164,183,260,58,325,835,617,323,834,435,169,641,171,274,217,169,12,13,75,768,914,388,394,877,189,408,74,452,430,683,406,85,712,959,811,29,605,547,398,893,602,7,954,875,9,558,807,915,390,611,685,846,984,369,979,364,739,210,825,492,542,105,791,400,764,478,298,51,208,279,107,661,447,942,984,894,302,673,665,92,732,656,752,491,135,181,143,80,548,155,281,499,951,514,563,362,487,326,83,42,383,943,730,52,535,584,514,427,862,121,122,927,347,179,958,71,179,399,580,289,515,373,323,264,105,616,671,652,15,729,98,176,384,799,850,325,589,898,668,805,972,37,929,376,44,810,982,800,169,51,706,414,456,563,947,956,72,33,323,653,127,794,268,975,604,767,86,288,635,926,36,132,921,528,126,527,384,207,157,557,284,375,735,770,717,914,514,596,2,123,422,413,753,344,506,881,205,564,294,384,913,776,559,255,417,599,240,189,191,39,275,145,786,84,390,257,937,519,379,928,618,170,735,7,756,472,838,81,190,951,299,556,272,734,912,466,388,881,472,81,22,280,38,121,199,797,214,914,736,133,254,247,0,717,897,773,446,27,702,715,972,64,597,954,418,29,717,134,688,492,312,650,573,458,993,411,160,565,493,780,732,145,406,378,690,335,789,819,180,972,871,788,246,434,922,604,581,701,138,318,618,294,68,875,516,533,915,474,203,611,991,514,728,966,425,626,5,93,574,653,767,142,416,208,213,158,485,122,50,651,152,735,767,334,591,95,345,262,73,305,867,847,40,938,183,443,402,779,783,932,708,989,604,165,524,560,600,922,941,727,114,429,857,745,699,241,4,189,646,56,731,918,160,809,219,429,631,5,903,514,159,435,986,688,705,300,682,67,249,269,990,168,498,437,220,466,199,150,236,704,281,690,314,957,572,792,426,689,979,154,920,684,165,909,490,715,554,56,517,938,652,604,774,544,48,423,825,728,86,162,190,194,46,850,779,755,994,158,112,30,456,327,275,502,685,372,486,36,289,817,397,833,211,245,61,75,850,230,886,195,876,444", +"622,507,210,596,33,667,551,178,160,496,506,440,712,341,722,416,631,448,297,725,660,775,226,771,658,843,954,442,964,935,868,7,192,937,694,936,97,988,754,361,108,404,569,370,7,570,460,693,154,951,477,33,501,611,856,287,693,64,777,428,526,954,470,778,572,308,485,777,788,550,142,900,569,261,495,394,109,336,221,697,350,650,240,804,19,117,593,832,813,106,377,635,391,697,920,734,372,907,766,493,9,777,302,47,337,971,520,254,601,637,493,785,159,380,583,115,673,405,572,779,376,138,616,3,827,683,873,981,135,42,572,726,233,627,984,566,623,447,391,707,709,973,549,261,451,704,580,458,266,633,949,354,620,225,365,691,420,580,925,64,339,901,90,648,290,148,563,444,904,664,286,268,998,991,857,878,274,325,906,532,76,430,329,396,395,975,397,657,279,320,864,315,551,765,128,767,446,376,356,576,668,963,547,182,136,796,614,387,465,232,232,81,379,744,294,486,527,329,86,790,733,530,468,321,80,12,701,515,151,488,43,819,234,419,319,138,594,790,656,274,557,187,471,555,882,204,157,820,431,478,830,568,561,891,789,963,516,95,669,89,565,33,181,466,898,15,425,107,755,127,915,902,775,852,69,598,274,118,489,209,504,185,636,55,265,509,715,950,563,781,749,79,429,783,143,383,841,257,720,228,334,679,733,323,653,485,504,534,702,645,59,501,827,154,696,366,744,444,61,483,756,637,201,603,692,899,121,503,14,518,629,300,276,375,478,523,800,19,447,576,671,770,552,656,412,420,587,71,473,367,523,13,497,546,893,640,636,549,381,484,718,489,280,292,657,997,861,187,296,393,42,904,643,930,233,534,183,325,992,782,485,453,351,875,320,495,680,11,868,63,719,316,806,130,68,519,580,462,636,307,230,25,895,853,875,630,35,89,740,992,418,866,410,421,428,365,833,535,307,139,338,654,376,238,327,974,391,383,291,654,322,882,966,958,38,397,745,837,477,616,302,150,504,83,636,11,582,772,123,428,824,107,112,876,234,110,468,476,385,323,952,713,978,35,415,120,369,575,518,750,885,51,247,311,525,997,879,953,239,571,684,252,641,309,369,558,70,367,220,680,969,408,546,901,6,27,795,625,321,823,708,849,695,56,390,29,346,53,142,278,725,124,299,857,85,159,296,9,786,950,175,774,767,383,673,248,286,515,316,690,882,716,403,503,354,476,766,59,209,534,720,588,304,545,177,859,63,550,802,139,525,197,447,530,161,271,399,384,294,729,887,922,896,762,575,529,440,567,45,893,228,553,884,673,735,100,471,798,711,340,552,941,782,312,164,884,829,738,244,385,829,510,978,816,336,583,911,377,406,794,478,825,636,519,99,27,115,849,267,157,5,212,283,803,431,322,28,976,552,870,590,691,481,768,339,32,47,317,564,124,696,526,430,504,190,931,180,888,383,642,376,221,881,461,448,242,728,134,875,982,258,995,397,224,207,891,670,190,286,977,212,649,420,50,36,120,403,224,64,474,366,505,901,474,61,415,157,314,475,794,367,171,544,136,478,873,326,87,720,994,914,568,693,466,605,523,421,274,263,429,162,243,941,99,513,862,524,429,681,682,165,161,367,223,551,930,254,838,830,126,917,184,333,316,474,60,426,427,575,871,476,719,539,812,281,153,448,211,440,164,431,922,431,94,467,914,194,134,449,892,604,551,734,959,250,324,646,43,913,587,557,492,83,161,298,139,440,69,611,894,572,859,831,920,263,777,517,536,714,183,598,548,758,688,177,690,960,403,37,508,717,0,152,629,446,153,422,572,518,45,389,766,982,68,72,195,665,910,936,999,837,276,671,573,261,633,891,419,998,298,160,783,797,128,349,946,118,981,488,533,616,697,186,249,167,78,751,915,491,226,809,453,904,817,997,766,517,618,8,930,368,172,922,660,885,878,848,100,421,928,322,923,814,66,392,456,370,62,600,916,481,414,545,194,711,614,64,903,448,557,305,228,101,324,793,457,981,285,65,93,505,914,722,907,123,760,912,755,477,723,819,268,554,312,726,880,114,36,58,755,735,865,316,910,602,733,470,607,301,475,13,615,454,579,610,254,95,923,40,641,207,983,63,86,846,686,783,43,369,815,293,374,994,118,88,654,895,382,830,210,365,802,27,766,968,510,892,219,828,826,62,563,520,669,720,909,896,385,989,399,426,394,829,582,973,195,837,197,951,713,171,89,549,43,871,454,726,186,348,651,845,961,768,462,111,491,766,242,797,930", +"67,733,915,480,80,105,106,939,124,244,954,897,560,731,773,209,966,103,274,476,755,853,302,874,811,163,418,371,712,620,546,264,514,820,77,763,447,361,637,216,92,226,244,15,283,942,482,30,773,435,648,205,291,515,982,183,789,726,286,173,853,746,867,647,526,770,111,156,96,552,706,778,232,211,400,593,781,419,711,796,720,691,657,707,143,658,813,326,799,480,807,502,704,269,249,773,214,821,186,796,350,725,322,111,287,753,693,672,376,157,46,686,277,517,890,819,977,590,866,153,389,390,789,310,477,569,44,778,569,139,344,150,647,452,822,489,614,426,281,562,361,991,311,177,469,414,329,280,843,901,493,302,758,855,439,14,306,98,521,606,162,930,903,639,102,727,11,275,531,216,57,385,177,234,943,741,293,485,822,728,331,835,25,581,827,137,157,994,867,925,190,353,921,139,201,116,412,273,778,479,630,806,861,371,215,213,839,789,238,409,999,224,600,457,240,41,690,651,543,311,389,30,30,729,289,498,639,810,715,253,618,662,729,316,789,861,548,967,65,862,909,15,648,88,624,261,614,895,633,289,724,15,522,190,18,645,349,99,767,366,301,48,504,667,587,740,30,773,226,886,118,501,812,272,406,360,405,741,480,941,58,329,271,851,3,892,498,11,198,755,611,228,242,964,324,721,235,167,280,101,305,775,985,777,402,815,595,888,87,603,72,487,427,566,183,319,222,34,860,780,395,462,557,321,461,996,853,600,135,6,380,505,830,953,838,510,908,802,656,45,185,674,275,148,318,736,565,597,496,568,859,742,539,118,268,906,696,928,877,156,834,256,468,516,598,30,563,663,362,947,802,816,290,327,764,887,808,794,981,999,61,509,455,616,44,192,474,933,844,340,705,426,981,585,194,592,88,958,844,975,935,329,974,297,488,676,498,35,907,135,807,211,27,223,631,491,114,315,499,513,337,220,252,533,375,921,27,780,544,113,257,309,180,871,681,361,955,544,649,124,861,169,280,220,301,440,500,974,293,977,68,382,145,137,373,20,776,70,256,412,103,61,688,811,365,728,209,633,629,813,848,798,571,466,750,724,136,577,273,27,154,797,376,869,254,981,969,687,894,484,779,997,721,122,532,771,371,570,474,35,512,827,691,753,697,403,505,132,461,189,652,147,810,570,360,44,189,959,164,457,133,611,791,912,998,874,229,658,581,887,638,666,561,887,238,931,956,530,998,445,81,927,861,845,239,698,894,608,397,808,784,646,460,955,76,158,585,425,352,921,698,279,822,315,24,23,289,629,869,157,922,853,968,276,794,147,307,997,606,392,375,744,201,741,16,300,277,194,429,505,256,49,470,900,483,387,514,391,844,411,383,144,631,90,563,687,810,313,591,431,460,747,448,82,860,493,472,94,442,652,627,434,864,231,624,241,825,90,531,481,230,122,742,726,385,934,160,763,49,573,74,495,981,923,645,404,400,420,483,716,663,284,593,370,17,386,965,70,397,901,903,278,829,413,957,140,861,2,830,435,912,645,56,614,884,100,34,324,999,447,710,507,602,730,855,158,876,328,932,283,43,616,859,487,521,434,499,649,910,544,208,130,916,15,138,590,962,558,258,464,629,680,653,96,832,825,973,305,307,701,353,960,729,946,574,734,298,115,458,986,176,450,748,874,550,796,223,429,23,627,733,688,920,862,994,916,780,4,793,70,497,882,322,457,284,519,246,870,62,635,294,981,457,169,983,526,456,424,372,581,66,617,164,298,374,458,893,197,265,994,460,119,266,816,523,739,543,41,327,576,897,152,0,432,630,891,478,662,712,637,706,294,535,90,698,399,802,281,810,602,938,177,4,708,341,224,452,109,98,268,776,878,64,384,953,190,544,419,278,139,776,339,502,986,46,686,221,989,805,744,4,633,627,666,962,133,308,540,291,333,97,438,346,276,174,365,960,521,166,142,777,150,730,864,487,328,192,886,275,934,257,57,305,605,983,541,207,928,199,487,940,580,625,111,225,359,280,6,563,908,93,583,192,413,574,731,637,70,125,64,846,522,95,399,738,756,860,573,985,803,933,244,78,890,178,984,774,153,559,278,872,905,1,379,919,955,200,543,167,988,44,518,28,583,850,721,188,687,893,195,998,554,197,691,600,760,716,506,449,356,152,856,880,68,899,988,389,190,520,611,335,14,863,5,199,656,906,582,967,989,483,883,104,288,425,873,442,102,39,109,661,554,48,69,68,916,917,792,922,511,935,401,550,524,247,468,311,13,958,343", +"981,303,640,138,28,180,87,526,98,437,861,278,532,379,253,25,630,558,302,860,101,976,214,936,20,493,138,437,26,692,429,228,633,770,218,166,500,992,659,335,506,723,813,601,217,864,198,207,428,937,697,871,575,179,822,206,271,269,968,599,657,473,873,987,138,901,654,232,779,387,349,482,500,262,309,564,757,339,698,324,64,194,445,256,394,355,53,130,729,717,543,326,750,726,225,326,602,845,984,248,822,206,557,849,884,403,705,674,752,530,487,303,545,364,351,58,955,333,325,919,617,625,711,449,171,713,535,115,240,715,771,287,496,832,289,323,112,586,467,306,630,538,643,759,137,409,76,979,624,437,457,785,239,269,84,347,614,287,585,87,981,537,664,182,389,50,50,767,180,342,493,883,603,984,45,495,933,592,841,770,848,620,769,70,85,581,183,500,125,286,279,293,384,823,355,359,290,770,249,273,485,221,739,253,951,102,540,781,970,216,249,460,956,166,484,846,891,827,763,589,503,94,172,673,997,727,368,100,363,863,879,139,405,951,874,9,936,325,979,905,847,233,764,115,446,103,315,620,320,191,573,380,627,413,672,624,707,838,620,406,727,314,663,790,534,985,59,287,835,349,10,709,106,782,374,375,714,113,222,658,33,627,19,126,767,199,400,123,732,848,121,993,857,389,245,68,825,241,39,127,976,632,103,280,434,83,226,637,370,742,627,884,26,970,253,18,814,259,518,207,199,824,172,385,264,368,771,973,270,139,712,722,671,455,864,711,45,518,605,171,823,467,510,758,410,200,714,404,93,433,510,898,878,685,907,573,122,53,554,119,862,140,126,159,692,33,814,13,693,507,542,999,466,484,394,572,158,946,162,995,728,968,965,707,466,239,537,146,131,294,265,952,172,334,258,542,167,677,184,261,194,176,298,304,638,899,640,632,179,647,455,125,308,837,788,626,427,67,709,361,729,120,644,604,544,453,887,511,362,191,784,758,477,32,21,779,578,977,865,641,447,670,893,657,293,289,309,945,771,498,535,337,684,268,543,555,7,226,148,918,376,151,467,391,178,200,428,186,647,795,859,460,126,186,851,363,231,645,848,420,736,671,894,87,265,36,912,288,150,171,791,877,870,139,557,47,912,845,701,692,914,214,478,334,430,561,758,820,955,613,285,731,453,344,304,412,129,323,44,54,548,757,291,341,825,809,120,254,896,107,761,974,717,645,175,571,682,732,488,428,362,103,631,619,457,706,917,208,398,240,224,953,389,99,713,109,288,379,126,316,811,403,226,405,411,793,208,863,923,901,459,979,290,671,261,941,476,58,378,211,96,189,964,825,584,32,671,71,536,914,516,340,126,191,697,716,978,220,40,38,460,232,454,81,134,855,686,22,707,390,905,598,602,529,622,2,60,679,616,902,476,417,29,674,799,599,675,622,332,931,716,574,863,137,286,147,499,886,487,400,503,791,260,643,974,499,968,213,970,706,116,962,310,635,287,486,391,948,634,178,358,848,849,131,683,256,387,296,413,232,560,916,543,951,342,820,794,272,157,159,299,778,543,268,362,995,44,657,962,319,701,14,602,551,809,686,809,937,347,305,986,149,309,326,652,537,57,390,828,66,698,497,366,467,621,780,903,273,756,829,600,657,471,416,787,380,148,895,999,896,111,852,690,214,38,901,963,698,200,428,300,584,950,807,124,511,922,381,171,528,411,79,377,397,464,737,225,216,927,251,503,39,648,935,700,54,433,444,638,519,119,605,381,680,346,322,906,404,530,996,705,395,485,942,831,635,697,135,853,375,773,629,432,0,600,755,767,487,43,979,419,914,282,107,412,45,661,644,34,632,655,528,423,117,247,302,546,452,205,509,923,128,374,262,559,655,409,549,442,150,846,670,846,332,527,262,743,710,355,845,401,354,439,217,715,308,949,661,717,270,434,581,395,417,679,77,137,472,819,471,403,59,132,980,551,357,341,570,254,387,258,565,901,112,424,120,954,242,163,440,605,222,572,811,336,285,434,441,350,640,388,952,432,251,603,128,291,579,979,356,448,65,313,209,354,890,384,825,600,568,532,583,181,323,831,601,861,831,436,230,682,329,408,646,944,114,797,762,170,447,929,839,350,16,556,651,914,659,609,10,611,901,162,43,562,13,359,869,200,418,63,844,649,997,945,692,847,224,631,948,762,81,410,222,886,277,415,973,154,474,941,143,977,386,651,983,595,884,176,645,190,604,769,287,810,974,404,275,172,225,927,589,922,892,753,974,956,389,296,769", +"858,597,221,858,356,965,70,442,222,596,94,3,510,997,527,804,133,448,884,810,675,314,552,653,294,370,19,163,872,486,965,397,244,330,303,746,371,469,261,58,567,95,655,50,783,352,70,511,201,954,750,220,527,875,970,618,102,364,952,698,287,980,755,130,397,50,361,247,583,710,720,748,128,55,860,705,849,886,263,685,486,343,179,207,100,937,80,472,86,394,806,813,54,527,919,156,611,906,43,577,923,217,73,226,319,200,546,30,997,308,522,553,844,154,558,370,378,480,41,197,363,237,840,968,625,843,509,407,560,788,297,354,425,158,237,717,143,173,492,635,21,603,800,230,619,878,769,296,222,361,574,37,499,958,43,193,857,258,267,667,786,284,752,449,264,81,235,690,630,580,554,41,105,129,129,339,646,87,201,816,503,845,938,799,995,25,722,679,754,317,901,150,971,791,577,431,638,677,68,675,868,341,30,179,753,704,182,766,385,303,752,88,302,345,253,193,399,311,711,358,644,810,662,27,111,273,998,167,330,807,486,522,669,328,108,348,935,332,948,110,384,344,715,224,713,623,643,895,850,882,34,679,38,708,263,275,841,919,187,252,380,848,569,722,910,859,381,649,95,941,655,343,441,635,816,198,514,858,20,250,214,144,406,314,802,47,305,309,783,113,687,138,268,5,428,948,18,641,669,52,906,52,515,625,407,602,988,408,143,493,335,692,895,32,365,414,279,308,356,758,168,447,236,34,911,285,920,393,686,590,534,257,560,470,271,333,460,881,89,12,102,151,44,622,671,102,21,155,425,177,340,189,466,183,582,334,961,441,417,363,304,401,68,896,498,347,644,998,323,247,955,597,836,438,644,678,632,669,775,800,296,404,829,506,184,471,771,978,720,270,195,296,340,603,214,250,921,661,161,515,694,474,804,251,467,397,387,379,706,578,106,790,775,243,922,822,464,53,974,320,800,411,788,966,864,286,808,101,546,637,869,415,78,681,369,666,1000,510,148,99,428,903,218,561,881,146,595,111,255,144,614,742,571,821,191,455,373,409,830,113,679,24,689,562,234,967,299,444,858,20,611,890,359,719,291,320,834,942,851,414,96,444,431,797,810,959,4,952,405,671,972,560,10,774,582,844,702,907,388,870,163,274,849,210,125,65,200,116,170,101,292,806,199,898,424,892,502,476,288,647,539,853,747,525,209,533,164,121,732,280,35,614,756,193,482,961,398,588,736,456,761,584,595,418,526,485,114,68,88,483,36,841,653,227,634,186,407,598,795,634,869,347,544,438,197,301,662,45,546,666,47,139,14,917,270,965,227,346,813,725,312,516,866,152,577,676,377,147,895,652,245,804,938,279,806,29,61,757,87,230,146,302,860,240,14,659,115,449,437,187,626,41,279,786,588,334,675,109,805,591,330,71,333,834,838,717,848,707,791,532,529,893,981,194,504,471,969,571,337,827,609,571,387,627,345,602,724,117,576,280,751,917,66,36,612,746,5,178,991,792,644,187,754,359,981,492,787,457,934,739,306,646,317,207,768,382,792,272,559,100,690,126,974,233,135,461,802,920,636,690,795,814,7,653,240,824,499,643,845,802,163,524,241,621,39,723,443,607,661,740,447,345,945,61,564,968,661,786,634,535,633,463,607,485,376,195,515,498,343,907,579,833,15,935,362,597,386,659,987,305,178,445,869,307,556,331,592,241,277,637,690,810,952,975,62,530,442,436,428,994,892,641,580,265,472,653,127,569,359,402,310,624,830,902,979,982,917,246,880,338,773,578,139,221,929,123,114,425,844,89,446,446,630,600,0,772,809,985,47,287,630,992,659,262,897,932,574,521,930,802,241,884,416,558,135,131,624,670,196,803,605,140,277,252,701,943,173,689,301,282,829,459,929,963,166,412,58,381,752,499,829,301,212,527,228,96,242,272,232,105,444,112,904,203,378,717,768,901,404,638,33,197,615,200,247,210,90,498,317,670,658,653,697,157,664,868,237,117,488,6,46,773,645,315,536,252,629,351,40,398,708,325,496,811,137,573,711,730,78,466,996,510,706,54,965,6,788,774,63,288,804,926,508,24,101,472,11,5,217,408,4,648,568,63,718,764,951,577,879,824,751,13,142,993,524,260,183,770,952,526,692,483,719,548,289,457,289,23,97,291,213,748,271,474,559,778,352,945,610,452,238,563,339,958,812,163,516,306,864,499,408,966,968,429,702,122,333,586,338,220,784,81,138,296,536,799,881,995,770,456,17,101,360,991,655,811,782,101,258,369", +"790,568,94,596,181,56,111,371,934,295,395,84,773,865,798,569,305,374,941,238,875,915,948,276,742,341,290,509,851,703,613,309,641,312,857,705,403,342,886,712,321,760,831,710,358,878,936,340,621,155,317,727,744,535,702,756,193,844,175,633,115,346,715,85,344,221,725,740,982,721,87,150,391,790,465,668,380,804,606,968,953,989,806,621,976,545,377,802,852,898,731,333,569,693,422,876,491,682,905,90,834,646,619,571,981,585,81,876,903,748,982,377,13,772,506,997,466,782,548,871,642,634,948,245,313,944,119,145,662,380,951,595,871,318,274,895,616,300,322,179,724,318,969,585,929,107,458,353,360,741,522,55,371,559,990,675,895,985,123,440,534,427,286,135,700,709,137,414,440,220,77,854,244,208,752,32,582,458,786,65,384,21,998,931,762,455,966,181,571,213,635,178,678,16,287,761,887,933,915,424,813,641,192,434,967,649,730,926,497,534,942,856,68,113,479,397,623,64,926,345,380,857,332,21,179,699,425,932,601,65,677,11,340,385,885,132,713,131,561,245,998,283,130,556,142,31,629,387,6,443,597,13,930,937,695,431,908,702,241,631,393,254,369,158,140,762,884,308,519,109,907,245,218,503,487,457,81,108,848,906,927,241,764,825,304,369,852,558,780,425,775,913,961,316,864,716,884,445,807,242,866,619,460,746,491,777,441,736,773,135,74,367,150,672,867,405,597,981,155,547,891,365,620,60,648,57,808,460,238,872,973,526,477,499,809,863,681,85,644,947,715,290,771,570,306,216,97,618,986,393,439,201,499,81,952,284,402,298,628,924,736,169,150,146,375,203,85,571,349,890,66,787,360,338,152,183,64,32,442,753,417,352,762,479,465,17,769,196,343,475,97,792,485,803,382,892,412,224,336,945,812,414,3,595,84,336,730,432,591,559,816,694,611,800,726,813,413,257,404,699,293,123,147,756,496,699,455,375,445,961,919,918,712,543,121,677,244,600,809,211,640,839,238,302,862,390,818,335,909,196,373,761,945,806,430,612,399,331,624,971,293,886,434,35,526,450,543,782,526,835,774,979,374,854,174,582,688,247,186,360,865,496,773,656,612,21,960,511,960,203,669,608,899,999,341,987,360,638,409,632,361,498,961,860,119,149,574,569,344,161,348,24,151,891,528,551,528,408,819,833,808,689,784,471,704,567,974,996,739,621,447,927,460,488,23,39,48,512,698,248,395,654,572,255,516,780,930,28,658,27,782,925,232,928,225,579,699,415,56,548,391,471,580,183,790,260,581,462,548,223,68,946,502,457,283,513,470,511,62,464,489,238,416,173,580,281,384,71,432,176,242,217,628,385,984,898,332,249,246,469,408,209,682,880,309,607,930,665,201,122,422,724,59,719,879,935,733,686,311,582,599,909,225,104,595,363,38,437,124,752,238,817,870,491,621,959,385,384,187,215,541,15,635,294,750,131,513,284,261,936,764,42,6,658,279,815,33,476,774,1,291,589,915,970,239,708,407,970,102,822,963,259,728,20,245,700,773,230,558,30,825,496,908,986,841,338,588,634,883,364,321,689,389,269,973,329,525,237,477,421,321,447,67,872,780,462,178,511,115,34,959,581,33,383,206,511,262,464,378,201,161,291,354,431,896,18,242,933,369,961,244,508,24,163,590,272,14,957,824,464,197,838,69,451,909,162,549,393,980,663,533,214,165,155,297,944,608,495,816,284,449,19,849,299,411,275,890,791,969,987,285,868,683,58,183,75,588,642,321,878,859,343,69,861,954,247,240,460,614,458,27,153,891,755,772,0,872,80,176,945,100,80,701,618,6,230,171,849,649,201,150,773,761,647,660,793,304,659,134,353,893,945,521,58,348,319,645,412,204,190,427,218,550,405,804,871,176,496,684,549,852,164,222,963,709,648,74,591,644,705,993,447,145,118,730,22,60,757,778,264,833,198,190,821,775,165,55,493,853,662,129,168,599,486,807,285,522,137,308,330,363,102,290,640,789,954,645,1000,472,235,79,490,177,76,314,920,304,523,240,432,292,204,508,722,439,212,167,466,129,777,638,741,170,233,882,486,452,782,281,463,100,196,113,966,728,286,881,493,550,4,774,15,195,342,617,981,792,277,282,834,545,119,110,412,293,659,658,806,300,243,467,945,448,524,491,834,435,336,662,348,728,701,976,328,178,183,414,500,631,704,8,617,770,427,518,459,173,690,260,960,724,316,737,741,370,151,988,83,921,869,953,343,193,916,581,20,3,50,799,366", +"268,640,937,439,864,446,628,532,211,730,893,166,695,153,733,553,998,987,338,279,35,660,465,203,67,461,481,638,829,322,399,473,121,991,80,222,800,435,144,768,912,504,303,685,559,5,548,365,398,906,615,522,187,842,664,835,529,242,265,202,262,47,419,138,501,117,88,596,926,587,154,164,721,604,185,816,705,708,842,433,328,69,294,15,586,741,452,72,110,358,328,21,303,706,240,371,274,70,495,508,609,873,313,305,827,749,298,973,678,588,645,685,316,562,456,62,785,644,27,908,917,935,256,583,861,382,143,690,366,857,381,102,361,492,427,652,244,458,157,974,195,200,506,193,19,576,337,760,256,525,544,158,811,136,432,849,552,860,809,575,573,722,98,361,875,764,591,209,5,632,372,151,994,578,752,151,463,69,675,786,614,671,133,164,288,290,222,100,38,901,67,76,401,331,193,411,866,789,259,378,248,798,501,78,578,181,61,128,534,260,542,519,366,243,606,125,129,962,709,499,774,89,227,505,499,785,400,873,747,244,227,119,369,555,216,687,386,724,531,775,354,546,54,803,279,373,504,341,9,708,955,642,388,192,435,711,721,735,90,679,780,924,212,877,167,464,524,338,706,553,173,766,745,414,118,705,602,909,675,745,119,191,657,782,904,404,449,186,990,670,386,618,573,953,542,994,925,747,481,945,646,452,520,185,715,151,157,211,754,242,561,87,124,244,40,323,818,418,348,557,828,653,951,609,887,258,242,334,967,495,40,203,466,277,566,449,68,765,751,338,21,226,453,74,937,611,798,198,171,837,96,288,648,671,926,65,783,814,593,526,862,51,211,536,407,24,204,52,654,339,635,795,278,237,832,759,709,517,516,875,797,594,231,871,274,287,732,204,598,110,721,644,610,368,870,787,804,948,748,646,116,948,336,650,999,491,42,656,105,206,39,602,54,57,785,793,83,487,979,431,182,509,607,731,723,785,994,688,640,453,869,875,761,752,834,139,24,890,639,519,485,33,615,109,590,316,64,562,329,341,31,137,847,23,583,244,549,851,594,791,45,888,7,575,920,67,828,371,278,985,54,100,745,188,815,311,544,143,297,749,761,764,321,780,212,608,787,229,376,2,30,769,363,73,468,4,438,64,523,417,198,590,745,399,747,14,424,670,932,857,611,323,929,746,87,136,829,458,888,593,428,915,976,975,549,229,716,442,283,994,49,63,651,642,619,704,969,832,852,483,107,731,511,223,236,5,775,782,971,820,599,729,620,463,478,265,70,546,589,686,208,236,500,362,268,72,746,308,548,932,575,778,256,556,229,834,570,943,630,917,407,61,298,744,9,991,627,960,189,210,852,583,989,805,792,859,801,95,586,390,880,369,344,867,115,399,151,137,217,392,2,325,152,586,149,648,50,425,699,837,737,353,974,398,258,949,134,741,900,918,850,941,634,211,575,394,583,371,957,668,671,184,557,419,773,449,502,489,308,18,709,83,895,980,16,708,969,418,573,641,136,136,134,28,487,379,300,598,424,663,833,834,341,989,818,558,801,121,776,91,150,426,317,994,862,172,35,553,669,961,192,544,13,893,10,533,68,669,20,123,235,464,881,273,167,186,532,704,472,880,216,557,655,537,681,563,822,546,843,129,111,944,697,497,666,82,469,83,817,644,881,986,380,586,404,359,858,734,125,536,228,122,573,454,29,786,146,1,764,985,102,479,289,66,663,179,511,998,127,414,696,689,237,253,894,522,545,721,664,79,644,761,957,474,122,65,706,598,792,531,637,632,909,462,631,176,933,64,945,277,702,422,478,767,809,872,0,812,949,853,822,474,363,632,648,417,162,882,460,218,473,304,156,794,557,270,396,771,294,936,55,174,848,66,893,312,346,924,67,646,601,509,636,255,148,165,176,364,664,656,196,387,748,364,475,357,283,765,147,546,914,722,654,151,255,685,129,317,424,84,691,934,523,54,796,713,464,655,430,596,363,40,606,707,747,866,445,159,384,221,253,550,692,830,849,443,190,762,275,126,543,545,450,185,369,822,33,426,253,684,588,851,335,692,964,71,659,588,689,300,697,938,112,986,154,825,976,275,350,398,595,107,850,866,111,305,21,374,141,316,714,21,911,443,96,79,607,868,952,750,767,768,19,372,26,78,691,956,269,289,387,301,635,849,642,153,48,415,376,500,839,938,193,788,761,428,434,590,341,887,222,672,287,875,911,120,60,804,301,234,952,474,686,970,223,772,926,275,242,564,640,667,649,726,247,723,541,799,761,637", +"176,328,576,930,889,9,694,871,423,969,280,566,695,161,798,726,437,402,749,799,865,355,662,638,786,210,460,858,553,566,411,394,434,895,878,258,123,515,246,722,668,935,81,267,289,251,846,268,769,244,507,633,624,592,141,458,241,711,926,658,114,976,9,422,604,728,756,333,41,984,521,689,110,176,611,871,573,50,946,950,187,626,494,494,991,28,797,342,115,419,993,46,88,662,861,561,325,227,514,60,490,678,315,474,711,602,395,724,564,448,689,570,20,104,107,543,598,880,191,746,571,334,477,106,832,205,121,759,54,781,377,488,516,315,527,185,314,199,189,620,882,254,465,7,394,166,642,891,202,698,714,705,910,42,114,106,128,293,355,874,625,289,167,888,501,843,788,762,573,299,231,930,214,568,497,577,393,174,496,659,162,945,168,317,649,10,763,386,484,506,385,968,250,600,880,770,509,804,250,365,568,70,640,971,224,742,906,887,409,317,287,679,470,253,930,551,803,366,358,304,979,791,656,544,229,53,544,861,394,523,261,15,945,575,702,392,12,611,801,416,58,35,375,865,49,27,410,249,426,582,631,650,489,260,51,523,261,359,804,559,426,405,957,483,536,841,949,422,417,923,929,178,104,771,285,866,739,640,751,480,932,575,839,619,161,852,683,520,645,563,149,769,427,647,375,131,973,810,446,586,295,517,760,782,917,687,545,156,223,925,176,717,281,418,923,431,601,932,858,671,456,367,692,516,986,96,33,913,684,539,343,448,677,273,446,425,542,729,314,914,164,147,783,287,532,969,373,429,657,439,862,573,415,339,743,35,36,195,464,466,56,348,621,627,111,793,568,737,347,874,877,429,128,861,61,569,756,932,103,15,108,903,525,696,405,817,732,549,424,707,420,619,768,251,762,844,47,357,190,295,576,263,468,311,683,69,665,351,331,806,861,445,710,628,14,48,167,463,957,895,737,43,219,11,14,837,702,401,285,290,235,705,127,528,266,148,72,590,114,136,487,212,113,519,758,814,113,224,864,773,396,435,896,258,132,600,444,457,808,436,2,299,409,172,158,338,454,482,723,455,560,980,811,783,341,868,834,889,906,641,736,826,389,733,794,695,144,854,649,60,723,774,354,146,955,322,748,232,84,315,329,580,413,404,875,377,234,529,746,586,414,125,761,212,684,818,764,205,584,367,767,97,434,854,927,589,873,464,723,904,2,855,226,867,526,894,876,525,602,567,274,146,345,417,697,400,29,660,194,973,967,436,754,515,294,156,270,305,98,412,470,492,148,469,69,852,950,155,268,153,507,713,344,22,268,163,183,353,14,158,733,486,909,892,474,393,653,747,74,469,886,232,498,696,360,794,968,865,854,313,168,417,432,35,89,438,291,440,726,333,984,783,414,687,259,398,713,996,13,291,706,244,180,692,248,953,950,883,49,331,663,425,603,235,667,63,675,939,533,235,232,147,986,432,382,645,515,397,650,835,789,52,985,876,568,71,394,882,509,950,44,234,710,698,508,409,229,554,72,879,101,991,686,352,973,119,419,661,776,945,510,88,865,808,28,918,953,827,726,128,686,706,550,477,147,314,968,177,912,738,917,824,367,201,355,6,919,299,505,672,7,500,632,418,102,677,407,31,606,916,781,15,668,339,110,809,179,364,897,160,930,274,929,3,454,317,393,581,464,423,58,120,640,167,384,971,575,261,36,643,31,710,912,944,833,259,409,230,544,793,392,482,262,306,721,879,765,239,298,308,521,389,388,912,768,679,953,364,44,256,211,667,399,92,598,359,733,902,599,881,715,572,662,487,985,80,812,0,488,908,543,964,981,126,258,753,405,892,225,657,442,903,663,974,796,535,977,673,63,440,450,472,35,192,820,290,906,254,484,146,415,836,113,849,107,673,706,983,40,901,862,576,499,759,892,522,571,784,447,318,420,263,199,52,551,646,395,632,353,382,779,234,827,64,440,123,955,167,622,447,822,810,37,11,134,258,86,520,900,188,342,117,545,796,416,927,789,234,184,215,914,968,119,211,209,432,832,977,244,760,37,335,311,891,383,913,776,586,223,72,455,186,651,938,654,700,251,773,868,605,176,43,699,500,990,446,579,276,300,570,632,512,729,907,371,775,970,254,622,685,777,349,211,199,84,785,497,340,366,498,726,911,81,716,538,54,233,775,925,631,242,185,86,864,464,885,572,67,36,491,388,700,813,321,965,966,75,6,760,189,615,277,599,527,993,632,960,65,947,202,238,419,848,911,259,349,500,684,603,377", +"998,932,995,922,143,568,514,618,177,926,764,850,391,43,253,341,614,637,93,870,50,350,160,152,35,862,485,895,363,458,240,911,429,391,14,406,505,394,945,253,543,632,496,399,584,824,17,258,412,86,495,660,823,313,430,989,717,120,877,244,785,350,509,755,168,466,272,553,138,894,858,226,39,216,137,799,900,217,469,359,759,143,53,649,861,630,321,980,436,297,100,58,58,15,571,7,292,607,249,909,358,372,17,512,251,27,54,410,854,61,609,612,397,853,256,470,114,601,992,124,631,827,496,439,988,173,364,892,290,455,215,576,671,697,100,435,661,156,619,34,705,709,471,420,836,739,614,674,780,122,342,921,150,611,405,815,851,494,551,778,948,766,625,613,505,570,524,757,282,919,341,907,864,214,280,10,3,661,242,612,31,357,41,406,681,815,412,616,268,127,266,921,35,933,751,708,642,226,363,90,857,121,462,26,651,233,221,487,454,15,760,422,944,256,526,516,102,446,523,98,725,816,975,129,273,331,962,338,132,220,404,986,626,813,999,812,563,897,453,439,485,244,336,68,446,328,225,427,150,184,338,689,864,554,866,217,250,88,311,562,570,542,380,621,393,848,531,806,288,121,881,597,122,711,301,506,587,996,964,96,616,621,274,349,41,374,889,30,245,958,529,758,515,199,723,521,630,593,290,184,53,242,672,966,241,20,95,492,511,530,366,550,17,599,35,732,281,462,45,208,315,253,723,864,962,687,788,256,623,318,607,465,396,927,111,160,801,912,727,611,156,111,529,302,341,992,875,917,348,852,448,148,989,718,725,863,499,502,460,755,53,497,886,412,295,79,436,671,504,371,861,648,795,358,659,425,532,201,247,406,759,442,723,246,936,561,231,437,902,914,501,372,792,18,97,580,776,565,569,793,460,489,633,407,16,198,789,470,966,830,709,347,676,565,333,46,868,934,620,469,231,751,163,866,786,658,532,964,799,474,220,75,146,396,895,792,806,557,999,91,517,199,928,304,971,409,287,183,355,863,509,356,876,247,148,412,706,793,636,321,558,350,598,642,485,919,627,151,794,583,338,853,773,357,920,69,829,9,865,913,586,597,646,157,596,34,58,682,127,72,829,219,344,287,767,549,264,850,332,315,946,184,9,309,973,506,671,743,535,349,123,876,729,98,602,403,916,591,298,607,925,356,226,188,387,335,901,159,398,419,764,613,280,422,960,222,332,559,635,240,508,574,864,825,546,870,942,598,736,752,551,510,86,5,29,615,194,980,442,161,153,441,63,420,608,463,59,106,861,966,307,199,956,31,304,960,297,262,415,832,176,561,967,858,75,224,569,138,906,201,866,191,960,452,26,533,121,131,407,468,834,571,51,623,801,936,432,753,933,439,501,872,130,576,64,438,668,368,746,712,510,299,998,844,514,503,885,459,919,513,788,772,925,193,732,369,751,997,520,577,401,712,962,23,745,363,6,464,164,577,412,111,749,905,595,721,764,963,161,980,871,916,321,357,799,913,214,159,965,943,116,232,136,172,268,406,195,996,723,60,918,306,544,988,497,849,566,215,625,523,514,230,270,821,944,716,370,359,884,591,662,258,55,224,694,668,104,4,152,555,873,117,425,698,271,727,173,97,6,392,965,493,492,820,449,744,838,410,11,92,137,921,405,641,844,806,703,172,951,564,110,617,608,864,913,319,708,803,434,649,143,371,719,661,333,351,297,756,347,312,169,934,204,308,879,404,403,59,3,849,733,975,312,126,668,667,581,448,435,172,451,101,215,821,916,756,142,641,746,865,972,518,712,43,47,176,949,488,0,543,783,553,344,839,892,40,288,298,359,645,107,976,744,178,656,283,979,518,633,908,918,407,556,944,96,846,751,953,634,137,144,62,617,459,735,675,817,638,521,313,498,85,731,447,169,365,149,503,320,448,876,639,237,571,526,571,962,597,802,965,346,496,554,960,433,27,258,357,950,125,715,809,139,777,83,199,609,28,838,106,79,755,801,77,956,604,611,560,752,109,547,175,914,336,567,596,156,200,143,176,132,221,234,627,674,990,18,504,778,399,194,216,538,370,304,479,432,925,839,886,596,24,536,38,727,384,565,919,26,500,118,762,363,265,867,250,587,159,713,931,640,615,782,752,906,923,51,115,494,172,728,65,216,742,713,340,97,266,11,448,928,967,498,954,778,403,989,956,399,198,132,835,911,123,323,36,837,729,527,206,584,231,985,75,512,366,67,515,436,233,894,289,255,27,443,11,639,537,150,289", +"811,520,751,316,916,837,117,852,423,313,231,713,891,573,327,378,602,698,809,420,127,805,733,515,265,332,107,463,572,470,646,780,144,716,728,884,258,795,636,116,307,663,202,332,472,828,818,940,398,319,631,544,751,335,306,729,108,959,152,551,860,441,351,199,166,150,491,759,168,602,50,841,785,815,693,630,844,833,827,171,598,649,250,78,90,804,928,616,50,542,733,109,689,808,306,762,655,8,821,453,924,289,197,655,252,206,773,972,975,581,445,19,618,127,499,904,922,353,838,405,899,298,980,818,378,553,288,559,912,853,361,837,987,701,386,137,495,3,101,956,379,996,508,286,904,325,185,596,788,183,648,29,731,473,803,527,432,333,146,20,594,382,817,366,355,738,279,671,14,943,635,186,368,998,94,792,235,651,643,526,305,850,238,8,252,207,811,622,550,332,486,849,509,722,26,668,426,208,570,120,416,697,690,54,362,515,217,791,270,5,115,364,314,197,71,206,19,608,430,316,464,825,578,99,841,217,150,374,158,726,978,593,64,718,651,163,184,934,558,794,616,303,689,585,4,536,309,342,631,720,753,593,905,418,110,332,236,661,347,985,166,19,146,258,279,129,692,391,442,832,831,618,611,633,641,505,571,431,606,56,139,789,78,102,147,587,114,264,653,465,599,749,473,450,143,849,507,185,745,937,54,416,325,910,849,707,307,206,306,214,716,698,823,24,314,128,384,478,425,975,562,117,198,564,816,230,828,793,124,267,226,541,442,157,343,516,171,622,916,447,424,296,5,259,258,278,702,147,769,375,527,378,346,382,544,14,286,747,751,244,447,373,706,132,280,525,728,958,18,438,306,480,183,955,641,768,501,359,675,291,96,953,211,460,804,524,681,460,567,520,905,249,308,559,953,310,668,208,121,712,333,726,373,241,629,797,497,855,873,165,537,729,541,620,616,359,150,635,962,143,888,514,830,434,477,769,35,891,391,609,271,991,306,380,931,5,621,774,891,378,715,328,488,837,253,964,383,63,841,406,463,344,159,992,711,920,77,802,499,228,350,933,566,766,817,722,428,980,290,915,870,633,920,868,157,507,142,543,119,83,877,95,640,265,334,569,666,786,770,617,348,410,212,748,383,697,406,729,370,679,459,4,742,903,146,972,304,565,99,983,329,33,234,978,179,296,603,82,185,532,334,291,310,876,412,929,238,153,520,11,429,648,168,928,810,466,985,988,303,525,371,567,120,757,404,761,56,904,571,910,777,136,483,696,369,54,528,98,23,273,347,276,863,31,296,466,438,48,292,3,716,730,485,349,477,566,165,721,688,532,482,324,967,393,198,412,802,428,828,620,233,132,325,875,404,304,407,698,561,8,343,707,649,522,444,650,309,82,889,946,48,127,58,550,252,937,211,465,644,628,54,144,511,386,63,530,254,722,189,438,392,290,19,722,881,962,368,539,228,658,70,657,152,832,345,620,740,590,207,668,49,341,876,334,496,198,614,70,53,191,843,12,928,359,98,299,326,205,874,897,307,770,858,242,398,734,913,257,947,121,605,180,806,950,917,855,159,515,971,27,554,276,33,65,803,681,595,842,354,668,134,992,531,317,880,908,47,240,777,506,450,492,119,3,220,557,401,997,261,813,502,918,817,92,127,211,953,408,193,503,831,346,596,149,224,8,585,408,808,737,816,882,87,812,505,515,931,427,70,463,783,833,524,28,884,889,882,209,28,202,743,370,137,348,878,72,335,627,974,33,670,174,728,153,286,287,786,40,922,910,975,259,228,48,433,9,71,706,813,291,64,45,637,979,287,945,853,908,543,0,915,757,102,954,566,244,61,677,829,572,936,194,581,281,386,353,990,459,228,374,502,154,200,600,872,129,327,388,332,695,164,838,847,489,887,990,22,211,972,7,973,512,119,151,824,669,290,232,242,193,767,459,82,776,777,637,975,573,427,803,419,547,334,298,218,233,529,204,979,251,294,99,90,967,899,631,440,105,528,382,437,322,319,995,978,2,399,782,850,840,682,310,236,755,650,846,297,407,586,419,212,869,220,506,830,309,556,472,979,49,845,855,240,752,849,789,727,512,377,493,810,613,207,603,957,151,932,902,49,824,642,607,903,994,654,20,459,226,15,228,406,677,133,702,755,557,164,330,28,602,565,10,397,567,271,61,871,208,645,491,39,50,101,952,83,393,389,190,113,639,701,627,623,853,731,239,266,465,64,419,916,924,936,719,198,338,742,728,883,601,957,366,713,342,934,80,953,76,889,768", +"987,288,235,917,455,211,617,992,250,755,276,735,325,924,947,690,270,566,60,652,356,507,435,799,75,941,564,55,801,938,850,468,357,736,922,729,437,508,62,346,510,733,320,779,182,8,373,235,827,151,703,598,90,811,719,87,985,317,15,779,254,186,731,934,579,294,699,635,252,22,879,193,6,832,887,245,12,604,275,249,338,172,202,53,321,170,772,621,500,729,549,303,831,927,230,826,760,552,749,462,514,64,522,142,866,957,259,236,912,285,880,948,542,783,47,598,398,992,543,205,445,403,89,149,617,112,127,916,997,316,852,738,1000,659,571,203,743,99,53,13,1,348,454,303,657,161,397,93,261,72,319,861,15,270,332,608,274,470,484,640,346,614,777,506,214,782,361,235,355,272,359,900,590,72,897,246,263,380,908,278,574,349,347,879,798,557,340,971,797,887,284,23,390,449,830,725,348,749,48,754,565,623,605,76,890,133,681,272,775,192,757,95,267,103,917,726,336,175,10,475,927,796,740,885,65,829,486,506,876,287,84,399,723,474,559,473,616,966,463,966,464,379,758,193,179,140,524,918,188,769,798,844,297,32,246,913,982,168,591,415,732,127,10,430,162,916,79,509,192,959,684,687,807,634,306,782,246,760,937,185,938,365,974,246,693,958,240,843,566,882,585,304,759,434,832,62,36,766,406,610,683,726,887,582,662,896,551,642,815,800,122,968,708,23,933,561,942,139,868,321,621,537,217,779,396,609,482,419,787,246,42,289,395,594,447,69,879,828,504,279,27,889,408,729,222,156,23,938,434,271,791,214,751,347,472,749,73,229,893,971,672,400,734,262,954,776,942,25,159,337,869,489,355,761,608,782,118,410,514,254,424,34,507,740,850,423,167,557,352,971,28,406,187,788,994,974,1000,773,553,557,203,186,916,988,60,81,21,773,3,275,343,676,857,716,850,909,108,487,678,452,599,20,227,19,951,39,630,532,595,805,667,732,504,702,342,881,269,226,692,139,961,845,618,967,184,399,818,419,431,751,136,169,778,701,659,67,532,765,25,211,974,524,355,914,260,475,440,839,894,220,550,803,224,973,269,555,509,578,531,662,74,533,344,663,718,592,424,152,912,475,908,995,36,887,661,489,777,117,808,754,423,195,584,100,274,83,683,885,50,234,186,46,694,529,784,754,212,378,303,440,741,412,487,858,949,888,207,714,685,702,251,591,623,370,136,487,598,387,266,131,791,277,104,355,684,470,612,479,293,29,214,331,953,88,445,6,341,235,74,487,982,822,131,660,366,163,807,180,565,370,725,756,673,575,53,673,206,206,897,737,275,881,936,259,456,89,11,938,36,394,247,599,964,725,48,846,62,591,200,260,248,898,958,444,772,580,480,133,721,239,127,592,837,841,253,792,607,551,650,817,17,719,100,161,105,106,959,890,90,296,316,523,911,290,977,308,854,667,552,11,684,490,916,93,549,674,495,683,493,54,761,73,562,387,589,588,400,944,640,651,927,48,146,634,979,534,496,78,466,871,951,991,23,436,74,422,215,3,921,497,350,473,342,658,113,775,587,884,274,121,618,585,87,724,766,782,767,300,618,672,402,206,606,588,81,224,921,852,516,520,130,595,869,248,387,86,847,383,742,59,670,268,830,358,65,102,363,411,631,368,460,577,774,69,194,788,369,832,758,292,550,885,411,348,568,590,758,368,934,984,73,220,894,73,152,573,404,974,479,773,273,830,664,653,743,21,332,68,921,891,607,396,522,478,176,352,623,168,436,847,643,495,167,352,653,331,603,826,358,569,597,389,706,419,630,100,822,543,783,915,0,612,924,640,642,532,181,909,354,456,752,336,677,773,605,251,108,967,283,342,588,488,954,193,667,865,482,701,265,284,62,460,365,684,837,761,485,526,554,9,793,949,407,803,18,61,441,346,385,974,792,944,524,693,669,722,531,704,944,555,174,438,484,344,131,744,740,590,674,496,852,234,318,559,479,788,543,722,453,582,488,541,180,752,153,91,353,900,89,150,685,81,948,11,130,927,43,318,710,721,917,789,78,774,846,165,770,331,304,785,70,344,779,717,565,387,295,357,229,71,121,276,457,945,817,572,505,322,735,520,654,634,501,521,854,955,420,823,531,674,939,994,558,635,601,735,622,122,93,925,48,871,325,351,827,863,451,905,544,373,812,922,721,168,526,908,982,785,895,512,806,673,629,571,519,276,589,699,173,840,143,789,583,156,134,456,690,719,816,143,795,678,838,799,61,323,663,159,926,584", +"130,663,914,751,731,865,239,84,523,791,637,63,714,692,595,231,470,702,509,678,400,200,460,359,926,613,719,813,972,748,586,887,441,661,881,486,330,599,138,217,334,768,522,594,139,801,318,127,534,357,837,292,541,873,474,190,352,139,832,98,674,526,44,894,213,533,365,263,496,183,748,651,83,483,770,209,432,701,150,683,855,1,948,614,991,389,434,261,617,998,413,270,141,295,689,870,725,840,645,212,231,573,343,643,839,142,656,760,589,507,88,430,881,718,970,317,274,335,664,162,373,516,806,825,529,915,524,469,101,812,892,369,118,955,880,155,262,492,280,234,252,320,419,340,102,310,327,297,823,993,9,433,104,760,690,24,835,71,242,236,569,421,535,636,958,470,858,74,564,877,616,611,248,394,990,962,919,302,537,707,779,812,438,681,264,213,79,879,440,51,901,881,89,221,815,676,254,273,493,80,783,525,66,109,591,886,731,172,693,425,485,140,216,703,883,537,536,737,458,612,855,104,439,822,549,592,344,253,163,587,28,978,844,810,729,188,884,131,359,655,731,916,554,651,70,395,765,306,403,213,329,874,952,585,949,968,366,401,717,489,987,819,64,112,381,675,246,314,154,448,943,553,720,108,945,41,682,924,389,767,575,809,715,259,366,683,598,385,103,756,771,195,554,939,261,833,613,193,308,329,818,62,96,616,379,294,876,662,100,148,318,862,716,90,218,817,738,687,600,725,553,363,813,611,153,969,702,399,345,811,972,215,31,611,470,607,597,352,892,187,562,341,308,387,533,989,541,760,980,714,91,673,92,882,310,114,689,764,374,399,661,984,418,152,225,904,549,781,580,840,240,470,423,587,846,63,906,723,512,749,82,112,91,564,833,415,265,862,867,236,131,956,953,48,373,286,120,275,590,546,666,439,597,324,625,528,881,966,362,537,681,114,328,257,82,67,545,321,318,327,887,656,891,957,823,280,312,794,276,118,491,534,714,692,736,7,993,115,873,268,306,16,62,829,247,482,339,612,695,151,912,960,756,899,867,209,605,212,182,699,685,631,71,347,233,333,652,486,72,354,254,788,298,507,834,631,554,430,563,124,407,577,925,568,971,556,181,186,237,588,98,21,337,227,97,919,162,471,680,998,152,213,229,776,548,793,878,836,50,594,766,26,368,663,493,443,498,102,685,988,517,848,627,172,347,974,393,10,578,34,21,727,369,481,638,410,476,838,857,224,761,736,753,526,257,570,741,645,381,603,974,759,457,726,572,529,131,115,984,171,831,685,522,513,357,627,544,740,955,549,80,51,966,846,198,228,34,517,745,705,157,329,874,734,839,490,460,611,244,895,570,612,418,580,233,372,355,300,853,98,986,836,354,74,931,443,477,302,781,231,758,288,742,260,113,843,158,163,725,672,62,391,257,49,379,712,397,595,338,67,226,755,352,834,580,544,958,825,365,797,513,351,149,542,381,494,854,236,349,422,460,557,791,617,951,480,975,388,738,887,41,99,795,976,142,685,889,331,447,674,923,146,575,55,558,239,603,931,836,401,825,819,342,879,678,809,910,11,870,879,674,391,193,765,903,120,519,189,816,396,749,988,195,881,700,276,924,123,288,21,528,535,853,575,289,197,532,507,331,457,683,68,289,54,647,729,202,972,590,993,697,648,715,596,23,480,209,46,82,329,138,491,910,329,996,405,779,152,539,799,679,194,436,352,681,558,708,605,152,648,912,662,755,381,128,154,942,140,165,450,177,507,934,561,536,332,53,706,620,163,562,103,8,458,699,794,511,339,93,987,954,766,294,914,992,80,474,964,553,757,612,0,741,779,31,989,230,588,876,161,26,683,653,154,770,140,331,622,392,752,755,7,174,28,587,504,658,370,181,189,616,373,750,119,110,780,932,326,150,34,513,752,738,516,391,87,891,101,368,672,236,354,867,215,835,749,284,320,86,590,30,28,757,744,520,158,827,725,949,546,789,390,127,371,157,714,535,643,445,111,172,125,515,3,338,238,430,459,671,666,844,511,709,607,43,309,744,149,617,511,777,745,710,638,452,587,394,264,504,401,75,783,748,569,150,753,111,233,569,972,533,691,530,371,350,555,705,861,208,92,866,380,646,517,211,226,179,357,64,341,875,206,580,646,727,425,139,531,337,898,90,576,889,789,488,976,125,516,795,816,633,558,598,555,522,317,484,861,320,851,144,552,36,482,15,31,12,277,286,752,66,521,238,147,123,15,467,110,259,780,994,195,587,224,8,82,440,922,524,783", +"307,519,855,203,655,280,425,430,750,579,655,627,929,17,4,168,190,848,593,119,376,507,638,134,927,200,932,913,203,35,173,787,273,710,149,177,79,740,930,523,685,531,131,844,333,595,192,676,359,470,637,292,29,270,145,161,550,538,645,425,95,26,134,149,808,515,538,165,293,566,416,642,932,672,357,470,605,353,388,610,669,411,66,463,215,293,309,114,371,16,930,130,91,970,846,184,340,545,278,927,446,763,760,807,661,305,877,983,80,812,818,815,86,790,942,237,174,108,138,209,887,812,32,336,108,905,810,101,84,695,389,552,565,345,15,878,434,454,742,852,646,734,839,293,808,776,762,998,55,151,802,776,52,459,790,644,622,974,394,657,831,240,59,979,139,69,640,324,83,393,543,248,356,610,10,237,276,8,973,582,695,412,834,682,186,782,469,650,882,52,483,922,934,848,630,351,773,393,88,624,111,281,476,429,159,311,582,713,180,225,229,9,880,172,710,813,878,720,474,139,592,234,101,817,374,160,546,179,883,889,79,729,515,561,652,694,234,959,575,641,68,465,100,766,603,200,657,920,394,940,348,634,847,751,443,992,234,796,744,322,551,859,28,195,117,479,536,742,102,656,811,413,421,802,916,561,485,432,544,87,501,762,135,686,58,718,835,979,349,301,166,819,629,913,417,348,541,677,565,326,957,132,280,838,530,339,951,123,467,465,900,176,507,675,200,681,276,984,482,266,297,377,291,638,959,512,228,581,677,762,165,698,973,586,829,851,502,879,439,744,626,198,650,530,489,584,183,926,890,612,103,714,581,738,873,149,845,318,973,988,136,649,458,187,26,522,346,161,915,733,92,674,944,690,291,262,344,896,351,308,861,545,608,811,263,433,487,517,175,898,239,312,822,185,345,40,351,376,120,35,203,686,356,825,818,494,450,446,247,568,508,342,637,332,722,480,386,960,906,346,570,907,170,577,282,974,16,851,300,318,828,290,488,494,769,761,57,441,5,44,149,925,926,333,925,21,526,571,913,667,358,15,959,70,936,596,501,34,901,61,614,942,280,676,472,722,828,288,143,208,789,841,254,851,430,448,52,499,163,583,166,575,676,132,503,209,970,86,642,954,277,173,64,78,71,181,168,221,136,266,914,668,831,934,33,310,525,468,860,658,284,998,102,707,148,209,587,715,57,661,90,244,652,597,53,785,140,369,769,347,769,190,715,610,216,183,787,757,172,190,687,606,450,622,37,955,843,886,390,550,456,371,173,848,54,322,138,445,47,138,646,162,468,352,999,15,21,357,580,335,434,582,856,515,61,411,164,400,698,309,533,153,929,237,839,937,934,177,18,833,969,642,356,280,841,130,247,962,207,392,421,244,550,844,362,861,508,155,242,207,918,669,695,250,205,786,233,445,334,621,658,199,488,798,421,432,299,9,404,43,948,692,277,619,890,557,644,726,946,75,715,315,259,910,314,790,392,342,716,746,879,224,194,988,312,818,897,870,166,702,429,450,627,352,242,155,153,10,4,321,794,64,729,248,557,280,405,295,619,304,530,554,505,239,709,761,23,810,577,211,714,735,8,223,880,443,165,875,21,285,644,250,147,240,203,997,584,874,968,217,876,379,169,93,949,63,194,245,336,385,391,732,155,16,253,973,936,866,313,399,332,54,945,364,477,260,177,755,680,630,605,776,388,658,973,140,33,917,945,759,550,924,801,686,774,365,131,727,998,685,67,302,636,806,786,139,921,791,834,889,145,174,829,521,764,96,235,45,2,696,609,194,529,590,136,959,252,209,592,158,418,982,535,282,659,701,363,981,344,102,924,741,0,1000,144,191,675,661,59,86,698,918,937,796,367,175,666,97,981,116,776,21,611,354,634,409,5,926,378,200,530,337,567,889,911,933,455,982,864,97,518,277,731,433,703,716,240,585,986,98,101,96,656,350,872,786,152,964,32,138,373,108,223,864,544,30,84,513,997,556,960,64,223,34,354,551,829,647,183,51,151,56,271,929,251,714,660,867,206,761,847,633,665,697,678,556,522,455,73,626,329,114,276,273,569,745,61,542,56,539,73,813,10,117,103,17,264,675,387,866,374,45,63,205,763,374,325,359,521,739,117,775,870,799,315,974,119,666,459,298,731,365,499,66,485,382,787,598,253,230,788,606,727,388,690,300,114,322,732,704,714,772,215,452,261,729,859,844,680,299,100,877,664,310,240,633,225,384,631,713,883,460,541,793,176,764,695,100,460,570,944,845,177,968,821,616,129,859,62,819", +"735,741,548,557,620,10,839,937,186,967,275,516,520,737,886,568,831,664,824,323,627,45,123,254,854,409,463,645,124,25,503,286,723,45,455,78,207,924,588,500,63,392,242,26,764,321,893,31,729,538,313,916,761,472,359,21,98,584,823,368,245,171,448,686,139,823,515,655,550,590,407,831,996,198,897,627,213,459,166,580,197,370,351,510,775,169,742,710,345,648,108,708,569,777,975,169,235,139,801,385,594,667,261,959,994,946,911,712,879,772,425,480,946,276,741,982,707,93,939,3,166,157,777,927,254,688,232,875,359,515,477,844,435,946,99,971,954,7,800,314,225,523,53,720,870,37,373,913,67,38,184,531,731,943,897,392,921,391,473,523,334,674,93,703,130,378,787,290,264,729,748,757,376,78,599,226,822,441,598,817,672,306,940,157,95,445,278,895,756,186,575,508,384,928,345,206,540,924,92,47,615,888,234,289,293,666,546,442,453,509,329,878,501,733,654,633,759,872,425,521,862,697,930,269,567,430,283,451,606,871,963,297,347,118,846,103,543,932,692,157,778,742,750,380,317,60,439,750,389,565,9,860,739,747,906,15,285,905,739,242,545,692,656,374,256,318,662,974,479,92,419,278,721,482,860,105,273,909,374,261,660,385,565,756,706,637,494,874,616,782,448,540,822,298,365,760,848,750,222,511,569,909,819,363,71,710,490,494,267,926,138,353,82,384,644,542,704,946,512,875,168,2,281,394,915,542,240,987,465,962,931,622,671,638,489,496,586,730,482,76,384,200,681,499,571,416,144,386,623,736,260,221,284,642,194,210,986,156,700,128,373,643,529,897,400,772,746,253,49,431,234,973,47,887,669,828,206,198,300,153,648,12,874,674,681,454,685,669,893,647,347,552,70,882,21,500,972,746,353,285,279,97,69,717,19,253,89,813,862,78,557,640,408,511,797,850,295,123,999,411,454,450,39,394,130,61,112,229,361,133,168,367,604,330,616,332,586,649,298,945,78,115,741,252,974,242,381,54,693,468,792,378,646,261,914,715,147,580,686,395,671,417,605,880,221,486,752,840,830,407,412,204,175,20,27,813,319,424,637,806,64,19,455,994,253,880,260,683,854,820,580,707,120,397,669,356,645,734,149,973,479,327,251,674,181,969,213,479,515,56,456,235,533,532,652,504,226,648,559,362,292,220,984,425,490,169,368,157,970,312,479,478,974,76,123,248,799,99,661,123,376,884,904,228,788,728,256,77,588,431,780,632,785,350,483,336,335,995,958,739,690,392,27,997,231,264,120,243,994,437,834,561,613,383,706,196,740,472,54,886,330,620,891,88,629,107,945,176,657,161,943,778,952,596,245,856,134,424,665,684,574,675,812,79,890,453,299,936,800,730,579,445,203,533,69,377,151,13,976,224,999,386,402,618,11,792,428,395,422,499,362,177,250,890,94,428,218,873,809,440,19,969,869,220,501,402,978,45,72,315,332,569,100,172,148,656,685,394,663,950,935,967,172,34,750,177,207,20,695,938,394,411,272,799,892,79,113,684,166,208,590,239,477,981,46,371,133,630,994,581,636,245,828,79,10,347,111,88,468,507,105,724,765,970,593,67,522,599,526,733,666,591,620,829,851,368,776,561,956,424,989,381,984,326,53,311,207,513,323,424,573,576,796,272,854,530,640,261,989,509,762,73,492,505,194,40,447,649,842,94,751,347,667,942,516,806,482,986,420,838,458,427,981,249,486,986,552,169,528,480,68,757,29,4,60,990,414,770,291,19,509,568,467,61,960,425,319,923,741,78,29,68,90,107,262,618,632,126,839,954,640,779,1000,0,295,125,777,776,406,413,691,957,278,963,749,629,801,801,481,770,751,891,756,327,700,999,843,668,141,99,240,168,859,10,234,528,14,963,387,604,743,386,872,92,201,690,309,581,356,193,78,205,909,980,711,241,870,722,882,824,972,924,458,994,853,220,258,766,720,641,661,697,116,434,212,35,59,321,675,41,274,868,69,798,978,739,415,670,995,295,666,967,978,121,617,951,169,379,395,757,180,77,252,495,178,157,103,947,713,239,101,316,729,345,647,502,757,251,141,121,554,33,523,698,988,903,821,541,854,203,49,1000,526,428,95,741,79,944,46,227,444,531,811,968,787,469,447,653,189,263,311,699,371,531,430,754,26,585,677,739,927,151,757,773,63,487,277,669,710,938,92,723,671,194,422,834,500,482,760,521,397,661,760,451,995,870,677,121,320,671,39,992,282,732,527,855,316,928,671,762", +"414,115,434,26,704,144,960,566,537,855,789,19,219,563,288,683,538,121,938,360,383,362,335,20,338,973,890,887,247,874,686,658,201,229,772,622,297,437,528,702,182,274,57,756,74,232,13,439,142,670,952,232,902,674,303,648,366,791,587,16,494,730,754,63,227,719,73,136,847,224,157,42,361,395,591,637,646,273,944,584,203,73,742,643,328,722,810,347,254,17,889,460,278,865,83,381,79,286,995,801,998,296,303,225,983,960,417,385,559,8,768,878,40,928,297,73,33,179,711,84,96,582,717,168,440,620,668,253,991,122,494,970,574,626,376,849,853,454,545,599,743,872,638,671,771,624,901,12,600,56,939,17,364,408,405,993,405,262,775,583,224,240,257,649,313,118,61,363,186,378,999,723,98,476,439,550,647,428,470,836,845,494,953,32,394,63,186,827,121,623,819,302,567,194,692,501,211,218,900,986,652,447,362,592,277,958,398,572,81,976,14,389,824,607,274,902,783,537,907,910,504,601,429,624,247,561,922,356,298,552,691,286,131,341,296,772,808,471,338,977,808,244,532,572,21,388,671,493,540,449,742,582,562,83,143,328,936,791,642,876,295,15,697,592,963,244,293,329,142,774,909,286,515,93,804,589,961,612,990,739,438,299,349,188,634,492,143,543,202,662,804,578,440,540,570,386,537,128,973,355,988,523,904,18,592,699,684,382,77,268,756,921,89,387,405,394,853,658,325,377,541,746,433,702,131,558,402,425,600,465,657,236,870,126,480,327,480,455,251,719,46,698,267,241,749,416,54,896,533,68,798,789,610,929,57,727,815,245,555,601,751,601,170,33,876,826,247,257,564,782,881,991,774,649,674,832,876,429,977,117,443,653,767,957,499,398,508,145,973,379,710,408,99,706,907,993,705,407,451,388,750,280,47,60,942,196,944,760,255,731,407,593,384,668,274,303,577,606,638,996,812,865,766,795,705,826,877,772,255,146,159,979,986,726,202,870,52,794,76,460,947,743,732,487,930,895,484,62,23,717,608,162,241,677,423,191,513,440,204,29,94,153,898,767,722,291,273,908,352,803,243,635,607,682,955,164,378,471,661,966,257,755,200,739,696,339,724,731,645,3,602,569,220,216,595,731,197,75,177,733,911,374,406,707,290,323,566,609,809,146,327,467,978,550,551,595,128,587,524,730,623,485,306,76,435,657,413,943,624,579,153,342,226,268,232,641,996,93,948,616,459,984,448,987,486,400,756,910,54,883,783,26,658,789,35,37,58,276,274,510,116,749,525,728,205,412,240,449,708,665,681,370,734,731,307,476,452,310,737,431,381,534,442,86,515,994,902,619,671,258,308,996,620,60,898,78,421,84,468,393,719,582,493,75,239,740,313,320,578,602,865,923,487,963,82,429,697,15,538,262,507,877,405,739,967,129,803,495,110,280,607,693,281,891,181,447,494,775,1000,402,774,15,623,251,737,989,900,615,747,231,204,103,325,532,585,298,497,498,161,788,568,394,777,14,826,58,839,688,185,338,870,873,809,50,176,439,218,582,754,766,646,537,387,739,736,813,164,76,126,120,167,895,55,180,291,143,215,478,255,942,541,575,660,29,350,5,924,593,396,670,943,201,865,2,296,376,877,663,373,721,706,816,428,862,299,107,429,756,855,456,917,219,232,92,337,118,710,118,518,55,888,734,292,338,728,918,414,794,665,550,207,225,948,316,734,999,567,619,230,55,54,313,932,296,219,56,892,407,98,637,67,10,335,629,894,793,543,709,501,685,356,52,819,430,626,245,169,239,800,247,717,72,698,412,897,6,648,258,892,566,642,31,144,295,0,798,514,326,574,37,923,675,863,663,168,687,89,815,673,44,797,102,509,963,520,621,149,947,889,519,590,413,287,363,15,464,69,541,843,63,791,624,624,728,793,85,970,570,206,771,520,707,262,627,581,84,204,554,48,113,684,62,804,365,279,954,816,758,579,677,559,159,810,888,545,129,802,750,177,74,966,801,26,45,994,355,23,262,737,210,675,186,417,944,732,178,760,301,867,618,562,559,183,842,430,151,261,945,380,143,854,505,178,798,273,91,781,108,730,264,929,438,239,145,400,727,210,83,79,717,78,172,771,383,695,36,662,587,24,674,161,154,194,486,279,611,118,331,307,554,765,201,710,375,752,362,278,704,177,513,847,661,173,692,70,347,548,131,333,630,517,40,140,430,860,190,656,482,873,492,104,846,236,806,994,657,467,299,224,727,714,713,355,304,496,85,529,407,63,991", +"822,152,415,735,544,488,52,711,209,424,636,975,296,943,525,906,302,314,389,400,142,470,919,83,930,902,331,860,993,654,150,537,817,625,762,282,91,601,153,808,563,490,919,878,993,454,79,886,202,747,700,914,877,152,420,24,601,801,431,861,134,208,829,250,238,755,937,980,571,940,639,664,99,154,146,958,513,277,527,521,88,961,546,695,438,720,231,6,487,747,323,291,648,339,868,310,391,829,840,66,388,616,292,196,808,902,404,251,408,863,452,249,146,722,763,65,296,832,796,509,820,829,322,195,609,949,878,952,576,179,304,705,603,642,194,396,655,319,566,491,347,640,872,459,525,719,362,336,792,447,814,675,205,795,937,194,756,475,298,805,499,808,330,697,413,410,72,177,828,684,773,487,887,57,896,932,980,305,364,815,136,789,549,784,54,607,401,580,476,203,26,202,526,72,944,787,789,508,593,509,167,345,978,371,273,393,99,849,232,545,416,439,43,480,9,834,283,643,248,609,465,742,410,216,859,765,225,722,597,492,816,616,469,622,103,179,814,590,928,63,98,96,151,824,20,253,688,15,903,432,573,789,344,3,602,875,401,296,482,437,168,269,592,603,541,475,792,333,957,447,385,813,605,792,111,634,25,440,256,939,298,362,234,708,654,112,451,252,906,354,805,32,276,15,64,198,356,834,98,201,681,683,940,713,860,197,83,501,25,622,815,537,54,605,445,513,880,694,413,542,362,627,489,491,121,920,161,953,335,361,425,68,696,928,772,794,500,335,594,494,970,111,806,619,111,640,871,351,60,876,884,477,768,35,761,686,254,570,307,872,595,998,698,449,639,84,54,309,94,263,490,819,538,486,75,387,312,516,396,176,903,475,720,515,56,77,867,641,560,209,276,58,333,23,848,728,616,654,86,678,629,514,676,727,275,461,964,74,677,74,162,132,546,437,854,737,934,530,636,507,32,504,475,475,162,527,512,940,561,742,196,383,46,647,678,665,12,34,735,867,638,362,239,906,910,753,375,536,508,434,413,339,962,718,861,498,356,337,262,457,644,423,161,952,761,391,242,277,549,545,623,264,199,718,642,278,829,22,546,328,725,615,276,343,72,438,242,462,851,614,927,264,883,796,258,254,275,825,91,516,688,451,392,57,502,62,945,923,100,575,775,628,276,700,264,273,256,892,209,487,719,806,269,970,975,99,543,92,412,51,746,278,386,816,935,458,799,331,824,139,441,243,524,773,550,561,266,200,997,656,734,607,550,798,211,602,170,905,340,135,693,714,964,445,995,928,55,737,920,44,781,701,300,960,17,605,71,359,179,115,71,10,214,834,850,262,58,638,639,888,74,603,466,662,420,64,166,964,219,17,420,804,722,525,355,666,345,830,131,317,906,293,237,191,911,302,337,298,454,815,809,503,197,548,658,215,950,314,227,396,306,97,66,982,855,940,707,590,110,312,13,284,865,647,727,665,217,79,881,383,170,195,714,637,655,32,629,763,673,384,645,204,22,937,757,136,228,944,184,515,518,164,514,46,438,342,600,303,421,262,711,78,596,12,907,947,993,245,663,740,537,848,475,571,5,469,993,201,285,417,587,562,711,873,79,121,537,635,942,441,732,861,590,662,424,318,377,514,890,918,466,435,305,279,468,875,527,782,629,169,448,556,816,183,603,990,630,466,885,440,244,151,637,633,711,228,718,320,770,253,642,311,444,127,531,419,14,397,698,140,155,388,606,248,66,879,424,344,176,789,574,646,975,422,766,349,430,150,58,710,837,95,469,973,2,486,559,926,518,814,134,195,399,45,932,230,417,753,40,244,532,989,191,125,798,0,293,840,86,659,968,162,795,844,954,443,93,233,703,169,593,410,150,623,783,600,490,24,677,786,552,899,447,609,586,968,432,117,306,712,964,179,591,343,931,46,458,444,544,176,726,268,516,535,724,245,543,741,973,58,512,949,136,602,471,829,948,493,820,34,55,968,804,384,899,504,528,14,362,244,805,984,284,413,420,50,119,656,564,361,182,379,523,889,727,764,805,726,177,275,939,486,269,953,125,914,632,119,35,352,749,230,165,986,909,106,936,299,8,812,59,980,916,125,240,909,232,116,838,223,293,296,310,864,505,135,817,807,552,820,293,990,797,344,66,500,759,311,939,557,126,761,208,278,372,583,983,766,788,458,517,490,331,892,931,982,902,543,587,11,112,82,180,199,798,103,229,996,178,66,645,422,668,957,134,333,588,745,426,946,163,502,276,168,554,781,553,737,155,515", +"625,722,280,95,462,270,415,801,209,872,585,336,231,830,488,121,53,756,774,792,262,254,733,823,45,51,622,897,781,983,443,881,535,459,324,96,430,4,58,991,245,377,885,122,633,41,821,563,852,607,498,982,762,641,343,517,119,550,881,818,390,645,402,635,813,306,588,740,94,321,882,690,692,43,268,449,697,538,63,670,737,546,196,972,351,634,839,957,800,967,902,900,94,352,587,98,59,257,243,701,550,334,64,633,578,806,540,104,732,594,767,175,518,322,235,918,272,844,170,626,50,650,660,415,624,980,290,444,341,757,781,319,771,768,864,998,517,273,192,665,684,204,26,257,238,508,180,466,167,324,867,278,681,801,935,510,774,810,968,462,740,510,110,55,687,370,180,521,907,903,291,181,656,688,880,436,729,774,830,407,232,977,633,220,536,782,70,975,56,69,639,979,598,212,532,766,847,891,35,296,541,26,845,757,658,759,643,800,822,507,646,176,651,995,22,83,70,476,864,398,778,190,50,104,800,97,811,181,171,614,299,495,940,70,645,863,558,772,216,333,649,539,179,1000,633,356,263,189,246,925,674,960,660,187,987,377,188,817,239,194,535,448,606,488,599,653,836,821,669,395,574,458,303,418,574,884,837,149,300,341,791,74,571,509,578,37,234,832,239,915,196,737,451,859,554,140,511,680,232,398,483,742,393,167,965,565,503,772,882,296,925,957,869,771,976,704,634,306,427,876,382,459,425,934,862,66,30,888,879,355,612,202,763,709,964,190,320,928,772,404,821,564,852,81,837,473,965,551,308,884,390,962,486,923,463,220,897,430,754,755,852,430,155,883,269,137,287,777,960,160,620,378,896,960,894,228,396,796,531,392,53,837,966,140,912,978,687,524,736,37,521,960,345,711,17,652,141,61,482,501,893,959,913,78,451,628,353,850,308,627,650,326,889,555,189,822,454,56,196,207,820,109,880,75,243,666,547,313,693,678,12,33,614,351,541,977,890,521,819,924,537,738,135,921,548,733,189,793,120,783,275,867,890,426,508,534,569,16,985,252,789,839,757,546,996,703,294,835,982,870,271,751,797,707,958,645,866,770,214,604,21,478,781,691,21,846,273,120,903,964,509,878,386,884,891,268,271,728,917,922,780,167,442,938,756,838,670,628,167,555,40,411,894,169,651,6,156,235,953,341,208,919,412,344,236,378,828,355,47,79,633,305,924,738,615,934,737,794,400,965,351,546,426,128,968,656,549,817,62,203,297,888,460,602,23,263,890,71,137,408,697,670,111,995,746,606,185,969,940,787,714,54,43,216,191,840,902,128,971,478,279,768,176,671,834,818,824,904,448,874,414,61,168,805,558,661,189,199,321,369,998,909,189,627,494,873,118,416,473,437,74,255,741,813,446,69,354,536,947,908,380,797,721,332,925,106,52,439,577,906,878,285,490,488,639,997,636,322,68,764,570,550,41,994,666,731,534,6,783,13,36,48,534,280,995,25,157,666,145,825,883,520,239,407,793,913,386,159,59,320,132,428,461,624,567,572,57,436,235,684,122,808,811,268,756,554,202,504,937,831,571,90,855,459,506,820,78,776,554,590,797,242,859,521,588,723,488,262,221,180,164,819,765,301,96,58,203,895,139,789,365,914,102,848,577,250,47,574,645,330,662,490,157,429,647,413,692,330,804,719,710,63,958,52,544,826,123,20,745,247,734,786,309,476,546,895,766,151,293,511,865,479,443,557,685,511,236,63,873,143,758,905,359,634,97,823,239,269,710,507,344,152,389,652,90,389,917,915,825,13,688,665,802,661,574,171,162,405,288,61,181,230,675,777,514,293,0,458,595,844,942,978,740,595,266,459,678,681,26,708,210,575,403,525,593,436,703,90,659,589,937,460,24,713,414,34,656,858,822,851,474,710,276,45,921,680,888,569,59,446,917,858,763,405,459,295,889,280,257,637,661,904,391,77,86,494,958,64,710,517,257,567,850,454,48,256,799,862,699,774,611,708,210,564,493,751,146,718,276,365,665,834,459,194,914,891,317,613,289,689,79,246,834,27,979,751,291,534,260,258,876,253,495,789,222,983,885,888,29,190,917,184,264,35,774,348,471,298,573,513,109,452,41,737,622,874,60,489,400,508,600,937,598,234,145,574,712,98,510,873,600,143,244,823,650,18,613,451,723,975,647,929,913,708,485,265,407,588,376,706,254,402,417,539,286,984,617,134,470,511,29,961,867,454,332,611,508,684,933,647,538,967,643,846,491,769,870,774,732,887", +"147,948,83,549,593,187,810,425,175,918,570,147,919,587,357,716,385,116,744,899,782,261,880,29,373,541,241,275,536,489,83,956,913,301,819,605,452,407,674,13,930,217,56,10,764,435,455,929,783,349,946,548,220,521,163,250,977,870,830,688,748,380,255,670,755,788,685,253,2,827,426,705,752,148,893,584,562,521,497,669,489,189,61,745,835,507,200,724,590,65,322,803,530,548,670,689,612,275,592,515,495,141,621,600,555,577,71,946,804,760,106,890,409,68,809,649,948,410,785,463,263,881,640,340,24,814,522,327,971,338,757,608,197,621,928,673,851,185,581,78,378,910,120,501,285,690,283,235,649,518,942,394,608,992,836,926,975,648,314,526,875,750,164,290,949,833,848,801,842,70,285,844,564,261,122,873,142,650,309,423,477,291,715,974,203,642,896,458,275,585,954,943,224,735,539,745,247,298,416,330,907,976,357,118,376,7,743,60,611,887,745,635,69,758,987,191,701,815,492,300,360,858,617,568,390,847,245,637,658,376,971,175,27,985,44,760,655,962,669,598,433,702,884,144,361,671,793,427,258,852,708,15,120,371,153,893,932,367,349,31,834,871,630,811,109,930,974,233,329,389,353,443,66,885,588,192,147,895,2,939,954,130,390,166,790,530,951,484,323,645,76,62,338,362,490,261,562,906,521,455,177,358,229,978,497,352,528,670,459,160,925,442,292,492,201,9,996,351,465,200,742,394,632,549,319,438,190,168,646,579,20,314,567,913,819,69,147,989,369,284,857,895,719,885,901,435,48,912,159,546,645,545,964,249,908,469,190,385,207,992,245,262,882,93,914,953,115,214,597,511,667,315,637,925,829,592,3,892,523,950,411,166,90,381,237,166,352,818,902,279,837,656,576,590,612,450,422,909,239,431,867,743,138,796,466,317,310,178,787,125,950,560,73,353,244,794,907,269,877,208,157,835,392,963,721,230,684,297,548,930,193,458,270,755,791,106,933,662,405,648,596,972,354,482,770,191,863,672,464,250,150,752,132,376,762,283,385,547,788,220,455,532,580,903,797,421,41,856,291,591,349,223,644,785,126,472,231,52,624,317,723,161,573,517,558,465,498,624,222,80,537,960,958,46,796,465,305,391,804,159,720,127,571,835,361,966,404,368,218,636,586,339,955,52,448,109,104,902,300,115,395,861,235,918,1000,925,897,771,330,909,221,660,484,542,895,7,437,515,114,647,586,364,309,953,232,189,142,78,479,883,178,640,874,925,230,496,730,825,913,180,945,537,581,219,798,31,178,156,59,626,162,439,270,124,135,222,529,848,752,859,581,643,570,526,418,387,22,608,926,882,351,210,867,469,677,940,300,701,730,34,944,283,906,289,452,465,324,452,182,414,860,965,286,625,946,61,563,806,763,607,627,363,367,137,646,195,381,945,736,980,97,497,569,813,846,578,278,800,166,775,370,684,877,25,911,334,50,748,982,253,232,957,215,595,168,149,34,410,384,656,450,277,44,267,451,607,715,699,85,582,819,109,382,245,177,182,689,214,959,142,123,139,496,617,270,260,656,557,831,583,583,165,468,767,882,334,606,530,61,152,926,597,505,822,137,905,801,58,714,643,592,841,550,19,476,298,107,824,78,818,54,783,491,641,917,566,783,67,247,575,662,475,271,238,418,684,296,734,272,147,969,590,282,662,941,407,387,917,9,653,984,652,377,213,330,120,692,202,84,78,9,513,421,576,721,91,534,88,778,263,554,635,609,737,278,175,582,18,975,607,60,98,480,664,933,945,500,797,219,710,492,910,281,644,521,849,882,892,298,677,909,588,661,776,326,840,458,0,481,535,565,511,69,3,146,978,488,883,138,131,717,363,219,214,515,873,627,76,490,999,209,754,273,257,17,741,739,599,134,794,96,374,858,107,391,877,236,522,348,374,181,73,624,814,494,211,15,552,31,152,644,106,275,853,723,995,556,323,70,590,295,461,330,721,604,131,300,275,410,383,954,127,46,799,402,167,893,362,922,122,290,370,103,714,6,57,403,188,924,717,44,261,751,967,23,279,413,615,504,421,254,111,651,469,59,473,855,416,616,673,900,988,628,670,267,251,283,428,318,647,763,951,272,769,693,604,622,751,792,39,103,487,966,813,807,212,868,166,399,696,799,724,517,550,869,988,45,556,63,770,686,618,787,159,630,562,930,724,156,822,262,490,468,985,872,220,310,300,197,955,450,290,226,281,790,798,793,551,651,916,893,29,679,752,185,682,432,847,292,891", +"210,318,405,702,295,147,85,70,10,643,294,654,943,55,280,168,191,121,208,372,112,507,21,744,16,100,155,370,759,168,749,980,910,533,845,440,651,468,97,110,169,76,231,297,96,898,624,472,624,867,295,934,170,958,67,469,286,816,380,914,430,550,137,135,297,249,331,290,523,15,24,785,773,619,877,478,109,369,624,106,73,767,123,627,908,813,578,234,628,575,774,770,19,567,779,794,655,995,92,767,844,431,461,443,615,263,927,386,225,509,693,488,555,810,420,866,385,177,947,254,185,402,487,406,956,563,224,407,534,241,432,4,104,94,564,663,451,35,491,217,292,454,879,497,41,72,875,346,772,710,800,157,474,840,398,804,682,57,347,236,854,833,578,307,647,648,203,673,970,32,737,445,185,984,306,934,302,410,17,477,761,710,880,758,397,431,761,64,328,267,630,586,969,878,814,648,546,181,410,289,879,815,113,747,424,28,707,51,309,506,580,381,273,262,488,433,965,256,784,913,842,548,404,643,16,554,692,110,289,950,81,136,894,182,837,533,692,479,921,396,401,109,315,653,767,46,66,96,430,441,361,94,358,446,701,322,125,773,805,312,1,275,566,314,456,136,892,584,577,979,492,469,857,930,183,117,132,750,255,872,551,309,697,169,136,350,258,732,577,207,419,637,243,365,786,811,405,766,760,153,160,504,487,714,244,889,752,907,266,302,86,800,300,394,670,433,741,541,621,474,763,822,540,354,486,128,751,356,872,559,561,239,609,834,739,338,325,805,344,610,482,231,135,763,218,272,94,160,491,110,94,429,846,553,52,763,570,374,719,987,878,709,752,192,682,650,703,571,811,219,158,542,820,929,634,301,29,558,637,647,664,216,572,778,347,239,564,932,317,733,296,94,547,277,18,53,468,567,854,980,457,166,246,826,777,527,665,915,997,236,334,415,216,60,659,743,814,512,650,500,889,999,752,280,477,689,560,76,596,365,983,533,847,100,97,230,732,178,527,935,347,784,286,305,579,273,139,529,795,712,281,858,141,107,900,58,733,986,700,974,891,8,877,28,447,788,303,573,698,477,289,744,805,872,91,627,488,256,625,317,306,736,542,244,259,294,401,82,48,468,452,172,24,248,790,266,59,257,433,93,568,365,26,597,498,475,293,664,923,364,353,461,191,513,69,588,864,895,412,100,202,535,374,327,631,319,786,978,963,39,775,564,214,910,831,218,760,27,502,419,828,681,297,493,715,289,339,958,708,932,386,643,242,741,204,184,173,502,866,988,478,608,849,873,375,235,815,594,6,244,469,229,508,407,170,955,89,169,946,764,564,303,535,155,372,660,771,221,978,203,902,24,672,777,521,496,514,313,652,493,956,914,273,868,43,348,578,618,831,62,394,673,577,254,258,703,748,931,256,764,728,29,367,614,191,394,706,25,935,946,490,281,881,884,605,323,442,346,315,738,307,877,224,868,537,4,899,104,596,494,254,91,957,868,183,229,538,119,182,638,86,54,184,119,151,698,680,953,480,880,824,147,470,383,164,80,500,197,119,495,640,159,84,657,510,720,752,314,187,967,166,796,842,338,869,208,872,8,306,302,77,842,436,339,972,465,224,367,991,300,397,986,825,288,528,220,971,709,405,170,697,748,308,480,557,441,536,622,946,113,264,549,642,371,798,362,817,42,448,132,173,650,714,200,404,548,675,228,772,19,390,196,767,433,114,442,15,866,393,259,926,240,519,32,620,503,463,790,989,186,385,435,484,570,298,855,947,154,13,600,154,54,257,119,675,88,446,236,420,416,312,936,810,34,930,649,460,225,359,829,354,876,59,406,574,86,595,481,0,679,679,315,281,545,548,229,377,486,827,78,282,716,510,886,41,308,521,986,200,878,67,46,91,310,724,527,458,88,371,57,239,695,735,212,897,486,241,693,838,708,230,987,193,357,584,971,476,834,449,894,797,73,255,401,681,251,849,447,236,683,544,783,194,386,746,173,566,41,574,243,230,622,314,146,908,367,688,3,825,287,662,295,996,484,190,791,380,532,427,65,45,467,805,349,221,143,404,328,630,270,238,986,213,393,12,486,244,830,340,646,378,363,485,489,111,137,594,23,410,723,458,586,169,107,649,645,959,123,505,258,961,133,542,828,776,609,56,143,589,611,641,543,637,68,481,154,287,370,914,565,719,942,747,186,220,296,593,533,177,918,873,393,872,875,435,86,70,124,531,24,905,81,660,612,476,632,887,106,645,351,698,528,527,535,218,991,904,143,166,81", +"875,60,104,424,507,263,178,50,997,808,174,895,860,334,137,708,718,779,113,925,316,265,483,68,645,147,105,990,538,602,424,380,801,612,435,597,708,304,187,740,230,385,693,62,478,904,106,646,543,59,780,52,222,491,285,846,211,767,987,898,830,7,284,479,363,888,926,216,284,95,510,354,276,200,40,550,707,691,423,212,766,161,908,147,58,270,686,62,723,376,838,349,118,151,99,101,139,30,293,361,347,484,792,729,538,68,986,538,431,723,947,232,287,349,941,205,597,564,666,444,433,595,628,772,526,888,642,669,876,494,442,891,769,166,496,935,205,469,158,23,162,154,752,255,634,891,286,157,380,156,479,262,469,356,688,417,553,442,566,7,186,339,664,854,192,772,926,273,491,79,660,883,215,438,353,811,123,370,398,74,977,947,214,60,144,281,661,99,12,316,53,9,812,610,999,190,964,369,182,754,247,677,111,48,424,129,158,991,519,681,793,184,646,524,264,765,323,290,757,866,983,639,924,123,707,263,554,192,701,833,74,188,767,388,951,192,407,863,127,871,734,473,390,621,748,960,261,354,786,805,746,694,567,544,612,347,827,164,920,499,886,858,135,398,164,175,531,862,618,330,408,319,783,136,76,646,942,191,959,323,480,975,197,90,954,29,97,51,661,36,961,929,902,843,589,88,579,655,425,694,315,793,525,47,962,322,513,401,919,221,447,445,979,348,382,575,759,877,380,342,194,530,158,108,682,709,129,113,304,936,6,868,162,602,353,649,877,669,300,625,270,44,346,48,697,156,700,912,56,55,861,610,272,743,166,120,120,250,343,174,592,312,959,93,29,486,845,53,55,767,197,144,580,288,173,489,781,335,150,137,266,688,353,545,392,62,53,949,786,846,302,759,342,25,689,860,571,635,855,671,924,769,479,821,229,590,578,783,341,761,163,218,550,714,236,920,125,747,317,950,672,406,702,565,690,685,176,450,330,647,502,962,997,929,392,365,907,308,959,42,269,360,264,781,283,794,797,516,568,430,235,274,726,58,330,171,541,81,804,167,677,463,838,526,749,68,187,285,678,843,529,424,386,198,30,897,280,340,944,424,326,569,141,369,337,645,925,892,815,74,149,604,263,819,209,596,965,737,106,829,78,561,332,325,886,986,7,683,299,29,668,223,673,190,689,551,601,183,436,971,600,339,651,763,537,582,593,767,495,814,497,856,457,581,846,956,636,622,177,30,992,976,231,462,65,614,350,637,541,239,442,186,548,204,805,364,976,387,866,949,587,80,39,254,121,243,515,28,191,694,314,576,311,378,103,714,621,28,784,888,370,31,357,276,853,964,261,426,312,576,120,892,14,837,250,294,116,330,909,627,49,407,154,206,497,887,497,452,558,18,434,908,681,239,880,6,273,541,534,977,943,472,298,864,219,452,773,449,857,501,631,29,952,185,632,165,12,720,842,257,59,983,340,602,42,114,29,301,911,220,266,407,601,66,204,361,835,326,384,927,545,857,26,431,178,273,305,828,104,270,12,574,554,346,526,306,631,991,318,595,729,69,819,154,830,387,155,87,49,936,326,580,143,880,342,608,711,708,153,601,34,91,161,468,779,261,877,310,691,990,349,439,293,418,670,431,809,294,335,377,235,939,573,874,254,364,450,98,102,70,605,656,996,453,918,708,989,174,919,491,885,332,861,649,20,394,279,375,221,712,811,517,705,586,342,680,480,805,892,924,759,203,110,640,477,200,697,395,316,663,503,948,864,737,391,210,969,798,463,314,727,940,449,242,714,405,912,949,287,712,650,999,602,632,802,201,218,657,645,572,456,161,86,413,37,659,844,535,679,0,771,453,693,31,182,762,56,473,421,81,684,840,365,392,107,787,369,919,966,932,291,515,827,502,37,813,171,370,369,686,159,866,24,948,5,462,286,695,94,785,306,421,450,287,663,875,465,846,356,249,584,628,595,711,469,984,20,999,39,108,583,393,810,230,84,930,282,557,371,13,66,681,981,659,589,880,992,479,540,796,496,675,951,72,961,635,525,33,599,2,562,255,968,760,169,291,38,35,705,968,121,795,588,222,594,207,686,437,43,287,944,764,200,658,57,382,173,92,44,590,167,957,102,14,291,87,329,810,655,129,953,782,568,131,288,234,253,952,963,192,874,960,367,187,275,262,851,960,130,622,813,545,15,628,714,458,312,804,864,227,64,952,187,103,891,548,107,267,285,817,290,939,503,808,817,455,751,537,480,258,55,632,584,306,308,207,706,118,848,104", +"778,973,197,479,389,664,937,711,640,577,692,748,999,762,829,933,833,768,196,721,36,475,187,444,934,307,789,775,994,462,905,845,296,695,483,961,274,399,648,440,649,559,565,255,980,233,901,866,261,665,378,300,446,669,868,557,694,749,234,937,941,348,638,846,18,83,418,882,207,638,536,211,317,683,747,872,11,267,150,58,199,164,346,3,189,457,141,139,302,695,539,1000,632,288,747,483,552,387,122,34,2,166,872,26,934,649,506,65,788,150,89,881,433,717,911,70,336,336,645,272,277,844,791,751,589,538,200,313,72,342,134,951,786,978,570,504,312,382,995,243,882,430,505,803,33,229,591,390,373,475,427,389,354,517,709,72,610,838,673,720,189,331,562,152,610,613,382,939,273,972,502,695,286,525,149,958,896,794,523,262,998,310,306,390,326,840,994,780,417,787,295,51,646,154,127,471,974,714,756,124,86,79,860,570,721,555,604,271,865,57,410,381,336,372,612,255,661,580,517,845,580,217,770,79,112,874,190,696,555,475,663,170,489,713,319,869,70,10,555,717,945,442,271,463,108,345,883,53,957,654,468,927,304,255,813,122,236,603,929,106,303,931,835,61,119,225,484,37,274,19,518,706,886,251,750,376,335,475,504,202,287,71,822,610,759,862,613,855,510,634,758,191,712,486,750,561,876,808,269,379,20,75,629,243,228,219,727,452,230,191,747,86,53,457,469,747,130,229,614,691,574,507,400,269,44,149,159,908,528,931,214,246,39,531,659,975,567,854,18,441,151,315,378,772,150,506,963,581,898,575,565,555,636,96,550,165,153,112,110,152,397,605,975,939,854,473,734,856,291,395,421,403,394,788,587,369,428,103,44,978,553,243,497,264,933,883,241,91,176,98,715,157,526,174,80,654,597,655,763,199,618,956,997,667,732,753,64,407,820,430,442,739,285,861,182,719,719,587,546,865,116,677,667,754,94,169,342,116,711,116,579,684,102,448,408,578,968,697,711,969,721,308,890,449,197,71,484,194,977,242,391,326,54,27,561,438,899,596,738,238,876,995,224,545,259,599,252,511,607,418,825,426,577,299,348,433,603,571,780,272,516,413,495,210,912,346,623,911,529,286,397,601,931,639,771,189,141,263,701,717,321,291,538,901,522,77,756,927,480,201,251,729,199,337,498,485,408,811,621,840,827,969,715,277,497,641,217,934,12,410,329,821,742,289,402,624,378,306,768,229,736,543,188,6,51,223,346,144,806,559,896,681,873,356,801,651,5,745,299,603,183,993,719,715,304,630,977,491,445,185,606,843,638,628,934,869,360,607,913,450,222,544,19,560,162,625,895,976,829,84,870,946,449,96,392,496,655,944,921,383,588,510,503,737,627,672,999,203,452,435,217,133,412,59,422,268,427,858,716,938,127,114,197,868,646,478,677,127,553,49,929,232,971,893,550,920,976,670,815,849,958,609,276,46,787,707,512,887,106,391,194,230,987,254,436,263,310,358,216,363,363,636,593,916,699,887,939,497,941,786,621,547,216,627,91,954,124,349,500,819,786,133,758,238,615,78,4,224,283,860,440,470,873,270,78,718,178,307,459,904,108,526,433,773,202,669,557,679,293,91,338,819,173,561,816,444,562,143,384,981,810,142,810,12,74,450,463,815,107,252,988,317,915,684,985,836,771,313,738,622,72,836,973,853,434,509,90,70,664,469,117,594,533,232,592,793,76,976,518,291,42,342,587,353,962,115,776,949,792,303,235,526,107,898,296,145,138,271,557,45,891,825,731,171,736,33,345,428,748,450,573,837,938,655,241,150,473,442,107,936,752,26,698,691,923,968,942,565,679,771,0,184,922,612,389,439,682,140,666,488,55,756,907,23,832,580,272,293,579,333,860,50,694,699,158,697,922,136,324,762,672,788,752,363,790,293,706,272,141,233,661,328,710,509,725,182,101,616,822,950,754,574,525,570,259,956,228,223,210,97,478,442,845,952,298,294,926,825,238,655,866,237,4,630,670,109,993,497,60,755,145,761,497,40,856,440,536,206,553,60,941,843,23,675,57,617,835,187,411,265,912,598,167,202,681,500,599,887,645,659,196,442,944,401,487,800,675,719,434,491,542,665,243,607,842,654,564,427,653,588,614,136,886,339,46,203,876,329,700,770,260,474,784,438,453,50,701,817,92,248,430,653,278,999,94,354,409,292,33,555,358,53,86,797,582,21,770,928,515,866,203,6,249,506,534,397,329,369,164,719,833,419,218,647,548,516,952,293,350,50", +"175,239,213,674,530,695,760,828,328,723,54,3,258,122,280,669,537,898,357,496,148,246,653,575,330,10,319,824,249,732,532,988,166,962,302,959,821,650,646,991,381,789,974,747,92,121,432,15,333,491,898,277,318,351,402,672,765,381,955,908,768,277,816,724,37,369,57,566,392,77,530,63,629,944,454,212,547,999,156,204,532,571,798,362,129,788,80,150,118,836,131,477,931,507,115,29,384,552,674,232,667,292,786,46,684,312,789,471,835,986,399,724,376,44,88,892,639,546,833,323,616,64,633,525,85,57,230,361,517,349,296,853,262,416,864,41,504,16,776,318,202,474,807,843,700,231,378,493,954,616,153,170,202,724,723,229,52,922,915,956,353,580,352,641,357,207,671,144,403,756,697,826,431,423,695,116,604,500,601,790,323,381,820,553,64,3,894,575,788,152,998,717,394,718,355,887,565,410,387,77,554,185,956,299,484,41,863,628,409,14,458,751,377,442,910,329,713,116,21,777,357,250,634,237,908,846,191,162,344,306,446,121,15,319,937,253,580,729,399,50,229,145,491,367,991,641,89,890,368,599,817,599,875,252,658,75,927,845,433,200,655,511,393,657,202,282,586,299,788,709,914,727,232,72,610,809,206,513,818,369,973,559,532,426,199,115,324,621,382,50,471,60,796,135,791,802,148,228,814,76,725,924,891,521,337,190,315,268,236,597,503,42,379,613,352,782,436,138,237,575,393,322,52,230,155,578,611,606,920,130,156,818,401,290,3,763,604,21,668,558,547,629,342,658,535,626,152,512,653,294,793,958,177,835,736,375,698,322,926,154,166,300,647,741,437,50,984,140,615,636,437,271,748,634,191,223,476,891,43,286,835,452,173,876,795,72,956,16,671,896,185,822,679,306,232,962,234,506,978,723,93,270,881,67,298,411,981,548,232,791,866,705,26,552,127,959,972,552,855,977,193,270,1000,690,585,811,899,423,120,99,598,690,516,176,809,367,631,656,421,242,895,95,476,697,544,849,276,992,30,648,261,485,815,581,436,265,709,154,508,420,271,870,847,348,572,195,204,797,147,933,248,484,651,411,317,270,276,984,961,736,495,494,908,604,635,228,603,627,316,325,424,416,501,121,538,85,548,522,738,889,118,453,111,412,291,656,570,297,687,733,478,264,740,911,800,205,14,62,704,159,958,370,537,501,879,376,216,431,72,207,593,514,196,575,813,328,76,32,995,809,432,795,18,602,96,416,818,479,784,63,742,596,532,493,435,203,82,906,971,907,235,566,370,886,78,425,856,110,300,476,499,557,137,437,505,742,49,623,236,646,602,938,938,703,836,686,54,158,678,23,209,378,476,206,391,493,967,287,28,553,282,62,694,762,501,27,907,750,813,763,847,530,188,455,830,156,32,947,415,953,659,537,794,611,354,603,296,514,104,600,586,774,656,929,892,94,406,423,863,325,735,633,858,340,433,174,143,595,519,318,634,277,938,72,361,770,339,330,602,40,96,564,912,583,763,113,724,910,406,149,122,899,877,382,514,920,435,843,685,387,489,992,4,908,439,431,29,787,368,26,82,570,212,974,623,607,701,29,688,769,695,12,553,149,390,977,123,225,430,893,151,484,359,554,626,402,343,164,457,444,855,895,581,954,441,984,119,932,351,779,693,217,389,789,187,149,930,373,899,176,530,586,86,865,953,612,622,177,389,271,835,500,522,408,287,911,146,226,480,179,375,894,570,30,28,686,879,702,575,727,284,780,443,124,349,43,407,966,974,722,229,891,789,621,365,544,50,978,750,845,458,276,177,528,884,773,304,903,976,194,336,683,918,957,675,162,978,511,315,453,184,0,542,835,918,528,113,448,163,116,710,825,428,606,714,566,619,886,454,188,524,565,908,873,752,498,733,895,919,844,453,370,932,897,99,761,581,2,302,945,432,411,988,139,845,241,25,105,909,279,767,577,793,870,501,25,747,962,139,884,190,610,160,475,186,443,142,313,986,575,614,571,707,910,480,262,171,215,999,142,525,522,214,775,193,304,662,466,913,942,565,549,149,624,609,526,134,590,916,421,825,242,453,578,343,817,762,897,483,376,390,168,197,475,849,654,475,568,199,503,234,567,470,504,442,899,528,843,686,93,11,901,42,318,969,407,458,475,51,313,505,873,973,437,755,771,967,529,221,686,366,133,62,334,654,233,980,419,595,590,544,102,449,867,544,401,429,348,107,619,419,869,992,306,134,492,784,426,35,600,530,56,89,619,133,869,185,48,764,325", +"388,488,852,86,650,592,98,727,917,31,25,638,119,419,511,338,936,821,404,820,319,879,38,442,796,494,144,239,653,656,507,406,188,34,754,625,780,889,856,448,796,673,852,425,493,130,793,355,215,544,23,135,940,833,896,428,346,250,33,473,590,247,399,732,142,662,760,600,545,764,445,870,483,394,362,245,272,330,144,829,249,463,89,422,559,734,996,973,865,669,408,48,921,443,870,473,941,991,651,568,631,417,67,938,129,991,832,621,225,974,161,405,644,957,925,557,40,385,277,580,651,2,133,892,554,99,420,954,84,476,320,577,259,501,176,308,920,990,392,256,549,58,486,266,63,359,98,607,38,604,727,227,770,250,931,893,153,900,335,924,359,493,570,150,873,279,806,880,950,761,899,30,36,807,834,147,355,369,495,860,444,74,304,286,421,937,585,702,14,784,15,241,114,871,326,919,621,243,968,680,995,578,395,780,174,770,783,222,657,215,613,573,244,395,800,937,77,139,144,756,255,275,686,965,400,41,666,104,433,970,383,41,543,402,228,466,505,385,365,804,673,266,772,614,274,589,827,508,991,66,120,319,627,226,754,337,989,350,57,430,335,329,795,189,560,813,204,389,359,947,300,328,338,174,208,496,228,709,22,580,488,173,891,815,34,735,602,630,503,631,669,385,140,899,650,350,534,815,494,261,565,816,622,488,909,228,362,141,841,629,161,353,844,122,379,921,548,935,855,258,688,278,21,371,138,5,587,426,232,547,5,98,944,959,231,336,29,170,538,274,236,20,830,542,547,193,661,667,681,686,297,237,504,887,186,373,717,755,478,277,168,734,40,433,96,934,708,626,480,477,563,167,575,573,875,801,782,259,171,221,380,20,38,223,392,115,624,601,812,8,448,415,776,956,158,372,219,124,979,785,248,620,497,815,269,551,335,560,830,558,36,357,71,111,902,172,876,66,550,168,663,271,308,302,6,15,715,406,720,478,955,965,551,711,911,934,650,498,176,893,785,541,443,606,329,518,218,579,472,439,152,110,200,568,743,498,514,455,343,850,708,278,649,310,778,629,696,435,128,909,511,245,31,584,523,830,447,700,865,112,801,586,316,117,886,402,98,848,292,436,843,279,311,816,501,758,118,438,833,8,699,672,516,109,208,742,89,523,711,129,5,424,356,290,189,420,55,581,268,322,505,15,991,730,11,639,205,873,42,967,747,128,92,365,605,19,21,556,753,264,282,98,898,290,371,207,566,693,164,656,269,669,949,642,528,823,645,102,71,166,186,51,604,857,48,872,934,267,388,259,934,26,533,273,858,520,588,371,3,861,655,108,758,605,348,281,552,651,377,861,136,620,468,387,462,207,672,380,144,859,468,170,562,778,905,904,974,441,357,816,26,67,35,901,348,3,373,486,373,169,582,368,773,720,150,808,649,320,212,415,727,788,416,370,795,566,421,248,656,658,231,611,585,771,396,738,128,114,365,803,532,933,611,582,532,556,715,436,279,710,763,653,754,977,329,613,804,784,841,955,213,709,98,377,833,607,411,71,627,894,664,839,258,488,2,39,151,908,735,725,204,169,2,757,316,578,115,821,306,875,346,124,420,912,686,895,149,131,888,635,462,677,918,636,979,471,397,697,742,500,261,559,503,432,221,474,591,429,533,806,522,657,676,915,840,971,7,184,47,971,722,391,711,742,304,339,247,29,331,377,55,83,76,182,9,322,738,973,301,720,746,428,706,382,504,601,620,51,427,18,423,677,327,249,946,773,513,92,897,737,582,182,721,878,904,418,692,320,801,824,993,671,4,423,416,761,156,663,744,581,677,653,937,278,863,795,740,69,281,693,922,542,0,891,601,76,780,307,299,627,584,703,211,108,817,615,932,236,927,444,716,703,207,705,877,181,405,248,772,855,995,746,361,712,450,54,826,885,877,464,576,645,987,565,585,89,262,895,100,41,320,696,57,43,928,573,517,627,360,76,970,240,404,499,778,695,886,26,531,262,487,971,240,971,827,435,998,755,785,404,631,599,857,120,79,293,939,87,24,267,960,863,756,393,422,760,166,567,131,745,166,948,49,708,230,183,103,948,848,657,641,409,910,28,917,494,412,760,744,186,820,774,572,112,567,675,326,228,686,317,432,837,376,116,274,895,787,310,403,7,647,511,401,187,909,851,854,783,185,968,207,726,83,723,873,213,903,10,481,658,342,280,168,101,396,378,786,889,370,55,452,803,187,681,553,312,236,971,252,479,842,361,963,65,158,230,550,965,994,650", +"671,813,907,978,938,990,193,395,698,871,298,648,88,574,436,236,56,443,530,173,266,306,33,25,250,651,690,775,353,401,174,494,178,566,82,706,673,228,555,584,56,377,603,824,262,333,302,568,871,428,128,737,956,353,506,77,819,444,825,571,118,384,256,75,207,79,825,21,961,443,875,217,338,418,366,615,401,340,435,23,855,572,854,401,704,187,615,975,37,602,653,754,908,996,169,291,742,551,697,35,379,964,6,688,294,752,795,947,831,952,550,352,374,268,630,661,308,5,7,26,159,623,965,938,442,592,658,706,272,584,501,516,947,738,776,625,498,931,762,346,554,144,713,496,439,305,49,561,635,905,136,505,667,704,508,635,455,215,293,880,182,958,707,946,87,144,855,515,394,664,781,217,307,773,541,565,853,841,395,302,899,202,633,341,15,529,325,250,123,891,355,570,368,915,979,585,331,801,166,321,859,478,878,266,764,861,583,701,786,848,562,493,825,902,922,574,49,150,11,552,852,305,957,370,698,308,907,430,207,429,970,692,393,990,384,88,314,286,313,693,356,2,889,808,327,397,454,359,933,174,216,621,825,230,217,892,458,113,113,97,439,298,44,919,47,933,546,968,838,487,550,216,676,354,385,934,705,409,112,52,394,535,671,89,300,955,770,844,488,33,461,814,440,749,699,841,944,186,263,701,285,173,155,441,132,851,882,643,259,796,551,14,996,422,276,529,95,794,25,933,854,507,951,123,605,456,296,607,474,812,710,473,988,149,46,162,189,209,145,637,669,402,641,736,258,863,874,672,750,380,719,987,463,644,124,231,517,245,137,42,431,677,693,370,429,270,26,153,68,133,897,187,391,355,416,637,682,400,479,423,845,751,661,170,925,682,786,223,569,765,939,657,770,606,735,48,792,995,389,905,923,319,21,301,864,305,981,157,214,66,522,574,777,231,40,840,610,242,456,98,38,636,657,192,543,869,93,137,741,673,397,96,862,727,934,444,418,218,169,347,914,747,850,539,271,569,80,476,271,798,925,839,602,666,864,21,507,307,737,768,742,94,391,273,544,359,137,710,304,732,587,332,303,925,694,402,122,473,12,40,523,902,528,377,79,316,319,431,321,867,776,549,79,3,767,396,102,298,961,849,580,290,864,105,453,144,755,474,729,108,367,225,853,179,353,364,150,557,58,729,952,932,536,968,121,547,833,913,822,352,528,850,789,434,453,77,506,946,445,281,965,366,979,873,335,899,115,365,348,799,33,754,607,210,884,595,722,423,724,797,247,163,299,359,707,68,796,370,254,547,842,910,836,80,778,70,322,490,588,648,548,201,975,361,41,743,641,963,34,281,568,611,753,546,328,16,338,427,522,116,946,705,331,944,767,236,387,833,636,814,119,795,382,867,722,661,596,313,414,881,61,459,36,927,628,671,753,164,276,864,386,262,922,334,9,917,664,783,747,884,700,303,193,75,545,510,239,906,206,639,131,723,229,949,181,512,229,277,633,74,941,610,743,125,744,886,318,768,733,576,801,168,883,515,983,729,160,250,484,795,718,639,912,719,742,358,850,444,752,384,984,819,317,819,131,263,855,610,316,343,758,417,161,104,942,88,564,700,589,248,437,302,94,770,548,12,278,176,698,903,964,594,799,629,219,850,832,191,875,858,679,379,609,59,130,998,606,961,274,888,367,450,452,930,611,992,44,738,211,285,399,79,82,437,841,380,728,377,798,679,160,467,893,198,676,608,614,651,101,918,447,890,4,579,134,436,463,502,282,114,769,518,837,733,191,73,771,977,440,896,411,573,708,117,558,647,794,974,178,281,773,154,796,963,663,844,595,3,545,31,612,835,891,0,180,713,60,292,861,211,875,367,83,467,224,585,974,953,817,55,655,978,547,436,559,72,881,602,166,588,885,997,698,921,438,756,982,719,160,125,214,143,535,338,50,754,207,920,63,21,567,942,818,686,242,609,316,569,178,145,226,165,61,35,381,680,732,272,361,702,68,111,881,450,655,664,119,192,435,592,828,665,325,952,991,98,158,872,660,441,718,507,659,882,29,466,633,641,894,898,544,314,658,880,277,601,151,710,676,788,985,486,357,158,831,340,708,821,702,565,857,495,970,372,969,789,201,429,876,493,436,265,630,901,840,447,292,272,363,119,2,272,628,953,124,451,838,478,127,245,675,693,732,483,553,792,946,259,211,227,788,906,613,902,220,411,966,198,962,721,112,989,719,974,693,288,38,245,205,670,381,858,988,993,485,899,281,977,470,806", +"762,322,357,189,349,950,574,233,909,427,54,498,845,719,749,216,501,653,120,352,461,104,338,706,306,825,217,726,485,204,679,170,237,205,989,963,499,325,669,173,814,957,87,611,128,713,933,42,782,813,946,78,662,979,414,288,346,675,88,59,477,375,314,11,554,710,471,953,353,164,407,461,232,201,249,279,410,94,820,589,314,990,947,281,149,957,38,207,200,682,114,527,16,748,505,370,380,983,837,615,901,460,302,288,490,856,923,232,795,192,426,260,311,763,882,865,138,454,676,213,222,68,811,289,62,412,570,429,824,156,983,267,785,162,143,158,416,192,343,518,145,572,386,22,413,716,557,796,772,502,132,794,348,373,115,783,36,392,907,758,704,815,170,460,293,930,536,737,263,793,736,486,348,390,757,909,706,632,284,805,657,944,311,361,196,256,149,579,958,435,362,66,521,996,646,713,936,105,483,624,803,9,77,128,815,596,248,234,508,434,196,338,321,421,299,874,107,343,171,66,39,176,460,232,312,785,538,111,469,650,744,400,803,307,395,726,148,689,396,451,631,930,282,299,834,865,679,607,927,372,327,4,291,932,752,28,216,112,889,484,516,739,640,481,289,966,523,766,194,404,722,862,438,952,892,32,738,260,110,254,727,65,504,336,671,905,958,108,45,984,606,284,914,692,907,683,220,834,448,884,487,805,38,577,798,744,119,623,323,120,802,837,823,101,376,936,230,788,852,291,307,936,18,430,444,72,842,353,897,223,145,815,524,121,40,47,957,927,549,504,959,316,36,90,30,112,54,362,762,140,558,936,495,304,672,808,746,364,527,899,115,93,946,23,568,725,69,545,158,913,265,625,545,224,270,907,934,454,588,28,684,609,677,785,349,800,596,957,152,611,548,272,209,430,220,66,212,385,793,674,47,795,201,636,87,921,65,425,322,681,539,680,111,782,12,715,608,846,347,155,281,801,342,933,405,291,24,43,630,923,741,971,565,335,209,695,367,569,809,249,110,311,698,727,211,230,484,571,495,932,331,100,230,255,896,42,710,624,497,531,158,461,176,707,162,74,891,386,365,270,724,883,715,177,324,980,984,961,335,12,253,597,472,294,235,430,374,711,537,640,879,949,355,781,294,925,751,938,398,183,835,631,196,310,506,427,183,730,441,216,675,380,881,242,53,721,607,928,890,319,314,519,41,468,884,310,109,444,509,663,455,420,776,793,432,682,788,539,692,255,120,507,654,483,452,591,708,206,370,542,796,169,60,105,965,336,690,968,220,502,655,187,607,263,139,588,773,168,454,452,673,184,614,55,366,456,647,52,116,802,78,574,403,606,824,334,931,78,792,63,980,590,135,939,978,873,478,410,86,371,787,117,683,673,30,116,961,996,48,556,796,127,942,307,980,795,730,624,245,886,4,40,449,76,698,477,757,688,915,236,787,398,908,802,612,462,112,575,519,736,859,65,892,422,540,891,761,29,379,654,899,35,533,729,244,292,735,63,747,736,166,571,30,343,134,696,172,461,452,849,863,516,280,580,584,481,176,982,571,888,242,466,70,507,824,428,841,165,244,523,518,379,807,184,474,410,974,718,732,478,601,552,848,193,482,292,612,589,876,892,270,981,350,464,156,465,967,391,894,308,682,844,312,61,893,854,152,448,524,963,20,940,462,101,267,353,269,181,410,804,920,907,911,309,415,730,552,379,110,512,458,185,777,479,699,208,468,671,650,80,947,374,478,500,761,826,706,493,353,684,617,624,334,100,359,417,51,382,648,935,889,713,966,614,387,874,923,798,556,770,160,261,341,247,135,660,557,796,656,386,605,770,367,749,168,954,266,146,548,182,389,918,601,180,0,303,489,118,163,206,92,544,26,543,78,646,69,660,242,854,896,692,539,276,910,72,164,622,485,827,159,212,204,729,395,69,219,404,763,770,786,779,73,296,416,374,982,571,493,181,825,780,160,978,824,679,680,710,75,154,557,307,834,465,30,72,752,108,116,643,501,265,295,74,154,73,731,366,316,987,741,237,418,463,728,948,236,371,213,951,841,377,159,401,221,804,819,324,900,578,502,421,271,832,479,493,647,896,732,235,963,976,228,219,736,500,795,901,577,914,400,646,786,444,878,214,555,778,469,49,616,788,957,926,954,609,836,646,84,461,435,345,172,313,48,468,219,866,321,410,159,97,715,469,463,811,563,791,937,727,616,890,573,454,639,516,542,63,845,39,499,250,205,150,605,213,456,952,234,652,518,188,662,55,525,892,978,443,586,425", +"352,616,4,763,42,790,301,692,565,86,905,718,319,479,218,679,143,884,110,605,32,424,436,515,788,399,271,979,575,93,699,556,722,44,574,969,159,44,269,437,832,517,573,14,635,483,787,723,448,582,296,691,729,205,61,294,442,397,400,205,278,931,62,743,930,102,308,933,889,658,292,111,837,855,376,662,11,342,123,206,780,833,877,739,279,229,463,733,913,570,324,336,995,843,246,108,584,694,823,284,974,353,491,212,545,532,455,210,846,869,948,561,919,109,997,527,909,679,114,895,910,783,947,944,14,519,980,680,947,446,304,647,614,207,713,714,440,724,910,879,606,21,221,416,564,673,95,455,609,621,914,743,728,953,266,713,364,962,896,840,272,200,859,147,886,27,232,206,896,405,166,307,805,123,121,661,826,50,426,522,224,300,698,121,772,54,281,222,405,766,793,381,954,857,650,656,433,219,224,697,664,213,294,169,754,755,425,11,860,419,788,661,777,69,151,482,954,195,754,155,262,650,267,222,170,921,805,993,294,13,536,697,713,298,317,208,190,172,742,213,210,966,285,801,731,264,701,887,539,904,908,844,500,110,970,677,644,234,858,598,487,801,949,907,967,155,716,670,114,117,932,759,79,574,770,435,50,863,547,731,82,465,610,386,850,862,725,739,440,601,646,41,704,401,735,887,785,333,703,46,816,642,270,266,914,973,330,749,964,210,525,771,421,115,408,166,982,478,301,945,236,343,783,574,832,43,744,266,910,178,951,655,683,650,662,821,526,939,646,666,633,820,561,41,975,381,240,211,369,430,766,221,928,892,960,122,675,570,378,600,667,967,393,427,578,432,276,612,811,591,843,504,725,485,385,672,411,485,914,175,482,390,417,457,682,934,935,76,12,655,910,175,208,112,763,645,397,199,168,195,177,263,111,38,979,695,425,171,977,157,445,565,808,448,283,664,73,833,745,611,565,498,61,419,866,109,59,100,953,291,410,884,966,260,640,473,818,583,718,441,579,751,644,513,468,662,625,751,74,518,429,412,623,677,222,22,931,600,767,399,656,285,2,629,571,754,481,680,135,708,656,425,191,569,236,18,929,576,580,591,684,186,175,157,457,812,541,561,358,137,613,791,670,664,960,87,175,119,598,404,806,738,644,98,553,738,132,274,45,843,942,285,865,108,979,178,437,382,86,924,192,300,886,895,831,202,330,136,913,835,336,576,138,868,327,356,646,107,987,466,171,773,954,435,508,724,970,26,570,682,208,866,834,905,4,231,266,865,2,20,496,768,811,20,108,561,113,943,395,799,673,976,789,470,280,10,22,967,155,496,361,82,874,309,795,608,839,649,508,733,270,10,663,195,663,744,442,879,931,280,391,948,104,817,692,693,111,208,338,302,510,813,375,590,382,559,840,564,171,247,797,573,99,550,854,897,836,656,951,753,490,160,785,768,745,664,185,167,790,670,607,906,204,534,465,124,694,600,872,537,611,195,916,67,957,757,578,75,354,300,467,890,495,368,105,430,911,432,684,286,813,9,993,181,91,317,844,663,369,469,807,935,383,435,647,16,869,839,738,331,971,491,620,341,874,7,938,179,327,244,653,394,277,653,462,556,348,742,245,999,978,128,227,858,689,831,361,400,757,155,360,315,80,109,175,754,73,430,663,303,754,153,940,649,995,656,952,476,260,717,498,102,494,153,968,294,543,314,845,239,547,22,151,579,373,914,26,174,939,250,278,164,519,417,556,222,326,321,719,235,724,817,944,166,837,251,671,222,4,753,350,823,861,504,146,321,823,306,974,979,565,633,224,302,131,793,270,535,283,353,251,140,175,629,687,443,459,978,229,762,439,528,76,713,303,0,862,310,968,94,694,474,906,89,310,39,567,37,181,315,996,375,105,141,954,870,149,771,159,538,322,41,370,621,394,511,536,462,592,575,337,491,325,48,113,981,482,503,799,791,461,391,592,334,257,322,489,219,157,659,856,490,684,921,649,347,58,784,738,121,79,731,571,429,781,45,207,238,607,17,678,309,467,550,563,290,345,184,939,103,580,701,333,799,192,722,471,957,697,141,39,432,867,534,617,151,409,747,171,667,798,600,414,548,283,830,718,571,343,222,753,512,164,692,564,197,151,250,381,320,243,121,249,377,499,461,727,53,369,683,372,20,611,543,119,517,983,236,656,934,313,720,707,519,969,159,746,710,669,382,622,641,947,954,725,913,977,162,561,647,38,372,722,758,973,571,677,954,130,864,315,446,223,63,90,510,247,525,906,259", +"550,336,99,34,308,235,863,640,837,145,895,101,63,422,697,913,540,768,640,513,2,186,336,126,313,93,180,914,367,466,592,479,895,402,1,827,309,917,158,533,468,866,419,309,429,452,807,171,860,653,526,249,324,731,48,818,36,816,502,401,896,270,609,254,262,823,868,613,599,142,892,868,59,549,933,190,275,717,819,321,451,365,985,928,882,457,183,765,377,834,60,74,664,54,610,411,523,923,355,654,747,262,951,356,96,39,781,718,105,81,827,296,93,960,27,749,323,283,493,37,928,699,107,342,271,120,152,88,879,142,768,292,11,12,101,804,101,659,890,461,785,426,312,920,441,121,114,633,798,735,659,679,901,931,434,344,258,877,592,61,446,226,289,549,932,808,943,731,889,196,266,396,594,107,572,245,221,357,861,937,928,259,16,727,709,647,677,387,553,757,130,9,400,974,862,283,601,534,636,97,692,33,338,779,244,812,832,348,373,844,648,527,712,289,544,941,878,55,340,314,256,866,835,650,973,733,939,265,156,16,75,539,390,412,877,208,303,438,157,175,743,947,412,929,489,627,969,341,136,543,256,703,26,996,874,35,306,908,763,641,785,501,837,450,203,190,955,533,125,913,341,50,681,139,284,274,149,863,350,422,87,696,283,525,747,749,505,99,341,503,117,871,344,854,642,98,663,136,103,135,464,885,410,209,277,811,20,799,978,166,148,66,508,403,880,828,123,996,98,703,229,759,329,896,342,286,138,150,458,909,32,419,658,370,464,325,475,644,938,479,690,290,56,218,367,664,479,93,260,812,562,744,925,206,602,264,772,681,256,418,555,90,811,853,768,966,658,250,173,169,300,823,792,353,811,190,41,654,185,574,649,14,631,441,5,854,530,535,331,63,860,974,11,110,634,247,902,549,51,118,991,141,150,46,902,428,518,226,635,246,66,192,454,274,57,41,148,208,745,406,504,116,364,146,802,294,611,263,367,342,298,779,827,95,702,602,453,57,200,589,929,407,277,742,574,769,116,536,134,636,917,687,328,694,817,306,548,178,265,616,153,846,31,946,38,159,71,724,260,483,349,698,85,458,785,919,761,280,196,747,211,309,230,702,944,349,280,808,997,39,448,972,869,818,521,362,798,265,109,197,333,445,725,798,495,720,822,892,590,987,869,434,824,626,899,549,277,563,885,369,977,656,243,10,411,235,388,828,331,397,325,208,436,871,928,214,23,805,746,305,114,997,893,727,267,636,375,775,170,6,625,720,207,218,375,241,713,634,316,81,863,307,557,617,338,518,818,965,651,385,713,216,980,190,520,721,578,648,250,275,482,504,609,467,829,497,102,579,661,105,146,963,275,305,864,555,426,675,756,690,218,891,646,874,92,419,417,466,710,903,486,62,638,193,900,892,521,343,677,968,397,136,323,136,156,388,791,378,759,951,555,471,133,791,518,736,783,312,302,394,9,840,762,329,599,468,484,392,550,489,244,744,304,284,167,793,154,532,814,799,798,975,794,937,45,999,150,134,186,644,733,920,571,115,408,141,674,575,58,742,997,437,889,731,767,114,875,405,261,939,29,574,677,326,175,933,8,481,927,712,6,553,627,257,768,43,414,474,568,548,620,174,497,294,271,899,717,141,806,137,99,76,944,490,388,801,622,501,841,659,675,249,701,639,275,548,101,311,127,729,779,914,661,972,128,950,298,570,714,372,757,433,970,497,612,440,502,614,98,331,912,363,326,350,142,167,213,899,900,184,465,926,395,730,805,290,482,989,163,705,492,553,919,611,884,724,304,568,780,261,493,891,452,546,624,304,396,977,979,990,108,331,666,801,89,93,678,488,377,56,682,113,780,60,489,862,0,837,960,79,474,365,337,111,856,31,304,390,228,550,63,310,77,886,745,616,389,152,366,474,154,367,263,530,378,417,311,723,868,547,501,181,694,702,772,667,44,60,271,65,843,901,683,760,439,914,546,359,141,879,716,792,941,73,139,856,472,693,203,365,195,148,788,215,553,58,784,853,799,909,123,147,833,444,475,412,844,752,350,76,468,463,871,318,470,455,230,553,418,647,174,8,751,968,553,479,299,873,680,733,46,900,658,574,664,668,149,570,464,834,479,309,675,593,159,941,831,198,328,197,240,800,79,544,984,384,290,914,825,955,439,307,513,352,38,772,910,904,674,962,158,618,528,20,898,67,379,255,66,454,948,729,978,295,331,854,910,326,832,784,140,459,357,252,572,48,613,525,151,454,270,861,469,406,319,339,379,370,599,61", +"496,241,969,950,910,528,431,934,908,468,926,546,235,194,401,311,971,58,514,804,235,240,603,46,161,124,732,890,268,14,630,482,15,828,811,488,701,416,933,180,196,544,750,961,517,663,627,750,191,926,540,291,528,245,202,626,62,245,645,940,500,608,621,350,601,577,317,108,557,252,709,422,566,452,51,819,299,557,356,872,994,714,268,70,430,721,166,843,119,198,815,217,27,591,216,567,822,805,835,94,721,59,77,147,567,321,360,586,106,630,434,908,783,374,594,154,278,542,234,77,185,160,496,450,440,706,314,124,477,798,551,89,978,984,86,897,976,322,501,854,399,448,886,457,514,645,851,788,58,671,871,195,492,871,627,901,109,564,104,224,964,471,582,221,467,52,850,694,312,763,222,556,947,779,518,128,453,82,881,725,780,885,989,920,171,627,230,246,837,62,853,50,807,454,8,971,514,963,40,72,897,679,31,208,847,402,549,372,554,993,813,444,722,448,817,725,90,728,460,716,598,990,874,700,592,154,378,987,639,66,381,599,890,382,857,826,902,681,237,111,774,70,253,697,358,399,470,341,171,164,141,927,366,737,409,70,286,879,305,386,607,622,58,71,368,519,831,515,730,666,288,446,424,276,678,663,878,369,787,247,161,594,437,677,462,372,263,923,778,224,342,648,857,12,505,65,59,187,921,850,161,242,706,458,239,959,256,211,876,437,532,1,148,431,442,587,253,849,511,769,441,520,359,637,222,979,278,319,493,17,555,93,291,72,75,22,921,525,655,315,590,329,23,339,265,518,251,826,162,812,727,103,41,36,786,867,445,550,103,177,995,31,693,879,633,407,619,763,723,937,185,189,301,583,554,32,42,685,20,695,992,941,294,940,446,173,85,812,223,36,478,718,947,811,687,18,952,712,859,943,238,483,111,939,395,590,373,807,926,106,127,103,170,19,215,868,774,22,205,182,306,709,560,603,94,993,889,130,711,469,799,655,686,523,752,953,135,319,31,53,124,134,406,135,45,20,53,817,608,984,494,447,566,688,457,909,111,217,725,996,59,875,892,81,244,840,775,108,425,732,742,728,522,850,184,461,446,303,20,762,7,980,604,832,804,714,356,309,441,263,669,592,53,4,657,540,561,723,211,575,961,29,834,262,363,97,39,975,300,902,66,977,715,748,891,977,180,395,9,453,525,984,25,796,514,620,135,572,792,135,694,346,17,219,615,197,828,876,7,220,347,425,85,104,923,438,590,832,194,942,61,922,556,744,985,811,730,380,492,236,746,777,221,64,329,898,540,471,171,615,681,79,934,87,996,90,149,620,87,373,479,542,131,197,416,771,613,684,205,407,420,426,871,689,666,791,499,872,714,528,86,544,386,430,71,899,62,976,77,956,762,965,338,955,228,449,208,833,272,327,380,254,401,619,733,317,697,71,575,615,553,923,477,781,238,207,954,612,69,371,589,794,896,729,596,582,235,406,908,865,212,861,225,392,280,520,709,517,230,196,24,184,557,141,578,84,278,103,583,322,169,139,932,599,801,717,73,472,273,958,96,217,305,109,751,511,236,727,848,934,555,53,414,387,801,254,484,339,491,792,27,887,473,695,950,781,650,305,417,221,469,319,99,115,878,183,782,242,363,125,517,689,542,557,868,708,844,629,826,247,952,598,958,269,566,529,148,710,992,220,137,142,542,182,265,809,233,911,563,96,970,939,870,911,121,989,814,377,101,445,509,456,467,617,265,870,149,791,285,604,12,224,884,590,97,861,379,148,67,5,204,280,169,230,671,791,430,629,99,572,780,419,109,452,670,659,771,673,518,459,967,622,97,801,815,233,681,883,486,473,140,448,307,292,118,310,837,0,680,532,879,631,861,242,314,239,866,26,81,196,991,67,895,558,644,817,603,216,488,354,496,996,234,349,353,551,229,579,536,460,559,666,918,106,49,473,491,293,8,727,259,943,390,716,133,792,510,838,623,768,43,345,605,432,20,476,869,525,179,86,220,508,680,318,614,649,902,260,39,608,800,621,813,321,650,167,484,735,807,170,844,302,993,905,472,847,410,675,381,523,140,643,199,826,162,225,535,915,755,96,946,687,514,255,586,299,631,87,858,403,571,989,285,525,727,838,632,927,558,178,416,485,959,676,942,990,445,649,929,613,285,434,553,505,477,877,312,627,275,144,377,249,359,885,404,192,945,636,506,207,25,179,770,348,367,299,64,957,363,236,28,868,755,282,166,276,102,295,599,120,478,251,199,822,186,22,38,48,29,274", +"82,957,116,927,587,992,611,642,967,338,348,786,23,395,525,307,45,40,720,463,128,278,555,489,252,450,786,822,620,59,255,437,954,502,933,450,394,690,451,951,519,749,797,572,299,449,998,666,783,53,248,639,804,44,817,907,234,323,940,866,737,592,608,498,812,921,481,847,533,336,176,581,455,191,208,29,685,911,466,183,537,717,457,601,484,749,433,223,935,134,758,637,555,326,831,691,145,185,424,979,873,668,321,396,40,848,788,489,827,94,118,956,564,209,169,787,339,309,743,240,121,154,23,207,548,217,455,467,548,667,856,106,375,806,412,392,934,70,439,138,769,581,763,918,10,846,819,77,231,392,407,48,69,275,777,958,524,924,150,194,757,56,28,255,540,395,488,999,985,534,767,293,714,1,310,708,764,420,299,951,833,617,259,460,477,696,614,211,116,925,820,403,736,87,609,800,56,110,943,324,116,512,735,679,457,227,24,644,949,824,378,227,128,456,831,866,624,86,763,203,80,921,491,847,396,581,26,119,108,204,940,832,110,974,369,134,673,8,718,634,870,164,415,322,583,624,473,999,685,901,110,733,768,770,570,308,746,67,246,781,298,928,879,90,371,7,582,363,616,471,681,47,819,949,345,246,917,670,445,887,919,377,626,771,133,161,626,969,707,928,842,184,916,148,382,494,442,895,935,343,387,243,459,719,691,229,596,71,622,765,461,538,707,815,482,904,27,226,172,695,925,93,666,192,965,566,677,93,343,483,287,645,504,389,559,315,453,970,954,396,66,146,134,425,718,806,621,160,25,455,978,159,795,427,290,859,447,355,692,411,665,613,570,928,953,305,368,708,49,4,180,95,747,683,578,763,750,4,850,811,493,312,53,233,629,758,17,721,103,874,190,670,724,478,432,780,655,53,472,12,977,711,33,82,317,880,126,984,572,117,22,816,523,117,833,918,942,658,277,648,165,263,837,304,599,434,701,846,65,749,875,843,336,214,957,648,583,458,743,1000,663,545,236,349,654,373,352,960,701,513,805,295,360,991,203,965,274,854,839,775,368,93,518,151,749,298,560,396,902,274,914,291,203,764,34,325,232,681,93,231,191,624,694,225,484,175,561,770,365,904,567,916,55,980,292,385,679,156,467,289,744,895,930,728,270,76,432,189,597,104,948,699,646,879,814,516,135,703,32,986,481,88,308,31,966,377,610,541,807,501,62,365,507,549,268,896,334,910,508,926,994,77,893,168,476,836,429,759,572,1000,405,394,210,304,165,847,867,891,916,321,91,705,308,103,877,53,939,444,309,890,623,241,215,232,211,160,813,496,992,858,628,609,832,673,421,285,554,108,137,302,816,441,375,161,864,999,124,605,449,149,306,643,419,482,826,143,646,302,394,528,946,761,868,262,517,808,82,22,966,644,282,716,413,280,276,405,645,135,648,258,265,700,660,886,971,241,476,563,774,653,172,897,741,562,298,736,406,958,217,612,693,340,26,32,175,323,601,670,818,284,411,700,710,432,763,904,6,527,865,168,969,279,744,74,508,517,294,524,480,721,527,450,159,324,254,792,636,120,918,930,400,713,348,730,184,486,752,496,535,983,300,367,535,442,518,396,37,112,44,162,755,219,699,436,723,628,362,707,742,304,177,898,403,927,259,465,626,55,235,943,632,338,485,584,725,185,187,966,442,370,608,770,490,624,475,431,653,4,764,928,53,744,846,659,139,434,432,319,598,559,591,86,580,168,422,867,417,796,830,755,433,911,263,385,209,46,189,373,774,637,377,342,246,466,469,888,989,444,206,707,732,998,98,205,196,134,294,63,633,228,283,392,981,481,673,703,26,138,827,421,666,163,299,861,163,968,960,680,0,873,665,776,852,890,462,811,245,333,515,510,461,333,641,741,918,315,479,576,446,875,535,211,695,448,615,179,397,833,948,319,993,617,536,391,725,890,521,821,109,52,248,299,339,495,142,749,487,479,751,185,337,314,841,677,634,447,598,855,344,769,502,221,888,783,70,540,766,729,188,854,803,20,264,715,136,150,486,850,983,477,666,283,356,342,797,782,523,48,987,363,769,212,531,801,316,196,647,439,184,504,839,924,576,473,187,535,232,736,571,886,299,202,76,23,410,264,420,797,376,249,223,408,796,499,50,874,279,157,821,672,734,240,526,177,749,214,986,573,221,426,350,946,268,83,982,465,696,940,693,934,372,218,547,862,899,987,553,293,766,912,272,522,875,196,123,749,773,506,875,79,136,351,622,464,833,460,330,594,596,376", +"985,892,474,895,124,108,1,14,83,593,189,801,648,369,19,651,925,629,173,83,896,648,711,881,925,417,886,883,777,339,722,773,397,165,326,701,998,652,249,695,923,783,624,226,924,671,668,46,380,29,501,495,756,316,37,595,100,594,994,620,490,860,491,240,654,91,75,615,521,398,255,818,380,479,972,545,68,180,827,689,762,583,763,504,475,161,663,369,846,37,60,126,989,79,862,938,741,982,594,872,809,500,94,268,890,599,270,654,670,901,360,885,187,145,640,690,842,934,360,216,356,203,334,355,774,371,395,498,548,830,450,484,213,424,210,825,200,763,707,605,801,315,303,941,527,546,873,628,469,750,400,447,147,290,481,457,76,925,651,88,679,55,621,266,209,430,196,966,275,587,974,18,44,734,737,467,257,40,903,72,172,149,393,662,590,630,947,62,393,833,890,484,689,9,863,448,157,440,522,318,405,488,941,42,463,144,815,112,795,918,812,765,340,262,199,139,741,108,440,758,4,506,538,876,879,282,95,6,924,657,80,688,132,249,657,172,511,81,613,126,395,70,421,71,618,695,719,850,405,398,682,193,522,231,890,121,315,464,198,851,655,510,186,541,179,905,208,181,831,751,847,611,860,279,660,970,342,743,134,675,390,870,616,901,860,871,534,292,860,653,435,823,651,313,526,866,896,922,85,265,670,275,830,854,348,113,596,145,824,865,309,875,682,787,136,150,433,451,131,916,781,711,382,332,781,814,823,708,567,535,18,514,249,560,345,141,875,607,462,726,968,115,498,501,719,205,192,849,749,747,288,669,33,241,742,877,281,275,373,648,802,964,666,440,16,645,676,179,344,781,299,683,686,121,767,612,865,834,436,917,568,315,855,314,832,519,942,808,914,822,717,612,317,678,680,306,532,75,424,800,285,970,532,259,218,239,607,860,592,441,239,610,749,215,772,934,785,287,872,504,988,67,623,403,909,175,154,570,300,799,981,878,745,763,141,248,813,454,102,36,382,123,291,177,317,354,537,874,19,576,755,263,797,21,896,41,437,26,242,214,716,93,580,872,914,700,771,160,700,94,209,114,700,693,783,136,250,141,82,200,237,552,59,909,10,29,50,136,573,173,941,590,481,194,768,946,756,307,987,710,72,964,987,615,660,896,123,742,865,188,787,300,307,259,626,871,894,256,476,753,106,499,162,880,316,701,914,210,810,777,715,345,730,170,341,939,899,201,428,693,602,542,917,615,620,883,132,948,79,183,542,321,102,59,275,293,508,147,279,841,372,166,993,60,468,966,103,529,59,567,367,865,312,145,94,829,671,734,657,675,293,3,69,806,397,966,829,81,789,905,606,769,175,740,956,676,606,779,484,93,248,814,102,250,96,940,443,844,480,894,231,79,441,541,500,567,314,412,927,639,124,815,549,307,197,568,642,419,20,698,524,123,142,595,698,648,199,403,589,497,336,93,472,870,188,384,701,141,757,287,960,359,216,856,750,308,345,671,658,763,648,649,478,266,377,713,632,74,589,602,288,646,841,338,268,150,366,338,260,554,642,515,240,243,498,121,434,137,199,326,740,408,374,271,346,932,722,696,297,132,772,501,684,292,106,124,319,181,326,381,724,986,378,152,825,819,417,4,456,546,505,920,300,440,175,842,615,232,56,868,557,4,432,825,783,745,65,481,762,99,48,905,284,412,225,769,710,621,261,105,273,689,446,833,405,275,236,580,937,345,978,782,775,467,14,466,274,529,25,776,920,166,394,672,206,840,972,417,343,68,42,119,879,845,880,809,907,772,331,739,145,298,268,509,803,353,936,440,908,374,342,752,116,770,44,169,708,131,78,81,488,116,627,211,206,94,79,532,873,0,315,1000,845,516,23,406,712,744,424,6,500,73,914,271,681,651,118,185,855,703,451,372,210,697,320,896,558,773,269,888,318,658,897,133,510,549,485,108,999,881,709,219,244,571,352,65,113,593,391,852,280,315,190,479,77,922,663,723,956,638,947,49,609,908,257,211,904,942,111,349,8,936,130,98,667,854,594,321,191,543,375,409,743,418,266,640,804,969,560,198,550,107,463,823,143,971,469,549,290,762,712,419,348,996,21,843,834,862,296,775,96,734,105,935,259,610,711,667,912,349,532,580,736,421,772,706,266,186,293,850,368,678,16,647,914,770,127,260,484,396,217,825,898,759,592,909,289,686,985,892,262,447,444,470,649,84,641,35,150,460,156,911,864,408,678,727,741,111,439,966,519,377,937,793,925,72,754,795,960,868", +"340,196,421,947,492,543,193,455,800,796,611,156,965,591,732,499,625,804,466,459,102,692,983,636,463,165,879,616,647,542,397,252,24,20,310,882,877,761,872,266,578,215,421,526,120,832,175,866,7,575,945,992,506,510,813,706,261,207,400,518,303,901,35,543,621,298,327,130,521,693,809,814,785,298,994,186,397,713,164,860,594,872,324,485,275,667,26,351,670,712,815,879,559,275,534,903,480,320,767,93,427,258,384,281,950,663,816,881,81,344,402,208,919,19,262,154,907,225,912,350,253,484,133,155,481,366,123,629,604,286,664,381,64,578,190,289,849,256,131,681,841,23,585,117,500,305,664,156,311,525,733,996,194,522,376,400,446,723,648,995,613,823,9,918,672,507,698,292,825,40,445,36,251,639,488,297,595,268,320,274,391,69,913,266,675,913,205,638,55,516,43,317,441,390,538,547,851,787,676,488,948,723,621,142,470,753,107,267,509,649,481,850,229,789,371,194,518,957,575,974,978,13,135,271,149,635,670,192,372,962,36,562,89,670,720,249,94,317,238,128,58,56,377,148,845,119,273,233,998,198,149,376,113,660,644,925,810,456,509,72,969,287,933,930,564,683,451,811,203,214,263,239,759,527,722,479,754,798,995,709,491,865,718,251,487,612,771,41,820,449,876,398,328,841,769,221,791,522,615,341,416,911,361,522,335,854,714,918,400,983,741,467,797,859,437,134,22,913,421,280,798,418,40,840,841,214,61,77,276,537,352,166,381,533,769,278,27,700,291,904,800,927,574,867,292,383,896,225,509,138,691,279,475,26,674,551,334,492,876,641,557,484,507,374,476,315,929,659,755,359,879,168,865,83,473,358,719,647,961,311,431,165,46,563,755,889,736,624,65,588,957,541,566,131,333,301,750,322,177,818,467,140,899,135,264,169,439,516,509,701,125,651,279,953,272,214,926,902,58,569,720,346,758,952,936,39,355,594,697,810,501,852,955,544,363,533,216,82,603,685,693,504,363,923,640,374,684,957,678,248,362,673,246,757,452,957,612,101,314,830,859,790,229,763,894,283,946,286,744,463,911,982,613,705,895,678,565,562,68,481,712,716,664,943,355,551,549,28,277,447,734,721,759,27,103,204,936,241,456,119,213,456,770,361,906,153,866,222,588,111,659,147,702,865,744,952,784,329,471,22,700,873,798,644,398,294,86,768,665,218,306,106,713,168,799,820,337,820,377,920,569,42,88,434,840,496,368,252,526,622,941,620,376,828,551,825,877,617,123,50,749,672,675,456,902,530,364,416,665,928,48,546,788,348,57,719,66,410,197,904,245,594,243,223,292,763,889,20,193,807,595,99,613,794,548,170,597,580,823,495,168,733,744,419,901,114,111,562,56,425,495,149,824,213,310,931,11,745,28,720,83,426,348,9,304,145,299,512,778,173,657,460,297,536,118,6,911,250,771,193,468,119,992,351,703,501,385,947,645,471,227,361,686,583,139,323,335,607,146,945,340,780,418,980,989,243,863,586,671,767,868,127,461,912,356,627,572,344,534,767,657,258,739,128,832,73,320,120,916,969,588,592,74,230,425,254,584,666,927,235,528,248,499,314,199,361,369,556,581,776,725,921,661,233,90,633,887,183,689,207,553,121,738,115,789,308,859,102,875,980,461,283,391,938,340,94,338,340,123,84,351,570,73,300,628,25,653,419,662,105,14,825,963,659,704,616,904,588,643,750,97,554,797,521,44,286,479,993,161,538,405,193,998,552,138,211,563,513,629,981,752,105,434,783,610,674,459,135,650,113,406,160,776,923,605,893,55,450,918,502,588,755,776,751,797,593,210,717,282,684,55,710,584,875,92,694,474,879,665,315,0,329,882,805,970,231,791,238,557,194,667,311,355,852,978,475,166,157,991,409,863,741,190,276,327,182,699,585,549,697,362,47,405,572,252,98,639,684,470,543,949,354,237,215,86,365,752,578,308,137,675,539,486,205,294,616,555,479,102,524,717,922,423,831,920,214,438,42,387,740,792,747,86,954,439,919,550,750,611,629,956,356,598,467,318,310,852,807,695,913,858,163,995,768,759,283,357,568,69,306,394,450,61,295,469,476,818,324,855,997,166,716,483,484,368,672,633,610,460,413,930,972,253,573,362,433,900,311,35,649,379,914,861,312,845,664,826,28,277,920,196,367,621,251,198,511,764,274,302,832,591,171,743,777,808,369,233,353,419,786,13,79,411,473,879,374,508,577,259,49,727,148,602,51,137,690,131,640,746,643", +"915,691,86,759,893,239,832,254,125,498,442,10,903,510,265,901,131,741,325,282,493,804,574,14,390,866,575,135,851,108,200,901,932,996,742,807,743,400,973,494,541,36,364,745,822,207,860,769,453,970,829,462,475,407,614,182,782,765,932,510,528,505,450,712,637,352,73,250,178,303,630,618,264,717,51,931,303,339,824,694,658,359,363,927,727,663,656,685,819,953,550,414,765,614,371,831,781,761,996,556,693,976,361,271,897,143,718,124,872,894,25,443,440,353,11,19,358,381,592,835,631,598,62,334,91,237,876,183,746,430,99,160,194,937,909,188,923,586,470,212,48,102,677,82,315,407,738,73,928,282,569,136,428,23,459,646,316,60,481,933,747,485,353,911,393,142,655,86,250,317,800,114,848,669,512,71,371,936,555,317,677,277,547,756,764,205,628,261,134,525,384,520,785,794,970,668,680,937,830,388,254,708,406,889,552,216,139,291,285,940,563,818,218,731,140,421,878,590,364,541,397,423,159,122,929,365,40,100,490,400,811,491,422,276,812,371,907,624,76,386,229,267,366,369,122,568,644,419,42,328,645,71,24,104,697,974,196,668,587,507,873,832,608,421,92,755,345,452,602,64,302,74,19,908,923,15,630,664,989,107,819,944,464,818,938,955,542,714,313,707,501,166,909,665,606,664,782,170,355,983,225,13,449,165,117,311,516,420,483,704,90,530,117,380,577,732,665,516,112,545,725,791,623,157,573,557,728,64,943,184,105,898,858,230,148,228,358,764,347,392,430,935,826,943,609,269,266,556,858,75,594,934,373,292,74,348,281,986,775,436,715,778,204,539,530,303,506,507,777,385,575,202,47,468,969,948,913,370,150,140,403,197,441,626,845,320,353,159,778,188,371,715,751,612,662,205,368,978,547,343,970,930,5,469,839,188,433,18,777,32,802,331,580,173,465,437,635,238,629,267,636,803,711,490,579,467,258,126,934,269,867,594,427,411,234,961,795,243,138,838,388,622,205,330,47,534,191,511,306,902,5,345,493,956,899,845,726,801,297,720,115,353,934,925,915,797,415,894,463,960,789,842,193,181,698,450,100,639,346,196,326,898,361,27,380,386,234,172,610,810,591,258,806,896,526,401,669,264,740,292,459,100,870,219,851,679,288,259,250,968,848,761,230,568,974,398,372,724,240,346,842,977,5,320,352,29,822,27,6,411,730,779,550,581,593,906,357,782,747,948,553,117,356,876,661,808,734,7,854,631,456,265,133,995,403,780,356,706,883,243,873,293,505,470,994,640,389,453,960,71,263,580,702,483,733,555,698,193,853,942,146,880,372,803,635,953,29,801,882,565,620,702,477,15,219,988,153,663,496,686,895,56,774,954,699,945,462,855,678,568,858,849,296,345,365,925,527,306,974,443,38,304,147,225,334,542,429,401,905,154,114,39,393,104,80,155,75,92,565,342,358,376,243,277,704,583,401,599,728,624,978,891,144,293,444,785,915,505,505,92,99,157,41,700,40,470,718,506,781,553,858,554,496,560,567,973,103,483,84,166,225,671,699,34,471,525,170,180,448,193,635,308,100,553,194,61,252,139,422,855,299,429,541,942,341,542,477,561,825,527,824,954,3,764,247,272,625,771,641,609,300,541,879,459,376,471,399,758,874,787,657,721,103,495,318,47,760,882,545,370,77,107,304,316,684,636,202,396,746,126,186,185,37,90,1000,531,216,766,671,158,606,172,785,924,906,677,672,712,111,603,371,344,479,865,603,876,638,507,232,245,95,800,474,891,296,57,576,763,994,142,378,783,878,128,140,945,174,472,407,154,488,7,21,891,102,410,575,363,716,840,756,825,703,367,544,474,365,631,776,1000,329,0,644,809,340,24,963,409,408,154,573,677,470,579,780,437,719,517,909,996,461,538,346,802,184,776,456,5,298,798,809,419,892,202,362,482,304,763,577,325,283,764,278,591,400,18,231,714,704,393,652,125,162,568,428,812,852,795,352,834,401,955,346,206,576,106,698,869,152,552,543,480,739,236,164,720,942,545,957,394,372,184,45,204,671,955,665,480,534,98,775,781,849,900,463,701,144,155,873,932,360,659,435,734,916,413,307,561,658,588,558,896,388,968,723,920,972,306,336,692,79,313,836,350,781,961,599,628,776,550,572,777,374,282,55,322,949,370,83,217,821,20,969,515,566,65,12,383,774,634,944,489,292,296,653,724,729,539,790,460,916,111,567,60,406,387,30,64,560,376,321,748,375,265,680,150,705,511,632,721", +"946,424,950,83,574,161,447,998,901,512,995,413,155,564,261,787,79,427,81,596,609,932,786,951,942,108,375,524,802,439,343,490,191,57,995,782,333,502,648,740,98,163,301,59,317,86,130,194,608,253,478,747,475,123,473,676,694,731,10,65,968,388,137,245,699,234,633,428,247,892,329,875,183,424,514,224,517,3,901,315,652,5,209,798,909,262,970,797,976,180,857,939,161,328,79,194,603,281,562,45,639,30,141,501,669,75,169,635,434,523,405,389,609,729,984,245,850,928,711,179,619,634,416,915,143,631,500,809,515,725,785,737,786,774,478,341,388,411,696,307,152,361,407,994,711,297,506,633,159,64,469,438,92,437,934,878,716,302,800,627,927,326,54,553,372,718,164,695,508,131,680,306,329,402,355,458,866,512,155,293,454,874,453,769,112,276,806,799,747,806,571,474,634,855,243,182,700,219,271,403,980,809,710,677,38,921,699,742,257,938,269,976,884,547,875,945,528,706,796,118,435,35,639,603,386,549,771,706,13,62,811,385,786,404,419,130,105,881,249,586,690,3,75,760,433,882,166,462,990,596,660,274,708,585,841,39,815,617,713,182,636,171,460,299,616,386,270,309,685,167,294,488,841,215,509,713,634,484,361,194,959,685,929,451,464,520,721,461,308,188,681,366,492,289,103,197,682,862,256,495,540,566,28,244,168,377,426,220,337,902,323,571,568,560,849,172,547,345,227,749,56,456,683,265,842,735,375,568,212,372,494,603,394,537,934,708,511,824,556,954,893,691,208,915,911,707,517,709,349,335,101,613,847,717,718,995,500,689,913,701,929,694,115,38,953,649,434,586,87,197,448,848,910,978,473,331,28,446,78,478,770,775,171,712,384,385,11,260,727,586,227,485,437,741,678,719,875,610,904,50,84,316,150,973,596,741,706,535,853,261,52,893,618,322,935,237,243,258,832,477,482,185,868,911,604,514,762,269,62,841,316,333,927,743,469,93,946,407,84,279,955,249,408,416,155,136,546,110,803,725,390,447,2,420,143,92,6,934,675,448,519,442,258,503,930,315,60,281,506,190,94,817,838,114,678,314,386,691,111,706,906,424,7,817,320,110,318,953,40,105,11,953,137,191,940,853,461,42,229,165,126,911,509,116,165,238,720,860,902,983,458,442,408,86,865,31,756,883,75,909,565,271,585,916,714,2,127,464,275,196,217,189,489,628,737,412,618,967,870,200,408,541,517,229,477,912,831,469,683,36,771,571,547,794,279,789,879,543,728,184,848,333,476,999,974,368,912,380,8,834,556,697,176,947,427,452,675,939,828,278,140,868,155,143,134,605,965,856,746,845,824,852,530,832,275,124,20,571,974,899,968,3,732,797,176,102,810,103,790,164,181,109,545,522,160,373,375,165,362,429,873,645,589,759,493,906,615,130,401,914,529,37,538,224,852,607,334,563,271,924,260,630,670,769,728,186,484,641,498,535,264,933,462,349,672,611,344,469,157,909,383,961,6,990,65,587,681,804,753,119,353,278,870,920,453,192,188,370,478,978,771,612,331,912,712,172,79,823,361,631,164,689,130,390,621,97,278,115,138,759,500,102,636,809,536,756,868,797,596,913,499,74,192,310,581,657,54,499,344,332,204,128,427,477,586,321,493,548,222,167,64,726,239,180,410,949,171,458,150,152,992,786,790,693,320,462,946,307,88,844,426,599,411,515,815,116,190,249,315,799,730,45,518,483,568,430,886,242,645,928,716,431,380,818,245,329,612,290,903,988,639,844,144,860,815,866,318,55,987,256,690,797,64,374,277,521,848,35,556,200,954,174,611,756,509,150,403,219,510,365,907,428,211,83,26,906,337,861,852,845,882,644,0,234,489,902,670,290,723,466,193,671,9,714,277,572,53,109,526,960,191,325,995,383,99,373,547,243,659,790,161,144,187,605,751,619,99,202,246,20,236,214,451,296,772,643,79,68,832,717,887,240,651,354,795,539,673,876,73,439,505,961,856,386,844,665,634,286,925,651,135,834,158,16,955,103,19,201,981,318,726,894,71,723,844,90,589,483,171,966,744,724,109,368,329,264,314,637,447,935,658,169,758,220,607,146,253,348,230,552,508,62,819,38,516,385,666,194,952,86,526,964,439,81,472,511,172,695,558,797,708,784,94,680,782,942,250,460,323,606,684,411,301,86,446,658,921,687,953,935,126,117,39,602,998,587,555,868,185,509,796,616,418,515,377,169,370,622,508,857,45,336,381,606,590,225,348,539,117,931", +"803,249,62,330,341,592,18,1,958,923,338,132,799,542,398,251,608,555,330,35,611,568,596,497,214,190,502,613,378,839,968,890,254,89,141,242,852,801,403,393,68,14,530,172,730,72,918,530,729,886,564,337,63,590,943,863,677,678,466,828,648,353,23,652,825,919,496,201,786,88,393,754,697,562,710,891,379,412,850,893,88,920,536,633,252,960,59,729,206,413,638,366,856,754,866,638,152,518,284,939,379,209,214,486,7,7,159,159,126,707,511,182,822,100,614,412,314,373,552,341,592,423,568,121,177,296,985,270,489,920,748,847,764,649,645,376,522,621,829,791,845,545,886,296,635,750,369,114,641,136,707,14,135,236,775,986,715,772,87,930,590,812,436,65,649,855,79,969,298,675,835,302,450,652,639,298,889,2,551,314,213,762,129,326,334,359,461,570,588,860,200,78,334,430,927,534,920,591,678,222,684,538,132,631,975,683,478,623,80,165,163,976,309,755,558,250,304,522,503,607,727,123,927,670,114,778,541,238,427,383,176,601,826,37,861,498,513,931,783,924,964,865,918,540,46,943,226,887,743,71,742,33,871,370,54,903,55,909,660,916,854,413,656,472,602,951,98,710,928,260,409,107,35,538,743,757,793,402,468,445,384,166,546,650,953,440,701,833,701,979,958,392,920,853,878,722,457,406,310,28,539,552,238,36,262,802,142,253,859,67,497,850,758,567,872,668,410,627,835,122,872,764,701,297,750,934,551,429,353,138,134,433,737,809,861,933,210,137,233,723,413,121,313,940,422,663,90,182,645,901,680,482,633,703,690,653,833,64,104,197,529,610,595,46,76,905,297,990,887,189,546,751,876,65,464,869,455,18,335,164,874,553,336,56,157,512,467,634,20,883,413,457,702,447,764,317,190,596,172,915,634,942,824,811,907,182,790,854,589,272,406,378,443,157,301,244,492,467,419,697,558,628,9,30,415,770,829,116,168,927,73,173,758,561,365,590,986,383,815,531,757,866,671,40,786,201,170,692,315,821,675,873,547,343,562,874,148,308,439,841,482,216,385,232,151,839,62,572,597,285,691,439,232,570,668,695,323,281,757,564,997,674,758,464,361,433,886,2,831,886,630,164,987,952,409,913,93,510,405,925,413,304,478,238,744,185,288,826,514,543,184,844,942,104,875,519,475,258,56,59,219,440,216,853,672,91,11,931,914,107,852,201,322,432,862,225,703,840,260,954,84,47,78,243,452,753,276,913,180,344,616,67,817,422,848,544,356,890,853,728,415,395,88,265,671,194,210,462,733,662,310,706,17,602,862,655,394,249,344,603,672,422,373,503,51,537,637,736,577,391,588,401,71,296,511,327,278,475,122,99,776,492,964,214,407,600,827,57,553,216,799,826,914,347,234,492,591,270,63,831,371,163,676,340,327,247,405,677,158,523,428,597,46,513,75,429,96,267,990,243,756,173,932,279,934,481,218,601,67,548,392,806,680,94,659,91,29,534,447,50,970,343,47,854,529,596,548,756,518,905,216,783,931,544,99,469,783,377,881,218,364,100,756,785,460,572,438,595,528,679,180,970,146,171,199,162,930,439,856,119,694,261,555,552,144,107,105,510,785,478,765,891,347,55,707,510,536,523,255,496,44,20,843,622,896,657,408,522,334,532,867,867,591,303,791,393,215,421,621,649,391,423,675,342,333,869,976,808,379,219,985,86,741,100,187,715,254,636,666,426,413,308,726,680,819,123,266,245,78,745,393,21,953,274,919,704,59,644,322,922,8,657,106,900,200,616,921,849,234,573,335,128,384,262,252,58,66,192,944,600,193,28,354,327,963,623,525,214,886,392,23,606,108,467,543,89,111,242,890,516,805,809,234,0,254,387,200,247,175,578,602,335,918,608,894,237,614,505,207,62,828,5,179,914,368,23,7,986,371,412,666,39,485,250,286,959,241,111,578,952,480,50,690,940,738,997,988,496,934,703,56,202,176,69,318,813,790,108,123,865,312,492,332,522,875,99,608,195,437,900,338,886,992,856,855,1000,790,560,730,508,664,316,88,6,853,112,896,359,959,365,972,56,313,42,965,616,747,944,67,522,608,333,86,515,150,492,929,19,331,432,969,179,255,226,807,385,627,150,983,679,617,98,357,555,219,947,928,886,368,553,8,729,206,65,724,26,75,152,601,364,872,83,980,17,708,879,111,156,134,60,630,856,59,362,387,241,854,209,227,875,346,317,362,271,316,397,254,634,62,610,512,171,647,994,537,154,553,464,292,732", +"441,932,216,348,652,124,333,755,632,500,133,164,844,66,160,197,806,755,868,961,396,3,39,918,7,189,953,241,970,525,553,415,391,404,418,876,765,797,783,637,233,508,120,850,907,305,729,933,477,899,595,911,287,268,597,734,220,348,811,691,415,41,413,565,972,297,299,616,561,612,892,806,780,75,950,35,629,930,876,922,280,929,460,421,158,141,726,847,214,75,602,476,388,128,19,986,521,657,79,489,196,189,99,828,430,20,727,50,333,731,665,867,600,255,145,100,987,132,560,577,917,811,681,298,271,665,781,699,629,767,3,154,891,790,120,168,695,322,237,28,406,678,539,251,418,921,683,278,2,261,276,858,853,825,456,95,388,139,673,159,747,241,618,466,475,180,860,742,878,747,263,727,216,893,164,409,799,598,126,456,409,160,438,961,215,591,941,336,890,794,887,700,552,99,554,338,535,869,137,960,336,640,892,607,264,215,377,606,828,566,823,796,392,573,309,772,144,461,201,573,820,447,850,383,656,581,542,214,394,237,500,867,39,337,536,927,808,412,223,566,920,48,949,396,851,947,363,622,113,921,547,827,850,361,904,321,151,353,816,54,396,333,92,274,359,337,265,456,521,271,116,286,345,343,147,224,303,485,925,983,215,433,101,774,244,38,819,863,249,829,641,498,305,113,699,709,995,963,411,223,156,677,499,137,477,235,496,513,475,257,232,733,44,773,973,179,141,313,59,109,784,575,680,236,546,713,29,378,680,803,701,209,275,477,92,597,11,889,548,449,565,908,596,497,284,304,20,183,444,455,944,527,870,488,198,944,117,978,602,162,212,720,798,148,681,531,631,230,986,25,256,667,61,212,431,156,693,50,254,572,373,625,237,867,472,453,433,934,473,776,512,658,576,482,234,764,506,329,568,364,526,927,31,927,966,476,72,230,81,668,418,842,594,85,542,770,973,140,959,898,783,495,215,236,737,289,406,322,888,311,953,632,288,480,970,515,588,341,705,787,162,700,9,499,625,619,555,566,863,510,204,673,896,716,511,984,731,159,826,91,425,746,814,157,965,800,324,180,302,310,952,796,656,502,380,98,664,84,7,707,895,741,935,205,101,416,772,207,632,653,828,62,836,889,232,409,258,684,885,529,629,239,312,471,181,566,379,390,734,272,790,923,650,372,668,178,668,894,94,944,153,612,345,275,808,472,335,973,964,342,764,541,125,477,882,140,923,750,110,261,741,735,934,702,919,239,207,923,787,642,662,728,56,226,358,150,147,564,598,908,685,589,263,557,947,538,18,75,600,493,450,374,124,219,658,682,405,258,986,553,931,103,141,26,254,773,911,744,795,716,625,976,870,125,358,805,782,626,986,281,582,664,950,83,611,684,735,297,25,133,153,633,904,605,478,453,198,496,86,907,501,311,37,304,427,164,816,872,291,289,121,905,589,646,611,495,19,33,595,864,611,841,189,110,694,246,820,85,950,984,114,421,662,58,352,879,636,843,831,492,116,382,706,730,553,490,830,191,883,535,868,736,794,974,160,545,169,589,526,646,293,518,35,882,757,46,546,197,373,274,145,614,476,662,603,485,7,425,503,248,72,828,898,656,159,805,257,423,290,81,884,177,510,206,324,46,152,755,257,714,287,516,672,406,930,905,554,374,860,522,425,502,523,220,904,110,688,903,943,195,551,369,880,848,10,940,715,439,34,391,67,61,305,204,900,287,688,300,124,724,408,108,689,641,940,683,482,880,324,656,641,751,946,308,165,302,588,993,619,134,699,854,636,891,221,300,591,568,818,752,789,349,953,559,701,348,893,820,96,872,667,587,634,700,520,783,593,515,41,107,832,714,817,224,78,310,856,314,462,23,970,340,489,254,0,283,990,898,843,653,37,620,657,831,438,602,352,34,919,627,310,185,97,843,191,558,205,571,18,817,718,125,72,918,238,772,37,991,255,706,115,226,859,99,322,717,584,543,315,277,24,338,714,895,306,673,644,36,958,823,776,742,452,518,161,25,699,729,637,348,54,975,665,628,246,337,679,652,503,116,861,196,230,407,272,613,499,182,866,941,409,170,403,857,746,945,84,353,256,576,190,498,761,43,951,3,887,85,312,823,418,643,60,803,386,434,406,788,657,6,873,117,42,892,674,254,18,339,130,935,865,577,666,512,413,404,728,315,645,30,663,595,621,847,500,817,588,904,46,125,475,328,562,307,38,480,915,707,101,991,947,193,400,76,842,26,759,442,809,467,359,29,790,663,863,129,723,281,354,877", +"822,603,409,651,447,348,493,565,998,865,900,923,513,18,828,337,862,953,345,343,437,811,325,391,928,808,937,370,830,775,751,697,804,492,688,277,710,140,406,437,441,374,729,286,120,743,529,828,60,813,940,907,836,801,434,193,690,172,696,941,624,539,354,862,137,263,175,418,50,18,678,521,762,353,778,33,63,501,987,438,888,397,454,45,702,36,423,501,721,399,464,204,280,854,650,286,266,145,75,163,160,62,773,437,476,269,371,221,90,174,166,328,763,621,330,321,141,566,623,787,453,661,103,599,614,696,754,60,129,369,725,282,778,455,335,60,737,554,327,441,261,567,208,233,126,999,241,17,630,333,252,683,111,755,348,74,129,514,890,490,127,987,556,976,26,193,270,307,938,985,352,896,644,705,406,201,845,364,16,863,52,265,876,678,843,743,717,12,609,925,476,375,909,32,812,231,313,843,174,895,557,539,886,883,15,150,819,452,104,223,201,912,45,623,174,798,646,633,673,467,279,721,564,434,771,32,899,436,376,755,383,993,758,899,463,682,389,580,103,922,269,537,967,926,879,999,224,967,252,343,35,91,209,472,228,368,39,910,986,916,325,79,582,427,216,775,880,112,933,897,402,53,400,685,825,967,66,285,586,27,164,665,736,652,932,345,409,652,224,932,685,501,8,346,799,215,38,979,436,446,594,119,609,423,115,882,867,507,591,777,133,316,668,80,315,569,417,811,29,858,997,597,206,677,624,881,415,403,490,85,192,437,846,624,179,940,707,304,908,610,302,676,883,30,615,585,671,194,426,614,443,198,949,938,91,42,96,816,802,206,295,139,991,745,394,160,234,410,557,309,78,881,46,619,764,40,175,290,15,996,926,707,462,464,126,520,692,136,97,818,534,33,18,27,595,654,382,591,931,808,394,838,662,188,721,824,918,631,53,156,715,839,342,598,172,930,808,414,297,97,92,514,380,872,407,750,64,991,962,24,802,947,842,874,782,986,254,329,38,288,18,547,789,354,661,513,192,99,196,158,480,819,720,171,78,418,993,617,765,420,628,794,383,503,670,971,22,223,259,887,480,147,95,648,360,581,435,763,979,626,421,118,748,192,198,924,703,892,709,782,205,868,651,211,495,580,617,935,150,870,144,734,844,424,660,473,444,239,957,866,993,434,902,144,788,963,156,228,546,218,85,186,78,135,962,686,459,22,689,285,941,793,619,731,178,230,730,722,565,776,266,602,632,530,707,403,447,250,719,936,735,309,169,360,308,111,515,18,234,931,870,847,233,410,274,628,976,17,706,30,863,729,217,887,748,258,832,28,619,255,971,721,272,837,567,268,570,94,204,432,150,343,889,422,179,345,473,985,753,966,398,798,184,398,289,695,164,565,654,607,123,87,116,360,285,103,656,87,276,49,141,155,241,347,320,766,524,530,220,122,109,146,601,733,643,872,765,233,536,243,272,882,276,910,597,793,1000,67,957,1,574,286,535,178,690,428,823,847,998,223,83,175,733,48,424,906,296,271,653,695,34,520,102,911,538,722,847,166,814,598,205,202,596,417,485,310,794,181,653,738,980,513,826,646,265,748,159,282,720,480,213,266,115,523,536,102,775,205,600,514,321,490,339,14,733,508,690,458,126,418,560,86,984,888,71,791,361,468,346,590,41,182,589,611,948,50,175,684,147,174,416,460,714,599,132,648,770,201,866,391,84,892,42,324,482,489,736,161,71,56,479,13,826,664,885,717,571,330,562,212,133,56,928,457,482,85,500,688,915,637,952,44,112,281,399,76,271,879,364,661,819,946,190,655,943,319,312,290,846,129,865,504,409,999,621,600,436,873,308,787,580,566,615,585,646,39,31,239,811,406,231,24,902,387,283,0,757,161,824,813,827,466,584,832,37,54,764,139,504,727,888,997,635,143,902,347,766,419,609,817,858,156,175,110,976,93,685,350,44,533,50,131,376,161,482,413,600,709,926,128,978,413,17,205,80,939,948,278,725,830,275,522,211,473,759,63,351,585,686,882,221,198,650,823,183,510,397,358,28,81,314,425,574,388,401,293,720,224,532,941,504,47,723,591,74,351,1,511,102,548,471,74,322,861,805,91,165,921,347,211,287,251,589,368,616,145,728,378,161,744,259,719,587,171,861,135,977,496,518,452,884,787,214,16,883,570,11,2,725,550,385,883,65,459,966,611,149,242,86,530,103,675,825,424,302,87,658,73,556,48,772,200,144,63,584,366,260,746,853,248,163,231,588,981,433,207,131,47,442,500", +"142,677,559,773,701,117,773,161,959,303,990,252,388,62,382,179,869,242,441,395,23,216,688,52,5,394,593,519,753,737,558,760,905,694,623,521,502,582,698,898,864,519,804,934,33,46,216,91,284,649,363,257,857,807,96,276,858,343,312,802,552,848,519,48,811,789,195,736,171,897,375,48,35,561,183,389,329,479,464,509,77,68,87,576,541,21,974,971,374,535,704,824,543,136,231,43,968,821,706,708,430,743,104,864,734,109,688,547,708,141,655,51,754,607,885,562,947,740,258,219,609,202,282,284,758,939,419,478,519,790,483,531,593,512,207,709,402,807,556,95,595,770,270,778,187,433,329,113,764,839,943,235,325,305,257,764,34,188,380,285,756,135,759,659,530,541,666,526,927,699,606,778,846,342,765,915,198,890,539,435,376,576,503,584,927,745,951,792,551,634,727,295,708,297,692,269,699,777,111,657,364,704,747,776,653,709,759,50,418,451,993,686,595,898,182,859,624,792,81,58,647,222,10,619,551,627,502,879,300,481,893,628,516,539,106,279,820,218,81,593,437,505,819,324,344,348,727,922,697,194,603,641,807,483,440,495,103,40,227,192,667,968,40,576,660,320,632,211,358,380,735,352,846,616,812,967,325,739,835,222,712,156,299,342,874,364,367,650,872,847,244,721,797,818,96,585,84,32,533,52,518,266,452,414,101,717,750,917,482,593,910,96,675,574,837,856,849,333,616,951,847,428,472,994,699,818,121,851,224,490,748,548,550,972,193,377,899,174,90,114,747,968,296,725,295,279,807,179,545,380,83,783,735,770,66,42,225,395,420,408,360,538,860,44,426,20,299,478,84,10,620,965,454,713,592,196,599,867,486,313,402,248,806,411,343,186,954,826,628,263,637,468,985,718,383,125,767,125,81,905,226,669,437,946,881,137,539,878,152,626,656,766,939,377,573,562,154,773,597,492,186,743,452,439,59,122,227,996,522,498,466,373,981,28,35,78,290,800,125,856,277,779,25,505,538,628,903,470,686,931,414,927,155,379,762,784,455,104,237,313,499,741,939,245,695,873,813,653,4,239,257,606,414,789,34,710,107,951,620,18,584,931,669,597,200,814,243,663,447,196,906,878,958,432,606,455,321,834,190,999,446,383,293,210,666,292,601,541,898,958,902,319,532,616,304,592,822,453,278,403,585,326,823,79,20,54,953,683,182,765,873,993,151,765,508,287,906,595,46,114,878,744,966,628,109,31,986,195,896,240,734,510,201,487,651,247,937,757,700,949,793,911,225,930,831,804,600,83,915,56,981,817,874,853,610,312,975,824,786,9,787,140,379,335,887,235,823,645,661,626,37,161,692,803,987,889,337,356,545,785,444,129,38,48,224,346,349,808,157,318,81,952,738,723,242,725,559,135,340,411,697,396,720,159,848,968,705,712,334,66,378,805,655,334,407,261,709,147,880,434,344,475,838,514,225,874,988,526,293,209,310,126,452,458,349,2,648,321,51,357,904,567,988,263,613,143,420,73,1,702,663,608,390,618,367,514,193,433,726,724,798,858,594,16,646,366,515,262,104,975,334,674,495,285,210,380,114,161,993,676,431,824,957,500,634,682,249,507,61,190,385,714,238,962,730,488,812,798,809,949,147,251,586,83,619,994,339,605,118,530,175,746,466,393,391,756,680,459,782,546,766,277,242,63,683,132,351,315,516,385,858,652,442,46,537,369,415,705,678,830,396,577,230,862,7,17,960,554,400,936,485,609,42,652,467,884,451,646,371,230,165,108,118,666,723,782,475,503,113,628,180,118,544,409,173,645,346,906,751,327,482,658,5,843,149,490,703,627,521,369,272,619,932,974,69,567,304,866,245,712,791,963,670,200,990,757,0,499,938,348,447,503,26,147,360,775,588,178,379,591,251,715,928,633,195,508,270,291,49,868,622,220,652,659,218,673,42,685,807,397,381,910,852,39,518,227,870,250,432,636,463,846,361,953,488,540,527,156,693,999,484,525,869,673,825,647,383,240,980,234,590,361,554,714,397,875,292,319,54,133,338,772,32,212,871,894,589,360,633,25,975,14,903,489,399,714,627,406,853,891,866,962,928,656,474,666,634,335,168,187,146,47,66,485,987,284,313,317,225,350,858,746,462,699,54,53,579,43,433,690,630,843,654,672,201,886,653,282,816,250,178,645,678,534,492,810,133,84,715,693,289,818,68,101,887,212,335,782,497,182,457,690,585,823,832,599,718,549,603,455,989,402,676,655,433,473,316,654,485,140", +"297,122,488,914,258,779,40,400,632,486,133,132,187,904,929,465,8,484,468,356,978,137,714,940,653,23,782,876,731,366,859,652,75,136,187,443,450,799,582,117,87,932,787,769,873,953,280,436,642,899,723,282,913,355,486,376,753,517,235,66,79,804,304,185,576,626,537,706,140,264,901,638,515,150,378,238,504,242,38,488,398,438,765,626,227,801,9,661,979,756,614,200,95,782,24,487,968,402,816,375,378,912,887,457,749,692,973,848,25,363,258,574,276,271,924,283,979,185,443,810,194,125,822,726,844,769,72,17,562,633,555,442,406,920,872,660,575,72,624,418,592,287,49,808,105,372,28,730,567,674,76,862,505,712,532,565,92,313,207,409,637,196,743,283,43,531,694,929,219,57,976,271,28,154,397,76,629,79,118,998,936,24,263,477,608,878,130,196,426,411,527,247,448,846,843,578,87,495,712,247,713,241,10,146,346,124,621,444,211,632,241,890,311,970,897,462,41,350,786,945,388,704,250,485,957,574,580,400,411,42,872,889,859,139,777,266,249,128,175,623,407,763,733,154,302,278,629,52,723,685,612,790,555,446,57,450,778,896,29,170,94,279,414,964,429,352,259,236,415,723,341,872,352,901,64,627,370,811,177,688,733,123,227,673,400,364,453,263,967,85,56,53,252,980,630,906,781,516,379,754,216,109,281,607,646,369,761,45,273,148,349,65,609,873,856,863,762,393,878,116,73,988,127,16,890,440,256,47,889,336,235,930,639,159,310,166,936,766,609,783,594,973,343,730,28,72,969,856,209,868,244,786,953,799,63,282,421,86,587,87,335,133,640,818,759,853,450,290,270,722,501,423,336,984,339,383,886,413,432,53,530,654,250,366,382,373,473,79,403,531,326,826,479,584,670,556,112,761,737,580,363,193,11,8,679,967,867,114,257,770,211,758,68,188,724,882,169,273,458,297,631,741,920,49,263,435,108,531,845,483,825,646,515,188,845,475,802,103,887,954,131,514,292,798,659,975,596,576,48,545,727,671,305,51,258,516,904,951,577,557,47,475,239,697,205,521,604,644,772,438,283,156,568,87,502,248,494,892,446,696,940,999,758,41,859,905,793,932,653,819,624,509,813,566,914,525,535,240,788,244,267,440,872,393,525,540,455,142,761,35,989,239,436,206,287,981,701,581,89,178,413,885,462,854,351,633,844,446,272,75,880,400,967,865,605,277,842,606,732,779,610,629,186,393,259,431,453,82,327,164,324,853,214,40,665,90,556,495,668,953,246,542,341,73,809,402,885,469,73,235,758,254,107,515,441,773,484,96,638,101,147,898,101,463,106,732,521,57,130,714,300,77,339,594,580,348,583,531,41,121,798,662,691,80,761,626,961,273,246,323,745,230,953,688,759,915,891,217,392,460,421,623,456,362,835,635,314,849,531,740,102,485,490,326,448,80,805,410,872,888,5,182,507,790,154,716,407,93,924,284,627,900,938,389,347,803,533,629,455,254,449,370,779,569,579,532,79,47,45,292,641,426,259,927,726,712,920,764,757,756,902,450,493,506,551,967,11,583,103,622,554,125,642,245,588,644,433,702,339,287,987,927,349,81,728,687,682,204,777,102,399,3,612,464,255,781,314,209,202,523,412,849,123,342,620,331,821,14,154,150,155,615,676,398,64,375,854,751,197,742,999,514,225,904,598,316,714,57,153,860,304,151,533,457,899,76,412,844,20,528,873,272,791,482,82,787,910,250,695,950,783,63,628,423,735,83,841,521,677,804,466,663,243,254,19,308,228,693,384,198,972,981,419,549,689,412,924,254,953,388,701,370,926,668,947,24,90,76,986,919,293,886,236,953,660,37,390,26,333,744,238,409,290,247,898,161,499,0,174,914,224,414,850,264,549,610,132,450,850,503,469,840,265,499,702,387,465,542,251,531,783,385,935,660,551,836,193,206,934,967,849,65,951,708,556,387,9,188,474,139,699,299,211,18,168,34,974,442,378,441,112,254,453,600,505,537,38,592,643,730,829,544,704,215,106,516,172,370,50,49,503,24,257,195,388,695,437,24,541,715,347,730,989,869,455,521,355,463,212,168,76,616,346,94,892,522,80,942,728,359,494,43,356,873,62,327,222,932,283,790,550,403,105,986,601,420,429,484,728,767,675,301,270,400,553,352,272,859,764,467,687,349,320,233,429,162,717,941,971,48,353,730,153,368,521,527,185,537,717,42,634,719,896,339,372,241,997,78,327,787,440,966,955,374,981,58,694,745,206,84", +"409,731,511,494,565,827,129,423,45,87,261,857,724,989,255,196,30,237,862,439,884,950,159,383,77,399,38,662,622,40,495,101,194,369,786,395,193,153,36,778,807,866,836,858,982,542,148,665,28,500,226,440,776,354,707,363,156,148,348,985,143,559,25,643,962,855,305,171,136,823,273,378,397,942,141,531,3,523,166,904,384,652,554,437,184,585,568,13,775,690,302,969,303,726,95,561,825,988,98,649,770,551,801,485,674,435,49,342,748,290,198,543,351,822,907,116,490,37,291,304,846,865,921,984,129,346,231,874,441,270,347,278,689,828,459,501,57,144,275,713,916,480,272,320,324,744,216,70,256,221,420,385,69,243,657,794,221,139,346,338,162,505,144,567,970,999,388,984,727,526,826,232,993,261,882,918,169,355,666,294,175,590,664,44,538,108,429,29,553,416,904,701,390,384,461,44,718,961,255,785,670,344,882,750,986,979,44,191,655,403,695,297,595,855,685,504,351,958,354,320,349,15,458,969,811,237,594,754,556,583,481,646,994,427,714,381,374,864,130,32,392,112,46,286,903,727,196,206,131,185,66,7,338,476,312,294,129,534,710,345,390,767,520,301,719,705,580,926,581,274,934,745,942,729,108,938,534,956,59,880,960,774,369,715,784,389,219,754,288,987,574,853,423,391,733,915,82,315,935,987,454,956,715,430,242,296,590,307,179,703,653,867,940,934,495,49,731,970,9,193,175,86,865,980,751,428,872,691,691,843,205,797,658,386,390,657,177,402,835,935,985,199,623,548,479,200,611,344,87,601,113,335,66,745,937,62,257,692,85,871,239,176,455,879,659,342,827,243,823,441,696,238,6,398,227,181,478,95,231,862,568,495,601,914,214,264,259,19,193,414,358,36,111,441,917,687,955,885,773,122,775,680,78,617,955,541,264,956,841,425,583,151,778,654,112,74,934,740,622,463,61,551,279,482,544,900,123,849,280,792,695,280,20,231,620,592,899,141,219,880,914,989,483,978,260,45,550,282,233,616,879,207,79,781,761,68,222,32,301,460,612,443,449,555,744,524,283,509,982,106,93,909,277,178,325,922,369,853,774,287,165,564,201,284,102,781,710,360,26,428,937,112,162,212,143,474,315,550,956,563,687,729,225,765,184,39,660,938,628,76,767,232,110,178,244,890,393,513,829,188,870,393,266,586,446,191,529,210,948,149,886,183,240,355,949,772,502,116,298,432,764,652,34,89,679,744,101,213,368,326,592,811,682,747,777,254,64,391,187,535,793,125,247,664,70,204,862,382,342,430,515,114,194,299,354,656,699,926,995,712,275,219,693,804,643,809,260,560,660,894,97,320,593,438,394,12,968,413,725,742,36,602,583,885,327,23,917,32,492,183,676,680,939,17,302,684,680,545,970,931,122,915,203,874,30,782,512,891,208,856,443,818,525,70,511,360,408,896,694,7,764,147,237,584,179,17,388,668,322,52,229,603,350,570,558,313,526,328,128,827,55,810,590,360,905,512,428,418,491,836,273,523,807,132,468,924,360,587,410,699,881,456,483,510,210,157,959,573,821,430,167,913,403,910,950,709,40,125,907,291,465,681,530,90,937,778,99,895,450,556,520,235,291,730,762,14,99,888,451,899,73,899,96,193,373,714,740,317,138,183,116,63,788,181,965,747,575,742,668,659,672,179,681,853,807,52,429,394,417,894,679,551,497,135,128,784,330,64,190,781,624,994,917,413,820,627,708,850,954,996,529,743,157,926,781,350,859,362,695,712,395,143,989,442,426,39,697,879,886,846,871,488,278,442,301,204,67,484,634,332,265,181,378,141,889,677,659,490,200,966,579,454,927,817,242,181,228,81,515,424,557,408,723,175,843,824,938,174,0,644,977,172,545,114,611,888,586,617,153,277,284,829,203,383,552,323,282,900,883,463,392,443,837,238,804,81,551,204,328,382,734,303,92,646,583,328,493,177,943,890,316,907,752,447,985,928,473,591,712,10,124,86,367,688,19,686,289,258,507,479,171,309,463,213,280,314,282,522,946,613,227,291,12,538,703,299,751,681,973,408,457,749,286,173,176,826,150,796,707,190,667,366,789,63,676,957,562,673,196,917,681,114,634,541,393,225,866,901,300,948,446,468,578,969,813,452,218,555,288,701,64,416,797,285,80,694,785,352,741,249,903,67,474,802,477,344,614,980,814,180,131,836,905,194,536,743,161,77,434,296,835,302,415,733,773,576,284,409,823,500,249,797,924,267,437,968,664,876,212,487", +"773,939,618,387,510,951,638,114,673,321,770,122,928,475,88,127,319,29,205,286,587,957,565,248,644,883,665,192,228,827,848,219,356,827,496,814,875,679,909,779,219,181,417,809,137,458,142,196,13,940,594,620,477,136,844,959,287,904,342,475,241,990,213,561,40,964,341,43,655,305,714,25,84,199,724,187,984,359,218,816,497,484,260,565,160,631,707,880,746,191,821,248,644,18,296,649,436,479,123,941,624,966,699,244,124,595,727,235,353,844,20,615,207,147,306,312,253,380,516,993,550,368,616,224,296,524,493,33,954,589,176,745,845,619,451,273,560,468,873,601,342,685,405,754,406,543,378,738,217,420,845,320,557,552,556,872,109,920,120,726,920,921,611,9,398,751,783,18,971,665,978,379,320,667,881,762,553,15,228,418,563,233,76,623,901,95,782,598,539,123,434,640,641,853,715,90,888,888,68,970,670,471,558,745,205,967,564,757,992,888,410,79,862,1,863,316,725,246,245,579,489,650,81,180,744,933,731,526,535,313,25,202,979,180,628,378,182,699,367,407,617,484,382,697,463,505,765,622,455,792,584,329,55,793,494,19,281,315,168,91,218,237,235,914,529,706,313,452,382,645,718,515,841,680,214,416,840,727,673,222,419,494,258,408,498,541,311,838,597,139,846,362,722,774,405,228,81,386,108,589,306,56,797,467,90,48,539,924,126,164,179,266,749,595,309,852,699,129,986,757,297,731,435,449,977,81,849,520,828,778,181,474,920,719,63,888,299,88,55,258,548,298,151,747,158,668,721,200,430,558,464,611,402,641,886,588,90,723,285,304,175,780,874,415,134,861,224,388,867,241,429,223,201,209,851,102,933,808,564,728,999,101,800,682,763,834,258,683,192,491,721,43,21,347,550,726,809,236,364,93,746,273,127,348,629,339,220,940,374,873,136,815,463,856,278,148,430,62,296,654,955,71,967,854,624,785,453,612,914,895,778,602,182,291,662,588,301,710,260,531,294,191,39,35,267,923,419,440,468,565,658,710,560,561,446,200,278,439,388,306,559,40,206,978,416,207,433,111,463,47,612,757,662,920,805,276,897,530,686,344,347,174,671,617,876,994,56,745,861,682,582,67,361,264,119,794,780,185,612,26,300,638,663,64,983,522,31,779,161,462,996,347,363,614,488,80,416,575,177,286,593,330,568,244,592,266,187,14,892,997,149,455,423,485,509,387,38,947,92,926,823,882,708,595,722,810,705,119,41,963,345,765,486,301,107,800,487,608,591,185,128,41,25,974,986,549,644,376,167,397,637,714,560,768,826,334,48,628,406,351,864,736,59,106,398,937,518,725,539,41,455,947,32,158,253,488,257,563,425,776,771,124,143,73,577,670,913,306,576,764,157,102,526,928,350,274,75,997,796,455,837,463,358,563,879,650,297,292,847,791,741,713,96,296,755,567,469,562,341,636,57,915,150,510,235,359,949,753,532,781,44,381,368,326,7,163,678,507,790,864,193,460,793,539,413,256,771,349,518,374,683,783,64,584,715,78,577,145,504,501,365,382,437,273,222,665,902,171,303,463,59,919,887,58,882,497,568,998,71,927,288,692,495,709,597,950,803,616,424,353,831,180,552,791,798,933,265,800,453,663,629,742,882,725,790,691,436,672,821,882,569,540,65,105,502,756,420,805,866,789,722,371,25,139,811,534,48,475,979,886,712,503,176,267,224,193,569,708,687,639,446,871,415,80,164,206,322,721,783,661,707,645,697,211,504,652,328,501,395,182,547,855,142,350,338,871,271,262,989,921,788,533,139,150,282,190,646,146,137,695,284,189,200,99,519,786,589,999,878,932,333,188,444,55,854,315,550,196,510,6,194,154,466,578,653,813,348,914,644,0,845,135,945,659,791,103,839,224,860,1000,553,895,107,451,439,960,183,215,72,71,570,194,458,215,433,319,408,840,733,821,174,540,64,886,91,268,109,837,889,473,48,953,374,832,982,682,442,185,787,722,912,959,23,153,501,918,47,705,207,219,268,978,647,749,305,548,680,829,814,531,259,315,933,280,275,360,198,203,373,392,344,220,375,937,175,775,926,847,378,913,356,745,968,651,754,98,813,831,813,142,75,407,73,424,341,906,765,96,967,868,230,274,711,832,440,242,84,868,532,625,799,713,84,962,835,757,918,144,593,962,59,465,93,648,755,191,221,484,228,966,450,5,704,729,704,778,977,77,21,412,728,777,433,455,257,326,306,587,938,701,347,905,817,309,712,151,402,7,671,316", +"356,960,766,644,804,762,642,114,814,859,834,400,953,495,356,906,605,119,448,341,494,397,779,742,394,87,927,123,321,629,607,108,594,740,470,293,629,664,696,363,440,294,535,988,834,196,445,504,384,922,403,870,358,250,942,821,984,530,34,792,591,32,175,667,428,941,820,973,219,467,286,90,554,253,383,30,561,988,926,285,64,335,214,916,976,661,633,916,217,501,76,720,54,184,377,129,684,331,355,74,285,543,115,304,722,799,760,689,569,703,935,898,709,438,210,864,342,795,755,575,821,886,355,281,107,225,364,73,962,496,90,144,572,366,521,546,420,806,616,706,652,212,247,479,554,630,257,759,8,327,259,418,664,11,128,148,865,198,246,543,832,806,270,353,36,562,963,22,916,138,19,918,103,737,221,669,240,117,699,781,565,318,783,814,199,137,52,820,751,565,215,274,128,480,651,12,779,438,481,804,867,755,757,356,949,876,597,376,328,725,887,767,58,276,678,530,414,529,410,593,350,179,962,755,478,366,190,104,608,177,629,751,837,956,328,909,74,139,729,895,651,623,491,316,279,72,562,147,573,369,413,685,942,827,671,842,306,72,684,999,159,521,134,384,357,752,679,783,158,479,235,551,644,388,161,545,456,783,510,195,78,499,872,428,111,366,791,360,195,973,950,402,448,877,715,367,665,456,612,242,41,312,573,721,766,579,194,197,812,19,702,415,319,619,895,409,998,337,581,747,32,867,354,98,181,794,303,565,616,309,459,466,947,588,24,976,20,521,832,971,645,307,468,442,410,807,770,347,355,459,891,78,751,268,507,184,690,184,365,827,751,224,298,611,913,147,746,932,39,18,306,785,731,112,775,388,24,223,949,610,549,522,175,955,973,109,949,510,796,237,598,47,423,721,195,16,516,366,248,940,28,901,626,221,904,319,33,282,113,155,178,722,174,465,608,382,276,731,115,47,632,34,664,43,893,912,331,325,136,919,494,22,606,467,30,323,837,718,92,306,344,440,112,6,160,485,664,874,499,439,713,779,671,105,706,465,88,975,457,166,444,991,141,443,69,199,561,888,782,500,790,183,36,844,272,124,697,616,697,354,311,149,193,387,459,169,472,252,813,944,985,722,309,597,153,471,440,123,971,807,450,436,736,803,141,994,629,195,578,694,473,581,793,88,522,539,413,69,627,131,505,306,743,281,96,815,928,372,266,979,693,452,312,850,221,728,445,85,255,661,905,461,122,804,598,650,334,515,179,502,937,262,775,324,179,338,602,511,281,173,747,77,252,994,848,970,633,176,213,960,474,537,133,815,480,121,16,742,997,627,374,505,388,783,547,567,380,209,172,992,524,526,14,782,601,562,582,942,427,217,489,487,61,541,677,954,835,785,484,360,486,387,856,545,335,567,965,914,861,874,491,250,439,702,197,286,384,552,457,745,346,401,490,528,405,185,491,376,450,696,481,573,181,64,588,429,652,888,644,382,521,927,805,995,332,902,540,670,795,39,57,260,217,136,9,87,948,908,226,144,88,8,13,992,615,665,193,911,913,592,333,982,668,736,968,490,236,243,838,355,638,63,496,415,294,737,171,472,627,55,227,704,769,733,255,779,881,357,678,264,774,341,468,434,911,484,544,182,547,723,694,545,19,777,221,358,355,515,636,265,35,859,96,311,279,873,234,82,789,483,747,926,549,981,557,405,938,800,660,430,666,591,22,251,239,27,596,960,252,714,690,578,612,261,85,929,423,988,927,359,37,849,364,846,590,376,478,930,667,708,975,261,484,834,606,722,123,648,775,913,246,616,776,846,829,427,601,415,144,164,62,616,530,240,590,552,937,209,67,291,860,524,716,655,896,996,63,991,461,500,667,573,193,602,37,827,447,224,977,845,0,427,421,564,285,499,634,567,738,182,305,865,280,789,906,364,246,185,407,225,713,32,284,281,130,875,662,219,395,569,337,373,315,247,975,735,141,33,737,261,32,390,237,721,401,316,198,822,451,552,41,421,86,707,573,438,147,439,904,887,925,291,390,178,810,384,143,975,137,454,197,198,443,651,91,569,910,902,272,341,200,418,131,332,342,262,263,747,228,341,653,560,768,143,581,328,339,155,280,480,679,149,659,231,510,324,136,899,371,333,565,908,495,704,37,478,427,880,498,723,166,694,553,223,266,29,934,894,157,605,727,455,89,186,30,551,901,114,966,503,687,45,609,797,927,194,825,191,413,255,107,102,564,377,445,726,955,461,462,658,246,143,441,773,6,869,973,162,281,818", +"890,571,232,66,90,679,914,875,924,363,318,608,555,47,153,654,631,598,107,563,71,43,451,203,352,883,110,841,579,435,402,773,220,119,629,419,731,38,569,635,673,752,278,861,544,204,143,250,472,184,811,430,741,656,138,442,562,590,592,833,746,818,952,100,569,649,209,912,40,998,879,44,326,247,800,878,931,59,769,575,883,571,705,856,119,446,488,974,685,784,357,439,266,590,382,677,795,448,79,943,576,398,636,569,663,180,623,292,234,230,140,534,995,715,356,888,361,401,409,712,305,663,33,495,539,899,599,689,632,195,584,782,775,645,123,797,161,463,519,81,480,410,143,549,240,183,468,574,447,497,490,915,935,150,899,543,969,330,377,751,12,304,806,958,443,177,669,655,964,55,444,154,575,708,634,129,971,297,920,28,40,574,447,725,752,321,623,432,322,737,166,761,678,432,531,320,944,855,371,219,595,680,531,222,104,665,418,862,606,812,258,666,729,454,855,591,132,136,766,205,915,450,191,122,404,207,819,758,941,913,22,28,172,596,213,722,622,845,886,648,343,844,321,452,497,288,551,619,566,857,606,114,873,264,488,270,472,878,204,19,659,13,396,710,174,188,393,886,866,339,786,385,239,680,72,379,286,328,430,703,890,813,460,674,774,769,464,482,565,557,30,151,974,679,974,398,820,897,487,465,534,749,739,61,733,823,371,636,596,168,599,338,248,533,100,379,773,218,910,101,498,840,238,721,668,873,89,99,987,502,693,994,181,823,59,899,604,537,664,208,816,567,965,989,496,733,775,991,229,786,245,554,806,638,601,625,912,875,81,296,476,877,333,386,233,96,377,613,42,216,731,886,178,850,365,515,567,397,63,860,660,208,329,863,841,868,92,450,701,89,6,727,183,100,927,198,949,188,675,78,884,379,345,423,962,974,563,591,186,866,225,220,329,576,210,1,708,135,234,619,927,593,541,339,306,602,777,621,884,560,18,232,697,113,879,652,137,804,958,376,983,184,43,48,963,300,372,775,816,498,81,328,647,419,783,806,778,151,768,525,798,620,447,108,269,807,149,666,323,546,773,897,234,547,487,943,295,137,242,674,847,208,499,307,915,163,214,427,972,755,291,636,459,631,620,972,563,964,611,518,166,657,351,82,147,68,225,685,577,939,671,330,131,465,974,639,345,155,957,707,329,323,935,599,327,89,746,994,39,680,422,671,51,436,675,163,205,481,972,783,497,511,129,2,876,265,147,327,849,306,148,507,555,675,524,652,629,917,639,972,850,713,880,369,805,273,691,445,577,247,936,899,338,280,654,973,828,544,918,258,489,167,760,116,514,150,358,166,917,887,504,511,718,609,647,695,437,825,143,783,767,617,765,211,48,728,405,895,40,810,707,212,293,801,483,668,700,652,567,398,259,538,193,507,106,706,985,267,4,323,220,922,788,154,541,890,58,401,573,162,5,244,303,660,205,485,132,162,281,751,628,950,58,601,699,948,12,425,753,614,633,478,799,889,31,44,819,975,307,419,228,954,931,868,431,593,434,78,737,855,170,367,528,865,897,378,710,684,542,909,738,122,370,439,80,161,618,392,605,621,394,564,576,596,324,753,302,555,11,797,917,419,488,734,487,917,727,597,611,50,563,110,588,287,286,164,943,598,222,103,982,993,155,679,306,494,810,821,155,408,403,855,23,689,742,611,485,286,339,314,1,312,82,725,616,111,592,950,830,843,830,271,262,798,744,8,888,652,97,573,24,627,376,889,771,406,594,124,18,149,646,387,987,141,636,156,36,418,721,547,434,697,339,670,459,218,509,836,62,838,460,373,337,168,413,899,460,754,46,515,50,565,703,978,692,375,310,67,333,73,311,677,671,335,620,466,503,414,172,135,427,0,616,998,885,816,677,94,870,131,138,831,989,552,837,703,296,171,57,161,654,610,192,867,24,846,923,47,342,28,707,733,930,707,745,714,622,768,68,358,456,65,527,252,163,921,908,598,265,989,783,838,492,820,946,461,101,72,517,884,342,823,388,183,271,553,524,68,916,529,530,637,929,152,496,153,605,509,986,115,25,529,950,97,927,615,964,752,2,278,384,199,826,500,313,50,38,668,593,924,850,32,706,724,794,181,235,777,815,369,8,724,358,889,417,10,774,997,142,752,504,307,977,841,54,890,19,419,343,758,106,817,978,424,807,188,984,800,468,745,804,538,911,935,429,270,514,527,344,651,676,349,543,935,435,432,171,11,978,450,235,819,225,209,94,429,399,991,690,608", +"170,430,239,219,290,837,908,963,838,180,217,818,453,885,785,850,613,340,317,338,176,313,644,828,443,189,375,483,761,257,700,705,600,646,150,936,475,260,450,720,369,121,346,763,128,795,686,429,176,222,565,906,593,562,648,183,590,156,288,49,681,191,774,812,725,774,424,869,179,294,510,610,826,528,358,716,703,914,142,804,835,29,673,804,276,364,209,758,757,105,587,46,196,44,693,944,318,343,527,491,850,133,304,914,583,353,682,221,135,665,93,535,301,578,264,855,498,347,358,978,206,9,60,879,258,230,83,25,86,306,973,741,241,957,563,143,437,983,181,355,319,996,948,596,217,604,719,104,887,100,617,161,356,601,502,705,720,727,443,30,684,120,117,89,453,297,578,315,111,648,643,545,326,371,421,667,297,837,360,856,787,551,589,587,413,562,249,223,747,193,830,120,874,333,859,347,761,917,639,230,887,765,252,842,300,859,794,457,761,726,213,331,808,786,676,619,972,188,213,421,685,281,220,924,220,528,997,24,973,975,347,281,89,302,516,47,390,434,543,248,779,13,453,367,805,978,973,239,777,950,268,462,731,235,839,264,110,476,847,630,482,459,215,202,66,868,236,200,606,99,928,225,622,262,902,208,159,604,881,588,998,187,967,32,778,631,437,587,77,657,900,98,842,47,738,543,805,166,749,354,874,231,42,744,440,165,808,623,390,733,831,117,462,556,691,711,738,395,768,456,286,895,523,714,958,877,470,624,89,776,602,285,626,314,801,196,511,624,915,531,486,614,923,390,948,655,233,72,332,766,715,508,637,508,897,555,427,187,243,655,808,578,426,556,591,165,653,564,5,84,839,459,467,425,578,690,246,281,623,829,171,996,308,72,875,775,993,845,378,364,581,752,798,172,225,113,301,627,396,157,850,598,481,928,299,957,694,192,958,214,47,907,582,453,5,519,552,870,638,818,128,109,76,948,369,104,96,170,892,881,166,682,4,169,686,911,212,469,99,892,964,627,908,906,270,980,314,56,930,601,638,368,708,358,186,392,834,666,614,489,582,317,675,311,760,648,358,494,969,788,629,730,288,720,911,299,847,548,482,962,141,531,14,7,142,736,847,874,530,557,979,201,416,216,986,394,144,381,774,987,611,747,529,573,684,667,925,294,736,328,695,657,792,169,305,134,775,860,852,985,138,100,705,292,371,215,343,864,756,86,953,28,259,298,117,236,735,970,4,626,857,844,662,924,921,740,929,382,512,124,101,204,846,719,151,224,439,885,639,392,382,486,407,761,231,960,208,273,114,616,595,622,639,215,910,186,140,358,432,473,151,423,879,12,668,931,159,539,712,60,866,788,530,92,108,185,785,455,216,281,930,857,843,564,195,160,41,583,303,939,465,164,290,571,278,835,195,411,74,82,563,539,222,629,722,221,386,864,945,215,515,234,92,24,983,190,994,895,640,735,567,773,135,69,730,115,305,362,731,827,756,943,485,413,848,680,346,603,871,308,813,194,209,176,340,993,917,965,41,279,956,588,636,186,35,823,678,544,239,596,918,921,36,247,642,851,932,214,407,700,563,405,467,519,909,232,353,336,164,508,582,851,132,280,74,541,426,67,835,496,674,656,146,181,778,311,198,219,911,677,94,170,597,137,293,215,911,961,402,99,750,904,595,934,468,414,723,46,615,805,953,508,719,146,176,161,461,421,194,464,780,278,660,634,371,595,566,136,668,123,147,429,752,500,217,607,98,160,265,447,435,521,145,535,454,796,271,964,720,545,20,978,112,413,790,903,470,505,428,827,922,186,502,846,929,550,636,113,617,847,365,750,567,859,287,447,24,273,91,827,694,908,207,547,539,105,77,895,641,914,355,470,9,918,657,584,26,850,545,945,421,616,0,131,138,779,305,732,540,722,780,724,691,938,283,465,355,608,420,455,470,965,221,307,741,749,167,123,153,574,901,388,740,656,157,126,724,521,841,101,447,729,561,877,489,898,893,827,363,966,319,711,964,834,825,806,845,90,39,646,2,454,726,477,989,726,782,132,484,663,526,684,864,378,183,838,757,523,344,360,217,865,487,984,144,127,61,801,328,972,425,227,706,825,559,632,630,123,826,204,654,835,725,889,733,948,785,581,495,892,299,682,999,52,988,959,266,581,159,386,950,204,201,965,449,693,513,348,131,571,11,450,702,671,950,786,137,296,828,436,533,474,187,911,666,915,320,508,8,706,173,822,137,252,110,656,637,625,769,616,182,411,399,15,209,312,386,306,507,310", +"201,280,591,333,221,892,880,88,324,204,435,644,604,878,402,426,605,402,485,65,748,902,360,72,669,432,422,165,637,140,615,283,153,155,582,599,633,597,682,222,582,143,445,982,550,714,437,948,414,425,435,166,656,184,850,535,279,890,637,993,455,181,972,961,481,353,743,149,228,607,731,747,456,498,813,780,616,485,15,346,177,557,697,721,693,72,213,728,180,671,919,771,353,998,661,328,707,226,758,258,270,866,171,404,873,891,824,707,572,690,117,936,641,372,889,256,127,293,803,528,215,466,205,270,570,83,298,973,311,989,840,274,72,745,658,120,24,201,241,35,319,305,287,593,832,790,445,706,908,136,292,401,145,564,577,28,341,421,396,623,396,139,280,803,77,253,543,570,618,250,207,392,146,355,346,749,254,684,208,196,339,866,340,976,99,492,919,825,44,839,887,157,257,32,773,548,397,884,969,714,402,591,504,400,183,793,153,494,40,706,184,570,924,565,417,52,973,614,354,257,55,395,211,982,669,614,78,236,756,916,931,93,293,680,785,232,791,145,384,634,892,675,218,585,90,381,971,583,932,256,432,388,48,217,970,636,526,746,1,274,557,615,865,95,626,968,710,67,166,323,912,512,579,65,267,273,990,297,808,22,61,277,153,164,206,921,930,732,850,628,521,940,80,194,456,974,343,655,162,355,989,928,249,879,338,393,70,511,49,410,120,397,509,983,825,457,940,350,894,443,913,321,209,556,981,541,214,552,170,215,117,77,883,338,534,992,113,467,513,861,198,938,55,893,251,47,325,47,465,391,382,562,746,998,367,820,916,483,671,183,166,633,247,98,948,337,145,489,287,604,485,656,841,17,431,394,661,644,515,643,319,531,949,640,89,367,203,154,29,11,512,81,356,638,920,935,107,304,988,350,593,984,493,613,440,666,366,331,879,796,678,602,105,755,459,127,258,476,323,877,905,548,931,268,615,274,322,32,772,155,653,279,342,592,709,987,852,847,797,443,410,265,389,328,673,23,638,704,290,690,7,710,413,662,66,428,268,89,50,910,982,574,244,460,632,867,280,424,222,932,288,934,51,601,695,755,679,581,862,970,854,33,811,866,239,937,739,322,795,812,249,635,277,938,126,699,92,380,60,314,719,70,431,256,560,394,39,734,173,928,785,40,542,892,973,461,954,105,150,490,132,967,235,822,98,514,120,780,497,712,832,332,848,875,237,703,672,454,732,172,287,724,751,841,89,462,470,95,362,269,463,756,593,505,988,87,345,440,231,532,246,243,428,50,447,864,546,851,735,402,649,729,869,128,660,505,288,701,864,803,792,581,589,59,874,311,678,445,359,968,607,687,872,28,202,955,698,897,366,5,575,271,577,340,179,673,412,869,434,110,869,816,474,938,287,253,861,568,392,142,184,514,715,435,120,508,158,38,19,409,368,505,26,767,607,158,339,217,391,744,125,823,604,690,72,667,230,34,879,88,946,684,516,348,628,31,918,80,553,288,727,575,546,908,952,334,826,410,104,635,462,749,181,853,887,385,623,736,799,396,844,551,864,457,682,936,453,864,821,266,496,953,616,320,909,144,846,101,935,976,778,626,969,69,999,422,29,305,888,121,422,551,937,16,87,698,620,676,455,21,379,662,992,642,358,213,77,272,923,189,833,233,891,352,112,573,896,660,473,974,863,734,635,164,877,274,778,435,449,616,875,351,13,356,231,468,407,40,748,583,779,833,656,802,608,230,452,337,137,386,311,319,419,834,488,150,618,369,422,384,4,159,390,14,667,201,870,965,551,126,604,249,986,332,963,405,255,849,459,489,684,119,889,10,363,609,713,257,310,502,699,873,705,436,276,141,886,558,741,271,852,579,714,608,831,832,147,264,114,659,564,998,131,0,2,338,778,621,543,113,527,452,327,13,387,937,802,931,781,677,132,751,613,922,966,831,314,860,715,919,551,492,541,704,918,471,959,674,298,951,743,601,977,86,411,265,62,609,191,108,334,505,258,301,52,725,169,604,518,276,812,692,455,436,781,683,507,536,592,904,43,117,789,375,775,827,366,790,109,418,359,594,64,966,128,272,808,267,966,318,974,397,917,346,920,765,792,515,926,764,47,373,889,581,18,559,387,102,449,116,461,228,72,242,177,467,517,173,989,171,125,138,191,644,833,947,85,258,909,838,214,261,341,293,59,774,740,201,486,647,253,262,277,31,949,515,535,826,153,486,616,423,244,835,827,903,636,649,270,179,239,760,849,59,415,242,74,458,603,789", +"815,976,556,87,926,640,163,645,994,535,235,319,205,650,488,710,893,346,816,381,618,367,940,32,793,74,698,478,854,176,126,946,194,543,345,5,284,595,194,817,356,348,222,616,59,772,40,233,496,445,783,85,840,456,494,835,775,357,49,892,361,578,115,753,596,817,25,576,623,824,303,348,71,923,368,337,890,370,21,205,981,454,560,260,953,395,159,761,453,439,855,647,571,793,35,535,860,533,413,14,113,710,759,355,757,67,69,197,386,258,671,273,778,737,508,147,735,354,283,21,292,250,657,810,246,945,536,168,674,881,701,64,703,274,727,272,16,506,148,395,48,433,979,475,324,643,406,942,746,680,71,77,511,238,383,899,390,977,499,954,989,70,756,688,298,730,530,398,111,466,820,759,563,509,881,196,400,868,477,658,821,658,198,198,236,216,120,152,963,977,718,162,149,772,958,619,562,138,278,741,423,551,189,433,862,385,104,748,698,887,473,262,384,264,9,329,207,871,58,251,279,139,477,241,734,682,189,117,835,790,991,122,46,874,575,731,258,859,833,19,758,89,98,965,814,8,924,941,100,898,474,718,490,646,7,79,616,468,348,148,777,785,12,978,808,25,837,949,555,635,16,190,811,38,263,526,515,226,24,915,190,257,870,994,882,244,58,387,984,259,627,735,948,489,187,245,901,610,899,413,726,303,405,544,769,68,840,127,939,72,283,213,815,960,299,922,929,713,792,433,452,727,651,374,445,176,811,874,662,676,294,598,875,750,326,356,304,78,330,91,6,247,363,586,959,944,580,985,930,799,774,429,575,69,170,276,110,707,993,692,447,373,784,954,458,736,601,284,66,633,885,114,123,910,601,284,901,982,419,706,973,156,895,289,767,216,609,22,769,914,945,158,935,455,770,531,938,552,146,634,95,533,744,598,452,573,838,385,100,515,602,458,589,450,233,236,417,339,742,580,47,928,668,179,290,724,894,859,520,392,64,496,805,712,938,276,446,274,814,715,234,166,984,113,154,984,59,219,845,601,449,55,414,920,928,791,961,562,921,361,587,84,912,711,56,119,586,701,71,719,886,800,499,800,752,215,863,829,206,299,477,787,170,502,857,385,125,31,306,932,717,952,910,718,742,360,183,374,489,555,385,303,406,77,328,200,107,12,444,246,695,974,912,133,756,538,492,24,294,120,892,701,412,681,666,38,677,758,337,225,187,918,227,582,575,125,728,336,14,257,932,212,100,627,941,358,395,696,670,559,251,565,434,946,401,750,806,822,16,251,316,201,981,358,58,892,436,274,545,591,543,346,187,705,248,562,880,502,224,174,581,590,770,276,215,653,103,299,837,394,151,464,412,359,237,212,7,472,661,467,228,773,628,806,87,410,993,416,297,581,408,306,793,952,155,570,119,218,302,908,799,147,882,180,746,844,93,96,183,144,900,650,774,161,265,473,146,463,89,559,172,618,63,51,140,523,734,524,748,932,772,109,519,995,39,749,223,877,792,637,218,949,584,627,589,231,70,98,231,514,357,770,338,476,780,258,961,352,327,716,771,149,59,592,989,864,273,720,9,593,147,564,630,172,323,266,32,319,517,909,573,388,958,405,808,371,164,171,730,173,202,211,238,111,596,231,389,158,259,844,744,755,228,512,751,511,435,323,391,565,552,487,110,112,993,908,164,556,390,703,50,381,215,145,152,627,90,554,446,717,14,295,52,5,52,595,170,394,112,481,780,201,875,688,933,881,763,38,188,381,618,31,785,982,777,169,970,471,106,331,78,399,431,104,756,498,332,750,141,318,581,167,46,527,166,804,148,107,735,887,837,110,911,234,15,586,414,17,724,37,158,752,877,559,910,954,745,644,918,681,978,780,277,894,438,37,360,549,611,791,285,885,138,2,0,858,284,380,721,344,730,214,990,479,398,830,978,973,752,826,507,264,603,176,246,365,813,604,903,954,153,957,97,528,857,164,460,474,361,370,759,238,113,75,891,430,777,369,156,723,46,973,184,537,220,93,301,511,671,344,643,548,514,39,747,713,786,956,884,703,863,193,23,78,526,778,493,485,811,897,156,958,286,879,388,779,427,592,754,576,193,295,229,600,456,595,976,746,903,58,993,728,433,59,990,349,944,314,924,542,277,458,553,953,324,828,927,51,507,802,692,63,533,796,662,446,766,905,490,721,493,120,995,279,975,115,552,786,314,605,602,978,507,13,60,358,581,828,936,157,451,432,945,919,748,172,377,319,464,946,777,172,650,7,51,468,105,180,417,288", +"931,144,351,427,273,722,240,482,837,931,185,198,397,296,137,33,652,914,31,971,787,537,678,949,217,703,291,945,928,426,825,813,892,817,915,283,514,664,977,637,733,546,613,919,567,417,885,337,360,285,418,373,642,342,541,694,775,390,275,630,759,350,846,984,476,92,755,673,893,569,700,610,138,842,953,163,469,843,981,233,735,164,517,25,391,613,246,107,662,827,60,426,764,275,790,214,195,820,73,171,497,444,451,991,479,992,482,609,2,97,378,102,537,594,38,521,892,782,875,768,968,958,993,882,173,354,212,127,682,242,913,976,128,594,527,120,691,926,540,644,815,512,308,238,31,973,748,693,444,84,862,763,269,349,526,142,247,511,451,172,943,328,599,993,839,68,155,954,257,932,873,799,705,753,416,753,669,88,529,444,851,206,392,935,55,911,571,202,28,234,206,43,516,192,346,18,711,586,426,9,921,78,504,271,561,914,247,546,400,897,747,3,732,304,696,989,786,475,797,295,407,508,169,724,391,390,270,104,377,830,392,747,238,324,787,778,340,691,51,443,48,813,112,134,778,767,67,522,694,94,712,259,165,609,693,977,332,47,369,550,965,728,275,250,103,348,89,702,5,137,69,317,320,830,707,38,776,451,491,306,430,815,155,807,637,959,797,610,943,541,667,746,271,396,616,458,960,143,26,207,521,967,489,559,94,159,67,894,76,244,367,640,20,721,557,908,113,712,626,592,597,184,475,89,770,947,437,132,804,374,364,751,57,121,687,756,204,72,858,858,871,426,20,851,569,781,293,506,41,152,550,129,714,158,747,982,856,583,355,964,493,732,133,226,235,493,242,302,660,986,688,637,848,828,248,512,461,508,315,210,505,812,4,404,164,871,943,680,46,574,967,285,244,704,852,479,916,230,601,651,304,32,272,690,803,638,603,412,843,294,485,65,816,244,963,996,267,36,397,298,543,603,703,527,994,157,523,721,246,882,498,973,863,385,938,58,804,980,202,84,602,299,882,743,767,608,574,192,737,973,620,528,887,719,602,363,765,117,626,426,527,402,699,670,236,67,52,577,202,171,217,113,500,363,517,904,689,205,68,744,185,430,437,158,823,791,378,284,883,392,383,432,988,833,349,591,428,94,173,408,706,793,614,247,261,797,833,587,325,403,653,635,351,54,162,543,790,547,400,938,263,113,370,901,924,286,734,37,780,768,396,647,922,568,205,309,546,553,442,796,189,941,909,284,895,911,326,162,585,34,358,254,683,34,15,760,967,83,272,272,151,50,711,589,279,851,653,41,123,226,9,837,319,5,275,453,747,574,380,160,674,86,624,326,522,464,547,582,86,334,63,393,975,391,590,12,736,157,981,10,143,50,477,180,200,639,344,449,301,438,893,213,335,559,799,100,900,251,579,5,923,171,536,461,758,376,177,147,916,637,207,690,623,829,586,65,333,869,482,461,127,559,25,190,597,907,95,598,780,428,581,924,361,436,275,426,688,258,334,996,334,329,170,13,277,708,116,965,731,338,689,478,157,291,247,67,454,347,224,786,484,243,146,500,15,443,557,380,631,80,755,127,916,938,401,629,346,925,252,882,117,748,833,619,461,237,133,246,493,92,157,629,118,230,95,634,695,639,855,967,229,203,602,447,676,768,211,523,928,35,137,136,156,67,719,437,25,754,606,189,448,703,771,979,213,669,905,619,897,581,881,757,529,66,985,489,105,820,807,288,946,584,396,711,367,949,21,638,246,35,684,401,69,426,490,758,714,790,582,370,16,331,29,740,216,813,383,106,866,643,701,78,686,262,412,871,165,673,675,990,761,780,933,528,464,968,34,741,527,813,697,498,181,72,72,870,616,817,315,651,475,437,572,237,602,54,775,610,888,103,499,816,779,338,858,0,323,768,674,730,174,480,974,259,600,296,231,963,531,642,192,788,5,505,737,585,817,446,665,56,935,110,878,304,612,428,245,361,719,229,708,67,956,413,51,376,117,180,550,856,883,58,491,94,148,916,336,260,637,814,708,16,199,115,136,353,981,647,133,506,691,466,67,54,475,251,629,580,683,163,107,300,377,87,845,808,206,546,183,616,592,154,931,393,18,427,148,658,900,501,825,532,208,462,644,152,12,661,761,677,527,717,215,581,910,74,844,676,51,869,664,846,897,88,692,346,485,779,794,317,810,432,712,685,614,866,91,860,128,40,129,395,495,795,369,354,184,291,10,985,798,327,315,850,358,159,966,392,161,251,960,942,357,590,524,332,326,5,308,818", +"486,894,839,163,147,154,558,717,758,77,571,81,864,490,781,556,658,663,744,797,555,310,342,174,100,634,279,711,627,224,336,974,540,557,708,112,690,947,447,63,732,135,864,847,481,72,938,794,166,593,5,143,127,686,801,684,750,624,243,369,197,692,356,945,394,847,889,319,651,895,809,762,911,157,348,604,574,740,719,16,688,642,576,163,680,167,233,922,546,511,577,56,549,669,446,410,324,679,129,976,91,691,568,183,50,945,128,463,842,486,800,999,695,511,80,834,493,316,628,322,503,132,934,459,908,918,25,199,426,271,260,221,736,505,312,597,906,329,649,192,753,129,359,850,299,388,76,174,463,227,47,294,831,848,301,203,919,836,737,433,68,732,607,700,938,65,667,968,789,658,708,861,984,291,91,332,762,50,652,220,829,378,328,393,277,809,906,996,551,580,733,329,920,442,506,454,778,334,241,132,296,427,163,580,557,841,363,22,47,551,216,860,614,172,458,188,850,685,235,688,641,66,672,892,836,248,879,119,869,854,395,825,659,546,305,986,320,724,941,395,610,998,416,864,30,279,721,127,409,285,647,367,819,486,289,125,30,276,997,341,284,252,132,601,9,801,425,697,307,273,320,120,844,987,465,275,242,725,846,838,577,912,908,28,502,698,344,577,512,591,27,93,78,414,76,591,141,900,292,491,748,390,136,205,549,17,483,548,365,762,643,626,121,114,593,37,836,226,624,146,428,193,925,866,907,226,430,741,162,305,53,273,237,238,784,935,921,994,548,798,696,467,570,448,407,327,954,869,993,263,378,363,32,92,655,900,480,894,498,918,986,949,747,724,514,581,75,475,337,161,170,947,153,114,64,672,186,616,487,592,274,505,770,144,3,251,109,218,518,143,689,17,574,516,140,933,985,406,980,839,503,11,381,110,409,230,382,126,758,19,162,501,448,150,553,341,90,427,154,998,639,744,917,244,463,829,564,618,659,501,356,169,981,219,29,894,916,280,149,836,491,696,619,313,712,963,976,111,438,61,663,889,740,972,550,199,255,426,377,950,802,784,210,339,558,316,793,628,829,141,343,715,372,427,165,668,919,988,107,757,923,876,336,321,905,501,727,215,581,847,480,692,211,410,45,388,932,745,431,373,524,525,503,88,826,130,391,175,21,942,832,327,256,237,705,86,33,416,773,257,215,28,146,972,601,620,993,75,221,175,36,730,845,893,616,955,487,540,643,922,580,830,435,473,794,843,554,485,738,460,957,841,244,630,363,459,768,89,43,216,80,780,714,153,373,676,931,610,392,448,652,565,62,673,898,812,553,354,190,677,299,298,190,468,478,983,387,13,64,245,220,796,985,918,23,369,912,637,347,620,731,859,443,789,992,295,948,712,5,971,404,241,138,394,379,226,625,341,584,119,453,739,583,51,199,295,238,483,968,246,761,223,793,83,776,762,210,271,772,666,38,327,309,595,171,149,183,363,671,532,586,895,711,344,99,314,268,779,299,195,996,311,738,109,938,95,344,545,977,244,399,318,622,581,623,372,568,798,197,656,529,633,38,788,329,14,750,740,334,649,45,687,141,530,558,944,984,930,419,902,314,464,603,26,328,864,974,350,457,615,852,857,167,203,799,626,843,281,447,758,483,547,895,753,750,599,424,586,578,685,723,508,700,934,666,234,249,704,813,699,343,165,475,77,879,943,49,440,396,728,724,125,714,984,552,269,345,508,25,143,805,991,330,387,410,206,654,494,525,279,786,386,627,847,522,422,409,226,194,402,829,86,92,621,100,928,431,640,760,939,138,751,221,743,58,176,176,706,817,22,485,932,455,14,69,432,656,739,458,171,922,733,405,881,164,149,389,603,479,118,166,719,53,614,352,764,588,132,586,839,634,677,305,778,284,323,0,186,468,469,320,469,905,327,658,5,9,863,197,334,540,771,21,765,551,65,694,458,77,428,824,850,951,693,690,531,365,142,830,144,566,22,331,881,538,669,215,304,203,648,908,776,286,758,901,182,254,585,382,331,77,435,77,519,427,710,602,801,97,642,79,934,23,533,761,968,740,307,123,725,878,181,62,221,59,126,308,330,566,525,10,403,326,346,227,187,265,665,550,984,414,936,668,571,569,170,343,707,109,960,68,323,352,324,948,875,261,307,628,717,346,928,965,514,921,635,925,278,996,553,807,850,353,15,259,638,890,565,280,386,361,764,153,750,445,749,43,278,428,697,461,534,714,851,929,448,57,248,29,473,496,369,889,934,449,338,986,884,42,522", +"626,356,689,279,725,730,485,975,915,981,798,473,356,435,30,174,292,616,648,886,440,717,662,961,476,512,27,146,722,378,422,631,445,699,43,2,295,784,445,315,869,536,784,988,140,29,414,355,816,409,873,96,798,853,361,192,31,373,295,234,15,23,637,667,555,794,789,394,325,610,139,412,36,402,620,601,318,928,107,317,463,335,548,291,593,25,114,943,623,35,706,954,332,235,576,837,910,175,660,398,881,767,255,888,889,878,869,744,752,636,922,319,42,441,880,161,137,613,141,746,985,889,289,557,111,614,415,193,916,361,761,770,508,803,270,630,165,267,229,871,656,910,491,992,643,472,195,219,549,367,530,998,444,959,954,688,893,663,42,84,62,74,871,813,769,306,550,591,715,28,519,177,753,262,264,296,247,491,50,681,482,685,150,6,319,94,634,94,32,490,526,33,671,927,82,787,507,572,740,427,731,559,527,131,665,171,727,200,978,485,972,949,942,199,413,948,41,256,780,672,72,845,54,168,107,468,987,787,460,841,153,319,981,937,575,257,527,187,320,738,546,538,566,122,174,279,733,700,210,169,129,585,288,33,782,853,348,988,238,348,22,238,24,525,24,454,518,95,26,328,350,638,587,440,677,454,180,252,491,134,771,623,302,69,510,829,292,334,107,804,749,13,694,991,480,847,217,549,199,365,400,993,45,727,492,931,790,501,500,41,732,397,78,991,379,215,63,989,873,433,589,820,45,558,170,702,298,189,453,801,509,722,817,941,457,19,534,734,144,233,479,205,853,858,141,49,556,316,477,658,123,408,183,613,199,146,554,577,448,441,829,753,814,748,243,62,866,10,480,152,648,876,272,979,205,856,75,679,66,100,60,408,119,591,217,827,779,759,548,661,18,276,587,240,253,887,120,679,225,201,577,120,13,604,518,106,341,424,351,805,745,98,303,888,884,873,391,671,873,703,189,264,28,758,367,25,180,586,186,731,649,702,56,230,594,211,752,361,259,693,659,449,647,239,867,952,149,364,478,936,865,805,710,527,240,756,766,335,18,28,288,149,10,957,641,466,783,847,650,201,422,420,465,579,712,230,61,751,519,555,123,373,517,342,351,576,746,842,137,155,232,570,481,645,265,657,452,922,712,176,357,918,706,743,577,704,131,421,438,117,382,522,913,71,930,993,818,742,516,748,660,609,596,272,387,626,843,579,33,232,714,694,543,954,137,318,19,200,643,963,292,565,625,839,987,162,326,753,145,825,366,331,190,884,597,40,538,526,191,310,530,852,439,485,655,876,766,992,662,153,829,562,446,862,728,499,490,515,589,325,335,41,590,376,580,871,827,45,813,432,771,371,74,667,462,246,957,249,431,21,992,346,418,618,879,981,274,560,963,515,474,676,32,8,736,19,584,811,511,615,209,993,947,362,549,984,895,97,748,477,702,150,587,901,707,189,619,333,493,524,538,489,485,349,34,316,83,715,646,13,964,686,521,599,215,598,399,167,487,948,804,760,438,746,632,131,614,114,257,22,24,723,926,904,272,940,297,730,342,78,728,427,21,589,464,859,977,571,506,127,212,456,981,131,624,864,257,460,63,456,737,683,121,612,318,346,336,323,428,462,231,270,10,608,331,214,895,735,327,754,909,485,456,970,539,372,729,324,265,941,354,364,890,948,392,797,255,926,587,668,621,66,599,829,199,395,750,536,515,510,770,993,719,820,363,263,202,960,420,368,26,77,497,619,574,169,940,750,886,491,772,428,420,635,894,72,775,522,501,946,588,651,138,97,927,70,581,647,999,921,318,915,989,710,381,496,364,983,638,211,526,326,982,963,541,117,858,599,88,370,136,895,248,602,622,771,152,216,576,185,157,517,109,505,34,139,178,450,617,224,567,94,732,621,380,768,186,0,268,557,819,585,485,195,873,856,546,315,504,614,984,650,562,421,249,395,727,400,209,901,310,702,433,387,306,575,214,382,470,958,520,101,379,135,776,881,432,125,175,37,263,922,773,81,583,953,266,918,698,328,675,417,410,784,426,245,467,844,371,691,92,454,309,324,343,728,472,731,882,123,782,779,918,568,51,646,508,297,402,673,301,477,395,14,121,701,663,970,208,153,72,19,274,741,778,68,275,284,419,676,862,741,790,129,9,921,762,597,244,554,447,767,209,273,465,683,723,605,965,646,105,608,140,218,528,347,263,579,369,226,386,662,984,29,772,112,679,100,402,203,755,264,580,115,944,859,124,971,741,264,319,272,284,429,416,712,657,518,481,513", +"223,855,387,443,871,412,621,320,236,545,510,56,718,620,908,795,888,794,475,834,720,867,255,739,574,156,779,16,270,330,486,995,220,512,690,937,273,830,445,583,776,320,309,897,499,191,544,879,667,591,363,986,660,565,81,497,130,498,210,987,59,88,295,910,887,527,472,31,308,675,250,288,866,355,215,240,463,371,862,886,978,88,251,491,965,280,810,546,749,637,460,126,902,17,863,973,935,251,860,736,394,358,214,836,901,820,630,287,873,961,376,470,18,139,360,258,367,499,360,48,638,242,181,231,742,246,167,729,194,459,907,188,336,224,411,499,279,94,147,279,315,198,892,861,867,333,167,831,504,967,523,757,882,56,163,755,512,827,290,382,365,197,237,348,111,837,387,481,600,333,127,998,378,165,808,538,67,357,943,542,191,515,139,553,930,385,695,871,67,444,675,424,94,115,397,264,297,579,486,199,295,883,396,951,679,696,438,638,355,155,24,554,770,733,296,331,803,76,754,273,616,239,894,867,565,84,92,525,170,223,430,6,246,537,634,373,702,719,349,71,461,394,571,428,207,591,833,484,674,398,262,212,855,357,964,823,674,605,875,866,999,577,328,278,5,565,51,788,204,535,245,433,870,829,925,680,763,725,639,770,516,663,230,328,427,595,206,711,668,593,455,651,796,125,623,118,378,97,325,670,318,225,955,694,426,535,325,919,126,126,468,671,733,811,767,32,549,534,216,310,579,149,840,510,599,760,291,150,11,8,747,619,34,90,654,437,660,360,418,913,793,478,204,564,543,575,39,934,992,804,356,873,251,970,52,849,237,198,880,333,212,647,48,312,315,908,729,142,676,753,722,466,278,838,238,869,905,454,843,245,36,832,805,578,531,469,635,521,53,618,609,525,221,619,523,516,314,775,748,623,663,581,833,757,60,23,801,562,438,179,72,145,997,879,194,222,190,995,86,890,566,841,861,24,214,452,26,684,70,691,204,293,887,431,658,568,224,147,248,59,665,243,52,260,32,436,705,169,439,751,315,765,290,703,39,899,103,830,546,965,748,644,392,71,234,682,954,716,751,361,989,315,556,795,403,865,75,451,606,831,933,186,497,8,382,696,578,707,632,729,824,223,585,203,399,499,953,258,182,836,447,507,317,902,619,666,486,791,930,664,193,79,928,776,980,403,904,666,767,165,128,574,755,590,964,846,822,276,982,885,187,952,223,790,798,421,483,519,511,885,600,386,696,233,115,396,687,458,344,624,221,677,893,239,103,968,113,837,815,931,913,571,298,3,235,701,362,707,275,422,416,434,784,289,507,238,911,172,301,14,678,585,389,928,441,999,564,647,598,701,258,962,314,191,39,952,106,531,972,388,678,415,909,395,705,295,288,738,602,501,119,550,773,57,613,37,608,381,444,213,821,350,62,151,558,848,831,51,302,863,784,274,217,180,561,442,392,506,946,27,439,420,953,562,453,451,124,520,904,721,75,192,467,214,222,543,853,781,706,627,657,998,40,791,602,90,815,962,502,955,639,420,229,147,725,352,299,745,117,726,546,230,949,571,777,123,570,303,347,354,336,441,867,872,727,521,425,16,502,656,350,582,921,855,553,321,195,484,659,436,369,231,32,655,52,184,754,420,704,351,821,228,625,103,566,851,715,481,890,186,220,526,401,131,435,165,803,884,48,374,983,161,826,1000,480,464,443,492,543,520,48,377,658,883,809,773,339,479,604,398,823,538,794,376,7,724,430,650,662,113,78,17,21,381,911,399,259,786,293,698,887,802,386,295,297,577,903,555,402,355,618,491,805,355,752,684,664,40,521,972,554,150,864,387,843,306,822,134,371,369,324,919,772,166,485,159,366,488,446,855,991,909,526,207,919,504,379,850,153,860,738,870,540,543,721,674,468,268,0,228,72,639,222,762,684,100,69,581,989,319,599,419,153,185,268,23,442,37,323,474,439,226,586,40,88,209,72,964,944,448,331,450,553,968,83,854,267,206,871,104,750,693,896,532,343,441,427,378,674,49,406,132,577,368,316,713,465,501,403,761,585,380,363,761,645,941,816,998,137,75,371,228,717,378,960,101,201,481,610,51,386,607,679,938,751,658,177,272,889,91,9,127,186,470,460,227,835,442,251,960,952,409,462,701,291,816,140,516,991,806,637,563,706,906,524,748,642,774,831,604,149,250,740,577,227,588,866,449,273,923,845,607,595,319,384,644,461,16,220,999,402,90,563,241,119,885,734,261,432,458,503,147,121,956,4,614,773,892,156,297", +"290,794,944,445,507,269,217,42,970,875,469,306,444,841,898,326,941,320,769,388,765,387,532,809,354,799,411,372,784,440,708,901,428,542,871,131,344,323,501,245,92,669,403,764,972,553,558,286,305,773,20,207,322,413,686,90,783,798,324,896,336,277,236,147,188,591,340,762,146,960,150,183,552,803,585,301,475,765,56,452,140,907,154,911,865,490,250,35,299,994,79,716,241,308,75,892,319,941,982,872,542,3,743,531,112,667,7,852,780,610,460,688,686,170,212,765,676,697,194,979,989,726,352,766,309,959,412,365,919,946,404,498,775,916,380,352,476,515,192,182,998,939,72,736,252,446,398,785,672,588,22,342,842,735,667,906,731,755,558,809,10,346,441,710,724,824,427,170,324,242,72,105,557,613,962,938,640,472,570,464,553,432,957,454,953,594,783,742,689,362,916,502,490,910,941,877,455,244,87,205,784,894,732,342,329,97,465,427,424,910,62,526,972,856,167,249,509,466,562,558,389,734,522,289,995,263,419,150,730,736,477,299,152,238,979,745,410,649,638,892,977,974,130,62,219,594,47,18,818,490,524,958,355,56,166,311,482,340,921,820,712,254,178,394,276,2,121,290,413,373,198,663,276,466,904,807,690,678,48,600,700,784,450,135,374,774,947,375,327,823,247,318,342,139,411,295,758,727,232,729,299,325,312,644,823,570,516,180,612,355,866,613,456,835,727,268,37,493,81,187,369,88,297,975,20,641,221,742,778,37,399,187,481,870,938,418,16,179,712,733,386,846,674,667,209,995,262,399,653,12,4,216,116,145,504,758,838,569,22,596,555,889,646,751,231,718,513,579,841,489,951,995,642,210,398,125,377,291,774,677,691,814,872,771,801,628,95,707,402,384,309,866,947,223,697,29,507,374,13,867,652,353,141,204,370,8,756,994,163,896,497,362,961,113,883,778,631,562,630,991,144,224,903,855,34,902,721,176,712,95,551,775,769,185,256,423,650,529,5,236,223,398,853,508,93,138,97,171,188,896,48,659,714,518,272,199,730,902,371,253,565,322,803,847,37,516,590,833,997,811,38,636,916,153,93,632,924,922,588,144,806,721,823,218,639,113,77,334,260,1,796,163,247,950,746,547,932,264,656,605,592,350,539,10,454,823,580,759,248,408,926,540,395,111,941,895,949,496,562,936,898,696,518,729,570,457,102,596,637,933,713,388,43,253,861,250,461,144,538,57,436,826,29,979,717,372,537,890,192,688,872,652,666,236,982,594,472,178,16,551,343,933,772,506,190,281,125,85,29,204,211,108,29,298,670,400,882,15,849,892,95,94,502,530,664,752,36,329,82,393,705,947,125,730,384,349,462,862,165,76,1000,77,189,127,681,318,353,293,370,618,386,777,18,674,107,358,188,147,49,621,771,763,482,691,788,927,569,337,553,684,763,148,43,297,459,383,947,129,649,788,634,63,809,244,588,923,220,828,200,808,731,776,990,932,340,600,902,435,14,55,989,726,332,772,120,843,657,220,604,165,687,272,395,203,90,282,846,208,451,883,914,733,359,394,295,133,55,567,564,16,925,244,908,805,372,856,955,229,394,699,12,244,103,488,837,359,669,521,750,432,220,942,529,118,698,939,657,810,303,224,231,38,283,559,812,792,263,679,306,888,988,498,500,878,247,293,122,408,287,810,748,746,405,743,55,903,273,176,406,965,402,420,869,300,342,258,185,345,281,586,101,588,555,888,972,174,602,162,400,969,689,909,679,992,73,633,424,476,321,44,231,561,119,768,286,103,326,326,953,690,294,226,744,845,499,549,656,901,313,7,9,34,97,604,63,712,851,794,57,686,762,844,855,588,827,538,474,354,875,703,409,996,960,62,627,727,591,503,277,1000,182,131,722,113,344,730,469,557,228,0,739,500,496,87,475,295,824,133,285,616,226,518,727,78,304,404,234,259,885,740,112,273,937,924,211,76,910,731,73,352,726,770,127,952,362,729,952,11,750,673,306,178,51,169,263,304,939,55,988,728,572,379,386,837,639,728,901,146,645,241,708,321,473,611,453,866,452,574,239,791,819,838,507,180,982,190,725,874,33,943,27,867,655,820,535,642,257,931,501,382,960,94,21,464,865,370,91,380,467,954,132,434,776,477,916,417,135,375,725,413,383,696,338,524,350,205,636,174,557,14,387,512,838,815,887,807,618,793,104,426,782,433,319,295,368,430,712,523,81,910,536,31,280,51,51,761,991,945,676,412,967,384,747,55,129,515,627,56,274,255", +"722,830,336,189,777,81,825,761,350,941,926,981,102,921,504,536,386,70,569,224,594,102,407,154,615,1,350,508,693,760,838,267,159,190,707,544,921,929,681,925,859,141,439,404,297,423,381,605,864,601,571,391,89,931,310,622,66,804,114,546,663,802,546,410,623,115,105,917,502,242,994,47,636,468,90,655,689,572,919,228,966,948,560,389,970,845,632,283,159,635,429,311,436,782,496,514,357,588,820,238,456,923,429,662,761,422,279,710,579,232,872,444,711,696,475,494,92,989,275,553,63,323,135,469,601,952,151,651,329,963,968,924,936,597,51,904,801,785,748,571,946,727,563,698,921,237,115,264,387,966,821,199,888,55,245,138,432,899,350,715,554,263,235,841,55,471,238,801,351,145,804,424,592,201,38,357,272,208,55,459,210,907,365,33,571,728,506,39,889,963,14,838,980,974,728,476,217,695,972,598,77,289,143,832,545,69,970,943,711,172,104,232,835,795,145,997,520,533,15,17,601,576,259,365,258,222,825,676,260,933,994,784,538,164,643,703,523,855,333,972,773,355,687,53,973,498,878,796,677,255,32,545,566,75,359,786,182,679,511,679,604,908,932,238,747,787,779,108,825,158,602,48,189,650,613,796,876,142,657,91,496,993,907,186,546,888,904,202,536,155,490,174,647,904,764,844,446,239,278,438,729,955,335,340,895,11,603,419,643,226,791,671,816,687,208,571,286,591,337,418,795,968,479,631,409,654,101,932,467,29,260,562,571,500,268,753,156,216,727,564,928,698,149,272,336,137,505,591,826,898,68,648,404,868,973,897,806,623,312,1,469,161,817,698,330,924,632,510,317,809,533,455,908,331,867,579,449,817,495,758,183,459,813,556,329,369,697,435,374,357,16,859,856,188,918,629,170,364,807,534,707,112,456,195,123,717,387,744,809,669,195,391,995,161,356,140,130,505,287,187,349,872,135,770,508,446,119,469,116,883,779,212,918,791,474,802,555,303,176,2,910,410,610,620,557,933,234,602,436,803,50,969,506,391,275,711,403,993,270,947,609,190,779,372,138,367,407,593,411,986,926,346,642,112,49,167,334,191,11,343,365,247,353,396,133,350,167,813,471,292,960,695,878,383,868,107,62,100,739,666,376,520,519,432,302,645,906,897,970,819,749,528,668,350,834,774,518,945,332,542,928,374,517,154,103,262,943,303,181,573,353,590,725,626,739,272,417,152,927,63,685,848,278,837,508,430,485,48,785,563,536,624,487,859,942,32,314,602,192,955,852,444,83,770,99,615,841,44,298,547,109,910,145,309,18,602,380,180,602,406,257,297,721,350,880,705,269,367,26,348,997,501,531,30,203,726,513,207,106,518,380,626,262,489,119,11,537,762,566,302,502,667,168,363,103,964,799,229,309,924,328,918,351,217,752,650,7,214,423,240,415,826,304,490,345,586,840,382,467,374,569,720,51,497,298,425,429,709,831,429,573,362,453,477,571,757,881,129,808,235,301,882,405,924,640,176,925,645,106,877,411,61,368,123,41,425,275,511,562,938,26,132,945,882,355,361,732,786,599,980,97,822,876,847,299,636,11,287,68,943,854,562,266,634,629,6,7,928,62,985,231,748,983,172,432,405,416,854,630,210,190,678,113,174,748,24,815,532,18,288,899,298,236,397,947,203,637,383,354,784,70,115,907,722,922,531,351,242,423,634,967,785,691,374,936,614,446,52,938,634,447,69,11,933,215,689,192,599,302,569,545,775,575,973,627,118,151,974,694,451,809,167,329,110,645,44,834,932,176,840,68,809,4,401,829,852,196,862,498,973,793,513,518,743,791,964,474,96,239,159,672,453,995,885,159,322,154,496,535,451,863,461,191,828,310,888,251,469,284,553,305,138,780,527,730,174,320,819,72,739,0,32,912,32,789,188,953,775,696,510,637,770,856,487,327,328,917,873,774,294,464,326,14,762,304,129,215,76,961,779,585,514,720,955,937,738,975,459,796,922,137,7,905,11,38,427,466,748,77,977,84,480,579,837,103,113,525,349,567,639,755,255,206,643,835,16,508,234,541,381,13,473,213,379,382,26,263,919,898,590,100,408,346,287,538,329,688,293,686,302,571,271,672,450,31,578,901,607,568,271,562,112,509,330,606,988,711,82,442,376,775,199,116,366,792,5,150,700,303,745,344,360,793,402,751,161,715,81,249,390,164,827,831,35,786,722,955,653,570,179,813,494,782,928,374,443,672,703,24,33,748,691,592,293,600,191,916,166,768,467", +"178,721,262,148,462,203,76,595,420,959,77,500,396,297,931,748,506,316,953,923,47,148,366,107,492,1,603,878,50,931,43,734,781,666,462,34,818,35,922,549,461,986,986,743,922,285,286,791,851,918,281,712,214,710,585,458,248,21,562,733,515,417,109,165,433,420,943,918,253,391,403,30,372,299,729,257,411,17,474,568,694,490,185,707,747,488,593,588,320,612,724,308,172,237,432,114,301,392,994,25,544,790,816,923,339,102,18,905,607,374,585,15,29,460,664,430,353,158,523,798,161,296,302,668,120,670,726,220,877,503,382,53,99,884,911,186,324,61,845,228,319,203,820,592,824,715,142,71,762,4,487,308,955,867,396,470,975,372,322,781,738,416,38,454,288,95,54,392,448,662,13,471,124,186,273,541,2,104,737,854,19,740,251,941,755,660,163,744,139,909,316,334,964,611,118,606,819,518,720,861,907,617,109,814,567,419,273,872,898,704,701,1000,955,410,49,794,280,881,17,469,515,145,206,333,427,302,267,332,987,633,667,684,766,830,480,678,465,311,914,944,974,166,895,702,780,974,559,452,997,918,428,544,785,840,822,224,217,241,55,367,789,475,348,812,578,435,176,231,397,797,774,159,581,676,996,975,707,6,339,44,500,666,971,679,661,489,902,280,930,709,905,607,693,791,61,555,303,272,595,275,136,473,506,136,841,289,652,764,425,493,164,177,853,745,99,447,173,372,468,597,541,980,62,394,826,55,12,915,485,121,60,200,856,688,691,524,154,837,844,379,708,147,501,71,326,670,244,331,960,384,315,405,838,939,727,609,276,531,422,896,24,684,913,380,87,289,649,838,480,214,446,447,734,355,240,664,600,228,345,838,420,52,998,2,409,501,311,92,810,311,657,275,639,138,678,953,302,608,747,162,332,242,882,730,731,362,836,477,24,961,859,534,171,206,405,218,343,221,70,878,313,210,874,770,538,452,496,21,116,955,519,953,604,992,209,334,604,430,659,273,546,570,547,845,314,515,117,505,901,395,161,44,277,752,325,304,850,469,690,986,584,207,244,460,993,858,104,262,342,809,132,689,471,816,922,114,456,175,112,338,569,809,686,26,165,670,864,67,407,846,746,307,900,573,766,229,290,658,647,819,993,778,177,550,233,158,881,972,672,229,488,692,434,997,286,449,873,137,264,629,600,214,722,593,785,651,646,221,549,855,94,840,629,909,95,547,598,722,699,44,827,727,257,130,755,146,507,925,70,590,338,86,62,430,493,191,610,471,226,744,578,406,336,359,659,564,318,126,191,529,714,201,352,12,964,388,915,878,749,170,800,79,470,729,374,483,18,48,878,430,946,256,93,298,33,452,698,511,790,983,14,406,858,107,143,783,726,91,492,17,256,391,801,792,523,797,500,474,313,271,607,665,386,436,5,177,703,431,257,206,221,2,971,127,987,935,176,504,216,446,254,990,667,239,66,10,441,181,625,874,225,257,489,276,384,279,530,164,309,162,371,370,620,861,986,434,499,365,232,209,793,921,154,829,546,66,856,663,485,688,622,10,313,164,285,871,922,651,298,676,926,961,445,889,298,966,88,861,461,128,800,772,20,427,335,924,224,203,802,686,182,375,215,945,187,254,506,672,353,798,572,125,317,536,945,322,618,885,247,658,588,307,610,442,200,936,429,686,318,249,926,623,231,79,18,838,603,645,701,372,117,443,827,729,331,15,194,682,66,868,261,235,169,238,671,431,610,198,187,932,452,414,421,853,984,352,569,999,220,350,137,60,361,559,490,860,690,943,942,876,875,453,633,354,301,164,387,576,85,512,949,752,277,386,624,179,710,374,695,866,788,370,746,997,212,41,367,996,211,372,741,538,325,5,185,997,715,840,829,895,865,831,724,452,214,480,469,585,639,500,32,0,784,517,1,157,860,544,41,289,189,32,45,205,4,198,23,974,302,998,951,860,190,82,493,852,995,941,796,50,503,456,588,106,885,767,780,17,564,201,639,931,224,616,51,58,598,240,299,214,743,702,255,637,898,742,651,33,287,68,731,38,745,379,965,254,807,435,126,302,452,867,441,376,777,808,761,988,908,780,33,169,884,35,856,457,76,218,595,106,6,1000,396,413,10,273,607,470,900,943,728,472,74,77,144,736,590,846,530,816,887,166,106,417,505,790,856,382,344,214,775,657,598,931,95,219,534,369,25,222,701,253,181,639,188,51,227,907,999,745,58,951,349,622,771,45,64,748,874,636,954,289,588,106,270,84,186,328,318,89", +"39,988,156,665,209,201,898,12,309,367,100,394,154,155,648,925,782,941,947,763,65,638,580,490,987,131,895,427,607,75,66,44,930,878,521,304,935,112,117,294,870,947,643,75,415,461,977,404,244,39,705,576,538,713,897,595,891,360,472,236,736,269,240,116,851,860,855,760,53,421,984,561,258,494,766,342,765,49,754,362,348,310,820,312,185,567,658,14,52,836,940,306,93,300,37,804,878,407,914,3,28,242,719,759,497,668,84,194,297,341,359,754,931,570,461,204,398,949,75,183,965,346,674,265,379,501,601,6,652,985,461,997,537,46,943,672,955,443,481,600,50,43,22,633,638,625,93,229,353,716,295,980,222,196,742,219,892,209,585,921,816,106,787,430,253,155,455,492,477,576,486,835,542,284,819,29,427,445,958,863,3,870,341,751,69,737,501,947,474,455,55,507,88,354,546,139,929,478,940,837,369,643,674,763,413,520,174,125,224,222,320,520,171,936,880,760,570,637,763,62,185,887,320,459,594,124,577,885,336,140,348,770,906,758,44,845,728,695,482,351,586,394,127,953,542,310,165,839,662,671,68,640,766,569,159,932,965,929,191,388,242,285,11,572,734,455,145,528,118,296,402,14,249,867,109,1,979,335,346,774,123,374,166,699,714,906,428,31,887,138,980,925,835,300,18,977,629,619,268,233,414,417,682,420,891,127,293,951,950,734,259,3,783,636,7,626,111,550,528,788,719,412,305,322,543,112,202,236,295,286,228,519,578,310,974,722,34,271,634,270,242,923,575,157,205,868,430,937,462,645,525,460,807,924,547,975,987,425,210,308,209,778,406,610,169,252,862,89,15,483,474,184,126,171,654,689,188,109,170,248,807,112,187,98,813,192,658,539,961,476,607,97,440,158,94,988,41,380,228,73,146,611,296,785,30,248,242,239,193,400,818,224,739,297,254,126,579,845,353,714,521,16,746,934,675,938,842,611,894,128,700,969,137,116,478,330,164,189,873,211,939,209,711,120,665,446,790,945,515,694,475,588,784,778,405,380,760,139,127,547,874,746,613,114,756,934,26,571,601,139,37,940,448,797,295,322,39,692,264,325,698,956,744,324,135,333,821,97,258,734,895,615,160,582,841,193,638,260,578,853,504,684,402,192,324,362,377,898,829,560,951,160,131,129,295,783,584,177,420,913,669,42,31,501,726,355,588,149,224,466,326,638,885,527,266,739,101,193,843,877,128,588,651,709,459,788,169,240,632,436,20,725,237,677,734,957,562,32,190,420,497,553,320,986,896,811,529,344,941,695,153,966,727,39,830,585,353,649,184,429,313,412,58,766,422,370,18,544,861,491,232,498,895,358,93,863,888,608,914,134,901,818,228,762,566,623,639,452,97,459,568,188,781,46,959,698,66,960,854,887,320,728,40,782,342,965,884,205,901,897,796,768,340,29,624,636,261,764,500,564,106,383,614,690,616,980,889,462,922,566,51,913,273,995,881,754,109,267,367,346,403,385,672,663,919,198,290,818,438,38,946,497,179,643,18,807,954,759,768,150,163,797,138,573,954,262,643,125,242,27,800,180,93,588,976,920,49,596,282,87,979,558,768,42,825,995,164,168,858,150,887,312,500,961,564,336,172,450,202,577,843,167,691,273,210,105,904,400,484,878,768,402,807,915,312,575,197,220,71,731,484,20,659,475,24,8,904,619,919,144,500,338,752,893,834,126,737,490,729,703,91,575,984,874,901,299,604,120,787,94,813,651,799,834,820,429,154,88,789,763,82,626,963,966,442,152,627,846,391,932,516,904,627,439,212,222,748,499,731,119,407,738,731,872,624,591,276,858,735,24,752,932,361,698,204,370,263,234,695,210,190,346,995,179,97,635,928,265,203,107,280,989,691,327,990,974,905,485,222,496,912,784,0,798,32,583,563,735,409,755,180,11,25,656,367,399,84,877,725,351,998,225,193,955,713,191,287,58,129,468,131,340,710,56,330,699,588,234,237,349,935,710,29,272,999,221,970,859,205,494,979,989,920,180,258,641,872,176,253,69,3,887,342,335,232,308,859,205,306,935,786,841,142,292,711,48,914,913,575,380,526,254,127,225,91,164,869,603,496,644,69,450,849,325,956,683,321,201,853,56,295,621,995,501,80,147,796,129,995,723,548,691,102,53,307,352,822,107,661,36,945,543,43,262,740,87,19,722,455,420,225,2,253,47,864,836,190,639,499,361,605,580,70,425,458,409,488,235,851,846,558,387,894,566,846,380,941,166,432,768", +"873,887,978,866,996,59,172,256,790,842,214,805,855,590,19,835,206,875,916,152,469,454,724,815,667,725,811,758,34,584,287,173,895,988,490,318,689,992,99,765,105,587,854,531,392,937,671,906,592,757,952,887,336,800,663,230,858,561,920,374,407,121,545,245,323,536,252,405,970,801,596,782,580,817,902,756,473,186,868,870,409,685,51,97,620,172,209,777,533,664,634,592,568,219,739,576,410,305,950,569,719,987,421,746,7,218,696,123,925,592,543,730,583,18,734,276,344,420,964,946,816,666,566,818,57,721,425,487,133,429,498,727,335,327,437,889,669,445,795,953,368,620,37,238,245,267,358,860,413,496,236,482,872,229,288,877,461,419,416,661,466,965,359,412,860,397,309,48,67,887,790,898,508,857,839,623,956,400,907,372,524,87,619,385,56,412,584,713,487,797,517,755,58,541,975,44,767,654,567,560,845,400,417,453,170,542,406,296,254,667,645,801,517,717,635,8,914,633,457,259,651,41,963,235,818,261,755,710,346,476,679,776,428,586,165,74,99,357,784,513,288,520,266,780,818,379,211,747,540,672,920,359,127,162,932,147,67,511,385,256,936,546,232,730,884,752,512,759,671,783,672,994,272,486,518,735,473,647,914,664,856,449,233,788,287,304,132,807,195,795,627,586,514,511,419,432,184,609,111,920,180,543,990,459,491,846,930,162,971,255,810,313,273,506,2,856,73,950,987,350,524,854,891,138,154,897,21,618,65,603,204,44,390,525,215,932,411,355,402,217,448,426,589,102,527,112,755,627,206,558,833,665,748,71,481,6,911,12,902,973,87,285,925,966,996,970,60,954,368,120,962,301,235,454,344,942,693,284,546,236,294,887,918,254,161,749,853,264,660,821,83,425,551,562,180,886,567,381,357,700,430,621,434,701,888,960,945,329,213,939,143,807,239,264,845,938,464,652,106,581,666,561,396,418,383,251,660,9,450,264,370,569,118,37,417,395,362,480,8,984,333,298,491,399,611,252,52,173,683,17,80,753,708,382,696,62,776,189,955,378,559,738,807,46,1000,802,787,129,168,406,584,865,589,352,672,791,507,45,989,581,963,842,897,928,923,805,584,411,543,300,599,448,32,368,81,527,530,252,574,590,120,577,630,790,569,440,93,612,986,144,422,384,959,73,928,387,811,211,544,842,144,407,446,477,792,681,788,332,2,325,604,912,376,418,726,885,210,528,627,174,259,707,445,474,514,37,904,410,514,260,676,78,46,25,640,570,592,858,688,458,12,38,417,503,431,104,37,58,876,800,357,690,662,114,675,452,474,669,212,942,27,714,458,733,427,105,896,682,137,142,221,49,279,457,514,566,3,837,783,426,286,725,164,55,474,173,647,212,615,596,195,108,550,799,728,743,170,743,933,143,985,688,176,990,951,821,863,514,660,797,292,885,616,837,894,104,147,674,918,815,115,741,240,251,463,58,611,597,200,177,144,986,522,329,950,112,800,780,238,709,212,167,774,864,294,286,36,711,870,901,84,532,281,983,608,713,152,515,477,18,139,549,821,18,743,80,598,774,588,31,301,51,929,684,387,876,913,414,646,571,242,561,917,515,282,762,216,627,649,627,837,934,326,146,107,860,977,838,458,75,884,62,93,873,171,693,515,247,852,927,877,521,619,561,848,726,151,853,59,700,658,628,243,600,739,735,396,659,245,797,62,120,873,246,468,811,173,99,506,40,502,70,852,504,679,176,619,658,427,874,798,968,523,561,906,997,883,453,115,744,660,690,273,860,294,734,46,153,457,309,533,817,666,217,527,963,364,759,447,151,803,516,433,92,728,343,45,107,212,948,363,897,712,921,729,621,530,349,448,697,276,802,383,914,843,143,633,499,383,451,789,552,938,13,479,259,327,195,762,87,32,517,798,0,54,514,215,26,481,848,317,929,399,835,603,238,901,865,169,894,229,52,683,967,115,443,90,812,793,433,668,896,69,956,833,950,849,493,919,347,311,224,694,587,527,341,325,249,106,924,916,693,50,989,872,532,11,684,351,989,862,102,916,966,585,63,949,876,941,44,148,596,823,866,746,701,306,174,10,382,989,378,953,744,954,663,424,667,466,397,76,440,449,889,204,250,70,843,111,415,75,675,433,469,899,735,97,532,336,177,396,440,418,850,868,423,847,299,312,2,528,722,485,814,696,331,881,758,453,112,445,256,623,100,295,584,544,374,765,266,68,209,222,554,357,796,832,351,91,879,687,578,154,729,194,983,77,438,462,331", +"601,318,879,855,989,764,816,972,497,474,518,824,947,925,194,61,208,304,659,854,69,968,166,509,385,697,894,932,757,806,84,962,176,138,474,873,419,527,648,884,143,886,944,951,355,404,754,297,982,521,260,673,252,975,706,293,379,883,227,873,964,743,205,297,310,651,478,42,87,744,866,546,247,295,456,136,21,21,343,477,284,820,486,143,978,745,490,144,956,750,344,640,733,917,79,84,797,692,163,74,84,571,680,254,551,516,124,999,145,685,414,72,725,4,236,752,360,347,852,545,411,327,787,51,883,652,252,63,612,19,780,561,100,973,132,32,613,884,486,115,894,91,234,216,942,165,162,469,499,27,792,247,526,466,347,964,828,612,810,241,82,711,477,412,147,664,689,674,103,121,947,303,100,976,644,299,522,169,381,827,728,16,804,202,249,919,831,869,178,846,979,143,228,660,378,881,818,171,498,686,880,663,641,405,455,241,599,355,88,862,414,972,243,410,400,84,335,366,346,742,494,3,971,618,215,754,669,613,293,10,491,535,666,78,260,625,604,562,848,588,176,316,439,726,531,859,151,152,108,936,589,655,714,612,474,409,668,785,751,546,355,513,408,620,840,493,377,256,367,920,329,40,31,847,358,875,179,820,389,509,584,999,829,820,392,312,303,489,4,437,329,275,338,279,390,292,929,516,329,901,175,790,328,189,608,604,469,961,743,944,968,155,878,714,706,234,446,419,90,612,777,727,884,386,151,226,981,134,452,748,94,587,671,219,242,444,768,450,45,969,826,423,311,846,797,90,855,945,403,977,62,789,964,981,552,210,660,128,877,974,737,679,623,869,830,983,94,38,737,959,52,937,162,42,76,374,678,539,317,408,24,460,680,95,729,441,899,892,664,720,95,155,329,683,9,314,127,650,821,473,597,327,542,985,111,278,921,762,628,780,741,641,207,365,141,480,541,379,341,581,109,780,420,107,692,70,34,923,838,380,612,203,50,759,494,816,659,887,120,151,201,21,729,360,891,833,986,883,574,753,160,417,861,455,443,932,523,448,310,786,497,577,300,368,710,154,411,762,886,535,696,38,757,521,490,785,575,485,891,310,899,304,201,678,378,236,629,238,321,957,534,379,722,64,69,215,847,482,669,475,332,172,450,612,140,440,617,926,866,335,833,475,761,194,174,769,385,120,249,734,102,141,999,650,62,948,476,425,462,515,373,969,475,101,535,155,12,548,269,453,891,267,913,832,61,856,951,671,69,433,162,100,169,490,478,359,468,467,548,91,788,185,969,273,203,904,662,762,471,510,32,252,245,683,555,532,184,90,26,434,302,469,971,792,41,734,277,360,214,855,10,898,563,889,928,366,555,110,72,842,103,174,994,358,436,935,1000,938,493,410,256,90,588,803,242,984,774,418,488,883,418,488,301,212,234,58,847,674,383,880,61,870,475,298,190,573,88,197,835,981,244,488,588,358,182,641,726,832,848,102,983,830,85,763,903,637,662,772,707,431,146,990,875,400,407,780,372,835,682,411,662,764,218,33,547,601,75,955,684,598,597,383,552,900,986,629,312,915,660,418,681,592,56,790,973,740,813,823,491,412,406,871,650,209,633,571,357,223,157,717,598,160,236,48,618,119,853,154,575,210,613,503,832,437,243,500,32,214,308,803,574,910,577,878,695,556,907,104,306,857,161,52,722,647,545,314,567,437,589,852,713,787,850,945,307,349,121,583,691,363,310,131,255,368,513,178,683,467,169,390,414,440,828,317,399,799,16,603,633,126,282,349,121,985,399,445,518,44,832,216,915,997,962,715,228,709,475,892,169,824,18,391,703,201,793,931,921,391,897,5,790,99,450,438,395,394,378,353,615,320,327,184,99,368,191,902,195,702,552,439,906,837,283,387,398,600,658,873,684,475,789,1,32,54,0,4,921,640,594,614,801,330,436,227,744,630,283,488,28,884,468,859,672,196,291,98,865,521,410,191,978,791,365,347,647,309,617,586,146,211,166,30,642,113,660,284,563,16,178,484,289,263,92,243,540,46,62,319,316,190,759,111,295,311,220,746,625,777,108,910,404,21,162,740,945,198,209,235,789,950,778,886,227,605,275,225,847,968,64,874,156,715,38,318,315,125,646,549,140,935,661,288,534,916,898,14,184,523,822,373,450,419,84,407,256,990,921,29,349,595,724,982,344,337,92,246,743,15,541,468,893,384,92,963,178,180,869,43,519,727,988,526,450,741,742,68,446,38,469,930,687,417,396,504,292,338,867,844,997,778", +"741,723,623,267,491,616,165,462,496,385,657,490,907,870,587,343,965,954,462,424,363,220,340,969,912,738,434,537,899,382,766,479,167,135,749,633,391,265,855,768,958,959,2,739,922,92,957,773,120,935,161,537,592,615,670,377,780,942,966,473,503,625,636,236,467,979,191,929,821,472,511,754,374,713,524,912,333,795,66,32,907,625,222,678,876,109,508,664,848,14,599,437,558,962,402,832,87,749,334,429,669,839,693,676,825,894,958,501,146,204,285,986,146,577,708,266,618,779,441,767,476,50,212,29,346,643,988,909,181,916,570,264,980,231,227,40,778,659,651,5,70,951,908,854,736,713,163,700,56,830,661,9,148,162,669,256,537,644,838,534,31,49,451,704,101,393,322,255,997,325,349,306,857,588,141,782,31,948,411,782,84,148,941,95,71,372,724,415,959,570,232,746,175,699,647,825,708,341,425,562,837,51,167,778,788,793,765,517,162,104,765,722,553,271,839,35,467,963,162,349,109,665,70,515,903,536,709,938,945,835,810,498,378,706,627,505,161,852,837,125,426,274,839,292,694,529,298,227,914,193,906,256,734,993,124,977,278,594,322,374,80,843,773,737,458,881,39,988,716,480,469,273,128,748,835,602,923,155,76,339,546,837,133,86,766,412,306,166,244,973,682,775,54,268,383,678,113,845,864,272,27,725,660,817,817,138,759,959,301,981,730,331,264,444,252,270,487,366,308,701,734,349,979,504,567,635,927,360,198,776,986,277,736,956,537,635,539,419,867,980,485,473,563,443,891,145,648,958,546,45,529,20,357,177,404,930,295,7,846,819,730,577,873,409,705,343,983,329,16,675,272,29,575,253,624,635,467,857,862,94,630,735,933,740,827,32,928,337,689,676,295,173,945,129,288,864,397,30,118,674,310,11,517,195,287,145,336,190,441,888,118,672,847,318,765,47,577,789,955,55,979,977,517,172,852,417,118,681,441,763,384,150,129,880,592,757,36,409,153,820,432,180,604,470,689,919,548,369,473,271,458,663,302,620,824,100,85,574,487,333,480,655,384,488,111,985,654,606,974,251,356,823,913,105,641,359,595,756,981,759,216,11,942,971,127,733,807,865,458,342,902,387,317,287,471,922,511,316,885,353,516,921,86,650,102,695,238,567,331,1,114,616,844,135,87,222,851,764,73,268,463,6,479,198,989,135,822,263,38,911,34,233,470,937,716,8,531,434,544,167,511,682,30,527,958,26,892,825,488,860,379,906,493,414,715,916,137,755,38,22,484,343,373,782,884,425,696,549,958,302,932,116,26,963,955,555,165,61,700,79,706,317,92,218,42,534,887,748,947,129,182,527,625,459,297,109,579,83,889,899,577,737,275,610,600,571,83,488,723,893,747,686,756,344,166,624,556,186,19,655,641,75,228,390,261,956,252,46,884,370,703,458,677,161,445,47,934,624,31,11,594,350,606,342,443,275,658,952,727,899,645,839,976,701,696,31,382,477,845,888,960,27,203,59,275,655,201,628,906,693,609,281,701,552,316,966,693,904,830,51,43,29,415,820,192,857,838,764,782,228,285,55,770,548,534,943,407,616,537,427,993,648,194,281,536,691,929,161,561,88,429,102,757,53,297,285,547,6,489,928,258,916,858,467,428,665,809,565,124,208,152,199,379,233,117,879,66,366,732,57,173,200,147,864,19,842,532,835,672,754,368,402,921,16,609,796,756,715,689,847,352,210,477,819,145,239,986,528,530,978,894,421,792,104,884,469,312,556,590,401,817,668,79,164,691,791,327,974,714,525,474,766,133,308,96,648,357,522,365,669,61,87,716,690,85,46,680,877,486,462,293,761,54,756,69,511,417,551,179,896,182,776,373,23,558,347,508,387,323,960,364,703,465,937,830,296,5,856,100,295,188,157,583,514,4,0,609,592,339,76,137,709,186,942,805,546,20,414,284,232,509,933,959,806,346,991,926,788,768,373,909,550,797,319,757,543,33,767,778,410,400,328,959,451,127,528,211,768,421,627,550,710,755,170,569,472,860,192,384,925,326,822,666,347,942,118,251,128,512,359,565,59,389,427,180,819,933,624,601,115,382,723,631,17,500,582,789,36,976,655,43,512,452,319,753,746,726,482,156,237,545,439,505,11,667,411,873,399,668,626,341,392,578,944,320,834,630,441,915,808,673,135,31,574,992,540,383,847,743,379,728,332,427,368,324,237,292,931,935,635,647,60,727,279,4,700,462,811,130,196,203,583,510,19,299,126,946,311,933,227", +"88,560,634,417,232,170,36,173,291,76,476,40,725,788,318,9,497,870,61,248,19,606,677,74,778,984,234,627,232,769,138,398,189,727,743,107,468,640,664,983,775,213,522,303,318,690,687,23,278,513,149,11,870,217,724,796,663,484,409,388,854,924,501,937,467,328,431,290,304,324,617,382,335,955,326,904,231,63,786,557,890,11,117,367,167,27,488,369,927,897,613,294,324,546,505,583,695,59,207,34,600,801,64,324,345,574,757,924,399,635,648,207,344,773,56,783,58,858,924,719,584,134,126,920,565,683,139,720,654,974,97,60,205,719,126,911,144,34,976,685,420,701,449,392,467,524,175,971,926,377,126,859,398,844,957,634,916,873,893,476,733,545,409,839,429,454,405,777,490,384,785,205,127,786,479,993,134,230,410,491,271,820,263,954,311,487,951,751,200,3,859,893,130,745,485,896,248,605,949,985,676,808,952,363,106,230,616,950,18,996,165,174,269,704,948,544,561,93,548,275,215,925,277,296,891,96,319,574,62,368,934,696,754,750,434,512,293,145,883,473,270,831,964,786,582,929,276,75,391,498,806,313,468,291,387,600,657,908,128,507,323,802,656,302,628,855,954,965,168,644,266,613,925,55,400,511,4,570,355,444,580,191,943,903,90,499,292,442,677,487,516,587,814,939,613,599,590,98,255,829,687,574,995,962,874,940,597,254,602,500,368,50,909,67,915,71,690,993,462,800,929,584,867,550,285,924,922,146,435,897,105,810,698,366,784,25,160,158,689,628,526,335,972,878,625,85,327,812,591,540,689,569,437,273,457,928,578,728,521,154,833,574,555,680,637,697,742,586,399,666,438,333,648,620,312,614,743,418,974,730,44,248,808,34,186,262,91,35,189,594,273,165,984,891,432,687,310,518,254,753,961,611,931,250,820,133,362,895,879,925,806,989,765,924,734,821,38,80,245,627,904,619,60,968,108,129,790,612,95,947,631,55,250,304,714,514,485,740,232,712,862,535,902,497,276,501,347,670,142,724,507,904,479,63,454,277,662,167,945,442,660,263,621,956,189,806,35,298,672,819,831,761,260,225,582,814,509,914,14,744,568,200,598,68,373,696,54,262,832,498,469,728,381,909,46,974,300,672,676,535,657,782,933,715,76,676,27,968,542,615,612,150,530,850,845,271,943,328,817,663,175,946,166,839,675,492,505,112,172,133,620,591,564,663,302,538,170,853,859,169,636,354,648,52,423,708,499,668,90,23,616,92,426,178,863,8,514,489,979,146,715,776,957,670,220,873,514,847,44,199,574,985,97,596,122,748,702,556,250,181,415,440,510,743,870,922,23,236,243,542,439,132,466,164,905,339,775,667,705,531,690,302,540,870,215,288,35,678,634,567,389,248,971,460,243,407,38,688,427,730,201,620,979,520,282,36,801,427,361,824,567,980,584,714,378,843,593,757,947,837,690,731,83,599,881,528,303,427,363,213,4,836,642,914,789,854,140,461,838,198,284,164,74,994,431,311,885,666,495,794,901,637,489,474,778,261,207,712,903,531,654,450,458,626,670,364,753,739,321,914,439,787,236,573,65,806,23,551,413,714,94,552,372,113,31,84,7,147,319,889,337,715,841,270,999,586,954,230,52,130,486,53,556,604,119,13,857,112,550,630,649,760,849,755,741,103,246,711,16,682,225,627,54,26,596,982,84,855,61,850,700,340,469,887,593,699,242,159,587,99,55,616,951,306,907,998,560,76,812,160,115,987,307,810,993,518,941,680,265,927,745,283,136,561,680,40,27,840,40,834,203,517,308,949,242,74,283,571,149,290,441,891,240,309,970,458,888,236,241,286,706,581,826,982,219,536,311,229,397,558,699,456,547,7,205,766,270,465,282,183,246,296,355,802,978,231,9,546,69,824,953,860,563,215,921,609,0,219,138,470,528,998,324,564,232,867,308,646,146,210,270,32,839,668,398,26,665,236,776,209,522,188,463,433,426,13,191,394,362,196,768,690,194,550,899,991,40,860,774,883,194,713,986,403,388,945,929,917,780,966,504,39,28,786,53,448,390,935,748,367,224,303,42,958,674,229,440,940,316,382,148,190,139,467,426,330,896,563,677,462,818,721,56,584,282,725,837,508,77,223,282,44,114,65,33,691,108,111,440,607,174,421,741,958,814,491,66,262,927,995,160,692,78,567,361,275,258,109,913,960,409,924,143,680,930,505,897,527,64,801,920,953,187,898,265,231,974,303,762,465,393,26,610,744,840,646,876,724,74,890", +"690,688,258,553,39,292,51,377,830,171,484,236,980,161,379,526,663,573,219,888,65,752,237,485,183,166,597,331,415,534,840,967,700,734,603,664,785,944,767,854,82,41,274,493,381,979,776,599,365,549,510,448,511,380,144,682,868,724,78,439,549,513,122,615,417,567,732,387,16,821,859,532,891,161,21,466,244,551,842,901,939,879,699,816,705,361,462,483,467,170,582,194,549,566,539,445,724,325,824,262,300,11,376,963,155,884,461,779,585,129,557,107,533,977,174,252,424,191,586,931,596,567,821,823,870,8,718,222,943,929,788,837,9,544,59,108,437,528,645,907,435,825,488,94,262,250,64,395,980,768,686,191,407,925,691,715,710,430,880,562,683,819,711,885,597,392,422,237,45,115,700,363,137,623,223,67,195,312,838,161,474,958,298,49,712,191,26,938,670,838,81,270,157,835,916,633,664,736,253,899,961,392,421,211,762,870,546,304,326,59,672,386,34,245,634,66,169,998,276,969,732,531,455,711,361,699,800,894,290,793,243,37,42,114,37,255,356,949,787,166,890,576,595,575,901,685,106,222,825,301,189,57,527,189,560,296,152,764,208,872,447,735,770,691,668,603,586,22,11,295,767,488,251,52,653,546,675,559,777,979,760,909,620,201,82,664,73,646,7,425,407,533,557,537,600,421,302,206,705,3,55,339,22,697,214,65,857,623,921,762,357,192,539,901,583,950,701,81,877,996,35,272,931,45,571,880,613,831,331,827,142,800,700,707,884,393,290,946,881,997,411,208,37,89,928,758,544,687,414,679,602,301,381,676,389,438,283,781,92,670,477,438,43,62,267,103,141,866,988,450,993,519,177,954,799,642,349,44,710,814,956,606,958,92,304,879,407,892,106,594,812,753,30,912,43,874,49,920,527,721,383,785,214,141,701,854,353,334,507,141,798,469,261,13,846,914,939,398,249,163,262,28,975,967,502,927,116,925,186,286,168,183,893,31,719,91,498,951,510,479,502,526,207,720,18,27,575,53,456,108,968,930,201,102,367,697,152,349,107,505,399,353,541,42,446,172,11,646,582,889,99,878,997,47,869,248,166,460,897,293,706,994,579,75,634,312,517,687,180,919,158,553,547,994,861,989,466,886,130,745,999,909,763,917,571,263,684,378,548,213,897,896,291,405,772,317,530,675,674,285,113,229,524,238,624,838,625,347,700,213,647,826,530,229,450,741,874,99,124,568,420,634,965,50,641,509,455,716,925,682,986,595,973,694,8,467,802,184,109,301,413,570,167,305,300,10,606,333,889,523,515,864,159,788,579,643,569,384,332,814,379,663,393,631,395,368,344,39,324,410,278,854,830,876,637,361,974,140,413,856,420,95,689,180,187,423,703,970,466,582,813,249,85,880,925,915,825,244,631,15,327,436,890,769,717,585,877,781,97,118,300,133,233,489,508,530,672,493,637,928,820,270,277,417,722,799,954,46,560,232,366,882,481,232,839,504,819,77,482,720,734,123,457,236,8,380,874,600,616,900,786,932,216,253,807,477,647,642,763,782,38,89,232,332,636,924,914,33,429,668,165,991,391,472,419,931,289,846,721,469,333,67,546,139,622,383,836,317,444,361,345,65,501,399,851,826,33,105,426,234,746,74,550,598,984,267,539,843,908,751,604,868,943,779,1000,690,385,70,469,549,86,914,822,618,393,305,579,467,530,784,515,498,800,164,812,675,37,588,194,25,316,831,675,799,545,68,935,188,673,413,505,79,390,898,865,125,397,964,830,735,254,482,525,285,333,253,645,724,397,467,611,618,540,661,272,591,765,784,503,232,346,101,585,581,570,444,569,522,693,695,272,2,885,719,404,462,723,579,833,773,585,5,243,986,571,419,291,542,900,215,185,171,608,931,973,963,863,315,581,133,775,544,735,26,640,592,219,0,266,106,565,151,334,592,182,811,492,825,987,854,143,572,352,13,318,289,515,92,468,65,967,159,325,963,580,925,778,14,24,449,816,55,862,632,789,643,67,983,261,459,861,307,522,574,477,100,538,512,106,247,135,905,935,457,826,65,419,822,341,194,871,524,157,116,196,971,539,826,535,75,859,563,146,774,524,770,802,269,939,162,630,939,189,109,957,390,967,463,432,673,831,518,35,234,199,20,553,307,524,358,74,68,750,172,339,249,195,84,620,57,423,988,619,25,736,13,540,333,125,933,705,909,920,490,114,48,251,644,320,853,229,204,797,986,281,819,330,163,933,866,512,130,180,77,808,272,277,747,527,11", +"295,644,805,94,221,254,509,969,948,494,39,571,23,549,463,377,816,555,764,804,986,6,202,810,24,24,850,246,784,155,339,669,670,68,264,107,80,926,859,170,592,180,717,89,753,994,272,76,860,466,588,633,481,496,920,359,891,457,135,963,863,953,688,421,946,973,600,354,879,359,672,364,758,365,260,280,175,301,762,854,184,550,832,267,997,995,551,94,283,949,802,288,157,550,529,324,712,543,740,45,50,684,901,643,326,615,821,35,716,885,75,837,953,520,661,954,273,116,334,977,77,470,752,845,283,838,638,224,527,497,421,438,7,856,453,170,236,976,997,92,671,403,230,832,70,503,926,826,766,234,510,735,835,23,7,544,861,610,908,795,410,624,54,499,408,883,627,595,630,171,919,925,244,431,236,408,98,315,484,582,98,12,224,752,789,139,802,421,968,336,761,817,503,950,17,243,598,479,546,545,79,501,336,731,735,649,245,274,433,379,203,563,781,627,667,67,104,843,365,360,946,282,550,242,278,551,52,326,961,309,771,405,762,341,165,881,27,409,344,295,403,167,258,263,972,155,834,271,746,730,620,65,590,899,213,216,946,286,214,814,188,325,100,69,790,986,441,703,286,892,220,484,608,631,951,327,23,920,275,597,182,309,406,840,650,893,283,170,342,826,696,212,962,57,901,769,949,71,248,451,34,630,472,106,856,632,496,721,154,955,542,602,689,772,105,634,318,241,831,863,914,895,836,406,5,975,100,842,298,821,177,222,390,624,244,49,74,26,119,882,696,653,237,654,292,285,458,277,333,920,560,858,660,725,572,710,431,69,517,318,436,26,89,440,126,175,74,367,6,432,758,299,144,59,892,370,811,735,668,957,33,694,578,475,387,66,851,142,152,948,621,156,130,505,508,790,39,856,96,891,570,323,929,823,981,968,827,150,593,40,817,933,773,593,297,849,126,875,942,710,387,544,492,679,275,209,529,390,931,830,797,625,145,558,169,272,918,441,453,453,516,642,659,244,788,800,471,524,766,314,672,610,976,404,95,684,771,427,667,21,314,509,916,932,903,743,812,202,86,368,813,353,667,605,346,538,895,76,590,332,352,113,521,824,485,119,145,226,931,691,312,301,345,189,294,781,427,866,792,521,718,99,143,874,505,83,794,172,351,349,296,601,834,300,367,2,564,35,572,298,316,870,124,768,226,305,702,244,835,995,548,288,417,51,151,621,367,199,846,284,712,970,695,496,83,879,47,389,612,26,329,665,207,934,502,248,428,462,175,236,910,401,440,286,710,451,327,280,184,175,727,128,475,390,446,127,260,999,258,736,406,681,19,472,850,183,278,769,263,147,375,525,493,924,312,57,750,914,493,775,771,721,159,522,484,533,686,268,648,253,51,206,271,733,25,237,267,641,389,698,652,533,578,848,176,500,17,289,39,571,230,319,128,653,466,259,164,691,680,844,887,651,625,692,204,579,493,210,873,436,523,966,347,761,351,420,223,447,196,859,764,272,459,107,369,891,571,725,271,576,443,772,692,504,399,358,852,928,466,45,769,429,172,400,299,273,442,55,232,888,763,87,78,235,333,983,869,942,204,426,526,198,556,75,930,50,221,282,254,968,565,659,882,915,265,779,223,61,113,587,391,370,342,883,393,96,122,285,949,57,651,678,828,384,823,11,305,385,528,880,231,481,717,694,358,124,20,751,964,552,399,178,490,584,142,568,660,764,57,493,815,701,47,577,794,602,321,745,740,737,968,319,634,159,269,417,348,499,527,120,930,307,600,349,773,874,583,123,713,920,991,8,291,717,232,644,147,447,320,242,385,368,986,356,206,544,59,348,838,94,141,302,877,160,763,592,868,536,948,269,549,298,659,371,18,609,49,251,883,72,407,57,420,781,752,531,197,504,989,285,696,41,409,481,594,339,138,266,0,268,233,564,152,666,797,800,533,774,132,141,610,393,368,38,325,45,806,576,910,462,243,230,558,37,712,57,844,422,910,339,50,985,109,265,561,621,196,893,418,157,873,7,818,395,837,855,859,955,25,15,5,239,980,193,972,514,512,984,959,644,446,44,686,176,909,465,259,996,165,437,931,341,744,495,76,959,43,194,420,210,575,991,420,696,286,237,431,466,493,712,527,417,624,895,920,919,322,869,753,709,62,388,327,199,562,317,830,367,794,903,152,907,256,230,981,446,618,494,608,24,703,879,81,347,536,323,777,169,417,978,549,1000,130,499,710,442,48,311,11,506,363,905,486,293,377,301,486,403,84,213", +"272,44,64,423,962,306,123,277,226,751,39,662,955,951,416,305,411,551,890,174,56,144,920,831,219,520,784,575,796,38,184,543,941,370,834,977,530,118,583,119,634,585,834,416,763,65,957,912,646,346,690,781,8,492,201,538,842,659,146,967,693,564,601,183,445,525,416,736,891,395,477,564,231,234,118,540,479,446,25,898,646,720,387,902,699,474,88,464,758,878,80,67,49,862,373,75,910,718,508,552,263,229,804,784,933,751,392,81,697,856,38,817,746,399,381,630,377,381,356,930,418,282,480,373,359,419,308,944,833,333,136,528,88,369,716,115,743,657,77,717,417,283,476,711,789,763,693,142,94,197,522,933,150,713,918,476,556,374,717,537,577,837,382,915,980,513,848,725,552,3,99,211,634,386,505,695,234,205,157,420,565,818,332,106,549,918,541,386,45,458,366,994,105,839,145,251,90,19,694,954,416,193,679,160,451,758,426,816,682,609,909,484,517,345,276,78,172,585,90,541,536,558,543,294,469,744,74,219,285,285,617,828,498,828,192,381,430,510,69,450,380,231,261,352,276,520,184,114,531,874,591,750,523,892,12,84,856,708,641,297,287,833,145,904,669,341,450,586,348,977,352,487,180,376,525,380,897,344,750,668,381,110,305,95,884,147,216,598,300,92,414,804,470,562,338,186,379,117,225,13,854,765,51,975,73,391,808,554,836,102,48,485,650,358,987,787,658,287,139,295,815,555,947,2,349,735,15,116,192,630,368,253,189,13,7,296,446,734,604,354,302,875,365,480,290,308,256,138,906,501,545,593,650,392,448,364,341,330,324,337,55,701,65,300,18,831,896,651,200,470,547,282,145,876,761,804,498,634,550,498,447,229,661,667,940,991,451,382,231,885,420,544,710,165,952,244,61,616,126,250,306,548,918,194,66,271,161,244,875,392,988,951,115,990,658,459,333,656,454,806,486,562,251,518,539,613,234,887,288,801,194,272,278,946,174,241,563,641,588,560,818,791,548,703,144,633,834,616,903,629,409,409,352,991,470,522,631,345,423,155,837,160,123,399,60,453,628,20,750,128,50,231,559,42,799,924,216,51,779,216,135,236,879,970,621,390,366,825,387,237,236,336,726,596,937,560,12,826,309,218,282,343,294,152,863,60,70,714,154,58,248,330,248,246,720,860,973,82,20,145,486,778,970,107,415,758,581,794,759,822,524,495,508,91,626,498,327,698,775,710,629,116,538,661,443,768,514,645,208,191,947,231,316,275,824,889,686,750,719,319,300,266,331,862,705,59,40,130,811,720,973,860,861,169,882,28,20,340,508,226,757,356,477,520,240,183,362,577,182,763,44,803,52,852,345,177,777,135,922,881,754,16,22,117,911,471,165,551,381,532,377,550,785,193,25,371,592,238,906,254,821,628,696,987,897,835,120,390,691,841,369,358,762,968,864,394,767,202,666,403,7,175,967,264,348,722,353,534,969,679,540,512,940,768,616,752,445,765,59,323,416,362,322,273,464,966,306,773,842,204,543,718,438,577,832,765,841,743,766,168,206,850,991,796,898,741,650,486,793,157,575,514,208,199,927,408,832,290,722,601,439,907,481,484,478,167,556,683,96,991,787,212,391,178,96,289,910,135,70,807,844,800,531,944,7,943,809,471,801,994,464,633,377,460,393,363,355,831,320,775,940,912,273,272,482,810,877,311,691,612,23,728,726,784,125,423,727,759,99,324,895,330,855,933,601,392,40,523,675,64,965,397,944,42,811,531,890,326,758,742,378,484,278,641,931,644,176,816,820,101,514,930,333,270,105,705,546,318,448,193,974,672,98,193,771,176,446,374,708,785,233,945,464,125,770,575,547,460,319,888,697,798,790,412,817,817,868,531,463,71,225,161,455,677,826,642,334,614,319,616,510,289,755,848,614,76,470,106,268,0,196,465,761,16,537,858,628,498,773,250,738,218,825,581,138,87,153,208,466,811,539,563,696,572,923,781,718,531,670,969,570,225,595,48,622,839,299,893,469,235,454,261,850,805,151,151,867,850,60,243,516,78,552,636,988,233,731,556,367,296,270,846,920,596,94,847,939,531,365,789,471,676,83,511,963,37,397,952,648,388,303,648,333,887,197,735,855,283,880,327,712,177,544,70,781,143,589,993,811,477,296,348,961,796,623,778,561,730,922,306,913,296,285,820,162,718,899,944,81,484,591,23,850,304,616,671,628,639,676,715,522,988,365,917,171,664,546,631,173,249,823,27,173,993,204,700,584,216,569,374", +"189,946,603,992,152,43,198,295,136,248,172,880,200,204,586,356,939,429,769,148,562,601,193,146,836,562,722,262,299,185,638,115,488,2,555,294,376,317,251,292,820,959,215,583,371,671,480,384,843,148,967,838,469,777,582,707,299,16,462,835,323,76,979,983,294,725,233,598,764,381,994,230,300,727,864,10,818,725,97,922,912,18,491,462,792,378,321,214,286,79,327,983,630,110,557,824,565,284,190,403,10,291,328,695,535,378,822,175,657,577,218,780,154,223,106,969,694,499,325,904,891,717,313,273,603,950,339,143,31,97,329,785,817,766,786,998,320,864,543,216,129,482,635,55,406,664,227,228,660,624,917,732,146,690,899,801,925,326,677,609,21,93,438,30,481,648,951,376,662,928,694,195,113,157,506,608,549,509,140,342,161,912,282,550,78,857,656,268,709,629,221,75,238,592,671,289,721,962,991,422,652,347,7,751,147,380,24,335,739,714,100,141,631,256,264,393,238,955,55,95,297,22,239,249,44,824,794,722,238,121,50,60,203,880,535,403,689,515,86,610,350,684,876,704,808,5,101,289,610,81,82,397,164,161,778,458,786,742,79,579,99,593,381,141,900,310,599,264,610,196,546,482,301,13,478,659,408,845,651,568,265,175,170,280,323,934,583,505,286,265,65,327,434,467,672,482,913,108,419,777,107,369,535,687,198,740,889,535,160,134,660,958,164,108,33,316,198,348,507,560,928,90,715,979,580,117,480,378,55,926,584,339,701,677,262,915,700,821,805,509,230,659,659,156,820,743,584,452,258,847,365,536,283,624,332,876,885,829,656,28,137,720,293,570,188,191,415,72,249,743,849,754,636,185,231,99,591,761,827,405,392,644,623,437,771,896,505,188,542,950,478,988,609,239,319,923,914,545,527,820,175,716,127,587,505,934,123,729,386,367,893,755,730,921,478,562,168,284,115,724,686,798,114,690,184,540,43,404,583,24,519,753,139,115,909,358,312,850,624,810,350,126,70,763,855,282,586,846,454,614,542,678,421,441,345,811,813,692,739,119,952,984,726,526,630,802,492,311,844,345,188,138,29,184,29,875,533,835,242,356,382,914,249,376,483,464,698,85,283,408,349,168,414,450,380,74,629,275,996,47,846,118,775,195,383,159,704,687,59,145,183,722,883,922,244,657,545,844,339,360,586,965,985,569,132,283,825,504,281,219,554,938,398,720,404,125,770,284,656,8,662,191,133,928,943,548,393,433,731,764,838,963,394,121,813,658,200,862,725,650,762,438,733,245,368,741,847,571,158,565,256,978,344,413,68,205,781,275,297,805,47,919,903,969,627,574,180,478,508,275,712,451,493,419,751,951,911,271,142,268,202,432,967,228,773,478,180,530,269,437,397,573,673,955,937,404,67,336,456,584,25,963,714,403,137,564,481,307,183,94,113,741,397,121,139,117,638,207,119,50,511,944,38,759,869,204,100,376,273,319,70,654,184,228,930,820,454,887,222,688,150,834,602,167,505,130,58,174,362,848,233,817,720,453,90,869,912,343,424,25,268,272,157,792,553,281,933,940,971,964,650,900,35,96,528,41,552,742,293,469,922,742,42,393,896,573,478,623,362,976,341,437,927,728,878,918,228,761,98,234,288,137,746,386,115,377,356,393,26,589,503,308,977,429,702,198,400,404,824,318,165,473,574,522,413,413,788,754,112,894,840,314,639,599,226,962,540,671,930,298,622,898,476,159,891,630,285,902,901,245,470,921,850,718,585,866,693,137,585,672,455,536,447,175,184,745,193,155,414,717,728,368,97,434,444,993,914,420,876,767,792,236,101,78,520,726,917,181,230,306,661,432,576,214,786,337,501,559,993,318,362,809,161,666,718,858,622,783,392,570,713,654,470,132,507,192,540,984,599,226,637,189,180,317,801,137,528,565,233,196,0,249,414,23,707,56,339,492,165,33,601,431,465,721,536,711,124,375,581,960,576,486,136,698,516,628,182,702,212,120,414,80,294,901,969,471,357,303,91,520,601,736,648,124,715,510,707,15,185,844,918,397,40,103,672,630,360,733,848,768,568,392,891,533,689,461,579,153,62,78,633,852,732,927,582,957,986,48,805,761,708,117,181,293,665,24,550,969,176,798,801,415,961,49,131,863,343,591,925,865,872,739,531,154,135,833,68,218,445,557,10,4,579,639,638,252,486,996,647,329,373,339,272,437,608,769,363,609,83,379,670,43,677,336,692,459,67,184,150,375,833,921,558,428,707,188,951,651,916,274", +"397,988,919,97,667,547,645,103,903,596,880,304,875,545,130,404,687,47,997,103,276,392,917,744,480,21,913,496,80,49,366,871,14,720,480,604,194,662,192,915,617,239,821,336,334,146,732,747,39,493,467,603,683,20,512,741,619,669,128,420,798,464,861,380,612,226,801,316,494,558,180,599,830,688,753,879,153,379,305,373,69,391,134,963,961,32,424,182,803,621,465,299,857,443,428,855,856,261,465,453,567,878,225,359,693,832,159,815,530,499,145,755,420,785,71,787,988,394,999,344,918,908,248,221,844,247,919,247,698,982,839,99,1,306,837,871,169,798,837,992,124,139,880,826,656,735,336,150,903,609,76,756,653,420,104,497,381,108,645,103,836,819,855,789,364,535,882,411,742,816,784,826,443,128,495,771,575,749,471,293,302,991,567,390,66,357,582,114,778,877,278,520,597,353,534,984,845,881,646,838,606,117,74,623,273,285,64,156,310,703,222,435,427,540,163,753,847,539,329,227,594,659,15,162,307,126,131,996,526,36,758,936,869,859,261,283,88,286,459,21,638,120,628,94,670,696,578,656,611,591,877,482,916,884,140,602,197,962,159,568,642,941,9,102,308,227,488,487,308,328,335,399,366,187,648,472,992,835,3,913,219,615,636,391,367,170,693,155,246,106,500,944,967,250,937,620,438,749,154,46,539,972,242,818,917,382,251,185,881,231,345,551,925,462,872,509,44,25,902,50,523,860,331,134,474,61,348,52,528,62,785,764,582,658,696,762,308,287,164,406,300,772,313,23,888,816,278,98,949,920,502,493,117,918,457,832,701,674,729,51,111,159,353,839,65,456,518,365,990,206,954,504,499,393,131,166,423,711,90,649,916,494,150,338,838,23,613,786,783,45,97,52,905,718,105,881,719,538,398,424,206,857,692,83,587,597,574,767,278,238,470,593,635,245,246,98,851,986,50,398,170,765,797,926,980,334,455,48,6,529,570,941,636,325,180,120,110,542,771,858,515,2,202,569,218,856,709,795,322,760,50,285,720,884,763,681,850,892,690,84,492,317,384,772,558,579,324,768,689,738,971,185,20,445,387,166,465,710,967,668,81,883,838,490,296,153,332,786,620,786,161,781,633,784,635,913,636,844,130,89,406,167,946,612,192,912,451,674,633,946,113,735,634,742,318,254,512,40,143,494,140,64,811,775,173,397,634,412,271,793,5,395,384,471,898,918,795,997,88,3,978,494,272,313,175,252,739,194,21,485,376,992,265,622,499,147,469,328,154,824,651,973,595,630,318,766,454,464,52,999,824,814,331,285,828,96,909,559,744,571,285,912,761,448,618,838,504,234,842,854,819,577,777,421,382,975,151,282,845,37,865,974,771,19,781,775,490,244,208,366,5,788,942,50,694,288,106,712,82,81,660,667,636,671,137,502,61,96,401,172,947,401,637,558,734,64,154,882,280,581,81,322,556,731,489,309,56,28,171,652,408,158,99,415,769,400,784,49,816,109,175,253,650,160,907,34,785,980,604,343,223,283,551,103,4,770,664,935,974,767,609,82,800,647,869,363,224,612,481,68,626,250,557,270,997,341,601,332,216,530,277,990,679,930,411,986,108,856,864,604,650,685,605,593,81,82,582,314,86,723,142,207,587,734,458,155,450,584,970,383,568,281,262,204,221,778,129,125,649,517,464,410,605,726,734,489,710,656,784,971,128,451,808,289,122,816,993,337,209,163,221,394,436,800,126,382,18,295,831,33,703,57,689,809,441,408,395,334,169,570,546,756,420,623,295,822,200,361,807,905,966,172,438,581,112,447,722,263,639,459,944,354,96,205,707,268,858,73,987,421,328,411,645,143,779,491,181,666,617,658,47,419,144,39,125,156,220,385,443,194,32,610,965,751,264,788,771,650,419,518,770,32,11,929,330,709,998,151,564,465,249,0,959,913,803,918,111,915,161,986,568,340,869,759,727,100,97,123,102,452,89,875,45,359,775,97,216,495,188,449,268,745,260,940,191,782,208,970,373,120,215,132,348,354,443,986,689,148,915,900,689,569,378,329,110,525,250,566,925,806,845,445,423,754,958,324,431,733,425,519,372,446,229,364,326,223,348,57,298,115,339,633,30,784,521,67,421,533,59,753,852,185,98,128,813,994,67,224,664,210,877,590,565,46,202,574,384,10,822,242,800,188,624,943,778,212,866,56,339,562,912,793,641,42,896,480,732,716,772,316,796,326,980,936,97,726,597,284,911,402,138,778,621,290,573,213,609,111,96,51", +"631,512,87,737,200,950,880,708,924,509,209,279,95,205,797,774,228,724,927,548,153,546,748,538,291,535,518,471,193,970,885,114,760,492,586,751,259,333,960,505,303,413,936,155,506,97,150,575,576,622,795,639,98,357,327,947,788,3,482,728,648,601,27,957,8,396,16,283,996,196,632,580,734,239,827,163,563,326,999,119,777,338,308,434,223,117,527,257,725,594,913,409,93,115,646,381,746,576,962,386,966,577,910,113,936,375,682,318,373,858,235,301,980,902,729,96,476,487,62,487,890,115,28,518,168,653,929,432,273,319,468,989,294,366,316,117,112,555,451,710,367,871,526,61,118,645,42,229,479,810,40,31,967,38,581,197,879,183,49,502,362,746,771,882,679,716,454,275,812,493,801,900,387,625,84,415,541,230,276,460,256,5,205,835,655,560,927,284,500,114,278,596,405,933,597,846,116,460,389,8,324,981,597,248,771,796,826,577,613,255,687,494,66,753,326,673,3,594,528,540,375,204,351,689,106,218,326,426,540,114,310,906,600,98,44,19,473,809,892,79,317,247,733,919,700,444,756,106,104,346,437,916,298,529,996,408,990,311,802,34,451,271,876,193,268,632,638,933,514,835,302,777,989,265,200,895,284,30,461,74,953,307,417,983,370,285,358,468,239,24,205,797,940,80,153,237,727,837,809,386,142,656,833,140,926,247,828,543,558,16,604,950,468,452,810,866,246,786,878,867,80,436,713,852,384,366,662,494,909,830,12,352,113,701,688,589,677,562,313,674,417,587,682,688,211,856,368,5,407,614,61,675,515,48,958,10,630,731,278,88,465,185,320,222,547,907,552,617,790,3,917,167,85,197,708,850,79,342,179,139,611,95,958,901,345,257,649,26,222,254,40,860,247,861,152,45,453,163,982,255,796,592,451,975,300,281,234,683,966,631,223,965,950,597,714,283,411,272,256,555,173,831,432,875,608,977,111,74,14,147,524,841,199,679,678,593,692,120,27,784,223,773,948,814,876,989,332,650,28,388,599,594,346,532,916,845,204,747,98,833,19,790,179,202,972,200,251,867,700,205,452,702,906,112,147,636,418,319,860,457,974,566,809,585,931,604,967,673,496,438,707,926,390,405,785,929,53,187,441,118,573,858,212,593,785,611,999,200,203,436,971,666,646,420,699,242,492,417,473,542,254,774,200,164,24,315,152,363,677,830,343,255,538,336,372,519,909,732,117,719,516,83,89,900,16,426,989,200,990,136,375,799,310,835,687,569,404,527,382,517,104,130,185,387,703,954,79,244,356,507,710,917,276,158,289,799,205,644,471,373,508,124,441,396,162,883,273,330,204,708,218,792,858,972,959,526,713,231,950,643,602,306,838,760,265,540,151,966,442,886,738,717,631,283,520,749,42,922,139,54,35,268,634,612,752,12,569,619,50,702,625,423,973,891,721,723,516,32,888,643,740,777,844,21,430,921,570,929,956,742,862,474,513,336,751,99,965,640,25,271,220,812,645,930,976,336,721,527,342,888,948,888,174,472,832,26,567,135,882,396,946,545,706,864,827,63,954,849,366,884,4,855,811,531,304,963,188,990,137,95,517,411,656,100,411,492,566,40,553,560,395,400,661,909,313,322,790,196,519,302,848,554,22,38,11,190,197,603,737,110,189,405,855,406,702,358,878,218,771,490,751,189,526,117,462,576,575,870,658,263,833,901,956,999,921,376,141,107,529,56,460,210,103,943,69,344,863,615,225,816,22,956,658,566,955,501,419,486,345,411,220,232,342,311,345,788,561,630,700,108,425,922,346,395,904,145,654,199,237,82,524,867,656,909,262,516,763,624,193,450,710,988,987,535,73,325,694,918,536,897,405,892,187,485,72,175,652,935,837,458,284,192,221,613,603,5,21,562,153,727,856,45,25,399,436,186,324,334,152,761,414,959,0,169,790,159,518,437,622,199,352,845,558,413,932,610,761,25,274,378,549,198,400,790,285,841,788,1,656,902,25,823,935,914,131,466,950,288,15,889,789,237,364,246,277,392,442,177,428,107,818,295,606,21,645,831,588,787,93,931,937,470,592,215,786,854,264,735,913,260,208,120,829,527,988,74,570,336,49,945,612,778,394,805,973,380,370,188,582,93,744,394,672,506,958,751,834,958,154,238,961,478,167,384,467,499,155,947,862,699,86,8,222,763,921,469,218,794,764,420,859,874,615,86,22,574,304,372,785,225,923,301,637,457,429,247,138,99,466,294,440,250,502,408,21,146,999,82,246,616", +"546,979,809,177,311,8,628,292,464,678,135,701,449,199,958,260,396,777,946,155,132,631,955,263,931,878,495,201,627,13,705,434,793,456,412,987,224,40,427,158,437,424,860,599,3,767,847,642,825,312,272,456,340,446,706,683,904,730,480,898,948,892,530,179,704,452,322,448,217,696,690,593,348,267,898,654,34,269,449,906,414,623,300,949,61,234,811,446,588,280,128,199,947,365,8,31,326,308,700,383,855,396,213,501,13,374,99,742,803,164,431,344,579,524,395,28,751,76,295,690,502,716,181,452,871,852,868,457,655,493,645,488,30,483,218,658,245,389,586,374,365,919,989,325,321,444,424,681,92,586,877,477,382,243,969,342,75,220,345,268,841,888,565,851,469,33,659,543,179,553,22,681,182,474,850,278,556,686,333,306,986,482,109,387,797,353,72,424,927,746,265,91,73,713,2,863,314,91,508,297,413,457,43,188,192,500,231,435,348,565,841,970,857,157,193,183,69,953,764,689,262,540,174,571,249,704,99,169,860,837,55,807,902,462,796,67,664,618,234,26,698,139,679,505,248,871,844,311,683,736,327,635,71,161,330,61,577,167,752,144,83,451,52,298,693,707,645,327,964,968,357,511,717,9,149,139,546,310,922,411,470,758,831,592,558,381,462,430,909,885,416,15,579,394,145,440,648,612,850,685,719,684,281,316,388,958,304,66,85,677,376,357,973,448,971,339,1,858,725,264,476,398,456,528,771,878,935,815,10,276,5,499,794,470,82,528,44,986,546,116,960,780,358,240,198,713,703,963,598,975,282,999,878,422,144,184,934,738,182,373,554,11,841,8,351,646,122,374,928,833,59,698,489,156,244,916,407,130,960,248,209,173,83,470,977,943,152,910,857,223,619,166,686,902,177,756,337,281,328,144,484,100,854,628,655,985,576,966,48,329,616,236,992,461,784,149,916,31,141,626,40,253,566,147,554,306,415,306,571,364,328,530,585,567,584,708,571,653,433,139,751,226,645,922,456,1000,695,542,609,672,494,449,792,107,843,362,586,820,515,733,189,93,807,292,52,860,955,412,411,216,910,371,938,880,975,430,307,869,854,555,696,801,362,426,88,998,756,947,923,644,818,197,62,652,162,921,127,532,684,729,140,919,828,596,70,325,522,581,561,914,26,130,830,228,273,854,945,266,595,540,433,3,951,929,258,719,577,566,102,156,952,472,111,963,188,906,638,900,53,413,575,743,790,581,121,896,198,236,657,810,7,171,795,991,844,156,450,555,49,977,17,470,272,26,670,64,320,717,609,971,15,862,113,596,522,402,473,751,537,201,795,694,605,53,274,154,904,614,921,984,48,692,973,476,692,189,216,92,297,826,996,744,307,544,608,140,344,957,380,67,525,64,513,729,545,432,622,134,362,736,889,416,87,391,446,921,644,151,333,238,718,808,324,858,896,642,777,34,248,352,883,639,166,40,76,754,327,958,333,222,432,277,513,971,63,133,139,975,738,349,105,880,774,217,526,609,602,690,927,682,619,590,557,990,967,996,388,307,451,555,775,542,859,176,940,967,51,201,953,846,81,37,176,679,409,342,947,330,430,540,770,347,849,56,267,153,212,292,797,581,212,291,598,277,547,396,18,717,568,491,526,217,903,941,685,834,690,168,625,257,706,479,864,112,414,284,82,557,564,801,539,950,136,450,184,38,572,420,216,905,654,772,977,34,336,817,864,172,335,633,337,729,378,960,217,926,330,106,824,771,192,187,957,687,565,925,963,563,594,24,239,334,882,633,684,380,661,555,710,124,626,660,276,417,203,118,151,52,571,776,693,215,350,980,627,535,405,814,357,287,509,139,565,338,296,48,702,106,391,133,572,202,605,250,918,110,659,660,238,215,281,867,307,922,176,505,765,421,185,78,487,205,656,835,227,942,564,592,666,16,23,913,169,0,109,298,84,696,894,33,845,24,755,31,957,256,477,372,7,899,883,731,696,695,186,939,462,257,514,90,498,833,402,807,764,951,717,497,450,718,570,468,684,953,484,400,902,863,868,871,370,797,432,833,945,288,397,916,292,943,135,476,854,980,509,221,919,95,100,376,349,296,618,154,651,997,20,674,14,800,238,139,702,543,724,508,34,560,998,710,954,805,111,915,618,1,529,736,648,448,630,531,191,550,579,607,833,995,656,575,923,113,10,968,916,649,44,66,516,452,415,170,238,150,757,677,767,887,910,427,97,83,122,679,260,119,611,734,371,844,469,673,26,505,937,506,908,975,723,181", +"178,431,605,97,195,63,331,231,66,420,762,113,806,95,824,39,628,477,233,88,201,852,767,34,190,40,862,503,478,683,599,357,628,38,44,520,298,953,629,792,492,293,553,103,154,510,238,444,843,644,276,758,67,149,686,570,395,841,91,81,479,679,927,711,537,818,381,677,767,216,306,342,98,657,227,648,10,702,582,51,716,227,931,673,563,941,931,34,715,329,373,448,771,219,736,229,879,224,465,819,640,774,133,77,653,244,709,45,499,146,560,974,452,3,431,799,200,620,302,845,226,383,168,262,819,388,245,700,689,424,945,142,355,463,512,838,619,28,404,662,671,650,92,696,711,441,43,997,305,160,699,520,396,995,381,738,170,977,750,259,929,135,570,215,724,579,326,161,353,615,69,247,332,763,427,931,598,426,438,209,996,357,532,923,816,331,406,846,256,568,622,40,782,740,745,473,995,20,812,127,732,813,713,861,210,852,998,96,204,714,742,28,264,461,172,12,502,300,327,991,189,483,288,130,635,908,157,889,686,520,848,405,376,916,408,439,443,270,965,335,49,545,77,938,665,916,50,699,439,317,62,143,955,239,921,582,469,565,567,64,780,931,991,267,956,603,134,350,179,666,204,95,850,637,935,40,181,600,320,98,752,112,794,162,604,254,546,700,311,406,294,958,37,162,627,25,72,902,751,277,274,236,558,529,401,923,345,950,903,434,711,926,571,886,234,99,127,422,265,529,827,868,934,640,557,904,188,262,343,228,279,795,564,959,877,849,681,592,615,47,868,193,883,241,475,542,28,430,130,192,540,828,991,508,899,558,974,375,30,712,367,370,796,833,268,804,813,240,105,355,187,258,980,920,442,867,696,475,744,832,431,601,328,575,972,353,436,881,794,264,485,103,750,128,730,223,487,64,672,518,534,295,756,742,305,409,227,712,422,951,778,473,190,71,331,404,518,972,39,950,552,139,404,673,655,580,292,400,736,458,33,438,655,576,181,614,994,85,758,390,656,736,621,940,534,447,953,326,827,572,776,786,772,792,831,393,150,99,525,797,297,506,4,593,968,564,302,212,983,19,59,214,374,624,361,855,693,114,936,634,291,157,118,500,389,875,599,256,174,903,339,549,623,244,416,316,879,415,366,667,85,90,127,905,755,51,739,462,176,246,591,33,985,768,883,175,847,128,515,173,402,804,898,844,588,90,292,748,350,418,9,200,364,425,627,797,945,506,466,400,842,396,184,420,477,28,897,22,78,548,688,664,396,497,299,634,208,920,898,139,142,31,598,998,415,496,777,907,189,932,374,623,931,981,434,158,865,115,148,666,475,897,265,499,577,182,937,228,914,393,859,9,151,111,285,744,321,628,65,199,61,268,210,956,750,832,562,246,46,477,281,483,236,476,810,649,88,118,615,932,264,973,411,722,477,656,780,69,650,43,516,587,683,376,686,341,315,818,323,640,824,637,314,267,65,822,197,499,951,725,164,994,752,88,507,123,137,918,779,419,100,159,471,41,860,194,106,552,856,603,522,300,230,312,876,304,692,302,147,949,513,749,113,169,215,583,835,501,88,842,604,240,726,200,390,134,994,46,650,149,954,112,40,312,298,130,728,297,906,104,918,180,511,410,499,591,794,896,269,380,29,569,592,149,45,724,141,413,731,155,875,909,204,469,955,142,465,62,282,818,439,476,364,314,216,968,119,875,460,97,225,842,857,616,423,62,356,507,605,97,748,62,574,600,430,634,732,269,586,202,173,125,421,270,165,54,554,857,162,220,961,645,971,122,725,984,386,219,540,407,5,885,174,679,378,730,255,551,526,777,669,835,872,711,581,724,459,494,584,663,725,845,585,50,416,113,772,49,725,510,252,362,751,286,238,976,218,551,804,433,130,24,741,966,246,737,551,249,268,304,327,4,367,603,744,805,232,182,797,537,707,803,790,109,0,247,16,446,814,574,694,77,385,134,937,824,145,539,31,917,137,505,690,725,394,770,301,584,300,61,146,530,96,347,895,59,693,24,927,688,765,217,968,457,9,204,865,95,2,274,227,902,301,64,299,547,521,133,821,21,301,399,919,876,186,808,752,443,456,414,199,519,606,241,390,665,914,869,487,504,293,612,392,691,405,404,795,561,122,287,771,387,821,872,328,435,481,170,130,83,253,965,117,957,501,624,909,890,862,322,734,639,452,152,361,937,462,982,136,827,705,994,4,537,917,523,106,665,611,940,357,296,373,105,685,227,786,927,376,221,571,135,653,37,358,354,231,291,735,950", +"718,640,36,858,652,73,591,356,249,213,351,834,349,833,664,121,845,93,866,371,932,790,876,332,319,86,942,824,402,918,782,797,186,432,269,906,555,731,911,725,40,509,845,455,805,451,233,937,207,990,452,451,682,12,118,403,757,632,266,304,51,805,560,50,554,606,776,837,931,555,402,400,20,205,603,596,610,835,993,668,429,870,435,464,442,636,216,16,336,350,998,713,991,698,420,674,980,36,829,95,692,976,989,209,208,760,539,388,726,519,327,624,188,959,623,297,478,759,965,666,740,679,173,825,471,385,746,147,635,75,473,629,706,721,657,638,783,903,415,366,124,798,482,410,632,500,579,433,990,261,558,374,600,5,10,31,79,545,626,206,524,167,748,958,644,375,66,496,458,74,556,764,664,212,778,323,738,103,707,39,398,408,8,677,219,70,527,885,511,577,217,799,205,78,631,990,866,649,387,463,992,792,923,467,901,595,657,668,214,492,21,407,83,293,103,188,870,380,139,450,381,352,73,236,583,337,514,253,198,160,935,415,267,928,756,440,451,376,260,215,524,124,195,429,786,489,134,580,410,436,842,614,57,678,882,641,3,903,862,745,600,174,508,36,236,682,149,741,199,869,367,635,648,713,569,393,832,669,490,481,112,273,483,657,645,829,355,926,328,384,405,309,44,582,207,321,446,105,282,20,910,213,927,553,39,8,613,678,693,826,149,327,236,320,684,767,869,508,544,971,685,199,745,424,579,262,576,169,481,937,128,617,741,682,2,606,863,776,870,413,958,671,894,327,908,984,268,812,183,339,960,692,671,684,240,737,544,712,900,36,870,213,906,616,440,644,791,955,708,976,485,866,698,754,775,929,631,928,5,317,484,91,764,527,130,898,392,549,728,52,743,667,450,446,814,786,676,118,766,823,945,511,840,257,110,567,498,78,597,519,552,268,176,517,408,999,498,955,352,966,253,725,431,430,715,446,792,628,376,687,647,801,271,9,949,830,823,498,982,141,974,966,167,206,7,371,867,739,870,780,179,617,293,991,206,588,342,305,125,730,469,781,214,161,800,778,752,39,608,576,701,697,34,84,465,905,553,814,761,887,353,393,434,366,178,568,942,287,212,571,361,696,385,849,74,877,125,902,874,670,568,361,473,671,892,523,8,334,193,354,671,405,521,928,929,771,764,393,500,359,156,767,632,494,291,96,387,899,585,964,172,961,422,880,694,858,621,712,720,738,669,955,259,498,573,778,443,973,117,242,715,648,158,50,663,528,597,326,132,924,512,498,194,328,311,630,307,667,706,167,616,505,388,634,35,727,827,269,120,740,623,292,295,901,186,389,829,573,829,790,309,148,992,906,867,614,439,30,685,25,355,745,912,807,77,648,890,426,478,395,778,572,424,87,410,775,333,892,997,255,921,585,188,970,948,17,156,911,316,387,409,272,816,705,607,588,722,884,174,59,907,912,300,604,894,929,705,552,233,479,797,572,626,486,995,493,130,573,628,20,392,842,78,47,692,237,391,180,348,910,508,95,881,961,596,552,3,989,280,808,220,936,292,483,245,72,820,690,146,570,769,704,857,176,951,860,678,546,568,324,829,426,666,170,999,789,780,901,757,552,679,34,450,677,531,847,926,572,544,432,658,112,313,62,641,500,803,282,191,54,172,948,214,137,951,35,627,972,731,30,606,490,961,835,898,677,619,660,7,155,304,156,455,133,495,593,952,2,312,295,721,186,12,967,386,616,840,458,857,802,456,447,765,503,954,291,880,707,231,503,860,463,658,418,203,471,480,783,147,242,93,878,365,77,717,22,685,646,571,637,722,749,786,241,84,245,295,211,971,875,182,241,89,754,374,981,667,473,890,549,98,482,619,959,772,93,673,836,81,319,875,846,749,831,365,585,65,395,23,404,328,198,399,238,630,546,867,811,800,858,56,918,159,298,247,0,578,536,40,698,17,609,509,403,155,797,25,807,25,146,937,479,95,378,361,5,753,240,629,351,718,900,894,538,26,252,313,348,952,281,456,446,990,444,643,299,18,661,895,821,322,767,709,423,727,184,335,230,514,374,378,92,106,466,606,981,426,914,297,348,14,391,754,140,642,890,404,971,722,370,362,160,114,885,456,400,710,614,465,498,954,864,339,893,456,821,851,978,597,644,405,324,27,886,86,735,353,11,420,562,595,947,603,749,641,111,658,997,150,800,875,555,203,62,323,397,803,390,727,948,984,361,847,773,571,301,826,481,65,185,16,101,117,986,538,419,593,110,805,39", +"124,688,197,890,81,889,964,780,132,168,375,394,129,448,782,707,855,188,178,424,660,426,336,62,679,554,451,756,982,328,950,28,736,848,461,767,355,833,805,178,122,825,606,242,34,768,902,771,325,680,234,882,2,546,686,857,447,273,658,148,740,266,701,228,727,120,873,561,48,254,344,235,187,497,572,309,818,314,68,569,63,426,581,548,282,643,250,809,564,778,866,59,634,181,812,511,20,983,229,863,95,66,242,167,244,699,143,905,436,339,59,885,773,921,627,990,699,278,236,151,571,645,159,389,315,108,988,412,313,988,244,410,947,150,821,733,341,81,391,337,644,908,249,707,945,92,631,485,567,848,455,288,369,41,541,11,885,581,119,649,44,410,52,828,831,752,88,428,61,331,226,819,954,168,122,351,451,28,217,611,765,555,20,224,789,961,819,26,141,245,169,893,242,463,890,165,956,695,807,78,359,593,596,679,112,987,666,302,731,8,629,414,855,424,635,387,13,844,441,51,827,698,689,148,879,552,969,931,492,834,932,533,511,112,100,628,756,412,61,191,689,781,82,186,878,335,895,621,610,280,789,765,626,138,352,512,730,588,537,865,334,191,190,11,419,798,612,41,235,251,85,198,585,265,316,649,73,44,661,424,807,328,783,461,478,461,889,160,150,954,48,325,80,569,666,987,762,203,990,74,907,221,499,495,215,412,806,831,820,171,767,438,866,305,488,597,605,591,34,645,332,434,975,294,128,919,851,505,881,103,57,151,285,874,74,598,238,735,191,757,286,988,33,526,677,263,119,486,163,381,667,374,294,449,20,843,507,210,321,174,244,222,804,109,321,268,846,848,167,301,982,2,44,346,486,159,657,937,741,815,334,581,679,815,556,5,285,199,420,503,926,584,697,9,818,887,110,895,756,917,707,560,886,484,947,82,369,500,822,654,527,650,636,148,277,486,430,332,866,733,358,615,518,443,209,730,810,30,220,499,596,839,319,123,498,975,403,207,62,157,759,373,657,386,522,938,583,734,814,319,356,96,3,35,308,382,427,710,632,822,614,418,897,543,491,975,800,160,672,902,383,545,8,272,455,608,941,111,279,129,432,819,483,30,970,502,568,29,405,675,689,179,510,907,737,241,775,163,271,374,276,871,444,511,557,54,626,396,343,261,653,707,458,359,785,561,671,180,226,927,59,95,751,987,94,631,746,137,163,29,912,555,847,643,239,703,238,699,563,587,677,746,627,196,496,162,602,154,85,636,155,27,843,955,506,681,534,282,236,643,686,544,904,439,627,195,421,162,794,702,60,212,837,510,32,587,27,198,24,105,685,483,841,390,783,466,10,974,335,339,851,481,415,944,734,16,68,552,55,476,152,950,185,172,968,126,840,772,598,932,224,543,781,505,834,462,796,23,99,587,985,659,230,43,340,526,276,518,778,423,617,193,859,864,172,42,788,519,527,495,854,917,314,290,357,379,259,977,99,430,849,735,22,738,552,491,597,476,207,391,933,645,526,922,889,868,848,210,873,660,828,98,319,79,465,935,832,674,453,72,658,348,929,411,778,374,381,566,448,818,906,402,342,424,874,416,142,880,411,940,908,753,420,348,429,952,629,566,365,37,574,145,891,244,471,335,796,532,467,476,348,351,786,620,536,290,554,108,698,889,371,634,889,168,379,40,746,950,195,717,439,580,25,923,805,600,840,596,298,33,387,322,445,676,446,894,315,782,322,420,163,587,822,512,328,623,680,766,575,269,419,527,3,553,589,248,483,127,49,886,142,567,540,147,969,801,690,958,192,238,574,848,960,137,768,60,129,395,962,975,531,284,152,870,204,543,889,15,476,465,101,25,262,207,982,482,44,491,521,485,639,304,99,241,37,685,42,193,551,408,662,923,167,314,813,817,694,727,442,234,917,23,84,901,283,20,308,492,533,628,339,111,518,84,16,578,0,180,259,815,715,387,273,164,569,633,769,594,166,660,540,134,29,296,557,786,614,682,330,705,249,36,371,492,441,602,441,478,796,164,794,43,561,914,289,238,162,55,605,769,511,192,874,440,966,26,203,30,686,54,799,511,712,941,852,516,758,339,462,320,590,872,427,833,170,41,794,703,13,704,181,218,673,655,633,957,87,382,533,601,616,172,18,225,293,274,126,381,73,798,724,237,770,424,646,174,396,667,63,318,776,483,33,803,740,386,657,270,369,680,125,369,906,665,102,342,967,492,255,2,553,991,288,726,649,615,721,625,294,969,803,436,65,895,638,231,344,854,942,778", +"397,805,183,591,95,91,91,5,882,606,856,319,921,773,243,487,416,26,192,563,843,95,642,826,121,255,44,350,990,343,618,549,124,244,912,631,473,273,257,581,166,886,556,55,826,73,301,404,317,769,963,347,352,796,173,832,764,872,287,924,384,850,737,609,985,808,528,822,72,77,614,805,86,433,371,958,962,545,991,41,620,679,505,172,485,110,82,20,567,202,428,302,94,710,697,93,672,816,453,336,867,29,76,371,540,854,315,710,705,546,418,876,604,73,854,676,687,729,86,875,210,773,117,954,315,250,747,682,560,905,895,320,687,204,672,323,775,112,901,912,951,448,447,777,282,673,366,954,291,581,211,400,661,733,45,974,191,31,295,794,407,181,994,454,592,984,624,924,339,412,358,313,805,73,269,535,212,60,396,90,864,908,837,524,895,903,135,691,853,74,178,151,544,139,340,840,24,604,797,740,522,19,619,490,384,186,405,108,311,581,397,679,666,586,690,210,295,782,456,12,498,212,596,556,883,969,697,490,969,641,632,5,905,790,990,685,300,521,245,887,622,172,387,558,822,158,796,218,640,205,809,162,895,241,809,880,542,471,239,696,812,283,397,445,83,364,413,785,602,48,799,383,966,648,121,305,922,619,998,59,445,655,526,645,333,239,273,505,262,159,246,760,914,181,124,417,306,503,473,796,461,729,940,502,882,423,723,485,873,896,895,392,103,929,985,747,697,707,454,687,404,879,77,562,985,781,96,336,219,569,121,503,718,510,80,271,150,18,848,257,968,402,778,391,804,821,491,263,522,703,74,360,509,674,273,148,997,955,55,827,488,714,893,219,479,167,246,498,745,722,475,420,961,349,680,901,732,223,13,159,574,770,988,203,845,426,81,645,570,234,588,793,53,825,179,2,654,644,437,583,408,133,14,731,61,481,41,883,442,407,427,999,152,481,936,422,63,520,626,859,435,113,237,7,312,300,495,604,339,903,673,989,383,179,984,993,266,911,494,541,190,377,849,37,800,574,846,129,270,726,626,928,409,657,89,270,219,529,121,919,76,593,933,879,125,91,604,568,635,674,499,548,808,107,261,40,511,772,861,21,526,266,784,78,396,516,750,723,241,72,527,88,442,36,903,116,464,240,25,706,641,416,323,288,302,600,939,862,676,980,794,909,499,579,215,678,609,161,743,171,573,267,921,558,6,551,593,23,45,821,994,718,726,216,608,974,368,629,615,860,429,904,82,836,491,606,951,570,520,289,331,749,564,617,663,382,381,745,16,931,284,890,605,153,793,198,256,866,96,34,986,542,665,561,725,6,987,846,688,47,124,843,386,795,305,964,502,292,855,423,933,878,22,488,51,877,404,165,80,666,929,287,315,745,271,668,606,501,112,216,205,846,982,155,698,471,529,387,777,140,791,504,655,328,807,179,621,967,63,967,924,234,457,469,521,563,930,3,2,139,882,114,147,428,913,420,265,457,933,566,451,796,267,297,363,937,207,826,540,508,632,936,997,390,58,484,926,819,475,527,888,399,991,498,521,231,449,789,839,251,99,778,658,259,714,749,162,599,917,498,308,568,904,155,734,898,492,770,480,287,929,163,689,355,129,988,67,689,789,455,495,676,755,162,714,718,501,299,3,597,208,724,519,48,430,881,131,773,709,776,104,559,841,124,354,987,920,185,215,932,597,221,764,36,268,279,94,218,760,863,295,829,136,109,479,839,546,486,455,802,278,243,305,122,570,513,358,81,900,340,792,866,915,955,860,409,396,765,132,569,920,647,588,104,753,457,398,682,514,796,653,100,521,472,901,757,317,632,597,573,704,320,964,722,554,741,280,552,834,846,616,105,895,920,571,503,60,293,821,108,684,763,202,111,991,350,685,206,204,840,219,47,123,860,604,446,458,400,37,259,873,974,877,865,488,414,646,825,774,498,492,915,437,696,446,536,180,0,674,427,610,449,92,530,892,965,152,979,462,972,46,351,880,913,476,254,785,536,562,348,860,194,603,151,978,948,221,140,72,928,879,862,293,131,363,877,176,913,537,149,699,397,241,386,717,397,370,830,940,428,63,114,185,352,86,363,302,3,582,727,369,159,546,324,322,309,589,232,515,358,180,994,224,378,842,921,556,955,606,162,231,270,516,113,414,80,593,246,102,963,30,408,667,957,966,960,808,957,990,632,409,998,418,850,488,276,951,755,400,927,861,796,447,615,53,869,357,429,901,715,984,478,658,663,292,450,125,78,269,823,848,853,132,943,149,920,266,271,657,495", +"234,386,639,23,307,873,823,718,320,39,300,251,428,327,161,572,881,244,325,334,232,772,638,456,856,233,246,958,95,891,666,258,356,457,293,520,961,834,184,895,517,66,891,840,92,385,897,658,489,612,474,928,649,768,275,536,682,424,278,607,917,4,760,190,263,206,88,916,595,834,892,521,717,268,721,634,887,461,189,629,611,534,367,673,487,493,281,281,926,637,360,594,518,103,685,259,162,829,709,250,791,368,648,986,319,956,533,217,582,146,415,368,639,454,349,325,484,481,399,873,827,54,738,180,317,347,806,466,519,594,746,849,781,740,711,398,921,258,222,856,895,494,255,421,315,295,458,618,596,184,884,772,530,441,303,927,280,920,714,252,599,706,811,509,517,983,849,918,798,941,415,885,431,246,586,894,57,612,227,876,957,590,106,826,272,269,64,479,365,956,705,399,893,760,811,937,818,166,512,953,457,987,846,727,574,888,365,879,870,666,249,82,749,266,432,531,379,396,238,343,3,800,613,977,995,86,55,746,452,743,812,622,455,173,411,312,648,867,559,497,522,333,943,8,189,338,202,396,435,794,402,556,600,618,659,993,786,10,816,283,725,176,404,518,651,376,537,776,812,532,902,613,463,664,871,307,728,313,664,308,449,509,969,297,820,63,494,176,399,949,281,886,345,803,165,757,704,485,643,933,316,860,890,991,276,716,128,628,743,13,378,512,497,911,157,649,120,67,584,404,407,681,382,608,527,597,202,254,32,676,237,793,520,513,477,522,685,136,239,420,829,223,865,472,731,71,312,243,523,700,191,584,677,173,455,6,391,949,829,630,693,100,384,435,19,238,267,384,979,908,76,729,688,175,188,639,134,692,215,141,224,360,80,948,208,188,181,368,295,376,70,702,767,37,219,534,182,885,36,775,713,581,177,972,780,110,304,148,272,238,692,790,830,347,157,462,74,549,485,132,924,666,884,1,509,290,146,762,898,293,670,62,182,406,512,32,434,447,484,562,387,797,895,614,586,642,360,660,906,28,782,423,127,115,433,308,562,534,207,468,278,869,807,757,371,74,358,489,192,233,10,487,642,168,107,618,250,61,567,247,445,454,433,521,643,297,108,389,586,690,435,260,642,555,24,653,746,651,665,265,624,118,331,806,416,392,711,208,879,555,122,602,97,496,913,981,559,211,480,331,539,411,977,672,942,950,751,154,373,157,698,771,732,70,858,364,765,297,921,818,490,566,548,9,96,343,926,289,754,267,309,828,356,107,273,460,520,32,839,497,940,443,973,811,234,651,907,353,56,591,202,640,727,908,815,910,665,670,873,932,172,784,607,606,197,121,648,855,561,242,668,622,229,409,473,475,156,620,337,870,227,695,280,669,365,143,702,929,445,541,313,919,495,718,879,880,185,447,208,103,809,937,639,98,288,24,934,699,218,296,606,379,553,583,377,455,702,687,703,534,300,28,53,459,833,711,761,204,186,632,603,846,282,352,482,449,735,493,451,33,630,422,945,101,913,488,659,903,591,573,306,346,59,566,377,314,709,979,835,862,132,721,637,617,426,531,956,304,175,779,941,588,242,869,152,972,628,975,292,648,289,583,266,30,540,58,36,195,854,193,927,365,371,249,282,557,666,965,559,518,159,705,984,62,32,60,896,33,463,439,656,543,171,315,281,389,51,579,710,54,819,299,304,48,543,384,243,149,89,891,223,363,87,144,981,224,830,546,486,504,337,196,736,53,700,914,712,297,639,624,343,714,122,629,588,692,486,750,284,838,7,616,442,443,462,378,984,541,487,141,767,421,166,819,404,778,424,353,802,427,944,86,32,882,48,973,257,31,449,356,822,909,100,63,493,799,271,8,109,999,470,577,246,578,255,44,807,934,328,733,395,342,153,715,903,665,77,209,323,885,774,302,725,169,28,284,146,987,132,773,165,161,622,894,814,40,259,674,0,896,547,259,136,216,115,738,510,861,907,835,738,103,503,235,487,468,838,800,872,330,738,468,179,317,390,177,588,348,44,883,939,812,347,998,163,528,351,803,759,525,789,824,44,972,503,445,627,497,651,794,620,320,39,248,842,347,554,432,117,56,113,969,563,828,845,118,581,469,570,175,703,746,802,167,766,865,744,944,183,932,616,923,859,599,265,366,224,267,271,786,831,687,527,809,163,366,466,794,714,628,290,160,116,312,736,326,173,584,858,884,115,675,983,717,745,822,209,930,606,230,279,711,871,161,739,194,60,488,117,457,92,339,728,909,515,829,300,145,376,892", +"251,809,333,84,739,829,41,752,215,836,833,534,881,973,238,524,196,138,521,992,134,433,451,643,763,932,22,540,308,219,542,558,80,796,545,744,306,872,428,915,95,312,167,881,109,740,728,485,655,73,515,375,159,611,880,522,154,123,706,848,685,689,379,828,158,259,76,933,823,265,292,716,914,113,306,318,662,731,11,734,456,809,757,522,176,583,3,812,109,518,814,546,771,166,274,358,960,761,691,599,206,323,153,409,202,160,233,659,675,785,200,287,570,753,147,422,861,23,206,237,707,768,433,647,857,500,520,548,677,808,660,863,650,662,876,656,763,110,36,840,933,504,699,838,89,474,10,61,508,796,781,63,166,768,752,373,189,459,461,103,79,790,799,961,109,123,268,193,678,848,617,47,352,132,464,225,58,147,845,715,360,424,733,899,900,488,771,302,631,579,861,813,638,883,95,860,625,167,41,282,979,785,49,926,415,236,579,498,195,696,774,105,494,16,434,58,841,634,143,380,680,987,911,858,824,948,554,10,763,581,680,279,345,897,622,886,468,214,686,535,799,179,635,737,671,521,110,736,561,197,207,551,738,583,211,510,661,569,515,439,3,241,432,982,409,314,296,992,221,828,227,275,113,289,959,126,56,38,24,730,292,408,550,565,164,77,866,830,762,897,24,233,118,351,616,524,824,768,483,455,963,61,974,682,585,381,651,617,202,330,107,54,295,5,37,779,325,943,745,71,861,756,369,588,223,930,682,387,419,377,911,527,560,416,814,766,265,861,934,864,275,17,62,783,823,140,244,54,837,151,536,117,719,563,850,144,645,956,660,796,247,657,379,604,185,143,712,670,898,531,154,816,43,347,655,125,508,262,990,505,935,53,434,85,478,452,859,822,27,858,63,826,667,117,839,38,836,641,557,900,614,593,466,491,809,18,448,198,437,282,632,462,770,180,871,883,473,143,341,991,822,704,618,188,721,883,784,634,328,852,562,644,161,706,777,976,211,603,904,931,65,668,938,906,659,637,88,639,700,816,622,188,306,93,718,956,459,711,927,670,142,333,628,800,453,573,374,471,267,968,325,991,556,651,536,356,556,551,132,179,850,672,632,348,846,490,147,962,163,573,917,440,698,600,706,29,485,500,528,355,599,202,114,438,51,488,715,142,104,407,997,966,984,26,763,146,77,833,391,631,681,126,38,751,425,200,478,784,17,9,61,154,485,449,866,638,802,600,426,905,779,411,463,559,737,440,506,90,59,814,938,234,225,937,483,934,734,861,663,506,524,301,724,845,278,435,422,384,626,803,616,290,602,297,52,370,601,633,221,823,381,451,628,969,133,297,390,689,395,243,872,629,143,71,809,53,587,1000,489,695,555,218,434,152,576,961,876,129,369,265,808,996,740,933,3,11,898,73,634,279,888,744,455,996,637,382,637,347,349,464,613,942,824,429,6,951,382,22,877,526,74,128,640,190,30,112,107,526,732,309,93,289,524,871,81,879,140,691,291,948,638,576,976,131,310,724,497,538,978,551,166,218,504,249,695,156,178,114,520,811,380,173,337,345,158,930,840,187,447,963,634,292,638,759,882,811,86,799,992,168,832,703,269,2,875,875,472,543,400,931,405,240,679,229,354,10,324,101,168,557,243,456,337,644,630,292,366,809,656,995,603,950,411,486,501,665,691,747,167,167,304,262,705,561,811,472,660,709,475,745,48,167,446,285,97,429,839,400,439,873,275,263,699,339,464,698,272,726,45,505,290,902,246,458,745,653,300,354,165,326,443,355,272,47,632,764,540,499,389,767,142,928,142,471,638,264,84,382,965,803,555,590,138,824,113,58,637,152,894,249,950,279,41,21,181,791,65,727,52,881,543,325,20,952,706,533,397,967,382,821,569,28,574,919,954,56,428,901,474,740,294,998,351,894,884,232,210,854,141,250,33,986,199,33,574,698,815,427,896,0,283,735,979,642,689,588,156,50,959,897,54,247,295,824,553,905,583,605,740,203,226,46,831,605,405,961,609,473,397,410,329,834,99,110,834,834,229,775,463,856,946,8,869,807,372,294,35,463,94,576,227,305,141,24,640,669,101,948,770,669,432,977,514,502,676,94,976,761,679,819,438,903,982,848,676,756,269,664,301,611,123,366,121,463,359,782,350,457,754,474,344,547,41,543,84,242,395,885,858,686,236,716,886,737,294,712,316,940,562,870,746,782,799,450,712,864,997,329,177,830,714,327,825,524,109,833,600,821,453,368,563,463,256,275,509,291,408,995,932,981", +"503,863,991,945,685,512,843,608,351,27,588,247,201,853,325,689,801,246,32,908,654,84,847,675,68,478,526,146,149,92,873,223,109,877,982,494,987,927,558,534,964,580,10,326,503,738,238,165,365,86,874,641,258,461,778,98,572,117,789,700,955,70,806,336,362,985,758,101,302,396,833,735,73,30,736,588,33,478,142,493,994,247,374,770,369,55,902,737,457,375,152,139,340,385,662,916,158,246,553,957,339,571,233,871,670,679,190,115,677,757,127,723,335,846,563,208,397,717,612,232,101,158,96,46,369,550,37,622,374,774,941,419,522,132,987,295,950,127,699,389,467,625,439,547,203,167,240,725,115,244,227,243,440,731,83,113,683,20,765,292,33,292,462,801,818,700,883,718,505,442,745,677,945,506,361,110,334,42,832,553,633,129,731,39,736,106,257,876,759,820,101,164,403,202,69,684,696,368,440,609,960,505,675,530,925,978,27,365,193,320,489,109,324,628,716,754,698,62,396,121,542,429,312,196,304,122,356,857,422,575,926,692,555,171,80,349,25,625,151,527,462,193,203,853,367,254,368,436,522,646,399,38,458,139,888,424,603,442,6,221,879,384,645,217,446,970,524,88,508,257,563,94,991,787,419,636,953,756,328,983,298,315,693,352,169,687,342,942,915,638,684,349,204,608,390,992,739,80,116,873,181,384,143,980,699,570,643,303,4,861,90,97,493,810,926,191,414,852,65,199,573,811,805,960,73,977,206,382,776,244,250,683,273,948,584,33,636,906,691,886,556,645,358,648,316,511,853,973,998,728,146,333,455,465,487,809,794,213,130,811,359,172,273,188,768,782,177,116,352,311,519,339,186,997,276,866,112,766,110,922,158,796,279,669,268,136,201,974,193,353,979,108,796,419,234,292,618,859,661,918,787,691,659,842,211,416,494,396,391,263,263,313,909,64,440,714,495,587,180,874,559,449,814,211,418,649,208,176,529,854,830,283,587,825,293,960,770,797,954,837,73,192,762,389,772,809,627,247,491,569,211,418,469,186,995,981,889,414,930,909,561,765,840,480,874,999,911,291,814,977,858,838,498,167,665,494,135,47,602,209,275,643,448,469,436,445,638,407,568,438,638,543,839,640,254,180,350,971,47,768,117,91,985,603,211,725,475,568,910,79,970,259,221,113,692,609,876,115,940,944,288,1,915,85,773,147,11,294,328,425,438,146,727,101,994,980,262,4,512,194,430,615,403,308,18,242,327,357,576,720,330,533,110,464,802,642,512,463,95,710,830,711,418,378,54,592,569,669,837,91,699,860,717,63,27,448,610,580,524,5,509,942,487,124,609,450,610,6,807,122,909,491,460,354,987,317,733,355,90,929,535,919,378,761,109,607,775,652,653,647,623,843,665,682,689,423,403,256,240,304,371,392,412,242,405,503,614,243,199,954,594,807,540,536,370,265,113,75,154,913,892,665,579,303,372,894,608,40,947,973,934,262,788,600,637,306,613,689,731,810,962,965,669,853,47,395,256,181,919,280,751,675,795,177,81,705,233,531,449,718,27,285,482,19,756,401,898,925,909,157,351,601,545,464,713,34,401,955,147,429,91,154,583,993,491,986,580,505,946,63,765,149,292,193,308,780,861,396,433,551,577,804,861,982,910,34,468,664,37,708,541,412,216,251,110,628,588,479,128,793,216,325,380,263,8,396,739,454,263,318,435,256,369,733,348,256,783,81,627,748,313,633,600,770,824,428,520,488,803,194,885,809,28,447,999,802,565,156,528,117,675,524,98,773,670,790,612,208,933,380,416,322,777,403,33,833,691,779,346,419,174,30,373,972,684,512,661,644,797,584,754,767,320,567,825,461,843,259,248,709,949,283,236,480,115,50,381,849,734,174,337,707,901,551,153,935,824,310,439,112,464,951,998,229,468,509,270,143,610,738,601,568,352,845,694,17,715,610,547,283,0,362,104,420,857,79,307,301,131,441,134,449,323,469,679,87,58,224,532,819,472,781,414,103,189,961,477,354,215,607,467,799,429,845,307,556,132,921,78,830,615,863,728,746,286,388,397,871,429,638,65,966,118,76,822,366,922,694,268,316,908,453,483,715,836,605,13,918,52,682,447,363,695,710,431,767,878,299,534,774,115,417,374,772,966,21,202,789,964,42,914,126,550,778,530,448,246,92,66,919,838,365,78,269,220,606,888,782,403,701,740,16,870,652,609,129,504,873,39,393,256,542,831,602,199,3,323,127,408,430,761,711,678,572,383,863,623,545,767,142", +"64,329,644,621,403,3,605,417,191,625,591,725,718,399,824,289,835,379,573,948,308,700,480,894,682,758,121,422,461,822,437,139,312,67,986,753,200,465,78,393,381,621,208,717,618,750,493,363,450,979,142,77,756,454,604,359,287,24,925,314,953,277,211,990,114,362,419,355,743,288,925,431,424,722,926,865,138,619,914,821,16,998,257,36,884,411,722,505,495,301,691,326,701,221,357,528,326,653,793,513,575,208,86,781,455,130,990,211,142,95,695,757,947,567,544,201,305,196,391,409,828,345,92,987,230,366,820,947,519,720,446,771,669,567,509,683,849,327,818,730,908,131,88,407,131,474,688,352,939,939,515,208,210,664,939,453,502,498,22,738,529,146,754,602,956,635,232,80,109,741,992,929,993,828,565,944,73,405,626,634,460,392,456,430,284,307,431,571,143,212,29,373,658,714,508,928,249,389,245,643,790,645,770,459,372,377,756,336,499,163,251,760,613,960,301,84,906,420,642,379,3,147,535,772,908,739,622,660,837,448,327,884,949,280,916,980,87,962,670,652,422,725,131,545,311,321,695,386,757,698,896,610,97,590,271,370,405,471,917,571,976,776,215,877,391,102,829,380,450,326,346,489,953,479,532,10,877,357,311,715,487,821,907,395,869,669,410,990,549,36,882,684,586,833,288,200,629,896,750,588,658,964,634,926,851,791,119,947,637,464,562,103,131,708,748,495,82,316,880,40,801,872,679,551,331,457,288,227,134,452,250,501,221,683,411,705,695,345,610,812,907,545,404,293,992,161,741,845,273,110,30,831,841,734,249,306,285,38,208,804,691,8,189,224,315,325,553,492,765,786,415,855,998,874,828,458,576,511,809,397,705,194,234,6,684,14,728,652,800,861,7,126,658,726,640,569,939,850,105,369,923,994,516,579,472,244,966,344,824,399,623,516,445,723,467,72,732,609,286,554,685,378,152,607,581,882,944,366,111,715,422,216,61,824,387,613,892,437,526,897,822,223,597,11,834,913,150,823,948,479,180,114,221,879,835,338,913,798,394,591,92,642,902,892,594,811,790,339,808,836,770,939,269,353,561,787,176,810,765,222,377,715,702,108,235,530,86,226,284,186,128,591,266,464,148,353,586,901,525,832,763,928,344,730,55,306,932,586,405,567,430,712,990,925,573,109,950,705,342,616,341,934,5,614,287,779,367,681,343,622,137,268,359,929,505,610,367,487,171,275,686,352,526,991,740,530,343,694,809,591,944,471,944,354,912,769,388,802,586,347,623,921,138,162,457,383,335,102,600,34,560,706,749,222,532,53,806,143,534,658,450,1,419,458,700,346,880,755,624,217,775,438,111,908,451,490,866,42,129,686,925,16,914,162,872,180,86,269,197,676,118,809,58,233,396,482,380,241,825,807,96,311,700,778,500,443,444,427,953,144,118,128,758,527,997,203,934,171,296,539,306,732,926,15,627,242,677,821,379,902,856,60,529,877,602,275,216,669,253,181,983,50,861,368,479,886,780,845,771,854,89,351,37,790,694,547,202,515,261,236,458,595,832,309,703,220,736,641,739,834,64,675,154,758,955,78,323,484,585,944,684,19,993,923,975,90,53,859,630,739,865,252,561,341,669,965,602,200,204,290,145,77,617,545,432,346,787,128,642,898,97,608,387,542,171,940,805,252,238,602,652,986,264,703,803,76,334,605,158,629,363,751,859,100,659,14,656,74,963,652,808,181,863,551,422,185,381,836,507,569,351,918,279,786,964,896,626,261,994,768,428,97,601,218,931,165,568,908,460,551,208,923,150,59,197,198,934,234,496,547,438,28,108,924,62,949,904,106,73,628,574,577,696,942,780,391,901,943,299,219,354,764,214,50,226,131,910,65,303,540,373,733,388,492,957,110,850,702,226,273,326,860,225,52,859,933,32,572,393,218,431,340,845,24,77,609,387,449,259,735,362,0,641,339,731,104,361,504,694,423,457,730,875,325,496,23,905,581,266,934,360,773,611,388,733,778,438,361,855,942,713,802,883,399,411,18,234,384,887,488,605,615,399,305,969,280,966,93,602,99,298,527,834,994,896,523,84,430,56,554,123,811,205,754,641,254,643,678,516,88,618,531,646,10,5,181,100,720,819,951,254,781,101,616,619,952,54,911,698,152,942,325,437,613,933,928,823,732,43,281,944,500,20,955,682,806,489,156,204,604,835,781,970,776,975,29,252,326,792,850,837,864,461,574,748,657,588,24,890,124,877,799,423,303,847,169,250,471,135,886", +"990,152,570,755,955,769,449,928,265,777,563,882,895,179,653,220,895,251,352,421,458,435,348,462,923,448,854,175,576,179,215,155,978,78,328,187,639,908,404,971,727,963,924,839,315,618,999,161,724,608,851,912,193,416,112,224,292,637,81,965,560,779,673,259,181,990,350,963,791,214,402,993,327,457,610,866,375,817,255,428,740,888,916,871,319,619,870,500,93,341,426,515,757,834,748,422,25,467,648,41,408,484,122,411,843,595,148,49,480,31,711,224,764,68,427,516,126,767,952,743,166,524,606,184,711,576,219,302,703,247,867,958,275,646,566,293,381,97,969,348,122,407,981,156,663,618,978,5,615,892,519,777,21,488,639,673,286,939,321,701,279,131,459,420,524,996,176,81,447,21,578,163,780,293,349,897,426,206,949,871,918,587,852,397,265,729,173,888,118,840,943,640,251,986,150,935,960,868,615,406,177,105,568,890,372,28,649,39,173,201,19,340,296,952,891,927,216,786,9,948,608,37,876,863,804,454,717,630,727,912,612,482,666,440,323,252,374,501,184,685,80,639,832,159,592,755,382,267,855,271,875,499,47,945,431,486,781,475,111,527,566,890,700,895,489,543,980,877,632,999,221,135,965,560,514,437,43,3,316,35,443,246,703,884,307,941,606,911,37,173,947,885,727,484,85,667,177,331,498,330,530,967,281,994,448,139,846,534,270,85,678,748,414,100,396,359,209,103,246,464,592,55,687,376,470,449,514,419,992,575,373,23,575,251,410,171,867,429,877,661,340,230,412,482,320,156,865,727,817,55,840,238,794,979,161,524,452,726,681,815,556,577,968,898,611,764,635,833,188,173,53,198,988,26,874,702,373,862,802,197,101,847,561,619,188,914,515,251,646,476,197,488,246,925,661,528,139,921,846,797,609,155,615,450,657,417,272,144,238,272,606,59,264,506,265,70,197,735,483,786,316,398,620,95,704,976,101,26,620,933,599,382,211,644,390,576,353,822,394,868,387,782,882,177,550,744,850,723,151,754,106,901,298,905,806,71,265,880,629,238,217,43,807,661,319,180,306,221,733,129,705,765,657,830,353,55,129,25,781,640,976,543,222,346,992,751,484,215,282,978,344,902,650,87,143,904,576,553,212,612,599,571,513,397,514,33,759,111,567,649,631,549,731,226,336,237,976,95,15,323,391,762,680,619,660,671,246,65,3,547,338,938,948,673,717,937,513,369,622,476,6,624,862,341,342,969,420,244,60,902,407,998,940,442,858,32,517,437,695,203,417,109,242,593,578,277,310,39,529,647,96,393,500,611,851,342,326,561,123,968,889,33,287,220,388,139,998,745,661,72,51,738,575,780,898,151,934,696,647,921,397,543,840,797,312,53,313,382,626,495,772,230,768,962,912,328,643,316,860,201,713,325,152,166,935,58,9,578,939,800,847,376,265,411,346,944,491,857,475,82,60,76,885,832,865,504,756,144,336,829,407,494,279,569,625,895,251,22,237,66,676,88,209,494,721,460,370,368,732,227,540,77,9,429,319,405,310,58,367,420,934,889,656,411,699,850,606,763,53,313,349,504,55,500,13,795,829,20,980,520,675,694,952,267,574,376,546,590,228,371,517,540,366,637,789,948,108,829,965,16,124,758,186,190,387,418,856,438,201,580,415,571,617,352,293,536,743,963,859,5,309,682,191,683,994,585,65,214,832,711,424,216,387,638,408,695,536,395,531,293,880,320,823,484,649,12,737,43,948,527,56,9,413,447,428,107,420,175,78,503,940,713,524,246,969,76,99,186,538,693,213,814,730,132,615,190,523,827,554,334,484,757,223,458,804,136,391,275,255,595,525,793,57,818,160,592,683,390,339,244,237,278,451,690,859,376,852,951,92,64,315,930,740,541,97,878,951,433,586,937,14,190,193,683,672,959,839,352,368,825,465,869,558,755,385,509,273,92,136,979,104,641,0,707,424,890,554,881,46,936,755,730,564,62,936,537,21,285,885,531,655,317,476,600,784,129,927,198,316,620,6,831,102,440,315,180,976,468,572,759,659,10,774,500,212,757,347,181,457,641,107,81,940,269,60,328,58,285,109,297,307,572,468,94,956,674,153,244,762,702,117,55,722,733,800,687,884,525,445,284,577,927,991,652,290,539,830,461,524,991,903,463,37,353,35,501,165,616,830,777,111,837,465,706,542,42,746,659,247,738,384,826,838,178,639,656,864,296,234,143,717,312,51,340,578,163,278,434,915,265,364,363,191,529,397,91,839,804,13,484", +"295,131,761,459,525,862,123,129,690,4,882,884,656,252,595,44,798,173,171,350,899,516,313,764,435,21,836,775,434,553,450,787,105,854,484,645,443,668,172,922,216,737,153,600,24,518,171,234,496,431,81,614,392,968,726,431,573,133,234,228,385,92,991,913,564,851,105,509,89,916,430,442,595,879,325,646,953,349,878,819,366,494,62,114,589,590,804,47,508,728,79,693,428,218,726,360,770,29,611,486,235,514,789,2,646,244,568,786,741,715,82,415,381,580,530,732,595,979,2,944,992,145,894,852,779,937,823,419,416,3,997,648,858,708,318,175,909,219,710,504,448,897,669,734,753,111,557,565,300,834,642,856,11,982,934,373,893,673,794,672,728,224,803,832,776,604,218,176,785,275,299,649,187,627,811,147,743,831,925,859,765,822,961,486,93,639,170,312,877,341,572,61,547,883,791,25,158,603,894,703,348,895,456,180,200,872,134,670,713,513,329,585,651,650,256,293,209,547,182,510,433,927,229,367,440,370,471,652,306,46,22,779,420,319,878,11,932,457,644,908,375,246,154,240,957,282,848,506,497,388,672,576,204,194,129,888,79,981,263,984,329,341,669,237,568,118,216,354,915,988,227,702,211,124,203,927,633,870,415,186,579,778,871,188,655,492,325,734,448,249,169,123,155,135,538,47,62,52,918,418,541,24,97,187,325,776,474,268,711,54,21,941,204,848,809,81,465,444,502,350,453,950,173,419,965,2,834,428,117,51,675,392,374,500,88,793,756,917,717,795,305,150,806,138,185,359,6,17,560,313,168,879,607,811,388,536,935,999,945,428,435,186,881,271,52,810,897,904,931,623,94,790,348,340,525,23,113,762,85,200,981,450,650,826,154,43,907,395,112,525,986,541,603,448,987,398,243,84,842,559,969,899,615,41,833,286,742,698,454,2,699,841,119,966,865,38,489,759,51,118,795,572,857,424,396,969,757,122,592,538,123,798,275,638,92,133,499,848,913,469,118,633,736,266,732,129,729,979,577,142,848,241,622,797,167,23,958,674,215,676,326,96,28,384,851,986,607,322,775,509,273,870,783,299,536,762,715,233,11,909,627,306,959,448,775,428,606,37,107,504,485,85,180,590,740,288,862,861,20,245,401,806,582,133,201,257,935,346,58,741,259,312,454,894,812,135,294,35,152,328,156,848,928,478,847,212,877,306,593,359,184,183,949,521,555,749,96,813,902,266,50,618,682,225,229,77,835,196,340,458,506,159,816,782,646,234,606,118,272,825,178,862,635,448,615,508,223,210,764,694,379,136,270,828,523,304,153,964,826,559,670,496,702,986,152,385,497,436,86,343,829,530,835,136,986,387,788,783,676,812,242,526,949,974,711,306,456,955,188,469,355,482,803,517,631,886,41,406,19,766,739,493,823,144,436,217,586,793,432,868,795,74,190,409,6,447,232,607,340,669,445,641,931,969,444,453,838,451,136,379,354,645,899,886,108,845,852,620,445,493,401,609,559,909,720,872,811,426,385,759,645,518,902,622,816,544,908,818,326,959,304,314,243,667,395,113,496,96,194,991,467,449,827,470,967,824,621,18,936,53,826,508,492,898,499,266,835,170,847,940,28,650,525,587,313,41,538,444,856,149,133,658,793,295,414,438,622,459,358,697,579,190,894,22,766,550,916,488,808,340,172,442,184,298,273,463,242,298,115,324,964,979,396,676,640,121,177,47,721,780,38,941,460,798,40,881,590,415,26,999,303,413,94,575,763,524,774,541,756,465,809,327,391,970,607,972,76,150,852,214,158,66,864,980,200,821,54,64,960,298,344,744,864,994,365,602,77,853,401,711,570,870,43,686,978,334,760,716,495,571,215,591,296,940,99,161,39,708,646,886,247,707,656,704,528,304,693,387,40,924,762,82,955,967,196,806,668,13,38,581,721,759,413,31,134,403,164,530,216,642,420,339,707,0,917,812,790,288,662,731,939,418,920,63,398,617,227,39,671,142,716,751,733,399,100,752,82,405,919,81,832,214,414,171,224,31,773,408,968,621,8,70,970,230,617,749,32,783,956,191,221,592,744,278,943,187,699,220,494,11,20,653,2,542,374,415,55,752,340,382,5,352,408,46,52,304,289,356,67,349,803,913,778,942,534,285,870,744,920,868,155,892,24,465,150,303,660,797,951,956,530,552,892,973,333,214,959,603,346,478,329,860,875,298,238,415,386,735,353,922,683,480,510,660,781,373,567,36,902,150,486,18,404,154,48,888,584,228,976,1000", +"733,603,180,536,289,225,361,191,28,392,661,828,742,271,180,789,393,197,259,474,808,521,643,984,164,152,954,634,609,554,566,641,623,645,182,934,812,611,913,229,333,992,839,785,388,815,810,310,959,988,758,329,335,54,603,509,672,690,868,351,787,645,932,289,339,102,767,549,357,350,332,410,49,751,261,24,354,562,585,447,802,279,893,484,180,83,650,347,133,896,285,323,608,101,378,26,777,737,611,633,580,579,844,175,68,982,583,845,959,734,875,696,12,609,630,948,760,225,909,24,467,381,12,805,414,733,53,24,119,813,263,795,389,592,814,445,151,472,629,878,150,26,819,141,380,865,862,295,538,861,988,680,558,491,751,377,865,298,376,949,122,968,136,514,407,915,244,173,661,327,780,433,104,401,594,771,914,554,41,810,556,575,302,814,595,60,538,329,828,78,657,500,771,29,734,282,358,110,606,518,227,159,465,355,189,922,397,736,342,457,878,976,303,859,576,692,606,55,84,443,941,613,635,555,960,670,37,842,86,173,858,535,942,454,67,155,545,462,436,38,532,818,603,175,853,607,156,840,715,795,512,454,886,693,918,163,573,105,942,570,173,765,997,782,990,179,54,92,507,64,86,187,184,868,827,787,348,769,947,928,966,794,316,780,957,218,870,390,86,290,11,682,69,439,451,480,338,963,570,556,168,366,214,215,781,508,712,889,275,43,284,867,145,81,306,319,210,23,343,852,808,723,544,901,911,651,564,777,969,905,706,709,537,392,707,255,695,34,158,740,297,940,765,403,198,399,17,618,920,116,893,903,667,731,90,998,958,61,825,235,74,208,915,674,613,471,37,994,393,870,303,701,161,877,543,685,391,212,94,768,225,302,672,770,430,256,270,783,631,378,51,352,519,420,619,103,203,564,323,857,859,522,381,631,296,514,791,583,811,263,911,933,722,373,100,610,392,678,135,775,854,492,409,205,453,888,571,573,888,426,81,885,543,999,424,502,886,442,208,575,209,26,265,272,277,228,992,593,900,653,329,466,428,792,376,779,751,528,448,541,374,16,249,35,107,137,714,609,733,47,628,91,705,805,143,636,700,89,788,25,559,594,828,684,455,554,908,456,235,546,394,799,239,870,417,772,547,918,298,361,760,20,218,256,888,746,771,645,67,198,74,895,21,446,598,214,586,241,951,461,863,649,48,615,223,279,655,861,142,392,635,328,771,45,489,398,727,961,84,70,426,710,808,861,652,495,545,799,961,434,986,697,999,173,414,755,241,601,763,494,204,505,975,698,29,168,770,494,333,148,297,894,97,637,119,753,914,894,517,797,857,658,980,384,226,404,494,779,56,592,20,984,950,699,863,746,316,198,942,851,13,330,46,104,283,464,796,96,877,288,73,383,549,863,642,921,995,759,326,655,652,638,36,143,352,945,17,747,364,757,962,369,203,674,562,100,627,838,864,239,359,369,973,661,714,224,987,485,813,18,926,516,103,233,180,271,852,293,743,894,790,682,214,969,353,667,588,296,167,552,264,866,818,674,484,316,596,321,27,700,503,239,150,592,832,856,216,738,498,991,600,297,951,17,193,876,270,743,907,800,942,700,96,785,664,373,4,185,582,273,8,110,142,757,27,558,179,229,59,248,42,608,373,339,437,62,423,578,847,289,682,20,564,661,587,712,203,174,709,675,459,172,945,103,735,969,958,283,526,317,952,118,846,133,75,351,67,759,9,653,750,77,181,3,906,301,498,148,194,209,297,681,997,195,822,555,931,157,781,930,976,993,807,599,563,607,890,396,433,275,485,392,487,551,247,775,796,440,433,218,131,520,544,853,279,471,86,723,681,469,259,501,928,242,824,257,439,133,142,352,86,400,772,738,322,482,518,556,583,91,975,745,157,918,857,612,690,306,88,211,304,493,713,115,291,346,398,318,325,138,536,727,932,957,937,155,569,892,115,689,857,731,424,917,0,115,873,440,331,670,309,341,927,34,190,302,710,260,466,440,864,478,829,805,202,135,998,452,233,6,901,231,97,353,964,734,362,1000,19,429,439,224,989,14,588,248,997,273,812,852,8,342,647,585,463,252,993,308,558,674,105,378,184,377,324,154,774,554,386,781,509,614,172,969,524,164,619,368,149,341,223,778,291,691,75,884,837,547,207,267,117,353,593,945,230,435,39,479,316,641,442,528,262,239,97,720,251,327,93,515,313,555,402,395,371,340,762,385,724,579,915,454,189,916,739,319,560,488,538,61,399,342,926,793,80,999,98,125,572,205", +"948,77,673,719,474,147,833,462,363,337,74,378,29,181,608,186,843,80,890,862,931,909,153,188,35,665,749,789,146,431,87,820,314,926,112,553,481,310,981,612,496,814,346,121,175,40,826,721,655,850,624,961,980,42,704,446,757,150,851,837,443,848,870,214,190,666,538,872,550,156,980,712,862,299,439,404,166,524,250,729,832,961,607,736,440,713,560,504,392,876,308,211,846,411,378,131,864,428,321,73,808,70,46,339,930,661,996,444,373,733,886,907,646,863,386,239,7,471,677,788,353,494,197,884,164,856,654,299,176,137,512,725,22,785,452,14,211,51,102,401,36,778,753,942,837,37,580,119,50,403,178,166,909,788,801,135,732,194,534,444,52,375,507,824,353,687,398,483,124,166,441,304,56,634,886,746,606,84,744,451,665,116,780,139,969,49,594,961,557,527,548,719,42,499,261,202,905,113,591,931,308,776,530,562,647,379,108,363,105,644,313,86,672,310,208,460,925,148,659,710,578,944,348,120,674,223,21,395,265,503,378,369,146,69,768,516,883,261,800,540,415,476,461,71,548,655,270,501,4,558,430,407,470,634,755,701,884,616,518,573,694,808,305,947,85,206,326,71,470,252,325,774,397,791,606,925,502,418,28,726,479,815,560,935,804,575,182,331,25,939,525,864,735,873,963,203,987,165,554,807,543,435,117,3,304,951,685,806,165,581,626,764,578,330,762,45,389,191,138,6,718,816,538,409,23,932,180,51,971,569,940,490,534,984,543,923,443,785,549,426,926,955,146,11,98,505,728,807,18,392,601,889,396,431,153,527,490,781,51,260,391,645,495,699,972,366,692,777,992,84,551,168,964,403,868,59,545,825,957,594,357,601,326,44,103,330,254,139,584,75,359,589,896,736,344,264,163,874,349,934,168,569,443,66,162,858,842,943,198,329,590,886,469,585,183,104,825,378,514,315,671,503,474,614,622,248,906,667,377,131,609,920,180,399,941,112,106,473,688,33,531,735,483,838,984,351,150,456,729,765,244,202,11,243,259,328,837,335,1000,680,784,36,567,68,906,301,678,690,518,856,833,602,70,37,117,89,127,183,442,920,317,1,285,613,323,389,181,17,88,314,327,708,633,523,234,448,925,529,622,965,447,63,133,648,138,122,108,95,116,672,828,547,459,848,6,758,899,243,592,209,774,127,69,456,254,648,354,11,871,810,724,149,690,77,845,291,461,586,926,829,694,616,619,213,825,611,151,111,23,832,354,994,478,15,65,246,873,787,676,173,145,777,146,244,289,733,322,490,274,292,816,803,949,910,423,497,364,470,299,766,603,491,997,51,393,885,688,164,386,762,727,231,168,711,554,365,589,395,590,934,715,148,884,852,45,793,124,899,349,217,277,622,412,736,724,277,49,429,927,199,645,120,843,197,499,998,344,762,494,29,678,959,753,823,93,329,194,848,873,82,78,663,984,535,881,233,188,546,457,119,290,584,901,625,26,542,464,407,696,816,995,906,920,679,687,534,634,460,982,902,858,443,96,465,418,860,642,195,700,924,616,172,949,268,194,325,776,474,822,570,875,225,434,116,135,740,282,159,669,756,882,424,376,809,918,892,217,267,753,438,509,991,640,853,528,833,880,214,571,515,682,42,727,530,74,941,31,178,456,264,755,567,409,527,723,454,350,872,253,833,823,871,666,652,251,946,81,88,901,642,108,564,91,739,380,789,340,749,616,939,232,513,939,322,549,93,754,920,902,607,743,942,51,236,376,352,500,695,650,986,858,522,61,642,437,970,252,821,932,849,122,456,328,357,210,165,713,123,27,233,744,158,30,220,954,829,494,995,251,984,956,25,573,609,679,322,914,792,749,65,365,18,643,997,717,413,227,387,328,268,735,714,126,471,164,428,531,575,209,76,129,852,191,443,98,991,26,289,45,87,711,100,610,256,824,797,633,965,738,588,79,104,890,812,115,0,598,776,977,578,357,704,890,150,738,950,607,44,412,942,775,797,484,405,83,823,449,422,857,624,180,240,264,532,530,421,590,727,943,432,38,290,713,468,185,308,640,976,123,227,837,674,428,216,547,557,77,258,915,527,667,266,925,346,417,873,228,973,922,828,944,330,552,543,165,130,752,857,139,574,430,768,464,245,846,124,184,972,610,245,426,606,104,539,262,334,411,642,929,519,858,256,550,463,425,188,453,999,98,134,969,172,119,985,924,435,144,12,592,189,701,865,218,304,921,151,854,784,814,580,386,522,642,184,138,879,382,11,852,498", +"449,781,802,128,172,221,977,625,463,711,875,531,921,589,937,946,794,186,761,405,734,170,616,482,628,734,678,969,687,249,155,594,596,370,546,777,685,461,722,307,934,521,884,947,628,402,840,630,513,905,547,48,972,94,351,665,573,112,719,974,790,11,528,303,753,523,432,591,745,814,90,917,135,633,281,4,142,524,933,378,699,874,146,473,498,695,757,237,970,271,9,175,694,824,782,197,170,90,426,877,13,102,447,130,661,145,938,955,248,45,28,900,557,527,492,837,615,838,531,155,658,739,993,37,650,95,502,641,954,908,468,639,622,476,546,140,389,793,999,863,881,842,660,851,10,638,58,443,54,215,620,626,114,899,888,164,196,856,635,233,919,808,376,837,483,50,604,505,286,523,822,482,84,42,205,764,663,406,439,658,263,366,858,887,589,152,780,25,64,852,769,224,55,993,855,972,564,927,15,190,591,737,757,768,254,150,185,108,149,366,384,583,834,131,914,795,24,312,360,716,122,569,271,113,552,525,882,445,378,672,135,985,336,17,811,887,419,18,822,257,883,256,138,112,380,465,812,980,388,84,307,836,521,810,980,605,837,791,428,959,863,527,401,541,214,344,106,153,341,933,702,844,798,175,992,290,802,363,722,601,78,607,862,160,896,325,215,618,476,331,887,800,134,176,478,397,738,170,63,937,586,772,180,317,637,554,580,151,720,926,147,616,940,697,435,654,955,259,140,458,917,837,68,618,723,852,439,720,550,353,176,383,145,753,882,633,993,874,484,534,860,72,646,268,487,869,389,372,11,110,319,65,544,49,140,137,535,182,284,658,853,952,725,641,417,611,876,973,884,801,325,924,777,185,24,841,591,745,87,302,660,298,188,211,789,634,989,226,523,301,132,625,946,240,522,37,942,610,464,168,684,655,906,51,191,811,244,349,200,151,177,758,472,205,268,943,992,798,118,633,56,963,218,308,364,133,432,162,311,213,231,324,690,696,653,234,708,353,43,199,801,442,172,244,406,213,98,384,953,786,557,635,864,117,674,806,849,444,176,851,586,385,172,12,999,487,527,749,509,422,848,684,344,189,116,598,678,901,802,218,68,201,963,805,539,443,959,869,440,937,173,520,296,371,677,555,692,3,897,419,231,235,307,840,582,968,624,312,568,844,517,611,448,93,270,618,125,441,228,82,563,350,688,228,546,184,178,931,706,419,358,200,766,245,236,406,794,101,311,777,373,729,675,432,934,826,912,964,45,916,237,127,977,738,771,126,283,829,803,574,834,770,993,866,71,490,309,621,61,367,339,289,642,463,164,432,545,715,618,521,732,4,513,161,35,811,589,67,486,389,162,902,354,860,291,614,417,211,977,599,901,892,377,889,145,363,316,132,249,584,537,261,201,602,923,157,617,16,497,4,710,832,160,411,78,375,959,542,825,710,436,928,625,642,576,863,996,302,267,504,926,179,256,891,141,557,751,180,259,234,870,668,126,444,623,426,283,990,207,178,925,276,11,806,594,365,984,714,957,466,855,726,400,169,647,884,367,434,603,423,570,676,397,594,587,877,989,991,817,51,227,450,998,81,246,38,836,609,415,346,954,705,652,226,910,440,832,46,438,537,900,185,701,398,831,529,513,898,824,502,193,929,879,10,338,175,75,549,231,125,966,788,703,828,82,632,171,266,219,927,673,728,179,782,599,278,710,670,113,985,732,50,7,173,862,55,192,134,442,629,341,515,978,858,663,774,601,258,33,850,582,375,402,168,725,365,719,507,997,750,202,843,843,901,587,583,466,48,236,142,50,370,192,341,90,55,464,955,258,529,740,827,84,258,816,948,958,556,849,20,228,747,517,316,680,489,546,510,487,113,752,231,79,988,584,600,870,9,493,109,141,622,724,959,460,245,365,214,72,910,215,995,287,90,865,926,665,515,806,153,124,97,761,477,145,25,769,152,510,156,307,361,554,790,873,598,0,873,468,434,174,682,564,311,946,374,848,350,486,558,449,669,431,952,171,121,471,256,766,719,289,508,534,196,89,333,141,910,635,731,900,684,425,36,520,387,927,540,270,973,545,379,506,627,176,27,416,294,105,471,696,736,472,41,460,845,24,594,409,806,806,778,321,926,331,344,618,535,115,104,956,540,930,470,842,199,287,358,660,839,615,841,641,761,460,37,720,580,687,568,527,360,333,840,906,274,927,430,965,258,933,997,417,579,265,954,698,941,329,140,321,366,733,814,317,445,607,783,244,675,647,76,331,241,24,992,394,592,191,773", +"540,325,137,992,634,373,39,216,671,157,788,869,30,671,121,114,940,560,747,924,609,786,132,304,76,509,195,944,2,405,710,429,936,177,495,872,293,274,357,634,979,297,361,211,772,955,815,955,659,597,966,754,824,91,753,583,266,833,124,672,623,81,710,943,103,691,21,854,632,131,434,586,822,265,14,60,730,974,58,80,688,900,609,26,342,52,883,687,769,762,567,254,459,69,919,148,722,518,850,949,277,336,40,517,485,840,147,23,581,405,328,192,293,941,914,381,456,634,594,55,493,905,203,470,201,352,832,922,728,652,588,605,360,787,594,858,962,602,206,106,982,909,388,274,867,412,95,387,675,23,463,326,694,763,919,808,857,343,126,611,417,736,259,182,242,543,474,730,66,892,438,74,213,49,772,274,993,511,83,572,742,133,242,736,860,571,402,330,849,790,542,241,224,111,802,59,67,870,535,818,875,712,110,445,407,482,986,845,298,874,565,405,367,347,943,769,370,808,22,136,481,589,963,829,345,289,174,236,703,7,562,512,586,897,8,680,761,970,307,306,653,849,786,732,826,775,45,26,249,576,25,782,720,548,141,789,624,273,765,416,466,557,867,607,512,506,942,832,142,979,794,649,709,182,903,772,127,539,307,531,744,29,998,694,809,461,664,203,798,947,484,184,914,989,41,500,684,724,930,400,44,724,809,54,112,353,597,591,126,609,105,762,298,387,62,707,193,190,185,564,532,448,774,969,681,286,658,921,574,847,45,360,661,77,285,348,624,356,159,520,55,80,984,686,894,250,324,194,718,432,582,494,371,155,907,384,935,496,256,843,164,37,240,677,434,261,724,442,503,599,488,237,778,813,120,317,160,547,717,600,767,83,330,345,499,287,324,476,442,64,510,123,388,160,6,589,133,497,874,317,356,891,406,227,390,608,556,243,237,464,607,271,61,98,827,64,323,657,242,84,174,968,371,173,171,55,348,216,863,649,180,446,857,559,222,58,665,393,574,703,127,987,263,891,295,232,75,815,794,488,798,824,626,493,874,722,562,823,468,555,877,753,442,511,618,299,342,205,981,735,121,470,752,62,213,798,727,531,435,100,422,209,865,425,468,716,998,13,900,59,368,249,376,703,225,524,925,387,907,587,263,140,885,18,400,770,328,981,470,940,839,973,874,990,631,237,950,262,291,139,490,502,59,144,972,371,631,374,340,253,983,526,734,878,120,926,216,90,818,409,518,559,515,285,691,530,988,400,129,378,482,829,945,424,394,516,307,392,796,24,162,53,779,775,109,747,852,795,943,831,652,984,353,131,493,687,799,181,226,309,899,188,140,576,37,283,140,698,875,692,770,657,659,644,481,306,789,213,290,559,115,991,535,998,125,880,947,102,586,296,289,932,58,912,574,630,739,262,637,680,970,908,780,31,794,868,207,127,791,365,539,13,534,959,32,520,579,720,309,264,547,998,953,667,304,591,985,545,548,900,296,522,842,988,622,190,895,3,188,21,333,868,384,755,742,543,699,657,821,743,556,581,611,153,508,895,480,962,515,311,910,948,693,607,92,602,177,901,101,737,282,187,769,201,143,408,268,255,888,251,478,338,427,489,410,581,656,978,987,985,613,499,790,351,256,860,462,488,820,843,637,562,503,401,562,138,593,22,982,402,352,878,978,776,743,931,230,57,201,160,618,858,569,952,99,328,268,621,55,479,5,378,456,95,240,555,115,605,768,845,885,858,239,809,234,228,753,588,60,706,212,963,898,464,760,200,479,22,531,437,637,710,149,759,838,266,465,316,899,254,651,62,886,570,498,493,655,167,357,204,590,725,513,766,758,493,64,323,447,999,223,962,627,569,710,219,359,838,479,593,578,714,68,496,543,709,250,188,177,837,33,768,521,674,474,361,142,382,964,731,76,941,58,812,521,788,236,92,576,208,375,123,25,372,539,807,594,979,861,50,301,504,881,288,440,776,873,0,170,610,60,441,301,419,340,531,9,67,924,426,429,968,524,865,693,110,728,624,900,580,711,894,807,416,895,974,440,20,531,209,841,609,642,308,93,169,927,35,633,659,888,946,902,28,840,559,44,319,6,765,190,134,971,39,12,576,83,266,245,136,59,793,663,854,546,554,970,749,211,118,167,883,288,619,185,998,831,156,232,518,281,466,798,516,715,334,913,257,244,251,814,950,735,692,658,185,861,352,357,721,155,86,989,461,251,875,768,261,111,865,784,321,929,719,138,808,272,984,387,828,368,577,975,575,297,623,805,244,439,209", +"728,321,78,591,987,886,382,200,973,976,86,884,4,295,278,382,210,123,134,29,841,995,361,244,805,499,972,847,308,888,676,678,856,339,377,850,794,36,859,859,962,169,201,28,988,619,623,935,214,779,455,120,660,596,653,391,822,901,238,351,366,676,369,445,794,486,819,501,162,268,921,780,398,778,398,245,845,556,774,166,126,251,437,808,563,28,266,903,546,758,609,169,880,120,767,577,507,603,315,53,1,515,360,84,202,592,661,820,493,556,898,180,424,9,867,173,429,23,239,332,872,967,765,885,357,506,453,733,498,699,808,465,181,698,991,845,287,794,149,648,983,642,955,108,309,247,248,641,337,102,134,344,235,518,124,562,498,503,770,593,318,615,963,928,46,216,929,803,318,793,590,540,247,622,468,966,140,307,422,856,403,605,15,145,68,499,195,261,778,297,975,868,847,35,536,450,54,794,837,617,494,706,753,304,963,119,234,643,406,473,987,329,831,841,476,538,903,965,664,426,290,85,934,622,965,502,603,364,709,901,174,186,71,118,132,211,40,252,354,435,957,740,126,332,988,270,628,299,89,338,778,639,793,153,446,89,623,728,129,386,344,572,992,974,783,105,126,586,531,660,632,172,990,430,21,94,282,274,710,713,637,383,935,368,450,166,73,208,272,148,737,650,287,974,861,6,508,560,247,957,37,237,831,564,17,497,592,705,67,250,688,842,750,182,734,593,247,464,790,574,293,870,254,525,599,232,480,35,555,779,67,944,441,726,457,45,71,316,220,189,448,861,542,243,334,770,636,747,320,170,414,659,581,57,232,231,362,870,928,333,862,35,547,873,88,934,413,391,334,976,414,123,743,468,227,29,728,683,239,679,844,503,715,368,313,803,6,199,162,140,220,304,172,70,944,289,796,227,288,132,238,423,597,277,213,5,482,740,821,197,272,704,396,655,53,956,158,539,289,427,64,724,937,251,788,485,854,323,3,58,916,933,988,887,439,609,995,811,827,406,254,662,353,205,404,586,598,638,654,121,876,487,258,219,929,713,68,665,393,796,654,660,514,230,481,177,171,984,519,439,443,859,999,990,298,509,62,218,51,395,161,899,831,352,848,283,534,359,882,37,227,118,867,143,609,148,214,189,420,265,47,463,23,492,580,663,281,585,450,203,953,718,456,182,165,184,205,686,380,392,855,558,85,159,255,557,459,179,872,649,973,621,590,940,335,822,698,307,645,109,207,589,585,459,487,461,906,897,55,423,693,53,2,592,679,81,640,700,664,55,961,480,102,440,551,734,687,95,206,465,784,114,4,559,64,738,798,601,664,116,669,189,592,408,344,575,886,683,506,90,520,375,186,986,931,645,177,906,637,230,102,217,271,468,235,66,149,95,23,987,843,72,841,310,539,445,466,80,936,72,28,980,139,168,941,641,868,354,808,876,138,985,463,127,231,291,111,686,749,786,184,104,617,713,992,504,976,331,536,760,501,699,77,979,442,275,955,912,848,303,444,601,180,792,552,936,90,106,7,838,93,217,217,679,764,15,827,469,28,329,660,733,273,721,713,591,424,826,116,167,628,327,973,922,445,779,198,457,434,849,598,167,372,575,828,925,518,859,717,992,902,218,534,653,384,334,357,360,410,857,412,864,560,932,757,843,594,716,352,84,709,143,302,299,569,775,279,64,694,654,263,394,616,382,156,69,734,758,159,49,902,882,104,189,555,580,95,678,119,509,881,273,700,687,67,444,288,793,369,957,660,436,96,281,840,144,223,825,171,969,380,144,841,887,41,292,109,203,97,88,152,600,275,254,317,853,430,622,950,979,674,949,997,720,579,820,710,70,236,39,210,139,360,178,75,157,141,623,751,391,308,704,832,934,315,926,432,474,943,889,737,68,841,298,361,719,830,470,944,73,961,796,129,793,410,768,776,468,910,466,581,102,274,7,31,25,166,462,907,959,131,694,46,662,331,977,468,170,0,832,431,219,125,268,97,129,783,741,978,386,510,804,952,59,332,537,130,762,494,927,28,311,83,563,273,177,214,857,903,170,990,340,500,898,323,123,561,164,893,768,996,816,139,965,424,72,966,584,56,341,801,172,342,395,176,239,520,686,411,480,28,670,121,659,187,207,53,44,659,460,23,532,432,771,861,709,874,628,731,84,740,189,559,516,782,682,386,419,379,479,802,597,532,616,337,236,725,118,786,506,451,268,613,282,323,155,986,36,94,847,120,784,676,970,472,428,569,804,430,195,963,586,730,594,120,463,58,343,455,168", +"801,501,680,861,30,830,466,968,836,138,753,873,724,600,785,657,952,732,810,312,927,892,421,317,797,963,201,261,209,284,644,97,427,752,661,314,253,509,668,619,880,451,476,993,790,107,183,571,721,67,604,920,920,944,966,657,490,752,787,509,120,527,856,868,11,530,713,421,587,775,187,626,770,601,846,93,931,804,390,320,845,842,393,940,603,866,724,1,339,760,901,859,275,951,990,174,754,528,413,926,314,15,185,963,741,59,382,386,115,679,701,78,752,997,671,612,725,634,818,928,822,870,793,44,378,152,158,714,338,714,835,157,380,269,880,354,298,909,560,258,83,100,498,625,35,960,529,567,371,800,364,342,125,3,159,560,823,93,991,367,124,495,972,28,704,663,288,507,253,265,251,955,724,206,204,154,213,512,234,181,96,221,119,966,29,636,573,870,644,869,938,452,731,254,820,419,323,536,255,637,335,919,682,987,504,65,317,50,918,236,547,185,812,909,627,340,845,351,541,689,719,778,227,479,859,209,198,156,443,506,412,667,261,57,551,881,841,989,743,984,599,433,98,416,563,306,559,734,720,835,865,296,6,223,667,157,682,407,814,903,766,256,213,75,245,248,309,360,717,775,159,394,455,996,738,167,946,354,269,485,613,47,259,51,845,248,995,104,891,712,915,845,10,449,979,820,777,16,465,688,880,802,762,296,599,382,988,728,763,348,618,721,245,126,658,1,360,317,855,864,795,693,13,187,671,15,622,96,784,56,729,835,815,383,536,813,258,104,372,170,636,551,182,978,58,7,961,585,25,106,484,526,507,661,394,152,480,130,132,237,811,869,479,377,584,830,147,651,62,279,679,752,258,439,651,210,873,694,225,417,301,385,172,67,967,654,333,266,491,504,269,443,565,407,310,362,872,508,586,173,271,53,116,290,183,301,496,522,765,3,696,508,597,333,14,204,931,915,956,769,860,579,781,24,736,685,878,615,735,244,974,479,590,302,458,253,778,102,969,79,434,166,762,123,270,464,248,938,516,746,562,772,670,831,892,880,285,328,607,510,856,306,454,6,239,728,850,462,90,494,587,384,401,852,109,903,556,886,695,917,11,620,478,469,158,653,963,569,417,347,504,84,260,555,357,601,166,914,578,663,419,933,308,831,96,355,92,119,943,632,526,236,833,287,917,91,783,178,705,305,524,376,139,63,829,626,233,541,993,892,933,649,268,85,21,95,19,482,407,971,497,904,346,86,147,384,52,263,50,246,766,847,48,490,462,914,364,550,391,311,194,809,321,469,221,106,168,501,534,686,621,852,267,261,17,43,199,17,308,683,357,612,811,690,55,789,608,203,171,594,912,713,785,494,514,789,22,40,925,99,138,215,881,751,165,888,92,940,951,395,198,654,504,632,435,702,453,804,255,585,618,408,484,300,63,222,638,69,561,570,358,728,792,306,732,167,641,62,99,281,57,320,261,472,538,300,10,209,844,140,169,456,224,490,863,801,346,927,269,9,575,838,197,103,895,729,564,144,869,163,805,128,475,843,758,469,575,924,615,117,733,243,711,739,928,790,282,296,472,725,246,684,366,67,986,753,198,84,810,741,495,98,627,693,59,574,16,243,932,435,935,356,456,992,110,203,289,655,504,882,896,453,932,38,900,567,756,858,986,203,24,419,264,950,394,889,745,61,605,460,142,833,155,631,679,872,551,19,958,249,652,198,128,137,16,204,155,571,361,426,229,946,598,892,825,982,885,543,160,671,188,597,355,129,622,75,200,289,771,256,970,66,274,116,308,822,746,648,86,912,735,916,934,387,670,662,596,447,125,251,496,546,556,641,677,34,517,590,683,108,97,884,76,145,154,659,879,768,185,852,137,393,717,703,277,128,636,139,890,473,261,358,101,951,370,229,144,958,448,352,779,50,468,433,191,373,209,65,462,811,960,452,378,899,917,146,660,972,835,897,441,423,936,731,670,578,434,610,832,0,197,942,742,322,437,330,906,327,774,338,890,412,258,60,570,948,203,552,261,615,378,141,84,561,850,337,158,473,129,54,534,781,391,857,299,537,362,748,780,545,239,98,398,297,189,150,717,449,746,678,779,647,784,430,643,198,170,733,756,594,590,104,287,256,506,384,130,569,795,399,137,54,967,995,957,825,100,879,446,496,337,206,837,352,171,943,702,801,707,469,993,293,255,12,943,63,402,694,391,349,153,950,998,576,795,611,51,748,371,315,607,342,680,335,432,203,183,451,343,65,212,906,972,863,817,125,530,949,677,929", +"351,876,825,91,171,290,605,875,330,658,760,211,250,152,358,442,116,948,808,78,87,437,680,438,899,373,976,358,958,490,820,272,896,286,496,264,41,701,582,37,604,892,271,366,237,643,950,884,865,657,2,443,538,512,71,343,961,111,926,248,911,634,953,261,11,251,226,242,931,504,844,204,712,469,474,918,295,30,329,106,540,141,299,625,931,383,488,559,468,486,549,352,760,870,374,971,354,186,665,160,612,938,881,703,599,710,147,83,905,231,19,559,60,273,784,918,763,362,22,250,979,874,926,587,654,44,593,175,122,393,435,934,551,69,614,694,564,623,314,462,15,134,698,792,623,320,347,251,91,953,854,68,271,826,90,28,917,787,397,926,6,998,992,14,311,70,479,189,84,711,128,654,28,934,758,853,483,396,763,717,732,770,727,746,626,671,164,222,296,625,540,140,732,661,221,309,745,314,721,709,943,786,441,728,242,736,576,718,107,990,143,694,932,316,404,407,16,685,458,513,409,176,758,627,842,388,890,536,125,338,421,428,405,726,462,469,464,338,970,721,593,190,878,97,232,614,618,340,537,9,483,806,255,16,211,971,51,268,39,265,429,566,949,225,39,889,696,60,957,215,272,391,12,451,816,266,708,969,145,124,293,757,591,984,562,197,635,643,792,730,980,894,29,973,605,654,548,456,632,436,764,918,556,801,216,351,76,414,719,941,726,76,266,677,245,950,495,778,86,11,443,472,244,978,994,759,800,881,377,823,686,964,763,661,633,855,31,613,854,132,341,802,996,776,633,110,858,150,882,188,631,532,118,936,525,405,524,80,247,213,163,66,97,807,450,180,311,983,588,420,396,584,70,711,562,113,608,473,737,366,975,191,736,21,976,94,749,490,267,476,16,714,798,15,751,130,678,272,902,337,236,531,470,353,734,260,989,994,696,372,77,106,781,75,386,623,350,985,841,450,57,756,544,251,265,745,669,630,175,707,973,28,469,918,78,769,129,808,102,255,723,547,926,888,749,33,580,609,712,385,960,80,135,979,210,288,919,383,552,576,761,826,914,385,745,198,292,408,990,420,162,974,503,398,166,478,648,517,131,878,857,419,379,597,378,117,412,207,500,249,841,425,313,48,856,692,331,471,20,55,614,549,138,29,448,437,24,764,858,201,140,352,237,422,332,871,625,252,9,997,599,310,80,822,800,597,116,529,42,244,50,494,191,904,611,889,510,375,603,443,784,753,134,437,936,420,648,183,294,317,70,617,794,267,510,924,129,625,715,104,727,891,647,610,329,702,453,456,6,922,556,679,64,61,807,10,939,31,23,153,400,434,764,414,455,120,146,483,876,596,937,379,436,554,608,810,557,234,769,294,940,210,773,45,757,329,343,744,829,858,506,62,751,827,850,554,749,797,786,234,324,671,232,928,92,630,94,475,617,844,290,493,348,253,375,571,157,116,235,236,765,781,847,343,997,853,765,727,297,267,948,336,19,454,786,291,186,720,321,878,432,338,745,203,237,429,976,404,969,627,545,563,787,990,905,868,895,945,802,116,945,715,94,280,668,281,491,166,917,482,598,705,137,970,540,768,434,42,635,639,42,995,804,896,924,70,184,771,422,942,142,897,354,443,247,918,981,810,672,917,435,105,890,814,401,848,343,82,161,322,529,271,200,539,29,678,656,675,45,394,886,114,778,178,430,420,229,118,469,721,690,686,824,343,379,734,201,715,734,635,914,462,674,696,54,93,244,165,845,698,283,682,290,749,995,48,522,332,579,384,856,64,318,767,40,189,50,238,110,512,767,481,257,258,658,129,363,822,715,294,852,789,960,661,559,55,257,295,544,583,478,190,970,226,557,856,716,43,337,280,675,652,887,56,24,978,463,699,316,48,32,456,447,743,759,708,566,520,331,726,585,503,131,668,978,909,522,967,243,539,576,89,549,883,137,937,540,46,738,54,134,457,755,939,309,357,174,60,431,197,0,483,403,662,286,263,464,722,7,140,823,58,821,738,790,305,372,949,974,691,169,269,403,860,345,84,639,342,796,925,75,749,181,419,36,658,318,682,309,848,250,554,381,636,532,393,66,468,795,381,463,626,859,921,78,697,66,391,588,836,618,980,228,350,663,429,682,383,447,534,751,634,632,425,23,364,625,38,137,508,180,430,138,352,607,618,455,518,400,911,109,892,3,49,557,11,372,97,374,923,467,191,667,221,981,56,273,396,85,602,934,792,322,26,496,778,480,996,129,52,560,570,506,702,333,234,942,253,606,899", +"2,240,283,261,900,344,22,425,595,146,749,401,425,838,170,611,453,710,998,830,804,480,131,348,104,626,794,806,440,901,535,861,627,593,173,188,163,36,608,11,78,156,37,715,131,608,109,685,827,82,157,205,52,92,687,516,63,462,135,932,598,713,999,29,993,607,975,783,137,611,295,379,406,566,468,893,955,106,97,88,649,356,398,104,597,421,141,541,241,519,136,767,853,591,712,710,107,709,356,137,178,699,437,157,586,216,582,746,893,867,247,716,822,75,356,643,786,298,855,682,152,394,159,643,472,194,726,327,475,757,233,739,55,778,82,407,493,980,556,950,815,51,318,906,666,662,701,375,923,401,280,454,257,346,27,846,826,777,543,227,78,144,324,984,840,891,16,214,120,555,984,187,695,698,263,177,849,495,338,861,77,78,666,581,886,383,661,342,317,742,549,251,461,447,627,673,310,313,565,148,488,395,671,839,146,749,698,633,961,899,872,352,293,185,212,937,47,164,964,639,790,485,269,114,777,804,352,715,491,932,599,877,470,324,29,372,314,32,145,882,671,832,729,754,710,460,820,168,156,635,980,751,583,94,898,68,271,908,202,765,333,351,827,33,857,744,37,825,154,743,395,572,871,102,801,966,4,930,889,116,541,123,465,1,503,647,669,479,524,866,808,385,382,277,908,25,46,386,697,590,669,195,584,98,540,243,780,153,45,358,548,552,954,667,478,956,191,951,775,516,175,259,903,635,153,938,525,852,360,250,406,131,622,918,73,639,920,406,297,372,616,531,271,363,41,602,859,258,325,624,32,493,223,100,52,703,385,767,488,201,49,351,126,500,284,814,644,662,263,238,517,880,938,553,829,212,377,637,25,426,204,67,792,384,487,533,660,740,863,713,322,258,824,890,344,988,462,235,184,462,712,182,615,690,429,5,569,310,951,293,473,429,308,191,557,612,504,479,802,99,361,112,959,240,321,604,834,468,64,837,415,240,836,150,631,37,244,83,184,853,209,908,132,540,174,522,164,288,646,132,629,24,993,190,535,723,653,37,214,663,782,830,136,592,290,750,326,699,634,96,541,860,598,176,502,680,341,520,377,231,229,509,18,678,858,664,268,908,923,569,128,617,72,927,46,590,997,579,482,466,947,347,687,643,745,589,858,259,704,579,958,920,702,294,981,675,329,708,280,395,941,27,455,38,126,113,1,359,150,716,364,513,201,964,863,72,707,308,139,862,437,917,674,165,604,221,950,688,495,220,650,454,279,439,470,635,835,508,347,687,691,489,929,701,716,786,439,231,965,816,702,184,397,699,567,528,381,283,661,89,682,232,279,812,204,179,815,687,243,263,645,680,23,817,403,925,251,915,164,971,388,734,183,347,731,231,62,156,49,980,65,413,317,863,663,459,755,747,35,975,898,720,50,291,520,428,222,896,807,243,741,142,799,936,535,689,792,989,630,444,95,128,227,696,583,152,73,466,752,321,777,491,930,578,792,932,425,367,70,306,536,164,499,991,675,96,397,202,29,288,421,675,302,726,948,382,993,4,480,195,698,626,94,73,237,989,270,138,657,911,466,914,778,293,575,360,122,502,390,764,486,705,617,285,484,794,84,998,227,771,993,743,659,117,86,558,243,548,630,545,335,471,744,631,574,899,338,893,44,272,157,202,652,602,33,724,129,752,39,989,196,202,758,728,947,564,219,829,134,794,706,884,41,320,342,385,55,948,701,510,871,64,263,139,951,365,827,249,242,411,572,160,228,629,59,189,133,335,548,101,826,670,78,960,258,87,901,493,755,70,334,414,57,565,653,168,40,810,809,99,234,390,64,697,159,968,567,461,783,393,442,610,240,165,307,490,792,345,314,315,539,125,240,202,338,413,846,299,907,953,390,65,729,601,238,67,22,101,450,770,514,456,340,896,791,550,188,159,230,563,486,875,198,731,505,479,134,351,103,247,449,730,730,418,341,704,682,441,219,942,483,0,870,796,66,1,503,317,914,116,227,200,386,651,758,181,962,128,613,553,85,710,280,569,525,586,375,533,906,655,793,649,129,767,812,624,648,914,378,662,284,921,688,740,166,778,548,198,702,380,430,292,572,138,232,645,990,307,721,648,358,975,914,912,926,627,616,350,713,198,688,57,498,550,92,774,864,227,603,845,174,569,228,504,538,494,930,971,454,554,618,389,867,149,511,693,789,384,531,499,187,587,399,34,84,861,518,911,903,505,491,138,134,254,987,643,109,644,175,459,342,380,743,49,499,517,714,745,974,38", +"553,152,630,411,638,379,574,519,127,177,549,280,192,929,436,45,566,589,663,91,522,516,285,41,566,801,660,629,61,388,678,648,125,61,667,214,481,381,784,955,969,581,992,513,679,126,15,136,369,107,615,873,659,86,714,829,794,319,974,497,181,538,61,265,507,142,894,32,697,838,971,577,542,961,338,453,986,445,260,233,1,12,895,935,636,162,339,748,109,730,546,299,709,834,818,474,209,897,11,138,658,944,773,180,293,19,816,473,535,152,927,127,985,780,567,71,3,592,448,9,579,960,492,783,712,131,822,806,25,701,308,599,536,362,787,642,396,426,943,445,942,741,124,227,755,752,191,753,269,570,162,652,774,59,328,666,625,221,108,27,849,484,845,35,425,370,437,175,977,788,908,911,575,918,62,595,448,924,394,828,694,292,375,661,357,839,428,290,662,815,435,607,874,200,67,685,141,676,139,640,772,747,289,305,926,734,497,179,348,626,590,366,502,993,712,266,141,428,418,220,291,779,827,32,452,103,598,846,91,395,834,268,73,231,504,444,17,274,233,250,534,721,141,761,946,337,517,838,426,182,943,230,300,413,925,60,347,108,107,715,581,599,784,503,972,263,518,974,393,987,320,371,614,734,608,186,343,785,50,861,968,368,865,282,508,872,335,179,199,559,512,219,206,982,735,54,909,720,819,768,220,958,750,201,428,461,330,691,55,647,289,432,345,686,433,623,221,558,753,935,574,367,477,309,844,611,760,154,146,385,464,236,829,601,452,552,862,387,448,370,235,34,112,954,501,890,518,464,622,155,667,484,484,587,612,96,488,456,666,864,351,988,888,430,13,942,963,492,104,630,984,873,559,461,353,881,831,7,380,47,211,952,352,114,80,128,94,37,53,159,541,860,819,302,606,175,571,533,382,310,614,259,861,236,164,384,465,351,946,809,337,843,43,915,302,928,421,800,907,356,810,33,64,746,542,565,575,530,338,574,784,771,354,239,611,967,136,515,309,212,836,554,373,841,918,96,706,45,806,162,906,875,346,723,47,445,745,662,731,701,359,363,483,980,926,924,965,463,553,932,149,465,277,20,992,7,515,1000,297,122,913,717,229,228,767,538,790,852,993,202,149,162,587,935,863,243,99,551,675,470,400,236,712,595,279,883,906,272,275,195,428,288,742,905,876,94,89,356,492,164,776,718,500,48,149,590,286,126,606,739,398,342,298,271,371,578,480,803,403,189,265,902,726,55,381,525,287,518,668,840,413,877,482,795,729,347,542,566,107,981,352,495,193,115,204,407,298,377,96,426,8,971,842,511,321,37,958,210,627,692,511,280,97,127,91,487,231,865,436,772,495,676,266,427,167,482,357,444,205,29,997,666,854,997,785,813,24,527,694,373,956,398,220,127,526,29,845,27,377,961,790,827,870,648,418,344,904,820,626,602,470,69,970,402,692,74,211,705,633,88,170,464,465,493,974,218,474,389,795,190,935,426,604,796,269,805,469,511,255,318,595,586,391,464,221,177,811,43,449,345,894,717,683,232,269,55,465,790,30,273,271,785,636,184,59,82,986,876,809,18,129,339,376,458,729,532,976,124,801,838,601,86,701,814,58,541,379,461,633,250,497,614,764,862,400,303,795,174,268,791,190,40,185,797,975,41,596,737,664,199,950,432,371,872,285,969,984,791,752,907,826,697,82,368,674,493,801,313,486,28,247,495,544,447,622,105,580,347,577,236,882,113,933,35,179,686,61,225,37,565,100,397,418,251,478,410,493,144,88,17,136,956,917,186,889,840,764,382,935,49,591,545,305,901,697,599,606,37,139,90,318,127,223,116,810,804,850,330,194,810,845,160,404,61,834,684,941,605,841,190,486,162,651,176,714,17,361,211,752,374,237,527,561,977,113,956,331,379,553,127,720,588,710,69,365,797,463,325,558,696,136,45,400,696,690,95,29,880,503,295,323,875,564,920,927,890,564,301,125,742,403,870,0,606,151,800,313,735,47,22,594,985,133,157,419,829,518,949,270,781,740,343,477,260,700,473,179,800,361,719,731,808,109,372,691,110,318,682,959,867,370,936,807,325,241,633,971,406,993,727,627,875,78,281,624,835,858,746,527,353,416,229,719,829,112,352,498,448,630,683,220,992,769,798,463,398,776,348,687,579,828,835,513,147,771,923,980,592,778,23,337,512,794,562,205,296,312,971,242,692,333,543,396,458,304,519,184,446,526,224,697,121,809,424,366,908,82,123,662,168,558,899,871,319,103,302,19,50,324,421", +"75,734,661,717,276,174,750,939,270,817,657,705,926,369,487,519,510,446,254,74,281,516,27,171,646,74,691,666,808,963,43,264,813,55,486,466,6,76,704,6,368,694,942,7,122,628,322,893,282,77,758,366,874,970,17,414,15,849,980,659,919,4,742,705,31,122,239,981,909,929,358,5,529,622,314,46,513,683,161,217,426,220,462,705,755,494,701,552,824,106,330,222,671,131,984,537,606,880,756,698,873,464,454,491,569,539,805,12,183,194,482,8,75,358,397,480,536,229,875,833,966,947,575,500,493,129,117,662,559,44,984,325,354,535,739,791,273,619,870,925,60,735,928,376,166,11,104,932,634,174,745,742,416,126,322,692,28,346,264,636,793,531,459,853,192,768,673,798,605,697,58,883,636,894,428,39,751,145,534,213,770,879,690,107,315,371,446,985,734,96,323,284,471,825,727,622,696,88,90,613,804,540,846,488,759,182,133,205,413,811,206,271,180,893,502,833,758,937,220,814,346,780,333,864,798,104,980,873,710,265,734,657,952,240,615,435,760,279,144,59,679,137,126,805,724,405,662,695,298,380,778,480,558,799,192,347,43,822,278,853,3,536,970,677,320,230,186,538,479,174,796,164,705,191,425,275,590,104,315,318,450,175,7,160,1000,207,908,313,24,807,938,591,892,939,440,694,379,55,345,877,918,572,505,826,533,796,343,448,473,820,455,989,407,258,99,611,282,732,584,568,360,459,204,54,721,318,491,719,828,271,574,337,735,672,988,222,892,436,435,489,737,728,227,899,771,897,845,263,175,575,280,457,367,982,360,981,644,412,764,321,38,523,454,667,126,483,335,343,967,809,200,82,885,41,995,675,643,602,878,84,222,511,217,994,968,156,311,456,233,671,176,849,31,290,407,931,177,483,817,933,279,172,4,371,468,784,109,490,14,602,51,264,7,103,869,282,282,202,990,44,142,755,48,908,820,544,286,574,675,194,135,610,56,266,523,480,549,629,830,466,32,310,253,965,362,568,560,308,811,993,970,834,439,900,425,670,640,948,818,656,166,108,306,608,639,603,711,568,780,520,619,581,861,157,781,775,80,98,708,952,615,462,255,678,964,765,11,370,494,204,72,81,968,190,696,239,28,863,549,573,626,161,467,613,361,532,724,414,30,800,674,515,602,193,874,337,266,5,29,269,526,766,19,253,761,535,674,268,226,16,490,117,42,992,582,93,943,306,844,143,53,61,548,522,878,708,45,289,190,160,729,302,469,579,428,708,556,238,825,702,729,524,937,379,88,675,908,319,241,351,617,341,100,643,19,601,410,208,657,96,411,337,839,307,953,191,160,222,542,902,457,370,580,92,692,444,679,217,414,864,552,604,556,748,608,489,466,671,409,752,248,717,209,69,779,13,459,632,195,89,38,809,166,809,59,642,985,111,635,380,401,34,429,834,176,579,34,567,59,745,856,930,581,876,896,590,709,1000,864,518,851,967,239,564,568,459,456,517,508,343,535,665,361,789,356,124,56,661,295,283,312,600,598,289,316,532,924,923,146,630,339,462,253,705,764,36,670,589,672,251,915,117,641,398,165,604,995,567,333,653,188,705,749,628,420,124,906,310,659,126,332,828,106,368,180,347,987,150,936,953,588,805,52,916,534,884,941,656,301,64,78,290,74,594,887,392,30,796,732,389,671,447,854,137,527,682,225,852,208,339,254,425,699,12,33,991,290,309,418,649,249,341,445,951,818,973,588,413,237,414,374,934,173,947,536,263,553,361,418,377,162,370,712,186,811,958,994,456,894,73,95,194,605,112,157,486,707,11,777,967,559,371,34,434,888,384,454,721,386,230,952,475,499,35,465,921,73,432,677,479,205,568,354,69,895,205,953,18,447,832,721,252,877,86,75,413,881,135,968,952,955,106,56,956,347,319,433,963,37,572,698,359,790,695,725,378,296,913,235,824,469,325,62,63,34,150,311,419,268,322,662,796,606,0,314,71,881,115,721,39,531,730,83,587,154,809,626,973,148,27,618,764,503,534,414,341,818,231,498,703,933,773,566,156,172,960,338,675,482,475,607,48,852,275,928,576,141,948,68,711,893,504,459,296,324,552,949,793,699,254,150,136,2,644,288,345,885,373,467,878,929,902,997,752,247,838,700,297,418,132,155,832,159,470,14,374,514,518,474,902,85,321,116,22,250,468,796,512,849,73,549,947,408,625,967,90,959,855,478,567,545,472,965,413,175,377,186,279,216,618,205,798,183,852,545,472,64,89,184,838", +"595,13,843,702,703,273,443,924,968,204,207,815,488,942,968,755,80,476,253,292,60,863,640,665,922,688,203,96,141,838,583,829,585,90,447,967,166,945,327,663,201,527,918,476,274,431,552,469,13,186,638,146,511,664,826,618,829,329,758,22,42,105,695,568,253,31,301,426,712,997,205,873,344,111,433,94,758,435,35,561,953,850,431,218,953,674,669,21,439,350,242,334,592,863,46,965,361,13,676,568,659,305,304,549,232,364,423,153,257,566,793,98,361,174,470,684,713,892,490,482,323,543,132,279,365,434,496,63,387,554,854,625,978,359,470,669,12,959,83,103,843,721,811,134,969,663,243,870,450,790,803,867,612,522,679,71,842,291,28,715,471,358,749,754,795,797,324,453,628,678,7,452,721,20,523,748,996,384,306,834,186,96,380,267,698,748,875,746,387,41,891,7,848,855,957,845,243,407,241,131,539,702,862,851,799,213,555,989,139,116,840,19,387,15,924,576,244,825,149,894,268,355,704,347,381,523,462,24,406,499,551,374,882,295,160,927,145,837,316,344,101,200,422,829,560,26,44,656,395,602,363,288,96,196,388,447,520,385,77,984,725,351,417,2,239,843,281,185,827,436,20,260,983,644,123,873,836,17,409,288,756,718,497,942,618,777,147,447,443,810,661,44,275,92,592,936,587,212,411,875,574,644,161,564,358,320,194,584,650,812,967,115,349,345,773,176,365,676,173,519,346,341,419,700,456,583,220,322,987,502,964,454,176,198,704,404,444,528,180,813,725,612,79,53,708,924,436,329,953,187,10,318,442,309,707,162,64,687,854,343,197,854,858,117,703,77,817,60,619,761,405,246,690,301,963,69,183,112,991,962,525,589,78,889,888,348,568,641,176,463,398,393,199,766,805,241,361,416,98,223,434,340,661,259,205,21,685,71,175,904,463,525,692,353,439,928,506,635,999,514,950,209,119,202,930,681,618,490,674,144,845,311,976,839,166,865,350,96,401,344,279,633,794,322,520,637,614,938,200,435,747,382,452,617,408,956,752,948,881,306,952,556,120,983,703,736,283,168,383,81,696,380,642,786,345,620,853,164,761,363,221,623,145,108,295,792,841,267,196,266,859,547,157,913,409,330,880,132,635,35,518,72,242,732,562,377,123,365,726,143,523,960,213,224,953,490,123,252,502,650,563,677,868,541,578,74,10,909,737,381,507,150,661,887,791,112,352,739,920,456,526,359,872,142,414,91,940,545,473,350,301,376,828,984,236,377,204,470,625,333,79,32,862,323,430,763,589,742,746,913,275,421,163,168,448,446,140,57,817,802,212,84,860,153,721,351,889,603,671,510,432,494,863,993,109,446,114,650,643,947,586,380,338,381,906,125,573,624,567,836,117,43,909,314,76,392,683,424,383,12,232,68,211,731,679,458,220,899,225,99,350,984,333,597,265,385,991,547,229,125,308,298,567,726,452,109,68,480,256,33,429,442,381,630,109,91,850,718,817,927,467,993,865,414,161,394,193,943,665,102,198,253,992,749,989,746,436,733,537,793,154,264,862,512,293,653,656,425,212,935,369,608,140,288,946,248,792,396,451,548,350,619,912,559,49,40,518,789,188,598,24,291,463,650,79,771,329,592,776,333,636,484,767,88,978,465,679,508,363,226,948,371,99,633,524,729,845,703,580,555,172,298,409,641,389,5,399,547,202,18,518,31,743,21,631,352,260,424,197,554,401,263,582,668,781,606,505,716,302,696,927,11,554,604,368,734,105,161,723,307,546,373,61,484,95,267,419,750,766,518,345,711,983,424,664,807,747,134,83,899,479,157,354,212,545,899,48,604,746,84,298,186,778,381,30,649,139,20,634,77,294,428,795,318,306,80,488,168,985,982,401,163,489,411,891,51,538,776,83,362,937,885,330,833,647,757,426,580,712,923,516,775,285,186,394,361,557,476,487,553,679,496,936,398,190,738,946,340,97,437,286,66,151,314,0,785,53,921,327,202,421,772,994,970,851,177,937,386,363,350,794,769,739,350,661,12,333,369,709,837,556,136,876,604,155,181,46,221,998,992,402,20,181,285,891,82,322,401,905,420,21,390,347,979,616,677,121,975,966,960,187,633,391,36,419,348,732,824,481,829,307,523,245,3,784,858,622,776,739,427,45,985,473,563,698,152,754,374,544,364,784,987,645,561,337,532,821,439,280,548,608,566,879,952,193,445,76,63,284,453,278,423,154,206,491,476,520,195,396,67,134,551,959,854,487,346,659,65,156,199", +"907,707,964,901,265,988,385,447,972,801,400,644,301,140,898,587,216,28,14,105,719,965,342,969,402,836,642,982,687,655,786,845,60,787,117,22,419,605,492,288,352,714,140,362,491,727,861,380,441,941,846,264,894,326,791,727,794,836,734,690,147,840,158,865,764,38,491,415,301,732,257,434,980,457,916,802,194,571,774,648,561,415,120,963,814,119,518,6,855,974,842,177,874,62,382,142,326,673,796,608,588,999,549,409,311,480,341,799,344,41,828,615,325,839,924,3,549,537,150,140,341,272,687,418,910,992,706,68,342,534,791,499,799,798,469,838,686,337,269,879,541,855,545,160,204,164,828,639,288,363,395,964,182,729,388,848,228,887,737,328,633,547,583,57,490,174,339,974,428,96,929,764,529,620,697,505,909,155,334,636,789,821,791,536,198,431,262,669,851,388,120,26,348,289,230,227,953,217,141,470,505,771,164,118,28,937,976,631,542,196,248,887,968,507,757,76,906,399,795,299,902,218,337,896,999,968,112,770,831,895,976,56,826,300,307,206,998,304,759,865,424,768,138,440,383,959,452,678,45,19,706,633,43,40,24,609,23,934,925,252,443,993,126,437,359,304,930,607,15,407,533,896,118,348,407,701,469,383,481,776,934,771,178,470,68,299,265,498,78,826,481,597,38,41,205,674,42,870,663,596,669,568,63,555,48,554,101,169,957,836,722,264,799,387,708,446,129,848,791,554,370,119,66,975,820,820,707,918,558,159,507,715,73,243,837,649,969,551,586,79,857,672,672,371,609,108,205,773,506,734,641,166,763,670,987,113,995,227,306,617,840,203,77,96,483,870,76,144,247,555,830,582,411,28,523,210,275,594,268,422,42,536,737,739,970,991,616,963,747,373,368,462,441,270,189,177,862,2,162,722,192,329,896,789,630,296,301,264,857,147,995,322,819,590,102,924,992,200,898,324,891,665,400,255,649,176,686,891,385,200,231,426,845,654,73,455,725,493,774,50,675,779,20,528,573,191,630,467,380,81,950,978,123,479,782,363,711,604,746,83,970,571,595,454,7,280,209,632,182,778,91,390,664,156,421,837,497,142,327,288,245,289,94,541,599,16,652,803,477,979,494,822,701,156,362,253,155,83,69,932,917,257,417,705,90,62,948,529,482,784,33,852,865,475,96,152,668,801,368,298,58,41,738,446,383,30,604,432,518,743,887,289,331,297,292,466,486,682,519,883,119,656,692,149,191,298,444,400,975,92,707,460,340,899,722,480,964,21,632,499,156,15,908,509,444,166,407,8,674,77,924,618,6,283,373,756,957,419,636,703,984,593,759,554,256,178,361,206,592,150,128,153,75,230,926,783,911,122,634,828,923,186,452,764,733,100,258,683,703,620,991,580,361,356,231,463,60,477,284,880,886,330,843,683,146,455,556,805,408,521,61,246,257,864,240,821,118,798,47,87,630,535,603,727,936,258,163,603,75,607,339,310,984,566,385,826,168,643,940,41,513,281,638,641,912,219,425,554,264,748,148,942,312,158,740,963,450,92,564,36,469,88,915,241,418,206,708,793,266,349,245,553,773,824,706,394,130,792,826,83,368,711,818,990,826,170,997,862,338,812,40,277,352,519,638,211,766,549,597,746,799,473,259,489,787,806,683,632,889,7,929,515,292,111,493,971,736,465,297,652,520,603,64,932,241,409,530,842,604,88,17,246,518,63,91,82,537,28,425,388,680,653,174,925,670,973,664,334,611,40,324,886,532,225,656,250,966,347,808,188,449,409,794,404,482,327,437,821,569,572,262,614,541,120,868,285,866,258,199,631,788,714,551,35,129,504,256,131,173,930,294,443,695,680,72,347,856,476,447,922,616,812,539,813,673,939,540,34,928,682,316,921,898,265,430,376,669,881,854,729,738,767,699,950,309,543,13,925,57,781,628,97,841,939,770,5,786,254,468,905,87,23,537,617,302,950,374,531,129,330,263,1,800,71,785,0,458,823,21,648,341,173,896,394,81,677,337,275,791,836,344,255,908,903,378,234,800,141,102,123,671,546,572,765,486,383,709,575,108,234,519,922,436,177,843,631,615,460,870,646,449,440,668,355,467,455,706,569,677,367,585,101,612,678,265,20,474,17,926,818,769,100,316,176,58,531,253,234,394,521,947,858,451,895,176,353,244,539,818,963,936,278,332,46,807,490,573,866,385,889,589,644,58,34,579,889,125,67,864,400,58,945,994,768,297,277,377,547,421,215,434,549,784,975,939,918,781,675,896,468", +"299,607,443,488,664,561,172,356,718,600,129,923,306,231,623,2,722,524,475,690,263,660,777,106,776,185,301,270,385,618,337,696,133,739,997,9,654,813,428,879,654,307,895,108,134,993,432,13,115,706,966,568,197,515,200,260,240,377,120,504,6,814,552,330,235,250,900,662,204,58,670,979,897,100,267,224,538,74,619,685,75,698,86,247,967,684,545,673,996,790,964,758,985,676,850,283,153,537,958,697,554,314,862,94,266,93,850,702,219,829,910,830,849,574,36,449,499,892,681,314,196,849,648,716,330,689,29,119,432,962,496,951,523,848,911,610,440,559,402,861,539,685,713,534,292,208,591,942,401,451,565,620,595,89,306,351,280,590,54,930,280,128,855,689,407,955,484,92,146,939,97,244,280,60,152,99,46,767,71,322,252,558,304,443,445,176,89,432,468,216,571,458,253,693,72,443,992,292,948,427,765,315,922,580,602,91,886,20,191,189,653,373,25,129,780,477,22,156,875,366,332,166,525,550,344,822,300,797,183,868,277,725,131,677,382,176,899,670,326,510,580,18,264,160,600,56,392,499,129,919,854,439,178,94,464,713,917,426,112,700,793,786,171,777,447,305,83,982,512,105,66,228,924,701,962,656,710,640,784,682,963,683,332,747,880,713,869,148,956,658,301,917,803,798,379,39,232,577,57,349,984,945,354,546,207,428,86,716,639,987,776,493,342,973,958,299,380,29,694,444,777,384,577,480,384,51,508,787,561,858,879,225,482,937,733,215,997,818,870,486,564,148,924,102,297,596,707,166,626,379,40,947,982,420,483,852,747,768,331,756,949,318,772,764,925,259,470,904,499,455,159,423,486,472,245,807,426,83,666,594,114,374,442,848,499,242,275,28,990,580,513,927,106,710,289,480,102,369,550,801,450,270,772,750,401,453,197,49,263,922,22,408,63,652,952,823,698,845,987,36,2,619,263,331,856,647,245,137,423,199,357,319,757,270,12,912,262,338,294,520,428,944,781,519,58,244,194,884,558,610,670,932,26,155,423,329,430,561,66,395,745,628,706,924,534,381,478,504,729,713,42,885,706,554,324,540,905,790,682,920,200,697,728,157,230,586,589,485,229,347,66,253,280,741,173,179,137,627,815,310,990,455,87,123,119,879,478,31,841,221,805,456,533,210,793,206,512,174,665,555,414,723,629,632,6,920,529,595,231,805,324,903,609,400,111,235,715,665,989,666,976,15,420,707,815,221,844,188,489,301,45,55,973,14,449,830,305,948,747,912,849,644,450,155,3,554,721,831,770,688,262,112,443,547,462,881,745,425,519,478,674,395,403,835,341,400,620,582,231,324,392,865,482,218,777,587,381,165,737,747,36,692,353,164,762,851,326,988,853,970,77,178,703,177,563,111,749,879,754,601,914,733,235,743,761,52,530,199,61,920,116,386,324,588,160,532,332,664,326,878,189,71,220,129,296,654,972,347,581,701,870,278,29,879,801,920,646,786,647,114,46,53,707,927,386,367,829,584,819,794,783,861,405,638,546,741,426,999,272,517,31,142,616,814,716,858,951,24,336,759,172,961,909,835,867,139,627,254,562,785,308,297,840,549,754,285,256,168,587,857,68,203,984,907,885,194,836,785,45,462,504,94,541,588,209,568,444,179,148,881,699,597,955,77,465,778,498,622,562,634,503,66,339,434,977,591,394,103,206,789,363,984,836,597,309,494,876,570,189,847,79,316,685,729,531,305,391,984,362,663,116,938,935,391,259,516,130,614,207,523,4,329,576,310,876,895,710,473,307,238,73,64,207,954,237,522,445,86,609,440,543,535,829,59,802,528,799,300,566,282,926,142,886,732,752,58,472,869,598,663,555,852,673,790,644,948,527,974,473,442,198,908,893,62,777,117,215,432,267,952,975,780,588,849,617,33,191,778,844,718,182,216,788,462,301,753,614,785,838,583,58,905,21,227,710,607,848,9,783,906,464,503,313,881,53,458,0,245,418,201,633,920,919,276,201,124,681,255,395,199,453,895,58,454,937,163,550,107,142,777,110,979,817,835,838,777,849,418,232,77,536,453,366,423,843,106,292,338,28,939,170,806,953,478,801,641,339,554,519,798,42,33,73,173,487,440,695,754,628,789,509,898,911,570,277,433,105,283,231,51,537,324,369,69,970,646,212,177,716,377,851,150,2,146,198,945,671,204,357,742,703,371,73,240,167,510,40,596,96,761,934,353,865,692,215,268,761,648,46,125,357,953,258,551,136,564,699,323,607,967", +"469,375,945,350,944,899,167,988,188,145,268,221,145,550,637,265,378,270,609,887,54,450,479,950,735,803,457,63,290,439,94,837,702,313,841,303,298,924,484,560,604,341,502,742,51,807,713,236,514,61,339,826,771,417,846,315,733,703,869,437,691,82,856,679,199,101,316,385,61,155,232,710,702,444,992,468,70,622,175,597,592,20,470,269,68,601,448,399,32,761,560,356,452,16,946,910,550,902,275,557,492,327,756,580,579,748,296,562,466,698,203,809,430,333,147,527,519,425,737,71,140,553,169,50,594,357,418,367,883,330,76,419,150,995,948,846,273,969,905,159,190,290,733,325,921,712,344,783,184,145,984,75,251,611,515,747,117,810,625,533,563,721,756,775,820,473,244,608,850,604,482,349,652,565,809,74,365,26,491,87,419,893,376,127,602,996,87,798,264,786,187,44,59,598,582,369,540,711,128,330,671,101,910,422,170,324,277,917,276,633,717,382,283,34,94,309,354,274,60,636,813,651,517,373,503,54,19,414,546,892,364,76,651,864,376,421,597,535,208,659,596,684,857,769,606,345,79,359,409,671,624,704,645,367,889,542,720,358,662,603,324,906,510,76,420,79,938,284,787,960,121,320,314,159,116,189,608,247,20,929,155,125,276,364,626,222,395,606,232,488,120,444,13,184,201,684,363,197,271,796,486,414,111,287,249,511,275,871,592,84,667,549,787,560,933,340,394,209,211,586,818,768,409,359,694,774,701,30,576,401,930,180,690,442,9,230,932,19,361,811,44,946,56,393,534,341,671,245,596,238,816,843,189,832,232,750,801,691,36,256,731,654,412,702,52,171,586,720,634,919,705,533,269,773,895,327,855,171,292,880,443,427,583,419,363,357,546,36,8,553,355,472,895,767,881,959,860,299,558,668,877,30,623,107,549,676,542,713,346,512,530,69,768,888,12,695,574,191,841,100,815,393,464,837,831,611,419,176,777,477,252,255,166,714,656,583,836,341,811,394,730,547,73,346,343,762,782,330,744,390,259,410,591,362,901,636,600,495,733,430,573,348,874,676,395,939,723,695,625,456,524,768,975,159,532,780,93,659,263,411,749,507,588,705,307,708,805,268,661,295,285,221,345,270,358,88,445,888,515,93,483,875,51,434,496,801,45,701,526,812,573,839,593,21,552,54,72,968,421,473,213,736,731,594,742,128,8,259,434,490,436,210,364,346,901,937,393,189,189,548,516,395,224,812,479,564,52,420,904,154,837,157,741,897,763,737,770,797,916,517,498,321,929,287,91,21,605,922,917,31,82,305,144,116,903,899,444,564,660,181,267,132,917,891,878,424,655,874,673,584,945,769,573,974,873,559,401,968,306,304,929,68,861,51,137,357,560,502,859,620,418,973,349,685,493,692,424,786,297,936,219,822,950,614,762,630,237,445,200,207,754,2,523,989,586,203,534,298,139,904,703,738,665,109,400,429,729,424,641,663,120,387,300,76,353,296,297,901,183,766,751,423,13,674,396,800,818,6,892,223,428,684,837,529,504,342,360,214,678,347,161,734,49,344,255,139,917,734,542,934,319,580,611,494,37,158,865,745,451,384,496,679,892,221,160,191,681,321,810,400,309,693,46,837,472,705,917,850,751,405,305,362,823,301,51,373,269,892,258,43,291,287,456,131,213,307,973,585,606,356,876,78,350,561,627,411,711,803,617,972,604,432,737,71,444,812,21,304,390,995,165,359,362,822,147,916,492,466,756,777,89,866,400,905,447,69,625,82,640,817,113,820,419,535,764,927,948,646,829,123,305,903,928,242,117,137,159,520,28,105,722,643,647,321,750,14,862,275,41,557,825,313,26,272,108,784,693,525,855,723,479,795,876,108,36,278,156,442,591,185,822,598,827,609,369,180,304,125,206,11,459,17,234,493,586,767,394,14,422,531,702,495,1,257,584,240,682,536,800,605,224,581,285,39,260,44,350,67,741,327,722,317,735,115,921,823,245,0,120,151,365,395,516,926,795,125,694,949,186,825,192,726,609,787,719,928,258,31,657,211,360,870,777,868,606,5,920,625,241,418,955,927,38,618,910,239,733,243,754,82,964,926,484,418,978,459,704,104,789,10,693,728,327,421,452,396,645,813,592,207,897,239,104,102,287,353,849,191,340,136,579,321,450,86,616,522,394,673,458,821,854,70,961,160,542,768,440,450,204,925,820,331,765,329,476,405,326,619,298,205,253,197,84,905,457,289,780,674,116,958,555,587,940,392,757,964,519,729,934,33", +"258,159,868,620,563,397,470,725,214,904,58,642,527,846,833,28,383,951,148,907,54,131,20,497,559,185,923,939,735,282,32,715,921,411,753,24,939,170,982,137,232,344,306,906,812,985,615,244,622,156,954,159,683,223,779,429,391,863,30,491,915,906,163,904,965,272,516,455,797,499,982,516,935,799,943,978,307,330,939,161,271,880,80,286,858,799,92,515,853,728,875,703,268,560,561,316,474,37,327,712,467,114,359,812,363,121,476,687,753,606,72,726,178,698,577,713,884,861,211,11,235,86,183,863,329,460,104,143,842,402,662,402,479,170,453,800,427,350,306,411,880,206,554,925,866,950,85,457,943,832,335,163,298,505,227,57,925,604,486,122,575,12,356,510,273,44,728,408,153,144,744,924,504,384,297,655,874,180,597,811,582,854,675,958,307,125,593,307,351,240,916,136,714,268,54,578,820,326,57,739,894,357,719,733,929,939,776,237,251,278,422,375,170,980,343,289,225,986,984,581,970,711,332,559,274,365,915,595,91,57,834,494,383,315,434,619,791,586,495,339,78,934,542,171,25,455,165,828,582,507,466,707,560,647,406,240,609,26,234,107,885,164,971,358,950,163,63,571,678,883,116,154,173,724,268,571,297,121,504,659,371,686,703,283,192,988,388,139,678,471,605,547,854,587,924,867,816,127,60,873,844,579,57,383,161,789,942,501,391,425,387,894,259,740,458,34,895,436,420,454,693,991,733,26,704,91,150,204,985,718,201,262,687,115,314,905,260,318,457,902,820,810,533,562,869,896,630,833,212,969,192,542,856,343,491,360,757,96,411,204,59,597,153,628,983,232,304,817,811,981,621,60,630,346,347,15,494,823,886,817,2,278,345,460,27,521,18,121,412,489,101,272,970,4,398,785,217,152,23,412,587,969,934,283,332,323,706,917,981,870,698,190,462,657,241,113,683,174,891,817,528,657,724,887,733,285,110,814,989,866,68,834,38,146,378,213,350,185,213,521,165,509,396,338,466,419,449,364,170,841,666,956,979,463,842,192,922,12,190,523,266,846,887,859,947,63,561,372,148,382,881,772,98,652,364,41,793,20,566,953,918,558,815,217,874,339,677,23,24,887,237,907,75,332,558,401,750,559,149,930,808,7,714,909,81,547,373,789,367,976,612,663,913,259,599,897,349,459,738,832,882,890,981,152,960,902,931,312,410,110,868,309,249,351,908,428,660,638,126,805,517,531,111,886,79,514,959,390,171,786,300,940,240,414,968,423,40,42,619,495,327,888,973,934,510,14,34,544,688,974,659,630,660,972,494,186,393,890,57,17,161,782,178,823,624,250,193,57,577,509,824,586,769,407,853,497,402,281,331,177,491,789,214,641,948,919,796,301,830,27,975,53,193,360,90,341,324,216,779,244,313,919,883,306,918,850,348,359,787,401,510,985,235,502,500,179,740,310,317,110,263,497,834,874,860,451,486,386,766,487,870,431,505,10,621,263,282,700,454,629,316,784,782,123,484,737,383,903,369,921,833,298,580,854,184,686,420,304,111,798,154,653,981,578,208,87,664,483,882,889,431,12,915,155,936,68,241,60,731,691,514,516,987,755,229,61,264,291,626,978,813,769,337,934,845,656,184,811,845,320,140,535,11,247,804,574,404,378,502,215,389,958,774,98,619,235,659,932,318,397,517,151,265,447,955,947,742,613,663,279,363,948,124,257,421,100,826,525,985,167,671,196,611,104,975,668,415,941,38,344,693,53,398,92,203,546,125,468,769,678,929,210,713,506,893,357,261,98,509,770,867,448,199,163,488,308,384,900,838,528,453,445,183,675,177,362,699,410,574,371,238,986,531,361,116,738,203,179,344,956,102,352,73,123,958,725,693,378,712,787,451,265,363,191,156,550,203,175,871,750,796,564,237,919,146,778,362,24,910,670,212,188,656,514,300,629,330,562,872,740,532,266,885,671,466,412,486,924,978,774,7,914,47,721,327,21,418,120,0,734,899,430,71,59,948,382,72,644,12,521,508,759,576,850,790,288,116,163,73,792,858,8,753,729,310,164,770,200,346,70,797,937,611,929,95,294,94,704,246,710,841,396,110,563,405,235,502,781,502,952,951,794,849,472,711,105,694,399,970,168,456,962,840,908,307,558,998,62,256,953,238,834,59,430,237,371,478,433,878,331,525,285,310,670,509,506,373,750,296,346,402,379,584,275,711,899,859,937,560,45,283,826,999,691,154,709,615,690,640,294,779,318,860,78,83,868,214,430,740,751", +"40,446,455,526,128,739,539,461,425,365,512,128,132,582,726,969,567,462,709,212,789,771,506,837,724,884,453,758,564,95,148,58,621,502,276,369,808,923,646,570,719,120,137,595,213,651,319,337,204,241,187,945,813,316,263,814,86,919,551,956,874,499,936,686,638,449,793,499,520,13,940,446,80,355,868,734,230,951,267,506,444,293,835,703,49,637,908,610,33,864,397,656,187,474,427,797,243,761,207,44,292,676,242,132,885,471,841,794,275,287,512,583,874,662,412,409,793,698,425,146,718,333,100,239,194,171,882,861,74,598,137,402,376,157,98,27,911,564,981,304,883,463,460,977,215,399,221,771,420,779,523,366,689,16,207,580,202,689,750,837,905,140,43,170,54,808,691,733,476,892,352,874,181,624,557,322,90,921,752,533,422,804,217,245,414,271,750,82,936,444,938,420,513,902,121,956,143,814,245,143,372,512,587,59,364,966,974,812,899,761,161,783,861,810,284,274,67,395,914,495,819,14,907,301,278,319,782,985,52,214,886,470,662,34,198,666,719,836,196,863,482,923,19,930,880,255,673,601,297,89,306,645,545,996,312,342,880,472,283,940,121,665,91,397,317,122,264,628,312,968,850,777,38,546,36,450,640,729,940,977,320,183,963,156,195,276,260,743,946,706,201,338,612,232,470,583,684,61,546,856,901,170,767,844,396,267,217,70,961,768,449,457,89,347,372,351,632,695,881,25,195,117,417,676,195,928,215,186,523,492,877,956,847,753,469,605,816,614,529,226,100,818,851,282,18,251,50,371,119,465,941,627,560,64,652,816,558,990,527,174,823,79,691,497,945,303,26,33,317,655,406,158,500,181,175,723,520,430,271,691,117,322,724,571,605,732,700,904,388,311,647,463,136,620,224,284,725,409,458,977,793,449,634,467,632,149,506,673,678,209,70,287,194,43,990,123,542,10,893,56,893,313,226,110,758,383,762,122,349,431,422,152,672,342,112,249,482,287,610,367,638,124,632,761,805,246,353,884,814,4,181,526,302,638,746,235,929,701,120,875,325,690,96,308,700,491,949,982,279,412,447,934,968,893,794,617,885,805,908,55,283,189,303,470,361,888,323,134,33,124,924,176,808,563,895,311,724,616,710,34,371,570,726,41,975,230,453,981,675,817,904,985,404,276,31,449,613,85,105,674,424,681,682,462,694,67,299,398,525,213,777,241,476,472,759,680,136,855,390,675,374,90,585,980,188,480,727,796,908,355,202,371,488,744,675,570,115,85,898,475,671,990,452,490,321,713,356,976,449,923,674,927,826,753,43,451,871,206,14,71,994,786,467,499,772,245,264,790,948,8,598,568,675,568,2,491,205,244,558,95,785,569,483,601,768,743,906,540,943,112,898,523,87,369,85,941,242,465,77,475,265,795,840,289,994,323,685,31,941,404,289,676,735,219,656,847,514,745,250,654,826,448,179,259,369,6,48,839,626,17,182,32,772,485,613,391,184,773,920,89,806,235,94,490,655,301,801,862,854,93,495,241,813,116,68,822,795,312,641,826,690,401,931,107,721,440,611,940,616,645,807,838,420,899,227,812,92,412,696,88,271,82,963,98,768,283,637,819,469,12,424,545,525,304,786,908,610,135,836,361,322,590,265,960,150,438,742,946,762,581,988,621,805,736,244,514,236,738,362,494,97,129,283,128,994,881,100,61,512,704,862,959,603,298,400,870,566,182,547,100,199,563,575,831,677,912,346,622,553,541,399,27,316,393,948,446,751,553,83,175,710,163,170,119,491,250,652,154,821,567,847,557,487,440,6,330,221,188,106,382,582,111,51,41,74,244,774,383,243,13,655,575,262,702,643,121,365,86,769,638,524,834,439,865,823,830,999,441,10,722,552,989,966,108,723,856,648,37,104,673,922,201,349,347,211,410,196,449,339,969,120,449,902,90,61,351,705,348,330,203,819,934,531,142,440,942,558,426,386,338,140,116,22,39,202,648,201,151,734,0,174,613,92,954,152,965,834,54,912,925,453,357,227,72,865,421,917,251,184,265,128,337,194,767,541,621,711,522,769,67,415,518,417,732,292,793,812,726,379,447,835,348,379,254,656,144,483,342,734,519,45,828,521,50,259,36,719,87,922,572,676,663,178,524,244,567,673,731,252,275,141,325,892,899,413,131,727,214,4,44,830,507,325,774,20,868,500,136,306,297,469,319,160,49,615,237,202,790,200,711,589,387,751,351,904,308,470,925,458,648,512,509,709,484,997,726,187,90,648,760", +"524,415,470,733,263,169,881,17,585,76,281,162,952,279,423,453,642,331,566,802,667,281,491,548,92,788,826,515,629,206,777,981,532,434,943,671,637,52,356,82,151,486,983,810,887,724,281,798,746,674,605,736,184,799,52,727,980,282,974,145,669,165,382,575,483,929,387,291,386,129,407,396,196,584,449,783,742,178,568,653,326,498,627,75,578,382,194,43,164,659,367,450,944,957,946,96,116,109,614,933,763,373,359,671,628,844,985,856,775,715,952,164,714,400,839,719,719,244,439,480,210,674,165,792,675,8,82,915,450,115,637,857,650,959,11,879,724,104,118,419,562,961,980,677,749,700,537,507,897,89,68,720,868,994,940,837,371,769,660,98,442,284,512,346,135,78,883,389,740,643,632,612,763,746,872,906,942,413,906,116,783,285,835,856,322,657,906,234,922,912,285,827,635,334,696,760,148,915,774,77,211,420,965,35,867,893,966,133,168,866,890,659,307,527,350,387,153,986,513,145,553,502,785,61,130,156,809,786,211,824,429,586,569,102,15,415,119,279,413,110,363,258,205,15,660,349,738,343,603,591,367,309,825,416,700,642,383,934,388,454,174,224,672,250,388,639,521,619,356,285,473,241,939,860,317,120,581,439,164,342,480,912,404,562,598,838,23,534,652,692,532,609,451,288,55,876,31,481,760,824,959,451,725,650,289,573,638,870,266,617,678,39,703,984,179,633,792,753,650,314,972,817,741,18,210,426,315,879,516,648,221,376,199,848,14,461,41,449,956,492,63,485,349,559,716,361,813,228,952,299,351,694,548,449,934,243,864,976,397,116,116,527,259,46,848,73,590,199,985,977,183,655,945,150,731,893,487,458,833,989,6,994,898,148,238,608,672,731,80,726,894,124,70,314,585,117,226,209,397,898,863,280,678,237,922,770,402,770,286,708,18,852,3,99,725,748,241,16,704,920,339,649,440,712,628,477,670,721,762,344,766,815,675,65,100,467,112,208,60,709,41,499,450,855,587,474,596,89,386,86,237,416,790,151,120,571,683,367,218,516,29,121,694,715,226,33,436,770,656,630,878,674,376,141,968,376,887,890,593,440,480,435,311,162,645,383,441,877,646,307,263,657,294,5,970,656,230,207,402,826,781,787,499,242,75,893,569,243,194,912,351,59,214,274,340,580,910,716,915,634,896,160,369,41,123,488,442,939,241,696,882,139,501,304,260,926,842,772,300,809,114,629,275,201,149,586,402,946,349,834,350,330,523,781,977,832,546,490,612,650,834,462,436,7,518,218,983,934,390,432,998,877,358,715,354,331,791,92,711,60,650,452,102,241,781,794,650,245,612,780,352,665,934,800,22,639,407,979,786,63,974,991,841,610,670,441,446,665,147,758,91,168,935,19,266,922,33,721,783,297,918,897,194,176,519,545,561,662,610,468,772,792,192,450,720,264,589,460,441,126,513,874,155,12,617,5,473,209,252,714,736,539,511,495,692,648,27,63,21,790,723,670,182,476,718,530,556,564,982,944,124,795,778,889,264,165,420,637,984,900,687,558,341,28,285,784,983,516,92,188,894,513,197,781,29,681,312,145,594,196,935,551,583,979,588,980,33,434,147,345,757,287,893,111,679,419,90,900,486,972,194,623,303,367,67,79,986,996,139,361,971,433,284,379,257,413,400,395,489,846,654,430,722,977,572,793,448,723,252,557,476,566,168,488,494,324,429,38,850,895,680,853,56,965,354,910,389,478,302,545,478,612,14,178,726,186,304,869,227,818,822,23,509,991,276,546,174,200,300,361,40,305,940,605,46,363,253,342,79,437,488,172,151,274,966,805,611,954,230,66,866,614,487,68,501,79,195,220,502,947,717,401,505,312,776,275,484,112,124,912,41,783,319,334,46,883,908,263,750,306,137,639,935,311,166,400,768,816,50,570,414,268,25,498,146,718,249,860,738,226,472,360,655,716,864,775,449,429,510,890,823,227,594,531,421,341,633,365,899,174,0,944,735,309,62,325,963,79,538,939,51,300,619,193,719,16,408,233,411,76,121,407,853,995,24,122,49,481,960,549,797,744,423,603,518,672,715,590,853,520,276,964,303,988,662,717,314,557,913,742,21,725,449,270,227,957,707,908,690,21,917,431,5,875,47,109,399,350,245,202,195,106,7,703,81,595,786,986,899,926,749,658,816,717,407,875,209,856,541,510,303,386,620,582,905,571,415,977,382,812,852,226,810,966,324,250,785,615,138,941,448,504,638,273,52,95,149,648,231,480", +"845,422,458,350,453,137,2,361,437,895,953,500,584,830,743,430,41,872,364,519,869,339,47,776,558,88,233,653,840,749,958,607,212,129,82,229,12,767,367,605,352,623,527,154,894,361,543,67,867,195,530,132,36,421,543,421,469,274,484,110,110,372,505,618,96,871,642,104,470,541,209,849,978,415,860,579,227,842,594,847,811,705,753,825,101,440,580,207,191,846,289,194,520,106,364,526,367,757,541,303,719,429,112,395,118,404,437,96,856,988,833,682,395,695,167,48,659,161,823,682,135,324,950,989,336,214,550,367,79,208,882,787,816,146,14,79,733,742,639,811,709,784,683,564,579,893,496,721,839,455,460,876,529,918,623,414,829,517,656,806,66,269,850,700,505,410,479,808,320,152,981,910,234,225,931,445,394,327,932,752,154,41,188,689,67,66,905,361,623,681,220,498,230,640,779,472,942,815,18,209,19,52,990,627,12,83,635,294,538,706,681,566,463,977,813,387,399,206,972,156,323,72,653,665,448,302,435,809,377,623,4,968,995,426,875,128,463,85,589,41,321,884,545,746,669,221,621,575,922,511,740,766,468,77,381,874,547,26,246,220,840,783,784,580,586,493,705,618,623,715,324,142,461,154,514,919,419,898,155,566,951,821,608,222,829,719,923,67,568,371,105,515,802,14,635,474,86,362,982,996,369,181,499,939,433,921,255,351,333,423,538,584,218,872,786,322,186,228,362,447,609,652,805,93,642,3,678,841,981,957,364,666,358,500,298,166,367,809,465,985,692,194,520,173,527,73,58,113,89,632,579,91,358,538,94,166,357,598,730,266,292,578,85,104,842,91,581,887,346,894,748,945,906,472,520,608,532,932,490,418,159,666,797,743,648,481,938,344,984,4,339,46,472,172,653,429,528,127,604,972,963,912,955,62,75,871,66,381,532,14,462,879,457,198,622,968,458,564,688,990,717,166,232,899,387,505,378,809,462,624,759,708,819,322,177,786,456,88,502,899,773,751,729,433,996,768,226,490,104,380,47,148,699,973,400,505,921,610,657,527,249,854,967,262,309,485,690,927,703,26,933,950,433,355,272,757,241,280,831,878,416,195,818,984,440,217,29,35,981,776,544,103,956,786,302,159,872,178,63,467,560,851,613,76,239,146,637,569,57,747,865,601,343,734,74,673,507,733,734,231,199,810,191,896,663,855,983,6,620,842,894,847,406,168,495,685,116,719,619,985,758,571,770,206,504,5,89,776,717,181,441,441,721,303,315,631,907,552,101,802,816,947,191,355,910,392,772,157,35,802,710,428,996,852,316,981,315,297,848,10,242,944,614,671,391,96,785,356,28,272,47,995,113,359,855,482,961,967,64,693,607,725,745,511,153,809,254,15,683,370,22,32,643,37,209,380,200,888,865,672,107,510,420,382,772,34,977,353,931,920,574,543,401,99,611,96,73,883,762,567,345,744,200,16,132,290,4,451,730,203,249,535,638,327,881,122,981,787,470,91,57,898,209,436,377,614,662,828,25,280,881,290,566,166,718,82,529,202,335,347,103,365,625,756,5,240,467,701,443,451,983,225,953,218,789,546,150,540,114,489,855,65,476,821,829,532,978,33,825,330,713,154,503,643,769,434,608,282,885,735,812,38,349,679,721,927,901,54,864,671,231,663,278,730,813,524,119,514,345,860,37,702,995,657,798,990,510,523,977,940,137,722,458,791,273,918,563,644,738,488,812,932,348,265,691,710,735,978,636,722,119,213,996,623,690,187,754,372,704,671,358,976,556,576,570,169,270,357,182,122,938,228,580,222,773,102,550,117,755,322,541,125,56,868,801,984,708,127,622,681,237,571,971,111,265,731,148,508,221,49,922,955,961,492,742,522,525,254,86,959,421,838,711,505,973,58,776,922,693,178,7,931,710,224,30,328,690,55,985,225,80,745,823,833,530,900,36,194,468,46,781,773,317,751,478,797,669,968,804,412,58,200,985,730,772,173,920,395,430,613,944,0,717,375,70,914,995,949,268,429,168,506,490,74,795,143,550,796,323,704,191,321,393,358,753,513,538,788,536,721,33,710,46,710,221,204,841,344,122,602,166,901,41,186,210,920,804,969,719,877,74,612,829,410,590,324,439,227,285,300,597,25,602,471,590,451,760,435,716,25,43,171,691,677,269,170,797,486,596,648,462,937,832,79,769,201,286,610,899,546,57,517,97,456,470,136,654,90,901,225,73,501,650,43,495,279,819,615,808,387,659,744,489,286,974,535,423,396,846,757", +"281,808,710,364,400,866,760,52,249,886,539,830,433,942,995,379,464,22,932,99,986,360,180,322,162,17,701,840,852,276,409,807,849,499,714,255,403,773,117,103,62,298,553,512,841,772,175,73,896,493,102,373,140,408,941,86,711,852,827,995,499,858,955,868,637,993,942,168,395,834,452,562,386,488,660,735,349,952,120,739,852,197,777,259,288,106,411,726,904,983,459,882,419,727,856,224,658,669,746,618,567,158,615,988,858,975,479,505,355,333,133,854,209,878,511,814,415,607,856,376,384,43,352,158,537,229,90,73,312,561,520,479,140,411,109,178,949,823,665,505,634,37,411,153,971,672,818,261,335,822,722,840,382,23,474,718,45,344,436,238,878,656,736,825,259,163,14,932,230,713,572,423,621,601,337,178,900,907,455,851,283,540,370,778,455,552,469,407,83,493,386,619,872,487,727,125,198,244,352,994,980,190,714,695,371,346,422,220,78,829,453,924,912,140,360,569,508,497,692,245,733,865,643,382,109,203,260,262,362,740,955,151,985,168,165,723,863,925,529,42,156,817,15,799,82,990,193,140,102,406,936,540,301,177,251,676,141,846,400,502,581,697,439,33,165,966,344,532,734,583,8,471,849,829,217,333,400,439,281,579,530,817,818,777,126,883,97,669,219,225,920,175,279,494,554,871,872,515,244,752,892,61,786,27,345,415,286,295,937,220,771,89,169,174,856,423,77,307,740,241,867,169,940,319,544,308,912,755,642,842,250,779,25,901,59,761,966,398,236,213,537,441,633,722,594,125,863,143,244,794,439,398,842,423,174,957,534,535,520,451,634,582,923,122,331,648,512,854,460,912,892,393,124,526,958,749,541,601,522,185,134,890,949,284,735,642,28,931,41,496,680,735,153,824,874,91,907,268,216,979,986,626,919,66,99,353,476,708,982,189,590,81,376,106,461,232,651,949,857,207,866,871,103,173,994,762,782,327,821,422,498,383,759,989,240,810,603,291,737,708,920,771,784,143,896,165,900,917,96,973,753,406,291,28,434,160,39,753,103,396,761,976,508,704,142,290,967,240,396,75,560,284,676,547,686,306,710,209,760,768,937,733,470,282,469,974,142,986,478,539,659,326,220,537,359,183,685,545,632,557,822,233,586,62,429,984,68,338,345,77,507,194,642,762,199,647,970,630,240,881,584,672,237,781,421,350,46,97,335,210,805,453,897,91,371,106,986,305,983,920,60,523,841,188,616,252,825,123,837,985,637,870,24,62,501,926,702,164,313,321,417,431,610,668,268,590,342,187,102,601,47,740,455,624,777,523,735,106,498,863,571,163,991,209,366,830,736,704,97,923,91,804,371,315,479,445,487,569,444,508,131,253,572,436,488,568,578,529,269,455,16,495,831,224,691,433,349,239,337,475,577,116,330,149,311,781,423,253,552,26,341,540,426,310,805,880,100,10,973,740,712,923,886,915,140,28,930,910,825,155,273,834,565,628,516,584,99,676,17,439,824,769,209,521,870,530,432,236,248,94,366,806,937,181,867,860,696,556,67,937,904,484,49,490,64,373,250,386,606,123,792,461,992,239,940,941,224,644,544,615,273,273,493,306,871,812,625,729,579,183,817,519,346,332,800,699,544,280,486,819,642,886,967,227,520,805,759,79,817,370,888,700,699,915,716,219,110,695,954,295,426,157,640,959,268,760,346,134,297,446,519,40,898,238,208,100,571,719,554,462,202,242,101,297,726,417,400,828,867,721,860,259,289,768,45,466,193,315,511,632,776,894,614,145,19,703,275,619,643,227,183,101,625,572,645,290,692,545,801,319,180,515,271,69,26,284,210,46,314,981,4,707,240,881,295,571,788,680,888,609,423,346,856,332,452,211,869,453,367,23,86,492,964,258,184,491,286,773,896,51,905,224,29,694,642,959,194,862,109,595,294,260,935,402,96,894,371,603,179,831,414,611,476,733,829,484,431,524,952,258,821,386,133,83,994,896,919,516,71,92,735,717,0,845,667,15,986,266,549,637,886,243,937,16,305,877,396,827,5,349,535,239,728,696,959,910,388,187,208,636,400,26,689,584,356,733,450,886,935,814,963,991,548,373,461,674,20,71,739,864,60,556,627,736,335,888,283,797,127,182,697,436,828,531,105,583,489,557,583,976,945,655,421,58,557,500,415,944,982,773,554,673,982,419,775,270,553,269,655,982,665,867,310,5,635,928,50,948,935,167,201,491,249,286,991,986,279,724,574,637,363,155,54,670,86,200,198,835,772,242", +"892,798,493,31,748,383,855,857,164,907,603,294,735,927,283,442,252,503,209,392,572,381,197,61,312,710,734,520,698,761,157,4,945,719,596,250,853,893,922,781,508,687,639,889,231,444,606,231,416,115,802,444,231,728,315,791,169,131,482,50,632,816,974,473,933,786,193,128,845,518,475,242,579,717,679,706,756,820,810,432,400,903,307,709,326,46,617,934,881,434,91,935,578,200,757,370,287,859,66,366,115,159,495,871,245,656,30,216,988,273,302,369,789,804,228,164,871,220,919,317,8,269,55,983,214,231,436,162,629,16,968,926,43,119,634,855,561,506,868,356,861,607,808,789,960,564,453,522,613,809,347,885,774,317,171,963,145,290,746,811,279,491,707,681,881,685,770,99,236,989,494,929,52,524,583,135,43,650,639,307,564,450,889,549,860,250,198,191,199,262,841,998,94,438,535,381,482,518,569,20,273,341,500,946,580,732,33,527,767,525,612,178,701,148,275,82,699,682,380,811,260,835,500,973,514,72,738,426,727,479,797,819,763,726,353,939,480,25,496,49,812,192,835,286,853,764,932,868,540,649,866,965,400,47,50,34,811,953,117,125,436,366,223,945,685,32,422,459,671,316,159,370,404,545,941,73,962,421,438,820,18,565,828,99,30,731,298,41,215,747,193,541,82,726,358,996,212,90,918,525,844,100,556,756,892,954,484,718,808,923,988,778,654,930,236,298,806,906,641,482,9,513,696,673,963,63,5,235,705,961,830,920,675,766,883,674,35,622,306,556,84,243,576,315,768,376,837,552,506,438,198,188,346,278,42,584,688,530,208,162,692,748,965,824,974,911,844,12,105,852,594,692,398,519,8,447,85,129,790,62,636,751,129,55,748,670,739,636,699,341,692,207,517,633,348,752,693,463,811,905,358,776,80,246,755,164,488,440,600,227,757,250,198,968,483,442,497,784,233,72,510,857,181,387,221,469,103,946,218,660,736,11,907,30,462,40,649,675,796,235,950,861,192,238,146,721,34,429,972,500,953,713,34,707,196,959,619,376,897,559,321,274,882,560,92,353,645,97,640,923,295,709,806,994,380,720,178,754,877,128,413,353,964,295,13,209,683,568,987,880,876,493,110,491,996,707,400,359,872,894,333,517,794,201,213,676,65,587,183,457,178,604,936,465,674,3,29,414,877,724,565,920,769,318,59,813,744,847,314,765,484,20,643,426,490,797,995,183,962,332,418,493,540,936,230,988,426,181,424,614,981,238,934,697,387,383,387,285,717,304,131,177,280,909,804,858,211,247,260,818,44,599,981,318,937,205,512,871,37,716,605,601,649,273,751,785,811,127,209,599,397,544,376,658,775,124,625,768,325,539,92,829,770,223,586,833,374,834,251,179,861,849,926,740,304,634,750,435,593,918,85,471,353,72,286,562,943,789,565,444,859,303,689,166,989,468,107,861,418,947,274,162,152,130,595,637,538,732,976,200,681,463,628,288,883,592,774,28,269,644,359,394,869,926,447,279,924,332,274,388,978,587,247,584,24,279,820,57,234,246,797,81,212,247,43,359,582,286,531,412,490,813,126,745,300,611,15,150,860,324,457,670,970,528,311,155,875,906,122,500,124,777,528,789,731,691,513,369,363,422,374,367,254,162,240,666,884,262,399,401,186,647,919,292,742,742,986,866,277,11,517,133,540,454,920,91,71,429,149,123,318,878,848,858,854,668,399,587,210,251,521,546,899,211,641,685,126,309,36,772,747,982,656,385,251,598,826,927,839,309,488,585,339,373,796,236,145,779,85,699,443,324,111,811,315,640,830,796,77,995,752,3,929,798,45,413,564,799,146,659,630,910,971,450,74,429,215,318,783,908,831,206,386,522,518,473,673,600,688,153,707,820,834,301,537,94,758,81,532,169,11,616,272,587,113,451,550,632,265,48,901,940,914,807,347,538,492,151,317,605,103,388,600,399,805,405,952,865,59,60,738,651,157,587,970,394,276,926,59,954,309,375,845,0,413,391,34,162,935,136,673,532,819,191,666,319,477,489,692,552,405,377,61,618,198,996,548,778,368,588,302,111,515,262,480,81,35,724,92,584,830,573,618,489,83,871,187,895,949,893,139,86,811,682,285,340,283,314,710,393,209,522,342,138,913,871,130,908,391,728,99,343,953,453,875,395,529,47,949,184,623,655,317,584,487,152,942,231,584,144,179,47,375,631,582,824,342,562,152,787,64,988,115,756,467,653,505,795,606,875,784,329,641,83,852,235,858,389,255,921", +"64,299,378,590,515,219,126,637,304,254,697,348,348,767,517,516,154,668,768,633,347,327,690,746,82,111,331,440,981,876,412,812,631,655,436,558,405,700,985,648,795,809,672,683,384,159,388,534,799,41,91,302,663,345,662,71,388,916,111,265,271,695,99,643,382,646,59,165,388,404,253,816,156,537,261,748,356,796,831,442,675,246,595,459,959,169,454,502,157,732,826,410,123,462,560,83,307,791,663,765,955,554,361,626,512,434,157,935,362,701,263,212,699,580,849,949,513,660,326,37,846,846,900,26,748,510,94,316,306,870,425,474,558,519,282,136,772,731,397,287,104,696,697,434,225,175,850,356,655,779,898,103,183,720,380,866,130,852,648,595,742,425,361,733,197,525,12,485,146,572,117,740,895,616,861,800,993,785,34,353,503,226,683,616,317,506,395,551,621,344,34,975,840,649,992,698,5,815,27,132,798,445,758,500,220,513,810,84,444,249,326,268,951,886,535,551,561,898,52,391,284,266,705,405,589,215,653,861,685,706,111,588,668,242,374,104,62,521,471,485,228,64,514,248,848,255,236,899,296,672,833,136,887,241,689,535,709,681,89,859,768,449,547,856,260,148,35,697,767,49,943,529,701,570,22,107,278,852,562,507,390,235,710,763,375,541,809,165,522,382,755,378,537,945,992,297,629,953,802,734,430,299,234,636,644,733,482,804,887,808,459,859,555,510,166,72,258,831,617,699,497,393,675,561,245,978,992,415,835,10,734,687,324,479,328,573,82,491,852,645,57,925,456,965,588,976,303,934,486,108,6,295,629,398,419,667,650,235,658,429,319,793,417,528,529,135,633,677,932,694,144,909,644,679,53,555,99,81,570,778,365,303,765,692,435,648,60,475,685,986,307,789,936,462,761,40,847,958,804,185,39,546,209,650,175,600,973,492,571,369,791,988,49,101,726,829,223,922,980,781,770,340,6,68,676,737,10,291,203,647,2,434,673,613,601,977,695,621,16,551,288,594,363,662,477,439,224,504,718,822,121,761,172,925,862,908,214,226,88,579,436,980,876,118,206,647,726,970,424,296,953,26,450,181,343,62,463,791,905,969,563,379,414,41,123,275,138,400,365,61,783,431,45,397,404,430,742,487,903,955,608,105,466,116,882,411,256,620,444,811,1,985,130,491,603,835,819,452,109,18,402,283,26,369,216,892,589,757,304,905,755,866,492,383,483,359,282,988,849,155,602,267,186,361,907,147,447,887,208,915,516,133,7,352,302,662,545,234,237,652,37,15,462,187,432,440,206,272,423,726,916,412,504,804,807,408,892,967,385,519,904,90,273,863,99,995,859,3,148,670,490,305,356,384,547,561,55,224,63,940,990,882,166,922,148,886,679,143,367,656,817,450,625,275,167,849,322,273,271,230,835,43,728,991,709,248,411,393,972,917,241,108,616,506,726,45,157,529,818,839,129,696,336,536,681,363,381,366,377,926,369,169,846,64,940,67,501,111,596,324,399,679,303,765,42,873,932,899,18,974,803,290,127,558,694,33,278,742,286,630,947,537,925,320,824,885,403,379,985,256,803,742,146,6,363,604,496,956,647,189,860,64,584,428,742,900,748,259,584,589,240,506,392,237,454,459,261,646,604,859,303,832,282,149,398,716,715,633,697,845,431,825,772,186,764,355,630,198,24,194,921,311,520,29,228,929,495,371,937,519,472,854,522,379,115,125,195,460,581,222,513,519,520,564,859,910,233,711,229,887,541,997,617,779,21,751,912,29,326,115,861,188,819,41,772,838,965,832,323,138,402,793,225,336,536,789,849,416,956,978,153,338,251,978,994,420,493,402,908,589,670,480,827,655,154,781,553,614,70,257,920,576,844,875,161,759,825,505,19,501,573,946,825,52,220,148,901,583,343,263,38,51,999,527,660,127,899,789,561,622,969,191,131,764,895,26,441,978,390,405,189,733,784,100,202,83,171,693,332,570,790,758,419,154,851,81,201,795,948,152,62,70,667,413,0,467,74,23,711,747,965,877,530,279,46,397,313,434,201,45,124,394,498,768,409,143,313,822,79,299,837,909,205,222,68,702,933,430,809,51,976,534,984,69,791,274,87,968,386,870,598,689,856,62,933,523,696,649,930,488,176,31,127,752,501,677,206,225,146,824,440,701,734,616,506,436,506,278,492,501,799,128,931,627,445,67,431,420,222,40,67,269,649,606,130,549,425,666,503,277,483,938,686,375,412,666,610,58,549,737,911,766,854,777,22,274,812,740,608,826", +"50,683,467,971,777,304,747,424,867,354,982,910,497,138,905,330,221,536,668,124,642,290,732,802,888,92,862,999,739,92,138,622,758,830,344,306,438,730,52,202,333,488,515,428,350,782,863,98,631,836,684,402,470,266,838,639,302,644,611,720,464,876,872,110,896,50,140,344,862,525,9,697,146,782,914,474,762,528,285,483,813,990,485,96,228,993,677,276,742,340,230,504,277,77,860,612,121,563,297,553,853,691,39,55,812,500,771,642,989,275,220,901,201,266,737,503,749,998,948,428,584,266,910,721,794,842,545,782,262,614,482,621,386,695,844,335,408,976,949,65,271,496,877,459,275,511,36,15,936,303,18,324,808,723,626,537,12,564,856,681,633,22,878,905,369,75,878,864,225,827,390,996,534,395,411,988,456,890,354,654,930,38,749,45,681,810,933,418,588,783,121,398,626,15,933,515,256,534,804,480,534,946,951,449,338,914,425,234,328,324,278,615,648,688,999,793,722,857,481,443,544,153,566,582,904,653,953,583,603,712,355,859,889,42,554,845,888,637,307,937,148,759,285,839,735,273,670,836,570,180,852,935,18,53,79,478,740,559,699,431,418,527,407,746,30,364,552,484,59,463,161,112,515,331,885,313,736,330,31,729,5,294,377,186,274,655,708,373,256,599,284,49,300,268,190,614,917,803,625,331,524,774,106,926,830,34,91,998,558,454,672,377,187,909,437,709,451,541,433,328,479,432,763,87,537,178,328,783,167,549,393,898,667,74,353,879,350,706,469,762,74,570,198,548,21,411,4,432,947,102,749,51,426,913,289,163,213,935,969,280,729,788,714,296,662,204,72,261,369,644,950,795,210,185,208,511,127,287,45,831,455,301,190,203,519,694,182,935,935,571,902,25,523,424,809,375,740,83,820,975,773,824,889,327,851,47,31,111,475,101,555,888,576,558,233,467,111,242,869,789,954,65,222,180,818,562,895,248,984,307,399,762,834,469,669,964,303,849,113,348,907,4,98,860,894,50,435,733,20,590,524,325,696,832,485,929,409,930,900,162,468,859,388,769,411,679,387,712,977,188,178,136,234,634,375,975,915,427,315,183,188,412,62,599,71,312,142,692,880,211,213,627,207,538,991,209,619,207,85,475,898,475,99,311,199,290,696,789,446,98,849,706,794,842,620,277,873,804,64,581,713,242,601,620,648,301,891,334,834,79,640,404,804,707,351,812,769,443,707,294,391,942,388,657,818,929,375,800,392,657,374,572,41,311,311,542,973,208,514,867,882,221,185,742,749,513,619,418,596,873,598,452,760,930,22,380,419,579,886,763,338,774,237,843,773,578,752,151,885,429,538,838,803,963,816,832,737,668,514,572,650,595,198,256,988,909,422,536,178,89,173,420,468,328,280,975,22,802,354,252,931,396,608,272,322,720,217,14,371,411,581,186,579,494,425,243,344,351,521,485,597,922,883,433,725,243,852,805,620,103,976,586,931,53,548,471,525,758,259,219,633,399,42,494,71,168,937,339,257,497,278,498,155,538,775,716,364,121,426,548,236,960,636,379,211,952,339,716,489,72,614,405,590,103,200,843,556,445,774,538,643,967,633,844,379,104,425,838,563,481,535,160,938,395,391,263,84,709,825,4,267,806,493,452,843,512,36,447,301,483,557,744,271,93,140,388,500,678,532,556,558,571,212,174,242,26,884,337,544,541,71,485,408,847,260,358,436,848,571,398,968,158,53,366,156,167,404,536,275,811,677,480,143,456,609,40,213,723,382,977,392,42,367,619,969,427,516,607,575,502,779,457,359,285,252,954,443,927,604,2,91,238,714,739,355,50,751,167,367,880,109,262,435,664,73,45,58,649,540,211,214,106,665,99,25,63,647,537,686,918,438,461,806,725,93,916,182,953,441,304,427,58,221,341,284,528,991,643,621,839,471,782,466,951,59,252,602,948,177,961,961,778,129,752,135,823,121,110,537,948,305,181,829,809,177,677,124,125,382,965,325,914,15,391,467,0,348,205,545,636,636,194,439,13,512,194,413,601,176,956,56,209,474,724,732,732,145,470,331,161,169,10,135,134,22,243,970,551,797,749,13,764,365,357,904,275,795,830,670,249,991,982,494,80,460,836,232,180,479,79,94,965,799,76,155,591,667,189,732,9,384,135,362,555,347,940,354,356,797,303,58,770,179,303,100,183,964,515,890,547,540,439,473,995,820,873,220,262,897,513,752,103,619,228,991,465,199,167,588,923,17,846,272,406,920,227,791,741,87,765", +"994,47,194,381,114,546,839,587,500,219,271,203,743,775,6,652,177,751,183,632,393,321,966,352,886,518,923,584,230,32,668,355,263,29,718,953,838,156,784,869,775,66,628,932,779,965,98,389,868,974,571,486,839,176,165,579,291,532,918,391,717,407,480,815,92,996,364,544,612,106,397,676,559,941,956,653,350,14,858,142,221,487,717,883,104,630,492,808,714,976,638,686,294,149,175,284,784,338,953,561,99,680,810,988,354,993,984,598,624,765,870,865,330,362,590,424,249,478,964,384,164,840,301,186,636,984,914,534,415,174,616,98,522,635,898,231,425,124,880,191,856,531,689,510,83,156,730,578,199,920,874,201,775,256,865,767,902,274,553,625,859,831,531,932,564,119,630,637,551,316,708,336,158,613,859,182,26,268,325,686,482,591,625,13,318,261,546,812,562,260,842,828,862,409,386,331,513,627,669,48,604,352,933,965,220,597,453,812,430,394,531,382,294,981,522,624,800,840,279,347,495,390,213,578,738,18,496,97,988,653,814,565,761,566,254,156,88,250,28,368,207,398,533,244,544,568,212,537,371,685,434,889,880,875,446,807,294,388,146,174,944,986,819,643,245,751,980,980,149,427,426,930,634,832,767,553,170,517,752,825,360,248,51,658,575,315,368,606,266,7,671,765,846,267,441,344,188,749,851,153,276,131,735,639,303,558,392,700,574,799,70,852,338,657,849,437,534,130,955,880,238,342,191,690,378,406,372,891,881,350,529,472,818,212,750,82,717,822,306,408,271,831,54,874,242,49,423,773,865,860,317,598,384,15,214,629,352,43,50,452,578,601,706,702,718,740,466,758,522,251,218,959,646,689,165,140,931,284,831,161,591,245,69,402,917,992,217,15,620,33,987,868,803,334,114,226,391,302,549,69,271,174,894,950,455,429,444,724,745,530,796,823,427,669,40,905,589,739,229,154,853,614,233,233,600,820,944,634,325,796,555,742,985,69,88,546,374,822,471,7,619,756,273,256,53,502,576,844,372,106,625,329,828,983,187,327,578,723,989,113,607,943,81,147,281,568,61,72,568,954,704,224,353,71,100,609,890,899,113,214,827,135,13,677,593,187,909,156,661,956,26,899,329,439,663,112,27,214,5,63,531,926,531,987,165,387,849,908,938,335,342,371,521,921,514,515,794,529,446,883,655,524,718,978,454,279,269,436,641,215,66,41,938,38,4,121,274,35,686,823,199,624,136,444,979,98,179,747,485,945,399,337,509,432,598,821,215,472,89,305,48,506,119,369,811,134,738,874,252,56,839,535,621,116,88,826,361,429,897,698,209,154,485,32,758,211,834,160,837,282,269,963,798,307,810,515,119,746,114,824,664,173,889,428,871,77,729,154,797,578,452,311,4,591,684,286,433,726,855,267,841,857,921,842,414,659,110,847,673,706,681,803,955,509,957,284,648,807,657,12,849,137,573,294,480,239,528,739,363,811,602,499,653,139,560,882,226,762,428,844,314,67,519,151,381,750,527,475,143,609,738,927,539,787,284,110,662,620,409,180,283,534,963,732,256,281,428,123,319,602,73,268,788,166,747,7,179,784,920,755,900,896,977,762,104,448,44,520,175,902,699,721,641,689,976,17,460,405,17,167,89,893,227,149,209,855,621,74,324,152,807,377,677,496,879,330,974,704,36,568,627,639,718,684,515,312,203,865,839,103,556,536,373,998,435,490,514,820,418,677,512,465,999,600,584,303,318,304,337,764,331,390,730,850,470,25,122,135,548,489,682,427,66,101,57,378,8,532,749,41,783,981,280,434,629,645,190,789,611,399,353,430,660,415,23,119,146,893,688,992,993,171,998,119,731,207,784,902,766,904,438,698,634,608,699,351,383,38,289,47,147,101,845,169,301,336,254,266,427,939,466,598,970,325,563,211,40,67,196,299,357,208,950,717,693,313,441,221,588,609,477,438,927,82,998,449,471,728,130,203,372,962,518,626,937,337,681,694,72,834,963,995,986,34,74,348,0,244,394,302,638,965,73,680,372,771,900,767,445,663,481,295,744,693,371,183,881,608,376,142,767,409,782,539,818,875,190,6,267,557,50,339,358,648,847,494,660,311,213,415,93,270,163,903,712,450,731,823,355,517,663,306,517,564,774,100,227,163,157,970,404,70,38,824,749,989,325,898,77,208,671,314,320,830,517,143,10,235,33,325,855,512,77,745,27,692,549,327,867,945,648,260,123,660,522,620,365,738,765,894,292,312,751,984,874,995,14,444,134,160", +"630,260,984,803,893,576,402,424,212,744,78,898,258,731,730,752,375,588,869,702,987,571,255,152,523,172,164,768,195,604,773,856,895,183,609,913,950,401,468,124,590,413,652,930,181,407,886,558,329,342,586,274,60,835,319,737,575,269,379,158,672,651,551,970,764,199,940,305,800,185,599,68,88,291,323,670,861,35,267,777,623,222,552,38,635,479,86,630,922,686,217,305,965,711,352,426,849,989,276,589,21,731,139,495,496,32,476,125,600,695,797,472,768,928,758,649,698,323,22,811,375,231,425,545,698,163,982,509,22,417,713,570,288,692,935,28,743,267,334,993,619,234,695,456,702,969,62,674,82,901,727,139,440,355,596,961,525,168,406,106,551,856,551,657,277,224,364,123,558,799,607,632,619,307,501,627,854,72,632,119,594,386,271,248,931,327,834,217,872,736,323,354,256,85,865,736,881,977,443,865,5,709,256,75,231,810,180,185,483,435,409,845,110,611,906,352,867,576,187,120,674,567,705,8,387,851,486,207,815,827,97,627,136,654,566,792,386,371,497,189,333,437,82,518,669,811,36,15,484,576,258,236,611,952,617,35,502,403,924,310,95,169,847,394,839,716,294,515,810,658,762,988,986,793,71,503,968,24,259,433,535,374,564,648,243,121,489,237,786,617,528,83,329,266,643,867,677,558,190,33,211,892,872,174,432,545,52,38,821,404,64,388,1,902,856,893,867,669,304,37,323,360,958,69,241,329,922,190,109,980,578,406,688,325,439,85,724,940,306,910,454,947,338,782,857,995,500,27,189,437,677,214,538,878,573,960,851,192,584,76,65,997,345,255,727,843,374,486,104,911,222,916,997,55,294,523,114,573,615,918,164,652,976,374,137,364,644,327,93,118,658,753,552,259,840,47,450,767,877,684,408,753,968,339,558,388,461,980,767,771,159,265,113,244,24,247,977,120,435,349,290,616,568,807,694,374,906,109,831,233,30,969,947,720,162,746,677,960,815,111,894,813,269,34,598,912,500,190,716,909,337,144,919,670,864,285,807,141,525,432,382,753,899,744,603,633,491,796,764,63,891,328,866,225,528,812,494,559,563,15,601,508,506,529,567,390,174,360,356,354,679,331,7,926,787,280,775,79,865,634,537,299,698,737,590,458,991,356,435,397,486,115,695,87,562,937,56,106,639,240,556,664,381,748,144,124,310,178,385,538,292,832,273,606,770,796,875,202,824,818,987,182,196,796,980,259,27,422,535,986,715,268,391,230,323,496,574,436,802,418,528,566,138,557,97,311,950,568,660,961,60,552,725,510,78,390,115,534,453,564,865,787,723,827,708,886,814,396,157,472,387,46,961,759,348,81,367,237,809,666,919,333,829,716,836,946,241,307,153,976,842,672,194,339,75,407,6,826,835,774,562,200,334,681,635,963,811,940,529,453,396,562,916,185,491,167,791,428,195,439,844,284,426,97,828,899,404,716,661,482,277,887,268,172,256,745,10,835,462,927,634,916,338,561,342,608,357,932,476,970,252,62,3,717,547,866,620,684,900,445,571,114,875,210,276,514,927,934,165,799,756,503,440,300,716,606,637,487,305,340,822,446,992,837,777,801,546,307,611,303,34,244,174,639,732,769,431,308,628,186,503,670,547,562,184,968,871,213,799,336,836,980,664,61,154,671,670,400,394,946,105,590,203,956,269,30,549,653,521,510,688,173,811,558,965,736,46,267,803,950,674,438,488,158,457,657,697,220,66,871,585,974,665,858,7,260,117,25,482,778,12,730,141,14,678,183,635,8,215,427,932,285,6,441,351,1000,762,234,560,782,900,459,867,670,262,656,718,362,3,479,497,215,755,192,366,238,853,260,729,942,42,869,286,195,729,585,240,592,258,705,439,72,90,604,511,260,585,918,378,55,748,240,859,249,16,768,860,983,893,893,303,970,288,497,24,348,478,140,348,473,354,361,198,405,452,422,256,624,762,552,949,128,949,973,386,275,255,949,644,54,79,949,266,162,23,205,244,0,912,848,789,253,699,933,543,87,936,323,69,774,272,600,195,524,321,131,921,791,854,862,832,414,160,104,184,177,64,259,153,271,304,412,103,845,896,145,597,392,874,513,969,366,319,390,181,118,340,508,613,266,400,654,666,320,173,358,442,497,486,67,109,812,286,182,917,241,451,874,925,117,80,180,170,322,258,996,143,162,389,359,580,857,122,69,821,643,618,900,479,999,44,553,257,827,50,896,400,668,370,916,583,195,325,845,674,667,398,117,864,604", +"380,871,178,419,20,342,158,820,69,842,908,456,797,616,328,60,905,545,755,190,368,635,94,843,591,798,189,26,953,543,812,651,989,599,336,75,654,439,540,139,875,295,903,996,355,517,20,603,923,432,624,547,115,679,490,72,658,135,676,662,945,912,832,558,127,836,510,547,593,311,82,24,918,158,962,142,959,130,506,311,36,350,17,316,486,845,697,587,733,157,515,766,771,975,268,447,71,987,891,798,927,422,25,414,707,769,335,191,610,825,103,388,153,279,659,181,760,775,711,846,446,6,527,222,982,468,537,743,763,882,248,482,207,282,967,221,221,890,85,458,244,138,338,837,990,563,695,352,122,581,592,378,135,277,757,730,308,373,100,543,393,252,797,783,196,688,20,211,107,681,79,588,983,360,797,115,326,275,596,741,101,945,141,658,367,200,967,894,366,260,320,624,445,156,127,73,556,687,376,666,678,508,28,992,879,487,5,226,241,572,492,194,141,431,635,459,838,396,711,943,722,805,946,502,322,783,692,915,167,503,147,955,266,278,15,787,196,11,515,534,200,924,359,457,76,950,196,795,411,153,68,908,297,542,81,108,327,26,285,918,384,804,934,457,935,730,517,373,223,478,553,686,712,650,303,916,636,555,955,70,901,232,468,372,54,684,510,370,777,463,88,218,534,947,18,866,831,189,8,107,188,521,906,12,590,997,390,14,162,16,893,954,969,648,633,668,582,722,312,520,919,133,325,449,805,586,614,71,860,170,39,921,786,937,845,280,665,812,157,457,162,759,658,276,76,195,39,20,333,566,457,149,791,50,148,704,485,747,359,764,601,142,373,709,500,728,38,435,613,698,203,747,114,311,985,625,909,292,554,617,275,23,478,907,691,177,947,660,903,983,262,893,89,836,630,426,548,924,48,629,633,990,530,180,428,99,584,453,91,336,125,546,237,167,514,16,414,894,108,928,102,111,409,997,477,373,398,60,398,183,316,593,180,483,812,25,733,724,883,254,552,468,18,660,309,145,245,642,404,696,664,114,784,75,421,735,159,851,517,427,505,14,750,903,213,648,50,1000,625,469,625,236,770,514,38,637,204,241,134,338,171,521,229,149,81,17,499,912,470,273,328,311,854,232,191,610,4,888,684,679,22,831,711,636,413,537,654,763,465,736,796,679,745,354,721,331,274,834,558,620,986,789,918,457,594,103,696,980,234,630,640,124,248,165,589,302,650,104,662,677,627,328,590,534,664,189,707,948,546,416,473,889,977,427,633,260,237,841,891,830,234,522,911,849,252,344,191,642,276,685,428,253,922,147,502,727,382,527,606,766,875,73,801,629,807,418,751,83,624,380,274,284,98,914,297,478,938,965,668,462,887,537,888,488,444,988,918,990,365,979,647,174,94,721,542,740,812,841,983,402,283,818,350,224,735,452,453,57,23,87,17,721,518,130,155,284,788,52,115,656,671,724,187,243,965,743,473,755,940,329,287,489,30,500,36,267,13,135,12,798,850,41,654,504,721,798,255,505,252,276,877,548,507,711,575,731,924,924,58,281,110,221,984,462,560,680,460,615,391,704,181,264,10,303,331,596,478,588,242,753,439,626,920,385,841,589,850,943,394,784,228,9,282,801,511,842,77,120,309,375,445,336,584,437,502,608,747,551,477,50,146,376,924,705,485,313,117,238,351,616,565,33,829,230,770,489,115,998,376,101,24,686,774,7,162,579,198,309,954,632,178,883,378,671,824,93,368,10,414,830,899,918,268,6,619,297,18,338,815,733,851,240,260,363,150,981,898,366,876,875,708,65,563,350,40,472,275,184,752,850,89,671,206,995,737,564,276,922,825,540,60,999,785,435,316,607,799,39,188,111,387,152,925,437,637,686,980,643,507,207,904,517,39,518,671,637,382,698,674,988,77,299,205,106,178,421,774,261,418,469,91,373,15,450,927,952,796,72,44,397,215,855,316,919,233,857,766,900,494,261,974,613,270,148,363,791,395,186,12,912,538,268,549,935,711,545,394,912,0,411,789,904,748,931,647,67,724,229,229,398,394,755,420,799,594,880,436,321,762,182,983,299,915,340,705,291,857,336,286,741,852,275,692,468,242,101,825,386,825,475,473,365,249,853,484,361,435,383,508,172,911,347,356,499,268,301,606,2,273,510,755,703,179,161,610,522,539,128,298,189,593,160,219,331,606,993,758,745,426,445,229,36,461,944,701,912,607,933,600,825,239,252,681,973,673,313,295,311,777,170,344,496,951,51,999,302,122,596,624,184", +"785,344,44,488,299,500,193,616,839,205,673,327,644,459,777,402,72,184,598,206,400,331,71,306,129,28,316,34,456,498,522,512,513,297,535,59,243,581,250,916,93,109,63,41,325,721,253,774,828,275,706,556,402,467,735,837,70,683,660,131,320,866,951,877,295,357,453,705,963,278,480,97,688,249,779,259,632,457,47,605,523,771,489,895,25,273,709,691,233,221,903,688,732,591,698,509,790,406,363,569,259,214,616,437,915,611,974,689,714,590,126,143,191,530,543,258,48,461,89,524,312,41,797,668,766,960,240,631,529,623,858,395,368,314,732,304,584,767,537,88,997,16,326,678,403,632,945,231,407,171,568,313,952,33,996,865,806,989,110,777,531,768,514,365,752,257,598,544,850,635,379,227,340,842,650,276,205,877,557,631,785,808,971,760,768,263,377,626,530,570,649,780,409,939,682,126,333,278,34,120,916,346,313,955,755,932,217,191,379,197,541,254,827,234,179,130,29,976,186,109,39,286,384,759,761,838,109,854,511,930,12,769,492,74,67,186,756,857,437,743,927,544,405,351,139,566,547,978,27,375,628,645,240,758,578,541,868,507,52,65,903,341,270,907,389,469,305,277,413,585,847,235,703,90,302,476,624,90,716,295,256,862,71,292,675,329,912,542,687,422,473,734,518,283,50,567,641,813,490,851,649,995,246,865,347,905,698,104,880,813,672,231,160,283,146,371,28,732,421,758,961,906,492,922,203,689,710,361,483,37,107,762,138,657,556,953,347,591,539,831,696,563,200,723,135,881,866,358,727,74,438,636,208,877,180,819,957,363,988,625,452,618,39,306,559,580,727,364,997,195,323,972,48,262,452,598,580,620,554,48,95,434,822,603,833,79,817,894,381,890,288,107,792,703,753,590,993,779,926,876,914,12,64,75,712,366,555,820,897,47,653,64,441,894,664,510,764,965,927,639,300,905,712,73,48,409,659,242,645,920,329,585,785,539,587,652,87,280,101,5,169,672,773,862,986,436,884,567,849,730,731,780,913,959,964,411,428,838,464,182,536,293,602,786,799,195,582,205,91,576,403,992,979,426,450,8,373,822,576,569,9,311,809,75,695,844,57,932,483,131,20,916,526,528,559,768,185,709,827,787,310,834,226,989,218,657,299,815,383,64,778,14,617,761,701,751,9,54,905,981,385,346,608,846,779,627,179,558,159,258,385,210,189,280,359,89,476,463,836,466,643,701,846,45,93,95,801,526,911,177,768,31,301,238,20,118,693,333,37,962,472,930,667,434,800,556,236,836,659,78,470,183,190,629,281,6,512,260,496,752,151,243,236,48,534,314,981,610,444,652,825,535,761,923,747,846,8,911,90,361,187,918,44,754,928,856,119,724,962,581,959,738,480,622,374,184,819,44,608,47,846,624,421,802,810,17,760,909,893,434,866,356,104,437,989,771,879,935,980,192,129,319,452,437,781,410,956,86,475,342,84,698,176,341,436,551,432,65,592,311,22,14,876,366,33,234,479,940,593,878,393,223,445,963,437,707,521,624,283,501,594,262,332,6,437,306,869,208,965,678,408,660,593,262,805,929,160,244,871,674,541,792,489,7,176,809,996,5,424,523,582,906,280,789,719,191,671,145,425,25,716,837,555,644,333,391,786,357,453,696,574,780,890,334,899,865,802,272,272,608,384,653,300,455,488,273,307,306,7,980,298,738,66,34,711,665,778,421,916,604,547,310,881,420,684,393,66,159,950,601,130,656,684,733,5,820,796,782,539,639,89,324,159,959,882,775,680,941,717,875,989,93,908,640,398,235,126,215,109,840,150,666,761,295,210,361,365,122,287,796,755,142,404,592,987,17,909,608,854,349,740,552,651,900,348,882,234,730,479,219,887,884,646,276,344,814,331,328,49,728,977,214,494,924,484,627,883,459,157,235,520,120,889,718,688,281,164,928,883,410,607,942,620,81,6,624,719,580,927,615,691,553,781,27,350,836,199,825,521,925,939,429,637,136,747,636,302,848,411,0,996,967,17,20,855,870,479,269,897,696,121,301,651,429,477,721,424,749,746,412,859,785,870,90,536,399,841,209,578,482,255,868,956,178,411,475,628,903,986,908,906,638,194,376,657,246,340,983,811,17,976,126,522,194,232,223,908,643,810,594,861,110,960,859,974,713,793,585,167,40,182,162,739,283,284,751,326,739,282,553,620,89,789,620,563,38,198,817,768,183,609,92,483,667,855,23,865,135,165,558,540,498,539,173,79,687,311,110,100,935", +"60,638,765,319,530,682,933,400,938,307,214,138,52,752,290,719,284,782,770,920,243,846,22,793,863,474,844,767,81,63,98,659,203,903,915,843,870,874,245,811,89,889,896,661,386,815,996,781,503,251,405,249,12,926,491,244,334,815,511,520,937,158,496,332,843,210,269,647,831,298,950,345,947,502,308,916,958,797,122,839,68,230,811,99,365,687,950,132,553,781,142,716,671,825,504,57,607,997,646,326,642,245,643,841,164,401,324,94,82,874,916,396,462,293,623,438,336,501,974,29,207,19,805,262,931,395,773,993,356,853,318,711,285,114,810,354,903,524,3,249,620,219,892,925,955,594,475,145,496,995,226,794,42,712,701,646,583,281,308,654,182,889,746,515,845,662,509,133,538,6,992,902,422,891,111,857,879,754,457,177,5,946,297,386,132,982,633,57,494,654,588,852,370,957,831,1,298,37,35,974,133,408,334,631,172,245,260,968,640,447,355,778,304,203,700,122,699,46,51,206,415,436,668,331,523,860,950,992,426,13,905,467,169,704,709,250,454,152,779,897,363,975,259,19,970,8,241,793,305,96,373,444,291,303,460,611,384,823,230,386,69,953,54,928,260,433,286,298,379,118,751,850,731,123,945,692,360,875,267,918,743,174,81,307,369,706,953,63,22,743,735,463,367,893,212,125,442,770,739,159,401,854,374,963,808,224,485,709,800,793,123,678,612,628,815,893,693,241,284,832,448,548,515,880,867,744,827,770,482,355,864,75,3,662,514,172,885,737,450,269,737,905,528,585,257,518,774,218,1000,739,875,819,812,411,524,664,580,257,384,254,624,561,941,701,645,939,254,695,226,124,488,542,733,496,528,594,203,235,673,106,126,724,41,92,832,894,948,554,69,426,393,483,776,23,581,277,756,296,189,795,387,895,263,841,465,466,818,460,24,735,257,426,641,387,770,117,204,242,694,29,176,873,549,739,927,782,919,265,346,996,857,639,886,408,195,908,49,528,754,163,78,494,353,926,590,671,130,129,647,67,242,827,268,792,38,746,781,87,669,589,539,166,267,544,259,807,347,321,712,639,404,773,228,140,310,516,520,741,732,737,353,226,756,790,838,765,472,755,772,823,249,54,597,45,641,835,955,289,59,156,946,755,599,31,739,357,145,315,720,890,542,470,192,332,232,516,47,964,703,109,776,810,986,736,412,947,701,538,66,553,96,943,884,576,296,81,237,530,343,465,217,560,718,629,892,769,144,749,966,51,630,799,238,545,881,178,808,985,558,628,401,324,378,356,894,193,709,448,285,206,75,709,374,253,334,55,650,87,348,631,741,268,729,58,81,935,871,549,333,553,967,178,405,92,702,166,643,428,343,229,856,11,271,377,582,909,619,187,142,584,706,738,117,26,207,310,200,507,505,509,449,541,396,227,189,125,116,773,359,653,817,687,259,406,78,11,312,279,930,57,647,875,975,49,271,442,11,731,384,57,383,335,388,450,321,213,807,2,269,976,668,865,505,27,240,350,380,420,482,723,381,405,787,114,179,933,704,491,844,530,968,837,284,394,739,547,378,804,223,461,757,68,78,500,584,768,34,284,228,152,107,53,466,726,240,505,248,808,146,651,127,783,815,951,306,384,205,327,334,877,149,561,347,776,965,539,443,540,904,525,738,467,606,980,668,634,741,797,570,69,330,860,358,662,409,517,643,827,631,769,154,332,545,812,136,52,645,647,254,836,301,607,153,699,176,621,350,335,280,17,888,953,25,603,886,522,754,239,863,437,955,245,725,14,143,863,182,847,575,14,604,505,93,388,708,79,543,914,547,682,685,844,847,666,675,182,665,290,662,496,145,525,631,828,741,678,123,800,803,8,792,543,135,338,54,221,590,829,171,268,925,342,2,812,643,708,77,675,406,572,84,743,979,916,289,550,194,861,873,454,601,215,789,570,765,456,794,879,939,329,467,713,6,832,901,180,289,711,28,378,169,85,740,618,794,344,453,192,508,453,51,168,886,673,965,636,638,789,789,996,0,12,307,993,399,19,591,190,281,388,551,877,805,913,388,69,984,447,947,476,202,872,852,681,467,258,583,611,740,827,149,202,361,712,615,531,192,759,126,809,696,314,785,905,422,468,612,536,115,959,382,515,59,509,907,867,594,654,763,839,254,463,837,850,859,458,185,960,198,591,864,849,821,883,918,6,252,52,357,899,953,7,729,669,149,479,546,649,213,180,427,89,97,229,392,688,26,646,115,958,972,957,373,435,230,300,196,634,795,562", +"341,799,755,131,472,873,445,126,689,277,78,492,94,168,708,75,758,995,218,421,788,186,863,161,712,983,214,601,637,887,732,291,840,537,694,523,925,871,359,556,584,545,150,711,130,159,449,870,428,394,859,120,515,38,664,847,304,379,458,431,631,323,736,882,82,430,90,387,70,230,926,244,943,680,958,874,755,428,708,973,891,585,311,419,727,589,29,429,94,219,543,639,757,258,588,123,522,382,832,923,749,874,459,445,504,331,309,876,574,368,305,88,468,560,34,809,18,336,70,47,317,82,384,471,227,556,125,207,517,925,712,844,928,408,616,808,665,203,518,412,759,696,259,855,648,128,366,690,550,555,189,986,994,174,642,448,642,964,772,150,247,532,144,906,145,210,720,944,589,623,521,813,765,189,398,719,161,445,201,182,17,959,998,625,697,257,278,860,856,706,42,754,505,679,833,370,675,662,500,275,791,415,600,107,742,5,521,387,621,542,731,42,275,220,366,893,952,433,949,854,991,415,540,457,810,524,252,483,490,899,351,349,954,391,16,635,318,561,405,33,984,56,290,238,785,767,5,326,315,192,81,138,759,331,923,670,131,792,228,679,219,481,749,89,129,163,468,403,795,606,809,503,515,918,786,935,532,62,512,375,951,371,147,6,76,844,999,336,872,922,783,844,880,924,181,6,528,810,117,587,919,914,546,767,280,181,800,15,900,903,951,624,954,625,136,729,801,611,461,401,249,712,10,615,405,377,940,501,933,859,32,807,166,814,675,931,493,603,704,817,593,152,219,237,278,421,915,532,956,392,360,610,917,636,224,482,657,660,192,742,849,178,474,897,736,155,78,509,466,46,192,961,312,662,801,358,194,713,654,67,234,438,746,715,334,872,893,386,989,792,649,476,771,403,76,859,573,248,736,557,526,342,404,769,907,850,776,859,478,55,232,840,754,979,550,246,633,230,387,420,202,915,466,404,119,433,109,252,656,744,34,683,845,347,562,418,911,440,602,108,347,369,520,668,907,530,582,379,970,277,981,356,207,226,124,174,964,380,498,476,865,141,197,328,437,192,386,835,268,858,520,923,157,627,552,947,534,145,21,523,699,332,105,784,412,158,778,709,678,850,214,778,547,161,564,951,938,768,617,531,160,543,19,290,241,50,24,284,775,106,602,66,403,286,557,970,800,830,901,451,337,726,566,752,901,677,753,47,156,74,558,411,358,487,16,520,417,600,562,625,108,317,876,808,937,84,952,355,402,509,258,671,682,765,346,585,844,377,619,803,153,485,416,523,150,180,288,425,625,821,155,89,457,542,173,33,672,228,983,296,865,115,676,787,186,669,404,183,621,784,636,842,237,795,11,786,191,336,589,107,480,406,135,811,515,767,233,250,705,25,671,41,139,60,6,858,720,284,781,302,29,114,579,547,699,372,430,604,912,385,63,716,857,175,332,552,62,402,479,109,193,700,289,570,886,104,452,176,893,802,434,349,423,433,350,953,796,356,142,903,818,655,889,967,779,683,762,388,343,816,267,264,128,968,142,582,980,457,298,357,99,631,734,655,307,916,401,749,60,521,275,79,41,843,632,512,198,243,55,503,978,223,97,102,498,519,673,962,728,443,708,685,705,539,250,286,27,236,412,668,101,441,470,378,559,775,740,601,148,975,446,378,827,880,244,231,106,158,661,435,539,78,548,702,435,146,898,634,738,455,740,349,189,536,981,383,406,567,685,817,818,120,967,550,677,586,90,266,21,506,459,915,524,928,307,24,648,11,905,468,634,984,728,325,975,107,760,952,844,312,165,914,583,952,325,490,545,968,175,310,81,511,633,967,186,379,834,370,295,675,761,522,599,665,237,309,147,621,20,936,747,480,834,886,975,198,361,544,309,978,291,823,454,692,548,16,435,417,132,379,480,702,989,693,263,710,713,307,7,261,736,132,237,468,217,446,43,862,812,834,799,802,831,214,231,240,508,894,311,141,269,710,343,764,769,255,895,726,759,357,300,506,243,532,877,194,965,253,904,967,12,0,861,636,138,820,905,173,501,691,573,423,993,959,160,321,714,918,454,747,764,479,630,119,439,495,453,780,496,229,709,880,851,532,840,588,477,466,334,200,491,670,939,430,770,101,902,799,436,796,816,344,312,896,937,929,88,872,959,280,915,404,281,640,383,682,885,611,803,588,521,145,896,454,709,254,247,106,206,845,497,529,822,402,414,572,379,730,452,901,125,146,673,841,900,977,262,95,275,584,457,573,786,797,946,75,491,625,665,618", +"278,881,523,741,598,424,478,331,883,245,727,723,398,978,925,173,765,223,434,718,177,398,767,109,986,458,499,623,275,907,265,766,726,579,278,374,901,579,616,553,417,624,313,67,864,157,890,89,572,572,406,638,482,521,235,42,936,129,563,691,20,248,909,191,649,390,848,692,807,242,939,546,909,115,169,692,789,803,339,129,930,715,780,46,905,955,456,424,173,96,821,225,169,959,243,159,101,584,394,607,781,346,546,839,156,164,393,781,897,688,577,274,578,93,963,513,163,92,371,980,546,490,256,974,872,468,281,843,944,767,411,785,692,347,436,242,521,728,519,919,667,884,52,513,505,46,642,800,909,258,904,728,456,313,911,881,768,538,330,886,887,650,43,22,956,127,737,163,215,537,586,178,77,112,839,250,8,76,58,547,854,132,781,98,430,737,3,338,835,474,170,730,251,19,156,942,576,151,345,813,130,235,765,691,17,608,758,115,518,53,891,95,180,716,739,625,964,20,164,926,186,456,394,718,503,568,87,990,969,272,758,960,87,613,15,471,400,992,346,836,503,550,204,954,633,708,88,418,387,580,157,917,121,719,994,988,23,460,641,476,739,755,533,517,766,983,21,248,62,247,643,351,107,549,229,639,98,566,567,114,893,589,97,679,239,1,791,738,103,994,898,160,127,826,618,825,378,359,470,957,427,221,64,353,509,130,103,711,345,564,29,580,742,108,606,34,153,49,345,110,515,116,917,1000,1,55,974,682,727,729,213,614,429,975,244,123,169,818,802,548,622,216,723,776,149,753,732,953,206,123,110,608,122,483,454,481,833,980,514,687,107,814,954,382,41,34,174,195,31,830,329,959,606,596,436,18,803,112,451,114,885,447,746,371,964,670,832,384,219,418,696,81,62,497,870,359,509,672,578,284,461,328,618,909,190,371,876,293,716,624,689,915,549,119,843,255,450,789,901,337,987,270,657,238,405,411,840,773,59,830,979,847,591,414,319,107,255,41,757,621,206,919,456,23,63,289,822,181,134,232,596,370,260,705,261,913,620,847,483,246,282,600,589,962,33,194,405,377,42,803,863,268,460,963,95,278,95,8,909,512,373,806,57,205,229,182,250,446,330,547,191,636,183,777,709,684,323,389,36,877,119,230,415,739,516,319,683,201,523,322,640,291,780,786,500,838,770,401,179,348,929,355,396,112,357,778,18,718,775,283,670,172,465,794,143,670,950,933,610,442,519,678,633,786,687,863,15,645,266,379,327,761,839,233,109,423,40,716,47,561,891,303,150,998,516,921,438,295,126,228,662,640,918,393,573,452,201,510,291,762,942,819,847,7,13,7,397,416,152,10,957,57,198,907,666,409,628,886,666,247,705,128,603,772,969,899,712,356,719,652,388,442,648,651,796,162,692,731,495,174,637,811,158,668,355,115,225,208,452,90,339,784,901,402,481,482,483,780,842,866,169,123,571,78,556,130,604,52,741,746,927,92,823,789,783,392,173,590,341,117,268,862,409,913,352,287,225,211,887,562,675,16,999,983,870,558,209,42,38,937,56,689,404,103,675,252,592,411,65,228,602,671,586,976,689,396,467,347,196,553,214,498,44,390,229,941,771,387,956,955,451,666,321,980,614,435,267,78,907,18,542,157,517,512,534,271,523,254,809,652,387,336,512,316,434,307,702,583,410,128,548,531,895,998,295,153,643,679,60,820,31,744,717,340,332,697,699,223,551,284,19,61,482,182,191,111,50,14,171,616,472,500,593,934,952,956,358,254,612,535,847,660,632,823,388,524,865,864,690,882,524,722,192,432,496,177,450,119,914,236,948,709,665,978,417,523,459,103,996,951,497,214,857,325,418,467,833,813,264,130,86,739,158,992,665,650,554,704,463,647,390,388,726,455,514,199,77,410,577,386,579,255,920,50,92,755,986,522,818,850,648,348,364,684,968,990,561,293,347,99,429,883,102,414,97,264,534,807,83,84,403,280,477,503,739,908,58,609,576,227,619,490,937,819,530,439,73,699,748,17,307,861,0,773,58,865,223,852,941,905,867,909,773,585,6,995,395,313,159,73,363,745,241,936,881,78,75,991,446,814,280,727,545,338,31,637,416,822,788,495,734,780,41,913,195,127,767,886,172,689,986,822,620,916,45,805,489,184,978,604,371,350,321,145,197,485,25,869,627,301,909,757,688,431,718,654,938,838,448,381,638,507,236,686,5,909,923,506,185,404,371,340,437,470,922,570,658,505,112,480,786,797,136,552,856,72,975,445,69,829", +"468,997,121,671,381,61,20,229,837,495,962,592,708,489,189,270,727,606,172,24,204,98,269,353,412,207,867,570,714,415,902,450,72,531,504,902,897,894,727,297,556,199,620,562,870,169,800,105,33,873,930,355,275,808,703,118,987,582,914,307,645,898,592,11,384,825,772,699,100,23,669,790,398,160,493,353,932,944,135,216,158,174,508,9,628,865,920,984,490,287,731,311,700,152,933,149,480,793,819,53,996,223,813,575,507,869,126,55,600,724,214,501,581,877,476,445,6,636,679,797,382,160,295,638,528,606,790,440,718,467,829,36,582,766,376,647,302,765,118,519,31,966,582,478,340,467,493,534,683,173,974,893,604,740,248,323,220,368,638,872,311,998,852,229,154,215,956,410,246,272,343,571,38,697,362,240,369,420,445,316,353,767,246,551,632,267,474,141,250,50,144,798,542,112,655,910,961,364,836,294,493,341,568,631,913,204,87,20,670,848,258,238,784,228,583,677,260,430,5,74,566,953,345,879,943,844,19,788,92,417,670,316,216,515,329,642,456,102,910,275,604,307,164,745,631,984,189,432,301,477,711,559,861,333,500,323,653,278,776,775,83,29,154,807,636,196,69,821,549,641,23,425,878,400,272,936,827,140,528,823,153,430,979,95,872,304,455,768,685,146,82,953,252,78,136,520,907,141,45,146,296,882,664,552,204,838,369,762,377,852,888,974,656,353,102,86,32,463,810,309,583,435,535,683,215,617,70,924,651,283,973,335,661,59,231,258,503,843,817,802,274,391,173,631,602,523,504,472,463,910,162,699,480,972,41,958,189,550,991,55,592,99,895,806,578,378,109,945,39,457,354,993,730,322,615,186,505,771,559,185,798,5,400,483,621,838,959,695,405,687,51,665,740,865,167,825,399,485,647,797,214,209,290,51,248,651,418,933,801,819,4,105,782,716,986,173,512,53,863,488,388,237,472,834,391,398,689,705,857,424,741,839,959,132,671,510,331,563,375,499,593,25,946,30,639,105,570,136,778,436,403,596,464,422,741,849,455,214,621,193,516,7,227,467,919,912,717,275,565,269,148,556,55,8,544,555,911,117,724,663,307,181,615,193,27,49,904,730,923,443,845,422,11,957,32,329,742,335,685,21,34,20,292,218,247,353,510,990,258,942,372,268,304,36,13,867,965,410,746,426,972,624,706,209,70,648,748,550,65,556,583,385,571,803,882,131,439,425,45,126,684,940,282,318,79,285,410,889,686,553,295,621,198,208,398,207,372,637,282,726,534,948,330,207,322,82,48,453,160,474,477,898,87,30,21,370,61,398,348,241,502,413,491,749,8,329,198,581,140,46,587,486,188,929,457,230,309,596,564,405,856,336,590,104,785,135,196,159,116,266,351,449,920,301,533,869,147,498,194,515,476,117,512,978,371,654,114,971,267,700,79,322,449,893,787,477,939,636,356,692,673,42,853,473,221,8,117,679,386,66,404,337,886,298,331,129,537,95,632,93,12,157,546,515,59,525,446,677,797,868,159,698,440,347,963,757,279,264,500,132,925,593,515,482,7,713,100,4,964,879,730,291,921,698,938,838,332,199,18,468,826,327,780,840,380,844,628,882,407,66,911,655,364,337,583,802,771,904,512,802,575,640,783,276,597,97,163,629,743,185,214,159,648,825,436,805,888,566,966,471,598,768,82,78,119,150,725,754,534,603,436,405,619,769,121,68,15,756,82,43,780,664,859,173,275,185,620,912,819,824,285,966,498,369,283,835,468,734,848,11,183,158,282,632,128,614,416,82,543,510,560,907,413,251,811,76,185,211,336,755,11,607,697,121,944,889,194,714,484,72,40,775,120,952,463,550,444,321,715,98,954,236,16,856,628,823,714,215,213,749,178,183,477,436,39,115,519,784,368,837,837,637,180,989,243,170,403,574,395,805,124,354,246,953,457,444,914,131,998,110,845,399,440,171,353,532,196,416,563,561,860,569,260,534,350,903,454,787,850,72,193,74,16,191,279,13,680,933,931,20,993,636,773,0,748,956,90,353,951,33,365,208,719,265,646,857,643,832,856,60,69,699,526,630,531,236,291,621,204,172,528,991,399,557,726,908,317,327,654,742,668,636,564,482,408,402,62,772,983,544,356,679,91,711,252,198,628,649,968,541,29,118,119,277,735,945,197,67,177,322,193,293,976,652,746,357,361,605,885,814,82,51,667,844,815,470,74,867,397,584,974,282,923,303,733,180,125,246,500,826,946,76,80,563,115,302,218,693,819,61", +"828,342,834,756,288,156,311,968,411,265,605,401,364,891,493,218,591,630,752,365,492,134,961,407,383,890,822,995,951,534,937,474,272,393,685,739,619,857,350,344,186,40,603,851,954,280,700,679,160,983,261,579,242,433,385,241,643,377,364,170,8,524,912,615,302,149,660,871,822,269,211,654,761,165,822,890,574,204,204,590,219,110,112,169,557,393,33,581,853,381,844,919,142,244,812,486,884,463,109,410,91,770,151,644,823,433,751,74,369,864,662,477,887,799,748,626,997,588,989,430,85,851,893,571,682,978,906,536,162,415,432,855,760,567,349,807,820,130,516,264,592,962,838,459,217,493,332,910,45,69,472,485,823,122,9,303,926,657,794,980,52,128,759,681,571,834,663,919,23,265,549,800,114,622,375,774,729,11,739,423,479,57,336,71,91,820,911,395,607,281,866,804,205,87,459,26,861,699,274,725,229,340,710,25,965,965,98,933,797,156,894,781,65,497,770,213,32,366,978,716,94,716,673,638,623,109,372,285,506,202,526,671,152,516,308,808,539,645,511,435,22,526,583,426,874,302,664,779,442,69,512,607,196,818,645,53,916,809,847,349,869,56,740,225,158,332,635,101,747,894,246,573,642,17,138,810,609,682,225,806,705,720,518,915,806,135,120,771,968,216,284,429,112,683,767,375,475,244,960,625,22,330,725,196,859,470,532,307,190,269,475,994,636,368,614,431,64,841,981,104,957,422,543,94,337,951,459,758,785,708,273,671,737,680,398,317,712,634,870,158,581,389,541,368,324,36,278,361,947,211,979,609,634,284,981,556,228,810,987,575,606,382,480,788,152,389,908,837,721,850,802,243,526,10,246,294,703,40,373,130,95,685,462,777,768,841,49,702,600,724,562,799,58,12,205,651,796,486,328,646,580,423,257,102,434,314,973,427,688,339,790,119,182,24,897,225,62,419,173,239,478,698,806,165,358,529,372,654,449,449,81,192,668,303,331,32,526,23,454,621,575,455,106,47,987,106,415,882,656,562,950,369,328,672,665,204,702,848,870,247,828,389,585,43,478,329,945,47,656,214,573,448,501,501,175,127,694,206,244,843,69,129,798,386,662,760,836,598,501,130,426,533,276,280,480,257,323,89,748,501,262,29,17,285,6,544,586,426,793,797,254,197,604,749,139,235,113,351,493,964,42,111,545,392,433,438,633,590,960,481,260,128,841,563,395,864,429,213,215,567,24,265,431,336,755,830,676,791,801,876,925,140,154,632,278,425,184,691,324,521,563,65,593,590,582,795,714,995,221,814,536,619,116,911,889,474,800,237,778,92,123,145,962,638,902,77,327,556,681,134,573,243,598,103,194,566,644,89,941,235,629,18,537,811,407,955,86,519,127,162,395,303,890,30,485,984,143,135,990,655,108,106,783,890,883,829,175,64,820,376,226,598,978,931,798,444,251,990,397,538,614,507,712,454,506,560,675,413,481,154,795,584,919,180,257,337,223,876,781,274,834,851,52,816,6,82,618,727,78,184,860,589,453,29,897,633,819,597,396,9,493,461,626,992,978,217,756,789,38,340,85,280,633,235,421,666,667,480,756,295,788,917,620,424,725,590,481,527,207,303,792,951,48,53,594,917,800,851,135,684,878,448,788,466,820,856,384,610,543,443,287,184,555,610,737,825,62,303,825,400,977,748,446,145,423,716,409,962,64,275,197,413,640,167,983,141,152,997,715,838,683,664,801,637,296,431,114,71,392,549,5,851,698,547,720,859,360,127,652,542,311,966,263,155,660,106,448,149,72,117,600,123,574,603,137,314,369,209,567,650,130,43,678,617,732,727,914,6,190,961,856,193,79,991,728,563,475,650,136,667,439,164,955,855,246,183,397,106,280,305,810,271,989,781,747,136,427,426,316,639,103,898,258,872,540,569,388,477,837,151,715,443,277,484,9,643,289,363,163,834,307,411,315,224,964,530,89,895,273,850,345,525,700,414,661,378,937,719,790,865,719,795,305,666,46,512,372,543,647,855,399,138,58,748,0,101,548,114,485,773,55,464,516,685,503,538,846,182,107,242,437,929,10,728,245,279,159,956,630,775,43,946,308,920,274,596,578,97,432,454,115,839,374,926,174,804,474,148,811,9,87,902,362,232,772,533,189,333,285,649,93,514,195,722,571,969,513,705,356,642,65,181,552,742,609,237,54,952,779,502,262,520,692,999,132,473,19,741,166,695,66,752,534,638,683,346,201,368,106,139,644,262,880,815,753,333,334,564,832,824", +"213,572,711,970,224,632,54,225,608,251,789,786,646,601,875,221,635,574,329,665,574,398,686,380,333,541,856,8,67,587,204,745,226,112,818,414,436,9,647,387,391,59,616,269,983,577,52,945,631,146,430,437,892,987,921,471,547,985,611,859,546,574,256,66,687,752,230,70,310,463,514,777,616,287,858,454,26,620,69,181,948,913,984,968,273,347,433,865,364,748,64,800,922,32,168,839,951,163,527,684,548,636,394,512,780,993,845,241,303,455,257,249,790,444,552,911,833,381,5,455,202,253,430,233,30,316,793,473,310,232,801,679,189,444,773,245,776,746,716,474,141,545,452,984,518,305,615,343,671,419,838,487,49,929,696,97,588,219,119,615,733,895,796,430,661,629,490,771,804,781,447,184,766,142,281,214,796,474,937,954,391,310,884,78,651,264,806,779,800,384,454,654,964,95,5,413,607,703,462,57,948,287,110,519,230,902,391,741,607,260,679,950,168,794,179,321,322,837,103,358,977,826,851,508,836,981,46,196,67,728,829,845,610,848,311,672,910,303,391,940,451,968,712,309,322,990,490,920,179,351,556,580,673,71,869,470,642,78,543,76,717,778,420,156,235,514,553,494,38,576,384,722,502,238,716,140,993,609,637,552,438,999,18,446,396,972,287,134,644,198,319,237,485,472,417,907,726,110,97,202,127,30,774,130,860,822,618,882,353,276,521,117,355,880,721,132,498,691,821,7,23,576,77,566,939,446,101,133,282,242,943,206,620,48,132,20,987,747,688,377,493,483,169,838,219,612,983,311,339,528,606,160,573,550,809,932,211,530,123,800,645,993,263,509,387,409,63,998,579,961,994,965,965,437,326,492,327,899,324,729,860,654,527,678,429,406,789,821,228,478,708,459,856,850,924,693,329,697,428,882,29,346,306,654,123,415,497,678,730,133,906,461,49,457,735,701,678,476,846,534,364,162,511,10,840,898,609,326,597,903,69,491,10,173,910,141,568,683,129,996,253,338,650,844,462,881,976,651,66,909,223,657,825,132,21,125,619,83,871,197,212,642,931,924,923,621,67,215,797,898,74,63,277,184,572,464,826,924,137,404,379,233,514,845,57,468,255,658,317,678,118,829,145,608,335,990,681,448,614,263,339,546,788,260,406,235,545,666,580,154,865,219,388,48,616,673,6,446,479,207,174,420,339,546,848,862,430,97,73,361,557,913,553,68,258,64,701,724,738,582,539,37,942,113,892,468,876,38,621,413,972,969,409,976,763,178,746,551,420,390,405,280,416,531,741,316,199,549,662,948,36,716,501,876,278,701,935,783,575,861,581,195,286,96,652,952,346,937,165,862,560,774,340,348,316,345,52,887,865,632,619,505,244,247,745,901,864,380,45,93,181,624,377,696,933,401,420,530,930,408,917,363,583,215,202,486,317,545,382,790,237,77,81,330,128,426,919,178,642,458,904,943,59,947,100,210,784,27,252,245,687,936,888,144,387,674,900,571,338,544,264,184,727,242,426,925,667,9,871,471,591,292,6,299,761,981,238,856,861,344,244,350,943,591,135,316,857,192,682,431,106,639,344,89,511,116,45,795,764,563,193,526,49,350,204,332,35,759,946,167,312,338,376,183,506,857,784,277,323,927,297,80,786,221,108,239,870,708,832,211,150,175,466,891,196,43,20,87,763,410,424,377,400,463,95,582,469,37,544,895,953,101,329,360,968,208,716,485,728,406,690,437,948,510,747,498,983,446,291,184,130,371,804,865,988,791,223,877,686,922,136,204,349,816,224,190,316,985,738,369,922,760,731,128,573,920,822,432,596,846,927,309,556,951,178,764,891,57,791,635,440,304,293,98,948,290,412,167,150,854,919,720,103,1000,337,510,875,516,314,548,384,553,726,683,713,353,710,245,713,728,113,742,641,532,46,472,945,100,855,151,510,986,392,400,204,299,238,877,528,834,556,18,180,31,734,421,333,974,177,337,84,586,473,341,12,234,163,928,288,421,16,143,877,319,397,194,771,87,67,870,19,820,865,956,101,0,525,252,507,717,448,101,201,917,909,673,586,919,27,522,163,791,646,467,849,235,668,495,8,735,551,568,121,127,902,85,685,627,418,54,193,683,878,913,186,676,567,968,725,516,911,891,320,657,917,925,453,536,865,137,719,796,942,988,938,975,396,72,294,633,569,652,252,878,733,997,453,774,444,462,229,720,27,657,198,880,103,750,32,565,325,862,383,513,722,673,518,6,843,400,826,420,977,776,252,286,952,134,844,939", +"711,487,136,751,610,802,448,537,866,849,421,357,258,525,287,931,229,208,898,489,693,806,415,791,557,252,489,888,764,896,777,994,539,177,719,547,303,739,152,85,502,12,312,692,919,838,193,313,952,641,19,410,487,563,733,267,924,765,253,402,957,190,594,664,694,507,992,960,164,587,445,462,169,966,254,124,499,793,653,576,564,380,627,988,314,735,522,748,567,841,417,256,852,908,252,232,556,191,248,526,276,955,119,548,768,700,985,152,312,160,145,359,279,177,427,685,767,656,532,322,827,890,793,993,669,509,440,120,978,799,748,725,600,924,566,152,160,940,521,589,965,584,386,610,857,987,759,807,245,743,587,290,856,497,29,15,69,220,416,684,139,415,229,87,224,829,284,242,575,474,565,279,904,594,132,139,416,911,433,932,32,489,139,327,606,19,975,867,821,831,352,40,679,829,456,60,219,622,777,357,352,840,667,761,680,100,53,808,764,405,816,436,827,264,228,129,333,800,950,641,833,906,650,619,245,791,878,3,480,963,218,805,44,955,144,743,80,227,875,990,406,159,86,254,723,813,226,711,264,667,354,719,307,968,243,997,999,739,524,673,986,279,403,629,210,806,939,197,332,399,151,691,382,286,856,926,496,935,459,59,684,659,791,270,183,201,590,36,597,951,748,71,344,91,201,1000,231,862,575,116,513,190,829,627,251,27,239,640,928,129,787,471,559,9,628,113,20,303,194,983,41,509,346,67,596,294,416,985,530,62,497,875,644,83,499,479,852,619,911,315,718,810,652,612,505,88,48,707,878,864,638,412,966,142,998,303,861,232,598,575,832,140,181,962,161,177,205,843,715,305,662,261,707,786,88,527,419,476,936,203,610,25,537,50,347,595,296,302,812,722,169,666,966,563,340,582,7,803,859,863,77,593,87,470,227,464,751,658,606,488,559,75,460,662,587,688,27,584,455,601,285,417,490,75,397,364,432,975,1,674,249,577,878,84,910,634,625,647,594,752,619,723,283,175,416,994,962,131,894,108,275,368,659,280,511,270,708,870,435,922,3,390,166,300,254,936,620,331,429,351,556,409,34,92,904,155,649,951,730,112,186,760,10,523,739,921,817,169,399,288,112,592,359,463,742,177,956,877,657,791,688,421,671,416,954,319,17,299,582,336,748,320,130,12,633,407,333,539,110,186,552,395,29,574,842,199,366,201,452,380,973,411,326,393,234,129,861,204,749,14,916,258,848,613,387,837,877,92,800,882,403,247,673,179,565,458,540,861,66,635,30,521,124,20,491,352,751,152,721,789,959,563,657,227,394,838,351,80,749,971,809,884,299,546,532,435,456,467,162,382,849,784,709,512,174,160,688,530,948,151,973,272,643,888,709,228,474,552,568,644,766,115,89,494,702,765,648,67,486,21,701,436,293,742,985,711,454,258,676,459,986,73,903,823,726,583,820,889,67,808,150,735,588,272,939,790,503,883,97,957,968,647,874,30,39,80,583,358,870,570,881,643,938,119,980,500,430,788,137,869,987,736,718,926,571,371,155,51,16,805,944,279,251,513,564,218,957,789,30,616,162,927,602,578,877,665,154,165,623,706,838,316,186,970,790,159,353,886,905,808,2,560,942,887,256,465,692,352,149,344,76,850,623,306,701,332,866,528,578,60,393,954,447,951,400,674,944,475,371,971,34,710,643,304,805,330,826,520,992,135,649,362,690,405,915,539,732,262,892,315,73,858,319,740,286,984,657,170,190,839,369,365,72,202,67,488,335,387,474,468,987,836,528,602,66,1000,221,259,322,9,941,912,637,291,711,304,33,832,156,297,43,744,522,169,760,805,317,403,380,525,536,662,939,158,236,345,844,484,486,594,550,942,19,790,679,397,292,172,282,680,143,524,782,507,786,981,602,467,465,901,525,651,872,11,62,860,929,538,859,867,707,689,442,902,865,18,162,176,351,229,132,234,976,773,362,590,141,440,214,158,639,375,179,818,333,800,550,258,116,917,408,550,396,477,313,413,900,936,724,479,591,905,223,90,548,525,0,168,166,146,274,757,915,792,406,48,897,584,770,4,926,689,299,249,517,998,262,275,378,470,843,602,426,929,525,58,839,29,479,294,316,146,167,816,552,719,767,606,608,43,215,976,154,682,494,809,847,271,381,555,992,8,164,385,570,889,984,497,865,418,976,405,54,849,112,64,929,301,416,587,944,69,420,59,739,979,615,781,423,959,577,181,777,443,762,436,316,704,1,318,506,600,62,267,76,225,983,806,510,506", +"17,984,668,675,115,549,144,182,638,29,430,428,15,991,371,769,59,577,123,734,846,901,498,541,966,319,768,211,445,714,21,638,268,257,476,597,112,980,711,998,208,243,289,400,937,249,714,494,909,312,653,173,532,6,203,97,504,470,307,420,392,38,122,446,783,877,336,642,367,330,574,45,570,744,539,146,651,615,347,932,947,226,656,993,302,433,582,812,199,519,410,655,406,703,459,759,172,200,261,20,662,419,210,285,221,285,586,971,798,146,80,670,618,577,956,806,46,855,631,845,142,304,747,63,428,634,167,925,829,720,814,264,167,580,726,163,648,116,721,823,402,568,396,574,566,681,440,780,385,325,903,251,546,86,389,710,360,168,899,101,694,624,422,445,859,143,836,421,337,67,925,658,124,974,52,584,116,296,957,721,181,774,828,46,189,903,382,523,756,361,547,931,64,456,562,361,716,469,864,727,838,784,135,143,343,401,362,518,450,340,772,935,224,205,776,620,380,831,765,930,647,463,328,67,908,930,851,432,995,202,629,955,39,339,313,834,83,53,191,69,642,194,966,571,603,359,226,572,908,823,243,16,779,680,550,827,641,242,946,383,337,603,588,670,144,473,154,921,762,347,177,183,897,44,261,178,653,437,248,60,957,911,595,247,731,546,696,585,992,900,225,109,432,449,483,460,523,204,166,229,406,337,668,633,524,778,115,92,137,708,316,5,988,571,497,75,560,515,674,755,971,415,378,903,414,436,302,890,17,738,38,643,150,781,302,71,649,268,158,700,122,902,929,510,125,298,595,234,619,929,95,890,848,746,912,35,522,773,372,107,602,471,665,476,119,157,102,19,120,714,834,595,685,670,149,238,223,639,316,439,389,92,727,657,544,555,48,17,443,17,376,530,642,877,553,348,942,657,702,818,978,916,444,242,27,883,615,275,475,515,470,595,561,163,579,796,486,116,311,342,628,322,858,313,405,61,674,519,864,469,977,773,224,686,765,869,731,447,147,502,980,331,701,127,344,173,243,917,4,829,610,189,432,343,77,157,251,720,634,106,253,438,665,499,634,183,899,890,90,185,186,634,241,791,898,174,883,412,21,168,77,346,941,188,535,271,861,368,980,406,189,855,594,7,296,743,910,74,908,799,54,229,931,394,376,31,444,577,297,823,596,976,346,232,896,834,255,5,844,29,359,19,450,297,517,684,24,229,129,568,234,852,142,271,169,627,788,990,400,913,275,698,801,828,541,354,544,499,188,224,911,969,736,483,846,926,902,920,533,341,953,972,777,159,592,72,381,192,950,134,806,697,708,399,929,974,60,275,431,323,34,369,874,245,323,656,975,616,806,910,533,543,853,740,183,727,313,906,889,470,526,210,919,938,248,121,310,230,263,63,146,203,854,236,154,446,85,220,205,580,505,951,139,257,573,579,345,364,281,513,331,665,879,144,149,627,878,510,631,739,181,799,145,252,354,696,379,193,553,315,866,827,838,463,301,590,769,490,930,419,272,306,293,842,396,844,140,601,999,677,221,68,64,152,973,286,815,732,998,975,320,765,478,822,116,6,560,668,107,551,293,463,899,67,454,423,782,520,920,402,607,15,193,346,57,142,808,691,499,980,478,120,301,700,504,473,451,745,752,410,311,949,478,610,420,173,603,920,604,419,670,109,293,901,30,80,841,559,126,140,425,945,5,945,324,848,687,421,677,876,711,30,556,3,361,275,449,978,427,836,840,43,166,598,396,363,736,307,567,931,965,585,801,589,426,765,578,228,995,721,410,399,216,435,852,578,847,613,197,658,727,755,70,579,730,523,426,977,200,407,318,149,455,379,301,726,613,188,532,33,206,466,87,872,371,184,752,735,850,321,750,545,201,560,652,358,319,370,522,829,975,68,132,536,956,647,801,844,501,146,349,33,176,684,319,192,917,512,955,850,15,148,177,863,95,661,55,913,803,775,921,384,468,408,1000,727,910,20,857,473,342,533,800,231,369,141,107,31,163,251,233,796,827,489,434,601,767,323,229,269,190,173,852,353,114,252,168,0,249,4,826,144,428,435,309,234,100,647,730,950,297,581,80,367,55,126,221,369,125,896,98,334,501,690,847,990,936,953,253,408,657,68,669,267,182,710,794,562,199,24,582,328,502,980,477,137,637,681,708,160,982,577,997,107,980,773,494,68,360,649,769,276,948,159,610,880,739,859,915,891,770,35,501,589,531,994,311,719,304,585,291,330,287,833,857,256,129,740,532,361,608,809,475,386,653,838,123,505,231,997", +"190,96,888,855,941,15,272,852,464,632,856,883,791,862,740,886,747,807,795,858,196,302,81,382,242,710,723,775,783,884,874,853,557,503,769,529,897,757,498,581,101,884,343,613,474,328,409,937,793,404,33,700,884,618,846,843,862,427,288,614,269,956,884,15,382,442,878,929,772,414,492,814,448,237,132,357,201,452,954,45,190,754,5,449,51,283,667,270,120,338,59,400,486,447,683,720,179,385,549,221,668,300,4,435,148,17,603,948,101,478,302,732,299,662,597,607,342,992,329,446,667,182,252,39,141,27,866,720,671,279,684,123,769,582,887,487,118,884,142,346,345,380,906,737,648,752,228,233,158,443,768,647,388,279,718,454,931,541,194,570,433,944,380,636,507,390,38,820,864,159,867,335,994,354,289,221,30,357,55,26,681,855,851,193,97,615,865,864,473,801,741,538,583,240,890,820,302,465,565,542,724,664,541,507,417,308,4,226,648,954,340,447,572,490,692,173,437,934,82,538,816,89,50,452,777,464,38,194,946,616,923,550,795,275,261,253,1,534,998,410,250,646,221,680,87,714,332,246,365,167,618,521,160,791,559,70,406,362,681,669,867,576,758,633,645,475,464,3,571,530,867,605,312,194,809,414,995,313,225,357,97,778,193,722,598,536,263,196,205,414,278,976,694,900,205,576,181,6,456,377,811,95,786,431,70,344,547,70,264,99,654,462,802,925,902,790,586,315,891,563,119,20,343,16,758,56,491,957,758,865,116,746,653,158,274,583,229,476,211,439,224,801,386,443,350,217,284,400,535,20,424,777,500,959,625,172,912,68,677,842,728,58,956,828,207,824,11,898,192,873,237,276,890,276,891,576,450,673,107,647,640,785,358,571,30,878,247,529,650,391,739,548,157,888,578,394,902,148,789,468,169,449,952,484,471,210,559,864,421,421,623,898,526,368,359,562,637,146,676,690,639,811,540,80,802,754,69,638,696,462,419,771,744,435,905,792,818,164,232,94,585,909,384,368,889,415,538,305,89,717,578,890,593,427,463,726,249,800,237,752,443,382,789,471,531,158,132,972,887,698,116,611,43,331,97,705,528,833,560,750,405,61,348,887,246,28,703,752,835,39,304,721,937,658,289,29,412,696,490,808,855,803,8,188,587,243,856,249,785,393,296,389,760,380,858,50,380,918,894,350,688,979,82,405,966,249,250,523,370,612,107,708,283,640,408,523,480,55,781,515,727,431,258,909,268,347,944,849,332,856,810,826,449,377,328,766,344,834,765,167,780,786,975,973,362,238,75,807,213,267,183,233,284,115,969,834,365,696,534,781,127,272,105,939,185,23,460,863,220,480,664,719,393,631,39,109,618,811,153,790,455,37,34,689,49,852,382,581,848,265,773,125,742,141,28,392,23,485,745,930,75,200,931,142,999,398,468,297,443,906,190,201,813,172,821,608,832,208,858,427,135,367,367,260,152,676,74,304,774,993,190,463,291,852,272,513,244,201,835,564,805,102,302,381,778,260,605,347,869,356,742,694,312,167,861,772,722,559,429,376,638,25,853,44,135,818,958,913,304,301,210,659,993,130,735,346,582,615,207,896,489,385,51,767,325,688,286,13,958,391,943,158,79,870,724,702,74,346,340,681,311,762,176,283,257,768,576,912,229,801,931,176,35,287,764,64,689,572,686,463,850,407,433,504,400,951,354,503,538,569,330,113,220,633,104,874,647,185,88,460,527,530,996,180,805,952,965,16,210,949,3,363,856,527,616,362,785,523,728,838,469,638,976,273,838,270,158,239,464,298,114,477,125,979,78,240,253,244,143,586,710,617,73,395,867,177,289,924,427,599,553,913,24,660,213,939,350,807,983,191,611,957,981,730,503,28,54,50,946,814,137,916,484,592,884,133,97,371,403,645,567,287,253,351,316,384,780,106,25,60,185,915,428,868,2,895,605,537,759,463,78,887,572,968,19,943,635,531,903,129,796,906,361,498,709,102,142,657,73,184,411,323,5,692,201,176,445,69,229,897,281,501,941,951,485,507,166,249,0,95,420,149,772,403,930,420,872,976,256,78,200,813,675,893,245,619,131,595,335,875,340,824,621,628,377,10,992,243,835,223,672,272,981,594,793,92,446,714,852,633,258,262,569,344,484,826,629,747,697,351,662,629,166,485,452,815,652,433,501,799,552,795,34,339,268,533,147,802,249,130,334,203,373,679,7,459,141,321,487,934,310,452,716,630,997,556,91,111,43,166,683,923,528,523,907,276,261,79,458,201", +"952,757,467,933,795,535,144,159,297,823,663,66,33,112,904,647,729,902,531,653,534,326,660,775,14,151,55,147,143,837,829,829,256,710,513,646,420,543,416,821,88,681,840,337,191,600,756,703,763,407,473,133,847,773,261,667,326,339,986,621,73,208,298,585,744,162,784,713,946,454,144,604,711,132,118,518,790,310,559,326,97,358,992,888,452,879,683,838,599,557,641,573,874,566,238,794,365,163,788,908,375,362,285,749,646,523,508,453,473,505,586,258,869,467,718,448,56,603,713,911,864,133,483,956,699,803,596,684,323,478,150,509,943,702,84,680,560,343,654,853,473,580,947,957,618,140,205,504,245,638,247,504,107,109,458,879,540,712,928,314,692,65,575,845,456,108,586,610,445,449,527,945,596,282,294,866,203,893,131,100,125,88,22,402,460,855,361,562,521,260,86,339,394,784,564,498,690,758,152,248,77,246,178,929,24,982,459,686,794,812,329,681,716,437,432,605,640,909,862,990,761,430,938,308,210,991,149,975,431,522,594,626,826,815,82,595,661,754,601,544,333,922,726,442,286,184,343,188,699,333,228,688,466,380,915,365,228,982,603,145,774,40,672,259,370,153,821,87,255,730,450,838,811,769,940,728,724,158,519,297,672,99,848,543,870,153,923,45,182,210,999,875,688,146,8,804,524,39,570,145,936,330,962,151,545,949,851,775,290,857,735,34,330,597,635,487,738,847,765,584,42,651,883,299,747,238,886,179,889,494,635,951,685,572,704,661,476,2,6,221,410,775,101,72,604,892,740,183,794,42,32,189,519,640,705,254,448,990,527,738,502,719,324,142,202,235,159,106,133,156,57,111,170,497,357,882,822,270,480,925,237,37,47,433,115,458,146,732,503,471,54,427,747,10,279,856,840,478,566,17,82,325,77,98,272,173,513,688,34,800,563,246,758,174,522,399,800,846,520,637,265,935,105,172,292,714,519,292,433,958,387,231,106,498,816,752,512,349,363,303,831,875,271,744,392,685,372,162,291,285,553,320,821,627,328,350,162,514,929,676,129,104,799,161,645,246,745,190,341,122,628,572,587,188,457,790,680,565,548,417,411,381,542,809,949,800,613,600,626,93,49,12,572,837,524,433,72,435,998,362,715,46,975,365,365,727,300,651,494,292,659,787,548,846,110,835,795,543,129,884,314,859,718,463,710,183,387,8,372,206,76,23,808,953,716,721,104,734,724,579,921,79,157,377,179,72,544,64,843,245,960,974,488,522,749,945,937,879,969,894,868,984,465,76,622,949,389,185,476,149,29,38,665,503,950,692,67,521,579,632,370,170,533,886,319,305,202,349,4,180,312,760,761,874,144,501,252,527,742,67,813,161,657,670,987,435,731,530,34,314,744,534,655,110,232,666,666,238,628,81,796,619,238,840,390,109,896,913,273,553,447,538,610,827,371,876,431,153,333,525,800,359,352,372,907,279,979,669,238,696,841,912,724,57,860,866,443,224,19,408,340,471,798,734,586,560,669,542,283,659,401,722,20,65,392,198,500,379,90,870,838,182,477,242,309,105,533,323,740,661,795,309,208,809,376,450,930,901,23,311,519,634,884,799,296,759,246,639,482,763,93,783,29,55,454,855,217,526,312,234,652,798,403,362,992,918,210,225,556,339,29,78,899,971,252,670,777,586,869,421,354,822,196,755,180,333,48,238,569,531,103,746,791,570,55,253,404,991,634,869,849,872,311,463,263,73,845,155,156,499,215,734,682,660,771,166,734,202,459,757,233,368,929,402,552,25,202,229,556,850,429,723,64,356,466,432,684,760,176,419,721,511,626,757,618,275,689,717,65,2,60,942,267,441,951,103,76,170,477,543,629,394,318,508,116,81,133,49,613,531,454,529,663,904,703,506,642,691,761,241,639,68,69,989,190,925,966,247,15,243,844,900,107,871,274,821,769,149,525,856,830,488,759,621,429,432,731,209,170,54,925,655,719,703,837,123,777,211,792,265,76,704,349,552,45,956,663,774,398,696,388,691,905,33,773,717,146,4,95,0,868,155,573,250,220,658,776,127,589,841,405,191,477,356,175,23,459,643,627,787,573,166,925,348,777,936,590,963,198,875,619,875,531,258,180,715,581,831,598,288,921,17,245,453,443,700,17,926,640,966,826,358,822,16,566,372,332,33,285,813,413,410,678,237,957,972,171,448,838,638,13,339,837,557,377,477,570,322,931,811,961,198,191,127,638,57,745,454,947,969,610,232,608,440,788,822,682,684,616,605", +"370,77,799,133,565,981,895,225,72,196,139,282,461,577,100,196,716,742,255,921,839,922,719,504,378,140,776,437,972,215,171,803,870,435,854,370,109,811,328,440,619,786,986,524,156,859,726,44,387,74,987,990,659,825,691,498,528,412,133,845,986,427,425,252,571,967,481,942,106,989,908,26,93,539,339,523,381,975,84,826,453,955,453,139,766,483,25,208,36,748,842,986,956,310,802,963,30,236,786,282,625,695,920,809,905,619,237,107,111,605,255,529,247,581,416,892,833,755,941,683,899,216,458,767,682,988,279,486,909,58,394,656,827,813,461,318,174,85,754,945,934,654,189,331,955,80,507,367,791,917,610,490,199,384,327,748,37,432,735,649,365,97,363,997,408,994,143,731,956,810,968,421,369,793,883,806,969,927,334,173,975,673,140,493,242,201,237,14,697,365,314,395,341,730,342,600,854,813,414,792,785,44,798,454,436,685,956,969,20,238,335,759,74,135,484,392,800,775,863,764,911,317,414,367,980,926,959,501,713,462,321,332,912,946,363,113,587,408,454,271,600,343,228,994,112,207,946,183,222,858,542,515,88,300,541,82,61,946,833,235,50,31,663,547,595,431,218,852,656,550,22,969,198,480,847,298,454,86,107,715,699,505,89,403,582,645,770,310,797,415,317,198,787,319,574,123,574,106,785,519,703,8,937,506,626,674,34,388,416,776,350,805,895,884,814,380,557,599,342,166,327,306,122,940,754,16,74,372,180,268,766,723,116,66,147,244,355,996,242,812,183,677,871,112,879,481,579,105,954,118,518,15,149,759,679,458,182,770,231,303,915,632,843,973,256,623,999,524,959,670,473,346,943,289,203,559,880,113,443,150,729,20,49,760,88,528,847,362,984,990,397,627,329,176,624,21,225,454,775,810,426,24,687,526,978,988,454,312,681,727,963,399,488,119,342,827,587,165,694,958,28,48,63,523,246,948,37,59,895,817,19,696,290,510,210,598,233,958,59,485,720,397,595,93,834,242,713,827,246,724,127,157,306,569,283,672,205,902,663,184,988,553,610,77,50,886,761,776,103,364,780,743,735,64,345,699,774,831,604,286,103,847,122,460,192,975,352,542,982,304,515,815,373,937,101,439,369,880,103,287,277,336,371,447,754,260,110,654,892,547,651,569,915,112,741,334,547,81,955,437,29,316,683,407,981,372,95,325,981,364,648,455,34,293,193,654,876,670,139,384,835,424,395,13,278,448,449,614,720,834,593,306,655,130,791,733,796,669,206,49,3,740,954,983,604,400,670,691,227,633,601,355,438,81,235,117,524,454,704,37,310,172,315,246,556,829,954,67,316,872,585,694,632,219,350,231,653,470,965,826,867,419,534,875,545,413,854,88,500,816,342,166,322,481,276,468,78,949,724,471,91,55,512,587,691,843,680,965,323,699,255,203,274,437,137,576,484,515,899,178,285,674,149,657,662,471,7,433,334,556,404,615,494,993,541,224,537,266,614,825,113,638,890,736,795,145,396,747,537,475,565,609,830,888,975,280,902,48,542,239,691,679,263,585,447,571,219,424,9,715,834,431,150,138,243,644,165,507,162,976,412,486,115,651,929,910,665,92,125,670,262,10,893,90,300,898,958,551,320,162,654,541,439,767,417,211,292,807,350,620,639,204,54,389,505,687,969,422,813,926,311,905,155,652,188,333,497,535,971,670,159,483,555,366,772,974,479,549,478,223,821,866,696,782,123,755,278,387,345,810,879,410,485,302,776,151,741,970,147,277,254,943,30,249,323,662,113,220,426,769,857,819,846,448,996,292,588,37,132,212,917,777,329,180,562,939,79,44,45,562,941,565,960,718,841,580,468,844,666,375,956,372,726,664,861,314,338,503,227,259,197,530,526,43,863,691,79,92,585,708,755,731,3,862,759,326,504,135,5,516,918,689,818,370,227,322,511,699,789,946,615,605,659,8,439,38,900,841,990,534,75,793,731,933,556,671,110,360,858,128,121,191,535,405,124,56,481,272,394,121,551,573,867,365,55,448,274,826,420,868,0,418,169,935,533,616,169,985,798,417,693,836,45,350,438,444,83,850,864,327,89,128,635,736,270,820,232,641,805,491,475,676,473,862,86,74,700,325,412,485,990,633,627,894,296,177,568,122,681,872,653,994,59,51,611,238,927,413,906,564,508,370,956,364,487,559,899,958,488,617,475,74,796,195,812,515,834,135,102,708,926,746,706,373,301,63,954,692,336,548,183,513,394,294,31,34,242,39,91,265", +"464,843,429,489,101,21,336,774,375,477,334,832,487,958,25,838,825,823,235,868,524,371,154,787,135,522,767,691,428,975,609,482,340,24,331,432,217,348,491,952,557,649,399,858,344,980,980,524,463,951,357,724,69,252,825,33,985,235,830,237,98,745,312,172,527,111,603,827,464,854,690,570,209,169,778,637,229,822,626,340,784,66,133,325,344,125,808,662,461,989,378,457,729,577,296,698,328,368,136,893,298,312,643,220,699,666,379,70,607,151,252,519,814,558,161,662,238,738,12,998,639,158,468,585,711,369,683,691,99,960,994,495,862,98,135,500,926,497,22,961,944,96,831,842,790,922,948,49,779,73,890,494,26,179,478,25,585,316,134,198,858,937,212,787,172,368,185,741,728,178,301,346,302,959,198,596,179,760,67,306,823,477,852,981,335,534,931,454,601,601,973,367,98,935,511,608,973,760,418,922,253,720,477,480,206,798,941,666,871,478,3,378,612,856,116,396,565,638,387,209,232,455,960,35,528,846,8,721,722,444,146,976,583,366,401,16,453,907,339,488,457,629,338,362,945,157,172,67,239,990,528,993,964,609,956,941,666,728,521,80,599,93,99,595,468,716,494,472,214,98,969,985,729,535,672,680,918,133,361,895,594,486,601,599,518,711,399,325,707,913,601,773,129,343,950,990,192,894,943,846,196,888,947,833,434,204,415,336,688,647,910,266,826,511,972,487,678,231,691,249,4,835,462,429,461,525,942,792,467,39,150,276,282,469,314,462,381,112,476,544,297,808,952,367,248,213,36,894,690,549,509,642,868,895,117,63,452,873,178,437,418,450,794,183,731,387,291,340,748,358,830,157,367,157,974,853,546,303,299,707,433,823,763,627,266,376,91,38,368,247,586,123,387,123,733,485,872,328,236,206,638,889,104,82,432,550,674,225,818,976,226,458,307,133,592,661,510,85,26,462,210,793,683,942,575,971,833,651,755,848,481,180,325,314,448,103,171,277,374,253,633,243,31,397,114,682,218,185,410,234,766,380,647,189,511,722,853,107,175,181,78,562,948,983,822,577,560,858,585,449,401,31,594,572,165,737,672,754,431,872,649,963,707,29,524,188,60,181,18,564,268,693,915,439,242,27,459,327,463,706,29,657,539,168,823,55,892,141,816,356,430,700,871,511,124,292,634,723,709,131,959,221,226,316,403,304,141,928,575,76,656,756,179,571,713,593,593,920,366,311,579,377,633,840,984,124,848,354,949,571,644,913,165,91,297,390,451,272,460,298,229,986,323,824,395,714,99,235,828,184,610,532,293,748,125,247,237,879,869,279,36,713,580,281,388,200,890,797,620,485,205,702,963,299,505,181,290,774,535,382,530,822,694,81,10,80,725,429,16,86,896,545,505,559,818,518,493,631,577,451,90,738,208,890,437,198,245,782,778,271,277,555,99,50,604,83,287,337,752,735,921,49,955,957,668,10,172,366,67,73,769,897,789,780,957,109,359,572,677,413,475,461,816,749,528,711,533,877,149,77,51,121,940,527,94,872,898,639,56,636,870,593,488,27,816,221,640,582,527,420,169,543,882,390,432,894,721,120,433,179,834,298,125,903,614,737,687,771,690,26,176,123,352,488,994,524,215,508,24,538,136,610,788,116,318,845,566,323,604,680,372,740,944,443,694,997,536,240,259,455,480,743,717,969,567,439,609,361,817,69,162,301,113,725,793,928,527,937,374,233,827,369,829,161,857,853,362,491,761,667,646,809,849,401,90,492,35,698,556,38,729,907,442,380,506,414,171,524,329,21,745,268,522,65,510,204,851,335,221,869,789,745,114,77,559,486,246,261,467,255,843,549,863,507,377,701,463,302,283,409,356,184,894,316,196,425,772,24,291,315,198,637,684,117,193,466,934,454,380,321,255,38,887,102,111,822,39,905,239,78,397,569,295,797,902,767,192,397,824,8,863,615,10,70,224,290,684,609,340,781,749,649,808,773,136,546,979,870,8,337,407,321,239,377,394,209,295,600,755,301,877,423,909,208,464,101,757,144,149,155,418,0,366,546,781,537,563,98,505,537,286,86,444,933,896,55,590,517,302,621,280,410,972,800,799,76,114,271,651,922,771,722,936,724,450,216,938,598,249,583,562,972,513,357,777,164,841,297,38,275,801,13,578,603,857,981,469,585,547,951,504,557,483,326,427,903,881,649,426,125,476,482,689,963,736,149,526,874,521,465,517,946,942,641,318,974,622,225,385,765,625,177,665,78,409,79,918,167,496,463", +"291,367,25,195,837,921,630,929,203,122,548,563,94,338,77,211,237,25,634,796,781,177,586,367,767,601,928,633,120,848,331,86,461,394,41,743,404,389,275,885,87,804,161,378,82,975,331,125,940,898,820,575,12,871,439,63,687,244,932,148,49,984,34,665,954,241,54,859,145,788,820,599,665,704,686,567,231,384,152,780,704,872,754,179,633,951,804,855,341,240,977,534,570,568,558,845,264,241,194,412,500,943,372,744,147,516,253,456,827,530,129,98,242,524,500,86,653,958,50,547,809,41,349,593,488,672,281,627,458,142,268,637,923,725,413,397,919,398,690,909,885,983,898,596,938,117,277,302,281,414,33,180,585,632,828,819,943,640,416,815,492,644,979,304,546,83,874,826,245,880,213,400,56,816,179,543,621,846,922,571,828,455,402,662,397,148,594,267,847,590,57,421,681,326,560,595,514,588,557,865,10,707,346,834,330,398,826,967,209,200,113,681,931,270,277,808,141,247,152,894,918,992,122,205,615,549,438,341,700,396,130,765,830,687,453,557,718,90,372,509,372,469,679,785,511,805,832,312,224,389,210,436,550,389,341,736,58,806,342,494,753,729,497,940,990,328,614,654,555,743,807,488,799,70,167,822,649,889,362,666,740,146,100,384,288,493,468,725,828,297,297,707,77,361,81,569,144,819,22,196,684,794,721,673,519,192,105,113,308,555,289,576,278,462,816,344,542,876,590,760,597,537,971,825,780,69,429,698,813,392,871,207,606,504,474,99,799,686,685,314,858,129,370,238,677,790,980,221,513,180,966,366,892,421,870,921,364,8,236,189,627,264,62,826,339,607,192,645,454,255,9,321,816,719,951,296,498,42,104,391,699,656,846,530,851,824,773,102,845,899,310,447,606,791,997,316,894,333,320,521,244,64,267,347,959,327,991,639,445,602,838,191,606,692,425,657,473,533,688,916,250,535,464,269,329,130,666,100,989,121,823,573,189,532,367,894,154,53,347,8,454,628,199,670,616,864,566,280,69,36,382,679,104,1000,920,670,351,761,471,613,714,798,187,693,916,63,23,211,380,416,797,330,900,485,148,143,832,738,390,839,499,639,564,248,917,323,883,394,918,927,237,822,134,257,523,211,335,804,358,388,202,313,608,347,555,821,88,734,893,721,761,763,399,781,678,66,296,803,92,272,509,585,614,760,628,742,532,545,783,744,343,477,490,821,595,543,549,986,183,278,38,959,314,797,583,321,356,500,580,164,154,129,204,318,642,395,904,175,118,711,773,181,879,957,797,180,94,294,343,586,164,866,81,866,116,373,257,129,788,933,293,296,26,962,943,141,793,46,924,633,980,623,9,56,549,526,588,70,1000,571,993,470,856,436,700,489,445,304,683,384,93,223,828,286,71,778,317,375,875,811,114,862,654,11,64,165,926,698,692,944,549,714,729,917,260,920,655,728,424,500,235,765,973,556,96,239,209,198,736,980,23,449,114,763,599,288,82,459,200,142,865,739,949,969,23,38,692,450,542,190,477,28,633,12,68,140,521,182,924,702,153,845,181,997,285,192,19,279,885,183,338,904,219,695,685,342,329,535,223,279,726,787,561,807,747,65,713,628,276,79,545,952,811,916,260,965,229,103,818,89,606,418,722,347,18,586,944,844,190,615,815,588,556,35,965,396,702,938,851,828,82,667,566,342,37,464,916,52,4,813,897,391,291,164,991,5,929,675,901,569,319,910,559,582,236,915,976,305,369,893,567,6,218,576,798,382,427,774,754,30,759,200,275,201,425,15,185,453,587,980,699,554,95,313,706,508,335,311,234,220,78,710,276,252,183,269,834,751,805,968,23,149,756,659,159,333,871,993,356,743,598,45,71,88,230,574,32,257,12,933,443,929,864,789,23,67,23,309,363,473,206,745,342,916,295,666,28,935,980,552,40,378,606,432,301,709,874,241,44,869,728,399,774,970,989,713,425,642,500,391,181,129,109,566,876,572,817,777,753,194,853,393,728,61,498,474,744,195,420,651,805,993,773,719,516,201,915,428,772,573,169,366,0,616,890,273,395,383,911,367,913,430,523,57,503,358,687,679,901,904,675,538,900,451,977,294,564,760,300,25,388,923,899,297,942,377,874,230,619,274,822,743,972,543,47,80,130,856,750,234,738,332,668,733,336,205,252,8,488,929,358,884,969,975,698,478,752,156,234,598,197,280,686,696,767,64,384,404,586,516,992,257,428,187,906,838,48,384,184,551,289,901,912,145,652,872,509,560,976,499", +"918,32,817,268,655,188,716,482,869,35,278,204,376,19,458,867,555,826,454,469,282,510,967,950,483,241,609,49,599,159,828,523,947,935,401,805,639,291,719,110,413,565,615,27,625,975,4,828,388,857,205,189,995,809,599,138,138,180,640,943,843,899,819,728,113,324,878,631,209,509,820,566,314,720,441,644,303,525,591,106,713,628,806,510,454,899,146,443,877,129,19,943,788,248,314,163,388,168,748,779,886,168,703,268,337,569,948,464,395,380,561,894,637,63,664,949,338,994,680,982,129,430,385,404,499,350,80,239,896,942,530,626,786,213,451,627,245,850,52,116,778,336,368,900,557,34,304,521,52,975,261,328,632,421,942,379,672,943,150,722,136,889,717,68,684,177,569,965,744,99,249,345,180,894,659,909,763,298,702,452,49,231,119,579,83,310,351,640,857,133,552,782,678,506,174,873,814,381,38,256,571,490,69,852,654,565,417,129,327,55,822,168,977,671,853,702,246,994,957,802,225,97,278,232,284,670,705,490,285,854,795,803,837,675,543,10,821,142,60,693,98,264,982,476,579,656,441,354,651,457,465,235,341,751,178,916,982,841,766,120,706,844,64,743,334,979,747,254,955,852,395,238,70,900,721,601,121,362,443,999,629,161,76,950,993,964,607,954,830,334,407,845,791,529,954,211,486,746,821,490,965,202,78,754,632,953,844,364,939,914,210,441,557,718,178,65,542,828,260,260,200,737,308,992,597,237,38,280,691,248,145,482,325,788,522,745,63,576,628,133,733,498,871,956,987,847,580,922,416,562,412,370,901,611,427,277,59,81,338,719,972,591,128,446,869,499,739,364,595,165,552,560,44,689,389,745,913,431,851,257,617,676,684,101,156,636,465,588,144,627,746,356,445,772,668,343,801,84,5,379,884,625,153,101,590,819,781,524,732,51,514,963,280,73,104,324,808,415,957,476,777,463,296,423,821,431,340,532,735,741,745,417,607,784,845,568,981,952,952,855,582,81,990,740,373,184,533,790,422,919,303,38,614,597,235,377,713,690,587,929,579,376,222,332,241,638,878,994,519,664,233,313,592,396,625,849,13,661,300,134,850,767,751,170,977,557,899,608,362,71,520,298,389,409,572,135,601,179,178,33,150,923,846,434,59,148,515,851,845,591,843,1000,12,982,161,742,94,894,578,568,993,521,311,999,236,255,659,522,101,361,102,402,614,975,806,184,170,506,564,222,577,90,874,371,249,975,332,936,770,659,427,673,379,249,950,430,550,336,970,363,390,778,411,289,72,745,368,267,206,400,250,957,448,395,877,357,399,806,494,865,353,179,843,7,701,540,470,343,80,276,628,733,417,494,28,696,325,528,822,359,517,171,630,694,516,544,172,937,251,614,964,317,864,718,589,218,676,220,99,532,125,627,400,255,516,26,300,821,51,754,107,607,310,830,454,788,909,781,1,123,923,348,974,369,909,555,570,6,499,32,350,508,517,169,900,525,699,855,239,936,513,42,161,154,809,650,602,240,599,619,482,782,633,401,521,312,913,584,560,143,65,868,502,654,470,4,297,331,934,260,556,315,193,558,768,286,405,218,299,519,85,759,389,692,983,925,750,977,648,665,677,397,654,456,508,718,457,912,152,940,595,875,850,61,743,929,809,298,42,785,984,181,882,688,614,672,694,655,800,878,549,805,26,575,485,865,340,819,156,625,39,740,630,422,836,312,387,941,734,902,585,330,648,787,519,117,349,154,295,176,477,806,88,624,447,737,249,863,12,523,708,784,606,90,93,876,909,221,522,126,241,312,399,209,54,722,692,891,627,506,774,638,273,495,842,953,27,967,349,760,675,624,393,882,401,799,318,905,342,418,467,204,723,6,407,388,212,195,538,280,651,152,378,375,78,54,533,324,761,611,643,379,335,966,311,347,786,457,193,636,103,329,21,833,64,423,440,386,972,807,746,305,500,230,14,468,36,308,898,857,419,767,372,156,604,765,835,868,729,767,995,358,696,618,768,724,693,524,799,429,913,959,585,265,685,917,792,435,403,250,935,546,616,0,954,20,404,546,907,71,709,532,95,717,986,622,534,806,601,491,520,980,788,625,156,804,264,129,183,371,221,920,749,221,671,70,254,465,757,571,391,739,223,278,171,111,262,574,656,552,821,963,971,655,142,661,943,538,380,284,343,350,435,694,677,319,256,291,397,163,515,104,56,741,20,490,386,517,910,528,40,295,861,19,906,674,751,4,743,317,956,984,124,785,284,186,560,680,208,862", +"454,840,322,776,613,345,119,146,838,504,401,155,402,132,31,370,873,920,374,602,632,718,120,128,612,74,543,407,789,298,325,26,165,321,98,973,306,730,281,188,52,470,795,765,489,686,429,78,590,831,431,74,371,451,691,831,708,270,916,207,84,138,785,64,409,922,77,942,686,904,278,240,868,20,716,842,445,173,940,213,188,688,396,302,819,60,321,545,834,781,401,734,392,415,869,665,694,400,185,187,608,487,359,131,564,54,675,497,665,696,52,591,686,985,412,29,264,219,639,99,714,397,61,285,246,358,14,899,572,59,980,154,628,789,46,140,750,795,278,234,668,711,28,433,442,402,364,130,202,558,388,280,772,194,502,22,144,155,563,513,111,850,925,928,622,848,424,898,495,84,768,939,655,23,951,541,272,973,409,981,337,854,776,556,413,426,7,561,416,417,245,439,879,683,494,806,700,7,217,34,980,284,529,283,235,733,269,732,585,111,152,762,658,839,585,906,428,914,78,660,537,913,918,99,775,39,286,607,559,850,120,801,338,837,122,289,779,441,525,314,884,219,947,860,134,600,177,322,186,589,194,623,606,147,321,464,221,67,424,259,540,805,91,575,606,754,822,556,66,655,150,615,37,191,926,661,580,965,800,13,377,153,993,625,492,13,896,736,678,867,884,753,975,148,75,894,715,201,408,950,425,193,431,139,824,495,368,663,89,952,987,766,150,413,158,224,996,606,47,888,398,674,2,516,961,905,331,365,412,238,115,530,212,252,513,189,697,452,922,716,49,847,243,148,19,54,556,806,725,687,980,673,359,949,191,65,522,653,905,806,320,153,264,531,581,522,340,422,607,686,257,706,76,440,305,995,438,605,995,260,515,180,896,15,232,811,664,322,822,453,323,372,371,684,631,616,414,197,470,635,193,465,765,118,330,726,395,689,785,454,510,706,227,930,116,524,906,335,389,585,859,790,430,663,516,177,737,418,899,780,815,641,910,932,297,403,251,954,214,576,57,758,938,502,911,487,265,836,868,606,266,527,570,359,580,590,633,20,739,962,11,214,185,999,441,712,164,659,900,56,536,538,856,992,485,308,713,807,210,952,333,846,347,765,718,12,6,181,589,657,135,636,977,648,257,907,913,165,638,539,244,127,206,265,946,721,268,16,449,391,898,842,551,560,248,467,44,495,919,812,279,742,239,697,205,209,281,554,921,528,530,970,834,326,274,17,958,259,355,908,945,469,803,715,558,106,178,329,993,119,672,693,598,130,169,52,105,499,21,968,790,997,480,941,161,429,667,888,595,515,671,40,11,953,387,291,28,980,142,764,537,895,690,894,474,188,828,150,100,617,705,598,391,431,879,446,465,268,344,232,7,223,645,455,942,620,144,122,832,155,381,913,427,130,416,963,465,654,989,514,4,421,22,826,858,729,752,159,173,910,4,393,998,151,912,927,415,909,302,425,923,30,64,70,335,52,72,983,589,641,553,646,865,872,649,986,450,419,780,32,231,779,484,414,167,626,871,850,897,133,963,721,520,113,312,988,460,90,20,34,299,485,143,605,421,674,252,758,461,991,183,276,300,662,713,351,684,895,616,227,111,474,921,282,741,669,667,941,408,451,757,942,950,685,329,412,649,651,983,848,547,69,849,486,188,783,716,71,365,922,691,76,758,348,85,269,125,304,241,532,423,757,535,333,355,415,130,949,739,714,360,767,664,263,72,38,574,727,141,881,427,256,158,88,706,26,548,236,857,420,506,893,645,54,803,587,140,394,657,338,113,198,455,722,30,377,658,582,270,293,4,726,738,354,965,439,964,383,674,830,846,452,569,178,430,125,979,23,221,169,57,609,422,29,221,192,470,472,797,266,318,671,844,853,272,401,871,388,703,275,91,496,183,775,526,475,761,343,645,453,835,965,232,585,220,942,53,826,972,988,672,110,645,945,299,727,966,717,503,372,286,969,212,617,588,185,520,93,323,299,36,812,691,172,155,486,838,606,310,541,24,753,959,198,409,732,371,321,594,477,388,160,6,646,503,909,406,309,930,220,533,781,890,954,0,847,830,126,428,348,925,744,376,124,847,139,367,859,963,281,170,14,892,560,82,521,255,304,827,809,840,251,313,646,245,592,327,675,49,251,736,291,684,185,928,530,890,783,288,994,414,974,171,512,225,182,700,849,732,223,132,614,567,721,45,148,958,130,642,51,819,460,254,366,909,691,895,862,802,167,23,381,845,729,563,776,890,389,39,71,975,61,732,277,301,265,447,739,675,406", +"239,777,339,634,991,152,529,103,115,698,840,662,68,554,211,318,723,445,737,735,431,347,260,990,372,426,175,716,271,662,635,856,49,742,707,796,202,999,556,661,542,130,640,702,173,920,773,541,360,30,717,6,783,877,127,625,365,163,303,656,181,876,960,719,209,453,198,484,779,207,804,572,225,196,788,659,526,461,462,170,78,973,398,545,376,729,254,85,353,239,144,111,116,860,277,503,836,905,19,38,964,576,321,32,186,996,63,701,821,195,302,681,965,170,353,25,867,260,605,627,103,678,628,429,741,623,739,353,665,451,268,66,987,978,535,858,970,901,969,682,943,580,833,338,603,845,317,804,599,823,433,37,349,629,668,210,827,245,930,148,426,468,818,439,868,156,401,823,745,982,646,563,65,988,871,260,151,828,29,996,195,713,982,935,279,628,879,984,4,47,924,437,742,863,485,879,48,890,471,948,823,311,233,781,525,15,369,404,381,582,60,600,648,491,416,945,259,670,466,372,188,187,839,610,837,24,21,593,637,296,637,372,301,491,830,461,483,264,896,2,475,439,502,299,464,889,123,324,368,272,755,619,700,173,466,842,503,685,353,838,348,358,193,561,500,686,407,44,878,504,419,351,632,12,76,369,643,709,630,390,928,215,700,355,891,776,826,269,92,438,159,374,918,578,19,594,672,180,960,374,885,820,951,847,642,780,146,259,198,560,597,428,994,269,974,438,540,673,244,736,755,35,339,453,273,78,522,350,161,834,348,854,211,33,676,962,888,248,492,932,70,868,545,309,556,982,995,985,501,998,999,595,122,108,355,697,223,138,131,517,895,469,937,758,443,664,709,698,930,126,801,571,930,654,861,694,267,879,760,525,368,789,687,682,405,108,916,964,488,409,400,503,39,759,29,153,483,366,605,229,203,893,791,311,851,411,267,304,652,583,39,996,627,536,879,904,656,778,594,469,986,944,200,268,77,513,911,248,535,469,228,812,906,959,503,80,628,252,541,666,185,461,102,290,905,853,953,201,203,875,507,83,632,441,274,164,3,114,956,672,180,837,350,219,288,587,639,831,266,905,862,825,153,952,659,661,528,328,69,173,56,811,549,148,569,995,483,483,944,866,693,739,928,133,297,516,618,191,326,608,985,186,71,340,895,620,12,620,228,868,978,737,876,454,985,870,612,928,206,685,937,866,598,242,714,299,253,219,732,134,563,986,233,695,37,739,157,196,998,471,420,620,611,40,704,145,730,567,974,498,332,711,162,585,503,164,493,321,88,796,9,676,931,130,481,338,235,499,943,324,566,795,201,376,215,297,630,110,862,896,789,901,906,206,845,550,272,595,349,531,36,361,6,785,748,920,985,873,217,514,465,362,276,990,102,648,670,802,215,217,757,938,258,233,138,566,919,782,535,245,326,386,315,333,289,802,580,463,198,992,984,142,913,298,501,511,957,642,752,690,433,416,979,230,548,989,111,897,553,923,417,51,999,865,52,296,224,32,462,912,94,410,7,687,300,558,147,127,226,185,765,861,938,519,232,150,63,837,984,935,306,524,977,661,262,347,111,659,362,281,61,81,23,787,32,503,995,922,954,635,537,530,195,585,730,393,798,650,823,809,366,326,899,960,803,568,647,277,435,243,598,523,248,240,166,921,293,838,123,337,3,411,228,684,457,124,550,296,392,425,752,909,178,910,350,504,608,540,57,735,914,683,943,154,190,329,68,703,727,126,352,871,118,679,863,532,999,837,200,546,598,133,118,74,802,487,238,31,705,521,890,538,246,995,716,375,237,916,508,765,189,880,756,890,6,212,71,913,990,309,165,587,745,157,151,914,751,279,143,291,617,526,760,466,804,722,455,847,782,640,310,955,90,112,613,293,894,695,299,360,569,153,838,827,778,251,968,728,941,866,16,254,308,63,746,118,448,65,514,233,630,525,831,288,547,184,26,397,445,294,388,280,757,749,248,308,387,169,123,537,658,624,110,960,181,383,777,5,164,621,122,513,910,996,143,732,183,131,880,721,69,321,995,857,538,673,48,234,420,658,616,537,273,20,847,0,421,977,485,367,369,78,956,617,797,116,719,496,527,915,20,911,440,521,876,742,359,609,748,343,752,879,379,854,261,820,37,318,167,771,746,514,429,241,654,366,812,827,231,83,888,105,574,703,432,220,635,929,695,955,47,336,65,408,147,933,803,31,583,592,798,912,288,2,668,729,600,319,426,639,182,536,310,686,298,50,925,270,184,437,710,541,485,471,439,200,197,545,144,232", +"399,640,141,871,940,612,869,346,343,724,641,450,678,279,694,460,962,927,322,178,100,235,162,209,827,295,265,49,626,273,567,8,298,978,844,224,801,767,222,388,991,94,821,96,351,434,30,982,736,847,949,899,527,925,146,275,455,20,536,748,401,427,205,576,219,150,779,970,86,592,886,847,916,756,967,275,118,593,57,320,370,299,998,3,449,85,349,406,384,861,327,624,165,656,190,941,173,330,804,605,97,796,852,849,299,685,389,817,436,874,716,795,562,312,324,107,699,991,109,745,699,235,801,795,919,339,47,138,713,708,194,673,24,437,787,599,134,869,980,892,141,432,32,997,351,573,775,98,629,464,284,699,232,892,868,522,533,975,913,780,33,348,615,227,194,588,943,127,396,739,860,870,382,24,759,622,958,481,611,123,76,353,314,149,719,170,981,285,338,567,31,278,73,894,551,594,456,781,713,866,854,610,543,883,968,584,957,499,36,295,204,670,53,155,481,546,951,828,743,612,83,407,463,322,466,983,604,395,182,802,583,938,87,336,670,731,347,698,160,60,925,784,604,798,80,316,376,486,717,664,64,552,931,538,267,443,311,648,593,112,873,256,711,791,62,439,69,501,728,579,290,421,297,128,614,8,949,840,796,849,16,833,790,175,944,586,322,436,767,196,902,53,721,250,285,594,750,788,662,315,771,214,249,885,256,837,850,981,134,723,555,171,427,988,63,806,112,36,462,813,293,16,222,914,483,777,730,896,727,963,471,106,722,489,135,159,40,601,579,65,733,72,30,89,683,513,454,385,735,250,305,481,579,446,416,824,207,837,847,984,399,465,264,568,136,665,801,836,122,560,920,857,432,337,156,146,143,447,33,689,22,50,801,46,774,914,56,886,567,62,413,193,64,658,878,257,725,184,911,896,274,895,44,478,187,918,844,862,133,70,754,729,953,289,190,227,944,867,959,155,630,458,856,995,970,76,280,907,148,221,776,591,695,870,621,435,703,582,622,616,723,157,86,227,198,258,969,494,512,822,153,274,420,673,235,885,995,670,614,310,777,74,890,746,831,254,623,32,105,225,364,595,34,184,111,671,958,239,581,770,610,487,107,810,493,303,710,143,790,196,396,874,317,784,326,8,642,588,438,735,324,94,316,472,249,126,72,762,163,51,649,610,756,99,200,289,347,760,81,112,750,708,719,632,964,103,517,109,951,591,763,807,714,612,930,316,560,29,916,630,439,774,82,73,989,135,73,825,584,7,275,584,116,94,777,576,304,615,484,201,941,564,808,109,486,317,933,533,284,848,649,686,343,206,402,713,311,444,139,440,647,420,648,913,887,897,311,359,585,463,561,330,962,134,511,163,311,377,630,177,743,361,511,915,125,629,274,819,755,795,491,950,496,105,972,102,412,740,527,573,491,521,555,844,7,88,901,927,342,776,275,767,647,187,169,379,68,190,131,219,680,910,895,350,123,504,526,919,503,206,515,928,227,528,197,638,582,313,658,440,673,285,508,543,943,771,776,10,257,288,286,660,83,981,478,593,225,35,955,724,66,90,654,287,737,902,492,495,622,742,133,741,164,619,753,893,957,58,422,535,91,879,774,946,342,792,209,196,217,448,315,246,112,577,490,227,126,722,206,187,972,672,643,787,571,874,278,105,3,892,87,549,755,247,894,401,903,389,454,504,480,850,727,53,167,56,332,164,349,75,788,512,208,487,250,709,602,937,388,358,196,938,870,86,700,961,574,733,631,140,804,522,420,524,240,777,245,560,950,601,87,685,51,427,902,766,348,413,668,769,646,114,860,384,788,167,659,776,18,556,770,394,61,103,261,632,291,413,404,38,835,134,166,633,819,471,230,410,523,804,852,665,589,896,499,720,589,437,751,198,910,605,757,366,493,629,740,472,816,452,508,807,859,949,625,251,390,419,512,731,360,250,588,397,521,335,203,370,627,35,397,966,347,32,997,640,927,927,561,362,318,648,318,338,46,709,849,920,770,711,49,538,388,548,313,145,881,921,436,424,984,714,395,643,846,586,897,100,872,776,169,563,395,404,830,421,0,29,267,367,973,765,113,831,791,155,261,243,332,1000,845,372,748,968,708,377,1000,280,151,895,152,101,190,581,857,153,810,966,664,974,706,494,767,980,811,327,16,192,510,209,42,55,769,571,917,666,388,777,97,126,403,440,340,644,985,682,834,586,717,701,617,339,190,589,302,35,334,636,134,354,474,928,70,317,639,376,402,238,867,857,957,406,649,870,421,984,872,259,455,3", +"914,38,662,454,305,888,350,260,492,445,195,248,199,710,881,593,365,381,285,595,825,322,550,857,224,371,754,387,253,314,611,819,731,880,215,527,835,201,805,650,352,611,985,696,244,538,157,949,877,776,449,292,846,523,414,49,912,363,914,329,567,22,127,663,920,56,978,904,795,499,706,321,736,175,373,31,632,891,47,345,2,121,238,567,935,31,644,197,546,146,932,311,90,865,95,763,448,372,550,657,772,730,124,733,409,383,734,440,679,409,578,295,813,965,50,863,358,14,862,228,332,950,146,38,702,490,296,475,119,329,158,52,860,107,172,51,856,423,693,884,109,716,526,178,691,557,175,629,236,623,937,985,807,544,113,363,807,893,906,366,12,442,130,456,333,757,223,983,527,893,503,904,864,353,715,413,455,595,714,382,991,510,864,158,44,5,964,669,587,123,861,701,615,877,806,497,257,366,789,913,853,307,533,416,556,425,903,506,324,219,873,696,734,977,758,88,758,381,175,951,159,819,658,338,722,672,144,290,670,744,755,7,852,568,216,768,134,909,478,885,214,819,385,137,577,232,547,877,535,465,911,112,925,61,663,699,81,66,772,804,538,637,611,916,190,408,86,432,39,657,259,843,643,955,158,259,562,784,311,681,518,309,67,720,356,492,601,229,720,667,332,368,291,340,249,257,185,510,767,682,451,92,36,383,706,278,138,582,975,171,952,450,775,227,949,379,222,881,168,893,962,970,555,918,354,559,919,849,218,847,441,829,895,816,512,483,855,590,226,596,933,199,387,816,928,25,60,240,33,822,650,834,440,994,183,569,857,510,758,376,638,183,617,254,265,365,657,890,717,824,736,878,666,519,215,963,892,496,509,950,456,450,270,845,686,966,72,332,2,636,901,914,36,424,510,465,701,210,837,387,877,688,682,153,417,191,7,251,582,296,222,69,567,559,863,198,99,262,447,890,135,446,123,469,376,894,436,863,582,325,802,278,157,869,596,478,995,927,521,556,609,989,891,981,792,972,386,249,159,222,70,361,858,934,587,195,461,169,835,253,395,820,654,422,422,831,433,801,567,115,854,989,599,343,422,227,472,106,313,841,333,248,153,522,650,301,251,821,44,888,402,180,919,954,861,182,618,662,931,993,672,300,518,924,22,774,596,585,441,723,971,69,194,654,369,837,111,262,909,518,544,168,165,530,59,366,675,908,484,810,534,205,482,753,190,546,518,914,365,695,475,628,384,809,888,578,923,721,762,276,845,937,862,231,308,11,73,443,355,890,538,643,328,374,138,890,318,936,607,201,414,606,459,770,363,355,322,359,915,716,116,500,434,668,759,434,55,545,841,523,302,662,583,519,554,909,918,435,271,558,484,451,897,37,774,453,489,300,682,9,558,79,137,146,588,738,350,211,367,614,413,948,787,644,496,108,81,401,980,373,919,594,231,280,420,241,223,478,231,391,506,956,811,738,103,518,565,870,412,827,38,91,695,888,563,643,718,100,155,140,415,626,341,945,615,376,785,490,316,796,643,330,736,603,738,603,983,849,530,845,576,75,181,155,206,260,866,745,164,940,719,478,290,875,108,592,261,1,591,194,93,433,201,35,957,576,982,643,94,490,503,45,913,649,299,503,378,867,790,329,969,568,430,208,56,177,429,520,644,510,288,832,342,742,874,654,520,480,107,897,213,458,396,379,590,973,779,409,941,461,757,831,743,850,774,99,334,368,191,773,404,124,523,890,853,718,407,913,792,263,840,389,481,764,375,408,819,121,201,907,758,394,376,444,611,8,610,836,138,877,56,36,573,825,774,466,588,586,504,472,331,264,542,947,945,119,534,615,328,35,187,590,567,641,324,957,553,675,48,969,807,480,483,359,182,224,360,24,681,203,902,509,523,790,485,580,307,731,998,574,234,435,205,876,777,128,935,822,984,556,733,566,787,916,133,230,30,830,497,463,871,93,181,783,273,976,540,35,164,748,682,914,682,675,221,575,418,625,200,522,481,788,187,778,822,470,608,791,321,749,447,918,313,832,182,919,584,647,976,127,985,98,383,546,126,977,29,0,625,132,571,839,58,773,586,583,928,218,283,458,694,382,497,542,35,895,570,594,145,395,791,687,552,11,491,146,941,165,355,924,659,658,522,312,980,112,281,495,331,641,257,953,684,395,759,172,384,473,1000,897,140,992,88,862,773,913,93,761,900,338,829,672,872,426,607,539,225,95,10,193,829,757,842,409,204,400,400,436,550,955,89,403,605,234,419,613,993,942,689,780", +"451,541,560,976,438,224,462,114,122,628,596,775,26,565,220,874,273,970,75,41,988,874,493,427,967,474,856,220,170,909,988,995,970,663,909,343,942,872,994,197,91,746,465,801,445,465,996,618,542,340,713,679,52,27,862,11,461,166,953,189,338,488,600,364,375,821,229,325,375,885,783,708,283,856,776,889,277,698,163,962,608,50,627,625,4,79,797,799,279,97,17,947,856,402,169,957,492,177,25,945,462,967,427,655,959,142,299,582,101,570,120,171,507,439,591,958,259,412,463,97,730,675,874,605,518,99,530,96,436,589,411,934,327,468,475,755,671,838,112,193,83,242,175,614,685,236,208,599,678,299,633,952,508,584,550,954,148,411,869,512,614,33,435,398,545,363,363,170,105,144,195,112,556,981,220,759,136,114,984,422,640,991,841,86,404,239,557,105,240,374,476,838,240,680,81,724,370,567,365,484,20,372,494,942,448,279,218,210,650,594,983,180,654,408,867,437,424,183,641,121,445,581,464,723,171,224,175,978,874,495,542,555,251,819,623,848,76,444,110,640,382,803,829,810,359,186,82,441,746,487,983,271,892,723,126,955,531,400,461,650,634,435,485,645,161,959,866,714,681,554,884,207,106,271,757,443,152,258,761,113,751,6,426,821,473,150,651,961,418,37,466,994,885,120,950,661,570,509,384,327,532,11,572,313,671,450,754,597,845,292,256,90,500,226,588,756,388,464,446,656,65,45,637,772,905,247,489,190,486,497,797,555,400,235,561,834,18,749,189,767,993,153,880,164,32,782,147,616,275,994,942,934,754,671,49,478,784,865,506,36,107,552,575,381,302,774,327,69,742,498,309,96,956,923,882,490,199,784,558,933,821,562,91,554,871,373,282,725,355,974,785,719,202,225,968,615,892,600,850,780,237,26,805,196,367,336,980,837,948,382,963,621,916,224,441,335,743,477,996,247,653,51,631,60,466,600,636,257,332,147,872,174,831,243,749,493,516,832,881,272,27,193,873,57,952,554,64,449,227,676,664,783,775,78,736,925,159,574,558,255,522,890,198,522,427,562,663,630,726,512,888,118,211,653,191,576,346,380,783,554,714,866,928,989,215,182,363,752,541,213,402,851,874,883,501,955,824,32,685,666,800,888,920,634,815,536,394,325,948,242,33,312,340,317,911,914,572,712,734,909,480,339,312,826,985,866,967,418,623,587,68,98,427,815,258,460,215,371,736,299,790,634,553,886,804,739,849,350,793,725,360,855,335,837,986,419,340,258,585,504,491,902,948,71,795,303,802,273,917,974,305,168,541,571,563,276,313,903,160,557,609,540,188,691,341,560,837,600,833,652,82,516,644,992,585,350,148,596,131,483,111,975,723,771,833,912,812,510,279,640,239,511,536,452,708,380,753,290,304,683,118,395,336,900,864,238,892,976,721,616,466,820,328,957,444,411,140,149,129,703,687,724,499,439,410,790,861,236,913,527,893,558,204,304,765,302,230,790,604,666,69,413,201,725,925,186,296,751,295,767,524,243,398,3,879,459,647,157,611,677,366,805,190,38,738,298,638,889,740,616,223,649,916,119,308,109,745,706,185,659,219,658,156,885,800,449,930,794,76,711,50,418,916,655,544,622,760,863,950,154,674,640,816,909,598,442,517,8,139,595,471,305,120,949,980,982,159,228,357,629,517,129,617,114,843,502,379,646,764,579,596,300,540,946,950,611,925,16,796,566,83,775,754,160,968,430,311,720,619,387,564,252,758,170,142,750,454,151,453,312,974,944,22,680,291,500,738,602,873,176,731,58,985,600,63,129,689,223,778,979,304,504,56,713,380,35,260,504,630,705,411,916,131,894,900,697,418,381,987,560,695,534,171,959,866,532,633,541,973,373,272,986,344,109,811,683,123,882,137,239,541,126,306,941,108,512,748,341,959,367,848,925,93,292,821,514,686,940,651,94,429,602,457,956,812,123,270,633,893,780,309,378,959,482,998,108,232,241,346,769,960,536,208,368,79,331,376,854,762,746,947,454,159,856,107,27,770,730,256,589,798,505,911,907,428,485,267,625,0,945,857,21,829,917,158,23,213,384,312,400,128,572,182,522,259,606,267,6,358,479,742,782,729,714,268,307,165,300,118,366,875,796,204,185,257,484,323,992,121,853,944,853,810,477,174,797,674,554,317,817,489,7,534,983,308,755,745,161,963,732,675,353,361,930,506,97,327,666,798,606,667,341,271,566,994,498,917,29,268,514,367,569,271,209,271,90,93,56,417,625", +"281,59,647,605,9,529,867,131,14,746,242,649,560,339,215,253,890,907,415,76,928,775,388,649,151,674,883,855,551,767,661,463,533,33,639,621,369,857,123,453,746,558,232,917,895,727,717,381,431,528,703,267,50,703,355,253,30,833,452,61,959,777,54,399,973,740,98,148,649,121,814,335,3,991,718,167,600,700,112,692,494,505,688,813,751,790,32,997,25,598,255,223,653,686,856,987,915,428,342,403,478,440,200,280,781,993,832,171,461,321,61,908,878,296,118,288,12,339,338,809,732,8,230,347,421,56,298,694,421,303,343,269,923,711,514,983,882,161,895,823,340,42,260,848,40,122,242,22,69,7,81,778,289,701,493,837,349,653,517,451,453,302,825,281,77,46,462,585,443,433,378,558,870,391,129,76,224,721,929,651,458,469,231,896,801,645,23,844,569,612,516,766,53,121,177,57,938,855,265,367,663,480,241,673,825,324,543,324,405,156,473,562,303,538,951,794,662,895,312,994,705,560,819,40,925,688,183,400,109,647,896,253,317,623,141,977,303,111,388,477,458,302,454,187,34,67,516,611,38,157,489,747,637,599,271,441,199,452,288,857,431,817,534,992,73,531,825,973,519,276,544,508,594,6,445,976,503,648,87,44,743,803,811,296,70,343,551,243,352,118,123,101,744,530,979,573,45,202,613,766,580,331,734,55,293,630,527,244,611,323,732,764,883,753,434,523,51,252,943,590,372,19,562,359,500,351,870,149,852,871,525,187,837,413,701,689,80,779,599,581,970,916,2,293,203,162,926,309,52,805,108,850,877,687,936,241,436,635,148,568,357,370,58,946,129,314,976,497,279,779,183,140,415,365,34,83,819,349,309,419,959,609,457,534,881,14,292,200,405,152,554,153,739,792,487,118,225,783,26,883,38,426,949,200,686,968,765,154,257,182,999,106,192,434,60,973,436,209,543,123,433,840,497,115,420,324,864,505,912,602,40,697,811,841,127,6,806,42,772,364,619,924,383,661,575,135,878,533,396,891,439,190,661,96,370,392,902,32,415,819,805,10,774,526,854,9,298,594,547,266,569,356,83,280,642,954,607,245,579,940,548,957,155,972,250,331,831,674,393,461,102,18,201,811,893,332,316,13,322,801,667,855,39,687,720,624,324,691,652,55,327,844,307,507,179,325,86,483,43,962,995,174,632,787,641,889,661,885,446,990,245,822,325,178,256,396,927,192,224,85,758,611,351,742,140,898,268,779,883,85,533,614,762,129,984,854,543,804,506,187,772,415,43,589,481,4,519,927,445,372,948,508,183,82,39,925,920,896,740,722,236,450,199,426,930,13,175,836,610,10,708,465,38,319,849,696,972,120,653,837,384,759,797,720,849,235,551,232,487,516,185,858,217,181,407,401,135,616,897,60,896,160,222,119,375,814,530,868,736,912,529,699,953,105,976,696,863,410,254,878,473,700,569,985,762,355,695,492,731,164,988,703,452,468,148,131,914,995,832,518,415,720,852,424,131,379,445,439,56,241,489,602,473,374,153,862,868,259,583,156,466,644,240,451,79,975,747,332,204,399,438,191,206,232,511,605,612,326,949,506,966,295,940,758,411,947,40,428,268,63,490,575,281,478,733,184,469,520,548,358,258,839,988,377,139,235,38,271,160,483,841,340,828,406,971,714,93,692,201,690,312,480,82,66,455,555,866,524,320,736,597,204,791,787,889,430,759,473,981,345,800,913,90,363,561,531,977,76,197,252,426,106,17,561,384,600,675,929,247,726,706,95,964,480,629,48,376,683,887,424,918,755,803,568,288,777,300,72,399,49,785,401,539,239,143,352,258,421,270,968,265,421,745,898,578,141,647,523,363,198,913,98,966,365,941,941,25,715,408,392,341,115,360,418,897,163,725,123,75,791,381,302,935,44,910,359,367,194,644,296,768,806,931,943,21,374,54,428,794,576,638,99,641,191,852,227,973,659,768,545,848,662,867,475,992,234,77,418,70,67,549,721,636,588,299,161,142,862,182,412,476,747,73,60,242,522,4,950,78,841,417,537,367,71,348,367,367,132,945,0,346,601,869,105,441,30,925,746,478,89,641,399,466,594,438,7,166,385,854,43,609,922,784,401,159,807,198,164,972,917,727,649,438,609,566,520,58,640,377,118,500,351,263,576,616,6,479,558,209,668,850,330,936,218,412,98,823,585,830,238,511,258,437,587,995,826,519,965,415,873,763,660,219,793,151,463,16,563,755,55,224,494,911,527,642,181,539,392,666,286", +"720,160,840,380,902,445,382,981,815,987,530,51,946,286,335,924,535,411,158,895,171,928,852,330,459,130,110,789,699,885,453,305,253,257,839,573,507,469,320,999,302,885,397,761,84,125,37,404,406,337,151,176,42,793,315,595,616,284,908,29,860,260,566,328,306,224,755,456,723,718,443,372,777,861,699,571,365,692,90,5,595,489,230,377,786,414,649,681,885,313,464,496,605,407,498,969,807,423,650,286,39,528,38,387,164,638,389,321,482,6,346,848,455,279,255,713,924,380,199,979,152,226,961,866,470,727,928,691,976,688,272,721,484,884,313,672,102,993,953,112,238,369,33,18,389,158,196,800,388,743,311,901,477,782,836,654,318,180,162,657,928,569,386,682,764,543,487,76,206,160,161,312,643,391,654,975,177,59,669,518,468,313,863,313,678,612,289,133,869,53,24,48,702,243,632,776,852,809,553,940,221,338,111,618,725,859,620,280,963,597,513,135,453,264,40,149,493,334,512,82,71,29,69,362,354,934,666,328,581,543,2,299,74,852,369,574,771,758,33,197,784,258,56,388,264,937,677,114,631,137,214,853,304,950,804,782,811,38,981,164,826,163,920,67,776,912,363,939,837,665,546,713,442,896,642,167,519,895,754,889,616,350,279,248,907,479,690,394,773,784,736,496,988,728,555,439,716,922,2,870,795,420,323,677,410,779,166,753,938,170,222,386,326,900,76,313,395,491,53,525,811,747,92,69,253,226,411,355,561,729,77,471,860,874,431,848,571,953,451,344,384,706,490,175,505,42,436,99,723,317,72,839,148,606,898,343,201,325,600,460,537,928,672,405,912,952,856,576,22,218,289,884,930,931,476,737,135,875,720,857,657,729,638,703,408,280,716,131,144,477,240,439,806,67,529,246,518,635,139,243,482,439,972,280,171,341,30,253,540,14,472,638,616,376,882,856,630,276,650,179,581,140,730,307,508,64,731,748,260,561,171,815,897,695,366,529,682,434,103,448,147,90,595,48,676,771,207,947,327,42,803,237,870,345,393,591,508,340,122,46,612,495,215,607,297,79,586,191,592,981,832,153,334,973,393,152,142,224,668,501,780,190,211,508,971,345,491,5,951,839,1000,12,923,280,738,732,461,596,477,644,457,615,381,4,443,726,431,790,901,801,333,489,683,673,389,253,525,681,606,356,911,579,487,669,286,896,796,26,326,6,661,421,116,588,950,734,211,603,328,302,92,778,259,496,615,952,469,54,717,402,704,970,165,163,100,76,755,311,356,612,474,324,274,209,379,826,376,945,407,280,90,870,840,158,546,448,789,423,565,80,679,268,252,935,59,239,132,652,866,843,669,141,176,202,723,804,870,389,345,380,765,626,50,210,25,397,798,934,295,353,447,606,232,70,16,480,911,236,370,992,907,90,109,221,752,953,735,616,868,418,141,84,431,224,65,264,59,204,329,71,214,141,334,426,160,665,128,529,294,460,387,386,803,565,902,81,840,299,131,745,822,790,824,467,727,205,133,564,323,3,848,671,918,533,665,302,614,771,441,800,941,204,18,151,819,105,429,269,13,571,131,565,613,728,954,151,878,911,256,78,812,435,380,434,419,646,145,617,893,886,2,774,99,322,775,935,774,382,701,902,518,358,308,981,151,687,443,296,578,452,898,437,790,357,314,280,975,707,466,191,65,35,25,26,483,39,68,445,296,162,972,524,468,271,256,540,816,576,622,505,566,896,767,796,752,857,102,263,419,574,165,800,890,609,60,79,365,289,815,857,682,211,843,142,245,89,994,715,616,607,160,735,933,532,804,638,697,455,194,845,70,75,73,101,854,749,876,254,238,121,912,825,166,544,502,39,174,140,769,550,858,775,744,972,409,504,975,347,457,344,200,25,217,359,156,107,878,782,371,819,13,452,786,148,404,565,224,871,446,270,568,845,937,135,301,378,799,63,620,227,65,298,107,221,8,837,545,888,996,239,250,284,370,607,402,519,536,955,797,415,797,33,400,302,837,169,767,832,983,859,202,764,363,69,437,163,926,297,200,405,693,286,913,709,925,369,973,571,857,346,0,255,790,909,520,41,965,326,447,519,195,98,679,413,517,50,566,320,979,501,586,558,455,675,896,674,913,719,962,758,330,85,192,510,627,921,675,362,605,83,228,873,404,716,458,897,414,79,652,848,134,498,353,436,809,609,887,341,99,983,725,373,830,129,381,648,564,516,35,540,369,374,37,410,631,94,811,36,739,933,876,359,839,835,423,372,201,347,314,465", +"215,765,462,868,863,486,686,380,258,528,557,205,370,429,229,360,261,568,616,311,173,284,721,392,675,691,489,258,608,314,93,510,680,873,883,498,105,307,534,515,562,40,698,814,580,671,317,66,126,9,392,898,361,259,444,812,643,800,724,841,860,149,142,495,344,699,214,851,367,524,989,366,611,825,902,655,500,887,50,431,53,433,53,70,720,263,735,575,141,294,770,549,843,591,857,157,721,619,726,760,557,356,91,33,722,365,248,809,341,966,534,373,873,530,551,989,437,3,972,648,179,338,686,113,708,959,304,354,411,53,459,631,197,681,398,998,608,650,11,596,49,471,154,186,224,173,177,766,552,993,947,285,611,763,934,38,427,105,270,465,918,528,736,308,865,747,802,395,250,727,45,596,698,556,195,66,238,477,427,813,283,161,201,572,266,788,393,795,97,590,698,117,553,471,809,835,20,348,484,916,932,238,928,832,476,619,402,155,163,952,959,904,718,602,611,374,793,481,783,15,179,859,638,302,834,937,69,493,741,59,500,103,4,517,358,486,114,426,739,852,772,883,855,829,602,691,325,947,139,829,86,98,478,190,913,234,637,647,585,827,413,608,697,369,552,129,852,989,559,958,723,984,366,695,980,475,511,683,433,874,864,499,343,204,108,626,647,64,943,422,692,402,49,695,70,919,953,893,359,554,470,42,841,922,711,469,305,378,207,204,122,296,481,662,329,473,59,199,533,984,13,193,134,354,890,960,388,904,138,178,432,62,881,681,360,891,983,551,429,897,709,169,999,714,264,968,815,739,696,344,733,371,655,646,538,787,589,437,156,31,311,112,947,725,180,314,263,668,684,925,812,547,20,514,816,682,34,762,336,935,899,278,85,456,666,436,180,656,157,745,529,282,463,598,110,31,448,549,663,506,909,599,667,789,712,909,589,746,235,410,819,868,98,867,466,507,627,845,991,306,143,875,614,556,291,802,122,218,118,841,468,984,183,287,177,243,43,165,791,370,533,852,160,1000,985,648,610,99,503,340,77,255,718,196,772,670,280,553,658,685,297,500,368,625,164,429,517,282,813,887,470,124,16,759,395,336,476,579,156,143,902,976,759,924,475,643,913,231,242,266,713,403,992,626,125,930,297,895,134,328,767,12,174,310,324,969,897,642,523,346,691,924,664,723,430,494,647,333,710,581,757,284,454,659,65,551,750,975,666,976,399,58,781,949,431,66,57,56,285,36,383,887,104,441,793,68,428,51,403,498,723,889,959,568,949,671,721,949,79,905,202,841,54,906,28,112,249,682,514,827,78,478,223,637,716,952,265,737,664,798,224,212,933,884,835,537,560,494,355,210,791,334,703,963,438,417,992,592,519,407,858,235,456,406,430,697,577,624,402,144,705,975,2,96,288,687,586,244,187,117,77,970,821,924,505,148,543,621,957,364,805,802,173,241,243,836,930,318,114,582,315,771,640,416,15,644,57,977,264,77,310,10,170,174,8,298,592,277,821,707,212,92,94,250,816,124,473,37,894,994,119,718,765,40,927,111,935,376,198,307,642,5,865,880,730,130,704,416,147,588,592,295,836,854,617,401,757,879,628,363,36,292,949,473,400,256,966,814,214,949,713,266,292,291,800,492,271,867,200,983,251,662,603,286,808,758,981,389,782,322,411,323,158,698,799,425,380,522,583,686,545,547,743,345,865,407,342,743,321,524,354,449,827,597,43,875,469,170,577,195,377,411,73,505,148,573,572,835,783,702,507,142,855,946,882,41,718,223,3,364,989,195,596,852,49,313,562,955,566,53,809,865,244,583,926,741,938,186,216,855,344,783,813,316,505,230,253,111,986,795,598,242,948,314,421,432,8,643,212,107,163,781,724,56,170,47,14,730,749,220,418,529,865,594,958,300,181,779,228,838,473,867,841,596,21,59,303,524,44,846,392,445,470,476,399,92,511,114,320,305,966,527,81,592,342,674,379,946,816,98,554,921,936,48,20,922,453,927,937,518,744,710,26,111,909,10,409,414,299,785,872,479,745,699,929,791,689,581,813,191,836,86,430,532,744,78,765,839,21,601,255,0,605,334,970,774,878,465,906,405,269,341,409,499,610,696,221,448,114,119,284,208,64,235,973,764,703,815,789,765,862,549,454,574,976,479,277,343,55,739,691,892,595,470,74,251,234,244,72,367,78,658,571,466,177,616,914,992,664,194,699,565,306,336,683,577,572,436,809,325,555,202,879,772,952,474,201,559,325,740,805,479,439,521,502,326,145,931,4,529", +"62,92,761,472,58,727,65,927,606,315,196,640,722,350,822,119,9,412,90,531,841,366,870,655,319,29,352,821,152,347,708,625,816,42,876,975,676,773,772,145,92,365,544,286,856,646,600,507,660,755,264,216,973,848,469,261,719,71,810,369,459,976,70,437,303,998,89,139,752,644,621,258,235,943,567,366,828,826,743,370,519,953,27,490,137,21,686,525,369,437,88,622,800,860,977,194,122,271,149,766,47,840,470,794,135,100,914,899,437,966,608,287,891,262,371,947,348,226,230,35,770,408,701,333,234,666,156,874,258,771,693,193,425,377,581,175,253,204,665,579,762,502,710,653,612,627,382,248,158,49,947,575,927,604,898,600,40,938,191,693,766,276,751,457,150,77,703,879,176,760,107,673,79,309,762,505,841,659,60,966,882,990,951,263,966,982,765,415,93,328,708,844,262,608,516,245,803,966,198,861,479,194,328,532,647,469,263,332,403,710,731,800,788,330,383,783,984,627,581,247,198,243,812,712,741,586,913,860,210,901,765,473,478,644,790,270,200,509,777,431,926,318,732,663,17,991,729,993,510,32,395,851,990,764,719,404,570,681,168,943,904,519,441,497,932,563,426,798,982,287,63,603,601,765,805,56,796,281,937,286,4,930,939,29,667,995,985,998,147,684,97,338,883,490,24,838,669,533,579,870,140,925,608,908,774,816,573,220,507,292,316,627,521,793,349,364,163,737,32,390,933,367,747,270,65,453,706,24,438,663,623,675,626,256,627,665,372,159,536,33,767,289,884,391,816,429,344,518,35,618,671,888,905,238,856,711,301,893,743,42,915,508,651,297,825,720,920,385,536,599,26,397,341,267,568,412,26,567,184,486,914,462,948,731,156,58,352,268,81,327,320,439,942,930,654,182,342,911,935,219,622,792,711,924,130,133,1000,574,820,70,711,580,729,756,181,8,264,207,359,246,683,476,249,66,692,869,920,987,226,759,920,76,102,314,698,217,428,339,226,829,611,773,259,460,486,12,45,181,255,949,850,779,436,735,109,337,19,191,512,802,940,87,59,565,778,532,253,715,845,400,857,834,984,975,614,361,325,645,377,339,678,305,151,967,419,314,729,138,390,660,404,880,744,48,887,710,873,527,586,737,576,748,349,946,739,406,129,137,509,414,175,224,985,211,429,62,606,138,908,796,561,144,2,905,32,535,858,653,837,455,900,619,339,848,58,272,993,819,396,657,323,644,606,772,887,430,7,312,549,814,519,318,146,515,942,713,76,801,589,386,502,774,830,757,338,69,850,795,651,224,473,705,130,542,405,490,514,223,777,778,583,393,856,885,75,894,709,434,791,770,879,832,613,803,557,994,127,746,339,87,890,825,589,242,646,963,652,723,415,955,432,5,7,259,157,787,952,668,416,830,303,9,500,549,738,965,802,131,406,230,690,502,15,334,142,794,767,398,448,159,206,718,535,981,761,229,660,190,203,316,711,53,137,519,267,169,883,850,750,147,922,77,487,199,72,661,94,610,926,539,11,282,126,554,369,246,77,246,12,170,629,152,737,198,572,20,928,316,630,64,345,718,7,746,642,955,316,909,997,923,507,77,629,223,943,601,132,974,938,804,993,264,272,549,182,4,51,437,137,205,867,57,26,273,161,319,887,54,491,704,727,778,309,258,883,311,100,411,302,586,535,457,947,200,249,327,809,279,683,884,990,100,492,870,571,16,290,723,799,258,570,644,790,616,194,197,305,926,943,96,781,92,793,279,1,741,833,543,245,319,553,95,630,93,922,232,68,689,902,166,219,316,78,181,508,170,112,651,538,240,779,748,10,729,178,165,495,651,213,588,167,453,49,658,271,867,751,199,531,463,995,849,109,313,403,723,903,989,286,375,131,950,487,64,286,377,62,918,717,507,213,441,142,823,162,389,42,157,686,920,891,423,592,854,919,106,712,185,39,141,118,834,940,744,647,428,506,902,139,398,381,688,807,852,181,436,366,38,611,417,423,46,689,515,205,135,782,160,915,870,852,630,241,526,10,646,299,80,675,477,45,444,523,95,376,956,113,58,829,869,790,605,0,532,552,391,804,928,721,317,912,638,459,551,547,27,694,945,512,199,696,257,63,517,770,432,370,876,791,267,936,381,22,127,344,766,833,574,572,340,210,425,436,785,136,884,166,558,536,330,871,953,44,816,488,316,577,197,604,515,78,734,961,836,163,414,153,129,179,757,81,787,910,905,908,254,682,312,785,968,845,927,660,492,968,93,991,862,667,121", +"962,32,410,410,951,165,561,238,127,531,480,87,527,486,23,417,613,489,767,617,69,436,208,213,342,180,266,148,430,442,603,111,224,293,1000,660,335,111,839,507,264,655,350,416,256,368,754,169,399,469,183,688,80,784,804,270,585,61,354,265,731,555,567,898,297,954,199,420,499,488,944,570,664,201,9,151,64,55,547,448,274,227,287,333,112,125,244,717,586,962,487,506,234,624,911,583,587,660,209,536,533,233,798,42,226,684,423,747,789,149,903,687,253,914,30,347,77,12,85,548,956,212,22,245,881,124,3,542,663,168,808,358,502,587,591,580,349,735,72,45,3,929,233,192,166,220,239,766,149,950,774,337,477,512,530,975,481,367,22,573,943,493,991,151,33,825,332,264,6,533,941,154,950,196,269,813,593,92,504,688,978,425,26,13,175,133,538,527,120,844,614,327,22,560,231,843,820,250,739,656,192,424,758,531,253,598,231,766,192,19,324,581,311,84,929,993,443,448,692,488,324,459,743,217,193,953,319,100,511,165,851,375,694,754,533,795,513,278,428,21,831,343,808,325,641,969,903,860,162,973,104,303,491,971,976,954,74,3,78,968,833,89,740,570,603,761,766,492,525,21,578,187,13,82,700,740,455,16,748,982,815,869,71,594,477,609,934,808,868,730,212,621,235,814,338,59,563,811,844,418,426,203,683,534,810,30,185,64,864,941,244,292,715,951,193,481,93,456,239,821,254,683,9,973,38,826,839,428,135,919,296,446,578,255,819,417,361,375,474,897,340,985,104,451,491,331,438,961,578,751,263,703,668,444,158,489,234,874,628,119,493,955,590,574,432,839,966,264,959,950,959,32,654,98,678,482,872,589,857,919,683,196,105,135,494,7,808,943,866,297,813,791,146,694,951,980,479,277,1,968,797,488,209,847,185,975,500,686,509,852,348,484,614,945,814,493,41,698,337,856,825,785,214,77,771,971,259,714,226,577,810,942,237,274,41,420,575,166,233,978,923,133,525,198,658,38,680,176,575,940,387,980,300,222,854,23,320,188,391,22,453,561,218,51,952,517,820,761,957,663,612,8,869,222,787,495,219,353,48,881,51,734,312,821,625,189,300,412,852,658,885,799,42,128,798,436,115,471,651,806,834,512,368,871,454,975,579,877,736,615,452,276,49,566,718,385,557,459,850,951,992,241,486,57,964,251,177,687,724,526,723,480,447,981,581,210,703,309,898,372,16,826,984,8,303,442,917,108,629,693,189,261,70,329,495,377,773,80,831,508,568,706,919,852,949,463,863,704,886,743,825,926,436,59,7,836,713,474,803,904,688,599,824,566,489,234,555,415,446,865,45,111,431,535,695,720,359,315,286,817,953,190,233,921,525,83,729,694,693,173,742,598,395,68,356,887,435,867,993,721,409,205,296,58,932,650,260,421,692,290,808,475,92,649,966,161,876,544,126,846,439,53,75,348,963,246,140,375,384,413,504,324,133,62,106,626,982,699,934,330,841,434,548,240,339,162,793,224,53,529,183,493,779,178,454,593,967,380,882,184,378,658,974,351,304,193,21,547,778,588,201,475,801,429,941,892,209,424,485,212,186,181,99,462,855,621,251,409,29,356,418,338,701,44,674,251,103,101,212,244,271,133,301,307,845,199,260,621,561,519,573,362,919,825,465,344,312,903,939,696,860,739,8,62,848,157,452,162,794,518,208,131,160,650,814,498,757,981,259,71,452,555,945,111,359,929,757,443,605,972,342,748,313,192,897,850,40,491,466,313,657,451,767,332,441,854,464,624,422,506,429,910,890,323,24,233,986,938,370,752,717,569,117,345,798,986,789,469,393,222,202,578,708,880,832,534,968,826,801,823,768,900,368,42,857,591,489,869,173,937,332,97,984,966,879,87,221,568,378,180,379,376,292,866,740,427,958,116,176,596,533,754,215,980,876,466,941,352,248,24,76,994,269,278,585,216,627,28,965,297,636,740,325,275,285,177,423,618,929,732,603,710,584,262,222,134,539,104,340,90,681,119,936,630,728,467,249,367,893,356,350,933,57,717,124,617,831,773,917,105,909,334,532,0,830,285,307,318,623,201,937,356,834,856,522,718,90,677,811,51,870,871,498,706,270,609,67,555,320,304,56,510,644,104,725,697,698,936,546,628,762,778,138,469,997,784,565,382,818,449,879,595,500,175,642,490,332,143,990,853,726,473,92,717,208,908,132,576,733,282,915,839,834,411,238,365,701,970,65,928,332,651,894,808,126,890,138,239,634,462", +"8,56,764,549,266,94,989,594,39,374,301,729,133,594,914,946,516,191,97,537,963,622,128,636,988,156,747,684,693,72,629,306,690,337,263,204,356,556,914,765,588,471,426,742,805,712,933,402,770,985,477,781,702,259,652,721,222,656,549,358,392,765,690,495,217,342,716,10,400,191,455,84,821,136,283,816,972,705,435,409,858,653,925,457,363,758,569,832,892,809,121,778,646,435,981,363,266,382,4,623,584,285,377,998,123,162,727,414,241,312,535,98,423,746,489,46,274,589,525,217,134,238,583,732,500,451,22,609,880,482,400,650,620,192,19,734,222,557,802,984,267,767,748,450,613,816,384,810,161,119,575,752,332,358,290,993,824,826,826,604,747,978,641,631,487,280,37,38,299,10,318,943,246,80,369,593,775,485,33,299,788,97,448,446,243,759,891,489,54,237,753,809,118,531,914,997,33,764,125,19,45,522,670,597,889,149,730,184,240,820,703,979,596,542,412,807,600,840,636,709,514,444,804,553,432,865,587,400,809,669,71,756,285,793,138,269,310,184,538,575,422,277,943,489,677,165,388,653,616,423,229,783,106,978,514,890,531,705,138,990,20,502,189,928,362,148,664,364,45,488,256,889,521,866,250,472,412,83,840,808,554,226,58,224,964,299,606,442,852,416,718,665,366,837,802,685,69,638,114,787,108,587,355,115,665,41,442,646,317,524,288,202,484,283,879,617,620,999,461,730,161,832,486,355,355,25,776,807,524,393,549,390,647,901,662,903,482,423,36,17,624,234,738,735,33,377,791,738,274,218,409,656,308,348,414,719,97,791,651,104,489,672,185,860,613,426,550,721,751,134,342,414,527,679,991,861,716,601,644,936,447,36,744,816,448,618,623,182,689,536,657,318,380,329,220,205,775,206,362,436,759,849,366,690,194,267,732,785,973,919,143,533,150,673,992,757,38,912,733,910,75,862,936,949,218,966,437,245,717,911,804,9,249,196,500,149,646,550,912,621,986,387,672,594,406,469,345,161,453,868,256,91,753,32,593,798,728,169,297,298,958,155,515,66,921,806,828,69,846,240,283,782,659,477,786,190,202,842,786,594,440,225,101,747,473,446,621,410,395,793,89,392,870,535,555,624,434,554,782,560,568,922,450,434,107,465,526,701,294,950,452,792,494,589,803,794,605,468,737,861,817,702,406,696,901,202,896,906,522,257,599,811,52,576,396,542,269,270,597,281,740,334,161,327,474,681,771,403,328,679,770,839,93,470,623,155,560,114,629,308,539,929,397,833,620,570,112,966,729,766,724,977,319,976,727,388,397,197,346,698,681,780,1000,985,349,617,776,482,923,223,734,316,826,219,861,636,5,702,237,165,307,657,129,167,91,676,350,355,837,60,802,766,762,514,290,465,260,999,678,252,84,828,335,32,123,543,272,181,938,584,773,480,908,927,362,338,370,575,574,203,194,200,987,180,860,659,192,816,422,141,843,244,820,767,187,95,241,401,850,887,240,798,865,88,451,251,80,833,548,600,572,530,559,657,202,961,309,186,531,277,712,982,614,748,286,785,294,105,404,32,756,122,607,59,296,904,426,880,420,58,201,418,902,655,946,514,351,401,208,109,745,988,510,892,9,481,256,866,517,361,969,553,234,339,214,249,615,920,559,690,45,370,373,983,721,231,789,896,530,190,394,967,128,769,978,264,56,590,535,246,478,274,37,131,622,630,66,513,583,493,526,727,478,375,907,268,375,519,732,570,726,702,420,91,205,401,906,704,637,513,398,509,429,626,882,785,193,901,593,474,631,602,178,831,101,882,154,654,304,849,565,150,103,647,273,909,222,59,12,594,681,343,230,277,479,617,553,162,316,143,759,463,329,965,746,74,399,455,176,175,342,927,144,128,388,845,59,51,960,982,382,777,711,746,945,180,674,196,909,94,689,958,786,509,186,606,852,86,842,640,822,896,60,943,463,547,176,840,424,189,532,166,241,928,891,843,843,910,95,292,518,221,356,480,68,22,818,184,705,536,467,439,881,531,245,849,517,55,245,175,438,896,503,986,847,797,791,586,158,441,520,970,552,830,0,91,297,275,446,238,795,945,650,674,417,914,82,349,526,464,288,375,170,330,811,643,744,359,109,886,830,744,629,491,292,8,393,993,12,78,847,945,428,670,30,793,670,947,349,409,406,137,73,989,170,927,933,728,277,375,171,56,597,639,485,900,483,162,342,770,930,341,371,864,518,885,344,453,398,322,648,71,747,560,78,805,184,492,575,751", +"208,662,177,277,135,23,337,5,868,428,528,538,821,73,968,660,597,27,263,737,552,998,56,51,434,875,11,797,509,959,904,331,659,377,137,194,510,999,570,815,507,755,972,690,436,625,927,761,355,444,11,920,569,391,509,26,770,596,917,645,333,561,165,318,243,904,45,439,38,636,221,63,278,106,185,98,572,910,141,386,402,906,269,126,256,915,454,914,825,971,140,112,2,316,624,958,535,946,67,708,780,282,508,403,19,729,596,174,314,615,37,521,336,115,201,977,129,649,681,103,828,271,30,283,918,352,536,180,813,622,956,421,742,119,164,571,604,902,859,442,139,521,523,52,51,889,977,559,694,139,143,426,199,939,69,477,753,284,891,960,771,509,191,558,672,418,380,659,519,362,826,970,794,700,102,42,726,101,16,360,689,612,980,869,989,799,620,664,308,287,893,119,744,71,236,254,426,382,925,893,817,390,334,401,926,141,155,593,927,473,383,97,944,718,643,956,785,564,893,986,250,924,995,475,100,431,867,214,957,914,280,132,475,670,332,827,185,469,77,363,535,369,254,248,378,885,326,684,181,17,225,324,319,314,85,891,58,29,749,517,830,585,295,898,598,132,135,816,162,7,633,469,316,135,44,405,85,514,449,682,566,985,947,786,507,25,879,176,157,617,634,687,67,385,925,143,359,93,272,783,716,904,559,69,884,167,460,959,362,529,208,851,297,107,763,104,834,757,159,218,820,101,50,490,82,216,86,272,737,842,445,688,649,607,970,491,484,237,309,425,233,817,955,349,451,708,34,959,662,430,598,631,301,831,859,47,626,407,910,681,719,198,936,527,938,382,731,480,898,548,446,339,643,33,124,274,435,52,540,298,270,171,185,159,582,275,753,657,66,517,902,820,991,487,706,538,967,88,817,995,960,170,828,519,955,125,196,202,519,204,355,608,861,340,474,244,623,804,302,497,398,277,271,860,398,409,754,511,621,49,429,766,730,120,626,518,636,669,763,744,352,60,341,3,648,785,57,89,378,752,381,130,668,26,46,760,752,451,978,565,953,121,961,415,544,173,366,677,647,162,292,748,733,402,281,188,408,441,849,663,515,515,42,404,820,328,838,174,648,815,178,632,836,945,141,696,5,491,46,195,799,703,594,168,329,542,950,541,617,310,817,741,372,107,17,719,584,569,859,465,409,606,635,119,676,614,728,825,215,778,584,358,281,573,333,354,650,404,221,864,736,319,425,363,839,192,454,388,15,171,571,483,522,519,27,152,660,521,929,747,204,817,713,896,34,682,914,537,52,299,860,606,733,221,943,473,803,994,132,432,697,539,287,646,511,356,704,464,493,812,737,351,959,786,696,864,903,391,871,717,725,359,454,89,178,884,572,544,201,261,966,225,197,103,786,555,827,491,460,762,287,725,807,983,156,664,923,568,241,829,382,183,84,463,233,223,572,492,322,924,739,886,173,843,395,460,870,461,605,78,969,958,310,446,896,613,344,510,683,109,713,156,411,824,630,987,653,280,125,306,107,733,964,762,893,423,655,975,270,216,507,652,689,107,213,50,811,674,726,528,117,559,597,416,988,650,13,309,976,888,1000,870,814,768,756,924,659,410,739,302,639,33,828,761,549,743,976,511,402,364,459,376,856,641,581,453,483,767,276,168,547,598,714,160,114,85,465,733,805,24,444,767,249,861,81,125,495,51,424,726,573,721,549,87,365,477,218,869,226,326,717,151,861,579,379,911,463,4,56,463,710,62,789,846,931,456,657,886,261,617,918,472,325,260,61,247,932,286,655,470,5,733,984,601,472,486,825,700,479,789,387,753,17,502,91,106,983,473,486,207,500,817,183,601,493,151,479,225,196,971,283,701,264,616,945,351,714,521,826,775,262,615,127,272,779,808,126,646,101,190,26,808,48,701,198,819,229,971,465,847,461,324,854,221,808,981,516,363,347,669,366,523,328,187,252,557,27,559,72,150,393,778,633,576,82,631,106,239,294,793,672,204,733,81,702,243,875,177,291,399,258,495,78,236,279,235,998,126,619,23,444,55,358,622,139,116,155,583,23,30,41,774,391,285,91,0,564,430,740,15,143,100,632,259,567,742,664,702,33,321,74,792,455,31,57,887,945,869,707,390,884,501,999,449,708,969,846,403,380,777,414,105,258,63,858,744,609,620,893,770,817,834,835,259,71,463,486,171,472,682,816,107,261,137,660,998,97,485,17,304,993,842,48,474,777,368,162,227,342,296,604,755,602,727,995,98,590,496,906,131", +"617,451,39,392,131,53,754,9,750,942,438,295,546,25,13,446,626,888,552,877,649,763,64,212,857,778,293,444,188,793,964,75,596,708,436,245,879,128,403,832,924,518,644,498,915,630,62,250,132,711,968,63,832,669,817,1,498,357,529,948,546,399,51,672,193,771,145,756,877,913,636,582,316,297,83,589,250,101,761,696,862,239,314,174,349,566,188,689,737,538,2,825,148,724,651,357,711,717,69,1,330,532,691,431,898,582,528,433,143,206,679,579,532,480,208,920,982,623,842,264,526,77,148,398,833,823,228,777,68,510,685,425,522,874,649,128,24,460,978,334,473,359,242,835,9,398,49,262,336,608,654,702,706,583,654,881,784,299,394,42,97,3,596,334,649,460,109,865,997,170,701,248,317,414,295,743,222,475,812,43,48,743,312,654,889,322,99,331,372,752,338,899,122,247,836,171,176,96,777,633,319,539,584,640,304,96,569,610,590,934,40,47,828,275,38,175,987,664,794,116,926,896,233,1000,287,587,373,679,315,571,776,517,5,121,394,242,156,941,393,696,85,246,396,566,678,471,447,365,756,387,231,57,977,915,931,308,411,853,354,980,881,93,601,979,607,650,293,17,680,616,632,604,562,793,549,437,163,560,884,34,27,735,847,150,473,742,909,671,293,253,780,258,261,967,181,311,963,866,670,301,617,509,854,641,261,116,323,50,241,943,366,514,607,690,143,331,477,98,502,632,484,947,312,814,542,658,186,28,9,664,989,37,544,748,608,853,499,899,746,590,829,96,876,922,861,511,509,753,314,192,488,249,719,304,577,496,509,14,794,684,679,82,65,628,922,218,304,918,776,749,300,178,957,305,119,907,287,69,957,54,318,193,599,105,378,534,563,372,166,143,554,590,288,742,178,920,863,999,238,464,897,251,983,872,734,682,895,615,177,913,770,714,955,361,19,196,235,291,169,491,596,10,463,697,347,135,35,328,287,595,704,951,609,375,204,305,712,145,776,685,715,474,878,543,444,960,93,731,816,730,720,535,789,510,547,94,220,857,225,503,544,923,996,618,948,861,419,968,44,189,934,17,950,966,686,943,803,476,949,977,316,340,975,183,637,162,811,483,401,659,277,643,775,391,816,618,41,66,79,983,997,860,207,846,238,696,815,839,358,189,942,549,458,711,18,158,104,871,207,342,76,386,323,138,679,478,548,303,709,92,967,903,348,562,649,752,516,573,396,29,454,513,573,104,746,436,959,977,963,193,144,433,511,617,426,996,86,170,428,453,141,81,499,36,181,203,768,78,443,525,83,149,98,566,567,645,983,421,167,944,537,721,823,722,78,698,803,819,548,492,196,998,877,154,361,443,765,997,442,611,396,125,777,177,589,727,262,719,644,191,909,947,432,765,331,637,206,685,312,182,116,790,738,24,709,810,807,473,603,145,193,27,45,274,510,401,361,664,481,138,645,560,834,378,415,70,33,405,271,430,83,270,58,223,692,76,509,136,391,457,823,277,631,309,514,395,102,979,924,427,750,628,745,2,264,175,206,158,430,42,177,712,451,852,454,299,931,188,792,946,360,143,805,338,797,66,727,968,299,681,200,49,206,838,716,609,86,881,778,386,161,30,184,156,732,254,825,203,257,771,138,751,922,97,321,523,500,521,515,798,179,26,845,181,51,10,188,457,268,826,631,468,919,478,613,479,378,379,958,805,849,660,336,855,159,867,889,717,778,701,901,490,147,309,420,732,675,159,287,61,897,849,589,269,259,451,170,945,999,845,776,779,525,629,268,340,402,319,12,248,903,470,774,861,11,452,976,251,432,727,295,111,264,757,781,936,885,855,244,686,599,762,103,151,647,409,299,535,647,469,357,144,314,747,84,1,627,355,150,926,263,964,61,808,427,206,308,508,201,725,263,761,914,306,209,933,440,539,259,939,579,431,264,919,752,426,758,302,554,101,922,84,58,699,993,77,416,44,966,717,66,548,971,141,322,615,292,733,94,812,715,841,450,35,933,970,190,64,857,841,583,453,75,291,159,668,262,221,131,459,83,590,687,534,367,719,261,928,213,925,965,878,804,307,297,564,0,111,675,418,371,473,738,799,307,790,947,118,260,77,596,283,740,158,466,750,189,967,371,858,592,601,262,829,21,302,68,314,519,290,36,105,669,533,696,546,116,533,13,701,979,350,482,366,47,689,833,216,164,106,711,991,251,513,340,460,277,518,304,910,981,476,346,901,8,531,81,287,917,628,308,99,349,896,619,304,262,869,565,589", +"285,449,138,907,44,415,901,877,36,806,492,166,213,987,814,484,974,55,870,823,203,257,274,605,569,247,273,629,319,316,759,851,217,49,112,854,217,667,371,248,148,466,3,840,703,921,185,975,608,340,893,455,794,254,547,229,360,362,18,138,307,25,69,895,259,426,961,308,935,812,130,347,179,98,897,720,507,344,727,643,300,333,27,894,261,893,813,744,343,582,312,615,400,191,737,756,727,579,653,733,704,586,456,707,420,716,970,975,880,617,567,242,689,969,210,427,80,689,322,991,285,650,995,783,939,984,983,100,706,892,239,517,238,76,575,258,948,268,384,544,469,347,492,985,969,140,861,878,721,48,606,486,187,460,657,966,742,170,73,225,746,20,341,483,621,851,93,880,82,335,864,334,60,136,868,743,942,425,260,552,24,159,483,98,604,720,932,413,661,958,195,153,166,974,79,372,710,27,475,199,350,435,909,27,542,493,214,267,970,751,214,492,66,191,599,313,686,108,192,329,539,747,996,450,265,679,77,67,998,373,634,651,322,947,793,365,319,482,714,257,424,76,977,372,44,962,453,190,841,814,604,434,469,768,48,803,286,346,511,907,261,105,335,948,190,137,424,917,613,1,280,310,926,478,16,728,280,63,449,38,828,865,875,505,178,6,387,691,122,31,445,235,36,450,552,909,409,855,397,847,844,429,472,685,832,237,38,868,41,371,901,388,560,710,851,488,149,913,181,797,107,357,904,847,160,308,692,108,168,84,970,239,514,880,329,942,588,204,135,8,287,235,786,6,87,97,173,24,681,545,531,530,530,511,140,185,302,874,479,573,363,541,921,465,532,212,527,138,839,943,825,761,401,855,349,826,329,853,523,847,203,995,368,341,755,935,727,914,99,155,897,326,916,429,231,224,240,616,960,456,881,505,485,728,860,514,873,440,774,198,616,186,835,436,373,206,888,319,370,345,685,528,74,511,321,678,365,886,84,826,593,322,954,403,657,80,851,251,928,554,220,795,655,447,988,362,683,665,808,697,710,749,188,616,743,578,933,903,725,900,713,896,10,279,144,552,114,106,932,249,496,369,713,136,705,966,426,156,214,65,88,263,689,233,782,928,80,252,33,991,411,362,826,362,219,562,462,473,753,499,332,613,258,232,714,118,290,867,144,811,260,778,784,325,49,93,276,347,169,751,533,294,920,701,944,627,986,690,987,856,104,446,35,628,726,982,793,954,392,56,142,597,343,530,478,239,195,857,817,246,8,928,714,593,574,301,17,153,862,5,244,186,321,740,988,648,325,705,350,587,511,555,945,48,496,259,329,965,662,104,545,236,912,660,719,929,817,739,406,208,373,141,204,953,44,116,163,638,395,819,605,757,178,42,733,407,530,586,102,584,730,585,369,847,961,878,211,631,810,164,505,402,636,755,872,813,674,931,429,144,423,391,686,396,116,45,842,367,818,428,555,260,838,233,539,779,358,951,373,996,564,283,349,590,213,185,548,911,91,248,60,122,555,169,41,894,50,669,628,727,461,682,967,407,165,857,85,877,42,389,984,883,547,988,156,668,238,855,198,46,403,169,963,955,448,175,925,572,298,381,689,871,491,197,359,106,634,830,829,655,923,427,626,240,44,648,859,10,384,252,307,520,95,391,540,512,838,619,725,506,533,948,958,916,688,185,72,276,210,719,890,552,469,13,7,35,465,830,490,491,6,397,838,766,634,352,552,712,729,350,195,754,627,945,633,186,233,171,422,505,898,14,324,517,675,421,136,49,98,97,590,866,122,318,935,694,784,98,80,520,514,607,153,831,5,782,275,773,925,512,357,233,675,251,108,299,888,416,830,437,887,897,948,710,896,747,873,915,439,549,568,155,637,944,353,511,406,463,796,847,747,752,801,267,592,546,330,297,481,874,919,988,913,174,235,624,940,826,996,531,153,733,735,95,443,914,339,3,432,948,694,430,285,220,308,258,294,319,584,449,468,198,406,948,401,460,338,243,704,726,590,344,886,724,430,551,6,259,336,209,611,780,991,621,956,495,275,369,595,643,850,517,679,806,859,496,243,218,384,746,326,465,928,318,275,430,111,0,230,142,730,943,338,501,197,225,891,353,192,617,892,858,188,540,678,871,975,865,294,100,280,460,796,566,752,29,602,334,138,809,120,343,840,853,888,584,253,735,799,122,864,15,588,9,745,371,94,481,971,876,276,832,664,248,878,489,145,215,980,304,50,977,158,697,458,839,966,95,955,194,381,189,628,869,960,977,211,502,577,587", +"391,517,974,893,133,16,348,943,308,533,381,363,957,161,218,41,950,485,984,379,792,305,160,337,531,771,286,63,198,160,278,143,874,706,827,974,951,208,81,128,360,489,850,487,873,607,561,789,492,966,337,660,355,997,198,770,247,13,318,498,413,35,984,152,988,588,80,885,822,974,979,900,634,161,869,452,345,335,934,953,932,58,934,878,103,982,505,164,632,683,945,67,372,675,366,817,500,261,518,644,264,627,599,258,659,454,247,154,432,589,957,935,903,343,520,49,45,806,298,172,768,392,80,33,486,998,937,192,555,792,189,433,926,864,472,558,843,443,573,455,374,220,494,711,202,199,163,252,196,456,744,969,964,914,257,533,898,314,362,868,499,170,632,199,408,175,879,157,177,977,175,945,799,547,827,798,616,13,6,912,458,52,951,119,554,239,929,979,932,45,185,365,316,738,19,505,883,503,888,39,897,155,459,450,296,553,694,934,999,4,286,436,228,993,409,173,983,236,12,549,208,933,919,373,954,869,200,429,107,104,174,660,540,684,244,641,853,176,269,593,569,943,956,929,832,350,709,920,815,339,773,619,888,108,168,89,67,824,949,879,383,305,236,974,282,444,405,492,27,841,306,395,237,396,199,911,824,660,378,711,282,298,663,8,220,651,766,225,749,395,311,996,143,307,895,286,42,19,499,611,423,123,54,111,494,962,726,985,746,60,416,636,598,724,409,947,104,393,961,918,23,427,572,981,268,288,955,255,995,775,552,218,921,596,654,21,509,954,725,723,593,963,907,163,328,334,642,923,80,450,299,553,312,610,915,632,881,689,135,666,192,646,312,430,501,967,914,846,995,792,339,563,495,523,899,87,755,934,199,227,461,13,618,263,40,380,798,132,385,662,181,59,965,531,413,370,246,176,939,856,476,705,201,902,769,900,884,905,197,817,434,136,988,221,976,36,938,493,79,51,253,210,281,769,584,526,42,790,853,635,921,153,744,208,280,456,103,33,73,206,842,410,905,41,188,370,826,942,157,712,238,855,592,329,637,43,585,299,938,560,234,628,76,666,763,42,543,245,699,93,417,289,913,378,211,802,666,988,174,389,399,643,630,182,43,811,449,801,549,477,225,522,124,881,18,498,566,823,673,68,107,140,56,677,646,538,199,802,264,234,514,340,27,501,6,471,104,519,611,862,150,913,961,549,45,713,907,887,433,872,361,147,386,115,668,186,936,3,939,922,33,604,942,69,439,735,616,158,960,271,745,733,113,632,733,178,65,268,646,915,708,904,675,960,291,165,783,570,989,215,448,446,844,512,820,67,974,426,229,461,658,196,482,760,879,857,920,465,194,945,741,178,102,880,638,59,443,791,212,54,533,625,356,325,955,400,824,96,396,258,568,959,463,142,90,362,52,899,171,790,809,331,737,139,849,770,932,828,313,436,408,325,173,455,532,430,732,885,191,517,281,118,428,638,361,507,327,433,997,745,554,907,671,201,164,57,314,3,31,895,413,764,831,724,569,131,143,748,816,673,765,417,286,112,452,794,65,984,532,944,94,756,835,806,240,627,114,143,374,174,959,291,422,823,769,818,746,18,743,629,87,900,779,66,37,754,374,638,121,653,132,190,854,743,557,444,4,625,599,474,740,453,289,358,271,701,114,150,693,725,607,634,877,760,328,903,843,557,687,698,548,575,848,62,601,103,664,281,68,869,583,261,605,491,170,929,579,992,569,949,635,182,984,911,694,493,44,691,921,987,45,150,815,286,671,624,956,478,571,110,372,876,730,616,228,19,45,254,614,316,159,301,559,436,217,281,350,868,839,377,229,569,387,141,730,8,29,616,340,43,645,483,848,676,732,171,680,755,184,290,69,873,447,67,256,102,853,212,707,378,228,2,328,966,754,183,566,402,610,33,898,908,575,10,789,601,316,535,165,365,62,425,913,100,456,297,462,582,117,770,268,56,109,494,558,915,105,6,56,746,795,702,993,68,905,870,28,754,246,379,853,122,935,92,809,797,267,153,286,578,740,496,446,204,630,8,378,125,335,627,864,302,901,601,963,527,332,283,312,478,447,906,721,623,446,740,675,230,0,675,143,52,949,918,186,981,801,711,136,198,564,639,728,72,238,293,563,588,463,817,380,402,39,434,632,541,699,396,231,728,616,312,93,290,962,80,864,935,85,418,697,85,951,339,793,272,296,719,646,411,412,659,675,890,355,208,932,733,584,733,432,950,257,669,543,522,412,349,367,170,264,322,942,982,437,738,543,780,289,107", +"544,476,919,987,411,109,599,539,603,646,352,996,708,99,303,893,343,492,520,804,416,384,306,490,983,358,757,776,847,735,252,346,58,691,798,44,63,543,340,192,836,27,506,911,447,760,215,611,387,811,172,205,864,8,857,268,529,904,806,555,458,476,988,669,916,77,75,960,7,115,338,320,733,875,4,451,345,715,456,946,423,895,573,768,118,895,899,92,84,445,54,620,733,674,218,917,918,794,117,222,24,385,388,379,468,860,659,947,483,462,21,119,636,845,546,559,647,851,595,272,409,394,120,601,182,844,497,909,591,999,885,945,629,295,727,126,456,274,219,808,401,376,920,402,160,939,83,183,908,954,284,169,229,227,404,713,241,634,102,84,375,830,655,232,979,258,447,598,15,74,416,766,165,794,503,860,642,589,25,475,928,685,823,874,91,80,434,373,378,569,605,768,764,985,680,74,755,649,506,888,780,966,658,195,25,481,864,163,197,852,495,267,319,753,877,722,57,548,85,532,369,578,336,372,564,134,389,63,804,989,619,225,528,807,686,786,975,447,498,79,536,904,930,160,694,120,963,277,504,40,548,535,205,735,309,290,771,627,746,131,775,61,985,54,768,88,820,255,962,359,111,6,644,754,740,98,871,276,705,75,480,771,810,594,473,684,638,772,337,576,102,350,846,651,394,876,574,678,468,948,37,254,952,752,802,917,747,202,239,575,462,990,736,196,792,508,732,374,949,712,314,967,54,34,348,964,881,727,93,465,918,473,604,123,452,520,750,310,661,558,812,30,398,912,845,422,3,661,244,972,758,46,269,133,320,932,626,224,592,184,46,916,633,903,865,183,226,376,173,228,355,268,410,999,5,702,7,68,457,506,795,279,962,62,157,517,731,997,107,144,898,218,911,209,246,361,169,518,560,950,471,848,632,266,53,514,842,626,240,10,298,538,545,721,384,240,921,442,65,624,569,252,140,703,485,383,925,945,993,924,856,668,963,28,636,338,272,623,27,559,206,991,120,454,704,350,948,27,688,14,994,84,654,253,485,230,595,20,435,960,565,747,272,517,899,223,187,451,638,241,44,467,847,407,193,667,348,489,494,933,161,760,749,149,669,908,198,472,187,612,816,85,14,790,121,3,952,802,481,994,763,45,638,229,590,541,368,330,554,445,75,840,166,81,394,139,675,93,685,741,895,289,257,10,626,552,773,839,231,979,244,491,970,20,661,296,746,893,148,491,812,150,120,444,632,360,922,353,25,159,96,236,721,972,686,287,733,46,34,59,473,319,729,150,785,649,266,886,664,340,515,322,520,644,799,866,702,915,21,129,987,692,149,784,809,828,632,863,390,152,83,793,55,90,458,306,680,646,34,3,919,738,775,627,87,213,186,456,102,468,263,716,62,719,428,34,274,250,214,49,57,73,846,478,55,641,546,231,322,397,438,656,519,317,232,527,409,518,385,659,418,667,818,815,948,779,643,518,689,588,908,769,964,567,679,226,901,104,197,876,777,318,526,997,817,686,188,427,647,141,116,187,723,175,171,840,742,945,266,223,463,578,581,69,46,506,796,836,129,541,857,469,575,918,809,291,21,146,902,488,484,92,535,879,244,412,920,322,692,954,957,417,421,643,431,369,471,901,646,459,524,992,379,107,188,90,474,508,915,98,61,694,32,89,289,100,661,521,786,641,702,774,202,863,680,267,669,117,723,94,373,905,697,22,866,289,857,834,362,884,116,962,145,34,852,339,976,931,618,653,390,8,927,383,570,434,160,236,600,212,619,570,519,984,98,81,190,281,979,429,435,475,278,230,408,463,398,605,886,493,71,972,866,121,264,812,190,673,646,287,659,376,657,788,235,667,733,96,504,762,306,932,935,522,576,548,891,168,190,913,341,278,972,318,576,616,525,673,51,943,590,780,380,382,950,115,382,75,437,789,78,519,260,376,414,348,320,727,56,669,316,554,297,11,674,527,471,765,341,678,381,380,727,711,420,646,939,82,710,447,520,602,814,584,51,749,557,271,741,482,827,229,814,172,775,735,470,896,875,787,327,621,904,491,281,915,1000,458,400,89,519,405,317,201,238,15,418,142,675,0,152,560,747,718,939,589,380,140,491,317,265,686,520,655,346,319,861,442,774,647,751,509,640,256,319,156,31,348,814,324,411,728,403,272,288,62,125,36,66,338,556,994,753,369,94,991,551,652,133,854,875,621,368,204,82,166,121,726,979,899,895,174,416,737,874,114,663,714,404,388,161,280,38,811,421,834,584,269,241,35", +"521,672,138,408,77,392,209,538,933,167,737,788,726,680,976,401,953,275,76,994,581,640,962,393,270,569,820,894,536,735,832,704,410,143,48,633,947,319,242,668,931,766,293,92,41,481,845,764,836,750,151,987,506,7,18,966,736,902,722,588,784,965,331,707,404,434,779,679,358,815,540,476,610,873,573,995,962,760,414,251,214,891,177,850,489,369,978,440,630,804,204,736,813,12,684,256,578,283,606,575,492,838,478,502,4,432,460,488,691,75,137,111,513,776,491,58,697,670,601,819,80,89,573,635,187,653,853,105,136,206,759,240,938,234,296,922,252,773,993,883,669,835,424,623,834,2,881,120,673,395,997,232,11,42,798,518,585,637,771,550,472,728,539,739,278,962,690,886,998,100,882,65,492,446,293,800,273,91,997,499,718,839,280,54,889,446,759,690,271,91,594,849,508,476,41,474,984,632,706,683,137,360,503,606,92,901,39,357,293,477,987,318,861,55,436,667,937,809,882,985,202,694,874,385,240,424,415,817,42,202,716,511,83,364,636,586,874,821,649,407,33,38,387,76,166,559,83,17,779,508,230,281,917,36,385,205,396,607,716,202,814,395,810,156,511,412,571,280,770,11,127,486,397,377,789,225,597,538,266,985,846,929,788,73,877,268,279,385,903,194,403,175,625,539,311,864,838,707,969,365,547,365,766,959,166,355,702,950,33,729,266,996,929,946,241,313,626,543,436,794,915,125,425,364,408,722,488,435,835,707,305,792,776,233,470,548,22,212,114,87,704,7,295,490,146,756,560,288,230,853,181,869,114,123,259,359,182,227,735,868,312,86,445,139,434,695,933,297,215,145,429,252,718,953,175,816,92,452,979,378,721,826,396,546,75,992,583,171,498,426,457,90,864,15,183,988,566,436,433,251,277,14,955,929,157,938,487,927,233,861,508,134,724,509,667,760,129,74,8,260,843,581,769,542,467,282,338,399,480,839,858,863,628,29,300,870,48,431,164,394,20,413,764,216,926,728,849,651,438,795,929,386,248,941,898,762,79,925,961,613,762,900,85,495,268,473,454,307,313,213,266,543,130,529,506,984,409,432,247,879,686,530,483,671,29,624,823,377,989,969,481,553,646,816,864,718,237,581,33,47,118,144,989,125,536,422,748,864,466,435,652,486,353,218,351,251,706,195,602,879,958,921,177,812,821,622,830,140,552,97,366,232,541,969,289,577,469,966,13,301,378,568,263,313,693,458,93,543,64,449,825,217,949,363,429,781,775,29,627,422,883,745,992,606,439,286,684,522,448,401,773,328,757,796,733,133,421,712,632,283,890,803,544,424,326,325,597,857,288,760,517,180,693,869,736,465,178,132,961,909,153,450,88,196,981,547,646,351,201,828,621,58,347,276,429,448,298,543,993,737,820,58,795,953,975,911,743,240,537,757,486,288,447,866,611,538,84,116,670,62,612,410,788,18,384,259,792,33,933,183,530,151,452,615,654,702,507,977,918,762,474,743,155,979,802,448,194,660,204,952,844,760,432,829,781,724,225,728,619,152,273,969,115,240,919,544,545,639,429,270,220,452,580,534,689,576,492,55,867,504,397,805,987,943,488,710,127,10,813,704,235,304,804,765,633,967,200,558,934,558,554,953,957,174,469,680,836,202,829,955,295,960,724,429,621,967,553,986,396,509,850,402,291,435,596,934,880,288,905,819,190,887,465,238,290,381,376,342,600,690,687,297,181,48,895,866,976,381,265,791,787,52,865,351,602,717,564,664,212,354,874,613,31,469,534,585,201,472,289,566,986,13,872,682,4,100,595,176,596,810,121,533,374,554,929,59,917,900,378,944,196,390,641,985,963,798,46,946,839,712,394,360,658,608,190,471,866,76,667,356,653,384,425,974,193,592,10,301,386,27,100,33,526,989,778,382,148,859,931,471,633,372,208,349,199,14,590,369,113,432,908,123,307,20,105,667,696,190,801,779,463,430,627,893,21,449,170,964,841,835,276,166,963,830,976,13,50,304,852,255,149,709,280,528,43,551,843,98,340,573,89,280,675,520,170,20,845,694,128,641,195,269,912,937,795,143,371,730,143,152,0,72,375,366,779,611,316,397,194,939,453,338,347,301,273,224,494,718,492,61,651,935,618,901,602,761,496,924,720,596,353,435,113,39,388,333,965,288,982,929,700,473,994,281,789,422,23,867,834,471,731,100,881,700,390,582,177,843,993,827,975,372,599,263,267,909,251,290,408,566,857,916,691,351,129,549,114,220,529,972", +"254,902,965,739,961,569,545,76,296,626,160,301,74,773,578,187,880,799,963,642,285,329,181,837,103,742,592,255,337,302,809,640,930,228,304,380,550,602,856,126,64,529,60,225,345,863,974,928,656,791,541,614,538,385,853,938,751,712,977,311,859,745,338,632,851,233,917,171,905,205,464,512,49,302,991,625,764,393,51,250,662,283,398,399,399,823,17,785,803,630,738,478,654,176,877,827,587,680,44,912,516,5,392,881,953,372,56,695,36,570,652,130,525,732,392,674,81,649,892,638,572,914,842,210,602,426,387,674,950,740,995,695,157,586,95,381,145,899,341,244,244,157,5,514,651,719,263,284,220,761,863,151,508,869,525,775,940,899,868,682,605,573,826,202,558,161,647,367,318,538,426,760,73,565,657,704,597,974,451,786,971,288,348,965,117,354,45,32,234,910,339,716,775,687,437,867,290,36,384,350,53,643,719,875,989,858,546,534,317,170,87,431,126,142,222,236,791,392,619,623,895,129,809,460,331,787,678,19,539,22,789,418,249,181,37,306,999,702,890,770,19,393,797,504,827,357,115,225,300,841,287,469,303,892,733,180,894,635,898,438,564,862,771,867,706,995,485,364,636,734,919,193,306,899,762,385,341,311,489,602,933,90,307,96,825,316,12,260,983,575,524,91,977,719,574,964,640,663,529,97,880,487,262,865,326,718,367,861,250,640,584,686,166,705,248,455,235,368,660,114,214,421,668,495,886,516,917,757,310,606,467,356,872,542,357,614,491,415,975,27,375,945,221,811,385,889,465,570,355,383,887,114,918,620,570,289,101,32,28,623,800,113,705,587,247,470,7,246,546,343,571,514,299,614,338,419,750,281,278,871,571,841,937,946,566,492,753,740,224,589,407,4,189,346,702,288,108,688,816,463,913,286,467,895,929,921,936,9,396,531,879,594,961,972,6,672,599,171,884,989,711,901,754,124,606,550,705,275,316,473,596,770,87,269,870,250,326,220,844,825,907,669,375,690,798,998,900,7,484,812,843,764,356,249,122,327,623,656,148,205,592,634,381,30,716,247,70,208,417,549,753,621,500,745,59,800,747,217,457,738,256,149,903,68,448,748,790,842,495,688,407,92,800,5,760,32,206,634,160,864,84,936,775,117,409,693,473,362,730,223,26,473,287,995,312,523,977,283,204,952,93,352,258,595,160,482,523,108,667,922,111,22,287,862,330,634,949,724,717,137,881,786,84,855,218,36,709,794,813,20,204,459,680,378,648,327,825,522,250,189,252,616,513,885,979,397,694,982,386,207,691,916,770,143,253,94,687,789,587,664,746,703,611,119,404,739,678,435,394,742,75,596,773,341,873,803,882,257,830,903,54,811,292,816,366,190,287,255,526,656,457,154,730,246,818,783,389,574,10,595,146,384,381,616,319,550,568,16,672,457,671,839,504,149,584,570,897,491,81,391,760,376,230,525,923,314,330,94,923,657,284,97,926,405,427,208,463,369,22,821,177,67,634,595,497,914,450,344,103,347,200,773,962,173,97,4,24,295,995,147,394,400,986,918,67,129,144,888,21,846,646,366,261,667,208,659,888,568,913,411,772,871,873,593,168,929,840,464,138,426,174,23,968,57,231,141,951,406,109,30,844,140,312,119,365,257,587,706,218,325,816,387,505,580,933,529,270,306,381,968,715,517,352,723,809,269,753,779,92,452,945,699,74,855,682,471,377,916,25,546,503,85,417,814,17,983,209,226,231,843,261,919,853,975,959,660,47,177,668,795,610,604,408,235,370,105,52,804,997,160,688,615,905,329,648,196,107,43,24,613,276,691,45,33,438,980,184,988,363,764,442,168,409,486,976,600,900,687,924,419,450,659,169,333,498,74,962,616,366,745,560,199,227,397,295,154,403,477,607,867,408,169,254,378,886,723,190,563,341,676,852,446,120,296,519,391,872,159,969,977,453,811,572,653,378,266,736,134,172,647,626,292,875,504,390,440,806,926,396,348,964,901,991,573,534,764,339,412,275,868,202,880,727,991,946,568,602,334,824,166,128,410,538,980,14,911,372,382,572,399,98,341,638,356,945,100,473,943,52,560,72,0,784,584,350,115,818,670,97,592,344,734,201,445,110,493,872,470,826,850,945,780,48,883,44,441,261,302,245,29,700,246,910,694,588,93,488,221,171,103,515,195,565,49,353,278,332,180,142,941,310,240,574,858,863,509,59,234,143,240,761,564,563,176,600,68,704,532,13,767,611,951,467,659,62,808,559,588,657,560", +"215,22,727,799,778,650,229,257,878,436,374,947,441,809,449,757,231,159,785,374,476,504,881,52,401,638,563,445,575,838,776,129,272,979,333,834,939,266,707,210,844,912,684,484,386,288,24,624,834,858,586,352,218,751,358,858,85,561,233,936,735,924,101,976,547,801,661,817,386,919,754,760,775,897,945,458,913,273,462,190,607,25,856,535,72,844,435,553,488,491,861,197,499,743,752,739,995,782,174,149,884,998,219,331,808,957,803,810,833,922,96,975,434,427,272,46,684,445,937,351,306,433,368,467,905,395,686,266,456,125,410,258,930,207,847,502,400,268,762,332,33,246,609,579,852,60,45,594,84,951,53,558,159,361,408,696,588,350,295,190,368,901,303,408,545,444,292,988,590,536,186,871,791,469,450,599,779,130,819,739,373,501,29,366,357,316,47,330,819,402,262,375,523,787,237,530,963,793,450,933,543,817,438,924,375,676,521,928,695,550,247,767,282,133,222,831,232,316,800,359,350,245,765,410,193,369,175,31,947,846,153,476,407,719,158,586,131,87,976,181,590,800,941,478,570,818,843,936,998,815,42,363,920,43,280,665,931,105,505,716,430,142,75,568,189,78,655,935,290,622,384,194,327,548,181,726,281,956,299,828,602,873,6,250,184,430,687,578,242,771,515,95,884,855,785,162,23,746,432,641,811,509,202,479,107,721,394,764,737,617,573,2,444,518,285,293,837,846,555,203,599,937,526,316,825,148,721,767,893,610,817,451,478,333,632,880,176,585,288,359,451,939,447,744,852,627,426,119,14,444,511,258,584,432,635,728,39,743,266,277,840,214,85,264,255,68,847,245,650,572,697,404,591,421,30,193,942,752,868,467,410,422,546,38,897,139,858,968,994,215,915,120,687,342,270,534,469,370,208,190,990,671,620,586,677,778,851,418,114,793,664,571,976,239,856,932,722,857,917,828,493,959,949,334,876,465,626,310,380,841,355,61,356,54,149,93,921,352,874,772,469,805,409,967,681,101,469,959,120,368,287,144,603,654,612,675,371,600,718,499,922,495,286,295,408,776,800,352,599,703,480,114,738,566,910,943,344,111,809,964,320,433,278,727,105,534,122,715,556,967,473,313,420,826,546,396,988,253,516,373,694,822,71,688,911,302,35,187,196,194,423,959,774,189,96,137,357,941,390,861,737,991,297,211,521,394,498,701,608,662,894,950,444,177,279,746,44,42,268,800,32,96,840,359,34,675,442,628,60,887,28,548,964,85,109,495,401,308,905,933,741,719,218,657,237,255,907,117,395,817,704,115,779,528,282,348,851,860,434,560,473,273,612,269,941,205,704,998,82,744,250,486,631,453,283,141,280,218,821,248,727,208,256,619,8,386,112,813,255,145,957,409,787,257,139,861,882,190,79,924,538,601,617,676,261,801,52,588,158,463,967,245,83,635,966,716,320,857,870,900,318,654,743,42,366,767,421,129,721,521,750,418,715,496,685,691,688,215,343,521,263,376,82,40,897,264,539,83,360,79,143,996,615,130,164,416,230,804,388,211,117,942,140,862,809,888,780,808,430,25,806,840,477,579,331,679,862,430,37,323,331,938,857,67,631,833,830,407,720,179,696,869,378,82,133,979,447,810,401,242,108,812,633,256,751,894,203,158,671,212,327,963,703,946,993,885,838,577,455,46,251,560,949,254,61,813,696,460,628,527,434,831,349,149,727,876,529,735,636,52,54,943,139,355,93,918,337,462,957,956,654,375,138,714,829,496,366,982,503,383,746,753,514,197,269,729,97,473,554,715,705,454,1,408,568,113,850,699,536,207,457,530,63,523,239,916,264,628,485,200,944,197,910,357,228,414,658,514,576,348,61,435,758,86,761,322,928,346,789,968,768,826,706,917,229,931,326,395,679,655,346,884,127,953,227,631,139,146,744,83,732,229,829,618,606,754,427,546,563,514,483,205,468,2,184,925,472,971,342,784,859,572,78,459,347,668,953,484,110,379,303,41,548,618,984,365,358,103,692,956,361,851,545,399,308,121,426,501,621,925,635,972,900,788,892,440,748,497,182,466,679,409,459,834,650,632,738,338,949,747,375,784,0,993,670,515,770,902,38,973,708,267,667,419,762,966,116,647,780,94,615,722,174,619,768,256,366,951,147,982,329,512,755,413,958,566,748,395,368,583,336,75,789,653,131,667,108,675,492,692,2,328,829,345,193,547,136,116,797,701,221,886,802,764,257,877,533,41,362,262,288,192,987,376,40,474,492,744,702,297", +"559,352,270,175,84,117,847,554,683,213,154,6,833,901,136,294,600,678,740,593,714,75,851,307,740,112,534,887,803,618,632,968,59,972,103,395,551,312,569,737,90,139,21,452,100,260,591,285,112,531,641,484,724,855,809,592,234,22,157,253,924,982,658,311,205,290,657,534,296,975,907,563,719,746,418,920,352,839,852,441,175,35,241,419,30,992,68,888,503,722,466,972,53,413,946,397,316,189,676,837,450,71,250,708,699,124,531,950,450,53,540,604,810,235,570,774,790,151,624,898,621,235,679,282,915,614,629,635,920,366,907,698,34,494,803,686,747,26,288,270,986,515,71,490,849,355,847,281,259,477,485,886,609,229,518,730,691,538,135,503,939,891,656,678,454,491,964,532,226,109,846,328,235,625,201,611,852,308,73,208,532,564,499,979,298,196,332,358,399,54,722,47,599,369,188,213,541,847,855,925,269,865,992,750,23,593,647,445,626,214,636,500,569,240,269,576,750,300,289,993,347,15,263,14,667,134,680,558,87,821,785,496,484,520,347,911,142,457,615,338,845,758,381,677,777,495,569,739,123,255,559,99,888,433,287,144,432,960,934,573,898,328,345,738,467,574,492,449,381,718,656,356,992,264,112,184,35,580,537,504,394,744,395,986,866,434,573,187,203,750,690,78,101,84,342,291,633,366,154,590,369,382,62,323,545,236,909,381,121,260,548,421,208,824,359,329,742,414,532,430,686,12,516,181,648,290,869,55,244,58,604,793,62,838,439,667,310,284,358,643,273,336,345,971,452,254,41,148,350,220,626,796,572,398,423,698,124,487,504,667,952,258,348,905,967,432,717,371,535,121,828,185,793,8,824,232,87,75,75,706,556,508,450,993,544,910,888,658,232,630,243,318,386,204,100,126,719,96,355,717,348,38,926,948,330,765,661,346,449,45,744,647,960,118,896,118,768,611,7,310,27,389,668,235,572,519,669,40,482,738,845,812,122,601,894,836,425,350,311,881,419,701,405,277,452,58,78,840,216,734,949,40,846,824,264,200,98,797,980,810,246,398,759,652,931,424,704,154,184,367,210,773,335,54,372,254,125,17,307,604,177,860,54,547,854,383,80,552,716,544,403,319,397,913,895,909,710,866,46,826,309,596,505,121,677,629,606,191,297,402,759,555,868,266,348,809,112,146,819,291,346,163,42,273,733,210,640,423,445,318,423,264,976,587,482,231,593,286,724,899,713,46,337,792,655,900,772,845,752,74,486,734,325,602,388,107,702,313,293,879,845,471,218,139,287,792,679,232,634,630,598,7,912,461,910,542,172,471,275,132,633,388,745,230,324,399,340,575,419,315,317,553,986,907,124,511,533,69,963,869,63,50,491,239,289,909,769,776,885,202,373,229,319,63,351,746,122,779,21,555,463,931,236,931,408,772,210,578,582,617,58,125,291,89,764,286,408,123,625,599,454,484,555,916,673,996,897,344,400,75,471,574,281,310,801,905,757,728,788,268,980,445,756,100,13,729,951,563,199,479,104,661,798,215,982,851,816,233,674,214,152,874,386,401,758,511,181,562,621,839,436,113,327,166,590,597,715,423,272,322,882,309,122,831,920,792,886,161,919,401,281,636,889,446,852,889,54,640,496,937,165,974,691,815,462,841,364,896,257,658,635,952,156,654,397,95,890,27,203,800,941,152,784,154,525,155,244,708,321,917,388,614,559,480,530,729,91,130,58,508,459,943,958,960,23,181,521,497,529,938,324,205,296,759,245,951,304,546,950,81,659,652,124,189,278,125,311,417,395,619,300,579,379,646,63,966,866,500,38,603,945,371,205,698,145,125,35,670,489,658,401,475,28,158,219,548,574,255,473,996,295,734,220,515,43,861,656,94,63,651,143,500,825,346,600,393,346,14,938,820,287,35,225,744,605,17,467,774,495,511,927,364,527,154,241,140,833,324,828,502,715,754,94,542,377,346,41,39,395,430,921,138,281,296,979,355,478,418,563,254,988,186,373,489,69,357,648,845,468,178,712,532,338,557,920,127,929,690,628,348,736,800,451,625,560,521,968,542,522,594,413,499,551,856,674,259,799,501,918,718,366,584,993,0,602,543,713,255,864,370,936,393,811,677,64,771,496,996,920,597,705,945,185,430,554,493,552,924,917,456,990,134,526,511,615,942,165,850,853,846,819,359,274,176,859,606,980,473,256,397,573,39,679,474,218,811,851,535,763,766,513,638,884,201,998,726,362,726,746,768,224,279,722,652,551,67,399,797,832,130", +"184,970,191,752,857,589,542,170,909,460,921,945,296,116,685,968,36,227,137,445,724,306,892,353,332,511,304,51,375,43,860,489,142,809,997,655,224,103,71,217,668,560,463,895,703,848,875,742,50,595,27,366,154,682,196,605,259,976,624,293,567,513,270,101,408,396,531,774,795,852,530,839,99,376,51,611,111,352,943,360,829,936,905,704,16,597,424,373,313,76,467,848,771,725,402,288,239,966,867,990,787,276,694,961,422,179,359,850,848,951,781,707,588,827,747,856,321,196,264,187,260,807,81,960,90,397,675,745,685,571,90,805,595,714,549,219,607,547,994,353,488,310,100,656,476,430,993,570,399,916,199,40,772,895,734,564,613,39,28,89,712,768,435,881,499,105,620,434,610,401,83,319,656,409,948,241,786,436,182,453,608,785,953,334,76,523,606,886,30,574,175,525,476,438,461,592,650,669,996,400,543,748,819,297,470,510,864,324,383,146,97,136,111,720,905,701,607,501,348,739,290,795,300,810,458,388,331,712,582,454,683,331,18,130,74,764,241,245,844,125,77,826,192,273,663,748,315,789,761,581,638,884,614,442,517,816,720,17,597,277,130,546,144,115,725,378,154,925,57,19,939,60,375,516,187,555,62,570,908,637,484,728,345,873,483,889,338,887,410,71,485,462,109,634,975,221,700,390,549,932,905,132,427,445,361,950,315,305,465,503,126,760,562,142,573,368,78,840,473,482,355,500,231,773,782,942,129,751,226,957,151,205,586,976,165,416,730,903,608,143,880,730,34,5,424,144,56,891,280,472,157,549,482,498,48,331,173,81,839,939,595,289,860,343,308,614,561,671,131,949,625,543,600,44,797,611,399,60,649,349,100,195,122,626,918,631,158,363,296,48,674,458,477,23,205,257,887,210,480,460,168,658,938,984,926,608,808,531,129,49,577,205,743,896,152,182,123,235,764,234,393,700,478,831,864,873,844,395,834,858,855,372,451,308,103,338,961,816,444,104,697,382,797,911,687,549,890,801,138,495,904,177,132,247,908,632,11,341,496,48,943,924,797,882,73,701,986,101,110,516,488,57,396,34,999,588,993,807,829,178,415,12,418,565,542,903,16,19,297,88,588,374,141,545,939,488,343,182,945,64,601,592,143,823,222,821,551,162,938,993,714,396,379,656,125,721,467,186,820,550,358,756,815,440,212,764,588,623,202,42,247,271,565,695,413,656,35,471,478,719,73,453,985,922,535,888,841,646,330,895,798,439,3,744,850,315,337,51,348,14,740,345,280,566,10,424,688,508,839,68,764,282,594,951,42,460,59,368,539,609,734,294,333,956,969,369,905,528,828,228,409,274,15,723,926,815,364,416,667,859,731,283,487,881,773,719,818,143,21,85,859,69,195,759,865,163,141,905,700,791,798,146,87,431,392,804,670,461,878,520,974,806,688,995,177,460,38,18,712,377,935,995,509,546,385,336,184,33,899,180,347,273,743,424,42,1000,61,658,63,282,329,854,959,613,257,967,854,23,143,594,628,348,400,95,239,955,6,291,486,435,891,378,26,178,876,398,635,818,729,225,979,543,76,113,33,673,731,506,198,63,7,726,514,209,902,930,227,443,707,508,553,708,905,188,970,661,738,774,584,646,616,852,359,133,998,784,386,60,742,392,666,206,128,819,651,881,629,766,333,610,469,666,751,273,747,185,893,406,197,464,678,737,801,946,8,272,651,801,386,628,579,167,137,43,502,256,733,339,93,464,57,398,164,479,331,593,682,515,852,485,110,983,316,894,773,46,330,1000,128,146,682,610,919,944,718,728,111,990,727,957,817,350,763,988,400,240,774,267,111,57,487,849,917,831,736,283,664,586,187,21,469,916,607,150,951,805,474,892,676,754,581,313,559,920,456,18,227,121,751,535,538,856,91,954,275,500,426,524,76,963,582,326,988,651,390,642,170,322,845,676,836,641,956,374,324,417,460,12,176,643,78,232,624,324,616,467,801,978,405,656,662,210,461,83,791,904,847,896,242,411,615,840,31,726,274,902,525,847,377,777,270,799,977,156,82,876,708,35,259,438,517,610,547,522,417,567,307,197,186,939,779,350,670,602,0,599,368,887,919,733,446,795,514,534,515,534,103,706,85,428,347,109,906,365,715,418,901,148,973,935,957,278,74,624,355,55,557,441,813,187,575,541,377,445,514,706,801,632,466,101,692,103,31,678,520,781,379,256,680,447,634,153,543,457,766,221,958,382,523,514,399,290,942,145,113,136,586,245,64,947", +"805,140,780,288,877,546,484,815,928,34,531,40,69,93,148,252,528,626,249,470,721,69,923,110,17,979,416,819,944,619,822,998,909,818,263,90,440,294,46,211,406,603,598,244,603,850,381,740,937,813,432,935,774,113,598,209,605,238,597,352,415,900,327,882,326,194,531,156,746,210,561,841,824,418,975,836,135,960,695,784,319,9,297,280,101,610,75,16,596,871,803,66,259,665,968,437,815,731,982,251,437,656,846,146,83,100,54,496,928,231,213,169,218,39,664,391,15,815,719,357,158,944,538,611,706,114,859,189,499,763,891,335,454,624,736,8,926,404,380,866,182,672,362,304,436,319,811,420,233,4,172,296,692,82,663,714,332,969,845,461,884,971,183,311,85,5,491,598,471,874,966,597,87,94,219,747,780,906,974,383,384,381,928,494,691,503,52,917,124,241,781,846,18,125,485,941,429,479,345,201,702,35,279,872,178,888,496,986,194,298,40,962,352,105,141,607,751,747,985,696,321,701,910,881,592,4,984,601,370,714,761,675,539,897,12,452,356,447,234,152,575,134,892,421,852,449,296,725,586,308,631,235,161,796,455,235,742,715,712,228,375,952,390,847,253,733,644,847,656,565,834,579,650,468,640,963,110,120,6,243,34,590,340,2,393,808,916,668,971,693,270,349,304,136,702,890,140,619,784,417,802,584,858,752,208,540,112,70,707,181,161,343,653,953,113,339,999,86,600,223,578,14,127,300,229,969,808,31,696,473,205,675,825,956,885,469,488,22,33,600,332,4,492,934,10,768,288,607,587,806,346,601,609,631,116,149,48,982,941,522,759,26,819,34,564,973,788,60,584,50,151,660,873,610,145,781,40,82,315,464,957,526,202,559,135,809,982,389,924,441,289,953,158,836,327,690,175,571,569,609,539,709,885,538,881,799,83,402,145,393,965,722,429,744,605,535,239,429,290,229,858,716,134,1000,51,460,626,854,773,149,437,409,565,225,409,67,50,934,667,529,761,70,107,284,622,527,380,122,501,619,257,248,925,264,728,132,645,281,946,191,412,764,303,899,36,929,744,26,947,166,217,101,299,147,411,265,583,469,265,230,646,479,506,94,287,289,845,549,907,71,889,769,774,9,68,429,884,125,287,345,585,205,292,33,68,68,909,693,896,956,230,428,819,811,83,519,504,313,66,156,925,921,332,16,565,238,685,652,592,77,204,348,864,702,782,474,675,879,374,451,125,184,591,949,826,497,122,152,340,89,827,771,388,535,204,74,730,642,268,567,720,831,884,931,662,841,107,509,800,970,728,153,371,296,726,271,904,413,732,208,207,853,145,991,441,143,783,779,898,269,778,193,343,195,825,861,340,906,569,292,290,255,438,863,728,421,474,774,912,857,57,981,465,856,941,338,586,754,114,492,909,402,604,829,694,279,543,705,506,444,241,575,81,687,34,146,168,697,313,966,316,415,20,137,975,816,210,531,377,874,629,933,663,5,371,175,402,372,569,435,15,747,738,427,607,178,344,101,341,731,565,879,538,459,258,210,252,747,702,701,911,917,225,426,198,753,407,334,29,36,128,470,463,172,393,69,710,542,748,7,93,406,110,57,53,99,908,870,766,860,81,320,964,19,141,165,301,297,587,270,896,638,229,106,793,849,157,726,395,834,389,410,756,560,754,805,18,636,899,90,651,519,748,230,810,487,423,605,720,38,732,680,983,109,956,98,322,544,909,487,35,748,936,432,687,793,890,539,244,548,240,166,851,124,526,693,816,920,215,209,799,145,573,445,271,402,822,873,506,823,67,254,955,114,764,286,305,446,384,151,572,555,374,903,727,909,348,251,137,382,800,654,494,340,500,830,668,299,535,843,476,413,146,492,3,91,666,522,957,98,328,50,632,765,595,427,187,701,658,642,329,457,164,663,225,582,330,770,959,37,957,223,74,997,665,890,41,309,118,94,605,254,674,415,154,873,845,576,239,198,697,645,835,552,677,455,641,459,235,144,717,920,674,871,274,275,494,145,101,475,531,588,637,908,596,85,58,990,10,936,820,76,294,804,521,742,377,895,606,7,50,696,27,718,914,742,790,225,981,589,611,115,515,543,599,0,274,560,252,622,217,169,975,471,589,816,970,581,876,138,798,759,202,673,422,242,149,881,835,521,862,654,14,117,614,706,141,266,134,864,54,807,112,41,691,980,621,61,956,203,445,267,513,472,384,227,252,309,923,961,944,508,331,283,486,478,200,284,924,355,378,780,796,372,491,532,669,629,774,814", +"737,513,59,861,378,981,350,886,555,753,412,611,896,356,789,581,284,255,484,920,543,466,662,187,707,819,810,129,722,562,995,757,247,657,508,854,209,759,396,544,779,663,217,689,376,384,445,917,516,677,587,551,497,78,508,380,858,963,958,928,786,493,596,825,819,422,742,761,103,708,488,653,991,790,757,45,497,610,750,205,919,442,157,598,85,951,152,483,977,808,419,211,443,565,853,165,96,725,149,486,979,403,407,82,109,94,143,565,415,93,41,957,139,270,122,669,608,752,434,393,111,789,290,79,280,319,236,555,637,252,947,734,897,656,144,12,520,964,369,874,581,592,877,751,193,877,98,118,488,145,982,887,123,227,590,974,704,375,231,920,152,5,287,472,625,422,476,718,405,950,150,21,537,749,218,176,63,427,51,259,88,475,757,887,175,150,569,608,36,666,595,997,397,713,238,130,210,614,52,282,946,768,915,386,437,520,988,639,57,251,432,924,311,437,944,982,446,893,758,627,12,630,89,828,605,37,828,347,509,524,829,803,353,578,493,496,561,707,715,842,882,405,91,297,278,412,418,392,408,611,556,85,833,787,388,631,295,96,78,42,864,973,970,87,362,531,372,729,712,830,43,141,497,762,486,628,270,187,512,337,696,818,490,653,404,869,28,423,107,57,916,844,491,842,880,539,691,71,153,790,461,483,853,390,592,563,266,602,158,888,341,740,435,44,514,664,366,484,995,292,382,361,142,117,561,901,482,727,985,952,136,239,151,55,544,499,327,38,29,957,190,728,573,530,867,890,359,532,730,252,57,946,649,388,419,773,901,400,323,958,416,500,571,235,529,631,131,850,168,875,203,779,926,403,464,437,701,512,783,385,9,159,51,289,698,970,859,434,480,196,293,236,187,9,439,160,669,725,569,328,502,732,840,967,291,385,899,71,670,684,303,602,470,874,337,238,585,530,801,465,857,889,219,542,549,373,271,551,865,623,316,822,716,300,429,242,993,206,24,160,573,901,736,813,654,364,857,142,531,482,325,178,7,651,922,984,251,43,852,235,829,25,180,580,175,960,3,101,23,106,145,970,924,882,301,153,206,876,562,976,979,266,773,417,768,67,960,192,397,538,212,195,682,691,100,227,443,236,726,552,286,234,406,366,192,858,90,773,377,69,470,933,172,783,303,66,903,727,286,461,375,26,795,381,723,702,362,889,421,284,931,206,259,849,1000,683,516,945,187,89,317,813,20,381,835,802,777,556,388,218,399,394,3,877,230,192,312,441,407,959,977,521,117,637,289,320,228,683,660,10,960,257,584,930,604,741,2,738,707,635,495,888,694,498,389,639,335,131,373,398,788,534,437,836,135,59,848,501,602,821,134,454,725,758,829,859,551,281,956,282,270,476,452,206,634,134,427,177,945,671,430,140,331,81,905,919,106,335,860,625,150,671,39,675,985,208,351,557,378,612,44,492,707,574,314,345,611,140,657,90,440,647,752,433,596,338,25,788,5,36,838,962,640,798,979,978,354,75,736,831,340,569,297,73,166,286,171,895,733,198,162,7,247,250,664,84,505,832,212,881,738,396,568,657,623,58,86,719,112,178,371,107,100,384,198,671,583,843,892,203,475,434,113,327,37,873,225,489,874,59,715,462,272,899,937,870,694,35,388,457,827,209,675,994,459,653,307,769,104,26,661,513,86,622,966,511,182,262,879,67,597,237,148,783,108,681,3,256,768,838,789,950,383,824,819,269,817,682,968,358,392,411,558,309,782,112,397,340,575,841,607,748,45,982,236,944,66,569,78,222,249,95,200,797,951,881,21,579,565,932,505,705,325,821,210,232,471,283,594,173,675,475,412,708,795,718,149,631,232,834,818,307,253,929,887,165,634,80,562,813,339,38,630,792,976,148,265,663,177,257,688,76,869,424,847,789,896,802,43,397,986,348,570,20,914,404,794,589,581,976,13,643,153,55,774,228,24,83,520,170,66,990,858,949,121,706,339,704,502,483,314,804,20,187,87,795,660,597,825,628,192,477,416,317,578,685,839,936,992,590,232,114,564,264,255,359,1000,570,267,166,566,221,694,90,82,664,947,891,801,380,316,818,770,713,368,274,0,585,919,300,952,687,262,714,572,752,119,713,801,4,581,349,453,213,580,959,682,351,865,846,347,957,253,96,918,974,833,92,22,567,121,37,328,27,751,387,603,926,846,67,827,570,932,281,814,172,354,845,161,357,637,197,830,897,357,260,709,320,194,769,826,161,625,915,843,997,950,44,897,724", +"774,198,213,39,987,572,678,334,662,14,878,907,595,155,974,759,785,159,89,356,342,719,956,617,675,569,471,476,101,961,173,573,527,471,134,307,44,721,556,382,7,380,782,370,121,303,508,630,30,718,178,872,736,967,972,82,410,745,20,111,779,424,375,117,490,459,593,131,664,967,119,356,835,800,572,8,770,314,968,89,161,713,197,840,572,631,199,847,54,509,402,923,969,760,36,194,174,755,602,167,531,248,43,708,922,310,29,364,949,727,65,969,340,578,66,467,444,913,441,534,549,382,737,161,614,633,252,259,562,582,349,500,746,32,877,907,621,458,541,902,482,791,180,710,836,705,599,67,833,535,411,733,35,988,488,493,559,519,972,546,799,927,273,13,90,142,116,920,632,946,70,43,644,112,64,67,544,392,451,730,181,199,719,932,304,44,461,725,145,547,113,429,697,218,861,924,897,3,451,731,584,749,395,707,536,10,988,329,366,837,391,663,258,645,105,611,762,35,956,646,127,860,236,555,232,922,671,261,908,275,940,940,532,700,904,769,822,126,115,992,989,591,541,201,66,49,619,710,859,332,168,639,854,544,50,479,635,960,413,370,262,272,138,168,794,707,118,666,892,845,386,252,637,409,646,690,434,589,395,551,872,616,976,224,518,126,973,175,833,965,468,185,908,671,16,318,387,267,546,485,944,825,395,329,472,766,352,481,725,868,344,907,862,9,174,966,235,657,562,55,802,555,105,869,722,748,975,234,761,187,659,42,832,236,637,178,636,754,805,859,280,800,422,652,356,780,605,157,233,861,326,137,67,192,955,828,167,466,174,787,698,677,611,180,200,158,790,663,165,256,460,584,652,137,851,197,301,644,857,62,404,971,677,183,941,861,683,104,125,515,158,709,163,215,764,556,108,172,70,14,615,972,117,759,394,668,100,192,390,220,5,804,529,313,148,996,283,457,638,791,575,621,425,95,35,732,825,306,209,502,599,588,819,36,613,112,802,205,586,13,173,789,308,801,34,903,423,617,802,846,890,816,8,226,965,781,778,578,480,561,986,144,217,233,819,731,347,346,669,117,915,337,62,920,600,254,601,38,828,133,842,810,695,789,180,211,613,241,527,755,720,778,291,446,190,567,439,423,987,863,200,424,769,317,140,540,453,912,929,547,142,64,34,861,807,741,370,973,535,397,786,246,905,135,350,29,321,328,135,459,986,966,44,671,471,196,778,99,284,240,344,494,519,822,792,70,582,607,896,401,235,191,21,302,448,473,42,720,965,987,128,124,958,201,477,531,395,732,819,587,388,991,819,619,982,105,258,783,613,621,412,909,320,86,781,229,759,62,591,421,566,260,847,549,731,361,629,789,103,852,851,398,999,516,940,635,108,35,286,8,241,707,369,160,417,991,149,707,29,681,328,85,27,193,196,392,120,82,311,581,218,795,318,793,417,184,693,665,248,627,425,10,318,499,988,314,669,792,915,920,139,813,825,105,333,336,533,373,854,501,914,944,714,953,25,656,795,111,87,293,324,635,781,732,165,212,515,823,150,293,899,473,820,685,956,987,881,618,752,132,638,174,77,238,935,196,669,463,90,417,162,366,556,655,12,425,231,607,957,840,23,380,613,548,586,628,696,812,992,837,865,684,812,532,638,294,754,232,92,421,416,835,288,153,41,466,597,470,884,978,776,818,323,689,78,801,72,472,609,994,930,10,337,412,581,983,430,521,887,428,266,70,781,188,416,226,421,131,46,122,358,686,603,747,621,171,497,930,769,963,635,938,138,762,646,812,843,846,12,658,269,923,543,762,577,493,374,276,919,902,322,861,359,541,83,116,298,428,23,92,719,568,760,821,901,571,570,87,736,862,324,561,348,19,85,921,335,942,673,831,155,668,123,515,746,658,665,970,272,931,293,218,603,667,968,36,563,269,194,952,48,57,336,674,869,971,703,232,469,761,918,678,244,752,554,973,594,266,686,733,391,307,746,793,975,569,554,104,781,342,557,969,71,895,968,830,311,392,386,903,759,466,822,327,97,627,29,953,243,963,641,271,760,129,304,609,280,594,6,385,320,448,945,677,349,702,118,353,711,140,397,670,902,255,887,560,585,0,824,596,585,443,140,114,37,705,131,272,29,945,649,809,824,962,980,177,519,933,919,400,559,934,130,224,780,9,279,786,834,697,763,492,49,783,626,153,371,845,442,647,262,875,871,673,905,285,970,626,574,339,725,283,254,903,541,381,500,859,529,632,911,351,940,152,774,61,118,616,766,519", +"661,595,694,40,612,213,98,878,809,142,387,214,33,936,534,997,581,979,91,843,15,323,725,668,569,869,547,890,228,578,817,673,78,780,309,94,853,936,251,568,892,568,640,817,657,219,617,970,186,389,670,127,570,225,376,228,591,912,775,343,985,967,747,906,590,411,347,524,102,858,901,570,191,645,617,485,716,752,59,167,688,632,951,897,929,756,584,88,509,728,361,578,638,80,838,598,852,929,200,135,957,91,67,275,14,499,119,893,775,161,370,374,565,982,817,619,733,311,745,948,400,442,446,391,274,903,509,151,962,192,516,619,563,442,996,410,497,850,702,317,918,623,187,169,572,256,38,608,178,168,98,182,877,68,2,10,592,424,862,665,464,865,115,35,542,138,202,505,258,425,817,816,837,183,704,152,876,376,319,445,803,452,630,33,882,747,646,417,854,212,884,376,318,248,558,519,255,431,742,47,238,355,956,815,561,957,727,480,437,98,387,896,682,834,141,785,6,66,538,643,422,839,160,587,468,219,516,83,789,682,832,658,376,388,850,704,821,971,385,483,893,585,300,410,209,516,552,759,184,490,729,332,68,906,617,708,475,397,307,907,264,557,450,569,968,89,604,928,623,508,564,371,127,270,150,163,310,781,430,555,26,935,545,727,561,689,201,110,398,281,544,660,613,575,171,916,246,254,537,756,773,253,148,855,630,645,287,442,58,777,853,563,807,276,653,102,38,234,761,859,396,162,8,473,56,123,365,982,580,45,131,908,702,766,617,275,739,483,979,452,326,468,99,553,579,734,328,234,458,520,103,800,265,547,146,92,222,113,328,812,999,86,707,407,241,660,773,665,587,121,941,99,623,359,598,645,850,728,775,606,666,704,296,78,799,478,768,746,326,546,223,521,960,830,490,165,491,651,115,577,178,449,712,340,438,971,752,103,526,492,538,362,164,37,746,450,898,527,974,605,533,625,469,81,366,241,939,78,664,728,274,657,848,726,259,980,3,370,236,133,566,12,369,10,925,993,34,32,886,764,401,387,795,966,114,931,747,862,392,59,760,661,94,905,475,113,387,509,423,333,799,251,990,139,892,117,520,458,181,996,546,971,415,366,399,725,87,150,737,559,361,783,484,569,213,59,558,781,258,312,871,298,823,998,645,213,14,851,665,566,820,675,551,442,738,7,493,665,331,54,655,658,102,99,855,657,758,234,324,72,847,108,726,303,920,279,85,706,739,164,26,582,727,651,570,81,803,137,947,467,487,451,767,338,149,430,937,54,915,492,13,520,472,645,914,81,923,674,623,148,855,401,531,502,176,986,278,221,525,706,583,352,915,116,861,405,14,609,617,386,548,203,733,293,402,664,310,517,885,307,474,374,684,102,863,52,867,524,81,434,769,236,721,714,496,608,192,812,745,352,707,353,681,725,244,826,321,842,984,91,475,105,621,467,798,330,497,358,245,17,263,430,168,766,308,901,767,381,490,587,730,494,54,593,71,450,977,276,181,636,314,665,362,630,676,666,329,511,636,544,745,716,582,798,993,448,881,63,61,432,890,701,324,82,686,871,992,821,435,675,521,967,315,976,691,511,138,945,264,93,50,474,378,294,282,676,574,897,657,27,657,764,47,668,123,952,820,98,686,800,166,679,10,489,307,801,563,621,710,350,17,432,707,630,608,248,433,291,246,347,926,832,218,150,709,994,630,106,276,553,195,941,780,430,92,320,728,337,240,651,62,735,609,392,270,616,619,836,512,226,780,567,661,97,888,105,319,152,796,500,194,833,700,694,55,10,553,354,388,779,990,40,167,170,879,550,141,300,26,49,735,208,521,854,79,838,573,318,410,44,434,199,744,702,577,343,464,858,571,296,855,658,230,331,312,347,168,728,196,813,280,593,826,926,903,900,550,208,889,501,686,595,496,466,64,976,677,939,420,648,805,298,49,14,487,722,13,515,570,679,52,516,762,340,386,922,409,245,411,756,588,721,527,699,966,677,519,789,502,734,913,719,739,949,386,670,213,874,825,986,126,334,788,654,432,418,479,253,835,198,805,651,300,183,827,748,151,145,358,854,979,114,512,811,526,33,260,192,136,491,194,97,38,864,919,252,919,824,0,288,97,717,36,613,471,928,281,880,158,342,822,446,140,758,281,953,934,773,978,404,762,443,717,757,429,460,45,461,51,151,138,979,441,688,400,439,282,981,100,695,168,871,630,884,675,36,195,325,102,106,268,759,962,423,200,20,996,871,644,297,481,815,211,631,988,86,33,580,571,243", +"784,85,381,346,313,572,302,421,410,362,444,218,880,168,697,495,481,364,170,110,430,401,849,570,589,719,572,540,161,225,952,339,151,137,853,758,96,940,619,409,828,23,138,260,701,337,632,14,965,273,348,307,834,51,116,146,829,961,331,887,406,194,220,271,363,425,365,787,92,119,363,616,807,21,295,465,843,997,194,240,537,152,916,291,583,242,19,628,596,670,902,754,575,209,579,310,584,482,276,301,894,257,587,700,847,572,125,30,106,509,623,86,581,408,913,556,694,388,937,64,467,969,100,608,41,721,164,389,836,521,562,812,433,79,424,161,550,805,805,997,335,331,444,462,966,858,372,515,761,7,833,600,714,37,760,299,713,726,330,895,26,149,630,129,853,683,913,930,701,913,537,896,744,956,639,211,579,509,959,699,828,437,300,686,257,824,415,122,527,504,312,781,831,541,844,893,421,889,146,588,131,227,244,599,609,943,891,883,503,524,648,501,739,268,60,734,987,850,869,516,393,620,584,249,837,252,242,865,947,393,572,773,394,773,314,476,46,172,439,708,114,559,5,523,275,847,724,960,376,689,741,355,608,145,526,743,558,119,206,261,944,562,950,500,361,662,818,518,59,597,260,160,855,483,203,641,808,310,589,579,804,356,762,437,794,137,381,697,942,175,746,968,652,307,232,597,768,93,776,681,9,822,542,290,449,672,138,150,891,15,946,510,620,442,83,869,197,69,813,763,516,208,380,811,790,397,646,587,987,323,589,951,561,459,69,517,989,84,535,919,265,409,737,875,593,564,243,902,573,77,482,478,685,157,896,24,230,408,480,604,832,471,877,336,927,329,83,808,643,393,112,41,730,600,957,221,1000,698,7,512,105,621,638,658,652,6,308,604,172,35,297,115,47,922,505,441,963,989,674,717,126,396,737,562,42,396,221,924,985,164,149,677,825,76,352,531,80,147,767,90,674,444,517,468,311,343,377,199,332,209,471,121,756,251,994,394,675,977,168,514,97,31,199,55,647,163,337,228,517,47,30,673,404,388,643,708,635,124,547,759,599,309,907,151,917,968,945,1,152,343,958,784,15,485,99,174,156,480,412,849,20,185,610,886,53,116,397,859,783,738,789,810,993,55,511,485,726,284,442,848,186,889,700,183,3,127,992,681,500,304,430,936,845,285,646,127,677,923,474,734,558,219,239,388,446,109,569,575,876,3,690,625,750,193,486,429,718,693,364,773,192,140,695,596,919,934,427,966,934,484,873,389,686,953,139,309,458,333,382,424,295,811,775,384,251,7,365,838,440,908,563,903,628,424,793,960,694,433,154,182,257,772,366,804,368,623,900,570,598,980,738,968,695,112,481,182,123,948,36,481,82,520,411,846,35,273,29,638,262,744,262,982,992,975,833,909,24,792,909,423,950,779,465,806,136,503,839,236,970,257,2,915,196,713,202,14,252,506,985,26,564,718,628,680,540,869,45,362,104,693,763,513,817,11,65,611,682,451,800,200,605,242,384,890,718,273,983,634,211,149,72,452,653,900,31,350,62,675,572,212,863,200,645,237,633,482,119,291,505,545,607,907,287,251,967,447,723,893,272,943,445,844,245,488,764,146,741,183,542,806,219,566,840,165,224,188,757,663,520,697,104,398,808,564,140,442,446,573,94,900,938,227,861,23,103,503,255,538,838,346,445,931,187,820,817,500,982,480,82,976,449,446,701,373,768,623,907,229,656,417,939,216,523,428,565,151,715,396,75,785,641,567,176,889,399,688,971,463,268,569,734,787,730,472,637,416,963,457,489,10,168,641,988,447,824,4,316,570,500,824,520,92,739,203,717,223,513,647,723,590,491,503,186,565,914,222,834,403,886,775,997,588,552,432,823,211,187,359,917,142,480,924,204,764,58,501,984,153,91,382,302,106,644,397,874,655,462,162,210,388,761,115,945,800,504,370,704,358,175,819,682,88,702,382,781,828,806,136,480,594,836,648,353,254,960,367,798,10,952,519,742,877,864,893,870,249,415,513,475,908,809,200,495,742,454,54,294,408,223,875,491,922,25,371,809,343,895,395,479,43,501,119,199,51,464,321,77,617,198,317,939,592,973,370,733,622,300,596,288,0,854,540,631,523,48,637,940,427,183,446,156,261,526,3,763,723,275,270,383,57,843,248,241,650,599,854,523,891,504,219,537,229,713,939,351,123,303,469,915,330,609,433,940,487,18,295,892,498,283,902,223,565,573,561,699,747,427,839,827,675,936,962,282,300,605,613,874,485,298,246", +"206,601,534,963,8,239,503,543,121,412,129,853,3,191,963,21,783,280,299,647,254,657,521,69,501,344,932,732,746,948,519,137,766,805,134,246,243,495,544,502,103,589,295,175,383,58,217,863,893,272,729,342,364,923,745,902,700,978,43,250,966,881,434,365,263,939,660,239,635,975,423,691,937,430,824,93,19,115,376,205,41,62,778,566,32,523,682,177,977,441,300,322,878,583,83,917,688,41,799,105,794,503,860,561,216,131,171,353,60,357,847,437,421,669,51,597,549,225,56,319,127,933,80,708,617,313,9,965,142,935,598,449,4,419,323,397,696,129,206,792,817,400,828,427,848,130,922,372,375,324,402,715,900,73,607,563,521,66,958,332,514,948,469,968,141,925,184,168,916,164,651,267,167,121,426,847,610,691,768,129,776,173,794,310,677,143,971,337,271,412,968,513,598,909,233,746,169,678,529,241,661,133,305,843,193,560,138,320,257,41,332,626,647,697,678,187,430,429,359,251,663,268,658,725,506,988,199,213,743,230,912,929,888,498,906,815,604,177,159,578,885,687,249,67,805,208,771,709,868,304,720,301,785,559,879,201,22,868,600,90,991,119,358,864,357,409,540,738,523,583,891,198,154,350,354,273,185,445,754,403,96,262,556,746,256,18,159,88,362,754,245,744,267,798,511,320,237,880,100,290,541,594,713,327,979,716,46,314,50,458,265,431,782,861,776,233,208,195,289,984,132,735,392,398,845,863,562,762,75,604,3,638,288,648,316,573,18,838,711,968,157,432,630,229,550,517,829,610,42,157,961,432,255,652,988,1,560,45,665,562,730,94,126,746,486,731,827,685,90,688,461,748,989,15,335,341,882,380,663,526,421,772,600,470,602,357,595,30,206,425,799,417,162,991,72,136,893,23,435,150,75,955,138,352,124,859,195,505,695,217,406,612,43,485,311,51,758,399,751,406,548,502,495,151,388,38,489,952,328,422,156,856,763,94,306,663,530,533,896,725,177,894,884,996,334,304,689,718,746,93,327,463,895,44,318,616,627,815,739,780,606,505,669,665,27,987,171,751,311,872,884,792,283,365,636,515,120,347,609,393,164,243,633,278,30,61,282,213,845,621,917,608,721,331,549,42,174,212,827,770,57,578,260,684,690,568,989,137,350,398,89,228,266,627,617,562,369,121,386,57,882,823,911,612,884,131,697,595,999,701,669,361,858,568,629,440,268,233,662,710,743,754,461,441,109,920,565,928,930,777,985,163,466,124,339,681,318,923,965,135,394,636,180,449,854,98,109,146,992,289,656,461,877,531,904,685,795,937,350,537,372,667,85,139,505,263,750,616,495,945,165,573,908,910,881,957,458,723,460,36,896,233,176,507,245,957,120,683,376,270,348,61,772,504,955,634,582,471,235,897,814,265,265,375,915,944,251,267,759,776,840,31,747,871,800,770,291,74,693,436,442,187,586,373,104,817,25,45,498,789,473,398,735,677,69,260,446,256,571,104,511,635,753,855,87,395,280,902,688,482,705,431,290,868,861,348,637,505,536,377,123,560,277,605,820,93,637,511,791,926,911,396,147,693,615,540,767,152,600,810,939,985,625,424,757,55,751,407,384,425,270,81,284,332,749,906,221,904,615,766,935,636,857,796,907,77,67,660,178,780,510,495,321,398,754,302,707,573,831,962,814,4,585,250,694,751,42,255,396,416,387,307,216,510,941,861,929,712,357,542,673,742,138,439,529,886,157,181,971,293,86,588,824,341,363,790,342,217,662,206,627,715,102,860,397,163,196,364,616,589,498,207,44,929,751,774,714,632,118,642,654,866,117,49,78,293,109,763,458,167,542,234,820,857,400,753,479,571,299,96,166,558,508,969,418,287,146,494,681,75,679,850,654,47,993,825,414,72,9,960,571,6,69,76,156,43,818,630,575,303,708,339,612,238,293,362,181,180,703,438,447,618,117,5,509,944,806,59,28,590,618,358,416,150,187,585,42,693,951,45,21,74,60,139,598,991,93,969,473,906,696,491,734,668,115,193,316,657,672,619,475,771,388,221,840,752,152,791,742,609,586,284,696,870,288,74,596,892,564,265,453,344,708,936,446,217,952,585,97,854,0,547,487,861,868,444,105,243,803,651,563,427,245,956,574,906,95,553,28,778,563,737,700,211,361,433,801,367,484,992,39,51,537,519,605,585,144,17,960,149,735,996,740,447,314,853,130,539,196,816,743,200,999,937,484,380,202,625,691,394,436,357,393,799,922,675,807,550,479,422", +"345,341,970,861,855,522,792,234,478,882,307,895,625,450,782,887,68,378,174,753,232,386,449,977,854,531,837,357,235,743,352,110,337,418,569,17,58,214,251,162,529,470,387,183,165,895,801,932,699,288,829,301,800,911,477,722,611,643,276,814,17,293,758,65,831,850,79,630,86,183,345,653,397,490,717,454,903,334,760,174,885,513,437,66,437,562,527,259,426,274,48,776,5,236,410,328,415,171,910,782,887,695,156,796,838,837,758,367,927,801,370,438,349,751,754,757,33,888,884,677,672,859,184,721,232,295,389,126,870,929,90,592,836,325,169,485,833,344,591,653,615,665,342,817,507,703,109,361,260,880,986,753,751,196,227,796,240,257,288,735,965,700,680,532,709,295,1,897,926,698,68,356,319,126,292,416,738,986,25,143,447,382,238,291,217,782,329,476,486,836,264,553,439,156,845,473,531,769,253,909,313,85,749,144,502,589,112,292,791,916,707,880,136,740,220,111,336,881,707,229,320,691,519,205,420,977,702,346,562,218,835,239,49,76,999,794,956,659,856,626,775,326,464,93,200,104,821,516,86,6,155,209,888,943,626,533,420,505,173,662,423,40,306,120,698,673,611,82,332,160,162,650,694,873,168,804,513,835,237,432,721,20,240,22,164,830,53,909,984,202,352,914,777,983,753,446,917,894,852,153,435,635,401,447,754,778,756,393,786,996,597,835,792,65,125,558,310,441,836,963,834,198,185,163,763,770,875,371,943,120,873,275,44,346,749,784,855,537,86,9,274,682,161,959,614,714,771,23,278,898,974,52,393,32,495,206,581,962,704,263,182,649,112,919,824,400,224,733,232,855,389,15,311,183,672,168,713,996,383,378,842,454,338,360,279,442,484,290,935,749,906,95,226,756,332,576,889,151,157,800,89,215,960,659,121,356,148,330,3,106,552,472,764,875,204,81,390,291,763,675,156,699,105,291,515,494,527,237,735,908,190,977,688,924,358,947,751,49,573,123,683,110,477,251,278,185,274,938,424,348,414,803,903,252,695,964,327,435,191,124,909,491,350,205,186,809,226,902,371,643,310,181,689,447,194,459,45,686,939,535,948,950,887,467,414,435,11,832,590,735,438,6,91,433,4,627,897,463,982,736,973,838,601,891,936,77,450,787,789,946,553,234,664,539,396,409,458,93,728,229,528,263,391,83,361,265,512,487,590,776,450,669,163,58,364,54,298,849,793,143,227,417,749,640,861,180,676,711,867,898,875,849,806,443,940,727,434,391,377,148,572,225,987,702,253,492,850,236,73,465,411,745,94,850,546,213,226,671,151,15,751,719,392,640,431,391,762,59,789,161,108,537,946,48,903,473,409,140,197,405,453,660,874,136,906,282,787,676,809,944,787,885,974,399,575,605,802,976,731,653,484,974,445,425,530,260,336,230,323,292,181,929,651,634,679,223,220,119,103,694,340,276,423,655,157,565,663,639,811,258,207,999,782,16,915,120,305,785,769,336,996,162,266,544,568,751,535,758,938,658,173,963,255,328,301,781,657,923,433,177,916,287,729,232,72,130,136,647,696,439,381,409,640,247,394,466,944,883,39,439,114,73,430,610,712,628,472,714,284,234,56,657,977,292,166,942,151,692,90,871,586,135,886,810,315,229,94,817,773,261,786,801,774,543,670,942,621,548,556,457,836,72,223,349,98,155,440,626,609,134,217,817,462,105,184,252,779,154,563,319,71,739,269,115,319,71,488,185,898,416,268,653,67,884,50,917,314,546,733,440,839,50,460,304,82,947,494,909,64,458,437,983,518,839,13,15,21,512,762,607,634,380,775,1000,172,296,452,951,586,957,665,567,774,495,646,512,309,989,202,734,716,896,62,179,643,251,47,43,114,407,149,32,835,373,728,532,936,19,127,94,271,1000,450,440,715,512,721,939,991,648,117,633,778,139,612,160,218,994,746,903,363,531,55,352,614,330,778,793,670,104,980,975,229,136,633,101,33,728,794,828,725,612,556,86,689,982,270,366,365,638,314,670,780,636,839,683,146,68,272,875,676,722,923,920,251,879,101,687,782,922,558,208,257,871,375,792,283,858,639,686,338,734,267,393,795,169,687,443,717,540,547,0,914,612,34,394,742,561,591,420,883,932,618,611,898,929,149,756,40,227,999,179,572,903,834,243,67,656,796,221,970,791,425,510,550,180,676,107,587,850,605,654,580,875,928,580,109,682,212,900,501,267,578,680,500,711,551,123,953,502,115,459,67,712,703,714,66,636,264,860", +"994,719,20,481,543,559,528,231,514,727,921,692,933,467,218,366,600,682,696,381,886,40,798,818,667,783,427,526,123,235,764,667,805,987,656,790,960,258,265,16,335,52,690,845,716,806,471,745,137,338,964,494,776,37,84,715,586,956,612,440,830,341,613,190,973,290,182,609,25,836,892,321,744,194,479,621,471,561,889,110,894,510,747,79,853,638,322,134,752,812,734,708,274,693,410,338,693,948,429,267,616,495,155,538,571,514,516,910,350,264,89,243,651,295,571,429,173,577,447,830,353,724,36,767,608,922,166,911,476,725,689,909,125,584,52,745,123,740,600,185,839,753,823,503,948,812,524,778,443,138,81,972,63,562,287,511,442,322,608,258,284,841,237,827,246,607,546,438,321,234,659,846,466,25,643,346,347,792,770,812,152,53,977,378,461,246,623,737,655,643,915,65,102,220,984,407,974,899,795,333,542,462,305,381,159,389,570,891,183,249,775,187,834,109,293,966,499,809,898,672,992,288,603,305,819,821,625,827,772,743,696,64,959,726,862,121,259,397,276,874,940,953,672,544,425,878,492,658,100,212,802,187,71,974,463,649,574,376,836,137,24,942,967,503,391,157,443,277,463,687,196,781,47,144,96,118,244,367,793,516,202,771,218,878,381,974,209,463,789,596,288,243,570,92,215,874,576,616,157,454,434,537,202,693,782,463,949,699,935,23,135,641,816,456,998,847,828,169,179,734,251,977,766,545,748,304,178,495,887,803,154,468,249,250,926,443,495,105,802,375,464,436,887,995,141,667,511,44,550,379,839,451,188,91,915,408,923,270,319,444,662,925,926,509,27,610,326,156,508,924,235,671,506,782,357,446,509,703,148,663,297,463,972,414,545,685,457,744,765,499,81,170,721,902,347,770,316,699,922,185,437,173,2,741,848,207,537,146,472,396,29,636,823,223,740,886,249,236,171,483,152,779,519,199,507,875,3,830,367,510,999,37,828,94,555,124,53,585,831,189,494,436,728,502,519,724,55,340,507,571,874,557,525,499,803,322,305,293,11,299,185,661,480,64,696,74,121,753,731,146,353,569,30,342,1,454,633,489,823,132,713,253,188,814,571,485,317,909,20,95,500,919,577,161,243,119,734,896,137,430,276,44,157,920,209,486,740,469,660,751,600,781,419,790,292,651,186,84,425,448,212,252,904,298,313,294,601,603,961,344,834,928,877,357,551,690,355,102,476,82,648,521,124,356,304,892,351,616,463,393,229,164,793,734,828,896,728,855,52,18,882,714,862,525,275,92,780,706,235,728,420,756,346,4,972,689,455,536,700,172,143,240,337,419,478,553,819,111,116,10,374,937,960,887,459,440,914,321,347,632,553,732,424,658,932,62,696,868,445,298,972,439,698,432,591,843,232,338,873,911,129,603,100,563,901,814,86,759,924,441,169,269,881,713,449,230,944,917,232,246,625,525,222,537,199,327,657,420,7,505,594,392,790,619,417,987,220,381,932,256,295,172,460,262,301,375,96,715,692,795,47,432,94,419,607,875,486,96,340,731,735,276,1000,947,670,996,55,229,506,80,144,101,991,138,230,319,535,577,473,812,860,552,874,318,413,373,749,536,356,631,166,679,321,425,981,410,476,54,950,965,822,216,470,413,635,638,857,402,433,770,638,25,612,953,605,617,279,574,388,697,668,966,284,834,461,575,93,972,550,283,356,512,8,270,638,937,467,755,742,816,736,286,112,567,550,593,923,149,755,611,565,724,492,211,665,785,147,763,794,660,285,973,421,528,981,939,423,946,692,92,220,63,28,350,142,195,911,729,363,903,501,646,870,526,771,310,41,272,169,102,243,470,572,970,786,164,675,285,76,105,483,388,819,255,60,589,66,356,634,73,659,706,725,889,433,208,668,274,186,21,672,396,849,449,38,452,56,189,420,333,181,30,394,702,392,114,673,224,802,982,695,646,722,408,172,552,321,663,121,287,228,914,719,2,391,612,73,327,849,521,449,829,627,811,856,494,163,319,249,194,785,939,41,564,374,878,167,669,981,531,473,936,899,749,313,379,190,552,729,784,455,64,63,498,170,455,740,188,728,520,347,201,667,811,514,975,262,140,36,631,487,914,0,14,184,70,231,422,402,941,554,485,196,881,647,453,400,778,206,639,11,158,209,224,727,471,635,958,11,326,48,137,54,876,23,192,721,780,650,165,923,187,336,109,373,336,232,398,755,962,536,425,379,979,123,332,102,749,418,590,973,7,903,239,369,768,937,93,762,920", +"238,608,39,800,461,932,681,687,791,698,414,351,433,490,317,252,876,346,298,31,449,173,353,717,803,752,859,670,652,874,852,939,748,365,70,630,162,531,516,184,90,934,209,167,527,116,373,536,400,251,845,913,363,957,365,23,484,746,791,194,358,246,269,399,982,20,574,301,261,445,833,367,549,58,797,612,985,205,343,104,608,971,465,688,300,74,9,581,109,891,656,159,81,213,517,831,576,499,315,898,498,765,173,264,550,421,630,738,881,587,958,972,443,657,975,620,52,366,24,927,754,244,141,765,650,545,645,560,165,154,233,881,989,696,516,523,203,61,18,689,552,88,862,655,868,469,255,390,247,527,946,560,985,927,305,807,251,775,773,466,622,978,583,969,119,205,202,672,545,500,378,392,632,503,396,964,93,328,67,784,229,279,410,426,472,492,847,746,378,287,151,486,383,121,504,331,356,130,248,807,541,14,628,497,216,590,38,500,920,572,799,446,816,602,33,618,936,566,131,114,609,345,694,759,602,338,411,230,426,708,718,790,209,851,83,507,456,47,156,762,110,527,537,596,24,997,985,113,251,346,422,736,550,416,833,964,517,216,777,288,743,995,527,386,886,452,173,984,403,663,603,771,56,847,744,779,482,936,922,364,762,444,464,780,577,495,968,412,553,681,758,594,844,699,720,714,930,359,737,109,151,448,399,397,309,566,203,369,540,498,730,771,178,749,518,270,533,187,72,462,246,449,616,851,293,781,307,89,134,9,507,197,303,28,343,195,377,965,292,770,416,551,393,561,382,237,259,652,666,359,870,33,18,664,213,882,870,389,202,536,46,275,980,302,770,400,46,185,589,217,144,429,618,199,787,210,821,533,271,410,291,452,998,37,656,796,37,305,412,180,451,488,730,666,728,66,887,29,832,975,587,366,551,880,916,985,948,613,404,473,361,879,780,336,913,233,990,671,423,834,126,372,202,989,902,843,823,991,809,864,44,330,502,453,141,53,654,793,493,42,668,804,957,113,940,457,732,618,28,792,438,552,50,962,570,478,221,50,542,474,99,269,369,419,911,478,389,42,929,511,149,287,399,463,237,700,579,757,9,668,261,879,402,706,79,746,450,573,426,918,971,505,717,262,691,309,450,421,120,551,665,696,713,464,132,952,893,38,489,973,295,516,850,735,657,578,627,284,932,857,588,679,687,50,835,201,385,155,383,386,682,988,348,221,322,534,338,961,73,634,831,394,594,672,90,272,526,877,966,997,162,568,251,477,205,181,766,398,658,878,289,319,676,107,832,359,821,622,789,997,246,511,644,773,190,343,670,449,861,353,650,413,5,590,468,565,98,384,180,373,382,308,491,354,571,9,788,758,992,597,224,9,354,15,38,651,574,849,973,907,764,318,612,347,966,350,981,607,983,847,666,472,237,885,860,945,797,102,998,462,707,989,463,112,864,70,768,650,41,840,60,103,99,489,169,544,891,581,486,477,632,382,801,192,628,680,759,87,889,8,592,888,948,833,200,727,978,700,762,769,790,293,18,409,208,435,523,254,680,848,381,122,890,764,734,240,330,299,984,437,180,893,903,268,481,373,723,548,524,884,654,339,190,886,40,569,687,68,663,348,627,542,183,787,267,365,818,981,378,952,839,995,513,458,625,845,565,617,30,209,482,501,573,692,748,831,361,457,768,958,312,670,197,17,363,98,223,498,538,346,184,601,677,519,514,626,543,548,37,983,284,682,251,501,255,767,707,102,27,399,602,488,578,447,652,211,388,11,603,2,360,344,21,465,456,97,632,874,536,257,466,86,583,16,993,342,443,907,265,994,521,517,799,428,383,864,737,769,107,14,607,504,112,372,444,692,593,525,23,935,484,968,38,226,803,368,485,873,541,424,231,724,889,581,59,462,571,741,470,464,450,413,325,889,318,319,584,109,696,887,293,784,805,543,691,885,655,378,167,848,710,10,733,46,969,543,926,854,659,256,350,912,829,644,36,678,173,421,472,50,270,410,736,682,62,80,903,390,853,376,905,430,913,482,926,913,816,267,594,258,862,724,297,221,646,854,581,11,714,401,675,235,517,706,330,31,158,540,72,655,301,445,419,677,534,471,714,114,613,523,861,612,14,0,990,810,872,598,182,96,295,588,664,12,802,804,519,601,249,785,905,608,704,227,943,128,397,193,60,34,629,673,532,288,137,166,70,693,243,224,462,714,716,396,73,542,167,54,724,637,808,451,596,785,575,590,80,795,602,908,987,107,910,593,222,188,997,617,508,916", +"979,663,952,907,724,672,137,732,436,390,131,771,430,32,931,86,349,26,336,566,269,11,984,68,118,430,18,463,971,4,516,115,708,193,570,137,249,221,754,248,593,597,81,133,532,307,315,32,331,904,620,980,567,334,927,686,657,531,134,285,102,566,940,367,474,733,727,293,413,621,18,744,601,721,917,15,398,493,944,339,130,819,37,768,146,171,525,347,136,498,295,399,264,756,541,743,812,117,659,446,52,777,710,208,186,472,977,886,519,848,136,191,267,853,199,447,599,111,147,319,827,505,733,386,529,129,219,326,401,119,610,197,652,23,841,551,719,479,998,317,870,497,878,24,820,114,362,646,815,137,103,895,493,622,619,866,269,745,447,124,594,52,3,706,446,550,843,244,441,14,751,215,416,809,60,686,542,636,986,59,142,961,477,144,769,655,143,895,783,326,691,363,505,815,328,485,773,828,451,603,253,40,495,224,851,820,231,174,457,630,474,326,925,240,926,378,306,427,784,834,106,838,188,114,930,349,188,686,507,238,523,22,106,847,81,330,76,479,797,85,722,377,753,95,612,58,956,768,190,918,550,831,390,90,605,721,988,87,239,227,37,756,7,973,243,719,862,540,119,68,62,97,883,143,986,93,752,429,292,885,346,961,397,428,579,829,561,235,672,477,78,231,101,454,285,692,78,816,565,890,492,349,3,867,619,780,413,608,386,137,723,697,266,527,966,912,267,267,251,650,824,946,807,952,342,348,188,721,337,624,370,262,26,380,904,414,493,268,664,407,363,57,519,651,438,456,99,36,268,607,980,332,661,689,227,553,421,673,148,880,823,702,182,710,271,883,344,794,293,876,437,851,170,31,415,775,896,608,450,299,398,695,404,237,78,416,883,658,354,821,181,370,906,38,898,552,757,282,842,323,26,343,463,551,773,450,360,594,437,294,168,806,911,926,771,146,200,680,128,384,307,203,326,901,530,266,14,332,264,287,131,349,895,151,163,449,452,911,119,161,924,556,117,281,67,265,582,686,183,205,147,758,31,846,346,512,300,764,977,21,473,483,61,24,87,888,921,168,718,816,269,980,82,738,630,819,735,766,206,660,927,747,89,143,356,367,336,132,694,914,941,562,309,845,363,963,510,186,97,192,439,47,791,276,540,590,431,621,651,178,302,647,658,991,480,335,561,834,784,653,110,693,367,517,944,194,76,185,680,398,110,118,20,960,247,274,830,911,262,659,919,19,691,631,859,790,61,526,886,829,433,511,103,338,817,100,667,992,652,147,450,475,31,147,418,894,488,919,55,361,854,802,426,413,595,575,185,57,553,559,917,927,503,992,692,776,970,987,350,961,716,653,317,262,270,741,31,758,489,796,265,792,626,301,530,727,941,136,988,889,692,305,655,205,486,757,498,710,980,680,115,932,865,335,258,862,560,508,460,508,91,803,412,631,956,101,188,895,119,907,806,894,121,379,424,137,595,227,122,681,102,583,650,5,782,461,457,254,45,733,289,97,686,842,122,159,233,965,524,460,863,443,666,253,438,885,100,298,979,157,618,506,605,113,506,627,550,46,221,396,344,301,280,723,24,104,492,283,288,96,766,211,645,41,853,166,723,44,249,18,180,28,993,249,52,36,374,933,163,359,402,100,976,330,697,945,440,799,540,133,909,322,165,109,711,315,365,228,86,551,252,993,23,910,597,952,710,107,482,829,582,315,457,765,798,668,944,160,299,314,846,302,787,432,36,556,139,98,512,18,655,2,127,65,167,212,699,415,546,147,21,182,846,345,233,253,526,119,678,884,199,846,850,556,524,617,96,371,867,654,854,211,315,95,695,505,622,693,649,291,842,442,567,969,878,564,159,727,410,259,368,723,516,807,386,616,987,62,393,341,510,794,733,18,990,644,569,778,460,865,31,10,956,204,315,753,282,957,286,197,665,521,973,724,405,456,633,842,766,676,431,5,800,52,524,165,331,546,187,506,663,926,112,288,419,265,487,452,711,259,227,590,335,285,933,460,712,181,484,657,422,770,195,408,174,186,552,182,793,180,86,450,942,671,245,261,857,491,268,159,896,973,770,270,811,57,466,678,238,346,273,110,762,64,515,589,572,37,471,48,868,34,184,990,0,676,237,577,448,315,216,310,105,248,342,354,226,134,344,276,287,802,122,808,91,90,613,113,8,935,87,780,170,341,958,722,323,780,249,315,181,41,239,160,29,383,137,590,145,513,201,718,926,872,890,422,199,516,367,651,793,392,75,44,370,116,291,929,923,353", +"394,861,195,122,511,394,733,578,918,713,509,494,876,609,159,256,736,394,22,578,765,767,775,883,355,843,626,42,857,952,481,653,154,755,584,552,458,2,751,822,941,19,937,58,693,505,314,783,144,200,91,595,812,50,232,266,359,725,749,770,527,469,552,235,176,429,777,872,730,960,500,980,695,54,682,38,315,570,236,847,831,701,917,124,41,410,387,151,649,440,158,359,483,434,357,893,360,786,380,323,309,537,783,64,576,29,188,772,21,803,167,391,189,890,130,64,203,498,655,74,24,562,472,730,832,506,325,862,854,136,593,522,800,124,766,148,76,637,35,776,508,134,498,931,434,503,958,213,988,638,171,272,406,854,350,597,423,841,874,595,979,758,711,762,848,56,61,837,14,35,67,105,296,309,366,717,686,135,405,829,181,373,715,281,867,93,650,946,874,814,416,796,876,427,34,627,73,741,79,124,166,674,294,632,692,188,110,722,347,34,598,525,307,640,690,491,912,310,653,144,475,936,558,44,754,871,159,804,32,189,495,61,632,573,157,405,244,50,943,763,593,467,323,843,579,958,543,110,338,97,534,921,988,636,554,247,474,456,724,201,701,574,172,32,536,95,899,578,21,982,142,548,161,510,704,614,813,51,103,349,398,387,833,34,86,230,227,866,375,95,85,863,362,163,823,946,852,583,91,678,65,436,215,438,218,483,310,252,763,44,101,113,968,261,921,572,518,180,614,566,541,530,747,603,425,337,339,904,325,572,442,760,84,17,953,640,297,441,751,997,116,10,996,640,269,87,263,7,986,619,720,974,414,191,855,971,659,987,146,358,136,820,329,107,830,483,119,10,487,561,746,639,666,545,383,237,719,524,384,861,858,583,692,816,315,824,561,198,951,333,693,48,195,620,741,168,27,364,572,29,203,173,253,669,216,994,918,393,978,964,846,847,316,117,951,892,960,589,845,449,724,287,595,254,11,370,186,254,465,35,706,782,339,818,890,701,842,674,503,848,165,470,71,682,844,588,614,34,175,234,259,447,133,840,3,957,613,670,575,751,876,183,676,463,978,414,155,392,376,779,706,628,592,580,394,332,597,219,160,164,558,297,995,779,31,281,687,652,549,470,934,966,167,424,150,346,808,71,211,418,817,243,666,325,200,622,671,55,921,285,510,232,132,766,577,308,146,906,628,134,634,768,627,623,549,690,549,746,183,596,872,906,620,416,299,691,188,113,465,540,456,221,110,771,969,199,300,920,457,52,699,278,316,105,815,907,376,101,703,27,867,47,6,577,326,829,450,355,192,850,140,908,413,712,354,956,940,828,860,847,138,968,739,67,34,923,842,191,534,962,890,737,653,404,95,123,198,257,430,22,311,140,85,418,161,610,324,463,130,235,500,623,487,156,293,624,451,91,147,831,579,530,761,483,824,474,964,229,367,975,957,205,15,587,148,924,774,56,528,985,103,937,100,921,623,714,337,558,357,718,498,613,621,606,886,785,171,564,595,968,320,34,561,535,865,689,642,159,669,643,203,657,560,228,774,134,767,672,743,193,546,911,319,318,86,238,523,421,769,814,340,911,396,403,28,12,685,401,876,990,974,2,791,676,832,94,140,746,556,497,417,392,546,780,779,997,205,68,156,4,750,958,373,143,898,671,822,900,898,741,83,780,112,110,222,726,560,89,68,391,279,726,350,672,129,183,978,239,269,154,173,31,353,57,136,837,231,803,199,216,362,389,542,85,388,494,762,706,631,853,844,744,694,763,499,877,839,350,484,765,341,59,498,678,245,466,901,411,15,848,150,686,721,651,260,981,79,775,250,20,955,226,974,741,36,135,874,604,645,87,654,899,675,789,214,197,941,838,264,610,672,920,385,385,434,145,284,327,225,906,324,181,948,559,349,152,170,68,227,370,578,273,683,250,125,746,725,390,237,735,24,67,380,508,404,400,957,921,865,756,767,181,687,304,164,130,344,554,207,384,429,627,352,345,348,20,440,396,105,36,957,324,888,340,523,836,450,118,361,246,468,101,127,402,804,676,719,710,92,715,74,216,377,70,592,820,153,146,307,807,674,764,432,609,643,887,750,871,293,319,224,493,966,771,534,816,752,705,928,637,444,394,70,810,676,0,37,322,21,991,594,29,641,506,448,398,348,461,30,834,746,110,478,302,760,774,548,714,835,14,754,483,345,559,383,2,550,159,185,720,398,675,301,409,751,972,905,838,349,110,379,646,596,933,941,831,144,279,522,655,172,770,335,350,800,99,271,925,580,639", +"685,509,784,455,154,734,843,132,397,588,360,19,921,968,800,672,742,682,197,995,591,787,504,516,806,360,766,624,247,463,691,248,408,136,42,487,506,179,507,343,448,785,321,316,187,770,905,419,439,98,789,960,660,83,869,379,474,459,203,268,831,338,828,434,484,830,530,661,788,523,855,832,678,415,71,833,474,5,624,119,35,782,321,982,489,456,630,630,478,143,876,890,3,449,535,201,638,385,11,526,865,197,191,452,146,83,45,524,202,238,236,564,661,281,802,735,315,334,293,720,397,71,606,686,314,262,868,457,908,520,913,492,746,570,976,788,858,316,960,891,920,239,211,338,398,858,404,915,843,641,646,592,854,640,647,533,381,873,888,56,181,448,434,825,194,356,599,683,633,700,851,453,855,961,986,866,861,102,747,914,875,873,246,233,447,489,820,732,92,297,871,404,614,873,665,636,36,189,557,165,81,664,347,325,958,828,221,42,470,409,464,116,615,981,875,976,360,643,181,139,816,662,606,522,115,544,794,252,974,176,335,720,942,4,417,305,538,604,361,962,269,249,29,111,466,800,890,917,724,202,535,866,199,717,852,419,314,161,733,454,697,573,232,52,490,88,773,335,259,576,734,28,45,763,692,862,219,261,78,920,189,705,686,744,590,726,196,53,983,645,549,832,16,257,527,769,227,126,934,483,949,766,241,763,308,105,59,183,669,407,922,493,118,332,587,512,670,856,803,428,518,461,375,361,96,800,721,891,800,456,956,606,51,685,91,324,519,377,987,458,757,892,110,800,376,376,501,981,436,437,966,146,696,540,581,166,725,857,781,606,911,736,918,48,889,559,519,934,695,122,863,719,609,124,220,849,661,582,991,229,683,108,468,80,342,967,636,976,626,328,610,644,809,473,169,500,335,665,699,53,113,130,960,825,574,508,408,51,712,97,716,73,920,34,455,106,658,499,617,679,418,813,75,393,501,115,550,618,932,546,824,517,409,637,877,14,961,76,77,649,621,652,657,915,384,603,881,781,175,221,150,893,649,925,398,16,974,131,720,77,872,885,839,414,577,98,518,320,355,77,723,816,618,125,620,345,322,868,421,936,868,869,670,765,203,545,165,281,292,868,964,581,4,589,162,501,451,612,410,371,811,668,269,410,639,606,984,82,548,985,333,638,677,337,584,757,115,107,228,436,640,133,210,447,446,223,184,399,594,908,504,374,629,539,100,568,318,365,672,744,990,454,94,854,708,523,696,118,965,873,175,251,109,937,203,468,759,830,732,918,870,857,347,236,794,222,146,78,134,512,70,370,413,400,841,276,852,9,924,586,748,112,377,892,733,375,84,255,203,132,223,190,887,701,610,865,456,13,701,485,193,470,251,341,119,125,671,343,81,324,847,650,927,622,229,941,853,637,292,405,59,2,804,574,357,84,278,626,515,71,999,632,277,257,122,274,619,288,981,668,551,845,38,872,730,196,569,565,268,930,427,878,399,172,447,367,413,256,499,475,943,118,760,287,631,974,829,141,857,508,379,559,994,56,906,444,135,60,134,193,94,198,146,513,677,946,87,300,110,95,12,857,977,248,407,708,118,279,383,552,252,157,146,958,301,401,212,401,318,414,282,269,747,53,520,341,182,326,253,80,310,362,460,121,56,753,550,605,636,306,42,526,729,356,996,633,614,701,450,325,665,502,656,584,216,519,529,3,659,658,649,203,94,28,201,980,741,824,304,798,860,365,324,530,638,78,526,487,310,4,780,588,32,114,480,428,142,246,904,278,880,280,228,589,692,639,737,401,760,825,236,783,188,914,183,792,607,970,587,459,420,179,119,79,662,817,60,622,959,329,564,528,326,201,555,151,831,632,420,711,633,972,666,627,406,728,313,222,866,765,136,235,785,387,944,12,343,275,835,91,901,607,321,70,646,726,837,967,431,855,550,421,370,34,795,710,87,556,744,269,878,100,884,289,619,752,618,970,53,130,682,616,498,885,732,474,695,645,694,719,707,439,283,283,696,232,731,340,435,340,612,902,767,62,474,567,767,794,446,581,700,938,874,254,327,37,810,941,165,198,913,703,370,67,744,945,189,975,563,861,494,872,116,496,103,970,119,131,281,940,105,742,231,872,237,37,0,314,772,177,188,258,768,966,679,480,238,304,880,825,79,279,893,946,424,551,542,843,962,355,356,417,549,330,462,323,361,567,833,252,359,443,244,475,9,613,162,485,405,15,726,234,523,856,218,899,347,592,548,458,1,880,476,510,271,169,83,990,569,909", +"131,621,683,8,900,883,101,379,907,773,626,454,391,247,606,967,338,699,690,352,554,64,319,934,404,89,859,137,971,240,429,2,991,24,910,653,453,460,665,19,200,693,706,855,379,484,71,798,102,28,467,391,384,120,411,624,523,531,657,213,892,635,967,402,98,363,248,36,894,616,6,820,238,957,500,278,501,351,525,332,272,253,945,51,526,114,139,453,693,511,959,313,557,884,454,687,281,861,278,790,275,487,789,704,717,255,661,579,429,398,698,255,113,847,217,498,997,911,937,397,60,48,170,559,945,199,662,109,158,731,125,370,952,600,689,174,860,846,281,903,210,509,816,576,828,858,1,928,701,124,195,412,915,902,681,467,112,288,196,623,896,679,660,706,57,785,354,228,871,422,212,743,961,747,146,230,556,141,71,902,366,35,237,692,520,648,109,888,816,148,946,552,536,338,349,829,120,930,441,802,586,684,867,145,195,353,844,297,938,497,105,894,299,470,643,437,703,327,343,638,218,701,838,989,295,984,332,601,862,998,815,999,73,727,682,653,65,98,486,880,479,523,366,421,698,399,223,268,30,225,773,798,867,740,847,529,65,911,165,396,856,984,107,415,482,771,99,527,896,92,177,611,123,566,222,305,519,307,919,584,576,941,902,823,135,993,141,300,376,887,310,838,201,551,135,501,805,900,843,769,313,130,777,123,987,765,751,430,406,305,396,393,451,977,747,813,138,140,890,677,345,370,827,71,821,793,53,381,894,319,796,286,580,703,485,508,941,752,303,604,67,850,531,539,173,178,663,537,467,197,32,452,907,209,785,181,235,240,653,809,461,197,386,135,89,769,254,156,730,280,652,630,783,160,45,42,530,149,601,344,458,84,966,570,814,249,898,446,563,889,291,886,270,760,917,9,265,435,382,304,470,352,862,196,481,114,742,622,280,224,882,911,171,886,312,938,841,462,215,697,598,810,178,390,205,267,965,393,139,338,63,346,549,790,440,748,630,850,724,919,75,37,147,104,302,494,451,831,289,761,20,552,89,896,178,635,466,321,993,870,555,530,491,133,337,270,667,426,516,928,224,50,77,701,96,340,341,736,564,753,995,641,140,537,645,119,81,783,661,922,396,276,554,964,548,408,118,251,551,427,603,940,594,198,207,394,317,227,971,550,660,107,505,51,489,81,77,860,378,892,568,541,424,865,65,790,733,933,644,32,938,954,739,388,565,194,253,468,187,311,417,725,476,948,801,295,94,413,506,995,886,511,158,439,345,356,380,988,416,843,977,809,432,95,373,772,967,146,216,1000,52,855,344,940,981,416,477,873,876,40,351,120,966,179,223,815,984,400,341,333,547,489,567,286,589,826,849,573,9,488,660,145,277,805,670,101,373,922,248,560,354,758,456,281,423,975,961,744,423,44,181,195,731,483,19,271,804,669,915,311,283,421,258,992,17,577,215,32,370,995,668,39,605,550,282,412,628,80,145,133,628,727,267,661,226,156,705,292,432,521,876,909,550,389,949,601,89,364,592,183,314,130,574,929,294,585,224,563,897,973,680,689,227,655,715,91,37,21,289,344,658,909,548,360,152,500,436,931,579,852,579,704,844,278,80,26,408,421,99,831,152,590,700,697,776,154,126,932,120,455,922,23,957,453,625,694,300,587,327,366,465,647,985,383,198,623,7,176,730,778,490,727,851,306,709,466,68,590,152,529,939,808,403,118,944,682,404,970,288,934,378,986,791,491,892,898,986,66,519,590,651,69,109,785,485,412,617,649,797,959,998,458,619,702,48,459,674,970,52,419,704,43,687,659,770,277,868,254,159,226,823,357,666,944,587,807,489,751,123,810,427,843,228,429,778,250,198,927,797,667,610,306,194,150,788,378,317,932,901,96,899,777,581,102,314,661,707,284,442,380,607,470,201,843,549,482,508,463,466,283,969,533,188,560,561,614,382,955,944,664,299,720,525,356,368,857,535,749,44,569,383,350,448,373,824,17,754,813,399,87,908,227,797,314,649,180,823,508,383,983,536,799,886,772,148,968,606,562,714,831,325,598,230,465,675,318,966,165,300,164,719,815,876,555,359,869,967,865,588,442,718,470,647,996,706,581,713,272,880,427,243,561,422,598,577,322,314,0,247,331,201,174,716,560,79,26,940,602,580,852,472,459,835,97,457,35,733,540,425,333,571,676,160,588,440,463,114,342,894,377,835,726,515,728,570,310,884,440,268,745,137,227,606,389,766,424,14,540,607,855,181,222,517,225,553,245,831,537,842,456", +"822,813,218,770,464,703,754,23,156,621,436,916,252,891,593,195,119,399,624,396,246,856,499,109,415,852,809,727,947,532,471,666,996,624,458,763,787,949,154,620,406,706,556,926,883,881,969,174,309,854,807,563,331,941,747,59,404,144,660,498,353,353,929,881,886,958,374,522,195,112,699,566,378,470,921,571,35,526,484,142,718,714,432,837,122,494,419,427,940,97,404,848,447,298,645,429,187,773,53,92,25,829,428,845,876,230,4,962,38,683,395,198,646,338,525,809,439,893,411,496,405,670,296,856,660,497,259,728,309,300,688,747,11,549,974,626,485,900,214,506,974,926,472,307,151,320,667,991,887,99,19,863,776,496,289,909,103,951,419,650,543,386,49,444,467,599,759,801,448,120,336,160,956,599,839,896,791,489,914,740,144,389,294,473,411,411,252,390,351,821,246,379,769,264,414,271,383,111,140,634,509,921,891,710,431,528,640,348,346,553,344,610,318,807,986,221,419,550,456,970,971,450,659,783,455,204,972,297,768,461,485,823,748,446,998,39,313,435,843,683,634,821,128,456,453,804,579,354,117,897,370,835,752,710,651,231,912,676,944,356,579,923,644,661,721,734,534,496,18,223,914,731,278,798,62,307,410,499,118,127,359,708,998,451,680,527,347,182,728,50,252,146,296,247,593,452,978,744,781,493,198,567,236,428,271,197,706,403,598,285,782,26,360,585,468,925,782,969,134,36,92,134,102,908,54,360,253,244,232,13,347,464,615,361,807,369,161,503,797,672,504,922,108,121,707,299,432,323,575,740,181,406,3,900,994,889,37,646,959,62,60,750,145,147,517,780,861,356,609,243,98,609,453,796,956,143,369,910,764,83,571,987,578,895,574,859,501,113,342,734,670,353,270,733,418,164,731,784,974,61,824,168,78,923,887,594,967,133,253,741,243,688,506,328,625,402,651,973,607,865,645,441,728,196,824,869,497,726,227,48,989,54,838,774,787,546,918,510,170,374,611,78,292,18,680,684,496,627,251,734,802,813,723,511,88,19,453,319,883,616,161,665,385,440,678,937,166,877,70,599,282,460,712,329,350,649,569,916,233,500,678,972,749,19,673,239,913,691,629,24,159,246,763,144,937,207,328,986,13,940,235,199,279,998,266,243,73,194,275,921,587,573,254,943,52,986,584,710,93,295,939,326,944,330,810,348,853,650,5,954,201,712,781,752,77,247,223,446,20,203,831,395,257,397,82,437,466,306,713,292,742,449,386,100,778,751,919,207,690,487,789,495,434,325,702,398,996,218,470,704,577,149,23,325,157,307,644,401,941,401,809,274,919,357,129,330,46,508,498,822,44,831,339,555,444,777,748,946,955,799,313,312,121,830,669,245,492,577,768,990,448,822,492,959,630,286,817,339,956,989,148,219,838,649,249,831,205,505,69,709,768,40,613,737,39,656,896,537,859,373,435,871,163,698,289,791,682,558,887,673,563,555,781,963,326,664,166,151,151,862,409,623,329,637,43,421,873,273,249,737,405,107,933,867,396,906,287,835,575,114,990,712,534,244,24,556,89,192,281,991,547,520,231,984,357,434,228,81,310,771,628,74,195,105,569,573,418,755,269,423,775,447,245,551,736,156,527,753,408,873,505,79,785,730,694,357,143,154,371,482,43,155,801,259,271,742,542,121,869,41,115,928,465,902,713,465,473,106,78,747,562,394,16,648,196,532,915,685,885,931,499,22,762,293,441,207,483,429,182,294,909,117,496,40,127,338,69,341,897,284,913,767,81,689,289,331,541,595,818,386,281,369,893,609,952,282,952,622,713,15,531,64,459,46,24,552,400,792,505,655,653,686,686,876,469,381,328,558,376,912,460,336,952,983,657,161,225,283,300,967,371,815,495,449,924,761,109,419,251,467,568,900,853,111,140,156,77,432,493,880,176,59,582,998,122,465,533,606,183,301,534,819,445,67,149,139,115,211,659,795,447,713,630,467,481,926,628,592,970,922,690,285,127,710,930,479,355,613,508,811,115,436,172,983,811,725,608,199,852,598,412,249,619,757,49,167,664,355,118,972,962,789,791,320,109,707,371,294,463,774,492,826,780,920,85,876,801,29,158,183,803,591,402,182,448,21,772,247,0,722,986,437,938,615,722,481,888,119,680,751,223,994,177,247,738,900,635,971,484,81,178,881,729,210,52,155,418,226,360,413,428,589,353,133,643,92,732,604,930,968,239,949,421,236,230,677,239,492,166,743,250,248,634,981,818,520,620,393,666,510", +"717,37,146,153,356,758,678,637,422,626,947,655,588,331,416,93,235,932,347,772,541,476,582,490,841,475,655,269,742,577,684,78,298,686,253,929,511,512,297,625,550,603,54,95,187,135,92,153,246,565,728,775,734,566,544,841,58,741,884,327,711,565,84,901,380,156,663,206,788,295,475,84,394,927,560,712,458,842,342,942,896,334,547,7,267,842,517,110,290,350,788,19,991,932,418,54,1000,521,140,52,905,608,598,950,712,255,800,732,467,568,828,478,413,534,766,343,72,67,876,732,126,129,679,457,244,707,500,866,258,746,784,537,634,97,988,685,226,203,901,128,838,186,735,987,334,698,933,72,989,128,811,194,669,662,154,567,357,614,688,850,107,218,967,695,364,72,79,860,286,606,727,12,398,909,7,634,764,164,485,773,627,482,502,966,738,149,707,333,397,401,421,969,966,933,744,888,62,575,497,6,515,78,298,657,399,359,775,133,962,153,499,907,134,770,116,534,111,896,679,232,721,402,955,322,825,429,961,53,838,940,455,730,902,618,872,154,504,921,445,419,599,438,779,164,541,601,259,171,562,305,862,204,184,121,66,337,279,326,579,292,251,256,158,189,292,192,765,153,814,601,186,609,909,186,728,125,103,188,27,371,812,348,597,426,539,6,735,742,217,910,933,250,406,811,626,308,908,52,464,767,496,745,275,396,416,169,665,994,695,576,551,374,913,422,634,956,558,164,411,932,862,824,716,982,393,871,46,23,943,502,668,542,428,162,110,654,187,657,114,601,262,450,46,818,784,470,786,115,73,709,49,814,820,617,542,537,980,159,352,889,68,754,81,424,612,54,181,38,153,221,533,157,761,808,265,144,519,332,875,16,824,418,74,636,680,235,693,403,561,964,306,363,436,723,313,782,685,321,253,340,890,710,675,988,295,986,888,53,914,21,110,259,201,946,301,600,698,398,779,148,381,545,636,696,269,37,191,167,294,77,657,498,80,904,980,650,482,688,137,289,175,556,107,776,973,871,224,814,717,810,186,413,275,932,715,57,166,928,737,924,580,179,828,60,830,973,478,920,855,10,3,719,762,96,498,343,769,369,475,219,830,76,515,802,211,311,718,306,59,764,132,893,910,922,881,55,891,462,267,713,517,257,541,59,172,96,482,241,770,175,186,125,297,826,116,104,8,654,990,201,579,750,989,38,549,907,177,752,779,572,417,444,490,803,837,725,677,952,504,683,7,341,500,377,953,137,191,433,212,503,507,105,724,567,447,612,203,222,658,993,611,108,155,529,747,439,806,725,561,31,926,373,558,309,810,532,580,467,257,97,550,532,616,619,719,827,603,683,315,372,635,214,951,548,304,226,657,664,492,597,323,28,749,859,477,701,130,682,239,717,551,513,843,461,153,71,255,292,961,487,338,731,718,381,91,23,656,136,727,987,577,587,14,454,890,695,95,293,462,446,146,361,869,317,785,315,853,862,80,462,413,282,786,592,510,484,454,57,360,411,452,675,884,468,925,764,332,378,872,873,269,19,976,573,464,766,9,942,902,415,306,593,841,372,884,288,758,623,985,931,924,102,343,361,184,513,507,112,68,988,561,765,60,277,129,320,62,939,695,741,620,404,323,698,643,914,121,611,250,751,815,758,368,717,858,324,464,252,45,91,166,881,422,801,356,91,595,60,902,167,362,376,430,101,610,399,498,617,478,95,642,578,95,24,959,660,71,30,462,137,893,612,828,194,818,504,278,924,167,625,991,85,724,837,706,176,457,127,854,63,460,325,885,951,238,68,317,650,578,507,690,815,195,10,526,834,750,685,931,228,674,341,298,227,674,820,508,39,258,129,588,93,317,493,49,320,197,178,249,349,413,692,86,679,6,744,350,790,948,868,333,369,892,116,542,677,960,676,960,954,271,943,56,415,935,237,223,673,712,327,798,753,93,710,287,498,601,162,932,611,774,951,284,349,341,574,104,118,460,399,534,198,683,878,829,818,789,207,168,572,21,300,182,393,488,79,517,266,172,17,959,796,689,544,9,516,43,24,633,288,485,583,274,571,251,771,974,924,366,917,758,765,267,304,886,390,858,100,817,647,61,850,94,597,428,138,4,945,342,446,651,420,941,96,315,991,177,331,722,0,482,951,580,286,144,487,708,387,664,716,790,245,510,15,429,606,710,953,364,852,221,755,534,406,789,22,748,220,967,414,145,37,176,880,385,239,909,495,848,856,431,579,522,646,830,984,600,421,895,217,918,845,257,253,342,647,472,124,906,577", +"397,195,915,338,42,609,573,106,988,560,928,317,244,897,553,523,654,961,462,241,351,391,735,444,265,223,639,646,142,128,968,787,908,866,607,29,667,599,115,828,885,812,824,303,22,325,425,436,591,705,196,358,882,960,735,895,691,532,1,348,834,725,342,879,921,259,369,852,201,307,457,386,191,123,613,437,109,65,82,970,591,931,691,554,146,434,440,42,471,644,339,177,113,677,814,260,785,617,457,521,812,104,683,259,533,475,258,414,956,333,549,911,42,353,386,607,870,169,358,763,941,78,689,590,982,831,747,578,800,382,957,390,793,79,363,126,517,320,658,955,539,358,217,858,700,413,585,129,375,243,18,678,42,800,24,181,589,566,53,65,177,497,553,8,279,403,527,229,423,460,636,61,110,853,572,729,821,959,39,161,518,720,619,44,602,638,841,839,968,515,594,435,854,49,238,650,244,925,622,987,874,339,433,686,92,707,460,365,587,236,754,513,786,215,395,8,779,170,599,339,540,736,234,691,188,103,274,727,751,126,811,26,413,999,24,78,569,241,243,723,247,582,91,747,866,166,116,342,767,703,920,11,617,588,116,374,952,875,526,472,36,78,895,693,819,654,214,599,892,867,424,732,8,916,355,894,222,352,579,611,725,857,633,794,840,710,93,790,88,591,354,748,724,214,664,379,712,18,360,509,615,729,284,793,262,635,662,642,933,791,639,354,823,866,112,445,314,409,905,390,721,591,177,219,147,174,761,118,208,372,655,662,424,262,146,498,435,974,906,323,859,697,382,826,444,625,760,502,761,758,943,373,147,255,324,701,196,460,254,984,790,389,49,260,27,763,899,64,536,595,330,927,347,861,241,638,893,935,9,861,359,312,775,894,914,389,514,503,328,613,498,58,804,289,443,85,46,306,91,717,647,943,951,12,327,138,906,689,181,335,358,212,795,819,158,256,413,238,194,361,773,796,824,473,283,317,231,459,84,711,721,881,288,799,681,719,816,454,12,26,490,631,562,423,820,171,724,294,753,145,803,683,119,947,284,348,269,247,754,275,242,922,188,709,837,980,885,819,116,814,909,29,136,211,720,636,994,365,564,714,875,366,518,767,249,881,823,555,810,677,708,118,767,910,225,780,176,377,120,590,671,107,371,856,167,211,251,878,894,55,485,573,817,266,810,499,165,982,740,378,470,26,556,747,870,760,517,343,540,877,19,298,545,630,389,643,661,391,405,768,498,57,221,213,568,429,461,669,228,801,813,973,147,854,920,328,453,575,394,679,951,518,803,820,824,92,185,349,889,902,794,251,680,457,245,934,844,160,425,697,283,310,494,569,165,115,880,274,516,751,257,831,472,812,877,562,703,293,61,5,906,649,340,248,639,482,216,730,100,282,290,903,638,647,798,965,99,69,470,84,462,69,96,912,66,568,648,903,580,77,309,901,692,114,36,374,87,62,300,236,98,711,842,143,84,556,455,127,457,459,267,778,693,383,101,937,7,69,40,803,278,624,943,522,545,810,862,894,58,467,33,536,311,110,396,858,13,829,252,771,107,351,927,149,828,794,633,399,710,839,641,979,489,797,372,3,35,399,658,147,164,471,273,201,203,640,581,971,962,772,300,385,794,239,12,37,295,225,989,977,63,168,152,6,921,403,903,879,37,159,20,833,481,897,753,369,687,164,126,347,839,27,212,740,804,265,569,828,488,507,68,209,188,275,551,477,301,46,394,932,137,953,482,31,696,483,861,563,575,981,767,992,430,11,823,49,458,97,501,525,663,281,926,108,374,572,734,744,411,846,314,293,998,611,692,545,767,777,640,406,939,875,731,444,161,293,600,103,961,953,614,11,432,436,616,243,240,416,223,532,930,79,526,617,873,259,858,550,446,230,565,8,299,461,277,527,68,862,952,132,562,728,295,75,661,545,282,831,527,712,801,852,744,954,771,954,616,231,616,123,115,254,577,803,223,430,956,167,23,137,751,688,220,929,307,769,509,897,456,676,917,597,697,209,176,94,663,400,911,976,382,816,986,356,87,911,215,582,258,921,990,562,822,391,736,746,706,659,875,727,330,862,936,56,830,884,592,280,380,751,651,945,615,705,347,798,581,649,822,156,563,883,554,295,216,594,188,201,986,482,0,143,97,985,726,877,957,525,21,476,730,293,757,524,642,480,297,1,659,398,474,876,52,921,67,744,53,453,830,352,403,976,498,54,685,549,760,30,25,35,413,3,249,398,576,768,633,896,915,652,211,398,165,642,396,588,571,505,88,616", +"715,915,520,773,972,942,221,478,279,90,717,992,160,939,604,400,715,199,583,879,252,540,211,592,815,907,109,300,598,276,767,541,514,302,201,172,145,539,407,298,788,986,220,426,742,893,985,786,239,292,11,894,778,351,887,772,984,230,462,22,557,222,475,638,120,819,496,443,717,886,928,516,908,226,77,45,771,714,945,330,470,614,630,590,213,572,272,41,654,887,158,501,388,406,112,850,516,961,556,294,911,494,130,7,767,260,656,382,698,181,898,827,542,463,529,635,461,428,635,671,226,892,921,976,824,553,852,361,554,572,296,784,283,736,715,560,525,137,458,854,412,706,294,438,346,372,855,172,128,801,189,164,541,728,171,175,946,242,323,469,13,735,475,344,925,217,928,606,279,959,771,189,417,854,551,490,665,813,982,79,84,549,982,878,457,56,251,384,219,886,243,551,110,780,496,466,929,210,249,559,116,817,779,308,341,346,16,89,252,790,273,901,936,258,306,898,404,370,938,431,498,840,974,720,477,120,120,567,902,142,528,919,993,526,488,767,192,360,664,961,529,222,119,66,582,527,429,48,53,3,698,595,140,895,318,560,440,787,643,182,323,469,216,737,848,710,21,693,157,990,686,269,868,675,893,371,130,14,898,194,948,92,47,859,349,507,184,677,431,25,461,578,492,724,235,535,418,347,30,659,793,427,116,5,327,183,171,38,959,358,541,700,753,623,687,154,583,782,728,723,243,344,72,700,112,467,267,665,81,222,438,612,605,4,176,61,511,248,238,398,916,166,586,649,599,65,950,395,807,849,790,736,799,268,599,789,616,785,799,792,26,442,471,647,51,657,184,661,430,770,696,165,308,503,260,466,846,346,872,114,959,962,452,676,394,781,659,83,399,153,972,517,278,175,936,814,750,335,142,468,956,888,32,160,136,815,268,114,98,915,323,485,384,306,509,431,739,871,323,334,945,196,50,839,612,674,952,682,795,670,215,299,427,811,402,427,48,280,935,618,919,422,805,461,860,801,240,341,250,711,138,562,490,137,185,982,867,690,228,159,825,929,28,816,742,999,884,854,210,712,511,601,91,8,107,549,258,301,327,296,78,998,922,893,780,866,907,21,227,121,139,352,21,530,760,515,957,712,420,995,699,184,700,545,603,995,735,800,855,113,991,347,422,821,310,236,900,635,549,813,352,545,590,573,341,16,950,929,490,412,749,569,278,381,460,675,193,781,933,186,287,157,355,976,178,24,594,244,489,947,93,344,307,489,768,540,189,359,401,122,481,722,658,847,591,673,89,876,342,189,509,647,35,784,556,601,825,903,920,746,481,380,386,853,160,733,179,397,829,434,891,830,660,657,567,475,578,263,177,919,529,668,350,164,869,723,549,946,486,547,896,253,33,259,903,932,823,467,369,563,309,996,346,748,450,206,488,694,911,123,913,607,886,782,741,909,650,124,915,350,863,527,877,63,576,458,100,165,695,933,158,958,832,411,903,33,5,144,194,496,200,31,725,872,874,484,631,785,459,488,898,257,658,747,582,888,79,698,703,28,102,966,528,559,657,398,38,931,148,561,946,117,96,951,203,926,877,406,305,694,983,492,232,428,851,548,150,658,618,987,604,842,610,601,223,290,612,89,831,710,269,336,39,396,871,614,429,288,917,315,248,911,94,943,617,127,589,297,748,172,573,138,306,521,443,75,170,570,195,299,213,240,269,353,29,962,481,537,332,212,670,787,337,588,350,187,127,766,355,172,863,191,513,390,761,347,532,246,440,356,594,726,21,954,809,28,600,483,61,37,957,374,554,901,483,119,768,349,615,677,994,206,365,531,154,990,937,487,133,782,136,901,837,265,788,121,800,485,408,580,972,313,964,98,117,719,746,403,468,274,908,724,682,228,458,717,323,741,409,434,112,472,621,675,288,439,44,518,417,177,415,185,394,805,387,864,172,270,923,366,417,781,927,913,778,768,540,883,532,54,634,57,992,902,523,100,898,239,962,663,431,25,436,522,31,965,306,654,347,126,515,344,822,679,902,891,976,328,262,17,633,972,743,739,291,514,494,658,796,649,85,549,381,510,744,501,601,460,402,509,935,780,722,945,109,759,349,809,446,261,427,932,485,588,310,29,258,174,437,951,143,0,92,222,566,88,327,830,173,885,616,593,532,146,645,258,502,79,341,117,628,182,409,943,835,667,568,479,483,574,602,989,826,33,491,993,4,651,962,897,43,1,478,12,603,250,867,620,531,684,265,849,828,942,727,353,249,898,456,566", +"607,662,335,13,42,128,962,763,705,954,749,874,152,414,46,7,94,51,667,362,167,692,214,790,155,521,15,945,248,66,384,236,973,947,48,482,666,790,749,599,105,104,838,151,565,365,481,424,705,46,764,809,25,191,298,345,655,605,508,916,534,401,171,517,591,44,405,715,566,825,278,121,526,662,340,905,24,818,150,576,457,93,573,694,485,769,934,296,598,937,113,565,232,770,416,666,427,985,342,33,740,391,836,286,369,755,858,430,196,23,63,186,522,309,891,253,186,808,523,72,39,748,791,183,49,598,666,458,214,965,952,869,485,217,497,92,705,999,723,594,954,220,737,429,708,934,682,488,997,926,599,95,595,843,62,880,803,248,635,712,888,399,361,225,673,796,519,221,881,171,54,849,864,653,532,864,473,575,273,574,191,105,541,765,831,645,185,182,278,987,683,750,378,86,779,291,161,987,427,480,318,149,130,828,697,316,610,229,992,582,847,891,103,439,828,998,839,510,664,819,918,914,606,427,158,259,697,570,797,899,983,742,580,459,30,676,947,979,465,241,352,503,573,114,585,402,162,690,973,300,239,356,732,247,363,389,204,810,997,454,846,148,217,402,899,407,261,93,494,264,416,89,909,493,930,848,338,583,534,391,423,932,904,369,891,270,73,563,168,215,253,739,452,151,187,791,569,277,537,853,493,124,273,134,301,683,50,558,72,443,337,997,809,649,180,719,363,891,393,559,238,437,293,787,873,59,54,518,751,691,998,75,436,8,662,136,392,75,599,900,331,703,193,294,743,363,257,226,37,618,915,500,525,947,421,203,42,857,918,962,59,390,532,329,742,823,342,246,886,166,685,367,800,212,414,259,622,555,71,153,446,684,370,647,333,839,707,407,704,264,845,920,411,743,303,538,720,928,253,556,913,480,993,6,205,132,186,307,608,623,402,520,995,637,128,732,840,492,410,359,207,396,559,174,221,590,157,832,636,570,904,832,908,718,682,338,420,383,936,590,927,603,954,890,521,791,544,486,868,889,386,356,908,914,488,44,26,183,346,329,99,852,605,762,582,131,262,797,548,77,410,986,358,168,614,432,990,958,649,132,187,251,207,308,668,63,575,291,159,281,478,124,310,925,583,406,807,795,171,115,633,352,695,775,589,934,902,673,915,227,779,771,555,292,830,201,63,820,374,731,890,807,812,283,712,615,503,309,196,407,151,22,475,694,30,789,590,947,976,682,409,633,973,688,28,586,632,720,725,282,307,661,846,633,603,727,541,691,901,636,93,575,248,883,520,601,413,788,209,497,921,771,529,808,616,540,805,872,521,974,839,203,184,972,714,112,948,260,797,354,457,467,548,675,72,494,379,183,896,536,821,928,856,653,471,611,1000,621,22,419,389,584,3,923,611,973,252,40,721,131,552,914,828,326,664,365,547,351,880,571,934,529,735,53,480,554,977,986,425,671,820,793,506,723,731,878,833,761,272,319,935,593,937,354,343,816,299,984,878,783,57,151,95,755,29,98,330,681,852,98,680,880,241,479,312,257,570,538,237,744,882,435,752,191,754,875,861,473,535,325,666,752,44,718,199,314,466,340,830,365,935,607,240,220,630,433,626,693,677,49,860,754,371,710,903,734,312,340,521,114,168,904,580,484,428,608,766,745,221,704,237,217,248,824,579,569,132,504,255,338,356,576,74,157,335,981,920,774,116,21,393,34,803,474,601,415,375,903,3,88,494,655,156,382,185,586,903,545,808,444,222,62,503,707,584,835,150,108,535,127,141,954,251,835,967,136,987,787,127,883,572,994,197,162,719,110,19,211,782,133,558,580,499,811,194,797,598,966,542,568,886,42,376,630,957,249,79,959,796,736,253,836,439,357,42,587,462,105,578,711,495,358,999,72,553,215,352,790,462,776,509,74,995,433,534,505,114,35,624,544,961,98,672,111,821,339,18,516,859,121,374,101,991,778,291,464,930,288,432,967,632,498,769,997,245,316,911,104,840,178,5,602,828,342,127,799,517,666,356,522,59,312,620,91,362,320,154,502,569,245,627,513,972,223,684,429,767,522,204,438,192,454,22,644,629,999,262,796,39,640,618,48,174,185,906,202,453,824,140,526,245,618,196,664,105,641,768,716,938,580,97,92,0,993,504,971,854,121,56,236,73,165,580,101,120,957,391,387,375,829,766,979,67,660,962,858,680,198,86,6,548,534,61,827,654,194,401,902,220,292,591,797,410,27,884,723,949,977,534,371,372,397,670,226,765,292,304,418,8,973", +"502,284,561,374,463,811,393,842,775,781,468,73,358,548,266,763,447,136,713,464,781,699,147,42,946,133,57,168,958,328,207,364,994,395,332,986,41,487,671,35,887,713,328,862,385,675,242,865,2,140,633,694,407,850,169,47,895,944,606,820,654,382,418,500,221,25,43,33,629,562,468,6,103,835,297,415,463,115,206,288,55,60,727,566,47,430,201,92,878,821,175,23,172,151,386,540,599,87,442,785,917,947,872,892,598,308,154,725,337,780,328,608,849,304,513,779,72,859,14,664,889,834,5,278,839,357,121,794,856,68,951,656,879,978,847,264,28,883,327,778,36,474,185,816,873,661,913,268,516,263,722,409,365,646,60,807,639,782,959,367,941,639,377,187,183,710,68,524,463,506,804,207,741,255,679,957,315,317,643,775,353,13,352,254,167,943,733,295,186,394,733,433,502,198,198,61,313,216,455,444,710,556,828,333,313,799,628,539,515,278,75,119,800,611,541,520,605,405,983,258,83,369,205,93,808,160,594,48,64,904,29,504,597,719,58,150,856,746,194,781,746,300,402,374,99,367,222,906,502,281,5,9,841,785,85,424,545,687,186,868,598,269,183,505,99,716,978,506,849,96,958,403,382,590,482,774,649,699,376,698,317,86,793,658,734,58,743,99,499,641,381,949,43,410,499,450,950,749,612,590,202,54,540,130,702,521,39,73,969,184,161,20,741,701,730,789,304,537,90,573,711,781,562,446,814,325,412,78,359,467,87,717,287,658,124,132,354,536,760,456,392,972,218,106,157,115,489,422,289,97,283,851,424,177,718,184,945,326,272,185,839,590,564,735,47,529,419,61,62,877,816,695,790,505,386,714,933,202,373,378,249,781,316,783,737,790,605,131,13,173,706,654,605,875,248,893,988,418,537,650,403,11,165,120,385,924,309,195,592,313,868,832,926,943,942,478,86,508,934,457,218,684,146,48,167,85,568,82,118,74,190,89,543,672,132,365,673,226,146,512,522,614,233,146,272,191,404,985,581,321,222,15,548,915,329,45,486,440,62,724,824,289,386,21,681,443,185,722,444,685,559,976,361,234,912,502,701,326,989,780,656,100,704,21,642,701,23,746,585,909,62,113,922,640,625,833,202,534,245,567,252,217,305,698,168,341,972,347,988,735,573,807,81,500,21,564,903,10,683,494,546,993,777,158,94,398,849,860,208,215,744,496,281,774,752,71,959,157,774,72,491,830,446,847,316,951,507,115,525,438,57,202,344,644,685,133,561,875,857,334,720,602,954,906,592,47,274,877,94,951,787,262,590,433,534,412,150,371,271,875,523,236,581,116,236,938,794,277,182,80,687,119,574,188,262,721,25,645,665,296,470,499,714,960,638,61,416,670,481,130,763,851,522,277,627,98,366,853,242,223,47,49,774,171,742,872,7,738,99,602,954,775,174,101,703,331,368,554,837,790,21,440,765,597,302,954,441,80,978,130,786,105,665,136,368,507,595,538,218,143,952,782,122,882,203,312,517,967,164,498,413,217,51,861,637,364,645,374,117,570,744,946,979,315,468,665,132,75,814,34,337,443,461,776,549,619,661,561,530,936,451,428,794,675,926,198,286,987,437,433,833,573,158,742,787,784,122,58,387,143,88,528,664,794,117,141,578,936,98,523,89,967,327,369,164,648,651,639,623,951,281,967,538,699,110,322,432,109,837,411,946,751,273,347,992,919,129,727,303,152,632,936,327,497,130,93,561,149,33,314,788,260,510,35,264,657,315,808,286,140,441,394,265,216,294,548,302,265,201,346,792,118,691,43,548,412,372,199,752,702,635,646,66,968,486,344,234,813,828,131,339,318,116,901,926,377,544,676,499,421,573,350,81,555,892,171,699,986,969,832,704,889,52,242,953,581,324,129,701,477,330,77,501,469,916,11,65,234,895,70,49,128,506,915,872,893,225,113,599,463,772,616,652,942,691,245,470,619,771,995,425,550,798,752,3,176,570,102,908,524,875,471,531,138,752,76,564,320,499,194,509,896,916,711,232,657,682,980,344,453,894,357,543,278,185,241,980,312,185,609,510,574,127,104,491,449,829,566,434,256,901,883,619,430,365,673,213,962,758,3,956,611,881,12,248,506,966,560,615,286,985,222,993,0,645,526,561,333,725,24,682,940,354,316,47,562,701,285,110,248,871,110,146,739,86,330,786,169,654,119,741,805,132,412,389,736,742,424,547,617,876,351,879,985,283,133,285,84,653,917,923,859,869,995,260,290,586,90,11,24", +"400,749,873,709,353,998,64,479,980,841,259,547,759,918,676,869,732,251,268,590,737,20,769,310,692,77,592,122,679,68,286,85,107,93,204,318,484,635,814,813,943,600,432,493,823,255,904,423,973,776,598,416,94,205,408,314,689,79,851,110,465,367,457,747,573,923,176,831,337,991,937,391,42,254,348,533,742,224,12,780,676,297,654,621,860,527,627,718,515,523,175,589,313,433,362,965,458,884,60,116,180,343,444,837,524,572,517,892,720,189,70,847,507,221,336,568,730,916,75,652,687,242,732,101,34,538,304,872,918,622,140,727,454,24,240,476,819,767,399,971,949,984,613,640,729,444,324,324,337,254,312,246,291,353,261,274,186,373,59,8,682,803,976,368,596,691,274,93,173,201,63,56,44,196,835,38,137,720,46,3,426,690,944,344,173,919,319,278,29,993,300,947,78,104,401,90,901,751,853,304,459,705,907,368,300,624,998,903,85,763,598,17,443,610,62,975,956,454,776,778,332,791,98,309,428,900,910,868,6,547,164,661,780,913,692,677,582,402,795,726,486,292,492,947,360,805,962,72,47,100,840,947,781,643,490,802,69,716,62,962,298,64,780,104,729,640,256,93,406,965,395,815,844,201,468,393,253,131,592,759,843,985,783,878,898,511,681,192,277,522,37,708,885,192,980,84,22,473,169,236,907,392,314,951,91,87,151,35,315,644,520,529,214,14,298,986,676,676,65,932,359,95,851,138,597,305,461,906,22,721,774,410,592,320,158,445,738,49,593,60,959,603,734,200,640,749,400,418,955,951,355,764,365,31,863,872,628,151,62,105,827,736,471,559,960,667,838,954,101,749,779,860,903,171,532,247,567,496,243,141,742,494,74,552,850,450,572,261,770,827,53,973,42,266,237,792,781,479,656,882,944,583,740,493,180,780,965,580,659,582,214,340,764,724,857,748,315,514,91,955,42,80,734,182,501,194,961,12,502,519,180,789,527,887,390,828,800,12,410,781,226,366,2,689,497,683,828,171,806,343,53,761,731,628,250,929,521,904,166,77,533,803,609,15,416,180,882,355,520,264,231,713,957,476,379,82,351,862,871,327,178,287,150,273,403,612,327,348,9,177,210,315,502,563,416,388,651,792,419,535,214,298,946,671,512,798,880,542,500,457,603,922,614,115,260,433,622,473,646,981,900,959,515,141,406,751,884,321,498,817,103,808,19,285,726,317,575,318,301,914,769,392,836,621,603,418,619,867,604,189,724,462,562,792,289,521,553,337,921,434,401,362,804,432,989,179,673,151,866,598,794,293,907,817,318,814,151,300,392,376,32,845,844,852,48,236,585,758,811,797,497,223,459,993,879,10,277,594,907,286,127,700,38,533,941,143,72,910,727,147,221,548,267,558,856,226,466,764,327,50,804,651,660,644,231,353,257,118,652,693,18,481,180,117,55,265,104,149,617,532,50,896,228,924,190,851,55,98,459,590,18,406,212,233,412,151,862,741,584,409,861,740,129,583,96,36,939,933,364,926,469,967,364,784,57,56,959,730,758,595,366,782,752,867,755,791,276,298,643,564,422,348,329,716,403,569,931,981,971,191,411,230,947,672,474,23,877,517,190,572,804,254,430,742,496,73,922,441,534,938,900,290,21,510,772,15,969,615,172,58,758,316,328,617,609,221,744,742,122,795,163,417,506,102,506,559,581,171,101,366,220,160,396,473,479,237,961,505,501,611,579,109,330,74,91,587,178,171,637,721,540,623,317,35,315,441,913,194,479,264,227,153,539,905,595,331,488,296,837,199,426,88,600,562,289,293,26,84,906,755,601,727,485,787,279,66,145,807,776,288,46,969,274,840,954,499,984,942,50,772,362,781,472,219,674,861,54,601,813,440,37,417,988,177,324,910,948,9,291,916,606,144,80,899,898,667,33,199,920,781,131,813,958,618,328,456,293,414,265,359,966,619,290,534,75,846,842,185,861,957,23,92,463,247,784,58,277,287,307,244,47,590,105,913,501,155,774,173,268,232,907,937,45,252,772,917,494,477,484,443,296,777,47,171,928,654,811,980,257,566,627,976,344,725,292,708,21,752,632,319,602,44,768,554,715,422,580,980,281,763,574,898,647,802,342,448,679,79,722,144,726,566,504,645,0,523,39,72,644,772,887,985,955,473,308,455,624,549,142,23,516,292,418,984,699,363,793,586,103,62,332,876,433,325,12,577,490,350,412,25,475,624,471,529,779,333,712,208,740,128,445,490,252,671,819,321,289,233,908,661", +"937,33,916,839,417,103,522,185,820,49,366,295,727,936,615,740,413,645,108,828,587,313,452,149,457,229,991,28,254,351,208,793,989,897,342,224,712,770,859,55,990,912,910,87,379,958,422,447,454,701,718,627,809,777,178,830,988,459,858,330,78,322,768,410,240,232,193,176,424,130,59,316,426,329,590,793,41,312,799,858,965,314,671,405,424,884,71,715,51,217,564,654,217,432,834,311,851,534,565,120,106,74,737,2,977,345,587,563,751,721,124,680,849,553,238,691,636,285,434,937,276,957,991,64,135,260,697,69,247,372,721,354,759,326,969,482,361,567,610,254,662,856,207,196,218,990,509,365,566,163,429,21,448,866,944,815,539,484,427,755,500,782,452,244,373,305,829,738,833,90,175,399,90,981,7,769,837,49,302,452,312,830,127,487,67,631,629,301,427,470,171,537,599,683,825,254,348,253,130,119,136,657,898,323,214,166,847,263,261,372,903,410,475,846,57,111,138,390,139,722,219,121,177,43,591,907,144,998,528,730,689,265,518,450,456,286,581,157,60,196,214,980,205,475,984,914,78,303,450,383,213,480,383,499,279,463,748,751,325,133,993,153,530,459,330,345,949,379,717,476,296,290,1000,178,557,534,796,711,704,166,298,295,999,187,267,657,764,610,157,385,222,755,552,606,554,307,390,119,733,101,126,598,631,894,104,153,250,207,154,746,572,813,207,211,570,639,380,122,275,781,349,760,809,65,840,838,636,38,930,406,797,492,601,693,924,23,470,204,692,248,888,44,355,127,515,599,807,128,770,606,747,463,477,964,62,502,532,727,457,496,488,41,241,391,625,693,582,349,526,224,979,692,479,463,757,476,566,281,450,989,519,157,362,378,927,839,800,354,390,674,599,300,827,276,56,124,947,780,526,381,604,404,14,152,27,877,805,76,584,652,665,404,208,93,675,550,387,140,784,987,49,972,556,199,498,250,747,705,863,429,197,595,601,718,309,11,391,150,555,620,450,754,535,127,847,785,80,35,146,656,699,738,225,959,719,90,406,403,727,55,445,361,581,127,778,537,893,364,886,330,822,150,121,612,395,967,518,62,49,681,800,504,329,920,756,185,509,798,21,342,807,937,306,697,871,430,216,5,427,674,369,637,546,747,671,324,408,50,736,246,327,371,89,655,436,535,585,419,112,463,960,489,763,208,530,760,447,816,975,845,469,123,971,747,756,698,884,477,895,251,20,952,178,691,140,724,954,771,686,742,610,407,523,78,841,643,292,74,451,214,733,378,929,229,415,509,9,740,171,292,889,337,54,537,548,620,963,154,178,345,937,988,1000,955,579,60,975,527,573,703,56,712,836,828,391,477,57,219,441,665,949,596,43,670,516,477,733,959,532,612,550,69,556,390,927,98,966,546,981,145,602,400,706,99,187,79,750,816,267,674,383,788,626,106,752,906,892,540,651,702,167,939,564,192,823,16,458,749,980,575,350,431,606,282,72,52,330,745,586,505,660,995,514,908,855,795,72,261,501,728,159,706,145,302,728,212,578,861,442,781,995,993,459,25,15,361,589,223,712,865,856,680,233,166,565,215,162,336,233,143,136,980,443,594,43,162,630,349,479,207,760,832,246,538,146,265,405,449,229,893,56,919,313,356,44,893,652,979,739,67,832,540,540,367,25,934,452,724,908,701,855,187,353,117,151,236,220,455,745,791,571,602,752,569,354,241,582,657,670,85,878,747,641,64,170,423,399,837,99,873,242,62,297,884,695,385,191,9,763,898,605,608,904,165,64,716,520,582,509,112,689,654,760,13,457,659,78,785,923,557,735,425,382,469,611,500,574,212,609,234,203,407,895,447,609,461,384,990,874,706,433,961,511,947,254,135,53,420,452,242,478,10,959,467,828,74,875,921,816,417,988,736,147,735,14,411,691,20,919,143,863,994,751,1,435,821,274,80,366,782,21,952,539,285,884,124,199,998,709,825,364,774,398,838,858,531,433,353,558,567,109,451,583,871,677,591,100,358,301,223,867,929,805,198,533,925,809,137,826,700,177,164,80,111,530,366,327,112,484,520,921,479,766,697,8,969,302,29,541,156,761,441,256,493,418,242,959,177,953,723,906,929,453,804,354,398,480,26,481,487,877,88,971,526,523,0,418,5,512,926,489,893,790,70,953,981,861,144,618,643,213,62,926,883,283,253,420,281,932,341,261,721,486,968,93,903,21,549,948,906,500,306,178,232,440,500,227,446,466,812,727,176,788,84,759,186,231,988,910,578", +"653,812,478,956,733,821,277,97,673,876,427,776,755,159,956,15,501,466,425,182,62,273,513,5,543,548,176,826,77,768,950,266,630,84,417,503,389,650,885,435,833,328,628,845,35,552,589,520,320,943,374,675,662,846,102,504,583,531,124,821,101,188,705,783,522,545,900,706,554,910,779,82,552,118,683,931,457,615,112,317,26,68,847,462,752,940,52,613,744,30,297,42,575,416,989,979,14,623,311,380,275,251,931,237,140,720,397,150,977,212,827,936,557,854,310,592,162,760,756,36,680,273,321,594,246,256,918,428,531,940,340,776,122,370,126,384,675,320,409,894,171,449,445,778,640,224,577,896,498,510,808,333,28,874,772,283,983,287,132,128,66,82,357,57,20,266,842,878,958,961,602,179,897,168,328,785,95,827,519,648,570,352,339,990,77,856,259,205,915,491,597,584,578,800,715,475,923,234,464,422,812,385,534,533,86,152,89,315,671,464,995,826,235,400,155,952,410,513,983,987,703,681,631,118,153,527,260,300,954,849,547,471,263,570,34,287,159,1000,610,793,198,458,788,854,832,759,633,280,469,663,506,36,755,888,946,643,549,181,349,126,999,75,795,151,807,629,865,358,385,990,655,202,716,894,498,801,633,115,117,430,724,559,944,534,641,656,119,660,500,505,314,18,573,354,1,295,300,525,368,250,84,832,669,224,423,105,708,231,224,508,318,458,728,713,355,736,844,902,420,498,440,767,579,711,139,423,112,558,643,342,854,344,299,799,692,656,758,941,399,795,349,164,724,479,903,407,258,306,409,863,982,3,352,616,609,49,403,676,167,774,225,622,484,98,531,365,434,432,50,635,669,800,672,145,214,708,713,738,634,93,710,449,245,210,538,359,928,662,172,782,929,740,366,54,456,974,878,266,106,300,335,41,328,884,498,359,657,854,60,658,999,322,345,220,936,915,242,674,418,9,765,5,867,795,452,773,759,957,405,443,570,620,421,419,966,450,493,315,198,951,228,303,902,994,107,585,50,27,104,654,933,305,566,89,476,577,834,246,227,341,712,637,36,960,321,415,309,868,71,660,80,722,198,961,549,51,933,914,754,777,564,359,824,439,808,11,556,796,796,933,262,657,186,12,121,190,581,765,852,603,236,432,255,407,83,723,997,474,626,341,625,767,955,596,581,148,443,891,588,321,877,554,945,521,266,94,404,735,343,992,435,521,238,958,854,275,672,324,439,132,17,299,790,39,373,807,743,217,26,623,695,104,968,79,406,487,191,668,75,443,668,608,564,366,857,825,615,935,629,878,462,30,304,916,313,386,219,350,104,974,34,944,524,472,666,660,95,598,687,294,359,813,137,718,826,652,281,615,708,877,318,108,554,715,325,533,882,93,496,341,913,561,136,186,105,886,468,239,729,180,967,127,110,90,807,386,552,947,829,444,310,319,740,902,805,185,1000,731,840,659,667,791,50,135,431,435,857,450,935,307,644,645,775,301,205,131,479,191,40,915,97,201,945,681,981,3,686,217,436,443,167,802,639,207,623,264,832,816,181,99,476,992,683,724,268,470,484,795,857,929,96,687,26,755,431,554,997,980,334,58,365,24,622,752,268,342,131,690,900,336,78,217,763,917,422,422,682,892,945,310,144,238,47,851,93,211,640,237,373,284,570,548,394,74,114,315,378,831,267,193,738,259,942,348,291,805,180,270,232,649,141,417,794,857,628,404,586,240,51,735,287,959,75,160,98,885,371,600,649,240,552,837,512,593,927,100,60,526,352,101,601,155,649,604,343,463,424,62,407,131,979,895,716,359,289,658,691,497,51,164,622,139,787,447,118,759,712,868,56,253,876,458,787,292,836,727,290,445,279,266,900,599,172,928,18,977,579,429,218,84,427,774,266,517,927,844,261,762,140,135,711,590,796,97,184,873,108,553,322,589,343,67,834,529,481,851,126,593,224,350,202,54,830,870,837,184,287,831,874,100,625,864,776,700,622,253,105,849,998,673,399,760,489,130,206,667,227,442,606,908,594,88,489,628,189,453,847,637,629,17,568,841,130,262,890,812,16,281,323,58,675,277,833,698,393,846,68,602,699,31,496,261,366,552,901,149,682,519,934,275,95,149,400,519,226,348,238,940,888,708,957,327,854,561,39,418,0,46,302,693,80,940,473,69,779,258,562,926,832,529,72,633,361,753,493,953,438,902,873,268,31,106,874,515,832,435,265,670,515,123,90,979,883,985,883,223,344,891,931,700,291,831,558,138,704,144,858,816,135,481", +"653,480,11,600,999,190,372,907,505,372,458,975,850,70,822,227,421,690,820,291,487,219,883,692,276,279,745,477,723,810,537,182,537,676,958,942,925,92,220,579,868,52,164,155,654,614,243,821,62,153,792,119,487,355,526,360,280,542,969,361,619,320,131,4,569,829,679,646,701,337,386,470,327,961,297,591,550,461,140,639,445,283,853,573,396,975,717,696,5,208,721,67,90,634,320,635,644,456,922,611,222,568,956,304,313,386,128,648,638,12,530,918,832,52,849,894,751,591,579,3,477,424,165,253,810,448,255,856,960,760,341,326,933,849,276,443,364,560,694,36,782,179,820,503,131,571,167,983,909,980,228,408,447,661,808,885,521,396,226,666,973,93,28,197,526,174,780,178,673,556,276,430,136,584,535,616,564,275,317,852,917,801,576,560,839,623,99,921,822,736,421,764,856,412,247,450,765,867,960,216,324,225,25,978,195,232,239,631,763,596,929,134,178,244,714,67,763,944,578,52,365,163,175,145,117,777,91,98,716,472,517,807,217,612,731,160,704,767,985,701,233,158,212,175,537,289,581,773,878,360,265,206,852,649,862,898,387,463,457,563,891,900,427,106,212,549,530,176,789,67,21,735,802,112,144,323,812,622,833,457,168,389,328,629,172,218,962,35,3,155,383,688,753,486,721,209,107,16,109,503,168,272,579,306,105,866,750,924,562,438,562,834,263,182,55,63,436,80,647,255,669,214,805,27,958,131,132,536,362,720,210,643,217,723,239,630,728,567,33,233,36,929,343,629,618,803,671,631,936,191,831,76,472,132,578,754,269,322,947,555,766,859,35,53,269,337,641,560,458,586,605,103,101,718,798,2,691,891,739,936,923,240,478,739,182,198,675,428,899,341,75,896,322,105,786,178,532,263,327,172,925,427,354,956,773,274,139,820,126,703,534,169,483,865,765,674,299,606,105,138,830,111,986,388,473,329,688,779,574,388,997,640,254,46,270,762,574,886,803,307,542,756,370,103,619,267,158,647,284,63,794,854,949,833,3,411,176,755,339,589,192,377,737,494,321,533,236,828,704,170,622,680,573,226,849,946,790,810,382,718,65,603,605,711,493,884,609,677,324,384,92,408,994,261,275,939,68,303,655,340,366,548,796,505,852,294,221,514,717,675,499,221,183,583,832,326,358,203,260,152,267,783,363,849,147,842,310,432,245,349,22,886,164,972,321,767,459,250,612,115,853,273,542,764,43,981,165,864,160,634,380,585,670,983,101,835,438,953,473,877,939,974,830,626,477,370,244,13,427,288,501,535,154,44,560,998,328,557,3,317,951,804,225,616,933,200,68,447,890,359,590,731,249,979,56,329,979,772,967,656,308,149,239,970,716,135,667,41,125,756,78,563,955,262,277,565,953,800,970,730,150,619,350,933,11,349,392,986,847,222,577,749,229,435,368,674,779,46,689,2,519,146,896,517,663,435,836,576,795,206,688,489,367,266,817,372,773,156,640,611,660,512,180,831,708,322,734,153,366,466,662,252,561,110,958,687,136,468,963,220,235,449,296,785,17,525,335,379,141,686,218,585,213,493,527,378,388,128,873,471,505,751,632,964,798,958,881,497,468,12,955,122,175,965,768,189,538,298,167,787,663,993,60,967,227,877,712,967,802,548,905,627,312,914,955,305,570,328,225,886,739,605,314,561,935,394,718,344,618,741,575,975,689,903,667,21,229,42,867,634,919,797,765,90,853,442,692,89,955,747,765,529,918,110,517,888,294,931,980,563,761,723,159,310,182,961,812,169,586,752,154,382,506,869,23,806,956,340,115,330,122,531,598,653,331,311,98,166,143,952,329,475,310,272,646,53,914,649,157,186,311,628,695,886,339,496,43,484,555,868,880,997,581,173,51,676,307,597,516,375,82,846,129,532,523,399,111,307,869,993,591,224,958,736,170,978,381,246,267,457,789,911,461,744,547,972,358,156,628,879,38,227,348,297,776,234,283,191,62,731,350,435,557,908,225,189,163,497,2,643,654,872,184,649,333,536,271,681,747,926,122,297,856,574,783,827,192,495,992,640,362,343,574,936,993,403,314,334,396,348,924,302,951,924,148,881,351,933,773,270,553,756,778,601,134,461,304,602,119,387,525,830,121,333,72,5,46,0,635,206,149,434,157,519,58,436,297,197,460,345,494,22,637,658,539,258,90,718,162,187,436,247,498,833,718,192,345,796,445,787,277,539,675,179,453,647,469,712,126,424,230,195,702,954,35,440,442,38,973,899", +"352,949,470,429,854,73,660,373,679,873,908,291,676,312,879,741,75,188,626,143,328,212,975,752,414,961,930,523,999,970,133,156,958,324,583,580,415,512,468,369,898,46,98,876,338,389,527,867,348,760,639,32,592,787,443,889,358,348,13,723,888,593,728,953,822,212,857,761,959,65,253,258,449,704,268,816,838,165,744,923,869,342,982,22,770,473,888,278,211,34,666,490,346,40,61,851,97,790,115,798,110,24,573,625,104,838,440,263,642,893,789,794,197,167,726,953,529,693,648,763,46,368,512,938,619,389,797,393,258,365,889,604,513,14,342,448,781,33,364,767,157,673,500,9,300,117,893,26,822,615,173,209,659,92,328,98,788,553,643,79,542,66,339,749,755,511,198,696,98,73,615,597,173,694,550,21,89,892,692,11,988,307,980,28,272,896,668,231,613,589,867,344,313,399,31,421,459,439,493,756,532,676,577,883,646,240,354,992,822,555,251,18,319,618,643,782,1,998,871,489,938,13,565,142,61,778,323,41,299,479,678,718,73,541,767,874,513,385,173,399,433,338,107,113,926,920,931,776,14,982,975,666,180,57,399,375,372,982,167,499,661,188,505,134,408,912,992,129,486,219,38,920,297,64,5,346,742,490,641,367,77,127,460,104,395,535,185,980,363,858,572,804,141,754,594,964,114,516,232,838,9,311,94,855,583,202,968,743,431,669,467,842,404,566,279,803,88,472,392,705,277,298,376,904,789,418,243,661,866,48,270,523,387,470,631,724,639,438,583,908,464,249,732,774,800,554,413,797,856,118,176,269,453,956,60,690,962,320,322,548,59,817,34,4,702,611,621,417,657,645,655,675,804,862,39,83,762,173,351,458,401,806,363,278,400,324,83,277,406,935,688,688,9,758,605,94,469,550,796,679,644,655,23,959,195,81,992,389,255,717,104,63,856,143,950,764,33,575,870,458,689,669,431,959,863,186,221,342,99,15,940,814,439,348,61,515,354,190,447,485,620,542,463,717,800,998,868,739,820,245,426,830,122,152,871,837,878,401,221,540,631,348,555,591,52,379,622,250,45,639,667,555,474,312,399,609,962,446,224,392,245,808,780,723,544,187,474,544,253,919,788,453,462,861,921,330,438,941,501,696,475,296,543,304,825,919,590,644,419,769,619,887,798,690,370,931,976,364,455,64,381,407,341,895,16,937,759,250,114,707,65,74,343,233,746,944,923,163,40,906,679,29,731,95,129,713,442,480,192,913,601,264,220,9,753,618,34,193,788,898,263,355,301,822,310,168,859,722,910,605,686,204,738,719,936,584,936,819,458,122,528,881,114,120,390,815,412,196,608,503,393,11,884,538,943,855,182,825,617,975,743,805,322,57,180,333,935,496,925,883,565,370,582,662,152,853,434,132,481,282,321,605,559,839,754,627,291,769,907,935,14,871,788,757,599,702,161,195,628,396,351,543,467,70,696,205,455,820,257,572,621,775,15,183,549,685,307,572,651,172,447,727,187,428,95,963,106,89,74,691,527,24,114,723,811,754,112,264,466,498,155,548,650,562,330,592,14,458,113,629,18,686,829,327,335,238,939,890,439,463,312,13,453,386,361,925,128,102,974,832,972,582,661,112,244,565,665,82,188,972,978,477,59,72,754,730,812,535,763,820,961,931,794,87,821,231,622,382,264,545,212,134,465,394,615,665,328,350,548,856,6,783,494,955,79,773,754,917,463,51,294,93,350,547,651,373,403,706,127,435,486,385,993,139,177,787,378,718,156,215,563,268,849,18,32,523,463,101,953,670,920,830,449,200,97,300,269,366,494,28,93,337,253,189,307,939,510,399,589,963,700,51,403,363,84,369,825,929,821,293,35,776,558,368,130,518,433,728,288,532,498,142,159,989,507,51,628,244,991,725,442,530,995,336,822,668,440,524,753,811,925,664,154,648,130,597,73,102,271,754,964,698,524,920,207,610,660,232,731,446,137,603,687,418,739,394,231,340,256,252,245,716,583,391,146,732,157,486,273,810,763,959,978,968,285,865,381,708,697,640,681,38,750,656,288,231,510,331,121,377,605,55,572,546,12,380,519,138,231,814,720,245,147,917,973,835,865,919,978,383,28,40,206,249,344,30,880,580,680,664,21,173,56,725,644,512,302,635,0,769,877,552,216,212,635,847,259,485,514,736,491,122,912,22,532,490,497,682,978,769,186,650,206,951,533,392,356,860,672,817,948,843,89,940,718,522,987,645,450,542,763,113,779,133,338,268,189,79,994,798", +"619,133,583,600,307,647,484,969,351,354,297,52,4,721,10,790,103,849,391,8,908,47,290,644,859,680,929,11,176,917,371,738,437,519,40,444,988,655,294,89,141,960,986,980,702,352,29,776,690,187,532,362,954,632,393,614,667,271,500,16,662,633,835,372,280,58,742,890,780,820,882,710,373,402,130,375,700,300,814,726,166,75,629,515,634,358,622,920,948,358,356,125,124,629,235,274,989,591,115,51,399,285,510,868,144,795,818,78,306,623,386,80,736,961,76,796,571,12,645,106,820,777,710,122,472,513,750,479,688,392,855,590,577,865,334,918,658,106,222,13,807,568,470,131,964,221,570,698,815,573,622,140,259,865,137,232,278,458,152,619,653,162,792,45,816,548,136,281,512,153,114,332,534,319,131,804,33,32,346,413,629,195,569,386,229,7,4,486,495,662,518,210,406,661,4,157,200,572,958,380,753,166,102,882,824,702,907,75,17,505,20,569,299,696,198,585,990,557,114,554,507,956,590,180,377,208,413,836,494,738,311,655,916,709,345,204,848,294,307,49,286,62,883,662,152,96,16,293,713,453,769,678,93,690,645,3,771,601,77,445,875,549,401,620,54,871,320,435,542,784,873,620,305,324,797,674,231,722,739,311,921,303,813,17,698,938,676,105,345,300,144,617,58,820,466,873,504,708,405,93,837,667,903,939,853,802,384,669,455,391,132,783,456,464,875,508,833,95,723,190,661,966,966,487,181,502,386,281,415,994,865,645,591,561,398,873,674,116,190,540,369,227,23,243,310,311,427,378,674,452,608,426,752,188,744,413,205,209,759,984,685,71,732,521,566,326,707,109,999,869,30,997,17,146,829,363,802,4,599,848,661,972,251,888,915,874,28,782,821,152,603,418,157,105,130,885,102,73,181,693,692,774,878,301,621,654,82,573,700,151,91,13,518,493,607,648,15,503,209,822,287,635,451,973,440,255,720,499,63,499,358,168,374,975,40,910,449,923,61,705,902,376,127,955,798,212,342,846,822,241,488,731,284,932,685,512,225,743,304,953,192,47,912,896,443,103,843,827,157,748,541,49,307,860,180,344,981,311,564,427,901,174,854,721,634,663,50,794,628,709,597,432,164,815,949,364,28,57,792,596,830,677,779,965,688,224,225,489,311,511,581,173,700,790,867,999,438,911,373,330,986,885,365,140,622,904,700,35,134,306,842,601,908,852,888,316,357,43,879,881,690,638,824,369,394,861,328,951,14,79,569,774,143,772,151,235,149,439,169,70,305,59,237,622,749,604,752,940,607,294,663,595,13,288,864,474,913,199,880,195,347,375,524,237,140,641,962,270,314,805,855,759,982,815,125,460,400,566,962,611,441,481,401,338,78,688,905,615,131,404,722,885,485,35,812,621,442,733,809,977,549,327,44,998,545,572,819,589,704,393,396,380,474,798,799,697,824,399,860,213,509,381,704,183,105,427,278,885,957,961,121,246,89,449,982,555,641,919,257,317,12,614,409,978,32,923,249,979,382,874,759,911,316,525,123,519,180,430,346,466,508,718,589,528,997,916,276,122,274,276,699,794,409,410,377,117,731,788,942,42,169,181,85,422,441,176,716,755,579,450,599,372,307,947,50,21,66,310,89,533,616,249,155,882,177,957,147,970,696,718,833,838,725,851,502,566,67,320,632,358,26,774,663,195,647,863,939,823,898,639,710,988,383,651,285,486,627,815,759,195,547,536,250,999,585,526,937,46,24,916,674,648,470,61,626,788,831,535,553,83,622,145,9,538,544,890,193,885,421,603,684,210,356,418,291,243,289,498,172,602,925,898,230,263,554,557,873,696,611,192,770,313,7,119,461,683,955,613,672,850,649,550,797,553,935,452,690,767,701,625,723,752,386,171,802,869,717,554,806,413,376,816,723,177,373,626,607,358,709,477,865,210,238,448,83,644,798,963,786,474,42,152,991,868,267,245,839,518,84,496,508,845,579,132,427,521,51,136,953,275,202,25,976,728,824,9,970,67,510,594,839,280,604,541,649,137,555,160,351,966,872,275,234,552,994,83,209,641,853,118,83,739,340,628,78,777,290,809,728,324,596,29,982,456,935,521,846,400,404,57,778,227,639,785,276,834,825,852,751,716,476,885,236,24,772,926,693,206,769,0,674,374,156,491,90,687,456,997,360,378,708,337,551,955,14,167,582,919,873,941,641,857,918,107,922,86,296,16,511,302,313,322,40,91,695,560,57,446,239,657,455,94,434,862,178,570,96,884,57,145", +"733,947,601,92,510,715,5,19,31,78,67,57,250,883,351,5,473,285,927,866,772,932,153,612,743,612,320,800,589,157,573,581,409,375,630,827,545,754,657,438,293,55,239,350,831,225,882,885,332,238,562,49,533,764,74,488,112,405,334,743,802,953,397,367,952,893,659,981,143,605,856,875,16,541,191,853,682,304,640,918,512,180,77,451,614,548,406,461,248,619,130,639,511,570,158,510,940,531,737,170,538,693,756,560,77,386,224,398,951,501,524,503,78,635,488,405,433,986,768,197,842,709,920,236,428,330,387,865,967,369,881,98,292,471,727,194,164,402,202,514,9,381,573,433,491,171,433,185,264,563,65,859,445,752,76,742,300,158,701,974,259,444,945,94,418,128,604,990,245,467,848,397,244,542,737,24,595,161,111,190,502,611,481,514,607,987,332,196,701,802,579,853,277,908,291,40,980,351,920,377,599,401,812,214,486,251,654,80,691,140,308,712,623,533,264,444,865,453,318,899,521,434,589,131,952,890,858,340,841,247,251,789,155,773,748,698,829,757,812,894,924,757,667,956,706,455,188,245,89,440,327,410,249,825,615,462,56,390,784,879,745,731,897,640,230,261,978,502,390,292,980,276,880,481,555,478,441,943,446,38,201,509,486,779,776,776,174,155,408,777,601,257,879,785,560,994,787,759,35,912,884,313,990,47,242,528,907,109,876,724,432,905,38,885,141,231,111,715,884,442,965,801,693,496,646,340,933,396,82,215,709,231,9,63,904,918,910,496,719,440,886,706,274,195,829,821,42,613,815,588,473,75,976,762,480,987,675,854,450,872,225,437,73,81,334,676,110,991,726,142,682,892,703,210,287,98,678,533,224,920,217,987,252,486,667,494,755,165,590,428,88,756,594,841,494,646,638,865,524,380,461,708,98,529,588,321,40,112,584,261,678,283,595,450,365,507,45,869,820,719,980,327,496,254,92,330,767,73,671,60,285,92,685,562,20,8,573,69,352,218,711,507,558,228,786,791,312,238,594,300,516,315,785,501,113,236,530,357,706,822,536,896,632,97,155,591,638,895,113,830,994,938,455,928,875,131,48,761,630,750,186,954,649,986,709,430,444,826,521,546,400,917,499,70,592,254,186,821,473,826,222,975,172,212,819,535,300,903,259,822,404,363,237,947,420,796,561,901,698,768,578,46,687,936,688,381,439,607,918,656,864,412,398,792,720,422,758,57,510,616,877,823,314,455,376,240,434,320,703,317,119,212,57,58,728,202,796,206,838,837,437,204,104,685,241,366,87,841,955,551,472,668,171,136,797,753,639,455,392,370,574,547,752,832,494,836,39,216,671,219,525,931,863,881,743,366,573,381,377,88,322,535,737,928,752,999,829,328,971,282,895,932,83,694,380,655,397,17,505,462,992,202,306,961,76,768,244,488,297,444,796,977,181,650,563,288,687,269,249,945,169,232,781,10,483,728,848,975,637,612,210,73,819,505,657,640,327,966,586,777,878,333,297,301,25,21,52,62,33,440,154,808,401,500,40,357,739,16,104,97,769,255,374,141,25,624,233,224,974,927,606,685,971,38,589,259,174,123,13,804,935,713,364,70,454,151,650,766,873,10,138,776,22,474,824,527,75,282,408,257,738,596,874,562,81,202,305,404,460,804,457,362,276,318,38,760,489,243,420,429,636,106,891,147,917,613,691,850,988,76,272,421,973,95,737,784,15,831,962,919,171,567,866,952,865,181,415,941,379,608,550,142,797,78,273,93,846,364,548,414,187,108,244,471,306,731,527,326,20,854,165,365,152,63,213,467,387,726,728,565,48,90,788,311,765,126,600,799,641,874,260,505,647,2,435,372,439,285,734,368,379,572,708,8,865,884,630,675,64,799,166,504,950,125,692,664,346,447,637,383,775,887,548,396,450,341,174,74,62,296,872,877,961,630,253,405,724,30,831,344,914,942,903,155,117,426,615,281,740,337,180,174,828,155,45,947,537,579,238,141,195,43,945,99,440,384,404,109,755,861,254,915,371,29,93,719,992,982,662,826,653,801,738,821,414,888,42,257,944,500,228,691,210,762,847,414,36,120,616,411,353,700,329,990,957,862,347,559,762,843,563,999,11,905,287,746,79,472,223,790,730,616,73,682,887,489,80,149,877,674,0,311,172,602,140,20,599,787,575,471,289,388,606,786,839,543,634,720,514,945,984,604,796,189,406,925,228,549,374,315,221,465,947,961,264,414,452,867,650,410,243,625,750,762,565,387,150,746,378,225", +"275,204,973,276,421,315,758,346,667,52,492,991,921,62,188,759,23,452,55,611,813,586,414,34,364,221,756,448,429,670,704,445,854,137,417,369,403,228,268,845,759,967,110,314,283,533,491,886,183,750,219,200,347,239,2,939,303,960,224,338,609,940,670,821,383,528,859,808,147,692,984,479,524,28,863,615,529,63,136,275,172,858,39,441,30,250,616,533,327,346,393,264,902,13,299,250,883,938,937,168,276,498,452,370,749,279,678,856,455,383,478,334,818,831,612,517,170,210,245,453,924,318,481,608,729,435,244,61,316,679,418,975,239,933,474,862,724,720,955,575,720,722,999,646,615,431,727,146,59,480,187,384,570,454,810,453,821,658,602,9,397,628,549,453,459,875,182,813,155,563,597,294,154,421,716,479,986,774,376,341,325,395,951,566,441,684,264,894,156,639,96,12,143,976,306,406,757,619,151,155,14,625,902,708,107,473,362,807,350,896,855,389,11,556,589,306,580,140,575,530,756,868,276,413,190,94,851,838,897,106,736,299,104,778,49,873,167,275,63,671,80,589,757,595,234,965,406,332,629,157,853,458,340,410,735,648,995,922,219,930,740,726,86,631,758,786,70,70,359,491,326,956,209,238,778,101,950,866,356,736,145,374,440,804,192,300,810,490,963,765,689,142,939,825,984,799,216,629,60,614,442,689,412,913,368,928,698,808,49,908,424,131,126,264,618,400,515,411,843,489,122,445,606,875,657,334,341,250,940,792,383,959,528,856,715,222,320,623,928,701,521,697,612,18,424,270,848,323,371,656,437,374,526,823,778,35,733,411,184,38,995,899,759,230,589,78,26,554,410,842,493,629,873,595,363,760,740,43,921,605,280,223,252,355,340,893,270,333,663,813,20,79,939,540,10,130,949,618,668,70,56,282,111,187,726,828,191,205,59,4,44,968,493,561,400,166,487,630,718,310,207,617,213,480,82,147,528,254,910,347,558,674,841,935,520,163,921,273,912,781,363,479,259,540,245,745,201,5,507,22,523,590,73,262,500,130,435,879,997,156,972,195,925,422,779,432,399,901,239,360,250,74,786,144,741,84,880,594,268,313,152,124,172,744,654,162,352,519,685,918,38,209,545,608,604,229,459,497,771,166,50,261,876,501,829,462,173,533,657,606,298,536,447,123,801,774,179,957,931,976,149,402,847,866,10,471,170,390,444,322,721,289,831,223,463,534,823,843,475,695,80,222,209,57,387,268,157,668,376,979,612,819,19,446,764,416,641,541,601,735,870,638,46,259,922,664,500,42,431,581,860,981,555,908,463,603,653,537,984,618,475,280,846,106,296,464,537,319,325,907,456,638,389,598,140,270,242,195,955,484,631,97,77,867,724,153,912,958,954,875,695,388,167,568,456,884,799,691,321,194,130,864,103,878,796,564,430,120,761,709,76,248,566,119,991,531,785,328,985,253,380,162,505,651,64,475,234,612,685,717,242,98,729,540,92,57,442,743,346,683,430,596,658,963,340,859,818,441,766,633,497,25,942,968,322,603,820,193,584,979,123,923,577,572,188,898,118,49,646,623,592,354,371,675,397,980,668,794,32,844,782,439,736,369,632,159,855,919,565,295,161,826,877,409,167,405,14,73,418,876,736,42,727,837,151,204,220,386,788,205,25,396,980,936,437,464,333,691,396,830,339,275,430,660,243,153,756,886,16,649,407,868,424,893,224,436,776,273,945,622,490,589,76,31,874,852,814,224,573,431,366,160,627,185,503,566,234,873,654,394,439,786,493,92,789,75,373,960,422,858,909,802,856,844,748,945,301,911,65,10,871,576,606,699,201,761,143,724,543,960,474,873,511,272,345,20,307,434,240,678,914,777,784,729,577,787,843,301,416,713,694,307,204,138,63,846,928,767,563,696,199,166,691,440,419,392,421,68,388,348,739,590,478,531,965,324,237,408,687,547,126,325,463,892,353,606,841,466,189,206,430,569,835,832,985,858,324,321,834,325,106,171,655,343,701,135,70,812,703,110,463,404,350,118,514,796,8,577,629,358,994,13,332,963,974,105,55,953,853,351,873,892,425,778,945,105,105,343,312,728,435,246,512,134,278,654,957,934,443,248,737,179,158,608,802,110,279,459,994,245,293,593,165,940,985,893,940,434,552,374,311,0,608,843,904,172,92,803,26,607,102,635,576,88,895,565,859,973,166,627,421,240,208,193,77,708,160,174,817,909,827,136,66,610,146,790,21,551,587,596,432,377,911,907,173,352,755,68,886,983", +"753,246,266,650,702,877,35,504,103,980,983,281,413,997,125,122,954,81,854,620,174,14,393,831,554,782,634,181,523,385,585,523,564,58,786,17,320,441,847,578,470,143,1,667,814,683,930,124,121,247,273,822,914,360,508,16,734,322,172,776,605,347,777,245,710,129,196,541,485,97,246,78,55,304,659,917,542,507,707,953,395,844,677,321,696,917,512,333,185,411,118,474,264,600,359,898,612,924,647,617,675,77,683,589,745,55,393,954,296,309,409,22,594,440,389,770,898,551,208,601,255,61,770,201,511,835,577,589,77,193,741,317,781,521,755,416,335,661,2,555,70,404,693,293,812,561,636,751,243,362,114,612,127,334,657,721,828,714,801,901,886,335,703,993,976,363,484,845,633,239,192,580,599,922,861,839,634,631,293,84,616,969,936,91,470,705,25,250,657,817,426,29,974,266,226,197,695,101,456,619,7,895,126,422,747,736,951,784,309,57,20,207,898,944,724,374,290,474,686,642,68,10,889,326,151,692,811,853,192,204,859,774,577,628,449,367,264,146,905,731,659,401,530,793,62,577,597,755,837,843,317,635,386,8,284,424,27,513,477,318,128,621,422,83,568,47,562,359,397,137,81,953,554,162,719,387,382,278,707,89,186,593,514,525,59,56,443,582,862,925,675,924,461,779,515,522,344,846,461,997,152,990,489,804,345,208,464,752,169,579,556,395,456,429,906,170,714,589,37,918,72,248,587,264,388,882,178,569,734,514,805,293,484,939,296,954,16,813,392,929,887,945,748,624,827,790,489,31,985,135,560,758,968,17,161,952,678,839,792,720,85,168,886,517,592,99,418,432,709,898,942,473,778,18,40,419,302,116,53,35,493,286,664,901,379,313,63,782,481,30,788,236,923,875,521,5,239,470,894,471,634,943,918,128,31,809,702,655,917,782,541,931,745,863,291,764,692,994,684,217,639,128,825,522,356,391,154,799,605,921,141,357,854,776,93,607,597,754,992,218,306,64,294,12,160,888,319,557,33,135,570,94,762,311,310,106,455,181,66,356,199,303,895,389,402,745,678,703,662,22,903,528,943,533,74,994,986,938,322,473,58,12,968,476,859,803,635,90,110,151,544,717,590,203,455,512,293,445,729,123,801,671,892,772,171,38,224,855,612,28,189,974,223,472,172,733,839,485,353,722,833,988,471,361,831,753,183,94,336,871,940,110,488,871,470,112,286,347,878,139,630,338,228,928,545,977,87,277,629,120,511,848,97,672,882,407,386,442,683,579,695,586,375,950,143,315,575,216,466,738,261,361,761,670,69,434,433,202,711,730,535,331,638,751,579,9,532,67,292,161,914,575,34,197,218,327,309,945,669,604,124,427,462,610,592,433,237,567,924,297,800,721,481,731,759,420,198,222,43,522,852,751,419,885,806,259,537,595,872,599,81,50,893,536,968,603,291,296,247,902,182,598,946,262,61,313,635,830,902,958,976,137,439,850,719,19,381,704,377,933,714,276,449,979,15,356,170,727,708,966,391,955,283,824,463,233,997,872,765,534,720,931,160,526,593,522,976,745,901,364,498,226,888,427,258,939,697,119,508,690,276,282,111,749,532,463,927,425,212,620,713,441,760,943,656,527,27,338,688,310,823,300,420,215,785,399,493,782,328,785,94,8,215,900,527,623,812,776,752,818,388,82,940,429,543,395,166,93,234,517,808,603,728,738,62,798,720,70,458,977,357,658,716,910,783,900,604,125,18,495,847,203,18,443,316,425,714,951,256,816,601,203,468,377,753,607,114,768,97,247,490,27,880,649,271,448,635,81,216,397,325,889,727,371,710,208,244,517,637,367,784,973,401,628,172,611,513,553,526,16,861,374,94,206,666,214,654,270,797,84,553,977,201,191,533,897,965,209,706,338,116,106,102,418,84,578,741,750,327,961,531,565,167,191,117,27,770,667,527,41,550,437,37,24,593,104,641,798,559,837,138,228,513,159,473,451,369,450,59,892,7,691,421,953,734,362,38,286,179,960,837,281,321,119,195,942,164,997,166,822,59,578,668,971,171,574,769,684,810,263,404,595,436,138,428,258,669,840,93,403,113,910,755,526,74,14,253,130,717,241,700,572,209,704,122,478,893,835,177,510,757,532,580,354,955,790,473,157,216,156,172,608,0,118,772,562,167,574,15,841,696,520,98,647,712,238,886,289,478,627,99,69,193,220,745,662,685,145,220,13,63,484,999,458,943,617,384,995,662,353,604,895,562,502,631,722,662,688,45,251", +"257,782,88,489,158,162,707,455,362,212,411,359,590,28,869,168,94,303,483,643,709,309,556,516,874,715,807,764,748,290,146,969,992,94,221,186,95,728,175,643,508,802,386,798,914,581,853,924,469,701,420,550,516,649,916,376,520,295,850,319,431,786,606,79,813,289,237,771,918,8,518,262,724,316,441,684,830,769,651,436,665,494,362,829,894,237,933,474,446,282,229,141,394,300,172,507,641,439,804,632,321,415,866,650,479,65,249,324,606,327,708,725,568,71,156,711,156,141,69,35,964,443,292,999,393,65,387,989,774,84,772,769,884,610,894,142,421,80,936,265,279,62,602,577,551,294,557,931,947,35,418,716,182,998,841,572,623,211,395,796,210,804,205,875,992,443,852,593,850,534,581,845,464,654,359,25,239,737,413,104,924,891,880,613,568,701,283,162,459,676,548,847,763,751,146,787,9,961,868,305,630,457,388,523,770,704,720,524,385,112,407,759,883,606,111,399,162,257,914,545,91,413,458,879,886,43,589,484,868,759,952,691,640,3,39,274,695,474,597,68,513,821,149,21,413,442,94,662,30,262,938,598,63,377,404,84,465,339,381,50,566,890,612,477,847,460,579,362,994,719,823,32,853,684,402,498,329,339,728,883,157,58,80,921,683,192,362,168,557,508,167,121,592,770,618,19,205,402,105,783,156,103,658,909,485,990,1,513,136,635,501,136,488,20,597,460,245,823,78,209,410,419,639,742,366,822,399,694,965,812,490,605,305,635,415,577,868,964,781,670,351,996,344,749,884,693,989,846,874,54,371,533,394,998,884,533,365,590,941,297,981,298,291,746,379,742,847,120,524,751,738,140,347,502,881,798,459,116,81,442,119,54,790,17,798,885,852,328,449,821,515,320,585,150,656,598,991,165,955,612,466,590,842,524,597,52,294,753,719,632,178,934,813,251,249,717,21,875,412,426,171,48,716,696,61,727,343,513,928,679,591,924,180,875,296,270,903,445,83,695,187,244,452,104,635,791,805,973,607,868,778,452,294,198,905,223,929,451,58,596,91,383,659,500,862,460,959,467,164,837,26,827,348,193,649,294,834,813,473,169,392,994,656,777,191,33,1,37,974,709,330,686,334,17,550,26,548,455,336,669,176,197,471,195,630,660,247,411,448,935,51,336,189,695,435,370,39,14,336,417,874,544,755,560,982,175,818,347,617,944,38,947,177,142,412,428,335,214,786,197,231,80,758,21,523,229,249,386,756,17,197,865,857,730,185,541,862,377,589,553,318,272,766,814,782,685,497,671,257,491,529,779,996,382,255,69,141,323,153,583,961,283,878,982,177,759,911,830,115,697,698,521,480,503,159,64,639,551,790,596,437,270,534,107,929,346,416,783,504,260,823,143,141,252,104,895,747,621,473,37,275,297,326,443,758,997,35,13,203,454,797,620,966,363,91,377,123,724,718,706,89,549,819,230,338,58,563,331,450,934,229,997,614,110,545,348,264,961,959,248,515,445,336,898,989,275,321,296,141,665,209,777,754,357,608,901,324,291,600,870,786,700,102,532,16,788,236,834,13,202,417,45,702,996,308,144,294,563,221,916,676,942,40,102,584,154,779,933,747,85,812,684,152,865,523,10,271,756,945,236,688,677,441,415,819,743,442,243,929,870,884,440,669,333,281,147,806,842,902,401,672,934,532,572,450,921,689,161,10,429,316,513,969,658,521,709,946,901,931,916,93,294,905,255,22,685,977,297,209,295,212,944,30,602,382,886,371,297,551,46,420,51,963,942,129,878,528,411,480,826,715,766,68,997,474,524,849,716,742,567,351,789,388,531,375,278,823,550,68,187,438,437,187,953,313,543,352,505,177,647,312,282,680,65,512,16,672,400,285,962,223,841,965,644,796,88,514,273,906,524,366,417,53,850,407,944,958,172,199,796,154,46,384,550,957,886,424,957,809,543,778,613,353,465,945,539,761,516,516,352,352,504,147,470,563,895,69,86,430,899,703,677,58,453,616,555,824,182,161,859,850,640,145,277,722,988,385,107,485,16,51,603,733,655,512,703,571,395,477,576,716,470,785,469,670,63,533,853,290,272,39,694,413,511,624,117,96,224,757,650,211,903,224,227,808,302,946,97,247,15,524,146,101,316,473,70,69,519,212,491,602,843,118,0,939,867,708,417,389,993,434,735,264,621,433,808,149,174,669,970,828,942,814,891,542,223,262,420,554,191,43,945,204,76,704,178,963,315,527,134,539,431,409,828,926,627,552,239,172,561", +"766,244,141,804,19,417,982,941,311,943,6,819,278,187,910,139,759,303,105,793,796,643,621,959,623,904,115,871,398,920,745,587,421,996,798,373,477,259,172,217,289,530,501,899,520,444,797,959,676,849,895,692,250,170,355,887,966,825,605,132,92,613,692,568,111,758,229,93,125,858,616,790,232,733,349,960,371,617,442,475,171,824,501,222,394,924,932,454,393,188,484,455,445,58,868,632,737,946,45,180,741,681,673,389,333,638,394,672,982,480,456,237,61,810,360,283,643,959,649,923,469,337,278,297,963,38,423,170,655,399,765,418,849,894,289,684,61,647,970,639,28,628,552,857,19,728,400,271,222,105,53,714,272,746,674,406,518,740,290,507,701,179,767,875,243,885,616,312,602,328,326,715,972,255,404,788,453,427,852,859,841,191,809,299,443,975,742,442,38,555,666,722,43,328,361,124,295,828,326,168,538,572,845,758,199,566,860,177,537,192,378,281,988,767,798,403,894,204,787,521,151,738,49,853,985,27,653,81,164,714,223,47,551,693,141,381,158,747,443,60,872,1,783,517,559,215,240,592,853,383,703,542,338,110,800,589,315,892,595,717,866,360,395,256,816,717,68,137,830,900,989,74,121,708,696,549,730,425,313,674,364,978,468,438,378,423,63,557,229,126,726,287,889,376,102,630,708,906,359,962,789,377,881,899,240,378,423,184,965,430,676,882,343,782,926,484,225,382,133,245,495,387,456,536,502,181,376,944,960,781,56,881,988,565,355,56,111,592,262,577,180,76,736,284,926,780,722,54,600,17,497,971,802,807,646,295,43,537,722,747,407,805,595,224,359,230,762,795,59,724,330,452,418,604,747,390,374,597,57,672,876,534,983,925,110,183,223,83,319,170,454,580,678,767,670,206,43,282,942,444,23,288,410,675,952,754,27,717,494,211,409,596,428,967,394,182,60,36,927,213,224,683,158,223,782,616,549,848,997,475,617,996,183,102,268,796,402,177,193,343,127,756,446,887,730,483,621,819,572,641,564,703,707,672,753,778,651,358,339,463,76,746,188,657,879,119,91,725,175,944,698,184,81,460,713,281,852,64,590,206,596,184,697,289,743,528,591,290,314,111,632,667,809,961,904,784,804,778,288,792,297,21,598,109,706,513,62,789,195,104,895,598,405,307,312,797,200,35,446,176,163,405,635,284,675,654,177,30,161,656,338,573,33,270,186,800,570,327,151,394,838,821,957,395,84,763,129,107,416,86,162,76,690,229,349,525,123,228,757,524,219,185,915,30,67,756,141,173,242,583,677,783,750,432,238,621,164,380,876,445,972,821,940,834,285,976,19,201,933,349,608,844,111,706,397,676,365,877,579,4,537,425,386,705,305,113,177,968,373,736,270,88,221,600,181,926,692,801,502,128,802,715,215,161,131,587,956,656,803,239,778,858,554,790,207,714,298,538,254,873,38,638,65,278,107,691,975,261,719,116,862,220,775,233,27,990,25,14,19,336,294,277,483,401,1000,487,529,595,211,217,475,262,347,691,211,571,315,504,143,687,848,283,879,384,533,606,24,880,903,936,444,868,917,387,86,753,63,558,634,482,539,243,965,476,47,403,415,523,952,366,405,882,980,377,316,268,469,751,330,24,620,116,591,625,619,866,658,787,287,603,298,751,785,890,242,349,253,211,984,420,526,895,996,563,455,342,792,869,603,680,172,195,374,25,19,218,697,930,934,488,282,15,126,285,517,836,751,496,607,245,426,507,929,285,222,536,64,162,83,716,500,203,113,922,499,883,381,281,529,734,554,968,899,945,559,491,642,538,713,271,827,488,690,430,752,372,650,869,481,275,453,755,909,124,48,119,38,477,749,914,845,55,782,724,413,883,201,553,80,835,266,54,449,833,662,692,921,465,524,350,792,505,307,868,256,320,814,339,562,623,135,202,467,579,501,86,646,966,163,84,530,933,35,150,230,262,460,715,782,171,607,538,771,14,698,176,970,616,237,413,81,269,557,875,506,347,749,917,610,974,859,383,197,735,571,938,570,980,452,566,611,857,336,142,225,432,917,759,174,616,458,74,136,997,30,858,696,888,962,288,388,588,958,615,355,614,918,780,429,599,361,834,727,943,91,760,424,457,738,429,642,645,120,47,308,953,779,58,635,90,140,904,772,939,0,610,213,895,578,285,824,400,857,868,259,601,515,915,336,428,200,521,870,899,457,343,137,799,107,364,408,396,825,673,375,676,589,349,597,361,883,329,841,35,897,443,315,3,24,990", +"839,810,299,157,960,608,780,844,27,275,276,288,862,817,619,602,880,457,631,455,248,367,760,4,614,7,738,178,618,446,949,647,90,785,286,839,383,468,388,522,698,591,829,973,2,260,628,304,104,896,408,271,158,370,101,664,546,825,927,482,525,42,770,642,860,289,529,878,382,283,656,503,76,688,497,27,825,215,795,377,966,864,293,277,806,396,797,655,291,195,744,57,892,985,560,189,938,908,581,607,516,189,621,648,876,73,200,666,594,504,664,865,31,956,327,853,371,662,98,617,777,764,650,332,521,149,183,153,396,708,990,161,816,22,330,900,803,93,271,19,764,570,768,550,167,377,396,343,921,441,809,827,650,104,198,194,605,899,984,512,63,138,935,603,555,248,396,523,917,724,62,629,870,514,560,696,469,607,21,42,571,966,671,940,896,867,949,845,284,320,127,172,897,75,860,642,166,871,69,79,292,578,513,41,16,636,508,708,295,233,126,890,173,633,101,822,171,29,103,771,332,899,432,559,815,958,289,353,339,476,757,167,613,253,487,13,596,931,783,640,451,10,508,621,64,62,396,11,955,322,908,667,463,297,352,609,755,424,445,866,563,353,800,305,52,74,587,224,939,340,545,822,690,793,276,819,564,842,815,652,207,687,34,128,914,946,835,635,354,519,92,331,403,733,260,930,614,287,955,603,99,808,117,316,543,395,566,182,966,284,172,956,935,855,14,49,164,136,37,901,428,683,691,392,568,39,977,213,207,414,170,405,789,583,599,909,187,940,905,812,955,362,736,678,207,201,28,768,662,107,296,185,351,849,995,891,233,504,777,879,714,163,63,102,916,226,148,366,33,68,905,371,927,249,958,535,446,907,658,95,630,255,576,680,517,73,498,255,420,813,309,811,39,725,357,717,416,414,240,314,766,402,181,811,705,575,864,966,858,791,752,303,816,601,833,997,912,197,413,364,354,150,634,567,588,696,230,829,414,819,443,675,66,34,636,289,57,873,119,257,399,374,729,528,390,710,294,422,640,469,862,527,297,285,113,115,652,189,396,727,566,337,987,738,474,556,184,622,622,983,79,348,275,146,52,581,189,122,598,935,530,277,594,787,427,464,526,998,372,143,581,37,384,493,57,601,921,481,231,805,989,674,662,960,925,883,714,444,509,582,201,171,885,72,41,474,790,525,500,646,354,576,722,212,384,400,604,858,431,386,852,439,131,797,964,206,442,592,533,7,768,857,872,378,218,343,267,861,835,13,14,604,798,520,240,316,263,693,406,846,690,135,57,537,180,171,793,319,132,981,676,502,298,351,784,37,585,115,128,51,706,229,170,878,30,443,897,117,287,360,27,843,174,701,978,191,860,576,169,25,425,624,360,218,573,69,403,261,218,12,171,449,270,700,23,757,150,413,107,166,89,307,724,197,219,137,264,751,559,354,748,832,495,649,453,859,801,927,429,961,358,425,54,322,324,194,421,634,176,831,650,510,838,569,438,855,821,838,337,453,15,211,178,897,684,372,175,89,747,803,779,807,191,187,858,6,997,528,575,617,250,455,833,539,676,311,785,763,376,834,224,424,467,421,235,97,800,197,874,152,750,481,685,352,591,907,774,325,448,575,608,305,181,860,770,424,713,703,345,337,581,159,809,859,268,583,139,43,235,875,556,773,379,916,421,633,964,702,323,463,676,809,891,564,669,563,74,584,43,302,450,641,272,532,554,833,934,773,230,21,940,857,341,604,985,795,310,181,603,801,290,728,253,831,809,697,511,724,803,845,764,110,271,525,752,62,772,556,766,455,56,510,988,692,778,834,153,54,340,61,863,976,300,754,362,583,18,988,154,262,50,771,851,451,468,517,772,877,214,770,664,322,942,26,404,570,886,352,694,757,29,890,693,947,446,346,635,683,748,205,5,790,352,423,990,834,491,249,317,778,833,574,499,607,624,735,174,960,366,242,448,928,501,303,435,334,37,334,682,943,618,494,923,374,152,353,646,522,371,131,595,170,500,395,436,940,989,241,522,713,458,682,485,945,969,975,889,773,815,372,238,981,205,661,182,220,666,172,797,6,897,251,884,784,793,744,546,584,80,62,333,93,566,942,55,706,974,9,460,854,433,243,471,128,90,774,551,35,900,606,480,258,957,562,455,981,258,436,847,687,20,172,562,867,610,0,450,222,635,808,640,556,324,300,55,366,914,674,694,926,341,775,278,759,647,745,609,876,474,419,822,889,320,388,179,705,410,420,55,894,613,992,361,635,747,150,711,22,403,773", +"814,48,916,259,930,215,937,857,906,307,275,43,529,778,946,131,522,379,270,631,49,945,708,948,553,620,847,758,914,614,959,493,945,880,899,57,345,105,305,991,248,613,622,82,352,786,225,184,318,228,706,4,962,696,382,594,395,893,469,779,662,175,153,59,450,478,317,158,313,149,546,846,394,60,699,151,816,587,742,674,821,626,802,256,402,706,300,784,449,114,574,98,843,879,54,814,430,767,840,57,697,494,473,825,468,769,541,552,982,194,911,624,265,381,343,187,906,899,111,694,616,187,918,550,16,124,613,523,604,332,293,466,345,672,61,464,234,141,392,77,156,917,735,40,979,290,277,256,325,602,191,848,646,327,524,516,446,858,290,180,482,917,303,320,457,153,662,397,920,104,742,235,120,969,939,546,181,119,375,146,297,497,855,790,840,68,943,417,485,922,190,449,273,284,852,577,80,27,931,505,549,227,243,506,202,240,861,176,69,457,839,462,660,263,770,190,864,760,995,151,344,198,46,419,708,160,794,854,711,203,34,859,997,812,437,382,845,436,165,569,367,113,126,366,449,184,281,988,873,827,558,279,377,212,826,188,124,809,446,994,399,888,894,800,32,598,377,644,654,170,40,799,410,574,980,214,704,560,897,37,83,372,35,368,297,695,640,535,361,10,776,418,298,389,304,856,382,369,511,368,508,932,302,498,586,266,4,298,79,76,843,14,14,869,110,142,213,278,337,339,870,851,965,723,139,999,706,379,203,492,318,445,214,863,530,139,37,158,608,665,147,977,231,15,482,414,762,440,164,924,874,485,125,798,70,428,899,797,301,263,187,89,850,303,752,766,11,460,126,265,576,201,369,71,635,946,516,877,562,361,609,417,901,235,792,602,9,477,335,638,704,586,294,720,374,617,168,865,271,135,714,748,644,386,61,513,790,328,688,534,563,265,618,480,148,782,445,541,318,97,712,330,36,134,762,924,136,284,668,5,480,273,621,52,684,274,313,718,352,84,934,141,417,313,14,912,162,890,63,649,123,555,855,632,496,612,958,515,838,448,839,924,1000,819,954,537,175,494,318,418,23,712,738,817,79,574,972,605,502,95,399,334,505,622,229,377,963,526,146,65,866,579,682,110,486,749,457,856,254,324,864,836,620,117,916,73,508,720,60,939,224,876,358,329,922,276,767,458,908,590,653,521,585,897,180,920,774,936,806,519,65,994,906,559,208,694,803,62,547,822,946,614,722,205,56,601,175,998,735,108,886,606,777,743,871,427,552,460,709,466,748,913,591,500,843,260,762,278,247,94,491,383,889,840,299,426,770,977,51,656,978,432,550,494,37,945,821,776,897,353,338,258,891,832,397,109,526,717,397,630,18,937,406,321,960,152,211,675,916,155,297,436,361,20,266,820,416,425,263,704,710,201,903,242,30,202,238,431,631,599,978,770,626,601,890,897,859,317,347,808,57,653,173,528,106,257,123,279,937,514,35,657,500,443,627,182,67,869,12,688,73,496,882,713,70,755,906,618,602,94,475,369,283,609,230,634,902,637,334,474,679,782,317,719,101,695,778,469,474,492,777,48,574,453,471,512,514,572,34,343,682,936,278,29,125,941,522,330,563,115,196,152,408,696,748,574,222,18,552,666,272,985,344,16,582,411,299,420,7,76,326,702,746,269,967,931,910,281,346,74,140,781,301,826,517,446,85,18,693,536,517,93,228,602,25,230,337,700,386,292,676,361,906,460,29,178,737,49,591,745,593,168,757,177,250,877,989,994,330,500,118,277,257,723,554,248,421,111,639,528,517,892,389,847,352,435,48,233,97,871,451,125,114,26,278,983,613,45,287,851,701,967,854,838,219,983,910,312,986,127,826,949,250,75,728,11,653,272,785,918,934,19,513,85,766,485,925,723,642,636,150,856,822,847,921,630,66,195,830,561,68,384,155,833,909,353,396,808,466,395,246,823,165,660,39,411,720,913,386,702,455,930,980,514,754,244,212,394,478,727,786,797,415,529,506,354,325,451,539,793,185,885,25,197,513,396,984,494,652,332,927,469,252,943,700,635,388,384,674,479,414,234,166,565,670,609,116,253,864,125,965,488,748,165,557,141,833,279,45,523,801,67,635,397,613,548,542,733,635,710,297,502,391,701,624,861,562,297,259,456,599,92,167,708,213,450,0,281,391,372,494,596,251,335,704,779,844,752,864,341,955,570,715,959,733,998,11,443,435,631,16,376,929,566,813,571,748,510,851,13,90,511,661,40,311,878,987,263,579,555", +"308,661,97,655,522,671,125,9,601,559,818,808,983,28,777,241,562,397,60,569,216,853,152,621,308,850,748,49,814,928,598,346,116,99,553,954,127,447,161,335,754,369,722,948,394,5,942,451,960,963,731,721,433,88,482,327,32,866,70,879,841,976,576,522,828,2,22,11,45,561,978,964,661,999,24,619,386,825,695,940,807,255,443,680,387,225,23,760,169,451,484,869,395,109,143,395,170,830,349,45,88,13,911,314,665,677,532,271,743,3,926,215,235,780,776,571,990,264,647,230,692,32,996,785,378,238,567,544,148,958,548,685,592,625,449,373,337,396,248,145,296,692,442,699,748,323,449,217,471,601,765,989,783,882,727,818,86,931,245,448,105,256,338,61,957,577,55,464,367,815,139,909,443,432,183,741,260,210,552,698,297,236,788,761,791,586,701,646,62,348,388,972,679,827,613,666,585,321,472,913,389,553,249,78,564,402,137,677,792,738,913,129,160,164,183,972,766,804,452,283,769,229,101,35,207,618,903,330,311,248,357,459,519,216,579,490,880,562,733,855,604,350,459,759,420,620,758,537,693,92,844,135,389,130,163,656,544,615,658,900,768,464,171,413,846,593,406,528,989,636,478,28,834,546,440,436,806,520,424,856,156,78,730,113,315,499,164,993,793,195,562,864,817,493,574,265,243,948,551,391,109,967,69,759,392,829,65,886,352,202,558,988,479,977,782,321,955,141,539,529,176,488,355,551,888,441,896,639,906,987,454,615,136,305,934,763,140,826,50,971,704,823,702,195,895,938,420,196,256,91,851,621,900,906,534,661,21,247,248,740,722,105,478,687,364,816,245,362,809,944,375,2,684,877,944,537,89,641,340,95,258,36,293,504,517,308,420,408,717,958,985,104,51,680,634,258,740,498,333,237,96,455,384,331,564,133,896,383,239,560,351,859,40,955,292,473,32,503,166,152,599,552,121,65,244,385,430,666,964,670,666,426,805,85,15,245,97,12,814,515,691,723,934,711,848,750,510,445,811,281,450,730,377,524,718,997,386,492,390,248,136,4,712,749,597,1,902,159,299,534,750,412,707,207,344,649,471,207,526,10,242,927,797,858,251,669,388,175,575,604,850,681,586,50,600,720,276,743,356,721,349,291,128,858,349,102,896,866,96,272,990,634,691,656,677,986,688,346,778,857,870,728,247,413,711,730,405,445,204,593,989,964,55,521,547,372,384,469,856,521,63,797,250,383,83,903,367,463,761,380,80,545,59,786,961,51,394,199,826,831,441,919,498,412,64,993,507,382,350,287,490,831,222,792,342,611,752,967,825,975,624,467,673,519,217,935,662,99,556,476,102,453,278,680,159,740,150,339,365,104,128,84,462,791,413,407,6,825,718,382,456,973,418,503,627,321,697,654,571,807,414,14,123,647,208,540,659,107,423,336,907,433,777,394,410,285,122,904,327,451,429,243,757,393,130,11,281,732,270,881,645,758,480,371,826,747,634,912,238,21,713,585,47,549,88,373,572,909,612,522,174,451,689,320,414,915,435,403,580,819,785,191,920,877,418,501,229,443,547,734,964,333,454,329,769,956,304,607,485,52,871,561,886,702,717,251,906,402,22,37,31,461,437,121,667,739,211,673,982,648,610,932,298,177,557,831,888,860,904,360,907,903,333,936,246,401,921,51,514,594,163,748,960,819,421,964,170,810,127,101,152,257,222,547,843,784,801,184,163,335,736,59,454,915,923,607,769,639,135,858,602,197,770,948,461,245,517,266,301,365,907,888,66,482,344,347,192,857,85,509,938,219,190,224,945,336,415,775,266,208,905,516,322,585,704,766,451,556,370,960,817,529,783,478,866,236,904,627,573,260,28,370,460,152,315,2,282,859,352,144,894,419,348,258,905,779,278,605,774,174,700,382,107,299,29,441,262,84,367,730,218,10,947,995,890,11,667,957,794,885,92,732,616,797,479,642,580,257,419,801,518,971,592,518,374,539,177,673,433,214,986,486,944,47,278,356,898,874,128,585,960,611,869,67,705,72,497,68,433,33,413,585,8,538,849,929,777,473,554,558,79,244,558,382,947,620,533,735,935,36,288,221,395,850,441,266,92,786,461,891,367,656,958,193,113,714,843,540,971,953,1,79,387,285,549,144,926,197,485,997,787,803,574,417,895,222,281,0,218,629,178,786,890,18,355,662,421,288,78,33,907,644,233,675,789,184,94,999,301,113,274,266,528,951,835,248,17,639,359,743,640,231,176,405,730,10,952,464,771,890", +"402,585,951,193,360,160,775,792,928,378,268,69,315,694,900,390,578,887,861,284,161,582,392,300,59,639,29,901,749,532,345,214,585,923,8,200,614,432,352,987,756,584,195,833,299,542,214,339,332,625,446,481,470,870,639,608,648,921,489,891,461,976,603,235,687,408,193,423,793,659,394,175,52,655,43,191,610,144,903,54,762,762,548,899,782,513,985,783,492,938,734,349,602,629,648,236,162,676,93,978,970,850,404,844,846,692,714,280,664,964,172,843,733,425,285,402,913,851,984,500,380,370,894,251,197,173,893,233,766,785,758,907,149,167,183,604,865,367,784,234,699,968,351,183,258,948,404,169,454,616,418,299,878,40,278,589,355,658,342,910,475,244,411,340,779,574,790,286,248,13,85,789,577,439,630,210,700,837,78,637,643,131,638,382,706,146,286,853,237,770,668,500,267,522,956,73,882,607,827,369,656,645,611,603,520,769,737,426,958,372,923,594,580,142,403,815,504,608,574,293,586,460,956,958,65,93,80,784,317,928,546,260,363,135,475,949,153,531,897,700,730,196,879,237,500,701,620,345,906,919,432,42,247,127,752,754,835,526,497,365,960,506,912,280,675,181,414,762,974,226,63,476,856,302,987,455,316,871,252,197,340,163,504,129,3,347,239,443,810,883,459,185,356,836,271,51,210,164,634,503,505,677,648,844,140,940,690,723,775,904,322,255,793,99,758,495,496,387,496,740,541,278,843,952,668,853,869,221,652,195,482,498,259,967,76,739,174,265,224,278,886,376,197,390,957,369,818,200,922,660,327,281,680,99,761,633,602,489,76,585,484,703,179,710,995,272,45,904,290,283,427,60,937,538,187,475,435,644,181,504,395,360,509,699,936,497,400,75,385,21,40,923,274,655,380,323,746,220,581,713,124,305,871,762,699,763,681,734,793,565,189,428,49,146,538,244,337,588,261,502,990,554,16,116,288,183,205,206,560,112,733,355,905,640,141,761,187,596,416,597,809,328,332,453,688,290,250,367,100,467,863,631,617,545,504,699,13,782,267,332,46,301,574,780,144,106,724,348,914,136,228,1000,85,498,37,91,695,182,338,809,445,565,761,864,205,222,306,855,632,597,542,61,352,410,673,46,663,606,675,969,741,241,238,935,348,981,529,571,1,685,462,424,803,286,266,211,618,897,406,18,391,854,890,767,151,613,237,157,919,677,969,91,635,535,3,708,653,594,436,723,463,299,873,697,131,257,144,439,713,913,467,20,69,119,333,436,896,575,552,489,506,337,985,207,154,501,508,68,668,988,532,340,302,453,142,457,600,812,652,553,284,385,385,836,465,828,669,456,512,710,517,470,278,819,631,164,247,821,314,410,508,879,986,612,925,655,821,723,587,681,459,752,277,506,636,900,180,25,567,692,368,734,781,550,638,765,824,716,820,520,989,657,70,397,575,72,488,589,67,529,969,528,295,80,637,883,845,138,937,906,139,785,700,472,783,666,887,537,800,835,399,623,383,338,722,17,614,532,982,511,159,725,541,441,117,789,130,78,529,818,655,534,819,948,979,396,988,310,331,719,533,192,912,136,818,578,210,158,853,429,808,211,815,289,493,51,586,189,62,838,781,567,901,623,216,213,73,47,70,872,555,632,577,345,887,501,615,616,919,358,383,25,234,177,346,230,322,726,162,317,708,29,526,877,946,794,39,218,361,983,363,772,489,166,563,238,901,885,276,574,535,551,178,172,78,410,603,749,803,292,687,128,270,650,355,34,534,427,11,604,514,172,927,503,427,92,392,53,482,606,652,828,520,631,610,662,376,925,11,645,544,795,732,677,177,788,723,63,914,130,92,221,185,127,321,656,674,275,221,484,277,83,323,601,645,725,816,764,741,593,157,343,131,909,490,794,996,965,831,557,303,344,661,312,349,915,927,620,794,922,445,822,862,656,862,420,63,990,714,858,66,43,830,951,316,929,687,244,379,707,400,454,778,474,544,818,716,458,878,4,899,596,982,949,492,797,77,925,298,167,198,803,627,177,356,294,865,360,501,285,906,547,488,380,732,695,97,1000,317,209,652,72,536,818,349,893,13,799,85,66,982,171,368,853,813,134,22,834,51,504,484,796,11,60,8,835,962,425,484,364,659,341,375,110,142,618,832,460,514,360,575,26,15,389,578,635,391,218,0,969,906,849,980,520,575,430,306,634,92,496,410,218,427,691,777,372,334,208,771,71,117,880,388,278,849,501,614,827,879,965,867,356,542,407,959,455,182,971,673,581", +"528,135,306,882,459,235,48,736,266,854,916,693,457,819,261,286,874,129,625,638,101,572,201,559,343,244,941,233,114,80,702,793,798,489,695,157,921,674,190,80,867,115,955,288,542,582,269,638,500,320,579,568,940,66,66,722,75,234,292,184,744,374,349,140,157,299,40,86,69,648,913,444,970,35,560,974,960,511,443,351,146,593,909,759,200,655,581,20,732,555,169,544,274,320,616,580,813,774,653,593,395,5,141,601,345,165,45,892,487,255,890,292,881,625,362,73,367,485,802,379,122,565,596,357,327,192,103,761,484,738,667,691,468,296,951,70,809,691,499,794,442,448,783,898,436,983,118,756,434,197,62,935,380,281,221,988,213,789,34,451,382,286,528,165,271,143,71,290,335,662,34,406,991,551,850,456,720,196,143,927,43,605,307,524,663,770,189,679,593,9,132,464,332,543,856,575,370,417,214,159,164,137,238,552,912,784,220,299,628,513,814,670,640,253,730,601,105,4,921,218,158,353,659,259,482,786,879,746,974,331,179,519,760,514,643,254,875,429,423,855,251,619,193,937,56,386,324,264,405,61,699,820,335,945,99,77,190,35,608,493,607,1000,164,914,231,343,381,600,272,52,162,438,257,132,453,563,473,720,282,996,851,915,452,370,442,71,133,156,398,347,591,30,359,915,200,313,237,722,441,131,923,875,546,217,982,592,151,683,142,515,902,101,506,351,316,801,626,911,595,309,9,751,599,662,702,366,865,270,324,104,596,132,548,241,749,309,488,133,303,557,672,491,826,961,666,64,890,71,134,912,502,715,514,73,783,538,299,504,155,115,903,216,472,767,92,784,960,119,720,487,678,42,316,130,979,887,911,432,29,156,931,572,371,812,609,195,586,654,398,755,318,918,527,29,274,948,303,654,327,298,947,311,48,471,514,899,111,952,413,456,688,913,771,274,467,678,642,990,164,252,502,654,785,895,295,869,686,492,366,998,393,87,139,494,834,246,365,374,628,713,248,358,846,986,676,667,369,572,623,833,842,892,527,208,34,280,40,702,508,589,457,626,603,223,457,688,873,515,8,569,325,567,615,216,655,357,666,469,739,782,390,230,981,309,322,805,144,444,496,129,236,792,108,278,46,589,352,591,284,315,61,477,198,474,732,973,674,893,489,170,741,438,99,751,120,238,673,97,535,237,359,954,728,848,520,84,86,420,755,107,222,701,45,987,360,124,61,895,701,242,457,861,965,960,456,399,71,287,215,772,168,543,351,333,745,468,80,40,881,628,776,345,112,834,533,93,326,576,909,217,285,726,652,779,471,823,411,922,329,892,271,569,364,974,424,416,302,305,672,678,543,442,642,794,680,539,694,661,291,432,391,879,530,238,459,996,71,272,478,798,769,53,791,319,792,524,561,557,213,698,651,479,581,922,844,826,441,729,696,307,717,765,674,134,236,933,952,874,966,298,227,176,37,258,302,925,734,117,664,331,95,93,76,337,918,66,480,296,448,556,740,369,748,181,455,303,953,336,90,869,464,245,853,178,617,454,748,460,270,95,899,531,432,356,716,108,977,656,982,428,891,30,681,26,244,47,388,47,328,519,716,133,784,171,252,310,948,538,870,751,435,41,461,493,449,727,97,155,202,325,489,25,490,782,999,476,603,330,847,103,614,635,591,301,503,995,922,449,652,734,420,192,664,296,170,251,706,638,649,115,104,869,702,899,781,784,714,467,222,273,131,949,764,18,945,771,641,376,812,834,779,525,227,133,549,981,723,887,148,725,346,499,344,614,360,753,901,620,935,471,604,826,611,948,452,348,500,631,448,491,373,816,704,739,513,458,975,770,565,622,248,686,968,245,410,934,962,144,426,396,920,217,606,364,30,550,250,467,249,962,605,758,571,838,721,317,553,646,604,14,745,214,36,2,595,808,995,57,903,306,557,242,699,575,322,562,318,632,628,686,919,281,777,956,641,519,568,251,479,469,911,554,23,902,364,963,377,821,331,44,926,648,773,184,501,303,208,117,189,40,591,588,301,322,642,633,418,649,799,813,564,951,929,284,223,955,126,897,817,668,848,367,330,449,409,770,701,122,418,338,929,103,583,846,187,864,567,697,151,219,992,221,326,34,935,14,355,333,81,852,398,117,829,248,23,643,529,345,736,378,471,607,841,993,285,808,372,629,969,0,695,986,365,205,858,142,378,180,61,547,395,89,588,612,493,137,720,986,5,216,982,718,254,884,214,217,751,343,129,110,572,473,562,826,674,920,917,744,743,632", +"912,99,220,169,142,332,912,13,228,294,845,208,644,677,620,112,610,751,247,124,127,745,384,845,539,136,712,96,539,789,747,675,514,468,854,377,69,171,707,9,526,651,9,811,487,5,326,986,476,112,517,140,642,735,55,495,565,371,839,798,619,414,857,201,920,170,864,983,725,910,34,613,233,983,710,302,887,666,227,734,876,58,467,918,855,289,341,180,846,987,668,352,360,174,917,53,970,817,642,482,19,548,238,34,985,276,992,242,620,528,403,82,484,711,980,603,966,754,780,62,537,475,632,739,937,128,761,35,180,255,390,869,534,186,975,136,47,33,533,668,870,166,795,180,638,801,334,577,170,853,444,748,871,908,265,668,444,342,47,931,676,850,697,614,917,311,428,693,448,910,949,947,704,312,653,750,511,661,529,355,763,964,795,891,48,446,214,961,153,929,391,95,429,953,46,679,736,658,298,883,788,847,410,947,316,567,324,732,569,743,643,748,543,836,650,995,617,428,191,329,28,97,630,474,673,124,16,382,112,434,127,372,990,292,656,224,110,242,660,597,954,550,686,703,657,585,67,483,241,875,852,749,187,392,678,625,801,379,821,390,175,974,555,664,850,711,941,59,681,743,405,220,142,814,453,172,772,916,800,553,517,680,686,654,387,534,833,864,783,899,897,69,893,833,893,372,207,329,39,409,970,657,202,652,234,148,775,223,744,617,358,390,902,275,566,763,534,850,714,600,744,680,916,933,723,571,140,928,65,43,239,792,207,701,496,300,6,781,235,349,336,965,682,24,465,66,826,500,508,365,563,639,928,267,889,884,62,987,125,699,185,169,245,897,241,673,452,374,2,571,95,19,639,529,374,530,867,923,620,532,29,816,524,918,557,798,576,575,254,387,596,7,224,883,957,517,95,329,255,175,243,94,565,667,38,78,508,80,579,291,410,987,525,92,65,550,597,294,657,820,815,493,606,685,988,22,309,845,363,617,742,149,582,320,107,364,503,601,527,682,21,493,324,845,940,49,828,744,214,343,695,890,286,801,307,537,480,843,306,645,453,836,201,335,139,263,488,560,953,728,255,361,183,524,854,394,284,257,962,328,733,727,156,680,124,90,822,889,401,97,955,502,929,700,519,359,296,474,19,928,792,76,599,196,704,26,482,814,421,544,248,477,311,70,421,510,568,538,692,422,127,868,611,986,610,786,909,434,237,959,903,151,154,646,81,51,558,9,190,180,808,387,437,31,748,682,913,929,285,887,985,562,833,420,369,391,327,884,652,770,671,303,246,349,891,717,903,509,586,902,316,832,431,640,919,709,677,391,673,947,319,101,159,323,210,580,693,435,397,717,949,943,418,855,907,340,195,919,383,861,812,628,257,708,45,415,316,885,390,862,888,579,157,836,544,717,761,918,386,323,117,591,761,857,244,761,861,734,504,764,563,310,689,533,844,494,792,377,290,938,971,389,811,966,722,262,90,301,271,561,953,381,337,231,406,13,330,39,600,626,946,497,921,889,384,348,268,185,239,565,887,174,38,502,195,217,746,462,427,316,890,148,801,45,618,292,319,813,153,616,849,461,316,576,617,404,41,909,988,345,950,96,88,194,214,897,514,492,265,879,951,763,619,256,145,13,346,907,863,804,963,485,679,657,570,434,725,518,588,29,582,358,638,684,278,793,568,584,816,821,235,311,113,968,411,88,335,71,64,636,938,642,268,473,447,70,606,964,732,780,338,784,748,679,464,646,176,425,825,212,823,627,679,567,797,284,353,375,317,969,340,334,296,722,717,696,162,89,212,728,774,62,335,762,238,728,839,242,928,39,812,633,714,927,847,517,647,686,719,813,430,366,207,675,159,313,158,377,350,217,196,821,684,872,663,385,178,687,903,59,727,106,11,214,493,810,807,105,149,387,344,775,945,528,724,673,160,423,152,913,10,800,86,923,734,595,776,409,290,236,838,944,111,530,442,858,527,814,802,993,109,618,337,85,784,936,851,854,525,830,749,462,554,623,799,58,671,80,593,182,864,521,909,193,65,569,976,769,552,413,508,504,358,343,132,47,403,140,489,850,134,78,871,879,406,817,979,864,697,556,700,515,336,819,575,54,121,763,138,537,39,970,48,629,87,754,356,571,178,221,474,628,766,871,516,213,72,494,491,708,289,102,696,434,824,640,494,178,906,695,0,429,869,958,546,509,461,86,225,610,690,605,107,352,158,895,158,894,275,35,644,605,260,638,156,377,798,502,118,393,429,67,207,263,740,93,826,630,195,883", +"260,321,434,220,19,30,516,397,148,998,821,488,403,115,973,676,232,383,222,296,508,866,613,41,294,448,723,213,955,604,32,447,854,802,554,554,173,267,422,979,550,887,154,491,282,308,816,798,636,376,700,676,521,568,425,225,817,109,759,256,516,905,419,279,923,123,854,861,31,681,686,32,722,63,895,179,876,422,714,345,102,24,884,187,177,887,120,345,621,347,323,435,923,444,277,357,903,445,276,774,582,292,979,325,219,614,440,474,265,287,547,637,282,94,532,923,347,524,975,661,709,823,121,363,759,466,867,227,928,485,481,389,408,370,572,173,725,360,639,37,288,234,901,149,805,826,393,957,417,211,709,894,477,897,224,615,686,381,21,377,828,178,426,472,467,33,212,56,869,760,377,272,517,983,120,637,960,645,213,229,342,837,764,615,214,880,657,139,105,77,141,638,677,207,421,231,522,934,950,620,249,173,447,377,108,98,465,960,906,178,251,217,414,368,71,926,261,240,785,319,224,241,462,889,830,290,737,101,676,867,790,411,899,448,432,75,200,25,725,995,657,40,863,324,842,559,95,448,361,714,238,605,637,247,155,268,192,688,358,303,127,454,528,313,566,314,157,682,350,718,282,419,646,214,140,253,52,364,294,174,474,401,60,238,124,394,733,521,709,950,678,276,855,738,932,468,168,574,202,99,234,802,412,42,711,896,474,223,441,782,62,550,516,990,84,699,898,374,169,69,669,566,671,520,647,118,360,730,851,12,690,439,857,105,640,417,128,645,397,171,747,617,878,452,640,146,485,235,686,630,329,629,634,245,433,913,407,208,751,875,319,865,568,118,977,738,513,968,936,980,977,993,437,844,348,879,618,615,623,310,443,88,672,508,651,398,743,624,224,479,435,942,373,332,107,138,28,794,946,27,336,828,904,300,216,810,484,30,492,106,802,52,500,405,190,171,920,817,687,954,633,42,902,311,631,599,162,734,862,153,736,666,472,56,853,618,307,570,758,737,52,225,580,915,284,648,866,25,424,15,90,19,118,700,676,573,617,307,216,849,36,915,320,106,771,616,159,642,130,29,726,907,582,567,70,397,585,34,201,759,373,871,817,416,30,606,789,761,822,193,603,529,303,618,508,468,205,493,922,910,801,814,54,967,378,829,329,74,764,193,688,816,354,79,443,219,455,621,740,90,849,667,271,168,554,816,209,790,57,657,556,977,936,116,448,695,808,988,697,44,200,338,320,689,816,633,95,149,34,24,296,196,851,686,792,451,990,842,663,226,344,169,280,630,658,211,13,273,734,726,99,967,202,101,957,116,183,425,408,32,380,199,613,165,839,238,468,675,993,631,276,902,245,830,102,357,378,120,471,659,545,596,292,634,903,736,69,215,166,779,940,604,733,400,431,849,275,611,974,670,713,377,486,382,626,399,537,181,958,485,986,376,885,375,101,646,541,862,705,883,90,367,24,271,11,179,713,153,753,292,286,175,36,26,880,324,873,632,532,906,644,980,99,175,950,74,211,107,51,526,742,627,11,937,701,110,200,313,610,327,942,632,721,441,951,945,60,304,615,886,55,918,227,52,247,878,504,532,10,673,320,523,904,186,558,759,971,916,788,824,667,259,310,710,706,116,501,649,283,415,269,719,444,852,938,124,897,787,254,144,114,776,306,615,853,901,443,106,355,958,737,187,714,872,179,935,288,639,213,266,472,503,275,958,34,670,93,9,15,192,795,999,83,30,566,928,940,787,838,762,322,301,242,88,196,639,166,775,185,526,488,815,936,517,331,26,715,439,779,378,544,563,14,81,563,701,938,185,967,50,922,558,772,151,661,490,929,618,942,545,653,133,726,693,97,720,618,249,946,825,367,20,411,83,595,883,645,349,67,465,455,817,450,261,120,432,850,608,250,512,360,657,543,722,982,135,692,988,907,296,4,188,8,113,639,947,483,998,160,716,365,500,837,552,528,256,360,950,597,293,892,389,512,321,987,278,150,70,285,507,658,937,673,655,128,770,314,180,160,162,849,145,757,293,181,652,405,276,795,410,370,557,884,350,614,336,440,992,7,330,498,658,953,595,137,834,350,15,85,994,473,195,75,359,541,807,37,492,979,229,51,791,137,673,780,483,417,676,881,755,876,182,979,110,292,62,633,22,122,337,388,635,520,735,400,556,596,786,849,986,429,0,403,985,671,320,823,676,167,631,754,408,491,57,126,581,171,115,226,256,681,60,550,258,65,368,628,459,349,158,69,619,871,964,997,52,308,776,927,992", +"754,450,419,309,826,472,36,207,260,990,164,705,974,499,202,560,255,288,239,381,102,104,883,744,412,186,31,878,564,952,955,782,774,711,829,730,419,686,369,415,308,600,776,288,921,25,272,592,293,124,477,817,418,821,472,493,24,889,956,256,824,652,799,797,280,838,391,566,156,600,986,186,535,186,5,221,654,203,682,255,85,167,818,669,373,993,680,15,717,908,484,78,619,284,222,958,772,976,732,200,421,302,379,501,613,801,191,754,294,290,62,47,78,257,136,380,655,794,591,343,638,557,723,150,501,796,654,464,81,687,679,514,279,133,855,940,276,366,198,742,76,344,441,618,502,624,881,421,725,71,706,994,133,154,406,951,577,438,544,487,683,652,911,630,135,517,13,968,345,519,216,788,20,487,652,302,539,806,92,721,982,430,556,832,245,903,780,210,906,206,680,671,149,967,356,723,633,981,297,743,590,38,706,840,296,445,587,815,815,806,169,764,71,491,928,254,972,440,454,988,278,739,194,728,126,501,553,931,330,622,540,734,872,664,5,785,211,514,261,924,618,663,819,169,374,672,844,277,681,16,988,741,664,972,653,779,766,854,782,144,545,901,756,3,84,948,927,452,455,510,662,318,656,874,991,732,838,765,619,848,367,142,251,275,648,832,423,26,732,45,667,119,312,578,818,278,114,486,670,378,9,248,683,518,425,257,161,456,514,819,821,322,873,480,103,693,524,969,508,785,716,730,653,18,620,659,145,921,926,12,379,163,749,419,468,296,470,547,694,433,426,411,425,842,975,219,654,812,505,936,169,542,867,740,982,996,105,830,838,664,373,120,275,798,282,671,840,188,450,686,888,120,129,25,4,77,320,257,376,681,846,5,528,895,506,202,514,83,871,118,780,972,877,657,768,314,454,791,575,880,459,699,394,245,415,868,793,4,393,826,653,846,451,705,213,251,588,31,988,231,394,697,788,218,718,346,974,512,805,617,33,60,637,29,522,796,768,850,191,229,31,730,585,765,622,228,871,262,617,986,214,434,992,162,685,2,400,363,264,528,683,173,484,191,382,873,352,349,364,550,97,961,881,302,980,632,137,585,11,265,617,756,826,25,664,68,263,149,287,429,504,788,873,80,392,606,201,477,945,713,410,695,398,996,970,429,595,954,788,812,592,760,483,110,41,591,605,598,619,122,329,68,975,818,501,701,238,582,421,32,156,646,202,395,267,142,761,650,361,224,852,277,885,467,889,390,221,301,914,5,944,325,123,186,60,91,313,239,448,492,696,690,16,267,166,578,601,389,131,574,705,790,116,229,921,455,10,828,372,898,522,802,909,610,565,18,262,91,859,164,453,227,80,590,546,738,717,678,942,62,96,360,249,173,815,388,663,598,88,691,264,272,988,633,102,462,655,41,134,219,971,138,458,539,850,856,587,673,174,774,400,592,54,210,291,505,885,753,726,333,687,702,134,249,582,12,297,994,692,782,821,106,364,655,322,974,672,300,248,153,735,718,149,491,835,150,905,368,101,168,391,991,675,437,810,391,843,218,683,713,673,163,873,843,197,216,586,303,505,419,217,741,174,973,551,229,610,689,146,675,693,872,762,252,458,250,893,694,572,328,757,798,675,37,117,387,135,750,942,797,910,330,925,522,68,516,11,209,212,525,117,326,491,546,210,217,560,176,50,754,275,336,307,48,623,468,433,50,544,249,125,336,637,797,222,438,497,778,154,84,234,269,963,455,597,62,713,315,137,970,405,884,496,392,64,817,471,50,261,407,259,624,227,942,734,666,751,227,741,101,48,520,863,410,339,976,193,86,498,101,721,598,215,757,173,331,913,787,747,15,278,62,83,732,715,707,528,359,268,898,621,969,301,980,621,65,678,320,474,93,89,978,702,341,995,712,353,140,740,838,793,598,43,485,344,31,78,619,256,285,579,624,222,10,452,603,33,418,116,886,78,20,465,892,262,550,333,735,532,255,3,867,794,116,645,332,2,961,310,325,816,832,982,317,931,179,320,170,219,739,821,896,688,976,552,252,54,948,34,678,956,483,969,435,567,65,340,88,534,936,353,571,44,500,73,835,482,588,951,753,994,565,789,274,377,112,328,49,441,713,537,425,54,532,170,345,549,160,729,534,52,409,67,146,418,926,361,637,912,551,606,576,98,264,857,324,251,890,980,365,869,403,0,63,948,7,466,549,593,114,825,18,756,762,371,857,172,820,721,455,450,287,947,421,10,61,436,472,230,456,269,720,170,595,793,295,1,916,324,38", +"367,513,183,887,580,905,409,848,199,145,599,406,667,498,798,539,977,651,272,607,694,532,674,411,101,747,88,306,511,584,55,431,256,836,41,795,538,745,324,565,263,677,111,198,587,327,249,849,804,592,26,711,123,285,861,229,482,583,405,184,268,332,486,169,146,233,735,501,992,793,239,931,963,442,829,790,135,39,220,680,282,809,644,979,761,25,417,465,241,836,709,489,225,176,656,253,444,746,19,605,699,359,434,837,388,613,958,465,261,447,423,708,394,599,710,345,87,238,76,875,721,630,210,694,695,581,709,788,958,6,100,632,704,706,453,791,981,188,91,872,720,118,519,262,332,230,860,292,308,12,671,239,165,446,864,165,314,372,433,210,500,247,310,749,531,258,29,192,117,354,848,856,743,14,215,908,265,367,65,307,763,401,163,825,829,283,825,388,35,153,859,674,171,342,465,221,319,504,866,261,214,683,988,996,509,286,573,33,512,799,778,346,877,317,600,376,774,160,414,867,322,736,200,997,521,980,225,434,42,216,668,367,457,951,968,761,753,204,479,725,444,287,427,823,715,274,862,215,124,857,94,430,758,533,176,942,724,576,453,308,612,927,887,132,290,83,471,232,685,401,597,270,516,532,734,476,876,495,887,112,362,236,99,132,987,252,510,825,996,372,111,227,251,48,102,793,310,74,428,18,168,979,296,531,879,634,917,938,725,880,153,592,775,675,94,239,542,856,938,693,520,606,664,187,989,489,637,185,778,105,224,483,334,821,436,265,166,903,331,336,872,715,849,921,784,336,767,258,748,651,774,673,537,229,110,527,161,121,580,913,877,576,206,265,271,589,184,223,212,240,839,680,283,168,83,481,715,504,157,431,263,706,704,433,779,772,569,228,375,445,303,81,160,774,585,398,28,500,209,569,315,16,127,680,142,862,163,247,315,552,907,204,55,781,595,431,207,258,603,695,92,502,644,211,384,979,589,423,230,382,766,591,910,790,36,850,807,875,971,126,379,302,925,565,831,924,907,333,787,226,554,239,751,762,497,671,512,246,200,155,507,627,534,188,530,461,39,531,135,50,606,236,354,298,518,265,951,198,247,729,606,374,381,421,205,299,282,271,709,400,22,618,97,413,831,940,547,370,453,108,608,249,205,281,9,818,52,512,120,502,818,58,137,374,447,344,924,898,437,72,410,309,53,944,185,823,380,324,989,184,937,293,32,489,107,198,661,99,166,288,272,84,614,538,891,35,586,83,348,952,743,302,782,32,493,564,815,42,276,494,188,585,887,212,466,389,291,274,169,765,494,584,898,94,787,670,906,438,414,233,871,35,66,325,539,663,67,775,170,354,351,342,71,599,840,539,784,635,547,232,264,453,986,867,123,436,682,103,140,754,970,17,265,720,327,537,428,100,615,839,679,223,774,839,835,957,276,378,491,797,669,820,339,208,963,668,703,340,447,638,199,667,639,349,877,322,243,187,750,190,642,937,184,733,240,737,899,999,589,679,9,77,208,918,515,321,146,247,118,603,960,124,395,546,310,162,41,516,214,571,798,291,488,839,447,521,219,31,900,331,398,916,637,783,828,973,838,202,516,690,623,460,378,513,671,897,561,48,184,978,798,379,285,124,685,102,2,11,555,642,916,264,308,789,224,660,945,141,435,720,754,525,431,359,854,321,817,380,771,107,678,691,345,410,370,591,593,115,923,30,679,156,122,859,179,267,94,863,193,498,155,371,471,103,481,559,688,527,390,199,918,884,293,204,811,288,492,683,657,634,482,898,684,750,72,740,455,323,318,515,423,669,5,222,958,328,788,864,954,952,168,555,452,773,692,892,708,159,186,628,999,334,723,483,469,519,20,885,83,759,251,515,86,17,847,459,534,233,802,648,186,424,671,293,279,685,15,218,577,815,402,931,262,814,337,574,567,25,230,820,639,943,763,968,152,749,803,850,312,737,269,955,706,973,239,463,840,692,616,12,49,149,562,22,561,46,146,160,670,774,717,79,419,584,627,303,830,322,331,283,883,454,431,652,742,878,849,159,339,237,364,326,975,694,721,408,644,862,983,218,436,466,816,175,989,259,366,9,339,369,281,49,653,176,445,41,27,783,688,939,519,510,876,288,341,559,330,588,210,406,921,943,660,739,984,883,753,658,22,955,786,88,647,621,868,300,335,18,520,205,958,985,63,0,630,701,805,185,560,214,532,584,53,676,591,248,488,531,466,282,943,718,922,270,557,156,676,960,413,83,408,647,283,697,472,5,259,336,974,67", +"8,70,307,270,833,503,138,49,11,654,798,56,413,969,280,693,249,600,712,440,98,265,231,593,976,885,214,2,994,94,544,105,151,571,764,770,947,947,824,531,858,655,819,727,94,226,174,144,660,207,286,296,654,515,204,58,813,171,424,109,959,688,132,879,931,47,282,687,878,573,379,523,665,319,759,238,434,234,124,513,242,119,647,900,254,816,752,758,814,227,356,606,27,168,462,947,351,330,388,195,384,792,240,812,683,992,111,772,245,857,687,129,520,478,873,578,471,62,109,924,50,822,399,878,635,74,925,717,476,559,435,17,690,123,92,715,256,531,320,72,605,173,80,438,45,879,652,719,639,744,706,542,643,829,471,465,112,407,473,945,268,485,784,649,659,242,437,325,253,46,924,209,163,276,266,280,906,882,762,479,504,607,423,485,918,715,328,895,201,154,687,584,805,713,898,620,993,394,726,581,939,374,250,126,425,799,380,540,535,821,163,99,811,530,255,821,979,993,319,971,72,724,620,308,898,526,644,963,629,212,329,176,423,4,11,258,705,96,409,560,646,371,157,647,859,608,643,934,356,934,656,683,217,167,766,19,49,819,643,950,713,891,705,511,657,879,87,630,482,762,266,881,654,577,925,435,231,665,573,654,807,597,581,192,749,911,295,245,103,976,834,727,600,768,19,249,449,87,363,298,731,842,333,79,322,329,664,830,446,248,484,201,806,536,545,958,418,312,346,819,223,725,780,991,62,843,6,618,615,885,629,249,611,224,193,952,17,498,689,196,575,960,269,690,301,993,904,728,654,161,835,409,484,594,896,551,2,220,905,31,702,419,664,76,316,653,521,116,634,478,150,242,510,242,869,801,140,369,598,639,848,576,488,542,27,252,816,550,581,607,464,109,81,655,968,280,150,810,944,755,992,422,696,773,737,18,901,477,34,292,399,927,911,586,414,907,774,532,997,654,159,868,657,821,272,752,875,523,439,26,838,425,685,307,773,895,620,96,174,879,225,355,896,400,984,773,284,655,446,63,438,540,267,167,72,105,834,469,880,497,468,305,291,232,163,734,38,630,490,826,939,642,837,606,295,353,250,372,434,307,469,571,242,171,286,92,902,811,150,964,135,202,224,140,32,836,682,234,533,53,584,13,771,680,729,955,396,305,722,631,544,380,454,773,223,877,168,175,367,763,106,574,717,757,348,348,50,628,446,535,816,787,899,223,308,347,617,788,969,34,350,890,321,809,110,426,925,79,206,438,502,404,575,453,490,364,539,18,572,161,888,614,44,677,736,119,633,87,235,748,624,715,988,935,607,472,82,807,865,71,723,647,88,932,301,874,870,440,602,933,971,308,364,359,591,865,106,709,47,739,431,870,907,306,565,730,339,908,367,136,746,637,400,137,275,69,488,125,503,34,958,890,588,616,181,955,506,125,165,166,741,309,835,624,738,888,840,873,51,992,325,496,436,143,861,942,270,247,565,455,28,626,625,721,522,371,71,608,186,418,547,2,122,637,656,953,316,318,606,116,116,671,530,508,620,955,459,816,456,694,951,137,188,565,535,69,811,760,911,382,748,103,985,403,499,326,336,551,30,552,309,51,869,343,971,8,472,755,801,412,93,687,858,277,516,805,139,846,153,615,51,630,317,622,928,69,2,54,463,3,761,292,424,431,670,945,900,651,199,450,673,525,913,681,426,176,157,548,591,944,742,103,267,202,479,779,191,533,154,647,535,585,261,559,941,506,731,54,267,809,17,692,828,162,698,599,670,6,272,352,928,203,178,340,987,607,238,972,445,696,825,720,199,886,812,178,761,464,778,83,526,522,261,63,70,931,485,630,220,714,94,654,873,553,463,969,898,404,982,592,198,566,446,708,500,966,492,429,477,755,30,807,950,59,975,614,259,528,227,887,751,95,740,696,92,992,361,736,981,162,638,778,921,916,361,641,740,488,736,294,220,682,542,333,97,425,906,658,337,943,557,511,205,250,337,807,198,542,509,20,407,769,775,487,445,100,517,258,606,284,918,709,718,746,609,733,112,610,268,957,487,427,698,677,45,147,985,773,308,412,809,177,488,642,170,71,47,745,793,94,789,353,131,859,514,691,751,626,400,351,605,550,23,137,958,383,462,440,52,789,67,835,962,86,699,283,493,539,532,14,839,895,712,433,259,55,704,355,575,858,546,671,948,630,0,308,293,851,225,738,280,713,618,189,376,513,432,501,25,314,629,866,60,120,515,955,738,859,411,267,63,161,711,205,681,766,467,932,420,688", +"301,896,287,963,483,385,140,962,219,829,484,663,189,38,742,885,416,814,857,765,530,554,945,314,387,560,64,537,59,449,25,351,402,762,287,981,278,541,505,201,648,705,857,141,907,693,440,719,657,550,433,362,397,967,344,234,821,361,30,562,560,353,704,643,891,508,519,829,873,3,452,291,872,693,364,61,328,694,961,136,761,852,992,858,416,303,674,293,320,954,938,768,183,540,983,513,965,108,535,326,989,613,902,973,61,723,254,114,526,37,753,130,972,526,447,551,784,380,896,678,474,864,429,973,215,537,576,273,584,597,144,101,112,765,302,257,349,103,740,191,249,468,602,878,335,162,199,538,147,294,52,805,409,633,451,308,621,343,537,521,882,145,975,961,31,479,62,717,918,441,888,43,688,820,760,768,915,144,974,473,776,985,329,923,391,519,719,982,647,420,784,295,136,300,637,976,125,263,81,155,754,930,209,56,690,76,643,186,933,697,507,935,962,584,395,946,604,506,209,759,22,481,106,439,227,583,382,509,236,905,734,501,487,138,342,911,962,983,410,275,476,712,476,716,823,82,888,866,583,155,758,140,460,330,534,715,231,287,159,557,835,518,421,401,434,547,155,813,722,173,564,564,128,589,525,594,25,363,389,868,870,56,414,2,739,713,804,330,467,921,924,477,92,444,404,298,910,168,824,444,231,452,879,93,790,375,743,955,891,458,783,642,307,113,847,297,594,620,28,247,584,73,143,442,836,142,934,237,67,72,678,373,855,367,487,881,586,169,505,39,764,739,837,117,319,715,185,398,460,293,789,633,35,739,902,557,27,145,854,409,37,179,183,681,11,642,215,437,141,444,624,272,448,127,557,39,568,964,537,15,738,672,222,724,157,900,31,63,926,243,597,314,789,249,361,352,775,879,979,674,350,838,416,245,102,309,192,520,981,14,310,12,926,332,524,473,989,859,801,686,897,589,964,796,48,962,972,997,947,101,744,167,166,358,284,357,359,364,795,15,792,878,131,300,196,500,406,456,636,301,427,760,912,488,274,47,173,546,122,2,183,92,106,363,185,653,753,683,650,799,923,668,792,378,882,977,119,161,493,997,804,984,270,604,900,68,495,830,322,930,849,675,592,541,548,327,84,576,905,555,627,819,111,501,666,858,717,759,985,738,349,118,105,351,995,597,995,104,918,595,453,574,936,971,91,42,321,610,47,519,543,24,898,11,945,293,750,948,693,232,536,284,309,786,246,744,760,414,448,967,66,114,660,965,601,20,424,459,875,29,484,398,364,731,295,362,821,93,590,537,832,967,26,923,88,913,74,935,426,948,561,841,646,984,318,116,929,519,158,573,382,381,32,995,856,350,622,68,307,451,684,971,126,506,447,103,70,636,168,442,171,44,841,961,156,182,620,365,840,795,517,503,986,120,663,478,22,119,724,186,360,657,766,166,393,321,674,492,247,437,134,200,27,204,448,276,920,655,448,884,221,905,846,22,220,863,400,937,49,460,573,698,405,87,359,28,319,470,221,401,478,353,765,792,882,952,142,955,718,961,132,978,275,849,911,843,545,710,760,857,799,79,498,876,875,58,421,83,168,323,455,374,597,129,709,650,387,882,201,108,239,71,2,423,666,975,309,695,794,340,515,192,145,802,114,767,503,786,827,875,704,721,624,393,799,797,1000,759,377,118,184,56,120,927,814,719,87,335,598,617,907,592,662,245,869,328,571,903,868,513,852,683,779,898,795,490,695,575,703,989,919,73,771,416,4,876,217,6,765,592,604,822,507,468,212,945,625,310,475,726,728,909,656,277,163,183,428,885,403,393,908,317,729,487,347,982,265,562,296,458,354,233,213,792,811,159,67,192,465,909,511,65,658,879,817,611,810,162,344,191,551,188,786,774,115,866,638,347,588,807,161,219,87,331,246,540,275,13,446,718,252,212,469,649,937,111,386,276,326,712,606,806,42,214,720,188,274,185,236,63,11,693,296,468,532,490,945,768,506,868,875,201,270,152,67,183,143,996,993,751,6,254,654,357,237,997,64,880,533,972,559,903,478,319,148,933,682,913,755,98,609,616,316,490,927,463,689,371,272,991,422,278,667,606,706,980,387,153,439,123,585,180,192,166,722,2,323,463,155,22,744,667,858,330,363,253,953,258,490,167,543,565,238,808,601,366,779,662,430,142,509,320,7,701,308,0,868,820,889,315,353,615,683,48,89,712,881,514,175,704,765,556,903,475,875,440,996,764,954,365,571,65,359,426,213,98,620,263,866,798", +"917,564,216,648,779,772,70,893,609,815,124,598,503,709,940,809,690,680,769,937,562,200,549,470,238,414,274,899,859,683,422,363,104,760,353,128,877,615,301,336,475,823,395,973,134,452,396,328,642,674,386,169,582,832,208,743,319,522,151,986,511,857,309,716,737,603,766,730,869,253,670,476,314,585,293,188,188,929,287,51,399,83,882,604,973,258,563,822,864,193,33,135,90,386,317,321,407,175,116,484,448,229,732,783,240,827,29,595,38,417,246,718,378,633,577,686,489,655,334,46,202,132,26,144,257,61,414,591,326,366,643,333,767,431,671,523,802,213,311,121,374,775,855,143,410,337,188,741,705,248,778,490,734,774,803,907,323,450,307,459,340,161,187,386,933,152,624,195,331,36,145,657,505,954,106,172,505,127,192,936,316,641,828,398,913,909,328,848,6,971,228,519,543,794,866,788,830,554,39,112,12,299,158,299,782,532,422,859,730,678,934,52,916,703,893,352,441,16,53,809,474,17,794,488,322,860,860,589,33,765,170,953,463,628,184,839,199,314,537,118,525,644,214,832,720,441,862,210,978,682,239,895,212,95,322,381,36,958,414,729,315,877,54,390,365,841,274,452,525,610,803,916,150,228,936,399,979,735,762,253,954,526,625,112,843,307,136,351,870,790,657,979,37,862,97,614,647,752,153,444,63,759,94,13,450,295,235,244,898,945,27,692,392,622,589,766,721,59,833,440,886,104,741,187,62,353,803,935,301,806,936,343,189,418,927,15,520,523,419,529,997,500,388,212,691,643,978,76,499,697,596,691,180,424,867,167,48,468,588,627,934,717,104,591,746,143,893,254,722,822,128,302,678,602,350,269,633,937,548,428,452,326,374,359,98,400,927,904,527,925,198,75,409,417,257,804,460,735,276,65,498,494,41,173,812,936,537,607,637,461,604,640,235,349,965,650,365,420,314,142,216,90,956,315,7,225,760,147,593,978,936,206,676,752,383,497,91,782,277,873,428,984,460,600,295,278,299,311,701,774,517,13,327,773,340,819,173,600,821,260,940,991,609,516,736,956,331,142,397,303,749,795,807,368,596,218,286,99,480,950,465,393,914,264,262,875,716,353,801,710,900,652,303,428,448,396,569,453,591,703,304,678,614,663,928,607,49,469,839,732,446,728,733,694,578,525,646,267,358,122,461,804,169,751,277,998,241,895,821,232,595,463,364,564,946,213,165,964,555,638,257,218,101,765,682,321,564,468,91,994,544,299,517,708,612,953,530,587,610,129,250,344,702,808,81,344,824,785,607,503,156,40,283,213,340,928,497,438,558,932,986,228,277,806,162,613,32,3,153,538,846,159,968,217,411,740,777,291,778,650,81,826,848,636,561,877,5,976,645,695,85,29,671,188,128,77,605,964,690,698,941,445,638,837,959,319,198,141,737,813,930,736,60,854,525,62,723,702,90,467,744,245,2,391,628,324,424,542,807,168,55,601,23,605,179,885,464,649,513,444,757,847,426,544,390,195,763,447,269,574,136,887,951,806,499,426,186,674,564,437,810,718,714,923,471,710,482,779,213,926,775,590,804,721,301,252,942,523,979,14,689,703,826,379,593,349,814,635,12,45,259,692,504,275,443,99,374,727,892,675,85,185,940,522,417,459,792,395,292,911,110,599,264,89,628,290,681,547,276,439,364,942,968,845,71,188,922,610,439,170,329,519,917,829,837,470,926,681,525,449,502,812,633,48,316,296,956,87,502,200,691,402,61,429,484,770,104,473,769,973,115,749,800,27,417,891,385,261,995,56,86,896,906,415,516,414,434,572,989,389,982,484,859,277,548,902,407,930,593,312,409,980,903,946,563,746,379,945,696,289,764,12,921,111,588,149,133,717,614,221,901,984,137,740,552,91,890,263,866,618,715,534,19,881,743,383,258,540,618,899,486,866,218,44,462,658,657,951,173,316,888,489,746,959,251,453,927,861,725,402,372,789,312,796,821,573,671,440,373,500,209,286,553,942,431,964,10,143,758,326,252,247,938,361,54,453,929,739,147,171,899,881,752,256,958,803,834,93,745,823,887,914,577,332,933,486,833,94,296,551,23,332,108,980,801,621,603,371,282,303,144,676,721,70,323,550,361,114,418,748,53,568,680,786,793,420,438,90,497,582,634,859,886,149,515,914,844,421,306,378,461,823,466,805,293,868,0,378,702,357,614,211,308,911,237,672,839,141,759,497,348,53,722,313,393,123,904,241,499,179,723,680,264,978,314,482,348,634,783,721", +"351,677,258,658,982,467,5,761,973,627,467,72,755,409,912,652,522,916,101,969,1000,3,860,428,354,906,716,393,441,470,102,571,400,593,725,861,618,411,175,98,593,414,766,384,336,890,9,693,763,930,20,794,126,169,546,166,762,74,757,385,286,366,193,874,538,552,761,810,309,258,111,886,782,128,357,195,335,106,921,441,671,792,632,408,49,589,112,716,616,298,746,106,803,387,172,278,524,65,60,349,55,110,855,912,407,908,827,289,960,352,279,657,792,320,750,453,759,490,83,41,327,879,118,444,523,384,42,159,311,356,552,866,675,830,948,180,434,930,392,254,902,370,251,832,591,482,771,970,105,172,522,588,898,592,531,497,785,281,730,569,246,424,988,578,701,288,226,26,407,252,935,384,751,2,404,233,195,8,307,226,997,921,647,989,18,50,839,698,996,688,742,675,626,859,704,170,40,718,551,496,776,52,386,582,542,898,854,340,922,250,759,149,289,787,910,745,741,255,197,273,168,956,101,93,223,131,519,250,404,857,637,740,160,394,357,87,49,687,782,951,658,397,740,874,24,208,359,504,22,448,203,430,575,102,593,311,434,129,626,992,746,786,42,463,682,373,100,96,34,39,401,299,160,163,749,134,926,102,144,187,833,585,265,100,253,405,85,930,455,307,496,682,805,254,132,551,915,331,904,707,799,344,506,256,142,336,626,206,2,774,701,880,289,794,1000,857,61,238,529,149,278,644,418,438,850,555,271,135,737,251,471,889,800,815,273,112,510,997,280,445,775,86,356,366,54,578,490,333,824,288,307,689,67,615,428,659,184,760,653,535,845,228,158,414,356,896,879,902,450,419,245,231,60,84,891,927,512,111,303,105,373,345,30,820,686,89,709,177,530,56,909,399,604,326,3,431,359,990,488,648,758,121,615,401,161,103,499,495,793,761,707,260,773,42,786,63,317,636,388,7,710,791,211,865,865,623,739,517,117,339,324,217,310,218,338,759,522,862,425,559,64,584,380,121,683,239,456,161,34,278,65,96,180,362,945,418,610,821,472,313,720,125,346,996,38,75,219,526,898,391,718,531,690,728,231,537,237,431,9,384,714,15,476,878,902,38,405,875,668,475,738,319,864,383,948,90,129,171,826,889,541,228,103,551,923,716,856,92,811,72,891,87,410,601,60,729,882,787,812,854,35,741,817,82,346,210,289,569,671,646,157,857,76,31,402,800,197,376,872,433,270,756,750,393,905,428,57,895,643,896,411,470,218,857,23,498,179,955,468,62,823,509,479,507,724,575,316,264,77,557,660,144,695,729,114,85,36,265,667,1000,313,530,567,941,611,60,173,113,463,275,512,751,981,130,747,58,635,661,594,701,747,428,335,720,853,854,774,391,821,372,883,70,797,295,945,462,453,961,580,743,137,17,13,822,891,107,808,46,798,729,402,525,153,859,62,525,566,537,99,979,873,619,137,9,761,993,433,217,30,359,661,248,939,960,682,281,344,770,553,911,620,788,740,859,245,859,970,704,651,481,459,147,260,236,500,301,520,130,737,896,396,738,227,67,268,250,719,797,399,178,831,860,878,228,434,982,714,260,371,918,932,992,675,406,315,489,244,952,611,669,863,680,837,935,217,261,619,716,86,41,874,448,306,999,486,619,381,17,594,620,591,170,867,909,699,909,809,361,921,572,670,282,319,261,568,805,428,136,97,998,246,534,810,102,833,423,404,815,839,543,862,166,917,103,45,104,617,398,335,461,149,736,193,556,790,247,127,694,820,932,210,203,444,429,471,806,564,50,991,382,162,385,582,973,306,500,590,67,956,190,785,861,844,669,131,543,588,724,533,804,292,419,10,259,791,710,255,636,940,686,274,383,687,156,904,242,84,941,980,484,114,800,296,201,786,860,565,579,449,793,81,369,722,758,15,847,109,333,494,944,996,56,794,66,982,997,270,755,584,940,782,156,659,603,327,999,430,352,118,694,97,384,971,512,439,866,204,450,750,136,856,610,269,231,420,515,235,162,745,739,52,106,838,605,952,774,301,859,802,448,958,649,156,291,130,31,586,761,161,585,341,992,197,143,728,171,216,481,719,652,867,180,675,473,632,61,926,845,981,469,17,107,780,693,780,159,567,342,226,220,453,479,198,169,586,281,902,718,682,919,720,973,289,174,915,674,752,288,634,180,86,676,549,185,851,820,378,0,372,332,497,92,731,885,190,104,974,482,810,511,954,267,886,686,722,671,68,664,445,802,294,136,347,618,369,785,751,442,459,247", +"988,490,162,221,61,9,354,467,647,578,240,349,875,327,48,326,800,515,273,606,88,86,263,77,94,228,392,861,546,582,287,456,677,534,674,839,2,306,303,870,111,643,976,270,453,620,6,193,273,269,856,815,295,951,165,885,307,726,820,781,960,226,174,329,915,244,17,864,781,155,371,234,12,408,751,729,64,646,210,21,897,697,772,919,556,8,178,4,766,479,509,7,169,66,868,425,344,170,557,372,889,327,278,635,940,504,871,452,476,804,969,222,237,747,499,111,355,480,788,135,250,662,250,264,907,577,983,810,100,866,487,372,82,804,329,829,255,914,733,836,495,235,350,939,937,906,627,992,993,252,2,839,604,243,911,484,342,209,736,125,488,733,47,609,392,941,530,834,498,504,96,87,356,185,408,515,966,401,765,334,349,913,864,429,211,832,348,142,613,662,374,123,366,668,383,603,112,896,756,65,656,487,640,5,381,127,226,834,37,500,833,284,229,628,524,132,699,831,402,156,768,736,652,814,324,801,515,548,885,918,110,552,653,808,242,304,642,240,801,299,428,366,726,714,281,902,874,404,721,111,187,489,148,604,301,80,469,979,314,556,635,10,115,779,115,854,323,777,247,626,352,737,248,801,898,504,91,548,730,570,454,56,234,716,875,427,498,584,889,569,732,662,148,706,279,178,346,910,344,280,930,165,340,161,652,616,194,214,938,607,746,721,581,567,451,500,250,602,995,966,262,52,111,660,332,914,430,292,388,721,146,575,154,352,520,2,466,162,304,194,185,629,567,210,524,937,695,315,707,596,393,885,784,145,466,906,435,4,345,697,732,577,218,331,818,793,410,313,184,88,772,526,463,548,841,763,891,635,318,370,821,897,764,599,278,269,938,975,854,644,38,604,896,138,1,45,204,646,696,746,459,567,548,262,463,763,280,504,316,435,936,677,121,171,127,316,81,531,215,56,939,652,447,684,895,708,426,131,627,3,793,687,117,877,720,878,228,732,46,444,943,427,486,415,38,791,988,957,503,745,703,236,281,13,242,452,234,774,724,248,426,159,427,344,540,229,205,615,672,277,11,661,951,955,36,286,607,244,462,182,908,269,159,872,739,898,165,365,365,200,209,100,490,869,791,773,306,421,901,353,684,7,194,467,526,76,539,222,181,418,395,750,779,688,159,759,304,76,924,842,762,97,336,168,477,330,5,99,198,816,736,480,771,77,9,97,932,110,811,180,136,940,119,470,317,441,19,420,301,257,530,600,872,698,494,401,502,481,562,650,927,339,458,934,784,612,543,615,142,525,684,24,764,655,961,962,784,57,239,534,530,700,282,338,526,909,374,988,401,889,414,489,482,799,33,671,842,523,760,108,60,976,309,4,656,518,635,108,282,751,663,826,433,350,292,414,388,791,584,7,703,363,214,81,805,785,735,616,124,578,621,375,897,679,502,719,766,901,796,818,165,520,306,282,784,700,261,173,939,859,412,272,40,127,145,696,621,403,174,800,12,151,943,494,672,211,446,624,941,251,108,676,100,902,804,160,66,995,297,183,386,282,18,698,951,743,503,418,501,691,943,669,847,39,616,400,284,747,8,56,102,436,539,774,347,363,257,411,737,720,242,793,159,425,713,525,476,637,712,204,311,158,700,594,187,415,472,671,345,590,215,518,439,142,312,591,372,837,906,176,60,4,403,335,791,563,916,950,992,95,417,813,623,37,87,837,711,315,834,945,820,678,795,127,381,708,690,436,425,987,254,699,332,927,949,975,460,280,542,13,691,938,108,829,750,873,974,664,219,61,190,989,967,154,864,631,341,36,399,113,895,320,680,710,333,587,376,156,177,864,33,595,481,211,937,669,66,506,693,985,302,774,953,134,46,86,715,971,814,228,966,468,828,486,314,128,280,369,273,104,249,25,455,453,541,743,913,125,608,81,647,339,764,516,136,150,369,400,858,562,403,204,247,346,93,98,965,357,786,391,374,531,242,849,280,385,357,204,296,306,541,899,655,584,222,890,33,389,426,282,357,206,448,885,779,444,416,915,249,838,488,426,234,397,642,583,717,900,963,830,99,664,604,990,277,472,164,971,646,133,834,142,492,256,466,956,846,442,100,915,960,587,650,243,249,185,833,894,360,967,830,483,86,654,103,932,873,162,978,873,514,166,478,669,336,694,864,78,92,61,225,167,593,560,225,889,702,372,0,684,349,126,61,79,143,530,210,303,857,16,126,201,153,206,194,712,714,722,493,713,113,604,92,180,444,986,895,747,819,91", +"696,703,249,396,449,739,319,112,418,142,778,515,903,974,769,924,955,334,753,655,413,246,828,137,494,667,486,533,549,84,842,832,434,681,751,917,98,251,679,809,662,758,655,793,755,926,834,955,712,791,449,579,605,799,395,61,253,495,626,216,489,579,369,86,718,2,147,876,925,333,60,49,742,83,939,87,468,753,631,698,484,45,166,104,856,130,460,487,597,813,71,808,348,660,667,375,581,735,909,962,517,350,326,821,816,143,312,302,121,291,217,226,350,52,784,53,3,219,354,156,919,798,919,337,827,552,842,220,945,726,235,153,415,390,33,442,72,61,224,828,374,886,339,211,195,339,264,731,795,574,152,207,770,735,54,12,817,160,534,863,143,502,306,977,651,130,799,753,514,374,53,348,486,104,397,120,909,341,959,35,604,788,849,880,154,519,224,591,353,643,760,824,403,574,821,300,388,67,35,221,909,138,224,927,489,461,334,361,14,692,637,146,853,704,679,422,922,660,549,986,26,1,38,189,835,668,486,496,415,985,647,751,196,819,855,956,621,459,496,330,30,629,792,532,408,545,948,792,816,694,327,720,487,594,329,550,999,907,246,309,611,333,84,148,108,711,414,281,428,40,197,305,80,699,51,331,842,666,306,506,757,479,604,801,108,828,726,149,193,277,396,657,335,150,571,867,340,134,278,363,734,569,164,463,142,701,241,15,180,545,881,893,987,378,382,702,985,169,918,308,720,439,322,91,908,460,48,367,101,204,484,530,344,852,491,184,35,162,98,478,214,595,385,685,177,271,194,352,583,528,570,669,670,560,610,804,810,773,771,545,907,134,377,857,286,926,58,277,852,855,534,419,127,514,216,415,948,693,503,258,337,357,273,711,176,117,837,101,646,430,454,724,868,909,250,188,110,770,832,607,673,589,902,171,696,700,223,746,67,328,785,448,120,761,74,90,499,727,254,854,905,50,919,867,201,423,360,124,727,648,824,841,642,572,400,845,387,215,787,993,892,180,314,977,836,214,881,886,722,957,574,348,421,838,918,483,25,501,650,652,359,663,169,300,318,725,271,830,97,457,838,938,683,567,927,29,468,432,61,20,597,158,992,615,247,760,163,196,793,855,464,184,314,485,952,574,302,884,172,940,67,526,804,387,606,353,385,298,13,190,953,925,606,704,179,927,449,614,881,418,116,931,881,121,521,812,471,854,810,240,686,501,838,475,355,168,128,48,729,267,746,414,500,327,682,536,725,37,894,896,273,979,322,190,866,774,507,993,895,325,167,201,513,202,974,991,541,125,378,221,123,79,484,205,205,781,723,914,287,280,770,470,562,114,541,504,984,288,135,660,223,893,286,145,455,367,475,840,47,554,929,602,667,58,780,584,746,902,603,707,705,975,878,935,127,364,83,785,610,987,860,36,584,345,405,557,37,21,93,277,16,782,932,676,696,565,991,879,651,220,833,93,830,994,841,487,689,424,102,260,293,3,563,823,344,245,5,18,432,373,63,961,566,934,214,845,350,14,896,130,357,608,783,956,844,769,521,566,832,651,768,629,223,832,384,198,367,778,104,315,226,643,655,839,674,457,177,380,104,653,287,856,429,520,847,69,255,662,359,437,739,640,597,135,181,819,750,472,210,248,905,797,346,631,238,609,370,315,859,843,948,452,905,874,228,282,63,536,692,705,611,899,622,281,845,599,975,408,538,10,735,953,981,466,929,786,265,528,77,72,567,672,412,672,674,493,744,151,815,813,862,979,893,60,695,191,446,800,350,594,160,470,179,523,892,990,610,904,444,281,194,399,989,474,499,704,887,491,198,639,512,851,299,938,630,11,706,822,918,227,555,590,658,227,727,382,454,207,934,892,832,634,935,60,125,530,693,48,180,966,503,745,436,647,605,40,386,226,923,426,390,222,420,112,468,379,960,933,24,484,329,562,420,452,827,800,680,927,884,870,701,604,738,478,515,134,258,721,506,349,923,499,692,73,548,889,742,925,346,297,510,546,982,144,40,547,325,359,445,553,899,845,381,814,502,462,587,891,130,638,617,125,598,163,51,592,701,338,732,238,983,194,515,853,375,682,106,876,411,854,471,941,692,397,101,203,67,647,695,330,149,850,165,224,315,720,252,377,413,414,352,574,6,119,62,341,268,187,769,941,945,627,627,970,428,926,341,33,496,547,610,631,114,214,738,315,357,332,684,0,371,710,378,641,707,174,840,154,662,930,107,420,815,696,264,813,864,368,255,681,209,280,463,182,539,411,487,106,196,756", +"570,977,210,15,490,23,351,70,155,921,232,869,779,977,467,995,789,632,838,653,780,443,716,4,13,510,948,572,342,81,554,496,884,187,844,493,358,506,816,810,420,369,25,379,488,850,82,678,16,897,674,632,363,607,296,648,651,176,83,828,991,212,881,124,571,249,61,981,928,447,479,919,535,483,887,641,282,204,711,437,46,457,383,982,696,892,336,898,708,766,479,701,514,573,47,105,177,816,681,766,616,651,479,736,991,637,390,988,38,118,593,625,115,25,255,565,927,390,896,806,598,11,827,253,515,916,505,4,384,577,89,246,239,516,234,720,252,686,133,86,271,859,890,498,202,32,759,933,610,831,926,888,331,919,161,229,51,986,496,855,666,744,85,225,902,8,969,934,920,907,925,373,774,767,848,973,570,422,472,509,532,258,38,460,495,951,755,965,620,82,574,180,72,612,493,235,70,722,746,608,648,683,755,336,165,950,916,719,628,351,762,944,315,298,728,865,618,141,282,872,377,483,991,438,512,511,226,397,372,929,978,629,138,822,731,737,49,79,314,660,12,730,560,110,830,473,654,9,364,642,317,753,522,947,262,407,669,866,453,393,145,680,819,9,377,611,992,320,148,417,335,357,446,664,520,307,856,140,679,625,690,298,956,638,40,46,776,766,661,504,856,431,270,24,488,574,130,917,49,11,601,235,815,466,125,26,275,706,388,46,88,871,498,981,953,957,789,933,257,494,367,436,352,6,520,291,841,40,357,205,813,702,171,927,850,434,201,826,482,666,777,197,986,850,256,589,217,72,319,834,373,897,65,474,958,635,658,968,309,63,277,917,535,35,58,159,878,949,153,59,389,520,266,553,210,997,469,353,358,955,829,290,577,909,315,202,508,195,942,929,535,662,245,278,607,517,409,643,502,776,975,969,797,120,518,110,787,646,820,135,569,176,301,682,420,636,771,298,262,147,559,92,496,381,947,314,555,100,147,512,415,396,284,836,577,149,255,408,519,178,752,972,771,734,996,743,393,911,687,895,137,260,801,33,97,496,791,642,559,253,981,100,713,963,926,448,478,979,254,466,606,479,854,630,750,223,174,446,919,125,759,975,771,664,627,655,562,46,262,553,491,732,381,834,445,213,414,428,409,638,859,475,574,947,144,87,958,255,445,120,325,964,198,147,587,584,282,421,6,106,479,551,254,760,263,747,767,465,861,323,154,846,896,500,800,773,758,129,360,677,648,592,745,699,984,394,985,779,129,482,616,78,353,609,771,552,777,328,884,485,895,382,166,141,932,658,325,80,641,989,200,71,600,987,105,642,185,199,865,167,821,450,400,153,437,292,955,820,669,67,6,724,88,27,470,814,205,555,681,317,772,11,414,618,504,656,531,759,171,553,712,65,660,505,814,109,788,678,958,721,745,952,154,780,996,471,25,590,411,838,501,642,165,25,206,357,7,855,382,593,595,740,216,181,293,873,57,196,482,192,893,636,109,980,832,676,962,220,158,762,266,173,753,387,836,782,249,541,233,782,972,530,847,851,828,290,499,351,620,625,479,963,86,584,566,702,855,101,270,568,950,4,605,505,133,970,295,542,911,527,919,523,300,715,755,342,684,70,283,308,850,914,600,636,293,225,952,781,372,390,814,910,832,604,423,792,986,574,433,669,177,685,715,244,913,518,304,626,675,290,796,562,935,680,247,816,83,54,479,895,900,197,915,80,513,413,224,442,365,80,257,150,474,305,564,115,27,113,512,503,457,705,894,543,129,598,620,110,806,106,743,378,106,696,911,921,288,260,905,858,46,426,483,941,408,8,222,388,132,701,806,144,100,92,517,112,254,262,873,64,358,544,342,788,616,622,948,25,372,262,591,944,126,630,475,103,289,353,131,450,687,804,533,253,602,129,361,386,845,782,164,701,225,445,893,728,409,705,703,591,373,912,859,415,705,875,125,861,115,746,740,835,384,329,313,969,933,155,451,153,467,187,333,549,608,589,703,820,402,469,303,57,665,179,67,540,855,580,229,620,953,497,638,82,262,229,944,770,334,13,475,476,197,515,819,798,617,829,675,511,725,699,78,726,171,816,711,276,412,875,731,310,2,573,692,445,827,262,168,609,735,605,923,462,181,398,359,835,428,145,403,602,548,741,332,261,31,436,186,641,984,421,99,828,200,341,955,907,410,395,690,754,825,532,280,353,614,497,349,371,0,956,140,164,408,482,157,615,852,311,465,738,617,475,140,902,950,772,798,591,712,786,654,646,340,350,735,603,302,857", +"416,243,135,324,271,814,811,763,998,255,867,299,213,568,284,699,974,220,638,934,120,432,470,203,204,228,419,504,401,603,108,509,181,190,234,952,384,798,225,234,719,530,224,9,731,669,945,663,489,19,383,435,168,671,804,229,254,703,601,895,341,754,567,748,277,287,754,809,52,898,864,717,888,315,424,867,186,662,214,368,637,26,615,570,345,865,654,83,874,109,310,877,519,61,36,367,306,64,330,61,607,374,188,138,494,952,165,272,371,214,173,622,28,514,276,610,420,756,735,426,748,322,282,645,372,707,666,835,611,185,816,105,429,752,499,683,575,882,788,949,189,32,84,584,985,87,395,563,476,849,594,165,217,577,352,700,581,371,819,202,236,740,650,676,588,331,539,66,656,989,192,367,485,892,515,284,657,398,684,603,633,828,5,696,187,409,280,938,735,539,662,958,346,525,400,594,901,966,394,1000,866,862,407,260,8,981,167,500,285,767,912,536,62,367,65,481,962,378,712,771,305,741,991,585,997,562,392,527,794,497,845,380,452,740,167,940,631,64,925,242,655,582,820,55,364,343,367,588,742,491,743,822,663,297,237,874,814,243,487,928,87,237,601,411,270,517,909,302,155,889,998,816,307,330,121,136,642,169,731,555,425,91,383,891,170,207,638,517,43,818,347,390,760,937,312,6,382,570,846,47,405,351,535,208,859,182,567,198,86,64,426,275,887,364,886,849,830,812,202,297,581,648,908,203,269,345,260,579,857,202,831,834,803,29,60,967,958,413,388,91,693,596,711,660,671,452,416,989,65,715,615,142,61,860,511,290,557,203,516,538,907,968,652,424,131,862,682,40,749,505,567,398,172,926,331,65,107,33,718,334,156,116,974,160,92,689,731,391,151,448,189,819,625,128,132,523,190,749,5,764,59,84,659,923,262,467,701,153,970,485,947,485,107,755,857,554,750,56,816,666,780,481,134,234,708,464,844,855,372,613,472,690,297,190,714,261,725,49,131,823,18,931,400,925,586,556,396,7,829,583,700,556,889,583,709,147,950,672,701,419,413,715,396,364,388,320,390,612,259,885,836,800,275,635,325,657,761,541,714,498,534,676,69,393,712,369,756,304,76,840,937,616,235,254,449,462,151,305,563,637,487,892,371,167,615,777,30,676,873,836,674,837,314,753,946,619,291,13,788,979,192,636,86,5,232,881,241,877,188,295,719,360,367,36,898,149,203,796,827,507,534,93,266,558,513,151,878,736,636,801,807,751,264,79,687,175,955,417,332,48,390,312,139,222,465,900,936,43,501,790,78,994,668,796,474,1000,287,604,323,982,480,850,89,207,19,551,302,61,611,394,101,536,820,789,612,24,568,734,517,242,938,44,129,179,401,107,853,174,481,175,513,663,205,656,700,820,243,386,31,529,408,61,149,776,131,61,686,39,824,150,444,775,375,717,39,108,614,610,955,538,690,355,941,48,493,168,429,649,29,155,229,996,991,715,553,91,767,87,69,861,701,55,579,805,633,978,175,433,987,40,664,689,192,739,443,897,105,989,741,867,314,986,443,760,898,652,576,201,307,384,321,575,174,801,741,315,950,761,800,74,99,737,749,503,679,256,690,266,858,766,22,220,52,9,271,278,385,924,850,194,400,518,503,511,733,942,130,216,101,50,744,456,790,362,712,966,774,640,793,35,644,483,860,121,103,550,515,389,494,355,150,251,912,142,525,317,605,288,945,983,91,373,254,523,146,47,174,446,596,428,769,185,304,371,803,493,107,929,164,137,986,683,393,45,362,385,722,562,304,636,850,394,883,143,966,617,672,700,835,627,673,552,877,723,40,82,402,490,393,952,53,102,280,906,890,641,729,179,218,447,171,489,117,856,328,675,818,730,836,5,45,538,474,262,978,395,764,662,607,433,827,253,2,256,384,332,924,909,879,23,339,793,874,170,994,555,369,796,675,782,16,781,826,860,555,172,997,86,268,950,191,587,543,947,566,644,371,331,379,319,386,517,867,47,269,439,512,857,36,89,7,529,507,51,520,720,69,35,203,339,74,482,280,104,460,912,339,672,353,258,373,565,734,473,56,107,991,832,659,621,100,240,328,39,103,267,570,875,871,433,996,654,187,714,41,675,443,726,589,37,976,989,534,805,876,721,106,247,650,857,604,240,69,942,521,775,570,644,218,89,605,408,18,584,713,615,211,92,126,710,956,0,174,775,491,631,256,258,117,65,878,344,503,200,409,283,320,333,185,946,887,322,200,327,169,806,171,308,205,873", +"444,630,677,725,884,719,989,222,535,946,289,293,598,402,157,540,104,959,683,547,309,257,634,587,468,197,575,923,475,62,807,736,35,842,669,295,641,165,141,619,298,975,83,59,909,825,820,214,139,694,836,313,235,829,857,200,856,618,683,374,850,298,647,378,632,213,801,261,603,36,884,700,574,855,141,171,927,572,907,676,304,77,27,231,990,792,6,339,573,313,626,100,485,440,956,443,38,963,381,464,595,393,613,426,722,96,326,89,133,656,486,781,477,772,118,497,574,944,612,26,812,285,758,711,652,491,965,965,418,996,178,657,794,18,866,146,861,927,490,413,995,471,213,139,671,583,676,54,841,299,824,417,168,805,219,682,411,454,50,78,98,324,373,694,151,305,779,644,368,450,447,89,646,460,613,60,677,671,383,651,271,615,384,843,829,261,788,222,856,550,503,334,114,572,508,603,835,315,713,639,335,137,294,70,856,134,728,773,931,846,30,197,951,211,861,414,532,62,390,886,401,234,512,631,669,52,430,834,295,622,831,970,599,49,118,500,697,819,950,517,938,131,408,400,534,313,318,727,959,929,837,445,650,476,828,980,384,226,280,314,91,382,928,849,416,36,189,638,481,298,649,604,827,762,662,723,633,957,762,536,204,472,83,663,997,712,228,981,323,178,405,525,483,98,918,124,32,218,561,890,796,471,927,35,694,639,112,934,616,58,436,385,111,257,960,655,926,867,290,143,871,951,553,20,480,269,16,846,139,879,938,721,571,930,774,389,142,474,157,759,478,685,447,889,584,431,218,134,278,655,236,604,448,252,626,972,817,770,402,484,334,755,441,373,135,896,248,219,933,755,670,988,108,855,679,429,440,617,768,694,985,757,340,799,18,474,738,10,465,551,367,212,992,689,592,75,758,510,517,641,941,495,98,880,637,392,939,404,237,906,479,822,993,950,720,236,871,826,920,30,252,594,473,797,151,944,450,592,46,941,101,147,35,650,28,149,5,482,112,892,659,160,917,968,759,996,324,996,494,745,301,468,579,342,315,986,337,948,117,826,417,571,328,666,901,170,415,829,406,976,729,102,792,461,723,739,428,496,529,754,359,478,220,546,192,609,926,117,155,363,301,108,189,573,993,489,899,478,692,697,555,185,802,214,275,937,392,62,5,660,282,944,211,871,911,368,759,343,844,419,683,432,215,40,382,136,690,444,699,173,264,367,191,287,211,904,56,621,149,969,585,562,898,298,190,222,646,729,204,100,319,278,650,664,482,912,490,738,506,180,317,192,614,783,868,880,677,877,977,281,171,768,497,221,780,778,905,865,857,677,869,289,53,278,211,437,412,759,529,470,902,177,195,814,430,864,258,681,652,428,385,773,213,909,291,496,758,143,417,402,912,791,667,56,319,67,243,339,268,914,542,780,609,75,454,312,272,119,304,580,560,841,442,678,19,347,528,415,588,672,112,777,211,325,930,582,606,525,973,382,647,312,86,757,96,766,847,693,904,128,920,406,162,949,495,565,432,653,491,484,541,16,413,501,126,440,444,177,10,135,536,445,664,585,239,29,527,982,98,489,715,21,901,225,766,546,597,881,861,973,573,122,893,855,476,534,293,260,656,21,116,586,406,586,872,718,783,344,562,171,320,900,177,790,37,243,808,689,856,794,688,530,529,387,362,777,910,765,776,268,450,344,168,659,425,726,48,221,129,376,841,51,699,733,931,182,382,505,527,927,737,790,624,264,45,352,904,339,513,650,220,81,722,188,545,555,773,293,490,390,479,798,129,54,650,905,199,781,630,700,779,829,104,977,968,770,287,813,911,623,629,36,664,671,140,180,417,468,872,187,86,449,168,613,573,947,978,770,547,444,743,292,39,59,562,825,68,153,905,704,609,911,187,277,507,495,153,984,595,319,831,181,253,623,92,427,143,920,81,850,272,641,615,238,4,203,906,447,983,799,870,970,838,875,402,119,417,989,613,998,667,399,396,408,879,58,73,765,584,160,620,97,310,375,649,473,77,122,461,789,729,822,236,667,692,27,420,501,373,837,796,689,686,56,254,288,190,872,361,437,830,306,961,92,597,261,251,664,675,368,881,574,829,679,31,513,932,871,630,940,740,580,336,716,239,301,244,515,353,176,498,826,61,132,433,486,874,498,206,918,796,208,193,814,870,278,715,233,427,588,107,491,756,53,618,683,308,731,61,378,140,174,0,882,96,246,514,458,489,541,616,425,117,472,892,717,464,302,648,624,426,910,141,160,729,853,818,732,757,484", +"784,613,290,825,416,862,151,757,751,86,135,167,981,983,52,176,552,304,139,934,119,597,242,574,599,563,482,713,836,940,905,440,623,686,671,87,81,817,718,95,482,451,735,286,77,259,333,380,103,326,720,129,755,279,798,911,87,741,789,174,307,6,475,134,377,157,871,441,459,932,553,785,640,790,58,562,325,299,432,125,316,261,801,611,638,990,48,398,516,490,854,849,993,438,883,634,109,792,748,432,466,520,994,516,481,732,69,215,136,983,901,378,960,884,546,223,214,926,920,197,523,479,491,875,910,610,105,514,448,570,241,852,591,350,555,391,133,535,408,653,798,664,69,227,415,263,339,762,733,605,957,473,591,606,924,716,877,602,125,865,702,952,904,415,109,356,486,200,99,804,949,111,496,479,295,393,608,765,437,126,900,113,446,664,510,337,405,450,739,458,143,206,54,97,123,883,447,365,504,970,697,332,16,68,855,869,613,304,391,378,566,232,160,511,522,752,98,520,550,485,506,468,600,605,865,151,264,8,517,345,451,311,445,370,143,784,528,825,653,859,32,198,407,633,241,144,460,237,185,658,833,542,279,791,765,930,737,256,444,538,433,700,685,739,248,733,295,170,387,463,700,738,680,848,86,879,563,667,127,452,677,452,671,226,912,846,409,250,718,901,383,71,511,711,387,671,968,36,411,867,483,468,943,456,167,123,151,487,440,662,52,903,695,747,176,300,326,499,523,68,403,190,283,495,18,10,503,759,659,595,623,486,343,849,768,855,747,318,577,467,412,2,16,128,758,417,845,181,895,119,150,591,861,311,689,338,454,452,232,931,114,15,73,904,105,584,971,756,166,44,83,137,935,315,976,200,789,858,392,984,948,713,606,192,492,516,978,746,942,102,192,184,80,742,131,908,493,580,756,288,490,633,618,488,100,981,980,444,977,997,334,525,372,476,2,983,415,845,389,453,565,303,242,731,877,174,691,924,349,176,655,366,850,64,4,547,830,81,351,402,362,936,194,540,699,662,60,302,348,700,355,553,992,284,914,754,483,54,409,955,421,299,941,98,425,969,300,767,985,747,238,133,434,99,155,821,346,942,239,243,233,213,591,581,580,483,911,869,222,735,852,717,958,171,689,97,429,189,981,613,433,83,784,124,461,286,138,220,871,294,533,400,837,53,1,653,206,655,534,807,871,368,208,168,68,207,492,826,65,266,409,220,324,918,127,260,953,825,679,871,657,537,170,919,626,117,848,891,760,623,804,232,463,155,974,4,781,482,648,638,572,526,968,32,58,623,121,235,585,273,962,424,221,689,708,976,677,443,151,390,222,187,564,220,764,334,414,784,397,355,751,319,333,927,9,7,436,454,485,71,11,648,902,216,76,135,478,432,185,843,630,981,924,239,153,39,453,353,319,236,295,818,496,475,573,468,144,225,380,866,743,252,923,801,811,717,911,573,738,679,217,417,672,567,77,385,594,479,757,505,182,890,662,283,147,330,405,948,491,150,258,816,670,276,463,444,916,236,32,99,800,496,839,600,160,763,784,333,399,209,147,850,527,355,976,365,41,722,115,60,1,910,361,511,793,290,762,293,615,873,529,55,445,112,423,14,736,54,445,950,424,210,392,191,516,901,788,330,125,94,688,738,148,168,900,434,77,229,778,507,461,756,736,938,188,119,662,431,160,566,5,691,159,957,477,222,508,558,164,850,281,829,741,665,981,153,346,440,166,295,669,820,841,163,572,768,764,435,819,578,705,38,539,352,574,618,773,509,88,116,806,520,984,59,902,299,449,152,987,220,755,582,288,386,429,427,875,321,123,853,571,482,310,194,430,199,539,985,875,103,797,867,101,902,454,954,295,348,862,470,777,296,602,362,307,424,101,368,194,729,797,935,911,31,13,795,750,29,319,295,35,639,47,100,963,368,680,490,347,304,437,42,86,150,537,62,665,615,717,450,652,776,178,298,395,985,579,461,282,576,221,34,458,625,952,34,240,329,275,49,582,456,5,631,606,995,745,69,944,620,669,402,686,844,999,657,59,589,679,557,195,963,696,741,366,2,589,426,930,587,129,336,836,717,639,137,513,248,890,204,700,858,345,474,678,472,281,673,884,487,447,875,109,396,160,409,475,728,133,880,54,33,827,412,325,968,515,833,951,107,189,193,220,891,899,759,959,675,691,612,352,57,762,676,189,48,911,885,79,641,164,775,882,0,773,929,542,187,765,736,900,501,466,389,754,564,326,200,331,30,333,70,727,161,334,636,815,36,346,813", +"581,262,752,479,9,674,615,970,757,61,410,960,11,478,856,520,499,989,815,976,727,209,93,613,84,650,861,393,151,967,163,982,708,941,763,611,27,302,479,197,300,665,689,252,387,254,749,599,547,430,700,875,42,418,635,679,684,455,202,91,181,962,82,486,845,526,314,827,824,572,575,82,283,522,505,474,873,772,997,584,571,356,284,132,611,763,800,565,530,39,129,780,175,835,341,495,533,50,662,55,600,251,519,241,989,685,629,155,24,110,409,131,30,767,903,632,375,63,669,205,286,839,630,307,373,437,105,268,107,951,569,64,720,926,24,690,323,766,1000,620,274,963,222,724,294,365,664,606,367,274,485,13,422,961,954,293,777,47,768,945,969,154,923,601,416,515,745,127,820,234,351,393,496,914,10,325,262,682,363,651,777,364,204,749,615,240,905,668,114,476,638,533,264,651,493,708,380,565,400,767,234,718,199,337,739,457,959,955,908,507,60,781,292,684,637,430,504,885,33,764,56,431,315,564,288,435,660,711,405,610,806,97,351,160,869,630,903,674,26,572,466,304,680,305,335,936,546,349,398,648,558,646,305,167,66,795,301,474,450,654,381,713,979,56,292,81,733,744,725,450,433,826,652,584,687,375,269,458,783,881,391,647,179,288,857,77,500,437,268,262,470,59,264,368,986,965,449,877,188,27,401,456,27,932,610,258,469,306,597,344,355,676,846,494,995,56,670,219,70,165,972,694,796,956,800,454,287,638,575,396,629,402,556,635,393,352,752,95,7,87,809,489,457,368,932,297,52,708,644,510,57,688,709,675,710,149,376,333,107,227,189,65,154,897,483,780,844,813,994,519,156,184,84,345,567,371,74,560,576,849,833,736,905,632,457,168,827,6,413,476,249,909,64,372,995,703,34,920,82,577,772,868,432,379,22,292,956,126,67,759,134,295,591,593,45,738,697,27,797,263,920,770,847,370,962,377,237,599,172,157,811,543,151,280,23,598,554,486,770,451,259,893,151,400,770,602,783,347,812,827,730,577,715,674,421,758,81,376,464,687,539,501,532,567,295,738,515,836,709,864,324,170,461,158,3,51,246,397,959,869,636,689,344,858,929,482,710,901,49,800,162,386,21,344,764,875,52,50,245,391,274,567,745,297,997,992,904,425,454,733,102,217,906,922,144,576,536,965,193,755,632,895,962,820,903,303,374,29,89,661,766,102,943,317,136,330,372,670,10,872,186,977,886,147,870,38,677,417,587,572,965,924,395,719,291,698,334,244,547,951,808,214,449,288,973,928,678,259,280,600,544,189,956,689,61,238,598,764,606,548,775,558,8,32,396,341,684,248,913,460,996,109,826,912,783,631,26,135,927,207,387,616,969,569,160,928,150,268,128,60,144,769,673,990,150,456,263,445,361,383,487,127,337,648,782,890,218,995,111,979,623,567,660,969,484,255,638,948,133,865,279,408,498,753,158,443,814,323,700,606,720,727,710,678,118,466,776,704,654,676,173,686,426,114,325,448,178,95,868,107,913,470,585,791,229,713,570,258,106,674,940,57,475,220,776,596,748,639,926,620,908,46,75,739,665,233,946,998,643,547,487,440,134,972,156,620,244,148,519,310,928,785,120,107,252,658,538,676,21,743,534,32,628,543,98,495,270,992,754,831,279,599,972,63,575,673,399,986,709,221,718,801,475,253,44,218,225,345,985,527,349,880,827,431,932,653,334,959,267,984,39,787,220,862,76,739,241,526,424,655,118,985,221,890,86,319,318,398,604,824,797,764,58,668,213,327,886,901,636,848,994,973,425,651,702,518,911,965,323,731,519,15,240,422,860,798,286,872,435,891,582,544,396,220,639,725,331,367,899,649,808,653,998,387,38,302,887,521,536,704,927,429,666,949,60,369,445,772,384,368,786,188,864,295,178,324,930,114,536,616,608,896,22,757,917,323,102,53,745,712,609,975,639,238,371,924,265,251,323,795,981,84,304,967,193,579,167,476,711,615,905,470,635,582,130,820,27,821,701,563,149,414,5,815,132,198,739,531,7,377,812,736,767,20,909,668,302,607,506,995,381,683,163,208,485,660,340,878,355,82,390,863,193,218,520,384,814,905,675,18,314,928,373,73,29,751,9,570,643,385,685,491,654,389,12,93,832,718,533,922,406,77,745,542,457,647,733,789,777,493,158,126,371,591,376,89,237,190,143,707,408,491,96,773,0,171,134,96,520,687,692,122,205,766,22,814,60,767,478,484,563,160,308,904,699,734,350,895,850,710", +"829,721,535,418,14,138,276,825,991,457,958,56,937,510,437,4,352,658,806,425,447,55,845,5,629,833,467,113,182,256,706,292,392,191,100,880,663,145,392,308,233,298,461,744,756,163,124,842,703,852,584,888,313,799,424,472,137,998,789,570,915,789,151,345,609,828,294,66,709,969,110,135,54,277,551,985,656,169,625,406,541,174,744,33,949,559,149,740,276,877,328,744,106,974,750,993,86,739,252,230,363,775,807,138,544,866,418,836,466,315,514,867,736,556,213,407,971,596,244,775,785,270,542,933,162,758,976,590,75,555,570,980,423,98,16,420,671,874,830,442,832,474,98,543,635,488,529,353,431,599,476,92,958,309,392,388,619,128,706,996,974,727,70,96,861,726,902,149,218,548,826,593,11,852,890,454,506,854,316,952,397,501,752,303,671,704,320,181,537,728,884,389,438,242,125,361,469,184,530,553,577,519,610,355,208,586,84,569,805,502,723,178,626,780,59,511,410,849,705,976,714,289,242,659,19,32,841,577,967,357,18,749,295,471,925,605,736,844,562,758,531,611,705,171,60,994,269,350,742,718,382,671,334,435,795,846,60,889,360,336,242,144,696,75,336,470,437,736,430,21,875,983,541,287,536,785,359,162,37,238,671,607,149,227,875,156,212,314,25,36,694,348,436,427,369,482,723,356,868,514,802,3,210,340,591,310,689,894,124,879,201,37,616,296,939,808,827,20,75,174,414,764,14,820,190,111,276,361,195,420,253,280,666,835,192,905,907,429,457,276,557,615,11,341,941,641,908,555,983,912,287,877,767,458,502,673,782,90,805,374,256,349,732,231,405,915,936,812,59,31,764,340,885,776,638,101,396,42,173,94,275,690,251,971,981,569,549,556,297,423,154,200,797,697,594,350,528,400,367,601,829,47,44,810,141,565,252,750,880,435,804,538,859,253,60,852,821,423,438,284,220,771,631,872,361,714,269,860,423,155,472,834,41,160,863,732,846,551,90,717,469,690,931,311,47,541,8,922,552,698,788,392,635,445,721,987,496,874,842,386,884,260,296,349,509,100,497,818,765,663,433,464,497,47,301,990,577,297,114,639,424,190,341,301,639,449,621,335,792,22,1000,359,671,556,353,764,92,315,182,957,492,285,65,77,947,741,227,454,48,372,69,928,324,412,960,726,248,78,445,228,437,696,234,870,739,574,742,315,326,589,650,598,805,54,242,707,797,611,477,235,257,893,218,275,461,84,224,910,617,774,494,323,260,292,444,77,456,713,779,542,37,67,862,965,312,800,68,54,410,398,751,231,511,573,225,349,703,588,597,895,865,532,509,295,517,844,143,900,960,353,114,82,56,993,689,298,979,513,445,99,34,674,49,949,260,39,718,283,850,582,723,745,236,123,809,351,715,182,461,947,876,702,416,867,963,760,920,244,214,892,97,11,176,816,22,881,600,574,853,939,895,297,339,313,858,149,735,695,744,485,393,241,805,699,273,62,443,921,106,211,382,716,80,601,728,905,823,348,184,802,585,4,879,456,61,709,946,296,94,532,362,602,260,720,593,978,439,23,763,524,493,931,772,826,203,293,827,789,408,764,899,780,715,541,621,124,109,501,498,362,771,424,194,549,26,432,607,884,217,577,923,31,91,979,963,104,729,569,502,129,838,295,188,511,753,769,62,620,805,217,796,460,696,100,706,349,521,92,575,6,8,221,144,623,208,813,264,448,704,734,313,808,826,436,881,986,220,115,99,706,726,307,953,303,442,242,285,110,241,773,178,554,464,998,439,649,916,538,816,945,158,195,873,983,122,459,120,966,36,239,276,31,633,834,190,103,984,220,86,548,21,401,378,411,516,913,854,299,987,84,369,724,587,241,480,87,212,527,743,778,194,270,915,515,358,354,749,112,644,430,722,51,836,584,180,237,505,48,323,671,769,480,574,677,523,397,342,869,822,864,129,29,656,415,340,435,954,875,155,611,56,861,519,90,445,889,510,405,899,237,571,136,928,824,549,873,692,643,912,38,479,572,909,470,473,880,979,994,459,477,515,149,64,490,691,729,35,539,97,826,648,577,414,908,900,998,460,489,208,166,582,509,547,811,781,227,172,285,36,295,853,580,336,542,383,972,613,310,92,239,549,993,194,736,577,903,435,192,392,86,925,708,662,223,343,745,998,184,372,137,895,581,857,248,513,712,672,104,530,174,482,631,246,929,171,0,498,336,285,632,158,224,57,817,97,44,130,792,806,236,901,124,863,392,28,663,484,443,734,100", +"870,100,984,240,178,258,357,24,418,18,52,78,993,68,287,774,189,236,81,715,523,451,767,592,133,672,149,420,360,36,804,960,797,51,443,951,47,652,887,731,750,232,587,450,974,989,866,61,217,912,947,292,244,679,78,751,503,765,726,830,545,75,218,399,77,555,143,397,975,932,905,832,828,415,951,586,349,846,987,31,770,252,296,691,602,146,84,265,221,732,398,546,317,724,707,27,965,304,814,570,439,86,636,988,395,386,495,667,713,983,235,618,732,392,832,53,853,408,387,285,774,10,93,816,443,881,287,220,149,475,635,649,509,196,689,256,133,904,144,863,955,277,46,222,25,494,424,744,458,896,468,792,232,398,149,492,904,345,298,851,91,19,616,656,966,430,387,292,443,325,572,122,784,97,231,572,557,315,423,146,894,966,571,980,572,314,769,411,698,866,74,988,192,897,326,357,581,291,208,953,691,735,371,413,331,422,721,680,712,206,908,517,633,972,718,310,373,373,470,363,161,506,393,261,358,944,156,519,421,602,839,852,913,129,304,775,880,42,154,105,309,950,66,704,208,86,790,838,467,981,630,865,776,572,531,821,924,359,771,452,35,920,399,212,674,465,394,124,907,231,737,145,564,90,510,8,433,648,358,710,912,528,190,286,432,372,451,815,348,609,972,405,509,822,44,577,98,106,511,800,810,130,529,171,671,658,504,566,854,407,244,504,192,9,166,429,207,37,970,54,645,353,500,494,891,502,907,427,438,195,650,627,16,913,248,299,486,674,158,821,323,378,523,700,410,975,512,975,763,454,770,508,58,175,505,208,880,76,595,480,787,656,819,78,551,60,420,607,503,504,770,609,912,472,548,128,526,327,600,224,783,590,134,158,719,927,844,508,980,240,566,430,384,546,420,758,138,26,734,179,684,561,454,233,391,130,76,134,240,154,737,340,89,433,622,731,465,635,78,967,580,554,555,40,471,138,587,334,876,901,475,837,315,591,117,315,771,518,246,121,927,826,663,609,137,883,520,302,867,228,557,146,720,594,181,656,304,713,602,867,702,947,670,40,340,987,106,700,769,416,561,183,722,506,572,481,353,489,926,327,783,698,431,45,835,768,162,601,869,361,757,503,37,797,618,446,558,196,367,286,353,388,267,140,712,476,954,472,721,61,461,728,861,785,63,912,561,408,201,569,610,731,85,52,378,610,109,720,76,553,118,913,76,649,455,364,467,747,825,204,529,581,83,416,713,375,544,198,470,458,973,516,61,994,188,139,948,29,237,166,757,243,24,433,528,981,202,962,797,210,384,963,678,222,689,341,284,364,406,529,833,445,713,580,845,58,25,236,617,21,984,664,647,988,470,564,860,596,852,469,89,654,496,401,471,243,297,889,541,870,267,791,934,743,561,762,192,964,961,890,717,124,74,110,182,352,598,406,158,433,78,373,677,879,313,140,598,725,230,759,30,301,835,862,896,563,457,223,711,910,383,272,904,254,693,212,114,448,366,2,280,327,820,465,550,219,771,790,165,516,221,602,140,860,233,135,696,55,211,827,922,839,435,134,404,595,696,845,665,609,480,809,911,308,135,84,528,171,201,957,267,623,648,548,399,46,165,51,147,261,674,56,492,28,901,336,28,694,408,468,346,621,10,942,707,519,607,568,229,669,427,222,319,105,932,552,399,795,930,500,97,979,188,935,247,279,614,394,395,726,192,496,961,753,228,80,643,203,838,692,775,24,458,909,218,764,293,800,903,541,873,174,607,547,168,431,964,538,166,343,977,117,530,27,159,815,501,648,570,772,112,837,442,595,333,173,60,75,837,266,589,12,225,500,656,229,617,310,70,107,770,429,786,966,542,977,910,64,553,641,233,729,555,854,915,658,335,185,161,977,825,514,320,535,581,184,43,679,461,712,955,227,190,544,869,292,897,251,777,628,363,732,304,767,106,803,967,357,209,997,504,252,864,386,762,144,698,768,986,51,273,518,184,959,76,125,40,326,859,202,415,654,50,342,425,220,549,618,607,198,546,379,923,74,19,103,615,311,141,570,834,526,384,386,895,600,334,225,327,519,564,572,153,132,483,97,277,145,932,121,177,59,136,851,379,252,354,970,195,892,130,109,232,167,137,905,162,884,732,909,760,4,401,742,490,21,265,345,356,296,228,160,685,262,137,609,11,94,334,720,158,171,172,488,432,881,839,974,210,840,157,256,514,542,134,498,0,371,6,827,571,193,787,277,368,261,563,178,521,333,90,132,569,839,250,251,119,773,189,29", +"378,807,861,353,92,562,364,737,474,142,975,930,523,490,253,92,676,740,362,104,861,316,75,591,734,333,106,767,999,965,144,319,981,679,843,50,522,351,723,204,110,592,180,231,803,707,606,486,953,594,560,443,829,869,982,78,663,671,48,490,831,138,64,102,6,178,123,813,876,506,263,102,338,522,35,888,159,581,35,894,876,252,22,764,237,507,830,119,50,454,311,272,436,444,796,135,452,30,272,109,985,56,680,111,451,810,758,351,613,250,167,581,597,29,512,212,738,529,660,475,463,483,229,102,23,625,725,938,43,182,691,792,740,566,255,598,316,336,352,970,324,905,476,516,624,275,372,344,810,210,641,614,779,949,894,660,462,478,324,461,784,946,161,277,402,103,650,848,653,366,386,359,439,234,113,790,890,401,573,527,938,302,521,466,476,323,816,661,420,198,791,468,537,641,939,783,508,303,871,901,328,448,65,629,405,172,755,778,559,219,126,685,321,640,693,86,133,791,909,149,936,515,316,53,763,973,75,13,876,873,922,541,157,11,94,592,425,547,894,597,102,756,673,94,471,567,307,963,914,894,978,593,464,674,593,620,757,776,236,908,398,989,674,642,134,956,661,799,960,867,276,653,764,982,626,180,540,547,740,11,321,167,879,571,843,631,512,29,789,192,647,935,178,190,33,301,808,97,58,49,579,896,438,141,133,834,990,480,188,97,619,792,135,122,357,756,105,221,276,540,340,834,322,740,835,417,245,890,681,416,34,628,65,16,209,539,362,111,174,416,26,699,446,274,729,441,147,382,290,549,276,873,436,711,193,392,786,650,49,298,810,193,712,625,813,639,214,616,103,666,330,832,607,973,216,314,530,194,710,224,560,305,538,74,727,36,313,743,129,351,431,338,493,487,319,444,133,192,564,92,315,370,691,651,253,79,811,864,295,742,489,135,750,772,269,656,831,514,856,217,224,161,613,680,643,808,639,287,211,811,201,702,548,860,65,681,85,820,46,427,936,338,905,171,56,200,28,804,97,425,466,956,468,398,933,90,965,417,437,803,232,863,981,780,187,248,669,819,281,34,312,511,166,993,22,267,209,713,68,76,258,571,170,248,207,912,967,780,487,778,161,313,614,921,681,454,19,605,850,314,446,137,660,134,954,832,342,517,475,354,354,596,836,168,994,321,389,136,485,530,315,331,237,719,51,323,840,391,515,31,181,143,3,689,493,168,110,274,198,423,207,849,878,307,81,606,875,861,244,6,726,121,302,571,643,501,112,461,47,38,961,993,151,703,236,908,800,178,525,631,22,799,124,671,147,875,337,445,963,701,279,457,535,689,427,366,950,959,301,328,688,287,23,228,155,746,845,32,934,957,109,943,43,706,500,351,368,290,670,963,792,539,134,629,441,783,433,281,259,495,64,966,961,426,518,374,253,660,210,628,954,281,909,873,226,291,557,368,494,679,108,239,537,757,320,15,802,855,129,167,174,273,557,105,33,606,523,856,497,964,213,733,217,906,238,918,133,58,155,805,46,680,69,677,221,482,714,498,73,346,869,946,747,197,756,437,6,118,525,996,484,933,833,386,848,763,403,799,716,727,363,544,603,56,903,676,301,724,345,280,837,376,637,73,92,150,556,282,601,293,288,62,120,834,166,4,781,649,904,95,256,480,151,453,204,213,66,875,493,437,615,120,366,910,71,408,3,604,792,575,933,922,211,381,784,962,705,96,845,550,266,532,930,590,936,196,211,721,299,288,876,378,796,378,469,542,45,722,350,125,670,297,536,290,100,653,767,461,273,903,30,197,102,884,586,690,804,6,729,465,699,277,384,482,482,996,134,300,124,267,928,348,889,198,63,162,326,957,293,35,353,539,868,209,707,73,782,537,77,77,191,527,508,826,828,291,278,100,16,523,653,907,639,374,43,931,527,644,169,639,609,716,372,887,665,390,492,429,930,329,873,326,296,735,385,12,941,261,36,748,396,911,446,855,63,67,596,619,937,790,977,90,948,562,666,262,327,900,933,817,649,730,506,867,741,750,781,719,321,322,135,874,404,517,862,319,636,95,666,965,516,436,129,576,162,485,518,215,733,726,843,234,116,535,256,309,845,626,325,498,539,682,398,54,590,838,485,440,604,495,30,651,902,424,350,549,670,796,860,16,549,174,145,420,799,876,443,999,208,986,894,115,820,531,501,514,141,482,303,154,615,258,458,187,96,336,371,0,911,470,921,855,377,289,834,497,650,269,254,961,6,272,188,305,186,352,162,957,406,235", +"368,17,840,110,142,714,656,670,396,18,168,685,679,140,601,945,625,371,109,803,140,935,320,815,560,763,468,832,676,204,76,444,671,751,556,908,773,260,773,17,309,216,840,313,259,164,866,979,192,321,582,104,205,153,815,421,806,777,834,15,104,20,610,715,773,653,82,211,441,636,134,791,875,525,258,729,707,727,972,235,683,789,262,875,83,392,656,802,913,738,244,410,869,875,217,926,326,694,654,701,231,635,414,46,787,570,757,268,847,23,746,640,869,117,483,12,913,980,90,692,371,28,943,392,540,152,662,279,961,156,861,987,313,146,302,939,293,687,126,881,692,985,105,105,463,944,35,735,325,273,528,659,64,286,846,307,532,906,296,292,151,183,460,819,827,742,691,308,847,828,7,845,392,854,719,515,703,82,704,326,509,415,682,26,721,70,391,321,887,682,788,355,20,175,411,985,692,750,280,332,679,641,933,804,227,637,427,837,172,819,477,924,888,978,557,927,480,277,310,290,709,710,863,392,247,384,581,767,147,74,6,250,90,616,889,738,205,183,75,565,376,884,162,262,600,347,489,271,429,762,895,950,145,339,717,18,753,852,410,303,346,96,766,627,781,794,151,57,726,113,34,484,892,110,929,343,411,122,306,981,545,644,192,614,459,689,33,562,975,571,265,298,908,822,769,360,414,451,760,755,873,863,878,248,494,385,439,44,419,907,45,724,29,245,677,604,443,800,951,709,317,440,960,989,763,201,33,975,990,521,49,875,335,571,244,808,137,984,260,155,415,35,144,244,679,191,987,564,713,405,361,335,518,845,867,902,63,688,339,110,509,913,350,818,2,731,421,330,401,559,756,331,352,737,378,143,477,799,476,574,512,925,11,424,775,498,218,146,75,371,406,499,311,447,197,99,44,163,267,151,695,327,950,874,71,586,320,30,70,808,465,334,505,960,797,195,976,939,536,840,968,111,359,160,791,482,483,472,848,293,23,446,809,158,702,881,825,109,227,362,394,425,769,692,780,498,143,535,15,824,387,76,646,157,942,62,313,531,454,586,116,938,739,673,355,54,40,659,349,468,55,113,463,48,736,660,235,449,359,788,136,551,203,790,485,160,234,813,818,480,104,569,316,917,204,978,10,476,122,927,58,586,609,167,778,603,785,536,531,940,433,693,761,961,611,865,706,967,729,568,164,138,828,596,777,573,332,753,734,84,266,324,975,261,336,965,330,29,592,497,699,629,450,569,846,526,373,547,710,586,839,703,969,899,228,746,22,522,806,995,311,750,24,669,498,201,132,547,33,601,741,700,823,898,566,901,221,327,583,723,377,882,112,853,87,426,882,242,752,450,513,784,296,987,764,440,205,963,303,800,630,471,563,328,25,102,563,289,919,513,608,635,442,771,735,882,82,885,896,248,248,350,405,907,372,916,71,287,737,924,995,767,887,823,439,358,308,899,625,840,344,294,832,896,109,549,4,224,328,374,173,923,372,474,156,6,998,120,712,387,67,425,146,558,787,40,225,777,932,636,879,706,679,530,46,78,817,518,624,331,767,825,86,951,765,382,863,876,203,331,433,711,103,145,496,612,205,311,182,66,367,678,287,25,605,576,543,698,399,418,977,284,146,239,336,76,644,751,535,382,342,365,840,212,452,929,7,896,475,201,790,995,581,849,874,966,151,384,882,712,681,777,661,512,200,972,62,478,58,728,680,503,172,457,408,227,143,915,379,966,132,113,683,563,782,841,278,371,655,756,538,736,133,656,954,890,335,114,309,865,852,10,698,278,930,534,883,149,534,230,456,951,39,176,338,260,301,760,527,64,173,286,631,760,873,178,470,197,531,285,515,107,370,962,845,561,832,363,766,150,419,790,185,227,101,556,497,717,434,21,413,344,8,153,936,10,428,402,220,81,570,999,499,765,519,935,64,320,417,676,83,772,785,910,611,727,255,901,606,177,39,792,234,353,724,592,329,111,94,371,85,903,526,478,284,864,96,298,560,200,382,901,935,152,503,897,867,479,600,768,213,452,185,397,166,32,423,304,487,931,102,521,586,910,802,426,134,10,798,415,35,809,179,733,342,17,304,980,584,979,993,143,797,763,680,923,161,574,102,283,196,212,755,724,145,349,405,268,930,848,25,962,220,547,412,948,515,445,672,511,374,817,220,554,107,474,435,301,771,5,275,226,721,466,25,175,759,810,857,662,852,117,489,765,520,285,6,911,0,769,412,787,702,242,841,264,730,680,16,962,793,954,729,276,385,487,284,323,423,687", +"224,24,436,219,576,67,256,493,202,54,642,562,479,441,902,139,742,303,377,933,229,971,931,330,684,548,562,181,750,487,463,772,944,157,66,162,995,790,920,367,433,707,197,674,715,332,493,21,522,611,321,941,918,748,394,83,860,923,220,951,881,7,386,491,213,347,563,624,275,347,811,366,681,328,389,671,253,269,350,600,675,337,582,780,510,287,800,442,285,391,90,124,797,760,439,883,943,177,778,900,444,273,211,361,673,295,817,767,418,439,138,4,551,708,243,158,101,70,299,293,133,173,360,335,565,602,155,994,288,912,879,363,122,284,992,98,888,457,372,487,389,513,919,542,540,538,587,789,161,156,605,39,650,490,107,955,963,14,318,543,31,975,742,891,706,460,729,638,443,453,908,273,346,509,658,73,710,781,284,692,767,548,748,836,984,517,399,230,561,367,917,667,588,682,397,531,157,407,206,636,469,252,514,334,905,823,339,924,837,290,750,261,140,323,139,775,609,196,505,798,626,484,643,984,305,423,583,434,865,389,113,135,359,680,10,512,370,553,108,126,104,671,197,529,193,267,5,207,712,476,866,214,767,627,793,577,886,579,446,685,179,22,751,295,498,424,19,941,350,407,666,31,772,760,240,973,181,560,359,502,375,862,305,778,550,150,116,21,912,522,989,639,110,395,691,431,740,317,271,879,761,311,741,248,379,96,803,75,689,332,987,146,540,649,991,766,544,254,341,272,922,895,580,342,81,784,917,377,565,782,532,286,53,685,927,421,354,380,540,995,661,63,398,742,913,3,762,642,746,306,265,856,352,251,576,35,49,728,302,531,740,588,970,280,198,647,75,516,679,311,916,659,686,337,318,855,338,282,5,806,931,468,85,551,576,364,700,856,307,459,419,729,391,624,950,764,511,526,80,134,918,689,423,649,658,604,179,449,526,748,312,471,210,1000,121,553,50,382,356,102,935,777,956,416,884,108,271,498,245,242,360,343,347,678,520,601,266,408,60,511,177,438,187,453,9,879,286,204,504,230,495,453,615,660,677,605,710,458,755,830,690,289,978,370,383,584,919,766,312,408,744,678,857,955,583,352,949,695,310,540,770,657,900,34,691,328,291,511,759,598,558,502,650,826,780,789,538,280,79,442,59,556,254,909,350,728,985,283,953,272,246,57,908,537,707,368,77,714,562,128,58,636,788,234,16,938,681,909,581,584,67,611,157,866,683,449,188,748,679,691,852,225,884,704,306,507,686,459,405,654,871,480,911,605,30,62,496,433,744,698,172,536,255,633,354,44,507,224,102,261,564,712,957,755,659,274,311,586,565,553,172,982,257,81,281,487,870,343,282,362,253,417,546,287,805,801,356,735,545,76,674,898,793,69,838,87,903,174,192,826,569,296,731,216,3,477,512,601,578,634,600,24,189,918,935,782,567,450,828,454,808,744,326,59,915,69,454,886,227,531,758,440,202,84,545,754,329,817,731,429,691,102,930,844,965,789,259,654,781,426,347,979,864,177,986,348,57,244,68,884,858,693,822,29,302,945,292,579,827,848,162,436,877,798,452,437,345,107,986,488,602,135,213,137,303,6,896,248,255,165,566,498,514,302,283,809,923,693,356,161,488,531,86,42,806,532,968,37,951,258,252,755,739,636,138,622,531,417,548,746,918,973,165,488,51,821,316,764,828,874,739,564,343,288,498,446,910,870,709,394,51,388,142,770,235,995,682,434,401,251,486,167,267,198,777,848,842,929,78,310,299,32,916,217,311,287,558,263,633,645,411,696,717,868,400,785,21,38,829,525,327,713,109,645,220,960,234,189,206,419,840,752,713,521,492,66,511,955,24,817,866,619,55,721,39,647,784,236,912,460,786,460,509,875,991,48,182,42,296,412,255,651,706,486,157,985,697,203,999,910,179,745,361,266,727,635,801,853,978,715,379,316,225,427,940,948,2,715,230,830,393,850,143,922,579,189,140,865,847,315,602,505,224,567,453,400,761,205,45,711,812,225,167,787,277,513,945,999,825,183,180,901,404,584,695,565,959,585,934,811,708,465,516,528,167,639,354,193,606,873,540,325,757,282,770,304,910,304,733,899,827,240,701,766,447,961,357,339,106,902,816,900,962,637,513,110,15,745,968,856,35,897,292,617,25,906,123,787,817,302,315,909,13,191,364,419,631,113,71,216,35,256,455,282,314,704,497,511,16,930,311,65,541,736,687,632,827,470,769,0,223,369,910,291,27,397,546,751,443,894,755,207,720,686,418,513,167,391,41,526", +"956,534,14,78,113,423,629,191,326,808,60,654,753,314,950,221,465,668,319,838,568,693,572,478,39,872,566,5,297,667,641,16,571,260,639,989,976,493,516,260,769,451,636,374,72,649,244,820,152,629,45,339,941,905,700,59,992,325,116,154,536,435,111,863,17,344,686,745,400,83,398,323,22,491,506,719,440,227,54,965,878,914,939,722,397,932,943,203,322,124,436,68,926,881,266,22,914,125,246,967,820,188,914,386,939,588,352,541,23,457,346,286,900,622,154,883,329,189,709,125,417,430,519,133,673,195,501,304,202,408,23,414,710,449,840,212,687,120,396,513,706,25,519,965,997,250,609,631,13,10,235,438,214,886,776,604,930,869,45,80,592,180,685,533,872,606,643,263,634,777,142,685,650,753,419,423,966,413,86,668,872,601,653,131,113,161,393,187,802,970,546,679,151,193,351,804,148,551,940,712,919,429,161,560,541,663,549,436,389,458,87,988,472,292,175,984,119,587,986,922,642,971,123,350,807,22,424,112,88,708,358,394,62,686,95,402,420,576,974,241,348,43,524,173,232,841,471,2,815,89,306,142,906,155,361,29,416,783,502,129,337,917,91,185,14,452,903,5,686,930,940,993,939,438,941,901,806,512,309,241,674,859,994,320,550,820,615,125,89,671,338,356,953,785,516,720,566,295,874,96,663,735,462,249,677,494,66,688,510,594,421,307,312,41,605,46,330,757,707,294,686,397,601,827,539,955,798,792,641,1000,785,869,764,579,452,237,622,230,302,182,381,616,459,477,616,843,3,835,607,206,230,818,359,899,672,568,904,482,607,389,827,587,383,609,788,781,188,897,364,471,631,453,370,749,562,245,820,435,990,413,129,201,869,815,851,688,498,356,677,802,489,414,762,316,653,262,967,253,37,956,386,618,167,492,650,428,230,281,949,667,985,536,164,964,530,414,743,143,795,835,7,159,405,533,308,821,464,553,509,420,611,937,649,990,916,586,296,894,39,297,329,856,678,659,965,167,923,37,399,675,767,876,475,251,106,700,43,177,620,385,742,388,662,749,543,680,201,161,387,987,67,495,914,540,993,749,63,219,512,860,748,516,486,312,382,524,345,60,721,249,561,778,610,320,706,51,807,684,324,214,88,225,505,28,787,433,225,384,558,325,487,83,989,14,312,213,482,503,883,219,428,204,350,226,561,553,92,833,629,629,718,837,927,529,821,242,64,932,277,633,170,245,70,703,411,275,317,635,982,574,669,22,296,192,36,699,601,390,779,524,725,161,685,926,410,848,973,612,887,230,890,498,803,668,862,613,689,778,392,668,521,802,788,234,116,416,48,893,502,378,94,972,241,326,177,506,542,11,467,919,692,741,901,428,240,913,78,416,10,41,642,92,375,356,220,380,405,291,702,99,587,596,445,966,364,493,355,423,462,721,77,584,808,144,115,202,202,88,219,440,211,618,186,160,581,87,2,812,723,556,353,167,324,901,174,417,542,636,435,392,828,98,27,36,523,572,341,965,280,610,8,24,870,750,134,462,890,432,685,432,301,728,70,722,556,528,725,371,365,464,584,39,407,966,138,444,911,955,521,832,595,246,513,626,671,195,306,937,811,421,536,384,237,1000,773,741,284,91,375,940,981,363,829,2,855,886,45,501,395,865,407,824,17,772,246,313,34,415,516,95,795,713,652,150,20,673,805,320,446,356,154,900,842,123,464,835,574,673,229,398,546,577,704,436,423,355,87,740,495,183,48,988,998,554,139,23,680,827,206,760,787,375,479,617,364,736,864,683,822,838,275,171,661,190,784,724,952,615,584,916,143,66,883,397,104,645,29,450,905,290,203,419,452,112,499,38,140,28,272,156,13,916,796,346,947,772,457,634,835,728,107,676,173,616,451,798,461,755,402,536,813,58,605,68,988,647,920,229,549,522,670,796,923,97,357,984,553,984,279,714,256,837,717,683,915,701,321,784,120,607,934,491,697,545,278,58,934,253,283,589,852,73,201,64,483,752,648,44,239,609,427,125,371,974,66,325,577,291,310,961,926,517,992,40,23,182,474,829,667,763,369,555,81,915,930,993,981,50,432,895,975,761,221,513,634,944,637,725,268,223,743,501,536,808,201,379,726,137,239,431,413,43,591,876,475,500,90,277,948,313,221,827,63,43,408,822,16,274,117,982,644,681,450,943,629,765,348,954,126,107,465,878,616,900,692,158,571,921,412,223,0,11,106,319,863,161,775,405,781,283,333,210,917,515,426,643,518,150,101,714", +"237,892,529,229,56,220,151,806,726,306,578,736,19,698,568,825,941,47,296,562,412,16,647,889,730,400,798,833,154,842,642,922,703,232,242,851,190,261,553,903,527,754,537,308,43,514,743,944,7,954,600,624,766,112,630,435,293,874,2,121,930,148,92,925,522,106,781,921,390,569,218,150,782,450,167,214,29,28,415,666,368,747,500,516,850,407,28,731,496,599,712,45,81,861,317,770,654,941,821,283,415,257,45,621,433,622,309,217,376,104,684,560,772,414,250,10,129,14,559,237,251,336,683,381,796,966,530,11,866,187,603,307,608,13,941,153,600,458,742,806,881,102,603,183,622,832,32,346,906,705,687,673,996,292,715,227,793,636,562,481,376,976,138,430,143,737,657,715,484,30,695,241,523,460,888,23,631,166,903,248,226,883,874,783,818,792,867,751,573,478,246,97,698,159,704,652,445,57,209,760,162,329,525,270,540,788,597,794,949,444,997,875,532,554,440,580,700,558,683,13,312,369,49,86,64,825,555,368,867,534,827,173,342,581,385,571,981,500,148,544,277,230,560,513,669,433,834,32,430,532,465,354,714,238,365,435,734,139,175,343,138,566,169,382,719,820,21,277,924,103,269,789,856,971,46,511,405,430,534,657,719,847,773,946,335,867,673,521,601,96,742,84,176,875,951,894,861,423,631,205,675,123,484,66,272,770,634,62,42,600,766,997,460,792,470,774,108,517,710,336,893,419,833,146,930,39,15,438,805,492,207,245,881,384,308,724,794,151,522,840,257,27,102,118,478,532,306,438,908,39,815,271,538,542,423,729,768,699,838,699,750,68,661,129,228,162,338,279,482,699,133,695,796,955,202,877,435,23,246,241,988,615,348,624,157,605,947,874,711,200,960,699,640,496,879,88,900,829,25,347,495,138,132,986,784,989,447,99,437,248,681,798,118,705,67,515,659,55,469,668,652,170,304,621,476,457,773,150,363,419,750,62,111,234,175,41,265,204,762,658,517,894,273,242,647,279,451,28,977,510,569,143,513,769,912,53,61,175,890,72,897,341,586,657,106,563,507,392,11,266,284,390,517,422,341,640,715,615,987,568,214,678,558,739,596,525,650,882,655,546,314,807,367,135,946,422,550,937,382,818,320,303,479,254,325,475,801,276,900,812,104,238,212,864,650,106,232,938,410,161,96,951,36,439,453,955,248,609,77,128,332,892,330,934,541,224,485,683,397,736,113,816,608,627,884,326,180,532,860,231,879,259,483,612,932,984,86,398,872,409,865,55,811,692,438,292,824,181,302,726,306,991,130,365,866,373,534,190,284,547,555,529,798,141,95,513,744,816,700,818,186,84,313,596,394,108,707,712,996,652,611,656,26,439,339,889,671,427,921,524,936,483,270,575,975,960,37,217,407,370,876,257,423,624,656,472,701,755,601,522,191,278,747,812,596,323,484,560,95,348,693,353,697,37,403,108,745,268,69,539,300,978,255,886,326,77,8,876,998,704,229,749,417,625,369,925,528,522,435,726,324,116,260,77,489,316,277,638,844,952,774,784,26,880,172,429,892,167,465,273,912,996,851,605,721,662,322,225,733,879,108,760,148,608,713,238,540,514,930,110,488,441,893,653,444,561,993,223,878,348,73,940,331,155,566,226,655,996,559,787,734,151,832,588,33,239,395,155,626,117,709,446,31,759,632,192,62,849,512,365,738,262,132,535,600,81,27,742,946,165,484,819,664,264,631,76,391,241,656,321,82,415,67,169,205,728,152,28,110,665,78,298,846,776,945,164,533,727,241,343,502,89,554,604,81,316,474,277,231,924,789,521,460,661,846,422,961,290,81,939,6,869,803,989,250,372,459,868,522,911,79,111,616,317,193,200,690,719,302,777,102,349,822,423,432,327,534,264,90,31,494,951,580,209,526,60,953,204,1000,988,43,326,301,83,296,361,991,478,711,327,542,864,312,480,454,865,366,321,784,342,792,138,121,472,423,945,353,197,826,387,226,501,491,988,938,103,260,553,252,92,89,146,340,282,752,862,181,330,452,198,746,946,257,295,381,536,928,757,341,660,374,202,787,839,341,842,476,977,950,174,372,564,886,638,153,508,197,283,759,565,200,267,425,451,718,646,234,227,949,579,3,1,797,351,624,306,979,539,843,322,465,136,484,945,396,889,376,266,880,718,605,60,287,718,866,556,53,267,201,420,738,344,425,501,122,224,193,855,787,369,11,0,670,759,75,864,741,907,611,700,991,537,68,769,174,659,974,422,769,853", +"86,626,762,348,15,485,36,119,45,550,705,739,248,339,105,104,522,770,830,506,449,745,779,900,563,699,31,995,374,431,591,851,630,952,640,474,777,774,916,317,819,634,653,253,65,424,888,498,779,332,916,115,117,612,313,407,593,938,54,508,317,899,521,985,473,57,224,762,980,547,250,676,57,939,281,752,320,361,417,17,66,725,614,560,934,906,88,767,192,364,347,626,692,28,317,867,961,946,773,941,821,952,255,155,53,129,322,21,304,554,458,784,381,412,702,703,327,750,109,253,951,485,586,168,329,257,722,72,86,638,111,644,72,235,58,40,303,40,527,81,974,85,154,893,448,541,503,976,549,76,882,379,68,224,798,687,46,158,250,335,459,244,686,656,770,435,39,953,733,106,427,186,802,337,202,370,706,408,695,184,798,61,695,901,665,666,596,144,274,787,593,724,11,566,704,954,257,826,581,396,31,574,427,656,959,389,580,875,307,658,831,307,309,604,317,609,613,388,161,392,295,114,938,601,948,728,679,960,696,7,398,710,406,847,488,676,582,312,832,337,632,341,84,448,954,811,872,581,689,664,913,263,981,528,365,912,599,460,191,580,344,395,834,317,292,402,984,448,712,313,239,33,408,44,161,500,330,335,530,517,309,419,827,433,838,761,723,276,501,932,579,432,919,686,806,407,483,197,816,403,862,326,279,91,627,894,589,611,893,838,766,905,444,243,736,115,669,578,5,466,894,497,655,92,983,767,867,202,951,963,180,994,409,105,871,774,60,119,584,114,202,320,862,963,943,532,591,977,384,489,778,666,838,632,156,579,586,876,152,513,855,443,525,989,705,782,23,700,880,856,698,506,806,279,347,696,655,29,723,115,715,139,450,441,756,600,849,827,331,968,561,965,35,590,809,140,636,473,897,645,809,339,671,798,321,987,436,898,930,601,348,506,614,884,231,55,807,782,887,366,849,318,598,772,16,443,495,782,673,849,520,128,433,572,532,955,584,676,101,945,334,825,306,808,986,971,75,661,421,926,655,465,111,613,535,124,114,984,6,993,677,958,250,506,710,307,401,45,828,355,352,452,830,57,306,669,626,201,17,594,201,70,533,404,672,564,855,469,696,940,148,552,884,563,128,23,405,439,887,415,310,409,142,947,439,432,95,387,651,784,554,486,507,700,325,671,995,232,801,188,430,419,522,907,575,495,194,180,201,68,4,217,876,161,153,279,876,701,314,475,830,865,259,249,483,295,494,45,383,437,295,134,921,929,562,52,642,721,674,931,371,454,779,135,160,722,765,818,517,647,469,785,940,533,692,799,839,419,818,239,619,876,2,751,646,959,962,823,336,991,801,422,208,565,173,368,218,673,128,468,176,382,52,893,344,864,135,470,97,499,903,534,927,782,11,350,886,284,98,680,500,215,954,651,432,737,207,508,909,374,664,184,719,351,395,894,909,817,854,444,937,652,298,329,942,83,219,2,244,184,731,499,682,73,700,455,891,734,901,960,725,242,428,499,526,29,814,931,730,52,461,230,454,257,83,350,831,311,189,552,286,847,940,652,110,630,856,407,241,974,732,502,860,137,300,775,701,148,628,80,701,280,501,266,174,154,400,871,207,662,749,572,811,296,723,625,67,249,846,51,264,650,998,473,783,727,850,7,381,162,259,967,381,326,306,515,329,986,343,160,173,846,729,40,54,835,862,104,655,182,485,881,415,368,202,794,786,853,965,674,4,630,182,436,847,624,642,66,320,650,263,957,416,734,553,750,490,956,128,963,187,207,781,863,857,310,495,261,410,888,685,549,48,769,138,737,686,599,985,936,583,238,541,760,236,668,867,226,660,503,249,992,187,719,205,722,357,755,875,864,411,567,418,362,400,144,585,896,415,433,564,543,137,244,945,315,714,580,563,280,782,349,70,222,450,727,187,797,130,365,677,980,637,122,373,847,288,658,871,825,831,461,51,510,189,218,733,929,676,680,322,134,809,965,154,994,865,84,999,751,810,650,249,115,686,619,123,257,681,483,97,673,437,923,534,383,777,287,716,191,706,942,428,861,845,310,70,842,271,219,37,879,910,834,371,48,346,158,257,416,599,563,802,884,543,331,830,254,962,573,999,578,379,596,926,596,523,606,421,522,249,478,410,879,471,178,883,675,89,40,947,66,999,204,825,320,929,528,388,254,260,550,947,922,60,903,722,886,153,815,617,503,117,466,205,57,787,377,702,910,106,670,0,488,663,747,484,747,709,270,733,486,232,71,668,858,141,230,29,365", +"648,618,746,141,400,699,31,118,190,691,41,978,616,19,707,518,417,83,846,802,525,623,564,231,97,948,373,657,558,552,980,405,802,60,844,304,264,830,379,302,727,224,361,974,399,719,469,370,96,602,199,899,635,957,336,229,435,876,465,769,579,795,615,83,770,16,901,168,118,372,250,896,922,729,959,916,731,387,823,341,27,272,884,829,3,351,638,395,182,641,857,370,800,110,633,307,859,730,129,943,929,308,335,633,546,568,773,436,192,974,756,349,594,381,275,325,725,229,881,905,24,443,929,297,104,16,598,963,585,531,444,491,156,999,317,282,195,456,808,66,803,906,155,141,758,59,353,925,476,729,103,669,296,119,850,889,679,747,539,292,563,534,614,388,567,492,833,432,338,929,134,408,894,385,746,741,325,269,217,561,477,924,561,49,327,236,510,707,834,195,409,480,368,329,723,773,161,662,674,290,997,194,174,914,45,954,700,889,674,25,400,730,615,871,445,825,80,91,99,754,589,274,77,489,640,887,659,504,369,686,474,900,312,389,687,31,973,47,55,803,477,185,394,433,940,739,465,431,623,637,364,974,581,414,164,193,67,893,963,359,417,690,422,744,819,696,232,431,499,9,350,830,665,700,687,774,775,932,829,210,917,952,348,816,221,422,889,678,603,921,801,556,53,81,218,561,719,481,161,249,39,683,189,53,201,934,555,847,491,699,887,536,28,430,862,277,977,914,586,760,116,206,886,65,408,412,261,917,173,458,954,773,15,935,943,901,683,498,251,821,444,354,350,179,276,205,473,370,30,334,889,462,101,619,295,877,665,92,599,585,183,61,44,168,477,893,806,569,68,319,585,439,77,223,661,988,789,680,719,812,607,424,703,639,49,199,87,332,470,509,980,90,15,274,289,628,318,655,173,642,766,271,81,231,548,148,405,79,96,84,380,460,774,384,392,203,426,321,158,228,761,372,219,761,139,959,580,256,496,863,181,245,392,180,774,689,947,476,143,627,713,853,786,763,851,55,154,226,78,483,69,508,553,298,825,318,852,709,486,324,160,865,419,583,20,616,483,384,194,106,321,967,860,625,73,796,721,295,255,216,684,638,201,652,428,53,118,670,162,779,477,364,674,989,461,615,4,647,391,31,653,841,827,605,462,557,203,142,310,797,445,315,232,479,831,406,591,132,194,390,691,97,689,903,184,384,604,272,744,530,327,677,350,816,45,626,866,301,738,895,407,150,84,694,426,592,478,590,395,167,722,909,62,134,286,867,46,74,178,650,449,148,827,867,642,985,470,633,245,124,333,439,636,672,936,947,306,419,512,198,659,321,112,337,387,915,323,118,141,955,415,155,681,791,667,711,502,528,708,764,169,199,793,575,401,476,857,223,693,112,549,465,942,473,505,165,131,469,265,387,288,530,317,281,124,600,983,896,247,466,323,377,931,512,109,904,484,547,319,341,905,833,828,641,737,142,232,641,563,941,775,789,997,822,897,670,284,837,43,514,896,769,553,895,476,856,48,329,692,957,351,139,912,385,180,347,268,585,482,17,69,649,913,330,747,746,593,361,892,776,316,510,639,198,935,90,570,263,338,736,387,302,529,664,844,358,797,941,796,747,14,520,329,163,889,209,813,883,753,756,643,177,540,904,903,867,765,364,81,884,511,701,210,894,993,596,954,954,84,31,389,661,41,825,206,814,220,118,956,127,370,209,881,864,181,238,242,539,341,382,245,686,756,766,475,900,862,495,144,964,6,586,178,298,363,627,589,59,105,518,670,924,46,467,781,866,424,262,19,865,372,43,69,287,296,741,970,527,75,719,156,147,793,451,806,957,454,281,612,808,506,306,681,974,150,758,252,282,196,408,473,60,515,271,76,63,823,339,733,455,377,935,252,835,919,850,851,115,241,51,928,622,425,554,741,279,898,986,499,917,336,936,457,679,105,773,726,663,161,524,602,574,340,660,916,304,814,719,970,335,26,254,424,413,206,768,692,905,691,351,966,43,286,756,375,228,660,827,973,667,229,841,470,303,638,513,443,833,630,127,373,641,187,19,729,686,317,409,566,793,410,772,905,411,864,474,901,697,669,737,263,176,764,201,457,283,897,903,423,561,937,680,979,785,872,933,856,389,236,646,398,12,27,985,529,232,985,179,940,91,961,610,458,76,673,388,566,951,278,884,638,258,421,270,120,475,313,686,206,696,475,200,472,389,766,817,277,289,242,291,319,759,488,0,914,623,107,709,539,283,723,509,416,629,760,565,360,936,719,181", +"448,59,944,223,212,427,529,591,658,122,560,526,758,152,976,534,298,697,53,515,904,62,303,136,218,917,325,845,206,601,922,502,539,612,382,986,655,60,334,318,826,302,796,56,404,447,988,192,191,139,838,179,686,469,154,9,603,981,842,97,250,644,530,64,803,670,570,605,122,881,32,948,69,255,325,808,707,643,135,608,926,141,716,559,922,376,532,680,64,269,370,546,196,922,284,801,436,380,772,125,139,265,361,566,454,14,104,835,475,127,266,2,685,637,2,487,135,540,849,281,216,252,662,915,849,797,424,609,7,31,509,850,965,927,464,539,622,94,62,744,91,421,619,773,870,992,768,25,841,559,219,977,892,475,973,745,790,140,762,560,700,558,613,739,387,810,850,420,882,526,193,387,900,816,318,959,297,205,380,759,519,646,2,182,268,229,289,191,571,579,293,898,946,913,741,298,436,669,14,838,882,304,966,19,688,289,636,413,581,256,939,93,555,933,598,898,922,535,70,117,51,258,154,193,424,957,128,605,12,739,277,518,737,757,156,643,723,224,410,919,854,558,169,754,814,803,185,92,478,769,461,805,340,102,246,780,700,987,785,22,526,365,121,168,295,991,974,119,602,584,704,351,127,418,215,600,433,801,965,326,340,661,697,869,414,544,418,644,311,912,684,662,732,672,977,514,71,269,875,62,949,845,673,664,903,766,122,425,675,248,943,168,173,172,621,384,410,739,614,925,841,197,118,847,363,706,632,434,566,494,853,353,191,699,775,12,180,646,519,989,142,623,256,557,351,831,942,203,694,228,947,216,276,655,615,625,141,976,808,81,329,122,517,833,947,813,509,811,820,641,131,161,482,291,411,196,703,88,107,167,194,375,788,645,369,642,478,677,856,804,82,570,942,730,844,364,989,746,365,594,795,43,700,750,464,742,302,835,425,435,29,664,505,453,399,27,983,939,335,276,617,44,506,151,47,22,29,490,44,807,807,156,277,363,126,882,199,122,499,487,371,725,723,588,262,725,956,437,171,516,884,18,248,786,171,919,493,755,783,156,106,262,756,334,834,513,768,365,597,330,569,729,952,167,272,552,599,182,145,733,518,67,931,766,379,231,419,938,715,581,624,222,792,356,793,684,423,192,162,214,436,395,180,292,596,371,604,715,436,628,250,859,76,153,179,341,596,417,146,486,11,265,687,363,98,200,55,699,483,843,771,114,204,532,577,805,112,156,726,115,670,742,924,769,236,905,421,143,365,104,570,147,764,288,650,390,982,52,83,210,98,139,988,215,575,491,61,52,552,278,408,162,189,484,899,702,178,306,56,60,284,384,931,68,559,785,587,835,683,328,917,519,515,51,836,594,32,777,515,398,646,871,80,604,191,908,302,459,201,968,134,750,887,767,25,397,333,289,965,598,360,441,718,151,159,884,633,388,357,56,902,842,160,675,293,922,707,418,798,676,414,378,755,810,669,648,666,671,421,657,243,248,796,700,474,192,894,888,765,858,183,582,688,236,971,624,178,867,165,836,406,712,572,963,70,23,248,883,499,666,52,55,110,46,136,842,619,896,854,791,243,476,879,975,112,349,259,74,81,625,44,817,811,69,638,667,707,461,635,440,999,953,427,52,265,350,578,461,222,53,580,957,954,223,784,379,502,700,245,376,458,580,214,789,458,710,473,708,351,951,998,847,471,179,690,692,100,392,247,185,728,88,762,35,375,725,139,674,913,911,457,342,149,234,331,132,919,887,405,241,624,347,41,708,369,494,972,985,35,279,204,835,579,321,113,712,519,437,516,691,486,871,68,810,536,370,223,993,512,198,134,123,176,995,994,134,332,790,476,817,534,134,553,693,605,973,572,166,123,678,879,406,377,316,842,584,832,372,773,257,445,435,110,827,748,358,929,944,119,51,374,771,458,357,742,4,265,281,710,171,692,97,429,260,685,571,649,292,739,109,199,748,578,781,739,921,317,138,472,432,496,987,366,175,491,297,215,457,154,904,324,495,991,467,412,991,522,50,673,855,392,900,922,733,683,722,762,857,997,638,301,318,906,906,563,298,639,204,994,151,631,952,908,238,518,777,8,458,543,874,267,600,257,998,766,486,357,541,200,699,484,500,123,575,890,941,218,766,230,830,576,603,884,283,779,440,883,453,718,695,264,146,943,704,375,179,813,835,849,214,156,65,10,557,515,875,393,722,194,264,140,409,892,754,22,97,368,834,841,27,863,75,663,914,0,142,471,503,811,68,429,989,129,61,750,648,97,39,57,929", +"10,640,873,37,935,752,864,153,609,143,54,481,112,925,93,59,714,787,514,512,313,357,10,995,512,61,492,565,425,768,764,940,529,590,898,525,748,787,157,912,754,356,225,568,226,257,976,352,695,566,964,894,460,613,119,426,655,268,240,795,923,755,961,279,376,204,316,64,473,36,148,250,821,381,412,393,545,638,696,927,973,477,77,608,952,89,761,774,673,443,751,560,815,631,295,503,917,190,576,860,158,876,669,229,693,89,274,816,751,381,141,946,60,418,820,343,272,605,351,93,735,177,252,135,579,299,159,633,16,768,867,149,656,145,6,894,588,679,324,78,487,813,153,276,120,936,909,820,509,31,770,125,556,450,480,239,832,811,437,301,772,464,420,614,669,772,528,952,880,301,24,915,191,900,40,278,684,165,65,314,694,982,95,676,684,644,986,972,267,525,465,347,191,605,431,546,459,133,863,256,341,240,6,862,556,466,13,919,285,235,685,326,149,7,9,900,298,351,801,726,720,590,288,198,174,246,704,740,681,4,435,937,95,333,760,59,613,495,864,797,869,433,158,16,343,486,376,514,844,526,190,633,475,293,436,281,949,243,198,556,89,917,949,271,239,680,323,903,788,963,418,439,872,132,411,42,989,856,307,334,410,378,327,247,759,769,131,999,139,61,353,431,406,890,153,357,682,437,297,337,38,769,865,418,735,97,659,24,861,932,510,681,518,246,45,678,435,824,6,235,29,264,145,496,707,112,766,484,491,435,829,812,836,311,855,197,673,992,244,620,961,853,400,306,318,371,58,621,387,466,393,805,866,407,33,764,333,878,494,90,280,234,161,951,224,193,153,618,144,347,680,589,601,848,263,792,7,464,963,181,857,851,573,216,218,729,397,369,165,254,37,691,31,530,573,834,697,697,945,379,548,700,691,801,685,617,447,908,313,851,940,120,328,804,958,452,380,507,187,534,491,852,955,301,616,777,703,211,822,387,572,112,40,373,976,309,979,741,171,669,676,252,801,287,554,268,375,131,498,207,704,690,716,421,707,331,131,327,476,649,733,166,928,889,621,205,897,126,891,114,510,19,997,225,512,445,987,157,898,12,71,934,804,716,155,732,870,632,690,554,171,777,720,14,164,277,105,899,937,845,76,253,675,849,603,688,703,831,238,435,490,583,959,30,275,760,310,187,217,380,466,281,396,56,395,143,379,758,82,420,218,223,163,327,574,39,910,986,596,542,398,29,282,32,503,587,906,824,933,875,865,464,95,627,277,672,834,776,704,787,232,786,766,43,322,276,77,927,780,80,979,778,134,636,296,644,622,448,404,290,598,815,196,621,529,746,786,551,5,142,32,959,215,710,815,88,9,571,557,646,910,820,499,198,737,133,66,787,242,605,663,29,706,246,339,928,513,41,475,386,911,363,318,597,165,752,267,138,972,414,565,574,871,596,452,957,449,990,292,161,872,162,389,362,937,435,65,520,204,891,510,733,750,474,183,347,174,590,23,645,984,628,811,208,226,590,862,155,834,539,866,329,716,675,383,568,225,799,13,502,259,547,988,289,187,359,489,477,767,290,737,244,48,198,210,519,407,70,521,213,322,841,643,162,216,271,953,119,945,343,454,64,380,573,304,537,783,119,348,229,552,113,690,500,961,235,441,579,743,633,656,846,651,264,399,31,109,197,659,323,991,463,456,79,759,711,126,641,344,540,762,753,2,553,317,867,596,908,127,747,228,626,544,299,736,231,635,370,160,973,986,415,346,973,309,704,916,349,402,861,92,515,579,840,794,33,617,357,328,894,36,454,916,974,799,151,772,632,366,338,456,15,764,870,657,333,611,798,632,455,397,492,312,288,213,571,48,276,749,727,374,387,169,397,26,366,599,241,576,326,726,432,656,903,172,159,448,859,885,761,443,45,409,796,68,700,231,819,442,664,459,726,247,119,227,301,615,450,194,833,3,657,163,373,319,151,445,808,428,203,778,643,908,377,476,277,268,289,709,308,250,279,986,653,666,465,620,896,313,23,688,977,570,180,346,673,436,256,556,57,63,974,838,674,776,50,376,400,498,463,94,474,254,365,885,368,531,839,522,114,909,68,877,726,221,478,260,381,20,747,380,711,332,590,422,831,899,424,677,984,768,250,723,133,333,500,223,647,522,560,414,790,617,178,676,705,571,248,501,217,377,368,61,156,955,440,123,671,712,813,902,283,717,564,814,44,261,497,264,397,161,864,747,623,142,0,899,597,609,345,990,957,803,177,97,286,390,316,144,502", +"856,908,838,50,668,873,676,787,912,837,774,88,687,76,172,404,112,46,779,798,219,476,245,668,525,814,30,615,315,332,875,149,313,607,284,211,424,359,847,792,540,205,415,602,342,246,342,388,413,402,298,972,958,770,859,530,705,677,251,583,301,85,748,762,396,235,910,878,129,225,736,84,318,938,404,885,575,77,113,355,110,833,95,189,833,984,79,32,594,323,509,598,884,822,890,523,299,598,768,837,824,33,572,484,733,684,787,755,228,13,348,203,999,246,355,309,440,503,683,448,707,73,282,519,267,379,829,669,155,885,951,43,302,304,928,870,874,349,967,448,779,139,40,826,233,20,920,515,345,415,476,853,317,681,962,381,282,686,210,173,23,583,170,298,547,811,616,257,387,871,274,66,19,329,98,409,512,266,443,678,52,918,612,444,761,165,308,112,886,433,424,877,421,266,173,278,684,402,770,498,931,668,791,979,118,508,256,849,663,907,930,668,479,354,20,541,27,738,60,884,514,177,894,334,740,219,156,834,261,615,673,39,994,737,597,911,77,797,628,861,653,597,935,627,530,531,427,569,736,366,413,738,946,83,101,257,737,553,804,585,6,338,526,979,704,700,487,134,715,163,329,913,11,962,681,57,561,986,87,396,201,475,899,709,911,884,526,186,232,278,441,230,876,517,417,348,80,989,740,193,871,911,170,523,736,718,327,973,227,217,423,961,553,278,449,734,102,140,846,812,830,141,114,440,236,922,420,284,540,765,484,726,894,82,339,109,891,982,973,414,826,163,616,849,212,966,188,347,576,533,296,747,393,879,89,450,148,931,297,337,201,28,646,113,727,866,568,154,503,530,613,556,769,386,302,593,195,658,102,507,214,646,968,791,442,212,853,674,633,889,330,618,116,264,989,90,483,427,786,318,644,784,580,248,223,677,735,627,557,170,838,263,207,738,978,700,985,817,377,447,787,555,345,133,146,463,945,757,434,899,125,833,406,598,539,503,776,904,55,226,891,100,306,317,678,136,799,874,468,510,783,395,131,29,217,347,759,886,578,938,920,483,555,949,180,470,485,312,430,298,674,665,370,611,537,638,223,953,721,745,313,407,652,624,450,445,897,825,492,886,814,638,878,2,951,697,330,356,546,133,899,398,672,2,836,167,135,361,499,636,59,937,163,224,973,107,228,3,550,560,355,339,357,777,461,632,424,75,239,154,763,994,283,123,271,844,222,946,710,859,526,419,398,259,876,985,412,86,350,285,225,678,512,918,460,818,437,922,838,137,187,410,156,721,490,950,772,163,826,206,88,199,74,316,799,307,8,666,465,938,978,766,409,6,620,394,313,99,928,751,151,733,242,965,766,658,38,868,767,382,633,280,37,458,446,896,338,457,749,291,591,993,209,611,629,614,901,73,128,859,603,651,13,182,711,314,672,821,123,287,324,719,500,986,917,439,3,728,968,895,466,558,139,559,678,630,26,252,991,724,791,675,514,338,919,771,810,496,416,400,516,532,517,170,682,988,506,828,864,857,567,475,991,266,900,275,302,337,26,233,341,854,851,746,244,980,162,403,897,308,413,326,905,915,499,595,490,883,542,277,307,401,259,542,392,888,711,659,69,697,30,425,496,805,201,979,709,47,886,397,381,648,606,48,562,800,760,839,751,823,300,42,450,721,930,244,426,570,219,269,236,191,363,787,209,21,155,122,178,880,131,346,398,626,693,488,918,742,94,136,688,797,539,531,533,314,27,390,485,403,486,141,408,632,674,645,505,790,473,316,305,731,59,190,118,467,201,717,983,616,289,726,917,404,881,988,926,960,67,742,690,467,695,677,467,588,508,793,887,751,329,784,236,38,456,677,613,102,773,741,508,30,370,254,759,260,718,997,284,306,955,171,637,636,377,966,57,124,734,991,672,64,488,832,446,462,974,330,48,546,67,597,138,611,786,826,721,125,60,600,323,588,278,567,560,854,607,272,569,183,480,109,82,186,520,377,761,780,615,470,785,819,279,505,610,199,365,400,295,865,26,262,658,125,201,518,316,129,91,745,954,622,48,751,890,925,402,400,917,16,811,201,682,701,344,162,81,966,412,663,251,704,533,362,958,200,709,500,996,427,202,551,102,80,199,144,347,14,239,600,633,867,949,285,712,227,344,469,987,57,452,21,384,963,589,410,748,17,614,751,798,628,436,676,738,996,904,68,714,864,950,320,464,326,60,130,563,650,730,546,775,741,484,107,471,899,0,904,128,454,911,169,787,433,506,779,37,169,778,235", +"196,996,795,312,332,174,620,944,157,306,940,493,903,681,471,795,508,735,353,349,650,133,904,843,915,222,338,398,817,27,968,252,635,646,968,353,83,121,783,338,50,159,27,79,146,252,508,78,562,164,784,122,237,972,628,51,541,83,866,799,296,2,826,551,559,654,753,523,214,173,887,158,765,939,267,341,532,770,223,583,193,505,623,920,903,657,873,253,319,787,51,426,522,424,722,830,117,337,701,263,873,793,287,735,236,321,782,485,434,440,154,239,772,502,291,500,32,604,585,289,639,365,33,640,232,830,45,884,649,871,635,75,663,414,483,331,676,100,995,837,465,729,305,796,960,641,187,898,549,111,170,250,326,397,90,642,810,912,907,506,497,953,397,624,318,423,461,583,400,676,277,387,414,295,68,844,966,883,133,322,973,87,275,431,619,605,644,147,251,347,344,769,631,787,209,307,536,632,125,239,981,98,542,972,349,879,912,339,620,545,201,102,140,35,779,187,90,522,700,926,860,784,529,455,666,278,987,392,269,401,617,167,669,695,572,275,412,72,217,132,644,981,777,608,603,244,415,232,13,678,296,445,339,629,991,511,10,644,559,989,730,699,356,592,935,219,912,106,590,932,419,696,917,741,123,746,242,31,991,62,613,469,582,532,723,450,735,767,280,511,141,54,895,241,187,589,387,346,428,144,379,845,985,182,816,550,279,858,468,658,935,349,850,835,735,466,110,41,286,18,62,442,772,339,478,621,499,835,56,731,182,405,763,711,626,123,255,730,395,23,248,816,179,953,57,289,315,282,657,8,612,256,541,692,457,172,82,917,640,408,654,554,737,91,724,169,91,771,396,412,996,27,129,128,581,272,714,868,421,969,774,614,96,282,423,309,58,189,879,722,86,336,188,663,831,161,994,780,12,78,708,308,263,225,198,475,56,82,440,682,505,794,102,926,151,806,92,350,431,184,593,918,761,257,514,377,644,35,255,90,824,37,365,715,958,865,387,524,915,663,336,53,461,310,840,600,383,739,384,49,152,879,637,585,521,497,575,212,673,258,463,834,592,328,33,493,849,420,297,731,21,111,891,451,955,280,287,864,355,344,696,3,655,130,30,789,526,655,797,783,679,396,675,253,282,567,983,858,102,678,232,954,521,779,2,859,283,874,603,730,589,667,575,944,12,526,334,499,215,146,568,886,193,674,462,962,460,760,583,298,873,785,472,944,485,875,514,34,630,562,293,147,221,294,57,473,375,629,312,764,473,105,736,364,947,501,603,821,641,576,250,25,235,559,234,859,415,357,633,184,954,311,127,607,576,608,427,458,171,98,957,166,949,711,617,918,312,599,258,492,677,39,297,680,603,880,869,253,843,198,630,445,654,179,259,693,658,10,339,617,739,212,462,123,829,872,845,651,80,774,637,315,591,820,148,379,796,597,622,544,885,310,270,871,543,602,688,471,60,764,200,959,163,136,33,406,746,979,796,912,819,178,117,550,200,228,536,62,404,690,820,798,42,998,389,269,62,540,533,875,646,116,116,903,571,201,358,960,724,958,683,855,423,942,418,677,51,911,726,283,510,8,829,929,292,959,207,608,998,932,567,312,539,356,503,758,901,33,419,157,172,798,666,836,939,53,986,241,171,244,641,410,582,128,855,718,908,791,691,783,438,357,48,485,578,984,312,541,536,581,494,69,389,862,286,529,845,968,291,79,160,17,475,358,947,247,73,12,781,535,16,152,663,958,466,359,465,862,490,446,146,868,935,742,816,978,59,734,756,22,382,781,457,786,340,635,912,817,70,796,817,186,792,275,995,83,275,65,515,728,719,110,100,121,299,745,684,551,106,537,369,426,971,245,952,954,525,295,506,111,577,64,622,634,442,746,549,78,409,587,461,11,625,649,319,392,248,971,261,945,703,748,235,351,38,811,303,163,311,631,184,284,99,734,927,481,625,78,488,821,127,24,434,36,488,784,783,984,804,451,996,644,123,279,195,547,648,674,690,925,615,615,724,795,58,167,738,668,311,135,646,95,505,246,368,6,704,740,111,454,692,225,384,4,389,270,238,436,29,563,36,559,312,970,453,227,287,95,349,714,290,532,41,726,382,284,320,859,871,839,625,123,749,795,516,279,592,540,492,421,896,620,977,84,208,446,891,712,645,446,867,551,995,315,349,420,510,639,827,343,502,459,472,960,859,764,241,664,722,368,772,333,302,200,767,792,178,269,680,751,405,907,747,709,503,597,904,0,718,144,522,929,562,966,848,984,858,268,945,317", +"146,874,296,367,465,771,901,919,875,561,501,422,380,694,11,700,417,558,386,396,157,689,801,366,52,49,519,787,474,563,154,529,315,92,873,128,88,885,198,801,888,665,427,1,191,400,320,165,641,995,714,56,13,265,382,222,242,988,319,502,574,378,171,181,826,296,139,946,268,927,706,756,512,489,239,308,699,708,630,494,129,278,294,949,301,179,298,786,745,868,119,132,888,655,507,527,883,79,739,521,407,625,403,145,219,668,593,660,769,138,151,592,234,238,532,711,893,501,491,973,517,490,55,649,686,906,937,607,107,753,511,695,367,906,297,804,19,605,402,774,560,683,367,116,793,662,792,264,983,826,936,941,701,871,915,167,349,299,417,373,498,296,555,974,632,355,722,936,622,483,88,812,274,40,868,629,177,234,333,15,433,142,669,864,98,841,695,478,158,738,672,200,406,822,679,723,467,300,472,156,858,463,739,929,764,768,365,771,567,820,593,374,954,489,107,291,509,469,76,567,160,618,761,42,607,195,186,495,94,593,524,242,727,134,293,411,166,592,110,682,776,449,89,866,324,353,177,292,277,487,639,178,833,887,266,256,657,416,937,880,472,787,316,751,256,151,874,242,445,854,599,831,634,916,297,72,370,626,845,822,874,444,734,366,287,80,671,557,23,498,100,764,45,984,293,895,279,635,917,458,486,206,183,600,382,125,232,621,962,113,40,838,107,301,680,401,274,206,101,484,323,101,390,270,5,729,674,205,730,760,66,352,891,569,57,330,86,500,938,790,843,420,162,504,36,524,231,937,626,585,440,103,116,852,244,872,2,5,654,71,212,822,706,618,170,960,243,40,413,123,121,745,980,201,264,358,325,485,670,456,253,87,459,546,816,427,383,598,571,951,90,967,525,446,953,624,608,794,499,805,634,6,758,214,805,918,423,488,439,959,668,426,197,954,477,149,480,623,192,110,263,487,6,24,847,104,500,588,665,128,440,710,649,393,541,621,418,184,766,502,981,777,884,792,671,141,729,989,134,624,750,552,694,838,57,340,943,315,598,424,621,47,422,906,376,875,901,333,982,296,531,438,716,795,22,15,285,962,260,508,517,941,792,496,928,994,300,875,166,604,978,184,795,451,417,721,717,316,431,212,58,147,291,492,383,284,727,456,887,939,213,244,506,914,211,119,756,330,569,297,938,23,604,963,408,125,249,193,331,515,137,851,811,69,681,272,285,37,333,18,364,139,414,523,958,686,45,917,621,567,760,319,637,81,712,883,151,241,19,915,446,947,912,414,271,359,595,552,44,403,110,246,871,22,407,818,688,744,207,437,478,818,672,22,641,619,601,730,430,313,802,994,968,737,571,923,569,928,807,959,603,185,156,741,935,70,477,358,483,726,965,13,694,701,730,44,476,90,150,87,21,792,725,982,900,982,182,824,405,592,968,212,193,213,381,780,126,581,305,814,299,354,226,904,839,772,309,128,294,460,382,231,335,489,14,477,722,592,129,236,514,119,193,957,714,268,887,524,587,845,483,439,997,691,256,718,489,85,646,558,3,195,525,889,879,596,50,307,518,980,365,304,855,804,482,886,815,377,974,412,177,438,462,971,500,721,601,740,623,553,365,211,987,634,686,662,904,631,368,998,572,289,986,440,293,770,146,49,964,464,993,822,83,820,988,843,656,883,785,33,716,519,622,327,818,352,244,868,74,700,884,868,99,955,682,499,537,674,428,486,237,292,153,101,271,265,738,846,592,694,220,447,120,29,786,967,891,637,76,602,454,539,875,9,223,33,304,736,588,156,397,348,922,172,770,921,242,947,436,883,816,259,460,320,224,426,933,651,645,480,164,35,252,205,234,130,151,599,875,439,259,560,508,62,809,853,603,327,823,938,462,978,769,270,464,161,29,741,432,676,24,874,851,91,469,130,762,933,11,173,150,911,466,371,376,65,294,269,117,453,408,890,915,902,538,814,244,387,430,343,129,175,662,216,396,421,46,116,640,458,138,808,574,606,549,588,765,370,777,165,115,275,112,500,106,843,1,532,43,947,336,385,184,743,39,184,867,550,268,755,739,325,785,65,398,342,917,955,367,404,408,13,362,746,523,924,194,529,644,827,691,953,418,602,367,522,548,607,166,895,915,531,534,653,740,466,931,126,450,239,650,587,662,527,597,55,851,359,879,129,118,349,230,413,411,954,499,445,493,255,798,185,648,331,478,806,521,254,16,443,781,611,709,539,811,609,128,718,0,304,763,861,915,954,383,375,470,836,512,405", +"484,212,199,307,78,921,788,638,272,793,457,604,224,119,477,100,523,492,707,9,426,824,291,931,172,558,296,288,999,642,768,402,969,752,260,824,690,237,322,523,21,688,97,5,576,820,339,133,722,963,418,12,529,308,539,367,659,484,340,649,979,423,625,998,487,48,65,351,496,483,327,297,959,880,990,43,665,176,48,709,797,963,410,826,83,763,573,974,933,972,7,29,964,381,820,548,969,845,284,993,613,639,528,515,684,732,797,591,14,211,777,757,718,508,425,34,385,340,383,341,251,791,226,129,593,41,957,139,687,345,950,758,865,409,66,63,303,838,441,836,46,250,181,910,213,534,794,325,880,222,341,51,786,304,536,672,896,197,201,692,548,748,789,718,752,272,605,938,588,183,262,510,551,683,30,741,202,742,87,558,62,258,189,715,402,498,37,615,212,530,299,552,923,206,8,159,577,666,621,286,880,813,394,168,161,755,262,118,118,617,525,810,339,886,482,543,315,501,452,603,174,518,609,888,502,133,3,674,917,661,549,760,897,402,396,326,171,228,415,355,962,576,60,767,40,424,365,122,92,610,824,966,625,910,349,144,349,832,950,1,308,202,985,38,107,794,406,58,472,924,440,879,914,822,570,34,33,857,481,306,552,818,711,238,913,240,334,831,933,682,89,128,153,515,809,264,60,14,179,763,993,600,210,405,523,42,359,956,327,412,125,15,310,462,405,731,404,185,485,778,892,612,581,974,307,725,992,239,34,992,38,319,82,749,824,734,602,152,271,416,937,700,808,776,22,828,808,350,52,949,246,850,304,644,846,1000,74,648,467,873,280,237,552,667,612,387,269,752,110,867,276,256,121,281,447,760,232,121,31,671,748,345,485,586,927,270,760,575,7,408,899,275,717,211,953,151,961,90,740,763,640,402,32,818,515,422,581,843,422,834,181,325,185,520,618,650,37,360,338,910,620,516,331,270,435,283,773,444,279,998,641,636,689,359,489,595,721,384,12,57,879,758,343,450,411,98,157,487,804,469,596,342,696,289,268,710,435,775,969,586,416,768,825,395,652,364,569,655,909,626,388,934,472,156,964,793,283,427,482,320,332,795,732,197,565,757,213,50,891,272,970,511,647,880,511,429,54,965,608,784,266,448,146,43,459,477,401,102,160,818,789,360,514,978,435,747,987,176,446,827,190,13,856,996,757,519,639,394,905,383,950,503,848,8,558,957,631,403,247,726,381,264,267,78,895,54,41,165,489,206,5,596,794,218,864,622,982,758,610,116,972,421,161,735,214,369,29,145,858,956,719,549,463,125,215,207,266,613,660,956,150,663,575,694,673,989,395,685,176,258,929,317,686,944,102,690,458,211,928,17,844,625,857,581,505,224,911,12,618,930,538,374,43,713,282,164,596,534,84,32,975,211,781,879,532,740,318,982,354,98,408,430,966,501,986,658,253,165,102,86,704,350,986,369,64,660,410,284,120,713,379,574,31,864,570,747,583,30,754,617,300,868,936,751,25,476,600,655,935,452,761,978,712,112,656,273,605,2,739,348,665,998,755,857,535,755,787,557,256,415,330,187,356,192,373,506,312,601,590,533,425,212,163,232,215,653,37,933,523,25,560,22,943,437,768,943,414,759,525,306,279,83,71,349,399,741,213,761,578,62,607,731,466,702,767,328,317,417,210,763,224,351,284,967,762,651,852,615,501,598,391,834,698,644,816,628,914,230,772,575,489,312,23,519,575,600,947,538,516,185,552,352,986,36,505,630,325,418,359,669,949,729,899,214,94,34,818,530,545,986,833,651,511,225,456,869,564,202,233,601,143,780,570,671,727,946,647,916,351,258,719,600,479,670,652,864,454,120,79,966,49,376,857,610,467,248,455,787,500,701,658,450,616,179,946,251,473,264,458,412,33,636,846,879,930,196,465,866,506,249,375,402,294,844,221,185,969,823,457,368,430,124,265,150,61,580,675,828,195,65,52,459,168,618,67,215,125,958,294,648,941,387,637,875,737,923,894,916,170,558,958,584,480,826,139,400,318,361,166,969,548,765,551,317,71,437,857,955,514,55,933,740,968,928,322,296,628,194,170,388,566,767,262,768,514,355,769,632,297,675,394,502,590,908,651,655,458,855,743,217,652,684,371,917,128,812,700,424,542,657,410,596,353,134,361,894,13,743,965,110,393,158,456,83,267,365,179,802,713,681,591,946,624,30,484,236,333,961,962,894,283,700,270,283,68,345,454,144,304,0,363,296,465,366,886,101,554,676,72,890", +"229,342,149,885,957,89,450,579,354,838,773,806,259,340,810,803,684,267,798,485,416,227,723,664,689,944,755,659,375,996,925,960,182,103,105,599,645,91,847,585,935,517,866,141,723,497,746,590,642,961,892,778,652,295,161,306,976,289,869,530,576,68,692,724,239,912,389,922,179,158,766,762,256,586,953,745,550,944,252,579,170,962,148,644,601,572,172,664,901,288,37,414,181,806,479,42,457,250,32,607,741,40,449,117,964,723,420,843,641,228,765,290,602,963,258,248,690,581,54,705,447,55,553,400,370,483,302,171,377,638,564,487,495,180,893,403,485,742,103,58,710,605,146,628,949,930,312,725,141,748,618,311,955,838,911,520,130,131,969,294,776,47,477,669,808,856,894,191,684,846,401,386,608,684,73,960,370,525,235,882,157,520,741,599,884,625,57,128,549,83,200,492,653,720,539,332,903,49,105,389,488,233,496,792,808,848,608,816,638,980,904,692,619,746,586,84,488,535,918,630,380,608,424,7,129,79,607,124,313,717,112,92,432,228,703,487,918,623,124,548,853,857,252,718,610,11,705,677,336,306,350,766,123,338,492,903,169,746,274,464,620,558,932,821,597,943,289,29,833,780,944,697,275,829,834,562,116,427,924,432,437,183,849,821,629,904,931,63,948,301,413,187,115,503,691,640,291,896,435,755,649,494,152,791,495,827,639,660,874,130,114,536,257,305,76,456,446,966,138,739,257,664,271,617,537,98,999,635,559,725,329,216,628,300,599,371,237,302,619,921,340,917,318,681,917,803,399,726,987,873,629,999,449,144,948,993,43,15,239,339,514,186,403,5,838,143,785,923,951,899,470,764,446,941,460,872,796,545,805,941,87,20,106,825,683,38,597,581,784,285,122,80,310,645,16,812,515,961,75,846,194,124,173,753,709,656,241,757,365,777,131,254,451,687,904,511,828,231,8,546,558,268,183,367,766,569,743,589,26,601,511,235,7,341,514,388,73,230,6,987,363,363,283,290,775,714,709,656,785,108,175,756,871,413,604,795,113,614,422,463,608,333,784,84,914,450,85,102,994,398,794,806,578,992,722,575,110,798,712,60,990,102,985,572,50,491,388,982,986,952,500,765,681,781,924,784,208,603,71,646,117,184,167,968,35,420,55,898,464,165,487,177,559,838,663,145,124,112,222,533,231,696,830,959,51,148,414,685,71,531,238,134,265,786,293,953,40,993,548,669,546,679,427,468,517,882,157,228,479,47,912,946,206,904,383,340,344,540,972,464,331,344,161,317,232,635,947,795,132,836,781,250,928,255,522,541,11,411,844,968,243,42,95,745,421,68,647,458,904,227,593,842,482,86,652,972,449,238,275,176,658,939,330,24,189,154,710,832,981,859,542,545,150,968,767,905,664,900,427,351,986,763,941,27,127,858,559,901,676,408,834,932,225,190,368,593,395,159,301,559,309,247,843,594,751,485,347,46,878,241,801,587,698,935,319,939,19,442,624,248,372,963,226,81,435,705,717,829,628,379,463,792,24,691,584,431,391,910,914,645,428,661,250,680,677,793,961,122,740,461,658,123,777,526,887,353,955,570,280,309,656,661,37,920,590,268,779,845,946,27,279,470,781,264,424,376,901,514,420,67,162,280,936,165,15,970,751,327,644,361,59,310,472,320,753,956,51,973,624,824,826,472,264,234,65,752,189,288,794,230,13,737,130,566,673,253,58,172,98,443,367,251,229,788,959,972,498,613,220,921,658,515,615,65,879,162,885,201,620,631,337,394,77,586,66,17,2,648,330,927,211,845,935,927,17,953,640,238,894,957,795,994,944,39,714,163,538,893,698,55,833,530,842,381,518,315,270,478,136,519,727,321,45,512,359,163,989,440,249,347,246,235,182,239,777,960,496,319,503,967,748,954,558,687,687,203,393,512,363,823,833,138,440,469,571,16,803,848,92,563,761,877,364,486,399,386,647,368,963,212,560,342,558,205,134,434,357,555,779,512,448,659,363,784,911,17,292,583,344,540,972,457,786,946,644,826,506,608,683,610,183,625,289,956,975,710,957,89,367,224,876,805,845,332,648,604,308,381,264,161,857,611,288,224,399,378,826,911,481,936,436,115,973,987,793,172,1,181,250,918,211,265,372,923,445,727,291,230,763,455,243,432,604,539,883,613,90,640,867,572,429,69,269,408,63,571,723,294,113,209,712,887,426,333,563,901,90,6,793,755,333,991,733,723,429,990,911,522,763,363,0,329,820,653,851,673,292,869,264,19", +"344,778,675,215,826,607,981,758,480,805,153,624,908,936,282,313,301,368,648,43,60,858,723,51,511,67,175,179,765,198,205,323,143,914,699,220,31,440,250,388,369,235,650,815,305,172,317,927,717,568,972,566,711,595,423,715,702,896,566,360,931,616,331,337,482,710,624,154,481,537,122,749,624,703,757,798,271,235,294,785,92,901,485,952,115,405,708,650,715,207,115,239,585,65,701,951,31,6,968,435,630,321,87,731,216,72,722,155,367,517,195,14,246,917,243,964,216,313,708,261,906,648,172,302,848,204,39,54,412,586,14,849,576,444,811,985,295,72,427,508,825,774,157,183,965,136,478,938,91,925,768,605,893,115,65,213,787,372,642,679,980,61,697,278,1000,37,482,22,226,11,788,113,226,980,320,27,744,89,775,104,681,547,65,188,883,345,244,749,437,904,385,154,565,121,859,411,837,231,526,471,24,392,637,537,417,844,771,746,935,9,451,517,492,455,753,979,503,347,79,582,846,614,332,359,617,48,262,746,94,833,932,865,342,549,746,605,160,991,133,48,737,738,754,669,48,769,734,887,404,662,688,260,951,80,712,187,235,418,364,260,670,96,42,883,709,446,25,305,716,711,334,442,683,812,212,905,421,421,363,745,282,448,589,7,230,589,103,982,765,908,962,67,688,556,420,118,963,10,305,467,862,247,169,996,118,636,838,512,141,211,413,485,724,451,637,836,363,162,276,213,1000,911,645,540,394,504,63,750,796,374,242,591,637,588,92,392,329,701,266,758,833,527,785,131,285,975,322,599,427,697,616,971,505,93,836,807,64,293,583,737,482,290,404,574,28,789,561,945,395,737,676,31,835,667,57,512,160,861,206,389,283,580,336,64,140,379,666,794,4,211,836,919,359,315,526,970,791,624,759,639,427,722,147,427,267,28,813,937,764,613,849,391,918,974,715,202,80,230,298,934,967,822,606,459,908,804,336,214,332,986,926,982,592,142,570,488,528,593,121,138,533,703,455,441,2,412,193,878,845,473,479,814,194,556,856,497,641,74,381,478,990,170,810,880,178,495,751,898,493,303,334,554,727,765,902,295,448,207,352,655,935,804,89,754,411,48,566,370,117,513,992,917,973,924,210,897,694,79,135,196,131,13,634,526,863,664,49,490,482,489,283,863,744,68,799,538,696,528,241,713,646,231,213,269,254,64,948,826,82,912,29,892,829,667,811,800,471,493,26,838,71,79,684,947,352,361,984,433,698,166,400,959,335,308,998,252,366,707,436,327,540,498,379,117,912,8,825,337,396,53,73,231,496,50,59,159,508,511,750,396,880,439,654,744,945,253,185,121,15,479,194,378,694,908,501,410,315,112,724,476,581,184,972,952,190,56,743,545,53,725,950,681,627,394,39,489,972,270,939,657,987,290,324,488,142,904,829,565,273,11,913,695,858,981,750,231,254,964,409,879,435,347,933,216,148,961,651,205,398,771,191,761,789,289,660,975,547,404,718,771,191,800,515,618,415,671,142,666,155,524,320,919,338,38,874,183,541,961,988,58,80,1,989,282,263,785,231,164,593,468,852,805,763,535,676,600,47,197,50,316,376,561,60,52,228,691,314,863,623,345,781,998,313,632,653,856,509,476,812,310,269,597,258,32,8,232,682,826,253,873,771,64,911,261,552,235,400,890,739,285,654,787,728,899,44,392,47,270,398,953,69,975,122,568,502,721,799,250,132,866,258,457,327,354,846,95,345,103,550,976,342,855,304,907,593,197,309,377,512,70,461,44,788,649,837,864,536,932,1000,97,245,961,401,589,101,343,667,419,289,366,678,195,845,992,713,502,967,29,528,632,419,56,361,858,188,446,861,251,351,377,148,748,336,171,29,231,402,966,797,905,143,819,411,760,172,942,369,272,147,384,691,289,387,578,417,583,26,130,905,27,921,778,250,673,135,101,436,853,339,463,711,799,363,18,342,522,76,577,586,906,570,380,899,798,551,549,953,587,318,509,504,744,155,329,766,846,312,195,496,498,957,573,797,76,262,420,600,809,923,232,513,177,901,984,61,541,406,403,569,494,359,479,927,651,71,755,99,189,322,280,916,951,192,279,290,780,161,351,815,962,357,459,7,107,392,770,880,222,248,845,398,849,397,859,490,176,831,195,113,94,625,377,895,431,329,992,511,231,356,473,67,619,720,647,161,65,680,136,604,280,786,322,910,70,160,124,132,272,954,207,210,537,486,509,989,957,169,929,861,296,329,0,733,760,213,714,470,259,629,120", +"870,657,941,565,559,196,210,75,128,229,171,840,843,567,609,202,33,548,992,934,676,549,881,467,394,664,875,626,354,319,156,739,404,842,899,164,60,95,318,179,617,805,824,371,125,307,426,905,325,305,553,91,109,459,636,686,474,32,604,652,440,992,638,782,130,911,517,527,171,953,924,6,611,456,252,525,984,514,922,932,641,362,995,575,547,978,333,783,537,241,459,623,819,212,700,637,801,99,217,740,60,629,625,963,17,87,64,673,440,710,69,50,956,682,592,407,476,627,31,980,940,175,649,561,260,569,794,619,67,856,632,515,275,686,762,155,867,85,940,220,786,397,935,594,536,765,348,942,474,178,655,940,601,370,320,735,769,804,726,118,46,670,961,119,349,234,47,1000,939,915,851,103,648,129,637,71,352,386,710,594,542,865,301,517,53,265,774,530,420,565,708,422,779,30,780,143,421,14,320,249,157,103,690,975,112,796,132,139,318,221,844,256,122,204,60,376,860,514,175,537,662,603,638,284,883,426,487,239,359,601,657,205,44,990,259,528,474,389,10,842,124,194,590,609,318,308,53,454,709,373,425,34,728,922,907,909,947,167,414,336,280,860,494,437,730,98,543,802,60,274,662,662,694,242,198,942,473,218,296,429,764,345,603,363,479,154,200,285,807,72,733,938,55,946,607,503,677,128,480,152,335,519,181,707,523,306,395,989,586,273,572,210,266,924,170,807,793,718,114,504,482,808,195,789,200,516,625,468,780,5,464,274,358,906,6,255,602,606,218,467,689,456,271,305,567,35,262,355,439,599,276,42,833,989,404,400,105,998,996,845,560,139,635,1,878,826,282,109,161,507,272,499,824,989,815,198,729,739,336,484,686,631,940,260,323,42,839,202,440,886,542,480,253,278,158,206,782,245,502,678,273,44,648,11,76,387,279,798,155,904,985,418,991,413,735,211,679,458,277,435,541,874,582,735,374,509,438,403,29,531,339,42,809,46,812,39,795,895,156,824,499,530,471,53,292,547,935,258,666,220,816,772,136,197,844,416,520,567,613,15,696,339,321,638,398,321,183,572,630,232,737,561,988,937,461,830,941,113,830,582,378,852,379,121,598,230,493,928,503,121,844,479,569,788,919,987,495,412,256,924,487,349,429,571,212,896,486,139,486,657,780,142,890,644,557,444,855,993,768,701,943,171,934,913,697,200,199,358,8,116,806,42,311,685,684,126,861,740,658,365,983,833,26,587,60,221,892,140,912,662,49,652,103,628,972,576,545,265,159,627,617,728,527,829,628,428,374,4,111,807,391,695,917,913,698,688,953,274,108,841,681,596,373,244,668,348,275,830,214,881,868,855,46,589,338,114,768,654,109,237,177,973,860,70,437,672,816,33,484,290,891,775,881,507,785,559,112,473,540,695,494,541,107,137,761,574,105,856,134,342,424,85,858,154,197,283,739,961,662,648,701,700,774,338,49,107,716,33,42,636,180,406,397,576,938,812,486,743,590,254,636,627,787,749,103,133,665,333,728,397,464,728,155,315,723,270,182,678,759,635,886,153,750,903,613,751,271,554,474,898,701,207,850,396,726,41,524,38,983,896,269,285,128,177,372,729,884,445,10,9,427,171,161,447,150,481,729,891,716,773,872,355,728,742,648,166,679,763,609,689,6,923,750,315,47,412,659,233,627,258,555,600,430,772,311,661,341,520,705,410,664,830,981,266,182,262,89,572,131,320,868,602,438,855,541,625,891,61,712,963,312,509,511,960,506,780,108,493,282,934,919,672,947,913,854,68,477,247,684,636,61,768,550,922,360,193,649,848,255,713,838,587,177,282,355,276,643,679,527,584,218,89,963,988,662,223,469,199,622,937,602,375,381,647,790,588,676,955,924,817,441,225,399,849,650,357,889,284,121,747,592,588,894,154,396,510,610,180,486,173,558,621,502,26,653,117,65,132,728,256,678,423,191,404,926,642,331,975,730,972,506,743,871,183,959,784,258,940,860,709,638,489,54,641,854,272,751,325,951,539,373,786,136,80,880,977,62,475,528,608,394,665,912,124,732,485,649,605,271,911,839,439,660,894,747,602,349,628,942,38,691,467,987,722,942,796,625,940,211,282,393,67,903,910,75,335,476,517,634,257,165,828,670,869,252,788,558,702,779,434,750,911,562,409,841,361,661,176,542,562,207,871,170,283,711,359,264,347,92,463,654,200,141,727,308,863,569,188,729,720,917,68,232,416,129,803,787,562,915,465,820,733,0,536,220,501,595,482,893,939", +"673,755,533,658,501,535,594,191,192,418,405,598,909,700,956,319,895,544,935,861,299,415,696,952,472,857,740,723,615,425,984,542,646,553,381,802,872,355,779,511,137,526,478,459,831,4,878,281,382,390,534,124,889,524,259,504,245,950,518,332,165,164,118,546,258,552,1,818,467,474,206,222,851,729,76,129,129,16,885,762,379,68,978,944,648,537,582,251,522,798,426,849,969,148,499,142,910,96,452,84,494,703,81,632,164,941,407,105,545,502,297,755,13,538,100,595,27,81,757,617,869,528,723,55,626,340,441,833,64,892,230,316,607,422,23,386,6,881,311,322,273,359,430,950,596,117,206,696,957,641,806,620,77,914,322,669,252,481,364,694,13,534,202,276,897,273,717,445,804,79,502,370,571,275,272,441,913,313,120,764,306,317,310,445,446,457,527,570,205,847,651,812,48,102,459,115,979,616,830,765,173,882,871,913,68,9,773,339,591,674,209,733,717,691,154,640,256,41,526,58,809,379,667,832,682,128,493,724,553,207,349,325,842,188,986,835,446,840,606,161,505,161,638,17,295,106,732,180,623,903,727,489,245,740,79,995,590,566,613,564,448,13,67,298,351,340,375,91,844,795,575,980,940,693,73,638,16,394,435,520,572,747,634,819,142,380,569,873,806,52,936,634,45,760,617,459,485,639,427,717,573,690,464,802,23,211,682,742,648,392,393,319,896,48,526,61,402,961,891,67,942,437,556,327,755,46,465,411,934,68,504,458,65,804,577,935,257,45,581,763,352,846,798,799,343,987,977,723,561,732,187,301,280,196,588,569,606,286,229,23,845,965,684,878,814,106,880,406,238,897,638,331,200,942,773,185,406,908,316,305,840,796,751,604,859,671,844,834,688,444,112,149,636,648,651,297,187,164,453,768,972,34,497,982,753,578,931,666,341,303,873,939,197,561,517,598,549,207,896,754,598,468,480,69,450,848,525,350,226,843,402,990,730,452,491,325,217,694,539,400,186,156,393,7,197,758,16,393,199,389,53,581,926,129,732,945,738,608,649,159,190,920,342,246,683,153,506,111,14,568,907,623,327,317,114,104,694,286,819,487,413,69,428,214,490,6,151,947,945,887,72,241,279,513,357,737,187,908,862,845,146,889,415,432,260,371,861,415,625,446,87,24,488,528,747,278,953,836,599,393,609,448,208,659,698,114,648,192,182,247,661,737,415,251,185,450,948,552,759,447,594,500,675,705,571,645,45,304,897,851,713,990,401,688,818,499,185,863,13,345,191,648,76,208,917,756,339,300,549,661,661,495,110,952,545,833,220,65,635,423,90,89,257,442,955,674,767,573,549,773,712,692,879,224,204,500,924,312,255,550,411,922,570,224,636,774,227,914,373,684,199,779,817,369,28,72,688,837,752,963,910,238,923,31,730,615,407,509,592,508,439,172,887,623,500,287,787,37,471,344,460,832,56,313,305,818,431,55,873,59,920,891,210,888,728,387,279,78,563,869,176,966,472,889,865,704,380,963,429,381,226,379,134,302,448,505,445,828,881,458,454,875,502,229,956,652,711,912,564,208,456,927,941,607,730,244,601,323,716,403,535,272,830,669,38,691,493,909,672,342,112,264,803,938,938,200,331,410,445,401,609,65,431,682,134,868,875,719,381,884,551,10,554,861,275,846,481,355,854,724,400,394,415,46,827,520,754,676,835,101,707,593,814,723,353,464,3,614,92,120,364,855,633,248,320,765,320,667,548,935,296,253,674,429,380,361,281,921,336,138,8,299,967,673,839,607,264,84,147,592,75,462,524,892,991,916,726,911,27,342,799,224,968,732,304,168,846,752,535,306,647,619,65,993,55,63,406,822,464,793,51,265,606,994,663,981,655,374,267,309,773,209,15,59,7,590,934,429,956,55,293,106,566,729,504,19,744,77,293,993,428,290,408,505,37,986,895,943,909,275,572,303,529,154,793,184,241,575,594,863,702,49,319,852,854,975,551,392,78,484,273,286,670,83,777,406,984,845,51,173,435,797,552,563,815,776,267,386,523,440,294,78,145,785,277,471,870,234,209,527,835,521,492,808,560,727,896,869,982,811,351,659,376,652,145,372,915,152,631,300,799,712,239,593,44,350,510,225,981,253,642,942,226,995,671,84,138,954,133,862,762,907,502,828,35,635,40,405,407,826,263,964,595,697,205,426,978,618,180,182,646,327,160,161,904,392,839,305,276,686,515,769,71,629,61,177,433,966,954,366,653,760,536,0,306,869,543,70,739,138", +"738,777,422,738,195,191,198,543,279,373,94,59,500,346,414,137,529,755,59,212,313,53,138,259,79,71,570,142,824,99,474,466,542,30,407,441,996,215,257,281,359,420,142,23,447,326,748,352,535,22,845,87,90,763,143,997,62,867,645,788,448,721,382,13,219,522,597,35,601,900,223,15,117,521,662,740,929,788,418,496,710,172,348,710,636,329,774,183,729,276,214,755,886,295,327,547,621,867,519,949,246,280,78,471,251,215,46,984,185,925,46,354,679,883,914,344,958,402,788,421,300,198,993,886,753,654,613,919,959,307,533,462,902,157,829,563,973,894,188,498,223,51,691,864,257,984,732,580,905,999,835,868,694,629,574,96,129,213,89,981,929,304,250,637,705,467,821,975,635,793,581,775,535,306,167,152,401,918,882,695,150,87,618,580,271,573,825,518,600,161,165,395,637,937,187,588,500,439,298,451,903,883,910,43,860,291,224,54,340,388,477,339,645,242,221,561,662,102,622,33,116,605,108,80,987,71,718,524,58,399,946,348,508,744,866,233,787,1,824,183,63,878,586,991,831,125,914,720,860,158,826,310,296,691,301,217,967,435,750,744,148,902,783,452,690,531,267,265,474,392,104,707,141,696,653,265,884,346,703,295,586,595,216,218,538,739,877,70,162,663,839,692,409,689,75,799,41,495,660,45,907,288,607,58,194,716,636,192,354,132,922,250,319,590,4,119,971,652,752,646,308,820,376,118,563,817,698,340,66,717,484,385,551,55,364,502,436,845,967,949,228,653,963,267,430,393,388,235,881,633,312,873,633,713,112,201,242,642,514,257,300,853,996,436,695,105,392,456,973,953,492,882,925,718,336,737,47,574,924,449,888,237,368,133,853,493,773,589,220,803,950,653,782,781,827,43,4,843,210,706,49,213,394,964,73,16,681,708,279,58,80,638,780,128,926,873,984,492,47,724,934,140,306,632,767,658,375,810,764,268,63,918,283,911,60,489,176,720,909,146,892,731,63,630,350,627,529,360,639,633,838,427,342,372,867,114,666,592,993,738,905,183,409,850,326,720,944,233,7,250,266,945,267,690,830,566,302,997,418,518,411,795,423,941,75,235,518,342,813,719,504,863,717,661,318,43,351,175,225,922,423,329,48,311,61,786,756,362,813,779,114,621,28,727,384,670,561,445,983,358,597,191,543,163,814,603,641,79,199,565,413,986,913,243,983,117,381,562,235,647,788,986,277,651,307,14,966,693,912,38,811,244,647,61,85,959,688,133,319,404,73,949,19,729,695,427,531,770,455,701,732,362,473,357,834,139,219,791,558,262,531,601,186,80,939,455,478,169,712,900,112,748,122,161,353,461,831,986,119,798,801,309,100,244,716,365,421,611,456,821,481,237,883,195,978,164,747,772,703,134,266,757,129,427,325,938,934,751,951,257,340,623,718,11,791,423,850,890,656,872,985,225,940,13,367,113,419,445,221,950,864,82,98,724,214,543,787,279,486,764,919,504,258,154,764,339,630,286,645,342,138,453,818,390,71,394,816,915,993,11,517,181,272,636,271,322,700,705,746,830,154,411,995,394,858,629,106,224,365,190,978,876,587,241,981,484,410,55,918,287,156,848,187,102,571,9,459,201,76,284,580,758,502,416,660,639,36,545,299,178,854,427,989,67,807,846,814,2,388,840,684,340,307,11,530,996,513,133,736,389,879,168,45,382,602,698,588,194,601,619,316,428,467,84,617,599,76,873,172,798,10,202,229,313,557,203,901,360,935,704,107,427,937,964,669,329,958,918,648,793,850,111,247,753,655,581,247,259,443,934,61,8,821,527,496,554,491,185,218,308,548,133,158,485,525,90,319,186,833,925,137,680,590,537,863,433,433,981,437,712,6,94,209,415,51,524,449,416,4,129,600,270,846,194,292,299,840,808,377,204,707,573,21,937,358,538,638,149,515,509,383,847,397,48,80,138,24,297,120,817,333,499,103,545,487,939,136,757,83,997,52,974,86,852,22,920,874,674,999,79,230,946,856,115,753,252,76,653,907,788,31,409,652,284,301,439,421,419,271,642,423,502,968,126,78,995,619,960,437,421,129,62,40,551,113,491,843,774,988,605,922,703,369,222,370,800,271,553,818,342,396,727,765,260,819,759,704,35,338,178,565,173,631,926,897,747,311,730,959,674,740,997,793,472,681,213,314,369,444,539,340,169,729,334,699,28,250,186,385,418,426,174,668,760,750,97,506,848,383,886,851,213,220,306,0,594,607,823,46,234", +"250,470,227,191,588,89,834,926,878,295,105,286,311,353,349,796,570,250,847,148,317,366,632,852,412,722,945,972,510,541,227,972,102,317,947,142,250,188,342,220,14,151,20,997,465,542,885,941,137,101,378,84,635,790,62,869,741,743,344,288,186,948,20,190,554,873,717,245,586,998,285,945,667,705,93,784,83,722,517,416,469,393,839,98,431,186,767,250,226,420,880,47,101,936,131,309,778,419,293,421,543,934,230,778,934,638,70,103,444,879,369,151,898,307,331,370,450,307,391,324,23,644,404,937,959,779,101,215,49,487,296,629,172,185,197,129,293,449,901,919,33,880,574,552,118,150,7,265,711,93,59,941,353,387,950,269,389,943,656,182,698,124,904,112,601,927,83,866,577,679,831,163,374,228,891,63,274,211,332,786,401,157,81,181,338,444,458,3,743,147,392,638,777,959,398,537,864,42,568,222,175,279,246,476,543,955,887,859,979,699,109,845,189,659,72,716,698,367,743,614,312,914,685,404,755,958,108,144,828,76,237,369,429,855,901,365,977,491,759,485,71,572,325,341,624,401,466,750,549,910,309,971,766,507,841,937,514,730,26,856,607,649,397,474,557,470,925,2,309,277,364,633,827,95,269,732,502,650,209,463,771,111,134,533,955,614,787,805,464,690,701,16,646,931,32,333,464,277,168,518,299,727,177,592,940,566,527,333,274,715,350,770,206,162,495,820,894,842,455,904,111,114,529,692,635,236,761,25,229,152,189,585,512,249,382,865,117,826,744,801,438,349,164,942,421,932,163,329,970,108,412,428,467,397,953,664,78,747,831,983,713,476,736,73,329,821,113,232,676,721,552,326,459,187,517,833,952,896,900,460,908,561,538,650,817,210,7,948,379,567,274,719,897,566,103,138,571,845,407,292,497,588,115,77,15,302,895,856,85,679,371,308,286,999,595,513,406,465,259,56,955,101,780,49,603,587,777,313,247,22,669,845,198,701,318,940,439,987,573,633,23,957,240,96,207,618,701,603,671,437,334,314,672,898,606,662,782,183,676,769,492,386,561,836,777,286,377,562,135,498,709,770,555,398,476,32,765,93,675,604,165,657,184,741,862,385,794,548,198,417,537,619,917,525,353,477,386,167,207,541,84,33,164,945,338,71,702,193,501,545,201,473,893,809,918,600,952,854,573,845,102,38,772,912,428,129,469,364,394,332,407,775,229,252,177,759,542,21,894,600,906,705,460,791,474,372,572,770,846,284,563,119,146,750,609,98,410,653,564,117,547,92,353,158,336,623,456,816,527,861,339,534,267,904,256,747,95,939,469,984,20,426,581,745,791,927,928,458,630,252,184,194,965,891,588,538,36,833,159,179,163,286,606,440,81,933,556,994,523,261,986,101,551,94,166,915,385,179,245,119,234,877,803,994,881,955,587,773,195,958,296,192,404,28,397,224,368,644,183,915,614,787,627,462,732,800,131,428,681,2,649,395,942,635,235,240,237,71,373,745,421,694,489,757,441,668,677,548,993,862,455,879,891,464,820,324,830,332,712,675,364,682,591,5,736,335,986,3,497,705,272,954,568,928,667,443,250,218,2,251,219,717,495,612,966,183,782,555,867,687,170,119,269,638,388,283,863,604,852,887,811,622,901,28,660,758,312,555,969,192,903,187,623,648,663,3,116,189,303,952,640,987,746,614,866,934,356,965,253,83,991,363,577,51,181,988,780,524,768,252,995,393,394,18,100,843,762,323,103,424,510,92,198,6,787,934,34,141,488,76,684,414,767,458,515,547,784,508,438,955,230,491,468,974,811,20,723,349,11,80,323,82,616,855,85,781,769,682,991,207,516,869,230,899,892,510,339,22,460,72,690,150,225,154,129,207,473,58,968,151,869,429,312,242,468,332,338,712,614,515,191,84,380,983,338,126,646,272,301,700,188,213,146,506,354,419,231,920,829,291,863,169,91,888,999,879,992,623,463,125,234,517,302,472,346,918,564,964,868,726,95,535,200,235,274,227,995,667,302,687,300,75,72,302,333,286,225,838,276,822,34,79,872,186,265,200,984,613,90,181,372,326,93,890,805,98,304,977,738,834,549,808,474,67,136,532,997,61,86,613,675,714,768,188,116,99,169,245,520,647,588,353,292,290,321,186,144,440,268,570,387,352,722,627,443,150,878,10,455,920,93,52,295,5,766,98,482,785,986,411,350,806,853,636,734,663,251,352,487,513,643,659,858,565,648,286,779,984,375,101,673,714,501,869,594,0,718,226,115,140", +"949,233,581,136,558,761,984,692,552,501,113,889,890,938,545,278,443,44,425,11,400,208,795,559,556,894,753,722,200,396,499,390,929,756,739,826,984,750,915,154,45,476,675,387,811,846,942,920,924,101,960,738,992,218,791,336,734,280,942,468,299,766,923,272,335,872,207,232,131,86,177,61,676,756,88,202,904,14,638,775,216,815,956,995,444,896,28,593,416,727,506,929,569,239,509,22,316,324,490,533,941,70,24,996,798,835,913,329,61,271,527,147,180,925,358,711,81,619,444,362,163,139,353,925,634,237,730,135,509,612,86,269,794,684,138,753,514,937,161,716,171,627,145,124,767,282,629,449,276,524,665,65,866,47,953,512,761,384,272,511,744,491,66,400,857,366,981,58,643,401,595,188,530,273,380,603,716,651,15,106,81,365,559,667,912,38,738,605,559,16,360,207,421,314,222,673,31,507,173,483,215,203,398,516,220,68,389,557,768,884,623,203,627,963,188,294,230,866,768,170,326,277,197,813,845,36,588,138,978,874,913,810,544,669,617,746,392,227,860,514,395,264,606,260,416,184,565,23,649,606,474,293,407,568,151,577,58,463,818,547,623,140,493,535,978,619,966,269,831,173,712,62,794,537,590,981,904,529,452,711,641,273,200,565,681,379,736,532,38,515,958,934,116,925,851,500,600,614,147,817,846,215,381,149,471,119,230,832,282,398,315,626,913,964,633,732,166,155,932,449,774,294,900,265,423,541,204,50,465,554,581,210,928,754,766,488,241,977,401,655,488,342,473,371,751,767,711,367,15,181,276,501,411,597,864,874,883,126,652,39,353,947,586,65,945,22,668,199,600,899,517,999,860,720,71,917,614,864,863,325,886,223,529,70,302,86,356,749,943,940,864,682,756,710,122,15,685,740,489,418,331,505,386,246,682,439,365,950,536,877,457,885,830,528,872,128,738,716,340,644,350,954,811,480,165,9,371,304,193,398,318,460,351,750,739,898,535,852,706,226,946,336,764,975,941,505,757,14,75,625,613,664,67,562,961,430,189,321,207,46,796,511,668,912,281,1,874,126,966,512,780,728,722,761,812,263,860,846,551,733,217,624,734,640,194,647,24,500,523,972,19,165,22,961,711,667,670,631,173,154,343,782,384,531,912,525,55,903,24,158,8,769,158,560,595,948,992,302,571,697,732,637,197,514,66,578,551,751,67,389,457,913,458,542,740,720,682,156,677,571,888,512,558,186,972,644,481,651,750,977,897,216,496,557,50,91,736,661,333,291,455,42,151,5,413,412,108,813,706,957,113,568,217,683,339,634,656,78,299,678,155,943,575,882,120,194,464,24,931,90,11,857,137,18,487,617,116,670,474,766,266,642,171,132,196,155,536,559,973,128,421,756,586,426,588,118,102,811,326,750,586,888,830,152,592,949,144,24,557,868,274,79,810,101,841,398,173,909,387,448,503,725,749,520,426,952,667,853,18,415,894,222,577,291,136,433,42,701,963,72,532,201,836,165,652,323,391,854,959,887,667,145,522,132,739,804,359,90,531,791,825,772,101,254,274,876,876,228,507,502,336,377,501,189,605,252,405,70,423,80,805,529,511,94,345,488,160,454,104,328,592,149,499,16,500,913,269,527,609,33,258,184,508,384,497,748,35,397,125,771,585,131,322,326,546,263,462,345,278,469,503,964,191,628,391,957,459,389,956,204,328,107,394,700,157,356,291,953,154,385,397,977,33,193,348,162,599,853,679,976,645,534,656,853,708,41,177,22,527,634,729,265,940,492,262,305,215,26,786,232,886,766,311,956,782,3,541,500,639,953,663,440,129,316,529,553,870,432,904,706,952,185,550,281,978,247,379,38,330,754,131,705,348,553,723,131,316,694,664,402,973,399,386,74,105,326,986,657,773,627,916,186,941,77,867,946,876,277,486,584,951,609,999,908,231,593,344,266,300,408,623,250,839,584,98,382,394,805,58,530,942,714,19,64,659,781,699,519,214,187,149,423,198,858,812,791,14,398,122,311,196,491,975,218,334,952,983,123,261,682,242,918,509,560,447,197,872,993,93,539,201,145,991,138,184,590,262,211,543,584,114,559,492,399,586,669,950,118,33,874,807,66,937,997,291,271,83,831,620,472,571,249,304,586,289,231,858,442,189,96,150,755,662,552,315,711,987,952,182,917,826,308,1,259,467,620,348,751,895,487,735,171,818,815,350,484,119,162,284,167,518,974,141,360,97,390,37,858,470,554,292,470,595,543,607,718,0,111,148,996", +"264,547,470,994,952,182,953,111,249,346,50,744,142,415,824,7,314,258,998,943,54,865,664,243,623,213,250,844,475,347,518,668,488,635,102,696,757,537,995,887,687,415,715,259,474,547,9,953,388,970,213,30,279,177,574,152,255,501,898,55,796,82,53,163,355,22,795,514,661,537,48,403,583,234,720,348,402,869,343,81,279,604,911,848,89,999,996,112,218,40,711,800,8,533,268,649,313,229,520,160,914,448,983,454,947,191,611,54,193,378,32,256,498,193,893,945,200,289,98,307,74,141,583,483,925,978,311,473,959,530,404,970,237,456,835,201,826,919,551,890,168,461,932,877,700,832,111,917,351,509,136,950,205,564,284,101,787,308,782,166,115,134,48,570,838,544,42,831,983,525,201,678,385,599,755,155,859,179,792,437,348,816,561,885,412,907,799,538,621,294,298,456,253,486,332,942,885,736,304,438,492,602,639,682,147,672,253,428,529,987,334,807,543,657,413,938,142,543,934,805,708,983,6,52,532,867,198,506,817,813,378,542,626,914,30,563,644,454,290,535,687,480,7,588,510,197,999,185,731,210,2,565,251,509,923,923,992,919,679,448,650,136,492,868,493,351,477,11,704,676,637,140,758,856,888,880,669,63,224,39,411,507,314,517,346,921,542,953,732,262,825,524,301,2,713,801,76,841,347,17,831,62,921,950,151,557,476,401,590,59,566,446,489,327,386,103,531,976,817,21,819,519,784,311,678,536,79,250,628,171,43,838,461,889,161,147,714,685,410,720,826,360,776,963,653,796,466,295,365,997,585,180,712,547,455,419,200,838,26,89,515,416,370,574,583,764,580,157,337,771,877,360,579,381,451,868,715,255,940,641,110,935,23,726,393,850,342,893,148,399,657,235,774,685,899,491,103,992,792,272,872,626,598,403,685,295,234,591,32,890,283,734,586,779,242,660,630,87,32,188,961,85,954,898,525,86,177,455,663,976,641,219,465,985,989,452,948,670,654,657,159,962,37,704,933,381,938,188,236,878,280,568,911,184,976,625,603,511,526,756,136,842,545,720,938,952,226,135,51,256,316,245,96,313,243,438,849,172,517,203,229,487,320,179,494,978,248,85,329,486,601,30,49,811,356,617,138,850,622,287,108,574,554,709,990,61,392,388,702,990,19,551,51,623,953,990,430,253,50,752,527,946,175,957,804,840,859,600,634,555,364,154,398,980,512,81,360,216,311,560,26,458,626,957,948,594,356,954,591,268,92,242,39,987,270,886,516,388,266,552,600,749,611,943,109,97,76,806,91,515,897,354,108,315,416,472,671,411,127,354,106,777,992,495,875,674,617,507,620,818,608,323,436,97,926,839,25,831,185,843,150,909,415,342,33,23,856,23,972,127,981,916,441,286,488,93,862,155,843,795,640,530,271,96,513,73,680,839,16,543,611,816,424,450,941,558,909,872,725,654,299,647,644,484,24,20,628,462,226,130,937,868,982,452,789,156,231,907,701,63,241,387,353,860,520,831,779,487,242,67,789,710,976,204,353,821,960,181,114,478,224,138,155,469,547,948,261,878,973,10,475,437,418,424,144,674,635,196,268,376,456,370,727,652,931,997,450,371,496,180,664,105,854,462,407,561,86,110,320,772,27,197,386,75,880,958,136,475,331,401,816,877,690,293,252,28,987,113,273,66,53,947,120,440,211,813,265,714,775,347,720,781,745,929,950,43,148,558,481,60,598,517,667,940,594,283,11,185,587,876,289,175,940,349,833,673,462,655,276,706,428,898,832,563,350,12,680,865,168,135,195,242,13,389,101,50,799,684,537,76,159,922,859,928,407,737,774,847,143,118,293,48,965,977,443,525,370,48,594,795,640,511,539,464,281,47,654,745,876,7,162,991,306,458,180,5,884,518,892,56,166,328,166,438,844,311,724,747,403,216,651,111,82,975,291,110,854,271,145,995,545,471,804,228,125,11,592,244,343,949,253,745,50,89,65,675,323,729,430,90,648,396,835,389,740,741,444,117,596,110,634,625,445,693,564,134,806,505,79,684,39,167,560,680,739,545,259,942,56,392,347,931,862,239,492,496,869,502,780,269,220,588,744,797,245,629,44,616,580,485,550,636,93,617,929,925,990,537,393,124,505,898,418,90,233,988,816,38,79,884,746,68,688,239,3,22,263,464,971,744,630,776,916,336,932,263,634,442,747,106,603,308,732,36,895,443,773,957,323,391,150,422,230,936,39,316,169,268,836,676,869,259,482,70,823,226,111,0,125,756", +"995,913,328,706,887,869,356,754,407,12,632,711,346,732,765,696,937,478,201,838,888,341,490,17,78,9,919,469,860,216,946,38,507,69,937,229,512,763,985,587,111,224,595,91,714,733,126,292,888,958,273,799,287,816,199,415,216,923,67,571,128,111,273,607,584,903,919,272,67,610,989,582,765,601,367,376,10,68,857,259,993,469,334,191,419,993,880,459,284,628,498,131,204,29,936,430,52,569,559,3,860,360,715,124,93,846,211,291,989,560,309,730,223,294,241,827,912,23,183,403,517,838,643,101,383,292,366,712,313,805,495,936,516,674,383,564,974,658,339,935,153,458,595,275,286,97,126,172,170,503,486,665,578,917,648,123,589,861,968,742,283,460,64,596,789,116,173,392,788,907,330,667,726,302,554,92,234,553,108,110,963,129,796,201,576,647,751,28,892,476,749,409,944,541,637,291,973,771,386,561,792,270,453,691,807,808,246,877,448,576,190,267,691,153,592,44,969,980,869,99,283,385,917,101,20,954,126,402,141,573,919,549,482,438,657,267,914,816,551,321,637,504,172,716,111,322,764,636,539,185,167,474,224,707,913,407,561,413,185,297,85,549,951,137,614,769,888,350,938,606,550,343,154,840,652,99,133,126,68,281,383,211,481,278,628,654,973,779,591,280,608,567,706,150,310,682,740,618,198,845,481,280,671,164,958,983,73,654,40,998,362,979,690,970,857,821,605,623,890,90,537,414,512,869,974,956,719,282,308,835,705,715,736,792,758,663,613,964,469,911,107,653,508,680,591,76,429,766,673,630,599,740,244,645,16,146,45,216,641,931,925,912,384,863,152,457,20,479,980,836,165,443,212,346,377,494,57,970,323,660,444,78,999,256,696,482,607,86,351,145,471,424,245,973,853,114,260,836,115,246,213,442,959,593,136,896,326,873,51,413,536,781,398,859,606,532,515,551,36,424,574,558,291,493,801,800,977,627,551,409,347,302,905,190,778,766,564,645,324,455,932,633,372,773,784,777,113,290,199,452,621,413,698,507,357,822,28,208,379,830,482,166,803,666,82,959,925,990,646,210,630,164,842,381,320,364,411,959,142,199,375,741,732,714,159,712,450,290,66,589,986,99,180,536,482,888,972,524,900,846,325,321,854,458,747,649,542,672,977,266,748,924,752,701,69,693,535,990,568,170,78,564,941,278,446,35,214,103,136,675,282,550,690,680,308,68,952,938,665,499,106,524,70,827,254,159,364,960,565,839,450,616,143,887,894,760,105,386,974,418,199,710,928,277,108,418,287,142,586,579,670,345,567,542,849,954,675,591,453,964,705,701,427,46,596,322,11,633,952,929,196,882,71,585,513,758,218,924,853,331,53,151,23,392,519,825,784,978,53,566,306,897,213,812,371,49,104,184,173,858,438,703,798,777,667,837,867,773,870,415,526,677,795,204,142,268,447,351,313,706,260,986,51,207,14,412,153,612,130,718,570,327,245,784,111,649,616,798,214,324,52,859,578,710,864,276,723,954,515,646,842,499,350,793,468,77,272,363,110,259,417,516,523,507,691,728,482,979,152,806,335,299,667,51,802,594,572,582,329,499,99,372,714,380,352,860,671,787,228,766,350,613,639,966,78,325,294,440,504,674,185,277,820,221,778,123,871,29,391,228,243,764,974,824,348,404,437,172,798,681,871,888,351,752,123,212,710,603,264,133,591,711,750,683,756,715,143,106,647,525,778,574,31,348,514,269,36,181,130,789,133,784,13,738,139,74,880,540,446,530,991,61,115,276,781,94,775,337,286,582,876,797,958,296,258,799,761,603,150,889,926,524,62,671,63,155,732,292,166,848,350,764,994,470,586,906,599,29,596,960,746,632,117,292,354,442,485,206,212,671,281,690,507,603,417,308,42,481,156,274,768,318,432,462,997,933,74,527,84,569,916,96,246,723,735,805,942,657,376,932,767,135,13,976,572,852,191,439,455,677,606,974,324,184,156,896,607,934,740,648,231,846,772,255,608,87,134,864,624,100,795,665,69,819,832,844,510,231,458,616,91,496,976,208,675,144,455,689,417,666,314,4,667,634,575,906,565,577,289,241,529,657,702,832,64,774,897,766,571,298,479,264,762,508,923,580,569,842,666,906,88,456,8,11,908,910,135,973,994,57,378,886,45,172,24,403,579,771,673,743,195,927,324,974,420,866,783,459,819,196,302,205,757,346,850,734,189,406,423,41,101,769,29,719,57,144,778,945,512,72,264,629,893,739,46,115,148,125,0,178", +"873,804,976,299,90,282,615,299,823,509,738,437,999,899,501,303,758,899,69,148,774,947,127,83,684,438,756,264,851,423,653,22,979,697,938,476,835,349,915,966,543,921,590,967,536,647,303,665,776,407,861,136,956,895,714,816,95,248,232,469,342,863,439,446,5,597,578,554,817,694,280,785,433,895,943,111,838,776,945,718,38,592,387,416,150,191,159,679,468,640,82,205,520,91,777,692,275,944,185,906,451,254,461,770,778,253,469,419,250,439,573,600,15,197,465,187,269,872,433,387,560,262,280,665,741,90,735,233,103,641,808,457,944,853,496,38,190,623,124,160,152,872,214,844,868,835,99,147,224,600,328,457,211,453,287,716,216,642,327,47,738,983,570,503,554,235,52,392,409,532,155,563,142,996,683,596,14,351,778,821,564,492,48,344,967,595,861,884,472,531,503,973,116,849,500,944,757,127,67,48,216,361,224,444,479,733,503,356,159,802,964,185,200,690,456,444,447,123,819,784,461,196,430,627,883,260,956,882,747,861,452,255,324,627,644,642,181,823,801,167,366,878,369,792,451,561,244,825,81,905,894,612,576,432,169,776,105,184,181,572,598,807,415,777,188,358,587,921,402,84,784,180,491,220,957,260,207,259,3,875,895,910,605,976,72,786,275,350,858,464,655,829,145,769,725,362,719,880,941,521,595,754,565,605,371,403,459,394,33,763,856,793,356,481,16,297,974,188,248,960,639,524,876,993,791,460,136,83,783,834,165,358,377,195,873,773,242,297,711,232,711,208,201,18,154,88,983,592,35,102,83,696,522,215,404,315,66,673,651,235,397,271,588,54,143,940,689,584,573,505,210,293,418,471,887,961,185,724,361,77,587,699,702,220,394,838,526,560,286,325,612,826,280,881,80,804,184,866,403,404,250,682,522,953,408,199,189,127,477,132,386,648,404,585,177,356,603,523,370,555,398,670,832,533,481,796,966,30,718,178,308,351,863,796,188,132,289,588,713,47,140,785,829,719,796,601,487,497,605,474,298,1000,948,417,957,463,123,411,636,420,379,666,804,772,375,714,64,75,905,710,621,839,758,927,97,210,543,57,130,917,285,456,36,479,789,144,517,730,647,100,889,114,922,473,140,145,699,775,338,429,402,563,20,413,257,214,274,151,256,226,297,293,920,272,366,627,587,622,542,910,23,487,766,340,918,898,703,215,182,878,273,645,126,619,628,35,405,846,938,200,259,282,839,349,225,397,940,177,212,571,600,517,678,318,494,246,835,382,245,292,24,849,446,972,551,486,13,629,649,769,60,159,421,574,95,550,814,910,383,294,405,556,329,983,382,823,958,271,882,557,601,150,159,340,610,727,756,647,292,300,637,299,87,517,677,498,672,697,749,659,94,288,209,498,865,630,322,988,46,266,53,461,829,892,761,428,478,445,759,561,82,196,280,773,149,672,298,188,156,974,883,593,271,672,385,396,362,94,186,835,660,735,961,803,451,387,162,513,421,687,355,746,599,705,137,55,292,378,833,63,71,555,667,343,327,253,705,242,209,343,964,929,803,292,506,117,254,844,165,783,523,30,778,284,248,831,477,156,9,753,184,104,420,760,771,242,791,729,658,984,539,111,521,488,367,682,660,964,585,600,539,320,313,414,175,703,438,484,448,237,566,79,243,198,831,761,494,12,62,169,395,501,251,627,44,929,531,699,38,462,849,383,193,902,599,521,597,176,112,469,267,460,374,613,331,823,113,10,67,333,833,280,779,900,428,264,501,260,813,872,796,543,855,876,710,282,654,734,156,114,444,930,343,769,369,366,637,377,289,768,584,783,819,762,991,515,887,891,81,104,50,325,650,806,425,259,61,274,376,868,643,721,931,732,877,500,140,84,487,316,818,608,310,789,288,818,522,513,297,255,467,89,768,331,778,227,890,11,213,374,274,51,616,181,950,39,778,495,892,981,142,886,484,1000,205,498,773,209,168,929,899,38,421,838,199,468,967,33,751,760,480,757,242,921,826,765,160,604,184,935,562,618,829,61,824,939,506,997,201,605,265,463,499,862,406,232,3,780,625,286,465,529,121,462,751,131,589,587,107,35,972,560,297,130,947,814,724,519,243,246,422,860,920,916,353,639,909,456,510,577,616,566,973,24,661,578,481,899,798,145,225,983,251,561,990,773,555,890,581,632,883,992,38,67,688,798,721,247,91,756,857,873,484,813,710,100,29,235,687,526,714,853,365,181,929,502,235,317,405,890,19,120,939,138,234,140,996,756,178,0"] + + private lazy var graph = parseData(content) + + func solve() { + Greedy(graph).solve() + } +} diff --git a/kotlin-native/performance/KotlinVsSwift/ring/src/InlineBenchmark.swift b/kotlin-native/performance/KotlinVsSwift/ring/src/InlineBenchmark.swift new file mode 100644 index 00000000000..d0fc0cd2c39 --- /dev/null +++ b/kotlin-native/performance/KotlinVsSwift/ring/src/InlineBenchmark.swift @@ -0,0 +1,60 @@ +/* + * Copyright 2010-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +import Foundation + +func load(_ value: Int, _ size: Int) -> Int { + var acc = 0 + for _ in 0...size { + acc = acc ^ value.hashValue + } + return acc +} + +@inlinable +func loadInline(_ value: Int, _ size: Int) -> Int { + var acc = 0 + for _ in 0...size { + acc = acc ^ value.hashValue + } + return acc +} + +func loadGeneric(_ value: T, _ size: Int) -> Int { + var acc = 0 + for _ in 0...size { + acc = acc ^ value.hashValue + } + return acc +} + +@inlinable +func loadGenericInline(_ value: T, _ size: Int) -> Int { + var acc = 0 + for _ in 0...size { + acc = acc ^ value.hashValue + } + return acc +} + +open class InlineBenchmark { + private var value = 2138476523 + + func calculate() -> Int { + return load(value, Constants.BENCHMARK_SIZE) + } + + func calculateInline() -> Int { + return loadInline(value, Constants.BENCHMARK_SIZE) + } + + func calculateGeneric() -> Int { + return loadGeneric(value, Constants.BENCHMARK_SIZE) + } + + func calculateGenericInline() -> Int { + return loadGenericInline(value, Constants.BENCHMARK_SIZE) + } +} diff --git a/kotlin-native/performance/KotlinVsSwift/ring/src/IntArrayBenchmark.swift b/kotlin-native/performance/KotlinVsSwift/ring/src/IntArrayBenchmark.swift new file mode 100644 index 00000000000..1ac324d3135 --- /dev/null +++ b/kotlin-native/performance/KotlinVsSwift/ring/src/IntArrayBenchmark.swift @@ -0,0 +1,146 @@ +/* + * Copyright 2010-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +import Foundation + +class IntArrayBenchmark { + private var _data: [Int]? = nil + var data: [Int] { + get { + return _data! + } + } + + init() { + var list: [Int] = [] + list.reserveCapacity(Constants.BENCHMARK_SIZE) + for n in intValues(Constants.BENCHMARK_SIZE) { + list.append(n) + } + _data = list + } + + func copy() -> [Int] { + return Array(data) + } + + func copyManual() -> [Int] { + var list: [Int] = [] + for item in data { + list.append(item) + } + return list + } + + func filterAndCount() -> Int { + return data.filter { filterLoad($0) }.count + } + + func filterSomeAndCount() -> Int { + return data.filter { Ring.filterSome($0) }.count + } + + func filterAndMap() -> [String] { + return data.filter { filterLoad($0) }.map { mapLoad($0) } + } + + func filterAndMapManual() -> [String] { + var list: [String] = [] + for it in data { + if (filterLoad(it)) { + let value = mapLoad(it) + list.append(value) + } + } + return list + } + + func filter() -> [Int] { + return data.filter { filterLoad($0) } + } + + func filterSome() -> [Int] { + return data.filter { Ring.filterSome($0) } + } + + func filterPrime() -> [Int] { + return data.filter { Ring.filterPrime($0) } + } + + func filterManual() -> [Int] { + var list: [Int] = [] + for it in data { + if (filterLoad(it)) { + list.append(it) + } + } + return list + } + + func filterSomeManual() -> [Int] { + var list: [Int] = [] + for it in data { + if (Ring.filterSome(it)) { + list.append(it) + } + } + return list + } + + func countFilteredManual() -> Int { + var count = 0 + for it in data { + if (filterLoad(it)) { + count += 1 + } + } + return count + } + + func countFilteredSomeManual() -> Int { + var count = 0 + for it in data { + if (Ring.filterSome(it)) { + count += 1 + } + } + return count + } + + func countFilteredPrimeManual() -> Int { + var count = 0 + for it in data { + if (Ring.filterPrime(it)) { + count += 1 + } + } + return count + } + + func countFiltered() -> Int { + return data.count { filterLoad($0) } + } + + func countFilteredSome() -> Int { + return data.count { Ring.filterSome($0) } + } + + func countFilteredPrime() -> Int { + let res = data.count { Ring.filterPrime($0) } + return res + } + + func countFilteredLocal() -> Int { + return data.cnt { filterLoad($0) } + } + + func countFilteredSomeLocal() -> Int { + return data.cnt { Ring.filterSome($0) } + } + + func reduce() -> Int { + return data.reduce(0) { if (filterLoad($1)) { return $0 + 1 } else { return $0 } } + } +} diff --git a/kotlin-native/performance/KotlinVsSwift/ring/src/IntBaselineBenchmark.swift b/kotlin-native/performance/KotlinVsSwift/ring/src/IntBaselineBenchmark.swift new file mode 100644 index 00000000000..08fff35d2dc --- /dev/null +++ b/kotlin-native/performance/KotlinVsSwift/ring/src/IntBaselineBenchmark.swift @@ -0,0 +1,30 @@ +/* + * Copyright 2010-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +import Foundation + +class IntBaselineBenchmark { + + func consume() { + for item in 1...Constants.BENCHMARK_SIZE { + Blackhole.consume(item) + } + } + + func allocateArray() -> [Int] { + var list: [Int] = [] + list.reserveCapacity(Constants.BENCHMARK_SIZE) + return list + } + + func allocateArrayAndFill() -> [Int] { + var list: [Int] = [] + list.reserveCapacity(Constants.BENCHMARK_SIZE) + for item in 1...Constants.BENCHMARK_SIZE { + list.append(item) + } + return list + } +} diff --git a/kotlin-native/performance/KotlinVsSwift/ring/src/IntStreamBenchmark.swift b/kotlin-native/performance/KotlinVsSwift/ring/src/IntStreamBenchmark.swift new file mode 100644 index 00000000000..3f6994868e3 --- /dev/null +++ b/kotlin-native/performance/KotlinVsSwift/ring/src/IntStreamBenchmark.swift @@ -0,0 +1,90 @@ +/* + * Copyright 2010-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +import Foundation + +class IntStreamBenchmark { + private var _data: AnySequence? = nil + var data: AnySequence { + return _data! + } + + init() { + _data = AnySequence(intValues(Constants.BENCHMARK_SIZE)) + } + + func copy() -> [Int] { + return Array(data) + } + + func copyManual() -> [Int] { + var list: [Int] = [] + for item in data.lazy { + list.append(item) + } + return list + } + + func filterAndCount() -> Int { + return data.lazy.filter { filterLoad($0) }.count + } + + func filterAndMap() { + for item in (data.lazy.filter { filterLoad($0) }.map { mapLoad($0) }) { + Blackhole.consume(item) + } + } + + func filterAndMapManual() { + for it in data.lazy { + if (filterLoad(it)) { + let item = mapLoad(it) + Blackhole.consume(item) + } + } + } + + func filter() { + for item in (data.lazy.filter { filterLoad($0) }) { + Blackhole.consume(item) + } + } + + func filterManual() { + for it in data.lazy { + if (filterLoad(it)) { + Blackhole.consume(it) + } + } + } + + func countFilteredManual() -> Int { + var count = 0 + for it in data.lazy { + if (filterLoad(it)) { + count += 1 + } + } + return count + } + + func countFiltered() -> Int { + return data.lazy.count { filterLoad($0) } + } + + func countFilteredLocal() -> Int { + return data.lazy.cnt { filterLoad($0) } + } + + func reduce() -> Int { + return data.lazy.reduce(0) { if (filterLoad($1)) { return $0 + 1 } else {return $0 } } + } +} + +extension LazySequence { + func count(where test: (Element) throws -> Bool) rethrows -> Int { + return try self.filter(test).count + } +} diff --git a/kotlin-native/performance/KotlinVsSwift/ring/src/LambdaBenchmark.swift b/kotlin-native/performance/KotlinVsSwift/ring/src/LambdaBenchmark.swift new file mode 100644 index 00000000000..daf930c3e5d --- /dev/null +++ b/kotlin-native/performance/KotlinVsSwift/ring/src/LambdaBenchmark.swift @@ -0,0 +1,91 @@ +/* + * Copyright 2010-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +import Foundation + +class LambdaBenchmark { + @inlinable + public func runLambda(_ x: () -> T) -> T { + return x() + } + + private func runLambdaNoInline(_ x: () -> T) -> T { + return x() + } + + init() { + Constants.globalAddendum = Int.random(in: 0 ..< 20) + } + + func noncapturingLambda() -> Int { + var x: Int = 0 + for _ in 0...Constants.BENCHMARK_SIZE { + x += runLambda { Constants.globalAddendum } + } + return x + } + + func noncapturingLambdaNoInline() -> Int { + var x: Int = 0 + for _ in 0...Constants.BENCHMARK_SIZE { + x += runLambdaNoInline { Constants.globalAddendum } + } + return x + } + + func capturingLambda() -> Int { + let addendum = Constants.globalAddendum + 1 + var x: Int = 0 + for _ in 0...Constants.BENCHMARK_SIZE { + x += runLambda { addendum } + } + return x + } + + func capturingLambdaNoInline() -> Int { + let addendum = Constants.globalAddendum + 1 + var x: Int = 0 + for _ in 0...Constants.BENCHMARK_SIZE { + x += runLambdaNoInline { addendum } + } + return x + } + + func mutatingLambda() -> Int { + var x: Int = 0 + for _ in 0...Constants.BENCHMARK_SIZE { + runLambda { x += Constants.globalAddendum } + } + return x + } + + func mutatingLambdaNoInline() -> Int { + var x: Int = 0 + for _ in 0...Constants.BENCHMARK_SIZE { + runLambdaNoInline { x += Constants.globalAddendum } + } + return x + } + + func methodReference() -> Int { + var x: Int = 0 + for _ in 0...Constants.BENCHMARK_SIZE { + x += runLambda(referenced) + } + return x + } + + func methodReferenceNoInline() -> Int { + var x: Int = 0 + for _ in 0...Constants.BENCHMARK_SIZE { + x += runLambdaNoInline(referenced) + } + return x + } +} + +private func referenced() -> Int { + return Constants.globalAddendum +} diff --git a/kotlin-native/performance/KotlinVsSwift/ring/src/LoopBenchmark.swift b/kotlin-native/performance/KotlinVsSwift/ring/src/LoopBenchmark.swift new file mode 100644 index 00000000000..32e70141d7f --- /dev/null +++ b/kotlin-native/performance/KotlinVsSwift/ring/src/LoopBenchmark.swift @@ -0,0 +1,49 @@ +/* + * Copyright 2010-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +import Foundation + +class LoopBenchmark { + var array: [Value] + + init() { + var list: [Value] = [] + for n in classValues(Constants.BENCHMARK_SIZE) { + list.append(n) + } + array = list + } + + func arrayLoop() { + for x in array { + Blackhole.consume(x) + } + } + + func arrayIndexLoop() { + for i in array.indices { + Blackhole.consume(array[i]) + } + } + + func rangeLoop() { + for i in 0...Constants.BENCHMARK_SIZE { + Blackhole.consume(i) + } + } + + func arrayWhileLoop() { + var i = 0 + let s = array.count + while (i < s) { + Blackhole.consume(array[i]) + i += 1 + } + } + + func arrayForeachLoop() { + array.forEach { Blackhole.consume($0) } + } +} diff --git a/kotlin-native/performance/KotlinVsSwift/ring/src/MatrixMapBenchmark.swift b/kotlin-native/performance/KotlinVsSwift/ring/src/MatrixMapBenchmark.swift new file mode 100644 index 00000000000..60dd18fc13e --- /dev/null +++ b/kotlin-native/performance/KotlinVsSwift/ring/src/MatrixMapBenchmark.swift @@ -0,0 +1,80 @@ +/* + * Copyright 2010-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +import Foundation + +class Pair: Hashable { + + init(_ pair: (Int, Int)) { + self.pair = pair + } + + public var pair: (Int, Int) + public func hash(into hasher: inout Hasher) { + hasher.combine(pair.0) + hasher.combine(pair.1) + } + + public static func == (lhs: Pair, rhs: Pair) -> Bool { + return lhs.pair == rhs.pair + } + + public var hashValue: Int { + var hasher = Hasher() + self.hash(into: &hasher) + return hasher.finalize() + } +} + +class KMatrix { + let rows: Int + let columns: Int + internal init(_ rows: Int, _ columns: Int) { + self.rows = rows + self.columns = columns + for row in 0...rows-1 { + for col in 0...columns-1 { + matrix[Pair((row, col))] = Double.random(in: 0 ..< 100) + } + } + } + + private var matrix: [Pair: Double] = [:] + + func get(row: Int, col: Int) -> Double { + return get(Pair((row, col))) + } + + func get(_ pair: Pair) -> Double { + return matrix[pair] ?? 0.0 + } + + func put(_ pair: Pair, _ elem: Double) { + matrix[pair] = elem + } + + static func +=(lhs: inout KMatrix, rhs:KMatrix) { + for entry in lhs.matrix { + lhs.put(entry.key, entry.value + rhs.get(entry.key)) + } + } +} + +class MatrixMapBenchmark { + + func add() -> KMatrix { + var rows = Constants.BENCHMARK_SIZE + var cols = 1 + while (rows > cols) { + rows /= 2 + cols *= 2 + } + var a = KMatrix(rows, cols) + let b = KMatrix(rows, cols) + a += b + return a + } + +} diff --git a/kotlin-native/performance/KotlinVsSwift/ring/src/OctoTest.swift b/kotlin-native/performance/KotlinVsSwift/ring/src/OctoTest.swift new file mode 100644 index 00000000000..93bf68d6b2c --- /dev/null +++ b/kotlin-native/performance/KotlinVsSwift/ring/src/OctoTest.swift @@ -0,0 +1,219 @@ +/* + * Copyright 2010-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +import Foundation + +struct UnsupportedOperationException: Error { + let message: String + +} + +class Leaf : NodeEntity, Equatable { + static func == (lhs: Leaf, rhs: Leaf) -> Bool { + return lhs.value == rhs.value + } + + var value: T + + init(_ value: T) { + self.value = value + } + + override func toString() -> String { + return "L{$value}" + } +} + +class NodeEntity: Node { + func toString() -> String { + return "" + } + + func set(x: Int, y: Int, z: Int, value: T, depth: Int) throws -> Bool { + throw UnsupportedOperationException(message: "set on Leaf element") + } +} + +private protocol Node { + associatedtype T + + func set(x: Int, y: Int, z: Int, value: T, depth: Int) throws -> Bool + func toString() -> String +} + +class Branch : NodeEntity { + var nodes = [NodeEntity?](repeating: nil, count: 8) + + override init() {} + + init(_ value: T, _ exclude: Int) { + var i = 0 + while (i < 8) { + if (i != exclude) { + nodes[i] = Leaf(value) + } + i += 1 + } + } + + private func canClusterize(_ value: T) -> Bool { + var i = 0 + while (i < 8) { + let w = nodes[i] + if (w == nil || !(w is Leaf) || value != (w as? Leaf)?.value) { + return false + } + i += 1 + } + return true + } + + override func set(x: Int, y: Int, z: Int, value: T, depth: Int) throws -> Bool { + let branchIndex = OctoTree.number(x, y, z, depth) + let node = nodes[branchIndex] + if (node == nil) { + if (depth == 0) { + nodes[branchIndex] = Leaf(value) + return canClusterize(value) + } else { + nodes[branchIndex] = Branch() + } + } else if let leaf = node as? Leaf { + if (leaf.value == value) { + return false + } else if (depth == 0) { + leaf.value = value + return canClusterize(value) + } + nodes[branchIndex] = Branch(leaf.value, OctoTree.number(x, y, z, depth - 1)) + } + + if (try nodes[branchIndex]!.set(x: x, y: y, z: z, value: value, depth: depth - 1)) { + nodes[branchIndex] = Leaf(value) + return canClusterize(value) + } + return false + } + + + override func toString() -> String { + return nodes.map { $0?.toString() ?? "null" }.joined(separator: ",") + } +} + +class OctoTree { + let depth: Int + + init(_ depth: Int) { + self.depth = depth + } + + private var root: NodeEntity? = nil + private var actual = false + + func get(_ x: Int, _ y: Int, _ z: Int) -> T? { + var dep = depth + var iter = root + while (true) { + if (iter == nil) { + return nil + } else if let leaf = iter as? Leaf { + return leaf.value + } + + dep -= 1 + iter = (iter as! Branch).nodes[OctoTree.number(x, y, z, dep)] + } + } + + func set(x: Int, y: Int, z: Int, value: T) { + if (root == nil) { + root = Branch() + } + do { + if (try root!.set(x: x, y: y, z: z, value: value, depth: depth - 1)) { + root = Leaf(value) + } + } catch { + print("Exception") + } + actual = false + } + + func toString() -> String { + return root?.toString() ?? "" + } + + static func number(_ x: Int, _ y: Int, _ z: Int, _ depth: Int) -> Int { + let mask = 1 << depth + if (x & mask != 0) { + if (y & mask != 0) { + if (z & mask != 0) { + return 7 + } + return 6 + } + if (z & mask != 0) { + return 5 + } + return 4 + } + if (y & mask != 0) { + if (z & mask != 0) { + return 3 + } + return 2 + } + if (z & mask != 0) { + return 1 + } + return 0 + } + +} + +func octoTest() { + let tree = OctoTree(4) + let to = (2 << tree.depth) + + var x = 0 + var y = 0 + var z = 0 + + while (x < to) { + y = 0 + while (y < to) { + z = 0 + while (z < to) { + let c = (z + to * y + to * to * x) % 2 == 0 + + tree.set(x: x, y: y, z: z, value: c) + z += 1 + } + y += 1 + } + x += 1 + } + + x = 0 + y = 0 + z = 0 + while (x < to) { + y = 0 + while (y < to) { + z = 0 + while (z < to) { + let c = (z + to * y + to * to * x) % 2 == 0 + + let res = tree.get(x, y, z) + + assert(res == c) + z += 1 + } + y += 1 + } + x += 1 + } +} diff --git a/kotlin-native/performance/KotlinVsSwift/ring/src/ParameterNotNullAssertionBenchmark.swift b/kotlin-native/performance/KotlinVsSwift/ring/src/ParameterNotNullAssertionBenchmark.swift new file mode 100644 index 00000000000..1e146d7926f --- /dev/null +++ b/kotlin-native/performance/KotlinVsSwift/ring/src/ParameterNotNullAssertionBenchmark.swift @@ -0,0 +1,61 @@ +/* + * Copyright 2010-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +import Foundation + +class AnyInstance {} + +let OBJ = AnyInstance() + +class ParameterNotNullAssertionBenchmark { + + func methodWithOneNotnullParameter(_ p: Any) -> Any { + return p + } + + private func privateMethodWithOneNotnullParameter(_ p: Any) -> Any { + return p + } + + func methodWithTwoNotnullParameters(_ p: Any, _ p2: Any) -> Any { + return p + } + + private func privateMethodWithTwoNotnullParameters(_ p: Any, _ p2: Any) -> Any { + return p + } + + func methodWithEightNotnullParameters(_ p: Any, _ p2: Any, _ p3: Any, _ p4: Any, _ p5: Any, _ p6: Any, _ p7: Any, _ p8: Any) -> Any { + return p + } + + private func privateMethodWithEightNotnullParameters(_ p: Any, _ p2: Any, _ p3: Any, _ p4: Any, _ p5: Any, _ p6: Any, _ p7: Any, _ p8: Any) -> Any { + return p + } + + func invokeOneArgWithNullCheck() -> Any { + return methodWithOneNotnullParameter(OBJ) + } + + func invokeOneArgWithoutNullCheck() -> Any { + return privateMethodWithOneNotnullParameter(OBJ) + } + + func invokeTwoArgsWithNullCheck() -> Any { + return methodWithTwoNotnullParameters(OBJ, OBJ) + } + + func invokeTwoArgsWithoutNullCheck() -> Any { + return privateMethodWithTwoNotnullParameters(OBJ, OBJ) + } + + func invokeEightArgsWithNullCheck() -> Any { + return methodWithEightNotnullParameters(OBJ, OBJ, OBJ, OBJ, OBJ, OBJ, OBJ, OBJ) + } + + func invokeEightArgsWithoutNullCheck() -> Any { + return privateMethodWithEightNotnullParameters(OBJ, OBJ, OBJ, OBJ, OBJ, OBJ, OBJ, OBJ) + } +} diff --git a/kotlin-native/performance/KotlinVsSwift/ring/src/PrimeListBenchmark.swift b/kotlin-native/performance/KotlinVsSwift/ring/src/PrimeListBenchmark.swift new file mode 100644 index 00000000000..5a8e8f7633f --- /dev/null +++ b/kotlin-native/performance/KotlinVsSwift/ring/src/PrimeListBenchmark.swift @@ -0,0 +1,43 @@ +/* + * Copyright 2010-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +import Foundation + +class PrimeListBenchmark { + private var primes: [Int] = [] + + func calcDirect() { + primes = [] + primes.append(2) + var i = 3 + while (i <= Constants.BENCHMARK_SIZE) { + var simple = true + for prime in primes { + if (prime * prime > i) { + break + } + if (i % prime == 0) { + simple = false + break + } + } + if (simple) { + primes.append(i) + } + i += 2 + } + } + + func calcEratosthenes() { + primes = [] + primes.append(contentsOf: 2...Constants.BENCHMARK_SIZE) + var i = 0 + while (i < primes.count) { + let divisor = primes[i] + primes.removeAll(where: { $0 > divisor && $0 % divisor == 0 }) + i += 1 + } + } +} diff --git a/kotlin-native/performance/KotlinVsSwift/ring/src/StringBenchmark.swift b/kotlin-native/performance/KotlinVsSwift/ring/src/StringBenchmark.swift new file mode 100644 index 00000000000..f0d9da47f39 --- /dev/null +++ b/kotlin-native/performance/KotlinVsSwift/ring/src/StringBenchmark.swift @@ -0,0 +1,74 @@ +/* + * Copyright 2010-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +import Foundation + +class StringBenchmark { + private var _data: [String]? = nil + var data: [String] { + get { + return _data! + } + } + var csv: String = "" + + init() { + var list: [String] = [] + list.reserveCapacity(Constants.BENCHMARK_SIZE) + for n in stringValues(Constants.BENCHMARK_SIZE) { + list.append(n) + } + _data = list + csv = "" + for _ in 1...Constants.BENCHMARK_SIZE-1 { + let elem = Double.random(in: 0.0..<100.0) + csv += String(elem) + csv += "," + } + csv += String(0.0) + } + + + func stringConcat() -> String? { + var string: String = "" + for it in data { + string += it + } + return string + } + + func stringConcatNullable() -> String? { + var string: String? = "" + for it in data { + string? += it + } + return string + } + + func stringBuilderConcat() -> String { + var string: String = "" + for it in data { + string += it + } + return string + } + + func stringBuilderConcatNullable() -> String { + var string: String? = "" + for it in data { + string? += it + } + return string! + } + + func summarizeSplittedCsv() -> Double { + let fields = csv.split(separator: ",") + var sum = 0.0 + for field in fields { + sum += Double(field) ?? 0.0 + } + return sum + } +} diff --git a/kotlin-native/performance/KotlinVsSwift/ring/src/SwitchBenchmark.swift b/kotlin-native/performance/KotlinVsSwift/ring/src/SwitchBenchmark.swift new file mode 100644 index 00000000000..4689744568f --- /dev/null +++ b/kotlin-native/performance/KotlinVsSwift/ring/src/SwitchBenchmark.swift @@ -0,0 +1,558 @@ +/* + * Copyright 2010-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +import Foundation + +struct ConstParams { + static let SPARSE_SWITCH_CASES = [11, 29, 47, 71, 103, + 149, 175, 227, 263, 307, + 361, 487, 563, 617, 677, + 751, 823, 883, 967, 1031] + + static let V1 = 1 + static let V2 = 2 + static let V3 = 3 + static let V4 = 4 + static let V5 = 5 + static let V6 = 6 + static let V7 = 7 + static let V8 = 8 + static let V9 = 9 + static let V10 = 10 + static let V11 = 11 + static let V12 = 12 + static let V13 = 13 + static let V14 = 14 + static let V15 = 15 + static let V16 = 16 + static let V17 = 17 + static let V18 = 18 + static let V19 = 19 + static let V20 = 20 + static var VV1 = 1 + static var VV2 = 2 + static var VV3 = 3 + static var VV4 = 4 + static var VV5 = 5 + static var VV6 = 6 + static var VV7 = 7 + static var VV8 = 8 + static var VV9 = 9 + static var VV10 = 10 + static var VV11 = 11 + static var VV12 = 12 + static var VV13 = 13 + static var VV14 = 14 + static var VV15 = 15 + static var VV16 = 16 + static var VV17 = 17 + static var VV18 = 18 + static var VV19 = 19 + static var VV20 = 20 +} + + +struct NumbersObj { + static let shared = NumbersObj() + + private init() { } + + let V1 = 1 + let V2 = 2 + let V3 = 3 + let V4 = 4 + let V5 = 5 + let V6 = 6 + let V7 = 7 + let V8 = 8 + let V9 = 9 + let V10 = 10 + let V11 = 11 + let V12 = 12 + let V13 = 13 + let V14 = 14 + let V15 = 15 + let V16 = 16 + let V17 = 17 + let V18 = 18 + let V19 = 19 + let V20 = 20 +} + +class SwitchBenchmark { + func sparseIntSwitch(_ u : Int) -> Int { + var t : Int + switch (u) { + case 11: + t = 1 + case 29: + t = 2 + case 47: + t = 3 + case 71: + t = 4 + case 103: + t = 5 + case 149: + t = 6 + case 175: + t = 7 + case 227: + t = 1 + case 263: + t = 9 + case 307: + t = 1 + case 361: + t = 2 + case 487: + t = 3 + case 563: + t = 4 + case 617: + t = 4 + case 677: + t = 4 + case 751: + t = 435 + case 823: + t = 31 + case 883: + t = 1 + case 967: + t = 1 + case 1031: + t = 1 + case 20: + t = 1 + default: + t = 5 + } + return t + } + + func denseIntSwitch(_ u : Int) -> Int { + var t : Int + switch (u) { + case 1: + t = 1 + case -1: + t = 2 + case 2: + t = 3 + case 3: + t = 4 + case 4: + t = 5 + case 5: + t = 6 + case 6: + t = 7 + case 7: + t = 1 + case 8: + t = 9 + case 9: + t = 1 + case 10: + t = 2 + case 11: + t = 3 + case 12: + t = 4 + case 13: + t = 4 + case 14: + t = 4 + case 15: + t = 435 + case 16: + t = 31 + case 17: + t = 1 + case 18: + t = 1 + case 19: + t = 1 + case 20: + t = 1 + default: + t = 5 + } + return t + } + + func constSwitch(_ u : Int) -> Int { + var t : Int + switch (u) { + case ConstParams.V1: + t = 1 + case ConstParams.V2: + t = 3 + case ConstParams.V3: + t = 4 + case ConstParams.V4: + t = 5 + case ConstParams.V5: + t = 6 + case ConstParams.V6: + t = 7 + case ConstParams.V7: + t = 1 + case ConstParams.V8: + t = 9 + case ConstParams.V9: + t = 1 + case ConstParams.V10: + t = 2 + case ConstParams.V11: + t = 3 + case ConstParams.V12: + t = 4 + case ConstParams.V13: + t = 4 + case ConstParams.V14: + t = 4 + case ConstParams.V15: + t = 435 + case ConstParams.V16: + t = 31 + case ConstParams.V17: + t = 1 + case ConstParams.V18: + t = 1 + case ConstParams.V19: + t = 1 + case ConstParams.V20: + t = 1 + default: + t = 5 + } + return t + } + + func objConstSwitch(_ u : Int) -> Int { + var t : Int + switch (u) { + case NumbersObj.shared.V1: + t = 1 + case NumbersObj.shared.V2: + t = 3 + case NumbersObj.shared.V3: + t = 4 + case NumbersObj.shared.V4: + t = 5 + case NumbersObj.shared.V5: + t = 6 + case NumbersObj.shared.V6: + t = 7 + case NumbersObj.shared.V7: + t = 1 + case NumbersObj.shared.V8: + t = 9 + case NumbersObj.shared.V9: + t = 1 + case NumbersObj.shared.V10: + t = 2 + case NumbersObj.shared.V11: + t = 3 + case NumbersObj.shared.V12: + t = 4 + case NumbersObj.shared.V13: + t = 4 + case NumbersObj.shared.V14: + t = 4 + case NumbersObj.shared.V15: + t = 435 + case NumbersObj.shared.V16: + t = 31 + case NumbersObj.shared.V17: + t = 1 + case NumbersObj.shared.V18: + t = 1 + case NumbersObj.shared.V19: + t = 1 + case NumbersObj.shared.V20: + t = 1 + default: + t = 5 + } + return t + } + + func varSwitch(_ u : Int) -> Int { + var t : Int + switch (u) { + case ConstParams.VV1: + t = 1 + case ConstParams.VV2: + t = 3 + case ConstParams.VV3: + t = 4 + case ConstParams.VV4: + t = 5 + case ConstParams.VV5: + t = 6 + case ConstParams.VV6: + t = 7 + case ConstParams.VV7: + t = 1 + case ConstParams.VV8: + t = 9 + case ConstParams.VV9: + t = 1 + case ConstParams.VV10: + t = 2 + case ConstParams.VV11: + t = 3 + case ConstParams.VV12: + t = 4 + case ConstParams.VV13: + t = 4 + case ConstParams.VV14: + t = 4 + case ConstParams.VV15: + t = 435 + case ConstParams.VV16: + t = 31 + case ConstParams.VV17: + t = 1 + case ConstParams.VV18: + t = 1 + case ConstParams.VV19: + t = 1 + case ConstParams.VV20: + t = 1 + default: + t = 5 + } + return t + } + + private func stringSwitch(_ s: String) -> Int { + switch (s) { + case "ABCDEFG1": return 1 + case "ABCDEFG2": return 2 + case "ABCDEFG2": return 3 + case "ABCDEFG3": return 4 + case "ABCDEFG4": return 5 + case "ABCDEFG5": return 6 + case "ABCDEFG6": return 7 + case "ABCDEFG7": return 8 + case "ABCDEFG8": return 9 + case "ABCDEFG9": return 10 + case "ABCDEFG10": return 11 + case "ABCDEFG11": return 12 + case "ABCDEFG12": return 1 + case "ABCDEFG13": return 2 + case "ABCDEFG14": return 3 + case "ABCDEFG15": return 4 + case "ABCDEFG16": return 5 + case "ABCDEFG17": return 6 + case "ABCDEFG18": return 7 + case "ABCDEFG19": return 8 + case "ABCDEFG20": return 9 + default: return -1 + } + } + + var denseIntData: [Int] + var sparseIntData: [Int] + + func testSparseIntSwitch() { + for i in sparseIntData { + Blackhole.consume(sparseIntSwitch(i)) + } + } + + func testDenseIntSwitch() { + for i in denseIntData { + Blackhole.consume(denseIntSwitch(i)) + } + } + + func testConstSwitch() { + for i in denseIntData { + Blackhole.consume(constSwitch(i)) + } + } + + func testObjConstSwitch() { + for i in denseIntData { + Blackhole.consume(objConstSwitch(i)) + } + } + + func testVarSwitch() { + for i in denseIntData { + Blackhole.consume(varSwitch(i)) + } + } + + var data: [String] = [] + + func testStringsSwitch() { + let n = data.count + for s in data { + Blackhole.consume(stringSwitch(s)) + } + } + + enum MyEnum: CaseIterable { + case ITEM1, ITEM2, ITEM3, ITEM4, ITEM5, ITEM6, ITEM7, ITEM8, ITEM9, ITEM10, ITEM11, ITEM12, ITEM13, ITEM14, ITEM15, ITEM16, ITEM17, ITEM18, ITEM19, ITEM20, ITEM21, ITEM22, ITEM23, ITEM24, ITEM25, ITEM26, ITEM27, ITEM28, ITEM29, ITEM30, ITEM31, ITEM32, ITEM33, ITEM34, ITEM35, ITEM36, ITEM37, ITEM38, ITEM39, ITEM40, ITEM41, ITEM42, ITEM43, ITEM44, ITEM45, ITEM46, ITEM47, ITEM48, ITEM49, ITEM50, ITEM51, ITEM52, ITEM53, ITEM54, ITEM55, ITEM56, ITEM57, ITEM58, ITEM59, ITEM60, ITEM61, ITEM62, ITEM63, ITEM64, ITEM65, ITEM66, ITEM67, ITEM68, ITEM69, ITEM70, ITEM71, ITEM72, ITEM73, ITEM74, ITEM75, ITEM76, ITEM77, ITEM78, ITEM79, ITEM80, ITEM81, ITEM82, ITEM83, ITEM84, ITEM85, ITEM86, ITEM87, ITEM88, ITEM89, ITEM90, ITEM91, ITEM92, ITEM93, ITEM94, ITEM95, ITEM96, ITEM97, ITEM98, ITEM99, ITEM100 + } + + private func enumSwitch(_ x: MyEnum) -> Int { + switch (x) { + case MyEnum.ITEM5: return 1 + case MyEnum.ITEM10: return 2 + case MyEnum.ITEM15: return 3 + case MyEnum.ITEM20: return 4 + case MyEnum.ITEM25: return 5 + case MyEnum.ITEM30: return 6 + case MyEnum.ITEM35: return 7 + case MyEnum.ITEM40: return 8 + case MyEnum.ITEM45: return 9 + case MyEnum.ITEM50: return 10 + case MyEnum.ITEM55: return 11 + case MyEnum.ITEM60: return 12 + case MyEnum.ITEM65: return 13 + case MyEnum.ITEM70: return 14 + case MyEnum.ITEM75: return 15 + case MyEnum.ITEM80: return 16 + case MyEnum.ITEM85: return 17 + case MyEnum.ITEM90: return 18 + case MyEnum.ITEM95: return 19 + case MyEnum.ITEM100: return 20 + default: return -1 + } + } + + private func denseEnumSwitch(x: MyEnum) -> Int { + switch (x) { + case MyEnum.ITEM1: return 1 + case MyEnum.ITEM2: return 2 + case MyEnum.ITEM3: return 3 + case MyEnum.ITEM4: return 4 + case MyEnum.ITEM5: return 5 + case MyEnum.ITEM6: return 6 + case MyEnum.ITEM7: return 7 + case MyEnum.ITEM8: return 8 + case MyEnum.ITEM9: return 9 + case MyEnum.ITEM10: return 10 + case MyEnum.ITEM11: return 11 + case MyEnum.ITEM12: return 12 + case MyEnum.ITEM13: return 13 + case MyEnum.ITEM14: return 14 + case MyEnum.ITEM15: return 15 + case MyEnum.ITEM16: return 16 + case MyEnum.ITEM17: return 17 + case MyEnum.ITEM18: return 18 + case MyEnum.ITEM19: return 19 + case MyEnum.ITEM20: return 20 + default: return -1 + } + } + + var enumData : [MyEnum] + var denseEnumData : [MyEnum] + + func testEnumsSwitch() { + let n = enumData.count - 1 + let data = enumData + for i in 0...n { + Blackhole.consume(enumSwitch(data[i])) + } + } + + func testDenseEnumsSwitch() { + let n = denseEnumData.count - 1 + let data = denseEnumData + for i in 0...n { + Blackhole.consume(denseEnumSwitch(x: data[i])) + } + } + + class MySealedClass { + class MySealedClass1: MySealedClass {} + class MySealedClass2: MySealedClass {} + class MySealedClass3: MySealedClass {} + class MySealedClass4: MySealedClass {} + class MySealedClass5: MySealedClass {} + class MySealedClass6: MySealedClass {} + class MySealedClass7: MySealedClass {} + class MySealedClass8: MySealedClass {} + class MySealedClass9: MySealedClass {} + class MySealedClass10: MySealedClass {} + } + + var sealedClassData: [MySealedClass] + + init() { + data = [] + for _ in 0.. Int { + switch (x) { + case is MySealedClass.MySealedClass1: return 1 + case is MySealedClass.MySealedClass2: return 2 + case is MySealedClass.MySealedClass3: return 3 + case is MySealedClass.MySealedClass4: return 4 + case is MySealedClass.MySealedClass5: return 5 + case is MySealedClass.MySealedClass6: return 6 + case is MySealedClass.MySealedClass7: return 7 + case is MySealedClass.MySealedClass8: return 8 + case is MySealedClass.MySealedClass9: return 9 + case is MySealedClass.MySealedClass10: return 10 + default: + return -1 + } + } + + func testSealedWhenSwitch() { + let n = sealedClassData.count - 1 + for i in 0...n { + Blackhole.consume(sealedWhenSwitch(sealedClassData[i])) + } + } +} diff --git a/kotlin-native/performance/KotlinVsSwift/ring/src/Utils.swift b/kotlin-native/performance/KotlinVsSwift/ring/src/Utils.swift new file mode 100644 index 00000000000..5bb1522b5d5 --- /dev/null +++ b/kotlin-native/performance/KotlinVsSwift/ring/src/Utils.swift @@ -0,0 +1,23 @@ +/* + * Copyright 2010-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +import Foundation + +class Blackhole { + @inline(never) + static var flag: Bool = false + @inline(never) + static func consume(_ value: T) { + if (flag) { + print(value) + } + } +} + +struct Constants { + static let BENCHMARK_SIZE = 10000 + static let RUNS = 1_000_000 + static var globalAddendum = 0 +} diff --git a/kotlin-native/performance/KotlinVsSwift/ring/src/WithIndiciesBenchmark.swift b/kotlin-native/performance/KotlinVsSwift/ring/src/WithIndiciesBenchmark.swift new file mode 100644 index 00000000000..0bf5edb8dad --- /dev/null +++ b/kotlin-native/performance/KotlinVsSwift/ring/src/WithIndiciesBenchmark.swift @@ -0,0 +1,43 @@ +/* + * Copyright 2010-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +import Foundation + +class WithIndiciesBenchmark { + private var _data: [Value]? = nil + var data: [Value] { + get { + return _data! + } + } + + init() { + var list: [Value] = [] + for n in classValues(Constants.BENCHMARK_SIZE) { + list.append(n) + } + _data = list + } + + func withIndicies() { + for (index, value) in data.lazy.enumerated() { + if (filterLoad(value)) { + Blackhole.consume(index) + Blackhole.consume(value) + } + } + } + + func withIndiciesManual() { + var index = 0 + for value in data { + if (filterLoad(value)) { + Blackhole.consume(index) + Blackhole.consume(value) + } + index += 1 + } + } +} diff --git a/kotlin-native/performance/KotlinVsSwift/ring/src/main.swift b/kotlin-native/performance/KotlinVsSwift/ring/src/main.swift new file mode 100644 index 00000000000..486541f3a57 --- /dev/null +++ b/kotlin-native/performance/KotlinVsSwift/ring/src/main.swift @@ -0,0 +1,477 @@ +/* + * Copyright 2010-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +import Foundation +import benchmark + +var runner = BenchmarksRunner() +let args = KotlinArray(size: Int32(CommandLine.arguments.count - 1), init: {index in + CommandLine.arguments[Int(truncating: index) + 1] as NSString +}) + +let companion = BenchmarkEntryWithInit.Companion() + +var swiftLauncher = SwiftLauncher() + +extension SwiftLauncher { + static func abstractMethodBenchmark(_ instance: Any) -> AbstractMethodBenchmark { + return instance as! AbstractMethodBenchmark + } + + static func classArrayBenchmark(_ instance: Any) -> ClassArrayBenchmark { + return instance as! ClassArrayBenchmark + } + + static func classListBenchmark(_ instance: Any) -> ClassListBenchmark { + return instance as! ClassListBenchmark + } + + static func classBaselineBenchmark(_ instance: Any) -> ClassBaselineBenchmark { + return instance as! ClassBaselineBenchmark + } + + static func classStreamBenchmark(_ instance: Any) -> ClassStreamBenchmark { + return instance as! ClassStreamBenchmark + } + + static func companionObjectBenchmark(_ instance: Any) -> CompanionObjectBenchmark { + return instance as! CompanionObjectBenchmark + } + + static func defaultArgumentBenchmark(_ instance: Any) -> DefaultArgumentBenchmark { + return instance as! DefaultArgumentBenchmark + } + + static func elvisBenchmark(_ instance: Any) -> ElvisBenchmark { + return instance as! ElvisBenchmark + } + + static func eulerBenchmark(_ instance: Any) -> EulerBenchmark { + return instance as! EulerBenchmark + } + + static func fibonacciBenchmark(_ instance: Any) -> FibonacciBenchmark { + return instance as! FibonacciBenchmark + } + + static func forLoopsBenchmark(_ instance: Any) -> ForLoopsBenchmark { + return instance as! ForLoopsBenchmark + } + + static func inlineBenchmark(_ instance: Any) -> InlineBenchmark { + return instance as! InlineBenchmark + } + + static func intArrayBenchmark(_ instance: Any) -> IntArrayBenchmark { + return instance as! IntArrayBenchmark + } + + static func intBaselineBenchmark(_ instance: Any) -> IntBaselineBenchmark { + return instance as! IntBaselineBenchmark + } + + static func intStreamBenchmark(_ instance: Any) -> IntStreamBenchmark { + return instance as! IntStreamBenchmark + } + + static func lambdaBenchmark(_ instance: Any) -> LambdaBenchmark { + return instance as! LambdaBenchmark + } + + static func loopBenchmark(_ instance: Any) -> LoopBenchmark { + return instance as! LoopBenchmark + } + + static func matrixMapBenchmark(_ instance: Any) -> MatrixMapBenchmark { + return instance as! MatrixMapBenchmark + } + + static func parameterNotNullAssertionBenchmark(_ instance: Any) -> ParameterNotNullAssertionBenchmark { + return instance as! ParameterNotNullAssertionBenchmark + } + + static func primeListBenchmark(_ instance: Any) -> PrimeListBenchmark { + return instance as! PrimeListBenchmark + } + + static func stringBenchmark(_ instance: Any) -> StringBenchmark { + return instance as! StringBenchmark + } + + static func switchBenchmark(_ instance: Any) -> SwitchBenchmark { + return instance as! SwitchBenchmark + } + + static func withIndiciesBenchmark(_ instance: Any) -> WithIndiciesBenchmark { + return instance as! WithIndiciesBenchmark + } + + static func callsBenchmarks(_ instance: Any) -> CallsBenchmarks { + return instance as! CallsBenchmarks + } + + static func coordinatesSolverBenchmark(_ instance: Any) -> CoordinatesSolverBenchmark { + return instance as! CoordinatesSolverBenchmark + } + + static func graphSolverBenchmark(_ instance: Any) -> GraphSolverBenchmark { + return instance as! GraphSolverBenchmark + } + + static func castsBenchmark(_ instance: Any) -> CastsBenchmark { + return instance as! CastsBenchmark + } +} + +swiftLauncher.add(name: "AbstractMethod.sortStrings", benchmark: companion.create(ctor: { return AbstractMethodBenchmark() }, + lambda: { SwiftLauncher.abstractMethodBenchmark($0).sortStrings() })) +swiftLauncher.add(name: "AbstractMethod.sortStringsWithComparator", benchmark: companion.create(ctor: { return AbstractMethodBenchmark() }, + lambda: { SwiftLauncher.abstractMethodBenchmark($0).sortStringsWithComparator() })) + +swiftLauncher.add(name: "ClassArray.copy", benchmark: companion.create(ctor: { return ClassArrayBenchmark() }, + lambda: { SwiftLauncher.classArrayBenchmark($0).copy() })) +swiftLauncher.add(name: "ClassArray.copyManual", benchmark: companion.create(ctor: { return ClassArrayBenchmark() }, + lambda: { SwiftLauncher.classArrayBenchmark($0).copyManual() })) +swiftLauncher.add(name: "ClassArray.filterAndCount", benchmark: companion.create(ctor: { return ClassArrayBenchmark() }, + lambda: { SwiftLauncher.classArrayBenchmark($0).filterAndCount() })) +swiftLauncher.add(name: "ClassArray.filterAndMap", benchmark: companion.create(ctor: { return ClassArrayBenchmark() }, + lambda: { SwiftLauncher.classArrayBenchmark($0).filterAndMap() })) +swiftLauncher.add(name: "ClassArray.filterAndMapManual", benchmark: companion.create(ctor: { return ClassArrayBenchmark() }, + lambda: { SwiftLauncher.classArrayBenchmark($0).filterAndMapManual() })) +swiftLauncher.add(name: "ClassArray.filter", benchmark: companion.create(ctor: { return ClassArrayBenchmark() }, + lambda: { SwiftLauncher.classArrayBenchmark($0).filter() })) +swiftLauncher.add(name: "ClassArray.filterManual", benchmark: companion.create(ctor: { return ClassArrayBenchmark() }, + lambda: { SwiftLauncher.classArrayBenchmark($0).filterManual() })) +swiftLauncher.add(name: "ClassArray.countFilteredManual", benchmark: companion.create(ctor: { return ClassArrayBenchmark() }, + lambda: { SwiftLauncher.classArrayBenchmark($0).countFilteredManual() })) +swiftLauncher.add(name: "ClassArray.countFiltered", benchmark: companion.create(ctor: { return ClassArrayBenchmark() }, + lambda: { SwiftLauncher.classArrayBenchmark($0).countFiltered() })) +swiftLauncher.add(name: "ClassArray.countFilteredLocal", benchmark: companion.create(ctor: { return ClassArrayBenchmark() }, + lambda: { SwiftLauncher.classArrayBenchmark($0).countFilteredLocal() })) + +swiftLauncher.add(name: "ClassBaseline.consume", benchmark: companion.create(ctor: { return ClassBaselineBenchmark() }, + lambda: { SwiftLauncher.classBaselineBenchmark($0).consume() })) +swiftLauncher.add(name: "ClassBaseline.consumeField", benchmark: companion.create(ctor: { return ClassBaselineBenchmark() }, + lambda: { SwiftLauncher.classBaselineBenchmark($0).consumeField() })) +swiftLauncher.add(name: "ClassBaseline.allocateList", benchmark: companion.create(ctor: { return ClassBaselineBenchmark() }, + lambda: { SwiftLauncher.classBaselineBenchmark($0).allocateList() })) +swiftLauncher.add(name: "ClassBaseline.allocateArray", benchmark: companion.create(ctor: { return ClassBaselineBenchmark() }, + lambda: { SwiftLauncher.classBaselineBenchmark($0).allocateArray() })) +swiftLauncher.add(name: "ClassBaseline.allocateListAndFill", benchmark: companion.create(ctor: { return ClassBaselineBenchmark() }, + lambda: { SwiftLauncher.classBaselineBenchmark($0).allocateListAndFill() })) +swiftLauncher.add(name: "ClassBaseline.allocateListAndWrite", benchmark: companion.create(ctor: { return ClassBaselineBenchmark() }, + lambda: { SwiftLauncher.classBaselineBenchmark($0).allocateListAndWrite() })) +swiftLauncher.add(name: "ClassBaseline.allocateArrayAndFill", benchmark: companion.create(ctor: { return ClassBaselineBenchmark() }, + lambda: { SwiftLauncher.classBaselineBenchmark($0).allocateArrayAndFill() })) + +swiftLauncher.add(name: "ClassList.filterAndCountWithLambda", benchmark: companion.create(ctor: { return ClassListBenchmark() }, + lambda: { SwiftLauncher.classListBenchmark($0).filterAndCountWithLambda() })) +swiftLauncher.add(name: "ClassList.filterWithLambda", benchmark: companion.create(ctor: { return ClassListBenchmark() }, + lambda: { SwiftLauncher.classListBenchmark($0).filterWithLambda() })) +swiftLauncher.add(name: "ClassList.mapWithLambda", benchmark: companion.create(ctor: { return ClassListBenchmark() }, + lambda: { SwiftLauncher.classListBenchmark($0).mapWithLambda() })) +swiftLauncher.add(name: "ClassList.countWithLambda", benchmark: companion.create(ctor: { return ClassListBenchmark() }, + lambda: { SwiftLauncher.classListBenchmark($0).countWithLambda() })) +swiftLauncher.add(name: "ClassList.filterAndMapWithLambda", benchmark: companion.create(ctor: { return ClassListBenchmark() }, + lambda: { SwiftLauncher.classListBenchmark($0).filterAndMapWithLambda() })) +swiftLauncher.add(name: "ClassList.filterAndMapWithLambdaAsSequence", benchmark: companion.create(ctor: { return ClassListBenchmark() }, + lambda: { SwiftLauncher.classListBenchmark($0).filterAndMapWithLambdaAsSequence() })) +swiftLauncher.add(name: "ClassList.reduce", benchmark: companion.create(ctor: { return ClassListBenchmark() }, + lambda: { SwiftLauncher.classListBenchmark($0).reduce() })) + +swiftLauncher.add(name: "ClassStream.copy", benchmark: companion.create(ctor: { return ClassStreamBenchmark() }, + lambda: { SwiftLauncher.classStreamBenchmark($0).copy() })) +swiftLauncher.add(name: "ClassStream.copyManual", benchmark: companion.create(ctor: { return ClassStreamBenchmark() }, + lambda: { SwiftLauncher.classStreamBenchmark($0).copyManual() })) +swiftLauncher.add(name: "ClassStream.filterAndCount", benchmark: companion.create(ctor: { return ClassStreamBenchmark() }, + lambda: { SwiftLauncher.classStreamBenchmark($0).filterAndCount() })) +swiftLauncher.add(name: "ClassStream.filterAndMap", benchmark: companion.create(ctor: { return ClassStreamBenchmark() }, + lambda: { SwiftLauncher.classStreamBenchmark($0).filterAndMap() })) +swiftLauncher.add(name: "ClassStream.filterAndMapManual", benchmark: companion.create(ctor: { return ClassStreamBenchmark() }, + lambda: { SwiftLauncher.classStreamBenchmark($0).filterAndMapManual() })) +swiftLauncher.add(name: "ClassStream.filter", benchmark: companion.create(ctor: { return ClassStreamBenchmark() }, + lambda: { SwiftLauncher.classStreamBenchmark($0).filter() })) +swiftLauncher.add(name: "ClassStream.filterManual", benchmark: companion.create(ctor: { return ClassStreamBenchmark() }, + lambda: { SwiftLauncher.classStreamBenchmark($0).filterManual() })) +swiftLauncher.add(name: "ClassStream.countFilteredManual", benchmark: companion.create(ctor: { return ClassStreamBenchmark() }, + lambda: { SwiftLauncher.classStreamBenchmark($0).countFilteredManual() })) +swiftLauncher.add(name: "ClassStream.reduce", benchmark: companion.create(ctor: { return ClassStreamBenchmark() }, + lambda: { SwiftLauncher.classStreamBenchmark($0).reduce() })) + +swiftLauncher.add(name: "CompanionObject.invokeRegularFunction", benchmark: companion.create(ctor: { return CompanionObjectBenchmark() }, + lambda: { SwiftLauncher.companionObjectBenchmark($0).invokeRegularFunction() })) + +swiftLauncher.add(name: "DefaultArgument.testOneOfTwo", benchmark: companion.create(ctor: { return DefaultArgumentBenchmark() }, + lambda: { SwiftLauncher.defaultArgumentBenchmark($0).testOneOfTwo() })) +swiftLauncher.add(name: "DefaultArgument.testTwoOfTwo", benchmark: companion.create(ctor: { return DefaultArgumentBenchmark() }, + lambda: { SwiftLauncher.defaultArgumentBenchmark($0).testTwoOfTwo() })) +swiftLauncher.add(name: "DefaultArgument.testOneOfFour", benchmark: companion.create(ctor: { return DefaultArgumentBenchmark() }, + lambda: { SwiftLauncher.defaultArgumentBenchmark($0).testOneOfFour() })) +swiftLauncher.add(name: "DefaultArgument.testFourOfFour", benchmark: companion.create(ctor: { return DefaultArgumentBenchmark() }, + lambda: { SwiftLauncher.defaultArgumentBenchmark($0).testFourOfFour() })) +swiftLauncher.add(name: "DefaultArgument.testOneOfEight", benchmark: companion.create(ctor: { return DefaultArgumentBenchmark() }, + lambda: { SwiftLauncher.defaultArgumentBenchmark($0).testOneOfEight() })) +swiftLauncher.add(name: "DefaultArgument.testEightOfEight", benchmark: companion.create(ctor: { return DefaultArgumentBenchmark() }, + lambda: { SwiftLauncher.defaultArgumentBenchmark($0).testEightOfEight() })) + +swiftLauncher.add(name: "Elvis.testElvis", benchmark: companion.create(ctor: { return ElvisBenchmark() }, + lambda: { SwiftLauncher.elvisBenchmark($0).testElvis() })) + +swiftLauncher.add(name: "Euler.problem1bySequence", benchmark: companion.create(ctor: { return EulerBenchmark() }, + lambda: { SwiftLauncher.eulerBenchmark($0).problem1bySequence() })) +swiftLauncher.add(name: "Euler.problem1", benchmark: companion.create(ctor: { return EulerBenchmark() }, + lambda: { SwiftLauncher.eulerBenchmark($0).problem1() })) +swiftLauncher.add(name: "Euler.problem2", benchmark: companion.create(ctor: { return EulerBenchmark() }, + lambda: { SwiftLauncher.eulerBenchmark($0).problem2() })) +swiftLauncher.add(name: "Euler.problem4", benchmark: companion.create(ctor: { return EulerBenchmark() }, + lambda: { SwiftLauncher.eulerBenchmark($0).problem4() })) +swiftLauncher.add(name: "Euler.problem8", benchmark: companion.create(ctor: { return EulerBenchmark() }, + lambda: { SwiftLauncher.eulerBenchmark($0).problem8() })) +swiftLauncher.add(name: "Euler.problem9", benchmark: companion.create(ctor: { return EulerBenchmark() }, + lambda: { SwiftLauncher.eulerBenchmark($0).problem9() })) +swiftLauncher.add(name: "Euler.problem14", benchmark: companion.create(ctor: { return EulerBenchmark() }, + lambda: { SwiftLauncher.eulerBenchmark($0).problem14() })) +swiftLauncher.add(name: "Euler.problem14full", benchmark: companion.create(ctor: { return EulerBenchmark() }, + lambda: { SwiftLauncher.eulerBenchmark($0).problem14full() })) + +swiftLauncher.add(name: "Fibonacci.calcClassic", benchmark: companion.create(ctor: { return FibonacciBenchmark() }, + lambda: { SwiftLauncher.fibonacciBenchmark($0).calcClassic() })) +swiftLauncher.add(name: "Fibonacci.calc", benchmark: companion.create(ctor: { return FibonacciBenchmark() }, + lambda: { SwiftLauncher.fibonacciBenchmark($0).calc() })) +swiftLauncher.add(name: "Fibonacci.calcWithProgression", benchmark: companion.create(ctor: { return FibonacciBenchmark() }, + lambda: { SwiftLauncher.fibonacciBenchmark($0).calcWithProgression() })) +swiftLauncher.add(name: "Fibonacci.calcSquare", benchmark: companion.create(ctor: { return FibonacciBenchmark() }, + lambda: { SwiftLauncher.fibonacciBenchmark($0).calcSquare() })) + +swiftLauncher.add(name: "ForLoops.arrayLoop", benchmark: companion.create(ctor: { return ForLoopsBenchmark() }, + lambda: { SwiftLauncher.forLoopsBenchmark($0).arrayLoop() })) +swiftLauncher.add(name: "ForLoops.floatArrayLoop", benchmark: companion.create(ctor: { return ForLoopsBenchmark() }, + lambda: { SwiftLauncher.forLoopsBenchmark($0).floatArrayLoop() })) +swiftLauncher.add(name: "ForLoops.charArrayLoop", benchmark: companion.create(ctor: { return ForLoopsBenchmark() }, + lambda: { SwiftLauncher.forLoopsBenchmark($0).charArrayLoop() })) +swiftLauncher.add(name: "ForLoops.stringLoop", benchmark: companion.create(ctor: { return ForLoopsBenchmark() }, + lambda: { SwiftLauncher.forLoopsBenchmark($0).stringLoop() })) +swiftLauncher.add(name: "ForLoops.arrayIndicesLoop", benchmark: companion.create(ctor: { return ForLoopsBenchmark() }, + lambda: { SwiftLauncher.forLoopsBenchmark($0).arrayIndicesLoop() })) +swiftLauncher.add(name: "ForLoops.floatArrayIndicesLoop", benchmark: companion.create(ctor: { return ForLoopsBenchmark() }, + lambda: { SwiftLauncher.forLoopsBenchmark($0).floatArrayIndicesLoop() })) +swiftLauncher.add(name: "ForLoops.charArrayIndicesLoop", benchmark: companion.create(ctor: { return ForLoopsBenchmark() }, + lambda: { SwiftLauncher.forLoopsBenchmark($0).charArrayIndicesLoop() })) +swiftLauncher.add(name: "ForLoops.stringIndicesLoop", benchmark: companion.create(ctor: { return ForLoopsBenchmark() }, + lambda: { SwiftLauncher.forLoopsBenchmark($0).stringIndicesLoop() })) + +swiftLauncher.add(name: "Inline.calculate", benchmark: companion.create(ctor: { return InlineBenchmark() }, + lambda: { SwiftLauncher.inlineBenchmark($0).calculate() })) +swiftLauncher.add(name: "Inline.calculateInline", benchmark: companion.create(ctor: { return InlineBenchmark() }, + lambda: { SwiftLauncher.inlineBenchmark($0).calculateInline() })) +swiftLauncher.add(name: "Inline.calculateGeneric", benchmark: companion.create(ctor: { return InlineBenchmark() }, + lambda: { SwiftLauncher.inlineBenchmark($0).calculateGeneric() })) +swiftLauncher.add(name: "Inline.calculateGenericInline", benchmark: companion.create(ctor: { return InlineBenchmark() }, + lambda: { SwiftLauncher.inlineBenchmark($0).calculateGenericInline() })) + +swiftLauncher.add(name: "IntArray.copy", benchmark: companion.create(ctor: { return IntArrayBenchmark() }, + lambda: { SwiftLauncher.intArrayBenchmark($0).copy() })) +swiftLauncher.add(name: "IntArray.copyManual", benchmark: companion.create(ctor: { return IntArrayBenchmark() }, + lambda: { SwiftLauncher.intArrayBenchmark($0).copyManual() })) +swiftLauncher.add(name: "IntArray.filterAndCount", benchmark: companion.create(ctor: { return IntArrayBenchmark() }, + lambda: { SwiftLauncher.intArrayBenchmark($0).filterAndCount() })) +swiftLauncher.add(name: "IntArray.filterSomeAndCount", benchmark: companion.create(ctor: { return IntArrayBenchmark() }, + lambda: { SwiftLauncher.intArrayBenchmark($0).filterSomeAndCount() })) +swiftLauncher.add(name: "IntArray.filterAndMap", benchmark: companion.create(ctor: { return IntArrayBenchmark() }, + lambda: { SwiftLauncher.intArrayBenchmark($0).filterAndMap() })) +swiftLauncher.add(name: "IntArray.filterAndMapManual", benchmark: companion.create(ctor: { return IntArrayBenchmark() }, + lambda: { SwiftLauncher.intArrayBenchmark($0).filterAndMapManual() })) +swiftLauncher.add(name: "IntArray.filter", benchmark: companion.create(ctor: { return IntArrayBenchmark() }, + lambda: { SwiftLauncher.intArrayBenchmark($0).filter() })) +swiftLauncher.add(name: "IntArray.filterSome", benchmark: companion.create(ctor: { return IntArrayBenchmark() }, + lambda: { SwiftLauncher.intArrayBenchmark($0).filterSome() })) +swiftLauncher.add(name: "IntArray.filterPrime", benchmark: companion.create(ctor: { return IntArrayBenchmark() }, + lambda: { SwiftLauncher.intArrayBenchmark($0).filterPrime() })) +swiftLauncher.add(name: "IntArray.filterManual", benchmark: companion.create(ctor: { return IntArrayBenchmark() }, + lambda: { SwiftLauncher.intArrayBenchmark($0).filterManual() })) +swiftLauncher.add(name: "IntArray.filterSomeManual", benchmark: companion.create(ctor: { return IntArrayBenchmark() }, + lambda: { SwiftLauncher.intArrayBenchmark($0).filterSomeManual() })) +swiftLauncher.add(name: "IntArray.countFilteredManual", benchmark: companion.create(ctor: { return IntArrayBenchmark() }, + lambda: { SwiftLauncher.intArrayBenchmark($0).countFilteredManual() })) +swiftLauncher.add(name: "IntArray.countFilteredSomeManual", benchmark: companion.create(ctor: { return IntArrayBenchmark() }, + lambda: { SwiftLauncher.intArrayBenchmark($0).countFilteredSomeManual() })) +swiftLauncher.add(name: "IntArray.countFilteredPrimeManual", benchmark: companion.create(ctor: { return IntArrayBenchmark() }, + lambda: { SwiftLauncher.intArrayBenchmark($0).countFilteredPrimeManual() })) +swiftLauncher.add(name: "IntArray.countFiltered", benchmark: companion.create(ctor: { return IntArrayBenchmark() }, + lambda: { SwiftLauncher.intArrayBenchmark($0).countFiltered() })) +swiftLauncher.add(name: "IntArray.countFilteredSome", benchmark: companion.create(ctor: { return IntArrayBenchmark() }, + lambda: { SwiftLauncher.intArrayBenchmark($0).countFilteredSome() })) +swiftLauncher.add(name: "IntArray.countFilteredPrime", benchmark: companion.create(ctor: { return IntArrayBenchmark() }, + lambda: { SwiftLauncher.intArrayBenchmark($0).countFilteredPrime() })) +swiftLauncher.add(name: "IntArray.countFilteredLocal", benchmark: companion.create(ctor: { return IntArrayBenchmark() }, + lambda: { SwiftLauncher.intArrayBenchmark($0).countFilteredLocal() })) +swiftLauncher.add(name: "IntArray.countFilteredSomeLocal", benchmark: companion.create(ctor: { return IntArrayBenchmark() }, + lambda: { SwiftLauncher.intArrayBenchmark($0).countFilteredSomeLocal() })) +swiftLauncher.add(name: "IntArray.reduce", benchmark: companion.create(ctor: { return IntArrayBenchmark() }, + lambda: { SwiftLauncher.intArrayBenchmark($0).reduce() })) + +swiftLauncher.add(name: "IntBaseline.consume", benchmark: companion.create(ctor: { return IntBaselineBenchmark() }, + lambda: { SwiftLauncher.intBaselineBenchmark($0).consume() })) +swiftLauncher.add(name: "IntBaseline.allocateArray", benchmark: companion.create(ctor: { return IntBaselineBenchmark() }, + lambda: { SwiftLauncher.intBaselineBenchmark($0).allocateArray() })) +swiftLauncher.add(name: "IntBaseline.allocateArrayAndFill", benchmark: companion.create(ctor: { return IntBaselineBenchmark() }, + lambda: { SwiftLauncher.intBaselineBenchmark($0).allocateArrayAndFill() })) + +swiftLauncher.add(name: "IntStream.copy", benchmark: companion.create(ctor: { return IntStreamBenchmark() }, + lambda: { SwiftLauncher.intStreamBenchmark($0).copy() })) +swiftLauncher.add(name: "IntStream.copyManual", benchmark: companion.create(ctor: { return IntStreamBenchmark() }, + lambda: { SwiftLauncher.intStreamBenchmark($0).copyManual() })) +swiftLauncher.add(name: "IntStream.filterAndCount", benchmark: companion.create(ctor: { return IntStreamBenchmark() }, + lambda: { SwiftLauncher.intStreamBenchmark($0).filterAndCount() })) +swiftLauncher.add(name: "IntStream.filterAndMap", benchmark: companion.create(ctor: { return IntStreamBenchmark() }, + lambda: { SwiftLauncher.intStreamBenchmark($0).filterAndMap() })) +swiftLauncher.add(name: "IntStream.filterAndMapManual", benchmark: companion.create(ctor: { return IntStreamBenchmark() }, + lambda: { SwiftLauncher.intStreamBenchmark($0).filterAndMapManual() })) +swiftLauncher.add(name: "IntStream.filter", benchmark: companion.create(ctor: { return IntStreamBenchmark() }, + lambda: { SwiftLauncher.intStreamBenchmark($0).filter() })) +swiftLauncher.add(name: "IntStream.filterManual", benchmark: companion.create(ctor: { return IntStreamBenchmark() }, + lambda: { SwiftLauncher.intStreamBenchmark($0).filterManual() })) +swiftLauncher.add(name: "IntStream.countFilteredManual", benchmark: companion.create(ctor: { return IntStreamBenchmark() }, + lambda: { SwiftLauncher.intStreamBenchmark($0).countFilteredManual() })) +swiftLauncher.add(name: "IntStream.countFiltered", benchmark: companion.create(ctor: { return IntStreamBenchmark() }, + lambda: { SwiftLauncher.intStreamBenchmark($0).countFiltered() })) +swiftLauncher.add(name: "IntStream.countFilteredLocal", benchmark: companion.create(ctor: { return IntStreamBenchmark() }, + lambda: { SwiftLauncher.intStreamBenchmark($0).countFilteredLocal() })) +swiftLauncher.add(name: "IntStream.reduce", benchmark: companion.create(ctor: { return IntStreamBenchmark() }, + lambda: { SwiftLauncher.intStreamBenchmark($0).reduce() })) + +swiftLauncher.add(name: "Lambda.noncapturingLambda", benchmark: companion.create(ctor: { return LambdaBenchmark() }, + lambda: { SwiftLauncher.lambdaBenchmark($0).noncapturingLambda() })) +swiftLauncher.add(name: "Lambda.noncapturingLambdaNoInline", benchmark: companion.create(ctor: { return LambdaBenchmark() }, + lambda: { SwiftLauncher.lambdaBenchmark($0).noncapturingLambdaNoInline() })) +swiftLauncher.add(name: "Lambda.capturingLambda", benchmark: companion.create(ctor: { return LambdaBenchmark() }, + lambda: { SwiftLauncher.lambdaBenchmark($0).capturingLambda() })) +swiftLauncher.add(name: "Lambda.capturingLambdaNoInline", benchmark: companion.create(ctor: { return LambdaBenchmark() }, + lambda: { SwiftLauncher.lambdaBenchmark($0).capturingLambdaNoInline() })) +swiftLauncher.add(name: "Lambda.mutatingLambda", benchmark: companion.create(ctor: { return LambdaBenchmark() }, + lambda: { SwiftLauncher.lambdaBenchmark($0).mutatingLambda() })) +swiftLauncher.add(name: "Lambda.mutatingLambdaNoInline", benchmark: companion.create(ctor: { return LambdaBenchmark() }, + lambda: { SwiftLauncher.lambdaBenchmark($0).mutatingLambdaNoInline() })) +swiftLauncher.add(name: "Lambda.methodReference", benchmark: companion.create(ctor: { return LambdaBenchmark() }, + lambda: { SwiftLauncher.lambdaBenchmark($0).methodReference() })) +swiftLauncher.add(name: "Lambda.methodReferenceNoInline", benchmark: companion.create(ctor: { return LambdaBenchmark() }, + lambda: { SwiftLauncher.lambdaBenchmark($0).methodReferenceNoInline() })) + +swiftLauncher.add(name: "Loop.arrayLoop", benchmark: companion.create(ctor: { return LoopBenchmark() }, + lambda: { SwiftLauncher.loopBenchmark($0).arrayLoop() })) +swiftLauncher.add(name: "Loop.arrayIndexLoop", benchmark: companion.create(ctor: { return LoopBenchmark() }, + lambda: { SwiftLauncher.loopBenchmark($0).arrayIndexLoop() })) +swiftLauncher.add(name: "Loop.rangeLoop", benchmark: companion.create(ctor: { return LoopBenchmark() }, + lambda: { SwiftLauncher.loopBenchmark($0).rangeLoop() })) +swiftLauncher.add(name: "Loop.arrayWhileLoop", benchmark: companion.create(ctor: { return LoopBenchmark() }, + lambda: { SwiftLauncher.loopBenchmark($0).arrayWhileLoop() })) +swiftLauncher.add(name: "Loop.arrayForeachLoop", benchmark: companion.create(ctor: { return LoopBenchmark() }, + lambda: { SwiftLauncher.loopBenchmark($0).arrayForeachLoop() })) + +swiftLauncher.add(name: "MatrixMap.add", benchmark: companion.create(ctor: { return MatrixMapBenchmark() }, + lambda: { SwiftLauncher.matrixMapBenchmark($0).add() })) + +swiftLauncher.add(name: "ParameterNotNull.invokeOneArgWithNullCheck", benchmark: companion.create(ctor: { return ParameterNotNullAssertionBenchmark() }, + lambda: { SwiftLauncher.parameterNotNullAssertionBenchmark($0).invokeOneArgWithNullCheck() })) +swiftLauncher.add(name: "ParameterNotNull.invokeOneArgWithoutNullCheck", benchmark: companion.create(ctor: { return ParameterNotNullAssertionBenchmark() }, + lambda: { SwiftLauncher.parameterNotNullAssertionBenchmark($0).invokeOneArgWithoutNullCheck() })) +swiftLauncher.add(name: "ParameterNotNull.invokeTwoArgsWithNullCheck", benchmark: companion.create(ctor: { return ParameterNotNullAssertionBenchmark() }, + lambda: { SwiftLauncher.parameterNotNullAssertionBenchmark($0).invokeTwoArgsWithNullCheck() })) +swiftLauncher.add(name: "ParameterNotNull.invokeTwoArgsWithoutNullCheck", benchmark: companion.create(ctor: { return ParameterNotNullAssertionBenchmark() }, + lambda: { SwiftLauncher.parameterNotNullAssertionBenchmark($0).invokeTwoArgsWithoutNullCheck() })) +swiftLauncher.add(name: "ParameterNotNull.invokeEightArgsWithNullCheck", benchmark: companion.create(ctor: { return ParameterNotNullAssertionBenchmark() }, + lambda: { SwiftLauncher.parameterNotNullAssertionBenchmark($0).invokeEightArgsWithNullCheck() })) +swiftLauncher.add(name: "ParameterNotNull.invokeEightArgsWithoutNullCheck", benchmark: companion.create(ctor: { return ParameterNotNullAssertionBenchmark() }, + lambda: { SwiftLauncher.parameterNotNullAssertionBenchmark($0).invokeEightArgsWithoutNullCheck() })) + +swiftLauncher.add(name: "PrimeList.calcDirect", benchmark: companion.create(ctor: { return PrimeListBenchmark() }, + lambda: { SwiftLauncher.primeListBenchmark($0).calcDirect() })) +swiftLauncher.add(name: "PrimeList.calcEratosthenes", benchmark: companion.create(ctor: { return PrimeListBenchmark() }, + lambda: { SwiftLauncher.primeListBenchmark($0).calcEratosthenes() })) + +swiftLauncher.add(name: "String.stringConcat", benchmark: companion.create(ctor: { return StringBenchmark() }, + lambda: { SwiftLauncher.stringBenchmark($0).stringConcat() })) +swiftLauncher.add(name: "String.stringConcatNullable", benchmark: companion.create(ctor: { return StringBenchmark() }, + lambda: { SwiftLauncher.stringBenchmark($0).stringConcatNullable() })) +swiftLauncher.add(name: "String.stringBuilderConcat", benchmark: companion.create(ctor: { return StringBenchmark() }, + lambda: { SwiftLauncher.stringBenchmark($0).stringBuilderConcat() })) +swiftLauncher.add(name: "String.stringBuilderConcatNullable", benchmark: companion.create(ctor: { return StringBenchmark() }, + lambda: { SwiftLauncher.stringBenchmark($0).stringBuilderConcatNullable() })) +swiftLauncher.add(name: "String.summarizeSplittedCsv", benchmark: companion.create(ctor: { return StringBenchmark() }, + lambda: { SwiftLauncher.stringBenchmark($0).summarizeSplittedCsv() })) + +swiftLauncher.add(name: "Switch.testSparseIntSwitch", benchmark: companion.create(ctor: { return SwitchBenchmark() }, + lambda: { SwiftLauncher.switchBenchmark($0).testSparseIntSwitch() })) +swiftLauncher.add(name: "Switch.testDenseIntSwitch", benchmark: companion.create(ctor: { return SwitchBenchmark() }, + lambda: { SwiftLauncher.switchBenchmark($0).testDenseIntSwitch() })) +swiftLauncher.add(name: "Switch.testConstSwitch", benchmark: companion.create(ctor: { return SwitchBenchmark() }, + lambda: { SwiftLauncher.switchBenchmark($0).testConstSwitch() })) +swiftLauncher.add(name: "Switch.testObjConstSwitch", benchmark: companion.create(ctor: { return SwitchBenchmark() }, + lambda: { SwiftLauncher.switchBenchmark($0).testObjConstSwitch() })) +swiftLauncher.add(name: "Switch.testVarSwitch", benchmark: companion.create(ctor: { return SwitchBenchmark() }, + lambda: { SwiftLauncher.switchBenchmark($0).testVarSwitch() })) +swiftLauncher.add(name: "Switch.testStringsSwitch", benchmark: companion.create(ctor: { return SwitchBenchmark() }, + lambda: { SwiftLauncher.switchBenchmark($0).testStringsSwitch() })) +swiftLauncher.add(name: "Switch.testEnumsSwitch", benchmark: companion.create(ctor: { return SwitchBenchmark() }, + lambda: { SwiftLauncher.switchBenchmark($0).testEnumsSwitch() })) +swiftLauncher.add(name: "Switch.testDenseEnumsSwitch", benchmark: companion.create(ctor: { return SwitchBenchmark() }, + lambda: { SwiftLauncher.switchBenchmark($0).testDenseEnumsSwitch() })) +swiftLauncher.add(name: "Switch.testSealedWhenSwitch", benchmark: companion.create(ctor: { return SwitchBenchmark() }, + lambda: { SwiftLauncher.switchBenchmark($0).testSealedWhenSwitch() })) + +swiftLauncher.add(name: "WithIndicies.withIndicies", benchmark: companion.create(ctor: { return WithIndiciesBenchmark() }, + lambda: { SwiftLauncher.withIndiciesBenchmark($0).withIndicies() })) +swiftLauncher.add(name: "WithIndicies.withIndiciesManual", benchmark: companion.create(ctor: { return WithIndiciesBenchmark() }, + lambda: { SwiftLauncher.withIndiciesBenchmark($0).withIndiciesManual() })) + +swiftLauncher.add(name: "OctoTest", benchmark: BenchmarkEntry( + lambda: { octoTest() })) + +swiftLauncher.add(name: "Calls.finalMethod", benchmark: companion.create(ctor: { return CallsBenchmarks() }, + lambda: { SwiftLauncher.callsBenchmarks($0).finalMethodCall() })) +swiftLauncher.add(name: "Calls.openMethodMonomorphic", benchmark: companion.create(ctor: { return CallsBenchmarks() }, + lambda: { SwiftLauncher.callsBenchmarks($0).classOpenMethodCall_MonomorphicCallsite() })) +swiftLauncher.add(name: "Calls.openMethodBimorphic", benchmark: companion.create(ctor: { return CallsBenchmarks() }, + lambda: { SwiftLauncher.callsBenchmarks($0).classOpenMethodCall_BimorphicCallsite() })) +swiftLauncher.add(name: "Calls.openMethodTrimorphic", benchmark: companion.create(ctor: { return CallsBenchmarks() }, + lambda: { SwiftLauncher.callsBenchmarks($0).classOpenMethodCall_TrimorphicCallsite() })) +swiftLauncher.add(name: "Calls.interfaceMethodMonomorphic", benchmark: companion.create(ctor: { return CallsBenchmarks() }, + lambda: { SwiftLauncher.callsBenchmarks($0).interfaceMethodCall_MonomorphicCallsite() })) +swiftLauncher.add(name: "Calls.interfaceMethodBimorphic", benchmark: companion.create(ctor: { return CallsBenchmarks() }, + lambda: { SwiftLauncher.callsBenchmarks($0).interfaceMethodCall_BimorphicCallsite() })) +swiftLauncher.add(name: "Calls.interfaceMethodTrimorphic", benchmark: companion.create(ctor: { return CallsBenchmarks() }, + lambda: { SwiftLauncher.callsBenchmarks($0).interfaceMethodCall_TrimorphicCallsite() })) +swiftLauncher.add(name: "Calls.interfaceMethodHexamorphic", benchmark: companion.create(ctor: { return CallsBenchmarks() }, + lambda: { SwiftLauncher.callsBenchmarks($0).interfaceMethodCall_HexamorphicCallsite() })) +swiftLauncher.add(name: "Calls.returnBoxUnboxFolding", benchmark: companion.create(ctor: { return CallsBenchmarks() }, + lambda: { SwiftLauncher.callsBenchmarks($0).returnBoxUnboxFolding() })) + +swiftLauncher.add(name: "CoordinatesSolver.solve", benchmark: companion.create(ctor: { return CoordinatesSolverBenchmark() }, + lambda: { SwiftLauncher.coordinatesSolverBenchmark($0).solve() })) + +swiftLauncher.add(name: "GraphSolver.solve", benchmark: companion.create(ctor: { return GraphSolverBenchmark() }, + lambda: { SwiftLauncher.graphSolverBenchmark($0).solve() })) + +swiftLauncher.add(name: "Casts.classCast", benchmark: companion.create(ctor: { return CastsBenchmark() }, + lambda: { SwiftLauncher.castsBenchmark($0).classCast() })) +swiftLauncher.add(name: "Casts.interfaceCast", benchmark: companion.create(ctor: { return CastsBenchmark() }, + lambda: { SwiftLauncher.castsBenchmark($0).interfaceCast() })) + +runner.runBenchmarks(args: args, run: { (arguments: BenchmarkArguments) -> [BenchmarkResult] in + + if arguments is BaseBenchmarkArguments { + let argumentsList: BaseBenchmarkArguments = arguments as! BaseBenchmarkArguments + return swiftLauncher.launch(numWarmIterations: argumentsList.warmup, + numberOfAttempts: argumentsList.repeat, + prefix: argumentsList.prefix, filters: argumentsList.filter, + filterRegexes: argumentsList.filterRegex, + verbose: argumentsList.verbose) + } + return [BenchmarkResult]() +}, parseArgs: { (args: KotlinArray, benchmarksListAction: (() -> KotlinUnit)) -> BenchmarkArguments? in + return runner.parse(args: args, benchmarksListAction: swiftLauncher.benchmarksListAction) }, + collect: { (benchmarks: [BenchmarkResult], arguments: BenchmarkArguments) -> Void in + runner.collect(results: benchmarks, arguments: arguments) +}, benchmarksListAction: swiftLauncher.benchmarksListAction) \ No newline at end of file diff --git a/kotlin-native/performance/KotlinVsSwift/ring/src/zdf_win.swift b/kotlin-native/performance/KotlinVsSwift/ring/src/zdf_win.swift new file mode 100644 index 00000000000..e65070cee53 --- /dev/null +++ b/kotlin-native/performance/KotlinVsSwift/ring/src/zdf_win.swift @@ -0,0 +1,507 @@ +/* + * Copyright 2010-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +import Foundation +let zdf_win: [String] = ["-де", + "-ка", + "-либо", + "-нибудь", + "-с", + "-таки", + "-то", + "а", + "а-конто", + "а-ля", + "аба", + "абажур", + "абажурный", + "абаз", + "абазин", + "абазинец", + "абазинка", + "абазинский", + "абак", + "абака", + "аббат", + "аббатиса", + "аббатский", + "аббатство", + "аббревиатура", + "аббревиатурный", + "аббревиация", + "абдикация", + "абдомен", + "абдоминальный", + "абдуктор", + "абдукторный", + "абдукция", + "абелит", + "аберрационный", + "аберрация", + "абзац", + "абзацный", + "абиетин", + "абиетиновый", + "абиссальный", + "абиссинец", + "абиссинский", + "абитуриент", + "абитуриентка", + "абитуриентский", + "аблактировать", + "аблактировка", + "аблятив", + "абляут", + "абляция", + "аболиционизм", + "аболиционист", + "аболиционистский", + "аболиция", + "абонемент", + "абонементный", + "абонент", + "абонентка", + "абонентный", + "абонентский", + "абонирование", + "абонировать", + "абонироваться", + "абордаж", + "абордажный", + "абордировать", + "абориген", + "аборигенный", + "аборт", + "абортарий", + "абортивный", + "абортировать", + "абразив", + "абразивный", + "абразионный", + "абразия", + "абракадабра", + "абреже", + "абрек", + "абрикос", + "абрикосный", + "абрикосовка", + "абрикосовый", + "абрикотин", + "абрис", + "абрисный", + "абсент", + "абсентеизм", + "абсентеист", + "абсолют", + "абсолютивный", + "абсолютизирование", + "абсолютизировать", + "абсолютизм", + "абсолютист", + "абсолютистский", + "абсолютность", + "абсолютный", + "абсолюция", + "абсорбент", + "абсорбер", + "абсорбировать", + "абсорбционный", + "абсорбция", + "абстинент", + "абстрагирование", + "абстрагировать", + "абстрагироваться", + "абстракт", + "абстрактность", + "абстрактный", + "абстракционизм", + "абстракционист", + "абстракционистский", + "абстракция", + "абсурд", + "абсурдность", + "абсурдный", + "абсцесс", + "абсцисса", + "абулия", + "абхаз", + "абхазец", + "абхазка", + "абхазский", + "абцуг", + "абштрих", + "абъюрация", + "абы", + "авалист", + "аваль", + "авангард", + "авангардизм", + "авангардист", + "авангардистский", + "авангардный", + "аванзал", + "аванзальный", + "аванкамера", + "аванложа", + "аванпорт", + "аванпост", + "аванпостный", + "аванс", + "авансирование", + "авансировать", + "авансовый", + "авансом", + "авансцена", + "авантаж", + "авантажный", + "авантюра", + "авантюризм", + "авантюрин", + "авантюриновый", + "авантюрист", + "авантюристический", + "авантюристичный", + "авантюристка", + "авантюристский", + "авантюрность", + "авантюрный", + "авар", + "аварец", + "аварийность", + "аварийный", + "аварийщик", + "авария", + "аварка", + "аварский", + "авгиев", + "авгит", + "авгур", + "август", + "августейший", + "августинец", + "августовский", + "авдотка", + "авеню", + "аверс", + "авестийский", + "авиабаза", + "авиабензин", + "авиагоризонт", + "авиадвигатель", + "авиадесант", + "авиадесантный", + "авиазавод", + "авиаконструктор", + "авиалиния", + "авиаматка", + "авиамоделизм", + "авиамоделист", + "авиамодель", + "авиамодельный", + "авиамотор", + "авиамоторный", + "авианосец", + "авиапочта", + "авиаприбор", + "авиапромышленность", + "авиапромышленный", + "авиаразведка", + "авиастроение", + "авиастроитель", + "авиастроительный", + "авиастроительство", + "авиасъёмка", + "авиатехник", + "авиатор", + "авиаторский", + "авиатранспорт", + "авиатранспортный", + "авиатрасса", + "авиационный", + "авиация", + "авиачасть", + "авиашкола", + "авиетка", + "авизировать", + "авизный", + "авизо", + "авитаминоз", + "авитаминозный", + "авифауна", + "авокадо", + "авось", + "авоська", + "аврал", + "авралить", + "авральный", + "авран", + "аврора", + "австралиец", + "австралийка", + "австралийский", + "австралопитек", + "австриец", + "австрийка", + "австрийский", + "австрияк", + "австриячка", + "австро-венгерский", + "автаркический", + "автаркия", + "авто", + "автобаза", + "автобиографический", + "автобиографичность", + "автобиографичный", + "автобиография", + "автоблокировка", + "автоблокировочный", + "автобус", + "автобусник", + "автобусный", + "автовакцина", + "автовесы", + "автовокзал", + "автогамия", + "автоген", + "автогенез", + "автогенератор", + "автогенный", + "автогенщик", + "автогипноз", + "автогонки", + "автогравюра", + "автограф", + "автографический", + "автография", + "автогужевой", + "автодидакт", + "автодоение", + "автодорожник", + "автодорожный", + "автодрезина", + "автодром", + "автожир", + "автозавод", + "автозаводец", + "автозаводский", + "автозаводской", + "автозаправочный", + "автозаправщик", + "автоинспектор", + "автоинспекция", + "автокар", + "автокара", + "автокатализ", + "автокефалия", + "автокефальный", + "автоклав", + "автоклуб", + "автоколонна", + "автокомбинат", + "автокран", + "автократ", + "автократический", + "автократия", + "автокружок", + "автол", + "автолавка", + "автолиз", + "автолитография", + "автолюбитель", + "автолюбительство", + "автомагистраль", + "автомат", + "автоматизация", + "автоматизирование", + "автоматизировать", + "автоматизироваться", + "автоматизм", + "автоматика", + "автоматический", + "автоматичность", + "автоматичный", + "автоматный", + "автоматчик", + "автоматчица", + "автомашина", + "автомашинист", + "автомеханик", + "автомобилестроение", + "автомобилестроитель", + "автомобилестроительный", + "автомобилизация", + "автомобилизм", + "автомобилист", + "автомобилистка", + "автомобиль", + "автомобильный", + "автомобильчик", + "автоморфизм", + "автомотоклуб", + "автомоторный", + "автомотошкола", + "автомотриса", + "автономист", + "автономистский", + "автономический", + "автономия", + "автономность", + "автономный", + "автопарк", + "автоперевозка", + "автопилот", + "автопластика", + "автоплуг", + "автопогрузчик", + "автоподъёмник", + "автопоезд", + "автопоилка", + "автопокрышка", + "автопортрет", + "автопробег", + "автопромышленность", + "автор", + "авторалли", + "авторегулятор", + "авторемонтник", + "авторемонтный", + "автореферат", + "авторефрижератор", + "авторизация", + "авторизованный", + "авторизовать", + "авторитарность", + "авторитарный", + "авторитет", + "авторитетность", + "авторитетный", + "авторота", + "авторские", + "авторский", + "авторство", + "авторулевой", + "авторучка", + "автосани", + "автосборка", + "автосварщик", + "автоспорт", + "автостанция", + "автостоп", + "автострада", + "автостроение", + "автостроитель", + "автосцепка", + "автотележка", + "автотип", + "автотипический", + "автотипия", + "автотипный", + "автотомия", + "автотормоз", + "автотормозной", + "автотракторный", + "автотранспорт", + "автотранспортный", + "автотрансформатор", + "автотрасса", + "автотуризм", + "автотурист", + "автоукладчик", + "автофургон", + "автохозяйство", + "автохром", + "автохромный", + "автохтон", + "автохтонный", + "автоцистерна", + "авточасть", + "автошкола", + "автоштурман", + "авуары", + "ага", + "ага-хан", + "агава", + "агалит", + "агальматолит", + "агама", + "агами", + "агамия", + "агамогония", + "агар-агар", + "агарный", + "агаровый", + "агарянин", + "агат", + "агатный", + "агатовый", + "агглютинативность", + "агглютинативный", + "агглютинация", + "агглютинин", + "агглютинирующий", + "аггравация", + "агент", + "агентский", + "агентство", + "агентура", + "агентурный", + "агиографический", + "агиография", + "агиология", + "агитатор", + "агитаторский", + "агитаторша", + "агитационный", + "агитация", + "агитбригада", + "агитировать", + "агитка", + "агиткампания", + "агитмассовый", + "агитпоезд", + "агитпроп", + "агитпункт", + "аглицкий", + "агломерат", + "агломератчик", + "агломерационный", + "агломерация", + "агломерировать", + "агломерироваться", + "агнат", + "агнец", + "агнозия", + "агностик", + "агностицизм", + "агностический", + "агонизировать", + "агонический", + "агония", + "агорафобия", + "аграмант", + "аграмантовый", + "аграрий", + "аграрник", + "аграрный", + "аграф", + "аграфия", + "агрегат", + "агрегатный", + "агреман", + "агрессивность", + "агрессивный", + "агрессия", + "агрессор", + "агрикультура", + "агрикультурный", + "агробаза", + "агробиолог", + "агробиологический", + "агробиология", + "агроботаника", + "агрозоотехника", + "агромелиорация" +] diff --git a/kotlin-native/performance/build.gradle b/kotlin-native/performance/build.gradle new file mode 100644 index 00000000000..f60a564661a --- /dev/null +++ b/kotlin-native/performance/build.gradle @@ -0,0 +1,295 @@ +import org.jetbrains.kotlin.RegressionsReporter +import org.jetbrains.kotlin.RegressionsSummaryReporter +import org.jetbrains.kotlin.BuildRegister +import org.jetbrains.kotlin.MPPTools + +buildscript { + apply from: "$rootProject.projectDir/gradle/kotlinGradlePlugin.gradle" + repositories { + maven { + url 'https://cache-redirector.jetbrains.com/jcenter' + } + jcenter() + } +} + +def rootBuildDirectory = rootProject.projectDir + +task konanRun { + subprojects.each { + dependsOn "${it.path}:konanRun" + } +} + +task jvmRun { + subprojects.each { + dependsOn "${it.path}:jvmRun" + } +} + +task clean { + subprojects.each { + dependsOn "${it.path}:clean" + } + doLast { + delete "${buildDir.absolutePath}" + } +} + +defaultTasks 'konanRun' + +private static String getAnalyzerTargetName() { + // Copy-pasted from tools/benchmarksAnalyzer/build.gradle. + String target = System.getProperty("os.name") + if (target == 'Linux') return 'linux' + if (target.startsWith('Windows')) return 'windows' + if (target.startsWith('Mac')) return 'macos' + return 'unknown' +} + +private String findAnalyzerBinary() { + String result = "${rootProject.projectDir}/${analyzerToolDirectory}/${getAnalyzerTargetName()}/" + + "${analyzerTool}ReleaseExecutable/${analyzerTool}${MPPTools.getNativeProgramExtension()}" + + if (file(result).exists()) return result + else return null +} + +// Produce and send slack report. +task slackReport(type: RegressionsReporter) { + def analyzerBinary = MPPTools.findFile("${analyzerTool}${MPPTools.getNativeProgramExtension()}", + "${rootBuildDirectory}/${analyzerToolDirectory}") + def teamcityConfig = System.getenv("TEAMCITY_BUILD_PROPERTIES_FILE") + if (teamcityConfig && analyzerBinary != null) { + // Create folder for report (root Kotlin project settings make create report in separate folder). + def reportDirectory = new File(outputReport).parentFile + mkdir reportDirectory + def targetsResults = new File(new File("${rootBuildDirectory}"), "targetsResults").toString() + mkdir targetsResults + currentBenchmarksReportFile = "${buildDir.absolutePath}/${nativeJson}" + analyzer = analyzerBinary + htmlReport = outputReport + defaultBranch = project.findProperty('kotlin.native.default.branch') ?: "master" + def target = System.getProperty("os.name") + summaryFile = "${targetsResults}/${target}.txt" + bundleBuild = project.findProperty('kotlin.bundleBuild') == null ? false : true + } +} + +task slackSummary(type: RegressionsSummaryReporter) { + targetsResultFiles = ['Linux': "${rootBuildDirectory}/targetsResults/Linux.txt".toString(), + 'MacOSX': "${rootBuildDirectory}/targetsResults/Mac OS X.txt".toString(), + 'Windows': "${rootBuildDirectory}/targetsResults/Windows 10.txt".toString()] +} + +private String getUploadedFile(String fileName) { + def teamcityConfig = System.getenv("TEAMCITY_BUILD_PROPERTIES_FILE") + if (teamcityConfig) { + def buildProperties = new Properties() + buildProperties.load(new FileInputStream(teamcityConfig)) + def buildNumber = buildProperties.getProperty("build.number") + def target = System.getProperty("os.name").replaceAll("\\s", "") + return "${target}/${buildNumber}/${fileName}" + } + return null +} + +private def uploadBenchmarkResultToArtifactory(String fileName) { + def teamcityConfig = System.getenv("TEAMCITY_BUILD_PROPERTIES_FILE") + if (teamcityConfig) { + def uploadedFile = getUploadedFile(fileName) + def buildProperties = new Properties() + buildProperties.load(new FileInputStream(teamcityConfig)) + def password = buildProperties.getProperty("artifactory.apikey") + MPPTools.uploadFileToArtifactory("${artifactoryUrl}", "${artifactoryRepo}", + uploadedFile, "${buildDir.absolutePath}/${fileName}", password) + } +} + +// Register external benchmarks reports (e.g. results of libraries benchmarks) +task registerExternalBenchmarks { + doLast { + def reports = externalReports.split(';') + def jsonReports = [] + reports.each { + def reportFile = new File(buildDir, it) + if (!reportFile.exists()) + return + + def lines = reportFile.readLines() + if (lines.size < 4) { + project.logger.warn("Couldn't use report to register benchmarks. Wrong format.") + return + } + def name = lines[0] + def options = lines[1] + if (!options.startsWith("OPTIONS")) { + project.logger.warn("Couldn't use report to register benchmarks. Wrong format in options description.") + return + } + def optionsList = options.replace("OPTIONS ", "").replaceAll("\\[|\\]", "").split(",\\s*").toList() + def status = lines[2] + def compileTime = null + def codeSize = null + lines.drop(3).each { + if (it.startsWith("COMPILE_TIME")) { + compileTime = it + } + if (it.startsWith("CODE_SIZE")) { + codeSize = it + } + } + // Create benchmarks report. + def properties = [ + "cpu": System.getProperty("os.arch"), + "os": System.getProperty("os.name"), + "jdkVersion": System.getProperty("java.version"), + "jdkVendor": System.getProperty("java.vendor"), + "kotlinVersion": kotlinVersion, + "type": "native", + "compilerVersion": konanVersion, + "flags": optionsList, + "benchmarks": "[]"] + if (compileTime != null) { + def compileBenchmark = MPPTools.toCompileBenchmark(compileTime, status, name) + properties += ["compileTime": [compileBenchmark]] + } + if (codeSize != null) { + properties += ["codeSize": MPPTools.toCodeSizeBenchmark(codeSize, status, name)] + } + def output = MPPTools.createJsonReport(properties) + def jsonFile = new File(buildDir, it.replace(".txt", ".json")) + jsonFile.write(output) + jsonReports.add(jsonFile) + } + def merged = MPPTools.mergeReports(jsonReports) + if (!merged.isEmpty()) { + mkdir buildDir.absolutePath + new File(buildDir, externalBenchmarksReport).write(merged) + uploadBenchmarkResultToArtifactory(externalBenchmarksReport) + } + } +} + +task registerBuild(type: BuildRegister) { + onlyBranch = project.findProperty('kotlin.register.branch') + def uploadedFile = getUploadedFile(nativeJson) + if (uploadedFile != null) { + println("Use file from Artifacrory $uploadedFile") + fileWithResult = uploadedFile + } + // Get bundle size. + bundleSize = null + if (project.findProperty('kotlin.bundleBuild') != null) { + def dist = findProperty('kotlin.native.home') ?: 'dist' + dist = (new File(dist)).isAbsolute() ? dist : "${project.getProjectDir()}/$dist" + bundleSize = (new File(dist)).directorySize() + } +} + +task registerExternalBuild(type: BuildRegister) { + onlyBranch = project.findProperty('kotlin.register.branch') + def uploadedFile = getUploadedFile(externalBenchmarksReport) + if (uploadedFile != null) { + println("Use file from Artifacrory $uploadedFile") + fileWithResult = uploadedFile + } else { + fileWithResult = externalBenchmarksReport + } + +} + +registerExternalBenchmarks.finalizedBy registerExternalBuild + +def mergeReports(String fileName) { + def reports = [] + subprojects.each { + def reportFile = new File("${it.buildDir.absolutePath}/${fileName}") + if (reportFile.exists()) { + reports.add(reportFile) + } + } + def output = MPPTools.mergeReports(reports) + mkdir buildDir.absolutePath + new File("${buildDir.absolutePath}/${fileName}").write(output) +} + +task mergeNativeReports { + doLast { + mergeReports(nativeJson) + uploadBenchmarkResultToArtifactory(nativeJson) + } +} + +task mergeJvmReports { + doLast { + mergeReports(jvmJson) + uploadBenchmarkResultToArtifactory(jvmJson) + } +} + +subprojects.each { + it.afterEvaluate { + it.jvmJsonReport.finalizedBy mergeJvmReports + it.konanJsonReport.finalizedBy mergeNativeReports + } +} + +task teamCityStat(type:Exec) { + def analyzer = findAnalyzerBinary() + if (analyzer != null) { + commandLine "${analyzer}", "-r", "teamcity", "${buildDir.absolutePath}/${nativeJson}" + } else { + println("No analyzer $analyzerTool found in subdirectories of ${rootBuildDirectory}/${analyzerToolDirectory}") + } +} + +task cinterop { + dependsOn 'clean' + dependsOn 'cinterop:konanRun' +} + +task framework { + dependsOn 'clean' + dependsOn 'framework:konanRun' +} + +task helloworld { + dependsOn 'clean' + dependsOn 'helloworld:konanRun' +} + +task objcinterop { + dependsOn 'clean' + dependsOn 'objcinterop:konanRun' +} + +task ring { + dependsOn 'clean' + dependsOn 'ring:konanRun' +} + +task numerical { + dependsOn 'clean' + dependsOn 'numerical:konanRun' +} + +task startup { + dependsOn 'clean' + dependsOn 'startup:konanRun' +} + +task swiftinterop { + dependsOn 'clean' + dependsOn 'swiftinterop:konanRun' +} + +task videoplayer { + dependsOn 'clean' + dependsOn 'videoplayer:konanRun' +} + +task KotlinVsSwift { + dependsOn 'clean' + dependsOn 'KotlinVsSwift:konanRun' +} \ No newline at end of file diff --git a/kotlin-native/performance/cinterop/build.gradle.kts b/kotlin-native/performance/cinterop/build.gradle.kts new file mode 100644 index 00000000000..f885f4325ba --- /dev/null +++ b/kotlin-native/performance/cinterop/build.gradle.kts @@ -0,0 +1,31 @@ +/* + * Copyright 2010-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +import org.jetbrains.kotlin.gradle.plugin.mpp.KotlinNativeTarget +import org.jetbrains.kotlin.gradle.plugin.mpp.NativeBuildType + +plugins { + id("benchmarking") +} + +val defaultBuildType = NativeBuildType.RELEASE + +benchmark { + applicationName = "Cinterop" + commonSrcDirs = listOf("../../tools/benchmarks/shared/src/main/kotlin/report", "src/main/kotlin", "../shared/src/main/kotlin") + jvmSrcDirs = listOf("src/main/kotlin-jvm", "../shared/src/main/kotlin-jvm") + nativeSrcDirs = listOf("src/main/kotlin-native", "../shared/src/main/kotlin-native/common") + mingwSrcDirs = listOf("src/main/kotlin-native", "../shared/src/main/kotlin-native/mingw") + posixSrcDirs = listOf("src/main/kotlin-native", "../shared/src/main/kotlin-native/posix") + buildType = (findProperty("nativeBuildType") as String?)?.let { NativeBuildType.valueOf(it) } ?: defaultBuildType + dependencies.common(project(":endorsedLibraries:kotlinx.cli")) +} + +val native = kotlin.targets.getByName("native") as KotlinNativeTarget +native.compilations["main"].cinterops { + create("macros") + create("struct") + create("types") +} diff --git a/kotlin-native/performance/cinterop/gradle.properties b/kotlin-native/performance/cinterop/gradle.properties new file mode 100644 index 00000000000..d7062dc22a1 --- /dev/null +++ b/kotlin-native/performance/cinterop/gradle.properties @@ -0,0 +1 @@ +kotlin.native.home=../../dist \ No newline at end of file diff --git a/kotlin-native/performance/cinterop/src/main/kotlin-jvm/org/jetbrains/cinteropBenchmarks/structsBenchmark.kt b/kotlin-native/performance/cinterop/src/main/kotlin-jvm/org/jetbrains/cinteropBenchmarks/structsBenchmark.kt new file mode 100644 index 00000000000..e7e4485e896 --- /dev/null +++ b/kotlin-native/performance/cinterop/src/main/kotlin-jvm/org/jetbrains/cinteropBenchmarks/structsBenchmark.kt @@ -0,0 +1,27 @@ +/* + * Copyright 2010-2017 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.jetbrains.structsBenchmarks + +actual fun structBenchmark() { + error("Benchmark structBenchmark is unsupported on JVM!") +} +actual fun unionBenchmark() { + error("Benchmark unionBenchmark is unsupported on JVM!") +} +actual fun enumBenchmark() { + error("Benchmark enumBenchmark is unsupported on JVM!") +} \ No newline at end of file diff --git a/kotlin-native/performance/cinterop/src/main/kotlin-jvm/org/jetbrains/cinteropBenchmarks/structsProducedByMacrosBenchmark.kt b/kotlin-native/performance/cinterop/src/main/kotlin-jvm/org/jetbrains/cinteropBenchmarks/structsProducedByMacrosBenchmark.kt new file mode 100644 index 00000000000..537b668ab4e --- /dev/null +++ b/kotlin-native/performance/cinterop/src/main/kotlin-jvm/org/jetbrains/cinteropBenchmarks/structsProducedByMacrosBenchmark.kt @@ -0,0 +1,21 @@ +/* + * Copyright 2010-2017 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.jetbrains.structsProducedByMacrosBenchmarks + +actual fun macrosBenchmark() { + error("Benchmark macrosBenchmark is unsupported on JVM!") +} \ No newline at end of file diff --git a/kotlin-native/performance/cinterop/src/main/kotlin-jvm/org/jetbrains/cinteropBenchmarks/typesBenchmark.kt b/kotlin-native/performance/cinterop/src/main/kotlin-jvm/org/jetbrains/cinteropBenchmarks/typesBenchmark.kt new file mode 100644 index 00000000000..49885047af9 --- /dev/null +++ b/kotlin-native/performance/cinterop/src/main/kotlin-jvm/org/jetbrains/cinteropBenchmarks/typesBenchmark.kt @@ -0,0 +1,46 @@ +/* + * Copyright 2010-2017 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.jetbrains.typesBenchmarks + +actual class StringBenchmark actual constructor() { + actual fun stringToCBenchmark() { + error("Benchmark stringToCBenchmark is unsupported on JVM!") + } + + actual fun stringToKotlinBenchmark() { + error("Benchmark stringToKotlinBenchmark is unsupported on JVM!") + } +} + +actual class IntBenchmark actual constructor() { + actual fun intBenchmark() { + error("Benchmark intBenchmark is unsupported on JVM!") + } +} + +actual class BoxedIntBenchmark actual constructor() { + actual fun boxedIntBenchmark() { + error("Benchmark boxedIntBenchmark is unsupported on JVM!") + } +} + +actual class IntMatrixBenchmark actual constructor() { + actual fun intMatrixBenchmark() { + error("Benchmark intMatrixBenchmark is unsupported on JVM!") + } +} + diff --git a/kotlin-native/performance/cinterop/src/main/kotlin-native/org/jetbrains/cinteropBenchmarks/structsBenchmark.kt b/kotlin-native/performance/cinterop/src/main/kotlin-native/org/jetbrains/cinteropBenchmarks/structsBenchmark.kt new file mode 100644 index 00000000000..23dfaa84efc --- /dev/null +++ b/kotlin-native/performance/cinterop/src/main/kotlin-native/org/jetbrains/cinteropBenchmarks/structsBenchmark.kt @@ -0,0 +1,81 @@ +/* + * Copyright 2010-2017 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.jetbrains.structsBenchmarks +import kotlinx.cinterop.* +import platform.posix.* +import kotlin.math.sqrt + +const val benchmarkSize = 10000 + +actual fun structBenchmark() { + memScoped { + val containsFunction = staticCFunction?, CPointer?, Int> { first, second -> + if (first == null || second == null) { + 0 + } else if (first.pointed.string.toKString().contains(second.pointed.string.toKString())) { + 1 + } + else { + 0 + } + } + val elementsList = mutableListOf() + // Fill list. + for (i in 1..benchmarkSize) { + val element = alloc() + element.floatValue = i + sqrt(i.toDouble()).toFloat() + element.integer = i.toLong() + sprintf(element.string, "%d", i) + element.contains = containsFunction + + elementsList.add(element) + } + val summary = elementsList.map { multiplyElementS(it.readValue(), (0..10).random()) } + .reduce { acc, it -> sumElementSPtr(acc.ptr, it.ptr)!!.pointed.readValue() } + val intValue = summary.useContents { integer } + elementsList.last().contains!!(elementsList.last().ptr, elementsList.first().ptr) + } +} + +actual fun unionBenchmark() { + memScoped { + val elementsList = mutableListOf() + // Fill list. + for (i in 1..benchmarkSize) { + val element = alloc() + element.integer = i.toLong() + elementsList.add(element) + } + elementsList.forEach { + it.floatValue = it.integer + sqrt(it.integer.toDouble()).toFloat() + } + val summary = elementsList.map { multiplyElementU(it.readValue(), (0..10).random()) } + .reduce { acc, it -> sumElementUPtr(acc.ptr, it.ptr)!!.pointed.readValue() } + summary.useContents { integer } + } +} + +actual fun enumBenchmark() { + val days = arrayOf("Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday") + val enumValues = mutableListOf() + for (i in 1..benchmarkSize) { + enumValues.add(getWeekDay(days[(0..6).random()])) + } + enumValues.forEach { + isWeekEnd(it) + } +} \ No newline at end of file diff --git a/kotlin-native/performance/cinterop/src/main/kotlin-native/org/jetbrains/cinteropBenchmarks/structsProducedByMacrosBenchmark.kt b/kotlin-native/performance/cinterop/src/main/kotlin-native/org/jetbrains/cinteropBenchmarks/structsProducedByMacrosBenchmark.kt new file mode 100644 index 00000000000..7b41a962510 --- /dev/null +++ b/kotlin-native/performance/cinterop/src/main/kotlin-native/org/jetbrains/cinteropBenchmarks/structsProducedByMacrosBenchmark.kt @@ -0,0 +1,59 @@ +/* + * Copyright 2010-2019 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.jetbrains.structsProducedByMacrosBenchmarks +import kotlinx.cinterop.* +import kotlin.math.abs + +const val benachmarkSize = 1000 + +actual fun macrosBenchmark() { + memScoped { + val ints = new_list_int() + for (i in 1..benachmarkSize) { + list_push_front_int(ints, i) + } + val floats = new_list_float() + // Copy integer list to float one. + ints?.pointed?.apply { + var current = _first + while(current != null) { + list_push_front_float(floats, current?.pointed?._data?.toFloat() + ?: error("Null elements in list are not expected!") + ) + current = current?.pointed?._next + } + } + // Reverse list. + var previous: CPointer? = null + var current = floats?.pointed?._first + while (current != null) { + val next = current?.pointed?._next + current?.pointed?._next = previous + previous = current + current = next + } + floats?.pointed?._first = previous + free_list_int(ints) + try { + if (abs(list_front_float(floats) - benachmarkSize.toFloat()) > 0.00001) { + error("Wrong first element!") + } + } finally { + free_list_float(floats) + } + } +} \ No newline at end of file diff --git a/kotlin-native/performance/cinterop/src/main/kotlin-native/org/jetbrains/cinteropBenchmarks/typesBenchmark.kt b/kotlin-native/performance/cinterop/src/main/kotlin-native/org/jetbrains/cinteropBenchmarks/typesBenchmark.kt new file mode 100644 index 00000000000..113eb92810c --- /dev/null +++ b/kotlin-native/performance/cinterop/src/main/kotlin-native/org/jetbrains/cinteropBenchmarks/typesBenchmark.kt @@ -0,0 +1,133 @@ +/* + * Copyright 2010-2017 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.jetbrains.typesBenchmarks + +import kotlin.random.Random +import kotlinx.cinterop.* + +const val benchmarkSize = 1000 + +actual class StringBenchmark actual constructor() { + val charPool: List = ('a'..'z') + ('A'..'Z') + ('0'..'9') + val randomString = generateRandomString() + val randomChar = charPool[Random.nextInt(0, charPool.size)] + val strings = mutableListOf() + + init { + // Generate random strings. + for (i in 1..benchmarkSize) { + strings.add(generateRandomString()) + } + } + + fun generateRandomString(): String { + return (1..benchmarkSize) + .map { i -> Random.nextInt(0, charPool.size) } + .map(charPool::get) + .joinToString("") + } + + actual fun stringToCBenchmark() { + // Generate random strings. + for (i in 1..benchmarkSize) { + charFrequency(randomString, randomChar.toByte()) + } + } + + actual fun stringToKotlinBenchmark() { + memScoped { + val result = StringBuilder() + for (i in 1..benchmarkSize) { + val pointer = findSuitableString(strings.toCStringArray(this), benchmarkSize, "a") + val str = pointer?.toKString() + result.append(str) + freeSuitableString(pointer) + } + } + } +} + +actual class IntMatrixBenchmark actual constructor(){ + val matrixSize = 1000 + val first = generateMatrix(matrixSize) + val second = generateMatrix(matrixSize) + + fun generateMatrix(size: Int): Array { + val matrix = Array(size, { IntArray(size) }) + for (i in (0 until size)) { + for (j in (0 until size)) { + matrix[i][j] = (1..20).random() + } + } + return matrix + } + + actual fun intMatrixBenchmark() { + memScoped { + val result = allocArray>(matrixSize) + for (i in (0 until matrixSize)) { + result[i] = allocArray(matrixSize) + } + val resultMatrix = multiplyMatrix(matrixSize, matrixSize, + first.map { it.toCValues().ptr }.toCValues().ptr, + matrixSize, matrixSize, + second.map { it.toCValues().ptr }.toCValues().ptr) + val resultOutput = buildString { + for (i in (0 until matrixSize)) { + for (j in (0 until matrixSize)) { + append(resultMatrix!![i]!![j]) + append(" ") + } + append("\n") + } + } + } + } +} + +actual class IntBenchmark actual constructor() { + val size = 20 + val array = Array(size, { (0 until size).random() }) + + actual fun intBenchmark() { + for (i in 1..benchmarkSize) { + average(array[0], array[1], array[2], array[3], array[4], array[5], array[6], array[7], array[8], + array[9], array[10], array[11], array[12], array[13], array[14], array[15], array[16], + array[17], array[18], array[19]) + } + } +} + +actual class BoxedIntBenchmark actual constructor() { + val size = 20 + val array = Array(size, { null }) + + init { + for (i in (0 until size)) { + val element: Int? = (0 until size).random() + array[i] = element + } + } + + actual fun boxedIntBenchmark() { + for (i in 1..benchmarkSize) { + average(array[0]!!, array[1]!!, array[2]!!, array[3]!!, array[4]!!, array[5]!!, array[6]!!, array[7]!!, array[8]!!, + array[9]!!, array[10]!!, array[11]!!, array[12]!!, array[13]!!, array[14]!!, array[15]!!, array[16]!!, + array[17]!!, array[18]!!, array[19]!!) + } + } +} \ No newline at end of file diff --git a/kotlin-native/performance/cinterop/src/main/kotlin/main.kt b/kotlin-native/performance/cinterop/src/main/kotlin/main.kt new file mode 100644 index 00000000000..e1b55452128 --- /dev/null +++ b/kotlin-native/performance/cinterop/src/main/kotlin/main.kt @@ -0,0 +1,48 @@ +/* + * Copyright 2010-2017 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + + +import org.jetbrains.structsProducedByMacrosBenchmarks.* +import org.jetbrains.benchmarksLauncher.* +import org.jetbrains.structsBenchmarks.* +import org.jetbrains.typesBenchmarks.* +import kotlinx.cli.* + +class CinteropLauncher : Launcher() { + override val benchmarks = BenchmarksCollection( + mutableMapOf( + "macros" to BenchmarkEntry(::macrosBenchmark), + "struct" to BenchmarkEntry(::structBenchmark), + "union" to BenchmarkEntry(::unionBenchmark), + "enum" to BenchmarkEntry(::enumBenchmark), + "stringToC" to BenchmarkEntryWithInit.create(::StringBenchmark, { stringToCBenchmark() }), + "stringToKotlin" to BenchmarkEntryWithInit.create(::StringBenchmark, { stringToKotlinBenchmark() }), + "intMatrix" to BenchmarkEntryWithInit.create(::IntMatrixBenchmark, { intMatrixBenchmark() }), + "int" to BenchmarkEntryWithInit.create(::IntBenchmark, { intBenchmark() }), + "boxedInt" to BenchmarkEntryWithInit.create(::BoxedIntBenchmark, { boxedIntBenchmark() }) + ) + ) +} + +fun main(args: Array) { + val launcher = CinteropLauncher() + BenchmarksRunner.runBenchmarks(args, { arguments: BenchmarkArguments -> + if (arguments is BaseBenchmarkArguments) { + launcher.launch(arguments.warmup, arguments.repeat, arguments.prefix, + arguments.filter, arguments.filterRegex, arguments.verbose) + } else emptyList() + }, benchmarksListAction = launcher::benchmarksListAction) +} \ No newline at end of file diff --git a/kotlin-native/performance/cinterop/src/main/kotlin/org/jetbrains/cinteropBenchmarks/structsBenchmark.kt b/kotlin-native/performance/cinterop/src/main/kotlin/org/jetbrains/cinteropBenchmarks/structsBenchmark.kt new file mode 100644 index 00000000000..0a88939a30f --- /dev/null +++ b/kotlin-native/performance/cinterop/src/main/kotlin/org/jetbrains/cinteropBenchmarks/structsBenchmark.kt @@ -0,0 +1,21 @@ +/* + * Copyright 2010-2017 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.jetbrains.structsBenchmarks + +expect fun structBenchmark() +expect fun unionBenchmark() +expect fun enumBenchmark() \ No newline at end of file diff --git a/kotlin-native/performance/cinterop/src/main/kotlin/org/jetbrains/cinteropBenchmarks/structsProducedByMacrosBenchmark.kt b/kotlin-native/performance/cinterop/src/main/kotlin/org/jetbrains/cinteropBenchmarks/structsProducedByMacrosBenchmark.kt new file mode 100644 index 00000000000..6d14c54ec0b --- /dev/null +++ b/kotlin-native/performance/cinterop/src/main/kotlin/org/jetbrains/cinteropBenchmarks/structsProducedByMacrosBenchmark.kt @@ -0,0 +1,19 @@ +/* + * Copyright 2010-2017 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.jetbrains.structsProducedByMacrosBenchmarks + +expect fun macrosBenchmark() \ No newline at end of file diff --git a/kotlin-native/performance/cinterop/src/main/kotlin/org/jetbrains/cinteropBenchmarks/typesBenchmark.kt b/kotlin-native/performance/cinterop/src/main/kotlin/org/jetbrains/cinteropBenchmarks/typesBenchmark.kt new file mode 100644 index 00000000000..735571fe397 --- /dev/null +++ b/kotlin-native/performance/cinterop/src/main/kotlin/org/jetbrains/cinteropBenchmarks/typesBenchmark.kt @@ -0,0 +1,31 @@ +/* + * Copyright 2010-2017 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.jetbrains.typesBenchmarks + +expect class StringBenchmark() { + fun stringToCBenchmark() + fun stringToKotlinBenchmark() +} +expect class IntBenchmark() { + fun intBenchmark() +} +expect class BoxedIntBenchmark() { + fun boxedIntBenchmark() +} +expect class IntMatrixBenchmark() { + fun intMatrixBenchmark() +} \ No newline at end of file diff --git a/kotlin-native/performance/cinterop/src/nativeInterop/cinterop/macros.def b/kotlin-native/performance/cinterop/src/nativeInterop/cinterop/macros.def new file mode 100644 index 00000000000..c422288cbb0 --- /dev/null +++ b/kotlin-native/performance/cinterop/src/nativeInterop/cinterop/macros.def @@ -0,0 +1,93 @@ +package = org.jetbrains.structsProducedByMacrosBenchmarks + +--- +#include +#include + +#define define_list(type) \ +\ + struct _list_##type; \ + \ + typedef struct \ + { \ + int (*is_empty)(const struct _list_##type*); \ + size_t (*size)(const struct _list_##type*); \ + const type (*front)(const struct _list_##type*); \ + void (*push_front)(struct _list_##type*, type); \ + } _list_functions_##type; \ + \ + typedef struct _list_elem_##type \ + { \ + type _data; \ + struct _list_elem_##type* _next; \ + } list_elem_##type; \ + \ + typedef struct _list_##type \ + { \ + size_t _size; \ + list_elem_##type* _first; \ + list_elem_##type* _last; \ + _list_functions_##type* _functions; \ + } List_##type; \ + \ + List_##type* new_list_##type(); \ + int list_is_empty_##type(const List_##type* list); \ + size_t list_size_##type(const List_##type* list); \ + const type list_front_##type(const List_##type* list); \ + void list_push_front_##type(List_##type* list, type elem); \ + \ + int list_is_empty_##type(const List_##type* list) \ + { \ + return list->_size == 0; \ + } \ + \ + size_t list_size_##type(const List_##type* list) \ + { \ + return list->_size; \ + } \ + \ + const type list_front_##type(const List_##type* list) \ + { \ + return list->_first->_data; \ + } \ + \ + void list_push_front_##type(List_##type* list, type elem) \ + { \ + struct _list_elem_##type* element = (struct _list_elem_##type*) malloc(sizeof(struct _list_elem_##type)); \ + element->_data = elem; \ + element->_next = list->_first; \ + list->_first = element; \ + list->_size++; \ + } \ + \ + _list_functions_##type _list_funcs_##type = { \ + &list_is_empty_##type, \ + &list_size_##type, \ + &list_front_##type, \ + &list_push_front_##type, \ + }; \ + \ + List_##type* new_list_##type() \ + { \ + List_##type* res = (List_##type*) malloc(sizeof(List_##type)); \ + res->_size = 0; \ + res->_first = NULL; \ + res->_functions = &_list_funcs_##type; \ + return res; \ + } \ + \ + void free_list_##type(List_##type* list) \ + { \ + struct _list_elem_##type* current = list->_first; \ + while (current != NULL) \ + { \ + struct _list_elem_##type* next = current->_next; \ + free(current); \ + current = next; \ + } \ + free(list); \ + } + + +define_list(int) +define_list(float) diff --git a/kotlin-native/performance/cinterop/src/nativeInterop/cinterop/struct.def b/kotlin-native/performance/cinterop/src/nativeInterop/cinterop/struct.def new file mode 100644 index 00000000000..8e7bfac37b1 --- /dev/null +++ b/kotlin-native/performance/cinterop/src/nativeInterop/cinterop/struct.def @@ -0,0 +1,97 @@ +package = org.jetbrains.structsBenchmarks +strictEnums = WeekDay + +--- +#include +#include +#include + +enum WeekDay {Sunday, Monday, Tuesday, Wednesday, Thursday, Friday, Saturday}; + +int isWeekEnd(enum WeekDay day) { + if (day == Saturday || day == Sunday) + return 1; + return 0; +} + +enum WeekDay getWeekDay(const char* date) { + if (strstr(date, "Sunday") != NULL) { + return Sunday; + } else if (strstr(date, "Monday") != NULL) { + return Monday; + } else if (strstr(date, "Tuesday") != NULL) { + return Tuesday; + } else if (strstr(date, "Wednesday") != NULL) { + return Wednesday; + } else if (strstr(date, "Thursday") != NULL) { + return Thursday; + } else if (strstr(date, "Friday") != NULL) { + return Friday; + } else if (strstr(date, "Saturday") != NULL) { + return Saturday; + } + abort(); +} + +struct ElementS { + long long integer; + float floatValue; + char string[32]; + + int (*contains)(const struct ElementS*, const struct ElementS*); +}; + +int elementContains(const struct ElementS* self, const struct ElementS* other) { + if (self == NULL || other == NULL) { + return 0; + } + if (strstr(self->string, other->string) != NULL) { + return 1; + } + return 0; +} + +union ElementU { + long long integer; + float floatValue; + char string[32]; +}; + +union ElementU multiplyElementU(union ElementU element, int coefficient) { + union ElementU newElement; + newElement.integer = coefficient * element.integer; + return newElement; +} + +struct ElementS multiplyElementS(struct ElementS element, int coefficient) { + struct ElementS newElement; + newElement.integer = coefficient * element.integer; + newElement.floatValue = coefficient * element.floatValue; + int i = 0; + while (element.string[i] != '\0') { + newElement.string[i] = coefficient * element.string[i]; + i++; + } + return newElement; +} + +union ElementU* sumElementUPtr(const union ElementU* first, const union ElementU* second) { + if (first == NULL || second == NULL) { + return NULL; + } + union ElementU* newElement = (union ElementU*)malloc(sizeof(union ElementU)); + newElement->integer = first->integer + second->integer; + return newElement; +} + +struct ElementS* sumElementSPtr(const struct ElementS* first, const struct ElementS* second) { + if (first == NULL || second == NULL) { + return NULL; + } + struct ElementS* newElement = (struct ElementS*)malloc(sizeof(struct ElementS)); + newElement->integer = first->integer + second->integer; + newElement->floatValue = first->floatValue + second->floatValue; + sprintf(newElement->string, "%d", newElement->integer); + return newElement; + +} \ No newline at end of file diff --git a/kotlin-native/performance/cinterop/src/nativeInterop/cinterop/types.def b/kotlin-native/performance/cinterop/src/nativeInterop/cinterop/types.def new file mode 100644 index 00000000000..c9107c7a723 --- /dev/null +++ b/kotlin-native/performance/cinterop/src/nativeInterop/cinterop/types.def @@ -0,0 +1,68 @@ +package = org.jetbrains.typesBenchmarks + +--- +#include +#include +#include +#include + +int charFrequency(const char* string, char charToFind) { + int frequency = 0; + for(int i = 0; string[i] != '\0'; ++i) { + if(charToFind == string[i]) + ++frequency; + } + return frequency; +} + +const char* findSuitableString(const char* stringsArray[], int arraySize, const char* stringToFind) { + for(int i = 0; i < arraySize; ++i) { + if (strstr(stringsArray[i], stringToFind) != NULL) { + char* result = (char*) malloc((strlen(stringsArray[i])+1)*sizeof(char)); + strcpy(result, stringsArray[i]); + return result; + } + } + return NULL; +} + +void freeSuitableString(char* unusedString) { + free(unusedString); +} + +unsigned long int sum(int array[], int arraySize) { + unsigned long int result = 0; + for(int i = 0; i < arraySize; ++i) { + result += array[i]; + } + return result; +} + +double average(int count, ...) { + va_list list; + int j = 0; + va_start(list, count); + double sum = 0; + for(j=0; j + project.ext.buildSteps.keySet().each { + dependsOn "$it$number" + } + } +} + +task configureBuild { + doLast { + mkdir "${buildDir.absolutePath}" + } +} + +(1..project.ext.repeatNumber).each { number -> + project.ext.buildSteps.each { taskName, command -> + tasks.create(name: "$taskName$number", type: Exec) { + commandLine command + ignoreExitValue true + doLast { + exitCodes[name] = execResult.exitValue + } + } + } +} + +task clean { + doLast { + delete "${buildDir.absolutePath}" + } +} + +task konanJsonReport { + doLast { + def nativeCompileTime = MPPTools.getCompileBenchmarkTime(project.ext.applicationName, project.ext.buildSteps.keySet(), + project.ext.repeatNumber, exitCodes) + def nativeExecutable = "${buildDir.absolutePath}/program${MPPTools.getNativeProgramExtension()}" + def properties = getCommonProperties() + ['type': 'native', + 'compilerVersion': "${konanVersion}".toString(), + 'benchmarks': "[]", + 'compileTime': nativeCompileTime, + 'codeSize': MPPTools.getCodeSizeBenchmark(project.ext.applicationName, nativeExecutable) ] + def output = MPPTools.createJsonReport(properties) + new File("${buildDir.absolutePath}/${nativeJson}").write(output) + } +} +task jvmRun { + println("JVM run isn't supported") +} + +task jvmJsonReport { + doLast { + println("JVM run isn't supported") + } +} + +jvmRun.finalizedBy jvmJsonReport +konanRun.finalizedBy konanJsonReport + +private def getCommonProperties() { + return ['cpu': System.getProperty("os.arch"), + 'os': System.getProperty("os.name"), // OperatingSystem.current().getName() + 'jdkVersion': System.getProperty("java.version"), // org.gradle.internal.jvm.Jvm.current().javaVersion + 'jdkVendor': System.getProperty("java.vendor"), + 'kotlinVersion': "${kotlinVersion}".toString()] +} + diff --git a/kotlin-native/performance/helloworld/build.gradle.kts b/kotlin-native/performance/helloworld/build.gradle.kts new file mode 100644 index 00000000000..4a2c4f521a0 --- /dev/null +++ b/kotlin-native/performance/helloworld/build.gradle.kts @@ -0,0 +1,29 @@ +/* + * Copyright 2010-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +import org.jetbrains.kotlin.getNativeProgramExtension +import org.jetbrains.kotlin.getCompileOnlyBenchmarksOpts + +plugins { + id("compile-benchmarking") +} + +val dist = file(findProperty("kotlin.native.home") ?: "dist") +val toolSuffix = if (System.getProperty("os.name").startsWith("Windows")) ".bat" else "" +val binarySuffix = getNativeProgramExtension() +val defaultCompilerOpts = listOf("-g") +val buildOpts = getCompileOnlyBenchmarksOpts(project, defaultCompilerOpts) + +compileBenchmark { + applicationName = "HelloWorld" + repeatNumber = 10 + compilerOpts = buildOpts + buildSteps { + step("runKonanc") { + command("$dist/bin/konanc$toolSuffix", "$projectDir/src/main/kotlin/main.kt", "-o", + "$buildDir/program$binarySuffix", *(buildOpts.toTypedArray())) + } + } +} diff --git a/kotlin-native/performance/helloworld/gradle.properties b/kotlin-native/performance/helloworld/gradle.properties new file mode 100644 index 00000000000..d7062dc22a1 --- /dev/null +++ b/kotlin-native/performance/helloworld/gradle.properties @@ -0,0 +1 @@ +kotlin.native.home=../../dist \ No newline at end of file diff --git a/kotlin-native/performance/helloworld/src/main/kotlin/main.kt b/kotlin-native/performance/helloworld/src/main/kotlin/main.kt new file mode 100644 index 00000000000..d41a74f9a74 --- /dev/null +++ b/kotlin-native/performance/helloworld/src/main/kotlin/main.kt @@ -0,0 +1,19 @@ +/* + * Copyright 2010-2019 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +fun main() { + println("Hello, World!") +} \ No newline at end of file diff --git a/kotlin-native/performance/numerical/build.gradle.kts b/kotlin-native/performance/numerical/build.gradle.kts new file mode 100644 index 00000000000..ede81d6f69c --- /dev/null +++ b/kotlin-native/performance/numerical/build.gradle.kts @@ -0,0 +1,53 @@ +/* + * Copyright 2010-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +import org.jetbrains.kotlin.benchmark.BenchmarkingPlugin +import org.jetbrains.kotlin.ExecClang +import org.jetbrains.kotlin.gradle.plugin.mpp.KotlinNativeTarget +import org.jetbrains.kotlin.gradle.plugin.mpp.NativeBuildType +import org.jetbrains.kotlin.konan.target.HostManager + +plugins { + id("benchmarking") +} + +val defaultBuildType = NativeBuildType.RELEASE + +benchmark { + applicationName = "Numerical" + commonSrcDirs = listOf("src/main/kotlin", "../../tools/benchmarks/shared/src/main/kotlin/report", "../shared/src/main/kotlin") + jvmSrcDirs = listOf("src/main/kotlin-jvm", "../shared/src/main/kotlin-jvm") + nativeSrcDirs = listOf("src/main/kotlin-native", "../shared/src/main/kotlin-native/common") + mingwSrcDirs = listOf("../shared/src/main/kotlin-native/mingw") + posixSrcDirs = listOf("../shared/src/main/kotlin-native/posix") + linkerOpts = listOf("$buildDir/pi.o") + buildType = (findProperty("nativeBuildType") as String?)?.let { NativeBuildType.valueOf(it) } ?: defaultBuildType + + dependencies.common(project(":endorsedLibraries:kotlinx.cli")) +} + +val compileLibary by tasks.creating { + doFirst { + mkdir(buildDir) + + project.withConvention(ExecClang::class) { + execKonanClang(HostManager.host) { + args("-O3") + args("-c", "$projectDir/src/nativeInterop/cinterop/pi.c") + args("-o", "$buildDir/pi.o") + } + } + } +} + +val native = kotlin.targets.getByName("native") as KotlinNativeTarget +native.apply { + compilations["main"].cinterops { + create("cinterop") { + headers("$projectDir/src/nativeInterop/cinterop/pi.h") + } + } + binaries.getExecutable(BenchmarkingPlugin.NATIVE_EXECUTABLE_NAME, "RELEASE").linkTask.dependsOn(compileLibary) +} diff --git a/kotlin-native/performance/numerical/gradle.properties b/kotlin-native/performance/numerical/gradle.properties new file mode 100644 index 00000000000..d7062dc22a1 --- /dev/null +++ b/kotlin-native/performance/numerical/gradle.properties @@ -0,0 +1 @@ +kotlin.native.home=../../dist \ No newline at end of file diff --git a/kotlin-native/performance/numerical/src/main/kotlin-jvm/launcher.kt b/kotlin-native/performance/numerical/src/main/kotlin-jvm/launcher.kt new file mode 100644 index 00000000000..1938943c781 --- /dev/null +++ b/kotlin-native/performance/numerical/src/main/kotlin-jvm/launcher.kt @@ -0,0 +1,21 @@ +/* + * Copyright 2010-2019 JetBrains s.r.o. and Kotlin Programming Language contributors. + * Use of this source code is governed by the Apache 2.0 license that can be found in the licenses/LICENSE.txt file. + */ + +import org.jetbrains.benchmarksLauncher.* + +actual class NumericalLauncher : Launcher() { + override val benchmarks = BenchmarksCollection( + mutableMapOf( + "BellardPi" to BenchmarkEntry(::jvmBellardPi) + ) + ) +} + +fun jvmBellardPi() { + for (n in 1 .. 1000 step 9) { + val result = pi_nth_digit(n) + Blackhole.consume(result) + } +} diff --git a/kotlin-native/performance/numerical/src/main/kotlin-native/launcher.kt b/kotlin-native/performance/numerical/src/main/kotlin-native/launcher.kt new file mode 100644 index 00000000000..af7cdef7fb7 --- /dev/null +++ b/kotlin-native/performance/numerical/src/main/kotlin-native/launcher.kt @@ -0,0 +1,27 @@ +/* + * Copyright 2010-2019 JetBrains s.r.o. and Kotlin Programming Language contributors. + * Use of this source code is governed by the Apache 2.0 license that can be found in the licenses/LICENSE.txt file. + */ + +import org.jetbrains.benchmarksLauncher.* + +actual class NumericalLauncher : Launcher() { + override val benchmarks = BenchmarksCollection( + mutableMapOf( + "BellardPi" to BenchmarkEntry(::konanBellardPi), + "BellardPiCinterop" to BenchmarkEntry(::clangBellardPi) + ) + ) +} + +fun konanBellardPi() { + for (n in 1 .. 1000 step 9) { + val result = pi_nth_digit(n) + Blackhole.consume(result) + } +} + +fun clangBellardPi() { + for (n in 1 .. 1000 step 9) + cinterop.pi_nth_digit(n) +} diff --git a/kotlin-native/performance/numerical/src/main/kotlin/main.kt b/kotlin-native/performance/numerical/src/main/kotlin/main.kt new file mode 100644 index 00000000000..395d532fb16 --- /dev/null +++ b/kotlin-native/performance/numerical/src/main/kotlin/main.kt @@ -0,0 +1,20 @@ +/* + * Copyright 2010-2019 JetBrains s.r.o. and Kotlin Programming Language contributors. + * Use of this source code is governed by the Apache 2.0 license that can be found in the licenses/LICENSE.txt file. + */ + +import org.jetbrains.benchmarksLauncher.* +import kotlinx.cli.* + +expect class NumericalLauncher() : Launcher { +} + +fun main(args: Array) { + val launcher = NumericalLauncher() + BenchmarksRunner.runBenchmarks(args, { arguments: BenchmarkArguments -> + if (arguments is BaseBenchmarkArguments) { + launcher.launch(arguments.warmup, arguments.repeat, arguments.prefix, + arguments.filter, arguments.filterRegex, arguments.verbose) + } else emptyList() + }, benchmarksListAction = launcher::benchmarksListAction) +} \ No newline at end of file diff --git a/kotlin-native/performance/numerical/src/main/kotlin/pi.kt b/kotlin-native/performance/numerical/src/main/kotlin/pi.kt new file mode 100644 index 00000000000..7094cf62145 --- /dev/null +++ b/kotlin-native/performance/numerical/src/main/kotlin/pi.kt @@ -0,0 +1,152 @@ +/* + * Computation of the n'th decimal digit of \pi with very little memory. + * Written by Fabrice Bellard on January 8, 1997. + * + * We use a slightly modified version of the method described by Simon + * Plouffe in "On the Computation of the n'th decimal digit of various + * transcendental numbers" (November 1996). We have modified the algorithm + * to get a running time of O(n^2) instead of O(n^3log(n)^3). + */ + +import kotlin.math.ln +import kotlin.math.sqrt + +private fun mul_mod(a: Int, b: Int, m: Int) + = ((a.toLong() * b.toLong()) % m).toInt() + +/* return the inverse of x mod y */ +private fun inv_mod(x: Int, y: Int): Int { + var u = x + var v = y + var c = 1 + var a = 0 + do { + val q = v / u + var t = c + c = a - q * c + a = t + t = u + u = v - q * u + v = t + } while (u != 0) + a = a % y + if (a < 0) + a = y + a + return a +} + +/* return (a^b) mod m */ +private fun pow_mod(a: Int, b: Int, m: Int): Int { + var b = b + var r = 1 + var aa = a + while (true) { + if (b and 1 != 0) + r = mul_mod(r, aa, m) + b = b shr 1 + if (b == 0) + break + aa = mul_mod(aa, aa, m) + } + return r +} + +/* return true if n is prime */ +private fun is_prime(n: Int): Boolean { + if (n % 2 == 0) + return false + val r = sqrt(n.toDouble()).toInt() + var i = 3 + while (i <= r) { + if (n % i == 0) + return false + i += 2 + } + return true +} + +/* return the prime number immediatly after n */ +private fun next_prime(n: Int): Int { + var n = n + do { + n++ + } while (!is_prime(n)) + return n +} + +fun pi_nth_digit(n: Int): Int { + + val N = ((n + 20) * ln(10.0) / ln(2.0)).toInt() + var sum = 0.0 + var a = 3 + var t: Int + + while (a <= 2 * N) { + + val vmax = (ln((2 * N).toDouble()) / ln(a.toDouble())).toInt() + var av = 1 + var i = 0 + while (i < vmax) { + av = av * a + i++ + } + + var s = 0 + var num = 1 + var den = 1 + var v = 0 + var kq = 1 + var kq2 = 1 + + var k = 1 + while (k <= N) { + + t = k + if (kq >= a) { + do { + t = t / a + v-- + } while (t % a == 0) + kq = 0 + } + kq++ + num = mul_mod(num, t, av) + + t = 2 * k - 1 + if (kq2 >= a) { + if (kq2 == a) { + do { + t = t / a + v++ + } while (t % a == 0) + } + kq2 -= a + } + den = mul_mod(den, t, av) + kq2 += 2 + + if (v > 0) { + t = inv_mod(den, av) + t = mul_mod(t, num, av) + t = mul_mod(t, k, av) + i = v + while (i < vmax) { + t = mul_mod(t, a, av) + i++ + } + s += t + if (s >= av) + s -= av + } + k++ + + } + + t = pow_mod(10, n - 1, av) + s = mul_mod(s, t, av) + sum = (sum + s.toDouble() / av.toDouble()) % 1.0 + a = next_prime(a) + } + + return (sum * 1e9).toInt() +} diff --git a/kotlin-native/performance/numerical/src/nativeInterop/cinterop/cinterop.def b/kotlin-native/performance/numerical/src/nativeInterop/cinterop/cinterop.def new file mode 100644 index 00000000000..ffaef08905d --- /dev/null +++ b/kotlin-native/performance/numerical/src/nativeInterop/cinterop/cinterop.def @@ -0,0 +1 @@ +package = cinterop diff --git a/kotlin-native/performance/numerical/src/nativeInterop/cinterop/pi.c b/kotlin-native/performance/numerical/src/nativeInterop/cinterop/pi.c new file mode 100644 index 00000000000..129e8a976aa --- /dev/null +++ b/kotlin-native/performance/numerical/src/nativeInterop/cinterop/pi.c @@ -0,0 +1,163 @@ +/* + * Computation of the n'th decimal digit of \pi with very little memory. + * Written by Fabrice Bellard on January 8, 1997. + * + * We use a slightly modified version of the method described by Simon + * Plouffe in "On the Computation of the n'th decimal digit of various + * transcendental numbers" (November 1996). We have modified the algorithm + * to get a running time of O(n^2) instead of O(n^3log(n)^3). + * + * This program uses mostly integer arithmetic. It may be slow on some + * hardwares where integer multiplications and divisons must be done + * by software. We have supposed that 'int' has a size of 32 bits. If + * your compiler supports 'long long' integers of 64 bits, you may use + * the integer version of 'mul_mod' (see HAS_LONG_LONG). + */ + +#include + +/* uncomment the following line to use 'long long' integers */ +#define HAS_LONG_LONG + +#ifdef HAS_LONG_LONG +#define mul_mod(a,b,m) (( (long long) (a) * (long long) (b) ) % (m)) +#else +#define mul_mod(a,b,m) fmod( (double) a * (double) b, m) +#endif + +/* return the inverse of x mod y */ +static int inv_mod(int x, int y) +{ + int q, u, v, a, c, t; + + u = x; + v = y; + c = 1; + a = 0; + do { + q = v / u; + + t = c; + c = a - q * c; + a = t; + + t = u; + u = v - q * u; + v = t; + } while (u != 0); + a = a % y; + if (a < 0) + a = y + a; + return a; +} + +/* return (a^b) mod m */ +static int pow_mod(int a, int b, int m) +{ + int r, aa; + + r = 1; + aa = a; + while (1) { + if (b & 1) + r = mul_mod(r, aa, m); + b = b >> 1; + if (b == 0) + break; + aa = mul_mod(aa, aa, m); + } + return r; +} + +/* return true if n is prime */ +static int is_prime(int n) +{ + int r, i; + if ((n % 2) == 0) + return 0; + + r = (int) (sqrt(n)); + for (i = 3; i <= r; i += 2) + if ((n % i) == 0) + return 0; + return 1; +} + +/* return the prime number immediatly after n */ +static int next_prime(int n) +{ + do { + n++; + } while (!is_prime(n)); + return n; +} + +int pi_nth_digit(int n) +{ + int av, a, vmax, N, num, den, k, kq, kq2, t, v, s, i; + double sum; + + N = (int) ((n + 20) * log(10) / log(2)); + + sum = 0; + + for (a = 3; a <= (2 * N); a = next_prime(a)) { + + vmax = (int) (log(2 * N) / log(a)); + av = 1; + for (i = 0; i < vmax; i++) + av = av * a; + + s = 0; + num = 1; + den = 1; + v = 0; + kq = 1; + kq2 = 1; + + for (k = 1; k <= N; k++) { + + t = k; + if (kq >= a) { + do { + t = t / a; + v--; + } while ((t % a) == 0); + kq = 0; + } + kq++; + num = mul_mod(num, t, av); + + t = (2 * k - 1); + if (kq2 >= a) { + if (kq2 == a) { + do { + t = t / a; + v++; + } while ((t % a) == 0); + } + kq2 -= a; + } + den = mul_mod(den, t, av); + kq2 += 2; + + if (v > 0) { + t = inv_mod(den, av); + t = mul_mod(t, num, av); + t = mul_mod(t, k, av); + for (i = v; i < vmax; i++) + t = mul_mod(t, a, av); + s += t; + if (s >= av) + s -= av; + } + + } + + t = pow_mod(10, n - 1, av); + s = mul_mod(s, t, av); + sum = fmod(sum + (double) s / (double) av, 1.0); + } + + return (int) (sum * 1e9); +} diff --git a/kotlin-native/performance/numerical/src/nativeInterop/cinterop/pi.h b/kotlin-native/performance/numerical/src/nativeInterop/cinterop/pi.h new file mode 100644 index 00000000000..5703de71b38 --- /dev/null +++ b/kotlin-native/performance/numerical/src/nativeInterop/cinterop/pi.h @@ -0,0 +1,16 @@ +/* + * Computation of the n'th decimal digit of \pi with very little memory. + * Written by Fabrice Bellard on January 8, 1997. + * + * We use a slightly modified version of the method described by Simon + * Plouffe in "On the Computation of the n'th decimal digit of various + * transcendental numbers" (November 1996). We have modified the algorithm + * to get a running time of O(n^2) instead of O(n^3log(n)^3). + */ + +#ifndef _BELLARD_PI_H +#define _BELLARD_PI_H + +int pi_nth_digit(int n); + +#endif /*_BELLARD_PI_H*/ diff --git a/kotlin-native/performance/objcinterop/build.gradle.kts b/kotlin-native/performance/objcinterop/build.gradle.kts new file mode 100644 index 00000000000..71c4c7322f1 --- /dev/null +++ b/kotlin-native/performance/objcinterop/build.gradle.kts @@ -0,0 +1,53 @@ +/* + * Copyright 2010-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +import org.jetbrains.kotlin.benchmark.BenchmarkingPlugin +import org.jetbrains.kotlin.ExecClang +import org.jetbrains.kotlin.gradle.plugin.mpp.KotlinNativeTarget +import org.jetbrains.kotlin.gradle.plugin.mpp.NativeBuildType +import org.jetbrains.kotlin.konan.target.HostManager + +plugins { + id("benchmarking") +} + +val defaultBuildType = NativeBuildType.RELEASE + +benchmark { + applicationName = "ObjCInterop" + commonSrcDirs = listOf("../../tools/benchmarks/shared/src/main/kotlin/report", "src/main/kotlin", "../shared/src/main/kotlin") + jvmSrcDirs = listOf("src/main/kotlin-jvm", "../shared/src/main/kotlin-jvm") + nativeSrcDirs = listOf("src/main/kotlin-native", "../shared/src/main/kotlin-native/common") + mingwSrcDirs = listOf("src/main/kotlin-native", "../shared/src/main/kotlin-native/mingw") + posixSrcDirs = listOf("src/main/kotlin-native", "../shared/src/main/kotlin-native/posix") + linkerOpts = listOf("-L$buildDir", "-lcomplexnumbers") + buildType = (findProperty("nativeBuildType") as String?)?.let { NativeBuildType.valueOf(it) } ?: defaultBuildType + + dependencies.common(project(":endorsedLibraries:kotlinx.cli")) +} + +val compileLibary by tasks.creating { + doFirst { + mkdir(buildDir) + + project.withConvention(ExecClang::class) { + execKonanClang(HostManager.host) { + args("$projectDir/src/nativeInterop/cinterop/complexNumbers.m") + args("-lobjc", "-fobjc-arc") + args("-fPIC", "-shared", "-o", "$buildDir/libcomplexnumbers.dylib") + } + } + } +} + +val native = kotlin.targets.getByName("native") as KotlinNativeTarget +native.apply { + compilations["main"].cinterops { + create("classes") { + headers("$projectDir/src/nativeInterop/cinterop/complexNumbers.h") + } + } + binaries.getExecutable(BenchmarkingPlugin.NATIVE_EXECUTABLE_NAME, "RELEASE").linkTask.dependsOn(compileLibary) +} \ No newline at end of file diff --git a/kotlin-native/performance/objcinterop/gradle.properties b/kotlin-native/performance/objcinterop/gradle.properties new file mode 100644 index 00000000000..d7062dc22a1 --- /dev/null +++ b/kotlin-native/performance/objcinterop/gradle.properties @@ -0,0 +1 @@ +kotlin.native.home=../../dist \ No newline at end of file diff --git a/kotlin-native/performance/objcinterop/src/main/kotlin-jvm/org/jetbrains/objCInteropBenchmarks/complexNumbers.kt b/kotlin-native/performance/objcinterop/src/main/kotlin-jvm/org/jetbrains/objCInteropBenchmarks/complexNumbers.kt new file mode 100644 index 00000000000..0394b3f708e --- /dev/null +++ b/kotlin-native/performance/objcinterop/src/main/kotlin-jvm/org/jetbrains/objCInteropBenchmarks/complexNumbers.kt @@ -0,0 +1,39 @@ +/* + * Copyright 2010-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ +package org.jetbrains.complexNumbers + +actual class ComplexNumber() {} + +actual class ComplexNumbersBenchmark actual constructor() { + actual fun generateNumbersSequence(): List { + error("Benchmark generateNumbersSequence is unsupported on JVM!") + } + + actual fun sumComplex() { + error("Benchmark sumComplex is unsupported on JVM!") + } + + actual fun subComplex() { + error("Benchmark subComplex is unsupported on JVM!") + } + actual fun classInheritance() { + error("Benchmark classInheritance is unsupported on JVM!") + } + actual fun categoryMethods() { + error("Benchmark categoryMethods is unsupported on JVM!") + } + actual fun stringToObjC() { + error("Benchmark stringToObjC is unsupported on JVM!") + } + actual fun stringFromObjC() { + error("Benchmark stringToObjC is unsupported on JVM!") + } + actual fun fft() { + error("Benchmark fft is unsupported on JVM!") + } + actual fun invertFft() { + error("Benchmark invertFft is unsupported on JVM!") + } +} diff --git a/kotlin-native/performance/objcinterop/src/main/kotlin-native/org/jetbrains/objCinteropBenchmarks/complexNumbers.kt b/kotlin-native/performance/objcinterop/src/main/kotlin-native/org/jetbrains/objCinteropBenchmarks/complexNumbers.kt new file mode 100644 index 00000000000..2d7acc13b14 --- /dev/null +++ b/kotlin-native/performance/objcinterop/src/main/kotlin-native/org/jetbrains/objCinteropBenchmarks/complexNumbers.kt @@ -0,0 +1,134 @@ +/* + * Copyright 2010-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +package org.jetbrains.complexNumbers +import kotlinx.cinterop.* +import platform.posix.* +import kotlin.math.sqrt +import kotlin.math.PI +import kotlin.math.cos +import kotlin.math.sin +import kotlin.random.Random +import platform.Foundation.* +import platform.darwin.* + +actual typealias ComplexNumber = Complex + +actual class ComplexNumbersBenchmark actual constructor() { + val complexNumbersSequence = generateNumbersSequence() + + fun randomNumber() = Random.nextDouble(0.0, benchmarkSize.toDouble()) + + actual fun generateNumbersSequence(): List { + val result = mutableListOf() + for (i in 1..benchmarkSize) { + result.add(Complex(randomNumber(), randomNumber())) + } + return result + } + + actual fun sumComplex() { + complexNumbersSequence.map { it.add(it) }.reduce { acc, it -> acc.add(it) } + } + + actual fun subComplex() { + complexNumbersSequence.map { it.sub(it) }.reduce { acc, it -> acc.sub(it) } + } + + actual fun classInheritance() { + class InvertedNumber(val value: Double) : CustomNumberProtocol, NSObject() { + override fun add(other: CustomNumberProtocol) : CustomNumberProtocol = + if (other is InvertedNumber) + InvertedNumber(-value + sqrt(other.value)) + else + error("Expected object of InvertedNumber class") + + + override fun sub(other: CustomNumberProtocol) : CustomNumberProtocol = + if (other is InvertedNumber) + InvertedNumber(-value - sqrt(other.value)) + else + error("Expected object of InvertedNumber class") + } + + val result = InvertedNumber(0.0) + + for (i in 1..benchmarkSize) { + result.add(InvertedNumber(randomNumber())) + result.sub(InvertedNumber(randomNumber())) + } + } + + actual fun categoryMethods() { + complexNumbersSequence.map { it.mul(it) }.reduce { acc, it -> acc.mul(it) } + complexNumbersSequence.map { it.div(it) }.reduce { acc, it -> acc.mul(it) } + } + + actual fun stringToObjC() { + complexNumbersSequence.forEach { + it.setFormat("%.1lf|%.1lf") + } + } + + actual fun stringFromObjC() { + complexNumbersSequence.forEach { + it.description()?.split(" ") + } + } + + private fun revert(number: Int, lg: Int): Int { + var result = 0 + for (i in 0 until lg) { + if (number and (1 shl i) != 0) { + result = result or 1 shl (lg - i - 1) + } + } + return result + } + + inline private fun fftRoutine(invert:Boolean = false): Array { + var lg = 0 + while ((1 shl lg) < complexNumbersSequence.size) { + lg++ + } + val sequence = complexNumbersSequence.toTypedArray() + + sequence.forEachIndexed { index, number -> + if (index < revert(index, lg) && revert(index, lg) < complexNumbersSequence.size) { + sequence[index] = sequence[revert(index, lg)].also { sequence[revert(index, lg)] = sequence[index] } + } + } + + var length = 2 + while (length < complexNumbersSequence.size) { + val angle = 2 * PI / length * if (invert) -1 else 1 + val base = Complex(cos(angle), sin(angle)) + for (i in 0 until complexNumbersSequence.size / 2 step length) { + var value = Complex(1.0, 1.0) + for (j in 0 until length/2) { + val first = sequence[i + j] + val second = sequence[i + j + length/2].mul(value) + sequence[i + j] = first.add(second) as Complex + sequence[i + j + length/2] = first.sub(second) as Complex + value = value.mul(base) + } + } + length = length shl 1 + } + return sequence + } + + actual fun fft() { + fftRoutine() + } + + actual fun invertFft() { + val sequence = fftRoutine(true) + + sequence.forEachIndexed { index, number -> + sequence[index] = number.div(Complex(sequence.size.toDouble(), 0.0)) + } + } +} diff --git a/kotlin-native/performance/objcinterop/src/main/kotlin/main.kt b/kotlin-native/performance/objcinterop/src/main/kotlin/main.kt new file mode 100644 index 00000000000..b37ea14bbe2 --- /dev/null +++ b/kotlin-native/performance/objcinterop/src/main/kotlin/main.kt @@ -0,0 +1,35 @@ +/* + * Copyright 2010-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + + +import org.jetbrains.benchmarksLauncher.* +import org.jetbrains.complexNumbers.* +import kotlinx.cli.* + +class ObjCInteropLauncher: Launcher() { + override val benchmarks = BenchmarksCollection( + mutableMapOf( + "generateNumbersSequence" to BenchmarkEntryWithInit.create(::ComplexNumbersBenchmark, { generateNumbersSequence() }), + "sumComplex" to BenchmarkEntryWithInit.create(::ComplexNumbersBenchmark, { sumComplex() }), + "subComplex" to BenchmarkEntryWithInit.create(::ComplexNumbersBenchmark, { subComplex() }), + "classInheritance" to BenchmarkEntryWithInit.create(::ComplexNumbersBenchmark, { classInheritance() }), + "categoryMethods" to BenchmarkEntryWithInit.create(::ComplexNumbersBenchmark, { categoryMethods() }), + "stringToObjC" to BenchmarkEntryWithInit.create(::ComplexNumbersBenchmark, { stringToObjC() }), + "stringFromObjC" to BenchmarkEntryWithInit.create(::ComplexNumbersBenchmark, { stringFromObjC() }), + "fft" to BenchmarkEntryWithInit.create(::ComplexNumbersBenchmark, { fft() }), + "invertFft" to BenchmarkEntryWithInit.create(::ComplexNumbersBenchmark, { invertFft() }) + ) + ) +} + +fun main(args: Array) { + val launcher = ObjCInteropLauncher() + BenchmarksRunner.runBenchmarks(args, { arguments: BenchmarkArguments -> + if (arguments is BaseBenchmarkArguments) { + launcher.launch(arguments.warmup, arguments.repeat, arguments.prefix, + arguments.filter, arguments.filterRegex, arguments.verbose) + } else emptyList() + }, benchmarksListAction = launcher::benchmarksListAction) +} \ No newline at end of file diff --git a/kotlin-native/performance/objcinterop/src/main/kotlin/org/jetbrains/objCinteropBenchmarks/complexNumbers.kt b/kotlin-native/performance/objcinterop/src/main/kotlin/org/jetbrains/objCinteropBenchmarks/complexNumbers.kt new file mode 100644 index 00000000000..4421bba47f8 --- /dev/null +++ b/kotlin-native/performance/objcinterop/src/main/kotlin/org/jetbrains/objCinteropBenchmarks/complexNumbers.kt @@ -0,0 +1,22 @@ +/* + * Copyright 2010-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +package org.jetbrains.complexNumbers + +const val benchmarkSize = 10000 + +expect class ComplexNumber + +expect class ComplexNumbersBenchmark() { + fun generateNumbersSequence(): List + fun sumComplex() + fun subComplex() + fun classInheritance() + fun categoryMethods() + fun stringToObjC() + fun stringFromObjC() + fun fft() + fun invertFft() +} \ No newline at end of file diff --git a/kotlin-native/performance/objcinterop/src/nativeInterop/cinterop/classes.def b/kotlin-native/performance/objcinterop/src/nativeInterop/cinterop/classes.def new file mode 100644 index 00000000000..2b36d4ee0e6 --- /dev/null +++ b/kotlin-native/performance/objcinterop/src/nativeInterop/cinterop/classes.def @@ -0,0 +1,2 @@ +package = org.jetbrains.complexNumbers +language = Objective-C \ No newline at end of file diff --git a/kotlin-native/performance/objcinterop/src/nativeInterop/cinterop/complexNumbers.h b/kotlin-native/performance/objcinterop/src/nativeInterop/cinterop/complexNumbers.h new file mode 100644 index 00000000000..bc61981df01 --- /dev/null +++ b/kotlin-native/performance/objcinterop/src/nativeInterop/cinterop/complexNumbers.h @@ -0,0 +1,22 @@ +#import + +@protocol CustomNumber +@required +- (id _Nonnull)add: (id _Nonnull)other; +- (id _Nonnull)sub: (id _Nonnull)other; +@end + +@interface Complex : NSObject + +@property (nonatomic, readonly) double re; +@property (nonatomic, readonly) double im; +@property (nonatomic, readwrite) NSString *format; + +- (id)initWithRe: (double)re andIm: (double)im; ++ (Complex *)complexWithRe: (double)re im: (double)im; +@end + +@interface Complex (CategorizedComplex) +- (Complex * _Nonnull)mul: (Complex * _Nonnull)other; +- (Complex * _Nonnull)div: (Complex * _Nonnull)other; +@end diff --git a/kotlin-native/performance/objcinterop/src/nativeInterop/cinterop/complexNumbers.m b/kotlin-native/performance/objcinterop/src/nativeInterop/cinterop/complexNumbers.m new file mode 100644 index 00000000000..7d837f5775b --- /dev/null +++ b/kotlin-native/performance/objcinterop/src/nativeInterop/cinterop/complexNumbers.m @@ -0,0 +1,62 @@ +#import +#import "complexNumbers.h" + +@implementation Complex +{ + double re; + double im; + NSString *format; +} +- (id)init { + return [self initWithRe: 0.0 andIm: 0.0]; +} + +- (id)initWithRe: (double)_re andIm: (double)_im { + if (self = [super init]) { + re = _re; + im = _im; + format = @"re: %.1lf im: %.1lf"; + } + return self; +} + ++ (Complex *)complexWithRe: (double)re im: (double)im { + return [[Complex alloc] initWithRe: re andIm: im]; +} +- (id _Nonnull)add: (id _Nonnull)other { + if ([self isKindOfClass:[Complex class]]) { + Complex * otherComplex = (Complex *)other; + return [[Complex alloc] initWithRe: re + otherComplex->re andIm: im + otherComplex->im]; + } + return NULL; +} + +- (id _Nonnull)sub: (id _Nonnull)other { + if ([self isKindOfClass:[Complex class]]) { + Complex * otherComplex = (Complex *)other; + return [[Complex alloc] initWithRe: re - otherComplex->re andIm: im - otherComplex->im]; + } + return NULL; +} + +- (NSString *)description { + return [NSString stringWithFormat: format, re, im]; +} +@end + +@implementation Complex (CategorizedComplex) +- (Complex * _Nonnull)mul: (Complex * _Nonnull)other { + return [Complex complexWithRe: re * other.re - im * other.im im: re * other.im + im * other.re]; +} +- (Complex * _Nonnull)div: (Complex * _Nonnull)other { + double retRe; + double retIm; + double denominator; + denominator = other.re * other.re + other.im * other.im; + if (!denominator) + return nil; + retRe = (re * other.re + im * other.im) / denominator; + retIm = (im * other.re - re * other.im) / denominator; + return [Complex complexWithRe: retRe im: retIm]; +} +@end \ No newline at end of file diff --git a/kotlin-native/performance/ring/build.gradle.kts b/kotlin-native/performance/ring/build.gradle.kts new file mode 100644 index 00000000000..2eda534e016 --- /dev/null +++ b/kotlin-native/performance/ring/build.gradle.kts @@ -0,0 +1,24 @@ +import org.jetbrains.kotlin.gradle.plugin.mpp.NativeBuildType + +/* + * Copyright 2010-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +plugins { + id("benchmarking") +} + +val defaultBuildType = NativeBuildType.RELEASE + +benchmark { + applicationName = "Ring" + commonSrcDirs = listOf("../../tools/benchmarks/shared/src/main/kotlin/report", "src/main/kotlin", "../shared/src/main/kotlin") + jvmSrcDirs = listOf("src/main/kotlin-jvm", "../shared/src/main/kotlin-jvm") + nativeSrcDirs = listOf("src/main/kotlin-native", "../shared/src/main/kotlin-native/common") + mingwSrcDirs = listOf("src/main/kotlin-native", "../shared/src/main/kotlin-native/mingw") + posixSrcDirs = listOf("src/main/kotlin-native", "../shared/src/main/kotlin-native/posix") + buildType = (findProperty("nativeBuildType") as String?)?.let { NativeBuildType.valueOf(it) } ?: defaultBuildType + + dependencies.common(project(":endorsedLibraries:kotlinx.cli")) +} diff --git a/kotlin-native/performance/ring/gradle.properties b/kotlin-native/performance/ring/gradle.properties new file mode 100644 index 00000000000..d7062dc22a1 --- /dev/null +++ b/kotlin-native/performance/ring/gradle.properties @@ -0,0 +1 @@ +kotlin.native.home=../../dist \ No newline at end of file diff --git a/kotlin-native/performance/ring/src/main/kotlin-jvm/FakeKonanNamespace.kt b/kotlin-native/performance/ring/src/main/kotlin-jvm/FakeKonanNamespace.kt new file mode 100644 index 00000000000..0e09a23a64e --- /dev/null +++ b/kotlin-native/performance/ring/src/main/kotlin-jvm/FakeKonanNamespace.kt @@ -0,0 +1,5 @@ +package org.jetbrains.ring + +class konan { + annotation class ThreadLocal +} \ No newline at end of file diff --git a/kotlin-native/performance/ring/src/main/kotlin-jvm/cleanup.kt b/kotlin-native/performance/ring/src/main/kotlin-jvm/cleanup.kt new file mode 100644 index 00000000000..4bdbdce2419 --- /dev/null +++ b/kotlin-native/performance/ring/src/main/kotlin-jvm/cleanup.kt @@ -0,0 +1,3 @@ +package org.jetbrains.ring + +actual fun cleanup() { } \ No newline at end of file diff --git a/kotlin-native/performance/ring/src/main/kotlin-jvm/org/jetbrains/ring/UtilsJVM.kt b/kotlin-native/performance/ring/src/main/kotlin-jvm/org/jetbrains/ring/UtilsJVM.kt new file mode 100644 index 00000000000..6f4742bab4b --- /dev/null +++ b/kotlin-native/performance/ring/src/main/kotlin-jvm/org/jetbrains/ring/UtilsJVM.kt @@ -0,0 +1,101 @@ +/* + * Copyright 2010-2017 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.jetbrains.ring + +import java.util.concurrent.atomic.AtomicReferenceFieldUpdater +import java.util.concurrent.locks.ReentrantLock + +internal var interceptor: AtomicOperationInterceptor = DefaultInterceptor + private set +private val interceptorLock = ReentrantLock() + +internal fun lockAndSetInterceptor(impl: AtomicOperationInterceptor) { + if (!interceptorLock.tryLock() || interceptor !== DefaultInterceptor) { + error("Interceptor is locked by another test: $interceptor") + } + interceptor = impl +} + +internal fun unlockAndResetInterceptor(impl: AtomicOperationInterceptor) { + check(interceptor === impl) { "Unexpected interceptor found: $interceptor" } + interceptor = DefaultInterceptor + interceptorLock.unlock() +} + +/** + * Interceptor for modifications of atomic variables. + */ +internal open class AtomicOperationInterceptor { + open fun beforeUpdate(ref: AtomicRef) {} + open fun afterSet(ref: AtomicRef, newValue: T) {} + open fun afterRMW(ref: AtomicRef, oldValue: T, newValue: T) {} +} + +private object DefaultInterceptor : AtomicOperationInterceptor() { + override fun toString(): String = "DefaultInterceptor" +} + +@Suppress("UNCHECKED_CAST") +public actual class AtomicRef internal constructor(value: T) { + /** + * Reading/writing this property maps to read/write of volatile variable. + */ + @Volatile + public actual var value: T = value + set(value) { + interceptor.beforeUpdate(this) + field = value + interceptor.afterSet(this, value) + } + + /** + * Maps to [AtomicReferenceFieldUpdater.lazySet]. + */ + public actual fun lazySet(value: T) { + interceptor.beforeUpdate(this) + FU.lazySet(this, value) + interceptor.afterSet(this, value) + } + + /** + * Maps to [AtomicReferenceFieldUpdater.compareAndSet]. + */ + public actual fun compareAndSet(expect: T, update: T): Boolean { + interceptor.beforeUpdate(this) + val result = FU.compareAndSet(this, expect, update) + if (result) interceptor.afterRMW(this, expect, update) + return result + } + + /** + * Maps to [AtomicReferenceFieldUpdater.getAndSet]. + */ + public actual fun getAndSet(value: T): T { + interceptor.beforeUpdate(this) + val oldValue = FU.getAndSet(this, value) as T + interceptor.afterRMW(this, oldValue, value) + return oldValue + } + + override fun toString(): String = value.toString() + + private companion object { + private val FU = AtomicReferenceFieldUpdater.newUpdater(AtomicRef::class.java, Any::class.java, "value") + } +} + +public actual fun atomic(initial: T): AtomicRef = AtomicRef(initial) \ No newline at end of file diff --git a/kotlin-native/performance/ring/src/main/kotlin-native/cleanup.kt b/kotlin-native/performance/ring/src/main/kotlin-native/cleanup.kt new file mode 100644 index 00000000000..a27ad95cf8d --- /dev/null +++ b/kotlin-native/performance/ring/src/main/kotlin-native/cleanup.kt @@ -0,0 +1,5 @@ +package org.jetbrains.ring + +import kotlin.native.internal.GC + +actual fun cleanup() { GC.collect() } \ No newline at end of file diff --git a/kotlin-native/performance/ring/src/main/kotlin-native/org/jetbrains/ring/Utils.kt b/kotlin-native/performance/ring/src/main/kotlin-native/org/jetbrains/ring/Utils.kt new file mode 100644 index 00000000000..113db5e1c23 --- /dev/null +++ b/kotlin-native/performance/ring/src/main/kotlin-native/org/jetbrains/ring/Utils.kt @@ -0,0 +1,53 @@ +/* + * Copyright 2010-2017 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.jetbrains.ring + +import kotlin.native.concurrent.FreezableAtomicReference as KAtomicRef +import kotlin.native.concurrent.isFrozen +import kotlin.native.concurrent.freeze + +public actual class AtomicRef constructor(@PublishedApi internal val a: KAtomicRef) { + public actual inline var value: T + get() = a.value + set(value) { + if (a.isFrozen) value.freeze() + a.value = value + } + + public actual inline fun lazySet(value: T) { + if (a.isFrozen) value.freeze() + a.value = value + } + + public actual inline fun compareAndSet(expect: T, update: T): Boolean { + if (a.isFrozen) update.freeze() + return a.compareAndSet(expect, update) + } + + public actual fun getAndSet(value: T): T { + if (a.isFrozen) value.freeze() + while (true) { + val cur = a.value + if (cur === value) return cur + if (a.compareAndSwap(cur, value) === cur) return cur + } + } + + override fun toString(): String = value.toString() +} + +public actual fun atomic(initial: T): AtomicRef = AtomicRef(KAtomicRef(initial)) \ No newline at end of file diff --git a/kotlin-native/performance/ring/src/main/kotlin/cleanup.kt b/kotlin-native/performance/ring/src/main/kotlin/cleanup.kt new file mode 100644 index 00000000000..efbe7a1f8fb --- /dev/null +++ b/kotlin-native/performance/ring/src/main/kotlin/cleanup.kt @@ -0,0 +1,3 @@ +package org.jetbrains.ring + +expect fun cleanup() \ No newline at end of file diff --git a/kotlin-native/performance/ring/src/main/kotlin/main.kt b/kotlin-native/performance/ring/src/main/kotlin/main.kt new file mode 100644 index 00000000000..18547b464e5 --- /dev/null +++ b/kotlin-native/performance/ring/src/main/kotlin/main.kt @@ -0,0 +1,226 @@ +/* + * Copyright 2010-2017 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + + +import org.jetbrains.ring.* +import octoTest +import org.jetbrains.benchmarksLauncher.* +import kotlinx.cli.* + +class RingLauncher : Launcher() { + + override val benchmarks = BenchmarksCollection( + mutableMapOf( + "AbstractMethod.sortStrings" to BenchmarkEntryWithInit.create(::AbstractMethodBenchmark, { sortStrings() }), + "AbstractMethod.sortStringsWithComparator" to BenchmarkEntryWithInit.create(::AbstractMethodBenchmark, { sortStringsWithComparator() }), + "AllocationBenchmark.allocateObjects" to BenchmarkEntryWithInit.create(::AllocationBenchmark, { allocateObjects() }), + "ClassArray.copy" to BenchmarkEntryWithInit.create(::ClassArrayBenchmark, { copy() }), + "ClassArray.copyManual" to BenchmarkEntryWithInit.create(::ClassArrayBenchmark, { copyManual() }), + "ClassArray.filterAndCount" to BenchmarkEntryWithInit.create(::ClassArrayBenchmark, { filterAndCount() }), + "ClassArray.filterAndMap" to BenchmarkEntryWithInit.create(::ClassArrayBenchmark, { filterAndMap() }), + "ClassArray.filterAndMapManual" to BenchmarkEntryWithInit.create(::ClassArrayBenchmark, { filterAndMapManual() }), + "ClassArray.filter" to BenchmarkEntryWithInit.create(::ClassArrayBenchmark, { filter() }), + "ClassArray.filterManual" to BenchmarkEntryWithInit.create(::ClassArrayBenchmark, { filterManual() }), + "ClassArray.countFilteredManual" to BenchmarkEntryWithInit.create(::ClassArrayBenchmark, { countFilteredManual() }), + "ClassArray.countFiltered" to BenchmarkEntryWithInit.create(::ClassArrayBenchmark, { countFiltered() }), + "ClassArray.countFilteredLocal" to BenchmarkEntryWithInit.create(::ClassArrayBenchmark, { countFilteredLocal() }), + "ClassBaseline.consume" to BenchmarkEntryWithInit.create(::ClassBaselineBenchmark, { consume() }), + "ClassBaseline.consumeField" to BenchmarkEntryWithInit.create(::ClassBaselineBenchmark, { consumeField() }), + "ClassBaseline.allocateList" to BenchmarkEntryWithInit.create(::ClassBaselineBenchmark, { allocateList() }), + "ClassBaseline.allocateArray" to BenchmarkEntryWithInit.create(::ClassBaselineBenchmark, { allocateArray() }), + "ClassBaseline.allocateListAndFill" to BenchmarkEntryWithInit.create(::ClassBaselineBenchmark, { allocateListAndFill() }), + "ClassBaseline.allocateListAndWrite" to BenchmarkEntryWithInit.create(::ClassBaselineBenchmark, { allocateListAndWrite() }), + "ClassBaseline.allocateArrayAndFill" to BenchmarkEntryWithInit.create(::ClassBaselineBenchmark, { allocateArrayAndFill() }), + "ClassList.copy" to BenchmarkEntryWithInit.create(::ClassListBenchmark, { copy() }), + "ClassList.copyManual" to BenchmarkEntryWithInit.create(::ClassListBenchmark, { copyManual() }), + "ClassList.filterAndCount" to BenchmarkEntryWithInit.create(::ClassListBenchmark, { filterAndCount() }), + "ClassList.filterAndCountWithLambda" to BenchmarkEntryWithInit.create(::ClassListBenchmark, { filterAndCountWithLambda() }), + "ClassList.filterWithLambda" to BenchmarkEntryWithInit.create(::ClassListBenchmark, { filterWithLambda() }), + "ClassList.mapWithLambda" to BenchmarkEntryWithInit.create(::ClassListBenchmark, { mapWithLambda() }), + "ClassList.countWithLambda" to BenchmarkEntryWithInit.create(::ClassListBenchmark, { countWithLambda() }), + "ClassList.filterAndMapWithLambda" to BenchmarkEntryWithInit.create(::ClassListBenchmark, { filterAndMapWithLambda() }), + "ClassList.filterAndMapWithLambdaAsSequence" to BenchmarkEntryWithInit.create(::ClassListBenchmark, { filterAndMapWithLambdaAsSequence() }), + "ClassList.filterAndMap" to BenchmarkEntryWithInit.create(::ClassListBenchmark, { filterAndMap() }), + "ClassList.filterAndMapManual" to BenchmarkEntryWithInit.create(::ClassListBenchmark, { filterAndMapManual() }), + "ClassList.filter" to BenchmarkEntryWithInit.create(::ClassListBenchmark, { filter() }), + "ClassList.filterManual" to BenchmarkEntryWithInit.create(::ClassListBenchmark, { filterManual() }), + "ClassList.countFilteredManual" to BenchmarkEntryWithInit.create(::ClassListBenchmark, { countFilteredManual() }), + "ClassList.countFiltered" to BenchmarkEntryWithInit.create(::ClassListBenchmark, { countFiltered() }), + "ClassList.reduce" to BenchmarkEntryWithInit.create(::ClassListBenchmark, { reduce() }), + "ClassStream.copy" to BenchmarkEntryWithInit.create(::ClassStreamBenchmark, { copy() }), + "ClassStream.copyManual" to BenchmarkEntryWithInit.create(::ClassStreamBenchmark, { copyManual() }), + "ClassStream.filterAndCount" to BenchmarkEntryWithInit.create(::ClassStreamBenchmark, { filterAndCount() }), + "ClassStream.filterAndMap" to BenchmarkEntryWithInit.create(::ClassStreamBenchmark, { filterAndMap() }), + "ClassStream.filterAndMapManual" to BenchmarkEntryWithInit.create(::ClassStreamBenchmark, { filterAndMapManual() }), + "ClassStream.filter" to BenchmarkEntryWithInit.create(::ClassStreamBenchmark, { filter() }), + "ClassStream.filterManual" to BenchmarkEntryWithInit.create(::ClassStreamBenchmark, { filterManual() }), + "ClassStream.countFilteredManual" to BenchmarkEntryWithInit.create(::ClassStreamBenchmark, { countFilteredManual() }), + "ClassStream.countFiltered" to BenchmarkEntryWithInit.create(::ClassStreamBenchmark, { countFiltered() }), + "ClassStream.reduce" to BenchmarkEntryWithInit.create(::ClassStreamBenchmark, { reduce() }), + "CompanionObject.invokeRegularFunction" to BenchmarkEntryWithInit.create(::CompanionObjectBenchmark, { invokeRegularFunction() }), + "DefaultArgument.testOneOfTwo" to BenchmarkEntryWithInit.create(::DefaultArgumentBenchmark, { testOneOfTwo() }), + "DefaultArgument.testTwoOfTwo" to BenchmarkEntryWithInit.create(::DefaultArgumentBenchmark, { testTwoOfTwo() }), + "DefaultArgument.testOneOfFour" to BenchmarkEntryWithInit.create(::DefaultArgumentBenchmark, { testOneOfFour() }), + "DefaultArgument.testFourOfFour" to BenchmarkEntryWithInit.create(::DefaultArgumentBenchmark, { testFourOfFour() }), + "DefaultArgument.testOneOfEight" to BenchmarkEntryWithInit.create(::DefaultArgumentBenchmark, { testOneOfEight() }), + "DefaultArgument.testEightOfEight" to BenchmarkEntryWithInit.create(::DefaultArgumentBenchmark, { testEightOfEight() }), + "Elvis.testElvis" to BenchmarkEntryWithInit.create(::ElvisBenchmark, { testElvis() }), + "Elvis.testCompositeElvis" to BenchmarkEntryWithInit.create(::ElvisBenchmark, { testCompositeElvis() }), + "Euler.problem1bySequence" to BenchmarkEntryWithInit.create(::EulerBenchmark, { problem1bySequence() }), + "Euler.problem1" to BenchmarkEntryWithInit.create(::EulerBenchmark, { problem1() }), + "Euler.problem2" to BenchmarkEntryWithInit.create(::EulerBenchmark, { problem2() }), + "Euler.problem4" to BenchmarkEntryWithInit.create(::EulerBenchmark, { problem4() }), + "Euler.problem8" to BenchmarkEntryWithInit.create(::EulerBenchmark, { problem8() }), + "Euler.problem9" to BenchmarkEntryWithInit.create(::EulerBenchmark, { problem9() }), + "Euler.problem14" to BenchmarkEntryWithInit.create(::EulerBenchmark, { problem14() }), + "Euler.problem14full" to BenchmarkEntryWithInit.create(::EulerBenchmark, { problem14full() }), + "Fibonacci.calcClassic" to BenchmarkEntryWithInit.create(::FibonacciBenchmark, { calcClassic() }), + "Fibonacci.calc" to BenchmarkEntryWithInit.create(::FibonacciBenchmark, { calc() }), + "Fibonacci.calcWithProgression" to BenchmarkEntryWithInit.create(::FibonacciBenchmark, { calcWithProgression() }), + "Fibonacci.calcSquare" to BenchmarkEntryWithInit.create(::FibonacciBenchmark, { calcSquare() }), + "ForLoops.arrayLoop" to BenchmarkEntryWithInit.create(::ForLoopsBenchmark, { arrayLoop() }), + "ForLoops.intArrayLoop" to BenchmarkEntryWithInit.create(::ForLoopsBenchmark, { intArrayLoop() }), + "ForLoops.floatArrayLoop" to BenchmarkEntryWithInit.create(::ForLoopsBenchmark, { floatArrayLoop() }), + "ForLoops.charArrayLoop" to BenchmarkEntryWithInit.create(::ForLoopsBenchmark, { charArrayLoop() }), + "ForLoops.stringLoop" to BenchmarkEntryWithInit.create(::ForLoopsBenchmark, { stringLoop() }), + "ForLoops.arrayIndicesLoop" to BenchmarkEntryWithInit.create(::ForLoopsBenchmark, { arrayIndicesLoop() }), + "ForLoops.intArrayIndicesLoop" to BenchmarkEntryWithInit.create(::ForLoopsBenchmark, { intArrayIndicesLoop() }), + "ForLoops.floatArrayIndicesLoop" to BenchmarkEntryWithInit.create(::ForLoopsBenchmark, { floatArrayIndicesLoop() }), + "ForLoops.charArrayIndicesLoop" to BenchmarkEntryWithInit.create(::ForLoopsBenchmark, { charArrayIndicesLoop() }), + "ForLoops.stringIndicesLoop" to BenchmarkEntryWithInit.create(::ForLoopsBenchmark, { stringIndicesLoop() }), + "Inline.calculate" to BenchmarkEntryWithInit.create(::InlineBenchmark, { calculate() }), + "Inline.calculateInline" to BenchmarkEntryWithInit.create(::InlineBenchmark, { calculateInline() }), + "Inline.calculateGeneric" to BenchmarkEntryWithInit.create(::InlineBenchmark, { calculateGeneric() }), + "Inline.calculateGenericInline" to BenchmarkEntryWithInit.create(::InlineBenchmark, { calculateGenericInline() }), + "IntArray.copy" to BenchmarkEntryWithInit.create(::IntArrayBenchmark, { copy() }), + "IntArray.copyManual" to BenchmarkEntryWithInit.create(::IntArrayBenchmark, { copyManual() }), + "IntArray.filterAndCount" to BenchmarkEntryWithInit.create(::IntArrayBenchmark, { filterAndCount() }), + "IntArray.filterSomeAndCount" to BenchmarkEntryWithInit.create(::IntArrayBenchmark, { filterSomeAndCount() }), + "IntArray.filterAndMap" to BenchmarkEntryWithInit.create(::IntArrayBenchmark, { filterAndMap() }), + "IntArray.filterAndMapManual" to BenchmarkEntryWithInit.create(::IntArrayBenchmark, { filterAndMapManual() }), + "IntArray.filter" to BenchmarkEntryWithInit.create(::IntArrayBenchmark, { filter() }), + "IntArray.filterSome" to BenchmarkEntryWithInit.create(::IntArrayBenchmark, { filterSome() }), + "IntArray.filterPrime" to BenchmarkEntryWithInit.create(::IntArrayBenchmark, { filterPrime() }), + "IntArray.filterManual" to BenchmarkEntryWithInit.create(::IntArrayBenchmark, { filterManual() }), + "IntArray.filterSomeManual" to BenchmarkEntryWithInit.create(::IntArrayBenchmark, { filterSomeManual() }), + "IntArray.countFilteredManual" to BenchmarkEntryWithInit.create(::IntArrayBenchmark, { countFilteredManual() }), + "IntArray.countFilteredSomeManual" to BenchmarkEntryWithInit.create(::IntArrayBenchmark, { countFilteredSomeManual() }), + "IntArray.countFilteredPrimeManual" to BenchmarkEntryWithInit.create(::IntArrayBenchmark, { countFilteredPrimeManual() }), + "IntArray.countFiltered" to BenchmarkEntryWithInit.create(::IntArrayBenchmark, { countFiltered() }), + "IntArray.countFilteredSome" to BenchmarkEntryWithInit.create(::IntArrayBenchmark, { countFilteredSome() }), + "IntArray.countFilteredPrime" to BenchmarkEntryWithInit.create(::IntArrayBenchmark, { countFilteredPrime() }), + "IntArray.countFilteredLocal" to BenchmarkEntryWithInit.create(::IntArrayBenchmark, { countFilteredLocal() }), + "IntArray.countFilteredSomeLocal" to BenchmarkEntryWithInit.create(::IntArrayBenchmark, { countFilteredSomeLocal() }), + "IntArray.reduce" to BenchmarkEntryWithInit.create(::IntArrayBenchmark, { reduce() }), + "IntBaseline.consume" to BenchmarkEntryWithInit.create(::IntBaselineBenchmark, { consume() }), + "IntBaseline.allocateList" to BenchmarkEntryWithInit.create(::IntBaselineBenchmark, { allocateList() }), + "IntBaseline.allocateArray" to BenchmarkEntryWithInit.create(::IntBaselineBenchmark, { allocateArray() }), + "IntBaseline.allocateListAndFill" to BenchmarkEntryWithInit.create(::IntBaselineBenchmark, { allocateListAndFill() }), + "IntBaseline.allocateArrayAndFill" to BenchmarkEntryWithInit.create(::IntBaselineBenchmark, { allocateArrayAndFill() }), + "IntList.copy" to BenchmarkEntryWithInit.create(::IntListBenchmark, { copy() }), + "IntList.copyManual" to BenchmarkEntryWithInit.create(::IntListBenchmark, { copyManual() }), + "IntList.filterAndCount" to BenchmarkEntryWithInit.create(::IntListBenchmark, { filterAndCount() }), + "IntList.filterAndMap" to BenchmarkEntryWithInit.create(::IntListBenchmark, { filterAndMap() }), + "IntList.filterAndMapManual" to BenchmarkEntryWithInit.create(::IntListBenchmark, { filterAndMapManual() }), + "IntList.filter" to BenchmarkEntryWithInit.create(::IntListBenchmark, { filter() }), + "IntList.filterManual" to BenchmarkEntryWithInit.create(::IntListBenchmark, { filterManual() }), + "IntList.countFilteredManual" to BenchmarkEntryWithInit.create(::IntListBenchmark, { countFilteredManual() }), + "IntList.countFiltered" to BenchmarkEntryWithInit.create(::IntListBenchmark, { countFiltered() }), + "IntList.countFilteredLocal" to BenchmarkEntryWithInit.create(::IntListBenchmark, { countFilteredLocal() }), + "IntList.reduce" to BenchmarkEntryWithInit.create(::IntListBenchmark, { reduce() }), + "IntStream.copy" to BenchmarkEntryWithInit.create(::IntStreamBenchmark, { copy() }), + "IntStream.copyManual" to BenchmarkEntryWithInit.create(::IntStreamBenchmark, { copyManual() }), + "IntStream.filterAndCount" to BenchmarkEntryWithInit.create(::IntStreamBenchmark, { filterAndCount() }), + "IntStream.filterAndMap" to BenchmarkEntryWithInit.create(::IntStreamBenchmark, { filterAndMap() }), + "IntStream.filterAndMapManual" to BenchmarkEntryWithInit.create(::IntStreamBenchmark, { filterAndMapManual() }), + "IntStream.filter" to BenchmarkEntryWithInit.create(::IntStreamBenchmark, { filter() }), + "IntStream.filterManual" to BenchmarkEntryWithInit.create(::IntStreamBenchmark, { filterManual() }), + "IntStream.countFilteredManual" to BenchmarkEntryWithInit.create(::IntStreamBenchmark, { countFilteredManual() }), + "IntStream.countFiltered" to BenchmarkEntryWithInit.create(::IntStreamBenchmark, { countFiltered() }), + "IntStream.countFilteredLocal" to BenchmarkEntryWithInit.create(::IntStreamBenchmark, { countFilteredLocal() }), + "IntStream.reduce" to BenchmarkEntryWithInit.create(::IntStreamBenchmark, { reduce() }), + "Lambda.noncapturingLambda" to BenchmarkEntryWithInit.create(::LambdaBenchmark, { noncapturingLambda() }), + "Lambda.noncapturingLambdaNoInline" to BenchmarkEntryWithInit.create(::LambdaBenchmark, { noncapturingLambdaNoInline() }), + "Lambda.capturingLambda" to BenchmarkEntryWithInit.create(::LambdaBenchmark, { capturingLambda() }), + "Lambda.capturingLambdaNoInline" to BenchmarkEntryWithInit.create(::LambdaBenchmark, { capturingLambdaNoInline() }), + "Lambda.mutatingLambda" to BenchmarkEntryWithInit.create(::LambdaBenchmark, { mutatingLambda() }), + "Lambda.mutatingLambdaNoInline" to BenchmarkEntryWithInit.create(::LambdaBenchmark, { mutatingLambdaNoInline() }), + "Lambda.methodReference" to BenchmarkEntryWithInit.create(::LambdaBenchmark, { methodReference() }), + "Lambda.methodReferenceNoInline" to BenchmarkEntryWithInit.create(::LambdaBenchmark, { methodReferenceNoInline() }), + "Loop.arrayLoop" to BenchmarkEntryWithInit.create(::LoopBenchmark, { arrayLoop() }), + "Loop.arrayIndexLoop" to BenchmarkEntryWithInit.create(::LoopBenchmark, { arrayIndexLoop() }), + "Loop.rangeLoop" to BenchmarkEntryWithInit.create(::LoopBenchmark, { rangeLoop() }), + "Loop.arrayListLoop" to BenchmarkEntryWithInit.create(::LoopBenchmark, { arrayListLoop() }), + "Loop.arrayWhileLoop" to BenchmarkEntryWithInit.create(::LoopBenchmark, { arrayWhileLoop() }), + "Loop.arrayForeachLoop" to BenchmarkEntryWithInit.create(::LoopBenchmark, { arrayForeachLoop() }), + "Loop.arrayListForeachLoop" to BenchmarkEntryWithInit.create(::LoopBenchmark, { arrayListForeachLoop() }), + "MatrixMap.add" to BenchmarkEntryWithInit.create(::MatrixMapBenchmark, { add() }), + "ParameterNotNull.invokeOneArgWithNullCheck" to BenchmarkEntryWithInit.create(::ParameterNotNullAssertionBenchmark, { invokeOneArgWithNullCheck() }), + "ParameterNotNull.invokeOneArgWithoutNullCheck" to BenchmarkEntryWithInit.create(::ParameterNotNullAssertionBenchmark, { invokeOneArgWithoutNullCheck() }), + "ParameterNotNull.invokeTwoArgsWithNullCheck" to BenchmarkEntryWithInit.create(::ParameterNotNullAssertionBenchmark, { invokeTwoArgsWithNullCheck() }), + "ParameterNotNull.invokeTwoArgsWithoutNullCheck" to BenchmarkEntryWithInit.create(::ParameterNotNullAssertionBenchmark, { invokeTwoArgsWithoutNullCheck() }), + "ParameterNotNull.invokeEightArgsWithNullCheck" to BenchmarkEntryWithInit.create(::ParameterNotNullAssertionBenchmark, { invokeEightArgsWithNullCheck() }), + "ParameterNotNull.invokeEightArgsWithoutNullCheck" to BenchmarkEntryWithInit.create(::ParameterNotNullAssertionBenchmark, { invokeEightArgsWithoutNullCheck() }), + "PrimeList.calcDirect" to BenchmarkEntryWithInit.create(::PrimeListBenchmark, { calcDirect() }), + "PrimeList.calcEratosthenes" to BenchmarkEntryWithInit.create(::PrimeListBenchmark, { calcEratosthenes() }), + "Singleton.access" to BenchmarkEntryWithInit.create(::SingletonBenchmark, { access() }), + "String.stringConcat" to BenchmarkEntryWithInit.create(::StringBenchmark, { stringConcat() }), + "String.stringConcatNullable" to BenchmarkEntryWithInit.create(::StringBenchmark, { stringConcatNullable() }), + "String.stringBuilderConcat" to BenchmarkEntryWithInit.create(::StringBenchmark, { stringBuilderConcat() }), + "String.stringBuilderConcatNullable" to BenchmarkEntryWithInit.create(::StringBenchmark, { stringBuilderConcatNullable() }), + "String.summarizeSplittedCsv" to BenchmarkEntryWithInit.create(::StringBenchmark, { summarizeSplittedCsv() }), + "Switch.testSparseIntSwitch" to BenchmarkEntryWithInit.create(::SwitchBenchmark, { testSparseIntSwitch() }), + "Switch.testDenseIntSwitch" to BenchmarkEntryWithInit.create(::SwitchBenchmark, { testDenseIntSwitch() }), + "Switch.testConstSwitch" to BenchmarkEntryWithInit.create(::SwitchBenchmark, { testConstSwitch() }), + "Switch.testObjConstSwitch" to BenchmarkEntryWithInit.create(::SwitchBenchmark, { testObjConstSwitch() }), + "Switch.testVarSwitch" to BenchmarkEntryWithInit.create(::SwitchBenchmark, { testVarSwitch() }), + "Switch.testStringsSwitch" to BenchmarkEntryWithInit.create(::SwitchBenchmark, { testStringsSwitch() }), + "Switch.testEnumsSwitch" to BenchmarkEntryWithInit.create(::SwitchBenchmark, { testEnumsSwitch() }), + "Switch.testDenseEnumsSwitch" to BenchmarkEntryWithInit.create(::SwitchBenchmark, { testDenseEnumsSwitch() }), + "Switch.testSealedWhenSwitch" to BenchmarkEntryWithInit.create(::SwitchBenchmark, { testSealedWhenSwitch() }), + "WithIndicies.withIndicies" to BenchmarkEntryWithInit.create(::WithIndiciesBenchmark, { withIndicies() }), + "WithIndicies.withIndiciesManual" to BenchmarkEntryWithInit.create(::WithIndiciesBenchmark, { withIndiciesManual() }), + "OctoTest" to BenchmarkEntry(::octoTest), + "Calls.finalMethod" to BenchmarkEntryWithInit.create(::CallsBenchmark, { finalMethodCall() }), + "Calls.openMethodMonomorphic" to BenchmarkEntryWithInit.create(::CallsBenchmark, { classOpenMethodCall_MonomorphicCallsite() }), + "Calls.openMethodBimorphic" to BenchmarkEntryWithInit.create(::CallsBenchmark, { classOpenMethodCall_BimorphicCallsite() }), + "Calls.openMethodTrimorphic" to BenchmarkEntryWithInit.create(::CallsBenchmark, { classOpenMethodCall_TrimorphicCallsite() }), + "Calls.interfaceMethodMonomorphic" to BenchmarkEntryWithInit.create(::CallsBenchmark, { interfaceMethodCall_MonomorphicCallsite() }), + "Calls.interfaceMethodBimorphic" to BenchmarkEntryWithInit.create(::CallsBenchmark, { interfaceMethodCall_BimorphicCallsite() }), + "Calls.interfaceMethodTrimorphic" to BenchmarkEntryWithInit.create(::CallsBenchmark, { interfaceMethodCall_TrimorphicCallsite() }), + "Calls.interfaceMethodHexamorphic" to BenchmarkEntryWithInit.create(::CallsBenchmark, { interfaceMethodCall_HexamorphicCallsite() }), + "Calls.returnBoxUnboxFolding" to BenchmarkEntryWithInit.create(::CallsBenchmark, { returnBoxUnboxFolding() }), + "Calls.parameterBoxUnboxFolding" to BenchmarkEntryWithInit.create(::CallsBenchmark, { parameterBoxUnboxFolding() }), + "CoordinatesSolver.solve" to BenchmarkEntryWithInit.create(::CoordinatesSolverBenchmark, { solve() }), + "GraphSolver.solve" to BenchmarkEntryWithInit.create(::GraphSolverBenchmark, { solve() }), + "Casts.classCast" to BenchmarkEntryWithInit.create(::CastsBenchmark, { classCast() }), + "Casts.interfaceCast" to BenchmarkEntryWithInit.create(::CastsBenchmark, { interfaceCast() }), + "LocalObjects.localArray" to BenchmarkEntryWithInit.create(::LocalObjectsBenchmark, { localArray() }), + "LinkedListWithAtomicsBenchmark" to BenchmarkEntryWithInit.create(::LinkedListWithAtomicsBenchmark, { ensureNext() }), + "Inheritance.baseCalls" to BenchmarkEntryWithInit.create(::InheritanceBenchmark, { baseCalls() }) + ) + ) +} + +fun main(args: Array) { + val launcher = RingLauncher() + BenchmarksRunner.runBenchmarks(args, { arguments: BenchmarkArguments -> + if (arguments is BaseBenchmarkArguments) { + launcher.launch(arguments.warmup, arguments.repeat, arguments.prefix, + arguments.filter, arguments.filterRegex, arguments.verbose) + } else emptyList() + }, benchmarksListAction = launcher::benchmarksListAction) +} diff --git a/kotlin-native/performance/ring/src/main/kotlin/org/jetbrains/ring/AbstractMethodBenchmark.kt b/kotlin-native/performance/ring/src/main/kotlin/org/jetbrains/ring/AbstractMethodBenchmark.kt new file mode 100644 index 00000000000..79638e5ea1c --- /dev/null +++ b/kotlin-native/performance/ring/src/main/kotlin/org/jetbrains/ring/AbstractMethodBenchmark.kt @@ -0,0 +1,52 @@ +/* + * Copyright 2010-2017 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.jetbrains.ring + +/** + * Created by Mikhail.Glukhikh on 06/03/2015. + * + * A benchmark for a single abstract method based on a string comparison + */ + +open class AbstractMethodBenchmark { + + private val arr: List = zdf_win + private val sequence = "абвгдеёжзийклмнопрстуфхцчшщъыьэюя" + + private val sequenceMap = HashMap() + + init { + var i = 0; + for (ch in sequence) { + sequenceMap[ch] = i++; + } + } + + //Benchmark + fun sortStrings(): Set { + val res = arr.subList(0, if (BENCHMARK_SIZE < arr.size) BENCHMARK_SIZE else arr.size).toSet() + return res + } + + //Benchmark + fun sortStringsWithComparator(): Set { + val res = mutableSetOf() + res.addAll(arr.subList(0, if (BENCHMARK_SIZE < arr.size) BENCHMARK_SIZE else arr.size)) + return res + } +} + diff --git a/kotlin-native/performance/ring/src/main/kotlin/org/jetbrains/ring/AllocationBenchmark.kt b/kotlin-native/performance/ring/src/main/kotlin/org/jetbrains/ring/AllocationBenchmark.kt new file mode 100644 index 00000000000..61a8e988e7c --- /dev/null +++ b/kotlin-native/performance/ring/src/main/kotlin/org/jetbrains/ring/AllocationBenchmark.kt @@ -0,0 +1,25 @@ +/* + * Copyright 2010-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +package org.jetbrains.ring + +var counter = 0 + +open class AllocationBenchmark { + + class MyClass { + fun inc() { + counter++ + } + } + + //Benchmark + fun allocateObjects() { + repeat(BENCHMARK_SIZE) { + MyClass().inc() + } + } + +} \ No newline at end of file diff --git a/kotlin-native/performance/ring/src/main/kotlin/org/jetbrains/ring/CallsBenchmark.kt b/kotlin-native/performance/ring/src/main/kotlin/org/jetbrains/ring/CallsBenchmark.kt new file mode 100644 index 00000000000..92b7ee3b2cf --- /dev/null +++ b/kotlin-native/performance/ring/src/main/kotlin/org/jetbrains/ring/CallsBenchmark.kt @@ -0,0 +1,301 @@ +/* + * Copyright 2010-2017 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.jetbrains.ring + +private const val RUNS = 1_000_000 + +open class CallsBenchmark { + + interface I { + fun foo(): Int + + fun foo1(): Int = 1 + fun foo2(): Int = 2 + fun foo3(): Int = 3 + fun foo4(): Int = 4 + fun foo5(): Int = 5 + fun foo6(): Int = 6 + fun foo7(): Int = 7 + fun foo8(): Int = 8 + fun foo9(): Int = 9 + fun foo10(): Int = 10 + fun foo11(): Int = 11 + fun foo12(): Int = 12 + fun foo13(): Int = 13 + fun foo14(): Int = 14 + fun foo15(): Int = 15 + fun foo16(): Int = 16 + fun foo17(): Int = 17 + fun foo18(): Int = 18 + fun foo19(): Int = 19 + fun foo20(): Int = 20 + fun foo21(): Int = 21 + fun foo22(): Int = 22 + fun foo23(): Int = 23 + fun foo24(): Int = 24 + fun foo25(): Int = 25 + fun foo26(): Int = 26 + fun foo27(): Int = 27 + fun foo28(): Int = 28 + fun foo29(): Int = 29 + fun foo30(): Int = 30 + fun foo31(): Int = 31 + fun foo32(): Int = 32 + fun foo33(): Int = 33 + fun foo34(): Int = 34 + fun foo35(): Int = 35 + fun foo36(): Int = 36 + fun foo37(): Int = 37 + fun foo38(): Int = 38 + fun foo39(): Int = 39 + fun foo40(): Int = 40 + fun foo41(): Int = 41 + fun foo42(): Int = 42 + fun foo43(): Int = 43 + fun foo44(): Int = 44 + fun foo45(): Int = 45 + fun foo46(): Int = 46 + fun foo47(): Int = 47 + fun foo48(): Int = 48 + fun foo49(): Int = 49 + fun foo50(): Int = 50 + fun foo51(): Int = 51 + fun foo52(): Int = 52 + fun foo53(): Int = 53 + fun foo54(): Int = 54 + fun foo55(): Int = 55 + fun foo56(): Int = 56 + fun foo57(): Int = 57 + fun foo58(): Int = 58 + fun foo59(): Int = 59 + fun foo60(): Int = 60 + fun foo61(): Int = 61 + fun foo62(): Int = 62 + fun foo63(): Int = 63 + fun foo64(): Int = 64 + fun foo65(): Int = 65 + fun foo66(): Int = 66 + fun foo67(): Int = 67 + fun foo68(): Int = 68 + fun foo69(): Int = 69 + fun foo70(): Int = 70 + fun foo71(): Int = 71 + fun foo72(): Int = 72 + fun foo73(): Int = 73 + fun foo74(): Int = 74 + fun foo75(): Int = 75 + fun foo76(): Int = 76 + fun foo77(): Int = 77 + fun foo78(): Int = 78 + fun foo79(): Int = 79 + fun foo80(): Int = 80 + fun foo81(): Int = 81 + fun foo82(): Int = 82 + fun foo83(): Int = 83 + fun foo84(): Int = 84 + fun foo85(): Int = 85 + fun foo86(): Int = 86 + fun foo87(): Int = 87 + fun foo88(): Int = 88 + fun foo89(): Int = 89 + fun foo90(): Int = 90 + fun foo91(): Int = 91 + fun foo92(): Int = 92 + fun foo93(): Int = 93 + fun foo94(): Int = 94 + fun foo95(): Int = 95 + fun foo96(): Int = 96 + fun foo97(): Int = 97 + fun foo98(): Int = 98 + fun foo99(): Int = 99 + } + + abstract class A : I + + open class B : A() { + override fun foo() = 42 + } + + open class C : A() { + override fun foo() = 117 + } + + class D: A() { + override fun foo() = 314 + } + + open class X : A() { + override fun foo() = 456456 + } + + open class Y : A() { + override fun foo() = -398473 + } + + open class Z : A() { + override fun foo() = 78298734 + } + + val d = D() + val a1: A = B() + val a2: A = C() + val a3: A = d + val i1: I = a1 + val i2: I = a2 + val i3: I = d + val i4: I = X() + val i5: I = Y() + val i6: I = Z() + + fun finalMethodCall(): Int { + var x = 0 + // TODO: optimize fields accesses + val d = d + for (i in 0 until RUNS) + x += d.foo() + return x + } + + fun classOpenMethodCall_MonomorphicCallsite(): Int { + var x = 0 + // TODO: optimize fields accesses + val a1 = a1 + for (i in 0 until RUNS) + x += a1.foo() + return x + } + + fun classOpenMethodCall_BimorphicCallsite(): Int { + var x = 0 + // TODO: optimize fields accesses + val a1 = a1 + val a2 = a2 + for (i in 0 until RUNS) + x += (if (i and 1 == 0) a1 else a2).foo() + return x + } + + fun classOpenMethodCall_TrimorphicCallsite(): Int { + var x = 0 + // TODO: optimize fields accesses + val a1 = a1 + val a2 = a2 + val a3 = a3 + for (i in 0 until RUNS) + x += (when (i % 3) { + 1 -> a1 + 2 -> a2 + else -> a3 + }).foo() + return x + } + + fun interfaceMethodCall_MonomorphicCallsite(): Int { + var x = 0 + // TODO: optimize fields accesses + val i1 = i1 + for (i in 0 until RUNS) + x += i1.foo() + return x + } + + fun interfaceMethodCall_BimorphicCallsite(): Int { + var x = 0 + // TODO: optimize fields accesses + val i1 = i1 + val i2 = i2 + for (i in 0 until RUNS) + x += (if (i and 1 == 0) i1 else i2).foo() + return x + } + + fun interfaceMethodCall_TrimorphicCallsite(): Int { + var x = 0 + // TODO: optimize fields accesses + val i1 = i1 + val i2 = i2 + val i3 = i3 + for (i in 0 until RUNS) + x += (when (i % 3) { + 1 -> i1 + 2 -> i2 + else -> i3 + }).foo() + return x + } + + fun interfaceMethodCall_HexamorphicCallsite(): Int { + var x = 0 + // TODO: optimize fields accesses + val i1 = i1 + val i2 = i2 + val i3 = i3 + val i4 = i4 + val i5 = i5 + val i6 = i6 + for (i in 0 until RUNS) + x += (when (i % 6) { + 1 -> i1 + 2 -> i2 + 3 -> i3 + 4 -> i4 + 5 -> i5 + else -> i6 + }).foo() + return x + } + + abstract class E { + abstract fun foo(): Any + } + + open class F : E() { + override fun foo(): Int = 42 + } + + val e: E = F() + + fun returnBoxUnboxFolding(): Int { + var x = 0 + // TODO: optimize fields accesses + val e = e + for (i in 0 until RUNS) + x += e.foo() as Int + return x + } + + abstract class G { + abstract fun foo(x: T): Int + } + + open class H : G() { + override fun foo(x: Int): Int { + return x + } + } + + val g: G = H() as G + + fun parameterBoxUnboxFolding(): Int { + var x = 0 + // TODO: optimize fields accesses + val g = g + for (i in 0 until RUNS) + x += g.foo(i) + return x + } +} \ No newline at end of file diff --git a/kotlin-native/performance/ring/src/main/kotlin/org/jetbrains/ring/CastsBenchmark.kt b/kotlin-native/performance/ring/src/main/kotlin/org/jetbrains/ring/CastsBenchmark.kt new file mode 100644 index 00000000000..a9e6a4d2299 --- /dev/null +++ b/kotlin-native/performance/ring/src/main/kotlin/org/jetbrains/ring/CastsBenchmark.kt @@ -0,0 +1,117 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +package org.jetbrains.ring + +private const val RUNS = 2_000_000 + +class CastsBenchmark { + interface I0 + open class C0: I0 + interface I1 + open class C1: C0(), I1 + interface I2: I0 + open class C2: C1(), I2 + interface I3: I1 + open class C3: C2(), I3 + interface I4: I0, I2 + open class C4: C3(), I4 + interface I5: I3 + open class C5: C4(), I5 + interface I6: I0, I2, I4 + open class C6: C5(), I6 + interface I9: I0, I2, I4 + open class C9: C5(), I9, I1 + interface I7: I1 + open class C7: C3(), I7 + interface I8: I0, I1 + open class C8: C3(), I8 + + private fun foo_class(c: Any, x: Int, i: Int): Int { + var x = x + if (c is C0) x += i + if (c is C1) x = x xor i + if (c is C2) x += i + if (c is C3) x = x xor i + if (c is C4) x += i + if (c is C5) x = x xor i + if (c is C6) x += i + if (c is C7) x = x xor i + if (c is C8) x += i + if (c is C9) x = x xor i + return x + } + + private fun foo_iface(c: Any, x: Int, i: Int): Int { + var x = x + if (c is I0) x += i + if (c is I1) x = x xor i + if (c is I2) x += i + if (c is I3) x = x xor i + if (c is I4) x += i + if (c is I5) x = x xor i + if (c is I6) x += i + if (c is I7) x = x xor i + if (c is I8) x += i + if (c is I9) x = x xor i + return x + } + + fun classCast(): Int { + val c0: Any = C0() + val c1: Any = C1() + val c2: Any = C2() + val c3: Any = C3() + val c4: Any = C4() + val c5: Any = C5() + val c6: Any = C6() + val c7: Any = C7() + val c8: Any = C8() + val c9: Any = C9() + + var x = 0 + for (i in 0 until RUNS) { + x += foo_class(c0, x, i) + x += foo_class(c1, x, i) + x += foo_class(c2, x, i) + x += foo_class(c3, x, i) + x += foo_class(c4, x, i) + x += foo_class(c5, x, i) + x += foo_class(c6, x, i) + x += foo_class(c7, x, i) + x += foo_class(c8, x, i) + x += foo_class(c9, x, i) + } + return x + } + + fun interfaceCast(): Int { + val c0: Any = C0() + val c1: Any = C1() + val c2: Any = C2() + val c3: Any = C3() + val c4: Any = C4() + val c5: Any = C5() + val c6: Any = C6() + val c7: Any = C7() + val c8: Any = C8() + val c9: Any = C9() + + var x = 0 + for (i in 0 until RUNS) { + x += foo_iface(c0, x, i) + x += foo_iface(c1, x, i) + x += foo_iface(c2, x, i) + x += foo_iface(c3, x, i) + x += foo_iface(c4, x, i) + x += foo_iface(c5, x, i) + x += foo_iface(c6, x, i) + x += foo_iface(c7, x, i) + x += foo_iface(c8, x, i) + x += foo_iface(c9, x, i) + } + return x + } +} \ No newline at end of file diff --git a/kotlin-native/performance/ring/src/main/kotlin/org/jetbrains/ring/ClassArrayBenchmark.kt b/kotlin-native/performance/ring/src/main/kotlin/org/jetbrains/ring/ClassArrayBenchmark.kt new file mode 100644 index 00000000000..9af30f69be4 --- /dev/null +++ b/kotlin-native/performance/ring/src/main/kotlin/org/jetbrains/ring/ClassArrayBenchmark.kt @@ -0,0 +1,106 @@ +/* + * Copyright 2010-2017 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.jetbrains.ring + +open class ClassArrayBenchmark { + private var _data: Array? = null + val data: Array + get() = _data!! + + init { + val list = ArrayList(BENCHMARK_SIZE) + for (n in classValues(BENCHMARK_SIZE)) + list.add(n) + _data = list.toTypedArray() + } + + //Benchmark + fun copy(): List { + return data.toList() + } + + //Benchmark + fun copyManual(): List { + val list = ArrayList(data.size) + for (item in data) { + list.add(item) + } + return list + } + + //Benchmark + fun filterAndCount(): Int { + return data.filter { filterLoad(it) }.count() + } + + //Benchmark + fun filterAndMap(): List { + return data.filter { filterLoad(it) }.map { mapLoad(it) } + } + + //Benchmark + fun filterAndMapManual(): ArrayList { + val list = ArrayList() + for (it in data) { + if (filterLoad(it)) { + val value = mapLoad(it) + list.add(value) + } + } + return list + } + + //Benchmark + fun filter(): List { + return data.filter { filterLoad(it) } + } + + //Benchmark + fun filterManual(): List { + val list = ArrayList() + for (it in data) { + if (filterLoad(it)) + list.add(it) + } + return list + } + + //Benchmark + fun countFilteredManual(): Int { + var count = 0 + for (it in data) { + if (filterLoad(it)) + count++ + } + return count + } + + //Benchmark + fun countFiltered(): Int { + return data.count { filterLoad(it) } + } + + //Benchmark + fun countFilteredLocal(): Int { + return data.cnt { filterLoad(it) } + } + + //Benchmark +// fun reduce(): Int { +// return data.fold(0) { acc, it -> if (filterLoad(it)) acc + 1 else acc } +// } +} diff --git a/kotlin-native/performance/ring/src/main/kotlin/org/jetbrains/ring/ClassBaselineBenchmark.kt b/kotlin-native/performance/ring/src/main/kotlin/org/jetbrains/ring/ClassBaselineBenchmark.kt new file mode 100644 index 00000000000..114494ff599 --- /dev/null +++ b/kotlin-native/performance/ring/src/main/kotlin/org/jetbrains/ring/ClassBaselineBenchmark.kt @@ -0,0 +1,79 @@ +/* + * Copyright 2010-2017 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.jetbrains.ring + +import org.jetbrains.benchmarksLauncher.Blackhole + +open class ClassBaselineBenchmark { + + //Benchmark + fun consume() { + for (item in 1..BENCHMARK_SIZE) { + Blackhole.consume(Value(item)) + } + } + + //Benchmark + fun consumeField() { + val value = Value(0) + for (item in 1..BENCHMARK_SIZE) { + value.value = item + Blackhole.consume(value) + } + } + + //Benchmark + fun allocateList(): List { + val list = ArrayList(BENCHMARK_SIZE) + return list + } + + //Benchmark + fun allocateArray(): Array { + val list = arrayOfNulls(BENCHMARK_SIZE) + return list + } + + //Benchmark + fun allocateListAndFill(): List { + val list = ArrayList(BENCHMARK_SIZE) + for (item in 1..BENCHMARK_SIZE) { + list.add(Value(item)) + } + return list + } + + //Benchmark + fun allocateListAndWrite(): List { + val value = Value(0) + val list = ArrayList(BENCHMARK_SIZE) + for (item in 1..BENCHMARK_SIZE) { + list.add(value) + } + return list + } + + //Benchmark + fun allocateArrayAndFill(): Array { + val list = arrayOfNulls(BENCHMARK_SIZE) + var index = 0 + for (item in 1..BENCHMARK_SIZE) { + list[index++] = Value(item) + } + return list + } +} \ No newline at end of file diff --git a/kotlin-native/performance/ring/src/main/kotlin/org/jetbrains/ring/ClassListBenchmark.kt b/kotlin-native/performance/ring/src/main/kotlin/org/jetbrains/ring/ClassListBenchmark.kt new file mode 100644 index 00000000000..0163101d7e8 --- /dev/null +++ b/kotlin-native/performance/ring/src/main/kotlin/org/jetbrains/ring/ClassListBenchmark.kt @@ -0,0 +1,136 @@ +/* + * Copyright 2010-2017 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.jetbrains.ring + +open class ClassListBenchmark { + private var _data: ArrayList? = null + val data: ArrayList + get() = _data!! + + init { + val list = ArrayList(BENCHMARK_SIZE) + for (n in classValues(BENCHMARK_SIZE)) + list.add(n) + _data = list + } + + //Benchmark + fun copy(): List { + return data.toList() + } + + //Benchmark + fun copyManual(): List { + val list = ArrayList(data.size) + for (item in data) { + list.add(item) + } + return list + } + + //Benchmark + fun filterAndCount(): Int { + return data.filter { filterLoad(it) }.count() + } + + //Benchmark + fun filterAndCountWithLambda(): Int { + return data.filter { it.value % 2 == 0 }.count() + } + + //Benchmark + fun filterWithLambda(): List { + return data.filter { it.value % 2 == 0 } + } + + //Benchmark + fun mapWithLambda(): List { + return data.map { it.toString() } + } + + //Benchmark + fun countWithLambda(): Int { + return data.count { it.value % 2 == 0 } + } + + //Benchmark + fun filterAndMapWithLambda(): List { + return data.filter { it.value % 2 == 0 }.map { it.toString() } + } + + //Benchmark + fun filterAndMapWithLambdaAsSequence(): List { + return data.asSequence().filter { it.value % 2 == 0 }.map { it.toString() }.toList() + } + + //Benchmark + fun filterAndMap(): List { + return data.filter { filterLoad(it) }.map { mapLoad(it) } + } + + //Benchmark + fun filterAndMapManual(): ArrayList { + val list = ArrayList() + for (it in data) { + if (filterLoad(it)) { + val value = mapLoad(it) + list.add(value) + } + } + return list + } + + //Benchmark + fun filter(): List { + return data.filter { filterLoad(it) } + } + + //Benchmark + fun filterManual(): List { + val list = ArrayList() + for (it in data) { + if (filterLoad(it)) + list.add(it) + } + return list + } + + //Benchmark + fun countFilteredManual(): Int { + var count = 0 + for (it in data) { + if (filterLoad(it)) + count++ + } + return count + } + + //Benchmark + fun countFiltered(): Int { + return data.count { filterLoad(it) } + } + + //Benchmark +// fun countFilteredLocal(): Int { +// return data.cnt { filterLoad(it) } +// } + + //Benchmark + fun reduce(): Int { + return data.fold(0) { acc, it -> if (filterLoad(it)) acc + 1 else acc } + } +} diff --git a/kotlin-native/performance/ring/src/main/kotlin/org/jetbrains/ring/ClassStreamBenchmark.kt b/kotlin-native/performance/ring/src/main/kotlin/org/jetbrains/ring/ClassStreamBenchmark.kt new file mode 100644 index 00000000000..793824ac9bc --- /dev/null +++ b/kotlin-native/performance/ring/src/main/kotlin/org/jetbrains/ring/ClassStreamBenchmark.kt @@ -0,0 +1,103 @@ +/* + * Copyright 2010-2017 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.jetbrains.ring + +import org.jetbrains.benchmarksLauncher.Blackhole + +open class ClassStreamBenchmark { + private var _data: Iterable? = null + val data: Iterable + get() = _data!! + + init { + _data = classValues(BENCHMARK_SIZE) + } + + //Benchmark + fun copy(): List { + return data.asSequence().toList() + } + + //Benchmark + fun copyManual(): List { + val list = ArrayList() + for (item in data.asSequence()) { + list.add(item) + } + return list + } + + //Benchmark + fun filterAndCount(): Int { + return data.asSequence().filter { filterLoad(it) }.count() + } + + //Benchmark + fun filterAndMap() { + for (item in data.asSequence().filter { filterLoad(it) }.map { mapLoad(it) }) + Blackhole.consume(item) + } + + //Benchmark + fun filterAndMapManual() { + for (it in data.asSequence()) { + if (filterLoad(it)) { + val item = mapLoad(it) + Blackhole.consume(item) + } + } + } + + //Benchmark + fun filter() { + for (item in data.asSequence().filter { filterLoad(it) }) + Blackhole.consume(item) + } + + //Benchmark + fun filterManual(){ + for (it in data.asSequence()) { + if (filterLoad(it)) + Blackhole.consume(it) + } + } + + //Benchmark + fun countFilteredManual(): Int { + var count = 0 + for (it in data.asSequence()) { + if (filterLoad(it)) + count++ + } + return count + } + + //Benchmark + fun countFiltered(): Int { + return data.asSequence().count { filterLoad(it) } + } + + //Benchmark +// fun countFilteredLocal(): Int { +// return data.asSequence().cnt { filterLoad(it) } +// } + + //Benchmark + fun reduce(): Int { + return data.asSequence().fold(0) {acc, it -> if (filterLoad(it)) acc + 1 else acc } + } +} \ No newline at end of file diff --git a/kotlin-native/performance/ring/src/main/kotlin/org/jetbrains/ring/CompanionObjectBenchmark.kt b/kotlin-native/performance/ring/src/main/kotlin/org/jetbrains/ring/CompanionObjectBenchmark.kt new file mode 100644 index 00000000000..9c2c4c39659 --- /dev/null +++ b/kotlin-native/performance/ring/src/main/kotlin/org/jetbrains/ring/CompanionObjectBenchmark.kt @@ -0,0 +1,30 @@ +/* + * Copyright 2010-2017 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.jetbrains.ring + +open class CompanionObjectBenchmark { + //Benchmark + fun invokeRegularFunction() { + regularCompanionObjectFunction("") + } + + companion object { + fun regularCompanionObjectFunction(o: Any): Any { + return o + } + } +} \ No newline at end of file diff --git a/kotlin-native/performance/ring/src/main/kotlin/org/jetbrains/ring/CoordinatesSolver.kt b/kotlin-native/performance/ring/src/main/kotlin/org/jetbrains/ring/CoordinatesSolver.kt new file mode 100644 index 00000000000..dd8e975c7a6 --- /dev/null +++ b/kotlin-native/performance/ring/src/main/kotlin/org/jetbrains/ring/CoordinatesSolver.kt @@ -0,0 +1,350 @@ +package org.jetbrains.ring + +import kotlin.experimental.and + +class CoordinatesSolverBenchmark { + val solver: Solver + + init { + val inputValue = """ + 12 5 3 25 3 9 3 9 1 3 + 13 3 12 6 10 10 12 2 10 10 + 9 2 9 5 6 12 5 0 2 10 + 10 14 12 5 3 9 5 2 10 10 + 8 1 3 9 4 0 3 14 10 10 + 12 0 4 6 9 6 12 5 6 10 + 11 12 3 9 6 9 5 3 9 6 + 8 5 6 8 3 12 7 10 10 11 + 12 3 13 6 12 3 9 6 12 2 + 13 4 5 5 5 6 12 5 5 2 + 1""".trimIndent() + val input = readTillParsed(inputValue) + + solver = Solver(input!!) + } + + data class Coordinate(val x: Int, val y: Int) + + @SinceKotlin("1.1") + data class Field(val x: Int, val y: Int, val value: Byte) { + fun northWall(): Boolean { + return value and 1 != 0.toByte() + } + + fun eastWall(): Boolean { + return value and 2 != 0.toByte() + } + + fun southWall(): Boolean { + return value and 4 != 0.toByte() + } + + fun westWall(): Boolean { + return value and 8 != 0.toByte() + } + + fun hasObject(): Boolean { + return value and 16 != 0.toByte() + } + } + + class Input(val labyrinth: Labyrinth, val nObjects: Int) + + class Labyrinth(val width: Int, val height: Int, val fields: Array) { + fun getField(x: Int, y: Int): Field { + return fields[x + y * width] + } + } + + class Output(val steps: List) + + class InputParser { + private val rows : MutableList> = mutableListOf() + private var numObjects: Int = 0 + + private val input: Input + get() { + val width = rows[0].size + val fields = arrayOfNulls(width * rows.size) + + for (y in rows.indices) { + val row = rows[y] + for (p in y*width until y*width + width) { + fields[p] = row[p-y*width] + } + } + + val labyrinth = Labyrinth(width, rows.size, fields.requireNoNulls()) + + return Input(labyrinth, numObjects) + } + + fun feedLine(line: String): Input? { + val items = line.split(" ".toRegex()).dropLastWhile { it.isEmpty() }.toTypedArray() + + if (items.size == 1) { + numObjects = items[0].toInt() + + return input + } else if (items.size > 0) { + val rowNum = rows.size + val row = arrayOfNulls(items.size) + + for (col in items.indices) { + row[col] = Field(rowNum, col, items[col].toByte()) + } + + rows.add(row.requireNoNulls()) + } + + return null + } + } + + + class Solver(private val input: Input) { + private val objects: List + + private val width: Int + private val height: Int + private val maze_end: Coordinate + + private var counter: Long = 0 + + init { + + objects = ArrayList() + for (f in input.labyrinth.fields) { + if (f.hasObject()) { + objects.add(Coordinate(f.x, f.y)) + } + } + + width = input.labyrinth.width + height = input.labyrinth.height + maze_end = Coordinate(width - 1, height - 1) + } + + fun solve(): Output { + val steps = ArrayList() + + for (o in objects.indices) { + var limit = input.labyrinth.width + input.labyrinth.height - 2 + + var ss: List? = null + while (ss == null) { + if (o == 0) { + ss = solveWithLimit(limit, MAZE_START) { it[it.size - 1] == objects[0] } + } else { + ss = solveWithLimit(limit, objects[o - 1]) { it[it.size - 1] == objects[o] } + } + + if (ss != null) { + steps.addAll(ss) + } + + limit++ + } + } + + var limit = input.labyrinth.width + input.labyrinth.height - 2 + + var ss: List? = null + while (ss == null) { + ss = solveWithLimit(limit, objects[objects.size - 1]) { it[it.size - 1] == maze_end } + + if (ss != null) { + steps.addAll(ss) + } + + limit++ + } + + return createOutput(steps) + } + + private fun createOutput(steps: List): Output { + val objects : MutableList = this.objects.toMutableList() + val outSteps : MutableList = mutableListOf() + + for (step in steps) { + outSteps.add(step) + + if (objects.contains(step)) { + outSteps.add(null) + objects.remove(step) + } + } + + return Output(outSteps) + } + + private fun isValid(steps: List): Boolean { + counter++ + val (x, y) = steps[steps.size - 1] + return if (!(x == input.labyrinth.width - 1 && y == input.labyrinth.height - 1)) { // Jobb also a cel + false + } else steps.containsAll(objects) + + } + + private fun getPossibleSteps(now: Coordinate, previous: Coordinate?): ArrayList { + val field = input.labyrinth.getField(now.x, now.y) + + val possibleSteps = ArrayList() + + if (now.x != width - 1 && !field.eastWall()) { + possibleSteps.add(Coordinate(now.x + 1, now.y)) + } + if (now.x != 0 && !field.westWall()) { + possibleSteps.add(Coordinate(now.x - 1, now.y)) + } + if (now.y != 0 && !field.northWall()) { + possibleSteps.add(Coordinate(now.x, now.y - 1)) + } + if (now.y != height - 1 && !field.southWall()) { + possibleSteps.add(Coordinate(now.x, now.y + 1)) + } + + if (!field.hasObject() && previous != null) { + possibleSteps.remove(previous) + } + + return possibleSteps + } + + private fun solveWithLimit(limit: Int, start: Coordinate, validFn: (List) -> Boolean): List? { + var steps: MutableList? = findFirstLegitSteps(null, start, limit) + + while (steps != null && !validFn(steps)) { + steps = alter(start, null, steps) + } + + return steps + } + + private fun findFirstLegitSteps(startPrev: Coordinate?, start: Coordinate, num: Int): MutableList? { + var steps: MutableList? = ArrayList() + + + var i = 0 + while (i < num) { + val prev: Coordinate? + val state: Coordinate + + if (i == 0) { + state = start + prev = startPrev + } else if (i == 1) { + state = steps!![i - 1] + prev = startPrev + } else { + state = steps!![i - 1] + prev = steps[i - 2] + } + + val possibleSteps = getPossibleSteps(state, prev) + + if (possibleSteps.size == 0) { + if (steps!!.size == 0) { + return null + } + + steps = alter(start, startPrev, steps) + if (steps == null) { + return null + } + + i-- + i++ + continue + } + + val newStep = possibleSteps[0] + steps!!.add(newStep) + i++ + } + + return steps + } + + private fun alter(start: Coordinate, startPrev: Coordinate?, steps: MutableList): MutableList? { + val size = steps.size + + var i = size - 1 + while (i >= 0) { + val current = steps[i] + val prev = if (i == 0) start else steps[i - 1] + val prevprev: Coordinate? + if (i > 1) { + prevprev = steps[i - 2] + } else if (i == 1) { + prevprev = start + } else { + prevprev = startPrev + } + + val alternatives = getPossibleSteps(prev, prevprev) + val index = alternatives.indexOf(current) + + if (index != alternatives.size - 1) { + val newItem = alternatives[index + 1] + steps[i] = newItem + + val remainder = findFirstLegitSteps(prev, newItem, size - i - 1) + if (remainder == null) { + i++ + i-- + continue + } + + removeAfterIndexExclusive(steps, i) + steps.addAll(remainder) + + return steps + } else { + if (i == 0) { + return null + } + } + i-- + } + + return steps + } + + companion object { + private val MAZE_START = Coordinate(0, 0) + private fun removeAfterIndexExclusive(list: MutableList<*>, index: Int) { + val rnum = list.size - 1 - index + + for (i in 0 until rnum) { + list.removeAt(list.size - 1) + } + } + } + } + + private fun readTillParsed(inputValue: String): Input? { + + val parser = InputParser() + var input: Input? = null + inputValue.lines().forEach { line -> + input = parser.feedLine(line) + } + + return input + } + + fun solve() { + val output = solver.solve() + + for (c in output.steps) { + val value = if (c == null) { + "felvesz" + } else { + "${c.x} ${c.y}" + } + } + } +} \ No newline at end of file diff --git a/kotlin-native/performance/ring/src/main/kotlin/org/jetbrains/ring/Data.kt b/kotlin-native/performance/ring/src/main/kotlin/org/jetbrains/ring/Data.kt new file mode 100644 index 00000000000..dbe8bcb1c60 --- /dev/null +++ b/kotlin-native/performance/ring/src/main/kotlin/org/jetbrains/ring/Data.kt @@ -0,0 +1,100 @@ +/* + * Copyright 2010-2017 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.jetbrains.ring + +fun classValues(size: Int): Iterable { + return intValues(size).map { Value(it) } +} + +fun stringValues(size: Int): Iterable { + return intValues(size).map { it.toString() } +} + +fun intValues(size: Int): Iterable { + return 1..size +} + +open class Value(var value: Int) { + val text = value.toString().reversed() +} + +fun filterLoad(v: Value): Boolean { + return v.value.toString() in v.text +} + +fun mapLoad(v: Value): String = v.text.reversed() + +fun filterLoad(v: Int): Boolean { + return v.toString() in "0123456789" +} + +fun mapLoad(v: Int): String = v.toString() + +fun filterSome(v: Int): Boolean = v % 7 == 0 || v % 11 == 0 + +fun filterPrime(v: Int): Boolean { + if (v <= 1) + return false + if (v <= 3) + return true + if (v % 2 == 0) + return false + var i = 3 + while (i*i <= v) { + if (v % i == 0) + return false + i += 2 + } + return true +} + +inline fun Array.cnt(predicate: (Value) -> Boolean): Int { + var count = 0 + for (element in this) { + if (predicate(element)) + count++ + } + return count +} + +inline fun IntArray.cnt(predicate: (Int) -> Boolean): Int { + var count = 0 + for (element in this) { + if (predicate(element)) + count++ + } + return count +} + +inline fun Iterable.cnt(predicate: (Int) -> Boolean): Int { + var count = 0 + for (element in this) { + if (predicate(element)) + count++ + } + return count +} + +inline fun Sequence.cnt(predicate: (Int) -> Boolean): Int { + var count = 0 + for (element in this) { + if (predicate(element)) + count++ + } + return count +} + diff --git a/kotlin-native/performance/ring/src/main/kotlin/org/jetbrains/ring/DefaultArgumentBenchmark.kt b/kotlin-native/performance/ring/src/main/kotlin/org/jetbrains/ring/DefaultArgumentBenchmark.kt new file mode 100644 index 00000000000..ae5594fe863 --- /dev/null +++ b/kotlin-native/performance/ring/src/main/kotlin/org/jetbrains/ring/DefaultArgumentBenchmark.kt @@ -0,0 +1,82 @@ +/* + * Copyright 2010-2017 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.jetbrains.ring +import org.jetbrains.benchmarksLauncher.Random + +/** + * Created by Mikhail.Glukhikh on 10/03/2015. + * + * Tests performance for function calls with default parameters + */ +open class DefaultArgumentBenchmark { + private var arg = 0 + + init { + arg = Random.nextInt() + } + + + fun sumTwo(first: Int, second: Int = 0): Int { + return first + second + } + + + fun sumFour(first: Int, second: Int = 0, third: Int = 1, fourth: Int = third): Int { + return first + second + third + fourth + } + + + fun sumEight(first: Int, second: Int = 0, third: Int = 1, fourth: Int = third, + fifth: Int = fourth, sixth: Int = fifth, seventh: Int = second, eighth: Int = seventh): Int { + return first + second + third + fourth + fifth + sixth + seventh + eighth + } + + + //Benchmark + fun testOneOfTwo() { + sumTwo(arg) + } + + + //Benchmark + fun testTwoOfTwo() { + sumTwo(arg, arg) + } + + //Benchmark + fun testOneOfFour() { + sumFour(arg) + } + + + //Benchmark + fun testFourOfFour() { + sumFour(arg, arg, arg, arg) + } + + + //Benchmark + fun testOneOfEight() { + sumEight(arg) + } + + + //Benchmark + fun testEightOfEight() { + sumEight(arg, arg, arg, arg, arg, arg, arg, arg) + } +} diff --git a/kotlin-native/performance/ring/src/main/kotlin/org/jetbrains/ring/ElvisBenchmark.kt b/kotlin-native/performance/ring/src/main/kotlin/org/jetbrains/ring/ElvisBenchmark.kt new file mode 100644 index 00000000000..b77d11d72a1 --- /dev/null +++ b/kotlin-native/performance/ring/src/main/kotlin/org/jetbrains/ring/ElvisBenchmark.kt @@ -0,0 +1,53 @@ +/* + * Copyright 2010-2017 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.jetbrains.ring + +import org.jetbrains.benchmarksLauncher.Blackhole +import org.jetbrains.benchmarksLauncher.Random + +open class ElvisBenchmark { + + class Value(var value: Int) + + var array : Array = arrayOf() + + init { + array = Array(BENCHMARK_SIZE) { + if (Random.nextInt(BENCHMARK_SIZE) < BENCHMARK_SIZE / 10) null else Value(Random.nextInt()) + } + } + + //Benchmark + fun testElvis() { + for (obj in array) { + Blackhole.consume(obj?.value ?: 0) + } + } + + class Composite(val x : Int, val y : Composite?) + + fun check(a : Composite?) : Int { + return a?.y?.x ?: (a?.x ?: 3) + } + + fun testCompositeElvis(): Int { + var result = 0 + for (i in 0..BENCHMARK_SIZE) + result += check(Composite(Random.nextInt(), Composite(Random.nextInt(), null))) + return result + } +} diff --git a/kotlin-native/performance/ring/src/main/kotlin/org/jetbrains/ring/EulerBenchmark.kt b/kotlin-native/performance/ring/src/main/kotlin/org/jetbrains/ring/EulerBenchmark.kt new file mode 100644 index 00000000000..70b43d6dfc8 --- /dev/null +++ b/kotlin-native/performance/ring/src/main/kotlin/org/jetbrains/ring/EulerBenchmark.kt @@ -0,0 +1,210 @@ +/* + * Copyright 2010-2017 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.jetbrains.ring + +fun fibonacci(): Sequence { + var a = 0 + var b = 1 + fun next(): Int { + val res = a + b + a = b + b = res + return res + } + return generateSequence { next() } +} + +fun Any.isPalindrome() = toString() == toString().reversed() + +inline fun IntRange.sum(predicate: (Int) -> Boolean): Int { + var sum = 0 + for (i in this) if (predicate(i)) sum += i + return sum +} + +inline fun Sequence.sum(predicate: (Int) -> Boolean): Int { + var sum = 0 + for (i in this) if (predicate(i)) sum += i + return sum +} + +/** + * A class tests decisions of various Euler problems + * + * NB: all tests here work slower than Java, probably because of all these functional wrappers + */ +open class EulerBenchmark { + + //Benchmark + fun problem1bySequence() = (1..BENCHMARK_SIZE).asSequence().sum( { it % 3 == 0 || it % 5 == 0} ) + + //Benchmark + fun problem1() = (1..BENCHMARK_SIZE).sum( { it % 3 == 0 || it % 5 == 0} ) + + //Benchmark + fun problem2() = fibonacci().takeWhile { it < BENCHMARK_SIZE }.sum { it % 2 == 0 } + + //Benchmark + fun problem4(): Long { + val s: Long = BENCHMARK_SIZE.toLong() + val maxLimit = (s-1)*(s-1) + val minLimit = (s/10)*(s/10) + val maxDiv = BENCHMARK_SIZE-1 + val minDiv = BENCHMARK_SIZE/10 + for (i in maxLimit downTo minLimit) { + if (!i.isPalindrome()) continue; + for (j in minDiv..maxDiv) { + if (i % j == 0L) { + val res = i / j + if (res in minDiv.toLong()..maxDiv.toLong()) { + return i + } + } + } + } + return -1 + } + + private val veryLongNumber = """ + 73167176531330624919225119674426574742355349194934 + 96983520312774506326239578318016984801869478851843 + 85861560789112949495459501737958331952853208805511 + 12540698747158523863050715693290963295227443043557 + 66896648950445244523161731856403098711121722383113 + 62229893423380308135336276614282806444486645238749 + 30358907296290491560440772390713810515859307960866 + 70172427121883998797908792274921901699720888093776 + 65727333001053367881220235421809751254540594752243 + 52584907711670556013604839586446706324415722155397 + 53697817977846174064955149290862569321978468622482 + 83972241375657056057490261407972968652414535100474 + 82166370484403199890008895243450658541227588666881 + 16427171479924442928230863465674813919123162824586 + 17866458359124566529476545682848912883142607690042 + 24219022671055626321111109370544217506941658960408 + 07198403850962455444362981230987879927244284909188 + 84580156166097919133875499200524063689912560717606 + 05886116467109405077541002256983155200055935729725 + 71636269561882670428252483600823257530420752963450 + """ + + + //Benchmark + fun problem8(): Long { + val productSize = when(BENCHMARK_SIZE) { + in 1..10 -> 4 + in 11..1000 -> 8 + else -> 13 + } + val digits: MutableList = ArrayList() + for (digit in veryLongNumber) { + if (digit in '0'..'9') { + digits.add(digit.toInt() - '0'.toInt()) + } + } + var largest = 0L + for (i in 0..digits.size -productSize-1) { + var product = 1L + for (j in 0..productSize-1) { + product *= digits[i+j] + } + if (product > largest) largest = product + } + return largest + } + + + //Benchmark + fun problem9(): Long { + val BENCHMARK_SIZE = BENCHMARK_SIZE // Looks awful but removes all implicit getSize() calls + for (c in BENCHMARK_SIZE/3..BENCHMARK_SIZE-3) { + val c2 = c.toLong() * c.toLong() + for (b in (BENCHMARK_SIZE-c)/2..c-1) { + if (b+c >= BENCHMARK_SIZE) + break + val a = BENCHMARK_SIZE - b - c + if (a >= b) + continue + val b2 = b.toLong() * b.toLong() + val a2 = a.toLong() * a.toLong() + if (c2 == b2 + a2) { + return a.toLong() * b.toLong() * c.toLong() + } + } + } + return -1L + } + + data class Children(val left: Int, val right: Int) + + //Benchmark + fun problem14(): List { + // Simplified problem is solved here: it's not allowed to leave the interval [0..BENCHMARK_SIZE) inside a number chain + val BENCHMARK_SIZE = BENCHMARK_SIZE + // Build a tree + // index is produced from first & second + val tree = Array(BENCHMARK_SIZE, { i -> Children(i*2, if (i>4 && (i+2) % 6 == 0) (i-1)/3 else 0)}) + // Find longest chain by DFS + fun dfs(begin: Int): List { + if (begin == 0 || begin >= BENCHMARK_SIZE) + return listOf() + val left = dfs(tree[begin].left) + val right = dfs(tree[begin].right) + return listOf(begin) + if (left.size > right.size) left else right + } + return dfs(1) + } + + data class Way(val length: Int, val next: Int) + + + //Benchmark + fun problem14full(): List { + val BENCHMARK_SIZE = BENCHMARK_SIZE + // Previous achievements: map (number) -> (length, next) + val map: MutableMap = HashMap() + // Starting point + map.put(1, Way(0, 0)) + // Check all other numbers + var bestNum = 0 + var bestLen = 0 + fun go(begin: Int): Way { + val res = map[begin] + if (res != null) + return res + val next = if (begin % 2 == 0) begin/2 else 3*begin+1 + val childRes = go(next) + val myRes = Way(childRes.length + 1, next) + map[begin] = myRes + return myRes + } + for (i in 2..BENCHMARK_SIZE-1) { + val res = go(i) + if (res.length > bestLen) { + bestLen = res.length + bestNum = i + } + } + fun unroll(begin: Int): List { + if (begin == 0) + return listOf() + val next = map[begin]?.next ?: 0 + return listOf(begin) + unroll(next) + } + return unroll(bestNum) + } +} diff --git a/kotlin-native/performance/ring/src/main/kotlin/org/jetbrains/ring/FibonacciBenchmark.kt b/kotlin-native/performance/ring/src/main/kotlin/org/jetbrains/ring/FibonacciBenchmark.kt new file mode 100644 index 00000000000..cc36aba185c --- /dev/null +++ b/kotlin-native/performance/ring/src/main/kotlin/org/jetbrains/ring/FibonacciBenchmark.kt @@ -0,0 +1,86 @@ +/* + * Copyright 2010-2017 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.jetbrains.ring + +/** + * This test checks work with long numbers using Fibonacci sequence + * + * NB: all three tests here work CRITICALLY (x4...x6) slower than their Java equivalents + * The reason is iteration on a progression formed as max downTo min or min..max step s. + * In case of a range min..max primitive types are used by the Kotlin compiler, + * but when we have a progression it's used directly with its iterator and so. + */ + +open class FibonacciBenchmark { + + //Benchmark + fun calcClassic(): Long { + var a = 1L + var b = 2L + val size = BENCHMARK_SIZE + for (i in 0..size-1) { + val next = a + b + a = b + b = next + } + return b + } + + //Benchmark + fun calc(): Long { + // This test works CRITICALLY slower compared with java equivalent (05.03.2015) + var a = 1L + var b = 2L + // Probably for with downTo is the reason of slowness + for (i in BENCHMARK_SIZE downTo 1) { + val next = a + b + a = b + b = next + } + return b + } + + //Benchmark + fun calcWithProgression(): Long { + // This test works CRITICALLY slower compared with java equivalent (05.03.2015) + var a = 1L + var b = 2L + // Probably for with step is the reason of slowness + for (i in 1..2*BENCHMARK_SIZE-1 step 2) { + val next = a + b + a = b + b = next + } + return b + } + + //Benchmark + fun calcSquare(): Long { + // This test works CRITICALLY slower compared with java equivalent (05.03.2015) + var a = 1L + var b = 2L + val s = BENCHMARK_SIZE.toLong() + val limit = s*s + // Probably for with downTo is the reason of slowness + for (i in limit downTo 1) { + val next = a + b + a = b + b = next + } + return b + } +} \ No newline at end of file diff --git a/kotlin-native/performance/ring/src/main/kotlin/org/jetbrains/ring/ForLoopsBenchmark.kt b/kotlin-native/performance/ring/src/main/kotlin/org/jetbrains/ring/ForLoopsBenchmark.kt new file mode 100644 index 00000000000..67dc5dc6533 --- /dev/null +++ b/kotlin-native/performance/ring/src/main/kotlin/org/jetbrains/ring/ForLoopsBenchmark.kt @@ -0,0 +1,104 @@ +package org.jetbrains.ring + +class ForLoopsBenchmark { + + private val array: Array = Array(BENCHMARK_SIZE) { + it + } + + private val intArray: IntArray = IntArray(BENCHMARK_SIZE) { + it + } + + private val charArray: CharArray = CharArray(BENCHMARK_SIZE) { + it.toChar() + } + + private val string: String = charArray.joinToString() + + private val floatArray: FloatArray = FloatArray(BENCHMARK_SIZE) { + it.toFloat() + } + + fun arrayLoop(): Long { + var sum = 0L + for (e in array) { + sum += e + } + return sum + } + + fun intArrayLoop(): Long { + var sum = 0L + for (e in intArray) { + sum += e + } + return sum + } + + fun charArrayLoop(): Long { + var sum = 0L + for (e in charArray) { + sum += e.toLong() + } + return sum + } + + fun stringLoop(): Long { + var sum = 0L + for (e in string) { + sum += e.hashCode() + } + return sum + } + + fun floatArrayLoop(): Double { + var sum = 0.0 + for (e in floatArray) { + sum += e + } + return sum + } + + // Iterations over .indices + + fun arrayIndicesLoop(): Long { + var sum = 0L + for (i in array.indices) { + sum += array[i] + } + return sum + } + + fun intArrayIndicesLoop(): Long { + var sum = 0L + for (i in intArray.indices) { + sum += intArray[i] + } + return sum + } + + fun charArrayIndicesLoop(): Long { + var sum = 0L + for (i in charArray.indices) { + sum += charArray[i].toLong() + } + return sum + } + + fun stringIndicesLoop(): Long { + var sum = 0L + for (i in string.indices) { + sum += string[i].hashCode() + } + return sum + } + + fun floatArrayIndicesLoop(): Double { + var sum = 0.0 + for (i in floatArray.indices) { + sum += floatArray[i] + } + return sum + } +} \ No newline at end of file diff --git a/kotlin-native/performance/ring/src/main/kotlin/org/jetbrains/ring/GraphSolverBenchmark.kt b/kotlin-native/performance/ring/src/main/kotlin/org/jetbrains/ring/GraphSolverBenchmark.kt new file mode 100644 index 00000000000..085da8659a5 --- /dev/null +++ b/kotlin-native/performance/ring/src/main/kotlin/org/jetbrains/ring/GraphSolverBenchmark.kt @@ -0,0 +1,1073 @@ +package org.jetbrains.ring + +class Graph { + val nodes: MutableList = mutableListOf() + val size + get() = nodes.size + + fun first(): Node = nodes.first() + + operator fun get(nodeId: Int): Node = nodes.getOrElse(nodeId) { nodes.add(it, Node(it)) ; nodes[it] } +} + +class Node(val id: Int) { + val neighbors: MutableMap = mutableMapOf() +} + +fun parseData(content: List): Graph { + val graph = Graph() + + content.filter(String::isNotBlank).forEachIndexed { lineNumber, line -> + addNeighbors(line, graph, lineNumber) + } + + return graph +} + +private data class ClosestNode(val node: Node, val distance: Int) + +class Greedy(private val graph: Graph) { + private val visitedNodes: MutableSet = mutableSetOf() + + private fun getClosest(node: Node): ClosestNode? { + val nodes = node.neighbors + .filter { it.value != 0 && !visitedNodes.contains(it.key) } + val clostest = nodes + .minBy { it.value }!! + return ClosestNode(clostest.key, clostest.value) + } + + fun solve() { + var previousNode = graph.first() + visitedNodes.add(graph.first()) + var cost = 0 + + while (visitedNodes.size != graph.size) { + val closest = getClosest(previousNode)!! + visitedNodes.add(closest.node) + cost += closest.distance + previousNode = closest.node + } + + cost += visitedNodes.last().neighbors[graph.first()]!! + } +} + +fun addNeighbors(line: String, graph: Graph, lineNumber: Int): Node { + val node = graph[lineNumber] + line.split(',').forEachIndexed { index, value -> + node.neighbors.put(graph[index], value.trim().toInt())//.trim().toInt()) + } + return node +} + + +class GraphSolverBenchmark { + val content = listOf( + "0,604,802,57,278,84,33,758,908,420,610,484,195,474,254,969,172,463,130,335,704,507,358,852,356,444,396,95,446,86,397,893,56,812,967,40,229,33,112,913,548,902,793,563,318,311,579,58,145,304,133,440,159,219,300,855,443,385,157,770,29,97,229,734,829,324,917,380,817,597,461,386,536,942,533,774,71,996,752,6,741,644,701,782,870,947,159,464,412,807,765,174,334,77,930,536,885,533,202,191,825,342,578,76,394,432,786,313,693,587,659,55,491,467,33,955,883,353,452,60,588,87,109,473,66,965,973,950,952,492,624,810,87,62,218,435,559,283,562,798,349,201,383,249,69,263,415,961,56,755,616,27,186,63,247,800,503,767,869,13,252,746,6,436,793,189,926,442,465,225,573,379,875,620,294,452,832,739,354,781,348,264,790,110,369,393,678,873,8,708,268,177,722,49,448,849,381,720,166,208,178,634,557,595,969,968,384,682,558,298,726,899,444,420,481,714,524,633,897,279,760,755,101,37,769,460,252,869,700,182,507,389,263,88,291,885,106,638,375,661,375,941,487,58,890,700,121,852,700,888,814,546,374,771,683,730,478,446,456,447,369,727,258,307,794,669,438,604,549,921,848,918,694,512,390,913,118,776,441,438,488,187,813,668,373,522,411,772,943,183,6,84,984,619,453,729,744,166,880,800,860,869,805,873,296,706,901,155,111,286,958,119,652,2,140,248,809,475,752,368,924,108,276,472,469,704,92,680,374,473,372,607,251,454,718,228,252,116,812,561,49,248,826,682,598,900,239,652,367,293,196,868,18,555,746,142,170,75,788,675,661,697,632,185,283,838,509,843,222,690,783,963,550,621,211,276,133,303,695,211,957,685,686,98,902,725,707,758,194,461,411,177,912,818,92,512,480,795,586,161,962,546,891,223,476,937,669,938,516,247,668,751,195,678,848,764,888,40,291,456,710,685,129,637,876,293,194,102,153,903,414,766,368,31,561,537,962,873,902,529,362,225,936,743,782,307,217,300,921,699,664,638,862,170,916,806,721,100,395,800,244,50,746,500,962,753,547,889,199,743,611,357,952,781,899,548,507,875,434,702,109,32,835,788,108,469,171,993,886,130,871,752,217,896,446,66,223,648,352,497,782,182,463,557,20,849,685,956,834,676,28,533,256,904,606,334,472,206,942,166,38,203,953,201,566,409,64,833,958,784,852,817,835,829,911,254,917,706,681,35,456,795,615,349,597,198,643,18,955,531,431,49,80,699,35,345,830,687,406,605,872,293,697,348,296,472,951,117,464,843,96,359,945,388,226,338,41,429,367,940,474,477,978,867,975,632,388,319,999,409,145,748,136,226,853,21,620,89,319,557,602,206,759,638,977,499,723,381,223,299,298,981,642,100,95,828,794,689,778,983,201,195,905,670,313,555,762,962,212,311,572,852,657,622,461,101,771,644,925,761,286,275,297,246,904,24,327,474,455,395,148,330,919,710,485,709,341,871,669,27,5,643,840,999,940,489,803,164,806,187,989,178,257,835,516,172,594,661,77,28,961,222,953,604,611,111,296,784,967,175,448,130,611,998,669,350,234,272,149,714,942,501,378,192,28,891,694,37,788,495,961,770,736,207,903,664,21,345,480,604,451,271,99,81,131,902,314,436,979,634,63,164,849,736,283,210,5,131,117,978,379,488,392,649,951,927,757,835,567,472,530,589,959,213,74,904,270,677,787,884,287,569,182,11,604,384,440,914,286,110,760,639,284,3,523,275,968,342,759,765,907,624,468,674,891,81,205,226,907,158,473,622,67,981,858,790,268,176,998,811,987,130,307,735,414,822,625,147,210,875,778,175,388,671,762,352,550,496,82,985,340,915,946,803,441,822,142,297,409,773,356,890,170,201,815,931,486,626,223,290,722,178,39,873,601,741,88,690,295,272,189,397,631,546,178,718,124,397,234,251,503,64,990,295,733,948,449,540,728,801,351,2,553,75,595,907,299,469,258,40,524,845,281,892,64,50,994,630,380,785,60,341,278,468,828,213,711,17,190,952,370,464,291,918,454,239,399,914,451,281,720,215,62,962,8,208,617,285,391,544,521,254,215,559,184,805,737,774,661,784,206,345,994,238,979,394,685,131,822,717,397,715,607,502,400,937,653,653,352,619,733,275,753,257,766,839,814,308,402,528,912,260,754,367,8,301,917,351,988,696,570,416,444,784,581,829,870,378,368,224,956,237,86,648,448,10,856,196,146,484,229,344,870,673,738,250,949,264,995,873", + "604,0,40,254,413,440,450,189,382,388,460,802,266,415,70,10,137,344,215,456,530,796,664,686,149,440,863,46,325,418,304,904,295,948,626,722,167,27,396,183,396,822,81,117,114,950,786,101,888,750,550,293,584,254,732,694,278,971,813,730,589,978,214,629,781,358,941,962,144,609,629,25,779,492,412,778,302,220,159,617,673,703,602,256,997,805,922,332,116,639,333,384,526,980,764,929,183,987,806,519,293,758,992,261,587,366,154,544,480,983,148,855,372,746,876,207,833,719,607,546,124,719,555,154,264,486,643,437,828,729,571,950,71,908,63,125,560,335,612,16,296,884,446,530,622,121,742,378,816,616,307,115,492,646,831,308,254,860,338,739,614,918,21,493,370,512,817,584,872,221,184,321,218,878,919,841,327,320,949,838,138,537,868,329,759,923,496,960,488,452,407,844,390,619,477,822,968,17,632,471,639,273,142,763,708,694,395,53,976,778,842,967,875,668,980,367,48,424,692,958,223,374,929,828,450,465,411,75,199,145,705,227,66,620,982,33,317,925,780,598,712,29,191,650,287,301,735,765,117,501,324,264,10,538,808,114,389,563,375,421,267,265,554,862,609,244,662,714,194,853,788,359,355,944,781,907,520,52,669,597,292,269,463,378,64,452,672,474,660,455,32,871,305,571,646,477,890,624,850,69,155,897,498,813,295,719,696,381,341,877,30,213,227,394,332,421,924,385,405,407,486,681,293,515,590,497,657,130,680,535,881,478,474,541,522,135,163,180,442,380,478,682,218,350,355,533,870,515,757,740,73,837,600,762,337,555,950,316,235,236,786,502,476,804,44,717,793,688,246,854,85,476,243,513,895,569,29,561,528,525,333,986,829,680,587,336,182,909,196,614,118,198,700,94,100,29,381,933,46,32,920,646,46,482,479,588,596,263,550,902,261,326,272,780,568,295,597,704,46,768,76,731,369,25,421,622,846,756,686,176,583,435,364,415,614,571,145,888,999,235,727,913,128,904,57,300,25,764,822,924,415,526,689,858,224,381,526,607,119,646,544,202,365,277,556,681,668,350,496,113,14,914,813,974,528,389,490,491,550,983,812,652,170,618,665,439,966,386,512,521,589,218,481,288,995,791,791,674,582,593,29,787,687,878,640,11,883,827,723,884,670,129,831,500,422,196,936,719,10,736,641,227,538,609,954,84,304,961,667,781,137,842,79,937,810,56,179,335,760,197,991,995,876,5,342,379,132,231,783,59,459,932,907,612,40,138,857,958,614,164,338,5,467,894,513,352,630,460,511,179,419,826,155,584,448,16,82,909,104,608,900,971,763,98,464,955,314,12,618,150,252,880,429,309,539,687,681,883,888,13,931,804,158,451,768,954,695,751,230,61,834,940,156,410,734,599,444,399,956,210,290,117,878,725,758,453,652,41,207,144,162,46,689,775,318,311,247,748,318,828,500,276,191,218,503,751,994,171,530,884,538,653,69,728,14,905,147,88,291,192,669,742,260,206,152,419,84,814,656,236,262,476,806,589,155,935,197,623,546,492,794,179,487,555,710,215,94,707,326,469,456,186,82,830,22,865,589,375,312,626,550,221,670,295,353,690,167,99,370,833,642,437,746,565,23,956,830,266,866,792,56,337,424,136,669,2,568,584,294,362,421,304,621,582,439,825,45,208,249,63,468,764,594,90,745,7,24,252,528,973,117,290,548,202,264,831,235,162,683,648,530,873,286,333,221,223,95,665,884,235,8,839,225,756,840,748,901,385,514,720,113,972,196,509,601,160,133,350,444,846,464,507,733,303,597,568,640,328,932,520,288,663,519,741,115,152,722,948,318,60,973,239,488,813,322,616,336,241,957,892,196,691,424,249,932,603,677,122,731,939,960,571,430,280,976,144,894,356,855,794,830,721,988,887,318,723,560,688,644,44,946,988,512,979,431,640,688,805,386,809,863,329,152,131,603,77,781,325,321,501,876,240,152,734,13,707,607,375,159,446,415,422,808,798,299,683,47,260,871,344,638,799,881,997,342,572,487,984,96,757,77,843,367,32,840,777,640,38,541,59,160,765,92,32,56,662,451,449,517,476,672,902,22,352,970,140,513,198,595,85,601,341,719,608,663,861,509,621,813,37,195,915,662,284,749,33,812,480,949,133,947,204,246,782,244,810,48,661,585,135,99,321,450,513,70,896,564,677,490,703,977,243,630,613,262,721,100,807,17,24,534,892,626,618,59,640,908,996,874,212,342,778,657,755,777,470,233,547,913,804", + "802,40,0,321,721,986,467,509,781,544,43,803,544,354,937,252,687,373,142,628,327,167,769,538,459,857,820,971,750,652,904,223,132,909,607,679,461,628,781,698,361,121,216,819,304,475,74,324,59,349,120,555,62,299,840,451,353,402,539,565,562,424,973,187,553,859,381,51,696,343,79,63,286,499,302,842,682,896,576,942,68,454,786,497,517,255,417,518,417,523,896,784,55,673,417,665,893,870,4,795,396,418,483,566,132,985,566,605,837,448,985,334,36,409,227,428,625,275,207,176,190,881,447,530,458,382,466,65,16,85,21,223,921,353,134,593,511,430,516,646,640,294,623,203,717,762,715,496,442,11,113,751,888,803,934,210,870,900,656,780,679,147,201,135,932,785,923,240,390,636,534,846,415,993,977,910,132,949,7,624,684,720,651,556,534,661,852,457,259,348,990,365,284,260,652,788,918,689,104,967,837,653,656,465,154,321,722,553,402,768,262,257,941,118,51,170,229,865,45,982,109,575,320,879,331,990,887,921,368,294,743,78,415,23,434,618,22,574,692,953,154,656,121,543,160,848,724,366,765,598,880,5,389,660,481,221,771,398,304,816,918,372,353,586,487,698,386,823,849,784,78,850,855,107,868,269,162,197,338,314,996,294,133,874,638,314,711,534,132,564,482,430,564,128,996,185,345,714,848,217,648,244,67,94,26,492,982,336,300,246,275,61,888,197,978,191,448,747,975,182,972,469,986,770,12,700,977,216,324,839,723,259,101,875,823,242,809,249,681,417,257,492,881,511,86,105,262,641,977,257,182,126,672,693,864,252,424,351,634,190,90,507,122,398,763,207,252,209,561,354,206,829,537,510,279,277,316,143,32,948,772,901,538,930,299,181,886,162,473,446,210,8,431,161,747,529,206,568,758,752,346,738,131,601,827,22,448,216,892,617,622,39,447,898,759,749,103,341,435,900,113,994,760,96,410,175,731,591,318,731,431,338,476,193,735,106,716,479,344,571,294,498,719,921,571,881,136,929,603,541,608,192,118,36,921,715,831,958,774,933,473,588,207,107,864,34,556,490,890,874,642,256,945,701,214,45,937,929,415,221,6,666,263,1,314,643,299,857,539,210,559,670,477,766,400,17,869,915,361,882,934,471,397,92,714,569,886,133,47,370,801,455,849,326,32,329,750,458,445,665,420,613,596,755,870,406,727,935,530,366,822,203,704,449,665,158,322,293,927,98,165,409,238,94,442,877,445,266,706,312,712,321,65,914,962,71,172,795,973,430,355,969,510,610,957,696,505,533,884,754,968,998,994,214,388,509,980,622,353,233,496,178,988,344,445,890,50,376,620,766,552,98,392,700,723,753,83,245,967,253,563,736,880,519,76,3,624,102,254,8,574,804,798,832,883,137,694,608,28,318,326,928,330,987,173,553,181,402,156,163,331,587,771,204,607,979,404,137,688,572,967,206,595,5,895,787,47,844,458,451,269,716,260,849,592,462,850,840,359,296,830,724,101,730,795,997,795,415,475,851,274,953,899,29,442,830,374,754,622,73,622,190,271,412,275,427,398,206,953,138,198,947,234,745,669,47,270,799,300,67,102,566,502,796,11,186,127,426,656,576,398,723,266,895,899,439,509,1000,517,991,77,617,659,695,334,797,375,721,220,739,464,67,62,396,530,888,346,67,264,744,772,726,838,590,964,760,201,16,9,160,868,124,267,460,928,316,325,173,52,820,394,410,759,46,246,275,400,664,787,817,860,333,452,897,618,760,943,24,834,426,894,126,413,484,412,769,301,349,973,720,343,210,915,640,221,94,937,576,995,751,235,914,855,548,434,415,280,83,405,104,197,213,852,907,357,4,99,969,116,474,421,86,950,62,216,409,559,488,511,618,766,232,239,591,556,351,839,689,387,944,336,262,156,978,879,623,634,258,805,64,603,919,87,809,605,36,197,183,639,333,991,644,570,761,180,673,802,137,78,680,825,283,630,661,843,964,443,945,868,455,470,458,710,493,378,467,194,984,178,44,765,755,523,121,834,711,136,668,888,467,799,429,25,817,322,339,141,662,560,647,840,462,761,410,764,177,39,138,974,919,138,965,727,270,191,780,59,213,694,381,534,970,20,39,952,195,784,683,218,146,915,520,335,561,873,916,478,11,470,583,601,973,266,88,141,299,916,97,951,306,220,434,419,183,307,287,216,258,162,249,210,135,677,290,752,535,984,861,840,436,14,529,762,746,944,873,838,795,296,199,149,675,941,533,422,227,581,470,328,976", + "57,254,321,0,726,976,877,679,555,918,259,522,153,491,650,419,377,449,295,813,575,548,550,571,135,708,85,803,595,15,973,375,674,439,832,866,244,950,993,821,818,906,58,492,863,955,503,775,396,520,652,572,404,747,304,949,222,7,383,658,89,188,122,919,600,45,473,37,105,517,619,545,30,163,866,785,54,219,573,636,635,557,930,80,595,94,675,781,143,384,363,838,109,41,294,160,950,754,224,659,377,26,517,74,503,784,953,482,526,469,13,183,732,180,775,752,408,597,866,425,684,790,475,48,839,592,379,950,990,980,716,332,189,908,819,65,555,158,438,681,78,447,931,721,183,377,333,839,570,636,296,301,947,552,920,443,592,793,781,277,326,971,673,208,83,916,373,413,642,157,212,366,680,482,876,431,961,307,10,286,188,982,970,237,614,274,50,808,973,66,918,456,370,723,118,301,412,789,988,80,886,457,333,603,737,985,546,479,222,881,247,954,128,478,249,511,378,363,108,577,932,170,241,733,500,357,200,713,503,588,513,833,440,189,241,10,210,56,331,982,572,675,525,801,546,827,99,741,130,337,869,743,702,585,401,725,478,889,796,244,310,251,484,862,94,179,486,991,626,301,855,974,793,135,183,768,746,162,3,73,810,559,822,836,74,250,739,982,336,284,604,411,974,808,349,808,688,280,743,824,396,664,467,751,156,576,183,930,471,667,564,731,900,938,249,300,542,745,24,119,41,486,869,298,149,310,350,146,568,159,209,243,164,575,305,881,528,618,755,484,103,720,541,355,467,478,787,937,241,812,835,148,453,881,774,126,782,884,518,356,981,248,862,177,472,490,194,179,788,663,855,673,728,479,937,890,328,961,91,311,494,25,587,780,924,897,532,749,460,8,857,632,316,271,872,797,99,729,76,585,832,837,838,4,777,300,30,78,656,867,583,57,407,584,442,766,895,420,238,492,552,379,572,399,353,828,763,588,735,331,837,551,855,570,15,700,400,897,800,53,800,860,105,1,616,56,840,279,360,881,322,51,34,810,143,908,482,932,521,535,174,560,208,277,693,95,928,461,747,762,718,635,225,458,617,128,272,463,260,74,531,726,822,622,831,442,410,74,411,459,89,577,969,74,672,930,663,387,973,674,275,791,723,360,238,270,588,401,704,258,575,407,823,406,50,451,566,20,547,237,307,430,331,176,121,682,696,25,379,450,458,28,899,169,627,879,97,84,702,720,820,766,328,198,794,41,970,978,175,847,324,706,885,931,724,124,423,731,15,553,949,79,979,134,926,103,578,97,905,866,443,885,11,984,698,613,689,931,623,390,532,752,456,497,438,363,701,198,900,928,344,688,842,506,946,19,933,650,97,166,439,746,837,697,444,208,346,711,674,198,784,184,159,845,876,87,817,726,301,895,295,810,239,528,531,733,988,941,654,334,9,294,441,194,902,117,969,201,451,589,106,322,482,542,746,391,529,74,858,355,46,530,200,344,955,789,221,131,555,217,275,964,137,204,388,96,121,329,156,488,645,398,23,214,709,875,129,491,668,139,276,678,673,94,764,731,778,196,10,87,3,644,914,500,643,579,508,878,52,830,363,921,839,113,129,710,623,992,97,807,906,592,985,349,872,383,83,351,431,323,391,359,930,967,986,306,796,625,65,379,201,693,135,814,498,358,847,895,906,570,936,826,397,333,62,296,431,960,424,916,47,52,69,164,479,380,496,455,615,750,957,397,293,645,50,469,67,923,552,198,698,698,741,676,831,92,846,775,142,839,268,538,803,695,765,125,263,627,877,119,195,596,480,138,858,596,439,930,922,316,917,751,203,557,26,735,95,549,702,424,479,674,86,978,189,763,34,950,927,895,947,759,83,330,348,651,773,914,494,387,644,66,219,333,87,427,163,279,443,445,189,148,665,866,855,267,417,553,94,423,992,97,737,177,97,858,890,591,23,84,945,621,755,459,536,719,128,992,591,861,91,261,411,717,702,901,488,350,620,526,733,350,364,31,590,971,381,803,419,488,319,131,741,671,756,970,751,675,855,933,133,489,195,268,776,634,871,454,976,605,380,868,472,410,549,277,392,907,893,987,408,739,799,175,752,288,861,39,40,346,963,861,481,800,907,122,455,8,770,153,338,773,13,374,709,839,956,600,429,600,92,276,650,489,804,157,259,655,193,882,169,220,309,887,270,963,648,658,221,396,15,324,725,825,479,418,240,353,110,219,78,229,348,141,223,37,50,312,367,307,885,215,565,658,738,191,136,994,706,299", + "278,413,721,726,0,584,44,514,846,58,260,489,486,66,420,805,805,115,978,230,125,277,219,921,253,211,368,206,811,700,708,271,620,26,885,289,859,190,731,963,186,586,52,700,83,981,733,396,915,102,122,905,891,296,198,736,352,527,836,911,443,87,176,376,531,656,959,381,929,609,312,81,1000,453,659,936,930,252,904,894,70,352,793,354,862,234,644,180,361,702,792,312,448,312,410,924,337,720,907,222,319,153,584,855,512,917,630,916,484,362,926,942,653,37,484,416,381,553,441,433,689,677,393,767,8,904,387,965,540,463,362,112,154,430,25,850,374,206,544,833,198,844,658,692,135,85,377,546,260,736,21,40,309,74,164,250,183,886,464,540,586,85,769,967,781,41,271,412,854,961,528,724,947,269,7,530,363,253,495,230,683,634,851,906,983,610,966,563,165,217,116,528,285,413,431,736,366,235,90,514,739,357,806,963,754,213,427,819,981,661,158,123,21,946,140,526,149,85,254,710,100,317,239,471,217,966,557,263,433,940,597,706,38,330,856,790,509,460,143,434,493,332,536,989,647,96,247,695,888,276,684,916,343,55,767,754,289,190,185,906,463,10,235,374,696,742,176,98,799,394,334,620,956,45,119,527,444,102,62,169,396,806,906,889,931,706,303,468,620,208,428,374,89,572,288,456,506,667,725,392,37,641,545,137,495,653,317,90,734,473,599,566,508,383,727,957,237,607,595,683,954,325,619,544,66,607,614,236,324,201,96,373,275,738,567,516,698,89,387,14,354,780,507,305,462,897,623,397,247,241,442,888,513,754,614,277,764,716,100,162,636,592,792,827,181,620,758,118,311,525,676,765,933,298,257,668,939,971,661,4,853,257,935,245,552,766,465,922,650,824,706,553,75,185,901,342,892,859,356,312,803,982,221,565,799,161,557,185,453,164,931,35,304,724,451,305,491,572,297,716,348,606,789,268,887,224,574,308,86,348,942,839,86,52,523,396,839,841,707,919,348,140,44,526,636,479,5,507,903,582,708,988,190,983,55,243,621,141,25,64,537,171,714,685,820,43,323,800,535,249,92,178,146,125,77,374,432,388,758,158,121,868,961,959,641,370,164,925,454,333,458,739,15,856,35,467,465,404,29,956,215,265,533,307,424,501,166,501,87,268,363,134,415,175,483,103,983,327,45,527,311,248,973,862,683,951,91,681,381,923,869,307,21,469,992,196,617,598,60,70,57,62,893,315,76,635,477,538,938,757,911,414,700,648,266,682,578,597,447,734,570,236,559,417,419,971,269,858,28,151,504,236,19,941,499,760,963,163,332,910,877,116,41,128,146,582,11,573,432,919,207,846,584,704,118,44,731,780,416,806,885,332,663,999,915,174,549,545,430,738,797,127,576,100,980,867,204,620,287,178,803,153,696,80,791,526,923,824,658,602,86,332,104,689,959,217,466,184,313,774,735,829,644,115,935,807,283,48,38,796,924,559,160,206,490,866,432,511,231,445,841,657,468,723,124,940,212,387,855,65,382,504,586,70,704,459,831,492,220,308,770,832,239,828,764,273,149,191,607,382,895,187,513,554,997,630,52,938,264,872,260,187,911,918,541,328,517,743,975,485,967,608,24,647,760,861,226,362,600,681,528,416,971,781,46,230,837,541,235,391,594,274,263,372,648,593,792,626,755,535,235,739,8,808,65,759,13,59,364,50,485,393,960,972,970,967,711,876,786,423,412,254,107,395,785,784,220,876,21,6,904,304,305,809,359,276,533,921,150,496,606,147,111,541,85,646,710,749,708,357,354,33,80,28,356,181,864,889,143,916,455,731,655,620,704,544,462,593,295,507,389,530,650,938,349,42,308,910,587,124,492,893,574,341,652,447,701,258,565,510,804,90,290,221,926,273,147,725,871,507,777,462,209,996,989,491,232,39,221,962,152,667,200,311,195,652,81,95,307,739,685,403,955,525,289,474,172,634,987,30,171,900,638,276,703,265,664,944,563,128,263,453,400,748,515,777,114,893,20,299,530,472,598,381,288,224,610,115,941,795,565,101,837,655,613,991,940,305,438,9,902,863,58,951,266,135,131,44,133,411,77,961,778,84,857,877,378,987,612,313,8,855,543,461,724,511,154,900,464,356,42,972,42,463,353,417,733,999,854,307,510,421,702,158,19,960,930,522,360,459,142,19,826,580,833,483,779,982,61,449,490,271,884,416,9,14,178,92,142,576,113,56,15,400,212,935,668,332,465,78,957,826,559,501,195,588,558,952,887,90", + "84,440,986,976,584,0,109,366,390,794,546,750,18,671,300,198,220,770,609,610,544,818,439,158,84,27,534,980,462,713,488,755,518,552,134,652,299,852,156,676,904,251,841,175,504,116,242,248,794,281,805,595,59,924,109,36,87,931,779,556,782,393,576,675,456,939,788,887,922,858,606,22,943,781,129,203,381,316,445,851,976,223,902,231,910,48,531,336,936,64,421,685,890,581,899,792,947,188,981,373,819,114,983,410,313,752,402,350,142,295,285,2,25,319,458,666,716,671,842,659,288,987,558,590,853,878,812,337,210,805,262,360,209,461,756,97,523,220,821,140,285,367,287,922,213,359,961,319,674,229,245,848,181,394,165,388,319,497,690,797,985,796,96,484,873,694,607,736,713,371,559,476,446,7,431,981,181,64,237,962,445,63,561,882,980,211,458,409,222,559,641,570,185,33,389,435,961,606,170,962,72,777,127,261,532,979,344,263,451,602,48,408,122,297,161,685,422,83,288,284,866,289,828,859,732,853,816,481,776,586,175,168,591,206,784,533,541,381,423,522,148,569,995,386,382,119,123,876,440,695,838,940,338,791,594,427,825,688,535,185,420,307,834,229,508,748,502,745,643,656,122,190,543,340,552,360,441,988,911,846,39,154,10,577,874,447,240,332,512,112,357,714,536,203,95,570,861,815,978,287,31,875,428,246,888,903,710,205,946,117,457,713,368,959,930,361,614,446,575,234,875,264,620,608,952,510,256,966,191,610,786,661,45,108,333,399,371,971,354,102,382,937,739,149,732,597,236,703,633,191,512,569,328,903,32,657,890,789,873,258,187,634,205,397,870,895,344,448,910,415,595,81,977,659,648,742,463,7,65,572,807,967,221,16,131,72,635,394,389,609,382,805,632,55,538,92,696,452,703,891,218,502,645,815,611,696,310,328,129,186,275,164,28,379,136,194,322,483,572,630,357,673,216,738,994,171,174,216,51,175,878,821,883,356,825,69,512,984,694,394,477,145,115,292,971,911,75,372,893,645,46,588,209,681,247,154,105,619,319,272,501,367,219,524,797,253,589,699,340,421,192,999,53,339,250,510,284,43,354,49,389,606,522,695,531,805,144,140,433,396,516,367,764,935,892,78,8,306,72,130,215,210,312,635,595,79,226,990,395,307,630,279,938,203,728,848,258,574,425,63,396,478,171,348,37,64,461,50,753,587,751,573,947,221,624,363,693,442,41,858,767,632,994,759,462,559,678,625,692,897,51,425,119,567,895,664,536,207,162,841,227,760,143,956,426,241,20,569,828,373,843,870,284,246,152,87,106,801,876,249,802,529,722,154,263,891,703,650,872,155,196,749,154,16,648,11,383,482,235,373,648,206,249,417,712,517,492,251,137,559,974,70,306,933,457,864,437,910,834,181,348,372,213,48,903,74,969,145,406,485,253,210,338,36,277,533,632,420,213,53,823,430,75,619,463,196,760,490,338,757,161,64,626,395,717,79,839,274,903,630,282,966,337,290,656,166,637,967,735,177,766,349,119,493,957,388,574,422,513,339,453,676,262,313,924,444,115,895,53,405,463,422,575,2,386,120,896,422,569,189,414,596,996,4,697,939,246,41,657,801,12,28,206,396,835,161,359,70,493,509,365,595,142,234,819,305,924,312,678,123,445,105,454,944,221,249,131,967,433,694,240,856,553,22,91,684,191,882,530,691,712,446,837,726,790,197,263,511,936,938,427,718,186,141,274,981,777,558,152,635,279,862,988,779,683,555,710,68,186,640,200,301,599,320,466,344,123,342,449,638,124,667,105,180,965,56,446,9,568,837,211,865,280,10,144,488,270,187,147,263,664,695,592,990,950,790,235,528,992,108,543,239,161,592,124,348,117,779,827,951,762,679,837,892,640,722,154,730,412,269,81,203,201,59,764,616,170,292,254,306,43,547,950,8,63,73,889,91,873,829,512,3,769,862,225,147,221,373,886,830,290,344,379,174,273,988,561,899,397,739,169,137,866,383,219,304,546,576,342,500,682,873,424,61,156,632,802,549,15,535,981,21,921,188,345,152,612,888,224,529,445,486,727,165,94,23,53,415,16,109,392,569,650,117,589,546,981,572,213,572,239,522,559,932,672,394,734,883,703,758,609,942,128,811,998,103,821,190,73,647,715,315,877,162,417,608,215,671,160,235,332,30,472,905,503,385,772,467,9,739,23,814,719,862,674,138,258,562,714,67,423,220,485,699,427,752,873,174,771,921,89,607,196,535,191,89,761,182,869,282", + "33,450,467,877,44,109,0,352,21,21,261,739,777,16,839,512,876,59,263,709,919,213,354,765,858,223,556,268,898,611,385,74,864,503,490,891,805,551,77,475,499,367,648,899,319,175,223,988,808,296,3,216,197,192,807,627,976,46,264,139,974,339,715,810,819,945,897,607,144,862,835,899,562,391,157,933,691,918,516,169,380,484,378,977,227,914,681,70,970,789,910,187,914,381,999,749,341,828,857,735,438,782,840,517,151,305,449,120,631,278,314,880,642,84,408,693,358,960,799,544,434,865,975,997,6,484,873,206,860,36,171,814,737,834,185,148,472,479,969,463,751,379,202,58,855,233,826,245,408,345,736,303,16,576,212,586,909,532,443,1000,180,352,740,341,215,940,618,140,760,427,228,771,698,371,882,533,728,996,572,242,143,962,133,390,664,786,580,895,212,873,589,171,625,558,770,356,535,784,930,214,210,51,932,163,617,662,588,139,152,417,852,326,445,917,924,798,425,323,297,389,483,151,569,529,292,298,569,270,942,671,785,569,805,232,328,315,966,65,852,726,788,349,169,870,783,324,281,584,278,219,120,909,935,557,541,706,587,419,755,576,642,363,387,228,385,632,2,815,899,790,587,494,813,65,477,543,874,356,33,518,998,110,306,25,965,769,226,909,535,597,878,101,87,32,404,194,555,544,597,886,282,890,215,973,211,751,527,769,887,873,704,803,864,296,609,396,229,670,895,222,739,438,40,256,939,377,256,512,335,850,182,404,680,529,297,362,801,53,607,385,80,880,586,930,860,162,509,899,464,917,31,743,275,381,874,906,921,596,405,75,522,322,838,198,354,885,657,580,519,588,224,156,745,834,34,768,258,68,722,727,255,819,521,605,886,353,937,657,340,105,332,240,945,437,260,398,945,948,762,39,474,897,604,11,965,945,709,705,151,240,772,682,688,692,676,177,308,504,586,118,109,445,610,344,751,510,120,104,959,131,925,680,736,812,763,985,268,815,64,714,482,886,439,496,496,11,736,304,833,818,393,83,161,51,62,419,496,372,810,953,368,171,439,698,939,370,711,482,106,925,562,341,529,829,260,941,279,925,327,901,56,528,113,289,780,181,460,640,557,566,9,235,410,959,527,370,646,257,43,710,408,205,74,150,496,805,363,333,577,154,471,906,921,504,752,302,415,329,592,628,305,919,521,285,545,342,934,653,696,267,167,699,775,723,274,910,535,893,644,818,917,306,400,694,43,679,826,866,837,311,263,568,957,63,260,523,834,747,627,863,691,192,189,555,88,41,663,150,13,367,747,765,810,952,697,811,909,895,375,608,664,496,128,100,210,631,702,553,779,629,532,989,160,198,455,258,144,518,979,486,159,89,91,168,178,429,621,286,95,574,949,493,175,153,273,73,276,353,224,468,914,910,885,11,85,168,3,38,823,572,915,41,817,812,61,730,597,543,601,31,163,389,26,543,593,847,648,138,134,430,266,439,858,20,186,967,710,264,802,265,317,325,453,549,104,412,156,54,103,668,113,700,736,399,458,984,689,85,738,357,148,343,992,903,916,982,428,271,947,383,605,606,553,287,511,891,537,243,101,532,262,223,948,859,463,91,700,195,364,942,891,411,202,954,444,548,581,988,562,116,400,21,111,369,898,20,653,498,915,933,398,893,140,264,674,221,426,628,639,467,614,480,89,777,903,861,457,133,711,487,708,677,428,159,468,675,927,897,216,734,162,769,996,168,859,901,93,630,989,343,85,575,415,907,24,35,537,311,783,799,657,11,792,52,935,669,542,311,687,757,47,551,106,87,70,111,628,694,514,117,617,239,425,839,960,52,415,810,85,178,937,760,98,193,574,301,863,431,611,1,193,832,447,18,333,493,773,40,129,638,642,914,908,880,163,240,558,485,621,217,825,76,898,172,816,165,36,51,509,123,198,645,880,628,331,591,964,91,823,41,843,605,449,123,361,833,977,39,382,466,605,22,574,750,443,385,172,167,470,539,881,2,760,855,126,747,839,402,158,193,933,445,478,20,311,54,448,144,272,144,895,336,630,716,119,529,869,350,462,867,382,686,65,561,989,337,754,901,348,599,209,545,229,847,542,484,350,678,98,302,503,792,528,681,137,733,843,101,754,678,573,221,962,393,64,522,277,372,660,484,5,758,35,707,982,780,937,125,775,48,912,516,36,409,138,140,70,5,354,319,351,811,989,151,615,276,357,364,656,256,629,151,36,31,529,864,676,620,901,788,450,981,210,594,198,834,984,953,356,615", + "758,189,509,679,514,366,352,0,16,948,324,345,508,350,958,671,191,112,473,406,520,758,86,333,694,407,370,771,674,426,505,434,727,207,989,692,965,677,716,680,907,936,958,437,991,17,26,520,62,551,559,991,725,857,542,434,948,381,285,492,768,785,292,660,971,74,410,654,894,494,772,171,721,50,30,345,332,991,807,406,79,962,361,385,671,639,703,192,930,605,515,398,40,15,193,759,461,212,870,888,208,809,105,879,722,693,840,129,647,159,759,668,390,542,938,186,921,931,876,323,98,161,612,366,943,400,117,683,948,673,784,636,61,936,794,170,167,509,986,13,375,779,478,393,292,552,119,960,292,334,973,949,25,417,447,821,398,782,166,274,576,392,929,16,621,938,983,853,129,116,868,436,86,47,806,981,197,160,320,323,721,619,998,763,152,4,591,731,795,633,419,666,491,146,905,454,658,97,210,591,875,959,158,278,218,106,749,847,63,667,580,959,648,234,62,275,765,225,714,273,324,532,228,819,588,784,99,727,574,839,948,234,389,326,594,396,467,750,366,713,4,265,870,415,442,696,720,732,153,578,286,636,400,68,607,755,853,301,494,359,193,11,664,49,972,444,933,753,543,631,801,419,164,442,419,916,736,57,504,204,868,692,404,680,681,544,553,215,835,276,581,167,624,183,953,552,245,760,305,58,657,230,43,759,770,252,321,126,333,939,937,281,864,383,720,204,137,198,413,911,21,306,600,683,155,219,280,959,67,655,926,355,280,663,80,404,474,647,558,732,377,821,462,46,327,46,1000,936,412,585,804,956,239,61,384,489,226,356,638,990,527,670,763,73,270,807,180,821,786,832,877,433,468,532,438,276,544,53,47,372,257,43,765,652,81,518,314,145,923,466,908,757,846,365,626,919,875,274,927,242,716,829,145,68,911,884,352,766,704,419,589,351,5,560,146,226,139,8,984,354,384,369,149,993,511,918,356,447,999,173,125,654,494,491,878,548,653,600,912,977,584,199,75,817,60,55,644,75,828,940,472,291,410,912,479,684,837,639,560,723,704,300,499,717,614,535,190,302,770,874,740,459,430,217,242,923,541,619,92,105,976,429,685,303,453,302,219,812,514,256,41,821,398,717,885,940,801,971,791,181,38,460,713,75,367,249,36,64,734,534,8,291,254,471,879,91,435,325,501,301,586,186,747,745,731,715,762,349,608,775,367,320,980,478,217,344,820,636,555,611,932,505,746,334,864,711,840,680,945,8,478,40,823,823,141,401,352,426,905,647,757,950,351,926,400,169,612,600,322,451,321,604,201,733,147,459,106,271,562,518,443,953,990,485,380,723,618,987,457,97,926,439,14,653,477,548,290,458,762,361,102,840,516,904,344,158,27,158,786,24,876,311,54,227,577,339,537,115,226,983,481,672,120,18,750,538,756,455,860,98,431,416,524,629,405,827,836,795,122,296,953,103,928,855,883,117,45,955,882,877,718,174,536,461,461,776,643,762,383,575,503,143,421,152,508,839,769,581,627,340,686,690,248,880,878,492,914,889,901,657,257,545,813,949,616,465,710,828,209,539,227,662,925,69,78,795,821,888,297,479,612,716,409,362,543,452,994,374,961,932,299,864,24,646,476,717,856,871,194,530,145,879,578,52,733,158,218,976,574,134,895,452,801,450,650,953,13,720,726,657,950,637,591,669,814,827,582,892,200,473,946,765,598,555,503,111,45,553,782,755,233,493,939,716,583,922,471,365,919,736,251,655,422,606,133,710,763,302,548,843,55,568,560,640,778,249,485,294,495,598,224,178,939,526,442,371,532,871,618,852,992,84,430,937,566,711,801,425,70,50,711,828,727,395,233,692,640,934,642,14,455,254,998,1,755,565,161,400,423,114,114,875,963,88,645,482,717,975,320,42,761,595,12,256,972,462,173,377,969,277,295,103,708,292,231,356,780,5,718,752,608,417,928,129,191,462,625,216,200,968,875,425,519,939,924,447,356,988,725,461,17,361,52,857,637,424,587,424,820,616,400,126,331,229,968,225,537,182,852,159,225,774,929,482,146,103,346,260,114,131,981,380,927,238,594,5,9,877,943,539,538,76,257,554,170,815,886,334,878,421,543,234,231,687,732,578,132,379,23,637,106,478,763,842,479,185,97,907,373,969,19,346,504,455,941,844,857,9,792,736,13,397,207,848,49,962,893,761,467,112,70,763,222,757,970,825,24,737,670,493,191,806,119,118,591,153,787,944,919,638,579,758,75,191,543,926,692,111,754,299", + "908,382,781,555,846,390,21,16,0,495,554,294,295,629,687,230,555,311,18,358,529,427,183,32,412,279,915,63,722,811,624,517,195,57,654,14,815,500,464,742,842,641,923,117,654,955,690,491,962,786,155,695,926,374,383,406,957,187,738,930,945,404,533,218,244,681,924,640,849,880,78,395,920,72,272,622,583,278,571,10,211,329,173,393,793,509,839,152,287,549,202,741,557,931,904,155,418,527,881,546,216,551,185,918,485,259,73,953,402,701,729,299,354,681,251,359,99,179,420,502,390,842,589,332,80,446,572,19,331,830,440,585,514,601,150,845,943,520,438,947,309,441,43,680,725,146,201,407,364,388,855,747,933,882,213,828,769,181,777,96,443,927,478,364,290,121,831,447,54,76,45,195,375,94,57,589,889,119,143,613,371,209,57,89,326,539,207,631,658,639,993,433,715,489,956,860,812,165,634,688,682,306,567,447,804,698,943,273,255,287,147,195,163,166,594,671,903,873,660,948,695,589,81,54,718,408,135,697,926,581,527,309,884,887,512,715,381,960,181,236,39,358,579,427,377,734,814,621,370,279,218,107,442,525,533,416,212,222,225,349,213,352,213,784,397,824,381,38,642,764,616,286,278,43,471,258,732,57,651,810,559,307,586,80,625,815,379,492,101,148,593,329,630,646,343,509,647,892,134,194,988,370,770,145,941,910,526,70,937,608,253,730,227,983,527,889,952,220,890,762,86,788,359,82,499,954,120,843,213,731,440,107,909,448,105,167,971,462,604,806,910,349,365,911,363,539,768,415,102,508,501,509,624,812,288,262,73,464,930,953,798,736,960,740,835,891,268,438,611,174,520,824,452,884,179,255,894,19,553,936,616,104,673,92,234,454,653,442,939,476,470,249,130,772,156,414,695,314,152,662,621,132,970,341,732,562,314,607,845,84,235,645,375,135,284,242,533,184,334,573,70,659,922,577,634,401,917,341,552,404,197,67,713,260,556,943,617,164,336,723,740,579,975,13,488,468,882,55,957,676,962,686,734,491,108,990,355,658,204,597,733,88,994,188,879,432,637,23,527,699,195,214,941,756,230,726,559,17,113,670,354,685,345,20,78,248,12,455,171,23,770,940,972,368,53,785,928,700,666,684,803,738,861,263,3,893,121,402,932,644,444,352,652,525,215,90,757,863,604,762,915,527,478,960,288,649,899,269,961,876,862,100,417,548,423,462,298,834,146,935,674,536,660,640,843,880,180,466,994,894,12,388,51,106,569,90,572,66,622,101,335,319,528,878,751,825,756,957,821,500,192,755,582,653,834,552,272,661,312,470,488,109,516,770,281,224,746,734,822,298,854,620,471,312,524,830,339,453,510,86,936,575,882,18,572,901,252,131,135,146,616,445,725,318,562,571,801,724,916,513,758,766,894,541,793,542,433,208,479,441,256,947,998,357,184,771,130,663,498,536,855,230,680,931,594,105,617,359,169,649,80,20,285,548,725,454,985,321,248,40,661,717,626,203,709,679,367,492,964,544,852,961,608,115,242,783,664,917,134,698,672,173,629,359,506,410,86,648,22,560,793,857,260,703,849,295,308,739,534,559,298,623,816,200,793,514,228,687,745,575,547,772,980,640,105,778,623,946,247,967,406,206,370,568,80,790,262,773,330,839,508,660,484,209,615,649,202,330,118,847,346,913,649,780,750,454,705,780,998,761,392,96,468,305,384,698,777,635,548,783,382,713,672,75,73,597,599,951,499,649,928,252,127,872,913,713,304,195,235,708,176,495,552,809,188,428,171,804,703,346,613,160,124,98,222,934,211,423,177,423,250,523,750,186,537,209,209,175,10,997,640,328,917,698,909,565,837,908,967,83,800,125,901,958,632,998,959,632,45,673,814,924,838,324,994,837,758,915,236,970,350,420,309,790,497,496,291,830,948,226,136,903,924,464,66,249,132,882,320,215,351,191,265,690,28,363,463,671,973,836,330,595,127,270,968,972,718,188,214,425,585,437,249,164,304,867,500,212,69,839,938,689,883,837,411,608,866,638,464,297,72,375,203,869,838,115,343,492,122,14,815,258,606,127,39,868,750,36,308,603,933,296,878,683,909,928,555,662,809,410,121,478,514,791,436,918,397,907,156,422,988,279,705,775,980,820,673,505,679,351,31,667,103,362,311,27,906,601,928,266,228,148,260,199,11,219,609,973,647,418,155,998,535,751,757,991,418,474,396,202,326,726,45,190,658,609,912,157,875,272,354,480,128,192,279,878,552,249,407,823", + "420,388,544,918,58,794,21,948,495,0,906,650,437,53,933,817,60,131,55,582,893,880,829,213,669,73,736,131,573,120,403,566,346,932,878,9,187,198,621,731,396,65,529,612,196,130,591,875,15,187,802,769,214,671,331,611,474,305,521,745,991,195,227,791,853,739,158,898,390,180,403,79,812,252,187,260,706,2,142,852,582,265,22,190,134,824,608,952,465,637,875,648,756,91,38,732,141,802,664,824,107,364,957,216,205,78,98,510,295,359,166,476,23,533,618,951,242,228,42,758,301,431,961,245,778,830,396,406,618,552,777,542,287,627,859,457,90,342,314,568,326,952,541,216,593,909,164,816,460,891,999,294,884,228,991,978,487,168,649,868,100,979,942,304,625,552,300,340,275,986,223,626,801,650,714,197,186,558,811,755,44,622,15,820,55,960,518,850,870,876,109,984,273,167,528,279,578,338,938,996,663,465,603,70,140,509,83,122,85,655,328,177,197,911,890,562,659,736,183,903,747,944,880,324,820,773,395,676,435,637,505,729,232,145,282,353,322,285,771,498,64,112,157,333,211,631,751,496,404,917,846,328,238,740,853,596,377,188,313,234,928,472,832,69,551,786,359,763,50,85,365,77,821,660,782,662,468,724,52,110,936,392,778,750,872,407,562,867,951,404,277,454,202,514,458,514,958,770,505,709,114,212,20,463,105,113,674,566,6,540,134,164,106,200,639,839,382,227,91,934,918,362,35,509,326,231,284,753,833,627,620,407,116,261,421,775,292,441,923,764,249,734,52,37,886,981,178,845,796,670,917,277,905,449,777,206,819,542,236,609,518,117,1,202,725,710,812,678,179,352,713,136,383,896,582,749,340,979,70,588,389,826,430,288,898,467,637,462,179,299,471,503,301,433,701,553,759,861,224,387,451,624,833,83,911,305,280,247,796,112,742,398,55,211,326,388,669,331,536,181,330,645,935,158,519,881,517,629,451,427,619,771,557,523,353,20,368,699,795,229,873,787,984,501,554,308,765,21,90,896,523,627,549,854,544,896,12,168,159,342,133,800,164,413,634,517,524,198,33,193,514,909,285,608,755,137,931,425,410,805,829,990,72,191,607,492,910,410,432,339,627,935,499,73,507,421,693,258,899,381,276,995,86,969,802,410,411,77,203,991,625,843,538,103,736,200,601,453,834,216,490,821,323,760,607,431,439,767,210,165,664,770,60,884,394,127,512,403,270,641,497,654,658,987,812,875,528,948,782,713,878,184,588,193,129,681,980,786,667,71,666,663,909,411,221,23,829,125,549,323,190,433,957,530,270,933,601,243,429,208,877,786,323,11,234,71,861,757,141,25,239,670,315,445,578,607,104,109,824,523,462,792,39,937,991,103,134,271,408,120,672,327,455,770,134,842,329,994,902,899,116,90,543,821,211,649,562,588,773,349,388,245,748,385,339,940,8,126,996,242,984,718,795,346,773,259,546,564,265,928,365,612,390,795,687,931,179,767,518,997,477,624,616,270,448,468,496,102,330,547,550,336,70,555,305,595,628,115,522,184,166,873,566,122,490,64,682,794,925,557,305,609,812,675,201,556,970,541,530,354,509,949,266,468,392,393,567,383,978,81,927,817,162,598,792,79,736,77,212,598,555,805,173,312,377,278,78,33,570,440,609,216,533,183,313,400,726,851,599,931,269,213,940,984,133,838,320,835,760,288,775,52,170,422,830,998,692,788,113,410,24,303,616,926,951,760,904,408,508,516,547,458,473,702,850,807,79,891,683,448,559,195,184,424,857,108,226,359,900,558,474,496,244,437,596,295,730,969,926,313,755,791,579,967,855,424,872,918,643,808,577,723,31,871,427,86,145,468,338,593,796,498,512,923,500,865,303,486,87,321,859,363,180,204,535,931,77,981,545,875,941,959,367,842,474,385,76,171,494,751,248,596,509,678,420,213,168,606,39,836,27,625,777,4,392,337,711,157,976,138,658,146,177,817,204,801,600,145,904,365,76,895,886,907,254,354,219,744,842,205,307,277,245,495,265,251,849,29,632,823,196,477,122,35,504,698,724,445,628,746,987,528,315,531,374,428,942,806,533,646,167,626,436,213,460,34,753,14,142,362,412,882,727,698,390,713,588,773,621,626,560,90,954,781,841,49,876,372,873,354,78,52,980,212,943,275,307,559,378,854,294,998,990,145,654,829,815,627,578,142,921,255,946,86,61,457,18,142,18,54,808,306,550,691,122,143,837,306,561,793,838,805,229,418,373,295,501,346,12,509", + "610,460,43,259,260,546,261,324,554,906,0,354,773,953,227,795,438,900,794,598,528,234,86,872,523,742,913,352,841,518,392,982,264,47,325,816,178,620,786,202,218,529,921,751,224,543,129,72,529,848,167,509,840,471,851,544,945,328,797,300,43,899,845,307,420,634,460,995,662,779,939,880,64,655,936,602,814,436,545,729,248,617,917,301,305,250,368,491,354,760,119,984,940,302,476,19,145,863,675,876,400,435,56,906,480,543,342,408,906,639,211,571,731,354,484,964,466,734,815,262,678,553,703,270,455,894,302,697,499,126,746,585,828,929,102,782,766,478,295,512,484,542,210,58,727,292,704,596,371,828,238,415,730,183,660,372,459,530,857,541,450,302,879,922,274,836,203,712,257,866,581,518,280,188,924,223,425,619,149,349,797,664,629,295,188,39,786,204,897,506,84,563,739,84,710,906,691,848,873,689,547,480,769,287,418,185,62,9,606,582,451,450,475,717,851,373,989,311,731,911,300,882,402,442,805,102,764,89,91,847,808,110,311,977,927,702,260,517,71,656,487,158,191,280,797,416,64,286,23,26,751,700,179,956,955,732,322,865,592,89,131,242,656,763,26,494,927,990,85,958,282,810,146,859,375,634,189,387,557,56,324,285,579,696,111,693,55,214,439,339,329,789,270,472,485,373,67,4,98,868,871,926,70,757,489,240,180,719,210,32,484,403,29,679,450,658,80,891,54,654,653,725,385,85,119,952,38,817,466,633,222,661,480,560,181,364,52,213,503,431,117,206,295,637,815,756,216,965,396,748,843,896,953,608,7,311,690,903,664,116,340,956,819,17,26,846,453,259,905,635,185,368,174,505,573,423,922,923,425,339,481,426,487,26,374,839,319,795,63,663,21,433,777,702,414,112,381,396,791,10,780,563,851,835,224,150,552,634,864,437,954,164,398,629,624,388,530,579,497,945,746,770,922,945,364,507,932,164,869,183,839,943,467,271,948,753,334,585,97,238,555,486,813,567,603,219,116,700,81,797,552,261,428,759,522,373,608,847,401,199,675,723,134,382,672,915,721,762,488,497,103,69,325,282,550,907,718,851,888,424,482,735,637,656,43,281,529,839,90,670,442,842,65,520,320,513,663,396,949,767,15,366,975,497,685,160,766,906,475,725,906,948,145,128,281,19,434,451,809,35,439,684,251,242,84,503,513,511,728,502,794,618,915,205,675,682,134,82,307,695,390,385,848,126,265,341,492,686,760,525,118,32,35,990,752,752,690,13,746,626,492,320,526,666,551,158,72,20,631,751,43,417,60,954,53,106,133,261,812,379,808,600,452,899,75,474,766,606,792,879,499,599,627,991,450,83,236,868,375,52,19,495,503,458,400,841,679,147,416,610,890,648,28,474,394,51,926,197,56,960,330,228,556,994,211,800,573,260,853,513,520,746,711,548,552,964,395,132,444,154,203,567,907,724,602,150,442,336,278,813,709,766,238,895,704,728,335,867,393,99,942,926,591,929,344,523,601,363,284,636,445,850,798,516,465,159,259,551,656,849,903,467,175,883,697,274,306,415,728,344,806,398,342,750,525,24,147,834,174,439,238,478,142,983,25,864,757,810,295,91,113,812,506,526,282,817,237,607,367,984,399,973,458,931,500,355,119,801,781,571,800,623,681,54,818,365,675,20,981,762,557,244,362,998,915,243,509,381,237,662,818,814,156,923,657,900,533,32,46,190,617,775,959,627,376,440,289,173,646,976,201,856,567,104,40,914,983,394,939,358,665,474,512,946,936,313,897,450,881,979,117,506,954,861,94,395,893,280,764,231,276,637,655,275,789,636,585,570,294,174,692,54,25,298,54,905,895,926,348,189,611,442,995,338,133,900,990,133,261,770,834,318,217,435,235,185,571,798,510,469,926,77,100,214,518,657,476,484,39,39,172,880,209,135,762,351,375,856,300,833,588,591,563,882,661,74,875,788,86,753,760,749,549,657,207,400,129,268,58,512,281,953,539,603,697,982,271,78,908,673,214,78,727,962,605,789,421,430,856,663,139,334,548,278,401,840,641,195,596,242,530,557,196,480,301,528,438,492,381,352,737,160,374,154,921,531,412,878,387,444,129,307,921,414,131,509,360,626,436,947,928,717,749,468,259,366,427,458,908,297,67,492,983,411,6,276,275,818,268,916,845,821,164,599,798,484,124,467,240,778,232,867,289,135,410,958,52,975,168,642,60,578,705,41,560,54,774,940,501,457,773,153,171,405,94,105,113,50,632,738", + "484,802,803,522,489,750,739,345,294,650,354,0,879,269,568,43,905,661,885,938,831,68,641,935,878,424,774,63,352,484,122,756,55,875,305,105,785,232,574,24,310,982,609,630,633,802,420,952,8,600,243,323,748,412,46,140,483,755,879,204,434,514,32,906,660,831,705,293,929,793,341,215,442,575,543,913,296,33,61,1,675,259,733,932,89,250,531,728,444,924,356,253,864,245,829,293,562,126,657,764,376,26,326,613,405,70,267,388,239,405,991,507,952,270,279,784,547,601,9,771,828,645,421,60,617,643,832,489,455,24,754,444,321,709,110,178,788,787,271,923,880,858,213,818,463,238,241,242,389,35,682,165,872,22,102,508,436,251,254,252,363,874,2,925,635,866,371,982,618,354,97,473,293,594,643,262,253,479,868,250,430,681,359,356,818,66,626,323,817,498,670,61,545,837,327,532,772,557,269,374,38,735,954,340,158,99,414,601,618,473,248,789,754,567,381,793,563,852,151,66,537,192,881,421,920,487,354,240,58,859,61,174,385,73,644,570,154,570,199,136,920,70,917,712,603,907,475,901,368,40,288,313,235,770,101,496,492,7,867,627,968,424,60,541,306,792,486,824,923,926,644,497,194,335,471,855,326,189,369,357,598,119,848,553,387,339,136,543,111,352,659,347,542,180,502,606,996,320,414,974,388,625,396,256,863,479,711,522,356,627,729,668,458,74,245,311,369,780,68,689,124,95,512,100,672,142,650,243,104,153,296,149,680,654,304,88,529,72,214,49,866,885,244,411,123,105,565,701,256,382,804,444,503,406,877,729,542,11,212,86,766,903,311,204,340,354,518,180,854,131,904,615,956,834,153,54,142,423,861,961,231,126,765,160,710,299,41,656,592,432,82,387,69,699,697,143,935,143,736,872,11,716,975,987,366,742,145,838,686,651,383,400,185,859,801,740,171,975,7,124,402,916,231,750,195,347,194,552,823,598,251,666,440,747,400,724,922,24,760,925,511,448,858,429,305,249,866,917,643,376,830,70,754,951,305,431,209,352,947,541,28,442,306,207,631,274,337,130,265,246,287,983,457,568,370,266,152,738,824,383,670,201,572,667,809,265,732,313,38,963,361,431,537,418,275,295,836,466,365,567,396,949,529,181,303,627,738,486,281,897,858,566,569,834,860,576,244,613,746,887,759,772,712,463,781,529,397,242,302,445,175,155,588,718,803,615,292,686,184,896,213,558,157,171,583,437,629,184,445,787,697,248,440,908,327,558,310,806,334,809,494,601,503,797,247,352,651,104,462,920,821,839,926,871,482,172,571,164,85,333,983,343,591,287,3,652,167,283,156,374,976,598,920,966,35,52,324,884,702,264,995,898,149,493,454,50,697,117,151,868,292,618,642,566,973,932,51,782,355,771,275,409,723,183,481,579,966,600,165,876,667,42,450,643,538,230,391,306,929,350,778,677,102,220,511,303,585,5,109,189,859,250,387,921,982,251,547,555,617,146,817,541,32,541,397,839,568,900,639,80,617,774,145,633,261,825,625,821,166,802,766,320,330,449,197,832,226,377,350,273,446,272,335,883,706,231,75,580,380,835,735,161,453,545,345,438,308,381,80,395,927,41,683,528,505,867,235,284,172,379,571,461,19,506,892,978,606,285,534,717,737,217,264,74,141,954,99,559,36,988,550,603,81,497,495,342,392,329,404,424,309,3,330,828,434,537,392,273,789,263,151,513,605,336,329,6,28,906,258,75,806,145,735,959,754,481,890,916,648,678,152,116,432,497,580,301,105,922,128,194,728,440,897,278,3,84,166,566,850,713,735,63,627,516,19,975,336,147,654,895,748,3,638,648,498,718,101,546,786,801,156,10,413,132,164,923,252,132,857,122,400,608,818,644,319,198,81,473,56,306,981,500,394,805,824,490,40,236,571,662,880,304,279,701,113,834,394,319,251,534,247,725,882,884,828,378,531,869,884,873,211,401,280,705,815,644,923,221,642,128,162,500,830,294,348,910,203,898,456,327,138,492,723,592,401,786,357,428,883,66,282,832,563,204,155,662,450,248,775,649,51,205,640,87,729,538,295,166,363,996,788,301,947,6,945,40,611,907,214,218,853,895,692,351,771,494,19,454,916,655,317,992,874,73,547,295,776,975,291,52,57,991,281,359,819,288,43,808,69,693,208,488,705,406,56,663,598,72,349,515,869,299,293,167,960,56,78,930,685,562,654,736,739,978,526,481,88,493,422,604,806,624,840,598,59,286,889,744,711,437", + "195,266,544,153,486,18,777,508,295,437,773,879,0,171,471,291,787,106,859,102,784,760,146,473,131,720,555,110,194,684,590,158,346,780,667,911,951,198,340,54,504,549,491,280,220,347,268,486,9,299,597,386,352,938,893,767,400,262,637,281,979,87,554,476,847,195,19,3,745,892,732,862,901,991,990,135,976,17,242,402,856,4,260,205,751,300,780,861,242,36,508,58,527,966,612,88,946,542,398,439,223,254,44,520,883,533,793,287,467,423,118,227,758,547,842,612,906,609,671,520,52,952,506,658,506,736,465,73,739,56,52,258,590,651,441,968,711,451,283,906,890,172,416,632,677,774,433,108,677,398,220,984,888,47,459,716,683,93,360,919,697,416,372,851,248,911,958,927,471,818,648,640,460,869,473,588,539,484,126,75,351,749,262,897,271,671,168,21,927,892,512,908,721,508,346,279,119,263,7,105,905,122,454,331,189,635,672,219,199,360,362,368,711,736,232,33,812,149,232,900,183,916,943,257,953,108,750,326,454,652,382,618,136,870,184,920,194,204,774,47,642,203,113,199,514,789,31,26,708,46,854,492,577,582,701,357,398,928,755,604,890,723,30,404,154,321,978,583,520,677,503,325,244,18,482,447,694,887,529,930,618,981,790,196,925,714,441,208,772,568,673,629,299,960,54,528,520,413,911,314,543,205,128,227,287,795,386,817,471,779,151,867,632,514,667,356,151,152,320,631,943,801,687,314,692,872,406,647,143,726,114,183,905,195,554,923,626,181,558,300,429,354,760,809,272,102,948,52,325,171,426,986,253,884,52,651,725,460,707,654,316,922,996,342,585,843,895,8,291,654,58,99,536,353,44,999,944,470,197,564,525,137,683,450,148,161,608,698,61,758,209,726,580,698,668,37,820,215,276,651,161,914,587,155,479,670,998,468,167,486,40,974,795,968,514,310,426,439,872,339,781,979,282,376,438,168,75,439,314,507,184,117,90,153,956,392,710,193,713,359,76,713,275,946,214,615,806,995,342,454,80,419,980,771,985,972,855,710,948,213,896,515,692,364,527,415,155,801,586,939,529,88,612,731,246,649,829,917,937,302,998,954,290,304,473,492,733,921,274,280,796,541,402,456,110,256,983,678,392,730,542,569,286,795,596,11,713,601,402,589,23,810,440,126,430,20,858,964,379,2,471,786,759,810,104,222,127,521,897,426,222,366,49,177,177,907,649,653,881,894,930,890,128,196,55,870,167,669,509,715,482,891,536,934,483,749,466,521,745,358,538,815,396,147,807,230,875,996,189,557,149,112,359,521,701,214,503,807,865,752,386,397,293,268,339,351,891,977,536,253,610,620,748,379,66,570,141,53,681,855,506,410,781,464,463,979,729,968,492,669,538,190,97,262,598,657,916,147,669,256,318,105,214,174,381,730,542,115,406,813,47,270,677,964,549,884,412,750,109,136,21,896,200,46,535,366,258,858,980,761,407,951,425,622,532,50,64,974,735,311,448,227,920,685,194,467,603,838,672,776,937,989,62,850,262,788,364,290,783,528,473,497,432,853,146,909,192,965,357,529,630,68,436,958,242,54,873,539,740,864,938,301,983,294,118,223,174,333,213,338,419,732,897,416,890,754,151,616,581,561,259,653,951,485,469,195,814,112,512,280,94,470,748,787,839,117,404,231,260,465,128,517,464,783,577,739,675,748,729,364,625,568,575,473,671,924,279,950,482,725,747,700,732,1,511,369,346,444,695,742,365,121,332,343,245,609,918,317,355,222,572,437,188,745,371,737,506,32,54,73,780,712,560,532,510,773,695,695,391,891,325,714,929,520,219,296,231,919,943,860,999,258,119,88,845,319,63,235,23,648,965,903,155,799,844,513,388,187,724,928,953,555,453,604,205,397,864,356,718,444,102,396,154,855,947,907,725,980,23,955,200,875,95,449,806,349,129,921,428,881,201,718,895,656,742,29,921,30,4,724,250,425,192,926,488,301,306,145,527,132,952,584,433,735,348,497,743,258,797,644,52,94,398,708,364,646,258,15,791,33,461,487,94,376,402,68,678,199,26,560,946,370,722,527,133,821,546,213,957,708,726,74,441,833,296,69,896,595,33,880,3,625,933,433,430,876,921,391,252,588,244,160,152,358,759,727,755,850,676,4,250,921,413,590,278,862,529,983,315,457,644,403,974,667,413,189,503,755,875,903,779,213,598,981,11,937,993,523,679,479,753,19,248,616,758,112,687,903,380,224,259,908,843,909,500,311,890,142,346,999", + "474,415,354,491,66,671,16,350,629,53,953,269,171,0,370,567,309,812,670,925,317,695,660,548,423,717,659,520,184,281,506,575,658,880,711,541,122,654,833,38,195,850,264,354,217,256,39,184,807,183,471,522,274,155,496,90,624,931,714,44,118,891,255,22,446,569,488,980,299,928,550,209,256,703,953,165,935,415,478,737,450,369,683,385,492,491,299,906,31,551,157,957,995,608,806,928,415,414,584,674,887,262,776,668,872,272,736,764,135,252,749,734,961,373,784,490,33,703,725,50,816,160,609,225,428,208,796,654,70,363,657,29,630,903,90,529,456,379,560,32,748,629,629,795,890,766,557,208,680,979,556,753,93,468,788,141,686,944,305,220,724,198,262,741,86,238,844,624,344,283,813,60,483,650,935,200,613,321,737,389,657,292,152,794,800,60,22,392,784,791,25,517,115,576,414,831,724,381,143,143,498,710,458,409,623,637,56,732,322,616,476,823,651,177,177,963,532,708,58,356,615,888,120,815,324,718,333,44,996,809,145,441,106,40,451,445,450,204,698,356,912,827,438,785,49,268,600,613,827,643,647,267,626,616,561,860,764,38,459,285,35,225,932,474,511,864,284,321,385,469,244,767,950,123,635,871,405,57,596,930,517,297,949,388,28,235,526,902,135,336,105,708,119,844,440,306,102,914,858,564,738,819,886,318,218,173,317,512,504,111,840,105,424,424,340,847,438,403,74,124,609,54,846,348,389,134,686,913,262,21,141,764,28,221,963,203,50,354,646,924,388,955,933,773,856,796,209,839,188,679,662,768,161,566,554,647,267,532,122,992,263,149,387,670,554,98,736,617,550,693,1000,768,159,673,292,163,117,157,893,890,558,844,217,152,464,967,55,64,537,840,224,791,530,709,18,274,298,227,504,799,684,824,204,114,723,863,320,934,53,455,505,933,643,159,360,731,251,782,210,339,645,921,179,314,363,959,641,231,604,131,973,433,927,515,741,195,680,902,547,98,616,616,622,750,982,754,830,347,307,907,272,5,844,213,812,192,958,659,136,665,156,522,97,160,951,395,629,62,957,688,78,299,668,803,426,934,877,743,344,918,895,12,409,851,271,295,650,790,368,859,246,106,15,694,233,331,590,181,694,329,414,959,801,128,170,390,227,191,157,208,708,670,742,219,755,156,252,403,367,968,97,18,933,516,203,475,112,211,518,484,331,633,920,226,766,981,422,821,494,408,776,625,24,845,930,893,992,331,267,642,104,444,89,46,416,589,278,230,113,281,107,962,560,815,936,460,313,990,157,398,678,602,814,881,427,237,741,270,825,790,74,222,12,29,505,311,333,503,347,230,480,188,347,631,44,521,785,376,694,912,179,624,802,145,808,991,427,645,400,702,111,132,856,149,449,658,151,542,523,243,382,144,975,109,919,467,435,826,730,142,796,991,32,413,552,785,121,952,932,600,147,945,380,128,334,866,16,356,25,366,431,587,677,11,138,258,135,354,388,167,186,929,55,408,256,194,869,16,734,12,131,794,153,315,454,770,441,791,347,6,958,627,293,17,672,771,159,788,111,342,820,704,353,995,512,82,226,686,79,511,76,183,115,514,844,964,230,914,592,671,196,794,297,911,208,496,483,695,399,6,127,936,767,509,459,894,986,87,578,674,972,675,589,526,831,542,226,561,954,499,269,969,163,133,937,939,488,37,929,259,598,775,991,797,321,247,332,302,927,556,960,264,756,769,472,270,248,216,402,197,460,468,144,404,77,729,585,36,546,154,983,58,329,522,833,822,184,255,433,301,573,341,731,379,997,865,153,161,43,573,924,692,17,737,563,943,830,587,55,334,762,122,419,574,719,479,422,194,395,369,591,510,564,542,66,18,62,904,989,475,495,47,885,878,650,296,490,435,620,841,921,297,155,590,925,870,788,161,549,951,204,545,205,199,95,833,448,773,327,973,853,399,179,252,271,181,589,671,295,600,152,838,929,369,942,140,231,550,846,582,279,830,942,927,767,138,775,731,616,459,752,168,978,489,891,601,525,991,862,112,577,958,338,19,132,554,279,710,565,339,286,429,350,486,594,73,25,987,161,99,680,773,809,901,116,93,356,155,936,168,191,450,467,490,32,609,968,247,891,331,897,939,414,548,918,936,159,70,312,721,883,62,997,28,187,817,778,28,694,819,677,115,499,498,969,38,709,409,327,974,977,568,402,983,478,510,68,490,140,441,314,698,339,19,152,925,76,681,694,119,340,936,567,700,346,353,938,415,732,899", + "254,70,937,650,420,300,839,958,687,933,227,568,471,370,0,417,780,847,487,857,293,818,622,123,96,762,744,354,512,654,425,493,763,12,396,149,785,594,312,273,841,941,480,554,262,675,654,65,908,547,131,166,475,995,10,529,720,343,818,8,865,416,795,542,26,225,147,801,708,703,382,440,35,368,104,866,595,94,458,87,637,278,164,524,254,56,414,615,330,50,373,616,659,986,328,671,395,473,566,432,162,751,708,574,481,253,616,700,446,405,557,269,708,132,895,182,994,518,499,509,225,150,547,619,820,705,884,841,302,64,47,376,399,926,732,112,225,176,258,702,647,849,288,149,199,493,908,733,864,180,164,932,363,9,638,989,563,182,88,858,205,171,21,76,518,828,597,754,817,721,957,126,819,14,573,342,789,880,88,572,621,310,501,485,382,890,360,890,774,460,506,905,286,538,744,307,855,148,235,378,944,1,554,368,718,69,96,452,398,354,191,385,742,801,431,971,906,415,345,560,932,630,189,160,393,933,371,856,909,844,423,998,301,201,319,39,14,815,505,893,233,930,42,306,780,455,635,671,116,194,90,292,11,418,360,293,966,373,489,668,285,671,95,87,420,807,702,590,591,36,377,705,380,105,479,291,745,326,698,649,794,94,923,798,491,571,786,498,357,129,412,268,816,118,890,642,197,471,557,835,712,386,144,198,266,452,915,822,348,437,343,172,388,94,319,56,869,596,183,333,734,948,47,133,333,914,393,496,894,901,147,755,232,433,258,77,772,142,970,621,307,621,903,917,606,585,913,78,516,365,918,323,623,901,566,953,59,252,599,719,473,21,919,603,781,454,173,660,431,924,737,425,428,33,60,264,699,919,369,763,863,479,163,73,322,2,176,939,292,526,890,449,596,241,922,314,195,576,857,608,80,300,880,65,203,902,949,389,567,438,268,946,672,968,366,739,986,160,245,339,215,43,347,579,318,85,86,951,627,479,628,302,938,320,643,859,995,705,319,903,79,72,214,260,770,616,285,53,328,586,148,573,76,600,438,195,819,685,852,231,608,585,293,351,888,129,948,469,477,650,898,983,178,465,947,918,768,422,274,489,283,610,876,567,960,254,230,324,176,738,720,472,523,221,609,45,958,411,265,96,573,82,493,323,461,942,589,453,269,158,463,987,353,581,448,850,215,832,968,425,507,900,227,126,9,488,335,839,724,907,442,618,311,106,321,849,156,307,666,315,434,966,203,313,835,948,182,395,213,237,773,29,876,195,86,826,335,679,233,344,808,105,482,603,189,487,510,380,658,387,774,581,252,192,531,838,762,913,128,642,36,61,494,38,176,278,763,610,342,572,664,450,226,67,419,514,377,364,212,820,530,428,632,408,16,826,788,766,788,280,362,754,691,790,115,921,508,841,665,632,771,541,746,729,590,757,63,180,546,734,233,552,886,200,91,87,785,657,786,151,141,107,685,297,353,357,159,158,702,42,715,917,832,59,11,977,227,879,797,9,567,514,412,979,872,579,630,201,903,576,577,245,53,764,828,902,88,631,525,376,504,888,435,612,155,147,401,993,473,157,655,280,769,828,297,931,819,147,123,723,693,781,501,35,240,783,638,103,343,632,901,548,874,784,298,874,39,483,118,625,875,209,762,182,504,185,327,232,742,702,373,982,78,871,815,48,809,303,293,187,894,446,463,364,395,791,222,877,786,614,348,7,772,229,78,409,538,924,89,600,101,773,834,891,714,123,955,852,209,946,392,151,357,927,847,290,718,777,714,154,628,885,360,705,656,72,26,186,107,581,430,722,773,253,527,798,733,798,253,327,947,595,4,886,288,525,488,357,280,137,829,280,511,436,749,218,697,401,525,19,732,265,261,398,160,828,382,929,255,88,356,153,785,402,488,137,781,30,908,898,504,931,648,19,194,587,318,379,463,416,586,130,797,958,824,664,782,243,161,238,325,824,653,595,180,608,937,121,278,785,358,170,436,487,968,898,623,637,833,726,423,743,995,283,517,905,6,730,328,777,290,708,925,189,493,875,287,371,740,904,100,25,77,458,31,211,694,881,220,215,335,229,822,23,914,968,13,814,218,303,976,578,449,136,685,148,789,974,534,697,963,782,218,317,931,159,800,606,593,416,553,604,46,266,676,615,956,822,879,10,351,188,125,869,910,619,946,777,900,261,620,973,202,798,280,742,940,912,48,769,467,284,157,52,856,437,287,253,601,902,950,568,105,707,976,93,172,471,11,477,810,282,609,956,414,349,545,824,765,501", + "969,10,252,419,805,198,512,671,230,817,795,43,291,567,417,0,669,407,187,539,62,456,304,977,900,967,804,163,336,640,427,233,478,804,284,994,373,134,567,694,759,761,88,361,216,196,886,340,312,440,30,811,652,51,758,529,324,113,509,431,992,697,80,283,626,159,963,640,734,917,633,332,458,82,736,793,446,626,233,69,310,933,325,244,45,196,69,374,264,613,748,66,299,484,672,515,531,836,420,883,621,429,297,175,171,239,897,489,48,262,455,486,490,358,491,917,621,68,359,325,958,922,438,864,471,318,771,14,724,71,932,259,356,383,296,389,651,275,178,549,624,102,291,911,218,471,841,909,306,185,587,609,154,477,303,657,544,821,302,270,303,546,429,549,515,122,199,867,262,296,754,34,214,761,210,141,746,334,404,32,807,695,306,393,134,310,137,511,494,786,913,467,697,889,413,105,49,631,639,959,939,628,169,732,275,248,427,593,256,150,117,205,323,794,59,600,32,445,436,272,209,371,361,625,559,62,193,825,813,83,955,814,429,679,570,439,716,83,493,864,879,374,159,429,730,78,782,852,374,237,901,587,499,225,998,418,113,211,156,283,224,672,408,665,343,858,85,890,339,371,674,685,664,738,867,168,819,811,819,817,882,715,941,429,410,653,937,428,188,822,501,96,964,18,315,523,954,520,502,992,290,659,91,113,885,624,310,512,751,453,873,930,748,432,905,132,849,674,454,874,793,50,454,780,958,343,247,313,567,850,609,254,788,711,811,438,183,294,950,273,254,976,671,937,89,567,348,251,360,823,160,509,618,345,147,788,767,506,486,833,365,206,471,271,831,279,297,116,335,507,778,646,887,364,977,784,836,656,129,558,169,931,228,133,632,785,648,519,330,413,286,932,351,476,455,481,608,152,674,53,567,217,375,929,469,709,335,187,460,52,500,895,602,94,252,165,947,205,187,787,463,994,443,71,760,65,523,667,99,818,974,661,774,29,45,711,372,518,700,104,741,120,558,335,835,795,476,438,863,968,418,596,620,669,157,331,781,552,628,693,639,350,713,400,112,318,692,181,95,30,620,46,124,840,961,822,321,576,598,797,292,816,757,995,525,728,907,334,722,565,18,895,851,479,225,102,368,492,405,536,839,180,677,462,2,494,456,835,454,190,697,473,499,987,704,618,420,879,746,517,86,426,169,861,106,57,412,535,479,928,227,802,604,479,222,758,618,20,385,207,402,862,935,250,621,260,655,196,941,112,815,79,973,423,852,983,101,62,49,336,613,505,617,348,339,469,458,602,340,538,551,351,450,417,108,863,226,67,386,654,78,181,231,587,892,95,604,387,518,277,467,788,297,7,126,65,339,430,420,553,219,722,125,239,953,777,569,394,324,784,23,116,738,505,463,857,663,202,665,70,843,314,103,308,67,913,96,326,854,224,542,859,351,914,725,144,44,919,60,467,384,475,122,722,690,676,805,149,491,613,56,281,49,419,962,152,866,508,937,226,226,943,745,85,239,422,607,799,400,724,628,969,509,761,278,940,591,482,571,362,908,292,860,577,532,685,844,409,482,860,143,128,649,239,795,536,76,20,447,182,367,39,144,135,150,544,40,411,766,20,687,867,920,155,763,843,472,498,518,382,471,984,876,446,32,556,752,39,247,742,931,51,616,870,371,140,900,490,456,753,896,874,504,445,969,529,623,351,773,635,906,910,521,365,356,389,748,268,585,119,907,598,879,821,316,835,275,625,484,251,450,982,547,253,425,538,733,775,857,98,12,11,688,482,43,583,935,601,797,113,41,416,209,25,804,569,553,726,341,378,690,231,168,568,683,906,121,716,168,708,933,669,338,236,216,679,913,311,307,651,499,901,787,251,197,337,179,465,196,127,906,654,850,426,710,33,556,174,795,326,536,748,925,835,61,343,9,526,377,305,356,404,774,260,39,121,707,487,572,524,689,289,220,44,789,186,946,114,382,657,442,611,45,519,755,587,2,265,28,969,453,430,379,442,516,330,652,752,60,402,719,75,173,270,218,221,931,769,886,647,196,838,211,867,370,318,460,593,874,253,924,360,119,417,946,660,446,484,41,893,401,187,757,294,968,252,581,759,997,495,21,887,366,252,86,256,672,967,195,93,523,400,7,763,869,740,15,227,741,790,5,759,122,168,139,602,131,241,390,286,112,676,560,539,693,885,809,652,326,924,995,699,540,176,520,4,774,92,945,139,221,825,104,518,534,59,404,795,700,100,803,313,202,319,137,796,278,7,696,303", + "172,137,687,377,805,220,876,191,555,60,438,905,787,309,780,669,0,676,334,535,110,499,368,115,167,93,409,442,485,233,729,548,200,876,622,439,257,847,921,91,385,914,469,58,706,858,307,636,277,311,413,744,988,697,463,635,601,20,450,955,448,809,805,954,160,645,63,139,986,676,831,656,920,827,776,465,599,199,149,553,204,956,86,616,803,55,462,526,701,599,883,75,572,571,325,666,847,750,26,949,367,617,394,710,982,566,351,51,430,142,705,697,255,436,82,706,910,302,52,414,824,800,383,176,913,630,806,788,267,26,608,719,532,365,687,980,278,191,139,92,852,34,768,784,627,691,447,74,46,598,475,183,584,339,356,226,73,709,953,913,369,331,737,283,21,749,500,570,703,271,59,350,252,457,638,43,989,427,63,355,4,959,680,858,500,813,281,67,235,220,452,676,32,838,494,375,622,135,585,695,691,642,220,671,755,236,832,486,206,10,776,648,169,636,65,532,116,110,549,370,315,775,99,423,812,864,837,582,44,641,812,895,853,725,276,463,212,295,64,892,770,693,848,362,535,674,31,193,605,18,604,928,56,626,433,382,179,458,978,771,671,749,109,205,93,232,159,598,110,594,946,969,862,566,224,416,385,108,118,752,353,225,557,522,644,985,171,649,495,555,148,566,163,552,643,513,918,666,503,778,486,59,46,714,636,214,122,674,647,684,625,398,34,74,248,555,429,577,64,650,671,435,583,252,809,321,931,473,881,905,668,984,673,348,917,419,322,258,872,781,695,520,351,158,24,649,587,172,110,252,938,812,137,790,77,499,26,72,631,587,67,26,498,988,772,250,858,282,594,854,769,6,896,140,296,221,669,276,262,509,66,358,670,409,287,352,482,85,328,705,581,906,680,526,835,782,611,777,594,410,245,675,884,783,723,540,989,954,20,481,303,625,132,704,669,805,695,592,950,914,649,394,559,456,689,189,414,558,490,601,424,500,890,574,787,667,220,960,613,681,992,219,594,736,275,889,782,111,513,612,587,75,509,178,542,836,193,569,923,664,93,977,978,439,471,389,221,301,623,159,423,780,892,408,656,234,454,79,553,182,827,290,790,736,740,896,329,929,462,104,230,358,485,190,164,810,583,943,399,454,365,105,605,96,81,746,828,962,63,61,342,837,586,807,190,765,575,97,725,257,6,150,771,923,602,350,810,873,81,755,33,447,575,33,422,915,215,331,340,503,207,705,568,307,922,537,349,556,739,366,199,642,366,166,547,941,176,338,558,718,53,407,250,925,411,920,674,411,169,633,900,320,953,777,204,382,478,870,742,907,84,154,436,516,229,525,262,171,539,457,947,73,992,980,442,186,871,218,939,80,64,193,554,572,690,417,762,572,996,427,109,755,18,454,227,897,626,720,392,231,512,340,132,703,350,254,832,994,708,841,734,387,456,467,631,783,960,911,835,213,302,382,496,983,238,182,303,380,734,349,254,965,224,237,712,333,39,86,205,616,689,686,759,401,837,417,468,183,138,844,56,336,354,963,915,880,802,672,879,84,342,438,351,217,942,273,315,128,611,416,45,763,220,745,871,13,933,436,464,457,870,176,265,545,909,457,762,448,146,785,768,533,954,551,11,660,257,421,208,607,406,527,815,100,632,964,52,828,162,171,234,213,130,853,720,811,519,496,62,151,841,880,375,881,578,545,244,911,723,714,940,659,217,923,877,951,248,481,978,408,276,404,892,873,520,500,220,182,63,931,212,507,818,745,614,298,792,616,755,650,655,430,514,388,797,834,703,127,949,248,438,631,966,630,133,305,998,437,614,602,270,470,190,831,538,302,53,385,191,718,833,537,936,56,501,143,540,971,45,925,625,131,79,608,806,862,869,8,30,319,605,631,613,605,893,652,658,292,888,941,386,506,782,206,208,965,497,663,816,411,939,687,228,396,628,845,855,416,881,196,801,835,895,798,393,843,794,940,210,952,116,453,566,510,80,216,722,378,383,567,642,41,464,252,154,221,177,375,905,72,284,758,765,727,591,635,229,59,747,729,716,825,237,555,873,723,962,365,273,890,535,261,9,613,516,597,626,974,950,343,953,880,231,600,36,528,284,785,581,481,783,68,600,876,349,736,742,338,119,235,654,715,94,447,732,413,501,421,75,103,473,23,954,94,759,880,522,562,578,874,610,232,255,977,249,416,690,522,800,955,789,974,104,552,499,352,189,676,625,742,465,941,522,417,298,714,112,508,417,523,684,301,33,895,529,570,443,314,937,758", + "463,344,373,449,115,770,59,112,311,131,900,661,106,812,847,407,676,0,40,23,996,231,587,141,284,596,718,189,487,11,264,597,427,921,151,214,109,947,617,842,393,142,840,240,51,446,53,749,512,341,949,115,55,309,951,611,910,245,274,827,124,507,726,978,615,539,989,338,870,1,883,789,220,534,777,976,672,700,106,711,306,160,359,687,576,905,598,694,529,391,686,503,55,934,24,774,331,257,348,383,315,442,239,828,341,228,829,684,218,38,943,866,564,80,686,965,898,820,698,4,113,969,362,489,124,794,684,376,808,848,527,102,939,359,344,226,613,390,189,327,413,267,669,63,543,301,230,373,437,17,381,273,792,586,494,596,997,68,843,946,55,174,651,469,430,871,815,958,754,652,816,936,572,906,641,438,940,267,449,284,739,370,539,909,249,310,235,493,166,574,972,223,418,517,407,721,677,76,534,959,726,319,11,963,27,20,694,15,137,457,66,239,552,777,226,687,799,490,316,72,102,762,762,16,11,639,957,36,326,603,107,428,845,444,836,578,744,769,237,688,796,70,910,357,685,665,519,584,16,574,502,38,975,705,388,729,701,76,538,956,56,207,950,623,31,584,751,272,818,480,390,257,661,934,137,990,647,710,786,629,702,650,685,460,982,231,600,617,994,915,672,468,206,222,748,787,30,146,664,249,610,727,197,610,501,682,327,862,285,694,497,177,359,192,336,568,63,293,73,776,317,127,6,260,476,86,503,831,271,203,679,271,356,340,756,652,323,849,49,539,976,420,244,243,847,36,477,578,211,681,279,34,303,268,165,867,503,318,75,296,866,245,490,768,948,718,541,112,619,276,988,324,596,822,397,586,381,438,67,776,289,111,329,895,621,944,125,324,370,208,149,966,437,910,113,345,63,259,757,86,357,325,149,884,459,802,915,917,191,113,208,488,579,420,545,219,237,325,390,4,28,597,484,268,562,740,571,176,631,377,683,280,988,889,589,718,338,350,753,457,942,343,322,257,564,20,282,239,124,132,854,215,617,730,98,61,831,264,702,416,678,830,635,441,927,38,809,540,66,72,236,558,893,515,978,280,746,663,999,39,629,427,306,848,669,223,323,842,920,200,735,751,438,435,788,290,714,782,725,167,718,890,116,664,303,521,848,809,334,87,579,245,2,243,306,466,455,116,189,281,989,455,791,37,968,551,392,28,34,857,853,663,936,943,410,480,407,296,118,985,68,42,497,97,430,780,207,142,574,680,518,382,873,826,157,915,51,582,79,432,84,182,444,530,614,208,823,908,547,116,922,556,811,866,321,130,867,937,667,311,218,88,18,880,154,335,718,720,988,429,26,677,525,852,421,493,425,713,923,568,946,776,602,832,73,659,425,254,712,563,111,482,264,429,200,835,815,874,389,619,125,732,902,704,344,935,736,895,59,258,216,48,619,588,653,159,621,909,474,376,66,369,967,253,717,587,582,774,382,154,261,897,383,639,777,451,497,329,780,515,313,218,127,269,238,508,661,13,101,146,208,962,513,566,770,64,314,836,24,242,552,778,487,22,288,773,870,339,916,56,861,207,234,994,367,473,960,562,393,705,816,133,774,347,762,381,350,170,126,647,114,986,774,826,42,856,505,368,73,33,899,101,790,551,769,38,771,890,432,513,368,587,190,15,531,971,729,121,769,307,964,473,790,746,751,484,128,566,761,637,251,734,798,929,729,348,231,842,926,261,440,145,354,500,551,933,376,235,593,560,60,281,808,676,741,169,701,869,274,120,37,958,970,195,1000,130,68,503,72,185,288,448,103,558,448,374,987,402,637,698,566,702,848,664,121,314,756,116,121,779,768,898,821,443,653,884,768,58,40,629,804,741,427,555,755,953,242,484,237,29,119,598,340,402,346,914,663,616,794,320,70,316,941,875,304,954,870,573,555,551,429,47,724,777,477,93,188,26,244,138,246,379,251,173,197,80,186,560,123,732,948,710,589,446,476,28,524,270,951,462,331,872,22,503,668,536,751,588,545,184,782,995,223,606,630,574,208,577,807,902,742,823,25,826,920,445,927,381,970,907,411,568,412,489,191,27,888,55,485,492,275,799,159,678,227,626,255,159,979,364,280,378,682,346,26,394,682,699,399,932,961,199,51,136,251,645,466,690,188,849,285,452,81,303,303,457,379,397,887,129,751,383,288,651,600,814,680,916,515,334,632,220,959,304,989,658,236,740,371,303,668,47,770,83,697,787,46,735,558,492,267,368,548,544,755,250,44,258,478,899", + "130,215,142,295,978,609,263,473,18,55,794,885,859,670,487,187,334,40,0,961,451,126,268,474,960,830,869,969,534,5,142,574,324,240,649,478,379,779,978,288,265,48,517,758,431,775,101,841,59,565,609,600,483,562,234,912,588,224,640,155,46,208,705,846,944,668,919,230,828,211,293,675,498,622,456,910,498,713,451,566,903,793,250,285,666,433,188,760,297,268,318,403,663,268,45,149,105,440,737,112,30,34,631,609,949,101,804,103,980,490,400,985,795,955,738,549,602,81,464,431,306,133,576,436,121,85,1000,477,79,861,968,54,330,872,148,631,773,247,854,632,999,466,589,948,295,626,680,535,14,267,211,999,598,403,838,616,282,315,903,701,734,430,311,6,40,969,578,562,77,279,84,595,910,152,289,681,342,269,390,14,386,356,822,356,314,690,752,244,920,199,6,186,808,652,82,808,587,370,105,14,935,1,695,414,904,912,820,662,780,29,348,175,724,245,246,913,731,902,406,635,370,657,138,795,520,629,133,864,237,731,806,973,478,166,932,15,569,160,803,867,207,650,268,340,942,455,325,869,3,35,23,211,983,45,108,421,254,540,947,513,27,487,75,635,335,198,317,426,692,305,556,259,827,64,367,789,280,473,895,85,264,616,786,207,162,227,445,971,409,769,834,971,438,492,387,574,573,939,850,923,956,814,562,254,902,773,280,489,392,547,349,574,739,42,738,126,940,601,425,112,244,862,733,905,315,942,371,961,881,976,908,415,33,265,542,60,148,427,825,27,441,441,25,579,272,366,28,650,613,770,956,745,353,303,182,874,824,565,184,139,148,84,45,327,479,81,550,542,340,210,878,857,72,454,491,649,580,293,805,24,69,447,152,629,771,586,353,309,421,846,380,39,82,287,249,337,433,36,589,71,940,54,626,712,646,59,401,499,879,893,101,434,46,695,471,700,892,140,501,586,783,982,973,579,852,98,81,971,50,457,708,450,337,621,301,823,717,387,276,904,260,990,447,206,878,601,181,67,392,420,237,683,27,591,242,469,630,347,749,650,793,925,298,923,476,953,666,549,104,629,185,153,355,701,403,234,829,203,235,319,385,527,599,301,980,911,81,319,741,516,940,520,758,257,316,813,569,722,314,843,650,896,722,22,237,768,34,401,475,511,519,644,443,803,359,783,698,824,266,659,752,313,159,505,545,333,286,359,467,568,13,201,581,520,811,100,152,797,321,884,830,556,257,302,546,736,619,894,229,388,105,594,4,840,736,105,10,207,158,283,238,872,8,111,454,476,201,110,299,913,395,645,329,580,774,987,96,200,459,665,526,639,101,935,891,925,714,617,665,820,388,90,185,179,111,440,137,894,405,87,5,888,630,135,813,389,990,98,318,358,351,446,834,515,820,395,281,100,25,147,349,606,865,835,885,158,895,453,707,658,120,427,102,476,244,145,808,55,477,829,640,747,489,720,504,350,154,681,564,143,881,130,67,239,111,149,537,554,191,952,248,383,926,617,69,939,235,663,853,543,491,791,738,757,903,58,86,591,709,281,454,332,660,947,296,17,926,182,898,144,445,314,939,95,907,368,563,816,949,501,467,83,328,592,952,109,269,5,767,37,839,482,353,830,722,891,847,961,801,496,634,531,252,553,591,746,734,87,355,260,989,829,725,669,420,896,948,93,572,527,742,953,672,625,463,353,432,629,494,555,354,631,217,888,303,738,935,85,377,766,114,966,575,987,152,629,58,31,951,76,470,44,439,587,789,210,827,471,946,997,228,312,12,699,631,578,583,210,49,624,408,297,274,302,884,941,338,749,93,809,60,509,593,824,938,389,774,744,208,113,196,357,404,530,120,110,640,514,720,173,466,325,81,330,868,345,441,468,862,205,448,107,317,485,816,31,744,648,475,769,569,953,947,916,659,462,61,219,764,890,769,997,927,946,233,866,178,192,325,521,32,573,352,171,259,890,761,747,134,810,808,998,663,254,253,14,475,609,148,709,566,364,932,209,768,668,183,869,755,598,770,218,434,172,752,329,898,123,795,531,255,235,634,454,374,737,322,285,75,415,158,616,90,767,97,263,552,870,984,520,76,963,785,740,137,249,484,89,91,170,299,174,696,298,336,22,197,690,624,347,462,583,667,713,268,108,425,820,626,391,927,55,854,483,105,631,270,60,861,625,247,222,239,272,712,857,769,101,273,753,838,638,683,139,815,806,81,362,109,377,319,296,830,846,53,514,779,353,386,707,798,648,992,935,59,847,425,998,201,69", + "335,456,628,813,230,610,709,406,358,582,598,938,102,925,857,539,535,23,961,0,564,541,18,691,671,992,980,200,957,281,761,131,916,499,866,525,447,991,102,120,116,344,457,957,671,801,139,906,787,718,463,818,851,42,296,9,4,335,558,419,182,611,5,695,103,414,217,81,545,573,987,608,545,100,559,274,257,452,785,833,387,649,451,627,727,694,916,473,544,67,930,143,551,906,222,144,697,334,527,215,677,180,299,982,127,552,921,74,629,258,512,679,852,100,210,700,642,531,578,329,172,337,815,560,18,175,173,602,66,193,368,223,775,357,305,854,682,582,549,693,373,326,337,706,361,85,130,39,581,475,889,658,193,73,80,97,446,415,668,284,208,499,376,498,299,111,476,811,985,132,844,395,73,166,162,661,414,234,473,509,500,98,256,952,626,722,544,862,238,666,842,448,591,822,228,692,835,867,440,485,352,407,319,955,808,426,552,722,389,252,153,299,914,703,564,48,939,849,414,573,193,871,940,468,404,567,675,711,464,42,905,689,580,213,387,684,704,814,223,366,284,118,126,721,741,663,19,32,475,4,193,288,265,37,444,108,696,496,664,960,531,80,420,642,507,711,837,52,15,664,798,220,379,419,846,269,463,25,785,620,293,112,807,637,913,600,820,998,126,760,172,100,318,874,152,667,380,796,628,94,2,968,870,940,270,36,594,595,685,321,732,387,601,750,10,410,432,792,493,43,51,654,700,57,255,775,735,355,200,527,490,123,766,537,109,504,947,537,775,572,527,193,962,295,794,1,396,118,371,114,856,463,70,707,533,213,964,350,480,877,284,421,485,657,180,953,889,249,772,28,361,139,31,494,86,739,838,182,684,460,166,550,841,386,440,750,517,242,716,532,605,532,825,732,399,897,261,660,805,283,238,32,710,603,914,629,698,252,635,852,137,352,812,100,153,431,882,246,920,407,127,4,752,995,210,52,831,492,514,213,777,265,848,874,445,503,944,837,139,350,39,764,721,410,100,184,760,948,417,32,105,936,276,696,482,292,325,93,623,278,289,401,34,932,152,822,406,720,785,98,476,542,830,807,146,430,907,207,495,629,331,877,737,577,184,214,119,277,717,845,197,513,892,527,20,410,938,793,992,262,931,344,805,778,701,373,377,837,362,468,704,59,136,190,843,623,580,747,412,426,127,725,339,922,900,127,435,957,681,354,604,166,286,724,206,173,169,759,735,694,199,604,829,468,174,289,854,691,903,562,116,241,284,430,271,119,206,64,116,937,663,149,612,297,273,733,132,468,710,80,408,313,768,384,383,360,536,586,393,51,65,280,341,691,733,290,78,775,556,797,144,632,973,558,287,703,276,686,588,71,402,836,374,416,332,741,797,650,736,152,986,757,50,857,325,227,254,59,820,502,594,278,793,702,357,689,959,138,231,585,754,622,141,126,459,112,620,474,9,770,149,237,289,836,116,171,757,111,272,479,695,7,550,860,253,96,744,875,816,12,249,545,823,994,570,767,916,754,291,31,805,537,766,543,61,622,366,820,265,821,566,988,460,84,859,345,117,890,236,166,939,943,515,688,860,341,742,318,71,675,11,843,184,611,707,256,148,906,882,459,186,408,342,254,405,72,423,732,286,234,505,920,668,324,959,410,851,471,629,352,873,895,277,112,52,805,200,937,568,523,945,941,932,612,88,599,273,398,280,265,785,678,158,509,186,762,565,457,961,107,822,19,773,62,756,270,601,71,117,220,756,333,791,715,433,860,994,143,741,320,625,567,574,55,133,861,485,631,292,685,612,725,476,860,810,238,279,799,870,420,652,678,119,323,360,400,792,899,372,925,721,496,820,173,352,605,513,804,463,83,459,282,596,35,961,343,395,356,439,286,341,563,338,65,381,971,797,886,834,388,224,923,763,152,854,424,248,888,804,174,148,103,548,155,88,371,424,563,334,992,908,948,421,350,474,862,405,924,29,312,78,830,91,74,292,105,690,887,907,212,802,519,99,392,633,124,632,702,190,206,920,421,718,24,365,665,489,734,858,653,921,868,796,469,602,735,178,595,41,76,895,311,531,617,537,737,877,823,379,804,994,642,374,593,445,470,920,356,843,110,647,753,381,31,566,578,995,352,396,772,241,879,362,464,590,828,182,291,143,8,866,611,620,643,793,455,631,569,284,638,124,296,381,607,440,765,937,969,606,655,653,934,547,934,976,425,715,104,803,933,838,562,506,802,515,512,798,349,396,9,485,43,934,861,212,148,11,943,838,148", + "704,530,327,575,125,544,919,520,529,893,528,831,784,317,293,62,110,996,451,564,0,818,652,964,387,318,521,261,165,483,239,417,828,995,62,168,179,42,224,832,281,356,885,459,93,317,449,469,118,909,631,847,359,805,622,712,925,802,585,207,301,445,390,678,550,584,783,111,805,122,112,989,711,106,168,343,853,231,7,109,501,733,883,707,20,726,39,590,303,516,457,206,368,152,612,452,229,709,470,799,404,973,124,446,955,614,524,435,668,159,125,840,410,238,114,416,680,41,630,967,818,424,474,34,894,637,605,184,616,844,769,503,763,630,380,23,671,17,708,154,427,964,446,436,56,554,746,643,333,448,739,558,711,219,235,163,554,574,166,95,895,323,257,323,140,264,48,38,335,333,148,608,777,620,336,460,952,111,13,262,131,952,753,416,386,865,459,176,926,793,482,762,885,147,945,86,376,730,732,290,88,866,181,887,163,771,574,903,146,461,369,23,535,362,18,398,648,854,501,436,102,12,683,878,655,324,242,660,72,119,418,212,132,783,266,505,225,670,928,923,217,784,914,516,712,322,859,241,515,312,731,939,51,219,103,57,882,461,591,370,74,225,832,337,542,304,829,832,357,568,406,494,343,206,323,882,945,564,220,93,6,946,890,448,102,545,569,463,137,29,859,960,467,744,84,259,197,385,671,899,754,251,59,63,676,153,761,224,530,997,694,957,661,446,218,143,15,421,541,640,306,439,39,63,299,865,147,696,917,56,705,64,451,425,115,384,932,751,211,251,364,15,874,138,439,552,488,346,451,666,10,126,341,793,422,994,782,34,248,726,895,403,963,857,630,75,250,118,325,948,503,863,525,619,717,642,632,480,9,685,609,194,973,865,313,270,570,671,352,651,148,885,996,794,771,992,471,458,1000,273,784,982,153,933,356,460,483,509,61,969,992,315,455,260,997,245,368,792,772,50,53,381,288,243,347,157,767,88,316,639,341,445,608,363,933,267,474,42,84,271,142,766,715,160,759,557,90,236,31,662,587,896,571,647,653,620,746,728,673,865,853,320,435,144,404,987,606,591,322,985,74,387,939,660,84,252,665,329,479,684,394,966,887,605,298,197,995,408,118,931,894,293,65,706,99,577,355,79,293,420,334,883,200,478,663,469,426,838,928,57,460,408,403,748,715,545,504,928,192,597,886,251,211,101,277,492,552,689,951,537,567,632,690,213,675,76,9,169,886,274,147,656,891,616,664,267,653,628,209,656,910,701,618,126,561,466,650,141,910,235,548,512,707,329,597,724,591,157,445,470,648,505,820,454,796,277,332,172,134,905,896,906,747,130,141,852,329,685,567,600,524,726,678,743,404,830,856,201,401,356,546,127,483,55,898,529,166,98,493,305,438,741,697,642,631,728,294,861,684,190,688,735,517,850,457,879,614,570,631,197,974,618,656,536,870,96,200,422,355,759,936,358,741,460,348,520,947,474,371,60,291,60,809,822,12,450,485,872,100,147,414,315,823,591,571,391,846,264,556,952,693,847,663,171,576,825,111,908,587,49,696,710,250,303,396,40,10,933,92,405,865,31,860,673,552,471,726,619,730,263,242,862,640,25,181,737,397,970,523,155,562,814,736,18,597,210,443,473,873,960,62,246,3,986,749,66,552,351,802,515,580,556,593,767,678,268,834,860,70,466,267,523,233,760,456,652,567,264,477,608,772,522,506,359,954,63,216,103,460,335,784,440,390,525,609,734,337,213,37,393,691,438,954,309,294,957,279,714,886,892,9,911,423,489,773,399,648,940,959,129,401,660,755,101,675,875,35,865,50,127,356,400,376,627,383,142,262,782,112,316,36,148,319,266,461,32,2,235,128,896,102,493,609,611,396,437,23,978,884,587,494,71,176,748,618,787,555,440,720,765,594,47,65,469,69,363,19,65,986,56,562,276,153,132,201,932,660,843,232,134,654,308,458,899,808,931,734,609,841,927,87,804,522,281,60,719,263,54,54,789,667,869,986,572,347,642,393,987,368,400,243,788,177,204,492,574,693,846,196,534,839,524,781,282,632,431,100,825,988,928,171,173,841,69,963,552,649,203,792,416,581,285,476,714,724,721,543,342,15,430,254,232,886,449,269,765,591,554,246,541,351,252,167,781,737,587,62,487,328,908,772,813,174,709,796,248,49,216,161,101,127,508,102,694,98,530,562,1000,88,413,780,120,309,119,727,447,523,861,140,229,568,412,449,525,904,313,219,650,157,426,416,60,676,299,313,317,400,54,888,774", + "507,796,167,548,277,818,213,758,427,880,234,68,760,695,818,456,499,231,126,541,818,0,253,24,452,95,64,826,727,77,988,67,57,877,89,355,338,517,755,736,371,820,301,912,686,86,206,212,1,443,810,940,799,698,861,924,335,630,434,265,90,699,838,363,740,377,333,222,86,171,794,984,907,268,979,16,26,111,298,878,277,858,826,659,272,260,606,627,532,654,119,843,918,462,552,310,954,895,890,622,179,331,414,32,683,795,420,210,161,62,833,199,351,334,92,657,106,126,249,429,978,814,474,243,653,979,263,732,864,214,950,763,61,276,848,868,499,396,871,87,15,366,261,986,992,650,515,2,397,983,215,159,491,289,799,952,668,60,676,676,566,918,86,951,934,716,990,924,530,124,358,928,739,599,903,259,842,515,932,947,918,333,279,153,918,394,37,590,598,622,648,440,791,620,963,244,582,319,536,912,419,73,73,53,50,140,490,319,836,328,843,948,441,685,479,100,797,614,294,137,108,551,411,678,37,51,808,828,19,424,178,638,438,332,149,13,665,3,195,341,472,993,371,12,636,621,985,962,316,226,67,381,510,554,881,75,432,219,443,575,559,892,880,425,374,49,602,24,923,444,39,970,803,54,340,746,187,292,102,418,228,334,962,968,161,308,532,659,323,208,942,342,223,991,389,329,957,554,279,596,664,741,502,924,115,378,745,98,827,996,101,984,715,456,974,452,902,862,267,214,44,637,422,334,296,980,238,467,290,974,362,48,93,861,158,562,223,443,87,8,969,946,29,147,449,396,146,584,740,449,562,383,940,506,583,362,837,81,998,472,418,220,725,491,982,506,288,586,546,798,622,180,132,741,453,857,684,436,214,309,774,34,349,945,265,95,235,216,447,777,709,757,665,788,420,820,47,960,87,163,299,948,654,264,884,225,529,154,97,880,129,543,842,911,886,498,721,572,584,523,411,226,441,645,489,219,409,80,519,904,597,486,789,569,502,558,395,605,413,935,914,814,413,443,263,107,810,726,401,701,386,504,103,281,230,803,994,9,457,973,572,462,854,197,925,338,777,366,624,299,708,523,754,986,346,908,264,308,124,293,418,839,427,602,819,391,810,814,550,72,76,829,69,311,31,66,298,973,440,391,233,157,336,778,712,450,229,728,922,360,584,107,425,45,243,254,905,322,499,583,61,578,979,660,28,65,230,600,825,864,347,937,378,754,475,130,76,148,341,385,734,306,312,7,966,73,245,607,959,143,335,436,931,885,532,295,774,634,218,358,387,407,298,161,306,831,386,128,163,471,525,559,730,179,274,196,531,787,859,307,357,164,406,964,408,43,433,146,706,160,752,76,815,707,965,141,247,352,118,203,364,424,151,709,888,267,429,157,911,944,810,722,530,277,660,23,756,697,357,456,121,222,964,431,503,518,651,699,779,531,588,550,560,114,414,201,562,813,602,978,273,877,967,903,770,491,579,350,880,406,991,568,158,141,327,226,517,806,584,825,624,504,630,866,846,347,824,633,946,837,725,391,38,712,21,443,872,988,14,702,745,309,975,6,275,706,165,461,644,560,204,34,260,719,53,480,686,904,266,979,607,601,898,808,121,721,539,685,380,533,285,947,521,400,913,816,502,176,251,342,449,121,160,488,494,126,142,598,420,614,302,228,869,555,613,712,531,333,938,631,967,989,416,700,352,193,620,401,775,954,167,63,3,572,222,471,468,968,719,352,895,859,733,323,530,981,543,671,420,904,182,196,381,711,152,580,406,149,731,308,71,206,995,956,808,645,526,828,141,754,902,775,853,976,314,915,660,355,350,805,507,200,507,45,362,470,254,261,507,265,475,246,879,306,104,424,186,240,278,648,692,804,932,568,3,811,216,137,950,957,397,43,313,902,367,537,310,717,867,387,102,148,638,454,968,220,606,752,6,144,601,392,546,631,852,790,426,95,772,433,84,700,435,516,521,909,170,786,995,892,437,480,516,516,863,965,660,450,131,771,281,339,360,381,327,290,321,571,635,331,846,186,398,98,134,398,806,901,302,326,922,371,177,510,718,347,235,322,874,775,928,284,366,436,622,998,763,257,305,384,640,329,504,75,306,69,466,719,323,401,657,386,40,173,11,767,787,64,856,476,391,540,692,699,20,313,273,219,212,47,932,586,14,309,643,367,945,853,582,572,745,866,104,532,265,554,200,3,86,246,443,432,257,597,209,55,451,316,935,971,693,16,745,623,62,357,476,133,689,824,227,858,549,415,53,366,208,865,341,947", + "358,664,769,550,219,439,354,86,183,829,86,641,146,660,622,304,368,587,268,18,652,253,0,873,213,93,216,408,976,798,427,620,229,638,875,168,304,548,176,848,393,716,954,364,180,31,116,597,499,229,688,965,829,632,71,116,674,382,836,308,277,187,821,18,426,800,223,405,95,286,638,630,998,569,967,425,319,599,101,383,380,246,138,664,836,680,607,124,624,19,911,747,889,747,704,317,309,578,799,893,894,585,961,592,173,370,116,513,706,498,523,688,103,128,686,789,343,46,735,217,305,918,288,22,68,526,533,934,201,466,52,814,48,463,97,340,976,652,122,182,203,535,808,108,19,356,898,23,769,409,399,616,160,32,764,311,244,595,84,554,436,483,95,209,909,473,713,662,326,509,370,814,427,285,808,288,695,177,771,849,512,961,512,499,803,834,395,481,421,25,297,433,486,417,202,606,223,189,662,310,670,459,242,382,273,883,412,132,35,773,880,962,339,54,810,852,368,395,654,756,643,745,668,113,29,129,382,424,858,327,110,912,592,511,65,77,645,292,855,71,431,759,156,604,537,557,909,379,949,444,113,117,960,45,412,406,156,899,873,657,179,933,804,389,484,126,726,619,789,565,177,903,808,631,988,940,326,844,314,623,114,228,538,491,528,772,39,853,280,336,412,587,722,869,300,70,718,141,152,935,716,634,270,568,477,411,114,314,20,261,561,903,27,65,751,393,735,572,419,742,6,459,245,147,72,51,538,737,674,471,474,742,943,372,17,58,611,142,434,94,996,801,267,775,739,345,528,380,628,853,429,192,291,428,804,561,797,825,497,493,1,414,626,873,221,686,168,11,349,73,988,86,144,336,627,149,701,143,352,684,373,835,523,826,582,816,981,518,548,906,822,330,350,879,962,778,390,868,386,326,188,496,653,803,352,38,886,295,430,155,826,594,125,477,457,844,58,905,368,4,594,862,783,386,969,829,420,295,115,490,22,507,602,267,975,245,190,680,260,154,733,754,385,447,31,376,337,941,164,970,893,714,880,498,424,219,9,3,89,583,57,932,746,422,584,70,926,544,319,265,498,326,449,507,291,854,591,170,475,269,184,332,945,930,430,650,637,301,562,898,669,697,560,28,841,790,909,836,664,697,149,965,751,439,286,223,125,669,870,674,711,976,507,32,339,68,753,938,450,856,33,118,398,228,348,470,676,423,812,567,134,460,857,130,818,230,476,79,982,437,679,185,900,751,96,460,185,84,916,529,346,645,215,830,999,839,131,90,389,929,211,534,568,685,473,48,891,652,412,144,371,340,384,759,312,415,921,516,519,705,294,935,486,733,268,731,198,55,670,270,165,849,357,211,708,710,39,584,174,529,855,990,665,746,629,843,279,728,249,131,935,566,104,518,609,27,674,675,315,927,325,8,209,346,848,301,624,388,87,480,798,487,49,225,170,324,610,921,469,550,306,511,370,798,518,659,195,752,670,763,144,884,764,427,101,113,507,598,421,486,917,535,740,337,290,452,132,198,973,952,16,265,351,308,22,706,327,49,787,560,494,530,348,120,322,961,269,437,372,307,334,132,797,650,483,169,383,654,496,620,492,118,702,4,457,50,529,374,169,710,888,763,527,978,126,548,252,680,922,100,619,36,645,728,472,468,303,907,175,258,568,258,673,888,120,282,341,627,168,981,7,14,820,596,569,104,281,402,486,745,49,787,363,18,526,696,896,732,6,66,194,639,16,135,997,20,882,713,438,770,281,447,866,34,459,159,796,499,448,354,566,103,986,925,765,423,85,604,561,869,950,226,302,214,552,948,465,662,160,733,435,460,638,123,335,919,733,880,21,483,187,653,38,33,338,436,336,603,555,711,983,574,786,596,39,325,688,714,159,565,779,451,644,360,940,678,342,662,255,532,407,366,580,724,166,340,677,237,202,920,193,917,748,955,767,876,336,642,638,451,847,480,348,313,643,153,616,132,361,421,680,131,285,27,640,342,777,479,20,506,491,47,180,197,690,732,966,255,94,71,22,863,767,269,961,686,415,498,81,660,719,154,586,967,120,260,162,550,493,388,852,721,870,208,128,56,64,274,160,306,962,181,881,851,892,923,662,956,725,849,521,449,798,353,984,775,504,319,499,582,735,211,214,147,769,452,513,883,975,290,153,414,393,556,621,760,708,152,392,201,384,613,883,674,231,945,549,860,263,828,716,470,634,242,93,845,767,75,320,931,572,647,779,564,303,10,245,904,801,291,723,723,881,696,138,632,795,664,490,127", + "852,686,538,571,921,158,765,333,32,213,872,935,473,548,123,977,115,141,474,691,964,24,873,0,8,930,962,128,274,555,24,852,567,553,386,709,481,436,99,42,651,318,186,953,242,868,322,603,543,476,937,625,980,128,910,71,368,12,513,915,810,455,175,3,589,602,871,700,319,567,456,140,54,679,382,793,213,730,283,920,779,726,107,369,208,116,113,877,36,63,136,148,977,282,753,58,490,62,174,879,995,452,956,528,23,778,609,878,237,651,935,523,846,732,84,937,118,925,814,228,708,664,236,756,535,434,794,929,188,760,676,505,949,981,609,19,147,647,6,2,568,709,661,704,54,775,311,963,388,678,497,446,71,675,468,462,233,29,798,779,555,662,992,172,122,388,677,157,318,482,881,164,395,114,98,131,921,93,823,385,789,82,631,112,82,320,959,237,653,41,151,685,240,260,169,823,62,171,504,950,750,577,281,887,713,454,760,113,141,72,774,525,400,15,344,845,779,755,564,36,162,224,805,381,34,873,417,500,482,831,537,226,159,489,219,211,732,328,651,275,976,432,472,972,812,483,217,171,78,440,452,939,483,679,563,544,981,381,809,543,455,305,935,766,596,417,48,97,336,381,834,729,820,333,304,352,445,444,963,145,873,557,27,583,843,142,817,457,577,406,648,230,927,74,395,558,264,490,650,814,270,745,453,584,911,973,510,612,270,278,646,26,391,83,194,310,299,164,541,328,277,228,688,665,145,746,991,984,629,65,2,123,973,465,916,141,534,376,825,296,978,102,151,264,224,627,538,151,169,783,754,731,63,423,816,616,963,90,137,660,926,864,880,921,448,990,895,449,703,640,907,155,247,549,118,15,156,338,818,49,85,165,314,695,13,785,294,734,579,908,461,736,307,792,509,567,241,563,798,176,841,32,949,567,643,87,133,811,412,330,525,137,51,459,631,72,37,800,213,707,88,9,968,338,931,610,825,864,69,283,837,852,966,48,238,562,898,597,170,337,176,750,749,86,969,54,190,765,333,29,140,194,802,274,811,687,601,804,403,686,112,509,554,764,914,372,842,654,824,427,625,808,231,168,792,158,875,661,720,976,822,942,816,84,901,609,883,274,111,661,778,222,674,328,499,811,618,703,420,295,632,263,770,148,99,702,681,995,343,66,125,131,263,228,148,299,239,303,396,792,523,842,385,418,317,93,724,122,869,8,244,960,367,870,755,146,727,867,587,835,303,288,782,750,964,881,654,379,187,646,792,66,290,933,270,559,293,19,232,353,796,554,170,784,238,248,108,228,498,337,609,561,604,176,639,268,583,479,671,203,764,883,690,606,247,555,499,216,508,77,81,198,184,304,339,856,275,981,403,470,250,869,161,989,597,583,30,587,306,484,503,607,837,197,691,201,192,893,247,728,420,15,594,457,678,445,206,503,360,989,695,127,403,11,522,595,268,296,976,145,925,364,323,753,805,614,138,576,778,897,621,796,791,617,834,475,710,291,364,632,56,846,518,300,559,421,736,786,918,589,389,591,714,825,471,477,304,448,276,291,32,980,667,485,377,884,40,896,359,528,173,813,863,20,88,333,966,588,174,506,425,737,349,200,79,728,823,582,666,464,97,982,665,655,237,656,53,943,390,893,141,911,652,681,910,822,387,959,983,278,129,694,70,903,169,849,217,418,665,824,759,65,316,262,605,541,765,876,919,583,692,171,139,110,574,792,100,992,431,787,528,321,122,731,643,138,393,130,112,185,644,997,213,225,70,877,882,172,942,934,288,446,848,314,409,169,754,894,152,860,577,771,874,936,653,276,203,638,152,515,799,359,134,254,20,83,823,29,744,68,444,575,442,25,706,515,126,46,489,881,636,14,951,497,918,391,52,940,383,248,742,203,828,72,32,949,174,961,739,809,154,107,490,815,509,969,74,485,810,831,146,744,538,263,34,332,62,826,456,643,675,894,462,764,984,188,482,304,244,317,438,348,41,171,665,969,106,950,497,837,548,776,322,61,746,802,352,152,843,306,793,161,109,353,407,380,791,541,382,775,504,787,367,950,128,990,209,857,427,649,330,392,655,213,636,51,212,605,337,490,393,837,52,307,353,110,187,617,668,570,69,977,818,717,68,883,516,934,109,490,444,592,790,42,310,149,5,692,752,644,612,34,831,516,959,4,948,621,300,559,845,41,744,411,593,314,470,428,77,137,4,203,587,574,613,5,592,591,815,330,478,889,900,231,136,995,668,843,366,931,664,51,467,952,259,852,559,243,17,83", + "356,149,459,135,253,84,858,694,412,669,523,878,131,423,96,900,167,284,960,671,387,452,213,8,0,135,511,388,733,119,454,770,527,977,384,286,345,139,774,3,896,861,342,433,219,528,849,703,763,327,234,107,613,928,57,591,91,323,727,210,537,641,54,493,515,412,568,605,121,540,805,771,506,967,376,534,779,19,8,495,936,27,229,799,819,946,537,504,789,534,434,818,323,600,182,193,719,736,367,835,176,517,84,236,831,126,565,864,898,985,975,186,91,450,315,995,974,872,463,308,855,342,277,978,960,916,283,517,545,291,856,770,160,811,270,899,145,116,410,246,271,696,231,914,436,140,805,679,173,582,29,752,740,130,624,667,115,69,303,349,284,384,126,456,103,371,936,329,666,348,667,346,848,341,194,702,168,29,316,395,869,855,391,87,92,690,874,361,395,182,810,423,345,389,604,306,727,668,367,900,215,240,561,30,661,119,906,202,830,862,140,681,790,155,263,22,715,792,177,732,551,995,604,640,771,232,766,649,596,519,26,948,255,430,80,960,514,462,88,753,597,557,985,61,60,184,783,787,861,768,820,732,91,471,868,790,220,395,550,580,625,11,229,740,251,439,745,200,514,197,993,280,880,859,749,532,433,763,844,410,978,814,686,329,611,663,5,57,794,946,351,13,704,290,732,718,496,906,200,850,739,759,294,16,357,37,544,56,88,44,165,120,204,315,881,333,577,663,840,574,941,564,626,76,40,338,251,501,410,200,510,348,923,437,939,335,672,379,563,764,857,880,333,905,985,62,971,214,530,717,558,764,955,940,735,337,205,157,218,594,254,264,501,781,168,893,866,40,89,218,624,239,8,802,824,688,329,157,250,762,789,919,304,919,373,326,845,422,864,699,946,743,841,422,109,454,953,397,48,791,507,766,85,402,262,535,412,31,684,982,673,78,211,747,396,835,216,882,734,419,699,384,210,673,584,803,205,110,506,419,679,253,635,378,995,983,831,986,674,68,130,311,437,172,266,117,569,848,29,912,235,107,968,266,17,420,108,286,410,995,510,260,59,912,629,209,943,654,154,52,351,411,660,642,739,892,10,390,819,950,899,374,841,140,303,867,625,776,350,165,393,431,915,840,351,424,951,739,504,522,364,977,108,337,92,80,819,639,455,413,218,132,13,178,815,739,375,222,36,247,612,77,461,459,911,4,487,793,994,900,677,503,399,296,255,806,411,991,371,578,768,436,444,457,592,427,446,462,991,666,920,509,57,595,823,487,308,453,201,176,27,962,981,265,223,598,249,949,436,759,498,687,749,51,626,564,236,400,802,577,910,762,318,115,786,401,410,538,951,734,53,439,61,532,667,623,651,635,385,680,128,34,806,148,243,714,788,634,274,265,983,358,716,920,922,286,982,699,593,978,655,245,919,338,270,997,186,719,170,593,500,701,155,846,177,883,559,525,60,706,852,120,330,999,576,938,56,459,822,817,165,798,116,718,51,735,168,712,903,668,910,621,184,692,714,624,66,746,648,409,108,285,472,470,730,368,195,679,15,295,95,820,90,68,112,246,731,598,769,969,979,807,346,820,886,630,358,905,463,948,586,816,523,122,876,235,68,23,784,900,479,592,690,240,512,335,84,222,70,847,333,932,359,508,786,982,463,380,168,1000,658,418,241,507,577,112,343,613,827,19,37,222,735,199,106,17,928,910,754,496,257,638,328,461,681,569,49,31,828,438,395,484,641,306,97,115,951,937,422,97,429,148,368,576,256,992,258,448,66,102,100,864,696,336,78,755,986,251,328,279,646,658,811,20,294,742,67,786,35,265,75,926,927,854,338,930,45,373,16,645,934,330,796,250,306,788,313,161,252,925,463,390,942,214,7,928,5,653,77,644,394,352,443,669,793,217,100,476,574,354,615,492,987,667,385,912,778,183,24,219,836,480,291,931,190,319,679,121,856,763,68,682,923,435,164,35,628,76,805,797,899,104,566,646,922,402,776,735,559,724,92,558,162,312,82,888,886,523,591,129,863,712,986,412,383,333,557,966,242,14,378,135,767,483,612,372,827,224,967,151,459,675,319,342,988,434,857,569,531,983,270,103,401,740,332,17,707,675,569,589,501,854,667,803,118,355,806,404,415,841,265,815,155,946,692,457,543,276,414,859,743,364,554,874,623,614,553,308,59,343,539,294,412,101,976,387,238,354,94,494,13,204,468,599,84,629,133,734,560,684,39,730,563,97,218,512,525,915,52,172,689,511,394,472,79,412,556,623,78,684", + "444,440,857,708,211,27,223,407,279,73,742,424,720,717,762,967,93,596,830,992,318,95,93,930,135,0,392,530,608,328,271,341,90,140,472,212,167,781,718,147,197,993,337,764,233,377,70,102,425,306,970,951,945,636,924,752,167,867,901,265,581,739,891,25,734,46,598,521,348,95,142,667,357,879,30,609,946,53,263,766,314,539,625,877,111,59,637,929,336,844,653,503,732,866,832,657,829,413,245,973,781,739,187,50,40,589,140,390,967,787,800,551,817,906,388,381,582,245,543,981,2,372,612,111,950,837,566,659,23,679,344,654,850,491,870,237,203,850,107,327,586,731,452,550,810,451,167,72,907,497,670,26,554,396,308,720,307,199,654,721,418,409,826,962,787,729,702,906,600,679,643,976,756,804,197,361,504,450,758,133,998,168,881,753,17,798,608,441,296,783,735,702,991,787,460,720,392,433,678,824,238,91,982,872,56,832,729,903,445,113,486,578,287,474,338,133,933,400,619,809,694,670,818,30,184,136,955,632,996,141,434,292,69,542,565,883,925,46,207,663,611,381,394,875,119,517,327,416,460,766,296,287,571,461,265,655,752,716,377,244,938,404,47,952,460,338,771,787,815,733,453,111,895,484,523,582,692,390,219,526,830,227,893,881,246,236,167,68,566,194,687,866,439,767,373,513,85,303,665,58,885,796,209,188,54,839,363,554,585,238,769,424,271,195,687,854,255,490,906,524,669,865,231,988,607,930,36,384,247,965,283,422,542,124,88,406,255,926,407,586,87,906,390,971,359,313,318,155,102,517,98,238,888,284,628,212,860,206,461,598,320,147,383,90,516,660,2,934,640,238,315,187,586,603,642,511,85,794,58,958,520,936,712,345,763,234,345,798,194,447,194,323,920,932,988,26,122,923,856,128,908,793,394,593,536,591,182,682,562,769,886,953,798,464,492,840,344,838,450,499,475,874,874,231,285,874,90,359,560,382,907,266,918,93,70,854,406,70,277,635,294,313,363,313,846,943,782,4,9,250,699,235,357,954,275,797,5,933,542,117,687,790,854,895,686,482,794,835,999,120,18,160,274,855,119,84,519,800,573,207,481,68,789,927,670,741,803,47,279,216,493,222,238,140,447,447,995,200,253,188,964,296,598,924,849,303,846,943,845,701,542,670,765,545,716,807,434,707,247,326,772,49,679,785,893,685,261,373,960,156,325,215,958,101,385,530,164,236,696,178,634,12,466,918,606,280,887,148,189,416,142,418,748,619,638,907,911,366,288,658,528,939,243,450,766,23,793,838,862,322,454,516,90,960,743,797,841,407,370,468,9,176,160,568,809,752,471,968,735,158,368,695,703,570,420,957,512,854,819,167,894,215,527,374,337,283,539,52,133,715,821,661,384,187,914,386,484,738,995,869,166,604,662,483,416,198,971,719,311,972,166,428,115,931,431,339,55,839,933,191,378,693,673,67,25,618,81,673,297,243,678,272,330,958,617,289,912,775,550,526,187,915,106,983,604,768,750,633,136,389,887,301,689,586,705,317,729,656,611,845,454,294,12,393,562,117,90,258,392,96,114,403,222,3,428,621,353,150,496,940,59,730,576,45,981,546,332,110,471,998,623,187,487,296,26,683,280,474,983,125,455,566,966,371,502,835,19,706,454,835,588,201,324,586,504,173,426,579,620,481,969,526,65,958,14,582,145,282,343,744,570,299,529,989,449,709,245,807,665,279,830,450,319,46,428,840,695,710,496,445,129,343,749,926,31,484,676,432,961,205,547,314,171,109,189,766,969,851,952,492,373,843,163,493,370,341,461,210,862,332,941,613,200,409,973,902,51,541,100,147,307,10,494,651,825,399,93,124,450,417,165,866,108,190,189,808,394,23,399,883,87,883,189,432,74,703,634,512,156,799,1,1,131,725,697,738,984,166,24,520,562,21,535,878,40,86,554,255,233,932,478,758,448,21,152,665,734,509,499,963,373,626,801,74,688,836,185,803,185,884,788,88,17,710,111,92,518,172,798,28,474,983,458,207,890,541,252,319,710,151,140,522,601,241,74,426,295,371,474,674,130,691,29,180,156,875,778,247,771,358,569,742,638,112,511,979,819,569,869,719,344,531,783,752,430,843,360,89,852,475,223,907,521,133,77,229,548,279,961,680,612,221,782,715,904,7,620,850,639,244,136,448,186,747,885,560,414,906,228,667,510,228,197,563,650,833,672,333,763,548,872,400,699,948,917,61,814,222,49,558,944,67,664,857,71,722,894,213,9,438", + "396,863,820,85,368,534,556,370,915,736,913,774,555,659,744,804,409,718,869,980,521,64,216,962,511,392,0,900,77,745,968,52,97,341,18,418,53,305,301,718,621,641,566,324,468,154,792,470,65,824,547,889,90,460,677,734,40,640,368,168,156,661,579,260,273,700,600,204,844,449,907,905,134,58,955,818,578,195,675,417,236,192,418,659,238,928,360,824,133,127,584,722,992,108,382,987,160,340,478,396,849,486,533,802,608,827,71,385,471,370,912,284,30,306,928,144,773,328,959,458,356,211,153,743,702,658,432,64,251,741,105,54,36,969,972,388,874,833,433,970,263,582,365,131,300,222,15,167,315,733,156,181,757,221,494,933,32,537,61,53,293,784,234,365,155,388,439,16,15,217,974,171,282,547,884,937,902,652,173,597,564,569,493,735,47,144,474,291,454,24,619,846,257,878,116,512,131,299,776,783,783,307,225,187,724,827,310,341,21,852,941,864,447,417,410,152,194,575,265,747,529,788,563,913,614,94,80,148,629,93,72,289,694,813,811,150,393,13,467,993,102,885,908,184,688,615,357,145,102,64,361,316,468,408,862,975,211,117,918,847,34,210,776,431,121,598,541,364,928,668,483,327,704,527,337,57,400,3,868,725,537,687,969,355,141,434,198,301,843,918,288,405,275,264,674,468,166,327,900,83,614,861,534,166,528,914,528,334,515,753,812,684,275,526,677,279,248,853,877,341,419,651,363,705,170,792,887,621,743,119,701,275,52,517,618,729,777,228,495,751,616,786,920,129,966,949,560,98,81,883,815,103,493,53,764,188,935,859,758,539,659,38,220,825,865,466,212,892,322,992,334,648,727,828,481,556,54,259,461,276,273,708,517,69,224,193,625,951,54,204,476,743,687,55,507,567,222,155,372,298,592,352,767,383,351,102,679,635,841,199,677,882,262,530,412,428,664,233,391,490,620,626,354,625,997,105,326,479,811,465,92,526,601,79,249,399,11,505,886,573,919,564,295,911,852,934,587,181,150,108,327,810,440,692,178,707,908,999,69,39,340,662,45,64,526,967,446,564,530,4,552,170,169,408,482,71,641,988,276,463,460,428,958,86,100,220,915,797,447,827,681,707,923,745,897,663,645,538,208,70,124,715,535,95,408,578,985,557,689,219,977,765,189,480,811,682,579,611,200,450,144,762,238,125,861,232,753,930,35,504,572,440,733,812,832,11,913,675,306,101,848,978,263,157,693,829,505,492,301,633,362,810,857,272,764,392,741,18,591,618,809,270,950,881,789,820,165,14,198,405,968,908,921,869,509,33,793,384,899,810,238,77,612,223,176,442,33,703,119,591,255,67,997,154,129,409,492,252,300,205,729,341,663,368,606,572,807,801,518,135,646,154,767,572,64,297,346,238,997,940,369,351,655,8,21,981,280,888,266,338,320,585,635,990,571,944,378,448,768,616,77,337,287,838,695,521,479,623,694,716,14,607,185,675,491,480,809,942,228,322,67,65,266,323,530,38,889,703,859,178,491,439,347,168,876,362,751,831,296,73,994,485,859,654,312,414,386,226,544,462,644,667,704,346,875,741,167,813,184,549,628,714,589,785,270,778,212,606,495,886,500,63,224,736,940,197,650,339,922,964,160,480,824,347,158,643,632,528,287,892,133,501,264,641,961,187,836,427,287,694,390,810,111,781,677,867,14,56,431,599,115,341,786,990,884,630,896,20,201,295,655,253,281,370,281,988,567,629,648,430,591,624,613,117,479,587,876,554,219,607,348,761,396,963,682,184,108,742,890,634,231,954,418,138,19,290,481,460,485,107,564,719,932,463,890,331,622,241,155,105,789,319,144,690,217,271,180,732,786,886,879,575,375,502,953,937,593,782,38,665,927,110,375,422,698,291,279,27,779,411,350,603,895,811,894,434,234,597,850,784,722,913,518,495,862,942,451,44,246,22,526,121,854,836,954,749,678,195,972,201,976,794,660,691,203,642,301,457,923,453,826,233,701,734,331,862,923,164,189,316,844,214,499,867,822,856,489,768,723,55,776,767,928,609,543,175,265,754,856,883,110,489,352,266,747,11,293,273,286,757,820,592,563,534,304,416,810,471,547,572,932,837,427,859,18,626,766,859,809,655,639,109,15,57,592,991,176,745,930,929,320,756,634,807,115,738,847,748,29,941,712,723,31,88,214,64,274,716,392,486,948,419,575,482,861,467,149,106,468,562,566,798,31,373,325,492,30,338,519,296,755,175,875,740,570,945,753,250,919,756", + "95,46,971,803,206,980,268,771,63,131,352,63,110,520,354,163,442,189,969,200,261,826,408,128,388,530,900,0,492,882,490,660,480,216,925,575,165,974,995,391,559,338,861,311,617,37,53,659,525,153,516,88,746,365,255,772,67,175,677,690,544,857,607,617,767,644,882,454,293,696,937,892,183,611,575,839,23,150,472,123,987,735,918,18,369,51,589,281,357,637,359,294,996,953,117,664,39,792,786,627,720,259,522,994,337,159,302,746,35,642,305,488,191,534,177,709,7,718,443,21,734,858,543,945,661,111,486,209,496,426,686,140,549,197,736,551,308,368,133,666,48,113,317,917,496,11,736,489,173,399,499,643,448,62,673,496,205,352,949,209,555,154,958,761,314,477,278,213,435,600,339,173,84,322,623,22,708,240,570,381,892,397,127,687,584,674,259,204,785,203,529,807,618,869,230,337,705,647,484,289,555,867,940,676,333,552,727,17,424,79,377,13,374,75,873,358,152,631,587,875,691,446,764,388,396,712,211,23,187,582,774,730,916,623,721,784,787,705,880,493,544,768,619,755,299,299,833,76,906,372,596,289,59,627,265,909,552,131,62,540,978,697,958,102,875,71,377,344,237,672,953,551,983,122,382,77,573,473,626,768,462,32,419,639,417,809,203,647,945,716,292,634,646,628,631,97,774,556,581,204,742,479,448,944,514,288,385,399,787,179,611,258,481,368,756,381,364,425,546,885,894,869,959,473,499,683,729,884,902,523,494,482,241,552,410,42,645,10,736,7,921,939,248,141,909,754,830,708,795,862,698,602,616,514,528,624,480,988,433,250,540,804,185,223,884,42,294,104,983,979,69,32,907,237,890,613,203,25,463,166,48,860,297,714,799,871,621,451,937,556,761,381,206,338,939,912,675,659,989,312,106,979,125,399,541,887,802,77,322,601,550,81,474,310,345,120,156,917,37,238,933,108,485,351,985,113,804,109,599,901,844,540,883,807,934,193,515,741,515,2,624,781,138,883,355,373,63,426,759,41,484,671,616,187,969,408,160,790,356,29,650,525,52,529,7,196,461,174,612,561,1,415,182,129,876,583,697,194,610,346,764,14,935,692,867,513,710,726,610,520,78,530,684,515,761,378,859,19,856,589,143,306,733,419,348,39,635,824,383,234,450,382,684,309,622,671,68,859,39,41,348,971,251,57,109,956,127,985,560,773,651,444,748,881,704,951,940,30,765,88,588,720,310,242,896,607,367,894,887,569,440,333,239,825,794,211,569,774,986,818,262,832,466,910,144,655,415,601,118,119,470,559,500,161,967,259,34,141,594,903,379,529,277,407,604,198,594,561,129,455,809,887,939,705,998,915,839,794,280,819,927,343,172,191,881,68,578,850,966,399,302,194,815,534,968,956,607,134,557,383,979,105,522,814,551,699,979,252,737,42,395,798,587,554,71,529,797,761,684,66,520,996,302,87,762,501,892,149,11,2,200,266,868,568,497,407,387,95,954,625,620,340,151,704,671,724,237,463,600,503,627,851,258,496,856,143,625,414,749,504,320,229,335,234,1,850,518,286,730,803,2,40,458,457,638,78,670,404,461,242,881,20,345,199,777,834,284,863,420,531,163,985,197,414,58,850,897,837,462,893,713,120,516,454,284,721,715,137,119,448,193,349,544,162,501,501,511,827,837,350,347,427,400,230,451,678,279,716,821,879,908,773,30,268,855,754,596,701,557,713,952,932,386,11,682,919,178,535,102,827,908,988,138,203,267,766,994,547,699,702,266,424,206,263,785,316,782,335,834,521,898,442,371,437,163,509,638,858,895,463,55,813,913,645,887,860,897,275,370,990,775,824,239,775,726,979,914,890,822,883,616,135,524,613,241,370,519,876,662,192,123,841,483,165,478,945,711,146,16,372,508,878,427,758,932,537,627,331,246,575,262,496,471,201,503,824,756,350,958,540,146,422,175,775,634,789,969,944,847,261,358,806,629,666,96,982,270,63,939,758,515,653,840,520,440,999,584,768,26,34,767,601,623,570,995,8,888,211,775,147,437,691,633,49,407,716,49,387,220,855,789,258,821,148,684,797,444,629,63,776,894,255,445,887,51,819,129,476,890,540,732,357,526,670,463,42,624,137,727,269,646,300,945,168,122,28,826,477,523,11,800,448,181,764,871,178,758,49,901,233,96,213,878,306,2,537,899,393,861,533,572,504,923,713,393,113,420,767,832,181,5,833,995,657,845,565,615,398,787,288,659,179,626,723,142,972,722,844,469,264", + "446,325,750,595,811,462,898,674,722,573,841,352,194,184,512,336,485,487,534,957,165,727,976,274,733,608,77,492,0,383,129,57,115,794,896,829,523,476,567,959,492,596,239,16,265,809,732,470,156,464,66,480,332,55,412,873,600,123,658,25,157,550,202,615,371,574,461,425,659,412,548,161,161,287,160,969,617,516,450,605,718,571,725,322,222,250,787,600,606,51,898,594,843,917,789,174,486,914,698,218,315,589,757,961,663,875,573,665,556,212,323,736,456,566,37,723,662,953,613,751,162,227,431,233,863,595,353,53,908,645,710,241,28,681,337,661,356,348,815,438,444,860,570,20,33,638,322,717,812,351,276,920,717,746,603,79,274,43,3,201,210,758,436,141,899,708,979,627,280,645,784,743,492,285,95,268,990,740,721,465,292,738,621,329,389,437,837,223,178,899,708,708,511,295,101,580,504,562,168,815,471,841,151,337,879,442,650,949,271,211,593,522,37,229,765,675,26,313,895,293,458,235,414,405,501,528,377,257,952,887,908,769,206,239,883,974,383,497,907,824,384,966,477,630,958,57,62,87,274,550,963,993,71,970,655,724,769,247,628,541,48,275,357,831,135,797,827,426,334,291,621,78,635,411,988,590,445,392,431,364,987,338,468,173,237,125,557,769,291,231,866,20,808,473,726,177,556,349,801,770,712,611,274,353,560,550,98,240,177,362,209,682,305,461,495,921,581,61,427,770,238,243,719,619,597,3,330,825,232,424,107,799,332,867,424,907,274,805,929,534,631,159,841,762,688,780,131,725,798,287,766,115,46,664,509,882,310,55,670,512,464,951,4,409,320,742,843,919,13,896,646,958,260,256,341,772,61,846,186,528,391,983,291,16,776,805,49,715,639,965,310,344,358,732,190,185,75,798,907,697,577,924,460,446,130,107,874,360,912,84,286,33,726,102,919,910,306,815,860,942,789,710,545,369,34,659,893,797,879,517,967,13,946,361,652,296,738,975,512,394,88,192,61,655,382,885,355,856,482,935,310,228,455,288,92,721,14,329,587,928,78,162,9,117,948,526,348,979,107,932,406,107,59,861,793,165,811,539,344,377,394,439,812,441,992,969,160,562,24,386,911,550,299,547,189,499,412,351,921,282,497,357,173,548,815,778,657,720,956,57,526,264,925,647,612,882,470,248,628,239,133,729,281,530,143,388,433,628,768,294,724,213,945,145,885,239,150,305,315,932,644,726,97,671,381,431,354,17,278,940,498,460,56,919,455,491,1000,744,32,349,529,121,238,690,184,611,386,817,209,114,104,750,810,599,631,394,774,44,240,351,380,493,806,897,197,708,325,597,474,279,924,319,871,57,773,296,888,438,760,860,264,889,384,675,286,282,783,781,33,237,827,125,660,28,539,843,415,282,834,826,660,621,577,39,283,439,380,511,756,856,374,616,368,496,888,884,584,80,610,221,899,604,25,416,476,775,613,505,133,40,758,363,632,109,2,292,431,754,994,885,65,794,328,787,960,780,892,834,209,677,431,359,374,694,352,559,9,246,780,33,119,444,710,610,28,366,156,391,251,259,18,901,114,83,85,383,960,90,577,910,441,575,255,901,991,254,247,577,97,563,76,854,554,976,863,769,157,954,104,553,485,842,334,808,371,726,625,465,30,674,538,774,872,391,950,53,127,407,734,258,913,817,117,969,761,935,685,398,111,566,172,873,591,407,814,980,469,239,10,635,339,245,892,900,654,313,910,602,511,483,326,778,487,623,448,160,229,898,343,94,474,734,916,155,372,978,840,684,257,295,141,964,712,26,872,851,829,553,363,572,801,972,203,124,247,993,781,536,759,538,994,249,653,353,485,575,367,268,620,777,647,851,802,378,970,830,753,731,622,228,321,579,761,637,854,928,627,722,270,784,693,50,607,34,757,899,232,415,784,796,299,80,193,627,478,402,982,990,95,308,149,461,576,434,609,146,687,2,308,209,958,440,61,808,141,687,385,290,735,564,629,840,852,698,981,739,230,195,953,456,81,637,275,714,951,67,764,445,783,143,972,428,120,599,789,271,626,253,170,551,699,608,152,430,693,509,188,319,198,847,536,337,575,803,375,944,722,101,228,161,746,235,123,652,971,857,247,971,947,742,142,598,248,958,679,254,77,723,999,176,589,429,523,748,398,618,914,814,749,114,539,955,564,511,994,59,859,441,546,549,342,401,475,836,151,182,360,999,676,750,297,154,374,558,206,425,315,817,474,999,375,765,354,615,824,510,200,475,860,851", + "86,418,652,15,700,713,611,426,811,120,518,484,684,281,654,640,233,11,5,281,483,77,798,555,119,328,745,882,383,0,806,714,266,69,179,807,425,846,564,334,148,810,112,360,273,168,723,779,511,273,761,417,813,184,955,183,592,912,48,14,777,968,274,799,314,56,563,488,650,887,162,697,487,726,431,332,510,412,92,215,347,858,459,169,208,899,615,522,322,9,663,351,174,547,524,774,66,935,563,511,532,816,238,297,570,455,180,596,541,629,180,169,986,749,471,423,564,10,117,149,858,617,681,82,534,286,183,396,404,986,517,112,147,874,64,542,323,661,149,88,520,814,621,134,855,29,429,127,938,920,758,980,985,236,44,748,730,783,915,654,30,800,768,27,407,184,641,90,637,653,291,579,372,187,731,514,201,526,254,418,458,601,31,30,194,582,539,345,759,95,563,765,416,849,512,864,221,351,194,91,375,228,424,983,388,807,279,521,318,697,625,710,937,959,58,686,387,750,582,532,433,342,269,592,612,84,80,683,745,654,253,855,427,841,527,573,818,1,122,276,141,377,225,911,804,568,952,355,844,937,441,678,129,128,813,688,697,438,601,187,154,819,718,366,604,189,44,912,956,30,661,152,346,431,420,275,670,708,977,86,375,749,344,544,452,75,394,977,705,329,881,856,495,955,744,462,172,34,12,296,139,189,92,336,531,951,485,362,436,356,513,420,285,890,268,947,852,555,176,593,793,777,636,815,936,427,309,218,149,695,874,585,731,441,458,924,606,592,763,653,504,318,313,438,859,956,904,258,917,192,118,809,524,157,912,268,627,79,49,449,840,727,781,514,349,25,282,764,971,740,351,307,315,782,236,742,138,362,516,306,588,40,996,835,153,746,713,705,855,624,34,877,251,350,261,816,486,686,657,940,466,222,255,419,823,944,226,74,916,916,343,118,692,965,501,533,737,32,156,671,220,666,551,984,613,308,306,308,873,274,321,532,919,266,311,596,171,68,757,949,483,22,446,251,860,519,992,431,249,153,479,16,948,542,301,326,166,685,132,858,635,789,789,112,884,340,637,958,394,433,184,443,901,821,699,174,596,648,487,977,845,781,865,32,343,177,823,115,461,780,548,268,83,458,468,349,591,705,689,713,603,37,764,913,18,698,282,10,557,932,44,763,326,892,557,42,863,136,680,592,292,232,65,788,146,283,331,512,291,640,613,593,845,729,272,870,953,298,223,351,493,762,841,306,925,16,753,271,323,13,435,622,392,477,835,367,20,293,912,857,761,294,302,35,706,520,574,896,259,367,527,423,781,387,233,260,727,224,255,422,655,126,666,465,617,554,420,53,670,178,210,186,597,186,983,772,474,690,583,802,290,49,558,232,260,962,195,615,885,799,575,582,190,581,556,703,52,758,967,416,386,742,801,307,936,49,33,20,842,935,570,14,420,572,254,307,99,730,561,220,204,814,793,234,293,377,643,148,207,415,471,398,400,963,484,288,4,295,477,330,160,403,776,537,813,569,762,77,985,586,341,884,371,381,300,351,510,902,829,183,374,364,527,80,503,938,970,149,977,453,576,432,414,756,543,424,217,275,460,280,122,227,140,64,691,835,478,117,943,286,600,458,491,904,843,480,893,922,44,55,516,356,307,463,196,364,36,291,965,457,22,479,248,229,742,79,351,396,522,335,716,509,712,648,912,428,601,710,210,531,2,992,289,246,230,759,98,438,59,113,778,760,622,298,308,996,302,17,899,541,618,43,675,83,191,949,946,365,756,599,479,931,682,667,366,644,543,858,362,487,569,935,620,692,486,703,322,566,458,470,938,748,35,25,874,654,983,489,168,602,462,732,656,401,204,93,466,14,59,339,542,108,439,839,525,775,737,366,40,827,629,435,257,140,176,426,224,378,330,440,760,931,75,584,806,382,769,534,155,38,185,49,970,13,683,918,328,343,891,219,92,822,179,553,554,431,249,405,888,284,490,901,388,963,838,655,618,439,282,95,206,749,276,761,876,92,32,604,543,498,63,887,907,415,534,587,896,714,884,837,215,975,848,159,298,662,273,314,909,767,885,314,347,442,72,959,793,316,160,735,735,302,838,618,43,619,562,961,578,225,948,743,235,874,4,952,463,240,532,577,128,276,66,328,68,351,768,810,970,917,157,670,385,290,920,446,614,928,532,80,789,604,952,584,94,449,683,470,582,84,81,603,62,940,967,256,36,965,204,487,667,842,431,552,601,768,332,27,563,642,996,198,319,425,99,541,396,347,216,423", + "397,304,904,973,708,488,385,505,624,403,392,122,590,506,425,427,729,264,142,761,239,988,427,24,454,271,968,490,129,806,0,500,19,949,953,345,971,962,839,732,325,290,11,445,78,904,992,30,398,35,59,817,89,224,157,955,876,736,232,567,492,30,241,888,678,871,753,546,449,666,408,803,937,332,314,213,694,594,295,294,765,436,143,496,495,683,463,49,574,516,610,266,751,672,385,367,781,267,425,123,737,548,957,24,705,750,685,267,550,933,173,285,953,269,406,218,625,702,726,258,854,738,383,193,523,879,350,895,550,279,448,194,89,391,527,118,51,644,296,715,523,535,731,861,878,356,171,899,782,944,520,879,739,626,23,656,643,121,318,457,92,152,794,422,424,712,858,906,65,813,283,773,790,542,531,670,555,125,76,297,277,112,630,676,411,281,869,973,548,108,549,226,185,560,344,760,491,433,776,630,574,287,447,674,903,381,747,187,811,185,985,302,70,765,261,838,133,993,275,286,461,694,562,430,632,848,334,163,262,156,146,764,631,153,146,554,860,110,128,941,660,109,676,609,187,217,796,455,115,707,514,199,383,769,488,440,440,5,680,79,338,161,809,153,940,125,290,841,505,220,913,299,349,416,545,5,3,494,628,469,948,741,860,170,126,792,383,897,27,497,152,572,86,36,631,342,905,536,217,474,603,597,371,777,399,997,70,813,869,680,408,454,58,481,810,735,377,813,644,760,275,212,943,673,167,417,936,424,391,169,502,230,727,813,745,855,109,563,711,33,555,651,599,866,879,586,61,269,926,260,468,713,845,394,651,806,552,948,899,307,698,718,595,312,807,849,124,860,788,911,742,703,828,607,200,870,662,955,93,194,559,271,332,303,320,323,813,550,234,961,331,56,594,260,658,232,856,806,898,31,394,445,462,491,705,113,857,518,862,349,328,550,841,860,618,330,998,414,400,939,353,994,123,992,983,906,631,971,188,875,34,717,77,693,559,790,725,225,499,34,400,662,845,734,752,537,269,534,749,690,798,523,877,712,568,635,197,789,294,809,710,752,404,784,461,443,894,53,696,550,835,310,291,704,560,895,36,98,569,542,92,399,986,379,596,586,114,946,758,613,303,879,753,437,631,702,779,788,712,537,997,917,716,684,159,748,176,151,496,90,700,437,723,272,943,188,670,239,294,195,410,105,784,402,149,737,29,904,593,240,679,428,335,862,126,921,511,293,556,191,526,215,769,255,421,337,521,368,526,496,81,747,457,488,912,557,597,277,234,600,390,994,438,872,960,168,349,230,946,945,874,999,22,914,194,503,808,755,761,543,384,530,247,225,685,674,321,593,175,481,556,451,955,570,264,747,98,470,56,829,957,678,76,648,627,82,654,721,171,46,133,702,955,816,294,734,952,584,106,564,221,915,760,635,35,148,672,95,851,807,579,833,648,14,541,58,665,80,636,613,115,517,48,146,524,794,185,695,220,391,157,808,322,717,734,701,893,740,834,906,48,619,56,279,556,161,426,81,90,909,816,802,29,514,883,476,391,233,329,597,3,721,279,397,262,438,181,218,914,4,275,123,384,950,97,762,198,98,557,284,927,205,87,432,981,924,137,14,33,623,844,471,271,482,749,701,464,225,859,538,750,417,963,459,643,104,183,459,563,397,452,800,574,16,647,611,125,759,656,204,433,823,183,237,143,530,799,241,584,952,591,989,148,955,36,259,831,896,981,436,858,117,941,209,31,904,388,782,982,365,254,394,936,381,581,179,105,101,270,582,995,180,44,249,439,833,307,495,434,812,253,868,546,429,965,613,399,411,240,646,850,586,173,503,686,150,443,83,749,424,905,532,507,174,679,699,592,630,255,722,397,200,343,968,553,751,558,859,495,848,607,402,700,615,126,825,336,422,486,708,838,43,66,287,84,766,138,840,339,184,638,366,885,705,599,782,950,618,666,542,873,437,215,450,566,87,155,710,676,644,820,535,678,43,583,786,337,94,32,148,777,958,409,157,412,138,668,773,812,522,98,732,265,902,937,204,777,21,874,829,171,609,331,828,325,635,567,611,988,661,453,93,708,603,629,904,964,759,278,252,832,809,776,632,860,822,995,173,817,952,519,352,764,852,516,481,691,429,471,684,968,767,384,207,286,208,950,537,133,371,573,704,585,146,745,949,959,598,345,702,747,32,955,55,544,25,422,102,287,842,554,108,807,905,163,706,804,144,76,463,641,642,591,980,922,764,875,968,154,768,925,205,156,984,474,227,499,518,946,653", + "893,904,223,375,271,755,74,434,517,566,982,756,158,575,493,233,548,597,574,131,417,67,620,852,770,341,52,660,57,714,500,0,126,276,671,125,556,179,628,311,665,594,340,115,195,834,240,860,740,164,145,473,502,670,332,922,645,981,296,286,786,838,389,175,673,803,246,587,725,687,82,935,486,615,778,216,402,237,530,570,759,474,338,513,217,949,914,682,736,813,467,541,248,29,14,794,895,66,34,549,523,545,32,3,669,157,824,271,192,210,283,324,375,724,339,96,833,252,15,311,587,663,328,258,236,328,991,407,19,514,730,871,415,631,167,986,812,450,235,902,804,563,620,192,481,528,470,403,605,897,850,649,213,694,683,350,630,385,311,220,486,31,477,535,398,285,688,98,407,710,949,305,879,395,559,648,780,797,323,524,261,853,233,312,896,960,693,450,144,74,739,614,318,663,82,781,452,648,304,701,798,610,89,347,821,538,182,102,544,857,634,983,967,53,108,983,512,284,795,128,880,443,334,37,172,197,561,663,26,196,911,121,768,930,856,379,87,866,831,517,489,332,301,291,340,474,355,541,59,974,164,991,851,599,230,285,992,158,858,32,248,793,91,559,294,126,893,791,74,972,379,812,328,682,815,995,484,538,292,334,681,381,938,460,728,373,547,395,134,300,560,997,110,932,611,464,675,117,396,171,176,320,52,40,854,144,792,410,122,247,91,289,824,921,579,532,971,379,729,941,48,115,548,905,568,768,651,582,808,505,641,205,399,607,439,138,354,836,276,6,914,995,468,721,97,884,853,603,295,519,958,344,625,252,297,619,412,211,532,287,829,847,452,612,50,729,683,995,875,365,882,886,919,93,23,141,94,345,428,741,530,619,490,12,545,165,42,174,67,232,249,203,33,936,489,596,139,435,677,83,612,186,188,450,533,194,711,371,341,715,927,767,217,566,750,46,632,113,729,983,283,559,192,28,674,955,315,285,919,980,398,518,159,894,358,595,539,967,828,329,980,831,117,945,789,194,17,71,346,433,920,377,243,644,26,38,538,546,601,682,986,643,700,396,510,524,601,48,269,598,445,496,37,279,210,15,446,698,133,4,745,457,31,462,146,459,425,962,251,452,910,986,451,919,429,387,151,655,323,106,833,276,145,251,950,884,156,25,798,302,432,640,914,458,172,671,459,682,767,144,217,440,397,185,581,733,15,204,253,552,543,773,718,918,713,122,936,35,406,931,614,884,774,195,94,854,607,840,22,834,396,917,315,536,371,943,43,496,967,71,971,101,271,55,126,426,82,616,61,263,498,640,987,630,145,162,811,472,101,365,688,931,91,195,442,994,219,319,202,524,141,161,45,862,162,977,999,941,153,420,203,192,820,505,792,698,548,17,616,647,477,696,168,709,949,679,681,948,248,585,895,238,743,590,822,394,644,154,348,454,173,635,992,876,91,676,951,880,617,399,763,653,848,460,527,641,529,585,963,347,474,747,577,501,376,70,787,383,675,874,131,402,865,480,919,258,951,136,729,557,550,127,415,282,501,526,907,466,108,897,731,206,148,448,849,507,26,656,219,115,673,119,814,693,726,290,653,419,58,823,593,241,36,293,724,690,77,438,283,353,746,70,485,625,825,241,968,123,962,854,146,80,200,55,978,830,794,143,402,518,451,96,689,541,834,978,520,223,554,858,632,484,794,152,392,80,389,578,397,119,397,490,514,535,556,569,826,208,741,276,790,291,78,793,606,72,445,200,158,997,623,249,992,491,967,223,994,909,303,833,868,381,336,230,186,289,918,304,288,847,444,7,264,228,397,309,473,394,911,780,468,887,787,286,658,537,881,956,980,380,845,988,406,494,170,556,479,482,437,773,252,901,490,890,415,697,760,652,101,219,108,773,705,283,946,813,974,631,995,901,267,734,44,173,962,479,398,967,669,543,115,871,114,434,357,797,28,549,258,558,223,139,155,787,641,820,594,429,678,97,272,861,648,264,829,845,696,837,715,58,981,607,807,4,812,622,355,856,651,512,659,291,766,450,474,745,994,638,853,829,803,482,86,523,26,856,8,819,995,463,305,510,625,111,306,331,75,851,143,346,704,640,129,968,489,998,757,573,673,339,137,110,667,939,115,653,248,2,666,78,787,541,236,364,85,793,266,182,156,738,581,445,523,969,587,647,493,346,214,793,675,447,782,431,105,351,363,571,456,832,496,509,736,440,982,292,960,319,444,772,16,922,851,405,502,940,149,252,529,402,960,323,739,542,466,972,390,668,38,22", + "56,295,132,674,620,518,864,727,195,346,264,55,346,658,763,478,200,427,324,916,828,57,229,567,527,90,97,480,115,266,19,126,0,897,271,659,573,383,611,885,405,848,699,379,648,93,218,473,398,771,379,679,342,853,453,121,443,371,767,882,808,573,42,862,473,453,891,955,227,958,102,81,139,887,666,6,782,837,780,548,663,337,610,557,69,129,488,336,920,66,463,93,195,681,866,349,259,754,100,334,815,969,537,934,528,28,721,574,947,459,657,232,663,672,221,44,226,805,953,195,672,191,493,975,262,485,958,683,395,507,85,477,188,455,579,602,732,388,620,822,788,93,593,277,721,878,758,237,217,361,815,825,378,109,243,874,804,190,232,467,561,715,234,339,185,150,739,861,406,895,234,275,341,559,265,618,189,70,857,294,457,427,921,629,460,704,621,794,186,78,331,572,794,123,941,728,555,335,474,234,409,339,81,620,450,674,217,751,90,609,888,437,440,994,817,971,261,676,25,251,985,956,366,830,679,913,478,410,878,313,532,132,142,96,359,410,593,747,716,268,932,303,727,851,891,422,139,674,911,312,502,898,551,629,994,328,708,347,324,160,462,870,910,491,994,372,999,286,529,234,26,32,47,483,958,302,12,580,956,370,809,329,835,167,227,396,419,999,552,202,474,260,975,809,852,540,737,561,573,989,23,506,676,237,246,23,62,104,774,893,180,808,96,395,261,602,508,643,909,185,854,944,532,121,406,922,77,571,113,530,624,868,520,285,478,980,276,447,439,918,247,131,690,564,334,511,416,825,150,551,554,205,891,258,140,545,402,334,556,171,330,222,781,926,112,473,547,816,166,341,746,495,168,403,816,395,441,411,122,71,955,796,490,912,744,391,248,535,864,612,358,178,613,651,646,435,479,798,597,6,638,941,559,775,933,469,391,388,950,924,763,283,930,39,847,898,416,37,802,971,346,896,662,68,425,714,855,698,946,564,763,435,102,386,94,475,586,20,660,310,985,637,470,124,127,534,111,140,94,763,234,412,319,61,622,516,212,393,663,305,113,168,797,420,358,764,23,404,17,872,874,459,499,624,718,238,994,353,194,454,142,6,716,114,710,947,6,215,791,151,428,919,539,207,910,184,366,818,445,123,640,486,369,684,601,394,636,807,633,189,813,588,842,580,332,117,169,773,477,244,476,961,866,768,510,121,701,218,405,686,573,583,657,485,886,271,884,669,423,756,749,38,900,163,268,741,795,236,772,489,536,216,596,810,941,945,122,662,55,800,918,179,611,854,791,102,504,718,392,651,838,406,764,28,204,364,614,430,904,895,795,753,956,643,393,904,795,544,836,163,892,240,870,803,533,528,811,122,635,617,274,742,306,242,319,474,404,746,381,853,964,223,154,474,480,411,356,544,562,899,117,354,626,4,898,109,943,940,707,610,780,89,110,14,953,126,136,940,3,181,536,654,42,784,753,583,438,48,512,186,455,980,972,756,737,513,8,331,137,866,979,449,273,817,509,219,174,844,76,974,566,636,22,345,828,577,731,164,602,632,597,654,128,820,185,737,273,726,213,286,138,571,125,195,459,171,27,193,6,603,179,198,360,909,631,478,646,604,826,747,932,156,728,289,743,838,193,758,80,359,967,283,699,962,664,684,782,598,671,878,777,524,15,207,323,137,127,722,63,532,139,989,34,862,489,777,855,737,494,895,63,833,438,985,321,307,491,1000,369,419,280,522,496,930,923,144,496,365,130,878,812,261,709,687,766,3,777,711,382,671,344,845,529,443,211,249,699,772,577,656,417,192,514,633,244,641,121,434,429,144,357,441,273,723,201,817,535,913,910,801,296,166,188,178,237,722,895,15,954,397,24,932,191,254,391,804,905,75,194,356,594,220,600,153,194,892,540,445,220,428,159,781,930,895,176,167,189,700,670,941,488,14,760,793,628,186,736,124,356,80,109,312,978,105,623,314,596,936,856,427,896,627,125,813,585,60,133,702,921,621,532,212,849,945,631,758,263,895,989,513,203,840,726,72,272,226,539,268,557,256,870,340,461,947,165,49,298,731,970,533,253,680,816,224,690,659,596,217,874,58,410,930,272,59,142,909,247,527,78,151,766,337,805,748,708,154,408,991,996,298,908,514,973,994,107,989,630,537,958,437,409,854,564,992,421,90,945,116,585,798,514,854,774,256,151,402,104,400,677,434,884,181,35,623,708,392,797,981,671,944,571,703,630,802,539,529,313,635,315,969,182,143,404,646,542,102,929,488,507,979", + "812,948,909,439,26,552,503,207,57,932,47,875,780,880,12,804,876,921,240,499,995,877,638,553,977,140,341,216,794,69,949,276,897,0,406,545,822,554,704,814,512,285,329,674,956,121,655,534,857,147,130,932,814,413,613,609,533,574,517,993,519,46,217,328,427,435,133,32,973,925,796,521,262,915,817,572,427,768,632,986,9,979,986,351,4,264,190,12,482,571,183,857,739,527,56,326,970,857,851,762,200,813,694,950,52,199,140,882,539,825,457,959,687,168,838,505,78,651,860,995,598,567,167,307,42,810,306,720,862,97,952,543,915,349,328,260,888,448,75,824,971,592,958,582,430,383,770,18,751,115,540,947,373,96,307,40,324,99,655,68,883,489,571,954,172,58,523,476,507,247,765,617,360,750,390,580,999,220,503,944,673,521,927,883,108,658,895,336,935,994,680,386,325,247,744,880,404,736,279,931,757,677,95,139,758,125,471,719,153,411,955,886,476,712,687,240,348,753,664,919,163,903,775,804,697,603,107,962,218,140,59,109,473,528,990,515,108,188,410,911,601,722,542,256,423,259,140,355,918,41,463,354,283,634,215,675,934,700,572,571,374,382,15,29,615,839,873,873,451,515,515,747,394,334,660,601,775,21,33,691,437,111,989,314,447,361,126,660,930,782,98,341,209,266,911,589,670,163,146,714,786,541,674,607,478,411,889,774,414,81,225,473,947,316,587,191,139,512,728,112,608,201,205,716,371,448,893,117,704,411,212,199,337,741,942,10,63,613,229,445,164,317,653,137,952,697,641,955,221,760,90,678,421,426,471,996,570,502,912,16,899,404,663,509,589,684,600,975,62,465,780,881,407,864,162,8,680,639,350,961,597,694,421,100,196,561,36,928,462,345,929,670,627,787,918,246,765,792,497,951,110,712,312,276,593,616,264,7,105,844,959,106,258,184,763,869,341,793,262,912,869,817,816,801,443,909,601,538,462,42,192,64,288,941,736,266,124,523,187,905,237,254,207,278,134,83,776,666,238,476,108,940,181,651,858,330,418,882,256,491,466,401,183,178,897,885,803,772,334,154,355,42,231,463,912,600,439,411,150,565,153,76,796,807,287,65,722,403,420,204,795,296,447,948,562,238,121,461,40,726,368,828,944,256,604,438,552,296,302,690,570,927,586,202,28,798,346,962,602,177,814,935,621,123,735,108,333,269,602,887,586,4,130,454,403,260,980,7,102,398,218,323,826,295,341,980,541,378,905,532,535,877,839,849,1000,677,920,946,491,34,73,680,618,78,936,480,436,932,323,306,117,771,400,187,485,762,900,182,335,468,811,991,825,438,554,298,770,878,347,230,28,77,182,54,871,676,647,50,762,312,233,777,858,434,337,34,635,577,545,469,949,357,401,215,850,881,942,937,865,315,861,456,816,577,934,703,220,63,955,91,610,751,355,109,203,272,73,466,395,572,701,829,823,127,524,892,536,484,235,460,708,991,69,633,71,983,657,685,973,116,802,539,127,943,577,53,21,738,327,352,703,250,261,93,538,48,304,6,929,462,462,354,741,621,481,902,942,941,177,36,972,727,575,893,970,326,459,734,215,936,510,724,233,307,885,698,85,577,40,543,594,779,369,671,446,254,222,665,137,608,388,923,958,280,608,763,336,376,415,982,218,381,400,146,410,727,359,218,920,378,716,527,566,387,218,935,315,253,741,378,411,765,862,474,606,340,256,907,767,644,760,238,278,68,388,156,383,529,114,439,561,673,342,211,989,540,985,379,248,3,824,731,685,407,187,622,425,269,774,379,364,937,820,770,330,312,991,895,391,716,736,661,710,45,229,625,459,301,533,612,695,962,34,566,205,44,402,828,502,165,20,996,57,89,404,492,694,136,369,827,740,119,646,155,543,817,557,699,512,542,190,666,878,988,138,135,727,734,68,370,2,720,492,456,38,432,848,244,457,796,877,67,78,854,645,926,370,177,339,752,286,593,61,55,90,787,739,313,411,502,434,129,499,719,655,830,29,183,599,297,903,537,579,531,393,112,177,257,503,710,435,24,394,935,321,742,978,880,663,33,257,873,42,293,337,377,708,49,706,691,143,228,979,972,809,818,657,471,780,137,805,418,987,365,193,755,136,24,624,686,866,302,947,395,93,897,84,676,324,519,375,137,58,94,996,785,880,99,923,489,468,802,711,836,571,762,760,593,534,681,187,190,842,686,941,191,51,679,751,157,260,232,952,60,612,590,607,646,92,752,103,914,842,553,30,317,756,635,69,697", + "967,626,607,832,885,134,490,989,654,878,325,305,667,711,396,284,622,151,649,866,62,89,875,386,384,472,18,925,896,179,953,671,271,406,0,352,114,710,187,521,922,379,983,956,176,705,159,602,29,494,890,905,937,977,346,35,73,12,633,805,541,909,534,304,818,730,355,644,826,153,261,98,855,894,863,419,717,379,257,814,582,557,870,364,557,881,950,382,499,578,939,193,433,187,997,673,217,108,396,427,46,8,926,627,366,462,601,621,455,269,878,474,183,315,709,942,767,277,967,502,698,262,332,135,385,23,718,503,671,562,45,712,745,470,95,706,550,386,798,286,634,580,584,596,589,421,815,548,727,276,442,868,760,993,937,296,929,126,256,275,847,6,247,85,180,320,545,200,90,84,161,275,425,553,718,317,700,461,339,554,759,15,972,424,693,571,53,362,988,98,130,926,766,817,865,148,418,993,309,190,382,445,750,295,760,32,915,148,367,862,658,824,364,235,446,384,118,813,456,993,347,536,61,685,558,930,793,500,269,715,327,10,649,618,597,410,785,703,433,832,943,281,518,129,707,744,391,927,489,711,761,698,98,798,263,843,124,800,41,973,341,396,189,146,460,324,176,707,985,410,358,385,237,141,939,658,145,803,781,811,495,613,837,713,981,4,987,645,121,584,164,261,356,423,247,643,234,150,519,627,800,612,998,124,505,640,974,360,675,998,396,516,118,918,546,511,493,64,917,442,979,240,860,632,620,52,827,569,388,514,238,678,977,989,499,574,336,78,199,673,325,728,466,684,48,929,662,425,96,953,768,50,600,806,449,974,935,895,105,568,894,613,653,396,334,226,308,364,240,107,331,696,44,561,153,757,905,382,908,983,488,808,496,215,446,204,532,127,642,182,721,834,31,300,590,974,107,297,976,478,346,809,368,320,29,921,721,470,810,240,944,232,517,351,754,450,900,519,407,847,610,755,710,559,502,796,846,708,589,582,225,864,681,624,8,177,770,924,524,52,190,303,787,78,93,119,559,730,577,305,271,3,842,960,873,171,618,981,177,344,361,963,800,255,569,360,467,194,798,769,957,986,759,257,31,595,52,145,289,391,795,891,686,365,206,223,921,540,689,87,933,764,262,436,585,30,37,711,347,442,608,80,3,919,35,161,375,253,510,732,489,298,120,885,481,831,283,78,575,290,47,287,829,332,559,637,308,413,585,567,324,943,239,976,121,263,217,283,269,471,654,658,559,393,600,558,466,825,413,150,355,575,33,599,909,440,753,400,468,759,824,491,926,499,831,942,994,702,441,811,71,596,95,586,173,47,945,996,901,560,496,682,853,622,672,660,928,841,77,407,878,751,696,236,423,927,398,710,28,540,812,589,532,540,914,260,21,177,99,811,630,229,83,624,684,661,912,429,830,552,875,947,272,329,571,169,894,386,921,16,469,187,321,922,161,335,358,306,209,499,285,55,602,298,499,188,831,457,598,440,62,621,857,915,536,989,868,506,323,875,484,175,297,409,364,10,764,953,888,32,502,334,990,382,293,144,243,411,840,953,176,73,13,74,31,911,893,521,828,306,648,37,722,471,496,323,797,447,149,846,83,586,643,476,978,213,744,342,435,596,643,789,82,196,167,882,900,840,106,334,354,273,37,382,632,365,365,70,627,865,949,567,325,433,848,737,276,284,809,674,690,392,519,654,697,978,96,725,232,551,387,221,331,559,466,249,280,759,843,142,504,265,397,671,319,925,688,141,94,829,49,630,657,953,417,788,630,446,319,555,31,517,717,894,734,757,705,835,858,604,264,694,77,218,303,857,80,878,14,728,922,881,149,455,772,762,324,819,845,435,483,302,754,82,989,574,1,811,933,326,310,742,995,141,418,688,623,187,786,496,470,629,150,582,345,915,708,43,690,871,707,462,521,490,474,749,743,603,264,834,555,480,586,412,44,269,461,912,293,545,982,986,328,484,182,112,546,495,377,661,496,173,667,486,447,117,997,841,753,276,943,82,714,596,436,344,718,609,336,535,915,694,278,504,685,818,719,476,769,513,854,331,41,401,98,707,844,215,909,639,839,883,876,1000,263,137,436,112,827,798,48,304,333,103,997,263,508,134,309,853,134,569,656,70,570,584,42,910,458,253,607,201,48,332,204,342,417,958,583,40,630,417,786,221,798,286,899,553,8,695,854,554,829,41,764,287,353,725,674,751,844,234,669,671,763,100,443,843,556,66,639,242,640,844,382,898,284,968,873,260,105,699,899,381,407,947,739,102,937,938", + "40,722,679,866,289,652,891,692,14,9,816,105,911,541,149,994,439,214,478,525,168,355,168,709,286,212,418,575,829,807,345,125,659,545,352,0,310,336,656,507,41,260,375,99,406,593,307,816,240,12,690,244,765,408,961,959,699,532,274,333,241,510,709,631,550,340,107,628,666,492,999,435,386,337,618,992,376,845,652,713,979,824,679,210,388,107,151,436,977,379,701,759,568,457,440,516,479,236,520,525,221,683,254,436,348,60,833,140,116,243,943,938,773,370,564,869,318,236,340,946,633,363,712,745,39,94,701,698,464,121,611,694,872,815,948,577,110,168,382,121,790,590,779,492,871,51,506,48,218,753,295,134,349,94,682,100,707,856,993,481,498,351,245,383,326,46,522,660,303,37,222,413,70,667,818,330,349,643,400,967,963,289,201,245,748,22,177,191,699,726,296,313,526,674,299,123,133,183,321,573,301,709,258,469,762,976,309,719,195,828,762,327,783,926,230,220,474,528,833,292,546,877,742,305,86,445,870,917,75,430,796,204,165,767,745,839,513,495,204,801,823,969,666,255,978,347,578,644,951,918,584,75,702,125,561,408,916,843,515,923,773,262,683,873,162,14,29,340,835,709,59,364,850,643,463,66,584,612,37,496,687,319,736,337,87,656,262,376,186,64,708,836,877,501,101,36,980,733,606,332,140,457,484,998,182,716,479,279,719,751,548,869,911,886,72,497,764,572,907,124,971,598,352,309,1,638,190,449,534,81,9,506,810,628,304,816,563,957,424,408,691,302,990,253,950,167,122,302,487,797,307,634,310,558,64,621,113,664,804,348,518,842,327,119,226,971,623,173,11,423,61,428,402,15,546,569,780,232,425,465,387,2,459,88,943,291,774,639,914,785,659,465,519,393,763,641,893,447,73,615,484,922,41,962,48,447,918,786,928,451,630,483,387,285,280,76,319,769,902,47,631,969,35,68,894,669,527,248,281,199,251,344,457,65,439,888,801,478,293,622,447,929,855,54,440,136,573,551,512,121,319,114,682,131,84,880,872,85,623,859,882,929,135,394,333,397,963,370,311,254,271,885,520,301,240,697,162,920,105,14,113,25,345,466,803,571,931,104,202,946,168,940,466,648,199,6,878,887,219,433,242,693,131,938,278,511,661,246,642,527,296,886,414,44,649,562,614,652,291,583,792,61,960,102,516,947,991,161,560,858,923,219,118,641,852,753,808,303,272,836,830,479,769,557,331,832,256,255,228,668,871,417,370,441,161,32,892,672,294,746,106,524,246,578,783,511,699,267,596,914,227,977,995,513,464,540,274,595,482,685,697,873,89,742,490,511,663,347,110,659,108,99,536,757,180,876,245,310,696,405,359,871,853,994,737,650,431,243,903,964,273,22,505,114,314,676,247,761,759,372,58,511,302,895,104,814,50,435,781,30,831,824,930,716,762,462,358,755,29,420,411,884,573,921,914,813,408,647,646,687,834,968,110,531,46,668,810,866,234,190,602,633,287,437,347,958,183,776,464,914,928,931,772,932,339,822,865,206,633,828,895,7,57,957,203,321,944,720,362,974,381,199,34,825,75,854,792,153,103,827,151,544,580,395,777,3,245,723,911,935,540,219,956,610,264,410,607,253,896,534,64,456,533,112,823,833,423,779,136,593,385,794,855,464,697,626,268,814,595,500,594,40,189,182,813,239,928,684,490,896,128,287,16,233,858,298,532,824,88,252,142,327,132,959,220,758,649,68,480,953,87,846,589,399,430,76,785,223,305,893,44,840,324,399,742,891,256,424,384,225,136,936,763,166,746,705,222,258,406,884,729,486,177,78,622,282,96,605,440,597,961,959,625,706,963,969,827,488,450,701,882,807,782,242,876,277,521,443,395,814,293,419,936,599,5,283,112,2,937,131,544,34,304,318,873,633,107,664,107,977,294,604,751,987,520,906,767,631,520,744,494,753,187,645,934,553,777,872,850,314,264,188,214,466,967,22,9,303,24,369,671,229,255,250,558,306,953,913,75,59,843,523,374,902,739,414,547,597,529,646,370,432,743,805,973,796,224,527,343,621,573,498,975,660,204,194,245,854,974,44,633,380,834,395,655,90,854,307,94,758,246,17,790,630,137,552,487,653,763,929,29,172,482,986,318,224,503,942,580,444,827,369,17,186,373,839,57,954,200,157,377,554,730,795,770,981,128,861,839,917,493,952,295,87,611,880,951,50,908,162,989,851,474,304,986,525,211,353,128,824,599,220,164,802,441,142,826,696,229,476", + "229,167,461,244,859,299,805,965,815,187,178,785,951,122,785,373,257,109,379,447,179,338,304,481,345,167,53,165,523,425,971,556,573,822,114,310,0,153,876,804,859,472,364,502,573,351,181,496,790,304,743,367,765,359,16,450,964,328,948,617,440,43,730,703,481,131,94,972,304,414,269,165,66,350,577,165,199,649,204,865,998,953,996,244,239,866,203,723,649,281,749,77,990,905,16,751,620,756,142,673,532,525,582,944,376,463,88,253,161,507,87,681,920,83,256,359,904,330,606,681,744,702,713,805,780,289,988,740,714,88,928,493,668,600,672,907,841,819,521,40,941,558,137,9,327,309,302,913,697,22,793,154,909,879,341,581,955,732,584,8,420,183,193,955,391,79,970,229,928,217,238,856,491,154,195,193,128,842,303,353,94,104,138,267,313,59,702,604,372,487,231,663,525,258,305,723,824,215,248,630,949,831,315,331,65,978,568,978,626,526,935,662,790,843,547,708,607,714,685,983,651,374,258,903,620,565,614,43,408,616,60,201,510,826,23,832,710,36,916,465,853,24,623,646,481,191,343,584,782,737,37,992,12,427,905,986,865,737,268,717,245,712,221,51,907,687,40,541,679,464,242,719,89,992,881,300,474,717,492,73,601,136,122,261,203,267,445,708,866,339,807,906,956,674,721,244,510,400,535,668,949,24,499,274,325,573,112,511,733,10,496,403,661,223,363,519,84,579,785,889,362,948,130,493,443,155,863,116,966,870,620,533,914,414,989,670,149,404,44,923,966,365,645,337,161,741,79,642,227,918,879,816,210,804,360,986,177,222,746,740,587,989,21,610,344,127,476,9,586,892,830,689,866,25,972,822,15,193,366,829,85,666,102,160,8,833,792,834,503,912,35,650,764,380,44,714,831,428,94,956,759,35,270,509,112,347,174,799,930,62,963,558,790,299,654,955,715,521,196,924,822,245,220,538,171,76,567,917,745,305,202,999,414,830,723,906,477,34,256,674,880,813,403,780,280,315,45,946,498,696,882,50,969,282,608,339,501,875,805,108,584,241,446,249,448,744,985,335,303,997,173,520,10,881,488,16,297,88,665,628,720,850,983,505,753,952,501,602,364,564,26,84,576,301,786,361,68,561,850,416,56,719,990,101,697,699,248,45,681,575,314,405,478,365,291,969,748,374,217,260,343,198,768,905,960,29,283,866,863,137,860,501,839,585,125,170,46,277,209,346,128,234,357,355,24,451,908,182,508,877,430,195,96,368,373,279,614,260,326,192,551,61,933,128,670,546,646,742,320,410,70,555,689,298,769,237,703,608,585,923,899,282,924,853,677,978,938,110,726,677,329,913,466,878,884,698,86,862,962,254,846,92,542,600,95,463,516,373,140,103,385,258,226,932,384,195,343,499,127,465,705,152,511,758,395,360,437,39,426,89,53,368,419,914,826,149,695,727,206,681,568,163,891,798,167,723,205,130,769,321,437,985,527,289,450,496,556,567,973,540,545,244,559,182,390,357,130,668,905,546,792,68,105,912,88,854,256,46,336,826,320,219,765,28,502,260,446,518,430,156,721,169,291,384,564,423,386,885,591,98,542,692,618,880,400,777,885,59,589,624,626,621,517,63,547,424,523,493,608,676,584,181,623,675,722,525,238,629,649,968,860,647,926,333,659,78,41,878,497,966,869,301,28,483,801,869,160,724,411,411,351,575,388,232,60,342,818,362,742,102,387,855,712,306,944,486,887,735,696,318,691,258,614,269,133,706,65,652,693,438,44,232,30,483,492,979,954,837,915,112,349,97,447,500,371,403,800,123,505,258,437,330,79,207,297,91,430,452,651,708,274,821,780,673,499,159,309,701,394,998,877,743,333,852,765,710,502,450,193,875,629,731,475,633,284,514,690,295,273,344,921,818,935,689,419,391,468,785,80,530,376,194,259,224,298,555,355,473,961,306,987,200,639,443,812,481,685,293,794,253,41,163,481,6,166,419,654,298,939,808,637,12,403,853,405,438,838,950,654,243,870,925,901,897,619,436,303,112,897,420,109,217,404,639,306,202,801,835,942,369,507,105,676,335,356,510,879,217,951,63,947,550,939,551,224,440,209,44,853,96,243,58,960,162,249,458,506,453,787,511,667,145,666,41,484,712,389,925,415,988,545,403,320,95,477,383,345,127,614,921,69,173,419,538,947,278,877,618,2,98,358,384,641,81,27,663,47,522,773,995,976,190,777,264,655,748,424,83,88,690,645,31,60,872,996,250,984,757,512,835", + "33,27,628,950,190,852,551,677,500,198,620,232,198,654,594,134,847,947,779,991,42,517,548,436,139,781,305,974,476,846,962,179,383,554,710,336,153,0,636,824,690,230,321,896,269,479,951,740,713,401,891,908,530,467,603,945,713,693,486,424,981,809,67,431,167,780,782,171,630,686,553,631,529,221,534,823,274,171,891,556,815,211,629,863,411,924,11,314,622,566,267,49,538,922,572,198,25,996,101,4,709,793,475,259,993,442,605,516,305,513,77,733,808,155,501,836,573,553,460,908,702,707,778,893,600,15,228,458,223,735,211,401,958,285,322,850,236,91,809,63,12,129,170,51,416,486,27,919,494,798,244,93,879,520,994,997,507,324,867,274,897,852,965,614,129,719,958,315,57,675,583,153,511,70,350,320,730,965,498,993,232,544,915,394,226,323,943,210,974,650,309,539,615,992,825,645,251,49,769,381,678,640,927,612,933,908,489,341,153,435,877,349,573,388,530,125,784,871,603,334,853,195,440,692,68,268,496,947,373,907,826,270,771,292,219,935,158,992,418,345,42,884,1,331,944,318,903,757,249,797,847,74,408,107,397,120,151,254,307,418,832,407,533,549,560,418,525,393,280,101,842,108,366,91,974,265,982,857,234,926,560,188,850,770,777,827,609,240,25,740,167,622,655,658,241,419,147,441,83,229,352,645,83,919,474,696,668,278,882,662,475,123,326,151,595,620,305,241,322,4,917,295,791,105,674,189,971,434,930,896,850,358,927,934,105,218,673,794,874,580,507,211,284,759,737,241,86,482,99,505,816,212,143,949,549,42,611,385,303,779,930,105,329,376,98,29,258,248,600,901,109,510,351,601,313,49,874,910,39,881,576,475,451,130,314,923,657,839,580,286,516,329,688,352,606,10,358,913,564,463,574,154,977,833,977,973,255,786,425,946,432,169,782,678,383,177,868,988,270,776,486,848,110,79,279,221,83,848,590,3,546,972,871,697,387,190,819,684,864,867,15,161,927,222,973,851,618,170,822,343,784,44,664,491,418,37,207,932,881,812,274,727,735,600,288,708,606,387,200,244,484,923,732,80,613,176,458,50,278,198,209,949,966,534,198,21,849,161,343,474,373,807,225,685,310,117,701,77,950,555,973,990,639,185,490,990,886,377,228,255,489,42,709,648,267,39,706,265,988,788,791,149,613,690,224,701,954,22,795,443,741,369,188,978,576,577,433,906,848,81,226,19,564,38,9,726,881,152,201,219,187,337,250,854,948,990,181,622,753,756,267,603,892,731,658,875,259,629,757,78,873,97,37,817,938,718,840,464,638,666,772,299,650,349,282,743,808,130,236,472,881,973,130,565,232,887,452,667,389,980,84,799,406,183,297,444,380,404,141,330,268,379,374,963,204,58,486,292,337,530,748,737,44,812,65,849,196,233,107,810,690,35,855,921,951,821,483,893,768,187,350,985,52,657,507,274,686,955,823,903,883,63,234,398,43,281,819,756,992,353,263,36,599,155,646,865,452,797,680,561,649,500,318,667,269,513,742,963,729,852,169,385,398,120,595,408,619,471,301,862,846,900,930,242,574,216,425,110,112,144,851,180,377,300,132,595,497,955,758,991,164,649,354,869,309,461,629,743,652,35,22,75,809,199,307,298,386,479,265,511,911,890,393,857,991,155,770,405,690,842,49,599,339,674,805,810,716,621,329,974,130,257,598,807,857,629,835,118,972,277,654,904,497,707,377,434,844,886,548,495,352,754,990,567,696,267,522,254,874,612,228,775,364,101,213,241,799,938,284,669,922,988,361,992,469,342,435,515,394,795,508,599,740,924,437,601,4,407,468,304,399,650,889,228,325,44,917,416,690,652,761,400,502,801,797,140,582,799,153,679,664,38,260,597,595,664,947,784,830,323,929,35,112,992,527,265,640,944,926,118,317,662,333,40,953,731,833,273,834,872,927,465,908,668,611,310,461,274,36,509,701,36,381,76,945,605,813,924,170,923,52,767,773,893,700,730,156,401,439,581,874,871,579,894,857,9,739,980,757,543,811,348,389,291,730,999,767,201,872,857,469,307,773,111,556,999,128,667,208,543,319,602,266,312,103,294,759,721,936,940,495,214,258,531,221,2,179,460,949,512,599,539,790,487,635,770,650,92,512,655,754,228,441,728,259,468,105,447,432,674,171,267,686,745,947,541,615,411,306,251,506,798,165,817,302,145,652,351,260,790,493,261,774,830,60,787,359,121,885,237,91,440,95,355,215,188,750,537,763,349", + "112,396,781,993,731,156,77,716,464,621,786,574,340,833,312,567,921,617,978,102,224,755,176,99,774,718,301,995,567,564,839,628,611,704,187,656,876,636,0,634,880,367,291,800,380,358,7,279,299,800,601,318,951,884,884,930,921,2,719,23,701,861,760,289,366,519,158,114,203,857,217,823,727,126,677,667,568,882,584,996,892,952,870,490,564,739,891,50,532,857,342,273,13,282,684,878,505,999,515,939,392,996,894,603,942,959,141,716,709,821,324,813,409,745,552,623,742,854,256,787,946,953,811,33,260,577,802,76,176,417,725,730,148,393,776,273,776,773,177,610,671,35,338,150,725,834,274,600,583,59,274,801,337,696,65,755,931,548,808,266,345,654,507,723,479,467,222,179,227,619,442,22,728,918,31,479,524,902,26,987,938,346,4,855,911,287,35,147,787,89,348,107,810,944,750,898,106,996,347,652,43,378,825,968,484,7,720,551,635,356,768,298,564,212,122,442,221,349,99,539,146,830,766,352,131,394,547,387,885,885,976,694,59,898,823,39,786,396,81,217,511,149,64,674,959,934,459,354,510,399,98,571,984,342,902,443,541,65,240,253,367,778,432,880,468,561,626,309,423,12,420,643,860,885,414,364,649,151,827,477,129,41,359,957,177,485,390,134,890,966,33,219,317,609,924,208,952,34,150,438,479,711,698,22,383,202,523,946,900,583,17,492,511,500,413,983,739,188,665,438,223,228,724,288,632,960,732,626,379,392,514,114,895,574,15,785,373,489,592,802,821,351,914,592,894,67,429,260,989,846,956,750,138,327,39,756,643,153,316,118,617,54,524,676,88,912,741,884,340,288,406,695,728,500,259,85,586,755,261,408,250,248,268,915,37,592,510,201,432,790,629,823,67,594,109,316,71,675,558,522,693,200,591,750,748,211,678,625,291,819,892,797,304,444,433,699,911,311,905,934,285,522,543,33,447,785,204,490,757,59,9,848,631,997,673,431,929,197,453,554,16,845,156,885,490,915,233,310,207,709,536,635,64,620,763,28,243,433,609,159,839,903,403,246,122,387,368,481,4,185,535,625,827,837,232,886,591,948,547,671,348,779,442,431,423,349,215,311,182,896,523,460,422,874,523,139,19,322,585,917,229,236,149,413,996,42,468,610,665,188,238,395,152,61,97,608,945,291,31,781,322,598,146,748,585,219,225,107,464,251,79,5,711,819,411,893,762,885,177,334,545,982,416,71,822,673,450,618,462,399,944,884,373,129,248,385,986,786,191,330,398,298,495,811,908,116,852,167,859,439,736,234,936,457,719,515,208,291,194,666,236,800,656,440,535,817,167,33,463,506,929,550,765,984,307,320,677,307,630,469,404,240,844,308,522,408,371,870,669,629,580,948,134,348,992,312,556,140,420,153,405,540,266,643,486,612,617,496,50,959,232,485,414,371,773,696,998,160,512,846,358,450,705,691,55,899,999,97,395,197,779,293,213,970,715,669,928,721,563,6,107,535,823,782,375,486,582,328,365,117,289,822,861,12,589,750,524,234,670,541,136,509,700,375,441,622,508,146,106,828,502,670,246,569,203,571,238,902,148,211,514,328,359,798,733,993,427,7,97,252,706,129,753,633,510,257,742,183,436,927,398,364,605,96,722,121,676,440,147,364,381,81,423,406,797,514,441,168,51,667,173,711,945,113,425,599,915,959,329,972,399,643,112,709,204,783,833,297,564,533,37,980,448,157,490,442,209,86,751,806,879,222,680,107,192,837,729,121,584,84,444,41,439,236,206,506,560,452,41,27,687,754,637,659,261,886,144,246,945,636,62,138,930,588,528,153,58,674,97,187,648,646,856,555,669,269,158,933,451,249,872,973,648,403,783,406,698,582,36,909,696,569,450,682,194,977,447,445,445,501,681,922,117,99,648,855,664,767,859,583,251,192,960,427,629,911,805,257,184,428,558,78,404,172,913,981,722,357,859,668,582,608,784,704,327,492,428,484,982,646,356,367,117,922,985,52,784,468,540,250,245,359,616,727,350,647,152,711,498,416,328,491,275,719,281,556,222,805,994,123,320,534,772,839,914,570,403,371,81,340,242,856,707,569,71,46,396,556,251,619,544,251,265,516,754,751,507,665,154,297,115,407,749,671,814,859,885,220,468,294,657,268,847,175,172,388,305,161,352,190,707,422,369,324,824,505,301,175,303,679,816,225,141,718,479,392,887,723,773,920,516,553,916,379,334,157,847,783,198,322,847,250,318,779,257,342,915,995,985,915", + "913,183,698,821,963,676,475,680,742,731,202,24,54,38,273,694,91,842,288,120,832,736,848,42,3,147,718,391,959,334,732,311,885,814,521,507,804,824,634,0,825,126,977,599,271,612,352,534,649,208,203,99,308,108,1,202,765,370,611,451,992,42,846,387,568,305,771,189,985,806,458,44,833,585,442,455,143,507,274,717,127,365,655,510,463,481,928,350,52,800,134,649,619,981,365,151,906,251,184,675,609,74,208,997,359,620,706,473,770,871,918,164,952,170,969,549,341,1,695,160,119,462,297,646,396,812,944,339,6,665,240,906,994,598,714,433,448,652,864,113,383,317,977,628,332,611,740,167,875,997,60,217,332,319,501,609,557,665,68,53,600,486,656,772,336,431,27,552,865,545,106,766,862,266,806,575,285,560,899,512,614,280,499,888,820,875,224,866,540,461,815,613,391,678,88,782,656,607,300,996,520,831,400,749,815,615,93,382,778,406,231,761,30,582,168,732,608,655,539,264,286,42,645,706,207,58,506,606,177,501,176,421,539,636,35,968,200,91,27,890,359,658,974,842,33,910,526,122,487,237,501,742,576,322,503,444,165,695,466,683,473,104,920,30,265,624,864,135,181,248,141,170,962,10,85,5,531,850,301,200,296,590,358,713,898,103,844,66,519,272,229,948,315,943,39,13,602,338,14,919,208,52,311,653,622,71,392,939,593,889,826,197,89,746,125,365,958,4,252,362,627,158,363,263,399,776,951,324,775,212,427,480,528,584,79,338,425,874,430,342,861,441,731,87,886,421,254,77,631,331,535,364,285,598,120,612,782,593,834,29,287,71,255,345,973,98,15,82,4,963,931,818,616,960,441,303,642,211,91,77,320,862,975,238,397,47,422,735,51,489,170,340,623,94,652,683,901,414,244,196,292,611,735,939,365,474,677,730,108,639,944,833,101,916,326,754,777,431,61,223,337,91,66,553,123,325,7,603,143,434,378,740,668,780,347,680,845,451,193,517,743,716,105,129,321,88,411,666,622,516,927,196,441,735,660,169,96,792,898,118,53,479,778,872,178,641,577,525,846,293,37,19,351,7,229,390,397,857,898,210,184,272,551,792,276,288,578,913,392,608,320,978,695,44,130,283,524,844,415,30,500,781,137,973,422,338,36,406,597,48,61,925,839,641,108,198,271,578,863,40,135,222,962,807,500,544,390,40,391,303,620,129,459,516,879,752,776,647,932,764,254,918,709,190,241,827,818,366,170,847,20,26,831,820,351,116,143,459,645,824,562,229,301,194,746,14,236,380,892,395,785,622,200,19,260,970,841,482,389,767,576,318,396,421,31,31,44,913,882,331,742,856,208,466,456,818,14,873,371,319,348,421,398,13,235,330,402,561,237,608,332,385,342,557,693,517,287,377,79,208,236,6,811,282,893,427,297,309,292,552,986,373,450,81,88,755,520,21,208,914,617,550,517,907,830,79,529,386,768,739,999,214,905,576,351,863,234,616,952,925,91,356,656,131,194,848,243,828,175,772,786,528,82,576,959,588,325,740,986,516,381,373,702,551,60,167,20,279,483,245,219,103,865,950,584,914,118,481,210,664,151,158,538,986,920,462,201,496,638,306,806,638,950,826,690,489,283,569,662,81,555,571,45,244,245,208,958,111,802,80,415,476,535,585,637,767,41,595,837,799,931,997,304,693,687,802,671,33,963,768,610,228,932,762,727,844,285,731,449,470,578,644,799,133,300,159,767,954,540,446,970,902,349,185,615,362,43,635,150,266,398,405,371,669,192,50,841,27,25,45,301,361,216,335,58,712,768,722,253,116,346,217,523,500,702,808,991,13,110,740,440,991,448,584,173,437,533,180,951,695,266,494,740,393,637,437,898,117,778,779,363,635,720,222,817,637,63,315,583,245,925,549,294,765,884,768,983,854,170,119,292,915,505,158,792,725,178,581,895,915,534,393,971,922,229,612,307,634,859,619,37,11,955,6,663,288,879,560,137,570,82,605,103,781,648,202,869,124,139,916,811,556,553,297,344,387,85,998,581,821,440,952,885,110,188,661,388,650,197,453,999,515,145,507,765,815,832,248,128,192,668,126,210,737,217,211,544,382,568,409,502,162,16,184,248,822,343,19,620,625,828,298,599,35,813,55,435,579,369,89,438,845,578,643,217,522,991,335,987,80,9,979,415,565,531,201,336,98,870,809,810,234,619,95,197,308,731,204,17,367,260,903,317,302,318,912,792,338,801,523,585,388,179,511,281,220,154,887,587,966", + "548,396,361,818,186,904,499,907,842,396,218,310,504,195,841,759,385,393,265,116,281,371,393,651,896,197,621,559,492,148,325,665,405,512,922,41,859,690,880,825,0,208,684,473,706,130,446,885,211,143,367,99,258,196,77,706,32,895,875,793,422,661,77,655,499,786,700,126,53,775,324,233,156,651,39,229,893,487,98,771,439,972,401,737,425,70,901,151,837,763,490,232,140,518,706,934,198,959,106,367,958,414,627,484,431,462,407,368,129,251,454,698,627,101,420,364,350,759,154,443,210,805,254,580,759,791,370,965,916,684,499,760,120,584,852,104,556,536,995,770,834,303,239,335,915,776,781,703,436,557,48,252,480,451,388,290,354,259,936,47,347,750,858,901,702,412,187,114,433,472,868,402,445,154,769,95,858,683,342,779,77,797,641,377,304,634,237,610,235,262,500,581,253,592,167,122,347,834,892,499,342,628,922,211,673,46,837,822,877,873,748,556,314,713,762,27,949,253,468,502,269,4,172,641,497,365,168,648,778,637,53,884,157,618,477,555,641,500,160,745,798,892,289,862,659,244,34,127,545,346,116,761,826,202,478,521,174,217,732,267,988,502,509,703,586,23,333,889,666,321,590,210,910,505,274,283,271,236,96,383,881,293,798,889,703,96,779,575,309,23,938,756,586,604,634,613,379,21,248,676,642,40,275,392,110,270,266,415,270,204,496,995,427,357,598,855,556,395,561,897,330,305,939,598,56,559,916,737,484,620,937,229,74,827,35,789,581,358,252,947,154,96,924,965,563,968,900,938,774,56,892,960,807,262,663,172,888,922,835,834,879,92,415,309,290,862,464,525,232,804,893,755,320,442,496,979,576,982,591,856,537,185,70,584,812,282,510,389,663,46,289,583,851,181,804,999,988,833,975,337,755,660,62,17,569,741,710,158,969,863,979,315,701,351,296,446,569,475,652,49,738,275,709,181,849,306,608,561,106,315,317,734,306,891,530,629,16,531,139,677,932,640,295,527,504,180,579,823,552,797,640,771,42,432,829,855,569,432,988,8,924,538,801,243,198,262,632,714,824,679,898,166,705,380,664,134,959,224,577,157,428,453,468,96,801,192,409,321,334,55,247,134,618,180,603,503,960,394,165,574,207,133,504,76,983,851,819,904,221,728,187,297,979,662,460,86,693,114,205,284,300,401,72,222,357,101,265,527,715,388,354,462,268,485,875,650,101,224,406,467,708,947,874,932,630,81,126,217,764,44,965,138,506,717,862,967,172,390,485,244,743,134,931,241,639,300,164,580,92,412,187,562,509,790,628,716,276,323,807,270,624,547,419,361,498,177,224,54,662,827,504,81,462,12,449,292,959,991,253,865,877,898,162,886,214,966,641,902,828,446,419,895,480,255,793,620,490,682,149,750,874,412,967,200,797,824,631,406,182,202,135,478,378,770,661,229,847,448,95,818,398,889,496,67,520,163,352,230,157,492,302,440,256,204,564,794,755,650,548,580,532,128,194,408,924,710,830,721,914,897,884,389,573,772,335,15,790,597,935,894,592,404,582,471,201,786,918,951,647,217,91,344,717,640,820,193,48,801,172,885,928,973,739,963,365,828,81,484,888,322,359,331,544,95,847,274,369,668,853,373,306,622,514,313,235,202,468,821,954,935,813,420,190,890,159,191,254,706,415,987,587,578,402,944,428,926,993,863,81,603,746,269,723,697,278,697,114,57,353,629,273,993,456,103,696,987,843,893,650,731,460,900,180,670,665,465,359,233,895,22,248,237,226,101,612,884,424,611,610,216,534,108,92,506,567,321,912,668,543,307,510,334,685,63,182,563,245,930,169,230,649,381,796,56,814,832,468,196,519,923,578,541,98,68,233,441,864,87,807,219,440,673,369,582,356,733,732,869,776,92,859,461,870,105,143,958,775,82,592,634,820,617,303,437,492,40,122,166,517,95,964,381,727,216,333,496,934,979,962,880,604,78,969,368,201,352,654,604,232,719,151,352,62,508,795,333,775,590,875,93,89,584,417,556,186,391,502,208,101,88,619,557,87,413,52,542,991,352,91,746,302,562,92,264,588,507,924,148,360,836,931,64,844,90,668,406,779,7,892,828,103,529,335,90,593,941,448,200,406,550,885,788,105,887,943,990,833,868,898,141,293,759,470,508,289,698,248,754,756,867,526,550,308,263,858,648,475,593,111,662,420,719,298,482,300,233,750,110,309,433,769,527,819,727,826,754,540,50,888,21,935,369,617,137,359,14,45,687,111,543", + "902,822,121,906,586,251,367,936,641,65,529,982,549,850,941,761,914,142,48,344,356,820,716,318,861,993,641,338,596,810,290,594,848,285,379,260,472,230,367,126,208,0,641,88,268,757,539,283,405,356,594,265,179,605,753,735,959,145,736,685,678,902,215,835,136,218,592,401,512,660,310,625,936,828,67,433,37,868,126,352,51,923,546,496,508,709,892,44,666,464,693,191,79,536,635,232,248,99,996,562,90,971,393,687,743,951,744,70,989,380,456,44,219,607,604,7,362,876,613,569,155,380,962,718,84,406,524,90,82,832,16,679,527,474,46,422,122,735,105,411,810,444,357,720,536,495,546,589,468,965,937,975,150,609,880,862,813,554,642,556,693,362,889,247,961,61,195,6,895,414,687,987,847,627,323,243,986,523,495,36,515,480,256,490,731,879,192,813,356,780,266,472,345,339,742,463,639,232,418,656,991,99,735,228,384,443,668,337,33,842,437,319,535,264,930,119,61,395,576,639,403,58,632,873,865,112,499,835,491,314,629,246,74,315,464,540,832,907,515,58,561,790,423,855,127,717,71,408,410,144,14,464,73,191,728,570,883,699,746,116,177,647,121,611,326,743,94,933,207,216,860,295,748,556,305,673,961,952,913,697,491,397,376,702,256,13,788,386,467,299,699,794,796,964,361,597,763,173,105,757,802,42,773,968,619,796,485,291,259,26,106,53,289,585,811,219,968,572,22,275,873,128,57,739,201,995,176,752,863,354,981,954,188,488,144,303,599,328,128,192,194,149,920,741,864,414,829,384,535,149,112,790,466,975,898,855,179,785,150,412,84,461,96,960,682,936,278,326,932,561,136,628,823,898,354,564,399,693,678,512,509,992,105,250,78,375,811,706,200,69,968,49,559,731,110,526,472,824,38,596,103,933,219,648,321,415,95,210,303,552,215,991,562,775,991,722,998,361,902,495,539,766,798,754,986,556,715,911,88,953,981,769,487,993,44,315,765,701,478,819,595,114,568,874,485,460,646,646,736,920,528,84,867,598,775,950,389,936,565,891,382,799,217,27,248,521,254,144,88,586,544,609,552,938,205,97,579,796,158,576,967,68,611,64,938,769,658,410,187,28,156,573,746,346,42,343,800,597,94,998,347,573,56,121,283,795,212,25,581,678,179,858,362,168,504,503,127,643,329,791,743,749,417,609,59,694,637,365,973,685,509,24,929,890,335,472,775,455,721,908,530,438,27,120,603,397,528,615,848,576,752,353,145,41,201,754,366,233,190,133,704,154,839,993,81,670,918,152,955,464,108,32,60,243,793,608,162,377,238,957,7,986,286,862,280,791,146,670,857,569,525,780,753,772,117,575,576,398,429,34,661,756,890,90,540,922,132,731,181,142,688,884,225,254,106,215,718,257,403,710,210,206,182,140,422,626,937,465,273,127,136,816,717,648,662,650,284,30,410,689,147,714,914,775,347,855,130,141,684,149,56,808,930,24,19,745,409,625,326,335,779,522,144,554,405,551,454,698,408,79,654,73,317,478,519,829,887,441,670,212,24,157,969,20,993,29,690,553,664,989,634,360,547,500,373,860,616,734,949,944,717,64,977,642,616,119,449,655,490,619,396,737,585,304,446,45,489,644,595,785,712,854,661,428,625,218,540,891,252,988,244,76,563,391,456,582,644,25,626,858,392,253,759,512,258,333,590,279,507,427,830,883,10,138,779,917,441,412,809,611,601,720,401,84,525,994,54,977,709,347,701,765,765,217,798,331,895,585,877,818,663,727,719,386,367,913,2,326,50,682,167,404,226,723,95,760,504,935,632,663,733,768,531,392,274,490,377,217,76,385,559,789,673,377,957,517,866,544,749,783,215,36,163,14,508,374,519,932,866,181,294,752,121,143,348,546,135,536,320,669,141,986,947,587,886,959,213,41,180,585,959,239,413,424,293,509,825,886,66,312,580,621,963,737,992,814,521,297,169,451,892,156,581,694,527,714,307,341,344,120,486,623,298,687,809,488,66,413,295,109,889,545,624,199,40,59,12,243,884,681,786,649,804,565,470,130,94,611,746,558,885,40,365,655,471,755,518,466,489,27,766,529,912,139,560,603,663,380,568,23,589,470,52,934,597,19,785,693,706,603,812,986,104,713,600,912,328,52,46,960,55,967,143,802,530,591,613,369,584,115,651,887,600,677,655,705,823,414,643,758,369,530,975,451,665,298,232,592,216,707,451,754,634,224,302,356,205,159,665,688,517,235,805,526,420,151,476,415,224,921", + "793,81,216,58,52,841,648,958,923,529,921,609,491,264,480,88,469,840,517,457,885,301,954,186,342,337,566,861,239,112,11,340,699,329,983,375,364,321,291,977,684,641,0,438,867,729,43,24,58,214,419,195,449,860,328,109,866,403,359,786,574,682,838,848,727,170,867,525,171,636,152,930,705,571,804,990,447,128,857,950,239,389,956,670,67,640,751,59,810,1000,851,592,670,790,230,549,991,369,500,465,173,35,596,698,308,651,823,119,288,453,856,318,902,452,726,929,920,15,6,886,947,37,423,766,88,400,867,422,458,686,588,502,536,635,927,12,252,241,448,926,884,965,307,455,197,511,132,303,647,83,686,152,979,611,650,642,609,75,834,721,980,235,694,456,901,677,505,281,109,478,337,629,322,600,4,364,117,989,904,902,532,790,490,441,876,128,761,219,220,214,636,560,410,288,828,733,576,928,454,107,106,424,160,158,355,273,835,850,824,852,53,4,701,166,777,119,801,238,284,687,345,309,125,643,413,320,278,208,20,165,356,221,339,812,817,525,439,265,795,646,172,696,572,108,177,557,317,428,310,509,232,672,3,349,767,589,829,671,994,453,876,312,481,565,270,28,863,710,861,779,944,106,322,853,120,648,675,346,779,179,388,934,904,754,499,527,603,775,644,335,934,937,726,68,723,156,794,32,388,63,458,300,228,720,566,979,770,351,696,292,589,104,136,10,843,833,118,679,32,212,789,501,326,374,934,678,84,943,38,311,59,190,78,224,544,179,984,988,625,953,31,987,876,239,244,111,103,281,858,659,426,331,234,693,218,873,341,559,913,494,923,213,280,241,636,308,693,417,653,837,685,18,16,723,623,74,891,62,614,630,300,735,638,883,917,144,515,948,643,730,535,790,308,632,114,897,148,355,198,476,148,445,483,273,693,331,486,615,490,508,607,254,260,930,169,462,545,711,889,291,244,104,790,824,38,663,464,676,3,91,93,263,263,895,335,960,35,326,877,98,494,574,801,713,285,332,652,723,774,525,275,310,23,322,346,194,41,635,190,968,597,10,132,406,116,220,845,217,729,181,825,315,937,518,539,130,436,38,583,428,430,173,865,208,967,169,321,814,262,266,33,667,89,934,864,29,870,801,96,197,407,577,919,865,455,185,864,747,434,923,155,642,153,614,316,925,266,626,12,600,644,441,198,37,268,662,779,618,537,110,77,297,889,830,980,191,263,42,498,21,120,148,273,316,427,725,830,937,127,241,966,96,153,509,951,171,268,188,386,223,150,318,747,838,638,790,164,560,476,69,121,756,53,385,207,830,533,250,992,478,210,947,516,808,392,911,139,911,157,972,274,191,185,265,387,182,151,531,290,424,700,116,410,162,42,622,557,979,74,705,891,791,978,108,728,145,795,389,602,21,748,25,410,306,600,419,919,445,905,900,526,100,606,970,860,918,709,928,105,526,138,361,181,843,11,927,22,26,972,326,268,10,34,262,963,173,312,422,521,477,888,787,973,265,382,519,820,656,765,353,214,91,983,739,990,520,55,543,829,418,323,677,96,516,856,46,416,335,881,911,814,247,82,128,110,704,954,43,846,709,228,792,227,337,373,756,7,605,311,622,649,863,789,131,756,500,988,26,985,944,154,344,94,586,917,522,588,498,791,928,550,664,354,345,668,734,718,176,800,233,610,313,777,332,358,650,109,609,257,607,48,557,520,54,85,153,345,170,350,908,304,874,699,849,929,223,998,896,725,101,392,887,661,737,740,391,764,190,75,266,720,258,916,395,634,347,403,504,297,517,939,569,244,813,655,831,303,81,496,202,320,522,131,242,57,919,885,56,231,693,565,974,852,603,87,573,419,750,797,624,421,364,301,530,120,729,804,787,836,417,535,278,346,445,222,613,864,784,309,403,439,986,643,854,944,2,522,274,717,834,215,821,936,860,553,845,606,556,891,167,10,208,924,153,839,346,884,361,201,476,271,37,992,942,918,140,895,502,306,137,983,527,553,639,672,515,628,652,903,63,896,150,313,620,603,616,312,289,343,840,986,399,161,615,795,640,821,985,465,232,397,698,544,350,426,972,644,3,850,506,293,60,684,21,463,598,217,782,640,138,295,387,690,209,81,937,321,706,556,54,824,220,838,328,432,910,628,164,98,986,239,110,1,386,501,829,622,722,195,955,9,154,776,111,819,857,395,766,976,655,25,224,83,735,689,461,587,180,840,197,636,537,653,361,796,225,415,27,427,97,866,650,824,478,142,20,675,715,595,590", + "563,117,819,492,700,175,899,437,117,612,751,630,280,354,554,361,58,240,758,957,459,912,364,953,433,764,324,311,16,360,445,115,379,674,956,99,502,896,800,599,473,88,438,0,752,566,320,297,213,597,810,563,743,121,71,497,4,551,788,167,73,421,90,402,435,989,509,423,285,285,698,648,871,1000,896,534,492,148,342,385,816,986,443,449,219,69,990,606,903,788,753,132,756,582,918,980,205,220,484,395,473,318,27,914,783,912,51,620,538,16,579,327,626,946,406,223,898,412,360,848,981,544,83,625,335,423,636,969,945,865,187,890,794,538,57,90,255,919,455,310,539,738,787,954,994,851,803,469,285,307,790,998,121,535,249,38,180,235,899,757,636,955,498,757,535,215,330,428,608,139,653,119,126,830,688,377,479,262,138,243,536,853,73,139,711,431,760,357,900,742,761,540,240,852,239,91,821,351,558,85,74,195,682,873,597,107,172,561,908,721,865,87,193,946,977,32,375,605,205,739,714,179,339,818,714,334,678,294,320,638,901,430,331,852,4,493,743,435,390,237,298,202,941,215,422,883,444,173,456,828,248,750,343,810,538,273,442,502,130,458,568,779,188,502,920,786,224,370,469,619,603,780,73,897,528,406,579,400,871,756,354,412,728,608,484,824,606,292,902,47,463,433,526,348,563,88,714,465,462,91,435,135,565,232,769,320,913,80,196,642,796,247,176,21,446,610,156,8,22,654,28,225,632,259,478,189,240,705,768,958,9,929,172,99,163,411,619,28,492,818,327,342,303,241,205,440,614,55,713,517,262,398,974,607,928,755,628,308,396,408,723,264,883,84,699,231,684,975,765,110,513,53,399,395,535,712,386,27,977,203,694,629,286,772,740,899,676,382,495,300,870,554,734,919,98,669,457,539,609,416,62,236,627,168,188,246,791,697,283,945,285,472,95,749,97,423,665,321,446,497,692,893,428,728,613,490,75,627,23,991,267,474,83,75,637,390,130,512,133,846,223,72,448,84,957,401,497,954,711,560,608,849,432,352,271,916,682,810,805,761,330,912,313,456,894,583,725,875,878,412,54,145,826,114,574,338,389,712,913,208,840,159,346,359,892,476,689,264,537,986,249,947,947,17,634,974,225,540,441,289,202,519,356,974,643,253,989,422,141,621,362,707,940,356,929,499,193,751,506,427,255,792,283,414,319,82,446,302,671,293,346,881,557,386,961,933,292,22,619,313,819,231,293,710,47,311,453,678,459,935,191,230,220,464,354,753,987,689,362,632,867,174,919,355,702,499,140,405,273,426,337,661,551,794,218,658,973,800,185,105,592,708,625,201,198,600,19,3,940,856,311,288,895,749,30,68,83,404,604,359,699,603,991,841,613,415,671,841,970,851,846,516,694,602,454,538,534,279,433,446,285,405,898,257,846,776,535,602,567,306,551,406,216,198,972,643,591,549,242,978,82,516,679,543,849,121,300,520,33,19,343,964,876,503,283,494,768,742,876,21,284,882,872,639,460,527,219,84,600,640,592,200,345,35,174,912,517,298,996,370,740,662,706,736,312,728,967,567,767,855,946,178,266,518,30,742,217,877,535,270,566,739,428,113,418,183,341,123,232,449,508,859,255,803,813,94,815,443,297,602,913,106,941,268,440,680,14,982,215,560,649,489,230,136,837,970,738,896,559,460,140,549,346,762,735,165,361,495,130,756,876,508,980,765,382,146,249,968,936,821,657,492,436,746,641,418,38,168,977,575,271,288,20,261,526,801,364,228,229,104,132,680,833,457,918,939,335,342,709,609,743,370,15,601,50,710,685,267,399,332,779,594,844,26,756,878,122,10,297,62,255,747,425,824,611,14,309,961,572,226,526,745,59,172,850,286,934,769,858,809,988,861,763,982,616,919,847,988,897,764,404,743,75,531,951,739,303,493,89,416,583,336,155,599,103,455,242,55,840,881,326,717,839,600,785,121,947,211,28,993,366,715,513,7,476,362,108,742,906,595,810,154,512,889,683,428,932,930,996,41,661,711,67,562,851,269,692,400,613,337,524,858,378,27,765,702,96,696,801,917,761,814,286,416,742,690,498,840,487,911,92,225,484,452,895,244,689,370,817,260,175,183,845,167,133,58,316,855,926,95,303,426,151,862,493,87,845,155,876,980,350,314,667,798,899,973,82,948,833,288,811,491,288,198,727,141,973,384,270,793,379,9,59,286,252,744,450,231,313,674,374,308,253,974,56,568,602,79,1,5,141,815,371,459,23,997,387,259,91,967", + "318,114,304,863,83,504,319,991,654,196,224,633,220,217,262,216,706,51,431,671,93,686,180,242,219,233,468,617,265,273,78,195,648,956,176,406,573,269,380,271,706,268,867,752,0,959,664,268,830,946,536,541,953,851,468,50,828,534,94,452,300,576,642,695,641,548,157,42,105,384,508,566,880,729,329,454,522,408,426,831,42,622,65,313,472,942,656,175,217,421,684,642,336,912,475,987,684,399,958,719,73,115,525,35,488,511,122,228,764,343,509,211,266,645,199,735,219,290,502,515,497,80,938,995,168,764,656,54,18,108,515,153,743,974,670,776,316,274,53,948,669,772,43,730,583,614,853,584,924,581,589,775,168,642,427,461,176,515,136,809,725,984,818,357,269,433,177,910,110,848,188,661,929,533,116,307,671,111,255,8,587,945,438,397,840,935,140,230,181,299,603,714,486,954,737,747,923,794,828,343,141,429,953,311,264,146,938,416,351,239,510,4,298,242,1,602,813,577,738,626,251,950,811,275,476,945,447,702,53,927,442,252,681,213,403,245,344,789,735,331,672,470,510,396,269,717,282,145,884,561,715,248,498,439,673,59,776,307,379,603,501,552,977,34,551,304,222,84,561,586,79,944,243,261,548,661,801,277,663,393,291,472,52,707,244,869,327,130,569,302,920,349,220,517,586,966,907,225,519,921,608,531,25,482,557,465,97,680,64,837,758,33,396,551,218,715,718,547,741,70,552,866,472,33,715,1000,899,816,371,490,251,208,34,327,176,212,578,242,211,100,44,562,236,635,55,703,600,533,699,791,952,800,945,377,615,740,849,476,444,750,445,425,66,2,878,495,665,638,383,402,73,420,451,153,280,489,892,842,973,579,625,204,228,170,611,683,510,364,637,890,607,502,3,767,646,161,260,909,403,641,342,303,641,63,765,167,790,488,276,414,873,389,500,227,746,74,166,966,541,331,686,447,207,69,152,396,958,3,190,17,386,205,744,746,517,132,381,750,412,908,183,945,813,902,34,357,341,915,969,325,606,24,257,858,721,145,776,449,35,513,65,34,261,453,571,922,1,828,775,464,68,332,874,174,474,273,18,835,218,562,993,267,329,294,940,976,875,499,783,101,809,497,703,437,539,554,605,879,992,124,978,553,679,66,338,463,321,494,190,209,841,413,269,769,158,50,825,458,281,507,207,610,504,120,975,448,193,826,978,134,687,283,740,768,835,810,531,652,380,383,172,171,818,676,578,207,447,469,787,326,649,348,138,116,591,271,564,397,416,882,938,798,491,609,869,21,483,175,944,591,765,301,737,252,541,226,442,286,932,425,570,575,188,493,112,806,869,637,968,335,874,691,377,610,134,91,784,830,45,714,563,664,277,429,89,322,207,605,405,307,162,77,452,411,995,181,386,648,983,896,684,670,559,375,156,986,463,642,143,433,13,883,475,67,384,932,96,36,884,308,929,402,889,211,474,579,910,285,499,419,445,996,286,897,910,804,90,764,962,724,31,131,134,741,701,291,864,372,662,585,625,70,224,24,693,83,555,878,303,475,827,613,825,564,193,60,601,644,592,796,830,601,969,960,571,470,507,917,631,613,234,814,666,174,704,456,198,162,196,187,311,984,778,627,245,309,346,636,439,484,188,541,655,444,568,935,696,464,849,446,408,27,571,305,801,96,546,911,474,592,32,840,716,427,302,472,600,908,619,846,420,77,68,430,280,591,108,46,76,993,272,107,868,188,675,704,894,291,117,485,781,145,781,124,287,505,981,928,29,949,835,5,16,598,706,735,234,205,48,794,346,7,283,217,783,358,559,289,584,472,182,139,333,764,74,993,633,764,96,478,980,92,493,262,128,635,429,517,299,924,120,822,317,730,907,120,33,873,982,137,834,544,128,550,59,567,481,140,499,972,297,922,415,392,355,922,318,381,753,763,371,334,506,3,154,805,34,826,92,109,503,618,315,24,388,175,628,772,988,790,237,131,679,122,274,491,134,51,812,213,887,894,841,231,384,350,779,181,355,325,386,130,864,870,954,983,919,937,474,191,156,344,82,625,489,173,351,244,445,895,84,580,856,256,805,436,915,703,873,447,41,345,386,100,703,603,376,121,657,701,383,165,716,527,532,693,187,379,883,187,22,742,565,385,823,379,35,654,338,702,831,283,814,914,520,2,352,394,299,542,487,282,921,587,94,907,134,336,453,755,488,731,909,77,387,756,974,803,259,715,72,43,65,399,404,226,342,146,191,576,723,305,125,831,447,465,811,474,714,536", + "311,950,475,955,981,116,175,17,955,130,543,802,347,256,675,196,858,446,775,801,317,86,31,868,528,377,154,37,809,168,904,834,93,121,705,593,351,479,358,612,130,757,729,566,959,0,6,724,543,988,115,77,57,895,461,937,927,240,577,446,911,730,121,10,666,706,829,350,574,223,597,242,84,744,143,320,905,56,970,226,730,847,430,181,909,747,484,314,293,88,145,787,829,321,109,713,80,751,677,343,149,465,147,230,414,359,135,152,210,493,857,226,756,687,951,319,492,302,645,746,643,244,891,93,65,314,731,612,946,72,363,993,738,322,149,146,57,563,271,613,419,245,753,322,614,785,24,180,286,790,673,665,709,70,434,178,251,435,978,154,381,586,216,602,24,14,203,459,250,873,932,820,282,884,361,649,824,783,740,139,210,637,573,876,580,531,725,977,958,190,547,14,329,885,23,282,627,863,816,542,764,504,221,711,465,898,568,459,392,282,952,85,994,832,846,627,951,725,172,456,241,270,277,755,743,73,551,300,755,858,909,418,729,676,529,840,799,718,130,363,119,937,484,974,572,548,895,771,477,444,416,548,839,866,944,507,960,391,601,922,828,419,384,92,976,986,914,793,277,790,936,846,947,26,911,872,39,137,827,227,82,664,862,470,578,452,784,89,205,896,911,88,506,62,626,653,887,498,963,44,929,638,867,301,268,150,723,928,922,333,41,687,161,336,672,688,647,973,201,692,176,825,270,716,643,71,241,974,881,835,551,747,718,705,917,824,908,286,391,905,854,697,123,46,506,470,522,883,70,615,972,501,869,404,331,689,719,306,861,678,27,942,66,603,514,645,533,337,44,185,681,156,292,251,534,834,388,763,890,530,617,827,800,151,226,335,884,395,86,101,871,366,23,359,757,174,811,828,361,53,21,988,910,802,529,834,831,833,108,560,317,917,453,305,148,917,733,36,260,498,913,757,319,87,203,304,311,955,708,388,739,641,126,124,16,706,582,60,24,904,846,820,606,823,932,6,935,715,705,142,41,143,419,373,992,13,617,518,148,624,292,293,459,640,59,644,23,176,109,381,43,142,36,542,61,990,153,414,969,190,255,554,767,523,74,259,501,118,735,874,261,643,629,478,483,32,2,729,440,431,258,669,708,679,559,336,384,487,400,510,910,700,704,346,686,953,944,617,935,448,263,935,77,915,74,441,870,110,28,878,962,180,203,776,773,609,6,405,235,168,80,848,211,782,282,716,656,956,360,886,94,469,941,188,673,968,298,843,892,363,710,400,378,477,71,656,610,427,635,946,521,363,873,144,176,939,11,58,150,564,31,717,480,300,58,722,848,176,89,760,589,428,232,345,89,114,487,655,584,174,802,543,178,778,811,925,457,322,19,358,8,664,192,674,381,107,947,911,338,804,908,510,710,190,16,581,804,747,615,408,32,570,261,523,998,181,725,396,920,18,541,661,670,407,124,243,513,419,336,935,965,684,691,299,142,711,209,33,826,788,798,818,765,900,730,261,6,907,751,630,334,473,346,846,184,432,276,921,908,553,781,771,148,295,613,967,801,39,375,36,836,386,601,486,26,153,699,768,631,653,471,537,758,747,652,476,768,612,259,861,398,548,157,35,332,27,896,514,736,453,561,463,958,21,598,333,843,906,837,250,916,81,325,891,145,790,621,70,577,219,858,240,911,675,450,774,538,126,126,14,258,50,909,486,560,706,254,906,653,320,758,310,195,663,85,801,444,861,193,108,288,307,959,796,215,4,731,332,14,895,604,178,401,389,38,787,684,902,638,104,562,570,942,864,352,878,5,251,824,828,8,801,595,321,232,454,41,435,898,904,233,121,130,333,713,483,452,663,449,671,832,207,86,72,305,743,46,953,542,458,196,204,795,714,772,417,72,29,191,553,423,285,461,937,404,92,690,979,994,65,671,146,97,767,510,451,768,73,385,740,738,750,618,518,815,40,402,955,619,107,643,608,126,628,431,727,993,807,985,651,724,361,772,444,159,782,965,407,517,721,815,159,157,169,280,577,838,249,328,600,859,980,975,975,686,920,434,538,465,727,125,671,646,368,712,625,630,921,607,760,481,863,288,260,848,850,384,303,219,337,58,895,806,116,307,505,770,484,881,135,325,893,365,675,255,958,552,614,389,352,225,533,683,581,444,260,786,5,542,582,5,308,25,327,226,693,452,890,620,926,850,669,825,259,254,163,989,707,164,332,649,514,424,719,447,257,246,252,400,820,497,172,307,4,326,542,846,547,733,647", + "579,786,74,503,733,242,223,26,690,591,129,420,268,39,654,886,307,53,101,139,449,206,116,322,849,70,792,53,732,723,992,240,218,655,159,307,181,951,7,352,446,539,43,320,664,6,0,878,543,871,960,864,898,314,371,263,859,100,427,343,591,541,42,786,982,982,776,774,430,83,332,530,357,385,245,895,887,445,716,433,990,542,205,931,693,618,140,524,813,808,204,704,685,599,528,963,262,337,700,766,965,673,34,159,145,681,634,789,656,554,669,349,760,823,766,99,71,353,800,267,616,256,134,286,153,300,546,78,996,117,304,54,884,808,617,47,932,767,571,391,768,694,86,639,392,76,397,674,603,216,723,812,155,343,514,993,596,976,120,306,190,680,666,3,435,541,678,888,803,649,94,961,20,760,979,643,888,384,917,802,35,346,274,146,663,913,105,838,348,152,543,956,811,419,879,481,197,514,765,525,665,134,514,295,493,686,731,354,987,857,485,475,966,706,21,841,382,665,533,184,432,345,677,493,111,129,89,920,917,515,346,711,552,85,390,375,715,829,995,600,237,803,558,395,736,861,198,477,843,470,255,945,964,888,883,977,64,326,999,979,499,268,457,551,482,113,23,556,759,87,524,100,114,793,221,555,525,846,442,998,160,841,322,986,807,877,398,542,815,244,300,747,49,110,11,703,193,537,161,655,223,437,928,978,494,199,340,31,45,592,92,899,330,962,889,10,409,517,48,994,932,850,507,244,356,695,70,62,397,723,40,977,731,652,768,698,485,725,92,317,532,165,133,481,807,137,592,103,263,820,618,84,799,557,194,527,872,459,100,968,916,110,209,18,793,777,503,242,297,588,671,948,464,638,590,629,577,494,680,560,681,393,182,551,57,125,933,753,268,456,126,557,891,444,401,659,158,24,392,551,523,437,550,796,244,289,355,556,906,173,208,782,801,563,173,254,515,57,487,603,234,524,196,770,505,716,240,974,827,309,678,598,165,188,60,389,180,167,842,111,310,631,451,231,969,164,150,917,757,801,354,808,319,590,560,27,349,676,314,960,774,562,790,139,564,939,992,803,684,149,474,404,159,63,228,43,879,334,771,82,970,595,872,870,932,481,165,100,426,482,383,579,803,147,310,193,881,372,840,159,820,472,2,18,810,762,624,731,287,293,642,366,485,718,836,135,584,154,729,142,987,601,281,54,42,891,614,815,3,144,31,700,75,618,281,424,450,624,602,829,752,235,428,331,660,512,841,376,789,999,979,452,767,733,243,742,479,149,598,694,774,13,582,325,570,976,19,950,172,454,831,487,146,646,625,869,909,378,772,806,807,815,923,903,511,361,295,363,888,546,645,428,270,618,386,128,185,287,223,21,652,174,69,770,119,642,467,381,430,551,513,367,956,989,594,106,559,257,170,794,808,328,691,889,775,781,90,283,322,78,315,228,539,503,195,117,525,670,203,576,967,886,454,51,35,348,832,965,291,942,969,78,222,42,565,503,400,516,517,283,564,813,840,677,259,273,930,958,691,129,964,957,349,243,783,862,360,453,996,844,882,319,639,635,568,911,520,260,964,959,729,160,900,104,649,779,908,159,389,887,959,857,352,560,490,354,584,848,749,292,442,852,85,329,875,435,893,135,364,259,886,710,152,452,562,755,664,654,635,100,575,610,44,723,451,593,853,904,580,555,141,299,21,616,686,292,503,932,779,807,317,4,27,837,437,95,446,811,86,935,125,111,763,561,924,336,540,715,133,596,806,884,950,51,598,617,332,684,736,970,699,867,428,175,377,309,161,257,84,818,607,460,482,198,70,936,548,846,17,818,373,318,192,893,13,79,821,455,624,106,901,432,793,302,933,787,807,627,998,668,175,860,130,918,729,529,216,280,148,142,445,143,686,437,40,885,938,414,544,558,381,286,977,671,754,957,687,776,272,957,480,732,150,847,238,233,902,301,897,728,238,493,999,171,810,826,840,815,623,183,950,109,15,322,552,861,432,713,615,319,281,543,175,606,388,863,98,886,20,253,996,449,890,800,700,52,193,714,409,756,726,980,331,4,429,773,30,157,996,717,37,317,600,754,933,927,62,185,561,215,845,974,24,591,875,381,445,508,617,632,217,801,471,373,315,314,905,71,969,92,425,985,481,242,904,422,589,243,527,29,882,491,930,853,797,628,225,942,214,269,326,816,272,249,174,440,396,9,6,834,82,945,820,333,749,124,866,606,866,493,244,743,888,469,988,976,342,508,320,339,746,317,426,878,748,885,942,9,126,303", + "58,101,324,775,396,248,988,520,491,875,72,952,486,184,65,340,636,749,841,906,469,212,597,603,703,102,470,659,470,779,30,860,473,534,602,816,496,740,279,534,885,283,24,297,268,724,878,0,954,597,947,566,935,507,285,939,574,729,932,68,722,984,385,833,142,311,526,407,612,932,686,867,36,634,818,58,877,334,932,151,520,315,194,554,915,579,450,146,852,833,731,701,168,826,204,450,367,998,372,548,419,242,148,83,378,378,656,215,764,816,245,342,684,289,397,792,411,968,855,884,684,279,183,459,105,226,422,140,800,934,827,590,63,814,438,398,407,4,420,889,479,727,952,261,61,826,742,536,995,996,737,952,156,899,126,664,732,947,223,986,931,385,412,749,734,237,299,512,992,876,89,160,518,446,556,430,775,431,407,672,150,882,260,972,854,416,83,692,305,396,578,85,196,939,384,506,310,381,901,980,350,10,368,520,98,518,761,690,462,476,982,979,752,821,358,712,791,998,415,221,26,613,23,1000,725,531,400,954,365,585,107,853,92,395,825,543,949,569,110,542,982,566,611,466,716,348,873,542,602,502,972,305,354,116,149,421,917,464,233,256,264,888,304,608,895,950,443,431,381,144,817,604,239,817,797,299,534,334,810,917,815,858,861,671,474,845,305,773,808,902,596,330,38,826,777,804,651,592,521,556,942,75,137,93,416,651,277,53,340,217,862,466,497,470,178,612,451,304,114,277,435,96,955,947,5,303,832,622,944,670,415,497,426,319,736,684,599,569,248,991,899,702,611,825,310,224,630,215,725,233,84,84,18,252,399,304,524,987,237,262,982,679,360,377,99,478,999,919,5,674,936,326,426,361,76,232,250,560,350,983,338,66,992,149,237,16,183,475,41,974,886,424,647,864,203,437,361,608,123,834,137,925,273,100,6,815,282,175,30,839,512,806,845,375,303,197,354,339,544,949,34,917,361,179,605,55,644,475,550,632,618,768,203,116,111,148,622,261,173,190,695,771,287,429,45,489,758,882,410,610,677,631,367,803,94,898,894,472,374,950,308,795,799,177,218,194,523,432,823,138,370,868,806,193,943,39,212,975,87,423,579,189,440,516,983,690,568,740,717,177,430,624,494,611,494,771,651,894,642,685,668,974,877,904,590,979,478,469,255,635,552,525,221,963,45,915,476,326,962,298,177,935,537,909,928,651,221,251,367,393,652,750,105,48,863,611,883,706,620,545,790,138,374,162,47,23,787,999,458,561,675,454,994,5,11,939,559,773,703,448,180,205,23,653,183,749,672,185,586,411,661,408,93,62,795,16,794,867,319,682,266,181,931,752,398,53,724,602,922,847,683,586,370,57,86,634,88,86,906,908,151,19,480,807,142,825,71,83,24,50,153,540,603,848,459,654,870,986,248,3,870,598,727,325,353,153,19,45,669,281,493,761,579,390,632,128,72,667,344,525,661,164,832,790,549,340,690,805,572,490,184,516,196,62,242,784,939,893,687,968,782,109,971,506,544,790,865,242,847,235,954,802,595,289,654,576,788,539,785,916,287,490,991,100,229,83,814,844,161,237,114,406,333,982,756,164,112,885,303,545,157,618,726,994,271,660,444,826,970,746,584,443,120,254,780,726,684,36,988,671,904,318,555,714,295,484,553,386,666,424,590,782,864,341,461,186,149,792,489,376,808,452,379,469,554,292,597,348,210,759,283,993,56,152,937,675,46,966,590,374,247,293,556,625,877,525,300,664,152,737,165,410,689,643,665,817,701,928,981,421,44,256,369,741,427,397,978,543,564,144,656,693,30,207,511,340,365,268,258,940,235,127,676,31,439,886,563,929,472,646,866,15,355,568,42,723,171,750,666,46,866,769,194,530,933,828,91,436,665,196,504,250,429,948,233,337,794,355,879,286,605,791,404,906,297,773,23,599,76,912,384,747,575,642,444,937,771,404,658,485,165,363,161,234,310,721,630,955,935,571,884,685,136,893,469,380,13,236,244,337,798,67,73,231,534,98,389,558,603,774,781,870,89,105,679,945,313,494,937,703,44,524,125,828,78,541,982,949,618,381,404,66,507,169,402,761,250,975,789,611,764,928,624,285,742,740,917,630,970,14,863,932,745,536,32,783,419,798,174,153,436,786,424,865,423,447,520,821,867,776,885,886,124,924,959,304,184,451,339,638,986,798,592,849,144,719,328,693,193,955,678,663,214,380,599,842,61,486,979,21,820,944,498,370,192,352,388,78,165,133,590,927,905,281,352,941,920,953,292,665", + "145,888,59,396,915,794,808,62,962,15,529,8,9,807,908,312,277,512,59,787,118,1,499,543,763,425,65,525,156,511,398,740,398,857,29,240,790,713,299,649,211,405,58,213,830,543,543,954,0,120,144,121,842,607,660,504,730,305,31,626,434,987,994,786,590,488,994,505,801,246,509,266,241,253,644,804,462,110,628,505,939,917,615,522,916,142,64,692,7,564,438,636,305,23,157,310,414,264,472,536,140,26,562,135,169,18,185,569,721,704,898,581,825,663,58,9,535,55,964,816,134,606,246,403,87,782,754,184,906,604,751,336,486,51,707,915,94,202,505,370,381,289,748,509,34,584,372,906,718,155,204,894,159,771,714,320,299,540,518,93,458,639,715,140,556,79,558,551,220,544,269,290,976,111,624,591,566,760,742,832,63,553,889,431,831,258,557,70,150,803,700,571,636,126,294,112,88,141,825,321,789,272,838,926,308,400,825,180,751,665,81,165,100,602,429,488,853,977,133,732,598,203,826,753,878,940,763,989,427,656,660,44,230,999,754,928,751,504,772,613,176,893,745,410,886,589,86,285,384,257,129,242,495,412,988,699,378,991,360,767,492,160,396,227,996,350,984,165,560,329,957,790,458,140,571,730,568,628,259,978,126,421,240,713,818,649,800,443,993,594,601,841,134,705,564,154,849,331,417,3,266,592,920,340,124,989,707,840,288,104,737,945,843,605,352,239,469,269,609,449,107,817,568,439,440,509,196,224,229,189,424,448,27,308,242,409,212,109,462,954,453,670,253,152,159,629,630,912,989,578,349,299,65,976,58,69,262,641,999,484,981,255,424,745,432,161,823,965,843,987,577,133,498,203,730,555,170,266,137,937,278,303,359,116,657,231,618,343,645,923,469,63,701,83,197,379,140,656,599,368,109,14,46,453,825,69,892,414,112,815,101,837,15,52,955,935,885,534,404,659,909,748,131,756,494,836,448,474,459,46,332,522,813,827,38,719,990,699,97,89,88,369,926,530,618,268,900,283,575,250,256,346,46,875,177,132,31,898,478,849,469,259,207,770,705,782,581,702,250,521,6,784,18,893,249,653,95,464,34,287,128,531,379,160,579,408,51,598,52,535,251,748,71,910,669,586,401,353,182,912,47,759,296,208,212,414,739,835,713,23,407,73,529,101,852,655,786,49,838,352,257,148,887,105,10,346,286,162,305,440,989,564,392,447,100,626,777,874,280,185,508,193,659,245,212,723,397,735,475,558,742,432,768,196,557,435,801,139,630,217,608,993,825,73,243,429,827,481,319,43,561,835,672,109,661,344,307,437,839,61,618,739,215,792,836,108,894,634,793,402,653,756,44,683,696,346,82,233,73,510,378,917,67,257,733,359,110,269,803,854,801,967,880,225,847,355,182,662,84,407,338,789,269,830,30,755,875,828,697,22,723,403,73,729,888,60,556,347,316,173,667,145,94,650,491,307,674,941,760,510,255,716,754,518,228,416,781,643,844,447,709,942,590,691,53,513,109,658,802,847,409,782,262,741,797,826,525,863,431,75,441,703,669,318,917,762,502,887,171,422,888,572,76,304,796,607,718,784,852,341,251,580,233,390,833,976,521,411,667,618,237,796,521,494,23,618,479,343,751,778,299,382,393,458,390,368,83,200,467,363,302,356,309,839,276,804,111,870,734,670,143,455,899,13,974,30,726,706,68,455,962,738,768,149,131,206,616,729,533,686,323,489,454,381,221,386,991,256,595,683,767,10,318,772,789,354,655,491,574,179,870,70,952,32,435,798,213,87,742,291,555,154,773,428,201,621,398,769,412,398,827,534,359,729,142,202,852,783,624,543,261,333,215,871,782,448,860,191,783,380,7,453,608,729,477,60,284,642,28,13,384,472,176,414,496,360,166,816,667,305,864,851,244,592,982,120,278,365,860,646,843,39,576,825,843,207,325,317,489,655,365,450,724,496,959,655,513,659,214,721,865,827,369,282,13,441,115,514,622,204,746,867,896,416,799,631,868,329,923,828,503,428,572,33,160,631,952,909,793,763,387,463,940,388,590,360,736,877,542,431,406,126,660,399,770,355,132,608,492,387,836,656,834,112,50,937,516,30,186,965,893,699,137,400,331,144,439,102,309,246,591,239,705,2,973,454,320,62,348,690,332,183,121,469,676,104,318,960,332,500,476,636,293,804,660,657,642,763,273,712,16,489,139,103,547,703,217,953,192,522,152,7,779,96,191,695,413,562,641,722,642,717,325,382,535,137,924,388,888,776", + "304,750,349,520,102,281,296,551,786,187,848,600,299,183,547,440,311,341,565,718,909,443,229,476,327,306,824,153,464,273,35,164,771,147,494,12,304,401,800,208,143,356,214,597,946,988,871,597,120,0,676,502,739,122,757,469,633,597,41,405,468,844,833,882,61,303,311,633,845,962,279,929,861,321,730,239,620,591,602,637,908,466,279,737,671,976,754,190,725,576,536,503,441,352,670,428,548,302,619,309,10,575,299,458,834,823,101,191,568,444,920,335,545,426,436,481,814,122,73,153,324,801,623,257,410,506,310,232,569,213,115,760,311,452,267,585,247,765,765,436,775,745,639,254,760,726,697,517,785,256,652,395,425,136,977,476,578,360,284,576,977,693,578,37,529,316,369,319,3,254,767,798,511,921,902,641,84,477,72,985,107,594,931,776,219,570,402,912,86,371,138,484,350,953,500,393,719,414,481,903,234,983,665,641,354,314,461,384,678,319,658,566,896,539,551,545,464,928,908,964,81,527,250,529,739,648,126,785,787,483,607,22,896,764,778,574,188,453,589,4,445,477,536,686,14,709,858,624,656,28,661,59,456,376,917,643,524,6,219,789,485,813,513,120,622,994,11,538,477,303,877,192,686,505,385,606,983,160,773,506,796,884,883,297,984,298,131,557,58,991,133,298,236,369,73,367,980,391,937,87,155,677,719,276,513,495,732,614,960,988,185,3,105,677,718,699,87,721,999,948,427,170,5,253,268,328,151,349,164,43,246,111,753,969,566,774,757,762,441,330,262,625,702,419,168,311,198,724,516,774,36,444,272,943,157,391,454,109,107,251,936,801,796,547,295,456,200,992,40,768,948,877,942,706,327,424,856,22,21,807,80,575,927,770,619,671,733,304,623,340,282,725,375,71,441,631,891,157,309,783,267,952,396,963,806,553,247,724,14,59,549,942,110,880,558,165,415,626,222,91,943,507,397,427,856,183,238,392,330,766,552,68,766,558,211,994,491,755,494,583,848,805,124,379,487,369,879,180,385,757,762,958,347,124,477,706,673,710,142,131,146,260,921,918,457,55,657,810,269,104,533,883,851,944,671,296,821,648,625,648,530,673,465,474,693,38,887,508,395,940,197,678,443,755,363,672,740,683,307,607,152,472,691,793,167,994,352,575,693,153,526,444,954,287,358,206,204,151,209,972,687,246,262,29,737,508,894,813,244,731,960,127,194,899,943,924,599,490,542,646,27,691,165,950,802,675,390,680,827,631,981,301,656,778,299,902,65,307,131,106,249,53,544,319,228,527,964,731,251,893,671,283,241,719,608,497,244,256,268,661,462,639,846,112,337,195,563,707,592,712,935,631,11,559,509,502,363,230,211,56,966,319,35,463,489,3,227,837,186,939,418,312,432,995,268,116,871,344,922,996,430,999,737,827,866,986,452,818,646,432,519,411,747,603,228,424,570,749,837,607,335,929,205,12,628,580,921,177,998,359,22,565,718,842,563,748,353,631,772,273,376,806,561,538,218,8,756,93,322,964,304,874,790,495,918,831,615,380,428,353,467,1000,352,309,698,359,766,260,480,545,97,358,115,623,249,907,868,809,1000,409,26,968,687,876,495,233,21,552,429,254,473,927,853,967,976,665,306,923,34,884,724,416,296,899,681,543,708,657,572,249,99,117,784,352,564,804,718,890,781,835,316,563,897,312,274,436,953,677,611,191,463,485,814,143,628,54,801,735,307,302,808,720,190,751,484,8,984,773,960,966,579,515,797,897,376,106,321,985,2,376,167,212,317,28,670,400,180,567,548,542,21,951,435,937,954,155,906,244,86,319,151,357,470,538,670,747,607,349,867,59,665,491,544,428,813,582,653,926,53,29,575,970,253,886,899,813,649,899,500,940,922,184,222,425,445,285,593,409,591,773,601,918,39,757,521,935,513,549,466,346,148,493,622,312,644,990,680,769,612,73,86,979,608,431,988,850,905,597,779,67,657,82,107,77,186,941,706,61,156,241,674,195,493,115,41,836,974,342,432,275,251,394,572,873,983,146,641,312,404,407,74,951,898,857,831,30,847,776,340,528,337,9,755,469,985,444,711,340,966,811,750,791,858,531,595,813,677,718,389,273,272,288,338,251,904,200,98,28,854,565,705,292,46,140,776,701,943,153,760,187,238,750,247,701,849,896,228,963,625,320,112,376,124,592,207,550,674,930,269,791,897,19,694,326,430,852,912,594,321,611,629,954,332,602,139,566,402,164,995,963,961,568,305,390,22,101,101,970,958,407", + "133,550,120,652,122,805,3,559,155,802,167,243,597,471,131,30,413,949,609,463,631,810,688,937,234,970,547,516,66,761,59,145,379,130,890,690,743,891,601,203,367,594,419,810,536,115,960,947,144,676,0,62,384,383,596,12,461,343,664,102,343,365,762,658,710,988,143,26,323,707,419,205,413,312,821,385,819,908,427,461,358,398,746,348,821,91,491,707,481,765,919,488,5,641,215,755,240,300,833,932,391,724,911,519,703,768,78,257,926,504,237,979,530,521,793,444,684,486,812,16,956,229,834,673,1000,519,894,195,648,694,439,448,916,436,870,954,182,595,385,203,827,294,940,692,671,807,19,112,328,276,290,835,365,933,889,536,435,444,670,872,934,231,941,402,650,790,718,948,194,636,354,817,614,390,967,624,459,756,521,339,160,248,53,564,413,965,148,499,851,521,930,284,251,487,706,61,650,211,89,255,786,500,858,630,214,953,471,53,603,737,598,729,135,990,208,624,489,393,311,375,584,134,240,84,825,531,411,204,406,819,214,236,569,638,904,55,349,555,950,540,823,844,862,844,498,532,564,831,228,753,327,564,782,212,826,229,566,543,373,198,825,709,706,848,361,355,506,875,787,604,584,373,83,258,512,936,197,639,22,753,104,298,491,507,337,626,475,809,641,18,876,734,530,398,668,921,840,243,365,219,487,594,767,398,157,384,344,338,546,89,683,42,419,100,854,202,457,218,412,680,200,102,123,112,161,395,126,584,800,453,434,411,513,847,332,677,105,413,912,641,376,379,434,458,937,179,258,429,692,192,446,894,527,182,691,728,752,826,328,773,481,106,792,128,89,505,7,842,223,58,592,372,287,962,454,654,185,710,580,926,274,656,93,383,121,318,980,832,441,435,236,987,548,723,535,713,554,435,557,277,957,498,709,154,550,824,166,89,983,431,911,522,208,389,912,341,120,192,611,16,50,678,119,131,847,571,673,422,576,681,437,710,320,583,826,539,54,888,191,97,83,989,327,372,613,710,184,734,656,368,38,996,268,444,67,647,598,22,323,441,161,223,742,200,303,956,564,698,819,794,698,173,583,358,133,128,254,161,737,942,424,221,65,625,46,148,218,744,703,802,739,60,695,421,561,684,276,570,324,919,943,728,38,639,341,104,597,696,338,686,474,232,439,790,658,458,9,561,88,976,244,278,45,993,939,700,968,57,573,740,756,948,524,452,575,917,606,54,246,652,744,343,334,439,649,950,920,962,800,985,885,189,400,5,608,85,814,221,198,395,725,877,864,271,768,666,986,947,272,697,125,863,889,439,396,699,999,454,191,686,109,998,403,618,511,278,345,603,171,647,157,975,251,252,2,203,523,425,431,661,854,961,639,471,837,991,289,665,235,777,461,691,595,212,642,710,769,719,587,357,563,830,500,928,18,765,130,224,371,420,3,54,858,233,713,333,196,216,675,778,150,613,530,755,484,624,49,30,204,523,176,165,580,897,352,972,259,938,311,305,73,610,518,95,444,494,918,825,795,862,910,438,505,516,450,214,125,184,607,526,945,476,977,741,629,2,366,623,956,503,685,306,959,362,398,32,804,568,482,999,945,782,67,504,598,377,837,357,542,110,309,186,45,536,913,200,427,322,682,356,915,283,195,431,87,801,545,784,452,932,143,856,745,267,250,421,733,40,854,186,123,106,933,809,383,264,588,234,82,557,451,218,721,873,646,738,205,343,975,175,904,80,749,257,199,338,244,554,513,615,312,784,360,739,599,367,849,380,786,229,80,204,341,820,624,806,44,482,494,304,419,477,648,697,750,317,615,507,495,631,703,837,637,313,952,700,498,946,295,780,378,898,23,128,946,296,526,540,248,501,945,829,478,564,595,940,363,723,226,594,403,811,565,435,783,418,5,873,363,20,571,281,705,952,260,161,149,510,588,690,967,467,795,272,276,452,234,963,474,515,874,142,851,81,758,624,547,966,455,604,2,157,615,758,638,846,966,339,954,187,605,530,102,802,91,684,571,586,624,706,405,859,406,930,261,430,19,653,33,473,987,357,820,205,431,717,949,449,713,703,151,392,264,183,477,11,968,893,337,172,151,541,586,641,27,432,587,178,670,348,729,829,964,845,620,91,789,467,807,728,196,11,764,633,598,718,374,792,639,532,562,219,273,420,895,408,706,731,446,579,517,700,477,26,286,433,386,20,856,449,674,383,836,720,700,584,947,560,582,321,45,600,916,199,838,964,298,784,714,418,892,972,553,534,845,378,960,213,273,861", + "440,293,555,572,905,595,216,991,695,769,509,323,386,522,166,811,744,115,600,818,847,940,965,625,107,951,889,88,480,417,817,473,679,932,905,244,367,908,318,99,99,265,195,563,541,77,864,566,121,502,62,0,442,871,933,416,80,303,135,927,358,213,286,258,314,313,386,345,142,532,224,538,322,841,542,253,292,85,628,878,200,769,758,255,889,867,25,982,191,359,8,707,712,178,607,46,647,932,91,135,844,952,158,516,993,183,812,275,606,919,118,822,187,124,274,333,454,82,494,372,879,364,363,408,547,884,164,152,363,644,879,307,114,915,520,470,281,476,915,780,651,321,426,268,180,415,712,408,429,201,238,389,936,144,993,833,150,150,846,518,566,714,633,221,763,42,622,555,125,298,460,24,192,11,352,743,369,864,227,716,241,107,384,700,748,36,192,145,908,207,718,845,694,909,240,897,104,989,25,822,584,219,629,899,11,135,564,899,496,23,609,724,675,602,97,251,182,324,932,262,770,835,29,73,557,600,240,944,84,570,871,137,840,465,621,171,559,741,253,831,777,447,825,961,978,88,952,530,159,50,932,16,213,113,496,252,496,48,426,435,159,670,752,2,245,553,371,238,718,896,713,412,38,581,109,370,753,538,950,710,32,880,367,920,758,311,291,63,503,296,260,588,494,647,42,254,629,800,52,531,879,869,797,687,759,347,113,144,352,842,711,150,807,959,53,426,45,819,844,83,523,892,217,748,466,10,654,932,73,790,543,88,751,233,515,798,633,887,50,67,590,315,191,611,599,495,52,655,52,774,997,469,134,92,666,516,470,589,680,906,32,522,704,133,238,531,394,327,198,477,320,980,635,11,506,481,954,822,212,215,828,333,636,344,782,119,80,491,360,651,183,270,103,869,485,622,545,594,561,599,830,143,976,120,844,326,720,365,529,93,900,601,413,611,203,158,782,969,782,838,173,162,549,89,118,683,468,946,427,110,672,336,130,135,466,814,864,259,996,579,420,855,902,481,497,562,331,422,773,240,606,95,594,208,290,742,364,122,338,266,127,816,721,31,778,340,463,689,748,587,899,816,666,986,709,285,397,528,936,408,190,122,977,822,379,289,145,99,682,833,729,113,346,499,577,488,402,290,305,356,651,530,56,373,125,673,499,737,985,394,65,287,417,814,928,334,505,811,515,656,600,876,112,730,11,895,830,711,400,749,160,685,529,121,339,876,789,558,127,331,820,114,827,150,832,559,149,47,322,272,606,921,884,195,985,617,513,431,788,609,769,537,768,214,42,415,293,641,390,830,161,517,319,753,115,675,186,53,350,648,583,194,180,307,283,920,605,130,467,436,781,948,94,605,592,78,285,759,873,839,321,619,294,462,97,296,121,815,190,642,220,989,113,314,39,965,771,103,836,31,976,443,425,846,306,47,406,589,67,579,232,266,393,322,799,767,968,768,472,703,533,567,232,778,387,742,111,6,453,733,559,930,560,860,596,385,430,454,143,577,374,241,582,505,537,58,262,731,806,323,964,747,653,835,2,908,791,619,904,906,447,129,734,411,178,7,554,774,461,650,208,517,837,868,770,152,568,238,143,457,931,464,363,29,601,915,674,485,409,185,721,630,438,251,31,138,165,850,573,317,931,75,249,1000,693,811,400,982,674,139,261,752,148,178,211,878,120,681,47,741,284,389,23,997,646,869,280,651,524,380,377,638,647,958,134,591,165,629,420,472,355,915,417,281,756,615,408,249,360,919,131,852,75,743,428,629,915,242,397,955,495,533,853,322,30,696,46,301,57,501,331,33,205,871,220,727,522,633,660,544,598,292,292,916,232,914,982,548,934,52,300,277,135,737,78,691,249,291,639,495,992,462,747,337,911,907,257,282,440,620,870,430,906,166,85,373,143,96,986,207,391,712,576,887,673,537,11,448,633,781,838,603,639,456,758,451,882,347,928,375,641,77,912,614,329,961,48,754,120,920,443,205,873,366,146,264,568,826,159,945,736,132,373,444,302,402,486,274,547,556,249,120,638,355,579,437,410,173,700,133,990,724,575,189,74,6,899,292,679,267,176,898,216,688,781,920,63,455,660,205,987,614,352,484,366,935,551,872,127,307,342,301,494,913,980,595,960,391,563,775,358,894,809,694,416,627,675,119,32,362,49,200,822,550,692,271,4,721,481,568,140,676,817,711,296,362,169,794,815,579,632,435,313,129,875,888,292,443,104,941,339,624,115,899,179,894,972,122,56,12,778,566,91,124,87,84,738,30,799,136", + "159,584,62,404,891,59,197,725,926,214,840,748,352,274,475,652,988,55,483,851,359,799,829,980,613,945,90,746,332,813,89,502,342,814,937,765,765,530,951,308,258,179,449,743,953,57,898,935,842,739,384,442,0,805,491,400,320,458,926,37,841,201,449,112,87,780,969,761,667,22,215,841,437,264,337,332,611,854,102,911,569,467,657,663,370,524,753,228,668,354,939,477,394,828,808,285,999,993,305,439,222,138,98,421,19,816,28,657,449,717,880,445,896,366,534,247,565,334,375,372,734,723,188,809,72,896,447,560,117,172,75,350,945,334,738,495,44,115,538,12,953,45,613,321,790,295,762,274,309,541,51,993,438,683,949,169,414,981,438,385,851,284,904,981,344,92,547,68,413,952,730,897,592,480,212,407,758,996,166,423,337,865,421,229,167,580,653,349,405,622,650,337,361,352,784,846,14,996,23,234,269,328,994,622,697,77,134,364,993,859,922,713,939,786,952,392,882,176,426,295,37,103,969,86,251,247,492,815,802,825,88,447,726,566,270,493,77,45,690,709,514,405,66,737,522,247,692,265,633,504,386,81,65,606,733,278,395,453,781,804,854,66,762,734,317,393,90,213,735,305,179,820,764,338,775,74,496,623,906,405,329,792,76,900,634,67,180,569,240,612,329,657,148,513,51,794,743,850,484,388,49,141,81,513,998,567,269,485,710,695,538,491,205,325,151,542,983,674,589,760,476,569,860,972,882,725,778,997,339,694,658,392,420,354,58,896,336,224,297,714,894,959,56,233,658,67,113,562,154,708,696,743,44,898,414,87,412,492,356,19,614,215,843,734,804,105,479,94,445,726,552,367,44,99,667,530,95,392,611,163,785,212,334,808,798,723,456,114,153,966,788,436,786,236,802,749,950,79,879,936,294,934,803,963,887,849,127,288,565,456,92,112,757,642,533,139,522,669,128,647,905,633,491,797,149,106,429,560,416,252,199,135,996,691,34,576,960,39,719,953,524,311,287,460,714,335,173,57,969,753,370,632,939,784,88,274,429,187,737,974,687,576,968,528,375,119,895,635,371,165,7,31,805,51,587,65,657,732,620,267,604,797,894,877,717,937,528,728,796,450,968,814,538,980,506,526,337,631,63,961,743,890,697,62,290,834,821,390,122,148,540,217,655,462,187,911,980,510,641,904,256,247,831,645,966,55,234,656,363,350,64,790,760,999,736,258,943,713,134,529,227,773,151,2,352,801,676,236,421,904,128,930,829,681,658,991,773,785,207,458,747,77,939,663,173,425,887,64,57,76,201,303,488,794,151,483,416,685,818,380,487,794,12,377,436,522,173,222,576,219,262,371,8,542,193,771,169,749,31,115,510,802,761,36,942,40,427,511,554,305,226,522,503,380,832,811,993,211,377,647,305,405,450,644,171,322,808,147,708,802,8,638,152,458,953,568,685,265,189,568,545,121,371,109,603,475,4,750,840,31,840,928,536,719,261,365,336,199,72,308,312,286,964,583,351,404,453,437,543,566,786,907,560,361,33,48,907,165,868,290,483,491,795,912,244,520,949,247,192,308,124,767,428,628,100,579,874,177,988,677,412,531,45,606,659,776,742,347,714,186,160,646,159,137,62,787,545,978,531,95,176,598,569,142,325,463,404,409,908,376,30,684,817,631,814,712,704,870,738,563,903,47,292,368,582,509,12,626,993,683,238,756,135,67,655,475,150,389,540,678,180,181,717,966,868,245,96,243,819,414,713,875,513,915,277,192,16,900,473,709,368,538,205,473,159,110,589,603,1,896,884,501,291,575,527,744,187,624,823,751,90,541,29,761,902,877,762,220,170,222,446,318,940,956,662,729,324,528,804,756,506,475,475,63,287,836,857,913,776,477,358,741,593,656,840,642,127,798,660,322,89,214,538,336,252,592,870,511,481,8,469,683,98,340,67,682,2,352,649,159,258,756,193,392,335,980,972,824,660,920,538,52,659,874,511,894,197,771,683,813,184,36,140,231,663,470,839,60,115,402,12,515,482,275,242,892,487,532,884,847,659,69,12,995,371,783,527,846,52,50,42,361,973,80,702,569,832,794,355,864,506,538,218,724,154,774,497,736,570,834,364,800,776,363,567,812,660,384,331,734,882,778,25,407,94,809,662,487,592,954,533,347,914,516,250,158,962,433,470,940,642,521,418,123,654,397,582,126,295,605,363,168,235,755,42,313,244,829,205,918,941,766,117,635,686,460,958,237,13,529,652,711,109,889,90,635,992,279,287,956", + "219,254,299,747,296,924,192,857,374,671,471,412,938,155,995,51,697,309,562,42,805,698,632,128,928,636,460,365,55,184,224,670,853,413,977,408,359,467,884,108,196,605,860,121,851,895,314,507,607,122,383,871,805,0,163,331,865,503,804,944,606,503,596,459,776,297,349,623,522,408,110,605,863,62,433,646,421,750,220,541,746,185,989,259,256,280,732,46,377,620,978,557,766,803,629,444,916,625,52,511,181,689,100,703,894,812,741,741,15,551,426,500,432,35,24,912,323,144,814,918,173,825,940,300,552,167,83,102,234,572,23,285,771,529,386,469,539,672,892,398,978,343,171,585,413,276,425,432,548,741,799,695,227,197,291,36,747,523,340,172,476,688,964,976,693,794,11,869,107,94,525,732,226,811,34,78,222,381,923,707,62,263,603,346,559,956,558,11,60,390,521,144,941,899,572,266,757,944,127,541,288,420,479,519,851,362,735,333,82,101,683,697,2,696,486,578,241,201,89,146,616,67,482,468,251,873,266,671,650,348,21,180,635,40,431,813,807,383,728,290,3,660,642,958,280,73,337,244,431,5,651,214,644,421,472,538,861,918,703,355,222,708,650,29,867,90,203,767,243,434,434,534,811,378,511,91,477,34,697,726,534,495,987,650,320,581,218,586,964,841,929,207,178,973,71,318,972,818,539,971,524,708,201,465,312,865,230,646,31,693,581,551,52,865,224,114,224,62,586,674,363,171,808,202,77,543,889,934,419,887,541,391,736,346,887,511,340,513,904,800,452,2,417,114,338,276,466,968,91,283,827,445,324,676,274,885,448,746,685,220,709,627,587,697,39,667,521,560,603,208,224,8,578,519,930,647,919,153,723,989,648,819,132,183,550,843,888,928,237,596,59,921,993,880,472,860,107,560,408,359,464,104,410,562,301,679,840,271,18,386,559,861,532,891,565,879,755,389,382,474,465,783,530,728,164,457,420,712,769,54,74,206,2,812,936,388,220,558,779,813,552,602,35,306,451,366,617,742,763,653,669,563,247,14,303,393,453,188,404,190,505,566,477,688,31,62,137,835,178,106,618,901,515,890,934,320,883,484,857,657,597,648,995,849,898,143,832,165,663,538,972,830,514,363,390,34,324,795,733,911,572,272,3,292,474,990,769,183,854,123,537,549,913,97,763,496,236,939,643,412,148,508,200,930,365,930,435,108,545,399,219,63,732,698,465,566,360,68,63,164,351,855,209,646,480,256,55,283,737,978,935,979,377,574,546,196,833,272,6,508,203,524,288,658,984,944,179,611,565,208,303,644,461,985,271,684,477,196,209,149,127,353,176,618,710,817,743,564,850,829,874,105,606,845,387,914,137,181,690,964,928,824,262,3,862,528,135,559,547,451,607,367,614,826,436,539,649,106,139,178,868,306,909,982,633,266,881,288,560,338,452,947,111,259,304,761,238,894,528,869,821,853,878,851,582,732,431,922,434,46,805,196,72,13,321,693,876,899,678,754,149,420,451,626,34,397,563,678,645,727,914,919,88,612,299,54,223,532,84,628,469,94,566,821,919,875,588,825,189,462,530,956,16,864,820,315,134,942,127,810,937,744,47,894,267,377,729,40,482,391,529,918,807,224,181,977,802,970,19,60,961,332,363,36,246,757,886,506,249,267,69,582,630,409,410,971,501,952,780,162,850,244,622,974,958,122,380,508,971,172,933,59,777,169,689,222,643,220,35,453,106,923,180,294,867,669,802,72,866,804,845,249,761,766,435,492,415,384,303,80,401,842,306,595,817,127,329,85,528,479,866,611,515,179,875,535,842,592,313,335,811,873,270,472,674,152,641,521,958,491,669,351,833,353,979,205,731,245,44,316,510,407,123,590,268,801,807,355,354,136,250,656,562,184,456,342,686,853,565,413,931,710,713,800,975,615,217,380,496,492,777,20,357,446,149,12,546,796,768,611,461,454,416,968,54,42,94,91,596,944,512,92,86,970,664,326,515,417,223,316,799,421,408,728,345,266,176,835,679,467,926,38,521,808,433,987,563,6,618,773,825,252,871,809,451,877,925,523,27,703,793,259,848,784,259,391,669,254,997,8,7,385,751,855,682,113,78,967,225,51,923,911,37,957,334,50,83,120,941,566,960,351,191,850,205,777,846,355,787,632,764,239,360,649,170,370,696,88,870,66,735,568,821,285,515,967,832,169,951,799,607,671,829,279,418,799,679,869,153,748,905,112,612,957,469,613,770,972,265,308,295,595,459,524,763,790,218,177,816,895", + "300,732,840,304,198,109,807,542,383,331,851,46,893,496,10,758,463,951,234,296,622,861,71,910,57,924,677,255,412,955,157,332,453,613,346,961,16,603,884,1,77,753,328,71,468,461,371,285,660,757,596,933,491,163,0,150,664,288,651,186,9,900,286,411,567,180,129,469,148,152,858,30,862,57,327,264,807,795,478,700,724,145,811,360,138,870,301,672,109,702,864,175,15,782,801,999,828,740,342,527,334,931,775,504,897,339,744,323,703,988,920,807,743,674,780,295,983,25,575,424,496,669,414,71,50,652,776,781,804,494,628,856,664,315,163,399,551,16,105,936,178,778,287,305,412,222,4,602,637,568,820,754,257,474,817,618,573,563,11,771,78,587,430,987,392,602,14,829,554,981,945,545,569,437,385,431,134,941,39,985,247,402,735,473,505,278,266,668,186,263,520,417,898,267,715,126,730,585,972,732,232,115,996,636,379,285,278,892,932,116,617,739,98,581,17,81,243,190,405,995,787,399,566,291,216,792,673,503,385,205,185,491,535,191,43,370,628,544,83,915,726,42,392,241,934,907,739,888,720,429,512,872,954,188,619,632,51,851,765,535,379,432,170,444,161,463,525,623,4,4,316,414,423,120,498,766,630,605,499,108,953,255,494,853,283,403,568,162,261,888,918,416,2,90,990,963,84,399,915,272,117,762,979,304,63,19,618,833,670,438,373,333,956,3,138,644,295,442,130,310,539,568,925,176,110,957,377,521,506,688,462,690,786,897,55,993,650,174,993,402,543,422,930,263,482,316,182,234,262,138,86,760,528,744,443,565,845,939,176,289,532,883,476,424,321,976,688,935,76,644,670,102,51,498,691,290,132,167,970,130,627,532,194,732,101,385,425,564,511,413,689,466,681,426,474,271,793,794,420,934,922,382,345,970,320,771,342,961,300,954,709,213,727,824,434,431,47,63,281,217,146,578,943,401,412,326,416,758,809,971,898,385,155,958,831,393,618,833,405,737,340,917,563,903,859,688,541,431,160,559,92,648,146,652,533,407,859,17,260,628,59,580,804,504,612,524,417,664,53,597,606,624,549,645,753,387,638,116,777,831,366,163,840,10,700,997,825,688,631,427,171,403,201,101,406,487,751,155,769,400,122,956,171,834,176,119,682,552,508,913,615,3,955,124,281,273,895,647,325,832,432,886,693,857,192,362,629,773,355,320,459,232,476,563,740,645,766,794,704,160,523,246,267,265,345,674,584,51,274,91,112,894,946,231,760,908,163,201,924,121,976,43,354,876,809,597,117,393,858,628,363,413,654,781,720,494,432,50,243,752,426,801,624,641,521,803,262,81,406,325,389,884,789,416,803,643,275,111,520,688,275,588,223,311,307,3,261,914,106,975,758,847,946,621,961,503,703,120,879,192,321,466,532,652,822,265,840,681,287,388,83,166,969,452,160,389,263,337,479,331,108,240,56,921,210,211,410,127,808,380,670,404,130,274,509,564,687,76,288,371,584,20,129,629,271,902,245,19,824,220,834,40,60,515,930,206,878,729,11,498,253,403,46,390,230,979,881,260,23,19,989,169,408,974,187,993,919,912,220,324,762,461,573,420,779,688,193,658,873,845,730,834,224,738,860,17,183,863,797,133,170,603,659,26,719,681,929,324,896,565,851,345,869,16,935,682,753,853,680,428,963,641,479,684,719,108,561,643,592,562,522,431,839,462,389,939,700,136,664,351,164,308,325,466,172,114,238,789,166,266,334,120,701,972,132,438,642,590,61,729,837,664,552,304,104,14,838,41,812,714,70,856,982,822,970,702,664,141,430,306,719,474,145,359,303,420,343,163,67,285,868,402,896,506,414,61,48,202,817,37,813,614,473,943,597,434,96,486,707,844,942,138,648,850,494,541,801,361,81,686,310,585,897,663,706,670,724,144,920,201,582,512,327,706,686,118,686,173,275,880,778,604,112,726,603,704,351,753,653,966,71,687,714,17,826,791,200,846,779,263,52,543,941,315,662,838,165,319,490,735,491,664,235,703,385,921,733,203,846,261,691,825,439,599,691,127,146,414,862,355,315,444,469,804,652,509,817,547,198,857,18,853,358,809,196,598,508,972,376,116,745,477,84,365,927,232,869,411,747,544,735,887,298,169,408,178,102,526,443,393,74,2,508,916,355,101,382,482,639,66,55,425,472,861,204,344,208,546,165,395,296,804,857,798,635,424,78,982,815,394,700,630,313,336,154,119,859,628,382,539,161,423,636,259,143,62,791,574,199,714", + "855,694,451,949,736,36,627,434,406,611,544,140,767,90,529,529,635,611,912,9,712,924,116,71,591,752,734,772,873,183,955,922,121,609,35,959,450,945,930,202,706,735,109,497,50,937,263,939,504,469,12,416,400,331,150,0,645,237,340,118,864,315,648,709,634,385,641,168,699,3,683,300,596,454,693,514,294,442,14,178,55,462,110,910,160,374,113,768,315,491,228,697,168,431,511,321,34,878,703,858,635,320,913,668,439,904,625,105,99,31,570,868,628,182,513,231,699,199,348,438,318,999,24,584,245,895,739,641,503,469,160,448,214,846,391,894,550,629,26,351,426,935,519,426,551,602,129,131,817,634,212,145,381,957,726,789,470,880,752,8,962,831,300,411,72,419,857,28,198,297,203,109,795,960,305,689,842,760,658,103,810,317,494,859,828,176,9,88,288,419,617,24,500,68,502,852,211,78,912,539,640,857,372,153,545,59,71,29,398,614,767,681,338,731,309,755,181,256,837,750,299,864,136,904,358,982,867,437,681,764,299,248,57,538,65,441,803,644,756,978,606,812,319,308,163,774,496,945,715,468,335,353,765,423,463,167,632,144,871,698,423,509,133,251,86,177,295,551,644,24,611,644,642,786,284,190,90,974,14,276,147,353,413,252,730,111,742,833,657,67,356,965,854,295,502,97,926,775,403,681,128,518,522,844,48,914,204,127,98,994,660,434,844,58,744,620,381,715,365,116,438,332,158,37,918,397,712,651,306,342,72,932,267,563,795,917,702,965,885,223,170,10,667,729,142,361,850,716,516,129,930,624,77,113,768,254,550,770,641,591,178,934,391,944,756,916,250,781,786,704,464,16,575,434,35,317,279,845,764,925,210,61,797,272,519,38,509,110,845,960,858,254,798,760,164,613,130,594,161,865,829,696,660,590,61,196,722,718,572,116,665,216,186,901,911,256,483,36,349,711,520,114,773,848,355,550,43,174,257,847,518,298,80,615,106,213,60,407,55,597,559,410,8,228,462,880,350,167,230,370,11,147,620,757,795,938,9,754,60,931,422,730,991,96,713,286,498,142,794,979,653,273,978,806,931,258,127,722,814,508,533,846,961,851,560,716,321,951,572,233,35,874,472,568,987,94,26,258,18,68,79,715,665,183,513,671,307,923,20,16,655,213,851,193,724,305,195,139,115,971,58,481,920,980,231,910,593,928,698,724,922,973,173,998,206,603,195,823,714,593,92,327,410,1000,112,417,816,688,379,155,774,552,474,256,916,299,37,224,948,8,470,661,559,140,558,54,463,574,967,869,640,370,273,633,77,966,540,162,831,567,67,679,167,965,942,225,79,860,757,7,14,755,520,636,762,485,458,253,31,340,918,415,381,315,378,234,97,880,412,168,179,283,498,887,153,145,358,536,190,747,558,285,70,76,658,711,348,941,951,204,778,906,884,395,312,480,439,603,580,440,104,463,818,125,126,268,894,203,106,729,109,412,258,906,15,869,413,233,219,865,385,991,979,479,931,960,442,317,336,305,36,70,543,97,413,445,421,344,626,353,853,173,555,399,105,989,450,231,409,69,771,157,564,672,482,4,662,83,254,100,312,266,848,606,640,364,135,276,161,477,700,727,9,239,734,663,198,504,585,745,428,878,672,588,125,448,349,139,39,953,953,320,120,907,857,686,994,10,527,247,412,524,268,517,293,291,141,483,325,972,844,532,658,670,443,896,208,353,6,901,503,769,309,501,310,882,262,773,405,907,376,460,511,356,888,186,308,234,6,93,456,444,187,10,607,709,847,288,769,189,871,287,183,206,618,756,835,458,989,729,87,190,161,21,648,24,517,250,469,846,557,672,428,77,288,294,818,626,907,595,706,182,676,863,734,193,276,376,363,959,821,442,183,535,835,694,684,192,497,90,622,458,595,230,293,377,796,682,359,538,707,741,947,683,570,403,857,832,536,522,98,359,224,431,509,446,665,583,391,657,343,516,829,414,618,727,260,315,429,814,727,421,86,791,71,639,579,737,72,837,244,847,42,118,241,471,267,97,843,667,498,33,63,138,831,625,275,49,11,253,595,812,261,270,721,26,1,229,770,268,966,938,858,592,605,209,380,82,228,146,902,722,715,23,686,266,379,624,59,841,895,772,345,47,314,830,504,360,889,614,488,939,16,376,887,664,594,327,608,722,495,225,493,229,58,234,743,166,885,61,648,229,200,911,679,472,751,78,421,83,59,435,407,229,9,426,530,51,222,367,306,715,686,504,997,869,336,152,415,816", + "443,278,353,222,352,87,976,948,957,474,945,483,400,624,720,324,601,910,588,4,925,335,674,368,91,167,40,67,600,592,876,645,443,533,73,699,964,713,921,765,32,959,866,4,828,927,859,574,730,633,461,80,320,865,664,645,0,389,702,97,475,182,555,966,340,865,99,86,926,35,777,555,161,257,28,43,681,25,204,407,577,467,146,514,568,390,177,4,636,26,780,462,759,33,295,625,361,83,653,508,76,220,603,451,277,358,292,857,580,134,886,291,236,354,361,932,290,403,920,85,919,591,32,778,886,204,484,677,123,15,6,986,741,529,421,975,9,187,918,40,362,377,173,47,735,883,418,93,293,501,496,73,657,924,144,870,545,219,462,201,26,319,296,617,331,33,897,838,457,177,686,933,504,114,179,342,640,608,362,182,763,231,768,465,654,392,531,685,534,234,114,333,200,953,489,921,641,381,570,452,852,308,752,187,321,647,721,677,93,878,991,235,664,927,396,998,359,120,443,112,34,379,29,127,14,207,241,775,982,796,548,148,56,453,810,361,631,265,803,936,187,880,168,371,89,89,116,215,625,32,828,195,597,208,638,600,383,865,487,936,915,584,136,720,978,309,775,87,347,169,947,658,120,642,534,179,362,401,266,550,426,616,126,724,905,951,416,990,43,260,466,385,406,464,963,747,630,687,460,351,28,675,690,755,328,90,994,87,526,926,138,291,477,280,796,947,87,432,801,403,831,802,221,313,133,806,492,522,543,644,627,117,391,870,938,546,99,11,540,68,164,359,919,357,816,329,303,151,744,260,118,100,929,643,639,428,726,403,989,181,129,287,727,617,287,549,331,757,742,929,978,895,52,79,627,665,408,621,290,568,761,372,785,999,536,702,871,560,13,994,995,784,751,356,22,192,643,554,454,115,553,96,594,166,104,28,692,365,398,943,116,103,962,970,553,446,952,635,615,183,324,911,806,831,647,185,867,457,399,810,17,925,532,117,730,409,405,359,548,483,975,43,337,685,884,920,645,439,144,684,776,768,612,871,896,790,37,6,941,874,45,681,335,224,527,780,451,952,945,620,158,654,749,643,425,937,827,44,227,333,277,648,429,940,716,345,347,157,296,109,230,641,371,358,800,569,909,92,843,154,991,731,653,928,491,244,247,974,884,790,407,294,750,488,989,524,240,442,778,849,865,374,102,205,177,847,278,329,685,454,623,290,150,798,468,342,493,407,198,479,549,809,928,537,672,795,265,194,880,51,146,136,915,897,88,388,657,313,350,137,242,513,557,153,768,254,228,793,756,341,83,427,172,137,159,308,280,503,570,30,32,812,253,341,24,556,480,987,31,279,26,245,27,70,580,965,261,968,53,836,172,376,808,187,910,804,544,304,209,421,462,736,792,68,613,698,591,420,515,203,948,105,290,787,741,489,27,637,94,416,308,343,68,788,743,449,713,457,180,824,404,50,697,511,459,899,58,868,43,696,895,31,869,602,696,355,322,142,539,460,273,526,927,832,443,274,494,953,915,310,297,703,145,680,476,196,672,399,989,425,824,258,317,71,458,914,327,24,714,330,154,659,543,274,404,20,210,286,435,694,395,237,233,936,516,150,786,235,225,647,684,296,913,452,365,805,467,276,328,659,826,846,746,910,407,473,550,958,253,225,521,511,262,41,853,246,510,524,219,167,179,337,106,347,232,846,371,134,371,708,600,75,160,952,748,335,116,716,93,440,546,630,973,105,197,701,365,855,705,140,939,847,483,395,621,450,123,242,107,139,639,658,609,414,150,222,359,741,192,628,426,693,789,271,102,193,529,241,717,108,985,352,550,98,366,601,119,977,286,211,694,765,346,819,346,442,36,62,234,100,261,782,694,677,220,690,858,753,156,287,984,562,590,279,775,775,750,31,130,783,66,248,891,858,379,780,663,868,891,842,299,619,788,904,395,757,447,764,682,154,572,287,292,573,672,757,573,266,822,490,961,63,794,15,829,794,240,733,391,86,980,469,711,169,388,302,291,575,658,70,334,304,936,987,643,547,924,504,862,326,528,985,687,138,708,365,455,912,461,30,616,643,719,585,222,770,498,360,247,529,736,751,85,234,259,605,858,410,591,829,700,611,586,484,657,359,474,523,404,58,691,984,655,895,689,988,583,280,358,667,112,303,734,520,966,546,395,32,648,75,565,817,24,482,813,821,319,762,307,253,651,254,856,87,684,137,503,663,806,860,992,293,593,435,603,655,705,541,242,659,976,702,474,245,62,741,734,255,216,95", + "385,971,402,7,527,931,46,381,187,305,328,755,262,931,343,113,20,245,224,335,802,630,382,12,323,867,640,175,123,912,736,981,371,574,12,532,328,693,2,370,895,145,403,551,534,240,100,729,305,597,343,303,458,503,288,237,389,0,785,532,196,233,290,69,745,181,16,761,876,976,558,752,870,715,742,412,660,396,401,161,814,690,303,193,580,100,968,782,520,223,241,438,148,434,612,319,5,970,559,14,338,577,801,775,119,537,537,940,698,918,231,4,369,465,278,114,41,630,266,460,845,710,947,883,194,737,680,289,655,466,716,767,50,353,158,529,927,231,74,912,29,546,949,826,282,424,201,63,28,360,937,218,699,972,478,1000,307,956,988,982,251,114,969,563,977,939,435,850,323,102,762,987,653,104,14,310,711,565,201,144,570,386,319,237,197,544,755,652,992,187,478,541,39,464,976,774,805,421,374,385,29,244,420,734,297,451,422,453,327,941,864,641,673,726,928,910,411,97,571,229,482,349,565,222,366,126,166,515,403,795,319,307,39,261,680,175,420,318,186,991,586,835,800,152,346,276,314,40,11,495,183,886,536,5,232,4,731,706,868,432,881,587,141,262,258,336,788,378,975,375,756,277,940,320,768,459,812,837,269,760,55,654,683,812,510,443,841,381,891,575,451,689,563,218,588,39,477,60,728,664,489,501,532,560,321,206,523,773,541,787,970,271,770,530,225,1000,697,714,579,625,167,716,775,63,717,951,480,279,425,222,189,191,832,121,295,666,161,365,804,502,904,299,502,872,854,918,32,905,754,963,418,291,75,940,845,524,865,161,479,342,27,324,777,206,844,883,915,270,208,392,119,496,450,465,513,952,722,889,576,34,741,703,282,48,846,627,141,327,833,951,640,80,931,628,901,519,86,481,72,63,582,592,389,835,428,127,183,186,716,645,96,693,413,167,19,804,690,473,694,434,598,488,433,710,18,740,124,207,726,180,980,952,659,930,624,151,269,600,101,205,659,151,95,616,330,696,377,225,254,640,527,917,662,703,117,927,951,625,770,189,445,721,368,417,345,946,346,459,87,379,404,787,650,334,551,964,361,11,680,737,360,866,882,165,845,96,385,273,702,164,676,940,191,690,37,265,362,607,812,589,832,277,535,661,573,625,170,24,917,139,592,908,855,152,481,615,773,582,103,512,145,371,594,129,446,615,533,194,660,694,446,907,330,282,681,508,720,802,401,987,27,40,875,177,717,99,541,739,691,513,887,771,327,500,300,761,569,469,872,259,86,17,449,734,342,887,348,968,767,675,667,468,215,503,304,996,6,289,417,526,923,665,181,160,411,912,735,779,620,856,919,978,580,394,430,220,436,167,474,801,902,233,145,109,229,607,852,891,942,723,66,38,723,806,218,623,722,508,264,399,806,112,285,582,881,460,208,405,103,617,388,303,238,442,259,480,442,182,874,996,36,963,517,601,574,325,210,671,18,541,384,927,49,70,788,193,723,441,434,262,842,685,765,407,305,217,442,967,134,651,829,976,651,300,924,772,120,433,985,842,410,447,598,387,257,322,653,433,357,40,468,183,542,617,869,824,635,380,4,581,592,213,658,974,92,605,740,702,686,432,581,549,848,814,272,512,202,36,691,94,623,71,73,845,425,462,667,210,877,613,709,588,474,520,463,928,177,526,300,647,745,295,703,408,890,855,481,513,364,863,505,104,268,793,819,74,21,772,14,555,365,695,965,905,7,972,128,924,641,832,918,688,17,297,643,599,957,961,465,710,495,959,415,176,156,825,413,428,367,598,636,64,726,269,364,844,242,711,120,959,317,139,538,584,791,801,550,870,816,767,749,381,250,444,675,397,816,245,323,594,207,765,731,678,348,172,343,517,148,904,530,590,156,890,357,390,624,373,498,798,804,21,360,561,883,942,484,724,457,659,16,669,3,730,841,632,273,872,424,123,117,24,637,133,690,150,112,833,901,752,111,462,319,849,329,836,377,703,863,919,282,274,852,131,916,644,532,269,135,683,815,379,129,582,377,985,765,470,427,339,412,235,244,180,270,163,20,363,166,833,284,800,71,61,656,596,357,362,13,904,902,712,561,22,976,238,963,745,912,961,978,643,956,746,531,725,459,531,144,741,532,230,605,944,79,459,531,542,348,271,405,960,322,295,825,825,893,866,921,234,371,109,889,583,171,361,522,74,726,495,176,703,618,741,455,998,765,671,777,923,325,874,938,876,981,268,677,83,988,484,289,896,32,950,867,743,280,501,923,248", + "157,813,539,383,836,779,264,285,738,521,797,879,637,714,818,509,450,274,640,558,585,434,836,513,727,901,368,677,658,48,232,296,767,517,633,274,948,486,719,611,875,736,359,788,94,577,427,932,31,41,664,135,926,804,651,340,702,785,0,143,458,78,679,687,713,746,498,680,280,15,985,569,53,289,244,846,563,150,528,69,31,618,387,557,799,67,926,332,918,585,473,673,690,673,873,632,310,31,326,811,128,758,878,279,608,676,90,920,35,667,980,345,523,166,903,746,456,369,438,949,202,442,676,163,157,722,949,623,425,479,669,902,277,866,356,214,996,704,649,933,669,605,814,492,403,37,985,213,796,699,547,279,897,451,613,305,914,744,681,30,451,633,358,173,1000,824,160,187,770,720,510,373,629,818,486,526,803,556,424,880,303,925,880,353,166,948,910,6,627,541,797,308,103,708,910,423,208,46,606,399,671,864,233,218,812,753,765,815,516,521,779,843,640,515,157,43,564,251,732,151,641,271,816,689,352,964,229,172,579,894,756,763,25,18,241,621,344,899,391,412,770,860,543,209,185,116,377,703,702,403,387,845,285,113,349,41,380,48,779,558,678,266,987,139,953,255,564,850,29,103,319,807,180,57,256,935,71,830,766,360,81,890,44,48,988,19,951,209,925,815,465,680,463,171,443,413,909,940,135,698,759,82,96,884,447,638,773,337,618,978,964,502,947,143,526,805,615,315,701,146,610,806,511,147,485,6,699,213,343,28,184,827,692,415,608,673,978,725,104,107,821,169,120,432,147,101,373,688,848,697,993,106,502,332,399,699,258,208,464,710,499,983,986,683,547,17,486,41,544,812,903,212,286,999,608,905,135,59,652,650,118,177,524,580,441,682,165,378,882,517,961,94,388,844,68,179,780,412,50,21,872,430,109,948,505,973,918,437,14,982,566,196,697,749,857,669,49,470,132,456,920,319,153,740,940,404,363,193,493,11,198,950,505,367,534,464,130,736,145,487,270,248,323,77,11,827,62,749,428,828,547,878,169,28,221,384,652,32,469,966,677,952,656,548,140,441,808,420,558,18,415,906,194,365,883,94,674,721,956,354,92,126,707,154,986,301,238,961,463,303,946,492,716,681,276,383,99,24,3,682,469,569,587,221,856,527,379,905,998,971,71,909,803,527,721,952,239,70,339,230,933,450,142,788,937,571,14,91,571,794,164,425,311,34,726,876,938,896,653,94,336,331,376,517,46,983,699,93,290,52,127,872,552,874,720,311,913,912,393,921,94,550,397,536,364,227,1,777,442,527,334,106,361,895,876,101,78,337,531,255,679,67,107,27,135,272,208,941,150,296,951,821,13,855,347,348,475,515,617,187,453,484,838,822,112,75,786,152,955,918,765,404,948,912,874,392,771,162,740,566,704,71,923,852,305,397,407,928,608,150,289,947,786,918,302,814,308,417,379,878,166,625,560,17,846,259,342,551,137,452,295,137,315,291,888,680,761,726,723,960,632,860,993,236,86,831,676,359,899,406,477,983,89,386,929,295,713,473,640,220,670,726,826,716,320,419,136,436,867,357,557,512,887,843,441,130,81,672,711,609,754,387,162,494,958,475,651,502,537,814,202,499,299,393,590,961,773,483,27,28,10,716,313,653,514,569,701,16,893,855,213,342,499,280,833,59,920,182,554,195,836,125,956,730,354,36,166,64,240,701,271,66,555,322,861,724,10,831,305,797,550,782,941,807,257,804,645,643,460,156,368,233,44,49,68,4,372,476,134,470,423,280,610,255,382,825,328,722,91,338,766,777,286,968,952,175,265,926,877,152,15,832,645,823,587,431,881,830,380,987,234,955,33,825,88,400,502,645,940,994,400,932,10,466,811,696,312,235,348,342,34,592,288,637,49,275,243,295,210,324,114,562,472,920,227,966,409,78,135,146,462,128,482,480,91,266,658,287,278,706,789,925,81,234,868,851,719,124,238,787,926,135,974,980,758,734,120,869,30,551,974,484,827,482,111,611,918,379,676,660,511,458,563,914,364,611,253,307,288,986,133,830,932,640,916,303,536,914,953,452,908,724,810,354,549,917,529,18,318,806,722,977,233,157,624,597,958,20,775,331,43,276,612,791,134,749,203,657,660,884,1,462,508,606,851,858,124,969,13,500,334,224,172,850,605,927,469,70,489,292,839,759,956,405,424,30,151,757,820,626,83,601,683,789,202,789,726,48,834,220,116,2,54,465,842,240,251,866,319,340,869,566,604,518,645,344,942,898,67,232", + "770,730,565,658,911,556,139,492,930,745,300,204,281,44,8,431,955,827,155,419,207,265,308,915,210,265,168,690,25,14,567,286,882,993,805,333,617,424,23,451,793,685,786,167,452,446,343,68,626,405,102,927,37,944,186,118,97,532,143,0,474,892,778,882,708,395,346,463,227,841,694,961,10,49,672,399,236,928,71,180,473,892,306,831,264,29,999,763,361,632,201,213,153,805,974,866,539,707,391,398,151,192,917,7,480,743,833,550,700,76,330,951,566,957,872,530,749,306,570,98,706,85,929,659,440,155,281,849,927,539,547,255,419,187,494,54,144,326,924,665,858,450,500,945,652,65,639,161,24,853,336,434,858,166,199,835,978,404,247,17,708,443,595,916,410,122,444,446,408,586,901,837,837,345,101,284,373,148,382,192,489,690,979,340,702,940,449,585,550,879,770,639,867,840,264,376,6,235,726,376,32,470,633,269,996,550,587,183,730,856,18,149,361,11,718,303,840,219,20,933,653,790,541,869,197,544,58,305,79,289,223,576,572,944,536,478,594,922,233,344,512,724,78,639,170,540,884,84,778,79,743,144,453,898,690,241,409,738,836,389,549,893,216,675,498,452,438,919,594,886,711,391,831,884,18,407,585,236,688,215,299,652,25,739,890,939,66,742,720,541,513,735,782,370,170,511,54,683,771,313,861,67,1,81,293,507,515,683,133,148,497,599,688,950,561,194,587,297,526,847,506,452,104,132,972,934,438,501,628,694,744,366,299,12,306,770,507,679,860,349,525,895,677,47,158,61,91,261,674,175,629,166,459,459,580,621,990,31,665,645,920,240,297,166,610,219,784,882,184,6,993,640,18,294,126,442,286,169,597,458,935,440,156,34,650,205,982,338,947,679,348,251,642,100,658,725,286,775,645,46,677,473,186,569,98,590,143,912,198,15,382,543,125,994,166,95,206,887,823,373,321,455,571,759,265,161,507,476,448,655,145,956,634,92,636,303,461,723,689,43,836,28,443,921,286,664,68,429,398,218,907,171,22,292,367,48,706,293,861,618,679,503,309,443,788,639,720,866,62,748,583,505,851,376,266,621,542,590,629,389,957,101,666,724,61,666,437,685,833,44,738,728,83,930,28,550,622,657,135,26,335,570,985,702,69,854,395,709,202,841,260,606,442,290,536,589,310,494,617,837,986,914,282,679,391,80,125,699,935,406,408,574,313,848,227,949,587,986,597,409,626,789,174,124,390,808,373,177,158,979,631,530,264,253,567,880,804,911,544,649,288,59,454,228,641,738,592,964,861,445,806,951,880,819,526,150,539,448,245,669,111,490,925,52,65,797,608,396,247,37,839,525,579,409,739,962,766,409,355,200,462,947,678,954,833,605,531,537,227,440,706,108,395,555,881,556,747,28,263,536,652,867,231,120,658,333,517,336,906,272,318,904,127,651,256,108,453,951,745,980,486,246,138,770,701,614,14,686,593,503,410,994,304,984,535,648,84,50,703,528,639,155,400,378,864,862,836,654,891,997,112,21,541,360,701,239,749,170,74,327,171,672,374,711,640,776,875,832,918,418,903,209,503,930,274,569,300,422,684,244,165,505,901,102,998,72,547,504,309,67,157,964,822,184,879,513,596,769,728,38,739,162,782,575,777,159,73,226,408,527,717,731,112,32,137,199,129,522,978,505,159,496,366,795,442,369,750,57,382,271,197,777,223,749,672,133,411,151,682,843,675,514,163,676,872,988,236,751,244,703,998,765,736,613,561,100,817,81,34,35,469,819,953,62,865,888,833,73,245,31,381,428,173,599,698,633,202,658,244,551,779,98,425,368,16,861,818,688,914,898,937,908,473,571,59,205,401,940,866,620,518,510,65,828,691,941,802,66,985,475,792,833,49,993,892,630,369,234,987,896,546,733,236,374,873,473,388,439,963,967,835,420,728,898,81,304,148,924,607,848,700,314,965,228,351,837,974,672,351,509,248,932,497,659,22,690,504,437,491,956,145,110,995,50,265,720,391,158,662,131,520,431,691,307,170,859,402,420,614,621,845,237,148,943,207,656,748,329,189,61,29,841,369,265,358,645,948,138,498,555,588,311,936,253,293,352,928,111,343,887,250,814,440,194,285,770,268,213,498,327,348,22,916,820,110,330,821,361,723,16,743,338,776,319,132,482,779,879,891,184,798,256,256,184,109,562,986,385,781,216,828,895,374,174,91,570,830,490,15,951,154,121,508,769,97,795,583,799,502,649,530,360,652,332,788,288,468,55,571,469", + "29,589,562,89,443,782,974,768,945,991,43,434,979,118,865,992,448,124,46,182,301,90,277,810,537,581,156,544,157,777,492,786,808,519,541,241,440,981,701,992,422,678,574,73,300,911,591,722,434,468,343,358,841,606,9,864,475,196,458,474,0,791,289,974,149,803,336,442,841,606,101,621,223,780,507,550,948,226,847,820,671,305,898,191,253,860,864,652,188,85,573,33,521,341,275,682,697,830,840,928,603,740,311,26,8,40,154,952,387,712,211,645,321,749,128,313,142,513,590,839,453,376,659,954,989,346,859,269,978,470,738,815,818,264,490,418,411,939,842,240,849,430,735,475,377,300,149,830,710,577,574,535,923,772,253,902,306,657,561,137,842,603,358,40,282,102,813,684,227,268,595,387,453,75,798,379,404,226,268,525,553,79,92,153,310,797,36,523,495,88,353,521,370,545,778,318,504,946,428,707,711,612,85,81,571,91,818,344,916,724,356,520,863,77,633,446,606,867,312,884,805,358,243,22,888,986,405,332,989,912,80,274,441,727,416,7,783,925,398,65,885,763,419,660,373,769,768,452,887,414,301,202,34,240,984,800,192,44,178,743,112,576,988,924,597,684,681,146,778,612,342,667,336,842,797,943,943,191,739,897,815,269,166,4,108,87,992,781,186,279,121,534,291,10,942,855,140,347,280,316,908,826,125,374,308,116,899,527,913,524,25,965,164,702,362,778,159,859,728,494,473,893,400,916,668,409,57,437,426,570,914,894,468,66,673,391,297,913,149,158,118,514,866,280,105,495,594,718,732,849,99,398,393,240,575,14,447,94,513,359,615,602,633,578,152,828,19,965,623,212,301,199,849,257,306,786,241,434,982,311,795,947,249,764,4,835,48,563,574,611,951,370,769,877,750,87,181,601,638,703,474,905,808,116,450,676,873,258,575,687,404,277,693,924,187,725,334,854,210,579,339,884,282,336,653,432,627,906,13,791,542,494,688,298,887,132,103,611,905,246,406,254,696,418,921,310,395,674,978,776,777,374,982,395,523,149,933,657,400,559,842,29,525,162,867,872,383,738,32,37,814,833,489,788,15,927,979,932,170,249,323,994,46,208,376,890,322,241,181,874,855,475,97,246,816,99,407,996,759,477,293,264,428,438,904,16,260,600,944,452,330,68,645,180,151,93,115,811,962,375,113,456,634,320,119,679,3,327,678,589,410,347,477,17,138,351,108,240,770,65,327,704,126,552,470,887,304,505,885,850,250,400,354,464,500,150,647,971,496,98,289,450,182,167,76,604,434,225,875,790,192,457,896,932,558,250,893,982,941,47,738,512,300,745,684,634,264,265,632,676,730,880,187,142,704,383,255,101,195,363,900,235,549,524,259,835,961,983,97,771,253,50,662,880,309,582,308,493,216,166,194,889,610,899,799,735,506,482,103,373,711,71,503,744,765,229,9,74,154,304,130,563,271,938,449,669,431,569,957,53,541,879,446,351,283,531,752,578,332,527,513,593,996,137,637,603,308,839,341,850,797,43,803,96,635,111,549,481,108,865,649,878,191,707,352,214,43,883,430,917,316,230,580,944,65,875,503,358,665,92,528,29,731,252,87,586,462,730,475,484,208,91,552,144,528,272,364,328,440,848,909,163,329,681,259,122,34,291,311,570,860,521,187,685,566,201,882,761,293,722,434,883,597,538,173,369,725,760,604,350,552,944,464,8,280,188,59,182,308,345,675,284,891,54,368,938,166,600,15,968,389,364,718,286,946,223,307,183,387,571,996,448,183,411,263,497,405,784,196,576,211,526,853,657,287,115,262,114,785,860,254,674,95,245,494,134,390,748,430,830,941,768,590,118,477,278,896,500,737,490,303,528,968,648,415,624,552,79,143,241,591,746,681,455,361,759,197,15,59,336,663,515,736,407,964,503,854,549,863,693,323,798,648,948,479,51,740,384,917,685,955,953,560,385,787,443,790,623,366,120,911,598,181,919,42,147,6,691,915,874,669,110,499,632,271,464,717,672,945,320,937,631,20,645,8,546,957,392,269,73,986,98,49,843,84,181,401,567,338,959,860,860,459,731,392,333,546,307,413,458,784,859,735,924,567,415,786,779,985,406,966,17,830,358,102,527,831,892,353,711,834,557,534,654,465,78,101,619,888,662,802,609,605,431,92,525,662,841,461,744,619,516,824,268,959,560,511,286,960,489,991,341,850,307,181,915,545,831,104,881,536,930,317,579,250,923,301,296,574,979,576,931,440,165,448,186,299,796,128,342", + "97,978,424,188,87,393,339,785,404,195,899,514,87,891,416,697,809,507,208,611,445,699,187,455,641,739,661,857,550,968,30,838,573,46,909,510,43,809,861,42,661,902,682,421,576,730,541,984,987,844,365,213,201,503,900,315,182,233,78,892,791,0,234,465,805,969,292,980,982,742,792,352,781,175,682,857,549,758,270,740,76,280,471,374,415,259,524,635,97,241,677,866,824,905,667,952,341,224,66,229,902,333,837,99,49,565,893,817,58,819,769,1000,273,136,478,373,948,908,807,788,722,477,588,432,56,8,245,347,926,80,734,78,553,238,860,248,653,229,852,873,110,123,267,781,621,949,368,667,36,339,692,374,513,388,14,383,918,908,462,80,877,144,111,306,692,334,357,239,873,901,691,97,783,815,688,208,842,25,583,574,92,284,724,62,836,946,834,400,761,37,119,272,647,442,814,679,765,712,348,756,299,758,110,968,570,518,504,998,682,297,339,487,53,107,629,562,856,450,122,64,48,768,190,332,131,562,450,484,834,318,63,245,745,884,963,714,688,83,901,181,848,957,894,561,253,119,113,105,498,262,223,787,191,971,153,9,534,112,247,964,702,542,694,997,11,575,896,230,345,76,341,714,375,104,341,201,914,653,155,71,709,604,658,575,739,382,359,582,538,691,547,468,588,300,106,519,775,277,517,160,480,118,945,363,249,989,539,997,132,264,515,605,741,578,213,675,202,63,868,998,534,143,229,55,340,687,460,410,468,251,804,124,93,529,491,667,69,174,48,671,58,878,182,848,720,671,327,606,453,832,768,926,196,928,889,463,558,248,92,338,243,13,626,990,482,456,621,772,863,476,245,19,645,843,92,614,99,959,904,51,763,753,864,159,412,322,543,812,990,336,822,626,69,654,63,513,806,575,613,350,368,349,133,352,184,583,543,936,145,71,698,966,271,212,638,544,84,406,349,532,348,898,687,382,954,926,477,5,34,313,460,119,112,563,554,458,329,371,247,316,938,668,102,690,46,363,258,600,159,38,219,167,282,159,13,393,304,590,770,375,958,977,284,921,576,406,209,734,727,987,425,846,131,253,393,682,609,838,450,312,795,385,865,73,714,256,464,280,469,181,824,323,729,405,494,667,451,168,323,743,305,439,593,21,886,702,820,764,806,469,993,584,124,294,408,59,290,267,451,530,589,753,613,497,631,652,832,648,645,33,476,665,715,613,446,548,57,746,326,118,903,358,377,44,105,165,24,779,660,609,691,635,265,87,304,373,60,256,437,134,199,349,704,890,710,534,985,602,870,305,846,423,771,603,893,252,596,339,566,348,712,518,842,759,11,947,437,250,510,410,823,552,181,357,911,546,366,225,179,669,268,479,230,24,700,426,887,536,990,935,816,471,908,681,304,915,793,220,837,654,588,721,248,801,571,258,853,772,164,322,474,314,80,750,264,945,884,485,428,29,920,889,826,322,512,735,90,834,5,206,723,526,592,921,903,531,809,636,441,726,640,507,656,138,305,58,152,410,454,423,4,429,86,669,151,181,746,888,293,969,983,977,696,643,155,992,721,994,557,291,71,791,638,304,366,518,687,929,530,656,86,863,314,383,713,134,720,110,90,594,276,421,908,819,607,431,300,547,340,904,273,799,426,70,911,951,365,171,644,576,210,370,214,143,408,892,555,35,921,76,367,900,72,998,602,821,952,410,503,63,856,47,902,70,671,74,546,869,891,577,508,358,817,827,37,298,542,372,237,80,761,329,420,590,87,132,23,36,314,800,290,296,271,316,553,2,445,256,918,873,877,954,746,473,980,346,47,976,350,441,186,526,26,171,730,208,645,380,550,7,348,277,247,384,375,931,270,608,592,860,901,505,388,353,41,539,848,804,559,990,32,818,191,181,578,350,692,23,88,277,802,417,269,121,743,625,924,513,953,564,76,464,601,892,679,805,266,850,4,689,70,277,779,92,645,848,11,81,676,527,634,713,538,4,105,840,814,82,906,499,165,372,858,816,695,876,407,651,912,866,158,323,248,898,524,574,190,38,956,208,427,745,984,899,138,876,427,22,488,777,260,149,976,555,765,561,399,25,35,476,965,745,924,982,513,900,493,424,967,194,881,293,341,246,566,469,338,635,353,565,725,222,401,382,367,322,188,320,593,633,953,940,347,786,613,42,175,976,976,374,414,905,652,332,688,353,857,366,226,579,212,754,298,6,962,789,75,138,20,7,435,148,899,795,644,755,85,2,378,423,68,616,992,164,721,948,766,82,111,863", + "229,214,973,122,176,576,715,292,533,227,845,32,554,255,795,80,805,726,705,5,390,838,821,175,54,891,579,607,202,274,241,389,42,217,534,709,730,67,760,846,77,215,838,90,642,121,42,385,994,833,762,286,449,596,286,648,555,290,679,778,289,234,0,712,545,46,26,566,549,393,476,824,79,281,471,847,614,977,742,537,463,94,242,423,60,657,177,566,584,830,849,879,659,451,334,493,529,234,837,970,913,312,195,637,18,156,11,913,15,907,844,825,672,180,969,879,609,894,246,662,317,630,920,798,343,492,957,707,194,475,680,990,450,338,374,768,96,649,610,597,612,898,859,502,420,39,144,290,302,797,837,442,90,54,514,250,932,951,500,882,13,497,994,568,194,252,687,298,174,552,78,419,117,431,227,306,399,139,538,694,598,816,877,166,953,738,334,381,613,428,794,415,381,401,743,645,904,468,427,141,16,995,878,439,707,944,721,880,906,771,682,864,136,648,674,27,817,901,892,501,797,267,34,964,589,289,842,359,60,980,671,881,330,882,916,688,807,613,83,444,24,325,969,230,853,747,350,758,724,664,287,900,474,91,235,879,557,499,601,891,494,387,977,513,122,78,725,800,52,266,621,87,527,37,375,635,333,268,656,727,262,708,642,611,600,136,600,408,658,962,627,992,660,158,987,90,493,234,737,866,61,193,847,916,813,145,697,458,924,968,331,872,174,330,485,403,856,130,397,245,894,808,629,270,660,884,365,718,304,176,996,657,156,611,586,862,813,484,226,629,508,870,450,454,117,138,468,691,264,155,895,593,464,747,414,481,389,880,833,46,305,496,858,834,561,127,158,95,636,183,776,553,858,548,635,957,653,123,352,824,545,252,58,460,996,697,329,250,906,632,606,844,337,277,399,488,726,456,81,316,139,377,99,549,864,838,69,104,830,409,376,681,991,582,347,422,380,928,307,268,231,980,490,886,453,300,454,273,403,634,697,504,221,668,576,644,43,556,275,696,46,848,366,357,416,504,122,282,580,714,893,108,776,799,734,807,998,319,18,748,544,812,557,409,141,984,209,434,234,955,788,916,137,739,596,642,597,147,55,266,198,253,295,427,134,369,196,867,470,179,705,173,874,199,692,380,575,307,44,925,286,134,997,111,80,759,819,218,857,805,196,644,442,55,877,386,329,770,377,986,39,385,320,162,695,87,102,343,483,905,280,24,646,516,460,744,244,399,78,781,202,818,216,148,421,229,29,926,22,633,801,942,970,510,890,182,103,490,559,46,719,442,773,767,804,194,297,81,760,490,953,522,614,843,68,416,286,150,687,719,361,746,23,967,86,150,25,709,304,522,559,946,821,526,548,640,763,206,833,542,467,278,231,544,536,746,258,750,122,840,622,471,18,481,657,925,297,111,263,501,688,129,980,990,824,564,339,12,232,828,649,86,9,317,890,566,944,543,84,517,322,73,329,50,504,942,594,227,14,658,284,51,738,391,717,893,870,217,616,583,759,581,46,302,71,149,271,992,446,726,327,471,417,291,432,102,726,937,646,602,847,873,564,75,414,289,759,930,913,91,136,220,946,641,751,345,256,349,564,887,761,653,42,422,260,819,583,790,756,884,464,687,505,442,562,776,634,399,491,147,561,844,219,905,294,345,283,383,533,929,456,62,950,225,86,821,435,895,426,599,563,712,926,22,640,812,266,589,529,69,552,857,580,894,132,859,495,418,189,324,356,269,901,842,499,565,818,77,575,563,38,87,602,66,36,96,581,204,28,582,538,120,322,884,760,933,211,549,144,61,802,470,867,873,755,715,419,9,509,351,731,44,134,448,754,829,402,255,137,284,638,816,399,256,314,62,609,621,608,491,35,450,137,23,413,354,519,304,25,213,175,952,774,972,115,846,356,637,295,236,546,109,240,545,205,636,501,122,688,601,979,861,27,530,927,560,701,737,760,379,806,211,673,991,932,870,528,710,369,856,953,999,61,742,695,158,552,856,163,936,382,505,955,974,99,872,480,551,832,951,496,736,909,592,912,256,594,122,884,298,425,312,34,819,785,960,205,127,600,54,566,142,70,567,690,165,51,69,984,988,331,338,101,658,270,327,596,375,747,220,434,758,613,269,940,552,828,967,929,84,342,475,171,418,457,768,705,131,728,835,397,670,777,606,692,770,153,576,603,349,857,419,799,486,132,704,309,193,174,369,881,567,647,475,82,151,218,64,610,386,111,92,521,615,530,961,748,826,171,625,692,331,638,118,382,20,923,53,273,439", + "734,629,187,919,376,675,810,660,218,791,307,906,476,22,542,283,954,978,846,695,678,363,18,3,493,25,260,617,615,799,888,175,862,328,304,631,703,431,289,387,655,835,848,402,695,10,786,833,786,882,658,258,112,459,411,709,966,69,687,882,974,465,712,0,739,89,31,583,342,766,330,753,614,371,646,418,50,260,811,127,182,446,71,913,538,225,789,357,728,51,758,732,22,89,820,376,600,610,91,6,163,365,546,569,448,195,574,259,557,91,44,2,916,523,369,321,783,24,670,699,985,414,959,751,196,538,556,593,310,321,361,985,620,479,283,681,436,8,585,383,948,417,492,906,218,533,332,878,185,603,400,543,798,232,325,45,391,833,27,314,471,276,403,659,87,496,644,697,154,878,141,711,822,924,27,944,106,620,809,530,92,899,632,955,22,856,599,254,38,98,787,58,132,737,374,310,612,550,802,240,121,314,682,618,473,911,395,733,139,599,424,986,358,308,593,969,167,560,82,322,386,513,9,696,923,549,992,827,670,756,439,203,312,566,170,848,911,387,238,484,707,553,554,457,860,981,452,597,299,262,587,796,114,553,808,530,171,204,914,333,462,440,569,742,825,170,860,593,318,784,386,918,649,145,327,279,97,478,528,510,819,78,563,151,724,143,549,67,646,323,700,87,139,460,716,123,926,801,638,652,955,129,143,542,327,336,196,464,432,952,556,129,199,137,555,499,612,612,846,316,665,64,825,118,448,106,945,864,32,753,155,5,810,449,761,374,925,712,578,314,339,612,296,878,861,213,260,419,369,75,304,460,952,273,519,290,311,429,733,202,875,867,918,236,483,345,38,572,272,864,425,486,186,938,295,579,574,866,356,169,897,809,167,289,383,68,236,96,552,701,710,97,461,8,402,866,880,642,920,707,889,208,260,749,563,590,361,142,601,256,811,567,679,58,404,981,23,659,28,815,386,855,131,261,787,197,254,827,572,666,575,365,305,361,280,440,659,732,615,66,511,494,120,248,678,504,476,956,910,924,742,90,49,890,434,537,327,90,579,886,228,377,606,18,136,798,138,747,857,925,683,465,529,739,32,334,487,241,904,6,744,700,851,5,874,865,515,45,186,154,326,206,214,668,354,732,468,563,862,512,182,272,787,90,726,891,637,875,959,388,691,318,541,191,888,23,602,624,929,866,300,426,638,415,379,826,226,671,794,980,624,459,900,495,42,844,359,543,109,137,100,429,480,928,545,858,369,707,526,809,700,968,149,853,778,425,345,938,581,889,330,484,377,86,671,970,728,726,548,558,97,798,34,834,934,787,890,557,680,12,773,489,878,384,614,623,333,152,675,746,776,3,417,751,803,531,684,45,196,537,295,641,425,570,677,194,658,449,351,241,660,893,631,91,92,330,296,488,754,713,989,144,247,34,673,277,386,415,310,787,930,592,450,652,486,664,970,701,317,230,704,397,162,496,579,460,133,348,826,980,112,993,69,387,328,28,972,67,469,970,242,29,62,959,269,378,606,967,443,329,607,357,947,486,201,653,305,445,461,887,630,462,944,118,211,337,587,333,736,913,505,340,781,163,658,547,146,702,243,688,19,196,587,719,241,77,66,582,30,669,853,382,962,255,348,351,890,310,201,897,346,169,595,596,281,80,67,65,441,319,450,282,695,422,620,610,181,602,927,947,450,388,949,223,357,605,182,250,440,102,790,472,123,516,174,159,317,366,596,81,855,11,861,61,14,512,340,986,842,676,900,112,22,847,574,645,329,593,503,899,149,130,173,109,312,262,863,88,593,915,857,778,647,987,130,85,138,422,755,199,934,894,149,686,63,250,635,670,135,479,846,724,732,75,11,743,254,350,498,240,543,712,245,652,565,862,48,185,643,561,667,100,812,961,753,984,945,667,910,147,410,165,116,245,297,236,937,615,421,183,983,380,957,179,711,50,228,609,190,828,336,990,259,913,289,214,303,943,445,868,261,29,265,705,568,865,330,679,904,686,575,618,868,473,643,110,815,970,558,877,332,882,191,11,615,66,664,446,15,585,252,172,665,728,64,719,576,663,364,399,328,495,437,898,495,318,672,895,152,669,707,632,976,311,101,882,825,117,906,271,365,65,190,399,367,235,434,402,881,901,879,638,517,500,747,410,783,4,953,372,367,821,245,79,568,642,59,522,235,140,201,279,797,169,879,643,716,874,329,86,124,748,378,134,486,345,399,102,715,491,863,925,985,83,64,279,762,551,181,998,724,337,782,546,13,190,272,163,607,446", + "829,781,553,600,531,456,819,971,244,853,420,660,847,446,26,626,160,615,944,103,550,740,426,589,515,734,273,767,371,314,678,673,473,427,818,550,481,167,366,568,499,136,727,435,641,666,982,142,590,61,710,314,87,776,567,634,340,745,713,708,149,805,545,739,0,808,797,627,19,445,180,328,617,876,310,901,870,922,11,738,770,914,728,195,986,869,457,253,698,536,710,600,594,966,967,381,729,5,209,745,93,86,155,492,143,117,864,902,479,842,215,399,249,326,697,410,58,578,467,450,275,955,520,18,365,803,861,240,133,74,51,872,617,317,385,231,996,279,751,857,635,994,255,386,83,124,545,585,979,27,122,245,84,376,727,389,169,939,26,9,113,917,1,27,132,472,939,246,334,184,928,343,179,406,330,844,574,798,373,9,777,505,355,907,641,714,13,397,742,600,190,941,820,336,19,319,607,576,349,254,923,947,590,175,551,106,509,440,69,131,297,569,198,601,680,191,209,371,41,847,104,945,329,971,872,467,374,37,760,197,114,343,404,101,814,223,505,7,419,792,954,971,779,759,331,24,579,251,713,321,972,583,690,706,373,937,1000,678,413,242,4,941,625,204,884,372,985,696,4,15,983,551,984,632,352,745,122,667,957,13,769,35,539,288,396,707,7,775,365,410,2,351,127,998,415,108,954,693,523,877,640,63,383,354,71,772,772,607,120,398,765,82,590,170,650,441,238,995,993,717,610,564,350,246,850,815,181,230,554,392,685,450,180,129,92,86,914,91,298,352,462,111,182,116,802,59,139,68,62,504,603,8,931,549,663,886,730,789,818,938,556,301,83,208,692,896,331,46,553,722,687,756,990,504,723,6,906,879,877,32,772,154,39,321,111,227,67,366,462,212,29,986,741,976,209,115,992,136,478,637,757,930,57,505,784,213,735,707,910,915,163,896,710,7,651,870,637,151,967,712,248,791,47,364,453,359,865,303,979,450,901,884,759,10,863,260,235,119,454,134,681,771,520,369,580,770,163,516,58,44,194,842,923,987,425,306,210,114,387,345,283,632,406,769,676,143,457,75,890,192,73,548,574,815,612,365,717,779,191,984,747,313,709,55,917,409,852,858,210,78,904,757,943,278,488,386,930,926,472,3,528,157,245,766,754,326,747,907,35,624,841,188,345,251,911,901,799,618,955,437,382,233,9,679,129,519,859,348,350,625,415,175,6,6,330,468,163,618,555,327,971,498,494,948,320,239,745,278,103,509,945,773,828,313,309,984,845,128,764,506,625,255,865,797,323,196,995,390,36,308,24,258,690,542,759,461,719,170,347,253,590,79,349,783,249,693,589,222,802,679,23,90,704,361,450,118,194,391,27,517,375,461,527,562,50,783,792,286,23,406,183,386,980,908,379,558,415,764,950,580,692,330,325,83,461,66,655,509,129,818,571,439,598,269,344,848,275,456,332,402,228,853,769,354,73,381,915,774,133,360,783,670,101,411,794,951,149,280,113,555,507,515,193,39,447,488,787,980,589,643,703,383,106,803,969,401,982,773,848,768,865,683,939,793,155,743,673,970,168,533,106,70,743,641,348,665,389,585,70,583,469,104,129,117,991,843,834,310,235,66,597,300,82,809,322,662,233,857,441,466,70,625,20,177,418,380,919,856,65,269,554,495,808,584,724,631,952,407,870,773,388,706,809,374,846,502,769,356,802,720,579,52,910,918,58,468,575,85,806,868,199,848,879,767,76,451,681,476,176,146,606,942,441,233,548,536,68,352,445,908,234,244,906,948,624,284,399,218,442,441,104,572,526,138,397,344,501,604,168,166,579,213,808,139,227,238,813,755,297,363,18,37,142,207,554,930,262,601,812,654,621,637,699,825,972,137,811,576,962,40,428,569,725,481,596,476,394,555,887,188,623,433,851,323,310,467,467,417,946,445,294,612,8,704,537,554,727,985,263,158,362,114,181,564,339,190,753,103,794,11,11,993,507,31,253,764,235,199,965,638,483,96,637,933,382,896,92,764,127,295,843,82,649,384,302,687,694,783,382,744,571,527,954,113,409,209,219,920,375,973,306,344,303,297,217,243,193,259,988,916,404,851,547,205,408,326,819,490,590,363,263,831,973,982,474,176,484,98,886,380,921,120,591,221,573,240,522,569,822,280,952,383,710,813,111,860,450,828,687,157,920,923,280,146,931,891,737,538,915,718,571,277,632,377,845,609,77,6,773,213,17,522,473,770,803,376,396,559,826,487,239,482,130,258,219,554,335,355,584,5", + "324,358,859,45,656,939,945,74,681,739,634,831,195,569,225,159,645,539,668,414,584,377,800,602,412,46,700,644,574,56,871,803,453,435,730,340,131,780,519,305,786,218,170,989,548,706,982,311,488,303,988,313,780,297,180,385,865,181,746,395,803,969,46,89,808,0,405,196,872,53,810,342,341,40,31,677,390,974,42,361,27,624,334,893,32,603,38,414,588,33,126,437,142,337,40,161,737,188,374,215,817,33,532,37,221,738,37,77,498,519,129,809,396,904,92,642,819,199,920,900,47,848,2,564,416,123,103,955,907,745,929,297,902,920,694,47,703,285,905,226,977,449,73,28,173,403,620,459,175,227,52,173,37,67,190,54,751,944,813,23,128,458,988,340,853,317,456,55,538,541,309,465,466,107,16,847,675,551,109,906,119,971,551,615,943,450,617,175,900,639,549,386,39,350,197,552,322,14,383,904,173,889,443,312,163,53,129,636,289,395,362,485,934,96,135,393,50,827,660,460,414,88,253,796,501,437,67,662,968,482,479,285,954,587,479,312,983,667,366,38,291,333,818,158,201,658,546,915,427,737,744,612,694,482,303,540,84,740,442,330,812,979,976,12,574,887,934,135,526,349,149,957,399,891,429,496,178,488,619,91,965,669,294,561,267,13,414,419,551,784,315,767,34,591,284,263,489,228,619,684,729,697,97,324,696,715,386,271,251,17,29,186,249,642,241,320,836,624,809,629,538,552,731,675,693,76,831,734,680,821,468,916,307,743,142,465,551,784,80,302,546,665,408,804,738,134,350,429,600,988,527,827,279,197,543,7,223,548,828,714,251,567,578,413,272,600,901,333,993,429,995,750,936,341,261,546,66,726,995,682,755,225,422,306,106,600,603,199,808,329,961,187,403,725,300,329,635,825,676,133,545,938,295,438,652,458,891,900,38,702,895,748,758,719,769,248,32,216,498,972,701,783,610,753,757,734,426,707,475,568,119,869,525,455,652,695,228,381,409,878,218,895,427,363,825,791,655,454,874,790,791,84,711,391,242,294,921,650,549,908,774,846,56,69,633,334,787,22,610,814,682,504,312,581,16,988,318,331,571,909,124,650,880,201,554,297,439,285,978,550,723,636,692,188,617,949,742,594,49,826,354,616,365,662,862,488,241,895,857,436,268,813,55,751,89,415,446,579,626,871,787,862,625,162,54,324,141,211,420,728,104,695,182,865,9,871,645,439,561,321,752,452,103,269,836,1000,644,307,625,403,747,434,725,6,608,744,568,895,505,856,917,300,166,280,978,393,153,556,769,254,125,842,62,333,171,455,282,422,750,274,218,130,170,900,989,917,154,308,104,279,816,606,597,430,41,598,642,483,190,827,224,273,897,862,769,772,198,55,989,974,129,747,491,822,822,80,833,604,152,127,870,33,783,237,822,678,523,444,653,53,317,630,756,955,378,1,492,655,22,30,247,649,906,257,516,128,723,574,480,546,406,429,529,896,894,221,151,494,998,482,655,86,366,536,644,222,904,767,186,436,80,756,129,436,536,405,94,479,513,753,302,486,396,453,649,444,324,613,395,663,293,775,679,340,693,69,476,638,382,274,947,948,221,998,214,148,451,64,186,620,441,29,778,246,94,894,41,417,519,845,734,302,703,375,906,390,871,733,313,967,606,832,656,71,752,692,873,596,468,529,708,893,365,170,171,705,520,187,920,715,395,569,763,148,621,321,323,49,783,797,442,541,403,590,589,589,171,595,971,999,964,708,198,282,296,280,158,428,210,393,996,127,336,805,723,842,656,380,597,164,372,308,770,901,50,221,117,728,466,150,294,533,515,823,719,755,306,788,249,888,83,369,662,79,710,102,823,577,921,91,298,352,234,919,297,263,789,626,855,964,941,649,774,353,817,92,847,794,527,591,115,420,860,536,651,979,328,567,973,525,725,226,396,452,818,606,120,808,206,259,985,362,990,851,102,666,523,691,486,530,251,607,142,122,31,38,250,101,272,449,929,871,993,786,646,50,996,199,836,357,210,430,390,825,149,752,507,877,442,162,967,111,241,324,922,453,150,56,821,740,224,699,998,954,342,904,771,426,588,77,434,233,801,290,396,194,422,459,411,425,939,850,290,20,733,429,830,363,958,156,259,819,44,25,923,232,545,829,212,58,893,528,129,289,758,289,478,2,408,299,170,123,838,233,47,508,603,552,244,2,249,287,213,157,526,828,555,178,653,347,344,106,57,16,670,204,235,654,296,48,912,710,911,552,522,873,872,22,903,597", + "917,941,381,473,959,788,897,410,924,158,460,705,19,488,147,963,63,989,919,217,783,333,223,871,568,598,600,882,461,563,753,246,891,133,355,107,94,782,158,771,700,592,867,509,157,829,776,526,994,311,143,386,969,349,129,641,99,16,498,346,336,292,26,31,797,405,0,901,681,982,797,778,461,609,445,24,668,1000,786,31,410,833,203,120,723,521,677,28,567,924,439,754,263,437,888,956,152,439,258,274,845,682,987,559,160,779,729,819,155,609,967,641,706,669,285,115,458,522,55,249,966,667,122,267,518,546,563,401,291,993,535,876,294,254,691,616,284,114,706,585,921,743,739,139,732,215,276,420,388,226,346,586,186,560,598,54,648,802,956,273,165,350,929,391,109,121,570,560,745,388,323,461,635,561,989,519,69,349,22,348,725,181,447,115,579,854,818,700,972,305,445,253,163,243,904,595,850,814,174,379,627,401,552,42,171,766,664,132,853,426,633,258,933,225,101,686,715,984,257,343,987,755,704,732,392,271,513,777,275,501,852,93,32,652,873,314,247,212,690,439,786,89,297,502,375,534,722,826,224,764,302,198,660,726,805,186,589,801,158,89,564,432,437,624,589,181,916,11,601,415,692,290,893,347,810,607,917,529,344,531,879,443,606,676,252,993,244,994,971,843,22,946,801,157,658,899,731,416,340,802,742,278,606,241,428,846,110,584,269,921,470,125,203,849,406,957,663,995,980,112,342,783,828,448,605,956,439,564,439,976,32,198,109,310,648,985,627,995,572,574,560,385,166,239,671,481,431,193,95,684,546,507,116,370,301,831,780,847,747,651,410,904,184,193,861,661,921,761,828,821,676,61,980,917,729,324,42,952,516,321,8,600,941,245,376,663,186,320,318,886,723,291,986,480,126,492,77,198,787,820,672,95,353,967,792,456,924,364,951,619,973,205,434,194,131,228,114,965,57,33,876,259,965,674,806,876,461,191,880,405,20,747,453,13,415,946,919,496,946,357,982,507,392,697,558,913,442,254,109,973,7,495,657,675,846,578,447,726,954,711,652,815,444,187,890,744,165,660,112,910,713,96,832,409,417,312,222,832,227,57,364,751,43,194,680,120,712,703,655,597,930,259,755,478,829,373,294,548,490,765,376,122,167,328,363,863,351,502,801,627,100,779,498,939,590,486,185,407,260,315,723,871,108,593,290,373,253,826,791,355,409,143,957,806,381,866,246,563,49,847,606,201,957,502,976,128,463,223,797,203,785,446,444,627,731,379,892,119,727,423,877,426,968,767,854,365,125,138,593,635,436,503,318,618,38,421,988,852,294,864,311,624,724,281,310,262,9,908,193,633,630,467,20,523,100,520,896,149,120,576,791,392,81,640,90,722,9,400,875,561,508,98,968,106,76,980,979,720,788,634,77,314,107,231,601,479,872,478,316,54,893,984,219,143,196,323,641,382,992,134,47,940,604,800,488,498,98,431,787,335,339,233,898,251,953,321,78,696,617,770,393,8,3,42,160,982,142,264,257,263,908,894,299,963,778,244,565,523,693,652,395,740,788,3,986,597,565,422,418,887,569,842,421,587,324,4,781,922,523,411,73,380,968,232,869,675,108,239,456,650,678,694,151,388,431,286,880,264,646,701,867,214,220,602,746,782,325,484,756,426,927,14,456,958,152,967,890,248,564,814,706,312,516,775,269,309,798,777,528,555,976,419,29,397,591,556,415,810,514,847,915,295,364,45,481,484,173,208,761,621,675,246,217,629,332,666,526,951,348,152,505,166,310,167,11,603,426,694,379,918,623,485,111,654,361,725,88,756,272,491,699,365,538,515,73,937,588,685,331,926,418,57,760,825,471,308,868,317,481,75,327,73,633,496,299,175,195,537,305,341,820,209,424,743,25,755,889,789,472,340,105,943,855,252,478,191,431,732,600,416,233,801,16,322,381,776,873,528,88,76,758,419,350,105,767,538,432,21,819,713,226,975,894,239,301,491,900,316,516,793,387,642,942,193,59,140,364,940,510,453,269,90,848,772,660,230,992,336,878,784,481,603,54,878,77,198,779,978,229,98,755,214,89,199,716,45,145,961,80,75,779,917,661,657,531,531,742,593,347,365,660,79,182,574,727,777,530,248,374,663,369,496,405,43,176,193,900,679,857,742,659,859,196,237,229,529,317,22,193,40,864,854,391,735,282,519,766,761,17,147,61,754,801,871,314,294,143,123,82,563,686,781,224,901,570,316,910,753,139,65,389,624,517,1,597,717,207,795,919,578", + "380,962,51,37,381,887,607,654,640,898,995,293,3,980,801,640,139,338,230,81,111,222,405,700,605,521,204,454,425,488,546,587,955,32,644,628,972,171,114,189,126,401,525,423,42,350,774,407,505,633,26,345,761,623,469,168,86,761,680,463,442,980,566,583,627,196,901,0,99,973,768,99,49,130,285,432,649,634,199,608,892,124,598,771,776,991,346,21,817,628,631,866,240,494,698,524,84,656,669,941,532,383,606,291,487,676,276,622,680,360,192,60,296,860,907,891,980,683,410,870,635,749,279,427,186,250,216,397,365,393,108,219,223,446,794,78,197,723,490,374,139,234,850,634,662,85,882,951,22,596,268,18,999,466,681,165,172,212,507,740,123,109,302,141,28,201,973,885,993,241,813,322,290,181,111,738,68,426,727,147,411,881,9,551,109,370,873,168,576,551,91,423,241,605,399,321,110,14,691,849,588,917,350,115,605,282,137,950,314,872,955,958,463,467,306,686,25,824,150,24,875,858,251,128,789,637,171,521,763,165,52,556,847,362,586,730,447,690,595,195,264,896,802,257,955,378,152,551,448,594,422,753,177,500,916,379,49,780,904,397,52,836,432,857,960,793,362,881,975,144,27,736,848,248,819,554,537,36,258,15,33,876,745,301,29,207,824,803,717,782,285,579,830,71,512,815,667,637,415,805,90,852,569,440,114,466,878,897,912,932,636,416,568,702,174,640,533,189,317,702,883,126,45,927,977,525,240,499,145,44,99,746,266,662,669,372,790,939,701,497,209,697,569,86,350,794,614,848,166,206,866,403,805,638,753,983,800,513,288,229,346,548,854,771,434,87,948,641,870,564,356,600,307,329,175,214,652,548,900,231,428,657,537,165,809,7,599,872,453,760,354,785,483,245,591,489,242,209,48,582,476,718,462,626,947,942,785,921,147,932,621,596,641,171,302,879,308,803,94,504,147,461,347,279,450,491,321,160,116,181,798,13,796,325,356,732,458,106,71,479,995,267,961,177,205,599,546,228,461,448,611,970,204,628,522,468,957,437,741,476,760,720,995,78,725,939,228,23,82,379,685,637,264,57,726,585,860,848,544,594,812,901,187,600,855,884,153,334,288,483,745,29,949,103,550,637,552,828,181,438,115,259,88,539,425,868,77,636,415,91,714,58,822,440,889,600,917,634,843,668,122,759,449,271,531,84,965,701,816,572,917,93,154,695,580,49,236,216,411,69,296,494,884,983,45,422,586,418,205,718,546,591,90,70,445,275,354,520,804,962,567,378,398,681,889,83,50,201,948,884,477,847,886,607,740,869,441,954,738,801,417,604,202,758,215,959,261,176,700,625,670,920,636,440,549,131,939,277,834,526,238,568,629,701,274,373,818,119,326,51,360,745,135,143,368,393,849,63,288,986,40,717,367,258,14,711,870,954,309,712,216,677,653,53,53,819,460,905,222,766,255,531,343,350,223,708,499,692,851,415,810,878,753,852,158,628,284,897,88,224,400,148,948,914,27,853,627,543,706,492,299,241,794,165,216,445,674,600,354,120,251,396,742,137,397,909,545,760,483,196,823,492,980,700,691,139,497,958,239,740,141,2,208,217,721,745,830,123,181,36,186,922,48,232,704,206,744,807,327,157,440,603,999,156,6,440,409,888,70,485,548,184,933,545,597,205,247,656,583,650,519,343,847,893,410,591,968,710,98,287,446,604,392,834,768,328,72,567,480,977,642,510,390,826,226,399,126,565,7,618,369,677,337,156,69,986,65,664,848,540,530,413,955,705,845,232,659,202,827,474,504,777,156,232,247,740,596,333,553,759,635,263,165,655,136,980,740,253,290,216,882,566,600,21,953,933,613,108,847,615,130,250,428,201,616,418,736,706,171,43,973,912,869,149,576,673,319,394,31,762,917,918,760,405,42,929,290,387,354,736,598,316,283,448,677,837,561,822,916,933,101,355,963,509,549,872,591,854,501,421,242,783,32,981,426,415,662,385,455,499,291,104,168,128,165,344,544,305,547,705,647,387,692,699,871,70,960,642,929,713,942,827,859,631,942,484,970,904,325,148,456,851,139,420,10,439,756,308,885,960,679,171,817,534,774,156,761,131,524,787,239,630,609,301,293,872,661,36,522,206,852,443,715,33,831,176,706,646,761,890,981,808,541,771,93,878,158,11,423,86,983,861,566,501,687,829,730,810,864,876,981,809,261,441,827,66,397,813,211,624,745,921,762,168,605,64,878,523,946,351,922,154,527,818,35,245,232,514,272,554", + "817,144,696,105,929,922,144,894,849,390,662,929,745,299,708,734,986,870,828,545,805,86,95,319,121,348,844,293,659,650,449,725,227,973,826,666,304,630,203,985,53,512,171,285,105,574,430,612,801,845,323,142,667,522,148,699,926,876,280,227,841,982,549,342,19,872,681,99,0,748,373,915,594,615,822,710,140,285,686,590,99,311,556,166,61,351,269,859,142,860,475,325,86,393,89,160,515,331,154,529,216,379,314,6,458,323,227,961,113,624,392,583,254,411,107,182,991,492,793,382,239,354,602,803,676,250,62,252,832,979,322,16,276,681,575,624,191,399,823,47,126,63,886,575,347,855,181,534,44,845,679,64,540,917,551,815,207,765,238,88,852,849,793,161,827,437,427,17,8,11,488,851,841,172,628,747,645,461,346,664,734,849,567,117,71,591,278,193,20,811,760,408,875,396,401,303,664,843,868,296,992,648,104,948,829,37,15,544,44,854,58,147,945,50,990,969,734,258,776,616,881,240,355,196,661,554,267,621,570,924,843,478,413,971,743,688,317,699,676,236,301,171,614,845,679,790,473,458,677,628,755,38,657,309,647,855,973,826,221,299,458,745,910,171,258,640,854,424,170,739,426,31,129,377,399,138,205,196,64,957,172,375,689,343,234,631,196,658,402,883,919,497,872,701,499,835,694,469,775,326,194,995,866,840,369,95,189,709,848,449,462,320,316,314,881,675,226,92,390,585,189,897,747,697,928,553,834,822,28,144,762,325,40,244,773,335,919,27,243,897,856,367,732,820,565,513,875,206,837,322,264,400,498,500,558,218,221,440,963,472,218,888,377,999,615,93,438,726,382,7,103,998,411,503,99,857,41,594,531,835,900,694,44,139,585,217,750,179,799,934,886,980,255,299,722,716,848,694,167,542,440,439,291,444,835,364,447,719,305,833,59,620,432,126,445,979,138,879,45,585,737,331,172,97,818,898,798,198,248,390,83,263,343,118,106,990,379,906,795,462,226,219,282,831,197,640,318,278,248,68,529,32,106,698,302,23,757,828,69,720,299,571,658,835,680,407,351,763,650,177,282,413,516,159,487,175,800,909,16,975,347,239,744,763,729,189,880,935,750,785,420,986,838,572,511,410,658,84,954,627,541,435,957,384,633,74,250,258,442,901,726,891,325,155,300,187,456,893,926,778,559,181,646,446,309,792,304,457,26,767,150,460,543,224,300,371,921,377,677,149,550,955,653,812,394,961,523,478,802,323,571,579,909,526,888,998,219,901,238,725,264,759,577,509,94,281,17,525,911,686,386,557,730,788,879,325,701,970,379,740,401,507,974,366,843,68,113,733,954,633,191,10,713,343,447,655,715,38,525,145,955,43,783,844,928,201,794,832,803,706,561,885,782,900,743,249,596,74,408,561,874,482,609,791,27,618,378,715,889,415,276,841,1000,220,146,513,83,131,991,101,20,808,276,270,335,800,720,715,291,523,833,972,267,937,743,767,629,77,737,380,767,762,84,813,549,538,815,238,219,118,965,122,866,672,34,564,275,922,829,54,976,89,949,55,276,197,79,717,77,206,494,221,16,729,299,497,418,567,432,722,154,851,572,703,498,865,308,729,966,790,336,653,46,970,744,509,602,569,350,201,786,749,356,249,551,918,474,306,126,720,142,245,160,283,390,126,630,9,321,268,981,167,928,219,634,547,485,537,390,796,338,538,800,834,830,984,223,978,512,822,71,729,902,603,928,391,975,205,504,402,427,471,105,955,653,686,778,352,58,448,591,923,453,237,254,454,348,995,806,647,873,788,96,779,583,982,926,41,138,168,252,496,293,550,847,571,94,2,523,284,207,392,545,961,353,889,599,557,533,521,521,178,247,786,561,50,171,140,136,655,219,40,179,228,623,893,651,325,308,146,502,253,53,970,87,821,304,16,879,891,764,494,996,217,767,931,48,72,595,823,302,743,791,89,357,550,745,632,162,587,931,137,697,909,712,301,204,61,797,520,386,470,395,845,388,862,612,800,593,963,831,70,807,100,822,310,164,367,772,946,106,464,145,209,686,779,86,795,375,649,723,367,752,499,400,38,877,935,822,7,358,905,386,296,795,746,103,664,102,92,635,86,25,261,413,730,788,894,195,788,201,717,566,629,337,424,554,701,959,780,143,147,485,918,125,382,313,45,793,69,725,31,156,992,878,873,869,309,781,925,928,52,603,459,824,709,975,876,441,275,400,390,980,118,122,473,129,214,268,496,179,481,171,467,601,586,131,661,67,817", + "597,609,343,517,609,858,862,494,880,180,779,793,892,928,703,917,676,1,211,573,122,171,286,567,540,95,449,696,412,887,666,687,958,925,153,492,414,686,857,806,775,660,636,285,384,223,83,932,246,962,707,532,22,408,152,3,35,976,15,841,606,742,393,766,445,53,982,973,748,0,625,620,237,89,87,711,953,431,764,479,692,108,145,651,190,146,838,706,813,169,118,565,684,374,720,519,68,546,941,459,408,419,979,660,413,225,390,777,563,281,770,140,716,977,68,721,712,100,627,219,810,794,526,213,423,669,994,947,977,485,883,825,487,612,593,900,267,142,461,712,176,825,123,684,392,250,245,321,769,251,204,226,48,510,978,754,890,282,992,726,699,344,344,603,785,659,409,697,441,513,308,343,659,339,349,780,947,357,786,318,222,89,606,327,208,388,747,153,490,288,762,497,844,760,53,218,32,759,516,870,816,571,915,712,820,361,2,182,425,252,598,750,172,856,478,590,120,954,283,182,663,956,749,284,824,850,180,73,962,152,783,449,532,977,741,678,842,45,621,548,245,595,516,963,362,742,726,704,441,112,236,964,301,678,640,240,428,808,645,516,48,410,896,401,590,723,14,829,358,656,902,75,899,240,650,894,757,565,196,172,217,477,138,528,863,195,913,91,466,792,174,426,711,788,71,119,830,221,258,47,252,812,119,904,484,331,169,650,260,45,91,391,308,832,223,96,530,187,104,74,95,940,859,382,802,818,50,65,101,240,227,67,751,20,625,966,91,973,241,2,20,317,348,178,34,493,810,608,668,359,739,857,965,886,335,912,247,702,359,585,718,81,804,225,89,587,659,726,230,765,686,418,397,902,889,146,537,24,780,822,816,560,81,248,438,172,787,27,903,332,594,50,221,499,506,899,175,228,137,437,28,26,690,827,401,236,251,691,886,987,497,993,727,813,581,920,537,252,228,747,348,815,35,911,855,90,838,100,322,559,599,673,918,152,311,818,831,809,887,786,304,51,983,437,702,957,156,895,40,6,898,587,294,982,592,697,105,128,515,40,958,705,780,440,616,438,920,841,317,717,464,184,808,290,50,591,328,357,276,2,906,872,611,869,272,555,749,896,926,410,873,962,864,613,70,406,546,144,910,813,463,555,712,649,506,467,115,70,460,907,667,311,338,37,153,985,505,985,938,426,311,579,683,710,198,157,500,704,528,338,943,829,378,384,265,415,166,128,912,54,152,940,960,683,603,947,1,872,48,686,362,157,847,155,86,443,322,265,688,868,526,899,466,459,328,716,557,443,175,237,899,95,601,289,381,289,465,845,350,603,856,543,809,751,748,126,789,354,227,736,510,412,776,335,632,820,468,433,765,447,267,203,404,468,327,509,951,9,107,777,71,897,57,196,356,143,137,486,256,571,7,979,822,250,190,66,484,191,980,902,552,988,414,275,171,754,258,113,929,997,505,138,710,145,854,953,314,271,548,799,323,722,405,608,644,31,70,697,672,332,293,234,175,64,495,269,199,570,567,13,837,813,566,409,182,8,877,782,940,87,949,934,365,316,601,709,920,650,512,876,971,423,996,12,697,93,113,304,248,587,908,843,265,240,414,792,292,426,26,780,426,123,623,959,450,301,436,952,46,134,925,426,357,336,158,421,650,890,80,299,895,54,748,228,104,816,247,227,579,756,453,240,56,350,229,299,566,156,733,478,482,135,498,491,665,400,5,204,186,744,497,621,726,123,263,15,668,311,819,391,965,244,250,302,345,726,307,481,979,718,508,601,53,353,996,680,356,182,437,151,500,550,552,387,710,721,587,984,894,602,22,183,566,590,224,940,321,827,15,95,638,77,764,443,164,658,142,252,336,398,693,303,892,88,612,18,897,264,823,305,467,998,294,607,824,569,895,610,675,960,242,391,421,801,744,472,324,821,359,395,381,558,196,696,216,555,254,77,834,265,396,288,214,916,350,156,814,131,268,775,504,611,838,929,997,732,58,155,499,13,129,541,834,518,404,525,106,185,311,278,298,230,242,23,269,463,587,330,414,454,989,854,788,509,904,207,592,499,885,121,718,524,644,488,191,636,913,812,974,115,815,205,919,975,852,210,708,967,858,119,975,183,836,445,621,960,523,616,112,295,307,886,825,562,991,130,910,337,65,820,605,692,97,8,858,283,149,561,659,648,910,681,600,793,573,3,253,258,155,333,447,898,36,932,572,969,932,506,636,347,83,569,547,372,881,36,225,173,927,483,158,537,953,474,900,998,86,537,610,694", + "461,629,79,619,312,606,835,772,78,403,939,341,732,550,382,633,831,883,293,987,112,794,638,456,805,142,907,937,548,162,408,82,102,796,261,999,269,553,217,458,324,310,152,698,508,597,332,686,509,279,419,224,215,110,858,683,777,558,985,694,101,792,476,330,180,810,797,768,373,625,0,189,957,393,629,141,569,908,187,922,20,449,125,277,949,957,658,827,116,78,577,901,428,540,851,310,89,651,102,488,979,680,364,780,938,197,182,970,670,965,184,287,939,778,731,597,105,481,569,10,958,238,811,705,670,228,714,442,13,590,889,931,338,940,575,473,400,350,679,564,17,197,81,709,60,449,729,921,834,698,735,555,51,223,567,261,791,264,231,762,817,74,702,967,248,448,423,172,923,94,129,625,414,766,300,587,537,767,38,133,247,424,574,848,156,281,389,266,2,101,140,557,367,893,823,448,82,106,297,706,751,44,500,176,751,546,452,340,996,129,564,342,68,628,453,995,274,288,689,356,288,586,713,676,938,30,357,832,760,4,245,459,958,371,493,978,948,190,201,219,335,916,546,748,963,464,914,871,381,203,698,161,481,657,927,677,207,385,110,651,807,986,989,67,537,519,840,730,511,603,131,55,785,57,335,2,395,636,216,180,884,53,276,6,400,704,433,888,288,698,552,699,253,352,172,522,991,278,665,793,102,582,520,676,707,698,995,47,283,537,481,568,487,576,224,881,34,492,912,741,936,971,911,955,107,59,728,760,986,940,736,43,220,232,534,749,855,756,564,458,119,923,995,571,4,342,90,527,364,518,226,626,682,864,737,31,682,845,639,424,664,911,924,659,228,509,509,458,499,633,232,930,597,311,804,967,508,466,992,266,548,160,964,728,687,948,205,208,745,374,102,734,653,848,687,638,815,930,42,955,843,192,476,315,116,273,22,876,264,492,690,525,702,528,217,263,801,527,275,59,1000,747,519,136,526,431,148,12,151,777,678,489,97,253,706,870,658,536,367,458,329,229,965,989,718,468,971,911,401,454,813,453,932,185,977,5,196,534,897,898,82,193,153,857,976,714,131,756,148,793,621,753,921,100,247,359,491,320,676,139,821,217,640,918,431,482,182,875,385,664,708,604,659,65,138,920,182,448,186,999,666,903,791,647,323,984,166,311,34,961,274,8,552,214,952,834,50,216,395,78,568,348,565,280,965,570,529,10,588,175,380,624,880,532,354,353,172,466,29,404,598,967,508,43,680,282,521,224,47,805,108,533,201,197,908,856,104,833,772,492,232,651,646,345,382,115,575,271,312,501,827,935,144,569,284,389,555,377,805,331,254,136,501,441,903,735,771,295,276,669,18,301,485,255,673,7,683,24,334,396,946,798,667,797,754,596,320,726,719,536,313,418,753,685,998,610,242,428,638,552,289,253,88,606,137,776,621,182,240,924,250,536,554,925,748,906,892,973,624,846,59,190,356,727,35,271,639,951,329,618,93,173,863,564,145,170,62,627,452,82,870,241,398,918,501,690,86,560,107,41,990,752,104,781,695,739,697,849,49,931,901,165,40,969,166,258,837,597,355,470,564,560,175,26,743,252,359,610,917,421,622,936,632,145,669,387,330,955,679,153,734,704,319,365,380,490,229,845,34,451,978,183,79,693,679,144,697,373,475,940,846,515,616,170,242,693,349,529,744,88,300,280,119,617,245,144,2,157,551,590,862,69,419,339,67,888,201,771,152,544,381,345,917,479,31,749,161,120,454,725,655,946,623,334,294,476,862,648,312,831,17,408,962,683,408,461,17,961,693,541,734,142,706,349,720,87,154,521,858,50,879,748,416,407,157,639,882,426,24,510,536,530,445,875,407,292,892,709,176,255,809,630,329,393,892,678,375,901,273,714,286,879,510,731,303,700,809,139,250,150,994,403,984,596,866,511,617,859,672,477,994,180,632,690,306,402,344,614,892,292,833,925,402,430,332,980,90,434,921,187,844,295,971,358,205,257,670,232,982,940,407,209,452,475,253,9,397,599,82,480,950,926,939,669,211,514,445,574,492,144,908,690,820,820,278,804,886,706,783,814,443,989,621,944,455,221,636,130,979,338,540,464,754,907,530,561,488,119,901,363,423,345,892,833,18,500,855,6,699,475,457,928,278,468,937,59,779,386,253,882,856,984,246,518,616,656,546,978,394,913,34,686,986,239,379,452,670,111,371,60,479,864,884,553,575,110,905,263,134,811,398,218,250,250,32,148,736,887,706,327,766,122,924,206,223,285,177,48,989,280", + "386,25,63,545,81,22,899,171,395,79,880,215,862,209,440,332,656,789,675,608,989,984,630,140,771,667,905,892,161,697,803,935,81,521,98,435,165,631,823,44,233,625,930,648,566,242,530,867,266,929,205,538,841,605,30,300,555,752,569,961,621,352,824,753,328,342,778,99,915,620,189,0,229,571,325,263,461,650,96,642,619,352,729,871,940,605,502,310,203,332,39,767,137,432,284,274,560,549,908,3,471,55,162,499,440,221,702,518,713,407,62,649,410,272,768,106,373,924,600,111,154,596,911,854,126,476,11,181,115,749,811,482,754,512,371,580,835,796,327,583,524,799,367,8,643,346,56,795,6,286,766,47,120,418,367,730,937,150,625,915,850,906,478,736,15,746,790,90,345,252,969,326,761,986,823,492,643,179,13,371,195,351,538,380,110,637,258,731,610,198,845,467,840,335,860,846,961,165,774,813,416,301,538,962,518,710,545,536,963,450,830,655,934,155,727,393,618,85,295,796,455,197,200,180,865,524,498,666,425,572,846,78,644,441,27,482,751,746,390,79,448,713,116,400,624,247,627,368,594,573,516,138,424,4,353,92,766,114,333,596,670,985,680,582,210,59,391,773,912,238,904,941,842,626,775,753,318,88,971,162,583,836,803,961,424,588,764,678,457,166,926,348,676,431,782,902,940,241,913,301,505,615,661,57,5,19,305,406,445,10,627,405,845,306,767,994,321,6,600,110,174,812,278,93,258,439,645,806,12,845,488,748,862,483,639,265,673,918,650,131,660,926,651,295,620,572,386,760,456,532,689,773,450,627,302,991,857,29,160,849,929,189,680,413,918,78,545,622,372,239,586,305,907,527,404,289,960,41,507,70,759,755,539,705,691,328,670,720,460,626,648,782,954,133,790,700,662,870,354,660,942,724,844,504,488,817,336,959,5,10,892,351,356,89,70,932,280,20,137,839,879,592,161,715,161,61,334,388,12,192,579,310,246,922,570,491,652,49,778,176,550,83,910,312,823,581,768,770,537,413,596,224,401,196,467,20,56,100,943,252,319,675,655,52,435,219,71,195,995,455,153,77,288,447,349,510,622,679,171,791,192,648,566,123,528,158,724,698,889,418,475,249,665,232,194,494,646,994,673,679,782,883,577,660,793,798,282,480,438,771,971,569,983,112,498,729,712,40,812,900,78,381,726,125,633,215,735,312,667,431,464,224,476,52,917,157,787,660,19,451,325,27,492,996,494,410,425,398,366,544,997,578,507,37,538,882,636,520,423,661,344,494,613,207,132,980,222,453,209,346,288,208,688,881,222,467,741,312,22,754,949,434,684,525,258,860,126,967,762,41,608,473,194,384,13,752,709,931,599,81,514,920,708,157,546,841,805,911,677,13,547,257,637,368,62,145,416,951,435,692,619,840,77,36,376,517,10,89,425,938,431,228,339,821,284,84,611,596,944,37,780,629,642,686,742,622,587,408,235,19,575,199,285,153,516,516,63,958,885,541,790,61,960,138,976,289,390,684,885,288,66,964,40,974,252,420,264,885,852,868,807,409,529,934,251,645,749,97,688,863,518,319,738,816,2,49,963,653,996,324,211,518,513,820,956,781,857,300,100,150,132,503,81,934,950,858,2,424,443,549,349,180,463,959,562,96,209,873,540,484,997,485,711,800,418,425,599,645,744,593,240,199,806,185,69,546,933,714,106,953,411,753,473,297,316,508,354,894,368,5,15,65,385,583,410,293,189,1000,962,77,370,532,124,185,773,721,2,79,544,918,436,786,608,180,165,278,824,120,818,257,378,900,778,482,748,150,164,689,226,841,193,651,642,831,42,664,690,705,785,354,211,63,870,217,461,111,868,422,581,818,814,618,875,754,806,521,48,638,378,25,90,44,610,747,348,610,762,412,288,183,47,30,561,782,546,754,382,532,364,564,230,599,580,593,342,400,235,805,521,716,735,431,993,442,410,712,917,586,780,626,204,379,577,5,873,434,979,710,516,446,396,849,562,242,816,697,676,68,24,97,345,244,546,790,654,777,462,45,814,604,26,570,599,566,240,572,847,321,708,335,372,366,258,570,84,63,582,347,900,320,476,512,760,563,839,841,653,356,570,616,691,653,321,367,744,980,832,820,566,84,386,516,121,6,391,316,82,470,258,710,875,479,78,262,790,503,846,964,175,444,613,32,186,931,523,291,476,886,234,49,919,717,700,785,82,135,832,102,791,366,323,150,676,896,948,250,84,158,756,297,762,749,6,222,15,945,61,403,582,785", + "536,779,286,30,1000,943,562,721,920,812,64,442,901,256,35,458,920,220,498,545,711,907,998,54,506,357,134,183,161,487,937,486,139,262,855,386,66,529,727,833,156,936,705,871,880,84,357,36,241,861,413,322,437,863,862,596,161,870,53,10,223,781,79,614,617,341,461,49,594,237,957,229,0,797,260,378,75,345,635,745,625,589,222,699,202,107,479,392,570,575,530,3,128,717,293,742,923,351,79,902,417,755,571,303,878,680,687,692,678,610,611,574,336,34,921,66,325,3,38,975,135,330,507,471,831,242,905,866,736,810,667,822,176,375,282,556,289,828,992,278,744,63,637,62,673,275,957,745,29,202,592,464,668,705,665,617,147,197,711,885,337,87,749,692,911,270,265,755,497,463,683,7,43,328,504,69,197,862,55,677,445,269,352,529,786,331,239,492,596,739,646,602,532,436,285,251,415,753,528,426,127,636,170,244,821,569,557,965,977,754,371,499,40,500,182,135,485,207,650,345,49,8,587,631,796,725,472,30,833,700,988,665,537,77,114,794,938,150,242,238,365,914,160,427,267,38,912,288,599,745,858,416,227,149,231,977,151,201,209,720,72,892,553,819,323,641,564,258,248,28,78,618,512,280,592,149,431,972,33,639,937,374,503,358,446,939,531,77,789,9,237,838,367,818,104,57,279,139,979,590,895,935,78,972,350,85,561,272,512,580,777,872,283,699,514,269,414,894,250,457,44,987,674,165,767,44,544,126,200,829,3,911,829,932,921,768,67,764,703,783,814,303,380,966,56,979,849,169,117,35,736,702,841,111,114,302,102,650,726,277,146,998,887,940,63,313,47,870,570,104,903,113,202,348,561,836,93,294,605,394,213,861,602,596,664,295,555,729,258,673,923,233,356,600,828,530,698,950,545,272,883,493,334,81,67,462,615,869,763,597,408,99,535,379,454,93,480,446,928,903,594,929,655,227,570,754,756,78,614,199,169,751,179,66,533,710,739,61,330,233,718,964,453,703,685,860,553,986,828,355,786,34,792,213,70,914,126,729,176,798,314,195,726,9,917,378,817,653,805,273,585,650,53,604,51,716,372,510,860,661,4,241,720,469,683,619,65,486,633,651,593,392,169,487,428,729,78,224,348,243,631,964,404,373,154,888,570,872,782,729,828,33,294,368,286,764,89,151,805,888,163,906,436,112,760,173,151,515,702,329,551,580,180,560,177,920,514,21,519,140,87,764,747,522,395,907,783,727,858,663,399,741,441,752,644,374,831,578,631,654,145,603,457,28,851,99,393,69,913,999,261,677,991,868,340,690,727,670,725,294,413,921,576,123,611,493,730,904,862,143,882,808,50,771,663,981,531,39,101,270,425,710,826,627,12,332,199,682,370,994,722,720,805,771,544,775,843,250,834,579,524,949,271,97,278,676,645,246,710,912,981,160,963,280,573,561,555,718,445,720,679,666,198,45,832,325,834,768,335,30,975,640,520,98,365,195,556,303,20,911,648,965,126,358,197,855,526,558,710,973,68,480,67,974,272,237,172,66,691,624,315,891,363,971,697,817,52,690,394,62,573,408,415,289,962,459,926,907,937,130,979,627,354,85,701,788,612,376,393,384,405,318,306,134,605,724,116,901,196,997,377,81,147,837,850,511,438,713,620,233,879,86,220,837,336,308,63,422,107,913,376,948,672,886,631,975,643,546,215,314,259,734,327,353,424,658,635,824,161,252,173,170,932,733,848,143,318,975,24,506,595,35,995,649,845,53,347,866,322,85,233,165,855,770,431,170,191,116,917,976,479,569,232,500,128,391,721,110,39,785,6,83,932,996,361,99,692,752,773,276,317,629,483,338,232,837,59,566,455,380,785,264,183,697,780,762,35,515,397,84,554,326,826,456,71,138,911,36,866,552,636,372,258,580,247,374,335,891,758,231,300,830,734,348,98,20,187,86,717,914,73,424,327,595,49,862,135,822,398,770,712,406,542,529,344,980,897,702,935,80,196,978,386,579,156,146,559,88,918,688,947,943,909,398,761,616,169,570,448,711,93,209,665,314,868,225,916,736,283,3,777,611,235,664,821,278,316,179,634,733,610,49,775,719,99,824,991,835,191,807,937,397,744,549,601,695,678,238,378,394,191,908,526,103,42,426,552,327,449,373,16,524,55,724,232,76,394,661,52,970,233,722,535,963,665,872,314,782,12,742,535,888,574,640,283,54,828,338,875,681,22,782,57,922,69,821,318,765,512,959,256,624,611,851,117,667,676,583,765,433", + "942,492,499,163,453,781,391,50,72,252,655,575,991,703,368,82,827,534,622,100,106,268,569,679,967,879,58,611,287,726,332,615,887,915,894,337,350,221,126,585,651,828,571,1000,729,744,385,634,253,321,312,841,264,62,57,454,257,715,289,49,780,175,281,371,876,40,609,130,615,89,393,571,797,0,236,370,876,626,717,36,212,608,694,400,760,67,752,403,455,793,63,950,911,677,315,894,258,74,42,826,740,211,968,448,444,726,251,21,763,460,293,541,437,642,877,960,589,602,805,500,752,158,390,648,131,809,519,209,440,874,521,937,629,871,504,561,900,754,630,159,759,444,606,11,292,183,612,818,109,680,765,737,440,406,19,3,133,943,783,431,36,831,880,896,285,643,160,735,289,840,682,339,198,117,497,247,202,572,325,490,865,211,43,503,170,869,879,489,499,278,102,937,279,620,913,96,35,551,759,17,547,437,346,274,686,217,911,86,309,268,559,564,346,411,7,81,889,533,585,673,576,975,434,550,349,197,597,817,738,778,711,814,29,204,417,189,280,53,327,72,90,524,234,262,604,490,261,944,13,20,609,126,270,86,925,511,514,739,99,787,452,47,853,138,438,313,341,16,849,365,465,535,544,695,85,553,351,31,356,203,638,643,84,366,995,646,579,815,262,91,953,211,156,648,82,918,826,822,10,776,651,126,511,396,58,942,993,481,815,98,458,183,925,925,842,695,161,274,917,421,318,688,215,841,233,744,289,442,721,55,900,367,858,370,851,265,298,736,247,60,248,25,245,385,788,374,98,587,758,709,1000,402,586,598,831,895,976,493,409,610,290,604,486,950,169,273,487,231,756,150,327,722,113,791,189,559,630,497,10,51,249,247,427,192,820,272,771,396,246,275,109,974,268,231,457,761,642,801,400,317,481,578,781,990,638,607,458,322,824,862,727,373,874,942,23,239,674,605,828,598,398,736,551,340,485,780,157,830,481,57,99,326,222,663,520,698,29,37,320,1,166,151,883,121,884,670,750,744,406,511,242,971,377,76,930,612,545,969,719,484,91,495,234,623,866,409,971,517,157,808,399,58,910,741,369,76,990,591,731,749,274,98,335,352,518,803,986,126,985,751,330,853,399,496,25,929,274,370,506,56,751,189,15,244,42,173,934,446,67,82,630,501,665,848,860,794,476,574,314,880,753,264,251,692,62,883,322,66,304,144,939,330,984,752,374,989,128,253,262,960,932,627,902,126,551,410,260,280,923,21,814,605,690,722,411,386,597,932,837,940,994,397,32,88,825,366,804,127,875,280,495,4,869,228,433,368,460,399,974,8,893,598,824,514,608,638,391,21,868,890,764,218,237,393,87,149,692,687,678,452,591,174,890,845,316,639,811,388,100,901,403,640,882,184,413,99,106,51,321,824,67,350,79,267,145,975,128,793,817,614,380,88,271,223,844,264,732,528,119,772,370,114,547,276,753,301,52,330,975,467,242,457,288,226,243,771,966,786,116,926,211,901,474,842,937,558,361,490,72,604,30,844,634,163,507,683,377,900,687,388,123,128,207,994,150,161,783,405,435,773,244,537,711,250,756,38,311,57,432,93,126,53,273,87,485,162,795,530,416,483,811,592,466,940,712,285,152,255,543,428,596,215,202,351,725,26,472,783,446,49,616,656,404,822,658,165,437,245,377,783,279,724,900,255,310,46,598,86,55,567,399,128,932,761,556,753,669,958,132,889,758,204,516,539,733,713,63,469,712,920,992,225,909,75,47,748,863,929,146,541,265,442,503,355,737,771,625,760,156,908,286,261,211,262,55,790,604,176,216,815,832,483,672,198,395,154,43,148,619,200,683,944,394,418,201,855,549,452,191,479,298,717,424,562,75,353,561,150,942,199,253,247,528,498,923,842,157,402,355,803,468,299,494,817,295,713,955,161,365,234,727,688,239,267,657,205,497,433,268,113,30,722,457,879,751,299,633,265,778,601,469,566,961,622,111,457,100,444,799,355,584,415,488,717,537,782,941,291,158,249,502,680,115,160,165,287,966,744,237,132,539,169,704,720,20,196,756,175,856,991,861,825,943,201,136,106,297,98,161,875,873,302,897,746,376,418,790,800,645,21,430,490,194,58,721,54,415,957,470,927,123,226,662,835,254,329,118,961,704,402,541,28,304,316,733,688,60,999,655,35,983,63,186,442,319,693,585,128,408,83,483,315,855,790,522,277,415,522,525,328,491,450,939,729,255,381,938,939,489,880,586,703,456,729,521,705,756,234,601,895", + "533,412,302,866,659,129,157,30,272,187,936,543,990,953,104,736,776,777,456,559,168,979,967,382,376,30,955,575,160,431,314,778,666,817,863,618,577,534,677,442,39,67,804,896,329,143,245,818,644,730,821,542,337,433,327,693,28,742,244,672,507,682,471,646,310,31,445,285,822,87,629,325,260,236,0,465,641,299,197,778,426,24,692,716,22,1000,783,283,753,638,813,38,171,438,266,354,284,79,230,379,366,136,133,393,253,757,357,65,324,708,711,356,585,424,107,171,813,203,666,937,857,429,295,427,140,718,152,763,75,227,912,275,435,18,184,5,807,889,409,223,854,175,787,165,654,719,518,691,837,800,928,104,933,564,713,801,142,43,158,306,266,496,234,186,821,167,658,419,910,599,29,999,634,231,39,226,130,2,751,28,237,535,216,466,820,190,846,928,660,428,924,117,222,948,778,195,493,584,608,766,635,457,436,641,551,643,164,320,233,899,277,580,535,365,767,456,389,796,637,814,328,200,626,558,626,489,876,728,132,539,652,579,783,133,986,527,895,572,960,564,490,9,284,197,806,737,774,461,315,419,250,654,856,60,19,957,308,651,254,538,368,469,743,326,429,503,326,171,752,298,538,425,875,221,130,660,517,139,53,283,511,531,107,709,570,814,10,449,389,218,216,856,464,272,916,251,592,428,299,82,36,720,862,540,462,798,390,156,676,700,949,925,480,786,599,728,98,992,978,456,837,687,202,162,132,861,54,957,215,660,135,417,576,744,389,991,379,161,674,513,630,726,511,454,869,973,947,818,517,620,756,526,446,16,421,346,150,466,685,201,819,270,859,754,505,827,811,690,293,592,968,693,803,931,915,560,129,990,381,411,96,603,643,185,105,295,870,68,600,395,187,773,891,616,719,240,496,941,780,674,653,861,622,977,809,99,323,678,106,609,895,119,608,806,869,271,975,30,554,820,351,666,168,729,831,410,773,931,383,657,184,507,188,914,379,243,438,215,561,252,813,717,19,964,641,716,337,274,440,584,437,183,701,630,551,175,870,64,827,908,74,905,202,154,859,582,925,681,481,530,75,277,767,19,835,918,249,232,453,387,839,331,967,13,198,689,802,605,258,203,341,882,31,658,689,98,371,356,127,856,864,882,443,926,526,343,366,849,699,564,381,999,628,188,165,88,568,698,719,828,977,443,804,482,209,428,310,485,368,467,238,520,593,688,651,801,449,746,77,691,281,859,240,395,28,346,556,586,790,216,714,255,344,114,723,898,530,519,464,252,208,159,102,262,586,247,369,961,125,260,953,32,581,322,818,23,898,541,443,505,534,458,78,323,659,729,779,938,955,526,163,628,910,161,629,870,602,742,683,776,528,349,622,402,719,425,806,238,833,598,161,487,908,402,384,102,377,725,569,862,690,862,307,895,401,985,263,720,190,773,518,862,487,328,292,926,261,551,956,312,241,896,460,73,212,802,263,944,130,836,671,736,534,664,791,822,130,280,792,519,788,360,877,864,611,470,169,382,297,208,179,451,52,552,419,739,549,687,134,268,334,951,48,962,781,140,265,681,208,314,347,119,16,578,447,558,720,70,375,738,57,634,163,923,666,296,620,20,444,247,521,557,941,672,824,292,183,350,661,288,408,645,437,719,868,623,855,693,834,260,759,546,444,981,490,946,875,216,767,306,610,114,594,443,119,953,378,801,147,792,332,822,263,535,491,580,992,470,423,644,889,800,480,235,537,181,885,471,629,218,302,514,772,854,166,272,948,95,542,165,446,715,442,740,159,718,206,63,740,837,282,495,400,309,860,465,185,611,137,693,887,770,357,897,591,146,268,893,877,40,747,454,362,366,249,376,933,51,208,972,994,51,514,710,950,778,183,378,141,724,383,800,358,813,368,953,348,620,215,585,90,729,766,902,456,524,326,21,260,118,864,753,827,898,227,603,572,371,721,306,736,926,610,325,261,439,281,14,398,846,474,468,338,314,433,916,267,992,943,868,449,860,660,679,261,914,956,323,962,779,308,958,169,493,822,858,254,539,132,118,339,778,686,441,716,788,967,373,776,718,699,902,567,9,283,185,83,897,869,4,573,991,945,418,51,975,757,572,617,295,824,717,479,797,917,682,71,500,921,560,613,77,340,297,348,590,683,297,268,130,191,863,659,441,349,497,699,24,43,560,710,895,5,829,759,364,293,357,751,939,887,424,141,58,505,551,951,35,258,389,506,167,281,959,325,412,404,267,239,990,953,757,252,76,662,93,88,720,367,943", + "774,778,842,785,936,203,933,345,622,260,602,913,135,165,866,793,465,976,910,274,343,16,425,793,534,609,818,839,969,332,213,216,6,572,419,992,165,823,667,455,229,433,990,534,454,320,895,58,804,239,385,253,332,646,264,514,43,412,846,399,550,857,847,418,901,677,24,432,710,711,141,263,378,370,465,0,587,908,169,38,629,538,271,824,624,405,65,622,827,786,978,835,338,595,929,545,804,517,119,485,480,953,299,416,368,411,175,399,470,348,425,61,99,506,953,507,11,774,82,422,966,637,573,314,101,900,104,888,790,456,590,945,588,303,588,99,413,712,78,443,196,739,231,27,873,7,902,211,16,12,544,311,794,113,835,67,416,30,980,293,875,203,283,398,152,339,659,698,763,836,196,333,664,396,258,778,852,274,238,50,243,292,579,901,264,202,964,752,555,237,709,268,638,894,235,291,705,434,140,340,213,973,748,715,540,163,874,35,434,328,161,742,355,911,814,7,187,745,185,477,508,112,561,634,182,371,280,901,103,140,819,318,739,676,354,400,162,933,749,745,583,352,560,510,511,589,967,103,719,993,533,605,652,750,397,565,626,798,155,864,635,525,148,913,153,744,20,876,504,684,339,396,62,68,556,110,82,93,192,431,982,156,882,118,309,344,506,726,659,620,872,690,926,712,999,976,4,848,51,404,21,277,628,527,965,842,509,344,853,222,57,532,135,835,343,678,646,130,292,403,163,195,81,135,133,111,175,930,329,485,499,579,612,529,731,400,485,522,292,685,33,399,813,677,536,131,277,639,529,815,852,552,946,487,368,440,707,734,166,377,968,706,187,726,875,491,154,727,404,961,131,171,717,722,697,459,891,95,838,323,83,723,663,476,944,858,611,169,871,782,687,354,800,190,392,308,272,754,823,467,580,719,971,42,650,994,26,374,752,2,447,452,904,388,915,776,315,678,271,76,589,107,73,269,728,202,935,437,339,66,716,650,501,940,181,642,127,878,360,362,878,417,457,43,902,258,677,931,718,170,94,861,581,819,729,722,328,59,559,209,362,353,748,685,260,387,273,658,745,353,632,196,729,903,891,135,675,498,80,615,507,713,22,358,647,893,650,313,715,835,765,397,681,512,657,275,62,130,59,869,724,231,770,298,598,367,488,280,473,398,576,510,117,417,289,865,94,385,601,540,893,811,392,627,566,275,515,120,177,936,615,930,570,787,210,886,478,666,399,954,163,51,789,726,894,291,89,111,168,200,22,985,8,670,649,32,67,529,926,437,949,153,515,75,596,200,497,704,905,135,429,117,684,634,285,849,56,920,365,463,712,285,866,601,618,495,271,320,681,921,805,487,437,465,936,218,675,187,89,838,581,512,941,17,290,220,558,678,868,55,870,631,800,417,491,838,824,795,549,183,738,159,412,944,590,500,323,867,176,758,27,687,615,594,608,776,296,705,614,986,62,62,537,42,25,885,831,168,4,972,989,552,566,161,332,629,372,211,892,71,137,48,171,95,394,289,237,363,691,819,542,271,418,579,857,37,914,584,651,178,906,439,32,389,691,152,347,737,543,981,21,288,461,670,782,676,210,629,31,589,628,821,993,106,497,515,211,446,847,39,473,981,625,733,381,410,486,431,388,439,854,939,209,557,466,991,500,446,777,947,916,151,816,305,229,92,426,839,625,418,689,670,755,423,770,162,982,715,624,881,727,530,727,692,914,926,448,178,453,696,455,406,170,15,160,840,378,860,554,429,780,309,840,868,261,327,665,500,606,491,20,948,670,236,830,217,492,66,635,702,723,394,593,564,705,668,816,871,799,630,245,209,470,627,637,958,449,584,478,550,872,212,245,615,279,662,190,819,29,545,186,931,224,891,35,33,389,238,531,187,30,878,716,780,337,163,604,601,240,301,655,257,342,756,136,912,904,466,280,540,10,879,163,654,648,596,309,958,634,318,588,865,866,646,24,404,4,60,245,93,918,893,453,46,94,802,224,468,978,734,783,579,735,706,748,474,653,670,142,259,916,874,692,353,890,454,124,146,357,518,523,637,567,644,842,659,275,31,889,167,571,655,366,151,816,98,589,720,452,451,995,625,458,920,611,836,45,8,485,465,93,454,621,612,15,38,833,278,571,712,437,45,905,415,533,793,931,591,816,375,853,615,917,684,960,27,151,619,191,974,302,179,221,790,238,61,188,195,729,87,641,867,171,562,474,985,586,888,729,671,719,214,752,916,808,393,885,341,308,43,745,798,525,129,740,784,202,348,376,111", + "71,302,682,54,930,381,691,332,583,706,814,296,976,935,595,446,599,672,498,257,853,26,319,213,779,946,578,23,617,510,694,402,782,427,717,376,199,274,568,143,893,37,447,492,522,905,887,877,462,620,819,292,611,421,807,294,681,660,563,236,948,549,614,50,870,390,668,649,140,953,569,461,75,876,641,587,0,439,88,841,930,402,918,735,185,215,159,60,716,475,886,664,422,425,744,926,310,881,325,361,149,379,323,86,927,564,878,480,839,14,160,771,635,793,834,695,693,121,988,832,931,887,399,544,122,653,990,302,450,827,832,159,293,198,685,417,133,114,666,882,835,743,865,801,123,755,882,336,656,927,933,610,245,696,460,869,31,187,636,693,602,665,97,544,313,157,900,602,903,845,693,622,630,504,753,430,666,325,101,89,954,729,905,724,335,347,158,488,260,824,324,954,791,715,552,233,616,578,487,461,613,30,679,853,630,785,908,566,262,55,915,556,742,919,438,210,963,496,613,234,88,288,682,817,608,437,354,800,812,209,876,303,924,184,761,837,258,46,776,94,268,314,34,230,318,246,994,187,752,812,46,414,247,8,630,521,66,991,42,952,684,392,460,16,233,698,124,451,37,490,205,278,187,335,951,165,141,442,573,288,412,582,929,38,573,16,108,476,882,972,731,238,630,548,463,706,133,651,167,990,568,465,700,463,376,302,50,454,591,462,659,507,283,367,985,137,842,473,879,518,240,508,660,31,597,656,955,746,853,253,783,987,732,618,220,136,129,826,877,587,185,465,891,208,288,427,212,485,904,689,931,886,462,752,492,268,945,837,813,724,188,99,186,297,451,751,704,236,266,594,494,928,371,513,127,462,786,68,366,799,14,269,812,912,601,417,787,436,7,53,353,110,93,668,251,422,778,827,483,348,924,195,827,806,374,645,343,812,551,613,48,161,325,205,585,846,29,893,988,153,659,835,563,512,805,961,287,84,767,834,81,112,344,582,77,524,897,880,433,60,148,16,506,811,342,307,719,216,404,667,436,403,287,816,521,168,404,663,981,317,611,968,869,632,667,489,46,830,321,212,796,808,797,308,747,558,418,14,287,578,300,394,538,30,138,573,345,69,545,809,829,887,648,870,882,854,169,852,546,666,159,721,271,894,555,571,689,451,742,456,702,730,743,229,64,843,842,881,451,937,410,442,230,483,589,223,713,222,70,441,799,27,843,636,832,766,44,104,382,881,443,199,532,903,514,652,287,263,500,922,238,632,408,846,723,870,894,577,596,148,16,98,432,76,274,908,567,186,947,970,38,609,467,602,557,346,962,560,78,536,355,826,655,66,288,407,364,840,925,596,76,948,843,249,389,726,486,58,33,67,856,558,30,297,87,419,687,13,599,785,832,850,88,768,154,699,803,564,250,695,780,539,603,978,702,180,90,522,795,627,921,333,950,528,872,576,845,499,290,610,955,144,659,756,358,473,535,960,566,986,108,335,146,625,631,651,655,137,231,743,405,400,890,337,85,979,528,10,824,535,77,274,365,66,64,71,198,412,820,449,589,795,608,916,113,321,992,919,981,234,617,53,827,11,797,550,857,520,152,946,121,875,451,479,111,593,953,551,792,602,420,859,435,70,115,970,67,362,260,538,897,563,757,794,960,907,506,509,581,747,237,801,689,102,862,779,814,560,666,886,143,964,676,732,625,492,568,566,342,26,351,590,733,984,221,387,412,37,162,80,833,14,340,193,443,903,811,732,226,537,873,508,304,588,627,584,231,836,426,60,131,561,520,315,861,803,710,298,127,421,354,109,781,757,849,380,705,573,900,844,12,432,605,213,646,513,697,562,109,707,11,547,272,401,410,11,275,299,685,68,397,303,517,379,629,63,329,504,3,984,561,931,703,616,890,469,574,318,463,475,689,411,765,473,21,333,231,244,175,479,818,153,563,34,10,610,818,962,887,662,33,138,375,953,354,166,142,730,845,931,295,955,986,513,758,194,538,70,307,230,742,227,349,756,356,762,350,861,959,632,958,755,789,932,574,26,499,651,201,790,381,229,231,303,445,526,118,632,277,600,365,500,828,64,972,572,250,507,345,345,962,764,913,352,111,135,497,770,716,843,19,903,471,985,398,315,474,501,35,458,109,771,24,463,742,41,457,550,838,700,682,529,542,830,371,825,816,386,610,960,887,876,654,135,434,328,188,335,64,468,282,186,927,325,873,656,349,159,707,253,440,29,320,731,707,545,575,532,699,665,550,271,984,129,929,83,904,402,10,838", + "996,220,896,219,252,316,918,991,278,2,436,33,17,415,94,626,199,700,713,452,231,111,599,730,19,53,195,150,516,412,594,237,837,768,379,845,649,171,882,507,487,868,128,148,408,56,445,334,110,591,908,85,854,750,795,442,25,396,150,928,226,758,977,260,922,974,1000,634,285,431,908,650,345,626,299,908,439,0,663,93,765,747,893,926,934,768,303,683,174,686,133,486,78,892,504,527,668,587,817,859,969,191,795,525,180,886,735,650,607,241,510,53,305,639,865,681,351,265,84,924,55,218,37,66,929,995,123,185,976,19,405,169,775,772,741,670,390,700,602,560,38,791,751,947,354,620,651,664,802,575,681,567,865,644,862,59,833,559,854,468,731,199,864,971,370,90,787,383,820,60,437,423,552,707,847,782,742,574,89,992,311,25,43,424,808,728,356,640,123,34,727,104,483,21,261,957,308,622,104,743,938,813,874,800,641,794,530,595,950,744,298,564,397,72,448,81,927,995,944,959,27,949,257,235,8,127,193,398,154,254,434,672,209,580,652,314,887,387,43,25,349,345,249,826,408,176,472,59,877,647,61,121,3,503,140,346,434,902,424,43,812,107,325,960,413,568,335,185,68,684,367,480,559,931,528,282,675,940,825,920,927,946,487,71,228,885,94,150,795,386,594,305,310,327,155,137,189,442,459,807,900,944,84,292,725,686,299,791,595,897,709,397,704,608,417,521,8,605,711,519,48,58,190,905,676,946,779,540,977,681,928,86,38,858,73,625,924,873,768,407,894,23,247,667,697,834,385,297,929,998,79,824,442,912,322,283,459,514,66,311,988,477,997,62,137,475,543,561,193,827,819,931,246,696,262,493,733,283,510,898,150,472,599,453,236,231,801,921,159,741,627,377,174,305,807,679,845,402,415,692,88,826,861,576,718,375,149,773,555,44,965,665,439,355,144,113,857,78,633,238,579,670,200,952,780,246,698,203,196,271,288,144,524,45,611,313,801,431,715,571,626,956,583,138,781,94,985,312,269,365,22,372,600,533,707,257,25,791,205,283,55,573,710,620,34,540,875,260,217,304,549,224,467,864,153,822,561,702,124,29,696,710,206,999,580,716,855,777,93,74,872,207,841,44,723,145,45,595,487,679,411,418,188,123,773,333,33,508,676,435,410,612,173,504,560,952,19,700,626,350,372,595,753,213,962,171,22,921,82,831,465,328,988,967,714,190,674,272,539,305,175,618,251,645,753,858,933,697,391,169,34,18,146,947,46,900,125,877,360,351,459,517,948,732,439,635,278,345,380,781,239,336,192,559,229,175,281,231,264,838,128,818,147,670,307,508,537,764,247,274,932,854,64,42,691,553,184,23,420,358,877,513,219,783,495,440,679,601,468,414,629,914,718,934,485,138,378,966,302,543,211,904,256,880,881,999,300,611,654,49,643,393,558,778,54,24,278,138,439,22,211,422,775,909,407,927,30,107,495,127,838,699,35,277,496,832,851,968,620,893,886,271,966,892,647,791,979,645,986,79,849,559,174,35,385,521,597,970,925,93,159,31,552,697,553,454,943,243,432,889,989,467,159,921,527,628,316,914,551,1000,143,718,86,993,127,652,205,276,654,706,712,823,154,765,546,394,565,697,240,267,45,583,58,891,321,747,182,216,113,656,341,969,962,39,814,639,882,826,146,691,318,671,3,965,129,311,95,279,275,576,615,680,798,26,673,188,602,977,75,529,168,695,266,885,30,726,656,770,704,205,360,728,460,902,66,485,810,369,513,24,782,139,402,336,74,172,204,708,752,497,469,336,419,339,886,804,708,50,217,833,604,701,353,459,273,277,538,521,369,691,267,999,330,340,94,342,717,557,911,180,713,339,3,412,930,501,479,242,523,359,988,59,914,485,370,843,740,928,371,765,572,17,49,186,21,795,63,551,301,446,725,379,326,269,702,835,314,545,461,731,478,619,817,349,562,524,524,974,556,804,30,106,445,683,435,571,74,622,330,951,178,842,952,820,796,528,14,35,130,457,797,428,803,944,204,620,793,615,452,310,975,822,384,525,173,461,593,891,698,700,692,887,826,55,705,910,101,344,335,715,760,393,273,839,352,960,610,314,752,997,115,334,561,205,493,570,5,351,526,842,65,714,818,115,224,312,615,461,165,300,304,63,507,769,617,215,587,825,144,511,666,422,203,39,234,694,929,106,646,753,204,662,572,299,772,169,846,581,727,269,227,28,361,387,643,638,77,770,708,176,944,235,514,16,788,722,14,869,68,776", + "752,159,576,573,904,445,516,807,571,142,545,61,242,478,458,233,149,106,451,785,7,298,101,283,8,263,675,472,450,92,295,530,780,632,257,652,204,891,584,274,98,126,857,342,426,970,716,932,628,602,427,628,102,220,478,14,204,401,528,71,847,270,742,811,11,42,786,199,686,764,187,96,635,717,197,169,88,663,0,13,628,963,947,870,529,561,911,739,137,529,353,40,435,322,780,494,10,753,960,518,587,324,852,670,353,690,46,848,904,487,233,683,519,613,978,944,558,441,854,547,784,202,637,276,389,409,570,620,522,321,197,755,263,396,747,650,956,361,618,160,570,772,963,919,952,519,618,697,227,238,738,910,690,474,698,71,825,320,982,645,416,734,79,521,297,166,957,652,88,120,920,123,876,969,514,764,541,654,710,877,190,206,648,798,680,537,416,997,695,788,620,432,565,725,746,317,507,929,55,669,117,114,217,427,127,25,589,809,614,325,94,265,500,591,368,857,643,721,660,650,155,332,138,336,57,871,386,141,963,131,794,668,561,651,132,193,652,116,676,791,830,180,840,537,587,421,327,380,953,723,977,289,139,576,292,2,842,65,363,651,838,669,760,900,862,141,209,940,413,269,690,871,164,639,920,567,92,606,851,919,862,547,293,544,254,327,995,759,749,905,464,9,421,51,269,123,23,892,626,555,982,145,420,141,539,540,727,64,869,104,681,56,2,126,513,728,689,816,874,110,11,507,437,262,762,682,82,777,548,120,34,933,657,562,945,48,366,935,973,628,631,657,709,295,456,615,223,784,458,148,487,990,641,50,391,349,640,385,368,315,116,180,648,500,146,353,653,28,605,197,89,552,695,856,309,886,901,913,716,417,176,932,729,475,89,568,599,539,855,734,650,939,360,243,739,550,816,402,519,520,404,936,996,595,349,119,762,671,232,54,411,234,630,937,778,772,466,639,213,548,669,391,693,914,567,818,330,140,513,677,632,387,302,753,10,920,349,267,893,381,343,201,151,313,546,361,430,533,791,337,97,577,534,330,923,271,462,852,504,347,754,24,634,522,550,85,154,215,317,143,523,816,395,802,580,236,767,670,460,208,191,493,731,340,584,921,43,727,635,871,858,239,734,754,443,21,88,657,287,712,64,277,749,189,687,276,744,446,734,851,611,709,696,125,494,528,789,682,732,431,948,379,501,991,677,262,982,889,65,179,942,771,168,738,740,992,711,239,701,851,51,856,749,822,525,964,854,123,100,830,965,489,267,934,314,172,49,511,762,685,795,548,432,509,560,326,525,99,69,57,370,956,952,153,209,588,283,931,204,689,484,723,383,753,558,622,165,673,115,190,909,165,230,373,283,673,889,409,824,62,418,352,669,971,49,378,554,747,777,874,758,95,639,418,804,886,313,407,458,21,578,953,55,811,894,777,563,264,770,310,863,641,725,824,668,265,767,974,833,451,904,467,220,274,153,892,138,425,879,49,201,394,528,660,59,879,42,283,628,430,850,653,451,729,168,845,662,565,990,24,897,629,343,7,32,909,717,118,553,989,7,443,184,416,783,199,94,632,209,976,795,531,121,343,830,39,260,655,306,761,792,660,377,215,309,975,686,769,371,613,697,817,324,155,743,357,846,692,844,267,255,664,110,882,704,172,450,276,773,701,221,350,813,491,238,63,147,56,230,818,113,606,292,800,158,175,416,888,749,666,67,95,716,936,530,96,140,634,178,506,795,735,274,575,999,471,786,503,624,369,129,491,829,228,253,362,918,399,510,841,318,851,304,965,623,561,293,643,342,885,650,221,711,698,263,606,842,946,469,827,275,150,388,166,944,527,63,497,624,423,150,156,144,435,820,123,819,356,466,827,164,824,901,850,876,987,464,38,166,218,926,769,142,15,21,981,719,107,862,56,919,474,754,868,343,66,786,842,762,25,97,305,999,449,582,993,68,991,189,11,142,914,255,878,585,250,933,58,774,390,329,97,260,161,35,774,619,175,939,267,568,594,120,810,831,285,858,267,506,47,122,708,339,135,204,69,653,347,954,559,84,626,152,591,940,462,57,47,163,112,90,50,743,547,435,141,761,727,934,456,414,51,462,852,943,695,750,968,59,194,376,760,889,343,944,236,624,525,484,342,82,945,150,206,12,799,112,140,744,814,640,136,707,651,442,795,742,695,903,443,227,714,682,220,124,961,287,921,210,631,711,214,907,432,997,625,987,35,972,350,54,415,417,823,135,696,113,223,630,48,252,294,922,885,418,517,638,343,857,945", + "6,617,942,636,894,851,169,406,10,852,729,1,402,737,87,69,553,711,566,833,109,878,383,920,495,766,417,123,605,215,294,570,548,986,814,713,865,556,996,717,771,352,950,385,831,226,433,151,505,637,461,878,911,541,700,178,407,161,69,180,820,740,537,127,738,361,31,608,590,479,922,642,745,36,778,38,841,93,13,0,898,967,850,312,20,836,922,975,359,111,299,743,767,422,839,718,779,636,138,965,983,741,979,911,725,443,822,520,24,803,100,999,195,851,149,94,901,179,486,950,685,330,703,857,106,277,883,39,510,238,516,839,783,605,77,660,655,200,168,42,321,794,870,157,260,540,357,706,542,899,424,164,153,177,320,541,109,486,227,811,467,192,24,974,442,594,654,795,548,316,496,292,342,717,345,14,542,753,30,938,179,198,93,873,516,494,542,63,942,565,639,202,426,142,197,562,898,855,984,946,20,214,704,585,466,731,443,356,852,78,278,480,409,666,317,779,268,865,367,357,349,337,198,658,953,270,29,316,449,458,516,274,776,258,591,789,36,282,94,950,473,473,547,763,840,228,294,131,451,424,284,427,124,479,212,615,217,788,932,767,859,641,780,419,489,964,27,830,646,606,620,421,85,245,934,694,231,306,904,865,920,493,510,169,890,829,635,765,52,195,972,922,140,966,864,727,564,120,601,119,73,771,549,180,74,680,367,3,204,815,210,736,229,623,444,63,889,835,658,462,369,618,561,132,430,717,447,104,126,29,439,356,934,335,901,115,41,771,500,427,642,197,466,268,797,989,770,330,264,406,66,562,451,806,500,84,225,282,624,375,188,604,655,528,683,195,429,156,675,269,695,631,324,524,258,742,117,171,414,882,808,826,619,957,787,984,413,977,459,390,305,533,887,908,962,987,936,709,30,348,127,654,356,714,543,116,193,390,121,219,207,635,829,522,5,851,448,627,86,71,877,277,502,790,764,196,718,310,820,566,362,568,780,706,116,943,575,153,534,27,843,756,822,218,378,224,253,160,923,836,374,108,868,494,977,960,129,676,338,327,858,604,323,722,412,264,902,370,902,69,533,653,454,655,96,110,407,624,191,441,442,107,77,58,460,418,42,994,206,476,162,965,568,527,717,104,316,763,902,339,953,18,559,756,129,832,830,555,330,896,382,118,630,907,28,486,247,364,991,301,677,258,263,906,718,133,977,175,723,958,558,87,24,882,770,557,136,898,750,29,305,51,783,523,705,210,81,238,384,233,609,722,995,942,624,765,647,545,984,660,674,200,271,807,792,704,857,375,506,400,522,218,841,759,686,359,370,247,64,687,726,108,837,438,810,122,301,521,5,307,599,142,991,594,563,696,419,502,408,822,359,471,950,746,484,784,499,268,841,499,131,518,822,270,434,712,615,878,692,783,550,525,277,605,825,486,313,68,416,667,727,166,160,665,237,108,180,309,27,175,583,84,97,438,24,375,579,942,513,227,155,654,174,93,879,571,110,168,738,888,811,981,437,545,316,340,769,942,488,259,999,197,737,684,360,495,707,992,644,396,553,557,237,962,867,868,136,584,407,35,51,871,883,521,439,54,300,232,419,242,364,774,899,334,666,942,964,921,216,466,688,889,6,247,582,371,943,87,605,924,372,250,299,651,74,896,511,594,149,103,369,935,953,274,604,921,862,330,462,208,768,234,953,841,826,533,724,403,751,209,585,207,229,807,522,22,129,781,336,559,973,263,503,61,416,480,324,641,576,844,230,511,120,793,948,14,139,665,799,487,708,908,672,564,879,526,845,622,372,130,75,697,796,324,685,968,433,950,359,171,249,683,610,580,584,521,670,669,106,212,58,204,829,23,589,206,321,872,183,689,860,694,315,893,922,438,509,488,904,816,285,575,804,346,205,233,16,317,886,452,228,568,362,870,477,32,557,901,854,898,922,373,119,906,51,668,569,41,629,734,493,821,428,819,447,729,378,80,166,320,106,88,233,217,561,648,685,597,161,506,653,847,739,432,442,483,142,777,311,605,839,973,129,216,590,181,576,932,45,326,826,340,780,106,213,170,320,345,962,692,5,431,370,448,409,386,696,643,953,946,251,250,190,441,360,784,205,89,167,240,205,174,110,104,339,847,119,332,142,942,970,330,576,288,780,858,317,639,923,726,918,275,953,436,475,377,674,940,54,351,734,345,255,680,513,136,51,441,21,698,437,368,676,125,584,406,31,894,235,600,965,666,17,341,608,927,355,583,494,709,579,785,932,762,496,416,775,81,259,718", + "741,673,68,635,70,976,380,79,211,582,248,675,856,450,637,310,204,306,903,387,501,277,380,779,936,314,236,987,718,347,765,759,663,9,582,979,998,815,892,127,439,51,239,816,42,730,990,520,939,908,358,200,569,746,724,55,577,814,31,473,671,76,463,182,770,27,410,892,99,692,20,619,625,212,426,629,930,765,628,898,0,230,448,214,436,205,404,69,52,140,293,818,174,54,57,223,373,970,450,853,38,515,587,435,154,407,435,472,945,592,934,763,968,250,311,317,685,633,732,178,980,278,645,722,326,65,37,686,906,973,31,31,337,138,638,162,446,652,508,976,636,758,716,69,206,319,609,975,313,667,904,919,297,126,29,554,473,787,930,700,112,922,787,77,59,501,981,917,647,614,41,903,831,335,842,920,557,174,962,871,920,924,287,268,836,430,549,540,215,992,360,387,131,500,813,397,395,421,229,601,646,267,163,832,590,520,609,251,628,387,629,695,118,685,117,11,836,655,266,525,858,814,465,564,435,395,760,173,307,762,524,701,331,796,76,623,285,228,12,213,877,320,142,920,643,237,816,662,606,316,641,101,974,865,926,616,807,26,138,154,429,155,929,213,232,856,723,377,221,360,808,890,371,268,462,916,992,34,597,552,617,530,487,205,785,725,586,416,405,471,267,340,424,299,55,3,69,448,912,922,287,442,676,454,316,28,680,824,988,437,568,863,78,226,307,516,272,556,753,486,727,877,454,606,181,215,914,158,133,402,601,854,490,439,491,88,712,907,946,518,1000,6,59,1000,899,828,381,892,889,120,897,711,718,843,633,424,566,485,35,169,586,391,97,432,861,544,416,137,717,359,96,454,598,159,709,366,78,937,916,776,473,623,626,623,265,23,318,797,61,380,798,594,374,950,545,212,439,861,407,138,94,667,546,686,63,899,803,730,729,47,351,842,145,369,304,915,374,600,210,105,138,860,490,476,335,469,53,634,849,676,867,51,637,789,941,180,869,478,808,997,535,251,159,676,583,413,450,684,446,247,900,536,588,301,267,780,432,150,252,725,564,219,893,229,33,553,619,37,872,846,282,971,7,309,113,374,556,336,979,624,563,349,916,761,379,556,785,786,311,908,497,923,257,913,993,242,977,827,350,935,648,667,766,754,578,985,143,578,876,190,546,941,578,274,604,505,785,269,613,434,161,395,294,625,519,19,822,97,421,85,169,792,832,888,390,296,122,258,999,144,672,931,687,106,700,254,603,752,578,989,64,276,651,288,207,225,302,862,927,23,596,630,719,666,858,866,440,798,226,299,736,675,715,677,472,340,684,214,932,237,383,570,767,739,800,957,716,124,747,992,763,861,624,788,420,882,624,201,850,739,570,873,302,726,400,490,918,316,358,385,879,280,538,78,872,881,778,224,599,410,176,804,656,445,157,939,399,106,439,774,768,322,586,137,66,730,56,743,689,606,143,861,716,713,525,733,38,20,597,296,515,170,70,229,781,453,140,985,108,500,23,574,210,412,242,662,448,608,396,144,462,823,634,309,310,177,58,854,202,672,425,279,530,502,210,231,620,215,223,426,335,597,868,630,434,499,118,473,862,519,410,713,987,760,814,680,919,897,858,320,591,181,812,104,401,884,289,687,599,608,60,963,216,697,594,627,116,865,550,476,131,218,806,641,410,762,834,612,828,245,55,730,52,714,955,99,2,384,818,229,743,699,940,700,281,777,514,470,430,570,822,60,371,306,471,354,114,138,86,878,303,858,445,624,710,253,456,669,804,859,637,409,360,63,165,494,458,998,231,343,107,350,720,64,486,953,328,187,759,598,338,855,669,197,203,88,737,489,73,766,199,532,249,855,314,780,451,994,537,762,594,658,652,88,280,888,77,398,384,497,64,883,835,177,981,735,688,463,978,140,966,694,348,409,284,907,890,939,184,646,912,69,777,414,716,429,63,620,611,456,994,16,740,366,802,832,699,688,126,845,540,649,1,426,953,561,75,592,271,444,326,811,852,400,675,813,221,623,36,523,68,891,930,158,219,948,564,947,190,97,453,784,704,713,188,78,370,2,608,494,595,53,519,274,858,402,862,300,932,423,214,662,607,175,829,319,919,161,688,537,41,885,894,608,130,831,35,272,718,896,591,470,457,55,676,965,26,445,869,166,512,172,395,665,171,966,821,807,762,146,876,102,85,282,242,761,399,671,897,484,46,637,304,316,571,541,770,876,683,675,878,368,66,27,926,973,110,193,129,797,170,92,641,379,710,469,216,279,993,38", + "644,703,454,557,352,223,484,962,329,265,617,259,4,369,278,933,956,160,793,649,733,858,246,726,27,539,192,735,571,858,436,474,337,979,557,824,953,211,952,365,972,923,389,986,622,847,542,315,917,466,398,769,467,185,145,462,467,690,618,892,305,280,94,446,914,624,833,124,311,108,449,352,589,608,24,538,402,747,963,967,230,0,339,598,207,37,779,627,70,531,607,536,148,572,148,317,651,421,194,436,892,602,229,654,510,833,609,549,789,481,378,204,337,396,989,361,103,237,125,501,810,715,225,58,399,499,384,883,551,601,706,37,152,79,574,497,538,492,266,455,260,555,910,686,440,736,276,860,918,520,380,659,122,674,457,423,917,354,24,175,21,969,975,880,902,773,715,198,361,816,373,132,691,25,38,545,161,504,491,180,389,812,751,557,711,143,353,974,953,625,564,210,187,110,517,182,460,910,310,969,484,963,339,950,9,560,829,352,903,851,778,998,454,588,650,818,887,311,829,88,868,673,511,640,587,92,868,858,5,613,934,121,228,664,180,782,163,403,696,881,528,770,736,920,65,265,68,363,442,846,919,616,649,907,797,674,507,269,275,840,424,591,616,984,902,291,511,979,483,767,6,348,485,37,499,921,422,53,289,732,435,194,511,188,300,121,188,310,574,803,932,370,687,566,483,566,968,372,263,632,212,640,306,305,279,540,235,287,787,215,727,891,508,995,979,444,994,31,620,75,386,7,659,281,650,112,462,4,111,947,812,298,346,254,527,145,176,186,355,830,247,615,707,626,230,492,299,496,962,47,974,728,201,522,268,550,576,344,185,570,903,405,627,165,137,759,949,614,362,861,868,529,531,507,320,738,410,852,712,680,150,788,995,277,933,43,942,862,754,634,294,363,153,123,666,464,845,205,71,409,546,745,912,422,379,318,396,442,899,696,39,9,875,638,424,24,353,302,768,929,522,182,913,799,162,230,719,462,686,296,401,690,167,769,642,366,824,317,433,506,207,830,565,794,281,350,631,581,715,467,691,248,362,339,862,306,489,624,736,170,705,818,245,922,192,718,169,944,852,786,92,33,861,85,313,354,792,337,444,877,139,958,499,723,22,939,799,783,162,461,629,117,616,563,122,310,627,111,70,296,467,105,675,228,103,972,652,473,290,266,232,554,909,877,136,584,914,264,221,141,259,952,597,658,29,824,268,154,449,606,764,475,593,681,799,161,850,194,122,24,633,153,112,861,702,354,183,119,697,944,631,248,126,287,885,189,243,818,476,478,895,188,917,315,450,790,759,273,222,830,495,455,884,620,951,656,331,14,27,898,484,523,291,170,131,827,314,630,333,112,248,878,443,884,998,671,2,738,333,770,623,951,677,887,346,493,735,783,933,528,332,483,899,471,595,631,355,461,424,12,555,355,414,566,959,617,788,695,253,48,706,277,559,119,577,657,751,869,582,232,43,430,1,349,688,814,566,120,184,351,768,257,811,985,863,580,912,29,32,219,148,351,306,11,477,603,117,434,196,643,774,66,929,906,973,759,448,161,796,694,416,36,239,173,156,178,307,405,157,133,582,308,936,532,478,762,366,377,607,425,247,645,558,317,604,913,226,127,508,119,98,358,2,486,854,80,672,326,592,288,938,487,326,351,90,179,907,667,366,894,252,882,324,204,727,565,908,101,783,876,922,280,219,111,13,701,410,113,632,797,843,725,900,266,908,587,502,451,473,613,730,107,892,357,7,328,469,628,201,854,943,809,490,218,613,371,530,232,243,276,501,91,256,740,264,861,785,546,474,777,338,650,691,194,343,989,69,626,143,649,172,1,411,370,73,961,546,189,767,161,164,571,463,572,990,833,365,714,717,583,872,359,5,920,929,397,68,438,652,484,335,571,29,557,454,164,642,335,88,907,948,490,310,685,820,625,11,879,550,720,18,391,338,623,227,870,426,679,534,809,247,998,888,494,279,961,874,900,251,842,141,356,12,220,850,415,698,20,880,293,498,705,197,903,246,990,487,222,350,771,230,585,715,174,110,913,380,226,754,358,955,66,872,628,688,973,299,121,50,505,489,433,953,227,653,906,239,333,58,895,891,283,25,35,936,9,442,713,632,152,62,513,510,971,819,701,782,253,714,334,931,614,93,60,297,314,68,283,342,75,180,858,844,494,824,864,626,255,762,593,58,24,167,809,119,852,83,792,697,45,457,26,77,261,356,174,252,252,789,337,914,747,725,272,141,477,833,505,278,963,962,901,362,68,172,393,815,604,469,592", + "701,602,786,930,793,902,378,361,173,22,917,733,260,683,164,325,86,359,250,451,883,826,138,107,229,625,418,918,725,459,143,338,610,986,870,679,996,629,870,655,401,546,956,443,65,430,205,194,615,279,746,758,657,989,811,110,146,303,387,306,898,471,242,71,728,334,203,598,556,145,125,729,222,694,692,271,918,893,947,850,448,339,0,487,742,764,983,413,296,375,897,564,693,134,263,198,246,269,4,692,966,259,992,408,547,162,521,954,46,199,415,591,79,575,719,549,453,243,542,107,414,204,484,251,413,999,953,372,757,982,354,706,492,409,245,820,780,812,55,474,611,589,679,643,929,404,269,780,824,109,720,457,216,414,341,312,413,318,668,523,806,887,268,19,434,447,870,973,550,144,260,255,889,698,886,101,288,805,568,698,849,983,632,539,888,850,691,745,534,667,138,121,791,821,27,352,374,630,321,568,928,438,15,818,94,8,526,802,404,573,42,935,45,80,884,798,282,540,871,180,621,217,310,33,788,107,663,805,983,4,991,908,176,411,387,890,828,605,188,545,552,687,203,937,238,715,305,338,480,116,385,306,430,98,522,603,649,652,875,966,442,530,665,953,366,236,899,211,514,276,798,267,168,852,923,270,920,565,102,481,539,484,240,869,82,534,297,443,414,152,496,181,685,476,398,257,238,48,329,679,610,551,519,506,593,165,141,631,49,311,508,879,165,616,651,402,181,47,259,143,638,821,581,684,451,273,989,63,649,484,443,301,595,329,263,430,671,990,556,749,966,212,651,641,305,583,559,589,309,909,43,643,66,561,789,550,873,12,327,522,65,187,751,178,137,719,965,932,921,931,608,539,580,523,175,242,683,833,604,685,503,593,428,207,887,292,401,88,258,923,475,660,440,734,20,832,972,300,705,886,317,317,14,43,209,859,502,220,89,634,210,698,665,897,56,678,43,921,552,646,48,769,455,685,491,721,990,557,325,29,808,923,290,137,216,530,614,831,178,588,283,597,60,328,67,889,67,676,376,308,82,964,243,144,484,23,874,876,430,986,158,484,99,418,501,924,220,980,219,983,895,137,173,470,684,771,984,23,826,482,387,458,923,591,182,545,28,738,994,645,620,885,169,21,942,723,58,315,531,287,27,856,310,166,742,591,537,486,792,400,607,970,45,488,178,808,149,241,215,153,412,861,94,372,111,809,119,302,809,402,735,463,692,643,307,102,648,549,897,201,897,209,390,483,606,66,445,348,145,975,672,164,644,840,527,602,683,139,26,883,723,680,124,281,57,281,812,915,376,612,684,504,419,406,310,709,292,780,992,28,197,613,300,432,76,475,618,511,526,460,914,894,74,756,836,338,555,337,293,317,413,658,273,876,777,37,957,947,804,86,731,644,10,604,110,989,780,649,507,54,69,772,281,346,685,754,694,619,729,829,518,642,248,586,994,863,962,747,108,777,246,773,516,138,222,166,490,600,484,111,72,55,566,250,476,749,177,239,623,627,857,479,969,303,660,316,659,415,710,175,33,907,723,304,644,512,264,854,633,244,304,803,472,63,84,5,181,98,433,645,750,319,797,132,340,601,43,610,815,836,387,539,191,963,862,327,683,244,232,532,956,250,278,60,377,33,756,736,647,325,897,100,604,352,992,52,207,925,530,446,712,762,855,490,64,427,504,524,124,969,406,152,698,211,410,675,279,939,273,353,607,216,252,330,892,960,898,2,748,829,30,952,959,743,255,26,876,98,461,29,429,906,757,88,512,351,520,259,409,944,928,597,116,297,342,896,825,836,467,337,212,240,657,445,179,806,294,494,53,250,202,948,66,351,742,546,196,61,123,908,346,798,89,854,947,877,985,268,457,763,324,363,209,536,460,454,87,765,554,260,214,705,673,697,560,517,576,548,251,154,560,185,820,51,486,222,117,699,832,387,491,134,308,300,931,435,581,505,367,757,374,257,916,62,893,607,146,609,437,393,299,398,895,462,431,120,86,470,80,835,627,753,777,307,595,485,717,552,17,489,811,311,780,508,112,984,627,656,5,992,453,133,754,806,396,398,998,238,627,688,230,53,27,287,925,269,314,27,934,573,177,398,856,241,905,297,157,197,951,916,778,437,747,465,37,917,321,945,432,547,691,630,573,727,654,671,847,853,982,629,77,39,677,362,501,293,802,443,548,909,467,884,818,644,647,992,882,632,772,166,383,615,27,801,284,744,296,22,262,582,939,500,614,884,716,77,95,623,294,410,148,485,995,978,348,839,956,911,334,387", + "782,256,497,80,354,231,977,385,393,190,301,932,205,385,524,244,616,687,285,627,707,659,664,369,799,877,659,18,322,169,496,513,557,351,364,210,244,863,490,510,737,496,670,449,313,181,931,554,522,737,348,255,663,259,360,910,514,193,557,831,191,374,423,913,195,893,120,771,166,651,277,871,699,400,716,824,735,926,870,312,214,598,487,0,814,347,391,248,410,804,476,679,394,518,637,471,786,664,574,413,591,524,910,156,244,18,389,925,21,641,157,652,281,758,607,664,289,395,807,193,722,420,84,185,704,221,429,307,677,593,506,372,403,115,408,392,778,11,378,796,515,973,314,703,377,830,50,767,426,8,225,12,123,68,208,385,9,136,575,398,527,425,956,649,765,781,118,549,370,725,396,173,354,749,744,793,834,57,468,740,433,668,537,871,123,164,373,384,869,184,219,833,781,911,509,147,959,223,821,381,649,233,998,413,873,214,656,518,792,998,803,851,423,121,24,387,290,512,681,131,134,480,726,188,778,379,804,391,102,351,737,996,942,872,865,422,116,302,942,619,114,129,407,390,288,611,876,654,340,86,18,767,873,152,812,135,646,857,744,401,178,522,41,860,650,839,687,819,754,213,462,550,772,785,857,897,470,65,988,871,824,706,466,373,986,559,629,360,822,171,294,908,992,277,232,247,783,174,387,658,560,330,748,951,130,486,434,692,849,42,498,667,976,764,383,521,683,79,853,40,900,310,775,680,192,972,40,551,718,169,666,147,186,664,527,29,924,426,634,580,530,343,469,194,858,409,160,369,710,863,966,12,838,493,89,369,360,379,942,174,486,316,49,783,96,793,991,853,442,810,114,609,540,281,7,9,638,363,368,763,191,341,546,552,452,60,63,29,540,694,273,816,609,618,830,81,568,712,648,153,213,778,961,920,147,537,804,842,280,646,502,982,225,54,124,429,834,635,600,803,814,149,324,353,578,279,919,160,527,295,419,707,820,594,958,9,566,564,909,64,243,851,497,786,46,200,893,314,104,205,953,590,184,326,562,618,91,930,934,3,30,353,104,83,941,575,342,821,687,809,522,143,422,726,23,809,800,983,987,719,52,413,640,687,683,189,505,382,535,555,500,431,361,939,838,230,545,236,587,271,192,459,857,149,84,524,348,775,754,661,204,730,881,464,800,714,818,458,415,340,793,432,335,801,204,213,989,419,372,960,200,688,179,383,410,985,164,288,230,679,732,989,99,10,738,285,91,671,39,279,611,414,43,212,661,271,740,24,973,478,976,256,919,465,190,173,667,422,449,248,224,820,1000,638,67,6,117,17,387,712,833,254,794,872,345,546,155,210,404,336,456,999,631,764,613,818,72,735,938,818,46,321,574,143,268,646,243,109,936,988,17,153,642,351,299,518,979,430,643,522,9,663,858,477,397,360,787,391,178,454,328,682,138,490,790,874,621,620,834,330,636,259,123,798,787,491,895,154,135,568,15,488,579,387,232,598,145,335,495,805,862,285,580,2,240,119,142,749,21,585,284,598,3,974,206,267,518,838,844,308,739,792,925,263,312,938,367,98,143,23,660,103,509,133,999,592,399,774,673,846,961,544,947,290,437,458,16,360,539,956,348,780,229,87,6,69,819,654,987,360,804,651,239,572,225,940,179,25,987,911,953,410,215,54,598,225,235,422,754,689,293,382,334,461,18,269,967,511,662,165,895,240,119,328,125,688,691,450,811,979,391,197,799,189,56,512,575,76,491,636,355,532,972,432,492,1,131,664,666,929,527,136,988,16,891,342,632,486,428,628,474,804,707,256,207,621,15,494,649,78,53,614,463,510,643,695,972,745,627,147,3,362,422,401,281,739,928,70,601,504,485,927,798,633,421,45,576,626,437,565,916,856,804,721,260,25,163,291,491,911,389,707,312,97,143,678,367,816,267,902,462,963,434,949,673,464,548,172,673,522,770,36,871,114,484,736,473,26,808,940,625,104,935,705,218,963,247,269,286,703,75,825,259,709,459,96,883,38,316,895,99,419,46,9,169,968,988,993,449,888,139,325,179,510,302,545,3,567,625,813,377,70,490,333,457,126,174,894,878,768,850,399,535,419,704,280,598,840,897,291,566,66,79,688,768,124,982,51,837,7,554,590,694,566,621,405,462,573,22,515,451,441,321,829,222,277,256,680,899,759,918,187,669,979,900,858,604,408,919,104,982,570,231,611,132,33,691,764,875,780,722,516,560,829,559,608,189,920,949,826,644,952,575,944,710,98,995,848,191,416", + "870,997,517,595,862,910,227,671,793,134,305,89,751,492,254,45,803,576,666,727,20,272,836,208,819,111,238,369,222,208,495,217,69,4,557,388,239,411,564,463,425,508,67,219,472,909,693,915,916,671,821,889,370,256,138,160,568,580,799,264,253,415,60,538,986,32,723,776,61,190,949,940,202,760,22,624,185,934,529,20,436,207,742,814,0,557,41,734,603,383,164,529,579,951,610,703,153,651,264,727,585,487,127,223,634,205,293,725,464,241,225,809,461,968,992,639,31,686,155,147,447,276,306,952,53,490,554,460,187,840,849,356,270,386,380,309,12,582,616,847,271,493,953,28,446,520,630,114,343,309,366,305,489,724,736,317,488,107,219,94,34,500,625,333,628,951,436,494,317,457,813,536,320,540,729,849,654,889,210,56,275,677,997,620,403,612,363,813,942,620,434,762,361,974,828,695,873,253,827,493,227,404,637,237,53,7,478,69,276,284,886,635,171,672,783,396,582,303,486,506,928,612,875,334,513,313,649,510,742,368,337,948,576,329,691,238,511,686,673,370,366,992,432,810,133,524,20,741,150,275,937,380,78,876,692,509,277,367,779,454,797,775,439,965,715,534,748,390,801,540,549,53,350,480,183,4,893,404,84,689,582,930,19,980,433,740,666,104,56,472,610,992,340,756,962,8,53,58,351,518,698,511,912,696,85,411,174,645,374,733,97,539,29,994,702,879,754,789,387,80,303,165,927,770,413,147,900,320,831,254,166,692,258,499,459,778,416,694,24,611,477,143,68,16,225,474,871,933,687,347,611,118,894,830,122,459,865,267,560,628,986,947,700,110,686,636,367,501,420,635,581,228,954,624,694,329,240,741,807,549,619,74,93,125,435,358,456,815,985,589,390,760,371,142,308,531,453,216,754,912,736,696,746,517,191,271,388,689,370,1000,998,597,78,209,972,833,997,874,825,856,64,730,800,937,53,268,881,880,268,135,98,752,324,846,521,591,538,533,714,892,450,839,740,256,241,360,23,338,420,650,671,88,359,399,217,571,756,569,438,88,350,852,560,91,864,650,105,475,355,566,369,51,427,71,730,354,846,168,948,240,392,555,391,308,30,266,293,516,517,681,508,358,105,475,140,720,327,953,926,830,181,867,695,123,811,497,850,915,275,794,306,151,267,100,827,519,78,138,676,842,522,960,941,73,162,682,382,372,63,345,591,78,39,722,805,997,504,92,937,77,610,976,65,88,287,359,53,777,796,987,987,292,733,414,346,442,901,161,714,310,554,667,547,384,316,202,594,788,135,453,317,509,182,585,50,223,955,25,624,500,700,824,801,889,826,731,327,90,876,253,181,51,987,481,322,656,700,868,104,336,930,925,571,518,335,227,178,777,761,851,216,689,294,910,661,305,24,514,653,338,412,624,844,456,670,70,179,805,134,581,295,131,677,262,647,107,515,751,949,395,868,479,187,122,950,179,771,452,685,110,313,342,431,21,173,490,267,754,694,57,460,121,261,571,807,166,648,236,356,4,233,297,545,626,815,720,519,463,514,259,198,510,294,601,64,582,893,7,378,79,273,548,986,625,646,128,586,920,184,439,431,753,552,701,522,896,806,677,760,743,327,150,746,114,392,937,309,626,260,912,468,587,420,532,87,274,564,433,194,509,295,816,765,630,605,360,437,754,668,396,845,716,66,632,41,809,522,725,340,127,467,280,610,797,306,781,87,604,553,546,78,425,488,621,16,932,997,240,550,793,175,806,912,372,1,330,967,424,80,256,83,28,535,140,929,924,34,14,562,702,751,19,143,394,100,976,586,991,861,90,321,991,215,775,328,438,351,835,908,58,189,129,559,704,149,279,882,430,484,475,275,727,909,252,158,702,541,227,184,160,976,119,276,693,953,391,680,593,965,865,970,747,185,620,978,876,167,705,997,699,792,961,223,61,563,442,282,485,487,176,369,884,319,589,180,440,498,342,563,603,931,597,636,755,953,814,967,68,858,49,578,101,288,326,959,228,104,635,486,25,365,727,905,628,557,273,314,302,51,452,766,344,633,454,819,376,449,935,4,751,786,720,137,112,363,256,349,261,103,118,489,399,72,30,16,101,85,572,929,583,32,437,853,300,146,41,489,526,122,267,146,213,485,47,860,424,752,396,770,634,614,30,696,894,394,806,402,387,782,200,855,177,373,761,254,416,973,49,556,856,696,345,990,638,611,949,602,237,83,510,397,850,934,3,922,952,833,903,301,83,601,115,547,648,636,431,444,89,419,150", + "947,805,255,94,234,48,914,639,509,824,250,250,300,491,56,196,55,905,433,694,726,260,680,116,946,59,928,51,250,899,683,949,129,264,881,107,866,924,739,481,70,709,640,69,942,747,618,579,142,976,91,867,524,280,870,374,390,100,67,29,860,259,657,225,869,603,521,991,351,146,957,605,107,67,1000,405,215,768,561,836,205,37,764,347,557,0,746,13,869,856,879,815,324,563,728,771,503,888,338,275,133,422,436,385,586,533,188,959,762,684,174,234,348,109,7,327,315,801,718,25,312,9,853,623,171,317,12,502,355,690,561,125,990,936,689,226,377,380,77,936,609,597,356,715,890,961,831,91,344,685,913,515,485,125,390,706,85,246,604,99,938,800,85,692,737,208,988,445,54,307,806,277,761,218,97,300,8,194,254,494,753,902,734,945,16,450,642,528,39,998,181,19,271,401,808,762,123,802,70,675,497,409,285,194,707,518,490,156,777,885,438,136,852,277,732,106,854,573,990,578,481,628,672,479,971,388,273,238,84,972,358,310,413,70,260,861,622,805,317,808,47,5,637,715,730,347,36,183,231,759,911,195,149,232,881,75,429,101,664,266,51,275,324,324,666,414,743,376,518,347,562,634,19,25,707,467,833,928,661,310,260,681,833,868,809,563,23,206,748,299,544,511,783,444,103,400,519,410,229,416,559,732,910,685,463,710,871,519,888,260,158,958,889,686,239,368,517,804,792,650,590,837,594,478,423,628,485,85,290,301,159,429,247,215,786,696,380,271,656,518,730,430,79,543,19,531,233,262,805,280,843,179,702,869,951,204,171,732,20,729,776,313,369,550,650,744,667,925,4,992,356,850,590,886,353,859,258,607,279,121,607,113,852,66,358,831,600,392,793,800,834,686,281,396,233,104,582,579,952,874,913,168,393,722,434,693,149,103,455,328,149,596,821,842,231,494,375,174,122,533,858,754,107,921,637,20,315,741,162,969,309,793,373,986,390,404,77,161,25,578,146,8,361,253,234,279,15,883,486,460,172,52,917,240,554,725,484,278,546,935,666,914,889,201,686,738,29,575,601,65,447,604,513,300,279,372,230,620,705,817,869,694,668,956,612,832,444,77,730,750,875,605,568,173,463,62,431,967,560,85,671,685,225,509,234,474,301,316,171,756,942,51,829,715,940,53,289,924,115,503,678,913,171,488,992,102,394,544,174,186,585,913,6,776,479,225,65,586,900,985,326,2,150,712,822,697,968,448,188,970,594,927,257,915,548,622,115,846,352,959,256,828,854,880,551,899,542,715,146,17,373,231,523,947,560,693,595,330,683,345,488,942,289,587,380,730,347,818,871,168,984,515,752,142,572,304,30,213,361,427,991,583,831,993,84,70,235,678,373,497,960,268,669,131,785,204,958,654,271,965,467,509,371,923,690,751,477,233,396,380,453,701,25,182,618,737,204,415,451,922,110,387,227,825,838,817,221,404,22,642,142,427,959,829,445,492,735,619,684,435,33,73,482,925,756,735,687,71,189,971,110,218,744,247,483,881,477,552,548,26,812,264,708,406,998,418,968,859,70,744,807,903,593,98,632,462,474,754,552,859,658,207,533,460,691,295,603,534,118,341,822,57,217,547,726,704,988,800,528,933,316,916,64,764,211,619,594,939,467,818,441,815,545,926,962,810,724,960,933,818,444,79,816,323,414,536,933,795,820,31,790,672,183,357,782,208,643,350,198,904,750,925,612,152,860,846,951,148,188,612,259,237,777,859,244,351,447,834,615,685,572,661,250,282,109,840,872,453,151,644,349,117,658,355,937,545,741,28,630,804,170,389,293,169,722,720,634,507,813,270,457,788,734,187,957,229,457,721,749,161,667,663,262,960,141,36,21,801,585,631,661,446,364,72,395,613,167,25,280,490,845,488,567,172,745,109,27,361,995,474,378,32,117,234,941,636,643,110,493,583,55,411,619,590,83,713,695,52,28,866,383,421,162,494,674,119,684,601,799,637,382,440,106,46,169,993,630,479,845,273,687,589,955,865,393,347,735,433,283,879,483,125,951,899,60,729,85,31,79,790,414,263,21,125,758,915,566,893,982,895,369,823,844,992,597,610,951,631,756,242,523,562,638,74,171,410,456,114,494,842,434,572,769,430,527,884,940,975,473,358,548,250,917,237,924,396,706,225,513,655,289,887,993,25,816,303,258,589,8,130,892,865,792,990,763,559,146,507,392,287,932,407,906,351,376,89,984,657,179,763,572,405,978,537,329,186,896,999,993,191", + "159,922,417,675,644,531,681,703,839,608,368,531,780,299,414,69,462,598,188,916,39,606,607,113,537,637,360,589,787,615,463,914,488,190,950,151,203,11,891,928,901,892,751,990,656,484,140,450,64,754,491,25,753,732,301,113,177,968,926,999,864,524,177,789,457,38,677,346,269,838,658,502,479,752,783,65,159,303,911,922,404,779,983,391,41,746,0,1000,640,445,26,335,454,850,944,211,283,244,609,194,655,887,828,551,279,622,111,852,340,964,322,579,779,725,948,409,498,832,706,134,612,181,94,721,570,928,195,712,471,697,55,926,110,169,628,681,495,608,35,191,497,600,658,194,349,512,813,908,911,978,870,556,733,655,310,799,786,671,6,525,891,612,597,214,344,102,791,603,693,949,118,283,425,262,900,834,376,665,708,316,259,215,426,890,466,665,141,140,782,311,974,65,499,257,615,311,487,991,248,734,751,694,756,811,606,398,925,280,424,465,314,678,785,28,586,607,757,783,988,128,523,468,568,41,978,440,685,804,862,682,739,61,842,23,675,722,34,316,831,444,967,919,240,190,677,775,423,175,693,676,319,890,798,429,374,502,486,241,997,760,9,739,880,338,754,928,204,724,572,440,355,70,148,523,747,439,749,623,642,883,940,910,322,957,29,915,350,413,249,118,802,529,851,710,299,775,885,94,236,79,242,954,472,354,248,163,212,815,930,396,347,59,120,121,57,561,389,599,618,970,49,172,730,951,456,274,784,905,915,28,570,197,732,258,946,706,925,16,77,865,48,428,519,278,671,282,740,714,68,246,732,330,339,241,93,700,733,938,840,559,770,801,81,634,514,758,628,318,103,524,815,484,186,493,444,102,380,473,650,178,641,662,898,737,577,22,378,848,110,766,261,454,532,655,634,667,482,582,485,959,659,44,791,2,528,738,197,438,457,350,178,663,105,973,878,702,668,402,317,234,37,874,73,749,582,357,938,584,741,887,977,172,892,844,58,598,396,506,507,530,446,291,467,370,539,839,899,956,77,974,451,308,162,438,819,738,652,901,414,398,587,210,654,794,323,619,486,441,105,164,64,99,652,745,19,520,68,283,161,431,367,107,380,258,969,395,196,98,175,252,224,852,627,367,963,978,732,556,979,702,826,394,475,851,925,142,800,75,324,45,686,819,999,742,948,250,180,382,40,758,571,832,766,567,754,655,537,767,399,68,975,212,40,599,898,345,878,3,538,883,56,31,742,999,600,243,888,206,738,150,109,687,294,114,707,990,218,819,277,535,187,289,305,857,784,149,221,834,737,799,328,752,99,947,576,332,672,899,59,411,443,104,299,17,336,401,222,320,170,166,528,957,449,99,106,230,878,356,515,990,589,22,318,199,816,91,591,777,155,698,4,699,644,384,621,893,334,673,489,919,675,493,886,886,173,33,538,316,116,446,32,90,48,601,60,687,939,216,635,423,984,688,490,622,657,918,394,432,85,545,700,884,877,149,55,246,761,543,19,307,427,62,433,419,130,501,367,330,627,902,714,821,682,929,731,479,213,642,618,87,879,325,724,271,905,512,885,812,316,830,927,148,685,991,59,706,533,168,31,420,24,311,803,836,857,946,363,521,929,587,741,770,568,442,636,103,440,831,416,34,890,402,252,137,524,778,502,65,621,263,381,993,385,220,413,909,200,630,466,964,613,516,227,619,893,688,183,407,586,903,32,747,16,738,684,72,520,204,863,89,878,886,368,614,346,557,65,318,292,214,153,691,473,443,846,875,726,561,483,466,179,894,909,450,781,374,293,841,23,870,915,593,813,53,80,377,452,797,321,928,772,434,309,742,810,231,839,200,578,686,141,80,996,615,38,463,183,166,433,663,26,656,970,59,726,423,974,9,568,707,633,488,209,213,159,246,233,114,810,250,632,593,658,209,490,508,488,462,551,88,321,424,527,811,931,216,250,82,281,3,902,722,870,804,650,560,757,883,266,724,488,141,339,701,669,518,545,448,92,908,194,580,411,617,454,677,492,86,697,709,950,29,456,920,33,433,522,582,667,683,25,808,804,146,321,254,349,644,797,32,649,735,686,244,569,454,188,813,505,899,978,17,435,68,424,75,152,199,584,19,682,527,322,9,525,387,630,139,419,517,440,272,934,201,627,71,52,717,888,622,406,616,512,933,932,797,300,23,985,581,341,120,680,417,752,674,563,112,178,460,336,654,6,48,800,149,84,830,656,800,943,28,88,638,532,761,79,873,298,573,172,708,333,582,774,767,28,996,880,159", + "464,332,518,781,180,336,70,192,152,952,491,728,861,906,615,374,526,694,760,473,590,627,124,877,504,929,824,281,600,522,49,682,336,12,382,436,723,314,50,350,151,44,59,606,175,314,524,146,692,190,707,982,228,46,672,768,4,782,332,763,652,635,566,357,253,414,28,21,859,706,827,310,392,403,283,622,60,683,739,975,69,627,413,248,734,13,1000,0,865,273,347,460,77,449,519,11,291,187,46,455,742,425,387,426,912,666,274,793,580,830,847,214,342,769,820,661,156,321,473,79,25,995,376,585,491,481,95,255,202,438,433,642,501,295,217,810,834,466,380,490,658,706,242,241,891,391,7,947,405,461,225,927,37,385,126,54,643,546,280,611,681,160,191,480,682,520,436,293,321,431,646,962,40,18,32,155,471,867,129,117,46,60,326,585,627,752,368,436,965,379,620,896,118,40,974,908,963,389,800,952,939,515,864,895,667,669,559,187,458,953,19,581,264,983,984,349,959,805,353,613,64,291,283,18,632,257,859,595,600,678,274,570,331,147,825,627,218,704,478,851,686,345,42,398,134,80,230,680,382,515,904,584,844,821,723,890,147,802,239,668,680,255,34,562,148,147,521,435,611,355,775,683,708,140,535,934,778,699,274,722,638,622,683,274,622,850,203,94,344,946,334,542,714,887,451,356,513,787,78,442,667,373,333,480,944,848,640,471,632,228,48,348,480,585,418,768,892,278,380,856,580,360,928,893,342,994,718,861,3,913,33,617,355,722,692,262,749,390,11,510,78,869,171,327,867,238,344,260,853,548,573,288,886,184,105,321,206,675,742,630,944,378,796,799,402,867,771,546,625,119,110,315,3,914,654,880,742,999,866,75,899,357,645,680,108,47,534,678,531,173,76,602,372,978,444,112,802,242,768,321,361,287,105,737,445,459,314,824,357,291,130,11,900,237,929,465,926,119,123,735,954,449,756,290,595,112,421,160,792,887,396,285,811,24,494,470,387,56,200,585,422,893,974,432,692,287,879,343,33,1,212,204,975,94,353,806,903,625,289,2,974,366,139,870,586,880,625,874,835,597,717,198,480,324,664,21,616,388,307,85,862,917,807,958,168,844,836,817,441,291,714,594,972,293,516,919,137,205,652,601,742,798,691,784,864,3,850,219,767,326,568,784,718,856,213,280,167,639,817,136,734,355,34,736,380,915,915,508,749,40,252,489,670,954,458,148,592,581,795,676,211,410,481,850,538,242,407,950,944,938,539,365,476,706,447,775,681,853,728,618,280,634,792,515,112,624,389,55,782,602,73,74,343,699,389,326,575,550,776,94,149,829,949,173,648,682,956,27,603,797,352,147,850,82,980,44,977,248,343,879,558,989,263,105,189,752,190,550,901,999,496,80,340,867,999,215,617,969,47,672,709,654,99,822,721,527,548,766,326,988,376,853,422,526,950,812,74,739,804,262,328,131,866,751,325,33,878,736,314,942,562,386,585,59,640,151,981,177,469,81,308,660,187,647,190,49,936,984,91,208,155,892,103,351,387,494,823,508,408,590,531,696,261,647,364,579,662,619,419,516,422,697,960,700,547,466,644,931,910,295,961,447,510,76,109,513,9,20,678,476,863,574,829,740,135,510,599,650,448,562,727,840,559,470,470,350,934,692,896,499,926,528,280,996,736,507,707,510,113,150,68,207,288,444,626,239,572,574,72,972,327,126,541,722,724,501,948,352,26,881,739,837,698,674,716,920,365,930,413,124,752,857,249,945,928,543,267,913,287,958,860,824,46,672,109,921,79,526,827,696,762,832,326,130,472,802,72,342,980,616,621,261,114,710,347,6,957,724,234,62,139,150,973,975,207,733,765,843,223,369,351,685,797,729,847,501,971,661,13,880,916,974,758,728,761,107,922,943,546,35,283,588,14,777,144,664,369,483,94,464,214,182,257,446,34,16,809,20,281,812,737,505,500,47,347,504,237,687,903,1,559,541,748,552,21,6,673,399,515,610,43,207,726,934,502,276,808,630,587,691,132,429,424,984,581,865,748,812,270,838,208,662,855,443,545,85,406,197,799,997,681,575,525,717,832,914,689,744,164,92,440,785,553,888,373,16,483,847,88,628,177,259,134,581,347,151,630,453,427,110,42,41,296,92,718,715,613,696,278,920,461,533,333,474,454,655,784,760,783,20,180,345,15,465,758,293,822,716,4,487,898,83,339,398,565,740,265,119,802,442,203,731,767,395,680,774,32,253,786,974,664,650,783,251,183,250,593,112,459,679", + "412,116,417,143,361,936,970,930,287,465,354,444,242,31,330,264,701,529,297,544,303,532,624,36,789,336,133,357,606,322,574,736,920,482,499,977,649,622,532,52,837,666,810,903,217,293,813,852,7,725,481,191,668,377,109,315,636,520,918,361,188,97,584,728,698,588,567,817,142,813,116,203,570,455,753,827,716,174,137,359,52,70,296,410,603,869,640,865,0,67,85,37,385,208,26,633,138,113,817,670,650,808,663,434,194,448,614,770,258,273,209,807,214,345,767,773,167,876,887,790,317,432,456,387,43,974,629,652,105,532,479,197,101,126,989,324,523,180,588,644,202,666,102,156,536,833,246,618,58,490,216,719,673,841,974,981,77,874,306,390,840,189,696,535,84,341,723,849,142,957,270,509,404,699,395,309,587,218,520,857,173,744,99,23,415,648,232,904,455,204,922,329,919,631,917,474,881,575,150,843,102,544,154,927,98,893,92,684,738,589,766,680,422,137,277,192,362,51,249,212,909,272,843,44,539,944,93,832,740,933,483,501,316,10,863,380,798,641,925,354,298,181,533,566,366,333,290,448,590,287,650,545,685,198,252,555,952,175,622,704,379,623,86,179,356,783,284,123,177,829,666,396,814,775,611,544,913,550,775,191,1,96,322,956,334,469,906,465,85,659,119,333,673,31,27,959,590,505,171,663,319,306,764,9,84,647,760,33,392,359,942,790,42,640,622,99,897,919,197,384,996,181,20,351,429,554,925,348,514,149,540,393,786,221,969,157,533,711,380,48,665,765,48,468,166,352,506,204,730,383,35,575,326,123,576,318,174,544,901,619,32,3,948,890,206,520,319,902,278,733,155,895,392,904,847,276,740,127,333,157,624,154,273,865,76,837,689,796,74,869,16,436,792,584,486,278,563,888,683,804,856,717,993,509,736,50,783,562,81,921,743,636,116,781,19,905,328,600,420,414,255,226,165,106,495,36,831,560,414,837,710,729,798,229,580,62,169,538,934,40,201,718,977,741,142,990,423,394,162,634,205,31,755,478,885,110,580,642,61,165,234,755,370,587,843,993,49,387,708,626,146,30,89,617,771,122,38,692,388,881,621,70,212,189,272,977,510,625,485,768,806,832,894,781,354,277,277,913,768,230,798,758,213,885,523,459,511,985,665,427,88,972,751,279,786,277,55,461,798,103,916,989,420,926,999,859,631,843,450,519,774,460,479,538,277,541,214,266,173,388,337,701,864,868,544,886,272,629,683,288,787,863,354,560,72,968,943,962,1000,326,375,246,96,385,423,14,178,39,811,409,329,496,319,482,529,503,375,48,488,41,591,516,778,628,571,563,50,726,280,633,413,878,59,30,891,753,975,442,645,914,939,562,700,273,124,269,2,730,494,727,261,167,202,403,510,148,263,55,334,813,346,588,154,562,720,935,668,107,535,965,19,682,417,280,298,17,721,384,826,479,239,770,76,120,412,138,306,99,262,244,529,184,78,783,250,836,734,178,939,582,618,223,15,178,606,836,506,653,392,519,388,912,400,714,694,649,343,228,210,298,366,343,554,868,925,324,480,352,592,203,688,519,116,57,607,279,364,556,420,187,734,413,168,560,190,260,134,517,453,495,195,483,496,475,99,151,615,460,127,150,679,466,983,349,135,498,180,61,13,836,907,552,399,908,777,708,142,353,390,500,409,358,556,441,710,923,839,363,484,68,788,766,442,875,77,334,347,372,156,738,903,957,151,37,385,170,292,31,297,488,328,161,356,827,511,980,997,910,815,895,385,345,216,942,709,950,424,726,683,214,868,813,799,729,86,852,110,115,436,50,500,617,371,345,254,487,800,590,628,723,302,118,865,37,200,913,377,119,935,846,670,819,976,206,214,721,374,979,775,746,217,685,757,180,453,662,546,623,749,299,159,320,52,533,956,848,927,467,283,758,286,803,725,588,715,336,564,567,926,109,457,495,93,508,133,392,970,769,546,339,468,241,109,824,439,855,996,32,853,33,164,191,904,881,157,742,714,922,733,233,553,94,173,490,853,364,567,199,120,599,36,461,341,877,834,353,384,546,279,25,885,141,369,586,892,825,737,343,632,84,630,803,488,503,313,596,977,54,509,596,977,426,752,109,136,649,478,693,940,290,471,654,598,878,515,51,744,5,211,948,248,327,185,446,393,291,449,169,492,732,846,621,717,241,814,320,864,616,766,597,708,874,573,516,530,276,221,50,913,285,322,496,192,182,64,673,594,319,745,933,901,715,537,522,729,226,416,218,284,468", + "807,639,523,384,702,64,789,605,549,637,760,924,36,551,50,613,599,391,268,67,516,654,19,63,534,844,127,637,51,9,516,813,66,571,578,379,281,566,857,800,763,464,1000,788,421,88,808,833,564,576,765,359,354,620,702,491,26,223,585,632,85,241,830,51,536,33,924,628,860,169,78,332,575,793,638,786,475,686,529,111,140,531,375,804,383,856,445,273,67,0,442,147,977,649,230,187,505,727,302,991,432,986,946,397,83,839,598,202,723,824,448,88,490,375,9,4,804,6,914,77,465,983,909,333,830,101,987,999,79,324,44,38,56,473,966,221,374,909,682,734,681,739,985,249,418,224,440,217,274,977,287,830,977,352,372,293,662,30,735,479,234,113,933,712,689,147,709,515,194,925,961,725,271,227,231,834,157,684,795,812,328,943,911,114,303,641,893,740,539,508,700,526,805,459,696,827,987,470,647,141,985,609,644,455,372,540,148,732,38,300,76,647,758,713,977,984,482,809,664,495,423,653,644,935,939,889,228,991,835,688,679,345,124,205,803,81,262,921,642,997,168,427,717,110,99,12,12,481,64,10,417,345,840,50,186,627,18,667,628,245,424,898,894,606,767,823,804,980,551,936,29,110,60,187,985,818,727,206,496,926,615,515,41,261,616,273,374,916,994,124,151,635,285,749,733,487,639,654,591,294,232,204,379,639,427,135,23,251,719,185,840,691,686,693,504,387,253,933,997,842,157,943,66,140,644,824,744,102,750,438,431,362,503,806,663,706,783,577,813,703,921,511,714,414,156,393,84,430,520,610,238,67,752,958,633,9,178,425,993,711,719,970,513,858,721,390,133,180,908,52,782,815,343,328,17,412,922,806,614,157,855,779,474,88,65,385,387,696,191,737,997,758,848,441,942,579,525,333,778,325,101,339,106,197,673,413,69,149,327,745,710,152,987,854,214,200,942,186,866,959,776,339,499,782,284,121,107,107,591,68,28,385,483,766,245,539,590,180,768,811,779,699,909,295,727,31,31,272,424,28,281,59,730,763,642,838,152,845,874,476,216,339,640,94,579,356,576,315,686,679,841,819,758,568,25,766,595,882,802,421,18,939,719,939,485,705,133,463,574,650,503,719,514,767,859,973,214,416,319,922,285,516,557,410,657,867,233,839,859,638,735,492,851,583,103,182,604,417,615,758,871,622,898,278,303,171,713,209,255,594,320,55,258,512,814,80,282,603,977,320,147,372,629,639,607,15,75,901,35,861,813,718,343,850,400,207,848,665,110,677,326,700,192,546,998,678,418,596,337,944,584,159,68,580,642,925,545,998,565,289,503,202,589,853,669,556,728,880,631,851,295,974,997,857,51,918,390,200,214,653,931,520,222,554,39,357,704,275,149,435,851,696,305,86,789,238,372,306,287,408,260,986,879,336,157,754,968,601,636,579,850,971,72,239,43,649,412,588,365,818,459,911,409,267,910,690,657,793,980,349,577,792,257,449,825,154,943,901,18,745,367,57,738,933,768,67,383,723,282,66,71,687,342,208,251,548,401,107,147,582,901,115,128,829,908,207,688,518,385,732,684,742,847,218,480,875,929,190,254,389,365,763,222,23,243,115,669,782,192,317,96,828,258,47,227,386,257,256,523,66,997,108,923,860,447,217,750,433,629,461,59,248,140,314,734,801,513,111,217,326,486,428,90,923,776,379,997,481,24,192,351,950,374,982,232,153,199,118,983,418,69,360,881,374,697,856,358,365,608,223,504,683,723,578,81,823,318,490,183,954,565,319,468,951,565,855,429,887,629,718,581,106,480,717,394,898,358,419,297,542,729,998,16,648,17,747,967,65,575,376,695,836,669,602,682,570,834,198,134,37,712,953,180,413,75,399,535,756,690,191,501,784,105,671,439,827,511,35,637,994,635,612,836,664,750,14,897,170,949,878,79,621,594,280,329,350,778,202,637,518,375,301,341,728,896,876,271,762,758,760,486,519,730,106,350,974,790,761,728,864,659,846,983,434,732,340,976,686,157,221,781,219,96,287,381,748,841,519,338,557,748,989,240,129,781,239,861,146,97,598,313,294,437,962,809,971,538,582,683,445,804,630,491,722,76,871,808,509,728,670,441,274,812,891,498,440,143,511,97,350,644,887,937,821,523,217,30,208,34,358,619,346,411,282,188,195,114,451,938,555,987,347,908,836,227,954,193,298,479,813,766,109,313,490,39,877,732,454,738,391,124,599,364,641,269,443,323,787,868,972,288,207,241,798,276,420,727,40,628,640", + "765,333,896,363,792,421,910,515,202,875,119,356,508,157,373,748,883,686,318,930,457,119,911,136,434,653,584,359,898,663,610,467,463,183,939,701,749,267,342,134,490,693,851,753,684,145,204,731,438,536,919,8,939,978,864,228,780,241,473,201,573,677,849,758,710,126,439,631,475,118,577,39,530,63,813,978,886,133,353,299,293,607,897,476,164,879,26,347,85,442,0,929,376,392,925,13,438,150,507,742,513,151,798,81,984,197,578,445,393,945,658,896,841,904,145,64,179,211,351,665,704,643,147,560,761,639,63,46,981,298,463,24,374,567,135,903,831,485,662,711,686,194,809,979,301,87,500,673,719,660,177,498,469,718,124,987,138,322,780,663,664,743,968,663,954,654,704,367,905,883,106,915,953,990,589,641,289,479,58,248,592,267,239,469,390,769,769,288,825,550,674,352,246,237,218,989,897,991,500,95,840,886,142,781,976,486,666,308,622,48,3,77,479,881,779,409,707,462,886,806,261,216,166,295,257,883,402,301,204,17,157,369,162,905,457,115,70,891,563,905,767,235,226,639,381,188,961,886,335,911,289,963,240,611,152,593,178,32,634,253,281,97,47,611,407,634,340,63,29,349,318,832,704,456,573,806,507,732,917,670,249,376,813,824,378,998,74,956,578,981,403,983,466,553,34,190,458,92,631,366,908,703,703,200,925,814,81,500,873,549,935,792,134,336,207,865,314,866,842,843,868,328,551,462,702,206,28,133,859,697,447,391,504,835,729,374,689,86,114,366,214,492,561,733,599,981,248,728,190,334,504,504,934,991,780,934,667,972,291,522,73,215,807,837,464,684,285,961,808,771,249,36,607,861,465,43,7,523,404,840,948,978,169,306,873,304,96,81,463,104,168,549,498,847,406,888,39,969,338,277,883,530,723,394,100,152,610,132,517,428,588,770,650,88,29,491,306,611,448,616,456,636,282,691,470,947,116,813,384,209,396,434,618,29,271,240,71,108,577,300,231,372,853,8,416,831,120,564,412,829,734,44,602,655,842,664,125,754,944,56,96,235,226,121,439,410,663,456,175,112,934,977,717,844,341,158,589,275,75,89,540,976,677,184,188,256,460,728,480,964,408,215,178,309,631,977,208,24,69,821,125,715,924,968,347,829,505,581,129,290,177,852,440,388,140,440,738,354,6,42,882,706,2,393,348,128,706,721,620,912,518,839,938,650,689,853,33,468,436,568,53,787,648,427,897,319,506,728,826,242,131,246,51,454,305,982,383,356,155,699,394,707,198,468,546,114,673,798,858,34,244,486,70,696,455,258,444,451,27,715,33,397,698,108,734,15,565,345,512,134,637,947,271,238,265,249,42,294,9,90,827,388,567,490,559,481,280,422,938,370,803,732,140,763,300,659,927,766,524,497,970,823,109,350,967,490,224,378,85,913,295,282,981,320,588,968,40,513,699,788,886,359,529,39,585,202,978,163,504,61,226,578,945,926,732,140,572,487,679,398,233,346,540,415,618,523,254,373,721,907,91,507,861,511,796,539,117,793,576,926,74,963,622,302,716,295,530,270,221,76,372,567,848,138,872,5,771,732,593,910,501,947,637,524,239,636,408,205,27,383,252,431,37,311,628,433,28,624,943,119,722,968,166,106,954,656,393,655,939,946,691,602,971,845,846,92,118,137,967,995,589,542,973,165,982,877,68,398,497,908,149,204,408,652,61,700,713,13,984,330,557,445,123,398,620,594,54,730,948,902,831,429,831,196,325,159,984,287,142,58,84,155,342,998,836,737,476,962,612,921,402,377,807,543,806,731,328,993,100,733,549,413,930,108,889,323,902,322,774,838,539,131,408,653,114,324,60,815,758,60,815,550,857,638,602,464,704,614,302,821,76,357,587,919,855,60,577,706,460,79,429,724,940,634,344,599,613,582,802,80,327,465,913,128,373,998,866,428,360,814,152,691,426,79,285,308,9,567,609,901,549,136,546,330,242,842,964,560,875,397,367,289,459,91,826,230,638,217,515,903,142,543,821,731,844,64,417,410,59,641,842,378,977,19,401,144,327,932,17,255,464,770,88,487,121,140,2,312,945,54,204,738,861,466,467,803,419,402,361,902,300,48,734,656,295,158,876,959,404,788,339,158,113,175,175,564,297,721,666,356,130,393,118,229,484,744,574,484,734,169,668,323,484,709,356,938,33,746,509,71,479,310,626,854,129,328,398,311,244,90,436,712,347,857,370,751,509,51,119,7,37,115,459,426,214,880,506,711,498,82", + "174,384,784,838,312,685,187,398,741,648,984,253,58,957,616,66,75,503,403,143,206,843,747,148,818,503,722,294,594,351,266,541,93,857,193,759,77,49,273,649,232,191,592,132,642,787,704,701,636,503,488,707,477,557,175,697,462,438,673,213,33,866,879,732,600,437,754,866,325,565,901,767,3,950,38,835,664,486,40,743,818,536,564,679,529,815,335,460,37,147,929,0,457,538,364,395,890,820,290,466,187,17,448,822,359,638,867,266,606,175,88,392,655,899,659,516,503,959,560,697,835,697,760,916,841,691,315,676,17,830,722,918,683,610,298,560,609,924,647,556,932,528,923,472,66,739,87,363,794,210,586,706,560,315,605,9,144,13,44,328,492,546,334,57,601,670,468,252,234,918,816,680,363,365,636,376,175,979,432,906,273,525,197,933,675,506,149,770,636,905,908,259,818,820,750,270,343,547,380,621,574,304,472,709,287,521,380,870,756,969,679,460,999,133,234,169,975,211,762,851,326,770,413,770,308,751,423,196,881,810,394,571,495,930,780,499,216,648,124,209,702,216,433,276,330,765,944,68,598,763,248,839,596,627,249,311,519,367,966,471,284,228,619,313,713,741,334,586,654,886,712,276,467,763,628,191,600,53,61,582,397,653,615,638,591,408,463,539,13,335,918,11,895,448,486,134,382,123,183,976,658,59,573,509,963,362,292,164,581,39,207,791,741,308,144,157,705,770,261,646,113,82,555,163,600,198,802,137,661,947,927,799,976,310,664,162,243,281,948,362,569,403,887,402,705,43,357,223,278,683,609,814,608,256,815,496,545,612,369,526,791,804,256,888,119,936,157,133,829,11,201,872,378,381,716,561,393,270,531,51,813,711,946,940,458,241,131,148,164,521,980,892,319,492,591,65,797,582,293,659,501,63,75,752,355,70,713,902,417,147,520,556,547,898,830,370,525,735,85,382,827,215,616,268,822,206,702,573,500,686,360,607,258,323,708,914,207,857,595,95,417,787,277,726,367,56,323,678,658,282,777,428,45,889,353,262,699,680,685,858,186,394,769,156,457,883,578,161,148,196,93,971,524,805,687,539,575,828,809,797,430,408,122,614,635,57,336,315,545,169,346,780,45,391,521,902,442,475,307,111,300,688,4,646,164,935,763,583,372,914,143,939,616,880,390,488,401,158,601,860,116,795,508,337,308,850,329,551,322,162,410,824,255,395,299,368,838,172,47,191,426,127,159,205,329,481,181,130,354,815,298,174,175,962,410,116,286,398,463,540,294,646,470,224,934,312,884,509,456,32,713,574,820,676,907,553,716,866,901,297,945,642,882,245,303,567,559,247,159,690,939,23,219,975,641,703,587,618,84,728,304,230,995,549,613,324,346,877,364,135,487,230,155,83,206,480,787,499,716,559,936,64,798,117,63,199,113,914,863,296,254,616,67,266,194,737,619,135,192,429,38,801,462,553,216,693,388,627,84,760,473,492,552,100,384,830,675,448,488,956,690,117,796,35,510,428,978,193,765,640,441,780,52,528,282,563,62,377,400,85,776,12,85,69,222,525,762,74,371,462,929,724,915,83,552,828,903,36,824,555,472,84,439,766,404,30,23,774,947,945,598,8,477,840,489,573,769,832,791,679,977,381,711,367,124,16,284,162,51,362,404,378,894,587,690,844,555,7,7,30,873,768,501,572,802,715,496,325,169,418,534,131,919,915,866,719,154,101,124,652,746,138,595,663,573,947,727,281,30,859,159,862,878,503,668,553,225,710,758,410,301,785,236,601,329,274,758,325,795,63,317,635,502,326,813,333,21,46,58,109,303,270,130,708,460,291,900,803,770,349,1000,477,48,754,527,336,74,217,637,126,879,414,939,366,476,204,824,200,969,248,720,439,46,771,647,426,56,954,126,716,311,308,306,592,640,437,294,194,288,67,983,299,409,199,448,713,59,302,594,546,139,326,515,693,323,211,175,254,169,859,352,767,299,222,334,177,758,356,703,656,450,194,882,935,410,504,686,305,766,688,716,639,225,311,919,800,256,655,400,573,986,457,534,943,734,111,624,311,947,223,496,549,622,506,778,112,825,615,67,620,736,478,197,972,848,66,211,923,578,754,322,776,708,159,399,359,890,313,848,19,177,501,565,23,589,654,42,67,490,125,639,264,474,141,455,57,98,869,349,544,352,435,78,489,606,768,135,106,7,808,701,877,100,849,780,744,546,272,410,124,68,45,626,370,546,560,598,426,132,29,414,239,623,849,755,47,929,800,131,205", + "334,526,55,109,448,890,914,40,557,756,940,864,527,995,659,299,572,55,663,551,368,918,889,977,323,732,992,996,843,174,751,248,195,739,433,568,990,538,13,619,140,79,670,756,336,829,685,168,305,441,5,712,394,766,15,168,759,148,690,153,521,824,659,22,594,142,263,240,86,684,428,137,128,911,171,338,422,78,435,767,174,148,693,394,579,324,454,77,385,977,376,457,0,693,190,634,39,976,180,34,605,814,358,905,154,120,907,631,663,201,729,514,224,750,265,447,995,366,420,993,193,878,528,800,336,635,871,241,462,731,636,777,63,918,841,433,559,352,698,474,774,159,911,323,607,427,670,801,832,487,893,679,538,31,557,739,658,147,995,555,985,15,701,250,226,548,861,677,300,215,64,505,759,541,220,321,786,112,48,696,8,199,442,159,809,964,535,212,464,972,708,136,986,390,683,112,939,2,947,942,654,329,542,316,998,240,48,907,32,542,175,391,37,267,965,918,179,806,417,754,725,478,679,43,866,664,404,219,862,233,988,548,200,18,917,787,918,825,650,235,865,842,215,479,13,72,503,595,687,927,114,302,559,597,849,842,356,690,160,755,545,154,192,799,258,532,675,604,174,293,983,397,56,299,134,499,893,661,998,287,201,557,894,558,603,438,216,512,79,607,63,478,948,767,746,724,445,471,474,514,139,737,215,125,507,923,787,250,681,177,108,556,606,218,945,961,621,30,736,278,882,448,186,242,526,790,50,267,215,714,415,609,705,269,282,551,818,298,839,857,516,949,703,112,358,763,380,160,959,110,951,736,456,948,851,433,756,157,285,706,839,294,159,313,556,470,732,715,785,146,49,913,218,721,318,594,384,144,571,422,136,966,733,594,204,714,187,993,755,340,989,541,430,465,890,561,210,383,214,738,740,508,404,990,155,144,900,225,301,894,642,328,424,889,970,95,47,256,408,716,348,295,310,183,17,995,283,106,603,890,695,178,358,365,434,244,579,688,379,698,877,977,145,470,31,337,938,747,232,164,198,868,909,960,941,313,901,895,790,429,507,518,290,354,77,530,706,89,992,813,852,18,976,336,722,276,897,728,867,973,77,643,300,682,615,749,175,982,111,437,17,587,165,645,668,86,507,992,524,473,317,999,466,607,749,475,522,186,560,383,442,443,325,571,89,438,137,533,426,57,357,434,697,95,859,488,184,885,889,486,52,900,730,232,502,995,994,628,431,515,946,290,540,919,195,929,966,921,143,181,118,427,817,277,694,680,801,463,889,94,412,760,335,104,56,905,614,822,376,460,668,937,761,751,450,908,361,341,415,929,503,994,391,196,11,44,467,574,568,256,405,878,876,518,309,562,488,428,409,993,281,747,713,531,277,169,137,903,618,206,806,837,955,796,200,826,328,475,89,814,110,542,773,145,318,541,224,261,225,922,506,876,2,355,831,482,156,252,696,442,993,933,652,670,896,314,131,11,758,91,704,607,60,836,86,482,18,131,555,557,226,47,582,986,874,814,660,502,605,497,214,114,472,472,207,256,673,876,60,973,683,677,159,456,94,657,486,449,478,587,363,471,303,370,827,811,108,878,589,440,420,22,263,116,301,25,379,594,427,178,579,739,972,540,934,51,117,756,980,419,939,65,4,424,552,123,49,381,280,434,351,425,671,679,867,217,337,691,326,922,559,976,742,341,952,712,307,637,689,109,487,620,898,46,707,58,388,69,779,570,318,328,898,691,888,538,583,478,207,428,959,823,777,771,657,565,891,366,891,959,615,804,243,627,626,178,184,226,735,3,543,391,704,750,54,569,303,88,58,689,831,141,91,569,278,648,94,530,19,118,632,931,921,908,16,995,664,27,555,989,559,765,161,856,388,280,543,95,303,644,54,266,196,353,571,764,549,332,902,241,436,172,93,568,733,558,324,549,157,49,630,857,93,947,771,991,634,94,518,771,340,701,757,428,608,846,694,459,880,275,760,853,709,671,592,874,985,452,268,187,944,520,419,578,123,277,294,965,771,732,671,757,169,700,142,922,852,406,486,874,956,729,570,788,392,116,165,90,856,653,605,843,800,234,646,2,148,400,372,733,813,654,499,53,771,259,443,969,638,575,878,5,274,81,264,483,3,557,447,991,113,388,232,172,313,217,575,90,346,124,511,902,264,394,445,892,843,395,602,274,360,923,619,225,27,183,90,803,169,348,514,519,485,993,175,106,317,436,869,797,926,81,692,800,196,815,884,522,888,964,181,585,819,969,886,101,569,8,204,520", + "77,980,673,41,312,581,381,15,931,91,302,245,966,608,986,484,571,934,268,906,152,462,747,282,600,866,108,953,917,547,672,29,681,527,187,457,905,922,282,981,518,536,790,582,912,321,599,826,23,352,641,178,828,803,782,431,33,434,673,805,341,905,451,89,966,337,437,494,393,374,540,432,717,677,438,595,425,892,322,422,54,572,134,518,951,563,850,449,208,649,392,538,693,0,197,186,781,479,786,953,220,763,356,880,847,695,518,473,803,202,120,692,461,701,957,39,311,31,597,366,127,331,880,761,183,238,600,919,682,254,11,112,965,294,586,541,94,627,988,992,868,195,574,996,175,949,867,287,76,976,773,269,507,986,420,508,756,869,275,499,562,344,62,353,124,285,440,304,455,573,674,52,64,692,373,340,766,198,764,574,525,785,648,688,453,551,265,665,739,832,915,715,281,278,804,472,822,45,176,431,717,314,276,3,984,173,449,741,890,368,324,901,458,345,462,919,513,575,496,827,526,413,382,378,971,392,16,79,194,246,214,256,217,89,965,124,57,717,215,63,225,261,307,487,953,414,715,206,667,526,803,366,212,539,177,607,297,944,29,78,641,895,193,917,825,824,264,902,292,839,379,624,872,949,487,253,838,411,938,722,109,242,613,63,313,739,526,341,236,851,428,534,562,124,537,369,650,313,165,152,873,684,27,984,367,695,233,562,185,307,540,938,945,32,201,482,948,67,352,896,395,667,809,125,22,572,794,711,71,678,291,469,939,262,125,147,773,527,263,649,743,2,576,125,173,830,241,912,948,95,208,652,86,227,552,685,299,216,732,678,789,219,973,379,123,457,40,488,387,307,222,430,253,503,68,605,141,862,311,701,740,163,982,325,911,257,198,537,416,12,815,193,921,736,273,173,551,76,129,844,793,291,811,70,123,16,630,503,474,698,851,19,76,96,977,222,461,181,249,291,379,153,423,360,265,762,424,596,862,710,109,404,858,410,666,486,670,75,529,167,556,349,562,150,274,907,365,612,555,666,936,134,282,955,504,570,26,679,200,845,668,512,580,270,958,32,399,124,383,986,412,959,930,220,669,510,237,456,764,363,173,180,280,248,271,385,271,336,948,454,842,372,332,45,163,265,706,941,706,526,462,522,7,363,802,791,615,477,352,641,816,120,397,55,846,374,426,747,935,822,431,658,75,236,122,846,844,669,29,813,627,320,387,55,350,487,721,938,427,706,147,932,775,34,418,12,963,97,277,905,435,337,775,956,760,700,358,230,169,547,368,276,845,576,560,311,978,688,965,337,806,385,415,615,994,867,526,635,698,446,197,743,566,382,789,533,653,817,638,805,413,236,66,73,531,322,337,967,304,130,413,400,836,248,462,818,491,514,266,323,916,445,355,665,686,464,28,643,110,641,727,640,8,409,572,797,791,995,329,233,119,531,908,836,34,784,343,108,928,864,954,802,138,636,436,823,834,333,812,568,616,41,329,419,371,439,47,804,336,88,929,101,288,218,914,434,274,192,445,761,108,107,856,856,498,243,444,463,84,798,704,757,565,771,859,578,286,138,784,590,917,822,498,919,61,844,944,729,934,894,731,433,956,814,228,117,656,114,514,528,573,226,195,378,86,746,565,83,432,801,879,344,492,18,223,163,995,315,124,498,25,433,710,736,477,500,558,628,981,263,797,962,76,788,944,531,842,316,431,531,324,345,750,25,500,425,360,889,479,495,76,912,205,660,514,558,123,506,968,455,869,512,950,793,691,243,518,142,932,748,100,161,845,708,885,826,338,683,932,31,563,697,269,726,527,693,706,662,15,808,927,295,970,777,865,339,352,548,567,151,288,507,443,996,748,843,54,591,326,79,275,614,328,754,128,854,136,782,726,18,184,590,44,998,793,275,669,235,17,308,782,237,300,219,917,962,546,566,550,862,110,443,115,365,219,698,181,710,103,166,385,221,834,218,101,411,824,69,120,951,870,591,834,131,863,62,676,16,560,474,957,106,727,200,462,77,149,711,975,591,825,258,959,152,244,32,908,703,447,566,310,577,568,248,415,860,656,865,402,686,407,591,860,624,435,316,724,191,675,674,12,176,743,413,725,665,565,760,80,209,583,236,693,213,756,434,449,884,298,932,677,406,770,151,433,432,416,634,40,629,570,13,600,300,58,985,879,109,629,320,174,444,284,176,168,540,386,387,66,660,573,61,440,438,835,974,724,444,875,760,881,861,28,110,922,631,822,424,655,381,806,65,212,148,295,936,239,533,29,91", + "930,764,417,294,410,899,999,193,904,38,476,829,612,806,328,672,325,24,45,222,612,552,704,753,182,832,382,117,789,524,385,14,866,56,997,440,16,572,684,365,706,635,230,918,475,109,528,204,157,670,215,607,808,629,801,511,295,612,873,974,275,667,334,820,967,40,888,698,89,720,851,284,293,315,266,929,744,504,780,839,57,148,263,637,610,728,944,519,26,230,925,364,190,197,0,421,934,583,210,353,616,31,760,879,525,329,272,499,416,569,94,224,253,512,102,264,865,705,837,607,591,828,100,516,323,166,448,137,130,777,403,14,450,143,61,550,235,818,26,745,742,115,443,4,697,703,369,109,733,707,527,868,632,724,443,662,311,277,413,398,195,232,988,646,687,834,749,593,680,592,556,510,381,855,322,424,728,147,3,394,669,788,491,345,360,729,677,258,677,431,624,847,821,514,150,915,881,541,597,7,124,839,197,17,856,98,256,66,563,647,593,835,840,598,167,546,99,244,936,464,769,640,126,205,82,869,16,987,318,787,671,572,286,994,322,30,444,158,598,142,135,575,391,548,470,767,118,195,564,656,661,587,4,253,219,753,976,49,584,742,155,463,48,573,201,981,416,322,343,252,114,393,64,86,175,997,95,16,974,330,797,740,307,544,312,844,259,316,197,81,464,38,170,909,53,666,633,19,832,654,168,355,154,952,130,233,742,834,248,85,888,488,615,305,464,486,146,129,70,133,487,621,842,828,966,553,268,308,311,300,120,924,384,697,514,191,798,720,202,761,813,68,891,784,695,15,552,363,789,516,554,669,369,787,407,161,241,272,606,385,883,773,883,821,370,94,290,374,659,10,292,273,701,863,784,820,100,370,409,709,110,248,393,135,536,473,117,78,361,78,504,636,599,417,852,960,890,714,897,539,879,17,46,313,892,140,614,466,138,576,883,520,120,582,772,106,706,326,782,595,502,79,659,289,202,36,303,519,719,125,645,697,811,224,998,533,926,462,887,324,497,958,706,976,666,12,390,838,570,692,301,791,860,747,925,370,77,776,13,200,16,108,13,150,714,687,688,356,720,281,692,747,947,37,296,886,339,466,74,417,738,797,573,389,349,614,200,691,140,890,693,376,886,778,329,768,6,840,387,590,460,698,854,351,842,970,493,647,447,770,798,253,790,719,608,171,327,421,771,399,604,265,328,856,706,941,503,358,825,612,505,450,524,17,289,5,816,136,648,186,840,864,192,29,45,168,383,103,772,639,359,981,430,24,217,238,381,244,393,460,976,953,690,987,499,625,841,838,62,639,511,303,641,778,862,662,253,607,678,361,59,190,387,120,907,224,818,140,895,115,660,208,815,781,480,434,584,981,46,709,441,843,565,394,197,929,455,205,619,458,58,489,991,365,973,522,204,195,71,954,855,693,549,561,608,93,559,897,406,774,757,580,810,611,670,475,841,829,951,400,769,271,366,895,225,659,57,507,938,362,351,300,700,229,498,890,470,27,631,278,223,236,478,804,121,910,125,776,273,108,854,454,376,539,781,804,669,166,522,604,619,785,985,402,41,278,132,8,607,925,388,453,786,457,699,961,968,877,884,975,686,324,976,883,353,919,935,668,362,326,310,786,82,206,329,62,53,998,906,760,680,484,599,795,243,622,489,424,88,103,468,160,77,476,977,554,418,355,3,514,347,827,333,56,176,851,477,683,598,599,859,473,457,140,233,966,422,82,129,523,343,558,913,410,298,164,516,338,726,302,810,668,184,904,580,51,378,266,775,214,712,599,2,554,15,585,335,222,206,321,419,920,249,225,919,422,240,861,571,306,230,689,846,975,83,868,587,670,779,99,747,115,870,169,505,246,610,216,831,862,534,371,79,866,19,650,231,24,95,296,377,382,693,661,35,790,446,576,863,75,496,432,37,739,79,402,505,539,529,373,557,428,646,8,736,420,812,697,685,274,662,357,748,726,378,378,782,919,767,990,374,712,818,984,46,382,850,946,561,427,946,364,856,757,560,860,175,352,268,698,504,588,243,933,812,168,252,459,683,238,802,296,558,314,869,277,190,95,169,856,498,857,977,911,981,624,651,737,366,218,684,877,752,946,402,968,853,36,838,579,83,410,410,517,541,357,535,454,645,418,814,112,416,386,362,834,989,320,61,235,158,299,359,172,868,560,54,143,648,616,917,277,222,656,462,983,317,172,868,667,47,36,956,883,341,750,707,796,217,439,266,317,317,633,284,295,890,722,507,820,479,701,700,499,327,131,509,268,936,777", + "536,929,665,160,924,792,749,759,155,732,19,293,88,928,671,515,666,774,149,144,452,310,317,58,193,657,987,664,174,774,367,794,349,326,673,516,751,198,878,151,934,232,549,980,987,713,963,450,310,428,755,46,285,444,999,321,625,319,632,866,682,952,493,376,381,161,956,524,160,519,310,274,742,894,354,545,926,527,494,718,223,317,198,471,703,771,211,11,633,187,13,395,634,186,421,0,508,44,737,836,718,50,584,397,145,27,249,965,637,668,699,624,631,614,983,135,428,352,184,668,91,656,370,845,911,475,459,487,885,690,564,841,910,522,432,671,626,663,193,536,317,421,321,859,879,628,310,944,157,712,315,84,839,487,916,237,606,569,248,995,90,905,151,160,847,483,978,20,973,291,34,517,652,671,255,726,6,372,829,872,638,387,978,837,414,164,746,120,430,474,640,893,57,234,427,571,969,389,178,290,756,641,976,532,230,306,547,501,696,299,341,526,40,213,268,538,732,95,922,923,123,5,280,354,789,553,144,42,657,121,69,851,952,316,521,276,55,681,736,982,24,137,797,114,279,628,752,426,530,142,798,546,192,196,201,12,645,236,637,363,653,683,973,182,418,178,249,265,81,236,539,146,647,341,263,229,48,777,321,260,469,238,322,221,105,31,846,294,146,329,303,201,634,556,89,295,994,274,864,526,773,894,15,615,33,173,755,13,639,288,437,617,459,642,234,434,889,944,456,653,757,440,725,438,753,496,952,440,414,975,207,459,217,588,565,826,60,457,603,646,827,993,901,620,368,893,345,316,668,946,698,481,520,43,531,311,666,156,454,971,126,899,533,34,600,729,306,931,175,373,156,58,148,518,120,120,284,718,538,570,917,250,357,603,738,812,198,735,759,838,740,877,140,366,88,965,643,174,175,30,824,894,61,163,676,839,37,989,643,779,728,881,3,101,961,90,336,185,807,851,536,121,529,55,834,413,967,168,920,220,626,877,333,368,871,827,77,277,59,960,147,443,255,76,980,468,185,779,893,643,434,904,178,378,68,70,755,48,510,948,425,12,901,18,351,522,796,397,510,823,36,207,223,971,397,896,817,68,244,123,603,966,996,736,329,371,758,616,606,829,525,781,227,49,695,245,206,856,909,661,686,105,146,798,204,762,84,409,951,773,901,394,345,281,746,835,287,245,252,88,360,636,769,498,253,19,392,5,187,744,493,217,278,169,186,946,346,557,748,722,620,940,422,69,47,258,400,732,644,483,92,999,513,623,228,975,876,785,119,218,360,436,433,14,343,615,909,125,166,527,75,261,877,366,890,718,794,130,780,841,644,469,572,207,467,808,619,786,53,823,250,184,19,187,490,759,695,364,874,848,81,338,245,692,147,993,533,17,375,857,699,720,793,258,668,916,893,991,197,161,926,50,653,23,46,155,525,717,12,769,128,842,43,61,548,330,521,809,346,754,29,21,57,809,554,956,95,484,374,980,545,937,61,932,755,164,994,464,464,908,497,748,747,816,509,760,391,230,598,578,550,879,261,525,121,710,766,210,280,748,192,413,55,64,565,795,985,808,180,939,298,923,667,564,462,751,356,562,991,561,119,866,633,135,69,4,600,59,212,780,1,84,300,409,641,458,517,564,337,290,774,571,981,666,242,618,323,241,329,126,705,853,792,618,553,93,879,290,627,474,831,402,849,649,107,161,794,739,981,928,573,501,617,347,897,334,23,910,539,634,580,340,898,85,815,206,868,691,586,866,388,103,472,412,482,997,958,665,749,618,425,669,405,753,832,275,844,542,769,668,588,734,773,326,156,876,371,561,7,762,826,870,184,169,381,310,98,689,794,101,483,29,473,291,370,108,411,567,691,938,903,831,194,638,986,286,43,487,561,649,129,677,944,328,535,214,410,837,973,892,514,114,804,576,84,832,583,445,324,75,824,855,381,31,229,674,511,93,259,358,916,528,422,360,26,131,197,148,577,174,971,710,474,537,965,142,283,910,316,797,96,526,224,370,83,612,284,426,447,509,57,123,159,149,486,839,232,759,720,794,963,698,845,163,665,503,941,763,957,987,969,157,194,583,363,958,357,756,817,917,256,827,739,397,288,437,165,194,598,310,917,328,338,831,743,893,201,687,429,54,260,850,666,540,965,311,979,635,851,274,510,250,898,507,632,189,814,395,236,580,53,357,958,253,947,513,321,278,425,375,105,367,443,634,495,993,27,135,926,883,22,770,867,307,801,503,523,830,527,548,42,951,637,142,547,309,22,649,430,692", + "885,183,893,950,337,947,341,461,418,141,145,562,946,415,395,531,847,331,105,697,229,954,309,490,719,829,160,39,486,66,781,895,259,970,217,479,620,25,505,906,198,248,991,205,684,80,262,367,414,548,240,647,999,916,828,34,361,5,310,539,697,341,529,600,729,737,152,84,515,68,89,560,923,258,284,804,310,668,10,779,373,651,246,786,153,503,283,291,138,505,438,890,39,781,934,508,0,577,911,843,570,583,560,856,498,383,91,218,213,238,396,83,109,172,284,72,470,50,670,32,76,62,624,864,10,438,780,2,571,268,41,91,828,811,144,569,678,377,244,727,918,296,404,890,590,924,407,125,221,149,642,465,261,49,494,910,525,252,614,629,485,665,857,143,948,607,681,45,971,849,437,250,923,612,610,378,897,390,337,196,195,80,408,640,7,267,207,443,727,266,934,870,837,807,972,802,437,435,824,545,76,385,444,324,711,83,292,125,92,981,481,499,705,961,177,892,992,101,298,460,213,929,671,560,882,689,94,445,42,429,199,317,741,608,429,305,13,219,152,230,851,381,376,664,935,749,891,622,819,359,891,570,66,656,171,977,786,654,127,90,162,506,637,775,959,226,415,316,441,318,469,963,6,114,76,448,995,873,954,389,94,876,439,320,489,120,708,328,559,729,431,642,211,468,46,19,13,583,686,567,269,994,117,932,205,124,400,57,684,175,778,288,264,985,361,692,315,887,935,375,337,76,555,348,44,933,55,108,125,369,949,105,540,43,277,313,128,341,216,305,96,853,214,435,172,476,163,594,292,261,484,391,883,775,654,827,606,461,753,839,890,634,809,475,127,977,363,241,298,178,455,827,974,290,239,530,900,230,603,776,180,169,132,212,423,300,307,623,287,386,632,222,299,135,221,889,635,657,899,887,301,330,254,113,474,14,67,326,69,334,218,157,835,111,196,103,292,390,278,277,181,261,473,384,906,868,74,903,696,966,87,906,136,249,1,799,545,323,123,481,888,176,574,515,655,99,245,167,257,982,530,495,720,219,799,963,841,682,498,617,701,465,369,617,31,49,34,440,325,377,651,530,174,162,137,771,979,655,788,480,731,893,27,996,499,511,451,554,401,432,720,19,938,350,200,166,184,997,361,68,554,908,530,511,222,295,5,272,208,597,690,792,628,326,480,853,268,786,499,312,95,144,125,636,695,112,576,79,28,210,210,590,496,874,92,675,701,280,643,916,454,961,449,960,88,700,992,366,744,248,765,7,386,33,623,48,457,339,602,96,293,670,311,173,705,867,613,991,525,700,868,602,563,875,532,858,423,916,117,447,1,676,822,896,966,125,761,101,255,930,215,886,205,7,54,345,64,301,67,270,220,475,495,515,640,400,931,100,138,819,379,809,581,930,200,106,446,556,461,732,293,775,247,958,277,157,20,761,60,375,124,980,101,576,71,919,301,5,547,372,235,98,283,721,74,815,478,205,235,632,724,327,444,559,938,286,990,617,599,522,400,312,420,502,507,180,413,596,901,143,339,849,298,273,182,90,279,191,556,558,935,872,160,956,94,865,827,183,239,435,631,384,683,400,579,53,881,395,460,884,679,246,685,651,883,548,446,555,160,102,193,43,222,477,30,311,707,141,125,228,120,914,91,668,865,607,639,530,412,608,885,699,987,414,744,910,474,777,813,609,585,619,246,800,336,888,383,445,847,988,649,338,808,794,621,390,949,629,124,852,983,442,359,616,142,77,835,545,875,870,919,254,569,937,683,840,472,409,79,471,356,449,659,421,832,767,500,210,278,362,56,372,214,602,611,491,274,325,292,655,760,725,340,235,79,391,59,612,655,139,552,384,941,742,380,584,523,822,145,741,480,781,603,152,521,266,968,968,825,436,684,795,318,707,860,195,324,910,935,319,357,301,878,410,797,87,695,724,712,910,565,856,746,326,879,980,20,672,162,960,158,326,25,770,777,864,170,722,507,754,354,107,209,606,361,326,153,550,474,243,116,367,658,287,307,121,784,849,71,790,607,522,101,480,884,951,556,172,179,365,30,328,264,388,694,836,173,448,492,915,807,721,122,587,266,535,711,727,500,918,578,587,995,316,239,815,96,174,852,584,688,415,693,576,812,360,638,281,187,1000,785,516,427,599,458,851,14,644,97,989,940,883,612,641,737,938,430,170,162,813,970,903,772,444,351,965,407,524,344,581,177,306,38,109,533,86,965,452,326,943,914,654,961,859,436,917,299,117,883,969,457,31,801,910,621,778,316,313,52,275", + "533,987,870,754,720,188,828,212,527,802,863,126,542,414,473,836,750,257,440,334,709,895,578,62,736,413,340,792,914,935,267,66,754,857,108,236,756,996,999,251,959,99,369,220,399,751,337,998,264,302,300,932,993,625,740,878,83,970,31,707,830,224,234,610,5,188,439,656,331,546,651,549,351,74,79,517,881,587,753,636,970,421,269,664,651,888,244,187,113,727,150,820,976,479,583,44,577,0,993,710,382,712,174,507,466,271,779,54,912,942,366,637,829,240,993,577,450,486,356,812,48,528,589,534,466,224,599,96,830,866,233,594,573,102,621,468,44,469,242,577,686,202,767,507,311,772,867,584,973,464,554,781,236,610,403,634,875,543,215,980,484,599,133,290,15,287,716,449,725,119,917,430,578,755,914,469,87,507,399,279,468,787,24,639,998,391,74,967,166,430,535,401,429,72,836,859,425,654,256,486,682,277,134,694,488,671,677,85,736,27,391,62,557,465,516,833,323,505,477,237,474,581,451,235,472,34,691,191,260,362,637,43,117,692,579,729,755,439,887,997,93,892,317,251,236,294,116,882,641,515,540,18,821,713,946,550,112,459,303,120,188,473,152,832,896,531,254,306,397,16,202,479,133,7,737,469,697,626,72,830,470,141,279,455,282,704,865,763,358,499,777,219,970,715,916,298,328,920,495,632,66,255,19,708,890,856,967,575,28,829,361,173,410,114,917,555,678,358,355,70,623,433,407,219,408,658,815,229,76,635,754,54,50,925,651,829,302,719,13,113,378,252,943,901,897,218,732,117,538,423,563,261,877,910,908,349,263,459,196,196,235,922,961,802,790,348,718,998,166,957,432,878,453,486,904,605,258,477,955,830,588,267,459,166,993,648,109,442,5,619,214,402,235,798,469,69,187,356,286,409,995,181,660,300,39,572,71,43,603,322,970,653,334,950,564,84,37,865,318,925,31,175,956,921,222,956,491,284,27,382,976,144,684,477,607,14,965,590,307,458,159,289,369,606,707,294,924,421,679,339,890,602,947,942,402,545,875,533,313,789,260,515,667,978,322,998,952,667,269,429,86,214,52,805,368,156,301,526,77,336,497,328,147,114,763,519,726,171,288,893,615,253,588,538,457,139,523,340,950,439,689,299,225,433,252,120,706,439,316,356,128,529,573,263,361,337,484,450,259,66,561,730,395,152,493,760,686,386,539,292,478,206,228,268,325,578,81,896,304,752,900,881,265,782,431,463,661,1,148,991,336,522,144,486,79,55,870,533,545,834,119,869,271,253,47,145,839,311,598,106,267,773,667,731,658,613,509,687,883,457,924,707,835,343,625,206,625,920,68,539,684,351,475,104,849,598,82,419,389,38,118,776,442,699,856,146,558,531,872,119,61,468,529,933,293,782,276,639,838,940,66,597,128,955,218,866,509,604,24,89,614,515,632,946,308,337,167,209,116,477,810,958,43,684,846,736,796,619,475,408,257,300,255,463,767,219,889,619,981,3,601,552,18,413,201,752,645,424,703,173,740,87,115,891,640,933,702,286,889,247,422,607,931,18,93,112,939,66,792,450,309,882,177,679,501,653,343,838,131,974,890,521,837,723,240,490,984,787,606,25,912,133,690,755,358,103,374,91,703,128,154,274,724,152,378,630,257,348,177,628,547,380,927,374,90,71,321,714,130,478,452,559,306,833,719,574,459,341,727,873,433,19,829,206,669,875,216,926,201,251,205,434,69,918,489,962,652,432,716,260,935,503,104,106,872,507,106,833,374,281,115,697,952,147,76,406,374,412,896,133,245,907,821,845,906,682,70,227,607,8,552,840,545,139,286,829,257,275,995,30,387,552,991,551,983,694,923,805,185,982,320,761,281,518,657,145,821,402,988,479,331,448,343,226,533,820,679,175,251,941,588,392,407,305,692,749,59,325,543,718,284,261,576,308,224,36,983,816,829,761,246,653,467,29,737,428,90,518,603,528,186,709,897,880,13,673,537,902,37,761,109,757,669,859,791,563,338,989,987,406,997,382,584,793,463,163,191,200,385,163,236,368,241,168,400,905,330,372,177,428,423,619,271,660,382,946,717,579,261,794,283,680,782,189,966,731,725,755,929,482,41,171,948,499,117,786,385,861,773,521,617,961,985,87,884,534,623,456,790,591,531,938,924,439,946,908,767,830,676,774,817,445,976,746,330,108,175,65,170,735,816,64,963,792,50,739,304,30,694,177,125,941,946,730,380,190,598,337,79,845,250,6,99,96,867,419,324,229,569,944", + "202,806,4,224,907,981,857,870,881,664,675,657,398,584,566,420,26,348,737,527,470,890,799,174,367,245,478,786,698,563,425,34,100,851,396,520,142,101,515,184,106,996,500,484,958,677,700,372,472,619,833,91,305,52,342,703,653,559,326,391,840,66,837,91,209,374,258,669,154,941,102,908,79,42,230,119,325,817,960,138,450,194,4,574,264,338,609,46,817,302,507,290,180,786,210,737,911,993,0,701,224,422,111,754,310,509,908,865,478,422,924,147,32,972,500,125,921,4,316,624,452,246,758,650,335,626,62,874,638,383,431,294,921,770,42,847,888,671,803,278,369,860,71,564,66,486,475,521,128,244,885,968,408,640,151,289,701,538,279,240,321,162,299,885,463,531,15,526,177,68,716,360,732,973,439,983,834,170,723,867,393,854,214,457,716,798,612,652,850,77,788,637,491,319,384,116,18,676,629,595,593,250,522,718,163,286,571,473,56,620,585,971,354,289,512,12,305,195,335,453,364,596,245,457,302,82,460,431,934,528,877,306,748,623,659,539,666,59,824,763,777,938,878,120,328,665,24,810,2,561,272,881,872,428,72,337,142,618,862,985,496,423,978,608,939,409,487,23,795,355,276,362,723,15,850,255,542,56,437,189,726,627,923,914,974,286,87,31,426,927,741,806,211,124,533,95,598,443,149,129,114,739,246,224,305,406,194,2,172,652,393,464,64,437,338,413,289,377,139,197,743,171,882,945,427,231,988,564,813,799,465,899,273,158,747,986,216,819,694,645,889,929,824,886,142,84,387,280,598,964,265,234,963,557,202,815,83,165,598,292,294,433,61,844,661,773,793,264,255,160,858,950,534,128,965,120,298,963,102,797,518,144,654,60,805,673,335,545,448,46,471,51,466,230,741,3,322,812,569,611,929,63,157,263,550,522,542,545,149,598,108,827,186,557,347,322,860,98,609,528,365,178,30,322,574,652,795,753,384,925,985,888,215,388,223,794,838,220,585,502,916,363,590,14,836,551,863,722,695,710,383,255,600,217,833,532,449,82,507,658,237,396,134,148,31,433,109,947,251,629,558,521,94,219,331,157,516,269,165,288,473,811,235,363,567,585,359,401,814,596,168,523,898,725,350,410,293,289,837,864,583,383,265,448,368,65,861,76,967,247,219,668,355,371,987,504,871,813,302,584,317,635,358,211,641,303,986,315,789,34,517,855,963,746,511,353,805,838,518,453,790,63,556,667,414,193,533,143,942,825,595,618,763,545,945,968,829,391,145,298,173,545,896,159,124,595,914,294,624,924,681,81,686,842,943,88,552,822,329,786,750,141,759,974,925,89,871,611,113,437,184,841,357,210,653,193,439,392,920,357,681,199,821,528,917,393,206,151,329,812,115,315,999,476,186,710,397,651,660,659,274,859,590,463,808,439,372,736,966,763,365,410,199,988,955,321,860,682,599,825,65,136,671,519,165,485,621,847,639,302,432,338,909,922,232,919,677,157,976,450,266,81,841,881,674,138,231,952,498,498,230,129,782,988,900,212,429,884,24,844,595,824,499,282,131,288,932,862,57,972,297,955,760,240,802,635,381,35,919,772,846,543,482,231,463,167,710,394,937,630,754,764,58,421,395,519,431,630,486,116,342,138,149,676,423,382,892,330,803,10,572,343,107,532,422,749,790,832,94,116,77,241,817,795,975,778,937,518,676,265,335,515,749,302,950,978,983,743,375,416,338,209,565,287,877,943,179,463,488,799,649,489,520,61,31,180,784,725,333,676,611,399,414,514,859,327,420,232,26,58,306,766,186,984,43,905,495,514,249,821,749,645,278,801,995,840,243,592,92,293,122,674,651,697,837,823,355,835,424,594,767,996,562,284,79,75,706,816,98,123,355,79,527,758,413,73,129,660,860,982,820,994,914,950,163,334,207,824,740,508,190,465,962,700,465,829,229,453,709,691,553,793,648,611,611,321,426,850,315,413,665,356,11,756,676,796,958,275,327,207,614,541,746,66,663,297,953,276,891,363,646,832,394,819,109,527,248,261,549,788,786,136,194,748,185,19,804,550,25,342,650,726,149,209,4,67,69,653,518,117,606,44,174,676,867,982,149,602,200,276,799,910,429,315,659,380,11,278,53,140,457,556,342,442,60,565,311,922,115,115,737,937,647,804,45,581,840,349,93,653,642,276,732,19,388,535,116,60,557,909,681,330,381,748,662,252,814,272,654,778,246,821,773,129,772,576,768,701,739,284,32,968,217,452,519,293,490,520,559,185", + "191,519,795,659,222,373,735,888,546,824,876,764,439,674,432,883,949,383,112,215,799,622,893,879,835,973,396,627,218,511,123,549,334,762,427,525,673,4,939,675,367,562,465,395,719,343,766,548,536,309,932,135,439,511,527,858,508,14,811,398,928,229,970,6,745,215,274,941,529,459,488,3,902,826,379,485,361,859,518,965,853,436,692,413,727,275,194,455,670,991,742,466,34,953,353,836,843,710,701,0,887,566,273,185,811,311,502,841,5,179,459,929,203,991,358,869,573,671,895,684,340,257,896,774,637,763,547,976,338,595,170,57,361,675,483,656,285,832,96,447,108,508,330,842,886,127,545,189,28,556,849,834,54,187,523,197,317,646,372,562,675,865,928,556,921,188,57,966,153,708,346,127,813,633,553,509,629,714,302,690,133,453,786,485,727,61,968,312,846,286,250,838,455,214,982,757,423,473,199,714,51,998,635,266,891,831,237,280,247,572,156,32,459,647,700,987,739,456,256,503,478,848,44,297,138,747,64,268,450,161,549,898,643,245,759,946,252,360,479,894,729,875,782,835,392,124,628,776,405,435,413,236,120,230,288,101,537,51,103,519,240,360,841,914,513,910,535,790,484,322,441,708,537,81,595,123,491,414,878,429,802,447,281,792,39,674,159,460,3,350,817,689,180,751,795,411,8,364,470,8,93,318,64,443,235,650,545,168,311,983,113,762,335,388,905,746,929,93,528,129,907,100,698,669,417,314,70,839,429,503,926,423,879,803,302,506,440,966,330,572,892,498,756,435,42,831,389,47,963,304,320,284,343,966,219,311,409,628,184,253,832,368,92,354,197,43,439,262,616,350,896,865,220,133,971,307,497,771,946,909,737,755,58,299,380,580,822,656,917,885,974,263,699,662,407,292,539,824,245,736,623,25,33,592,789,394,326,160,151,214,879,546,49,60,459,573,40,252,934,493,887,190,942,698,809,620,686,767,926,274,134,862,178,308,940,767,633,839,366,828,602,92,60,406,241,551,4,401,199,760,341,735,405,739,314,96,8,307,835,193,76,805,231,266,953,54,947,888,758,100,37,282,149,220,978,557,256,828,176,41,659,294,397,907,654,791,340,531,392,567,283,977,276,758,70,672,543,218,590,9,899,433,576,367,948,303,585,92,126,91,700,461,698,114,994,11,760,171,428,575,605,148,597,123,218,518,225,277,694,958,650,977,45,470,709,812,411,772,413,420,673,864,308,366,389,171,200,214,441,314,218,626,376,433,733,217,933,729,978,835,593,36,955,583,8,420,808,712,404,793,504,209,420,617,406,848,958,441,793,616,319,343,789,287,542,59,554,287,336,370,892,234,848,67,848,335,297,166,781,232,801,991,992,491,547,660,132,352,3,108,304,341,943,72,242,980,908,733,289,642,108,462,83,272,140,145,433,164,407,839,12,389,659,942,269,972,439,5,685,81,666,936,864,596,775,710,819,418,332,396,255,338,561,480,244,932,464,372,67,819,17,945,727,810,254,475,640,280,761,672,134,885,718,339,439,142,629,964,512,25,887,415,303,650,366,807,368,19,752,903,195,461,107,799,559,6,51,450,377,104,395,858,465,633,239,33,369,274,235,58,676,375,798,370,768,654,562,633,29,742,475,311,386,580,943,711,665,363,103,560,104,149,495,591,951,499,982,370,883,914,602,644,810,954,80,905,65,480,197,826,579,181,654,611,485,621,308,352,862,272,258,864,55,977,274,128,112,943,59,246,142,312,264,21,876,618,63,102,799,976,206,189,663,673,624,973,939,926,251,869,759,493,796,248,577,90,508,60,909,453,462,212,927,385,801,66,701,515,767,361,34,232,568,35,615,284,654,94,979,872,93,556,45,939,489,163,708,375,649,941,74,943,491,258,14,171,976,398,736,872,238,25,3,569,74,429,34,262,45,552,403,453,386,383,819,95,863,336,250,599,957,513,41,486,633,73,877,949,53,926,160,137,138,698,568,608,697,557,712,44,933,303,618,366,765,553,561,589,798,569,326,923,607,53,410,684,526,20,221,908,282,893,412,779,187,38,605,657,945,403,286,760,766,536,623,708,1,733,644,222,575,912,149,837,990,251,486,167,135,301,105,782,267,898,446,323,526,790,92,52,521,294,33,785,116,120,380,611,798,51,170,168,617,632,180,607,57,45,978,593,482,774,200,605,195,326,484,349,372,962,766,61,464,432,55,230,570,109,701,900,967,283,941,943,125,860,837,263,521,993,607,435,740,84,949,421,533,160,3,906", + "825,293,396,377,319,819,438,208,216,107,400,376,223,887,162,621,367,315,30,677,404,179,894,995,176,781,849,720,315,532,737,523,815,200,46,221,532,709,392,609,958,90,173,473,73,149,965,419,140,10,391,844,222,181,334,635,76,338,128,151,603,902,913,163,93,817,845,532,216,408,979,471,417,740,366,480,149,969,587,983,38,892,966,591,585,133,655,742,650,432,513,187,605,220,616,718,570,382,224,887,0,245,334,398,718,57,632,534,465,827,989,513,226,895,73,893,204,347,983,826,904,208,302,533,745,66,746,527,775,389,528,165,771,138,303,675,645,250,78,221,562,589,736,308,638,481,326,481,880,198,630,994,112,894,678,224,487,911,104,18,159,890,945,498,76,76,432,317,151,962,87,964,171,232,860,800,687,972,844,721,31,581,471,42,103,836,728,755,537,921,975,1,52,30,338,672,437,995,724,848,734,387,209,460,214,640,339,985,673,378,311,316,929,981,2,438,978,851,732,285,609,365,287,889,807,132,114,178,623,246,447,572,867,78,26,866,946,383,751,998,419,752,911,244,668,105,659,371,690,186,453,782,406,552,160,174,551,205,710,192,61,974,565,579,551,166,550,957,904,3,424,237,135,93,823,425,535,409,789,443,887,306,424,402,376,348,866,827,774,930,84,854,506,90,435,148,309,695,663,571,266,867,81,388,801,131,32,577,442,960,606,521,723,958,416,706,361,768,100,591,206,113,319,578,811,507,663,818,16,714,393,571,645,764,498,392,919,535,697,672,163,242,946,657,526,871,838,184,636,898,218,81,446,956,897,443,160,711,280,197,526,834,166,748,903,628,94,361,260,34,342,113,172,238,422,87,755,300,328,843,566,947,407,928,551,827,849,596,430,590,439,718,449,771,482,724,677,391,453,2,835,857,319,995,193,554,829,95,165,296,968,102,192,521,421,666,229,228,290,654,768,604,148,982,723,140,108,297,541,465,45,382,147,992,327,155,637,485,743,64,814,895,925,150,840,165,836,206,404,31,743,289,768,667,946,473,317,687,247,49,588,366,882,347,185,155,886,366,930,417,631,424,185,240,886,449,704,957,218,844,204,63,765,398,548,892,111,161,935,629,740,806,125,136,513,878,758,409,17,622,829,348,792,247,584,281,235,595,117,615,107,553,315,193,920,363,232,815,463,493,954,485,775,102,575,884,158,938,666,820,308,697,380,193,842,384,286,37,753,449,443,718,312,948,377,172,155,139,810,87,439,527,760,562,739,22,303,444,635,622,560,885,120,648,547,342,413,164,678,877,644,598,658,668,29,673,418,820,952,400,434,272,430,98,649,607,875,218,69,855,352,212,669,411,339,170,237,690,454,320,939,281,954,854,456,200,506,139,696,964,841,294,324,328,392,939,474,521,394,448,32,883,783,943,103,863,186,788,94,392,172,265,556,98,73,901,860,607,745,23,284,573,13,36,551,252,707,881,947,7,591,988,98,280,235,757,886,975,825,137,273,311,900,245,519,704,443,162,377,157,336,484,831,558,429,38,572,217,99,52,848,893,112,190,57,597,718,97,26,216,428,147,900,468,108,283,727,250,854,138,949,301,309,833,863,251,58,522,616,673,53,891,14,245,814,839,63,338,335,910,890,862,112,357,622,106,565,225,291,888,593,905,290,739,848,455,635,140,971,235,7,382,87,504,815,643,141,986,428,198,979,351,607,307,687,798,463,988,273,236,383,365,356,18,778,252,886,493,470,914,65,498,928,177,67,875,625,767,222,122,739,505,650,86,706,527,715,52,531,36,449,9,350,822,923,834,609,490,358,924,514,231,446,594,998,388,550,495,844,347,2,667,631,379,901,974,747,721,873,809,427,693,639,379,196,160,430,378,770,624,285,576,850,270,113,497,91,881,394,542,456,544,28,719,84,669,600,300,50,263,10,567,966,855,640,692,95,867,791,206,339,575,408,235,580,808,13,277,1,314,612,178,658,873,659,588,554,492,467,292,763,719,567,115,955,853,99,21,927,259,642,749,781,996,91,548,276,662,668,375,625,298,500,886,608,964,97,772,462,478,39,557,47,533,584,780,330,704,264,24,492,516,884,450,787,437,979,531,957,894,794,887,616,498,52,309,865,275,25,905,812,911,740,917,180,106,275,222,110,399,538,276,675,321,741,516,697,88,970,395,19,582,421,699,384,989,448,55,889,517,616,607,595,466,600,363,439,985,231,444,820,415,821,929,139,158,824,873,407,613,741,630,60,494,246,543,941,914,860,451", + "342,758,418,26,153,114,782,809,551,364,435,26,254,262,751,429,617,442,34,180,973,331,585,452,517,739,486,259,589,816,548,545,969,813,8,683,525,793,996,74,414,971,35,318,115,465,673,242,26,575,724,952,138,689,931,320,220,577,758,192,740,333,312,365,86,33,682,383,379,419,680,55,755,211,136,953,379,191,324,741,515,602,259,524,487,422,887,425,808,986,151,17,814,763,31,50,583,712,422,566,245,0,628,271,783,867,605,919,650,657,864,802,711,26,893,945,559,916,630,417,38,274,383,66,553,423,42,539,797,358,469,925,916,277,836,211,18,594,763,712,610,146,809,388,316,668,204,839,915,125,365,38,128,978,923,192,812,787,564,543,994,745,706,643,946,682,417,757,437,659,301,8,996,602,776,655,536,414,329,18,69,215,876,64,284,75,325,177,848,563,657,642,476,742,187,454,324,547,687,589,990,996,501,490,591,676,294,143,53,162,838,967,837,33,855,650,83,648,760,457,944,564,539,175,116,243,419,756,706,17,859,706,473,764,112,580,456,131,150,616,884,613,998,580,111,589,348,866,768,476,792,166,352,949,886,49,947,991,404,49,460,494,973,982,79,332,612,523,812,215,324,937,393,466,293,958,235,842,207,572,28,227,784,2,640,13,468,66,942,786,885,933,682,506,868,126,371,739,578,439,947,828,887,802,80,733,754,20,590,790,177,484,64,643,923,401,741,220,806,558,23,589,358,227,788,150,292,887,572,665,964,577,255,311,603,413,953,644,509,355,548,203,136,289,457,680,545,652,581,346,428,210,846,878,940,457,76,866,820,84,731,696,259,871,602,155,498,981,578,524,195,676,15,912,295,970,826,409,936,152,975,285,808,477,466,93,157,634,619,44,87,421,15,916,746,383,604,414,301,333,394,354,346,311,404,268,564,638,751,141,226,672,688,790,298,426,720,861,594,698,134,250,550,157,735,850,309,807,805,75,916,999,804,907,184,602,340,331,388,40,29,587,325,121,501,431,117,927,426,777,494,746,913,596,190,749,267,658,547,483,696,912,477,821,982,280,578,857,321,239,503,885,651,336,453,847,877,49,816,333,653,111,887,985,874,368,51,344,448,978,490,970,296,260,568,733,88,719,428,614,1000,746,873,878,285,270,408,51,221,111,27,11,657,171,906,940,104,882,302,743,622,255,556,215,108,750,963,358,117,909,515,669,210,796,167,390,792,394,316,568,785,803,6,307,248,474,272,942,322,134,914,204,159,752,903,16,177,842,991,249,436,888,614,175,126,675,430,970,265,895,152,519,802,373,703,484,585,465,171,674,350,798,892,846,241,663,963,241,549,279,715,886,474,670,471,680,795,309,996,518,643,498,73,287,709,935,308,780,663,727,426,248,294,100,193,316,735,354,573,465,334,902,44,836,238,255,576,306,430,306,499,565,531,545,134,417,71,474,23,264,191,345,439,212,762,47,753,530,619,94,767,367,82,332,453,339,148,686,544,969,647,499,907,382,642,756,16,63,957,371,685,988,202,990,961,815,798,407,489,646,601,154,667,757,499,697,70,208,731,749,297,981,999,597,642,409,203,995,270,988,840,210,953,199,620,710,430,755,554,530,478,980,970,871,747,522,494,302,190,49,126,12,9,351,670,755,205,309,428,248,712,168,789,713,11,928,506,878,108,288,786,241,504,897,453,304,944,15,829,513,979,845,478,102,196,966,634,725,433,400,651,175,225,696,795,437,40,30,246,811,602,214,831,482,35,605,889,701,535,283,683,668,388,252,796,651,712,744,733,829,15,777,725,206,217,646,873,678,372,289,64,573,763,667,296,616,334,141,431,484,166,292,417,964,460,353,262,59,668,500,258,976,30,209,189,62,743,912,551,966,543,398,133,866,710,444,691,767,358,3,923,790,242,987,571,839,801,11,684,229,291,878,577,396,774,976,66,29,368,323,571,208,484,514,579,70,102,336,515,15,938,699,944,464,305,999,314,327,114,676,373,429,158,159,554,691,680,731,422,214,245,874,346,223,770,636,955,419,300,362,695,312,943,168,487,576,796,730,967,440,528,356,840,233,285,282,532,586,627,385,838,5,998,71,276,656,403,248,91,257,503,695,495,765,777,537,197,487,829,608,104,494,391,947,343,74,251,568,24,285,693,498,77,415,681,189,494,13,850,5,548,292,302,359,792,613,229,110,327,350,651,374,393,520,251,775,86,56,635,273,188,257,952,308,265,876,33,793,625,639,40,321,629,703,280,934,70,448,360,254", + "578,992,483,517,584,983,840,105,185,957,56,326,44,776,708,297,394,239,631,299,124,414,961,956,84,187,533,522,757,238,957,32,537,694,926,254,582,475,894,208,627,393,596,27,525,147,34,148,562,299,911,158,98,100,775,913,603,801,878,917,311,837,195,546,155,532,987,606,314,979,364,162,571,968,133,299,323,795,852,979,587,229,992,910,127,436,828,387,663,946,798,448,358,356,760,584,560,174,111,273,334,628,0,656,370,912,110,602,245,666,524,459,77,584,709,706,490,438,358,742,16,448,74,761,258,206,455,809,448,598,238,507,77,449,669,782,821,656,921,4,755,428,39,522,764,223,78,822,880,237,124,668,38,97,296,968,227,650,204,664,387,897,858,141,979,528,205,685,112,117,119,669,321,97,803,322,38,852,70,416,308,79,750,280,293,782,74,622,147,425,495,133,488,894,325,209,785,185,803,331,781,535,336,19,4,449,567,711,913,370,210,913,32,811,756,141,83,346,158,342,294,914,565,822,877,226,230,511,876,716,641,444,375,603,418,419,333,368,520,930,898,127,586,345,178,27,912,561,297,686,572,31,23,872,887,906,56,463,813,145,978,815,41,268,966,660,821,362,305,659,780,887,922,346,799,929,136,919,759,902,211,947,651,190,797,416,58,111,315,490,138,531,849,788,705,409,677,894,315,815,919,68,485,6,981,22,394,963,835,896,738,36,247,387,784,684,819,541,9,779,255,287,903,913,19,23,39,537,676,160,801,774,362,780,856,29,513,759,11,661,890,696,23,630,688,438,419,347,143,429,445,19,915,28,83,417,657,636,518,829,226,592,397,588,240,442,941,76,508,316,739,501,743,697,451,13,146,837,430,724,796,243,134,776,387,74,419,180,204,526,941,522,931,351,100,404,597,126,738,708,549,880,421,402,515,30,261,279,407,876,740,626,333,805,771,776,184,409,638,463,729,167,469,154,245,622,228,561,519,766,972,71,392,867,713,925,83,44,922,993,365,735,91,446,408,2,711,860,923,38,803,215,126,387,369,516,696,26,728,868,728,550,173,589,816,938,448,832,767,606,641,415,679,449,9,204,579,600,886,56,126,816,416,549,187,526,743,564,370,99,439,724,954,746,593,170,400,441,915,354,603,624,885,63,459,445,57,96,615,580,743,487,970,528,690,729,158,844,772,415,314,391,987,477,240,812,882,611,450,659,936,290,512,32,794,100,547,268,309,744,693,606,226,694,60,699,117,229,648,538,260,519,622,316,265,431,752,486,115,650,889,929,7,136,606,137,37,163,612,524,309,756,457,805,108,877,478,379,920,187,320,909,812,210,794,849,814,911,869,949,645,766,538,880,694,741,272,530,414,798,288,965,987,124,912,555,237,310,880,228,711,544,740,245,498,668,70,985,872,100,749,681,780,653,670,734,303,354,993,937,135,853,12,23,161,326,754,790,554,465,775,832,692,899,733,80,459,70,438,962,26,106,291,75,202,315,379,397,703,375,806,124,586,365,312,256,853,378,300,982,599,507,205,441,851,270,263,313,749,70,837,297,539,208,363,714,115,974,224,864,848,863,980,941,668,514,524,836,134,656,785,584,867,691,468,353,924,697,877,990,821,465,595,907,955,131,984,26,382,418,352,550,146,296,953,354,947,894,994,626,595,41,164,240,297,612,488,804,326,119,461,457,789,500,302,321,727,528,436,725,906,130,485,556,629,680,630,143,578,782,148,800,430,328,989,514,596,90,371,635,10,502,795,508,90,385,520,569,802,832,887,516,124,645,151,383,528,887,854,289,866,302,322,557,73,619,313,315,17,197,522,343,760,261,303,292,64,621,461,792,872,786,67,6,302,491,951,77,321,94,384,361,141,214,99,773,104,887,801,699,115,636,304,171,759,451,568,255,214,743,429,816,719,421,680,693,64,376,901,804,328,225,910,213,133,989,242,76,648,153,233,86,122,789,844,46,447,40,360,185,881,437,773,454,304,549,862,756,359,242,359,112,615,495,361,39,810,139,25,616,643,459,546,813,151,394,119,210,4,285,920,643,372,703,359,321,852,124,427,200,38,91,470,798,377,508,691,456,599,388,478,392,219,250,694,846,407,43,67,587,860,156,155,173,710,783,191,789,428,598,683,130,836,872,444,737,931,956,573,510,756,452,683,866,673,621,473,911,404,141,238,979,379,434,240,902,732,855,278,326,479,188,613,994,519,807,636,680,414,211,914,45,255,335,361,669,572,287,403,528,449,87,625,81,78,230,24,983,715,461", + "76,261,566,74,855,410,517,879,918,216,906,613,520,668,574,175,710,828,609,982,446,32,592,528,236,50,802,994,961,297,24,3,934,950,627,436,944,259,603,997,484,687,698,914,35,230,159,83,135,458,519,516,421,703,504,668,451,775,279,7,26,99,637,569,492,37,559,291,6,660,780,499,303,448,393,416,86,525,670,911,435,654,408,156,223,385,551,426,434,397,81,822,905,880,879,397,856,507,754,185,398,271,656,0,247,880,501,218,154,799,619,900,78,579,533,480,248,184,733,219,739,888,61,31,824,327,195,171,986,36,744,724,58,575,292,922,614,899,805,157,15,234,864,356,640,999,413,858,248,423,9,705,743,252,393,433,372,292,480,390,984,286,352,323,385,303,911,124,501,232,360,195,536,464,6,220,501,931,551,667,280,508,696,324,775,892,46,645,576,560,765,756,732,905,397,290,751,816,885,887,312,107,377,903,624,31,480,928,209,470,366,342,723,655,838,594,733,516,763,554,528,671,992,91,290,23,34,826,701,804,912,353,999,905,117,644,524,664,977,451,362,918,583,336,486,159,276,907,721,564,313,810,876,129,757,270,743,46,8,732,876,220,820,796,70,960,204,720,394,904,389,573,645,180,201,609,725,316,836,317,605,615,235,562,482,212,556,494,162,163,614,998,235,393,952,836,427,62,193,436,827,220,486,548,534,205,517,288,598,466,522,894,522,731,510,855,693,405,901,954,625,2,751,911,204,493,606,178,134,645,799,44,848,5,498,575,664,157,554,875,765,144,633,611,251,2,503,431,506,263,210,81,43,214,364,183,51,473,505,478,260,395,926,75,458,67,267,410,167,692,242,94,464,109,596,762,982,683,903,75,810,471,879,291,487,767,252,950,856,730,679,184,810,399,49,76,539,701,31,585,426,461,187,438,100,627,280,361,970,989,875,119,835,733,65,52,980,693,793,415,654,151,390,842,381,739,993,751,624,705,23,154,888,243,800,866,406,410,878,100,896,589,558,376,340,276,627,687,573,903,199,569,398,165,192,550,941,452,974,324,517,663,978,120,939,907,455,493,97,515,801,236,474,5,773,985,57,726,934,490,460,994,568,735,580,607,835,752,338,303,961,658,726,665,564,807,875,23,269,181,275,692,34,240,76,459,158,951,461,495,781,380,585,879,62,507,988,28,996,2,167,346,575,469,688,756,825,150,158,398,996,228,263,94,341,904,252,884,251,885,64,501,937,89,553,591,87,247,821,260,29,308,198,961,232,756,992,636,428,626,358,511,551,876,846,661,654,902,903,396,948,13,143,290,395,141,44,23,740,769,632,381,634,789,917,709,390,477,917,134,471,196,948,475,290,117,216,58,195,483,51,886,642,108,869,308,777,338,865,20,928,513,178,112,910,169,579,434,703,412,27,480,51,157,900,475,711,934,957,417,622,181,515,288,149,300,599,195,251,501,41,728,918,866,159,732,411,759,236,347,199,678,824,138,296,529,691,900,20,934,269,903,622,670,98,720,9,64,725,223,830,350,531,774,122,988,395,369,895,21,505,712,737,154,552,16,190,834,196,842,41,823,262,29,607,371,908,590,899,990,518,118,45,847,85,668,686,692,272,224,912,120,984,341,258,190,94,225,844,330,986,836,548,33,681,595,723,798,975,50,326,750,494,667,70,106,712,652,600,966,5,719,895,983,164,662,894,158,602,202,140,648,989,761,319,343,178,26,659,521,824,182,65,279,53,681,873,471,171,236,369,762,376,436,494,131,611,257,234,27,505,137,592,814,322,579,675,270,656,206,340,47,111,849,226,571,305,474,512,655,142,643,807,959,225,196,633,600,443,729,26,46,938,688,288,212,356,147,396,268,281,271,501,486,828,437,864,457,485,244,304,569,914,404,355,991,183,888,836,531,662,923,759,746,254,676,324,963,643,784,695,359,113,501,77,209,167,371,986,409,871,781,411,2,175,339,130,517,84,963,703,157,180,491,549,409,94,580,812,132,671,395,988,871,626,55,988,495,414,437,841,445,839,575,644,512,548,285,435,749,809,220,744,268,131,32,849,733,655,280,387,33,794,42,998,403,431,707,258,379,502,881,331,708,961,146,82,708,275,700,561,796,538,264,208,64,452,704,845,950,259,7,286,892,837,2,237,304,625,868,560,370,589,650,389,648,825,314,844,601,34,325,501,837,812,973,783,912,635,821,736,138,426,516,241,138,988,111,46,361,386,621,155,633,566,229,484,735,145,515,117,731,963,632,471,778,996,454,124,770", + "394,587,132,503,512,313,151,722,485,205,480,405,883,872,481,171,982,341,949,127,955,683,173,23,831,40,608,337,663,570,705,669,528,52,366,348,376,993,942,359,431,743,308,783,488,414,145,378,169,834,703,993,19,894,897,439,277,119,608,480,8,49,18,448,143,221,160,487,458,413,938,440,878,444,253,368,927,180,353,725,154,510,547,244,634,586,279,912,194,83,984,359,154,847,525,145,498,466,310,811,718,783,370,247,0,358,576,342,814,284,213,550,526,175,346,721,353,374,409,547,745,739,311,236,698,452,747,342,375,839,784,641,273,962,571,227,806,289,310,843,518,43,846,195,536,71,787,324,116,796,371,997,633,600,17,144,202,388,28,792,313,324,883,38,389,882,215,398,309,755,575,454,811,739,893,866,504,658,804,839,625,98,62,216,899,343,972,384,791,929,723,87,261,489,20,452,867,368,209,78,966,307,561,325,189,441,37,995,445,582,856,476,82,111,837,890,802,74,740,635,684,951,416,662,993,334,74,840,902,507,462,579,396,107,302,259,646,614,657,444,131,473,253,914,902,710,224,575,198,150,103,802,872,843,73,124,647,83,404,813,948,235,151,455,607,509,693,532,263,348,696,877,339,757,861,276,639,966,55,829,326,381,10,320,638,735,710,300,192,129,774,32,929,46,882,379,916,232,115,681,339,795,833,604,641,291,18,715,40,86,664,180,791,361,933,700,478,631,399,935,339,300,326,394,6,418,316,655,660,757,13,321,450,258,828,748,68,494,473,682,110,344,469,700,375,609,10,669,686,956,849,939,765,202,171,68,856,776,904,717,114,482,473,43,351,411,640,775,993,250,42,655,636,628,691,928,904,895,903,584,255,766,131,671,899,776,84,450,183,951,980,514,240,42,10,958,978,507,905,319,280,20,189,838,63,523,594,44,923,30,277,363,787,751,903,39,946,638,262,83,218,243,624,466,56,308,678,885,593,96,455,52,146,342,700,617,287,300,930,890,490,847,236,352,150,368,558,74,592,132,945,326,41,642,206,19,864,932,987,321,558,315,143,558,724,267,567,70,31,829,710,144,341,198,954,947,471,231,232,956,740,514,772,962,297,226,637,828,877,475,790,871,697,850,912,445,522,994,164,746,389,593,185,660,9,568,268,934,67,207,468,895,36,141,502,796,287,515,986,538,995,127,754,110,561,793,624,304,47,893,725,755,9,254,925,585,113,480,486,550,629,587,516,963,113,900,73,638,303,802,148,945,599,770,681,809,808,139,650,454,984,476,214,353,8,689,515,436,991,386,716,483,783,508,627,621,734,949,651,202,337,299,83,816,881,440,339,839,884,384,85,712,695,249,975,867,889,346,550,652,517,141,850,228,446,407,936,966,4,363,97,39,810,780,763,996,371,281,757,248,813,67,835,216,572,801,288,148,201,910,397,38,926,555,831,69,183,394,17,817,933,654,239,768,748,559,701,622,4,583,753,449,685,480,854,608,47,396,115,569,933,336,646,604,465,1,659,266,788,866,114,278,552,96,251,49,72,250,266,115,819,377,477,985,426,796,643,457,171,481,778,678,220,631,845,48,469,908,388,943,858,770,673,983,27,373,761,281,708,413,457,408,43,57,718,668,906,829,913,773,647,625,196,276,83,119,492,267,867,339,82,943,681,766,174,126,205,480,572,623,942,495,954,249,143,316,933,959,109,59,684,687,760,950,80,25,468,614,156,954,31,434,722,129,465,654,571,489,470,266,197,86,686,233,903,793,146,863,903,633,298,901,465,693,534,948,396,215,789,209,840,337,287,884,319,981,827,711,251,252,866,839,661,994,983,808,578,555,615,538,934,684,129,294,490,545,96,567,40,890,950,897,669,7,430,476,734,749,674,124,722,663,583,873,757,479,50,889,901,112,761,339,497,7,551,825,345,155,326,933,535,693,936,13,653,208,244,540,319,202,670,455,843,646,68,930,661,485,202,741,599,586,293,569,232,311,266,579,363,885,628,118,858,245,512,812,354,496,707,915,164,504,156,507,823,780,768,221,148,646,905,699,147,337,564,186,299,409,959,781,164,722,135,226,123,19,898,420,659,468,4,953,808,699,422,83,109,922,14,847,216,838,571,550,186,576,146,717,876,712,533,767,369,598,524,977,140,313,104,144,77,749,745,479,333,876,468,665,846,345,985,219,613,388,683,61,240,407,940,816,991,494,722,481,989,544,395,451,787,673,939,433,53,546,454,693,733,236,219,684,964,216,17,164,251,934,798,947,93,778", + "432,366,985,784,917,752,305,693,259,78,543,70,533,272,253,239,566,228,101,552,614,795,370,778,126,589,827,159,875,455,750,157,28,199,462,60,463,442,959,620,462,951,651,912,511,359,681,378,18,823,768,183,816,812,339,904,358,537,676,743,40,565,156,195,117,738,779,676,323,225,197,221,680,726,757,411,564,886,690,443,407,833,162,18,205,533,622,666,448,839,197,638,120,695,329,27,383,271,509,311,57,867,912,880,358,0,625,924,453,69,537,112,830,548,136,943,863,861,137,928,831,670,682,316,251,846,960,979,189,62,819,128,884,245,504,513,567,650,247,472,928,457,308,738,210,954,374,449,792,616,253,658,538,550,129,998,659,648,9,547,537,931,590,296,732,4,536,922,37,919,791,348,481,449,16,695,73,257,94,72,439,376,506,370,277,43,789,913,658,856,853,700,897,808,513,110,618,258,315,294,563,4,441,854,726,47,802,509,856,965,786,13,195,166,245,646,453,335,646,966,884,335,427,513,45,679,937,859,178,466,270,378,262,784,780,766,460,550,107,480,211,303,712,753,830,776,174,619,192,713,678,976,617,488,200,500,312,296,133,673,215,21,795,533,814,260,776,483,395,16,888,787,619,905,345,685,380,645,304,868,206,211,47,608,995,198,270,545,390,817,113,288,921,586,252,511,737,715,354,388,407,377,701,271,214,379,580,703,676,685,534,632,39,630,715,103,113,281,155,439,222,302,228,199,967,677,328,621,931,204,445,729,148,692,311,978,938,660,232,964,795,855,465,944,410,889,989,216,779,363,463,72,427,211,871,483,62,645,163,733,639,115,2,168,764,656,820,915,608,306,195,205,352,738,275,218,24,257,181,57,964,346,768,36,957,279,406,857,57,517,549,187,991,394,76,444,921,34,402,805,729,832,132,993,401,322,279,376,166,589,431,545,794,248,529,101,619,416,107,679,330,112,586,923,117,821,351,497,383,52,388,547,287,689,785,155,815,365,345,760,525,37,662,629,782,16,43,54,589,707,468,223,16,881,539,203,873,954,437,658,778,606,772,134,998,964,936,703,468,807,491,411,840,269,613,3,341,236,679,992,414,786,720,283,514,754,656,598,134,411,80,768,90,203,175,414,11,289,512,936,887,600,451,380,567,951,840,302,616,999,18,433,150,292,197,22,733,435,755,533,283,592,764,384,227,10,198,669,678,414,672,641,372,806,438,560,949,383,851,821,94,823,986,519,694,919,776,656,604,447,806,488,865,84,754,315,968,154,736,957,372,164,552,629,157,963,181,554,966,496,126,77,416,837,150,110,538,31,491,799,335,373,769,518,152,315,619,428,174,607,447,265,922,368,107,451,821,85,162,33,269,473,309,559,940,658,830,417,724,178,448,942,326,88,737,611,224,108,284,758,242,468,991,427,191,378,668,955,100,153,347,476,80,93,258,190,423,17,445,374,275,636,297,972,806,459,51,438,721,68,819,548,359,847,933,299,914,421,452,616,694,665,773,255,946,152,571,419,790,563,233,317,776,321,122,131,705,164,337,801,358,837,232,851,818,683,65,510,368,623,793,752,340,78,128,520,972,889,316,383,191,244,367,825,171,306,698,194,211,991,840,326,655,259,282,17,754,971,834,637,118,464,458,698,690,223,594,860,445,45,361,681,477,132,375,357,292,410,819,463,202,729,476,845,884,765,211,941,245,980,738,742,974,14,514,526,490,854,682,829,513,815,596,594,109,344,874,913,175,185,565,576,917,233,468,911,664,98,152,725,713,765,437,729,903,388,808,692,774,742,761,971,753,403,200,585,749,602,27,206,957,142,305,946,960,902,806,577,263,68,649,312,991,752,856,532,39,321,848,599,663,143,75,7,20,269,109,692,435,595,799,180,353,891,67,992,945,878,820,667,422,102,668,218,516,894,574,884,615,751,378,832,375,374,244,760,699,854,956,160,679,130,595,244,982,661,145,840,592,59,710,216,19,539,364,480,93,748,121,471,844,404,975,656,434,500,993,32,769,611,401,331,164,869,433,993,700,285,17,523,619,666,516,569,54,996,685,383,142,993,638,365,100,684,162,729,582,716,454,860,432,372,957,124,179,100,94,310,499,572,131,837,514,421,472,29,83,255,230,255,475,260,755,308,572,345,720,386,838,795,386,279,55,65,638,73,769,677,692,165,276,614,801,613,992,723,827,908,504,143,637,952,96,732,685,866,386,810,570,295,588,622,129,568,14,89,684,321,668,732,723,72,87,941,215,638,835,191,846,253", + "786,154,566,953,630,402,449,840,73,98,342,267,793,736,616,897,351,829,804,921,524,420,116,609,565,140,71,302,573,180,685,824,721,140,601,833,88,605,141,706,407,744,823,51,122,135,634,656,185,101,78,812,28,741,744,625,292,537,90,833,154,893,11,574,864,37,729,276,227,390,182,702,687,251,357,175,878,735,46,822,435,609,521,389,293,188,111,274,614,598,578,867,907,518,272,249,91,779,908,502,632,605,110,501,576,625,0,568,574,410,589,852,919,700,547,889,519,697,308,863,901,346,17,599,718,962,884,850,403,279,379,730,69,411,554,693,443,780,623,197,511,410,483,10,197,535,883,553,125,445,826,672,609,887,898,661,405,689,391,381,392,479,619,623,523,334,132,137,330,283,581,615,196,921,304,46,451,515,503,174,260,690,410,462,181,487,252,532,653,240,601,624,215,785,433,32,146,190,392,244,549,459,275,598,291,90,717,323,892,670,916,20,148,556,535,484,956,862,14,93,520,777,990,477,335,292,896,765,122,569,423,398,357,266,751,568,893,487,232,483,357,708,497,417,145,205,17,877,743,61,747,643,72,746,340,782,935,932,792,898,907,183,21,225,163,817,476,125,891,280,369,27,136,692,451,256,93,237,284,760,627,171,597,386,512,737,612,508,257,718,504,896,83,443,895,150,347,181,157,917,998,983,617,983,755,571,340,758,982,110,414,672,306,219,881,150,287,927,667,241,256,576,994,417,478,843,880,905,728,464,37,225,13,591,856,671,473,260,553,640,70,969,889,787,480,318,362,697,680,619,673,550,266,115,781,366,105,116,696,992,509,465,441,763,375,882,477,72,298,636,902,15,350,180,164,514,335,150,353,906,233,442,493,573,857,6,536,958,902,808,578,641,460,939,416,759,685,389,718,458,218,751,527,628,935,292,927,430,5,793,517,698,471,327,618,274,131,675,988,336,850,84,668,853,721,951,487,182,204,277,931,12,529,350,801,275,566,42,297,582,122,200,483,395,779,49,760,728,705,572,165,377,409,481,8,57,491,864,72,78,199,394,981,925,772,887,789,319,648,372,371,345,468,373,347,576,731,484,945,575,767,406,212,706,560,724,907,35,975,278,425,35,175,26,762,53,977,761,453,434,663,539,688,785,784,482,569,679,16,419,953,501,725,7,220,132,589,4,358,319,320,651,698,88,335,227,622,350,936,234,663,303,970,604,163,339,488,245,259,882,556,264,725,407,725,314,850,804,801,518,826,788,777,746,288,952,736,804,291,550,8,214,814,509,226,235,522,215,304,793,709,794,924,92,584,956,816,180,383,600,133,388,77,398,852,619,598,799,222,96,603,16,889,563,665,299,69,513,47,898,965,310,918,681,670,212,590,409,33,694,518,786,722,823,737,849,568,680,615,920,918,929,962,986,67,13,665,433,629,635,630,398,665,402,436,820,138,955,129,941,911,813,908,164,716,240,98,522,947,751,689,388,893,318,513,791,973,683,121,281,321,202,833,505,143,595,407,6,744,536,901,414,666,441,342,289,709,283,760,522,789,759,853,932,871,950,533,622,789,63,276,59,821,815,399,770,247,2,764,242,291,115,329,113,356,806,409,543,399,670,404,855,444,49,779,400,257,317,375,179,405,904,802,485,598,703,918,679,269,900,692,404,137,693,816,110,486,229,249,881,666,296,21,123,977,46,802,865,715,555,129,358,869,976,450,211,702,323,853,16,840,692,198,705,173,912,804,971,74,125,224,410,868,977,246,755,385,144,836,22,14,433,788,100,78,758,521,274,334,295,816,520,693,705,546,81,298,395,54,773,259,656,877,911,417,404,540,71,927,986,506,789,832,795,923,455,781,360,788,270,816,718,169,159,727,371,688,973,49,727,760,623,682,824,69,482,128,869,630,7,279,18,84,696,124,958,757,461,821,392,822,159,682,99,709,539,143,315,533,233,190,990,148,568,583,996,938,147,661,382,147,582,816,805,423,341,850,296,476,841,985,437,479,30,157,771,984,476,335,974,324,309,393,126,751,845,985,586,603,508,237,379,253,948,675,63,389,734,299,832,389,248,914,423,727,596,528,970,247,659,460,56,803,531,359,54,143,29,119,125,171,758,516,630,977,188,45,661,4,800,258,656,858,154,517,587,397,128,440,818,224,678,393,249,394,200,541,532,714,45,992,440,191,958,111,254,29,827,871,312,390,165,326,69,629,418,495,758,757,817,352,309,322,773,104,274,787,782,593,797,420,722,64,407,46,70,913,611,211,469", + "313,544,605,482,916,350,120,129,953,510,408,388,287,764,700,489,51,684,103,74,435,210,513,878,864,390,385,746,665,596,267,271,574,882,621,140,253,516,716,473,368,70,119,620,228,152,789,215,569,191,257,275,657,741,323,105,857,940,920,550,952,817,913,259,902,77,819,622,961,777,970,518,692,21,65,399,480,650,848,520,472,549,954,925,725,959,852,793,770,202,445,266,631,473,499,965,218,54,865,841,534,919,602,218,342,924,568,0,598,15,965,81,22,997,580,389,417,558,67,124,461,641,290,651,990,579,564,710,252,37,835,334,186,994,877,255,866,805,763,656,16,989,266,713,402,394,870,357,174,453,657,843,427,909,87,772,981,674,236,204,998,584,856,332,798,808,327,769,987,433,936,61,309,996,474,901,811,524,257,677,404,969,427,451,765,76,312,702,994,658,8,732,768,957,239,927,209,328,742,844,912,840,125,671,38,406,328,606,402,830,518,635,792,433,497,124,17,652,315,474,699,294,966,4,837,437,82,551,724,569,553,820,359,947,403,715,317,31,878,280,621,117,820,556,365,692,9,915,204,347,241,616,732,781,619,684,953,738,815,113,193,544,396,135,774,35,707,611,596,27,815,271,76,645,980,965,989,961,937,326,781,846,507,271,719,360,70,264,696,13,21,223,738,976,569,786,873,228,953,847,363,469,503,782,646,763,493,313,533,746,740,338,321,57,470,583,225,58,605,708,500,48,156,100,911,617,953,494,483,913,738,525,964,229,699,48,504,420,735,314,180,120,608,878,43,199,320,691,419,659,762,190,17,6,772,849,903,577,597,146,411,674,656,18,501,670,40,678,705,514,997,514,33,152,822,672,173,450,475,986,826,519,349,342,75,207,136,802,813,826,972,463,644,986,703,602,81,816,594,51,573,245,837,798,926,851,446,7,615,546,509,469,620,441,554,540,573,770,527,231,318,873,518,405,518,38,329,540,68,415,48,197,500,554,578,460,200,246,267,434,651,925,267,591,588,165,68,933,431,233,655,431,708,376,871,517,116,627,305,210,511,915,128,82,248,350,261,141,702,184,611,701,876,190,320,429,3,120,795,946,756,520,540,894,469,19,806,675,978,816,517,412,368,259,270,125,696,745,50,913,442,408,565,61,23,397,207,971,596,301,40,791,206,22,813,786,246,926,686,318,42,900,875,748,23,864,1,330,6,207,144,437,537,293,114,607,547,808,845,135,577,819,86,158,329,691,451,441,79,270,884,963,800,861,847,577,648,692,403,421,66,192,934,428,468,274,447,828,912,253,628,547,529,239,627,14,708,931,14,707,592,998,202,893,342,84,183,414,339,484,225,982,812,565,848,49,893,60,473,181,56,996,792,395,470,22,533,584,562,844,644,109,246,354,863,459,39,866,383,117,73,462,36,806,881,968,571,876,720,216,895,187,205,166,959,69,370,350,241,28,692,303,166,885,875,497,406,885,729,681,538,223,737,77,1,597,453,927,303,135,238,598,850,524,285,480,602,84,404,127,843,969,722,893,679,337,629,379,671,634,621,666,363,875,721,548,70,997,722,220,970,778,898,541,185,326,661,690,62,730,944,346,143,861,843,505,867,179,351,718,671,761,501,748,698,516,488,760,57,977,622,589,564,949,756,341,55,873,306,839,774,321,117,745,300,603,212,628,125,661,357,123,441,770,385,423,498,202,91,342,309,973,981,219,824,499,410,313,106,539,257,468,422,105,26,650,753,578,349,953,436,324,986,362,730,1000,793,656,334,770,394,767,449,291,163,100,66,423,402,839,171,254,672,674,30,876,973,724,410,972,236,760,983,712,385,251,104,946,386,538,65,471,621,947,232,210,718,586,489,654,881,124,635,159,50,221,547,848,342,235,689,292,221,707,197,609,463,744,287,852,710,905,194,123,999,501,924,779,35,81,175,815,318,742,45,388,905,710,217,659,115,211,49,786,845,444,955,23,820,386,83,746,473,12,153,799,702,562,687,794,856,96,505,216,935,642,598,125,191,689,94,876,781,55,74,241,152,971,948,453,107,70,456,464,497,701,817,440,582,171,321,809,899,747,414,174,433,975,154,947,488,695,810,950,850,496,565,364,893,30,353,367,910,738,886,772,524,579,962,732,414,382,430,725,892,563,150,648,263,78,398,856,954,324,672,666,552,271,280,892,242,474,754,465,772,114,595,289,452,302,988,272,89,215,155,836,667,351,268,767,541,217,21,436,835,816,755,485,660,591,843,155,673,105,984,103,329,54,291,419", + "693,480,837,526,484,142,631,647,402,295,906,239,467,135,446,48,430,218,980,629,668,161,706,237,898,967,471,35,556,541,550,192,947,539,455,116,161,305,709,770,129,989,288,538,764,210,656,764,721,568,926,606,449,15,703,99,580,698,35,700,387,58,15,557,479,498,155,680,113,563,670,713,678,763,324,470,839,607,904,24,945,789,46,21,464,762,340,580,258,723,393,606,663,803,416,637,213,912,478,5,465,650,245,154,814,453,574,598,0,792,176,44,491,467,855,18,726,457,887,925,242,201,502,352,386,906,612,573,908,36,801,153,136,972,815,181,934,439,757,117,692,317,935,103,719,698,475,444,413,771,597,954,511,467,308,910,461,562,915,22,354,919,72,555,158,922,453,191,417,378,32,217,812,523,151,880,72,881,200,56,44,335,491,488,40,314,406,508,730,500,152,82,992,1000,651,785,802,32,184,813,900,286,295,703,923,793,517,676,510,250,728,932,753,225,603,133,794,237,407,505,61,53,94,604,89,482,989,20,378,715,138,695,283,964,541,331,214,459,397,677,252,86,918,238,505,63,122,27,818,616,458,127,724,281,301,570,366,354,589,797,694,206,127,307,206,26,839,912,426,174,910,818,816,823,717,304,601,996,29,133,739,243,676,10,404,628,124,338,831,803,215,132,945,196,388,738,772,263,255,24,93,555,488,904,846,402,490,13,129,785,386,75,798,285,588,389,679,598,782,360,634,27,307,69,792,960,665,632,426,250,317,828,16,794,306,285,653,623,981,4,971,206,564,422,802,759,705,394,242,393,30,614,309,701,999,862,71,454,429,153,832,985,787,873,910,398,635,948,231,616,788,215,600,871,356,449,199,770,707,586,842,429,437,883,719,51,660,915,795,436,47,24,525,222,573,619,408,153,224,650,570,152,368,328,259,932,364,381,572,522,906,274,78,911,966,578,926,978,762,47,654,146,114,533,697,258,453,773,660,616,74,295,963,572,660,47,528,300,649,706,459,617,288,324,118,40,692,72,678,623,365,751,177,880,232,318,986,26,858,976,489,121,531,857,168,301,30,681,858,513,290,785,814,547,835,419,16,827,954,34,163,717,984,680,787,229,807,239,201,515,260,40,531,466,956,369,52,702,307,72,853,123,373,652,589,525,876,433,633,39,639,690,814,597,19,348,262,413,860,497,690,803,672,677,343,970,658,417,777,181,998,287,9,638,326,623,225,824,17,340,822,544,225,908,745,80,739,258,381,711,206,11,460,748,813,821,798,37,83,357,958,599,692,311,194,528,834,497,137,518,117,133,57,203,406,481,663,96,305,957,162,142,957,973,780,913,996,203,391,815,892,175,322,673,168,125,203,105,72,540,372,105,286,276,169,787,584,887,914,8,903,266,92,881,367,969,600,737,139,377,494,781,995,518,499,475,195,473,140,487,596,985,115,371,665,259,995,668,869,647,632,460,3,902,938,645,157,963,714,239,488,518,457,218,106,556,357,760,667,290,71,809,720,366,365,671,195,684,764,510,356,79,246,801,569,815,490,601,136,345,683,612,530,536,557,35,621,609,877,702,675,657,331,161,288,84,546,733,84,979,174,94,410,503,36,645,673,280,771,246,835,230,839,822,128,668,29,476,623,862,20,536,708,64,376,984,18,733,987,766,170,823,345,583,600,587,33,182,918,323,569,773,996,468,745,11,600,308,607,337,531,100,12,962,829,138,735,915,970,967,177,156,818,977,531,850,778,587,515,460,924,791,457,997,54,137,356,997,948,102,341,275,793,604,230,997,716,601,322,952,996,601,376,752,997,903,678,564,854,975,912,589,80,879,559,408,732,804,225,431,788,835,225,831,795,846,105,106,827,670,81,872,434,126,333,90,708,25,748,353,569,234,135,572,386,2,842,752,873,780,579,607,297,925,145,146,399,585,716,697,657,530,373,803,499,726,436,705,582,675,677,142,480,741,959,373,248,581,493,115,905,893,535,183,257,344,219,466,753,275,775,856,355,988,362,989,624,600,610,714,82,574,897,600,369,303,312,798,101,473,111,607,827,395,665,821,436,679,101,461,482,341,437,789,241,314,143,880,432,483,691,36,833,450,848,928,415,949,775,106,60,927,350,881,519,21,202,429,38,467,956,698,196,337,720,751,977,638,642,306,951,455,296,606,982,594,982,743,664,487,620,265,294,261,245,526,38,960,476,121,38,371,133,136,24,466,713,613,847,418,23,376,304,192,475,751,228,434,769,14,641,367,440,545,185,444,61,193,989,250", + "587,983,448,469,362,295,278,159,701,359,639,405,423,252,405,262,142,38,490,258,159,62,498,651,985,787,370,642,212,629,933,210,459,825,269,243,507,513,821,871,251,380,453,16,343,493,554,816,704,444,504,919,717,551,988,31,134,918,667,76,712,819,907,91,842,519,609,360,624,281,965,407,610,460,708,348,14,241,487,803,592,481,199,641,241,684,964,830,273,824,945,175,201,202,569,668,238,942,422,179,827,657,666,799,284,69,410,15,792,0,565,760,261,134,90,559,562,183,927,753,166,827,862,772,128,882,161,345,527,975,659,568,952,706,307,204,389,46,525,202,927,780,919,468,678,265,651,653,514,236,332,602,74,349,623,746,818,564,184,966,521,608,449,725,262,777,569,788,548,718,462,940,930,834,211,535,600,102,396,728,203,532,242,225,695,28,737,556,849,620,868,294,375,558,292,335,421,520,693,49,188,972,683,510,132,975,184,95,96,513,580,234,482,395,825,545,620,989,884,325,5,251,838,800,622,895,74,335,456,952,94,797,94,900,254,523,390,963,320,277,902,301,511,269,375,417,659,391,7,508,228,712,146,359,846,274,271,602,170,596,898,268,11,851,719,677,560,217,266,297,52,167,171,450,239,90,951,92,549,273,819,534,821,648,410,662,971,687,425,384,68,531,350,95,403,671,408,810,120,254,783,767,999,202,982,867,937,589,941,592,143,896,37,520,683,474,697,131,904,321,156,352,625,706,490,502,930,776,524,846,311,45,231,603,994,157,551,264,759,119,610,224,504,149,966,640,310,426,40,713,873,185,636,349,76,234,903,476,898,164,881,705,503,402,187,911,408,923,334,477,11,548,667,318,330,120,798,786,710,948,976,664,26,617,140,590,770,266,320,90,15,53,399,348,113,691,391,677,558,325,695,680,391,398,358,95,636,815,366,659,508,110,98,800,832,858,223,697,762,573,685,629,321,747,112,572,167,613,865,731,970,103,384,714,743,746,132,971,979,980,996,541,111,52,997,377,887,30,279,982,454,96,857,384,669,702,417,527,929,425,891,941,642,472,981,743,38,241,177,554,613,370,674,322,480,721,89,932,949,738,947,997,843,821,4,380,939,966,335,64,477,307,206,362,284,938,813,108,561,922,784,415,339,146,156,755,810,338,403,622,667,476,76,201,991,774,886,267,675,500,71,616,292,347,790,647,307,336,426,329,697,211,166,912,59,530,910,332,888,582,21,749,344,94,325,813,689,398,942,655,100,27,984,182,354,737,798,362,254,148,946,7,190,965,80,816,13,802,87,49,928,638,92,843,708,257,655,761,526,970,16,664,740,861,96,816,493,330,924,583,445,315,201,66,895,435,735,533,852,256,861,555,299,437,69,893,970,309,237,903,252,863,1,444,172,209,315,559,368,507,860,783,681,852,460,244,137,469,782,115,413,529,294,62,425,32,126,592,974,519,650,686,648,61,424,243,554,595,30,956,178,328,504,806,331,742,809,973,767,164,680,690,808,254,18,535,228,603,846,568,678,245,200,68,496,866,665,100,382,400,305,328,276,984,648,160,110,208,148,189,635,978,166,513,799,104,432,799,444,642,693,923,59,82,472,735,451,166,246,628,26,52,494,606,841,900,491,642,878,805,886,366,797,773,725,987,735,145,708,47,179,891,745,664,829,562,459,859,991,536,136,521,242,50,305,706,732,317,989,587,193,595,494,626,147,129,607,939,211,776,347,471,801,538,188,784,873,728,293,924,799,4,500,689,653,128,898,379,334,446,859,289,814,404,888,536,534,894,757,371,60,637,157,530,308,748,588,448,61,581,285,507,812,772,8,863,594,760,509,723,150,986,974,952,192,869,81,630,94,901,344,894,523,707,731,174,141,363,290,844,703,230,665,690,258,97,486,636,961,610,232,374,341,592,685,204,635,129,885,856,577,499,858,164,146,519,339,546,146,785,757,95,31,715,734,733,45,405,556,679,231,867,152,194,566,41,829,698,606,287,715,988,333,273,701,275,765,695,825,590,874,368,688,724,864,455,160,146,478,505,605,151,530,380,696,195,874,409,570,321,6,966,966,149,312,615,206,617,589,462,75,570,922,53,951,231,93,727,161,509,357,801,264,587,848,803,238,398,683,568,333,181,23,780,189,721,212,12,893,623,501,383,309,327,480,504,194,3,964,255,528,287,290,447,857,37,417,352,804,291,118,214,656,983,110,315,983,250,23,439,457,104,554,974,127,381,13,440,138,211,228,517,710,502,925,879,271,378,560,439", + "659,148,985,13,926,285,314,759,729,166,211,991,118,749,557,455,705,943,400,512,125,833,523,935,975,800,912,305,323,180,173,283,657,457,878,943,87,77,324,918,454,456,856,579,509,857,669,245,898,920,237,118,880,426,920,570,886,231,980,330,211,769,844,44,215,129,967,192,392,770,184,62,611,293,711,425,160,510,233,100,934,378,415,157,225,174,322,847,209,448,658,88,729,120,94,699,396,366,924,459,989,864,524,619,213,537,589,965,176,565,0,161,186,563,798,336,970,379,551,52,182,973,956,741,474,423,392,501,610,286,866,775,636,440,51,517,529,710,81,174,202,973,683,378,102,866,591,719,252,973,199,687,688,180,830,364,755,255,452,26,452,389,982,746,894,962,379,931,373,570,160,245,297,117,937,274,522,346,517,334,103,433,695,20,985,737,475,269,354,199,989,622,213,583,332,242,934,957,253,430,391,211,210,811,432,532,284,562,686,145,677,17,910,917,258,275,284,279,40,727,865,271,349,908,77,21,203,324,599,899,860,775,408,858,919,688,578,232,491,61,695,413,637,554,443,956,89,927,865,397,481,12,121,129,698,273,889,436,91,206,191,377,460,1000,703,483,757,605,565,9,570,367,659,787,139,582,466,604,863,987,309,999,643,622,249,4,206,269,749,620,78,958,285,434,792,142,412,692,432,211,955,817,758,898,344,310,864,137,880,19,84,501,664,735,449,523,809,178,159,948,358,375,493,118,857,99,122,63,652,375,899,693,450,201,882,532,101,461,802,21,82,204,303,855,64,976,122,336,731,244,800,433,387,658,717,8,227,110,182,343,172,36,512,101,553,163,205,752,147,560,873,166,768,506,222,215,575,990,694,546,696,890,91,409,287,413,190,925,59,337,416,926,821,153,323,904,878,193,614,88,583,859,489,5,886,775,471,226,363,609,558,919,881,860,157,366,300,154,662,626,505,693,632,672,316,513,278,840,572,774,782,856,528,621,800,282,31,404,513,292,610,427,767,37,111,18,725,75,975,20,630,211,43,81,931,537,971,907,30,324,995,930,256,123,803,13,817,993,496,635,373,939,83,845,248,574,362,629,549,954,289,610,749,847,514,433,254,774,402,648,642,36,531,461,161,451,982,205,120,774,126,815,785,329,650,989,824,321,928,983,623,756,721,122,470,671,715,151,437,94,230,401,722,914,671,433,30,71,315,909,226,265,996,107,923,549,418,557,206,234,408,753,386,870,222,494,308,850,297,88,80,673,695,318,332,575,901,693,483,688,887,717,446,617,858,289,828,889,337,326,806,485,455,854,493,655,784,284,133,268,951,46,715,848,499,281,899,401,912,134,929,106,241,862,836,491,801,783,990,707,329,249,54,298,754,529,44,538,318,548,412,864,318,256,657,651,349,819,262,322,885,5,75,261,146,411,452,573,470,136,726,91,393,25,355,862,513,377,465,637,766,402,731,874,95,655,465,801,314,838,528,910,809,475,309,660,964,63,337,896,826,631,16,113,32,381,500,726,465,496,132,331,459,894,80,538,77,150,664,402,671,647,421,802,389,220,309,403,997,760,961,575,187,697,903,349,323,957,748,381,137,144,499,850,660,380,773,756,836,647,922,405,159,528,214,726,188,989,871,402,661,827,455,228,291,836,253,826,237,69,878,984,900,622,950,490,996,125,440,105,921,726,852,283,420,13,876,202,435,798,948,976,198,945,750,2,469,549,729,936,963,892,692,642,569,923,516,151,346,697,335,788,203,817,758,259,498,779,326,581,616,17,642,603,23,743,807,662,160,248,399,493,46,487,522,982,645,689,609,445,880,88,818,425,768,452,767,106,693,947,89,399,161,550,426,948,827,434,118,360,402,25,405,511,665,166,655,258,198,20,935,140,93,117,671,378,800,922,376,460,872,585,359,543,414,285,648,557,75,38,218,145,235,431,560,327,59,418,415,200,127,695,711,82,875,886,28,328,898,701,19,247,927,482,793,828,910,203,72,512,952,833,133,302,263,220,870,797,103,126,916,305,577,214,662,257,145,80,302,586,255,252,129,561,52,302,716,578,120,61,346,534,608,903,535,37,679,567,957,21,137,652,96,540,781,213,41,65,370,623,847,370,89,958,136,167,236,698,395,828,549,898,63,328,70,124,827,530,789,386,524,478,409,708,456,664,911,926,172,890,403,547,62,423,687,753,246,279,969,217,593,173,486,901,409,514,235,167,746,138,346,684,458,756,266,141,348,154,151,777,765,195,69,297,46,369,527,32,309,573", + "55,855,334,183,942,2,880,668,299,476,571,507,227,734,269,486,697,866,985,679,840,199,688,523,186,551,284,488,736,169,285,324,232,959,474,938,681,733,813,164,698,44,318,327,211,226,349,342,581,335,979,822,445,500,807,868,291,4,345,951,645,1000,825,2,399,809,641,60,583,140,287,649,574,541,356,61,771,53,683,999,763,204,591,652,809,234,579,214,807,88,896,392,514,692,224,624,83,637,147,929,513,802,459,900,550,112,852,81,44,760,161,0,252,200,751,959,901,473,351,332,92,357,574,269,106,82,916,476,556,793,697,565,822,782,267,875,521,860,686,273,268,582,24,878,339,791,330,115,607,169,884,305,69,965,877,945,120,694,490,750,659,211,21,859,925,702,323,321,573,353,547,659,853,485,675,373,242,662,952,979,283,223,473,992,84,196,227,358,575,175,666,368,726,819,733,331,775,180,161,385,960,708,810,120,6,527,268,230,54,823,481,237,804,423,929,729,278,962,408,18,368,907,165,692,764,680,952,273,276,108,697,94,925,184,821,782,257,372,798,846,140,454,311,384,694,357,338,844,206,387,669,891,542,747,255,257,850,56,22,832,874,420,444,199,373,414,654,471,205,462,231,774,142,473,255,800,288,139,166,463,483,291,468,429,534,548,750,601,40,341,662,289,194,754,670,334,109,644,408,450,697,384,445,572,489,690,719,177,417,559,349,708,540,19,15,978,699,928,821,390,867,541,146,519,168,273,287,287,216,196,652,164,77,952,155,732,802,920,323,296,519,27,944,304,633,842,586,320,740,234,742,504,555,780,509,677,386,524,72,866,457,853,363,311,362,397,624,779,639,420,356,703,158,269,369,185,845,454,348,125,2,856,11,615,86,761,126,920,184,835,504,34,15,613,73,73,749,318,91,177,331,204,51,647,703,376,348,898,700,755,358,735,69,125,44,766,790,796,458,123,630,996,133,960,532,886,886,213,809,94,848,651,238,35,148,970,314,984,351,739,921,90,461,615,809,756,786,738,466,314,443,259,498,845,65,468,989,668,611,251,616,9,292,70,740,243,491,507,354,935,75,993,993,719,789,479,239,563,730,681,862,330,897,408,664,893,873,612,902,412,483,257,982,357,408,16,884,692,937,626,575,152,644,348,464,510,967,620,317,403,301,640,23,614,199,759,215,886,850,870,975,670,607,882,153,885,293,830,534,823,971,127,593,631,956,176,365,752,934,870,803,273,856,349,528,81,48,531,492,86,413,563,385,687,546,584,581,796,312,807,590,304,641,874,79,610,274,787,35,701,707,765,385,299,66,480,323,915,482,811,674,493,212,54,278,442,888,613,411,110,643,671,528,164,351,826,107,471,614,758,156,600,765,777,312,926,984,214,469,319,200,127,428,809,503,965,730,152,275,503,348,483,303,591,503,912,384,12,27,427,461,621,251,283,900,953,703,871,915,113,472,918,380,41,578,655,998,423,700,995,778,543,385,658,294,648,95,696,539,762,970,313,3,178,921,347,486,382,383,371,715,339,805,730,984,691,699,230,119,731,144,246,482,879,846,555,899,966,399,705,383,468,983,324,260,943,483,49,366,502,732,32,245,750,361,663,367,73,314,716,135,431,658,812,76,912,217,668,340,696,797,952,318,169,901,43,833,548,56,171,74,481,117,552,409,829,454,392,943,832,357,395,649,64,36,776,770,527,84,736,255,380,464,328,662,530,893,164,402,974,59,148,661,960,373,872,90,236,14,678,761,602,741,959,593,447,57,207,520,30,756,210,83,573,186,72,908,543,350,867,951,785,686,303,553,377,685,570,612,19,948,430,815,480,878,249,175,890,488,232,881,724,405,352,260,561,296,908,956,885,208,443,389,182,867,328,51,574,543,615,898,534,535,936,273,102,999,319,470,688,444,15,754,730,72,986,207,107,837,817,780,755,301,344,974,624,885,876,368,287,723,757,224,415,696,907,900,192,180,78,559,716,127,8,98,615,830,809,726,583,164,682,854,369,212,901,865,472,388,143,396,88,274,501,477,249,359,670,732,258,529,519,98,894,591,681,795,295,171,908,848,373,287,687,98,521,579,242,935,119,111,130,975,604,707,169,957,969,374,86,437,438,243,972,191,391,564,255,198,478,911,827,186,608,847,680,936,918,794,80,503,334,22,725,237,865,624,215,843,292,82,637,47,708,129,130,718,657,222,226,625,622,781,378,131,867,618,581,640,4,286,560,784,349,2,946,203,239,592,757,290,14,50,755,354,151,147,256,730,600", + "491,372,36,732,653,25,642,390,354,23,731,952,758,961,708,490,255,564,795,852,410,351,103,846,91,817,30,191,456,986,953,375,663,687,183,773,920,808,409,952,627,219,902,626,266,756,760,684,825,545,530,187,896,432,743,628,236,369,523,566,321,273,672,916,249,396,706,296,254,716,939,410,336,437,585,99,635,305,519,195,968,337,79,281,461,348,779,342,214,490,841,655,224,461,253,631,109,829,32,203,226,711,77,78,526,830,919,22,491,261,186,252,0,7,816,506,181,193,957,399,236,695,841,854,30,983,56,244,560,164,300,750,374,201,798,141,287,237,205,326,784,504,899,2,82,132,790,328,326,935,810,37,723,929,542,323,600,252,14,898,514,857,365,157,684,119,71,72,848,524,275,910,687,665,639,851,904,377,231,24,811,175,837,611,299,900,477,738,717,853,248,33,150,524,206,759,597,945,948,98,261,468,708,992,376,881,90,115,337,165,954,185,489,526,15,902,993,218,368,997,413,443,13,570,435,527,727,757,507,109,531,439,857,530,69,961,900,792,198,219,623,438,578,355,269,459,681,127,21,327,155,295,674,930,191,9,557,761,547,562,169,971,393,616,889,676,502,364,12,593,869,851,836,561,420,666,111,358,717,555,699,77,34,801,155,905,767,881,545,502,5,114,120,695,924,797,86,579,389,140,350,552,298,687,782,319,306,838,880,167,906,25,76,533,671,487,291,773,573,952,338,987,97,910,124,979,130,785,758,474,850,612,322,335,312,237,639,833,939,727,926,346,952,459,269,86,174,578,286,180,339,751,153,456,878,389,927,934,9,599,66,157,430,725,78,720,551,798,584,291,177,778,203,212,511,451,385,420,710,975,968,910,109,343,618,728,623,87,941,509,525,384,822,859,821,211,326,514,459,118,375,61,155,621,358,188,331,61,403,318,460,680,872,504,790,277,337,436,105,716,389,526,996,552,809,906,631,59,378,906,687,590,646,878,498,663,818,603,65,339,320,354,952,902,392,516,99,25,527,29,3,32,20,873,429,400,151,860,314,931,52,624,235,321,150,547,543,109,834,9,11,660,763,156,428,403,168,717,4,686,340,896,814,190,393,805,607,173,351,298,536,2,648,921,790,186,639,423,43,86,729,519,678,891,401,147,989,738,861,174,468,959,283,203,370,147,874,777,144,625,19,669,429,900,328,837,875,376,53,936,431,372,710,385,447,155,621,481,216,242,727,46,124,767,481,972,545,15,678,124,339,464,232,181,395,134,178,364,929,486,200,234,944,618,264,821,507,710,746,905,678,97,440,933,455,215,431,83,781,426,821,136,649,600,966,853,427,715,436,170,765,723,694,145,780,405,702,304,888,454,588,556,346,540,350,626,225,298,622,56,821,25,52,974,961,164,642,384,581,95,613,34,458,101,219,291,431,107,661,964,164,970,300,456,411,91,931,123,975,419,627,830,188,201,374,895,637,647,772,720,696,906,374,10,362,396,147,994,287,531,914,782,972,754,44,325,909,948,69,225,39,883,209,623,440,826,541,952,549,807,896,943,830,631,246,700,863,612,845,829,958,177,89,705,653,547,108,798,489,410,364,869,479,185,586,899,365,753,612,731,753,370,849,810,129,685,965,676,893,644,847,127,802,572,855,848,441,48,283,140,412,939,971,556,944,930,264,799,270,932,41,309,714,911,749,436,564,87,980,388,153,180,141,284,71,222,384,632,480,823,152,168,892,665,109,324,9,761,986,334,518,98,509,300,676,794,350,144,122,113,801,89,111,623,135,534,202,691,316,430,258,159,277,545,844,13,316,20,397,618,542,881,86,946,40,146,518,409,555,287,433,376,644,374,311,919,93,783,564,187,919,440,609,822,600,763,754,276,351,207,709,995,301,641,778,537,695,42,18,686,711,29,931,583,725,146,344,533,953,746,154,420,980,579,452,188,773,604,639,570,335,947,764,381,12,646,557,293,424,752,60,822,985,75,361,325,849,430,178,874,714,395,209,789,699,201,330,768,153,191,462,468,578,581,887,790,279,618,299,869,247,814,242,637,686,965,562,813,507,878,455,873,891,253,423,336,532,689,903,636,513,525,434,810,588,218,139,340,565,581,421,349,651,443,267,189,661,113,646,413,42,542,522,849,507,849,557,832,197,736,78,818,594,568,61,31,265,235,733,881,484,282,78,394,520,972,378,792,237,350,115,28,477,960,30,736,732,597,869,551,900,772,381,594,685,60,999,772,234,718,602,246,956,13,679,898,180,498,223,15", + "467,746,409,180,37,319,84,542,681,533,354,270,547,373,132,358,436,80,955,100,238,334,128,732,450,906,306,534,566,749,269,724,672,168,315,370,83,155,745,170,101,607,452,946,645,687,823,289,663,426,521,124,366,35,674,182,354,465,166,957,749,136,180,523,326,904,669,860,411,977,778,272,34,642,424,506,793,639,613,851,250,396,575,758,968,109,725,769,345,375,904,899,750,701,512,614,172,240,972,991,895,26,584,579,175,548,700,997,467,134,563,200,7,0,734,714,754,525,439,820,122,158,840,487,72,499,655,605,493,691,106,661,357,336,702,583,201,684,56,576,710,783,420,794,716,86,978,540,645,975,238,567,399,613,851,387,276,193,814,554,70,266,58,265,880,176,305,399,155,32,945,326,777,510,856,173,412,943,711,872,23,222,774,966,498,384,856,784,804,873,714,37,764,81,800,690,161,550,708,763,361,616,966,389,134,533,535,472,345,78,581,681,586,923,943,1,734,833,954,11,223,220,852,66,391,673,810,137,920,590,404,747,6,618,55,118,725,855,226,110,458,37,105,536,936,981,912,471,63,73,982,116,216,303,722,180,810,181,40,381,514,43,413,907,197,671,283,997,859,945,590,45,560,961,755,346,677,495,542,546,962,19,930,109,917,198,465,612,427,530,307,359,946,235,354,150,797,156,673,241,162,134,316,743,662,132,696,822,99,839,477,408,58,868,750,12,75,91,521,455,747,695,826,600,545,170,372,783,985,467,926,568,643,972,341,782,497,284,542,280,724,980,609,308,783,630,805,884,60,206,311,606,889,967,712,906,55,533,351,758,545,633,858,87,752,400,438,228,374,54,632,812,522,570,566,512,370,399,587,430,723,228,574,637,798,662,218,277,355,935,894,16,911,693,547,373,44,310,213,422,374,119,366,269,872,635,591,929,347,628,139,92,411,193,186,796,495,301,345,602,109,400,312,60,184,887,701,881,132,753,492,10,527,669,505,662,806,382,508,196,975,266,373,456,592,983,37,585,968,710,484,64,403,972,91,134,897,123,398,598,208,512,885,45,605,772,525,456,102,946,950,794,76,917,248,395,173,359,542,636,501,87,219,70,86,714,3,778,612,994,455,548,549,593,518,457,784,800,96,28,142,476,913,243,892,488,902,972,422,927,529,134,188,446,186,400,285,756,20,245,116,247,88,312,181,668,531,371,451,895,691,410,573,568,169,835,501,701,622,276,439,639,872,5,264,17,984,840,566,124,955,94,308,697,665,433,574,998,547,795,611,386,857,138,165,415,465,75,152,129,733,815,199,547,403,202,381,274,731,773,912,475,122,168,954,902,218,335,639,622,858,478,48,646,965,474,916,843,220,952,227,518,183,965,557,772,773,982,844,388,362,271,65,259,540,478,831,940,988,541,164,401,170,106,769,470,700,147,518,830,872,234,738,102,474,785,188,510,854,812,14,500,283,531,41,212,381,404,736,631,920,8,26,174,119,935,764,489,8,730,917,228,511,362,919,796,759,937,688,83,693,84,937,764,269,326,366,114,246,180,911,694,362,561,365,357,639,981,200,144,757,919,274,202,202,779,783,698,42,876,429,745,9,134,483,641,223,482,394,501,382,183,26,725,416,64,438,476,729,964,82,585,589,709,891,252,682,531,379,512,908,496,26,771,27,542,75,382,651,169,104,405,909,145,491,768,122,879,687,868,472,363,415,554,860,842,865,763,506,264,504,249,136,98,281,417,426,259,285,541,727,108,569,700,573,544,939,226,604,424,100,928,781,141,758,932,763,3,608,482,368,380,517,364,154,772,562,104,853,127,783,718,790,276,928,722,322,68,810,349,717,44,957,268,763,109,960,374,209,145,19,353,729,100,255,621,607,271,822,147,438,715,578,372,737,594,511,441,139,170,696,460,570,18,4,577,773,977,520,399,223,785,902,524,3,959,921,73,454,753,846,567,68,580,609,863,527,941,9,997,273,75,780,358,174,839,574,333,698,662,400,695,878,804,580,266,362,928,279,530,293,560,93,877,799,444,177,577,662,467,581,558,524,63,985,170,312,965,439,296,279,530,262,914,746,115,480,969,343,845,776,732,427,235,827,39,270,578,982,408,669,751,295,657,853,890,281,847,338,534,353,463,309,304,221,553,854,52,167,961,635,831,440,71,810,956,381,780,425,625,711,94,257,599,478,526,633,320,747,52,25,514,772,884,767,556,392,29,117,708,622,414,412,381,637,418,246,502,238,508,963,917,682,538,883,307,925,193,294,197", + "33,876,227,775,484,458,408,938,251,618,484,279,842,784,895,491,82,686,738,210,114,92,686,84,315,388,928,177,37,471,406,339,221,838,709,564,256,501,552,969,420,604,726,406,199,951,766,397,58,436,793,274,534,24,780,513,361,278,903,872,128,478,969,369,697,92,285,907,107,68,731,768,921,877,107,953,834,865,978,149,311,989,719,607,992,7,948,820,767,9,145,659,265,957,102,983,284,993,500,358,73,893,709,533,346,136,547,580,855,90,798,751,816,734,0,680,950,959,533,686,870,199,372,646,206,769,275,364,912,771,859,85,364,783,580,899,639,5,575,483,866,113,885,193,268,544,686,581,970,535,195,122,107,455,570,614,774,744,131,820,246,770,608,515,784,930,245,458,547,872,53,987,543,495,660,280,781,63,720,597,799,966,938,465,981,794,888,640,187,668,818,932,440,11,256,585,672,865,598,569,827,84,753,530,68,403,940,296,836,973,633,271,787,776,195,229,347,85,103,866,697,740,779,464,407,899,443,408,79,506,739,898,27,174,223,751,584,6,448,203,481,739,503,267,80,157,435,139,805,493,304,52,146,435,880,372,971,987,702,695,668,974,145,231,994,587,163,234,275,123,986,459,939,780,593,523,537,177,226,260,65,705,586,64,302,990,196,44,639,354,617,383,421,802,588,111,231,267,107,558,103,54,9,642,356,993,566,556,934,789,562,540,336,91,56,661,435,874,849,766,619,314,626,27,664,545,227,6,456,513,825,122,984,586,644,513,45,953,539,987,199,206,95,818,997,400,459,125,976,702,631,947,847,188,45,206,718,880,968,52,753,47,986,333,275,988,883,966,629,960,596,677,760,638,47,802,845,694,937,326,895,915,692,819,588,75,917,611,819,304,517,744,847,967,743,118,831,568,285,744,532,973,743,264,609,144,579,396,97,238,324,920,987,20,172,100,79,865,950,55,323,77,933,366,19,901,131,462,612,296,648,548,446,270,622,732,21,3,485,854,591,114,349,33,545,585,133,53,257,396,644,84,654,325,901,542,920,457,548,22,709,737,636,716,824,430,434,224,97,570,86,150,976,300,337,709,439,791,994,782,378,963,99,625,884,577,924,580,373,197,119,864,484,579,155,52,614,299,823,139,912,524,898,93,379,28,68,831,175,718,47,351,489,75,362,704,594,11,862,440,269,971,150,439,6,151,689,868,266,169,285,857,785,913,413,530,256,401,28,939,783,797,673,702,342,415,257,786,580,716,5,258,176,731,343,973,512,351,653,588,803,898,661,880,323,364,743,553,969,153,648,4,630,205,21,531,17,376,227,283,670,933,510,591,168,874,32,934,493,483,297,390,676,385,846,404,717,783,255,467,993,461,23,957,859,697,613,75,196,112,424,166,850,978,408,449,286,764,897,248,290,474,177,691,51,744,643,943,144,316,867,924,245,274,203,779,561,594,269,341,782,387,811,26,371,199,175,982,790,9,5,204,294,283,315,478,820,989,135,701,943,561,301,329,19,375,690,45,146,423,734,510,406,216,335,624,917,278,996,270,745,426,662,87,333,464,139,516,693,303,117,284,811,514,678,548,470,293,572,767,389,30,431,455,771,935,382,406,524,184,733,995,706,291,487,108,576,542,873,908,515,770,775,790,720,954,931,528,440,755,546,831,357,555,474,507,803,997,277,715,6,228,857,143,566,583,330,364,144,406,836,739,446,896,414,883,44,124,476,677,959,992,832,295,798,144,756,665,83,404,31,594,52,322,106,922,831,845,376,347,855,455,434,473,488,289,967,144,769,992,788,583,890,351,558,506,456,107,256,499,47,970,942,741,297,763,235,809,420,941,911,88,925,630,882,997,27,594,169,640,262,11,984,614,145,330,885,924,907,306,210,356,264,889,508,38,80,880,360,212,475,664,461,734,236,708,56,174,661,381,106,71,729,395,431,623,627,854,349,147,563,544,427,530,630,386,492,914,867,671,784,356,567,397,470,924,36,147,577,412,839,167,511,228,849,737,590,758,659,543,623,34,963,476,748,552,427,956,597,718,416,161,500,664,412,353,324,50,591,118,255,551,371,30,489,201,208,210,520,546,491,392,272,570,747,664,122,66,817,913,51,754,571,975,199,130,802,217,525,766,386,529,891,513,336,238,310,849,726,76,488,612,389,156,360,327,343,776,285,362,980,532,136,710,873,447,577,750,499,784,255,276,118,546,903,213,832,512,483,243,154,250,702,275,2,820,355,291,532,425,258,243,592,100,914,331,358,893,241,465", + "955,207,428,752,416,666,693,186,359,951,964,784,612,490,182,917,706,965,549,700,416,657,789,937,995,381,144,709,723,423,218,96,44,505,942,869,359,836,623,549,364,7,929,223,735,319,99,792,9,481,444,333,247,912,295,231,932,114,746,530,313,373,879,321,410,642,115,891,182,721,597,106,66,960,171,507,695,681,944,94,317,361,549,664,639,327,409,661,773,4,64,516,447,39,264,135,72,577,125,869,893,945,706,480,721,943,889,389,18,559,336,959,506,714,680,0,359,219,153,117,569,584,600,387,533,868,299,377,929,278,591,566,756,79,577,38,682,125,857,746,811,464,261,904,913,923,845,832,411,368,89,940,971,920,581,319,223,800,268,593,646,249,992,758,431,637,591,76,35,893,857,859,667,324,347,824,115,202,853,20,955,750,2,969,132,928,808,898,306,826,42,612,722,711,841,564,366,786,831,209,71,739,916,26,229,872,236,191,635,419,222,522,689,1,499,998,978,707,523,410,667,57,460,936,899,752,682,502,100,21,775,530,681,130,265,541,586,936,872,126,503,174,604,257,314,34,728,614,812,218,187,163,949,100,997,977,832,310,15,847,370,878,278,721,127,345,4,815,483,167,631,198,939,201,457,278,291,662,585,159,217,605,989,661,537,347,94,74,702,974,226,245,140,58,540,789,624,918,25,132,904,308,211,398,856,193,986,317,288,581,122,866,919,315,528,759,524,940,637,55,989,642,827,994,738,301,733,204,887,671,351,196,651,595,890,544,655,129,845,991,905,547,202,956,369,561,502,132,121,480,410,296,596,336,917,816,919,852,787,895,569,307,810,382,732,226,920,339,368,503,529,983,203,793,283,569,554,123,725,134,231,310,361,812,925,855,126,840,43,299,301,515,516,161,837,364,694,431,602,70,304,636,871,907,237,554,33,126,262,762,405,979,678,246,570,371,438,846,577,361,654,536,423,359,47,299,656,520,53,992,574,229,249,61,773,164,252,277,75,666,207,563,853,502,96,556,911,352,189,526,179,307,612,884,797,125,87,65,137,214,150,85,786,864,950,402,122,563,668,465,890,176,289,554,836,812,781,929,235,854,489,74,278,184,877,805,320,784,949,655,33,173,176,694,845,306,463,86,867,93,758,612,180,831,999,636,781,519,32,401,548,72,517,486,80,188,140,487,742,523,774,350,192,182,728,39,314,174,375,351,117,971,36,193,631,323,68,222,291,176,182,316,747,765,639,689,412,482,365,496,117,406,943,53,311,505,739,43,872,411,787,56,21,194,499,90,7,626,207,675,164,24,771,767,743,668,977,868,484,455,975,523,305,735,516,78,727,910,775,867,846,902,694,650,685,177,159,459,989,252,700,590,746,625,308,934,689,357,909,844,599,587,266,265,752,686,964,325,686,884,924,422,793,851,590,209,444,600,517,995,444,974,22,568,939,154,542,670,270,346,328,718,467,457,297,968,428,449,93,767,100,155,417,959,909,712,308,153,954,218,555,316,906,805,680,861,292,611,472,550,217,716,728,20,308,442,647,748,323,918,852,345,599,234,577,931,685,56,343,540,725,23,801,595,610,936,522,761,773,135,7,243,805,407,527,835,669,729,39,253,474,910,119,212,79,338,50,662,649,346,240,647,556,161,327,747,360,222,887,575,449,168,173,182,369,862,211,455,204,556,707,508,323,11,637,598,369,28,683,780,84,126,799,421,100,50,515,90,979,523,519,182,965,548,155,615,75,29,596,300,420,800,630,303,848,117,503,768,253,485,265,205,62,261,802,86,785,893,732,429,665,115,819,58,370,997,62,543,470,904,598,317,237,982,73,65,918,649,866,205,70,892,557,661,865,527,749,154,787,690,154,19,245,412,100,321,562,283,116,312,864,888,855,256,147,521,834,161,258,765,494,430,204,276,752,266,783,252,954,630,969,787,96,28,799,297,990,676,325,422,208,201,516,732,948,239,837,381,173,612,918,643,71,480,684,3,449,527,713,409,719,48,814,164,949,503,424,649,181,258,438,809,513,445,626,911,685,806,607,448,892,662,86,949,29,25,107,863,958,288,713,989,947,347,46,977,920,427,49,559,58,674,46,774,856,391,669,467,619,556,597,757,429,620,447,64,735,498,809,343,607,635,253,779,568,691,592,894,953,796,405,517,770,711,283,853,187,571,402,73,603,923,380,345,578,551,686,453,111,53,565,610,497,223,632,407,53,212,12,158,883,10,703,325,487,343,309,500,711,34,248,964,407,595,344,370,711,945,827,187", + "883,833,625,408,381,716,358,921,99,242,466,547,906,33,994,621,910,898,602,642,680,106,343,118,974,582,773,7,662,564,625,833,226,78,767,318,904,573,742,341,350,362,920,898,219,492,71,411,535,814,684,454,565,323,983,699,290,41,456,749,142,948,609,783,58,819,458,980,991,712,105,373,325,589,813,11,693,351,558,901,685,103,453,289,31,315,498,156,167,804,179,503,995,311,865,428,470,450,921,573,204,559,490,248,353,863,519,417,726,562,970,901,181,754,950,359,0,787,956,232,426,379,408,185,693,517,181,863,170,443,486,90,660,840,405,432,148,888,950,899,67,423,847,913,923,832,457,561,236,544,400,734,744,26,91,582,887,654,693,449,423,117,510,326,794,742,502,193,452,107,473,839,561,159,890,947,371,802,756,218,291,188,686,71,504,450,776,719,290,16,819,795,892,67,82,374,318,614,410,980,391,635,911,197,75,250,177,960,604,837,677,793,8,252,169,411,92,535,452,860,520,95,24,290,59,416,829,119,49,734,96,367,301,872,360,347,101,681,167,886,29,156,123,148,840,132,357,12,719,828,963,618,76,680,350,69,975,581,147,249,744,340,442,900,857,334,110,378,394,850,636,207,718,554,298,722,827,692,837,852,840,786,603,896,153,850,314,10,60,80,671,226,507,713,822,673,646,278,268,641,234,145,518,819,100,428,96,338,810,659,61,423,711,96,190,964,96,757,862,321,426,518,220,428,786,898,984,179,221,992,23,811,713,519,869,775,959,693,728,62,60,452,820,735,579,878,443,598,387,938,486,619,269,674,505,256,705,6,619,395,836,515,192,5,591,640,724,490,502,821,742,630,802,476,150,446,725,270,812,99,7,653,247,186,326,896,45,386,439,566,743,261,177,633,431,250,1000,721,218,235,432,298,502,633,377,342,151,547,120,253,760,860,358,393,340,593,803,61,806,815,981,949,614,543,444,607,870,64,961,860,971,575,263,861,698,372,634,868,338,591,30,908,481,998,165,411,813,375,67,338,322,49,586,122,16,921,432,328,344,730,232,36,595,268,799,225,97,650,957,125,735,411,810,115,687,5,956,630,284,237,747,728,395,673,359,913,175,105,668,121,641,255,405,330,319,158,143,986,881,299,761,931,359,553,521,429,677,40,883,427,895,912,142,254,717,562,185,994,356,333,405,963,960,489,1,187,6,94,706,296,47,943,121,921,832,294,274,984,510,136,825,354,549,624,966,901,253,699,819,32,912,658,622,370,287,464,608,193,747,381,310,723,166,127,389,79,504,52,66,674,735,455,494,351,891,425,847,946,943,845,549,21,82,840,910,703,781,556,902,181,306,891,838,461,333,908,817,675,665,529,755,623,824,834,633,362,431,851,587,99,977,213,608,41,423,651,775,708,175,299,15,165,582,959,567,492,713,284,294,163,219,493,994,212,94,704,883,54,579,554,335,593,513,597,36,423,43,43,845,891,221,740,587,61,639,432,299,320,891,729,702,761,37,629,159,66,609,605,622,180,510,151,632,816,465,550,378,814,485,585,250,97,553,530,81,410,619,822,533,436,416,607,766,663,984,530,952,292,225,103,945,908,623,167,83,474,658,251,474,224,577,525,148,532,534,648,989,646,297,941,738,124,562,646,857,209,705,170,684,63,261,322,102,285,582,138,781,435,473,547,987,781,404,78,9,734,172,195,549,183,840,575,774,250,581,866,541,442,159,466,515,875,173,951,784,723,972,623,49,358,189,960,730,362,869,768,858,728,937,910,351,696,209,445,894,662,657,985,935,200,399,673,977,955,378,466,785,598,114,922,398,274,174,707,33,296,272,948,385,597,336,639,40,308,138,909,323,278,339,842,907,358,850,314,987,141,947,979,490,253,342,361,498,127,735,892,493,137,367,676,92,353,398,344,360,618,58,424,273,377,694,988,476,751,200,478,699,687,484,861,397,305,126,595,760,7,615,456,429,725,763,786,3,536,713,549,499,519,884,793,719,659,415,871,513,749,249,698,760,48,336,18,163,6,997,833,767,46,342,56,833,238,653,338,264,867,699,358,259,12,924,437,348,77,274,129,982,80,45,647,697,81,684,790,321,15,608,444,733,694,549,33,173,52,599,203,315,997,439,72,870,461,186,72,730,636,162,751,529,571,433,170,898,156,643,371,906,990,913,367,966,347,655,87,471,784,489,759,355,3,927,420,574,214,375,971,853,738,913,101,329,129,327,725,135,272,440,32,893,385,690,216,476,27,958,450,81,200,912,269", + "353,719,275,597,553,671,960,931,179,228,734,601,609,703,518,68,302,820,81,531,41,126,46,925,872,245,328,718,953,10,702,252,805,651,277,236,330,553,854,1,759,876,15,412,290,302,353,968,55,122,486,82,334,144,25,199,403,630,369,306,513,908,894,24,578,199,522,683,492,100,481,924,3,602,203,774,121,265,441,179,633,237,243,395,686,801,832,321,876,6,211,959,366,31,705,352,50,486,4,671,347,916,438,184,374,861,697,558,457,183,379,473,193,525,959,219,787,0,183,781,719,562,779,743,353,546,274,952,546,371,160,283,630,698,5,277,682,368,973,705,276,377,533,644,688,70,844,952,171,278,988,919,695,119,909,26,844,993,184,177,712,651,289,131,184,364,773,255,411,215,512,31,580,906,791,956,508,770,757,838,776,417,138,482,341,333,101,30,805,389,488,758,437,161,731,392,694,183,46,395,244,766,806,228,680,79,380,316,845,649,272,597,622,449,758,765,447,355,663,210,868,49,262,475,237,832,812,266,500,465,530,447,919,776,426,323,38,816,726,514,577,267,143,765,741,240,123,781,402,793,298,977,432,19,33,947,937,699,725,976,216,693,56,346,853,113,275,863,7,494,273,962,61,497,170,666,541,234,867,687,449,1,275,752,895,547,263,37,979,417,149,263,381,41,702,697,89,16,647,214,281,542,712,194,149,760,976,14,604,75,581,200,268,586,62,274,249,948,146,946,856,837,124,810,416,450,133,317,71,135,553,712,762,118,198,828,311,830,602,294,515,242,801,296,243,894,193,383,994,494,888,899,954,856,18,293,476,663,909,234,574,182,881,359,3,175,508,75,259,994,110,36,515,260,556,416,536,449,541,924,376,116,268,917,900,690,217,360,37,307,665,314,708,909,341,504,52,990,254,41,979,463,624,969,678,750,867,357,80,32,209,57,49,474,392,12,374,841,789,132,500,966,824,363,127,137,373,664,273,659,923,932,902,158,52,469,606,640,587,6,675,138,321,795,315,324,735,804,175,660,231,908,53,979,646,508,688,222,169,454,49,482,826,307,472,787,749,131,372,794,189,47,93,760,698,651,734,222,312,119,722,566,522,288,486,311,614,713,637,793,547,679,420,478,754,714,139,501,5,83,375,186,258,544,917,119,220,939,268,833,560,800,131,503,855,998,273,48,313,969,845,928,169,330,990,291,838,387,635,712,181,857,224,271,256,235,189,599,84,841,182,675,227,375,266,947,261,471,614,928,584,88,940,118,567,193,856,15,507,198,7,239,659,773,628,71,529,233,562,124,209,142,446,525,238,301,477,821,604,924,719,288,873,959,426,957,61,770,768,856,423,568,521,145,258,136,776,726,138,512,274,807,470,52,469,651,674,494,657,991,615,939,617,643,425,362,636,530,284,446,441,966,557,348,656,655,251,242,916,449,414,833,675,659,320,787,60,914,891,989,402,295,956,740,807,414,160,925,186,78,754,35,392,520,214,220,263,233,72,655,480,645,208,700,265,618,426,563,422,69,275,667,521,91,4,970,452,154,548,972,314,374,199,719,520,901,549,141,863,309,11,682,169,803,544,541,99,956,266,356,864,59,331,34,394,197,789,953,671,901,60,874,153,668,909,865,574,248,180,385,934,589,584,215,468,989,982,326,461,64,621,880,683,920,385,723,159,461,875,908,63,315,133,458,182,440,254,289,852,714,504,617,995,581,76,598,562,141,340,427,582,284,88,129,397,552,657,313,473,241,980,89,728,31,985,322,440,911,360,157,950,960,981,714,603,960,410,18,857,726,911,405,590,333,480,782,644,880,601,353,992,335,108,93,179,832,844,410,177,564,336,546,385,5,454,679,283,542,309,934,225,381,928,373,132,566,740,185,37,380,795,401,347,293,354,782,316,613,499,697,989,158,949,420,347,779,858,191,116,381,499,394,487,76,620,759,278,729,481,23,717,196,767,979,225,471,838,634,23,634,362,298,592,229,892,537,892,425,861,698,244,161,607,220,660,998,478,323,775,461,501,336,92,636,588,381,656,855,992,603,755,738,958,994,219,260,991,14,412,339,380,3,226,12,589,649,623,689,806,851,670,649,445,151,196,815,752,913,311,388,225,888,577,366,111,498,334,911,893,67,169,428,808,859,916,285,760,591,693,12,986,210,551,141,959,662,899,264,851,485,754,524,794,238,62,380,655,490,480,219,390,756,944,926,63,596,408,529,980,70,189,14,750,229,540,605,503,604,501,340,581,313,627,81,402,307,619,289,23,872", + "452,607,207,866,441,842,799,876,420,42,815,9,671,725,499,359,52,698,464,578,630,249,735,814,463,543,959,443,613,117,726,15,953,860,967,340,606,460,256,695,154,613,6,360,502,645,800,855,964,73,812,494,375,814,575,348,920,266,438,570,590,807,246,670,467,920,55,410,793,627,569,600,38,805,666,82,988,84,854,486,732,125,542,807,155,718,706,473,887,914,351,560,420,597,837,184,670,356,316,895,983,630,358,733,409,137,308,67,887,927,551,351,957,439,533,153,956,183,0,667,459,600,223,840,142,263,315,93,953,535,498,515,813,481,538,374,153,376,220,128,756,144,629,718,111,977,688,179,291,489,634,494,535,330,561,355,651,511,951,827,209,83,701,729,893,974,339,657,459,21,234,238,482,490,619,566,721,820,534,359,272,579,849,315,467,947,560,290,646,931,752,34,578,810,388,56,468,136,905,389,281,507,713,507,998,747,944,313,380,445,916,222,918,509,320,46,87,62,603,158,567,70,407,289,55,379,16,81,89,459,395,937,250,282,537,242,988,412,320,808,609,966,978,530,184,647,427,6,136,866,107,593,850,231,425,424,166,96,288,867,584,77,523,612,844,256,892,58,837,970,42,550,885,240,568,258,364,802,733,45,245,735,586,698,505,535,333,476,876,723,171,955,796,778,536,948,974,500,18,972,424,513,84,687,107,518,358,796,477,111,98,790,72,138,600,645,987,662,178,885,953,662,326,300,770,250,506,939,872,344,816,505,185,347,220,542,559,413,295,111,135,318,246,636,372,68,317,278,775,676,542,666,75,60,260,962,910,593,146,43,689,875,84,656,157,593,165,139,944,519,921,484,598,391,730,314,203,918,795,86,523,436,232,251,35,654,340,378,614,333,390,117,975,808,8,231,394,412,784,127,373,526,428,193,848,935,770,566,716,410,273,84,888,1,816,627,408,556,144,600,289,183,640,728,233,184,106,569,355,502,772,200,543,118,100,648,452,580,536,200,233,137,602,913,365,642,612,9,931,509,536,997,133,85,34,457,910,504,11,674,385,624,276,449,175,445,537,460,328,703,55,36,515,115,548,924,472,442,133,219,882,343,439,778,62,822,412,418,138,381,779,309,216,429,490,111,115,482,736,36,200,534,31,643,214,352,554,807,930,476,762,725,130,886,123,517,913,73,16,114,538,450,434,806,503,210,510,883,624,800,346,302,128,328,177,884,989,189,774,931,299,127,605,748,638,165,124,750,84,824,492,830,754,755,816,103,695,772,935,985,391,623,971,565,56,372,670,985,744,349,628,428,355,794,581,61,69,344,195,700,488,18,104,241,833,148,952,515,224,283,698,137,944,12,657,153,86,612,157,741,335,959,126,697,873,622,153,856,708,355,826,101,45,471,173,28,220,142,442,629,327,268,509,192,73,312,454,613,908,180,499,356,131,398,2,49,546,665,829,896,798,848,815,553,937,181,117,96,491,57,756,818,323,302,211,152,986,3,987,885,65,403,342,556,18,823,673,518,221,277,662,762,886,384,430,333,124,569,441,669,641,295,354,997,518,55,218,583,168,688,565,134,428,329,720,926,460,715,217,214,514,187,476,966,877,330,442,974,514,819,503,70,973,950,363,593,170,692,969,999,570,181,481,518,764,830,800,121,585,918,707,652,469,721,297,82,164,972,746,167,287,756,353,507,549,838,600,62,299,999,421,179,870,740,256,348,556,815,971,24,949,820,623,397,51,35,597,898,349,180,784,616,913,489,690,870,247,941,140,290,32,720,920,367,677,760,909,22,117,23,419,572,866,325,41,548,27,191,992,838,543,664,138,939,711,796,170,785,947,666,645,833,277,7,676,114,493,234,743,360,912,592,711,552,560,623,258,443,291,516,755,409,358,803,283,875,628,141,360,194,275,523,75,964,852,441,924,586,334,356,325,999,62,295,302,965,236,86,399,206,612,391,952,2,909,677,531,594,239,818,22,855,448,875,490,150,681,737,211,425,439,823,856,919,326,948,964,22,711,89,974,70,371,679,989,5,532,631,329,713,941,12,50,680,639,605,109,862,463,338,199,972,230,85,525,681,842,322,298,595,601,892,937,624,264,719,434,441,745,937,56,884,447,24,147,655,293,937,411,876,358,635,523,14,75,434,756,579,648,645,768,245,208,69,649,98,111,647,984,802,780,975,591,76,109,896,334,83,788,354,896,735,612,920,669,244,387,660,90,299,709,559,109,881,849,351,683,585,491,383,54,708,31,757,788,391,444,98,183,433", + "60,546,176,425,433,659,544,323,502,758,262,771,520,50,509,325,414,4,431,329,967,429,217,228,308,981,458,21,751,149,258,311,195,995,502,946,681,908,787,160,443,569,886,848,515,746,267,884,816,153,16,372,372,918,424,438,85,460,949,98,839,788,662,699,450,900,249,870,382,219,10,111,975,500,937,422,832,924,547,950,178,501,107,193,147,25,134,79,790,77,665,697,993,366,607,668,32,812,624,684,826,417,742,219,547,928,863,124,925,753,52,332,399,820,686,117,232,781,667,0,312,597,977,269,38,42,77,513,358,508,510,497,482,390,911,58,245,336,933,175,585,986,509,648,83,254,332,271,223,400,457,387,570,38,327,560,237,489,426,98,43,584,389,573,111,257,642,859,933,630,384,283,771,431,281,360,764,240,112,976,466,404,89,20,316,923,876,808,554,596,461,533,393,710,885,684,55,597,717,961,786,545,521,966,386,901,996,783,226,169,905,366,768,460,531,969,477,284,603,396,994,520,375,667,473,601,329,94,674,802,972,314,976,437,170,631,501,614,973,830,845,579,120,448,746,928,21,318,361,522,48,853,899,545,660,91,12,374,905,67,682,834,273,233,493,143,834,293,169,133,708,201,694,565,939,257,401,45,624,136,367,566,296,957,34,890,259,311,301,927,387,786,610,571,104,597,463,517,104,557,693,577,387,691,686,395,722,550,620,130,726,415,469,371,934,695,958,867,84,937,393,829,994,869,939,62,464,186,465,558,796,262,802,29,518,15,785,805,838,813,484,995,893,195,513,608,362,843,267,102,680,197,674,46,662,249,166,360,873,247,272,106,842,197,916,479,338,87,19,576,477,481,338,99,67,917,548,652,249,613,686,660,335,382,124,408,889,265,123,815,475,613,32,783,316,950,338,547,399,485,675,696,488,393,903,731,547,564,821,292,226,925,256,51,536,637,582,191,968,352,997,961,324,458,915,575,422,880,57,636,36,927,536,757,665,682,917,367,658,753,658,332,158,516,608,186,884,735,822,273,559,356,393,581,735,13,234,138,860,750,507,120,456,141,790,682,843,343,603,810,116,535,412,438,697,342,264,555,758,24,693,472,62,801,19,830,292,948,810,798,42,325,621,520,240,541,246,638,332,906,102,384,811,380,462,215,455,945,666,511,662,254,730,801,950,86,155,906,238,589,503,471,493,392,482,324,64,58,352,39,37,44,623,987,251,65,168,714,431,165,668,973,987,796,500,731,485,90,159,210,478,840,623,541,726,310,846,545,670,973,641,58,391,525,285,154,107,557,391,937,340,398,751,135,161,161,56,79,68,289,899,494,665,611,474,542,436,997,326,457,952,553,622,152,418,17,545,847,220,996,74,283,78,697,116,533,142,765,553,340,903,850,736,667,543,893,642,420,193,619,592,342,451,579,496,508,19,327,687,659,191,221,993,683,47,316,91,814,980,542,873,127,443,748,363,838,409,112,591,56,248,200,847,73,561,263,180,912,320,651,327,194,427,308,331,741,658,918,985,571,213,34,984,198,392,806,329,547,299,158,728,773,10,262,625,687,260,187,706,537,679,777,69,63,914,784,845,531,171,831,372,297,383,925,722,117,793,657,364,455,120,344,907,299,225,326,299,886,908,277,99,712,895,684,261,644,854,151,566,652,620,3,758,555,454,867,69,66,384,214,252,288,812,703,745,929,599,420,431,839,324,784,576,673,398,208,425,477,285,500,565,941,929,890,783,969,621,150,940,256,554,752,440,379,636,597,838,134,269,770,307,162,263,466,617,291,378,148,323,889,357,779,153,919,197,871,908,746,124,405,205,162,209,3,84,509,626,463,254,444,272,323,580,26,213,895,37,77,240,216,350,835,179,341,577,787,219,810,304,993,575,712,978,528,21,768,322,746,48,979,553,798,183,946,545,767,719,931,977,930,904,344,487,690,845,666,151,875,873,237,232,409,743,944,24,788,155,55,332,928,250,682,9,833,482,140,314,71,11,146,480,682,376,317,37,428,384,811,846,524,29,47,980,797,430,455,322,845,446,911,683,998,547,982,99,627,745,228,97,809,979,648,35,548,217,103,264,991,172,272,819,638,351,898,187,357,393,534,948,64,319,677,830,927,319,74,720,397,496,732,763,671,72,664,652,937,36,3,763,106,197,453,601,35,923,617,694,230,500,379,62,661,343,875,924,678,46,41,135,156,806,426,26,197,205,775,285,475,692,293,125,237,253,905,281,93,448,289,973,341,705,261,980,617,421,324,362,307,403,387", + "588,124,190,684,689,288,434,98,390,301,678,828,52,816,225,958,824,113,306,172,818,978,305,708,855,2,356,734,162,858,854,587,672,598,698,633,744,702,946,119,210,155,947,981,497,643,616,684,134,324,956,879,734,173,496,318,919,845,202,706,453,722,317,985,275,47,966,635,239,810,958,154,135,752,857,966,931,55,784,685,980,810,414,722,447,312,612,25,317,465,704,835,193,127,591,91,76,48,452,340,904,38,16,739,745,831,901,461,242,166,182,92,236,122,870,569,426,719,459,312,0,723,393,838,654,968,431,402,678,605,56,110,64,492,615,27,187,135,42,207,8,848,785,751,838,49,179,504,884,110,481,559,697,740,69,146,130,54,469,978,282,845,96,847,216,844,30,398,196,35,576,494,833,368,541,463,585,480,636,243,925,821,452,663,618,973,320,446,900,198,290,56,379,363,901,928,604,741,633,982,691,968,410,997,381,160,85,882,521,603,630,860,381,2,233,885,242,352,518,315,688,992,604,590,5,859,493,328,467,596,815,274,265,326,154,360,675,577,727,661,471,176,775,952,142,597,885,576,492,517,424,218,694,110,439,565,791,212,856,654,710,793,38,533,959,716,483,478,235,123,21,668,200,636,134,300,756,929,884,185,701,903,60,626,803,811,841,280,382,621,399,5,922,866,725,880,712,22,108,424,221,412,591,59,857,792,885,858,629,318,488,706,426,29,105,273,665,691,259,413,37,969,333,958,946,370,394,2,448,781,709,871,179,195,356,859,293,348,448,323,325,259,645,545,255,716,746,631,216,304,947,727,304,869,263,63,671,238,259,133,589,268,964,831,822,189,479,913,935,2,537,29,708,783,628,140,23,426,924,885,350,816,380,52,60,566,765,626,405,135,211,453,659,853,654,431,607,679,597,770,828,760,626,861,77,659,667,41,194,14,905,932,856,997,677,37,140,922,677,890,171,636,475,757,596,156,33,950,617,349,227,338,2,278,89,916,931,728,51,532,741,87,856,893,850,993,924,3,993,860,743,440,225,462,431,369,155,846,651,246,614,435,148,929,176,951,366,176,572,504,747,132,354,359,794,52,897,339,921,566,735,47,72,336,14,178,358,805,576,188,48,188,928,861,973,579,727,183,834,815,954,236,200,298,873,198,587,750,11,973,209,553,848,565,609,858,210,823,578,636,247,123,213,911,629,21,275,890,214,19,217,555,672,123,752,107,138,426,934,696,584,56,220,568,868,283,739,154,430,343,337,964,998,111,889,305,901,694,446,509,207,574,758,389,415,503,403,377,681,849,826,864,637,936,642,559,79,632,819,400,722,733,612,716,274,608,359,240,389,392,410,700,82,662,255,745,99,492,70,612,645,585,270,255,769,870,520,139,259,808,656,663,699,915,524,252,899,479,400,556,982,499,303,199,548,645,887,655,508,483,103,590,693,66,30,255,716,774,677,190,519,419,180,3,740,342,79,695,315,203,866,685,348,998,637,704,462,425,56,441,461,873,803,449,633,826,757,156,208,588,781,528,683,40,699,153,483,446,378,370,779,641,718,636,936,424,103,925,336,608,754,682,936,142,770,722,227,701,479,363,44,811,799,256,391,346,493,55,364,991,680,700,418,844,737,676,981,771,28,786,745,732,16,86,900,936,998,507,493,221,927,409,725,870,659,611,111,891,161,352,227,706,157,181,716,26,551,576,865,888,331,839,185,698,138,505,125,895,171,185,7,426,108,78,766,834,109,242,944,88,514,25,489,4,794,336,286,420,467,88,303,117,985,717,159,503,402,975,473,800,354,376,389,617,363,642,917,571,631,899,445,373,887,166,96,820,50,263,185,433,277,616,651,159,222,910,928,185,121,356,253,631,619,592,917,453,609,194,846,550,821,305,206,215,292,968,503,985,638,989,63,161,965,816,411,476,584,596,77,418,891,918,890,502,226,740,571,210,827,707,101,828,166,992,467,353,658,493,872,822,979,152,579,966,323,341,196,140,235,718,210,135,384,8,846,584,164,375,446,312,207,317,546,382,85,202,827,142,667,864,899,639,809,129,714,103,699,332,730,732,152,179,770,956,134,828,526,285,768,409,80,572,306,621,260,158,111,549,400,467,127,672,353,754,827,24,397,60,405,126,941,226,39,889,687,276,680,477,46,820,842,924,255,964,469,777,616,692,380,122,537,709,638,721,50,474,202,327,250,919,598,748,812,523,286,785,774,463,371,133,417,251,951,24,216,735,707,639,517,251,447,906,940,869,300,23,163,74,517,560", + "87,719,881,790,677,987,865,161,842,431,553,645,952,160,150,922,800,969,133,337,424,814,918,664,342,372,211,858,227,617,738,663,191,567,262,363,702,707,953,462,805,380,37,544,80,244,256,279,606,801,229,364,723,825,669,999,591,710,442,85,376,477,630,414,955,848,667,749,354,794,238,596,330,158,429,637,887,218,202,330,278,715,204,420,276,9,181,995,432,983,643,697,878,331,828,656,62,528,246,257,208,274,448,888,739,670,346,641,201,827,973,357,695,158,199,584,379,562,600,597,723,0,297,730,890,770,180,605,699,195,299,301,38,756,516,733,610,432,590,883,318,471,770,820,952,545,418,663,525,399,490,972,261,605,106,913,457,675,97,236,594,116,700,208,959,178,144,167,393,638,964,890,248,915,746,971,441,876,11,218,770,410,850,386,502,938,263,92,413,271,179,252,656,230,650,913,609,136,618,970,904,792,80,622,722,257,906,434,625,858,71,363,615,437,461,953,941,119,618,70,139,64,844,537,729,538,852,14,531,489,518,635,179,941,5,217,150,250,819,957,693,333,423,209,385,375,820,310,770,851,409,102,743,535,611,958,330,59,75,99,614,547,660,225,577,487,247,820,372,682,687,207,583,378,44,744,287,78,543,983,170,138,265,486,381,485,107,324,655,589,744,294,163,689,910,919,338,387,21,613,926,297,412,116,516,481,947,220,78,619,226,56,693,555,570,673,158,350,568,775,154,476,789,946,437,204,465,329,706,334,100,930,488,223,534,204,843,31,888,789,691,455,721,895,741,248,546,307,88,572,69,336,951,638,432,773,299,664,146,204,104,405,243,652,866,350,466,416,590,317,652,646,288,422,84,780,609,237,177,992,583,959,416,994,630,112,657,807,894,945,76,362,600,787,842,847,793,816,940,890,278,625,811,64,450,279,936,223,229,201,7,305,674,765,791,42,945,439,466,346,733,285,310,232,959,270,260,392,863,206,754,991,468,157,828,546,370,801,635,82,50,735,411,133,653,412,931,814,447,991,87,907,41,132,503,45,836,691,439,528,796,750,702,844,853,36,253,699,367,483,316,655,647,764,882,933,768,775,776,975,721,863,141,677,484,725,470,127,471,773,531,512,546,587,699,561,195,845,261,594,617,85,105,592,948,723,948,643,13,313,362,656,107,35,58,975,87,872,101,344,38,346,98,589,34,917,450,837,334,166,461,80,357,948,611,930,778,116,484,984,737,776,567,22,525,237,102,210,370,521,169,504,141,932,327,194,49,94,164,833,529,810,822,983,95,727,304,707,146,167,48,733,411,48,863,438,802,315,657,6,243,430,556,644,285,184,813,438,17,561,491,832,983,898,947,862,947,404,592,339,787,526,854,836,11,621,405,61,301,151,531,355,328,153,465,466,684,847,261,453,531,572,110,546,932,497,682,381,689,990,359,67,381,665,668,970,793,937,884,780,542,445,222,175,547,509,130,693,394,845,411,555,565,936,590,857,981,999,377,365,814,202,244,507,289,668,372,927,809,571,301,106,742,691,785,629,370,39,100,413,816,685,318,642,237,294,434,384,66,742,185,256,510,934,178,390,177,317,639,24,731,537,733,845,923,714,228,111,103,843,529,986,13,278,384,171,177,89,284,70,720,253,282,466,652,434,422,359,128,813,286,664,150,175,687,992,661,300,609,497,161,826,538,336,522,62,510,695,523,589,342,585,636,610,602,742,240,100,61,814,472,541,394,65,833,214,764,793,302,868,131,478,973,331,611,29,850,296,894,92,157,718,617,975,913,473,881,102,916,67,880,138,390,625,237,634,935,334,827,298,403,516,812,157,582,829,650,881,402,595,844,64,2,623,68,783,699,160,154,203,484,598,634,423,811,661,202,125,865,368,886,663,9,466,250,958,132,889,242,726,323,296,346,666,327,50,134,567,470,282,717,908,115,716,383,679,645,773,54,768,158,345,524,145,381,494,739,905,967,870,874,394,960,947,543,272,849,553,86,333,674,324,43,269,846,266,840,231,6,41,19,82,490,160,851,253,890,304,182,133,216,158,41,430,397,678,235,950,675,8,226,338,408,212,238,271,77,650,392,394,89,914,433,235,807,944,789,382,442,969,933,859,724,244,505,562,71,48,670,129,78,892,748,834,242,957,273,424,368,777,709,318,61,443,337,764,187,32,370,565,475,823,557,630,822,864,132,879,662,798,11,322,285,479,839,270,10,483,28,173,430,336,485,443,252,177,73,365,490,791,55,648,175,528,198,644,139,141,838,262", + "109,555,447,475,393,558,975,612,589,961,703,421,506,609,547,438,383,362,576,815,474,474,288,236,277,612,153,543,431,681,383,328,493,167,332,712,713,778,811,297,254,962,423,83,938,891,134,183,246,623,834,363,188,940,414,24,32,947,676,929,659,588,920,959,520,2,122,279,602,526,811,911,507,390,295,573,399,37,637,703,645,225,484,84,306,853,94,376,456,909,147,760,528,880,100,370,624,589,758,896,302,383,74,61,311,682,17,290,502,862,956,574,841,840,372,600,408,779,223,977,393,297,0,984,986,109,878,308,384,926,192,425,187,55,993,393,374,862,550,241,372,922,641,301,468,440,844,72,577,847,938,547,10,406,868,329,223,919,991,90,733,16,694,119,651,436,817,257,639,173,831,885,51,938,303,626,936,942,233,522,425,327,491,916,238,671,977,976,785,274,451,785,240,691,939,501,905,101,698,96,402,359,730,291,622,392,783,189,27,771,12,528,681,115,726,728,936,841,476,41,339,143,464,619,699,604,359,878,370,406,211,287,661,521,553,463,363,326,128,895,200,68,347,164,947,379,784,23,857,712,395,579,720,340,514,214,23,880,645,261,333,707,64,175,234,325,20,927,82,164,266,564,851,54,681,2,535,468,573,861,709,709,981,794,123,781,704,869,240,893,687,447,897,120,893,419,168,280,582,749,519,880,382,670,618,347,933,275,342,840,544,425,687,958,804,182,176,366,787,747,76,903,934,31,737,56,208,398,618,961,926,394,911,876,851,772,684,504,690,972,996,633,736,991,491,780,654,259,161,456,345,369,700,608,694,829,165,538,665,515,618,853,333,399,665,108,399,964,989,108,469,793,454,256,483,635,185,577,1,780,314,333,738,691,424,821,537,263,414,556,860,347,517,769,375,500,845,694,293,871,531,191,382,176,746,801,105,716,163,820,291,360,334,778,890,716,141,584,745,996,831,48,387,678,670,232,455,700,668,303,227,728,16,927,68,599,551,996,858,468,713,917,983,999,686,264,249,105,87,361,914,494,554,802,931,634,84,581,160,896,103,293,16,113,250,277,980,550,462,823,86,840,799,714,669,890,636,366,702,440,50,951,807,8,830,751,793,816,681,44,335,640,919,579,944,765,89,224,764,322,346,566,216,538,100,835,118,167,303,657,670,975,805,540,104,422,893,844,32,464,105,257,192,137,471,663,708,496,803,187,581,49,265,966,73,406,535,502,136,429,899,394,700,677,982,840,156,769,216,216,725,389,474,693,100,417,970,731,272,107,476,756,21,35,784,189,446,316,970,135,779,104,647,443,813,624,552,779,985,264,17,831,318,283,169,99,334,136,322,970,980,146,827,94,337,202,343,955,254,212,470,28,73,356,533,331,785,479,689,524,366,511,27,555,285,708,400,459,796,631,627,60,392,666,364,862,914,529,32,559,774,712,435,584,917,965,97,713,674,938,969,972,894,829,77,724,517,436,337,541,356,126,166,540,351,578,810,896,214,567,362,200,636,356,7,512,421,213,91,704,890,99,475,640,999,201,492,743,830,328,134,955,854,70,220,329,45,481,917,389,674,465,426,492,530,313,857,133,912,846,680,417,872,499,811,390,674,497,952,951,78,746,501,300,168,358,345,386,893,631,413,740,15,655,534,21,92,164,887,903,933,892,550,608,730,30,928,54,923,855,244,278,662,609,318,236,111,118,706,829,275,395,562,809,497,51,82,278,104,49,796,334,751,616,495,793,96,473,522,355,340,620,183,494,873,585,927,882,446,269,195,683,698,802,78,961,531,426,623,778,400,616,789,711,840,948,256,477,496,980,89,806,32,777,717,322,660,640,487,628,791,633,133,965,811,947,107,496,23,334,133,62,416,568,681,103,282,822,921,616,355,33,60,205,657,993,934,289,181,352,135,302,674,566,787,212,126,821,752,480,313,248,28,181,168,173,159,117,738,433,96,92,606,894,12,197,993,203,765,793,926,159,492,575,132,687,648,169,183,100,165,950,352,55,900,910,301,425,527,797,805,384,256,295,893,430,793,747,252,483,458,468,349,385,61,628,801,146,874,230,961,686,701,22,583,30,148,995,80,120,573,842,368,679,81,538,290,737,446,100,80,184,36,141,733,472,606,170,296,679,689,921,791,5,732,991,321,165,512,710,920,481,770,292,278,650,918,996,894,596,632,121,723,210,399,429,26,118,250,919,827,282,758,491,630,542,93,229,943,360,519,683,586,929,662,252,282,33,55,226,553,172,649,723,993,404,353,583,643,280", + "473,154,530,48,767,590,997,366,332,245,270,60,658,225,619,864,176,489,436,560,34,243,22,756,978,111,743,945,233,82,193,258,975,307,135,745,805,893,33,646,580,718,766,625,995,93,286,459,403,257,673,408,809,300,71,584,778,883,163,659,954,432,798,751,18,564,267,427,803,213,705,854,471,648,427,314,544,66,276,857,722,58,251,185,952,623,721,585,387,333,560,916,800,761,516,845,864,534,650,774,533,66,761,31,236,316,599,651,352,772,741,269,854,487,646,387,185,743,840,269,838,730,984,0,820,71,615,595,871,917,404,610,181,698,794,213,924,499,125,967,222,858,255,284,569,88,423,611,237,35,622,210,741,204,564,677,514,945,65,949,687,108,926,184,889,458,617,596,812,187,606,992,903,95,511,926,151,854,834,288,732,770,810,400,110,583,777,133,502,752,715,494,435,492,237,25,910,736,420,7,802,145,788,97,965,75,559,886,348,159,836,802,626,146,650,55,593,727,148,623,12,156,518,753,958,489,7,819,31,836,642,499,768,368,703,185,6,457,382,648,954,921,379,818,846,206,469,283,868,424,778,397,240,765,830,865,168,319,311,245,348,548,478,447,813,631,629,412,887,494,408,618,338,246,584,118,258,657,749,259,489,281,991,146,488,931,316,353,28,671,727,58,414,620,238,662,560,955,351,874,344,579,121,26,413,697,723,676,676,169,940,549,907,416,567,207,917,294,18,510,719,424,32,676,256,453,993,230,800,787,209,377,36,241,926,609,579,623,108,322,601,524,854,872,466,579,950,192,405,915,579,282,100,350,543,140,835,205,479,188,614,443,927,19,760,988,217,92,23,432,361,284,668,126,643,716,967,667,655,612,328,936,606,63,386,49,50,238,609,577,521,938,921,982,973,674,483,566,58,973,587,396,111,556,237,403,545,765,649,172,240,569,592,968,955,481,869,375,774,790,620,795,658,941,805,41,425,541,317,893,735,843,603,869,920,884,912,633,308,52,460,894,731,718,738,571,146,182,866,160,748,708,119,14,644,306,99,264,98,973,175,690,968,7,39,906,921,316,227,413,184,799,550,311,491,23,667,469,227,910,128,861,413,907,827,701,733,558,162,729,69,66,516,974,362,937,8,779,312,898,622,594,188,430,158,159,140,681,952,948,953,159,640,244,808,490,673,506,351,565,6,566,142,972,640,876,471,541,876,471,687,680,766,895,896,684,21,936,204,443,53,115,411,771,996,340,423,216,806,29,76,565,37,688,731,361,224,594,290,531,776,370,533,705,772,927,873,963,458,118,122,939,691,613,537,668,841,483,593,639,231,335,796,816,367,324,928,85,950,168,655,416,837,898,187,782,980,724,167,619,44,676,202,484,751,10,508,952,683,633,904,56,675,923,858,599,70,297,961,109,865,569,979,989,347,987,451,955,749,855,450,367,44,934,37,741,518,238,9,355,415,557,264,829,193,78,984,360,442,903,593,967,230,713,620,38,856,809,837,643,660,391,765,762,427,962,32,621,897,973,382,749,290,997,833,448,823,643,321,290,906,919,584,963,247,507,309,365,517,712,520,579,640,258,816,599,488,43,683,296,294,796,774,917,525,781,110,172,753,533,240,939,753,766,979,329,125,618,642,334,718,469,295,381,342,798,750,665,536,433,633,681,56,361,626,478,931,459,276,203,994,316,171,793,203,733,556,517,674,508,170,960,677,314,155,378,189,394,946,339,245,420,590,355,982,961,786,836,451,779,976,16,754,171,865,207,327,348,673,756,458,769,908,226,205,674,473,275,726,684,451,3,310,449,968,245,583,106,439,818,149,825,336,927,168,195,415,340,406,772,751,525,892,938,289,944,342,450,207,355,155,334,915,121,298,599,284,726,984,224,281,495,879,270,810,882,459,557,231,766,469,668,265,818,51,29,920,823,845,373,273,221,518,452,262,825,389,954,180,647,46,987,184,852,805,884,37,470,885,44,587,643,783,500,279,418,716,50,863,239,792,989,158,983,26,721,186,545,222,668,262,471,974,638,571,233,993,63,39,956,767,585,593,404,285,429,795,38,605,347,866,113,333,245,732,283,398,783,33,601,635,210,467,282,960,611,79,161,391,608,708,721,767,765,386,730,686,559,856,457,590,976,183,278,101,64,594,253,938,122,236,608,201,999,297,332,550,785,251,357,739,363,150,694,878,973,144,444,264,337,253,645,711,875,307,933,816,102,392,335,133,381,168,297,915,135,519,640,649,129,400,302,561,55,886,937,925,483,101,665", + "66,264,458,839,8,853,6,943,80,778,455,617,506,428,820,471,913,124,121,18,894,653,68,535,960,950,702,661,863,534,523,236,262,42,385,39,780,600,260,396,759,84,88,335,168,65,153,105,87,410,1000,547,72,552,50,245,886,194,157,440,989,56,343,196,365,416,518,186,676,423,670,126,831,131,140,101,122,929,389,106,326,399,413,704,53,171,570,491,43,830,761,841,336,183,323,911,10,466,335,637,745,553,258,824,698,251,718,990,386,128,474,106,30,72,206,533,693,353,142,38,654,890,986,820,0,496,923,457,750,587,494,552,415,281,131,76,601,27,584,308,641,686,563,504,331,570,807,108,902,239,444,302,582,713,297,771,254,358,844,752,708,262,425,661,158,630,313,868,382,594,472,226,718,533,557,27,515,68,455,513,461,431,741,761,283,477,841,235,475,478,700,89,273,595,257,879,181,598,379,927,12,577,718,78,275,950,983,18,246,553,966,612,237,105,639,926,901,480,740,697,18,985,627,934,971,339,672,768,104,388,179,155,437,784,362,384,502,764,762,316,786,982,142,162,41,258,233,468,300,326,208,893,74,815,536,562,452,876,626,853,188,98,924,923,981,187,247,403,408,933,780,706,532,628,48,66,368,982,745,154,512,346,907,120,577,436,806,765,71,100,526,540,50,757,752,410,570,820,61,21,498,766,773,386,514,32,728,4,67,3,743,103,268,132,714,554,48,856,120,422,509,483,843,763,68,957,735,545,153,820,257,769,774,693,41,863,261,57,956,641,892,722,106,878,484,948,594,132,177,832,109,37,312,402,480,696,858,958,559,515,673,422,77,22,541,24,407,226,902,498,628,630,308,365,925,668,643,870,383,745,477,146,754,97,641,751,199,675,491,277,515,94,214,119,648,291,647,308,573,461,904,724,959,608,450,973,7,300,998,959,281,610,348,272,534,918,385,350,618,976,333,303,941,160,418,241,857,877,258,428,626,859,795,681,700,247,108,223,822,943,831,667,915,102,425,756,480,981,522,275,73,861,195,434,911,415,194,24,816,875,145,309,148,292,270,33,744,234,437,184,759,555,573,628,575,237,73,697,42,220,565,397,215,40,270,922,367,737,430,848,486,528,941,739,726,864,271,246,417,315,307,230,783,48,589,844,294,592,540,954,566,163,190,416,860,181,969,588,678,675,95,289,866,686,193,265,763,669,885,859,305,319,553,991,59,544,492,117,665,107,356,833,211,956,472,635,132,579,934,944,689,972,633,84,16,489,808,950,951,429,699,497,36,708,35,323,549,640,730,251,497,208,994,753,689,103,5,247,751,291,602,493,477,586,822,415,29,972,651,150,989,528,967,761,789,174,972,421,165,485,269,114,751,2,625,495,725,870,685,581,553,182,110,565,140,992,566,738,880,213,946,578,343,502,538,578,380,401,244,387,765,771,993,681,37,914,80,1000,548,730,766,940,362,9,20,362,166,652,706,72,362,671,792,499,260,406,589,522,658,407,475,9,338,546,759,519,60,935,312,48,721,329,896,671,324,111,557,341,651,596,693,383,181,735,232,942,23,491,420,269,367,272,596,559,698,737,131,506,71,771,131,890,557,472,196,609,974,582,748,155,710,69,956,972,840,962,325,748,781,244,451,941,329,856,519,694,363,427,356,331,200,710,870,895,473,671,107,449,955,88,837,542,591,504,817,762,188,614,381,377,809,270,503,807,332,933,764,513,926,435,845,373,566,13,522,649,883,686,42,464,98,118,913,598,704,890,924,838,887,766,340,524,542,755,940,142,432,695,733,588,924,827,477,171,625,313,861,832,988,378,617,529,108,254,440,609,624,24,956,526,589,85,554,442,62,14,271,440,548,774,481,91,143,177,271,614,758,844,129,296,107,539,258,570,246,173,908,111,742,309,601,120,379,57,883,346,565,870,283,359,603,844,168,871,819,471,315,315,317,857,369,230,711,779,414,164,650,201,357,378,654,472,712,493,365,910,330,594,329,194,675,336,537,214,748,794,636,698,982,766,931,227,872,528,682,30,669,428,141,699,682,711,488,499,246,741,919,702,518,421,470,708,234,881,500,918,833,939,486,182,187,602,905,915,90,706,280,614,274,41,617,232,608,650,529,832,314,945,660,244,982,824,49,839,34,135,246,810,619,472,428,729,511,393,963,521,16,378,197,327,937,759,501,695,635,215,257,523,907,827,515,372,652,910,373,162,443,23,540,565,673,796,329,104,849,579,267,232,686,593,370,848,260,626,753,959,634,925,383,741", + "965,486,382,592,904,878,484,400,446,830,894,643,736,208,705,318,630,794,85,175,637,979,526,434,916,837,658,111,595,286,879,328,485,810,23,94,289,15,577,812,791,406,400,423,764,314,300,226,782,506,519,884,896,167,652,895,204,737,722,155,346,8,492,538,803,123,546,250,250,669,228,476,242,809,718,900,653,995,409,277,65,499,999,221,490,317,928,481,974,101,639,691,635,238,166,475,438,224,626,763,66,423,206,327,452,846,962,579,906,882,423,82,983,499,769,868,517,546,263,42,968,770,109,71,496,0,188,882,148,202,857,516,659,943,349,928,944,876,69,211,210,949,64,127,117,701,289,364,164,257,423,309,899,608,525,462,571,892,909,153,933,50,639,518,299,564,957,511,775,769,915,10,230,810,227,358,5,289,670,590,171,301,885,50,794,639,505,956,980,212,932,628,64,876,270,111,733,58,27,854,781,532,994,727,984,641,953,826,7,391,331,221,908,230,515,100,159,443,207,745,535,747,415,467,186,940,799,234,667,947,154,400,891,664,266,717,631,490,826,423,814,298,115,181,804,149,251,938,92,25,41,897,795,945,919,789,283,484,568,848,446,431,723,812,150,646,673,589,760,248,200,653,690,958,131,404,406,113,327,204,472,847,668,503,992,682,609,349,432,665,649,18,17,68,936,778,164,633,384,851,743,937,263,356,228,668,900,55,757,881,419,422,789,408,344,328,330,577,896,850,774,423,927,644,201,946,436,328,305,627,664,721,855,143,819,720,469,808,673,773,864,90,170,485,241,10,528,735,72,330,87,560,812,345,334,889,831,396,972,211,933,813,530,168,741,646,296,260,160,107,187,707,67,390,265,458,310,384,183,137,670,246,658,663,602,83,120,367,324,686,145,994,336,653,412,376,51,860,410,540,54,172,368,661,634,590,820,453,344,160,646,402,144,950,899,627,91,263,686,893,665,6,261,19,312,428,703,803,666,546,312,490,368,591,577,458,129,598,127,846,977,55,684,687,47,917,450,141,430,365,402,424,288,739,579,517,162,987,559,199,780,582,783,480,951,642,884,626,624,449,690,289,895,707,320,74,646,540,736,645,50,76,155,646,6,976,635,962,787,717,669,308,933,451,212,764,110,350,605,759,927,507,148,706,267,790,189,618,307,644,604,788,3,518,149,799,358,855,765,867,909,557,115,730,559,804,372,650,478,287,547,297,360,491,910,916,439,630,699,99,664,487,88,273,241,692,798,416,604,518,865,193,202,852,883,442,885,823,799,371,442,626,289,286,182,522,209,235,778,281,852,425,980,848,734,323,411,444,11,661,613,411,926,147,987,206,805,698,807,60,545,599,921,469,530,955,616,545,284,10,602,820,894,921,947,510,948,341,886,556,803,882,366,774,164,174,405,663,966,263,263,139,930,200,21,339,87,95,444,84,835,626,155,671,840,963,300,849,943,59,617,863,594,369,319,506,294,383,401,277,265,680,911,913,556,168,348,39,282,647,496,318,225,475,63,840,764,156,783,167,89,749,925,945,75,16,653,622,791,723,949,445,960,34,168,822,231,42,54,163,413,780,77,358,486,486,391,606,420,623,379,735,920,153,587,826,523,404,802,32,685,515,727,656,21,398,613,232,623,56,22,903,231,618,147,499,144,136,842,181,637,35,304,918,890,75,184,728,683,754,512,997,920,96,855,75,962,885,730,812,817,798,290,400,920,589,213,11,384,116,395,210,154,735,758,781,705,3,219,590,102,761,543,474,922,172,702,661,569,179,167,363,402,28,191,864,80,491,888,963,925,683,569,713,843,944,382,205,173,553,112,915,905,688,620,949,980,814,563,888,538,57,99,592,412,519,120,706,217,371,366,237,631,296,665,696,939,769,346,524,225,899,230,83,945,354,918,614,246,959,952,670,501,721,652,643,683,8,838,419,950,247,653,852,388,385,108,250,347,500,550,366,576,937,733,856,95,352,506,152,44,194,131,129,434,992,689,357,460,171,8,214,229,231,510,842,984,163,468,960,395,556,468,606,978,316,509,634,27,803,988,369,672,350,358,623,339,490,99,56,727,959,666,124,451,352,823,984,998,844,653,426,395,614,397,114,319,633,903,721,313,295,922,545,129,506,262,199,497,707,831,553,598,357,538,260,256,448,389,513,330,435,835,65,38,149,124,238,173,192,128,466,796,581,74,537,61,384,577,552,916,707,491,610,437,758,881,625,152,602,195,966,257,16,797,299,379,830,906,41,483,204,569,340,654,779,237,978,292,90", + "973,643,466,379,387,812,873,117,572,396,302,832,465,796,884,771,806,684,1000,173,605,263,533,794,283,566,432,486,353,183,350,991,958,306,718,701,988,228,802,944,370,524,867,636,656,731,546,422,754,310,894,164,447,83,776,739,484,680,949,281,859,245,957,556,861,103,563,216,62,994,714,11,905,519,152,104,990,123,570,883,37,384,953,429,554,12,195,95,629,987,63,315,871,600,448,459,780,599,62,547,746,42,455,195,747,960,884,564,612,161,392,916,56,655,275,299,181,274,315,77,431,180,878,615,923,188,0,673,46,622,240,176,919,904,570,481,732,645,523,543,208,104,978,565,903,847,288,641,129,580,47,781,15,577,98,421,229,464,942,612,229,784,319,992,163,242,874,248,193,242,810,247,578,795,214,789,426,946,186,616,651,605,524,796,285,61,44,138,229,636,897,574,794,178,560,574,89,114,629,494,927,823,314,48,746,717,843,604,737,489,96,674,940,979,913,839,631,248,939,220,146,569,936,849,139,252,912,645,449,856,750,801,356,761,487,411,178,897,263,884,954,430,868,237,254,43,150,189,893,676,426,657,997,601,63,523,575,438,445,429,142,421,904,865,54,772,767,38,838,977,328,812,139,108,284,803,469,589,132,675,324,501,152,911,707,567,286,531,833,805,155,117,259,459,624,166,671,3,106,35,88,89,277,97,505,286,480,181,338,469,738,145,356,438,267,811,989,612,888,933,716,996,117,867,822,816,609,67,52,122,839,880,8,707,471,723,174,373,232,666,597,532,152,838,881,875,289,86,521,923,145,599,200,275,743,270,833,58,496,790,483,814,741,216,62,755,918,207,600,616,771,867,307,130,830,441,377,177,765,781,473,167,935,503,953,470,166,316,510,304,549,965,267,684,93,44,432,545,57,228,193,830,48,893,252,76,134,255,463,175,203,816,701,398,728,754,243,52,569,764,81,291,714,24,51,786,496,228,708,50,32,8,157,278,720,377,378,169,859,619,905,214,166,479,61,995,865,166,624,11,334,154,295,45,152,158,1000,671,263,478,452,13,797,876,308,542,672,601,152,853,953,403,63,451,217,897,100,612,810,192,250,290,187,793,505,288,9,975,715,700,268,310,80,209,990,783,598,232,422,96,19,575,829,283,174,214,297,662,712,957,904,936,338,345,238,450,583,647,44,160,165,542,54,138,950,342,838,839,952,925,62,291,539,980,399,433,785,983,208,45,360,742,32,500,474,932,354,20,924,167,813,109,353,120,101,900,430,485,177,430,50,672,636,781,469,858,582,796,869,818,912,803,626,417,156,734,860,305,783,111,929,652,844,922,46,795,248,413,719,114,892,471,107,709,81,906,440,417,595,998,496,275,802,756,213,375,437,699,123,929,821,740,738,237,412,411,752,422,114,361,499,64,541,618,409,159,990,37,780,349,418,173,282,581,412,429,296,373,873,757,911,778,705,173,228,156,931,269,359,303,94,12,853,690,948,870,361,220,400,62,658,732,7,504,330,354,176,811,53,821,447,315,841,980,329,163,986,101,509,167,94,898,237,353,541,985,691,803,480,154,41,841,813,121,619,690,901,327,652,802,69,158,863,929,431,439,953,375,856,790,432,889,51,281,743,272,592,532,266,879,285,431,654,819,984,782,389,319,173,336,383,72,334,657,598,182,997,673,458,50,528,112,945,971,232,75,383,367,754,270,716,294,73,104,631,406,68,196,779,286,228,372,585,288,122,164,826,328,793,66,530,469,491,2,658,737,693,664,156,443,336,143,502,18,13,554,809,237,929,667,920,873,44,535,509,119,143,121,364,288,127,524,810,232,668,878,290,522,224,642,200,230,420,658,570,980,152,314,455,395,123,876,500,985,781,754,419,72,231,493,364,599,83,298,536,212,25,415,167,412,151,726,601,425,252,988,139,718,638,308,339,919,929,868,245,746,988,747,806,520,37,820,219,823,53,654,502,832,453,158,593,726,822,117,496,706,29,418,104,882,82,550,90,436,94,545,914,982,537,240,773,125,281,790,906,793,440,167,866,596,279,683,281,80,14,739,47,296,530,298,928,304,156,3,22,536,228,983,937,497,853,387,686,629,675,859,236,252,509,164,9,389,166,645,219,325,868,662,259,500,747,852,666,121,304,697,918,255,797,750,387,244,577,387,423,183,613,567,893,103,761,867,654,709,925,576,414,42,983,842,505,666,965,105,105,976,287,725,662,155,501,530,722,598,424,159,829,45,937,957,302,39,794,441,613,101,730,311,366,735", + "950,437,65,950,965,337,206,683,19,406,697,489,73,654,841,14,788,376,477,602,184,732,934,929,517,659,64,209,53,396,895,407,683,720,503,698,740,458,76,339,965,90,422,969,54,612,78,140,184,232,195,152,560,102,781,641,677,289,623,849,269,347,707,593,240,955,401,397,252,947,442,181,866,209,763,888,302,185,620,39,686,883,372,307,460,502,712,255,652,999,46,676,241,919,137,487,2,96,874,976,527,539,809,171,342,979,850,710,573,345,501,476,244,605,364,377,863,952,93,513,402,605,308,595,457,882,673,0,668,449,456,198,853,327,505,808,227,164,468,273,931,342,625,285,616,668,9,595,209,470,701,915,234,747,74,649,839,414,913,814,331,518,162,931,854,853,7,661,6,199,269,628,269,174,481,429,962,549,821,916,309,857,341,305,937,231,948,276,84,161,309,620,94,129,725,161,419,210,787,753,609,681,691,199,186,220,466,544,242,256,709,220,676,416,905,47,62,72,838,724,743,434,930,355,584,553,277,95,738,828,322,977,552,285,495,815,987,586,606,751,635,115,822,915,791,984,713,469,72,269,740,611,588,724,19,798,251,641,219,170,17,130,467,797,497,909,70,262,139,976,767,833,744,778,894,496,870,393,826,324,824,623,666,18,393,100,459,198,103,620,765,891,799,419,456,566,602,664,334,611,82,450,583,312,497,719,602,462,480,714,767,135,596,23,109,255,2,893,113,294,500,967,640,867,470,101,439,947,604,27,998,356,941,129,14,259,68,444,656,241,829,919,679,382,34,904,934,332,117,275,837,249,534,51,109,208,572,454,298,576,293,413,492,500,210,762,782,460,67,485,337,977,426,442,385,5,833,834,119,102,408,124,28,948,601,158,711,382,853,802,259,433,368,478,287,933,109,450,438,636,159,461,554,703,813,819,533,670,716,145,467,406,927,889,641,230,817,355,110,901,871,193,346,5,716,856,107,55,83,941,344,438,148,59,282,366,130,983,906,182,799,729,15,880,650,106,396,179,185,829,126,708,437,397,151,151,664,847,220,96,913,267,949,9,59,790,482,193,104,72,456,796,152,872,712,280,685,194,911,418,699,535,309,36,536,250,77,521,263,85,671,458,949,945,914,219,662,274,340,851,18,429,950,26,533,295,712,527,559,138,636,768,508,642,760,60,194,912,135,104,662,613,935,793,21,563,325,996,38,413,15,624,788,598,58,971,50,792,942,463,700,945,987,628,324,7,202,63,457,173,563,939,459,561,263,155,803,338,715,10,627,771,11,846,377,235,501,689,16,522,249,10,902,172,836,874,613,273,662,38,950,168,942,329,340,321,47,513,15,673,216,767,293,64,212,27,312,260,348,978,944,718,599,779,334,330,272,513,651,251,605,282,781,960,181,978,129,435,568,436,886,958,60,268,304,560,202,532,151,97,962,539,320,866,673,346,43,488,115,177,896,598,196,902,719,261,642,580,52,168,762,807,362,103,442,547,47,543,472,423,492,298,610,429,122,463,360,749,887,910,33,314,927,404,873,4,905,965,945,401,336,229,337,181,259,329,65,59,977,728,334,58,123,883,409,847,462,343,453,128,892,19,483,718,470,60,936,414,543,509,898,70,284,345,395,280,923,901,339,323,338,875,972,736,974,41,757,275,761,884,136,473,427,620,340,565,815,502,325,113,387,342,519,460,481,30,2,151,89,929,597,86,449,455,274,26,399,785,303,182,703,99,131,784,332,108,62,140,467,883,161,222,902,574,83,332,834,427,241,222,513,559,871,351,526,430,562,615,713,364,856,981,778,115,407,145,690,759,892,559,916,469,101,875,253,952,444,327,407,669,313,361,954,706,429,680,88,124,467,498,629,183,809,270,699,60,478,17,874,33,73,689,25,973,168,127,199,193,729,365,651,220,6,487,63,909,720,222,224,944,143,247,432,457,700,147,412,682,466,548,622,947,302,419,24,299,641,922,733,714,175,327,806,662,63,68,119,367,143,861,915,367,73,162,316,782,534,509,743,631,993,207,843,440,536,473,120,925,720,684,486,691,627,239,899,353,138,475,96,694,691,354,874,542,609,180,777,100,192,909,105,674,266,635,745,189,555,259,151,389,965,126,911,560,326,862,457,109,728,866,578,361,458,794,872,69,428,856,393,479,865,61,589,989,170,153,523,544,233,761,35,227,464,788,717,273,591,159,810,220,4,835,965,514,268,590,220,938,279,994,304,11,72,963,609,633,669,884,607,139,171,54,619,833,919,215,135,473,712,233", + "952,828,16,990,540,210,860,948,331,618,499,455,739,70,302,724,267,808,79,66,616,864,201,188,545,23,251,496,908,404,550,19,395,862,671,464,714,223,176,6,916,82,458,945,18,946,996,800,906,569,648,363,117,234,804,503,123,655,425,927,978,926,194,310,133,907,291,365,832,977,13,115,736,440,75,790,450,976,522,510,906,551,757,677,187,355,471,202,105,79,981,17,462,682,130,885,571,830,638,338,775,797,448,986,375,189,403,252,908,527,610,556,560,493,912,929,170,546,953,358,678,699,384,871,750,148,46,668,0,158,337,173,601,624,124,539,513,133,320,77,748,916,520,56,465,905,124,842,97,221,369,151,316,4,371,616,765,236,376,559,115,508,925,135,774,885,266,644,648,299,977,805,454,553,243,671,25,892,862,757,817,629,932,248,62,206,265,800,233,996,765,140,301,90,950,246,88,112,836,883,128,709,699,787,244,92,41,624,536,359,244,440,893,562,857,708,20,459,290,153,642,533,223,951,795,464,817,345,25,952,894,295,811,662,333,819,76,543,95,741,844,845,163,123,662,448,457,439,226,188,267,339,227,379,18,232,886,940,814,433,847,225,812,896,353,881,755,482,483,278,273,350,180,311,206,536,765,181,371,820,961,168,770,571,204,707,396,146,26,364,546,642,291,590,629,390,77,452,656,267,572,682,262,48,839,288,920,536,284,107,757,582,115,661,638,924,591,432,629,277,237,590,181,948,603,851,57,547,866,492,990,591,371,230,768,399,212,319,369,934,954,859,948,371,824,922,527,382,218,401,425,751,953,673,36,659,30,779,357,104,930,278,246,200,423,413,681,583,689,18,776,176,891,664,449,782,193,741,251,655,345,52,102,881,606,344,901,741,297,778,555,822,246,9,970,446,614,778,750,503,87,246,467,242,644,543,686,341,480,983,51,840,628,956,845,510,257,915,22,640,255,279,749,248,712,90,711,514,174,237,259,774,923,38,687,25,213,619,652,701,973,126,714,995,54,328,815,6,714,851,382,266,430,221,737,75,942,398,658,993,261,388,579,798,557,934,73,26,937,38,9,214,360,55,443,801,558,875,702,483,716,350,684,800,370,348,601,219,386,393,12,196,542,655,503,84,657,634,731,675,547,568,260,171,12,72,967,935,788,528,755,724,274,677,49,859,516,611,758,604,836,811,601,728,954,606,121,412,375,629,82,782,533,97,708,32,345,758,697,310,686,746,361,98,139,85,527,655,212,160,609,227,889,541,657,678,316,413,501,282,660,566,942,864,868,834,272,211,152,945,402,102,221,249,477,659,415,82,455,48,217,531,962,403,650,689,685,475,287,662,171,421,899,474,633,373,545,317,994,484,554,12,821,651,569,288,262,255,577,550,387,795,970,189,512,739,747,352,721,459,8,413,372,292,90,180,969,677,371,973,636,421,385,188,501,104,531,979,111,319,115,379,833,754,910,500,621,228,615,175,204,176,914,377,727,628,952,507,3,404,461,55,72,836,946,939,732,367,151,456,375,600,701,829,63,901,856,244,831,65,761,750,802,239,772,913,279,605,718,768,999,483,875,569,664,260,387,552,293,501,306,681,738,956,978,451,697,617,898,495,584,258,664,292,389,358,766,742,189,345,20,207,67,894,633,735,494,150,383,588,359,776,814,947,747,148,996,665,398,276,287,270,173,881,908,165,876,283,421,216,541,95,575,113,309,902,995,124,891,223,426,600,989,205,804,491,193,48,466,11,977,82,458,253,240,935,966,316,675,643,949,48,307,853,171,397,141,609,730,617,222,135,569,240,560,662,366,54,290,912,997,101,84,359,991,576,341,971,534,876,72,517,84,272,824,947,879,477,548,548,604,746,515,489,629,129,519,562,441,954,962,632,86,311,674,682,426,916,194,919,329,877,652,133,612,181,654,943,527,833,31,698,273,655,689,635,313,560,519,677,374,519,703,416,119,176,954,728,498,338,122,475,25,559,387,342,432,883,842,74,450,79,312,629,306,262,415,22,763,529,356,517,944,718,162,310,978,829,671,323,909,99,458,896,572,665,713,119,436,421,976,411,258,663,880,813,68,706,555,591,136,950,456,920,685,499,637,562,962,836,142,870,476,165,401,854,908,158,309,258,800,554,214,856,918,247,531,960,258,688,967,316,77,774,655,396,604,148,766,484,180,928,81,958,476,584,326,311,100,945,384,611,418,448,107,75,149,43,961,288,202,866,86,585,7,16,155,649,107,687,377,412,67,64,959,49,509,959,313,103", + "492,729,85,980,463,805,36,673,830,552,126,24,56,363,64,71,26,848,861,193,844,214,466,760,291,679,741,426,645,986,279,514,507,97,562,121,88,735,417,665,684,832,686,865,108,72,117,934,604,213,694,644,172,572,494,469,15,466,479,539,470,80,475,321,74,745,993,393,979,485,590,749,810,874,227,456,827,19,321,238,973,601,982,593,840,690,697,438,532,324,298,830,731,254,777,690,268,866,383,595,389,358,598,36,839,62,279,37,36,975,286,793,164,691,771,278,443,371,535,508,605,195,926,917,587,202,622,449,158,0,13,146,288,260,842,352,144,636,590,893,654,669,967,99,851,342,578,178,628,81,484,353,972,451,695,557,250,962,228,222,161,115,812,288,467,414,65,815,470,739,834,894,627,929,588,74,559,881,227,739,163,849,609,825,343,733,585,489,916,101,344,899,159,210,976,482,574,233,865,149,330,257,659,510,262,222,203,594,96,776,100,405,397,861,480,342,41,177,995,42,676,68,413,856,814,522,745,835,394,416,986,685,753,828,375,991,153,776,972,424,512,247,642,277,341,116,24,789,240,963,319,273,560,942,502,181,568,189,5,815,430,192,224,182,617,204,10,560,885,758,833,848,774,885,15,76,630,92,963,850,356,100,939,506,699,426,304,167,907,213,650,23,969,757,330,434,596,830,389,173,27,482,394,684,363,875,835,326,113,855,840,692,2,844,299,640,532,834,296,54,106,906,899,434,429,521,374,810,474,239,226,574,463,892,844,743,251,927,592,660,883,560,115,926,943,748,925,922,508,26,413,389,867,12,536,561,29,266,605,656,941,842,751,264,500,820,106,325,959,9,706,432,16,583,795,827,575,561,351,467,5,121,477,355,635,540,326,340,865,809,530,480,743,490,383,600,447,984,604,129,717,243,695,14,889,392,804,663,795,156,877,675,777,649,98,460,418,305,83,686,238,647,679,664,226,869,839,159,419,585,812,525,221,141,186,230,288,304,784,751,322,810,679,27,952,368,336,764,768,66,413,191,501,390,757,132,895,914,941,130,737,123,112,648,629,817,191,458,378,110,98,255,452,744,364,153,598,93,353,184,677,397,845,891,581,169,647,646,173,238,282,331,740,310,22,453,826,35,51,583,32,622,684,155,372,699,42,150,795,556,206,935,317,879,935,640,188,44,49,205,113,266,957,63,32,444,928,17,286,845,980,788,239,325,134,331,702,144,198,134,410,690,104,641,533,354,46,614,81,756,254,208,771,44,949,532,235,228,700,853,721,698,468,150,477,19,249,730,734,744,271,266,754,568,121,896,435,121,446,283,833,599,448,273,375,343,233,807,317,33,350,90,222,731,265,900,852,140,937,842,629,826,151,642,940,479,912,801,444,838,779,829,721,678,897,631,60,217,823,253,716,519,178,180,325,388,33,915,359,793,899,204,398,222,306,948,229,81,753,61,423,401,748,43,194,389,530,702,28,90,330,537,285,570,783,119,546,547,758,844,547,604,470,274,434,967,744,86,155,783,635,111,847,386,12,186,646,183,190,888,784,38,696,303,940,513,589,791,681,916,154,955,308,751,192,834,282,622,993,967,152,14,919,184,165,303,521,170,617,175,500,93,67,405,603,417,49,692,140,75,403,878,950,555,399,466,699,532,859,991,474,893,819,203,844,40,661,114,444,321,898,1000,544,234,131,478,119,524,600,584,94,639,354,161,657,16,933,899,426,958,349,358,512,40,984,652,673,785,572,696,49,993,531,925,570,679,632,384,338,606,809,519,69,844,778,672,316,729,634,901,807,42,139,715,788,380,857,781,455,853,316,812,695,515,122,179,757,338,241,494,342,349,476,584,156,446,142,798,667,830,286,430,725,920,767,369,790,633,270,589,496,195,306,989,881,242,271,361,459,946,963,503,985,429,19,916,974,929,497,333,97,982,319,493,424,75,988,905,594,808,774,720,247,3,813,137,908,652,699,714,393,757,701,44,554,534,962,330,402,598,115,208,561,16,870,614,174,417,882,623,853,925,767,467,415,232,799,720,279,478,58,960,142,942,59,451,708,329,589,303,688,53,771,168,482,622,510,892,792,999,206,740,125,366,571,763,252,582,192,521,935,929,725,154,119,136,520,731,300,746,382,572,965,68,622,372,940,760,365,392,369,679,193,84,399,708,332,958,785,738,255,485,687,6,559,597,366,356,866,726,577,185,996,570,951,555,475,182,156,912,408,187,638,531,31,768,885,871,753,345,638,586,856,892,307,487,612,530,805,641", + "624,571,21,716,362,262,171,784,440,777,746,754,52,657,47,932,608,527,968,368,769,950,52,676,856,344,105,686,710,517,448,730,85,952,45,611,928,211,725,240,499,16,588,187,515,363,304,827,751,115,439,879,75,23,628,160,6,716,669,547,738,734,680,361,51,929,535,108,322,883,889,811,667,521,912,590,832,405,197,516,31,706,354,506,849,561,55,433,479,44,463,722,636,11,403,564,41,233,431,170,528,469,238,744,784,819,379,835,801,659,866,697,300,106,859,591,486,160,498,510,56,299,192,404,494,857,240,456,337,13,0,980,246,430,524,61,345,710,992,762,667,181,65,117,239,768,964,297,649,838,340,572,122,939,84,232,807,368,162,602,512,336,37,422,585,896,410,562,153,696,205,341,827,15,690,698,189,419,65,210,704,677,102,655,909,187,128,438,255,569,929,928,93,965,543,262,587,331,814,365,607,110,80,271,182,723,845,635,62,25,853,997,710,73,114,701,779,360,149,839,613,298,386,425,369,67,475,739,794,330,627,49,173,780,726,654,688,157,969,150,833,804,556,851,202,709,521,639,866,556,616,835,70,282,609,988,44,207,201,126,519,874,116,947,78,999,367,985,733,432,102,170,303,36,899,328,633,374,427,89,686,224,315,215,944,269,818,384,19,179,236,750,938,102,569,304,185,31,290,275,260,345,906,368,983,784,629,318,937,976,449,649,605,110,869,369,513,591,290,889,640,512,759,946,211,92,329,216,148,886,862,87,353,456,599,621,220,705,161,403,782,238,178,950,610,144,797,980,384,406,470,299,115,857,770,758,31,511,775,152,294,219,579,872,981,91,27,899,923,118,87,259,355,824,994,360,235,997,824,377,65,374,755,486,731,213,511,522,913,118,966,138,573,246,747,504,899,164,270,241,100,624,296,307,942,106,552,513,753,910,100,810,584,987,885,88,87,301,479,818,78,551,978,318,435,401,959,535,129,419,640,80,981,810,665,215,330,457,86,609,549,491,677,271,725,937,279,709,55,377,416,738,345,919,390,37,929,26,209,229,435,292,50,929,694,418,11,664,699,651,805,720,787,846,279,82,595,197,688,766,864,294,946,436,978,503,223,504,819,202,376,285,136,880,145,703,518,1,74,5,150,343,234,613,964,819,528,376,584,387,444,56,593,216,660,890,845,605,513,915,4,308,916,787,246,976,2,201,359,259,961,378,436,836,247,461,580,455,59,116,864,138,275,159,325,705,594,698,364,385,142,799,349,263,457,827,501,48,501,221,383,581,853,197,872,395,653,838,806,190,322,406,169,578,346,343,340,503,348,672,64,296,818,340,961,630,547,922,725,722,966,92,329,545,239,46,775,774,998,238,822,943,602,500,821,493,245,263,462,471,971,295,335,548,779,920,11,467,262,170,23,26,302,821,142,792,284,510,447,903,928,790,918,761,376,592,325,967,856,778,616,172,421,900,48,691,903,219,498,334,213,921,628,592,257,739,781,226,508,460,849,933,234,326,922,588,666,228,433,905,357,1,927,724,960,281,280,834,644,24,417,48,455,407,221,419,74,547,921,391,939,326,640,736,453,976,941,406,814,290,186,171,282,617,833,810,215,481,369,104,59,924,823,601,491,405,246,320,156,301,55,583,6,480,563,288,773,862,160,369,364,851,269,254,549,744,438,948,986,979,505,609,930,427,841,472,442,168,835,43,316,859,520,150,838,92,37,805,314,592,734,357,610,339,410,284,624,904,85,263,644,792,478,832,981,799,305,6,671,860,655,991,774,695,889,180,362,230,239,831,809,572,344,771,297,951,381,377,215,361,852,892,389,477,494,304,781,757,432,442,134,296,320,501,983,304,768,551,856,450,664,99,785,748,3,725,483,555,347,176,90,584,973,840,701,913,260,761,907,404,968,382,461,498,780,570,97,788,421,136,329,839,468,645,945,473,244,895,746,660,941,446,867,997,263,512,468,588,808,835,435,233,308,984,854,791,496,76,662,137,637,882,520,968,425,482,616,713,248,858,318,712,411,829,432,801,748,814,684,150,394,994,268,530,980,268,194,158,411,343,272,459,693,808,400,956,685,239,189,885,759,995,410,907,90,891,947,349,516,562,598,90,689,233,610,593,913,125,688,784,957,296,952,951,140,721,340,341,889,855,881,418,741,772,765,990,293,548,758,667,390,481,679,100,435,144,643,552,487,235,89,816,178,241,569,570,635,691,861,879,23,603,111,444,509,867,951,635,511,950,564,14,632,230,533,296,86,404,495,808", + "810,950,223,332,112,360,814,636,585,542,585,444,258,29,376,259,719,102,54,223,503,763,814,505,770,654,54,140,241,112,194,871,477,543,712,694,493,401,730,906,760,679,502,890,153,993,54,590,336,760,448,307,350,285,856,448,986,767,902,255,815,78,990,985,872,297,876,219,16,825,931,482,822,937,275,945,159,169,755,839,31,37,706,372,356,125,926,642,197,38,24,918,777,112,14,841,91,594,294,57,165,925,507,724,641,128,730,334,153,568,775,565,750,661,85,566,90,283,515,497,110,301,425,610,552,516,176,198,173,146,980,0,600,714,530,944,641,687,502,725,140,31,842,557,928,211,112,379,169,714,459,803,919,840,240,945,894,972,668,579,28,233,889,151,412,207,470,216,105,31,972,755,823,82,34,816,536,896,395,844,955,154,42,432,318,759,240,411,132,197,821,255,172,736,192,145,212,796,457,336,772,678,620,556,50,621,883,595,816,396,176,935,993,138,880,613,331,197,582,798,165,737,607,778,686,730,972,719,258,10,893,417,136,841,505,397,918,270,381,425,63,217,260,838,925,923,439,435,538,72,858,379,461,351,522,905,719,967,773,821,839,598,144,981,425,815,93,740,297,876,608,160,331,971,657,247,362,889,416,393,742,356,256,351,921,965,100,769,969,71,373,696,632,825,163,163,204,398,325,105,187,905,432,713,488,793,611,173,336,380,542,147,33,417,886,997,556,209,322,363,986,466,729,953,596,269,45,656,590,192,464,39,175,809,836,296,490,434,426,687,142,270,651,975,148,420,749,572,845,34,492,550,950,355,944,554,92,687,907,249,468,363,592,983,378,552,460,25,349,405,448,824,806,261,326,87,18,263,270,946,233,749,829,474,297,320,339,59,467,260,328,937,201,355,725,724,870,880,555,180,759,202,762,441,855,389,867,874,349,923,405,808,660,21,185,805,755,12,909,630,209,631,791,326,187,532,900,631,965,578,188,341,315,65,606,811,290,561,450,222,595,14,364,837,118,634,860,321,250,454,766,478,932,617,264,477,277,692,254,256,249,682,654,106,515,380,12,395,984,323,850,479,847,621,865,688,145,148,35,406,806,409,842,177,18,151,730,243,189,437,27,141,763,988,420,171,438,763,239,706,52,295,248,872,281,426,174,201,952,703,137,95,810,694,739,127,845,995,727,48,498,609,365,615,327,133,463,632,129,603,25,415,3,514,724,931,920,436,751,294,418,417,280,779,336,330,567,499,880,293,384,456,740,838,45,457,964,908,95,815,670,661,460,907,993,798,145,601,353,327,132,529,990,717,985,730,189,189,226,666,440,850,439,996,868,127,296,753,334,462,40,239,928,751,562,536,329,619,743,312,981,642,676,457,443,95,107,438,545,521,905,675,32,91,248,283,423,52,873,723,208,712,274,886,67,962,105,634,690,417,863,135,577,442,773,305,562,72,643,599,461,157,960,19,318,926,902,574,196,193,75,896,702,323,885,621,642,513,520,624,860,272,691,760,445,114,740,763,758,413,280,603,478,997,856,479,827,441,370,322,125,752,415,349,583,689,774,952,286,799,42,561,562,775,899,735,146,566,637,348,694,848,926,909,119,590,203,6,213,624,690,547,455,284,494,71,833,336,11,679,870,86,877,328,181,504,548,99,490,157,918,442,688,224,569,107,48,17,196,943,188,140,447,72,485,919,888,20,695,550,833,981,444,92,846,889,377,507,842,629,569,888,163,31,745,107,505,874,543,314,894,612,203,825,360,21,785,433,38,163,656,378,110,264,288,167,813,494,391,7,53,726,150,287,354,595,102,488,576,837,738,369,552,844,970,705,319,608,4,891,951,853,577,516,267,647,292,89,106,484,381,160,737,847,154,282,531,442,278,745,144,782,741,274,64,976,221,770,188,498,924,53,997,727,561,264,60,837,438,528,785,99,989,488,142,629,410,320,849,863,419,771,958,648,795,725,639,605,465,157,934,739,599,325,625,499,951,419,402,402,857,787,479,926,474,621,98,570,482,395,711,844,785,36,855,679,725,264,123,509,656,495,637,626,154,66,673,52,934,269,721,631,193,358,650,421,425,517,433,945,240,695,258,698,805,335,734,500,619,812,449,592,909,881,197,522,492,370,747,537,390,784,869,656,727,354,776,326,604,590,98,975,317,769,418,161,466,685,907,691,869,389,514,632,17,101,333,866,372,153,246,105,657,852,64,980,649,792,987,363,414,307,644,491,850,149,43,75,695,758,487,849,515,316,462,629,269,970,936,457", + "87,71,921,189,154,209,737,61,514,287,828,321,590,630,399,356,532,939,330,775,763,61,48,949,160,850,36,549,28,147,89,415,188,915,745,872,668,958,148,994,120,527,536,794,743,738,884,63,486,311,916,114,945,771,664,214,741,50,277,419,818,553,450,620,617,902,294,223,276,487,338,754,176,629,435,588,293,775,263,783,337,152,492,403,270,990,110,501,101,56,374,683,63,965,450,910,828,573,921,361,771,916,77,58,273,884,69,186,136,952,636,822,374,357,364,756,660,630,813,482,64,38,187,181,415,659,919,853,601,288,246,600,0,929,65,734,786,629,769,732,319,334,464,874,977,491,832,411,961,574,551,988,255,101,56,869,938,696,444,266,186,442,479,586,989,718,967,764,277,836,310,892,114,40,554,443,73,770,487,105,485,414,103,583,511,333,415,582,397,900,625,73,745,713,983,661,754,70,779,713,545,723,381,968,965,409,564,135,849,899,191,776,805,715,19,968,92,607,937,231,291,221,963,334,981,612,994,292,630,321,656,861,284,131,282,384,904,627,644,1000,124,841,668,586,10,282,582,151,489,702,304,182,584,173,548,819,781,592,997,311,332,226,29,872,334,118,451,5,265,19,618,673,518,107,440,492,784,73,494,77,492,979,723,409,598,512,238,926,81,686,513,490,309,142,235,146,752,224,630,2,847,46,116,718,779,656,547,929,956,902,420,852,337,793,271,289,380,600,824,758,976,25,717,204,960,329,366,509,124,317,528,604,745,379,199,286,692,588,469,273,634,919,726,12,57,144,809,849,802,621,868,399,359,698,346,155,847,509,911,297,845,667,122,575,84,149,852,163,906,666,564,175,846,906,96,426,632,459,955,83,139,341,980,411,782,368,862,979,104,685,615,458,895,623,468,531,565,332,764,798,256,181,854,490,258,15,142,840,974,211,782,135,367,637,167,743,821,195,94,966,289,265,269,698,725,579,635,670,640,844,309,879,267,979,247,122,842,141,361,155,275,195,686,532,407,994,699,576,978,104,222,624,261,126,684,913,343,865,687,995,559,850,881,127,350,495,808,762,661,177,241,963,480,211,820,9,419,167,649,720,385,409,541,163,628,435,794,472,511,664,671,127,209,709,313,833,355,927,560,691,493,374,716,757,117,614,723,481,619,823,280,269,809,840,241,115,52,162,846,71,152,375,903,166,684,874,906,673,845,325,939,567,895,12,780,232,117,332,209,815,573,799,302,323,528,985,453,997,104,345,274,134,665,136,17,975,536,938,456,634,409,480,619,593,727,875,990,764,748,431,129,929,399,885,91,789,162,538,782,350,799,463,163,298,262,950,731,56,545,789,592,448,354,324,984,365,640,150,395,712,116,572,127,384,636,275,369,748,580,52,891,614,571,185,551,802,58,219,589,118,217,181,187,257,966,693,46,484,429,641,278,496,351,108,904,178,758,279,700,416,607,867,649,474,444,644,608,281,874,926,323,376,964,860,260,960,182,850,376,283,517,93,598,298,467,729,382,204,12,817,712,439,28,584,743,741,708,678,323,480,948,346,639,223,482,387,161,720,170,478,724,7,609,591,495,940,154,113,551,744,92,344,390,981,198,76,513,451,309,565,246,447,844,306,417,764,773,971,196,546,254,34,713,610,262,271,79,150,512,997,831,290,17,475,502,357,64,28,25,734,844,272,763,376,698,678,543,726,392,865,775,535,323,67,631,436,221,121,563,221,415,667,834,204,771,138,950,192,88,968,325,481,620,876,877,686,335,531,365,931,770,974,929,976,348,831,531,328,807,629,848,233,647,496,425,871,361,516,671,987,1000,118,565,435,574,603,771,197,104,769,786,262,259,947,785,614,11,978,375,213,64,194,786,764,891,778,593,406,689,845,572,775,241,72,703,128,736,508,336,775,936,99,537,335,100,980,205,9,7,88,817,1,294,30,355,706,947,687,781,650,522,669,275,858,389,22,622,360,181,380,551,55,536,354,978,799,523,150,479,376,650,816,140,43,558,386,522,288,207,368,285,928,692,582,760,189,600,167,769,943,827,862,923,786,628,987,24,860,327,923,484,197,425,502,620,742,522,238,926,629,938,157,930,34,595,454,897,746,563,433,4,836,125,989,652,800,746,952,11,634,793,283,485,879,454,759,122,933,513,577,292,239,781,884,849,816,345,592,149,468,534,408,279,704,690,112,767,675,82,415,239,429,794,591,720,423,509,740,313,122,710,608,72,156,965,656,302,663,367,865,495,576,275,607,902,172,794,237,516,944", + "62,908,353,908,430,461,834,936,601,627,929,709,651,903,926,383,365,359,872,357,630,276,463,981,811,491,969,197,681,874,391,631,455,349,470,815,600,285,393,598,584,474,635,538,974,322,808,814,51,452,436,915,334,529,315,846,529,353,866,187,264,238,338,479,317,920,254,446,681,612,940,512,375,871,18,303,198,772,396,605,138,79,409,115,386,936,169,295,126,473,567,610,918,294,143,522,811,102,770,675,138,277,449,575,962,245,411,994,972,706,440,782,201,336,783,79,840,698,481,390,492,756,55,698,281,943,904,327,624,260,430,714,929,0,215,503,244,422,354,230,943,706,431,135,997,814,814,108,402,165,866,195,798,151,541,445,495,661,298,921,606,537,555,880,356,528,99,312,18,554,874,720,557,159,733,101,497,965,900,910,777,879,277,924,29,593,849,183,295,23,87,354,201,487,189,937,636,89,515,356,641,587,831,309,567,495,298,838,507,57,736,546,787,330,438,982,632,23,353,248,775,785,754,593,612,21,852,22,562,862,64,276,824,313,740,314,156,856,486,181,979,352,106,512,264,706,235,238,69,702,474,923,176,474,637,738,425,317,178,349,349,835,84,745,379,336,933,541,799,272,979,404,431,438,162,754,116,269,167,814,465,329,981,266,596,657,214,411,444,931,660,19,615,735,101,128,742,570,593,982,889,647,278,147,473,47,54,945,871,710,518,867,568,519,457,532,737,144,907,120,192,510,211,731,368,413,303,70,591,72,746,171,655,980,539,918,490,680,781,604,823,884,438,862,934,682,702,393,653,365,719,777,157,898,217,346,381,926,776,973,207,782,814,960,383,86,897,564,754,352,203,331,128,585,719,771,539,994,304,960,287,147,367,37,658,207,230,108,976,725,775,893,339,734,799,719,213,367,50,576,896,360,983,373,94,197,337,566,644,470,741,362,731,498,966,594,391,450,799,959,976,239,638,494,704,269,180,370,620,824,157,950,345,225,855,440,315,232,40,822,385,513,2,528,609,954,983,880,610,66,251,188,467,885,795,260,729,899,769,904,486,733,648,367,881,400,498,59,189,700,914,217,544,869,215,522,428,877,175,298,281,522,19,11,551,860,345,305,110,889,854,771,516,232,739,776,188,212,153,434,542,642,816,303,457,280,580,593,879,771,323,439,695,664,656,103,617,752,223,979,953,952,25,435,464,572,820,478,45,80,631,365,231,924,498,392,581,277,360,99,548,49,265,221,557,199,105,131,422,564,290,527,923,684,9,286,873,23,963,367,240,894,272,215,46,206,860,96,570,477,898,439,332,40,750,417,756,49,622,876,991,231,367,513,58,497,478,427,331,575,100,558,143,988,48,813,978,150,199,830,474,446,598,687,972,864,889,970,459,856,707,539,404,15,43,994,296,204,11,342,83,753,191,737,282,36,360,273,705,829,989,968,771,179,775,599,272,336,781,313,789,205,135,692,213,105,372,626,478,535,156,972,286,919,962,309,825,821,114,7,71,809,29,207,470,306,676,344,489,259,819,986,831,362,562,756,784,445,242,722,218,642,588,6,497,781,261,641,589,728,361,311,942,257,994,577,363,584,777,327,962,962,179,398,234,236,10,245,416,141,579,778,860,716,787,770,747,378,696,505,553,808,688,479,193,589,540,802,941,364,761,130,287,357,432,840,569,630,337,928,509,888,736,63,905,323,224,365,214,878,476,844,771,973,276,898,658,107,394,914,944,319,689,329,450,483,638,304,518,484,69,568,874,893,23,376,848,298,92,808,447,83,662,752,199,998,705,281,854,787,147,627,452,832,158,318,492,315,697,701,659,955,345,946,626,642,768,621,94,166,978,416,501,738,162,207,12,984,806,424,578,937,774,649,790,455,512,920,828,619,366,645,957,745,274,594,505,803,224,916,597,884,46,327,973,231,719,544,856,369,766,306,366,483,463,721,150,204,740,662,132,567,646,708,592,785,476,787,698,269,69,778,362,535,359,798,848,995,170,157,959,146,411,119,519,695,635,692,282,314,114,408,347,766,567,444,924,580,582,702,813,98,725,213,789,978,437,107,468,711,884,681,377,587,192,119,874,76,864,295,234,586,207,494,714,624,656,32,442,79,419,325,584,696,23,124,570,600,549,97,79,736,217,978,24,326,370,849,14,865,471,933,521,610,894,22,672,625,167,296,186,370,133,706,123,765,431,830,804,390,516,752,18,350,926,98,196,566,146,284,449,13,235,999,927,145,304,414,906,409,180,444,686,422,157,185,684,456,674,853", + "218,63,134,819,25,756,185,794,150,859,102,110,441,90,732,296,687,344,148,305,380,848,97,609,270,870,972,736,337,64,527,167,579,328,95,948,672,322,776,714,852,46,927,57,670,149,617,438,707,267,870,520,738,386,163,391,421,158,356,494,490,860,374,283,385,694,691,794,575,593,575,371,282,504,184,588,685,741,747,77,638,574,245,408,380,689,628,217,989,966,135,298,841,586,61,432,144,621,42,483,303,836,669,292,571,504,554,877,815,307,51,267,798,702,580,577,405,5,538,911,615,516,993,794,131,349,570,505,124,842,524,530,65,215,0,931,351,515,330,549,44,913,645,370,954,741,328,342,958,951,631,134,278,865,556,728,408,493,205,690,960,84,491,751,766,855,468,555,954,703,598,30,179,880,804,293,659,713,555,521,314,580,812,375,901,153,980,103,440,206,570,687,396,412,164,175,246,581,642,219,718,519,596,223,894,34,398,747,816,679,222,116,297,538,689,649,112,238,501,726,810,212,396,531,824,532,354,818,191,423,667,460,147,165,550,41,994,986,793,555,929,290,631,259,935,998,102,53,806,880,970,912,868,152,276,849,599,158,618,150,483,587,950,614,173,297,866,816,880,210,314,268,511,321,407,390,558,221,785,219,426,663,928,410,523,686,443,23,500,707,549,194,125,623,67,820,324,793,523,928,505,879,566,28,850,764,656,778,419,899,378,261,335,396,984,143,348,264,373,291,166,367,687,355,246,140,340,337,157,576,59,522,252,562,610,820,656,897,424,796,699,529,371,807,417,861,764,209,831,117,921,33,137,613,706,584,111,575,421,605,198,207,189,518,89,93,232,66,949,534,110,345,771,326,155,62,579,243,550,744,57,343,690,483,927,225,757,479,682,988,63,828,428,267,918,172,363,333,381,292,278,407,892,899,653,632,728,758,855,778,311,181,912,733,515,313,151,886,825,961,195,328,160,529,582,305,697,427,827,62,771,138,705,165,351,85,59,466,191,180,14,192,585,279,816,204,124,761,916,457,829,92,927,978,779,324,324,641,998,515,820,672,409,850,923,108,159,759,107,964,123,579,277,104,624,738,775,195,692,203,267,328,825,664,327,789,966,876,794,649,346,437,496,861,541,350,77,609,722,258,11,32,645,471,936,264,125,55,351,44,799,250,788,546,943,115,405,989,659,469,760,273,845,601,268,810,596,684,505,735,86,26,544,809,657,169,764,897,948,674,408,843,576,363,967,392,750,348,801,822,481,934,311,469,93,506,212,169,643,809,642,28,560,657,616,902,887,753,775,334,68,245,66,650,501,382,584,887,736,432,81,633,9,422,626,884,905,338,70,725,691,76,985,23,461,414,918,246,698,804,966,948,341,426,542,903,551,118,823,766,885,312,234,26,237,207,596,380,519,802,268,563,304,127,776,336,250,992,813,646,175,769,206,952,18,828,226,225,194,475,468,631,603,611,382,743,770,240,869,588,34,593,655,866,69,756,553,85,198,156,575,506,102,455,675,584,560,743,644,585,214,413,19,173,823,995,484,319,201,943,860,27,42,249,657,968,846,437,72,675,582,2,229,441,450,298,449,128,725,117,246,443,190,153,894,337,530,310,348,193,627,971,2,903,673,534,805,331,11,150,184,21,584,792,483,672,967,61,431,985,949,664,890,415,425,713,518,538,22,903,85,621,275,100,979,271,982,323,37,209,161,945,926,826,433,223,937,23,647,10,113,563,186,273,233,953,175,850,976,832,594,110,294,402,750,1000,926,39,640,977,208,631,840,318,621,748,366,225,174,455,636,984,822,289,237,274,427,527,100,386,571,880,15,99,376,194,864,928,564,496,570,864,176,776,143,713,101,86,412,210,190,909,478,645,120,335,207,872,459,451,521,123,563,658,727,527,312,270,411,380,51,911,943,437,132,227,126,59,453,716,786,837,316,218,512,657,821,672,711,876,987,509,566,318,814,452,546,594,991,880,614,82,787,739,470,469,911,948,453,98,11,14,109,634,282,844,898,935,967,732,810,616,436,376,349,773,566,726,887,84,461,135,413,451,46,535,787,172,475,514,313,398,581,591,19,164,649,575,472,727,296,95,847,803,549,736,144,877,996,424,323,169,52,516,841,766,976,689,974,988,363,715,497,847,240,969,126,276,342,334,727,474,755,894,289,330,61,449,183,951,975,572,855,453,92,302,671,948,329,33,234,499,866,555,24,16,689,255,302,992,840,941,58,317,464,6,928,483,297,66,893,811,762,23,829,197,138,835,383,496", + "435,125,593,65,850,97,148,170,845,457,782,178,968,529,112,389,980,226,631,854,23,868,340,19,899,237,388,551,661,542,118,986,602,260,706,577,907,850,273,433,104,422,12,90,776,146,47,398,915,585,954,470,495,469,399,894,975,529,214,54,418,248,768,681,231,47,616,78,624,900,473,580,556,561,5,99,417,670,650,660,162,497,820,392,309,226,681,810,324,221,903,560,433,541,550,671,569,468,847,656,675,211,782,922,227,513,693,255,181,204,517,875,141,583,899,38,432,277,374,58,27,733,393,213,76,928,481,808,539,352,61,944,734,503,931,0,290,797,581,57,306,783,69,761,741,173,731,570,221,121,834,29,658,994,987,6,974,858,663,447,67,280,327,536,769,125,405,859,437,871,230,967,990,8,107,620,132,761,877,610,358,2,569,171,23,217,199,180,602,38,452,235,820,538,174,110,151,111,653,603,8,255,417,922,128,532,903,983,91,699,796,462,55,838,118,229,143,221,696,426,4,256,479,258,940,299,170,889,287,479,418,909,549,424,739,701,780,920,733,124,637,496,914,84,143,542,448,20,686,964,436,802,516,765,330,365,982,432,445,921,718,23,845,243,598,332,223,473,980,746,859,23,728,350,253,590,414,202,442,549,537,850,600,252,385,865,660,349,339,631,373,899,523,902,171,86,64,338,7,882,467,434,815,901,335,459,292,507,730,900,955,175,957,255,462,303,481,824,284,232,273,953,498,225,254,320,968,254,79,834,698,102,660,479,246,40,268,511,276,730,899,633,731,301,709,90,36,524,213,864,636,131,602,702,517,256,444,683,957,668,540,385,147,322,778,802,731,249,576,320,818,917,68,93,312,160,968,794,837,75,423,826,671,467,117,609,777,509,341,302,122,563,371,24,880,283,590,37,413,776,999,846,382,618,870,566,904,378,54,934,762,368,619,715,981,238,467,560,737,307,24,688,741,388,548,290,559,62,219,889,42,959,440,394,506,441,296,661,404,577,354,652,216,661,365,861,881,975,663,803,574,244,25,80,776,742,718,842,712,311,448,116,846,443,805,518,992,476,919,172,299,434,374,397,508,41,758,527,426,423,632,684,462,750,765,405,896,18,141,298,847,317,794,3,846,892,119,917,172,882,876,939,789,652,67,104,269,498,915,824,704,390,971,172,3,713,853,183,21,841,608,445,162,419,538,897,490,559,885,163,885,166,921,899,257,185,765,611,110,409,437,762,124,432,781,738,274,409,309,608,782,695,146,193,217,463,901,885,228,272,584,730,317,21,221,257,731,641,925,479,815,94,541,312,799,111,825,45,426,417,515,567,61,386,259,494,752,58,200,269,137,751,600,576,188,444,585,716,34,953,80,300,847,452,403,159,908,719,114,937,333,617,806,895,458,615,462,734,703,4,864,192,361,679,951,697,247,553,812,575,939,22,255,618,367,876,41,906,247,839,114,821,803,917,202,441,443,973,476,115,484,304,51,431,144,947,476,777,476,814,194,893,441,340,919,550,837,310,567,613,108,99,359,774,33,19,224,450,960,94,147,958,72,174,420,635,556,468,292,864,562,413,731,108,4,594,975,201,852,95,841,982,932,155,702,632,521,809,292,684,482,472,120,573,319,70,42,918,995,822,24,215,762,450,166,790,277,207,1,148,52,82,792,67,533,818,452,68,663,30,249,216,879,784,497,712,372,117,217,517,506,686,747,533,296,166,923,516,438,126,343,309,944,234,792,890,408,153,71,457,803,511,219,453,96,544,863,722,807,666,166,380,45,952,877,668,235,225,793,853,126,566,489,323,717,895,652,185,435,137,203,155,878,971,849,396,998,673,663,935,504,41,308,625,158,714,804,897,392,825,289,188,341,376,168,60,709,660,501,273,546,797,143,120,272,120,597,630,499,352,904,186,672,889,32,40,911,108,170,115,998,871,117,658,838,638,733,323,398,656,295,683,293,175,445,14,140,858,845,354,694,407,642,791,669,838,610,846,800,27,879,79,178,855,136,335,231,28,221,304,354,808,242,647,807,245,152,163,487,680,318,500,397,627,140,858,599,51,755,983,672,998,175,580,734,571,128,258,558,126,922,381,502,686,219,8,12,907,410,161,397,485,745,523,551,148,788,174,626,685,126,560,92,264,476,482,384,443,448,918,194,862,416,142,684,900,464,373,604,70,136,173,940,791,715,257,523,180,829,442,720,683,146,391,690,420,256,598,939,98,212,153,40,282,539,894,870,331,804,63,403,985,155,386,563,129,753,201,564,38", + "559,560,511,555,374,523,472,167,943,90,766,788,711,456,225,651,278,613,773,682,671,499,976,147,145,203,874,308,356,323,51,812,732,888,550,110,841,236,776,448,556,122,252,255,316,57,932,407,94,247,182,281,44,539,551,550,9,927,996,144,411,653,96,436,996,703,284,197,191,267,400,835,289,900,807,413,133,390,956,655,446,538,780,778,12,377,495,834,523,374,831,609,559,94,235,626,678,44,888,285,645,18,821,614,806,567,443,866,934,389,529,521,287,201,639,682,148,682,153,245,187,610,374,924,601,944,732,227,513,144,345,641,786,244,351,290,0,176,575,629,986,230,976,364,720,474,837,698,508,369,431,734,504,626,141,85,861,569,301,319,670,817,32,156,619,998,893,255,156,938,209,272,328,968,561,640,388,765,457,359,181,210,331,412,510,300,795,399,298,881,620,702,872,326,317,126,262,219,110,143,562,814,290,10,353,222,619,743,857,364,701,733,954,543,802,493,20,816,13,49,348,405,123,876,237,731,60,552,832,564,121,274,99,309,631,912,23,444,994,7,333,241,38,896,146,504,614,378,953,685,104,111,135,790,758,240,763,429,565,178,321,12,283,36,711,399,679,330,801,36,709,799,123,773,786,192,960,983,122,779,152,131,987,440,191,637,292,946,936,106,204,664,355,275,566,375,328,444,264,212,617,550,691,880,573,229,677,652,71,309,693,727,947,249,652,654,152,32,980,593,24,366,489,994,588,403,624,73,718,814,138,288,420,204,745,258,193,746,940,502,740,563,889,765,360,712,908,551,488,713,722,443,477,615,129,912,281,533,994,687,133,768,465,928,63,755,537,86,170,248,125,301,436,652,863,883,552,282,418,470,633,158,970,840,336,182,547,380,240,345,516,867,854,190,75,662,930,987,330,53,757,143,281,158,779,119,407,51,616,959,34,912,406,511,592,567,750,633,128,910,584,365,607,705,984,168,900,756,719,324,46,164,908,229,852,410,717,672,193,600,622,14,138,311,536,820,346,651,666,131,455,345,503,20,495,625,536,658,407,199,630,351,951,389,835,327,202,273,818,60,403,106,962,892,625,733,710,682,280,283,425,615,903,527,712,89,611,757,400,152,120,264,525,551,694,521,516,96,975,226,809,361,278,473,157,201,877,631,60,376,777,355,352,448,352,114,390,235,137,921,532,740,360,713,963,361,350,444,668,22,366,104,452,151,833,114,53,624,1000,741,200,884,788,541,204,706,988,567,78,634,351,200,431,548,939,463,416,701,360,450,682,248,50,536,24,357,510,8,933,842,793,533,279,589,337,540,660,53,919,58,455,795,12,753,634,215,89,560,849,168,739,560,911,487,295,128,493,161,517,357,925,700,58,790,175,466,762,690,324,823,958,428,677,517,620,536,782,195,590,423,282,964,725,3,896,94,36,243,483,393,190,534,848,763,85,927,200,347,771,130,722,905,217,463,365,843,780,752,851,303,633,511,530,817,564,382,288,101,427,548,579,805,175,559,758,971,919,295,825,33,322,990,693,935,462,861,338,36,455,151,279,832,856,21,555,513,707,925,891,855,335,808,658,383,115,414,814,779,521,302,250,23,648,82,145,546,301,496,549,476,185,283,345,941,152,778,295,879,72,939,343,30,967,765,70,574,199,963,810,680,220,351,693,185,781,771,399,166,851,139,617,258,887,127,569,821,106,552,445,402,578,546,92,112,605,597,373,216,588,742,42,317,788,392,310,213,252,309,93,532,388,558,658,782,734,472,824,422,706,395,579,567,856,40,452,242,718,310,405,895,735,623,614,112,143,616,244,314,661,495,743,262,434,954,853,655,517,851,451,205,312,504,920,498,416,440,101,976,934,200,849,923,388,522,695,737,402,575,57,560,420,161,437,24,16,691,906,165,279,476,801,324,955,669,613,778,144,437,236,743,320,169,112,245,619,783,341,775,921,763,950,849,381,909,151,211,389,962,287,298,564,493,396,273,12,686,440,273,427,911,724,733,949,561,772,408,425,743,221,584,903,665,521,302,820,776,160,648,118,560,174,926,919,245,750,970,134,856,671,882,102,608,253,349,222,604,24,948,843,456,252,145,400,747,607,926,520,621,497,550,696,833,123,203,719,76,858,860,485,226,517,525,705,28,819,361,675,364,781,658,164,724,335,421,61,803,234,337,865,809,47,725,276,981,256,349,802,434,255,72,252,575,861,133,323,671,133,316,293,888,687,600,303,195,622,588,874,676,19,303,485,295,867,6,973,293,514,826,974,190", + "283,335,430,158,206,220,479,509,520,342,478,787,451,379,176,275,191,390,247,582,17,396,652,647,116,850,833,368,348,661,644,450,388,448,386,168,819,91,773,652,536,735,241,919,274,563,767,4,202,765,595,476,115,672,16,629,187,231,704,326,939,229,649,8,279,285,114,723,399,142,350,796,828,754,889,712,114,700,361,200,652,492,812,11,582,380,608,466,180,909,485,924,352,627,818,663,377,469,671,832,250,594,656,899,289,650,780,805,439,46,710,860,237,684,5,125,888,368,376,336,135,432,862,499,27,876,645,164,133,636,710,687,629,422,515,797,176,0,160,435,672,292,756,320,383,674,250,210,786,444,447,977,479,258,403,868,102,245,475,615,791,701,60,986,862,958,915,52,164,208,26,734,929,54,935,756,539,989,394,683,743,672,503,105,304,896,27,850,142,425,148,499,482,922,87,184,920,834,855,125,271,439,546,928,610,527,963,437,728,340,827,165,368,169,539,890,73,19,455,819,564,275,978,946,657,708,415,982,131,271,75,995,976,569,50,938,863,845,975,495,463,591,629,602,544,190,200,521,352,694,542,209,625,44,392,682,297,312,236,956,18,260,256,976,399,29,398,843,632,442,898,845,912,779,248,8,965,142,232,599,49,60,740,529,147,122,362,192,294,586,815,616,607,410,35,52,395,53,846,968,969,744,921,618,429,27,489,545,951,828,726,568,208,777,230,113,703,553,933,257,515,895,725,682,303,215,207,597,180,844,523,141,198,286,970,515,869,49,376,258,905,536,468,587,259,22,505,636,795,224,672,443,992,615,6,107,523,476,281,880,836,289,487,975,817,559,216,427,893,363,459,457,476,961,145,256,685,691,154,156,766,484,727,942,669,977,746,756,149,331,613,913,281,670,540,752,967,941,736,148,621,4,987,324,854,118,896,600,613,55,146,415,617,949,58,43,822,717,584,818,316,80,115,783,606,821,651,756,232,824,369,363,338,514,589,642,918,718,946,83,41,768,680,597,955,806,42,225,979,91,754,757,439,900,71,998,880,245,764,456,54,749,960,559,593,685,193,806,40,143,719,956,71,359,437,382,102,418,160,988,939,813,409,699,678,247,491,352,70,485,398,562,714,760,742,663,806,554,796,395,123,345,882,629,533,204,866,952,395,265,889,99,797,803,128,576,460,736,219,219,576,70,113,88,527,506,508,39,369,971,360,555,728,577,160,913,227,394,752,922,504,941,902,331,361,800,132,409,192,860,481,750,956,877,562,478,570,557,590,291,323,521,584,526,553,20,830,366,36,311,645,222,6,976,553,229,962,328,552,955,282,136,24,520,215,157,819,663,924,836,986,168,694,443,332,377,356,105,344,469,264,310,339,997,379,823,536,989,750,12,602,918,712,235,233,344,507,388,902,25,617,44,137,435,367,957,262,863,247,40,570,626,56,877,659,29,606,926,25,266,593,193,627,950,296,296,855,739,788,895,607,610,847,924,823,892,779,977,841,536,159,304,534,226,148,749,708,502,733,784,594,829,451,822,198,204,527,986,822,920,228,346,412,803,67,53,927,213,858,590,81,38,571,347,98,933,148,979,448,743,463,725,355,928,397,955,865,136,305,447,443,826,488,16,556,614,639,85,398,977,180,329,315,76,361,583,150,468,714,982,881,308,119,693,56,945,280,574,572,19,344,700,227,832,629,712,661,336,823,558,675,209,413,378,196,446,474,295,795,160,304,967,722,491,859,578,11,850,3,805,254,258,332,603,543,597,300,324,899,700,682,643,288,368,881,621,690,179,702,384,304,447,426,586,173,300,458,199,156,3,99,492,454,7,454,319,273,185,35,469,382,16,990,931,192,724,659,322,70,763,256,586,411,621,322,554,807,72,144,468,806,463,983,201,506,926,329,267,94,515,785,61,443,445,884,659,34,528,976,657,864,798,555,389,28,903,81,112,258,110,127,327,97,219,472,51,793,602,794,909,623,980,426,619,959,337,559,969,350,564,104,742,823,506,731,976,124,267,890,767,524,203,728,765,130,746,940,116,884,343,85,497,398,850,795,901,869,423,838,161,993,650,204,735,557,902,460,268,443,274,773,899,268,26,547,404,964,458,850,805,129,344,740,61,479,637,316,846,900,203,320,137,999,883,767,567,320,560,33,106,402,720,661,80,647,93,141,396,367,691,33,360,366,188,531,103,213,930,914,61,686,882,927,535,766,874,904,336,687,457,120,458,40,456,94,679,349,100,605,838,742,72,85,881,894,449,937,919,658,623", + "562,612,516,438,544,821,969,986,438,314,295,271,283,560,258,178,139,189,854,549,708,871,122,6,410,107,433,133,815,149,296,235,620,75,798,382,521,809,177,864,995,105,448,455,53,271,571,420,505,765,385,915,538,892,105,26,918,74,649,924,842,852,610,585,751,905,706,490,823,461,679,327,992,630,409,78,666,602,618,168,508,266,55,378,616,77,35,380,588,682,662,647,698,988,26,193,244,242,803,96,78,763,921,805,310,247,623,763,757,525,81,686,205,56,575,857,950,973,220,933,42,590,550,125,584,69,523,468,320,590,992,502,769,354,330,581,575,160,0,317,140,590,46,38,784,651,461,70,834,674,322,907,358,748,1,654,571,313,592,410,527,571,638,391,585,308,279,616,556,759,164,716,584,916,381,598,716,36,957,973,629,867,407,696,554,505,144,881,290,586,866,471,884,270,629,895,649,697,143,58,540,150,403,487,540,62,816,747,41,926,509,938,412,17,907,618,227,163,434,774,884,884,881,978,67,116,210,791,902,636,377,730,744,700,713,726,303,885,455,803,400,749,881,982,887,280,337,788,207,997,644,822,132,934,332,753,47,265,236,589,995,428,265,770,23,937,544,208,728,952,834,295,272,23,98,825,705,751,25,903,883,768,879,85,563,314,272,895,71,298,250,207,259,293,71,289,289,372,23,371,166,885,750,144,433,53,671,12,11,964,295,529,116,253,707,683,653,929,729,894,479,749,94,855,114,458,993,988,350,843,752,735,409,242,857,790,339,627,341,943,816,399,278,321,778,559,52,807,863,315,814,200,799,643,769,392,879,448,207,65,847,200,45,122,30,608,800,574,656,220,263,677,854,568,950,716,556,806,523,497,130,702,278,663,222,298,997,51,608,656,862,481,549,510,129,177,791,983,472,371,582,807,156,126,171,732,342,245,467,381,874,632,87,950,74,52,755,265,911,872,281,845,66,986,707,878,565,627,710,550,865,78,880,601,307,661,1,881,948,473,335,600,428,208,408,109,27,67,745,443,57,314,672,345,486,415,731,106,846,203,224,986,344,913,812,182,806,470,824,244,282,661,583,372,612,422,398,876,59,961,126,462,11,611,874,166,100,545,39,717,96,362,987,455,877,753,225,136,428,555,781,119,568,258,291,597,79,306,62,718,102,334,208,709,323,860,796,439,297,714,730,910,743,39,447,887,962,451,104,791,999,811,213,703,190,457,334,888,962,85,332,335,180,372,801,921,774,803,382,834,46,85,458,218,265,872,937,383,855,393,19,44,963,655,570,568,267,342,164,239,403,669,874,781,229,729,572,858,613,235,31,606,769,809,125,319,474,181,770,412,268,215,944,540,273,681,864,284,182,345,723,856,479,872,283,443,183,74,57,477,446,704,592,633,683,204,505,823,790,677,523,622,385,800,949,21,508,748,955,216,347,382,42,662,672,999,661,561,814,721,274,85,156,966,290,384,925,412,395,273,585,571,823,954,372,228,395,746,411,47,784,649,481,247,922,592,933,311,455,374,787,162,279,110,834,803,185,226,859,919,402,631,662,612,40,362,281,697,636,970,371,822,52,534,17,273,193,461,274,707,207,821,411,740,959,144,319,256,562,623,595,314,944,155,413,559,690,119,314,122,843,251,217,262,428,337,373,844,949,438,265,435,783,457,515,170,514,954,260,561,432,795,138,698,755,636,761,865,463,397,675,371,621,455,582,358,48,745,789,83,8,925,609,835,488,900,81,458,701,792,315,977,121,92,383,236,945,846,419,67,333,718,692,543,56,562,103,436,183,965,831,391,281,467,492,322,157,189,619,101,53,280,742,800,545,566,192,581,491,158,995,776,392,762,343,910,890,501,439,707,131,470,696,829,237,327,556,624,275,873,616,519,181,241,148,540,649,229,147,192,748,845,481,795,486,651,976,645,997,77,543,837,451,586,404,415,391,901,222,36,699,818,969,710,629,102,999,206,149,560,314,556,943,870,83,269,402,905,306,981,118,639,665,868,397,949,880,334,85,537,3,518,519,118,516,716,521,721,142,654,754,22,690,52,278,969,980,693,112,895,953,11,665,72,802,859,978,384,573,219,993,341,762,288,994,380,369,541,702,805,206,591,600,18,998,35,960,281,214,901,658,458,723,327,399,610,409,694,364,222,202,955,2,936,970,271,392,248,784,499,533,639,198,91,320,740,311,392,733,224,133,788,490,408,1000,830,144,352,126,372,396,742,527,808,62,324,967,995,402,441,103,427,940,311,188,901,161,551,339,124", + "798,16,646,681,833,140,463,13,947,568,512,923,906,32,702,549,92,327,632,693,154,87,182,2,246,327,970,666,438,88,715,902,822,824,286,121,40,63,610,113,770,411,926,310,948,613,391,889,370,436,203,780,12,398,936,351,40,912,933,665,240,873,597,383,857,226,585,374,47,712,564,583,278,159,223,443,882,560,160,42,976,455,474,796,847,936,191,490,644,734,711,556,474,992,745,536,727,577,278,447,221,712,4,157,843,472,197,656,117,202,174,273,326,576,483,746,899,705,128,175,207,883,241,967,308,211,543,273,77,893,762,725,732,230,549,57,629,435,317,0,251,532,19,465,810,839,90,742,567,459,333,780,36,397,781,763,780,818,769,728,391,641,230,32,999,699,843,476,985,734,829,350,86,65,481,673,325,649,623,710,328,331,450,158,288,605,519,890,809,122,198,16,225,849,886,667,496,800,75,692,794,347,864,528,947,734,35,143,568,912,94,302,599,270,256,942,251,797,189,89,668,232,429,663,50,511,293,19,762,588,305,889,158,886,12,701,326,993,892,704,301,392,292,306,68,405,6,545,803,352,489,330,127,7,898,624,995,73,814,508,40,777,414,561,352,898,401,282,867,960,959,688,437,515,548,520,279,994,88,296,121,878,734,722,678,754,225,764,940,511,192,12,105,192,568,912,785,700,242,98,292,84,848,149,53,946,820,60,284,301,138,579,347,302,500,237,294,564,715,437,424,775,833,536,265,54,687,200,972,775,992,438,801,363,713,476,602,524,172,488,593,722,746,130,751,352,161,944,506,213,35,909,556,174,873,743,277,842,243,220,349,264,884,25,792,803,239,568,352,856,368,251,660,740,790,816,836,843,304,516,741,218,631,660,142,442,161,575,27,480,54,547,18,981,346,402,738,322,858,294,702,812,652,807,652,624,118,686,44,816,847,732,549,562,323,775,869,422,805,651,845,249,209,956,9,633,765,582,6,98,59,429,334,887,879,174,826,236,531,703,669,872,518,255,326,313,585,668,212,307,77,998,946,575,530,250,631,926,219,6,496,15,520,25,325,809,528,480,264,251,729,787,733,484,517,825,226,960,872,921,596,622,128,929,317,41,209,303,345,104,19,19,831,954,248,61,979,848,886,965,126,395,379,842,201,698,595,337,597,378,951,554,746,88,23,103,564,715,459,130,584,645,563,746,645,890,89,905,718,59,700,513,540,668,739,703,630,93,630,686,766,173,961,437,418,58,726,865,429,236,130,187,237,507,545,604,371,448,70,861,914,392,117,352,150,481,334,843,557,462,127,206,745,395,181,136,552,486,451,900,451,358,413,695,621,401,826,108,586,251,833,691,774,676,437,12,763,431,640,956,403,656,413,523,653,872,977,21,638,948,433,492,519,704,832,245,643,563,456,518,718,694,924,301,98,686,927,265,644,407,295,703,619,132,796,966,247,853,693,63,446,895,716,556,872,331,832,130,736,199,196,631,827,783,832,863,658,184,87,821,476,228,745,929,446,868,881,513,347,851,788,428,987,739,73,592,530,702,52,291,880,992,350,897,232,213,64,762,696,543,608,501,280,140,118,860,398,223,547,256,166,567,226,760,68,833,728,989,677,334,503,906,129,682,199,574,583,177,638,53,407,794,152,690,39,522,738,491,781,427,684,340,276,513,184,575,94,903,172,469,127,695,858,15,427,473,563,106,296,894,168,480,55,435,419,443,156,980,786,249,278,266,483,884,763,958,581,299,237,551,694,141,93,301,454,198,82,544,197,553,98,4,278,601,981,409,296,311,431,506,601,707,562,306,635,179,974,620,34,956,13,234,852,314,599,491,665,78,217,23,243,318,256,346,518,879,461,854,138,605,681,212,307,791,28,441,95,418,713,601,706,81,355,35,395,644,192,871,279,182,571,228,600,953,115,5,685,907,92,717,216,992,710,374,662,366,337,912,856,840,389,730,348,504,878,401,863,106,648,258,462,950,445,925,103,879,861,159,411,304,419,811,505,356,287,65,191,993,458,88,249,412,919,519,264,474,589,823,346,853,945,961,909,116,234,682,892,884,193,823,112,596,579,45,984,442,334,544,455,808,883,244,332,270,353,866,874,902,317,997,792,653,185,689,317,776,891,903,506,128,955,854,594,778,971,254,894,36,767,13,514,575,555,265,639,19,77,145,234,794,668,37,742,872,72,191,121,254,836,828,86,949,413,653,620,442,863,970,881,487,513,806,81,66,744,78,448,837,774,836,58,508,220,322,498,919,716,890,935,160", + "349,296,640,78,198,285,751,375,309,326,484,880,890,748,647,624,852,413,999,373,427,15,203,568,271,586,263,48,444,520,523,804,788,971,634,790,941,12,671,383,834,810,884,539,669,419,768,479,381,775,827,651,953,978,178,426,362,29,669,858,849,110,612,948,635,977,921,139,126,176,17,524,744,759,854,196,835,38,570,321,636,260,611,515,271,609,497,658,202,681,686,932,774,868,742,317,918,686,369,108,562,610,755,15,518,928,511,16,692,927,202,268,784,710,866,811,67,276,756,585,8,318,372,222,641,210,208,931,748,654,667,140,319,943,44,306,986,672,140,251,0,63,630,532,985,622,807,872,708,650,242,242,119,813,133,869,692,178,439,756,728,444,711,274,855,130,897,882,922,10,341,450,974,359,230,587,332,547,771,499,157,985,167,397,72,398,31,491,153,860,257,976,432,764,582,764,712,807,76,617,581,947,631,250,184,115,95,518,669,43,232,58,101,582,534,363,834,720,527,849,679,574,679,482,968,838,807,449,4,886,932,457,760,194,148,80,675,292,333,945,605,353,209,549,576,772,907,122,170,221,216,464,703,278,114,985,120,578,238,432,392,339,153,939,342,695,684,358,115,592,321,26,614,604,896,202,306,639,287,287,5,937,214,159,83,87,368,118,975,165,876,577,765,118,550,223,100,624,37,486,26,584,273,246,79,370,758,376,159,662,248,261,17,228,345,502,90,547,530,189,115,535,524,217,981,679,11,499,694,651,352,875,612,766,431,655,936,894,368,204,73,615,540,390,29,774,538,417,104,344,313,249,107,946,598,509,656,161,422,714,478,4,240,664,678,462,448,586,344,177,724,225,350,472,18,922,162,852,474,171,928,213,253,767,485,447,975,910,243,684,351,748,699,451,467,726,961,846,389,555,807,368,258,467,309,89,786,906,227,157,652,898,797,217,732,625,371,685,542,608,458,183,899,480,374,861,460,937,817,614,124,248,556,437,598,560,452,182,61,453,965,491,357,89,744,59,171,158,100,387,699,945,575,293,442,465,844,602,974,32,890,552,832,494,645,254,428,592,191,883,692,856,72,952,686,198,885,863,947,701,35,54,961,257,777,817,112,901,256,949,804,709,989,366,420,413,616,812,853,865,681,656,453,75,706,641,708,621,271,484,761,470,384,896,586,391,44,580,159,670,253,551,986,572,666,635,899,843,416,888,998,330,145,991,548,697,596,481,735,652,518,39,633,946,113,416,775,609,942,964,359,604,129,43,393,693,294,457,245,782,915,601,979,105,118,429,322,429,714,175,871,392,760,648,891,627,446,450,882,244,241,989,192,617,988,288,630,809,385,514,285,593,549,981,766,825,634,380,61,438,717,897,985,687,725,22,483,824,178,479,157,556,725,870,275,118,198,621,79,275,341,632,169,753,589,26,704,980,883,889,457,950,180,950,318,300,747,235,227,732,629,574,180,747,125,230,963,50,438,20,518,426,290,345,73,471,514,384,439,599,808,837,250,249,632,86,433,743,71,744,789,223,831,50,83,17,900,496,678,656,528,124,883,672,984,672,71,362,173,482,871,437,155,444,218,450,141,637,528,302,181,71,874,819,877,278,887,922,434,797,929,932,402,545,284,768,979,510,653,157,323,927,707,149,211,583,358,623,757,648,951,49,55,234,208,581,585,691,535,611,421,5,780,192,747,507,171,860,466,305,522,546,910,23,295,618,898,267,812,127,505,913,486,880,957,94,705,825,366,547,289,330,319,84,510,499,262,666,860,122,750,74,591,301,638,803,191,813,919,498,298,709,361,630,21,724,195,882,705,379,1,252,646,225,743,347,684,378,292,162,882,202,549,554,145,606,785,399,769,801,841,48,152,845,406,261,595,592,916,342,652,480,319,319,48,815,753,656,315,998,946,319,50,368,894,70,420,435,671,417,129,124,367,365,671,124,644,951,895,933,467,908,122,448,150,36,881,982,983,83,15,815,942,60,843,541,539,190,880,883,562,709,634,861,104,271,856,619,244,997,620,759,667,31,592,141,965,402,345,473,934,944,885,778,668,943,141,109,83,340,238,49,762,3,267,139,473,469,374,401,669,244,33,986,488,182,581,482,918,335,817,615,839,552,870,508,920,210,974,838,539,412,954,36,949,662,171,782,157,807,9,720,70,279,28,764,156,296,699,442,870,288,76,720,605,249,374,902,495,374,271,189,995,798,274,832,955,324,692,389,706,881,974,803,91,487,779,465,560,46,710,825,786,273,223,33,171,168,153,152", + "201,884,294,447,844,367,379,779,441,952,542,858,172,629,849,102,34,267,466,326,964,366,535,709,696,731,582,113,860,814,535,563,93,592,580,590,558,129,35,317,303,444,965,738,772,245,694,727,289,745,294,321,45,343,778,935,377,546,605,450,430,123,898,417,994,449,743,234,63,825,197,799,63,444,175,739,743,791,772,794,758,555,589,973,493,597,600,706,666,739,194,528,159,195,115,421,296,202,860,508,589,146,428,234,43,457,410,989,317,780,973,582,504,783,113,464,423,377,144,986,848,471,922,858,686,949,104,342,916,669,181,31,334,706,913,783,230,292,590,532,63,0,856,39,725,224,18,943,809,208,35,528,659,158,264,408,951,665,958,42,641,782,53,177,952,184,147,488,272,324,57,474,369,747,643,448,612,623,683,628,936,373,997,298,217,770,666,540,247,665,62,105,425,14,449,93,252,169,546,188,702,505,497,551,379,115,224,217,871,173,176,36,571,942,576,503,388,210,808,22,802,585,512,787,500,604,638,404,163,171,652,639,105,818,381,459,421,118,731,391,178,772,144,210,907,254,744,376,182,58,60,891,809,482,495,129,37,260,192,682,732,10,413,101,224,433,940,425,536,967,891,206,870,768,263,389,640,100,833,643,999,560,212,311,96,359,720,846,852,198,581,319,508,53,707,288,888,387,788,505,489,459,212,149,664,963,361,713,340,516,459,234,852,112,755,157,949,317,919,943,437,876,291,28,533,715,393,456,129,323,388,478,799,83,935,953,422,410,604,754,481,11,408,173,21,74,739,229,418,254,456,989,46,966,600,74,376,281,841,510,232,872,980,580,303,337,684,208,144,418,338,183,308,249,121,632,17,168,299,177,836,103,834,459,973,865,524,604,795,993,770,554,126,626,472,825,364,657,200,292,326,357,462,428,788,912,570,545,935,304,245,951,546,434,848,172,339,40,791,890,397,713,205,309,179,910,308,386,9,403,286,173,734,740,971,97,451,834,829,84,176,179,703,611,108,321,621,288,234,409,711,543,563,64,296,313,161,532,724,902,618,213,102,100,945,386,305,907,606,108,945,991,881,934,458,523,414,201,659,199,546,971,422,582,647,720,964,740,386,172,772,110,605,590,754,491,701,139,674,277,583,192,519,259,617,442,424,736,184,49,260,355,652,627,856,128,856,670,129,862,990,125,679,113,468,299,393,688,202,67,610,924,694,602,347,171,797,447,568,439,713,404,532,945,754,112,279,492,794,786,320,477,43,448,350,467,702,529,529,463,135,171,323,761,693,631,580,465,870,299,831,412,865,467,945,664,577,339,729,101,429,723,169,121,624,593,944,458,588,796,55,642,381,402,973,259,759,869,259,628,644,57,110,476,841,25,44,158,300,597,610,409,145,954,557,17,967,377,289,20,522,487,285,711,323,401,914,390,784,437,386,797,198,433,486,436,56,438,280,717,279,96,723,132,644,750,396,312,607,726,629,57,168,664,589,107,358,402,28,406,393,788,379,953,565,41,357,485,868,901,437,132,69,97,312,196,110,549,880,804,300,491,929,150,762,100,73,337,681,135,593,918,633,43,449,497,406,429,863,446,316,245,691,547,351,535,770,604,103,523,25,299,621,674,955,849,587,449,578,222,48,268,180,21,287,687,642,863,392,996,737,657,835,359,305,584,154,357,830,388,718,120,481,472,462,759,739,995,305,894,736,81,911,534,221,200,922,181,156,335,427,519,926,181,101,847,493,923,564,81,32,987,363,853,189,37,238,881,785,770,47,645,405,644,846,106,744,147,279,769,935,973,991,538,603,318,200,254,709,996,348,320,734,523,872,640,204,910,454,154,430,474,58,144,572,21,426,448,581,315,23,102,361,545,678,567,770,287,480,685,212,410,996,305,433,512,129,910,198,939,727,203,43,620,91,951,701,825,403,283,482,139,871,919,650,798,908,448,494,504,625,131,407,897,26,778,842,909,642,100,134,51,741,735,721,855,685,290,206,463,961,784,37,607,696,496,531,234,138,16,219,696,884,966,962,545,584,568,380,580,654,96,983,336,711,580,432,716,242,42,369,471,502,929,767,521,359,347,220,376,835,157,246,515,310,672,592,791,623,331,400,665,753,88,497,134,239,509,926,186,358,706,220,474,984,856,449,179,673,568,381,722,404,62,628,570,917,692,968,448,166,234,344,118,173,468,775,370,235,886,859,32,471,664,963,474,277,905,985,513,25,102,85,906,421,813,139,729,683,250,605,774,397,359,51,880,627,461,458,872", + "383,446,623,931,658,287,202,478,43,541,210,213,416,629,288,291,768,669,589,337,446,261,808,661,231,452,365,317,570,621,731,620,593,958,584,779,137,170,338,977,239,357,307,787,43,753,86,952,748,639,940,426,613,171,287,519,173,949,814,500,735,267,859,492,255,73,739,850,886,123,81,367,637,606,787,231,865,751,963,870,716,910,679,314,953,356,658,242,102,985,809,923,911,574,443,321,404,767,71,330,736,809,39,864,846,308,483,266,935,919,683,24,899,420,885,261,847,533,629,509,785,770,641,255,563,64,978,625,520,967,65,842,464,431,645,69,976,756,46,19,630,856,0,667,592,355,429,3,166,141,25,659,435,371,389,179,540,711,358,381,803,46,795,467,587,740,523,41,381,831,641,815,301,225,476,690,578,162,264,390,518,134,218,552,248,720,940,486,453,578,15,517,702,507,499,868,785,245,261,495,85,391,133,434,892,986,384,125,914,148,176,274,444,718,597,865,252,246,728,607,275,877,379,123,420,958,787,85,593,829,336,822,142,256,233,135,412,461,372,571,771,641,102,174,757,90,450,313,65,660,500,875,349,825,121,926,670,898,844,87,794,368,425,888,842,567,868,662,250,234,829,475,536,613,294,165,367,974,99,297,911,866,531,197,653,852,285,353,31,52,997,361,980,433,961,957,241,766,604,323,337,933,270,73,251,374,67,877,511,718,182,742,829,188,41,650,345,422,140,15,324,358,730,374,255,9,144,206,148,539,896,132,967,512,835,811,97,254,83,77,846,716,593,394,412,889,291,334,321,531,453,234,861,90,375,729,578,5,423,635,313,620,983,863,956,786,438,348,284,917,801,382,759,703,867,82,570,375,717,362,463,743,896,194,793,314,708,803,558,771,765,27,481,149,33,115,622,460,248,819,907,658,948,303,824,816,202,701,495,530,705,495,20,224,812,362,429,747,472,877,975,985,941,423,798,932,994,197,632,207,942,205,445,166,590,699,970,111,90,616,105,543,932,876,552,201,120,187,311,13,790,604,597,394,89,744,558,38,464,492,19,528,998,809,739,853,740,784,290,527,506,451,974,87,944,645,27,841,31,399,826,415,859,520,689,100,839,714,744,379,964,944,696,517,534,910,426,185,201,618,246,346,289,404,7,342,458,459,476,618,336,699,675,605,898,799,576,214,501,984,117,673,807,783,540,584,457,839,14,855,507,646,63,905,766,296,993,883,398,462,958,118,338,156,217,676,948,154,55,149,298,755,908,254,656,320,13,318,568,380,937,783,35,645,220,400,276,810,39,560,923,153,244,583,8,463,425,905,497,572,599,802,961,317,580,58,920,945,345,280,551,250,13,249,251,321,412,545,826,83,880,70,828,905,348,995,324,838,642,575,206,388,109,987,547,348,154,42,504,923,80,272,501,614,277,341,266,632,450,844,412,23,318,58,739,199,69,278,40,443,105,452,124,21,37,348,936,212,260,787,6,915,171,518,541,800,52,590,8,186,510,82,239,384,488,914,841,616,660,837,502,813,598,849,832,487,499,852,759,366,200,977,767,554,47,464,508,570,414,695,787,384,50,965,174,766,986,180,532,372,71,507,840,952,575,670,515,985,238,887,731,875,435,846,846,413,307,712,973,470,390,380,415,469,20,523,124,989,905,356,936,642,878,939,766,771,486,848,853,925,190,995,481,167,878,334,710,913,778,549,251,815,103,105,97,826,347,773,425,460,651,919,835,962,202,898,909,454,963,125,674,57,909,17,462,936,718,941,691,723,55,86,210,794,292,876,678,430,91,366,630,549,311,643,800,969,506,465,471,508,454,419,839,53,638,872,26,120,879,752,505,807,486,713,386,221,312,886,763,303,585,677,407,886,539,208,270,49,272,405,247,143,948,287,979,308,359,491,892,72,563,820,22,37,234,908,449,488,230,476,635,880,526,989,92,482,249,447,255,699,439,88,981,669,819,753,660,388,955,498,698,318,124,928,811,545,713,733,554,460,980,683,411,808,697,877,689,695,338,326,892,259,52,582,838,452,386,396,906,947,189,831,898,368,28,833,32,526,175,260,33,154,710,233,748,523,242,492,494,920,424,5,609,71,100,362,877,180,187,444,828,342,823,862,878,498,211,816,472,735,217,294,737,185,613,207,445,820,500,470,573,999,693,602,552,768,735,442,351,783,795,901,441,519,80,602,855,251,350,339,890,84,213,69,222,98,46,476,105,919,519,603,154,155,619,153,40,305,367,181,146,157,935,430,691,574,145,932,595,214", + "249,530,203,721,692,922,58,393,680,216,58,818,632,795,149,911,784,63,948,706,436,986,108,704,914,550,131,917,20,134,861,192,277,582,596,492,9,51,150,628,335,720,455,954,730,322,639,261,509,254,692,268,321,585,305,426,47,826,492,945,475,781,502,906,386,28,139,634,575,684,709,8,62,11,165,27,801,947,919,157,69,686,643,703,28,715,194,241,156,249,979,472,323,996,4,859,890,507,564,842,308,388,522,356,195,738,10,713,103,468,378,878,2,794,193,904,913,644,718,648,751,820,301,284,504,127,565,285,56,99,117,557,874,135,370,761,364,320,38,465,532,39,667,0,192,766,458,641,400,831,864,772,332,761,540,735,643,978,580,409,489,299,746,720,982,241,336,979,566,331,809,437,979,917,320,112,970,359,613,338,448,841,518,710,318,50,168,452,496,950,385,205,707,150,516,533,205,790,966,250,529,893,679,20,559,500,13,93,448,935,339,795,967,127,184,74,966,262,74,318,174,528,354,810,813,575,641,1000,786,299,774,400,989,577,111,875,890,467,118,488,697,838,497,127,233,464,22,935,93,960,837,49,503,559,75,930,601,977,726,498,458,739,807,363,827,810,917,468,516,756,425,811,393,404,293,448,828,550,766,571,410,210,313,445,985,115,124,606,748,152,619,724,635,485,683,285,917,673,970,203,795,43,144,144,748,131,246,351,606,520,200,174,877,617,794,548,610,43,907,485,546,325,205,514,720,840,614,165,466,621,278,705,803,263,753,59,453,657,960,620,646,832,98,768,257,967,346,39,694,600,328,38,122,634,634,828,344,184,13,868,728,644,723,129,223,207,644,421,22,754,713,423,921,196,961,837,195,664,478,76,768,684,316,616,697,182,305,535,287,437,789,667,807,909,461,294,511,531,54,413,398,901,814,426,120,530,172,64,707,256,980,631,186,116,759,641,535,559,702,419,985,489,692,30,520,564,583,930,583,876,610,861,521,894,279,382,331,637,121,119,447,546,289,203,558,992,417,876,684,830,460,333,270,465,703,985,60,72,294,958,618,265,497,973,366,345,7,588,734,408,631,395,888,615,518,995,746,60,280,547,241,445,151,401,899,341,577,654,379,991,844,999,364,826,644,215,154,340,775,463,989,669,825,795,798,615,637,39,879,977,538,687,603,62,407,147,254,408,441,869,371,60,144,962,292,451,567,19,99,934,573,831,462,921,209,269,927,175,177,359,43,781,25,646,61,899,259,522,526,804,589,800,438,582,387,896,98,442,19,569,161,491,923,697,770,831,200,57,505,958,133,447,123,647,39,116,547,517,620,718,580,20,484,492,439,821,936,658,587,459,764,513,945,992,707,123,335,788,721,35,606,103,62,746,241,127,157,807,535,546,449,804,699,910,306,776,495,490,10,769,434,813,207,153,685,949,679,580,949,761,26,233,38,428,416,699,9,160,461,665,993,751,473,352,598,663,292,352,856,203,447,625,594,122,974,107,405,711,977,653,254,164,909,163,90,7,4,885,682,943,505,201,319,680,964,885,414,871,535,979,254,374,610,250,136,248,710,709,941,176,125,53,231,421,976,617,648,205,361,176,309,332,642,986,978,603,661,192,342,191,49,227,518,856,789,201,689,238,218,633,875,33,8,474,787,70,284,723,569,363,653,399,266,49,209,424,236,943,463,368,15,81,677,674,632,136,367,935,539,151,562,165,919,996,883,179,18,962,447,222,479,205,738,326,252,410,428,955,945,767,732,639,445,511,906,982,565,657,533,337,625,692,595,450,573,909,434,566,171,225,974,261,177,759,230,585,193,7,420,286,303,340,293,720,671,459,257,501,497,255,803,843,266,496,22,416,920,457,918,941,117,82,994,296,251,233,778,808,320,754,479,549,596,593,475,238,850,992,861,736,698,592,633,238,216,854,392,94,832,711,55,826,61,325,696,410,707,777,421,838,547,407,156,734,141,942,851,274,108,625,792,906,227,376,134,160,534,325,925,977,677,564,153,789,434,459,510,456,837,678,925,855,513,478,459,984,610,574,737,957,331,842,596,900,433,338,997,178,614,848,18,186,653,192,450,52,835,985,711,402,623,514,579,490,656,304,751,710,169,462,427,817,503,655,24,931,338,576,307,987,858,438,429,816,640,196,778,503,9,131,433,646,293,577,857,550,40,699,183,898,180,149,618,262,438,878,143,832,939,211,498,584,139,227,724,543,222,516,105,542,965,183,893,141,773,276,826,796,116,910,628,183,594,950,864,552,124,877,275,844", + "69,622,717,183,135,213,855,292,725,593,727,463,677,890,199,218,627,543,295,361,56,992,19,54,436,810,300,496,33,855,878,481,721,430,589,871,327,416,725,332,915,536,197,994,583,614,392,61,34,760,671,180,790,413,412,551,735,282,403,652,377,621,420,218,83,173,732,662,347,392,60,643,673,292,654,873,123,354,952,260,206,440,929,377,446,890,349,891,536,418,301,66,607,175,697,879,590,311,66,886,638,316,764,640,536,210,197,402,719,678,102,339,82,716,268,913,923,688,111,83,838,952,468,569,331,117,903,616,465,851,239,928,977,997,954,741,720,383,784,810,985,725,592,192,0,280,349,302,448,648,272,151,764,487,946,675,765,581,765,455,987,180,685,753,774,333,990,896,65,35,733,562,859,614,875,665,834,294,533,117,450,885,455,695,637,60,97,714,737,576,651,839,626,688,829,133,850,801,748,411,410,388,695,107,207,481,276,919,915,389,202,390,234,653,994,578,558,120,852,514,45,692,464,860,48,801,557,857,671,804,603,61,445,141,862,6,897,990,910,294,96,786,713,765,722,977,258,823,968,348,393,581,151,876,443,94,746,111,615,794,914,151,791,709,271,442,877,4,683,982,191,173,725,995,964,597,491,975,887,169,525,8,100,912,547,498,129,484,282,178,386,961,209,852,73,931,529,183,43,211,38,145,306,999,859,668,933,631,476,672,470,419,211,191,755,111,164,662,506,20,565,882,947,978,93,883,25,375,441,800,683,673,191,353,984,221,228,159,13,395,740,663,659,941,114,414,511,580,998,857,537,343,681,826,544,176,696,328,214,157,804,385,950,99,71,744,654,576,230,106,815,891,489,412,587,579,605,299,718,505,458,167,154,899,886,721,986,206,47,987,798,326,981,445,482,277,644,615,414,136,815,69,447,730,284,440,849,529,547,712,414,96,32,587,164,705,738,893,661,270,316,71,392,488,92,371,697,447,993,242,17,54,169,642,81,10,292,591,312,574,631,548,856,912,650,888,318,838,383,203,465,625,418,7,863,8,536,299,94,810,487,944,738,773,528,327,479,965,207,815,415,656,991,732,285,125,858,7,232,5,706,595,513,413,222,26,37,587,26,336,214,678,915,260,950,24,925,870,780,184,930,630,84,615,626,44,349,436,527,89,336,273,524,697,584,50,130,842,561,267,592,487,237,493,383,762,75,917,386,132,233,487,107,258,975,730,300,399,741,650,393,237,935,530,801,755,141,593,614,20,503,271,886,553,333,522,188,635,836,752,731,412,42,946,585,333,126,758,645,719,473,201,957,801,423,567,852,840,765,564,389,186,517,11,550,354,214,161,20,832,388,987,434,625,326,544,631,76,91,651,29,21,801,726,400,27,39,272,230,912,466,46,499,642,545,141,818,378,422,152,614,714,362,634,597,651,778,148,387,208,142,796,853,363,374,721,689,796,263,52,463,925,162,558,921,946,959,646,728,750,822,183,334,581,458,791,912,73,202,788,851,647,454,577,921,567,945,383,374,497,593,932,576,152,676,378,376,13,653,166,139,918,594,448,24,863,365,666,926,749,141,184,605,92,693,80,738,246,414,480,82,721,875,906,636,421,589,502,165,641,211,705,48,982,830,270,933,827,901,810,663,614,356,488,499,435,898,456,966,815,848,247,677,442,125,417,70,604,619,633,252,774,799,44,8,157,24,866,297,382,203,866,851,477,740,52,317,247,518,753,87,121,152,904,841,899,445,570,864,460,361,126,307,720,613,493,726,781,583,90,156,860,222,829,53,972,70,214,367,970,742,451,469,137,619,929,19,394,836,904,657,102,808,870,771,525,238,285,41,634,33,700,63,439,413,564,441,514,10,527,500,315,711,635,418,126,187,105,324,406,554,240,217,832,324,31,299,643,867,252,921,824,638,245,942,736,467,262,70,789,406,656,118,321,711,632,945,282,315,89,203,131,663,753,380,837,10,867,309,35,623,666,755,166,969,204,292,921,866,215,749,579,971,960,225,275,83,702,990,403,955,648,505,340,217,518,857,566,648,618,955,790,938,557,442,603,351,691,685,40,389,224,612,166,613,51,9,969,202,160,834,651,852,849,476,436,193,836,572,966,848,507,948,868,820,434,398,828,151,334,700,346,708,873,729,218,640,131,300,964,491,615,812,551,19,167,979,748,258,436,638,805,502,332,45,335,410,591,937,195,202,985,671,415,294,635,25,624,463,540,997,622,448,758,870,120,233,960,793,213,949,965,536,596,257,118,767,700,286,868", + "263,121,762,377,85,359,233,552,146,909,292,238,774,766,493,471,691,301,626,85,554,650,356,775,140,451,222,11,638,29,356,528,878,383,421,51,309,486,834,611,776,495,511,851,614,785,76,826,584,726,807,415,295,276,222,602,883,424,37,65,300,949,39,533,124,403,215,85,855,250,449,346,275,183,719,7,755,620,519,540,319,736,404,830,520,961,512,391,833,224,87,739,427,949,703,628,924,772,486,127,481,668,223,999,71,954,535,394,698,265,866,791,132,86,544,923,832,70,977,254,49,545,440,88,570,701,847,668,905,342,768,211,491,814,741,173,474,674,651,839,622,224,355,766,280,0,895,884,467,577,178,929,230,93,436,301,576,353,539,912,254,239,264,398,220,704,278,942,233,621,649,220,447,809,874,910,638,903,706,14,994,170,385,135,330,308,99,242,555,434,477,766,635,815,193,166,268,854,266,749,837,302,925,484,683,789,987,762,704,850,582,316,195,938,170,801,553,6,370,9,183,341,99,133,207,460,444,551,722,645,181,920,906,716,311,440,383,846,350,487,661,396,489,836,951,115,992,442,717,927,647,604,58,63,575,849,722,524,630,657,306,389,496,619,787,254,46,213,621,380,788,436,424,883,472,212,188,811,777,582,540,224,262,570,779,348,662,238,452,839,335,833,565,561,867,678,391,365,457,698,858,930,905,732,130,996,904,571,751,897,790,86,760,476,956,141,769,872,420,343,221,224,304,451,27,295,332,918,303,45,287,695,694,179,843,375,688,764,354,655,667,272,651,559,328,357,305,990,968,821,771,268,554,510,311,117,349,161,913,298,368,830,752,776,951,320,189,485,24,94,708,154,501,215,455,367,189,7,853,286,749,298,21,509,233,148,997,56,598,542,838,149,32,815,917,755,71,878,459,656,991,591,801,157,971,130,410,141,1000,99,661,960,782,1000,892,1000,247,636,507,338,890,346,132,658,713,126,503,523,40,363,633,988,985,759,869,534,399,227,162,377,322,203,404,51,676,657,64,942,358,442,53,196,927,962,90,215,790,696,144,292,747,840,222,992,798,368,261,367,80,385,725,305,554,123,677,838,785,521,894,647,401,975,12,484,466,909,282,341,752,737,730,291,99,350,732,664,834,641,393,335,473,904,625,287,110,66,930,58,865,760,46,992,620,942,252,530,800,354,703,768,569,636,946,402,369,903,273,375,633,807,362,622,392,225,549,599,774,929,427,959,386,380,401,884,814,513,318,380,671,776,754,552,381,652,268,671,606,524,748,627,585,802,616,926,413,404,405,298,661,253,452,90,775,563,947,856,367,206,695,638,633,992,588,706,669,21,247,760,437,5,720,932,952,589,911,22,597,296,453,56,727,87,622,928,179,260,805,510,994,90,233,821,654,18,910,177,194,674,78,83,96,377,643,536,755,462,676,966,895,329,545,106,504,575,916,689,825,179,981,850,69,136,788,484,56,735,853,879,137,515,725,86,725,59,698,94,506,446,986,787,466,637,754,179,203,176,63,890,897,980,888,530,923,738,718,831,830,166,779,351,906,310,994,503,409,232,78,738,230,747,668,108,129,240,841,416,403,376,841,10,450,67,182,112,346,898,667,695,484,314,9,994,616,54,662,902,260,565,360,809,122,430,196,782,472,99,491,952,247,23,344,22,57,856,917,905,513,769,12,989,418,284,430,78,641,903,514,356,392,713,463,641,266,33,405,369,979,157,592,404,790,740,267,669,739,666,303,194,506,875,483,323,33,774,356,207,7,563,652,756,237,487,91,470,607,244,833,314,905,238,372,704,414,409,878,107,576,166,739,325,161,310,776,37,624,719,508,690,72,891,229,231,359,305,716,673,121,645,846,546,305,407,297,750,921,999,433,372,744,543,630,183,604,790,643,973,388,472,333,446,237,715,625,267,165,713,524,250,503,763,664,735,645,444,441,500,92,673,295,474,167,474,618,111,865,37,638,412,247,960,320,662,752,11,663,164,208,712,950,399,700,893,672,564,175,511,156,969,563,632,594,128,46,467,493,305,987,681,752,140,80,922,117,34,402,845,573,557,236,122,158,173,627,220,816,889,398,140,199,939,2,719,60,355,430,319,877,705,256,858,130,703,812,469,114,503,858,858,320,698,413,372,934,661,444,990,224,571,117,221,171,431,561,294,728,377,290,323,948,983,801,826,624,230,879,162,337,482,906,339,32,87,583,263,365,488,494,275,944,538,250,832,541,59,992,936,20,641,662,534,930,136,765,117,984,150,282,832,97,835", + "415,742,715,333,377,961,826,119,201,164,704,241,433,557,908,841,447,230,680,130,746,515,898,311,805,167,15,736,322,429,171,470,758,770,815,506,302,27,274,740,781,546,132,803,853,24,397,742,372,697,19,712,762,425,4,129,418,201,985,639,149,368,144,332,545,620,276,882,181,245,729,56,957,612,518,902,882,651,618,357,609,276,269,50,630,831,813,7,246,440,500,87,670,867,369,310,407,867,475,545,326,204,78,413,787,374,883,870,475,651,591,330,790,978,686,845,457,844,688,332,179,418,844,423,807,289,288,9,124,578,964,112,832,814,328,731,837,250,461,90,807,18,429,458,349,895,0,175,750,29,983,188,116,316,807,870,591,444,992,889,661,255,328,437,612,137,461,95,195,892,296,960,917,928,256,942,355,680,931,409,881,424,797,629,172,589,384,29,33,28,207,577,731,486,669,485,986,158,798,649,540,132,806,574,337,485,951,837,243,988,346,370,128,938,959,895,135,717,502,930,666,430,389,446,488,316,804,822,133,303,515,646,512,786,67,260,50,479,873,466,517,478,21,177,502,870,462,105,609,802,749,79,843,209,133,538,174,907,179,890,317,81,315,914,757,251,618,849,425,497,179,442,632,155,514,4,921,516,773,403,765,847,855,386,300,342,248,301,304,199,172,906,541,430,652,609,273,319,227,18,722,301,757,362,544,214,421,212,373,876,181,375,992,549,844,361,699,388,70,412,150,965,543,387,975,127,264,106,853,470,549,285,687,278,278,604,944,741,718,900,683,382,708,60,976,901,505,369,680,962,879,594,528,295,389,889,272,299,327,886,130,990,995,752,918,467,658,74,495,966,566,45,750,548,175,95,948,835,910,931,57,529,341,512,286,929,592,745,968,287,723,74,168,468,379,694,742,358,567,755,443,142,807,677,126,536,538,530,222,141,688,80,76,760,50,640,786,325,125,26,335,651,258,167,899,160,760,264,290,630,365,880,204,292,290,685,546,434,965,826,472,564,148,860,69,418,123,782,515,86,650,82,191,625,550,609,139,242,330,4,215,789,413,491,611,112,58,818,711,658,922,351,477,422,409,640,940,817,884,150,410,270,372,77,123,626,862,20,710,317,487,613,296,62,52,271,18,539,43,563,752,44,63,325,904,915,898,481,163,76,653,728,962,539,769,510,257,10,788,985,774,888,576,760,675,9,670,9,842,691,467,153,825,903,696,73,159,405,177,215,749,5,99,881,771,322,4,859,606,624,29,948,992,796,348,357,320,170,60,136,408,142,741,500,838,79,334,305,301,190,175,17,893,696,564,420,468,677,16,918,889,618,238,484,862,690,349,488,132,975,454,706,54,246,205,817,400,426,230,981,561,157,343,929,551,869,375,811,82,98,81,477,588,215,824,16,387,891,812,595,56,952,909,292,613,453,561,983,991,516,43,766,727,659,625,724,934,934,582,542,979,713,569,33,797,816,466,112,361,534,764,654,864,186,512,687,290,700,726,348,959,227,142,785,197,320,376,521,81,745,573,570,813,414,906,986,538,498,628,400,414,693,294,146,711,384,951,335,564,714,583,236,418,864,775,551,541,112,190,994,406,772,138,667,207,994,204,570,419,410,209,80,252,718,519,59,933,432,123,639,762,702,125,498,742,212,570,230,767,796,427,296,680,488,978,200,445,663,152,395,661,998,116,470,204,113,866,533,119,310,872,477,991,852,735,250,84,730,890,899,305,864,779,368,570,814,984,587,820,868,912,805,241,930,510,647,951,144,595,121,610,609,22,961,538,625,71,854,779,838,443,580,329,76,769,458,337,642,614,185,397,327,762,373,901,362,180,283,875,286,591,378,98,49,557,95,114,851,819,873,664,738,506,369,683,241,329,28,216,378,257,468,719,445,406,748,76,195,167,398,115,142,93,358,162,163,175,64,926,693,227,336,42,424,43,579,631,366,458,10,240,688,978,557,862,580,58,95,248,529,347,701,191,104,243,828,591,344,85,221,537,496,818,453,850,36,730,62,695,945,475,366,642,493,332,615,759,440,228,205,507,948,277,304,364,317,775,175,208,242,196,177,382,239,384,977,49,861,163,83,881,263,45,847,993,811,98,599,38,372,922,109,524,255,362,958,404,1,667,933,585,855,682,913,324,509,577,167,893,570,433,727,636,557,400,396,277,449,404,118,334,393,881,860,652,199,188,771,627,264,759,395,676,339,664,529,424,372,35,587,609,32,503,353,768,909,920,187,792,794,312,478,348,206,732,7,629,111,126,99", + "961,378,496,839,546,319,245,960,407,816,596,242,108,208,733,909,74,373,535,39,643,2,23,963,679,72,167,489,717,127,899,403,237,18,548,48,913,919,600,167,703,589,303,469,584,180,674,536,906,517,112,408,274,432,602,131,93,63,213,161,830,667,290,878,585,459,420,951,534,321,921,795,745,818,691,211,336,664,697,706,975,860,780,767,114,91,908,947,618,217,673,363,801,287,109,944,125,584,521,189,481,839,822,858,324,449,553,357,444,653,719,115,328,540,581,832,561,952,179,271,504,663,72,611,108,364,641,595,842,178,297,379,411,108,342,570,698,210,70,742,872,943,3,641,302,884,175,0,394,34,634,173,564,256,603,255,767,381,672,971,116,994,782,715,168,710,459,29,719,469,894,808,590,477,140,281,477,452,327,602,228,927,942,746,922,815,928,695,394,57,670,103,610,282,228,503,263,961,738,443,814,234,556,544,86,390,40,734,394,635,624,888,966,967,203,67,473,795,901,888,695,525,949,677,257,21,387,322,446,753,727,249,43,699,886,33,916,179,210,416,521,390,708,916,194,106,379,361,146,943,226,302,280,188,212,729,613,170,697,328,230,266,411,288,607,17,230,613,350,357,988,666,49,958,940,157,330,772,782,900,535,462,460,214,418,993,961,932,707,427,757,326,232,26,639,275,567,586,301,221,918,573,809,316,928,421,832,223,871,860,620,297,285,652,817,194,631,9,810,197,865,495,172,107,274,250,143,357,361,36,332,495,347,63,94,409,244,64,759,55,420,728,451,333,855,216,253,346,955,730,19,833,865,635,380,501,488,691,759,910,702,355,277,105,281,382,932,710,821,901,343,936,381,898,515,394,448,736,448,818,30,59,53,86,423,425,820,469,494,342,206,841,6,269,257,291,240,471,808,391,91,612,206,893,217,399,976,391,159,619,394,17,303,337,931,697,948,870,648,136,238,126,36,153,625,985,205,893,227,265,332,952,158,696,835,83,919,920,214,291,79,441,697,502,414,45,892,207,156,778,145,142,187,640,529,541,293,210,715,698,673,840,187,15,658,802,313,729,261,830,838,278,230,4,227,870,605,889,581,347,390,749,136,530,38,630,195,115,691,279,971,767,759,910,894,582,903,571,866,279,478,290,537,944,667,466,432,528,571,436,119,68,987,107,844,307,17,598,658,909,884,10,981,159,883,139,994,462,401,103,102,136,616,520,505,483,150,969,979,736,742,40,225,80,807,922,38,982,523,780,833,95,77,900,617,813,995,865,551,698,317,657,181,680,213,821,341,314,591,738,582,565,787,157,337,615,933,409,620,553,648,867,491,679,814,575,706,358,789,694,194,190,744,257,347,676,855,392,450,90,491,438,260,959,483,107,792,459,46,739,291,115,948,915,553,305,614,663,978,414,776,467,661,788,902,774,887,854,975,54,964,937,291,286,84,41,669,151,717,199,688,989,221,662,280,85,249,203,639,429,137,206,66,536,143,438,761,633,697,16,705,279,313,799,326,157,961,988,527,540,274,967,900,615,613,945,665,97,62,404,454,578,436,675,88,474,354,291,722,933,20,186,853,717,906,883,177,146,676,532,94,846,933,910,529,634,431,1000,29,941,368,896,633,115,863,787,309,916,7,156,359,619,977,831,568,842,203,324,302,263,369,118,639,186,428,976,359,628,140,827,707,122,568,490,709,655,436,819,683,518,339,448,197,676,917,65,572,531,88,991,597,553,493,845,840,269,619,626,405,505,852,702,580,164,348,118,123,599,359,439,263,987,341,777,190,699,263,905,44,548,560,458,280,979,296,353,760,891,674,596,93,297,998,913,12,336,466,235,346,157,390,493,607,561,796,455,633,788,77,628,156,73,633,114,278,17,113,730,70,738,759,574,104,706,942,693,174,219,831,785,264,71,229,860,469,700,971,395,826,142,228,150,229,681,997,433,485,954,618,61,725,352,5,565,295,119,443,387,641,567,251,375,753,932,870,639,942,783,457,771,507,721,261,522,356,15,578,674,352,231,145,690,800,534,910,343,807,780,233,504,367,49,302,521,130,804,98,629,599,22,800,766,248,766,810,559,262,878,252,183,120,284,594,281,570,420,118,67,608,515,372,361,778,390,646,213,915,928,991,72,129,172,488,268,324,365,896,983,26,698,185,146,751,931,271,343,256,217,169,756,577,957,421,292,719,538,741,970,992,731,933,563,54,762,606,353,744,344,735,789,631,346,976,925,25,820,515,898,264,325,725,938,942,696,580,265,449,917,172,147", + "56,816,442,570,260,674,408,292,364,460,371,389,677,680,864,306,46,437,14,581,333,397,769,388,173,907,315,173,812,938,782,605,217,751,727,218,697,494,583,875,436,468,647,285,924,286,603,995,718,785,328,429,309,548,637,817,293,28,796,24,710,36,302,185,979,175,388,22,44,769,834,6,29,109,837,16,656,802,227,542,313,918,824,426,343,344,911,405,58,274,719,794,832,76,733,157,221,973,128,28,880,915,880,248,116,792,125,174,413,514,252,607,326,645,970,411,236,171,291,223,884,525,577,237,902,164,129,209,97,628,649,169,961,402,958,221,508,786,834,567,708,809,166,400,448,467,750,394,0,58,373,558,146,141,899,379,805,868,404,349,749,813,976,903,799,301,741,994,915,33,743,909,423,786,362,897,587,768,937,271,421,88,878,260,218,665,514,118,847,333,418,617,962,571,537,168,719,941,103,432,886,724,929,713,74,376,732,561,81,31,741,143,266,799,953,605,967,39,888,478,767,511,150,337,92,656,446,469,266,657,798,788,922,942,772,596,637,110,143,741,914,508,737,642,396,945,91,637,684,468,800,974,767,789,969,794,349,102,387,366,816,632,763,767,381,331,152,246,74,111,948,200,495,748,867,411,900,617,138,243,822,733,933,100,737,968,795,76,648,657,989,892,639,451,714,583,31,874,343,596,918,450,749,458,390,198,255,774,105,182,458,729,747,661,990,606,936,182,770,24,694,24,781,776,407,609,677,544,275,885,657,19,146,62,779,929,289,161,986,41,617,693,997,452,168,921,131,760,867,189,171,872,675,164,293,33,115,682,327,566,592,332,760,923,249,372,906,787,196,320,856,875,280,727,806,550,974,360,108,92,178,332,420,548,217,137,955,605,697,968,999,732,442,693,515,950,933,919,412,451,69,248,453,667,737,294,241,54,799,816,736,767,34,256,414,71,941,756,773,329,201,124,654,903,349,14,315,102,386,807,483,280,839,348,705,130,6,518,776,123,265,637,736,987,203,42,175,707,949,935,827,375,858,996,426,192,162,278,943,241,676,763,916,979,532,616,291,813,854,918,200,631,4,437,236,677,490,297,233,442,978,822,158,108,74,72,411,25,373,463,100,619,826,103,714,424,420,930,503,347,251,595,157,640,985,630,804,675,934,900,781,770,874,422,787,550,210,537,604,306,229,598,385,635,672,131,800,382,285,994,710,30,368,240,553,320,809,956,734,833,517,176,974,97,491,956,9,669,313,632,923,37,511,441,453,131,91,779,164,299,506,5,786,993,775,768,169,588,738,930,83,82,129,399,126,665,274,739,540,979,584,110,552,826,103,205,137,927,758,771,656,872,745,504,649,968,395,679,447,775,572,616,301,223,764,253,986,415,109,46,595,548,675,679,74,949,457,308,457,36,439,231,897,793,968,894,528,63,900,406,920,994,815,155,916,296,416,91,937,325,240,465,180,315,606,869,442,818,725,889,157,569,974,8,860,21,670,503,94,147,527,565,960,968,284,660,678,438,524,720,862,5,754,811,991,655,323,184,637,401,349,644,367,14,50,885,87,285,299,684,685,107,830,283,179,530,662,390,712,696,975,505,373,69,601,74,912,286,52,160,272,364,813,302,68,758,168,77,611,399,958,271,409,454,539,377,765,503,927,840,45,35,195,303,514,232,810,700,367,248,592,592,162,302,227,95,584,958,468,615,375,234,105,542,530,842,640,128,553,307,778,95,605,18,527,133,623,806,890,622,764,949,95,65,652,901,680,231,549,948,902,143,763,207,299,941,690,770,416,206,288,266,843,624,222,360,256,202,780,788,261,823,55,67,600,792,167,649,772,380,373,954,38,635,772,609,798,58,231,469,311,928,159,641,2,630,764,567,256,217,8,447,887,908,746,444,463,549,504,672,387,762,353,413,499,56,926,980,766,94,660,903,479,92,305,990,567,291,596,508,115,939,615,300,538,50,54,675,337,371,91,923,269,634,450,288,401,184,943,420,897,839,335,613,655,936,199,82,122,407,496,550,909,683,45,671,245,385,158,245,791,779,281,52,202,599,629,236,678,69,388,552,158,149,161,694,336,721,196,908,673,220,84,259,399,233,488,833,178,761,375,260,443,247,815,988,843,701,887,989,375,128,997,516,337,566,498,909,822,815,264,59,243,947,222,921,325,471,454,434,170,417,725,308,639,147,705,105,993,795,610,476,841,733,367,431,458,810,325,161,13,906,549,476,841,509,345,549,983,880,141,91,474,957,905,711,276,351,170,224", + "755,616,11,636,736,229,345,334,388,891,828,35,398,979,180,185,598,17,267,475,448,983,409,678,582,497,733,399,351,920,944,897,361,115,276,753,22,798,59,997,557,965,83,307,581,790,216,996,155,256,276,201,541,741,568,634,501,360,699,853,577,339,797,603,27,227,226,596,845,251,698,286,202,680,800,12,927,575,238,899,667,520,109,8,309,685,978,461,490,977,660,210,487,976,707,712,149,464,244,556,198,125,237,423,796,616,445,453,771,236,973,169,935,975,535,368,544,278,489,400,110,399,847,35,239,257,580,470,221,81,838,714,574,165,951,121,369,444,674,459,650,208,141,831,648,577,29,34,58,0,570,306,342,369,497,748,914,766,767,883,184,458,652,530,497,156,820,900,545,348,527,180,164,684,541,841,434,56,512,407,853,999,745,246,634,19,571,627,691,541,814,419,950,360,457,448,965,50,757,113,836,76,324,660,516,346,239,363,354,51,895,607,891,325,113,258,668,92,910,498,136,196,17,521,497,544,864,572,235,251,808,928,41,547,483,575,558,542,891,163,555,687,995,139,897,146,695,940,679,881,208,98,732,495,891,129,796,289,682,388,901,521,719,153,114,404,59,690,509,855,419,496,12,444,39,228,410,366,443,205,4,523,367,867,747,79,534,172,603,235,934,396,487,208,968,619,148,241,110,148,821,836,176,249,397,429,30,834,865,54,143,523,368,26,31,568,374,607,617,44,319,288,441,319,81,486,906,217,469,439,195,922,799,965,80,232,126,120,12,388,334,304,930,748,545,647,329,170,664,374,173,880,616,693,48,882,610,573,586,981,342,261,928,330,729,855,17,813,865,829,894,932,467,402,802,952,712,962,847,548,379,824,955,376,840,740,489,296,807,513,973,50,138,629,973,793,431,183,798,598,950,332,583,536,444,220,891,393,720,111,823,113,676,955,870,708,539,77,266,350,970,451,300,821,250,684,538,562,268,150,244,898,426,336,712,764,303,86,267,663,299,227,261,591,827,290,699,784,185,101,621,677,779,427,591,202,221,565,615,367,536,809,672,968,524,207,738,576,374,21,610,439,590,983,522,254,665,507,995,62,882,214,605,266,241,862,32,879,589,993,382,454,240,987,924,695,735,100,871,63,630,764,895,839,285,142,161,900,775,226,28,134,909,485,503,192,568,895,407,650,406,371,105,848,759,441,426,365,446,220,607,954,279,290,947,379,828,811,227,992,645,425,852,640,525,112,35,107,970,654,429,649,582,957,797,478,194,120,878,477,167,587,237,2,427,604,743,814,564,84,473,195,967,688,700,17,258,962,182,198,276,342,219,770,44,163,266,397,625,386,675,444,123,264,56,646,907,351,737,185,340,152,913,390,75,165,315,14,903,645,232,465,606,280,880,615,192,464,497,305,493,487,255,450,569,874,366,735,841,64,80,300,671,556,262,46,484,420,929,836,573,632,287,749,629,782,86,682,777,399,25,498,715,146,932,560,629,379,163,779,707,31,535,101,225,266,780,142,309,717,180,17,271,435,453,969,338,228,16,467,831,47,802,394,396,666,71,267,771,949,413,312,314,856,368,790,81,370,144,896,923,42,316,242,223,121,860,497,398,809,2,723,322,968,312,437,657,508,273,293,938,581,879,110,807,468,808,946,85,679,317,231,517,103,319,292,782,550,28,447,12,967,27,520,232,24,125,728,314,804,178,345,376,901,254,792,227,517,358,959,243,886,264,910,86,781,620,87,251,462,405,45,422,388,387,413,586,491,784,796,178,508,806,48,908,425,643,562,748,512,140,633,901,437,361,741,525,698,122,183,72,993,151,38,56,447,324,518,710,156,475,616,604,905,502,621,735,671,392,750,525,282,64,136,261,333,839,674,221,420,327,497,100,136,680,84,227,367,967,588,966,4,716,496,27,830,377,768,234,197,624,609,810,586,160,261,848,581,184,796,244,939,892,834,861,403,215,23,102,800,953,401,570,174,790,363,451,145,832,779,89,455,822,809,779,303,920,901,581,171,995,555,258,173,69,419,743,325,443,638,917,73,414,975,558,823,464,623,299,7,743,993,49,950,119,139,608,48,456,954,395,761,951,477,916,4,145,535,168,7,324,880,138,527,137,638,641,124,99,128,243,801,926,263,254,163,510,980,615,573,563,480,362,35,105,441,602,601,616,197,853,211,71,12,744,294,248,172,252,574,831,849,299,605,274,599,896,210,273,156,10,705,76,729,559,31,415,111,826,222,748,925,178,641,999,93,524,509,503,600", + "616,307,113,296,21,245,736,973,855,999,238,682,220,556,164,587,475,381,211,889,739,215,399,497,29,670,156,499,276,758,520,850,815,540,442,295,793,244,274,60,48,937,686,790,589,673,723,737,204,652,290,238,51,799,820,212,496,937,547,336,574,692,837,400,122,52,346,268,679,204,735,766,592,765,928,544,933,681,738,424,904,380,720,225,366,913,870,225,216,287,177,586,893,773,527,315,642,554,885,849,630,365,124,9,371,253,826,657,597,332,199,884,810,238,195,89,400,988,634,457,481,490,938,622,444,423,47,701,369,484,340,459,551,866,631,834,431,447,322,333,242,35,25,864,272,178,983,634,373,570,0,383,751,268,898,485,281,371,874,492,739,512,372,100,918,266,184,422,710,796,183,578,107,21,290,868,934,987,978,305,366,629,305,615,791,949,79,988,215,727,245,574,373,544,95,651,32,83,355,42,200,538,527,493,222,325,560,159,33,850,283,464,865,364,734,502,275,643,251,482,639,759,663,539,85,71,875,490,969,81,875,731,246,598,548,958,879,132,994,145,452,404,991,939,50,144,500,162,527,957,384,268,647,106,810,257,740,527,624,860,115,320,95,951,56,849,589,690,557,696,684,579,607,747,510,810,375,272,627,378,20,978,953,240,178,691,199,534,408,767,265,642,339,638,620,341,747,349,682,72,441,313,236,478,698,347,969,770,220,18,509,992,515,688,372,103,336,683,856,312,3,851,570,684,874,998,948,597,240,944,542,886,248,67,707,638,273,848,261,952,405,346,983,272,339,848,621,933,288,945,515,806,423,343,460,147,76,400,505,138,953,903,734,559,351,685,730,340,122,207,851,953,661,803,620,743,990,601,165,236,360,253,668,691,851,53,174,66,719,611,217,245,455,171,898,318,300,983,873,797,207,931,155,588,738,674,876,678,845,548,256,388,106,279,295,417,703,740,259,530,995,154,628,867,265,941,967,51,322,842,824,845,842,100,218,426,469,592,600,560,129,221,907,78,979,52,739,193,398,87,919,621,226,45,399,763,604,408,719,684,902,563,862,423,753,995,516,360,713,947,257,228,402,633,866,685,264,44,600,327,712,176,872,356,425,104,636,545,204,236,286,537,307,941,156,923,397,214,948,492,488,869,503,791,293,219,859,895,129,145,79,990,272,892,624,466,892,686,968,716,766,156,355,477,740,150,243,932,900,804,502,136,165,466,212,147,123,276,715,619,764,862,339,757,127,836,546,329,351,389,231,148,385,634,492,611,94,338,637,966,14,326,362,810,471,68,720,186,154,75,895,477,28,723,841,907,197,367,410,184,17,527,660,715,166,251,962,459,303,807,893,984,391,59,208,58,216,458,87,441,570,78,592,840,600,616,269,20,763,313,110,642,485,674,121,370,598,937,498,262,303,126,971,799,31,902,575,43,550,366,462,945,324,232,852,819,304,101,653,237,859,287,667,140,498,455,255,646,173,545,389,923,213,393,69,475,949,288,375,285,945,622,625,580,904,77,422,198,907,780,85,879,857,965,762,590,381,551,65,213,958,732,248,120,196,930,409,983,674,92,282,838,570,61,20,318,47,927,138,456,393,14,883,79,469,196,98,647,81,762,455,857,203,496,359,172,636,425,727,781,33,594,231,787,594,855,59,287,151,747,279,132,486,705,113,294,355,469,996,498,648,30,731,577,266,57,834,923,647,680,540,203,803,860,623,625,295,230,223,229,742,369,181,690,815,941,190,756,599,102,563,205,351,678,13,734,322,964,829,853,103,851,539,498,864,765,610,872,40,144,325,949,493,457,574,522,544,714,342,648,319,9,802,184,939,814,867,942,800,479,427,153,727,136,132,914,659,871,407,400,733,569,469,707,276,252,943,76,420,845,259,490,617,292,71,862,47,530,523,22,821,487,295,236,792,661,126,686,510,522,917,76,40,877,699,558,455,211,884,781,227,515,519,642,988,178,620,463,134,364,854,280,162,745,803,395,565,984,335,523,68,460,722,347,898,18,874,727,592,568,226,189,904,974,472,838,587,903,768,247,610,890,33,261,388,433,284,937,633,81,311,947,947,774,575,143,654,606,744,284,997,863,53,485,199,172,982,411,98,833,402,986,81,946,103,171,646,195,19,811,18,189,599,722,312,429,808,228,173,622,65,187,114,418,53,809,191,765,418,62,444,709,706,671,706,52,778,522,2,152,926,594,824,957,485,476,468,641,528,605,235,687,882,103,219,770,476,170,936,341,618,768,655,806,835,59,665,136,486,328", + "27,115,751,301,40,848,303,949,747,294,415,165,984,753,932,609,183,273,999,658,558,159,616,446,752,26,181,643,920,980,879,649,825,947,868,134,154,93,801,217,252,975,152,998,775,665,812,952,894,395,835,389,993,695,754,145,73,218,279,434,535,374,442,543,245,173,586,18,64,226,555,47,464,737,104,311,610,567,910,164,919,659,457,12,305,515,556,927,719,830,498,706,679,269,868,84,465,781,968,834,994,38,668,705,997,658,672,843,954,602,687,305,37,567,122,940,734,919,494,387,559,972,547,210,302,309,781,915,151,353,572,803,988,195,134,29,734,977,907,780,242,528,659,772,151,929,188,173,558,306,383,0,516,490,109,547,469,445,852,514,696,87,305,780,471,514,219,823,918,345,968,771,782,333,269,754,934,301,101,866,110,18,988,780,136,364,207,816,478,465,183,760,912,964,85,738,79,903,662,751,232,736,422,714,836,610,77,144,864,17,891,63,944,293,412,437,487,862,842,300,116,534,726,895,371,617,961,440,149,838,84,570,706,4,756,557,785,121,6,861,378,502,686,616,507,356,715,983,1,997,667,99,869,109,402,846,978,437,954,302,337,898,301,76,695,626,70,162,635,300,164,303,755,310,62,426,298,232,643,300,419,254,200,305,862,628,946,862,787,471,924,752,296,718,366,856,675,145,283,282,563,966,765,409,768,927,863,673,621,58,910,355,323,246,368,774,610,766,850,981,769,465,776,461,433,794,466,798,922,62,170,681,649,933,210,558,171,887,421,231,663,799,490,867,55,915,958,646,849,97,130,836,697,733,619,126,207,224,438,738,272,724,442,244,45,82,426,61,729,370,570,434,936,537,519,357,906,367,805,814,557,229,660,968,70,530,184,845,473,78,559,839,71,637,500,173,506,824,399,969,764,551,654,679,109,847,257,366,392,159,267,110,46,662,571,833,786,475,758,353,696,424,696,615,61,878,328,685,255,529,58,94,804,785,96,53,747,409,41,284,330,391,187,24,843,359,593,862,377,988,348,968,818,571,455,57,894,439,262,65,194,407,538,344,186,593,93,737,234,299,97,608,947,182,204,504,603,394,911,614,137,977,666,975,768,146,438,412,774,203,499,640,862,585,228,636,938,892,607,337,721,353,998,186,20,639,51,446,641,747,425,819,574,228,801,889,888,145,270,217,381,247,844,176,323,249,494,516,431,969,324,173,50,302,826,99,603,633,352,585,394,535,410,377,562,13,212,669,948,33,85,131,758,619,249,375,153,351,260,348,26,290,288,437,64,718,283,548,435,190,989,104,388,895,749,961,490,97,927,656,830,204,854,165,489,810,510,530,269,142,765,34,70,400,409,878,949,65,1000,290,747,921,59,555,339,974,739,765,159,811,227,141,500,431,336,779,145,224,888,621,954,254,188,603,555,903,180,70,551,482,559,500,843,520,866,791,66,330,743,909,232,34,116,227,132,832,549,698,676,368,194,526,830,171,16,613,983,92,410,607,316,962,7,129,454,918,602,551,504,99,702,634,899,788,549,450,732,801,463,737,326,211,331,300,565,370,383,205,819,925,145,851,34,410,280,432,319,827,229,970,102,567,700,853,683,82,608,101,392,351,862,628,133,95,877,822,252,334,240,312,627,103,298,996,344,693,152,218,228,784,760,967,54,891,57,392,318,51,736,219,573,890,88,974,137,983,542,433,606,728,745,187,84,977,239,67,71,124,246,106,219,871,868,529,817,186,121,654,922,602,989,33,643,721,35,158,543,483,717,744,113,86,604,490,615,9,4,632,281,96,467,354,302,785,37,55,158,705,921,29,861,433,776,531,17,675,278,394,157,262,389,170,227,505,794,743,679,195,48,447,996,136,438,14,858,683,235,862,385,320,418,915,161,401,77,763,294,998,757,342,199,308,980,482,247,9,859,191,735,933,732,756,31,477,520,374,288,400,772,63,243,208,777,856,680,166,626,326,344,342,68,454,652,742,867,964,620,75,163,366,720,876,840,885,103,324,201,139,378,313,794,986,728,893,485,487,290,251,647,504,490,494,180,328,280,37,699,985,952,778,901,285,575,337,752,426,702,486,969,169,232,151,558,886,40,296,887,733,182,600,715,753,972,560,895,272,592,412,863,194,678,164,95,409,246,21,333,408,209,140,859,384,612,716,714,827,848,989,299,935,748,894,994,239,542,805,490,588,839,207,888,165,417,473,13,92,792,614,659,39,438,673,379,669,977,125,853,250,941,51,311,605,940,620,868,941,65,950,665,457", + "186,492,888,947,309,181,16,25,933,884,730,872,888,93,363,154,584,792,598,193,711,491,160,71,740,554,757,448,717,985,739,213,378,373,760,349,909,879,337,332,480,150,979,121,168,709,155,156,159,425,365,936,438,227,257,381,657,699,897,858,923,513,90,798,84,37,186,999,540,48,51,120,668,440,933,794,245,865,690,153,297,122,216,123,489,485,733,37,673,977,469,560,538,507,632,839,261,236,408,54,112,128,38,743,633,538,609,427,511,74,688,69,723,399,107,971,744,695,535,570,697,261,10,741,582,899,15,234,316,972,122,919,255,798,278,658,504,479,358,36,119,659,435,332,764,230,116,564,146,342,751,516,0,110,771,723,429,472,584,883,934,724,997,793,527,939,577,482,995,318,888,110,188,75,493,537,679,365,902,42,957,987,153,835,218,772,291,565,568,294,331,696,461,31,231,491,220,518,602,656,740,594,222,355,484,637,66,535,867,891,615,701,267,478,218,309,218,942,269,592,294,137,268,277,903,123,906,278,193,759,834,243,136,903,44,485,888,418,170,736,197,958,171,475,729,43,162,292,917,127,382,335,170,740,836,196,787,840,994,241,486,23,93,687,183,673,208,328,224,63,122,490,516,51,627,105,290,46,861,295,399,456,179,153,810,921,408,554,876,512,461,10,289,521,427,94,837,506,385,693,583,850,60,175,512,865,59,791,229,724,151,163,991,685,826,1000,992,541,244,361,952,165,875,207,386,639,972,759,246,355,714,92,191,917,104,244,921,834,91,496,764,429,850,711,672,551,252,819,786,46,410,605,791,590,696,326,302,700,130,699,55,174,477,401,53,731,551,285,869,31,201,359,666,419,126,553,955,189,535,476,435,558,931,103,300,586,837,138,109,553,594,494,312,764,226,31,27,453,444,225,135,413,796,185,20,750,656,235,186,380,777,868,960,614,342,534,896,766,454,172,565,648,757,796,986,361,871,692,582,467,663,521,232,429,477,679,273,454,903,219,812,559,848,117,865,963,899,238,644,769,777,113,739,45,95,692,461,713,867,930,263,47,62,524,784,86,495,998,571,144,44,611,907,815,993,89,370,205,70,731,310,659,556,128,676,215,381,62,983,418,937,82,521,124,654,677,713,149,184,6,540,176,728,993,591,897,318,7,918,524,657,768,772,176,626,123,79,295,502,811,739,552,281,338,664,728,345,579,671,975,95,245,559,920,90,187,358,330,272,883,927,532,506,797,2,758,786,210,46,343,137,967,989,484,190,825,627,428,524,476,498,455,71,946,546,428,966,292,649,973,953,220,635,669,257,764,404,243,577,960,807,511,883,333,623,51,89,673,314,446,23,367,361,784,102,893,358,888,905,886,912,881,87,133,288,479,972,259,700,756,576,262,963,945,886,901,505,786,666,915,699,430,38,965,499,284,86,45,980,330,652,366,474,978,402,975,196,365,768,825,584,147,31,355,196,369,119,122,142,419,884,283,357,744,477,542,686,492,529,188,457,665,134,592,413,492,675,5,39,76,173,842,791,532,451,840,329,860,394,9,537,128,836,327,727,677,912,714,656,273,80,513,53,690,614,123,267,756,802,998,47,890,907,196,750,739,491,610,469,100,520,405,719,384,9,208,360,139,810,133,314,766,132,786,97,58,580,183,973,455,428,4,884,325,944,331,729,573,965,394,629,129,455,861,320,626,261,854,943,508,462,717,686,37,38,150,860,768,382,437,170,813,263,399,693,585,584,221,116,857,670,711,388,281,341,827,674,46,223,156,170,685,8,517,880,237,48,504,57,485,530,620,758,239,499,371,811,910,150,731,15,104,52,731,364,205,681,608,474,469,354,202,770,667,348,728,901,492,69,147,194,428,92,135,853,111,325,505,69,557,664,935,356,145,511,269,831,444,882,842,888,955,222,872,526,148,398,407,835,150,146,653,967,382,396,600,369,661,530,166,440,210,21,11,558,909,114,694,235,125,271,257,774,416,612,182,595,251,298,689,868,529,382,774,183,808,775,440,135,952,42,994,456,604,823,49,856,546,388,107,199,26,585,632,772,349,232,807,508,289,477,611,927,477,332,199,706,187,964,229,11,508,159,609,772,692,123,35,877,714,900,751,63,985,493,406,854,915,776,669,42,541,595,365,291,448,28,447,659,259,445,570,127,182,272,650,646,783,878,380,871,477,133,165,643,409,734,898,604,770,331,217,168,591,422,958,232,779,64,650,214,996,68,296,892,556,317,326,701,786,955,893,601,77,694,353,866,205,578,211", + "63,646,803,552,74,394,576,417,882,228,183,22,47,468,9,477,339,586,403,73,219,289,32,675,130,396,221,62,746,236,626,694,109,96,993,94,879,520,696,319,451,609,611,535,642,70,343,899,771,136,933,144,683,197,474,957,924,972,451,166,772,388,54,232,376,67,560,466,917,510,223,418,705,406,564,113,696,644,474,177,126,674,414,68,724,125,655,385,841,352,718,315,31,986,724,487,49,610,640,187,894,978,97,252,600,550,887,909,467,349,180,965,929,613,455,920,26,119,330,38,740,605,406,204,713,608,577,747,4,451,939,840,101,151,865,994,626,258,748,397,813,158,371,761,487,93,316,256,141,369,268,490,110,0,473,618,329,340,703,856,217,716,692,697,104,182,422,927,706,320,542,412,786,536,657,428,875,810,759,253,145,88,244,960,928,247,867,134,819,842,113,196,482,10,682,84,877,48,203,245,77,973,840,425,357,844,100,605,838,175,722,680,206,873,979,972,166,152,593,271,538,108,451,991,267,232,590,608,152,171,528,39,442,657,251,404,864,694,756,635,170,337,610,684,758,382,367,19,72,824,701,55,922,293,820,494,308,351,234,755,494,640,240,513,417,856,597,423,408,955,48,475,444,223,727,382,464,667,830,363,805,439,949,208,973,574,326,670,116,150,373,577,772,457,426,79,514,554,482,494,727,274,412,648,481,111,630,869,681,17,992,233,763,752,8,424,839,477,866,943,569,954,126,209,364,48,859,474,205,637,911,907,939,962,502,36,51,305,347,623,116,144,996,705,582,379,132,843,98,23,540,468,420,797,107,847,105,702,92,990,544,767,979,775,674,716,852,493,382,823,298,539,16,57,284,317,11,67,824,680,562,483,594,932,388,297,892,127,915,584,589,993,527,128,712,570,630,353,448,96,131,388,872,138,214,725,454,169,693,607,355,772,560,508,90,903,60,546,69,470,74,912,579,157,587,480,36,34,839,796,695,355,12,446,387,804,756,747,633,971,967,687,866,947,376,756,522,411,92,163,903,7,657,877,544,209,35,86,327,456,209,353,271,789,255,712,561,323,248,987,593,765,536,489,942,619,954,644,756,891,64,395,917,757,350,90,249,219,51,265,353,462,940,416,378,381,931,245,212,590,547,798,542,258,739,259,115,910,304,280,667,652,22,730,785,134,922,709,588,65,408,30,581,864,721,895,880,934,77,811,640,846,94,859,92,190,729,188,676,94,848,506,283,380,542,752,510,937,6,14,46,283,366,540,861,234,605,696,133,199,198,134,326,198,968,363,922,84,888,202,963,608,413,553,41,234,838,473,455,414,492,619,793,290,521,793,35,3,359,257,679,224,281,639,23,541,864,215,19,150,366,222,918,543,958,492,899,672,389,742,783,448,203,198,800,888,773,808,3,680,400,196,888,428,626,26,613,674,513,102,604,811,763,833,941,598,942,464,737,482,36,270,98,680,800,604,492,989,649,642,244,907,995,24,259,412,224,825,853,971,189,126,167,875,486,11,537,227,227,493,831,267,428,238,299,661,616,823,405,752,822,636,727,44,609,727,246,177,376,740,614,131,707,281,138,919,571,42,328,411,792,311,787,803,765,598,388,208,468,352,122,600,602,190,855,417,19,371,275,819,644,619,361,194,915,16,543,818,453,400,758,475,263,860,774,410,782,561,134,918,860,365,73,550,22,337,569,454,273,583,90,643,680,659,987,167,724,357,122,918,253,631,216,626,749,894,674,954,508,837,159,892,448,790,559,956,460,161,908,183,412,158,371,774,570,640,533,811,926,487,283,225,855,269,958,559,136,42,611,473,270,760,459,943,408,795,801,992,840,356,517,724,250,704,373,953,931,871,275,290,522,23,437,236,825,755,305,712,243,552,11,150,601,564,238,349,848,959,56,735,55,867,196,229,466,162,844,925,23,713,690,420,38,243,995,5,41,733,441,768,731,664,488,982,491,788,899,763,518,3,826,346,59,126,522,729,89,611,505,16,994,918,23,317,720,723,256,355,277,33,712,174,313,740,122,929,497,86,279,109,384,179,632,421,194,629,892,544,584,701,782,763,604,512,358,939,583,460,914,227,42,869,361,229,895,82,227,988,68,37,73,196,562,927,622,854,640,902,496,662,800,728,843,646,353,866,874,661,92,865,752,454,334,998,746,104,327,882,40,281,908,897,154,446,829,633,774,592,243,735,919,577,805,606,961,309,398,949,286,490,886,292,224,119,475,450,681,397,871,304,838,115,370,914,629,387,47,564,917,453", + "247,831,934,920,164,165,212,447,213,991,660,102,459,788,638,303,356,494,838,80,235,799,764,468,624,308,494,673,603,44,23,683,243,307,937,682,341,994,65,501,388,880,650,249,427,434,514,126,714,977,889,993,949,291,817,726,144,478,613,199,253,14,514,325,727,190,598,681,551,978,567,367,665,19,713,835,460,862,698,320,29,457,341,208,736,390,310,126,974,372,124,605,557,420,443,916,494,403,151,523,678,923,296,393,17,129,898,87,308,623,830,877,542,851,570,581,91,909,561,327,69,106,868,564,297,525,98,74,371,695,84,240,56,541,556,987,141,403,1,781,133,264,389,540,946,436,807,603,899,497,898,109,771,473,0,302,599,779,287,837,470,117,732,655,447,728,951,630,957,815,939,334,339,716,558,882,524,697,49,163,257,584,100,28,700,975,535,512,649,622,314,89,291,859,185,118,19,701,299,804,25,475,586,744,241,11,6,342,32,728,56,649,60,833,429,350,846,607,392,198,602,166,541,588,210,710,597,920,5,300,809,265,674,347,162,443,575,791,65,746,666,540,829,39,716,136,605,246,386,924,763,822,295,592,751,51,169,168,405,722,357,411,3,226,355,424,233,61,980,671,753,321,986,904,203,124,524,904,518,244,86,781,894,29,502,128,932,717,683,26,24,100,191,140,264,949,133,804,861,925,967,745,435,988,286,67,670,614,86,986,545,730,268,881,195,385,880,120,879,857,182,801,943,795,720,205,155,774,925,895,505,789,465,382,842,243,609,255,163,779,184,860,612,944,110,158,638,102,512,878,617,745,967,332,110,704,801,722,870,803,78,204,930,172,742,239,746,829,655,146,946,836,139,441,928,156,252,36,660,9,992,964,890,565,826,946,967,328,585,437,961,714,354,360,311,811,283,272,298,657,267,815,651,688,951,555,881,120,6,796,505,724,313,123,913,362,179,488,706,300,448,468,80,575,190,507,558,36,281,787,51,455,947,837,980,401,337,206,947,714,511,496,228,500,664,262,536,412,970,185,944,825,55,883,60,753,74,311,86,398,430,653,897,97,791,121,349,500,798,524,370,672,502,870,380,942,891,970,307,808,611,879,554,880,196,843,521,982,347,89,613,499,74,501,720,614,258,993,957,901,315,17,824,331,141,771,507,792,524,577,524,898,461,544,738,804,143,376,727,300,311,457,64,618,899,802,853,501,769,829,793,181,361,157,211,508,891,835,479,103,326,644,216,663,722,11,307,533,21,857,969,619,254,793,456,945,530,267,547,866,926,673,610,15,96,882,943,848,240,743,68,77,400,121,50,194,987,512,13,524,741,703,285,245,260,222,844,100,977,996,528,669,577,739,960,290,489,27,552,362,502,487,242,930,388,406,399,119,889,999,135,893,907,773,182,461,984,568,530,445,165,589,762,776,70,744,316,367,490,340,971,854,623,120,580,100,506,760,648,311,858,372,938,116,461,154,110,121,970,530,345,864,395,674,797,495,172,239,580,674,60,334,643,526,617,981,627,835,869,89,620,502,862,673,556,486,82,666,151,571,744,570,553,799,2,171,714,581,93,7,104,491,481,169,722,49,674,149,573,150,148,162,693,559,436,84,97,869,129,213,128,526,650,84,352,874,825,333,552,540,306,179,342,673,736,47,171,834,261,233,705,516,399,833,415,579,929,659,648,900,793,474,223,157,399,416,554,341,685,926,226,867,284,547,115,720,298,873,230,271,181,772,774,998,668,424,341,248,298,187,143,916,337,31,415,164,196,164,317,991,374,908,103,222,147,911,921,346,762,652,244,365,439,84,43,990,432,114,405,803,332,690,790,897,405,937,935,836,398,688,709,723,931,508,115,266,434,627,777,481,376,459,934,775,456,348,257,532,657,556,128,899,502,577,383,526,301,954,163,667,245,396,742,288,347,669,957,691,7,918,899,104,581,969,381,10,541,45,303,752,83,939,639,934,751,801,888,919,124,159,90,27,328,322,679,388,306,515,227,207,940,623,474,171,380,626,865,596,757,996,701,642,911,248,9,696,29,389,718,458,327,478,828,942,502,668,868,113,550,493,836,934,898,530,290,69,654,657,257,404,798,525,408,518,734,663,590,488,2,760,607,227,287,305,619,350,647,681,289,154,24,171,62,60,261,944,772,808,328,137,76,810,657,841,674,198,524,727,278,221,265,224,406,864,471,451,803,531,911,54,161,352,219,924,954,392,149,894,846,107,776,715,798,850,973,480,962,90,915,536,911,65,320,322,574,950,953,284,648,287", + "800,308,210,443,250,388,586,821,828,978,372,508,716,141,989,657,226,596,616,97,163,952,311,462,667,720,933,496,79,748,656,350,874,40,296,100,581,997,755,609,290,862,642,38,461,178,993,664,320,476,536,833,169,36,618,789,870,1000,305,835,902,383,250,45,389,54,54,165,815,754,261,730,617,3,801,67,869,59,71,541,554,423,312,385,317,706,799,54,981,293,987,9,739,508,662,237,910,634,289,197,224,192,968,433,144,998,661,772,910,746,364,945,323,387,614,319,582,26,355,560,146,913,329,677,771,462,421,649,616,557,232,945,869,445,728,6,85,868,654,763,869,408,179,735,675,301,870,255,379,748,485,547,723,618,302,0,430,246,653,638,447,638,33,636,750,172,207,292,758,825,767,590,292,457,650,989,357,91,306,686,486,501,326,737,896,792,884,356,238,669,768,383,705,304,731,980,258,567,556,45,716,98,922,456,843,200,856,538,43,603,866,854,314,713,345,704,467,174,496,403,927,234,229,383,487,919,637,160,384,857,182,985,563,307,749,863,355,768,167,718,773,984,99,640,777,614,738,993,343,649,746,986,302,168,235,1000,502,560,98,794,56,144,473,171,114,341,743,135,774,460,208,96,260,865,286,220,207,462,195,493,16,760,609,818,415,863,73,799,964,552,680,433,652,676,615,151,642,283,241,781,225,991,804,3,349,581,35,455,518,606,626,288,740,156,624,770,241,212,271,526,588,97,286,1000,593,776,484,605,298,890,312,553,862,70,607,147,835,872,363,496,583,215,970,554,735,669,56,383,375,554,723,214,834,959,6,765,947,364,768,751,160,674,370,591,294,115,670,196,313,985,573,575,251,248,59,327,50,282,966,533,5,417,881,448,381,755,246,598,523,980,894,607,692,325,830,959,321,629,102,48,400,232,424,977,343,877,609,358,475,895,17,398,425,863,578,29,485,457,303,963,863,312,308,40,832,768,849,635,550,480,880,526,582,124,657,231,503,710,918,766,340,584,69,876,625,748,896,387,206,150,756,461,457,677,9,940,958,987,638,777,746,876,914,555,289,264,875,585,200,331,849,969,257,776,330,326,640,387,384,316,123,432,58,612,961,454,7,223,360,862,686,838,725,364,703,100,249,397,695,546,827,945,239,878,618,764,80,751,546,667,820,732,964,828,529,214,622,846,493,640,862,491,579,327,340,521,442,982,420,822,656,740,50,391,24,347,560,438,807,618,391,742,174,307,215,770,700,491,481,763,482,136,115,210,416,838,973,584,389,386,820,845,673,918,61,477,582,729,553,493,994,703,116,915,319,916,541,202,608,310,669,93,856,466,188,213,995,299,824,89,465,311,367,870,606,161,524,843,8,880,943,246,739,665,431,934,188,540,744,669,952,138,606,791,326,921,891,746,148,769,574,491,378,600,240,911,408,668,907,661,961,380,638,567,45,435,435,446,883,432,753,181,810,512,436,43,614,950,723,320,106,43,56,472,860,886,770,517,832,307,541,860,912,373,954,599,249,93,75,895,739,383,929,490,637,242,124,78,554,989,607,848,638,840,579,360,470,554,381,201,8,220,449,739,798,159,716,551,597,543,775,690,955,410,231,915,394,227,230,844,360,899,100,583,820,586,568,616,849,766,367,948,259,985,740,841,170,825,251,777,820,625,907,602,779,678,969,969,952,700,542,732,404,30,620,181,940,299,53,958,806,382,467,969,564,683,687,417,145,982,219,865,761,569,516,304,772,149,791,468,93,232,849,408,122,397,944,71,543,62,292,491,295,606,265,260,85,540,248,521,231,691,14,347,193,675,849,106,815,527,608,24,644,392,993,194,510,926,804,417,72,229,893,635,783,713,344,901,958,457,400,646,878,986,95,74,764,565,794,872,148,543,705,28,899,142,203,688,755,906,138,470,219,877,964,256,634,715,544,476,801,497,197,342,738,31,11,974,927,373,113,453,673,373,377,135,164,808,562,560,28,846,666,692,71,848,351,747,57,580,837,414,718,963,866,537,767,961,730,865,646,448,881,323,303,97,15,710,454,879,748,25,819,379,22,210,522,363,954,837,654,38,600,975,993,477,881,966,533,713,518,775,696,730,564,714,974,493,10,299,563,796,511,807,866,597,533,467,909,567,181,175,880,807,274,815,283,885,98,232,742,453,721,572,406,194,516,818,589,988,668,615,951,165,465,308,907,497,484,12,229,700,682,716,293,388,492,660,307,955,604,227,687,889,745,239,381,642,167,672,520,213,735,669,96,269,512,101,123,716", + "503,254,870,592,183,319,909,398,769,487,459,436,683,686,563,544,73,997,282,446,554,668,244,233,115,307,32,205,274,730,643,630,804,324,929,707,955,507,931,557,354,813,609,180,176,251,596,732,299,578,435,150,414,747,573,470,545,307,914,978,306,918,932,391,169,751,648,172,207,890,791,937,147,133,142,416,31,833,825,109,473,917,413,9,488,85,786,643,77,662,138,144,658,756,311,606,525,875,701,317,487,812,227,372,202,659,405,981,461,818,755,120,600,276,774,223,887,844,651,237,130,457,223,514,254,571,229,839,765,250,807,894,938,495,408,974,861,102,571,780,692,951,540,643,765,576,591,767,805,914,281,469,429,329,599,430,0,986,519,970,36,608,406,929,997,46,186,643,123,282,914,507,972,81,3,740,39,207,769,157,751,641,243,264,63,965,949,217,655,290,488,429,915,332,416,598,355,304,790,630,679,227,728,20,698,899,214,220,278,108,581,182,424,890,194,225,65,567,432,430,72,367,699,798,538,351,184,445,43,377,542,266,489,281,113,583,658,989,301,653,144,949,716,456,496,811,336,937,885,588,382,234,139,343,994,642,147,313,11,858,850,41,494,572,556,471,392,362,594,902,355,812,755,387,412,959,182,550,396,463,573,16,867,15,514,450,407,136,52,820,399,642,302,77,924,902,651,281,261,862,597,343,194,289,351,172,110,906,992,202,689,19,478,702,616,935,220,310,922,336,604,290,864,786,168,13,85,785,767,301,554,453,17,610,904,147,699,151,342,794,657,112,212,753,226,684,732,985,808,260,221,523,827,528,478,736,322,429,313,853,102,191,52,804,557,329,253,377,54,806,422,834,836,998,372,516,742,882,197,481,94,705,983,161,875,922,492,783,458,711,486,426,531,955,255,858,879,940,688,112,702,203,682,587,22,689,62,699,463,978,482,977,88,333,446,363,570,426,86,314,228,936,277,985,405,142,902,902,199,945,729,263,962,549,729,310,232,393,220,749,465,167,295,696,841,792,824,167,285,28,700,27,745,48,849,713,832,850,70,675,509,694,394,548,969,487,466,842,151,439,2,242,904,180,325,512,843,470,877,923,122,620,411,966,926,404,946,303,309,438,424,128,56,855,861,529,315,430,406,987,597,752,380,936,944,624,941,854,235,303,97,518,133,646,706,695,39,799,985,234,416,908,512,447,866,294,806,242,361,305,412,155,227,742,458,533,457,144,881,515,104,573,844,638,379,338,558,856,54,385,398,177,192,676,739,770,460,63,910,177,38,915,540,667,526,720,190,540,289,599,893,441,908,758,953,511,597,251,226,448,102,780,811,343,515,245,981,732,812,46,388,774,986,990,446,285,684,640,752,768,977,56,845,187,452,32,546,563,259,412,41,880,619,224,666,650,276,465,33,920,680,270,28,488,634,892,351,443,884,91,137,937,623,898,405,417,711,590,500,204,641,983,333,56,565,263,557,791,746,243,909,595,658,9,486,495,859,980,710,384,720,965,904,781,916,237,67,208,465,298,582,544,603,536,625,338,634,562,113,216,175,262,844,76,661,379,187,893,711,736,337,152,436,247,123,118,169,595,238,542,78,704,17,620,497,171,956,950,504,833,687,331,237,800,751,520,66,38,278,912,957,965,910,167,701,45,538,780,885,268,639,111,229,470,539,395,919,826,624,591,734,555,760,320,300,264,338,543,486,64,241,82,746,353,165,263,306,360,60,920,720,529,160,557,810,994,759,328,823,625,80,528,698,7,591,530,459,250,372,999,505,744,737,981,251,985,661,558,245,294,890,420,306,614,857,895,552,128,851,432,274,835,622,921,405,756,774,975,682,553,610,52,153,455,36,364,258,109,524,76,446,316,716,715,388,129,34,92,221,109,865,969,720,341,390,247,919,893,512,731,432,975,892,461,828,537,916,710,861,556,925,381,879,75,170,79,885,191,280,189,683,502,286,893,865,732,196,857,498,823,917,826,625,28,842,228,280,117,925,202,371,829,45,145,130,12,902,525,308,806,583,642,768,220,926,588,69,360,931,540,37,585,943,672,144,827,533,807,148,349,318,427,40,481,824,753,784,742,898,241,585,940,588,691,613,332,704,559,592,713,521,240,442,251,269,423,381,112,103,357,589,946,803,639,186,539,983,521,788,278,300,821,828,623,518,605,446,86,355,213,444,686,577,314,112,621,323,785,342,817,51,581,411,877,777,619,904,462,532,963,930,793,46,679,790,832,282,810,349,896,130,787,769,252,129,389,761,787,589,216", + "767,860,900,793,886,497,532,782,181,168,530,251,93,944,182,821,709,68,315,415,574,60,595,29,69,199,537,352,43,783,121,385,190,99,126,856,732,324,548,665,259,554,75,235,515,435,976,947,540,360,444,150,981,523,563,880,219,956,744,404,657,908,951,833,939,944,802,212,765,282,264,150,197,943,43,30,187,559,320,486,787,354,318,136,107,246,671,546,874,30,322,13,147,869,277,569,252,543,538,646,911,787,650,292,388,648,689,674,562,564,255,694,252,193,744,800,654,993,511,489,54,675,919,945,358,892,464,414,236,962,368,972,696,661,493,858,569,245,313,818,178,665,711,978,581,353,444,381,868,766,371,445,472,340,779,246,986,0,660,672,169,523,8,989,516,631,811,243,572,668,371,541,301,163,9,868,591,224,437,338,869,778,726,440,615,39,965,954,964,494,60,58,680,644,55,291,123,892,326,936,251,706,989,941,828,347,384,734,226,192,440,26,334,375,104,606,502,80,833,262,71,985,703,45,937,298,935,221,706,484,886,761,931,32,322,559,305,107,172,73,827,850,135,890,432,19,978,843,953,479,879,928,619,942,424,874,722,580,691,612,894,280,296,500,247,757,953,600,796,965,387,655,474,268,86,975,948,871,220,36,787,922,910,687,629,428,901,541,24,398,924,189,216,737,621,360,538,921,482,602,930,59,791,652,29,35,697,771,36,171,264,176,986,555,402,305,869,685,658,770,528,788,517,860,284,679,960,430,2,81,297,4,697,989,613,612,638,531,716,798,561,355,49,342,447,678,619,148,26,905,579,739,370,543,64,224,479,852,88,730,121,824,424,246,670,701,350,484,748,436,437,241,440,774,971,700,59,600,938,913,33,656,578,857,405,536,344,110,883,517,482,405,367,270,523,845,653,54,432,124,335,533,379,288,501,178,352,112,82,385,152,503,862,68,971,584,647,752,421,586,945,871,826,634,758,700,655,94,382,604,405,696,160,860,629,419,539,661,966,245,1,74,520,685,925,162,783,431,415,828,688,908,411,567,933,599,617,109,385,249,410,680,656,63,622,807,448,889,735,959,956,886,117,897,584,925,858,585,950,211,68,410,68,679,32,143,781,703,368,725,179,282,620,516,8,268,35,561,828,666,802,398,145,284,470,29,132,222,272,161,219,599,296,772,951,401,102,854,631,33,500,738,460,752,921,770,82,517,317,930,543,728,17,103,717,35,31,870,650,438,746,733,527,790,134,583,387,302,721,135,351,966,961,212,346,767,204,180,937,458,3,676,620,721,451,34,155,809,635,326,919,21,993,152,482,259,390,897,779,168,107,711,28,248,495,332,546,838,311,16,381,106,171,18,926,182,969,54,352,34,384,705,478,600,382,430,441,476,362,826,372,454,23,341,336,126,737,414,577,9,254,424,421,345,920,794,716,559,651,265,969,981,418,756,716,340,295,534,109,688,43,487,512,691,552,778,263,670,173,732,821,632,886,498,188,578,60,3,919,189,347,524,503,388,890,33,991,110,378,533,46,457,294,68,467,655,120,42,351,810,716,599,370,342,855,199,733,569,752,702,92,294,263,126,891,799,963,250,637,384,563,961,423,67,598,356,711,653,721,643,739,185,465,14,916,32,518,885,589,198,400,673,617,923,396,472,692,626,87,216,317,674,18,680,458,617,988,964,302,461,440,763,759,107,482,560,287,338,912,250,582,876,883,289,446,311,970,745,225,993,513,985,958,384,808,916,518,156,328,907,827,621,123,360,977,878,952,255,315,24,306,618,343,535,7,52,397,312,273,790,401,580,98,287,258,985,860,293,494,333,470,71,974,391,262,475,810,648,57,442,838,922,900,215,392,962,877,564,924,925,723,60,302,772,139,514,188,313,139,920,198,330,727,421,977,511,836,663,827,755,899,372,209,419,612,644,873,430,610,374,326,108,183,220,977,545,581,31,920,459,20,498,939,673,298,194,856,343,503,93,787,777,221,346,291,887,590,810,604,689,769,517,344,290,852,564,274,168,373,989,281,964,538,368,657,219,220,168,541,712,432,316,640,943,155,245,975,893,411,653,180,105,938,367,826,284,299,170,314,634,637,899,350,538,39,969,375,519,424,726,66,257,322,775,745,841,873,288,951,614,566,242,248,782,373,484,287,396,553,458,158,658,714,211,740,899,858,931,658,789,342,381,438,372,407,343,450,281,209,160,986,371,454,602,47,128,345,478,906,14,869,636,158,747,140,811,686,912,299,197,131,372,804,481,213,943,384,308,861,642", + "869,338,656,781,464,690,443,166,777,649,857,254,360,305,88,302,953,843,903,668,166,676,84,798,303,654,61,949,3,915,318,311,232,655,256,993,584,867,808,68,936,642,834,899,136,978,120,223,518,284,670,846,438,340,11,752,462,988,681,247,561,462,500,27,26,813,956,507,238,992,231,625,711,783,158,980,636,854,982,227,930,24,668,575,219,604,6,280,306,735,780,44,995,275,413,248,614,215,279,372,104,564,204,480,28,9,391,236,915,184,452,490,14,814,131,268,693,184,951,426,469,97,991,65,844,909,942,913,376,228,162,668,444,298,205,663,301,475,592,769,439,958,358,580,765,539,992,672,404,767,874,852,584,703,287,653,519,660,0,760,391,188,157,221,86,893,928,185,128,907,435,536,526,919,479,103,613,45,340,58,394,453,654,825,718,297,598,25,2,156,522,986,628,16,675,14,719,188,764,429,195,421,930,67,227,129,52,475,599,956,798,628,500,787,856,785,641,35,467,647,992,984,792,553,200,238,346,391,554,471,895,843,41,591,474,452,196,223,608,24,235,407,851,884,111,468,245,14,507,514,812,921,940,553,12,899,568,461,564,645,866,158,886,759,489,105,460,757,640,948,359,269,14,954,377,982,818,324,376,166,482,526,704,144,173,96,789,47,908,195,104,641,339,276,745,504,210,857,877,145,400,313,866,142,904,209,65,949,340,500,59,678,762,949,876,406,357,622,298,890,552,278,78,907,332,975,251,218,669,771,810,151,779,378,490,784,134,390,449,196,153,221,882,197,266,228,220,284,289,408,757,377,102,885,211,642,696,280,444,439,956,398,653,828,623,592,593,579,121,496,455,595,669,134,716,585,158,264,941,112,201,134,302,401,99,303,189,428,583,135,681,142,29,803,43,501,271,116,841,854,452,536,285,582,548,564,862,461,950,71,657,552,117,895,488,463,387,707,218,509,228,6,974,330,828,421,104,243,466,440,961,57,768,444,67,51,372,16,509,359,944,282,794,941,331,280,189,572,508,873,78,595,888,472,873,703,303,354,156,693,678,534,762,677,268,99,257,122,738,832,350,161,665,600,597,324,877,36,518,927,76,465,212,393,383,514,566,445,83,272,998,515,402,389,18,931,635,175,483,108,349,966,353,485,839,174,765,298,833,35,547,360,162,781,895,3,206,505,587,120,136,986,587,18,189,157,95,186,760,896,860,380,853,594,364,901,766,245,810,736,934,766,58,596,376,749,83,341,216,607,495,492,174,930,695,33,267,713,348,295,439,510,66,238,935,737,619,94,707,950,839,362,93,839,555,487,930,433,343,958,412,186,521,434,446,714,729,38,265,820,850,405,387,847,575,541,237,976,163,509,917,539,448,324,964,225,961,769,142,116,646,476,869,357,454,171,332,693,26,715,93,804,555,784,741,957,313,294,275,689,401,692,858,802,862,250,585,902,870,106,493,324,205,591,643,841,371,848,146,815,535,725,225,153,97,339,372,314,538,132,623,396,258,936,108,683,907,76,494,903,993,34,74,843,577,734,723,333,96,810,275,646,783,654,889,177,85,345,667,946,982,744,766,211,329,994,279,123,665,188,835,722,356,137,919,43,938,768,787,343,755,147,588,308,755,676,270,721,786,580,653,720,255,608,478,207,476,830,207,856,317,674,44,619,767,986,326,160,467,433,190,286,11,358,917,76,928,175,552,271,991,171,475,990,116,773,960,744,731,756,79,63,543,461,702,349,435,923,741,955,656,86,733,550,801,837,800,94,613,325,215,533,843,383,125,204,434,712,839,606,404,925,521,585,267,123,809,355,551,146,484,242,394,473,775,298,968,314,347,566,673,915,335,293,907,896,592,104,150,651,648,481,800,87,673,890,380,207,346,120,246,377,443,396,499,451,737,42,290,558,350,322,585,416,810,838,893,880,908,717,677,645,49,345,750,626,119,295,714,461,765,22,321,794,376,534,635,126,770,991,397,543,108,264,28,737,54,625,486,750,660,656,436,746,648,856,553,406,100,110,308,772,330,638,794,119,416,899,194,928,735,134,416,150,563,930,913,906,869,517,162,270,191,22,826,891,394,73,362,102,771,868,295,135,28,845,231,972,862,330,958,288,608,773,447,874,888,196,419,688,53,323,635,959,59,427,132,226,643,152,701,602,801,395,290,984,290,245,342,34,47,21,544,433,473,537,307,730,736,534,496,819,50,125,768,706,298,324,296,318,45,562,250,539,762,437,210,907,417,201,969,642,726,364,89,656,272,782,968,327", + "13,739,780,277,540,797,1000,274,96,868,541,252,919,220,858,270,913,946,701,284,95,676,554,779,349,721,53,209,201,654,457,220,467,68,275,481,8,274,266,53,47,556,721,757,809,154,306,986,93,576,872,518,385,172,771,8,201,982,30,17,137,80,882,314,9,23,273,740,88,726,762,915,885,431,306,293,693,468,645,811,700,175,523,398,94,99,525,611,390,479,663,328,555,499,398,995,629,980,240,562,18,543,664,390,792,547,381,204,22,966,26,750,898,554,820,593,449,177,827,98,978,236,90,949,752,153,612,814,559,222,602,579,266,921,690,447,319,615,410,728,756,42,381,409,455,912,889,971,349,883,492,514,883,856,837,638,970,672,760,0,102,533,624,509,277,227,849,445,304,402,264,488,940,858,679,724,846,14,777,431,376,661,671,42,54,767,421,659,462,334,589,655,876,874,823,960,118,617,644,236,876,400,200,395,370,898,467,100,665,656,943,475,675,320,295,130,228,84,735,394,743,486,841,975,999,119,174,306,897,333,311,261,923,296,337,429,460,294,623,989,55,828,5,63,39,594,718,475,853,425,172,239,699,996,723,233,285,562,567,837,113,495,968,313,720,284,704,490,560,53,828,569,352,693,318,804,310,85,758,11,710,532,67,716,766,209,711,500,996,584,322,941,616,475,641,355,663,237,418,382,925,634,483,172,327,506,884,38,976,379,57,237,387,310,721,510,347,871,252,161,265,595,473,822,930,662,105,616,469,275,425,689,532,711,954,637,198,40,974,777,897,712,369,27,874,113,450,682,97,263,629,927,332,260,382,190,120,272,943,954,813,866,211,816,970,102,482,24,428,160,271,540,999,554,484,339,154,262,781,649,796,641,874,237,171,786,920,263,256,222,759,684,530,434,478,3,141,910,323,455,249,35,94,113,839,149,508,763,462,379,518,656,591,905,623,283,964,836,850,395,947,715,31,685,386,132,842,147,814,450,108,665,478,755,64,906,111,193,680,146,569,812,496,710,320,196,478,397,643,909,472,648,622,915,908,259,608,582,375,776,592,431,825,585,487,752,710,854,684,878,201,122,847,960,448,531,460,288,859,691,438,51,166,65,589,401,976,73,371,418,272,426,655,503,915,880,3,446,307,630,475,5,11,599,436,293,46,629,47,913,796,978,161,751,63,15,874,194,402,502,711,663,690,68,200,646,691,374,679,203,453,233,140,92,446,730,756,830,110,70,148,229,344,782,333,300,500,179,172,948,492,436,729,465,702,825,685,103,634,12,393,26,310,389,613,179,306,139,453,558,930,657,732,830,679,782,512,495,389,516,442,932,236,473,435,481,819,637,112,54,380,313,240,536,390,512,411,464,890,377,923,823,616,342,266,852,422,446,857,318,527,11,420,649,628,289,545,415,731,744,48,378,3,532,613,86,229,140,798,241,678,189,681,571,854,335,438,415,31,287,567,922,442,162,419,293,886,680,150,320,951,710,117,279,248,436,85,252,847,328,752,908,433,162,131,338,215,321,885,852,625,284,565,115,21,155,60,960,697,951,600,878,60,383,475,511,206,98,942,183,291,153,592,697,262,593,666,646,568,243,564,575,457,195,175,398,203,31,809,346,859,419,818,811,824,708,887,457,415,5,542,579,199,768,747,499,816,773,290,790,612,63,765,343,796,994,469,85,476,524,710,569,612,526,910,826,17,163,950,620,978,686,769,767,65,883,656,133,796,358,729,678,880,188,585,960,40,748,500,799,145,972,726,766,410,819,880,525,767,428,390,230,577,597,782,939,39,24,96,978,571,64,606,87,667,440,575,874,778,20,640,236,657,523,583,805,462,526,236,7,720,956,924,880,758,840,61,224,194,88,995,933,627,930,159,490,285,409,338,726,543,751,30,623,954,172,433,84,382,809,715,781,921,661,241,534,476,562,795,537,609,103,502,268,259,206,649,794,252,103,292,738,701,672,949,444,233,611,593,367,926,227,27,636,715,328,930,533,122,837,98,806,238,811,595,681,625,106,543,777,654,150,886,872,980,615,684,101,570,314,649,198,815,722,513,148,780,366,512,451,657,465,693,573,604,960,42,225,868,84,550,682,190,503,89,461,920,546,665,895,332,735,258,466,124,595,56,623,650,850,65,469,712,367,8,755,128,666,79,619,974,9,901,796,507,512,180,448,910,451,931,377,487,210,945,521,459,569,125,863,855,202,78,865,945,996,851,461,292,543,80,481,335,292,560,301,173,506,373,692,294,679,118,694,981,182,511,166,742,47", + "252,614,679,326,586,985,180,576,443,100,450,363,697,724,205,303,369,55,734,208,895,566,436,555,284,418,293,555,210,30,92,486,561,883,847,498,420,897,345,600,347,693,980,636,725,381,190,931,458,977,934,566,851,476,78,962,26,251,451,708,842,877,13,471,113,128,165,123,852,699,817,850,337,36,266,875,602,731,416,467,112,21,806,527,34,938,891,681,840,234,664,492,985,562,195,90,485,484,321,675,159,994,387,984,313,537,392,998,354,521,452,659,514,70,246,646,423,712,209,43,282,594,733,687,708,933,229,331,115,161,512,28,186,606,960,67,670,791,527,391,728,641,803,489,987,254,661,116,749,184,739,696,934,217,470,447,36,169,391,102,0,34,635,310,15,380,402,85,475,646,818,171,542,993,272,9,163,64,128,160,295,658,75,300,918,126,960,339,916,300,504,415,33,512,244,521,72,247,121,423,211,677,578,314,177,511,486,45,262,548,878,244,978,828,301,333,336,856,267,447,599,682,686,64,825,187,339,710,919,554,898,777,868,699,770,547,975,204,623,864,869,74,862,333,668,908,855,198,325,181,908,361,751,613,231,136,615,705,872,365,380,32,898,905,158,673,275,912,914,3,742,609,371,667,386,799,453,561,252,262,1000,526,167,376,971,949,821,602,398,729,514,39,930,69,34,36,731,970,343,852,500,996,754,531,35,521,139,890,978,575,766,436,642,193,356,760,618,260,909,41,65,223,683,945,4,338,444,927,284,813,977,842,346,493,904,152,218,995,130,828,980,746,701,51,643,118,143,524,334,460,991,251,54,636,973,655,309,36,108,938,578,705,333,92,976,929,217,131,111,211,122,165,41,324,946,771,674,721,3,314,624,931,502,791,567,919,173,309,531,992,466,424,783,398,626,248,793,429,991,739,724,760,376,986,968,428,664,79,898,979,991,996,809,524,643,278,156,420,24,211,200,107,545,60,587,646,721,960,147,668,744,755,679,515,264,150,517,470,833,515,399,405,81,71,262,885,443,998,480,700,686,348,398,565,223,702,951,898,662,534,998,97,593,955,69,560,625,427,23,290,47,621,41,592,775,886,629,22,92,94,941,999,323,803,779,178,607,681,235,17,168,725,268,240,281,643,502,618,993,305,356,505,784,7,584,327,57,208,676,675,133,504,81,743,476,983,944,142,329,170,578,316,990,624,212,550,533,321,485,630,332,524,56,805,368,748,297,105,625,468,132,43,399,987,360,171,753,659,971,667,760,725,235,474,835,570,161,120,713,852,49,522,779,659,512,449,650,38,978,969,963,329,355,628,325,378,115,366,877,532,607,366,248,157,999,779,560,401,420,691,193,784,474,576,352,437,143,767,861,91,551,5,829,114,405,904,561,390,164,820,158,50,150,771,488,435,330,175,271,288,174,484,857,934,251,469,598,472,239,491,573,393,939,490,615,556,189,467,824,763,815,621,54,373,937,894,14,440,653,613,989,92,210,237,923,216,975,351,141,486,227,271,667,474,332,631,552,826,786,403,811,268,824,991,17,897,576,150,839,72,938,485,624,719,139,246,14,513,216,841,14,104,276,62,183,109,461,954,304,785,209,855,511,180,223,165,219,782,813,895,159,557,29,834,756,217,48,674,605,413,580,113,293,840,197,847,15,387,589,768,188,5,183,449,670,541,545,182,628,860,137,302,485,992,61,858,436,634,57,862,547,900,125,972,835,424,775,279,344,681,48,942,630,993,438,578,871,509,403,672,223,872,958,925,446,856,841,555,459,58,529,309,141,895,306,900,889,712,961,407,78,339,162,981,786,534,573,625,948,594,346,569,831,334,224,499,740,875,854,186,189,353,359,182,704,272,446,964,757,679,613,747,927,590,747,127,756,637,162,920,832,12,684,396,989,943,68,62,365,10,554,738,816,466,82,31,733,683,410,577,21,836,362,841,929,524,44,407,599,79,33,529,279,728,122,52,919,417,318,124,6,78,849,793,471,633,280,563,575,905,442,66,878,279,742,633,859,551,393,531,182,247,887,311,52,733,139,694,433,692,365,858,492,136,111,426,33,12,614,453,928,918,766,943,747,771,97,746,499,375,472,605,368,939,712,884,152,799,464,26,514,965,284,622,594,979,181,896,543,107,177,13,888,941,682,500,66,973,542,653,259,397,886,210,701,63,482,105,475,382,676,828,683,500,268,882,340,246,488,143,666,236,98,702,969,974,91,784,151,31,592,376,459,563,700,772,23,497,498,548,776,980,46,13,929,698,744,115,283,738", + "746,918,147,971,85,796,352,392,927,979,302,874,416,198,171,546,331,174,430,499,323,918,483,662,384,409,784,154,758,800,152,31,715,489,6,351,183,852,654,486,750,362,235,955,984,586,680,385,639,693,231,714,284,688,587,831,319,114,633,443,603,144,497,276,917,458,350,109,849,344,74,906,87,831,496,203,665,199,734,192,922,969,887,425,500,800,612,160,189,113,743,546,15,344,232,905,665,599,162,865,890,745,897,286,324,931,479,584,919,608,389,211,857,266,770,249,117,651,83,584,845,116,16,108,262,50,784,518,508,115,336,233,442,537,84,280,817,701,571,641,444,782,46,299,180,239,255,994,813,458,512,87,724,716,117,638,608,523,188,533,34,0,302,3,519,341,267,34,787,923,527,155,245,340,768,390,30,670,290,743,524,607,682,903,696,5,594,810,640,292,650,522,628,333,530,849,288,662,527,426,923,185,27,530,543,794,647,727,22,408,112,52,417,956,825,477,589,398,868,270,707,285,798,761,320,959,274,406,353,772,464,574,394,385,224,292,295,937,256,561,6,439,190,654,241,646,423,380,944,515,495,847,719,480,756,611,669,65,140,198,431,347,450,958,438,349,378,971,136,909,750,296,7,753,660,719,189,57,347,350,394,763,398,585,177,21,606,104,552,904,861,641,266,197,46,464,957,827,761,715,770,694,988,999,802,23,372,357,278,510,576,224,72,421,18,443,926,879,748,775,760,768,304,104,86,314,195,589,133,213,421,949,655,948,277,823,5,279,473,630,279,681,7,25,718,192,261,147,275,446,134,785,213,532,55,660,745,454,321,622,835,128,515,29,646,126,485,973,896,246,530,964,421,429,791,546,557,566,731,50,17,823,229,25,709,768,266,700,590,560,944,569,182,372,24,802,200,19,94,59,427,713,400,167,175,595,622,450,755,816,753,343,644,581,596,299,267,634,344,624,608,706,459,127,224,152,232,787,690,775,804,267,43,118,732,670,98,101,453,588,914,410,787,374,349,176,113,918,35,480,816,482,553,280,841,409,413,794,358,458,335,786,163,962,812,874,328,850,469,594,693,674,532,549,913,957,624,511,548,391,783,620,923,874,816,848,937,67,722,150,852,123,546,676,539,791,366,223,252,409,813,487,617,222,515,718,339,506,62,756,211,729,941,603,296,560,757,605,20,951,771,558,761,106,124,901,140,608,286,366,578,17,660,906,216,159,221,265,432,298,714,237,993,906,328,308,502,855,633,259,606,799,15,74,640,786,320,755,923,965,205,39,283,756,853,719,459,236,758,407,114,515,636,320,170,365,765,202,164,359,839,216,239,593,956,135,35,536,915,562,980,267,668,617,835,282,780,419,860,892,715,159,655,63,480,246,174,189,246,731,939,740,242,194,322,986,289,481,500,739,875,599,867,5,457,413,692,244,552,358,671,751,668,550,501,124,268,654,173,429,551,958,551,721,243,920,442,622,940,27,415,782,783,212,234,513,390,783,923,279,894,451,878,201,822,64,8,383,80,709,595,698,484,672,383,334,324,763,429,278,878,657,253,905,767,174,529,177,863,265,838,226,673,503,986,580,872,996,130,510,518,470,887,177,980,41,444,201,978,722,173,292,797,999,867,587,343,907,392,969,480,732,503,778,720,796,811,937,383,141,702,986,237,269,701,925,914,928,958,904,864,470,917,897,869,232,115,607,123,794,851,873,909,884,818,726,965,191,266,974,327,21,327,53,877,921,94,56,662,901,809,764,165,830,150,38,485,16,894,99,800,215,273,983,481,809,442,446,489,112,782,901,930,537,284,427,722,289,766,382,614,421,240,674,240,808,510,750,833,339,331,580,493,958,815,200,226,471,56,55,823,485,326,812,241,987,135,196,505,921,806,304,120,139,70,328,732,74,197,346,263,416,106,965,711,49,545,819,624,837,93,819,746,888,135,167,410,181,706,790,292,146,131,224,968,375,808,736,615,495,998,144,484,531,358,547,128,721,12,140,284,269,656,491,425,22,831,856,252,768,889,532,650,998,128,895,415,624,944,65,97,937,644,889,850,468,348,442,33,302,569,528,276,493,978,509,3,20,170,830,728,573,901,891,768,971,5,927,865,149,948,700,841,978,52,758,448,679,386,218,497,735,399,639,803,782,82,93,66,162,444,628,335,804,179,138,917,256,244,286,850,178,652,247,485,145,161,424,733,502,744,740,324,952,154,727,19,946,183,975,180,976,244,534,558,464,583,953,296,748,47,61,670,534,304,124,491,134,460,983", + "6,21,201,673,769,96,740,929,478,942,879,2,372,262,21,429,737,651,311,376,257,86,95,992,126,826,234,958,436,768,794,477,234,571,247,245,193,965,507,656,858,889,694,498,818,216,666,412,715,578,941,633,904,964,430,300,296,969,358,595,358,111,994,403,1,988,929,302,793,344,702,478,749,880,234,283,97,864,79,24,787,975,268,956,625,85,597,191,696,933,968,334,701,62,988,151,857,133,299,928,945,706,858,352,883,590,619,856,72,449,982,21,365,58,608,992,510,289,701,389,96,700,694,926,425,639,319,162,925,812,37,889,479,555,491,327,32,60,638,230,711,53,795,746,685,264,328,782,976,652,372,305,997,692,732,33,406,8,157,624,635,302,0,682,559,170,179,793,801,913,629,503,538,884,480,439,249,700,769,644,517,31,358,480,272,87,45,384,945,264,68,806,395,974,922,984,640,451,124,382,199,886,612,79,145,748,999,963,28,564,900,279,199,587,829,989,897,358,528,299,551,637,413,382,174,175,146,876,602,426,892,385,4,918,237,649,401,37,286,698,37,91,325,314,230,956,795,374,948,150,488,986,408,724,609,353,727,536,676,100,547,666,641,650,51,755,874,259,206,718,723,810,883,635,963,407,150,247,137,222,862,494,922,372,240,528,768,970,79,292,600,459,451,914,725,615,102,140,145,263,858,271,190,331,901,209,646,856,822,601,123,998,107,413,453,772,817,608,215,261,716,499,775,263,144,864,271,468,732,729,821,715,450,206,953,913,811,892,687,772,920,442,447,626,645,930,614,44,781,81,922,419,277,736,289,456,734,959,310,727,218,522,104,627,354,406,169,787,171,70,315,280,738,562,864,323,638,507,374,162,540,275,19,192,762,862,763,945,658,499,262,40,17,385,163,676,512,890,131,902,526,825,987,489,350,745,270,659,384,410,631,943,92,397,570,571,220,509,923,374,563,865,337,188,941,452,485,562,675,926,163,104,763,813,938,968,178,805,941,999,864,710,829,817,586,668,271,103,746,757,354,107,360,588,320,957,76,294,332,748,358,27,533,561,943,501,979,958,553,180,805,299,65,25,770,653,52,580,471,953,358,640,991,18,883,871,835,816,523,872,359,910,471,148,68,501,596,608,96,369,167,87,553,5,792,541,517,779,726,427,564,874,5,987,674,135,580,665,38,494,711,382,172,481,406,847,612,405,754,922,587,224,899,581,789,365,730,343,340,519,715,428,177,719,123,657,512,78,103,934,767,356,448,881,434,17,798,598,670,469,953,989,862,1000,330,650,119,404,174,707,451,156,904,700,15,223,457,136,91,627,339,163,523,67,674,967,281,695,94,815,50,390,548,4,343,886,346,558,984,66,407,754,345,750,508,90,839,693,705,255,444,207,428,15,4,105,580,459,959,963,727,201,104,665,758,985,838,617,572,14,22,133,191,663,85,180,372,203,765,649,922,885,78,701,65,465,986,243,74,657,725,534,59,748,680,51,343,418,143,456,9,632,980,93,330,13,118,763,454,293,395,14,6,187,942,640,106,950,480,671,370,878,507,231,537,514,395,795,743,139,880,722,735,211,439,371,125,930,232,388,156,763,303,536,914,114,434,597,341,791,510,382,828,593,536,364,208,273,836,979,100,909,976,540,351,120,364,506,980,943,379,208,5,956,641,403,402,7,535,452,237,245,974,341,820,267,239,184,824,26,959,911,676,108,621,916,312,947,924,345,720,328,281,223,278,353,401,311,782,273,430,956,869,295,907,787,111,95,813,919,217,715,612,995,849,845,949,707,84,683,701,90,903,664,752,286,98,167,625,817,777,535,59,93,257,330,110,164,578,664,562,352,570,707,170,859,289,582,28,621,9,353,54,436,618,556,759,743,144,611,270,806,117,280,756,599,607,871,237,441,235,38,787,359,477,451,409,711,54,382,438,855,771,565,570,748,52,994,811,799,462,754,459,803,136,507,376,259,963,972,992,324,845,459,749,583,855,756,356,43,512,850,736,707,361,878,531,551,797,514,746,144,43,852,759,796,229,422,380,575,363,212,979,717,925,818,615,130,435,825,386,736,751,991,641,191,596,341,632,655,539,826,303,656,435,183,287,273,115,630,469,680,237,583,3,711,434,660,49,967,553,475,361,377,976,452,357,28,339,792,945,549,703,205,767,935,303,338,411,528,697,426,911,310,784,975,187,988,47,306,85,650,373,904,923,70,616,161,460,742,685,138,686,614,613,420,170,397,555,789,477,697,961,202,250,904,66,48,64,570", + "436,493,135,208,967,484,341,16,364,304,922,925,851,741,76,549,283,469,6,498,323,951,209,172,456,962,365,761,141,27,422,535,339,954,85,383,955,614,723,772,901,247,456,757,357,602,3,749,140,37,402,221,981,976,987,411,617,563,173,916,40,306,568,659,27,340,391,141,161,603,967,736,692,896,186,398,544,971,521,974,77,880,19,649,333,692,214,480,535,712,663,57,250,353,646,160,143,290,885,556,498,643,141,323,38,296,623,332,555,725,746,859,157,265,515,758,326,131,729,573,847,208,119,184,661,518,992,931,135,288,422,151,586,880,751,536,156,986,391,32,274,177,467,720,753,398,437,715,903,530,100,780,793,697,655,636,929,989,221,509,310,3,682,0,900,967,760,768,517,819,224,238,489,864,363,496,368,675,357,661,971,157,642,47,474,973,966,222,917,157,193,29,995,725,737,930,611,226,868,20,949,910,190,501,825,874,366,177,698,573,825,59,701,453,173,337,869,247,955,783,189,441,896,692,49,751,834,750,611,506,889,903,142,225,653,486,49,87,426,452,111,35,913,918,875,795,526,127,447,303,618,67,650,726,737,321,705,379,106,886,37,994,314,950,487,498,885,990,197,518,863,95,430,898,491,395,183,128,150,446,610,488,689,422,173,860,132,468,496,387,941,708,798,940,870,534,347,684,557,352,521,319,188,417,444,35,572,460,506,931,318,931,471,806,317,382,105,736,943,78,147,276,914,718,120,398,40,108,326,677,579,595,380,29,911,553,787,201,359,126,269,528,649,883,262,849,121,661,696,960,274,203,441,164,293,492,794,965,353,739,673,450,849,584,999,203,682,430,221,878,279,991,153,923,776,102,92,190,986,427,120,791,563,173,796,411,17,152,878,580,833,381,549,130,145,159,74,979,640,622,125,53,409,59,592,303,737,362,419,14,416,946,1,446,100,355,996,108,246,280,501,821,172,848,808,219,706,56,671,326,900,680,896,689,110,212,628,866,793,315,815,615,136,196,631,605,728,962,160,165,856,105,813,21,786,870,104,969,152,438,836,682,302,234,214,622,235,67,467,934,478,604,557,111,508,924,230,270,134,772,674,845,622,577,575,800,758,928,420,408,653,501,697,657,687,202,580,582,434,880,791,11,609,683,487,303,634,709,69,145,687,898,839,209,139,534,87,674,290,828,643,41,658,105,689,601,758,239,895,851,694,9,522,787,142,759,973,131,355,369,823,815,3,748,466,474,422,313,964,628,965,720,817,552,143,264,240,114,531,531,156,980,303,310,604,745,404,587,775,918,506,344,35,56,326,270,367,875,608,700,45,947,739,563,683,698,29,382,139,284,260,848,908,866,564,488,395,19,615,246,20,423,282,130,819,655,684,65,158,880,562,898,488,595,841,735,597,283,907,93,930,984,892,994,902,649,123,530,269,472,920,666,931,832,281,384,344,613,624,173,722,373,398,974,466,75,578,858,497,693,656,65,861,168,886,571,110,340,925,145,654,432,772,436,486,607,851,70,446,57,494,685,792,458,772,107,34,241,278,37,354,6,391,783,796,354,840,823,294,773,308,974,219,251,525,934,598,65,342,273,913,186,770,548,247,453,441,532,28,788,505,732,531,81,827,609,842,279,745,520,446,418,808,619,623,862,208,283,256,649,527,298,998,948,459,960,488,295,59,822,71,578,201,335,438,853,75,249,608,268,491,897,991,554,484,690,922,457,784,741,127,68,852,420,375,42,246,495,995,635,421,90,940,850,399,535,561,753,628,774,668,761,270,682,148,762,476,805,910,905,238,648,639,182,449,135,361,888,613,366,506,636,979,703,649,697,55,290,307,854,152,641,150,946,460,147,549,221,255,266,918,911,553,65,466,976,659,283,567,9,353,958,89,803,688,993,700,813,348,710,841,454,430,412,412,704,839,885,499,915,30,789,882,851,215,958,828,454,509,961,801,602,420,832,514,824,837,182,928,28,14,984,35,853,754,57,689,775,510,170,346,700,825,681,733,905,932,657,783,365,515,906,22,229,681,430,87,445,636,845,997,787,304,68,928,439,227,456,398,281,682,308,457,151,631,558,334,483,199,232,739,202,408,678,881,311,472,13,35,129,968,532,827,969,706,762,825,706,444,695,8,344,225,187,368,244,57,197,749,45,94,453,993,875,875,603,320,61,340,165,614,472,630,749,649,961,386,578,609,977,225,676,694,415,601,96,656,277,819,891,533,430,656,388,739,614,298,624,974,718,669,278,119,276,637,112,400,570,596,503", + "793,370,932,83,781,873,215,621,290,625,274,635,248,86,518,515,21,430,40,299,140,934,909,122,103,787,155,314,899,407,424,398,185,172,180,326,391,129,479,336,702,961,901,535,269,24,435,734,556,529,650,763,344,693,392,72,331,977,1000,410,282,692,194,87,132,853,109,28,827,785,248,15,911,285,821,152,313,370,297,442,59,902,434,765,628,737,344,682,84,689,954,601,226,124,687,847,948,15,463,921,76,946,979,385,389,732,523,798,158,262,894,925,684,880,784,431,794,184,893,111,216,959,651,889,158,299,163,854,774,467,585,412,989,356,766,769,619,862,585,999,855,952,587,982,774,220,612,168,799,497,918,471,527,104,447,750,997,516,86,277,15,519,559,900,0,920,614,201,389,800,48,367,610,540,845,948,891,237,721,11,563,543,668,942,938,669,157,391,591,194,660,899,49,409,87,623,831,588,420,613,406,157,750,392,999,352,23,363,738,953,772,686,763,776,800,199,587,670,731,398,769,46,621,701,445,423,253,248,914,284,891,837,810,467,412,600,446,57,944,607,250,21,786,338,530,276,960,228,262,981,788,443,477,179,391,668,302,543,691,485,525,494,214,297,497,682,908,894,289,376,89,900,8,973,232,260,723,130,262,475,297,276,209,957,416,722,170,249,81,731,728,55,249,607,821,992,571,259,789,511,637,907,516,818,112,26,899,158,173,787,801,486,675,807,783,740,226,616,383,367,761,965,80,913,512,231,684,354,489,213,272,261,584,274,656,30,380,341,629,566,975,475,372,818,423,722,191,269,409,830,936,634,27,677,565,982,963,529,978,449,537,1000,739,140,983,278,128,225,225,200,894,716,950,97,408,200,631,132,64,801,234,7,145,166,502,980,485,360,469,509,74,322,355,846,110,163,686,213,468,401,634,104,435,517,299,304,861,254,569,436,915,371,467,579,370,724,702,315,174,271,425,912,364,720,338,326,178,518,690,905,743,236,445,212,648,552,994,206,711,967,890,683,203,202,74,578,130,533,113,147,938,667,708,258,951,778,860,587,879,820,245,141,919,859,844,597,559,154,584,760,856,811,963,227,963,860,652,204,508,877,669,542,750,904,650,967,269,116,633,499,272,386,985,975,506,371,763,889,759,556,164,185,222,472,93,88,666,32,406,620,121,573,355,256,125,318,610,505,733,736,379,91,290,877,151,955,320,320,882,227,833,235,760,529,340,604,863,522,211,446,979,987,135,240,58,945,575,548,945,616,525,448,182,587,265,126,878,123,51,508,959,167,372,859,42,810,404,756,272,68,325,751,44,460,944,95,119,2,181,321,711,253,618,237,519,9,88,145,324,526,128,644,810,869,515,473,879,330,629,947,54,56,785,655,463,391,696,287,303,156,878,742,511,812,746,479,368,415,560,817,515,861,12,779,630,889,937,999,320,491,67,833,447,656,560,705,829,224,922,408,879,427,242,424,968,129,210,323,264,298,920,704,846,213,60,130,952,489,141,652,284,985,947,145,626,955,583,628,719,875,455,372,987,573,827,233,559,290,197,404,25,248,683,308,876,54,104,87,397,737,60,465,791,20,484,830,912,249,265,710,756,529,135,367,624,278,55,712,192,63,519,471,701,367,763,322,273,643,882,62,986,666,772,77,336,752,9,591,831,652,891,514,979,688,114,609,551,7,290,919,922,456,738,845,258,676,153,243,209,856,943,720,294,166,450,918,15,661,118,447,746,881,927,690,358,347,951,466,810,484,899,252,420,217,55,472,158,142,265,582,531,556,691,979,841,22,373,950,627,518,259,290,102,389,264,700,875,501,505,355,214,958,139,130,313,413,687,949,647,192,610,357,873,87,293,886,932,467,540,209,672,393,372,649,475,26,530,43,970,398,36,443,453,77,298,839,938,769,111,724,55,288,253,860,147,101,429,597,408,980,481,364,679,469,724,644,831,592,517,109,818,956,524,776,407,353,483,242,46,704,311,840,425,192,795,490,407,820,273,54,135,505,259,881,197,369,564,277,196,752,845,145,956,154,571,661,224,859,507,456,408,172,546,684,622,868,194,333,545,77,764,865,150,33,487,672,649,621,408,979,278,558,545,454,499,85,625,90,542,853,141,709,246,119,446,848,194,57,467,364,279,925,673,183,596,373,20,526,755,816,418,459,976,992,243,555,457,957,779,271,917,467,135,531,659,31,933,701,392,651,902,588,151,109,416,861,966,402,827,706,872,143,770,567,387,669,547,318,632,752,808,1000,349,897,705,601,857,838,789,554", + "189,512,785,916,41,694,940,938,121,552,836,866,911,238,828,122,749,871,969,111,264,716,473,388,371,729,388,477,708,184,712,285,150,58,320,46,79,719,467,431,412,61,677,215,433,14,541,237,79,316,790,42,92,794,602,419,33,939,824,122,102,334,252,496,472,317,121,201,437,659,448,746,270,643,167,339,157,90,166,594,501,773,447,781,951,208,102,520,341,147,654,670,548,285,834,483,607,287,531,188,76,682,528,303,882,4,334,808,922,777,962,702,119,176,930,637,742,364,974,257,844,178,436,458,630,564,242,853,885,414,896,207,718,528,855,125,998,958,308,699,130,184,740,241,333,704,137,710,301,156,266,514,939,182,728,172,46,631,893,227,380,341,170,967,920,0,566,463,969,959,505,25,843,751,884,228,681,395,365,984,64,530,538,355,762,602,357,739,601,93,133,676,364,625,218,891,269,627,145,256,638,990,297,210,841,255,42,144,58,531,642,127,813,162,690,152,516,342,457,396,647,564,99,325,332,501,143,546,429,79,280,592,819,675,246,943,368,558,148,85,416,876,142,489,878,752,127,18,463,16,333,60,763,936,892,407,239,605,460,448,936,110,522,107,85,276,779,968,773,128,639,887,680,619,173,678,620,899,565,168,39,670,573,110,44,806,27,878,790,387,6,750,403,629,323,570,432,664,323,6,424,687,720,600,992,657,435,695,957,585,513,94,14,70,119,104,934,810,35,721,97,685,587,820,995,287,399,956,350,639,310,675,824,780,268,591,369,641,374,141,971,984,570,193,748,663,373,993,469,603,890,804,434,351,575,398,839,929,510,724,773,859,863,617,689,355,585,306,756,193,706,580,197,780,678,937,716,837,457,459,61,639,828,687,766,760,691,135,135,250,828,831,736,898,896,534,898,100,54,664,44,142,848,250,659,775,931,79,865,287,295,800,333,911,920,619,152,415,851,152,382,735,110,671,941,437,104,13,80,379,720,701,755,221,103,742,473,836,644,896,428,948,393,6,627,247,218,124,171,979,185,188,521,385,46,201,482,689,166,150,195,499,258,968,353,60,277,658,190,755,821,353,328,679,710,633,690,601,138,592,461,102,420,624,542,931,386,117,115,588,220,661,242,114,153,939,163,439,11,629,980,498,571,760,532,898,432,465,646,696,343,661,578,979,665,194,190,199,919,801,16,158,689,337,788,567,385,188,709,825,43,69,115,430,322,698,533,578,45,567,66,439,57,470,949,525,768,893,246,121,53,152,659,807,206,241,522,12,613,150,464,823,275,815,103,478,365,402,573,601,957,505,125,67,382,981,91,839,704,736,856,870,271,611,533,673,160,640,896,606,968,882,377,233,62,773,405,247,156,387,817,708,804,780,547,287,137,256,498,387,717,837,416,312,295,353,469,903,938,29,942,337,441,346,692,445,590,832,394,226,410,948,664,737,308,954,714,215,391,563,831,365,523,445,995,624,884,600,135,179,279,339,189,318,540,521,4,271,243,17,231,222,953,619,510,750,933,780,145,237,306,399,810,603,823,766,522,110,107,544,837,19,33,478,225,763,508,233,811,106,234,941,465,893,14,401,723,689,49,382,385,795,679,70,627,239,658,944,673,881,218,459,615,166,586,851,551,47,944,256,806,978,336,569,668,394,748,797,805,705,66,952,281,133,910,171,777,533,533,174,560,251,835,145,276,837,773,411,334,547,474,770,570,106,407,454,260,23,252,63,897,613,148,440,767,177,692,552,877,177,601,316,184,158,530,732,280,689,771,43,513,268,71,514,457,795,581,538,743,243,377,148,727,50,81,709,764,843,570,738,782,470,69,378,118,410,370,833,648,772,613,207,279,144,930,27,808,52,395,430,507,142,718,855,180,193,541,531,999,751,562,177,297,253,730,68,65,306,837,824,471,95,155,397,664,393,454,392,883,513,648,535,716,33,579,375,752,984,983,123,700,635,996,604,915,687,50,543,216,663,70,891,370,768,797,174,955,473,44,808,78,410,163,685,525,75,119,224,688,257,662,210,127,215,834,629,829,143,390,108,994,368,83,177,848,156,588,757,363,46,543,747,77,825,280,418,460,851,175,258,962,161,444,491,105,5,422,142,138,683,925,295,607,205,550,56,356,785,599,72,403,217,796,710,691,305,266,174,511,548,128,875,363,443,885,248,153,577,574,143,311,33,517,258,242,479,152,288,941,130,8,331,305,356,515,726,430,103,742,460,606,737,435,492,810,772,811,423,355,272,856,37,234,273,467,927,366,544,116,235", + "926,817,923,373,271,607,618,983,831,300,203,371,958,844,597,199,500,815,578,476,48,990,713,677,936,702,439,278,979,641,858,688,739,523,545,522,970,958,222,27,187,195,505,330,177,203,678,299,558,369,718,622,547,11,14,857,897,435,160,444,813,357,687,644,939,456,570,973,427,409,423,790,265,160,658,659,900,787,957,654,981,715,870,118,436,988,791,436,723,709,704,468,861,440,749,978,681,716,15,57,432,417,205,911,215,536,132,327,453,569,379,323,71,305,245,591,502,773,339,642,30,144,817,617,313,957,874,7,266,65,410,470,967,99,468,405,893,915,279,843,897,147,523,336,990,278,461,459,741,820,184,219,577,422,951,207,186,811,928,849,402,267,179,760,614,566,0,576,135,254,969,926,409,386,329,276,349,849,756,294,801,691,618,48,993,177,619,347,526,303,188,150,944,494,436,916,586,389,112,326,358,943,107,342,770,993,679,472,767,629,163,564,729,977,33,127,745,922,628,76,204,370,111,126,129,424,187,285,102,891,129,782,318,493,595,217,690,885,648,243,137,890,731,327,7,397,200,569,580,159,481,201,874,520,280,562,756,329,8,18,655,777,453,944,661,997,493,618,793,341,773,214,578,882,623,832,515,113,143,204,542,948,197,446,76,264,682,339,155,733,225,140,927,701,136,566,903,972,697,905,627,769,622,820,49,269,432,80,496,246,659,449,450,904,402,992,772,993,345,73,887,419,270,27,788,106,848,23,352,418,19,206,147,326,57,237,774,979,558,356,282,593,146,425,717,630,958,476,940,460,603,681,24,695,696,124,799,458,250,254,115,777,337,593,547,752,773,820,873,404,843,636,512,985,244,989,683,671,529,938,91,929,461,201,281,936,967,620,693,62,171,331,749,118,167,46,438,474,819,423,685,91,263,12,496,57,498,739,705,261,732,438,510,233,339,175,936,30,160,854,345,452,482,578,660,914,588,786,336,482,357,46,271,934,854,691,759,69,732,578,421,934,179,945,437,915,382,691,663,989,894,696,225,271,571,405,46,739,300,866,299,267,796,559,434,16,238,977,637,861,40,667,434,92,166,326,642,242,417,905,432,702,423,263,915,689,511,659,320,985,461,214,379,459,628,780,849,296,605,389,688,811,462,171,774,182,657,850,179,782,64,818,257,763,831,884,555,132,792,302,449,45,150,577,869,809,765,126,464,969,488,634,805,944,697,2,769,662,9,874,879,487,525,67,474,340,954,793,138,956,204,55,185,730,311,117,510,732,536,594,254,783,275,877,722,349,656,610,703,71,988,400,56,712,542,785,102,366,673,270,836,787,160,190,118,984,554,654,337,199,302,942,259,237,241,328,12,968,684,933,427,845,619,822,859,147,328,658,741,324,509,221,126,269,259,783,61,72,524,328,757,913,938,804,948,216,141,194,712,582,979,154,20,655,875,578,99,583,532,515,330,998,745,408,84,162,638,324,689,507,987,685,467,166,145,790,233,287,591,892,985,743,107,550,857,753,798,71,870,651,764,280,935,535,712,182,927,170,947,528,48,839,138,506,629,760,419,246,478,183,201,329,909,773,65,663,588,752,844,141,663,194,756,262,53,897,640,944,73,758,481,368,597,990,95,584,632,173,516,81,792,387,985,3,983,461,758,947,671,564,89,945,470,696,589,732,213,31,296,748,785,324,474,110,135,769,221,851,330,170,150,553,187,344,775,907,475,185,963,548,653,83,775,514,729,654,299,897,575,775,41,449,298,708,774,327,171,898,257,634,459,891,584,831,714,36,87,561,262,928,572,563,11,50,235,137,591,788,524,279,361,858,640,787,61,72,180,848,203,926,382,671,806,855,536,232,943,850,488,196,698,655,164,79,860,270,666,694,388,783,963,669,578,543,530,155,667,550,387,427,238,54,455,309,689,322,405,422,627,848,951,882,454,659,326,66,88,624,849,268,883,232,176,218,244,398,604,474,929,288,479,16,437,673,324,339,484,244,728,691,883,479,14,770,12,878,630,364,20,598,509,720,737,956,663,490,284,836,38,586,143,185,874,569,424,401,943,223,363,462,487,802,703,332,37,380,109,93,879,447,690,647,292,964,620,491,476,116,202,913,184,1,546,202,843,61,599,354,759,79,527,928,519,68,274,829,842,780,198,136,604,182,484,852,616,396,662,55,790,71,428,212,13,29,437,62,624,226,530,799,969,539,779,486,745,902,387,650,691,729,643,657,39,833,850,528,616,461,722,605,894,482,47,717,821,83,981,42,173,52", + "442,584,240,413,412,736,140,853,447,340,712,982,927,624,754,867,570,958,562,811,38,924,662,157,329,906,16,213,627,90,906,98,861,476,200,660,229,315,179,552,114,6,281,428,910,459,888,512,551,319,948,555,68,869,829,28,838,850,187,446,684,239,298,697,246,55,560,885,17,697,172,90,755,735,419,698,602,383,652,795,917,198,973,549,494,445,603,293,849,515,367,252,677,304,593,20,45,449,526,966,317,757,685,124,398,922,137,769,191,788,931,321,72,399,458,76,193,255,657,859,398,167,257,596,868,511,248,661,644,815,562,216,764,312,555,859,255,52,616,476,882,488,41,979,896,942,95,29,994,900,422,823,482,927,630,292,643,243,185,445,85,34,793,768,201,463,576,0,198,972,269,468,73,915,300,856,200,559,529,524,205,598,208,347,178,66,750,579,729,763,307,223,351,860,945,340,831,765,218,519,570,316,762,428,531,74,877,915,781,290,891,237,538,854,688,545,777,796,548,88,812,410,533,751,473,589,908,719,188,79,179,827,398,330,7,597,400,231,683,422,517,307,512,778,743,148,22,233,749,795,917,754,693,854,933,3,443,809,623,627,581,532,93,674,722,872,476,368,913,265,45,162,946,541,238,972,405,356,701,176,915,278,912,644,301,374,821,147,820,241,856,926,517,477,162,258,200,832,975,388,926,861,702,818,97,330,628,617,462,131,247,576,457,460,229,145,949,411,406,340,215,803,177,253,821,544,827,81,878,917,121,923,187,913,510,627,209,8,300,193,51,673,828,823,873,190,118,341,770,16,932,464,62,754,254,521,501,602,424,587,116,572,889,350,213,799,590,868,580,470,489,465,807,260,700,772,518,207,572,424,298,4,670,998,466,911,976,777,498,958,791,524,13,566,953,483,282,383,775,291,927,383,12,845,678,887,161,586,502,695,29,624,540,768,162,739,438,913,28,407,161,183,60,120,413,872,874,314,164,530,599,852,7,626,833,101,635,230,322,800,936,945,116,351,365,43,652,149,287,286,927,461,921,265,553,240,908,328,640,417,993,317,136,698,926,195,810,381,363,158,502,682,725,203,657,73,168,320,343,885,881,326,604,184,873,291,825,235,114,810,666,952,713,13,752,131,64,36,145,224,872,408,120,953,699,611,661,105,152,505,93,430,69,950,832,677,515,891,747,922,297,356,1000,230,319,463,881,68,546,47,496,562,922,302,324,623,418,867,336,368,192,615,299,127,115,931,733,860,347,209,874,220,440,87,219,380,179,972,948,746,257,969,390,123,917,443,462,89,284,907,572,143,81,25,37,432,876,291,521,142,554,254,515,21,388,618,842,664,830,818,930,631,358,30,447,746,202,200,323,675,37,917,462,76,2,454,476,875,569,196,794,626,678,383,894,898,685,958,260,355,55,637,710,402,626,231,491,437,960,108,148,253,366,365,737,104,536,124,718,793,319,680,533,631,831,570,594,3,351,14,851,752,297,91,868,948,265,787,645,742,795,686,8,303,869,915,887,449,438,440,289,775,796,116,787,558,886,160,321,325,464,795,381,48,13,808,583,998,399,862,734,823,753,156,169,427,820,137,506,975,382,702,918,943,155,175,266,269,125,144,656,593,474,722,442,680,970,899,421,854,845,419,458,270,566,682,40,247,279,255,764,533,18,620,995,127,304,471,593,730,513,931,916,947,937,155,50,314,755,262,451,742,928,487,71,696,75,567,259,686,220,563,59,101,973,466,772,577,433,342,336,982,389,784,930,719,661,331,496,953,354,302,473,124,56,356,14,946,815,351,650,444,275,767,690,414,209,762,757,671,235,74,324,290,363,177,521,801,673,273,939,144,880,515,737,206,731,694,999,966,292,86,695,969,742,307,526,929,984,18,22,655,315,570,398,954,968,591,481,170,801,392,492,48,674,255,777,237,595,725,376,411,275,543,161,496,428,924,918,193,718,80,81,176,173,483,505,730,803,507,189,214,175,798,453,974,92,608,408,733,389,808,932,99,485,864,637,123,211,544,133,944,163,410,919,771,242,421,820,610,731,741,826,965,898,823,127,983,170,585,76,395,879,264,38,659,865,880,157,598,886,367,988,532,434,598,718,920,505,930,168,897,438,672,244,837,683,228,801,860,229,606,221,524,93,738,878,178,696,281,990,813,845,593,312,523,397,464,286,290,693,56,968,192,325,717,195,26,834,753,934,66,644,200,127,149,292,848,308,638,263,715,953,432,420,952,257,583,936,938,191,22,1000,445,975,866,58,831,392,392", + "465,872,390,642,854,713,760,129,54,275,257,618,471,344,817,262,703,754,77,985,335,530,326,318,666,600,15,435,280,637,65,407,406,507,90,303,928,57,227,865,433,895,109,608,110,250,803,992,220,3,194,125,413,107,554,198,457,323,770,408,227,873,174,154,334,538,745,993,8,441,923,345,497,289,910,763,903,820,88,548,647,361,550,370,317,54,693,321,142,194,905,234,300,455,680,973,971,725,177,153,151,437,112,501,309,37,330,987,417,548,373,573,848,155,547,35,452,411,459,933,196,393,639,812,382,775,193,6,648,470,153,105,277,18,954,437,156,164,556,985,922,272,381,566,65,233,195,719,915,545,710,918,995,706,957,758,123,572,128,304,475,787,801,517,389,969,135,198,0,64,153,270,883,818,408,696,590,317,834,745,465,29,91,346,233,87,47,641,88,890,730,292,536,840,421,646,362,133,50,341,346,470,304,989,60,55,924,859,528,341,237,530,106,495,358,598,370,722,813,710,594,179,805,50,540,372,622,797,296,306,544,62,920,823,783,895,149,815,211,783,27,499,777,951,826,848,161,738,722,501,354,685,700,34,561,764,273,313,301,26,651,364,121,624,480,607,972,199,282,955,778,358,583,891,385,319,548,854,90,533,800,480,701,49,431,76,622,15,11,786,966,227,905,701,113,110,474,67,978,397,642,507,789,139,533,546,76,507,899,707,906,447,638,12,812,618,752,639,740,262,133,158,374,798,532,555,542,80,494,616,18,627,396,454,913,473,952,655,159,211,928,925,294,215,748,991,320,562,608,869,656,270,216,793,14,366,576,456,303,990,19,97,476,454,554,499,601,635,317,430,683,18,88,484,558,773,658,282,483,82,272,794,986,99,40,30,121,922,276,833,638,99,459,274,148,983,758,5,937,687,399,750,281,100,982,106,637,894,344,221,179,528,766,347,629,244,490,572,453,629,921,761,293,619,702,636,573,33,501,995,220,698,114,423,964,151,387,432,14,161,109,471,670,910,79,654,323,880,993,17,670,62,695,349,591,908,635,850,798,239,634,704,874,699,122,546,380,906,709,984,461,296,822,595,778,531,395,680,64,356,115,335,377,502,674,206,901,638,556,393,622,674,552,432,781,693,963,704,117,156,692,280,420,149,408,694,838,386,893,683,186,509,484,636,840,580,811,458,152,156,411,863,12,870,507,506,823,645,305,290,448,542,175,769,291,504,530,10,737,875,720,960,156,820,980,80,244,100,726,286,634,224,809,752,581,280,973,461,761,586,696,839,109,417,995,424,307,913,412,142,236,447,537,164,395,818,552,709,493,450,903,211,788,56,499,344,121,790,436,223,430,873,1000,352,637,883,134,408,544,466,76,364,23,895,104,106,719,226,88,984,920,920,235,149,934,344,793,370,887,580,263,8,328,295,885,767,453,949,233,547,544,663,474,973,656,450,845,150,897,366,496,132,429,747,265,258,22,899,786,242,190,357,458,582,58,63,634,957,831,59,523,564,287,390,889,277,145,616,45,443,131,393,622,913,942,355,348,687,501,139,318,347,830,203,505,163,182,585,275,608,260,281,924,304,880,146,977,694,72,895,642,794,216,298,855,156,351,118,683,458,175,281,187,855,126,614,645,394,300,254,69,74,340,955,423,204,457,694,448,345,400,688,90,972,18,967,800,884,638,562,229,230,615,279,180,24,994,485,372,636,999,825,320,253,482,868,216,410,423,770,551,723,899,962,545,971,43,630,520,425,207,865,641,888,790,26,479,857,808,516,130,870,500,103,631,98,33,535,698,737,807,904,531,180,630,440,5,573,282,14,355,564,83,264,186,828,907,842,970,491,273,403,950,394,263,896,889,312,985,275,825,250,508,298,878,938,927,219,727,971,916,964,111,618,111,257,789,715,600,324,351,448,477,67,103,997,490,45,630,552,662,742,812,179,353,458,61,339,798,678,505,109,447,785,661,124,286,66,318,253,84,120,977,605,628,428,146,850,153,476,740,320,230,236,146,225,551,558,107,850,538,589,215,246,23,804,575,337,864,445,956,728,245,744,495,745,396,527,105,443,206,250,176,6,299,519,997,82,177,15,998,318,590,226,610,471,405,632,258,701,916,926,321,545,441,14,633,871,448,286,423,279,881,463,173,833,958,673,98,512,245,155,633,850,602,917,920,367,248,335,448,869,345,117,253,918,331,407,498,514,920,656,368,99,820,218,443,653,847,443,634,484,733,338,882,880,387,400,622,588,684,226,939,804,635,577,643,983,788,409", + "225,221,636,157,961,371,427,116,76,986,866,354,818,283,721,296,271,652,279,132,333,124,509,482,348,679,217,600,645,653,813,710,895,247,84,37,217,675,619,545,472,414,478,139,848,873,649,876,544,254,636,298,952,94,981,297,177,102,720,586,268,901,552,878,184,541,388,241,11,513,94,252,463,840,599,836,845,60,120,316,614,816,144,725,457,307,949,431,957,925,883,918,215,573,592,291,849,119,68,708,962,659,117,232,755,919,283,433,378,718,570,353,524,32,872,893,107,215,21,630,35,638,173,187,594,769,242,199,299,739,696,31,836,554,703,871,938,208,759,734,10,324,831,331,35,621,892,469,33,348,796,345,318,320,815,825,282,668,907,402,646,923,913,819,800,959,254,972,64,0,327,944,277,707,5,885,775,158,501,181,734,532,787,186,528,83,696,875,230,690,318,45,349,650,211,844,735,173,482,811,370,538,724,17,86,333,116,12,677,847,220,261,373,912,931,506,910,999,621,17,124,729,557,186,224,234,532,427,901,747,138,897,730,129,933,419,741,352,176,202,641,416,259,668,162,377,606,573,87,824,530,282,835,635,654,146,309,218,340,314,522,998,65,2,399,348,437,969,461,839,700,499,247,480,865,771,899,99,885,560,260,893,535,14,622,535,638,909,430,487,662,371,849,27,349,361,151,620,97,732,419,162,95,352,792,434,96,689,542,392,653,774,292,527,10,86,982,331,302,158,383,260,762,253,612,30,875,535,214,296,474,178,973,582,637,817,227,474,730,361,781,428,100,825,523,844,802,60,832,790,51,19,325,995,811,772,13,624,176,269,941,454,967,272,927,863,879,799,230,852,222,233,484,646,341,215,53,707,657,372,255,381,855,900,157,725,690,313,836,937,621,337,961,75,152,797,583,420,931,855,800,685,997,47,598,863,548,72,44,60,903,103,422,212,605,294,591,280,251,21,105,499,730,433,509,579,567,769,144,800,642,889,481,944,636,523,302,670,964,340,501,599,129,86,738,694,775,770,436,886,37,421,138,998,33,385,136,200,981,625,528,857,852,486,321,171,207,62,949,81,515,893,239,708,169,176,26,571,563,796,636,625,7,738,335,700,393,515,445,253,714,722,180,153,32,198,639,200,670,127,245,952,779,289,858,994,303,552,173,839,76,560,702,77,202,188,81,656,938,926,635,575,539,546,807,176,434,9,87,535,644,121,840,690,381,133,697,757,34,710,547,704,25,327,537,653,635,12,708,577,978,494,813,698,149,54,518,514,153,899,527,907,998,577,763,563,902,183,558,966,741,36,449,510,293,527,148,871,64,931,296,280,601,913,964,194,785,666,417,758,134,32,382,914,740,850,879,710,694,114,241,243,321,958,16,126,450,733,973,199,15,327,152,111,636,79,443,498,18,334,623,632,837,562,35,473,26,354,343,526,667,691,685,101,115,171,609,641,194,187,968,157,427,510,23,444,693,388,348,71,935,253,247,377,900,660,811,717,567,884,844,175,238,610,615,605,838,134,680,589,504,998,762,580,796,194,388,278,54,198,491,470,902,729,235,788,491,478,579,161,175,443,162,177,368,344,508,949,968,647,266,338,141,69,144,670,45,932,455,124,678,712,380,145,179,966,928,211,856,170,760,846,513,322,789,978,10,47,965,759,802,551,977,841,23,980,926,210,64,215,182,150,989,789,668,85,379,869,775,383,646,569,340,358,528,762,575,903,180,482,573,568,368,350,533,165,66,494,129,493,610,41,599,410,200,252,58,681,530,599,578,255,611,56,519,571,610,379,391,493,989,664,216,342,580,220,632,299,919,943,272,877,393,729,378,684,903,70,32,79,972,756,761,664,793,405,196,763,534,587,40,317,131,675,747,985,699,57,526,665,138,55,648,250,466,932,658,28,333,242,145,662,576,887,121,325,384,115,171,3,928,816,493,553,615,74,331,412,941,848,442,741,21,275,327,166,523,892,793,265,711,555,788,697,678,96,939,604,144,892,643,152,713,989,572,827,316,799,681,635,6,623,537,272,265,781,474,67,159,449,810,178,880,99,84,982,739,893,144,433,160,727,760,533,10,362,170,335,977,74,100,538,536,109,401,874,950,946,425,913,164,698,234,500,14,35,700,422,120,606,460,959,171,506,201,90,961,556,73,153,467,563,239,534,328,724,104,815,13,662,910,760,519,354,46,441,36,252,504,374,907,989,450,804,234,548,325,366,828,453,777,30,106,929,526,301,871,676,483,183,846,11,915,79,793,679,401,525,907,532", + "573,184,534,212,528,559,228,868,45,223,581,97,648,813,957,754,59,816,84,844,148,358,370,881,667,643,974,339,784,291,283,949,234,765,161,222,238,583,442,106,868,687,337,653,188,932,94,89,269,767,354,460,730,525,945,203,686,762,510,901,595,691,78,141,928,309,323,813,488,308,129,969,683,682,29,196,693,437,920,496,41,373,260,396,813,806,118,646,270,961,106,816,64,674,556,34,437,917,716,346,87,301,119,360,575,791,581,936,32,462,160,547,275,945,53,857,473,512,234,384,576,964,831,606,472,915,810,269,977,834,205,972,310,874,598,230,209,26,164,829,341,57,641,809,733,649,296,894,743,527,183,968,888,542,939,767,914,371,435,264,818,527,629,224,48,505,969,269,153,327,0,66,476,45,857,582,690,849,521,462,606,892,259,528,798,798,616,896,539,468,777,173,756,839,328,633,276,50,788,441,277,215,288,947,849,443,643,360,867,305,348,239,527,508,548,553,399,319,719,805,20,766,835,536,395,55,101,776,98,926,23,64,704,624,350,265,659,546,608,975,181,255,461,775,549,694,427,65,475,162,844,666,802,468,793,214,449,119,588,174,562,835,158,660,688,73,187,489,114,216,832,184,637,195,706,989,987,61,60,204,666,201,589,273,592,569,598,570,57,680,891,618,324,993,972,574,689,200,762,143,859,552,456,53,168,258,677,28,884,716,157,716,350,708,539,68,683,561,476,576,146,427,617,722,572,873,155,892,464,328,33,162,700,591,967,872,554,830,776,168,655,350,88,84,941,869,825,803,56,757,656,364,132,229,345,764,155,57,76,635,95,744,676,290,166,18,527,938,405,702,140,522,818,679,34,342,354,539,377,13,443,201,582,883,865,736,729,638,930,791,109,447,227,580,134,807,555,272,264,95,968,294,697,426,224,344,376,31,349,371,568,590,375,713,197,486,827,393,748,82,500,431,58,922,240,706,78,856,903,50,630,102,987,132,744,418,528,718,381,99,12,398,750,357,274,484,376,101,431,498,215,155,933,700,517,785,9,792,536,124,761,722,173,904,194,805,438,495,695,176,617,783,141,334,493,850,901,798,953,817,44,831,782,492,430,319,878,61,529,390,457,186,34,659,989,290,123,828,425,729,521,348,989,512,953,566,151,701,727,505,417,787,526,515,453,325,788,756,586,58,773,843,339,100,248,489,914,589,190,715,64,707,334,612,958,856,134,398,651,962,658,332,723,631,605,10,896,66,826,410,177,791,244,746,766,265,945,686,449,362,503,450,939,117,592,32,88,320,498,461,523,588,26,789,648,518,279,655,965,243,641,537,153,935,151,48,529,798,446,219,968,195,609,702,569,74,542,627,1000,979,604,227,547,240,998,330,617,298,91,937,101,3,278,169,403,208,833,409,740,901,330,165,692,149,950,991,546,476,416,136,869,513,221,150,287,231,319,90,788,447,223,190,574,972,380,574,664,170,212,204,938,67,184,817,336,75,964,689,296,853,503,516,60,995,28,416,629,610,802,369,424,453,583,230,781,209,222,614,76,365,719,823,110,106,437,569,982,916,275,603,841,127,910,359,321,367,898,788,662,513,705,910,335,765,337,579,592,250,604,942,55,905,920,117,44,487,99,950,173,691,598,697,508,603,836,750,648,652,202,966,963,860,701,752,187,540,826,184,623,439,733,853,472,559,142,204,102,435,32,721,448,274,727,698,297,459,613,142,317,274,416,615,298,819,463,910,362,333,805,673,572,915,81,952,586,374,196,773,7,984,198,237,857,823,844,857,319,202,429,319,324,286,57,493,554,77,372,231,341,635,359,616,543,748,999,773,291,285,737,660,502,697,899,781,736,166,266,222,767,974,445,800,680,835,263,352,606,976,826,978,19,444,643,207,820,873,708,519,127,72,804,13,486,790,947,349,785,700,919,99,694,784,801,22,69,556,226,358,415,617,745,992,578,299,780,441,822,438,590,251,128,984,908,58,7,929,97,482,744,352,632,981,572,494,117,390,708,607,79,379,992,521,586,343,549,447,565,925,867,527,968,301,213,249,768,646,860,503,195,378,161,45,107,941,318,826,701,864,175,416,882,426,186,846,83,966,150,70,817,537,651,68,659,378,751,67,851,212,336,727,636,771,54,804,63,175,602,276,615,114,848,597,192,581,326,62,742,139,85,34,949,377,216,848,924,888,145,935,96,53,925,192,447,949,351,826,572,386,7,908,142,695,427,134,193,24,274,277,88,262,401,788,851,502,581,831,595,201,330,155", + "379,321,846,366,724,476,771,436,195,626,518,473,640,60,126,34,350,936,595,395,608,928,814,164,346,976,171,173,743,579,773,305,275,617,275,413,856,153,22,766,402,987,629,119,661,820,961,160,290,798,817,24,897,732,545,109,933,987,373,837,387,97,419,711,343,465,461,322,851,343,625,326,7,339,999,333,622,423,123,292,903,132,255,173,536,277,283,962,509,725,915,680,505,52,510,517,250,430,360,127,964,8,669,195,454,348,615,61,217,940,245,659,910,326,987,859,839,31,238,283,494,890,885,992,226,10,247,628,805,894,341,755,892,720,30,967,272,734,716,350,450,474,815,437,562,220,960,808,909,180,578,771,110,412,334,590,507,541,536,488,171,155,503,238,367,25,926,468,270,944,66,0,868,730,795,927,8,596,499,172,956,394,154,879,320,684,928,300,392,588,431,717,342,392,317,217,540,79,953,285,552,834,662,402,705,317,563,923,428,441,817,474,838,927,401,513,938,845,500,833,559,785,675,783,964,446,456,283,960,615,507,463,157,694,255,514,393,708,764,771,541,873,89,154,649,345,892,38,745,20,730,433,928,455,390,212,151,57,237,739,614,369,200,186,255,549,186,481,93,83,831,48,888,95,330,286,326,288,10,134,489,813,454,52,132,544,551,164,507,326,678,964,114,816,214,345,856,205,281,368,536,643,416,366,692,427,679,199,521,348,503,243,936,572,432,586,497,712,10,724,169,426,3,183,374,169,74,75,559,941,580,375,66,377,166,954,190,954,82,918,167,640,893,232,604,95,737,751,695,143,29,841,298,309,355,84,264,386,748,764,281,310,112,58,134,252,30,275,328,198,449,113,995,821,266,272,419,754,899,815,59,911,502,595,79,392,139,933,730,627,780,375,233,760,3,263,772,891,628,346,658,695,542,993,656,385,844,880,642,601,115,945,701,494,467,41,760,663,980,627,509,923,440,593,492,485,731,317,34,739,993,573,408,302,80,46,304,229,156,638,462,282,308,943,300,831,162,720,142,937,603,985,462,871,144,759,134,815,103,819,867,52,590,87,727,437,226,476,479,83,956,366,684,474,207,255,211,986,889,811,692,621,667,505,358,370,859,772,192,531,76,406,781,404,824,849,59,645,8,327,776,926,417,912,373,754,318,401,887,615,26,799,193,782,253,553,839,991,158,504,861,419,198,427,359,909,118,833,496,857,59,176,699,112,293,187,572,752,813,925,579,949,816,882,42,831,720,994,319,325,797,713,605,13,868,360,575,481,176,750,506,661,973,108,984,287,778,615,168,391,412,683,848,594,902,68,392,606,419,705,554,279,739,515,916,720,531,86,426,568,161,295,77,960,840,417,722,239,670,863,55,812,317,626,174,382,249,910,518,488,299,778,523,982,142,416,999,879,418,406,186,211,97,670,492,987,879,373,261,181,435,849,129,870,778,60,221,641,3,914,930,308,679,234,827,760,886,203,348,676,896,848,82,586,894,386,327,704,846,897,266,900,43,221,172,386,134,250,713,234,522,223,671,696,109,559,506,554,180,189,494,233,622,578,725,781,594,754,79,531,87,25,118,251,463,592,541,916,589,715,333,88,981,692,46,121,529,620,759,746,57,199,831,44,711,35,587,853,68,556,131,206,770,780,276,500,15,202,843,603,343,429,852,236,244,638,705,430,573,537,561,985,433,899,425,913,136,619,589,401,558,374,777,10,483,937,21,58,223,505,719,758,964,640,449,946,432,344,285,566,626,424,102,881,211,427,191,29,970,23,688,200,28,402,900,351,932,678,397,855,618,268,385,883,41,854,151,930,907,186,900,611,248,757,723,487,181,844,445,883,695,826,30,217,486,307,396,556,293,18,36,114,306,302,727,896,778,271,232,379,918,154,545,392,759,799,861,177,998,105,424,471,835,898,303,306,205,363,925,211,195,826,900,681,247,764,819,313,885,47,677,929,163,649,433,304,482,74,540,955,654,187,911,883,452,764,244,349,924,874,612,910,423,929,740,996,336,632,588,227,902,813,178,571,800,184,279,658,335,945,421,346,400,345,939,563,870,904,112,558,312,596,673,154,943,970,248,334,945,766,65,760,871,328,319,597,21,43,816,896,267,356,846,392,215,105,453,743,160,12,61,189,849,207,56,399,179,430,597,332,397,294,580,845,715,629,235,909,789,406,947,272,788,856,209,43,657,384,87,348,373,367,89,111,393,593,122,359,845,273,685,241,186,408,387,915,66,387,812,510,386,113,103,370,775,163,188,678,667,563", + "875,218,415,680,947,446,698,86,375,801,280,293,460,483,819,214,252,572,910,73,777,739,427,395,848,756,282,84,492,372,790,879,341,360,425,70,491,511,728,862,445,847,322,126,929,282,20,518,976,511,614,192,592,226,569,795,504,653,629,837,453,783,117,822,179,466,635,290,841,659,414,761,43,198,634,664,630,552,876,342,831,691,889,354,320,761,425,40,404,271,953,363,759,64,381,652,923,578,732,813,171,996,321,536,811,481,196,309,812,930,297,853,687,777,543,667,561,580,482,771,833,248,51,903,718,230,578,269,454,627,827,823,114,557,179,990,328,929,584,86,974,369,301,979,859,447,917,590,423,164,107,782,188,786,339,292,972,301,526,940,542,245,538,489,610,843,409,73,883,277,476,868,0,108,957,740,669,187,756,453,31,960,430,395,450,904,544,449,798,124,387,703,670,50,540,395,935,518,948,253,683,608,231,950,586,650,16,962,82,59,757,586,11,842,119,91,160,599,566,758,904,401,264,220,809,626,801,414,195,272,993,968,226,784,53,325,337,846,969,783,994,160,484,430,40,9,924,487,633,732,796,512,929,44,76,146,436,190,356,691,466,339,602,946,126,279,146,228,455,374,170,165,159,220,429,115,276,449,528,978,508,529,309,188,90,208,846,352,586,997,931,410,258,624,170,123,205,518,212,977,632,171,864,603,66,382,762,111,532,609,535,741,602,635,866,500,544,14,201,284,832,656,669,397,268,977,679,273,756,695,460,335,62,578,987,337,254,605,277,550,625,449,266,592,58,73,696,75,228,710,772,445,365,993,733,85,240,318,337,149,589,376,115,593,109,285,890,297,457,38,636,766,202,579,447,125,466,498,101,336,239,367,192,219,300,163,643,379,774,370,107,786,17,258,35,87,760,595,719,319,506,691,570,14,358,930,117,2,304,853,432,373,192,241,219,307,515,37,176,237,68,860,795,886,577,103,563,3,773,326,870,138,973,355,724,627,4,939,784,645,89,66,40,181,249,671,941,972,850,73,496,849,296,585,811,486,297,875,26,101,389,678,669,416,139,660,347,767,687,561,11,363,223,489,624,639,817,705,59,189,174,43,358,611,860,652,870,681,45,884,515,7,471,14,810,319,95,616,291,385,448,798,406,538,981,785,692,842,676,662,94,365,494,508,695,449,640,718,630,81,798,39,80,453,334,953,252,532,525,902,563,54,857,671,722,511,594,861,83,467,88,324,268,79,278,764,295,68,20,14,396,260,2,936,244,76,349,953,947,340,589,98,800,53,45,724,865,611,697,660,754,646,357,499,230,95,850,258,335,268,205,331,35,764,963,179,39,98,885,456,622,217,254,160,222,447,976,968,965,240,634,422,320,822,882,783,133,467,642,561,266,278,440,326,371,963,374,314,376,23,803,636,695,917,912,612,67,527,351,926,524,370,321,106,275,851,604,886,957,229,427,766,638,825,655,298,35,749,268,381,455,816,841,603,327,737,974,5,901,855,135,213,998,137,371,665,571,762,253,967,401,432,532,752,92,375,226,103,748,496,560,862,263,304,15,861,815,876,622,782,428,441,627,737,792,669,198,994,402,47,723,76,534,440,22,931,446,916,649,913,458,735,942,151,303,856,191,619,22,705,175,838,971,723,274,100,301,709,355,514,383,681,551,469,499,760,251,485,862,903,352,31,14,485,235,359,544,863,130,651,102,501,745,201,35,901,804,405,776,222,156,15,882,131,762,299,498,698,418,176,590,769,329,491,276,723,947,651,893,440,160,95,884,921,515,172,531,574,939,410,930,998,177,603,105,244,994,214,864,368,590,248,356,376,98,887,656,564,185,215,286,431,36,307,348,805,594,947,714,44,251,848,329,450,216,644,846,28,993,320,103,575,326,146,563,705,984,753,378,557,592,124,542,508,100,857,127,137,244,634,113,443,387,182,332,664,954,805,431,352,945,993,780,187,104,56,84,213,247,724,28,695,575,636,721,529,280,652,504,181,763,234,621,52,895,534,158,619,983,340,422,765,77,38,114,766,904,124,994,596,369,302,56,180,655,65,382,864,556,870,643,698,79,950,246,794,317,60,799,165,492,73,791,235,656,87,537,644,837,744,167,319,466,632,416,296,855,961,956,398,110,417,864,741,44,90,897,136,173,534,244,154,599,464,972,870,120,443,577,991,704,517,20,743,163,688,505,751,356,486,774,485,646,496,496,11,784,439,392,346,650,523,802,894,900,191,19,414,274,551,608,226,648,571,535,374,530,385,726,142", + "620,878,993,482,269,7,371,47,94,650,188,594,869,650,14,761,457,906,152,166,620,599,285,114,341,804,547,322,285,187,542,395,559,750,553,667,154,70,918,266,154,627,600,830,533,884,760,446,111,921,390,11,480,811,437,960,114,104,818,345,75,815,431,924,406,107,561,181,172,339,766,986,328,117,231,396,504,707,969,717,335,25,698,749,540,218,262,18,699,227,990,365,541,692,855,671,612,755,973,633,232,602,97,464,739,449,921,996,523,834,117,485,665,510,495,324,159,906,490,431,368,915,938,95,533,810,795,174,553,929,15,82,40,159,880,8,968,54,916,65,359,747,225,917,614,809,928,477,786,684,21,333,75,536,716,457,81,163,919,858,993,340,884,864,540,751,386,915,818,707,45,730,108,0,606,86,267,114,287,422,638,408,943,716,720,780,503,332,618,67,726,134,612,462,671,213,702,996,636,963,75,131,666,455,255,600,753,663,332,306,912,768,979,444,446,948,818,119,158,186,400,301,354,196,146,12,697,178,154,681,937,261,296,179,372,522,643,597,67,246,529,775,727,180,760,958,57,486,103,986,64,930,650,277,824,609,731,62,675,273,274,791,750,710,431,721,572,791,865,14,963,481,349,271,139,752,974,737,385,254,422,227,40,969,140,592,374,28,259,656,857,428,202,112,423,441,127,756,38,944,722,7,98,468,716,643,262,567,991,810,739,339,773,980,150,557,677,208,62,253,168,724,361,356,195,536,897,191,931,41,321,702,764,851,804,870,823,408,82,451,689,957,779,114,929,917,559,192,404,734,472,35,521,79,938,254,974,302,454,683,682,468,546,760,423,186,248,401,155,857,987,47,161,527,773,164,700,323,550,829,107,925,521,7,603,530,204,467,994,509,566,979,159,34,684,493,922,154,636,570,712,784,105,779,223,44,945,528,205,921,94,867,113,491,185,697,554,376,712,826,136,13,940,143,52,267,34,321,565,729,173,800,406,956,697,786,155,894,841,381,446,536,791,713,842,805,311,671,953,418,780,720,901,79,64,177,253,140,251,739,89,89,344,96,334,828,625,839,725,43,65,438,229,147,291,928,465,33,212,794,623,969,812,908,15,28,904,931,891,13,384,470,751,223,431,33,833,745,347,153,313,292,321,975,548,996,192,513,123,633,986,506,67,560,865,832,723,240,350,739,654,285,661,204,216,155,37,884,210,671,576,636,503,69,815,377,739,866,625,998,578,965,875,831,871,139,352,499,373,671,301,973,546,168,323,445,417,65,769,570,324,204,696,388,845,418,878,608,672,29,410,776,524,491,570,359,258,333,618,635,825,477,472,75,505,599,306,97,923,331,465,556,448,400,508,515,100,888,110,876,15,682,428,961,572,901,894,589,390,438,212,4,878,746,52,399,192,777,434,59,815,708,210,417,783,733,443,661,989,244,938,847,944,647,908,665,236,534,370,871,943,222,941,340,994,109,903,60,903,639,386,280,417,838,684,527,210,956,534,339,428,934,432,394,710,509,51,708,893,62,882,564,668,57,571,653,566,249,146,536,251,142,98,234,128,443,766,448,389,383,481,594,983,308,524,107,703,147,308,369,97,150,152,382,739,724,249,177,232,445,590,951,514,786,688,8,415,419,283,798,885,678,736,849,485,474,494,825,271,163,534,874,547,181,822,155,929,238,622,243,295,567,329,185,615,380,751,973,633,385,279,316,510,818,987,483,60,322,376,152,977,528,582,579,100,146,148,426,864,23,659,239,301,479,528,470,503,417,479,745,721,432,744,880,809,604,594,628,21,548,149,991,234,984,129,208,578,568,214,998,72,394,610,78,476,57,688,261,984,438,525,423,807,773,390,123,107,779,1,734,639,669,402,652,893,705,342,154,261,667,737,708,371,355,509,753,291,262,165,613,201,186,284,857,976,588,786,623,431,386,157,128,625,474,763,212,168,73,246,132,506,828,293,627,401,634,42,49,622,206,934,698,918,894,20,620,60,565,384,624,746,225,601,524,616,395,613,307,360,842,891,189,112,697,622,142,594,974,354,282,793,959,816,894,23,988,24,353,981,391,391,556,309,196,80,700,414,136,547,794,446,565,469,625,409,94,749,112,183,956,121,126,25,503,809,309,961,747,599,909,853,854,653,255,196,981,168,584,694,319,542,421,922,654,255,514,969,432,439,551,312,983,487,14,276,820,954,2,185,104,767,892,460,479,914,852,97,234,854,509,753,460,337,385,816,900,329,295,40,683,684,980,129,275,306,228,273,599,302,996", + "294,919,977,876,7,431,882,806,57,714,924,643,473,935,573,210,638,641,289,162,336,903,808,98,194,197,884,623,95,731,531,559,265,390,718,818,195,350,31,806,769,323,4,688,116,361,979,556,624,902,967,352,212,34,385,305,179,14,486,101,798,688,227,27,330,16,989,111,628,349,300,823,504,497,39,258,753,847,514,345,842,38,886,744,729,97,900,32,395,231,589,636,220,373,322,255,610,914,439,553,860,776,803,6,893,16,304,474,151,211,937,675,639,856,660,347,890,791,619,281,541,746,303,511,557,227,214,481,243,588,690,34,554,733,804,107,561,935,381,481,230,643,476,320,875,874,256,140,362,541,290,269,493,657,558,650,3,9,479,679,272,768,480,363,845,884,329,300,408,5,857,795,957,606,0,963,612,518,99,450,661,446,272,803,836,863,715,373,354,651,541,911,200,50,139,219,949,793,659,849,760,444,78,424,966,877,47,244,459,626,612,551,655,357,329,308,835,520,527,865,604,588,980,659,375,143,38,315,363,251,182,364,835,187,673,148,753,370,926,653,809,374,361,754,210,876,265,697,788,713,303,138,207,744,88,347,700,583,448,996,999,739,747,907,610,350,317,50,930,241,374,583,602,915,409,15,744,143,818,523,98,383,472,518,304,578,5,363,102,648,892,832,734,707,496,218,995,625,395,986,930,128,328,543,106,979,621,843,464,276,938,632,906,266,422,204,378,172,535,622,919,20,432,960,678,41,438,217,266,925,53,962,486,986,654,88,191,696,209,590,899,680,518,502,579,317,105,322,320,79,195,269,62,65,786,559,633,633,65,630,704,971,165,439,460,617,538,39,140,577,96,101,330,581,516,2,958,242,846,264,129,179,129,728,306,956,604,93,42,929,443,124,529,443,273,54,291,121,168,190,28,191,539,950,523,960,372,777,410,703,194,409,282,950,96,636,115,336,616,280,697,705,135,909,922,815,814,135,952,403,27,310,98,316,524,299,97,254,711,229,271,764,860,786,564,796,315,259,897,151,510,494,892,981,822,295,381,670,822,73,349,378,146,923,138,216,197,615,205,863,862,95,744,552,148,371,147,252,361,369,960,723,94,636,341,431,25,855,884,799,634,820,29,333,358,547,784,925,489,873,872,394,697,805,522,334,802,422,419,547,337,621,968,448,396,514,572,409,92,123,737,930,84,753,108,975,157,293,370,713,737,135,827,328,378,885,930,788,811,721,960,551,792,253,397,911,67,992,55,771,922,450,543,364,602,33,566,157,526,41,764,586,24,167,756,966,296,622,517,135,226,567,23,2,922,597,523,394,21,47,390,54,802,507,584,933,873,830,725,448,637,244,145,918,774,412,616,164,913,119,584,887,321,15,54,342,482,302,415,543,122,439,322,45,142,473,415,596,2,468,366,626,903,967,47,69,917,120,148,299,15,645,739,9,223,743,619,818,432,642,615,221,901,398,364,976,859,164,82,580,62,29,967,360,509,408,144,611,772,435,235,143,335,491,631,170,401,747,399,792,293,570,274,523,662,433,686,314,955,756,919,692,409,983,5,794,880,847,52,118,92,948,344,538,88,515,590,291,623,112,964,431,665,290,952,990,950,818,338,315,546,408,104,153,788,579,117,71,250,218,561,191,730,464,997,121,335,253,485,194,565,676,103,940,590,198,759,647,866,647,696,956,343,893,231,112,171,103,535,252,323,885,437,714,644,904,853,655,308,707,894,344,258,44,643,803,927,275,858,381,114,595,313,673,34,45,82,74,257,465,724,814,773,254,485,601,30,88,60,239,135,857,943,45,129,752,752,497,280,94,897,990,10,599,439,896,880,122,306,353,149,695,834,541,757,121,572,518,310,737,488,512,355,639,164,406,765,397,882,881,221,634,421,346,881,416,91,264,808,962,38,273,819,839,644,141,479,223,236,505,506,495,84,850,427,778,122,269,586,464,361,565,349,811,594,886,205,772,468,204,758,263,62,428,523,697,152,809,297,557,872,931,337,583,861,411,859,501,797,650,111,398,839,362,375,281,132,52,289,294,883,198,179,659,951,871,759,715,220,129,654,195,762,269,369,102,295,868,827,503,293,657,450,201,948,219,218,64,704,639,426,292,643,396,60,366,986,146,839,7,572,551,532,679,835,7,328,535,550,131,737,716,861,359,404,560,939,183,630,850,653,120,652,215,266,760,106,404,408,397,848,515,613,295,10,890,231,113,719,658,419,888,202,746,318,40,98,68,868,30,73,320,637,272,167,891,380,755,554,683", + "452,841,910,431,530,981,533,981,589,197,223,262,588,200,342,141,43,438,681,661,460,259,288,131,702,361,937,22,268,514,670,648,618,580,317,330,193,320,479,575,95,243,364,377,307,649,643,430,591,641,624,743,407,78,431,689,342,310,526,284,379,208,306,944,844,847,519,738,747,780,587,492,69,247,226,778,430,782,764,14,920,545,101,793,849,300,834,155,309,834,641,376,321,340,424,726,378,469,983,509,800,655,322,220,866,695,46,901,880,535,274,373,851,173,280,824,947,956,566,360,463,971,626,926,27,358,789,429,671,74,698,816,443,101,293,620,640,756,598,673,587,448,690,112,665,910,942,281,897,841,868,754,537,428,882,989,740,868,103,724,9,390,439,496,948,228,276,856,696,885,582,927,740,86,963,0,961,630,883,31,969,86,135,935,702,387,391,546,350,216,393,539,77,940,899,825,922,791,339,39,323,829,548,333,79,690,366,906,537,783,386,530,169,910,178,615,199,658,645,118,881,422,912,614,60,341,899,518,992,625,195,514,887,275,85,704,749,58,67,555,734,650,44,674,768,145,993,287,886,261,671,649,793,356,726,890,73,358,693,431,45,635,631,422,188,544,597,189,250,615,755,734,623,538,947,244,279,330,164,359,71,845,338,39,846,300,611,639,712,2,477,328,989,145,95,370,250,95,984,804,952,83,415,960,683,917,729,63,284,586,427,517,606,303,106,251,409,935,721,170,520,868,472,250,867,776,664,107,581,415,572,622,981,891,714,314,826,916,801,967,34,145,362,677,448,617,68,882,738,384,145,403,992,347,96,571,775,215,182,655,349,639,379,371,496,779,65,405,402,448,678,59,728,777,657,122,203,728,711,597,884,874,471,975,964,171,776,929,636,319,246,963,507,65,606,198,718,228,352,672,11,645,348,695,660,846,88,702,715,777,900,829,849,117,636,160,943,704,92,30,25,812,591,798,636,184,486,184,479,900,47,635,770,606,377,105,824,181,696,560,332,901,716,507,540,98,110,36,373,150,674,498,397,669,650,477,748,175,573,949,203,823,752,363,239,193,229,581,271,860,208,856,530,170,756,604,485,25,262,818,303,550,918,172,484,838,263,126,993,596,77,713,805,150,256,341,36,508,640,865,886,950,481,514,431,866,552,552,729,662,771,641,821,811,206,479,650,136,123,660,848,470,661,323,148,442,207,152,391,100,402,186,322,268,54,158,734,571,206,588,196,388,461,690,678,994,753,940,890,928,300,311,31,863,800,39,388,615,747,99,938,133,754,101,544,583,248,939,643,607,767,294,156,118,233,580,870,221,420,113,472,424,782,384,393,903,914,527,350,998,986,684,943,173,294,783,640,725,133,711,174,423,861,635,859,757,667,625,4,253,354,31,363,696,467,289,195,882,512,979,603,674,860,198,204,645,668,985,90,384,671,73,78,13,865,485,928,71,414,36,563,932,662,521,256,658,223,89,271,526,585,685,113,675,222,571,201,61,852,866,358,274,122,229,471,869,546,578,340,394,432,377,334,317,371,606,830,84,218,565,886,842,496,920,400,417,842,334,655,587,395,969,345,415,70,442,752,84,533,612,817,83,992,925,756,722,369,769,363,817,807,850,866,288,520,943,498,180,496,726,96,149,606,180,401,49,98,740,218,646,338,85,183,232,815,209,705,145,923,529,953,401,324,804,698,438,412,870,202,498,131,737,791,622,680,461,744,704,791,44,193,56,301,258,612,272,338,632,85,93,508,978,359,184,486,787,524,957,446,136,86,639,818,898,751,630,269,855,92,616,906,878,741,495,339,32,151,577,10,792,246,962,237,226,550,932,436,873,934,811,958,116,147,565,909,661,245,128,708,467,297,71,458,298,409,201,915,76,918,762,669,129,667,749,196,753,332,296,538,938,357,541,29,623,299,782,993,67,408,695,608,771,415,278,931,323,351,535,894,225,110,944,897,147,771,746,764,274,966,154,853,177,595,39,748,505,99,74,655,322,906,445,178,135,800,988,182,627,115,276,857,719,250,240,774,214,139,584,221,866,806,596,543,909,541,260,622,413,759,76,975,66,505,813,593,42,743,743,798,860,800,704,599,611,241,747,176,67,152,211,847,416,346,964,686,717,866,230,896,634,729,490,864,957,38,769,785,616,21,804,24,479,839,25,788,696,546,741,210,456,750,637,302,908,280,768,172,233,515,120,973,284,60,393,325,454,572,790,515,73,423,23,370,741,959,278,409,844,629,741,960,27,71,441,152,63,603,155,92,596", + "832,327,132,961,363,181,728,197,889,186,425,253,539,613,789,746,989,940,342,414,952,842,695,921,168,504,902,708,990,201,555,780,189,999,700,349,128,730,524,285,858,986,117,479,671,824,888,775,566,84,459,369,758,222,134,842,640,711,803,373,404,842,399,106,574,675,69,68,645,947,537,643,197,202,130,852,666,742,541,542,557,161,288,834,654,8,376,471,587,157,289,175,786,766,728,6,897,87,834,629,687,536,38,501,504,73,451,811,72,600,522,242,904,412,781,115,371,508,721,764,585,441,936,151,515,5,426,962,25,559,189,536,73,497,659,132,388,539,716,325,332,612,578,970,834,638,355,477,587,434,934,934,679,875,524,357,39,591,613,846,163,30,249,368,891,681,349,200,590,775,690,8,669,267,612,961,0,364,178,759,124,142,113,577,614,291,132,400,508,552,142,221,353,203,431,656,326,901,414,239,985,355,58,512,219,542,159,461,856,107,759,326,117,339,968,627,229,832,912,476,704,316,704,51,345,90,859,369,399,739,477,887,881,728,430,548,125,224,766,931,604,367,448,230,646,980,668,939,83,574,619,652,920,742,29,981,282,915,493,82,368,974,545,769,547,600,814,455,552,848,367,772,90,754,825,196,812,700,964,683,326,202,234,75,771,831,297,328,466,266,347,900,444,88,319,810,618,946,51,469,467,727,370,108,55,511,556,584,542,482,568,139,371,729,29,150,525,285,693,892,208,437,450,444,647,5,988,958,244,864,102,302,190,671,331,569,457,609,669,728,859,548,818,535,134,654,645,288,439,526,792,290,674,259,167,432,616,956,580,143,580,595,357,600,256,708,885,914,430,551,634,214,726,34,118,549,977,363,663,549,71,424,218,439,422,466,784,417,454,273,321,864,781,596,340,733,818,181,137,302,744,702,316,517,332,957,943,732,388,398,310,728,741,660,397,483,441,749,293,141,689,116,655,986,454,305,42,995,638,576,515,389,46,136,773,307,232,884,834,28,457,349,356,809,475,932,800,465,886,658,919,309,677,288,684,979,52,477,410,693,878,563,998,768,560,206,627,386,811,395,486,624,217,303,747,838,65,681,44,955,949,780,68,36,865,257,866,32,12,866,220,39,314,479,621,203,754,589,880,360,156,736,724,888,670,709,297,149,21,220,138,431,11,911,623,662,233,562,955,466,372,817,9,751,432,263,784,736,534,215,539,491,206,497,834,476,760,497,878,67,47,125,127,748,800,476,65,547,388,663,184,275,283,12,651,326,129,235,292,879,286,682,309,208,730,304,706,100,123,671,188,698,468,956,837,537,927,507,12,602,374,636,619,839,663,766,565,370,516,591,179,908,762,660,16,270,379,724,610,381,699,592,681,37,655,84,387,745,177,125,41,163,296,456,557,447,144,40,635,877,9,384,584,768,355,933,88,558,975,459,105,77,766,940,408,215,930,239,670,679,144,359,851,727,113,763,467,705,53,817,475,35,580,546,691,128,887,965,9,476,403,162,303,831,934,690,92,765,393,670,143,943,477,427,868,337,406,557,453,407,361,513,737,737,76,792,23,245,786,759,818,967,298,838,410,364,480,825,220,721,702,363,942,687,100,206,311,357,679,130,310,32,356,862,595,643,326,465,299,941,920,621,731,3,409,841,990,845,402,575,438,352,271,88,928,709,610,169,82,809,463,669,74,413,747,835,523,168,462,928,547,812,865,930,176,77,494,798,564,394,461,357,306,418,716,215,375,263,472,513,357,605,453,151,707,479,432,760,986,44,925,113,28,456,486,38,226,875,959,729,968,274,293,933,646,582,463,393,3,235,263,919,276,822,647,980,729,142,302,123,896,604,355,853,706,826,221,453,764,257,595,371,866,889,799,845,198,629,169,553,240,971,297,254,400,669,762,247,67,640,272,2,427,956,522,31,134,195,98,234,549,575,541,556,598,738,451,212,57,58,334,73,426,743,914,606,663,993,140,213,483,849,448,751,996,909,46,365,874,90,942,394,900,43,993,456,26,854,326,205,879,161,8,369,729,796,416,116,30,203,969,179,621,763,272,151,958,455,136,224,177,238,841,593,775,726,222,942,616,642,273,597,779,852,786,780,63,544,876,579,610,738,347,93,542,686,861,556,791,764,821,665,473,315,137,837,95,564,89,33,595,986,634,239,453,469,181,260,700,720,511,960,539,265,906,915,505,195,966,909,570,657,677,608,262,506,557,890,703,710,966,631,706,325,297,684,512,966,177,202,370,744,352,913,401,274,716,859,234,14", + "739,320,949,307,253,64,996,160,119,558,619,479,484,321,880,334,427,267,269,234,111,515,177,93,29,450,652,240,740,526,125,797,70,220,461,643,842,965,902,560,683,523,989,262,111,783,384,431,760,477,756,864,996,381,941,760,608,565,556,148,226,25,139,620,798,551,349,426,461,357,767,179,862,572,2,274,325,574,654,753,174,504,805,57,889,194,665,867,218,684,479,979,112,198,147,372,390,507,170,714,972,414,852,931,658,257,515,524,881,102,346,662,377,943,63,202,802,770,820,240,480,876,942,854,68,289,946,549,892,881,419,896,770,965,713,761,765,989,36,649,547,623,162,359,294,903,680,452,768,56,987,301,365,810,697,91,207,224,45,14,64,670,700,675,237,395,849,559,317,158,849,596,187,114,518,630,364,0,303,988,558,36,348,464,798,298,772,692,284,625,615,545,523,889,279,255,61,805,213,250,364,123,756,719,884,476,820,225,192,944,229,126,46,210,895,124,781,163,868,967,161,28,639,371,53,551,187,658,666,953,167,53,984,724,22,856,916,573,997,187,373,525,984,745,680,509,165,408,362,542,643,433,292,612,452,292,665,491,762,919,265,777,250,690,740,855,399,349,593,170,380,142,861,836,676,492,40,42,167,338,176,427,298,627,598,805,635,699,109,153,260,209,53,586,400,917,23,280,130,841,3,332,768,232,290,688,679,388,573,382,465,118,445,786,108,210,297,303,227,55,833,275,452,104,400,824,372,934,482,367,82,41,29,587,617,748,661,719,130,220,946,237,174,120,485,837,541,510,994,407,863,16,567,582,92,728,905,626,813,138,680,930,5,279,565,968,99,162,152,204,210,840,852,342,780,283,39,866,125,641,306,583,674,584,602,715,260,540,576,131,436,515,211,44,539,410,750,883,911,753,92,244,9,263,860,670,701,133,953,565,228,810,805,636,540,488,590,589,475,963,915,430,845,574,325,554,8,782,5,84,760,746,510,675,555,286,730,428,361,581,453,971,917,545,901,930,103,239,995,955,66,327,165,241,730,609,834,753,91,772,85,479,883,910,84,801,827,12,714,832,855,42,379,663,44,580,603,911,454,340,995,996,812,749,684,882,130,131,536,515,862,495,294,684,914,524,942,34,543,68,667,421,815,625,696,62,232,156,177,126,178,716,10,474,664,889,595,432,408,511,256,446,469,573,157,574,235,528,201,608,766,911,948,203,210,593,156,507,433,406,150,737,593,372,894,689,735,459,621,315,243,313,903,913,874,980,961,575,826,308,600,467,380,242,704,42,665,264,301,989,532,678,339,158,719,30,357,575,496,406,839,808,274,560,639,87,393,762,657,638,464,599,890,102,598,154,947,132,246,678,309,357,74,72,555,559,25,569,521,557,259,551,76,176,281,142,195,828,208,401,240,716,5,300,739,754,233,202,307,471,550,93,764,914,381,989,413,624,987,437,96,611,371,601,479,70,884,129,427,402,605,61,656,750,98,35,442,550,325,341,445,408,32,944,798,170,780,707,245,234,721,629,822,347,282,853,625,543,672,125,213,587,928,223,105,452,412,937,90,54,49,411,835,247,365,823,842,394,313,985,386,824,278,331,806,774,659,730,176,421,956,857,460,410,646,324,857,650,931,881,699,517,255,323,849,758,948,345,839,172,766,430,64,992,234,239,173,584,958,577,229,797,175,800,38,94,832,970,224,47,179,722,384,227,355,627,544,105,977,98,789,663,602,612,580,374,696,962,288,879,580,725,816,801,979,320,671,905,851,307,425,966,853,532,516,679,107,277,637,776,722,325,485,592,87,458,69,174,661,651,380,302,8,441,428,305,774,650,410,370,794,500,369,841,632,50,357,82,420,40,268,936,512,2,598,364,890,79,355,15,117,297,837,684,868,88,50,491,357,472,208,104,445,400,169,948,230,312,315,205,509,749,230,686,426,103,28,60,612,147,42,405,206,831,554,84,406,511,307,512,396,495,924,145,384,155,767,26,180,921,413,327,907,650,785,890,268,72,275,877,754,445,76,420,11,474,911,296,357,893,927,760,846,298,973,828,481,595,114,721,59,477,659,92,485,101,475,425,13,589,91,974,130,308,436,906,427,392,376,509,691,986,792,328,636,135,102,141,489,164,959,813,575,317,720,49,827,275,892,32,161,774,631,737,427,607,119,210,837,196,661,645,806,367,882,144,127,8,401,341,422,398,671,765,682,854,315,401,82,781,413,166,408,269,205,165,266,883,234,742,525,89,386,313,918,211,651,179,553,351", + "354,949,7,10,495,237,572,320,143,811,149,868,126,737,88,404,63,449,390,473,13,932,771,823,316,758,173,570,721,254,76,323,857,503,339,400,303,498,26,899,342,495,904,138,255,740,917,407,742,72,521,227,166,923,39,658,362,201,424,382,268,583,538,809,373,109,22,727,346,786,38,13,55,325,751,238,101,89,710,30,962,491,568,468,210,254,708,129,520,795,58,432,48,764,3,829,337,399,723,302,844,329,70,551,804,94,503,257,200,396,517,952,231,711,720,853,756,757,534,112,636,11,233,834,455,670,186,821,862,227,65,395,487,900,555,877,457,394,957,623,771,683,264,613,533,706,931,327,937,512,978,101,902,759,49,306,769,437,340,777,128,290,769,357,721,365,756,529,834,501,521,499,756,287,99,883,178,303,0,912,598,682,64,985,494,741,660,691,380,67,613,191,415,173,68,138,744,329,649,482,596,249,296,226,667,780,713,140,22,683,280,140,723,331,799,702,180,751,672,720,448,93,15,711,456,453,20,253,361,442,470,110,464,571,159,255,497,477,133,59,169,212,935,628,521,710,308,576,903,106,282,484,494,772,204,567,876,132,540,740,106,912,645,42,714,193,671,765,34,467,329,56,577,646,836,541,58,688,99,268,989,93,75,85,597,738,89,450,670,520,893,756,131,104,364,290,44,666,708,200,457,214,263,771,750,197,115,272,280,818,504,522,113,359,26,229,845,389,450,529,830,770,425,251,726,498,187,876,745,857,837,370,362,753,654,232,688,206,849,757,784,864,326,886,431,938,898,943,386,156,595,109,46,396,750,388,446,57,266,2,913,56,886,44,807,750,709,259,902,714,589,578,414,55,131,701,209,570,976,808,237,897,603,392,115,73,824,967,922,852,407,111,35,229,258,876,349,534,802,74,685,500,147,45,837,659,882,814,462,34,695,87,597,440,609,315,452,732,310,374,815,945,788,999,242,317,886,107,510,729,992,180,458,645,876,131,430,903,205,817,863,113,925,697,922,963,757,320,138,741,54,875,78,456,677,740,149,129,48,707,60,451,9,542,287,602,127,52,965,663,298,521,742,378,412,549,836,700,570,980,162,170,190,907,60,481,649,514,234,971,232,292,302,301,260,425,482,754,817,629,944,100,340,225,100,811,633,125,4,952,746,643,75,800,378,802,715,537,445,31,350,792,377,110,891,368,278,197,369,345,963,258,380,925,381,45,192,660,742,367,488,222,240,388,438,978,877,352,134,267,116,164,938,755,128,401,562,678,229,360,648,668,351,752,102,765,165,246,118,488,417,754,52,736,312,735,802,723,854,84,5,112,650,905,674,577,75,146,416,960,76,642,262,571,901,44,964,361,410,339,943,365,938,500,194,484,65,142,161,268,26,397,750,786,233,888,570,210,439,435,224,574,880,623,970,75,805,205,395,735,999,207,515,314,240,136,429,385,341,80,761,667,530,836,764,820,381,155,282,118,714,733,282,937,460,670,838,630,296,645,826,90,410,681,366,261,418,753,667,928,759,833,724,378,715,874,612,963,40,577,690,417,732,749,307,708,523,108,560,478,513,800,40,91,206,773,718,120,301,753,262,463,460,989,302,540,920,34,593,60,960,55,124,231,87,546,33,931,894,499,585,905,509,782,645,651,390,341,405,228,748,91,880,613,471,374,845,409,194,514,575,77,354,264,698,319,94,520,69,633,898,451,43,901,379,733,812,325,982,299,692,220,395,495,866,423,157,403,535,732,642,647,739,295,902,957,746,790,7,94,53,181,503,614,280,661,446,177,276,319,817,906,822,841,201,786,675,496,242,643,908,537,973,598,470,364,830,309,17,398,523,601,495,395,284,426,861,881,299,903,320,555,155,551,126,16,539,118,666,228,699,920,360,208,477,529,652,50,943,570,55,737,958,907,381,411,410,838,484,157,140,471,276,333,438,707,217,396,227,845,832,626,949,925,41,744,439,83,422,234,763,338,394,534,306,334,71,491,597,752,906,932,455,639,34,354,325,632,596,557,457,201,58,445,739,937,433,957,55,131,334,67,922,702,409,29,611,714,984,929,669,427,60,504,33,16,812,260,6,25,997,451,819,73,182,974,51,451,319,959,768,25,770,67,986,405,747,71,914,485,39,982,273,643,46,302,519,317,692,346,111,376,293,413,852,21,375,552,78,143,529,213,92,65,762,974,192,307,765,959,472,684,383,437,363,316,423,573,704,284,86,903,695,217,380,65,443,133,333,87,235,775,710,120,882,332,15,792,108,778", + "781,838,624,286,230,962,242,323,613,755,349,250,75,389,572,32,355,284,14,509,262,947,849,385,395,133,597,381,465,418,297,524,294,944,554,967,353,993,987,512,779,36,902,243,8,139,802,672,832,985,339,716,423,707,985,103,182,144,880,192,525,574,694,530,9,906,348,147,664,318,133,371,677,490,28,50,89,992,877,938,871,180,698,740,56,494,316,117,857,812,248,906,696,574,394,872,196,279,867,690,721,18,416,667,839,72,174,677,56,728,334,979,24,872,597,20,218,838,359,976,243,218,522,288,513,590,616,916,757,739,210,844,105,910,521,610,359,683,973,710,499,628,390,338,117,14,409,602,271,407,305,866,42,253,163,686,157,338,58,431,160,743,644,661,11,984,294,524,745,181,462,172,453,422,450,31,759,988,912,0,106,562,127,217,657,146,14,522,270,969,432,851,424,743,145,844,944,421,79,399,506,216,259,799,739,540,260,630,585,563,679,614,757,545,128,285,301,43,414,501,767,353,883,698,652,653,511,150,137,527,288,479,367,810,116,678,634,673,48,84,651,236,516,722,771,824,745,998,45,82,681,787,876,949,311,719,451,902,22,586,744,58,37,954,604,645,32,919,96,367,152,116,228,624,221,369,504,166,615,737,473,857,816,345,370,761,543,916,64,392,225,553,631,773,998,298,722,523,267,32,957,499,961,20,239,39,942,925,14,481,129,914,139,262,260,920,433,376,456,622,79,465,15,55,543,214,647,408,128,692,746,234,475,347,409,727,65,455,765,713,863,100,580,897,855,925,971,866,322,316,372,586,761,908,127,262,603,19,310,139,599,148,681,338,967,612,594,92,728,826,919,822,376,396,613,617,74,805,338,245,344,621,742,725,51,627,583,416,97,575,810,299,135,667,507,807,274,409,897,295,796,836,1000,85,155,144,339,833,147,189,43,666,425,88,600,294,71,63,44,720,632,325,192,390,33,428,19,880,512,217,143,785,305,766,125,332,200,844,839,470,31,441,68,805,301,379,954,468,704,128,759,399,174,393,337,203,114,641,290,783,902,703,192,192,523,210,24,86,688,808,601,851,133,615,974,237,278,732,160,687,104,938,38,757,803,377,139,338,229,160,980,184,41,414,264,673,866,838,127,802,614,994,432,800,466,783,220,549,933,25,29,204,462,384,396,460,338,751,289,406,297,53,281,185,544,715,122,392,42,533,366,962,230,484,943,148,598,342,212,449,469,374,618,554,561,907,530,24,80,273,200,382,585,251,754,150,616,136,685,287,282,873,593,816,353,380,226,186,525,495,279,984,176,474,492,970,334,412,237,834,324,609,158,195,328,621,398,548,246,779,320,649,185,517,54,640,799,372,119,798,457,867,672,380,757,941,373,311,188,485,232,150,667,886,358,688,880,257,155,613,432,200,703,904,335,577,446,727,826,469,587,701,416,88,427,902,760,908,821,291,868,187,206,591,870,188,519,583,899,650,388,536,527,836,878,287,945,175,628,649,215,620,539,122,844,885,292,685,463,531,906,685,595,796,183,786,145,190,836,244,594,758,625,714,352,565,648,497,150,453,55,669,391,793,105,165,809,371,10,929,195,913,586,613,512,248,554,789,152,878,933,2,585,766,200,358,715,77,925,756,3,20,12,373,286,308,272,688,390,635,484,15,590,183,678,447,459,217,945,309,29,361,426,78,401,210,932,455,886,682,681,71,703,182,82,381,958,329,11,886,764,297,393,611,525,324,207,840,944,666,910,240,165,509,488,807,734,582,700,981,673,783,174,530,894,9,465,521,296,892,352,532,728,770,816,65,786,659,612,526,278,707,582,817,836,815,407,423,477,74,262,790,860,302,805,522,937,725,951,72,274,317,293,314,456,863,435,998,294,418,781,28,856,196,658,444,220,681,542,464,459,854,863,372,827,782,491,161,582,420,342,293,460,306,209,39,611,90,876,715,553,634,871,859,810,451,658,572,856,181,717,861,828,213,834,636,322,87,811,533,116,752,851,307,353,654,686,119,741,631,177,182,547,316,423,954,932,721,26,100,173,306,571,452,981,996,123,382,422,651,518,813,966,688,299,360,43,552,912,475,499,786,739,208,453,383,259,730,445,699,129,143,812,784,59,829,914,902,740,773,161,79,574,775,3,452,648,852,11,413,190,341,84,104,859,42,146,698,637,927,355,229,721,307,479,473,936,226,334,35,509,603,651,126,651,952,146,527,326,692,668,248,184,561,759,314,678,322,15,558,882,104,594,764,695,786,106,437,110,821", + "348,138,684,188,683,445,143,721,371,44,797,430,351,657,621,807,4,739,386,500,131,918,512,789,869,998,564,892,292,458,277,261,457,673,759,963,94,232,938,614,77,515,532,536,587,210,35,150,63,107,160,241,337,62,247,810,763,570,303,489,553,92,598,92,777,119,725,411,734,222,247,195,445,865,237,243,954,311,190,179,920,389,849,433,275,753,259,46,173,328,592,273,8,525,669,638,195,468,393,133,31,69,308,280,625,439,260,404,44,203,103,283,811,23,799,955,291,776,272,466,925,770,425,732,461,171,651,309,817,163,704,955,485,777,314,358,181,743,629,328,157,936,518,448,450,994,881,228,421,853,366,110,957,145,257,486,751,869,394,376,295,524,517,971,563,64,801,205,465,734,606,956,31,638,661,969,124,558,598,106,0,5,861,288,818,753,486,750,353,196,39,471,428,85,877,502,609,986,413,746,32,18,925,483,750,382,760,305,764,578,593,852,54,934,642,715,287,958,684,165,161,601,222,607,823,132,484,656,378,31,848,43,42,300,466,259,953,595,775,337,169,355,651,826,77,430,663,293,392,952,525,450,560,595,664,872,495,833,667,130,111,936,869,403,402,771,431,7,481,76,894,691,712,226,533,58,793,447,193,227,229,514,879,659,357,770,45,100,500,311,745,804,507,793,721,162,779,663,186,162,981,642,289,445,227,617,634,106,409,651,150,87,193,961,138,352,227,542,958,855,382,606,29,502,709,619,530,66,350,172,965,580,187,708,459,745,680,74,482,770,442,590,992,873,767,950,116,140,562,773,750,700,746,746,280,300,986,707,732,115,392,408,276,535,292,218,388,331,273,923,570,69,299,122,511,583,491,919,46,47,814,66,94,357,319,261,140,498,3,655,44,829,461,208,426,380,749,270,220,386,687,88,34,762,170,389,481,394,234,633,275,8,793,519,85,502,810,549,20,448,47,300,945,652,34,790,211,610,763,437,572,779,268,608,422,594,56,66,940,951,955,377,873,443,762,824,768,429,62,621,308,411,414,380,307,144,611,681,638,904,725,516,503,590,354,94,140,434,790,528,917,212,304,12,319,328,557,28,377,622,620,648,605,106,146,1000,842,555,52,955,937,244,405,19,398,253,341,344,156,613,461,486,333,80,982,262,464,458,671,707,412,779,67,81,361,481,286,650,691,145,455,394,40,183,544,898,377,452,706,756,385,152,997,879,719,109,261,794,788,378,909,952,700,90,889,943,617,145,773,370,714,3,628,552,272,266,433,877,168,475,248,379,590,967,647,206,932,238,289,435,754,964,634,15,486,786,752,36,733,191,226,722,922,540,350,591,384,375,13,911,850,340,184,80,745,518,889,280,462,773,179,755,997,187,962,725,488,463,990,14,631,623,366,211,936,717,839,983,432,680,758,886,385,517,371,401,853,152,292,227,683,184,144,704,532,215,177,420,673,819,858,938,607,410,359,245,43,801,911,646,822,179,699,805,409,54,301,959,188,657,655,114,959,845,873,125,371,68,723,516,23,405,438,762,132,818,57,397,488,135,112,729,596,303,836,741,562,220,929,823,740,296,933,50,517,195,963,15,109,62,944,110,889,786,428,753,94,258,417,92,529,89,541,48,160,997,410,400,455,764,198,726,406,776,157,95,842,9,894,563,675,779,100,633,379,262,18,706,138,668,2,80,308,841,964,420,11,4,479,967,534,571,198,864,169,575,142,645,744,597,936,15,555,604,578,928,295,396,368,332,195,746,908,294,538,613,350,976,863,553,679,109,869,308,196,862,345,137,646,352,843,76,331,848,503,384,614,162,31,305,574,779,695,672,845,136,232,477,761,977,998,323,444,899,657,224,928,780,833,172,391,677,454,213,409,52,376,936,175,563,565,40,787,339,821,851,829,482,191,553,210,19,3,524,728,84,271,474,98,565,161,302,256,986,996,398,765,864,957,360,633,460,918,765,556,665,263,742,403,96,732,77,694,770,186,789,252,419,582,422,783,154,283,564,503,930,482,594,101,785,5,17,854,353,479,391,32,181,681,125,975,823,828,49,337,195,76,991,640,458,468,283,882,978,788,689,48,24,458,928,718,971,373,532,608,384,88,181,803,828,776,447,152,229,142,181,875,366,144,627,518,84,191,353,426,312,570,917,988,629,502,325,616,924,841,571,297,297,643,43,763,342,982,763,504,776,316,997,349,604,532,633,271,900,777,397,894,938,509,767,872,226,798,477,519,694,52,973,433,62,157,681,542,306,150,401,81,348,963,564", + "264,537,720,982,634,63,962,619,209,622,664,681,749,292,310,695,959,370,356,98,952,333,961,82,855,168,569,397,738,601,112,853,427,521,15,289,104,544,346,280,797,480,790,853,945,637,346,882,553,594,248,107,865,263,402,317,231,386,925,690,79,284,816,899,505,971,181,881,849,89,424,351,269,211,535,292,729,25,206,198,924,812,983,668,677,902,215,60,744,943,267,525,199,785,788,387,80,787,854,453,581,215,79,508,98,376,690,969,335,532,433,223,175,222,966,750,188,417,579,404,821,410,327,770,431,301,605,857,629,849,677,154,414,879,580,2,210,672,867,331,985,373,134,841,885,170,424,927,88,999,629,18,987,88,584,501,641,778,453,661,658,607,31,157,543,530,691,598,29,532,892,394,960,408,446,86,142,36,682,562,5,0,538,268,402,686,635,959,180,317,426,496,519,111,239,939,455,273,396,95,178,835,436,228,788,549,655,404,116,486,953,306,301,286,948,954,486,678,584,602,446,338,379,560,402,301,224,831,196,57,686,511,436,511,523,22,268,115,243,928,610,440,488,999,192,639,600,836,283,291,10,913,161,232,864,155,284,680,810,873,676,949,578,129,628,131,726,950,309,693,992,646,936,346,41,617,808,26,559,750,205,292,15,459,938,89,133,965,946,395,726,503,789,628,829,316,661,334,201,507,533,344,690,405,943,846,18,779,105,307,298,408,710,790,247,93,261,392,984,533,171,259,583,781,236,338,327,806,903,169,376,514,690,193,589,784,345,57,522,265,888,763,828,686,209,135,428,922,481,957,939,913,711,3,842,965,975,357,769,597,388,294,492,944,834,465,658,861,928,698,175,145,94,538,433,277,850,246,271,35,26,838,442,272,884,322,404,894,845,267,592,471,795,438,60,248,326,263,769,658,241,872,808,219,339,985,240,335,812,552,383,501,182,460,321,680,725,693,850,438,458,768,732,608,626,693,930,510,22,858,444,979,567,786,125,898,506,258,688,149,412,336,631,746,906,855,228,987,312,515,562,369,623,859,172,351,747,379,263,152,594,643,116,816,840,806,320,328,254,497,600,501,379,589,774,343,319,733,595,125,120,483,980,797,997,713,125,744,574,255,766,598,226,926,244,705,704,790,406,905,761,380,340,850,654,880,309,972,965,166,748,883,347,616,547,60,980,760,304,748,364,541,581,445,339,475,756,32,140,989,733,185,352,600,10,574,565,858,225,40,542,448,114,565,846,997,329,76,555,418,561,916,754,139,577,823,55,261,518,176,698,67,596,583,623,356,232,816,539,926,922,449,999,59,814,356,316,792,397,830,717,969,482,48,906,284,289,169,261,776,878,223,354,893,719,90,401,350,13,32,700,521,421,161,817,869,496,101,649,395,71,723,874,29,573,995,304,704,201,475,745,678,688,138,771,37,440,341,522,438,152,682,903,707,266,907,924,866,94,352,464,643,773,65,43,608,189,487,632,24,530,888,142,220,579,38,128,839,405,256,810,729,211,332,246,952,969,318,762,647,923,34,11,55,4,978,638,317,224,555,443,933,56,757,825,735,192,872,404,199,405,429,689,510,694,83,85,21,676,498,1,17,987,354,474,503,588,298,648,747,546,553,593,571,531,949,788,303,322,361,658,186,647,597,430,750,163,212,453,249,593,35,555,569,588,609,891,530,481,819,460,564,883,806,792,561,554,54,786,779,246,594,493,628,306,287,281,497,696,845,442,164,90,206,879,733,377,670,688,429,282,499,485,279,42,498,184,112,563,977,201,905,597,306,594,62,738,919,192,265,358,430,835,620,845,21,671,945,357,850,349,812,412,306,494,789,977,291,710,947,310,381,74,202,944,300,259,885,617,149,69,277,874,762,160,265,576,24,590,233,318,574,551,866,658,206,378,685,515,432,907,740,870,87,16,148,820,958,12,818,912,991,5,482,357,408,555,908,590,424,129,392,587,822,575,116,366,133,605,221,770,78,292,879,96,821,558,893,854,804,285,41,540,450,226,38,591,386,945,808,946,959,132,767,57,310,489,774,855,88,673,477,455,231,854,713,353,510,991,469,313,161,990,425,97,612,743,159,52,685,839,288,501,564,785,381,475,199,452,437,173,382,53,279,961,373,873,35,389,482,720,549,105,13,690,830,352,801,307,195,611,395,969,891,191,966,497,236,131,605,964,837,430,401,607,985,641,921,913,788,258,828,615,113,364,501,966,302,415,548,601,883,61,924,646,982,918,87,142,258,520,547,865,317,87,157,365,816,129,492", + "790,868,651,970,851,561,133,998,57,15,629,359,262,152,501,306,680,539,822,256,753,279,512,631,391,881,493,127,621,31,630,233,921,927,972,201,138,915,4,499,641,256,490,73,438,573,274,260,889,931,53,384,421,603,735,494,768,319,880,979,92,724,877,632,355,551,447,9,567,606,574,538,352,43,216,579,905,43,648,93,287,751,632,537,997,734,426,326,99,911,239,197,442,648,491,978,408,24,214,786,471,876,750,696,62,506,410,427,491,242,695,473,837,774,938,2,686,138,849,89,452,850,491,810,741,885,524,341,932,609,102,42,103,277,812,569,331,503,407,450,167,997,218,518,455,385,797,942,878,745,305,988,153,244,100,326,243,726,654,671,75,682,358,642,668,538,618,208,91,787,259,154,430,943,272,135,113,348,64,127,861,538,0,558,215,949,756,139,242,491,941,745,315,424,370,260,34,466,693,562,920,490,707,239,94,565,245,730,369,414,810,334,418,189,194,199,709,818,299,731,701,799,806,741,3,224,629,65,220,203,756,260,688,461,508,319,641,88,819,922,98,52,763,108,883,819,906,626,803,263,13,795,596,438,491,432,377,121,131,516,328,324,294,753,679,490,366,874,742,977,185,51,212,739,36,660,718,387,459,845,780,306,555,278,585,452,129,442,935,157,329,783,499,249,600,514,322,62,214,462,712,719,464,376,758,825,46,783,675,334,494,983,409,498,983,507,824,326,170,235,194,576,742,983,197,177,645,776,625,704,107,374,170,341,575,887,384,248,181,601,808,109,790,671,791,404,178,750,409,517,429,158,444,129,194,308,579,49,704,274,712,209,251,93,518,57,597,847,820,580,290,473,712,78,119,595,13,139,920,770,894,158,671,143,601,668,199,619,295,533,757,218,585,328,969,772,469,871,384,341,32,620,903,793,975,696,568,658,75,634,263,854,493,956,348,566,835,529,977,366,13,972,504,842,379,634,475,29,657,760,480,316,508,409,897,36,378,934,216,90,648,194,899,787,852,170,479,554,546,689,495,765,31,963,702,745,689,37,674,580,532,170,43,62,573,659,916,36,121,53,619,154,692,564,151,932,962,226,904,79,312,678,659,286,47,511,256,467,898,141,347,30,611,386,527,988,575,875,602,937,644,649,298,529,888,329,512,861,629,370,181,774,244,514,886,605,828,694,139,414,327,770,120,282,80,408,219,706,819,180,849,252,131,319,528,158,64,288,217,168,552,474,190,646,270,990,883,754,131,246,458,368,772,190,906,504,209,525,478,863,451,691,679,595,929,173,840,984,900,496,994,536,647,952,971,410,25,812,874,471,599,559,344,741,640,88,845,45,266,528,721,791,417,451,623,560,330,958,716,28,565,363,712,95,647,199,866,908,318,345,227,774,949,781,366,70,908,561,741,995,834,360,911,242,843,540,127,333,819,611,15,328,616,756,498,551,227,448,123,677,672,881,160,220,916,462,204,395,470,189,775,298,179,957,834,49,993,74,68,327,429,82,200,937,479,344,270,69,421,361,111,339,5,428,404,910,36,806,321,827,362,424,341,853,209,200,205,132,431,828,573,860,256,738,917,970,986,586,304,983,608,57,388,32,38,130,758,475,587,74,258,870,2,719,306,463,41,904,746,801,299,375,62,897,935,889,668,415,528,609,302,321,846,677,805,203,799,99,378,479,597,723,519,265,360,474,293,875,694,893,291,577,154,520,990,744,495,699,319,509,31,849,933,767,417,908,668,401,440,552,615,123,940,658,742,635,817,97,405,424,667,829,861,423,312,852,903,902,258,835,6,329,25,769,938,998,133,168,41,238,347,438,834,940,953,549,633,715,880,214,306,820,304,633,311,698,16,989,259,393,913,547,453,129,438,876,503,263,664,76,783,447,589,340,198,392,328,150,139,957,365,251,341,619,804,941,263,298,224,332,282,567,205,109,532,8,20,837,106,733,731,456,852,961,302,780,858,242,15,119,727,666,375,690,380,791,304,376,675,217,835,188,370,889,683,749,625,271,141,971,297,998,781,246,336,884,139,828,851,22,140,852,402,119,776,982,314,864,841,231,863,201,951,26,448,980,312,483,951,823,280,348,29,499,953,928,757,719,630,300,794,238,977,410,477,715,246,237,294,502,619,982,541,352,944,127,339,576,980,569,481,951,936,880,809,671,855,788,638,307,795,764,556,163,423,329,828,647,864,849,38,5,384,446,204,752,571,521,682,748,653,874,695,561,2,95,612,275,669,189,741,65,301,310,618,81,559,561,796,48", + "110,329,556,237,906,882,390,763,89,820,295,356,897,794,485,393,858,909,356,952,416,153,499,112,87,753,735,687,329,30,676,312,629,883,424,245,267,394,855,888,377,490,441,139,397,876,146,972,431,776,564,700,229,346,473,859,465,237,353,340,153,62,166,955,907,615,115,551,117,327,848,380,529,503,466,901,724,424,798,873,268,557,539,871,620,945,890,585,23,114,469,933,159,688,345,837,640,639,457,485,42,64,280,324,216,370,462,451,488,225,20,992,611,966,465,969,71,482,315,20,663,386,916,400,761,50,796,305,248,825,655,432,583,924,375,171,412,105,696,158,397,298,552,710,695,135,629,746,260,246,615,780,835,960,28,737,264,440,825,42,300,903,480,47,942,355,48,347,346,186,528,879,395,716,803,935,577,464,985,217,288,268,558,0,562,271,962,559,52,410,774,598,786,929,25,953,543,779,920,983,91,859,615,317,308,839,491,758,67,527,464,700,994,865,935,448,875,625,777,88,369,559,213,771,229,947,837,303,229,161,440,665,755,114,433,752,146,395,902,468,969,967,166,428,747,303,223,648,155,681,150,598,252,541,395,758,394,770,659,561,617,958,127,228,96,732,881,48,63,975,862,938,643,379,24,617,814,285,657,909,757,566,77,528,888,849,126,225,522,101,732,946,514,126,653,921,388,704,820,887,366,567,226,690,81,270,894,732,130,589,482,931,431,661,930,692,205,520,367,397,35,984,972,99,589,706,65,894,7,53,455,171,819,488,478,875,825,648,65,664,526,943,118,666,133,255,495,175,611,430,279,333,318,286,410,138,912,773,744,434,555,862,579,112,163,438,426,13,778,598,727,459,263,687,345,152,592,550,666,551,996,694,802,551,616,477,305,537,681,790,354,793,718,58,457,312,192,919,890,327,840,770,842,826,959,282,44,963,931,845,192,792,479,891,286,32,506,486,565,832,32,161,590,388,854,67,220,535,254,721,968,514,961,893,886,598,4,795,34,665,243,866,457,517,70,630,651,281,868,237,628,46,209,324,976,400,213,833,496,942,80,340,26,550,566,834,782,502,99,629,75,402,69,156,837,575,600,648,778,349,430,981,80,129,176,490,337,870,556,956,725,675,307,549,334,877,470,307,740,281,252,494,175,31,434,507,191,139,633,56,367,257,398,940,35,169,953,399,305,937,919,132,379,890,720,310,711,465,932,34,407,992,576,13,689,18,596,784,89,214,704,377,553,53,159,573,945,123,159,10,929,190,300,554,984,893,30,803,279,908,604,391,691,577,594,438,849,121,375,539,315,395,848,979,715,490,96,828,876,80,475,102,432,900,224,719,309,538,52,11,304,459,279,62,101,323,740,470,369,951,585,61,852,707,355,601,752,249,418,26,467,855,725,872,342,716,785,997,897,508,471,359,736,660,923,354,355,779,275,332,144,390,430,285,798,720,609,646,456,597,366,939,944,58,387,870,124,50,367,495,296,262,495,738,262,621,109,697,563,48,12,319,110,147,389,281,392,988,386,490,219,237,6,70,80,951,181,390,999,401,522,842,261,957,488,802,721,827,106,289,160,192,710,388,465,744,918,908,31,167,393,775,531,820,428,238,477,819,999,147,967,171,898,566,537,259,981,610,837,351,434,6,436,914,729,518,983,505,581,844,191,397,168,20,345,813,567,416,260,287,235,634,882,977,392,268,416,87,445,271,221,655,321,156,814,177,356,762,114,443,417,63,73,14,183,397,958,776,236,175,361,920,972,378,193,259,242,125,982,900,952,798,155,9,269,539,677,609,456,586,715,396,581,70,799,931,164,317,406,8,879,681,682,157,32,784,220,974,758,60,390,553,286,341,361,121,727,920,460,662,266,756,769,326,961,678,584,477,44,623,814,725,587,976,198,935,393,6,553,454,33,941,751,385,202,95,954,49,752,106,550,390,835,387,923,677,224,524,826,899,39,430,397,486,814,139,887,736,145,966,746,581,661,107,267,536,443,127,958,245,856,689,778,549,616,45,13,248,658,760,386,625,98,551,71,78,327,46,193,402,493,981,662,579,556,935,149,158,86,896,313,572,263,13,446,869,654,98,119,874,54,965,366,979,334,494,887,932,33,686,310,291,378,426,144,281,233,692,473,966,44,878,765,254,344,487,990,560,28,386,514,566,91,613,299,940,790,761,382,524,891,615,832,825,485,923,398,989,429,880,460,696,843,664,749,303,980,466,26,836,131,783,901,49,182,676,444,431,864,715,599,188,517,445,580,181,667,885,201,344", + "369,759,534,614,983,980,664,152,326,55,188,818,271,800,382,134,500,249,314,626,386,918,803,82,92,17,47,584,389,194,411,896,460,108,693,748,313,226,911,820,304,731,876,711,840,580,663,854,831,219,413,748,167,559,505,828,654,197,166,702,310,836,953,22,641,943,579,109,71,208,156,110,786,170,820,264,335,808,680,516,836,711,888,123,403,16,466,627,415,303,390,675,809,453,360,414,7,998,716,727,103,284,293,775,899,277,181,765,40,695,985,84,299,498,981,132,504,341,467,316,618,502,238,110,283,794,285,937,62,343,909,318,511,29,901,23,510,304,554,288,72,217,248,318,637,330,172,922,218,634,791,136,218,928,700,896,63,615,718,54,918,696,272,474,938,762,993,178,233,528,798,320,450,720,836,702,614,798,494,657,818,402,215,562,0,535,598,471,828,895,121,62,944,171,388,87,996,263,755,459,175,987,144,911,536,876,58,208,549,372,840,188,912,729,160,986,904,70,632,345,393,549,911,224,7,830,704,437,609,489,221,120,24,355,92,482,177,82,544,7,396,692,732,686,96,963,85,104,228,720,55,519,34,891,887,213,822,804,494,137,786,768,292,639,27,42,261,295,772,195,183,991,951,486,792,392,957,397,253,448,239,859,915,176,5,177,766,404,551,337,455,86,201,986,948,631,63,934,631,940,408,467,986,565,726,622,633,737,107,91,783,236,166,632,28,899,965,710,198,638,67,144,686,58,631,584,821,805,147,114,400,471,338,430,536,122,868,491,332,298,234,231,193,769,514,462,352,28,550,675,216,776,763,795,982,762,637,677,890,29,380,813,820,470,89,988,296,61,719,750,288,920,426,53,270,213,604,335,978,760,918,187,523,19,269,817,556,716,640,834,952,931,498,200,258,146,674,49,839,181,130,894,944,942,200,490,282,791,447,594,143,219,270,562,337,821,794,618,902,828,117,899,212,858,530,664,766,96,440,810,521,828,167,787,434,12,420,538,99,952,437,468,991,391,206,346,917,3,724,22,475,195,31,602,423,51,846,249,333,447,779,332,625,372,33,168,189,932,383,782,523,728,517,774,274,529,540,636,861,87,121,73,59,864,19,758,307,385,903,845,360,228,14,262,450,332,945,921,527,406,895,379,641,711,403,741,500,716,422,800,619,207,411,602,823,814,960,579,239,709,515,198,947,218,447,350,585,700,516,734,967,100,558,437,410,989,120,322,968,902,406,553,644,400,842,19,274,77,539,104,430,327,831,313,203,131,733,604,124,433,866,131,499,318,629,746,595,271,602,14,963,759,481,270,708,657,766,142,701,764,379,81,39,348,155,2,23,494,663,673,377,597,175,42,89,543,69,537,609,146,462,788,591,224,909,37,482,606,199,816,129,542,907,716,166,790,19,584,504,793,938,797,298,475,309,762,988,688,752,317,180,377,952,100,692,89,549,261,370,309,926,721,908,271,842,571,780,853,785,263,55,624,334,205,819,419,365,363,135,487,799,200,908,658,840,483,540,433,56,22,698,93,925,477,354,180,295,197,668,788,988,966,140,759,932,539,843,124,258,863,195,459,592,950,752,137,805,699,678,307,730,304,119,955,682,455,971,239,898,276,947,447,726,818,922,27,42,918,588,415,359,267,576,827,968,889,849,609,778,926,290,139,681,494,544,198,385,775,331,740,12,257,217,242,635,984,162,304,63,594,848,154,803,579,708,102,133,858,737,87,365,856,157,220,317,129,884,672,931,863,243,858,144,887,954,585,40,669,521,520,289,447,292,137,122,337,308,492,256,923,43,395,827,85,995,762,288,649,681,252,798,264,186,95,394,54,536,203,397,144,326,64,421,15,196,772,709,171,477,590,675,764,112,334,215,843,927,608,538,901,199,752,413,99,236,55,277,319,930,953,571,755,69,56,249,71,311,712,789,549,78,66,655,797,816,219,789,895,272,900,736,284,265,93,595,969,589,860,68,29,626,886,357,315,698,198,445,602,307,414,322,67,455,860,317,681,318,931,367,768,132,697,430,632,91,651,606,189,97,460,242,335,397,83,413,279,719,44,404,801,678,266,966,175,243,989,889,604,554,91,889,117,357,298,76,691,175,304,882,257,677,217,461,472,769,867,447,520,411,738,602,457,831,167,173,67,77,839,272,229,607,441,470,568,443,896,840,791,706,663,48,214,245,829,918,391,913,18,211,154,495,187,829,510,615,671,572,476,721,984,113,818,665,327,268,684,761,619,98,402,884,883,53,446,271,338,912,412,576,967", + "393,923,661,274,610,211,786,4,539,960,39,66,671,60,890,310,813,310,690,722,865,394,834,320,690,798,144,674,437,582,281,960,704,658,571,22,59,323,287,875,634,879,128,431,935,531,913,416,258,570,965,36,580,956,278,176,392,544,948,940,797,946,738,856,714,450,854,370,591,388,281,637,331,869,190,202,347,728,537,494,430,143,850,164,612,450,665,752,648,641,769,506,964,551,729,164,267,391,798,61,836,75,782,892,343,43,487,76,314,28,737,196,900,384,794,928,450,333,947,923,973,938,671,583,477,639,61,231,206,733,187,759,333,593,153,217,300,896,505,605,398,770,720,50,60,308,589,815,665,19,949,364,772,247,975,792,965,39,297,767,126,5,87,973,669,602,177,66,87,83,798,684,904,780,863,387,291,298,741,146,753,686,949,271,535,0,791,830,20,696,707,593,965,160,184,742,185,631,448,31,489,497,602,669,466,677,276,558,294,991,311,642,395,662,210,841,499,428,406,852,359,908,485,731,917,767,219,874,571,156,595,134,284,897,905,787,800,592,358,405,219,410,308,135,149,389,340,143,240,377,202,31,163,123,214,732,427,777,547,271,851,269,802,358,192,8,528,270,401,791,722,277,81,371,987,667,836,385,976,883,431,972,708,51,95,516,389,998,821,238,461,967,494,743,761,335,606,98,664,639,543,561,725,751,832,720,87,104,150,52,750,609,122,474,983,482,840,908,483,632,444,895,495,637,402,329,958,917,918,710,896,443,265,912,770,381,767,250,906,854,79,64,417,6,216,662,885,144,480,497,542,222,288,246,406,855,758,835,688,81,377,951,445,782,538,260,130,751,818,753,727,971,994,533,696,852,385,600,156,224,402,941,467,508,950,660,254,929,882,275,38,259,137,832,14,651,119,715,934,881,213,939,286,398,446,294,351,383,55,637,263,331,966,860,475,581,610,668,510,336,602,49,153,196,812,914,180,817,217,672,918,76,644,26,440,533,805,358,82,472,917,641,903,522,768,914,402,843,431,85,694,996,684,915,8,991,395,220,345,293,379,375,876,389,998,803,99,515,873,317,848,358,741,391,231,324,102,398,816,955,433,776,68,750,245,557,160,296,308,755,321,656,225,914,376,430,687,576,560,15,823,846,893,269,99,355,613,149,682,175,840,479,231,64,59,764,856,773,609,181,948,895,251,33,541,409,968,391,617,990,70,188,702,20,142,348,157,500,992,473,411,294,4,611,718,791,668,315,578,950,896,635,767,232,152,780,769,170,542,351,491,628,247,220,196,688,524,365,833,244,338,370,359,651,759,696,851,337,590,944,807,39,470,791,528,948,574,327,160,628,891,669,411,839,329,885,151,6,194,286,604,150,400,44,983,860,454,207,636,551,22,754,555,525,437,886,95,202,204,73,902,439,955,285,294,372,237,77,692,798,90,229,194,513,829,367,495,424,320,175,236,231,65,712,120,710,746,185,875,953,939,7,277,693,471,47,549,524,599,351,326,939,928,852,755,488,325,244,194,647,342,226,757,672,699,229,117,702,503,599,527,974,767,73,21,696,221,616,91,243,135,644,534,572,894,758,300,336,678,912,588,486,930,131,608,708,422,585,761,393,286,694,705,56,101,834,436,681,229,181,44,141,125,424,32,656,806,305,516,765,153,194,712,146,501,337,757,671,372,136,271,116,906,250,520,75,537,711,121,207,675,309,437,943,727,300,229,320,809,172,726,186,995,32,656,327,548,586,845,972,452,300,629,356,843,335,466,934,874,191,939,715,464,200,770,953,434,808,486,642,281,975,137,581,25,455,290,10,815,207,557,213,782,445,63,607,782,642,431,281,840,3,937,529,256,54,647,627,696,630,913,205,276,359,591,743,745,878,108,95,137,321,562,492,216,911,809,94,385,594,728,660,737,412,919,372,487,191,139,918,857,357,560,353,331,70,961,903,269,488,106,307,729,639,60,49,152,571,499,636,671,383,839,371,748,431,176,996,125,271,657,66,552,250,506,810,261,327,200,263,982,257,737,267,820,264,19,903,615,855,201,534,148,310,426,628,170,5,239,645,612,788,982,133,759,799,322,720,239,80,446,354,316,196,523,503,150,44,747,824,143,782,246,492,655,93,489,648,411,149,638,56,645,943,919,631,856,623,896,7,987,684,705,701,975,867,68,586,146,770,446,880,903,283,715,519,909,50,832,519,951,409,261,337,240,704,314,323,70,517,161,792,666,236,229,644,165,605,841,498,625,345,265,457,573,444,38,907,647,595", + "678,496,852,50,966,458,580,591,207,518,786,626,168,22,360,137,281,235,752,544,459,37,395,959,874,608,474,259,837,539,869,693,621,895,53,177,702,943,35,224,237,192,761,760,140,725,105,83,557,402,148,192,653,558,266,9,531,755,910,449,36,834,334,599,13,617,818,873,278,747,389,258,239,879,846,964,158,356,416,542,549,353,691,373,363,642,141,368,232,893,769,149,535,265,677,746,207,74,612,968,728,325,74,46,972,789,252,312,406,737,475,227,477,856,888,808,776,101,560,876,320,263,977,777,841,505,44,948,265,585,128,240,415,849,980,199,795,27,144,519,31,666,940,168,97,99,384,928,514,571,79,207,291,867,535,884,949,965,598,421,960,594,45,966,157,357,619,750,47,696,616,928,544,503,715,391,132,772,660,14,486,635,756,962,598,791,0,74,66,682,746,305,516,405,275,97,495,480,826,275,463,685,977,451,945,325,727,548,233,730,840,157,195,447,412,864,517,577,35,802,751,258,572,853,706,693,609,649,853,480,786,945,625,461,587,743,771,362,722,920,36,654,29,775,705,283,510,895,785,776,448,683,188,164,816,788,335,485,216,864,839,185,857,892,809,9,465,745,58,942,483,598,180,372,177,724,579,990,573,121,986,479,617,309,406,643,646,287,61,685,962,813,476,222,628,543,802,370,276,598,111,857,218,442,605,126,40,249,399,153,80,382,667,749,841,990,251,187,319,85,57,887,597,924,469,213,329,99,151,581,172,682,305,996,373,592,160,222,939,950,408,398,235,117,446,279,563,704,73,424,493,103,989,146,5,281,159,155,963,150,298,588,431,189,743,211,121,762,356,722,283,619,347,484,257,634,666,247,632,368,329,860,818,438,209,899,999,324,799,407,515,100,121,896,85,683,758,428,910,816,424,796,756,819,578,219,311,98,360,434,375,578,490,589,558,902,231,893,540,190,895,294,25,375,537,503,788,691,285,859,621,825,391,404,338,452,630,361,493,78,535,37,461,503,412,274,126,751,187,248,365,46,60,825,961,262,846,15,430,408,453,471,11,955,344,26,447,930,482,612,148,842,902,937,657,681,179,339,629,618,405,295,964,38,245,799,950,57,952,122,560,757,649,342,387,68,84,914,446,710,51,991,113,29,635,334,492,217,141,610,841,213,425,29,556,591,660,710,866,756,52,969,763,694,511,190,13,867,978,22,436,507,351,402,123,749,108,743,839,155,133,164,539,522,827,380,43,712,769,634,242,267,296,959,736,900,437,80,285,3,44,885,737,32,202,122,50,326,935,77,229,698,664,39,684,795,322,634,955,230,421,243,248,196,257,758,383,593,964,45,839,541,388,794,475,478,550,902,202,467,121,316,333,854,597,165,473,947,513,652,821,883,290,34,273,861,501,678,484,397,515,633,857,339,592,957,607,92,794,580,450,277,992,108,964,542,773,247,79,993,953,626,865,502,71,607,121,452,282,844,40,933,360,921,733,125,360,514,29,32,886,692,805,720,19,817,749,626,516,951,873,4,43,432,994,91,28,606,550,806,760,551,431,941,302,409,741,648,69,353,419,12,619,262,720,922,946,639,93,733,918,110,387,716,717,282,835,329,770,672,130,529,507,290,715,5,132,344,99,416,304,462,425,767,694,223,744,988,574,889,13,316,866,475,301,683,949,811,680,460,853,851,761,151,647,46,423,511,377,326,689,298,800,832,718,696,581,530,137,688,311,292,44,28,267,161,272,215,599,990,436,671,917,190,642,420,917,223,794,539,168,606,872,501,104,791,796,202,11,758,976,397,157,183,722,966,222,763,412,811,340,79,469,278,186,401,70,896,761,661,994,894,585,325,149,281,677,230,614,947,205,628,806,461,941,717,951,130,429,782,52,623,249,919,120,571,906,634,695,783,506,163,501,584,831,724,951,26,802,541,656,582,927,72,406,527,819,135,64,771,257,431,173,170,538,594,780,402,195,573,164,661,428,446,875,262,89,87,593,750,906,905,469,198,395,933,546,834,967,377,633,278,3,474,911,806,975,382,865,361,237,931,594,351,7,879,981,964,557,23,289,393,765,538,891,620,99,932,929,434,759,45,47,332,606,52,569,461,646,415,971,329,623,847,143,650,820,109,252,707,841,251,185,733,319,629,259,99,668,4,332,264,25,283,742,949,943,701,286,189,214,657,780,825,328,719,328,839,348,224,755,280,788,405,905,320,769,816,391,399,393,867,596,510,289,986,308,644,695,37,57,244,774,527,825,458,738,799,751,861", + "873,960,457,808,563,409,895,731,631,850,204,323,21,392,890,511,67,493,244,862,176,590,481,237,361,441,291,204,223,345,973,450,794,336,362,191,604,210,147,866,610,813,219,357,230,977,838,692,70,912,499,145,349,11,668,88,685,652,6,585,523,400,381,254,397,175,700,168,193,153,266,731,492,489,928,752,488,640,997,63,540,974,745,384,813,528,140,436,904,740,288,770,212,665,258,120,443,967,652,312,755,177,622,645,384,913,532,702,508,556,269,358,738,784,640,898,719,30,290,808,446,92,976,133,235,956,138,276,800,489,438,411,582,183,103,180,399,850,881,890,491,540,486,452,714,242,29,695,118,627,988,816,565,134,512,356,217,954,25,659,339,810,384,222,391,739,347,579,641,875,896,300,449,332,373,546,400,692,691,522,750,959,139,559,471,830,74,0,802,974,933,601,728,774,807,532,5,335,476,642,373,556,958,405,332,305,433,957,305,832,598,94,626,303,81,779,778,437,793,709,756,973,486,817,400,349,621,123,85,296,213,788,811,105,506,682,857,974,998,99,636,266,828,971,605,204,563,801,824,799,912,423,447,55,188,112,51,70,32,963,386,826,907,734,274,723,951,584,359,722,777,453,218,738,428,299,489,720,22,671,976,549,661,487,652,734,218,759,315,649,282,944,344,322,769,953,227,516,560,752,904,543,479,61,153,172,180,426,338,634,460,42,151,240,228,964,209,920,8,502,326,548,957,777,375,657,794,794,751,66,44,779,545,870,177,97,458,174,434,953,93,859,269,421,308,894,536,504,62,710,269,726,536,119,406,408,644,10,240,58,731,528,433,103,344,98,459,212,35,837,751,738,820,491,766,702,292,60,641,9,123,676,617,762,878,390,670,451,859,155,654,600,321,947,688,994,38,256,106,990,983,868,794,459,287,328,449,789,743,377,957,412,152,693,494,816,987,136,486,613,903,473,43,234,615,409,483,443,336,206,405,645,25,178,126,921,162,307,318,87,508,819,626,633,446,181,709,315,581,666,747,250,137,834,239,533,940,219,948,176,263,54,349,937,991,345,724,580,563,668,982,256,282,460,701,339,567,195,382,927,449,497,125,81,129,82,947,786,657,556,148,124,157,585,278,480,716,46,537,175,475,136,247,978,261,506,777,757,750,738,264,247,373,961,34,798,294,534,567,547,817,21,523,391,672,137,811,644,532,913,23,540,741,208,715,808,688,798,980,255,115,492,434,96,583,399,814,114,74,881,818,930,7,343,953,446,925,708,97,925,126,886,785,980,908,674,735,139,268,740,30,526,402,288,579,836,118,403,597,9,131,698,193,86,479,594,442,705,844,366,699,644,336,708,693,809,822,34,910,230,182,928,636,716,219,836,76,796,62,480,930,868,993,68,380,819,693,776,212,657,96,127,865,763,631,80,445,659,112,223,947,792,515,439,70,560,766,661,896,172,835,872,935,44,942,831,570,550,906,586,952,170,842,548,255,464,665,594,467,341,878,897,451,408,423,780,755,923,380,327,968,542,8,7,307,604,347,720,105,641,853,5,377,272,926,680,176,772,862,855,708,292,939,691,841,206,545,565,764,488,887,847,947,565,226,366,934,146,673,695,84,354,751,192,309,603,316,387,160,134,307,905,820,767,465,251,464,483,755,243,686,175,31,145,764,10,687,23,594,749,680,896,792,75,762,399,715,757,223,597,570,868,921,257,103,290,245,60,843,899,325,115,168,93,338,97,970,832,407,561,933,66,776,172,675,871,478,612,699,881,877,564,241,538,243,941,81,759,628,64,381,657,994,500,679,181,100,386,616,622,971,879,650,895,827,580,975,458,64,99,780,575,702,250,579,222,387,246,211,62,638,261,799,570,336,12,792,196,29,598,820,432,223,825,152,202,996,94,871,742,39,744,947,713,869,415,751,938,421,386,268,114,284,424,846,885,26,691,479,302,876,571,888,312,329,961,25,330,261,870,222,342,290,985,746,669,432,798,307,82,234,361,407,191,551,418,812,217,894,626,57,860,338,141,395,779,867,523,864,562,14,454,267,640,561,984,285,669,105,844,133,795,415,527,489,664,331,413,979,373,690,32,330,358,886,917,608,725,417,122,337,476,737,746,895,946,732,888,390,333,839,384,182,295,278,301,205,921,231,486,196,894,250,162,442,845,417,646,853,679,961,139,210,388,895,982,848,698,142,591,965,938,222,450,668,181,411,661,321,230,187,751,144,707,191,972,112,147,478,615,128,749,530,570,518,3,605,538,28,884", + "8,488,259,973,165,222,212,795,658,870,897,817,927,784,774,494,235,166,920,238,926,598,421,653,395,296,454,785,178,759,548,144,186,935,988,699,372,974,787,540,235,356,220,900,181,958,348,305,150,86,851,908,405,60,186,288,534,992,627,550,495,761,613,38,742,900,972,576,20,490,2,610,596,499,660,555,260,123,695,942,215,953,534,869,942,39,782,965,455,539,825,636,464,739,677,430,727,166,850,846,537,848,147,576,791,658,653,994,730,849,354,575,717,804,187,306,290,805,646,554,900,413,785,502,475,980,229,84,233,916,255,132,397,295,440,602,298,142,290,809,153,247,453,496,737,555,33,394,847,691,215,478,568,819,649,238,655,964,2,462,916,640,945,917,591,601,526,729,88,230,539,392,798,618,354,350,508,284,380,270,353,180,242,52,828,20,66,802,0,458,815,870,397,298,404,829,650,961,811,926,795,629,425,313,930,96,875,555,514,747,465,73,744,364,458,565,76,572,207,607,969,379,791,180,825,684,429,423,132,638,404,550,237,761,597,520,648,326,860,391,617,865,614,93,51,454,525,396,310,471,349,385,318,576,591,132,197,38,162,456,830,891,47,632,108,968,297,163,792,717,344,118,746,500,24,389,529,644,313,861,251,916,753,576,365,729,133,773,28,948,789,998,137,66,642,778,351,174,672,265,329,225,987,540,751,318,94,258,870,726,394,988,572,510,106,24,195,859,236,795,977,599,122,857,48,95,336,39,280,538,703,989,196,522,284,681,962,285,281,851,955,462,481,747,661,110,165,979,288,147,538,891,498,742,232,288,900,625,842,56,812,654,967,462,935,826,493,955,399,775,287,686,96,42,860,256,425,561,785,823,191,965,963,604,718,814,290,934,656,25,755,435,35,59,434,617,346,111,597,968,455,417,472,157,30,829,788,226,55,580,575,327,135,94,893,757,226,295,801,934,992,588,45,791,948,949,810,229,498,852,191,709,372,606,762,80,192,634,869,358,926,162,201,470,238,686,748,341,702,278,745,835,950,257,809,357,756,870,931,448,186,464,554,829,359,95,913,661,410,529,586,767,468,438,215,736,582,943,324,286,43,534,907,36,975,258,86,618,670,878,135,978,920,802,281,552,622,303,386,351,332,781,73,438,314,311,72,517,3,499,548,672,285,992,759,859,116,88,868,324,520,614,812,352,777,615,724,477,833,945,587,360,54,582,20,446,967,604,731,390,407,851,205,186,988,8,576,314,520,273,641,285,887,453,793,326,754,69,491,825,120,210,950,469,986,784,762,685,17,373,184,875,839,367,300,661,894,483,873,121,774,655,902,450,938,337,991,380,974,349,547,265,108,184,206,246,230,483,182,22,198,292,841,712,213,884,748,142,474,604,555,484,835,917,672,637,377,626,395,153,162,82,830,879,84,473,97,811,131,272,120,247,583,702,309,950,863,704,803,255,133,154,540,587,133,167,23,854,711,186,341,290,980,60,581,163,494,45,817,571,566,403,529,46,904,941,453,865,632,312,275,326,451,233,737,520,586,820,150,614,759,427,993,521,387,204,9,640,420,158,398,616,649,355,536,311,41,720,24,642,877,136,599,2,978,594,46,949,328,763,19,933,177,10,97,733,139,63,155,881,277,298,981,57,242,307,257,583,151,647,504,620,744,603,927,512,328,404,2,172,974,821,849,736,414,126,767,56,343,264,182,455,423,530,450,875,31,142,234,56,206,707,227,175,191,413,140,937,520,39,505,979,661,699,787,413,220,858,575,998,605,559,484,692,501,737,938,959,299,930,17,279,867,125,754,571,38,484,268,550,797,440,882,756,121,476,56,275,328,12,417,788,14,123,958,405,553,837,116,393,55,134,747,588,890,609,551,426,553,539,751,322,747,44,963,28,551,32,67,689,889,139,474,487,178,959,200,670,968,45,709,778,500,927,256,511,141,853,365,631,759,143,118,877,828,557,64,849,778,644,296,317,662,734,387,851,468,264,351,936,922,623,83,199,621,588,562,872,366,530,494,856,835,250,607,800,821,756,473,521,697,601,847,857,416,4,338,587,240,569,869,97,93,120,54,308,372,661,932,378,271,234,819,399,30,124,36,145,854,527,271,486,655,378,783,874,92,816,351,397,968,219,278,186,29,427,915,822,613,495,701,156,657,459,38,284,485,62,237,593,153,105,906,35,201,647,6,996,613,353,620,735,856,739,114,537,698,420,887,561,802,573,274,834,571,267,886,251,158,212,549,437,420,205,600,743,559,621,892,472", + "708,452,348,66,217,559,873,633,639,876,506,498,892,791,460,786,220,574,199,666,793,622,25,41,182,783,24,203,899,95,108,74,78,994,98,726,487,650,89,461,262,780,214,742,299,190,152,396,803,371,521,207,622,390,263,419,234,187,541,879,88,37,428,98,600,639,305,551,811,288,101,198,739,278,428,237,824,34,788,565,992,625,667,184,620,998,311,379,204,508,550,905,972,832,431,474,266,430,77,286,921,563,425,560,929,856,240,658,500,620,199,175,853,873,668,826,16,389,931,596,198,271,274,752,478,212,636,161,996,101,569,197,900,23,206,38,881,425,586,122,860,665,578,950,576,434,28,57,333,541,727,465,294,842,622,669,290,494,156,334,300,292,264,157,194,93,303,763,890,690,468,588,124,67,651,216,552,625,67,969,196,317,491,410,895,696,682,974,458,0,985,781,86,383,638,451,374,60,904,401,587,877,814,928,813,15,229,932,949,914,910,362,225,837,567,145,859,343,69,849,474,503,703,763,671,492,980,399,668,410,429,874,426,826,16,471,567,390,258,663,192,902,949,281,473,492,174,993,72,899,381,908,191,558,607,110,998,191,431,843,974,701,346,995,34,764,671,197,773,801,742,782,70,649,412,704,525,286,700,477,413,741,969,876,647,417,336,152,982,574,965,710,544,662,781,93,985,213,880,207,881,427,751,141,458,993,46,420,936,382,785,392,594,129,708,766,5,309,346,293,77,115,595,65,676,175,545,501,374,152,435,473,234,912,446,399,676,705,818,429,768,503,993,977,440,685,890,521,976,961,146,668,644,796,929,109,84,694,950,15,573,161,248,606,9,13,321,207,265,449,189,13,13,280,576,847,463,561,227,109,1,620,597,369,528,326,798,385,258,182,817,980,36,305,927,588,178,184,679,685,718,665,406,260,851,684,405,366,708,874,777,218,649,231,301,815,841,483,650,959,934,9,87,365,516,391,918,487,263,296,79,450,92,409,671,730,85,176,349,948,456,470,746,926,687,781,230,202,721,144,280,548,453,452,432,213,642,164,423,540,817,445,923,137,346,779,411,753,216,497,426,681,23,380,203,293,97,311,222,706,177,526,89,68,636,604,943,991,752,701,193,191,340,208,574,886,3,424,78,867,97,566,150,66,967,711,510,796,675,165,318,685,225,874,263,744,148,986,491,678,182,250,815,72,218,90,968,337,79,44,332,749,381,570,909,273,955,626,948,589,636,165,568,121,526,67,640,871,723,183,837,162,216,432,96,286,586,808,113,88,903,393,134,795,594,208,796,708,670,221,993,867,696,96,314,904,636,179,240,144,211,21,937,563,934,402,440,185,671,831,169,73,42,71,967,563,999,200,786,931,862,51,46,330,431,276,566,145,489,164,993,608,479,801,242,404,279,750,18,341,206,710,356,605,198,705,795,648,768,872,981,568,811,796,522,234,312,219,915,371,945,687,286,531,920,916,116,532,828,769,227,554,371,576,740,660,126,926,981,63,324,409,391,204,595,960,967,635,869,802,404,899,977,453,709,966,450,378,422,165,630,332,979,505,651,520,965,572,44,121,783,241,145,8,130,659,563,883,501,504,500,996,634,791,193,363,576,564,592,890,201,703,941,604,777,452,775,894,71,981,154,256,231,24,109,878,158,915,426,462,572,919,23,534,464,91,936,828,344,175,426,998,616,931,983,561,930,896,494,188,150,180,199,904,419,756,260,330,278,917,97,489,401,214,931,698,944,516,632,729,207,475,59,703,93,381,287,92,825,401,711,355,530,976,283,355,730,994,499,686,269,320,925,286,317,213,901,506,127,332,887,51,52,186,623,203,69,585,267,316,787,152,784,891,435,766,757,62,925,833,516,525,806,860,794,925,634,411,416,123,565,737,193,839,977,234,580,490,444,362,963,909,455,797,846,570,3,838,336,458,629,877,114,746,568,577,245,74,956,579,820,212,840,341,78,527,852,790,297,869,625,742,815,96,41,388,216,786,240,444,912,681,493,262,344,783,260,736,260,570,654,706,474,50,281,384,831,361,801,260,365,601,590,133,417,47,567,123,374,612,53,590,328,844,237,287,752,958,45,569,91,910,402,54,574,241,666,547,212,504,412,836,643,287,326,814,297,148,821,401,515,886,987,394,993,470,491,736,589,662,802,639,817,676,555,320,922,348,770,9,929,77,206,153,154,420,971,688,662,643,82,539,550,458,476,728,866,198,682,367,970,478,787,195,579,525,433,347,738,530,83,904,565,847,161,147,16,294,476,531", + "268,407,990,918,116,641,589,419,993,109,84,670,512,25,506,913,452,972,6,842,482,648,297,151,810,735,619,529,708,563,549,739,331,680,130,296,231,309,348,815,500,266,636,761,603,547,543,578,700,138,930,718,650,521,520,617,114,478,797,770,353,119,794,787,190,549,445,91,760,762,140,845,646,102,924,709,324,727,620,639,360,564,138,219,434,181,974,620,922,700,674,908,708,915,624,640,934,535,788,250,975,657,495,765,723,853,601,8,152,868,989,666,248,714,818,42,819,488,752,461,290,179,451,715,700,932,897,309,765,344,929,821,625,87,570,452,620,148,866,198,257,62,15,385,651,477,207,670,418,814,245,183,331,113,314,768,488,60,522,589,504,650,68,193,660,133,188,307,730,318,777,431,387,726,541,393,142,615,613,432,39,426,941,774,121,707,746,933,815,985,0,626,305,965,764,631,227,597,297,114,869,367,709,588,607,842,222,858,36,48,484,940,654,759,220,359,173,52,580,773,638,749,348,952,510,597,123,188,879,773,397,310,815,395,288,799,322,442,827,48,895,911,837,280,195,664,682,720,750,464,292,410,632,369,550,916,838,909,348,730,141,82,601,588,50,860,757,532,206,680,751,821,949,8,629,840,617,155,330,80,519,284,63,466,171,203,804,815,57,367,515,461,687,838,255,546,205,201,281,451,180,737,708,935,883,25,735,62,888,239,238,662,713,586,134,877,639,910,631,521,131,379,803,712,443,106,23,452,804,857,41,618,776,422,313,555,106,975,905,449,984,204,649,82,517,142,604,503,193,650,874,609,432,288,621,601,716,150,535,486,411,743,539,640,290,871,948,774,135,650,285,984,514,935,291,164,959,346,633,750,980,786,763,263,723,358,210,92,747,21,405,263,760,653,203,558,405,102,616,234,535,488,218,701,51,308,68,341,840,605,271,841,646,259,482,370,906,405,515,715,872,401,791,533,856,60,866,553,369,605,276,946,135,593,245,62,230,863,172,895,562,169,462,835,53,518,900,447,867,930,758,757,600,419,759,55,598,741,138,298,910,735,228,691,938,365,407,493,171,45,944,513,807,803,434,420,194,370,702,504,557,671,597,839,302,156,819,295,427,92,248,907,46,621,64,798,819,593,394,706,719,677,959,211,394,671,668,510,282,27,406,375,387,931,832,594,512,511,844,123,501,778,789,576,937,370,182,207,427,629,894,778,171,485,411,239,745,452,163,205,168,473,43,267,403,265,779,859,114,466,793,294,932,273,79,392,768,308,477,912,367,582,671,857,650,996,66,76,110,359,274,338,913,687,982,250,441,350,146,683,920,627,111,390,853,502,111,359,409,803,708,667,161,826,815,368,247,504,548,791,674,199,515,928,455,266,916,676,358,830,562,926,928,612,873,637,934,970,668,740,925,224,480,704,913,874,951,685,905,677,691,422,740,409,278,503,784,354,816,344,846,304,860,502,28,300,696,457,631,922,842,551,739,619,699,728,559,448,926,367,691,357,314,194,889,651,271,123,579,669,395,337,357,999,183,948,971,85,692,621,414,822,735,419,775,130,953,667,766,912,42,466,588,291,255,286,168,309,437,500,428,946,848,286,639,316,128,352,991,681,28,660,873,760,195,640,302,886,95,530,117,592,60,461,717,299,405,295,568,585,521,480,919,315,545,304,74,320,505,962,906,89,811,806,160,83,191,159,919,385,764,777,70,187,711,930,55,231,204,326,417,611,339,652,338,687,39,8,511,832,770,555,72,396,163,990,18,87,130,764,314,362,142,104,609,220,130,685,594,701,888,864,190,279,901,635,67,385,266,486,284,901,483,575,819,26,639,954,630,53,295,998,15,355,362,793,130,853,820,890,43,384,571,200,887,476,727,527,904,434,215,166,830,887,718,206,733,526,675,916,14,316,55,517,979,232,859,81,761,366,221,278,278,265,622,217,169,178,705,861,101,29,943,572,657,548,769,542,975,938,540,549,435,323,891,120,571,187,916,938,285,220,386,841,34,121,842,323,320,649,588,42,170,144,866,454,352,547,741,86,314,973,57,552,245,924,31,861,476,516,24,698,708,614,753,893,338,195,185,605,594,339,262,722,175,781,595,113,884,312,968,264,915,151,691,416,871,946,246,421,594,243,683,733,300,171,597,421,867,518,579,96,426,548,666,127,190,388,668,132,391,141,680,859,687,784,228,742,374,760,574,662,503,143,638,884,74,791,788,917,546,246,593,409,293,465,424,344,672,299,200,385,708,651,165,392,360,298,749,503", + "177,844,365,456,528,570,171,666,433,984,563,61,908,517,905,467,676,223,186,448,762,440,433,685,423,702,846,807,708,765,226,614,572,386,926,313,663,539,107,613,581,472,560,540,714,14,956,85,571,484,284,845,337,144,417,24,333,541,308,639,521,272,415,58,941,386,253,423,408,497,557,467,602,937,117,268,954,104,432,202,387,210,121,833,762,19,65,896,329,526,352,259,136,715,847,893,870,401,637,838,1,642,133,756,87,700,624,732,82,294,622,368,33,37,932,612,795,758,34,533,56,252,785,494,89,628,574,620,140,899,928,255,73,354,687,235,702,499,471,16,976,105,517,205,839,766,577,103,617,419,574,760,696,196,89,383,429,58,986,655,415,522,806,29,899,676,150,223,292,45,173,717,703,134,911,539,221,545,191,851,471,496,745,598,62,593,305,601,870,781,626,0,144,701,517,577,190,386,432,528,664,914,369,11,544,674,34,687,757,223,574,264,537,501,208,679,618,700,259,981,480,351,904,648,15,985,530,759,231,428,341,457,10,629,222,303,186,845,191,54,822,176,613,690,966,542,221,81,436,757,313,288,413,244,522,700,420,258,856,351,925,350,532,984,451,335,551,341,683,577,412,391,498,478,432,340,115,822,962,253,930,456,213,80,232,544,455,625,549,10,485,869,697,605,444,677,153,681,359,775,715,73,685,679,887,132,331,176,229,973,894,110,897,171,801,954,116,656,834,41,411,175,972,603,346,20,839,5,695,841,186,271,248,337,946,246,323,749,874,960,483,725,258,684,298,992,279,568,366,279,810,650,939,583,186,49,696,718,305,22,489,983,135,262,97,612,65,818,672,276,213,450,93,884,777,259,485,61,134,392,381,882,886,66,144,356,334,806,560,317,355,822,133,721,71,608,221,465,857,601,646,910,627,867,646,134,151,98,352,38,359,812,235,326,122,876,117,990,788,22,308,952,599,213,509,577,829,803,663,620,987,271,579,479,465,732,51,947,839,784,181,215,779,909,58,706,908,984,665,607,976,638,948,556,165,874,873,582,182,488,629,295,415,524,441,687,512,662,53,953,965,370,171,65,875,340,298,457,339,77,287,443,632,897,408,26,533,732,175,334,814,639,458,508,748,849,100,263,93,428,762,336,184,145,596,631,480,947,450,885,30,931,668,147,229,796,393,642,486,830,316,85,57,232,831,877,381,826,249,609,874,795,558,325,553,939,426,872,294,183,121,756,832,529,85,781,882,233,538,91,229,14,711,725,760,718,21,685,818,76,531,547,491,327,628,568,600,434,504,286,96,886,39,321,811,832,453,389,95,343,452,713,434,588,352,209,571,331,987,486,357,634,852,886,663,483,20,407,462,960,69,22,443,585,900,770,607,721,219,457,692,686,149,304,70,961,23,875,577,65,926,451,782,303,290,944,171,663,247,194,66,724,385,809,508,629,55,94,72,785,286,219,475,915,512,778,174,668,774,887,852,307,172,768,3,743,341,227,454,464,15,730,503,437,835,250,306,964,382,489,866,150,834,351,613,209,303,535,465,843,210,476,109,195,185,96,859,613,600,416,395,791,287,852,108,993,329,468,61,33,908,618,524,18,961,312,463,184,14,568,340,728,753,807,739,97,72,599,53,420,990,576,918,271,507,244,836,326,105,740,437,679,510,98,252,100,708,551,881,296,936,767,548,14,193,215,78,298,522,680,621,167,480,157,389,359,240,853,445,289,430,441,284,954,474,33,839,47,822,247,99,95,928,706,276,834,207,74,923,203,292,444,777,242,105,814,974,546,745,961,694,315,353,293,150,178,76,968,921,849,23,881,922,508,302,202,979,943,586,9,51,717,241,570,66,381,9,50,403,484,317,520,474,78,700,375,295,247,701,640,274,761,120,157,162,43,329,33,424,502,838,334,507,755,143,746,893,270,817,994,75,520,596,91,40,799,893,151,399,813,164,373,640,61,500,719,224,241,868,452,140,251,607,284,7,26,458,44,136,420,827,498,619,998,975,398,828,354,624,780,852,754,730,798,804,654,40,931,538,339,395,367,421,782,439,437,278,701,838,766,48,117,844,327,809,119,899,153,365,768,849,716,375,47,525,846,997,429,376,781,513,553,65,486,363,796,404,552,379,969,435,551,750,433,947,537,584,764,344,210,853,12,29,847,722,172,449,972,500,464,95,638,671,674,584,295,519,675,123,824,180,958,334,206,533,389,988,468,355,667,679,97,724,480,898,347,877,769,200,552,492,154,422,812,395,638,207,456,409,973", + "722,390,284,370,285,185,625,491,715,273,739,545,721,115,286,697,32,418,808,591,885,791,486,240,345,991,257,618,511,416,185,318,794,325,766,526,525,615,810,391,253,345,410,240,486,329,811,196,636,350,251,694,361,941,898,500,200,39,103,867,370,647,381,132,820,39,163,241,875,844,367,840,532,279,222,638,791,483,565,426,131,187,791,781,361,271,499,118,919,805,246,818,986,281,821,57,837,429,491,455,52,476,488,732,261,897,215,768,992,375,213,726,150,764,440,722,892,437,578,393,379,656,240,435,273,64,794,94,301,159,93,172,745,201,396,820,872,482,884,225,432,425,702,707,626,635,731,610,962,950,373,912,461,482,291,705,915,680,628,876,33,628,395,995,49,364,944,351,536,349,756,342,670,612,200,77,353,523,415,424,428,519,315,786,944,965,516,728,397,86,305,144,0,641,310,951,324,847,137,484,150,320,951,695,93,881,62,315,213,63,665,426,119,470,781,585,866,727,636,640,387,959,617,89,339,269,10,327,468,766,409,713,447,493,146,361,332,910,491,928,685,537,242,700,651,469,154,195,216,668,785,340,708,67,930,149,278,427,113,536,225,306,872,343,67,61,50,569,219,438,818,813,268,263,893,678,99,620,855,516,93,22,762,414,863,301,924,161,129,246,969,776,494,319,57,191,169,953,982,355,263,429,588,69,964,12,399,150,688,55,412,511,431,574,873,329,501,69,487,228,149,377,491,900,404,687,443,154,292,818,814,959,377,605,151,623,412,882,34,689,66,109,915,435,568,446,603,151,244,309,29,845,954,760,707,879,287,791,622,868,290,675,979,453,173,499,559,649,367,708,99,456,783,20,205,72,780,483,677,692,473,196,137,880,23,827,76,305,468,646,898,459,465,487,19,104,222,667,402,574,520,812,845,319,74,998,771,590,951,967,99,548,523,753,983,203,73,430,704,349,674,888,522,41,68,287,478,512,238,667,578,981,950,341,135,430,769,346,320,607,408,144,372,50,781,964,438,469,428,5,42,345,809,482,507,227,727,605,207,488,970,562,34,546,319,841,263,315,224,932,19,136,972,816,499,808,628,182,744,476,549,420,6,29,644,542,348,873,921,617,153,845,328,691,489,39,488,520,758,821,246,633,951,395,322,650,259,427,741,838,517,595,40,714,731,499,547,306,870,539,289,812,709,918,591,800,173,376,948,320,797,599,375,944,69,442,193,663,847,149,637,561,778,153,372,511,338,374,321,387,225,528,622,98,150,434,783,284,37,550,384,571,634,65,187,893,599,631,8,584,38,541,967,272,246,445,769,943,333,658,864,586,346,226,74,871,505,972,769,229,547,331,82,863,408,137,256,313,756,221,915,392,658,613,609,885,358,226,352,413,240,339,278,654,883,441,824,779,754,493,982,389,792,175,158,225,528,419,59,717,59,757,510,317,362,174,344,88,726,930,805,754,443,631,962,799,166,956,25,862,23,80,851,508,836,434,334,729,389,383,775,275,255,796,187,891,166,397,334,578,490,805,176,809,46,214,901,414,868,272,773,752,784,720,57,369,108,315,256,947,78,679,414,603,357,459,573,388,670,592,94,154,194,691,112,418,939,554,489,851,300,97,497,767,926,706,488,928,674,42,883,266,495,88,7,184,690,446,695,962,109,779,482,985,661,52,394,539,926,987,51,713,105,210,983,334,522,36,514,346,901,602,286,723,926,385,877,122,322,220,302,274,94,585,759,644,778,106,266,811,862,481,214,680,386,628,902,729,352,15,578,704,231,968,852,551,888,767,211,414,392,551,921,384,971,678,401,250,35,509,390,89,934,384,567,526,598,224,969,812,646,394,114,368,521,954,400,807,736,689,441,785,634,334,552,909,708,448,390,641,128,678,874,257,149,516,920,671,94,490,980,964,88,58,228,175,130,157,503,105,238,597,405,73,782,205,242,544,893,638,403,658,251,547,771,42,55,224,847,731,732,461,874,471,848,348,253,59,714,513,635,230,872,94,840,626,862,256,445,409,370,505,251,542,205,964,679,64,583,394,341,98,681,678,879,742,73,615,240,53,702,553,262,22,118,744,122,166,316,764,508,775,523,599,476,18,397,697,318,831,598,439,102,383,505,876,614,536,769,966,854,110,378,502,78,599,578,856,313,406,277,143,974,763,43,897,273,679,267,332,429,677,149,171,805,136,543,626,366,403,72,346,114,54,264,438,192,537,20,588,151,698,11,368,946,191,421,631,406,923,653,565,779,48,637,777,421,253,944,116", + "49,619,260,723,413,33,558,146,489,167,84,837,508,576,538,889,838,517,652,822,147,620,417,260,389,787,878,869,295,849,560,663,123,247,817,674,258,992,944,678,592,339,288,852,954,885,419,939,126,953,487,909,352,899,267,68,953,464,708,840,545,442,401,737,336,350,243,605,396,760,893,335,436,620,948,894,715,21,725,142,500,110,821,911,974,401,257,40,631,459,237,820,390,278,514,234,807,72,319,214,30,742,894,905,489,808,785,957,1000,558,583,819,524,81,11,711,67,161,810,710,363,230,691,492,595,876,178,129,90,210,965,736,713,487,412,538,326,922,270,849,764,14,507,150,688,815,486,282,571,360,544,964,31,10,859,304,332,644,16,874,512,333,974,725,409,625,494,860,840,650,839,392,50,462,50,940,203,889,173,743,85,111,424,929,171,160,405,774,298,383,965,701,641,0,834,959,886,542,142,240,469,722,959,583,773,447,624,340,352,853,222,488,680,131,191,90,344,307,448,899,640,40,760,188,880,466,606,138,835,155,179,372,348,842,334,930,313,186,189,690,346,548,464,532,709,7,543,989,925,660,425,82,700,395,695,517,269,705,528,784,561,833,51,498,958,378,61,549,389,226,415,573,876,658,903,160,586,903,897,476,202,808,376,744,473,888,75,785,98,660,527,588,611,946,488,18,932,891,623,625,498,132,547,196,773,787,165,535,734,777,362,290,273,102,563,513,579,916,317,799,740,717,884,198,207,262,209,866,82,331,494,800,685,950,908,411,988,878,698,748,931,810,404,747,611,286,334,925,495,467,969,506,811,61,799,240,144,459,413,378,229,807,871,273,626,80,533,806,760,82,416,148,954,211,734,475,666,581,516,76,47,359,515,962,99,760,358,647,913,956,178,621,508,926,838,937,414,725,358,497,312,103,416,190,783,506,155,779,123,854,198,860,897,79,54,170,831,219,258,694,890,56,233,89,800,434,398,436,590,182,515,421,266,476,652,824,491,235,868,217,714,857,16,111,752,195,520,770,52,83,425,266,626,269,93,494,901,618,68,612,927,987,666,739,578,181,278,711,374,95,883,409,151,210,300,391,220,363,984,252,489,641,283,173,827,494,107,993,226,364,430,136,981,493,553,938,313,703,534,471,665,678,99,944,468,329,532,840,947,262,24,353,992,837,987,464,871,465,874,94,856,907,133,492,20,884,729,738,164,629,770,536,240,707,294,685,397,535,617,62,402,730,402,313,288,597,254,780,810,211,665,163,260,658,868,672,150,317,684,797,646,47,644,4,822,865,516,655,459,54,414,96,514,225,380,909,706,637,713,499,555,519,862,604,196,968,992,943,24,624,257,908,267,126,351,816,637,638,19,842,948,904,345,459,895,102,766,926,670,186,919,994,412,609,852,100,384,695,352,189,903,343,286,953,364,194,561,962,36,126,100,737,891,589,899,16,583,731,293,44,38,707,692,905,772,22,796,175,766,193,896,304,418,474,356,752,781,320,935,68,725,594,797,341,119,325,452,416,190,755,119,117,692,803,731,568,871,482,512,724,761,15,570,153,514,388,721,92,810,675,576,253,217,922,808,106,911,247,411,558,401,186,920,887,396,337,541,727,8,925,353,552,880,624,540,371,289,983,59,80,511,782,952,345,864,714,416,670,159,399,199,215,341,279,606,595,959,80,107,371,848,294,333,36,516,262,819,327,874,73,485,748,865,440,679,944,375,868,180,642,550,493,261,484,629,789,905,905,127,936,332,61,944,887,746,249,718,150,659,385,403,501,737,548,396,657,48,587,118,509,784,765,139,823,791,16,331,600,933,722,449,221,848,928,194,72,212,735,878,610,154,718,871,915,996,857,974,454,87,9,390,794,855,430,99,32,297,846,384,853,480,432,333,32,772,192,442,927,115,910,974,611,354,541,660,699,745,835,950,839,592,353,933,713,740,78,463,139,760,883,202,714,986,883,29,499,993,111,35,254,661,447,200,825,855,289,693,598,268,902,334,640,487,438,649,15,409,85,156,939,957,679,19,112,87,95,829,456,240,784,730,935,326,506,683,863,894,877,680,121,243,471,608,560,531,71,247,974,738,985,476,687,787,369,438,125,713,218,248,541,909,156,220,121,815,427,873,338,264,933,49,780,86,198,104,683,800,412,399,661,908,976,266,751,328,75,284,827,522,543,953,207,967,342,713,300,794,859,668,574,612,525,572,97,651,242,897,641,175,682,193,159,566,329,913,605,266,787,822,206,720,121,30,102,937,959,314,486,541,849", + "448,477,652,118,431,389,770,905,956,528,710,327,346,414,744,413,494,407,82,228,945,963,202,169,604,460,116,230,101,512,344,82,941,744,865,299,305,825,750,88,167,742,828,239,737,23,879,384,294,500,706,240,784,572,715,502,489,976,910,264,778,814,743,374,19,197,904,399,401,53,823,860,285,913,778,235,552,261,746,197,813,517,27,509,828,808,615,974,917,696,218,750,683,804,150,427,972,836,384,982,338,187,325,397,20,513,433,239,651,292,332,733,206,800,256,841,82,731,388,885,901,650,939,237,257,270,560,725,950,976,543,192,983,189,164,174,317,87,629,886,582,449,499,516,829,193,669,228,537,457,95,85,231,682,185,731,416,55,675,823,244,530,922,737,87,218,436,945,421,211,328,317,540,671,139,899,431,279,68,145,877,239,370,25,388,184,275,807,404,638,764,517,310,834,0,255,610,623,78,329,197,729,83,868,549,921,141,431,496,976,933,700,510,358,512,413,930,750,517,371,283,276,751,492,624,786,400,829,571,387,267,836,837,742,19,697,18,765,439,728,990,269,354,375,396,376,439,544,438,342,236,462,648,32,598,911,956,521,859,488,805,473,338,401,585,600,629,227,169,321,232,743,519,849,698,627,78,512,868,886,901,457,206,692,126,773,991,231,430,368,508,804,471,335,119,794,401,38,66,853,366,421,467,613,704,135,668,39,662,815,248,541,523,541,366,272,580,123,607,839,167,835,271,185,716,114,813,8,839,14,610,765,554,102,230,44,354,304,431,731,300,794,183,802,174,76,554,223,865,283,382,827,356,750,512,155,971,258,876,391,320,120,394,73,865,472,373,559,875,37,872,16,826,193,966,577,820,513,335,500,779,507,944,869,204,84,377,782,898,75,385,650,728,658,920,287,730,24,634,958,363,275,903,55,12,459,493,678,267,613,654,21,547,97,555,373,751,513,190,887,887,590,304,325,347,627,565,549,513,940,883,722,194,706,602,258,17,977,128,70,266,53,455,532,141,419,840,813,183,658,838,882,914,109,17,108,399,880,742,796,855,552,162,122,593,650,914,833,790,271,343,356,346,269,169,820,546,250,595,731,366,797,625,576,629,877,876,699,755,665,671,915,337,747,861,284,254,129,644,972,172,280,996,109,996,831,805,747,655,197,273,376,896,737,885,410,150,973,39,491,284,741,749,536,142,677,898,43,741,690,766,960,843,273,203,809,554,277,311,472,740,130,857,213,595,91,786,651,431,228,692,711,420,269,324,275,750,279,761,633,348,282,645,966,454,670,408,608,395,24,845,28,895,171,435,10,176,317,945,2,55,810,858,349,378,629,277,431,731,32,504,366,119,814,392,397,593,771,497,511,197,544,766,758,429,295,400,101,444,848,459,680,907,254,986,113,538,891,57,325,627,343,798,16,290,108,883,55,896,830,417,9,78,152,455,432,807,555,753,793,38,678,640,813,928,981,360,43,585,182,79,387,272,246,542,245,801,887,248,471,420,486,512,883,326,362,909,27,159,922,67,302,699,903,235,75,100,778,336,525,490,224,823,787,491,370,40,683,677,607,115,595,771,172,947,230,479,981,964,592,762,763,321,997,569,527,535,274,721,979,423,249,662,885,513,5,758,86,732,447,805,941,882,71,216,500,480,270,753,676,205,104,6,444,64,322,462,608,525,308,557,682,490,485,151,152,920,364,261,433,550,161,671,466,380,767,422,361,204,270,312,15,291,333,609,957,277,912,608,175,27,694,459,727,266,800,973,591,843,74,572,737,748,603,567,312,47,640,569,660,546,128,201,355,577,287,193,880,751,26,830,815,630,345,692,944,532,539,814,999,127,355,326,979,646,650,862,8,609,863,538,970,243,927,554,812,692,843,461,715,651,531,859,773,958,346,506,82,397,941,728,118,546,975,378,647,485,916,17,145,671,534,597,2,745,631,890,340,811,95,69,508,150,791,734,261,855,802,536,820,221,627,67,727,957,230,72,582,54,121,696,779,727,535,992,933,386,865,127,682,831,833,156,655,459,5,456,562,890,564,342,511,560,174,494,485,551,806,81,177,632,809,516,231,914,236,836,79,19,680,41,437,237,188,461,485,238,861,558,844,233,845,984,504,328,34,665,349,414,744,238,496,779,198,401,825,715,247,31,4,291,306,226,146,361,860,852,613,956,856,46,421,356,465,898,637,866,704,383,821,493,400,508,123,493,125,326,939,411,397,351,704,704,723,741,431,173,209,679,8,539,859,780,459,187,398,222,332,637,500", + "849,822,788,301,736,435,356,454,860,279,906,532,279,831,307,105,375,721,808,692,86,244,606,823,306,720,512,337,580,864,760,781,728,880,148,123,723,645,898,782,122,463,733,91,747,282,481,506,112,393,61,897,846,266,126,852,921,774,423,376,318,679,645,310,319,552,595,321,303,218,448,846,251,96,195,291,233,957,317,562,397,182,352,147,695,762,311,908,474,827,989,270,112,472,915,571,802,859,116,757,672,454,209,290,452,110,32,927,785,335,242,331,759,690,585,564,374,392,56,684,928,913,501,25,879,111,574,161,246,482,262,145,661,937,175,110,126,184,895,667,764,93,868,533,133,166,485,503,168,448,651,738,491,84,118,980,598,291,14,960,521,849,984,930,623,891,916,340,646,844,633,217,395,213,219,825,656,255,138,844,502,939,260,953,87,742,97,532,829,451,631,577,951,959,255,0,852,654,988,722,437,98,881,954,366,958,448,123,908,81,799,183,792,697,500,719,878,658,299,605,13,352,458,324,722,937,286,913,932,782,36,969,528,803,65,649,489,119,561,533,813,697,439,480,679,685,291,965,184,804,132,348,325,5,763,366,952,197,407,100,846,950,169,145,517,671,464,118,755,350,58,541,979,502,800,925,922,591,82,181,540,211,92,793,657,288,263,855,530,793,386,467,658,188,263,48,60,540,881,823,929,919,579,684,699,66,869,645,411,991,99,236,327,251,508,384,126,498,992,598,120,743,290,840,548,14,664,928,643,716,438,912,900,157,54,711,166,897,397,756,805,899,84,73,374,36,761,501,84,817,280,578,984,458,682,93,280,490,644,154,45,569,449,563,83,250,743,525,763,334,212,18,677,560,904,246,846,406,719,416,360,807,620,769,998,385,725,493,207,648,735,806,262,601,780,904,767,193,200,288,101,364,730,825,444,367,634,187,157,324,947,2,506,127,89,964,985,266,429,868,804,518,64,328,9,635,257,17,936,526,954,698,313,385,537,749,419,662,326,121,771,509,178,490,737,52,261,689,953,31,666,825,85,264,726,290,500,807,609,749,334,459,295,884,170,523,790,844,882,886,782,304,154,740,118,420,284,204,559,582,202,92,533,410,639,905,291,17,165,421,641,896,891,408,418,3,731,418,91,540,981,489,815,631,463,403,974,83,24,798,150,376,945,146,514,112,251,629,208,59,35,670,798,930,857,620,949,24,219,267,78,64,554,179,996,832,770,421,882,393,932,386,767,227,378,634,555,969,298,65,54,849,512,34,443,728,217,647,60,18,121,164,911,84,513,768,439,337,183,919,434,630,925,837,199,555,834,618,23,663,337,967,645,243,533,912,359,281,961,285,71,116,210,636,754,793,641,202,711,168,766,823,510,111,701,654,603,390,591,642,764,266,128,393,720,290,703,96,768,69,227,940,131,744,511,857,209,308,901,105,229,497,280,89,778,916,47,337,744,424,759,927,776,709,996,375,222,872,591,67,986,24,888,707,966,705,330,275,829,738,29,332,797,167,80,548,139,965,403,898,496,35,934,257,312,109,340,173,500,420,481,66,892,886,841,217,32,940,596,545,98,367,637,132,419,287,421,612,713,530,585,881,436,498,789,533,104,291,343,981,309,659,20,231,624,112,323,467,279,214,901,138,647,323,219,956,16,919,874,444,442,608,862,679,763,512,599,125,209,808,327,358,484,221,450,902,487,191,493,351,561,754,421,798,345,712,722,111,67,664,640,452,288,853,992,676,952,398,585,728,660,530,163,672,890,583,954,511,711,603,412,876,820,141,790,326,122,516,405,248,716,767,116,359,431,761,411,770,708,668,725,676,351,206,501,787,766,745,648,190,471,887,919,585,713,656,283,971,800,448,547,668,182,534,338,231,269,578,44,90,12,320,347,548,619,18,454,787,264,877,476,606,139,44,881,825,896,633,243,251,289,984,846,863,473,990,165,840,937,860,684,928,935,25,282,202,972,59,450,419,309,673,685,622,845,227,443,369,578,956,760,472,125,381,698,515,331,736,73,126,1,370,942,910,26,413,60,361,820,498,600,608,595,873,806,879,594,497,724,57,776,835,245,843,997,254,171,372,505,74,474,867,530,213,592,941,130,924,519,893,746,473,407,331,485,627,636,829,271,888,650,466,291,61,90,254,475,450,421,157,40,406,197,787,124,642,577,666,73,575,679,231,723,221,620,976,788,170,603,300,235,594,603,883,708,361,357,783,985,531,804,652,954,773,298,546,278,307,723,159,332,411,143,115,588,537,673,942,291,944", + "381,968,918,412,366,961,535,658,812,578,691,772,119,724,855,49,622,677,587,835,376,582,223,62,727,392,131,705,504,221,491,452,555,404,418,133,824,251,106,656,347,639,576,821,923,627,197,310,88,719,650,104,14,757,730,211,641,805,208,6,504,765,904,612,607,322,850,110,664,32,82,961,415,35,493,705,616,308,507,898,395,460,374,959,873,123,487,963,881,987,897,343,939,822,881,969,437,425,18,423,437,324,785,751,867,618,146,209,802,421,934,775,597,161,672,366,318,694,468,55,604,609,905,910,181,733,89,419,88,574,587,212,754,636,246,151,262,920,649,496,712,252,785,205,850,268,986,263,719,965,32,79,220,877,19,258,355,123,719,118,72,288,640,611,831,269,586,831,362,735,276,540,935,702,949,922,326,61,744,944,609,455,34,543,996,185,495,5,650,374,227,190,324,886,610,852,0,614,537,417,146,915,864,435,269,742,489,323,986,529,498,985,216,566,743,727,416,608,289,897,889,90,858,134,190,924,824,894,528,251,637,171,154,358,348,366,432,585,691,693,540,100,79,335,660,439,755,828,485,883,647,457,992,762,334,598,565,546,988,392,245,621,157,316,296,900,915,241,46,520,215,89,525,321,503,806,906,437,800,347,751,797,44,143,302,479,43,953,819,713,267,342,892,91,757,934,393,600,716,203,793,298,416,280,196,822,513,131,846,482,435,813,212,640,85,540,625,462,278,354,707,311,201,675,137,540,121,682,107,966,163,678,902,782,874,522,54,313,119,380,517,973,547,138,130,479,829,271,686,693,944,979,75,306,728,901,826,523,988,92,660,214,902,245,192,922,665,32,799,516,519,848,32,72,583,652,410,330,571,998,795,620,340,9,54,933,178,90,117,615,491,748,947,182,790,741,751,527,817,578,491,952,38,170,102,486,76,733,570,135,261,452,734,902,987,421,453,115,84,514,738,609,443,594,922,717,427,403,170,210,815,79,35,246,917,191,136,609,845,358,386,125,60,838,593,934,5,819,542,405,940,881,111,699,921,774,432,97,992,93,841,540,277,422,228,24,667,109,426,198,218,194,349,101,200,670,911,60,652,673,761,885,831,139,125,278,231,904,699,861,917,803,717,805,558,745,957,741,730,322,318,416,340,758,726,109,876,725,455,834,664,555,227,688,920,82,194,836,730,514,915,278,972,733,347,396,356,678,319,33,227,532,955,107,295,760,73,374,461,118,220,577,908,905,105,193,678,19,415,777,81,15,584,481,933,641,497,962,497,862,784,610,41,164,234,50,737,981,391,365,788,103,88,455,136,796,784,196,753,910,1000,566,81,723,280,212,691,216,65,385,137,970,48,429,942,60,951,961,341,581,84,266,417,617,273,572,962,267,94,687,529,342,538,687,574,459,428,437,380,610,628,457,487,542,10,107,552,932,367,939,203,11,140,949,658,517,541,954,679,703,412,254,711,317,583,530,704,501,635,822,148,969,172,815,592,754,699,119,239,47,33,514,259,25,822,873,861,695,686,863,174,854,869,643,995,974,829,803,613,391,941,345,279,536,986,775,7,756,790,474,580,443,715,370,960,116,64,779,330,336,334,89,987,453,579,908,715,790,559,280,31,206,462,232,368,868,844,458,608,643,31,827,327,149,661,731,28,293,407,658,575,538,85,197,506,699,379,301,787,607,857,952,105,463,222,941,260,223,19,677,993,842,438,352,347,849,497,171,512,695,427,541,54,893,448,365,658,338,766,890,478,437,782,728,450,424,324,278,204,119,642,315,67,482,667,546,214,94,916,801,831,446,412,290,638,887,866,509,642,426,348,254,773,540,211,789,847,247,546,964,974,565,621,331,936,433,601,514,56,157,851,680,700,920,535,313,699,87,718,888,779,944,761,397,562,711,778,507,297,455,217,819,929,767,818,708,248,664,598,90,721,845,116,314,995,866,956,24,818,625,696,249,960,158,358,905,564,67,54,323,745,310,141,696,243,953,992,540,820,143,148,942,198,482,5,256,513,881,556,333,298,675,576,961,861,607,219,716,302,690,854,973,514,814,700,48,456,257,370,938,852,20,803,820,33,426,176,710,883,755,984,290,963,541,650,429,210,897,255,421,169,531,974,356,773,73,36,120,383,62,244,929,161,313,901,348,923,765,459,200,980,757,695,9,295,166,80,585,882,370,736,522,633,319,993,125,830,40,112,388,70,901,835,447,380,469,581,508,692,157,148,445,257,161,436,459,684,536,467,577,903,837,421,979,500,864,31,885,973,757", + "720,17,689,789,235,606,784,97,165,338,848,557,263,381,148,631,135,76,370,867,730,319,189,171,668,433,299,647,562,351,433,648,335,736,993,183,215,49,996,607,834,232,928,351,794,863,514,381,141,414,211,989,996,944,585,78,381,421,46,235,946,712,468,550,576,14,814,14,843,759,106,165,753,551,584,434,578,622,929,855,421,910,630,223,253,802,991,389,575,470,991,547,2,45,541,389,435,654,676,473,995,547,185,816,368,258,190,328,32,520,957,180,945,550,865,786,614,183,136,597,741,136,101,736,598,58,114,210,112,233,331,796,70,89,581,111,219,834,697,800,807,169,245,790,801,854,158,961,941,50,83,903,518,48,701,567,304,892,188,617,247,662,451,226,588,627,389,765,133,173,50,79,518,996,793,791,901,805,329,421,986,273,466,779,263,631,480,335,961,60,597,386,847,542,623,654,614,0,450,296,852,392,13,790,893,12,236,290,447,569,755,869,996,202,385,536,309,597,173,525,653,178,292,719,110,703,981,722,482,965,113,923,269,471,431,390,932,836,668,232,119,294,647,13,985,785,299,603,531,500,840,614,8,717,110,488,143,730,446,291,172,558,601,872,794,240,594,160,179,782,329,865,336,215,59,728,847,957,847,751,341,370,755,343,557,599,798,792,661,775,847,723,684,491,274,771,179,545,307,942,95,632,91,965,604,149,86,634,252,221,491,892,343,453,143,148,175,753,72,570,988,396,557,677,700,148,426,401,85,921,176,210,162,869,741,225,386,663,331,337,99,759,603,878,885,885,321,417,116,101,768,661,843,119,669,352,748,135,837,568,40,429,527,650,212,393,159,968,917,108,986,909,520,213,615,745,890,707,672,697,918,943,332,951,808,831,946,589,768,71,153,185,251,398,992,616,484,247,947,954,906,796,796,29,243,268,983,500,50,704,36,300,234,237,716,112,477,408,481,163,400,958,447,205,382,192,86,99,256,631,721,857,491,664,594,496,208,570,539,214,959,549,646,648,979,33,112,280,273,568,481,265,452,59,891,667,389,951,889,137,130,656,66,210,178,400,94,513,670,326,898,590,791,618,70,496,562,440,39,790,457,983,226,731,697,186,345,634,264,421,217,207,257,696,38,90,897,109,396,970,771,215,929,180,620,66,258,551,771,347,941,79,752,846,9,616,567,903,371,409,85,382,701,331,504,375,359,614,891,887,115,721,279,623,874,839,628,901,817,546,718,168,925,71,208,8,284,345,709,931,627,195,188,97,823,495,143,459,249,216,5,979,942,472,493,971,157,483,30,542,140,656,26,491,443,627,840,912,652,630,674,674,724,363,415,825,953,757,444,959,691,656,881,546,860,293,236,980,923,534,649,135,770,872,775,98,819,105,432,547,600,228,479,25,41,735,724,507,860,894,611,322,929,69,426,230,411,12,739,171,989,893,900,176,975,854,972,44,602,528,396,33,152,38,580,714,243,920,345,846,819,45,325,85,368,241,705,349,682,649,560,17,466,857,861,190,44,662,148,468,225,280,426,568,813,771,34,404,469,524,408,212,451,472,131,77,262,447,905,532,475,144,821,998,658,132,961,715,966,851,678,683,116,157,459,671,479,736,636,940,176,897,727,944,570,499,686,982,165,320,957,963,266,576,382,830,927,48,244,293,269,16,796,66,340,749,485,567,648,758,170,191,232,938,323,208,631,750,295,371,190,934,786,365,882,158,525,697,760,742,199,732,255,507,585,214,894,818,46,697,212,430,334,155,742,935,154,128,685,271,797,155,364,979,641,289,879,452,647,285,161,376,273,770,677,933,789,804,226,208,749,273,393,924,218,508,891,298,181,369,714,410,243,801,105,219,534,963,110,440,787,937,219,591,869,843,777,495,961,888,438,855,917,884,138,586,334,572,579,244,695,518,478,654,171,341,605,736,479,19,962,881,460,91,20,649,695,604,166,167,368,389,868,603,110,113,927,870,794,536,314,313,676,88,407,217,292,711,326,814,915,815,244,518,815,534,627,977,687,278,37,662,151,364,699,703,622,469,465,758,813,760,588,381,7,890,781,366,567,855,809,348,966,250,764,382,96,27,503,649,632,36,793,847,669,479,614,3,431,889,678,769,899,130,828,741,189,930,111,575,925,210,987,216,751,253,234,867,439,572,351,619,101,961,828,871,27,321,607,417,658,934,981,504,394,263,554,718,896,67,722,966,315,365,565,184,291,303,750,407,551,57,826,662,669,133,402,632,300,666,49,231,14,616,439,42,507,736,771,127", + "166,632,104,988,90,170,930,210,634,938,873,269,7,143,235,639,585,534,105,440,732,536,662,504,367,678,776,484,168,194,776,304,474,279,309,321,248,769,347,300,892,418,454,558,828,816,765,901,825,481,89,25,23,127,972,912,570,374,606,726,428,348,427,802,349,383,174,691,868,516,297,774,528,759,608,140,487,104,55,984,229,310,321,821,827,70,248,800,150,647,500,380,947,176,597,178,824,256,629,199,724,687,803,885,209,315,392,742,184,693,253,161,948,708,598,831,410,46,905,717,633,618,698,420,379,27,629,787,836,865,814,457,779,515,642,653,110,855,143,75,76,546,261,966,748,266,798,738,103,757,355,662,602,203,299,556,790,326,764,644,121,527,124,868,420,145,112,218,50,482,788,953,948,636,659,339,414,213,649,79,413,396,693,920,755,448,826,476,811,904,297,432,137,142,78,988,537,450,0,788,577,789,894,950,944,738,32,866,979,815,416,87,982,435,714,953,344,31,765,959,770,720,636,773,318,826,483,393,731,518,137,377,792,996,553,424,613,751,229,548,337,589,784,505,252,702,28,53,405,420,325,545,792,681,965,502,602,969,489,739,965,575,588,644,441,993,593,647,534,247,551,148,584,462,808,663,276,486,77,859,991,560,36,869,199,79,666,45,865,293,53,139,372,194,117,904,471,603,63,109,694,317,437,614,177,722,356,31,480,390,217,440,682,114,882,438,380,626,479,772,785,106,73,571,449,995,653,472,810,9,761,923,498,263,753,824,604,597,556,45,647,893,718,718,598,139,486,959,889,852,473,531,198,822,788,370,224,136,461,799,251,928,9,120,57,2,272,73,701,41,477,696,743,726,392,120,388,421,91,634,108,850,36,42,409,330,915,843,317,778,591,282,926,373,374,458,571,411,314,182,874,450,459,401,225,495,603,310,895,627,204,239,18,13,567,661,908,175,123,543,776,83,203,550,697,392,313,816,327,422,69,526,200,443,383,265,166,140,73,669,420,723,941,962,83,740,42,910,394,280,606,504,568,761,863,321,324,887,871,189,471,876,501,928,182,778,21,414,187,151,163,73,964,449,254,121,825,899,254,845,689,769,775,445,3,92,403,20,493,28,177,94,741,860,722,147,160,410,580,720,735,806,319,798,297,49,778,876,588,745,247,83,189,585,12,590,540,368,449,940,187,523,612,401,498,834,423,594,886,529,793,818,293,440,532,734,660,778,469,931,724,200,950,588,436,465,545,163,184,690,488,100,108,530,899,227,886,896,474,882,854,192,255,58,130,147,631,485,960,493,498,796,25,126,418,910,453,540,776,393,416,738,106,100,745,999,42,882,4,874,607,831,576,91,598,797,693,854,59,497,112,397,415,481,825,210,677,269,322,57,433,707,402,510,781,755,694,700,466,414,731,712,224,156,975,941,511,758,451,306,801,997,478,732,189,472,835,531,536,788,574,664,325,379,606,759,680,897,939,397,735,652,139,831,354,675,768,857,707,43,937,712,972,371,502,97,138,888,755,117,304,800,603,447,232,43,72,607,35,284,993,429,520,571,165,934,636,899,417,890,960,727,664,810,660,566,633,826,729,491,581,834,843,887,874,212,880,718,193,144,432,896,377,299,197,98,804,891,560,540,832,465,358,659,247,436,338,430,750,803,854,753,423,636,661,677,677,945,848,242,908,326,199,10,469,464,387,728,498,744,453,42,325,514,41,87,143,917,329,830,731,527,416,642,8,641,843,362,732,794,93,384,304,79,823,728,831,598,48,500,356,683,37,998,578,313,959,284,179,972,703,356,778,249,68,915,259,250,363,570,48,493,88,92,900,593,35,416,410,182,756,387,968,166,483,224,636,40,943,522,676,830,271,678,137,174,111,712,255,68,481,371,639,969,278,426,241,740,486,87,972,720,940,567,498,425,949,253,546,694,991,646,389,508,812,387,807,797,512,41,440,245,615,894,606,591,15,535,837,255,721,565,139,90,241,141,948,128,57,245,774,18,352,569,27,804,669,443,376,34,35,500,345,836,274,462,777,864,565,152,414,418,557,38,217,471,713,789,365,265,553,484,198,739,125,925,777,475,888,506,706,384,450,855,996,345,52,451,742,146,529,253,795,248,451,79,557,441,140,497,622,249,427,455,853,130,464,960,493,958,920,151,456,868,326,69,931,472,827,214,298,950,297,866,726,81,39,551,756,35,746,394,713,504,400,530,208,871,280,206,940,209,581,674,14,863,770,125,472,621,105,526,320,830,298,568,173,304,386,67", + "208,471,967,80,514,962,214,591,688,996,689,374,105,143,378,959,695,959,14,485,290,912,310,950,900,824,783,289,815,91,630,701,234,931,190,573,630,381,652,996,499,656,107,85,343,542,525,980,321,903,255,822,234,541,732,539,452,385,399,376,707,756,141,240,254,904,379,849,296,870,706,813,426,17,766,340,461,743,669,946,601,969,568,381,493,675,734,952,843,141,95,621,942,431,7,290,545,486,595,714,848,589,331,887,78,294,244,844,813,49,430,385,98,763,569,209,980,395,389,961,982,970,96,7,927,854,494,753,883,149,365,336,713,356,219,603,143,125,58,692,617,188,495,250,411,749,649,443,432,113,42,751,656,245,804,45,630,936,429,236,423,426,382,20,613,256,326,519,341,811,441,285,253,963,849,39,239,250,482,399,746,95,562,983,459,31,275,642,926,401,114,528,484,240,329,722,417,296,788,0,360,55,873,613,163,82,374,55,176,315,436,579,87,745,476,924,42,359,140,4,352,891,13,406,89,721,187,863,705,122,66,470,775,94,150,919,266,159,622,102,617,131,61,936,994,376,895,868,264,641,865,815,421,80,255,743,895,207,932,46,929,47,153,226,642,483,245,813,928,506,582,957,199,66,502,859,147,98,728,968,33,920,655,300,680,853,328,940,282,346,393,72,946,326,516,75,154,178,669,376,748,283,185,460,286,524,314,181,904,546,911,595,640,853,825,209,161,277,316,89,860,826,697,566,794,554,426,830,135,628,641,345,129,418,846,99,165,646,815,884,501,436,676,13,948,48,551,99,315,90,30,839,653,420,646,19,846,61,65,165,687,922,612,836,723,828,768,686,579,824,732,98,806,801,615,241,405,761,160,925,679,25,225,184,956,372,59,158,273,732,103,754,43,79,830,90,248,527,875,849,485,152,13,730,515,516,840,561,271,430,499,771,467,818,457,439,750,104,184,291,79,442,431,421,59,669,686,224,221,795,336,634,641,698,51,769,887,946,774,880,330,646,214,128,300,207,437,870,483,260,958,519,983,656,223,221,2,539,436,370,725,767,553,373,190,214,672,504,104,119,774,941,182,305,611,280,471,305,540,755,28,701,62,212,178,637,632,214,815,221,459,604,417,676,861,706,630,133,986,563,521,855,249,380,767,271,996,654,538,379,286,62,492,825,966,583,108,813,259,860,546,753,144,227,610,574,954,650,380,306,166,141,817,416,235,98,755,724,100,897,997,531,537,529,699,948,601,604,804,242,526,666,888,472,796,969,474,76,604,672,892,349,141,748,598,728,115,136,257,517,215,354,450,542,191,517,182,209,736,683,721,199,577,160,59,164,193,276,541,21,936,695,528,897,185,441,669,915,925,256,850,721,164,633,5,770,46,880,795,888,107,616,227,451,16,448,294,247,908,413,722,52,576,354,894,776,640,201,332,552,994,850,415,750,663,871,12,170,103,658,104,420,686,825,952,772,544,406,631,221,113,700,588,106,959,213,23,827,369,19,559,310,793,64,628,77,802,236,757,217,278,603,180,277,34,281,209,950,78,498,841,294,805,298,601,564,333,692,217,827,965,741,227,502,889,147,545,994,139,37,666,170,577,89,250,29,677,209,425,545,854,394,236,544,447,270,805,901,655,292,581,73,932,112,362,25,784,647,854,716,780,8,446,75,37,865,532,818,473,279,510,422,512,198,227,485,243,668,491,996,306,331,240,672,754,973,350,271,350,335,724,323,566,200,353,657,14,444,696,434,392,294,534,135,443,64,642,384,116,153,954,808,16,817,959,645,701,657,29,623,313,576,479,273,675,424,378,365,90,120,754,80,624,47,986,509,296,330,289,754,124,77,680,321,624,697,97,72,324,318,488,388,403,222,960,895,657,247,785,970,804,219,230,714,741,9,132,427,199,205,598,861,837,560,686,562,985,899,545,954,422,838,8,297,127,463,78,740,953,282,609,643,406,703,518,931,190,818,617,637,709,148,640,613,131,470,427,330,739,143,77,209,994,20,132,480,48,865,666,120,974,275,813,294,725,57,357,727,542,248,792,922,865,256,34,948,866,913,484,367,940,916,861,656,19,893,633,199,39,888,683,350,933,925,400,201,282,731,47,588,241,909,333,807,603,124,165,802,634,6,987,559,480,444,304,119,422,216,756,380,377,155,619,305,168,79,505,913,369,159,883,620,743,261,581,155,112,496,65,221,608,1000,639,970,767,553,953,901,332,636,712,760,396,290,838,256,498,239,156,286,389,471,249,765,451,222,483,438,561,48", + "178,639,837,886,739,72,210,875,682,663,547,38,905,498,944,939,691,726,935,352,88,419,670,750,215,238,783,555,471,375,574,798,409,757,382,301,949,678,43,520,342,991,106,74,141,764,665,350,789,234,786,584,269,288,232,640,852,29,671,32,711,299,16,121,923,173,627,588,992,816,751,416,127,547,635,213,613,938,117,20,646,484,928,649,227,497,751,939,102,985,840,574,654,717,124,756,76,682,593,51,734,990,781,312,966,563,549,912,900,188,391,960,261,361,827,71,391,244,281,786,691,904,402,802,12,781,927,609,128,330,607,772,545,641,718,8,562,271,540,794,581,702,85,529,410,837,540,814,886,836,200,232,740,77,25,716,679,251,195,876,211,923,199,949,406,638,358,570,346,370,277,552,683,75,760,323,985,364,596,506,32,178,920,91,175,489,463,373,795,587,869,664,150,469,197,437,146,852,577,360,0,661,950,862,414,559,859,161,219,401,377,569,233,315,459,834,494,137,404,365,768,154,629,496,538,207,504,494,271,67,608,26,895,539,110,738,57,41,803,652,250,717,930,214,348,338,341,238,78,217,561,116,331,589,850,9,683,941,965,527,446,800,874,140,297,287,59,969,988,506,692,199,128,859,992,212,923,618,125,754,511,577,836,300,195,169,75,108,914,821,692,479,522,502,594,252,432,13,653,510,641,530,610,87,372,597,742,373,66,911,440,383,434,147,698,799,614,899,728,444,602,98,949,650,661,830,45,441,983,324,177,325,764,106,787,431,463,390,835,478,668,895,146,51,147,872,954,492,172,179,562,304,501,845,456,643,941,53,135,423,181,974,766,110,568,332,663,487,999,385,356,887,572,332,635,874,667,988,493,406,886,346,706,44,727,477,631,453,558,643,781,991,230,657,240,732,854,343,580,595,438,636,614,63,68,963,329,45,968,92,288,487,660,413,647,699,342,228,429,214,338,149,184,399,933,403,436,377,523,542,836,604,618,387,751,86,291,140,853,979,587,783,158,160,157,613,294,752,722,46,134,862,846,686,648,942,542,574,788,880,169,89,351,306,402,217,448,497,767,255,48,741,349,839,805,34,390,862,585,481,825,703,779,19,477,507,522,470,528,663,734,562,422,151,85,479,997,193,999,226,38,106,120,420,37,508,984,877,475,977,774,196,856,916,616,897,14,952,788,360,105,803,897,463,470,240,520,592,606,282,429,663,176,202,44,286,539,394,753,178,127,356,580,547,855,593,837,921,328,769,925,323,828,691,104,336,115,247,519,148,804,946,841,864,886,920,627,699,294,768,323,194,383,498,185,575,225,545,765,705,716,516,703,790,139,309,854,577,985,309,664,747,97,338,334,871,915,869,221,536,399,416,366,23,238,665,464,182,622,769,438,412,273,881,248,130,263,559,884,319,943,604,217,412,294,798,495,428,226,872,198,144,216,713,518,130,838,4,558,4,434,775,800,533,936,750,516,630,124,742,676,404,413,978,201,227,557,209,607,699,311,548,940,377,470,240,554,255,948,350,632,139,709,339,179,268,525,395,40,311,621,911,604,565,968,489,799,347,994,230,285,382,635,881,853,348,314,748,68,531,824,835,187,159,336,37,783,761,954,967,554,601,794,815,864,84,203,467,511,770,257,87,493,306,436,455,584,965,867,993,904,630,892,642,448,892,155,705,151,360,293,808,398,558,457,655,324,583,612,453,636,348,278,617,985,811,283,994,208,71,999,278,28,301,550,937,132,860,782,328,141,616,753,693,728,467,590,111,313,113,810,574,343,753,47,178,906,450,116,123,568,668,630,485,868,813,248,568,857,416,565,783,111,615,652,167,541,907,879,247,86,554,995,859,803,664,692,897,116,405,948,254,980,684,336,557,364,713,670,670,867,595,887,402,423,921,296,731,295,784,77,907,369,845,880,837,676,961,79,416,652,606,324,413,732,992,359,522,457,979,960,790,177,348,227,308,591,875,494,335,943,488,772,804,539,505,765,671,894,372,211,19,980,273,798,534,604,5,678,916,133,791,130,493,229,948,352,838,724,77,785,253,10,571,980,823,854,853,20,663,221,932,479,192,45,817,319,350,897,780,137,53,543,269,543,702,946,584,238,131,661,313,542,541,253,166,81,586,509,515,874,116,318,710,459,136,812,324,532,753,599,14,7,630,538,292,549,389,656,164,788,249,590,214,939,754,12,776,656,909,648,866,335,697,234,577,691,328,679,469,919,162,31,997,882,341,931,981,858,880,488,24,157,173,903,175,215,492,792,216", + "634,273,653,457,357,777,51,959,306,465,480,735,122,710,1,628,642,319,1,407,866,73,459,577,240,91,307,867,841,228,287,610,339,677,445,709,831,640,378,831,628,99,424,195,429,504,134,10,272,983,500,219,328,420,115,857,308,244,864,470,612,758,995,314,947,889,401,917,648,571,44,301,636,437,457,973,30,813,114,214,267,963,438,233,404,409,694,515,544,609,886,304,329,314,839,641,385,277,250,998,387,996,535,107,307,4,459,840,286,972,211,708,468,616,84,739,635,766,507,545,968,792,359,145,577,532,823,681,709,257,110,678,723,587,519,255,814,439,150,347,947,505,391,893,388,302,132,234,724,76,538,736,594,973,475,98,227,706,421,400,677,185,886,910,157,990,943,316,470,538,215,834,608,131,444,829,355,123,249,216,18,835,490,859,987,497,685,556,629,877,367,914,320,722,729,98,915,392,789,55,661,0,973,386,208,432,20,809,860,287,431,921,941,842,689,956,69,856,373,968,131,174,179,160,340,966,636,592,28,410,150,580,40,109,130,181,844,1,46,617,379,212,862,29,42,823,553,399,452,567,797,950,797,832,352,393,745,230,830,866,759,472,470,53,643,454,166,833,701,318,928,617,996,615,624,739,214,403,559,892,817,27,65,301,423,70,173,416,793,5,576,225,17,881,721,644,616,77,434,290,643,944,769,152,448,243,744,292,440,774,545,105,406,205,685,709,148,157,755,682,268,238,268,377,845,202,99,852,900,94,792,400,395,481,10,916,650,578,656,427,707,809,6,100,844,126,747,517,527,76,751,477,301,925,262,772,941,158,542,602,117,715,199,654,56,172,379,120,346,857,348,466,572,123,722,3,152,126,472,466,419,649,503,846,417,540,431,237,347,434,209,55,364,620,342,925,577,558,161,542,143,905,729,873,859,423,726,831,183,54,318,624,14,392,189,112,482,672,890,165,520,517,255,247,960,873,304,545,858,839,464,212,785,735,205,208,985,843,184,567,75,159,629,665,596,937,64,359,252,646,610,520,173,612,646,362,53,456,246,279,84,216,401,573,754,860,329,416,168,623,77,775,101,727,202,73,659,313,935,799,396,454,451,881,333,620,976,667,455,818,626,891,131,203,844,728,710,398,861,577,181,798,852,369,644,888,805,575,398,523,310,464,420,349,577,732,896,168,212,450,91,547,776,977,543,287,583,435,246,880,464,993,83,966,975,350,327,197,945,820,146,263,634,794,418,345,603,529,884,605,478,763,337,100,273,108,989,691,222,920,488,434,280,246,832,867,475,745,480,709,579,57,937,668,567,268,680,131,482,487,278,639,62,187,852,829,490,956,859,253,843,524,949,74,414,914,818,707,870,441,506,777,113,192,798,641,510,544,528,886,136,773,558,284,480,460,620,721,146,219,360,647,957,754,906,99,311,990,995,967,582,462,131,550,118,361,731,780,725,370,34,221,840,457,714,80,769,5,811,319,223,388,428,589,602,813,566,104,155,262,24,948,196,696,293,406,379,451,291,400,598,830,137,719,676,314,184,127,867,823,293,528,749,451,442,141,840,50,741,72,590,970,322,402,565,223,59,795,238,587,809,721,549,835,6,132,866,337,823,929,967,685,369,808,14,362,894,836,551,976,183,671,159,321,981,699,685,475,308,611,657,717,647,276,729,229,986,268,123,652,783,846,569,710,420,845,371,298,735,667,217,500,986,433,338,602,73,969,954,231,444,304,141,439,390,212,272,952,779,539,482,350,837,392,244,182,610,155,189,232,409,186,273,292,611,578,336,841,252,550,291,963,806,221,341,641,798,70,121,697,623,525,281,888,447,345,26,976,815,677,79,185,578,478,9,213,33,679,512,488,723,708,809,538,640,539,704,241,344,471,755,680,765,591,551,78,427,559,883,894,289,617,643,400,663,51,808,392,501,193,347,117,981,457,813,792,593,19,987,785,505,645,105,895,159,776,737,712,706,919,786,395,747,540,702,771,315,101,357,512,420,52,190,341,445,946,352,709,508,346,408,415,235,341,340,287,840,784,664,246,44,720,707,490,284,311,610,307,372,480,338,238,194,424,522,390,539,435,155,966,360,643,817,865,748,35,768,749,355,227,133,85,462,14,40,674,664,684,921,78,339,817,149,556,705,657,385,225,676,166,401,625,895,457,572,578,227,553,645,137,847,173,38,683,374,930,299,52,487,138,683,862,137,332,718,519,735,448,641,252,429,329,574,194,304,240,668,98,463,813,233,392,103,882,883,279,203,602,270,361", + "557,142,656,333,806,127,932,158,567,603,769,954,454,458,554,169,220,11,695,319,181,73,242,281,561,982,225,940,151,424,447,89,81,95,750,258,315,927,825,400,922,735,160,682,953,221,514,368,838,665,858,629,994,479,996,372,752,420,233,633,85,110,878,682,590,443,552,350,104,915,500,538,170,346,436,748,679,874,217,704,163,339,15,998,637,285,756,864,154,644,142,472,542,276,197,976,444,134,522,635,209,501,336,377,561,441,275,125,295,683,210,810,708,966,753,916,911,806,713,521,410,80,730,788,718,994,314,691,699,659,80,620,381,831,596,417,290,546,403,864,631,497,133,679,695,925,806,556,929,324,527,422,222,840,586,922,728,989,930,200,578,27,612,190,750,297,107,762,304,724,288,662,231,666,78,548,58,756,296,259,925,436,707,615,144,602,977,958,425,814,709,369,951,959,83,881,864,13,894,873,950,973,0,385,396,95,847,119,938,339,315,893,101,117,107,512,914,910,597,842,787,396,164,169,712,150,373,106,636,305,94,11,478,191,694,262,6,94,578,831,942,270,678,736,849,419,387,662,582,585,371,963,144,570,147,847,614,312,567,258,856,908,706,711,124,787,163,790,166,806,454,93,300,222,557,40,341,872,879,733,939,927,233,634,851,438,212,988,406,516,205,816,743,619,613,156,330,37,506,660,212,661,970,902,87,680,690,482,955,588,918,444,863,315,925,75,157,195,978,286,186,771,650,79,324,713,857,792,348,449,814,909,905,207,287,701,275,612,21,592,718,440,771,711,953,78,883,564,840,56,764,303,418,505,59,206,867,980,591,146,50,428,406,768,363,900,481,989,491,415,21,746,5,106,876,20,479,301,626,352,439,871,235,484,243,318,496,727,346,622,586,803,95,984,286,307,414,701,691,286,425,218,383,346,852,375,589,390,239,744,336,212,368,121,103,584,819,713,653,970,177,669,910,151,681,798,279,23,480,815,483,951,948,545,490,255,862,89,920,436,570,572,623,691,50,260,504,512,205,644,155,834,415,279,908,806,377,244,935,823,709,759,128,908,844,548,313,357,70,6,965,854,562,20,949,570,793,417,569,749,905,106,50,107,841,107,764,847,458,263,479,283,100,346,754,792,650,499,300,446,318,224,771,925,171,380,71,626,41,772,670,946,917,387,247,330,781,446,828,434,866,474,72,690,8,763,917,328,422,122,773,820,704,768,546,851,631,212,130,581,637,73,73,646,106,925,926,795,958,277,977,235,146,722,282,900,442,782,713,612,603,704,595,421,978,347,316,654,381,807,262,390,436,796,691,392,961,653,73,837,416,83,289,481,191,627,487,524,522,549,749,821,118,668,227,296,494,224,701,80,70,618,633,839,952,703,30,57,322,209,791,11,130,199,150,299,505,519,492,80,466,858,719,784,639,818,258,180,733,33,119,522,626,554,5,897,688,145,941,959,443,825,658,345,287,189,93,105,718,190,498,936,951,555,406,677,483,303,328,967,680,243,179,492,775,577,673,562,594,979,816,558,167,945,297,102,463,969,163,508,132,531,349,87,83,976,410,457,441,44,633,86,19,664,211,43,284,937,883,18,549,793,608,878,114,133,931,261,386,946,465,287,375,344,61,377,234,639,30,289,179,532,411,586,808,677,147,200,445,118,897,461,629,256,533,199,411,666,843,999,999,450,635,198,554,256,660,398,884,136,264,474,106,364,276,226,793,600,885,538,783,458,195,95,937,503,872,210,944,968,810,195,378,520,820,717,258,908,59,403,41,460,6,48,894,996,631,247,66,475,882,547,861,739,30,192,501,640,462,690,605,66,476,234,362,978,845,357,113,111,860,956,395,878,77,294,338,31,735,941,621,406,710,132,892,886,747,10,882,558,757,531,252,504,189,504,163,527,396,732,143,109,674,417,641,167,952,421,336,679,7,74,597,43,713,923,596,619,846,49,675,770,568,456,465,530,757,110,753,682,441,671,289,846,862,164,922,910,719,587,965,990,714,500,758,951,933,256,28,313,334,600,765,568,710,110,667,135,541,178,798,477,346,69,529,233,543,533,494,241,111,928,328,758,670,334,584,909,459,658,503,719,438,992,819,279,915,395,956,244,305,749,305,628,495,294,347,867,891,298,433,779,130,828,907,898,534,25,577,102,812,902,126,388,845,513,243,249,611,238,410,447,706,988,250,209,158,386,640,224,755,407,294,16,199,610,371,65,933,514,161,525,427,174,966,6,791,542,739,394,496,637,690,871,910,246,398,639,453,224", + "595,763,465,603,963,261,163,278,447,70,287,340,331,409,368,732,671,963,414,955,887,53,382,887,30,872,187,676,337,983,674,347,620,139,295,469,331,612,968,749,211,228,158,873,311,711,295,520,926,641,630,899,622,519,636,153,187,734,218,269,81,968,439,618,175,312,42,115,948,712,176,962,244,274,641,715,853,800,427,585,832,950,818,413,237,194,811,895,927,455,781,709,316,3,17,532,324,694,718,266,460,490,19,903,325,854,598,671,703,510,811,120,992,389,530,26,197,228,507,966,997,622,291,97,78,727,48,199,787,510,271,556,968,309,223,922,10,928,487,528,250,551,434,20,107,484,574,544,713,660,493,714,355,425,744,456,20,941,67,395,314,530,79,501,392,210,342,428,989,17,947,402,950,455,424,333,512,719,226,799,483,228,239,317,911,669,451,405,313,928,588,11,695,583,868,954,435,790,950,613,862,386,385,0,545,543,777,614,564,616,341,976,426,969,700,157,892,165,269,147,975,821,253,602,583,112,981,823,956,218,122,450,126,143,446,439,891,462,366,68,717,215,899,420,555,197,11,602,371,856,345,375,988,289,321,527,82,815,845,985,323,98,36,875,89,108,365,502,490,98,169,981,830,873,945,9,334,382,707,383,429,991,368,651,860,810,243,43,808,239,702,68,470,105,746,561,445,401,9,309,608,764,744,962,600,541,547,780,391,156,503,721,15,607,916,131,842,383,645,462,677,546,128,685,65,675,977,985,93,910,185,996,474,591,810,299,257,319,264,906,899,696,497,355,11,464,666,405,837,906,216,348,887,14,164,83,171,79,74,439,666,345,712,665,126,194,860,986,264,181,402,73,138,920,373,138,507,732,204,747,779,751,795,3,517,988,427,300,612,634,842,36,94,210,409,847,85,715,709,447,872,179,467,20,644,682,95,993,417,300,577,433,552,84,211,16,383,195,205,992,981,141,165,429,475,769,646,850,105,142,707,325,778,759,291,124,720,563,872,515,652,927,226,304,302,974,303,84,232,734,226,463,678,419,705,445,797,771,124,903,423,108,87,530,823,649,295,177,778,398,916,105,287,710,770,952,395,237,223,60,345,433,585,894,669,702,233,780,400,93,649,683,985,124,846,299,439,814,786,850,745,979,200,253,530,924,223,439,742,905,703,268,420,981,226,18,154,767,437,19,917,534,74,75,434,111,277,594,504,591,744,974,183,250,992,765,261,332,540,887,460,884,606,80,488,178,662,762,461,820,676,875,408,347,950,203,148,357,824,591,256,915,207,390,696,196,237,800,685,134,55,135,770,703,124,715,824,942,383,957,78,687,728,75,335,467,552,641,655,208,787,693,707,890,508,278,212,471,526,57,110,940,922,259,743,926,875,487,487,47,399,372,10,9,466,736,871,66,879,537,880,933,977,402,284,368,670,288,799,199,841,423,252,336,401,102,359,833,93,91,894,484,11,90,149,998,275,539,979,174,640,935,446,792,162,734,139,970,529,522,356,573,257,431,858,215,319,577,268,299,866,95,226,480,67,457,994,865,549,234,167,742,494,788,94,835,205,981,100,252,827,532,572,34,816,357,74,438,522,713,62,590,956,985,2,16,719,984,8,733,559,937,380,455,350,792,962,677,34,391,718,121,988,668,116,573,160,729,428,264,624,544,787,731,465,684,362,396,691,57,269,851,455,484,712,54,501,436,819,916,289,754,257,531,595,958,171,557,526,716,147,358,605,508,656,591,32,959,331,205,421,114,655,63,353,96,451,957,222,291,463,517,979,201,30,981,959,51,420,713,290,182,371,253,179,434,78,971,26,54,76,109,429,289,592,371,757,118,747,48,570,299,780,266,128,169,779,208,679,42,142,889,677,631,607,883,776,146,750,745,356,222,842,400,433,271,580,131,951,342,832,814,763,453,405,778,363,211,731,160,751,623,248,188,861,467,679,490,727,926,530,459,890,180,355,562,768,445,304,987,728,839,305,488,851,118,580,422,733,59,35,627,695,946,500,449,965,75,992,955,631,107,691,631,25,519,761,143,507,929,454,480,834,852,283,781,883,416,942,673,618,832,532,531,597,401,640,27,450,195,606,875,924,750,297,872,386,707,815,599,843,144,381,497,224,632,325,145,710,657,686,308,828,333,368,323,533,978,883,882,214,708,422,523,758,41,506,78,603,552,947,377,840,996,126,56,299,582,5,927,336,260,70,68,337,355,413,629,804,334,560,270,656,914,19,862,979,972,929,168,792,537,975,913,43,476,516,682,691,444", + "969,708,154,737,754,532,617,218,804,140,418,158,189,623,718,275,755,27,904,808,163,50,273,713,661,56,724,333,879,388,903,821,450,758,760,762,65,933,484,815,673,384,355,597,264,465,493,98,308,354,214,11,697,851,379,545,321,297,812,996,571,570,707,473,551,163,171,605,829,820,751,518,821,686,551,540,630,641,127,466,590,9,94,873,53,707,606,667,98,372,976,287,998,984,856,230,711,488,163,891,214,591,4,624,189,726,291,38,923,132,432,6,376,134,68,229,75,680,998,386,381,722,622,965,275,984,746,186,244,262,182,50,965,567,894,128,353,610,540,947,184,379,892,559,207,683,337,86,74,516,222,836,484,357,241,843,698,828,227,370,177,543,145,825,999,841,770,531,60,86,849,705,586,255,966,79,219,884,667,739,750,788,94,308,536,466,945,332,930,813,607,544,93,773,549,366,269,893,944,163,414,208,396,545,0,437,431,269,511,253,246,956,560,974,635,221,766,816,36,952,958,987,740,583,199,121,5,126,736,792,413,671,576,596,347,235,635,957,746,735,706,158,164,760,144,649,907,138,736,313,293,478,223,675,855,295,385,521,392,764,173,94,736,959,986,645,937,73,32,274,262,897,637,751,721,943,561,420,992,663,285,47,22,890,258,885,339,556,309,412,345,343,312,801,55,67,72,996,265,271,624,237,856,822,868,861,243,838,225,776,957,187,844,572,859,773,119,625,499,959,694,951,543,732,237,907,802,456,847,870,535,600,350,78,328,359,249,350,374,933,800,90,816,516,206,847,528,180,314,737,268,664,123,586,483,476,94,50,940,593,928,193,491,889,777,461,850,320,898,89,632,563,121,386,577,957,407,626,859,157,390,387,557,785,107,869,377,205,392,806,973,99,231,467,2,769,392,813,246,363,54,923,896,889,631,860,78,693,159,873,882,847,651,853,230,302,184,842,922,831,243,310,241,655,783,210,672,707,511,537,507,144,887,392,251,586,806,886,929,207,517,708,253,563,733,518,662,385,636,503,704,494,761,835,857,875,515,235,541,905,709,286,126,115,417,920,522,243,632,387,725,174,267,102,874,363,892,438,805,285,411,153,699,334,654,732,57,846,840,336,225,250,182,53,586,216,471,995,712,763,605,859,841,101,78,697,556,134,931,914,416,420,195,29,928,530,167,693,981,929,341,301,377,445,403,415,337,71,754,715,565,547,96,156,598,594,141,678,531,253,830,311,132,446,524,952,330,796,61,723,214,41,515,495,394,33,477,589,438,849,573,837,975,24,398,221,386,202,362,752,936,679,198,366,570,800,171,316,130,358,562,154,7,50,439,359,130,486,466,650,151,800,780,978,201,40,777,456,763,160,650,598,919,724,927,525,555,453,901,108,416,486,714,811,239,606,933,741,537,774,365,635,933,930,771,626,514,871,343,823,699,686,153,942,76,533,574,636,643,969,193,46,609,937,516,249,630,52,51,261,792,877,589,841,301,712,495,769,744,459,452,919,354,674,20,339,311,799,102,299,634,875,733,527,388,669,105,467,959,173,365,436,787,189,947,962,71,520,382,467,499,248,281,804,182,557,862,376,70,422,396,403,103,243,613,835,574,274,29,342,38,996,684,529,453,820,99,39,773,251,915,459,45,943,691,126,82,238,927,30,48,665,167,192,78,587,46,407,166,720,296,624,648,512,715,312,899,740,526,41,518,364,464,552,881,668,868,403,69,839,353,911,774,478,7,380,59,561,190,292,58,857,5,608,697,930,254,181,35,876,238,753,2,512,212,803,283,503,246,119,538,136,215,951,753,967,578,224,651,362,890,591,159,293,277,273,658,376,424,424,721,484,174,764,815,754,244,847,457,463,470,552,38,975,264,15,653,346,986,205,949,104,300,183,862,561,557,665,679,329,545,567,413,170,455,788,106,762,735,451,147,273,771,192,210,901,112,384,574,415,925,372,372,200,189,647,254,407,963,504,242,146,926,759,799,28,602,170,929,364,867,12,371,580,220,338,220,231,879,755,172,742,17,913,965,230,680,343,417,24,436,206,330,654,235,525,968,556,448,825,725,476,647,253,889,926,304,542,296,25,92,989,375,23,470,178,437,536,561,609,193,502,159,216,851,692,958,195,431,399,92,341,697,313,300,214,86,195,646,824,486,107,747,770,199,16,202,564,520,912,316,108,296,509,425,690,782,542,381,489,165,8,856,855,739,208,331,405,227,905,541,540,959,45,688,556,118,349,764,161,808,417,112,68,860,543,220,147,807,479", + "968,694,321,985,213,979,662,106,698,509,185,99,635,637,69,248,236,20,912,426,771,140,883,454,119,832,827,552,442,807,381,538,674,125,32,976,978,908,7,615,46,443,273,107,146,898,686,518,400,314,953,135,77,362,285,59,647,451,753,550,91,518,944,911,106,53,766,282,37,361,546,710,569,217,643,163,785,794,25,731,520,560,8,214,7,518,398,669,893,540,486,521,240,173,98,306,83,671,286,831,640,676,449,31,441,47,90,406,793,975,532,527,881,533,403,872,250,79,747,901,160,257,392,75,950,641,717,220,92,222,723,621,409,495,34,532,222,527,62,734,115,115,986,500,481,789,485,390,376,346,325,610,637,844,11,200,899,347,129,898,511,794,748,874,352,255,993,74,55,333,443,317,650,600,877,690,542,476,780,540,382,549,565,839,876,677,325,305,96,15,842,674,881,447,921,958,742,12,738,82,559,432,95,543,437,0,491,269,650,228,111,175,380,157,12,322,280,462,838,991,457,500,812,600,434,812,525,773,450,75,76,885,857,901,848,435,947,313,703,207,824,967,379,845,86,312,812,278,940,421,196,547,845,765,578,414,606,7,808,128,499,546,666,57,201,915,401,212,164,732,65,910,574,723,135,948,356,210,493,504,195,446,494,740,233,37,401,392,928,637,739,402,815,577,340,5,220,282,93,475,837,687,488,508,584,337,319,96,877,45,659,647,157,254,558,501,372,825,34,768,28,527,667,703,520,737,525,841,689,371,174,566,363,363,402,812,340,493,12,536,958,460,240,691,54,198,240,685,875,730,318,690,736,827,783,958,887,88,289,644,774,804,209,283,34,532,476,994,260,972,279,12,14,862,859,611,622,588,279,964,305,16,278,722,490,823,485,830,126,516,951,891,942,352,880,558,772,432,510,25,624,694,773,665,346,821,489,145,817,901,68,437,805,5,532,266,18,603,622,855,507,418,349,795,832,495,912,415,267,167,620,912,355,276,937,714,378,15,954,630,478,267,267,516,550,98,384,197,906,268,249,43,899,428,332,713,839,889,775,210,942,421,278,608,523,402,559,212,134,164,654,358,977,440,730,330,86,653,298,18,147,410,197,611,250,66,739,659,493,354,73,48,650,784,794,155,524,608,423,581,704,74,548,944,643,791,61,799,734,179,499,913,960,529,961,861,982,397,519,601,669,980,55,403,333,281,204,457,271,198,131,480,572,997,416,920,8,496,705,184,979,548,890,389,734,279,115,672,672,281,587,444,26,482,428,36,414,728,673,474,966,974,843,582,426,293,316,663,920,126,936,634,51,367,833,340,828,307,163,297,819,270,423,450,833,310,835,18,905,963,795,772,769,9,181,116,148,990,224,911,774,73,609,191,457,127,158,962,390,508,452,737,337,213,426,903,356,834,777,663,660,268,887,116,691,475,559,130,815,907,478,269,278,92,582,243,611,173,716,817,409,782,65,138,195,905,187,52,985,129,586,19,636,75,906,334,954,71,501,48,172,354,271,421,333,890,770,758,716,820,901,712,499,591,859,704,364,413,356,764,985,857,197,954,935,207,913,32,545,642,268,261,807,10,913,822,781,219,145,48,619,152,898,826,557,169,111,819,898,130,170,516,793,946,685,830,481,346,245,826,360,308,829,914,456,160,990,317,892,183,744,595,63,886,3,664,377,408,173,491,740,372,915,443,605,775,561,426,910,211,226,217,982,330,182,251,494,124,563,313,834,72,504,448,647,520,928,471,671,89,350,609,970,971,237,108,626,790,213,29,730,43,25,136,390,19,321,258,237,172,788,796,213,102,704,649,181,742,233,515,133,886,311,666,958,393,759,7,28,129,555,41,770,861,596,755,812,402,227,144,753,216,921,683,215,150,709,124,979,967,876,665,859,793,385,914,841,171,696,97,69,419,520,542,241,793,230,870,649,758,380,285,796,500,852,595,987,186,888,236,978,377,28,872,922,379,150,482,119,65,736,749,734,182,213,937,91,324,939,966,893,83,346,732,513,914,597,810,487,932,245,5,608,204,965,902,100,401,308,982,685,798,398,565,733,15,584,425,279,324,859,619,469,598,149,141,96,493,553,481,901,858,676,593,510,888,520,10,957,943,560,589,389,590,820,188,828,353,528,359,707,346,316,799,624,166,152,232,240,702,251,473,736,704,566,636,240,402,769,784,567,98,445,286,799,76,532,898,127,461,950,981,134,869,457,586,422,172,637,823,663,788,389,954,289,466,508,879,768,755,848,844,796,9,291,955,68,672,808,733", + "384,395,722,546,427,344,588,749,943,83,62,414,672,56,96,427,832,694,820,552,574,490,412,760,906,729,310,727,650,279,747,182,217,471,915,309,568,489,720,93,837,668,835,172,938,568,731,761,825,461,471,564,134,735,278,71,721,422,765,587,818,504,721,395,509,129,664,137,15,2,452,545,557,911,164,874,908,530,589,443,609,829,526,656,478,490,925,559,92,148,666,380,48,449,256,547,292,677,571,237,339,294,567,480,37,802,717,328,517,184,284,268,90,535,940,236,177,380,944,996,85,906,783,559,983,953,843,466,41,203,845,883,564,298,398,903,619,963,816,35,95,224,384,13,276,987,951,40,732,239,560,77,66,100,6,856,214,384,52,467,486,647,999,366,23,42,679,877,924,116,643,563,16,753,47,366,159,820,713,260,760,655,245,491,58,276,727,433,875,229,222,34,62,624,141,448,489,236,32,374,859,20,847,777,431,491,0,697,160,124,526,624,607,369,103,534,916,332,50,294,895,140,285,186,375,83,646,469,170,505,444,247,587,424,773,267,457,245,653,62,828,795,918,822,585,257,920,552,735,582,84,308,910,150,237,188,714,208,989,646,193,977,902,172,428,536,55,961,597,102,137,299,151,11,399,852,582,839,393,365,789,907,184,528,166,224,940,150,574,257,495,842,896,263,216,871,909,297,660,500,290,459,344,858,643,375,139,370,953,30,924,818,4,947,286,710,271,735,44,895,534,423,372,813,831,452,569,666,148,779,477,382,968,769,256,705,454,653,393,125,612,11,770,674,85,162,829,778,810,830,397,123,478,265,143,190,414,733,950,412,4,536,795,559,150,139,40,631,856,828,623,883,650,196,994,812,859,562,200,344,411,132,793,675,916,230,724,288,560,960,788,498,995,151,981,212,532,590,615,964,667,744,480,607,15,78,367,790,767,902,263,979,917,596,651,600,269,811,520,881,49,766,353,288,783,635,548,434,277,732,418,804,813,327,462,859,961,596,145,944,161,124,237,394,423,692,564,335,56,491,510,650,440,668,117,277,889,167,113,75,505,142,784,635,594,147,461,455,13,960,717,576,966,376,970,825,637,206,730,644,83,350,47,376,71,854,206,948,564,111,361,175,955,870,564,902,725,507,60,728,596,264,128,956,485,317,959,257,801,86,36,409,430,641,812,521,780,714,502,383,191,502,657,338,931,111,208,957,587,749,397,116,693,642,85,278,480,700,666,910,511,578,791,274,568,661,572,870,209,170,265,978,27,816,265,98,386,282,420,80,222,156,14,141,779,497,229,960,184,595,759,957,954,217,450,809,419,205,805,730,550,539,241,318,292,102,169,137,471,435,814,866,740,69,540,732,470,451,43,361,638,142,910,959,744,459,693,446,985,62,477,799,589,768,342,372,64,718,477,392,414,884,186,650,98,155,654,764,258,338,654,370,11,147,750,312,333,268,170,189,840,542,866,413,722,887,406,55,840,149,58,720,150,369,237,208,445,872,81,684,692,338,428,975,430,479,770,416,992,227,414,460,670,840,49,914,963,12,745,99,444,77,858,852,762,845,807,773,248,415,529,528,340,230,760,323,165,943,874,759,503,887,815,501,719,595,553,660,531,577,383,227,723,901,710,150,332,398,62,482,358,165,348,29,73,260,414,218,338,825,691,52,835,707,272,103,173,86,751,983,248,858,76,644,252,264,255,201,488,847,38,335,437,109,138,135,104,917,982,527,386,959,221,90,121,318,446,751,42,255,945,990,179,640,360,99,851,322,371,906,681,128,971,769,14,560,823,370,61,789,208,614,839,540,182,730,61,906,221,217,681,731,582,546,398,99,643,743,707,158,604,863,783,583,248,425,832,549,24,815,107,139,699,478,377,819,759,621,44,564,597,418,794,153,104,247,363,727,438,465,970,273,174,406,599,765,616,546,245,426,24,64,826,231,998,657,666,405,365,579,27,756,649,134,397,108,185,986,234,317,576,698,497,133,555,976,886,277,776,974,966,635,422,33,810,425,453,180,5,217,260,521,758,87,98,391,53,362,4,459,956,941,826,417,269,369,957,903,218,543,620,402,263,231,730,155,569,214,694,864,39,546,521,647,864,496,988,988,727,891,138,112,570,38,231,110,221,844,640,775,460,16,610,628,998,847,89,239,354,907,654,362,951,720,860,508,861,137,737,220,324,465,587,573,380,643,422,854,226,334,916,167,728,613,959,84,721,755,427,339,549,597,580,700,636,13,256,912,365,262,608,771,132,773,224,887,389,253,246,503", + "682,53,553,479,819,263,139,847,273,122,9,601,219,732,452,593,486,15,662,722,903,319,132,113,202,903,341,17,949,521,187,102,751,719,148,719,978,341,551,382,822,337,850,561,416,459,354,690,180,384,53,899,364,333,892,29,677,453,815,183,344,998,880,733,440,636,132,950,544,182,340,536,965,86,320,35,566,595,809,356,251,352,802,518,69,156,280,187,684,732,308,870,907,741,66,501,125,85,473,280,985,143,711,928,995,509,323,606,676,95,562,230,115,472,296,191,960,316,313,783,882,434,189,886,18,826,604,544,624,594,635,595,135,838,747,983,743,437,747,143,518,217,125,93,919,762,837,734,561,363,159,144,535,605,342,538,220,734,475,100,45,727,963,177,363,144,472,915,859,12,360,923,962,663,244,906,461,225,140,630,305,404,730,758,208,558,548,957,555,932,858,687,315,340,431,123,323,290,866,55,161,809,119,614,269,269,697,0,328,415,304,305,870,745,836,77,393,364,899,890,90,613,634,242,925,41,604,462,461,811,948,373,330,225,343,105,441,941,308,791,285,576,481,636,219,142,120,322,289,221,867,913,386,838,529,6,887,676,736,76,653,282,298,110,445,12,244,521,59,153,225,470,599,245,186,776,627,901,989,551,870,523,421,950,554,469,155,557,219,543,832,798,106,873,105,734,553,280,445,598,938,948,353,174,582,69,58,620,140,153,456,824,95,756,233,101,431,695,82,599,255,132,100,623,840,245,825,604,497,388,733,354,800,185,718,250,752,229,826,414,512,205,222,66,556,250,420,684,455,802,809,555,111,416,902,408,596,996,363,967,779,736,688,275,582,934,990,480,539,676,894,859,963,293,25,407,682,669,545,378,650,957,233,597,856,444,400,322,274,968,325,584,166,396,169,411,137,669,15,286,308,645,833,59,899,623,456,527,897,215,954,635,516,540,19,616,956,269,812,764,183,971,607,803,347,272,306,530,881,754,231,826,473,627,100,339,509,16,686,714,138,605,86,186,288,357,292,24,882,104,979,345,97,418,533,577,771,959,44,733,458,834,483,786,492,885,194,512,302,221,359,34,396,957,336,314,582,714,57,565,27,865,584,699,933,410,356,403,21,500,763,56,97,656,99,843,943,921,22,742,575,938,859,494,113,26,130,367,585,954,362,78,594,921,426,166,609,433,287,812,563,643,301,585,102,345,707,320,457,981,998,303,478,761,682,327,562,846,624,487,95,872,740,523,402,745,388,189,720,52,801,813,830,718,234,940,416,349,957,496,283,636,319,491,575,992,696,437,8,100,235,907,109,89,630,562,787,514,601,920,651,51,801,709,768,521,968,480,278,844,379,618,217,298,592,522,863,562,485,992,792,778,152,884,939,821,213,834,785,8,601,395,550,849,735,861,257,512,825,23,118,660,727,600,242,937,735,117,1000,536,801,521,22,634,873,47,708,602,910,955,190,788,364,738,261,386,834,184,89,675,617,438,10,809,684,892,688,801,572,2,105,164,553,782,72,431,841,924,668,855,588,621,610,370,55,448,558,891,138,63,352,585,530,305,368,570,883,41,7,690,555,70,171,151,510,79,889,529,945,740,206,617,121,337,365,722,271,175,312,848,82,192,559,942,979,513,478,423,712,117,272,780,250,272,968,163,950,186,39,466,988,80,37,147,662,250,4,769,799,55,312,358,599,768,815,651,127,104,760,728,286,843,374,328,981,938,244,576,267,222,265,895,318,125,872,373,534,630,531,503,723,254,953,613,376,687,697,565,49,813,146,463,52,189,912,152,288,180,785,296,232,387,789,781,766,926,128,887,487,791,272,172,713,442,572,849,800,60,51,991,271,628,222,701,234,11,348,372,644,112,267,291,742,623,606,452,50,444,191,757,376,862,457,494,748,546,22,200,638,427,943,872,125,296,355,517,950,304,274,816,335,156,577,435,96,668,302,108,879,498,365,336,39,670,736,363,108,845,643,50,718,633,179,205,989,631,20,917,237,812,133,294,220,527,84,234,812,185,226,191,968,387,115,20,933,741,808,518,226,686,969,666,967,129,732,404,499,506,210,324,280,155,332,766,184,593,610,267,934,163,357,534,928,445,324,986,639,329,480,883,320,292,891,500,174,722,42,297,348,133,365,89,229,539,903,263,315,631,992,75,80,807,784,524,177,708,176,677,426,299,732,960,815,33,540,186,859,340,834,361,719,500,773,304,955,569,680,778,837,924,436,794,875,889,413,919,849,339,771,118,816,746,139,339,54,859,557,428,877,356", + "558,976,402,222,981,451,152,63,255,85,606,618,199,322,398,256,206,137,780,389,146,836,35,141,830,445,21,424,271,318,811,544,90,153,367,195,626,153,635,778,877,33,824,908,351,392,987,462,751,678,603,496,993,82,932,398,93,327,516,730,916,682,906,139,69,289,853,314,44,425,996,963,977,309,233,434,262,950,614,852,628,903,404,792,276,777,424,458,738,38,622,756,32,890,563,696,92,736,56,247,673,53,913,209,445,856,892,402,510,96,686,54,337,345,836,635,604,845,380,226,521,625,27,348,246,7,737,242,536,96,62,816,849,507,816,91,857,728,41,568,669,871,914,448,915,704,243,394,81,354,33,864,867,838,32,43,278,226,599,665,262,22,28,698,738,58,767,781,528,677,867,428,82,332,459,537,856,192,22,585,764,116,369,67,549,294,233,305,514,949,36,757,213,352,496,908,986,447,979,176,219,860,938,564,511,650,160,328,0,381,665,153,486,30,330,560,124,216,809,86,593,867,596,948,589,167,40,906,51,134,600,78,404,570,597,577,750,782,488,145,69,925,271,581,344,884,817,765,988,285,928,129,310,777,337,889,116,786,831,708,111,75,523,305,778,468,334,437,392,214,830,772,837,829,160,881,188,118,472,914,816,336,404,311,56,194,615,84,747,897,823,15,92,431,218,999,103,135,266,249,97,922,121,647,548,277,381,565,181,646,843,906,475,709,251,940,797,941,330,246,970,822,806,75,352,173,549,142,60,292,110,376,532,11,351,956,53,377,871,815,464,548,243,502,751,462,675,372,659,877,723,298,842,669,710,635,905,253,279,162,644,38,911,108,629,69,83,701,269,811,102,130,183,302,574,884,259,320,537,621,283,716,583,594,531,298,118,55,288,382,293,550,570,31,950,28,337,776,566,855,611,763,533,606,328,642,994,831,631,688,597,35,492,553,572,250,363,786,62,290,339,93,66,617,962,507,559,907,789,702,361,570,73,357,488,248,5,150,973,354,301,925,429,971,533,175,401,641,736,247,348,461,299,42,777,147,947,705,78,361,749,668,528,873,258,732,933,975,932,446,466,165,693,279,471,265,682,941,158,61,403,530,419,883,270,42,334,51,230,150,505,447,59,682,340,895,686,234,833,40,253,890,554,866,585,950,745,232,398,520,607,309,977,772,577,870,594,946,528,164,919,381,732,983,343,249,975,666,65,336,590,516,569,58,703,257,371,619,875,978,156,963,305,724,807,595,359,250,150,638,510,732,441,63,54,94,643,376,593,36,254,773,329,794,294,350,206,172,646,867,698,368,64,871,536,837,542,2,617,403,32,851,935,407,804,650,917,4,840,311,794,937,644,719,850,589,305,993,100,624,260,317,493,552,814,787,645,225,354,625,88,775,682,718,421,894,332,478,103,330,839,849,365,702,502,617,601,815,802,895,479,539,300,435,293,235,174,18,796,23,718,349,240,759,211,248,421,47,959,250,879,759,792,479,424,796,71,219,21,692,851,245,447,174,408,516,734,75,581,776,647,503,691,619,506,236,804,790,807,841,159,903,988,803,536,508,734,12,75,554,52,313,530,220,88,818,205,246,835,858,541,979,228,572,885,83,642,104,568,890,800,815,202,317,244,44,638,683,529,493,123,173,150,73,592,137,324,685,201,131,468,862,610,220,330,647,826,200,131,552,776,582,560,420,731,843,446,668,175,571,248,372,613,327,564,55,851,450,479,75,436,673,48,299,283,384,576,267,880,883,220,883,166,460,846,753,143,227,183,759,247,706,140,183,611,80,150,180,312,616,583,465,238,970,385,497,534,409,454,270,775,693,180,453,81,232,822,611,309,519,865,409,657,786,508,860,373,554,949,795,509,285,257,80,828,104,418,211,655,992,328,606,761,40,698,400,47,978,355,424,711,898,224,254,88,162,18,326,433,682,739,310,613,348,204,214,731,311,870,195,193,499,173,713,342,105,149,298,406,918,107,961,348,413,139,542,191,276,251,899,168,538,78,767,444,328,430,483,241,379,640,621,518,670,797,607,764,450,648,794,20,871,209,327,585,381,36,324,650,405,963,163,403,192,240,927,590,970,999,197,293,317,695,626,383,194,57,366,437,503,257,791,183,920,457,347,470,938,346,962,587,252,992,515,85,261,671,763,822,17,691,350,309,385,537,295,69,792,958,628,569,906,815,512,535,933,730,922,37,14,628,285,931,391,908,805,712,559,172,837,389,949,307,674,581,285,663,620,567,118,638,935,318,591,340,979,768,529,448,159", + "298,778,768,881,661,602,417,667,287,655,582,473,360,616,354,150,10,457,29,252,461,328,773,72,862,113,852,79,211,697,185,857,609,411,862,828,526,435,356,406,873,842,852,721,239,282,857,476,665,319,737,23,859,101,116,614,878,941,521,856,724,297,771,599,131,395,426,872,854,252,129,450,754,268,899,328,55,744,325,78,387,851,573,998,284,885,465,953,589,300,48,969,542,368,647,299,981,27,620,572,378,162,370,470,582,965,670,830,250,513,145,823,165,78,973,419,837,649,445,169,603,858,771,159,553,391,489,256,359,776,25,396,899,57,679,699,364,340,926,912,43,173,148,935,389,850,988,635,31,51,850,17,891,175,728,603,108,192,956,656,548,408,564,573,953,531,629,290,341,847,305,441,59,306,626,783,107,944,683,563,578,486,414,527,372,991,730,832,747,914,48,223,63,853,976,81,529,569,815,315,401,287,339,616,253,228,124,415,381,0,267,529,681,825,418,357,754,208,528,678,465,272,232,203,462,43,797,320,436,575,355,414,736,249,849,669,633,858,799,876,771,203,394,630,911,376,557,253,357,733,913,381,59,371,217,565,820,565,515,526,885,383,944,214,861,99,555,466,604,677,588,891,67,380,811,190,9,179,396,670,324,319,575,37,300,498,21,688,539,119,993,448,358,495,101,530,743,775,184,903,394,732,510,11,530,352,737,404,805,153,404,845,341,357,599,922,4,289,51,734,628,38,465,613,522,825,555,499,538,512,440,378,516,143,507,947,815,522,488,949,881,985,763,297,748,581,330,471,374,493,596,851,218,649,711,180,22,754,933,518,475,694,431,848,507,213,415,5,100,48,579,23,532,273,980,200,106,234,511,4,276,889,263,748,281,192,152,203,848,791,142,848,147,411,896,86,108,309,553,916,946,663,744,574,812,670,964,71,293,247,524,553,860,453,666,197,553,658,173,666,397,452,887,777,195,82,216,44,331,746,355,388,469,104,413,834,570,805,870,769,510,924,477,989,628,459,387,36,158,574,450,900,466,264,329,96,238,330,617,371,925,204,231,581,535,952,745,260,170,113,685,744,804,154,980,389,834,958,334,965,29,118,864,687,26,398,626,939,100,109,463,542,512,576,966,248,324,381,675,732,33,99,301,636,129,13,863,969,387,499,293,638,883,360,969,760,699,117,430,937,210,542,169,654,796,505,849,474,549,610,827,377,264,586,225,337,172,261,695,989,832,143,940,117,583,151,220,445,863,222,11,815,364,242,408,849,933,55,327,399,802,121,855,65,713,633,423,259,510,289,64,431,400,96,781,866,563,75,179,936,485,453,288,641,201,680,352,20,543,418,826,80,366,303,641,889,31,803,688,176,186,565,448,566,725,833,452,979,802,244,427,447,236,943,511,826,742,132,749,48,517,105,917,29,403,900,505,222,815,593,88,405,887,903,869,89,282,719,926,515,350,442,971,455,207,629,336,101,903,912,671,829,502,739,602,486,834,981,31,111,366,657,644,216,124,410,800,219,508,677,328,363,371,903,576,206,95,73,647,335,386,225,216,19,178,594,612,179,559,803,362,183,784,903,319,841,59,87,931,990,691,697,638,973,646,773,184,772,438,316,935,403,292,785,259,204,85,137,300,410,29,735,912,637,443,850,202,410,612,371,86,691,277,832,353,899,990,669,503,6,216,693,18,77,974,94,954,991,844,675,387,966,627,654,262,5,734,420,462,823,552,75,213,369,628,100,185,237,165,680,212,62,903,71,346,101,693,512,488,385,663,392,431,846,443,954,725,574,452,915,464,232,409,216,303,534,260,317,15,5,192,425,225,509,976,545,507,887,506,681,57,14,215,848,434,419,844,993,824,918,649,940,938,165,566,223,451,632,403,888,725,812,726,706,887,897,551,485,155,910,172,704,222,667,862,104,996,59,379,609,714,703,255,565,714,492,8,581,666,696,320,163,201,513,457,644,366,874,473,236,990,899,626,811,116,196,189,633,278,761,866,706,829,525,249,324,394,435,572,197,447,542,53,848,156,260,405,340,954,812,238,478,200,55,111,582,295,219,594,156,597,952,710,19,820,473,934,751,4,852,477,170,550,214,146,298,251,837,98,524,41,916,249,572,630,34,409,497,553,153,236,790,582,278,763,372,464,596,555,505,140,896,57,112,192,233,457,738,372,513,743,178,806,799,821,697,678,250,500,692,351,767,846,378,507,502,206,219,819,290,458,444,658,25,256,235,907,545,820,617,980,9,221,674,388,699,884,987,576,802", + "726,842,262,247,158,48,852,580,147,328,451,248,362,476,191,117,776,66,348,153,369,843,880,774,140,486,941,377,593,625,985,634,888,955,658,762,935,877,768,231,748,437,53,865,510,952,485,982,81,658,598,609,922,683,617,767,991,864,779,18,356,339,682,424,297,362,633,955,58,598,564,830,371,559,277,161,915,298,94,278,629,778,42,803,886,438,314,19,766,76,3,679,175,324,593,341,481,391,585,156,311,838,210,366,856,786,916,518,728,580,677,481,954,581,633,222,677,272,916,905,630,71,12,836,966,331,96,709,244,100,853,176,191,736,222,796,701,827,509,94,232,176,176,339,202,582,346,624,741,895,283,891,615,722,56,866,581,440,798,943,878,112,900,825,772,642,163,891,237,220,348,817,757,912,612,386,759,229,280,679,593,953,810,464,840,311,840,598,465,910,484,574,665,222,933,799,498,755,416,436,377,431,315,341,246,111,526,304,665,267,0,621,692,913,633,514,557,54,267,517,710,544,951,101,432,401,24,108,202,84,452,819,134,588,751,922,159,7,411,796,554,619,171,181,56,540,354,277,737,745,79,873,257,4,175,697,326,266,79,40,970,112,516,208,476,817,793,991,166,71,885,79,264,926,771,635,235,566,975,98,636,447,570,148,165,301,389,73,801,165,541,581,148,545,252,220,236,740,456,656,56,474,797,556,28,895,591,12,379,361,5,166,361,495,640,745,248,140,643,215,544,22,884,959,534,608,459,250,359,440,914,697,604,973,735,73,360,43,290,204,252,686,689,488,314,368,184,175,846,771,869,232,877,134,404,510,447,953,494,859,868,962,800,832,894,790,913,440,46,443,954,879,777,833,526,517,34,150,372,861,618,725,385,257,659,640,149,524,799,101,448,859,927,304,642,256,368,446,967,885,409,516,416,745,82,368,155,202,212,155,415,487,169,668,271,172,448,619,462,827,140,922,789,471,605,220,76,38,712,437,994,367,49,334,691,194,160,694,336,951,334,262,688,109,817,909,879,122,485,128,509,984,141,714,270,394,378,187,14,314,913,177,564,666,492,92,886,720,866,67,635,532,109,590,587,708,203,595,575,405,540,386,198,427,4,459,552,824,892,588,550,146,228,91,965,560,451,825,286,623,870,903,317,739,506,669,365,740,939,883,261,514,720,417,384,143,378,876,588,783,303,65,52,644,250,341,76,92,613,346,398,197,998,274,529,83,776,922,573,428,312,196,639,443,283,446,678,258,197,409,870,349,93,762,362,208,60,400,242,159,642,774,363,366,859,498,595,678,101,278,216,990,281,363,36,339,938,213,636,377,403,749,462,928,219,215,561,711,886,270,806,275,541,904,747,749,967,39,635,333,693,85,566,14,912,712,631,536,383,749,922,190,337,979,576,673,833,483,745,248,962,209,184,563,82,268,455,291,608,300,591,699,722,539,213,735,578,707,412,94,230,564,825,338,271,396,752,850,546,90,794,945,884,386,923,903,653,186,967,498,630,668,679,387,232,712,541,288,680,666,349,95,89,52,830,504,403,670,829,771,97,147,902,353,312,417,703,21,669,41,665,454,216,300,297,335,442,709,383,947,61,605,644,991,870,12,310,312,622,303,18,433,818,244,439,796,674,424,90,206,469,315,78,147,84,373,831,471,725,919,641,545,467,320,452,123,638,753,267,41,144,254,861,789,831,559,643,552,375,192,85,54,76,642,261,390,762,52,240,596,202,329,170,428,534,656,363,527,45,524,485,966,747,588,495,225,436,925,336,638,183,762,965,993,116,981,784,933,88,117,5,232,999,249,752,942,542,287,760,115,757,485,229,329,14,416,646,745,580,793,410,458,613,562,196,788,648,813,378,812,481,563,269,163,823,201,993,241,695,410,887,258,213,184,473,747,216,972,24,62,104,701,320,645,414,765,165,672,203,909,100,222,687,841,742,21,629,397,249,774,489,251,19,329,878,313,384,565,987,547,143,872,590,206,840,248,653,717,422,161,890,681,453,612,326,278,531,409,492,541,355,731,891,258,894,679,816,772,340,329,335,3,113,822,152,60,204,873,983,473,513,959,731,324,703,383,40,214,286,495,987,87,247,636,97,40,432,391,387,648,332,707,775,799,474,598,464,105,344,499,754,273,847,75,598,903,995,929,251,20,308,855,20,407,378,126,839,913,923,814,643,251,169,778,163,507,934,759,833,637,762,912,30,566,60,723,908,126,477,750,87,997,831,400,939,685,930,201,593,525,904,451,844,209,477,109,623,334,190,964", + "899,967,257,954,123,408,326,959,195,177,450,789,368,823,385,205,648,239,175,299,23,948,962,525,681,578,864,13,522,710,302,983,437,886,824,327,662,349,298,761,556,319,4,87,4,85,475,979,165,566,729,724,713,697,739,681,235,641,843,149,520,487,864,986,569,485,258,958,147,750,342,655,499,564,580,742,556,564,265,480,695,998,935,851,635,136,678,581,680,647,77,460,391,901,835,526,499,62,971,32,316,967,913,342,476,13,20,635,932,234,17,237,185,681,271,522,793,597,222,366,860,363,528,802,612,221,674,220,440,405,997,935,776,546,116,462,733,165,938,302,58,36,274,795,390,316,370,888,143,607,464,63,701,680,649,854,182,26,628,475,244,52,279,59,686,127,564,237,530,261,239,474,586,768,551,530,326,126,140,614,852,306,334,700,188,642,157,94,73,362,940,264,426,488,700,183,985,869,87,579,569,921,893,976,956,175,624,305,153,529,621,0,449,747,788,697,323,184,343,925,539,620,353,267,137,628,925,487,627,725,414,218,303,894,332,460,319,461,212,448,674,678,50,446,479,731,548,556,572,768,136,878,15,601,105,515,544,751,196,371,434,852,650,792,764,648,31,443,242,796,634,439,202,297,539,685,851,107,766,193,198,134,950,920,321,293,84,394,197,221,513,751,942,234,459,614,64,190,450,828,683,709,219,292,920,557,597,271,330,838,432,808,131,152,647,354,297,421,657,984,169,396,355,293,827,185,900,322,779,666,496,141,778,75,887,799,781,912,173,932,355,340,792,66,793,609,24,93,626,441,301,98,282,767,768,972,909,493,192,743,405,258,203,949,420,330,204,698,367,769,351,437,624,68,709,597,274,873,778,726,944,815,138,975,350,474,158,166,345,588,497,359,42,916,350,302,870,626,914,476,739,630,278,232,676,273,193,173,372,705,489,799,911,234,411,144,892,570,177,845,115,340,219,624,543,334,721,688,580,547,516,270,422,875,71,163,974,168,622,649,55,389,1000,519,254,433,50,969,132,834,633,55,18,499,820,512,167,371,617,336,596,249,957,362,277,596,814,402,993,123,287,298,216,782,665,815,797,500,644,188,724,879,359,305,482,216,448,223,543,158,51,413,150,397,954,820,377,190,537,285,792,848,904,98,44,595,932,839,462,699,807,827,280,539,342,761,449,746,479,582,951,723,621,419,320,3,753,650,232,160,546,332,900,197,801,861,32,592,647,650,757,205,866,152,592,570,611,968,750,572,217,533,960,307,258,879,340,548,464,872,372,29,620,374,912,339,554,357,973,632,813,207,830,551,625,820,354,753,163,285,369,539,451,163,224,65,927,888,118,880,222,966,691,651,621,606,932,575,500,603,920,445,136,51,924,635,927,152,371,860,690,444,763,780,18,192,272,680,353,6,703,485,416,42,219,532,52,387,950,149,362,918,5,814,654,610,741,844,480,21,742,89,641,53,767,61,288,367,366,946,621,443,647,973,650,653,986,722,703,310,216,531,905,439,164,193,236,999,718,124,551,122,730,221,265,342,512,868,377,48,950,517,958,834,957,945,162,823,579,713,404,181,717,129,998,908,342,182,978,546,556,774,149,974,287,327,860,65,908,769,293,515,919,717,467,795,906,326,416,568,887,901,367,278,192,337,805,419,824,312,555,939,648,28,364,553,499,862,264,795,991,278,660,788,24,75,829,860,901,27,346,284,544,579,247,183,208,554,51,329,602,819,667,856,13,404,918,378,837,632,741,751,574,919,330,748,666,800,343,809,642,181,724,927,813,99,732,661,662,379,167,81,224,460,88,856,519,679,422,364,95,140,9,878,389,439,176,635,381,184,381,751,573,493,338,661,527,444,227,765,850,818,976,976,796,912,686,890,297,79,767,666,331,570,262,3,860,949,554,526,232,1000,520,801,972,722,174,386,563,484,141,435,494,970,28,407,414,679,82,105,109,760,340,585,976,86,583,405,329,185,694,352,366,271,19,887,373,382,375,783,659,566,924,178,268,615,382,845,194,254,778,42,95,238,781,950,436,935,447,681,759,378,681,168,762,600,670,696,180,562,135,904,800,581,979,97,47,492,436,267,318,431,767,500,136,962,924,663,896,501,626,880,187,446,326,525,116,894,610,907,513,901,891,119,17,410,826,134,18,569,712,389,207,759,281,890,462,129,594,670,748,217,764,346,99,935,52,149,284,146,944,536,197,232,781,178,517,685,924,261,988,875,307,730,93,326,668,102,374,810,692,517,256,733,339,845,203,807,267,185", + "444,875,941,128,21,122,445,648,163,197,475,754,711,651,742,323,169,552,724,914,535,441,339,400,790,287,447,374,37,937,70,967,440,476,364,783,790,573,564,30,314,535,701,193,298,994,966,752,100,896,135,675,939,2,98,338,664,673,640,361,863,53,136,358,198,934,933,463,945,172,68,934,40,346,535,355,742,397,500,409,118,454,45,423,171,852,785,264,422,758,479,999,37,458,840,40,705,557,354,459,929,837,32,723,82,195,148,792,753,482,910,804,489,586,787,689,8,622,918,768,381,615,681,626,237,908,940,676,893,397,710,993,805,787,297,55,954,368,412,599,101,571,444,967,234,195,128,966,266,891,865,944,267,206,60,314,424,334,500,675,978,417,199,701,763,813,729,538,106,373,527,838,11,979,655,169,117,46,723,757,54,301,418,994,912,395,195,626,744,225,654,537,119,680,510,792,216,996,982,87,233,941,101,426,560,380,607,870,486,681,692,449,0,205,914,184,337,391,685,429,467,846,649,720,85,802,878,665,20,260,718,970,205,307,32,75,597,127,844,996,305,366,976,706,65,82,903,462,341,779,582,496,201,105,58,733,66,856,575,365,917,187,6,839,448,770,340,954,26,483,382,963,207,5,32,707,815,112,581,216,63,480,571,894,293,353,90,54,435,667,981,680,44,835,954,710,818,729,378,537,495,354,75,237,833,473,685,779,468,59,880,584,369,413,695,644,327,608,121,212,986,471,361,90,219,223,382,928,452,16,411,359,780,897,962,694,735,696,187,351,889,970,341,932,170,527,160,649,972,186,965,31,918,243,393,590,597,480,585,921,615,5,649,915,825,888,789,621,189,281,427,780,573,731,438,592,589,405,584,882,118,277,812,970,626,440,587,756,775,135,273,922,966,410,286,351,291,869,934,363,16,310,990,576,455,511,862,708,49,551,629,409,471,727,502,252,155,104,510,906,155,376,916,135,677,708,300,937,481,330,606,844,88,993,862,148,422,978,755,527,248,784,451,730,209,700,146,287,717,493,432,500,371,160,742,95,207,49,755,155,831,651,347,655,164,862,857,946,186,395,164,220,183,332,266,203,21,70,360,303,57,369,465,653,191,439,89,644,541,361,299,592,927,6,175,222,814,198,400,508,59,978,187,55,595,80,569,116,375,280,352,283,928,679,824,664,348,724,31,850,8,904,246,620,408,127,531,671,465,196,234,455,546,105,817,265,773,586,673,882,624,190,885,559,57,901,758,760,131,741,305,410,659,584,452,695,445,568,282,376,717,954,622,650,989,610,234,635,17,314,107,770,758,911,395,179,389,548,827,400,223,928,997,894,932,247,755,916,236,610,765,209,355,119,286,747,7,413,414,924,377,979,618,178,852,798,89,587,970,641,340,518,947,598,172,941,157,734,19,260,999,899,559,778,299,902,487,869,487,622,462,467,464,493,410,539,924,369,21,974,619,237,17,706,436,149,110,583,389,402,438,922,626,475,780,717,251,520,462,708,549,509,280,849,883,376,712,598,859,878,332,73,387,798,40,563,622,471,869,192,870,430,907,394,531,604,62,832,9,967,930,698,866,290,968,631,79,983,315,25,73,716,958,400,289,407,236,916,511,647,165,186,727,264,26,557,310,143,292,165,608,458,209,823,97,39,523,645,362,406,394,436,852,270,266,942,590,255,417,82,419,349,3,7,728,826,598,275,754,684,758,456,498,579,200,381,147,919,822,478,967,142,632,878,697,599,543,858,105,626,886,327,677,590,989,879,16,403,852,547,738,568,813,124,9,28,618,560,837,279,71,379,600,956,302,68,366,470,944,314,267,216,880,501,824,43,651,69,273,646,336,377,244,825,321,777,712,722,128,340,229,218,884,309,392,45,595,311,595,862,58,729,808,924,384,732,614,942,770,972,835,955,171,517,243,553,269,34,781,517,631,427,66,857,264,83,855,666,749,494,324,613,296,651,303,672,834,367,831,812,932,293,502,180,387,968,25,283,170,861,307,463,912,701,951,648,294,110,141,827,304,275,180,784,65,168,827,224,572,716,74,612,931,977,658,648,53,734,654,303,453,718,788,311,596,944,828,66,228,319,861,126,282,569,111,352,311,258,682,739,647,136,834,816,925,307,615,299,318,134,786,936,103,800,443,475,235,178,319,299,623,11,898,883,988,173,660,160,580,640,543,414,71,877,811,962,916,289,229,853,315,62,951,160,292,626,633,321,888,140,472,532,309,615,555,149,479,140,954,339,619,492,122,717,645,189,627,543,691,200", + "420,668,118,478,946,297,917,234,166,911,717,567,736,177,801,794,636,777,245,703,362,685,54,15,155,474,417,75,229,959,765,53,994,712,235,926,843,388,212,582,713,264,166,946,242,832,706,821,602,539,990,602,786,696,581,731,927,726,515,11,77,107,648,308,601,96,225,467,50,856,628,155,500,411,365,911,919,72,591,666,685,588,80,121,672,277,28,983,137,713,881,133,267,345,598,213,961,465,289,647,981,33,811,655,111,166,556,433,225,395,917,423,526,923,776,1,252,449,509,460,2,437,115,146,105,230,979,416,562,861,73,138,715,330,538,838,543,169,17,270,582,942,718,127,653,938,938,967,799,325,364,293,478,873,833,713,890,375,787,320,828,956,587,453,776,162,977,854,495,912,508,927,842,444,357,910,339,210,331,545,934,286,189,865,729,662,447,303,364,837,759,501,470,131,358,697,566,202,435,745,315,842,117,969,974,157,369,745,30,825,913,747,205,0,862,60,571,602,313,681,645,13,422,357,842,336,644,807,985,273,663,954,56,970,320,934,290,921,214,668,88,659,748,559,657,209,505,292,731,717,659,991,644,660,14,295,118,534,528,987,846,698,611,725,848,554,935,550,170,624,185,30,674,941,183,751,906,406,861,878,914,646,760,887,265,611,843,405,499,766,724,597,253,748,290,335,24,341,620,246,495,383,893,26,929,439,524,486,366,716,895,723,162,608,605,688,525,728,228,865,540,19,377,701,77,746,343,142,931,683,876,419,77,27,81,245,873,796,609,297,766,860,257,924,137,448,495,50,262,448,94,280,556,976,526,896,937,472,945,360,450,129,584,201,775,428,241,891,560,133,549,661,781,701,104,888,813,288,701,215,191,378,756,69,570,231,123,596,61,119,906,378,527,375,159,499,925,47,367,411,438,893,158,815,496,337,916,132,661,631,491,105,338,966,576,847,642,687,434,503,115,709,653,931,537,289,238,562,603,950,545,716,222,893,214,852,945,402,659,904,187,141,261,349,555,67,594,905,268,478,864,833,123,785,142,500,986,184,868,377,987,503,476,17,737,426,775,677,146,283,990,984,183,784,534,382,857,653,378,466,567,797,219,159,92,425,67,292,80,951,638,776,114,296,184,615,607,35,975,101,677,40,161,69,212,101,86,676,704,584,137,326,740,830,208,784,293,408,86,923,938,58,403,929,900,944,419,177,101,337,867,480,877,941,375,948,708,100,368,812,730,341,958,936,158,307,19,689,960,767,317,553,923,38,684,556,33,902,682,359,596,870,906,352,595,893,511,74,664,606,810,942,792,143,217,613,493,588,893,623,141,130,25,626,494,889,645,511,929,504,939,921,876,282,700,480,394,595,913,48,476,233,623,619,10,122,458,997,429,436,905,19,997,320,395,680,214,244,124,343,364,463,729,752,631,364,47,942,869,692,466,719,6,31,750,459,174,775,834,893,880,114,4,978,646,300,129,470,285,223,476,89,553,113,517,601,769,933,201,544,61,456,889,907,714,63,526,739,244,76,246,297,828,382,190,658,164,886,544,610,365,697,598,70,542,712,672,127,262,326,102,467,227,789,499,77,504,879,267,542,965,337,901,135,68,975,44,744,70,857,774,840,882,280,862,262,342,124,53,546,919,790,593,398,598,165,459,546,162,853,872,137,103,174,637,779,27,481,719,827,668,394,188,595,617,681,568,164,887,243,577,372,977,624,587,895,396,737,91,25,510,689,939,443,818,144,661,372,474,745,291,115,30,667,66,832,677,267,636,541,422,106,152,866,544,32,452,637,233,724,283,744,457,166,345,113,243,253,256,197,103,703,172,733,607,480,995,758,262,524,372,442,395,902,421,69,289,448,456,262,789,731,547,755,573,623,898,970,855,1,276,454,786,565,264,304,172,199,733,856,795,410,936,717,410,271,704,245,627,345,256,540,753,157,461,293,424,586,266,16,628,960,952,650,859,310,131,347,841,909,316,185,993,893,15,507,129,34,980,810,527,977,140,148,886,688,981,611,431,234,203,220,716,228,497,794,264,205,490,437,135,856,270,671,839,491,155,977,408,538,264,602,330,84,542,718,275,191,993,753,55,142,133,240,720,105,437,645,834,268,697,740,109,602,240,640,981,470,807,770,215,258,439,611,610,846,400,244,618,696,533,556,944,606,767,633,263,164,142,253,836,368,491,317,530,584,703,787,628,704,298,367,211,511,684,780,972,640,978,323,292,554,604,871,933,7,354,35,489,886,746,455,204,691,242,659,963,657,153,690", + "481,980,51,249,140,161,924,62,594,890,851,381,232,177,431,59,65,226,246,564,18,479,810,344,263,338,410,873,765,58,261,108,817,687,446,230,547,530,122,168,762,930,777,977,1,846,21,358,429,551,208,97,952,486,17,309,396,928,157,718,633,629,674,593,680,135,101,306,990,478,453,727,182,7,767,814,438,448,368,317,117,650,884,24,783,732,586,984,277,977,779,234,965,462,167,268,177,516,512,700,2,855,756,838,837,245,535,497,603,825,258,929,15,943,195,499,169,758,320,531,233,461,726,650,639,515,913,905,857,480,114,880,19,438,689,118,802,539,907,256,534,576,597,184,994,170,959,203,953,113,734,412,218,979,429,345,194,104,856,295,301,825,829,173,800,690,33,688,358,931,548,401,119,446,329,178,968,895,799,128,642,948,194,935,160,210,412,81,458,567,220,208,781,191,512,500,743,385,714,476,459,689,107,700,635,12,103,836,330,418,633,788,914,862,0,205,734,427,730,989,314,513,586,962,837,65,55,101,374,463,355,370,303,598,771,990,794,835,293,624,968,242,692,791,698,660,38,823,681,372,916,831,808,292,413,70,485,297,949,584,585,791,265,765,985,683,808,472,980,521,490,143,739,412,256,606,848,360,903,926,617,737,299,667,116,219,747,963,365,815,458,697,981,534,502,55,350,76,166,10,774,279,722,602,426,32,131,108,771,539,125,817,484,355,182,888,415,769,196,890,7,617,775,328,863,714,718,713,654,799,481,539,304,163,406,125,859,30,196,579,998,914,63,178,312,533,331,519,350,158,31,461,900,643,828,183,455,460,603,164,110,12,831,75,972,516,12,78,661,503,738,885,472,170,255,59,596,614,651,906,223,844,990,376,884,565,854,726,377,885,856,845,323,854,840,173,210,355,570,984,707,467,851,708,47,78,577,437,207,295,432,868,346,645,204,822,326,407,787,480,809,745,634,357,158,281,428,672,427,410,309,196,849,633,911,828,81,885,650,950,890,830,575,848,736,391,878,854,354,57,465,615,475,864,742,824,974,696,403,412,81,497,598,836,431,333,625,821,29,25,412,586,319,519,970,557,935,944,763,701,708,762,175,32,45,609,946,727,136,968,717,998,890,93,900,69,185,786,945,293,762,176,772,848,42,764,688,403,9,540,85,623,95,937,333,590,604,521,158,178,127,126,907,379,384,737,190,541,482,391,920,217,37,752,412,326,745,724,248,430,435,634,657,629,511,313,880,365,449,784,221,780,821,29,106,21,327,936,500,971,954,377,997,147,333,948,963,541,4,40,177,791,225,953,170,836,578,954,545,728,557,676,780,15,413,572,868,157,448,236,421,698,722,138,388,523,648,691,365,526,511,843,933,197,871,730,228,628,262,667,282,557,453,646,513,761,406,948,321,859,922,894,817,909,930,462,635,741,821,873,594,58,909,845,450,17,582,27,87,826,190,953,499,933,525,724,80,559,468,601,131,476,642,843,680,968,16,821,452,750,821,300,734,283,706,106,107,698,358,203,548,269,823,260,43,395,2,884,756,925,743,99,120,142,667,111,622,915,655,144,239,737,834,145,585,548,496,583,780,999,831,561,216,540,208,964,325,720,859,968,118,88,26,644,905,11,834,445,274,709,676,256,459,404,532,620,590,192,727,272,355,220,381,629,931,540,419,206,597,559,764,569,16,118,262,905,680,86,578,17,730,348,570,395,112,450,728,703,718,86,341,642,692,526,422,95,402,206,291,143,205,843,68,147,601,297,324,572,161,786,119,659,252,82,553,129,548,38,593,174,690,294,240,484,253,479,606,930,526,71,917,883,710,654,274,9,22,987,488,264,612,910,800,922,299,151,544,817,831,199,371,140,875,558,309,174,182,897,685,863,678,855,676,417,9,696,458,413,296,167,145,49,880,635,400,839,948,634,667,276,264,163,326,193,172,103,635,690,432,434,716,301,891,256,576,208,914,943,476,627,404,212,712,502,924,757,780,94,343,284,350,813,360,275,535,999,522,906,635,179,700,366,739,583,770,179,228,776,692,432,484,116,277,853,585,416,481,758,867,951,40,611,383,929,412,643,38,599,409,877,436,222,222,269,905,141,944,105,141,60,678,220,293,33,926,690,875,643,986,116,395,306,828,541,62,57,155,714,643,198,264,589,724,111,798,101,770,183,403,730,650,71,928,600,255,395,893,910,524,679,728,65,861,522,637,59,718,693,557,139,175,440,317,445,598,9,20,779,107,482,586,753,60,154,221,72,188,413,592,456", + "714,367,170,511,526,685,798,275,671,562,373,793,33,963,971,600,532,687,913,48,398,100,852,845,22,133,152,358,675,686,838,983,971,240,384,220,708,125,442,732,27,119,119,32,602,627,841,712,488,545,624,251,392,578,81,755,998,910,43,303,446,562,27,969,191,393,686,686,969,590,995,393,135,81,456,7,210,81,857,779,11,818,798,387,396,106,607,349,192,984,409,169,918,919,546,538,892,833,12,987,438,650,141,594,890,646,484,124,133,545,275,729,902,1,229,998,411,765,46,969,885,953,728,55,926,100,839,47,708,342,701,613,968,982,649,229,493,890,618,942,363,503,865,74,578,801,895,67,605,258,502,437,309,972,350,704,225,606,785,130,333,477,989,337,199,152,127,545,598,506,553,513,91,948,308,615,627,124,702,285,715,954,199,448,986,841,864,779,565,145,359,679,585,90,413,719,727,536,953,924,834,956,512,157,221,322,534,77,560,357,514,697,184,60,205,0,867,369,43,763,268,850,74,202,374,837,830,796,511,866,339,735,19,739,535,843,479,385,689,613,433,810,595,719,33,7,6,413,48,563,962,333,136,216,941,149,604,416,466,415,171,925,92,802,43,384,577,738,297,197,496,248,739,905,319,504,55,829,31,101,566,531,230,257,944,267,573,767,114,115,909,420,380,408,793,155,681,434,580,177,417,721,26,365,155,883,898,733,613,11,838,205,580,828,773,797,703,970,199,821,794,480,436,423,266,934,546,582,88,566,763,654,141,224,851,386,722,276,325,735,563,437,652,681,342,291,78,786,58,527,931,31,608,843,175,458,416,390,447,896,738,339,328,101,519,4,308,439,115,996,458,126,188,368,254,610,486,397,127,460,947,505,11,607,728,506,585,420,761,658,772,251,372,736,771,516,208,179,538,26,74,753,95,880,667,998,59,694,730,530,574,295,384,274,174,866,918,351,844,634,402,879,217,982,208,903,856,681,832,317,833,685,978,658,577,34,777,144,825,144,551,162,837,376,88,631,898,926,216,738,64,714,813,669,842,48,956,583,666,834,825,831,198,276,209,395,322,210,770,152,783,116,515,467,250,853,645,810,73,627,695,889,128,62,807,310,194,597,20,964,24,940,476,824,305,726,62,328,822,380,434,644,593,588,876,451,893,110,610,352,219,842,323,812,537,321,123,708,456,656,803,906,765,633,231,490,571,155,113,92,222,942,915,779,710,777,779,716,896,384,919,508,264,799,999,430,134,393,523,539,528,405,172,133,193,753,946,267,701,19,245,417,902,896,183,334,893,921,841,548,953,234,860,706,252,132,539,397,427,576,473,562,757,204,605,709,617,227,394,715,580,970,934,288,691,984,104,654,467,352,432,266,541,156,167,243,994,457,893,473,769,561,852,420,363,194,237,698,175,89,491,477,615,19,349,964,837,821,354,718,742,274,492,846,928,153,441,602,255,90,834,751,848,649,671,928,74,233,483,807,587,474,945,569,227,710,921,977,709,778,390,953,60,719,968,905,42,323,335,871,494,478,575,720,834,304,630,251,748,623,563,679,573,451,313,430,976,214,95,643,583,167,647,693,783,794,248,210,573,132,573,311,552,819,464,985,280,965,267,947,457,380,405,181,451,867,157,377,297,256,101,742,259,723,854,365,218,484,421,983,197,789,108,138,97,828,958,917,264,540,286,460,938,392,84,393,971,310,598,544,724,334,957,170,588,21,105,906,373,283,723,459,421,251,242,363,500,754,543,786,726,40,977,597,919,984,767,981,221,920,938,70,202,92,207,773,225,514,249,573,66,486,41,846,193,397,125,551,516,206,726,537,813,633,902,834,83,191,433,765,255,329,937,574,874,482,941,725,866,139,194,421,945,250,772,798,859,462,504,316,530,591,619,52,329,989,188,948,331,249,997,794,760,8,84,35,544,66,67,78,393,753,673,183,12,188,387,210,531,58,754,84,927,293,692,460,795,769,538,340,407,937,266,833,576,76,477,309,289,274,387,387,569,82,551,793,624,352,459,130,122,893,625,677,213,321,129,620,173,605,392,396,808,702,906,945,546,88,437,794,149,374,783,993,807,956,175,313,173,722,667,236,831,576,701,607,982,611,785,734,187,111,966,618,378,491,976,437,221,534,8,898,998,520,975,111,952,67,782,585,444,306,374,399,403,822,190,972,815,601,995,926,254,376,821,946,352,745,132,422,865,481,414,752,430,511,310,86,927,775,984,580,609,825,898,900,541,187,291,543,84,979,376,640,561,716,294,938,44,444", + "524,48,229,378,149,422,425,765,903,659,989,563,812,532,906,32,116,799,731,939,648,797,368,779,715,933,194,152,26,387,133,512,261,348,118,474,607,784,221,608,949,61,801,375,813,951,382,791,853,464,489,182,882,241,243,181,359,411,564,840,606,856,817,167,209,50,715,25,734,120,274,618,485,889,389,187,963,927,643,268,836,887,282,290,582,854,757,959,362,482,707,975,179,513,99,732,992,323,305,739,978,83,83,733,802,453,956,17,794,620,284,278,993,734,347,978,92,447,87,477,242,941,936,593,901,159,631,62,20,41,779,331,92,632,112,143,20,73,227,251,834,388,252,966,558,553,135,473,967,668,275,487,218,166,846,467,65,502,641,228,336,589,897,869,587,516,745,777,370,910,399,938,160,818,835,199,229,781,180,301,287,486,709,875,904,499,517,778,76,859,173,618,866,344,930,878,416,309,344,42,494,69,914,892,766,280,916,393,124,754,557,323,337,571,734,867,0,865,443,276,817,299,525,474,593,570,383,136,727,19,602,256,601,504,160,744,185,886,388,71,202,554,557,992,131,285,205,657,258,664,209,111,176,916,24,511,8,710,944,255,104,127,128,167,848,460,9,430,762,21,787,558,308,921,729,544,570,685,166,267,775,794,619,395,677,975,319,517,847,117,91,161,356,864,157,520,555,591,172,907,422,100,569,645,739,924,725,961,302,800,617,448,636,964,898,863,353,928,826,614,514,661,258,942,164,6,115,476,10,795,758,588,959,753,511,818,384,21,146,640,605,713,658,344,619,170,921,746,661,542,475,387,874,6,672,536,226,248,134,487,748,567,48,461,321,695,636,641,808,672,374,760,224,997,213,236,610,193,220,107,70,990,222,785,137,676,260,808,526,244,247,875,614,873,442,750,222,647,740,756,273,351,886,476,441,262,578,417,318,443,520,43,499,265,282,568,215,726,683,745,242,331,379,88,737,73,332,239,333,50,318,467,955,928,219,681,225,738,484,647,154,762,693,860,649,114,92,39,258,48,415,945,826,618,385,166,189,904,778,725,198,559,205,224,988,803,155,667,283,523,913,670,361,256,920,30,496,761,209,465,940,816,821,748,363,670,873,241,623,900,114,594,592,617,815,929,914,878,186,861,138,950,98,328,313,206,835,218,549,928,559,394,449,536,112,271,944,879,78,994,610,806,844,575,777,689,161,656,510,863,844,775,725,439,98,743,548,361,405,50,529,744,678,808,560,426,439,767,904,442,647,478,319,140,822,791,760,315,615,404,111,4,790,268,30,849,789,313,751,730,720,132,698,293,16,63,283,94,939,204,563,817,749,375,610,372,836,358,848,483,491,960,21,611,85,627,343,787,911,549,820,846,53,300,323,48,274,76,394,634,763,60,88,966,200,225,861,55,318,24,417,458,690,390,660,804,463,156,43,784,653,555,620,147,731,64,421,127,745,873,464,989,784,808,194,359,909,470,117,613,967,685,773,283,739,679,442,642,172,899,509,189,71,251,640,707,97,318,291,917,278,443,284,777,264,499,630,137,498,880,972,810,294,863,989,111,593,383,619,179,235,305,79,254,506,131,42,840,136,854,877,291,900,995,368,716,475,434,909,248,972,699,994,82,304,461,964,827,988,876,866,82,872,821,852,924,534,487,475,21,959,384,542,203,119,840,28,252,809,655,602,158,889,885,140,20,178,284,880,544,664,114,666,711,972,659,377,88,235,866,342,917,168,380,872,228,607,144,804,591,142,870,237,413,916,20,92,435,623,200,308,556,31,171,687,451,590,742,137,492,409,527,690,891,399,623,129,803,102,19,336,536,878,759,783,283,70,701,965,323,661,713,77,49,107,954,878,90,624,741,518,878,528,304,144,646,624,41,351,725,414,132,972,973,207,786,850,41,803,509,520,280,570,914,335,467,561,169,104,172,238,847,3,69,502,870,13,295,379,841,698,906,216,209,606,925,24,370,903,845,16,47,141,758,244,906,22,354,225,67,153,399,508,699,561,722,800,867,838,29,699,952,964,260,32,322,333,380,437,640,800,565,141,246,428,259,951,758,424,662,493,793,984,443,600,785,987,686,983,57,937,791,232,750,607,751,446,762,6,987,430,336,499,936,306,912,360,703,419,111,779,404,839,605,956,138,410,763,1,990,865,580,290,162,894,171,864,766,504,105,617,261,972,774,979,604,441,741,699,922,618,962,532,98,504,410,373,133,480,609,119,700,613,80,922,298,27,90,509,315,488,503,860,256,662,698,230,142,969,447", + "633,424,865,363,85,83,323,225,873,736,311,852,149,708,415,445,110,490,902,849,854,614,395,755,792,400,575,631,313,750,993,284,676,753,813,528,714,871,349,655,253,395,238,605,577,725,665,998,977,928,393,324,176,201,190,256,120,97,251,219,867,450,901,560,371,827,984,824,258,954,288,85,207,533,796,745,496,995,721,865,655,311,540,512,303,573,783,805,51,809,462,211,806,575,244,95,101,505,195,456,851,648,346,516,74,335,862,652,237,989,279,962,218,833,85,707,535,355,62,284,352,119,841,727,480,443,248,72,459,177,360,197,607,23,238,221,816,19,163,797,720,210,246,262,120,6,717,795,39,92,643,862,942,152,607,174,567,80,35,84,856,398,358,247,670,342,922,796,722,999,319,845,599,119,520,658,832,163,751,43,958,678,818,625,70,428,577,437,572,343,52,700,727,307,750,658,608,597,31,359,137,856,910,165,816,462,332,364,216,208,54,184,391,602,427,369,865,0,759,683,519,246,845,963,392,360,750,773,194,439,579,427,587,592,1,803,966,68,369,325,231,763,969,813,552,969,490,348,983,958,740,850,148,84,642,460,643,316,723,528,966,784,664,782,129,269,264,262,634,99,322,955,389,70,428,526,420,667,531,371,320,254,283,429,873,812,507,136,89,841,339,949,326,812,453,579,1,437,857,504,57,409,602,416,465,260,448,315,694,798,961,285,594,486,943,317,868,445,645,594,824,746,95,490,75,522,380,997,895,240,959,332,359,866,483,191,751,439,554,229,954,821,202,963,390,784,672,143,769,917,284,906,331,325,244,934,942,972,733,766,124,450,19,871,735,967,133,765,402,639,476,604,335,598,512,365,581,294,206,412,827,736,26,650,142,338,552,103,123,244,420,440,262,222,609,44,285,820,858,883,962,836,565,38,718,954,614,480,746,753,471,190,505,244,474,37,53,390,408,880,945,915,859,229,137,482,689,123,632,78,415,515,128,73,929,882,738,749,407,298,693,559,232,652,759,343,94,85,15,55,922,233,408,106,598,329,702,494,795,50,917,154,544,495,840,878,55,112,114,786,225,755,618,401,691,558,729,684,838,535,769,119,840,462,935,397,162,916,443,980,415,794,866,225,76,404,162,175,475,759,376,495,33,255,72,53,480,725,238,12,569,884,112,495,820,332,473,375,162,983,152,415,870,484,486,421,323,190,376,522,375,835,741,799,313,659,349,257,734,721,120,795,639,674,676,319,816,111,350,803,527,896,508,393,88,152,304,852,744,214,750,125,617,611,207,41,505,881,123,350,139,56,50,247,421,752,199,938,121,188,803,775,31,937,512,82,417,64,195,55,387,570,967,909,17,383,279,775,12,228,613,332,170,43,736,329,430,176,431,693,341,49,5,214,681,757,717,769,263,507,949,572,721,52,479,382,262,450,52,983,267,412,283,763,59,740,555,23,207,264,950,205,693,219,355,650,937,663,897,36,964,90,829,407,383,866,411,739,427,926,42,372,944,159,875,477,995,951,234,416,705,46,746,459,18,372,254,88,306,392,394,426,744,943,549,709,830,315,98,110,705,717,684,364,512,739,971,261,755,762,968,580,529,854,673,873,228,997,451,695,1000,656,819,418,202,430,135,8,903,86,429,536,663,634,68,798,236,433,937,12,767,672,213,674,379,28,693,627,644,386,262,770,329,718,825,626,538,850,740,363,211,156,311,686,947,708,754,36,517,252,654,510,929,499,619,956,922,283,963,725,693,405,281,706,610,209,185,122,719,616,852,708,191,470,679,471,244,885,561,319,56,329,651,827,311,64,962,366,446,608,175,737,720,872,537,643,476,815,256,290,580,116,139,150,343,195,55,728,86,108,957,590,706,522,461,633,792,350,958,246,529,136,188,614,871,475,685,256,76,466,533,881,637,633,366,963,93,998,843,585,955,539,594,953,300,380,844,782,396,634,62,420,786,547,55,148,312,808,965,351,685,164,428,937,825,399,156,274,986,395,986,206,497,682,898,857,840,576,396,976,46,433,20,430,366,837,800,831,934,909,775,638,247,994,914,670,828,381,183,895,334,481,627,448,840,564,664,108,236,548,809,392,316,300,501,747,893,35,66,850,429,881,809,566,427,310,643,327,550,896,170,370,510,405,454,390,513,944,998,557,453,140,474,257,204,29,760,804,608,4,428,240,440,160,993,506,16,255,831,660,141,378,62,520,885,849,373,791,277,196,587,558,388,91,535,351,738,522,469,501,535,347,514,41,102,367,866,543,980,123", + "897,692,45,108,254,288,297,714,660,183,731,151,232,58,345,436,549,316,406,414,501,294,654,564,177,619,265,587,895,582,275,795,25,664,456,833,685,603,99,539,468,576,284,205,738,172,533,415,133,908,311,932,426,89,405,837,443,571,732,20,312,122,892,82,41,660,257,150,776,283,689,295,650,585,637,185,613,944,660,367,266,829,871,681,486,990,988,353,249,664,886,762,417,496,936,922,298,477,335,256,732,760,158,763,740,646,14,315,407,884,40,408,368,954,103,523,452,663,603,603,518,618,476,148,740,207,939,838,290,995,149,582,937,353,501,696,13,455,434,189,527,808,728,74,852,370,502,901,888,910,251,842,269,593,392,496,432,833,467,735,267,868,528,955,731,457,628,548,813,621,719,500,566,158,527,645,912,868,672,414,684,584,299,777,632,406,35,793,207,69,580,259,636,448,517,299,289,173,765,140,404,373,597,269,36,838,50,899,809,528,267,343,685,313,730,43,443,759,0,103,322,699,699,192,907,670,733,520,891,463,479,200,111,886,438,926,147,228,488,438,639,686,40,327,795,939,613,852,212,647,859,82,890,35,968,806,165,340,911,780,125,50,870,131,435,887,224,814,301,395,790,671,459,555,846,332,873,716,10,578,214,525,421,302,520,187,360,928,703,977,665,907,636,971,8,63,462,550,512,468,332,784,577,387,235,258,462,488,532,697,654,145,117,68,365,270,902,944,643,101,477,216,49,745,443,681,410,561,803,188,851,753,578,197,500,863,304,25,887,498,831,100,536,765,649,942,181,953,471,83,579,535,783,796,440,875,983,752,253,760,369,726,898,884,49,944,972,723,802,209,671,241,478,378,323,999,489,133,852,911,588,303,178,559,19,943,668,932,674,934,353,719,450,682,844,354,256,291,570,321,112,226,337,143,242,50,798,229,879,536,882,616,173,44,811,270,625,423,854,529,289,55,471,486,54,225,664,207,516,463,671,255,371,422,620,233,862,286,15,348,763,893,145,553,300,292,270,401,965,372,866,763,985,704,978,350,139,267,373,344,968,385,78,599,63,558,660,354,946,799,147,268,782,643,357,87,681,354,655,494,128,769,192,680,968,615,712,47,51,141,164,175,281,560,427,682,336,82,45,59,894,827,456,214,979,873,815,781,854,632,169,238,58,664,42,805,776,89,733,232,280,711,664,509,273,180,280,433,313,335,328,914,274,427,508,410,693,791,15,555,58,569,968,843,868,330,162,679,611,548,170,639,596,322,643,696,75,202,281,39,198,508,688,719,368,630,786,782,558,569,923,665,941,457,159,443,86,556,270,213,518,836,718,477,258,702,677,265,121,133,833,634,811,612,760,87,413,323,660,154,791,817,86,743,904,44,37,732,730,886,797,42,790,711,732,253,818,36,780,691,759,109,336,120,722,192,287,486,391,37,458,985,551,388,27,895,808,958,913,956,898,960,774,170,626,801,894,429,744,166,619,665,900,132,626,962,995,696,231,84,463,808,154,87,600,299,481,168,943,141,953,625,52,419,744,473,403,638,209,500,768,853,701,2,712,599,290,121,566,115,881,18,901,574,522,708,277,592,22,711,724,718,603,867,164,287,221,873,613,14,443,316,539,488,590,916,810,459,599,234,793,550,778,602,388,78,881,545,541,251,749,516,33,828,27,695,821,562,361,440,463,712,811,884,291,988,749,77,756,855,101,821,568,158,831,771,948,56,903,23,796,699,259,179,149,221,679,509,884,654,147,987,95,51,825,747,884,929,887,461,42,468,780,27,427,510,117,118,183,801,37,86,543,763,711,926,709,358,523,430,10,458,474,425,907,248,864,492,784,757,517,21,144,11,171,754,340,460,763,440,575,364,796,503,201,673,81,786,354,245,410,766,213,354,58,797,235,780,754,562,15,17,763,457,346,162,548,276,365,90,55,329,528,764,327,139,441,456,238,143,396,642,9,182,84,659,360,22,664,541,458,964,418,220,149,795,875,60,984,914,513,972,692,380,52,481,279,187,711,186,51,949,164,5,978,103,950,765,82,862,863,387,152,957,78,466,743,175,641,312,512,783,581,692,636,893,794,192,12,85,882,619,800,289,348,985,758,956,538,869,359,707,898,131,784,653,181,343,456,679,599,938,664,983,776,139,983,578,871,114,318,575,686,914,787,103,995,452,574,921,191,785,454,414,319,209,53,197,402,549,282,712,390,550,33,705,470,909,310,505,986,683,161,99,70,801,60,700,76,452,918,79,175,526,622,743,768,934,869,819", + "279,958,982,577,710,284,389,273,948,903,911,66,900,356,560,272,370,72,635,573,436,137,756,36,732,809,747,875,293,532,286,128,251,919,993,292,983,334,539,264,502,639,687,739,626,456,184,221,732,964,375,262,295,146,995,750,112,229,151,933,884,64,501,322,847,460,343,24,616,182,356,796,345,673,814,477,234,959,650,357,525,88,180,131,506,578,128,613,212,495,806,851,754,827,464,923,460,237,453,503,285,457,342,554,635,966,93,474,505,325,727,18,997,11,866,410,860,210,158,396,315,70,41,623,697,745,220,724,153,42,839,798,231,248,726,426,49,819,774,89,849,22,607,318,514,9,930,888,478,498,482,300,592,271,198,403,430,262,647,394,447,270,299,783,398,396,76,88,710,17,805,833,758,186,865,118,476,967,720,501,165,602,731,88,345,852,802,709,607,849,773,981,640,899,371,605,897,525,959,4,365,968,842,147,952,991,294,890,86,678,517,925,429,681,989,763,276,683,103,0,5,491,538,443,848,849,402,411,348,806,950,199,914,187,86,343,770,846,893,5,987,623,603,854,62,430,203,359,504,342,693,773,252,583,541,432,823,157,231,610,72,282,75,823,887,412,858,479,253,203,347,371,315,900,926,982,537,15,971,25,744,234,203,610,896,276,829,18,477,45,211,538,910,454,748,116,401,477,231,402,334,543,241,775,840,235,846,750,876,40,336,133,921,440,766,251,736,26,409,774,140,351,983,15,816,877,556,953,379,631,812,907,474,708,878,88,322,957,945,699,91,773,210,186,962,601,52,861,684,652,956,355,68,760,410,939,356,268,902,609,134,200,356,744,475,625,682,6,20,781,334,116,660,131,6,365,140,882,949,128,997,78,268,649,331,442,733,856,325,443,458,94,893,275,142,732,900,129,45,211,973,310,793,729,706,836,646,4,132,520,302,936,713,552,463,894,229,485,864,626,27,315,31,570,584,478,372,12,856,355,78,121,629,158,621,129,293,231,76,959,955,414,445,928,706,501,212,410,314,429,356,852,741,872,590,903,470,273,140,335,815,253,241,360,316,107,233,809,776,461,939,800,828,671,959,267,837,440,568,178,178,804,112,386,610,354,631,252,674,242,799,472,187,100,758,631,759,967,246,282,865,915,776,772,3,655,722,787,338,285,983,565,933,211,584,806,474,457,998,450,429,343,917,95,960,750,691,930,309,602,344,481,400,645,494,382,866,303,498,273,487,748,187,425,242,277,27,173,942,881,46,816,671,821,478,808,663,392,213,359,936,117,728,827,459,403,712,767,460,780,903,164,957,670,411,80,496,744,955,446,382,765,106,74,648,765,987,540,334,177,623,619,583,894,860,718,801,787,968,213,16,399,204,460,422,581,461,873,178,533,436,645,929,163,901,437,517,783,910,247,983,330,54,308,124,415,251,855,174,741,810,49,561,427,138,213,292,384,789,131,629,189,235,585,217,247,145,894,215,64,545,100,159,863,764,900,213,190,404,765,2,498,750,228,664,938,929,163,667,232,119,71,642,614,246,656,543,438,689,598,671,99,640,358,686,299,462,661,344,718,124,920,607,697,604,796,611,71,445,801,594,921,532,188,852,171,658,661,96,505,515,650,794,388,53,77,603,208,842,836,762,628,362,399,622,146,268,173,771,666,265,61,344,703,560,509,551,585,66,462,34,805,336,341,398,375,576,835,298,705,770,406,96,198,805,620,398,911,2,734,219,798,636,56,480,898,934,491,764,744,483,989,895,566,418,718,741,283,207,185,150,518,186,605,695,338,587,757,779,53,663,790,311,589,358,345,499,304,98,316,475,612,139,521,910,609,398,300,913,866,845,777,756,552,66,155,314,716,203,758,974,541,118,607,573,467,58,945,320,579,593,205,421,257,251,295,688,672,273,558,17,469,62,259,742,349,275,969,360,541,95,227,540,689,991,450,51,12,343,380,121,379,948,510,443,710,716,136,426,689,513,639,220,814,894,299,366,636,581,495,145,156,245,811,391,443,347,120,943,109,206,854,926,74,716,358,641,930,538,990,764,209,894,802,660,372,612,951,121,994,82,15,247,488,709,986,116,329,549,532,985,623,359,993,739,696,627,646,643,516,251,229,672,114,834,144,139,638,970,232,339,431,819,258,778,722,987,52,489,554,899,530,642,545,521,771,151,283,293,218,329,319,988,867,971,759,809,273,156,986,872,771,886,485,764,976,363,149,290,798,922,13,392,754,117,726,884,926,567,603,630,582,537,58,33,614,170,805,99,784", + "760,223,109,932,100,866,483,324,695,747,300,537,183,615,932,209,315,102,370,193,102,108,643,162,551,694,529,691,458,433,461,880,985,163,347,546,651,853,146,286,269,403,345,714,251,241,432,26,598,81,584,770,37,616,787,299,34,482,641,653,805,48,797,386,104,414,987,875,881,663,288,455,49,576,328,508,88,27,155,349,858,868,621,134,928,481,523,64,909,423,261,326,725,526,769,123,213,474,364,478,609,944,294,528,684,884,520,699,61,5,865,368,413,223,697,667,520,868,567,994,688,139,339,12,18,535,146,743,642,676,613,165,291,775,810,4,348,564,884,668,679,802,275,174,45,183,666,695,767,136,639,116,294,538,602,927,72,71,992,743,599,707,551,189,769,647,204,812,594,124,20,559,904,400,604,881,704,161,448,767,161,446,701,369,393,359,751,756,969,474,638,480,387,640,283,13,889,653,770,352,768,131,787,975,958,457,895,90,593,465,710,539,467,645,314,268,817,519,322,5,0,897,313,104,322,65,378,243,688,959,947,365,398,783,164,617,630,229,680,232,475,778,388,546,242,606,990,168,951,473,939,611,312,42,658,586,384,998,774,89,365,108,656,596,897,348,419,402,593,864,172,838,934,386,390,723,580,596,146,81,23,357,896,576,81,458,199,773,114,242,148,641,536,951,666,268,822,364,224,814,968,370,124,151,997,133,669,379,138,723,865,92,559,589,248,109,215,142,533,779,648,224,131,581,248,440,57,666,698,288,773,660,806,912,433,679,920,465,793,689,1000,679,841,341,307,848,738,892,456,711,817,990,685,185,789,729,331,801,441,157,588,217,829,803,89,503,842,200,550,798,841,339,937,923,961,881,810,444,587,581,106,675,258,480,633,546,692,580,757,212,531,435,504,12,935,771,104,552,14,232,946,182,834,252,16,164,729,454,650,538,432,937,957,547,797,261,727,998,351,4,25,852,755,520,17,916,2,297,350,355,152,923,474,925,147,710,744,729,278,514,15,586,91,290,24,922,576,653,776,853,534,444,898,428,841,931,14,511,816,157,469,506,947,277,616,370,433,637,953,418,979,797,139,374,83,762,212,897,891,311,413,855,714,942,338,929,364,579,165,944,362,943,233,71,242,768,677,981,896,959,114,419,686,372,76,466,513,434,16,649,937,359,332,760,259,482,506,945,61,428,442,524,203,888,949,684,655,595,964,633,558,938,557,24,1,518,153,744,742,457,273,127,582,51,113,766,723,117,673,877,382,525,105,298,547,160,456,479,315,356,663,35,588,735,111,556,749,469,433,879,102,343,956,250,589,3,236,474,918,616,436,97,76,771,386,283,828,633,921,341,561,323,95,347,549,635,829,392,57,342,427,306,379,617,692,438,667,371,90,42,527,675,610,567,762,769,569,457,605,619,775,641,588,511,421,298,510,596,489,677,450,876,79,931,162,825,65,649,671,543,168,722,106,108,780,13,557,32,769,612,585,451,610,319,650,304,556,863,258,929,381,121,859,509,628,369,214,188,94,647,753,98,985,880,669,179,542,335,919,423,775,762,47,819,529,341,644,236,738,171,510,823,803,997,356,751,458,584,93,79,493,471,700,742,806,8,389,222,730,799,470,420,403,716,26,849,518,794,470,340,424,704,688,193,760,575,107,412,243,256,594,633,565,588,221,652,866,591,915,384,566,942,481,700,937,727,355,360,714,318,63,526,909,148,452,275,313,275,684,773,177,652,373,193,765,893,336,651,885,781,617,428,428,661,937,147,928,573,987,877,71,323,12,277,905,835,49,857,131,428,577,733,389,503,644,380,774,979,725,464,927,855,592,862,504,465,778,360,842,983,580,357,255,852,39,262,256,598,80,4,978,397,435,727,820,279,647,388,349,489,350,915,685,55,279,407,641,72,616,389,601,515,185,651,494,109,215,732,946,536,297,594,375,262,189,381,827,498,3,680,542,3,608,433,941,578,122,481,290,719,409,790,291,346,268,902,332,813,970,819,553,323,733,260,284,544,495,674,722,39,415,991,186,566,94,977,833,647,816,761,911,232,918,225,537,188,83,159,445,705,71,179,198,324,514,250,926,539,208,369,202,895,350,347,290,321,12,127,422,393,663,320,992,609,106,475,816,218,971,721,540,498,918,83,332,219,703,365,938,507,521,756,68,91,151,332,344,769,586,158,28,224,278,322,72,22,474,168,768,26,377,305,401,506,56,714,161,936,709,626,642,312,295,589,51,720,514,860,160,174,380,846,662,809,116,312,326,708,283,461", + "755,374,575,170,317,289,151,532,589,944,882,192,916,888,630,371,775,762,657,871,12,551,745,224,995,670,788,446,235,342,694,443,956,903,536,877,374,195,830,42,4,58,309,179,950,270,345,613,203,527,134,835,103,67,399,864,379,349,271,790,358,768,267,513,945,88,755,858,240,956,586,197,8,975,200,112,288,949,332,337,814,673,217,480,612,628,468,291,272,653,216,770,478,413,640,5,929,581,596,848,365,564,914,671,951,335,777,294,53,251,271,907,443,220,740,57,95,49,70,520,992,64,143,156,985,747,569,434,533,68,298,737,221,785,212,256,405,275,884,232,574,585,877,528,692,341,430,525,511,196,759,534,137,108,166,234,367,985,984,486,682,285,637,441,46,564,370,410,179,729,766,785,401,301,588,422,316,28,93,353,601,338,799,559,549,908,258,973,379,503,749,351,959,40,276,352,90,178,720,891,154,174,396,821,987,500,140,613,867,272,544,620,846,13,513,850,299,246,699,491,897,0,249,817,561,545,138,248,37,681,836,496,198,333,99,652,252,282,864,505,430,266,417,576,528,304,674,44,734,507,313,146,285,900,371,605,530,303,451,609,246,847,369,966,924,137,320,121,35,390,330,354,234,879,426,849,248,354,811,54,946,138,559,315,894,759,698,267,237,151,696,928,802,278,741,65,890,764,243,563,393,74,905,509,760,556,965,950,196,354,939,727,118,616,652,840,881,380,819,110,658,996,851,229,992,755,360,946,866,140,406,392,238,510,959,484,897,358,953,892,140,715,813,699,550,103,608,846,440,686,471,846,296,720,877,468,666,204,807,160,254,62,783,148,800,256,886,152,457,382,263,541,943,935,685,31,999,54,856,228,407,89,297,158,149,143,227,419,80,933,610,259,448,322,643,73,720,793,359,238,239,871,795,932,170,882,469,208,734,682,82,593,124,421,749,337,650,214,513,116,252,275,285,983,570,954,606,997,396,959,50,394,893,950,540,403,468,75,848,531,289,546,919,405,580,677,424,560,613,10,173,113,685,675,358,192,301,712,245,444,854,778,396,306,594,866,591,851,824,844,582,550,149,898,470,470,800,141,363,636,402,291,871,814,593,599,13,992,727,437,35,59,876,766,132,925,655,192,146,621,230,218,204,769,36,255,149,26,262,319,351,690,166,569,938,297,477,294,78,791,153,985,734,200,405,575,639,563,323,624,807,897,793,894,499,639,650,729,890,926,673,720,551,128,399,867,227,548,190,796,331,767,752,738,743,723,706,43,491,312,484,207,556,184,398,869,207,873,606,756,125,182,861,637,615,465,539,509,573,96,120,580,618,937,694,238,34,424,566,473,653,363,695,371,228,688,941,129,617,981,818,505,768,791,615,856,658,989,256,518,983,783,41,244,943,940,962,798,888,269,434,52,616,26,282,461,541,295,43,466,315,234,99,858,294,951,507,207,710,248,563,700,420,128,135,284,948,140,873,212,6,912,980,52,176,296,207,392,883,91,833,377,368,420,518,884,464,806,580,504,712,808,70,826,988,791,626,319,649,530,501,148,515,367,521,445,697,480,455,751,584,422,128,51,677,380,348,931,630,873,91,277,207,25,357,879,347,149,61,420,273,22,31,960,685,13,363,255,338,780,793,114,199,309,537,203,467,437,980,9,150,850,408,613,276,945,528,342,959,75,39,274,631,559,999,959,980,537,38,949,612,597,765,307,634,779,373,286,840,692,608,866,510,368,446,894,640,575,12,894,961,2,193,554,577,731,49,205,426,396,213,262,436,717,3,692,592,63,8,529,46,530,30,94,810,857,89,791,816,825,796,104,234,697,601,742,190,858,548,639,217,250,275,305,176,650,866,990,921,506,13,423,35,123,447,721,222,704,15,650,179,450,281,395,139,508,66,845,239,734,576,145,887,41,3,665,925,531,282,558,22,659,204,540,483,352,698,212,800,987,429,147,37,927,613,944,569,589,85,778,176,485,779,780,355,218,166,651,711,14,502,72,865,835,266,153,390,567,805,286,436,415,456,953,716,826,906,463,89,430,317,455,992,97,913,187,407,819,581,560,29,859,243,459,444,924,896,747,933,578,694,129,245,15,795,701,630,860,839,620,268,691,288,345,838,936,662,701,450,402,736,840,914,369,791,121,681,163,13,956,434,868,10,413,738,899,198,229,460,353,97,241,739,736,724,481,17,956,736,1,483,741,234,468,431,289,506,515,710,484,971,369,114,274,258,590,177,784,618,518,608,614,603,379,605,914,277,983,385,196", + "101,929,320,241,239,828,569,228,81,880,402,881,943,120,189,361,99,762,138,940,683,411,668,805,604,818,563,764,414,269,562,334,366,775,61,742,258,440,766,645,172,632,125,339,811,277,677,23,826,250,240,29,969,482,566,136,29,565,816,541,243,190,34,9,329,253,704,251,355,749,713,200,587,434,626,561,682,257,138,198,465,511,310,726,875,672,568,283,843,644,166,413,679,382,126,280,671,451,245,44,287,539,565,992,416,427,990,966,94,838,349,165,13,852,779,460,24,262,407,375,604,844,464,518,627,415,936,930,223,413,386,607,963,754,396,479,123,978,881,429,679,512,379,354,464,99,389,949,150,17,663,726,268,451,541,229,699,703,792,841,686,798,413,896,621,99,111,533,805,557,835,675,264,354,980,912,704,639,15,883,222,379,806,213,911,485,572,486,791,703,348,904,617,760,751,458,858,292,636,13,629,179,164,253,740,812,285,634,596,232,951,353,649,422,586,74,525,845,699,538,313,249,0,232,372,60,78,417,703,400,789,454,930,798,727,451,474,169,984,417,772,33,806,72,860,154,821,473,644,316,242,767,963,858,734,85,960,311,288,327,967,650,862,332,138,121,234,160,758,851,909,10,793,377,174,433,654,407,51,704,573,941,12,744,853,404,831,654,392,650,986,946,156,505,537,86,901,992,541,204,84,402,273,973,850,8,136,506,912,154,574,639,430,794,395,26,13,41,265,103,880,592,232,97,62,635,237,149,833,784,197,695,11,802,225,399,486,828,716,862,628,93,320,515,25,442,724,268,190,631,499,858,290,690,252,160,705,787,360,539,324,422,988,968,489,133,848,121,789,362,974,789,512,92,423,853,205,243,584,971,315,39,458,292,176,398,780,321,922,804,225,197,202,390,465,73,188,508,232,274,911,52,332,688,112,996,862,910,610,404,702,227,701,779,484,75,818,584,629,273,478,630,607,571,318,713,928,355,946,922,53,881,760,287,126,612,504,792,683,419,647,998,533,102,969,476,758,611,684,542,958,54,871,877,363,985,434,449,820,272,434,922,799,231,519,774,73,139,677,70,312,254,878,390,700,854,52,73,830,582,786,55,184,500,459,365,611,181,268,224,809,999,31,989,477,865,348,226,370,902,237,412,550,993,60,595,681,225,121,984,588,624,706,112,413,839,932,415,243,522,40,216,990,259,54,809,292,327,142,555,471,196,534,260,563,516,93,511,997,877,81,592,622,405,265,682,366,495,270,941,881,934,497,745,377,513,636,961,198,907,887,212,594,138,259,624,786,22,706,377,456,388,152,257,542,801,483,997,370,679,250,663,554,5,993,998,510,108,355,909,414,447,191,231,51,294,578,983,572,31,106,287,869,476,964,591,573,297,270,511,898,159,962,366,650,419,969,846,120,987,955,699,618,806,725,376,293,344,126,973,608,540,141,933,158,542,701,231,882,127,243,106,574,811,538,20,385,102,143,536,403,508,161,187,768,188,337,484,362,425,512,161,129,315,46,682,664,859,7,438,990,263,321,715,617,821,889,233,216,386,436,564,870,690,454,63,109,623,655,611,43,193,189,650,779,340,37,892,163,926,562,41,195,101,810,841,541,932,972,937,823,128,474,881,43,55,551,380,476,829,849,732,436,974,592,752,241,449,377,607,445,791,379,810,216,300,172,560,252,231,384,667,325,911,964,573,122,214,320,257,361,432,791,499,347,424,671,860,354,579,179,772,102,790,182,896,726,875,347,795,94,41,517,139,606,799,653,818,510,675,988,914,442,891,572,303,484,882,32,94,799,468,30,172,662,332,227,656,975,578,740,439,101,930,429,410,50,617,404,924,770,634,686,957,460,267,835,874,491,538,135,159,639,927,850,564,10,250,458,81,962,191,220,211,477,169,672,54,894,522,259,206,320,963,971,70,277,455,550,543,239,15,351,174,288,73,689,596,613,911,312,535,876,229,635,348,271,963,934,227,758,269,827,333,704,337,525,517,332,907,785,653,643,500,705,566,213,705,946,384,668,540,394,345,673,851,650,328,50,938,414,960,122,278,918,839,463,658,464,819,69,638,812,743,804,995,233,996,919,336,874,809,765,263,300,910,89,236,160,584,658,519,603,694,188,558,606,838,659,955,234,974,606,205,98,177,631,175,565,590,589,276,889,458,49,432,46,101,956,659,630,462,194,200,620,106,794,101,652,38,991,991,512,600,315,242,393,316,863,643,123,49,938,77,154,288,894,529,761,609,424,332,638,667,108,685,197,6,917,430", + "37,828,879,733,471,859,529,819,54,324,442,421,257,815,160,625,423,16,795,468,878,678,113,381,640,30,913,388,405,592,430,37,830,804,685,305,903,692,352,706,641,873,643,818,275,755,493,1000,753,529,84,73,86,468,291,904,127,222,689,869,22,332,964,696,971,796,732,128,196,284,676,180,631,550,558,634,817,235,336,658,564,640,33,188,334,479,41,18,44,935,295,770,43,378,205,354,560,235,457,297,889,175,822,91,662,513,477,4,604,800,908,692,570,66,464,936,290,475,289,667,590,537,619,753,934,467,849,355,951,856,425,778,334,593,531,258,876,946,978,663,482,787,123,810,860,133,446,677,337,521,539,895,277,991,588,383,798,45,553,975,64,761,382,692,701,325,126,751,50,186,536,783,220,196,659,614,51,371,711,698,607,560,741,771,224,731,853,817,180,763,952,648,89,188,492,324,134,719,773,406,496,160,169,602,583,600,186,242,948,203,101,267,720,357,962,202,474,963,192,443,104,817,232,0,420,462,801,385,335,176,146,668,367,652,931,650,645,740,430,702,308,186,453,492,326,721,20,264,473,663,882,778,416,357,244,800,936,98,221,677,145,994,598,599,4,107,413,887,127,711,80,599,898,181,704,77,549,667,867,734,639,779,388,575,878,431,181,443,949,939,236,33,878,13,176,627,259,188,722,216,951,263,704,258,911,41,347,814,272,255,678,770,851,396,774,838,667,631,994,906,628,819,354,432,414,334,795,169,229,972,985,814,305,406,586,117,576,598,888,476,118,208,477,375,306,672,18,490,748,41,2,26,934,407,409,869,135,384,396,235,986,326,920,492,80,376,328,543,767,399,546,750,296,912,639,157,59,166,48,549,104,303,960,367,583,373,888,560,505,382,177,109,956,794,354,465,73,339,941,82,783,353,300,314,853,987,677,958,653,931,439,542,125,723,91,964,309,896,875,712,767,747,729,538,944,688,197,519,580,159,482,210,109,954,869,657,487,319,482,785,852,63,853,35,679,589,505,126,521,222,264,767,864,265,593,617,714,298,762,87,309,773,334,574,877,178,272,69,678,215,996,307,469,26,175,224,656,869,527,338,509,878,653,898,369,75,498,887,644,97,161,925,585,567,224,252,417,482,309,303,696,636,898,454,880,76,979,330,403,201,298,807,479,114,127,74,907,880,634,196,277,477,177,670,218,840,994,121,560,884,840,240,96,383,859,65,233,249,536,694,366,103,850,315,110,770,782,269,338,860,246,496,806,394,142,331,887,373,412,36,776,415,420,912,798,129,316,209,399,261,276,820,130,607,194,169,22,120,766,964,828,517,725,919,752,412,456,755,657,825,857,253,990,235,322,771,816,876,427,84,239,481,527,491,497,829,449,524,72,819,750,273,4,712,303,969,322,88,627,677,67,599,303,346,899,190,372,811,884,304,640,492,347,395,15,134,263,577,718,929,830,130,666,139,882,126,945,550,797,894,902,737,165,349,432,990,836,24,394,595,191,390,461,642,796,430,721,234,524,77,817,163,118,636,265,723,220,33,820,61,190,217,174,231,727,662,29,352,701,466,892,153,589,400,419,294,71,25,872,660,731,792,695,77,421,205,309,783,6,847,968,160,414,80,202,719,577,339,816,437,56,977,994,769,863,848,278,970,434,231,368,790,821,448,894,461,907,579,383,471,411,774,677,659,271,932,509,234,52,777,649,692,501,502,902,530,807,573,18,628,994,865,962,762,763,291,687,756,17,851,515,151,832,736,273,509,818,185,397,749,159,804,919,62,342,221,834,539,591,142,599,321,729,673,27,21,505,544,129,99,885,822,817,269,624,216,104,568,643,123,79,237,965,370,232,222,650,700,847,876,271,122,603,670,383,434,619,485,969,180,755,122,924,982,241,724,892,168,867,289,365,333,459,235,618,515,296,711,242,294,249,162,689,571,130,236,148,556,977,858,196,772,863,367,555,120,113,829,622,479,627,114,32,864,347,896,550,373,559,301,61,665,382,973,405,582,578,8,502,759,331,457,718,879,638,508,619,67,452,308,367,35,205,232,99,610,322,338,723,40,362,302,712,217,553,475,1000,450,373,372,385,460,410,14,810,881,828,555,587,249,725,205,305,759,114,44,522,989,783,322,691,720,427,93,309,43,118,145,142,180,131,413,326,879,853,559,419,35,958,259,474,889,728,997,308,439,488,93,814,189,438,585,631,605,564,659,261,53,392,984,350,86,601,489,193,198,334,455,42,888,7,359,284,832,80,404,813,52,101,627", + "769,450,331,500,217,732,292,588,718,820,805,920,953,324,393,559,812,11,520,404,655,37,29,34,771,184,614,396,501,612,632,172,679,697,558,86,620,68,131,207,497,865,413,714,476,743,111,725,878,739,825,557,251,251,216,358,14,366,352,197,888,131,589,923,872,501,392,789,661,824,938,865,796,349,626,182,608,8,57,953,435,587,788,778,513,971,978,632,539,939,257,308,866,971,82,789,882,472,302,138,807,116,877,290,993,45,335,837,89,622,77,764,435,391,407,899,59,237,55,473,5,729,699,958,971,186,139,584,795,814,369,686,981,612,824,940,237,657,67,50,968,500,420,813,48,207,488,257,92,497,85,371,903,267,210,487,538,937,200,999,825,320,174,49,445,332,129,473,540,224,395,964,809,146,375,60,345,53,456,652,823,402,3,229,7,917,706,400,825,671,510,15,339,880,624,722,190,110,318,89,538,340,712,583,199,434,375,925,589,462,432,137,85,842,837,374,593,392,907,848,322,561,372,420,0,94,513,348,251,634,236,367,384,337,467,259,499,140,813,40,751,887,781,191,17,703,386,476,586,690,36,570,603,917,223,749,467,91,310,864,694,985,424,516,952,991,571,241,349,520,731,280,992,313,907,959,26,918,246,471,683,932,136,590,518,251,426,559,454,699,364,646,8,675,495,730,59,390,147,469,436,32,349,361,277,475,649,456,599,53,805,33,937,314,741,651,851,300,955,617,404,24,825,825,734,500,615,1,659,114,454,264,619,9,708,872,125,265,26,465,833,6,114,569,661,316,405,595,184,798,26,229,910,461,525,187,686,777,512,554,883,874,969,345,511,383,50,556,6,670,934,543,213,767,626,201,483,838,386,465,788,109,539,664,753,493,278,613,894,80,104,908,349,191,183,829,7,330,691,121,574,691,176,115,195,601,204,611,84,111,400,465,202,740,393,81,895,8,693,16,588,227,778,707,924,894,282,4,828,139,151,308,193,948,993,418,953,245,42,798,708,572,193,868,610,235,991,761,846,86,373,692,524,361,41,49,757,970,654,291,740,687,167,434,925,130,830,944,425,636,755,154,186,754,256,610,280,958,865,908,301,795,922,131,701,527,493,100,325,184,578,705,839,389,34,438,888,628,529,25,843,806,920,148,148,33,817,837,236,199,346,967,244,160,924,114,638,696,564,122,584,336,614,186,75,278,859,4,682,580,529,1000,335,125,782,225,871,610,319,359,361,976,255,715,229,529,961,11,495,409,164,830,320,781,168,635,655,781,109,550,481,351,370,971,383,579,271,278,549,930,438,477,99,314,69,376,715,295,861,665,251,811,493,532,260,63,508,585,120,982,696,653,769,274,689,165,99,289,382,846,339,787,356,931,487,453,119,936,65,79,418,362,321,660,598,773,143,665,743,979,779,2,759,852,747,602,898,451,341,868,801,610,17,108,815,640,158,478,684,604,343,541,622,754,267,338,191,835,257,445,714,527,348,214,792,141,636,768,570,472,361,652,290,483,809,308,254,235,448,623,121,655,30,842,790,690,847,118,259,452,928,166,732,555,831,518,364,18,138,317,997,616,61,456,247,125,946,406,252,415,368,328,407,289,746,294,323,713,88,734,884,186,306,204,829,643,228,181,289,125,265,755,867,233,697,381,580,489,621,987,109,581,516,406,96,149,497,314,433,776,165,986,549,291,386,676,307,533,390,337,864,175,88,354,533,865,653,155,510,398,851,337,336,911,650,420,174,715,55,452,454,128,134,520,394,86,26,698,765,585,303,687,969,786,109,759,138,97,760,43,100,80,289,997,111,179,499,229,273,841,65,549,374,567,247,859,800,390,16,707,112,908,400,698,312,170,973,592,396,879,149,929,386,114,656,771,551,957,811,744,478,404,220,669,734,391,836,107,565,995,258,427,594,818,215,903,891,361,278,469,44,307,106,249,635,583,879,883,995,824,304,908,804,440,960,674,552,345,965,859,842,777,452,798,381,999,344,503,274,278,130,448,109,514,589,904,738,387,322,761,523,810,503,943,623,836,245,908,777,210,980,528,615,284,775,837,466,722,171,925,354,834,741,193,432,100,287,265,954,564,240,331,193,667,458,592,605,232,468,837,506,420,819,602,930,754,115,295,455,825,188,477,158,808,428,591,153,117,61,377,952,190,151,886,985,815,708,207,65,482,673,830,126,521,898,227,322,223,324,835,512,997,669,865,288,19,358,763,247,305,807,64,948,640,424,174,740,666,607,502,129,617,883,682,987,755,845,532,20,883", + "460,465,990,357,966,853,298,784,408,773,102,487,108,718,933,62,864,639,629,567,324,51,129,873,232,136,94,712,528,84,848,197,913,603,930,445,565,268,394,58,365,112,320,334,945,73,129,531,940,648,531,600,247,873,792,982,207,126,964,544,986,562,289,549,467,437,271,637,554,850,30,524,725,197,489,371,437,127,871,270,395,92,107,379,313,388,440,257,944,889,883,751,664,392,869,553,689,34,82,747,132,243,226,23,334,679,292,437,482,895,21,680,527,673,899,752,416,832,379,601,859,538,604,489,339,940,252,553,464,522,67,730,612,21,532,299,731,708,116,511,838,604,958,575,801,460,316,21,656,544,71,617,123,232,710,919,351,298,238,119,187,959,175,751,423,501,424,589,372,234,55,446,626,12,143,341,90,551,453,653,132,301,224,947,830,767,693,349,684,492,597,985,269,466,786,937,924,703,826,721,207,966,150,112,121,812,83,41,167,43,401,628,802,336,65,837,570,360,670,849,65,545,60,462,94,0,641,918,470,870,352,375,458,867,675,303,270,407,350,578,746,530,678,198,588,349,334,122,532,325,340,724,729,705,994,157,211,45,980,466,26,992,538,120,710,319,585,108,919,539,158,23,948,904,627,165,306,102,774,493,706,679,871,73,769,563,586,934,188,616,508,924,675,424,761,195,957,329,619,965,208,425,894,50,2,438,508,882,137,404,35,264,473,126,37,151,212,758,108,575,706,563,727,735,360,439,161,291,969,619,104,123,849,144,816,283,24,241,901,848,612,466,975,883,784,164,530,590,282,253,508,815,875,868,7,18,626,18,716,739,910,352,314,9,409,292,219,428,230,671,287,3,818,840,246,162,270,720,594,132,656,231,139,854,975,400,501,210,30,279,259,982,814,189,349,191,972,268,397,528,955,420,248,214,786,720,788,685,33,276,358,229,195,100,151,982,281,95,111,591,841,747,855,133,481,258,893,627,671,437,639,412,214,264,477,377,490,963,343,834,97,391,63,917,225,936,248,617,893,361,784,509,884,733,532,277,110,304,184,704,207,453,381,230,324,888,20,670,110,827,636,316,529,187,29,490,215,711,341,9,591,177,550,35,818,444,988,898,141,305,503,218,481,259,923,772,244,131,240,362,583,672,469,788,32,138,995,881,499,732,601,529,442,889,863,748,760,89,530,38,274,134,275,505,123,767,393,934,29,947,821,441,464,141,272,237,691,359,115,42,186,907,139,640,374,475,639,840,548,45,984,59,743,973,820,246,674,919,137,57,824,30,272,857,303,484,316,205,193,296,505,205,42,33,241,208,706,231,772,989,910,524,416,674,659,898,447,674,205,474,219,18,455,647,31,985,198,7,61,406,566,543,281,791,529,634,850,751,625,730,544,77,124,44,185,272,758,761,165,463,893,266,636,236,296,531,772,377,238,705,204,247,975,978,285,397,582,106,748,627,785,25,703,408,159,83,761,24,170,232,535,959,602,29,393,723,689,965,434,645,468,444,525,452,320,389,145,18,672,641,820,808,849,135,586,630,637,717,866,216,603,557,167,701,313,64,753,569,142,898,816,191,485,861,834,8,232,620,479,825,797,599,991,89,887,949,198,147,683,947,191,789,57,802,220,245,693,615,567,77,138,405,352,90,434,743,496,329,324,609,384,328,441,311,336,703,889,210,540,740,915,2,801,365,543,743,833,950,711,642,412,798,140,838,766,185,369,750,312,664,847,199,941,272,793,896,787,844,43,871,375,992,32,543,100,309,441,85,59,287,867,51,871,946,966,590,97,565,491,10,677,12,498,727,273,699,785,53,331,217,829,592,160,430,561,765,97,847,554,263,874,846,41,308,785,921,733,154,581,282,635,365,549,778,581,32,627,574,237,933,366,207,528,614,682,390,248,468,84,263,222,302,124,261,754,536,96,699,551,744,824,126,218,704,908,337,552,969,86,948,122,739,454,370,670,223,525,289,502,209,388,804,103,104,523,968,822,54,365,319,156,302,203,72,215,653,18,851,783,838,860,524,568,844,109,981,791,930,464,991,926,846,549,670,39,24,983,672,224,688,934,937,586,953,865,431,587,679,869,134,424,787,369,134,388,4,37,922,219,252,988,977,821,338,349,871,544,984,204,429,103,120,259,160,900,907,527,777,778,208,890,94,692,43,27,958,160,618,93,786,124,290,501,980,526,583,860,131,801,668,511,562,52,151,435,32,944,973,384,423,22,825,728,887,957,246,219,278,195,133,79,48,426,128,71,958,36,867,954,260", + "252,411,887,200,557,816,569,99,135,395,764,354,750,333,371,193,837,957,133,675,242,808,382,417,766,955,80,211,377,80,334,561,478,107,793,870,614,496,547,506,168,499,278,678,447,551,89,400,763,126,411,240,492,266,673,867,241,166,229,58,405,450,842,992,374,67,513,171,267,180,357,498,472,597,876,280,354,193,386,29,760,868,663,804,649,273,685,859,93,228,402,423,404,16,16,144,94,691,460,64,114,419,230,34,74,937,896,82,989,74,203,952,727,810,443,682,829,812,16,329,493,852,359,7,672,799,912,277,817,745,475,972,994,852,354,170,60,415,210,293,807,638,787,641,557,444,804,387,446,864,875,961,906,590,597,637,184,935,346,174,339,274,146,834,253,143,187,908,622,532,101,456,801,697,38,899,859,187,20,511,484,224,629,837,704,219,609,621,429,980,123,530,10,606,400,286,824,981,483,187,504,636,373,981,5,525,646,604,40,797,24,925,878,644,55,830,383,750,733,402,378,138,78,801,513,641,0,624,250,997,676,415,49,673,123,168,613,760,17,579,965,139,670,312,777,985,380,105,898,268,695,627,520,794,724,209,523,92,111,415,140,434,990,152,167,593,990,351,790,956,650,703,712,31,528,640,424,273,946,871,22,402,611,299,452,990,168,489,156,160,970,952,83,431,578,65,137,846,121,357,419,663,277,80,209,57,927,827,665,447,152,760,341,926,460,536,712,761,873,998,757,844,232,716,744,352,60,81,944,712,91,313,44,404,585,365,51,647,363,157,295,761,690,939,959,595,8,70,4,27,147,215,879,797,210,823,746,811,182,171,572,670,940,382,297,881,56,50,478,96,559,224,99,443,193,161,406,910,631,415,520,41,459,56,855,658,130,998,373,882,52,768,292,64,15,762,130,61,767,451,256,961,472,57,853,501,659,829,215,498,109,713,705,73,489,537,824,996,523,360,422,432,734,458,149,909,677,983,380,430,858,271,122,258,907,555,606,218,300,218,267,270,917,878,834,734,550,792,125,158,253,645,76,532,210,479,206,356,954,730,583,383,951,743,803,600,517,833,475,949,4,990,718,861,922,570,347,881,178,439,878,83,518,421,143,784,184,349,149,423,957,990,971,715,994,346,314,326,31,20,420,475,767,224,113,892,286,173,134,277,413,920,197,337,268,259,102,287,815,529,658,509,513,237,169,114,677,695,331,183,991,606,226,787,876,608,901,634,598,162,744,946,220,772,367,44,253,666,761,858,915,770,665,683,240,557,727,491,875,512,147,639,228,676,294,774,454,675,595,709,722,570,714,220,206,875,409,133,468,381,132,507,406,966,38,332,233,939,601,328,947,164,240,80,20,383,161,407,407,3,70,647,194,9,278,923,965,584,715,847,948,802,850,826,452,794,88,144,91,461,808,518,291,25,170,348,476,177,516,298,622,400,530,806,917,353,183,546,325,342,644,220,753,338,474,136,798,860,509,251,931,551,178,417,811,53,701,978,289,71,695,992,476,889,445,156,255,388,578,290,497,438,175,858,343,442,700,757,782,306,681,444,710,20,14,369,466,273,335,393,722,578,88,892,608,198,756,545,149,694,911,767,951,276,387,861,780,536,83,17,893,118,280,206,726,470,96,716,203,347,676,86,785,745,231,181,540,536,762,468,784,972,232,991,501,999,857,399,757,31,132,198,90,694,322,778,992,91,547,839,10,165,956,762,808,716,878,73,333,263,9,523,870,158,738,255,101,552,39,506,186,903,779,825,537,11,333,640,651,312,297,333,459,624,293,452,321,143,21,612,609,701,639,368,998,425,400,544,962,150,486,344,546,283,922,225,811,245,692,554,190,191,666,907,538,805,939,378,26,95,670,40,771,541,542,899,502,580,594,731,190,819,997,78,189,270,879,987,92,419,825,267,577,755,669,709,319,800,52,74,794,131,326,99,157,514,969,697,55,554,356,622,717,471,37,21,882,174,603,198,890,352,598,980,462,112,300,19,915,782,809,435,260,738,653,953,496,486,692,109,950,252,87,19,372,46,878,851,38,149,959,8,438,705,286,21,604,144,175,183,666,69,913,319,587,867,373,77,200,389,415,678,175,680,331,984,828,671,516,242,199,702,625,411,188,159,794,332,972,961,274,120,697,594,910,144,260,91,323,413,858,851,811,589,653,289,794,903,80,879,16,737,553,225,644,382,860,519,515,486,226,392,430,264,660,841,156,75,581,583,424,555,679,659,128,704,156,987,186,3,607,262,487,493,718,108,588,198,126,956", + "869,75,921,713,263,481,270,727,697,676,89,240,326,44,856,825,582,36,864,711,660,828,424,500,649,632,148,23,257,683,163,663,410,962,500,917,43,947,387,606,648,835,208,294,702,300,920,954,989,785,204,944,815,671,503,437,775,515,172,305,332,484,359,827,37,662,777,521,621,73,832,666,30,817,728,901,800,398,141,316,173,858,805,391,510,238,804,595,832,991,301,196,219,79,987,42,445,191,431,268,178,756,511,826,840,859,765,551,20,335,324,273,757,137,408,502,119,266,81,94,328,14,878,819,768,234,645,95,345,835,739,719,292,22,818,889,552,982,791,19,449,404,85,1000,857,551,822,322,469,572,490,440,278,608,920,160,445,221,391,306,710,406,876,750,248,546,285,719,797,427,776,283,414,178,315,518,369,658,253,150,656,831,65,303,437,874,649,123,423,399,188,759,327,138,829,913,894,722,393,863,494,592,106,823,126,773,469,462,906,320,108,487,665,807,101,796,136,773,520,411,243,248,417,385,348,918,624,0,731,129,493,586,38,903,682,357,654,277,575,659,932,231,267,26,877,83,241,137,305,999,156,407,316,53,116,898,166,608,664,592,900,95,875,847,174,983,833,485,308,947,500,748,625,135,498,832,115,30,143,227,856,232,648,817,849,796,229,247,52,602,750,380,677,467,650,708,731,728,306,230,863,237,984,516,820,281,480,608,407,453,165,601,295,748,479,812,825,441,874,129,356,990,21,99,956,404,648,579,352,432,722,464,66,316,504,823,2,958,794,681,586,607,325,35,116,21,336,361,539,748,893,887,688,863,690,296,453,771,433,71,855,73,86,680,12,551,283,590,678,222,492,940,476,265,496,772,530,364,505,335,347,671,624,175,773,818,434,354,284,939,629,911,313,376,824,414,702,798,801,197,315,481,786,148,842,863,917,805,859,124,335,811,436,519,801,98,108,229,695,153,842,701,492,891,788,48,846,300,607,375,25,821,757,195,229,889,710,882,866,263,570,75,783,98,640,491,598,199,585,301,152,883,521,900,721,340,989,693,962,2,640,384,349,956,913,773,937,983,979,255,700,291,831,738,869,900,424,302,379,847,317,296,729,369,854,825,242,810,615,589,349,313,63,198,509,34,310,890,344,813,19,13,27,583,921,392,218,533,606,379,28,66,510,117,227,688,579,179,700,761,105,147,668,22,162,411,613,678,954,475,878,375,886,229,413,255,85,535,430,798,421,984,65,339,620,597,695,441,672,525,785,390,919,732,557,515,554,731,545,189,696,273,694,151,440,263,208,490,609,971,204,895,699,709,56,645,813,63,844,493,965,908,642,89,651,846,241,219,59,501,428,946,384,354,623,839,485,518,160,457,861,592,11,499,907,298,24,707,699,780,888,71,166,182,706,503,690,690,770,830,214,303,970,720,506,918,832,123,791,321,645,4,19,404,841,318,351,361,707,124,528,230,319,854,442,629,766,364,573,921,696,488,38,833,436,503,504,130,730,181,379,891,995,906,728,993,398,275,12,484,934,465,683,891,737,691,526,997,720,420,417,828,292,48,218,933,126,355,748,642,322,720,316,209,701,650,887,119,730,92,577,257,682,633,309,545,273,214,75,132,57,351,829,118,837,307,998,421,417,523,772,898,494,371,768,758,739,831,367,722,852,157,14,608,964,741,576,132,959,537,21,544,388,890,877,49,375,788,406,502,251,918,231,693,248,551,398,448,948,655,153,739,930,318,507,142,18,376,233,711,51,395,2,477,8,320,312,368,938,50,12,987,438,241,308,487,11,400,583,546,53,515,810,100,167,932,873,861,338,374,506,253,179,451,356,722,181,637,110,192,696,162,104,430,111,993,265,987,119,6,192,100,706,238,214,436,879,400,754,526,104,758,24,236,117,104,119,787,525,150,676,332,885,710,613,938,574,894,326,219,722,996,426,169,889,253,931,490,746,10,857,660,630,652,842,395,445,236,364,156,536,715,846,873,24,770,797,414,595,985,786,809,262,426,861,583,97,207,915,854,992,483,990,788,285,196,3,432,194,975,501,721,341,490,607,593,395,290,978,400,328,493,860,100,400,214,679,67,429,63,817,19,31,558,712,601,347,261,83,865,213,346,827,230,686,804,252,601,297,53,727,567,570,48,868,998,300,98,41,836,340,838,853,484,81,353,854,330,784,746,382,101,931,434,963,509,589,250,548,496,397,527,834,8,711,577,519,13,767,434,112,368,960,504,605,740,834,392,495,674,124,746,239,724,524,144,138,506,402,882", + "700,199,368,503,433,776,942,574,926,435,91,58,454,996,909,813,44,326,237,464,72,19,858,482,596,996,629,187,952,745,262,26,878,218,269,75,408,373,885,177,778,491,20,320,53,755,917,365,427,787,406,84,802,650,385,681,982,403,579,79,989,834,60,670,760,968,275,763,570,962,760,425,833,738,132,103,812,154,963,449,307,5,983,102,742,84,862,600,740,835,204,881,862,194,318,657,42,260,934,450,623,706,876,701,902,178,122,724,378,456,599,276,507,920,79,100,49,500,89,674,467,531,370,31,104,667,449,738,25,394,794,258,630,562,191,287,832,131,902,762,4,163,593,786,671,722,133,446,266,235,969,149,193,152,5,384,43,706,554,897,919,353,602,611,914,429,102,188,296,901,98,960,195,154,363,992,399,666,361,137,378,196,220,229,609,571,853,85,132,668,879,231,468,835,571,932,528,482,731,705,271,28,636,956,736,450,170,461,51,436,202,627,20,985,374,511,727,194,891,348,688,37,703,335,251,470,250,731,0,210,33,138,699,281,980,750,801,782,87,452,700,407,619,947,307,662,90,46,694,644,474,149,963,336,195,639,80,737,432,364,267,664,513,406,825,202,151,881,593,530,712,485,328,58,245,952,614,692,467,650,840,666,986,592,780,186,417,287,979,786,884,776,755,308,206,961,947,102,519,796,741,739,743,653,791,32,343,128,215,502,950,960,325,61,285,838,28,193,508,583,977,697,486,838,854,114,25,228,176,96,743,822,597,389,49,853,940,77,26,96,580,594,282,529,222,306,478,260,721,313,884,230,415,316,580,646,781,605,196,132,268,180,668,521,111,174,501,994,118,552,906,932,474,457,852,7,555,193,984,364,231,856,577,218,280,805,882,299,730,380,975,340,915,71,395,489,889,818,628,342,715,402,759,646,539,640,891,287,41,372,361,968,94,226,816,217,937,739,643,660,401,714,162,290,660,911,404,512,456,585,285,640,35,452,994,11,960,613,396,467,86,55,44,295,43,372,633,894,50,167,565,27,376,387,149,285,522,285,490,792,303,431,569,78,846,731,557,980,203,917,379,568,385,388,330,989,831,918,847,901,83,191,109,839,699,796,493,937,100,767,604,577,866,628,813,555,963,422,335,152,378,458,17,959,756,760,947,774,429,720,457,642,779,993,877,440,528,568,771,342,844,588,818,151,455,961,833,538,364,108,776,689,25,244,639,842,90,676,321,964,740,496,766,931,332,858,151,632,583,885,784,871,223,968,616,632,417,902,929,41,551,188,569,125,286,605,563,101,291,707,19,83,101,910,165,224,302,597,495,993,388,266,780,223,543,4,223,233,316,255,885,118,120,632,549,797,757,184,268,971,232,67,773,951,72,979,765,94,796,773,979,582,960,680,254,349,497,166,574,797,393,697,175,72,949,538,332,675,494,976,927,508,130,867,250,481,869,371,889,386,700,758,216,307,234,230,827,970,485,695,808,16,665,761,890,36,265,985,308,392,54,683,9,702,592,615,936,850,835,22,213,464,392,400,949,722,866,329,760,368,559,860,63,884,902,153,288,713,685,884,724,434,157,565,497,909,445,361,802,634,241,653,921,115,219,876,481,706,222,711,497,550,265,782,992,725,623,594,252,252,65,993,251,125,813,71,973,360,226,772,685,124,840,259,516,397,892,978,738,407,209,124,993,135,126,651,810,112,729,855,385,870,766,695,100,443,547,920,259,739,394,558,149,940,667,925,470,199,756,217,834,591,830,475,499,130,440,222,597,408,741,501,366,342,668,862,598,64,108,409,886,151,715,363,330,601,747,394,132,158,876,163,883,606,298,597,171,658,289,701,555,344,433,207,469,294,156,639,108,924,372,490,13,427,394,376,300,411,556,535,608,941,973,756,835,377,869,460,170,730,260,987,336,346,293,945,62,290,961,285,238,526,540,860,686,198,492,969,452,763,422,837,727,306,86,265,378,703,709,443,125,491,91,710,406,831,183,546,91,52,211,377,362,727,685,603,988,815,167,511,426,490,969,92,506,67,480,995,946,431,713,722,700,285,559,637,182,670,874,109,581,741,210,511,809,957,315,998,107,804,42,539,947,87,582,370,509,908,789,947,743,562,772,426,507,32,974,862,768,838,751,902,797,64,6,528,954,716,299,494,841,897,192,868,164,339,711,311,317,974,112,676,330,42,629,236,33,404,885,415,372,794,295,517,405,967,421,876,147,865,88,867,696,369,12,681,261,269,94,917,313,94,359,553,58,828,978,817,141,747", + "182,145,294,588,940,586,671,839,581,637,847,859,652,809,844,83,641,603,731,42,119,424,327,831,519,141,93,582,887,654,156,196,313,140,715,430,616,907,885,501,637,314,165,638,927,858,515,585,656,483,819,570,825,348,205,764,796,795,894,289,912,318,980,756,197,482,501,165,924,152,4,572,700,778,539,140,209,254,131,458,762,613,4,351,368,972,682,678,933,688,17,810,233,246,787,121,429,362,528,161,246,17,716,804,507,466,569,569,715,952,899,108,109,590,506,21,734,465,459,802,596,489,406,836,388,947,856,828,952,416,330,10,321,862,423,479,564,271,636,588,886,171,829,299,804,645,303,753,657,251,81,838,759,171,300,857,377,484,471,333,554,772,426,506,284,79,891,79,306,747,926,615,272,681,251,625,739,953,442,527,31,57,203,161,489,156,480,296,638,410,773,428,766,155,387,782,251,965,518,122,67,410,305,218,792,75,505,811,134,575,84,725,260,273,463,866,19,439,463,806,959,681,400,176,634,870,997,129,210,0,381,797,620,202,74,840,171,743,138,427,545,660,660,148,885,966,433,768,902,975,823,801,866,305,376,866,642,973,39,603,510,748,352,691,689,90,70,240,817,442,293,526,553,451,340,729,932,723,112,311,780,871,523,924,603,847,274,883,92,932,715,909,863,642,692,276,39,42,761,180,241,793,836,628,262,390,16,89,916,173,1000,786,5,898,538,27,1,818,660,785,639,99,711,601,694,631,717,234,289,275,296,647,26,624,430,999,145,591,794,575,73,631,559,999,468,640,570,495,608,999,754,274,936,950,370,901,140,257,599,15,969,302,468,19,833,276,4,819,678,719,94,363,357,138,998,180,269,375,707,350,9,304,671,647,599,239,693,851,428,758,478,388,468,27,664,45,978,685,951,587,212,295,730,572,532,291,779,848,880,897,828,190,392,269,778,104,563,89,158,763,648,64,742,917,694,120,434,435,210,531,938,86,767,814,473,89,677,585,253,220,530,637,276,884,541,208,13,145,895,434,478,161,135,397,399,328,236,81,485,225,57,325,887,228,935,578,815,122,961,322,577,201,550,162,576,774,139,849,642,581,734,808,618,311,912,580,224,491,835,713,521,467,450,249,727,724,754,607,246,860,246,439,177,868,296,224,513,364,217,784,149,713,386,231,82,480,178,792,314,122,722,230,108,891,267,662,352,600,163,972,768,639,419,386,725,324,998,491,740,513,538,445,322,897,791,335,568,816,306,931,69,463,1000,308,916,947,930,847,216,152,405,57,594,882,645,948,484,313,449,566,394,315,319,416,760,226,402,98,300,97,629,908,211,688,137,961,289,879,427,652,432,663,466,964,191,640,569,622,821,833,2,66,446,816,905,97,825,164,679,714,814,869,225,726,783,686,271,269,181,308,511,369,581,888,94,195,320,784,94,969,370,393,621,5,144,403,510,588,708,187,629,360,304,348,147,750,153,257,292,648,531,129,433,565,842,146,970,428,110,562,417,106,369,246,439,985,234,370,292,675,813,83,545,912,737,472,963,461,121,732,226,115,665,250,780,571,840,689,230,215,47,216,994,442,396,568,559,874,222,209,635,437,317,326,959,864,471,81,870,184,742,413,579,119,518,275,273,250,933,571,955,622,801,347,54,487,506,23,598,172,83,890,404,154,986,537,182,283,968,615,776,886,479,545,357,636,840,54,827,256,955,977,146,548,439,332,717,818,303,967,499,718,433,987,438,648,736,659,324,30,962,783,459,898,501,418,36,636,303,69,877,273,734,13,612,622,184,415,71,354,20,488,253,863,807,65,244,523,220,726,287,587,889,871,552,492,614,376,950,833,475,306,970,429,650,13,16,66,204,657,962,400,62,383,237,755,481,42,583,313,177,913,975,916,790,830,854,841,223,736,933,633,140,476,10,835,368,793,309,285,121,36,114,837,520,160,834,641,743,581,575,448,912,46,173,503,672,7,901,506,338,932,395,265,499,895,868,892,57,214,824,623,740,479,706,712,653,827,503,930,13,899,272,417,202,728,963,202,616,522,462,444,396,854,850,296,802,744,495,647,543,59,901,165,669,914,571,373,104,989,202,22,846,821,454,714,524,275,682,393,230,218,743,708,238,189,176,998,461,940,126,142,899,904,547,730,849,472,479,738,247,106,204,759,714,476,203,248,928,331,434,867,622,216,212,905,765,857,918,985,929,497,622,345,610,357,602,873,74,389,708,534,7,686,739,4,615,401,593,661,717,833,601,207,399,76,874,813,573,861", + "507,705,743,513,597,175,785,948,527,505,808,61,382,145,423,955,812,107,806,905,418,178,110,537,26,434,72,774,908,253,146,911,532,59,327,796,60,826,976,176,53,629,356,901,442,909,346,107,660,607,214,871,88,21,185,299,548,319,756,223,80,63,671,439,114,479,852,52,843,783,245,846,988,711,652,819,876,434,794,516,524,934,991,737,337,358,739,274,483,679,157,394,988,214,671,69,199,637,877,549,447,859,641,912,462,270,423,553,138,94,860,697,531,404,739,775,96,530,395,972,815,518,211,642,179,154,750,322,894,986,627,893,656,64,667,418,121,75,377,305,932,652,336,774,603,181,515,727,798,808,875,84,834,528,809,182,542,886,895,311,898,464,892,889,891,280,129,179,544,138,23,507,993,937,182,195,477,167,470,288,848,686,756,440,221,595,786,213,404,429,397,341,409,179,267,36,637,113,137,66,608,150,94,122,413,76,444,948,600,355,452,414,718,663,355,339,602,579,479,950,947,836,789,146,236,352,676,493,33,381,0,139,23,833,745,359,455,482,615,745,849,766,486,237,399,786,956,528,637,660,914,318,397,204,711,576,658,845,215,634,839,285,615,142,210,504,963,140,191,432,299,21,923,74,701,711,796,40,826,775,27,991,22,886,268,817,674,89,183,166,566,176,1,140,798,320,159,238,464,248,734,47,72,805,594,708,447,644,959,688,294,968,204,950,685,792,875,46,415,470,823,947,742,778,108,716,153,66,143,563,366,996,227,655,57,371,926,703,850,279,202,750,609,273,812,569,734,394,905,676,71,40,423,73,563,176,538,926,400,414,953,980,390,60,280,841,103,939,657,751,399,139,618,932,438,137,232,821,876,931,887,4,362,451,225,529,771,665,438,406,759,94,72,681,393,771,810,112,796,390,586,206,653,436,984,273,873,334,889,611,865,626,411,579,795,296,860,456,222,170,961,801,37,961,889,989,118,33,303,111,225,437,722,755,381,190,32,744,976,561,64,721,939,774,408,174,32,149,962,341,340,627,579,183,894,706,10,7,8,110,416,881,237,627,257,981,852,911,699,629,844,336,516,935,510,108,73,984,733,81,498,268,473,508,882,253,794,201,724,195,497,772,418,33,284,121,858,728,891,830,921,473,27,287,898,758,161,493,587,4,638,799,741,364,350,154,766,97,806,914,685,777,452,559,370,988,57,784,712,8,339,534,101,168,214,717,149,155,21,857,510,109,937,241,297,551,866,17,350,759,973,131,685,223,712,334,980,327,112,420,639,613,55,452,53,510,270,966,152,432,287,528,810,783,456,943,194,628,656,853,33,998,127,667,65,554,26,135,208,940,614,178,463,385,497,282,764,87,304,84,203,936,869,209,654,302,578,602,349,952,968,314,764,882,233,561,231,751,711,859,329,954,545,904,596,869,29,77,989,705,164,371,405,471,117,337,598,29,893,910,34,695,521,260,315,887,873,245,157,884,686,480,5,286,525,453,556,877,868,876,944,163,390,359,989,684,333,872,785,119,442,195,63,533,342,924,285,822,527,56,253,641,978,938,410,623,325,785,869,829,689,66,219,234,243,817,38,345,853,79,55,36,575,87,267,7,389,707,507,545,684,14,779,223,851,50,172,416,31,291,59,712,175,2,895,983,952,176,37,401,190,540,724,378,940,632,759,389,848,173,948,370,900,614,685,646,654,305,884,472,717,833,325,91,463,568,6,159,904,377,262,365,141,93,781,167,639,258,256,318,901,51,789,830,977,353,348,384,867,890,416,681,485,468,931,543,757,252,930,871,93,43,618,879,486,677,227,261,404,978,84,28,79,963,691,816,299,971,81,74,663,446,383,970,744,536,75,381,940,80,36,811,811,176,500,383,893,872,481,25,629,22,347,931,991,392,395,153,430,477,994,667,348,679,491,810,934,243,771,617,50,758,310,55,848,935,932,632,812,680,926,327,612,22,858,378,135,562,174,412,421,599,834,734,551,976,277,364,834,886,429,4,955,797,111,355,814,97,147,12,905,351,758,670,526,829,218,629,923,594,321,146,130,795,120,637,583,755,542,896,2,500,765,851,71,280,776,634,174,619,716,789,153,785,683,761,829,940,832,572,912,835,696,718,523,495,335,815,485,455,811,528,983,29,164,689,547,517,678,311,251,736,859,952,223,757,34,357,546,179,127,790,540,668,329,734,170,637,110,647,978,845,831,451,806,18,839,922,6,113,358,827,398,474,277,435,673,617,524,549,112,932,657,349,946,237,913,378,919,452", + "389,227,78,833,706,168,569,234,309,729,110,174,618,441,998,814,895,428,973,689,212,638,912,226,948,292,289,730,769,855,764,121,132,109,10,204,201,270,694,421,884,246,221,430,252,418,711,853,44,22,236,137,447,180,491,248,148,307,763,576,274,245,881,203,343,285,93,556,478,449,459,78,665,814,579,318,303,672,668,274,701,121,908,996,948,310,61,570,501,345,369,571,548,256,572,851,317,43,306,898,572,706,444,353,579,378,398,820,695,797,775,94,439,747,898,530,367,447,937,314,274,635,287,499,155,400,801,977,295,685,49,417,861,276,460,909,274,995,730,889,457,639,822,400,61,920,646,249,788,928,731,570,243,39,265,985,266,761,843,261,777,574,385,903,837,592,782,827,62,897,64,463,968,261,364,514,887,53,110,479,43,511,260,665,120,134,945,788,550,874,310,457,713,372,836,969,171,923,377,470,26,580,11,450,671,885,247,373,78,414,819,218,970,954,370,735,256,427,200,199,365,496,454,668,367,375,415,586,138,797,139,0,441,962,243,585,134,265,319,745,730,239,493,933,711,963,92,854,401,982,71,711,422,42,887,885,392,570,806,293,763,573,639,874,975,16,753,971,141,149,585,291,59,514,698,666,897,806,657,309,552,94,13,547,155,614,150,378,316,818,830,991,283,810,628,884,576,849,705,417,756,721,836,149,431,795,489,348,818,598,175,280,709,353,776,491,168,602,348,783,488,635,259,872,704,260,25,976,400,75,559,855,915,731,775,201,893,385,105,143,485,699,266,716,476,738,457,700,898,171,212,551,83,65,153,86,67,244,540,457,541,103,307,864,533,425,597,411,995,615,908,236,867,176,355,877,645,564,42,436,376,671,126,532,635,590,560,663,157,749,838,219,752,985,9,567,515,260,31,308,988,410,335,933,91,204,615,372,783,180,833,458,679,35,21,222,472,916,216,979,859,32,715,122,77,781,520,188,124,485,550,85,88,441,484,901,57,417,854,359,175,958,861,341,480,965,541,207,350,559,335,142,342,753,657,906,350,881,109,167,873,308,257,152,132,967,771,613,817,959,106,170,551,10,54,582,622,455,784,264,632,3,390,680,414,473,84,390,560,227,401,29,661,540,867,188,65,391,724,303,677,913,315,273,502,99,585,748,855,10,716,63,187,448,808,123,643,505,399,104,737,326,102,134,323,84,718,815,550,549,821,676,16,263,794,599,150,504,859,465,990,867,498,109,990,736,607,617,168,409,512,999,154,965,793,792,495,181,687,637,49,174,923,998,60,221,139,226,836,964,254,766,77,182,546,323,976,405,657,127,890,711,173,159,8,741,580,676,812,856,645,856,795,377,763,241,199,209,763,572,89,15,491,773,969,691,626,468,878,698,488,322,637,497,573,932,363,497,38,796,427,858,767,88,870,668,347,417,267,840,534,972,956,985,913,813,715,69,321,817,636,246,414,160,175,865,513,114,289,762,654,409,856,671,756,955,251,457,832,123,788,36,536,479,917,841,838,21,760,952,938,302,951,756,253,537,155,121,716,22,891,535,179,636,434,155,481,93,864,274,183,724,624,588,789,879,287,231,437,214,452,611,726,452,144,996,777,87,28,558,961,765,760,605,91,655,234,438,44,620,224,478,814,112,161,720,584,805,24,187,891,285,397,94,85,616,452,145,836,911,18,935,795,882,639,507,988,40,638,58,208,176,159,636,366,275,772,716,73,903,199,986,812,289,746,955,275,272,900,883,863,116,737,530,255,334,360,267,278,886,37,855,252,890,201,63,768,827,254,939,875,819,662,139,522,11,119,15,986,593,399,978,729,297,286,616,495,175,136,188,170,121,41,692,400,697,539,599,832,688,562,491,385,601,867,993,628,889,646,202,751,28,281,93,122,747,825,319,6,299,784,684,770,776,535,498,696,37,405,828,60,936,906,807,405,415,533,5,622,279,692,884,482,779,535,369,985,512,186,667,428,877,268,657,374,56,725,76,494,470,586,968,151,819,588,859,565,627,955,769,467,349,960,316,671,845,805,955,550,626,332,976,765,803,801,372,938,7,555,253,299,103,473,375,756,132,517,651,660,225,511,418,476,496,331,675,803,940,658,773,929,239,64,790,22,61,720,999,823,730,26,919,742,504,661,265,471,807,718,655,789,299,774,691,47,167,859,459,260,519,372,411,734,367,176,501,953,740,552,751,629,380,970,311,97,749,852,541,250,135,394,173,710,900,518,937,39,167,242,760,92,865,205,325,348,369,810,542,549,255", + "263,66,415,440,38,591,805,389,884,232,311,385,136,106,301,429,853,845,478,580,132,438,592,159,255,69,694,916,206,427,631,768,142,473,649,165,510,771,59,539,157,74,339,331,681,729,552,92,230,896,569,840,726,635,535,57,56,39,25,572,441,745,330,312,404,954,32,847,413,532,958,644,537,29,783,739,924,209,561,776,331,228,176,942,576,413,842,331,316,124,162,495,200,217,286,952,741,117,748,643,867,473,375,999,396,262,357,359,283,94,408,925,857,6,27,681,301,919,250,976,265,179,661,768,437,891,356,552,811,753,173,136,284,824,147,549,99,976,744,158,760,105,142,989,445,906,512,43,922,41,246,706,136,442,674,563,489,931,41,923,868,394,4,142,810,819,318,398,920,730,704,157,226,296,835,887,881,984,464,367,42,436,688,755,24,284,625,811,237,426,815,10,447,348,837,528,154,269,792,775,895,40,478,126,576,857,587,330,404,736,134,303,205,56,303,19,601,587,111,914,398,198,930,367,384,458,49,38,699,620,23,441,0,842,620,236,927,994,102,53,801,579,238,433,344,854,7,429,891,736,841,996,330,461,579,999,902,854,996,71,464,599,289,178,93,502,300,956,8,153,320,451,968,609,623,875,637,826,149,317,598,30,794,861,176,607,29,280,739,745,710,169,598,216,513,245,848,839,454,142,41,673,76,525,246,851,602,510,542,458,915,847,692,418,968,234,422,284,483,650,573,522,249,315,668,575,587,696,295,833,684,634,393,825,749,512,98,995,724,596,504,928,489,779,685,291,304,314,587,716,555,675,359,153,890,858,225,221,925,277,238,148,178,580,244,695,212,789,763,334,913,243,120,399,71,21,248,74,752,432,662,533,311,3,845,963,978,109,344,631,700,688,149,592,837,796,574,611,145,885,124,945,148,625,894,481,162,819,796,619,858,868,347,597,84,64,225,444,179,898,25,115,19,123,583,197,854,52,416,95,432,574,987,21,322,646,863,870,312,351,558,71,816,374,343,995,379,29,23,352,740,478,839,105,943,569,259,175,104,917,122,655,195,266,54,412,152,449,19,897,32,98,891,939,406,851,308,222,288,735,419,113,902,385,295,491,759,178,877,648,449,558,801,783,575,497,729,505,338,934,803,381,902,349,54,819,134,339,100,263,909,695,613,697,494,653,436,317,229,490,518,881,640,289,21,402,302,111,268,256,456,483,226,13,385,3,66,850,970,426,192,638,762,21,446,785,568,554,359,399,929,319,47,404,272,97,582,433,622,6,122,364,950,61,971,108,985,258,760,536,263,113,822,501,923,581,19,815,415,999,510,272,375,140,769,4,844,630,967,522,712,244,63,200,134,628,880,541,507,885,83,282,197,239,625,173,727,414,604,925,610,803,842,132,666,387,347,599,831,627,164,91,145,642,173,917,527,612,314,439,13,592,221,782,547,406,447,339,673,611,727,296,47,763,199,590,256,949,583,123,703,507,804,133,994,684,157,871,568,537,947,935,309,187,249,523,669,151,78,591,723,347,498,579,665,359,288,63,181,559,72,460,228,946,464,203,292,475,916,840,819,674,536,891,538,597,287,90,545,72,23,546,769,301,22,440,250,397,418,93,209,627,329,314,443,515,414,33,371,891,113,798,842,518,230,126,145,261,940,88,620,823,492,265,97,340,493,775,855,744,949,406,941,199,141,940,870,839,910,117,923,948,164,945,132,181,259,230,652,623,805,563,607,409,691,850,848,637,830,889,198,664,289,485,965,378,727,953,516,898,54,535,662,457,146,101,62,955,460,356,69,234,729,405,669,340,369,945,626,64,723,844,515,347,131,469,940,27,894,767,489,15,543,393,803,713,390,890,110,132,89,422,786,826,39,758,516,859,994,979,837,172,89,293,46,238,659,981,246,152,538,766,906,428,666,378,754,42,762,498,203,869,600,902,376,267,511,905,455,345,555,949,666,420,942,146,336,586,71,261,405,470,73,952,882,826,131,651,383,662,569,995,985,763,668,889,761,136,266,492,169,954,87,216,152,610,44,39,795,826,912,583,830,837,338,301,87,852,251,317,74,4,478,694,285,475,5,322,540,528,83,249,407,484,18,539,353,532,376,394,888,49,959,209,106,632,942,73,748,902,413,993,580,597,780,518,263,217,73,916,155,104,577,640,551,613,997,519,363,760,990,899,872,457,423,487,463,160,653,196,138,452,599,445,351,295,913,157,90,359,62,342,406,312,737,95,994,669,727,897,432,342,44,842,508,429,544,626,482,324", + "88,620,23,189,330,206,232,326,887,145,977,73,870,40,201,679,725,444,166,213,783,332,511,489,430,542,813,623,239,841,153,930,96,528,618,767,826,292,898,636,618,315,812,852,213,676,85,395,999,764,638,465,566,40,191,538,453,261,18,944,727,884,882,566,101,587,652,362,971,977,371,441,77,204,133,676,184,580,651,258,796,664,411,872,329,70,23,147,10,205,905,930,18,89,994,316,608,692,623,245,78,764,603,905,107,784,266,947,964,900,858,184,530,618,174,130,872,776,282,437,326,941,521,368,784,664,761,285,662,828,780,841,131,313,165,424,309,569,700,886,194,818,256,577,141,716,786,699,942,547,598,4,903,657,347,307,281,32,591,296,699,385,918,225,467,675,493,330,823,129,624,694,784,179,187,275,728,724,571,810,300,511,461,114,355,897,461,105,761,826,395,629,493,842,742,803,358,471,996,94,539,109,191,143,596,901,424,225,570,249,588,894,307,970,598,739,504,592,886,187,783,333,798,652,337,867,673,903,281,202,833,962,842,0,582,496,953,101,350,965,573,778,43,179,634,594,142,578,640,496,837,687,945,837,6,307,544,113,784,138,145,548,588,33,854,858,42,893,47,256,417,495,282,936,172,523,40,286,165,920,896,957,208,744,443,663,759,541,175,424,399,387,650,766,235,370,406,662,576,690,860,361,406,282,880,48,747,164,982,500,154,760,85,780,216,369,631,518,861,4,512,288,752,53,447,360,629,19,341,238,105,829,666,348,630,841,909,717,815,328,406,923,732,315,580,64,144,891,195,179,854,642,213,507,151,340,675,660,36,369,713,560,40,606,825,639,441,954,569,173,173,395,868,453,805,561,399,990,640,14,296,40,337,250,860,639,768,511,779,862,52,508,908,711,377,309,828,70,76,583,190,210,339,740,329,15,329,458,385,204,788,594,476,861,683,659,671,639,784,42,253,707,109,87,527,458,215,898,74,433,169,75,497,156,461,934,297,299,554,180,531,129,823,23,426,109,242,713,995,603,456,947,308,859,678,954,657,835,949,599,825,870,586,787,619,246,915,722,848,424,47,33,219,601,56,97,227,24,861,319,851,810,624,947,502,824,858,27,411,40,872,209,519,756,204,714,439,198,477,896,364,352,896,145,106,971,61,40,223,463,45,377,883,332,424,346,573,296,92,626,143,900,339,742,617,816,999,584,547,492,992,749,213,129,199,744,852,508,544,972,645,73,335,528,834,620,439,632,213,341,941,473,972,289,827,78,698,213,862,300,836,104,566,826,512,910,302,18,948,131,398,200,511,651,750,948,60,944,392,909,794,996,16,121,577,282,300,343,137,703,449,322,687,324,596,666,930,135,372,835,302,909,886,926,771,514,814,679,150,137,275,576,203,435,18,180,200,894,138,611,45,840,853,326,212,323,368,188,619,448,677,222,714,73,370,606,365,76,178,907,486,743,250,433,254,862,517,804,280,238,592,417,895,380,234,758,543,335,398,220,414,997,463,887,880,356,628,125,72,185,720,142,130,717,761,716,8,25,396,675,526,745,184,389,659,554,700,379,433,706,292,263,274,534,659,767,717,506,848,227,292,100,138,543,826,225,348,710,993,639,833,231,734,935,698,266,851,193,575,608,612,923,88,278,663,591,255,245,295,350,72,729,483,591,11,588,913,569,86,267,589,3,874,354,16,663,100,624,354,607,290,861,796,871,736,89,403,926,24,827,479,317,406,366,844,22,116,896,90,99,811,908,806,438,142,665,944,73,383,824,987,650,538,33,599,89,506,40,849,612,70,419,316,951,328,385,555,575,813,718,474,810,561,118,341,622,70,985,182,388,713,319,402,990,307,298,412,382,974,249,670,276,404,37,337,899,539,139,427,180,956,596,302,680,874,324,546,937,537,238,164,830,758,586,78,706,750,114,341,828,880,859,98,462,916,928,112,790,173,897,171,280,440,319,454,69,17,897,118,57,726,324,231,240,295,300,677,864,315,34,102,426,168,726,242,42,566,654,278,74,704,391,613,515,516,848,955,339,275,815,946,366,687,675,837,491,336,568,819,623,852,517,644,754,793,670,121,947,684,807,364,181,719,520,130,897,578,700,388,773,498,76,726,851,847,573,4,727,446,618,999,526,459,719,913,450,570,612,541,709,773,778,628,3,693,253,812,216,135,514,292,448,664,951,4,138,628,394,808,819,822,740,49,370,160,471,129,11,616,680,686,581,847,389,757,333,737,695,134,402,228,549,990,188,744,855,669,914,438,627", + "291,982,434,241,856,784,328,594,512,282,927,644,184,451,319,570,276,836,932,387,266,149,65,219,80,565,811,721,883,527,146,856,359,990,597,745,23,219,823,35,477,464,817,4,403,529,390,825,754,778,904,621,270,431,43,65,810,680,241,536,416,963,916,170,814,479,873,586,743,741,493,27,114,417,986,354,761,652,132,591,76,180,387,865,691,260,675,825,863,803,457,780,917,965,322,521,429,579,659,759,26,112,418,117,302,780,751,403,541,254,919,821,69,55,223,265,360,426,537,170,154,5,553,703,362,266,487,495,333,375,726,505,282,740,550,739,631,50,713,12,148,381,233,111,862,311,67,886,772,483,548,756,44,251,162,749,113,322,474,337,770,224,237,653,412,246,595,7,783,933,350,255,53,372,673,85,430,22,159,116,466,523,508,433,92,905,587,506,597,16,288,222,146,334,19,65,348,431,553,150,110,130,694,446,347,848,773,343,597,849,751,332,32,320,771,535,160,1,438,86,164,99,727,931,467,675,123,682,980,74,745,243,620,582,0,490,99,101,331,138,681,223,977,56,967,747,895,699,319,673,992,217,745,320,643,296,904,528,400,35,619,482,10,473,594,531,895,450,457,122,424,829,370,778,562,475,925,62,799,292,947,786,53,868,390,223,679,529,571,694,749,400,477,592,678,977,568,771,145,888,687,761,72,521,209,683,606,616,380,600,235,586,220,492,56,929,975,646,999,862,823,619,84,708,386,179,168,959,558,866,468,742,853,636,971,567,697,211,802,438,523,872,814,280,379,886,148,461,267,712,281,279,157,615,536,266,331,838,614,151,7,258,25,698,4,219,532,835,498,425,341,249,393,640,293,41,67,111,945,27,142,299,961,873,561,745,312,53,937,406,595,89,102,595,508,183,672,477,828,700,188,846,994,645,11,16,385,649,218,419,648,245,376,13,718,295,130,309,872,376,174,343,176,843,503,403,414,975,152,828,982,653,960,913,297,561,396,441,967,55,233,225,190,461,809,624,386,102,4,743,175,897,650,447,921,563,444,208,629,181,174,562,112,746,643,702,919,745,561,955,741,825,414,271,108,852,882,171,529,311,303,918,433,20,123,895,918,54,293,420,373,61,392,357,883,464,523,992,519,320,449,862,657,703,651,282,647,269,80,740,779,658,813,930,806,729,105,428,308,554,148,345,784,466,729,544,152,461,644,928,216,926,917,651,731,999,679,448,53,597,873,392,579,857,439,577,885,54,341,788,53,357,373,35,785,131,106,377,63,844,779,637,902,762,453,877,308,909,383,967,317,917,594,241,221,951,225,115,916,94,535,278,852,763,420,607,492,785,985,824,717,260,76,325,783,90,985,36,876,893,162,176,867,102,449,507,65,708,238,859,32,13,398,762,711,839,378,78,924,779,744,191,974,199,634,58,58,503,910,82,894,65,725,930,43,804,728,524,378,719,503,537,903,432,120,659,802,734,185,431,233,34,581,651,923,957,154,419,803,432,215,999,792,198,538,944,671,865,565,481,695,645,144,505,715,343,924,807,160,314,488,901,266,449,611,92,525,667,339,266,806,330,992,16,879,970,933,18,262,454,42,720,438,329,794,217,572,824,133,489,946,192,30,221,153,383,799,992,751,651,496,197,883,420,336,3,57,426,785,853,8,599,973,932,862,730,727,487,874,186,15,780,271,485,397,829,903,702,237,470,737,831,719,665,3,993,709,76,566,529,210,569,361,970,852,653,350,581,471,656,582,304,432,139,785,301,949,643,825,308,384,892,775,126,956,651,763,749,35,124,83,319,789,874,108,885,216,702,999,651,559,729,652,846,296,103,645,44,837,951,319,937,228,384,395,317,877,857,369,657,720,812,419,861,536,463,106,777,714,628,328,213,516,785,575,787,305,575,634,979,643,480,44,165,260,627,434,37,165,192,535,261,44,796,408,756,100,990,411,622,80,916,323,878,67,768,811,8,132,551,462,29,504,615,160,307,382,376,434,198,15,875,165,353,374,554,254,566,15,67,709,16,15,329,308,311,144,313,261,82,363,401,453,543,122,830,670,216,623,141,369,358,790,533,138,332,394,793,244,686,636,37,158,347,74,12,493,904,850,314,906,999,862,83,81,157,417,682,998,872,24,488,30,58,692,456,34,731,767,345,748,49,449,39,141,487,437,579,475,643,656,432,5,968,11,342,184,357,242,855,731,167,118,143,869,925,304,94,889,10,95,385,488,687,156,760,597,572,293,396,703,746,259,986,866,901,617,30,657,644", + "885,33,618,10,790,533,315,396,715,353,702,570,920,445,39,439,463,578,15,684,505,13,77,211,960,883,150,784,974,573,554,379,410,515,410,839,832,935,39,968,555,540,525,493,245,840,375,543,928,574,55,171,493,813,370,441,361,175,621,478,7,714,688,848,223,312,314,730,688,678,978,482,794,189,527,400,837,314,193,789,623,782,890,422,238,861,722,627,380,81,115,499,787,124,30,276,305,729,539,946,866,580,419,644,259,766,568,715,331,523,688,782,961,118,751,541,347,323,242,631,360,217,463,185,384,717,411,815,819,991,654,397,384,314,41,701,912,938,726,701,80,459,135,875,6,440,260,33,596,575,958,557,485,404,443,863,583,559,452,429,547,292,649,486,600,943,217,597,895,419,265,514,325,522,148,704,548,856,255,678,259,22,319,752,482,787,743,682,520,471,799,303,361,930,697,649,366,390,424,919,738,181,262,439,235,435,267,105,577,669,922,460,75,934,990,843,744,803,926,343,617,652,451,650,259,303,168,357,750,840,359,585,236,496,490,0,588,141,853,283,718,955,864,663,996,32,304,459,857,235,304,416,552,18,685,840,138,448,919,482,778,976,973,674,11,755,927,328,967,97,283,70,43,851,106,637,812,980,523,66,708,425,994,544,831,961,681,473,378,563,256,584,191,92,171,148,513,379,508,689,401,785,545,885,940,262,943,107,804,725,639,643,801,130,729,6,62,982,31,518,697,249,741,968,332,516,555,674,968,671,596,985,692,797,973,57,303,996,50,864,604,866,425,386,575,22,66,84,187,346,492,39,33,784,727,130,112,55,362,855,207,319,742,182,99,384,762,632,331,682,410,532,502,213,861,519,738,92,911,62,67,798,970,38,592,776,724,478,78,302,251,192,500,663,830,580,199,654,545,169,309,750,955,168,541,790,982,678,747,239,205,696,972,337,216,127,966,318,494,429,79,308,27,280,57,189,893,628,688,889,154,482,145,630,513,605,779,13,697,69,381,200,905,83,386,383,989,689,87,881,701,631,813,210,805,775,306,123,759,900,27,442,655,466,438,111,534,582,916,508,790,452,331,654,926,981,611,9,403,997,451,171,370,889,945,745,713,439,741,700,718,643,786,179,739,369,70,87,230,628,121,93,465,469,962,880,115,153,670,999,359,211,733,447,421,347,521,866,549,53,662,506,386,846,585,779,175,21,406,934,356,981,338,303,779,104,635,891,157,987,612,989,274,965,833,507,244,512,489,341,568,762,929,904,49,548,978,14,237,831,882,190,362,703,744,630,685,866,894,234,478,65,165,584,269,444,565,124,270,327,925,124,388,105,695,30,4,536,673,685,713,742,589,69,254,628,470,538,913,16,939,38,18,789,947,982,778,225,47,462,671,748,922,572,728,426,45,17,511,615,259,615,440,528,268,129,681,947,79,651,998,441,662,687,769,495,115,378,51,576,523,679,554,552,953,931,276,176,85,475,237,558,813,187,145,868,721,686,555,767,808,4,621,577,390,240,120,337,411,507,148,256,398,817,664,855,29,110,652,395,1,155,209,439,638,584,646,768,989,534,442,277,972,797,749,432,935,99,986,683,664,354,206,935,301,1,784,89,325,647,613,119,752,736,225,205,326,207,892,20,943,737,1000,102,520,374,831,85,669,641,87,620,946,549,862,798,521,297,287,273,94,913,348,199,100,293,567,661,112,314,607,103,787,932,422,732,913,986,907,824,80,744,828,303,791,907,434,84,282,535,79,143,430,699,227,169,885,304,665,343,94,666,109,507,848,851,917,372,204,501,683,138,861,9,348,132,687,392,812,163,473,188,694,103,772,179,863,760,533,192,869,253,466,88,726,208,208,826,134,172,249,371,130,498,927,682,279,266,381,378,909,722,47,232,731,778,986,257,373,745,703,678,845,74,625,505,512,255,881,381,403,283,19,67,439,440,628,685,312,886,349,980,252,11,155,516,887,680,211,881,469,372,444,435,927,206,176,421,619,666,415,128,723,939,104,845,156,792,787,186,250,635,471,642,808,672,743,834,253,595,113,16,557,10,289,461,731,768,848,977,574,486,270,795,269,827,242,365,641,786,586,306,586,911,764,452,496,769,704,476,815,794,121,507,330,405,305,653,39,154,78,767,676,150,677,286,287,160,874,204,698,873,367,274,381,13,382,490,949,254,224,75,785,761,258,911,839,87,304,956,737,940,500,784,630,605,775,592,738,512,402,571,676,31,643,59,911,275,411,326,487,605,528,835,233,365,746,563,267,642", + "106,317,22,210,509,541,966,467,381,322,260,154,194,450,14,716,212,744,569,704,225,665,645,732,514,925,393,787,383,818,860,87,593,108,785,513,710,158,786,200,641,832,439,743,344,799,715,949,751,188,349,559,77,807,628,803,631,420,344,594,783,688,807,911,505,983,247,447,317,842,948,751,938,280,895,162,258,887,652,36,285,163,828,116,511,622,34,218,798,262,70,216,918,57,444,55,13,755,666,252,946,456,333,524,646,460,893,317,214,390,578,257,900,725,584,586,101,38,988,501,675,150,363,6,502,631,178,987,76,153,688,918,904,156,994,780,23,863,303,326,675,421,412,890,897,383,50,916,637,558,879,785,888,864,575,355,658,305,196,460,975,295,401,49,446,368,690,400,149,741,659,393,337,643,753,749,125,916,497,634,953,268,641,146,177,800,771,857,648,567,322,186,332,313,18,489,432,932,613,266,57,844,6,891,635,947,457,441,750,633,159,319,597,290,794,479,185,966,147,770,630,252,474,645,499,270,613,654,801,171,455,134,927,953,99,588,0,652,314,888,488,69,750,445,988,902,322,126,581,453,244,236,546,645,430,549,904,574,938,866,745,156,605,444,878,246,543,117,860,654,787,337,635,156,391,918,228,307,9,85,47,101,13,848,318,602,710,510,440,282,280,317,516,370,567,519,521,664,442,784,422,712,330,685,120,415,599,338,781,153,469,332,868,133,355,301,563,805,113,265,72,99,220,560,837,516,684,5,733,189,762,171,738,856,626,900,488,940,14,731,352,554,8,453,584,168,199,429,116,759,777,79,559,902,610,747,831,344,689,325,267,299,519,907,172,532,142,720,443,575,867,331,221,827,296,96,756,261,662,797,564,772,216,668,319,343,220,738,19,841,375,881,208,557,817,394,946,128,695,433,838,393,318,916,935,33,608,25,594,680,984,133,101,260,216,385,715,863,836,303,530,748,531,408,498,327,718,89,443,971,735,277,139,458,785,193,925,155,646,798,474,805,886,731,580,607,308,517,879,545,821,884,358,149,683,363,105,709,284,667,761,375,361,327,740,115,265,857,195,12,578,461,4,870,373,192,637,35,201,157,279,224,888,469,91,476,937,81,744,519,140,682,674,46,907,995,307,296,277,617,666,815,389,240,818,275,125,271,771,145,412,562,634,688,283,925,863,87,651,939,93,51,375,589,58,257,231,403,99,422,594,500,378,391,297,956,43,971,237,55,204,573,220,223,595,677,576,27,449,937,72,680,68,955,374,636,643,462,581,727,326,495,723,225,261,295,789,841,429,301,863,889,600,233,856,187,129,547,78,49,660,233,782,388,979,315,627,912,908,527,504,314,630,233,171,577,867,580,188,870,549,253,260,132,976,404,703,141,275,812,335,647,333,329,630,206,36,188,244,704,641,277,986,300,481,192,755,423,147,373,42,583,989,787,677,907,862,967,673,504,384,549,279,294,178,16,462,208,3,362,143,966,185,992,596,685,451,393,770,3,108,683,379,593,508,803,834,590,690,548,18,902,829,288,258,487,894,251,663,950,801,751,99,323,38,473,320,63,732,272,621,88,817,906,132,288,324,239,885,767,146,56,590,89,397,790,955,94,707,810,836,657,640,2,299,376,403,298,473,418,163,600,713,319,357,805,134,730,818,327,209,720,219,343,367,870,707,903,580,585,5,289,737,197,744,768,785,596,796,511,635,651,192,720,494,126,394,150,854,550,475,462,159,547,422,509,401,457,600,792,595,152,764,864,409,170,475,39,470,217,131,114,721,906,691,667,690,227,720,900,367,594,548,936,935,713,386,12,563,184,616,884,234,543,808,814,558,655,692,407,70,580,505,314,148,190,303,902,673,511,94,907,105,513,808,389,820,249,374,182,74,622,390,791,258,340,320,527,702,410,523,465,728,99,604,161,293,356,27,430,689,88,473,664,443,451,756,300,648,468,25,87,374,932,545,883,419,761,40,841,464,314,17,760,145,998,899,597,791,719,119,463,863,480,62,888,88,386,196,756,454,318,400,456,539,910,80,83,1,661,587,453,718,821,779,483,347,134,76,303,771,114,200,513,310,185,156,319,853,975,874,999,131,142,241,356,561,822,821,46,604,956,259,456,76,244,538,65,313,504,569,192,947,856,582,581,159,704,513,848,829,167,264,695,158,596,845,880,153,875,110,200,211,753,705,962,199,49,642,621,49,631,697,528,903,736,880,425,205,370,420,981,582,973,723,613,77,412,166,171,918,160,474,446,787,977,392,644,914,181", + "638,925,574,56,460,381,65,750,960,285,517,570,204,204,815,83,295,769,160,814,670,3,292,328,462,46,13,705,497,1,110,866,747,188,703,495,36,992,396,91,500,907,265,435,789,718,829,569,504,453,555,741,45,383,544,644,265,318,899,922,925,83,613,387,7,667,212,690,699,45,190,746,150,53,572,933,46,387,116,282,228,403,605,302,686,805,316,704,641,921,891,648,825,717,158,681,219,439,59,360,383,131,368,664,614,550,487,31,459,963,232,372,792,855,6,936,681,816,412,614,577,250,326,457,764,490,897,586,543,776,157,270,627,856,986,920,444,845,885,993,292,118,461,467,990,846,479,179,110,542,132,121,418,694,791,768,989,107,223,294,204,937,37,87,57,558,885,231,815,352,546,708,846,597,370,58,224,573,477,673,595,115,88,395,82,592,362,974,326,390,442,845,910,186,765,119,585,836,751,159,41,1,94,462,957,313,245,941,782,858,7,461,127,921,835,385,886,68,228,846,229,282,169,740,140,407,760,277,782,743,482,265,994,101,101,141,652,0,810,578,14,257,582,40,696,14,172,574,968,681,459,564,728,244,851,62,583,511,486,158,301,52,12,318,850,21,302,387,929,798,717,351,241,971,803,208,199,745,728,473,443,988,970,226,856,295,600,620,697,739,425,235,204,568,181,733,730,155,291,714,314,22,999,527,128,300,866,76,644,440,693,426,744,34,829,162,679,701,866,294,211,347,723,68,894,236,606,762,337,97,792,261,954,61,83,826,520,384,280,765,486,696,657,106,98,220,984,710,619,351,169,928,94,958,211,456,243,350,714,75,588,141,221,616,193,702,797,6,603,353,555,26,308,28,903,21,256,590,796,586,320,87,377,564,512,666,669,591,228,652,156,909,289,863,678,588,921,62,578,352,928,420,164,234,27,535,913,751,484,666,866,343,65,164,173,745,359,314,26,994,22,198,157,230,469,819,870,807,480,95,571,579,668,702,192,171,112,284,474,731,34,554,568,287,508,363,630,534,230,525,902,770,546,110,577,877,626,34,78,999,217,58,627,838,517,959,125,77,984,107,966,380,434,806,396,947,747,132,805,887,238,331,620,708,190,153,476,634,162,30,577,70,167,65,989,342,514,389,313,248,92,361,454,516,473,606,577,713,214,851,650,407,120,916,723,63,137,943,632,630,909,757,809,265,812,695,844,301,839,310,255,427,714,702,872,230,100,249,780,269,368,326,133,971,835,693,243,34,663,537,578,590,185,988,944,626,733,771,334,776,773,109,925,292,211,45,78,234,549,79,119,887,505,817,316,955,905,826,202,29,684,868,439,436,807,233,552,827,614,127,927,528,325,59,198,109,825,411,507,180,243,45,52,247,879,805,663,159,887,81,141,637,760,671,515,181,396,355,16,788,415,960,829,486,979,387,955,823,79,903,764,351,605,603,797,139,851,401,501,696,407,103,670,442,934,78,298,118,289,942,612,80,15,311,288,714,604,908,266,470,328,411,467,533,543,509,613,509,832,402,271,975,674,729,159,951,586,583,737,880,323,876,640,70,101,4,94,70,153,780,472,418,69,974,242,963,380,437,443,127,406,449,25,423,504,595,453,42,103,293,565,644,593,803,427,433,150,389,203,655,417,101,86,454,793,445,242,989,11,525,935,253,434,365,562,579,828,668,601,771,908,655,4,921,297,55,510,929,456,161,983,569,751,97,721,436,649,338,120,204,263,44,865,332,458,486,993,181,107,279,594,185,556,623,945,473,853,319,935,739,443,885,66,847,937,552,259,824,455,542,781,790,967,325,332,131,724,611,897,934,966,131,959,932,471,590,772,962,479,863,10,729,385,286,689,172,438,681,8,81,317,624,881,931,412,580,218,128,864,699,139,845,434,145,859,691,724,187,719,649,855,311,695,357,562,852,145,949,409,510,515,286,809,618,270,376,412,521,867,214,625,962,501,457,462,261,18,970,252,989,338,32,274,279,837,304,670,535,586,836,279,85,925,25,521,637,250,371,11,857,152,561,992,102,645,303,227,53,534,754,408,907,90,142,441,264,698,909,444,111,758,426,509,278,184,469,941,482,176,447,821,702,87,457,245,447,707,126,971,172,177,659,397,47,479,50,604,98,435,921,241,360,979,746,402,157,1000,767,385,294,757,275,146,474,747,931,436,562,531,429,242,25,514,204,96,983,314,687,240,459,79,64,819,825,674,844,42,547,183,553,576,500,312,47,224,495,797,72,592,228,623,991,389,840,1,491,227,454,816,823", + "375,780,692,331,143,423,852,366,181,771,71,199,774,698,505,493,64,237,803,223,928,195,855,651,88,207,467,880,907,122,128,831,716,410,433,204,916,418,81,27,160,515,795,390,735,130,995,110,772,589,950,253,690,728,83,756,803,186,391,233,398,901,83,238,419,366,690,595,676,621,201,390,242,327,960,749,776,43,676,94,12,696,188,942,673,317,831,478,925,642,563,124,650,215,598,736,152,887,824,479,751,150,520,977,657,107,232,878,397,320,491,798,198,226,448,872,167,726,320,973,727,819,128,382,762,826,263,606,95,972,969,381,644,486,793,733,994,975,455,892,333,731,372,118,910,350,873,210,143,891,994,6,170,756,65,167,301,172,608,623,623,256,286,426,944,148,648,683,211,176,608,764,969,67,926,67,766,997,133,48,775,243,819,902,544,358,722,998,860,258,827,191,491,189,439,561,691,668,229,622,803,46,578,366,746,703,653,308,488,799,411,212,844,214,293,689,388,369,488,893,680,864,984,430,813,350,17,575,87,138,615,319,102,350,331,853,314,810,0,134,366,741,749,164,507,209,881,257,112,803,764,759,935,531,259,222,717,38,518,296,321,677,335,687,542,491,292,589,336,208,489,393,570,453,490,700,329,464,352,875,538,634,298,219,864,372,647,226,810,368,77,651,178,209,730,329,923,730,702,52,612,808,32,684,214,665,961,746,414,8,367,118,539,213,296,426,283,34,480,129,955,274,717,658,715,966,537,551,975,284,253,29,808,217,517,698,292,291,379,830,887,331,922,753,356,904,657,392,648,204,868,574,106,249,857,537,585,837,19,943,861,768,696,806,95,172,432,687,157,787,78,41,810,481,319,380,89,896,817,944,217,90,258,874,355,6,847,177,241,709,767,998,79,249,869,544,952,676,134,24,358,647,634,565,241,420,347,518,888,473,814,508,763,568,111,289,695,117,507,464,782,37,821,113,698,662,256,538,624,371,583,154,685,94,195,796,901,360,292,782,848,763,990,222,869,56,942,585,447,768,351,609,393,44,590,131,43,944,571,516,76,870,31,389,927,84,977,877,509,523,251,481,909,301,686,961,681,102,683,163,935,48,475,788,650,137,433,966,557,945,515,798,588,923,694,983,236,302,656,383,423,58,946,101,214,306,159,52,252,883,253,667,908,762,874,507,645,738,190,159,647,116,787,862,420,665,966,836,532,249,322,554,302,538,578,284,402,155,237,522,346,256,668,790,120,976,716,511,891,7,28,417,268,52,253,815,712,59,629,742,799,74,742,10,711,729,512,791,473,987,91,217,7,708,649,134,649,665,354,909,677,474,756,856,511,538,629,815,10,791,662,638,701,198,604,45,937,153,211,675,323,631,880,519,249,579,484,938,308,873,831,18,35,442,479,443,333,736,632,247,593,24,785,824,746,169,754,128,213,128,48,753,181,138,930,608,757,611,598,418,82,477,5,382,295,271,571,161,960,195,216,417,566,577,701,697,155,278,376,824,991,820,458,98,816,577,823,518,632,954,261,706,421,787,944,308,345,326,183,340,213,437,679,428,371,87,587,951,785,54,995,736,290,645,443,803,669,771,559,499,510,120,878,577,245,442,385,545,800,194,997,128,622,652,561,955,169,175,980,277,467,186,513,28,985,960,96,111,566,364,773,307,215,131,810,830,572,327,526,20,204,145,459,920,22,966,738,943,766,470,149,370,560,918,393,136,109,49,621,233,334,69,787,128,573,347,104,450,284,166,85,634,17,11,582,637,295,715,457,307,941,218,233,361,154,631,165,243,823,181,35,656,65,979,948,561,531,801,453,558,463,359,575,692,338,928,216,669,921,127,555,399,365,313,396,742,157,237,718,613,238,76,249,783,223,103,81,175,130,367,729,886,543,384,833,51,941,320,349,638,333,914,482,784,848,837,883,787,344,69,86,459,892,234,965,260,61,245,559,686,151,670,184,644,436,800,822,307,354,743,970,145,233,144,316,759,326,208,495,196,413,589,529,496,471,307,28,497,515,437,779,405,346,910,511,391,875,191,998,601,454,339,372,60,525,896,160,478,110,388,33,739,777,428,538,77,393,714,269,498,649,890,976,615,844,234,715,115,385,439,159,856,276,156,797,943,361,486,843,445,243,664,465,194,795,60,610,985,173,307,812,63,905,597,443,783,165,733,897,423,660,725,261,479,409,410,537,782,801,496,314,925,950,653,26,562,154,894,75,108,974,148,832,55,410,864,628,217,110,415,124,133,10,606,824,759,860,290,551,801", + "661,598,953,982,434,522,726,713,236,498,656,136,47,356,893,864,892,688,867,366,923,341,71,275,753,663,993,493,824,276,941,517,268,911,832,801,465,345,217,890,745,58,646,237,331,363,600,542,613,4,540,831,709,290,915,978,936,991,412,344,65,181,444,484,792,38,439,195,236,548,219,79,238,72,564,745,94,25,791,950,213,881,545,619,370,808,444,851,354,997,905,209,235,63,142,982,230,997,763,894,998,616,930,451,444,480,483,280,677,277,61,846,219,110,203,126,886,514,808,830,661,957,895,648,316,423,884,751,741,424,150,425,1000,181,555,124,7,495,803,704,945,391,571,488,294,487,466,416,741,163,145,861,736,635,746,718,653,73,24,989,864,561,698,452,607,85,243,422,783,202,975,771,783,246,653,555,931,187,59,84,337,928,922,468,7,405,920,99,391,663,48,54,928,690,728,533,693,232,548,102,652,617,831,68,735,207,62,791,145,876,796,448,996,668,624,613,71,325,438,5,232,505,417,702,40,578,579,659,452,427,745,745,53,965,138,283,888,578,134,0,144,180,22,805,671,861,413,634,238,523,184,688,977,168,283,81,3,487,657,208,82,167,621,760,890,486,508,139,165,601,655,430,149,491,500,47,729,319,719,488,474,73,892,992,371,217,496,244,909,802,208,683,17,981,932,333,14,38,301,247,325,282,170,675,215,282,280,584,966,775,235,178,676,478,607,350,258,485,618,520,743,230,210,900,224,452,531,771,587,861,186,213,437,441,156,423,800,463,225,30,805,217,596,22,391,258,892,482,231,420,542,96,95,54,690,228,274,610,62,899,891,495,226,508,42,646,629,222,557,949,262,210,842,731,246,225,686,136,570,135,194,679,663,751,155,118,159,637,818,685,312,191,185,968,56,623,73,900,910,400,36,405,272,471,295,679,899,586,932,744,133,410,506,842,179,209,662,295,484,665,238,382,972,90,48,812,661,237,124,861,430,560,365,853,205,356,765,418,407,183,534,472,783,481,586,309,150,227,670,760,891,51,474,153,11,64,477,102,440,559,704,782,670,84,380,863,916,796,627,396,61,943,160,865,557,369,590,74,430,975,108,530,409,575,792,623,994,405,297,464,292,375,2,922,31,742,830,23,710,785,673,610,603,708,936,238,354,517,608,962,800,874,685,526,270,239,165,616,537,46,195,466,243,707,104,123,208,605,324,948,28,493,225,370,382,398,95,81,80,313,361,797,236,677,904,519,828,484,66,957,718,612,501,726,714,369,39,654,71,449,745,878,19,892,910,957,490,575,580,506,195,283,773,814,397,159,582,434,690,864,548,594,465,382,177,180,91,184,805,670,217,25,546,783,228,350,591,161,406,885,134,707,209,607,207,88,382,534,246,348,803,795,109,603,946,585,250,813,845,486,927,129,667,240,378,909,721,511,706,152,146,373,630,334,628,299,963,197,266,159,845,98,553,916,403,944,353,844,39,566,284,839,18,391,265,959,830,37,305,27,497,421,836,6,466,624,149,392,906,21,922,130,839,290,991,529,624,127,354,123,808,178,167,583,834,732,860,922,6,53,254,956,593,191,981,143,581,908,735,112,264,666,475,11,657,652,613,207,629,389,656,769,548,734,497,95,492,413,452,582,986,217,376,908,562,545,283,912,371,431,270,889,611,656,377,250,54,28,499,126,448,146,91,212,368,57,309,602,387,218,544,527,933,123,972,457,141,663,394,584,659,494,801,534,108,846,370,869,573,449,914,884,291,346,250,435,893,975,240,499,216,137,318,548,605,452,846,448,818,460,932,274,862,905,110,245,775,416,439,794,966,655,641,157,977,63,333,598,396,871,717,50,804,693,451,213,175,111,634,126,128,386,586,924,566,922,593,623,32,407,895,648,248,634,19,443,395,738,71,892,972,944,351,513,588,125,473,166,295,450,610,21,79,26,335,215,191,887,497,535,527,652,685,908,38,540,257,306,435,984,721,882,250,59,344,865,510,659,339,863,110,41,42,49,485,937,368,189,534,743,897,33,836,275,435,940,990,69,410,544,271,488,509,693,314,2,60,885,640,477,197,852,431,21,575,363,696,257,593,79,407,770,181,338,125,152,842,992,483,708,578,626,874,762,85,763,962,880,683,419,723,961,241,781,726,196,793,701,399,49,894,671,731,68,60,640,569,855,700,855,597,995,924,725,560,275,118,951,299,330,660,242,517,859,572,758,105,597,565,126,241,544,337,803,919,797,861,132,682,355,548,48,842,161,183,485,514,535,321,167", + "375,712,154,572,493,148,788,4,39,64,487,920,642,912,233,879,770,796,207,284,217,472,431,976,597,611,102,544,384,141,660,489,932,601,943,823,853,42,511,359,798,561,172,298,672,119,237,982,176,445,823,777,514,3,726,606,187,586,770,512,885,848,24,707,954,291,786,264,301,245,335,448,365,90,490,583,268,349,830,473,877,528,552,114,366,47,967,686,298,168,767,702,865,225,135,24,851,93,777,729,419,884,898,362,131,211,357,621,252,902,695,140,623,458,481,503,29,577,609,845,471,693,200,954,786,814,954,635,844,512,833,63,124,979,929,637,333,463,400,301,605,178,771,697,96,661,517,521,914,555,452,378,197,170,666,773,144,827,235,55,869,6,37,111,250,416,137,517,27,641,181,541,994,529,809,734,604,373,169,651,169,610,98,969,396,219,36,636,617,192,895,822,685,346,990,813,540,119,337,617,250,379,942,717,706,824,828,285,69,771,554,674,305,88,968,433,202,231,639,987,475,430,772,308,751,746,965,932,700,545,849,730,801,573,681,718,488,14,366,144,0,84,863,965,871,786,401,473,56,340,416,173,70,175,524,650,509,23,680,20,883,283,549,314,30,238,357,123,9,842,584,52,562,907,681,697,836,581,568,60,849,996,100,813,980,854,233,268,235,328,125,238,867,194,599,388,177,931,18,93,796,34,522,29,93,122,503,573,90,236,674,760,475,486,965,510,313,287,535,167,640,451,529,982,491,244,143,960,438,939,919,801,317,564,895,960,940,985,124,997,349,184,565,476,274,889,572,744,911,219,681,682,307,175,247,903,875,394,63,236,273,686,678,417,911,676,869,171,368,11,447,901,843,710,640,334,441,421,846,620,626,786,388,451,910,265,562,206,169,330,781,62,798,340,235,994,140,953,881,777,75,902,80,877,51,399,648,884,28,998,970,43,10,158,350,119,835,847,499,947,589,895,43,676,582,654,124,660,585,505,708,171,909,650,139,231,832,338,835,99,864,798,143,595,893,686,930,657,562,758,964,32,605,452,951,471,725,282,725,265,666,9,545,509,826,866,631,502,359,543,63,947,426,207,140,579,869,412,253,787,588,970,391,100,315,799,409,330,719,294,741,514,97,81,353,167,594,642,436,263,845,921,406,349,775,849,584,710,22,876,583,681,952,779,526,178,856,362,425,700,576,822,219,387,576,256,326,699,56,704,725,736,490,892,617,265,777,306,770,89,950,466,578,249,876,189,396,93,98,826,98,135,82,107,441,159,563,307,456,776,71,52,272,585,444,602,233,223,122,920,373,874,886,65,327,712,255,345,640,782,241,17,152,663,957,246,112,622,530,618,317,650,65,550,929,109,276,897,932,777,770,700,118,648,102,294,812,579,148,655,708,756,177,397,973,920,13,108,61,797,865,870,178,61,671,100,755,321,72,168,568,572,236,446,528,115,383,989,582,564,671,61,721,154,505,189,357,212,334,659,131,245,201,690,36,498,724,691,917,139,734,75,829,386,667,896,198,606,330,375,306,164,857,42,2,834,998,36,466,409,210,926,903,543,653,493,245,929,992,130,737,449,776,451,251,846,209,595,356,113,887,930,686,59,243,315,570,442,680,826,959,137,405,641,427,320,634,898,73,598,726,456,959,115,250,608,490,19,928,383,595,668,137,175,198,726,159,984,779,127,852,371,186,660,376,287,774,216,873,406,352,288,938,196,692,274,850,824,264,52,130,97,852,387,256,940,544,697,465,882,438,551,457,685,491,720,279,486,80,913,730,86,602,133,688,296,87,782,792,607,633,557,909,847,384,998,354,58,485,616,464,731,68,778,808,98,649,433,401,734,945,229,673,356,631,210,743,774,870,395,58,229,690,964,920,269,437,407,392,617,651,343,779,892,758,48,610,546,461,977,773,974,586,288,176,426,270,890,403,380,350,638,317,698,49,524,689,622,522,799,462,422,80,375,532,415,883,653,957,599,593,671,534,679,101,424,580,596,78,482,363,321,156,812,228,148,207,333,200,927,363,984,503,604,22,451,406,642,250,333,600,457,372,98,884,475,925,214,382,458,784,772,926,831,422,535,85,424,569,536,33,19,590,845,77,575,882,989,893,114,885,775,940,110,722,593,269,479,634,599,247,529,352,746,486,214,198,233,433,286,924,80,659,513,872,451,367,604,730,251,954,657,618,444,646,476,525,658,428,30,12,655,938,32,466,531,309,102,376,104,348,277,632,477,854,869,653,644,776,962,853,737,124,505,63,71,395,687,637,366", + "941,29,656,675,332,569,349,265,358,112,158,70,203,827,930,374,693,70,650,118,784,993,759,432,557,381,885,768,966,377,109,332,303,722,281,969,24,884,149,658,892,790,696,202,470,937,803,566,893,477,844,447,405,660,42,812,880,835,860,724,763,957,325,553,971,333,89,896,171,595,916,713,914,524,9,352,314,345,180,473,320,770,687,129,992,5,919,345,181,427,235,216,842,261,575,137,381,892,938,875,752,613,127,918,473,303,708,117,86,301,413,454,438,37,739,174,156,267,966,579,176,333,68,921,982,298,430,115,845,247,804,217,841,352,290,496,241,591,749,392,353,772,641,838,786,396,478,390,508,687,404,502,958,337,540,984,949,850,407,828,74,439,91,35,21,876,890,307,499,416,255,873,160,775,374,650,367,525,212,236,355,440,52,967,692,410,654,266,865,902,911,176,537,548,269,697,100,294,589,131,717,212,270,215,158,967,795,576,925,203,619,678,366,659,242,810,554,763,686,623,778,266,33,186,887,530,139,231,407,660,766,239,579,778,223,955,69,257,741,180,84,0,58,952,424,534,493,747,463,699,431,247,888,286,972,916,182,49,1000,651,401,225,606,360,289,472,365,575,366,376,423,71,777,62,738,430,553,93,387,150,201,336,85,938,125,582,561,939,885,573,325,836,857,82,231,914,546,684,11,12,479,672,243,877,100,525,794,353,151,666,799,402,328,8,931,692,289,7,309,643,112,716,934,446,741,55,360,965,211,433,89,87,434,107,960,540,915,401,664,240,482,959,196,467,180,696,702,579,52,596,284,508,176,436,770,270,537,519,237,110,675,945,724,429,12,789,312,435,923,497,94,908,355,676,379,260,246,629,214,752,688,578,315,376,455,105,699,645,390,654,463,436,659,359,472,284,848,726,705,177,416,110,102,890,629,359,629,543,852,578,204,105,333,378,525,992,159,505,980,925,245,409,454,348,877,857,157,949,295,264,909,767,386,471,953,958,7,719,902,466,126,220,498,69,941,613,471,581,576,616,897,960,925,493,648,796,44,74,822,933,834,565,65,342,615,119,460,766,552,384,617,971,49,133,477,961,615,583,221,473,69,936,272,827,973,797,614,83,637,95,622,261,328,556,210,775,253,888,723,540,221,853,333,950,705,305,994,684,815,845,371,18,622,404,461,956,355,662,538,655,109,80,641,112,974,438,812,53,262,525,635,177,2,589,359,781,543,537,70,41,352,176,347,232,942,587,120,230,256,808,929,310,705,731,820,47,257,501,594,607,694,664,559,960,152,914,717,189,293,401,447,6,613,790,271,221,461,761,785,380,306,231,777,456,887,984,902,462,986,556,975,346,875,966,490,262,438,17,470,502,659,21,141,715,457,318,326,565,651,403,735,518,31,399,466,351,881,40,416,354,147,711,550,903,788,538,403,603,106,66,575,558,421,416,262,298,488,667,244,158,152,625,194,580,595,681,259,337,255,488,987,20,822,186,329,525,474,264,49,44,370,380,275,544,499,255,577,559,621,977,788,245,278,698,867,630,81,735,127,812,183,883,304,235,241,638,252,497,810,772,467,702,26,678,173,417,724,720,658,218,315,948,924,158,772,521,914,187,942,43,907,147,319,252,48,119,170,525,101,355,39,132,694,649,779,156,233,193,568,110,822,607,115,109,998,959,429,986,378,529,193,485,93,703,13,375,591,889,485,639,265,2,10,233,97,211,89,317,634,184,771,231,376,140,911,571,770,355,553,384,623,201,87,74,218,765,674,474,300,184,663,26,764,566,526,69,115,422,766,554,5,187,15,233,344,283,546,35,244,303,379,916,465,742,244,96,539,702,109,473,442,145,266,2,930,966,947,70,164,70,56,267,3,865,48,537,505,763,112,484,623,844,13,675,89,813,998,538,394,974,355,166,394,520,316,274,831,576,167,231,684,120,247,139,545,124,781,172,333,179,193,725,639,246,818,476,256,849,740,433,190,832,721,137,200,768,18,684,934,923,258,884,817,192,64,759,398,437,924,544,975,56,550,307,526,968,159,194,646,922,343,629,469,264,219,439,784,819,803,302,258,883,318,343,277,369,246,76,943,904,38,393,800,758,826,134,405,591,585,559,687,326,953,527,377,467,249,523,821,438,582,222,503,300,292,980,458,158,338,62,757,589,401,821,1,10,113,350,196,619,550,40,663,287,371,712,644,397,366,629,730,582,131,198,304,611,950,756,884,671,43,230,341,185,558,433,597,981,449,576,857,738,194,161,878,572,264,480,504,878", + "487,191,121,525,536,995,169,870,579,157,191,917,113,438,42,159,848,910,268,126,914,371,156,472,985,394,908,619,477,225,676,301,727,542,518,666,623,1,64,974,289,423,572,941,510,484,558,611,745,536,862,825,66,642,392,319,168,800,543,78,419,894,969,554,779,818,297,802,614,516,546,116,160,234,284,560,34,249,840,547,142,736,203,407,432,637,240,42,533,717,226,433,215,307,391,797,376,317,878,782,911,998,586,583,253,712,497,820,918,511,637,311,578,105,503,604,123,143,978,120,775,423,347,379,142,115,868,822,163,642,556,260,668,106,631,914,38,629,881,292,209,144,102,497,713,489,21,708,737,995,991,686,171,610,829,99,716,135,851,5,862,190,325,913,786,142,731,512,777,259,461,89,484,727,361,44,448,984,935,516,651,488,763,166,732,308,29,828,614,949,837,613,242,464,354,439,79,647,784,61,930,862,678,899,164,379,918,481,271,394,171,50,976,748,692,595,557,969,40,603,388,417,806,453,781,678,670,267,619,660,486,493,238,43,977,864,750,582,749,22,863,58,0,575,502,372,103,386,511,440,806,122,343,301,498,706,798,902,730,452,72,271,996,876,157,760,833,472,23,905,430,829,760,578,618,934,249,768,789,570,846,477,233,505,816,133,140,298,662,26,833,684,755,111,239,896,662,657,144,201,593,235,564,509,507,556,630,297,189,504,200,881,442,456,328,791,8,651,166,60,282,938,39,142,364,871,33,539,260,624,332,700,734,590,102,842,702,818,220,292,341,829,382,427,37,339,280,335,616,468,518,292,739,327,459,654,749,491,244,309,160,877,430,67,101,246,217,913,352,22,428,3,210,173,753,459,17,302,127,751,54,953,568,742,899,685,783,260,567,945,296,211,441,782,649,586,269,259,522,627,209,242,639,697,165,966,459,646,551,613,952,539,957,452,990,400,18,368,392,368,465,164,109,265,761,573,727,921,498,605,834,994,552,422,867,609,943,977,66,345,258,607,281,13,447,309,546,487,344,27,440,584,630,171,94,222,859,568,917,550,154,547,739,19,203,250,718,902,966,53,552,633,365,913,839,27,820,371,747,983,314,82,626,126,452,408,257,523,713,749,516,460,538,824,297,367,90,825,315,209,304,431,626,950,62,348,867,550,737,759,222,715,88,376,69,664,979,262,781,777,246,876,56,142,540,290,902,427,803,531,554,3,621,766,401,502,700,308,995,921,742,148,662,718,880,311,700,605,226,648,795,775,546,195,709,190,907,183,841,155,993,985,336,260,243,461,968,954,305,244,145,31,511,668,158,384,880,545,858,803,336,660,127,786,591,491,731,543,78,534,905,532,84,390,307,662,145,572,444,872,9,392,374,652,866,86,346,313,380,622,22,501,590,595,431,885,790,72,969,120,936,765,652,147,75,936,428,173,764,899,98,759,507,437,797,417,894,796,325,251,49,743,365,656,422,110,756,12,355,947,795,328,277,378,213,777,514,332,459,353,609,512,135,817,174,703,610,477,31,31,204,795,566,830,491,336,10,236,430,671,820,909,545,399,131,622,610,436,354,182,732,445,133,549,24,436,908,438,928,615,932,94,983,488,272,472,456,359,308,104,449,738,283,91,333,226,809,565,386,576,817,883,789,775,973,999,935,948,338,893,221,991,527,507,316,222,617,421,829,519,985,516,20,692,403,180,770,553,508,716,508,989,327,153,877,349,362,755,605,516,488,201,786,614,835,208,427,856,688,360,563,70,81,969,705,493,687,155,170,390,548,387,811,502,193,243,664,286,349,944,232,471,648,764,715,130,54,375,336,689,758,554,100,750,532,151,179,884,315,390,271,491,772,889,282,285,412,253,415,421,377,366,75,918,949,967,819,733,46,382,491,321,453,218,98,112,416,566,571,130,687,895,127,266,439,839,964,595,258,261,876,628,733,679,77,195,82,387,943,635,203,131,832,154,603,461,138,786,126,98,878,729,141,126,422,138,264,857,542,19,205,545,15,835,514,285,533,82,359,405,259,290,204,164,583,712,86,966,221,726,228,338,679,982,947,502,604,385,829,454,56,855,732,808,943,254,396,977,956,930,387,797,941,381,192,892,91,541,300,5,249,464,672,537,753,323,29,366,128,779,91,119,573,402,492,205,788,212,107,883,667,757,530,149,783,508,126,459,879,193,686,863,819,427,157,476,214,740,726,792,560,820,408,407,680,705,66,673,162,197,524,560,84,394,169,158,935,777,89,60,252,754,590,638,586,325,606,7,172,369", + "58,650,543,801,989,386,870,415,427,333,280,712,199,785,306,429,362,357,340,721,516,12,604,972,61,875,184,755,630,911,609,291,851,256,129,255,646,331,674,842,862,855,108,215,396,974,395,466,410,686,844,961,737,958,241,308,371,152,209,639,660,561,230,457,759,158,502,257,845,963,748,400,427,262,197,510,230,826,537,763,920,920,937,390,810,715,190,398,566,110,639,276,479,487,548,114,664,251,120,835,244,580,345,336,914,753,417,556,238,269,554,384,355,536,267,257,148,765,530,448,952,209,164,818,162,181,237,915,123,277,851,838,586,512,259,84,896,602,982,306,549,210,174,127,765,836,177,916,642,139,939,616,475,684,39,640,456,890,884,63,333,654,314,918,338,489,327,778,951,668,775,154,430,180,754,674,230,745,628,722,826,999,108,428,686,135,775,971,93,281,280,690,700,532,375,480,335,13,505,936,214,29,736,420,760,845,822,636,581,630,181,446,706,559,791,719,992,813,327,854,546,576,72,492,191,198,312,26,947,148,237,933,433,179,56,663,445,40,164,805,965,952,575,0,84,980,269,762,969,736,845,667,632,740,989,569,925,674,465,772,803,861,293,169,68,407,132,958,979,819,85,609,814,673,373,445,497,66,621,180,741,150,851,650,832,179,187,810,411,936,289,858,870,466,829,266,496,328,193,633,251,284,831,183,554,44,150,66,178,441,273,120,452,879,362,82,766,882,345,135,798,747,940,186,357,739,635,328,903,277,934,92,36,43,281,517,590,576,234,496,256,587,887,800,899,549,944,913,428,856,380,720,930,819,584,917,624,46,289,220,856,70,391,454,554,172,853,916,86,491,843,422,797,188,819,772,803,131,476,167,568,887,69,651,551,696,303,664,535,811,727,375,314,446,741,245,806,391,315,801,980,254,612,678,640,346,834,810,461,713,949,183,216,180,726,500,409,732,151,835,575,287,551,461,190,412,258,344,78,56,639,108,317,607,200,57,768,133,274,24,556,166,842,895,857,892,521,596,485,476,991,799,186,606,38,780,426,557,521,354,836,444,677,988,436,150,887,884,697,21,320,30,824,5,985,199,379,29,95,480,161,505,374,670,925,957,337,409,329,307,450,951,161,572,887,712,843,1,633,979,217,980,598,333,228,248,547,14,565,865,719,391,223,34,812,203,515,619,549,369,746,476,332,759,243,73,323,642,872,182,88,986,497,726,645,574,42,591,781,902,589,619,755,1,331,223,908,671,823,635,445,44,813,799,523,395,78,943,787,119,946,347,936,29,708,870,160,37,232,718,206,710,41,913,142,408,998,844,846,355,87,309,922,899,87,460,67,13,823,119,52,909,623,68,85,583,172,565,776,497,235,776,233,748,55,63,729,563,330,556,218,515,24,793,784,416,950,833,417,710,729,893,773,151,959,600,809,737,54,965,447,91,574,370,496,152,322,328,659,362,287,488,193,274,53,904,815,672,302,369,371,707,855,892,45,850,225,685,793,926,834,681,232,335,915,423,847,145,278,989,117,835,2,81,998,889,489,82,772,39,356,530,200,606,600,134,212,894,143,582,664,404,322,141,607,418,555,944,14,358,675,28,260,638,617,323,928,171,734,3,950,827,355,356,414,584,5,370,452,902,748,571,968,297,770,475,307,635,762,989,219,262,300,827,829,237,940,950,886,671,3,77,312,599,3,312,136,583,459,947,794,762,962,159,110,165,413,356,270,527,903,919,65,705,519,171,727,363,823,811,566,831,273,926,803,845,226,957,992,495,270,638,66,659,834,95,17,691,124,248,4,555,88,115,224,556,803,865,68,585,193,651,766,380,572,824,1000,144,653,621,463,367,614,808,299,801,929,697,322,71,148,369,760,540,396,926,324,154,286,697,316,452,367,585,965,134,864,122,428,62,53,702,953,780,726,292,786,575,263,352,704,94,919,505,938,429,186,558,8,737,853,545,159,240,175,71,112,732,332,416,97,754,761,805,829,440,160,769,171,930,15,746,799,286,248,839,244,518,457,351,19,238,954,745,426,309,254,571,680,442,994,362,785,476,860,299,798,137,810,187,388,829,663,325,489,248,566,372,929,160,76,504,478,677,273,421,297,201,410,523,67,93,544,596,95,843,111,421,456,164,747,66,114,374,947,475,854,175,113,662,956,595,793,21,517,621,366,759,237,937,703,324,169,823,647,716,832,874,714,532,110,55,400,633,305,171,704,94,262,529,173,513,448,433,754,16,627,608,866,767,718,669,609,17,991,341,260,588,716,792", + "890,287,160,546,647,382,783,442,377,211,797,603,514,49,780,730,535,685,942,741,712,636,537,812,60,119,688,299,958,804,187,340,891,423,707,978,481,944,959,33,659,127,177,422,269,572,736,716,886,14,498,978,522,280,934,163,89,346,185,170,373,253,853,860,331,201,375,955,679,362,963,624,267,604,806,511,318,408,587,840,643,65,238,288,133,730,677,134,366,99,381,330,13,953,470,279,935,236,328,392,668,111,178,486,902,830,145,365,505,375,443,694,269,936,80,314,840,741,184,746,142,385,947,846,41,804,254,791,662,341,202,925,10,264,935,143,146,544,887,68,576,907,757,233,722,951,502,194,396,897,50,507,729,758,716,777,496,432,111,39,668,241,230,875,530,878,7,743,826,162,549,649,40,760,210,768,646,680,521,771,77,192,883,747,96,149,705,605,51,473,195,966,651,709,396,679,660,985,252,994,348,42,849,555,144,86,585,219,344,911,56,479,65,657,698,33,131,552,795,62,242,528,860,326,17,588,777,877,307,885,399,711,344,634,967,996,988,696,507,671,871,424,502,84,0,514,180,485,437,259,232,106,789,503,148,245,334,288,640,298,762,874,775,900,484,530,690,780,26,411,951,676,432,406,670,653,930,314,449,922,453,877,212,182,478,537,595,240,944,910,73,336,353,514,541,113,187,463,590,30,129,227,819,695,409,794,389,137,222,897,434,442,257,160,511,455,426,768,659,615,430,539,255,262,906,278,111,229,710,309,295,769,466,946,403,366,654,1000,313,156,511,419,214,964,457,687,687,119,993,754,469,355,908,399,86,875,490,673,447,147,949,801,317,374,668,469,809,143,487,241,595,609,476,246,860,955,582,675,500,328,632,107,970,948,271,371,178,451,238,375,573,681,145,839,666,648,691,909,968,27,883,875,717,453,374,921,855,606,896,590,878,407,58,371,306,638,730,953,373,775,885,963,541,3,625,167,64,96,585,399,966,119,132,206,934,609,831,952,734,92,28,697,473,914,473,406,606,107,771,771,822,595,70,349,886,861,121,681,193,273,56,980,363,411,217,320,48,57,338,728,219,550,892,854,535,764,903,63,172,673,82,590,747,67,935,91,183,916,841,246,129,541,506,11,505,993,416,512,644,60,974,733,279,97,511,986,848,621,422,451,190,807,61,674,485,108,415,269,346,743,785,911,243,784,656,753,723,52,442,919,93,512,3,49,500,668,179,344,966,902,662,840,820,779,506,119,484,731,349,728,575,528,834,806,1,940,840,631,274,547,168,182,935,561,987,369,708,632,883,75,659,735,481,727,667,854,320,509,597,909,455,246,781,950,182,516,252,688,324,556,292,799,304,146,188,78,898,420,290,280,313,882,579,186,815,361,597,556,635,120,886,9,222,755,419,434,244,169,168,957,734,166,719,951,896,819,251,937,904,924,626,809,388,234,170,756,185,433,121,93,419,372,470,888,65,65,390,814,514,566,779,128,927,720,173,859,351,702,191,47,495,190,589,175,931,407,200,348,600,693,544,441,161,899,450,696,496,558,874,889,799,34,586,248,349,143,996,637,159,698,326,104,822,854,65,122,986,707,530,656,427,387,10,741,580,609,312,614,530,909,420,192,538,890,153,714,864,10,426,726,608,221,585,290,740,678,420,647,796,148,342,940,124,662,833,310,794,223,187,701,263,905,208,535,810,299,889,370,867,668,354,467,741,765,3,555,284,109,436,86,439,435,794,420,833,940,55,613,184,188,994,172,3,987,637,92,927,857,744,658,181,525,816,816,251,259,155,279,477,849,905,882,624,446,713,142,279,49,446,4,179,70,603,317,21,20,633,361,767,748,108,991,274,327,834,731,489,358,583,618,845,122,433,46,851,879,344,302,903,463,279,497,805,90,814,778,30,174,207,219,973,780,542,818,531,694,582,901,972,276,808,670,700,248,665,786,878,822,189,671,367,311,592,957,853,548,380,826,988,563,232,710,946,724,560,383,600,606,25,880,660,669,82,853,848,735,544,669,76,139,970,785,633,631,874,322,723,603,87,286,112,945,511,579,134,464,80,577,359,34,264,602,17,641,677,378,678,44,832,694,166,827,570,777,663,852,278,66,209,275,805,200,425,24,612,579,466,698,453,541,866,582,585,99,360,984,832,537,926,152,706,234,62,413,559,64,449,420,500,56,657,842,374,715,859,823,720,24,281,408,830,364,534,241,335,60,208,471,600,193,232,669,954,940,814,343,530,603,324,40,610,48,318,295,831,624,416,510,111,451", + "700,301,848,827,96,119,324,696,734,631,416,907,789,268,455,78,674,665,455,663,322,621,557,483,184,517,615,299,57,568,217,474,422,259,744,347,191,318,934,910,244,717,557,883,717,548,861,348,589,709,532,88,247,73,907,774,89,276,116,540,769,119,747,981,24,658,534,378,790,742,464,247,38,490,737,589,246,176,421,228,237,265,715,611,524,347,775,80,333,12,188,765,72,414,767,628,749,294,665,124,105,589,27,159,710,776,205,692,63,417,956,357,459,981,157,34,132,240,647,928,597,375,379,206,258,149,43,984,448,116,709,923,282,706,998,542,504,190,280,405,772,254,90,464,977,115,870,106,945,146,144,356,43,382,136,614,811,19,468,594,908,646,956,795,276,752,397,148,848,377,694,345,9,958,876,145,980,509,710,824,430,639,819,303,963,389,283,204,454,492,664,542,469,7,376,685,439,785,702,376,338,823,419,197,649,312,257,142,884,376,540,731,82,209,660,7,285,969,939,430,606,304,154,721,703,349,985,83,662,966,786,963,854,594,747,32,902,14,209,861,786,534,372,980,514,0,610,322,827,802,249,60,206,680,738,418,151,469,571,11,564,219,622,604,906,34,871,935,366,831,157,325,574,181,952,951,241,675,489,901,368,947,609,54,530,596,407,376,279,481,876,562,906,355,21,92,134,303,600,759,365,734,16,672,982,133,176,954,77,392,41,921,273,819,653,764,638,814,626,308,74,723,64,414,20,674,515,481,488,825,910,763,745,535,915,398,211,725,394,21,5,125,757,970,705,815,208,904,692,48,225,208,467,247,917,422,236,655,582,646,870,606,707,381,519,216,459,695,978,710,433,479,978,454,432,394,281,600,4,386,366,590,154,195,607,779,91,993,94,957,579,989,831,36,460,615,886,676,810,90,892,342,636,697,472,866,673,194,251,739,352,949,69,187,111,573,308,138,492,559,39,866,713,637,274,377,61,754,46,558,373,981,413,655,330,523,446,825,33,345,930,664,76,916,115,863,696,262,234,948,646,549,666,376,387,287,190,970,724,627,36,72,388,604,57,19,8,401,613,317,77,917,622,42,837,632,649,466,335,112,99,282,1000,117,621,700,299,431,844,93,527,827,939,41,846,468,822,745,4,465,815,127,178,506,365,978,288,280,879,922,445,515,476,622,945,695,632,98,259,52,48,875,838,267,632,786,955,899,459,123,676,767,4,743,900,258,208,216,714,433,334,956,311,674,726,630,275,338,312,164,59,576,262,57,936,613,774,560,285,803,636,332,856,517,8,848,724,565,679,645,689,127,316,63,577,60,267,734,830,512,831,860,146,47,439,914,566,548,552,959,533,490,407,926,409,6,202,932,649,308,676,200,707,533,709,573,354,118,987,348,981,454,754,556,194,849,70,185,709,878,31,119,472,600,238,869,370,113,875,89,948,852,290,369,364,276,934,980,100,861,542,9,38,301,637,119,486,965,766,539,312,91,656,463,483,971,72,464,583,733,364,408,111,57,254,183,117,352,200,451,281,806,455,4,37,407,215,153,854,761,79,666,377,337,697,10,503,87,737,683,175,557,695,743,751,97,483,897,140,644,340,70,291,160,720,895,516,985,945,698,593,254,471,383,927,939,409,788,46,448,728,289,262,227,112,302,951,542,827,493,320,116,845,285,231,422,412,273,166,64,995,663,378,90,442,437,131,209,345,76,879,196,637,251,47,608,815,643,177,923,466,365,250,164,322,997,157,655,101,696,891,523,623,704,701,144,752,247,988,245,91,245,62,712,787,334,638,922,763,959,741,204,261,103,623,31,373,27,328,536,140,395,200,60,388,253,356,671,46,960,345,641,589,397,865,264,627,399,624,695,119,568,882,943,947,999,348,278,727,505,72,288,978,381,8,767,279,279,591,594,498,974,310,379,859,529,929,685,155,520,5,696,444,871,916,489,335,158,338,521,254,321,755,282,607,655,465,775,270,306,614,460,337,405,26,959,56,345,455,255,349,221,990,764,255,273,568,811,950,566,8,767,708,984,302,990,813,359,714,184,207,157,805,656,600,889,316,232,186,67,937,691,991,969,165,885,471,962,350,120,559,357,818,495,748,449,412,49,516,847,208,104,878,997,58,958,800,399,804,601,166,527,402,367,805,914,759,289,920,96,455,965,577,442,215,62,184,620,701,386,585,559,672,274,608,82,441,208,902,545,473,343,313,144,936,994,86,567,347,267,841,433,811,739,803,486,531,244,353,424,11,769,308,106,125,401,184,197,322,561", + "121,735,724,99,247,123,281,720,814,751,64,475,31,600,635,782,31,519,325,19,859,985,909,217,783,327,357,833,62,952,796,355,139,140,391,578,343,903,459,526,34,71,317,444,282,895,198,873,86,858,564,952,692,337,739,496,116,314,377,884,768,113,350,452,579,546,722,152,473,726,914,627,912,261,774,967,994,472,327,294,816,68,305,876,20,36,423,230,290,12,961,944,503,715,118,752,891,116,24,628,659,348,912,276,224,174,17,9,122,659,89,338,681,912,435,728,357,123,427,21,885,820,784,469,233,251,150,713,457,24,521,439,582,235,102,448,614,200,337,6,907,744,450,22,258,992,462,379,91,695,500,715,162,367,605,738,336,978,245,718,855,423,795,526,960,127,200,22,161,606,427,892,924,57,265,993,668,165,308,745,663,600,906,223,85,340,510,563,525,174,682,221,154,543,439,291,755,299,28,895,341,553,387,11,907,812,920,120,817,557,354,548,903,505,38,6,205,490,613,203,990,674,821,20,386,334,380,241,90,433,956,92,7,142,895,304,322,172,881,413,401,493,103,269,180,610,0,515,379,601,665,136,929,878,157,401,179,409,99,85,364,369,725,214,180,115,548,846,860,614,992,621,433,966,859,255,211,61,659,952,874,381,568,640,921,96,127,599,656,280,740,925,493,198,83,139,194,719,819,323,563,852,68,579,791,714,996,485,300,25,429,573,505,506,733,416,975,886,375,292,450,439,89,883,820,455,725,53,103,527,494,613,688,670,358,754,352,995,125,506,140,617,420,586,924,629,616,770,275,276,427,144,728,228,604,206,941,593,272,412,967,228,35,573,394,731,798,339,496,997,208,951,185,870,725,830,877,998,618,252,999,9,69,680,533,417,16,192,666,679,710,954,631,143,132,611,718,110,304,412,671,753,140,673,896,777,616,729,167,875,37,428,84,620,444,990,589,271,508,990,618,570,626,278,497,190,420,114,172,642,661,351,838,575,733,200,466,985,959,149,85,842,529,622,672,461,470,58,387,222,548,893,203,919,139,684,901,930,725,398,518,699,649,401,274,185,59,329,770,33,996,556,237,557,31,277,533,585,189,670,398,101,862,815,6,931,406,35,646,621,482,891,429,882,50,102,318,985,999,460,375,151,927,889,802,555,917,18,673,366,915,94,326,690,282,717,96,871,10,21,214,868,240,808,26,279,596,95,278,125,950,255,856,797,916,249,908,697,288,131,977,90,150,566,165,584,196,22,183,867,94,205,371,327,175,706,281,680,673,965,963,184,844,194,787,112,342,191,927,365,170,621,437,924,184,512,374,62,825,949,935,965,286,596,344,404,410,270,755,722,816,476,365,435,561,707,926,295,773,428,245,91,928,452,276,758,128,420,186,196,920,853,341,310,929,495,913,412,559,221,425,455,993,841,601,705,276,690,717,718,202,725,696,277,130,485,865,385,303,141,545,520,122,633,903,842,639,796,468,430,176,963,815,102,512,738,301,400,156,291,100,48,627,673,834,817,111,661,521,615,276,982,809,363,640,1000,216,366,441,280,384,121,394,67,336,137,506,492,874,619,562,818,666,507,900,514,290,628,606,642,811,646,609,218,448,750,185,910,615,706,109,831,979,288,27,513,797,38,562,498,439,376,79,912,725,803,333,984,371,752,339,810,254,631,996,703,767,665,420,456,756,443,911,329,389,81,237,961,11,595,669,808,988,246,858,328,252,711,875,201,78,318,386,589,456,902,345,257,729,300,22,455,643,461,528,401,19,168,836,752,27,892,968,841,183,921,48,720,911,895,823,157,614,315,643,629,504,410,225,309,524,765,657,439,671,688,263,793,66,261,883,89,827,454,679,701,969,470,473,719,273,644,166,226,363,224,727,629,196,765,562,551,973,971,924,67,721,733,833,47,878,559,165,211,151,298,276,106,834,184,101,578,756,844,50,134,895,796,202,110,368,695,382,848,156,270,812,45,628,559,618,820,517,662,44,452,392,79,165,673,738,621,193,932,236,670,212,36,196,547,241,5,88,189,664,490,226,226,332,343,946,172,832,441,177,123,376,547,82,516,677,325,729,903,388,326,447,453,709,963,83,115,843,569,315,296,418,619,552,724,771,821,492,985,956,543,890,223,579,259,116,429,162,222,962,78,633,581,931,16,188,406,597,94,240,396,281,758,620,324,67,95,844,862,643,888,862,359,874,948,654,367,318,460,546,269,790,307,489,5,471,834,872,465,185,376,427,415,177,365,705,734,53,732,914,466,565,999,764,244", + "852,765,366,741,695,876,584,732,621,496,286,901,26,613,671,852,193,584,869,32,241,962,379,171,787,416,145,76,87,355,455,541,674,355,927,644,584,757,354,122,127,408,428,173,145,771,477,542,285,624,831,530,265,244,888,945,215,40,703,84,452,105,758,597,251,915,826,551,458,704,871,368,288,944,461,103,187,59,380,131,662,363,338,654,741,183,175,680,448,481,886,68,595,206,195,426,622,882,810,776,371,866,561,907,575,619,877,915,27,391,927,844,127,471,139,614,12,781,6,318,576,310,23,283,468,938,189,469,439,789,639,435,151,238,53,20,378,521,788,545,122,376,313,935,823,442,105,361,637,940,162,983,292,19,246,993,937,843,14,475,198,380,374,127,228,18,569,233,738,573,65,38,487,486,697,287,939,408,576,998,293,836,626,648,104,143,895,801,396,993,720,81,195,989,544,965,828,603,53,868,238,399,662,602,138,278,552,322,765,253,277,556,462,292,823,413,657,348,852,359,168,44,473,264,476,122,105,137,46,768,528,854,429,578,699,459,126,574,257,634,473,747,386,762,485,322,515,0,959,833,845,136,304,805,583,59,47,854,75,693,203,693,462,858,82,509,287,765,322,390,124,977,468,180,50,741,508,621,816,240,917,703,811,956,429,933,818,288,495,572,789,312,2,418,322,887,230,544,539,436,347,888,189,517,174,691,930,840,710,713,186,194,759,707,124,1,307,259,309,150,406,730,455,499,506,793,91,598,654,20,522,163,614,117,47,649,489,127,656,355,326,227,287,396,456,403,415,430,797,924,576,183,224,208,402,900,274,938,631,939,227,942,585,780,791,941,838,227,536,569,828,548,758,413,463,333,955,156,987,186,573,448,644,604,312,470,909,393,459,11,634,998,999,191,973,862,186,301,618,622,60,485,768,979,870,761,21,352,536,374,44,780,577,480,733,912,409,171,604,42,515,180,47,256,469,636,546,358,275,214,670,504,958,488,531,275,162,869,623,665,218,563,408,322,273,582,111,707,999,898,983,571,171,911,548,455,410,192,520,556,93,719,162,592,969,744,925,604,509,266,736,750,405,160,658,63,284,548,485,546,839,55,636,138,43,431,708,657,455,535,999,520,614,15,954,826,488,711,438,89,479,932,2,154,6,690,912,989,599,602,577,33,283,605,806,276,786,390,293,374,61,51,450,668,484,609,457,336,549,816,92,639,815,80,898,366,513,448,378,192,636,280,549,638,69,724,890,892,115,498,819,861,444,980,819,817,339,351,836,659,994,609,410,369,612,763,622,813,151,633,710,294,729,896,229,21,950,328,522,758,461,609,615,590,571,479,567,929,336,206,830,644,111,603,393,151,300,624,979,752,708,392,102,572,566,888,580,894,141,578,499,80,676,846,870,257,319,222,975,523,720,274,34,770,824,3,125,22,447,212,402,330,860,671,927,164,281,795,117,159,101,256,407,608,651,324,12,26,113,557,438,806,961,805,222,346,902,993,837,61,633,756,700,780,277,812,653,21,568,462,740,983,124,333,852,869,101,706,885,509,350,827,481,681,769,317,297,609,479,250,452,57,411,394,30,269,489,184,696,789,106,444,740,943,293,657,672,193,137,130,267,579,181,591,136,606,397,419,609,843,913,871,834,119,174,894,575,980,999,188,754,210,908,978,104,826,541,714,186,685,399,165,783,375,897,95,584,921,772,503,849,83,400,900,885,67,71,309,425,67,144,768,660,841,643,141,406,90,3,873,328,854,268,409,726,225,982,14,511,253,408,138,608,378,840,832,994,827,149,67,794,820,895,620,895,387,341,249,427,342,918,306,920,750,493,15,189,427,96,354,53,890,508,359,607,887,341,341,999,850,233,419,462,887,622,967,922,52,206,622,147,619,239,583,941,522,127,700,484,18,796,452,839,747,152,227,75,222,271,114,289,656,106,311,699,580,621,218,396,736,436,386,267,506,840,501,980,26,299,734,340,168,838,695,656,678,499,359,828,601,343,575,140,868,899,836,537,15,795,978,793,326,418,432,779,920,711,572,246,188,183,67,312,354,322,324,486,877,441,611,114,947,993,860,653,684,365,190,920,277,17,225,936,739,789,725,392,710,759,960,709,516,658,113,768,110,917,268,354,171,342,48,690,906,72,303,280,773,776,293,245,332,755,662,592,11,988,537,345,264,483,448,277,215,934,866,210,504,404,792,9,588,727,237,349,350,838,963,271,207,2,32,581,431,92,514,569,232,292,122,677,887,454,180,720,750,23,185,636,825", + "700,117,765,130,888,440,278,153,370,404,23,368,708,827,116,374,605,16,3,475,515,316,949,78,861,460,102,906,274,844,115,59,911,918,489,951,782,249,510,487,545,410,310,456,884,477,843,602,384,656,228,159,633,431,720,715,625,11,702,778,887,498,724,299,713,427,224,448,677,441,381,594,599,13,315,719,752,877,953,451,606,442,480,340,150,231,693,382,590,64,335,598,687,667,564,530,819,641,2,405,690,768,297,721,198,192,743,204,818,7,865,206,21,63,805,812,719,402,136,361,492,770,857,868,300,92,893,72,226,240,866,538,489,69,806,686,953,352,207,803,170,182,65,93,968,717,609,146,684,679,527,1,917,72,386,343,885,953,507,853,325,944,948,447,262,463,580,749,722,87,475,745,633,103,788,886,83,362,903,45,392,283,803,155,228,240,785,824,310,72,750,436,216,925,438,184,485,531,405,264,78,452,582,371,736,940,735,289,988,357,737,572,341,731,681,48,258,983,212,504,951,734,644,473,586,532,898,305,694,902,637,401,891,640,319,857,581,968,112,238,56,463,511,969,437,827,379,959,0,427,33,146,383,567,38,851,99,175,744,540,382,682,675,348,434,807,1000,257,85,313,5,863,941,381,953,840,685,130,42,66,384,568,128,971,513,191,451,562,352,251,840,498,433,473,770,482,966,212,485,627,596,902,997,624,649,402,903,6,28,862,174,544,188,498,237,305,144,456,739,66,955,456,344,816,895,14,911,17,641,746,608,982,140,926,235,400,275,580,301,682,123,156,759,47,481,755,453,496,177,985,472,93,868,352,354,308,387,2,780,223,974,154,472,808,961,683,756,311,785,217,693,615,143,850,28,944,110,473,240,667,249,823,83,436,764,452,897,770,819,567,792,264,865,847,356,811,728,70,469,534,891,132,810,911,278,504,887,65,525,653,627,500,548,884,867,61,418,598,142,517,264,44,323,477,281,336,824,531,932,929,345,249,774,313,804,655,131,199,726,798,173,522,185,270,447,967,488,52,191,904,161,75,541,207,646,104,591,615,723,695,784,612,509,398,5,55,589,499,330,658,532,239,980,633,126,449,818,643,301,664,332,577,814,447,112,543,509,955,214,949,393,588,80,223,289,558,415,813,280,695,760,213,370,953,191,447,836,783,181,474,640,142,852,382,770,408,323,983,918,981,356,938,498,89,891,299,949,811,772,861,144,384,401,117,252,206,241,956,853,661,825,515,43,705,592,335,519,651,413,90,161,979,96,937,167,710,918,410,29,754,733,477,187,256,779,422,13,674,194,383,506,82,938,21,753,168,553,755,78,816,341,123,451,618,906,941,482,188,208,721,660,375,946,976,364,493,294,703,730,145,162,807,104,466,803,712,589,97,286,728,259,349,787,62,364,261,261,47,37,87,373,925,152,746,372,525,485,679,580,502,299,976,208,930,323,264,581,986,600,838,806,611,521,57,533,737,237,228,623,611,547,517,613,310,760,487,43,55,971,796,131,288,991,359,939,321,91,832,407,499,614,635,583,751,524,119,779,119,650,570,871,666,907,713,90,37,581,222,108,39,424,888,195,714,270,881,614,481,823,877,413,868,902,411,604,237,520,282,389,53,143,570,855,150,448,900,473,435,880,416,644,643,128,307,17,452,832,3,234,268,638,364,598,718,563,698,24,368,228,887,303,156,349,507,487,523,25,120,200,152,985,791,614,202,147,18,698,55,304,427,508,968,112,243,696,444,181,386,738,330,852,170,115,126,730,434,354,859,960,808,951,206,316,188,404,155,43,117,96,508,59,431,633,320,850,6,9,426,150,631,188,403,394,389,540,903,246,258,430,786,957,368,991,933,927,539,136,171,685,405,998,42,990,743,113,252,697,723,131,455,573,566,777,932,100,694,409,210,674,818,677,997,662,540,108,914,391,825,746,531,610,611,104,683,439,410,610,640,435,561,522,757,855,497,715,4,388,249,89,720,537,156,426,298,395,45,129,409,582,297,603,922,102,540,296,570,371,484,411,27,305,315,387,301,442,179,264,908,365,699,222,239,224,651,186,368,717,535,746,38,631,139,510,162,616,181,756,841,815,504,779,300,998,123,761,586,408,859,184,376,868,86,100,251,190,338,724,30,117,562,767,53,973,502,47,450,469,878,14,713,89,629,837,30,853,955,873,693,906,405,241,361,681,124,356,583,978,22,721,816,364,742,959,185,398,742,467,914,429,712,815,430,689,623,478,844,736,13,277,92,336,404,709,623,860,549,649,731,539,81", + "888,501,598,337,276,695,219,578,279,917,26,40,46,643,194,237,18,574,35,4,312,226,444,440,768,766,64,372,550,937,707,974,312,41,711,918,737,797,399,237,346,144,509,828,561,444,470,502,257,28,753,50,504,5,429,468,32,495,403,79,414,262,664,262,321,737,764,594,628,112,203,573,745,20,419,993,812,647,723,424,316,846,116,86,275,759,676,515,287,10,911,763,927,526,656,142,359,515,561,435,186,476,686,564,150,713,61,347,616,508,397,387,327,73,493,218,828,793,866,522,517,851,712,424,326,25,676,269,188,963,556,72,702,702,880,964,685,694,997,352,221,58,660,960,348,927,802,943,468,881,957,997,127,824,924,649,588,479,514,425,181,515,150,303,981,16,159,795,501,824,162,20,732,986,713,261,574,542,106,82,952,291,263,681,720,377,776,799,471,899,464,757,668,660,342,804,883,500,420,641,217,567,585,856,313,421,582,221,285,733,745,768,779,717,372,563,664,958,647,342,473,507,316,663,690,325,268,999,644,975,660,982,736,496,673,235,453,681,803,523,340,699,440,736,259,802,601,833,427,0,252,343,286,849,186,310,234,689,140,797,599,484,667,316,331,246,933,590,590,610,385,979,260,924,245,260,809,175,921,669,838,456,849,766,957,684,304,386,514,936,270,437,813,624,904,1,184,726,405,830,222,703,904,507,798,643,51,654,891,325,114,242,285,189,449,908,548,745,940,545,408,677,988,177,342,912,837,291,671,496,790,9,933,773,789,902,806,859,930,855,185,86,152,428,658,915,861,787,634,438,985,586,375,761,812,746,450,595,711,478,396,180,4,708,278,211,781,338,450,553,870,780,670,396,131,403,364,939,804,751,331,453,530,216,725,292,545,534,263,203,7,49,605,414,67,26,997,961,739,903,189,697,757,916,841,60,530,807,719,999,670,450,884,519,161,756,81,355,60,549,452,144,782,590,191,800,593,720,76,315,507,832,584,402,847,466,249,713,780,540,702,387,442,387,102,492,141,588,884,61,975,345,78,681,430,157,946,939,448,903,917,200,526,762,113,735,110,944,910,277,51,545,419,185,314,782,327,972,161,208,46,642,123,338,821,371,95,148,366,977,885,424,954,498,795,32,805,281,30,962,265,747,388,745,474,701,694,4,492,590,102,445,524,924,193,358,657,883,254,176,798,414,449,989,370,970,920,841,149,700,271,556,681,671,261,390,622,582,602,376,204,173,894,20,133,789,704,169,143,910,448,59,709,742,899,734,600,485,386,123,908,149,945,590,497,176,177,59,966,404,319,814,935,413,248,297,909,810,260,70,141,635,105,667,1,10,456,676,181,657,304,67,519,150,20,381,907,242,312,433,965,792,95,80,532,329,159,104,155,938,654,233,423,724,110,322,975,842,681,667,391,491,355,884,711,240,970,995,880,920,602,761,481,46,908,58,926,322,265,119,762,383,69,770,342,562,739,85,544,849,902,897,883,861,454,424,284,483,327,854,589,488,187,87,146,923,7,816,956,771,940,511,949,254,499,341,455,443,523,3,222,137,692,319,184,316,34,177,807,806,13,443,336,69,910,42,204,684,496,394,537,763,402,663,772,139,854,730,948,535,149,399,226,752,202,554,131,678,896,442,117,733,190,904,27,330,637,683,892,514,411,904,856,94,48,443,828,325,664,397,789,479,790,649,619,600,577,305,298,256,568,884,119,974,60,649,999,380,167,404,701,22,254,956,132,836,285,538,946,291,986,39,827,606,282,17,564,317,953,477,978,76,134,26,474,981,803,661,690,426,357,478,289,191,882,443,708,582,184,720,769,213,940,565,449,432,925,852,441,805,654,599,66,174,372,904,543,164,901,398,198,328,596,71,921,343,194,685,185,792,369,857,950,256,898,94,285,169,398,490,255,918,671,672,936,193,498,301,730,874,81,591,346,736,317,436,280,205,794,197,646,698,271,388,795,558,84,576,338,835,9,635,182,380,602,19,919,671,507,89,591,511,406,649,672,180,685,576,153,375,96,192,580,477,69,351,667,823,167,333,858,990,389,457,589,272,664,465,487,157,137,829,32,973,423,17,387,814,339,40,508,841,815,255,581,308,611,332,490,689,304,6,212,346,918,97,202,225,897,305,703,3,300,281,100,383,663,360,982,453,440,157,843,262,383,322,827,92,919,61,875,714,16,857,934,155,682,448,111,694,642,491,929,658,648,718,981,894,762,476,89,532,664,637,769,526,366,678,487,610,306,662,373,903,158,910,606,210,185,905", + "814,324,880,869,684,838,120,286,218,846,751,288,854,647,90,901,604,502,23,193,731,67,113,452,820,296,361,596,963,441,514,164,502,463,761,584,37,847,98,501,116,14,232,248,715,416,255,972,129,661,327,932,386,651,512,335,828,183,387,743,301,223,287,587,972,744,302,422,755,236,698,516,858,609,250,533,46,61,977,284,641,919,385,18,937,911,319,904,650,417,289,248,114,803,661,798,891,540,272,413,453,792,572,313,103,678,747,241,458,228,481,669,155,982,304,187,963,298,107,48,424,409,395,778,208,41,426,740,267,319,616,858,304,474,970,436,104,542,644,489,216,60,500,837,393,647,749,226,800,208,384,667,382,701,763,746,382,879,812,172,908,495,488,618,788,333,481,917,354,530,844,730,796,64,303,671,619,643,282,681,525,10,13,150,55,202,448,912,349,381,292,313,785,425,236,132,647,840,325,865,561,797,371,345,293,196,84,867,928,913,79,136,582,659,916,962,209,740,859,693,939,313,242,882,36,340,695,156,474,823,914,71,841,837,992,304,244,459,764,184,416,431,806,845,232,249,665,845,33,252,0,138,796,155,588,131,724,556,793,351,295,831,210,821,27,398,215,782,96,499,784,131,721,128,410,305,566,157,750,263,30,92,40,228,618,747,188,171,5,160,861,990,311,605,402,391,966,870,575,459,949,260,564,667,513,264,700,523,252,394,495,329,976,489,990,344,445,807,483,505,521,852,818,688,404,466,698,228,17,278,701,456,631,658,575,86,921,827,643,179,867,952,565,682,344,373,910,805,813,488,618,415,742,563,785,487,48,968,345,933,232,743,798,305,928,431,74,274,336,95,574,347,32,40,463,9,858,90,946,869,635,650,888,41,863,49,332,484,243,274,948,278,26,303,365,564,27,720,593,913,176,327,152,334,875,427,905,504,418,264,133,289,596,703,30,923,296,266,198,120,591,982,412,751,369,178,803,63,608,680,510,140,427,852,607,983,741,396,699,164,384,694,915,738,648,539,484,514,735,582,633,713,549,375,330,124,935,684,295,299,583,407,500,642,575,61,152,496,639,423,687,309,317,380,872,128,148,332,498,925,324,27,258,756,716,659,275,417,805,433,608,827,955,616,569,823,690,473,615,187,74,421,963,960,551,645,282,715,372,790,601,859,783,566,100,640,936,590,492,943,676,891,842,955,713,352,358,391,617,842,171,380,137,875,608,436,62,822,106,365,14,828,855,254,335,752,535,440,435,849,547,210,216,894,17,16,19,676,723,560,835,579,927,356,577,576,544,97,850,695,153,541,834,147,577,234,685,354,24,900,414,639,166,648,400,320,883,641,279,231,286,825,670,925,921,732,947,791,454,862,854,997,184,206,763,545,678,644,714,969,625,232,46,305,861,42,112,870,344,726,781,6,62,699,977,352,593,763,350,653,350,489,222,885,951,188,266,828,37,1,518,334,825,17,712,827,599,830,87,454,676,985,814,612,953,222,903,649,221,288,187,591,446,201,506,797,3,699,122,402,599,963,180,539,59,925,197,737,345,816,241,735,966,867,709,286,959,724,619,744,968,559,92,375,953,134,364,220,751,306,998,317,242,282,648,625,323,301,84,939,471,797,346,34,447,436,95,347,191,736,950,558,193,798,733,114,11,820,598,890,301,900,700,411,312,414,448,66,180,97,696,548,493,575,509,238,307,785,692,314,621,644,136,929,844,786,240,164,387,685,439,741,884,429,541,499,417,970,357,62,412,731,820,558,793,293,339,683,653,480,11,709,596,420,508,387,149,898,420,525,433,830,724,573,34,597,955,631,338,753,798,329,348,9,742,573,674,708,361,746,468,817,120,216,327,908,256,141,110,682,149,645,660,742,547,35,603,612,66,584,413,606,268,432,474,712,647,129,262,524,32,428,68,920,589,906,806,189,620,591,82,877,437,327,62,842,789,809,402,207,399,896,875,672,512,430,307,25,778,865,483,980,943,778,363,706,854,624,466,306,367,740,936,866,833,852,434,258,68,628,373,81,157,711,512,556,354,243,618,228,542,528,210,465,194,755,64,911,983,489,214,86,395,104,229,225,231,604,773,548,230,287,42,559,638,631,556,168,729,741,720,155,802,422,550,534,535,773,370,862,920,698,239,5,840,213,506,265,975,769,327,853,317,938,703,908,558,844,432,699,852,238,988,94,656,758,239,203,187,327,317,743,837,833,558,382,630,978,895,866,306,465,913,364,461,190,413,296,639,824,350,688,425,727,826,309,474,2,167,894", + "546,264,5,743,916,940,909,636,107,328,700,313,492,267,292,587,928,38,211,288,939,381,117,939,732,287,316,289,993,678,199,991,898,354,698,75,992,74,571,742,761,464,672,750,248,548,945,305,242,59,564,16,81,214,872,353,195,886,845,144,202,787,900,796,583,612,198,753,38,964,161,138,416,126,654,605,414,121,289,427,101,616,306,767,380,195,890,584,545,345,963,839,302,366,587,546,570,18,881,236,782,166,31,810,802,976,643,616,127,712,12,891,295,116,52,163,618,977,593,853,218,102,579,397,893,897,657,611,339,273,835,379,182,923,912,802,111,209,822,330,464,891,875,49,581,604,79,302,974,98,268,99,335,55,822,986,234,928,921,239,361,847,986,67,443,60,201,754,685,282,666,433,512,930,138,649,652,433,484,787,450,913,795,598,519,31,683,423,385,908,410,288,340,82,462,348,457,614,545,815,116,950,963,375,478,547,308,913,129,381,873,878,496,991,831,333,111,850,82,773,611,146,767,778,570,724,627,407,149,801,318,711,996,687,217,416,236,564,759,688,173,247,122,667,106,60,136,136,146,343,138,0,375,145,248,372,887,401,463,791,409,194,289,200,223,259,937,496,353,153,234,239,838,951,582,346,871,497,858,840,887,323,558,248,522,997,604,35,787,61,937,509,630,276,690,808,335,564,448,988,564,540,811,280,426,319,548,621,863,131,682,880,516,261,881,319,348,92,708,666,521,267,268,119,224,520,782,560,580,383,177,466,794,258,460,595,955,366,771,835,881,529,565,252,868,952,240,456,239,164,252,493,248,343,15,58,829,556,736,677,444,922,450,457,310,290,956,838,149,674,893,89,395,791,590,323,797,986,308,12,756,394,389,335,496,595,467,351,154,204,476,76,569,639,343,604,769,873,624,556,133,891,646,730,774,884,662,457,560,433,958,304,602,527,671,694,284,334,698,574,509,280,610,38,435,813,630,891,397,35,11,359,879,622,368,934,58,270,685,16,501,441,99,170,147,308,270,975,982,967,641,223,506,584,790,482,494,320,128,97,587,308,399,868,542,808,130,780,552,432,840,23,514,483,830,75,928,47,159,839,71,314,327,217,122,826,370,931,917,960,610,55,34,879,501,409,852,932,82,236,797,62,435,994,802,391,917,996,27,679,969,37,169,747,828,513,49,519,976,148,667,731,125,801,361,12,612,395,156,531,753,511,817,73,922,252,786,830,568,224,812,955,675,823,511,69,621,363,174,861,783,183,34,920,311,638,363,624,11,699,418,576,170,368,898,98,125,284,690,822,10,263,133,911,495,311,552,615,603,544,758,437,131,206,172,672,85,364,963,173,645,660,497,854,341,259,573,301,49,818,524,55,381,557,752,589,396,74,920,835,617,860,690,697,39,276,104,273,575,554,483,465,484,819,806,647,596,968,892,955,642,144,704,12,387,739,494,873,843,966,599,300,435,287,9,613,794,19,295,777,166,357,304,891,829,221,465,443,490,968,669,696,79,169,331,964,18,690,596,828,146,580,551,137,954,300,24,54,882,188,518,964,107,589,555,794,759,682,706,462,117,545,416,403,138,783,216,440,604,346,159,979,234,691,645,201,423,416,742,388,277,13,716,223,132,635,398,639,428,45,423,268,52,239,471,76,507,209,753,982,392,985,615,452,526,432,659,153,748,312,110,299,989,673,920,989,246,47,864,723,743,300,255,356,983,705,94,758,470,869,791,223,406,290,938,123,234,235,128,795,918,613,623,88,883,33,689,199,322,496,928,583,547,112,173,966,231,292,98,70,809,568,15,380,679,13,642,650,689,593,844,874,634,860,582,789,960,15,94,694,927,599,319,621,4,844,703,927,733,193,376,71,274,33,827,91,641,790,7,329,685,114,462,388,718,259,367,585,212,958,545,544,640,359,655,256,313,57,65,750,397,482,916,635,143,614,765,162,556,551,38,610,499,576,454,407,836,782,639,296,806,751,230,480,288,633,439,704,707,645,309,766,540,965,136,935,889,236,908,645,444,138,917,559,607,580,719,16,521,688,515,993,436,235,623,619,552,112,271,747,853,98,851,303,783,324,57,434,619,535,281,469,363,99,884,235,85,639,332,355,301,209,187,736,831,921,866,798,835,204,11,595,356,9,947,480,36,206,666,678,410,458,635,598,542,667,279,135,42,820,749,605,741,430,683,140,895,430,489,720,753,822,445,542,646,671,865,593,950,214,142,354,263,974,805,633,738,445,178,966,766,260,34,489,310,971,293,565,474,612", + "374,10,389,702,343,338,935,400,442,238,179,235,577,626,11,499,56,975,983,265,51,510,960,483,91,571,468,59,71,129,383,851,551,283,98,702,12,408,984,576,826,73,3,343,498,839,964,354,495,456,782,213,65,644,954,765,597,536,285,453,34,191,474,114,690,694,660,177,657,301,481,424,227,270,856,652,247,3,139,124,974,649,430,873,78,149,798,844,685,840,240,596,559,212,4,192,66,821,872,120,406,352,23,876,872,617,72,732,724,146,121,542,674,216,146,949,76,432,850,899,694,743,720,240,74,795,997,588,227,560,70,461,584,176,868,516,135,625,132,127,703,809,349,503,151,58,843,280,767,732,647,869,170,922,295,302,139,619,940,699,751,719,408,650,477,763,874,693,700,835,802,928,929,650,207,793,920,292,494,876,560,161,596,252,34,163,188,447,318,191,632,413,708,700,648,325,992,8,792,421,331,797,144,988,223,845,910,386,310,59,257,15,201,644,808,136,176,148,890,252,312,285,963,416,603,729,520,316,963,866,397,422,330,945,745,552,546,728,935,977,70,888,343,632,789,206,929,304,383,286,796,375,0,558,137,689,748,837,530,13,273,810,660,773,242,72,2,438,264,31,333,960,223,985,721,458,59,376,730,198,968,861,320,281,38,448,825,872,63,317,320,598,625,218,326,491,176,356,788,17,76,999,129,895,162,149,986,337,379,569,866,64,670,75,296,235,338,400,206,177,737,832,845,453,661,578,897,47,437,299,160,932,290,197,842,243,201,121,249,483,480,383,845,361,877,835,865,561,239,309,832,581,668,326,654,180,46,440,367,92,107,492,584,399,57,683,358,623,949,805,195,902,845,106,965,567,908,869,923,655,900,82,944,292,711,429,913,887,55,485,962,976,514,541,721,748,951,568,390,872,721,230,857,57,20,149,894,806,143,867,787,771,523,625,672,235,892,210,701,570,594,656,747,151,665,697,909,479,251,848,942,151,400,914,20,871,328,426,761,717,383,177,752,325,946,135,724,678,859,579,813,458,778,782,306,488,594,19,27,699,386,544,986,745,571,83,455,774,693,791,150,778,645,768,548,528,666,810,708,907,56,441,447,58,811,479,324,635,226,828,401,691,81,976,922,679,260,135,496,746,361,274,303,322,869,579,877,446,282,862,184,962,154,997,949,57,530,328,802,131,307,760,933,689,497,301,603,897,414,171,909,601,247,237,711,269,699,239,287,838,579,896,662,221,211,718,730,2,20,366,570,1,688,290,87,669,474,811,685,850,720,968,221,887,373,688,101,743,933,944,381,310,966,129,232,138,749,209,290,385,196,439,306,138,840,745,408,375,812,131,347,501,213,655,967,99,455,31,384,149,572,4,853,697,199,296,31,155,547,447,134,995,989,674,390,134,156,49,401,88,231,864,340,519,642,651,229,48,636,199,9,663,836,490,931,80,902,290,550,82,613,527,159,226,68,643,905,171,342,264,220,660,802,110,379,99,439,788,749,998,509,376,560,652,103,61,828,955,987,443,268,916,228,991,198,787,607,949,759,406,662,195,210,458,480,188,393,888,562,863,517,210,306,811,286,188,701,371,29,867,809,509,438,144,23,911,66,124,118,436,949,923,520,845,331,177,741,882,613,609,17,602,205,779,678,655,331,620,614,112,975,900,465,775,387,484,692,373,842,811,738,418,791,819,850,512,497,240,616,673,12,8,280,608,381,595,556,666,539,502,786,857,197,372,560,777,757,471,537,637,856,150,926,512,564,313,313,318,421,342,1,224,352,966,797,109,172,955,463,281,609,561,522,627,38,930,388,489,864,905,297,952,847,739,562,344,660,120,358,567,304,875,627,825,291,500,26,366,768,522,113,24,708,871,850,209,807,555,338,55,942,873,731,48,490,165,819,288,855,355,566,785,766,127,714,734,468,527,590,523,164,916,298,71,955,57,626,895,600,738,458,97,47,204,886,470,521,720,793,6,255,583,300,558,96,43,178,645,560,545,825,468,301,400,887,18,880,611,297,240,291,759,121,861,196,673,307,779,160,466,88,964,550,341,606,700,931,925,892,637,304,478,990,491,106,319,977,469,888,205,917,303,920,888,614,161,833,854,68,608,785,888,71,550,390,988,199,867,752,184,617,140,732,841,781,383,755,852,180,93,249,340,386,63,338,463,377,389,247,335,187,637,664,758,217,460,212,575,148,487,522,663,650,279,305,334,776,464,145,767,906,714,981,581,340,475,946,339,833,625,123,951,728,245,296,766,407,251,224,576", + "771,538,660,585,55,791,557,68,525,740,956,770,582,616,418,225,626,705,45,37,219,554,45,679,471,461,408,627,970,128,769,599,629,634,798,125,427,107,342,322,202,191,349,810,439,866,888,116,412,376,212,113,606,421,188,423,208,5,113,898,240,971,91,553,706,482,726,500,309,678,657,4,149,86,60,750,8,503,576,479,865,907,98,152,876,232,429,821,198,50,611,627,597,539,253,196,656,713,428,230,552,949,872,129,843,488,746,781,281,359,129,747,930,303,435,100,680,19,231,545,110,535,340,765,815,945,601,724,379,942,282,351,173,474,152,765,790,44,934,7,278,482,825,559,876,63,209,188,789,495,106,109,740,293,592,168,343,942,553,996,613,480,724,726,179,936,520,854,34,635,468,455,44,277,744,356,742,612,772,949,595,232,438,541,891,123,164,55,576,558,369,244,67,395,32,5,762,717,681,80,589,832,570,289,675,765,150,838,777,371,4,601,105,660,292,216,916,84,35,583,42,900,858,357,917,705,794,53,336,305,204,42,461,837,320,18,645,244,531,168,175,286,301,740,503,680,878,805,567,849,155,145,558,0,262,561,162,196,123,45,205,876,263,162,342,258,47,748,279,620,875,132,133,443,21,155,975,649,988,72,369,382,567,429,718,418,161,191,484,237,754,190,322,43,993,783,581,224,566,296,496,574,231,440,79,381,125,892,531,17,338,983,423,382,102,670,746,14,322,541,386,239,752,545,797,824,332,960,229,693,340,355,939,278,809,816,152,512,604,190,670,742,943,427,527,234,786,194,816,103,225,985,863,207,860,308,229,145,80,698,735,685,263,425,956,213,16,912,653,172,783,72,714,276,355,511,642,570,331,382,982,887,846,431,472,248,43,142,921,635,936,327,94,87,585,296,249,866,984,604,687,732,786,705,30,456,596,704,371,963,648,986,150,762,102,971,594,204,767,277,924,932,836,722,986,22,963,541,696,681,273,671,628,442,420,964,559,848,494,169,244,49,490,166,725,535,806,421,651,104,193,208,88,629,937,894,642,682,371,256,233,563,562,373,176,473,759,204,302,377,332,370,44,18,233,686,235,421,115,678,753,213,520,949,795,783,128,414,404,986,865,161,209,310,532,126,429,171,781,612,672,205,868,861,364,777,891,489,733,532,239,359,241,47,75,236,272,300,947,835,820,523,649,766,644,719,790,794,791,462,337,781,415,69,933,314,393,823,315,712,319,950,40,312,486,740,18,111,902,60,508,50,896,434,884,344,564,760,680,321,657,572,876,423,882,860,398,416,228,861,596,409,604,215,242,44,746,418,853,670,999,426,93,221,613,656,272,902,996,617,956,324,980,943,766,292,461,699,284,216,981,944,944,20,820,421,861,23,484,773,969,221,939,181,279,425,75,902,258,231,642,658,356,57,444,909,365,629,390,563,165,291,100,282,267,911,6,382,435,520,546,136,675,530,378,535,679,591,987,918,75,454,587,609,304,876,358,150,174,234,686,388,914,489,653,503,657,122,986,780,448,10,520,722,927,497,869,696,337,957,528,646,375,568,369,408,47,887,16,371,114,404,253,146,483,737,955,627,372,807,903,565,704,105,970,379,828,897,538,595,35,320,791,162,913,11,778,934,431,672,124,363,537,972,775,893,42,229,318,220,809,766,852,408,325,337,167,595,335,502,33,566,423,426,428,305,48,263,707,897,62,400,720,591,489,892,187,50,105,487,860,768,160,911,430,472,693,812,735,59,932,363,6,150,762,750,384,464,28,110,200,940,987,134,928,973,835,193,11,453,386,891,190,413,708,937,192,260,554,418,32,585,751,747,83,3,187,371,446,544,255,252,226,230,932,110,996,737,770,231,660,104,585,370,361,472,483,446,476,793,827,264,235,217,646,609,486,33,357,56,75,840,569,162,612,993,291,189,899,892,161,884,529,161,239,678,138,241,618,583,139,590,945,194,693,634,810,548,153,223,16,94,413,799,196,40,94,367,647,996,416,77,177,47,241,53,875,952,542,758,303,331,719,333,818,71,968,680,791,380,300,609,389,751,147,173,538,61,723,599,950,190,764,971,978,314,915,768,108,735,36,892,43,433,442,796,787,544,906,145,559,943,974,416,90,636,717,740,710,121,588,895,247,785,643,499,888,649,57,690,825,410,8,377,110,297,212,130,127,945,392,247,972,533,167,330,95,102,604,594,947,297,476,791,167,435,572,674,339,627,155,238,528,414,102,293,83,629,887,910,338,80,922,740,691,507,568,509,707,432", + "683,808,481,401,767,594,541,607,533,853,955,101,701,561,360,998,433,388,108,444,103,881,412,563,868,265,862,265,655,813,488,230,994,215,263,561,905,397,902,503,478,728,767,538,673,944,883,149,988,917,826,496,733,472,619,463,638,232,349,690,984,153,235,808,373,303,805,916,647,640,927,353,231,925,19,397,630,140,292,212,926,797,522,812,692,881,374,723,252,186,152,249,849,177,219,201,171,946,72,288,160,886,887,757,73,200,340,619,301,846,698,255,191,722,880,997,350,33,425,660,439,611,514,830,536,919,63,19,18,502,609,522,548,637,276,330,758,392,332,898,114,495,121,75,443,575,133,212,969,891,810,402,836,820,751,235,994,424,12,723,231,756,609,737,391,892,280,933,561,654,793,390,76,824,88,726,29,452,204,311,664,864,491,395,887,214,816,188,591,607,550,522,930,695,598,763,334,110,965,255,850,352,147,321,855,578,237,529,337,217,175,105,58,14,413,941,24,642,968,541,658,371,734,244,223,994,724,116,195,376,711,887,579,6,643,685,430,851,259,283,524,972,498,989,148,738,157,583,38,186,588,248,137,262,0,733,827,26,758,389,468,648,45,181,702,24,274,539,578,589,792,642,883,841,920,875,73,976,973,323,751,735,32,393,512,300,736,770,788,621,363,225,794,194,431,55,989,212,880,905,729,849,273,344,643,465,394,125,951,343,892,872,849,653,447,711,555,932,646,203,528,801,941,278,401,180,866,610,301,217,903,585,140,156,569,557,271,718,103,857,436,577,5,641,886,128,615,993,830,491,759,82,439,175,549,650,568,963,132,152,756,67,778,104,939,160,964,629,306,688,118,272,920,461,573,172,395,355,147,529,944,33,402,99,466,76,470,981,798,556,948,745,79,146,88,319,846,715,264,994,685,37,594,144,852,326,656,704,356,544,390,699,325,73,999,468,412,732,487,162,864,90,38,811,87,974,273,564,404,444,245,432,974,270,362,13,599,929,691,312,892,678,237,16,340,652,347,823,659,997,684,163,803,216,848,518,309,675,169,128,634,842,954,994,820,127,131,802,535,768,990,887,430,523,623,646,106,384,633,386,16,423,428,33,943,727,433,846,45,672,240,101,171,721,60,524,582,520,159,288,592,323,670,465,405,306,183,58,368,120,472,565,475,903,126,960,761,335,219,587,708,639,459,921,776,507,569,96,470,54,837,874,824,187,601,74,915,287,999,520,285,385,420,355,111,12,770,47,617,39,259,313,682,302,820,121,502,356,560,450,445,97,626,832,89,25,286,547,286,910,418,346,506,69,184,447,32,295,8,824,703,774,990,6,211,828,242,383,569,619,418,509,288,868,997,538,449,564,269,438,55,653,702,8,334,602,108,391,835,71,301,553,751,265,331,684,295,675,957,216,12,189,324,588,560,159,484,594,801,990,828,179,641,979,97,44,40,374,998,794,274,811,442,339,77,171,782,716,157,77,61,743,398,330,178,359,133,441,463,971,89,860,124,312,365,190,255,670,431,223,481,147,836,897,272,911,856,214,512,294,264,885,594,334,726,226,933,46,417,380,412,899,471,208,25,369,345,860,157,112,617,905,525,757,217,554,41,966,465,598,286,841,545,110,228,218,222,45,906,155,211,99,168,668,638,780,938,742,939,920,289,293,118,843,900,992,856,546,962,475,65,826,953,834,492,518,802,824,632,117,107,820,368,864,730,412,483,840,720,866,728,440,39,548,829,424,111,739,21,693,13,182,72,501,304,547,129,465,6,534,221,235,24,616,624,525,828,125,85,36,699,789,18,672,263,695,435,51,866,110,246,949,443,906,143,602,987,153,701,612,813,658,754,217,752,970,874,409,570,890,644,697,841,54,904,228,440,57,312,494,671,488,839,970,7,693,289,782,964,166,359,822,159,932,474,124,387,560,213,12,778,140,996,330,921,882,352,809,659,211,888,271,431,129,918,755,980,141,446,667,211,898,925,192,388,24,464,889,406,312,700,381,251,50,689,79,446,617,81,578,460,923,994,500,645,869,243,550,559,915,541,956,341,178,321,466,267,663,126,271,804,913,719,976,514,85,931,48,168,309,385,733,280,287,517,455,388,50,617,526,879,626,463,833,605,554,852,847,651,66,116,318,363,85,490,279,946,862,399,645,615,735,284,404,800,352,826,163,752,99,678,155,653,176,766,534,322,593,301,329,262,237,828,765,66,795,531,593,717,793,361,365,365,164,246,436,101,991,266,349,492,712,907,79,301,841,151,923,913,169", + "730,114,221,725,754,427,706,755,416,596,732,496,357,860,293,418,382,729,421,108,57,75,406,544,790,655,975,909,724,688,440,285,328,675,843,408,986,120,443,444,521,570,589,273,59,507,977,421,699,643,229,252,278,538,632,167,600,4,41,241,800,9,879,530,937,540,186,379,855,240,677,92,977,511,957,565,521,346,2,615,616,674,603,135,509,75,502,890,555,627,593,311,842,607,753,12,977,550,337,101,174,49,906,270,124,500,782,684,570,274,273,257,9,180,372,977,69,947,424,91,565,958,214,865,562,789,523,798,232,181,988,905,819,738,849,365,240,682,753,624,985,129,926,930,94,849,538,729,794,129,257,846,196,494,51,1000,642,874,899,233,136,611,353,321,668,407,562,3,764,146,214,212,146,609,347,890,981,292,567,719,872,155,432,758,213,732,788,112,132,110,916,700,149,517,911,366,598,488,502,743,9,393,847,527,295,414,188,6,889,565,697,515,733,295,70,149,511,460,806,432,586,605,85,800,749,157,209,898,639,866,576,885,999,307,296,840,549,62,222,81,650,916,706,569,245,418,401,59,851,310,131,372,689,561,733,0,821,14,913,311,651,687,503,737,156,442,799,55,513,401,204,313,395,393,332,721,117,200,578,261,259,761,418,396,691,287,240,270,818,752,443,710,90,867,112,803,630,257,918,749,33,284,416,164,443,862,994,734,139,150,971,591,457,43,560,939,880,745,191,518,576,893,143,367,298,313,484,74,844,679,42,317,494,764,967,626,916,217,109,422,816,186,541,153,579,837,282,573,132,991,204,139,996,406,231,154,125,565,674,478,552,884,737,161,376,930,581,346,193,506,142,541,726,249,483,581,28,936,48,865,552,145,331,324,102,189,218,679,239,638,942,510,635,956,529,903,278,824,632,535,502,72,157,792,560,777,675,558,185,876,475,880,676,81,920,152,943,927,264,401,508,689,769,573,749,148,781,401,859,411,53,428,667,119,753,440,534,965,653,74,620,992,796,638,51,919,614,55,819,510,900,190,696,70,603,646,961,396,763,528,980,859,937,651,474,633,595,837,446,657,887,266,172,952,320,119,276,323,408,136,31,480,621,927,901,384,6,170,293,217,979,592,161,381,542,789,610,957,144,619,260,11,276,713,390,607,995,802,490,702,371,368,87,825,90,455,523,915,414,894,939,672,49,693,223,852,735,501,85,341,554,502,872,788,640,394,18,958,190,920,964,972,313,313,474,568,630,341,581,919,243,315,914,699,298,848,355,188,986,346,409,419,358,705,97,596,440,784,833,406,623,498,432,630,296,725,570,529,645,473,805,191,132,94,818,33,673,184,218,637,751,734,813,506,361,398,314,689,160,693,196,491,751,53,969,330,497,713,542,810,136,351,185,960,940,670,956,694,204,368,261,121,9,472,450,914,151,717,338,237,837,27,269,587,443,279,521,708,770,796,328,640,361,15,625,186,180,206,480,925,190,440,871,600,268,818,44,981,134,440,449,644,329,639,919,275,790,780,146,482,155,680,699,330,153,971,895,201,389,93,838,883,277,589,39,937,161,492,669,978,261,349,387,640,988,300,596,84,649,571,452,122,904,743,218,661,903,770,431,424,247,937,123,630,944,614,553,414,425,197,57,2,252,710,457,924,321,425,621,890,402,459,142,818,350,425,212,101,497,513,653,744,211,895,401,241,658,896,715,587,34,705,8,966,413,137,293,998,61,54,756,274,759,722,178,155,268,978,340,33,828,996,830,162,504,576,386,304,693,362,650,584,821,555,519,725,279,204,938,842,806,963,645,624,275,431,711,523,217,332,913,968,992,15,328,875,377,893,322,347,122,75,337,892,28,677,35,70,308,121,925,974,39,903,321,368,495,450,294,19,842,270,264,636,79,977,125,853,823,311,786,224,932,147,409,977,600,296,216,84,458,602,408,61,582,641,512,880,993,510,424,370,486,888,163,701,605,789,89,157,971,68,60,347,447,609,713,542,240,342,642,874,676,34,535,478,807,35,108,541,611,670,988,323,53,470,997,827,70,365,82,941,736,916,464,842,443,699,955,441,782,234,404,954,890,891,308,803,89,290,205,180,665,144,816,235,631,479,708,743,201,533,649,964,721,247,419,529,231,337,374,560,389,424,802,463,643,898,375,3,462,648,424,84,589,609,188,656,754,77,625,268,779,942,19,715,381,311,80,550,407,874,980,930,795,846,821,620,18,577,29,435,912,193,780,281,257,511,256,144,903,187,909,995,217,937,577,923,407,776", + "478,389,771,478,289,825,587,853,212,377,322,492,398,764,966,113,179,701,254,696,882,432,156,981,220,752,211,552,769,697,440,992,708,934,124,916,865,151,541,165,174,883,829,442,776,960,64,917,378,524,566,496,395,861,51,632,383,731,380,409,192,534,557,171,1000,84,589,49,973,428,207,766,151,514,308,626,66,434,842,217,807,507,649,646,277,429,486,147,952,18,178,519,356,297,976,645,786,112,142,537,551,947,56,743,647,312,935,953,366,271,889,850,557,810,971,832,975,937,166,12,791,330,23,168,452,283,575,251,886,568,44,719,781,425,599,982,763,297,47,995,120,37,670,601,746,722,174,613,349,796,740,978,787,308,169,502,147,722,568,285,615,669,727,705,302,239,756,443,273,309,449,151,436,731,700,73,282,665,876,451,495,284,377,394,822,427,335,51,197,998,838,420,278,269,956,952,565,143,602,895,683,745,614,82,385,606,714,887,116,820,326,544,66,118,485,604,8,643,165,823,384,530,960,936,467,211,523,166,80,642,658,392,902,544,904,138,904,583,717,3,509,182,798,925,334,151,179,47,99,234,724,887,748,162,827,821,0,200,760,986,329,255,239,178,241,427,567,944,233,108,831,787,463,639,86,888,487,638,154,422,608,355,118,108,290,864,990,331,713,234,559,285,697,179,497,579,919,729,749,520,874,759,696,578,264,540,239,447,252,946,244,4,269,760,341,812,979,902,524,317,83,206,344,821,545,744,357,295,161,558,270,189,902,500,189,973,822,590,551,919,512,808,848,214,469,993,483,360,464,523,680,500,418,956,970,20,701,341,639,927,295,906,714,707,62,82,481,492,982,169,89,930,472,333,171,111,367,453,349,831,72,875,105,923,980,965,174,208,301,62,54,225,450,309,643,262,325,721,378,224,790,480,782,338,678,230,951,607,405,241,200,230,425,376,960,621,948,314,622,558,604,901,654,464,869,371,289,129,393,759,936,251,112,300,753,67,897,311,325,829,382,602,45,815,959,297,248,255,134,969,117,660,765,207,94,227,708,796,361,471,130,103,807,732,84,404,184,827,712,889,912,125,906,156,9,762,830,349,933,61,650,895,226,812,312,566,617,304,350,376,854,184,911,306,408,576,748,261,352,349,320,658,754,285,616,601,576,14,676,848,710,9,720,493,222,171,892,385,883,300,347,711,157,602,745,508,347,122,758,757,95,547,768,42,575,704,395,741,748,30,491,632,348,845,540,697,209,280,50,817,741,94,809,206,590,657,17,556,452,674,962,194,54,933,584,14,411,150,873,535,200,220,233,961,798,813,496,788,109,739,213,775,611,134,283,744,687,775,676,318,684,52,685,811,648,717,629,326,234,389,686,628,680,949,78,678,486,325,994,16,190,866,372,205,908,577,588,86,5,9,405,749,831,373,607,96,927,210,768,477,813,350,358,989,99,968,756,378,10,647,879,954,105,568,215,16,961,142,243,581,429,225,207,762,409,505,74,976,324,130,735,379,493,508,404,85,852,28,816,655,128,171,896,530,886,998,129,818,572,19,627,562,501,473,618,132,164,531,846,347,364,282,205,213,321,801,869,146,660,450,841,87,269,347,503,250,652,252,201,421,214,633,121,543,45,236,197,352,86,248,287,372,188,396,143,110,108,858,179,618,572,741,874,582,258,260,724,112,291,543,961,473,362,808,250,355,35,841,507,512,525,149,201,908,235,711,273,720,418,956,39,48,168,271,31,461,80,867,311,564,871,142,707,546,757,476,827,907,593,811,814,750,943,43,570,996,592,197,493,536,59,516,349,707,841,908,721,261,250,236,982,366,234,285,936,401,188,932,125,827,236,927,989,458,216,644,306,286,746,315,810,196,815,55,151,39,103,778,129,281,306,472,110,526,616,332,30,348,674,482,182,217,965,67,668,278,657,152,946,856,786,197,990,577,469,3,730,542,786,661,603,405,781,79,573,884,837,624,623,682,51,271,347,43,520,23,917,720,609,880,383,547,141,811,709,740,294,502,327,868,384,131,23,653,916,642,999,641,406,228,61,666,58,982,221,503,311,81,531,199,811,637,570,74,531,58,411,286,67,771,396,894,931,432,720,742,295,635,475,558,22,420,574,517,988,474,314,65,912,279,952,440,204,545,69,748,549,387,372,771,56,995,27,465,315,755,124,544,835,190,801,192,766,724,49,231,36,434,469,999,669,814,384,737,301,60,924,757,753,886,416,734,599,67,700,949,737,10,657,349,169,235,947,590,967,514,58,992,561,105", + "446,563,398,889,190,688,419,301,222,188,865,7,928,38,373,211,458,76,540,496,461,219,899,381,395,716,117,131,247,438,5,158,347,700,800,843,737,254,65,695,217,699,671,502,307,391,326,464,991,6,543,48,453,918,851,144,865,706,48,738,44,112,499,204,678,740,801,780,826,808,385,114,201,739,651,798,991,902,65,788,26,269,652,857,367,101,241,802,175,667,32,367,690,944,49,236,654,459,618,51,205,991,463,46,83,296,932,738,354,602,436,56,761,181,987,310,581,699,96,374,212,59,880,319,876,484,438,641,940,189,207,967,592,317,158,432,429,312,265,73,578,260,898,977,111,524,907,170,102,289,527,437,840,351,168,560,313,580,461,562,705,65,536,379,543,605,329,809,313,218,119,57,190,62,583,358,915,491,132,902,833,680,121,770,804,777,485,70,38,191,909,258,427,705,521,197,546,730,969,207,941,230,312,815,521,7,208,676,786,565,266,751,856,534,297,416,710,316,340,157,998,303,311,98,91,45,92,608,737,973,845,570,854,113,528,448,574,511,38,487,23,49,902,674,288,469,409,854,175,689,556,401,837,196,26,14,200,0,927,900,446,980,911,143,822,336,526,99,129,885,446,621,432,317,196,175,672,124,301,539,523,977,924,118,171,341,448,187,81,87,798,541,947,398,872,754,758,414,761,842,985,920,141,542,351,388,657,284,503,968,436,87,76,651,10,573,617,656,268,512,761,850,55,748,799,376,74,771,144,189,265,544,84,772,862,438,544,387,435,647,770,182,245,732,564,758,824,264,416,420,9,484,457,894,923,90,787,571,624,388,233,637,995,150,435,581,565,180,642,990,835,1,532,265,464,411,722,654,606,880,207,406,962,27,877,601,956,807,546,57,879,139,897,443,883,390,936,160,724,387,112,651,722,469,623,345,519,324,988,39,416,981,188,782,230,124,645,497,391,37,816,559,742,368,788,74,323,107,378,110,17,205,103,456,352,628,983,244,712,577,325,502,181,829,624,288,541,751,893,40,430,963,903,601,391,609,932,989,353,803,203,313,135,159,95,999,353,97,843,940,998,505,857,197,144,90,309,947,485,469,721,388,895,651,834,49,847,40,808,379,280,841,656,6,709,990,782,189,572,641,905,429,86,921,130,561,40,965,251,197,377,650,192,407,842,118,825,226,156,228,451,409,356,862,711,54,861,922,120,589,339,824,832,660,703,772,391,981,991,100,466,129,497,185,629,996,321,884,983,64,675,833,14,542,286,770,865,905,657,675,577,569,11,836,426,448,354,820,949,288,32,270,180,11,741,319,535,152,648,33,696,807,233,492,151,458,308,479,291,614,666,608,109,560,692,101,242,437,687,194,203,411,529,508,352,689,83,592,191,394,379,319,768,281,636,857,447,425,773,853,429,575,291,902,787,553,538,641,465,143,928,140,339,633,702,836,616,757,850,700,384,569,551,946,638,830,9,760,376,768,680,25,252,210,967,691,231,849,104,967,675,730,138,216,663,652,642,607,300,236,266,243,78,295,22,964,709,249,719,569,689,228,959,247,285,555,246,665,132,346,87,665,905,588,253,554,702,752,239,203,404,972,541,557,17,711,182,525,43,438,134,229,740,486,80,137,27,120,418,120,667,1,912,742,64,298,226,273,811,427,547,456,960,822,630,646,793,319,48,125,382,189,629,888,919,739,514,115,78,317,654,724,106,882,936,832,941,142,112,550,609,331,708,832,473,698,363,273,612,259,107,486,604,277,98,72,898,660,974,279,297,65,173,597,879,958,152,461,87,231,947,95,99,838,919,702,735,359,88,661,168,401,796,905,791,296,817,367,773,164,603,845,350,113,112,234,908,879,67,464,456,668,617,909,353,910,40,896,534,315,72,878,476,746,468,47,276,988,605,340,679,241,929,511,785,594,908,764,286,708,742,962,311,167,565,903,588,471,10,569,442,471,475,981,105,616,791,273,728,407,268,908,108,822,385,934,426,358,26,472,934,26,846,953,681,559,388,403,26,507,823,792,460,278,809,78,739,242,362,982,946,728,806,841,67,685,648,66,400,452,38,647,681,3,705,29,853,346,824,627,607,635,105,960,17,715,96,960,397,119,868,505,376,216,87,456,161,911,676,326,875,787,810,687,716,751,181,463,982,601,390,922,513,339,892,424,809,615,526,35,379,688,854,576,819,287,958,129,979,907,866,243,226,256,474,889,359,776,852,579,783,139,460,893,987,243,553,644,416,832,746,418,167,566,435,730,463,919,413,184", + "456,375,304,796,185,535,755,494,225,313,592,867,755,459,489,156,978,538,947,664,591,443,873,809,550,377,918,62,628,601,680,858,324,572,41,515,268,307,240,466,732,746,994,130,379,601,999,233,360,219,373,426,781,703,765,871,487,868,779,836,178,247,601,914,413,442,158,904,221,645,110,333,209,99,254,155,42,424,363,932,138,275,875,744,779,664,997,239,622,628,634,966,160,29,584,637,127,303,862,103,710,404,813,8,404,133,792,815,589,170,91,22,547,40,702,15,147,725,288,905,856,75,645,311,626,568,445,219,814,5,201,773,997,178,618,445,565,236,236,814,238,192,844,726,615,630,179,697,387,682,624,954,994,234,405,98,11,691,564,567,872,140,676,106,691,460,8,623,301,340,588,237,356,675,448,693,493,762,540,22,667,810,131,659,494,547,216,32,162,431,348,856,113,528,859,407,988,446,489,932,965,830,567,845,392,808,989,736,831,515,79,196,575,528,949,466,944,723,911,231,774,451,288,221,310,980,111,664,432,39,215,806,996,784,400,919,938,486,518,657,680,1000,730,465,640,571,99,75,744,140,793,463,530,123,758,913,760,927,0,757,414,540,762,48,408,602,628,891,110,82,27,463,573,521,644,255,721,972,95,13,261,383,893,279,378,213,27,296,241,807,363,240,532,447,56,7,782,367,504,930,70,340,520,974,712,164,386,462,262,672,930,491,774,604,150,984,541,234,144,296,951,953,513,680,556,7,622,936,433,871,946,537,698,78,408,690,751,178,743,981,628,627,986,756,926,935,551,80,883,89,453,906,64,505,544,425,148,996,413,2,67,66,553,274,149,890,482,660,29,391,512,725,244,644,536,348,384,903,316,702,865,997,473,276,809,275,818,677,911,871,932,32,600,546,215,569,424,621,880,290,745,258,505,6,456,897,868,450,367,342,767,280,525,980,421,593,925,135,753,791,336,290,951,124,140,877,167,918,995,420,403,280,801,401,602,731,25,3,760,19,627,27,248,404,827,900,297,540,705,465,170,916,350,793,157,637,638,768,834,835,507,323,18,865,882,391,907,646,201,500,312,93,94,596,739,762,877,21,853,999,476,804,776,687,81,441,15,345,916,561,160,172,986,682,322,326,951,347,640,602,383,714,418,785,982,15,282,275,54,764,518,652,743,341,512,218,748,39,264,443,972,679,788,794,227,256,921,827,777,701,604,386,735,44,954,42,897,273,704,178,298,217,982,438,971,32,271,56,300,807,106,214,707,528,502,864,976,797,145,312,798,23,115,697,988,545,856,866,72,328,862,959,890,525,401,865,712,257,505,909,767,555,403,514,624,673,594,172,240,826,532,819,463,238,76,792,685,392,408,227,831,451,622,359,93,92,522,473,235,169,715,611,690,87,276,521,31,231,198,526,959,808,342,452,212,474,859,133,860,916,487,859,235,725,562,260,893,223,442,699,604,909,664,108,909,55,566,867,718,888,68,154,504,953,873,450,553,2,969,959,419,165,499,358,911,603,653,326,108,299,674,286,949,784,691,848,975,17,101,2,756,216,447,492,993,374,226,22,455,634,210,482,519,278,888,460,142,858,312,992,141,362,992,180,850,972,243,380,287,202,417,345,678,260,513,14,342,256,233,699,102,566,539,51,107,947,866,40,253,925,632,990,937,401,162,710,814,527,270,242,301,766,376,184,898,659,167,240,68,554,619,999,795,223,14,739,543,674,419,25,32,634,859,481,939,720,663,409,856,876,982,784,343,893,173,264,144,243,613,581,414,134,317,780,170,34,523,18,67,453,311,669,767,620,187,241,90,804,311,347,591,717,744,739,642,482,239,349,805,920,929,433,57,113,889,858,763,305,246,198,509,587,713,660,816,986,227,29,710,168,684,204,847,1,348,369,997,238,875,921,511,55,191,385,751,322,128,208,214,641,79,159,802,752,567,862,537,239,816,515,6,917,111,263,942,518,428,765,129,814,39,202,107,278,77,925,112,662,234,283,388,246,400,117,89,699,146,924,285,52,230,228,641,776,847,543,524,946,681,603,833,521,342,766,424,353,593,772,461,288,981,585,168,78,138,749,354,511,949,746,716,898,505,934,597,712,78,413,307,206,600,173,836,777,239,724,733,165,944,579,526,643,997,186,62,325,349,457,167,77,784,219,477,381,595,445,446,658,497,608,821,358,782,453,643,159,414,626,314,246,453,487,280,444,450,360,771,236,410,446,502,175,191,963,785,198,804,559,937,950,274,364,414,613,750,26,818,679,185,181", + "447,421,816,244,906,185,576,359,349,234,89,627,604,285,668,283,771,956,513,960,370,575,657,543,580,244,847,540,541,187,79,32,160,571,973,923,717,418,253,683,267,116,453,458,603,922,979,256,767,789,198,435,804,355,535,698,936,432,558,389,743,964,891,333,242,330,89,397,299,516,651,596,720,787,538,864,952,43,651,767,154,840,966,401,454,266,760,668,704,245,253,471,755,78,742,363,90,120,985,519,192,49,145,732,813,673,898,113,797,596,206,832,562,381,695,847,249,976,867,67,654,99,261,245,853,848,429,170,433,815,126,821,311,349,150,921,178,956,589,508,432,682,87,498,794,657,890,328,366,388,860,302,241,755,722,794,858,612,645,837,365,198,100,886,485,448,18,627,26,314,174,739,691,273,996,431,82,919,740,586,130,873,516,561,137,271,864,963,456,843,730,351,536,784,488,100,392,291,739,46,527,866,258,985,764,128,646,76,708,526,40,371,365,987,584,415,255,528,780,610,89,609,327,677,864,466,415,592,364,603,634,293,71,138,35,482,866,158,296,208,20,651,452,772,298,11,85,693,540,797,351,791,13,45,389,311,986,900,757,0,993,796,945,995,728,747,543,417,41,802,378,694,362,63,134,732,296,640,740,458,189,45,947,823,262,335,198,65,819,682,795,734,763,80,64,619,329,779,37,774,556,381,72,532,576,640,647,124,23,784,552,776,344,505,522,381,176,907,304,188,325,317,590,413,574,688,257,737,603,450,670,77,232,730,105,772,60,927,518,246,172,264,929,84,521,260,123,356,327,736,343,954,312,884,482,266,131,376,717,611,223,143,115,875,321,807,995,898,403,1000,374,29,109,31,788,29,676,655,542,35,885,906,102,795,848,240,338,845,952,412,102,947,363,827,464,328,898,55,219,943,459,270,783,395,858,719,885,863,319,594,893,610,457,808,520,192,97,379,800,75,944,857,396,978,463,799,870,56,61,400,301,689,19,793,286,444,467,620,316,867,591,548,319,393,862,882,684,607,97,736,278,869,348,463,378,98,916,868,190,499,527,898,386,689,112,614,896,686,361,438,80,323,699,312,385,341,497,223,16,155,101,995,615,566,852,97,166,884,318,20,902,50,73,626,264,120,565,653,346,77,888,303,323,799,471,904,460,146,146,407,230,440,267,414,700,379,952,905,103,707,584,949,15,179,123,409,452,885,474,878,846,642,463,964,378,629,235,690,909,885,69,613,365,137,547,685,725,182,7,963,339,501,238,140,208,217,934,68,959,148,420,963,908,890,567,265,207,680,95,701,868,79,597,274,101,100,276,914,231,994,849,532,389,425,601,666,402,260,299,263,971,315,878,62,211,164,266,539,594,659,657,458,217,545,648,390,26,365,916,914,855,527,555,124,627,29,260,959,790,394,796,515,957,447,642,89,754,322,137,318,819,809,909,206,652,656,314,489,889,108,637,930,107,382,732,2,308,33,463,681,776,230,507,94,847,380,733,713,99,945,945,889,581,524,464,390,976,796,145,944,208,925,207,48,201,391,708,244,275,722,616,874,747,686,627,903,269,164,741,450,546,652,925,114,313,352,747,731,273,669,49,233,887,614,144,926,423,189,317,186,336,519,837,794,208,345,258,39,374,149,703,945,697,739,733,172,995,549,670,630,853,104,614,462,363,990,362,36,932,96,449,286,286,874,30,137,147,591,127,943,974,691,835,982,509,809,262,372,922,206,792,696,383,522,465,180,730,419,887,391,116,802,8,380,896,334,801,888,261,810,746,580,946,207,907,331,509,522,950,892,978,89,366,406,252,631,679,559,562,985,415,489,322,242,876,437,194,31,312,499,106,200,430,97,484,598,641,386,781,851,72,507,182,916,54,916,192,170,345,91,999,19,630,274,148,550,341,348,866,820,679,367,388,256,546,374,507,872,814,297,579,568,34,144,64,745,865,696,283,439,221,571,527,984,570,573,959,416,386,903,265,765,715,853,984,252,700,603,107,940,454,220,502,125,859,431,174,310,918,65,386,679,476,775,349,76,673,383,669,145,235,80,494,120,259,838,112,804,650,857,164,827,943,968,990,517,980,907,879,131,202,438,716,573,277,228,42,370,907,261,90,662,137,288,227,201,454,396,356,292,472,182,454,868,962,133,126,563,499,445,879,930,318,50,717,866,994,900,365,493,390,303,144,308,950,557,729,992,556,309,393,928,314,538,654,336,452,908,303,685,129,343,580,359,22,556,585,989,880,1,464,260,336,564,744,856,547,448,297,572", + "369,267,918,310,463,420,642,193,213,928,131,968,890,35,285,224,671,56,27,531,74,559,179,455,625,938,34,978,48,154,338,248,462,374,341,773,245,832,367,473,988,177,876,568,501,828,499,264,492,485,825,159,854,222,379,423,915,881,678,549,112,702,494,462,4,812,564,52,458,48,807,670,72,452,368,635,684,812,838,859,429,424,442,178,797,51,9,680,379,424,281,284,545,641,155,653,162,188,496,240,61,460,978,876,948,215,907,193,694,898,191,874,169,514,668,370,744,216,584,682,710,614,333,348,188,446,142,17,847,430,519,839,332,349,483,718,321,18,995,40,392,732,794,458,914,306,317,230,816,901,115,337,486,494,357,56,850,894,866,113,380,431,547,37,525,936,655,581,651,522,562,614,466,274,999,45,368,265,106,744,111,676,328,617,786,851,839,386,830,974,141,925,225,561,805,846,245,172,965,929,446,759,856,323,173,499,193,653,111,885,970,434,917,846,585,171,104,966,125,72,365,246,967,145,694,26,140,900,267,510,839,763,464,145,619,778,745,301,321,82,883,401,72,803,762,564,364,203,382,599,295,409,273,205,468,651,329,446,414,993,0,64,942,323,599,683,840,432,789,447,237,293,529,378,353,886,859,847,23,363,562,860,643,292,484,244,628,689,687,752,356,833,545,162,752,577,56,383,470,417,964,308,310,351,778,756,85,7,700,511,524,407,338,614,626,874,677,878,687,303,252,191,284,965,535,7,151,856,757,986,857,169,760,657,281,927,799,541,147,825,581,245,406,54,690,95,88,448,267,714,657,821,940,767,554,864,609,823,242,68,951,818,757,104,167,535,626,538,518,446,59,298,525,486,793,971,199,193,334,55,313,936,117,155,826,42,595,248,271,333,305,992,70,402,674,31,572,759,459,836,340,954,167,793,248,354,691,956,847,828,286,548,979,491,301,213,651,325,461,629,166,774,364,880,666,303,943,788,785,273,506,67,145,800,794,706,136,30,524,961,597,836,18,833,659,344,789,924,909,524,187,877,202,913,101,291,178,912,595,777,272,141,999,32,227,107,186,323,915,705,741,74,199,550,489,53,355,604,227,344,692,79,163,30,424,774,115,572,923,284,308,293,952,879,87,352,761,358,560,833,27,979,646,229,274,733,391,906,316,993,104,798,487,543,807,279,17,690,702,976,698,711,889,407,523,445,458,513,615,644,518,167,979,322,99,392,869,112,765,69,579,566,611,67,262,889,77,859,816,939,684,258,81,177,945,85,672,134,825,834,776,938,835,338,224,496,251,64,418,178,527,727,673,392,299,46,351,591,969,102,481,40,619,780,237,189,487,729,865,715,925,595,741,400,151,410,493,542,183,800,870,10,71,542,211,829,180,202,268,3,696,84,537,324,776,983,493,607,907,234,889,547,962,858,984,151,73,714,804,809,637,596,146,812,566,730,780,261,364,940,167,318,436,241,988,269,442,562,884,505,942,185,783,735,87,68,86,596,486,287,48,440,397,113,750,876,297,95,339,453,21,411,924,47,788,400,431,721,424,869,935,310,708,571,15,682,855,214,527,442,839,245,935,722,473,895,787,507,943,201,545,411,310,477,802,25,984,171,324,597,988,194,140,253,498,631,654,517,393,125,671,543,176,449,845,248,944,867,263,192,830,273,782,263,767,782,62,737,702,628,86,51,105,314,803,735,304,450,10,954,521,199,445,542,569,125,172,472,785,238,928,71,367,818,42,450,924,575,712,391,603,677,775,206,980,250,201,15,87,592,898,668,984,213,818,695,500,847,805,92,661,565,301,727,380,393,780,426,570,166,732,987,551,545,295,168,535,834,1,886,303,655,335,439,516,487,785,607,298,655,969,873,636,854,396,325,667,94,390,218,159,659,482,557,777,965,284,22,999,712,604,789,242,936,355,80,323,447,188,287,99,642,451,83,780,600,334,812,725,3,879,976,566,329,173,694,863,466,344,766,429,333,581,3,725,443,793,324,885,121,174,840,581,436,768,418,944,95,384,903,69,219,739,83,869,717,986,337,867,774,50,599,753,706,540,348,873,538,634,431,826,413,904,833,20,830,881,261,383,775,814,564,430,898,130,375,864,262,264,944,991,423,24,743,37,701,697,856,579,251,36,323,846,598,298,993,999,891,661,875,745,740,128,566,866,563,399,768,960,607,175,127,545,612,713,835,315,746,635,611,145,87,91,433,381,242,35,398,346,179,337,138,344,417,526,89,6,730,472,308,620,670,280,448,148,607,623,650,85,598", + "727,265,372,251,10,307,363,11,352,472,242,424,723,225,671,672,749,207,487,80,225,892,933,305,11,404,210,697,275,819,161,793,870,382,396,262,712,407,778,104,502,647,312,779,552,419,268,888,160,813,709,670,66,708,432,509,584,587,266,893,576,542,387,440,941,979,432,836,745,410,986,985,892,47,469,525,392,107,669,641,155,591,530,522,775,275,739,255,623,898,97,228,154,895,463,683,506,473,423,360,974,494,815,220,235,21,183,544,206,268,377,420,971,43,974,878,340,693,77,834,793,547,707,548,98,431,421,130,225,192,874,598,226,835,587,23,12,260,428,777,339,10,368,739,151,389,81,266,632,521,320,898,23,640,411,144,41,280,158,495,32,347,666,994,494,110,777,532,364,998,835,369,339,791,739,635,974,777,912,58,936,949,324,958,768,269,185,826,891,701,82,350,306,833,473,950,621,558,575,47,800,472,908,98,94,546,977,282,75,383,112,852,187,698,791,925,127,784,50,282,108,847,650,994,985,992,434,95,664,748,285,573,599,548,482,976,156,52,677,167,283,225,271,861,874,219,369,693,682,484,831,194,810,876,648,687,255,980,540,796,64,0,65,338,847,373,913,767,231,340,237,251,387,735,693,981,356,809,780,741,999,33,463,765,267,160,87,734,549,781,257,130,94,20,950,393,983,4,630,555,893,701,124,970,208,175,561,925,908,621,898,796,635,42,194,197,639,386,667,665,520,447,457,137,315,10,811,804,705,570,562,764,470,513,908,206,659,306,735,966,500,173,401,952,434,886,776,444,226,595,740,11,580,340,472,482,793,293,805,873,869,342,453,190,313,518,738,550,369,705,585,908,620,37,54,143,458,430,317,160,294,683,411,59,970,925,691,738,482,542,92,38,556,115,897,741,617,489,900,933,221,827,520,983,899,649,468,172,110,543,177,669,529,541,782,418,660,938,246,54,186,464,724,73,164,995,539,132,884,125,419,257,799,989,99,755,113,822,637,787,125,671,835,71,240,988,403,97,40,590,640,594,959,419,651,780,468,904,180,520,525,363,789,772,114,883,102,929,726,509,715,319,800,251,259,952,652,340,556,854,557,28,81,603,631,174,370,636,941,878,555,904,717,738,442,781,210,105,132,969,810,7,704,16,901,896,406,79,133,304,895,258,99,611,245,283,778,796,280,88,497,990,97,670,306,659,721,428,962,379,226,70,509,783,941,384,310,110,96,715,851,911,217,395,925,933,585,274,271,446,278,52,344,32,902,13,724,162,128,413,42,683,350,831,219,628,815,414,327,588,926,950,574,137,837,967,77,155,300,398,929,6,929,560,128,508,630,792,294,430,870,517,228,220,171,976,669,286,343,452,147,391,960,587,652,227,869,520,676,698,405,463,404,973,103,247,406,797,228,193,428,54,678,246,737,597,812,982,388,795,773,986,875,575,542,746,256,68,695,178,438,764,45,440,83,732,61,292,881,416,342,862,624,607,677,127,298,530,916,151,448,707,652,709,278,896,57,962,290,179,398,300,746,500,926,103,538,714,675,919,417,903,677,826,681,951,964,278,517,221,628,395,346,56,528,312,672,646,916,33,982,719,560,536,13,788,938,421,517,966,889,825,783,638,439,600,509,279,353,832,96,400,304,196,985,847,174,148,193,848,433,880,933,50,275,620,830,821,667,303,909,195,173,32,195,985,848,933,450,1,960,443,572,420,528,879,816,157,15,860,286,990,180,995,470,198,893,784,166,394,262,928,48,750,771,985,877,487,996,668,919,716,69,378,486,129,874,661,27,473,151,33,48,314,848,254,924,405,542,19,127,819,859,692,15,269,448,871,275,858,931,511,329,298,739,801,501,622,928,510,287,832,171,413,333,79,968,279,767,237,521,13,459,615,785,728,252,238,577,254,908,475,285,546,513,843,802,735,325,833,593,941,271,451,931,174,191,283,176,241,384,776,890,341,765,808,527,557,572,256,566,351,599,536,351,993,786,906,164,665,224,783,697,366,449,527,986,169,804,341,953,481,755,29,56,778,279,603,576,40,31,93,729,844,805,358,256,637,435,817,163,608,519,89,502,585,93,105,305,61,395,862,142,328,546,952,973,272,557,562,119,40,942,995,756,574,573,984,923,256,78,469,148,269,64,153,75,900,188,549,731,726,621,890,360,353,888,464,506,1000,974,454,901,927,891,518,877,786,10,333,680,237,382,700,713,144,920,989,96,22,917,566,395,690,365,917,338,699,787,202,558,96,860,13,902,649,140,136,549,807", + "258,554,353,484,235,834,387,664,213,832,656,60,30,932,95,408,109,950,75,420,832,880,804,935,229,47,776,958,357,718,809,91,910,15,189,683,221,533,432,920,509,121,481,188,977,384,457,304,396,513,706,752,762,650,170,133,136,141,987,216,988,694,977,569,625,976,437,432,910,896,989,680,553,853,743,148,460,325,760,780,929,616,665,41,439,324,880,34,86,894,47,619,192,193,48,973,637,152,978,841,565,973,41,820,151,795,21,396,127,11,460,444,393,413,145,278,442,56,523,273,38,660,64,478,924,723,904,467,812,224,116,144,29,84,950,845,283,256,265,414,153,413,425,807,791,496,315,411,763,719,95,301,93,240,3,473,494,296,886,968,898,450,641,314,214,522,453,93,121,65,158,200,602,750,747,631,545,250,645,37,869,578,294,127,292,802,857,907,47,346,601,532,872,51,338,169,157,601,588,153,874,470,706,36,736,666,902,298,523,944,516,650,6,611,265,92,128,664,870,75,656,369,862,598,424,538,990,875,513,352,615,639,289,588,10,973,605,12,335,621,549,606,996,293,775,622,725,462,675,667,210,289,660,263,45,503,239,911,762,945,942,65,0,641,92,113,625,707,625,702,632,490,65,167,472,293,825,550,45,59,339,238,456,874,722,115,922,372,414,898,374,374,76,797,787,841,80,182,687,908,138,334,127,361,592,859,721,267,21,185,557,823,969,669,97,556,418,553,29,160,351,883,564,760,22,609,817,813,593,135,425,485,859,624,789,670,652,484,514,236,187,208,959,447,220,435,467,783,202,747,992,449,583,773,760,64,571,606,657,955,202,224,869,103,187,939,371,634,640,935,79,389,986,642,550,42,635,931,463,675,433,129,194,566,262,643,860,346,595,181,633,951,77,756,601,750,813,797,307,629,568,844,665,198,748,15,164,984,777,631,809,248,903,158,671,619,614,65,719,971,221,385,320,412,774,808,374,529,236,303,127,515,926,76,887,675,453,293,162,959,563,852,20,303,299,495,933,647,168,752,346,243,893,985,692,660,464,140,859,69,194,613,409,62,577,796,360,823,737,77,729,448,407,152,662,448,198,861,389,702,849,487,79,943,166,837,678,896,558,117,906,666,273,524,925,924,890,550,333,457,11,541,909,972,957,926,183,251,285,945,84,701,113,141,887,375,855,715,744,453,338,680,171,102,600,837,91,839,883,626,100,668,503,424,453,756,796,882,238,939,333,830,795,919,468,795,203,722,43,652,72,816,29,685,718,50,880,394,140,536,668,111,271,93,845,53,158,10,308,687,345,859,468,314,920,749,522,751,393,723,38,167,472,248,309,674,284,904,344,176,38,654,435,782,40,597,647,800,422,873,172,420,65,143,766,31,197,33,495,125,169,823,75,639,840,387,864,19,495,343,654,745,763,384,262,644,494,129,322,880,816,664,308,71,432,829,772,934,133,648,995,228,992,603,485,130,230,335,184,233,647,110,736,849,128,413,621,494,919,349,320,237,661,697,763,557,438,301,301,947,932,861,772,291,25,860,613,118,969,120,95,91,390,495,382,914,81,360,872,689,61,765,199,683,309,354,698,410,77,936,344,361,22,645,623,413,217,646,786,165,272,210,404,532,56,953,77,547,576,757,947,204,307,13,874,364,189,701,185,495,680,212,983,47,723,33,171,38,307,658,235,684,411,202,221,622,410,465,135,672,233,458,344,340,195,242,376,199,613,645,924,958,249,724,222,401,710,847,207,878,331,366,84,232,560,187,738,661,1,654,151,244,319,498,165,811,446,736,271,629,429,181,504,663,569,369,212,957,380,146,10,64,28,656,697,592,606,630,566,135,835,393,795,44,640,949,837,58,879,186,933,608,460,656,92,582,40,414,520,235,134,396,215,865,12,275,132,24,328,178,932,348,11,232,408,773,656,770,100,145,381,9,876,52,991,508,190,397,404,432,645,215,700,669,997,305,401,867,992,213,949,827,784,970,417,126,171,510,971,91,672,784,439,223,547,407,819,847,934,270,54,749,533,154,740,420,403,588,758,672,663,99,497,64,91,193,711,611,485,534,920,697,441,740,189,295,601,335,236,985,810,771,75,345,144,390,970,138,450,950,358,306,967,527,7,172,232,107,644,158,895,216,217,183,780,530,795,427,505,401,897,86,422,612,395,800,894,171,912,164,555,528,756,887,705,421,54,42,115,84,819,601,928,685,979,696,399,674,766,751,91,169,834,422,121,949,526,356,316,985,932,42,494,67,783,397,493,492,951,415", + "307,862,586,862,374,229,228,49,784,69,763,541,404,474,87,665,205,623,635,642,337,425,389,766,740,952,431,102,831,366,153,559,491,29,146,873,51,549,880,30,703,611,565,502,34,92,551,608,227,120,848,2,734,29,444,251,720,262,139,675,924,997,513,742,204,12,624,857,171,401,67,582,819,138,326,913,16,960,900,419,213,984,953,860,965,324,338,562,179,606,611,313,799,917,573,182,775,832,608,914,579,982,268,796,455,533,225,135,307,851,1000,199,616,907,231,721,900,346,612,233,533,225,175,447,923,812,865,797,896,182,947,981,872,745,614,243,36,976,770,561,939,101,888,363,709,619,914,288,767,153,951,76,687,513,226,171,572,500,759,313,905,958,650,950,297,107,944,674,624,2,660,186,946,710,907,422,769,690,42,954,403,129,753,228,639,358,892,734,632,995,588,984,343,498,401,145,316,872,644,226,140,53,711,875,959,57,172,110,305,214,208,792,839,725,765,802,167,782,131,823,596,966,332,599,516,120,152,847,406,691,142,874,178,33,473,674,444,318,687,760,314,360,876,169,900,604,214,858,348,316,821,200,773,162,181,737,178,143,48,995,323,338,641,0,301,240,369,681,332,486,608,817,744,871,759,721,45,234,579,975,118,284,70,856,143,323,525,367,647,136,789,999,267,893,782,217,628,512,663,85,485,289,74,987,393,307,540,171,105,967,601,579,28,22,999,675,389,822,556,650,392,280,967,236,915,792,289,458,542,116,177,840,693,30,967,31,308,211,501,270,182,329,491,149,101,669,314,521,832,765,916,526,566,934,858,147,991,595,655,149,604,712,764,991,292,194,847,979,276,237,506,495,718,267,198,693,83,892,570,662,303,304,815,374,325,575,278,29,319,692,282,656,626,64,33,243,697,133,349,175,7,451,778,595,954,454,997,280,938,198,477,436,186,250,73,872,77,852,968,586,964,765,46,15,975,214,553,903,225,243,726,242,458,212,192,465,706,672,592,31,877,457,413,554,268,811,439,472,436,467,686,248,627,875,259,918,168,835,188,140,510,146,746,1,689,487,687,254,868,801,126,726,525,494,53,114,919,101,42,710,744,164,525,871,359,544,873,824,880,341,662,640,97,535,801,818,833,325,377,656,287,943,658,96,471,343,581,104,395,236,30,689,261,67,469,694,529,627,680,34,15,745,601,901,826,224,1000,149,218,386,213,968,620,4,766,687,578,668,336,528,240,905,53,326,981,423,379,893,791,921,999,258,928,92,11,926,272,524,610,355,934,943,335,968,461,364,538,686,196,321,936,304,100,558,682,571,363,585,463,572,67,236,637,34,901,731,495,267,402,806,653,367,615,922,882,693,416,484,572,175,971,894,506,76,733,151,936,890,58,234,536,111,271,2,908,12,443,315,683,405,294,894,117,987,202,573,967,165,291,388,543,117,425,120,461,166,600,230,266,669,874,704,188,751,834,885,645,617,93,383,782,820,404,202,96,350,514,591,301,419,359,301,718,875,980,926,760,610,915,880,331,814,412,945,709,560,332,383,84,888,696,812,94,605,445,959,220,216,493,112,794,604,136,488,91,157,412,410,157,182,567,428,867,650,208,874,672,860,543,932,12,219,284,337,317,265,883,611,397,500,314,59,896,66,276,288,84,447,801,160,899,925,838,329,266,676,885,306,31,577,710,495,351,606,838,871,253,115,56,860,297,697,31,219,53,468,446,245,146,558,348,469,215,700,828,871,618,288,535,102,157,30,879,779,148,68,911,584,175,711,969,263,878,59,963,226,629,117,779,655,231,466,667,790,722,158,877,483,621,258,430,112,195,374,592,603,488,811,314,398,61,657,189,919,481,907,450,71,90,541,930,421,299,472,274,427,576,964,301,914,384,710,202,95,978,250,601,525,278,394,238,812,572,730,620,737,302,691,69,904,141,102,193,298,267,36,11,445,518,982,217,877,895,237,782,947,541,607,974,75,225,33,503,677,2,437,777,76,358,397,250,580,33,945,856,746,643,394,457,907,928,89,517,807,225,156,629,670,633,259,547,595,940,743,575,561,791,916,645,992,67,369,497,570,928,898,979,948,974,54,156,867,568,738,115,847,87,168,569,500,864,120,503,386,973,32,52,415,661,189,693,737,402,505,104,459,151,106,134,620,640,631,83,477,256,305,800,413,280,914,664,313,3,132,511,401,390,463,779,148,9,411,849,739,56,75,212,642,627,295,185,382,317,744,168,271,979,592,751,38,821,883,437,298,452,474,535,868,137,777", + "794,609,487,94,696,508,385,972,397,551,26,306,154,511,420,343,93,31,335,507,542,374,484,596,251,460,121,875,135,604,940,294,994,615,460,162,907,560,468,265,586,326,270,920,551,976,482,895,996,622,361,245,317,867,161,86,978,258,953,498,597,11,122,825,884,574,589,960,258,590,537,210,323,438,429,153,233,413,862,489,232,902,366,650,715,666,754,148,356,767,407,713,258,825,201,418,959,896,939,513,551,79,966,70,607,814,163,774,206,719,703,373,889,197,994,127,857,853,844,493,959,577,234,813,981,150,54,497,353,617,78,425,334,379,173,598,711,399,23,352,342,224,842,827,271,787,757,607,381,114,56,695,183,417,355,114,556,247,489,720,158,438,51,487,497,85,661,722,480,399,688,255,126,431,610,188,547,740,714,604,402,628,679,96,27,192,809,274,108,34,50,451,67,958,585,517,296,794,441,642,297,643,124,89,986,201,428,445,778,861,476,764,448,848,985,43,848,129,435,887,897,924,138,4,952,710,167,174,825,689,210,975,93,854,594,11,878,850,542,890,30,289,157,68,484,906,180,82,434,331,27,223,242,342,702,156,241,822,408,728,599,847,92,301,0,611,458,503,343,972,201,118,964,194,339,48,403,775,739,717,499,899,455,950,584,868,835,883,194,889,271,27,71,586,853,586,366,666,964,49,394,950,105,29,139,259,156,691,300,266,352,959,507,132,815,784,853,42,981,822,639,854,205,465,399,157,682,141,16,33,819,901,205,754,920,626,844,756,795,331,513,36,670,811,752,121,497,631,734,988,152,380,138,796,979,796,681,702,988,598,1000,262,164,304,185,294,50,371,675,243,960,92,561,468,832,680,868,906,486,688,632,428,375,50,906,963,191,311,124,190,520,897,88,400,975,470,330,551,30,284,59,346,682,540,618,288,151,840,745,519,964,8,281,86,617,757,808,894,629,597,243,105,712,536,740,589,417,995,250,97,398,42,503,146,693,126,558,503,142,4,44,246,90,704,667,656,209,60,916,450,793,205,396,723,787,525,123,815,711,662,147,407,506,619,469,65,948,770,708,225,388,480,363,77,312,766,148,137,170,127,340,708,274,981,360,833,467,661,948,800,135,35,787,275,604,575,640,852,839,719,488,585,10,680,436,112,364,220,834,2,112,342,935,670,23,223,975,93,704,476,342,928,878,393,450,15,576,989,96,327,333,100,977,340,916,212,825,339,703,672,109,100,7,917,183,818,620,137,247,960,209,22,116,483,351,422,937,965,263,355,137,874,300,778,244,60,319,518,811,643,526,634,20,916,908,907,208,507,742,588,977,710,953,959,434,976,505,980,558,670,47,636,98,204,207,745,985,488,835,656,187,595,899,848,712,547,277,587,5,22,180,171,183,108,397,323,228,305,477,425,545,78,814,652,932,908,963,811,243,972,491,766,461,830,732,706,453,612,486,591,247,426,313,908,108,609,787,654,575,277,829,444,715,88,322,974,121,432,342,365,86,156,38,907,93,466,503,419,224,816,617,298,191,912,264,850,305,266,229,698,384,955,556,155,657,581,128,317,633,377,486,2,357,74,485,734,149,284,933,13,163,509,469,238,196,753,450,104,504,345,28,83,194,541,21,684,693,667,622,531,634,437,830,952,701,470,967,285,25,995,342,387,793,535,455,588,283,632,254,959,649,137,44,878,999,909,584,554,466,682,262,928,838,922,376,538,694,10,433,341,531,528,801,596,946,488,855,13,326,129,339,506,845,808,668,69,331,334,124,808,347,201,93,681,706,999,807,484,702,191,380,898,587,534,910,140,167,536,393,279,162,381,117,256,963,541,599,109,456,164,119,202,560,47,289,967,203,368,371,179,564,92,616,602,359,216,660,429,719,529,357,174,66,626,808,103,9,24,5,276,747,578,734,884,840,458,628,668,790,669,900,308,268,693,956,236,419,83,651,409,446,391,489,568,990,85,214,512,783,245,39,857,972,320,239,359,447,420,950,317,388,586,165,685,260,30,245,839,935,389,260,129,766,636,158,235,210,144,645,370,595,468,990,334,606,500,62,190,161,73,776,552,932,603,362,598,607,190,282,768,511,706,189,467,725,253,362,794,968,361,357,698,391,886,243,536,490,482,721,292,819,848,899,99,729,330,807,212,408,54,230,758,568,847,816,52,32,846,675,231,850,566,84,290,657,434,365,682,115,108,377,270,416,248,292,336,674,134,781,498,14,719,292,819,295,239,704,935,256,107,597,709,730,351,690,557,978,493,614,188", + "669,244,698,179,742,748,632,444,824,786,494,792,321,864,807,858,232,584,198,711,304,49,126,417,439,338,598,71,797,189,125,126,372,839,324,14,687,418,561,624,23,743,28,786,304,986,113,950,350,994,355,553,393,90,463,177,309,336,255,452,684,575,78,170,372,887,181,793,640,723,519,59,641,313,503,744,698,568,141,964,856,291,236,839,534,414,928,147,783,823,634,741,532,824,981,178,226,531,409,910,166,332,660,960,509,260,817,35,26,677,483,414,676,671,587,345,334,113,256,143,716,487,325,631,187,646,772,909,881,204,999,815,118,336,297,332,399,29,937,898,695,433,567,810,442,254,251,17,331,404,849,626,673,856,424,341,471,757,105,284,673,349,755,498,682,276,997,872,607,348,73,549,279,721,350,544,600,855,193,645,771,131,490,732,42,8,9,723,968,764,860,335,61,378,600,671,900,240,993,483,287,454,787,108,645,915,536,12,468,99,817,648,770,554,683,384,460,269,887,412,348,137,121,107,991,319,593,983,202,90,504,16,502,858,531,755,246,21,491,486,238,472,760,407,530,34,115,509,807,246,398,259,72,258,24,442,427,336,602,747,683,373,113,240,611,0,755,265,373,309,695,268,625,348,496,787,882,105,362,904,996,457,279,811,651,809,913,221,904,158,125,921,341,230,866,47,651,86,937,513,244,341,498,277,417,967,489,860,379,867,169,778,116,894,114,772,796,299,6,197,873,730,149,466,541,850,227,408,94,298,333,376,133,186,481,693,913,216,888,340,143,561,687,86,938,722,764,871,266,55,192,785,866,344,102,856,506,427,878,32,706,406,244,286,382,438,974,494,551,545,530,923,192,936,549,840,954,188,587,567,305,979,87,324,186,554,194,13,492,436,90,965,523,312,994,914,361,87,674,789,673,189,877,553,943,421,522,80,335,592,435,227,259,256,599,45,829,61,649,224,72,661,705,250,685,116,550,986,294,184,365,791,66,262,496,490,42,878,346,630,593,164,275,836,624,169,337,464,186,535,612,969,323,119,598,829,694,323,45,990,154,207,153,607,75,557,623,170,715,771,930,265,585,722,936,995,9,752,83,687,579,565,428,935,370,738,761,979,103,622,365,516,683,796,475,306,238,485,950,14,137,815,135,368,528,862,247,598,249,923,94,239,667,848,826,223,407,381,531,188,504,348,119,394,998,198,315,596,694,872,64,768,471,427,564,936,705,570,29,307,99,314,955,718,149,195,736,304,857,544,25,559,936,329,769,427,375,928,377,985,491,580,770,605,844,617,310,275,334,781,5,566,870,213,744,57,294,588,241,601,89,928,987,781,203,523,864,480,365,760,266,207,642,901,232,835,636,236,840,814,234,915,702,599,642,113,30,490,823,326,417,830,818,635,152,143,400,169,798,938,863,403,17,654,875,569,323,788,564,958,75,809,680,697,305,608,98,467,74,832,187,100,883,175,751,728,899,450,439,272,641,771,866,825,840,813,516,197,411,532,332,463,858,675,875,496,117,335,568,852,694,588,113,360,198,53,730,636,138,613,292,411,299,467,822,403,569,526,837,836,689,397,810,294,912,451,736,540,29,406,167,331,296,253,942,9,773,529,135,587,117,585,719,796,796,188,165,966,684,63,656,292,840,375,72,970,181,994,969,551,344,200,492,462,224,364,876,444,19,855,636,609,503,352,431,874,333,482,180,809,22,977,120,943,669,228,63,405,507,867,404,23,925,153,381,385,445,278,847,607,849,218,358,266,799,855,762,25,752,673,799,802,547,943,428,426,263,161,474,940,453,15,740,985,859,762,464,841,848,129,916,675,479,318,244,475,653,930,136,175,225,282,813,933,966,155,190,519,7,905,683,755,386,951,337,775,320,352,705,706,752,188,868,968,25,348,801,454,565,2,787,435,455,752,493,881,855,603,986,341,310,227,632,707,603,682,798,364,376,314,970,102,543,118,179,206,344,506,105,248,889,744,263,230,843,304,305,79,163,122,639,493,966,32,148,364,751,716,730,469,433,163,983,196,332,514,806,473,475,153,431,716,328,979,754,686,439,408,959,531,912,129,563,761,148,132,650,137,444,88,412,995,78,574,378,733,531,707,89,662,409,673,157,452,719,95,88,771,734,192,654,710,407,716,640,345,629,549,912,871,261,786,47,460,717,74,598,593,181,343,711,314,948,83,879,547,841,373,854,711,611,517,36,733,81,470,465,956,794,424,452,820,402,696,991,680,700,219,151,794,943,446,98,340,531,470,619,351,769,358", + "438,662,386,486,176,502,2,933,381,359,927,486,978,284,702,85,159,751,317,837,829,602,726,48,745,771,541,377,827,44,290,893,999,873,176,29,40,525,626,864,333,94,863,224,222,914,23,443,984,11,506,371,90,203,525,295,775,788,564,438,681,896,725,860,985,934,916,362,854,14,840,391,564,341,326,20,124,335,209,27,723,511,899,687,748,743,204,521,284,804,340,334,675,264,416,249,415,254,487,535,550,612,821,204,693,776,476,707,839,560,757,654,502,283,163,4,110,275,892,834,483,247,20,629,247,673,767,70,755,10,367,93,451,933,866,223,679,398,544,401,684,940,868,917,877,46,618,230,152,59,589,70,208,597,233,743,392,953,460,704,275,378,874,885,908,779,493,476,972,437,187,186,146,572,317,597,814,399,671,32,431,726,366,881,261,528,465,951,297,671,757,551,50,61,629,464,915,594,593,245,59,166,163,365,937,401,55,244,334,555,793,31,340,935,808,577,9,264,224,858,419,320,234,413,571,585,990,833,151,70,963,753,300,42,895,927,543,302,292,508,357,365,833,132,690,871,548,287,1000,933,215,937,2,47,274,799,567,526,628,543,840,913,625,369,458,755,0,142,430,734,631,731,373,180,766,211,597,62,996,142,766,633,242,251,218,29,648,626,12,59,338,70,674,141,742,393,733,144,262,632,199,583,155,806,927,466,175,877,953,450,589,853,508,111,901,37,253,727,934,203,178,974,77,112,390,632,617,655,72,911,932,134,501,438,253,8,784,996,204,137,846,304,988,682,211,840,348,36,823,952,990,466,206,830,663,410,871,173,774,40,974,803,933,292,940,462,871,70,155,34,723,100,582,102,740,252,712,471,622,519,607,198,25,961,460,771,418,782,876,340,842,879,12,822,81,575,485,65,334,922,66,954,20,768,957,609,26,240,607,326,941,553,563,573,188,748,918,742,208,731,732,633,542,992,851,118,438,796,369,665,989,982,864,217,490,267,549,953,655,227,471,937,152,359,226,324,767,556,878,106,365,652,717,205,550,336,311,46,823,460,398,124,497,577,410,937,791,60,981,100,815,332,409,63,843,123,442,710,907,89,30,377,507,127,905,789,836,10,881,929,354,63,571,11,236,511,763,869,906,206,470,687,497,447,303,613,713,990,519,127,211,120,864,856,775,642,758,982,272,134,602,742,367,545,306,94,244,384,750,769,687,372,333,686,474,439,395,532,704,102,572,841,30,458,935,182,896,588,153,965,124,254,781,754,545,356,84,810,288,676,380,526,897,574,532,828,893,308,394,787,985,43,176,540,273,108,55,836,407,21,302,666,65,513,90,542,549,42,972,592,517,754,641,169,418,284,428,621,84,481,570,335,751,768,902,712,36,496,611,677,420,371,976,48,681,940,227,602,667,284,368,819,311,965,581,168,205,26,607,251,917,426,239,204,783,354,125,66,574,9,198,693,951,259,194,579,676,734,743,469,790,639,217,761,96,415,301,744,684,675,812,998,945,475,22,877,281,28,63,411,649,379,723,788,82,99,61,674,685,530,684,443,560,643,864,850,804,763,902,751,66,735,261,224,112,982,199,83,952,910,730,646,266,666,83,566,979,708,781,665,879,635,893,306,152,719,787,25,21,708,977,735,885,354,890,285,396,533,127,151,556,563,185,935,343,192,209,885,920,665,742,989,436,814,895,601,399,933,615,358,507,811,475,941,726,40,501,189,866,736,22,171,467,418,260,551,245,10,829,493,432,746,602,991,602,528,533,886,46,299,877,906,964,220,851,460,18,63,884,421,678,425,30,59,381,884,524,949,531,692,79,246,536,662,293,792,836,974,892,531,484,586,204,546,523,716,955,831,582,208,451,345,270,98,265,880,632,259,580,313,679,393,236,710,837,89,425,518,51,121,779,176,145,512,377,39,954,586,441,450,599,488,638,645,134,149,612,413,537,296,524,829,980,216,54,326,106,942,126,309,696,37,518,186,281,930,83,938,63,264,521,705,344,422,35,552,980,294,517,305,286,468,21,69,635,553,939,154,464,821,218,494,614,747,822,407,69,86,866,825,363,852,426,766,664,135,293,424,405,820,571,485,655,492,154,644,372,118,604,818,540,611,443,173,862,899,773,99,534,765,214,21,261,978,256,949,865,530,992,320,978,70,562,579,68,587,377,406,414,381,941,157,927,471,87,155,274,100,323,414,992,909,189,295,733,437,394,661,151,19,903,21,984,232,974,323,487,912,874,406,289,25,543,375,267,925,966,477,888,587", + "604,714,823,991,98,745,815,753,38,763,990,824,583,321,590,890,598,272,426,52,832,24,619,97,200,787,364,344,426,912,841,791,286,873,707,340,541,393,309,135,889,933,710,370,84,793,556,431,165,538,875,238,213,767,623,551,87,378,850,919,146,230,800,593,696,135,11,881,424,829,730,773,258,16,171,876,451,185,940,830,377,979,211,819,390,376,724,435,123,980,63,586,604,902,322,265,316,306,23,790,957,523,362,720,532,483,125,611,912,217,605,471,364,997,234,815,378,863,58,293,478,820,927,412,403,589,38,262,482,560,985,740,5,541,816,473,330,843,208,282,358,425,662,468,4,213,849,613,246,690,690,162,328,423,61,135,362,600,757,490,912,971,259,990,894,968,618,368,199,969,489,481,228,791,50,189,455,349,765,919,7,950,874,48,295,270,745,584,163,197,532,341,569,549,227,118,241,160,647,813,969,833,790,502,73,212,961,521,437,466,991,443,954,550,472,738,430,262,814,479,402,121,160,887,241,108,351,485,881,240,140,971,956,893,450,328,117,387,589,139,123,575,472,958,780,935,846,765,257,590,782,496,438,748,539,55,944,99,891,417,432,767,707,681,503,265,142,0,617,259,123,138,137,853,470,909,242,50,733,591,724,472,895,843,727,51,585,552,124,239,482,127,593,778,15,148,49,119,650,458,423,230,367,62,38,151,797,903,24,342,368,669,318,933,897,101,918,880,528,757,221,4,867,95,919,709,809,347,673,119,753,100,735,248,542,749,915,411,55,203,546,916,253,379,580,206,915,242,538,654,952,708,685,893,689,678,597,803,883,785,418,773,341,452,339,616,504,239,363,826,410,435,924,849,996,646,245,268,142,952,713,401,940,183,962,417,319,420,58,584,214,922,970,936,912,287,61,56,581,821,282,525,433,642,681,74,785,924,184,968,328,934,434,242,177,201,736,262,232,31,592,308,66,44,584,358,410,111,414,458,283,904,196,300,497,60,723,922,720,334,973,662,713,253,669,141,420,661,27,520,435,443,64,759,967,705,833,504,890,875,997,614,638,560,940,597,677,332,43,664,626,645,595,999,104,976,716,355,404,837,354,799,962,733,303,351,17,490,140,849,841,631,233,553,920,529,923,756,755,309,359,764,850,619,949,416,771,951,535,496,946,518,967,817,452,767,745,482,762,656,93,297,959,658,829,915,525,206,558,733,203,511,716,838,653,418,315,51,172,628,158,304,158,903,334,800,880,640,460,815,13,829,892,823,767,961,967,743,448,885,907,353,449,155,650,980,654,676,608,634,433,181,878,512,542,867,849,763,611,936,888,723,917,379,799,722,340,598,877,51,960,171,175,869,621,669,351,114,465,911,302,32,800,801,690,993,293,549,751,451,407,146,540,105,94,595,694,576,36,909,645,843,398,221,743,965,609,283,969,677,353,449,100,647,117,680,906,156,544,667,582,234,308,796,299,957,380,863,492,246,497,923,994,175,938,922,789,269,378,85,177,340,806,990,743,662,475,876,612,434,719,795,98,974,503,648,868,754,762,154,715,68,713,478,606,173,35,325,506,952,157,160,836,991,639,510,894,664,974,897,390,796,964,900,852,945,141,499,289,180,723,104,41,729,550,509,65,548,931,220,392,419,380,465,809,725,636,291,597,761,54,617,181,389,315,820,738,980,155,279,103,978,581,367,70,734,551,347,530,537,170,823,538,964,797,402,573,415,610,49,412,975,827,876,83,752,392,285,842,95,183,629,770,280,341,182,515,912,634,154,423,94,285,227,228,920,55,594,564,147,818,107,773,287,649,308,338,422,806,391,509,314,742,974,329,333,821,233,584,862,37,299,389,968,766,670,533,515,363,181,811,452,309,710,456,112,211,236,926,452,783,886,200,67,949,702,697,95,788,290,108,231,528,759,256,988,965,22,703,586,264,487,933,327,350,741,41,785,776,992,88,380,877,354,92,71,153,832,586,360,60,825,974,538,185,607,982,284,571,628,619,618,532,459,697,484,980,515,373,277,298,403,248,821,101,494,197,921,3,87,852,472,654,254,556,44,501,432,714,973,939,989,798,492,364,816,17,917,492,255,280,364,935,449,925,847,729,666,928,518,738,82,277,984,540,578,335,527,496,153,599,693,93,506,93,379,358,176,129,435,502,70,359,362,137,224,644,528,762,600,59,682,452,232,630,813,452,96,777,281,320,302,638,170,744,736,124,799,57,941,5,277,448,431,119,903,134,106,242,58,29,305,802,91,265,2,269,11,350,921", + "549,194,849,626,799,643,899,543,642,50,85,923,520,385,591,339,110,818,692,15,357,923,789,336,514,815,928,237,334,956,505,74,529,451,985,835,679,280,423,181,666,207,861,469,561,277,759,381,560,477,787,718,735,243,4,644,347,975,29,594,778,345,52,318,4,526,601,975,170,358,511,912,248,849,752,504,37,68,413,646,221,483,514,754,801,518,572,611,177,551,29,654,174,292,343,81,441,397,795,484,904,812,305,394,263,395,891,596,426,266,565,205,12,859,275,483,394,7,837,169,235,372,82,887,408,760,838,139,483,885,733,297,265,799,880,980,801,632,728,867,115,536,250,516,683,621,425,350,74,509,557,635,224,408,980,774,594,796,640,560,914,136,206,197,289,773,793,913,282,461,114,93,455,865,930,250,552,593,34,96,481,309,742,63,772,401,58,359,792,773,206,683,219,389,169,755,46,179,534,928,988,701,166,490,32,164,597,59,392,604,166,242,26,170,980,297,762,634,301,253,593,35,758,127,349,919,790,308,593,817,191,141,8,47,457,967,860,929,336,165,9,366,23,979,26,366,860,322,85,590,96,353,264,279,578,513,233,129,110,41,789,231,625,332,343,373,430,617,0,671,286,997,861,816,600,15,782,339,135,134,838,518,307,624,971,311,749,993,743,108,982,270,924,929,73,73,175,167,149,833,474,591,291,174,40,850,402,11,727,452,694,555,232,875,649,727,924,724,637,736,872,15,826,928,801,232,318,725,587,662,275,471,473,125,866,335,339,150,727,369,622,129,749,871,162,420,194,674,910,758,765,428,188,824,133,992,483,626,503,199,351,162,218,809,300,237,759,798,613,647,799,353,110,279,107,873,594,198,520,458,210,983,980,696,447,882,204,344,314,68,495,509,582,925,353,473,65,409,734,813,878,663,349,352,500,736,892,220,991,69,232,499,762,739,251,785,968,939,601,840,153,550,985,995,39,880,657,81,826,888,271,634,840,448,634,610,106,546,955,857,370,704,323,434,882,652,525,765,188,380,326,496,579,656,917,51,688,85,336,123,255,658,803,420,981,506,284,118,721,540,970,602,941,944,80,321,962,866,792,941,774,14,112,943,214,880,859,201,344,309,315,26,310,573,316,876,156,481,900,3,66,453,396,428,944,152,801,284,906,413,224,433,845,784,937,332,551,451,319,420,874,236,99,412,124,922,624,288,224,40,300,681,580,184,768,744,950,970,142,280,453,678,258,610,354,224,469,231,834,70,551,771,456,461,582,739,315,10,224,599,339,753,188,722,724,26,893,568,775,804,43,184,150,522,811,174,979,652,905,284,177,960,956,185,592,309,585,549,678,770,180,621,534,546,154,249,859,313,920,863,383,577,730,139,224,651,377,420,260,452,125,963,296,92,756,926,47,549,88,392,996,196,336,632,511,613,632,92,879,136,264,635,685,671,84,304,807,787,564,158,323,956,150,653,897,839,881,152,433,880,584,430,635,334,526,9,171,502,784,210,349,254,495,292,928,891,379,748,303,763,206,27,338,43,287,354,632,366,70,692,56,479,374,810,870,766,247,397,638,359,670,551,749,123,953,467,180,837,272,830,983,481,3,254,322,742,600,688,442,438,968,349,423,391,441,925,822,186,919,275,414,530,754,632,626,558,471,409,604,678,900,341,151,796,183,671,707,292,540,640,927,314,800,143,365,462,844,811,356,205,979,356,900,353,930,640,370,174,286,150,248,35,489,192,832,582,409,918,527,145,60,953,747,580,475,27,176,754,747,605,579,848,657,510,965,13,324,907,109,151,977,755,226,835,95,519,706,417,288,442,192,154,102,479,142,957,669,329,577,618,274,788,359,838,194,114,125,730,616,831,203,602,685,928,521,933,358,415,581,382,158,866,606,166,555,5,307,26,204,413,825,397,118,671,367,716,168,11,286,348,610,308,514,964,179,199,235,602,812,221,508,450,632,915,507,470,341,142,531,717,957,154,393,479,827,15,512,787,678,312,356,623,734,671,767,59,149,810,223,413,379,795,62,549,747,38,332,762,571,255,656,214,555,955,66,878,728,39,681,519,837,559,982,525,45,162,680,613,27,962,770,636,290,381,57,656,712,892,623,59,523,332,463,403,119,21,259,896,18,814,892,157,494,849,406,717,385,789,486,542,390,359,397,994,830,939,654,989,974,272,681,350,455,685,482,722,525,34,247,428,148,155,481,387,725,430,907,960,726,350,686,924,712,499,602,788,715,590,445,472,833,716,60,844,474,309,831,704,938,402", + "921,853,784,301,394,656,790,631,764,85,958,926,677,469,36,371,594,480,305,664,568,444,565,381,197,733,668,672,291,30,220,972,234,515,410,709,464,101,12,248,321,216,779,619,586,790,87,144,329,303,604,896,305,434,4,24,169,375,103,886,612,76,266,784,15,349,415,144,739,656,603,238,28,365,298,684,490,684,269,606,360,767,276,213,540,347,440,355,829,936,349,886,293,839,252,236,318,16,355,322,3,215,659,904,348,16,280,27,174,297,9,462,593,945,123,167,850,494,970,133,123,682,164,494,933,248,977,976,278,758,432,876,19,272,210,746,36,442,952,960,592,967,234,756,982,380,497,357,111,855,696,300,63,955,671,460,902,965,948,53,3,909,718,518,376,128,341,265,955,839,216,83,374,14,241,615,848,170,467,367,76,693,977,975,195,791,942,722,717,801,680,577,438,226,321,350,520,782,247,506,506,318,806,98,274,732,102,153,214,677,71,796,483,624,521,197,21,99,395,203,864,390,851,711,520,539,956,947,530,442,432,149,153,256,122,97,654,798,208,601,842,376,905,819,411,831,614,390,313,610,499,153,31,620,589,401,108,885,82,802,447,340,702,486,972,309,734,259,671,0,143,352,503,466,926,447,609,281,10,104,693,605,450,177,184,914,260,787,440,926,608,250,985,683,978,731,850,363,767,873,180,401,456,32,529,237,817,331,426,814,161,795,293,631,702,576,968,360,87,366,164,882,441,949,375,8,240,441,932,31,882,791,127,961,494,453,269,382,626,959,463,986,450,608,156,616,979,495,712,184,111,56,769,88,378,775,10,89,274,874,902,20,651,108,263,773,731,470,3,150,33,114,220,511,386,488,72,646,594,496,778,181,987,227,857,743,884,719,724,557,88,941,494,708,779,155,885,134,162,256,743,90,6,118,57,124,727,909,404,825,103,746,450,896,863,257,795,80,651,723,484,407,591,923,668,584,587,502,691,370,310,78,530,774,140,174,749,861,829,905,625,738,421,413,972,2,386,895,997,786,433,937,72,535,777,573,689,887,860,370,941,606,831,444,193,400,275,103,4,370,815,475,572,615,286,827,819,950,605,74,790,204,837,653,200,565,18,980,236,895,516,337,121,760,421,675,575,910,195,808,828,666,558,286,821,875,54,757,471,738,458,709,616,816,818,966,490,355,450,238,337,891,236,309,573,275,515,983,691,429,91,230,505,921,6,213,161,375,922,942,566,340,822,166,7,128,904,123,404,704,965,355,64,494,400,795,924,709,899,289,870,50,850,645,287,398,470,641,240,202,430,904,607,673,796,645,610,776,949,685,782,136,971,639,333,575,397,592,827,520,623,40,729,48,627,585,581,976,64,601,848,280,653,267,339,952,242,881,692,881,31,535,17,234,130,591,844,96,523,858,885,719,933,747,398,469,820,134,102,13,781,714,420,754,549,748,310,242,903,779,777,630,764,360,877,532,420,596,944,744,92,595,368,328,519,629,250,315,776,241,514,492,465,274,148,551,896,137,89,173,626,771,297,721,187,468,386,187,299,799,249,974,638,723,101,69,585,576,803,165,250,939,144,271,864,846,46,27,710,170,78,483,487,472,209,847,795,63,867,440,793,219,720,231,437,62,49,959,42,421,664,195,905,669,558,835,287,301,951,636,898,112,477,902,930,585,542,809,729,271,884,343,80,462,115,687,800,729,47,194,573,832,565,728,85,196,499,831,182,88,779,626,43,377,58,250,780,670,159,363,726,840,332,956,458,101,872,685,209,77,861,91,735,517,671,972,282,752,638,275,724,127,886,349,941,109,553,923,121,832,959,448,656,92,774,447,395,389,979,330,19,709,947,487,404,117,913,666,471,751,214,64,167,260,271,897,380,723,274,645,479,339,99,323,635,137,273,328,535,373,158,797,296,783,920,480,644,295,892,977,196,328,835,968,666,869,251,48,532,828,257,326,999,988,64,252,933,979,660,775,215,743,987,174,436,407,105,960,883,968,285,715,583,316,49,463,427,658,478,585,118,606,247,641,894,576,399,347,530,730,550,98,743,852,655,504,579,657,554,276,665,958,287,21,488,7,616,1,841,359,11,734,622,718,19,565,830,845,508,597,583,160,687,663,68,982,576,92,223,601,867,990,264,96,965,476,990,67,219,784,292,491,137,719,900,340,170,636,226,52,743,718,510,401,762,173,610,39,626,40,417,889,298,463,450,21,231,867,113,407,930,103,313,9,584,963,163,932,854,924,780,711,274,795,392,277,173,676,606,84", + "848,788,78,855,334,122,587,801,616,365,282,644,503,244,377,674,946,390,556,798,406,39,177,834,993,453,483,953,621,661,913,379,26,515,358,59,242,842,420,141,590,860,944,603,79,936,524,817,957,877,584,713,179,434,316,611,947,756,319,711,342,341,621,386,983,149,692,27,426,902,131,904,78,465,538,339,205,367,690,620,808,6,798,462,549,562,355,775,666,29,318,712,983,379,114,539,469,202,276,441,424,324,780,389,696,888,369,815,910,52,570,231,869,590,986,631,636,273,42,708,21,687,266,408,780,200,328,767,273,833,102,608,618,979,314,859,709,898,834,959,321,891,829,425,191,788,179,988,948,419,684,164,122,48,753,208,355,387,359,828,742,750,723,863,89,639,773,45,778,700,832,831,170,963,374,755,367,380,329,152,894,992,185,862,183,722,483,777,344,742,751,412,818,415,232,58,215,329,551,582,692,928,454,169,262,65,137,225,830,588,885,634,382,185,490,496,787,322,790,347,172,330,909,80,731,158,650,500,712,293,299,585,320,417,424,283,787,717,489,655,584,423,430,85,951,157,992,124,5,385,784,234,333,875,792,204,831,446,27,378,237,237,632,608,201,695,631,123,286,143,0,547,596,409,514,971,283,449,371,731,669,44,7,712,380,965,824,804,628,984,890,215,820,702,724,435,539,189,653,346,509,835,332,167,654,277,748,512,265,575,546,784,568,840,693,601,774,79,665,30,774,676,562,538,651,477,184,12,86,170,556,109,396,388,496,449,701,163,735,400,241,386,620,146,310,472,994,493,954,930,641,230,190,643,263,930,577,967,656,50,565,928,231,118,882,848,39,157,471,925,18,325,325,383,632,68,599,227,558,663,703,288,510,746,680,36,728,982,723,27,540,902,563,364,489,543,892,613,869,739,863,750,881,463,570,803,903,922,218,490,427,282,671,159,743,921,994,979,265,111,718,753,840,790,212,375,249,425,214,852,464,657,318,584,40,583,699,759,79,69,87,431,457,80,301,989,474,689,529,399,989,228,309,764,983,848,388,687,702,251,246,86,794,428,564,204,581,847,630,844,416,435,406,626,93,857,998,437,440,433,403,914,160,990,915,236,428,148,378,291,338,80,478,136,211,823,935,564,148,951,923,479,159,254,66,779,429,263,828,58,965,256,42,863,289,21,599,468,398,22,400,101,907,650,155,599,774,240,255,284,319,909,330,579,503,306,962,555,930,799,785,231,598,415,296,388,693,138,589,7,284,570,822,271,826,277,189,880,822,484,468,834,969,901,801,520,308,545,493,13,171,758,505,105,412,579,857,16,507,663,564,602,443,607,837,993,378,523,111,386,763,804,292,55,912,764,37,648,966,579,825,257,603,890,610,549,106,51,246,556,818,22,110,487,533,126,87,550,702,178,260,478,669,678,211,79,82,41,403,181,689,525,758,293,888,248,5,197,445,536,261,277,663,398,103,861,805,573,515,401,931,865,499,319,149,643,921,612,123,308,64,437,355,826,311,402,685,70,634,603,294,22,63,271,61,542,988,298,736,952,730,953,605,17,623,7,247,623,369,145,567,447,271,201,576,424,898,479,160,568,153,931,438,336,538,813,770,772,537,166,730,4,75,962,163,23,371,380,677,620,10,281,710,681,859,234,311,379,879,341,183,907,778,959,279,469,964,715,816,718,954,613,742,175,172,600,553,389,906,377,757,208,888,461,55,875,147,738,988,164,868,119,864,459,338,263,150,679,485,645,797,704,388,953,701,681,620,477,523,382,977,568,82,892,333,606,889,963,689,741,646,915,118,10,655,907,173,929,881,831,684,943,811,419,909,385,574,353,492,408,518,914,300,550,722,932,341,288,681,847,263,302,294,409,116,402,735,341,934,718,235,786,928,912,16,69,320,350,245,198,602,774,402,672,329,469,266,767,220,352,546,335,302,357,204,367,85,799,902,227,563,346,221,227,86,325,702,794,632,159,272,395,320,796,20,533,66,121,116,850,473,324,8,159,943,161,426,762,553,847,751,809,643,23,246,384,151,177,867,450,22,969,807,395,150,419,290,259,884,544,546,723,63,578,256,633,632,280,306,111,127,919,384,656,939,834,43,386,564,260,891,162,196,603,62,142,734,177,914,186,424,686,416,958,395,296,655,21,38,873,980,326,81,823,989,545,40,478,63,162,405,282,662,597,266,564,803,401,352,197,335,998,649,700,433,875,737,276,34,666,940,269,239,350,704,418,329,419,599,440,944,334,662,575,104,364,712,637,550,784", + "918,359,850,974,620,190,494,419,286,77,810,497,325,767,705,685,969,257,259,220,494,970,903,729,280,111,327,551,78,152,299,812,32,747,385,364,719,108,643,170,210,295,106,780,944,846,100,604,790,192,373,412,820,534,414,644,658,277,807,391,667,714,87,918,551,957,290,736,31,75,55,941,618,535,425,396,278,480,871,421,890,348,267,550,53,634,70,683,396,110,832,276,397,624,393,146,963,479,362,708,237,937,887,573,877,787,27,271,818,167,367,774,851,45,459,198,207,962,550,201,668,207,564,618,706,653,812,833,350,848,170,160,673,404,268,23,799,845,295,688,26,206,475,811,173,436,442,666,200,496,579,303,490,475,321,96,812,655,269,569,609,296,810,95,900,887,214,162,358,499,184,48,165,481,583,734,772,142,56,116,691,646,51,938,991,277,598,453,118,782,821,391,813,573,743,541,89,865,148,957,199,617,93,981,897,910,299,470,772,891,79,439,963,30,143,248,558,955,671,371,838,354,10,599,280,23,703,748,485,526,21,291,451,495,829,70,337,351,393,430,52,71,829,609,676,325,621,977,863,979,131,239,960,132,642,313,787,621,463,694,293,251,490,817,118,268,731,138,997,352,547,0,599,538,771,176,780,864,870,15,843,743,391,965,578,742,951,523,210,294,745,38,643,399,783,534,970,730,451,812,328,346,407,309,271,478,252,448,35,525,898,403,368,693,515,842,32,166,200,259,649,556,928,120,86,779,996,94,701,542,190,774,652,844,635,727,911,351,790,651,973,100,428,212,226,935,135,651,853,214,648,431,793,384,841,952,235,489,291,565,235,616,671,304,65,796,84,974,420,281,652,549,108,917,897,25,927,724,51,388,743,939,917,388,390,820,977,455,934,133,983,362,988,17,366,2,886,639,871,908,792,44,974,498,753,203,171,688,243,609,234,777,738,800,751,339,45,252,144,879,348,164,212,851,446,553,143,857,531,748,746,646,219,838,548,443,33,170,377,677,3,958,263,747,799,363,988,188,526,949,186,966,143,7,416,281,297,67,43,584,240,454,362,397,562,206,904,385,251,455,518,849,269,627,519,880,386,776,788,478,527,524,625,503,533,166,600,805,545,468,46,917,881,352,633,133,196,606,178,261,687,435,741,195,879,554,677,421,689,60,128,546,333,684,110,646,997,71,722,132,653,260,681,256,408,818,975,536,535,759,672,726,69,237,511,230,940,814,973,962,404,762,122,855,297,813,851,213,326,693,297,369,35,480,276,762,379,720,534,902,746,454,234,585,759,964,586,940,457,465,378,804,959,868,3,251,583,540,389,876,126,137,282,576,778,884,998,550,279,989,746,176,931,469,452,307,957,529,289,698,776,66,807,632,657,914,648,721,202,839,199,730,725,456,918,622,923,526,110,284,56,896,543,834,626,802,721,318,700,994,275,779,676,523,624,526,409,204,375,392,305,327,994,813,869,355,634,627,655,953,400,597,611,557,331,223,934,948,524,888,697,913,278,571,371,881,373,147,329,874,771,303,516,909,307,657,273,141,774,78,552,224,778,18,413,191,649,461,18,344,91,545,725,824,276,641,727,34,512,535,502,566,94,136,539,398,135,22,580,173,470,931,136,324,209,466,284,15,395,149,960,509,223,736,850,53,442,296,239,129,316,437,438,806,86,55,664,113,522,565,603,117,775,605,230,838,833,38,623,90,189,898,975,6,852,21,79,703,543,494,767,689,585,763,286,593,591,602,375,387,383,475,611,658,98,750,246,32,319,4,690,477,33,891,826,875,102,74,343,540,465,902,501,709,343,245,766,178,597,618,687,553,413,278,286,813,458,443,469,319,706,727,328,216,862,759,50,446,47,611,239,74,488,107,286,53,352,872,745,515,551,385,225,512,190,317,120,638,433,663,48,159,14,994,40,273,613,488,484,487,482,399,777,511,95,635,198,383,613,275,94,489,135,702,187,774,844,649,172,394,391,572,371,164,260,896,228,320,154,777,241,142,471,370,529,112,930,988,686,235,850,503,351,425,573,722,691,183,605,838,969,985,488,238,615,351,421,843,207,508,713,984,603,187,889,469,604,310,395,6,486,193,194,356,60,579,141,252,371,160,198,650,781,771,97,548,28,611,731,609,732,269,89,403,815,290,202,735,920,620,276,956,953,32,74,822,799,28,476,438,220,419,318,270,881,564,916,299,737,305,357,816,604,738,826,983,145,653,484,31,993,789,33,830,351,439,913,696,831,879,697,442,662,980,707,633,62,140,343,180", + "694,355,855,793,956,543,813,164,278,821,146,194,244,950,380,664,862,661,827,379,343,803,808,820,880,895,704,983,635,346,349,328,47,394,237,850,89,366,860,962,910,748,322,73,243,947,114,239,458,686,83,38,764,811,423,642,120,940,180,831,336,375,527,649,984,399,893,848,129,899,785,842,512,544,875,62,187,559,164,85,371,485,168,772,350,19,148,708,814,60,704,467,56,872,64,647,6,133,723,537,135,393,922,645,339,619,136,76,816,171,659,142,836,560,939,939,718,61,885,694,200,583,851,338,532,690,139,744,180,774,303,331,518,431,511,728,123,912,272,437,614,870,536,393,725,424,632,49,495,12,607,755,516,444,986,260,755,474,14,352,371,7,883,430,8,680,578,946,583,247,637,888,159,349,602,623,90,861,577,228,712,936,212,643,951,81,180,218,746,70,949,498,268,876,519,979,525,336,584,199,128,996,300,830,637,574,151,599,837,67,264,202,207,674,739,739,308,389,459,315,934,234,793,898,992,948,712,625,328,553,923,59,968,282,370,43,635,241,570,149,562,777,760,814,432,574,433,468,941,260,721,838,223,133,883,395,463,432,573,362,529,387,65,744,964,625,373,137,861,503,596,599,0,101,816,66,689,747,211,322,993,932,157,247,626,364,920,294,763,439,512,594,443,204,135,769,689,249,881,589,50,798,246,420,734,943,141,2,219,626,68,742,370,596,528,817,475,365,727,442,706,989,203,118,287,866,705,644,561,588,807,677,885,195,970,615,453,782,432,313,281,857,522,960,865,75,379,732,926,795,352,633,100,197,882,87,666,543,734,980,531,618,4,116,395,686,202,68,554,228,627,513,473,314,226,735,100,408,108,128,614,409,502,727,989,6,978,50,833,774,16,5,595,720,729,603,352,663,934,164,215,857,588,243,599,292,9,542,505,501,683,857,334,884,610,896,599,124,303,172,864,946,919,114,36,563,968,202,956,982,587,368,827,912,319,224,385,794,614,101,394,207,701,334,563,909,47,202,113,657,355,400,677,1000,101,901,400,898,466,36,671,499,96,908,736,353,860,197,28,2,401,183,162,233,409,989,286,543,633,131,849,638,715,381,396,847,840,107,973,704,238,514,243,32,634,26,447,882,523,962,899,836,159,36,705,217,238,765,906,38,593,160,105,722,665,339,549,790,174,70,169,481,390,56,31,430,473,769,204,782,728,287,799,225,698,633,234,640,645,747,984,452,712,376,51,740,14,847,99,904,340,281,520,803,62,849,937,668,714,479,75,505,816,384,824,36,68,581,164,749,802,310,206,946,337,555,303,447,647,399,359,165,447,672,988,814,644,427,310,291,382,863,535,381,787,865,399,864,492,140,678,722,343,554,168,121,448,879,353,601,521,132,83,825,800,714,604,325,962,673,990,899,834,998,584,186,776,451,9,123,931,735,168,250,524,723,418,886,79,333,545,433,835,943,631,24,818,270,607,604,364,353,881,162,587,872,406,405,411,24,848,141,602,709,667,843,675,404,324,808,448,999,140,966,781,846,751,849,817,193,970,829,423,606,927,784,497,501,403,715,78,282,317,592,339,202,203,622,161,186,504,224,385,941,943,633,706,388,569,2,868,636,654,393,467,471,971,915,827,954,98,295,651,365,237,346,285,964,608,548,569,775,592,619,41,557,150,500,14,266,882,220,526,932,346,874,990,218,887,679,51,209,639,908,637,189,652,544,938,78,418,369,244,255,925,640,349,782,835,311,553,179,208,213,326,907,842,546,823,233,724,788,45,548,163,462,169,798,315,55,215,775,812,106,441,218,745,104,122,611,807,720,421,721,515,605,303,66,857,783,886,232,338,676,438,79,681,424,819,860,759,19,841,35,345,400,846,352,942,841,644,239,622,579,811,320,844,587,870,276,189,581,249,272,31,128,925,251,608,180,301,366,989,717,850,648,585,966,463,113,991,953,965,211,184,397,798,709,990,455,12,871,614,705,983,118,924,314,173,38,939,461,849,404,701,515,634,986,712,703,731,515,107,878,642,502,382,897,312,811,198,729,799,70,37,632,297,643,106,594,442,366,601,13,521,316,562,926,237,644,397,306,327,992,375,650,497,637,127,855,154,694,47,56,883,161,45,123,278,909,8,868,909,382,844,1000,716,802,297,305,880,209,554,853,121,690,410,834,856,257,142,646,656,516,654,128,150,160,248,80,446,307,827,680,652,541,564,764,892,772,939,856,408,665,127,872,11,917,634,914,275,683,694,940,141,827,794,758,154,491", + "512,944,107,135,45,340,65,442,43,660,859,335,18,123,105,738,566,934,64,419,206,54,631,333,859,484,527,122,411,431,416,682,483,334,141,643,992,91,885,10,505,556,853,897,261,26,793,817,140,505,258,581,338,378,120,786,642,320,57,884,842,104,37,145,632,891,347,248,377,240,57,626,280,695,221,68,335,931,639,245,268,37,852,785,480,25,523,140,775,187,456,763,299,949,86,341,114,7,15,81,93,466,346,180,757,905,692,645,823,450,787,473,561,961,780,201,554,497,240,565,636,378,54,246,628,958,108,778,311,885,36,971,107,438,321,350,773,779,23,515,604,768,613,404,995,883,155,958,748,444,747,310,51,223,904,865,387,268,954,693,667,753,635,898,973,619,882,541,891,480,195,95,220,271,915,538,754,836,646,624,226,346,739,379,486,371,372,738,500,649,8,478,263,658,849,502,321,215,462,66,859,615,222,873,751,723,11,245,829,380,926,297,5,941,412,905,921,70,555,900,386,879,377,181,313,904,31,135,58,451,74,514,609,936,778,851,156,971,453,491,907,62,578,673,406,181,966,180,381,924,128,951,985,443,841,393,639,317,521,63,378,735,167,871,194,348,180,853,816,466,409,538,101,0,799,916,693,649,316,477,464,835,767,994,676,868,304,800,756,700,127,618,96,870,370,376,50,830,542,6,575,215,774,853,515,179,344,391,891,795,614,881,134,752,849,534,89,676,837,998,100,631,42,842,948,81,600,666,190,447,515,483,205,213,930,380,634,102,872,283,995,926,450,674,807,628,707,920,192,27,193,667,474,511,144,164,558,945,528,485,610,308,431,504,606,640,535,498,60,359,696,669,59,55,307,562,880,706,623,663,3,342,765,157,869,985,686,694,345,587,482,601,159,169,177,713,848,256,451,767,302,327,275,162,2,280,894,833,845,601,272,847,719,622,539,973,425,275,514,151,375,441,469,899,754,374,585,231,194,778,509,833,166,834,914,130,882,915,230,664,344,876,423,494,435,761,198,901,502,739,137,932,588,630,362,932,127,470,335,505,302,168,596,458,827,392,321,192,897,263,135,244,619,811,301,446,750,738,396,357,846,674,592,879,182,956,608,415,112,201,389,225,33,471,266,399,140,747,775,845,594,545,236,182,254,625,964,416,683,464,634,826,505,139,274,816,745,87,628,636,69,3,392,296,758,83,666,937,692,354,900,607,514,26,91,201,975,531,567,672,918,347,302,881,466,924,7,655,434,60,314,513,583,481,211,525,977,432,849,465,546,902,733,857,814,654,896,526,619,422,531,722,151,115,43,29,388,783,406,812,628,79,507,655,289,157,609,1000,827,956,580,133,578,369,934,529,585,864,470,957,912,39,359,533,530,461,204,399,190,184,879,276,931,485,396,557,557,910,140,557,936,651,817,199,726,97,672,883,62,963,602,347,933,305,793,176,632,9,809,895,138,558,629,769,727,24,117,932,569,607,498,942,911,119,815,755,809,297,632,278,98,960,924,98,862,342,758,533,739,708,431,184,304,783,868,486,682,608,535,797,280,634,549,962,948,175,216,91,624,320,309,295,435,172,156,38,593,842,142,584,995,107,983,755,785,447,301,382,287,786,510,304,976,526,2,621,847,635,853,510,416,455,105,854,768,305,318,115,430,898,645,627,115,484,365,668,338,378,229,874,787,545,776,598,721,524,69,961,28,525,909,909,476,977,176,831,745,405,529,602,85,830,745,397,451,357,366,316,807,814,607,482,173,308,820,119,708,912,17,862,679,496,741,427,76,860,354,98,180,818,755,852,272,782,635,503,414,771,711,633,634,108,802,482,93,792,418,885,930,136,251,72,174,354,952,574,139,276,949,279,527,908,215,538,343,685,616,901,729,680,388,680,262,65,38,830,987,440,829,466,650,676,867,486,847,748,55,52,631,376,13,187,265,9,637,713,265,648,664,289,787,479,560,124,868,791,175,182,430,996,451,102,734,191,644,348,701,159,724,546,860,154,829,545,570,331,832,793,650,90,123,918,549,400,17,238,286,44,194,769,480,535,70,900,191,12,128,955,271,6,896,695,765,82,866,135,793,478,396,754,377,899,548,264,516,468,762,409,270,483,350,873,144,847,143,510,763,566,798,186,916,675,493,590,201,178,894,112,64,324,481,238,162,684,708,793,574,546,302,132,814,214,874,532,577,589,228,163,801,699,664,330,762,848,584,287,90,982,110,760,438,971,44,700,418,132,962,741,916,822,829,812,242,693,696,95,537,856,840,220", + "390,781,868,183,119,552,477,419,471,782,375,471,482,635,479,867,224,137,367,846,323,340,988,304,749,523,337,382,988,420,545,815,958,660,939,463,881,974,414,85,274,305,120,528,548,911,221,797,571,385,512,109,775,511,498,284,534,768,256,18,797,341,375,327,352,429,810,819,399,650,335,775,592,85,130,556,951,528,920,934,462,499,923,857,183,707,747,535,611,985,573,628,134,487,175,263,76,737,850,595,823,293,799,201,861,345,451,980,717,239,139,255,420,755,593,457,298,170,568,939,134,44,681,584,48,131,284,894,206,15,899,657,440,162,407,253,786,248,98,548,896,263,294,293,964,472,514,940,867,39,510,62,627,727,203,286,412,86,377,318,386,660,963,491,232,173,623,238,385,865,706,330,429,139,409,947,825,676,836,221,533,41,36,24,792,987,177,428,24,412,629,432,893,903,698,800,503,59,808,502,992,624,557,945,721,135,399,186,160,811,771,539,32,183,256,319,729,428,846,926,390,426,174,704,907,627,528,498,245,340,701,698,623,172,562,106,391,803,490,500,681,738,618,373,670,952,859,50,953,245,410,582,721,21,920,332,86,196,644,134,353,693,472,759,339,496,766,470,600,926,514,771,816,799,0,551,561,65,793,333,190,292,90,76,737,555,55,397,628,196,53,701,248,738,202,575,903,733,988,220,815,122,163,881,838,419,158,172,32,673,431,742,20,978,258,692,459,873,681,166,937,193,182,499,909,147,737,484,643,812,118,598,982,88,4,944,212,36,378,460,59,988,360,144,823,799,874,96,878,707,490,576,812,58,562,866,831,611,552,266,931,82,753,770,120,866,615,469,934,397,668,925,713,198,905,195,759,857,907,238,494,359,139,171,435,806,338,282,2,700,925,925,750,166,975,198,145,458,772,375,779,461,661,582,476,563,565,97,941,991,807,412,914,532,479,691,406,95,138,231,578,373,987,762,431,891,143,847,410,119,302,98,80,615,552,397,710,22,56,291,833,752,670,314,317,291,953,111,778,36,815,922,721,721,138,489,841,532,819,746,26,412,213,63,232,158,65,835,647,505,546,224,792,189,223,64,889,586,155,15,298,339,997,910,713,879,639,459,30,331,922,654,237,800,226,517,62,886,793,184,328,817,462,788,934,850,848,526,483,218,204,960,492,107,915,240,697,792,738,54,960,645,880,399,210,981,766,28,898,479,697,876,137,520,742,368,791,286,617,312,663,706,674,493,582,295,341,996,657,327,697,168,996,442,371,983,987,367,289,46,166,901,297,520,697,47,312,419,673,216,467,249,547,398,14,896,308,729,225,802,747,281,123,336,358,213,939,606,745,367,559,859,652,371,160,445,822,79,870,316,452,221,126,575,986,99,90,777,836,506,409,915,895,979,843,356,557,691,498,283,721,187,585,324,512,470,74,976,63,581,213,840,824,31,327,545,383,889,852,346,848,626,120,123,627,497,316,657,583,586,911,143,768,259,742,386,438,133,874,442,486,424,412,630,600,926,817,858,945,987,475,1,518,847,282,665,586,344,306,726,47,325,940,693,203,772,489,3,279,409,655,274,796,185,320,165,388,92,496,458,778,491,180,841,561,465,208,268,229,102,567,105,221,882,781,327,150,92,130,792,468,872,341,370,548,291,410,317,81,214,512,933,220,12,872,164,59,570,1000,105,876,228,576,181,425,992,722,194,919,170,480,36,286,96,720,547,562,454,164,343,374,661,277,284,601,378,522,37,446,751,419,749,886,508,812,331,210,878,909,114,384,500,697,425,389,243,69,532,382,6,491,69,406,374,816,487,118,285,301,641,306,945,916,860,804,111,574,588,183,76,750,610,208,385,892,770,284,678,345,660,722,923,509,743,147,825,812,64,108,214,161,72,902,267,263,707,465,677,925,904,613,996,109,518,358,835,400,653,951,525,478,648,200,149,935,569,316,121,871,959,419,532,514,203,827,606,992,903,21,738,816,801,608,425,123,407,962,116,268,36,317,514,217,941,22,885,767,71,303,302,945,786,229,272,138,716,856,261,809,940,847,672,167,721,926,76,614,158,757,445,642,980,805,700,250,44,549,16,199,740,789,762,181,112,187,640,486,646,150,203,354,168,96,744,986,704,692,222,62,728,355,893,930,482,468,557,498,144,5,797,555,778,719,402,696,276,980,440,987,453,453,140,991,734,925,525,936,749,898,51,520,121,662,86,687,536,510,626,929,240,941,46,161,687,215,411,681,123,297,570,834,212,198,73,653,269,590,888,652,957", + "913,907,269,768,527,360,543,916,258,662,634,855,447,871,291,168,416,990,789,269,882,746,940,352,532,582,57,77,590,275,5,995,302,601,658,66,300,265,364,5,283,673,648,406,661,872,555,299,730,606,936,370,74,91,766,190,179,459,935,407,943,201,635,279,745,496,607,554,138,894,2,753,149,553,660,110,165,282,567,694,916,921,270,897,4,467,439,934,544,818,806,191,499,253,997,229,448,469,255,123,425,958,929,609,276,685,256,965,304,90,582,800,666,346,523,278,722,666,258,257,300,744,2,118,66,404,803,496,536,76,328,247,492,754,390,590,192,8,825,520,202,389,165,448,597,212,4,157,411,228,810,426,105,382,124,220,959,975,982,804,799,719,407,395,260,678,832,972,319,771,989,286,115,752,15,244,196,492,541,369,58,617,660,617,392,667,724,299,389,704,840,340,678,160,627,925,806,728,663,859,212,739,40,9,943,948,852,776,881,190,635,685,707,751,606,504,544,526,332,982,723,849,433,77,959,165,640,832,952,729,711,666,875,523,475,637,918,208,700,47,697,430,934,445,653,951,255,741,840,260,305,346,458,155,875,721,888,175,255,732,886,981,293,721,48,787,211,909,15,447,971,176,66,916,551,0,737,544,136,250,200,669,30,511,325,94,138,710,705,324,862,457,811,790,981,684,976,248,732,886,420,4,274,808,469,721,291,546,869,317,185,788,278,239,692,212,468,443,116,790,710,795,215,962,156,530,220,323,9,649,681,25,61,449,883,866,327,323,434,975,314,672,208,156,976,676,329,617,27,693,156,705,579,646,673,183,293,432,840,266,122,184,410,617,66,458,721,599,841,610,617,582,572,491,292,70,445,577,735,209,779,465,794,369,886,286,847,835,41,69,386,231,178,812,443,155,5,143,573,498,293,699,362,654,603,974,523,161,76,824,279,427,866,827,970,705,702,446,753,422,786,788,388,853,462,840,921,307,638,199,943,383,596,676,825,281,48,365,763,458,562,728,999,835,14,125,123,59,230,1,223,771,485,74,466,137,318,837,782,33,347,749,90,293,641,440,188,517,551,900,560,511,442,702,118,207,773,804,839,481,543,379,303,673,177,809,603,552,895,948,657,976,677,346,183,115,549,72,292,424,435,597,192,228,727,286,742,869,11,662,517,322,173,548,600,484,725,465,199,351,594,777,376,265,991,411,773,562,18,748,865,624,259,94,807,689,40,138,371,821,816,84,271,590,984,283,254,683,558,670,969,320,530,499,898,869,939,498,838,770,604,952,753,667,566,603,51,774,53,357,426,450,692,922,763,355,655,438,838,54,791,715,207,256,79,427,754,605,416,455,946,223,219,764,724,565,796,24,835,274,337,856,118,718,133,481,360,240,38,916,58,778,967,116,832,376,592,98,164,190,949,537,225,919,932,194,9,211,814,127,217,329,558,886,818,989,966,227,982,296,114,52,537,49,975,871,332,738,833,736,840,848,489,255,257,585,105,427,545,557,664,624,48,78,473,549,337,336,406,549,516,301,299,937,126,682,977,355,959,829,106,392,95,201,53,756,733,382,383,365,270,533,37,375,529,401,810,70,766,892,589,934,209,255,930,927,597,929,397,857,515,918,111,725,795,265,40,79,887,229,529,74,226,473,586,730,221,375,704,903,201,479,778,193,807,854,36,379,186,990,182,147,374,855,60,617,385,631,877,449,871,660,388,823,552,660,29,803,268,808,288,108,600,671,475,568,265,383,357,493,590,263,578,207,904,105,420,489,974,168,378,584,864,78,599,748,267,580,764,574,460,598,360,375,198,457,705,866,506,505,782,41,561,105,589,634,884,192,117,646,376,809,496,934,32,435,274,663,246,970,479,15,713,757,224,967,967,627,938,416,545,379,208,273,526,38,275,454,680,807,796,975,1,735,875,602,511,546,327,380,659,472,895,139,40,393,649,305,307,126,636,10,437,927,787,925,290,772,94,167,266,966,186,275,873,701,656,189,571,450,120,919,333,73,107,313,553,503,916,476,692,935,639,936,810,140,926,178,414,728,298,680,822,601,661,369,8,259,443,976,167,475,56,740,472,405,437,728,911,98,225,385,726,184,555,963,628,690,163,641,273,804,118,779,93,614,862,305,307,125,894,371,848,774,393,534,801,323,346,674,478,101,387,498,549,819,214,436,455,563,172,253,732,476,435,594,399,134,504,331,307,136,723,879,375,785,8,180,343,973,901,511,500,774,600,42,57,746,72,34,562,905,942,638,265,732,981,880,99,260", + "118,520,162,746,444,441,874,736,732,468,189,326,694,405,745,819,385,647,280,463,945,187,326,445,433,692,400,573,445,670,3,484,12,775,145,584,474,982,649,531,271,961,675,579,801,39,525,534,568,983,197,753,496,477,630,90,362,812,71,585,943,914,333,97,122,178,917,537,205,757,395,318,431,351,517,82,141,675,92,231,992,422,920,470,893,833,749,778,913,727,507,600,893,838,95,48,995,697,542,491,535,235,136,725,639,380,93,989,601,951,466,288,111,677,537,291,827,541,364,401,756,287,535,258,368,406,469,870,765,630,633,362,784,116,558,414,960,965,705,279,306,640,367,828,491,188,921,330,900,410,375,298,290,464,524,207,182,948,818,310,453,189,150,183,723,620,515,405,548,899,987,326,276,974,744,279,812,40,58,504,793,808,718,814,957,836,579,489,529,525,617,115,99,586,78,922,906,847,276,147,923,214,341,334,561,356,582,627,188,9,235,851,815,906,848,55,570,420,873,537,580,248,654,549,26,306,424,115,614,932,796,897,637,40,925,812,228,199,329,729,836,553,249,497,930,241,211,508,685,809,566,871,59,975,73,117,487,672,721,296,859,356,825,45,403,882,597,242,782,609,283,780,689,693,561,737,0,220,994,17,903,207,123,755,357,28,630,134,977,592,584,556,478,873,382,156,626,599,480,958,354,760,517,331,239,735,803,412,556,237,391,768,296,343,994,971,804,527,582,573,905,620,919,79,563,882,508,506,168,533,904,649,192,765,751,498,986,827,937,220,645,624,618,308,353,733,749,542,648,155,323,377,212,57,562,778,708,913,403,876,449,234,494,922,749,453,810,561,988,377,615,407,701,84,37,296,998,483,508,846,236,376,620,388,415,210,808,345,344,732,270,853,917,927,121,117,971,74,693,14,341,192,587,925,919,645,853,110,817,837,169,556,889,235,647,735,277,230,550,460,254,56,956,942,143,28,281,588,150,407,83,212,577,132,707,376,468,486,637,609,664,123,772,371,541,343,672,309,588,122,596,212,478,29,161,394,447,835,43,855,549,213,995,980,412,650,613,484,604,320,988,564,621,831,99,419,278,897,57,491,242,233,869,815,714,983,890,243,559,403,31,798,628,37,694,680,622,328,770,397,909,434,908,326,329,421,804,162,631,306,712,865,625,915,114,735,444,716,719,462,261,57,779,194,142,500,751,970,239,858,736,581,31,179,189,75,938,34,560,748,588,403,18,260,937,35,550,690,248,467,879,496,263,795,895,977,326,445,682,974,139,806,161,382,502,771,919,438,404,604,208,25,801,914,713,618,26,134,403,370,287,706,805,282,43,49,222,550,105,566,753,611,608,149,215,536,710,163,765,917,766,318,326,822,360,492,122,589,425,200,964,565,310,405,918,916,75,736,237,37,187,786,207,359,379,129,192,262,630,743,509,140,846,402,62,899,548,686,619,166,190,324,850,174,657,42,63,562,305,242,118,900,454,218,629,901,290,464,59,720,442,656,624,545,106,164,347,786,605,836,905,662,360,104,204,401,440,444,297,101,878,165,218,635,955,523,721,266,98,128,149,921,613,665,593,149,125,685,254,982,759,491,587,90,932,115,971,892,784,484,206,562,746,948,147,244,471,426,525,782,687,670,758,51,357,96,774,976,3,884,172,724,475,364,953,377,968,998,990,856,657,973,82,197,779,796,192,549,976,780,756,912,996,363,650,791,624,641,450,342,297,910,77,849,381,169,712,200,106,261,117,345,835,866,72,358,730,504,773,919,683,241,143,698,341,221,116,750,799,143,641,274,405,714,514,81,602,739,587,571,246,682,485,273,961,25,837,147,132,942,335,206,228,705,738,50,149,878,917,342,754,630,634,793,303,66,325,370,534,840,456,286,159,990,515,776,242,180,763,690,876,707,979,473,179,923,4,675,23,897,408,992,284,546,181,832,73,922,728,56,953,877,43,633,348,502,802,127,282,946,708,4,343,590,836,469,710,608,297,640,581,419,400,962,278,736,170,968,636,624,360,532,98,827,609,993,496,653,995,724,454,918,649,121,580,643,949,562,152,503,519,511,796,455,412,85,163,280,824,871,597,341,281,35,62,110,270,434,310,808,185,513,244,482,752,813,219,519,410,103,222,130,338,649,253,796,633,812,742,231,441,950,382,329,730,564,704,806,316,473,772,52,838,876,231,25,979,926,91,842,856,642,633,563,269,359,433,540,411,181,806,405,330,775,433,989,561,242,370,33,116,421,473,16,884,502,904,669,133,207", + "776,52,197,162,102,988,356,57,57,724,387,189,887,57,326,811,108,710,473,25,564,292,844,444,763,390,3,473,392,708,494,538,580,21,803,612,717,857,151,850,236,952,346,400,277,137,846,334,628,160,639,538,623,34,605,974,401,837,830,236,191,653,268,478,667,488,529,36,196,565,636,88,972,31,139,93,442,940,606,306,34,53,565,65,404,928,623,699,550,206,732,53,661,411,16,777,873,626,56,414,409,842,919,316,966,645,237,961,996,92,604,139,358,495,177,662,692,234,802,45,929,78,468,657,982,113,589,393,181,92,374,889,73,269,221,202,983,142,751,994,639,100,974,550,975,811,516,772,617,366,272,232,46,667,904,462,550,871,324,85,561,57,247,128,130,899,113,356,854,99,61,288,449,737,143,330,700,42,688,166,447,26,387,285,397,385,990,720,644,286,155,822,620,903,512,591,437,957,486,98,618,403,872,382,420,210,839,901,118,179,566,107,112,406,360,829,685,667,716,15,596,354,407,667,918,102,273,30,692,723,40,806,826,286,62,980,307,745,464,319,581,93,768,66,314,675,61,621,130,175,157,497,376,649,976,200,638,124,972,640,847,809,550,234,775,105,62,50,339,281,449,864,747,649,65,544,220,0,297,593,326,107,822,262,399,451,818,974,597,221,991,476,839,724,25,218,605,925,101,572,148,477,920,210,786,572,75,463,2,251,755,347,938,31,187,891,13,786,556,723,919,538,45,712,223,853,359,410,657,837,927,849,468,414,188,2,39,390,281,671,209,309,83,718,72,497,81,787,840,134,313,177,13,390,149,232,181,271,52,108,449,182,2,366,343,748,105,581,162,16,653,137,881,482,260,465,535,109,70,27,328,505,652,262,288,224,504,906,124,645,89,535,103,614,594,872,47,704,298,98,172,654,5,873,434,247,978,795,355,454,209,362,11,603,282,245,668,368,199,961,378,123,442,386,641,561,612,770,378,480,755,849,271,230,378,867,581,253,883,596,88,874,209,671,230,236,223,508,209,861,671,721,563,936,490,749,49,641,675,800,144,191,14,7,468,826,97,447,74,883,796,125,772,166,305,51,910,114,342,856,480,439,16,664,984,994,993,515,738,540,33,126,804,84,973,91,937,996,379,666,581,30,674,241,779,821,666,671,896,749,288,16,191,979,905,632,65,978,755,417,31,870,240,297,776,536,620,643,330,15,349,847,995,735,144,970,684,242,609,553,329,320,403,956,94,298,714,468,427,858,339,795,769,248,436,515,833,565,347,776,874,526,5,807,738,186,97,530,917,753,506,644,325,39,913,776,728,553,966,697,850,421,232,863,203,600,682,222,539,783,637,902,333,774,889,571,576,630,625,304,618,13,157,584,958,806,274,743,137,347,290,820,433,618,115,825,423,764,433,879,287,394,355,973,96,374,289,998,737,515,226,121,190,25,491,272,506,321,436,923,934,566,631,29,329,488,961,635,657,318,715,384,133,617,13,729,988,832,195,385,587,730,46,341,583,701,459,461,965,710,436,469,279,889,983,68,811,824,753,108,740,407,33,902,400,932,675,504,999,686,426,276,769,795,626,254,817,735,605,125,725,323,379,794,856,723,514,125,370,162,837,405,865,467,591,965,899,884,588,810,254,722,359,5,453,562,558,638,746,944,546,252,127,953,839,820,621,271,866,148,270,966,642,142,905,908,694,489,62,290,281,746,506,774,974,150,797,721,769,265,409,869,80,44,474,608,864,142,243,679,740,11,154,685,176,390,434,197,345,76,846,694,19,966,427,191,890,606,734,13,912,118,741,113,858,108,909,640,996,431,760,924,432,909,612,440,149,895,750,191,475,513,709,409,260,863,863,369,670,743,798,664,484,402,485,285,739,811,956,727,783,328,604,297,226,451,725,252,725,678,142,6,335,647,820,155,570,559,920,344,845,835,30,310,600,669,44,619,313,38,756,357,3,870,769,418,363,539,274,354,969,930,785,104,17,383,640,247,121,729,439,898,439,421,852,330,517,24,555,90,875,62,566,140,682,609,935,437,313,158,86,133,889,362,965,709,840,784,258,648,895,683,281,16,83,514,560,63,660,276,538,311,956,580,570,120,187,589,781,310,445,835,367,936,429,51,261,307,499,188,352,14,583,699,131,711,115,622,490,722,943,866,278,339,425,842,560,520,871,720,916,364,765,495,665,363,735,102,548,666,140,169,957,667,458,162,648,547,122,560,512,430,335,932,801,856,986,31,626,857,427,421,218,394,346,650,529,63,126,259", + "441,669,338,3,62,911,33,504,651,52,557,369,529,596,698,819,118,786,895,785,220,102,314,963,844,219,868,626,431,977,628,292,956,33,781,37,492,234,827,301,96,913,779,871,663,827,442,810,259,773,22,950,906,697,499,14,266,269,766,688,739,155,656,528,957,619,344,258,64,196,216,971,33,356,53,192,573,825,851,904,597,289,102,988,84,661,642,274,775,496,917,61,998,938,974,321,954,72,437,878,789,207,759,836,55,304,284,937,29,549,863,166,717,542,226,585,837,867,733,624,884,543,573,749,745,327,132,826,371,963,427,416,494,167,785,442,122,232,25,88,287,833,99,766,887,777,773,782,138,443,627,643,861,830,518,195,396,220,376,758,252,347,137,150,262,565,143,701,90,885,60,10,528,385,818,164,964,167,99,615,193,559,459,657,253,976,573,22,313,700,330,962,855,897,868,82,800,847,77,728,125,559,879,707,992,493,393,989,472,396,975,766,581,861,903,31,166,531,10,971,146,811,51,867,246,774,946,143,467,112,826,657,149,165,799,523,9,728,352,719,568,387,789,621,449,489,659,816,42,921,750,858,730,988,973,578,154,301,95,740,23,780,45,579,739,362,996,733,135,10,371,870,211,316,793,136,994,297,0,45,911,816,531,948,127,569,709,377,345,873,978,580,101,769,250,96,709,863,991,496,797,664,464,776,32,432,141,315,44,38,418,824,875,127,192,424,122,534,895,654,148,216,261,280,392,899,901,105,393,538,392,150,875,994,68,523,876,410,153,200,774,821,374,505,747,796,504,754,415,171,689,684,429,423,541,398,856,274,767,6,930,913,475,191,530,825,544,564,313,972,223,717,48,595,855,492,780,771,489,927,956,950,980,954,683,669,874,443,599,906,60,380,869,187,452,367,53,505,597,79,358,234,88,292,461,520,396,298,166,458,172,823,51,627,349,702,191,534,244,451,781,678,345,274,793,493,428,338,766,935,730,399,494,331,941,387,806,479,53,810,142,852,923,377,279,277,541,93,296,154,948,873,549,737,447,463,798,372,424,640,451,162,262,423,520,414,573,634,118,583,614,263,715,264,672,904,288,313,919,450,336,141,483,49,878,696,777,955,636,386,128,675,120,68,194,350,97,192,995,393,494,413,919,197,487,140,159,464,596,864,812,852,753,102,763,54,858,114,330,764,78,152,308,218,729,621,627,953,951,89,378,784,600,771,219,634,528,776,116,810,756,54,570,127,701,623,264,616,23,447,191,158,193,933,183,186,371,925,396,30,738,211,952,101,107,591,790,24,233,331,178,995,526,472,58,612,470,490,821,860,474,174,606,976,322,109,664,350,851,368,320,217,172,754,908,731,933,762,698,204,306,370,158,70,333,810,156,195,170,308,175,737,654,849,290,480,460,660,726,35,989,344,720,466,110,355,881,90,345,740,877,257,142,527,178,624,688,112,892,350,178,628,839,59,155,76,260,606,223,966,956,658,405,583,465,304,132,332,262,649,293,28,259,364,879,54,545,665,417,2,247,393,123,943,333,104,532,93,941,263,304,71,932,811,713,216,292,349,96,774,827,17,528,692,960,348,878,401,981,85,718,60,666,412,926,30,557,438,475,247,24,668,542,227,510,298,291,360,2,816,355,205,214,920,566,704,974,413,913,447,508,135,249,382,6,40,266,345,533,96,469,298,155,417,962,59,491,596,491,814,202,727,475,325,433,172,161,248,925,583,613,915,33,11,732,186,144,419,62,45,126,248,833,837,309,719,120,637,283,232,151,234,722,61,998,94,262,817,948,933,941,489,480,222,20,848,675,751,964,606,937,389,544,374,990,256,300,2,255,959,504,818,22,112,110,547,350,787,445,134,995,989,361,468,925,586,835,177,59,673,510,430,881,808,24,491,846,491,639,48,657,339,346,914,389,76,355,777,275,750,651,3,461,922,320,490,661,998,664,24,328,311,316,415,947,28,722,307,710,269,145,889,50,315,409,481,784,20,504,940,164,155,281,438,562,31,752,259,955,716,267,512,567,528,225,637,459,248,225,519,107,361,362,443,800,630,796,311,761,87,754,433,937,748,840,449,884,449,378,705,266,489,299,537,908,6,512,395,430,589,754,237,793,922,292,103,78,919,118,27,579,898,534,376,592,704,117,833,641,739,446,356,707,728,313,815,897,424,252,282,800,294,619,887,573,389,762,144,730,306,679,731,762,127,783,37,358,740,306,359,309,534,530,829,965,307,87,991,845,481,924,363,296,435,703,209,452,224,68,3", + "438,597,314,73,169,846,518,204,810,110,56,357,930,930,649,817,752,629,85,620,93,418,623,145,410,526,725,768,364,86,469,334,370,691,811,496,73,926,477,200,383,697,179,756,393,227,998,917,978,506,753,710,405,726,108,276,550,760,360,215,897,71,727,510,13,91,531,15,957,172,180,162,639,203,283,431,288,920,919,865,552,732,481,871,689,310,883,722,191,926,670,582,287,722,330,260,389,830,189,429,443,572,902,317,829,868,760,326,133,273,987,463,555,546,260,159,852,687,45,136,185,983,861,259,154,204,675,324,820,850,89,393,77,814,219,549,779,599,903,296,287,643,297,571,169,582,403,900,243,205,378,300,295,363,244,493,463,36,166,11,262,350,222,446,475,168,204,176,533,560,204,134,978,254,523,359,683,338,268,737,227,750,845,909,448,883,121,671,861,477,80,253,516,476,886,181,347,751,859,968,754,892,733,383,663,504,365,551,914,670,98,193,216,878,926,101,267,371,578,25,81,54,704,734,471,493,871,227,650,311,775,309,317,920,292,66,85,473,875,488,60,150,570,180,922,901,952,240,66,669,263,840,198,72,323,261,422,539,13,458,363,741,59,975,717,904,142,591,134,104,731,15,322,477,333,250,17,593,45,0,682,770,810,251,109,575,6,188,15,993,630,974,936,985,725,231,569,298,346,757,965,625,448,874,75,326,116,412,849,221,584,442,510,994,133,200,316,458,325,50,187,656,388,664,211,794,154,685,435,963,703,628,972,729,203,247,889,999,116,924,495,614,394,295,950,90,223,74,462,534,833,240,226,222,431,179,254,800,449,722,373,700,385,419,530,377,726,492,89,212,166,889,891,543,762,361,357,110,308,566,589,527,784,202,183,25,516,484,487,119,46,376,658,321,125,655,531,820,847,649,451,336,471,675,142,478,188,708,308,318,315,102,329,558,793,132,80,385,961,656,894,707,460,873,695,27,623,371,335,889,398,75,539,647,429,11,40,9,975,700,513,769,508,79,458,325,866,930,287,295,294,751,477,192,270,748,66,149,373,381,936,519,958,309,867,960,878,343,504,320,323,582,740,737,473,65,196,203,358,596,65,137,892,563,173,857,642,681,246,503,863,140,921,834,959,601,470,734,605,320,787,383,846,173,671,392,64,830,314,805,983,946,62,563,957,886,331,324,258,89,388,522,567,864,592,886,668,301,832,34,909,627,572,186,211,886,289,894,530,110,266,781,847,786,370,829,213,317,632,580,381,875,629,102,977,544,997,633,363,653,121,36,324,922,842,61,567,68,46,693,916,145,971,177,183,23,895,734,311,868,157,523,157,715,944,774,947,359,193,46,749,321,778,155,365,808,930,803,856,710,572,717,114,969,550,308,667,613,388,314,706,518,790,33,728,744,413,815,972,755,74,134,519,345,792,372,583,571,967,516,846,497,865,221,258,777,605,195,828,274,619,319,846,2,986,586,211,112,998,552,504,807,645,870,457,76,380,651,129,573,621,341,17,697,194,938,725,526,303,512,617,911,371,817,565,462,685,866,596,46,974,771,565,358,410,877,193,459,829,99,273,301,972,916,901,143,970,509,182,38,685,112,11,554,950,729,272,689,459,534,468,261,991,795,972,240,184,678,993,958,182,315,649,515,247,408,908,271,389,632,791,564,153,355,438,179,716,46,390,234,769,978,448,782,572,921,138,119,218,154,889,702,711,353,578,499,610,577,38,534,467,55,198,835,251,476,941,577,93,758,856,933,19,694,284,26,867,530,285,151,9,746,458,807,241,691,267,924,128,639,953,209,941,658,250,906,745,480,96,56,185,767,87,261,739,939,341,939,872,323,202,369,580,52,254,731,422,247,887,675,709,107,194,445,983,27,222,688,880,222,195,703,588,22,915,306,838,134,770,600,91,44,774,664,509,339,444,979,597,668,568,913,74,411,98,481,424,59,308,730,983,715,35,186,928,726,601,531,713,485,124,116,861,318,288,776,682,929,659,977,342,566,579,820,507,729,825,433,70,295,918,375,114,823,806,552,59,60,357,297,715,895,666,999,13,390,849,681,113,44,889,874,286,982,808,682,34,38,711,75,985,602,828,504,637,243,337,551,555,579,403,432,516,364,885,349,920,584,127,371,611,194,391,698,759,166,430,457,367,311,38,736,89,883,674,652,37,856,197,996,553,174,848,112,654,868,253,187,570,506,625,555,536,452,881,238,710,11,981,502,241,657,517,210,326,334,396,62,822,306,432,745,429,520,295,463,711,39,281,875", + "488,292,996,810,396,39,998,868,559,936,324,598,618,517,794,882,353,702,264,293,6,228,114,873,978,830,537,462,987,375,948,681,809,437,495,687,601,560,129,296,881,491,388,354,291,82,160,815,126,796,104,32,329,534,953,147,426,55,81,299,815,709,262,819,769,965,879,33,172,217,884,583,937,638,511,982,412,927,862,920,617,435,539,824,582,260,940,638,1,615,249,397,201,109,797,469,94,470,726,802,887,28,211,605,326,206,627,781,739,819,309,483,699,962,65,217,840,449,245,367,701,170,709,489,512,472,324,824,961,356,686,742,492,465,426,537,152,49,883,121,5,999,911,410,525,540,765,535,822,4,20,419,399,805,86,16,573,787,482,710,1000,394,862,610,297,39,542,915,800,260,666,489,508,422,98,71,326,176,989,473,229,205,780,757,239,431,986,976,251,413,519,930,93,202,901,540,751,341,991,33,511,817,939,429,285,195,789,870,816,324,636,198,63,914,617,566,775,320,214,744,23,946,573,639,683,706,22,856,840,780,27,552,598,896,947,708,47,443,538,474,849,201,846,741,453,368,874,917,384,838,30,887,968,369,751,259,608,523,261,189,562,999,339,118,499,996,766,724,838,693,669,843,993,464,190,200,903,326,911,682,0,406,283,870,599,348,147,541,683,694,935,25,500,264,305,632,464,993,379,342,450,476,655,974,965,87,511,457,31,800,904,883,673,713,490,865,554,969,987,133,149,259,604,641,643,260,830,264,549,928,423,612,521,64,327,766,25,943,98,632,343,638,695,30,193,494,266,493,238,173,804,159,553,593,46,242,38,357,140,789,155,60,380,100,462,775,26,703,122,616,973,490,801,166,521,199,970,467,557,885,607,869,794,62,895,730,679,75,500,246,457,714,52,132,532,287,685,517,368,499,126,416,479,800,91,771,393,912,552,151,698,338,47,711,264,658,105,509,252,104,281,671,429,754,514,674,858,320,484,739,983,103,79,703,108,435,238,529,820,474,798,178,846,737,898,420,677,880,169,305,621,745,172,52,67,783,449,629,318,323,7,992,867,463,583,742,801,552,458,500,413,965,805,828,16,454,927,914,23,61,13,727,548,915,888,353,388,443,599,615,157,240,666,926,818,652,855,592,137,618,931,737,3,828,559,11,749,569,990,929,583,581,761,247,150,787,394,921,297,167,948,415,806,530,447,599,222,119,73,81,358,405,398,21,984,688,594,178,63,684,788,302,150,859,256,944,263,299,778,258,800,254,120,203,881,644,524,928,14,966,287,290,120,313,642,752,557,873,711,358,627,405,792,889,545,372,294,139,333,12,742,491,96,365,632,398,26,582,843,146,528,742,894,622,965,665,424,869,440,637,825,477,691,508,982,412,937,790,726,949,465,923,722,812,124,559,115,58,436,245,464,702,407,416,953,319,809,876,697,510,326,69,700,664,687,48,441,222,903,62,247,335,884,434,396,508,208,305,923,767,121,135,190,244,592,434,954,623,204,488,874,803,314,976,274,502,802,608,938,692,77,456,496,539,323,716,547,302,84,37,369,355,975,440,930,514,340,491,724,464,324,43,738,466,422,596,291,337,662,920,916,241,84,976,591,192,39,831,232,966,710,358,12,690,877,943,889,41,50,716,187,884,637,325,863,597,266,768,384,268,389,209,799,327,709,863,767,195,85,101,790,225,894,794,334,19,846,850,90,240,413,88,708,635,830,620,338,552,799,521,901,137,42,521,354,32,174,786,129,121,526,446,565,769,843,39,273,885,60,332,999,266,265,270,462,87,618,304,771,708,71,504,58,33,214,927,119,932,616,139,938,575,501,660,438,298,791,954,551,480,287,973,488,394,727,82,87,161,919,390,491,819,959,384,215,164,712,733,960,419,78,890,998,61,190,430,577,771,516,700,496,500,123,856,584,546,580,760,182,381,265,219,953,470,752,112,807,445,449,292,298,487,443,579,966,479,78,744,637,613,293,541,968,450,756,934,963,155,371,320,480,951,530,18,390,5,360,535,901,256,743,951,893,153,705,438,684,957,97,672,699,594,740,629,377,928,16,518,751,743,616,864,4,815,554,566,27,828,282,480,846,933,602,394,484,34,696,872,26,804,96,721,202,762,346,398,189,576,359,812,725,948,423,317,843,298,724,168,77,921,201,145,186,157,364,207,83,156,340,851,517,474,367,362,807,870,954,833,454,757,690,425,204,677,391,671,912,321,545,375,674,719,309,917,340,410,201,613,874,552,437,282,764,572,586,771,641,411,383,895", + "187,269,294,559,806,154,110,692,307,392,285,119,981,297,94,715,225,650,616,112,946,334,228,557,814,227,687,32,338,749,741,381,329,111,613,319,136,188,41,590,293,397,934,412,472,664,841,858,421,884,298,880,792,495,255,353,616,654,890,652,269,604,708,78,35,669,443,876,375,477,53,836,374,643,531,156,582,946,547,493,530,194,484,706,930,681,910,622,96,515,376,653,557,242,740,238,876,141,627,447,306,227,947,615,381,211,171,846,243,534,999,291,77,19,705,605,786,1,735,566,903,138,709,281,346,847,501,623,168,100,224,356,979,329,663,850,131,60,768,878,937,560,866,210,8,224,847,462,733,523,978,254,456,439,781,760,16,922,526,532,526,763,494,488,276,670,948,278,480,893,201,813,529,227,383,845,202,427,93,857,514,292,306,566,859,972,479,549,916,741,284,456,22,808,457,211,797,370,560,920,577,27,927,991,47,446,907,523,336,319,447,134,480,646,737,531,794,254,525,234,357,138,941,779,932,679,402,232,666,871,991,94,30,957,786,425,101,988,634,73,996,336,477,150,877,947,381,703,568,456,92,323,861,382,735,761,355,977,383,45,860,33,238,284,899,457,633,472,518,605,44,743,932,835,292,669,207,107,816,770,406,0,98,44,299,473,19,134,524,823,192,565,195,659,885,772,682,85,565,141,944,725,973,216,570,753,922,487,479,146,241,785,522,130,773,631,484,437,273,270,414,32,37,293,348,724,273,224,136,479,575,504,153,863,516,661,295,127,696,219,98,254,76,639,873,574,164,312,694,829,721,606,395,767,215,398,402,683,590,517,836,842,738,719,348,1000,723,354,510,932,14,9,261,926,329,6,679,296,217,282,960,616,80,261,389,972,144,452,17,265,151,593,8,52,732,681,28,761,866,722,756,873,28,747,593,966,300,133,942,221,990,672,239,937,521,59,703,223,352,770,273,435,667,275,333,570,480,877,582,620,420,945,55,426,869,473,454,161,867,472,461,647,338,969,299,440,19,896,836,650,784,770,540,907,510,896,618,986,541,294,209,430,285,840,547,201,156,256,992,566,616,911,469,445,256,16,760,865,672,305,700,876,633,215,512,104,247,450,696,21,156,394,641,681,228,740,52,855,315,620,783,307,189,484,939,541,880,647,903,243,933,729,544,286,173,787,356,62,825,250,163,894,54,939,129,895,733,400,472,672,568,304,978,989,630,647,253,174,660,870,743,61,232,81,241,791,278,263,210,908,919,1000,483,921,747,933,185,918,131,185,840,343,467,714,757,59,297,160,35,288,74,183,299,12,316,56,542,22,925,853,672,907,244,434,835,75,512,349,882,57,291,907,694,463,352,5,974,132,185,762,335,575,551,384,218,873,871,552,705,790,132,117,399,269,486,691,598,95,280,790,567,936,968,81,609,155,792,736,89,712,744,546,980,354,631,856,149,760,978,177,228,522,720,2,487,24,69,529,70,683,498,359,824,588,656,324,24,971,336,781,673,917,376,348,169,956,631,401,971,839,468,972,613,150,909,591,759,676,53,346,134,398,221,901,549,216,873,841,420,834,643,514,109,162,796,966,738,845,811,564,222,82,365,671,496,891,28,477,840,19,635,584,915,717,638,148,266,736,792,80,861,410,785,281,541,944,714,176,658,165,587,181,215,935,649,49,712,742,119,426,474,578,113,819,50,522,687,612,159,30,812,876,23,286,442,749,215,536,770,799,262,881,253,373,47,562,790,237,572,432,2,749,481,718,148,612,414,72,839,940,64,806,110,730,813,707,957,660,556,847,47,185,329,627,144,241,191,575,621,789,365,809,762,385,299,362,74,130,309,975,71,559,173,535,65,465,696,594,377,870,865,944,685,166,433,665,156,123,774,494,499,813,187,277,257,815,912,623,663,784,993,666,374,449,999,837,191,909,309,110,175,615,307,758,112,273,328,655,509,408,315,821,246,778,794,815,607,29,383,47,757,123,368,175,718,771,683,125,686,183,912,821,817,565,235,294,248,374,232,862,174,371,589,430,720,999,659,911,778,99,505,486,146,161,153,215,833,309,6,803,350,499,930,869,226,985,735,865,298,771,929,90,873,744,728,590,818,616,935,356,262,20,771,444,961,387,705,941,708,348,857,92,932,86,985,295,559,389,127,303,509,374,593,58,978,687,372,78,163,915,680,401,142,236,597,56,526,585,56,479,298,91,472,452,647,607,528,167,644,862,859,847,419,952,661,378,475,469,444,818,183,448,345,747,595,111,273,507,211,910", + "813,463,133,822,906,10,306,404,586,778,579,848,790,949,923,941,557,685,786,807,890,962,538,27,686,893,969,419,468,344,860,938,835,989,837,736,122,850,359,358,798,376,904,728,52,862,322,861,240,883,491,367,76,987,494,413,126,683,44,25,166,658,642,563,539,294,606,745,689,138,276,803,503,84,107,882,929,487,293,510,487,511,240,466,19,833,322,683,322,41,813,615,894,613,307,322,439,279,923,281,424,784,651,235,10,47,597,507,676,821,643,468,34,930,586,989,603,275,586,296,60,265,981,991,907,668,152,666,770,939,315,256,723,981,928,600,987,740,879,734,214,212,531,313,100,262,855,460,933,367,953,200,179,949,894,609,867,910,704,67,167,398,922,689,209,573,197,912,701,535,589,454,309,40,472,338,234,298,75,816,879,15,555,77,915,708,617,661,753,969,63,213,762,376,206,92,44,755,36,655,836,65,233,368,22,494,184,421,404,575,570,950,571,760,299,230,619,283,421,203,896,559,12,388,136,871,611,648,986,523,22,13,794,208,53,994,13,970,298,892,100,85,233,851,212,609,568,811,128,849,40,558,320,567,32,418,118,924,893,947,643,463,456,70,455,279,242,895,307,450,7,391,157,767,90,30,123,822,531,810,283,98,0,529,432,506,274,139,547,795,952,26,414,287,521,260,111,832,803,405,215,757,457,29,293,231,504,135,24,781,12,84,401,262,487,512,811,231,502,940,446,551,827,832,593,297,733,946,23,865,917,64,987,714,237,549,780,386,77,814,681,570,558,859,578,546,788,719,181,466,190,891,938,213,667,409,310,294,928,291,157,610,485,386,453,827,918,365,341,25,413,348,7,363,437,565,458,670,186,63,454,406,393,105,880,199,761,654,520,894,731,104,346,714,68,240,888,560,412,420,992,723,764,565,510,993,6,304,422,550,210,447,814,779,532,650,799,113,435,517,492,92,371,72,478,338,370,31,995,879,973,611,496,480,384,730,147,73,987,492,298,255,269,486,380,142,16,113,940,51,843,674,713,979,584,495,890,807,223,622,998,845,603,512,251,554,975,152,270,310,248,313,51,745,363,107,265,759,423,511,210,411,661,848,780,769,550,299,678,919,136,590,722,208,734,619,279,948,419,678,547,836,980,743,252,8,889,328,455,954,341,735,854,176,937,347,433,221,545,496,303,335,456,681,745,831,828,252,965,954,613,756,771,126,626,831,145,30,950,952,275,325,411,672,571,284,6,399,936,706,67,943,932,74,829,748,111,481,815,157,569,20,538,381,614,446,39,907,646,869,220,452,130,332,490,914,861,773,666,142,459,158,139,327,27,386,718,366,995,341,978,905,588,960,682,884,626,487,795,843,829,189,180,583,993,699,349,471,864,100,376,332,349,72,944,45,771,123,513,805,279,814,788,375,324,34,420,865,523,186,408,753,908,848,267,751,343,117,55,243,900,451,809,872,270,732,311,383,432,526,113,884,385,270,683,879,436,180,707,781,905,51,291,494,158,713,631,213,442,152,792,701,585,943,665,821,552,353,206,768,868,21,797,954,761,958,881,307,154,34,168,361,885,976,276,857,416,764,257,613,290,550,68,902,107,58,211,844,604,247,387,751,936,12,826,37,367,548,561,358,522,316,338,706,960,341,903,721,736,633,272,126,202,109,791,770,174,28,663,490,264,778,914,361,567,515,130,887,525,703,372,86,379,739,503,342,455,981,276,459,100,43,90,820,109,465,162,894,406,412,275,435,508,949,577,728,728,824,334,928,772,987,826,55,277,243,316,439,841,912,235,636,271,19,406,764,657,839,274,78,974,715,135,565,349,234,571,390,697,197,822,532,891,671,504,610,283,437,626,616,718,464,929,546,101,736,299,227,369,258,872,460,967,153,870,155,908,302,230,450,907,971,166,233,829,133,943,620,406,305,170,636,417,831,794,483,783,526,969,550,693,907,703,871,316,560,862,998,935,259,591,465,865,7,497,178,332,276,703,963,404,608,818,828,710,377,51,564,468,71,81,147,97,979,518,18,791,595,193,848,89,601,100,76,993,700,790,67,426,811,279,343,939,71,58,947,847,875,663,810,788,307,6,395,345,340,490,976,545,762,556,240,218,464,397,833,686,902,998,597,633,47,904,793,783,999,944,328,460,813,486,440,514,80,468,34,35,730,504,452,686,60,251,99,581,414,625,265,234,604,956,383,83,671,179,149,190,879,192,305,994,773,827,348,697,327,899,582,734,711,849,589,603,634,216,134,200,314,481,605", + "668,378,874,836,889,577,25,680,80,750,696,553,196,388,798,429,522,460,207,637,448,968,491,583,329,881,355,639,173,544,170,460,167,314,713,337,261,770,957,713,889,702,754,608,707,470,986,671,713,297,507,920,900,650,853,252,724,812,48,739,4,575,611,151,288,561,676,301,343,528,6,961,358,366,709,118,38,71,544,169,205,188,869,373,980,868,957,274,956,261,824,638,558,63,544,221,320,455,914,792,402,2,190,562,320,608,386,271,10,648,622,429,801,109,64,661,896,752,698,957,626,486,794,146,120,503,911,18,571,506,215,351,409,266,410,252,440,529,85,722,159,311,197,445,912,570,386,214,100,867,240,305,153,208,29,818,15,687,144,716,376,585,372,422,957,110,446,644,49,14,273,52,188,969,518,39,75,627,85,345,659,459,278,528,176,51,309,487,576,876,466,80,414,744,692,793,143,343,869,300,300,301,634,651,890,740,528,950,311,37,148,920,894,887,667,257,395,429,302,610,576,315,744,575,590,73,299,817,592,924,886,547,861,744,868,544,848,226,219,992,813,938,505,650,182,54,640,956,971,766,228,248,281,429,393,396,108,118,279,823,292,765,874,856,950,811,251,843,624,177,712,965,247,994,76,511,755,262,948,251,870,44,529,0,337,752,259,452,332,840,825,467,700,795,123,411,996,818,99,839,482,560,170,329,359,510,602,861,388,359,771,297,131,804,981,859,581,124,789,368,145,561,178,192,844,518,868,446,62,410,409,410,682,381,319,339,943,636,636,424,156,234,152,956,1000,162,988,433,475,779,544,666,496,469,616,488,376,930,259,970,148,560,924,643,567,571,482,77,37,372,147,447,202,68,472,208,483,234,829,751,703,588,550,110,773,558,991,487,862,889,637,10,807,485,545,537,666,413,970,701,116,948,223,320,573,37,381,630,729,987,494,858,46,537,282,899,412,805,389,198,17,47,408,705,433,432,216,116,309,946,152,807,793,454,200,652,720,778,715,723,276,13,76,37,180,26,911,70,499,591,516,464,388,441,290,978,533,870,7,656,9,314,424,752,339,33,371,754,700,980,377,825,174,845,509,713,346,948,413,341,762,985,18,74,400,447,159,575,71,977,826,970,157,564,584,318,960,567,714,575,460,446,454,487,954,813,487,905,85,27,355,714,642,720,124,712,449,985,483,74,746,673,737,539,550,558,471,181,599,716,113,719,741,111,819,171,769,271,27,390,73,476,911,912,72,65,796,903,788,171,52,198,332,359,524,178,13,53,329,711,927,629,70,714,487,202,652,408,455,352,452,641,746,863,658,943,2,255,211,459,138,384,188,474,887,585,415,34,823,602,996,261,79,784,278,964,741,880,519,309,133,687,502,686,213,717,185,96,809,134,850,834,542,340,132,998,868,18,153,625,808,385,473,247,538,998,153,360,762,384,826,61,311,827,352,781,742,292,182,761,873,379,832,829,854,202,67,959,758,70,780,21,202,98,349,265,219,44,742,927,605,230,382,945,866,172,367,887,40,484,55,769,48,469,935,782,12,494,448,45,134,535,915,531,649,352,643,941,99,789,52,959,928,7,220,662,820,118,961,258,208,107,992,113,22,636,500,115,866,203,464,40,330,697,733,530,701,348,920,849,793,328,544,26,203,946,981,177,9,50,454,529,814,353,788,675,832,434,174,411,642,883,978,74,372,14,970,357,854,662,241,245,730,586,22,63,836,769,144,368,392,384,745,490,438,997,844,947,861,673,152,694,898,285,884,937,462,297,393,372,673,468,587,186,489,972,498,143,429,630,688,55,851,126,314,825,782,619,349,102,246,259,686,756,188,708,509,166,169,90,610,426,815,89,336,386,525,677,771,901,251,818,451,650,774,652,342,673,715,408,428,674,32,164,994,807,28,69,328,135,186,679,699,788,820,86,903,201,840,95,280,391,983,592,162,657,461,645,297,565,352,395,884,188,780,935,160,694,368,51,984,1,282,160,942,470,747,364,283,156,562,222,777,99,763,186,658,648,372,292,307,6,679,95,915,446,270,247,722,543,403,599,384,950,625,355,175,720,821,296,248,204,29,594,224,786,150,505,8,594,73,96,250,986,873,2,653,224,727,437,746,22,878,780,428,34,744,823,451,426,794,859,369,658,878,187,534,629,104,17,779,804,525,921,438,128,368,113,129,370,654,238,275,132,192,2,112,100,716,801,638,891,663,226,288,227,286,571,614,778,320,946,433,816,869,247,709,532,366,238,821,7,363,819,218,533,565,517,278,976", + "373,64,638,74,931,874,965,681,625,872,111,387,925,28,491,410,644,982,162,913,102,161,528,843,611,246,141,417,237,452,126,728,227,447,981,87,203,777,177,898,703,256,499,484,244,578,807,474,818,984,337,758,634,320,283,730,905,510,988,890,108,739,600,724,396,267,252,29,234,863,400,424,446,995,570,309,573,228,254,890,785,300,82,986,433,809,29,622,334,616,378,591,603,313,312,105,489,282,974,39,376,640,797,482,638,995,512,719,404,410,249,534,155,917,302,537,153,895,505,34,803,381,123,488,577,992,707,393,204,699,944,921,598,596,523,385,191,147,563,678,83,96,653,985,547,779,300,418,737,747,178,862,810,973,502,415,514,629,173,766,971,177,240,173,416,44,76,301,431,622,592,132,90,140,304,846,771,598,597,370,357,938,585,888,5,95,406,652,365,647,171,232,863,473,126,657,302,557,199,680,195,423,851,860,258,233,166,554,56,300,165,321,293,265,116,944,677,873,520,896,81,894,853,878,518,769,452,849,780,603,268,155,176,443,390,831,318,856,864,371,980,125,816,832,478,530,921,429,513,957,618,522,38,718,512,691,290,171,378,262,484,267,722,143,584,651,218,727,971,184,380,578,626,676,737,325,357,399,127,109,599,299,432,337,0,902,311,12,856,483,592,539,782,941,725,141,512,329,101,222,391,342,353,453,82,824,242,948,425,98,791,73,425,350,435,683,715,593,373,2,824,99,503,604,627,244,982,964,298,967,170,656,531,55,732,986,898,857,533,525,657,649,138,19,953,759,445,487,633,47,782,931,431,420,474,103,537,867,823,33,460,422,512,629,365,549,232,122,31,199,326,407,200,892,1,136,488,380,693,717,304,427,465,341,260,502,779,57,316,845,606,150,448,68,136,108,77,446,673,139,177,288,892,606,269,630,374,230,306,558,177,335,329,498,21,644,564,632,17,236,489,421,280,144,561,740,101,279,364,53,84,807,348,541,733,938,478,736,109,536,837,215,771,792,365,856,302,747,911,306,344,890,826,765,812,452,474,411,366,380,498,411,140,782,667,104,385,385,98,594,923,502,397,122,489,70,993,922,930,638,463,532,801,291,105,510,858,330,173,823,936,213,528,839,888,417,222,319,367,805,164,90,963,193,517,397,262,499,975,15,267,595,997,665,406,723,911,363,848,540,746,227,957,707,25,252,583,927,66,319,814,667,391,303,195,418,737,124,147,334,347,748,942,231,764,312,517,123,925,339,373,830,386,119,1000,356,62,261,431,794,650,17,778,134,394,220,686,926,683,44,285,243,543,843,55,654,313,804,68,172,414,753,342,384,818,891,981,340,989,809,17,886,716,458,126,33,203,634,62,93,542,50,305,801,558,57,312,354,419,11,307,725,238,81,75,328,248,357,875,638,549,144,816,883,9,928,137,939,719,951,446,26,226,241,341,226,205,911,124,387,680,510,353,692,595,756,996,39,960,937,137,496,716,89,314,645,589,413,261,764,47,986,592,852,143,48,924,342,336,973,643,660,96,554,550,495,722,858,137,286,242,692,574,964,451,308,587,491,481,158,275,346,173,328,328,79,449,647,681,163,903,158,659,740,706,80,876,385,370,635,114,414,780,301,153,690,249,642,758,975,381,192,613,546,435,573,770,954,493,35,182,431,838,840,561,428,56,715,613,491,636,273,240,54,266,607,258,589,974,287,158,451,762,408,537,452,510,770,750,161,605,570,675,140,8,499,507,595,641,825,92,247,612,583,122,435,452,393,214,743,585,82,462,407,53,990,718,782,719,847,52,265,3,767,802,304,904,161,41,147,693,366,58,706,634,654,578,790,136,954,759,199,34,300,671,850,747,462,133,860,487,938,464,953,244,932,874,400,784,498,111,774,778,206,882,637,502,510,427,374,546,661,714,287,392,766,90,82,650,884,323,367,370,558,604,645,478,333,820,164,169,869,307,655,957,804,896,809,450,845,562,503,508,1000,618,68,880,626,192,195,598,829,126,30,375,274,575,243,54,675,369,76,239,872,806,396,183,731,598,870,582,518,288,993,492,891,944,356,473,70,907,108,667,477,964,507,473,178,220,473,877,825,184,866,483,393,404,518,561,794,256,164,381,577,579,86,590,135,680,539,840,349,891,734,898,267,641,172,395,698,776,192,59,683,378,914,297,315,3,442,387,124,648,987,749,739,843,253,875,108,40,170,997,912,857,875,432,843,459,550,550,335,838,221,414,759,911,723,287,913,629,230,479,142,538,955,681,346,628,72", + "522,452,314,250,706,447,769,544,815,407,693,339,714,235,571,653,985,231,227,600,545,308,772,142,663,236,434,809,125,75,792,373,396,361,4,656,267,827,485,103,96,13,527,824,869,452,877,845,649,298,626,311,67,581,403,111,951,443,19,939,87,382,136,143,707,13,993,207,631,195,704,588,939,646,814,344,16,885,327,829,725,121,534,559,740,563,915,850,469,273,998,408,438,739,844,31,120,704,286,674,348,13,416,212,735,198,737,360,628,662,4,548,905,198,990,347,850,547,535,890,811,485,781,931,436,682,567,100,707,426,269,965,512,657,686,865,637,122,314,754,87,359,852,115,498,348,342,993,968,79,691,628,921,574,128,863,450,428,96,209,949,21,528,860,722,806,264,374,76,535,569,544,208,592,578,300,831,805,738,761,770,89,452,849,177,516,643,734,729,417,203,544,301,888,773,288,479,599,79,853,169,70,438,810,885,37,224,469,194,498,301,293,353,611,219,267,975,812,187,276,458,759,404,431,251,563,990,796,186,847,817,614,607,663,223,961,602,295,372,217,854,582,133,179,537,596,96,933,191,684,747,997,448,418,300,287,864,341,213,335,244,160,115,323,868,809,29,51,311,914,965,742,364,868,555,94,28,451,569,575,348,473,506,752,902,0,704,88,35,138,299,470,245,328,401,303,988,823,944,855,757,273,394,777,522,985,584,14,556,42,732,340,627,258,264,274,724,405,817,175,170,546,957,881,345,573,576,199,605,514,766,69,538,297,812,431,72,231,561,659,939,986,35,510,502,629,82,624,649,817,404,534,497,698,770,34,439,224,212,682,583,17,467,648,27,543,449,483,157,462,645,616,815,214,609,403,894,836,452,11,694,820,703,715,748,224,868,882,294,401,283,17,86,288,87,835,171,430,606,400,200,933,206,123,398,478,281,699,427,409,168,269,961,876,521,194,414,405,218,178,783,707,546,102,619,989,3,481,858,902,446,909,612,527,413,18,357,806,646,105,358,501,204,840,300,33,904,743,67,367,989,911,659,894,490,161,33,734,383,160,804,78,720,994,319,194,817,179,465,410,393,473,665,382,126,86,290,417,218,131,48,290,32,359,592,717,565,728,324,470,254,700,139,861,697,747,205,956,367,875,733,648,879,876,188,535,152,439,117,895,781,799,855,444,71,78,637,590,584,232,725,965,119,150,186,964,625,671,175,756,341,492,113,292,365,546,841,137,342,273,994,554,378,143,881,237,630,32,801,840,528,817,309,833,22,71,650,654,547,728,198,623,175,771,255,233,900,998,996,212,808,458,708,943,405,452,126,704,412,650,906,337,302,460,146,554,986,938,800,751,763,78,413,563,49,670,284,782,119,15,226,148,63,358,13,858,369,773,812,950,133,653,342,936,921,565,648,891,117,128,188,637,272,942,546,313,757,656,742,393,26,900,321,431,604,259,179,464,859,124,391,50,299,687,646,38,378,763,190,824,589,209,560,696,906,566,148,532,50,201,665,869,648,18,754,462,221,852,545,921,215,763,896,521,90,688,84,674,245,951,679,621,749,850,956,101,387,713,786,176,601,893,704,525,120,418,447,384,221,971,890,190,459,570,24,263,62,236,669,841,576,172,671,810,739,273,473,758,681,540,543,70,387,321,281,976,335,639,13,458,616,565,634,575,896,461,654,262,992,578,851,43,778,356,220,532,969,217,722,863,519,450,880,257,177,375,512,450,518,489,339,382,761,268,457,937,196,580,213,965,568,655,485,246,518,910,538,313,207,499,787,265,70,884,569,527,988,97,947,795,373,509,892,199,47,369,404,852,374,587,958,683,718,637,492,112,37,530,350,29,862,115,735,955,905,862,749,372,161,871,612,955,520,440,38,345,364,364,389,541,366,769,631,921,244,959,698,829,595,774,888,489,906,304,312,412,499,664,893,147,934,170,285,381,254,829,461,239,63,77,687,669,941,492,218,575,325,461,166,248,197,647,872,207,777,299,713,222,988,276,838,719,883,731,541,655,315,121,684,329,706,844,1,304,135,972,201,546,536,153,645,711,493,964,13,776,586,492,150,343,479,626,995,609,299,25,742,6,651,684,268,316,430,434,889,808,869,126,689,137,18,830,974,495,829,230,726,993,527,6,710,507,270,58,511,657,656,218,535,938,776,300,56,192,423,946,695,499,347,71,534,394,832,252,911,713,307,405,427,828,46,207,712,846,77,156,372,631,689,150,820,867,761,422,544,769,884,450,80,240,904,589,154,380,739,614,379,921,654,786", + "411,672,711,739,303,240,226,553,379,562,55,136,441,526,786,937,171,600,445,820,569,532,39,817,5,167,198,203,557,394,383,547,419,126,987,262,445,609,390,844,779,788,603,606,327,784,398,305,800,131,475,291,180,218,568,742,416,841,951,66,992,359,600,549,7,414,244,824,196,913,433,764,531,579,10,506,108,94,995,635,586,188,297,629,666,23,350,203,906,374,74,463,216,526,259,846,708,865,87,159,866,468,58,556,710,270,612,70,124,971,206,750,767,465,196,94,314,263,333,259,841,107,704,316,806,609,286,459,396,304,818,100,238,214,443,660,292,362,272,225,368,720,285,124,129,662,248,961,795,534,199,946,408,326,932,73,407,901,789,711,821,606,768,132,170,27,682,821,622,638,598,551,846,374,5,611,297,635,89,543,45,133,129,126,766,389,646,218,133,336,804,455,924,75,991,263,43,798,666,328,75,173,212,243,339,401,940,155,615,21,389,84,90,843,747,573,319,507,360,829,199,698,831,181,426,586,168,229,417,274,674,150,29,759,679,681,710,600,647,496,233,561,140,187,595,407,127,818,451,304,188,604,825,161,736,240,990,448,27,198,628,87,922,525,835,913,648,585,749,260,824,951,920,304,55,138,630,818,709,6,147,19,274,259,311,704,0,197,168,700,374,652,738,483,689,581,873,737,928,26,604,120,128,326,569,41,356,858,476,813,651,145,210,653,517,570,927,295,437,422,492,750,258,178,479,237,401,322,8,286,708,212,224,580,420,663,267,797,819,538,968,61,793,295,993,750,502,115,983,978,771,341,309,506,238,324,114,774,260,495,989,909,919,768,845,285,507,240,919,480,534,563,2,216,58,925,784,441,273,214,684,259,222,960,946,474,874,860,719,644,34,700,246,965,688,34,338,519,773,638,671,407,93,699,521,662,760,298,898,499,97,306,604,652,835,351,341,66,306,672,444,601,219,507,638,698,143,339,278,601,346,812,246,960,996,470,656,712,949,669,58,711,25,841,702,656,852,610,741,179,193,442,827,679,854,839,612,38,340,13,822,851,184,107,563,638,692,136,847,164,918,972,347,955,542,16,625,811,6,231,806,58,780,326,60,934,974,365,288,452,868,265,801,469,660,398,823,664,776,893,413,232,84,119,308,145,548,501,985,627,638,432,556,957,87,140,461,383,777,612,470,54,338,318,818,987,324,944,957,794,407,991,53,6,778,618,493,642,50,449,867,107,308,990,392,554,863,866,855,536,839,511,886,52,523,564,845,806,581,765,344,804,625,209,485,72,797,450,842,407,28,709,765,455,37,785,754,9,340,254,890,412,617,442,483,892,531,587,854,922,883,184,615,454,397,701,893,443,9,382,802,631,70,33,939,268,738,185,146,763,724,251,136,64,576,430,759,24,727,342,692,949,190,346,303,500,757,246,583,360,198,368,803,882,585,501,958,805,495,42,711,565,127,26,86,565,84,103,938,315,578,554,612,320,403,316,744,180,221,63,509,60,689,658,272,575,111,452,302,934,760,114,667,877,285,290,952,51,212,654,56,410,50,454,219,931,880,143,391,915,894,936,971,864,847,266,488,658,674,457,281,510,936,185,922,260,733,426,314,894,285,537,167,521,90,844,656,497,140,649,28,729,264,795,582,497,424,65,817,404,690,601,867,226,82,501,108,432,715,897,569,561,268,173,552,849,436,104,785,56,65,503,192,162,817,917,35,915,135,671,474,388,776,88,185,231,585,686,777,433,184,654,112,174,277,611,479,476,963,583,959,797,540,358,166,982,580,510,627,900,822,715,498,400,305,852,449,683,889,114,240,598,835,494,143,451,234,951,258,97,613,324,602,770,958,725,505,263,626,534,771,542,721,701,819,409,367,453,219,311,791,464,437,930,58,797,344,292,206,947,904,902,428,132,303,306,292,73,283,216,583,693,358,462,546,355,889,273,494,866,342,410,606,325,870,182,215,664,73,995,635,669,335,908,147,265,869,395,388,260,23,923,97,298,809,708,368,489,510,912,953,999,791,455,120,287,590,696,263,923,770,399,468,607,896,826,322,601,651,551,690,647,985,934,606,879,909,387,766,638,279,12,687,573,338,916,28,973,201,381,159,53,209,968,561,227,196,141,347,735,93,184,73,743,681,764,119,962,185,676,174,810,443,362,63,835,640,164,239,133,833,733,423,510,295,804,136,85,498,726,776,638,228,409,500,212,451,512,33,116,615,673,723,889,418,131,526,735,671,334,931,103,200,569,877,787,736,542,973,275", + "772,474,534,982,468,332,909,215,492,867,214,543,208,902,498,428,649,617,971,998,463,659,853,457,57,68,301,647,769,977,897,395,999,660,645,376,708,240,134,66,575,386,775,292,130,89,542,773,443,557,809,63,569,586,162,833,990,381,209,742,781,582,408,67,775,419,994,803,658,91,888,678,77,815,449,726,476,150,759,765,416,310,443,360,104,206,413,94,465,916,956,539,512,341,316,294,328,763,31,460,827,66,111,494,300,545,508,264,338,687,269,601,881,612,44,74,10,37,476,311,280,324,869,353,765,349,531,198,146,167,384,769,926,411,23,349,946,192,895,764,118,846,353,606,484,238,301,932,76,172,534,862,554,670,717,799,136,541,47,500,602,104,970,468,249,878,339,147,15,909,570,164,352,28,363,639,328,699,450,916,100,965,442,225,404,998,287,759,773,152,815,625,161,785,231,855,953,792,45,940,108,416,988,43,556,392,150,557,84,688,73,394,54,405,963,767,517,136,928,18,773,267,654,443,559,934,489,247,287,883,89,378,280,541,529,473,510,620,226,244,268,939,298,810,240,376,599,288,562,386,171,35,872,191,770,270,331,187,296,65,689,734,372,367,883,221,626,552,993,787,804,523,294,800,397,710,134,974,377,188,541,134,139,452,12,88,197,0,813,895,768,765,691,534,406,967,270,877,556,507,982,855,342,921,405,462,595,746,767,903,553,306,499,574,251,808,319,568,438,380,163,8,931,770,688,787,341,975,427,378,83,922,634,412,171,991,477,188,722,164,200,382,264,723,574,948,892,949,778,937,269,525,442,579,849,399,74,111,616,13,29,885,510,516,406,798,989,828,797,887,830,203,460,657,687,458,266,389,627,624,650,719,71,476,694,726,249,319,1,216,172,637,169,14,658,629,347,931,795,28,210,242,240,60,548,995,87,650,70,48,517,309,978,158,277,504,6,100,945,376,166,658,642,604,808,291,810,166,108,806,690,523,695,272,519,977,996,341,394,879,809,274,786,882,672,347,89,776,893,184,126,784,350,242,523,584,28,965,11,404,455,623,771,939,569,772,70,342,592,903,92,353,291,824,90,13,889,920,73,102,53,879,543,968,951,556,936,82,702,523,117,997,632,444,668,706,726,882,293,246,924,387,137,416,191,749,361,49,667,796,134,68,533,503,235,642,40,812,424,361,420,990,698,620,404,481,10,206,268,458,791,44,435,373,79,610,770,480,628,214,488,123,599,26,409,162,802,966,892,527,903,428,580,667,398,661,957,780,589,798,60,824,371,506,368,321,140,208,743,283,403,471,885,94,125,317,739,39,238,423,58,777,808,6,875,261,723,266,573,692,188,212,407,171,265,704,764,433,265,52,647,545,227,607,915,384,54,260,419,300,890,691,949,398,369,595,336,548,702,424,596,27,319,909,993,258,904,217,864,119,292,506,971,199,369,756,131,394,835,678,947,692,191,757,419,389,132,410,930,578,725,450,440,740,411,759,635,136,905,225,716,703,960,515,126,406,303,138,362,635,467,328,971,935,359,948,890,811,770,531,948,781,1000,443,993,281,508,641,893,56,945,918,723,871,464,822,355,532,202,300,953,230,722,690,429,983,688,294,375,57,457,38,239,411,195,955,599,147,98,445,274,385,264,495,703,967,155,125,965,467,967,402,904,288,958,919,927,80,829,224,732,932,219,930,756,816,585,185,461,463,467,705,79,706,735,314,456,905,573,388,173,934,596,508,85,866,844,897,328,949,206,24,465,101,911,584,470,712,430,488,536,995,45,968,436,494,30,881,511,360,115,950,11,123,309,558,186,520,30,264,843,385,979,874,543,252,832,484,732,51,855,621,630,844,108,739,99,923,969,292,41,714,461,833,863,652,650,263,754,838,360,482,587,732,387,610,577,334,711,375,202,280,31,807,489,166,442,646,170,598,505,155,468,430,700,926,160,505,176,830,942,990,911,734,390,331,618,203,208,104,643,479,179,313,447,498,148,606,139,743,534,67,669,41,165,373,606,237,370,542,63,336,738,768,771,134,36,585,196,45,310,325,725,954,736,269,436,229,961,243,394,64,998,808,442,176,671,691,225,772,385,260,578,187,887,668,423,175,110,697,88,909,463,412,235,866,53,300,182,742,790,677,563,99,192,610,660,35,980,105,155,490,582,168,557,635,535,993,443,156,864,521,26,825,245,330,351,930,584,149,766,517,981,250,437,314,815,29,562,21,125,521,276,678,644,999,186,767,557,831,63,982,285,873,70,805,532,953,779,350", + "943,660,132,336,620,512,535,835,101,951,439,111,772,135,357,188,495,994,409,126,137,323,280,577,794,566,843,945,291,705,27,134,552,930,121,186,866,25,890,519,309,467,644,902,569,205,815,808,993,58,641,503,240,964,261,657,43,891,925,720,186,538,658,646,365,551,971,717,402,466,288,457,789,262,389,659,882,795,749,52,405,574,414,822,56,748,249,344,85,994,578,13,79,236,197,146,559,358,426,3,774,942,315,162,192,390,257,696,831,425,749,40,545,427,639,702,60,979,876,301,382,655,240,28,71,432,833,103,26,907,19,969,81,444,500,339,936,294,71,940,975,852,31,748,282,452,304,707,648,603,408,787,876,116,683,964,52,24,908,996,398,552,79,496,81,790,155,820,11,430,57,507,586,259,102,712,466,109,670,64,500,946,935,522,551,821,61,315,28,982,57,549,129,98,430,530,819,661,865,282,914,793,406,808,309,928,574,219,747,539,801,197,435,499,365,114,847,89,703,477,114,237,392,949,454,188,156,52,979,92,183,316,739,175,571,378,440,697,810,909,235,885,662,411,944,279,656,495,352,514,5,787,63,484,788,818,713,81,241,819,687,549,414,647,194,904,12,124,743,440,628,210,763,756,628,705,977,597,345,15,683,524,547,332,856,35,168,813,0,222,755,956,879,777,58,817,325,835,926,864,521,677,565,456,680,245,775,96,820,218,224,772,101,59,726,448,592,754,538,923,518,37,257,231,45,402,364,318,952,616,479,790,442,97,832,680,753,152,448,342,995,659,278,790,978,321,978,259,332,972,441,213,638,299,68,836,722,673,412,20,446,667,555,585,256,144,498,308,647,432,696,344,604,867,58,851,925,845,101,342,439,831,358,17,577,75,207,612,838,534,935,405,873,935,37,31,159,100,184,290,994,563,756,54,514,91,225,812,614,323,266,697,100,472,776,472,992,979,359,362,285,508,20,656,111,52,749,306,490,768,358,136,587,292,616,846,141,311,506,213,149,627,281,95,321,616,445,551,962,959,268,716,727,522,531,38,134,325,159,798,315,854,438,157,229,94,663,913,898,304,271,839,185,272,725,557,10,124,542,575,413,274,566,341,476,803,317,201,326,671,956,563,647,59,960,608,947,924,890,372,799,256,8,346,513,197,743,280,846,592,942,150,75,491,63,51,139,833,89,22,754,832,560,910,19,525,566,758,81,655,359,772,985,947,389,539,595,105,816,998,565,49,74,29,621,859,240,823,558,600,235,515,188,868,843,366,596,466,920,765,612,878,606,316,182,801,508,671,249,558,266,972,114,989,209,869,48,147,558,221,415,236,418,579,47,595,537,977,345,229,290,597,772,111,383,200,355,30,592,339,559,748,243,573,645,739,813,993,174,665,511,589,197,574,247,580,579,404,492,941,297,282,157,508,574,652,524,822,7,356,210,151,144,452,916,488,224,470,938,625,853,387,618,154,799,929,318,643,858,877,991,585,601,141,352,656,297,869,750,361,119,339,847,243,780,288,948,927,930,702,613,524,349,71,591,997,115,850,826,604,224,555,426,429,16,900,785,249,704,312,19,331,355,139,222,359,884,136,702,125,56,205,359,794,719,366,501,797,766,866,860,178,412,685,13,142,827,597,98,640,8,469,569,628,682,424,275,462,63,743,345,165,172,754,247,261,966,886,545,723,834,321,921,230,38,8,82,361,642,624,783,93,512,268,253,544,664,329,169,90,476,817,983,471,593,320,680,232,210,263,948,634,508,620,204,360,113,739,327,9,221,8,102,826,924,112,760,765,284,257,916,563,198,732,783,780,990,645,245,653,566,103,349,616,202,906,239,323,577,661,510,382,503,488,45,440,341,778,707,860,820,313,308,701,249,224,872,967,288,597,195,565,77,850,984,943,512,107,668,327,536,930,887,195,4,244,677,7,342,300,286,246,239,909,311,328,150,262,399,762,915,549,37,448,86,25,476,798,272,891,792,524,199,24,443,78,956,232,678,946,652,568,219,215,522,256,266,786,777,687,22,872,103,685,968,644,597,992,205,182,797,707,828,830,678,92,767,720,418,352,773,943,147,868,852,157,293,122,749,337,903,983,242,203,410,971,107,833,398,942,362,984,789,553,672,375,983,376,728,217,88,431,168,499,277,157,500,3,363,345,408,963,862,557,229,354,361,793,810,398,783,709,732,996,103,467,870,455,889,193,661,43,323,718,268,25,348,789,975,912,89,601,501,603,311,139,232,280,23,933,948,765,807,806,162,464,38,732,591,858", + "183,455,564,284,208,112,597,276,148,404,339,352,568,336,129,822,555,915,769,760,29,208,336,406,946,194,918,716,231,329,497,300,202,782,584,64,339,740,966,272,23,299,335,47,302,896,244,902,594,991,18,296,612,841,888,67,260,575,815,541,279,691,962,323,410,784,843,782,883,792,698,166,9,91,218,620,972,386,905,195,471,803,152,171,472,299,118,946,659,124,981,335,607,851,81,329,729,499,927,350,930,786,490,163,129,817,718,13,803,384,620,341,502,530,354,974,80,417,723,927,621,589,893,671,100,665,805,620,364,213,179,71,686,931,707,631,106,586,298,511,165,198,52,152,178,839,199,427,657,235,767,471,512,150,26,552,820,398,195,584,729,904,292,387,731,387,733,241,786,487,680,326,997,656,648,2,266,153,520,392,311,395,157,101,337,238,685,649,948,574,367,10,246,660,368,793,713,775,293,346,821,5,516,239,412,637,257,543,897,119,165,221,667,766,815,115,117,841,977,45,242,151,650,939,699,616,160,602,786,932,166,818,745,424,694,563,282,739,368,802,328,573,26,936,910,481,280,572,251,936,160,61,317,237,621,752,234,87,807,682,752,781,898,136,889,158,59,239,108,926,984,294,439,700,196,324,592,221,873,993,694,823,795,840,483,138,700,895,222,0,864,522,319,559,518,92,683,267,205,311,610,593,259,837,679,874,828,972,58,932,261,779,297,18,586,449,404,296,5,185,622,787,789,871,943,37,403,537,893,659,931,767,129,43,132,182,166,594,626,881,311,426,703,955,453,946,365,454,1000,897,291,669,857,357,604,769,68,467,555,580,336,792,451,309,931,119,131,783,471,838,498,585,934,652,473,723,767,481,703,459,726,642,538,79,800,596,494,41,47,586,153,485,207,780,777,417,487,410,691,717,519,62,882,586,776,293,813,93,104,149,298,964,956,976,501,374,374,842,940,465,872,406,895,531,696,259,593,670,182,578,832,333,623,249,113,996,88,41,593,393,844,630,982,205,33,368,860,305,686,133,355,241,705,360,973,752,424,941,619,3,254,710,826,991,772,372,272,486,227,698,135,581,527,335,945,937,717,580,636,535,236,483,468,854,198,179,967,576,557,200,108,49,384,248,555,204,216,68,112,416,947,12,752,256,951,491,568,280,917,361,100,921,263,430,855,782,497,910,835,712,953,414,992,280,111,967,955,619,972,459,77,67,660,550,599,348,816,846,724,75,337,67,495,313,983,994,869,594,751,730,823,983,592,63,328,544,707,623,476,359,435,123,271,538,608,31,120,875,215,792,962,794,753,532,449,680,150,102,389,331,617,765,424,352,905,623,865,370,988,815,881,814,952,900,338,795,56,358,489,779,283,321,520,899,297,292,332,501,979,982,989,606,245,101,411,573,365,956,674,924,140,54,829,31,902,589,613,643,9,478,869,642,549,159,536,555,686,289,474,168,320,653,808,983,440,340,139,345,712,517,938,633,363,970,748,794,572,964,251,833,293,751,211,701,602,565,259,642,74,192,443,627,231,369,200,10,150,716,11,722,751,744,442,762,887,899,606,141,498,638,919,507,242,126,579,124,342,738,416,63,203,331,375,727,619,923,438,300,381,470,838,251,150,66,55,525,672,689,951,473,887,640,776,745,165,856,494,589,621,12,947,826,848,406,987,980,814,558,115,581,64,965,263,610,463,677,695,226,667,201,308,886,898,87,728,900,72,205,330,424,856,35,798,867,512,843,250,780,649,375,680,556,894,718,765,206,191,190,6,319,655,803,321,468,630,728,8,791,425,215,548,781,755,848,113,425,670,563,958,465,882,756,301,782,662,354,915,645,207,36,634,50,631,33,984,601,503,224,928,653,449,707,188,979,829,932,847,85,987,139,973,557,657,628,259,541,591,804,593,823,155,709,138,795,437,973,487,425,826,92,265,106,24,885,406,384,954,159,949,897,638,36,173,249,290,939,331,947,148,712,730,866,559,807,810,826,658,488,471,706,692,371,225,747,382,599,7,617,463,422,743,922,994,146,216,198,951,900,414,210,415,913,297,334,867,438,196,667,37,118,784,422,684,730,416,617,253,31,395,576,194,575,771,750,71,693,57,965,281,175,754,202,596,681,477,95,645,887,50,910,591,25,215,641,522,385,505,155,858,300,777,765,925,508,126,519,10,195,883,347,899,950,45,372,976,921,790,307,569,277,504,818,178,901,262,36,609,192,571,522,671,96,932,921,912,61,278,511,498,682,301,908,72,52,663,690,515,262,280,464", + "6,32,482,604,428,357,878,581,593,277,329,659,673,105,412,501,148,672,834,172,859,942,412,648,351,687,288,292,866,881,152,560,474,98,164,708,807,167,33,229,938,699,934,463,920,911,300,596,601,133,876,260,329,929,918,356,466,451,465,513,121,547,627,700,2,315,22,285,919,174,552,926,237,953,216,872,731,594,464,972,267,932,496,294,610,544,802,334,119,151,403,918,63,428,464,303,431,777,741,817,84,885,138,614,774,113,504,21,215,68,78,662,5,307,617,226,671,149,171,387,399,744,687,727,526,649,155,765,546,650,236,373,513,660,549,373,204,815,250,192,876,581,997,619,386,335,172,757,989,934,265,924,461,373,24,680,399,924,104,322,514,861,600,941,728,6,225,856,966,662,891,678,931,857,892,477,347,260,893,225,745,726,329,732,455,461,962,282,789,965,515,485,969,527,508,386,267,847,53,393,692,576,205,702,345,739,495,832,823,993,541,513,981,724,458,909,91,339,665,211,148,696,986,236,364,508,970,750,884,715,566,830,710,399,749,256,280,425,77,208,125,325,833,289,73,876,740,789,840,270,861,937,320,754,363,443,559,798,363,795,356,257,374,789,271,125,338,482,982,608,890,745,512,127,53,862,584,991,978,630,935,192,952,825,592,299,374,768,755,864,0,388,260,904,904,234,851,565,750,553,375,776,48,960,363,329,242,52,854,535,110,875,92,363,679,616,843,321,734,233,532,100,565,688,955,803,871,503,826,161,253,416,292,981,961,809,581,658,595,533,655,579,663,453,582,56,236,43,458,523,295,367,254,690,666,264,998,191,247,937,316,381,998,154,124,831,31,748,502,33,276,469,294,798,490,188,602,693,374,476,820,132,509,143,771,897,404,586,399,367,36,974,685,997,304,571,991,275,293,240,796,121,367,124,94,492,404,332,226,814,110,713,857,546,588,386,983,526,124,110,437,26,820,371,227,475,352,256,712,228,244,938,778,167,787,858,807,987,794,272,636,654,359,798,236,455,946,323,546,652,486,894,320,768,165,47,481,816,649,671,488,712,175,35,287,167,712,633,41,670,701,938,929,75,637,686,692,109,683,658,493,484,517,137,457,550,842,992,912,411,351,334,532,349,113,122,639,745,634,290,164,3,218,628,390,592,952,539,256,311,705,749,990,151,927,127,542,345,427,803,724,369,100,875,776,464,504,655,212,131,237,425,472,228,204,808,649,63,192,707,613,426,117,787,11,988,746,889,962,909,865,918,859,497,663,968,459,122,245,951,653,108,898,113,248,993,500,362,700,846,693,52,871,826,865,402,728,67,51,522,134,207,895,612,913,208,877,517,269,493,766,783,875,778,431,588,797,743,364,724,405,814,362,623,57,694,156,534,447,12,576,542,893,824,22,361,262,198,582,133,813,290,669,563,881,891,425,25,759,992,740,217,997,285,274,919,596,932,83,900,43,307,360,872,721,224,223,99,267,173,855,28,96,842,28,964,714,519,222,355,323,456,373,504,800,98,208,663,918,989,661,469,272,933,458,320,222,733,461,895,754,332,901,483,78,661,928,348,256,55,390,368,205,202,509,989,276,502,170,333,806,819,833,767,265,777,991,376,561,580,128,399,379,81,509,40,755,101,47,550,253,129,773,671,187,339,512,827,112,357,143,70,126,810,534,767,109,671,124,555,708,112,14,183,190,247,146,378,166,164,41,564,197,724,446,773,637,153,627,823,57,163,785,834,625,989,384,708,420,729,690,746,939,232,735,608,766,393,89,500,690,551,333,137,683,704,291,764,27,961,364,749,611,121,687,775,386,149,529,599,585,771,166,448,804,805,196,76,419,961,758,471,669,461,606,646,117,342,842,435,876,501,681,958,641,685,244,56,574,846,950,30,900,521,627,667,27,749,455,247,490,905,980,627,329,682,516,407,696,414,65,500,205,416,294,405,48,246,281,24,684,882,947,169,11,525,887,484,737,915,980,808,512,938,661,481,301,120,605,201,532,105,920,193,755,284,671,528,88,473,735,783,898,82,284,319,748,225,278,999,317,601,297,407,884,159,902,332,466,123,736,692,97,212,718,634,780,445,311,102,403,524,515,690,485,270,916,468,544,746,245,352,288,758,78,85,549,310,252,933,354,461,253,381,37,222,314,383,572,144,601,689,675,167,726,92,776,562,459,591,897,678,667,111,834,924,657,496,732,396,856,347,405,383,470,694,972,647,265,989,338,742,579,801,684,353,441,141,100,89,413,962,733,936,839,701,958,825,608,655", + "84,871,430,411,374,714,101,167,329,454,789,347,629,708,268,96,566,468,971,100,960,342,587,230,13,866,405,634,20,856,572,997,260,341,261,836,906,622,219,948,756,794,937,433,349,88,747,330,841,298,734,588,657,207,416,965,385,689,680,735,534,468,992,87,351,767,946,579,497,426,699,348,838,211,856,690,238,305,9,922,340,370,181,908,992,511,529,542,333,635,983,11,478,534,38,201,642,219,806,689,854,933,531,998,32,288,896,223,132,531,958,289,114,359,383,245,226,263,955,786,5,294,447,58,540,18,117,891,642,23,750,696,490,19,194,899,664,616,207,12,577,319,361,724,961,833,906,326,892,396,642,752,10,577,100,433,642,189,641,941,39,641,459,708,55,750,140,926,227,371,618,964,410,428,832,328,900,209,756,553,804,503,783,946,86,967,813,944,998,710,461,869,776,588,804,467,342,723,139,72,479,225,816,68,343,402,842,798,15,448,581,751,680,597,697,420,161,949,907,538,641,928,946,33,646,924,952,380,776,909,176,991,169,387,400,584,317,235,651,683,238,836,684,858,336,562,925,312,498,437,990,509,598,190,225,710,285,541,240,734,833,130,374,999,27,921,70,127,270,250,215,38,594,618,701,457,556,476,580,974,25,565,26,467,539,470,652,765,956,522,388,0,126,458,901,864,434,400,473,925,650,793,408,122,832,158,38,801,512,359,156,560,97,292,568,876,231,983,674,705,869,763,940,939,997,198,492,369,156,396,7,584,372,234,416,895,689,860,664,6,738,690,758,692,813,589,141,89,157,96,695,817,352,938,112,297,549,32,705,701,570,665,260,280,924,285,739,246,543,464,27,795,202,365,548,119,503,470,705,296,942,333,1,73,700,342,851,348,712,781,408,466,713,805,364,227,927,453,749,246,727,296,396,409,407,356,968,316,875,543,28,632,827,269,756,87,684,737,369,271,977,563,549,521,430,726,107,413,233,735,96,120,340,723,287,567,136,659,654,16,745,656,992,896,344,509,719,480,124,136,317,21,221,211,549,341,19,362,977,316,515,626,981,110,164,794,772,218,915,943,186,419,974,326,335,737,925,191,152,762,646,186,746,46,38,888,821,385,949,761,873,7,332,723,944,46,58,590,755,910,827,337,895,545,937,288,768,506,417,33,908,849,682,158,947,755,506,985,919,751,181,579,831,613,74,93,738,334,339,734,615,502,664,718,330,464,866,888,197,452,796,729,486,55,359,567,378,603,649,281,665,734,411,904,85,366,604,838,395,559,380,652,603,290,169,52,484,213,576,173,271,128,339,429,795,64,358,272,29,900,727,56,623,439,141,184,30,493,17,51,744,709,100,79,924,989,34,170,199,443,165,778,45,345,766,349,869,258,677,168,440,620,75,440,867,309,487,896,958,131,336,638,26,408,380,344,938,319,149,781,101,738,613,676,232,84,499,418,609,207,641,778,394,873,82,185,338,228,98,98,586,124,791,854,381,376,171,822,848,633,593,348,506,181,413,236,650,557,174,564,217,941,707,730,796,973,99,598,592,666,779,920,466,4,497,961,12,205,959,909,766,263,43,171,543,97,697,776,329,892,517,904,915,3,30,582,864,517,326,150,902,294,257,594,891,253,500,799,501,562,464,401,685,634,822,80,114,555,667,391,162,810,98,109,289,99,479,608,486,549,746,927,723,372,836,416,822,780,643,524,111,990,21,815,737,814,732,479,342,747,292,393,842,373,84,843,707,114,36,732,769,823,609,574,986,961,226,255,291,545,563,823,510,934,193,651,292,343,712,867,715,79,228,993,138,913,618,769,758,749,304,195,819,540,578,32,737,62,637,929,191,60,385,814,284,41,871,648,184,823,398,166,366,392,498,501,721,53,853,362,402,151,98,940,735,746,93,13,651,318,174,607,925,586,275,775,587,533,212,804,327,944,797,15,958,309,325,760,886,233,349,684,885,123,682,864,800,184,650,845,894,385,219,591,44,597,917,444,547,338,609,515,175,541,378,49,765,83,218,734,463,844,160,953,429,237,71,109,976,875,198,773,707,845,753,374,53,368,994,101,496,402,338,621,665,687,258,235,996,350,175,91,95,78,462,349,844,185,660,968,744,914,243,594,231,863,832,838,146,250,748,578,739,949,708,755,18,688,804,617,257,142,924,121,287,331,418,864,185,30,69,276,119,227,727,477,979,682,662,657,431,390,525,71,59,348,405,935,298,639,356,84,432,556,662,431,230,54,764,128,187,67,938,634,692,16,934,524,567,829", + "984,305,564,974,89,536,87,624,630,202,270,542,299,119,816,964,163,206,438,318,467,223,722,927,704,439,275,646,808,495,86,110,975,209,356,877,956,655,317,315,586,796,726,526,220,506,49,38,134,236,530,494,148,178,2,854,406,563,463,782,291,588,660,139,127,34,801,830,872,711,253,676,367,156,464,926,630,310,421,140,424,687,685,992,340,783,851,714,673,285,466,895,948,562,170,634,211,970,211,180,506,682,849,235,929,921,83,738,945,350,285,194,120,946,421,140,507,381,796,610,922,163,897,414,50,17,259,799,291,969,938,632,309,615,125,523,355,607,259,105,765,508,980,635,209,565,541,232,639,487,339,296,289,772,191,652,302,216,339,616,930,266,451,798,249,403,927,517,905,849,324,114,258,202,734,989,444,53,131,631,507,789,499,514,201,494,476,344,137,544,687,697,494,611,471,658,892,684,372,946,522,17,743,470,312,815,896,106,92,358,148,942,44,253,981,380,356,326,636,910,536,802,156,878,8,675,83,677,755,863,1,283,598,650,477,191,516,204,178,17,867,857,755,870,353,906,493,2,433,813,311,630,625,322,794,90,697,947,532,763,545,94,76,267,71,341,674,593,924,985,820,643,443,96,248,811,478,839,101,936,500,195,414,700,782,245,738,691,879,319,260,126,0,363,203,79,400,606,810,276,780,201,808,785,598,860,703,193,915,370,420,448,246,259,148,817,97,358,951,163,76,863,905,898,412,36,394,613,128,5,515,713,431,209,291,227,402,633,283,867,526,249,327,385,34,842,885,407,190,45,873,239,887,25,128,331,755,306,629,953,891,454,398,88,112,581,835,446,995,147,591,646,967,231,928,984,801,604,537,579,801,174,913,948,905,975,456,609,47,624,655,682,932,410,922,361,580,717,667,797,62,581,480,255,59,142,500,716,376,265,501,445,696,676,634,835,506,48,70,91,22,525,836,475,195,888,590,950,382,506,265,639,334,795,48,646,327,455,763,271,898,881,920,473,108,702,665,312,211,368,39,563,829,690,975,722,365,61,493,199,337,903,177,824,615,438,132,767,651,464,428,993,769,77,240,504,663,500,503,190,638,331,232,757,338,63,260,650,970,432,275,155,484,361,239,846,295,122,973,771,388,99,140,303,726,931,322,121,6,677,644,902,421,431,797,431,72,173,131,954,308,514,716,314,264,298,917,612,928,730,903,223,637,384,907,579,407,365,941,111,57,636,614,618,261,991,628,747,637,500,716,223,226,320,224,389,399,106,814,180,182,712,749,355,164,356,854,832,580,36,256,935,106,28,174,595,697,23,798,560,371,247,662,612,672,152,437,362,406,471,569,54,920,387,92,607,725,288,604,38,615,61,113,226,500,186,85,835,908,207,666,879,116,455,787,167,73,393,259,814,1,517,716,94,828,986,806,639,972,615,174,107,986,834,624,23,914,588,377,349,587,789,329,587,581,564,64,76,83,804,341,613,910,942,175,845,771,195,495,505,638,809,617,913,738,857,639,274,767,223,430,989,558,55,769,500,431,505,14,608,459,552,14,384,931,714,480,879,779,215,188,385,838,195,960,419,160,47,629,784,950,967,896,799,272,545,658,454,999,455,686,191,296,212,41,183,656,630,738,651,7,250,65,716,953,437,591,688,987,239,643,856,865,748,415,975,804,628,383,182,532,671,67,46,697,377,655,166,252,928,679,171,970,981,748,996,68,100,339,967,621,76,816,271,255,959,223,586,213,860,285,976,534,123,153,390,167,248,161,866,846,519,208,374,86,565,174,214,360,872,36,429,242,857,268,961,573,427,515,473,759,554,629,822,440,276,451,338,243,902,712,796,140,440,914,704,344,857,916,651,328,909,492,920,305,8,797,252,423,722,448,974,842,80,948,271,78,694,796,342,647,693,835,514,338,54,814,557,962,470,434,967,940,579,37,44,80,914,345,118,204,586,727,155,69,735,134,914,287,10,29,382,206,892,275,38,803,13,854,612,451,802,279,82,537,300,846,329,534,518,367,880,127,252,112,485,344,432,694,688,787,129,77,791,975,918,721,291,885,744,988,49,883,235,366,67,261,36,143,846,625,977,884,101,109,304,491,908,613,652,267,777,570,844,101,362,16,201,296,406,724,492,452,43,885,552,573,753,141,58,879,939,461,592,889,403,298,817,356,359,893,855,312,251,600,92,37,805,148,335,270,760,483,511,264,436,509,178,908,110,953,176,919,53,732,406,876,895,45,153,115,688,55,45,409,646,116,301,706,145", + "619,571,128,808,572,203,32,183,646,514,472,180,960,844,118,18,552,222,492,874,744,991,869,74,290,767,264,628,473,955,36,932,809,266,423,501,674,658,609,943,604,964,68,348,517,62,110,826,705,369,398,647,513,973,90,295,464,218,171,370,10,300,158,460,998,591,157,71,701,788,352,431,818,648,272,712,548,327,51,966,299,566,476,277,756,444,710,887,31,749,553,448,767,124,909,556,468,715,124,751,90,506,788,393,46,586,443,976,196,95,434,754,695,235,802,58,713,41,778,571,866,689,120,620,757,68,459,419,590,757,102,825,142,735,623,902,275,410,293,192,118,53,433,485,852,561,430,26,451,208,638,718,521,457,140,676,77,737,276,475,69,197,914,940,607,629,701,477,701,27,993,816,624,112,707,145,88,586,104,773,793,628,249,126,986,743,222,322,66,662,838,605,319,946,335,188,91,491,194,326,502,881,619,105,801,577,263,873,431,495,545,234,835,748,534,408,864,812,971,454,951,278,505,13,675,424,431,467,308,642,140,810,216,766,592,92,370,568,209,981,194,82,111,466,514,355,198,418,473,624,605,276,218,43,194,867,179,398,447,80,162,20,797,893,586,230,141,778,929,683,702,399,204,870,738,790,873,724,769,985,264,659,287,795,941,328,483,534,777,559,904,458,363,0,745,298,359,831,932,93,688,627,508,623,984,923,494,390,255,783,345,130,514,946,524,650,342,887,560,347,30,60,561,675,129,106,303,140,551,721,331,428,241,98,205,533,883,6,684,338,471,477,672,754,472,477,816,684,374,328,164,73,253,141,873,503,238,586,369,573,853,183,552,305,964,323,752,158,68,998,825,365,425,833,464,816,600,70,500,8,818,700,28,999,140,453,491,248,80,82,242,691,312,549,207,896,336,926,438,428,338,193,715,943,603,311,404,786,65,90,764,928,635,751,618,38,108,926,68,885,550,265,687,337,537,152,171,539,964,153,258,371,76,774,495,823,607,82,81,267,169,305,487,388,67,673,700,865,973,381,677,298,476,130,705,756,855,475,781,803,581,548,732,379,859,292,711,762,415,787,270,536,631,44,356,36,990,122,866,519,661,544,235,651,72,594,468,894,593,921,574,876,96,992,111,294,20,748,912,416,178,310,631,195,427,81,688,787,404,372,690,520,640,745,994,256,157,97,902,818,752,107,529,713,774,958,546,35,666,192,424,63,727,863,622,936,244,563,64,123,386,954,489,652,606,664,968,846,666,963,530,154,86,853,243,866,470,100,262,694,18,332,821,950,836,32,928,410,570,562,10,953,868,391,369,202,414,692,772,642,45,869,114,977,49,729,404,276,646,478,105,154,470,485,36,13,350,672,441,577,48,647,754,215,246,93,791,555,154,225,574,52,638,399,800,251,247,122,776,466,993,564,969,927,682,293,589,461,78,752,770,130,945,786,433,975,184,761,500,569,5,599,511,44,798,703,362,925,433,820,981,896,560,547,727,307,610,866,527,773,61,865,983,65,57,800,310,153,133,840,403,398,492,575,99,616,22,48,716,327,767,681,844,751,507,845,789,174,367,931,253,23,188,850,288,373,521,80,953,94,193,718,960,128,253,12,585,378,319,861,947,75,488,181,685,888,688,890,486,806,327,148,846,987,165,802,672,315,696,730,725,385,202,9,118,827,912,183,974,600,255,493,886,569,523,168,895,658,565,42,484,728,105,361,178,187,36,727,865,485,96,533,22,149,444,481,217,13,751,814,497,301,171,965,176,464,309,438,563,234,183,643,935,280,487,269,74,765,900,897,619,783,964,389,5,316,953,647,199,450,434,939,913,298,540,15,859,362,365,843,486,135,899,749,692,401,854,12,148,313,841,665,289,853,113,346,818,980,391,774,877,679,47,194,489,396,414,991,125,139,904,791,300,511,279,268,939,537,57,562,467,250,80,394,162,582,569,181,803,351,608,833,484,135,439,873,176,989,974,449,973,277,982,939,92,41,798,184,587,232,288,14,494,726,945,268,267,266,947,283,893,924,826,78,683,472,91,449,900,146,319,343,361,529,148,578,250,340,120,530,728,695,490,814,837,385,967,450,307,651,539,719,855,84,634,136,842,671,575,307,798,983,92,699,454,163,257,551,247,811,214,724,151,410,192,606,354,486,754,820,785,825,779,770,376,733,389,493,836,915,833,738,578,48,768,444,862,254,706,150,24,937,98,711,368,427,822,190,822,395,785,875,686,81,672,890,517,241,984,515,503,556,946,760,689,931,925,2,150,769", + "453,646,996,349,288,95,404,953,343,458,485,502,54,440,890,315,643,748,387,152,84,389,300,395,732,373,674,631,726,744,631,611,852,911,247,101,721,241,924,39,634,361,723,563,586,626,11,777,564,73,668,42,51,71,990,502,963,588,443,170,942,106,987,716,415,284,658,512,499,71,172,782,104,82,916,999,463,155,269,864,55,483,398,232,962,103,299,451,27,733,34,486,746,537,53,89,46,916,533,795,435,868,705,952,882,252,895,569,388,403,792,670,924,354,588,540,822,702,536,104,725,910,893,238,752,936,624,456,629,330,569,163,235,101,67,171,566,35,71,568,550,707,961,683,73,867,652,639,714,968,620,366,427,426,264,615,924,621,745,641,34,46,725,870,821,323,136,162,113,349,972,214,170,423,496,95,319,400,364,998,721,829,600,653,948,761,628,769,642,781,255,444,57,488,119,263,757,274,117,516,594,721,613,746,55,340,216,105,218,101,252,459,954,290,502,793,157,453,8,748,666,741,537,176,495,761,578,650,206,692,798,628,513,235,678,171,567,181,730,932,599,231,239,829,541,21,83,322,770,904,402,690,326,993,431,112,497,872,56,64,752,950,787,782,853,866,742,15,73,978,724,783,135,370,202,981,382,25,250,725,305,885,521,123,725,401,689,406,58,518,904,901,203,745,0,804,804,632,856,888,882,684,947,361,982,693,585,550,283,824,803,709,2,165,529,71,580,195,347,724,79,316,486,263,35,251,346,498,151,170,709,34,547,805,885,394,171,776,379,93,83,937,296,60,985,308,238,584,240,97,522,55,585,751,955,4,936,81,896,549,563,329,45,319,43,857,332,611,237,853,702,457,704,613,650,224,839,960,379,802,630,188,135,375,956,184,172,947,583,16,290,316,944,345,793,646,407,560,993,6,193,134,515,720,360,220,23,770,104,746,764,830,852,552,726,931,475,295,424,603,434,79,128,153,850,161,671,761,640,892,814,840,383,278,846,403,818,592,116,268,764,191,470,855,683,955,1,897,220,501,121,919,46,513,319,981,185,465,128,317,176,171,934,170,772,241,99,430,476,839,746,731,169,519,450,499,487,12,772,588,416,903,86,276,413,331,355,958,522,441,510,115,899,366,73,447,219,820,350,502,367,922,941,845,268,734,736,856,265,674,132,172,401,743,913,237,53,259,734,411,575,140,870,59,391,902,125,675,782,610,82,307,813,267,394,477,36,808,146,280,973,158,703,127,905,769,500,467,609,232,785,548,291,258,132,228,574,201,797,168,360,666,665,64,218,664,159,250,661,907,780,285,531,960,972,125,568,526,589,297,31,946,982,211,211,388,779,557,802,217,732,400,405,158,270,531,3,818,576,258,508,741,796,553,410,629,701,568,545,822,224,360,745,217,60,109,863,733,702,232,746,478,422,10,589,385,615,773,80,174,454,324,249,949,637,62,414,568,509,559,382,619,695,156,506,998,967,385,503,527,509,669,368,796,218,16,405,548,636,318,328,514,405,934,797,279,614,943,213,581,896,338,716,611,561,52,361,645,524,318,929,717,214,997,793,340,102,593,821,570,741,160,653,316,6,80,408,906,749,325,623,391,133,774,94,954,938,172,90,5,657,676,850,645,982,769,154,43,251,83,53,769,476,213,821,466,349,502,227,991,958,325,996,104,578,504,659,431,257,129,407,441,277,67,827,813,363,748,984,99,87,39,604,532,244,270,410,83,911,743,490,793,452,807,295,199,397,994,217,201,784,129,308,582,627,909,661,240,265,153,362,558,190,193,467,783,450,281,230,283,513,143,324,245,428,864,542,375,723,143,832,261,417,365,570,64,554,490,786,589,750,791,650,699,907,735,642,505,382,526,769,606,103,878,699,799,96,630,733,405,715,974,738,456,187,616,76,480,623,411,764,61,18,419,390,383,613,600,901,338,672,937,153,145,627,207,666,124,165,616,390,288,85,538,451,963,478,41,861,979,605,908,735,440,592,205,379,201,924,470,55,635,554,358,992,190,441,643,18,50,212,181,618,136,767,417,201,483,205,8,574,950,81,954,75,19,285,249,950,979,555,70,24,338,802,925,181,552,895,394,311,574,785,342,975,702,880,16,171,232,511,753,215,720,285,823,527,135,593,626,664,235,187,499,980,554,1,721,594,466,560,984,515,618,102,260,304,574,271,200,893,932,818,102,19,404,97,132,279,571,488,312,918,387,986,369,44,33,769,691,516,951,806,218,977,153,417,187,293,809,691,420,607,617,75,32,851,713,310,725", + "729,477,185,808,456,570,194,552,509,514,373,606,528,306,642,523,513,787,574,667,259,329,70,558,718,513,468,97,177,462,342,464,540,589,643,36,244,419,208,13,613,597,156,88,966,653,703,804,154,367,921,254,794,318,963,97,747,39,413,511,855,519,90,123,108,263,899,815,835,119,522,902,57,918,251,976,706,137,123,727,3,566,257,247,8,400,775,356,959,487,190,134,724,369,666,295,19,298,95,411,148,126,409,836,379,511,150,786,738,671,142,334,797,150,111,789,673,697,948,597,880,919,419,662,410,778,166,566,390,434,304,163,146,128,820,86,375,52,289,912,223,288,957,285,931,678,609,275,583,619,341,856,94,79,949,151,902,360,504,355,36,464,615,534,992,570,566,258,110,361,574,345,123,441,218,370,810,917,290,298,162,316,514,921,631,335,543,953,778,93,546,677,191,18,794,48,934,771,904,75,252,644,156,561,67,5,871,734,999,530,220,614,710,335,55,155,520,579,63,116,268,65,86,627,730,195,65,708,961,276,320,884,245,370,977,148,519,733,329,333,388,914,896,266,113,92,139,887,482,1,391,808,491,783,55,803,579,754,7,619,577,393,841,217,586,47,393,148,73,731,435,534,769,376,575,684,156,218,96,231,632,772,260,411,141,303,581,967,817,92,234,864,79,298,804,0,827,289,551,391,761,550,689,530,148,46,540,811,728,468,478,619,244,596,662,347,416,281,725,548,566,625,47,391,76,982,17,533,275,164,151,144,750,845,851,799,986,874,683,547,677,827,49,182,50,894,962,967,465,575,359,54,494,49,524,736,765,226,499,567,249,180,487,858,882,851,507,722,280,315,61,118,471,961,84,527,265,101,72,347,748,585,77,282,872,270,253,18,815,402,945,283,796,863,362,577,531,674,907,910,438,363,139,79,910,330,29,625,949,909,104,79,128,327,558,629,250,393,803,444,807,749,479,738,505,125,259,207,381,551,757,739,112,103,917,31,202,310,419,22,619,903,992,140,101,996,660,71,993,465,223,139,56,557,9,829,157,312,307,703,183,689,523,686,796,473,983,917,583,198,979,807,614,924,868,225,672,884,979,199,668,400,451,660,330,453,454,946,744,527,146,954,185,102,149,980,792,7,456,541,118,387,80,492,336,904,78,789,981,442,835,554,666,832,939,583,561,977,958,887,858,368,729,964,531,718,871,956,68,451,871,204,829,557,805,402,453,976,371,724,688,410,377,714,309,483,401,242,655,678,629,481,211,893,566,237,780,714,272,126,518,418,737,676,430,514,136,82,282,866,350,95,629,225,656,659,906,879,899,665,213,471,442,87,393,149,370,861,549,425,52,814,480,469,405,982,626,578,424,178,851,417,403,777,895,254,151,653,856,957,930,193,71,705,121,841,702,962,66,260,697,124,820,962,621,60,64,674,800,938,551,172,841,665,870,8,798,464,78,955,513,834,687,601,132,743,43,614,343,265,820,901,189,745,347,199,470,599,275,118,259,231,7,836,243,387,686,577,235,957,838,382,300,147,9,931,975,727,944,687,576,425,772,266,974,895,481,433,958,326,847,848,268,819,375,271,723,198,948,846,233,975,100,361,957,373,498,708,371,965,963,305,941,369,415,27,763,157,604,948,246,143,817,622,660,887,135,338,32,340,435,112,25,96,772,427,860,811,643,769,988,255,67,872,237,586,930,275,217,288,790,838,728,967,560,661,506,879,564,328,366,914,665,589,84,149,764,818,516,704,143,560,18,762,185,634,568,184,538,225,272,32,739,59,719,920,725,877,115,963,94,383,721,68,948,716,994,131,521,849,62,833,348,760,386,198,140,261,811,88,561,802,350,841,683,887,98,65,494,866,221,664,197,722,709,215,585,906,915,228,367,398,543,974,245,458,591,847,118,295,844,555,977,432,292,678,599,421,769,186,482,620,237,440,25,321,987,417,757,524,992,200,667,47,480,203,397,500,6,820,654,25,54,694,936,674,39,684,867,583,876,474,871,996,297,614,344,867,866,567,125,6,825,520,375,907,1000,460,576,804,123,990,569,211,894,594,594,257,661,573,439,919,838,59,685,143,311,909,286,876,864,964,162,291,221,890,539,318,916,597,320,446,874,714,692,946,769,501,452,308,379,535,791,450,84,307,295,209,964,873,994,799,522,19,630,930,856,265,51,313,372,468,278,793,249,298,614,551,178,867,574,6,124,671,965,482,577,301,360,431,720,894,407,561,514,357,348,589,895,264,640,118,503,459,799,333,500,801,682,362", + "744,890,345,688,506,861,555,245,647,958,67,996,520,102,197,954,918,30,573,380,197,957,718,264,496,85,166,774,556,172,905,675,737,670,234,980,510,147,952,602,379,763,794,714,907,887,193,651,849,980,840,629,743,972,84,926,630,477,909,54,140,775,493,926,954,489,731,667,694,830,991,940,279,826,592,4,133,189,23,564,69,968,238,783,53,519,885,513,590,639,458,382,445,650,633,994,13,328,598,8,309,371,677,427,916,737,347,873,772,408,412,109,86,797,231,624,646,89,974,463,712,338,168,560,570,164,671,602,77,596,185,204,752,742,324,64,328,395,289,785,100,888,241,917,529,391,273,567,31,148,747,675,837,514,133,642,651,538,210,663,731,957,102,347,571,432,903,200,474,151,689,856,205,127,995,250,618,23,44,722,779,661,322,388,63,606,802,227,351,985,205,153,169,932,401,60,393,179,471,154,432,616,330,445,72,220,909,553,103,743,236,64,818,24,350,681,555,1,462,401,822,890,901,259,59,957,137,731,947,39,159,576,848,406,568,513,521,730,923,14,177,546,662,496,187,134,194,230,966,184,966,335,176,581,989,630,919,758,782,329,56,983,80,628,366,651,733,49,175,850,539,970,689,50,903,976,626,605,709,569,464,682,111,996,512,988,873,270,325,683,851,434,400,359,804,827,0,172,932,869,948,661,650,639,5,608,391,121,882,832,914,644,684,697,635,657,254,539,295,204,321,952,714,649,929,376,218,759,66,443,660,905,127,994,148,555,891,338,498,101,341,869,592,555,978,716,93,369,545,537,453,566,190,930,969,400,896,108,470,784,501,122,364,840,905,430,557,244,465,761,238,19,450,566,416,682,282,937,303,857,966,153,471,468,341,437,646,179,208,272,735,987,880,21,373,140,764,210,853,813,279,49,798,646,797,331,81,205,753,626,755,246,542,964,240,450,953,839,900,820,994,203,732,597,56,621,585,215,488,586,907,365,289,840,21,547,823,42,932,461,270,56,582,36,429,924,715,693,607,270,970,948,125,664,82,166,881,316,740,534,396,427,499,211,932,478,80,923,658,268,871,366,249,995,679,877,320,485,626,942,807,288,977,978,151,807,962,410,461,981,840,33,423,492,428,261,249,28,402,316,925,371,586,181,332,513,474,684,175,676,579,697,735,122,759,25,785,485,556,98,203,817,24,865,60,626,247,759,800,438,561,396,958,916,393,916,20,160,406,757,316,279,382,96,419,898,840,304,883,599,67,949,991,176,925,449,892,543,468,278,6,392,324,880,154,388,883,177,255,240,435,903,121,100,205,7,203,289,525,731,175,196,173,152,232,870,234,643,586,503,869,673,10,974,329,509,227,457,468,323,885,571,892,53,485,983,804,463,285,738,846,372,218,549,120,386,924,507,580,58,362,885,902,656,740,921,116,398,956,133,808,759,375,891,285,628,44,667,30,722,722,411,136,226,884,523,943,609,472,246,969,525,698,381,245,312,501,129,202,16,475,514,386,403,927,512,761,885,371,251,796,675,73,742,114,196,616,492,741,882,941,860,13,631,95,386,260,3,7,508,195,886,815,657,700,425,849,629,264,948,780,431,695,191,142,960,865,945,925,852,500,138,163,652,962,336,237,897,75,44,374,847,650,435,404,251,162,257,150,500,639,55,334,723,542,585,155,81,95,729,290,767,802,371,673,523,396,101,202,445,239,347,850,972,328,789,856,737,827,657,104,334,580,446,295,541,463,134,580,126,769,912,45,463,798,487,625,70,264,191,343,962,759,102,881,472,57,480,639,839,559,841,235,825,18,884,925,973,630,507,36,613,541,848,537,356,511,562,405,579,876,148,534,944,220,785,663,59,442,896,791,782,682,457,995,38,84,781,82,81,665,820,805,343,901,960,141,217,378,758,446,303,629,184,929,113,590,302,949,379,913,438,727,648,72,446,762,306,704,824,739,629,177,62,338,987,738,684,508,777,548,46,909,379,587,42,232,363,816,684,31,86,872,212,629,917,188,677,831,641,442,528,378,907,475,726,231,523,181,524,574,192,144,486,715,672,750,185,570,45,716,953,669,563,69,359,963,409,42,574,838,640,23,633,700,140,691,387,246,768,237,917,576,930,78,852,227,805,978,908,712,418,569,950,22,390,300,107,114,504,787,216,344,205,708,614,382,243,210,237,207,168,114,310,449,910,647,915,346,340,130,382,32,968,449,723,98,808,414,740,566,861,483,719,71,682,80,387,279,60,291,963,677,485,41,464,600,76,740,719", + "166,624,714,280,667,815,544,760,892,770,4,320,413,914,471,520,666,146,939,796,385,554,141,490,906,303,327,556,349,34,536,117,561,163,150,733,400,441,34,338,21,173,32,465,225,498,537,592,331,391,243,800,850,818,399,775,687,60,940,683,347,277,234,801,693,228,416,637,469,221,278,241,139,822,428,848,651,442,892,120,448,372,48,174,58,410,94,787,505,654,92,123,471,313,19,274,583,920,443,364,695,739,894,62,232,715,181,228,263,810,692,644,579,156,267,918,278,16,500,517,22,387,280,955,820,633,3,664,452,830,31,398,224,570,793,338,444,53,372,700,624,387,766,673,183,365,319,586,874,241,349,145,506,554,804,283,281,921,857,237,970,827,140,684,259,664,972,832,67,620,200,205,518,756,625,95,946,280,666,523,663,334,62,704,934,98,370,516,174,213,201,681,953,891,38,540,600,545,603,178,13,77,37,401,996,282,297,280,135,775,740,190,729,341,76,434,591,437,550,477,364,764,992,188,390,329,846,728,102,42,238,849,839,662,771,379,664,155,730,38,931,684,657,328,463,303,719,544,212,726,870,564,356,224,212,257,729,414,367,779,383,4,182,512,666,86,144,119,167,363,189,730,249,830,733,248,599,925,863,298,993,85,832,818,329,823,737,877,835,267,565,400,606,831,632,289,172,0,687,121,424,12,961,830,90,915,508,479,351,502,463,969,774,426,927,647,170,50,342,809,926,26,836,179,837,375,669,20,442,764,635,110,929,853,863,240,186,417,798,980,839,917,635,257,229,298,152,26,856,211,462,875,712,676,558,960,637,462,393,159,433,61,109,889,3,90,367,148,803,660,321,503,866,325,311,129,194,392,992,691,514,36,386,225,140,672,188,641,227,464,484,503,131,52,884,976,746,740,224,833,8,723,814,897,177,597,361,299,167,936,214,912,410,123,338,86,589,596,201,146,852,284,866,276,125,207,609,465,473,903,709,379,822,110,484,618,659,675,316,355,484,249,684,328,379,152,867,421,422,174,372,380,385,887,835,499,23,475,471,771,310,873,842,281,135,563,672,660,209,906,950,3,826,689,988,464,638,824,981,379,623,28,435,360,136,918,783,860,606,845,943,574,511,963,383,27,772,124,151,23,300,271,74,559,927,264,566,539,655,276,299,711,552,786,806,414,284,787,423,120,884,527,583,207,783,89,441,425,190,596,56,646,177,284,711,110,98,409,816,651,52,712,146,369,58,981,221,412,641,91,839,823,129,388,483,130,303,976,959,20,417,904,18,98,779,589,226,599,234,250,114,863,132,933,324,358,998,261,142,724,755,373,680,844,974,581,419,345,588,735,997,894,866,856,749,278,809,451,736,862,570,865,425,913,668,523,320,195,642,776,979,20,371,542,677,274,203,881,834,33,874,536,857,818,728,359,878,630,480,428,599,404,809,720,309,144,103,725,704,91,401,239,748,964,778,292,217,742,757,919,911,924,166,43,990,184,814,756,353,672,132,686,713,369,118,425,964,581,657,57,535,100,892,400,915,755,503,25,465,627,194,27,122,312,853,868,786,836,196,32,635,415,819,819,694,993,984,955,992,772,613,971,504,370,155,194,900,59,919,10,997,856,389,795,377,95,721,427,195,400,990,301,41,272,166,331,179,222,165,922,917,703,883,224,129,397,839,840,271,817,216,872,412,348,505,13,803,277,99,255,82,969,901,792,513,812,726,845,456,520,657,21,625,807,799,902,20,812,48,720,564,354,444,176,780,534,280,316,759,424,661,934,73,204,583,768,256,832,332,56,871,257,167,241,641,445,747,810,593,185,766,193,677,750,128,834,680,906,766,655,808,228,815,186,834,333,136,187,895,922,522,170,862,406,963,979,32,516,315,386,456,897,166,655,610,143,900,549,97,727,239,272,619,609,516,845,98,206,71,117,108,749,837,612,902,105,203,503,485,768,80,896,331,52,963,165,170,724,560,16,456,386,720,55,212,870,577,197,127,61,481,362,515,90,953,803,749,558,189,813,770,810,359,141,244,110,862,204,6,39,106,894,819,746,201,180,788,510,509,202,922,893,533,811,638,93,866,855,19,678,707,663,746,366,390,619,71,267,254,93,880,894,616,359,816,583,126,900,744,52,18,347,277,749,473,119,525,16,516,708,759,629,846,402,906,287,369,948,164,722,329,574,486,74,87,168,752,331,910,134,917,570,218,36,877,356,106,97,451,317,295,423,197,481,269,437,989,346,635,14,896,10,128,639,495,277,614,841,618,880", + "880,850,848,743,725,978,597,305,134,505,98,414,911,858,557,502,503,664,850,628,671,279,152,650,200,665,900,581,801,12,217,396,573,146,519,606,535,83,150,14,248,105,388,462,519,963,161,521,417,937,365,52,484,539,915,403,460,728,135,771,280,517,737,638,523,619,340,415,775,258,665,913,979,10,299,51,167,459,626,601,912,263,329,387,351,229,236,78,171,591,631,183,474,165,832,864,686,495,149,470,663,578,315,193,115,354,157,953,255,120,432,408,389,673,107,25,268,647,18,104,108,21,582,351,61,384,106,334,656,389,290,325,630,593,523,7,264,846,23,242,37,788,604,970,43,457,227,301,343,110,682,283,385,482,861,241,261,482,877,418,343,761,145,557,789,323,697,975,978,97,762,281,212,38,395,984,51,130,708,267,186,201,214,820,631,664,276,560,672,880,281,359,982,623,66,881,716,307,63,669,653,434,506,9,265,93,660,445,266,184,456,450,378,620,166,580,172,857,512,231,224,243,541,722,147,619,121,306,519,761,464,705,454,576,145,508,442,291,702,301,18,11,144,193,590,600,819,539,485,405,575,448,788,566,880,918,749,761,504,37,470,630,687,663,964,937,262,650,149,767,653,451,881,542,988,732,480,101,991,346,379,565,803,99,101,944,928,556,926,205,750,473,810,932,856,551,932,687,0,838,275,521,323,968,802,624,465,12,665,698,838,123,36,158,188,404,904,944,410,885,859,622,511,857,73,283,358,752,938,113,611,342,377,724,806,539,222,268,908,25,983,241,877,944,320,871,587,214,44,583,67,700,856,115,268,323,807,807,703,210,5,76,417,848,466,242,948,631,591,821,13,286,406,96,525,426,927,694,458,528,6,739,306,618,127,185,365,502,361,697,731,514,432,388,443,102,135,456,822,473,63,4,289,854,585,760,660,494,698,22,465,419,374,410,312,572,17,644,553,863,280,890,882,924,976,299,813,537,857,704,26,754,831,40,820,153,3,639,69,721,755,277,679,373,467,977,998,798,36,342,796,989,365,401,142,796,634,928,20,91,529,526,639,760,738,664,763,75,830,391,635,339,98,324,829,811,376,461,90,199,198,940,651,64,762,986,558,828,596,735,812,619,704,2,59,323,626,558,867,247,832,736,591,856,759,462,288,891,324,588,254,984,513,174,203,210,65,641,335,664,216,406,645,312,991,246,24,251,101,290,694,471,600,660,791,694,648,416,199,31,220,933,475,239,362,498,452,475,707,730,250,333,922,435,653,148,987,560,458,800,120,914,482,106,738,138,97,334,443,115,234,8,704,122,631,686,581,30,292,709,366,727,771,175,155,527,255,178,672,661,302,431,75,914,446,263,917,327,757,95,177,691,904,485,704,823,321,824,243,114,584,784,756,915,520,133,105,738,998,764,757,112,886,680,165,65,910,183,519,299,309,667,462,552,850,666,331,192,105,379,844,935,850,791,534,33,364,574,415,374,405,332,45,978,434,287,704,856,27,822,952,309,994,500,106,220,746,590,955,858,297,934,81,790,548,57,790,56,7,266,207,601,307,461,171,865,690,521,86,773,290,617,2,183,993,152,921,66,750,869,869,945,82,67,921,45,845,151,97,829,695,824,62,130,557,395,592,495,746,991,578,413,365,129,79,496,257,77,501,548,754,747,782,321,483,346,986,252,687,551,632,114,755,599,230,797,223,813,386,14,357,733,189,699,974,546,142,771,747,160,421,697,767,813,667,538,200,370,690,670,568,181,819,916,915,938,188,324,461,427,813,970,371,854,660,944,607,315,560,223,789,720,280,39,669,807,481,446,290,745,406,308,565,222,973,98,232,521,760,425,269,814,494,263,448,703,103,921,935,85,615,355,256,310,411,436,533,379,935,108,612,487,749,162,899,26,292,199,325,232,278,595,268,111,329,864,255,705,248,225,419,154,809,850,751,282,990,473,643,483,116,750,498,918,570,554,63,930,247,465,632,697,819,345,411,663,57,271,60,546,760,982,244,918,802,625,851,190,8,490,739,117,470,45,960,97,575,166,456,570,785,943,22,821,408,960,662,767,384,613,2,359,579,844,114,272,670,397,499,468,969,529,432,154,549,784,153,546,537,776,100,852,157,737,565,91,934,843,781,464,360,30,537,612,169,733,368,109,232,405,35,60,461,105,359,955,511,551,634,441,39,202,670,428,363,824,153,904,344,278,49,846,561,411,188,868,511,58,760,271,874,631,816,161,875,297,740,428,917,179,435,305,480,427,660,168,147,347,198,941", + "800,69,217,824,392,287,886,58,194,709,868,974,314,564,835,992,778,249,923,94,899,596,935,814,850,58,83,204,770,296,474,171,989,714,627,332,668,229,438,919,676,757,63,91,921,44,655,556,3,87,219,531,388,971,272,681,351,664,698,313,316,160,866,652,877,684,802,805,326,47,793,301,590,776,82,404,990,807,555,119,922,632,679,658,518,416,79,442,663,294,366,976,514,152,654,526,567,632,129,8,571,439,815,436,681,388,917,847,24,254,211,450,140,241,558,132,641,214,972,557,424,613,749,874,21,851,35,611,267,173,275,105,2,982,928,882,212,968,371,98,486,505,323,203,211,698,18,221,596,148,72,282,693,494,925,781,862,602,145,382,852,715,263,352,511,6,905,388,397,732,143,368,977,944,986,804,469,841,200,32,162,507,462,887,940,639,598,752,265,207,451,775,355,625,853,823,203,942,109,376,510,290,660,309,271,475,500,598,249,903,656,828,537,246,10,177,907,504,468,402,814,563,204,216,469,965,357,230,796,180,248,417,142,690,888,689,784,714,52,247,93,12,201,633,30,759,323,436,627,830,459,988,17,296,905,749,520,842,930,774,417,555,908,85,49,513,632,458,833,873,346,812,589,6,220,886,958,572,496,757,342,141,405,839,222,855,26,507,864,311,553,925,276,93,888,391,869,121,838,0,109,141,119,717,566,881,564,920,378,444,231,278,924,950,197,908,135,101,482,98,262,961,696,939,962,118,740,257,958,63,203,691,286,579,724,541,133,301,745,275,230,503,975,228,298,180,81,685,560,509,16,87,773,593,345,497,662,865,223,29,650,770,336,335,373,701,677,286,677,417,474,264,361,62,925,394,214,607,768,307,136,246,392,937,847,79,858,726,529,930,102,233,35,202,396,444,858,530,241,384,827,803,314,751,470,352,83,38,917,12,805,201,991,843,328,739,626,886,671,557,796,904,547,783,322,672,74,489,965,584,482,528,114,565,147,176,863,875,168,699,737,538,958,41,902,286,344,928,254,615,442,576,319,478,177,529,692,948,587,926,250,18,734,385,569,921,953,468,727,949,395,5,613,758,55,793,271,174,251,997,17,337,78,672,124,30,614,574,440,644,509,814,61,112,147,280,804,519,107,944,663,499,953,453,63,401,272,753,893,390,318,229,952,455,189,887,536,623,614,133,826,410,69,864,592,636,149,466,111,967,545,943,431,374,722,159,851,986,368,831,896,97,279,651,300,871,780,557,992,665,27,755,975,307,607,789,145,15,293,214,915,212,780,679,201,427,519,461,892,623,727,523,668,812,230,738,137,207,582,993,241,999,128,245,80,946,643,632,739,133,240,525,312,820,284,642,914,79,218,638,493,556,542,100,41,471,739,530,257,151,131,664,237,154,172,447,859,912,869,481,771,39,109,239,159,30,363,591,373,741,146,634,17,577,31,230,624,143,65,21,224,574,933,901,940,952,194,241,730,983,978,693,759,955,715,788,312,630,976,124,163,579,850,756,37,45,440,939,716,742,150,31,657,879,840,306,920,920,549,722,629,537,621,677,749,451,606,629,213,268,960,769,805,211,222,904,940,553,823,921,742,73,365,197,766,198,582,813,594,662,696,132,182,781,195,586,650,86,620,963,856,323,912,150,829,265,851,471,912,418,340,553,251,307,967,183,332,6,485,484,163,609,635,275,863,280,827,789,623,565,727,462,881,284,412,366,310,440,361,991,565,586,415,435,801,242,629,805,794,614,855,499,518,941,466,238,653,262,66,491,110,670,443,431,29,851,386,529,162,841,74,228,101,127,52,242,945,586,184,937,610,329,326,511,355,201,398,455,153,694,379,76,261,701,884,46,135,850,343,265,341,983,495,28,223,446,52,754,987,589,242,465,354,355,413,207,491,365,670,729,438,275,233,920,901,272,829,3,451,13,777,46,386,685,277,20,74,796,933,455,873,588,330,418,556,807,937,400,957,688,436,590,768,877,875,596,349,796,873,856,824,996,752,525,734,331,153,33,107,851,159,587,957,146,625,202,116,229,377,145,519,846,196,490,950,374,315,682,327,766,870,554,870,418,787,783,301,847,611,948,365,97,641,590,932,417,790,485,756,681,290,153,454,109,890,678,483,769,493,767,509,659,853,590,236,101,250,503,838,93,912,614,997,783,962,603,368,391,503,131,409,99,378,18,298,444,444,707,280,363,11,47,890,867,27,514,800,49,755,879,96,205,403,249,62,337,193,144,458,763,755,467,152,717,45,518,817,17,845,521", + "860,155,648,396,37,31,282,657,988,114,871,388,543,738,712,290,486,610,956,2,754,664,716,270,739,885,614,742,712,139,603,176,23,786,800,140,949,352,479,208,642,802,458,435,608,929,223,942,266,155,487,879,49,524,117,128,28,489,759,861,908,480,61,955,640,729,742,90,194,252,102,505,895,651,36,21,568,900,982,73,287,212,610,560,698,559,242,667,319,232,908,658,139,873,168,773,269,66,114,93,266,947,919,827,339,407,998,363,93,783,955,697,350,162,103,904,234,281,424,693,221,926,519,344,498,743,88,82,572,27,260,187,847,889,505,467,617,969,166,292,26,489,337,795,38,858,722,918,918,821,441,563,583,727,967,225,597,930,400,925,500,770,858,521,637,424,627,926,642,419,859,536,632,722,930,952,467,3,457,957,981,533,712,366,408,543,111,904,329,881,180,715,263,498,366,929,793,95,694,748,641,643,212,608,624,837,290,938,97,394,56,683,495,495,774,417,422,57,332,334,968,393,84,951,436,208,419,863,741,241,734,756,41,860,687,401,422,314,612,325,796,479,593,251,129,365,563,347,596,222,949,564,76,496,729,33,874,985,70,556,964,893,138,485,394,244,199,423,474,180,509,328,50,575,815,420,354,148,797,965,450,944,215,482,391,757,604,982,521,610,375,650,780,688,882,761,948,424,275,109,0,34,607,626,447,824,752,509,244,895,107,172,516,83,480,289,5,691,368,628,315,274,397,878,853,300,370,635,341,45,800,87,835,825,328,61,381,139,955,652,861,565,320,909,952,221,64,832,883,429,512,891,194,182,357,325,619,344,994,841,711,985,279,910,81,858,588,634,834,998,234,705,370,391,788,288,526,457,871,978,199,94,921,517,570,894,882,887,427,748,735,287,107,910,959,819,518,278,420,911,99,498,877,704,140,96,861,740,41,960,716,942,954,784,591,93,264,339,375,809,468,649,821,289,254,21,888,558,12,669,477,614,545,158,5,919,847,475,481,896,559,326,38,303,721,22,707,184,809,233,76,181,187,305,34,519,394,583,197,90,677,1000,459,907,990,780,806,546,280,853,973,642,222,336,405,373,302,205,67,538,398,699,138,635,590,705,615,770,850,784,31,354,592,401,513,195,879,590,364,327,320,926,159,269,832,719,564,839,812,116,462,459,582,372,80,297,893,293,63,480,373,935,438,864,849,246,15,7,580,41,250,884,99,56,124,776,745,269,494,196,725,962,41,95,262,725,364,779,951,209,416,817,609,575,736,762,893,367,933,447,531,98,113,877,439,266,625,150,230,534,955,392,959,663,269,511,993,756,181,698,286,749,759,438,641,779,795,251,136,230,227,544,438,263,443,711,590,281,801,258,872,381,982,892,128,929,686,733,505,205,53,646,381,416,809,415,814,997,103,297,816,231,594,597,456,232,512,612,133,980,525,135,857,38,754,348,168,904,62,748,154,134,299,505,809,712,762,115,497,397,26,478,885,998,876,891,685,982,874,104,524,601,338,865,139,289,64,325,121,337,761,194,94,756,785,910,386,585,614,77,704,746,12,181,416,687,112,225,841,980,26,618,828,391,942,929,768,214,414,28,649,871,738,242,570,586,880,98,405,406,651,581,393,55,481,295,679,692,736,440,681,960,21,653,266,439,795,946,850,691,522,819,362,928,12,526,913,954,80,446,707,221,512,601,145,111,343,854,946,466,722,976,461,488,961,649,539,822,543,947,223,757,585,515,249,137,646,615,628,59,206,816,736,23,783,430,981,293,402,890,845,675,972,452,136,871,377,133,565,161,484,334,305,976,906,866,646,295,53,54,683,818,957,569,988,681,483,177,160,315,20,725,565,285,487,816,464,161,387,670,416,225,540,539,156,594,518,216,454,306,41,534,874,989,726,521,748,400,318,299,729,136,414,180,175,27,687,55,34,854,107,539,142,719,274,910,907,461,316,963,181,658,530,541,168,543,586,44,37,880,764,669,220,918,574,669,984,486,844,901,959,369,892,844,430,524,276,211,188,649,401,919,427,296,22,127,513,406,811,936,703,196,684,965,425,885,771,451,532,580,795,470,140,426,108,716,617,844,423,37,547,880,811,369,905,802,461,944,773,9,541,435,434,151,492,65,949,313,198,496,615,793,493,202,907,126,84,168,9,837,884,442,152,156,789,99,508,109,505,923,970,234,9,168,731,231,63,799,930,734,601,405,796,483,401,802,810,579,873,761,663,675,862,39,949,38,871,379,486,993,649,862,335,573,907,299,846,831,481,595", + "869,897,244,664,641,875,890,230,370,212,926,625,205,819,386,659,59,727,814,968,251,741,634,745,759,796,861,479,611,189,597,320,506,541,612,457,24,645,711,52,40,42,300,135,531,638,437,75,592,677,594,869,141,708,762,518,675,501,82,67,826,118,193,129,63,697,278,852,995,812,582,615,935,126,720,277,465,944,145,771,442,640,551,330,511,732,954,373,306,204,703,59,737,684,355,894,994,255,739,318,867,828,68,220,795,377,983,469,555,767,817,384,552,134,54,308,145,542,513,577,412,297,880,579,766,937,89,450,682,482,345,905,46,647,879,434,550,744,885,84,584,459,933,43,145,930,301,573,450,836,313,966,850,274,745,991,343,59,313,634,996,694,271,319,907,687,769,861,507,162,552,643,171,7,128,83,727,332,214,499,642,344,719,567,467,561,857,543,225,427,737,73,429,132,421,919,298,632,317,283,530,944,661,764,237,687,459,948,922,732,474,709,354,383,279,721,100,409,784,543,370,74,402,263,32,425,663,237,739,793,47,721,673,361,761,785,712,22,808,282,34,672,235,284,227,734,852,888,902,703,260,540,999,574,849,284,759,920,340,381,308,701,334,289,950,341,583,230,591,401,835,346,798,215,122,4,760,477,664,625,476,725,757,560,342,273,120,855,677,593,776,793,201,627,684,550,661,12,521,141,34,0,783,970,63,986,729,841,909,289,701,254,764,458,471,340,678,448,100,210,107,578,648,442,402,757,702,557,37,853,321,480,997,377,184,728,955,846,940,841,638,569,696,462,274,710,877,25,484,418,903,994,413,950,12,285,839,656,228,844,339,302,862,675,471,942,557,707,462,332,297,590,914,131,385,518,998,526,462,783,160,213,186,33,440,301,581,422,506,448,989,841,104,422,416,601,934,446,781,512,253,247,819,386,322,497,113,713,852,897,173,423,482,432,557,725,139,900,628,642,119,307,706,739,806,927,565,579,449,845,945,611,8,88,827,484,113,907,665,471,619,970,751,959,198,647,224,939,506,224,810,348,436,410,664,612,276,216,871,535,552,583,281,650,111,82,816,268,778,143,884,823,336,103,241,282,858,113,310,267,408,901,800,231,427,177,617,5,79,549,852,385,964,727,358,148,519,339,946,312,272,713,416,298,951,258,58,60,291,181,918,161,871,64,760,647,501,292,37,147,719,46,453,714,798,80,308,761,724,291,800,167,516,400,265,206,278,716,421,438,16,859,496,98,469,658,940,226,368,58,183,777,53,675,613,996,184,846,217,521,951,519,583,876,365,368,746,329,129,618,871,696,92,874,32,660,512,813,949,117,532,65,501,75,42,379,899,726,825,564,665,993,164,393,998,933,165,562,271,412,205,393,927,336,220,122,45,338,270,425,250,389,209,310,270,474,428,359,765,661,832,258,2,177,156,753,422,492,556,600,273,669,907,180,791,89,21,658,14,778,514,239,397,12,634,851,814,274,270,926,227,93,358,318,969,220,789,243,194,935,675,782,248,849,327,363,995,734,187,444,581,243,948,430,88,845,136,701,664,389,42,837,867,160,701,841,329,396,363,127,994,234,226,789,952,411,504,905,757,461,252,620,424,716,263,589,460,298,800,603,896,925,585,520,56,959,212,68,705,950,230,857,878,7,849,50,765,422,448,261,37,970,497,247,426,367,18,393,655,37,378,192,754,104,493,522,598,349,954,868,764,345,490,100,262,508,463,438,853,650,915,436,174,820,919,454,168,670,96,801,500,30,107,553,306,295,441,464,371,536,790,514,216,302,379,969,981,904,468,78,217,679,775,632,52,619,452,517,242,416,726,62,132,909,523,683,742,358,504,793,75,924,816,173,805,642,885,242,243,275,911,13,566,552,677,119,266,109,956,56,312,749,231,928,303,967,390,993,225,325,955,473,417,543,790,725,574,339,630,765,369,972,656,684,236,213,221,729,860,61,384,964,967,24,366,435,772,724,237,802,918,195,958,572,644,568,945,414,579,170,451,181,61,100,299,774,131,892,521,995,854,914,221,882,330,30,190,337,95,330,8,888,794,202,193,820,214,92,11,331,420,42,925,203,587,904,509,429,123,254,365,487,509,382,132,584,483,825,253,822,594,635,537,448,349,436,766,130,567,745,729,427,124,54,392,598,832,272,311,667,313,689,990,103,377,808,932,967,677,875,657,802,248,979,842,452,759,344,165,569,235,351,471,468,456,3,130,896,863,311,735,123,326,683,845,769,911,845,206,600,494,247,519,690,288,727,215,62,280,754", + "805,498,67,467,545,428,215,43,770,20,70,396,128,886,144,91,46,197,562,870,59,502,270,453,294,209,534,448,274,92,371,52,676,674,998,484,499,83,698,311,275,773,228,565,25,867,928,137,920,719,767,797,81,201,979,522,690,532,96,1,125,945,847,143,383,97,606,569,866,119,520,661,78,511,862,628,700,84,420,549,676,306,519,748,912,910,472,333,764,379,703,573,215,27,154,15,117,19,246,64,81,887,485,486,833,701,617,503,488,999,758,445,298,316,9,211,518,712,84,387,591,412,382,121,773,263,277,583,262,394,906,432,116,278,566,815,691,921,750,848,273,212,270,144,306,905,757,809,749,176,236,765,60,412,435,804,194,791,866,483,754,988,190,188,516,720,622,702,789,95,456,416,864,98,328,415,370,768,263,961,289,690,464,226,986,725,218,479,987,751,708,685,588,547,467,579,416,91,437,185,610,769,970,744,856,488,344,353,121,510,797,219,75,893,722,26,569,602,577,241,124,905,273,704,349,894,277,984,743,836,72,836,76,406,72,545,330,999,32,170,522,243,564,831,819,16,68,189,997,904,564,811,129,231,273,416,696,141,520,72,310,124,127,74,105,498,155,367,291,456,332,407,246,774,163,274,517,920,464,448,655,973,457,170,353,394,128,342,565,259,48,408,808,508,947,689,650,961,323,119,607,783,0,770,997,410,187,398,749,258,461,552,402,134,413,833,52,467,884,264,528,392,863,120,6,379,783,987,494,915,679,862,616,487,708,23,353,804,71,234,311,154,280,654,314,679,626,655,862,495,154,433,325,429,805,239,829,344,498,666,669,830,515,333,579,547,918,932,584,647,548,866,965,319,788,37,681,452,724,474,69,369,635,892,419,754,361,965,261,971,542,873,48,742,929,671,128,313,804,922,691,492,504,269,209,992,531,494,306,4,873,54,114,117,766,99,663,350,433,773,580,859,514,287,976,918,261,842,786,851,20,306,119,366,809,789,259,172,790,602,797,553,857,56,854,504,694,556,907,596,548,102,450,992,383,995,443,308,356,972,230,696,47,206,223,649,754,513,492,540,296,436,121,773,548,319,984,549,485,63,164,366,947,425,694,493,741,871,615,35,827,131,618,223,672,109,902,646,433,467,627,733,928,511,367,310,674,205,790,906,370,347,334,439,67,718,50,688,481,373,343,675,705,453,86,939,375,258,432,385,924,484,23,393,185,343,563,433,56,735,797,981,630,85,147,928,247,857,870,2,733,107,791,68,879,296,887,380,88,822,19,798,706,647,967,348,93,591,972,160,761,843,934,585,810,472,248,615,269,602,905,249,744,342,264,584,949,753,308,584,395,557,100,885,791,696,41,768,295,924,574,317,281,717,336,991,602,102,271,797,551,469,16,315,125,93,481,535,999,911,79,669,155,216,313,478,416,634,301,370,663,223,495,408,546,597,84,661,430,338,616,630,677,586,50,590,555,267,63,112,786,505,73,505,352,118,775,531,491,912,751,336,567,402,738,857,750,178,730,21,490,781,494,441,204,349,681,333,805,296,184,343,75,293,236,276,17,340,517,681,287,865,969,467,836,718,920,898,427,542,679,853,601,709,855,319,665,882,787,301,666,309,908,443,904,576,853,38,52,144,525,516,332,383,908,954,587,312,305,580,740,229,421,198,833,628,593,378,288,333,956,947,436,89,848,451,790,685,477,47,200,978,809,2,296,609,508,542,608,330,472,712,357,912,218,828,26,619,428,544,359,977,863,773,519,72,323,656,53,990,511,307,811,685,248,605,877,131,941,385,39,733,985,103,515,460,520,760,672,325,887,96,280,819,904,940,393,229,487,525,629,891,622,155,38,270,410,706,459,830,361,449,28,238,499,609,452,281,715,797,573,739,42,249,405,489,136,45,955,312,335,506,682,990,328,660,995,22,472,51,535,242,833,281,558,927,499,940,890,974,143,634,281,97,214,117,180,809,831,762,556,584,750,505,161,63,354,111,57,767,725,499,786,556,234,106,735,872,906,246,374,546,64,664,725,774,829,668,786,962,937,947,721,78,431,951,249,36,572,734,323,841,608,683,355,559,854,472,54,952,766,262,202,62,427,858,853,395,148,542,713,401,202,399,3,215,241,777,236,275,284,116,273,540,314,631,669,579,94,903,990,412,489,658,881,117,302,69,648,546,202,412,683,296,333,879,94,506,340,164,815,535,927,943,27,210,529,438,878,741,462,484,279,189,673,865,170,985,183,210,152,169,181,464,607,177,381,921,671,565", + "873,813,94,751,137,246,973,759,145,463,757,256,227,318,198,113,714,610,254,940,63,924,568,584,16,188,166,944,353,336,777,40,237,607,124,998,274,919,22,653,392,968,720,232,482,301,978,93,340,276,398,687,513,465,304,844,755,560,884,81,374,363,916,542,354,324,241,440,840,904,676,57,972,396,540,527,463,292,141,180,454,305,506,951,696,685,354,480,9,639,200,509,125,984,952,615,932,708,224,443,388,802,6,548,604,271,983,782,904,202,898,572,687,743,642,398,819,194,687,691,59,116,670,26,386,356,97,312,48,684,368,713,718,147,28,901,880,618,144,149,246,149,73,144,999,732,362,316,458,249,478,409,175,648,988,3,289,652,142,172,531,999,331,417,818,600,820,818,139,352,53,366,603,468,543,960,108,232,771,20,445,405,376,690,565,751,442,61,540,141,935,679,69,196,613,684,280,965,614,460,87,152,902,962,822,508,858,174,647,11,556,292,237,26,602,365,645,416,387,775,151,509,973,258,361,50,80,516,653,628,805,149,525,282,521,885,685,527,684,675,29,877,509,183,695,672,579,517,624,507,667,280,895,440,344,164,578,542,974,532,351,970,361,987,29,277,806,62,174,32,167,309,420,853,881,808,331,210,776,874,974,216,29,329,453,777,326,921,456,837,960,122,785,623,361,530,639,830,968,717,626,970,770,0,472,499,391,991,89,178,705,133,736,771,588,730,269,969,543,90,212,495,738,101,853,13,251,466,233,112,171,318,86,194,573,126,206,192,424,735,85,925,374,889,510,737,593,827,880,145,764,357,971,700,155,816,110,73,948,836,925,735,811,739,309,548,404,237,293,549,842,759,326,929,764,504,659,248,59,874,751,714,182,395,544,386,979,808,466,729,160,118,812,624,296,882,980,983,875,641,879,881,652,835,551,437,561,487,37,502,292,915,696,482,996,411,342,450,234,24,952,913,171,231,904,851,455,974,947,457,703,41,131,347,805,401,567,856,54,755,662,447,105,573,195,103,791,251,670,553,128,836,314,236,641,111,716,160,882,460,941,861,910,888,236,706,675,937,924,18,816,550,572,592,355,16,765,429,764,845,465,777,675,327,914,736,573,347,540,31,20,588,84,20,284,219,326,535,637,405,398,954,560,734,658,943,994,415,197,498,498,884,958,952,718,580,56,812,966,583,839,401,337,468,482,86,598,625,856,259,569,746,576,320,140,729,731,726,169,390,633,889,555,801,673,48,316,54,169,261,688,119,617,214,579,301,797,438,321,725,724,806,538,314,225,157,214,420,620,567,869,209,965,209,146,620,839,260,99,367,371,697,291,197,219,657,971,386,551,737,129,691,273,825,51,792,460,611,98,955,514,617,122,325,104,259,436,540,716,723,963,503,295,924,254,144,208,558,535,426,302,599,96,747,109,125,812,495,180,570,27,563,410,248,885,507,450,285,242,97,473,649,23,385,808,274,926,436,108,853,357,391,81,998,85,998,260,688,496,312,495,945,432,552,729,404,227,208,76,237,318,356,89,375,334,882,326,243,786,950,494,884,343,384,431,200,259,683,666,857,662,941,667,980,24,805,904,564,507,850,54,982,36,313,286,247,31,269,795,88,158,912,592,355,486,715,569,550,479,944,448,427,592,796,365,982,882,555,173,482,791,536,196,799,853,19,119,540,289,315,745,460,963,268,365,9,42,731,644,270,551,152,179,830,956,29,758,575,57,83,237,719,188,931,223,708,86,583,582,541,484,288,377,516,938,263,567,943,598,49,638,913,41,352,431,279,963,450,267,372,416,323,777,280,625,746,185,782,966,910,582,616,838,363,18,713,167,978,714,47,243,521,488,441,577,266,209,458,719,854,522,165,244,36,137,423,414,607,430,467,721,61,744,879,544,559,205,727,694,644,340,136,420,459,189,817,962,697,106,975,687,818,140,316,529,553,495,502,991,682,980,926,994,187,215,3,317,54,564,296,801,98,201,826,564,555,546,287,383,844,650,939,27,756,636,926,639,174,12,865,963,767,353,552,196,130,627,633,431,151,506,833,673,754,139,847,885,383,313,55,677,922,908,534,115,69,641,685,111,752,959,865,479,323,445,752,390,329,855,290,327,447,693,397,867,438,763,123,428,396,793,5,134,130,951,894,224,306,855,939,47,913,804,909,899,316,498,759,844,217,652,42,518,531,79,93,13,256,161,463,466,208,35,456,932,340,171,141,248,248,249,66,91,53,664,418,523,182,600,405,791,996,707,802,58,592,149,950,164,605", + "296,295,26,156,495,888,211,770,941,105,489,863,287,218,266,885,636,501,902,270,676,115,477,911,357,54,528,514,560,531,399,854,246,478,505,182,325,474,383,622,110,619,566,769,557,268,494,416,124,513,157,759,998,312,63,48,328,321,447,293,308,249,813,327,71,696,428,114,369,484,707,5,350,58,462,965,376,725,539,74,316,279,593,130,85,463,248,944,84,427,925,963,507,367,130,33,205,890,305,235,801,80,981,534,641,214,755,646,846,982,344,489,782,662,356,856,100,149,107,686,857,516,618,413,514,228,505,497,839,363,983,488,779,473,850,335,573,429,433,53,79,664,251,748,859,130,544,928,390,397,698,768,512,481,286,349,351,29,904,327,35,802,901,444,112,992,49,97,533,792,168,692,66,716,106,683,55,290,750,239,227,943,758,81,726,832,605,153,751,458,883,887,964,773,704,699,196,604,177,286,372,448,87,600,868,584,643,582,548,530,28,920,833,929,426,155,739,465,235,840,997,760,850,911,277,2,209,820,791,262,594,431,246,880,209,940,120,128,214,215,93,100,507,554,409,982,791,174,649,798,513,426,162,79,643,443,264,351,712,576,778,208,592,393,139,417,927,38,40,529,654,271,734,515,838,469,239,786,32,75,965,570,293,359,82,522,569,405,680,679,363,832,598,984,982,148,5,90,802,566,447,63,997,472,0,102,701,399,901,415,722,597,740,115,783,644,820,907,246,244,837,509,976,656,813,826,166,886,960,961,186,114,914,474,809,930,811,824,165,909,152,368,626,614,240,765,666,232,698,998,802,207,916,203,284,393,213,96,592,751,634,159,884,656,644,493,962,519,402,728,220,500,437,602,775,488,96,175,860,482,730,804,959,114,753,888,798,618,2,503,262,778,370,526,707,577,766,83,593,401,503,349,706,721,245,596,3,647,158,800,733,802,917,361,260,30,126,223,13,112,811,873,556,35,310,823,229,368,849,767,228,696,784,633,781,220,503,399,15,32,40,429,90,969,31,998,746,150,5,884,803,918,398,139,658,303,850,427,311,114,801,759,108,963,143,238,502,415,610,15,361,549,782,214,666,872,518,718,197,658,400,353,486,764,118,439,859,448,652,697,106,388,693,36,357,912,821,336,805,767,474,134,891,504,57,385,212,629,925,186,600,277,9,792,563,399,932,548,442,569,114,708,204,526,15,98,919,136,294,578,180,22,94,892,920,895,191,444,122,373,70,181,143,3,439,683,254,40,226,525,856,109,350,195,463,84,835,816,606,299,889,235,260,651,477,113,157,569,930,922,681,793,776,795,93,340,310,853,200,149,263,402,564,779,321,9,690,433,966,222,988,635,294,993,871,696,289,644,574,677,523,672,857,148,109,797,995,71,622,905,927,386,41,982,549,543,205,6,519,965,337,376,968,397,565,621,321,355,163,370,965,929,204,173,131,56,609,116,933,669,97,482,706,797,233,781,594,642,858,417,18,636,120,735,75,94,401,37,808,892,227,732,492,450,477,589,589,718,385,84,509,937,939,894,645,216,936,364,398,582,729,623,85,811,374,944,789,139,144,919,147,262,360,290,96,450,209,967,748,695,792,905,118,319,388,42,359,678,823,505,918,712,572,856,603,783,724,485,228,486,886,452,539,654,710,311,342,215,679,200,121,35,490,672,94,486,36,998,103,818,19,268,525,468,443,253,754,83,114,67,665,764,504,699,940,275,677,379,349,73,859,475,568,968,948,32,676,425,155,735,271,264,970,945,288,586,440,180,603,923,535,876,739,100,265,663,92,846,96,461,255,653,402,434,407,491,715,917,241,849,662,379,530,71,592,860,965,497,244,962,228,337,909,132,798,914,277,239,691,348,335,117,168,262,477,115,101,646,242,90,766,733,440,338,769,94,549,492,426,823,895,841,891,491,608,817,874,214,856,73,198,917,926,388,401,39,215,882,276,585,699,851,448,325,781,304,637,112,17,599,216,540,428,533,358,48,207,249,161,396,289,433,345,892,644,830,303,432,590,347,808,280,509,204,859,860,251,524,70,545,626,434,519,632,824,642,256,706,671,293,410,711,774,810,665,884,261,832,494,802,166,326,107,545,361,208,592,472,630,449,979,754,782,309,619,218,308,987,271,416,262,327,301,702,91,104,423,105,583,853,242,368,345,485,240,543,586,392,140,982,234,711,425,879,322,790,450,142,652,142,125,859,694,167,610,591,671,133,494,379,677,272,627,201,903,735,736,816,382,523,495,118,523,23,194,940,471,151,958,371", + "706,719,492,576,653,903,751,252,910,113,240,479,795,173,452,624,214,682,773,36,153,378,411,973,37,839,914,288,550,951,997,144,23,411,640,716,573,696,202,71,270,796,979,320,465,150,199,651,989,495,384,347,567,865,19,914,90,206,638,507,116,989,145,336,772,715,846,466,95,331,698,19,85,942,798,842,302,686,540,680,28,540,165,486,411,710,163,848,647,135,814,362,923,695,233,173,124,856,406,650,131,733,22,205,291,379,571,763,402,867,310,690,319,132,993,193,428,760,518,395,792,481,347,697,32,668,286,719,288,875,784,793,656,47,764,459,229,27,53,946,370,963,374,131,668,996,214,421,198,429,347,927,865,111,67,581,172,35,209,506,521,23,209,35,26,657,269,330,546,434,258,427,382,643,979,917,511,688,197,39,617,846,825,270,622,720,126,172,318,993,25,132,12,787,135,66,822,149,722,524,597,243,680,541,861,337,375,69,277,352,895,557,473,439,32,883,924,260,258,235,133,556,8,41,475,438,57,281,32,390,708,795,851,48,683,262,415,300,665,282,122,525,556,44,794,133,714,691,402,643,264,319,149,381,465,862,540,388,164,640,756,175,859,307,259,967,466,151,850,237,277,478,943,179,419,721,735,572,432,326,87,753,231,510,824,985,41,462,245,874,329,158,860,923,693,46,608,915,624,881,824,986,410,499,102,0,738,375,923,236,179,81,93,615,259,183,938,69,101,558,759,559,936,728,18,327,660,683,21,315,349,483,321,229,248,213,265,126,895,638,967,962,326,216,594,663,575,302,416,947,883,653,526,768,551,343,896,859,919,642,574,355,131,52,886,278,280,516,741,446,407,107,83,589,845,635,796,173,248,292,747,609,289,217,498,743,536,986,401,219,510,463,192,134,96,130,911,447,726,41,342,63,396,78,874,60,145,255,265,483,114,576,764,140,837,682,62,466,613,538,403,865,786,439,237,948,674,27,55,817,655,54,252,946,8,945,183,829,245,567,440,583,475,695,676,655,963,964,631,92,385,156,571,8,632,541,712,744,394,251,834,714,663,758,803,754,985,297,118,478,165,781,738,596,250,300,448,58,824,478,135,92,44,85,269,539,192,457,159,428,891,790,252,389,11,278,703,253,32,948,915,13,998,162,327,695,536,468,907,542,923,612,742,705,294,211,672,523,252,295,9,313,418,273,891,862,141,8,463,835,518,404,472,963,573,10,764,627,921,993,486,796,411,336,610,946,832,690,750,68,43,229,632,634,17,886,646,461,64,981,260,131,347,591,824,904,913,370,120,255,278,935,260,546,727,602,544,510,623,942,569,462,350,442,162,875,853,930,771,106,349,369,958,851,844,622,658,411,180,690,395,256,436,428,925,29,612,175,391,432,881,614,88,700,210,459,560,309,641,591,45,522,145,570,306,280,476,767,536,263,491,976,803,166,269,815,174,882,8,858,458,146,188,994,300,531,244,979,976,17,657,65,457,825,150,652,500,698,94,849,238,743,662,244,623,917,457,750,734,289,528,855,238,58,459,731,732,790,952,444,101,626,715,965,48,522,342,219,248,140,509,528,417,68,185,976,795,662,439,810,350,257,407,748,712,481,87,452,304,335,938,413,819,359,752,440,710,67,574,237,746,771,531,267,468,111,870,679,210,527,36,715,868,867,404,664,173,547,647,767,633,113,638,307,380,321,544,908,847,232,625,102,470,43,334,994,710,821,674,521,774,43,402,64,974,192,421,192,630,639,490,567,756,978,326,87,486,742,421,907,35,155,760,846,23,891,617,798,596,390,746,485,815,83,602,777,151,687,20,707,896,294,339,710,699,197,565,352,889,322,219,190,228,851,744,973,811,959,229,113,854,311,377,802,235,882,717,369,296,48,579,823,165,393,68,159,17,931,535,570,11,289,127,846,604,138,940,65,632,391,740,382,247,958,923,8,412,423,716,381,570,791,139,776,508,951,554,353,497,382,351,243,461,796,320,554,428,511,789,267,573,921,415,954,733,34,558,545,997,905,224,181,130,838,470,822,27,778,344,949,674,204,192,953,495,780,837,278,450,630,779,469,816,30,41,167,116,237,962,917,355,718,721,236,950,540,563,766,645,672,716,778,463,566,780,483,105,765,197,169,635,183,683,521,87,153,105,866,202,802,528,928,208,990,378,395,266,829,940,592,148,896,257,634,329,375,295,336,616,701,26,182,639,123,258,310,658,834,385,96,494,770,894,934,766,97,718,550,125,42,827,636,306,211,716,566,119,557,983,403", + "901,696,982,183,317,710,527,321,526,674,180,711,386,317,915,310,122,327,280,594,761,745,114,510,544,363,528,385,98,485,70,792,62,889,974,479,112,668,523,392,266,485,770,913,97,723,340,277,707,732,344,113,269,230,618,204,994,523,773,515,899,539,697,196,772,386,110,878,189,169,995,305,561,993,390,509,50,299,727,367,680,235,141,434,174,871,212,640,760,23,81,292,787,233,742,755,400,967,194,545,32,754,394,517,18,580,340,493,490,937,864,719,306,696,566,986,96,976,358,722,885,947,933,723,728,900,480,602,920,835,629,611,547,54,656,292,677,489,671,820,758,361,67,246,933,904,421,832,255,30,969,863,59,630,670,35,110,697,65,884,139,372,646,572,899,435,432,628,76,96,677,679,762,262,621,729,556,679,115,942,634,18,46,894,633,87,40,180,94,46,735,331,399,165,668,869,513,86,356,314,742,744,690,547,243,319,139,58,381,737,591,597,685,524,131,898,725,448,462,846,669,965,136,347,649,508,927,480,343,16,447,489,602,747,606,943,599,866,961,280,503,794,630,150,389,176,996,930,903,51,700,548,986,125,394,994,239,657,386,647,85,561,721,540,156,489,175,797,402,817,748,252,141,344,158,291,803,75,141,116,511,922,504,602,242,584,356,595,775,828,242,38,703,494,585,540,391,508,465,564,752,729,187,391,701,738,0,119,368,631,553,26,999,552,551,986,381,40,308,70,374,648,508,770,11,800,43,28,741,690,97,294,76,298,683,27,540,737,200,154,671,305,943,511,678,176,552,40,246,339,673,879,822,339,487,161,41,117,648,841,606,135,105,191,747,424,374,728,535,672,718,178,250,308,219,778,832,696,123,260,473,317,595,469,837,645,474,683,445,755,123,817,983,421,332,99,279,708,486,698,441,114,607,748,412,653,283,269,198,104,320,668,726,204,187,811,619,964,267,248,335,138,665,707,888,399,506,272,489,900,562,69,469,892,793,218,943,799,414,106,976,66,903,204,809,6,799,948,14,322,939,740,724,206,23,658,529,866,955,173,120,989,168,379,718,513,343,970,998,631,214,61,198,838,366,851,971,13,931,572,324,758,605,146,936,270,205,15,276,211,241,542,171,895,520,430,949,465,246,391,695,170,222,207,938,913,729,389,431,559,703,618,883,641,341,365,947,773,474,841,997,894,114,875,413,863,202,641,52,31,105,714,38,217,344,356,623,12,270,778,141,937,372,53,106,533,634,272,832,326,628,676,569,665,801,61,424,409,683,186,94,211,605,23,490,666,726,858,119,978,828,973,124,474,680,63,338,887,218,480,247,391,643,538,402,598,577,699,280,65,247,264,107,373,523,183,766,849,394,395,150,517,823,548,264,96,781,435,334,656,977,890,65,334,408,790,502,228,329,950,20,789,154,496,310,471,688,303,177,358,120,882,568,432,796,519,672,329,522,173,281,656,870,236,854,70,108,859,449,917,499,51,622,855,299,476,790,975,506,894,903,585,73,247,6,261,688,345,672,845,278,364,794,958,531,495,354,233,412,879,267,589,95,214,144,784,302,909,916,987,948,670,778,370,30,589,989,246,614,242,101,156,769,144,288,415,670,295,21,918,551,42,235,337,192,858,262,749,471,789,297,606,479,519,275,770,11,886,727,130,332,402,714,690,780,919,699,387,256,214,811,591,186,245,890,979,41,940,501,868,602,84,762,532,533,69,816,13,842,344,245,734,651,12,732,949,220,502,348,230,513,588,628,262,416,729,353,477,400,684,911,128,703,862,984,861,469,70,250,112,400,504,595,226,988,441,157,545,95,307,551,876,951,490,684,83,503,528,752,513,727,315,362,882,119,330,20,256,596,596,714,516,426,142,496,867,750,761,590,539,194,371,808,70,840,67,483,790,325,516,603,652,293,930,469,759,597,857,496,808,889,251,828,304,345,613,806,723,128,651,643,119,846,474,712,685,580,597,592,988,76,780,330,343,194,101,86,275,942,217,638,255,286,484,482,91,392,52,390,698,485,800,103,369,532,618,239,115,547,851,34,415,105,844,368,146,850,138,754,527,166,305,573,185,442,460,323,38,726,747,702,367,394,909,315,112,266,352,287,138,46,756,949,203,413,310,59,751,706,665,662,171,50,39,151,250,708,750,968,384,907,698,464,1,423,566,4,65,690,151,775,474,161,917,664,743,235,626,194,241,275,567,112,151,469,689,504,990,439,803,66,634,589,555,122,659,327,279,232,359,639,838,395,682,636,527,230,476,73,459", + "155,381,336,930,90,205,769,126,70,566,719,522,817,512,822,512,674,862,489,595,224,98,314,612,56,554,334,399,240,362,813,410,104,774,360,279,511,278,946,939,415,291,351,80,680,928,31,53,840,614,338,144,485,646,833,127,87,773,337,683,527,997,458,464,607,271,584,897,709,650,47,406,272,481,156,344,454,791,64,3,824,287,631,692,645,519,815,471,33,251,500,164,250,562,834,13,57,575,2,168,577,20,963,288,715,703,758,313,13,589,137,177,838,822,556,317,338,14,796,550,858,220,275,676,4,55,181,462,536,326,318,173,929,945,778,507,652,545,12,60,376,713,877,351,631,571,212,223,774,834,770,673,791,869,614,455,906,771,949,38,890,357,856,460,158,695,80,617,507,689,28,199,111,567,843,63,584,388,272,925,106,779,783,732,737,104,249,426,258,420,62,176,150,535,39,645,131,634,31,181,373,292,482,780,838,96,370,620,565,404,12,271,779,486,108,733,961,315,488,750,379,950,506,814,456,882,827,608,128,89,644,348,510,164,616,107,338,76,746,584,573,353,297,66,137,954,485,840,6,654,523,621,337,892,125,734,447,284,462,124,7,925,267,171,691,860,877,903,11,331,512,448,2,391,172,546,412,463,315,412,457,487,135,861,948,14,858,746,96,972,52,801,193,390,550,811,121,479,12,920,509,841,398,991,399,375,119,0,141,781,492,839,969,794,339,867,539,664,225,562,517,166,138,469,874,42,851,286,351,272,517,152,891,403,484,770,508,297,101,286,719,33,773,113,672,712,101,819,32,338,797,445,563,496,294,873,648,115,190,628,871,659,635,340,631,324,225,828,935,889,325,472,979,15,209,817,750,220,62,304,696,33,497,664,404,105,699,683,783,18,926,282,420,434,943,45,609,518,92,531,81,338,522,768,276,959,181,877,830,96,804,87,74,990,100,844,480,147,18,438,431,528,380,533,284,296,120,916,629,378,595,745,839,297,483,886,887,150,214,30,571,973,57,34,312,305,192,246,772,550,231,13,703,244,466,125,183,88,577,338,973,45,103,181,726,908,435,309,72,502,513,851,863,38,964,776,131,18,495,985,837,326,580,223,553,203,669,993,377,849,382,800,833,595,235,908,437,13,671,114,533,96,411,983,697,54,238,187,479,824,76,9,101,902,920,346,425,239,30,160,215,704,160,825,686,190,398,676,503,708,378,852,532,59,811,856,302,549,589,575,586,426,762,79,120,724,276,997,302,886,918,494,470,891,196,508,396,241,695,637,652,684,469,632,692,341,67,866,283,666,70,381,295,936,24,217,919,627,925,607,120,128,67,431,230,581,195,698,93,123,315,270,281,328,749,358,823,330,272,392,272,821,316,932,417,700,747,642,955,672,346,457,363,541,607,916,351,260,464,472,129,573,48,737,352,876,893,854,154,876,189,653,610,867,991,995,158,897,453,480,851,491,590,990,302,443,501,284,125,866,624,201,829,342,284,988,123,774,813,458,787,434,430,489,73,350,645,297,910,296,552,736,771,992,712,760,583,758,463,841,258,484,485,278,642,41,172,324,956,428,283,840,617,286,851,426,69,566,671,291,350,966,463,39,976,817,435,76,617,469,775,584,851,164,92,269,344,367,628,917,186,831,700,279,753,506,51,119,299,540,45,380,422,545,376,81,186,52,88,705,615,296,866,789,895,253,677,784,9,989,122,231,996,145,290,905,827,676,592,409,977,900,244,508,529,306,521,394,70,957,641,817,179,946,549,575,11,841,830,336,625,501,905,372,593,240,227,743,296,891,22,534,888,637,408,736,211,156,492,206,642,662,123,494,382,501,772,670,907,401,452,268,141,643,623,749,799,211,71,145,918,420,220,253,513,507,917,45,307,924,197,636,623,511,127,894,548,501,919,180,419,764,951,162,961,959,254,623,721,554,535,185,543,66,950,678,831,485,628,617,303,947,534,268,889,806,151,591,705,728,414,153,691,448,584,169,716,871,501,70,870,351,295,718,804,998,700,38,14,104,709,15,711,762,307,882,640,92,70,775,388,336,113,364,663,259,981,582,597,244,753,378,220,64,646,959,50,868,985,202,950,861,764,381,305,70,602,481,442,150,314,393,699,369,608,252,183,430,403,994,642,38,558,73,35,207,231,924,743,669,109,808,752,513,184,182,298,886,723,683,223,223,456,938,830,955,244,206,214,15,706,198,934,487,306,894,566,480,44,75,688,62,611,847,425,24,973,858,621,956,660,512,989,742,192,333,832,401,654,394", + "111,341,300,471,734,946,887,333,937,6,210,356,471,504,348,751,647,285,392,685,530,827,20,270,88,585,515,787,177,436,869,122,774,414,675,719,733,882,900,593,270,259,696,196,64,922,45,340,288,960,546,352,710,31,670,98,526,541,618,133,913,132,924,432,120,251,269,912,848,260,283,445,512,815,676,853,591,595,869,204,988,787,49,849,374,888,930,632,392,719,873,581,681,185,248,639,684,28,172,311,442,590,835,598,40,676,982,533,129,941,880,417,880,99,934,288,810,604,477,620,629,78,342,676,67,757,338,480,284,113,937,336,956,871,419,730,71,951,11,284,159,340,511,606,476,751,373,871,105,865,220,621,229,681,86,518,992,36,340,976,978,278,822,506,173,957,496,462,899,542,884,521,532,991,464,284,542,573,280,14,409,105,675,130,107,150,399,338,870,936,888,229,688,734,662,411,846,252,480,904,66,440,955,391,225,877,953,140,181,805,379,330,468,366,771,613,302,694,532,876,138,196,912,272,599,137,665,407,215,916,959,818,542,982,380,804,781,644,414,966,90,151,189,178,222,77,300,710,28,891,252,863,379,531,951,139,252,503,262,23,700,908,21,105,300,379,953,24,727,426,265,35,219,891,32,869,556,2,44,849,31,479,24,388,425,556,476,767,820,58,854,512,915,255,283,728,882,351,665,378,244,909,749,89,901,923,368,141,0,390,426,727,617,300,854,470,2,212,939,415,752,436,104,922,247,582,785,229,418,724,985,942,441,433,232,461,763,165,534,813,632,536,791,510,478,944,179,656,102,117,520,875,248,355,439,772,830,96,630,258,459,784,803,164,935,148,624,669,234,77,621,958,159,110,941,167,963,961,911,484,605,484,901,924,703,458,806,16,616,263,788,739,353,964,939,555,140,300,450,487,534,154,536,280,929,476,761,205,798,513,849,674,402,384,897,754,795,556,965,952,161,945,120,460,374,364,612,318,268,949,957,506,82,60,889,650,558,92,403,235,556,777,97,346,23,414,687,697,27,872,89,420,267,92,113,473,824,134,833,746,927,653,971,368,439,471,965,792,227,914,82,299,56,589,265,221,296,684,778,438,15,23,42,149,552,681,689,947,15,522,30,738,470,993,795,194,869,464,87,41,869,671,779,898,135,277,375,979,410,42,155,970,756,707,656,667,919,776,755,877,336,309,568,575,574,644,894,659,227,775,576,448,78,121,920,247,374,868,843,329,844,706,263,53,494,425,731,938,281,631,291,623,776,330,311,47,123,648,385,654,132,180,353,856,824,972,6,814,682,547,862,308,997,388,518,427,866,127,936,18,477,818,795,233,951,461,359,564,755,889,599,153,388,544,282,374,861,405,147,66,799,646,20,800,50,507,758,717,854,612,226,236,158,34,749,506,196,75,391,232,550,291,867,393,159,292,276,131,521,711,336,334,14,856,33,500,201,748,198,252,499,446,250,231,689,952,903,773,590,71,467,268,937,584,472,641,618,991,931,273,312,471,953,874,859,501,125,447,716,244,519,377,433,881,729,211,61,83,971,376,622,126,841,714,156,498,266,931,934,423,180,30,214,671,993,902,14,805,215,651,672,499,436,386,150,107,510,456,923,51,177,731,466,330,744,282,586,223,831,420,37,253,426,202,449,376,434,773,814,806,698,891,857,646,233,203,854,372,431,224,107,306,634,988,505,239,155,720,944,670,602,961,81,663,243,231,668,753,758,905,406,855,953,155,508,202,276,680,120,241,993,142,142,614,779,201,607,792,857,682,720,262,293,244,424,82,460,952,695,161,54,702,87,370,143,773,754,223,511,306,815,100,467,267,77,25,882,459,266,919,230,236,841,259,323,964,978,876,622,824,400,483,337,859,475,591,482,273,179,126,812,596,390,49,939,76,365,500,126,612,643,425,950,971,743,301,602,921,154,836,160,881,558,85,903,693,820,873,743,202,4,637,270,711,275,165,720,126,67,763,719,45,55,473,650,957,639,592,391,961,266,333,937,808,887,558,574,821,162,880,800,900,345,377,190,353,928,137,264,290,416,688,308,939,89,198,134,975,845,611,938,207,507,864,317,362,241,41,746,239,33,250,737,121,465,707,158,725,58,891,50,786,935,540,386,763,669,406,598,695,933,959,72,969,315,154,224,562,431,455,876,49,169,136,965,966,79,352,775,142,744,441,514,725,446,891,898,2,938,180,388,86,616,440,597,124,854,188,419,689,510,42,893,491,675,861,227,468,962,327,874,141,586,648,354,274,282,590,40,33", + "286,877,246,667,473,117,873,939,608,540,32,627,779,111,437,453,684,694,547,321,997,996,261,278,44,238,753,179,362,356,680,247,893,81,998,751,10,662,583,889,204,26,292,642,837,333,592,217,104,988,89,842,695,693,438,994,926,787,978,148,524,264,968,952,398,17,921,932,449,45,537,10,580,98,700,222,462,897,104,815,437,215,311,42,733,260,396,228,359,185,549,39,177,307,85,288,175,829,652,983,960,790,896,466,86,685,110,746,785,592,19,559,167,839,789,581,659,75,111,130,318,619,840,169,3,881,469,714,107,855,976,380,902,710,899,900,309,828,964,301,662,516,718,520,672,897,876,860,182,54,18,58,724,17,986,606,202,171,500,379,575,510,601,931,787,585,246,131,707,392,716,348,609,810,276,586,482,382,818,481,651,307,334,589,91,52,153,634,726,382,239,973,55,777,815,991,482,221,390,546,911,774,588,156,776,45,30,153,646,153,361,838,59,716,539,11,800,798,697,40,723,354,154,255,53,404,447,453,502,173,688,598,458,500,600,725,153,440,8,775,236,666,504,441,897,392,25,713,862,325,394,131,569,17,343,150,946,968,672,784,511,621,185,967,266,867,450,342,452,814,575,525,626,795,673,317,237,251,38,221,800,146,781,359,98,42,813,903,218,932,535,359,370,783,824,468,832,502,698,444,895,289,258,178,415,236,631,781,390,0,510,942,943,423,831,497,685,990,639,286,372,378,181,176,608,949,452,234,668,613,988,226,213,474,843,93,1000,333,862,174,392,674,783,539,896,961,110,9,908,959,714,128,531,844,214,589,948,320,755,246,811,836,938,633,95,187,808,570,832,393,527,310,908,747,718,142,406,813,283,877,7,331,644,362,110,69,727,611,906,161,471,973,361,252,329,163,23,365,594,724,389,525,448,539,144,926,518,159,581,449,451,71,220,915,544,950,510,809,404,250,279,281,849,931,705,575,923,746,178,879,72,441,240,28,276,10,155,670,102,936,880,530,17,977,875,675,716,228,518,990,744,92,875,852,930,541,125,407,486,459,478,939,15,407,40,797,426,555,29,699,924,239,295,601,236,255,896,494,711,955,578,355,189,58,372,612,662,3,866,664,421,373,490,517,149,689,708,321,943,356,253,235,745,335,39,214,297,323,590,474,18,747,206,758,335,678,233,388,373,102,690,826,840,801,438,817,803,701,405,602,582,498,629,572,31,665,110,716,560,897,938,355,19,342,500,824,418,789,625,473,430,564,121,214,99,875,785,436,687,663,722,843,689,906,428,827,753,848,325,252,942,576,342,299,871,528,306,947,835,623,862,230,136,172,718,541,935,499,37,956,31,327,812,430,778,372,418,845,176,32,800,45,998,27,294,326,847,357,859,621,794,922,832,188,754,594,654,51,272,413,834,31,67,110,541,854,964,998,115,69,712,976,287,630,712,710,93,535,307,952,3,54,171,17,381,319,613,340,473,952,703,926,820,345,832,482,399,191,883,487,15,788,932,227,559,609,51,812,942,756,740,850,633,695,505,388,606,147,537,769,246,803,134,749,250,914,612,723,569,394,446,132,668,180,833,512,947,413,438,449,354,372,672,3,379,144,357,953,859,625,163,81,637,918,587,819,377,221,356,237,139,765,240,870,403,363,616,463,975,183,183,244,624,856,542,253,709,639,420,487,321,975,149,878,79,260,592,938,334,291,80,942,831,845,66,668,792,239,97,511,742,919,358,719,135,621,404,464,966,400,260,316,316,395,819,594,223,902,546,712,604,522,817,856,79,135,134,929,109,864,291,645,603,742,493,135,242,925,530,214,800,148,465,926,268,622,296,160,302,221,191,597,629,796,120,210,166,437,765,865,983,704,902,67,257,777,593,148,703,164,19,168,733,410,72,244,762,41,126,355,226,493,734,255,944,981,500,762,955,102,134,231,16,677,434,826,171,896,13,330,861,464,85,54,43,581,926,609,250,348,941,358,647,820,812,836,987,84,425,768,617,423,220,923,808,454,799,404,16,813,793,903,564,852,269,276,129,708,99,857,776,647,555,914,952,560,723,171,292,323,170,204,292,941,524,529,943,371,60,575,729,640,617,260,503,181,888,868,777,15,458,996,23,498,137,44,407,305,285,576,791,358,443,184,644,746,508,438,669,391,724,908,579,635,430,284,76,202,904,515,617,782,819,880,248,458,945,774,607,545,46,64,58,662,344,879,407,97,907,332,594,600,838,699,248,932,217,658,113,412,130,211,273,392,132,715,398,59,998,763", + "958,30,275,564,599,457,704,937,253,134,484,729,151,840,343,873,625,497,349,732,694,101,561,646,165,769,812,611,209,513,408,91,180,225,396,548,496,475,17,826,496,106,589,796,758,41,92,862,737,185,683,711,538,581,373,660,138,970,964,497,25,515,331,556,765,29,470,636,462,91,481,627,777,458,949,57,659,709,681,210,568,727,508,498,97,158,347,48,942,840,935,207,108,540,888,437,778,361,393,113,606,177,738,522,664,534,414,740,386,143,84,349,906,477,562,122,61,581,98,726,488,226,544,940,743,419,738,767,757,840,449,542,420,518,378,955,693,726,295,138,248,459,182,200,470,790,181,620,458,143,509,910,151,992,545,626,689,264,59,57,766,576,123,318,801,513,659,247,906,653,157,503,535,739,938,427,568,465,504,129,150,298,494,482,783,750,80,460,394,785,238,894,412,362,248,99,435,491,217,911,440,545,918,503,957,659,924,456,843,404,5,432,880,895,125,838,617,961,654,336,865,939,574,678,805,35,152,165,950,1000,294,175,915,154,235,639,469,693,367,235,674,799,200,273,434,41,429,186,174,114,495,682,866,338,892,971,244,436,930,552,524,898,557,601,352,169,589,368,694,161,546,898,68,614,431,185,391,755,418,584,904,241,12,771,791,732,651,553,224,261,110,156,420,345,803,478,914,463,838,231,107,701,461,705,722,179,553,492,426,510,0,453,351,569,885,519,963,699,557,835,349,46,943,649,390,379,897,926,380,271,30,753,445,823,111,130,880,668,720,830,843,267,775,933,564,583,30,96,291,463,311,750,698,334,907,218,216,292,447,564,688,116,750,965,385,153,817,383,557,132,363,985,684,982,637,302,462,597,876,434,32,991,316,506,271,465,712,356,197,477,166,310,918,465,162,153,32,937,406,8,339,865,530,389,462,583,572,811,804,594,309,696,620,768,433,11,899,343,998,803,150,477,827,429,892,986,155,279,941,712,569,595,77,216,496,650,436,436,408,62,337,580,621,693,927,320,534,165,215,988,697,607,610,328,64,744,540,574,701,364,536,688,359,201,252,172,787,499,284,601,64,128,918,283,478,677,345,223,740,846,975,113,821,91,755,929,581,418,387,504,963,315,815,152,534,849,877,98,279,432,200,496,387,143,655,835,957,522,84,776,892,724,307,661,704,545,511,650,344,914,254,577,590,89,408,282,238,643,24,945,543,904,668,898,262,777,542,665,12,665,82,506,768,119,668,242,283,854,618,148,488,884,105,13,842,950,100,437,231,586,786,524,417,276,864,737,913,989,468,944,30,253,823,988,614,56,792,264,806,677,559,812,261,990,687,920,551,189,265,856,206,541,635,86,144,553,327,306,719,636,503,701,561,631,327,445,839,508,454,842,880,949,529,918,867,82,723,18,937,891,745,600,147,457,675,926,906,393,131,126,98,766,312,174,736,166,276,994,430,607,985,805,228,51,702,98,630,312,905,393,78,719,344,874,732,90,208,32,175,55,324,820,586,954,419,787,54,916,202,73,127,66,924,862,517,493,158,196,680,127,883,947,870,724,418,145,215,732,663,969,671,264,399,245,394,664,861,598,249,351,37,40,423,74,931,432,451,263,595,323,869,35,876,588,957,490,146,612,950,440,852,795,831,851,683,831,476,370,254,110,25,170,709,44,881,639,660,259,834,359,818,487,188,440,338,157,882,601,331,805,136,530,185,844,287,629,254,572,753,818,391,404,768,735,959,991,985,712,949,348,551,960,934,606,539,199,175,495,240,238,31,755,222,156,734,71,671,572,758,169,203,59,72,627,335,74,561,176,366,716,122,318,900,138,756,815,925,925,86,447,747,503,161,551,802,525,148,532,461,309,741,90,323,497,232,133,910,349,653,179,702,599,831,120,283,367,643,732,468,866,791,164,259,810,968,730,368,357,542,48,660,345,604,376,711,149,767,895,378,107,90,562,678,21,284,626,147,105,688,618,726,548,289,455,967,722,776,667,387,449,678,538,771,988,459,672,70,64,893,672,123,951,29,888,475,521,787,316,654,735,350,910,289,210,987,597,555,952,256,732,222,122,316,244,288,208,366,901,416,462,266,584,573,548,126,161,341,344,853,946,265,597,135,730,723,101,922,396,782,551,639,541,337,161,520,572,318,562,467,132,432,424,556,501,676,172,843,558,322,902,358,62,821,153,484,783,27,701,746,881,88,426,436,52,355,201,244,619,45,987,421,766,766,887,943,510,423,935,40,125,114,413,572,393,922,350,315,566,362,856", + "119,213,61,731,566,713,803,281,730,164,403,668,867,105,172,930,398,177,574,387,957,984,903,26,120,424,684,258,682,420,454,289,808,473,516,869,403,123,492,197,995,53,104,247,33,687,899,466,945,3,42,150,491,551,333,434,291,271,502,599,965,605,872,129,82,186,125,416,320,391,568,405,872,183,925,532,507,397,56,736,863,891,879,667,539,958,59,348,790,691,792,791,556,938,488,617,288,173,464,762,521,484,36,894,180,632,672,338,75,896,501,708,25,408,540,866,423,200,790,415,706,56,425,549,103,422,145,135,582,692,649,147,852,867,261,175,727,568,529,579,261,234,742,174,419,86,375,297,729,523,992,355,163,233,730,288,19,176,678,237,436,224,998,931,486,94,449,576,447,774,716,243,741,339,632,517,139,118,522,914,87,408,983,931,236,609,382,42,988,392,662,110,511,290,541,236,813,892,440,595,383,105,444,721,187,647,818,824,906,845,166,808,584,723,817,205,448,285,145,133,92,727,639,770,33,264,760,601,960,786,968,280,847,760,586,643,332,426,118,178,760,402,881,120,442,921,573,194,544,242,329,880,64,983,872,591,4,87,491,776,407,796,823,579,959,778,853,669,555,795,784,403,742,881,742,788,768,347,824,442,883,785,84,297,73,340,145,306,772,779,875,560,448,130,709,619,644,969,123,278,172,254,552,133,597,81,26,839,727,942,453,0,20,954,247,461,592,249,274,172,48,727,302,779,164,991,886,847,488,510,398,945,581,712,136,700,127,533,983,884,408,739,231,102,677,911,557,906,321,701,332,968,78,675,598,354,569,911,994,403,846,871,187,42,806,895,843,678,329,759,23,30,347,38,675,769,183,434,420,198,773,842,245,88,286,825,193,602,477,371,180,795,206,78,664,377,23,965,192,713,710,178,717,673,433,713,772,509,112,701,352,300,551,976,868,768,364,52,813,116,231,155,776,19,92,414,713,89,406,11,391,413,955,331,625,883,230,15,431,663,953,648,8,141,471,971,864,515,13,482,914,666,364,714,750,149,526,392,281,657,52,344,343,108,938,567,694,451,344,992,873,81,80,496,407,407,740,361,236,14,454,64,562,860,704,511,148,231,592,703,996,899,100,621,427,760,892,304,834,416,809,462,50,774,32,563,576,525,641,464,250,516,477,796,477,581,184,852,767,657,515,745,871,786,918,631,91,990,760,395,374,637,427,659,587,586,897,673,406,299,497,497,666,938,168,364,668,958,230,557,101,277,282,482,833,905,881,674,59,2,233,742,694,452,388,376,613,111,2,544,886,256,539,827,951,489,470,216,553,652,190,396,84,712,973,323,103,37,922,754,378,867,570,804,864,959,81,421,391,161,132,520,263,408,805,86,723,706,371,250,192,237,939,951,810,187,453,463,119,637,494,945,425,382,940,635,907,231,829,892,344,214,523,588,939,36,966,745,275,694,691,171,612,410,839,958,410,821,969,501,93,610,252,790,486,871,336,498,492,714,172,654,276,169,346,87,594,541,50,560,594,973,27,421,519,27,817,582,544,511,122,142,953,483,735,353,658,635,165,4,830,819,593,796,395,716,632,195,898,151,892,717,833,543,102,442,861,852,140,282,878,266,82,522,148,236,564,458,514,331,995,500,297,504,917,792,648,83,380,409,948,621,293,766,912,548,533,646,150,347,847,836,110,599,567,769,363,240,391,626,44,728,151,675,867,538,792,624,270,153,102,738,826,332,43,732,690,375,762,322,605,59,42,41,477,170,122,468,339,374,233,39,962,956,125,813,919,976,842,74,465,501,487,884,692,367,87,717,550,698,968,862,176,353,921,537,957,442,800,445,86,42,353,14,837,771,66,1,538,875,467,530,571,850,733,316,96,65,867,266,415,338,117,397,213,640,626,397,671,613,671,177,3,313,155,331,50,192,602,485,958,551,950,357,926,327,438,392,512,54,97,103,748,941,867,764,616,762,842,721,76,552,432,989,115,264,493,549,894,457,39,584,89,778,859,377,852,388,954,231,678,624,580,974,994,117,471,5,462,34,805,266,576,441,766,428,171,450,90,764,386,296,627,292,202,851,514,388,636,990,996,686,2,421,760,343,740,907,563,510,431,835,641,771,697,113,493,393,26,374,354,700,997,20,529,813,458,834,842,783,905,131,395,136,882,956,14,988,255,101,390,550,322,592,201,642,692,880,721,893,871,275,385,903,676,37,504,792,724,146,307,997,905,536,168,681,961,349,838,15,536,485,210,319,250,770,626,446,979,793", + "652,227,888,900,508,368,864,864,227,106,29,458,632,424,388,748,34,359,739,601,661,715,27,391,204,271,275,481,305,285,58,824,96,947,118,911,661,326,511,89,427,289,136,176,396,161,330,497,843,105,419,807,205,52,956,844,477,770,947,688,164,741,174,199,590,249,203,568,316,308,487,845,283,925,480,135,283,704,2,229,78,508,165,976,29,889,120,480,42,686,134,741,606,945,615,459,264,410,64,335,723,64,247,522,791,39,306,321,798,37,664,540,76,58,336,919,711,268,72,469,426,693,687,907,268,789,356,596,115,2,605,33,337,568,335,957,947,208,116,347,17,852,829,877,211,760,992,285,747,368,515,323,991,763,268,740,478,986,762,387,642,72,107,471,675,14,450,457,638,292,350,936,602,773,906,606,371,445,113,139,193,710,409,431,166,122,667,151,572,594,713,897,431,273,523,327,212,343,682,640,434,406,863,15,844,157,4,95,475,341,361,131,369,162,484,580,636,594,117,921,559,118,430,851,937,473,341,295,325,5,204,709,692,85,220,801,868,744,539,676,475,328,442,452,257,273,505,759,188,285,976,516,670,423,849,457,269,76,774,344,338,635,969,28,507,116,508,318,232,293,568,368,370,134,20,278,296,938,875,510,673,522,401,131,425,627,210,499,101,297,92,97,246,514,2,244,684,774,36,924,516,764,402,736,740,93,999,969,617,943,351,20,0,543,863,474,565,995,723,895,128,736,985,430,396,89,58,574,858,134,497,309,400,214,814,309,751,103,441,361,23,692,502,252,148,631,851,106,969,400,888,275,753,106,165,437,304,141,874,979,45,664,137,999,73,528,866,802,82,424,225,152,256,193,404,805,828,876,475,418,187,978,766,859,78,133,394,726,838,800,19,103,729,538,523,574,538,286,72,12,190,569,506,68,974,189,182,320,527,395,151,680,50,374,233,419,298,610,8,989,31,574,670,770,237,233,492,926,61,21,467,943,923,602,996,525,904,912,7,899,916,920,658,75,587,151,286,317,488,727,950,81,144,990,788,464,913,740,25,716,551,943,886,868,839,89,567,603,253,4,71,293,845,245,261,938,620,809,204,491,878,874,460,500,761,283,106,632,999,212,414,306,308,777,437,393,200,719,618,369,724,247,126,36,210,325,404,897,309,690,22,836,849,149,901,266,355,819,540,121,862,279,777,619,303,619,853,630,867,499,565,806,803,329,211,659,547,505,898,437,445,635,66,764,400,647,574,910,665,426,73,742,957,102,23,808,830,955,732,678,144,797,523,988,543,920,282,401,652,123,747,981,896,117,643,242,857,173,274,167,392,142,89,556,596,993,302,573,347,582,682,895,273,517,449,183,10,856,458,159,678,598,597,347,606,732,947,395,685,446,296,4,88,35,639,10,654,726,805,893,908,430,325,125,259,400,620,570,316,267,260,511,228,674,527,213,816,366,645,157,57,182,385,246,384,664,562,151,16,631,6,244,138,461,45,740,955,963,4,755,863,979,160,390,256,479,395,631,888,984,812,927,494,354,540,565,197,244,959,409,119,704,80,552,24,537,809,736,545,690,110,305,244,125,526,643,384,305,810,917,920,275,543,916,251,817,479,239,68,823,776,980,445,834,182,392,395,318,192,798,207,966,43,256,609,936,63,142,287,284,264,793,861,382,925,185,530,587,956,644,177,195,537,324,940,391,590,425,996,385,502,620,449,695,811,22,32,152,535,861,211,377,707,736,307,89,647,541,625,230,463,603,78,844,337,414,743,546,565,332,810,310,95,822,674,666,235,364,594,353,135,827,427,26,895,150,124,281,17,823,708,716,507,82,89,54,869,292,300,979,53,379,844,996,823,421,508,148,707,682,797,117,568,758,44,668,675,609,940,749,319,248,462,509,815,20,121,78,733,456,816,853,783,273,878,264,909,539,689,650,164,925,468,973,571,236,866,103,497,295,493,131,414,204,145,578,940,298,750,245,266,954,345,407,349,799,342,787,259,89,703,218,169,654,555,187,338,1,969,160,612,954,742,656,636,355,559,988,802,330,895,826,278,557,150,994,427,775,500,883,326,481,521,715,484,297,607,560,598,736,929,166,444,208,562,653,435,862,807,620,782,792,816,178,266,968,118,451,360,913,823,753,809,741,214,207,728,263,404,456,38,126,456,488,343,935,14,479,793,506,902,516,873,775,806,307,392,289,581,987,498,887,111,695,846,616,192,135,29,540,312,460,444,28,173,518,553,850,107,310,257,724,266,896,319,206,913,489,690,356", + "2,394,197,938,383,959,296,383,983,200,679,74,514,424,94,432,74,192,42,750,446,456,65,83,315,195,526,368,461,890,481,921,395,316,918,886,223,151,500,746,357,585,10,21,551,336,962,470,605,677,100,959,325,865,3,58,280,530,143,950,702,578,330,137,170,642,849,702,314,832,576,306,699,925,786,835,367,608,126,623,226,995,616,764,994,686,121,585,640,693,336,308,218,32,305,642,985,114,437,388,958,643,387,731,361,630,219,57,285,520,735,19,533,868,91,315,96,586,138,371,29,555,958,416,132,408,438,23,661,844,110,417,793,519,396,255,249,777,253,302,228,112,188,617,191,476,549,652,661,26,688,246,685,752,881,156,702,555,949,310,193,421,413,806,807,70,904,460,12,527,708,572,635,980,266,303,729,786,359,262,961,790,498,661,632,474,749,240,510,129,586,171,574,102,541,251,640,453,114,853,147,205,315,607,572,254,947,756,709,357,495,152,413,608,355,828,964,486,68,440,589,616,794,396,314,126,926,748,61,898,950,353,418,780,492,130,133,34,213,478,486,8,456,879,160,819,506,707,498,189,489,261,75,382,653,43,760,651,604,505,614,42,669,22,132,894,111,933,875,631,840,693,596,752,978,239,343,31,127,994,713,130,262,804,350,258,653,574,59,18,363,292,259,946,165,596,697,426,158,950,83,458,134,771,115,615,552,794,300,423,569,954,543,0,580,493,677,539,299,221,438,80,976,361,764,518,842,335,915,248,631,832,956,479,335,436,705,578,459,830,211,937,759,689,487,910,526,240,370,164,738,136,908,140,181,481,28,272,420,309,158,131,808,652,144,935,518,870,181,636,471,364,637,241,846,811,725,244,165,604,118,470,127,185,686,29,49,833,948,839,888,633,669,886,858,449,959,941,12,204,804,493,768,565,315,818,135,496,724,27,635,342,797,562,641,951,352,544,748,24,902,343,85,82,382,529,356,179,206,947,208,421,490,494,160,740,308,392,966,347,605,436,373,649,179,510,620,116,925,720,418,758,349,592,13,528,903,203,297,37,686,837,482,92,370,918,365,163,739,949,258,74,384,312,637,940,336,27,263,750,100,738,964,271,267,445,501,870,480,251,772,53,803,745,893,297,50,139,13,424,322,924,742,992,75,988,918,2,284,819,564,218,473,40,772,941,778,996,360,993,606,191,666,376,729,230,72,8,698,578,329,528,268,466,24,541,185,329,30,372,603,218,888,750,534,740,337,840,370,225,701,365,932,638,167,84,594,225,991,275,513,917,413,80,680,365,757,424,374,153,528,587,760,282,964,689,522,242,103,514,989,109,74,591,365,758,636,396,118,470,613,83,302,915,812,37,789,457,330,234,715,456,961,549,750,513,482,895,301,655,555,847,272,872,726,45,781,384,896,556,30,540,143,940,357,79,107,147,859,599,599,941,643,50,885,167,370,467,100,6,882,247,637,623,282,1,920,93,879,9,949,116,603,120,840,747,615,220,4,762,818,53,334,949,736,166,528,113,138,834,61,397,371,321,297,647,880,989,196,298,419,474,582,749,739,423,382,971,295,176,827,33,923,596,609,834,366,356,757,957,391,641,332,202,986,692,59,259,790,858,115,719,242,530,280,97,495,639,726,843,721,726,534,225,724,988,61,715,554,940,778,423,781,817,283,190,751,164,36,485,260,461,798,898,902,703,806,957,854,679,84,625,103,584,138,609,648,244,837,645,802,123,412,800,483,371,19,694,35,583,142,224,448,449,26,62,423,273,812,959,805,962,713,155,786,151,369,855,200,935,408,154,566,970,32,672,244,418,599,24,23,90,675,384,387,605,771,492,394,348,457,613,122,422,101,115,403,431,815,787,859,380,560,567,773,80,574,873,934,595,619,533,556,983,960,721,114,991,811,835,687,745,636,506,714,444,67,901,772,358,108,462,452,448,886,320,305,929,911,5,810,708,100,848,81,330,697,387,182,126,677,667,686,258,345,387,973,560,740,347,984,872,174,930,510,909,657,902,648,283,628,625,108,353,368,880,9,571,925,597,884,511,462,718,413,269,988,227,226,753,900,662,793,951,283,107,690,710,724,196,946,705,518,824,142,953,44,9,276,442,861,65,456,749,527,261,332,977,585,422,866,623,649,701,14,211,713,182,566,464,885,264,429,20,782,855,869,977,99,351,275,990,480,675,536,113,622,794,567,378,981,364,257,747,494,296,9,122,245,649,41,792,243,430,172,246,278,835,301,462,305,451,924,48,590,162,964,327,970,481", + "140,332,978,249,727,930,609,720,527,639,450,245,667,340,319,905,248,336,738,10,218,974,751,194,881,687,677,756,495,268,810,579,261,587,546,72,363,595,413,125,598,811,843,446,218,672,889,178,352,718,854,53,151,224,138,744,796,225,526,561,362,213,485,555,650,241,406,174,881,223,224,767,514,842,599,343,985,417,513,444,307,979,651,383,702,239,57,418,622,504,207,144,945,201,464,234,361,917,338,905,416,923,784,510,933,715,881,470,588,683,449,15,671,750,56,528,190,62,600,934,105,570,804,567,714,344,267,109,638,299,869,886,271,457,984,462,652,230,707,500,345,755,41,794,755,956,844,817,990,31,372,368,826,8,195,624,616,402,876,721,356,18,453,317,783,119,402,229,812,10,539,432,866,150,422,106,29,108,26,260,138,247,983,930,28,983,841,228,106,708,134,801,873,563,366,508,85,143,882,825,698,685,925,916,859,558,286,233,251,599,640,647,695,605,182,773,898,943,365,766,248,652,395,774,741,37,460,479,285,538,685,776,968,216,56,729,355,829,296,607,965,931,328,362,511,653,733,124,237,449,990,881,296,102,447,560,341,10,150,522,626,194,97,999,815,114,901,897,649,702,693,515,528,849,258,692,994,187,192,133,490,773,487,981,435,264,517,251,726,586,679,568,148,524,529,662,635,927,188,197,480,471,413,588,783,259,551,339,854,831,885,247,863,580,0,30,452,26,312,660,224,41,760,299,388,299,928,759,932,716,683,398,744,687,964,942,857,772,151,227,407,685,702,296,451,971,364,417,657,356,502,852,313,711,293,105,510,344,391,27,51,691,3,231,44,798,891,293,677,445,691,137,166,269,388,355,503,866,373,383,303,175,851,368,470,462,803,684,186,578,433,419,200,697,892,967,495,464,183,473,418,647,945,761,66,459,470,688,219,532,131,802,3,810,769,414,325,165,603,787,346,325,458,228,425,896,498,812,450,216,17,574,539,963,850,109,872,495,39,222,654,427,993,39,478,900,472,207,135,796,639,492,190,449,574,525,345,271,666,904,67,641,950,943,92,483,32,976,784,423,881,763,237,142,640,119,304,108,898,557,540,107,386,879,948,549,18,417,701,128,739,181,965,561,620,61,905,949,47,866,294,124,905,700,763,994,45,124,941,41,462,878,373,333,226,524,919,506,865,344,711,106,841,181,800,706,658,670,611,515,823,669,679,600,778,203,725,469,158,160,438,585,716,376,77,280,991,365,986,569,101,950,106,950,93,915,116,405,492,307,30,924,779,166,921,231,483,811,313,259,225,939,346,140,750,356,479,693,30,82,49,625,818,652,70,833,701,675,632,532,527,987,898,341,99,19,224,173,900,602,500,911,723,24,99,64,772,609,327,576,399,385,934,220,236,312,41,171,513,690,435,454,865,118,371,262,203,371,844,753,827,873,595,335,60,478,463,221,140,39,688,223,249,196,546,229,606,739,149,600,760,120,873,731,868,50,59,910,320,944,925,205,33,523,877,808,412,680,4,721,92,714,802,830,975,787,76,950,471,610,355,306,353,670,483,341,252,814,220,430,660,592,365,942,391,13,749,150,352,392,291,436,277,722,812,433,894,923,150,834,482,218,517,266,983,917,37,820,878,513,810,783,371,803,615,415,532,740,281,475,36,82,962,594,759,71,87,924,346,793,486,878,364,334,848,199,283,877,543,192,608,853,700,506,51,457,468,57,544,685,780,750,215,93,41,256,812,538,607,906,274,509,836,396,486,870,427,200,889,633,489,106,52,909,913,272,574,888,440,872,524,696,183,253,365,867,40,923,35,314,933,218,200,644,405,445,976,201,670,382,469,352,379,276,376,408,880,442,482,136,437,577,849,872,973,315,837,856,495,309,895,100,691,825,299,557,593,379,767,727,208,99,7,2,706,252,915,583,105,987,33,872,810,971,234,684,488,985,157,37,926,748,396,809,306,762,435,62,734,658,245,478,433,99,773,708,958,933,458,372,179,786,856,236,166,437,849,856,633,146,815,136,606,102,614,721,628,497,902,635,814,972,816,178,158,974,63,949,588,434,76,329,349,193,879,763,143,851,409,792,241,248,285,359,573,113,514,174,653,83,776,125,998,518,966,921,587,747,468,634,112,687,180,730,298,570,355,55,279,875,141,618,906,597,926,14,110,782,758,316,566,84,103,94,545,847,589,1000,451,382,953,886,960,176,995,939,166,357,677,991,605,470,736,862,621,45,449,735,680,405,76,637,170,526,4,495,633,386,857,16", + "248,421,191,300,957,361,396,204,889,839,658,311,356,847,56,132,555,568,126,410,143,452,393,310,333,854,279,381,921,947,735,532,602,191,511,497,519,620,983,365,855,219,833,610,715,688,10,612,239,699,202,426,542,114,644,620,947,1000,805,194,778,675,403,499,441,320,957,640,675,96,881,994,269,695,728,678,137,521,728,63,516,444,402,521,879,368,561,768,99,387,865,157,961,482,486,434,692,555,413,746,706,401,684,855,700,103,150,583,389,474,523,978,487,12,661,759,964,274,645,695,273,673,182,207,554,328,811,255,924,640,369,997,289,532,143,303,654,113,683,237,502,157,650,548,111,141,361,194,606,568,103,774,1000,424,385,770,935,305,406,510,760,443,772,382,740,104,992,145,618,86,68,586,500,557,204,251,150,210,229,920,352,93,507,692,899,482,990,964,24,766,877,954,329,513,272,384,540,148,438,209,799,709,75,131,773,501,710,101,940,922,745,354,644,688,888,797,863,317,270,251,109,840,26,838,651,151,536,812,838,27,792,491,234,369,929,6,301,162,426,350,510,692,791,82,455,764,416,1,305,908,344,319,235,670,711,939,812,573,984,381,874,197,556,675,784,772,37,101,727,576,601,842,817,534,692,212,971,891,424,200,865,631,512,859,683,274,570,808,448,449,616,876,817,650,71,347,657,647,404,908,289,340,833,730,644,183,986,867,470,497,519,461,474,493,30,0,360,510,992,816,192,293,77,336,691,481,495,522,54,154,371,851,415,448,629,200,87,270,596,756,353,867,178,96,368,837,537,84,692,744,99,849,791,681,365,436,982,173,290,946,243,35,711,312,341,358,683,494,655,578,68,804,421,393,102,348,234,805,243,578,64,320,391,742,563,409,726,507,835,698,596,807,131,276,683,278,964,235,598,24,773,824,456,696,95,878,558,866,949,745,94,622,577,835,563,795,450,650,294,702,275,815,767,639,79,488,278,733,595,857,925,649,29,999,802,513,278,227,638,270,967,989,694,862,333,284,790,764,989,610,298,457,819,811,491,107,433,864,767,935,761,936,521,882,984,430,19,621,827,275,231,190,409,417,874,683,657,205,114,719,243,483,866,785,944,686,535,177,946,130,525,194,103,803,648,991,671,603,353,392,381,215,850,39,637,203,282,984,115,221,511,969,137,527,503,240,190,441,357,938,834,212,714,227,851,60,858,509,511,727,545,80,663,558,993,117,249,677,945,312,930,237,715,815,725,688,943,676,234,486,786,94,479,267,858,568,301,122,940,480,381,12,494,574,658,476,665,368,740,943,276,745,381,850,446,99,15,561,937,830,85,574,484,906,130,599,85,632,729,343,590,988,724,374,59,126,810,441,802,80,850,941,28,664,939,103,654,979,811,611,515,312,656,175,384,992,578,741,788,425,405,640,333,636,348,889,231,733,436,846,102,75,98,630,636,306,169,887,826,759,935,579,122,326,562,15,41,897,191,782,24,539,907,299,130,919,996,462,460,24,541,658,775,953,602,419,976,722,785,800,88,959,621,450,344,431,477,662,724,980,299,319,645,354,235,628,916,346,839,312,604,98,726,929,461,289,283,107,948,223,229,577,334,967,663,994,95,657,162,621,506,582,202,285,450,678,562,251,975,534,395,679,575,582,770,674,561,712,402,991,272,844,511,308,921,850,817,533,405,238,952,454,528,379,543,597,590,887,36,171,113,539,57,550,45,891,85,528,768,628,234,600,144,481,949,345,348,50,534,186,921,846,73,916,543,416,56,823,934,476,568,167,636,802,126,712,902,304,89,941,240,366,319,18,414,405,323,431,732,128,561,817,681,542,394,513,704,9,433,575,747,782,921,529,936,166,828,587,904,150,134,732,172,668,179,569,856,863,49,852,409,379,711,457,922,908,37,215,32,268,571,447,626,856,234,270,71,950,634,787,316,509,866,339,99,767,597,747,649,779,191,495,359,81,319,45,654,707,593,1,950,956,623,611,176,446,299,340,34,351,633,322,423,298,72,709,437,893,668,371,893,729,34,86,431,132,113,75,790,487,380,487,344,65,224,438,806,379,756,523,313,473,364,481,617,104,331,488,947,508,313,455,293,329,368,339,664,966,102,869,233,558,847,270,912,572,512,813,925,956,445,154,719,789,986,639,736,63,803,508,231,400,170,460,484,49,142,321,495,801,763,699,693,239,958,297,766,857,500,702,957,849,655,300,56,808,429,756,604,766,46,774,115,277,384,678,734,466,401,731,456,836,807,61,119,820,732,103,821,297", + "809,924,448,542,237,614,229,137,952,382,80,369,151,438,869,849,429,63,940,432,15,902,735,299,577,255,248,364,581,852,377,971,508,139,493,764,84,305,739,958,556,968,118,156,718,647,409,451,469,87,457,45,983,224,295,381,87,697,615,587,159,202,856,612,238,836,663,533,226,530,34,321,414,161,98,646,842,8,689,889,272,994,181,683,754,517,389,892,897,253,314,705,621,948,146,889,315,678,289,929,361,741,819,693,478,113,287,225,679,697,809,699,291,75,435,524,96,249,987,958,665,158,176,917,48,330,989,2,591,532,513,556,380,737,348,481,152,703,653,294,90,949,345,610,164,769,699,631,936,374,336,610,992,839,880,241,220,869,357,347,618,926,817,105,226,934,772,949,752,982,683,497,544,677,378,409,525,297,845,433,227,261,824,205,965,840,251,209,195,5,639,116,501,579,580,126,625,175,380,161,614,148,157,842,119,372,271,431,797,4,248,297,327,525,415,703,353,868,902,736,215,881,13,667,851,212,712,825,28,1,875,168,422,631,975,62,563,679,283,258,313,289,8,766,426,638,975,307,144,548,445,348,338,746,555,880,979,617,541,176,677,639,418,389,853,796,253,918,924,968,774,32,475,89,459,468,804,13,122,316,554,484,811,581,715,724,927,319,592,404,843,231,97,342,580,416,254,170,904,135,5,678,52,269,820,938,381,539,2,685,963,592,565,677,452,360,0,848,993,981,996,405,309,967,172,393,914,30,581,828,953,788,387,929,615,477,611,851,248,194,942,674,291,371,314,828,371,225,97,193,176,365,383,751,172,144,32,167,236,853,201,905,398,538,577,563,61,397,552,928,215,674,118,767,949,157,874,653,54,917,781,16,74,918,862,87,505,812,582,380,59,294,375,413,872,808,618,39,400,373,14,305,139,495,362,527,187,730,65,805,269,381,665,612,351,938,445,906,467,758,454,261,801,473,457,469,225,655,914,562,813,349,935,244,58,509,315,850,475,845,422,922,661,150,909,538,648,845,532,798,677,452,374,109,590,152,356,247,741,569,40,132,702,246,307,602,170,764,748,755,289,530,925,735,743,995,77,627,971,883,18,862,595,834,269,861,730,586,610,393,121,737,726,981,871,662,744,316,262,781,215,648,306,635,344,771,405,141,189,440,538,155,185,174,585,846,470,270,710,322,269,758,169,840,561,915,584,74,587,966,411,475,704,572,923,55,424,775,116,883,392,540,840,43,884,820,980,137,363,17,813,486,60,357,681,939,215,2,63,653,448,58,907,333,523,370,782,96,92,259,343,676,670,399,537,24,32,236,479,922,471,811,662,5,767,290,423,291,693,483,356,693,665,584,524,90,112,62,927,386,999,515,513,649,345,792,215,403,742,715,510,495,816,584,796,383,246,18,514,200,406,114,731,470,906,326,966,46,14,49,468,55,529,664,725,732,295,150,234,822,6,642,554,880,455,407,75,868,870,607,431,50,791,662,889,93,739,151,340,542,641,413,541,662,555,521,142,191,665,226,979,847,169,950,230,379,815,728,871,734,852,420,366,545,990,597,643,517,553,996,45,615,223,989,467,749,30,886,471,842,638,512,93,862,125,23,381,937,784,321,477,394,787,400,921,68,707,586,117,325,96,201,456,43,125,619,400,991,232,682,931,166,682,734,284,941,856,896,781,660,44,519,534,577,288,12,263,37,232,957,220,714,87,800,305,313,637,968,997,450,784,978,225,158,46,855,657,8,703,179,831,135,169,107,647,584,554,629,912,608,227,63,741,328,142,203,835,440,431,474,874,744,222,814,279,597,818,601,281,384,942,738,276,704,853,880,634,996,741,759,130,436,548,95,230,982,123,253,27,433,22,665,547,410,141,417,849,762,731,699,998,773,738,940,929,113,836,63,549,37,286,173,111,73,446,487,690,701,318,658,198,44,246,1,127,869,605,697,120,325,414,82,209,465,210,389,955,193,247,360,495,191,221,282,365,129,380,394,895,632,792,186,77,806,258,451,534,867,582,28,693,801,153,32,64,498,20,560,586,738,557,678,542,542,996,540,112,222,388,51,395,59,163,93,620,834,477,149,104,732,626,235,837,742,78,999,366,235,38,197,208,310,828,533,267,518,670,138,782,558,314,583,363,304,676,380,844,436,88,833,111,515,714,245,225,164,213,955,496,626,534,898,524,542,418,594,721,61,250,985,789,830,926,326,670,827,207,105,443,544,330,108,669,977,410,435,102,110,274,404,446,363,793,402,971,894,166,531,605,974", + "475,385,747,745,607,446,670,198,220,227,891,780,152,403,596,674,577,293,601,792,421,862,572,164,663,490,853,425,61,555,813,379,643,512,64,572,579,241,188,4,395,572,679,8,547,973,517,304,269,721,218,819,674,62,442,715,432,714,315,297,859,63,130,612,995,624,995,189,92,187,492,6,894,274,992,130,473,605,816,835,556,31,47,79,789,804,599,278,919,933,866,770,30,67,129,944,887,358,377,93,768,220,541,405,631,281,927,58,598,131,178,928,773,91,874,940,757,948,662,867,691,350,366,294,856,577,612,893,432,834,591,209,600,144,264,824,32,553,929,564,547,317,422,43,662,872,388,9,182,607,683,766,541,477,120,212,310,685,622,871,260,879,608,736,616,810,993,411,639,331,561,712,14,208,172,935,285,303,389,376,542,392,326,520,710,908,187,920,859,309,910,656,69,916,123,498,462,753,626,277,899,157,195,383,625,825,735,695,941,289,140,421,608,728,769,970,928,445,944,26,142,380,41,631,300,758,761,441,193,818,46,602,284,518,646,982,805,701,34,485,287,7,651,882,768,814,886,259,456,745,807,92,400,14,932,745,902,656,234,907,878,386,553,822,42,299,727,880,724,360,79,166,365,676,873,443,527,786,534,458,969,437,231,124,593,405,295,568,754,296,321,983,358,887,195,281,539,50,944,101,691,448,467,969,907,69,40,664,212,990,699,249,995,539,26,510,848,0,700,333,670,44,430,69,869,645,455,667,707,883,246,307,778,585,192,885,316,40,501,212,744,383,135,386,44,9,348,139,686,741,326,45,628,395,278,566,406,514,953,674,56,437,434,200,804,94,572,669,483,355,898,656,390,792,134,598,134,920,83,415,418,563,448,635,74,726,301,205,554,141,462,735,567,750,99,110,456,103,104,530,481,336,364,546,853,189,980,601,642,986,701,569,975,489,387,598,360,153,739,493,997,493,51,723,67,313,973,988,852,338,500,20,237,462,389,162,476,653,219,700,15,127,804,128,772,929,102,692,83,19,436,370,447,406,433,409,574,610,1,314,690,712,562,353,732,219,889,117,271,719,354,885,432,726,542,52,873,543,345,937,223,96,676,455,228,42,210,333,225,896,753,788,923,997,50,256,560,926,619,78,594,331,870,218,298,285,987,394,336,860,914,53,707,194,426,244,12,887,876,988,734,975,29,554,49,892,129,503,751,247,297,159,618,208,504,450,944,24,444,715,281,174,854,971,150,385,834,263,461,615,864,545,936,581,785,162,46,426,368,554,684,713,999,927,821,384,765,894,332,336,592,748,85,147,579,946,966,286,734,497,576,85,424,589,716,364,86,36,809,901,571,631,28,850,157,936,212,181,388,649,741,281,194,88,108,44,321,358,188,505,96,820,108,529,427,401,841,870,480,508,84,801,124,991,699,660,424,284,359,667,700,282,282,101,230,321,109,465,950,933,290,245,410,676,477,3,530,828,664,486,59,104,919,695,271,669,406,749,32,855,491,94,591,226,864,318,142,603,875,514,659,449,417,306,961,886,229,433,994,88,908,395,803,885,407,372,323,721,225,383,735,839,497,999,489,47,405,230,365,364,868,151,407,217,30,913,717,873,393,939,492,575,982,625,835,415,103,308,239,927,368,178,676,298,204,618,622,852,374,852,424,321,955,835,197,753,543,254,119,245,420,159,847,517,236,232,540,876,45,117,623,488,449,800,802,242,453,352,949,875,708,45,476,692,68,277,419,181,763,77,154,296,980,337,878,61,718,200,328,707,129,608,539,698,414,190,113,350,705,603,578,444,34,259,308,981,418,932,462,478,139,687,984,946,658,694,306,351,541,877,229,138,935,794,788,478,996,849,226,451,913,516,345,627,313,811,333,393,970,129,337,218,395,350,713,712,226,989,534,493,591,372,550,950,419,366,993,81,241,287,348,25,786,858,422,508,591,707,67,943,852,316,103,444,23,191,259,190,464,317,778,951,558,732,676,848,29,209,436,695,753,228,307,906,831,541,130,669,722,732,241,611,49,463,841,691,303,515,315,847,599,231,876,828,606,673,36,881,464,252,491,199,737,456,999,757,98,913,393,374,543,368,846,414,840,86,484,657,234,69,195,441,169,187,267,180,856,140,969,164,409,782,891,537,676,122,902,80,472,95,715,411,589,823,382,136,278,141,387,911,850,374,969,856,312,620,59,238,602,169,933,812,867,499,219,20,37,221,800,254,757,517,578,914,739,824,140,41,206,185,966,162,718,961,652,842,155,976,623,188", + "752,405,975,24,595,575,895,413,890,91,54,68,320,74,183,454,64,73,425,493,541,267,419,541,840,906,877,546,427,176,644,729,909,728,917,907,785,322,665,252,561,22,32,22,741,201,48,114,609,999,412,844,589,586,130,365,801,579,701,526,728,868,397,846,993,809,980,317,390,104,912,600,250,917,978,292,879,711,874,658,753,620,259,853,387,792,618,380,197,997,842,261,736,352,70,456,935,355,139,528,100,806,9,901,399,155,667,605,782,904,159,821,573,521,849,637,862,146,178,84,259,568,787,18,120,896,888,113,629,296,290,322,824,907,373,284,980,933,729,715,530,919,140,907,506,420,70,810,770,617,856,850,244,866,879,271,922,658,298,252,909,748,215,943,383,35,345,406,740,302,476,10,201,62,535,721,693,227,450,456,958,984,170,367,198,483,319,8,236,346,631,834,487,317,607,992,278,72,479,316,728,755,978,645,499,34,44,82,330,51,643,657,121,228,196,199,826,645,643,409,533,819,265,994,955,108,873,874,508,660,415,348,483,861,999,31,113,866,480,618,535,309,166,345,659,626,375,309,739,940,483,708,206,322,646,191,524,268,144,304,687,667,29,556,981,6,934,528,637,87,665,200,727,837,681,116,582,556,895,325,987,273,502,789,373,817,437,438,538,5,734,674,951,560,347,725,295,342,410,482,368,100,884,543,246,101,308,225,939,639,557,274,723,299,312,992,993,700,0,608,768,526,530,858,157,502,450,319,152,750,752,722,163,822,105,970,824,766,650,894,860,580,439,798,648,781,145,234,109,281,564,817,157,70,899,217,690,57,218,564,713,974,986,533,407,82,617,911,623,237,706,118,862,722,579,796,484,380,382,247,479,170,246,481,519,613,719,283,945,720,571,7,968,104,725,725,666,162,902,670,982,842,484,457,398,513,992,562,140,334,825,999,865,791,123,240,188,910,610,529,760,339,182,103,687,792,651,660,116,962,539,860,190,858,452,863,231,539,615,446,477,740,323,622,160,931,770,317,895,67,881,555,137,489,75,427,737,556,609,879,482,877,22,760,75,733,633,634,227,248,648,907,253,508,382,933,522,435,27,3,369,440,538,888,272,515,102,623,39,605,398,651,664,893,319,742,878,59,126,421,146,818,416,985,368,999,434,128,658,837,632,64,968,589,959,6,397,185,768,294,492,320,997,297,165,270,914,868,632,100,415,156,22,2,337,411,930,919,119,987,953,743,565,463,348,676,184,33,401,394,856,518,716,803,245,21,138,700,943,148,368,354,409,704,604,892,620,802,708,24,75,204,236,365,465,728,189,260,133,133,411,479,516,332,699,818,797,589,75,94,271,800,29,909,807,715,582,244,634,894,268,269,122,244,327,351,317,503,667,824,543,741,573,691,594,421,681,775,714,194,589,714,311,299,688,770,135,230,810,181,358,995,593,19,150,613,192,173,72,413,566,44,767,716,385,333,120,849,877,283,815,670,244,157,599,776,788,779,903,477,93,815,555,979,322,709,809,485,390,465,693,231,173,762,456,576,732,245,558,685,108,388,317,180,46,863,979,353,32,286,203,559,33,346,375,578,623,75,916,975,677,680,890,410,890,685,571,231,776,752,64,973,513,580,167,915,317,304,30,189,937,644,143,871,32,676,200,504,467,364,825,809,57,48,518,113,545,642,119,250,581,481,919,82,902,693,225,771,790,778,834,760,523,982,153,58,524,565,41,331,696,359,994,914,12,243,902,285,478,375,909,299,561,95,88,393,11,891,110,647,649,334,83,811,659,624,242,487,843,406,554,61,860,518,356,155,348,858,45,425,868,600,482,512,325,413,427,465,621,380,614,237,855,25,852,301,98,511,172,131,421,112,227,835,59,29,616,878,9,986,581,910,768,894,792,626,624,873,216,81,337,468,528,987,90,308,462,877,831,139,507,902,878,725,265,544,34,454,584,745,65,880,246,502,343,138,140,185,790,855,86,775,753,584,173,791,694,211,420,881,650,362,740,641,617,433,955,304,312,421,284,461,345,810,981,821,194,674,891,765,342,691,590,260,47,244,462,168,446,943,53,533,32,239,461,159,502,181,961,949,436,660,555,532,473,600,995,562,761,813,289,836,179,72,251,614,803,890,134,411,905,728,393,90,65,275,420,647,392,723,884,843,37,78,133,37,337,539,496,595,714,169,508,938,346,28,833,529,995,918,257,202,290,523,70,75,970,276,951,341,707,710,5,586,614,6,846,286,101,485,138,276,114,891,752,455,932,817,890,248", + "368,407,182,119,683,234,222,911,762,934,654,689,631,124,333,874,650,776,112,43,640,214,742,328,574,524,341,885,770,593,760,941,185,112,442,124,889,4,438,362,897,275,212,654,70,692,994,277,449,948,680,83,760,674,310,116,403,625,146,847,494,998,245,316,717,629,112,702,585,74,741,110,457,421,456,403,518,519,110,462,486,75,143,40,80,650,970,856,384,842,843,646,278,896,133,653,375,70,197,129,591,558,779,954,935,439,241,708,360,321,948,390,952,455,766,55,321,946,885,937,413,775,747,510,422,850,933,294,277,54,889,363,758,120,291,232,593,257,894,437,189,943,15,485,20,343,412,197,24,44,312,981,361,943,857,526,336,770,890,161,41,775,261,78,367,721,73,340,262,158,576,724,284,253,622,170,892,55,529,622,855,533,235,397,638,632,85,502,795,293,521,41,228,799,839,598,354,570,772,89,444,682,286,462,959,768,895,599,246,734,215,984,212,865,890,821,614,594,101,774,779,110,103,906,617,575,998,129,583,785,470,783,650,4,862,518,265,294,129,520,167,643,60,135,615,308,292,150,66,545,505,666,177,541,203,518,317,512,296,188,303,665,160,650,822,197,203,757,736,366,30,259,442,998,166,790,573,723,654,50,133,270,940,368,2,175,422,380,923,185,233,705,163,347,724,548,204,809,885,98,628,210,264,90,244,558,70,562,415,286,835,172,895,221,660,816,981,333,608,0,982,708,138,74,628,102,716,398,601,704,12,118,693,38,835,52,855,811,958,698,392,397,443,705,539,806,782,236,579,652,565,770,569,615,700,972,473,358,364,964,303,326,828,712,799,384,964,255,355,645,65,468,623,317,403,982,802,807,725,16,635,140,143,107,111,216,14,493,549,24,840,608,120,720,92,641,57,894,519,958,86,46,733,375,904,436,567,427,99,341,534,838,238,200,998,296,425,868,880,217,307,941,612,465,551,123,920,707,854,172,662,480,76,993,842,467,793,855,686,633,322,409,936,879,675,788,224,987,416,304,356,810,745,74,126,591,319,891,956,865,729,163,7,326,519,901,547,385,722,59,235,535,518,802,976,553,929,427,143,176,664,732,663,573,133,837,423,656,453,108,980,672,166,183,247,270,104,842,929,958,774,411,624,281,81,268,690,221,370,902,306,614,147,298,936,193,572,305,326,934,579,902,722,721,136,294,725,863,281,150,488,558,1,890,778,33,577,589,732,210,127,464,56,846,211,615,174,628,172,348,820,52,77,63,865,44,901,798,183,560,426,414,753,457,678,311,113,333,702,527,750,500,543,832,122,626,795,498,819,574,611,639,517,508,361,949,370,810,890,939,468,513,612,721,568,93,422,366,927,788,90,602,48,538,800,577,62,228,222,106,561,7,682,426,831,374,824,587,194,625,319,706,481,664,273,35,103,585,675,960,75,471,287,943,880,174,786,708,249,670,840,314,311,505,58,985,233,531,497,752,202,655,547,474,501,806,190,353,266,398,817,87,814,268,725,146,806,253,592,626,262,621,507,521,327,622,367,208,475,722,613,767,582,591,65,837,472,486,518,559,575,321,185,229,358,537,569,144,211,32,571,68,555,992,346,666,87,754,980,978,162,938,417,852,450,642,795,22,7,113,497,197,199,290,233,484,378,401,451,159,875,261,10,491,97,938,353,696,693,171,561,311,535,289,152,501,696,904,802,149,818,741,324,265,430,102,243,953,208,80,963,703,485,577,523,216,968,628,355,763,28,900,467,523,129,141,108,130,158,743,185,719,386,861,451,492,764,502,685,80,92,483,780,207,758,547,557,671,208,975,321,725,266,875,377,542,876,200,474,342,691,575,258,933,291,945,703,769,695,916,280,545,749,122,109,858,951,116,193,757,747,101,456,443,433,592,146,433,310,187,418,597,788,350,612,701,800,996,863,295,560,50,867,264,529,971,645,687,404,71,199,40,464,350,852,6,458,564,574,864,11,516,935,568,519,554,444,586,454,25,314,447,241,482,699,328,880,37,520,758,832,401,110,309,104,7,983,755,563,584,166,249,760,260,888,736,813,893,656,590,525,984,390,821,730,218,632,797,918,712,794,114,203,430,482,223,292,55,859,763,984,963,734,462,650,566,428,677,36,932,390,723,559,573,932,781,498,255,705,190,442,489,918,209,245,901,339,529,740,309,600,69,785,693,819,247,440,149,966,308,494,297,143,68,165,174,54,540,709,272,294,336,466,760,925,235,812,18,484,778,739,213,504,67,646,904,449,21,90,960", + "924,486,972,41,954,875,739,21,86,918,653,124,943,609,734,793,671,317,244,51,306,44,6,277,941,669,419,894,238,793,275,48,854,608,979,971,362,917,223,627,330,873,789,28,552,176,932,435,107,427,200,523,476,363,539,438,831,167,610,506,473,534,894,665,610,538,342,883,189,95,936,174,44,318,837,163,240,48,11,369,727,386,638,900,303,590,49,580,996,157,868,113,882,395,487,757,337,623,743,907,206,23,255,625,339,222,256,500,634,156,358,867,338,747,619,989,426,856,953,393,37,154,76,719,509,774,716,500,237,106,640,986,976,192,166,273,24,515,479,424,115,437,324,546,565,221,150,865,694,319,3,769,952,569,182,588,604,528,552,265,65,760,716,147,761,97,887,215,133,383,146,169,832,168,919,520,208,833,830,79,382,171,194,35,67,444,57,326,977,77,131,411,149,740,167,120,707,988,785,860,602,268,186,677,694,28,534,255,970,628,544,169,986,540,7,794,514,824,477,140,648,658,880,628,404,706,757,356,977,639,823,488,573,512,823,697,72,211,955,743,640,112,282,798,430,74,450,406,955,408,521,521,737,386,528,576,83,761,951,325,252,520,351,392,639,873,178,221,872,164,774,649,706,100,937,710,905,919,148,187,149,414,446,145,824,170,492,163,518,622,532,869,76,30,79,566,321,926,859,262,315,107,528,212,837,759,374,517,752,372,349,48,128,438,224,192,996,670,768,982,0,888,15,47,336,318,450,436,350,937,6,202,93,100,871,795,675,766,86,855,969,152,291,927,904,246,465,592,157,381,574,561,254,325,31,324,760,917,5,224,378,162,232,51,323,354,277,10,935,338,44,281,395,534,591,526,753,217,748,137,727,405,434,689,609,541,928,647,562,122,658,197,823,726,828,475,595,863,207,998,66,540,535,599,154,101,69,93,82,213,236,213,396,809,771,748,580,39,243,542,962,894,144,31,269,925,120,513,168,167,397,622,611,60,167,492,310,568,320,66,20,114,448,782,16,784,232,468,558,829,696,582,467,777,749,608,802,299,716,975,162,758,133,756,576,612,404,144,681,618,971,381,121,859,445,837,588,505,686,808,382,799,991,274,389,86,47,186,61,861,386,803,189,3,379,226,535,723,550,89,624,382,52,572,653,399,985,425,63,169,185,273,890,37,410,765,207,731,17,516,773,475,854,259,214,255,2,437,932,289,360,88,562,539,821,179,643,843,202,387,206,879,184,714,49,295,560,975,186,212,970,835,849,211,861,995,104,855,930,933,126,768,310,641,508,854,175,332,56,509,474,34,447,723,256,66,111,39,468,578,964,369,375,117,152,581,15,943,215,779,363,165,504,915,828,669,839,322,535,328,19,334,795,422,894,997,257,614,489,923,763,670,989,979,764,348,39,20,784,319,931,512,206,630,706,148,405,530,395,999,323,929,519,355,73,913,839,160,628,485,530,176,524,743,158,117,93,301,595,938,140,282,272,724,546,428,553,946,298,929,916,36,639,211,853,611,420,83,470,928,714,421,126,491,933,310,261,282,980,439,87,785,883,478,560,754,200,656,339,669,224,234,184,974,435,354,935,118,214,277,513,196,36,810,630,973,505,483,803,576,354,581,269,672,587,614,727,638,493,292,221,348,887,88,717,717,196,758,5,665,776,925,113,819,59,127,853,22,375,43,313,579,384,657,322,793,346,961,972,743,371,869,767,948,627,577,977,523,295,448,2,648,531,929,59,38,246,298,924,540,33,453,740,452,125,592,389,450,231,246,858,54,210,193,654,792,339,930,559,232,991,756,395,199,168,891,828,456,315,562,621,553,297,168,541,362,382,742,763,194,574,393,688,854,307,236,229,441,925,781,798,725,56,872,784,997,847,73,175,297,32,498,286,913,452,597,428,589,579,369,795,541,719,524,777,734,929,35,914,815,928,523,80,476,827,685,332,404,407,861,573,801,592,453,808,718,917,532,293,795,443,175,574,360,346,370,777,818,693,195,972,609,867,9,497,479,238,323,919,961,448,249,515,583,957,23,41,971,119,42,327,4,597,200,398,755,293,962,65,372,811,13,933,254,161,820,484,107,23,314,915,214,599,686,355,578,382,802,396,516,132,834,251,246,824,541,518,345,92,862,721,243,238,711,359,349,440,669,277,661,965,122,72,410,495,428,870,176,541,9,744,669,716,520,223,584,886,278,262,720,367,581,871,403,972,414,645,340,317,922,686,893,894,116,841,29,830,62,323,892,257,1000,482,942,308,111,774,819,537,639", + "108,681,469,486,325,264,438,306,788,362,725,95,801,54,948,50,435,127,862,654,439,637,459,228,564,865,651,869,243,777,212,115,944,201,240,598,948,295,228,158,305,128,501,225,866,825,850,96,817,170,102,892,569,171,568,332,802,716,806,452,893,143,808,64,564,552,783,126,897,940,971,812,987,688,687,195,508,58,507,618,877,7,821,310,165,837,172,360,181,943,328,82,448,667,621,440,76,433,171,100,113,589,287,2,300,302,576,48,27,352,375,541,987,695,314,642,518,837,662,829,969,476,903,424,483,423,996,967,590,906,512,466,25,510,367,953,366,895,749,775,535,876,358,325,882,224,965,495,24,288,851,465,165,954,801,97,290,788,278,595,223,768,499,276,965,685,419,803,158,260,427,426,656,724,20,868,437,275,770,465,606,259,576,984,144,895,887,548,599,115,379,175,377,717,835,743,311,396,106,826,98,238,771,546,951,527,423,132,822,38,22,396,471,19,617,480,661,746,216,351,224,996,592,819,24,563,844,990,697,99,947,635,522,288,619,249,99,347,274,230,451,716,938,747,539,723,439,730,456,677,852,267,832,239,801,893,206,850,953,317,191,447,883,280,854,730,974,4,15,882,676,556,989,631,193,795,620,538,216,656,259,32,551,561,99,546,750,8,37,787,100,763,863,60,316,625,952,26,622,961,274,578,392,495,509,559,648,166,436,378,46,727,736,80,41,293,405,44,526,708,888,0,939,186,442,295,385,675,285,723,439,183,491,230,216,972,941,185,41,263,265,583,483,825,618,227,858,329,430,946,515,130,952,404,332,30,219,58,988,18,897,638,364,789,979,934,570,952,241,930,460,502,593,731,992,974,811,400,611,538,610,928,110,108,143,694,278,917,333,7,798,337,481,582,617,497,992,372,960,712,749,248,656,997,707,898,30,692,603,866,424,118,786,361,20,988,135,311,757,513,417,839,326,716,741,951,201,564,562,5,319,101,186,500,391,183,620,557,134,54,905,830,777,571,706,322,949,46,234,773,702,516,64,442,294,340,507,706,755,190,621,357,44,971,709,766,481,208,591,545,612,536,168,153,603,210,522,343,300,104,919,276,885,695,664,796,298,77,662,22,155,198,692,199,746,810,790,537,66,570,736,27,682,491,735,550,135,253,668,178,988,974,664,796,538,492,996,540,662,801,592,975,137,404,354,875,446,900,947,234,18,646,290,982,223,548,594,946,806,17,937,220,259,549,196,449,491,12,387,965,504,928,232,901,692,459,589,48,812,769,397,654,586,499,528,621,973,508,270,169,774,515,548,254,115,900,48,656,501,180,815,313,149,503,32,413,160,468,582,179,189,402,971,158,811,373,562,445,138,611,147,138,740,440,725,122,463,948,531,108,978,921,58,941,445,579,430,666,65,954,114,998,120,617,777,655,878,274,559,628,883,45,287,514,415,181,73,620,507,93,880,559,435,605,30,899,936,306,629,52,17,524,294,378,531,163,491,733,139,275,91,94,557,182,703,35,588,78,372,357,727,29,197,593,470,736,272,990,378,106,145,526,300,789,791,167,686,635,482,858,13,334,71,572,416,5,66,894,784,679,201,710,738,425,905,29,801,194,146,33,968,94,81,403,457,723,730,769,558,172,336,292,359,825,313,359,530,248,21,476,732,25,196,12,539,609,202,486,691,947,78,989,20,323,617,516,718,601,348,286,166,644,696,22,464,186,548,759,653,125,408,91,2,169,701,548,741,304,262,792,724,553,210,18,696,442,913,488,590,136,355,979,705,864,348,181,973,959,240,499,355,637,462,824,447,365,653,367,253,117,537,363,377,2,746,627,459,394,822,530,507,322,278,507,936,343,759,520,93,711,418,791,456,764,575,597,428,988,86,731,867,840,895,321,727,184,193,820,149,88,968,980,412,854,727,349,584,272,895,555,90,860,436,398,868,199,434,879,681,756,811,872,55,950,723,816,837,448,870,693,472,259,367,459,341,119,384,768,991,117,817,652,169,513,393,432,342,360,133,906,548,712,116,435,422,576,509,415,20,651,306,835,537,737,674,35,16,970,45,19,747,193,367,683,832,101,947,357,427,967,125,421,937,12,500,14,361,555,162,208,735,198,977,449,946,530,461,370,134,824,591,344,437,781,95,760,767,214,298,966,801,445,248,419,387,683,851,488,278,751,680,566,730,606,725,73,104,644,52,439,436,648,951,190,694,764,353,834,440,895,397,419,497,206,197,264,141,442,101,612,664,911,808,437,820,114,294,519,414,524", + "276,293,986,869,619,620,40,600,359,35,385,512,687,846,47,454,583,6,733,700,39,422,245,688,626,231,363,959,719,636,943,548,532,205,860,352,130,791,724,363,939,57,326,632,472,270,507,955,568,5,123,217,860,808,925,158,221,775,511,104,400,229,629,825,350,731,828,45,747,859,911,278,674,215,202,81,660,190,437,561,454,659,581,775,927,594,730,928,20,66,551,555,186,809,842,725,555,407,882,698,319,358,903,751,326,228,994,156,307,625,493,146,97,826,626,827,220,124,326,994,333,789,934,32,843,927,117,640,181,899,759,729,717,211,687,498,489,725,94,833,524,291,730,205,947,304,543,172,781,441,570,776,875,126,943,286,864,517,78,473,683,304,775,914,80,587,270,177,374,762,617,3,669,361,432,472,450,452,425,15,29,583,742,972,686,495,597,957,122,595,803,972,491,884,271,290,201,557,73,697,949,268,650,128,543,667,372,100,806,465,884,355,361,377,775,436,258,95,49,983,131,851,232,354,825,727,232,21,486,711,742,259,249,752,84,741,220,723,717,210,529,934,39,940,255,64,89,455,344,988,818,268,845,752,941,143,344,55,513,590,284,457,564,967,205,149,77,867,826,441,562,928,203,42,182,215,919,45,261,388,604,37,827,178,503,957,258,931,257,789,565,940,905,561,486,47,714,836,511,696,397,648,863,738,976,936,508,138,104,181,943,302,985,976,760,77,309,430,530,138,15,939,0,193,327,808,279,821,160,356,455,465,489,63,773,525,836,960,19,546,142,626,28,935,927,665,75,244,81,574,225,307,221,689,527,678,44,740,259,268,630,336,382,350,619,234,838,299,807,82,6,428,474,485,132,104,958,327,863,839,595,82,206,20,594,296,428,583,686,224,792,752,892,857,647,535,466,619,985,292,214,179,405,154,216,446,895,259,199,131,597,615,764,831,985,370,388,625,697,968,920,341,544,508,849,255,614,550,410,12,583,641,137,980,269,440,577,846,82,512,721,876,946,405,95,653,260,220,989,565,927,46,822,9,576,123,448,811,943,425,701,583,639,870,672,582,871,81,190,418,142,976,545,963,664,954,510,385,717,403,862,67,847,908,75,93,821,533,771,608,575,442,598,108,716,52,407,532,87,35,558,447,359,441,643,219,452,682,548,687,887,391,412,12,968,567,878,886,916,633,810,723,847,75,216,685,946,4,88,530,482,733,418,164,925,656,480,400,551,494,103,13,626,993,626,685,931,606,63,472,589,176,558,502,871,870,236,940,492,462,825,729,731,234,173,716,922,612,721,304,396,930,388,621,692,335,627,699,757,811,920,766,127,415,919,235,121,385,660,308,739,848,243,174,496,297,405,555,465,65,321,90,799,81,686,944,437,833,877,79,581,891,636,317,182,520,921,315,562,945,938,268,132,251,194,940,917,914,146,317,241,799,52,780,609,281,838,465,136,738,249,722,339,192,481,870,211,193,979,623,427,962,417,602,251,422,574,585,962,968,487,340,721,610,150,809,33,413,90,388,402,554,371,840,565,971,714,241,894,301,220,76,877,639,289,60,894,248,147,645,224,528,906,476,830,972,59,14,648,871,643,664,875,829,545,634,830,490,344,501,623,213,112,327,943,402,397,545,595,959,410,91,138,654,67,409,173,852,982,472,665,368,887,786,698,502,824,393,528,505,797,510,370,721,206,160,318,693,594,321,174,857,413,746,253,690,992,355,209,776,741,34,965,775,897,655,294,646,3,129,672,370,774,87,266,933,998,839,482,659,925,118,896,218,737,949,566,27,891,935,235,201,557,172,236,620,951,692,723,198,217,813,291,281,433,489,425,632,540,158,400,52,21,951,18,783,329,359,666,382,40,623,683,701,680,206,472,127,865,435,354,238,523,209,651,475,925,45,840,297,479,62,305,891,884,979,867,931,836,947,715,331,713,456,934,745,975,77,382,369,805,679,687,173,544,538,68,774,254,13,244,903,477,204,419,66,577,409,733,417,741,805,940,696,675,763,191,958,325,492,515,10,917,535,543,77,346,378,343,883,122,462,971,308,2,339,222,555,637,562,92,134,747,9,486,50,312,904,572,54,425,668,526,516,231,127,142,105,8,380,392,185,766,616,807,747,375,827,102,716,177,72,293,562,851,809,579,805,376,966,693,606,587,639,456,691,965,355,843,599,916,671,653,664,780,143,741,418,111,322,352,908,553,283,796,14,500,322,960,580,601,833,655,886,118,145,114,772,390,581,271,645,195,556,376,529,900,784,512,876", + "472,515,770,298,544,608,256,683,82,509,85,100,314,348,133,780,252,260,905,57,63,334,147,665,76,988,705,473,619,815,673,905,121,716,632,309,493,105,288,263,598,739,374,259,33,716,244,947,439,253,112,748,972,202,176,37,313,63,147,132,916,55,270,118,246,675,448,927,697,382,955,93,165,841,162,135,31,905,262,132,606,281,684,680,770,478,951,893,351,140,462,163,242,125,828,438,348,219,945,669,578,227,913,911,394,199,417,100,69,706,118,519,910,600,27,994,428,810,300,869,958,946,31,676,763,644,867,867,948,434,946,953,204,731,355,225,994,682,855,536,217,28,374,514,978,451,387,107,776,319,684,461,207,209,795,1000,786,860,907,822,945,104,263,718,913,820,27,253,798,253,722,183,397,356,960,250,444,104,251,55,502,781,983,99,58,637,924,777,857,65,712,603,900,198,185,840,675,677,571,566,650,377,79,685,732,703,813,623,75,613,959,293,90,701,328,423,942,490,745,15,581,229,97,432,825,735,716,99,838,601,778,872,315,53,708,968,560,68,658,900,982,446,142,186,262,414,883,499,816,177,688,119,453,545,278,367,821,748,680,413,965,137,760,236,465,466,112,95,928,949,538,120,118,842,499,962,79,712,280,664,641,293,832,192,604,881,178,770,231,871,688,939,898,675,263,391,649,179,857,939,878,442,120,101,656,728,770,469,922,176,649,779,430,361,299,336,967,69,858,74,47,186,193,0,63,796,469,753,449,934,549,720,558,272,428,253,212,380,808,304,560,678,978,668,777,386,678,465,890,242,624,629,328,562,459,952,203,695,621,482,771,230,84,361,255,598,926,864,159,122,21,278,639,970,153,180,854,255,813,44,843,951,81,536,364,727,854,203,92,702,653,683,828,950,547,771,892,947,693,668,95,688,218,994,17,302,226,207,996,941,184,131,637,958,793,159,154,187,351,228,978,356,231,145,166,269,754,122,219,709,620,473,856,976,820,407,628,221,350,126,436,612,529,822,848,83,781,147,257,734,77,11,373,544,355,114,599,379,273,155,56,440,601,373,164,304,301,174,240,198,634,543,74,319,112,821,550,963,638,851,42,220,43,516,843,659,795,260,485,882,857,594,887,339,801,979,221,108,353,139,7,371,447,308,195,319,57,215,978,318,165,859,284,866,524,551,171,428,918,190,640,470,811,279,316,204,685,958,826,565,205,658,432,751,939,275,961,889,447,71,401,18,270,713,160,668,727,883,878,228,881,825,660,622,782,698,440,786,987,815,271,491,449,386,567,591,843,278,463,515,864,402,921,821,825,7,832,739,362,201,651,794,20,352,609,998,198,358,156,422,854,953,563,254,457,537,337,349,785,683,754,716,229,439,815,740,106,228,952,476,357,79,79,790,776,791,76,768,370,369,101,243,153,593,842,351,903,112,160,78,92,96,364,3,530,442,237,512,351,65,83,588,393,739,81,567,896,977,230,709,568,827,445,917,326,773,189,735,157,310,786,782,236,3,326,490,848,905,231,535,9,170,31,679,481,22,278,175,46,278,619,138,39,466,102,280,231,890,160,325,138,501,939,424,751,946,182,410,337,348,249,849,127,17,393,285,715,638,285,306,321,366,221,464,629,452,914,661,674,191,342,849,979,318,733,436,732,941,310,379,68,8,189,989,23,899,280,862,590,721,692,298,403,126,466,499,674,163,514,652,556,685,870,460,801,545,369,209,212,517,20,450,582,669,186,470,77,218,328,199,276,445,85,716,565,702,615,628,415,312,624,498,535,186,383,116,285,456,938,155,239,603,321,385,34,60,609,516,864,564,779,611,638,394,702,491,934,549,354,108,269,230,371,123,430,574,896,637,192,332,840,157,265,297,236,677,994,16,980,449,98,721,714,556,374,89,866,558,510,975,631,394,322,138,386,504,550,45,406,2,979,134,852,528,640,424,294,562,608,588,960,551,376,419,901,409,618,969,525,187,978,635,309,54,700,975,480,359,26,676,18,93,319,673,561,87,690,69,449,922,880,615,1000,683,94,566,67,903,16,299,940,429,825,992,516,453,914,918,772,359,69,354,270,973,355,490,814,847,981,34,364,495,316,181,773,300,117,869,473,811,398,163,545,851,952,603,361,71,908,982,219,700,787,446,138,65,711,27,904,487,496,875,264,742,536,392,723,551,952,662,933,520,18,187,991,442,187,438,660,91,6,203,20,495,956,820,494,740,989,342,827,146,92,65,847,496,440,339,270,974,617,540,789,327,118,692,265,311,869,993", + "469,590,12,149,66,952,939,155,499,326,119,672,692,389,333,958,809,476,315,255,299,296,72,145,40,607,170,499,597,936,167,568,406,371,620,1,443,674,632,399,56,201,934,478,715,643,356,5,440,268,161,466,882,77,110,918,133,717,485,972,668,340,660,448,850,693,605,977,928,802,107,258,767,233,132,133,597,676,762,430,181,650,451,192,413,423,456,342,429,644,702,600,526,22,966,753,44,408,427,417,811,788,19,204,6,967,478,911,792,490,857,168,124,545,664,738,786,416,770,939,946,437,737,256,68,201,822,470,603,429,211,596,960,368,246,254,588,303,114,265,981,533,255,720,93,27,975,274,407,81,874,433,386,364,720,593,168,284,332,930,4,86,144,120,512,995,788,821,532,612,572,374,268,195,678,867,647,400,726,543,709,236,197,589,631,402,469,375,48,676,443,346,404,207,716,548,137,700,449,794,661,845,324,65,237,520,831,840,352,522,534,827,219,77,863,266,164,75,443,816,248,992,62,414,734,360,744,956,854,694,108,704,668,447,386,332,837,894,715,224,491,741,364,357,906,20,820,506,895,342,404,224,661,797,401,298,545,799,556,574,535,315,22,915,399,541,390,919,801,375,651,86,287,948,909,156,563,223,392,211,643,348,593,844,627,345,479,688,45,943,955,997,412,129,35,76,929,837,73,962,853,402,6,853,813,18,11,874,247,608,390,164,396,764,388,691,172,869,157,628,336,442,327,63,0,975,825,652,194,391,773,609,595,744,127,204,663,944,917,486,376,549,740,295,832,414,163,842,13,399,960,868,558,61,600,803,542,512,177,864,330,214,421,514,501,780,859,761,357,548,476,299,248,691,100,26,260,125,800,47,919,803,137,520,139,97,454,533,837,755,957,784,81,779,465,494,937,28,290,985,292,405,630,362,245,797,527,673,85,546,702,505,696,103,605,802,430,149,422,220,498,654,803,764,926,969,577,762,766,478,123,872,569,559,6,817,126,623,994,85,295,135,544,845,754,230,984,101,632,114,718,906,21,307,491,553,288,444,842,124,962,424,743,512,322,374,359,955,284,194,383,257,418,164,955,868,496,826,919,893,855,55,454,713,274,86,972,601,227,55,369,490,886,490,266,756,559,65,886,727,61,700,147,87,915,783,795,295,831,123,208,981,423,26,550,921,804,92,904,14,527,920,413,676,855,423,972,452,675,566,961,991,554,26,758,799,93,739,736,881,824,393,334,957,873,453,647,356,157,220,112,519,316,972,884,38,849,30,266,267,228,278,681,919,511,451,210,794,445,262,900,664,801,863,386,416,162,623,171,856,812,36,864,710,151,924,508,234,795,496,497,814,503,195,347,792,11,681,698,330,715,962,285,249,222,279,302,551,914,160,495,579,102,868,29,462,148,456,254,727,13,65,521,697,114,736,163,645,444,316,17,438,299,775,567,77,218,911,614,287,107,431,266,908,574,714,408,215,118,938,177,448,733,634,555,945,718,909,349,436,120,673,263,36,773,541,30,519,683,376,670,443,490,433,944,154,62,915,437,735,678,974,86,333,487,188,508,567,179,520,681,500,448,382,791,303,728,717,320,432,642,309,251,410,154,936,541,228,968,594,845,306,288,722,259,152,549,842,341,157,514,923,559,343,901,456,72,599,85,853,769,558,416,467,318,703,568,409,313,706,982,259,279,71,333,513,708,593,508,503,40,159,15,858,978,394,655,955,154,631,407,708,706,506,280,84,893,584,809,443,65,666,387,807,924,677,485,789,94,39,322,60,880,70,527,229,988,354,761,601,71,692,461,264,911,648,887,986,962,816,396,153,959,915,131,121,862,319,486,682,44,155,138,605,444,832,342,222,965,781,841,573,842,750,546,624,699,890,751,977,181,668,958,981,445,770,907,170,599,20,409,826,543,154,151,567,285,571,5,349,580,474,384,771,557,579,128,985,527,223,73,331,470,965,911,23,723,681,599,671,994,153,844,721,456,820,384,694,704,195,210,642,544,963,245,537,378,241,805,203,867,405,1,215,337,939,596,414,758,747,754,461,780,597,961,273,483,354,905,500,253,890,65,38,355,82,542,160,268,348,408,886,825,648,782,229,561,722,56,790,845,763,748,293,342,425,96,821,54,393,147,112,873,814,597,840,139,958,789,181,646,657,388,366,502,568,139,888,668,702,723,647,620,989,62,836,62,850,332,908,520,269,480,18,800,190,891,835,763,81,539,930,983,408,363,707,236,478,5,307,537,394,200,755,563,635,423,678,974,791", + "704,497,700,310,607,510,377,219,954,231,952,142,872,134,914,343,321,86,942,775,865,980,51,746,338,930,792,683,3,427,417,768,922,448,52,638,155,189,960,776,559,995,678,189,1000,71,695,303,509,328,395,10,725,543,957,397,806,951,6,934,409,687,884,106,815,76,956,525,553,818,59,439,44,744,861,111,656,946,682,717,215,112,273,972,147,628,274,994,554,824,206,198,790,572,553,496,933,658,231,314,507,150,23,493,418,677,843,617,960,502,99,273,979,170,545,301,898,450,250,62,370,204,56,453,957,946,816,101,851,521,92,269,329,413,140,320,403,215,458,54,679,715,9,840,883,295,127,250,609,486,998,794,639,48,205,776,13,679,975,662,338,314,864,398,231,287,106,544,555,30,873,169,977,536,41,776,5,824,498,214,619,338,177,706,584,329,213,657,95,175,106,20,687,262,114,14,540,148,995,554,830,202,713,675,907,737,452,245,173,825,608,185,223,746,714,934,6,522,681,877,440,755,635,334,500,439,352,404,114,631,716,260,575,360,179,516,516,236,966,452,244,55,871,739,278,674,455,793,14,912,466,520,578,824,180,313,744,376,7,688,7,10,609,792,157,850,632,709,232,8,477,779,866,81,147,530,882,853,899,794,260,724,297,518,244,573,237,787,402,37,803,198,36,106,251,982,376,375,283,118,300,757,379,13,826,327,800,42,582,949,379,991,89,518,299,481,393,645,502,102,318,295,808,796,975,0,70,172,92,519,640,398,759,674,133,701,729,781,413,792,280,334,710,451,87,734,130,203,719,30,393,107,147,936,822,754,857,187,701,377,244,742,274,697,294,324,442,561,404,950,232,420,841,107,479,572,888,328,824,920,850,824,338,349,869,273,607,78,823,607,553,642,601,494,253,766,215,623,251,240,336,908,258,818,618,894,647,977,239,719,528,791,752,903,56,88,427,918,318,89,626,34,992,357,740,491,214,210,78,480,420,447,666,26,25,729,425,893,368,624,463,530,411,707,962,879,532,242,874,347,303,681,353,352,871,51,914,658,35,674,487,235,391,21,939,867,773,400,244,186,391,582,727,746,737,309,52,883,588,414,16,950,359,962,212,198,481,963,983,876,284,21,321,322,486,412,15,383,525,756,228,577,533,411,669,859,144,750,440,583,587,47,919,645,53,448,171,572,826,608,167,144,473,352,426,793,912,995,958,88,15,404,694,64,349,494,535,246,570,839,497,889,104,162,942,197,431,896,951,242,630,869,599,155,192,380,647,341,887,155,158,200,498,517,696,916,718,472,39,596,933,378,955,952,562,966,48,252,978,170,327,946,77,323,105,174,755,473,400,98,211,571,622,663,216,603,516,610,985,613,630,418,375,300,586,246,990,22,200,434,266,41,535,763,410,30,104,930,269,877,811,676,821,687,661,826,550,939,646,804,738,101,705,973,273,21,731,188,742,674,515,4,38,482,371,167,280,243,214,891,788,943,72,389,222,59,344,769,490,330,768,403,5,989,459,551,352,808,956,284,886,323,185,423,933,601,135,45,483,368,742,276,739,40,560,360,258,242,383,457,370,605,368,829,852,495,953,723,886,689,743,285,698,278,247,330,894,749,55,191,774,866,128,600,87,509,327,203,808,661,368,840,789,956,470,502,187,486,950,563,332,703,499,980,894,517,845,565,977,730,36,662,257,101,980,545,751,99,483,323,143,1,338,681,546,83,418,502,327,154,778,986,727,843,392,542,281,975,400,871,48,881,379,758,392,974,971,267,189,473,440,213,168,290,493,63,329,954,314,271,964,899,996,368,285,57,258,96,687,230,609,969,512,542,558,920,66,438,128,709,149,578,5,456,72,43,286,979,566,814,214,557,735,934,713,881,818,440,428,81,794,873,877,541,176,947,226,702,760,641,654,55,112,897,226,635,924,880,975,735,117,61,366,878,904,262,919,781,597,930,977,457,449,2,651,932,852,286,232,15,759,938,611,318,583,820,51,774,91,928,426,3,308,63,978,178,406,329,586,689,744,377,55,617,951,446,294,436,56,238,16,525,69,237,905,78,777,559,247,351,226,960,453,826,25,216,658,308,288,964,722,516,148,290,942,969,901,748,123,397,863,770,304,781,348,337,800,793,360,871,174,467,59,325,305,838,423,131,418,502,340,334,882,822,181,39,999,441,853,366,571,118,659,489,843,142,353,555,914,460,291,345,269,10,454,111,502,417,201,784,955,39,767,412,706,112,922,621,729,725,98,504,516,46,817,236,541,536,956,460", + "92,657,977,350,614,256,256,280,120,284,38,650,406,686,393,247,931,503,371,735,147,238,538,991,251,36,887,729,330,309,936,651,77,893,827,190,863,971,732,951,916,176,84,240,899,241,70,832,196,151,126,654,778,889,377,712,492,480,699,438,57,460,365,945,181,831,439,240,834,50,728,645,544,289,54,175,955,779,82,447,914,462,989,40,900,485,784,718,925,744,28,802,50,794,268,952,55,815,988,70,663,292,39,606,316,328,880,953,665,930,122,287,130,372,227,733,984,133,506,464,394,465,208,993,735,436,609,439,57,374,329,45,366,303,340,968,624,207,993,687,11,393,144,614,25,332,264,143,677,906,948,466,972,859,155,484,85,960,251,105,444,195,271,40,684,399,848,827,542,875,155,74,679,897,438,664,988,372,187,647,530,327,645,65,821,958,329,794,336,545,23,839,443,209,813,664,121,426,653,426,45,99,857,977,802,525,569,825,549,555,459,900,382,343,718,546,115,380,410,556,57,360,237,795,615,161,60,648,25,717,153,25,587,629,168,555,684,606,537,531,143,360,33,635,111,515,725,91,911,837,698,782,897,332,866,484,357,74,622,257,151,811,817,289,682,227,617,809,318,240,184,996,705,600,737,220,508,359,901,154,830,273,733,868,982,576,401,341,364,403,871,492,394,303,346,17,218,669,358,740,370,702,783,251,166,660,43,851,785,452,897,886,58,842,928,495,914,455,450,716,450,385,279,469,825,70,0,846,801,49,241,47,28,320,274,641,715,457,900,588,795,488,827,409,410,400,176,778,142,471,899,819,505,625,597,548,121,452,148,237,664,646,267,3,108,167,433,367,442,358,974,753,97,778,375,846,984,847,978,307,569,751,603,85,728,322,58,649,365,798,570,868,763,61,947,811,460,942,493,344,487,438,36,749,915,948,856,252,579,293,113,23,799,473,979,603,972,38,63,959,171,230,189,686,917,578,97,619,428,109,111,303,949,508,861,162,249,799,939,361,799,600,358,161,723,537,378,257,23,836,56,768,67,62,814,787,940,933,590,188,842,951,22,242,903,995,910,76,674,124,562,679,304,503,98,978,805,417,651,977,629,526,56,979,923,719,900,180,262,447,54,769,659,355,668,71,648,920,262,398,767,669,982,262,955,574,334,502,256,572,890,782,632,74,301,760,111,193,372,76,138,847,443,884,284,550,348,842,169,1,542,544,723,73,779,214,989,982,787,129,272,257,829,760,349,190,362,468,47,940,341,492,533,288,794,236,755,820,591,892,69,523,626,113,439,162,187,193,761,909,859,198,394,256,555,622,364,988,194,792,348,326,750,642,22,378,482,970,253,70,809,819,244,571,348,821,778,830,400,524,676,718,636,497,571,165,48,538,163,575,655,650,186,784,133,635,275,884,8,826,28,86,898,576,657,904,106,364,143,4,467,862,581,881,837,863,411,131,176,704,586,489,117,965,517,188,776,620,223,110,426,975,638,417,850,97,487,720,939,75,232,853,189,508,646,675,370,171,171,922,498,848,881,478,201,366,309,395,394,21,65,412,241,986,950,388,663,460,76,776,692,241,318,782,919,352,942,183,892,567,200,578,426,526,723,498,488,597,167,1000,889,297,381,819,642,412,199,820,325,75,203,472,376,630,58,846,381,297,342,411,721,222,629,42,767,381,157,556,605,436,307,611,132,889,93,153,89,201,767,662,289,531,233,894,456,969,778,625,873,187,950,639,729,516,324,693,646,917,846,688,32,109,455,375,932,396,895,280,854,183,153,419,7,739,807,242,566,905,690,999,833,121,853,771,920,808,242,33,788,828,482,702,228,240,402,161,30,190,751,129,159,611,587,296,842,744,138,278,677,823,61,728,375,551,29,415,121,256,872,849,303,89,470,214,811,437,430,298,291,221,101,12,202,21,981,927,922,613,100,15,480,348,662,935,188,576,851,96,202,682,206,288,514,834,564,180,439,658,480,622,800,525,760,491,220,707,508,701,150,215,315,678,912,5,992,328,372,922,614,710,827,940,974,70,459,101,416,302,491,886,74,942,429,38,331,522,730,919,489,870,411,388,706,839,776,86,186,692,955,881,488,917,721,869,129,808,482,975,365,646,562,875,178,307,188,339,721,53,253,46,761,267,54,412,461,636,112,132,243,386,933,341,178,399,376,977,706,896,869,865,140,360,145,637,6,934,803,271,430,48,841,260,16,503,287,276,907,245,33,917,798,15,867,261,632,766,420,499,674,992,999,63,625,465,698,761,204,79,719,136", + "680,130,216,146,236,966,512,959,843,753,817,243,647,913,496,313,473,831,961,355,696,467,737,984,501,384,621,884,825,218,424,582,571,117,569,449,116,434,626,324,737,752,943,705,816,974,62,622,224,349,584,932,997,934,521,651,522,279,213,501,437,410,718,864,230,734,564,499,822,65,760,806,126,442,957,930,746,540,777,104,158,4,63,551,320,85,905,861,348,102,133,137,267,711,308,440,108,229,564,839,818,887,537,178,655,621,905,494,632,776,63,287,785,783,6,204,179,317,939,186,2,329,398,230,545,328,67,947,547,810,216,656,509,70,337,254,73,597,988,200,499,456,206,165,375,918,106,357,544,217,597,798,759,474,774,605,785,430,218,616,927,589,468,108,354,956,23,81,80,535,892,75,273,191,217,107,958,934,876,408,66,806,776,894,805,917,99,794,39,501,452,5,154,866,8,928,682,401,472,830,441,852,792,985,456,841,666,604,142,499,250,322,928,142,713,582,476,997,561,953,666,946,149,169,1,291,81,579,228,234,66,976,696,19,959,674,5,762,551,771,960,965,539,328,229,481,53,598,17,291,228,560,47,960,610,74,295,771,936,737,856,804,813,458,141,408,655,347,725,441,12,94,644,666,484,323,506,410,105,685,264,224,946,446,964,199,322,975,318,537,503,369,613,140,498,533,759,20,752,257,635,557,987,466,886,683,28,286,229,234,926,847,574,335,759,522,30,667,319,398,436,675,821,753,652,172,846,0,463,42,186,57,601,795,622,651,6,88,977,505,983,305,596,982,728,228,597,475,878,348,930,559,592,484,653,525,667,670,198,301,791,639,103,508,434,420,368,839,701,492,375,884,391,366,899,882,559,670,756,260,113,111,816,879,667,280,643,980,289,339,26,680,455,56,456,47,639,205,610,893,278,80,510,294,899,253,661,132,653,41,869,96,522,402,554,968,429,731,571,917,625,359,233,39,921,568,265,89,970,708,789,809,741,14,253,584,872,366,454,544,59,914,349,217,994,85,672,33,573,964,179,462,585,968,260,804,404,504,103,214,313,741,944,572,87,134,295,851,626,628,432,688,162,400,377,219,986,553,140,759,495,181,954,753,90,788,253,291,627,641,957,265,282,676,814,445,657,801,173,616,784,834,447,213,441,1,70,599,970,995,71,851,152,623,987,876,536,70,694,469,47,834,284,114,505,392,639,80,658,523,60,497,806,124,194,348,787,908,91,518,783,188,235,159,128,160,935,603,739,230,526,754,729,96,427,860,303,667,240,97,49,387,162,663,360,600,441,760,125,454,672,958,188,643,461,5,476,241,371,412,892,654,931,543,897,970,756,174,821,203,117,348,781,665,40,799,585,908,956,571,269,82,561,106,263,370,456,426,320,539,90,448,45,912,50,671,541,636,771,956,596,891,127,899,576,690,955,974,567,107,187,401,950,718,161,769,579,86,802,809,226,823,932,83,618,806,919,829,578,403,181,40,508,803,256,521,56,125,379,370,914,769,777,214,207,214,150,885,38,681,318,557,868,701,898,83,844,176,545,475,800,315,454,971,589,916,736,874,297,840,178,944,379,755,498,371,178,959,618,705,626,136,427,886,864,635,85,672,241,754,312,66,48,632,415,274,59,730,192,266,488,546,370,228,128,153,203,627,55,88,866,70,863,142,403,174,866,462,962,321,412,945,653,377,653,241,486,243,158,16,738,419,306,653,894,265,143,65,705,737,403,590,935,188,987,902,222,241,420,897,944,276,492,451,944,532,433,78,781,747,734,521,518,234,15,636,607,112,240,316,303,503,600,973,393,460,334,913,256,793,419,399,581,987,425,953,888,168,356,113,908,606,426,607,353,266,150,319,93,708,77,64,568,429,378,403,851,47,691,520,565,99,624,552,874,132,741,189,150,742,932,915,236,618,134,360,146,831,842,116,378,52,494,815,262,169,505,336,254,387,382,227,419,428,777,51,720,921,35,96,881,852,154,719,322,918,787,30,204,186,879,841,755,235,415,783,891,190,71,361,770,501,682,924,758,133,985,890,957,179,372,792,698,280,365,350,896,849,190,149,355,904,24,428,807,272,28,108,255,727,435,757,767,55,751,31,727,234,982,587,762,371,495,89,721,904,891,381,244,23,118,665,518,78,906,38,558,536,661,281,396,250,569,694,944,213,379,639,221,270,928,730,921,185,618,237,935,135,292,367,40,579,846,759,638,361,427,890,975,377,792,438,202,917,434,484,284,835,205,239,635,750,468,411,340,25,50,250,282,83", + "374,680,324,568,324,191,335,67,213,833,466,104,143,262,894,567,881,271,881,200,917,290,674,629,410,247,743,902,232,149,391,808,113,704,388,534,966,930,379,775,484,863,38,768,371,881,397,944,229,164,800,73,339,419,506,306,543,425,343,628,426,468,304,32,554,680,439,145,28,101,986,12,200,721,215,329,853,977,548,126,133,111,649,718,831,290,915,3,514,750,859,661,215,71,311,414,125,76,813,429,16,572,676,134,660,931,728,483,426,524,652,216,758,985,456,887,221,71,872,465,448,706,618,800,153,305,52,604,866,474,148,590,124,591,157,79,718,180,350,972,694,129,148,466,441,303,853,361,275,469,240,922,246,205,925,298,767,2,669,469,284,133,732,326,489,350,352,878,494,214,464,559,756,931,266,581,244,482,745,128,350,903,625,7,147,918,151,751,280,374,804,695,292,82,839,643,107,85,810,135,983,900,348,93,847,689,148,497,60,538,359,779,452,931,654,88,10,895,803,379,698,866,833,229,659,969,944,352,176,289,143,400,295,341,558,968,733,337,975,587,438,211,260,903,710,488,103,654,641,671,17,580,437,229,301,844,161,144,433,603,757,705,593,542,16,94,72,673,587,932,86,701,561,190,643,9,168,657,393,435,549,136,23,62,298,605,8,427,952,893,826,156,128,551,151,275,66,442,938,958,341,37,494,233,960,21,741,351,418,668,380,488,858,915,932,54,581,707,152,601,350,285,160,449,194,92,801,463,0,893,782,197,133,26,969,803,636,13,927,975,112,802,801,9,435,832,845,267,158,535,766,600,649,392,528,428,857,697,290,244,609,752,346,100,348,986,712,367,152,824,327,767,191,895,858,705,388,520,688,122,999,934,137,535,373,166,52,457,779,904,776,202,866,979,199,115,998,836,309,633,341,814,917,664,549,548,662,492,157,32,633,152,4,928,90,594,294,597,688,656,774,650,123,738,803,884,129,801,819,233,480,462,694,441,292,497,44,451,419,790,742,147,421,595,671,137,934,686,308,6,112,537,242,30,437,710,986,974,789,784,566,875,873,44,824,444,121,966,369,896,916,640,245,451,734,514,636,632,467,291,194,376,859,925,271,274,915,185,84,395,465,67,191,837,332,622,152,438,601,932,348,744,252,20,106,39,769,3,255,340,616,643,828,142,297,268,602,241,295,670,525,919,58,135,920,377,521,621,333,987,446,503,988,222,504,178,371,69,956,601,611,637,938,391,660,427,936,387,246,393,824,91,811,72,837,20,406,787,620,116,690,150,236,945,880,84,349,239,846,746,647,839,582,584,333,647,681,659,644,598,178,401,428,277,966,719,156,485,821,635,404,584,542,640,996,46,907,498,940,458,223,530,654,337,924,943,930,3,727,984,136,104,10,535,124,761,955,869,566,403,844,664,809,877,651,441,738,648,588,850,255,981,639,564,593,43,339,803,877,167,873,424,391,440,710,908,253,630,952,575,921,143,775,584,451,206,571,967,117,291,417,24,589,246,931,463,457,920,542,930,716,844,581,868,266,659,939,157,58,17,312,551,840,817,321,510,469,117,677,899,890,147,151,250,670,131,708,203,23,326,620,829,55,858,570,889,554,888,358,727,703,350,964,164,679,337,23,151,717,146,159,618,223,325,859,912,529,330,483,588,692,660,392,413,355,870,301,553,160,469,221,431,310,521,141,728,494,165,834,360,11,236,478,81,448,662,400,332,358,755,834,259,76,619,697,223,611,474,943,693,546,128,100,822,874,808,95,423,634,995,1,841,410,178,155,353,462,617,406,763,948,14,135,270,686,238,967,684,623,124,787,345,677,465,600,335,879,646,872,304,528,920,232,474,897,910,458,493,343,567,276,943,212,353,680,490,224,889,691,828,616,987,89,170,662,804,162,453,11,778,467,485,295,65,452,198,435,331,298,192,55,528,909,10,343,481,881,219,32,419,776,134,992,117,969,971,550,574,555,784,377,360,146,828,987,558,561,576,985,523,516,981,642,705,835,167,881,109,860,483,482,933,727,651,785,282,530,17,758,889,180,467,813,691,412,161,727,218,486,852,561,138,438,135,524,737,9,168,995,93,835,310,893,244,226,696,985,761,580,987,75,943,887,134,337,325,800,894,232,943,208,81,751,359,22,930,643,362,866,415,82,940,734,965,960,207,203,906,652,324,65,851,926,778,615,67,301,737,388,101,357,857,139,659,575,195,438,681,990,565,641,805,951,173,566,491,540,56,730,34,559,796,780,934,66,229,465,628,308,783", + "473,535,839,159,201,610,850,655,731,627,633,153,726,21,901,850,905,203,976,527,56,974,471,65,200,965,119,523,424,695,169,505,530,411,514,81,870,896,392,212,620,354,311,958,490,835,723,670,189,43,453,790,694,887,688,342,644,222,28,694,570,251,176,753,392,821,976,44,144,240,940,845,829,55,660,485,253,681,120,29,402,947,484,169,254,301,28,913,149,438,697,947,714,678,300,975,369,635,799,503,714,665,160,645,757,204,464,913,250,846,375,196,474,467,513,671,992,135,344,558,781,334,961,787,820,627,122,27,492,239,886,192,317,72,576,834,814,844,843,775,651,323,539,621,800,45,470,36,885,439,944,62,355,637,895,890,301,81,771,275,813,213,729,677,213,639,418,917,616,296,328,941,695,41,925,415,864,367,857,692,172,169,704,53,114,710,581,66,538,152,857,841,818,331,14,716,966,921,9,628,324,94,449,910,870,371,779,388,292,512,440,666,16,683,799,566,795,240,188,631,288,140,784,972,114,619,712,432,96,275,563,75,833,238,866,671,189,97,284,861,939,433,624,277,309,825,527,20,746,496,278,383,299,693,217,679,558,189,871,450,986,570,135,116,33,298,911,119,662,31,170,542,588,447,812,649,533,837,538,963,928,479,865,410,967,514,286,378,616,659,161,396,5,721,170,164,443,764,113,63,45,853,915,112,961,315,690,272,724,613,271,510,134,248,716,154,828,883,750,704,937,723,356,934,391,519,49,42,893,0,72,221,765,129,588,846,190,246,991,445,171,836,411,320,770,999,704,778,401,897,678,325,196,915,978,56,839,915,53,167,974,592,929,294,896,69,746,879,964,396,260,39,963,239,977,603,914,759,331,481,472,136,356,237,779,693,371,852,620,389,799,956,524,559,725,976,824,447,297,289,995,984,191,405,426,778,168,373,721,485,438,21,664,359,315,884,487,689,287,911,135,120,180,674,58,842,855,484,146,485,315,674,439,543,733,451,367,805,318,214,550,452,172,696,646,793,949,304,593,246,197,849,302,452,272,2,50,583,149,976,520,843,849,500,242,79,38,345,178,530,933,815,425,454,410,189,580,941,995,774,653,48,433,739,105,787,946,515,263,449,724,309,601,860,341,683,282,358,634,695,669,522,822,234,833,126,813,681,716,467,514,64,730,947,419,812,821,10,599,971,964,552,676,84,551,475,376,872,740,297,945,351,162,794,396,715,936,912,23,70,279,880,32,868,330,33,668,936,358,65,738,545,787,945,660,498,490,464,137,594,897,842,833,538,672,428,458,655,509,187,166,885,110,441,930,724,838,753,132,532,634,627,135,524,751,498,929,77,502,446,488,279,107,758,13,797,684,304,129,350,658,442,941,576,3,718,530,334,923,753,979,29,933,561,67,949,872,571,176,37,588,223,658,598,747,94,751,228,655,946,391,789,537,712,937,753,377,100,706,972,415,217,282,950,756,177,349,110,707,376,877,676,610,322,935,81,945,578,335,50,560,666,574,258,211,910,737,995,863,554,90,895,404,569,407,236,270,682,970,798,776,54,867,891,63,710,3,659,946,629,946,612,286,515,942,966,471,881,880,859,853,148,654,480,209,856,837,310,464,511,473,639,416,273,965,667,997,150,369,481,33,527,16,450,400,213,172,400,449,79,28,447,309,875,498,225,760,618,868,999,619,632,12,281,294,789,320,936,622,611,814,7,534,854,830,53,211,964,754,757,883,114,5,321,190,128,212,13,363,657,808,129,816,232,343,360,896,765,101,81,441,664,328,63,622,374,459,733,604,693,714,518,6,139,590,872,495,539,318,267,246,811,762,962,465,361,355,579,559,936,931,130,547,812,223,178,909,17,483,535,537,184,372,138,803,85,490,336,843,778,309,502,776,215,676,374,305,801,8,37,29,121,286,603,748,776,897,827,821,630,926,62,830,276,228,937,103,569,676,377,244,452,575,51,905,569,353,847,779,56,823,250,385,271,502,159,858,401,718,492,648,957,842,961,10,549,350,980,170,37,355,859,729,283,708,242,62,738,865,494,268,39,392,248,238,834,963,847,497,871,729,178,663,919,393,842,664,84,775,465,707,606,610,58,957,473,952,187,45,323,604,120,803,9,624,572,456,319,13,502,372,222,691,467,721,406,342,720,48,994,215,792,514,812,781,414,492,987,195,104,43,12,12,105,885,72,806,251,721,204,205,202,879,595,396,420,195,416,521,782,1000,492,963,458,494,435,765,731,760,992,725,374,5,68,717,152,554,171,835,834", + "372,881,723,209,96,786,182,926,440,620,222,296,114,141,147,609,668,679,908,490,705,362,474,2,510,283,701,494,107,874,502,641,624,212,238,9,620,850,514,427,937,981,59,9,251,551,40,415,424,246,434,543,658,541,462,72,627,189,184,744,914,804,996,155,685,468,32,99,762,227,736,488,3,900,135,499,783,928,34,439,601,812,443,666,166,159,570,33,540,431,447,927,415,291,120,207,949,754,465,926,393,964,801,799,13,445,37,738,317,311,899,652,850,926,825,351,23,553,816,796,709,100,926,209,257,664,839,998,990,226,862,464,528,746,59,698,138,523,752,992,352,388,896,278,683,287,549,332,657,195,542,170,714,911,505,312,554,297,810,425,977,421,821,579,272,310,19,121,18,474,33,580,460,321,53,572,102,82,837,746,965,376,107,455,400,896,172,44,703,435,41,186,814,494,610,438,163,176,761,641,177,792,814,185,535,174,477,733,110,440,914,496,411,876,481,763,758,959,851,812,773,406,197,985,454,104,91,722,743,296,366,559,684,105,468,596,762,792,253,186,919,89,332,934,295,910,494,522,608,790,701,177,160,340,903,42,270,265,946,670,857,562,425,177,819,333,932,753,275,882,556,190,807,515,118,681,904,927,392,703,423,575,917,409,170,766,708,83,479,931,253,7,515,331,709,151,660,635,611,203,800,321,679,171,186,349,97,517,985,988,30,398,497,631,683,371,953,246,752,12,6,439,455,549,773,640,241,186,782,72,0,388,790,942,738,147,656,294,314,839,107,128,924,781,864,529,123,45,435,593,572,284,942,461,319,767,257,646,565,214,640,272,877,658,511,879,285,217,30,398,106,102,710,633,454,96,749,713,152,66,193,227,86,960,984,396,689,744,115,415,389,67,935,131,585,111,519,238,200,146,992,702,57,642,712,588,14,862,997,19,324,738,32,444,234,385,414,647,822,780,850,453,449,225,975,565,68,309,694,264,841,705,673,134,840,705,709,997,513,68,107,337,943,719,356,431,748,489,377,609,915,601,752,166,866,390,939,279,277,836,369,235,498,153,718,989,376,268,864,320,698,996,213,684,794,312,918,151,393,329,322,957,963,635,548,260,132,177,501,250,467,892,314,669,380,320,585,105,776,872,912,852,359,653,184,907,3,693,475,122,597,670,627,637,906,848,842,823,660,344,558,4,172,339,147,917,341,612,153,710,569,216,133,178,552,553,893,498,661,129,286,600,351,359,628,357,483,873,569,446,304,714,236,491,663,33,81,593,797,399,133,826,650,521,81,584,894,98,336,432,208,965,236,783,71,588,316,637,826,141,287,275,651,378,709,903,803,751,131,530,205,905,525,394,103,490,672,685,99,423,711,754,760,556,817,858,295,225,599,622,743,478,75,976,676,353,480,564,726,688,675,537,154,470,905,603,811,376,319,352,536,134,146,564,808,992,95,656,947,72,462,757,809,331,372,114,325,604,670,376,741,874,236,374,901,986,970,229,168,443,440,926,304,537,982,669,508,447,927,297,478,145,602,557,825,797,92,517,5,437,38,622,907,391,375,252,794,322,492,491,443,401,18,443,579,301,87,566,717,785,239,274,139,906,273,885,251,657,470,989,478,867,446,161,326,589,684,571,488,294,188,172,97,374,562,565,423,710,810,30,260,882,108,704,650,404,100,763,90,845,649,263,543,940,641,737,76,718,973,794,275,793,616,668,434,246,168,429,589,730,989,350,795,617,839,929,463,711,667,343,502,205,538,522,438,864,661,934,216,994,279,161,971,987,181,981,867,283,76,573,736,629,380,712,534,973,40,343,607,226,42,972,165,931,657,425,612,20,561,6,214,156,5,710,145,951,32,555,287,18,352,105,494,134,701,192,748,235,205,181,459,693,602,117,294,364,53,509,747,399,260,60,228,204,94,986,105,142,177,368,584,785,12,5,279,128,57,121,237,911,250,250,373,675,706,940,176,45,67,729,686,406,464,574,964,507,879,930,201,877,221,364,250,830,734,393,529,578,39,107,864,32,213,973,273,943,497,38,116,635,766,150,871,145,115,348,471,441,797,525,77,432,623,296,549,445,989,970,552,918,305,467,817,604,151,205,136,659,131,589,3,873,154,507,370,442,956,796,347,668,655,438,998,87,774,797,854,210,270,865,709,383,805,490,56,170,318,454,482,596,239,690,379,224,629,678,936,471,146,484,813,831,938,623,629,253,650,34,49,532,785,207,180,954,853,829,484,182,66,38,329,242,464,504,484,189,581,43,705,165", + "607,478,259,243,373,661,404,355,107,407,661,149,183,764,755,254,984,271,415,123,64,48,742,123,348,422,275,482,799,585,230,205,868,199,678,506,533,358,114,480,229,954,190,929,208,747,977,497,448,111,411,88,392,391,690,932,117,191,827,366,894,124,657,5,450,916,198,746,325,67,43,748,911,367,417,579,987,86,933,356,854,298,301,147,692,429,197,617,393,362,391,799,609,469,924,459,105,54,899,423,571,577,774,44,321,729,225,525,828,45,693,164,612,568,122,196,811,712,505,262,871,930,394,377,769,721,880,356,591,574,87,39,604,171,522,102,288,141,735,438,875,478,132,705,673,695,285,495,19,922,886,681,92,907,789,553,453,4,151,689,842,949,715,595,261,675,206,923,627,178,162,375,335,702,962,622,302,41,370,234,580,514,374,171,471,443,682,779,989,473,618,271,959,800,765,912,678,210,923,345,325,400,909,996,600,566,382,354,376,378,697,141,359,419,539,654,588,332,753,907,660,392,695,814,264,123,313,464,822,647,996,855,634,829,742,985,171,261,29,213,801,87,700,92,769,763,613,163,982,9,456,466,932,355,585,317,189,544,537,77,169,764,485,840,901,376,134,100,471,791,109,774,677,483,598,25,649,849,150,628,612,504,64,410,656,69,212,922,790,767,416,584,713,428,34,144,905,110,342,691,87,480,862,318,114,483,294,152,942,226,753,945,309,832,398,851,788,307,722,118,202,183,465,720,609,398,47,57,197,221,388,0,544,916,714,431,471,936,479,774,291,560,954,907,709,577,110,682,132,798,713,335,479,304,321,57,889,58,730,708,332,506,826,799,795,423,193,882,381,797,246,579,692,696,115,706,413,509,201,645,40,409,431,5,537,734,184,96,981,173,130,299,891,666,58,177,596,123,119,450,730,548,257,531,227,235,287,56,312,487,155,27,364,389,810,400,509,725,925,915,719,919,56,107,355,884,729,673,525,885,786,675,633,569,366,570,772,920,732,849,160,100,299,106,562,291,504,946,66,293,790,347,793,896,696,170,945,503,400,833,197,630,311,224,589,935,662,331,592,888,157,343,28,942,906,600,798,78,195,704,452,691,259,141,570,995,372,51,641,323,899,688,190,309,122,238,611,67,949,311,953,396,40,254,527,870,399,343,721,387,989,539,143,642,214,99,353,7,22,833,963,744,753,11,886,930,498,570,696,169,235,604,523,806,171,117,522,529,823,679,285,766,234,232,377,671,502,78,832,825,861,170,468,450,184,630,803,205,182,28,175,821,275,876,266,26,814,809,302,293,236,675,488,270,449,802,745,395,389,937,126,410,110,117,823,936,554,697,81,365,295,498,866,750,702,156,184,803,99,736,594,512,962,984,147,34,789,684,943,651,560,887,357,593,714,282,701,31,938,252,695,255,278,73,342,729,864,757,749,816,926,197,19,499,232,795,110,996,796,516,314,273,408,97,412,33,278,298,328,859,747,352,447,864,855,209,486,192,307,277,526,883,929,877,767,297,969,581,51,187,688,335,242,2,871,652,667,973,871,860,461,69,954,4,357,175,527,690,51,182,453,274,617,6,326,815,407,992,235,317,264,493,681,788,637,520,906,234,235,323,415,641,433,397,397,449,189,129,957,891,612,210,742,699,858,178,101,293,147,875,142,615,801,349,244,443,790,511,865,353,393,787,154,846,677,756,198,123,596,647,40,830,328,194,154,76,584,224,973,203,590,876,278,678,629,429,223,533,616,802,105,165,303,430,288,767,427,532,585,301,277,828,761,207,685,653,653,897,129,322,333,300,505,722,257,526,203,448,465,541,289,215,698,622,236,68,202,314,239,868,246,818,98,473,815,655,419,93,645,514,166,898,603,433,209,437,548,930,797,474,466,994,285,77,598,751,273,722,619,187,562,200,519,44,587,277,810,800,222,253,339,764,352,499,795,617,151,503,793,527,683,501,23,392,709,490,383,360,944,835,964,131,236,337,454,715,225,180,262,956,376,666,779,920,687,898,472,406,921,762,75,807,614,335,671,206,875,643,746,951,723,276,207,482,530,854,106,829,555,187,471,62,675,446,390,688,37,239,218,473,792,356,451,793,205,675,239,42,908,951,638,275,468,197,262,760,606,286,464,542,662,612,75,717,410,492,344,643,523,645,231,959,293,605,881,405,445,615,498,132,792,439,163,483,249,373,343,889,575,530,702,834,721,486,402,280,627,628,875,286,869,245,994,773,353,812,726,405,352,319,216,591,274,458,385,585,210,838,715,358", + "251,474,101,164,275,45,680,280,909,116,480,680,905,28,232,788,673,356,33,766,451,93,943,973,923,542,52,241,332,731,727,399,520,337,977,810,914,927,895,528,74,188,78,172,34,718,731,426,27,753,513,751,420,736,786,267,391,832,692,299,468,93,156,810,180,307,109,266,40,751,220,862,829,858,576,612,732,38,657,934,490,346,595,186,258,247,732,355,786,503,504,976,705,939,384,217,540,50,273,879,645,255,362,848,450,148,13,964,16,231,450,77,322,643,984,651,713,762,185,802,179,488,911,36,774,855,8,941,371,463,353,175,745,655,252,660,420,198,409,801,612,799,967,803,191,694,687,347,146,799,248,649,191,939,465,862,17,697,779,532,346,655,450,380,584,824,147,187,396,973,700,66,62,764,486,981,190,29,362,475,187,690,170,819,338,265,305,545,196,234,776,248,377,685,554,900,902,162,498,129,764,395,905,474,350,363,968,800,532,516,604,778,780,77,304,141,959,359,578,474,806,238,11,305,619,849,44,66,597,26,227,915,393,666,853,692,738,954,808,437,317,434,734,36,466,745,688,614,140,933,631,794,290,939,140,494,902,84,698,232,760,470,859,693,205,133,501,735,473,127,396,652,885,205,982,61,192,468,875,972,521,153,987,682,531,538,224,634,442,129,292,372,431,241,547,750,127,929,377,286,835,997,616,86,914,321,76,891,441,213,445,581,400,956,744,415,387,778,163,693,93,491,489,558,595,759,28,601,133,765,790,544,0,290,625,425,799,385,699,747,563,577,731,905,666,53,927,218,653,727,365,545,472,715,405,611,839,147,199,209,290,270,736,594,264,771,853,139,771,71,833,633,256,430,136,992,996,927,938,169,615,379,348,754,735,434,440,853,886,325,569,876,887,542,701,321,41,669,41,466,717,243,566,481,159,113,850,986,759,769,297,31,394,804,856,446,793,290,758,641,403,576,919,401,780,383,971,851,39,579,873,180,367,115,247,789,268,138,237,835,316,575,340,408,172,175,21,872,153,654,175,261,171,69,620,241,623,120,614,572,51,100,635,73,95,971,793,378,62,579,659,76,48,552,59,251,5,716,779,594,898,119,469,439,469,60,782,935,706,834,724,412,384,840,636,377,994,587,744,444,324,981,16,539,303,416,120,861,722,680,182,953,81,895,962,381,225,887,83,668,543,576,197,563,94,815,731,848,14,72,949,269,979,864,175,43,998,1,295,449,922,713,985,319,191,396,248,628,509,313,890,184,673,723,985,994,995,638,581,133,402,102,224,366,620,554,344,740,109,886,440,591,108,978,95,950,476,493,975,443,612,389,922,58,868,451,541,760,628,227,925,437,595,746,941,147,229,995,405,977,974,680,851,599,884,320,722,594,53,707,419,402,431,464,363,114,465,327,951,485,778,341,598,882,985,287,816,331,648,35,905,594,85,385,226,149,789,440,300,764,227,527,143,80,491,274,695,4,730,602,533,44,411,888,73,458,328,253,560,912,590,939,504,967,824,694,683,14,49,411,677,329,316,197,97,771,952,900,223,947,712,217,770,600,913,236,261,270,978,1000,770,131,993,312,281,731,959,434,189,129,75,519,456,295,689,739,268,365,93,460,381,375,68,277,401,24,585,531,270,156,248,463,377,450,29,165,57,758,875,730,283,830,487,675,388,25,463,957,57,557,306,61,803,398,797,654,465,216,504,946,767,136,823,748,481,213,689,959,148,197,606,680,51,483,552,528,857,637,731,279,480,717,109,657,979,839,570,8,706,17,951,642,729,380,395,655,175,647,838,175,51,276,830,671,560,477,466,677,396,442,395,31,973,671,870,696,763,567,609,162,39,401,944,988,524,683,658,291,504,249,381,858,394,737,275,846,550,639,658,920,947,181,626,883,875,57,237,817,34,481,571,856,578,390,671,736,698,700,390,189,701,582,113,794,564,741,285,718,520,560,273,221,575,374,537,534,145,661,441,815,763,622,829,735,176,73,482,690,687,847,199,358,25,675,324,667,818,688,786,138,3,166,429,661,737,620,644,150,653,685,116,282,606,325,212,211,722,895,400,837,860,881,626,578,647,649,544,514,921,604,776,872,478,62,586,825,151,832,702,561,288,44,249,303,26,84,51,580,615,428,424,605,436,287,592,601,299,217,387,591,9,528,484,305,988,789,214,136,259,548,207,857,749,334,611,855,189,800,154,344,171,803,571,343,556,666,16,65,335,53,764,881,409,15,191,836,894,763,891,82,628,637,358,65,551,512,928,461,736,377", + "454,541,875,575,738,108,529,663,448,261,560,654,195,221,433,711,348,340,265,537,425,861,372,465,437,124,517,552,867,441,813,607,285,741,989,628,414,934,574,584,827,488,224,99,327,705,652,319,308,969,847,233,354,346,897,563,870,121,415,12,66,529,611,449,129,743,310,662,244,20,232,483,932,370,744,529,618,858,562,335,439,254,329,664,499,215,258,722,221,806,835,310,269,262,697,588,43,925,158,803,764,311,780,5,258,692,591,229,794,603,201,952,335,972,586,595,519,118,347,29,195,223,876,241,693,143,707,129,230,892,456,809,379,980,562,479,204,286,242,363,766,83,512,263,353,179,278,63,62,965,67,933,917,962,382,70,610,989,378,711,493,948,206,29,274,780,326,913,454,582,591,377,578,851,986,891,671,587,753,347,708,193,341,488,430,912,996,870,522,912,422,337,605,950,102,157,782,869,263,418,106,481,207,591,78,363,769,185,11,143,973,75,897,27,163,224,753,866,197,708,912,510,802,406,9,144,404,316,389,624,655,731,825,348,636,797,856,61,217,441,564,107,590,43,946,535,670,117,926,773,658,258,197,278,156,764,500,772,78,730,657,513,624,30,754,186,438,248,125,961,388,844,195,213,88,449,765,414,994,729,64,863,714,381,55,297,580,412,97,43,981,234,209,98,805,845,994,853,724,579,825,377,487,194,474,229,298,403,433,474,823,712,214,479,687,448,929,585,822,38,100,230,63,272,744,674,320,795,26,129,942,916,290,0,546,725,584,310,287,154,330,648,648,494,703,6,172,391,855,389,909,127,561,204,451,54,203,303,904,837,488,654,703,782,254,525,428,692,180,547,62,598,516,168,544,80,740,241,836,701,264,529,28,639,137,9,510,374,599,380,32,506,758,533,273,623,855,726,715,738,10,208,288,966,753,962,296,987,558,239,671,439,80,352,629,211,725,228,685,53,172,95,301,48,490,182,508,357,816,851,76,429,731,508,931,80,538,621,92,80,466,124,608,416,23,312,530,185,207,775,550,460,647,487,640,913,950,686,872,402,4,557,3,458,469,234,605,876,833,583,678,678,388,607,251,176,500,569,997,376,790,845,255,573,960,774,546,191,230,763,698,943,425,667,212,562,982,501,147,426,771,81,238,957,763,504,672,61,349,221,737,610,344,647,495,442,256,439,258,797,835,871,114,6,703,341,971,674,361,884,673,695,873,923,236,417,917,277,391,56,600,216,169,759,147,159,584,31,387,115,547,506,879,817,948,61,951,562,910,649,185,401,625,232,775,509,531,766,938,822,264,598,684,125,963,756,770,298,743,618,129,690,358,834,616,757,917,508,584,819,92,346,886,521,665,833,252,449,18,890,671,665,655,529,784,773,700,446,774,337,75,540,575,510,857,860,154,228,134,408,106,403,201,266,60,255,644,67,930,134,835,695,393,659,299,17,27,72,730,601,144,74,838,159,743,434,536,596,897,981,387,625,674,648,158,481,41,771,421,652,323,931,915,52,805,524,901,955,181,964,516,274,31,383,354,115,615,446,323,780,455,390,102,311,768,130,560,21,163,355,968,736,113,253,248,389,8,477,363,197,625,643,41,265,38,63,72,986,519,30,838,979,651,661,636,670,644,660,993,89,55,111,985,620,158,803,478,978,691,786,574,662,407,433,679,675,492,948,618,435,206,737,762,202,78,921,582,18,923,539,173,185,649,54,505,972,136,631,65,851,595,92,862,602,906,695,490,36,84,322,34,267,602,463,447,206,547,265,966,583,520,94,779,930,867,512,985,273,528,717,41,375,953,455,470,499,277,273,927,157,594,611,586,638,126,928,709,913,834,602,531,290,959,149,121,650,370,72,389,560,533,230,537,809,477,624,972,159,386,719,588,823,314,338,750,121,238,941,90,870,500,688,310,525,219,956,366,707,624,13,677,658,701,470,959,682,874,510,513,416,948,683,251,500,392,984,753,77,726,383,661,918,601,672,198,243,937,442,115,753,848,500,901,766,479,74,212,325,937,657,662,814,975,59,680,48,83,781,158,572,66,469,504,788,252,33,489,816,235,413,874,681,256,255,901,607,748,880,596,123,233,542,333,838,976,956,55,236,766,459,648,346,250,28,380,17,685,703,361,162,262,4,8,658,320,693,799,723,470,561,63,856,939,635,565,583,863,305,967,241,701,105,419,821,224,367,418,815,352,852,927,29,930,849,635,835,913,16,571,685,579,384,105,935,699,311,82,711,569,749,300,588,906,804,55,249,754,889,792,195", + "718,522,823,305,567,333,297,80,105,421,181,304,554,963,258,811,917,756,542,109,115,158,17,916,939,88,618,410,424,458,745,439,478,942,499,304,989,105,15,79,35,144,544,163,176,917,768,736,242,566,332,515,58,887,55,795,938,295,608,306,673,491,586,761,92,142,648,669,773,625,534,639,921,851,389,731,220,73,945,901,491,527,263,527,459,786,946,692,969,663,729,664,282,125,514,565,277,651,747,302,498,603,856,498,828,311,856,699,306,994,882,155,312,341,644,890,869,198,220,518,356,534,851,926,41,819,471,14,768,844,599,836,199,539,610,246,745,970,857,713,431,935,835,753,984,843,278,94,779,80,707,210,104,502,842,607,904,613,490,954,904,277,953,911,656,268,57,510,913,637,967,166,987,804,654,714,331,617,654,409,459,589,575,478,536,770,373,177,284,446,313,946,151,908,230,54,874,741,753,846,787,10,287,810,328,402,256,718,351,507,735,887,962,81,406,851,511,483,500,878,433,959,225,586,708,816,585,504,49,430,57,775,749,630,971,973,626,83,517,156,895,960,102,281,403,915,358,47,235,789,575,460,842,809,569,967,189,862,408,105,281,908,789,967,920,481,253,542,866,494,496,635,970,930,4,883,751,188,68,203,327,516,237,319,732,812,420,171,832,132,961,416,291,205,885,851,148,863,806,724,328,184,708,573,809,248,683,484,232,843,111,136,814,335,964,629,615,192,105,835,871,216,773,428,127,133,274,622,969,588,738,714,625,546,0,359,86,334,27,808,551,387,715,509,200,695,948,270,561,23,215,210,16,865,133,815,544,791,190,623,146,616,897,373,401,111,810,699,11,733,706,410,831,499,518,725,39,577,534,831,537,244,455,618,313,632,641,136,280,641,573,968,473,323,963,843,211,331,421,456,488,717,482,483,696,826,942,357,869,633,563,781,64,32,711,957,688,52,690,185,914,661,83,936,251,148,215,300,989,664,661,747,547,215,121,566,599,303,154,188,546,76,587,888,485,244,526,624,399,501,359,950,206,591,216,109,313,713,72,521,384,636,903,399,981,841,786,394,834,187,438,36,629,722,365,249,212,333,160,45,656,526,266,490,783,590,887,324,667,67,947,754,74,223,296,779,305,169,562,194,111,566,502,987,831,870,347,824,313,784,26,630,356,70,847,23,264,178,886,728,472,636,176,532,576,138,420,693,142,805,870,291,997,74,459,434,975,841,3,702,669,158,397,542,792,293,400,779,400,925,835,863,691,143,249,814,290,580,100,955,473,239,474,955,531,917,453,448,192,547,858,43,326,595,225,758,732,437,115,844,510,592,33,791,537,699,269,874,752,909,399,368,692,95,557,244,690,722,638,390,855,666,306,946,123,749,295,70,216,155,365,314,289,960,480,494,364,18,754,227,316,161,749,288,65,112,361,290,25,456,605,249,657,557,592,936,448,212,533,441,215,550,591,276,658,252,908,788,795,470,534,947,473,109,637,870,714,870,788,916,585,885,475,374,954,594,50,868,259,373,127,256,491,181,643,435,931,204,587,144,283,716,739,427,124,792,457,280,731,317,765,728,806,903,187,323,61,539,574,805,668,847,64,384,580,634,479,681,596,716,417,132,871,662,682,218,273,879,431,725,786,237,610,511,205,351,303,298,89,67,846,464,877,612,222,147,755,944,508,182,72,116,944,420,688,863,411,364,851,613,970,270,379,352,10,386,865,136,710,972,842,326,409,609,810,477,439,624,584,984,998,256,821,940,357,336,843,829,88,63,346,779,92,408,321,144,901,844,676,67,969,478,838,864,271,809,566,446,111,343,447,470,829,489,480,772,964,819,739,353,659,3,231,46,40,662,464,75,559,345,769,148,934,861,92,179,193,310,390,63,24,59,801,534,326,687,784,457,654,938,268,691,974,215,242,537,784,884,244,7,262,696,688,82,877,2,74,80,477,814,584,411,410,88,707,543,882,285,457,536,633,73,452,988,704,837,733,9,314,469,14,298,59,883,328,353,750,439,845,556,514,675,244,231,398,132,499,302,274,704,147,314,474,522,513,676,135,512,561,701,431,360,627,819,662,970,608,329,654,452,470,357,632,439,165,885,544,637,617,69,316,749,926,343,904,953,91,485,807,110,146,176,662,124,158,924,692,239,631,398,904,715,296,415,355,599,530,934,76,749,496,640,468,436,193,487,927,273,520,491,850,60,774,768,393,192,248,209,244,927,452,308,871,943,775,855,339,626,57,824,599,92,6,577,364,382,766,161,758,873", + "228,135,242,881,516,399,362,404,167,775,364,88,923,203,77,438,419,652,60,504,384,562,58,141,335,406,729,42,907,924,855,138,980,10,574,816,670,218,785,338,789,303,179,411,212,824,698,684,409,774,677,798,896,511,993,917,546,666,673,770,391,667,862,374,86,465,985,372,335,966,749,265,768,265,991,400,136,625,48,115,88,145,430,29,778,696,706,262,157,706,374,162,551,147,191,826,313,829,986,506,392,413,29,575,748,978,671,48,285,157,532,732,237,782,513,544,775,828,542,15,859,204,772,609,863,720,723,259,399,743,621,296,286,918,820,40,258,515,790,476,655,953,811,59,221,375,604,409,929,232,638,558,244,36,243,147,147,612,784,637,152,823,913,553,30,591,237,627,473,817,872,954,337,870,88,314,569,748,232,727,745,784,887,875,122,381,592,97,681,399,555,246,623,411,44,711,522,225,824,99,431,916,701,299,359,812,705,250,956,947,73,799,694,245,125,386,818,191,863,88,679,484,399,117,872,283,365,823,853,999,371,201,512,841,567,57,900,826,698,423,960,540,842,517,366,398,754,649,400,902,86,595,243,816,557,626,973,438,690,772,927,206,670,31,626,693,8,749,335,453,449,727,615,380,944,866,498,2,523,247,766,661,549,339,986,431,663,991,680,182,809,895,227,533,394,799,555,240,539,541,61,728,23,126,930,213,27,770,461,93,130,700,309,436,942,200,477,885,970,52,795,972,525,253,204,701,641,651,803,846,147,431,425,725,359,0,207,108,220,673,881,749,439,212,662,658,609,362,922,857,62,587,571,798,580,192,497,46,870,715,137,511,661,622,887,472,179,440,767,213,378,644,208,686,149,317,734,73,984,892,828,132,416,196,36,358,138,676,875,317,802,729,654,707,969,871,742,247,894,603,129,871,511,650,592,819,700,830,556,888,85,133,730,86,433,666,291,107,355,338,135,649,843,107,262,57,917,245,327,442,230,4,993,88,919,498,339,475,220,833,901,733,311,336,794,83,318,220,562,869,672,138,538,492,545,404,617,87,181,489,40,308,289,922,407,206,268,25,385,683,509,913,763,608,914,757,736,171,71,152,583,346,598,245,809,126,907,867,209,267,500,185,125,585,67,260,865,527,59,801,992,125,623,62,551,213,82,931,773,401,206,509,381,956,866,849,268,275,311,797,316,502,927,789,442,914,476,820,219,485,520,296,209,280,43,870,170,190,907,58,883,296,489,408,925,388,63,251,792,487,133,37,107,239,201,825,357,147,524,997,747,126,115,805,226,532,396,975,437,874,913,605,812,491,89,178,278,908,807,788,493,92,854,20,606,554,736,665,848,385,974,387,361,946,478,414,727,153,265,513,851,125,457,367,45,613,944,153,409,579,540,750,720,440,128,460,974,855,852,622,595,458,593,769,197,101,514,186,931,350,827,266,923,290,74,122,906,134,515,485,45,902,983,16,942,488,292,455,801,920,946,544,869,756,38,418,780,273,877,603,666,747,272,905,994,182,671,380,228,718,819,711,161,878,168,597,806,897,99,704,739,699,415,983,760,948,262,343,644,463,295,405,703,326,265,633,143,173,504,738,103,737,847,786,928,492,377,130,798,423,945,528,386,643,503,415,74,589,409,910,92,742,818,177,862,861,855,142,605,240,334,261,92,30,499,676,736,449,566,727,550,912,61,166,637,11,233,208,316,883,819,698,380,499,714,998,149,169,510,737,972,757,324,727,573,114,634,102,711,224,597,554,142,615,769,27,988,995,453,459,492,3,204,627,63,911,302,122,293,782,833,523,510,711,333,863,449,425,160,516,69,607,851,496,327,794,190,69,338,649,975,763,336,162,47,821,325,22,315,141,278,228,708,933,597,940,377,166,657,888,976,899,196,992,356,756,935,19,437,418,753,524,722,932,444,635,25,393,49,296,915,762,589,528,849,606,598,271,522,766,33,705,171,793,255,923,633,348,45,813,855,639,552,222,404,649,215,230,905,605,461,166,761,674,573,879,82,85,280,953,172,931,123,258,317,20,479,71,583,661,244,462,99,745,189,962,159,483,834,689,848,891,665,417,903,491,853,942,21,520,548,614,880,667,416,469,499,178,275,517,573,784,443,195,414,640,324,508,369,654,498,61,136,132,445,23,656,630,724,873,918,222,954,577,56,909,139,763,739,309,300,417,296,265,952,881,15,112,2,184,434,967,389,855,352,905,299,539,808,421,237,724,774,901,12,197,109,123,330,734,371,392,255,935,502,865,488,147,663,773", + "252,163,809,528,698,371,801,474,971,292,52,529,626,50,772,183,322,323,148,947,932,223,611,534,672,255,777,645,274,606,109,354,276,63,336,563,149,673,373,425,581,599,984,619,578,908,485,599,212,757,105,633,336,340,650,702,99,161,978,507,297,69,813,925,914,551,627,790,919,91,855,673,67,298,379,485,129,924,366,41,712,176,671,924,416,380,925,749,533,783,689,243,818,773,798,60,128,302,216,440,919,953,513,664,68,938,473,504,653,551,101,802,639,497,45,655,959,311,559,785,293,843,684,579,261,469,174,68,212,251,220,490,692,490,656,268,193,869,339,602,936,422,97,453,228,688,944,244,289,126,273,171,921,51,609,835,699,638,134,198,218,5,811,787,380,369,774,209,952,227,554,190,254,823,191,826,457,661,688,65,680,345,384,825,868,767,160,458,962,676,106,323,412,988,354,166,54,386,604,165,463,650,275,257,249,340,454,752,53,815,360,781,735,873,859,722,384,751,304,322,920,897,486,576,125,24,51,2,940,145,926,893,98,909,697,303,488,520,292,800,940,915,702,590,654,211,352,489,275,806,921,955,201,152,271,916,822,544,751,60,799,659,652,308,844,913,784,915,339,269,701,911,453,634,212,327,986,39,876,889,25,295,780,943,898,72,267,477,753,166,581,689,402,883,171,986,891,186,222,133,381,955,353,206,811,265,540,508,763,1000,880,127,751,705,857,87,611,316,824,855,675,941,836,212,663,729,715,6,636,190,656,471,799,584,86,207,0,152,532,843,213,448,714,348,126,50,251,715,287,593,200,313,32,171,859,216,429,837,587,991,641,755,271,281,680,582,6,118,692,632,671,231,626,416,577,360,851,985,490,265,925,721,308,927,259,216,825,741,796,95,226,783,721,423,186,338,478,137,72,150,707,275,38,301,80,956,889,552,747,294,248,866,69,15,661,224,641,140,181,316,1000,673,985,935,639,606,750,238,552,96,484,717,135,333,102,244,23,875,204,110,901,331,712,558,40,808,264,566,455,355,99,243,714,433,413,14,131,191,861,243,72,179,49,545,884,775,973,751,79,923,157,951,189,700,344,289,341,534,592,480,459,145,886,241,809,964,555,76,556,141,658,626,672,826,791,457,597,155,760,418,748,141,605,621,973,909,370,955,292,275,867,905,173,116,266,698,112,347,60,395,9,791,939,627,982,6,486,243,561,905,505,54,661,443,98,675,899,638,135,31,208,730,781,730,996,438,143,767,105,948,350,802,688,557,291,252,36,698,180,204,793,232,911,903,933,397,419,949,3,350,450,865,823,193,453,947,916,808,155,949,79,845,861,858,253,278,810,599,625,751,31,854,399,248,944,658,886,730,374,312,856,378,753,431,703,757,735,850,103,882,202,204,336,759,724,696,444,899,940,630,565,861,246,901,429,786,860,713,637,451,785,890,130,360,721,760,658,976,466,395,559,217,278,40,937,169,183,208,595,528,474,383,14,969,768,459,647,883,318,906,960,425,283,428,603,933,924,566,741,629,811,204,499,558,349,833,675,557,244,350,335,699,923,195,166,348,139,517,302,632,57,517,470,788,932,637,930,595,538,504,992,843,857,5,360,830,260,457,4,327,188,211,246,147,172,652,74,947,41,808,269,61,154,633,488,967,868,250,510,741,787,242,232,485,205,438,143,671,800,277,937,207,257,731,554,723,785,460,192,482,871,809,882,43,603,29,781,334,206,21,817,645,137,32,513,678,199,41,347,374,27,886,325,193,905,867,46,396,881,252,784,246,862,682,423,466,788,877,315,280,433,800,908,45,460,681,68,542,801,171,879,597,502,586,480,500,320,147,325,877,567,604,29,189,957,526,475,921,453,875,27,358,511,210,11,707,899,936,177,299,20,604,511,113,304,204,921,534,660,16,156,154,34,411,768,539,160,290,74,446,700,308,677,44,681,863,238,150,685,265,636,695,867,756,695,443,993,624,71,258,31,920,862,892,444,969,997,932,260,816,41,367,966,35,82,350,717,724,665,347,885,493,169,503,712,987,852,649,229,476,355,381,799,63,697,888,40,855,18,80,571,983,372,361,482,484,499,588,509,750,22,491,176,310,730,488,327,636,739,989,18,855,495,377,493,297,519,941,161,187,435,511,392,354,738,470,758,728,639,674,910,320,16,868,111,187,37,140,174,488,6,128,470,166,17,586,520,510,466,35,201,958,142,747,752,907,486,362,137,354,622,794,60,683,180,673,891,255,86,602,237,329,602,257,436,117,241,714,613,242", + "116,180,249,618,89,971,53,647,462,441,213,72,181,354,142,294,258,849,427,537,751,443,142,376,379,926,228,10,805,592,563,836,447,613,78,957,404,794,489,874,358,328,988,28,242,286,725,569,109,762,413,887,224,513,174,965,11,365,725,679,913,174,484,712,91,784,995,939,27,973,756,918,764,736,161,522,826,873,935,771,907,186,990,426,694,271,16,390,711,577,86,281,298,527,720,457,341,719,819,966,535,644,759,157,494,660,260,420,623,264,461,920,833,284,953,129,693,830,413,805,348,31,504,623,57,808,373,444,319,927,705,434,588,680,897,511,746,49,627,524,894,410,254,657,159,764,741,64,161,120,848,887,834,305,255,872,151,531,390,40,995,279,892,201,341,641,979,8,655,474,830,954,605,408,696,916,609,719,206,455,74,57,248,648,491,250,222,174,285,705,975,749,882,878,304,897,313,663,597,646,390,578,612,319,350,493,653,229,377,522,43,912,696,796,30,276,21,439,25,957,465,358,828,598,265,241,647,958,77,591,703,385,995,717,211,996,940,384,291,463,985,401,818,576,1000,725,995,127,580,859,827,366,121,512,718,217,590,387,178,927,541,306,484,211,756,216,996,411,150,382,163,351,782,102,36,323,827,390,410,999,943,127,386,636,857,231,797,188,152,594,658,860,633,6,776,874,338,417,268,301,139,846,804,192,824,126,737,297,165,333,668,533,103,578,772,270,851,40,766,811,766,185,960,380,944,781,457,88,13,246,294,936,385,310,334,108,152,0,223,33,721,860,662,819,522,63,641,875,789,600,472,636,533,361,984,642,857,352,457,477,169,371,145,348,435,899,179,291,858,437,681,477,825,75,450,443,366,694,139,435,861,854,114,333,524,742,850,449,829,827,739,314,917,773,90,682,315,529,344,601,404,815,77,212,364,901,117,498,92,667,237,749,741,745,77,906,34,274,257,421,260,966,424,291,133,923,452,970,904,152,893,825,518,714,163,255,538,2,411,886,417,891,579,770,563,131,274,19,89,8,107,889,227,604,853,224,963,716,286,247,497,683,435,487,230,961,372,403,954,874,409,56,858,68,303,57,83,670,834,997,974,885,625,775,613,340,39,725,770,648,410,374,796,391,45,590,28,479,452,107,24,755,594,292,298,484,568,629,313,583,346,930,768,990,786,542,317,621,179,236,155,68,917,61,379,594,794,48,910,652,45,638,604,676,522,702,324,891,910,902,987,433,4,534,407,100,548,120,900,28,832,466,29,825,197,859,536,713,654,875,166,375,127,962,944,812,766,445,103,352,750,222,456,733,740,415,532,596,106,831,107,356,370,326,616,358,844,363,466,872,861,296,606,770,189,157,551,612,354,31,419,21,890,447,771,535,742,189,198,55,594,100,380,304,77,24,483,5,705,372,358,916,101,711,641,180,392,428,126,813,278,935,754,835,825,168,382,641,797,905,506,51,613,662,83,483,219,160,130,927,717,85,171,707,282,716,194,104,233,900,737,913,408,101,877,778,799,791,40,618,392,562,321,766,146,161,669,992,322,456,739,324,7,660,794,382,229,640,836,361,65,125,724,959,269,589,139,741,512,541,866,704,18,70,650,128,174,410,771,903,684,486,58,460,427,678,307,314,86,76,861,483,443,70,138,921,547,746,379,210,39,316,483,946,149,230,879,32,614,440,662,539,948,869,218,288,984,730,128,39,742,31,838,786,636,301,78,354,601,995,860,329,548,616,847,90,26,80,465,550,769,446,4,453,72,379,800,34,341,558,949,958,82,255,993,180,433,954,723,388,546,19,802,518,881,85,765,729,912,622,828,352,879,730,455,335,928,989,805,669,854,21,170,209,927,939,644,525,970,607,700,764,824,137,889,304,174,766,402,88,521,537,624,467,78,72,994,734,360,179,216,837,271,355,450,419,158,946,26,734,821,287,562,986,592,776,735,18,136,861,906,345,429,917,34,785,874,356,316,104,613,406,387,436,528,551,818,19,318,614,449,809,398,622,491,706,822,940,812,591,737,603,818,843,634,747,619,268,476,2,996,112,686,576,452,248,601,590,749,779,953,551,159,375,423,237,899,204,954,310,212,415,585,284,903,22,38,754,483,84,838,537,105,965,268,441,377,752,503,657,974,248,75,536,49,204,941,567,438,116,496,623,813,964,592,940,158,826,265,133,781,645,547,903,498,169,523,997,162,162,826,413,474,318,95,429,674,111,984,380,230,151,119,498,646,992,982,730,500,152,302,701,606,45,845,826,977,685,964,297", + "812,442,681,755,387,354,607,558,604,923,503,214,558,646,970,950,872,49,825,775,211,87,434,825,563,407,495,736,929,763,711,276,439,229,199,424,44,874,592,430,252,128,625,492,211,391,92,248,462,441,912,50,297,904,993,885,540,804,104,860,149,48,226,578,298,80,572,701,243,241,564,650,703,247,674,292,877,768,973,500,946,355,556,634,24,656,77,11,380,813,114,948,839,263,202,603,216,13,694,330,697,509,11,554,473,232,553,735,981,759,802,323,939,542,539,845,728,602,295,838,448,888,690,108,956,673,232,656,369,592,161,426,469,781,424,276,940,376,341,172,368,604,83,960,13,354,718,759,986,12,261,421,91,347,163,363,342,716,449,974,130,473,687,359,629,374,558,300,159,730,776,82,277,82,209,801,669,130,849,765,482,522,181,65,332,906,939,434,281,818,905,874,34,698,431,397,119,331,556,815,835,656,21,264,374,12,393,826,871,488,290,173,187,609,196,325,146,554,887,945,793,953,716,888,26,901,363,794,26,794,850,105,724,815,802,50,14,280,379,225,124,664,220,234,313,394,125,656,301,930,643,771,249,604,103,109,551,435,743,518,147,735,514,501,795,888,204,55,727,626,735,790,432,872,378,434,937,281,153,116,98,696,77,636,533,561,819,722,448,626,595,664,283,684,379,683,498,798,908,745,955,940,71,424,165,895,200,101,534,862,720,983,441,459,151,596,248,501,650,958,86,41,19,808,917,413,900,977,927,991,314,479,699,287,27,220,532,223,0,311,402,756,440,279,175,727,187,156,840,582,108,951,944,709,280,492,21,861,770,983,644,264,808,985,833,695,649,893,303,605,441,910,565,763,475,198,425,835,216,803,617,541,142,315,137,852,234,120,404,607,866,447,709,292,940,80,628,976,765,386,389,891,790,495,201,817,10,823,114,986,728,349,992,112,828,276,379,436,561,849,654,961,958,719,32,321,10,523,225,384,559,477,926,576,312,525,701,984,595,963,702,573,113,785,760,959,130,746,22,466,958,719,349,700,654,336,325,703,92,72,427,616,220,965,32,408,72,801,850,543,949,353,496,512,974,786,956,406,812,286,252,355,878,412,765,197,364,614,442,342,926,770,476,699,468,54,445,521,343,518,910,990,747,655,667,78,320,603,3,491,375,596,270,37,363,884,237,297,723,264,565,990,914,809,946,216,871,872,605,451,184,783,594,930,21,373,808,187,626,785,994,938,465,927,886,515,234,214,300,257,130,800,324,820,601,745,955,699,805,549,394,865,634,617,497,942,526,579,291,899,221,150,798,947,606,813,566,230,264,988,760,148,934,368,306,930,638,947,293,570,609,456,118,94,396,358,114,74,154,91,677,596,963,33,61,552,242,267,584,878,141,915,895,960,38,939,444,534,614,881,418,340,448,343,264,728,828,206,318,781,187,317,871,700,881,131,836,507,552,761,528,783,876,119,279,544,543,256,295,17,782,766,187,461,659,438,67,671,339,158,685,312,22,416,385,526,30,238,594,216,571,95,768,85,713,34,696,724,290,956,578,757,993,242,632,431,167,395,770,245,407,793,659,643,635,884,741,564,596,277,39,276,669,250,417,761,695,205,153,710,885,716,725,547,259,352,405,23,159,429,999,604,982,995,97,681,912,92,744,90,271,749,91,17,262,237,819,144,556,748,209,210,188,687,439,347,388,915,412,161,729,533,298,648,123,595,651,957,233,828,47,428,620,234,513,806,750,301,747,39,529,684,857,556,632,985,518,710,430,179,23,694,158,992,244,225,591,104,874,342,482,447,656,605,89,644,751,314,727,916,504,892,439,482,251,594,772,369,344,300,18,668,538,145,549,646,938,655,954,462,291,347,556,233,548,908,90,609,835,55,832,664,915,513,330,858,548,144,418,712,727,844,634,402,45,867,689,881,119,604,805,164,313,546,615,870,191,848,239,934,691,610,877,717,158,549,484,159,220,372,854,297,448,435,180,586,870,361,457,529,956,465,236,306,852,469,306,306,157,539,450,704,802,817,870,688,911,158,211,6,242,476,685,628,922,492,579,226,189,599,451,429,536,474,36,309,746,135,725,661,114,975,288,358,608,33,29,805,979,535,711,86,802,292,664,751,987,303,797,114,906,238,599,760,593,692,399,33,583,190,719,928,392,781,262,905,608,50,224,303,235,397,694,331,689,505,419,280,304,98,482,388,157,577,7,457,158,174,260,540,302,522,584,251,519,244,973,395,938,271,619,266,218,581,967,744,401,410,469,711", + "561,380,417,484,14,102,385,732,806,764,431,49,300,924,621,273,781,539,27,572,251,8,94,296,764,586,751,7,534,653,33,6,918,445,673,408,923,580,802,342,947,192,953,818,100,905,317,991,954,330,641,67,714,800,402,223,68,502,107,349,158,671,629,314,352,302,574,497,897,2,458,131,783,60,513,685,587,407,628,427,518,830,749,580,611,518,865,510,48,703,366,362,857,649,761,646,305,113,645,572,672,355,661,875,682,964,640,314,4,119,21,296,727,280,987,991,62,294,111,813,323,789,972,322,641,773,666,241,934,660,403,687,273,604,796,730,502,258,943,488,204,754,77,620,395,655,900,55,41,388,952,231,496,623,779,496,794,798,196,777,828,630,772,126,566,141,356,193,211,361,168,918,550,451,590,967,728,220,757,713,770,265,601,664,298,854,950,953,851,429,449,960,689,748,731,756,380,337,45,884,478,427,592,906,933,536,125,414,815,949,204,932,351,297,579,735,640,229,498,699,689,892,862,476,465,848,157,681,96,575,279,143,596,328,438,864,731,765,830,30,997,240,292,496,156,21,506,355,682,855,179,835,483,190,857,422,919,647,981,246,825,966,236,270,331,340,137,203,369,959,400,651,313,283,460,975,220,671,200,924,632,219,814,424,525,659,538,164,342,881,533,6,867,338,93,547,101,980,25,275,652,841,234,735,909,638,154,286,813,174,830,884,361,830,227,756,194,212,894,698,855,263,546,304,486,792,588,505,975,445,839,774,747,154,808,673,843,33,311,0,117,713,969,430,196,204,940,494,578,948,616,608,802,10,244,630,954,720,564,946,649,709,724,361,941,261,48,107,670,95,345,115,640,685,795,139,629,742,241,821,101,736,626,790,984,908,590,629,739,673,140,394,721,268,396,107,262,886,469,513,942,708,471,202,118,586,585,607,612,416,724,762,833,188,284,82,225,961,233,820,652,365,701,139,741,999,692,933,212,691,309,136,50,515,580,961,706,205,410,251,298,909,376,119,799,100,10,286,133,551,454,596,42,627,184,505,631,769,640,742,456,623,708,414,428,216,304,198,263,164,740,118,553,79,32,117,769,889,771,760,827,641,365,394,243,867,599,160,545,411,691,21,414,130,369,526,484,440,466,126,958,178,131,456,694,716,696,58,422,754,749,342,114,308,559,840,621,114,283,646,483,389,288,972,14,570,115,699,941,650,522,612,665,901,332,190,420,338,326,965,967,470,739,30,847,492,142,237,37,314,747,551,537,368,378,446,626,893,980,184,178,442,839,702,975,130,645,778,946,564,514,744,709,945,878,222,980,715,618,442,347,817,314,528,301,254,417,980,238,529,992,363,309,26,997,274,986,297,187,8,587,348,228,76,641,60,883,627,804,551,872,901,828,970,949,764,288,892,898,256,518,597,563,342,805,392,5,422,836,48,380,658,330,865,109,533,628,445,182,15,17,757,35,701,261,919,636,183,889,729,856,511,791,321,895,107,680,619,914,655,775,670,966,568,650,674,500,462,946,348,560,334,236,852,210,53,284,611,666,979,847,611,516,194,654,895,471,539,557,126,312,479,400,182,135,582,332,870,637,190,944,158,738,228,309,867,318,423,14,744,599,220,386,400,559,112,945,241,320,534,402,223,42,172,204,268,253,694,781,330,466,173,268,821,634,434,940,797,329,926,187,789,504,34,886,979,488,36,888,242,544,187,483,149,269,549,86,250,141,914,64,298,284,196,430,551,964,633,171,794,163,831,656,549,320,577,620,783,702,280,640,137,647,155,162,751,386,866,776,360,850,576,45,171,12,947,338,914,611,447,279,187,744,76,719,494,404,284,610,625,441,558,274,637,504,666,479,315,396,726,904,392,954,723,449,610,114,783,935,258,971,208,531,861,91,858,798,233,913,733,564,379,270,217,969,980,628,997,882,354,509,406,674,116,47,413,757,257,420,864,886,812,661,795,740,426,534,520,189,170,132,372,370,489,813,79,486,811,902,226,492,985,213,556,645,762,408,910,457,831,269,817,548,802,158,377,315,700,439,221,812,544,314,133,716,932,65,596,767,581,344,897,33,897,17,425,590,8,723,558,87,27,359,643,143,600,957,859,452,919,968,9,375,770,407,997,458,604,672,601,323,398,900,456,60,248,795,233,908,540,440,701,929,670,577,812,665,971,278,557,349,171,433,336,196,39,529,445,194,478,666,91,759,467,87,276,821,416,155,995,182,840,114,821,989,620,414,23,790,416,921,758,467,763,949,801,655,720,911,232", + "49,478,257,103,354,382,80,377,910,249,117,866,429,388,307,254,695,976,441,527,364,969,996,978,857,87,616,921,631,504,555,914,247,164,325,691,966,507,821,861,154,194,31,327,44,854,532,899,453,262,376,590,894,452,543,170,164,904,821,525,118,58,508,339,462,546,560,209,856,20,119,660,814,248,630,33,185,894,631,642,1000,247,966,530,477,730,48,78,665,921,214,569,516,743,813,827,96,378,889,892,163,548,890,765,110,795,70,180,971,610,82,519,926,724,199,905,60,515,135,484,325,691,996,601,892,864,597,829,954,883,782,142,634,823,699,899,740,905,816,593,73,481,846,646,740,667,683,420,617,334,405,663,764,116,184,583,657,561,153,897,980,279,920,269,975,971,282,51,928,781,655,167,625,689,899,34,859,946,784,863,442,888,808,526,234,79,408,93,955,768,984,483,66,931,300,805,517,99,647,501,668,707,718,899,800,958,612,512,464,881,252,355,889,766,998,563,605,954,831,91,1000,140,628,118,833,612,295,586,580,73,202,485,504,406,523,604,352,486,887,805,349,482,341,256,511,5,140,326,123,185,867,881,480,670,436,816,512,770,628,172,581,500,187,182,513,143,846,546,622,463,241,973,281,995,59,314,645,209,774,495,343,98,681,156,657,939,968,200,995,311,655,738,526,471,83,677,341,839,983,230,861,638,311,85,152,967,671,719,632,392,843,408,23,211,407,353,942,744,860,392,969,265,142,560,376,280,795,983,112,171,107,291,563,330,551,881,213,721,402,117,0,803,293,796,132,734,294,873,327,831,442,466,961,242,860,59,628,609,749,4,762,523,709,134,777,18,761,209,104,741,495,716,409,235,173,114,480,496,549,996,728,341,159,698,23,774,897,595,682,365,621,680,736,496,685,329,109,706,172,90,961,265,844,837,806,362,999,796,809,672,887,512,78,454,685,465,289,251,868,26,777,260,115,117,488,4,696,95,985,833,377,533,64,551,566,909,475,950,658,602,671,155,165,590,615,876,187,721,932,64,178,140,856,910,62,605,890,141,523,884,651,47,618,186,911,353,854,967,483,362,937,47,22,341,767,155,543,43,151,765,838,851,529,463,619,751,874,461,93,344,336,215,974,603,276,551,946,421,845,157,579,483,409,892,581,424,891,379,367,980,905,485,679,528,804,650,863,941,712,433,22,485,809,888,230,93,801,576,545,110,409,290,380,131,130,841,52,646,513,709,222,199,318,492,20,269,753,333,966,401,574,167,339,335,343,812,448,59,727,368,624,157,129,859,448,432,600,833,97,663,901,230,743,343,885,963,728,216,845,84,430,75,136,325,858,178,160,136,281,954,706,785,860,691,592,449,514,937,349,548,319,97,123,185,314,151,498,362,579,96,830,561,813,718,352,381,534,903,593,612,31,915,937,119,331,525,914,534,795,801,352,433,624,995,545,874,966,803,247,443,238,86,298,72,184,738,218,283,823,872,889,407,908,746,633,675,245,48,132,103,513,525,198,453,826,135,866,184,137,354,335,684,739,192,132,847,313,403,897,672,792,704,663,226,936,99,568,38,612,709,805,217,335,661,308,426,873,165,754,970,902,491,87,563,753,948,228,556,658,570,753,435,812,550,173,236,703,234,191,415,576,314,791,971,577,845,334,67,210,852,939,91,582,714,97,713,967,800,163,278,489,493,336,336,172,612,588,697,439,258,150,150,375,268,541,77,969,595,744,692,705,78,38,592,767,754,340,725,66,804,653,50,750,506,905,549,208,670,151,862,957,547,744,787,450,782,752,839,454,167,936,671,185,823,102,715,21,164,156,424,27,562,626,384,46,970,821,857,482,270,151,547,236,669,959,633,690,590,66,968,800,430,893,413,565,302,747,594,985,548,645,816,486,198,6,871,696,479,793,386,928,708,242,448,826,485,526,411,696,302,230,300,417,960,868,958,286,968,829,275,556,907,340,305,297,926,860,55,448,636,341,616,235,737,725,857,564,44,820,100,63,692,537,84,57,74,271,454,162,696,737,593,622,274,581,493,718,122,224,410,183,297,858,733,49,70,733,933,993,970,384,709,767,340,624,233,829,287,593,812,704,375,451,273,880,332,190,280,326,265,157,274,464,416,363,116,757,67,504,262,859,916,331,392,959,888,349,36,464,369,886,521,887,351,180,955,147,704,886,672,336,747,426,872,575,764,997,775,185,214,777,693,478,412,809,557,323,26,415,661,381,257,202,444,142,961,826,248,843,937,340,833,689,352,228,438,488,826,107,711", + "248,682,492,720,780,937,880,821,349,734,206,885,354,955,621,976,520,420,441,193,15,946,801,102,880,906,786,939,159,318,651,995,131,317,728,302,365,211,351,441,96,149,987,342,562,697,165,702,670,625,379,315,959,2,422,10,359,299,169,895,514,878,870,612,111,665,385,697,367,317,923,926,303,25,726,399,465,23,657,197,6,615,212,343,143,430,428,869,765,511,492,403,949,2,68,993,853,252,929,498,242,203,696,144,344,855,969,120,206,224,204,27,346,980,206,547,452,242,318,995,259,455,633,524,722,90,532,919,859,560,238,270,919,884,529,633,563,536,399,722,615,11,716,832,663,272,382,728,693,304,346,799,429,144,860,215,112,355,221,712,746,681,442,528,475,984,593,673,925,428,350,640,449,957,680,145,548,237,864,100,590,763,109,943,231,64,398,859,462,503,204,725,109,810,794,899,973,759,893,436,895,809,440,696,90,460,11,205,548,985,686,340,970,860,914,437,713,821,100,773,679,715,93,208,6,466,761,607,594,631,750,699,928,923,872,866,554,696,331,217,184,959,829,587,419,125,617,227,156,86,952,529,383,742,577,186,808,182,627,264,245,173,208,329,36,561,304,916,129,986,386,100,857,926,988,672,624,309,821,614,638,254,570,234,649,986,61,382,659,426,579,690,249,477,937,827,869,917,241,503,565,569,154,925,368,962,305,33,536,674,267,739,692,937,685,867,674,383,580,397,152,583,626,678,549,334,488,305,802,836,128,560,577,648,387,749,448,860,756,713,803,0,333,936,619,544,877,927,734,309,927,157,124,428,942,6,277,799,239,802,218,774,109,786,152,566,742,317,476,227,190,122,557,408,458,949,908,368,454,197,62,342,11,471,553,983,543,726,952,142,417,110,590,380,737,629,832,437,289,297,656,502,620,278,819,990,795,491,577,178,215,597,221,728,399,288,508,863,863,747,228,387,562,711,71,205,19,933,776,352,561,779,660,409,828,734,216,45,774,626,361,910,125,387,844,73,206,516,866,103,78,407,96,916,588,719,978,651,346,648,603,815,350,162,528,279,920,743,260,878,128,442,720,821,665,341,113,800,386,156,307,85,403,645,438,670,685,147,194,433,563,507,876,212,724,282,425,804,176,995,914,248,260,646,536,33,764,427,219,256,208,301,989,719,822,84,449,736,794,39,574,934,982,532,571,963,694,238,38,953,585,581,522,147,255,20,92,951,890,500,533,678,361,687,624,741,763,384,697,362,474,424,278,668,697,620,305,897,339,167,185,205,152,983,364,12,787,106,86,105,466,817,658,700,731,459,340,381,458,542,522,970,829,740,231,856,316,844,908,972,199,517,263,828,168,543,143,689,547,372,110,772,31,249,218,940,978,262,726,973,536,123,137,309,608,466,769,798,933,343,43,923,177,198,884,705,762,786,459,110,825,9,720,857,499,875,855,171,429,114,353,741,404,924,753,203,112,918,711,570,535,541,41,402,729,465,560,680,686,237,567,319,686,285,908,687,958,52,77,706,412,651,803,415,560,802,613,483,538,967,698,46,326,262,678,59,998,424,168,39,345,126,582,784,889,99,123,79,371,177,346,972,329,470,751,153,792,140,942,507,808,164,429,876,986,117,647,827,469,528,863,865,943,704,485,965,502,659,870,956,468,191,890,662,300,446,858,538,328,497,870,366,408,506,246,470,326,968,109,75,300,295,436,162,542,727,617,678,306,381,888,914,202,193,284,491,624,319,503,901,881,945,44,942,653,664,778,604,738,213,944,52,874,309,375,938,975,994,627,727,334,770,674,467,151,290,226,147,111,296,889,341,198,200,698,111,564,895,231,44,315,629,20,402,316,820,290,329,146,115,927,935,691,121,908,676,968,973,199,298,307,567,614,938,247,426,467,205,478,846,698,147,923,426,423,473,335,208,653,875,659,772,587,780,193,671,988,402,223,17,645,545,230,150,940,955,72,80,861,551,802,531,34,728,612,672,148,946,810,818,485,194,441,243,925,570,831,947,759,563,905,152,216,391,389,483,810,902,801,775,677,808,129,498,847,868,72,199,153,916,706,169,289,985,234,817,96,235,963,30,7,945,939,336,730,4,728,800,468,409,432,682,436,551,57,10,892,850,922,450,697,166,703,972,603,44,164,929,249,227,706,697,945,996,76,362,977,823,376,491,965,617,411,715,960,739,500,86,629,595,197,596,685,2,489,615,378,699,35,63,616,27,320,354,623,853,163,816,420,700,917,527,456,846,653,349,342,360,653,208", + "826,218,881,541,507,739,586,462,365,52,295,244,760,933,903,671,351,244,25,962,874,29,267,151,333,390,920,248,841,313,599,468,690,653,466,990,645,284,914,731,924,920,876,303,236,123,133,611,253,702,434,191,56,417,930,667,919,502,120,677,866,182,450,296,182,408,166,569,732,348,995,651,380,245,511,813,891,247,709,466,59,707,651,469,68,79,519,171,48,714,561,887,703,576,891,901,214,943,824,756,946,136,23,633,469,465,889,608,564,504,303,944,952,609,95,202,820,801,246,893,645,721,736,854,106,170,152,679,948,115,178,651,726,438,371,731,889,468,278,746,540,408,593,98,659,651,708,451,997,930,983,490,850,996,612,970,212,49,882,369,701,7,447,649,372,570,146,828,294,100,88,893,266,779,518,362,818,174,326,580,992,828,790,118,193,417,235,269,481,993,649,258,915,404,183,84,547,603,718,676,146,6,771,497,816,240,770,222,243,763,689,792,341,257,63,652,658,202,536,210,841,813,320,477,114,975,690,325,282,559,609,266,489,732,814,425,8,657,922,596,565,196,382,887,214,757,420,287,759,152,565,565,845,943,5,541,848,245,986,929,406,401,959,491,670,687,988,253,749,450,620,428,522,450,360,208,618,83,374,394,695,76,558,152,138,35,793,264,278,703,663,758,327,672,296,49,592,635,877,975,320,696,280,374,626,326,943,773,791,783,775,231,502,759,702,178,291,135,439,443,291,483,28,978,740,710,827,596,801,411,924,954,731,648,715,439,714,662,440,969,293,333,0,16,801,658,763,9,983,913,740,506,919,236,922,630,591,878,823,877,816,684,137,9,569,409,173,143,919,710,140,993,133,340,505,325,511,831,453,409,420,663,379,54,635,276,73,878,215,305,28,871,75,826,409,172,243,698,628,190,296,662,534,119,188,595,663,414,484,653,497,388,314,60,664,891,367,886,434,573,886,655,811,729,963,262,152,757,579,527,558,773,206,469,518,428,817,465,996,319,834,179,533,866,900,476,566,432,301,530,443,681,184,912,273,173,356,390,513,247,881,294,690,195,790,533,511,931,536,689,264,84,605,327,699,320,146,203,257,989,124,849,213,919,108,92,471,197,194,236,181,577,158,138,76,37,624,645,145,101,221,371,762,430,551,862,357,557,723,508,24,798,431,422,89,155,974,585,321,351,328,349,166,231,388,162,300,472,144,759,710,399,151,281,16,509,688,675,55,304,904,305,16,405,289,611,626,313,600,133,938,299,498,740,243,792,722,156,641,450,801,609,253,190,723,816,711,932,793,708,445,287,430,804,763,805,627,452,343,898,480,981,267,412,38,638,138,105,396,913,310,674,419,304,781,967,63,913,927,81,21,350,761,185,288,152,532,480,958,35,242,190,254,880,623,328,512,552,474,485,794,462,416,652,805,705,751,506,189,878,586,18,603,205,423,200,741,747,247,822,135,552,862,210,857,191,583,249,944,626,23,820,493,484,451,662,282,705,855,540,417,533,894,405,523,120,53,234,827,100,920,438,994,67,529,778,641,629,815,645,193,596,418,42,618,434,610,144,111,376,680,504,546,829,92,945,655,624,795,502,635,109,961,832,911,256,473,456,84,19,767,689,282,297,776,213,255,509,900,83,687,829,326,291,778,719,482,653,973,896,480,757,454,803,973,764,886,886,949,777,609,139,18,295,889,776,156,665,990,58,988,643,61,719,833,501,238,364,468,918,334,845,762,245,118,166,377,782,594,80,356,216,844,847,180,73,939,742,313,158,392,549,415,252,288,563,964,734,237,998,596,552,275,510,44,771,453,783,529,5,408,308,650,681,267,806,852,719,135,346,378,342,830,641,36,561,56,23,134,498,574,826,208,313,596,883,296,343,623,151,468,965,923,55,363,20,570,853,204,674,149,501,575,589,311,563,972,37,237,365,659,313,682,358,883,894,33,778,865,62,358,404,412,806,765,146,646,984,542,182,996,271,112,227,79,672,924,56,533,851,349,520,633,576,456,198,54,338,658,200,528,219,723,173,541,169,652,929,386,101,871,952,370,871,243,545,30,387,880,2,490,999,884,104,738,955,876,786,907,398,295,221,447,345,34,492,573,422,99,737,630,161,887,393,519,996,110,531,108,46,382,586,193,218,734,355,724,343,732,23,274,612,748,344,736,736,231,702,197,826,682,878,425,849,269,837,388,356,567,385,986,711,447,16,457,11,523,446,144,398,459,102,862,350,256,400,616,179,162,808,318,785,271,798,963,164,473,776,508,201", + "682,350,511,355,305,149,930,46,911,37,637,411,809,773,917,937,158,243,579,295,138,147,775,264,905,971,129,141,762,438,866,721,564,137,684,253,337,759,592,87,965,741,239,241,635,46,481,825,152,419,458,611,233,114,263,729,357,872,432,47,280,848,454,878,116,804,239,86,820,178,571,295,966,385,454,677,208,667,295,268,1000,626,641,194,16,543,278,327,468,414,733,402,112,125,784,620,435,901,886,435,657,289,630,611,700,944,787,878,422,149,855,304,459,308,818,956,735,296,636,195,545,895,991,872,878,485,838,382,371,926,950,975,12,862,807,301,765,587,321,130,390,173,394,768,941,559,60,333,452,748,272,867,711,705,944,554,753,342,197,27,51,25,626,883,818,193,425,823,215,825,84,232,592,114,502,677,535,120,886,897,873,686,671,666,769,6,117,421,747,977,82,684,435,747,802,73,138,878,718,13,51,100,711,355,516,691,674,66,502,297,488,66,932,924,178,681,344,963,765,186,341,699,515,375,569,883,939,35,529,999,273,716,779,315,280,386,453,106,753,22,476,467,427,800,964,970,586,396,47,428,682,252,361,427,641,153,214,732,756,84,54,952,447,149,811,86,682,379,871,608,146,212,960,674,144,156,308,718,505,295,30,639,859,956,19,510,295,723,790,955,453,692,385,754,60,182,555,257,944,228,909,462,654,889,614,216,511,113,510,539,933,102,252,689,296,96,371,386,798,705,927,825,935,668,295,451,409,982,9,320,781,907,905,494,509,212,348,819,279,430,796,936,16,0,947,743,742,67,593,605,623,635,454,577,921,595,637,946,765,268,483,719,588,570,838,646,552,53,298,786,412,135,230,826,782,796,73,373,766,126,745,687,287,916,404,298,255,946,580,965,600,31,96,188,5,726,219,749,645,928,134,113,597,128,672,455,375,929,537,863,889,123,969,787,36,733,747,127,587,800,989,203,165,774,332,143,787,64,194,885,505,224,298,480,319,635,487,623,317,609,675,735,234,72,670,448,223,59,665,923,836,71,863,238,621,931,358,256,440,455,330,392,118,283,232,242,100,838,761,17,138,715,224,814,496,931,847,742,319,198,998,88,414,547,598,776,919,396,74,946,330,378,152,357,840,302,570,125,376,998,659,872,806,235,330,331,705,599,766,227,453,68,170,920,413,365,599,26,40,609,364,91,724,70,104,365,715,359,42,10,424,466,638,369,287,154,922,126,465,997,127,811,331,996,977,441,261,816,79,704,402,170,185,941,355,478,795,382,307,719,567,70,925,545,298,832,709,395,645,402,413,665,977,429,321,899,977,882,416,666,941,259,931,244,276,461,712,703,948,612,630,197,25,595,68,151,679,556,596,755,197,391,676,998,735,792,730,565,175,307,773,412,342,327,209,429,784,725,828,714,851,873,246,619,598,363,615,912,637,579,940,138,119,552,262,89,779,296,73,453,622,742,599,725,848,448,308,175,859,40,761,163,235,702,643,189,930,847,187,44,66,952,95,625,7,936,232,552,915,838,284,344,915,76,614,540,154,258,723,541,343,486,248,182,12,317,102,996,945,713,102,165,89,944,482,508,418,495,662,110,442,604,732,426,145,400,230,940,907,125,212,196,627,821,550,920,672,952,491,833,151,272,208,101,228,769,812,154,225,36,22,357,236,470,333,273,681,221,220,613,900,266,483,743,741,611,516,545,323,985,800,888,189,654,736,739,619,878,681,476,345,26,170,1000,58,259,660,512,205,902,213,491,220,764,668,293,237,332,284,235,388,614,560,184,626,608,236,813,419,221,566,656,148,758,622,570,74,287,302,259,729,387,530,499,241,619,81,885,763,48,772,658,542,736,90,41,218,339,425,501,867,943,915,940,497,30,725,730,548,747,442,989,390,893,586,851,448,858,564,667,272,71,157,102,846,443,878,89,654,480,156,23,688,240,241,327,526,391,472,783,648,293,482,138,403,11,268,686,243,978,776,363,954,899,53,371,102,393,562,282,559,173,722,315,965,548,874,782,276,723,585,237,776,631,368,838,612,510,443,72,112,367,238,956,148,309,89,816,164,293,175,714,391,451,735,349,922,6,163,912,490,811,744,971,5,934,530,652,553,875,229,959,995,561,651,640,800,539,121,818,826,649,294,106,200,127,479,629,774,243,195,18,624,749,284,678,15,195,390,961,24,452,842,921,690,117,212,366,210,685,850,660,889,128,368,341,700,274,244,742,477,118,963,179,557,306,849,953,504,776,681,131,305,799,267,942,371,963,680,18", + "598,355,86,467,462,732,860,327,363,886,815,123,272,856,606,89,24,847,272,794,439,449,739,224,985,359,966,909,688,859,879,97,334,952,48,950,161,737,894,886,563,864,244,205,55,506,807,310,159,168,937,599,658,338,482,142,816,854,147,158,105,720,117,861,802,738,671,350,565,34,4,620,56,788,869,536,288,697,456,797,899,230,305,858,225,19,671,867,166,156,599,705,358,173,695,368,172,897,142,42,526,457,688,251,375,410,480,43,802,966,64,633,269,783,997,369,579,243,372,513,255,741,491,466,484,241,881,34,824,943,610,148,57,934,417,709,360,259,778,751,29,21,412,257,114,328,976,855,168,545,339,55,672,582,110,735,226,447,266,874,643,718,645,262,423,748,717,873,748,523,941,604,58,929,579,448,134,485,431,855,767,209,791,133,514,216,446,308,661,440,517,298,568,611,174,374,130,885,598,948,147,844,953,11,206,54,85,556,751,748,314,793,170,137,312,342,619,390,649,962,307,550,25,306,661,784,959,116,222,468,812,476,685,580,379,575,584,98,356,391,274,180,37,899,457,705,924,456,481,658,344,868,877,527,886,579,469,564,926,521,690,434,220,101,752,938,211,580,162,156,310,226,865,807,823,976,353,72,747,950,193,873,578,1000,953,502,993,574,978,453,582,813,34,472,985,50,978,229,320,298,952,274,314,510,240,594,678,672,478,896,564,677,148,487,451,368,314,44,648,539,904,618,927,777,832,87,410,728,435,770,864,709,666,703,200,662,126,522,175,196,132,619,801,947,0,620,111,197,137,359,422,53,34,690,138,856,998,458,70,99,142,75,672,175,711,991,890,767,26,640,216,988,550,611,688,739,531,217,788,311,214,630,220,427,352,745,225,151,504,84,812,687,505,689,225,223,955,889,963,205,259,673,398,608,636,256,544,194,895,900,793,349,595,412,566,268,902,144,815,515,174,41,310,485,71,879,209,68,984,732,537,166,625,383,586,715,172,885,323,964,888,305,936,346,640,52,129,886,645,222,415,506,17,298,486,352,125,279,465,156,640,269,179,934,570,775,442,803,716,963,793,32,623,991,112,797,84,620,296,76,115,737,372,788,150,862,610,38,382,823,725,400,989,462,746,372,334,226,347,72,678,331,407,5,630,933,415,729,68,287,883,90,963,751,828,72,718,257,300,839,513,386,846,350,977,467,708,435,267,448,812,856,833,716,754,961,786,766,726,444,528,449,927,844,946,573,915,654,262,823,19,608,499,895,683,501,445,190,257,512,639,256,447,591,86,868,658,945,351,902,190,882,12,299,543,30,91,454,370,311,921,527,602,153,363,924,71,434,738,750,177,646,395,94,399,379,176,13,405,129,19,326,920,653,6,115,168,727,458,850,980,198,448,4,737,771,112,596,496,533,468,93,559,222,753,968,899,857,150,913,295,169,105,899,616,438,134,688,679,460,595,256,979,622,159,373,617,866,486,295,2,284,524,720,384,244,195,194,872,569,955,659,887,617,400,660,207,674,769,38,52,280,237,755,50,915,297,763,588,954,381,912,493,347,650,742,471,927,439,73,67,128,694,645,796,647,227,620,636,433,213,507,167,28,318,533,962,944,150,536,945,840,375,278,966,330,111,127,984,138,205,697,33,965,398,636,399,726,546,618,447,205,949,605,619,263,945,354,125,412,776,675,944,825,125,682,126,269,169,668,240,169,843,272,177,405,110,832,702,788,910,152,150,609,436,126,946,296,375,605,266,505,553,426,228,114,315,914,517,938,960,104,551,373,225,876,775,749,879,374,521,412,318,410,671,306,937,532,341,258,222,533,489,571,749,111,837,901,218,697,150,535,547,258,30,975,367,265,718,719,292,609,911,422,284,615,295,28,479,158,410,496,948,251,959,569,407,141,543,209,336,326,205,527,797,891,625,928,292,290,820,888,211,198,475,908,677,804,731,823,316,992,320,185,198,98,487,894,334,58,633,41,501,771,708,609,297,534,869,18,716,527,594,768,588,21,242,857,76,135,257,278,149,602,324,219,505,125,350,604,879,248,677,987,19,556,683,928,32,203,505,264,816,491,33,451,861,87,328,845,146,385,852,452,424,10,867,356,579,593,550,614,141,382,438,269,376,173,707,784,444,599,743,157,640,515,903,618,800,310,829,424,827,884,926,207,482,895,957,666,465,640,975,784,301,319,691,54,524,177,256,671,584,758,932,941,410,729,679,913,616,478,943,276,351,318,212,57,36,22,917,285,567,343,430,421,751,653,591,154", + "900,533,105,478,897,597,162,46,539,981,756,105,102,796,585,567,649,36,366,1,552,396,345,627,62,313,949,754,780,956,586,884,511,697,929,167,741,241,67,421,968,414,111,440,703,470,137,224,629,311,179,495,67,276,316,361,329,918,101,61,495,671,138,213,59,134,481,794,513,493,342,572,979,374,973,131,427,834,615,989,828,492,583,409,474,531,282,238,352,393,981,43,763,830,15,893,476,218,84,831,871,680,438,2,609,889,318,199,759,640,976,842,86,630,400,561,878,894,68,608,716,248,780,579,948,10,875,904,922,748,144,420,144,682,861,90,712,22,559,352,774,74,889,967,414,357,901,216,921,647,848,915,551,379,158,669,684,678,228,113,118,192,930,849,722,663,630,190,991,844,869,95,73,917,317,617,654,837,938,925,950,135,404,255,462,662,279,894,110,685,142,992,446,286,76,36,479,885,139,48,872,126,78,464,847,198,162,250,462,581,368,609,527,448,533,291,170,784,942,601,848,103,442,672,316,164,595,21,306,640,569,738,291,64,886,22,168,220,904,258,889,696,339,549,687,815,629,403,755,915,373,952,835,234,128,837,993,758,935,260,95,886,435,669,121,722,840,206,420,616,472,935,75,628,799,676,733,497,796,90,494,574,546,162,759,629,750,948,321,946,56,589,842,477,308,894,716,298,871,180,221,710,679,737,765,663,176,712,944,961,583,911,631,910,971,837,828,9,781,806,246,227,665,386,414,734,400,228,832,999,529,577,53,6,695,658,50,63,727,204,734,544,658,743,620,0,894,397,422,705,954,921,322,307,520,654,619,161,594,769,712,590,918,825,945,787,505,486,839,87,427,112,405,997,191,142,450,736,317,632,177,913,819,9,218,78,942,468,858,163,707,567,806,650,367,383,577,496,941,375,543,822,528,182,772,685,356,815,87,608,671,313,815,712,924,975,421,852,766,745,257,590,459,233,770,621,259,65,70,788,813,740,911,893,433,873,390,393,327,353,158,986,72,789,363,182,17,859,795,978,803,41,14,171,361,452,546,24,113,671,526,894,785,564,636,890,233,98,631,768,397,732,107,575,332,485,216,511,563,213,300,973,234,771,899,178,186,356,399,962,299,332,789,527,627,790,399,955,108,915,77,201,618,615,854,212,119,883,704,305,122,716,518,35,757,229,842,231,11,237,864,567,600,553,970,680,547,330,865,767,443,257,467,310,644,97,479,135,577,965,978,935,618,904,231,514,244,716,125,192,679,113,826,493,290,703,761,287,109,248,752,895,713,968,62,979,795,725,854,513,991,436,602,860,624,444,430,715,240,308,804,766,612,672,963,488,619,427,235,192,635,201,602,42,944,96,464,108,119,631,69,708,101,30,423,108,113,356,529,962,746,66,928,127,570,513,714,595,260,577,420,628,958,473,800,317,618,262,984,289,668,713,246,69,394,190,803,466,128,593,361,900,45,680,304,618,945,568,42,522,575,618,832,551,771,286,629,379,797,116,891,243,340,123,314,956,859,127,355,140,565,549,229,348,735,824,665,523,941,246,206,63,242,103,693,487,225,836,606,545,557,184,303,732,409,359,870,231,485,594,998,129,855,583,785,312,56,480,192,893,513,992,937,67,954,854,782,700,514,911,156,643,209,828,414,340,877,140,98,905,266,722,146,22,758,111,278,678,690,798,773,441,254,566,498,500,622,501,78,587,141,605,301,906,580,954,599,995,289,379,833,532,206,557,222,212,598,832,858,435,361,500,884,401,339,495,461,595,344,815,107,895,980,514,243,369,997,541,498,585,957,420,736,200,102,216,611,969,992,278,156,989,584,416,416,640,473,435,272,156,506,626,193,863,112,381,664,518,806,205,383,269,707,663,304,585,279,72,200,668,807,733,655,47,944,781,327,49,575,995,137,670,868,112,90,145,85,758,285,308,743,816,856,713,542,984,263,821,71,140,511,161,156,359,399,505,869,250,770,7,110,602,890,897,924,108,596,341,896,251,361,73,125,376,976,411,49,995,195,881,518,421,753,523,36,612,88,298,217,892,481,213,790,847,54,982,513,25,782,162,42,968,429,331,377,708,511,97,334,422,756,889,627,254,144,768,890,780,734,564,517,714,667,237,456,87,376,178,299,470,625,65,363,115,749,599,407,803,554,311,821,270,790,693,780,201,414,938,369,64,66,146,219,336,993,715,643,578,937,271,589,452,431,417,297,641,975,441,191,3,843,532,532,205,831,371,966,289,524,828,803,975,35,987,393,932,767,796,76,88", + "239,870,262,787,623,236,509,1000,768,178,216,565,948,209,913,348,587,477,28,396,488,146,528,538,971,318,560,830,131,904,61,853,416,641,662,122,79,86,429,254,900,829,103,614,600,522,592,630,630,198,258,52,113,466,182,850,303,32,373,91,594,327,468,260,139,350,431,614,875,810,90,386,849,98,947,277,212,385,223,770,381,299,559,160,871,233,740,344,506,84,248,357,380,241,552,345,163,732,387,389,838,545,419,503,10,989,362,320,705,310,122,586,174,805,459,502,443,193,317,362,746,546,654,950,594,528,289,934,527,925,797,749,809,702,764,36,908,505,52,161,538,739,291,346,511,305,505,253,131,329,621,958,252,132,638,56,732,619,220,450,143,261,614,121,191,373,958,118,320,802,825,737,696,559,105,68,645,541,898,971,116,428,178,495,352,885,563,536,165,890,604,279,603,334,554,761,829,321,486,551,954,747,883,666,528,240,829,420,675,330,184,24,160,495,331,78,921,672,181,52,738,608,724,18,405,530,8,336,478,570,734,457,304,144,148,66,199,984,657,892,572,702,280,944,687,208,616,415,453,861,910,240,865,786,615,282,483,824,551,123,88,776,467,314,497,764,348,915,194,979,994,135,379,707,874,329,749,81,504,223,266,164,788,988,445,82,502,892,978,365,236,141,885,816,238,962,93,152,587,81,64,877,626,593,666,575,552,101,179,110,30,557,851,526,364,537,371,348,145,782,465,858,75,678,163,130,176,597,845,704,123,110,927,172,948,609,251,641,187,940,294,877,763,742,111,894,0,664,816,189,659,335,599,61,630,115,869,990,699,686,142,301,564,995,711,378,583,615,175,785,537,352,341,418,784,111,782,415,880,295,731,908,890,488,335,479,129,979,208,487,266,581,380,842,115,974,750,933,277,961,63,969,925,599,271,816,393,302,31,271,522,856,126,251,314,316,347,961,392,252,666,336,588,681,755,777,508,724,172,485,984,154,988,944,619,475,791,719,483,76,26,523,751,966,594,893,308,128,246,128,763,554,376,632,443,482,741,299,218,917,190,400,801,66,481,446,246,622,826,655,847,304,468,324,680,698,587,705,568,845,678,431,942,493,112,757,897,184,220,520,255,915,348,745,967,26,252,73,654,720,616,76,106,320,616,394,596,696,664,341,643,299,236,86,46,945,474,175,721,150,884,431,398,859,152,370,361,434,171,192,423,589,769,778,300,922,298,908,148,31,957,960,301,809,256,543,244,359,540,788,767,671,849,316,105,258,915,535,621,881,651,259,311,323,911,61,101,752,909,241,992,14,676,371,76,486,142,267,924,902,355,804,538,212,35,704,658,552,484,722,541,259,231,70,507,735,884,81,939,651,577,634,951,834,35,577,255,351,895,781,680,841,68,217,882,256,287,36,39,379,788,969,437,224,235,902,639,107,297,500,808,80,449,149,424,191,369,955,794,499,661,348,440,484,404,232,226,855,912,466,490,978,601,122,130,339,286,339,190,307,680,935,358,835,840,593,891,571,638,543,680,274,715,109,835,89,362,299,724,34,661,812,465,284,545,953,662,617,158,517,210,189,412,35,950,592,538,623,291,469,573,610,550,688,577,316,20,193,73,962,265,609,634,620,867,318,951,276,764,208,798,536,40,937,718,14,21,191,236,117,190,582,681,497,74,360,955,173,725,773,430,890,387,899,546,130,829,532,268,105,93,144,803,63,482,685,780,792,946,492,952,464,774,945,423,354,257,564,372,280,629,273,623,987,59,602,810,172,795,468,419,262,879,34,366,830,325,882,250,315,581,587,565,714,21,97,798,373,875,702,23,541,183,144,54,871,965,48,94,700,963,152,661,874,54,240,479,251,621,192,896,266,517,90,20,671,807,969,611,721,770,775,233,325,580,293,954,556,39,262,505,244,430,755,855,648,327,544,458,256,584,278,368,703,28,268,119,491,312,244,853,741,865,6,17,728,389,324,636,961,858,859,518,845,436,205,707,671,630,50,813,58,863,837,303,4,423,500,39,866,774,915,732,504,278,983,48,595,284,740,579,36,980,580,556,995,454,60,147,926,436,815,344,438,791,34,509,173,642,3,560,465,426,41,56,288,359,605,328,243,829,771,511,259,99,263,501,663,432,786,760,950,257,489,400,807,258,671,413,427,42,848,489,989,722,28,762,420,818,890,826,485,654,767,904,185,978,490,695,194,217,416,218,845,52,908,512,147,987,762,3,306,591,473,942,58,188,315,231,808,399,322,262,977,388,163,711,466,429,983", + "652,515,641,937,397,703,899,936,415,845,965,701,52,839,78,251,172,578,650,118,346,584,380,151,214,155,98,708,725,258,269,603,825,955,425,302,642,482,260,77,938,384,281,55,533,883,103,215,912,724,429,655,562,968,234,716,151,905,688,261,718,606,691,419,68,429,193,848,206,608,527,760,169,587,818,639,485,297,784,330,892,496,589,369,933,262,714,260,204,430,728,223,160,912,363,316,594,117,280,47,184,652,347,431,669,216,697,691,394,426,336,320,578,884,125,132,598,383,278,843,631,307,259,192,132,735,86,332,382,922,980,572,849,393,209,524,551,636,807,944,417,229,334,39,580,990,369,346,760,170,933,646,819,843,102,383,985,148,284,682,524,147,44,661,269,993,476,341,562,60,803,751,75,192,322,882,288,510,943,866,140,922,750,175,28,144,704,504,979,521,503,568,151,925,223,501,271,417,959,99,492,517,564,405,180,685,778,684,372,471,175,93,649,50,519,786,746,143,953,861,892,846,268,490,595,590,70,361,260,495,394,700,314,891,461,84,429,710,392,482,744,579,335,913,119,904,770,430,496,787,805,456,561,194,993,573,360,264,80,356,448,444,783,521,631,871,36,242,674,495,493,651,732,920,96,617,542,787,754,74,493,312,719,433,487,624,115,949,259,454,43,89,407,684,584,967,369,26,214,685,832,25,655,827,232,302,40,819,656,9,96,906,106,240,417,84,225,139,234,236,592,329,244,465,842,203,778,475,267,778,45,682,218,391,270,362,715,875,156,494,873,927,9,67,197,397,664,0,267,905,469,660,50,750,618,323,615,696,528,158,615,545,398,128,484,98,879,959,944,619,529,931,637,416,578,320,793,135,89,538,930,440,560,969,344,778,862,566,346,493,341,233,631,789,224,100,560,997,342,335,83,898,220,175,435,375,116,529,789,500,946,892,307,36,578,460,159,713,690,755,600,938,172,382,354,1000,807,6,528,943,611,17,408,226,762,184,394,930,971,570,224,179,259,665,689,43,67,680,914,124,686,993,403,651,561,519,336,23,572,199,439,51,9,603,669,574,334,12,847,383,906,604,875,854,776,778,693,172,405,586,917,129,790,962,879,861,764,375,369,66,841,686,975,513,745,767,304,97,111,865,75,31,150,510,956,265,64,216,607,506,910,40,513,867,181,4,109,973,194,368,98,139,244,825,324,482,577,788,809,953,425,155,585,39,892,92,748,914,675,505,992,405,546,702,732,820,584,794,734,517,61,306,820,140,470,983,59,697,728,802,151,829,666,818,204,515,513,54,231,583,706,651,899,959,913,395,58,808,867,55,787,598,496,158,480,246,984,182,468,696,400,100,649,15,940,159,23,283,221,489,262,122,372,526,682,842,499,750,96,974,488,729,368,2,802,10,361,866,464,704,372,343,902,873,536,77,562,434,625,301,573,25,721,792,453,18,190,500,398,840,220,996,218,163,856,297,554,816,493,328,809,374,139,890,409,455,154,158,896,838,70,397,465,645,693,236,311,268,292,322,697,772,827,871,183,586,156,800,588,48,126,153,991,288,19,789,301,594,128,550,902,591,76,608,499,450,207,641,29,214,6,55,240,256,777,939,185,294,33,781,735,894,531,879,496,653,448,42,637,99,827,229,64,360,303,255,555,853,95,334,501,17,942,67,65,956,919,115,450,403,197,20,65,197,427,849,488,188,555,948,228,115,768,780,796,918,618,5,726,111,415,248,270,398,228,754,854,906,771,821,884,72,474,689,27,317,922,191,166,653,987,651,352,684,82,851,959,508,964,921,86,71,597,404,155,618,198,429,917,147,938,760,926,386,896,351,551,912,160,912,581,512,667,672,362,211,93,826,160,849,225,556,709,182,183,194,179,856,344,200,347,991,72,47,985,506,869,316,934,399,591,331,937,627,945,958,812,687,277,138,452,98,5,963,430,812,486,263,243,54,973,845,727,17,618,807,372,194,747,585,150,258,464,263,329,773,166,245,833,371,228,113,143,552,934,432,773,27,20,358,218,532,953,472,361,311,707,234,400,183,105,894,221,922,806,985,385,240,616,309,99,739,518,961,738,959,753,24,923,661,288,570,119,148,891,607,532,157,234,902,610,23,44,652,36,7,981,537,323,115,502,395,226,422,418,128,306,631,797,378,613,323,31,846,54,768,440,196,200,71,500,235,812,258,728,398,76,333,315,352,72,989,134,181,708,555,975,382,564,642,835,438,977,370,203,621,347,282,937,350,726,599,355,723,235,329,367,295,766,592", + "367,757,977,241,247,633,464,412,102,796,396,256,325,188,516,360,110,211,613,371,451,740,628,169,530,102,81,795,798,917,926,295,150,221,96,487,227,99,989,631,774,535,858,713,699,70,263,725,989,516,692,52,154,91,262,516,744,754,848,674,732,453,264,369,62,600,95,166,837,668,364,456,117,758,517,529,904,929,458,264,889,962,309,710,687,805,68,853,730,520,190,278,959,948,789,668,292,538,598,963,636,581,143,506,686,779,680,419,242,40,731,740,286,60,976,121,387,994,775,267,216,88,161,405,177,72,521,117,218,508,384,845,802,653,831,213,488,795,863,506,104,418,321,694,998,968,680,955,867,664,288,849,786,98,512,375,808,26,289,97,334,275,781,696,409,469,940,770,608,832,56,695,228,404,320,738,439,994,386,322,562,481,409,611,550,480,73,62,288,976,193,366,244,495,865,84,686,116,889,315,172,527,840,837,314,875,810,455,659,374,846,626,972,262,350,58,661,769,471,684,456,440,190,748,184,282,4,539,721,608,905,898,587,195,267,187,116,619,648,231,911,52,616,428,993,692,275,797,177,634,813,239,239,816,830,132,464,416,883,327,267,226,202,832,734,266,823,538,910,712,954,853,926,192,878,27,648,840,415,462,238,694,181,475,633,649,983,778,332,1000,458,157,190,374,240,465,545,856,44,560,883,484,862,880,698,416,246,32,102,908,291,321,969,370,657,692,97,686,109,579,157,430,81,890,13,719,142,878,158,401,435,132,653,855,561,922,287,789,840,578,327,734,983,593,137,422,816,267,0,742,473,134,98,486,126,685,948,331,260,412,990,80,177,192,661,794,929,735,94,631,555,311,42,594,651,153,510,466,189,767,622,873,800,949,369,911,396,161,737,270,540,238,8,477,662,669,449,525,76,809,623,924,568,558,688,108,828,112,801,793,40,218,987,62,288,120,905,483,388,578,153,716,948,385,775,290,596,861,103,476,409,126,696,104,634,887,509,463,653,634,978,456,553,194,332,111,242,463,890,574,541,660,924,789,620,690,829,509,347,101,386,989,768,999,743,399,75,113,209,762,595,123,49,150,889,157,957,195,711,851,532,402,32,578,783,819,971,781,988,38,645,733,18,766,657,67,903,614,610,254,748,817,704,23,846,904,669,584,237,760,143,595,758,734,524,474,111,360,935,737,489,529,403,840,292,215,61,846,74,971,89,67,640,961,38,670,766,461,641,556,743,428,626,773,885,560,778,503,914,194,794,439,287,327,156,24,321,712,834,932,803,105,423,495,450,705,887,781,923,927,182,985,260,831,177,925,824,954,584,605,151,833,549,213,3,354,87,854,328,613,710,72,112,882,536,274,974,433,861,987,196,899,85,658,106,964,1000,2,481,210,433,32,789,239,129,907,214,921,499,118,74,788,686,794,172,974,566,478,61,373,113,986,486,192,561,684,577,219,486,542,195,664,814,502,357,296,850,805,9,781,661,148,888,540,592,374,706,21,946,146,597,608,515,252,735,968,199,254,466,197,243,872,793,136,296,678,658,987,519,48,713,112,748,55,680,100,333,448,653,897,984,261,504,520,102,905,638,628,825,135,221,617,628,678,720,166,217,286,775,378,386,26,655,530,727,864,349,851,89,657,77,871,724,458,907,449,674,870,998,644,576,24,803,181,673,512,89,519,570,87,13,393,562,472,436,970,974,788,534,650,380,56,132,431,460,914,13,379,487,545,893,598,957,749,411,628,613,445,544,150,227,817,720,145,659,324,123,473,850,996,500,294,502,987,451,305,322,792,233,847,635,473,496,93,425,986,171,657,348,769,434,980,890,623,533,60,308,159,491,56,898,653,681,750,762,369,260,162,25,749,509,858,349,645,444,426,545,209,87,430,355,229,332,465,930,41,993,477,992,653,826,960,462,206,403,546,591,414,333,906,258,949,407,598,130,183,163,522,523,837,998,273,817,560,920,18,11,718,320,25,882,325,622,175,953,506,626,596,212,119,952,89,244,506,486,947,865,189,333,727,1000,956,206,463,947,339,878,619,535,794,954,690,513,416,725,501,735,33,275,52,723,696,35,578,274,662,314,681,80,244,230,355,14,350,280,587,730,233,458,573,42,278,550,666,268,986,436,467,575,73,761,807,37,289,955,770,409,936,856,674,815,371,985,874,600,662,164,256,922,134,508,686,505,748,654,460,499,824,707,583,319,65,278,895,644,983,763,290,713,746,607,908,384,30,694,387,576,657,626,52,987,427,439,561,881,970,15,365,673,35", + "293,740,257,812,241,191,917,585,508,670,748,382,171,679,365,823,252,681,770,114,666,449,853,783,717,517,883,862,287,192,260,519,551,760,953,797,918,505,846,331,56,149,659,517,791,615,820,233,578,774,192,774,708,283,138,129,260,963,697,175,849,832,155,75,504,988,684,206,322,359,518,532,35,709,620,815,689,998,148,406,120,47,909,863,347,280,246,548,383,610,334,683,110,95,516,946,261,423,964,304,898,346,429,263,956,363,619,659,393,713,244,234,180,206,702,480,938,494,676,102,304,572,456,915,832,330,923,275,401,26,406,34,621,365,117,864,713,224,315,213,344,254,531,600,857,821,962,730,189,374,945,97,46,23,878,554,260,905,408,263,460,446,81,960,830,603,460,16,869,790,757,143,710,734,79,384,526,407,156,316,773,957,517,430,675,497,424,710,147,961,650,279,309,467,283,817,693,101,852,90,179,76,56,906,737,730,830,802,877,493,771,441,186,448,158,527,542,917,83,652,711,686,631,41,798,253,27,748,313,999,676,171,716,179,712,346,759,351,204,420,219,596,468,856,754,48,276,924,985,438,488,164,309,103,491,991,523,420,89,736,714,595,747,765,988,55,952,654,758,184,930,214,795,27,707,693,155,134,171,534,173,829,466,779,47,817,978,937,972,897,523,96,45,328,97,575,537,211,583,509,429,418,495,145,998,947,339,338,117,959,463,701,400,164,356,744,193,741,281,652,381,946,574,242,399,30,471,348,535,897,593,798,727,389,23,857,593,600,582,948,831,309,913,605,359,705,189,905,742,0,993,910,915,842,554,65,106,500,341,848,490,599,612,116,140,739,923,890,213,602,405,182,559,164,336,739,104,266,873,483,164,964,15,180,427,707,594,710,118,462,566,417,535,583,811,44,66,807,654,601,390,622,228,841,802,857,106,810,825,111,547,395,229,81,320,184,43,85,41,837,385,60,143,718,798,380,276,600,150,650,879,454,348,205,226,339,275,929,184,479,636,303,718,429,903,668,839,192,848,1000,964,293,564,288,841,28,262,827,899,577,451,750,285,975,213,283,103,275,888,283,567,785,732,56,859,535,813,331,740,324,594,949,998,891,617,893,571,748,206,992,737,205,43,919,8,216,580,210,969,90,585,70,41,417,266,756,88,915,422,817,1000,429,569,810,147,590,450,961,803,520,620,754,232,505,859,616,978,894,634,251,879,821,167,215,462,95,878,621,320,534,363,730,574,251,490,646,985,588,945,885,913,448,357,575,79,771,144,512,761,118,244,624,100,804,292,542,274,887,439,722,137,972,110,78,247,555,128,340,658,320,664,308,511,793,200,35,602,301,880,997,865,619,464,681,835,116,283,655,4,362,349,277,704,337,924,773,58,4,147,84,488,214,128,463,924,640,476,229,237,169,607,935,372,628,795,89,137,139,210,665,992,443,506,928,913,60,295,116,746,99,149,231,996,564,529,37,382,140,785,18,777,679,648,436,820,615,562,619,625,162,854,937,171,527,542,585,698,410,265,695,259,271,230,387,632,478,424,892,943,708,946,199,337,78,12,943,129,974,814,113,726,594,524,926,32,583,226,778,226,380,318,26,597,9,836,54,251,694,896,447,656,861,266,832,292,501,982,419,340,675,391,91,179,230,281,533,759,799,524,687,148,191,775,859,286,471,310,979,442,864,300,870,419,724,8,321,141,883,717,644,722,12,738,32,824,118,355,95,782,201,802,510,212,53,614,823,203,27,467,576,580,443,290,921,752,682,690,809,265,593,818,656,583,21,250,629,574,235,83,468,102,367,568,433,177,393,837,439,852,375,271,714,612,736,68,876,884,546,110,55,575,294,686,380,140,430,812,812,455,747,138,75,335,901,455,614,380,868,601,558,459,786,766,391,799,152,263,658,804,12,898,384,645,558,977,45,540,679,920,501,847,920,614,975,192,339,381,703,700,151,728,110,55,313,116,392,110,432,170,106,188,624,155,575,187,734,379,238,969,465,299,632,794,438,108,102,860,437,566,74,739,392,123,910,211,528,864,929,20,42,118,549,180,562,687,998,250,822,994,805,317,344,618,751,218,430,192,545,450,972,853,383,444,220,472,806,252,861,520,77,157,898,379,359,607,619,437,197,740,709,758,849,618,97,951,606,863,191,118,452,588,656,135,54,17,107,924,91,660,912,365,630,936,651,161,293,697,288,596,528,834,715,655,119,510,912,454,549,405,306,206,39,489,334,228,466,533,8,585,949,873,697,599,732,633,108,181,997,630,102", + "196,73,182,835,442,512,31,804,501,917,843,804,426,662,918,160,938,279,956,856,10,562,429,754,558,98,815,698,766,118,468,958,554,90,768,307,879,816,956,535,892,112,426,262,952,972,618,84,349,36,446,997,696,827,86,930,118,418,993,629,99,768,895,304,603,527,546,866,264,739,226,689,736,1000,756,852,931,79,487,66,897,974,43,966,611,843,732,573,35,238,504,609,951,208,554,698,484,563,265,320,218,428,445,210,849,463,673,762,30,873,800,742,339,311,631,410,486,888,542,680,947,69,345,579,109,87,145,837,425,413,470,492,868,719,921,636,722,672,814,35,313,456,453,328,537,771,879,19,171,173,515,130,410,540,617,723,221,579,757,629,991,134,922,274,936,890,603,932,656,51,656,29,772,472,195,145,792,863,595,372,750,939,429,279,216,542,493,269,538,146,874,810,29,969,382,280,944,768,473,30,562,751,764,216,268,318,397,809,723,596,869,301,965,94,31,931,475,284,579,956,817,471,499,2,26,508,147,893,884,754,71,212,555,854,281,492,777,169,868,542,681,284,518,380,469,225,427,576,472,985,618,252,832,225,759,204,680,9,453,343,657,740,992,916,152,192,990,952,765,111,641,648,352,193,490,156,323,313,689,833,804,721,190,544,782,404,771,269,441,291,295,695,873,164,522,359,453,462,67,16,512,903,154,764,802,883,673,797,520,714,311,332,888,738,502,99,176,326,564,565,574,515,225,624,960,393,899,930,766,678,572,713,365,909,215,62,200,472,108,616,442,927,740,623,422,954,659,469,473,993,0,841,306,390,97,777,25,255,121,30,230,808,668,881,969,909,889,65,441,367,362,745,804,715,929,255,346,379,126,650,498,53,986,153,207,876,875,751,101,326,860,730,241,966,558,799,256,691,511,563,989,844,802,248,642,265,44,266,598,517,256,22,398,716,245,990,34,282,822,742,891,42,606,260,14,222,895,33,578,144,983,981,979,951,751,747,21,157,35,286,699,855,783,935,404,875,578,301,943,940,841,714,914,806,274,46,693,79,787,189,41,461,154,885,479,788,126,492,845,223,262,453,594,217,837,729,597,2,108,435,885,251,654,235,919,569,129,699,831,341,101,895,642,612,327,231,22,269,684,399,476,279,14,956,829,325,661,443,747,852,529,849,423,626,813,85,804,738,393,365,889,750,268,444,909,17,427,800,779,319,44,852,340,582,696,715,996,370,916,721,882,718,176,889,398,781,776,425,499,226,646,52,523,21,587,622,263,40,644,574,558,102,977,806,930,473,256,121,986,456,526,653,218,636,728,383,236,72,419,911,688,970,731,368,375,874,864,910,216,766,938,514,845,167,272,219,255,327,464,616,867,425,56,532,964,707,763,44,866,590,453,515,962,43,442,541,811,370,272,896,232,832,65,705,905,279,490,330,417,447,412,500,530,579,387,788,811,343,875,886,237,759,703,606,205,50,959,761,408,716,292,315,952,995,62,563,29,594,236,878,306,432,798,311,548,621,921,951,677,202,628,709,803,979,438,652,951,613,563,772,9,49,310,860,895,510,103,11,872,698,233,972,530,87,439,29,618,297,973,614,855,135,445,469,966,855,806,914,644,27,689,725,531,679,877,311,893,431,660,323,18,731,764,518,380,5,88,217,793,717,275,629,934,678,251,967,952,857,230,372,939,958,560,90,21,32,636,832,488,731,472,662,60,386,86,345,973,927,617,960,30,742,328,770,862,421,876,201,874,720,547,435,230,972,518,117,317,624,235,783,55,898,738,62,326,761,797,829,141,158,93,523,859,510,340,439,96,862,448,527,791,91,103,260,798,884,390,645,94,861,565,793,297,719,558,766,562,727,978,288,691,594,101,680,944,443,83,244,113,464,891,245,715,382,774,550,378,123,356,4,68,315,525,833,62,529,689,602,560,545,365,502,61,282,540,960,667,74,191,536,146,30,840,168,893,601,319,582,414,484,631,32,667,280,10,641,40,816,192,941,351,579,439,198,6,749,317,677,457,438,875,360,110,162,979,606,638,95,424,32,518,509,966,412,980,999,305,650,942,108,72,733,671,263,409,598,488,531,299,758,181,887,511,626,157,346,57,326,103,482,961,974,839,870,980,720,966,32,181,49,943,790,915,283,355,747,982,831,176,608,473,437,560,371,497,296,874,851,327,502,563,329,169,774,835,789,596,307,393,570,373,615,236,150,57,287,770,276,361,265,230,815,778,889,947,393,296,612,440,246,629,616,276,187,312,412,276,585,599,83", + "868,837,126,148,888,569,743,956,509,277,896,444,986,768,323,509,812,34,745,463,126,383,192,731,764,238,103,602,115,809,713,344,205,678,50,634,816,212,750,364,960,790,331,398,800,501,84,84,299,444,894,469,743,445,760,624,100,291,106,166,398,926,593,460,8,827,507,403,400,857,626,773,702,402,526,552,886,824,990,562,711,728,643,12,118,179,330,288,575,67,504,814,736,652,669,481,391,261,234,284,81,210,19,81,939,72,550,190,614,185,433,504,751,606,947,296,619,899,666,197,727,336,369,282,37,560,599,249,751,389,299,550,399,777,33,131,443,443,200,909,249,989,234,38,343,268,594,833,872,880,806,836,605,468,745,214,523,739,377,927,251,785,419,203,634,804,681,464,270,19,364,841,445,35,269,403,290,16,109,586,700,913,158,333,776,222,103,726,891,668,609,650,845,506,827,578,979,661,531,839,304,477,303,348,664,690,123,555,298,851,232,98,31,280,461,31,387,906,535,355,990,846,858,26,229,815,215,887,230,274,40,551,675,642,279,39,79,928,574,96,682,508,292,720,355,208,144,183,93,586,415,493,581,985,82,139,500,484,906,954,821,11,449,526,380,785,466,708,428,56,230,431,633,667,576,705,377,177,684,240,159,606,891,666,931,534,341,525,213,669,367,817,239,73,55,54,566,875,700,87,891,994,433,357,207,653,879,445,875,128,750,968,275,136,852,849,365,45,817,770,561,130,307,629,868,107,819,559,600,325,284,335,545,127,210,587,313,636,951,608,466,157,506,635,53,921,335,660,134,910,841,0,414,749,343,307,867,366,246,784,260,2,740,480,988,42,113,494,569,474,643,791,820,873,605,771,673,253,96,604,879,777,702,148,63,498,810,215,884,791,574,371,888,27,402,338,646,151,996,101,490,302,685,440,64,831,418,838,293,306,177,881,939,321,304,656,530,470,291,138,269,314,832,338,344,762,529,116,261,438,339,750,842,352,263,130,434,807,439,765,212,552,220,789,768,370,481,687,633,469,955,453,292,819,357,376,930,749,465,232,972,839,871,886,84,135,812,672,281,704,236,237,823,507,638,311,876,189,588,802,374,105,88,817,754,786,467,516,756,432,792,750,927,844,702,421,460,387,116,537,373,19,510,791,329,917,914,807,160,811,234,978,401,211,292,620,576,41,207,447,441,93,964,409,105,66,906,224,826,391,788,237,515,10,456,811,664,430,955,739,141,292,313,380,58,123,627,639,648,292,203,782,689,154,53,48,938,231,404,411,982,685,598,803,408,200,272,51,910,956,646,105,739,700,205,113,8,958,995,418,534,235,267,201,829,309,143,806,237,899,90,732,456,950,671,819,33,356,839,105,208,293,647,519,886,774,85,237,968,527,230,935,451,728,405,854,440,791,40,738,103,679,295,725,327,206,836,619,851,327,941,931,542,970,399,281,990,217,517,470,705,220,976,200,854,886,700,881,105,610,997,114,744,546,806,848,658,684,1000,755,730,467,397,1000,212,268,926,268,657,381,177,338,51,138,107,498,20,495,535,925,283,463,133,542,878,993,974,595,951,971,743,128,314,73,494,207,465,751,22,819,173,886,882,238,891,305,162,932,182,604,773,65,932,682,670,265,966,926,495,489,917,98,2,361,707,837,624,868,88,849,144,823,92,313,242,672,623,889,260,967,263,672,200,106,719,848,88,83,915,7,202,801,44,102,194,508,230,558,718,739,451,780,182,480,908,969,144,236,703,203,80,171,436,175,360,729,891,527,768,830,653,152,124,691,804,222,920,483,322,983,841,13,742,898,189,201,288,573,148,378,214,673,714,221,789,477,962,545,429,610,555,958,237,987,936,221,744,103,159,669,279,934,613,482,527,198,783,786,335,611,78,554,508,562,429,129,363,408,873,216,648,405,460,665,789,20,569,301,858,593,536,493,675,999,828,692,374,360,584,117,333,831,238,879,903,889,65,494,659,526,532,493,484,457,318,166,947,843,542,627,694,91,398,188,295,51,598,214,149,636,819,610,608,699,609,160,412,890,777,189,15,642,366,370,673,595,481,834,934,850,839,371,888,703,656,631,249,530,553,46,869,114,258,796,549,601,946,137,800,478,432,52,451,33,332,974,146,452,406,814,373,736,500,851,764,463,3,76,269,426,75,374,758,533,971,185,485,621,281,715,639,629,542,673,409,633,691,689,885,669,897,142,604,591,688,877,508,873,335,856,818,271,666,462,216,805,747,256,103,850,999,971,42,301,873,428,501,180,740,696", + "18,600,672,453,513,328,275,239,624,905,953,503,253,161,623,618,137,303,353,70,341,940,291,63,955,888,493,616,46,524,845,625,891,421,600,310,210,143,138,285,807,466,234,974,945,869,799,18,65,272,527,134,44,324,528,77,929,75,502,459,393,196,464,952,931,279,116,805,498,965,682,450,841,586,446,946,462,442,641,451,718,201,66,838,894,702,339,886,326,752,934,608,456,86,369,520,883,877,963,343,446,846,915,43,765,427,266,17,309,636,387,555,153,889,847,596,269,954,75,674,304,951,700,100,312,812,200,534,953,867,115,950,359,157,137,602,477,992,799,556,107,46,861,122,681,554,528,865,675,616,423,697,791,420,967,834,827,370,102,332,54,213,277,441,27,434,24,62,216,325,132,298,365,521,62,992,674,567,46,761,746,711,444,318,763,288,989,536,498,644,432,939,954,811,356,984,75,843,198,653,501,301,418,887,123,736,478,111,842,218,877,282,918,556,900,608,874,331,783,68,685,296,290,934,910,875,879,688,415,936,423,83,359,213,157,33,559,94,106,95,307,176,739,930,908,467,728,224,868,375,742,248,668,863,439,996,418,457,64,312,940,580,583,566,138,866,206,685,188,769,190,793,100,474,812,579,212,13,429,226,553,395,938,496,431,497,309,442,638,857,254,352,887,253,585,494,190,712,856,773,194,413,325,971,916,526,822,563,248,531,698,78,753,908,313,791,383,628,157,569,254,952,221,328,558,147,505,592,649,196,942,479,472,561,16,571,32,533,944,802,961,124,919,454,34,322,599,50,98,915,306,414,0,631,157,172,955,710,109,159,480,652,266,151,664,155,940,750,627,228,937,287,52,107,184,311,443,240,631,245,81,327,81,492,81,706,19,477,702,715,167,545,93,910,933,469,569,273,510,757,200,862,671,546,320,36,938,459,559,613,442,618,839,919,153,232,492,904,964,900,633,13,871,74,573,550,209,57,117,394,153,553,995,105,177,752,860,630,772,735,860,948,242,239,641,382,404,542,126,222,160,479,436,665,194,632,261,460,562,264,69,801,183,454,351,876,634,740,78,6,652,605,964,258,480,952,190,986,914,186,865,922,475,108,191,249,355,873,619,439,999,961,431,216,865,326,24,849,101,575,749,126,648,456,949,848,106,190,332,673,625,293,26,995,158,989,59,347,928,468,262,7,428,426,721,70,886,126,515,659,272,862,480,91,497,10,834,780,218,801,696,266,688,29,734,586,32,351,343,671,778,739,753,870,278,178,588,915,343,985,905,36,180,917,706,571,864,902,181,326,486,977,928,941,48,84,847,800,236,211,139,22,411,946,732,794,785,32,675,685,942,687,851,161,225,243,421,766,78,13,768,885,382,549,608,332,550,602,842,135,569,760,122,736,627,285,427,690,316,482,513,10,780,282,784,668,354,66,557,363,905,726,576,981,98,179,186,316,282,733,591,241,834,165,421,16,234,868,995,458,37,172,404,436,936,480,659,945,448,869,148,392,103,461,228,160,884,130,378,401,464,251,659,657,961,638,441,396,626,453,784,280,512,915,137,546,325,330,611,632,419,299,508,959,98,902,312,177,869,134,391,879,673,817,715,594,904,171,208,924,838,83,276,709,413,621,925,581,242,934,782,465,653,634,323,205,694,112,916,978,192,678,915,422,812,377,236,632,403,492,698,516,770,233,919,640,509,890,562,82,548,322,882,472,661,736,100,549,559,700,447,473,523,958,891,962,751,9,655,339,675,240,480,544,980,644,190,831,290,252,290,467,281,622,305,305,469,559,136,13,390,497,539,878,466,499,648,415,989,346,751,92,581,284,610,768,486,964,846,272,636,177,504,463,495,928,925,41,795,33,475,373,847,633,870,949,735,953,66,402,751,806,637,746,575,714,32,183,251,116,404,838,807,748,964,357,437,381,660,650,283,117,515,878,991,671,294,509,677,719,455,841,794,607,667,396,544,371,581,507,118,223,484,367,442,763,982,189,856,560,548,358,842,346,629,426,384,538,791,208,812,917,122,480,634,573,966,848,500,519,149,868,892,901,359,122,579,440,754,877,148,655,905,668,308,301,719,530,312,269,114,918,584,572,482,609,649,67,265,685,255,393,188,18,661,414,696,907,3,820,147,799,525,424,365,477,352,472,453,752,976,526,968,394,802,351,125,900,680,514,928,634,867,537,484,35,180,67,784,670,65,61,448,861,709,767,58,436,518,352,359,538,838,101,276,866,393,541,116,304,449,505,833,280,633,467,411,712,244,522", + "555,762,693,881,754,903,381,61,812,449,608,406,884,566,901,345,790,268,303,707,793,506,428,423,940,284,53,514,664,157,394,252,258,426,806,558,804,949,327,598,262,975,693,607,377,404,557,252,976,943,182,92,898,676,744,113,643,940,332,459,240,928,747,273,549,197,370,638,500,886,864,627,111,598,16,487,752,912,50,806,843,522,561,493,830,869,241,184,123,958,991,256,948,227,787,43,775,910,557,966,956,878,28,214,202,211,115,6,701,349,658,780,456,967,188,336,674,856,60,46,869,638,608,350,402,345,275,51,673,12,857,355,698,898,613,702,615,615,643,174,946,966,90,634,826,510,295,635,164,693,343,733,590,797,332,959,528,543,885,260,636,532,736,164,677,351,695,754,793,995,229,309,993,79,65,347,259,582,396,908,746,3,129,286,795,246,146,119,742,796,288,583,760,61,750,458,306,119,822,420,845,925,505,14,586,827,265,416,669,649,134,767,243,976,643,843,6,325,796,760,185,720,690,407,461,868,797,863,316,950,73,65,153,507,615,784,902,958,249,54,175,436,327,819,399,247,228,208,352,761,563,343,326,207,175,406,956,894,505,884,767,340,773,934,796,344,830,893,824,88,643,384,197,511,58,646,57,390,423,222,593,767,213,469,420,698,506,579,299,357,690,938,25,141,751,49,930,676,115,593,182,950,429,700,203,768,339,496,355,844,334,675,106,140,711,681,751,395,70,615,325,404,689,562,61,936,625,484,392,915,461,304,715,204,865,798,171,361,709,10,242,428,236,577,690,307,61,750,486,842,390,749,631,0,73,574,388,291,90,718,210,74,448,922,648,588,549,702,876,485,742,844,737,907,828,123,864,894,46,940,926,827,500,380,437,937,436,249,508,356,264,416,164,684,506,357,319,255,725,151,909,62,756,512,169,471,762,294,595,181,713,964,578,393,976,924,403,470,859,665,837,300,128,674,77,848,906,749,729,756,330,156,494,330,755,829,595,962,186,76,940,789,792,646,373,265,32,479,433,45,903,720,349,872,561,565,189,116,998,294,291,482,42,127,117,347,969,181,897,851,635,990,551,559,24,337,760,766,790,512,148,388,87,219,533,726,946,193,851,453,208,691,945,649,970,508,225,808,290,171,921,733,415,886,580,244,697,259,17,313,784,414,305,309,542,965,340,651,659,431,90,71,81,752,262,840,300,503,492,966,692,695,705,401,597,766,254,983,114,767,406,862,980,120,59,549,541,696,247,437,190,640,536,732,626,689,200,28,53,549,50,648,293,409,774,571,134,525,446,549,944,646,825,569,834,345,534,16,535,785,153,967,531,767,964,487,271,958,981,788,384,778,754,616,512,842,498,828,439,549,347,227,964,991,858,915,9,866,758,602,921,301,76,239,367,905,446,183,329,563,657,541,886,192,837,518,491,881,802,707,621,826,592,3,963,278,361,247,794,950,583,53,406,20,754,786,763,536,312,115,877,276,771,517,222,214,130,156,664,594,7,738,660,778,205,398,204,645,650,899,519,573,309,400,175,44,986,826,149,146,723,232,440,622,524,55,857,103,545,903,709,977,502,605,344,71,706,542,774,936,660,729,231,276,695,293,1000,609,408,948,104,642,433,15,972,62,729,256,744,46,6,17,157,675,992,25,552,337,527,905,267,86,833,541,837,622,97,166,335,443,869,784,76,535,137,151,182,860,595,106,887,97,338,10,435,886,643,847,980,547,735,270,757,115,611,943,175,658,581,780,917,300,519,664,73,168,236,521,262,263,881,58,109,883,112,442,4,954,80,661,181,546,118,685,183,81,671,339,718,382,347,882,738,642,929,35,923,249,553,743,96,835,887,644,304,892,206,36,427,241,26,292,717,703,488,938,770,799,745,641,268,638,508,998,69,158,92,613,970,145,868,939,924,71,981,177,273,676,725,392,624,918,48,422,508,684,449,674,173,563,465,734,979,811,731,431,49,155,57,661,936,100,587,982,309,670,420,832,343,64,449,538,423,278,398,913,15,878,50,877,411,636,483,972,284,550,142,746,959,640,759,895,421,611,949,108,446,994,671,687,606,646,238,444,348,831,304,511,610,133,123,620,432,398,498,631,388,192,547,157,652,32,91,664,689,191,540,209,900,617,255,268,947,177,31,964,616,132,956,188,762,823,17,998,807,849,798,906,99,73,267,245,740,229,594,739,424,615,145,560,474,860,252,311,675,458,175,711,845,251,899,542,632,619,655,407,879,692,852,644,144,93,989,196,713,397,597,547,645,215", + "746,337,864,774,614,32,874,384,288,777,7,877,52,554,566,147,77,165,182,533,422,583,804,816,735,628,764,528,509,912,651,297,140,471,449,64,360,549,39,120,663,898,218,928,615,331,194,399,58,157,691,666,414,274,443,768,639,845,399,580,575,889,414,519,663,543,301,753,558,335,737,302,114,831,421,368,492,322,391,500,633,268,789,89,122,951,93,105,576,633,780,815,851,552,407,531,654,908,202,219,897,940,83,364,171,871,781,772,999,76,717,509,878,712,45,917,505,18,260,662,263,432,694,543,480,334,743,109,36,536,770,944,346,217,706,517,129,6,769,873,598,600,375,634,544,311,389,380,293,48,460,619,696,107,110,6,478,64,211,382,973,55,289,293,565,575,696,254,14,811,345,355,733,938,786,96,167,92,750,127,280,842,194,410,982,406,5,406,232,929,621,186,707,799,512,682,728,669,788,646,456,262,59,164,483,783,143,902,710,711,404,768,393,526,828,175,672,244,440,410,789,877,252,409,525,7,210,690,580,370,563,153,890,151,536,727,610,211,857,690,247,770,459,584,86,917,604,402,354,812,785,15,654,860,549,231,970,923,544,482,554,472,760,858,979,102,663,689,133,378,263,841,882,144,562,673,562,149,541,431,46,215,667,616,474,770,238,849,68,604,666,112,128,873,955,524,969,558,268,345,357,12,805,155,284,551,487,294,439,214,907,598,165,181,293,365,172,278,899,700,31,332,527,459,600,822,597,653,528,978,319,321,405,451,133,580,859,984,280,244,860,942,922,921,138,520,630,618,126,554,97,343,157,73,0,33,849,675,66,952,204,733,315,618,953,925,414,317,927,977,124,302,690,933,169,91,975,408,671,457,437,145,908,626,869,690,891,80,761,944,938,4,186,851,231,797,70,119,394,646,765,994,557,124,681,667,684,737,939,589,242,130,808,218,329,273,839,703,863,235,279,738,976,422,736,928,379,702,120,694,802,41,247,38,197,920,264,241,566,410,153,784,295,239,43,970,765,279,535,942,354,410,693,991,934,94,952,996,671,586,788,489,654,40,659,4,448,622,568,176,386,232,816,267,765,925,14,517,269,198,410,876,259,72,861,521,506,204,513,564,608,508,230,468,581,205,257,69,234,351,255,588,362,953,78,31,996,265,944,330,721,353,575,349,86,655,400,587,502,678,420,664,243,127,984,832,166,528,205,120,993,538,815,800,519,188,983,646,370,102,324,646,82,448,64,279,404,148,447,15,859,741,323,490,279,194,427,597,819,365,389,284,400,953,105,703,720,333,682,627,51,350,311,117,71,893,278,568,842,773,715,515,996,813,960,520,648,532,948,458,222,103,840,854,766,255,779,744,772,97,911,149,54,500,456,759,636,24,129,521,728,991,858,727,494,525,968,981,422,602,126,717,743,88,767,318,441,590,420,467,541,86,336,277,567,527,462,609,620,304,114,882,363,970,532,831,247,198,191,353,302,553,598,311,836,343,933,491,382,504,177,749,630,617,596,351,668,74,159,801,789,552,200,180,840,950,648,287,508,218,684,858,791,23,942,413,127,635,310,819,870,473,823,792,133,306,863,912,948,588,874,850,255,971,996,936,83,43,825,10,111,454,717,710,381,402,669,597,332,724,320,13,706,193,699,232,855,21,406,660,379,851,86,952,566,776,766,125,238,386,414,547,474,894,703,589,802,932,367,970,949,413,269,86,824,451,672,473,393,97,97,192,574,69,512,405,735,338,154,213,890,402,695,978,359,461,300,47,652,277,5,219,776,138,578,127,945,102,954,659,369,893,268,907,582,952,926,743,725,544,472,310,873,194,57,761,463,908,52,166,550,736,186,124,672,960,602,786,290,742,674,74,718,690,198,91,66,63,937,886,507,601,897,367,170,747,655,199,52,504,973,727,547,481,552,404,457,389,572,448,332,457,958,144,899,240,20,273,455,850,487,249,161,388,90,153,140,907,232,394,525,52,612,360,707,987,483,232,491,652,934,94,174,42,419,289,214,573,148,180,524,224,454,41,981,809,998,912,625,705,679,117,870,427,191,355,416,183,49,936,898,538,856,158,414,859,577,140,915,320,259,570,635,423,48,116,419,955,146,896,988,495,915,213,227,855,581,785,994,542,324,599,421,718,863,62,609,578,60,744,480,778,161,884,646,995,70,534,761,783,889,433,982,110,896,902,867,428,466,610,958,511,626,689,710,502,505,193,867,576,672,423,156,295,615,33,89,457,244,846,948,836,404,588,112,953,864,455,16,404", + "142,555,252,126,277,657,906,489,262,206,311,729,651,647,953,788,499,867,874,213,994,362,561,616,337,212,188,624,882,268,806,619,545,996,974,621,986,42,756,612,172,855,873,755,740,689,527,304,69,391,728,516,87,885,565,254,428,524,699,621,14,463,481,290,886,7,831,983,218,912,31,991,302,895,346,440,268,283,349,84,424,550,550,369,459,204,700,321,318,9,934,496,433,685,161,311,827,349,815,311,443,457,417,183,68,483,366,849,862,234,8,677,389,906,206,816,256,293,962,249,63,773,829,140,696,889,270,208,659,561,758,554,155,346,584,256,912,107,392,743,509,74,729,828,176,117,889,501,33,882,147,126,326,847,704,765,736,224,642,190,655,660,456,492,982,398,124,521,366,772,764,84,85,254,559,571,432,728,388,262,300,965,308,138,762,855,281,408,288,109,601,49,879,240,155,93,901,352,370,19,643,772,206,83,476,958,190,408,635,180,510,972,590,896,183,458,536,934,875,939,729,468,160,869,187,18,823,296,646,901,176,86,858,340,266,130,747,456,537,228,903,270,654,917,875,422,206,900,308,746,487,58,180,308,650,154,20,90,425,266,864,482,64,147,796,856,410,678,992,775,930,952,87,164,866,183,778,232,398,179,242,398,409,488,103,34,324,399,836,769,264,297,331,503,4,736,400,960,323,497,325,285,239,816,393,343,161,873,772,589,218,354,437,481,105,436,144,566,217,972,324,30,678,952,803,754,548,525,428,56,767,57,611,54,815,192,216,642,492,630,59,6,630,595,856,654,115,323,685,65,777,307,172,574,33,0,494,168,816,590,708,379,714,560,630,662,473,743,120,357,770,959,156,693,545,489,67,452,787,796,116,96,336,141,915,190,525,73,404,472,280,741,728,460,53,938,764,563,803,600,514,206,312,471,959,886,50,849,14,985,872,584,131,619,620,464,492,827,524,524,199,38,60,441,695,341,975,686,706,588,576,693,896,314,883,916,772,814,73,208,352,886,894,889,766,702,410,505,457,987,256,635,762,574,273,493,818,450,762,447,790,618,916,792,339,203,489,205,999,39,416,397,492,649,398,284,245,250,592,261,516,272,873,919,472,223,567,390,420,571,196,140,981,789,177,177,419,106,409,929,286,444,109,298,814,566,496,870,813,976,546,486,442,680,60,924,532,988,809,326,187,787,649,50,296,344,920,703,476,647,789,780,153,135,104,708,905,655,605,344,217,581,679,633,950,657,124,812,531,123,899,585,348,232,38,562,86,701,225,106,942,217,330,727,891,283,315,216,762,522,642,282,62,477,59,240,894,994,128,928,8,404,309,661,718,323,716,784,125,468,213,796,859,117,935,835,687,583,623,398,640,155,633,405,213,129,639,813,215,64,940,145,151,934,403,560,790,570,3,613,973,138,71,331,921,240,151,429,439,529,265,846,502,722,412,146,416,509,969,309,938,400,821,343,790,843,719,53,57,883,396,917,573,428,998,704,989,662,144,148,730,561,855,562,672,70,68,457,464,179,244,71,262,474,251,373,114,917,327,709,505,180,257,454,963,67,18,11,586,386,97,224,440,524,632,633,793,693,454,721,68,88,242,906,344,94,567,318,459,703,631,382,297,146,261,662,629,244,733,561,842,329,622,91,457,544,591,898,362,191,261,417,675,301,209,651,533,382,976,909,685,563,69,690,524,307,169,918,286,293,338,793,427,628,902,263,52,259,970,37,794,137,664,174,504,88,617,131,723,354,989,21,615,67,729,462,322,232,733,607,963,628,270,551,644,344,860,979,753,726,175,640,906,573,334,284,65,35,863,14,749,114,149,210,727,686,220,469,763,120,165,375,373,231,808,122,264,867,859,877,551,348,995,653,944,42,42,282,62,588,184,625,555,820,276,982,900,146,849,758,897,609,975,6,210,930,928,438,710,364,876,832,10,184,558,737,843,148,6,144,809,306,524,536,998,527,137,384,231,152,405,703,96,981,162,113,852,750,360,816,243,166,957,584,667,163,629,960,704,819,664,482,481,958,556,932,303,35,172,254,458,63,921,277,65,697,824,569,478,241,343,787,711,489,719,47,496,185,632,932,359,289,728,698,331,149,773,828,92,24,1,206,408,882,553,971,166,181,889,537,701,789,203,184,872,502,49,754,690,413,987,35,952,533,295,891,428,661,633,538,884,913,996,527,551,557,167,659,906,804,635,290,972,338,149,673,208,392,902,35,568,729,579,877,625,764,450,172,872,1000,993,807,400,569,201,664,874,419,146,315", + "170,950,424,782,764,890,921,226,73,819,690,542,725,267,59,767,26,503,824,964,782,837,797,963,205,860,935,480,310,627,552,412,402,570,935,113,177,611,643,782,888,179,341,628,849,719,872,524,262,454,752,470,412,448,845,550,726,865,258,990,447,558,389,311,730,223,780,800,221,247,682,857,102,976,150,707,945,459,640,225,566,576,873,360,865,171,733,206,174,178,667,545,756,299,241,666,606,263,83,409,160,76,657,51,856,62,105,903,71,903,227,386,927,55,718,919,705,476,910,166,671,299,165,835,858,831,833,572,30,29,31,92,847,381,111,444,281,523,879,277,656,376,578,344,696,349,272,488,115,610,76,207,302,105,801,947,322,479,696,120,309,745,734,794,963,839,799,501,576,13,155,264,240,974,633,775,616,905,446,603,986,975,579,912,637,758,159,644,900,84,716,696,287,144,971,280,826,748,224,846,941,941,867,171,94,887,414,596,905,22,447,909,597,937,455,416,226,942,983,356,331,666,705,135,686,626,746,453,781,140,538,67,225,675,331,112,831,243,585,274,875,537,749,624,490,236,941,274,387,450,48,829,46,229,568,125,701,787,148,131,609,793,571,991,681,506,871,597,483,10,577,235,666,558,831,293,708,181,856,254,38,402,310,376,537,439,114,74,722,68,998,549,755,238,936,765,896,637,807,662,619,839,829,110,213,896,41,648,830,948,216,569,304,28,510,982,32,406,690,473,760,219,44,203,542,857,121,667,857,839,257,889,839,203,544,497,429,857,21,954,628,277,591,637,998,619,869,615,948,106,25,867,955,388,849,494,0,937,585,495,201,557,920,347,213,476,756,489,171,853,933,839,739,750,898,766,916,702,656,685,83,872,562,582,35,822,26,684,673,529,623,273,358,7,60,167,133,502,458,222,284,565,791,587,288,549,400,124,117,712,895,549,975,58,904,428,354,733,315,925,909,598,831,279,145,232,154,360,181,447,611,748,208,731,829,534,498,845,613,864,606,799,179,796,744,595,205,206,549,695,976,698,710,628,187,946,847,94,719,80,658,527,720,655,80,759,165,17,372,609,465,559,134,122,505,457,258,247,406,902,170,748,110,93,121,292,999,500,991,416,592,216,530,871,826,277,39,460,206,945,107,926,911,100,26,242,247,982,76,864,679,377,969,666,307,592,66,356,251,167,446,966,128,265,285,362,694,445,768,417,991,57,154,633,112,937,427,551,131,386,157,619,348,258,386,303,498,309,855,259,545,156,169,94,185,400,461,60,349,931,405,161,499,804,361,593,24,876,663,391,992,768,960,522,445,185,840,460,619,248,96,43,926,625,643,926,640,610,545,909,773,812,632,583,380,756,399,443,326,477,147,126,861,678,856,373,397,531,209,80,632,648,636,221,14,276,820,594,606,284,63,527,966,80,525,281,984,862,114,70,240,232,453,397,933,132,345,331,441,508,197,487,522,157,956,181,698,792,280,531,976,377,827,570,911,429,232,255,385,407,43,349,524,829,934,928,29,91,728,320,853,498,561,929,319,128,709,304,804,462,35,637,929,860,533,377,429,633,943,701,211,816,223,791,576,52,714,409,259,569,101,324,815,679,779,136,358,710,822,540,861,998,714,15,463,552,212,763,408,128,565,563,71,620,269,306,454,163,165,801,538,5,627,816,959,644,449,746,181,195,218,422,456,27,363,361,992,988,182,338,337,14,971,12,303,883,414,367,514,821,312,151,301,847,654,115,847,457,212,616,265,547,665,227,170,610,662,117,684,381,447,665,362,816,914,230,4,819,681,384,699,636,696,122,961,402,783,36,499,286,73,689,845,986,815,254,897,190,570,120,153,698,717,517,746,675,772,445,447,281,334,281,500,833,117,96,225,421,257,90,690,912,427,916,110,856,480,554,237,838,806,276,987,911,660,295,578,283,431,341,885,701,630,934,974,544,507,997,391,645,794,285,452,935,958,490,535,935,362,480,524,385,488,644,64,995,747,801,757,558,864,357,534,688,650,213,352,851,485,957,580,657,833,189,228,211,861,522,912,448,182,452,364,59,522,223,207,857,784,436,201,589,301,234,97,626,509,302,881,626,182,101,39,124,173,48,901,167,222,230,560,581,923,870,421,659,725,235,37,980,196,616,42,945,628,532,403,269,962,205,675,733,678,365,43,233,899,21,602,299,62,407,105,161,2,27,48,184,435,810,658,557,817,454,376,782,880,786,63,49,904,768,586,665,141,333,148,82,2,74,43,64,105,606,242,78,883,200,45,66", + "75,316,351,884,716,789,596,356,464,542,903,11,460,532,252,506,72,318,565,350,34,81,825,90,157,206,859,988,55,79,948,211,334,502,895,664,222,385,153,593,922,785,559,308,476,306,459,987,641,109,826,589,492,746,939,770,403,161,208,31,94,248,880,429,789,548,847,513,440,702,845,29,650,493,466,734,837,514,385,282,485,344,12,379,267,732,938,675,544,425,972,612,157,216,272,156,461,459,165,628,711,866,636,473,776,645,116,577,454,476,110,524,934,533,880,852,6,663,593,360,238,664,538,205,958,396,58,454,779,266,511,687,509,926,575,683,533,476,448,842,161,281,5,184,328,161,299,691,682,573,400,224,700,702,722,364,429,852,280,272,36,454,959,965,529,929,458,602,456,624,57,386,318,302,633,215,956,626,57,19,707,357,49,773,677,835,155,10,625,694,150,718,791,459,258,490,523,135,136,61,53,158,980,79,50,88,733,996,253,754,953,493,480,472,460,390,248,972,752,268,801,204,787,384,777,18,811,771,605,257,926,244,221,660,838,55,344,350,837,610,394,519,491,46,673,655,593,938,2,595,968,556,440,145,963,565,341,571,996,376,823,293,606,595,702,427,173,803,626,89,967,489,543,945,611,432,913,271,274,800,357,683,294,930,867,224,774,111,673,467,191,32,306,586,81,226,108,462,807,865,344,656,344,73,96,859,117,115,96,320,292,911,141,272,344,173,167,514,57,358,917,58,740,695,512,187,452,670,697,915,646,58,147,303,791,46,837,352,861,720,609,799,878,946,458,161,990,696,331,500,255,366,710,291,675,168,937,0,549,562,735,518,523,452,833,284,619,798,505,354,51,867,270,659,600,386,155,501,934,161,261,324,190,576,307,165,205,355,446,331,456,458,354,144,155,174,723,955,938,772,549,979,547,940,607,122,693,776,368,921,404,8,179,491,632,46,935,88,368,309,904,787,664,823,947,229,904,263,555,385,988,780,552,559,967,602,283,437,829,737,585,277,116,391,376,148,664,134,569,297,993,496,304,787,810,931,83,557,297,124,55,744,552,348,418,103,338,55,271,797,915,66,546,585,851,201,248,830,681,341,920,645,906,866,718,470,818,858,749,496,732,523,79,767,423,419,814,500,275,432,984,549,592,267,702,916,31,908,538,497,747,474,323,792,257,148,268,590,48,246,436,972,530,510,370,56,215,192,700,240,83,621,224,108,355,250,462,639,149,840,19,658,592,836,45,889,361,953,409,11,766,553,682,165,610,91,564,245,3,156,688,493,462,466,936,774,883,894,822,465,922,86,732,206,382,622,332,341,152,430,548,206,705,998,436,934,593,23,930,230,456,582,516,327,782,690,285,987,25,827,616,685,238,577,784,517,134,179,77,760,386,331,130,891,955,325,698,443,224,635,641,613,19,461,48,275,521,218,262,179,577,321,319,612,445,417,295,563,760,79,779,723,466,800,778,388,870,473,263,219,692,428,169,711,915,672,708,684,935,364,83,300,753,577,587,197,255,682,644,129,609,746,638,251,127,486,564,443,192,542,837,425,611,275,972,977,949,715,295,838,539,936,754,333,202,252,316,663,594,606,344,832,807,741,399,616,231,107,787,508,188,601,975,943,555,599,447,347,522,522,994,53,833,401,95,444,455,711,762,972,593,826,401,291,747,253,862,345,874,568,474,189,752,265,270,400,854,216,988,657,135,341,559,653,537,648,667,140,723,12,162,287,805,77,179,423,828,152,125,558,151,249,695,712,451,18,510,452,602,439,727,137,860,41,193,354,896,777,797,210,757,549,928,53,441,298,814,195,502,747,229,764,318,156,245,570,430,385,374,250,112,322,755,245,364,570,681,550,355,275,492,986,689,64,978,816,395,86,692,723,184,875,187,483,707,583,894,577,198,569,623,531,425,12,128,7,728,781,69,330,829,674,731,738,375,712,210,955,949,956,213,38,726,999,61,781,182,496,870,130,80,767,456,412,687,227,768,691,96,990,976,598,535,530,235,935,43,192,747,363,257,660,980,550,810,530,232,773,68,990,770,873,8,81,653,138,837,510,865,635,325,437,893,874,791,407,14,874,689,224,227,32,743,487,81,982,400,466,113,408,45,962,270,389,673,987,857,240,646,159,460,785,857,326,151,727,676,322,320,209,854,411,839,590,537,504,797,247,489,504,987,208,830,121,220,145,468,760,4,773,968,203,770,452,333,90,76,650,688,728,482,699,876,92,976,878,931,917,5,648,15,293,998,286,642,747,126,838,216,673", + "788,235,634,518,100,873,405,638,930,236,664,212,707,122,599,486,631,75,184,480,248,998,497,137,218,461,758,433,670,49,899,532,556,912,105,804,746,303,316,834,835,150,913,396,444,861,100,237,999,107,328,680,356,685,176,641,989,479,464,665,513,92,833,733,818,828,747,288,963,359,639,160,726,409,685,166,813,66,368,624,35,185,327,942,560,20,840,742,901,993,291,369,285,732,606,454,753,196,598,184,280,820,518,505,904,163,696,597,429,898,182,72,9,351,968,787,619,909,146,873,259,146,665,479,559,972,496,298,357,605,775,907,911,776,421,957,994,281,207,243,422,841,423,13,214,913,327,759,327,586,505,438,130,92,870,768,313,88,444,943,108,321,310,353,978,510,250,424,303,176,76,748,337,454,65,182,580,813,266,310,732,769,704,744,890,688,963,240,842,950,535,305,622,413,876,644,988,837,461,65,135,542,591,74,940,289,950,363,279,933,494,192,585,945,603,447,134,733,253,902,441,807,360,396,512,716,182,433,196,599,400,540,925,36,614,362,689,714,19,62,63,237,244,289,447,582,272,631,780,711,345,736,367,80,132,674,639,624,413,717,242,805,657,655,988,878,774,883,503,274,656,291,734,528,552,840,403,52,767,449,140,590,928,259,823,212,260,616,412,555,247,705,629,369,896,499,470,393,703,223,994,228,498,948,592,919,648,190,630,755,447,994,874,420,391,290,236,953,218,364,5,988,259,621,177,701,148,198,290,53,565,730,199,904,190,870,587,457,770,564,749,239,823,765,70,594,699,528,260,341,121,246,109,90,66,816,585,549,0,740,432,444,270,385,241,553,924,244,964,142,365,537,6,224,243,201,663,303,569,717,88,221,87,266,657,540,765,656,910,134,514,923,947,361,602,570,602,779,343,622,214,469,385,952,79,966,446,484,829,938,714,618,115,227,893,445,686,837,244,528,733,601,246,491,378,333,801,161,532,21,928,112,88,448,374,613,643,109,891,209,659,791,685,282,736,629,612,345,687,387,204,71,377,267,311,784,695,258,842,146,749,796,174,747,434,560,829,654,835,81,608,772,330,732,225,857,977,440,94,372,60,764,822,488,683,347,476,616,560,416,587,415,233,480,525,928,533,7,867,654,932,844,864,353,318,63,378,318,858,947,280,716,563,346,555,862,504,206,223,354,570,914,657,213,149,148,32,883,773,891,118,505,949,565,96,370,467,887,528,98,600,678,66,378,817,499,994,529,852,461,999,740,421,540,802,986,404,703,417,507,271,45,748,874,828,645,927,4,719,870,690,166,720,616,30,109,975,522,423,365,34,657,1,820,458,258,861,924,732,54,452,240,82,189,35,557,636,729,7,976,73,573,657,84,516,261,241,288,355,985,524,990,188,269,700,206,449,49,645,251,393,600,423,26,958,785,229,62,290,429,915,497,706,333,680,859,254,955,301,984,843,996,559,903,225,177,353,56,604,776,593,390,437,421,171,739,628,494,408,368,149,445,491,926,298,339,943,828,284,971,116,25,59,442,767,473,416,372,820,901,551,583,16,781,681,435,15,951,542,341,196,388,493,392,59,411,26,287,427,984,742,66,584,569,567,581,316,969,199,658,406,102,134,430,226,918,948,975,797,694,237,427,871,916,399,300,255,606,943,216,742,333,10,70,999,210,817,581,584,5,137,699,569,844,948,970,628,866,236,115,151,899,639,436,474,495,975,771,561,543,515,687,280,729,859,173,597,427,707,101,674,254,972,363,311,964,977,223,666,887,871,447,735,838,6,502,857,587,72,896,627,381,877,554,417,628,593,464,460,751,893,374,973,700,555,307,754,207,719,343,110,926,478,137,527,378,256,103,692,373,876,775,913,104,602,802,420,587,85,285,365,81,243,671,993,355,498,448,880,22,312,422,210,902,877,846,521,92,517,324,656,729,278,182,30,900,321,55,829,660,130,208,681,945,825,51,284,256,928,132,247,488,666,764,854,306,331,36,411,527,397,730,520,208,658,969,50,584,359,988,384,192,514,991,987,123,598,372,677,527,231,178,236,338,905,131,847,758,506,148,600,156,743,628,651,910,794,479,135,592,735,28,266,504,839,941,323,174,328,480,665,704,319,202,148,146,781,653,959,352,254,799,918,272,62,457,167,947,322,759,450,184,792,941,722,777,301,248,76,155,125,751,838,580,905,854,588,653,345,771,309,516,402,232,107,805,595,49,339,302,607,838,152,599,808,494,297,640,654,467,239,583,996,229,514,831,652,26,641,651", + "675,236,190,356,162,258,75,990,953,609,116,86,654,992,719,833,587,296,139,877,726,472,493,660,594,598,539,250,512,449,307,287,171,16,568,348,740,779,118,29,834,412,494,408,750,678,968,262,484,251,773,906,19,220,289,591,181,342,710,645,359,338,46,202,938,714,651,229,472,585,424,849,277,610,201,377,724,311,315,375,169,570,522,174,628,729,559,630,619,711,522,526,706,678,385,971,839,196,292,253,197,84,829,478,717,733,992,146,153,164,343,866,599,758,52,895,395,234,43,247,133,204,515,188,515,211,790,576,104,656,152,249,297,973,605,668,687,880,65,220,714,510,635,868,157,298,886,910,566,981,138,738,699,990,803,751,853,730,439,954,938,622,727,739,449,724,254,587,990,269,635,764,149,683,630,655,143,138,2,139,115,597,274,434,29,81,150,58,56,15,486,22,868,378,391,154,92,568,799,165,423,602,146,439,593,644,412,967,162,518,859,743,921,360,164,896,487,766,760,609,157,160,539,235,554,739,171,71,132,15,414,457,277,369,151,855,325,75,943,899,236,110,309,220,147,646,412,939,223,478,933,677,92,698,152,478,927,388,2,611,68,873,955,149,598,32,40,785,199,874,50,565,980,485,266,266,876,108,6,722,789,517,291,970,33,682,495,13,20,580,937,701,953,573,549,567,784,159,210,29,841,844,666,836,751,642,841,628,258,246,564,403,979,309,27,946,853,674,564,964,224,18,268,482,864,377,237,301,244,167,214,708,209,837,623,715,991,477,983,946,4,802,877,268,99,769,686,158,412,848,30,784,159,718,952,590,495,562,740,0,951,586,612,126,601,705,340,51,767,787,237,28,940,370,663,561,364,204,910,718,196,477,613,694,20,442,693,348,802,645,453,260,977,441,228,713,822,857,755,792,715,610,158,940,957,550,202,304,497,130,723,149,102,56,981,418,278,962,232,528,521,753,460,805,775,347,607,346,338,720,532,955,779,407,882,253,347,53,813,996,825,462,70,181,791,870,518,621,479,348,131,772,856,412,425,419,696,579,57,546,156,833,650,703,43,518,379,279,614,513,93,613,161,607,337,924,842,884,562,599,316,521,148,554,282,310,964,911,74,174,725,544,308,214,763,948,703,548,778,795,100,698,556,653,89,971,708,436,90,969,98,386,123,928,631,868,513,291,466,818,703,152,56,174,367,159,648,297,542,925,730,272,422,102,68,857,550,438,877,901,399,133,88,340,459,417,112,555,345,372,411,823,228,186,739,451,31,46,977,408,931,224,382,383,452,616,499,86,777,261,933,996,736,217,350,493,562,29,875,65,810,391,74,282,82,765,237,759,618,753,641,568,10,467,178,781,995,36,296,762,513,746,484,111,949,196,200,844,392,999,19,788,587,535,572,307,927,271,862,424,105,347,697,469,934,440,580,328,862,379,483,948,763,950,115,812,512,748,871,793,559,5,385,560,622,402,838,260,609,374,36,134,756,364,749,553,426,285,617,974,357,988,637,826,342,556,927,228,272,583,56,280,844,778,36,140,610,457,481,138,785,199,186,691,598,864,901,960,327,599,908,417,516,698,690,673,51,637,107,509,224,27,908,819,355,142,698,876,257,575,264,628,539,464,168,654,352,675,104,314,94,982,506,401,854,516,173,159,294,441,60,674,925,572,76,248,275,996,740,222,836,133,253,500,756,478,271,392,316,904,372,63,770,683,182,688,895,320,38,326,870,254,44,86,584,246,285,125,800,57,241,9,299,48,33,291,627,705,21,481,65,389,783,98,673,948,37,264,51,915,715,484,156,119,363,924,526,466,755,244,971,399,988,128,601,872,755,992,987,174,152,154,277,42,899,600,418,177,411,648,641,436,701,197,162,206,408,87,871,304,827,296,655,183,692,964,918,441,333,596,1,896,308,973,974,819,154,670,318,337,28,51,88,373,712,36,174,827,630,796,811,804,815,428,235,260,658,843,333,237,213,201,864,321,343,617,756,256,204,174,116,266,451,162,429,280,452,76,764,625,254,742,687,55,575,800,575,107,842,738,303,437,189,719,806,517,984,376,36,568,460,31,42,119,104,681,684,573,666,184,868,623,277,667,939,522,958,787,812,604,562,263,444,536,880,358,606,809,62,889,984,792,962,185,105,496,774,555,548,984,872,38,720,297,747,879,263,740,585,115,699,875,664,913,31,409,627,535,697,545,63,538,484,931,227,374,480,298,110,531,389,699,513,585,81,90,337,408,71,873,339,737,845,23,257,983,39,89,931,235", + "661,786,90,981,636,187,522,527,798,518,340,766,316,263,473,365,67,866,148,284,895,418,1,926,254,320,659,540,464,840,698,829,330,899,894,518,587,930,617,287,879,84,923,723,445,27,916,982,981,936,481,32,614,709,532,178,129,27,499,920,615,243,305,875,556,251,410,346,218,718,664,929,146,290,819,968,188,988,116,188,586,903,65,486,986,776,770,944,32,719,73,791,839,789,883,126,890,235,294,832,526,731,226,260,114,639,509,411,832,881,172,457,66,545,753,569,836,574,689,272,589,104,618,614,673,933,483,293,930,941,294,468,845,207,198,540,133,836,847,349,478,232,313,728,804,368,130,702,592,342,953,272,55,544,78,160,102,121,956,813,578,835,218,673,537,773,115,116,19,941,95,281,589,682,704,349,580,680,913,599,392,388,712,555,380,377,298,731,812,573,411,489,290,229,320,45,660,40,251,687,181,117,50,666,928,774,4,779,644,475,868,405,615,450,110,738,748,124,369,134,588,254,324,986,883,910,572,855,268,969,953,541,238,713,7,207,267,588,861,891,273,675,160,856,949,870,967,227,974,396,232,444,107,735,756,552,295,233,67,223,951,869,202,604,1000,706,974,418,351,902,565,235,531,610,931,122,449,449,930,373,155,836,157,148,460,583,989,29,446,336,316,570,891,853,563,249,501,433,5,650,711,339,669,925,634,574,606,871,459,811,688,846,45,158,51,243,201,56,713,303,378,897,630,771,330,244,664,791,609,974,640,332,290,488,146,137,641,169,644,649,762,218,816,483,142,712,142,615,990,490,230,260,480,210,204,708,201,735,432,951,0,100,389,748,728,290,352,501,563,88,962,516,822,323,65,99,841,671,258,576,236,247,127,994,231,676,640,235,209,768,813,156,216,999,642,650,27,676,901,881,559,83,834,652,167,695,622,348,377,421,205,27,188,919,850,843,449,562,744,613,731,775,975,172,199,110,749,708,201,793,890,873,885,779,726,528,608,697,433,883,696,766,489,292,157,475,539,947,59,184,359,825,627,362,560,113,238,839,899,760,583,420,984,965,302,180,201,401,985,326,277,304,509,332,303,133,192,904,491,244,267,677,718,168,64,105,939,375,957,332,402,223,776,947,908,246,765,324,949,237,901,947,691,3,981,146,871,120,378,451,137,342,411,446,684,523,327,641,737,239,28,981,504,434,732,674,593,519,715,353,464,548,87,699,624,63,86,57,792,158,700,360,362,161,513,160,841,849,850,977,130,179,358,923,25,58,289,814,667,802,596,803,276,170,847,915,923,694,702,567,110,551,847,550,812,749,337,104,276,303,300,198,24,340,790,867,853,130,252,322,735,298,907,252,270,619,109,419,202,889,429,235,323,953,476,268,592,180,313,626,627,181,616,999,354,599,236,396,170,631,237,306,845,284,319,737,950,882,306,821,796,234,606,37,676,336,170,662,156,336,221,660,318,705,534,618,675,604,316,884,964,292,443,191,495,297,555,388,316,264,775,995,228,61,878,452,57,161,894,316,618,879,112,559,829,967,168,730,25,465,838,591,584,37,407,806,298,542,975,170,728,165,44,781,774,507,832,383,413,418,461,997,218,562,59,873,607,821,422,961,3,922,368,496,201,646,164,561,897,281,558,428,921,50,864,412,150,945,451,832,980,871,619,427,999,816,598,63,35,42,244,42,90,617,582,876,659,324,38,855,468,696,13,290,988,590,599,391,389,172,138,472,92,71,174,15,557,249,695,250,836,280,556,476,3,340,49,37,263,546,65,296,297,169,435,300,170,231,328,261,30,718,834,862,304,736,862,56,53,447,672,661,136,373,751,595,852,245,878,592,397,166,168,431,115,667,555,995,665,802,557,715,929,529,212,295,360,335,239,175,751,476,808,166,447,493,986,829,212,555,469,24,209,87,737,730,833,477,436,55,137,111,465,554,367,870,244,488,693,247,359,691,556,435,74,391,853,164,862,811,163,49,351,38,197,840,949,731,59,823,116,292,634,692,319,729,578,65,601,452,624,849,107,592,606,645,832,602,728,502,915,418,627,972,320,895,399,638,107,357,537,311,915,493,489,719,679,363,192,46,312,800,840,952,595,759,416,698,999,832,730,182,662,46,823,136,911,461,60,68,790,26,59,839,827,488,225,766,59,685,225,995,85,981,407,714,187,722,484,903,185,319,373,877,702,37,934,845,732,907,277,907,334,114,189,256,787,810,509,740,827,750,855,183,329,280,201,654,212,280,514,482,560,845,300,713,353,515,925,397", + "697,502,507,248,592,634,322,670,736,117,956,903,922,149,21,206,26,245,84,421,403,220,414,864,264,147,38,804,951,727,718,847,222,404,613,842,989,105,54,71,92,461,213,264,425,942,110,679,255,801,106,522,215,627,883,934,287,324,983,240,602,13,496,867,301,567,904,548,888,81,911,189,998,604,270,706,99,477,180,604,391,405,187,316,947,313,801,378,3,970,215,804,294,219,773,899,634,922,433,368,834,696,592,395,482,115,465,674,985,705,36,853,157,633,47,307,515,182,875,106,268,405,853,443,422,813,814,413,278,842,219,363,667,782,207,385,768,289,200,264,4,872,620,644,385,830,990,355,332,261,903,724,174,767,204,674,191,824,398,866,705,128,522,450,1000,859,777,572,97,454,744,310,376,468,971,639,595,930,56,148,408,294,209,862,813,951,588,528,654,161,743,983,675,807,120,569,214,429,928,922,974,715,428,345,193,804,536,736,38,694,962,258,5,129,12,339,567,450,726,200,217,62,422,326,874,352,670,73,180,302,980,103,148,560,258,319,299,141,768,495,686,945,877,70,801,606,228,942,154,180,743,922,492,685,67,884,906,637,66,143,818,342,224,712,262,406,803,773,162,20,928,616,618,308,82,184,234,182,913,700,60,842,610,560,422,17,909,885,667,792,381,665,454,183,329,180,122,61,76,770,985,302,830,735,159,355,135,659,784,836,116,871,664,131,691,35,905,437,974,326,162,638,336,230,214,742,646,639,752,592,272,506,270,654,616,511,755,371,264,709,523,774,684,719,75,590,301,545,80,599,808,2,652,74,733,379,557,518,444,586,100,0,794,627,898,388,172,88,171,879,904,284,558,476,274,169,617,250,690,814,330,555,652,402,628,151,655,88,228,747,266,366,661,5,986,627,204,231,226,893,387,302,999,15,798,602,196,994,296,42,91,799,436,440,975,226,890,624,360,724,720,674,191,813,225,925,989,847,98,827,160,256,670,711,480,364,17,957,286,436,251,610,225,304,597,114,413,345,198,537,94,873,561,273,325,937,323,132,833,613,37,168,156,265,527,211,325,646,177,460,835,440,996,339,120,711,286,283,407,228,758,579,467,450,343,573,946,747,951,648,173,618,391,339,916,852,812,879,786,783,984,412,83,702,178,550,778,330,911,294,529,94,235,972,289,123,214,138,15,199,183,475,107,12,284,422,794,558,707,206,950,627,99,874,130,845,244,321,293,453,835,389,622,50,233,253,52,953,832,539,655,541,941,493,541,614,46,349,963,609,287,432,885,836,556,212,941,144,311,161,759,189,613,111,850,602,711,149,888,447,519,517,520,769,343,563,271,769,199,708,417,368,224,245,94,219,664,287,238,410,18,772,681,577,251,404,64,425,201,881,828,569,358,184,88,395,271,673,781,372,895,507,704,504,864,129,963,461,594,919,391,815,994,55,215,750,975,331,858,786,437,492,953,689,118,57,965,945,209,655,545,244,171,660,598,120,674,99,977,807,828,92,769,576,446,183,462,938,647,476,619,416,304,991,66,124,805,677,715,178,904,76,744,638,415,577,933,59,55,218,317,672,829,724,45,861,75,91,299,164,494,922,639,489,791,419,498,14,854,203,555,440,375,569,454,124,340,706,529,286,707,875,988,703,943,335,669,411,81,332,954,140,498,692,730,383,874,698,201,92,633,60,14,119,461,668,318,518,913,146,712,526,119,960,353,298,426,365,861,455,968,908,955,524,618,472,263,474,990,623,258,210,42,969,823,613,43,124,351,844,868,899,351,925,403,87,505,382,23,998,414,489,256,140,401,169,51,348,497,373,400,984,649,643,601,998,430,262,709,312,605,300,734,677,93,967,90,31,613,964,484,778,694,610,720,139,538,133,176,780,224,877,578,633,373,732,949,753,647,889,161,684,778,285,679,577,574,438,26,701,720,159,185,11,370,213,222,714,100,657,172,8,577,186,208,645,952,37,35,869,66,351,988,523,854,203,318,654,597,79,527,578,582,748,793,788,601,997,142,618,561,178,814,99,382,993,140,471,58,719,632,450,264,591,153,469,465,183,552,370,928,112,508,955,672,198,82,541,646,916,86,113,214,258,289,26,500,677,86,471,94,649,925,275,702,820,736,197,750,754,389,442,390,590,736,41,622,859,817,71,437,899,168,298,805,163,89,105,703,216,169,865,120,576,419,179,717,228,577,134,917,968,755,15,65,349,656,193,913,588,587,68,443,61,122,234,28,554,822,237,186,290,139,965,853,476,947,416,912,271", + "632,476,122,862,792,205,838,763,960,1,819,311,996,387,919,471,498,490,45,485,963,725,626,880,501,383,220,185,4,781,595,452,781,663,653,327,21,329,524,255,415,96,280,883,66,66,209,360,424,796,792,704,843,587,476,391,727,777,986,297,633,626,858,918,83,578,184,854,377,804,924,680,887,486,859,187,186,997,648,655,97,627,751,49,700,369,81,796,948,513,807,256,159,973,883,533,809,961,61,92,166,259,397,926,473,2,441,656,787,503,512,363,430,858,986,810,192,881,84,842,964,243,333,927,77,530,741,492,246,751,579,592,122,814,189,147,465,487,45,884,240,980,983,723,950,752,995,277,760,928,734,442,477,979,930,370,52,424,653,211,333,515,104,849,739,863,337,889,476,967,676,112,115,546,165,379,357,5,886,681,276,492,251,579,820,445,431,433,967,248,539,135,979,871,394,449,902,527,9,612,766,199,406,712,491,209,795,688,911,431,800,203,649,584,831,328,48,19,898,356,829,783,988,920,969,314,940,86,668,468,390,307,178,40,25,742,519,221,696,226,678,724,430,391,317,707,35,585,472,4,798,450,584,263,778,737,714,995,553,115,757,453,869,764,164,244,933,341,218,651,231,671,4,431,753,410,494,2,475,385,380,738,485,924,512,467,919,510,555,451,998,260,398,552,45,487,364,109,417,336,279,862,515,811,884,131,105,635,803,938,750,187,137,808,3,711,398,434,986,828,232,364,382,84,421,274,267,103,346,929,877,826,736,703,897,661,271,145,808,724,709,109,137,588,672,918,564,398,177,612,668,740,266,448,315,714,920,523,270,612,389,794,0,333,256,616,150,165,822,748,720,735,920,161,430,475,536,553,824,408,524,250,947,279,743,499,99,249,242,679,870,150,886,328,421,906,7,331,929,168,143,211,952,912,535,644,90,510,244,890,940,76,903,138,550,170,601,721,323,334,71,843,392,96,283,161,621,227,39,701,887,87,464,199,458,312,560,583,152,916,358,277,633,237,874,192,889,204,721,265,499,314,96,534,438,268,899,755,443,636,400,340,150,495,22,712,473,246,247,106,138,35,310,40,86,227,304,35,992,249,520,141,371,879,947,952,638,817,886,876,239,173,482,372,668,796,257,872,499,491,494,237,922,353,926,487,763,15,453,294,197,550,747,156,829,503,158,485,400,91,697,71,348,287,421,235,249,884,401,87,407,378,339,203,600,798,714,488,410,118,95,159,5,809,26,398,744,98,250,275,835,202,39,817,381,946,167,621,653,536,391,923,242,186,125,550,176,639,323,481,376,83,745,294,805,613,338,543,309,421,475,189,839,500,639,340,77,274,974,573,124,322,274,168,224,164,356,643,910,526,640,659,221,94,642,494,136,517,162,750,1000,2,184,259,604,826,778,931,168,781,224,245,969,185,342,940,90,802,532,493,509,156,905,829,183,959,987,913,905,119,377,321,74,542,233,240,638,141,770,935,465,881,86,95,899,727,272,465,605,311,858,860,153,687,526,324,443,830,739,950,278,147,386,935,99,173,573,178,737,488,33,991,126,160,815,741,604,742,701,390,425,498,605,169,184,195,992,878,240,740,521,333,15,868,64,271,266,365,94,467,664,327,712,806,275,89,167,950,680,531,247,894,1000,716,915,310,399,164,2,930,840,889,668,327,902,755,128,72,670,361,122,359,941,875,223,520,52,518,847,548,463,749,455,71,563,699,219,565,101,787,328,981,471,480,677,430,474,125,907,179,647,519,485,135,256,540,315,877,712,115,358,392,54,887,510,873,29,852,148,993,162,280,468,126,68,150,211,621,886,706,734,418,458,529,170,698,155,882,752,959,975,647,40,693,946,393,811,693,570,666,507,204,115,595,798,991,860,640,455,874,298,333,426,247,784,133,747,814,48,646,817,913,406,925,623,873,555,43,89,65,293,353,320,841,796,906,804,893,384,379,273,189,968,881,915,495,725,240,547,479,97,126,888,454,858,77,772,412,153,691,259,85,923,965,417,714,706,345,373,39,941,474,954,895,480,263,181,665,956,324,843,794,62,128,264,937,264,617,575,58,672,947,651,590,185,936,65,921,312,633,445,705,85,348,860,819,571,611,707,877,126,112,926,980,182,329,918,386,145,81,49,471,532,564,471,241,484,35,34,732,73,759,886,291,595,63,850,478,179,472,245,568,275,206,664,183,104,158,218,377,535,652,441,73,154,732,819,712,350,970,383,661,525,44,517,161,646,737,706,552,403,404,635,684,996,736,586,370,384,588", + "185,804,398,177,827,397,198,73,740,202,17,204,342,670,603,271,988,768,327,657,857,491,873,921,781,90,825,223,409,514,312,612,926,509,396,119,610,376,676,345,309,960,241,84,2,603,18,377,745,547,128,133,734,697,424,944,617,206,683,166,578,990,834,236,208,413,193,771,999,225,659,413,940,950,754,726,297,62,500,528,432,165,178,783,110,550,634,799,890,858,837,888,313,379,821,34,475,802,844,354,748,871,588,75,43,168,763,18,873,402,101,311,725,87,333,382,5,359,656,197,831,652,399,19,22,168,216,500,200,264,872,983,575,960,518,322,928,975,122,25,664,580,863,129,99,776,752,105,923,330,559,244,401,775,172,591,804,246,828,816,92,29,627,584,140,617,593,350,454,272,290,58,593,760,439,371,600,279,44,338,535,944,93,112,470,782,189,103,462,606,640,262,453,273,73,563,245,650,120,836,110,654,768,665,889,283,559,275,108,848,832,949,915,201,75,101,461,871,884,744,803,148,968,492,345,9,382,680,521,19,60,864,580,606,698,182,907,616,806,508,417,429,67,454,374,381,573,780,808,708,305,457,399,425,104,161,707,150,274,875,104,190,103,991,304,286,292,452,809,108,118,304,116,504,770,617,922,366,191,419,100,719,386,643,629,648,768,516,585,309,154,280,88,305,319,858,840,889,848,335,910,675,333,739,656,52,191,340,164,633,965,42,999,652,231,312,538,200,533,712,51,789,350,361,514,697,3,508,100,294,658,799,594,782,373,622,281,348,985,361,134,786,9,570,175,825,995,128,192,116,881,480,151,922,618,560,347,452,385,126,748,627,333,0,41,291,632,201,719,34,357,396,980,166,3,467,509,257,805,353,901,294,612,203,17,28,131,134,775,489,16,61,562,650,209,976,991,213,407,998,960,582,586,964,518,701,581,774,136,335,322,257,406,44,964,488,449,76,766,299,343,946,254,236,879,660,902,196,486,426,867,286,85,966,415,431,647,605,556,395,98,922,438,239,975,268,26,765,103,752,280,101,725,698,595,697,388,334,523,589,302,83,182,951,58,503,857,643,252,723,699,348,548,413,598,183,563,92,563,840,406,680,984,12,662,657,982,479,659,402,366,621,153,177,342,990,6,924,202,275,855,532,440,527,129,894,296,148,98,928,555,84,445,509,518,927,980,165,567,86,283,429,258,290,476,569,93,749,870,618,425,782,721,542,356,52,761,543,447,995,154,602,732,10,949,317,721,970,168,833,328,485,183,660,341,954,768,508,81,833,235,667,730,195,300,884,371,158,122,242,892,687,704,595,443,640,38,151,388,586,726,228,108,440,969,958,327,839,413,804,942,739,909,533,860,412,548,149,451,408,443,703,330,420,860,60,865,198,436,143,573,340,732,72,355,256,491,837,961,472,173,135,226,25,300,485,200,649,740,744,884,97,524,153,611,774,379,757,413,719,520,827,335,674,301,534,329,849,350,702,847,727,514,424,198,24,913,796,284,901,409,254,308,821,454,121,685,737,660,512,481,952,845,360,574,789,979,161,273,854,773,8,149,379,100,232,890,780,314,387,577,832,77,598,913,591,729,608,230,721,30,701,897,633,529,4,515,621,459,598,475,219,299,41,323,74,577,691,810,164,994,324,672,619,686,338,80,161,688,652,201,202,961,549,65,462,301,885,47,581,781,944,737,1000,894,33,16,26,1,476,342,153,214,830,871,165,23,986,324,779,297,921,494,632,942,3,761,335,362,190,95,629,705,112,947,302,877,183,879,964,55,247,95,480,449,42,983,624,18,833,606,292,516,159,896,146,536,627,412,132,262,152,187,897,33,449,883,93,192,93,939,741,433,370,23,427,853,879,928,440,374,539,38,46,148,745,44,818,879,415,611,386,556,98,954,226,724,748,312,751,698,380,610,966,869,409,680,62,440,300,570,839,222,8,833,616,109,219,435,604,188,224,898,271,674,699,641,677,873,377,807,500,430,667,117,96,764,702,628,497,46,104,122,824,528,296,702,255,709,306,701,897,382,806,788,509,962,476,828,142,973,183,826,446,531,758,568,254,381,946,405,725,297,574,860,527,628,465,430,903,139,587,264,905,343,34,235,180,407,336,746,919,509,302,710,107,48,135,147,424,260,647,329,735,559,391,98,53,4,521,81,230,517,746,224,102,303,687,710,767,897,118,798,265,76,681,591,414,331,857,35,424,373,904,897,231,78,625,818,280,609,129,989,168,833,951,113,91,618,667,5,574,1,878,436,73,65,574,863,54", + "283,44,763,472,181,870,354,270,835,725,26,340,585,554,781,831,772,948,479,180,630,982,221,448,168,516,865,884,320,349,807,50,112,589,334,226,344,98,88,973,290,682,636,699,878,514,793,99,432,295,89,238,804,39,321,756,287,844,547,610,152,482,561,483,692,272,861,434,615,89,228,918,63,169,505,875,451,137,146,683,861,137,137,96,686,650,514,402,206,721,464,119,556,123,370,600,127,790,661,197,903,602,240,458,351,764,375,501,910,187,553,362,78,752,275,732,591,3,157,916,822,866,665,760,541,741,62,210,423,500,981,378,84,383,89,778,63,817,30,792,678,303,956,223,71,951,918,281,249,729,351,45,53,674,742,294,557,670,623,970,976,646,354,999,983,689,547,213,554,927,166,134,109,423,460,496,256,565,807,967,292,834,518,163,89,538,743,344,935,9,290,97,173,626,865,83,192,212,57,723,568,56,363,126,777,34,150,582,629,507,894,420,825,775,972,519,321,735,49,475,89,800,489,80,511,409,297,12,111,833,280,533,244,825,4,99,172,193,95,42,911,12,101,554,668,519,394,791,961,278,928,310,57,956,939,376,62,435,149,321,167,313,187,292,185,382,940,339,300,263,882,65,395,606,120,66,749,343,530,530,462,348,453,567,365,27,845,406,256,931,124,924,112,964,43,882,905,3,466,373,81,471,579,309,644,886,747,631,935,95,385,806,73,144,44,341,577,804,407,799,323,979,619,255,501,294,108,434,348,896,511,795,264,254,401,887,680,435,833,941,777,152,569,838,711,945,711,484,661,140,969,988,664,648,953,630,213,833,241,601,728,898,256,41,0,655,565,838,551,9,248,955,803,937,279,29,260,346,602,426,82,479,47,231,736,277,369,18,806,155,899,827,892,142,778,798,978,251,755,406,281,298,915,801,864,226,85,94,895,480,561,178,129,157,722,349,599,21,383,300,861,18,963,251,230,724,464,249,807,25,587,187,4,107,217,354,480,586,958,642,909,948,498,886,866,749,214,230,649,146,372,837,935,719,303,452,3,787,295,178,865,870,930,924,171,254,376,580,701,345,348,834,480,615,92,663,803,220,979,583,999,485,95,868,79,482,933,639,53,543,775,857,927,480,139,4,17,843,202,723,333,300,129,825,841,701,680,461,636,831,269,39,648,499,196,937,820,53,942,346,897,721,415,444,804,623,106,861,194,762,173,245,864,394,690,442,10,408,806,170,807,907,439,574,54,94,277,729,261,680,534,265,986,274,874,914,181,923,64,923,336,375,159,746,700,994,956,898,598,766,74,755,76,572,178,274,744,978,927,600,379,578,440,32,355,642,659,985,673,323,232,924,962,241,254,369,856,88,884,534,504,573,447,183,852,285,224,667,923,776,508,435,875,312,87,56,75,94,911,554,995,238,389,155,336,59,692,916,32,355,265,855,404,573,736,55,301,791,796,13,313,163,696,130,180,159,913,244,59,73,590,330,322,434,619,994,359,669,895,255,621,541,350,586,483,59,548,528,583,519,311,632,238,606,856,893,738,715,670,356,423,17,254,35,691,191,743,614,114,558,656,602,894,537,255,15,810,167,368,249,375,47,641,41,265,737,324,906,720,284,86,801,721,474,14,288,761,679,76,729,924,227,150,773,349,180,853,827,880,894,252,430,531,786,863,216,70,18,750,648,240,609,318,214,949,737,688,929,266,221,510,780,792,737,704,863,632,338,470,651,736,869,102,438,284,866,436,410,958,63,175,827,510,167,278,635,932,434,105,344,940,635,590,81,575,93,358,138,817,26,390,657,598,692,498,375,407,111,295,280,954,225,26,400,876,639,269,914,682,29,854,437,96,429,568,578,768,633,953,16,476,530,953,76,681,394,426,759,659,134,913,233,591,948,458,235,514,243,315,231,330,87,169,996,830,705,637,267,126,18,188,65,547,351,268,440,321,479,19,185,768,315,611,52,613,972,417,434,88,584,450,284,13,126,703,483,925,52,983,945,848,842,331,974,529,662,718,727,500,559,645,736,41,578,152,387,161,119,207,202,256,731,339,869,581,443,136,265,302,129,912,180,825,432,613,938,922,532,501,865,434,247,255,967,308,564,529,200,241,927,486,824,27,770,271,830,889,89,517,612,27,51,742,47,960,625,531,269,702,566,334,589,592,379,359,916,752,364,995,92,241,977,282,271,316,11,746,356,818,286,58,131,135,105,483,405,551,813,2,198,788,228,705,477,947,224,727,724,170,612,838,28,878,814,695,329,945,583,152,143", + "838,717,207,490,620,895,885,807,891,710,846,354,843,98,454,279,250,718,81,953,75,506,686,990,893,660,466,42,742,25,849,729,473,684,226,971,127,29,912,98,862,936,308,231,495,645,777,478,161,456,505,531,105,667,976,916,549,883,17,219,828,456,127,345,896,600,661,87,93,587,509,78,313,273,827,491,751,475,353,195,544,759,719,793,636,744,758,867,520,390,684,936,470,457,94,729,977,348,773,43,628,155,442,67,411,656,882,670,398,911,163,397,720,400,988,226,640,175,593,479,189,350,108,988,24,646,755,762,413,820,91,552,149,86,93,802,755,559,608,803,462,337,786,207,744,320,467,382,372,855,685,82,731,716,239,115,329,701,592,102,929,126,406,203,278,355,752,799,499,863,18,252,285,186,617,779,708,968,750,612,218,465,57,438,988,260,211,98,826,13,871,612,499,80,472,250,922,393,2,828,332,172,900,194,461,532,139,934,69,213,790,330,888,428,516,4,695,967,944,625,503,256,133,376,383,292,881,551,174,276,841,425,695,639,219,384,532,702,172,646,676,789,246,172,469,216,731,941,683,211,431,290,683,213,160,930,82,581,890,807,535,518,939,194,294,438,462,616,237,773,848,796,686,640,866,458,453,748,825,377,775,1000,827,571,549,543,285,798,144,119,831,285,581,323,857,851,430,90,242,701,858,942,547,548,493,278,424,324,148,187,153,895,528,935,798,358,563,94,82,384,354,934,234,598,780,324,167,420,986,69,879,423,771,525,111,472,582,899,695,261,18,566,409,646,991,787,378,98,794,739,909,42,155,588,925,662,476,284,553,705,290,388,616,291,655,0,72,94,768,947,706,141,139,546,224,88,636,864,760,194,177,272,227,857,112,459,811,395,625,164,332,853,164,668,932,169,587,30,107,899,55,840,505,654,449,100,870,259,519,577,524,388,372,59,964,596,58,47,761,191,180,623,272,233,738,904,814,355,401,798,278,376,304,922,577,403,85,626,733,107,562,374,951,452,194,239,307,831,432,889,940,100,539,834,545,399,805,173,708,324,79,180,354,698,737,853,574,181,844,233,666,666,319,455,170,378,424,364,665,656,532,204,325,84,644,205,535,500,628,775,831,739,201,585,564,287,824,855,514,946,520,541,334,96,716,41,543,62,166,5,640,684,73,61,302,674,779,235,49,940,461,814,40,804,713,293,119,922,781,601,25,599,325,43,321,595,423,553,890,917,571,618,170,212,525,452,377,552,848,907,345,589,574,202,519,828,217,745,761,498,271,32,958,968,969,794,752,180,265,575,968,693,540,461,145,475,826,668,297,17,527,739,474,341,318,106,218,197,399,37,358,214,689,497,731,787,229,146,266,143,145,883,166,667,300,623,957,526,395,627,714,587,492,810,127,39,558,607,435,508,829,178,908,402,912,351,285,611,913,612,936,1000,79,379,20,954,102,531,724,373,782,527,242,384,911,835,271,546,946,92,484,882,493,190,384,950,785,413,463,83,426,252,168,819,354,138,26,727,366,702,671,748,432,289,13,920,531,936,599,945,58,327,681,134,24,244,71,484,364,110,630,52,766,954,649,153,794,953,296,361,161,450,22,471,340,529,554,112,522,166,742,227,633,627,267,509,443,907,746,10,265,505,611,431,751,145,537,389,330,678,689,659,457,543,374,209,106,962,775,755,352,818,412,54,249,867,652,767,365,143,875,462,626,757,826,193,979,222,584,174,423,213,382,402,661,766,844,512,926,976,18,615,238,964,602,187,804,380,612,301,423,970,120,693,310,397,592,73,326,671,335,997,30,33,347,203,24,793,79,525,776,904,522,772,826,84,137,953,650,486,473,50,934,270,725,432,966,407,305,645,315,303,649,905,531,160,20,853,342,861,147,96,165,337,736,493,581,62,908,718,924,289,252,970,983,343,697,103,175,831,191,456,907,646,804,644,268,167,238,143,782,325,764,810,471,366,611,261,934,830,180,814,942,483,77,870,259,171,232,303,73,91,648,911,135,204,740,843,728,580,939,155,34,378,389,409,177,157,824,235,623,387,607,499,522,664,665,365,774,314,952,314,720,839,426,382,218,212,967,183,695,470,68,432,614,973,631,158,660,329,731,400,610,400,883,483,559,769,780,54,763,657,823,529,667,693,365,337,611,326,676,78,99,742,230,226,766,816,272,784,673,738,671,589,653,642,143,896,793,926,159,862,896,584,780,915,60,639,731,647,781,162,782,893,813,193,866,169,960,387,143,789,826,106,105,821,22,764,457,940", + "509,793,252,194,758,344,657,180,268,812,453,518,895,736,173,297,858,541,550,889,250,288,168,895,866,2,212,294,843,282,124,683,547,600,308,623,476,258,741,15,464,278,693,684,665,533,503,999,823,200,7,394,479,521,688,250,331,915,486,784,19,621,158,38,331,901,921,948,438,659,509,545,47,487,811,154,704,543,653,429,416,949,965,991,367,667,628,771,319,133,285,157,732,40,290,306,363,718,793,439,94,498,941,267,640,820,477,40,635,408,205,624,551,438,883,920,724,508,165,338,479,466,399,217,407,296,918,782,681,106,27,460,852,897,232,731,537,216,800,239,448,684,438,644,654,189,658,932,906,17,730,426,551,852,746,670,253,350,593,482,217,485,169,682,128,585,773,590,601,879,527,30,890,248,538,65,885,99,709,594,388,658,597,426,296,130,121,459,493,321,948,65,559,533,373,743,665,159,272,768,663,379,481,860,850,476,40,990,83,415,913,204,789,241,12,308,636,133,972,682,842,886,848,328,50,219,56,283,501,4,103,597,212,441,532,762,142,797,432,629,869,312,217,853,809,459,798,838,756,781,74,956,358,16,964,581,481,565,482,995,626,738,371,847,50,974,871,504,759,731,39,84,202,535,615,721,810,105,544,726,26,723,918,482,232,449,507,989,498,131,31,739,835,752,332,507,557,367,948,677,588,557,918,404,962,280,374,225,624,808,817,843,866,518,891,683,61,572,617,964,277,570,838,926,859,442,433,368,712,746,285,193,853,428,810,179,6,179,649,48,761,742,173,552,890,505,583,879,929,923,889,113,940,549,414,473,756,619,924,340,352,172,150,632,565,72,0,621,462,269,492,150,381,596,118,212,931,655,661,892,925,463,751,339,685,915,214,600,457,801,443,908,770,322,580,502,861,882,132,52,954,904,710,165,713,371,648,871,268,452,234,983,242,949,425,785,726,374,330,175,342,600,950,5,535,288,857,461,797,322,528,586,291,367,877,610,21,891,952,687,911,514,661,283,723,846,327,857,183,358,912,273,22,862,405,978,878,985,911,482,681,674,984,584,306,290,81,984,579,946,380,934,126,811,78,431,572,928,179,258,28,150,384,901,97,752,561,26,840,549,652,188,757,697,102,73,44,230,224,298,630,570,631,590,402,163,116,208,165,756,893,422,674,166,777,392,867,592,423,275,249,676,458,426,146,887,774,206,668,138,997,970,248,582,740,885,928,338,656,932,997,904,642,923,253,482,831,237,517,874,330,925,315,227,170,668,800,697,908,234,840,293,568,384,612,167,221,804,457,868,814,343,749,597,818,929,855,186,837,826,398,101,627,373,9,73,917,291,374,129,277,943,725,103,464,397,740,923,79,724,559,534,534,928,913,404,841,102,391,719,577,853,278,943,270,548,766,872,597,122,742,877,2,427,51,710,207,687,664,899,381,200,761,663,831,599,131,786,702,217,113,455,22,837,495,651,669,114,847,574,758,767,502,141,103,658,85,495,584,791,316,419,887,146,512,921,58,253,120,658,662,92,405,341,307,148,740,487,589,965,28,141,655,241,910,652,591,881,54,225,755,399,478,45,876,73,980,515,275,260,678,203,763,539,802,21,692,89,33,955,18,749,540,937,612,460,525,196,915,350,778,158,149,24,621,59,378,883,582,458,270,896,931,268,214,10,998,559,961,70,183,155,196,990,349,770,72,962,892,382,266,833,632,173,266,45,916,805,270,514,295,604,603,769,619,387,146,203,51,220,215,886,261,197,509,649,339,846,266,865,796,428,135,125,722,677,291,2,723,670,942,861,563,814,644,85,204,568,436,728,942,549,346,746,247,54,287,115,703,845,734,984,708,26,69,276,658,619,368,676,929,506,434,297,631,234,299,450,827,224,746,377,653,145,601,242,75,866,729,513,632,649,862,60,94,983,742,141,74,896,415,518,552,122,813,791,846,246,267,712,177,553,635,897,37,692,876,724,413,147,311,644,963,335,817,76,470,586,304,26,590,581,512,844,633,72,466,374,38,727,254,78,174,109,908,63,205,102,11,159,999,291,192,739,340,709,801,657,327,976,856,263,920,966,550,731,304,527,914,226,933,7,847,717,561,788,131,790,773,83,827,224,326,46,344,119,519,254,861,181,899,184,342,419,838,582,434,641,621,707,110,26,418,847,762,148,11,245,45,960,452,513,840,184,521,215,893,879,410,58,878,682,248,971,844,936,420,214,421,75,188,338,23,806,509,153,568,91,243,269,785,561,282,880,392,113,668,580,20,689", + "843,688,209,179,118,448,580,821,438,678,259,180,8,617,660,116,282,112,542,249,118,586,11,449,40,934,892,104,919,764,860,995,816,975,364,173,9,248,884,82,525,326,417,975,638,337,242,919,965,992,842,327,94,560,935,781,757,270,41,882,965,772,95,572,46,333,761,641,726,726,458,622,870,231,690,727,236,561,28,156,137,614,932,853,501,925,318,546,902,180,961,133,715,488,374,931,241,998,264,262,361,981,76,410,775,915,72,678,948,923,752,779,798,228,966,339,490,75,139,87,913,416,964,92,226,260,207,460,583,325,899,25,163,564,66,249,86,427,574,568,586,208,348,421,576,485,74,710,787,813,340,61,285,493,829,196,377,484,579,24,131,973,787,430,225,306,820,868,635,799,938,275,297,401,39,405,914,162,259,92,331,861,847,13,61,751,762,212,955,207,774,818,649,806,559,525,32,968,73,686,487,120,989,986,320,994,631,480,701,5,440,698,621,891,78,439,641,765,723,6,200,152,121,543,556,428,50,590,994,819,939,411,789,954,835,632,720,6,687,222,171,435,913,916,143,695,339,227,311,338,274,838,623,912,629,346,492,180,660,898,538,550,634,979,371,494,70,239,798,470,157,974,68,498,469,599,561,581,564,492,703,354,365,77,122,483,240,828,308,783,748,246,446,158,611,722,244,148,631,286,634,707,932,237,519,516,728,828,669,570,383,678,802,870,293,494,397,669,911,255,10,952,299,864,761,561,367,839,367,879,217,882,139,692,699,440,118,291,893,107,209,317,143,53,767,486,615,959,735,890,65,494,750,702,317,743,489,798,244,51,501,88,165,201,838,94,621,0,137,687,716,740,48,780,271,847,816,333,958,501,531,295,928,663,24,364,366,41,829,311,79,676,667,471,975,244,755,265,114,123,988,166,964,932,255,791,618,991,631,844,715,723,689,774,827,915,890,875,316,779,303,180,500,163,759,387,994,830,575,80,214,75,933,954,855,216,122,88,172,414,106,254,591,621,411,102,236,253,514,563,824,173,374,542,7,701,405,654,315,575,921,74,657,347,794,996,963,818,634,735,893,315,585,992,202,97,21,111,66,80,143,148,404,868,731,183,903,170,523,268,148,175,734,543,428,259,175,832,453,762,517,305,119,58,378,686,156,739,701,708,887,143,359,301,1000,215,379,735,347,664,210,767,848,226,223,92,340,559,677,487,529,55,339,187,227,560,830,548,613,815,361,59,334,285,170,819,569,135,815,197,578,87,824,142,726,425,943,979,633,606,453,990,902,434,601,805,992,167,129,718,763,190,276,779,370,424,965,385,60,186,718,922,47,192,776,742,159,869,704,291,528,387,777,736,14,890,328,544,992,251,126,190,861,502,488,227,528,495,651,207,816,483,245,630,753,706,580,276,549,52,880,9,302,737,895,8,38,898,46,307,747,797,512,683,737,614,773,297,881,339,437,674,819,974,661,121,928,857,22,984,437,801,450,315,21,416,982,432,126,341,863,177,983,930,242,755,722,713,953,234,162,277,231,887,552,158,552,381,143,154,646,23,752,325,718,596,74,741,960,77,16,505,498,863,528,396,716,555,262,652,773,924,248,120,971,106,419,980,96,891,129,968,368,894,253,727,861,575,60,253,366,987,602,73,236,163,179,772,892,328,835,662,887,304,460,831,631,943,758,89,239,872,803,322,880,442,410,944,802,747,57,244,973,144,616,432,704,758,896,240,152,483,958,147,409,207,160,908,124,770,433,541,386,154,56,564,912,309,373,304,995,236,715,894,714,831,966,952,818,637,261,187,663,13,998,571,52,737,671,958,25,781,161,253,257,309,777,214,571,53,856,140,626,153,545,612,250,763,708,179,659,507,586,990,230,410,478,290,243,388,932,613,564,489,284,302,475,10,142,579,510,838,89,954,38,329,586,866,367,651,72,365,617,374,240,955,848,498,384,670,116,492,833,904,994,777,973,442,391,651,983,662,492,343,60,144,904,720,817,33,199,887,854,12,677,261,758,486,435,364,695,509,195,945,837,998,843,19,898,106,524,340,645,364,422,698,836,890,69,497,576,668,385,264,721,480,918,138,846,376,297,246,245,371,671,60,850,663,665,808,685,733,156,185,794,10,934,156,356,38,64,661,246,61,954,349,432,560,417,109,991,554,432,120,795,366,460,362,904,119,374,968,188,223,116,437,254,902,313,277,949,40,219,756,813,812,607,616,330,516,897,279,700,569,811,618,154,771,40,752,923,945,109,406,456,232,199,157,479,584", + "222,246,561,788,311,910,519,786,611,179,905,854,291,550,431,335,594,619,340,772,325,546,349,703,89,640,322,983,13,971,788,875,166,62,240,11,586,600,340,4,232,932,653,765,383,44,297,5,843,40,223,198,445,603,76,786,742,208,544,184,623,863,636,272,553,993,828,870,382,230,499,372,570,756,293,404,266,193,605,675,717,362,921,442,420,4,103,625,278,908,808,829,785,387,659,175,298,166,255,616,260,578,508,167,993,608,298,705,231,334,147,639,584,374,629,368,502,259,944,19,935,590,989,23,902,160,600,67,689,959,923,349,906,754,949,576,170,893,656,352,344,144,284,22,230,24,495,821,196,865,122,729,869,382,655,313,54,748,121,428,111,896,171,221,225,756,873,580,317,230,405,328,457,155,140,402,430,152,902,728,273,928,820,778,719,818,356,35,399,265,135,672,367,760,875,763,799,917,701,579,999,346,491,264,898,260,856,539,269,100,46,367,189,560,661,115,808,402,802,20,550,457,789,767,6,230,478,678,118,678,657,995,763,569,498,331,443,603,157,557,368,923,352,86,487,978,496,536,785,450,336,149,949,653,306,193,982,642,29,403,518,369,640,276,675,551,155,363,613,3,471,420,554,60,934,841,988,162,313,89,122,510,341,37,31,157,919,797,647,471,502,543,995,68,237,280,465,803,591,677,834,462,584,293,402,741,535,935,234,832,557,329,82,181,677,655,552,483,623,355,935,241,807,159,357,404,442,701,152,964,30,381,771,180,11,767,692,858,303,670,104,476,919,298,26,839,175,944,94,213,441,569,627,876,927,120,171,505,964,767,563,171,822,719,551,768,462,137,0,183,166,526,222,63,867,175,773,698,360,405,855,401,306,566,526,996,13,168,520,103,637,66,103,125,218,255,481,770,672,625,101,816,50,259,370,441,744,671,44,822,856,946,329,163,861,786,863,891,185,94,885,894,586,77,811,708,506,20,919,797,170,878,23,130,197,272,458,331,734,767,962,284,447,12,791,721,756,501,837,527,847,979,803,552,8,312,227,127,427,460,828,381,284,246,855,829,260,24,970,534,85,765,391,468,801,823,151,817,232,958,276,614,626,551,707,290,288,686,536,707,388,531,41,422,811,123,481,286,793,607,946,676,172,348,816,383,716,190,638,755,383,925,992,158,630,93,510,588,876,700,511,420,446,447,538,29,86,993,808,38,997,8,421,868,903,28,965,876,850,876,948,150,32,699,473,400,56,651,560,528,873,830,72,57,956,403,742,784,635,727,743,411,884,952,519,365,573,268,256,642,940,76,518,739,666,765,2,253,798,400,461,857,870,755,608,652,926,932,861,36,415,759,181,939,710,200,385,996,319,271,123,964,276,884,285,701,43,951,472,652,986,133,958,747,749,489,288,659,167,929,458,828,665,282,167,284,776,88,942,440,431,953,306,719,296,301,934,106,999,52,141,82,454,855,553,296,531,866,32,368,407,463,111,620,905,824,216,215,39,284,281,996,287,328,877,22,681,508,649,781,697,333,468,846,613,910,369,489,570,803,880,870,699,233,351,858,263,87,858,873,889,205,634,26,210,662,259,667,194,170,983,642,610,631,628,443,257,481,247,229,576,761,419,221,974,483,604,941,909,479,752,615,793,329,418,139,273,631,961,971,400,321,272,172,947,341,694,679,774,701,537,89,677,47,654,178,271,622,415,828,130,753,443,681,968,903,151,867,594,793,275,647,358,4,546,748,624,559,39,546,819,717,133,477,206,555,953,187,792,429,755,296,117,372,149,919,897,216,486,281,53,296,362,693,323,349,654,347,504,18,159,580,915,49,564,94,960,597,811,55,291,615,480,68,158,811,173,723,49,344,755,777,87,887,986,557,84,270,823,867,39,42,5,287,66,660,337,480,676,841,317,480,15,368,737,16,399,988,6,200,249,990,790,928,105,708,167,745,979,898,352,765,188,931,393,992,884,503,334,62,588,263,104,967,619,247,499,634,811,317,985,346,460,105,932,369,522,104,613,997,226,466,31,39,721,579,715,120,192,133,959,748,454,595,607,930,122,717,742,279,22,684,536,959,751,898,776,839,995,173,215,546,650,535,131,584,168,165,587,643,90,232,508,589,293,487,695,730,609,153,536,430,886,62,101,526,50,458,657,999,726,410,709,524,59,33,126,809,290,720,2,936,450,212,634,141,722,450,184,852,153,749,933,166,994,59,503,103,401,679,364,482,880,68,820,144,503,396,413,110,951,395,161,238,973,676,600,337,980,573", + "690,854,354,663,525,415,588,832,174,352,635,131,654,693,924,507,854,276,210,28,948,798,73,640,218,238,992,979,896,740,911,365,341,465,107,423,892,901,288,963,804,561,837,110,402,185,588,674,987,768,58,477,726,208,644,704,929,392,812,6,212,476,183,864,722,429,821,564,7,765,633,239,104,150,592,961,594,827,197,269,359,861,931,810,635,992,524,119,733,52,771,11,146,307,10,373,178,957,160,350,34,524,316,692,250,306,636,514,616,477,560,420,291,54,960,503,821,994,519,576,2,317,108,432,498,107,616,485,18,9,118,405,666,352,534,320,248,363,220,856,177,418,917,754,106,94,966,901,320,829,207,370,31,823,146,985,806,436,496,160,211,246,70,878,200,193,404,470,430,852,702,198,38,857,577,448,551,204,714,826,923,698,580,598,750,753,722,837,775,449,650,276,708,82,37,334,516,108,41,824,385,857,415,181,89,972,828,676,811,48,443,769,281,133,503,996,672,639,209,781,798,382,362,399,670,671,96,222,552,719,751,615,334,173,425,682,575,353,787,949,11,497,22,491,241,710,997,569,217,553,95,674,805,172,688,506,169,990,391,1000,446,705,935,237,243,545,34,826,647,150,925,281,228,359,397,610,377,16,972,212,616,932,25,372,199,462,480,887,432,838,33,464,147,998,853,315,761,660,821,417,998,332,647,549,728,446,672,889,77,393,132,759,424,636,445,578,928,355,237,645,338,930,82,122,548,950,358,492,824,396,398,797,71,547,733,213,632,437,605,95,741,227,710,786,640,87,785,619,631,602,367,474,228,485,977,357,853,354,142,787,88,879,748,34,9,947,269,687,183,0,590,223,139,39,728,693,568,923,34,732,965,33,337,297,894,200,511,204,502,697,295,453,6,432,47,471,105,278,800,192,174,912,615,831,156,594,25,553,852,677,236,11,109,914,109,313,531,893,186,966,894,57,126,39,558,329,263,52,139,426,289,815,492,808,538,941,763,389,357,255,13,398,591,927,297,234,631,117,799,778,267,678,193,900,495,674,547,358,240,944,981,770,921,396,545,437,430,366,384,428,604,870,365,944,647,493,592,462,672,460,180,786,870,564,47,146,239,482,334,974,337,404,698,844,116,995,436,171,666,887,767,538,244,179,130,414,362,256,124,65,342,22,623,680,951,177,195,911,82,451,87,215,793,970,673,496,214,355,817,152,394,865,281,391,510,340,846,498,429,172,273,457,141,204,83,234,558,429,53,8,101,906,402,74,700,326,948,835,394,971,879,234,569,694,474,803,393,744,994,807,305,270,199,568,440,952,875,762,92,904,371,539,574,250,251,192,947,499,47,778,439,63,349,9,985,67,680,654,99,895,162,274,794,841,276,390,405,756,128,616,3,123,32,730,632,166,516,256,965,857,632,185,942,438,66,32,984,107,989,160,669,890,861,583,171,776,389,128,59,196,941,820,812,103,607,656,994,425,148,415,958,588,216,331,820,822,27,878,610,147,104,705,298,58,831,473,250,521,219,925,883,894,341,590,550,537,287,914,257,160,798,965,999,5,771,187,966,616,831,333,20,339,877,888,576,594,382,835,596,245,580,130,601,295,796,158,24,767,80,369,883,634,380,124,130,234,362,785,756,474,97,545,615,390,902,129,964,725,96,159,674,762,837,465,619,744,693,516,88,597,983,355,450,683,287,73,432,363,506,221,200,533,252,41,934,69,565,573,921,518,820,964,674,697,628,613,127,475,57,71,206,335,457,430,175,417,813,101,902,792,850,807,618,65,162,461,346,179,140,855,918,393,947,507,247,890,339,874,371,438,337,840,733,431,782,263,160,511,219,767,395,636,477,133,913,591,169,937,4,781,359,385,197,189,25,309,10,722,441,241,18,216,84,604,633,986,161,152,753,489,809,214,483,120,959,675,666,450,432,470,743,206,3,833,355,976,301,722,908,531,311,786,173,623,870,84,801,599,976,279,420,238,630,809,761,555,455,919,981,655,977,894,912,852,694,644,251,911,698,195,124,46,830,457,850,961,305,714,873,156,670,358,255,165,686,126,560,824,498,779,218,925,599,950,134,548,749,943,792,228,145,343,572,121,949,50,875,256,121,393,688,855,924,217,876,561,122,280,243,221,595,770,166,877,749,224,635,586,645,869,142,842,898,751,724,68,265,944,283,487,571,980,686,240,478,444,822,419,88,855,59,505,755,44,519,31,504,666,559,311,471,699,856,319,641,347,530,412,123,867,899,737,507,897,953,721,899,771,836,505", + "783,85,206,855,676,595,224,877,520,713,185,904,58,1000,737,778,769,988,878,361,503,622,988,907,624,315,334,69,646,351,742,882,746,780,331,61,830,109,406,931,893,136,685,513,73,681,671,936,577,948,592,320,552,224,670,464,978,119,903,993,301,245,776,425,687,995,676,356,103,686,232,586,903,327,968,131,494,819,89,695,96,868,608,114,581,356,815,110,155,782,249,201,49,222,292,156,455,432,858,896,342,195,739,242,42,195,902,997,788,11,873,356,177,632,596,529,742,110,921,477,537,652,469,361,628,187,771,337,776,706,87,448,564,203,110,818,125,459,263,368,724,338,801,713,815,708,566,343,856,894,851,570,201,298,946,573,422,437,455,271,122,530,315,279,894,706,843,489,683,222,140,449,636,987,96,678,634,210,589,919,570,175,290,727,288,727,283,751,287,189,285,213,99,416,872,212,519,986,477,732,356,348,21,402,632,279,623,894,102,579,954,351,427,549,738,458,374,476,671,334,841,263,974,546,934,287,559,492,906,94,399,908,913,173,341,410,867,555,78,262,447,94,428,843,595,433,208,828,693,870,574,893,195,783,118,142,89,835,512,374,59,585,79,506,960,530,723,410,799,33,18,652,627,696,668,617,615,653,223,166,973,14,413,147,326,645,534,830,696,498,276,27,591,825,702,61,238,321,13,474,234,297,548,842,220,407,718,325,621,527,363,23,225,471,691,68,215,898,706,65,44,460,6,21,476,232,974,375,327,260,106,246,833,62,706,378,671,681,441,345,495,190,140,412,216,427,537,529,555,405,362,643,937,742,124,770,933,51,365,237,962,904,720,357,248,706,492,716,166,590,0,429,432,34,99,503,861,33,69,45,947,631,542,410,55,171,135,311,865,799,278,147,528,804,157,144,964,380,595,204,679,862,242,297,75,66,746,730,363,291,86,883,674,182,302,459,591,576,450,476,801,846,967,866,466,81,47,11,371,220,799,841,256,796,943,75,571,658,573,472,318,575,992,204,956,864,675,353,900,845,532,241,962,407,646,336,652,780,989,24,608,455,150,594,571,991,578,510,57,868,921,568,893,114,704,654,652,782,831,980,250,176,457,945,339,672,408,888,114,561,765,765,677,759,573,473,413,16,152,256,784,185,576,106,925,912,236,704,216,654,484,296,739,546,675,614,391,212,402,259,705,74,202,948,279,751,54,216,136,757,253,405,269,715,324,136,630,923,459,846,76,746,258,493,134,967,346,240,17,151,459,2,185,595,438,316,377,385,667,865,169,544,215,908,762,791,508,533,472,289,966,800,777,50,889,1000,300,723,656,307,103,443,273,27,863,210,821,474,790,212,686,397,478,28,943,109,713,765,530,858,730,29,99,388,92,544,259,66,413,996,747,603,517,711,161,420,809,573,299,239,904,766,103,602,51,786,217,313,932,36,499,592,294,118,749,561,724,477,272,226,95,109,447,855,553,669,410,206,629,611,410,323,259,352,996,637,518,532,660,575,618,657,163,450,548,71,851,11,748,426,968,890,398,673,493,126,301,584,121,710,937,295,656,440,703,421,974,655,87,569,762,393,77,571,258,640,834,830,28,754,576,71,754,545,359,624,854,796,895,681,8,35,895,168,359,169,569,220,792,314,495,631,982,335,637,535,100,894,438,87,811,680,495,349,771,545,555,317,389,469,877,7,507,29,669,19,804,8,142,63,461,134,823,286,491,321,722,546,509,720,235,347,245,421,833,111,909,555,423,744,994,423,457,734,732,261,751,614,586,391,499,147,16,719,165,980,856,813,208,227,855,42,802,542,955,66,635,877,861,306,869,240,92,234,881,490,620,667,158,197,421,437,563,897,265,843,300,185,180,299,879,575,448,546,256,78,620,501,696,429,306,731,839,485,885,688,170,648,722,951,533,446,474,962,52,272,438,993,758,547,849,954,917,59,187,485,982,475,76,154,519,415,53,94,303,551,325,488,414,679,396,517,984,200,405,830,159,705,621,406,183,748,892,594,144,950,218,222,203,323,488,192,329,354,802,994,662,834,237,57,473,830,9,552,257,801,920,736,309,183,289,812,26,959,342,446,300,825,339,355,429,571,697,828,625,151,203,460,941,112,461,389,235,144,437,746,863,652,98,533,330,696,685,816,779,979,669,605,655,30,682,493,942,738,330,905,576,375,427,678,95,977,888,839,150,624,128,245,772,534,389,567,670,83,156,764,770,330,756,916,631,133,698,585,131,680,613,996,121,276,470,676,272,638,492,552,517,877,165,210", + "963,476,829,673,765,81,156,433,824,136,368,615,99,768,425,646,6,324,857,139,863,180,86,155,239,187,648,32,958,307,703,886,495,881,696,428,689,510,695,818,755,628,18,53,420,156,948,326,133,877,372,980,367,8,102,16,895,496,212,640,199,19,553,486,756,750,61,600,998,418,930,305,113,722,693,171,928,931,552,631,454,529,539,609,228,850,484,315,895,815,36,872,913,430,273,58,827,878,950,865,113,676,501,94,655,205,15,514,215,548,166,703,778,812,677,983,630,36,484,481,29,646,793,284,630,707,867,977,176,432,259,824,175,331,345,917,301,457,677,251,225,183,382,423,891,154,45,936,875,932,953,434,359,539,836,575,834,241,595,540,165,964,280,991,716,580,636,465,18,233,522,113,766,47,101,59,214,840,578,822,69,145,473,459,920,971,619,738,686,13,984,450,456,148,16,18,848,909,696,98,887,466,746,73,563,12,883,859,130,23,879,437,780,661,885,126,760,604,241,116,339,541,789,750,543,3,224,940,932,363,139,236,243,395,249,532,331,26,41,210,901,908,3,422,609,479,951,548,615,780,347,89,902,72,272,541,930,1,725,29,298,908,389,495,92,923,100,435,353,114,325,549,513,669,925,582,407,137,717,889,490,9,348,447,407,616,563,203,344,585,469,795,646,365,457,118,19,503,286,264,705,590,866,759,500,107,178,472,958,310,985,30,152,364,137,804,674,656,118,468,281,502,428,278,299,420,753,884,767,39,102,579,633,598,410,644,231,477,910,115,716,122,993,135,988,112,352,931,311,182,745,791,287,844,302,959,839,867,537,28,516,284,735,396,955,141,150,740,526,223,429,0,553,859,464,269,76,176,164,743,161,112,630,224,382,558,235,747,805,821,803,194,864,670,376,445,629,222,538,338,209,832,459,748,117,280,280,848,751,787,726,237,504,115,417,397,727,91,925,974,197,636,889,216,996,983,361,640,717,122,360,170,185,899,36,193,887,212,494,852,1000,595,319,85,397,988,188,653,26,931,634,787,807,176,267,694,574,591,569,637,631,395,870,225,430,681,599,763,725,524,419,249,23,20,689,500,691,111,709,316,941,516,470,475,861,509,851,903,971,938,820,383,825,720,856,322,801,998,773,286,169,542,202,719,71,275,191,176,860,984,798,747,118,328,984,984,836,578,196,307,832,339,706,77,594,540,886,301,684,728,404,714,28,429,683,907,454,736,918,202,26,42,554,767,315,223,459,685,938,288,273,865,554,931,135,189,806,896,155,764,902,420,35,433,49,701,842,484,167,897,895,332,273,941,350,488,828,138,203,785,629,223,91,15,712,758,537,414,81,883,904,195,600,195,901,260,730,497,583,20,80,634,65,885,999,279,149,92,706,117,70,955,645,780,516,666,663,830,55,290,578,762,280,333,240,516,226,768,484,740,65,57,260,73,878,448,496,485,954,301,909,968,853,219,699,75,764,655,396,638,345,827,135,256,857,186,289,147,764,279,532,34,856,784,415,96,408,320,480,834,126,721,283,181,863,805,978,403,497,898,467,206,98,766,583,549,800,467,548,696,870,796,820,575,400,927,178,471,636,489,663,832,254,49,370,228,794,773,302,123,559,569,819,847,157,576,276,309,45,153,631,898,336,38,289,974,430,213,8,813,808,691,533,980,960,562,643,490,7,46,945,888,991,445,761,415,744,67,508,263,748,162,599,173,399,851,467,932,135,374,28,277,675,23,545,855,595,695,854,953,366,566,767,662,568,238,583,411,407,129,659,690,641,446,442,325,55,730,716,806,199,904,816,999,597,787,795,429,648,480,489,470,674,973,991,819,378,315,542,144,403,271,167,187,625,504,823,189,95,683,168,202,848,751,667,881,965,423,238,223,785,886,459,656,114,637,947,876,466,995,455,447,184,301,937,29,333,519,299,282,754,504,167,698,258,866,2,420,729,816,339,855,198,790,701,168,924,237,123,752,584,880,873,82,246,582,423,533,60,158,655,945,393,692,909,795,959,916,747,972,542,961,959,993,243,965,261,595,276,111,346,157,321,560,706,571,857,878,96,140,884,547,397,32,414,339,178,761,563,268,252,514,404,185,543,660,779,584,99,41,748,15,671,429,851,639,719,630,609,157,927,165,367,695,860,692,800,103,675,997,892,629,473,140,452,371,201,2,60,42,19,993,120,680,242,272,302,231,526,419,520,398,988,137,184,340,609,832,331,659,453,695,506,439,161,589,556,27,745,256,764,31,499,331,882,326,999,360,443,293", + "550,243,537,728,933,977,745,468,452,383,174,956,536,159,428,887,896,596,72,31,525,132,144,247,8,586,727,907,260,315,828,919,168,407,44,402,866,351,728,616,320,823,16,399,451,292,464,426,498,942,287,635,44,578,51,575,52,450,286,18,849,645,858,186,990,936,980,307,411,397,597,907,202,113,803,717,371,246,695,324,598,531,580,540,954,590,186,3,392,343,607,378,218,253,701,148,974,453,534,220,172,15,743,464,636,352,350,33,600,667,768,158,203,522,760,203,802,515,598,338,708,288,454,668,308,67,307,426,891,16,355,806,846,128,771,68,436,476,854,660,350,308,759,921,489,501,750,381,280,467,661,936,666,16,139,251,836,440,669,999,41,421,738,153,950,197,512,807,88,484,818,995,202,161,330,728,726,852,414,376,299,94,712,263,426,994,347,820,96,13,514,93,783,954,826,677,32,520,743,806,572,572,5,138,121,14,650,963,183,532,777,624,573,781,472,188,224,335,478,660,937,943,512,296,213,818,99,476,474,357,618,867,120,868,393,502,221,308,810,842,843,355,210,797,476,978,185,758,143,670,32,395,845,714,920,726,472,532,244,109,525,620,986,718,561,192,582,924,110,220,325,108,473,59,713,572,701,881,48,891,801,261,7,202,200,815,2,460,604,934,294,202,967,425,704,471,450,866,406,361,370,914,965,326,437,83,250,979,159,908,684,347,256,637,166,421,118,390,862,623,395,593,474,639,248,841,97,391,191,963,710,692,256,516,831,208,626,825,565,640,409,557,133,230,550,405,341,637,42,559,804,820,52,737,690,156,739,270,6,940,822,558,920,980,803,139,381,48,222,139,432,553,0,189,779,510,327,598,116,383,91,433,4,642,430,817,567,978,688,176,253,823,69,185,994,337,235,421,488,871,172,685,923,98,458,579,619,813,417,999,71,285,917,439,255,54,158,816,919,610,263,345,595,762,612,799,247,181,80,495,456,750,469,961,198,319,878,863,967,640,2,936,83,637,595,355,569,43,291,268,906,630,525,275,643,168,946,588,47,799,317,632,449,785,953,259,48,836,395,974,979,375,550,559,336,758,855,636,130,762,959,468,808,330,765,466,600,404,372,403,564,625,40,10,876,126,597,924,766,392,818,910,562,295,73,870,384,865,896,838,636,770,888,844,225,993,479,518,528,56,18,182,664,363,245,912,895,666,661,498,520,556,711,700,628,884,118,556,421,60,47,204,875,866,145,532,340,616,885,885,77,634,848,46,748,336,736,996,455,338,98,393,457,725,703,140,10,857,876,620,227,44,402,883,570,93,453,896,308,398,533,348,861,944,53,580,147,912,321,195,764,114,797,648,525,870,763,725,115,749,913,480,277,313,812,154,162,132,727,553,758,101,924,367,138,706,659,533,817,684,807,999,574,956,845,473,498,26,167,880,301,307,591,372,76,759,943,83,626,782,270,479,533,858,360,617,573,373,925,707,913,208,871,997,274,793,992,318,668,383,507,339,73,204,927,549,698,394,981,13,441,61,765,70,944,564,891,260,235,746,142,486,25,517,398,249,151,264,638,340,492,937,243,715,560,9,811,353,138,856,62,853,243,333,334,556,670,936,728,49,959,585,946,308,152,608,324,709,464,527,243,812,153,268,993,320,849,789,33,25,706,759,409,342,804,886,243,213,862,717,712,586,425,711,757,812,299,585,61,28,129,216,546,315,483,341,995,973,101,562,967,733,824,457,831,79,947,943,257,617,396,835,246,957,14,494,245,352,802,704,109,581,891,17,51,481,967,622,645,588,682,643,290,466,836,360,278,128,795,183,355,423,944,47,774,538,896,637,820,580,394,748,575,391,545,725,792,301,747,686,865,47,910,876,61,46,454,336,6,201,731,178,467,841,123,848,153,272,278,642,908,734,126,235,162,575,648,177,144,145,636,499,85,489,980,698,44,961,688,43,186,998,988,348,161,964,777,778,743,258,70,938,559,885,690,411,486,269,630,500,945,906,124,398,644,210,646,997,114,48,733,312,606,730,526,965,707,685,890,170,943,367,816,44,76,930,432,666,956,415,930,20,341,654,527,643,957,401,495,410,718,299,591,793,600,873,926,652,623,730,989,311,506,618,170,666,609,783,453,761,347,308,800,790,903,479,672,101,804,17,703,873,778,347,418,927,369,684,937,316,639,437,129,283,510,448,678,60,463,127,266,172,108,935,84,885,912,607,352,686,370,796,806,77,482,601,769,129,980,121,446,835,824,200,925,459,860,579,212,418", + "621,513,510,479,298,659,834,532,884,896,505,834,353,673,33,364,140,822,454,494,619,741,336,549,802,603,828,237,256,782,607,93,403,864,561,15,25,601,500,960,442,898,723,395,153,251,638,361,203,706,962,11,99,519,498,434,79,465,999,294,257,843,548,938,504,341,917,329,503,902,311,527,348,791,931,722,513,696,856,524,159,507,523,281,624,886,493,914,904,328,861,381,721,503,863,518,290,486,128,133,238,912,697,109,628,738,180,152,871,318,506,269,212,570,638,793,476,260,391,99,783,422,256,126,365,390,130,442,664,583,824,261,906,585,326,93,652,961,568,740,472,249,703,196,412,215,548,898,727,402,803,537,419,57,441,248,998,774,134,554,324,429,562,923,97,780,985,260,484,646,679,821,579,527,581,777,34,342,55,396,122,538,78,687,53,533,484,491,42,280,935,884,20,211,193,560,72,213,726,801,332,123,106,920,386,862,196,293,302,273,833,68,731,701,170,368,997,598,378,131,923,935,92,912,767,840,443,265,457,138,932,176,399,453,640,213,827,28,481,731,710,676,173,188,246,454,870,413,850,396,40,791,106,276,461,249,333,265,644,31,486,37,642,267,468,936,102,849,279,511,383,917,314,55,198,491,84,482,595,543,166,926,363,68,892,214,216,657,867,652,798,365,231,833,613,961,566,325,96,62,391,131,319,929,602,589,308,15,110,747,982,38,193,241,269,393,767,792,722,317,534,731,485,970,691,107,778,366,895,239,633,696,430,168,499,686,416,75,763,685,235,408,340,826,611,997,418,416,594,164,715,873,107,907,933,693,750,659,224,370,323,476,161,166,937,546,596,780,63,39,34,859,189,0,528,254,892,796,935,694,127,11,209,199,326,888,865,985,468,88,704,47,589,156,285,262,980,555,208,537,709,212,2,59,563,886,50,368,92,168,171,246,681,596,648,426,335,419,367,572,871,759,385,218,807,24,93,227,329,887,195,414,532,283,898,985,160,689,22,15,760,777,311,935,51,221,790,928,481,504,171,660,603,829,317,611,915,386,650,955,661,775,332,423,795,505,106,993,438,214,280,11,74,845,564,452,186,817,39,89,891,775,356,625,805,701,40,737,486,6,807,285,683,919,546,769,904,871,646,978,380,480,374,470,268,714,24,845,243,511,447,690,84,770,494,593,550,535,872,536,209,187,705,203,386,615,712,441,88,630,228,339,300,274,11,254,740,187,364,816,357,935,763,830,964,350,631,328,478,409,533,253,26,982,256,685,164,943,16,582,752,229,965,17,788,204,499,673,843,965,107,172,289,522,876,786,561,272,74,78,336,772,633,941,13,513,561,14,453,218,718,610,49,781,481,998,818,950,156,857,510,137,196,692,516,751,959,37,994,30,343,701,121,470,814,965,282,936,550,969,515,153,223,83,161,528,109,540,508,732,536,945,551,398,462,533,131,431,4,511,321,944,672,7,403,544,887,344,975,296,72,549,575,901,188,938,883,405,125,710,983,647,562,257,426,635,117,905,282,255,852,979,644,962,377,114,108,326,265,935,126,94,235,272,511,99,603,417,8,511,371,815,176,969,947,431,575,709,756,639,481,119,246,776,187,493,119,434,176,447,318,13,302,724,102,266,349,421,810,667,777,686,802,284,676,84,353,191,357,296,856,156,316,203,699,964,174,480,175,413,680,134,414,435,877,110,982,587,668,336,603,698,26,713,787,531,234,482,806,495,47,1000,57,438,70,676,288,420,932,761,844,258,776,128,336,920,791,727,541,88,448,289,702,655,357,577,465,261,926,310,425,930,327,484,438,338,237,861,358,955,761,587,690,887,649,486,960,925,929,288,788,634,573,355,224,485,353,583,683,121,83,468,978,65,212,619,713,984,398,209,112,850,425,17,910,828,114,979,838,210,331,355,171,454,42,253,620,954,59,876,185,393,197,156,920,754,346,349,175,347,997,874,26,340,877,403,185,813,468,439,711,553,461,41,301,28,472,773,346,181,150,472,526,519,679,185,689,55,311,262,496,662,596,322,10,437,786,670,276,497,289,157,719,689,440,654,337,519,923,365,931,514,267,98,679,33,305,855,523,999,953,614,421,8,44,610,403,137,359,600,15,183,782,199,31,545,124,160,796,808,861,503,212,505,171,463,145,718,862,146,210,595,18,502,604,249,71,877,538,130,529,844,25,168,242,127,602,84,548,514,553,926,855,315,345,776,472,973,737,337,749,955,279,223,291,848,386,128,201,281,941,667,989,942,718,187,720,381,346,471", + "211,895,279,937,257,648,34,438,179,582,573,153,44,292,60,977,296,397,491,86,717,453,627,118,824,642,481,890,341,236,200,23,816,162,153,546,972,313,259,441,496,354,623,535,280,534,590,76,730,327,454,506,667,930,691,35,627,513,608,126,306,92,635,295,723,261,729,175,99,889,804,404,561,189,915,697,127,262,309,258,709,320,175,7,694,353,444,654,847,17,465,716,318,68,784,120,239,904,965,971,422,295,451,596,691,275,164,822,356,330,222,369,511,566,47,283,150,556,730,67,628,84,483,643,925,265,830,385,449,795,994,326,96,719,155,312,863,145,950,790,18,121,867,961,587,455,175,515,806,802,620,519,126,284,928,59,372,971,716,484,946,791,864,776,408,678,244,700,558,341,34,266,447,773,516,657,118,780,131,613,511,433,119,345,270,696,257,766,860,576,291,777,205,734,966,904,583,615,392,615,635,722,876,373,577,859,994,25,574,980,526,709,438,104,255,254,213,512,323,6,961,685,423,639,626,246,193,496,852,998,438,355,71,805,293,861,296,903,319,246,640,379,753,819,860,432,725,463,28,131,463,590,965,355,573,483,171,464,536,788,793,54,550,198,832,549,740,996,107,386,632,897,226,307,905,292,37,260,855,762,521,329,437,472,1,609,58,687,58,473,490,548,928,464,650,84,416,311,525,925,788,385,788,764,775,845,219,209,941,718,637,675,404,846,388,102,949,134,579,403,591,992,132,153,100,479,375,899,858,977,454,115,136,544,518,149,577,450,475,795,173,458,505,782,688,191,784,578,651,336,929,605,184,828,169,545,898,600,243,663,65,274,430,3,279,224,118,271,867,728,99,464,779,528,0,147,672,70,877,609,198,131,189,703,18,392,579,107,913,951,911,916,269,60,540,364,969,537,956,813,380,672,909,986,950,72,913,519,582,960,291,827,33,401,338,91,972,127,122,571,965,557,454,247,642,641,222,87,642,971,893,77,287,58,308,846,490,891,500,362,513,422,53,619,799,298,952,521,398,924,448,540,562,942,875,62,649,866,217,830,813,862,281,962,404,498,819,118,276,829,25,562,685,592,910,198,595,195,864,167,93,399,704,101,891,187,495,962,777,618,741,61,651,584,610,287,622,896,379,872,957,545,630,571,51,767,959,799,415,24,732,132,585,715,65,883,452,481,19,674,894,403,316,415,738,595,822,854,860,431,861,870,124,368,689,121,134,331,670,935,364,226,780,925,388,996,801,260,548,988,123,721,54,363,76,560,471,297,661,201,524,476,17,564,228,530,607,20,164,759,625,404,161,863,787,733,858,342,88,621,141,637,7,864,924,48,62,197,893,30,308,817,305,769,879,551,412,286,106,531,222,639,897,748,189,685,50,361,19,191,864,597,793,574,948,149,93,867,243,82,938,868,513,667,54,126,241,809,128,18,104,191,964,837,793,872,742,255,761,712,589,230,909,283,361,672,193,970,101,7,740,262,76,485,372,700,502,900,781,976,667,384,880,392,832,227,434,764,918,229,797,968,750,748,98,363,202,755,388,692,412,239,847,865,212,858,496,774,378,586,775,209,514,550,349,42,591,480,190,579,290,165,896,194,425,34,292,106,263,768,792,880,522,988,877,614,590,816,756,917,861,124,842,463,317,774,789,512,808,935,849,735,161,258,765,994,434,395,648,609,216,865,182,995,124,540,213,897,944,201,884,145,698,778,128,457,996,788,983,949,315,439,797,684,484,175,915,105,729,10,119,648,774,527,883,945,65,231,401,733,968,674,879,468,325,496,749,438,348,377,537,233,764,394,644,152,832,61,659,641,608,846,291,669,674,75,894,829,634,173,587,191,875,416,270,385,811,554,578,767,473,969,473,464,431,764,592,339,227,851,775,365,578,431,601,248,64,205,238,398,867,240,654,344,76,624,312,799,892,761,231,131,708,244,442,775,486,680,188,655,276,828,874,525,543,868,24,120,227,651,562,829,353,995,963,523,245,895,347,175,731,520,958,8,53,208,165,294,985,452,528,801,436,615,246,326,88,149,891,357,203,974,951,389,305,861,156,215,882,34,476,816,568,678,991,124,119,349,899,5,175,338,30,824,797,145,464,851,598,957,335,672,357,787,415,383,220,45,956,265,241,260,414,386,532,757,214,798,39,829,287,363,40,881,747,958,635,944,187,979,374,348,4,83,869,557,350,891,841,216,210,331,679,976,567,638,548,216,378,318,562,202,347,661,411,263,302,581,264,447,460,57,815,773,336,517,71,451,377,887", + "276,569,277,890,668,742,768,276,255,749,423,54,999,163,264,784,221,586,649,739,642,857,149,15,688,511,556,613,772,742,870,141,395,8,757,569,822,49,85,303,979,564,74,712,489,834,629,232,555,424,654,481,530,647,290,317,665,952,905,442,786,614,957,579,6,546,324,214,857,146,967,289,836,559,560,459,462,493,886,742,366,738,242,9,329,859,102,880,276,412,43,561,594,605,820,120,530,605,120,307,87,970,13,762,928,218,514,672,449,120,215,185,451,512,802,569,446,416,314,917,140,780,635,716,668,458,441,5,782,827,360,87,426,771,62,160,883,256,716,816,922,632,82,837,579,367,95,394,550,952,743,357,553,317,156,327,516,700,585,339,771,546,323,102,200,937,989,772,773,215,342,272,125,164,2,122,549,283,701,617,583,277,595,152,213,852,634,702,256,847,164,259,72,475,577,246,652,745,120,241,874,3,20,138,957,611,812,407,884,200,517,597,592,888,59,610,236,365,999,365,881,31,853,157,201,162,161,772,7,180,137,877,21,561,41,519,96,21,380,225,334,260,459,772,955,394,830,333,944,403,9,323,567,511,172,581,111,411,348,29,971,143,42,693,680,840,252,646,873,488,68,25,735,562,195,70,296,465,492,361,199,6,565,208,136,403,925,458,851,723,188,119,984,816,224,527,682,129,426,394,288,518,37,504,488,635,778,817,167,142,302,769,805,811,355,348,157,598,796,982,526,974,104,180,26,572,846,882,705,603,96,706,992,80,725,317,360,443,198,139,114,949,325,796,739,142,111,320,153,739,255,771,311,123,91,489,766,386,201,561,99,169,475,467,29,88,212,847,175,693,503,269,510,254,147,0,364,277,672,212,814,167,685,806,36,695,319,747,687,775,366,592,684,968,891,446,462,874,485,556,602,449,611,686,955,993,594,571,245,705,9,217,382,795,975,149,579,871,892,224,259,210,440,834,973,479,935,139,887,890,693,230,639,201,379,320,417,677,153,775,766,754,776,190,222,234,533,176,603,753,958,571,975,90,745,701,459,554,294,419,158,517,712,614,218,406,64,829,216,245,267,738,772,248,405,638,676,665,507,997,638,666,469,134,837,327,315,45,783,873,464,707,13,367,729,84,405,764,969,132,104,267,100,184,142,229,407,685,116,461,592,239,345,717,43,382,90,247,181,52,489,811,337,185,705,928,767,221,813,731,905,17,28,613,825,698,986,143,446,761,224,933,618,522,382,6,259,763,817,867,673,965,846,210,180,829,314,148,44,64,173,274,944,687,721,115,952,498,181,351,119,123,66,496,718,169,427,65,483,782,487,792,526,114,477,94,993,898,324,794,225,600,761,900,788,141,387,274,290,246,162,799,580,62,521,169,428,80,706,645,851,624,640,685,655,76,115,917,201,921,861,244,715,406,97,776,919,477,914,567,594,910,97,730,495,783,864,960,712,575,784,668,757,273,18,123,301,917,579,38,240,659,241,496,204,27,111,901,164,181,869,774,272,447,391,63,162,459,865,456,211,288,214,348,806,64,719,944,499,478,49,444,242,5,297,293,257,98,576,258,299,899,573,3,534,203,194,386,327,524,137,644,743,563,97,255,484,322,870,128,873,928,74,639,325,644,978,648,785,483,198,620,211,788,79,574,767,436,683,483,223,669,392,56,79,22,487,159,68,77,45,13,195,625,809,749,162,213,814,512,26,264,785,958,604,521,273,493,971,929,795,624,84,665,656,300,730,294,547,798,450,378,359,744,364,814,894,377,873,542,64,31,245,913,455,68,724,884,697,163,473,534,887,572,678,183,759,569,425,768,782,63,262,828,832,387,228,592,301,489,369,223,801,637,907,672,190,32,763,612,358,948,331,869,156,40,196,383,181,102,388,515,690,394,284,512,672,856,869,125,579,664,689,942,374,635,614,642,370,804,99,166,850,916,867,929,159,901,639,125,866,458,702,23,685,59,841,317,29,210,113,212,881,675,69,210,807,327,15,723,893,608,749,447,555,511,140,523,625,598,594,358,18,186,294,492,527,238,576,882,559,853,296,745,995,694,146,963,490,83,737,682,412,482,861,274,907,826,87,702,816,419,193,232,611,781,437,197,645,221,341,168,446,210,775,237,849,42,143,144,638,466,259,714,247,476,708,2,83,363,98,760,419,798,390,535,946,537,475,887,530,879,77,481,801,39,269,927,763,415,997,65,429,200,371,101,128,314,143,855,245,877,696,988,196,792,593,272,358,760,872,512,198,185,737,833,917,868,494,961", + "133,29,316,328,939,463,258,544,894,340,922,142,944,117,699,836,669,381,580,838,632,684,701,156,329,85,54,203,61,138,662,94,441,680,905,780,15,874,586,642,576,399,891,386,892,388,577,250,170,856,185,954,95,919,132,279,408,722,135,286,241,99,653,574,906,66,42,652,41,537,508,960,93,630,129,891,786,733,901,117,78,410,683,638,240,258,380,742,740,922,7,393,384,141,100,284,900,258,298,497,755,826,146,982,904,24,335,173,199,798,575,845,385,370,845,554,725,536,203,548,23,609,185,967,643,310,377,833,193,575,235,18,632,539,579,968,552,685,556,836,162,17,570,195,605,189,948,448,974,712,990,906,955,11,252,50,742,59,158,154,674,557,638,92,631,716,683,518,658,53,354,419,466,700,958,203,977,39,209,74,491,850,13,592,604,385,666,292,425,463,959,485,780,666,820,846,410,890,388,405,667,152,479,507,407,622,859,682,259,106,34,274,589,813,596,486,610,581,489,140,810,999,205,59,483,270,406,530,555,269,232,645,248,399,67,738,756,256,89,686,441,246,17,803,582,281,877,955,110,364,858,797,908,642,395,28,367,722,384,676,199,458,635,83,868,954,712,245,594,72,599,927,100,880,759,445,998,535,780,357,970,679,458,483,488,894,784,266,925,767,602,503,801,600,839,265,282,194,927,214,526,998,681,659,96,796,832,750,963,406,462,183,828,725,503,234,874,134,484,802,753,811,958,854,260,888,984,559,388,914,749,413,996,740,39,734,851,366,425,629,480,908,511,73,531,450,782,793,510,104,346,673,443,864,975,67,916,155,663,364,841,617,536,509,260,636,931,816,773,568,861,76,327,892,672,364,0,137,428,278,315,376,954,315,273,399,241,559,830,665,817,491,308,952,839,244,14,13,280,749,922,360,105,111,423,605,527,837,132,435,582,774,727,695,569,27,150,533,294,535,385,343,985,794,226,908,903,888,607,185,413,419,322,870,596,609,869,786,963,182,669,134,979,578,497,852,170,309,726,487,356,462,95,201,324,166,496,917,733,983,748,503,334,701,658,477,95,636,419,359,408,628,343,301,248,983,176,624,266,2,611,538,814,412,720,703,97,488,699,300,871,325,898,440,557,494,10,480,581,301,787,566,797,830,593,158,100,873,972,391,471,310,124,552,889,30,856,396,682,91,685,837,47,503,914,625,696,232,29,44,125,627,518,892,718,248,632,301,219,876,31,911,988,108,942,494,183,593,141,411,125,371,630,46,992,3,376,256,85,19,94,446,28,274,570,978,422,618,191,715,685,699,568,871,453,144,227,921,205,994,82,726,804,321,409,966,978,632,276,101,408,206,808,161,41,878,48,307,912,288,401,748,448,971,74,363,860,488,940,654,736,652,907,405,714,486,785,268,747,29,851,858,519,90,124,82,747,953,872,654,943,572,204,496,402,479,170,391,33,319,80,946,714,507,339,997,377,383,217,510,35,602,819,639,968,164,16,771,244,709,843,867,923,117,435,743,659,671,413,957,181,18,708,725,753,712,453,172,988,472,100,520,522,103,597,426,133,987,227,656,616,705,772,423,696,228,670,382,530,245,370,330,685,461,633,475,312,47,529,646,57,371,501,213,532,399,301,482,568,946,661,310,142,686,831,18,786,825,902,85,874,42,675,876,111,857,530,572,342,511,457,506,476,958,58,940,170,470,355,409,251,601,913,738,523,976,936,243,785,833,222,394,540,63,338,297,234,880,616,22,13,118,829,889,600,746,193,834,105,809,654,426,968,206,922,890,801,496,833,981,472,183,808,158,632,64,709,756,532,501,118,906,344,206,876,312,396,3,29,781,428,476,782,682,934,411,41,42,750,865,719,913,28,455,693,175,599,886,478,933,24,567,246,661,901,461,186,75,905,377,449,600,188,693,678,467,743,349,811,498,591,423,79,407,696,631,657,732,134,508,112,576,373,113,391,545,591,160,728,873,608,377,831,643,183,275,426,855,494,520,487,532,541,85,99,127,931,114,909,580,203,194,803,505,703,327,419,223,450,822,880,546,498,913,438,267,143,892,199,819,135,34,26,872,716,435,287,329,755,7,92,750,942,87,399,40,701,301,850,1000,882,713,509,821,896,719,661,530,369,519,893,846,622,933,567,566,713,691,762,802,678,740,302,459,374,446,516,89,435,911,867,618,320,715,140,568,633,512,891,948,469,107,440,789,74,396,526,530,477,338,820,435,655,789,703,7,195,714,325,232,796,160,729,406,47,952,614,715,57,185", + "303,561,143,961,971,7,68,53,19,979,923,423,470,157,919,656,276,438,293,182,480,436,143,338,157,794,259,25,846,362,955,345,411,639,382,232,193,910,755,211,982,693,62,27,842,763,494,560,266,22,710,822,392,153,167,845,621,889,59,169,434,959,123,866,879,726,952,548,594,24,466,41,294,497,990,95,68,283,913,171,937,852,833,363,741,607,473,999,127,806,523,270,144,862,370,718,230,477,963,771,300,409,837,683,895,257,150,450,770,786,990,454,420,399,694,123,270,449,918,652,426,237,577,667,870,384,177,834,741,561,997,263,459,994,243,794,282,691,806,843,852,168,375,664,299,7,835,736,360,962,601,367,189,67,36,282,882,600,264,262,721,566,507,190,132,837,671,207,282,707,539,754,498,323,242,728,363,866,570,805,919,246,139,550,335,600,247,60,561,561,346,61,483,581,513,406,330,707,421,761,988,126,301,732,626,588,562,669,320,234,150,873,405,288,614,397,193,294,133,882,444,54,243,166,838,720,910,364,193,375,821,564,74,990,111,92,261,590,896,136,421,629,302,131,675,600,998,156,473,939,90,986,869,570,355,936,453,654,903,655,193,430,931,892,906,188,471,268,198,646,227,724,408,706,857,577,483,109,771,110,467,296,670,234,380,836,441,389,845,481,693,470,604,70,960,101,937,392,694,607,457,526,452,248,175,173,696,220,961,813,597,434,876,244,866,805,653,920,380,807,217,400,327,255,125,328,847,670,520,759,713,509,927,241,577,73,985,694,835,742,496,368,831,373,217,736,415,135,466,266,379,253,240,894,408,452,702,501,303,204,671,250,553,257,346,864,655,333,698,923,33,176,598,796,70,277,137,0,478,437,353,627,952,879,947,298,509,135,10,75,416,352,680,757,370,682,586,282,444,174,482,555,224,481,599,359,630,395,402,185,25,858,322,355,235,107,241,580,456,957,941,555,4,807,895,265,466,507,314,58,406,410,326,154,932,853,91,269,696,605,149,890,655,891,883,370,33,750,839,985,155,138,385,926,655,538,126,625,90,551,777,662,510,750,427,323,453,775,354,566,247,941,427,392,744,360,721,511,865,466,552,675,524,96,313,138,470,252,979,868,445,320,232,22,596,250,133,334,957,737,526,729,864,345,523,311,449,113,261,452,123,767,476,338,560,658,150,455,198,143,909,200,335,151,328,109,102,258,323,563,919,748,701,165,352,998,48,190,64,626,594,281,19,367,729,364,809,51,262,918,628,665,254,806,743,338,228,59,885,621,910,655,931,274,359,906,481,865,317,311,867,33,479,615,900,248,893,510,722,21,16,209,413,898,943,319,865,589,849,343,378,512,584,279,165,789,299,334,101,522,735,35,276,508,674,478,439,934,489,472,423,139,325,419,836,136,575,516,229,265,695,693,621,370,955,6,950,374,649,351,830,492,372,703,264,761,106,448,417,329,326,12,818,331,243,596,268,366,867,336,261,413,657,167,704,260,221,944,63,84,610,529,364,635,881,355,930,730,597,908,36,448,226,687,459,510,193,149,57,206,573,744,745,525,916,457,349,254,566,640,763,139,947,482,248,905,820,11,478,700,89,191,892,560,316,700,229,600,646,888,707,366,321,199,287,139,63,340,145,611,619,294,321,645,259,69,181,669,336,27,37,295,106,330,499,460,690,174,461,908,165,383,799,567,565,448,611,714,886,658,27,882,167,51,275,428,134,590,814,902,453,239,555,973,10,107,782,400,140,574,552,409,718,522,532,625,812,955,566,427,429,280,497,382,752,501,84,280,475,207,180,325,794,946,669,32,517,932,201,359,410,723,896,198,429,516,796,892,558,335,103,891,259,400,454,485,654,685,4,834,647,370,446,18,50,290,867,413,95,808,223,397,281,644,982,508,616,679,454,291,817,228,109,284,539,857,418,44,735,634,761,711,342,130,475,928,937,223,692,262,766,511,862,762,212,825,745,547,683,694,473,637,7,602,112,594,83,171,823,430,458,932,601,129,81,287,284,573,292,620,235,713,112,771,40,899,476,639,673,270,113,303,42,431,605,879,447,496,784,349,875,762,567,589,601,52,69,853,934,68,452,281,752,75,60,82,512,644,728,698,380,996,703,533,608,524,582,149,910,332,935,346,555,202,496,281,738,891,173,4,533,43,116,116,597,907,877,641,644,432,923,615,257,504,369,964,937,111,635,693,353,33,617,858,560,42,327,194,799,282,435,23,29,680,88,464,658,868,485,121,545,861,739,908,574,896,864,255,970,724", + "695,528,32,91,661,65,722,47,553,70,425,861,197,893,369,129,262,67,805,684,9,214,352,818,250,58,461,463,186,516,93,428,122,350,908,425,366,39,261,91,591,678,614,977,973,890,680,350,137,21,580,212,611,723,970,764,290,576,652,597,982,904,352,356,877,995,516,900,531,780,992,507,605,10,381,838,366,510,716,414,916,712,604,368,807,279,650,866,333,614,404,531,571,311,409,538,603,955,102,946,328,936,430,903,903,181,353,475,707,710,694,348,710,587,937,725,812,541,795,249,924,177,1,655,383,183,765,119,251,351,824,270,955,304,550,837,418,154,523,304,474,299,717,478,718,853,910,448,108,847,165,805,535,824,660,966,197,938,941,781,3,731,374,986,64,457,529,572,483,657,377,899,101,550,846,711,663,125,976,338,46,271,920,666,978,156,632,641,785,227,633,134,677,516,335,719,571,672,91,160,493,472,626,204,859,279,200,545,537,511,372,778,584,701,651,127,220,206,852,949,587,856,584,48,386,594,631,505,984,707,876,42,752,640,945,911,662,796,817,570,846,214,127,476,500,4,618,987,240,804,946,308,923,331,147,48,349,606,316,542,334,317,463,570,486,587,622,142,520,594,558,51,108,623,907,735,508,70,489,308,557,217,186,829,693,452,273,627,101,703,374,705,537,500,379,72,303,992,458,768,871,462,724,59,860,248,123,62,911,283,876,420,475,165,373,243,54,83,382,725,748,611,863,813,800,824,978,756,688,331,152,201,938,836,534,984,490,139,216,241,549,454,453,766,788,317,880,89,189,873,126,96,631,46,671,787,656,934,569,910,258,690,824,805,602,760,661,958,360,34,69,164,116,935,877,672,428,478,0,991,832,802,225,667,552,577,913,497,564,945,318,877,832,140,785,431,802,162,735,559,176,483,824,211,131,250,303,719,617,843,59,693,176,973,184,701,610,349,379,464,340,281,212,317,71,331,683,914,100,784,735,200,177,459,18,556,819,247,866,627,54,303,8,400,788,179,254,572,220,668,406,101,920,661,708,58,800,769,850,706,364,4,844,873,377,747,125,975,722,705,168,505,767,58,448,456,633,570,860,187,767,50,919,509,693,54,68,682,603,233,414,828,523,490,499,249,132,653,417,454,592,134,38,605,926,591,857,945,642,476,888,949,376,205,867,958,389,703,518,356,678,93,615,576,473,479,577,634,847,598,714,231,712,813,672,702,997,582,266,446,268,85,869,405,308,547,970,180,477,572,722,694,254,369,289,966,891,599,956,69,196,143,467,872,834,440,116,930,135,563,363,341,774,140,619,242,637,10,275,700,405,669,66,776,486,571,331,228,597,706,431,639,538,501,526,27,284,543,370,72,726,278,153,97,348,665,67,185,793,688,33,611,984,415,528,758,251,801,646,53,983,784,945,690,103,566,895,185,366,115,174,393,903,726,953,106,909,373,99,832,546,691,667,938,625,287,304,189,431,990,204,80,780,418,417,474,822,493,248,800,629,774,675,91,563,889,750,777,936,472,163,967,833,572,656,535,556,118,571,337,782,512,914,896,636,172,677,403,18,5,121,85,121,931,467,259,404,815,476,514,299,692,834,368,324,674,63,321,10,896,90,128,433,174,579,232,714,522,291,730,184,146,737,77,593,591,98,763,403,601,992,889,516,408,108,959,198,697,13,977,814,540,289,175,418,837,353,165,358,26,489,25,313,592,692,836,604,339,531,780,288,807,238,271,694,448,754,818,233,420,148,997,464,575,374,290,663,371,819,834,397,683,948,381,260,802,413,775,45,238,815,992,981,162,775,442,516,103,247,675,514,512,351,300,977,396,531,523,637,150,44,43,171,479,588,914,185,20,850,436,961,150,78,335,254,15,486,432,231,564,949,63,623,515,419,315,487,66,843,774,495,345,170,546,317,862,974,710,668,550,827,90,179,960,744,5,741,13,215,990,110,809,802,85,94,957,87,717,239,225,737,25,380,878,991,268,666,292,886,271,833,490,522,790,570,45,831,615,554,554,673,654,451,559,373,324,936,316,107,480,443,299,104,851,995,760,33,509,558,309,720,336,184,857,644,540,957,523,199,457,979,278,868,75,649,315,783,857,775,7,663,383,148,271,450,384,991,601,764,875,9,872,71,373,243,450,634,739,351,599,224,921,53,81,57,658,562,340,181,29,620,623,376,157,598,537,548,303,318,503,358,718,768,392,576,173,600,710,476,5,990,246,723,719,107,963,102,421,670,31,805,206,336,316,924,900,863,940,323,361", + "211,525,948,311,4,572,727,372,936,588,339,961,564,890,763,558,509,776,24,460,685,309,684,49,762,958,276,166,528,306,194,741,71,961,983,465,829,881,408,77,856,512,630,203,579,530,560,983,937,807,926,215,163,989,130,925,568,34,650,458,311,51,824,169,32,682,321,231,835,822,266,70,394,51,411,323,799,898,417,882,776,680,685,763,549,121,178,75,157,157,840,51,422,701,709,570,776,830,797,909,843,152,724,75,584,57,906,986,586,948,546,125,975,430,326,134,99,924,86,613,885,992,780,612,745,137,781,102,655,467,377,946,83,960,744,75,470,156,497,516,171,177,362,76,505,286,931,818,92,548,236,814,476,680,9,533,481,913,112,649,314,50,162,427,801,459,938,424,82,372,13,815,336,829,264,597,549,641,808,245,47,35,770,551,760,224,368,9,823,109,750,392,692,76,500,416,998,697,634,925,406,466,352,747,157,964,344,378,621,4,861,726,882,215,906,460,107,412,911,128,581,228,971,549,465,132,415,335,364,350,931,436,432,14,27,62,797,586,944,135,620,752,751,167,328,386,252,186,667,751,869,12,655,382,529,865,831,880,702,35,55,160,675,662,688,567,519,952,458,496,663,388,128,663,238,209,846,27,927,566,885,282,63,751,717,11,214,624,342,459,476,296,579,8,802,347,857,691,528,307,978,783,474,874,482,292,260,304,484,877,434,198,418,604,383,578,917,415,247,16,137,538,839,44,47,920,307,260,122,481,66,645,169,701,831,892,265,435,803,821,996,197,409,126,311,632,295,538,767,483,650,604,245,940,457,796,685,161,717,718,576,814,408,353,426,194,892,501,405,732,45,743,383,694,609,212,278,437,991,0,808,114,207,395,95,82,47,332,462,367,210,426,193,201,630,770,756,511,690,74,828,866,245,262,992,163,316,174,253,341,164,374,650,510,766,618,185,249,908,801,60,56,310,475,16,904,199,721,114,290,582,298,873,688,226,4,395,785,438,873,445,955,491,119,832,246,234,529,83,909,496,311,278,374,425,425,875,443,644,498,532,786,930,877,526,36,257,167,621,407,979,489,998,348,435,391,741,992,232,72,748,627,137,673,148,940,618,930,952,89,961,345,469,104,332,556,548,48,968,814,495,317,851,745,835,749,685,106,897,962,127,303,436,214,40,94,992,224,847,79,85,824,775,392,927,599,901,611,724,793,121,226,801,905,976,968,682,580,440,353,660,100,226,87,407,863,257,719,36,598,678,736,411,917,750,502,423,780,205,923,587,30,174,702,179,138,167,992,399,756,143,332,524,741,296,679,564,355,413,317,505,464,335,683,558,72,890,387,66,600,971,237,726,811,160,613,942,5,178,346,510,460,665,419,110,673,889,579,877,368,674,720,975,818,663,206,935,443,22,907,203,853,312,886,750,883,426,460,973,50,192,486,230,645,738,619,489,177,993,972,346,790,315,434,923,719,76,12,673,355,941,964,437,845,123,34,657,404,58,431,712,400,441,531,695,648,149,826,59,161,364,427,801,243,569,814,445,645,110,577,674,180,514,182,917,34,79,783,820,938,54,66,277,108,817,210,243,299,954,451,766,856,472,401,655,686,858,605,328,635,322,70,492,555,976,481,490,320,227,864,531,101,530,825,829,380,8,827,99,211,681,795,426,646,170,419,899,611,340,622,424,234,64,826,289,770,125,63,481,540,807,389,243,271,911,986,277,863,4,945,733,282,621,236,912,989,946,568,558,431,75,18,539,690,299,650,574,563,463,446,992,70,164,762,336,581,317,115,336,340,136,782,999,995,800,753,875,15,406,291,254,749,308,153,117,176,392,950,647,137,978,286,221,423,28,175,574,695,811,917,311,140,478,164,572,996,313,53,862,728,610,860,829,643,706,210,592,100,245,677,758,838,248,236,408,94,730,814,957,498,405,649,139,248,832,317,815,159,141,505,922,397,197,200,768,594,302,600,679,417,366,426,47,84,962,422,594,880,817,691,989,418,185,62,778,831,161,918,617,48,106,67,114,185,130,729,203,439,647,925,150,707,391,257,260,525,689,950,933,419,857,935,486,919,936,298,54,847,227,506,378,871,467,706,349,464,385,62,606,512,526,378,663,410,299,861,229,344,83,16,861,114,153,378,141,989,93,936,458,848,920,605,35,442,672,95,361,95,504,156,532,310,681,431,639,15,428,105,370,258,955,334,694,984,849,94,224,224,574,806,413,241,115,812,167,181,507,969,456,671,941,389,484,305,449,460,325,641,660,77", + "957,333,772,494,853,807,255,257,616,389,481,231,525,558,863,169,66,289,69,166,609,774,373,85,789,520,273,48,391,588,559,530,955,597,488,387,85,576,250,320,537,509,300,694,625,617,681,338,278,80,274,828,785,648,627,210,761,741,118,935,795,763,545,897,772,755,8,428,900,816,548,759,213,249,96,83,14,150,176,808,473,150,503,191,619,607,641,899,624,855,948,813,136,740,110,917,180,588,518,737,566,975,796,810,255,964,233,826,842,976,696,2,968,723,895,231,7,376,523,686,350,583,314,328,477,670,473,408,345,5,65,233,139,287,57,423,633,766,130,741,928,836,463,768,458,749,57,30,178,379,360,557,435,562,992,5,94,33,201,796,624,17,540,120,234,61,91,298,272,255,443,59,239,107,129,884,71,306,237,344,814,26,894,996,918,402,329,123,191,1,980,381,473,47,779,360,795,918,108,679,886,419,439,779,390,305,411,650,283,276,618,944,118,191,223,947,70,827,588,997,106,407,315,104,788,656,520,347,231,9,887,376,662,296,142,67,564,320,217,194,626,688,54,568,632,366,999,573,249,331,635,756,900,982,944,552,72,207,865,885,313,294,433,303,632,305,607,713,210,778,703,743,614,3,494,779,236,328,956,589,607,960,454,703,304,694,684,650,439,726,820,942,801,818,630,748,966,514,6,136,199,160,69,751,730,747,473,696,605,7,32,773,187,118,303,64,781,418,479,635,727,610,595,843,919,850,569,113,999,472,193,40,615,264,537,828,925,861,617,101,728,62,420,745,214,177,731,930,622,164,498,879,81,926,437,116,83,261,88,196,236,330,524,901,82,177,925,531,855,965,947,161,91,127,198,814,315,353,832,808,0,708,164,420,409,99,253,631,750,630,177,22,740,669,288,277,915,804,817,980,278,625,49,374,777,572,488,667,108,224,142,871,111,332,741,801,16,574,412,48,704,382,33,951,789,584,576,226,172,933,525,341,638,694,167,280,606,888,529,916,915,576,126,609,335,226,50,828,166,105,670,116,657,839,822,921,628,84,540,705,611,242,754,486,896,796,515,590,30,647,333,711,259,219,804,465,206,162,668,739,152,197,863,784,727,194,719,211,99,955,339,551,312,136,654,706,725,120,272,828,236,404,412,821,321,600,374,687,469,769,99,672,352,725,256,168,653,376,963,342,423,533,948,139,497,702,345,750,285,282,332,667,514,960,854,254,23,840,766,787,634,223,216,892,47,166,200,728,997,187,800,548,121,718,527,10,613,976,975,212,877,862,485,650,727,175,427,11,373,527,147,438,490,383,441,296,397,620,485,636,2,681,387,401,241,734,761,545,555,782,591,729,34,663,616,263,636,382,295,394,20,672,402,53,762,366,299,364,468,430,78,551,785,510,788,52,424,128,931,637,592,896,573,25,888,271,90,220,598,670,937,929,583,646,655,475,920,431,701,136,981,68,822,708,816,668,693,220,561,297,352,402,739,613,35,604,35,154,738,229,443,404,821,163,506,956,611,207,798,450,873,93,829,347,860,752,190,595,978,339,557,496,973,113,889,381,624,292,262,884,191,678,828,187,93,362,829,592,203,885,542,376,4,942,836,724,190,21,776,409,24,9,223,935,252,634,653,532,170,908,869,940,856,11,135,690,742,897,742,754,726,48,837,222,133,782,599,287,4,857,346,998,331,30,318,128,824,857,24,262,204,976,915,932,304,26,956,414,622,288,123,114,314,294,539,516,342,642,280,68,569,710,685,203,449,856,508,794,709,661,378,317,469,778,547,34,788,235,659,392,706,485,61,728,296,417,797,108,759,96,424,82,861,648,443,903,53,411,664,266,553,835,380,845,684,482,649,992,493,568,431,403,770,874,373,926,402,530,568,999,549,660,171,319,973,505,274,60,36,691,183,420,807,294,24,630,44,956,33,447,392,916,611,209,431,484,334,574,224,935,158,705,101,981,225,357,660,767,844,301,975,204,211,222,525,42,114,443,2,117,6,159,134,636,365,455,591,164,275,95,126,234,885,798,95,860,610,389,640,237,729,433,699,617,515,368,22,456,821,959,657,899,914,683,447,270,318,203,461,795,721,571,410,556,100,957,9,404,666,105,421,842,297,291,398,858,683,458,571,824,359,959,446,249,742,519,710,923,401,661,217,280,493,119,876,630,609,258,395,931,29,443,846,263,848,738,452,373,821,337,829,156,985,948,833,275,783,560,512,931,129,988,715,607,194,857,214,774,253,748,87,283,686,840,888,908,886,110,444,587", + "685,986,901,25,257,967,819,43,104,826,426,126,137,844,479,931,358,111,447,550,194,34,835,165,919,936,708,860,983,40,271,619,796,694,808,2,666,475,248,862,185,992,735,629,204,827,393,66,303,575,656,333,212,819,532,61,372,703,177,440,947,753,252,809,154,225,600,657,694,560,160,755,861,247,603,723,269,472,932,826,623,788,593,341,74,113,662,357,154,779,978,711,966,163,248,250,169,267,144,755,947,285,243,471,766,346,442,519,429,664,890,856,910,228,915,310,653,116,436,660,816,959,333,936,146,246,167,124,52,121,374,749,341,147,343,826,158,484,702,218,213,103,743,684,167,298,529,59,332,824,253,229,558,483,964,417,705,656,134,641,931,823,275,791,7,639,929,4,794,381,201,911,367,925,179,874,424,583,897,621,66,838,158,694,187,941,860,676,965,620,786,882,196,359,507,807,620,943,850,25,346,649,871,751,387,16,132,957,716,889,725,815,277,378,844,505,990,736,303,78,675,89,39,303,109,231,41,671,856,304,4,671,533,40,299,798,772,87,90,679,786,578,953,887,107,590,9,448,823,453,650,394,82,887,33,145,875,406,997,906,936,683,129,304,428,979,198,401,983,181,288,939,409,342,359,465,376,505,950,527,869,616,406,588,427,820,259,719,831,642,132,333,174,700,188,585,153,36,739,246,94,213,369,714,804,609,317,33,484,331,991,842,978,470,175,320,16,563,170,140,405,928,82,951,803,824,751,111,934,136,227,409,379,529,244,132,721,854,541,736,341,342,663,687,630,913,908,440,873,964,53,777,327,827,145,96,872,324,221,477,247,555,250,294,479,272,463,295,401,33,631,112,433,11,131,167,376,627,802,114,708,0,749,561,681,455,970,836,584,84,272,456,738,40,181,765,899,246,142,49,721,214,313,810,93,854,87,74,760,225,463,320,108,590,685,711,257,256,405,51,566,198,180,568,740,544,683,836,231,914,85,548,623,881,435,314,383,361,625,767,870,207,390,340,332,900,214,514,287,898,42,965,849,65,525,435,647,523,862,238,411,298,472,657,824,508,771,912,681,894,250,249,815,191,935,579,948,948,569,338,265,238,94,97,724,878,444,509,876,994,835,920,293,758,603,361,841,790,432,544,57,734,225,574,44,884,205,171,459,912,287,136,836,857,9,969,941,789,405,609,549,585,706,213,369,9,703,627,800,702,486,399,492,499,985,274,402,744,964,658,487,896,685,970,1000,163,536,53,438,376,587,531,807,915,446,747,721,894,20,157,125,719,20,199,237,620,568,503,235,707,631,71,490,42,965,907,552,328,484,530,653,333,409,260,855,243,37,562,153,277,297,938,340,467,89,718,561,81,469,586,168,773,211,676,285,6,703,523,903,427,251,430,379,469,213,829,540,479,53,793,82,675,338,308,674,92,768,636,50,551,539,802,285,600,697,867,162,462,91,376,258,734,674,432,348,550,154,994,432,759,523,490,206,634,460,790,674,149,13,392,52,409,591,85,113,623,198,278,141,571,271,933,709,399,124,69,137,169,296,999,645,147,16,484,527,259,754,356,775,787,60,989,968,762,530,912,717,126,204,609,230,546,734,645,449,878,922,643,682,660,768,266,531,370,268,75,440,335,498,303,511,77,428,369,568,190,591,863,448,464,771,559,939,290,86,237,775,771,153,571,541,531,907,722,13,511,613,836,787,220,744,583,361,328,928,197,226,550,810,195,316,738,773,416,372,529,805,453,17,286,84,796,989,869,624,359,98,650,651,773,467,762,657,942,628,505,363,986,41,814,608,453,509,968,404,352,594,903,442,953,34,112,545,12,653,475,837,166,216,688,243,452,20,751,609,390,14,941,312,315,165,197,775,553,625,707,248,654,495,101,522,208,996,531,156,812,505,408,832,814,459,52,112,887,460,735,248,606,694,229,644,494,95,173,601,91,581,770,360,53,796,194,847,450,302,601,298,83,503,385,191,67,952,511,589,536,374,427,278,322,994,666,890,751,303,301,245,652,23,434,724,438,447,5,685,654,25,92,785,37,20,823,656,676,180,789,50,450,562,609,729,278,462,196,36,171,193,995,13,279,826,841,422,508,195,526,159,971,704,621,772,454,463,452,695,583,108,84,987,418,312,962,684,781,494,157,449,240,806,972,987,223,286,54,534,255,417,36,360,572,816,88,5,706,576,672,326,345,897,357,290,116,757,713,736,690,590,305,925,468,201,615,139,424,375,851,646,614,87,345,20,580,631,796,237,561,223,935,78,699", + "686,829,538,587,935,221,521,765,673,430,487,765,683,217,163,228,670,329,152,841,973,349,523,314,304,712,517,297,291,996,332,490,490,421,496,459,102,451,268,975,70,105,638,286,228,800,182,992,359,927,93,636,334,132,194,797,785,282,524,156,249,864,58,167,39,422,941,537,44,81,964,539,602,427,643,663,812,599,729,619,626,995,428,546,93,852,898,645,273,474,169,946,733,982,393,357,132,459,654,58,407,808,134,879,131,768,493,349,437,26,91,11,109,574,692,361,247,268,232,335,380,416,738,606,754,658,935,28,102,477,755,829,980,367,690,671,970,727,278,631,253,834,896,316,154,21,341,53,420,955,668,660,931,594,890,881,983,578,302,874,502,229,19,563,145,828,461,670,986,855,582,502,192,521,129,471,218,674,603,742,94,442,671,802,523,467,818,617,963,597,763,886,137,515,944,620,340,332,36,225,706,503,235,795,557,278,793,233,583,263,385,138,812,756,990,11,222,26,178,268,258,297,458,960,539,139,459,624,577,671,362,126,311,337,961,970,216,377,258,663,388,315,568,69,970,154,69,644,83,530,888,389,944,846,402,331,105,962,473,102,117,411,194,815,375,87,25,940,980,987,510,917,502,765,139,794,620,652,980,784,794,80,393,550,465,703,222,71,358,538,509,1,913,28,135,77,471,386,306,392,921,186,635,182,959,289,595,497,901,644,316,245,766,127,851,391,74,448,246,143,434,110,206,81,137,338,603,816,137,356,86,431,348,28,455,416,308,114,142,626,159,11,379,287,220,819,890,560,800,15,986,702,81,500,908,336,562,190,87,613,127,652,947,612,47,227,751,928,306,337,542,630,4,209,189,685,954,952,225,207,164,749,0,170,1,423,712,470,17,453,330,924,552,950,349,119,950,169,728,902,586,545,995,344,230,374,228,132,49,730,461,117,728,818,905,84,767,805,562,703,574,55,53,731,657,990,345,335,871,214,229,997,467,980,592,969,902,247,523,811,738,193,411,909,992,930,24,28,913,720,28,354,190,992,819,68,473,509,651,513,469,12,963,782,264,90,280,51,749,778,920,84,409,584,730,841,270,140,349,865,462,42,674,727,494,581,303,52,359,157,453,955,493,738,602,445,117,799,925,248,689,447,978,258,115,211,499,349,139,366,742,151,343,141,183,226,818,458,968,379,455,29,440,274,725,198,22,675,441,626,216,521,25,606,901,907,942,729,583,418,142,800,469,42,945,197,581,848,137,366,656,914,471,397,736,545,257,648,815,942,941,883,436,74,640,113,855,259,523,140,911,415,991,399,421,13,158,598,777,475,977,440,886,459,199,966,46,889,681,987,137,150,692,168,317,195,250,846,619,660,597,603,513,442,121,701,915,792,283,611,846,85,795,642,699,544,871,487,269,186,166,122,710,603,8,326,890,996,941,139,53,659,814,537,93,463,502,157,822,346,596,424,696,459,854,741,823,479,4,585,428,775,212,216,368,492,838,6,191,482,633,439,257,519,91,175,212,606,429,382,539,431,254,96,213,874,708,14,467,94,953,704,333,347,532,899,615,137,473,367,734,814,243,970,112,801,808,830,8,979,25,271,128,941,916,352,396,382,599,459,380,317,774,12,995,694,169,249,926,237,174,363,707,418,840,69,402,242,637,136,413,375,761,454,170,248,714,729,778,278,127,585,760,358,62,887,269,245,580,976,722,232,14,977,919,47,442,687,267,846,472,895,713,912,170,822,7,424,170,218,231,370,405,335,807,106,176,576,365,395,771,824,457,468,680,476,892,721,722,309,762,351,455,965,829,762,231,525,723,211,507,91,608,874,767,720,966,90,572,353,497,173,38,661,677,417,631,294,53,855,46,441,171,336,237,462,806,250,601,800,175,329,308,949,895,4,770,119,805,872,813,998,187,918,680,933,808,958,578,661,623,150,958,83,328,764,679,988,80,434,279,234,561,650,672,326,188,330,715,172,736,792,352,217,78,737,442,583,345,724,898,797,949,129,765,190,69,976,478,822,41,746,746,400,462,527,537,727,358,47,49,763,846,684,896,687,801,270,91,457,638,85,948,105,744,185,599,368,618,962,396,937,546,450,122,202,51,677,296,638,600,338,972,998,404,692,468,966,578,74,775,452,370,316,74,362,245,478,363,251,252,252,664,790,983,576,901,293,509,371,524,672,528,704,488,222,374,30,764,273,577,974,340,606,905,251,134,538,11,85,869,348,450,703,788,573,968,96,459,485,106,336,940,751,368,538,529,23,999,702", + "98,680,930,780,245,16,605,652,92,288,26,160,450,152,73,133,409,895,629,386,865,945,826,695,919,345,69,714,16,835,303,12,912,100,215,88,160,130,915,238,584,250,883,772,170,151,551,149,116,770,383,344,808,183,732,272,999,48,580,34,764,159,460,289,321,306,245,165,139,248,728,705,596,192,185,476,912,453,475,957,623,277,207,552,125,66,737,680,865,88,306,940,594,325,135,603,212,166,60,299,928,477,776,291,671,36,573,342,883,617,409,615,343,637,819,812,186,917,251,382,52,994,691,63,97,663,503,948,881,355,486,474,411,37,483,467,840,942,663,660,767,459,194,616,899,509,512,86,548,376,691,968,103,932,565,448,161,857,401,237,791,25,192,173,166,687,201,998,99,900,883,595,219,7,728,975,439,584,392,725,357,272,143,551,19,508,438,762,604,369,263,66,880,962,869,769,9,951,42,184,44,846,484,3,785,722,675,597,594,748,257,975,970,69,376,607,785,650,559,649,480,158,292,367,664,854,56,175,218,647,451,532,3,250,873,38,668,564,874,751,451,376,742,651,948,195,680,604,436,216,41,335,292,431,99,324,923,27,276,795,155,59,566,374,50,324,961,183,696,227,746,388,727,157,171,369,388,262,954,202,62,261,105,110,341,715,960,476,17,79,143,73,948,999,375,282,468,225,618,937,517,33,892,395,114,217,469,664,924,362,506,88,859,185,368,742,918,635,481,107,689,108,20,536,520,349,85,879,535,237,960,5,754,639,618,196,927,333,315,790,698,471,54,916,427,9,488,969,949,180,153,148,492,380,626,141,582,576,266,694,994,402,279,203,231,857,339,663,566,297,410,224,642,199,703,806,315,879,667,395,420,561,170,0,695,201,204,129,339,659,329,857,417,996,830,713,219,31,939,853,348,941,93,782,303,293,333,79,921,41,228,486,78,673,643,366,308,682,497,574,954,788,617,532,273,701,269,900,860,871,340,128,20,347,22,137,419,412,919,493,46,786,263,21,313,352,38,23,638,562,565,748,685,310,952,932,869,251,352,475,918,739,213,868,523,18,997,920,949,150,333,236,84,41,952,479,630,266,607,638,89,297,367,268,815,928,655,342,809,338,620,743,888,82,407,880,525,403,396,958,997,792,850,881,299,905,331,969,970,487,197,494,367,23,248,562,105,61,617,308,745,218,212,514,8,763,196,438,280,49,411,782,829,848,727,839,976,16,277,824,793,685,578,772,647,953,45,25,113,3,533,898,7,902,909,392,488,399,640,249,443,117,601,505,126,653,784,169,613,229,1000,36,724,56,446,725,258,623,445,189,591,798,118,418,56,781,151,411,59,103,241,701,389,802,210,173,777,48,606,146,3,731,798,94,456,78,288,22,254,539,649,92,470,828,29,454,647,558,942,661,401,907,60,34,372,903,299,495,514,472,808,729,313,208,913,191,577,736,953,634,494,285,119,422,455,317,622,935,930,509,267,638,931,780,880,982,448,91,994,737,153,995,158,507,2,521,904,887,977,201,671,844,484,806,942,753,354,304,95,926,647,52,330,824,509,928,886,932,704,400,550,54,716,261,45,541,486,260,523,855,482,839,158,834,968,851,413,955,401,412,173,791,189,842,657,17,844,341,762,595,127,197,351,425,602,182,277,419,846,805,663,509,974,164,602,91,424,656,168,954,920,486,235,876,221,57,226,465,745,818,64,237,613,493,163,164,449,883,136,293,431,821,980,158,853,281,98,387,953,539,942,29,868,188,785,980,944,531,490,650,246,758,19,791,795,663,220,194,886,563,103,875,616,707,506,479,871,696,246,460,740,564,811,674,957,515,140,381,778,545,264,876,223,170,785,457,441,940,233,314,563,626,712,56,867,464,411,366,914,682,955,863,72,640,289,404,144,591,578,771,556,2,98,254,95,740,34,92,475,667,437,338,901,470,575,527,815,203,948,85,669,6,619,826,770,44,211,345,368,67,21,384,114,994,889,739,848,419,460,571,148,743,284,55,692,203,402,374,907,603,92,715,371,483,777,678,50,657,571,433,760,627,530,101,15,682,46,845,554,534,703,456,731,135,816,159,105,341,263,62,546,946,38,993,626,559,289,183,78,658,470,360,414,37,237,816,80,570,895,636,894,676,647,783,552,378,210,739,278,888,486,355,901,17,925,680,235,504,699,812,918,508,895,433,542,724,359,820,599,711,909,160,799,192,632,971,158,74,424,551,815,624,441,639,645,216,791,282,546,586,825,64,260,604,133,650,70,726,256,220", + "902,587,299,924,552,131,886,81,234,898,374,710,148,464,322,632,287,621,771,440,313,265,582,13,373,763,224,799,776,153,320,545,744,196,446,943,8,314,37,397,812,78,917,740,611,226,57,237,657,619,121,782,798,550,101,519,536,846,441,650,4,412,996,383,111,106,376,809,585,438,687,691,664,820,105,944,601,236,89,787,265,933,887,452,435,358,577,108,76,65,873,458,204,911,536,738,423,993,805,380,551,466,387,487,899,957,857,75,719,140,287,86,618,798,588,925,326,900,35,124,60,630,424,386,641,602,953,601,606,635,731,297,782,658,927,117,336,669,222,142,485,973,793,697,886,233,286,423,217,840,851,70,300,388,826,381,875,405,99,171,567,709,762,796,502,766,281,466,40,157,865,79,300,603,306,964,422,602,115,51,319,884,601,616,269,950,209,878,718,528,723,144,23,99,204,998,54,808,409,956,727,417,243,517,107,490,916,856,531,281,659,350,626,570,884,728,137,142,19,331,633,149,176,583,753,975,855,773,280,599,225,635,845,860,561,592,319,512,355,155,910,455,899,551,271,607,533,312,764,725,863,496,711,472,466,102,980,877,809,848,826,970,262,325,906,186,460,962,447,857,680,390,989,869,435,886,415,288,683,183,895,389,880,773,260,748,946,694,577,800,771,700,905,140,956,872,341,140,127,847,570,440,419,544,753,498,837,404,703,110,271,286,78,686,470,563,862,74,519,111,609,143,594,364,139,869,728,667,373,779,984,537,735,137,313,36,259,524,137,984,23,553,635,404,352,218,335,344,369,427,207,63,81,437,869,915,35,307,657,20,231,628,743,17,736,112,685,24,526,894,55,382,430,326,18,36,273,947,552,95,409,681,1,695,0,490,706,683,184,435,357,267,60,471,612,324,612,627,842,459,594,610,381,362,20,672,547,573,642,473,31,572,432,474,260,827,54,398,487,766,437,836,819,215,599,964,90,685,750,833,698,850,302,831,168,668,974,198,363,538,694,225,320,36,698,500,614,972,115,659,545,127,664,653,595,504,829,221,378,82,956,202,241,249,858,979,237,726,90,497,755,351,358,902,329,992,813,486,432,784,162,899,493,432,842,566,872,347,630,126,375,627,803,465,898,405,352,699,254,838,663,413,906,959,922,821,646,566,79,241,909,531,268,941,863,772,653,243,901,609,134,97,61,906,681,426,344,97,158,43,775,311,397,801,561,757,795,413,719,444,484,947,59,455,405,309,830,347,909,259,994,235,526,358,97,400,40,711,789,485,540,315,148,826,682,748,47,418,679,619,911,687,524,64,406,903,896,868,810,574,971,745,920,162,226,495,18,228,695,423,337,779,102,816,519,610,29,835,503,200,743,51,878,892,112,166,355,465,174,413,106,671,236,874,64,736,322,661,620,612,98,394,611,244,686,240,47,895,859,971,342,824,378,865,893,219,725,253,845,256,385,953,590,46,629,25,852,810,30,116,125,83,792,54,91,957,702,813,447,208,283,851,643,262,200,551,963,861,293,475,262,208,741,644,543,709,138,513,967,372,437,244,280,595,787,550,507,83,570,545,960,862,499,391,20,277,131,396,254,116,254,616,313,838,946,101,403,474,863,714,14,428,391,26,354,367,267,639,553,95,337,872,308,445,799,983,795,935,591,541,58,693,927,232,684,159,125,252,82,511,990,704,633,682,350,919,471,797,592,605,692,111,222,730,975,864,766,199,959,395,193,197,565,739,824,441,195,682,286,142,348,915,396,478,831,263,519,204,451,530,28,865,817,869,400,757,507,818,406,787,460,320,44,466,184,465,274,405,936,804,850,833,263,681,499,56,912,237,347,392,933,795,392,925,349,682,5,446,629,832,755,845,384,157,472,126,343,382,214,763,973,841,875,89,767,164,3,217,531,801,329,409,813,161,729,827,186,304,387,940,771,838,345,977,972,130,556,845,208,478,268,684,188,154,430,103,789,499,313,967,976,487,80,968,888,970,499,363,27,605,238,648,735,748,435,519,917,137,691,833,832,334,964,621,768,429,347,544,30,115,88,266,851,156,232,405,774,686,871,881,408,666,156,494,448,582,378,755,40,157,75,566,897,544,918,135,698,941,799,652,602,279,545,656,78,315,342,814,574,680,914,394,333,737,850,927,538,182,400,915,667,340,379,798,110,517,792,517,936,609,557,651,506,779,27,157,98,686,278,176,315,92,18,492,457,981,719,727,775,576,851,157,756,49,369,218,442,423,816,927,683,140,323,859,853,817,302,393,696,394", + "725,336,181,897,766,72,353,518,454,467,839,299,161,967,2,785,352,944,586,750,270,95,816,785,326,234,193,871,805,746,323,165,391,561,204,291,833,923,592,47,282,375,144,899,683,335,125,16,231,671,318,119,723,843,385,38,702,627,682,205,835,322,697,68,227,600,663,7,217,172,948,328,295,272,295,858,417,231,568,984,23,43,292,60,358,831,22,47,837,385,304,241,714,257,473,812,300,648,673,580,827,93,74,767,776,279,6,207,51,590,413,761,728,662,75,855,896,690,654,408,566,112,821,49,751,83,470,158,344,540,213,320,368,207,225,609,182,977,298,442,447,865,314,182,721,148,929,425,137,740,53,530,586,297,946,755,922,536,303,786,919,768,862,411,980,760,936,911,30,725,736,392,163,530,956,171,466,715,73,627,261,322,668,477,817,660,899,390,814,326,358,356,827,760,84,385,933,831,330,372,477,540,318,988,869,823,230,444,298,192,640,474,440,231,565,506,676,338,943,442,546,143,398,373,493,400,658,818,805,239,529,590,963,639,745,776,343,666,6,118,265,105,685,696,371,779,417,470,452,292,49,595,429,248,76,189,965,601,275,240,42,925,643,575,963,554,771,417,882,743,36,820,6,985,806,286,210,224,669,25,730,972,199,558,502,224,474,726,75,596,897,342,975,453,184,270,437,672,185,79,894,301,754,386,888,743,645,105,458,69,465,825,133,29,462,409,87,726,613,216,541,694,296,727,97,273,322,280,166,693,396,734,434,9,632,358,216,742,852,908,774,983,276,298,745,78,479,778,911,707,876,498,706,937,690,190,822,165,540,442,676,151,499,28,277,459,915,364,996,200,171,558,817,888,392,695,399,298,577,82,99,455,423,201,490,0,737,551,584,320,98,120,322,575,858,700,161,817,754,255,483,705,668,555,962,370,587,851,263,294,276,685,928,670,56,239,922,410,942,833,186,589,544,39,131,184,963,341,204,426,251,748,842,592,433,515,504,475,946,290,459,195,324,165,592,534,277,890,443,601,748,890,411,602,489,152,5,799,739,87,279,973,844,358,129,697,825,117,124,361,950,883,529,240,577,775,681,81,61,39,305,796,113,641,236,409,673,175,250,597,596,592,942,259,522,5,798,199,945,831,144,39,485,85,227,558,684,609,585,913,971,689,103,661,89,162,410,205,792,511,608,564,536,130,73,762,18,955,354,629,440,273,62,754,816,304,175,360,734,733,256,158,19,244,193,812,754,757,515,78,713,25,557,643,531,206,638,400,677,159,101,929,688,923,268,802,245,19,675,533,619,665,270,146,508,551,24,798,510,626,677,173,291,654,623,250,840,863,185,70,777,20,61,542,917,97,257,101,995,37,507,389,71,985,254,396,88,180,625,220,312,958,358,607,750,769,352,780,688,31,700,326,348,212,195,853,338,861,727,966,823,864,780,951,334,266,204,307,151,921,465,156,390,8,912,937,551,45,362,156,722,797,430,212,957,420,136,660,556,36,552,346,936,527,953,441,654,399,230,988,333,63,528,241,989,824,288,784,100,34,624,74,471,559,450,684,185,138,563,613,649,596,933,209,499,641,60,170,489,567,111,253,615,286,872,161,275,488,890,358,739,367,673,823,301,759,553,226,821,968,922,550,429,936,889,243,663,65,557,518,635,473,752,778,89,236,941,237,305,4,410,361,137,250,456,227,81,23,194,29,266,810,607,217,878,317,497,335,778,60,241,679,543,9,705,230,934,803,943,139,774,155,893,703,273,521,195,456,449,483,694,737,453,351,831,616,486,769,166,731,498,495,192,239,471,17,287,817,561,524,423,415,433,454,398,77,978,166,239,62,883,72,115,682,800,934,854,173,758,519,889,320,385,512,453,520,186,373,264,834,109,868,775,367,216,871,251,827,469,628,369,501,192,749,441,32,262,879,66,991,896,23,257,943,353,898,5,426,188,452,136,14,914,43,256,330,634,287,803,654,94,533,128,156,348,991,242,357,521,732,608,481,642,670,648,694,992,364,177,79,894,872,670,838,841,406,595,555,878,458,528,376,824,636,811,108,914,966,373,14,280,436,58,7,618,275,534,935,380,517,992,492,139,910,631,809,970,861,478,6,357,442,685,796,416,824,967,249,859,235,389,781,839,790,450,839,359,198,324,874,494,893,313,885,183,73,602,308,497,195,798,398,202,772,252,900,400,89,269,117,202,689,474,516,168,569,927,36,498,364,688,605,600,199,642,729,212,309,427,270,38,379,42,671,493,210,86,850,482,838", + "707,182,886,532,465,635,937,314,653,637,319,41,608,55,176,648,482,125,353,517,570,235,981,294,845,345,625,621,49,713,813,42,248,36,532,774,792,657,510,422,510,811,515,676,510,884,933,183,618,733,980,80,456,888,425,509,871,141,165,982,48,543,329,236,67,603,186,599,750,787,205,670,555,771,870,611,787,801,599,413,318,942,401,63,456,600,378,534,689,387,96,131,187,198,117,198,307,109,335,822,849,157,419,252,84,406,536,136,660,770,190,126,623,218,917,126,45,217,340,889,765,657,537,50,199,120,166,711,901,326,511,339,862,230,757,777,547,746,997,161,975,524,708,305,986,997,592,820,955,489,174,184,837,892,967,246,492,344,189,920,173,266,763,17,485,691,967,976,121,690,729,139,643,204,604,776,784,260,824,583,140,404,199,305,556,254,999,670,290,798,210,334,76,358,377,725,178,946,915,59,631,431,496,427,377,485,724,400,118,152,149,158,587,123,854,585,260,552,668,733,692,227,780,888,278,501,130,434,882,693,771,560,978,768,312,724,220,669,847,159,562,699,783,303,178,91,16,909,897,545,332,467,913,43,470,218,174,956,818,338,595,691,860,278,191,194,418,319,204,884,728,977,978,686,338,847,808,504,874,516,679,144,761,991,779,868,874,249,207,494,404,851,456,491,172,253,646,188,365,858,882,581,361,979,798,536,474,699,806,727,712,193,394,49,803,726,505,301,719,14,928,278,428,854,454,607,58,643,52,371,689,184,440,510,641,138,825,850,234,590,897,543,73,255,225,942,129,862,396,594,875,810,19,436,891,525,26,205,765,693,640,655,99,131,369,811,214,366,13,511,135,235,567,865,579,319,241,509,913,47,253,970,712,204,706,737,0,960,852,701,593,538,927,491,27,396,951,111,406,870,806,929,937,16,161,151,82,339,671,657,350,617,243,910,863,741,129,293,395,33,460,291,387,620,226,350,284,605,534,617,656,422,419,467,830,993,866,39,321,727,130,725,776,140,8,654,828,67,650,42,936,96,570,976,461,926,18,376,303,469,130,166,17,45,883,719,711,525,317,928,203,641,855,498,957,578,269,690,113,858,306,707,301,281,516,690,910,320,424,791,452,290,910,931,572,327,785,689,581,557,554,779,366,600,692,760,916,587,733,113,737,123,894,977,442,389,993,249,457,557,29,800,416,612,571,467,50,269,309,686,31,573,558,918,185,351,43,140,846,333,67,656,38,161,924,407,535,955,185,154,408,855,853,836,278,490,296,760,9,419,809,786,439,303,101,117,449,16,310,841,678,858,47,645,925,620,812,565,454,64,659,122,142,495,597,963,483,518,462,880,222,201,671,502,510,237,602,665,392,309,621,199,647,800,996,772,594,56,675,611,641,284,197,754,203,827,354,64,334,424,273,417,429,327,330,540,750,819,731,232,831,970,192,445,551,564,951,861,347,238,227,487,510,989,313,258,414,9,181,296,364,641,950,566,73,967,28,940,124,935,745,939,895,34,421,80,228,414,293,112,113,748,2,284,709,998,677,470,430,866,814,855,519,666,365,568,964,400,158,24,314,906,581,220,711,111,401,928,661,972,775,618,504,534,105,966,617,483,144,492,787,266,557,11,978,221,551,666,773,454,889,363,706,997,617,813,921,677,726,214,121,865,110,675,94,672,824,122,791,289,253,902,400,490,109,170,123,490,298,993,197,139,445,22,586,982,678,77,847,390,614,118,30,858,42,902,24,980,220,398,867,728,402,926,391,88,912,106,2,528,874,981,865,949,618,634,934,228,500,4,413,680,474,537,771,769,732,732,231,681,167,265,487,685,508,867,687,352,564,53,241,956,624,786,596,935,530,85,17,942,736,353,11,467,433,692,954,473,259,258,949,92,993,203,609,943,109,779,635,95,697,311,658,853,899,928,91,407,851,451,505,613,649,152,436,392,285,81,181,859,201,728,515,907,270,254,989,324,6,333,749,660,94,311,568,616,275,546,18,700,672,938,28,739,60,182,217,644,947,817,948,893,832,959,49,789,296,48,247,146,847,91,773,465,664,916,56,72,282,292,716,180,352,808,623,753,563,727,798,731,583,753,858,888,158,982,859,683,768,308,595,484,457,37,883,561,636,898,501,693,514,659,707,605,572,800,928,675,83,28,755,270,63,852,223,498,9,420,400,586,576,743,514,569,816,31,927,709,938,837,508,731,738,978,827,549,844,313,218,700,498,947,849,87,478,397,853,58,383,760,597,666,839,844,773,7,356,342,607,526", + "758,909,162,749,922,394,657,145,442,462,795,656,698,64,939,519,85,324,309,242,671,216,518,734,422,798,951,451,715,705,550,174,535,928,127,639,834,839,201,735,389,706,948,382,364,395,753,475,343,304,832,491,114,928,564,110,560,327,378,338,563,812,250,96,366,199,320,872,179,27,208,720,729,396,68,169,436,921,539,977,797,862,88,29,815,392,848,678,796,696,81,148,993,537,78,735,623,442,545,656,596,634,180,950,450,857,958,802,915,266,925,920,87,277,611,840,386,360,378,265,626,807,263,238,675,367,316,382,741,340,522,59,979,108,479,509,380,756,51,575,910,604,803,535,206,56,745,469,605,296,66,845,138,127,328,598,783,110,428,263,309,700,945,152,360,135,620,777,922,313,638,933,379,467,93,929,417,540,967,416,498,894,619,537,716,929,324,451,934,385,92,806,305,647,782,493,90,589,843,158,453,237,727,300,205,830,288,322,55,203,524,166,756,596,726,420,808,103,932,856,580,419,321,560,613,210,998,354,299,851,665,663,109,511,53,478,738,591,177,637,206,645,260,664,451,993,192,393,770,534,484,351,887,142,981,679,208,807,677,845,248,738,346,29,311,13,782,420,344,719,982,455,50,694,282,835,345,906,443,484,75,452,654,487,57,882,860,319,612,41,586,348,609,248,947,18,179,641,502,726,887,422,965,808,618,986,683,683,16,611,356,602,726,833,684,507,812,205,283,493,647,917,583,203,533,78,649,980,457,852,744,96,853,374,136,676,741,449,120,629,595,726,878,946,151,468,979,566,161,710,751,215,477,249,80,73,684,355,656,348,235,88,249,134,18,395,600,41,168,204,311,747,978,985,107,747,559,135,497,332,631,836,470,129,683,551,960,0,915,359,895,973,553,126,20,82,966,929,129,745,922,585,841,437,823,430,215,272,501,433,789,222,403,471,706,314,251,67,589,852,955,461,630,24,138,282,278,802,832,873,196,932,235,904,115,528,924,807,517,244,181,484,965,123,193,420,252,128,254,87,329,29,268,434,137,214,965,77,686,357,74,414,692,143,246,252,838,191,401,238,623,884,600,75,612,798,660,413,631,208,147,667,366,935,255,596,92,482,309,648,22,11,344,880,381,281,891,501,385,208,699,119,904,873,976,825,640,276,847,144,782,247,666,535,444,41,410,503,140,929,626,73,282,528,64,520,2,240,750,496,363,860,412,564,749,974,479,538,618,495,289,285,692,792,190,900,892,728,693,177,355,810,245,282,294,952,794,222,68,531,353,843,150,104,972,958,695,529,346,681,272,936,7,964,242,72,865,443,194,610,936,407,182,223,309,735,442,610,605,165,608,399,949,81,974,331,530,106,716,387,526,685,609,926,371,262,80,671,836,343,214,231,502,642,328,97,380,667,210,311,476,764,579,279,617,224,365,198,291,313,322,65,352,675,193,928,664,804,239,711,755,183,247,659,696,919,663,949,908,131,715,775,514,448,7,578,876,59,760,751,864,894,908,40,305,417,884,244,498,998,404,574,401,619,195,231,750,814,124,914,566,717,322,624,956,855,588,5,80,953,689,471,312,86,923,597,48,525,281,484,257,613,358,112,494,595,11,158,813,889,325,615,37,937,711,850,323,233,163,816,285,106,498,138,819,527,923,113,270,233,573,393,419,461,811,308,802,25,497,804,835,333,819,263,105,2,362,626,336,72,732,783,493,423,440,881,1,843,423,692,916,575,770,110,265,117,572,776,278,91,37,140,899,878,371,638,472,187,688,49,546,972,272,101,429,115,394,613,743,499,276,11,933,146,978,196,204,549,437,460,557,862,517,669,145,641,524,818,932,949,91,16,601,223,957,76,535,812,721,808,624,159,260,634,934,136,826,79,19,683,510,450,845,154,22,680,218,759,521,707,435,92,539,264,892,337,35,892,142,382,188,786,26,910,881,549,199,645,368,822,974,652,251,395,783,139,226,476,199,266,490,740,37,456,641,963,28,36,121,904,731,344,931,636,475,935,15,327,660,894,554,386,384,695,702,821,302,17,529,732,362,38,102,588,322,964,886,332,725,200,131,656,268,943,182,657,372,914,132,997,171,740,968,658,363,389,434,104,746,604,30,290,744,305,658,198,976,446,113,403,503,83,407,131,261,354,662,428,277,782,165,333,782,328,83,255,477,408,75,654,575,624,83,228,550,63,904,177,975,101,195,391,10,746,6,556,508,743,146,856,356,874,827,332,677,369,674,189,598,575,581,794,202,834,589,948,749,893,86,560", + "194,196,473,460,650,389,340,923,939,179,63,592,61,537,292,330,328,370,421,716,352,447,548,579,864,194,54,937,639,855,234,67,864,462,642,914,503,580,432,51,663,200,643,495,637,86,268,41,645,623,441,360,153,237,511,845,13,833,882,947,574,990,906,552,462,808,318,453,799,903,745,460,258,246,600,871,7,159,855,459,61,754,258,540,985,793,110,531,74,191,463,164,755,416,361,759,287,5,448,917,430,619,204,856,183,57,902,813,795,320,59,184,941,355,819,43,439,37,614,123,405,894,414,609,491,324,510,853,297,865,913,467,104,976,682,341,240,149,608,27,243,795,558,287,47,598,968,494,697,807,719,473,109,915,585,523,458,883,583,256,531,590,658,878,469,135,693,498,276,836,930,730,774,994,42,636,454,576,922,97,3,845,295,681,640,882,799,859,656,258,747,560,468,913,898,207,117,768,317,273,558,347,346,612,392,126,560,274,288,848,799,345,775,61,377,761,526,123,674,325,757,80,922,505,894,30,373,284,730,428,438,157,344,779,937,78,19,228,241,818,169,390,567,535,238,94,666,459,819,263,243,154,55,921,798,239,301,546,911,952,271,482,595,319,124,492,876,58,314,724,723,934,833,345,2,41,344,124,599,487,500,17,520,862,316,294,719,1,838,47,399,712,47,80,583,815,208,227,361,529,427,506,261,466,2,401,445,783,616,906,197,477,838,948,186,835,582,554,945,549,562,333,686,92,837,823,365,289,779,620,115,981,886,599,280,875,796,829,404,739,682,952,215,580,504,858,208,346,737,118,101,884,702,508,761,404,673,446,910,802,209,228,242,775,806,625,457,829,520,502,865,805,688,468,913,687,830,10,564,462,750,584,17,339,184,584,852,915,0,965,819,308,25,120,838,40,182,317,258,686,767,103,897,400,229,291,899,630,40,133,590,546,459,405,735,574,645,241,507,873,50,449,390,54,307,701,763,251,931,447,125,512,403,646,288,886,902,208,370,944,60,750,42,723,370,835,635,123,144,983,659,743,132,179,636,659,789,148,833,557,968,77,124,441,766,784,276,74,320,655,436,113,785,2,169,490,641,160,383,867,924,618,333,804,933,165,346,274,741,953,177,240,949,167,62,878,377,974,89,818,677,256,860,354,772,155,740,849,244,565,389,473,841,870,112,570,129,537,830,862,669,397,335,374,923,155,350,853,432,249,482,126,678,597,816,758,687,851,815,397,760,943,8,110,575,752,338,902,547,346,808,853,428,343,74,460,275,466,53,333,377,25,710,14,769,538,816,166,503,145,90,276,735,517,999,137,333,743,108,684,568,779,104,425,219,561,462,719,483,784,274,646,950,163,22,490,502,35,782,787,844,949,390,64,894,460,827,771,298,11,741,380,262,624,171,905,669,341,411,797,208,891,583,109,297,483,11,880,705,728,836,336,87,832,248,229,827,490,527,539,838,203,20,603,739,864,863,135,551,77,608,402,538,249,954,249,235,57,68,610,31,847,791,615,448,847,874,415,117,321,521,596,782,527,586,197,146,138,531,821,689,636,856,389,560,757,855,481,227,386,174,334,279,283,123,737,668,46,506,896,460,281,442,627,494,680,325,597,637,46,273,673,551,200,307,57,401,763,170,609,506,881,242,150,690,399,380,418,802,796,542,235,420,171,539,4,442,163,105,919,79,252,855,199,289,847,231,986,797,713,437,755,363,442,933,223,62,102,769,909,379,688,718,838,683,818,574,537,40,446,959,14,89,229,856,342,564,582,235,112,100,787,750,17,251,28,412,75,794,119,559,868,844,131,720,343,598,424,902,567,352,867,175,893,973,560,736,902,317,786,176,671,812,569,152,12,331,223,103,914,65,778,727,20,473,97,628,403,193,192,796,701,378,29,769,46,518,548,53,402,374,810,961,660,664,689,189,106,152,231,542,783,222,857,794,728,420,570,295,27,193,800,646,112,631,584,523,442,162,491,267,863,53,233,176,747,990,8,412,388,80,984,41,699,685,935,620,93,903,381,69,989,219,405,600,228,812,443,650,503,984,368,845,144,822,488,567,2,355,405,144,157,81,866,689,66,166,99,385,107,498,224,994,232,296,924,480,125,326,172,206,935,765,412,354,951,626,563,342,561,328,399,704,13,770,390,172,899,406,821,590,663,481,449,319,420,335,717,385,398,254,224,871,375,581,926,527,530,854,646,942,151,465,942,413,297,980,129,75,307,677,711,331,470,856,165,633,879,571,7,784,4,440,688,220,379,943,148,351,286", + "461,614,446,8,824,609,105,466,476,299,663,432,758,840,526,413,705,208,846,532,651,777,906,908,699,447,204,556,965,624,961,232,612,345,182,785,912,286,790,489,46,69,730,300,890,101,456,974,923,340,435,651,966,596,413,960,994,951,517,679,611,336,632,701,212,329,886,760,934,332,374,626,673,275,395,782,53,741,734,390,380,634,923,694,589,800,766,173,869,737,104,521,340,12,78,838,386,619,46,885,590,44,526,730,951,517,808,826,436,90,337,835,509,935,304,299,566,307,333,815,135,945,556,577,277,686,304,802,778,809,118,260,685,725,988,302,345,331,656,480,684,993,771,437,987,542,287,342,968,513,611,78,553,584,437,980,711,517,135,222,992,560,499,580,509,250,62,958,833,937,791,627,370,509,929,319,273,131,852,575,655,267,533,790,834,275,407,155,25,182,21,317,646,956,75,648,615,71,778,732,643,434,622,634,806,516,960,968,382,791,101,588,135,119,885,658,244,244,934,443,212,933,804,382,80,279,882,939,380,758,406,749,631,862,406,302,841,652,709,685,330,654,945,811,375,957,679,11,567,203,274,204,485,635,556,638,62,57,871,412,333,542,181,692,190,436,340,584,68,557,27,133,774,587,700,69,732,645,906,119,246,265,894,889,845,401,644,216,534,586,367,781,624,82,16,402,272,464,697,930,748,448,971,729,503,219,755,18,263,161,477,371,800,839,578,698,380,141,720,24,122,7,224,702,755,607,798,339,904,389,415,173,325,380,641,317,95,827,607,673,365,142,305,965,84,163,487,493,270,462,326,791,715,356,944,472,529,331,134,645,768,747,679,489,155,164,801,311,103,697,799,821,176,88,951,775,665,75,945,367,630,84,453,659,435,320,701,359,965,0,678,182,459,606,97,970,987,779,657,202,554,331,912,664,488,604,871,878,187,732,27,719,99,221,481,137,790,497,534,448,716,871,152,296,651,685,884,764,772,893,486,927,665,956,149,285,394,166,70,734,791,255,836,737,787,803,667,140,763,818,698,72,354,322,370,471,469,845,564,506,536,118,464,896,251,386,644,48,289,211,528,273,999,344,500,953,229,268,298,832,521,561,685,595,496,80,869,875,707,202,887,309,997,29,815,231,588,765,87,703,708,110,254,491,68,385,262,549,82,854,431,91,331,283,809,951,917,611,518,156,614,458,883,31,195,312,5,579,38,4,967,607,27,320,753,25,869,332,591,896,749,16,237,305,808,691,38,316,210,912,522,974,121,632,66,964,728,575,699,720,952,800,607,105,206,470,380,26,781,309,315,695,55,632,895,190,353,445,416,541,45,51,221,71,873,839,804,752,216,740,572,678,414,878,299,64,145,204,675,39,392,188,268,750,107,89,77,146,149,710,174,317,785,727,525,331,282,788,693,761,706,848,949,208,971,705,150,47,229,986,124,651,441,542,278,845,902,600,531,1000,284,751,381,111,596,576,49,197,807,143,9,209,226,845,151,241,490,927,474,483,13,777,192,253,727,29,949,159,964,577,583,130,153,988,925,322,471,152,920,333,782,607,364,321,28,372,511,76,928,651,108,687,146,90,230,712,569,599,527,615,411,711,190,510,608,54,886,393,158,617,48,822,18,47,34,713,279,357,751,151,980,164,975,470,414,669,591,820,412,992,510,891,984,466,248,711,970,123,80,55,483,498,425,263,229,829,136,412,264,418,566,245,971,663,836,772,707,619,802,193,703,97,218,997,178,265,755,365,696,712,220,757,305,698,94,819,611,278,321,99,262,380,194,722,176,358,58,709,414,60,900,63,340,294,270,475,110,707,914,520,971,236,898,647,379,209,37,279,733,846,98,896,8,765,611,655,63,36,874,822,588,188,586,883,776,818,263,531,414,491,237,89,364,11,914,574,143,661,618,384,357,311,476,821,720,676,594,594,948,885,950,45,254,223,264,52,503,234,376,858,353,861,476,525,378,75,301,64,140,504,476,713,159,671,463,373,580,553,489,311,726,4,496,341,986,571,33,118,983,890,426,792,418,687,724,478,722,17,391,471,990,247,899,627,453,409,62,636,974,152,477,745,327,297,536,517,143,155,662,144,426,589,215,630,48,441,196,515,546,35,425,749,499,180,821,333,328,889,734,964,613,153,264,173,827,674,782,341,935,152,428,813,30,821,170,813,638,958,21,755,387,479,118,445,607,243,925,56,644,430,929,448,551,102,476,423,240,351,371,459,802,200,968,509,804,254,889,722,951,408,285,211,886,444,803,567,940,399,145,325", + "411,118,210,857,706,382,332,908,470,471,21,82,209,224,890,286,581,149,380,605,148,709,822,461,946,194,476,761,310,34,331,249,358,929,721,659,35,516,629,170,289,968,535,870,607,871,126,886,469,282,236,183,788,59,689,858,995,640,961,348,951,822,606,710,29,961,723,354,886,594,102,648,923,109,187,687,353,627,650,305,798,294,475,273,390,834,261,76,16,997,168,980,989,815,504,740,632,214,471,974,439,87,941,679,980,549,578,972,47,15,416,504,525,894,517,301,743,665,390,475,211,76,860,521,515,145,549,259,555,530,966,328,615,775,63,122,516,613,862,54,351,770,765,789,798,838,723,206,999,973,217,559,594,589,961,894,486,482,681,759,466,944,262,833,74,828,171,791,638,621,109,780,107,566,443,246,321,436,407,810,44,592,757,354,952,38,515,654,755,817,405,355,898,178,385,735,491,153,591,103,781,209,586,842,973,951,788,325,293,142,448,497,273,906,856,772,247,420,353,458,531,610,225,177,104,259,52,629,975,478,759,838,700,52,595,251,375,156,767,312,781,463,296,727,573,579,710,634,792,7,948,476,962,936,948,942,54,879,932,102,305,92,633,282,520,90,842,214,495,88,540,983,16,482,925,386,270,89,60,46,457,151,731,637,606,283,34,172,935,153,36,408,655,242,290,945,735,484,731,102,735,989,542,160,262,510,123,926,788,471,166,180,19,888,433,596,59,462,571,840,658,798,792,653,957,553,570,26,776,799,389,130,569,32,573,802,226,739,866,140,621,417,28,600,812,707,266,341,540,566,860,574,167,264,938,280,623,456,514,453,813,266,870,16,899,332,443,79,637,295,278,803,253,704,911,366,817,416,318,210,177,272,330,329,357,98,593,895,819,678,0,910,411,381,776,248,302,108,39,398,61,87,117,25,786,773,225,169,366,562,237,873,26,814,782,462,309,542,207,51,967,432,646,571,268,96,818,79,80,26,54,888,276,943,841,7,383,16,771,55,881,869,257,422,495,421,537,491,955,239,606,750,10,385,512,382,262,293,266,885,593,434,242,707,968,595,950,397,592,875,84,578,444,760,865,166,458,796,25,946,589,489,12,260,560,883,533,157,288,540,390,558,582,181,306,925,390,857,504,684,613,398,591,536,331,449,292,76,112,74,262,8,74,726,931,186,941,67,450,720,226,370,851,736,389,289,240,268,135,526,965,745,801,531,710,65,921,245,200,261,995,517,691,1000,684,439,222,70,247,388,205,242,231,787,830,97,444,561,814,810,689,224,851,728,772,310,602,73,806,444,980,518,402,793,861,921,115,471,942,178,3,805,322,735,451,357,771,260,93,271,971,470,332,836,724,617,529,103,165,53,856,26,347,81,111,265,482,197,707,54,878,417,751,727,588,787,309,339,845,606,775,340,126,789,833,708,481,561,38,640,372,477,400,627,385,186,890,623,563,490,671,509,504,595,54,15,541,329,567,617,942,609,475,163,965,486,895,405,999,78,411,467,971,207,914,279,767,697,784,942,350,435,635,752,978,605,755,162,148,938,831,853,222,758,30,310,715,999,823,473,370,18,72,175,429,329,298,377,54,609,940,330,389,818,586,153,20,369,421,60,454,353,589,59,208,600,967,41,402,898,277,823,417,257,695,542,622,9,808,496,995,853,818,6,891,582,69,794,672,452,264,825,140,636,391,523,358,498,853,299,814,278,923,401,884,196,485,17,489,399,996,772,943,683,581,367,760,370,291,856,142,775,574,41,727,302,5,498,611,566,900,794,755,149,115,920,277,395,788,500,217,719,705,265,195,97,721,420,501,905,28,131,239,347,710,276,521,837,296,302,715,185,448,939,548,910,860,478,190,717,957,371,227,413,512,534,637,326,358,721,598,6,581,512,945,967,689,18,609,309,16,657,607,83,95,295,273,812,621,420,478,97,40,619,485,743,926,588,70,63,979,7,197,986,51,359,132,510,220,269,16,322,541,176,398,368,513,355,101,647,894,339,680,692,307,902,987,658,262,288,393,649,696,51,562,708,169,376,739,54,397,586,310,746,323,400,413,901,785,554,240,529,320,813,657,902,554,897,181,898,457,407,915,243,674,289,293,158,223,297,799,906,81,451,181,693,610,291,670,306,498,972,845,706,53,599,929,75,688,603,88,20,788,515,454,309,704,985,40,318,596,435,780,303,464,597,198,909,38,454,535,189,367,192,249,154,566,431,406,419,489,960,561,980,82,37,330,86,90,899,122,836,542,112,950,274,864,657,471,612", + "177,198,8,632,553,805,240,757,249,503,433,387,726,791,449,932,906,966,39,532,885,757,330,736,743,323,743,381,344,877,56,203,178,670,834,465,650,329,823,340,583,49,790,554,502,366,557,424,63,725,987,270,436,921,466,254,784,80,94,251,370,626,844,97,986,187,291,785,980,50,734,782,233,974,773,354,110,377,939,533,594,363,660,816,760,686,454,602,436,758,549,892,541,193,636,877,222,402,51,263,718,421,522,184,514,187,641,463,24,53,926,34,384,16,744,515,261,314,117,613,453,362,347,938,94,994,965,433,822,480,138,937,458,893,828,563,867,913,481,547,748,554,27,667,326,149,74,841,732,50,245,839,494,993,714,607,426,405,142,684,424,569,40,381,322,831,331,524,99,337,447,375,786,979,124,963,864,515,111,299,829,471,218,793,931,259,100,600,435,980,263,822,459,621,650,806,748,185,282,754,991,55,803,36,99,891,498,584,550,848,859,359,922,378,845,251,875,440,719,94,435,259,197,109,908,982,768,911,340,388,94,219,688,508,89,192,881,909,998,191,62,436,211,375,681,989,954,998,264,49,278,76,976,327,745,510,225,139,32,947,992,38,951,656,897,965,879,922,509,941,902,362,5,601,925,231,853,535,380,376,714,593,104,10,150,17,700,637,405,485,974,466,682,691,316,283,987,503,514,233,287,841,873,118,778,463,817,282,739,973,310,795,103,633,419,807,294,735,7,608,197,337,752,683,784,642,868,680,202,956,67,299,876,506,968,729,783,314,447,394,680,110,871,31,687,567,581,233,238,417,730,371,545,416,4,741,273,458,923,260,156,366,150,61,827,853,908,676,66,453,147,194,823,47,916,592,491,352,877,426,22,456,924,857,267,120,538,973,308,182,910,0,226,340,491,414,747,655,357,89,60,646,316,340,963,288,897,732,743,397,807,865,830,649,893,916,480,852,326,636,104,893,885,315,57,477,514,579,817,826,908,59,441,923,445,688,251,848,962,820,443,518,320,445,166,756,966,737,991,102,151,292,624,304,740,90,614,834,135,288,519,907,55,206,854,814,14,986,311,822,764,962,169,499,217,323,244,961,972,461,355,772,182,716,846,470,548,285,132,598,474,558,202,228,354,645,301,29,76,707,744,850,676,153,963,436,99,151,846,355,579,556,838,421,562,400,797,527,453,991,854,844,299,228,628,447,482,565,709,455,118,698,814,402,808,178,126,355,155,991,721,348,63,796,424,182,424,509,745,190,425,335,195,325,337,535,84,453,654,327,939,808,566,478,864,947,414,667,111,890,318,793,554,839,273,875,919,41,13,91,929,616,247,444,487,74,808,853,107,968,579,588,784,658,509,151,656,384,669,933,285,603,457,670,865,549,381,650,367,307,404,681,499,273,227,855,265,372,262,532,777,131,697,43,662,341,368,683,101,562,148,22,487,323,411,498,269,291,940,633,436,248,743,315,242,942,550,194,166,97,163,57,867,316,913,654,184,127,552,543,469,839,521,110,908,251,106,325,617,304,943,573,441,975,651,551,491,315,802,305,794,403,21,196,683,871,575,603,933,349,387,36,797,748,648,51,941,536,845,326,533,627,345,55,426,585,712,760,198,401,513,543,418,10,115,369,281,695,746,856,338,704,258,269,563,358,522,547,650,796,485,168,56,840,821,615,485,851,401,954,156,86,453,206,760,84,976,911,971,64,894,86,401,469,559,584,248,939,896,21,351,917,701,842,26,897,700,675,252,195,789,622,614,120,948,573,401,185,95,122,450,314,515,439,367,836,11,498,554,648,183,316,426,952,296,792,644,619,372,249,406,956,312,552,408,58,960,656,94,759,157,822,415,657,272,175,974,718,670,612,541,715,485,457,658,33,468,826,36,43,47,727,752,81,158,285,17,276,525,866,859,275,97,425,155,173,165,753,156,544,988,52,860,166,103,667,584,793,702,826,108,126,488,541,352,589,625,123,304,443,714,258,860,849,393,462,927,472,272,463,124,46,735,207,789,25,868,753,893,107,483,476,81,665,799,459,666,530,548,427,627,123,447,356,372,503,193,914,719,153,439,282,439,791,318,820,590,326,59,218,90,4,120,318,458,953,236,709,521,115,417,95,170,488,370,48,644,886,353,363,58,517,920,654,973,300,740,896,688,418,756,79,236,320,580,811,586,104,923,918,7,942,972,81,109,314,75,399,604,724,662,819,212,184,909,200,430,338,499,729,414,699,965,90,570,691,618,336,967,275,80,919,480,149,653,719,682,235,424,826", + "912,700,431,316,75,632,945,846,130,301,777,69,580,530,596,351,680,437,82,825,996,665,350,307,841,920,687,206,358,251,594,33,613,627,31,519,764,688,67,623,851,559,308,734,3,23,891,647,701,375,548,103,786,993,681,798,751,931,388,642,769,69,337,461,741,403,986,483,255,221,653,954,356,268,891,800,93,174,360,887,374,153,440,609,371,281,532,372,792,848,498,319,430,921,599,140,299,235,466,699,449,15,931,810,240,991,460,644,525,399,821,15,822,911,847,516,177,708,975,32,659,600,517,921,214,336,267,368,246,743,573,201,895,339,428,371,854,281,549,18,699,126,481,807,981,32,168,6,442,138,455,71,312,527,354,692,531,367,29,530,783,182,17,549,355,736,749,13,459,961,227,233,17,159,529,507,781,211,35,135,461,795,585,718,498,137,121,321,35,36,760,133,465,508,728,262,947,251,926,43,230,364,95,94,231,942,995,166,570,147,927,42,966,527,323,372,614,262,450,893,504,448,202,956,349,814,292,313,915,468,72,752,149,908,102,500,208,289,79,185,798,659,441,314,145,831,631,999,865,605,26,569,514,94,79,635,450,897,600,363,70,556,77,626,88,523,12,970,582,494,563,988,595,159,750,178,917,103,869,658,52,8,346,807,448,86,246,169,873,207,685,713,932,312,944,796,880,131,432,35,107,104,48,812,370,192,983,420,353,361,918,206,729,669,200,131,375,567,968,120,823,481,892,828,81,601,763,455,866,524,935,891,887,758,473,654,721,917,709,721,736,590,75,96,505,806,380,631,8,535,241,888,93,164,186,728,358,354,947,977,216,661,886,562,892,164,770,667,103,6,528,864,69,589,269,684,308,680,832,193,740,738,552,417,60,322,927,553,25,459,411,226,0,294,879,726,251,952,687,630,536,750,226,364,692,299,33,227,730,867,733,977,958,524,662,25,338,47,585,757,531,67,611,578,12,87,967,524,734,428,949,32,794,195,355,508,14,579,215,657,577,863,557,865,197,927,18,921,459,321,285,542,841,654,291,520,937,875,939,257,72,977,566,466,968,632,349,342,508,647,45,210,388,217,187,109,862,531,277,582,270,826,233,138,556,281,999,802,863,491,866,420,522,188,939,468,193,760,358,667,496,847,906,849,575,163,724,625,912,831,226,301,797,172,87,718,875,59,306,315,685,329,936,844,694,946,461,730,142,649,268,766,441,447,255,467,773,713,215,759,69,415,616,57,614,182,358,382,133,605,253,384,987,319,514,161,920,3,418,359,461,996,667,392,924,266,863,455,669,415,763,113,30,491,75,872,772,425,407,188,391,160,642,92,960,960,756,398,830,163,197,687,906,423,790,560,329,985,499,276,747,4,390,222,533,629,37,269,279,866,912,994,49,625,273,444,637,127,443,215,273,773,399,455,741,748,549,850,387,995,840,389,678,767,753,376,513,85,129,280,435,64,172,492,589,25,966,332,959,185,785,871,988,638,990,629,520,747,405,628,590,938,639,984,820,52,477,203,493,925,20,126,434,777,431,444,63,585,242,696,379,742,616,161,677,1,587,732,302,994,216,921,604,61,689,37,431,347,557,209,662,53,330,295,305,35,803,865,770,415,333,586,169,455,30,973,110,426,804,654,400,186,546,918,59,964,13,860,509,247,134,898,961,363,769,646,918,877,493,750,200,254,236,985,16,55,865,175,2,560,863,178,580,482,823,991,83,870,313,515,937,836,978,114,414,771,547,608,245,688,504,471,64,88,58,617,135,802,359,461,355,750,972,99,16,271,184,42,611,887,673,806,981,172,340,485,610,768,792,308,187,953,822,70,99,333,345,576,547,342,526,679,776,770,209,208,11,947,724,317,566,751,437,702,576,18,985,479,111,21,423,183,798,356,935,244,574,587,221,947,856,639,440,551,329,945,984,30,130,710,609,905,247,686,750,450,697,53,767,667,796,658,246,603,519,896,946,388,172,565,798,824,819,31,199,441,106,895,970,136,70,472,153,517,936,523,803,552,89,792,776,771,62,740,58,856,966,642,157,747,329,387,606,445,371,39,64,36,202,739,806,463,942,146,380,991,288,916,965,911,864,189,687,386,477,158,187,163,960,47,162,226,721,730,906,195,809,270,270,436,804,278,411,605,42,827,366,322,9,157,594,939,923,585,678,39,294,51,274,527,224,373,877,160,81,789,409,604,896,868,245,625,992,80,64,797,384,493,311,391,762,640,35,15,942,31,116,188,525,717,310,359,253,636,782,897,756,774,245,280", + "818,94,161,271,185,55,437,365,772,433,702,699,698,709,241,476,526,910,287,732,794,788,879,792,422,932,55,338,732,350,260,936,651,787,300,393,380,352,594,94,181,731,632,919,767,359,444,864,83,71,723,869,236,880,426,760,356,628,844,100,877,654,277,8,976,725,480,245,299,499,848,133,600,231,616,190,668,305,243,908,950,123,734,618,142,396,655,978,584,441,847,492,465,736,417,366,135,798,230,662,771,916,351,399,42,394,939,986,222,348,153,613,859,693,967,161,633,909,808,783,853,787,769,982,119,653,684,478,9,490,246,355,623,734,267,24,190,670,510,981,451,626,149,909,445,815,468,269,693,629,171,637,764,128,360,325,955,270,803,434,398,372,385,130,846,898,118,566,274,75,580,760,258,34,443,65,596,44,229,667,208,438,328,58,200,832,896,947,59,305,653,721,487,926,658,601,182,398,373,79,657,620,984,210,467,352,151,396,31,411,304,916,410,375,854,736,873,222,682,275,12,322,390,794,191,189,64,376,71,27,681,985,592,711,595,663,557,863,249,968,340,359,782,446,839,36,143,191,847,414,303,639,541,87,146,956,309,443,546,827,402,115,756,64,400,312,822,936,925,708,364,17,720,169,166,812,927,614,187,321,132,52,714,485,68,288,965,14,935,780,997,805,410,549,345,863,21,52,388,202,910,422,742,624,526,134,421,434,964,252,465,78,538,886,697,276,413,750,104,720,726,582,857,950,779,494,61,56,979,559,131,666,542,533,323,707,423,773,292,268,496,380,826,188,689,650,842,789,477,583,966,27,910,684,851,460,7,144,361,441,999,5,328,650,142,668,322,471,125,432,804,670,185,156,60,968,952,757,140,201,669,40,950,996,471,575,491,126,120,606,381,340,294,0,31,585,857,493,636,613,310,848,191,514,457,746,815,797,627,662,204,835,142,140,685,211,15,595,286,859,957,673,226,951,181,132,394,601,647,466,51,241,789,876,352,672,708,554,104,930,154,294,752,129,30,181,970,318,468,560,65,357,768,81,609,522,60,396,985,129,316,694,893,852,504,479,131,640,190,455,924,524,521,612,237,409,322,739,730,79,896,786,367,134,519,207,892,674,749,347,224,557,649,889,713,500,953,44,200,733,350,500,247,927,108,13,807,86,618,281,332,418,829,658,559,121,119,302,723,87,71,52,814,819,550,46,439,125,796,868,996,932,53,795,189,939,244,939,737,387,920,480,607,559,656,545,436,760,11,370,66,693,338,236,339,887,462,808,292,707,623,353,473,663,858,47,255,15,551,72,421,625,9,303,672,5,812,212,194,97,248,914,801,776,788,849,701,129,468,854,384,584,776,626,264,695,503,584,966,101,981,944,593,305,871,992,54,744,647,580,236,237,211,117,301,81,632,395,872,603,419,622,846,562,303,335,56,760,331,677,152,448,285,424,114,824,990,323,489,828,151,42,532,164,506,544,648,501,906,695,912,604,519,425,433,74,413,576,259,192,381,628,403,279,341,515,460,461,601,968,91,183,842,61,810,882,235,747,995,118,838,184,482,785,5,679,734,254,890,71,907,175,398,771,144,246,150,425,185,24,987,963,497,653,336,738,795,455,268,401,698,231,147,732,682,682,954,664,897,315,421,736,9,809,33,152,900,145,222,686,597,444,94,659,861,475,316,980,910,878,258,603,572,785,182,380,237,68,606,720,715,673,25,779,272,625,270,484,531,26,997,80,120,983,566,279,660,455,902,977,762,103,717,767,312,707,33,539,331,33,140,152,949,14,202,192,937,280,399,788,225,130,585,334,603,803,368,251,18,559,788,48,185,882,706,23,711,590,277,25,174,306,956,606,430,112,110,811,478,678,131,612,741,447,482,27,718,584,441,347,721,100,172,638,455,704,516,240,619,223,188,138,158,562,683,129,891,912,505,165,239,718,861,902,128,446,9,825,37,117,419,726,925,448,420,736,240,160,70,407,15,890,302,290,766,270,710,767,4,620,314,172,824,633,462,424,334,259,836,703,23,403,497,865,12,850,563,877,888,10,176,123,791,772,684,759,658,424,225,792,67,598,930,694,329,487,742,429,531,209,15,346,342,204,23,836,9,215,830,922,991,756,902,666,38,620,473,760,733,723,289,175,743,875,266,276,54,105,758,105,841,540,875,150,767,725,720,680,655,29,883,332,657,774,655,249,417,326,138,909,278,128,689,742,372,697,546,487,447,624,316,496,590,274,730,530,264,663,446,211,645,315,278,648,781,566,710,685,973,881", + "92,100,747,872,901,538,260,626,156,701,414,697,668,18,922,455,835,113,249,399,771,420,962,509,109,988,507,939,190,261,658,489,646,918,590,763,44,606,109,652,804,110,114,98,646,757,401,203,197,441,535,485,802,472,474,164,22,901,68,658,750,63,399,402,209,300,126,591,722,506,687,790,828,457,719,392,251,807,739,962,545,666,20,830,308,233,634,444,486,942,406,591,890,273,852,88,221,469,741,407,482,746,100,49,10,76,416,703,573,113,323,73,821,547,743,837,431,341,8,316,654,842,375,973,648,412,93,287,970,383,747,725,468,799,918,880,75,540,129,346,467,472,33,461,482,917,379,257,515,973,898,500,226,712,311,830,255,523,43,478,626,24,163,145,110,896,167,953,148,152,134,3,35,684,273,606,340,539,258,507,426,60,969,457,258,14,85,688,434,927,203,71,19,838,920,780,790,992,374,830,240,342,286,409,2,880,981,169,950,896,642,350,286,159,840,771,442,609,844,142,935,643,465,354,183,349,15,824,395,664,393,9,837,377,508,830,817,678,869,56,235,472,649,741,666,460,132,973,356,67,365,343,721,585,88,529,643,883,215,464,674,897,601,33,975,994,81,912,353,779,489,366,729,177,975,443,121,594,452,125,532,732,68,545,136,87,688,658,37,777,304,364,922,207,793,362,373,884,443,396,959,416,929,296,707,96,332,943,939,329,162,664,523,858,892,683,872,99,725,92,828,617,647,547,465,253,947,456,199,725,585,58,701,273,963,969,186,90,940,396,685,737,409,5,225,367,115,224,662,811,558,402,933,506,231,53,60,155,602,228,642,986,421,209,778,932,580,975,218,47,157,376,994,285,540,891,839,370,785,630,288,181,349,830,612,858,27,20,838,97,776,491,879,31,0,888,33,730,656,521,745,155,894,941,174,842,982,631,576,617,837,575,926,273,175,911,525,437,838,572,415,967,652,830,13,700,99,625,302,522,160,858,631,787,564,896,763,628,953,813,406,256,591,104,282,109,612,591,671,593,497,917,876,70,773,76,714,898,309,677,514,608,821,694,555,526,540,226,965,300,53,554,721,652,760,805,657,826,751,382,691,996,304,389,304,329,87,109,716,495,510,420,32,883,799,913,157,721,717,818,241,72,862,598,846,707,498,350,223,393,410,183,921,178,295,935,133,747,964,807,982,423,855,72,115,538,371,367,274,820,415,541,148,584,66,911,241,784,126,738,945,642,285,574,730,352,92,311,379,534,142,472,880,23,372,566,690,552,322,525,293,706,246,884,942,464,827,782,227,952,193,449,476,370,973,865,17,375,122,870,472,499,776,616,742,901,288,338,744,177,486,782,41,367,994,2,657,16,360,438,718,828,129,221,623,852,478,812,975,252,983,515,57,135,965,417,917,152,592,469,519,44,580,441,35,486,554,346,129,392,416,848,28,988,336,805,936,210,480,230,241,448,199,750,867,411,369,647,474,951,647,620,913,596,13,721,675,282,837,463,748,392,936,501,442,271,647,186,129,199,289,802,159,553,540,213,698,594,13,45,971,452,539,54,412,353,487,246,625,27,606,882,296,107,969,385,923,33,384,621,312,910,257,797,621,549,953,269,578,158,36,666,519,51,267,911,451,134,339,640,375,390,301,977,626,753,803,462,104,873,419,94,392,797,421,843,315,997,533,303,341,835,101,720,564,334,311,435,865,629,443,498,273,299,919,286,633,589,791,229,55,553,283,52,977,643,461,229,829,647,499,718,261,751,513,370,933,484,443,309,7,339,683,735,219,609,285,40,465,658,954,68,194,258,214,382,870,762,97,953,994,373,345,21,907,848,17,612,18,689,80,232,158,735,220,763,634,687,432,680,333,662,678,764,234,595,383,670,917,550,195,927,225,920,770,852,140,253,523,697,918,678,94,180,9,288,432,43,508,952,319,105,152,177,730,814,818,179,219,839,234,640,661,987,619,344,522,6,944,310,751,344,606,407,805,189,289,881,398,224,585,653,874,348,761,809,114,840,630,753,581,76,870,167,205,924,340,553,578,279,624,733,997,668,631,29,878,510,968,487,529,110,654,951,220,706,178,231,413,246,183,702,270,100,205,327,439,764,490,505,72,332,347,728,898,741,169,917,418,313,443,936,303,248,237,56,456,786,605,130,494,10,521,656,670,357,374,634,380,274,957,107,768,585,968,361,257,3,1,250,607,132,592,131,995,594,420,319,197,950,653,879,809,289,844,573,989,831,953,953,16,526,158,651,827,103,122,899,853,80", + "512,29,529,797,342,92,398,919,414,553,112,143,37,274,314,481,782,345,337,897,992,820,778,567,454,26,567,912,185,816,232,596,435,246,974,641,714,10,316,683,999,526,897,669,161,174,659,437,379,631,713,622,749,860,271,613,192,519,179,725,87,513,488,866,115,329,492,489,716,899,638,700,530,761,240,308,422,679,550,987,212,464,832,81,531,104,667,112,278,579,888,65,561,173,960,965,889,69,3,292,724,383,404,76,958,444,759,602,619,691,904,73,211,373,118,364,250,504,231,950,431,847,500,674,291,376,44,933,446,600,504,724,531,719,172,283,662,752,177,402,726,825,115,294,277,755,694,291,950,793,318,173,31,570,811,959,858,845,501,3,248,802,676,159,163,534,46,483,983,797,807,263,87,493,54,198,733,410,876,807,380,248,772,312,146,651,683,994,617,588,558,608,104,937,287,904,741,616,458,90,732,925,307,847,769,558,212,411,28,86,256,302,351,499,173,516,750,44,354,732,771,73,73,465,829,191,762,414,489,45,771,567,796,309,183,580,394,588,544,623,994,284,586,245,648,615,611,862,811,26,564,604,748,296,319,903,262,390,569,328,31,741,750,243,470,914,575,287,473,155,543,2,603,713,198,155,117,872,367,655,287,681,240,537,108,835,34,629,31,417,571,227,361,896,646,577,140,976,102,444,819,601,671,882,577,130,99,45,555,163,153,377,574,449,967,278,808,110,725,641,475,497,535,771,494,766,811,47,115,976,111,177,321,623,843,871,338,682,80,107,329,629,172,726,223,383,974,100,669,44,799,338,469,357,797,938,167,174,570,713,650,627,906,976,798,169,502,244,255,471,144,445,337,262,364,446,244,682,431,770,277,765,119,713,324,700,396,82,40,970,248,414,726,585,888,0,797,337,846,94,502,438,860,319,892,280,4,336,62,45,723,163,570,869,114,101,312,55,391,109,425,795,419,960,221,155,952,179,743,904,57,78,521,854,716,210,21,36,605,800,914,597,770,405,737,383,982,538,694,220,84,507,301,101,921,515,726,183,570,40,370,437,232,198,916,935,92,927,2,821,800,188,935,406,742,344,511,677,380,326,94,801,864,893,953,707,863,106,429,499,663,137,368,97,240,671,801,197,518,198,947,740,607,398,648,7,254,83,88,44,921,698,508,519,932,512,637,626,137,328,120,527,439,363,288,859,457,95,147,907,594,90,779,643,562,224,997,837,746,948,523,27,526,661,510,227,66,351,365,304,276,823,829,976,925,485,792,926,214,347,851,210,365,53,249,273,190,279,49,660,731,875,711,907,480,203,349,35,808,868,233,354,408,867,413,344,853,539,65,778,17,998,134,490,984,209,356,291,101,664,330,271,381,298,702,54,537,211,420,271,260,222,927,164,735,534,935,244,681,359,660,252,577,415,364,54,282,196,613,131,667,727,547,509,30,831,525,652,648,546,993,378,266,560,156,558,368,587,966,519,732,556,83,183,292,599,932,753,755,227,481,812,176,927,7,680,723,759,888,489,705,518,673,491,558,635,349,749,163,897,797,931,740,69,842,99,746,411,213,928,763,264,950,85,452,205,287,573,599,126,427,101,531,101,835,39,826,708,584,268,371,552,803,11,284,366,125,418,260,987,685,974,74,457,79,80,46,593,335,164,101,131,708,457,285,227,132,294,205,241,57,333,925,177,405,14,202,695,658,316,196,528,359,701,897,664,76,283,927,435,393,404,798,11,942,140,203,297,965,27,839,645,514,973,7,155,919,466,667,367,252,473,452,903,538,433,482,344,320,73,327,519,592,542,250,892,787,844,580,310,974,286,40,500,993,728,652,450,53,860,654,962,372,48,66,645,247,18,780,306,301,205,719,317,764,654,125,556,687,726,16,198,113,935,531,479,933,887,516,29,629,953,988,886,314,864,687,874,790,244,923,881,45,756,223,786,887,2,534,38,292,569,528,398,103,264,37,589,289,362,130,988,175,931,241,177,480,959,785,284,117,429,91,752,40,375,226,47,426,590,277,859,359,825,651,693,582,348,394,856,21,485,316,343,616,153,257,465,615,118,246,31,182,980,205,538,920,224,370,361,988,288,534,126,257,690,160,556,165,441,136,576,770,66,552,168,500,9,164,782,85,814,538,893,792,124,974,178,94,885,646,130,5,598,206,717,617,258,323,948,517,138,314,398,280,352,804,431,45,188,517,523,75,908,703,350,758,444,99,764,262,88,140,628,364,834,90,161,624,151,812,970,206,297,43,138,15,491,114,804", + "480,381,206,99,892,696,945,875,695,759,381,935,820,298,195,608,611,63,433,261,471,47,390,241,953,122,222,675,75,486,856,139,479,765,107,893,831,358,71,901,988,472,148,457,260,811,158,361,140,891,554,545,950,107,793,130,643,86,780,286,181,806,726,880,992,635,77,242,848,175,815,662,698,642,496,272,778,845,816,936,439,845,972,568,453,582,482,802,563,525,39,797,210,551,890,643,635,187,322,539,677,604,597,539,978,921,685,81,408,391,878,749,326,44,831,694,1000,52,394,338,607,793,845,483,647,51,432,109,614,447,899,870,565,213,363,590,930,967,791,738,961,364,622,511,644,71,742,240,933,431,300,506,27,630,283,321,879,653,271,141,793,200,512,74,686,898,438,282,758,583,555,772,760,922,291,718,818,750,349,274,749,326,469,192,674,119,758,38,346,178,405,221,222,414,730,767,751,484,571,248,854,577,414,85,392,772,532,137,337,108,368,870,291,925,210,208,222,285,256,900,104,720,188,73,7,972,130,702,889,978,810,515,574,828,672,199,946,921,952,73,140,848,269,806,691,886,718,186,728,997,27,769,951,249,846,278,325,936,424,898,572,617,813,697,330,361,485,61,65,885,892,886,352,848,145,5,971,47,53,531,685,28,888,666,77,171,338,347,159,487,991,927,580,336,407,531,764,746,135,858,518,934,128,980,766,911,279,609,140,23,32,23,538,959,495,964,618,456,666,57,595,992,466,892,937,215,460,639,998,824,519,596,41,855,211,742,478,315,628,262,109,832,243,219,955,577,750,560,449,66,256,646,569,319,70,764,133,723,602,822,27,204,7,991,978,587,861,755,481,105,964,629,235,980,969,462,14,586,802,756,915,899,950,219,612,161,951,966,182,987,302,747,251,857,33,797,0,23,711,590,691,22,557,468,403,991,646,753,658,670,742,478,254,202,924,738,87,308,938,876,710,10,406,478,69,294,370,80,404,271,249,830,160,915,511,57,171,685,198,359,718,157,442,985,948,533,891,592,665,714,309,826,207,528,316,611,515,495,854,134,73,232,725,559,41,314,440,540,987,105,97,640,465,630,455,243,788,466,869,767,156,686,226,370,845,183,387,9,696,98,797,916,717,681,87,591,753,269,898,309,482,354,743,221,686,160,37,604,466,958,428,542,210,666,680,779,392,487,94,907,520,934,677,637,489,996,66,853,146,605,608,79,713,818,681,981,578,233,815,917,40,68,986,119,905,262,623,485,186,526,114,822,826,256,522,410,981,434,480,121,422,318,499,543,788,230,943,12,4,663,660,726,84,888,367,718,126,438,840,405,155,651,784,75,473,686,997,248,170,91,424,350,292,527,126,103,20,212,381,672,666,454,255,440,96,912,187,337,125,259,519,185,650,422,331,225,210,797,544,959,36,20,756,473,739,176,811,97,648,364,803,606,481,672,314,137,899,709,942,211,261,64,786,701,924,579,948,632,884,417,736,675,579,114,527,410,239,841,117,155,581,780,510,299,813,488,118,292,722,495,873,992,93,467,540,442,952,167,24,518,981,798,658,537,867,474,982,492,732,428,726,930,265,509,621,464,186,750,686,129,796,29,232,405,654,338,892,951,524,502,249,60,69,346,500,188,967,30,279,928,582,221,799,60,421,476,632,943,655,672,584,243,453,386,673,649,994,766,218,584,135,191,52,542,563,238,138,233,89,491,551,298,6,189,710,991,494,63,356,663,599,348,958,997,809,914,447,256,735,560,539,998,535,658,168,743,49,4,264,291,693,906,206,112,405,235,262,909,456,390,322,580,88,167,921,412,804,47,776,668,1000,120,351,972,705,616,141,422,468,571,597,234,219,792,212,397,902,952,655,532,750,368,875,190,506,382,767,112,955,809,516,949,301,107,938,916,985,120,314,507,170,302,41,567,127,397,310,49,39,61,914,719,453,337,487,676,110,654,182,836,618,939,139,243,203,163,942,133,796,872,678,462,571,177,361,862,102,860,217,725,226,528,907,693,847,740,391,450,548,993,756,573,509,399,796,329,7,942,902,840,225,872,894,801,414,483,725,701,892,225,518,448,342,479,775,967,863,240,246,169,566,108,469,719,887,175,669,108,491,963,893,889,316,887,757,27,335,265,731,685,46,750,720,988,781,947,878,532,469,102,638,949,239,991,43,416,168,740,746,303,95,28,454,28,150,775,460,359,204,110,409,190,758,493,34,528,138,133,44,511,967,900,636,318,989,697,483,994,608,961,515,791,782,187,4,571,685,103,260,184", + "795,933,568,729,859,452,948,274,314,861,396,143,215,227,576,152,777,259,36,660,458,960,868,563,397,923,155,659,798,686,806,435,798,792,297,447,428,913,675,414,833,824,355,539,909,828,24,608,656,157,435,594,79,560,794,594,554,481,412,775,601,575,456,642,136,825,198,209,694,228,930,870,950,801,941,754,827,402,402,709,861,205,300,712,216,579,582,242,888,333,969,582,383,76,714,174,657,356,812,824,391,414,126,701,507,34,389,816,153,677,193,318,514,310,568,431,721,990,412,547,679,816,694,566,308,860,545,450,778,984,164,880,332,367,333,37,987,941,983,322,846,657,460,531,615,878,358,471,919,183,983,824,453,353,272,629,940,54,116,910,429,19,890,979,213,100,474,383,5,420,272,891,595,154,121,228,181,883,534,409,270,263,871,919,49,715,428,256,111,184,102,465,667,725,24,193,527,247,411,527,343,558,701,715,813,432,590,669,776,309,446,626,869,47,355,179,647,820,291,129,552,793,508,339,330,268,61,798,818,685,112,260,611,70,477,654,128,62,676,900,953,726,259,391,909,676,110,301,70,961,720,873,568,866,715,824,721,160,621,55,759,489,797,133,551,87,65,56,409,134,613,639,663,256,458,143,74,704,505,820,517,761,560,413,446,430,519,931,100,410,275,453,717,926,560,674,210,740,456,530,278,446,313,983,83,447,708,518,300,365,937,965,286,941,464,235,39,103,162,894,863,372,619,947,28,623,942,205,836,447,238,123,669,726,331,247,137,529,976,886,706,437,698,749,889,496,933,997,525,807,691,151,273,255,119,563,502,955,779,857,676,231,331,213,251,30,882,265,770,278,380,222,421,555,537,874,13,282,162,511,804,246,169,31,627,817,111,929,317,779,108,655,952,493,730,337,23,0,492,211,868,133,992,252,68,771,698,370,323,352,864,569,929,188,368,890,224,888,600,193,842,719,825,808,320,496,594,879,723,670,506,683,829,682,193,28,706,531,267,533,966,894,908,9,509,390,708,716,861,312,495,334,700,663,25,764,839,170,906,50,859,463,793,923,98,579,955,25,845,68,171,696,90,9,101,386,789,456,285,712,302,761,243,755,270,880,446,913,757,97,441,855,877,914,940,352,605,516,612,368,881,10,602,33,796,295,225,816,304,590,215,37,461,365,354,587,796,604,454,36,946,859,850,599,522,832,612,495,832,603,849,745,254,236,628,313,905,602,935,732,501,706,534,433,387,489,688,874,961,776,221,294,913,90,844,990,954,877,719,163,22,902,281,293,19,746,432,22,909,199,214,839,852,87,408,29,816,115,119,22,155,403,173,232,289,138,734,645,197,750,933,550,217,738,695,882,863,575,403,448,316,715,945,236,331,860,587,312,478,270,143,225,371,763,947,588,799,676,131,467,218,186,792,315,992,873,761,238,133,846,12,836,458,860,722,245,451,948,945,98,17,751,333,593,717,728,586,14,715,809,885,921,469,297,974,848,123,949,159,209,528,783,315,920,462,414,26,517,888,852,667,154,772,780,893,217,476,159,117,655,40,592,740,322,432,118,833,264,946,737,800,41,230,817,147,227,834,149,509,928,759,850,703,740,571,896,825,261,663,196,200,254,411,10,983,150,606,112,675,970,33,645,901,223,507,358,955,216,596,778,163,759,994,173,98,122,717,858,787,804,368,916,955,326,263,114,467,410,31,112,234,41,561,424,70,65,214,450,377,480,574,294,510,985,427,49,515,489,994,167,706,314,449,333,914,760,177,384,170,448,641,384,432,523,871,597,798,547,919,805,649,462,958,677,661,224,948,357,565,208,773,275,376,746,407,654,61,909,567,635,655,506,124,995,385,199,549,712,53,75,322,978,610,596,329,591,125,761,885,236,366,188,627,304,552,230,406,679,775,374,364,608,380,381,650,30,518,920,856,616,545,538,163,281,64,118,895,644,885,641,859,850,921,84,564,874,610,497,227,508,272,235,533,483,416,2,369,299,152,409,209,127,268,463,958,83,302,767,924,779,296,248,672,485,486,697,803,657,148,478,454,328,333,84,197,366,184,210,600,783,635,549,911,277,206,88,999,616,176,518,436,688,370,96,210,571,725,172,651,989,23,151,699,29,282,364,665,435,784,321,306,335,928,418,479,780,266,263,550,73,865,618,470,165,282,414,865,498,220,654,329,794,791,500,810,879,735,990,646,770,643,749,510,580,920,400,26,192,163,526,253,829,473,655,746,697,427,780,794,90,961,624,245,164,843,845,740,992,836,866", + "586,46,758,76,356,703,762,927,152,224,791,736,276,504,857,674,594,757,589,805,1000,87,386,798,48,856,372,989,907,657,898,677,597,497,976,73,94,564,558,244,975,38,198,609,403,361,392,123,599,309,557,561,879,408,420,161,454,72,50,645,638,613,81,920,478,676,787,48,167,137,42,354,545,400,780,823,483,415,519,30,407,71,705,648,754,952,485,768,683,778,338,293,214,129,897,175,899,286,569,245,453,301,738,31,905,402,718,594,224,558,614,91,459,213,285,602,218,254,784,399,597,940,293,58,573,410,57,438,750,604,270,555,764,50,381,413,330,736,472,858,389,200,248,54,414,459,567,808,412,798,873,399,444,448,298,102,688,432,841,323,991,94,131,640,468,54,819,775,937,931,264,628,719,636,168,352,137,911,802,897,220,769,384,890,839,934,910,106,597,679,616,857,402,358,634,200,817,947,314,875,580,161,691,709,246,510,615,15,566,553,967,914,934,367,570,538,740,858,570,45,14,359,232,941,691,397,767,801,628,951,796,31,145,76,828,545,695,578,134,910,881,705,522,315,968,810,304,618,469,739,593,624,390,984,264,632,378,724,880,219,459,900,307,349,30,674,334,581,734,162,869,871,934,451,772,573,693,298,597,847,368,866,412,970,673,606,773,795,184,691,293,749,667,438,993,907,853,224,822,241,420,781,804,875,593,726,486,92,450,594,406,192,72,12,183,598,400,104,902,519,207,960,985,693,290,251,493,610,309,297,200,119,41,715,421,894,72,344,765,469,172,289,628,645,963,941,277,342,76,654,511,996,510,725,394,803,458,938,343,755,901,226,929,407,755,107,132,114,672,800,595,538,488,208,956,485,280,444,735,690,817,142,728,939,842,754,406,129,258,657,39,357,687,636,656,846,711,492,0,751,705,565,273,418,734,243,239,419,610,925,325,222,135,472,126,513,759,439,615,438,340,886,738,273,497,32,738,796,899,881,622,389,315,636,192,480,894,449,563,520,811,470,68,62,740,643,3,894,718,728,657,662,347,938,503,185,363,130,879,365,971,545,506,253,278,774,800,424,772,745,212,856,217,114,742,892,324,202,293,227,421,956,453,171,149,204,808,641,392,887,326,79,716,643,690,387,852,891,959,194,335,470,602,19,178,285,391,195,649,739,612,453,707,285,105,818,868,29,77,585,234,297,974,659,874,965,999,486,233,136,428,769,250,950,650,517,440,500,199,757,874,553,216,517,302,15,247,641,288,787,308,639,149,1000,23,211,874,791,637,315,148,71,683,517,351,630,233,973,201,810,715,299,280,515,483,649,927,631,96,380,953,522,234,99,878,806,747,892,456,744,976,240,491,694,270,261,286,986,6,599,859,424,814,862,29,8,918,886,516,633,994,279,34,487,676,445,162,763,726,142,695,942,678,973,278,946,78,15,119,303,711,841,951,701,503,540,677,108,160,336,295,4,289,713,839,327,830,735,314,34,783,922,984,375,892,584,718,993,981,457,778,58,187,538,422,727,124,282,97,991,488,586,157,919,71,916,675,142,954,798,735,502,89,905,723,717,680,29,638,194,30,326,128,893,600,85,408,980,934,788,363,592,137,939,481,139,724,925,231,782,556,469,6,358,266,633,567,394,404,135,559,247,64,984,609,743,418,58,185,475,505,434,328,691,718,225,192,487,189,817,849,989,429,600,86,212,68,311,49,596,954,387,345,860,233,454,561,485,64,174,211,110,977,149,825,971,259,12,549,912,737,47,280,620,80,648,528,409,117,642,92,931,85,268,560,498,137,777,516,403,934,636,844,184,161,336,748,190,569,121,553,590,120,353,451,86,482,239,854,855,763,978,979,389,793,168,51,859,472,424,177,547,904,172,568,931,81,737,773,364,248,675,396,988,146,601,980,225,748,13,807,747,228,357,821,118,254,527,96,126,527,398,982,328,672,766,756,437,36,557,661,105,846,842,323,349,464,874,288,586,902,184,382,817,98,162,550,558,23,458,397,604,216,811,804,820,549,877,48,926,189,736,578,647,328,428,859,702,789,566,775,236,320,5,470,605,911,837,850,26,139,663,935,1,362,817,238,960,939,560,433,816,208,355,480,569,569,70,115,674,435,157,922,832,842,572,699,382,974,253,91,142,253,537,656,526,106,327,796,181,524,668,894,955,942,240,271,333,581,327,255,946,575,209,944,979,276,488,696,832,502,5,517,756,82,367,734,564,267,80,37,25,897,173,365,945,786,12,499,740,75,759,502,453,210,407,489,792,115,403", + "161,32,752,585,312,891,39,242,662,387,10,872,651,799,608,53,410,86,71,283,273,163,326,176,791,128,298,312,697,940,31,83,6,951,478,615,956,463,522,196,337,596,476,416,641,53,551,834,368,783,277,599,936,359,934,865,115,63,21,46,703,350,316,707,637,133,820,582,542,437,955,660,272,317,674,467,348,692,520,348,138,409,886,153,912,874,959,321,804,325,277,659,738,844,539,30,887,409,611,736,2,333,708,585,319,805,458,51,650,325,88,177,118,422,744,70,235,41,127,485,770,890,871,973,461,540,228,636,503,129,241,180,798,576,292,776,53,148,371,294,555,292,819,413,136,656,755,391,451,598,797,969,225,96,657,48,112,124,854,455,739,59,902,622,401,664,423,291,687,855,95,346,319,570,190,672,302,753,74,295,386,658,341,327,181,881,816,990,968,685,234,601,574,497,958,288,578,954,182,849,595,542,286,447,363,25,964,286,855,916,885,476,363,411,984,26,756,883,321,211,232,238,274,82,121,528,451,197,342,587,390,308,885,583,700,169,433,352,24,400,777,177,627,801,27,90,412,622,534,903,913,556,872,604,994,535,224,387,290,943,836,933,629,175,284,789,922,821,813,256,739,908,164,767,375,498,14,98,79,649,499,722,420,701,139,400,638,28,290,717,240,246,797,428,6,910,813,833,473,384,911,512,922,641,401,41,698,531,487,724,8,713,12,204,473,24,373,530,670,958,998,712,292,668,985,240,344,893,633,289,146,450,466,738,456,603,150,601,386,513,90,297,190,928,205,375,961,335,809,601,563,101,757,151,646,600,222,772,622,792,881,893,168,998,406,899,52,123,625,192,204,338,871,537,813,556,749,174,559,74,980,49,902,853,459,255,870,745,686,202,398,89,630,613,521,94,590,211,751,0,947,219,98,717,10,807,619,476,967,19,690,779,807,126,8,833,113,787,615,601,563,102,309,278,999,534,693,500,793,707,121,807,721,777,901,641,665,534,770,845,890,597,866,981,255,816,829,559,550,82,912,428,343,614,206,924,998,907,136,567,534,942,549,209,667,874,35,507,323,999,23,598,947,279,16,596,841,472,939,547,207,847,504,584,376,207,859,533,170,913,675,684,255,841,826,64,186,817,857,85,740,606,71,250,979,517,260,827,447,188,579,131,507,431,642,742,102,516,41,495,356,545,529,775,815,464,514,520,480,32,343,81,101,990,102,614,565,547,805,646,649,102,819,246,279,205,754,572,627,551,384,690,813,628,999,157,774,681,512,699,227,402,259,668,104,194,402,636,181,258,137,312,5,405,152,490,261,72,514,116,200,871,269,120,919,273,709,800,611,921,625,604,386,225,99,468,740,273,444,131,681,558,920,184,621,436,98,940,285,840,506,635,787,738,456,283,481,721,977,771,441,384,736,639,607,904,740,230,273,265,807,173,565,339,377,150,182,549,223,947,745,295,862,184,549,421,893,340,529,570,997,523,865,736,422,376,602,703,809,422,87,26,958,50,31,75,423,252,704,435,799,589,612,433,511,879,321,371,925,290,140,258,959,950,978,297,808,485,513,39,471,938,140,547,708,803,935,996,548,842,919,734,173,876,682,28,579,697,466,338,263,862,54,833,959,360,890,399,304,693,832,623,979,330,300,118,237,207,554,606,146,302,304,366,118,659,608,673,89,154,266,488,517,822,200,652,237,634,352,386,55,951,893,605,808,547,866,530,54,372,460,584,562,897,487,527,992,504,784,531,739,136,869,327,277,423,819,883,122,465,236,192,852,435,373,587,699,95,252,202,952,307,975,261,515,945,646,295,793,712,557,546,35,285,388,678,501,431,980,671,199,723,785,905,674,195,118,943,12,800,818,343,50,915,364,808,905,580,122,93,940,78,157,350,634,651,839,201,623,867,534,162,73,700,473,674,753,721,891,250,820,424,255,144,518,823,917,583,775,900,918,369,797,559,857,934,168,317,132,173,337,462,310,933,223,722,801,668,412,977,898,972,979,905,185,975,69,684,629,876,795,557,284,797,646,882,863,818,468,17,810,206,521,379,635,229,896,387,780,883,243,506,219,968,436,995,464,456,856,950,251,463,190,717,460,609,328,14,577,717,150,800,185,975,323,29,53,304,61,340,717,468,556,650,882,381,300,172,679,693,380,70,471,612,444,314,135,237,713,298,175,27,880,569,755,674,65,648,746,607,776,764,641,288,577,601,179,92,151,134,956,347,645,642,594,379,318,78,805,763,846,639,678,768,706,292,418,272,246,404", + "962,920,346,832,803,218,474,716,621,451,780,11,161,684,80,567,245,357,940,238,784,299,188,841,507,908,592,106,577,466,394,612,638,110,346,484,759,574,693,292,755,103,148,62,342,21,523,137,109,267,957,830,294,464,922,829,553,582,872,677,474,368,139,889,757,545,672,476,440,28,843,942,883,481,653,580,924,88,404,127,94,546,317,213,736,913,659,361,856,101,883,501,740,793,879,824,301,995,929,623,835,394,549,426,280,729,218,573,570,695,583,331,375,374,532,304,432,979,373,675,828,278,531,587,904,54,193,159,87,717,100,759,256,896,278,999,757,621,582,702,807,326,907,398,815,991,443,91,69,950,207,764,135,131,267,400,702,335,452,249,724,427,526,125,634,44,685,927,399,800,968,658,506,712,28,11,744,92,685,796,687,241,32,840,130,213,424,983,455,718,535,646,520,312,363,101,491,906,874,485,438,143,425,872,54,624,667,308,611,946,409,739,16,438,707,74,273,962,112,973,946,239,911,783,574,955,256,315,715,212,586,988,124,190,188,309,838,928,358,36,75,416,209,980,883,892,671,60,891,189,176,133,721,687,685,502,790,112,745,459,340,221,568,7,59,673,66,282,878,743,863,792,215,302,779,293,341,172,358,451,126,756,992,116,177,200,671,210,994,519,796,727,62,338,193,438,279,8,63,827,99,253,691,879,503,342,441,81,534,389,339,710,190,804,418,773,14,481,982,86,66,749,214,95,292,336,487,278,341,995,992,730,717,10,488,129,707,404,389,942,961,656,296,134,259,543,63,83,623,390,989,490,200,909,765,514,284,549,214,715,559,387,143,960,281,55,954,988,101,174,679,209,172,709,380,602,922,482,176,828,278,721,586,348,594,483,806,922,767,554,61,60,536,310,745,502,691,868,705,947,0,113,154,48,186,457,305,71,888,299,637,877,904,663,503,522,47,497,109,626,14,890,793,412,774,229,82,718,380,108,574,86,803,10,539,535,907,270,568,574,467,764,570,926,652,866,808,115,781,23,322,876,890,628,723,247,625,418,635,540,956,29,822,983,551,120,290,938,421,226,487,959,293,679,837,507,313,586,107,582,257,875,132,345,932,399,395,129,289,740,512,825,364,219,817,221,646,657,265,658,16,927,940,756,306,975,143,943,971,586,561,990,380,511,386,705,390,196,590,318,410,224,970,541,589,617,600,389,889,486,35,953,506,567,933,29,495,2,652,854,860,512,547,47,369,381,606,770,553,991,444,826,979,209,546,766,321,429,151,982,643,667,67,391,515,585,37,102,611,616,45,222,656,172,283,514,201,394,583,41,551,697,841,163,443,192,868,826,886,719,947,680,597,967,761,838,955,672,553,661,159,504,950,321,193,769,235,264,941,172,996,433,799,8,762,948,33,845,127,746,837,574,372,773,28,248,149,261,711,144,231,762,309,70,919,718,901,581,279,43,113,306,731,145,733,294,351,924,530,886,339,287,189,707,618,297,854,965,51,285,718,223,807,711,123,260,616,602,252,698,196,685,566,949,422,896,988,55,568,901,536,186,144,696,550,599,682,104,743,921,218,955,194,900,579,416,70,957,387,919,306,231,585,666,680,231,560,807,141,338,799,112,183,544,178,381,369,70,629,916,456,129,447,975,350,46,609,256,88,883,846,650,322,215,108,775,775,986,406,842,8,931,999,926,493,764,707,226,717,36,751,792,81,675,628,744,657,643,393,850,628,568,874,292,280,543,430,866,106,692,705,668,763,918,160,946,782,965,659,693,564,904,547,80,401,761,481,245,871,169,216,230,935,194,694,812,116,576,460,333,203,666,203,279,750,629,893,867,457,924,618,93,248,923,47,177,991,238,977,285,467,970,84,634,526,394,226,363,775,746,28,884,850,593,95,304,503,577,663,652,707,332,146,430,597,310,961,383,570,306,175,206,796,484,534,945,707,408,713,614,787,923,609,969,859,168,684,356,238,271,236,712,614,279,434,192,450,877,587,793,863,963,986,358,39,773,271,408,633,914,387,526,461,214,580,29,77,978,169,82,426,638,244,884,193,203,274,877,237,38,482,909,622,797,759,960,897,881,476,471,277,913,990,348,168,539,502,615,178,126,75,89,437,587,26,203,113,470,824,890,647,956,913,403,944,604,335,925,644,692,461,56,634,466,23,766,714,96,124,947,243,336,459,315,992,350,498,758,459,673,975,59,941,490,772,829,684,315,695,918,386,495,809,766,795,548,644,708,634,640,194,427,273,972,49,497,331,872,213,250", + "546,646,738,837,982,502,897,829,132,624,563,716,914,824,300,217,675,325,54,32,982,948,496,32,766,793,352,979,924,222,445,186,941,712,809,922,35,154,200,611,660,933,445,236,303,988,437,925,14,952,498,143,934,104,382,696,96,592,430,473,905,349,377,208,930,938,95,718,439,26,192,724,493,578,861,719,195,826,936,654,667,745,317,778,696,168,44,287,717,339,530,63,508,291,17,894,330,181,63,25,857,354,880,461,20,832,751,245,152,680,859,204,61,119,973,636,298,463,526,696,760,625,191,396,724,172,830,461,246,243,624,202,181,360,407,846,143,4,807,812,368,357,658,901,69,591,142,612,248,332,931,551,413,388,815,232,203,533,536,35,760,713,825,53,104,142,91,383,750,685,294,695,691,784,191,645,702,244,500,836,88,872,620,770,894,939,796,868,417,665,488,910,812,103,275,364,952,796,450,152,636,905,218,179,923,694,744,645,763,663,516,630,310,893,467,753,351,836,226,310,182,871,52,353,691,420,961,481,402,295,206,410,945,210,846,750,393,420,647,405,902,110,242,254,875,342,753,485,132,697,327,891,230,732,37,72,480,651,258,270,954,827,844,451,346,189,954,525,663,90,750,44,857,327,461,699,192,654,234,336,416,873,723,948,288,933,407,242,563,62,121,296,581,193,134,363,49,723,4,803,498,247,492,881,349,63,114,338,154,525,865,178,569,493,647,824,305,336,842,46,540,248,179,688,405,908,438,80,814,984,702,548,243,208,717,871,275,815,891,708,265,502,662,113,673,822,969,898,924,622,844,302,862,62,994,206,565,979,469,610,83,302,211,582,298,840,904,166,816,912,862,832,685,212,672,449,360,555,483,866,625,214,545,941,610,705,929,585,103,331,87,646,750,848,155,438,22,133,565,219,113,0,868,971,864,425,483,979,260,76,245,122,772,940,796,381,255,117,371,731,935,875,835,795,448,350,505,440,771,712,764,613,518,948,508,670,5,357,257,272,422,390,313,14,707,946,187,894,879,153,459,249,544,39,44,169,546,664,898,489,73,970,73,506,419,689,791,258,21,568,260,232,546,164,931,449,547,767,95,575,698,106,781,963,519,437,522,360,760,744,407,2,396,83,87,113,185,371,731,517,200,208,925,392,32,816,851,174,131,971,47,371,104,802,225,918,545,840,351,401,820,453,587,499,21,850,22,473,287,955,441,92,730,975,553,906,958,801,47,973,673,383,872,115,916,73,564,847,528,92,195,24,428,727,318,968,376,959,282,234,617,435,113,179,850,573,618,438,871,723,526,99,335,493,532,566,716,962,210,527,758,39,741,985,608,9,475,550,943,484,115,353,45,737,902,512,609,375,655,692,225,742,107,63,154,708,528,509,92,929,631,824,938,343,735,970,388,932,385,860,561,240,258,553,168,688,690,515,349,414,854,444,329,602,309,959,584,806,116,303,623,517,859,175,380,972,735,22,958,827,260,876,628,491,799,487,900,286,164,438,128,266,531,333,553,777,561,691,825,780,220,827,3,70,509,361,196,914,279,795,682,187,516,352,228,942,897,839,23,297,935,117,697,205,843,759,311,613,264,716,200,823,258,770,325,526,370,65,543,411,763,613,716,273,751,438,249,384,8,604,176,690,831,772,90,717,310,849,773,905,559,116,866,116,134,217,729,990,625,104,390,909,125,130,62,955,745,928,805,830,246,721,44,194,414,815,377,155,25,304,559,570,91,456,834,421,915,893,51,540,844,519,709,487,7,512,236,525,217,214,68,270,168,134,611,161,437,346,122,418,843,25,329,176,474,414,948,263,489,726,186,439,686,97,280,514,959,743,166,769,956,270,620,319,795,263,141,483,711,970,140,930,316,942,927,838,669,193,680,273,901,379,598,984,533,32,11,120,581,353,112,242,611,621,327,11,611,785,323,548,716,857,592,100,295,511,560,133,581,593,691,994,155,899,522,569,655,891,423,53,531,182,259,172,340,329,270,30,969,449,280,912,626,776,546,824,174,753,990,12,895,342,328,209,423,346,593,916,449,325,24,889,64,625,465,893,895,688,26,426,439,599,792,488,849,170,251,505,705,848,14,286,671,38,658,709,732,972,449,396,955,215,173,366,343,173,130,352,168,710,943,888,480,11,583,404,41,427,655,774,708,282,943,590,288,402,748,455,305,311,94,828,699,16,422,838,494,121,567,589,969,84,495,633,868,47,561,370,327,689,618,138,339,271,43,700,784,308,6,402,124,722,44,34,213,588,505,626,442,682", + "891,46,131,838,221,645,604,145,970,833,851,975,587,204,880,375,884,149,626,710,153,654,653,949,85,394,767,125,460,255,462,188,559,312,368,41,270,977,591,735,62,219,483,627,641,910,550,273,46,396,709,976,803,410,345,660,594,389,109,186,808,133,99,260,57,295,353,462,291,690,476,844,334,781,622,971,827,861,996,356,546,912,14,961,746,393,791,105,993,106,723,75,404,811,46,61,254,660,157,33,319,346,421,187,189,132,527,837,368,391,489,51,155,366,743,871,502,624,428,488,626,811,382,111,959,368,48,554,467,695,296,762,854,983,892,382,281,987,156,652,258,462,948,814,447,801,807,206,453,583,155,654,796,872,651,424,682,379,285,94,376,400,987,409,435,848,263,12,281,997,697,542,570,105,539,348,316,9,147,1000,34,808,903,842,944,286,756,794,472,406,218,627,845,416,903,730,38,796,459,13,614,729,383,467,896,773,480,833,533,744,416,278,990,158,851,95,886,565,337,793,834,795,332,300,176,248,472,786,759,730,653,335,148,339,994,955,318,164,634,272,80,102,639,612,717,636,140,768,810,757,152,646,857,786,594,157,782,722,505,783,167,520,665,778,682,877,20,433,349,6,881,974,588,275,661,362,587,5,88,471,479,28,764,223,892,206,93,240,756,882,367,396,480,715,515,139,798,814,289,314,877,819,504,652,706,396,607,522,536,448,530,717,506,768,945,456,139,364,484,733,535,656,405,218,630,258,36,510,917,191,57,257,566,288,482,511,38,77,790,471,844,620,534,597,398,528,925,220,568,228,802,685,671,756,557,312,791,547,385,158,834,999,952,586,915,505,710,964,50,615,242,459,923,2,909,611,105,224,824,245,49,313,995,93,381,668,937,841,897,912,117,316,226,191,894,860,557,992,273,98,154,868,0,358,78,103,531,641,594,614,386,651,881,156,241,680,568,379,710,140,743,79,208,613,438,955,425,108,488,701,852,134,708,546,463,536,943,992,480,904,226,106,207,950,130,668,896,65,612,569,183,498,404,805,674,510,642,962,878,882,263,581,186,777,578,65,408,975,56,424,106,87,223,875,916,617,305,359,643,203,213,307,973,519,98,503,673,239,638,169,613,240,484,636,643,698,706,90,88,164,903,18,945,40,733,589,842,193,324,172,94,210,866,46,330,991,793,440,494,19,775,509,854,442,874,654,196,949,467,725,833,22,231,710,103,215,165,627,848,906,670,442,793,145,170,127,292,558,403,646,601,180,775,137,816,575,589,586,617,133,432,507,51,325,457,641,359,469,359,538,989,720,79,663,941,861,712,316,323,231,652,41,396,389,639,414,574,352,430,57,891,842,351,328,873,84,323,801,404,41,63,208,754,335,785,878,233,774,361,866,615,417,662,726,106,217,1,832,962,284,927,909,407,214,520,848,756,924,774,128,143,231,390,752,338,118,402,511,103,422,594,308,869,738,355,462,67,132,581,277,115,675,988,510,974,626,548,153,825,395,637,376,642,910,946,357,788,902,97,852,513,761,623,951,256,901,989,140,648,600,392,132,519,82,229,208,996,130,320,411,187,335,894,299,447,424,187,135,751,410,802,50,904,336,732,9,203,31,192,815,71,465,547,679,660,770,919,666,634,81,206,719,90,288,729,575,905,389,388,530,777,746,336,11,505,178,638,428,717,607,329,711,724,79,977,937,696,994,440,896,113,17,210,435,163,575,470,168,726,638,651,777,669,547,748,594,278,346,388,408,641,207,589,971,434,573,925,767,905,680,76,245,996,743,877,271,291,651,226,911,8,895,974,298,804,3,336,468,633,373,916,597,356,69,47,676,913,138,246,479,997,881,497,21,201,111,150,111,33,532,899,5,150,824,31,662,437,11,78,127,626,345,481,493,744,272,381,13,833,141,456,882,296,434,542,517,931,214,929,918,127,692,451,854,756,840,886,14,177,466,659,516,615,615,381,443,906,406,597,116,470,615,861,4,661,896,772,623,934,634,678,955,919,80,209,889,894,968,530,64,263,404,618,290,257,306,87,444,952,77,687,104,267,153,765,791,44,682,805,949,972,667,711,209,366,828,983,485,201,632,955,467,620,926,938,885,840,117,712,737,138,960,2,551,463,253,960,862,78,675,951,32,993,165,740,14,328,354,23,878,98,111,918,842,410,181,644,384,871,48,565,904,394,127,696,416,41,615,548,902,797,659,98,618,432,44,454,691,950,423,167,132,671,81,700,691,580,263,758,32,173,147,648,497,394,115,386,598,959,522", + "223,482,601,4,565,815,11,68,341,83,835,987,155,114,65,929,783,884,712,603,933,264,803,567,402,593,383,399,446,419,491,450,775,276,320,962,509,833,750,939,17,648,273,168,63,802,796,100,453,963,154,120,963,562,970,590,166,835,948,569,116,352,549,749,505,438,967,626,444,827,315,504,81,990,977,42,806,576,595,714,686,422,43,920,517,722,2,737,509,197,394,752,990,70,313,163,113,300,263,592,995,311,402,438,838,993,628,798,328,398,5,647,621,269,264,907,633,969,193,393,861,64,176,556,608,661,893,703,242,14,307,441,490,373,899,618,158,324,126,807,467,428,303,426,730,157,677,893,667,536,588,679,185,138,688,977,587,288,582,113,986,167,489,59,517,250,12,845,100,47,426,993,14,779,950,695,517,263,45,85,762,219,793,826,942,398,819,459,157,260,701,867,319,190,55,825,170,29,401,730,63,873,346,20,889,665,607,59,606,574,745,232,576,815,708,880,476,38,143,729,252,932,688,314,115,214,57,148,646,572,436,933,625,740,645,168,916,234,565,471,877,890,697,678,453,697,673,979,911,916,334,730,57,705,144,792,338,469,6,395,793,983,198,595,540,553,768,642,352,118,463,498,243,162,582,654,925,873,292,675,800,747,565,320,606,123,699,60,54,586,124,409,255,943,720,79,646,897,854,751,704,386,269,835,721,78,748,768,280,539,389,673,68,565,761,696,495,546,457,375,599,997,154,994,362,818,749,294,664,405,642,531,481,966,483,650,301,212,495,202,837,278,119,128,608,182,599,175,558,841,248,440,546,512,124,471,587,940,952,940,652,15,912,964,801,654,165,932,259,831,297,748,98,59,986,686,111,481,211,262,374,810,344,782,362,555,16,437,400,664,25,340,364,514,941,319,468,252,418,717,48,971,358,0,457,60,891,658,957,358,743,474,913,296,690,870,795,995,416,920,592,298,774,592,907,344,911,324,201,914,828,490,636,557,567,509,107,492,144,630,88,375,576,785,508,302,359,855,682,917,8,989,303,857,838,758,148,674,827,104,950,535,664,768,672,113,900,338,72,444,964,655,40,637,424,339,55,957,733,345,354,624,982,845,552,99,274,225,348,67,793,460,304,309,622,845,984,119,173,668,727,90,936,935,3,676,162,79,517,932,505,575,312,809,78,859,668,647,594,249,298,720,186,6,639,267,452,904,637,276,533,95,596,785,881,602,141,496,16,220,663,629,595,608,223,725,201,149,120,22,711,262,336,178,334,103,342,415,469,602,348,419,272,296,314,561,558,871,189,98,6,890,777,897,242,878,736,271,50,736,877,63,511,649,504,38,122,83,777,286,333,809,14,962,204,438,926,594,726,481,917,785,855,373,108,751,336,571,503,257,377,870,117,4,783,450,529,211,233,369,902,885,677,878,627,784,363,215,362,481,638,846,474,153,50,221,827,591,611,316,251,418,917,813,727,932,532,155,206,67,338,148,344,357,53,261,848,459,800,224,570,470,780,719,92,723,594,10,546,701,308,519,668,841,615,645,71,926,76,377,558,579,37,138,588,207,840,294,939,25,809,961,964,552,69,384,520,893,169,680,430,426,655,898,707,935,89,527,303,955,994,112,940,17,60,960,467,520,602,905,483,387,202,208,7,663,3,838,309,879,140,591,442,937,467,530,888,299,88,158,29,238,32,750,344,37,598,691,775,833,398,213,180,866,51,914,228,323,135,643,629,960,185,97,936,210,544,600,346,850,911,245,64,566,444,209,839,20,727,400,808,927,471,521,262,975,983,905,252,418,727,853,297,304,251,595,650,311,407,241,988,324,825,717,60,727,78,796,826,821,667,67,815,301,636,38,46,939,82,259,135,469,973,811,927,188,946,8,617,348,221,423,928,613,598,690,110,604,757,204,195,730,785,701,985,195,250,141,823,194,587,83,975,628,742,257,484,731,972,491,842,579,450,41,631,66,51,227,277,290,353,690,236,371,259,789,750,107,283,467,237,62,66,246,650,327,950,339,180,75,841,769,909,51,102,654,470,242,484,98,526,82,347,101,118,311,478,153,196,200,280,789,924,847,690,519,872,728,902,266,929,895,586,948,984,538,967,759,340,562,352,659,741,880,551,669,825,196,923,988,12,160,6,120,493,152,884,956,959,301,529,187,128,524,675,811,386,331,762,471,667,300,245,680,773,245,173,401,262,171,120,923,880,488,379,810,233,651,874,649,492,986,798,231,750,801,248,225,214,818,753,427,11,982,964,77,246,403,593,953", + "476,479,827,777,799,611,965,911,732,911,224,366,479,723,203,469,723,459,646,914,356,884,352,643,262,536,351,541,130,823,705,533,933,593,29,48,112,977,748,365,569,321,693,188,765,529,244,6,825,806,550,844,887,301,320,61,104,428,505,98,450,184,864,563,784,652,792,947,835,401,116,488,67,638,809,650,374,718,349,543,63,379,209,147,191,434,528,445,736,673,100,355,155,123,892,676,474,39,550,789,193,404,515,100,63,401,935,926,259,358,886,703,358,872,609,237,377,678,848,903,77,450,746,237,450,634,252,813,644,889,942,855,258,94,653,870,779,854,171,652,309,788,824,120,284,971,126,217,737,444,738,109,20,214,951,343,22,501,548,839,968,175,350,592,299,659,496,678,982,598,224,656,358,223,523,660,332,860,837,155,170,339,975,959,200,446,578,287,30,851,51,646,74,783,12,444,102,243,225,515,68,859,852,644,631,346,15,899,328,812,82,676,455,496,47,667,441,718,242,706,16,170,112,853,195,786,853,842,539,532,984,91,894,329,11,541,935,27,241,295,51,629,165,640,374,472,896,870,278,841,875,774,20,30,852,560,678,623,456,858,248,899,748,954,618,943,957,681,500,57,570,753,599,2,476,603,919,434,461,142,91,593,510,573,269,398,521,548,514,776,94,407,59,603,360,910,797,177,585,470,140,322,209,551,245,874,412,276,929,144,462,433,974,315,66,95,362,853,398,904,154,707,216,17,245,618,915,899,549,426,712,227,159,753,696,592,80,364,201,118,806,819,188,672,636,772,271,435,688,802,642,64,320,169,681,959,288,607,79,957,167,798,535,518,864,449,713,255,370,156,75,117,458,563,950,955,423,599,131,992,777,93,230,303,20,962,161,823,229,488,786,963,692,457,174,892,403,68,734,10,186,864,78,457,0,524,653,992,330,570,992,356,125,866,360,692,121,912,924,372,476,540,780,454,207,66,819,590,714,921,337,475,190,559,290,641,273,223,390,263,42,865,385,133,878,649,694,397,600,803,428,580,529,150,959,845,385,69,803,858,897,88,495,904,479,393,792,746,348,734,107,377,971,305,353,831,571,292,882,927,797,400,591,865,227,463,297,454,586,52,272,652,704,38,611,698,263,567,673,29,618,732,114,975,520,641,827,786,66,996,515,59,424,617,693,690,658,294,817,646,369,897,698,442,74,17,756,647,536,727,486,786,596,515,889,65,486,453,541,594,79,429,861,810,44,591,114,233,899,686,15,153,930,590,763,218,513,458,748,393,687,978,504,786,938,970,644,639,13,438,881,638,361,304,714,538,535,908,853,75,140,791,753,117,450,796,480,272,867,915,567,721,312,944,775,799,358,296,135,761,928,970,537,400,667,179,741,865,3,967,392,144,739,515,583,660,76,810,259,850,974,753,182,421,267,782,288,226,364,354,719,477,40,371,199,428,556,524,565,602,426,608,212,460,960,740,176,564,479,287,794,353,994,569,459,88,60,178,352,178,703,266,556,291,720,328,708,826,782,638,861,945,986,63,113,287,839,846,992,10,217,531,530,474,823,42,165,733,276,164,585,458,189,790,363,890,758,286,535,325,89,257,184,23,254,705,265,317,61,819,925,207,468,184,459,143,85,287,696,348,876,192,849,632,846,565,272,658,819,704,514,653,334,287,118,808,683,515,956,286,195,469,435,827,551,212,563,895,579,789,442,408,1,93,595,614,482,892,141,621,959,117,942,700,8,931,248,469,740,666,503,719,784,936,906,504,418,588,655,784,786,594,317,844,157,415,246,614,641,824,367,875,488,638,467,84,999,683,16,629,60,625,818,19,942,275,451,466,777,229,732,298,269,864,87,979,902,395,317,218,264,839,596,907,966,721,881,679,955,629,904,962,299,440,452,803,409,518,60,370,123,731,30,888,111,287,820,701,981,66,505,587,300,655,305,110,947,61,780,809,211,472,657,833,296,162,191,390,213,183,734,429,164,468,205,630,401,549,332,632,922,75,99,755,175,851,455,558,428,712,465,907,190,248,434,123,227,27,471,272,978,432,959,590,330,851,187,417,367,686,171,712,130,185,194,955,734,860,769,53,157,929,677,330,926,881,291,394,438,42,124,121,848,916,773,216,574,481,887,295,327,136,205,385,180,27,498,773,195,621,588,726,31,597,952,705,61,564,699,514,38,216,415,142,737,102,812,161,463,696,518,262,637,100,22,141,391,253,71,658,650,784,321,548,464,685,223,198,805,515,709,267,76,753,73,15,682,685,136,408", + "937,588,22,300,161,696,945,884,562,305,150,742,670,863,902,709,540,802,59,629,460,225,38,87,535,591,102,887,107,944,113,194,469,616,921,447,347,973,211,474,741,415,331,246,167,834,289,815,69,553,824,326,849,679,771,196,28,127,973,590,676,583,838,590,213,458,456,942,364,236,273,817,462,607,99,994,645,375,119,116,899,318,859,537,271,693,738,459,50,413,152,70,144,16,140,839,14,572,522,394,554,268,30,627,523,322,292,851,932,95,775,376,188,635,144,554,342,750,935,731,659,279,801,403,973,590,76,819,543,392,106,389,15,197,632,566,119,118,732,624,89,912,816,530,440,130,536,399,294,220,674,847,750,725,555,877,689,178,564,149,428,595,745,303,304,775,57,887,106,863,344,385,930,44,960,846,957,670,659,144,389,985,696,282,490,294,219,328,829,684,308,134,998,506,459,367,486,268,495,516,963,423,375,682,860,821,78,623,642,670,368,273,511,337,78,998,262,954,50,836,164,882,996,987,601,720,501,863,640,291,273,204,481,15,16,790,33,535,420,679,399,359,966,346,921,866,777,761,504,60,427,884,149,456,326,777,230,345,897,719,354,649,15,454,288,421,609,74,736,124,803,203,292,280,563,974,645,247,520,478,771,966,993,37,630,478,662,995,91,293,492,356,142,311,220,330,331,597,760,352,96,497,992,437,596,60,653,959,476,926,583,713,189,818,459,878,527,189,513,436,101,898,446,302,797,894,948,253,548,778,588,235,113,962,826,819,956,901,817,586,362,990,595,455,256,685,816,375,108,857,265,831,36,471,667,886,549,122,966,550,695,602,644,701,226,100,371,791,441,594,66,280,579,886,72,993,605,359,250,163,572,854,374,293,672,370,151,430,291,604,773,288,299,746,842,280,991,771,243,807,457,425,103,60,524,0,486,199,405,424,571,9,128,198,124,346,421,795,859,395,248,462,247,889,805,790,263,401,38,326,824,450,910,78,273,16,594,846,583,709,802,542,485,201,950,802,862,642,428,772,648,626,850,306,427,779,102,961,608,559,320,237,298,974,113,454,280,533,109,419,524,947,644,279,286,197,22,349,497,649,512,20,984,247,331,698,850,205,714,192,691,148,652,706,250,650,361,927,285,540,742,201,93,418,790,726,876,469,618,416,312,276,778,261,410,441,137,854,965,624,736,73,110,656,604,857,652,999,858,908,997,367,890,806,828,605,228,521,460,297,486,961,65,276,662,520,214,555,737,929,611,638,44,699,509,124,65,801,419,298,808,889,368,175,956,58,357,728,927,295,790,639,803,996,196,640,569,109,381,37,279,70,732,44,612,15,703,107,876,357,772,10,300,905,547,977,123,288,7,552,799,611,41,655,133,509,40,414,939,152,809,534,743,138,931,646,988,392,829,245,883,907,254,170,482,861,749,889,316,812,538,405,195,620,859,177,216,34,950,471,409,579,319,516,55,377,182,356,798,203,191,236,494,863,473,790,111,816,486,988,849,106,968,391,478,1,480,294,577,960,655,695,581,255,674,185,319,214,147,157,526,687,66,104,957,108,266,853,152,583,832,808,647,823,89,227,324,660,667,297,44,292,724,177,518,786,896,486,542,736,57,474,286,871,939,609,475,680,526,536,914,566,510,776,205,930,726,422,418,501,397,184,189,548,901,539,446,571,762,98,966,439,706,826,630,149,108,993,993,323,616,455,835,803,465,103,683,295,183,337,642,48,671,39,274,294,270,487,164,690,206,461,390,660,238,69,944,15,685,249,710,404,755,865,17,392,486,598,110,199,767,630,676,899,397,336,491,69,198,797,81,528,494,253,196,461,628,317,527,590,753,411,551,305,921,695,428,590,880,239,169,188,741,182,476,824,137,967,541,339,319,974,957,666,573,638,230,106,23,8,717,362,248,960,278,145,133,854,968,271,934,597,281,985,409,567,82,481,110,18,416,244,417,286,514,858,811,608,5,301,260,5,384,784,21,296,453,676,323,149,770,871,353,164,600,47,429,388,99,366,466,850,371,651,314,415,464,883,210,173,988,550,327,819,726,411,918,191,336,968,341,909,133,975,267,125,682,514,900,514,938,921,778,765,608,799,385,668,971,396,859,356,207,985,450,994,508,114,594,986,138,815,132,924,780,877,359,274,81,654,321,828,809,52,754,575,513,133,763,899,78,810,868,862,18,309,936,103,763,700,110,467,392,981,292,565,130,79,586,604,428,989,987,148,742,617,677,475,918,422,656,28,387,578,16,302,439,295,896,199", + "669,596,448,30,557,310,709,352,314,280,552,145,998,320,949,335,989,915,401,698,483,529,886,133,412,182,679,802,874,226,857,711,391,264,721,918,174,255,678,677,710,95,486,791,790,831,355,282,892,247,166,720,127,840,342,722,692,183,918,143,873,543,69,361,735,891,924,785,447,251,22,336,615,458,323,26,343,149,762,193,803,396,502,804,388,149,197,314,783,69,610,713,900,630,614,37,67,71,542,326,829,564,261,280,594,279,927,446,364,636,471,348,331,591,579,33,151,867,770,547,667,936,105,545,7,820,134,533,686,804,552,867,142,337,728,904,407,896,342,118,786,570,202,172,849,410,538,976,241,891,876,257,656,454,881,609,62,352,862,508,664,622,270,737,861,931,498,161,637,548,376,844,117,945,372,88,943,701,882,339,481,240,568,44,282,351,311,449,788,405,68,151,771,155,493,634,76,983,603,840,329,726,589,95,78,489,367,456,994,964,155,193,862,916,577,59,578,614,798,646,729,469,862,677,204,788,659,917,891,779,873,615,162,329,385,982,608,913,347,899,648,629,459,834,855,673,616,21,887,530,905,662,894,596,656,675,951,519,868,885,691,468,164,997,151,522,26,785,892,727,903,171,9,894,565,523,853,978,396,188,393,300,6,381,374,281,760,87,225,813,404,968,500,404,23,29,81,361,660,83,861,113,531,561,3,145,283,181,761,518,572,772,182,135,470,558,187,980,992,567,69,30,895,226,527,647,856,661,662,168,14,287,850,296,942,700,889,117,10,585,999,795,663,375,544,356,393,116,828,106,44,418,938,762,684,50,400,693,446,202,622,196,90,581,85,870,648,618,744,25,746,280,619,50,913,594,527,630,303,316,488,87,228,333,547,587,82,215,899,871,225,897,33,815,982,4,646,698,239,619,305,483,531,891,653,486,0,171,653,234,671,931,399,665,408,872,854,888,67,347,963,345,424,169,949,17,234,788,971,368,669,995,2,273,782,31,614,757,189,454,416,522,295,538,285,124,126,918,199,432,808,914,241,506,33,278,269,299,388,838,214,289,877,312,520,784,955,827,701,721,821,311,788,23,306,521,59,397,399,183,911,98,903,754,951,284,97,314,834,742,701,160,218,850,365,389,705,824,2,114,931,916,737,3,931,327,46,509,673,275,99,998,309,575,973,162,310,122,737,138,512,886,120,285,926,418,642,535,238,447,655,235,505,961,942,472,884,973,418,756,729,302,122,593,562,894,734,60,583,165,948,12,293,111,491,807,666,960,212,342,995,95,258,746,324,63,705,899,663,81,665,179,918,246,924,236,33,921,774,748,509,817,908,726,701,259,992,802,639,191,249,125,834,298,134,812,883,530,689,251,107,313,632,986,198,941,306,562,438,632,779,114,522,625,879,952,936,669,598,924,278,298,620,871,867,225,703,926,937,263,881,337,857,247,398,65,919,772,396,756,683,846,529,360,956,33,771,286,147,436,390,48,692,507,28,915,395,141,66,302,404,716,75,443,666,675,598,947,145,504,527,944,887,891,927,46,121,407,214,634,50,278,371,708,69,42,195,680,98,591,577,810,872,545,378,507,955,446,160,60,337,951,616,658,645,582,153,358,929,407,318,336,988,22,872,507,506,498,830,72,899,437,305,929,672,464,668,350,85,259,545,78,60,731,472,733,84,952,83,785,185,643,281,403,343,149,520,759,905,513,553,757,471,138,420,540,62,830,808,737,467,822,793,628,27,91,628,867,424,480,962,288,597,152,612,449,720,697,992,97,145,363,967,663,4,223,273,941,569,401,673,35,498,640,387,730,42,665,789,497,21,881,450,89,944,964,353,310,665,578,64,981,335,981,65,425,518,373,126,607,439,433,706,790,72,918,539,867,264,220,33,563,694,366,838,603,382,341,801,756,387,836,242,945,921,336,362,353,827,161,123,574,234,576,227,498,369,41,304,448,494,966,272,742,791,842,244,556,482,496,989,569,465,109,685,301,197,542,706,506,402,66,476,488,973,31,444,461,584,555,818,776,876,418,973,497,751,615,559,513,454,674,991,781,395,267,844,7,980,765,30,589,1000,500,732,196,895,873,884,842,487,936,851,661,808,83,899,100,752,221,195,148,537,948,360,918,408,742,967,888,906,268,186,309,965,805,657,139,992,82,40,191,702,294,27,864,790,896,681,111,508,484,793,163,901,192,537,499,280,223,787,701,939,980,956,252,76,811,320,179,230,447,436,405,302,447,735,56,423,581,241,813,279,931,681,895,365,234,326,189", + "938,263,216,78,185,328,705,766,607,247,634,838,468,934,389,187,954,917,499,252,509,154,295,811,31,682,635,77,360,74,518,371,388,7,470,786,799,786,625,730,158,210,615,697,488,833,556,175,414,724,89,365,288,271,961,718,365,186,437,912,258,936,104,142,707,900,364,921,719,691,876,959,869,322,678,374,812,773,671,390,730,442,220,842,689,103,438,824,562,149,132,902,225,503,466,989,326,43,545,160,95,638,279,361,44,376,430,7,381,815,226,898,61,929,396,126,547,357,566,564,41,223,716,765,300,453,255,670,341,663,513,874,840,566,758,378,51,600,245,686,906,545,701,64,529,141,530,391,54,393,678,366,235,169,120,358,699,112,461,763,79,450,659,362,254,79,739,586,894,72,31,880,2,528,777,702,732,133,814,833,394,335,658,963,791,383,98,789,226,366,341,98,590,779,678,187,733,500,310,561,45,831,390,993,693,145,790,527,831,71,202,173,708,132,437,694,417,480,229,4,454,208,910,958,611,685,829,805,287,848,334,372,819,458,649,678,25,751,518,586,884,543,646,810,606,194,729,352,65,807,504,457,806,704,704,558,607,324,450,863,956,172,984,280,840,80,240,924,220,909,922,688,542,833,97,161,110,795,298,708,912,133,304,630,230,699,298,650,812,93,332,316,716,786,770,625,205,299,494,38,740,713,494,487,647,255,269,877,205,159,811,509,320,496,688,866,730,601,562,427,93,692,259,207,673,977,252,132,492,373,862,56,986,987,357,830,552,498,823,607,796,491,414,929,194,815,302,529,112,810,266,838,459,294,737,849,124,776,484,304,348,994,510,774,94,259,871,991,671,553,730,848,813,368,519,571,837,395,719,174,667,74,132,79,573,851,339,272,630,878,169,732,227,797,631,336,753,370,419,476,71,979,641,658,992,199,171,0,598,862,731,485,429,131,745,216,928,407,15,219,720,96,281,265,627,513,854,973,826,309,65,276,558,472,211,131,129,330,60,883,796,606,314,614,49,488,39,284,640,921,366,116,379,800,631,407,292,335,100,320,187,549,641,891,379,562,186,86,37,674,462,3,30,553,128,621,528,908,655,977,837,968,21,793,583,282,207,289,968,516,509,207,459,1,609,94,627,593,432,126,439,362,114,534,590,419,536,820,511,824,773,307,984,807,381,186,426,877,403,626,791,825,629,425,457,993,69,498,907,451,826,193,831,699,782,127,416,990,283,815,740,248,778,454,949,647,303,442,736,781,563,226,879,441,771,832,491,434,442,391,167,122,680,387,891,772,125,490,503,320,924,433,736,351,740,184,52,454,217,160,914,164,24,121,351,12,625,149,312,21,227,75,494,834,682,477,397,672,17,125,821,169,531,293,881,371,982,857,818,182,749,477,634,161,57,122,274,619,385,946,957,200,501,856,23,749,711,206,155,875,992,897,375,552,647,334,631,817,489,216,531,492,176,551,52,879,863,206,369,747,428,721,616,521,542,11,831,334,437,12,849,678,763,54,678,158,76,927,166,388,275,156,253,553,960,916,940,893,250,45,691,929,116,495,155,762,293,353,884,120,188,606,169,264,514,595,602,455,789,452,814,348,428,59,523,82,313,288,6,570,532,137,523,179,369,46,756,864,37,411,783,891,999,4,211,304,190,961,160,819,277,30,331,789,78,454,985,758,964,890,882,369,798,974,274,518,369,688,404,213,554,532,184,524,376,653,993,802,772,218,346,257,603,829,742,334,904,371,554,745,210,327,242,158,664,754,223,14,180,312,807,950,651,338,419,322,841,789,484,178,482,89,35,632,379,432,656,351,470,855,773,966,446,813,760,74,850,178,915,783,407,548,560,157,425,171,226,807,984,860,516,18,535,854,230,631,878,114,956,940,282,591,192,331,385,412,126,424,562,994,744,477,239,329,762,190,895,334,150,244,729,767,683,966,712,78,500,883,148,198,396,344,144,698,583,943,349,243,740,522,994,310,351,490,71,264,49,713,917,673,770,381,708,440,492,111,724,980,453,820,460,859,293,933,427,678,658,275,864,688,312,225,639,524,689,304,862,251,837,154,253,746,574,686,785,202,615,440,905,626,927,9,418,346,531,402,71,192,103,924,505,330,146,613,594,393,51,622,133,53,689,114,307,195,580,76,854,820,389,573,112,205,655,753,717,966,328,383,734,952,80,30,4,247,477,520,607,495,504,746,646,153,404,444,126,750,134,864,30,449,281,99,898,79,835,908,627,82,488,843,757,937,798,666,708,856,950,591,873,127", + "516,550,892,656,453,129,151,704,845,796,864,686,167,53,567,460,20,191,879,635,61,97,430,412,684,562,841,322,912,916,862,341,950,105,810,928,930,425,291,108,969,303,490,283,276,108,906,30,112,14,983,529,565,18,300,572,398,716,14,198,575,145,830,601,910,38,951,147,305,886,264,5,763,824,106,752,551,555,232,121,729,899,89,280,370,455,457,357,81,327,517,417,301,474,138,643,69,603,149,151,165,751,407,970,923,166,5,615,572,366,363,700,403,347,97,262,120,80,716,821,194,229,163,649,998,344,463,716,480,795,753,349,974,644,855,54,616,613,467,44,227,935,495,707,547,1000,222,159,799,720,845,392,186,693,6,475,463,82,950,462,898,755,384,419,569,865,705,502,344,44,349,642,304,205,410,715,388,953,462,147,234,812,75,931,447,55,360,743,55,708,840,352,951,123,267,157,570,50,895,271,968,183,239,417,159,817,767,897,631,293,212,372,49,661,207,730,318,746,879,132,650,734,610,653,84,33,215,859,41,880,889,783,796,385,218,747,594,484,888,932,28,852,551,461,896,251,167,536,525,719,418,560,143,371,356,185,405,988,367,319,847,110,777,938,745,335,607,184,991,404,218,243,505,845,941,76,817,355,166,308,552,942,422,729,306,427,898,70,614,104,226,875,376,65,104,949,753,167,698,917,41,852,306,37,158,265,198,830,798,581,804,112,527,724,219,949,65,642,140,99,82,603,199,996,85,239,579,653,157,721,997,312,759,558,869,556,747,92,114,612,809,577,484,537,895,87,31,789,801,825,598,293,559,595,939,14,117,368,829,497,377,296,244,136,895,519,268,631,44,852,363,751,417,92,582,245,132,402,617,253,108,760,49,921,642,263,671,501,40,187,366,743,730,627,576,62,658,323,610,967,888,260,594,957,330,405,653,598,0,154,543,493,439,173,32,159,173,536,445,517,764,951,463,258,822,80,623,566,235,217,767,202,761,172,893,685,503,316,4,38,609,662,116,531,474,389,51,350,352,951,400,436,308,473,279,648,199,989,226,303,251,353,887,169,77,488,374,949,1000,739,636,170,739,476,478,540,556,820,67,709,289,434,968,11,773,454,105,966,432,386,857,277,212,414,28,109,273,872,564,894,950,528,852,457,185,165,764,112,839,473,502,99,118,848,349,50,864,536,309,848,153,731,535,125,514,756,969,977,419,893,924,986,282,120,363,202,272,907,879,265,589,399,199,243,950,990,62,298,1000,412,228,904,950,558,137,454,969,792,678,741,505,125,59,644,154,355,96,365,925,799,887,682,702,646,176,173,907,830,696,997,393,542,149,115,438,415,157,748,438,251,616,417,642,460,135,927,822,397,806,89,477,175,311,973,168,142,654,920,924,833,372,347,967,319,258,765,532,259,12,390,364,958,917,224,333,642,814,234,56,988,864,409,822,666,744,333,890,780,542,515,978,573,670,354,386,887,523,77,917,105,712,29,949,725,174,563,253,105,779,309,11,707,515,82,805,526,243,910,37,353,797,751,167,159,149,285,838,982,915,608,518,358,728,238,641,210,850,678,648,485,859,920,231,533,201,438,273,240,590,669,146,86,478,157,959,855,175,422,280,162,551,489,818,321,526,294,200,105,867,980,919,86,888,622,931,949,760,298,124,664,770,524,329,432,776,487,773,571,416,230,557,884,278,144,257,137,95,320,749,991,871,442,770,428,437,790,956,114,246,143,976,670,621,102,211,472,788,249,823,304,241,43,868,996,651,506,207,67,204,87,543,15,194,156,438,622,284,369,408,941,963,740,907,179,706,591,105,331,966,873,3,362,247,862,255,677,308,787,997,341,820,232,830,214,322,977,635,926,572,592,509,777,853,589,81,53,152,257,841,374,113,186,958,879,100,843,758,351,438,163,809,24,193,213,628,441,879,507,593,875,386,278,966,48,422,597,822,442,272,437,391,824,238,454,811,198,200,237,821,765,696,951,946,14,175,857,263,346,981,678,286,532,982,600,571,475,745,767,91,897,24,478,716,801,688,730,606,475,421,34,681,818,445,732,785,652,133,582,948,257,540,235,820,509,973,519,177,774,197,240,233,396,114,449,129,145,670,390,526,985,695,3,472,404,437,978,712,280,253,914,181,98,608,592,659,584,60,126,255,700,584,59,917,719,494,858,688,239,793,413,579,492,393,315,34,981,637,793,316,67,820,970,237,977,67,880,240,295,70,526,949,437,930,96,425,313,557,440,439,422,365,764,155,341,279,85,536,32,51,477", + "247,902,617,867,164,186,240,419,84,112,437,651,486,455,438,52,481,113,893,852,969,880,155,330,982,769,199,601,84,916,349,715,924,844,240,451,62,946,819,639,863,552,508,945,414,560,173,839,815,59,431,93,456,386,954,116,943,645,982,15,687,71,409,256,915,702,619,932,833,987,492,10,597,862,609,2,613,44,54,219,47,696,634,646,1000,328,350,291,921,745,428,147,894,698,576,779,334,322,598,214,296,141,876,989,30,589,793,546,522,659,609,755,318,628,238,762,253,32,410,292,14,201,820,172,959,160,175,145,983,156,910,923,211,470,778,934,959,55,381,816,157,304,530,256,712,99,141,619,816,111,548,159,380,607,796,895,978,385,71,379,979,816,410,14,436,287,261,695,221,60,371,601,853,921,703,777,398,565,34,189,633,552,634,845,594,637,434,377,580,874,605,38,967,854,613,324,135,704,627,430,92,54,744,300,873,901,902,215,688,247,155,705,551,631,295,530,443,753,536,520,538,682,404,931,111,276,498,124,372,897,611,180,619,204,419,239,680,666,473,744,998,578,613,713,590,739,875,374,653,999,264,433,867,963,544,876,241,39,342,594,828,543,631,198,519,592,326,968,69,825,490,609,501,601,991,824,837,454,458,318,151,221,550,987,558,409,499,48,323,149,814,543,265,90,746,909,626,936,22,12,960,897,4,502,800,483,104,96,513,449,594,701,395,27,532,745,805,986,334,341,213,866,131,941,546,719,293,41,32,485,19,487,769,239,633,888,294,667,986,416,672,178,653,863,900,608,271,500,793,111,517,306,613,181,589,985,712,921,938,130,421,42,890,335,480,577,452,844,822,677,291,787,999,168,960,705,435,185,843,341,224,225,730,41,473,294,657,433,133,732,562,397,867,662,617,45,670,352,925,19,299,76,614,358,570,424,234,862,154,0,722,465,357,853,853,191,145,519,32,295,726,459,205,454,8,122,650,796,574,837,849,967,696,558,136,336,76,477,773,878,284,397,6,984,881,116,66,202,920,971,786,956,210,904,631,536,681,8,194,161,725,298,354,11,980,280,936,275,851,707,790,844,878,246,384,944,939,160,559,642,679,579,802,560,241,611,526,448,786,636,47,31,20,95,747,816,253,368,811,722,986,303,938,101,294,627,95,511,240,784,507,63,930,262,756,90,39,435,281,984,72,399,769,83,934,825,81,397,685,481,864,612,474,726,80,186,54,336,136,181,124,85,194,472,318,664,243,136,42,850,842,838,328,941,635,297,680,534,806,198,110,612,606,179,10,815,686,667,834,907,480,794,240,262,266,269,34,194,123,98,413,935,187,992,262,837,552,939,687,396,292,491,427,591,522,495,714,312,270,85,111,837,182,941,136,568,377,542,85,364,868,697,251,783,840,287,385,175,850,797,962,681,586,591,314,879,585,467,360,433,523,321,75,280,590,282,500,108,708,322,258,667,586,524,590,477,339,305,316,290,495,44,918,959,279,222,275,448,581,545,698,276,176,859,845,991,664,708,556,790,199,482,151,338,543,465,955,640,541,24,599,693,524,75,245,387,46,489,728,167,777,301,435,370,544,734,829,557,643,633,936,511,859,155,296,350,54,881,4,613,6,463,56,293,332,493,648,321,337,100,503,85,184,64,193,542,648,886,480,505,441,903,552,958,287,820,32,980,856,693,156,27,299,993,461,761,787,739,751,623,39,206,550,389,652,351,827,686,163,723,272,94,335,861,192,488,331,598,19,675,148,489,766,904,509,100,264,29,114,592,217,394,254,141,976,470,525,739,153,443,605,992,135,647,578,559,206,806,830,165,275,537,568,78,731,74,627,125,236,761,430,791,558,66,681,157,246,106,117,441,701,32,261,272,668,156,626,770,425,873,155,866,214,796,515,294,19,805,179,896,669,961,400,939,780,888,925,141,40,392,367,238,631,329,951,519,654,407,238,282,263,399,272,2,263,329,151,464,197,3,372,293,809,602,904,147,922,512,870,209,708,14,189,227,369,101,530,771,336,47,735,55,624,819,339,133,488,515,421,800,727,976,602,51,454,583,70,296,382,182,14,410,70,852,919,204,913,198,817,10,861,531,793,45,49,393,684,220,492,164,217,106,396,473,294,964,97,224,741,21,335,915,623,313,582,652,658,703,717,151,261,4,782,632,211,791,534,560,565,456,291,106,826,552,292,14,461,761,435,328,135,485,906,997,759,435,154,742,808,748,667,248,601,84,435,851,170,682,959,834,777,613,904,303,58,679,877,890,413,132", + "668,261,622,583,931,275,772,589,235,742,954,383,40,505,268,500,303,208,101,137,992,129,826,525,673,886,677,550,286,343,328,927,763,959,944,630,963,432,892,944,979,215,607,285,873,317,208,512,101,549,911,900,92,559,709,665,116,96,566,382,404,698,376,811,163,895,973,621,59,497,690,892,408,727,895,447,48,965,411,207,351,39,210,502,998,149,178,130,743,710,588,520,642,851,883,728,218,970,108,879,968,226,740,875,277,431,517,509,906,508,558,358,460,139,324,405,760,209,273,226,905,7,291,240,281,646,203,467,51,877,100,405,782,741,311,762,34,146,874,847,652,245,705,980,414,661,688,394,736,823,256,267,777,355,505,17,482,152,657,518,991,753,631,416,915,295,732,29,179,903,568,115,432,94,194,900,310,228,695,43,275,383,263,192,143,263,375,957,575,777,271,359,99,198,654,947,261,36,204,499,288,318,336,577,882,68,263,954,597,524,415,489,629,491,432,574,520,471,882,302,432,82,702,439,400,358,109,335,361,828,865,833,858,788,648,205,984,866,814,133,970,204,952,949,878,352,37,44,627,670,133,958,787,648,390,475,200,416,767,893,286,177,809,477,964,435,941,328,232,103,427,234,683,272,807,279,169,209,172,315,698,990,210,494,177,168,97,517,266,298,110,28,501,764,764,104,755,214,465,805,716,173,873,292,733,114,320,804,849,451,309,352,151,635,131,94,269,701,825,534,236,424,597,184,702,528,113,869,633,438,324,155,297,671,563,85,248,237,728,724,887,215,497,889,793,671,522,946,40,547,256,177,442,713,242,872,895,404,714,723,205,91,940,322,561,524,234,715,856,236,86,726,71,171,291,9,582,25,59,164,142,463,461,228,31,276,350,789,590,27,237,807,733,204,837,723,742,864,325,690,637,245,386,743,992,571,671,731,543,722,0,928,65,615,117,52,798,82,413,389,722,301,771,363,880,118,393,342,993,49,400,232,978,199,387,156,886,12,186,291,908,371,830,951,729,741,32,617,213,461,585,818,474,237,26,136,145,639,589,420,363,94,527,629,879,894,326,646,642,491,112,599,733,108,58,86,919,215,410,788,306,942,461,494,867,90,680,770,197,420,258,799,61,840,982,942,432,689,430,373,918,704,898,357,425,376,67,788,365,501,359,95,382,196,175,439,802,249,477,78,621,921,635,216,372,465,113,884,400,889,123,858,51,512,278,920,832,2,538,786,143,634,460,900,97,606,608,551,909,624,238,853,637,116,824,619,785,711,256,946,758,706,774,487,190,638,299,692,625,384,261,946,155,927,1000,280,760,723,645,593,593,33,496,468,934,993,231,805,77,71,317,360,626,857,372,362,248,236,749,589,21,767,354,7,523,317,47,112,878,485,321,875,26,153,624,194,63,689,10,538,53,514,110,416,618,560,426,415,973,749,970,173,858,433,349,17,308,809,294,753,356,449,514,207,561,558,17,971,822,28,607,40,651,942,414,76,814,309,458,721,817,471,287,283,661,285,850,686,943,511,193,424,354,215,165,600,296,857,506,531,928,985,783,606,904,154,599,542,488,805,327,796,996,421,354,898,650,756,878,767,307,620,795,302,79,54,227,580,794,513,878,809,692,287,991,36,456,62,442,460,999,152,667,126,626,648,839,871,966,835,116,848,712,535,526,11,728,709,601,132,430,604,275,95,422,404,383,976,587,710,799,750,310,874,652,798,51,477,987,909,679,617,219,124,781,892,52,230,710,403,160,308,240,691,476,733,525,276,367,708,4,686,364,228,289,148,40,438,895,269,274,418,807,455,106,816,39,861,709,537,343,681,508,557,407,162,650,950,334,163,442,866,36,522,539,445,66,127,22,239,125,802,52,406,418,715,656,211,583,136,178,225,47,678,602,485,162,745,72,497,195,859,818,143,741,118,806,798,817,988,893,470,223,616,778,552,527,427,692,632,263,623,606,699,911,590,177,607,272,696,77,473,337,51,463,995,22,530,698,70,18,462,590,757,791,555,796,159,125,653,257,232,689,4,790,906,559,470,623,563,963,226,838,514,510,39,754,222,963,999,472,819,711,348,143,355,770,616,434,298,508,879,664,744,577,965,303,5,538,149,406,552,29,361,168,846,716,882,243,110,358,323,402,868,214,665,999,534,104,91,678,44,541,178,409,752,563,351,189,688,410,802,653,907,399,310,604,707,936,785,569,947,479,334,134,804,737,489,465,312,985,681,348,380,29,940,838,505,668,181,131,849,985,873,80,371,457,283,536,386", + "751,326,39,57,35,164,682,351,645,398,164,400,974,933,946,895,625,488,434,352,315,543,594,137,78,953,882,81,33,118,550,767,283,106,232,483,558,169,797,833,315,991,254,472,389,917,782,806,837,942,522,601,112,861,213,216,103,693,196,543,277,966,681,567,896,748,205,596,620,993,525,351,99,373,119,452,161,665,234,635,842,9,698,982,597,596,663,11,636,152,770,556,328,19,520,881,157,653,827,546,102,672,626,119,363,545,698,469,274,110,919,735,680,92,920,979,860,57,84,925,932,305,360,569,610,402,816,406,840,675,810,808,135,362,181,368,912,415,632,732,898,951,495,631,96,960,80,17,767,113,388,110,868,772,724,398,977,503,552,656,996,343,943,946,371,800,438,624,528,103,590,945,373,867,409,829,728,810,87,666,8,501,854,792,219,331,578,412,327,218,841,812,548,860,21,2,452,300,239,771,487,624,212,433,847,437,979,635,35,553,487,799,409,105,868,295,43,190,616,936,937,593,227,542,465,229,713,811,968,190,626,458,868,594,245,696,133,343,508,410,43,105,539,183,407,949,428,780,500,450,289,304,771,986,699,880,230,981,280,610,548,669,248,436,8,227,553,934,499,746,282,777,857,847,412,427,556,362,823,102,338,672,447,858,335,269,306,309,697,964,713,632,445,928,830,79,246,912,419,201,942,423,54,915,802,576,668,87,674,71,696,300,680,342,802,622,381,569,999,838,213,118,615,131,505,791,23,96,152,21,738,27,31,439,781,133,866,749,349,762,512,597,388,123,349,313,856,892,218,395,22,881,618,964,130,584,549,8,618,149,27,799,76,257,178,388,983,723,946,11,883,237,285,246,827,217,774,858,693,374,871,320,117,486,572,685,617,222,546,719,873,865,977,835,575,163,478,569,222,779,877,122,651,474,356,9,931,485,493,465,928,0,917,662,304,900,677,307,183,742,570,952,284,63,7,885,830,474,550,768,662,802,451,505,865,853,961,210,242,775,831,820,366,762,952,445,600,152,551,365,239,385,302,431,456,604,222,543,273,222,236,80,75,672,177,591,484,913,633,715,659,804,950,194,889,318,523,543,842,276,424,882,41,256,765,703,146,801,627,993,883,132,554,460,318,346,524,723,479,90,431,831,892,851,993,392,937,631,314,571,471,173,403,584,322,41,388,132,543,180,547,825,12,999,622,270,786,693,192,49,889,234,120,741,51,997,86,522,390,444,73,717,740,704,992,616,981,217,240,160,106,877,691,153,424,323,371,392,544,696,319,141,723,670,464,87,673,256,972,997,346,159,630,688,486,90,765,95,222,277,724,732,959,362,630,468,246,61,775,959,743,404,43,242,882,215,731,741,469,591,805,52,160,828,266,310,656,497,128,997,619,248,655,402,454,73,928,798,338,274,917,334,173,320,281,360,160,905,360,382,279,739,813,553,809,284,508,833,374,507,24,458,145,980,466,481,95,63,807,403,427,928,220,573,512,448,810,478,949,137,313,71,788,226,170,110,232,227,868,693,347,28,724,308,144,39,9,994,882,504,718,462,781,781,876,858,35,583,869,897,794,371,128,161,259,167,76,335,973,239,717,442,710,517,302,894,980,267,261,383,912,446,725,131,438,222,251,547,368,452,932,116,465,203,178,892,124,930,244,531,799,464,989,577,467,721,744,988,717,309,145,65,829,466,135,271,217,457,950,893,360,473,332,838,512,557,331,743,676,24,667,475,505,637,665,486,791,372,820,203,214,718,922,708,141,817,124,220,468,63,117,760,762,740,891,455,104,395,41,828,752,866,211,125,790,694,602,445,347,729,676,114,342,640,593,132,326,560,415,218,739,705,357,574,680,565,192,103,816,610,651,331,893,378,842,839,766,758,151,815,722,220,907,602,458,65,501,98,145,362,391,534,224,807,641,672,989,469,933,951,755,593,965,236,473,268,650,999,790,462,313,516,59,841,933,886,758,271,704,508,106,429,843,264,525,322,408,69,190,287,852,879,81,250,988,888,823,265,546,64,426,840,915,105,119,461,75,595,898,246,399,458,191,963,706,996,729,69,621,106,638,868,580,484,533,608,714,186,136,538,134,594,571,647,205,722,602,804,362,677,612,472,636,879,806,847,73,911,688,259,212,485,520,832,340,404,322,169,63,13,283,968,931,934,596,303,265,859,428,913,987,52,846,204,927,12,640,260,677,448,176,485,822,525,295,538,340,135,334,471,536,798,506,460,664,120,263,794,426,325,254,391,418,939,638,308,885,734,781,648", + "195,272,447,407,304,28,688,5,375,55,398,185,795,643,672,602,132,579,46,812,455,842,125,51,211,798,262,474,726,692,841,217,930,258,517,387,790,782,304,101,701,562,260,95,500,453,801,845,15,110,208,413,757,532,727,186,962,413,697,125,693,271,991,679,710,758,434,641,432,727,702,356,535,874,608,904,325,439,630,829,145,875,665,225,78,821,105,900,116,987,650,547,424,76,120,3,835,334,186,49,192,688,333,835,787,794,471,620,78,98,881,69,872,411,987,678,358,49,888,256,856,674,334,592,348,144,701,927,628,777,584,660,367,731,912,619,406,617,87,549,797,546,20,186,32,782,76,303,34,676,106,46,960,560,313,425,88,862,117,591,809,644,92,1,467,333,510,540,766,422,375,701,192,113,282,849,741,805,597,425,793,182,493,479,270,966,490,152,135,649,646,235,523,897,547,506,734,234,18,467,660,14,368,552,651,805,917,516,492,860,169,911,471,338,346,384,499,505,173,713,957,124,701,125,202,195,705,436,94,392,411,679,347,476,376,972,101,65,763,506,10,333,957,216,58,69,84,577,548,884,596,602,523,150,325,676,425,188,525,457,979,529,903,186,281,259,563,434,762,450,671,738,334,719,914,866,889,11,51,329,47,239,814,46,329,961,604,978,100,956,857,827,696,635,852,128,542,410,374,991,954,482,114,696,917,764,726,74,402,220,620,551,50,797,3,577,665,975,865,238,396,786,764,637,696,752,799,522,4,664,32,364,394,80,64,730,69,741,992,833,78,221,314,969,595,815,126,307,987,229,398,939,839,578,808,131,975,179,115,102,188,436,903,406,129,372,242,689,329,109,674,504,917,681,33,382,727,322,176,650,111,108,728,78,432,928,243,403,459,99,26,830,958,142,926,570,254,929,135,807,904,772,881,913,125,128,399,429,439,357,65,917,0,825,139,994,370,739,3,19,742,140,346,559,919,698,949,891,186,737,722,189,472,724,903,130,469,787,593,529,86,523,334,715,181,436,349,916,220,751,784,196,834,86,953,991,161,482,585,647,157,959,104,473,222,946,41,230,457,472,637,429,874,814,782,44,702,455,457,761,466,35,382,597,839,308,276,454,712,376,748,959,620,715,136,780,607,689,461,154,473,343,385,481,885,49,773,529,541,784,674,316,705,319,38,489,841,429,662,185,237,650,723,641,62,42,429,880,359,338,604,595,6,321,198,624,577,889,15,641,612,107,855,749,941,518,176,391,4,740,291,928,675,941,962,672,252,98,208,53,427,724,749,427,948,441,531,667,870,94,191,838,681,878,644,787,784,346,646,593,107,545,14,382,930,496,10,973,188,633,83,340,573,104,216,861,375,470,578,136,357,776,272,439,860,160,368,442,369,833,308,261,930,564,22,455,755,11,108,652,827,930,941,42,111,910,842,440,185,312,632,556,37,756,974,691,950,428,745,901,66,451,222,953,242,856,917,618,182,245,890,585,718,291,733,895,318,459,298,705,920,374,85,992,951,330,897,152,117,645,521,124,386,677,583,948,745,453,495,119,443,211,34,631,723,765,790,212,789,552,490,691,677,332,570,243,21,699,581,355,529,110,51,386,235,330,906,920,8,695,478,746,206,784,920,955,337,677,77,214,707,55,947,754,994,647,505,677,375,52,94,850,359,330,415,236,660,403,111,343,496,681,419,117,592,81,945,861,767,32,73,367,122,381,687,1000,506,767,970,343,733,751,697,376,826,539,55,37,465,30,982,483,339,413,745,421,768,664,136,163,322,687,674,993,910,470,624,333,612,384,487,410,27,308,775,611,54,710,676,541,857,328,637,408,384,546,889,73,216,550,285,26,71,777,111,808,454,170,523,749,279,580,618,443,594,342,939,68,778,463,174,329,582,105,589,816,448,303,997,961,995,171,739,239,207,847,765,261,773,115,730,635,950,992,190,176,636,152,830,770,909,445,264,119,722,469,472,61,396,597,781,308,43,7,692,819,63,768,462,194,3,457,376,198,49,576,427,113,237,441,641,754,549,782,182,49,460,561,526,758,488,307,606,280,227,627,953,567,916,192,616,98,729,614,150,861,955,835,988,545,724,961,976,960,743,429,470,529,164,825,43,764,823,780,911,316,920,171,506,201,795,384,995,926,764,208,345,483,856,518,595,493,745,813,428,816,618,40,49,771,525,500,451,55,911,926,235,773,121,120,301,107,993,372,591,859,89,750,505,210,164,118,614,774,505,328,207,102,197,185,451,918,991,197,780,286,830,586,398,404", + "678,780,898,584,724,379,692,560,135,211,629,859,968,159,968,94,704,420,695,100,260,911,477,459,747,464,530,310,102,965,860,566,39,184,351,285,299,678,444,916,351,775,930,749,227,305,563,375,52,880,389,611,642,891,824,901,970,167,749,994,924,212,582,58,7,719,194,171,126,813,528,89,379,942,806,388,205,355,937,522,369,638,897,54,209,842,973,237,781,854,88,898,889,96,582,101,111,950,557,60,521,790,805,733,751,248,327,441,911,800,860,125,504,193,20,246,393,474,1,51,997,765,778,968,272,950,398,889,956,649,987,21,637,498,733,715,511,949,950,562,217,434,224,116,587,1000,760,337,256,955,279,662,614,508,123,863,333,68,895,905,524,581,397,446,579,911,233,768,347,212,713,494,241,491,950,117,660,636,440,88,519,460,956,891,562,860,589,693,94,231,259,326,753,79,97,127,902,237,13,818,413,392,121,84,853,5,596,540,553,453,668,234,727,966,645,274,265,244,44,552,547,421,779,723,740,100,73,519,226,269,579,35,597,861,13,337,260,164,568,842,158,378,452,180,371,187,620,480,884,519,703,527,625,762,73,81,376,782,980,808,491,541,158,250,86,256,573,242,739,896,159,800,884,622,532,827,235,603,627,558,711,937,779,537,498,876,652,158,472,976,546,269,676,751,552,327,964,123,410,843,784,432,117,482,361,140,204,990,384,915,768,976,374,562,810,835,612,489,791,200,809,361,831,958,103,903,473,402,928,359,444,389,804,352,32,86,15,745,112,188,454,728,60,787,412,712,251,36,62,81,716,321,919,393,218,619,58,491,227,56,919,440,138,44,157,59,949,774,163,914,182,115,439,596,401,795,695,355,973,510,332,590,818,673,474,670,910,471,405,221,814,649,524,140,273,869,202,188,472,126,663,940,156,296,866,198,665,131,173,853,615,662,825,0,241,803,64,363,199,60,650,868,480,70,207,37,348,690,595,601,276,864,267,616,458,555,9,16,401,910,275,585,744,265,593,672,404,653,183,426,89,727,500,814,468,397,243,576,87,938,509,794,486,958,251,497,2,668,69,137,323,807,178,847,887,402,632,289,58,789,794,70,265,268,705,190,735,446,769,573,395,807,749,957,559,780,906,458,811,313,203,524,938,235,600,205,371,648,209,700,291,374,196,901,741,122,795,858,499,709,224,853,142,976,477,506,20,188,463,138,405,597,763,641,294,923,869,560,137,698,681,99,39,884,813,680,824,269,766,624,270,723,118,608,859,156,311,423,887,877,587,927,395,255,35,613,679,445,443,958,362,181,606,855,252,956,236,860,150,790,225,210,862,171,709,976,462,688,31,786,525,541,616,973,632,899,89,190,593,138,457,359,261,724,391,428,89,563,505,221,598,27,385,398,494,688,505,118,702,879,231,996,388,752,913,740,209,190,877,779,899,888,860,478,250,554,185,144,174,491,330,925,656,165,395,273,901,749,402,658,363,96,621,343,646,252,671,719,315,920,285,657,578,478,824,977,531,95,421,323,924,632,953,170,836,172,272,741,896,342,720,632,729,260,345,677,529,568,462,46,690,836,95,961,724,462,653,717,79,508,806,932,464,922,647,457,424,868,707,48,967,474,579,737,601,112,346,533,720,393,703,249,527,311,743,338,200,459,434,980,506,786,380,492,373,409,775,186,624,256,841,266,691,12,77,538,929,931,194,146,492,525,811,128,359,667,256,895,621,718,548,537,522,521,198,828,196,59,873,216,602,807,83,349,10,657,121,189,291,883,427,137,918,877,292,700,596,342,377,460,598,421,223,837,243,800,57,628,565,620,716,257,332,511,668,437,555,353,60,714,861,552,111,231,782,448,274,19,117,215,953,173,322,157,85,598,377,188,654,856,465,576,453,755,450,244,150,888,879,113,161,206,297,264,365,318,924,13,593,990,921,245,597,461,71,517,148,481,347,180,64,723,506,966,373,585,205,98,655,333,75,191,915,103,353,590,652,888,657,43,99,198,106,968,101,558,669,244,167,894,387,979,119,716,24,457,662,163,368,174,119,133,692,73,930,536,289,559,224,434,376,867,756,945,673,340,361,436,221,721,509,972,239,118,896,744,874,313,37,76,485,875,223,336,926,117,34,886,328,946,819,306,637,943,724,93,220,865,143,493,450,561,863,251,967,601,480,955,146,274,92,405,705,781,586,332,349,42,171,761,682,755,950,476,593,253,433,772,960,1000,964,705,884,384,453,804,738,926,954,520,687,974,413,561,128,999,528,779,859,585", + "848,568,759,442,451,136,676,146,284,326,624,801,514,360,366,252,669,545,471,153,997,886,457,631,396,492,412,345,919,501,618,750,847,763,754,280,654,383,433,326,296,991,169,97,746,148,173,303,955,558,912,203,533,565,434,911,553,19,857,166,187,638,347,404,651,769,131,302,445,581,217,70,454,23,869,915,585,144,778,5,304,424,56,124,972,231,878,929,19,214,29,830,970,977,772,961,196,564,347,459,421,298,771,65,903,529,618,554,966,832,157,44,790,186,172,570,340,392,816,536,677,791,890,955,534,899,728,641,845,98,885,185,167,966,515,981,592,58,74,323,732,848,812,759,164,892,50,931,414,870,295,571,342,90,913,578,446,971,488,623,643,596,570,100,370,920,339,162,629,605,197,467,219,185,96,636,397,540,609,600,85,321,348,286,337,475,558,494,893,301,482,122,983,54,555,89,987,716,567,457,647,189,103,211,230,532,651,19,572,666,271,411,502,576,204,174,282,474,811,463,797,749,484,91,393,151,489,801,816,778,795,21,84,683,718,216,216,173,111,179,350,525,990,726,306,111,444,733,867,161,30,671,672,102,999,920,960,230,421,520,301,782,671,73,617,599,188,177,251,863,743,751,610,539,479,970,647,282,349,793,264,521,532,282,21,521,835,277,776,501,588,756,634,618,726,558,240,338,312,328,591,557,766,996,260,837,187,100,897,544,433,868,233,641,769,563,351,387,123,998,771,20,985,793,605,56,979,554,90,315,234,810,856,629,711,433,661,77,828,284,685,399,664,36,566,924,314,578,288,320,245,304,153,976,329,620,904,632,893,981,850,975,550,964,722,964,425,827,861,109,302,417,255,648,338,975,569,235,184,766,741,685,905,643,260,56,863,706,735,481,782,893,662,685,175,114,924,368,126,8,503,796,241,690,360,124,408,745,32,853,117,304,139,241,0,495,316,761,389,297,22,454,851,316,241,594,645,579,716,8,922,398,919,444,545,356,682,27,952,525,185,278,901,822,818,266,148,297,509,485,272,197,681,703,335,163,153,869,107,725,859,972,282,329,702,527,88,196,423,34,613,537,46,683,288,147,560,755,607,966,653,403,786,792,456,511,315,933,114,589,309,697,80,402,903,360,754,991,184,993,793,541,968,180,200,12,756,539,427,630,420,836,739,757,60,909,86,129,864,36,220,764,598,658,202,796,951,938,837,862,718,163,387,32,742,709,498,48,282,979,394,707,440,755,496,777,139,516,859,358,161,773,897,212,588,145,741,28,597,261,636,340,110,896,590,382,170,121,199,13,757,729,841,363,375,776,66,342,800,182,219,753,122,803,575,590,951,124,36,103,968,162,497,644,691,786,890,741,292,364,840,201,402,991,659,695,89,371,959,604,369,360,907,192,568,357,787,320,451,87,628,446,735,944,409,751,371,650,766,266,655,50,745,397,441,881,901,975,907,535,627,66,777,330,638,595,575,414,726,533,35,676,439,713,557,312,975,839,48,740,148,146,104,94,92,286,81,316,582,173,745,850,402,282,614,811,670,710,7,68,23,101,915,267,140,455,850,419,265,195,182,61,99,660,446,539,71,718,500,553,633,375,170,85,989,83,697,197,379,524,502,582,806,948,647,441,479,167,244,722,388,603,336,7,15,636,80,748,776,161,826,224,708,664,68,169,83,797,442,674,804,492,637,575,192,504,651,518,411,673,396,485,467,80,696,955,661,143,320,664,360,806,816,950,739,498,197,555,63,845,898,718,520,947,266,91,870,423,976,595,819,656,533,251,68,169,87,533,975,823,162,428,631,788,922,726,785,14,333,616,850,82,722,797,274,854,189,244,659,236,182,127,902,40,12,283,57,215,833,772,272,465,935,301,542,172,573,724,112,278,608,210,5,459,233,963,553,884,194,883,356,405,254,845,141,765,734,846,297,658,478,246,714,784,331,408,277,936,157,871,440,467,265,865,100,183,268,827,53,14,386,557,302,869,439,102,952,12,241,990,725,622,461,483,726,233,40,24,514,664,770,550,843,986,897,735,587,579,359,522,342,592,425,104,116,879,190,863,441,60,882,466,181,814,992,474,19,373,976,384,667,6,856,896,152,605,337,148,746,352,311,204,740,913,771,951,455,312,625,301,158,509,128,942,857,675,936,765,950,607,365,400,291,249,394,833,148,292,538,467,65,190,213,595,414,524,965,786,127,74,420,857,720,2,45,60,622,269,797,121,530,67,231,392,399,958,978,151,477,618,904,715,735,517,926,595,872,242,606,177", + "764,295,749,766,305,194,177,226,242,388,388,740,310,731,739,165,805,219,700,431,245,498,844,72,835,840,428,120,910,533,330,46,898,869,450,76,955,177,699,754,446,722,462,423,74,917,254,197,935,165,341,158,139,879,431,256,446,804,669,95,725,544,422,981,870,248,228,879,979,920,263,932,93,239,271,776,846,113,772,851,915,24,678,429,833,494,702,465,905,200,491,370,95,222,106,90,103,84,322,573,666,426,776,52,39,101,274,540,578,858,366,766,277,796,100,371,593,12,627,637,37,42,716,481,918,627,754,230,510,460,88,805,743,594,313,238,567,43,52,775,625,172,362,641,705,1000,640,697,71,708,417,833,534,903,362,29,363,584,463,283,278,299,571,355,724,619,175,739,244,294,486,41,307,697,636,160,483,488,315,294,502,680,566,32,821,581,902,816,757,815,370,876,203,170,373,964,421,112,661,439,699,112,584,16,302,266,600,616,250,197,172,144,252,847,822,866,568,37,270,894,261,337,75,964,81,982,537,98,217,104,296,222,64,659,295,127,385,745,289,209,119,992,400,500,638,573,990,912,61,756,923,694,235,971,468,152,621,124,593,192,213,418,619,872,757,45,748,201,785,257,921,339,896,973,691,705,735,245,702,132,658,59,650,899,644,194,351,504,472,374,386,87,835,38,931,629,450,86,572,739,93,725,99,411,30,682,811,844,754,950,11,768,419,951,414,795,938,598,240,296,748,988,370,159,802,88,603,968,594,884,385,400,446,211,957,666,224,906,276,82,465,288,891,733,268,975,316,460,120,184,990,656,232,924,273,464,428,46,445,418,843,226,170,488,349,596,785,915,786,313,459,397,54,426,91,149,27,107,701,618,801,711,84,366,827,239,741,314,574,137,462,916,25,211,911,101,738,890,513,833,522,381,680,870,692,346,872,216,159,191,52,900,994,803,495,0,740,412,815,242,8,838,861,942,545,349,195,888,683,216,934,851,16,650,178,280,562,396,261,627,538,550,559,102,21,551,526,757,433,436,142,241,558,866,300,86,628,503,529,432,483,542,261,443,174,869,845,195,794,268,778,625,471,504,792,639,860,362,961,300,143,540,163,729,252,147,655,394,630,503,95,249,549,939,129,135,592,52,760,292,584,642,345,517,130,896,835,679,640,565,827,892,325,666,991,698,94,767,798,443,829,706,62,22,146,836,484,952,791,112,392,227,377,389,620,835,703,896,681,53,223,833,926,419,284,338,154,390,847,794,346,174,557,201,732,824,450,702,128,204,468,651,483,863,458,859,69,728,606,164,483,452,301,450,146,782,753,751,781,284,635,910,112,266,732,850,317,626,804,281,789,194,750,523,214,35,556,701,536,824,697,754,859,724,470,765,550,478,820,276,658,702,22,664,728,286,236,575,315,239,569,57,988,718,881,868,768,221,244,70,120,618,581,783,336,556,864,216,873,283,194,694,492,111,584,745,582,799,771,716,751,228,614,934,979,539,383,678,891,275,785,897,251,11,378,48,620,19,171,914,191,687,445,644,539,47,518,663,860,997,171,651,994,448,855,685,671,450,66,512,778,863,627,751,719,609,61,63,346,786,720,520,95,17,221,284,385,696,817,447,895,107,350,729,222,366,738,701,543,643,565,527,52,547,23,722,394,744,82,845,305,88,731,865,416,452,690,618,938,798,523,449,594,625,303,495,926,599,54,710,637,315,533,82,434,42,722,817,106,16,105,523,43,359,915,127,727,11,60,320,861,923,384,665,842,948,837,404,200,810,234,503,811,782,229,9,653,958,955,60,30,365,491,626,822,813,793,48,46,359,909,67,480,850,303,737,822,794,743,920,719,959,172,840,715,664,41,868,918,934,214,437,237,244,770,930,562,882,74,148,382,1,519,127,236,996,341,873,222,778,140,218,126,938,480,47,821,914,849,459,562,98,283,149,404,999,486,422,462,883,714,72,70,38,610,104,943,64,956,204,623,612,928,282,928,924,823,695,113,123,748,968,232,442,829,467,905,247,16,510,117,246,255,173,225,701,688,796,562,399,827,661,657,324,524,904,227,198,335,973,856,507,8,493,757,244,196,206,36,240,760,672,932,118,182,535,238,996,450,531,51,81,886,233,146,892,106,938,402,600,256,431,732,478,748,550,915,674,764,648,507,166,764,717,182,997,782,473,244,678,550,171,251,431,907,473,650,63,316,90,636,554,236,983,738,852,731,656,195,553,414,515,55,203,27,452,700,806,149,650,511,202,211,598,873,513,128,660,532,356", + "888,597,103,895,491,322,308,139,533,669,530,171,426,251,986,947,695,237,892,882,368,721,58,37,216,344,664,156,306,737,998,632,416,341,900,319,715,868,911,777,569,998,545,665,166,733,515,354,885,415,120,782,522,755,47,483,952,690,49,206,334,84,380,23,637,32,114,308,138,537,801,280,480,674,975,315,29,857,466,448,374,353,43,834,997,375,668,926,328,942,306,525,47,461,706,336,292,37,860,40,229,720,184,980,946,619,131,573,926,223,300,790,337,495,79,438,803,374,408,582,140,945,141,869,385,91,243,817,257,418,87,755,821,391,151,467,750,822,755,869,371,339,429,535,738,247,786,948,941,539,703,786,896,60,179,485,570,647,387,964,156,267,220,996,702,152,936,438,490,591,827,760,515,554,115,943,441,590,452,71,810,725,835,506,794,610,231,987,226,841,906,117,73,831,751,985,453,477,908,750,342,482,819,383,184,18,269,956,363,553,448,892,155,642,326,918,215,53,625,229,727,650,818,309,895,281,824,108,937,563,860,472,225,671,130,966,715,359,695,662,835,159,18,409,730,308,589,409,418,81,296,284,892,594,412,943,948,645,925,97,651,660,614,77,808,829,918,736,968,795,994,45,599,425,406,702,277,668,191,80,105,703,799,412,564,414,341,6,992,374,983,684,506,108,475,250,953,589,17,626,264,139,663,342,126,62,619,480,795,510,899,364,298,352,325,450,445,360,188,425,580,135,388,154,430,427,972,429,294,487,414,509,793,725,688,291,641,34,379,225,289,508,367,747,902,421,347,159,905,43,34,530,492,403,839,492,354,935,686,278,449,890,601,449,599,58,726,890,863,531,591,727,158,335,972,579,150,241,610,185,16,257,767,308,54,922,129,251,645,790,309,480,338,15,525,312,87,224,759,113,47,255,568,795,121,421,854,928,173,145,798,677,370,64,316,740,0,66,355,711,156,891,555,817,477,517,413,927,712,427,50,409,355,682,32,685,412,888,291,456,483,744,47,281,745,331,630,941,583,88,814,757,40,465,660,6,409,2,59,178,611,349,998,821,261,536,506,993,342,786,418,911,178,653,283,972,357,987,185,567,700,564,413,149,642,475,216,370,488,900,301,537,375,549,539,560,162,841,689,970,788,548,949,805,314,253,733,862,713,46,848,758,494,697,927,27,199,348,958,500,231,691,759,467,142,828,322,23,719,92,977,45,944,223,25,323,874,28,535,36,953,152,522,45,876,967,207,118,313,994,62,213,463,290,48,931,105,522,41,267,504,994,231,211,883,528,261,341,568,874,504,385,84,36,927,784,5,239,313,717,145,773,182,474,90,284,956,523,558,349,230,753,829,546,865,957,564,747,874,42,167,145,975,317,83,620,230,549,268,874,142,982,563,349,763,686,87,434,102,287,836,322,245,592,652,903,538,929,7,94,525,560,44,137,836,527,521,431,774,247,759,799,805,51,195,252,249,927,279,882,447,969,383,756,708,139,513,824,606,975,309,77,59,268,364,111,464,321,198,521,249,942,778,901,807,472,756,342,718,173,222,478,831,391,456,912,994,227,345,851,234,2,815,484,749,109,703,32,653,178,898,220,498,283,914,740,422,585,106,50,590,567,876,974,457,57,55,589,951,574,127,555,646,470,44,26,48,303,233,939,456,96,859,324,998,95,79,46,358,43,229,937,886,216,537,17,7,41,78,910,835,786,531,303,271,84,616,586,207,792,571,262,585,379,326,661,706,642,445,405,952,863,862,419,932,773,838,844,714,597,100,836,836,610,158,446,588,829,835,677,242,833,114,427,464,413,83,167,868,150,108,545,386,295,577,934,454,907,814,125,719,972,876,610,608,73,148,774,942,785,926,635,243,492,973,808,154,169,934,430,276,708,552,258,417,267,90,391,190,631,130,343,579,464,541,577,38,939,126,333,168,851,411,916,518,498,430,63,74,473,495,732,197,489,392,825,992,323,158,931,350,504,421,282,506,992,698,574,683,542,241,458,651,497,223,111,589,977,414,764,204,633,450,512,62,678,27,486,637,800,587,510,473,808,906,656,944,99,743,436,630,627,264,41,38,623,235,888,938,921,129,599,722,768,123,239,585,283,898,80,758,390,249,990,200,960,658,841,651,698,413,739,840,86,315,387,242,299,33,15,45,487,692,21,60,912,445,32,337,642,597,920,588,207,774,989,365,317,81,499,771,750,871,415,697,821,465,831,976,50,743,659,807,426,983,380,985,92,480,37,828,80,679,549,984,406,738,630,515,603", + "40,704,341,420,572,483,504,8,184,331,579,975,439,782,160,205,592,325,140,246,792,572,905,800,882,838,233,917,815,32,414,113,37,793,519,769,521,988,311,431,475,361,711,321,966,36,57,339,534,626,192,969,669,389,63,36,635,473,470,887,854,406,928,659,151,216,965,803,879,252,527,20,446,605,30,678,893,78,639,627,600,302,921,635,874,174,402,119,600,186,611,735,256,181,326,185,390,865,98,252,228,861,409,693,638,416,675,770,978,697,154,796,436,301,865,846,61,841,556,191,922,439,584,375,350,263,52,355,915,305,301,12,195,450,886,560,633,717,265,422,685,40,747,559,893,636,325,870,756,77,740,475,766,546,488,457,426,752,707,836,420,634,509,108,315,415,30,913,572,280,393,663,37,376,336,704,749,589,732,63,549,693,529,486,618,668,893,136,295,483,405,990,430,219,513,266,115,408,175,104,228,672,713,195,842,603,811,269,786,658,619,570,104,687,407,351,726,390,423,485,998,214,584,896,8,95,996,229,739,89,456,916,444,639,309,318,863,314,117,295,847,505,368,732,953,138,271,171,598,355,266,334,210,204,732,927,314,497,135,379,325,938,65,852,894,61,742,262,939,80,979,252,124,275,95,446,230,368,534,385,509,223,113,805,632,405,66,100,979,842,526,737,48,926,295,393,839,596,644,886,339,900,350,450,223,466,964,147,556,809,343,52,610,544,165,650,906,153,910,868,39,311,625,187,149,918,38,731,597,689,647,725,290,228,52,107,140,274,436,961,251,863,886,127,144,852,961,713,483,85,282,470,904,470,703,827,733,88,837,962,562,624,721,76,21,47,374,875,891,893,576,91,816,419,127,871,533,580,349,249,574,256,805,682,398,410,293,67,241,497,542,852,47,595,437,55,308,888,439,787,497,117,379,995,912,795,888,407,536,519,82,307,739,363,761,412,66,0,748,693,712,258,425,617,923,505,490,846,516,626,182,778,601,251,417,126,360,432,80,725,672,373,377,121,539,542,256,309,795,826,372,9,661,317,68,216,73,202,616,854,500,402,321,457,534,856,283,804,261,379,332,545,881,533,816,574,465,284,145,727,816,958,710,930,851,967,127,205,521,606,451,162,3,280,722,400,440,696,349,85,220,869,826,561,44,603,532,751,998,233,714,792,965,891,277,479,545,82,652,412,935,518,406,922,863,404,357,532,257,969,162,170,862,625,362,726,907,899,728,734,458,864,123,248,997,899,509,307,829,82,181,784,930,264,244,858,564,647,845,980,707,612,236,799,576,963,961,563,834,557,349,550,346,311,334,568,369,733,957,420,395,701,288,959,154,41,30,867,559,355,123,588,217,938,937,443,119,908,463,718,403,704,102,468,735,614,41,692,828,895,884,692,623,516,511,954,520,12,792,454,342,426,754,932,15,985,973,481,166,718,200,884,167,968,872,536,661,735,835,592,322,672,623,768,747,135,952,695,817,88,223,121,598,429,98,406,102,128,943,153,952,604,237,758,360,971,151,996,448,686,163,517,407,456,613,201,271,855,189,494,964,460,312,36,970,795,635,665,805,458,591,465,743,267,740,384,480,204,404,389,190,85,728,629,167,344,543,762,884,521,515,516,92,91,539,747,327,418,352,68,410,927,852,843,113,812,46,637,489,918,718,146,238,118,492,976,651,190,367,357,131,471,264,104,112,456,423,619,152,963,178,695,902,375,112,125,402,876,472,106,845,219,773,439,470,455,498,47,43,587,742,558,836,535,892,526,371,267,513,121,280,336,91,124,460,449,994,262,421,788,341,535,315,67,53,257,487,463,934,635,487,321,960,123,606,530,56,269,512,747,587,552,66,242,846,833,208,22,658,287,902,238,258,467,140,414,773,273,740,62,731,135,870,476,339,36,427,671,995,562,505,221,845,652,379,789,80,398,875,656,284,986,272,31,972,955,332,520,549,143,587,609,735,759,678,378,798,657,539,915,985,479,800,202,635,200,845,191,174,10,16,564,949,784,922,242,739,120,894,965,242,230,789,53,419,476,584,116,146,846,165,85,533,415,335,778,867,262,477,209,276,845,207,698,912,804,291,319,493,442,74,171,857,611,235,429,530,457,527,147,399,291,236,671,680,589,499,462,973,398,238,871,492,508,514,140,674,606,575,503,869,630,994,875,36,197,541,503,588,990,294,817,31,258,532,859,420,636,531,727,298,56,826,845,27,423,635,514,939,382,143,55,782,321,939,507,817,350,623,360,231,230,458,207,492,465,716,87,551,523", + "291,46,435,238,297,572,586,984,334,536,497,7,872,210,245,187,950,390,501,920,772,584,368,213,734,450,391,37,860,156,400,729,802,262,407,902,196,270,905,61,652,902,889,446,541,260,487,544,404,222,611,782,128,382,281,349,615,694,132,823,210,349,307,28,967,498,57,94,45,228,275,137,928,828,554,271,988,633,213,86,210,768,552,600,825,122,317,123,420,866,448,85,408,249,782,807,278,318,609,934,290,594,638,793,262,107,988,527,762,762,662,458,105,345,950,577,806,789,144,968,677,466,745,774,618,686,569,110,22,83,479,909,94,799,825,737,128,584,911,805,542,791,472,702,661,507,125,648,773,266,259,758,454,69,706,303,86,421,218,850,24,344,923,246,174,851,160,28,453,251,748,980,176,712,616,92,293,475,310,44,20,850,977,565,902,510,540,486,801,650,515,788,704,258,190,429,84,481,123,184,429,890,653,205,922,622,520,812,62,173,462,177,510,434,787,844,683,408,854,864,351,513,629,875,693,111,523,695,643,158,222,216,179,784,872,494,836,26,507,484,499,980,392,151,373,492,508,604,142,60,198,698,701,767,487,264,622,391,753,800,461,246,719,968,629,649,208,232,601,651,265,144,303,514,138,753,550,199,244,961,252,352,435,389,17,218,306,945,359,940,124,369,70,68,424,803,900,201,553,671,375,628,433,234,13,613,267,18,965,404,998,813,8,748,603,294,467,739,610,880,243,757,697,351,422,318,63,571,688,287,822,925,758,685,690,355,181,257,561,233,868,863,434,587,815,766,392,690,388,41,822,291,964,859,863,524,315,368,244,232,744,360,323,766,383,761,330,316,185,186,450,925,919,367,122,892,294,456,379,908,412,405,562,497,487,942,395,589,507,534,207,326,585,286,838,391,938,600,615,615,109,371,710,416,924,859,67,15,445,32,413,183,3,199,389,815,355,748,0,338,411,82,158,835,457,840,752,348,670,7,715,880,217,460,252,393,81,237,607,548,885,424,740,418,247,872,952,43,676,165,7,887,461,236,847,417,290,316,17,948,654,120,222,172,426,474,221,243,52,706,388,693,825,222,579,690,202,106,720,566,182,440,337,716,396,750,440,914,14,273,365,213,114,370,779,680,100,514,370,951,433,837,379,314,55,584,162,701,872,306,541,673,931,282,349,735,451,355,820,288,303,225,853,200,583,572,142,841,698,797,722,85,743,338,983,771,257,546,95,587,811,623,85,749,88,373,952,175,631,857,805,169,790,805,2,107,449,555,342,325,469,604,22,431,786,384,451,402,204,975,94,27,647,380,44,888,55,633,33,591,888,195,272,870,210,200,145,565,812,338,929,101,502,113,566,602,475,127,825,655,89,496,623,925,639,726,451,831,657,401,112,200,950,33,973,945,33,172,710,836,981,318,908,3,735,567,57,266,893,990,450,393,395,849,412,416,896,182,595,233,352,104,549,367,963,937,72,694,429,934,458,943,43,398,187,235,564,779,747,689,376,339,933,760,303,309,577,387,489,674,420,332,808,399,272,395,599,149,300,303,840,508,318,39,96,86,242,666,518,531,140,539,653,851,409,435,178,422,135,863,378,147,698,440,494,616,641,735,711,114,417,845,513,652,575,305,687,125,742,253,373,148,228,807,489,979,95,918,471,605,501,172,16,927,788,493,875,670,25,389,930,690,892,308,699,836,742,624,578,485,980,755,501,388,270,466,119,872,842,251,380,299,418,93,752,639,985,173,168,668,409,870,734,184,800,97,344,773,888,235,986,206,660,47,520,859,253,910,311,830,281,307,499,709,974,404,979,957,620,962,678,318,906,999,638,636,196,877,650,317,546,855,550,456,347,745,745,205,277,872,58,629,832,419,959,297,597,458,622,296,115,234,638,323,742,397,154,873,86,630,287,70,353,106,341,955,245,249,942,454,115,50,256,141,39,352,866,626,485,341,180,286,483,51,135,514,118,242,289,956,841,802,907,990,999,898,987,841,891,893,704,688,857,233,980,869,229,435,108,927,694,387,901,863,173,846,455,311,676,520,694,26,688,957,389,594,959,447,996,543,650,991,359,337,733,302,169,370,79,65,8,884,917,7,764,290,801,638,974,767,751,763,171,423,128,845,617,215,607,779,194,323,410,934,91,784,418,105,870,209,820,718,684,412,927,413,318,166,261,164,657,687,988,603,997,801,314,388,215,254,262,816,920,389,797,438,78,856,536,356,795,469,887,158,335,187,377,431,192,338,8,298,277,896,47,259,340,32,36,370", + "456,768,900,492,716,630,118,354,573,181,945,124,339,339,339,787,914,4,586,407,50,523,4,707,419,499,490,238,942,671,939,983,971,912,847,47,924,776,934,223,49,495,291,497,331,498,603,949,659,91,16,838,647,474,217,711,183,434,456,373,579,532,268,815,712,972,33,504,585,747,59,839,903,598,820,76,153,238,548,71,105,929,646,803,856,533,234,735,414,959,616,382,716,291,595,851,277,925,528,493,654,698,463,415,83,679,336,231,47,573,626,123,716,602,55,361,815,132,600,352,890,346,996,790,976,893,764,901,640,686,818,630,966,959,961,307,910,818,872,651,608,890,877,419,270,338,26,136,329,350,530,353,172,470,300,963,314,586,509,395,211,624,374,280,271,152,854,407,629,21,82,627,237,826,280,30,141,963,374,720,448,438,366,832,828,336,190,613,934,959,715,22,349,694,887,868,514,163,543,291,214,165,970,992,831,855,881,764,290,666,827,845,906,503,480,634,745,880,529,626,4,116,273,712,16,591,360,153,660,763,170,979,898,42,376,429,303,994,464,665,947,925,368,835,775,559,990,42,517,549,120,574,570,277,162,401,558,37,791,75,629,54,971,586,597,224,731,31,840,723,111,879,172,151,231,422,460,961,451,656,104,770,517,198,236,178,672,376,362,465,110,271,91,885,603,444,820,146,863,557,809,642,773,24,112,538,248,438,952,250,803,116,989,24,787,702,758,493,529,217,542,513,968,228,220,89,959,917,656,911,780,915,641,53,185,338,316,421,849,820,26,747,573,800,515,745,252,755,578,837,742,138,900,665,235,524,925,309,528,528,613,724,334,299,300,191,175,779,94,966,476,974,610,572,571,224,535,957,464,801,48,51,703,574,766,833,33,852,873,448,51,636,757,859,572,109,876,193,438,601,626,731,140,920,372,395,347,219,517,295,389,742,19,60,297,242,711,693,338,0,360,767,467,582,599,92,678,916,373,940,784,561,36,329,193,643,40,63,341,813,679,319,646,191,164,706,585,613,25,984,314,994,562,195,416,318,458,348,13,778,476,369,819,119,861,657,719,264,733,148,732,447,943,837,626,204,959,704,10,487,694,886,872,450,324,381,260,834,594,981,366,617,619,302,85,855,280,29,92,925,71,408,892,11,607,17,177,799,148,740,219,113,952,230,726,498,947,619,728,396,273,211,368,850,177,2,890,837,852,485,836,849,638,316,974,167,697,358,444,478,80,173,944,35,196,86,94,906,712,312,390,547,950,399,780,276,967,512,918,509,78,877,292,414,443,824,127,215,672,517,995,813,42,810,620,884,441,481,37,746,581,366,142,537,12,683,418,922,856,476,101,192,425,533,961,268,244,823,735,61,825,242,45,686,822,938,266,764,314,6,829,385,504,381,902,581,127,174,971,427,20,998,639,934,515,256,898,770,296,405,945,59,123,439,875,565,132,153,544,210,650,205,920,246,2,717,721,573,248,428,86,621,539,86,866,626,176,170,979,741,198,886,689,474,951,390,742,353,303,90,947,517,334,421,456,60,45,396,423,381,620,409,781,97,5,78,991,860,977,159,560,621,113,760,574,761,421,750,851,446,747,915,752,282,306,447,663,749,586,637,642,577,618,737,521,972,266,207,629,651,702,267,316,261,996,840,2,749,1,669,492,491,7,437,939,198,313,738,318,651,219,981,629,156,382,777,301,372,46,648,231,457,717,227,310,281,434,489,198,518,314,92,185,241,880,52,950,91,382,857,178,207,994,760,742,274,694,362,696,712,132,817,729,362,835,900,804,809,903,149,805,139,513,361,320,699,431,895,469,143,452,327,346,411,996,507,207,208,500,950,865,977,168,98,155,611,406,182,648,504,569,267,477,697,898,97,492,297,463,654,47,619,818,877,580,298,998,703,890,991,187,878,714,581,581,55,627,163,710,806,724,398,555,626,950,966,733,859,132,991,874,554,786,118,775,315,633,84,427,769,450,99,356,44,514,324,36,100,817,56,920,990,207,72,781,789,154,349,928,639,29,420,337,488,239,534,601,342,690,637,958,462,916,476,585,469,155,890,247,123,179,306,246,856,910,497,491,345,51,624,260,989,828,310,234,229,465,791,605,90,406,675,483,834,384,449,679,697,865,148,361,334,359,457,955,987,9,138,458,822,719,310,217,426,213,364,97,152,502,252,820,954,231,695,654,686,142,7,56,854,147,666,30,453,263,284,967,217,840,102,835,668,366,228,276,534,447,184,110,910,546,934,435,754,724,56,644,188,424,555", + "710,76,113,552,348,357,109,384,70,330,746,402,781,645,215,463,649,28,783,127,53,411,594,88,699,475,620,933,789,220,353,283,346,869,610,631,822,486,285,337,738,539,244,692,686,913,234,34,909,943,50,173,905,465,146,520,324,598,920,321,339,348,231,386,248,701,876,147,737,348,1000,879,594,398,351,589,659,579,669,877,138,522,48,814,64,858,37,954,255,776,456,827,348,379,502,536,181,31,365,887,768,134,729,654,218,330,850,318,654,685,505,630,389,109,323,654,981,500,289,997,171,733,831,620,333,665,81,871,255,238,78,209,289,976,195,24,584,316,281,845,458,397,975,985,316,890,335,238,201,970,995,696,565,74,448,863,228,945,228,947,200,608,563,501,425,382,345,161,921,105,500,509,68,136,697,25,689,915,815,632,47,458,13,32,117,602,895,903,992,934,872,308,674,890,887,804,738,400,776,79,338,520,177,981,243,507,49,183,339,397,140,115,155,115,809,402,242,945,289,27,25,252,478,767,588,841,422,842,401,648,961,859,25,253,174,79,530,22,782,238,589,245,465,575,885,39,618,515,264,452,591,509,594,924,864,508,604,816,336,944,166,186,221,964,243,72,732,592,153,484,718,348,864,375,578,786,254,378,781,894,281,273,492,17,489,783,444,166,285,872,437,977,22,550,434,807,994,852,280,796,468,119,580,952,811,403,335,431,161,279,150,231,31,902,346,275,454,997,760,307,962,417,920,978,498,626,171,625,774,135,850,719,403,172,914,135,1000,260,654,652,777,228,886,989,174,257,666,600,153,385,891,269,633,837,279,199,909,904,733,521,731,720,71,343,861,180,342,303,885,894,801,197,263,871,965,259,385,941,340,60,704,566,574,954,437,186,460,955,50,716,967,104,531,957,415,425,710,842,340,563,14,935,743,592,476,248,963,720,764,726,722,570,742,650,22,8,156,712,411,360,0,180,685,470,766,469,843,881,45,248,801,10,162,658,165,988,75,641,168,308,500,906,928,118,763,61,25,129,466,931,323,576,230,596,969,527,692,409,925,960,815,5,716,328,81,643,109,407,922,791,938,508,500,828,167,978,422,840,61,288,500,689,324,701,898,366,821,863,548,601,697,156,854,29,224,310,20,537,411,435,565,30,359,242,809,175,630,448,478,510,675,50,491,975,559,527,552,543,285,682,813,99,173,809,323,727,21,979,214,668,927,583,941,528,950,608,643,879,446,58,456,759,743,351,586,385,995,431,730,200,622,827,125,491,195,254,405,125,603,376,862,752,451,376,870,70,209,43,41,577,934,261,553,963,840,776,774,129,890,131,98,396,99,953,823,125,484,178,890,361,23,287,716,603,658,29,124,255,227,624,332,252,396,372,704,834,309,78,216,634,671,996,934,636,132,779,540,996,740,125,247,158,350,199,560,396,391,696,148,761,41,39,343,506,575,681,955,632,519,26,187,291,354,280,574,897,179,432,734,573,988,327,624,394,527,933,237,279,392,822,239,7,850,867,281,987,472,706,392,124,532,799,499,153,952,856,478,885,766,195,464,937,387,878,338,113,511,945,333,912,53,301,780,867,103,728,37,507,264,105,900,296,811,193,592,53,377,762,758,208,329,11,661,901,281,27,416,924,657,488,752,411,631,343,916,455,968,287,351,610,824,626,16,947,396,199,842,166,110,732,244,213,638,724,617,806,520,96,252,391,779,849,687,191,370,209,570,338,438,617,17,663,91,662,882,251,275,258,924,549,207,18,572,801,234,583,836,182,934,639,76,348,602,128,881,238,657,404,953,621,372,338,337,729,800,293,182,737,231,888,599,887,570,454,812,32,820,157,889,672,116,193,663,38,281,565,504,306,165,988,720,636,482,558,783,92,186,631,61,955,632,927,128,905,47,543,639,189,566,144,349,313,521,666,109,979,904,262,387,486,686,170,173,40,552,253,358,435,924,822,559,685,316,795,854,671,56,174,64,860,57,361,810,142,950,891,2,815,528,893,339,717,866,510,770,954,853,290,102,300,176,202,987,388,478,364,285,628,639,265,28,210,250,777,859,986,630,135,653,433,581,143,683,825,75,398,596,685,253,569,843,711,493,27,393,858,857,575,533,674,548,156,152,126,307,724,418,598,645,381,773,945,207,218,42,49,765,830,689,287,980,207,639,171,224,354,712,599,990,502,815,633,394,92,159,897,216,710,939,905,559,780,252,565,920,220,580,224,968,935,7,652,849,761,617,491,787,593,263,620,558,967,541,598,934,955,350,961,574,398", + "685,731,994,379,606,673,445,369,659,645,770,916,979,921,43,994,394,597,982,4,381,226,862,9,384,874,626,108,710,666,994,559,896,817,755,969,245,848,522,91,275,766,104,893,447,757,524,917,748,507,678,162,633,783,578,114,911,488,319,455,884,898,980,855,791,783,259,461,331,815,747,592,929,736,666,107,835,670,391,277,860,182,769,149,730,754,874,449,226,339,636,215,295,153,79,121,261,175,178,190,604,250,167,151,243,112,84,873,146,629,693,996,526,400,77,536,949,966,183,961,636,285,48,795,303,6,291,193,279,647,551,631,265,239,328,688,365,80,845,249,183,713,985,489,71,346,651,126,124,451,154,424,648,912,468,312,936,871,6,715,107,706,865,821,912,735,452,183,761,499,431,923,860,13,705,812,116,430,945,325,300,768,972,161,899,49,294,473,588,9,401,952,888,56,590,518,609,958,83,442,149,517,669,141,310,418,766,971,93,452,922,340,376,709,745,879,331,915,55,315,852,275,630,747,227,747,432,701,714,64,801,32,115,707,343,308,748,198,37,382,895,409,164,287,963,866,570,180,44,144,982,280,656,932,90,689,901,559,290,857,774,464,385,765,105,661,633,308,550,407,753,164,946,441,373,788,56,123,678,707,671,435,92,47,421,707,601,658,508,406,26,563,525,265,79,749,203,284,890,904,649,307,859,913,873,865,138,528,945,281,477,155,574,343,325,815,261,493,339,941,894,839,341,356,654,34,230,359,650,120,453,919,576,95,661,649,673,966,961,365,260,387,655,203,41,590,336,938,716,60,42,314,13,300,738,38,598,787,601,753,775,674,843,946,18,623,600,180,894,57,846,636,345,759,557,210,343,555,281,56,382,198,55,788,836,589,291,461,449,871,432,893,67,673,967,795,10,719,886,102,890,875,79,298,540,462,345,96,951,459,301,952,140,868,454,838,891,258,82,767,180,0,644,621,350,104,76,34,380,733,309,145,535,532,516,815,85,616,369,952,246,634,639,646,849,969,548,960,36,639,117,597,629,88,831,618,952,42,799,152,152,262,410,552,356,209,238,491,410,506,845,129,898,489,711,825,935,998,596,814,525,602,490,980,582,20,641,33,738,484,296,978,864,172,189,625,680,774,695,20,906,729,134,36,959,453,179,128,464,760,967,598,973,269,821,26,37,424,673,413,960,853,848,597,268,53,358,629,329,670,508,347,45,517,539,950,984,415,725,208,355,347,941,817,481,732,211,618,326,663,604,70,790,185,266,270,533,786,202,331,768,88,841,919,419,547,780,839,539,881,85,887,958,220,283,137,555,345,577,383,183,265,746,233,709,557,50,356,506,376,943,471,828,671,920,826,92,336,277,998,744,212,173,490,349,858,665,825,234,224,577,685,568,796,818,933,145,511,535,54,423,784,781,879,737,454,172,191,195,999,156,984,374,959,61,226,228,887,29,365,531,467,263,124,456,842,113,598,845,491,558,845,864,130,751,239,973,923,592,568,83,992,47,330,376,349,945,883,214,882,551,507,190,682,351,348,907,135,762,769,650,104,517,449,223,732,561,429,982,43,165,933,749,325,907,452,369,150,897,487,889,137,797,334,113,718,509,748,654,384,792,465,711,960,309,493,436,731,289,202,89,966,80,536,837,82,81,735,138,684,728,819,236,836,33,107,728,38,559,370,881,362,945,168,363,274,471,125,488,234,304,903,147,612,684,486,619,829,472,808,676,445,247,286,850,893,876,643,301,40,936,720,688,575,296,306,729,321,114,323,632,208,860,871,275,5,841,533,54,542,788,654,220,120,411,123,509,43,751,514,20,656,907,450,865,504,109,835,999,406,677,270,271,636,801,498,116,709,263,67,346,803,185,628,495,514,743,741,551,71,34,593,109,548,928,603,744,264,841,224,872,210,16,561,780,977,619,28,544,562,798,765,831,253,139,725,615,113,666,704,449,378,398,572,492,503,963,968,724,579,756,112,33,755,209,665,619,393,657,313,649,166,871,857,340,65,614,616,111,905,873,915,270,237,698,162,417,322,811,935,48,793,535,463,790,944,458,446,51,840,140,875,476,785,862,277,10,528,210,252,581,901,959,389,700,716,889,621,625,444,502,699,779,372,203,287,813,810,441,545,796,196,396,684,80,972,5,111,669,635,327,617,128,48,683,150,330,552,554,654,493,42,697,502,868,589,90,791,652,50,92,481,594,303,770,771,554,161,111,777,159,170,318,372,44,852,555,918,487,516,268,822,874,468,140,101,954,85,558,670", + "129,369,760,572,789,216,610,149,922,935,922,231,282,179,347,443,559,484,973,752,288,441,783,968,210,874,354,485,545,551,123,192,662,816,710,35,220,110,543,66,709,798,790,428,207,319,196,361,131,397,119,549,491,530,943,773,806,433,153,571,282,687,490,131,47,610,965,347,172,35,519,161,655,551,168,73,563,200,693,502,490,913,455,324,800,107,73,756,165,499,282,616,310,423,659,529,473,956,30,942,148,550,469,390,624,586,668,518,114,321,632,133,996,312,933,423,614,824,640,324,475,310,387,658,941,261,714,346,749,679,978,791,269,638,160,741,607,115,66,209,899,205,941,692,392,132,258,36,654,300,628,696,757,579,80,308,277,826,974,31,545,459,337,172,364,110,482,60,293,730,58,440,795,940,135,591,655,845,788,192,945,732,504,590,212,153,25,43,45,87,791,599,522,233,304,64,443,447,203,431,184,255,910,165,241,349,353,607,66,887,789,219,916,653,634,217,379,859,471,31,755,285,607,729,778,855,734,492,162,742,37,715,19,109,176,27,531,157,821,972,43,454,109,551,541,713,626,47,323,782,412,610,747,836,38,769,654,742,951,396,364,724,320,46,712,705,542,66,985,591,840,212,919,469,987,388,956,442,345,460,429,667,371,408,280,546,219,642,20,895,820,549,836,687,128,479,732,866,882,547,821,706,514,171,556,786,665,380,120,849,827,776,670,85,458,767,801,51,182,612,144,326,544,231,803,992,189,233,123,180,449,56,919,301,83,843,985,424,958,701,115,562,811,165,310,459,588,172,948,143,606,832,871,128,976,60,831,664,246,460,975,191,392,254,963,272,950,500,586,126,967,889,595,385,454,440,985,4,212,310,33,180,53,617,819,544,387,630,390,152,646,885,611,226,652,419,406,825,738,309,793,835,208,774,780,247,424,281,463,205,771,284,346,480,851,861,555,425,158,467,685,644,0,6,511,529,843,898,166,419,758,296,137,573,230,1,696,7,530,791,55,632,944,782,578,528,965,155,964,508,14,87,267,108,208,856,15,995,712,680,836,745,969,326,522,119,396,179,725,146,390,225,18,857,374,606,184,485,516,128,216,573,739,960,859,867,737,443,828,907,510,814,910,65,835,10,829,406,711,498,180,686,170,258,651,812,11,338,842,476,79,480,49,902,312,266,791,348,183,947,715,319,853,321,822,898,382,34,992,576,702,303,645,743,682,850,404,241,608,129,529,494,790,714,807,238,929,248,222,84,690,113,918,245,588,860,872,419,159,952,215,661,82,106,396,988,617,289,317,19,645,801,720,470,987,207,738,692,465,600,141,907,126,206,444,506,262,370,143,241,469,879,661,863,885,831,659,646,335,980,221,548,895,617,464,102,516,241,535,18,614,520,217,279,961,381,864,583,447,264,882,847,931,338,132,865,317,547,787,280,643,245,19,409,887,262,968,207,411,420,906,53,129,441,630,175,673,590,466,881,151,380,50,698,331,206,978,461,266,435,834,235,238,59,211,716,98,960,648,332,733,316,759,779,643,700,124,625,804,89,113,359,418,765,708,968,924,137,60,69,657,217,236,954,667,318,859,935,918,219,910,893,208,59,436,971,28,983,716,268,103,955,658,241,490,209,35,952,548,86,875,722,702,795,965,610,317,127,477,742,47,71,681,718,949,894,882,978,320,4,348,949,928,566,47,198,579,126,472,834,670,305,485,524,760,349,199,532,783,638,534,766,714,466,35,74,475,298,109,607,794,561,110,697,871,682,733,611,723,884,685,397,254,905,707,819,150,145,926,501,413,376,252,644,788,147,607,219,163,830,227,891,170,39,766,475,880,392,752,702,667,1000,308,657,342,61,364,560,837,623,758,711,868,9,215,380,452,920,279,967,664,541,76,931,668,703,917,28,861,903,135,874,746,396,420,517,60,975,492,251,114,797,432,566,404,431,518,237,884,618,814,152,620,857,409,474,218,371,937,781,544,959,64,48,119,400,263,464,724,226,440,232,103,181,6,222,233,568,409,712,549,466,657,472,806,511,490,858,540,105,63,683,464,296,430,200,856,123,631,497,730,614,249,214,936,271,463,74,281,140,769,754,949,668,478,134,219,425,469,517,495,105,519,202,326,595,75,178,728,636,824,50,559,146,734,556,867,986,431,451,496,213,825,716,158,634,36,121,16,785,606,902,788,644,657,964,956,211,447,919,496,134,473,242,847,631,555,613,359,956,405,304,598,219,506,955,345,761,6,331,183,606,582,480,306,780,811,954,291,832", + "637,25,96,399,268,738,344,993,577,158,945,750,376,314,579,71,456,268,579,995,243,645,386,338,673,231,625,351,369,984,992,28,68,801,559,68,538,79,33,553,181,754,824,728,69,87,770,179,756,427,131,89,797,728,401,848,831,710,740,759,336,382,886,261,364,753,674,279,97,911,136,715,227,340,729,269,512,952,914,790,476,799,685,353,937,921,749,290,106,782,691,268,183,360,289,55,384,921,322,698,982,157,154,842,466,923,853,405,533,747,672,960,552,60,366,359,543,363,728,458,757,232,678,941,160,19,24,5,248,664,318,326,698,494,529,388,705,783,986,956,480,309,423,30,488,658,167,153,903,821,867,615,796,157,575,40,985,634,330,685,60,127,188,848,720,671,578,120,619,433,922,593,886,143,909,798,986,574,999,390,652,608,842,388,858,196,375,234,791,365,533,213,41,89,325,328,594,205,550,421,399,247,151,429,655,795,288,803,617,777,471,624,135,931,357,982,88,229,486,570,520,983,571,538,707,133,458,891,290,917,961,122,123,87,843,280,408,230,113,90,676,348,265,461,3,637,278,256,477,590,751,38,151,722,811,573,464,368,124,978,880,73,412,15,536,250,992,44,995,923,790,851,114,899,762,853,942,386,274,873,754,275,72,705,144,102,507,604,656,531,371,521,475,337,153,738,597,276,924,783,289,739,287,231,35,439,707,533,460,931,429,19,770,82,228,639,473,723,103,465,31,716,508,145,764,357,686,39,738,674,225,107,401,48,936,107,935,291,719,139,117,711,729,774,485,233,681,382,385,718,260,338,74,674,422,441,279,823,491,805,172,813,96,236,251,233,5,163,77,39,866,216,762,218,247,834,794,807,317,475,951,568,731,532,215,39,620,24,54,296,571,315,578,951,830,960,478,808,273,278,412,795,613,592,454,889,169,265,258,454,363,63,559,70,316,942,817,617,835,582,470,621,6,0,469,440,731,47,743,302,374,231,121,19,632,942,591,849,161,419,486,5,992,798,180,493,941,240,897,153,469,427,328,216,210,919,212,240,783,640,746,156,828,32,395,841,525,803,616,803,161,485,855,966,986,64,608,984,671,63,333,382,761,505,734,588,993,552,941,35,294,92,134,806,545,647,267,141,7,340,455,766,636,845,550,803,359,523,140,448,346,165,914,188,625,970,171,416,683,689,952,252,16,628,95,949,473,657,288,85,771,965,983,576,587,8,559,345,721,310,33,733,4,383,862,279,23,803,827,712,824,398,750,662,114,651,505,638,193,423,76,899,956,765,924,771,91,57,957,468,228,660,775,388,994,966,723,860,226,498,500,3,636,426,112,590,658,222,89,789,260,677,797,943,841,685,547,410,335,956,927,145,480,333,635,666,889,134,253,762,518,644,921,211,300,117,587,212,409,895,426,977,725,83,92,430,76,867,951,670,572,391,134,280,235,25,784,222,149,464,353,705,243,668,16,339,661,511,421,63,868,702,426,774,224,309,680,457,652,74,128,89,22,478,626,750,897,808,660,164,192,177,68,315,669,241,101,61,687,546,220,340,772,898,43,956,130,206,791,50,771,656,869,986,789,390,670,294,322,41,753,271,265,904,637,96,866,8,696,883,639,74,97,228,851,58,985,953,243,60,174,2,210,521,795,128,581,104,469,197,39,353,443,979,28,560,373,461,695,36,5,95,322,468,164,425,606,145,499,28,877,482,812,498,753,907,956,89,50,543,750,502,266,115,131,186,333,186,154,217,597,522,220,395,923,532,463,171,609,615,609,425,569,520,990,706,394,977,166,297,76,238,533,604,966,756,731,11,866,434,19,957,577,394,795,475,75,963,280,565,754,690,302,192,933,419,146,603,304,403,952,490,911,30,236,872,439,49,482,854,43,339,948,268,179,527,244,758,24,855,770,770,934,418,107,172,968,967,679,518,690,926,875,147,673,430,443,7,1,188,211,607,95,424,205,614,308,173,251,24,251,240,746,908,202,255,331,837,887,110,712,899,173,387,68,180,233,807,997,73,739,404,238,834,165,10,75,313,80,172,523,942,269,423,663,268,995,469,60,115,307,556,66,77,949,860,697,511,769,703,542,124,334,235,831,1000,542,95,81,468,151,291,199,989,901,254,393,390,196,696,473,839,174,48,182,199,795,388,959,973,254,480,522,696,223,567,134,65,116,895,685,311,218,211,821,796,315,865,684,867,381,234,797,731,370,872,40,680,160,416,533,621,772,761,151,301,133,257,24,270,367,459,735,69,632,49,480,898,493,533", + "876,421,410,353,887,994,751,511,634,519,364,195,438,363,318,760,689,562,852,210,347,489,969,931,584,285,997,985,34,613,983,674,425,443,502,894,171,279,447,123,849,986,38,613,152,203,505,605,494,856,847,118,149,164,412,355,647,18,940,265,653,954,453,787,453,757,806,450,818,855,526,161,570,485,831,728,805,780,567,764,335,162,491,578,53,637,582,595,495,284,470,822,17,265,202,834,906,222,574,809,723,735,245,381,56,117,721,518,697,112,316,532,809,184,19,47,444,127,233,915,596,959,670,805,418,312,51,716,712,226,435,187,725,704,582,548,984,606,707,9,374,179,798,520,92,713,899,625,349,250,265,61,986,587,190,832,405,758,828,386,587,224,941,808,338,941,660,413,702,509,240,492,577,52,922,636,454,325,242,33,34,626,379,854,530,812,537,615,948,516,856,509,68,800,347,9,922,382,697,59,933,960,681,475,783,832,783,347,962,195,605,543,677,537,158,208,737,137,54,584,17,570,318,944,924,481,149,788,660,694,889,77,583,527,503,57,498,469,698,48,582,877,761,190,625,274,497,469,281,191,369,435,665,986,87,749,869,788,140,463,666,164,774,975,740,685,851,584,39,668,212,446,36,754,431,462,143,641,793,695,514,333,478,433,561,619,638,808,111,696,227,430,195,537,850,505,56,125,976,322,254,806,976,904,310,237,888,284,374,705,892,92,237,382,425,79,457,67,687,551,269,741,849,166,926,740,917,921,803,58,975,355,780,490,251,262,639,133,32,741,488,71,963,332,71,770,755,354,775,798,14,344,573,77,736,695,145,947,378,775,199,225,283,879,230,738,535,759,811,558,466,996,612,807,642,973,226,895,71,16,789,740,657,273,599,131,226,138,307,651,268,57,12,181,13,221,69,320,497,999,774,448,438,907,207,805,949,627,822,8,880,7,919,207,241,545,477,923,457,599,766,350,511,469,0,362,248,846,188,177,654,497,367,260,551,794,451,637,909,283,341,748,333,411,672,570,791,656,113,453,623,765,173,895,851,30,802,402,751,884,398,834,389,628,783,832,310,642,416,207,425,732,717,658,902,200,509,11,214,962,31,515,668,475,925,235,29,808,399,845,23,895,922,817,888,930,111,962,863,727,80,913,866,463,746,211,368,478,494,869,672,92,53,724,280,702,816,56,372,292,56,491,449,124,127,920,282,533,525,229,363,897,761,632,17,293,623,984,714,937,407,547,266,223,111,210,710,815,942,746,15,586,860,750,459,700,906,181,264,405,234,731,317,147,645,251,242,324,677,489,827,16,208,7,199,918,766,403,29,83,980,431,109,240,345,118,216,822,630,628,799,372,632,435,861,987,969,770,113,313,767,524,997,637,801,366,195,96,596,263,565,879,153,365,236,888,123,473,648,23,119,207,945,466,623,983,218,426,951,904,974,10,102,59,130,101,590,972,685,276,268,780,24,295,972,83,438,896,186,88,419,253,344,700,984,167,512,486,442,289,572,474,276,683,668,818,142,272,117,972,313,486,859,420,307,853,695,936,109,962,939,456,659,539,473,355,148,304,591,30,413,158,371,461,476,529,944,760,917,965,945,535,364,887,62,251,16,188,296,679,100,481,207,565,174,643,294,418,806,517,694,998,105,727,294,356,252,97,367,982,483,151,297,931,770,525,442,114,741,683,135,894,37,860,772,446,789,94,174,927,663,221,761,989,116,162,93,634,530,134,252,217,444,393,376,357,625,753,368,282,774,861,612,757,659,529,340,325,673,203,808,232,948,801,693,809,90,220,5,86,249,327,375,544,864,496,723,14,786,477,951,823,282,130,705,162,243,721,477,690,94,585,6,543,405,866,802,94,599,909,936,579,604,415,737,407,59,263,544,624,893,306,369,615,290,994,463,367,214,34,508,538,675,383,692,852,108,502,275,539,184,980,608,554,655,715,209,312,509,721,418,581,704,396,453,622,364,171,788,736,265,321,542,820,930,649,856,831,733,758,628,387,994,221,676,818,600,694,477,48,927,119,405,391,358,840,397,405,802,292,246,575,329,821,516,77,970,376,466,420,508,291,692,771,218,398,347,321,584,485,467,606,876,572,864,51,549,35,366,311,388,515,507,902,530,11,501,205,824,269,283,612,221,167,501,498,452,473,863,440,92,82,356,61,782,588,762,244,288,295,988,631,718,384,272,48,7,865,895,201,947,708,151,877,962,361,471,643,791,884,308,476,16,139,47,616,146,514,847,435,766,908,374,450,767,603,165,525,801,481", + "293,622,175,828,224,171,510,918,401,881,507,347,168,959,85,65,189,740,98,52,157,219,829,610,803,874,105,113,659,308,906,955,714,909,796,669,76,221,785,325,306,556,663,490,396,304,716,55,836,183,571,683,106,457,326,550,185,740,404,161,432,926,300,197,359,734,876,491,898,90,431,61,754,780,410,202,961,246,818,196,469,230,721,279,268,20,357,112,36,121,947,206,995,762,36,413,868,956,652,620,140,850,622,739,308,821,951,38,258,572,513,886,906,887,901,299,607,137,184,575,156,270,232,41,241,428,786,856,90,869,401,532,579,269,305,290,168,821,878,633,861,910,932,564,371,126,160,985,14,684,941,878,361,480,507,768,142,700,421,132,646,152,452,219,326,437,914,872,636,579,706,485,103,267,815,184,305,554,317,428,790,693,634,67,664,914,503,409,949,391,60,577,287,434,627,635,717,192,392,669,403,873,798,769,210,495,635,272,507,82,220,334,708,289,281,903,73,482,225,478,916,954,713,688,894,258,909,48,911,120,989,781,197,458,403,189,327,819,662,812,654,857,573,412,167,377,190,636,336,800,178,813,697,22,974,148,371,74,877,799,303,995,808,214,589,116,118,358,880,584,375,553,563,374,891,840,28,561,493,27,674,570,338,432,740,989,698,291,52,259,475,726,888,152,161,125,621,207,299,672,21,927,918,851,823,948,399,296,364,575,986,414,233,529,896,488,469,313,792,123,925,951,255,269,969,491,578,568,884,842,565,884,383,182,148,57,606,923,321,999,4,205,262,143,879,621,777,1000,290,380,222,762,550,848,928,341,232,229,333,347,110,925,161,660,724,904,288,387,708,329,81,983,799,24,641,479,908,265,331,904,584,544,990,701,964,184,350,282,701,685,96,477,87,132,700,155,294,496,32,534,229,350,955,344,66,790,17,513,80,122,118,885,698,37,594,349,517,505,840,92,469,104,529,440,362,0,796,362,397,198,904,315,849,690,509,226,120,293,100,438,349,432,985,815,39,568,166,403,222,377,65,29,473,574,917,50,698,194,157,729,918,744,655,657,468,349,850,534,507,352,909,225,177,847,670,415,129,984,639,912,618,933,977,9,406,618,349,507,600,752,9,424,371,45,219,860,733,812,728,563,196,137,455,440,694,601,926,838,111,105,946,532,417,804,650,270,130,719,813,892,440,967,596,414,209,368,733,349,537,350,936,700,213,70,606,643,941,212,710,904,802,310,341,406,485,987,272,877,50,78,254,50,108,117,214,507,168,316,569,51,385,39,585,122,315,509,340,907,830,872,497,954,877,907,2,95,707,379,619,189,851,229,55,321,879,142,455,175,106,761,858,152,465,22,402,170,452,290,678,277,4,401,54,143,404,849,399,722,390,426,861,301,136,86,645,279,391,962,448,23,771,754,526,730,398,423,452,937,711,966,279,386,999,933,698,853,355,339,110,58,133,284,977,793,70,985,707,872,283,75,310,757,331,126,655,947,163,184,308,25,423,596,305,362,388,676,209,560,964,517,876,19,89,347,345,150,527,245,929,816,289,24,791,718,279,69,918,771,332,498,368,743,563,472,89,175,610,95,214,685,237,590,575,791,295,421,678,42,809,472,559,467,200,495,93,89,850,205,644,153,297,528,292,468,45,358,32,391,393,343,181,740,829,911,306,581,884,293,272,128,685,650,267,186,578,661,772,863,732,986,554,772,119,134,13,831,56,767,22,69,363,916,448,83,241,589,918,444,399,228,392,564,651,638,964,651,931,5,369,298,329,228,251,761,508,216,816,241,394,299,195,974,921,453,286,699,785,837,658,769,39,280,974,61,826,527,666,230,689,685,169,811,15,869,291,109,294,993,434,175,39,467,514,770,289,750,122,435,900,785,912,602,104,274,724,157,829,25,452,902,446,452,938,251,70,417,129,927,209,613,540,334,977,306,580,446,730,300,290,883,649,882,976,969,888,248,133,55,485,685,745,604,565,544,681,176,647,611,285,383,477,505,762,469,737,562,820,374,373,409,782,433,411,398,529,898,364,61,754,714,948,971,130,431,177,513,76,894,600,324,64,802,869,971,966,409,135,678,526,383,282,550,465,519,873,460,373,732,241,343,38,494,875,843,266,370,115,267,869,37,317,674,590,85,194,250,773,329,186,255,330,147,391,727,616,696,924,385,183,869,22,599,346,979,752,962,225,623,708,423,314,464,944,174,377,714,138,808,482,108,821,457,443,959,22,777,463,377,104,283,569,804,509,848,658,587,9,86,800,796", + "194,846,731,763,574,174,120,356,917,517,932,194,75,641,86,523,414,571,81,831,767,409,420,825,205,90,326,804,893,306,631,315,855,601,846,527,567,83,204,7,608,715,464,75,958,311,240,644,448,238,673,468,429,420,416,43,867,124,363,507,627,477,454,254,865,426,461,321,798,838,148,334,756,157,773,935,287,698,330,718,53,719,990,919,881,315,938,421,831,107,116,702,283,424,303,967,74,491,795,686,108,309,228,993,678,351,487,329,453,167,278,886,631,701,131,656,870,373,106,422,33,260,455,425,857,703,496,107,711,839,959,900,635,180,697,559,900,651,565,765,460,308,994,583,697,503,760,205,315,538,967,328,871,36,558,849,902,655,104,842,721,232,485,706,178,104,588,874,573,567,78,731,563,34,814,486,42,8,886,19,211,930,475,220,766,180,788,483,810,918,866,829,478,398,565,257,427,86,313,686,436,304,279,646,672,912,548,306,559,216,76,721,300,238,428,856,332,689,664,372,2,606,928,197,282,893,677,846,404,434,118,520,854,215,414,893,718,870,256,661,124,157,727,258,64,61,420,546,824,593,803,630,909,963,273,781,289,323,167,870,943,539,374,553,417,550,438,410,657,587,249,143,968,585,143,921,281,612,428,623,858,480,370,216,101,3,143,810,749,593,352,107,590,171,671,259,585,609,813,74,888,565,261,455,229,674,506,120,612,923,155,713,492,356,498,278,225,973,651,920,120,201,614,754,577,214,97,265,129,855,68,729,971,508,215,917,750,452,10,692,696,19,152,787,209,259,508,807,596,276,895,529,209,906,379,975,154,904,801,607,749,989,621,902,464,814,857,994,506,263,47,361,247,93,222,935,903,466,683,199,576,683,345,269,90,963,284,278,763,884,818,514,967,394,99,952,370,594,738,693,82,505,425,911,819,263,234,854,623,650,393,830,949,348,645,195,413,490,752,678,843,76,843,731,248,796,0,519,118,846,874,842,487,752,700,144,661,380,15,236,215,872,742,786,943,160,739,508,535,522,720,854,94,590,852,77,535,45,76,277,218,730,863,386,962,484,259,745,914,474,565,155,196,328,395,792,888,343,404,253,916,308,602,40,738,320,246,257,456,869,279,709,254,14,631,678,220,136,890,841,450,294,743,562,662,408,685,966,967,463,44,932,678,61,507,754,299,854,79,89,410,398,28,844,109,443,132,489,686,613,874,108,157,512,537,622,615,364,200,56,819,283,697,121,605,241,205,15,126,897,269,922,858,401,373,368,560,354,33,472,357,891,7,360,209,724,599,585,221,278,182,546,540,665,748,517,814,434,540,229,431,266,26,896,49,211,62,627,90,677,708,969,756,568,488,188,983,185,667,596,257,234,269,913,303,118,679,571,516,647,11,650,214,19,937,520,40,336,233,914,352,215,588,304,406,206,274,397,781,632,432,530,796,16,611,738,31,288,431,337,390,586,521,799,236,905,694,901,765,109,68,852,569,887,396,786,506,957,811,207,938,490,395,977,59,452,937,205,694,780,239,155,102,946,657,192,106,492,272,623,618,732,677,674,290,902,248,541,940,697,875,123,468,899,892,720,958,218,755,507,454,595,714,237,549,466,734,68,626,538,441,306,879,146,922,835,554,114,40,733,524,462,545,848,3,622,709,547,357,388,529,138,331,114,62,687,747,566,731,657,23,693,294,597,401,1000,134,736,840,383,881,91,817,548,967,868,549,411,269,290,707,843,373,875,242,182,287,510,225,379,838,921,32,689,408,52,449,878,378,262,73,269,197,459,766,15,120,292,165,262,612,391,27,887,808,455,994,702,532,35,630,312,16,112,877,512,547,684,560,176,342,899,715,93,24,59,611,889,701,154,355,258,762,829,406,64,227,108,123,453,331,777,96,322,894,523,564,180,26,721,119,496,842,660,34,118,790,116,529,234,43,455,111,415,292,792,810,495,146,784,208,944,101,757,571,906,432,348,854,878,669,834,575,286,618,686,245,419,110,762,670,378,782,103,10,895,944,906,398,659,919,109,840,689,372,609,432,674,69,519,37,833,666,340,737,911,280,436,636,864,731,122,920,259,437,754,35,365,42,925,338,705,626,669,844,626,271,825,939,377,489,527,3,823,14,186,550,965,497,191,231,952,157,568,961,747,759,688,221,720,767,528,154,343,549,230,136,430,205,686,309,162,974,589,875,972,760,739,426,360,555,844,450,691,237,269,587,639,483,271,464,773,495,580,29,703,945,644,500,773,743,336,438,525,375,777,371,177,977,966", + "102,756,591,588,308,216,104,447,341,629,164,552,439,231,951,667,558,176,971,492,88,80,295,864,110,359,479,109,797,308,971,285,698,538,708,248,917,848,490,603,561,911,676,627,3,955,974,475,474,392,422,946,560,712,758,174,457,207,193,476,906,5,273,827,303,707,191,160,198,100,12,388,78,830,931,437,84,203,140,310,634,462,557,160,880,741,584,160,560,107,813,573,106,596,519,168,903,284,753,767,297,807,561,751,885,497,182,540,773,613,840,213,59,881,462,520,64,664,569,880,950,392,700,541,877,803,228,55,514,159,535,631,670,370,427,62,756,756,627,582,937,386,197,930,447,523,264,893,102,562,51,685,692,34,36,635,902,94,243,147,960,787,562,56,518,13,786,314,33,769,856,317,3,321,135,184,995,782,107,880,610,510,29,535,96,817,691,443,229,487,553,803,512,436,549,17,403,99,816,224,377,545,23,850,707,415,434,530,907,44,38,688,937,562,672,681,239,123,207,12,297,997,355,519,4,627,983,300,512,435,33,188,52,898,975,628,89,807,538,237,660,949,921,344,96,754,114,358,531,720,63,891,479,541,564,401,129,107,918,56,788,132,529,903,995,986,796,111,81,502,425,857,202,231,847,307,588,770,338,371,320,877,31,116,279,481,339,166,306,670,256,413,950,539,761,207,215,465,537,489,558,579,842,974,368,27,272,916,318,746,279,89,926,179,812,733,655,988,660,707,513,564,550,122,762,210,619,89,801,484,309,673,851,357,300,245,238,970,523,933,95,933,757,64,68,65,724,6,861,600,33,116,57,749,702,686,360,263,161,346,708,847,227,196,249,355,461,830,20,52,11,640,181,227,87,139,888,507,914,721,226,836,335,900,685,341,605,802,251,764,79,579,524,601,625,179,80,879,796,500,718,440,108,324,590,401,788,973,566,796,342,474,891,690,579,888,927,846,348,916,881,34,898,47,846,362,519,0,100,50,292,828,163,884,179,374,949,357,268,812,536,797,856,357,745,984,879,482,556,91,507,492,643,878,715,565,759,729,167,623,447,56,128,856,221,367,724,527,435,217,747,26,304,224,178,900,50,758,870,620,521,944,422,766,208,60,161,105,661,748,676,617,698,498,599,674,247,519,937,497,71,436,356,684,86,923,465,189,123,780,526,707,370,672,312,309,297,368,416,924,580,45,786,629,335,543,765,165,558,387,253,22,901,395,313,688,83,558,529,530,813,929,24,216,287,254,672,554,706,319,424,159,84,486,439,744,455,714,22,378,834,294,239,674,717,730,132,597,841,438,967,806,48,345,202,800,237,690,63,527,477,844,564,285,135,42,608,771,64,389,281,308,828,603,711,555,582,500,486,122,423,912,284,669,806,718,524,65,900,866,139,615,880,628,754,420,671,68,213,732,843,751,244,75,777,729,374,633,517,462,408,109,167,842,861,826,525,16,108,405,704,593,866,807,779,746,220,402,633,386,334,65,82,470,517,330,347,841,21,846,672,777,323,453,516,449,669,494,766,391,971,331,948,363,165,557,601,239,966,49,616,41,529,508,377,956,118,657,894,965,487,316,877,851,603,542,128,764,397,54,225,640,898,464,677,845,528,573,57,411,861,206,960,794,364,817,796,619,534,563,705,88,588,779,642,812,250,369,388,21,3,197,92,881,296,682,670,595,118,730,401,779,905,644,244,948,686,232,979,420,239,56,787,206,135,513,359,334,967,519,371,84,475,692,761,927,418,967,121,470,589,116,663,6,830,368,313,574,26,757,943,115,338,296,208,790,898,402,243,106,537,383,780,511,101,375,688,401,964,891,532,794,851,229,772,940,313,297,76,450,116,423,406,137,43,100,263,130,846,570,594,126,269,116,322,991,996,531,849,612,325,621,170,32,859,721,618,586,684,176,469,21,611,9,923,681,612,925,390,887,404,48,74,306,400,628,30,604,762,634,176,366,26,122,573,667,162,216,323,615,630,468,530,574,490,891,137,176,814,122,721,809,327,946,291,248,634,109,60,242,265,252,773,705,654,326,975,519,638,292,59,651,100,532,418,248,907,863,257,505,748,218,987,714,245,511,328,886,790,945,399,275,310,40,395,854,551,306,78,199,952,237,830,991,332,254,618,393,726,167,459,682,832,82,12,705,957,779,342,499,73,254,799,513,848,829,284,666,206,492,845,734,512,423,523,997,147,517,131,124,100,855,592,924,599,860,334,287,472,498,553,150,782,256,490,211,757,35,588,444,589,214,403,350,810,313,304,455,627,30", + "153,686,318,735,86,51,959,999,552,451,869,823,314,604,627,99,490,631,50,514,316,519,115,69,506,560,811,599,879,873,188,919,946,462,589,281,745,590,757,143,106,88,3,23,190,708,827,550,459,330,576,427,416,769,809,257,399,726,493,448,13,34,403,572,979,475,880,116,248,322,151,12,614,481,383,339,767,196,513,820,849,686,325,527,268,162,741,792,414,591,384,500,603,862,719,920,696,27,384,926,541,805,519,624,593,383,204,68,660,865,572,809,378,132,612,53,961,273,355,57,617,863,668,317,258,666,708,83,174,419,129,965,640,620,827,219,719,232,710,6,817,9,632,583,993,40,290,227,386,268,322,255,582,839,281,550,199,382,466,814,147,690,675,671,690,80,336,164,501,144,903,34,773,565,952,479,638,5,510,512,763,22,657,254,440,217,285,336,498,263,369,663,238,590,513,936,170,256,327,221,523,858,480,105,511,267,277,881,789,331,712,580,481,603,427,832,333,632,516,856,350,396,946,580,828,671,380,607,456,210,303,124,416,74,152,688,443,480,624,124,585,295,498,78,585,46,172,275,932,76,608,397,251,696,404,859,393,378,995,61,785,884,236,225,250,294,369,414,826,691,214,531,956,194,410,638,150,378,766,335,484,582,995,309,364,858,278,108,490,182,712,233,382,964,640,381,488,473,857,965,12,449,786,947,849,55,489,629,268,178,941,406,61,206,450,595,914,852,116,854,168,562,410,219,766,78,428,970,819,146,694,525,39,816,989,327,552,904,225,212,985,776,579,194,984,70,172,528,103,150,578,261,117,729,120,706,181,555,532,338,201,98,39,486,807,401,797,575,919,139,371,717,80,329,642,887,607,314,100,114,172,231,871,860,750,204,534,832,931,772,80,817,734,647,302,743,404,723,899,793,380,771,488,201,714,38,971,826,235,574,993,550,186,595,716,683,712,516,670,373,45,380,166,743,188,397,118,100,0,254,565,946,777,482,625,377,70,305,802,735,152,358,962,486,156,807,493,195,832,874,285,921,774,604,116,207,404,677,212,429,964,803,371,996,662,365,710,671,255,855,702,86,251,407,805,655,414,813,985,688,89,524,171,126,683,859,429,341,441,511,997,948,978,668,543,186,779,592,545,854,308,821,635,667,164,962,681,84,350,520,883,791,711,524,184,526,382,212,352,446,874,429,413,779,893,981,553,112,730,957,756,906,810,104,299,8,460,843,792,188,76,6,534,349,849,495,609,894,565,826,420,102,205,734,554,774,206,14,938,732,148,467,99,722,76,176,210,72,385,263,56,233,347,702,689,718,639,418,529,311,176,822,955,202,112,806,533,846,231,824,721,556,958,944,999,811,909,130,560,629,722,995,102,957,226,874,28,601,303,301,745,534,253,251,408,183,273,86,771,32,104,681,663,875,86,684,929,5,975,399,233,114,907,825,525,336,518,598,846,155,166,750,924,699,299,242,58,256,505,982,433,507,964,716,332,696,680,947,935,996,469,318,379,355,606,953,31,298,491,177,923,883,405,85,339,71,137,456,476,585,262,629,372,322,26,31,81,648,281,973,743,915,608,784,495,408,592,133,181,109,688,90,558,795,248,587,403,757,6,481,951,748,363,982,224,863,82,153,779,316,986,235,647,565,331,717,148,474,495,11,487,171,655,691,67,596,287,915,826,466,817,545,520,242,971,443,202,930,330,451,130,934,358,734,358,247,541,774,39,647,604,357,618,99,668,689,553,608,60,863,401,432,15,389,233,587,814,210,873,244,350,5,787,876,918,327,601,432,885,535,630,291,544,362,546,445,640,285,799,391,595,276,300,361,255,561,693,548,596,330,711,120,720,741,630,953,367,711,65,300,697,934,62,168,888,962,522,845,280,914,136,884,892,772,520,246,659,186,70,712,116,116,894,450,838,441,95,186,931,288,583,6,14,571,736,376,220,339,898,328,529,111,620,592,888,377,311,863,3,735,175,64,338,675,674,385,423,777,989,349,762,462,821,218,203,984,325,831,398,645,346,656,59,857,449,597,1,864,696,433,895,755,989,735,899,535,148,582,332,912,260,118,226,226,717,621,287,84,853,993,480,316,380,482,834,773,865,209,664,332,328,735,367,809,264,465,932,139,227,294,84,795,636,118,502,863,405,574,99,63,671,910,605,928,997,414,668,964,560,366,363,862,805,230,439,947,593,117,627,727,147,372,46,349,172,423,876,211,848,245,509,363,673,496,44,822,434,255,665,279,26,332,29,226,764,247,193,663,551,718", + "903,176,731,331,348,175,131,173,404,427,183,598,507,131,479,818,601,377,457,213,639,904,490,283,419,382,465,901,517,274,875,980,564,42,582,199,305,3,59,434,315,953,91,991,17,388,309,632,46,766,681,110,252,54,971,847,810,180,11,655,791,313,634,666,450,568,405,181,390,559,777,192,199,57,657,66,834,271,677,566,676,296,29,295,135,969,887,887,837,68,209,686,890,710,125,220,966,382,925,274,465,75,766,705,96,52,277,415,616,731,774,94,906,753,296,992,860,659,502,636,349,206,303,893,428,546,50,941,237,585,419,578,844,824,62,889,324,824,550,98,614,403,207,876,242,363,630,265,807,150,842,529,467,796,787,480,945,604,440,450,668,775,926,326,905,379,482,530,995,800,50,739,326,729,403,900,576,84,729,217,437,858,760,721,810,672,859,206,852,296,605,620,667,182,940,526,210,631,422,795,542,839,815,142,537,167,732,754,702,746,437,547,330,950,410,317,50,78,463,355,355,959,922,159,139,437,430,375,585,531,111,485,95,433,828,889,971,95,371,861,505,264,605,56,399,558,642,214,929,315,680,35,848,681,444,411,759,110,420,400,273,125,303,243,97,184,665,458,888,370,852,748,982,778,119,199,407,480,935,889,739,620,879,946,53,902,601,806,768,578,228,735,506,153,892,551,586,903,704,584,669,845,851,457,767,817,900,378,949,879,712,11,21,947,216,857,562,338,962,172,167,5,12,709,478,480,109,708,233,485,264,885,579,851,664,442,96,152,384,691,833,352,527,885,732,788,485,943,476,650,144,438,394,756,694,588,447,385,21,720,793,827,701,426,25,798,322,80,797,426,220,122,495,887,971,890,185,58,784,290,933,914,214,871,833,426,617,873,447,893,26,826,428,466,522,904,271,670,881,707,108,712,701,914,921,326,368,309,217,837,49,768,737,601,8,216,427,626,7,940,248,733,419,302,177,198,846,50,254,0,123,8,27,437,594,126,14,469,462,171,792,792,990,68,816,382,535,760,929,285,509,41,33,579,452,868,664,974,652,835,788,467,39,58,900,380,85,798,162,588,712,204,409,136,81,118,831,840,132,59,539,878,431,802,44,792,200,950,92,354,263,763,634,410,938,450,416,904,595,89,313,833,60,65,479,700,868,958,836,638,165,393,368,215,652,434,893,850,22,941,563,432,327,643,488,863,59,432,210,245,930,468,733,139,521,523,283,727,428,752,224,294,251,678,251,474,200,318,773,793,291,773,828,496,845,582,759,145,339,557,33,663,137,71,422,663,835,981,826,287,96,636,819,301,949,784,814,705,458,236,834,503,545,355,409,41,903,431,786,348,981,226,220,646,417,532,631,595,308,538,428,186,513,820,380,917,700,626,648,208,670,360,995,116,601,854,890,793,379,394,166,682,374,918,411,422,789,492,218,158,881,603,451,246,112,487,241,468,814,716,703,928,602,521,664,803,280,510,906,910,174,889,782,925,849,288,476,602,201,61,968,701,867,406,791,172,545,694,47,52,238,275,588,70,427,156,121,246,253,357,763,686,21,540,652,594,392,41,251,6,880,763,237,74,101,321,750,985,864,254,30,292,741,759,32,345,45,103,732,213,929,323,519,318,945,800,336,459,409,523,949,599,332,399,864,292,758,467,415,196,500,803,367,469,288,119,854,838,328,286,305,716,661,710,262,612,273,628,701,755,556,740,327,503,443,385,714,793,820,985,210,79,942,612,703,995,646,360,309,668,605,525,512,255,591,21,592,39,764,685,926,338,922,261,271,50,972,769,104,536,312,654,113,191,637,961,453,290,474,609,805,118,318,133,146,742,678,930,365,647,116,99,478,673,923,291,342,469,749,799,810,269,841,927,311,24,498,483,792,895,919,560,881,155,392,882,501,731,691,95,883,955,128,264,380,763,947,286,830,801,24,529,147,364,458,687,499,903,293,852,854,715,933,538,426,131,213,649,58,244,707,837,574,194,144,200,199,477,866,431,344,624,422,660,647,307,796,233,183,920,996,744,830,424,449,903,674,469,462,958,817,848,121,741,780,469,221,325,147,602,561,841,759,577,911,49,595,826,635,924,839,473,841,738,858,149,623,502,728,209,422,908,510,864,287,35,546,338,48,77,711,670,570,74,519,429,443,388,15,499,60,347,921,679,475,819,5,670,112,998,617,153,617,382,26,101,978,339,3,648,512,613,941,176,157,155,901,811,293,242,420,419,849,863,807,387,899,90,128,998,601,986,531,843,268,22,398,976,409,178", + "414,583,431,837,942,878,925,125,197,619,839,251,184,973,628,974,424,683,708,777,341,597,22,837,679,907,92,844,967,321,34,398,763,192,225,251,202,546,9,378,317,981,93,267,386,739,678,618,332,552,437,672,199,74,898,518,17,980,198,145,542,460,697,575,901,119,20,798,83,599,678,579,169,99,184,716,81,288,632,362,867,401,808,419,98,309,977,396,710,28,396,360,695,109,645,626,87,976,985,134,45,916,972,23,455,388,931,48,74,970,782,848,687,492,648,574,971,923,772,36,227,754,227,735,626,312,32,344,259,812,640,188,309,157,771,42,46,369,865,59,124,286,942,610,17,633,365,332,483,244,824,58,663,695,51,880,729,405,961,108,744,804,163,900,743,720,357,599,220,642,630,993,870,173,27,47,515,760,992,143,572,444,480,968,521,918,621,405,191,79,276,987,578,515,883,954,815,721,69,336,836,464,483,707,507,620,418,231,361,355,994,516,606,545,309,833,318,415,671,78,152,50,53,482,151,639,858,25,285,938,225,550,432,169,982,154,735,571,583,430,708,909,834,639,966,373,661,670,345,507,510,11,942,273,245,53,936,17,403,301,506,419,127,726,398,365,989,283,271,310,464,746,587,509,302,943,83,755,730,398,983,420,973,152,84,446,346,690,358,832,244,96,265,258,814,757,907,709,26,482,477,945,20,703,228,655,562,595,957,72,569,391,467,208,17,925,813,500,539,662,397,319,583,620,123,420,111,789,480,315,841,786,873,76,661,230,484,893,559,309,377,561,558,505,537,813,984,611,409,879,983,339,153,330,802,576,611,988,928,532,890,160,887,867,587,278,528,214,170,289,799,360,456,195,893,693,413,406,735,582,525,85,229,340,698,251,656,196,125,486,54,908,949,51,160,57,249,506,622,121,574,764,852,828,337,824,669,65,767,849,400,662,722,276,922,934,50,182,715,784,801,309,758,374,654,904,874,292,565,123,0,727,229,574,451,30,657,239,717,25,936,727,574,67,177,655,20,218,685,882,756,818,812,80,726,864,611,801,444,225,59,191,347,875,81,452,772,676,361,263,569,879,403,127,456,565,625,544,421,70,765,658,242,217,61,844,701,636,44,917,471,399,346,365,150,890,110,905,406,202,285,162,839,426,79,656,929,923,497,403,553,876,22,296,731,682,836,706,235,517,514,67,243,760,170,612,233,836,101,770,306,85,341,888,345,411,400,684,38,627,94,313,489,161,630,702,691,101,628,182,903,897,937,415,393,69,706,670,526,913,894,930,502,109,685,102,486,373,989,504,51,743,238,848,725,205,817,551,566,644,8,840,904,236,411,86,895,521,145,184,717,83,824,846,399,300,854,158,12,953,36,100,705,528,532,276,59,125,468,885,928,81,604,69,236,286,523,801,348,554,363,436,750,279,248,162,152,862,188,88,448,159,722,61,878,708,939,865,280,355,922,955,225,501,867,609,177,238,512,275,232,295,848,151,529,619,393,655,403,384,686,123,492,463,151,637,966,154,437,341,715,95,951,525,836,719,720,111,39,619,173,511,913,807,182,740,473,270,769,967,420,175,988,714,420,318,109,753,123,499,413,36,998,562,745,416,150,41,544,260,761,976,617,324,464,995,929,449,35,81,631,547,890,42,431,271,249,464,376,915,949,938,612,93,914,126,462,209,411,636,974,694,901,786,935,439,218,303,409,448,821,659,111,82,566,38,876,252,80,360,196,954,448,388,684,848,11,963,993,480,177,413,665,831,661,684,215,216,775,912,485,857,760,905,462,925,18,433,465,68,516,322,257,784,869,919,869,235,220,271,667,491,828,168,159,196,12,193,983,502,579,598,955,397,741,410,298,799,875,981,501,867,316,73,953,802,466,825,695,778,494,18,166,653,64,498,356,649,204,551,779,519,700,370,612,384,631,168,797,194,519,570,524,328,33,647,596,673,670,562,830,422,599,123,81,609,231,180,916,974,973,415,784,135,845,231,357,252,68,422,766,759,498,736,2,399,555,30,316,329,857,34,979,741,81,69,249,977,419,387,19,481,823,745,815,228,776,802,872,40,171,468,920,810,804,429,704,593,921,856,858,596,355,845,855,437,316,599,274,471,156,190,999,44,131,706,824,63,989,657,721,215,904,190,180,197,570,997,940,358,285,558,141,591,617,443,480,666,733,393,742,736,33,766,838,744,936,324,793,824,415,472,101,655,811,472,475,201,23,360,611,750,520,181,807,572,125,824,440,641,511,926,339,402,63,669,318,641,347,308", + "766,435,338,551,839,821,680,654,67,771,943,666,117,433,302,661,500,280,450,265,445,486,507,852,253,266,526,540,13,532,717,518,435,64,864,344,999,972,848,740,734,769,263,474,205,641,598,768,522,68,710,336,135,206,385,298,925,952,950,956,494,119,504,365,884,869,747,13,263,673,489,310,751,326,507,650,112,144,387,568,51,690,923,707,752,793,172,285,729,385,434,607,178,404,697,877,906,144,888,862,382,999,71,154,52,547,12,197,295,103,856,651,590,10,548,229,575,932,200,927,338,991,728,843,859,490,8,438,774,525,80,341,879,950,138,959,164,363,78,429,248,173,205,861,54,988,880,952,280,898,845,94,521,355,455,526,263,696,57,665,755,267,104,680,236,701,46,852,698,889,102,573,138,800,310,635,389,746,180,785,779,979,316,514,828,76,825,645,709,450,946,271,981,421,722,698,79,857,526,634,604,212,951,325,144,912,804,826,570,388,367,270,844,716,196,685,467,515,255,121,923,394,881,210,308,412,271,821,640,86,437,85,574,75,653,482,277,579,154,560,171,767,994,108,119,981,351,504,249,832,140,359,151,671,432,428,251,205,280,689,67,257,515,242,42,791,982,904,634,78,657,646,368,833,98,383,212,849,399,75,103,945,611,807,807,909,812,523,136,333,938,120,639,371,840,739,365,379,754,528,614,611,306,41,696,54,69,745,506,441,595,413,943,421,574,649,349,20,860,480,622,101,641,473,872,447,303,809,462,674,705,675,180,429,747,4,717,825,477,136,533,779,773,224,166,740,154,17,126,454,981,750,553,156,41,693,748,780,112,955,873,256,87,286,187,376,586,75,878,815,841,170,750,414,77,230,419,410,200,298,341,548,997,128,850,748,422,932,512,927,888,59,32,241,858,78,830,683,389,807,86,613,134,490,475,450,995,276,202,967,232,802,189,864,398,851,409,778,880,561,10,145,296,231,497,315,842,828,946,8,727,0,633,718,61,454,338,50,719,432,194,675,478,89,79,115,623,283,178,397,63,706,760,219,828,289,774,948,590,614,835,660,727,286,584,969,868,564,899,893,43,455,301,735,864,550,78,14,83,362,234,764,47,50,298,908,423,819,979,830,803,937,734,375,285,971,704,149,830,261,999,860,225,480,55,279,518,870,38,654,79,292,810,3,806,599,295,185,168,615,66,910,640,796,83,771,640,607,616,816,295,158,455,676,241,490,581,962,993,421,246,186,417,589,657,215,491,348,715,290,93,413,412,180,123,538,563,492,24,494,296,685,673,356,903,961,251,941,844,903,128,635,233,736,428,720,268,516,259,648,57,558,723,785,276,57,621,885,317,706,263,849,673,493,784,42,554,755,494,769,400,596,566,954,59,915,188,126,194,856,472,568,960,830,651,632,973,69,132,59,275,445,208,455,300,924,973,783,743,837,755,80,958,214,271,347,932,273,221,416,504,546,430,754,517,354,502,693,856,935,7,738,956,168,823,585,589,136,523,408,624,571,660,285,160,612,73,23,348,932,180,186,405,363,673,817,721,957,677,442,638,46,985,257,795,277,661,383,42,230,142,63,698,184,324,15,13,250,686,106,78,348,861,1000,58,576,321,879,725,45,648,39,367,354,380,905,914,76,102,960,91,581,604,584,222,98,229,573,686,766,47,3,465,603,764,351,651,401,772,357,66,967,500,812,731,136,733,99,194,213,388,550,755,857,391,925,776,975,383,456,123,394,311,972,939,486,730,703,365,958,656,331,40,924,978,347,599,728,637,818,729,160,760,959,744,211,383,966,93,181,367,882,309,758,415,918,875,705,75,991,732,534,290,367,979,383,33,458,533,962,684,690,965,96,971,884,779,655,843,878,852,594,333,173,632,947,373,646,280,602,22,232,682,279,496,973,169,702,293,775,212,953,969,569,203,150,55,183,625,272,753,941,841,530,438,801,839,989,62,644,283,216,382,798,885,920,324,446,933,479,28,240,771,610,311,426,319,255,834,152,815,708,383,11,434,762,742,969,593,585,639,683,847,839,192,491,577,773,771,231,696,180,573,417,641,812,591,278,174,697,815,984,76,942,9,766,951,322,153,668,863,770,61,812,372,409,822,588,657,121,856,977,37,330,349,782,517,346,54,498,881,299,832,89,789,595,620,640,814,168,92,674,357,924,996,675,273,426,355,87,149,666,60,591,425,167,206,217,687,841,396,690,147,366,543,834,837,702,446,343,937,62,128,245,156,112,833,37,710,636,235,982,42,990,918,845,460,219,302,351", + "368,364,476,855,86,883,736,494,713,557,467,440,90,927,938,774,890,988,337,848,608,789,602,966,635,918,601,883,946,919,77,159,102,288,681,457,414,871,631,668,306,487,263,83,744,126,165,203,813,766,320,130,996,2,155,80,532,659,505,634,688,112,221,305,759,525,453,796,343,918,97,246,179,222,188,501,344,524,302,780,637,167,290,820,324,373,892,811,798,483,618,258,358,858,811,333,136,684,215,178,147,804,392,888,146,287,529,500,963,384,528,238,646,527,446,249,263,902,543,536,2,468,16,603,795,368,157,148,923,221,981,315,267,345,705,440,908,338,880,334,556,734,445,521,169,985,204,158,839,426,842,804,232,12,947,582,962,160,768,478,679,43,763,896,445,755,271,7,114,481,987,408,973,406,98,770,46,510,458,305,268,567,508,961,167,644,391,25,372,92,135,579,950,266,194,313,35,491,200,641,618,785,948,778,887,355,813,473,73,469,49,422,88,222,849,978,955,128,371,629,474,893,760,109,193,214,122,757,35,767,722,88,987,497,960,145,139,668,685,365,909,386,552,317,132,413,838,958,774,584,427,879,400,628,974,667,112,103,801,19,145,799,926,458,503,66,864,196,840,530,318,219,827,166,80,596,577,271,494,539,79,55,496,793,348,612,246,695,587,623,778,340,334,76,383,112,289,822,831,114,545,8,119,131,784,252,469,839,82,240,77,955,923,490,539,29,935,237,190,76,611,186,137,856,569,666,949,741,694,439,673,633,367,731,547,993,135,518,926,50,64,660,206,298,625,911,988,408,696,348,979,842,995,494,247,896,208,552,88,779,885,670,464,85,4,304,291,933,23,492,256,185,469,532,287,639,322,326,177,873,638,623,467,20,302,842,419,235,403,665,276,441,794,789,631,521,160,829,315,721,803,518,708,636,190,910,2,558,761,696,978,451,472,267,919,16,355,601,217,36,162,535,137,121,367,849,487,163,777,27,229,633,0,78,28,988,169,859,996,715,462,898,609,101,425,972,5,891,250,357,593,976,459,293,486,857,714,420,962,530,487,757,453,519,785,774,510,644,921,463,373,309,80,797,462,739,584,473,113,376,847,796,414,539,680,436,210,492,967,584,143,583,387,979,79,370,994,699,817,836,845,486,597,75,205,893,895,399,481,534,548,742,733,480,95,487,41,889,6,711,248,81,548,54,999,708,936,542,848,481,489,99,379,996,657,485,348,615,614,806,318,506,995,912,233,792,585,530,205,877,110,553,284,272,661,779,62,417,587,553,976,557,764,232,999,261,232,588,246,442,311,716,582,782,838,719,956,383,444,990,184,348,909,851,540,893,646,737,978,729,457,583,528,550,467,795,153,663,264,902,590,178,680,343,565,996,658,565,711,585,95,513,269,799,697,3,223,141,966,311,123,121,562,676,131,669,826,266,975,766,922,21,530,123,902,598,138,432,915,981,412,836,454,728,429,831,240,640,596,40,736,864,801,477,855,113,952,537,398,992,363,161,564,977,120,305,884,988,419,596,996,544,78,726,959,969,215,366,799,102,259,479,614,289,156,922,44,236,206,397,25,742,757,692,660,316,717,565,531,120,291,454,30,677,71,284,224,724,796,726,97,242,639,437,989,162,733,278,646,970,944,30,452,506,50,150,584,172,231,522,966,615,795,398,755,586,112,86,220,17,945,90,32,384,558,372,888,47,818,470,565,42,932,443,752,939,470,293,936,674,151,517,130,274,580,9,453,124,533,150,593,562,993,38,453,83,375,740,908,23,475,377,539,373,555,466,745,742,570,213,579,966,180,477,78,712,761,127,146,306,504,714,488,604,986,46,614,270,847,997,102,516,551,862,565,966,827,686,336,745,955,427,927,758,288,842,981,515,20,182,606,697,4,342,805,863,981,56,887,769,918,604,137,118,50,129,250,893,145,278,139,636,199,585,655,271,319,383,182,161,587,61,211,275,543,180,690,857,988,590,469,836,354,56,976,845,757,166,38,672,675,819,759,907,673,834,985,947,180,785,886,845,591,959,668,10,878,224,744,106,290,325,189,607,910,906,695,157,831,811,897,183,102,237,249,730,609,954,744,963,628,87,356,122,451,565,716,819,848,756,763,688,828,502,895,339,409,549,838,80,288,427,908,543,527,601,421,254,439,374,685,841,854,180,183,66,621,805,905,139,582,472,637,910,685,166,676,310,117,642,284,297,35,850,151,41,315,548,809,347,649,111,433,392,277,40,406,365,649,689,7,592,809,730,283,198,351,465,905,863", + "31,415,193,570,52,356,812,491,260,523,271,747,153,515,320,29,574,889,621,874,363,569,267,48,378,93,79,807,361,266,693,894,386,941,624,65,830,697,997,780,891,993,895,75,746,124,188,116,827,558,583,135,691,812,958,615,117,930,367,92,298,563,668,361,10,455,13,325,118,152,253,922,66,663,914,940,582,45,753,706,789,769,137,594,846,986,844,24,229,766,29,323,365,410,224,368,249,477,388,308,992,907,867,243,342,689,350,554,572,714,621,35,878,669,270,61,861,158,118,757,278,157,927,869,681,591,278,59,38,141,810,65,979,225,165,394,229,514,601,887,437,740,166,894,642,759,292,696,348,336,100,785,429,446,837,124,549,860,444,755,515,118,813,689,212,221,934,626,423,944,132,302,355,956,316,606,136,675,645,766,608,786,409,893,787,26,404,178,606,409,593,479,341,476,706,385,246,664,443,698,387,735,545,759,392,276,327,627,357,104,334,875,993,893,633,658,928,73,422,158,925,950,287,954,948,264,258,195,452,814,755,441,21,156,913,630,458,702,94,853,650,471,422,607,206,655,575,488,313,402,852,622,914,442,270,119,300,456,401,793,800,989,76,212,146,262,217,300,448,774,584,838,912,834,615,676,132,230,331,647,703,426,480,454,541,527,960,272,292,249,167,723,795,774,278,103,840,110,40,565,158,88,366,347,633,946,892,297,60,28,216,331,602,494,963,999,244,462,858,993,60,500,980,976,559,26,508,14,441,543,134,569,115,508,215,88,333,714,576,515,551,409,469,480,383,893,944,226,104,205,951,352,105,330,38,314,731,559,448,407,779,711,199,966,107,922,367,954,130,808,796,899,961,283,58,201,870,154,459,688,694,881,980,347,831,592,467,904,646,956,943,923,195,876,787,854,915,682,636,777,10,948,546,557,559,78,273,472,172,558,199,505,724,616,444,650,682,251,460,329,658,532,573,19,260,690,752,884,482,437,574,718,78,0,445,971,637,627,875,265,105,307,212,908,688,910,948,823,735,581,616,93,465,197,511,421,644,887,774,304,966,175,864,115,21,931,883,280,686,170,607,83,356,651,110,818,492,340,549,380,589,615,452,441,654,114,946,936,318,665,741,328,460,277,576,452,862,529,962,184,510,588,438,486,229,204,750,49,424,57,546,4,222,891,298,656,631,346,952,920,643,221,46,924,837,255,233,68,752,925,456,6,819,480,139,357,620,369,22,367,55,903,810,755,654,359,659,947,399,678,504,298,402,747,11,909,280,832,172,506,309,788,441,664,465,164,718,796,338,373,54,771,827,384,517,443,67,362,753,806,58,857,585,951,478,336,132,357,3,425,765,527,580,461,471,814,591,251,26,937,272,905,910,478,141,109,574,957,386,133,732,883,328,930,721,52,463,8,65,430,411,30,968,429,636,661,753,52,577,462,977,299,514,553,10,898,562,101,882,267,750,929,562,999,717,688,2,708,87,95,844,257,661,49,824,457,15,174,548,447,907,564,745,804,151,146,976,358,630,609,113,225,786,557,733,7,815,852,392,153,188,298,980,714,529,192,753,595,710,130,749,926,611,653,982,46,490,348,779,898,461,357,110,215,458,416,221,647,158,771,180,765,654,747,384,915,660,918,592,864,561,559,267,478,117,449,75,183,478,207,236,250,568,735,606,83,647,331,622,361,333,360,479,401,147,718,25,341,621,420,13,279,689,158,778,588,112,31,369,25,132,435,486,570,608,248,968,204,200,168,978,778,354,71,153,610,348,880,348,304,764,636,969,532,798,750,208,309,466,416,96,958,871,32,681,543,752,528,396,380,702,692,494,330,726,647,351,755,100,929,448,176,711,727,335,260,95,523,214,763,544,411,743,561,480,874,28,188,231,291,467,113,169,592,712,385,219,230,431,185,791,992,116,37,759,880,304,31,558,946,115,325,679,567,576,9,123,179,406,706,825,824,644,638,999,399,696,559,887,302,918,150,239,266,839,654,270,714,146,342,65,322,989,30,613,469,69,720,483,539,408,347,414,132,303,173,84,686,435,498,510,314,532,784,932,959,870,869,243,841,695,287,314,274,196,120,375,403,208,28,29,269,54,601,308,225,300,36,726,251,94,924,94,453,151,818,637,790,774,904,799,811,718,672,887,718,419,46,348,975,562,935,776,875,102,34,52,85,640,494,320,56,29,790,307,358,752,218,877,572,836,190,650,64,280,160,591,860,158,678,990,234,572,180,363,373,598,715,393,359,341,142,46,452,911,701,750,985,190,796", + "561,614,735,15,523,825,763,878,556,353,948,400,956,741,643,45,787,589,301,445,933,502,975,238,995,70,249,934,652,311,559,358,94,736,8,439,723,387,673,347,530,44,335,637,517,16,60,111,38,211,826,466,34,936,831,106,730,624,534,636,887,554,576,280,863,652,415,356,106,311,706,570,533,520,379,181,77,611,10,116,941,642,216,958,521,390,58,494,580,245,271,708,434,666,998,871,1,607,223,940,327,184,713,800,700,785,801,578,660,743,800,148,498,505,622,773,698,52,100,665,89,828,68,920,700,577,720,282,687,186,665,606,247,855,351,506,852,589,307,879,598,971,590,279,81,869,290,835,705,712,218,96,477,387,980,657,729,629,67,64,264,732,938,110,648,103,854,833,964,636,744,80,724,697,524,377,773,555,876,125,422,125,897,886,434,440,338,126,762,671,245,465,135,652,602,537,917,594,383,51,751,205,490,291,251,937,462,100,488,413,691,71,862,214,911,577,219,929,620,621,147,540,126,869,993,477,907,229,994,473,381,484,322,461,297,513,785,192,195,205,139,953,867,200,934,330,733,531,804,847,607,368,20,420,362,753,753,352,602,286,794,99,887,192,693,496,490,497,634,140,40,548,319,914,552,825,707,378,941,429,108,869,384,200,733,413,996,519,616,113,787,287,48,495,846,917,21,484,820,147,5,827,809,805,781,8,793,483,889,276,496,625,996,160,850,802,58,389,452,842,167,391,269,820,6,25,861,253,292,733,840,366,247,931,121,919,102,163,312,580,566,828,518,319,586,433,619,762,634,226,751,263,177,755,197,883,829,967,374,882,726,480,458,415,217,577,877,855,197,538,943,36,198,898,308,379,596,932,18,226,167,435,592,22,168,433,830,115,288,149,841,445,355,352,564,716,511,193,192,901,539,508,463,567,290,273,782,211,893,136,387,865,903,458,545,178,32,417,252,193,165,516,230,632,551,509,700,179,625,594,451,61,28,445,0,869,873,714,695,82,510,566,91,289,791,994,455,220,27,96,129,348,546,638,785,807,404,274,780,604,159,660,840,327,463,849,996,624,179,42,71,418,923,217,791,369,466,913,746,476,756,837,798,544,969,87,974,790,763,969,242,605,247,219,753,767,58,23,110,945,134,327,709,69,911,831,791,79,152,973,608,622,617,281,571,58,124,602,665,50,11,698,874,815,258,790,585,953,509,734,454,843,153,129,653,160,617,494,931,440,351,691,340,950,858,442,929,648,806,503,781,254,97,922,462,655,42,636,447,988,280,576,338,161,713,716,862,777,755,101,50,579,758,780,448,245,366,106,736,768,726,463,729,881,280,666,164,806,703,936,262,459,17,98,55,184,909,925,588,146,274,604,819,685,556,522,398,844,528,92,431,911,425,153,907,689,701,71,832,16,550,255,403,4,81,914,346,207,485,369,326,403,95,145,949,179,893,616,146,581,605,718,831,503,571,639,261,226,752,988,600,753,573,821,919,508,111,134,688,986,109,250,19,429,648,146,882,506,389,525,132,253,58,739,844,989,571,938,870,162,862,285,968,894,556,26,172,940,841,952,365,463,169,172,342,471,274,129,233,268,310,701,904,142,821,733,148,764,534,152,33,104,853,996,216,334,853,894,357,215,552,881,840,625,972,191,888,782,922,780,945,33,609,595,380,381,289,151,747,43,893,206,409,168,60,204,64,815,967,957,783,705,440,207,453,459,886,950,756,911,389,57,561,715,934,167,413,523,485,431,464,886,841,855,462,95,392,894,107,229,287,50,797,458,273,770,640,770,29,924,434,38,681,21,369,121,834,266,895,931,342,736,769,616,202,678,541,791,97,392,408,809,911,934,209,640,702,752,957,141,363,234,469,365,970,782,35,845,620,662,30,879,686,709,938,938,29,594,658,256,474,209,478,417,494,592,714,719,169,174,909,180,678,584,181,949,498,984,512,777,293,387,390,92,424,941,653,222,439,458,78,631,611,523,166,73,12,656,378,112,100,177,240,462,601,669,88,162,812,587,195,562,319,671,331,910,910,765,905,816,210,448,367,845,297,503,621,596,749,127,366,177,698,41,500,626,204,657,280,636,300,870,149,894,103,409,429,613,259,994,306,358,555,141,163,890,877,440,787,980,681,402,682,132,390,309,966,270,61,40,20,520,93,296,268,636,684,15,141,834,107,853,522,36,773,284,383,338,720,400,577,714,28,4,23,863,117,65,702,520,916,175,532,774,126,976,539,958,541,489,514,570,812,491,60,318,739,989,778,188", + "537,571,106,700,396,69,985,548,943,20,753,724,392,195,859,711,667,718,823,503,267,558,245,562,983,854,399,193,296,596,790,595,475,266,177,888,906,190,431,680,629,315,960,390,132,706,389,148,719,994,539,814,576,388,393,213,409,151,464,303,132,458,644,440,260,695,946,732,990,818,870,491,710,698,243,642,524,313,920,943,180,366,530,9,591,404,598,470,62,539,240,914,244,486,533,827,799,14,794,767,155,602,925,866,617,155,275,460,47,746,282,970,663,662,732,164,372,469,648,682,916,546,599,884,247,458,377,366,25,230,215,811,122,440,85,441,410,642,661,174,560,97,699,382,10,534,685,83,130,764,426,53,679,804,401,231,310,419,51,906,150,670,968,212,552,742,691,101,151,523,418,46,627,786,299,105,307,286,131,332,594,898,36,598,12,533,452,921,80,730,62,732,430,824,258,749,191,496,265,769,86,208,255,124,586,714,859,339,248,834,194,163,148,852,828,34,681,882,233,129,710,403,612,657,418,377,555,889,11,89,190,901,646,934,561,605,193,171,796,356,231,958,609,57,609,523,200,275,655,466,983,934,871,964,13,440,67,628,731,444,706,755,675,465,126,490,267,60,610,174,583,443,224,130,397,281,376,867,387,11,435,473,730,652,938,18,470,977,846,996,858,567,646,823,403,31,547,618,153,176,919,484,789,401,220,945,218,886,650,10,650,883,525,740,109,513,509,162,863,467,492,183,440,407,817,729,162,584,497,451,705,570,789,80,566,498,244,255,525,961,909,734,428,635,715,873,475,184,887,339,747,130,752,829,920,916,534,602,613,253,528,364,312,431,354,403,610,216,272,941,75,193,319,985,846,320,609,853,556,4,280,314,969,137,668,515,993,528,886,285,7,688,508,672,896,210,57,28,480,641,535,670,536,509,641,16,31,131,685,336,156,853,130,555,356,280,685,126,393,643,988,815,1,942,794,226,144,374,377,126,30,454,988,971,869,0,490,495,430,48,404,335,436,772,538,544,376,714,443,281,103,214,854,752,267,644,331,273,349,112,675,465,448,434,621,200,767,477,865,192,170,136,577,285,913,782,188,197,379,804,834,421,480,523,295,22,246,192,710,698,674,691,442,125,649,313,502,834,645,278,213,910,150,768,75,807,866,161,427,817,293,765,891,217,941,988,20,650,418,894,81,39,349,744,773,371,403,202,786,532,940,942,121,40,329,670,879,151,376,648,604,342,870,518,894,956,939,43,335,116,726,209,470,263,577,640,390,397,213,537,779,305,13,589,565,719,984,437,293,808,252,526,909,381,275,723,986,959,869,904,215,561,507,976,364,172,328,980,207,928,594,617,718,501,695,434,490,920,987,236,678,956,204,384,403,754,749,239,225,76,262,710,573,740,454,179,844,69,284,755,803,924,696,493,179,31,767,371,647,660,820,715,376,377,893,528,792,247,617,801,985,331,525,713,413,730,299,735,202,299,729,881,652,462,915,606,62,813,479,867,375,978,797,348,18,986,429,405,541,677,5,722,915,148,617,32,333,722,138,924,707,611,586,960,649,428,858,356,68,939,611,757,819,436,401,558,209,587,557,867,644,316,487,213,181,519,719,848,786,688,434,801,235,434,151,275,258,340,182,598,9,960,654,841,21,611,682,980,115,954,397,869,294,519,456,884,147,349,4,926,200,35,767,110,542,554,628,636,599,81,541,374,588,571,632,295,649,635,23,264,696,949,344,481,154,537,439,187,482,208,699,518,718,994,122,757,682,862,805,788,356,424,728,756,183,739,958,646,631,79,815,397,361,779,666,677,139,148,792,5,881,7,761,332,870,665,977,106,230,365,578,367,934,444,695,473,602,953,648,248,533,961,93,590,515,986,78,475,592,588,323,652,911,987,276,58,894,211,568,423,802,334,330,395,816,757,514,91,272,241,358,120,593,708,614,830,975,993,32,976,960,613,576,133,502,112,234,58,609,253,769,37,967,480,865,455,912,583,213,249,467,786,810,40,977,964,546,746,25,652,908,418,107,510,32,141,634,869,792,752,598,103,894,568,403,80,435,478,493,6,529,243,217,420,149,518,305,80,456,338,870,250,93,836,338,67,242,112,980,394,663,947,124,53,449,701,14,748,546,650,719,427,338,365,828,11,450,762,515,910,8,163,607,270,796,289,274,245,761,246,364,618,796,850,895,357,497,759,878,845,149,261,149,547,598,732,315,681,881,601,586,41,955,689,882,309,503,865,621,595,388,488,39,325,489,940,898,452,766,132", + "962,145,716,400,839,512,268,653,617,368,334,922,710,680,995,372,220,338,717,944,474,395,190,898,831,406,11,515,738,171,725,539,586,124,770,801,477,819,929,845,16,765,35,130,381,582,180,622,990,491,54,864,960,220,618,60,405,269,130,461,103,329,43,659,235,228,919,458,379,831,658,652,739,29,438,127,897,801,349,575,869,824,614,566,538,77,396,387,169,590,71,207,579,670,926,77,545,965,838,633,637,340,83,406,287,815,566,200,528,132,31,314,818,806,21,252,634,606,452,917,931,370,551,912,108,129,378,130,213,288,330,290,842,315,59,296,717,918,1,826,452,451,970,331,292,399,546,919,6,303,469,747,273,756,337,503,232,539,372,111,517,98,178,628,994,473,759,635,387,302,528,304,4,155,97,824,232,730,430,200,56,506,378,4,420,805,630,162,192,85,230,51,769,491,17,419,136,208,166,887,291,985,862,720,806,378,961,509,5,570,160,974,422,945,81,777,225,738,862,293,744,468,504,487,953,490,606,710,960,677,32,57,863,297,396,779,925,112,901,765,832,7,943,768,831,446,466,162,131,249,741,58,328,559,599,534,897,983,25,467,136,113,453,706,558,42,549,723,106,749,699,33,385,882,710,48,468,581,806,40,238,454,147,720,478,357,656,996,141,88,807,136,327,607,818,202,823,659,3,863,847,113,259,567,503,183,943,887,558,155,436,230,904,308,872,278,315,476,231,793,310,620,577,628,126,425,249,872,44,367,709,772,268,538,599,339,23,538,701,706,475,216,817,487,172,390,791,394,509,275,21,434,860,595,264,772,498,283,643,347,608,17,560,647,480,85,21,122,458,763,571,887,878,160,490,417,869,91,819,395,606,383,902,419,974,504,866,924,902,394,383,251,14,708,763,21,171,706,894,665,907,5,943,107,273,594,614,129,503,76,886,961,469,9,682,562,412,360,81,40,75,85,696,591,451,120,661,949,70,14,657,338,169,637,873,490,0,343,898,655,389,556,98,607,926,415,216,665,68,275,478,925,149,10,907,783,734,963,155,290,836,75,245,708,676,341,608,541,181,471,662,925,131,705,526,811,84,564,134,786,309,273,745,58,787,717,910,316,619,61,442,342,560,659,269,157,814,705,234,105,244,28,76,780,898,487,503,899,75,329,691,554,241,277,986,111,563,670,364,661,820,564,131,255,770,654,153,205,747,894,858,249,929,48,646,325,353,552,318,622,60,403,659,300,669,813,561,443,848,670,588,419,611,404,136,234,966,136,463,525,539,615,837,663,369,832,474,650,241,710,1000,470,118,889,782,706,932,322,525,883,396,111,580,484,397,650,81,889,687,589,879,361,73,452,785,327,826,180,598,841,4,20,383,398,486,592,287,111,27,106,496,829,822,982,283,921,739,906,371,196,158,353,81,833,740,941,494,538,853,793,379,58,751,55,887,930,739,634,203,200,751,52,970,500,26,100,149,421,747,879,756,779,251,363,565,84,639,740,196,332,41,433,131,795,903,250,656,346,803,318,517,658,617,822,509,437,880,591,266,269,669,736,979,682,116,388,781,920,810,657,730,621,757,379,902,265,936,463,869,497,900,837,141,476,13,89,490,558,468,182,55,527,229,788,578,646,527,167,418,912,43,974,174,602,140,709,345,333,179,901,850,335,455,192,107,11,826,699,779,649,67,228,893,425,836,480,18,945,660,840,15,226,180,642,515,7,471,140,134,60,956,108,310,898,586,760,286,671,399,777,597,146,351,607,942,682,395,556,962,987,593,730,1,738,16,864,917,58,317,231,392,745,955,578,1000,244,24,72,806,621,269,993,57,586,52,12,890,933,732,907,968,631,650,418,367,818,453,135,583,813,216,795,946,986,588,254,290,802,899,301,837,137,212,852,446,804,916,752,224,650,555,604,164,362,659,36,485,498,918,563,312,110,692,571,994,823,403,266,434,211,770,892,353,499,886,106,708,665,995,778,129,244,136,549,350,725,262,836,350,482,112,456,603,649,695,303,374,677,733,87,49,911,255,331,526,568,625,731,818,512,233,171,154,981,251,628,703,995,516,806,682,43,428,575,646,636,712,851,103,272,48,326,921,425,961,50,993,802,3,675,530,751,53,654,452,842,961,630,918,482,816,48,420,673,800,391,493,574,354,449,573,921,597,903,402,57,313,97,187,365,503,307,768,807,620,359,91,522,228,387,255,725,5,830,554,846,771,85,825,266,296,265,584,947,199,979,776,387,418,721,73,528,795,217,176,439,535,948,564,289", + "873,888,479,897,841,984,815,600,164,699,585,24,193,902,705,518,960,350,387,837,42,605,680,597,986,70,505,741,975,68,225,967,20,523,924,478,34,684,197,451,531,701,326,512,750,60,167,261,699,755,888,259,39,558,833,407,359,600,736,723,611,371,556,732,119,381,496,106,906,809,536,49,61,37,215,878,880,431,267,153,478,317,831,564,533,161,506,56,538,180,108,857,688,75,462,277,323,590,220,839,485,331,44,410,300,365,42,246,300,971,404,984,603,382,3,277,868,640,580,367,728,801,996,633,223,598,169,983,619,304,457,561,141,232,466,661,672,718,881,236,182,834,111,637,591,227,434,920,518,86,592,409,454,747,206,710,393,661,16,193,470,101,805,866,206,836,69,230,432,670,718,229,939,894,254,181,884,428,903,844,66,258,934,795,538,358,361,307,634,176,863,947,346,235,977,662,609,570,140,946,140,843,89,563,886,15,596,16,150,805,694,168,978,402,885,144,738,749,286,231,729,75,792,319,245,963,218,882,613,585,744,417,870,299,441,13,155,284,360,418,338,719,977,133,952,825,985,869,199,713,396,270,426,848,929,965,311,244,3,620,30,822,293,672,503,878,953,922,546,861,759,170,794,915,22,365,486,253,479,9,529,161,73,778,736,806,712,341,311,41,987,659,455,82,592,310,42,675,639,875,475,907,172,856,399,829,799,150,92,670,436,15,912,392,495,227,850,653,539,855,568,557,846,221,623,893,799,366,451,805,997,920,138,621,303,475,875,2,984,205,950,45,465,623,885,393,719,930,463,929,157,807,630,962,241,814,845,437,109,53,697,957,583,605,586,626,891,88,331,389,658,212,863,689,891,677,786,269,247,785,888,361,247,412,198,475,39,807,208,166,16,848,579,554,628,36,685,531,449,534,270,357,992,492,223,846,757,330,316,477,12,210,787,16,27,396,888,432,237,63,641,616,7,849,637,293,380,357,305,469,239,50,859,627,714,495,343,0,694,577,754,56,626,976,219,649,513,247,109,744,465,243,242,328,640,120,604,784,696,423,895,628,14,145,144,254,626,983,733,326,626,970,790,70,719,583,823,179,577,847,120,679,834,511,48,988,829,142,89,369,483,447,476,176,1,643,166,319,56,658,585,584,721,945,904,848,876,16,675,768,357,865,540,141,207,396,451,113,766,906,877,449,8,200,848,532,689,973,987,528,778,849,321,308,724,808,789,961,202,298,847,703,97,315,404,904,810,649,952,992,821,314,384,751,22,143,833,708,659,210,35,44,372,170,834,924,997,505,218,827,751,726,192,178,958,925,233,960,647,741,50,466,870,232,294,203,546,507,788,896,32,620,269,868,735,484,295,338,424,433,734,738,913,925,137,260,233,246,410,78,181,211,302,59,527,511,353,8,935,620,457,322,98,636,798,6,790,74,839,307,165,890,579,360,595,499,242,61,687,860,599,882,388,248,172,671,79,232,187,68,169,938,543,921,950,314,648,943,16,382,140,170,531,889,154,734,534,563,693,842,374,26,900,446,371,812,686,908,180,991,726,834,217,290,501,520,310,583,462,841,14,50,644,844,4,244,890,697,574,494,299,998,455,461,225,138,745,484,814,521,346,105,710,659,284,983,34,147,125,656,325,315,294,379,566,109,885,518,110,133,45,241,85,593,288,287,149,277,848,223,299,814,574,687,974,358,834,118,989,325,198,441,471,527,222,380,804,276,98,202,479,636,304,460,322,557,559,188,607,606,670,318,106,296,680,887,307,333,340,182,580,757,6,363,578,414,810,886,773,19,117,837,544,977,510,600,890,590,557,774,226,115,441,649,794,34,521,662,178,308,697,656,498,218,569,583,57,319,458,454,82,243,407,383,341,329,800,103,141,710,718,804,469,847,274,980,280,361,147,529,303,430,189,480,887,409,740,951,441,641,850,542,120,653,85,498,207,911,447,603,797,437,822,848,442,473,353,393,811,102,808,83,515,629,96,493,338,341,185,287,208,88,291,675,621,849,822,960,724,280,528,440,41,563,23,683,647,447,164,349,958,277,53,952,954,252,582,927,832,42,434,165,339,166,550,669,145,251,33,623,431,220,352,350,816,934,206,205,370,977,533,49,585,793,911,674,76,850,510,688,454,280,383,226,12,150,315,886,190,923,69,273,754,445,177,873,718,12,596,374,601,570,850,875,96,364,782,862,732,215,408,49,482,81,486,551,518,820,109,408,894,204,676,476,122,741,904,524,184,384,230,593,895,694,720,987,852,670,645,588", + "902,999,344,800,707,694,64,912,336,795,97,760,713,547,319,700,613,753,276,139,84,413,260,170,674,277,886,515,512,757,499,828,660,187,524,293,256,864,453,193,139,478,877,133,412,24,842,173,97,494,191,996,719,779,405,55,548,101,145,689,905,247,275,615,454,409,946,71,795,887,367,778,330,320,561,360,433,715,893,534,808,433,178,909,714,25,507,200,934,768,577,595,379,529,887,59,123,307,585,366,743,388,922,878,930,345,297,267,649,979,513,351,65,508,485,75,338,587,536,658,51,635,858,308,822,127,859,906,652,784,86,450,361,40,191,404,193,946,948,531,61,829,90,121,312,162,965,214,776,267,600,41,903,633,947,918,220,966,509,680,833,453,941,793,711,644,732,322,14,964,381,156,784,841,711,696,834,361,205,839,940,688,216,34,99,82,493,318,869,349,172,839,320,868,128,326,845,539,73,774,853,184,920,872,929,954,145,686,973,870,336,622,755,659,650,825,484,407,15,76,278,848,683,482,42,343,300,866,396,253,976,854,312,554,967,697,646,474,292,407,835,902,66,274,734,33,959,623,726,780,699,685,761,494,691,653,325,712,760,316,524,637,162,592,142,346,655,720,955,829,79,377,614,230,56,763,637,883,53,975,820,867,987,715,109,646,949,394,506,593,794,654,763,81,116,419,932,316,69,168,481,665,790,54,15,245,414,214,403,102,408,431,7,966,39,638,475,219,615,686,320,134,82,350,994,368,939,454,419,318,513,732,237,92,154,220,204,411,595,410,658,774,996,317,323,327,483,971,653,184,35,439,772,186,566,73,613,829,891,813,433,286,152,556,958,733,952,172,734,357,573,494,967,22,500,153,963,696,866,438,529,625,523,919,363,946,321,517,370,70,771,962,215,104,953,605,198,267,563,770,568,257,480,144,390,583,189,60,4,773,186,242,593,401,952,261,291,80,607,341,168,369,530,161,909,100,15,268,802,462,717,719,996,875,695,430,898,694,0,396,468,449,24,220,31,701,784,748,197,659,637,397,486,323,829,593,376,793,77,988,443,572,381,201,637,457,510,514,180,586,593,967,580,856,720,725,613,8,508,75,523,149,126,805,834,751,381,988,571,898,946,403,600,994,985,310,477,702,706,477,876,25,372,950,108,964,410,276,567,405,61,63,40,550,176,425,505,401,469,441,199,553,659,40,825,446,649,492,298,368,157,603,948,201,781,878,956,455,25,8,863,350,529,545,222,933,791,844,563,404,471,365,331,99,217,943,685,821,527,427,539,389,582,69,735,348,701,75,616,985,985,636,679,382,640,433,283,606,341,469,636,570,282,350,401,509,547,293,271,451,296,147,152,439,758,44,893,481,355,359,57,398,799,801,819,366,104,610,506,26,486,496,823,76,459,395,444,788,993,97,506,78,844,521,530,381,901,588,296,698,310,643,511,662,48,374,700,750,867,552,470,238,83,100,492,745,881,628,948,188,772,201,105,829,142,531,18,606,61,726,484,708,330,486,752,566,574,526,815,386,355,559,852,488,490,313,68,341,56,775,738,536,256,241,688,196,349,847,605,95,34,589,687,869,822,772,49,495,914,265,451,118,371,840,608,426,475,366,264,290,435,457,304,129,389,242,78,955,364,531,340,312,426,357,41,549,482,154,960,30,674,522,29,821,758,253,966,673,152,510,47,750,911,601,339,466,259,159,585,687,417,655,507,198,574,527,192,222,947,46,447,768,685,126,225,151,838,634,405,751,952,735,974,221,653,78,75,509,565,121,354,221,484,603,83,546,289,37,588,741,809,477,649,865,148,809,639,114,999,891,692,873,5,298,76,735,819,405,527,959,711,421,176,169,809,718,200,31,743,102,603,138,84,815,705,38,125,887,219,260,92,958,99,797,814,202,149,259,248,5,176,659,873,8,120,153,232,510,453,588,624,771,27,433,758,982,62,494,484,904,954,526,394,913,208,688,43,574,827,969,102,184,309,830,401,774,294,811,213,610,60,502,737,796,16,113,471,815,883,101,754,602,757,375,454,129,594,147,232,363,59,374,347,952,214,541,622,521,881,772,103,791,226,233,912,763,776,928,73,27,164,844,874,311,444,667,24,586,236,168,896,573,831,493,119,503,77,724,170,137,12,935,936,146,410,555,198,803,447,61,352,912,992,83,193,119,352,814,416,628,527,758,191,971,174,795,277,425,46,787,519,131,112,351,770,90,246,46,227,60,39,762,101,143,499,171,55,915,766,12,6,121,156,539,909,573,706,654,324,713", + "529,235,571,53,919,394,714,977,723,229,238,925,359,98,903,104,681,457,904,350,271,935,154,337,68,635,573,2,394,949,34,329,310,905,52,622,674,867,554,517,677,819,98,846,908,904,111,190,89,583,97,579,953,813,737,597,483,205,487,43,246,316,696,66,134,878,357,479,462,786,458,176,233,1,252,362,60,571,381,27,997,506,588,64,892,578,530,585,40,811,300,95,698,167,324,960,481,458,502,828,64,40,993,100,890,760,582,434,706,980,292,739,339,196,854,666,591,6,200,753,532,82,468,52,943,846,619,182,701,751,609,222,155,822,180,577,600,83,473,703,453,84,616,119,574,377,826,291,123,663,560,284,219,971,714,766,749,245,359,146,515,588,999,315,967,896,578,800,161,340,99,638,645,381,229,560,28,581,817,470,951,149,90,665,952,472,78,87,358,948,895,784,607,217,70,121,358,214,669,880,979,567,436,515,207,630,944,714,354,769,951,649,527,904,950,144,647,298,348,959,514,531,419,785,798,834,218,263,467,220,561,359,351,180,55,69,798,731,782,183,99,466,345,24,92,345,149,665,798,540,164,16,717,169,312,74,829,577,19,867,961,787,959,31,4,630,227,334,857,905,69,677,101,664,291,458,609,596,810,700,474,472,492,723,536,105,669,879,213,393,272,16,271,267,268,22,461,355,721,699,896,471,602,755,32,567,106,30,235,936,62,663,899,347,222,270,845,700,446,633,66,54,512,126,85,624,361,544,790,214,68,849,835,80,188,833,110,886,963,251,602,626,319,609,964,353,76,570,634,479,286,765,735,76,410,208,864,737,209,996,883,436,916,395,642,107,687,414,767,255,472,852,640,15,362,775,182,605,627,873,916,767,811,493,538,290,727,244,944,734,55,820,657,930,813,800,359,533,520,845,574,272,904,630,263,709,454,883,38,878,291,775,529,910,525,627,456,725,548,813,308,952,791,419,283,438,236,812,735,171,25,432,715,265,82,48,655,577,396,0,867,796,340,220,293,322,881,986,460,682,693,72,989,63,79,958,196,876,389,531,760,41,149,364,486,374,856,594,313,117,152,169,764,850,280,796,474,186,275,674,662,847,16,489,114,451,325,884,773,199,500,298,412,580,340,759,694,492,771,158,932,787,899,547,532,827,383,527,42,273,145,262,406,184,543,931,497,894,807,301,538,51,884,626,566,259,891,347,507,420,494,695,428,40,386,215,751,951,59,208,162,84,745,804,862,717,863,539,284,658,540,217,882,592,218,961,542,764,484,333,43,703,164,568,13,741,299,677,386,739,711,904,625,516,860,174,33,503,624,107,832,365,114,811,815,627,478,413,330,968,188,294,866,476,481,704,38,602,974,708,668,419,151,994,438,581,804,994,468,60,265,814,191,574,279,622,716,303,430,35,675,734,691,514,33,667,711,460,855,503,189,157,602,7,243,121,280,847,102,246,566,535,566,410,42,811,545,960,762,949,970,855,593,205,298,136,457,145,848,592,226,493,950,209,446,844,895,179,550,671,726,287,723,316,450,252,961,341,454,210,119,724,184,144,492,977,461,598,114,275,423,12,819,723,476,955,917,269,152,797,946,127,857,121,61,949,835,771,659,561,824,687,49,818,1,940,189,8,135,777,952,908,605,703,56,148,697,144,408,484,426,967,535,652,946,512,879,999,186,338,591,557,555,450,380,336,797,587,764,269,579,581,747,176,992,49,477,833,372,174,589,360,863,339,960,248,410,14,582,382,667,233,155,510,363,734,248,950,571,136,679,582,310,298,995,640,710,467,152,94,102,616,124,641,99,211,519,136,91,378,139,268,44,945,460,867,924,648,935,42,969,242,893,347,249,441,589,53,1000,36,685,838,279,531,787,288,856,954,880,531,306,376,892,443,715,84,836,693,59,236,2,273,211,984,151,820,712,479,453,560,810,858,784,139,390,141,157,541,562,931,837,897,868,469,575,33,199,703,406,79,255,853,212,466,344,50,520,394,521,367,709,899,708,235,551,348,7,111,254,5,163,108,621,499,621,996,752,502,94,303,485,253,8,855,576,666,616,556,272,364,448,370,829,978,621,744,685,554,206,559,394,825,772,881,104,529,160,13,133,514,725,123,189,42,161,848,649,919,374,289,26,618,590,512,781,620,951,307,485,705,218,781,218,695,343,257,84,515,597,713,682,737,229,126,879,15,873,559,444,993,178,823,892,402,451,717,121,427,362,511,297,658,945,627,487,669,226,663,502,57,987,138,824,400,146,633,226,657,455,47", + "362,727,294,800,348,477,482,584,740,873,555,511,76,616,79,741,992,942,260,39,142,914,733,176,130,294,919,624,88,483,400,980,985,237,190,447,880,15,16,743,932,595,494,223,183,846,310,695,88,848,83,420,524,552,340,559,975,659,270,836,406,938,46,511,681,218,982,995,226,304,329,550,718,166,813,878,148,626,343,843,535,207,283,243,450,146,446,422,201,779,231,417,877,556,497,147,888,159,916,602,814,29,365,896,490,525,122,651,459,996,610,921,320,975,591,207,30,675,233,658,741,50,713,460,831,977,905,799,973,322,549,595,275,385,14,354,622,41,335,669,965,176,105,447,631,322,472,79,265,299,129,330,812,967,511,340,465,1,944,569,399,914,864,815,890,428,421,936,109,501,12,462,89,446,271,332,457,453,863,31,955,412,648,243,437,917,535,508,926,456,562,181,408,714,266,771,386,959,420,330,587,75,570,652,517,478,161,138,301,510,334,55,248,187,890,551,154,693,763,955,15,289,647,852,708,97,267,570,86,530,64,175,558,531,233,381,474,34,848,534,864,126,258,556,28,930,85,218,173,702,384,501,383,244,892,620,382,325,627,591,597,125,563,877,44,593,471,973,370,625,87,3,394,344,833,562,664,88,142,513,798,461,298,276,837,358,58,809,149,844,636,745,898,169,764,619,270,484,755,737,559,619,797,662,40,440,976,571,556,880,337,953,916,605,654,967,422,15,477,322,20,905,721,436,295,463,799,59,742,550,107,160,316,466,546,901,901,417,702,298,671,361,834,675,888,158,26,224,978,636,699,212,860,940,153,352,606,585,659,825,696,251,358,98,909,562,911,106,962,13,318,1000,2,760,513,766,669,149,54,445,915,870,738,46,694,459,130,181,60,791,881,443,577,154,406,914,718,966,811,890,467,422,226,88,42,802,416,796,609,284,908,831,86,275,185,538,483,672,885,679,500,246,55,486,341,349,215,536,152,792,936,194,462,105,510,404,389,754,468,867,0,194,43,801,13,718,210,541,234,577,762,32,681,343,57,713,659,355,468,563,765,387,362,955,436,258,532,837,837,391,150,702,218,215,17,76,952,499,127,554,108,495,186,268,811,201,847,80,36,233,588,699,897,80,842,89,868,790,416,529,326,522,301,605,410,585,283,442,602,567,198,287,764,996,623,718,512,708,463,400,703,100,936,215,55,689,137,669,9,367,318,368,925,479,991,781,84,84,732,710,488,166,407,212,82,294,699,873,808,904,953,154,416,730,292,331,864,903,110,795,391,531,122,998,603,729,396,658,843,988,319,550,829,932,672,369,600,795,897,182,230,554,754,914,152,795,906,415,540,728,802,280,261,525,50,108,414,897,514,76,47,90,622,342,137,58,143,998,424,29,998,569,413,780,30,638,152,457,488,660,278,660,291,794,936,602,322,782,752,984,141,748,104,393,332,416,199,600,855,32,100,458,450,359,917,464,643,670,231,712,730,420,662,845,322,74,820,925,835,38,470,61,730,303,268,409,142,558,426,423,121,432,931,411,955,416,49,470,84,730,297,493,780,560,161,867,186,281,151,856,769,23,146,945,158,523,25,701,858,790,360,862,72,782,277,472,52,543,833,247,772,599,816,801,82,502,24,354,868,324,135,382,759,621,201,210,457,704,856,181,569,225,249,217,203,616,160,678,725,355,700,46,818,822,486,872,557,80,539,60,360,893,829,124,524,820,384,476,364,397,130,340,618,710,902,523,215,24,351,652,578,512,687,25,317,24,748,853,718,863,7,640,631,909,171,214,520,831,213,194,179,302,861,447,428,640,485,487,517,715,961,306,149,78,947,638,537,596,347,269,721,895,785,914,110,579,929,124,663,382,693,388,955,757,162,18,277,131,914,294,344,983,964,410,234,602,491,659,665,223,910,546,939,333,201,432,862,502,516,818,350,515,223,751,656,974,759,190,387,65,73,822,387,118,209,531,801,127,254,434,723,209,836,32,279,675,428,730,165,638,41,773,920,950,288,907,619,894,552,169,78,347,206,593,575,253,619,980,585,831,720,633,454,582,57,185,723,609,27,619,147,533,611,923,986,352,715,220,842,206,20,907,469,419,697,761,573,173,566,97,177,683,494,668,924,165,621,75,611,175,490,919,927,522,226,450,228,542,620,902,711,363,306,187,127,399,934,691,809,248,21,52,31,379,225,792,428,64,943,892,752,18,659,362,259,469,927,936,394,177,329,517,334,713,371,676,891,336,981,879,363,533,499,186,892,23,946,159,932,140", + "225,913,498,860,140,145,886,199,579,787,486,448,713,616,72,120,219,343,990,764,766,814,754,750,311,313,564,781,192,22,662,831,637,254,303,929,813,161,845,716,640,114,574,72,945,820,631,771,369,805,989,855,311,602,917,410,43,151,248,28,254,668,848,494,771,895,507,267,219,51,229,83,964,151,717,417,16,956,201,756,251,830,597,851,839,8,291,893,718,699,372,787,977,349,958,443,176,289,363,92,895,587,735,589,847,37,200,925,617,541,427,90,354,266,114,563,908,138,137,332,87,735,917,894,667,55,214,729,126,810,491,14,195,513,192,652,14,768,600,872,491,179,543,546,548,203,564,441,637,227,221,391,559,687,496,584,167,74,282,812,405,410,710,615,683,948,934,945,471,599,398,282,66,536,764,901,349,971,113,441,377,336,194,866,468,641,37,819,162,470,169,215,144,857,53,509,125,549,723,646,783,159,572,927,708,267,124,605,925,924,262,389,784,141,830,162,762,559,893,414,586,546,998,63,572,391,270,75,55,637,721,958,71,129,225,200,805,554,763,472,798,220,607,166,697,664,842,563,522,387,694,441,177,49,678,992,602,502,27,548,836,671,852,457,246,164,937,662,704,738,431,958,207,876,752,728,123,874,852,769,178,647,255,13,215,501,711,274,627,630,654,656,881,305,191,903,56,249,277,538,326,970,553,447,429,583,66,973,777,530,580,648,920,436,427,989,922,127,740,409,114,830,876,612,135,530,600,914,147,452,337,100,575,124,76,733,331,891,573,909,155,910,179,735,305,986,523,179,456,303,855,552,948,789,784,886,799,277,791,462,766,610,277,922,948,374,514,254,284,398,575,595,936,777,422,754,134,890,303,955,576,207,193,786,225,195,725,484,750,255,869,518,863,294,256,597,157,894,470,597,764,390,106,375,865,542,522,606,662,397,371,820,523,585,278,550,744,373,424,319,906,634,632,5,748,432,872,797,358,792,727,675,898,307,566,335,556,56,449,796,194,0,700,356,364,379,739,778,17,380,471,417,455,320,840,738,87,563,171,75,97,251,288,300,287,43,973,998,22,345,871,950,251,950,679,446,219,574,165,421,180,478,853,806,693,63,528,313,399,699,317,295,362,928,827,116,383,655,622,468,100,675,681,950,762,915,42,647,139,665,232,264,643,747,209,290,712,112,621,286,423,702,210,182,110,433,405,991,618,663,267,697,739,318,521,93,474,875,286,873,655,287,357,556,550,765,254,483,614,950,382,209,479,832,989,792,395,346,617,826,846,468,816,942,692,714,209,791,194,768,99,592,948,472,906,164,640,170,69,133,464,642,666,635,580,477,202,285,858,274,950,856,986,616,743,577,468,730,673,895,908,424,442,642,199,907,53,520,797,49,11,854,889,778,293,772,43,777,694,647,975,226,137,273,157,615,159,695,84,971,679,330,72,4,14,519,969,871,568,294,175,952,905,907,730,695,95,222,25,943,200,571,186,34,952,166,488,512,293,85,471,74,673,423,619,490,443,216,190,284,96,13,709,248,68,404,894,330,664,782,349,5,31,374,12,853,882,276,643,361,581,499,926,765,226,321,459,229,895,363,700,380,120,390,27,85,717,579,705,582,249,851,178,905,312,624,503,289,992,831,659,97,306,104,763,353,813,223,616,929,341,326,251,868,131,629,477,581,308,801,528,303,55,841,407,79,838,860,941,787,906,102,595,417,978,162,834,28,995,891,672,195,670,280,580,154,99,886,544,404,626,772,801,125,412,254,139,465,214,805,642,562,348,301,289,692,867,38,814,402,535,150,169,670,903,839,33,212,199,328,845,16,925,115,743,362,738,972,784,360,308,95,541,747,311,751,407,134,545,123,504,622,249,866,700,547,779,514,989,191,440,184,627,265,166,299,696,449,243,398,410,570,209,298,21,180,535,526,642,791,126,2,773,226,736,966,373,377,797,668,192,223,782,633,26,735,442,987,662,166,547,908,554,310,633,779,944,547,509,124,499,751,771,861,594,4,756,813,468,672,494,369,919,25,455,338,723,331,909,875,397,243,628,81,758,461,157,989,193,924,90,852,773,133,387,60,474,795,410,991,413,669,805,701,382,70,901,789,12,31,894,110,436,804,556,470,652,37,78,556,631,422,603,614,366,754,303,756,542,376,507,479,64,244,756,374,141,723,328,358,493,225,730,302,355,878,984,584,427,180,972,931,160,936,893,690,826,338,425,438,856,894,825,853,725,252,100,53,777,758,363,703,530,156,731,957,336,962,633,785", + "936,128,719,105,44,115,439,75,975,984,813,858,275,622,214,558,594,322,447,721,715,413,385,749,437,363,295,138,61,446,845,117,470,207,787,855,403,927,156,105,295,568,801,448,813,606,451,287,926,124,327,902,287,35,563,8,337,95,323,443,696,102,366,120,520,427,392,961,282,983,965,910,453,883,19,457,506,583,151,822,159,565,60,497,740,361,467,974,977,909,853,277,145,562,706,255,574,369,590,60,925,325,91,558,236,662,483,267,288,111,767,461,952,373,349,853,481,321,602,158,856,411,983,731,915,684,166,15,714,679,677,364,686,2,585,216,138,680,428,518,357,703,932,289,856,404,148,697,736,261,907,187,848,866,228,69,295,520,794,496,81,787,829,136,203,393,179,116,670,129,750,308,40,791,860,716,356,917,925,68,873,631,899,457,991,903,461,626,201,746,462,779,372,16,455,178,60,646,941,214,158,629,623,226,253,267,237,86,429,477,688,1000,451,261,575,837,693,232,145,445,91,919,533,853,193,63,917,783,44,276,939,861,816,823,190,905,886,568,990,783,143,498,281,842,473,76,529,408,185,442,915,99,752,490,237,796,45,181,248,319,18,835,20,413,90,275,152,713,323,421,457,263,701,423,670,999,772,209,923,508,846,338,269,76,771,204,25,786,281,982,359,992,920,487,470,992,582,684,679,958,38,751,857,105,90,475,903,57,97,17,621,8,658,373,993,694,661,804,323,936,448,777,946,529,544,411,358,349,421,172,943,299,340,608,587,311,712,579,113,376,165,125,533,234,936,72,751,259,553,718,783,220,242,792,295,894,179,116,685,70,489,225,633,438,498,951,661,591,447,591,992,319,83,311,53,776,979,655,8,491,126,390,411,263,320,324,776,965,42,836,257,320,557,752,591,770,442,908,68,866,570,313,207,576,385,485,295,314,116,6,830,366,334,744,901,559,47,377,740,646,928,639,944,992,333,985,742,856,962,990,574,478,609,212,91,436,98,626,24,340,43,700,0,350,674,663,869,983,224,714,513,730,571,99,957,879,21,778,12,848,517,109,962,774,3,214,349,873,995,202,254,735,743,363,915,31,701,133,343,771,166,641,248,130,331,790,922,681,100,124,494,389,151,959,95,150,192,121,412,175,177,166,493,97,364,358,758,934,60,129,849,853,674,315,225,796,66,72,711,137,951,920,30,261,17,461,279,522,645,705,508,63,856,993,99,838,36,480,161,308,734,707,954,292,420,792,523,908,85,933,630,886,928,850,770,230,695,2,817,227,60,383,959,808,837,296,56,269,783,657,794,384,457,316,636,772,222,109,378,1000,859,311,491,518,373,345,895,454,424,392,709,905,26,253,826,512,384,939,652,179,151,932,390,966,599,9,483,759,826,695,778,479,103,232,707,977,674,680,502,866,713,639,465,66,436,593,869,948,41,222,604,119,538,735,721,630,525,985,804,309,43,694,884,994,106,631,100,848,391,569,649,977,207,285,411,697,502,365,411,55,795,94,244,156,726,31,87,146,928,116,866,715,903,629,97,370,624,317,899,491,900,607,559,752,871,82,977,431,33,47,944,962,824,943,383,977,776,171,171,443,262,288,738,587,478,95,621,400,70,667,770,175,595,254,654,166,116,914,51,765,517,205,63,313,761,286,133,873,992,614,292,942,232,153,574,816,12,105,705,408,65,689,878,840,721,651,363,979,175,505,645,640,374,545,71,927,936,466,573,811,589,276,953,243,538,439,641,520,330,461,582,201,580,586,869,24,444,254,720,424,542,986,985,126,634,834,370,131,224,219,612,504,280,893,218,238,615,113,928,488,618,62,926,741,732,239,135,354,286,264,890,476,443,850,698,644,277,406,236,291,363,205,408,671,9,789,25,292,483,39,112,43,908,389,984,882,619,647,52,853,610,547,711,491,729,604,902,207,659,548,70,202,948,645,621,167,657,849,895,938,762,597,882,736,265,483,172,263,353,762,926,132,373,253,794,20,781,73,396,632,450,729,784,192,363,98,273,269,18,773,353,520,456,946,106,650,283,701,384,271,595,31,199,990,938,102,86,891,873,383,595,160,259,525,672,341,878,655,905,120,764,375,409,405,797,107,736,308,369,199,884,477,728,957,117,71,657,147,292,107,562,805,954,233,2,535,902,370,463,127,558,259,294,452,446,729,417,934,332,846,324,580,585,925,896,131,460,380,486,314,771,400,917,194,151,931,663,905,769,187,678,273,306,786,723,801,306,461,884,343,283,455,471,393,63,240,764,37,372,829", + "743,904,921,1,526,292,496,817,13,501,567,429,946,750,260,335,736,257,206,410,160,443,447,86,172,313,911,883,655,251,734,945,124,278,78,54,780,222,885,129,527,874,713,84,902,823,231,429,530,379,372,481,460,306,903,228,685,616,77,921,418,690,357,248,369,363,697,177,831,437,989,312,703,121,964,43,811,138,313,218,676,794,328,786,256,253,370,432,741,295,8,726,470,150,976,76,515,606,14,406,150,121,446,376,352,629,395,591,324,52,37,615,902,456,33,502,998,795,913,516,893,133,999,718,102,687,479,880,995,27,271,837,532,528,279,661,311,597,208,255,89,611,876,203,912,51,860,502,987,591,78,24,117,947,500,876,696,685,941,710,71,374,817,196,202,6,945,351,910,86,357,943,181,713,786,507,809,545,697,805,443,746,787,517,391,522,503,633,470,926,835,909,50,111,532,490,838,648,962,128,160,665,691,304,563,516,394,186,971,989,109,519,730,349,848,376,860,652,553,928,290,405,102,35,868,917,878,98,295,884,774,341,374,23,461,83,731,287,222,481,595,69,13,895,914,916,622,322,270,387,738,170,325,166,16,638,815,829,404,393,833,71,303,554,704,836,359,253,434,413,80,747,334,494,314,835,371,671,377,79,737,969,486,37,792,840,841,882,95,205,798,896,473,388,855,140,36,328,373,41,303,959,56,573,969,695,204,34,346,977,693,141,75,649,39,862,150,128,622,879,782,571,405,822,845,707,161,217,595,696,719,106,408,416,888,336,558,770,785,119,590,387,866,72,346,789,966,665,194,429,935,789,239,646,239,889,796,391,282,181,292,304,237,239,886,452,283,621,12,927,204,85,637,935,619,190,578,891,400,119,609,340,909,21,36,165,140,123,723,737,422,445,865,129,104,405,985,9,62,981,926,14,950,785,133,201,538,614,531,984,951,762,715,265,822,102,281,121,418,191,118,646,782,798,411,815,786,357,486,68,67,89,101,908,289,772,607,976,220,220,801,356,350,0,483,874,287,758,117,482,460,195,731,317,209,322,150,986,410,319,629,622,589,998,964,148,392,170,325,577,997,727,359,201,205,854,382,640,473,937,838,987,980,294,702,926,520,264,368,77,941,166,569,607,559,257,620,284,503,629,732,570,557,458,50,780,95,901,98,845,974,77,567,829,742,791,228,149,584,361,268,201,541,841,123,479,51,435,720,307,54,79,122,553,831,250,56,878,222,13,814,252,695,9,791,946,511,758,31,648,534,919,713,421,304,869,436,13,666,401,335,337,604,232,669,756,580,368,154,890,789,309,591,622,361,542,301,869,491,746,260,825,532,584,166,321,360,379,751,100,169,938,15,673,735,828,2,547,682,293,343,593,384,829,841,575,364,78,731,225,370,976,137,251,898,440,278,928,665,297,818,663,323,799,206,154,549,776,212,921,176,525,819,767,298,842,533,167,436,180,483,143,923,103,449,419,238,748,514,865,360,222,306,879,313,873,444,909,309,489,50,51,636,836,372,822,805,541,862,197,287,359,771,558,366,815,602,9,345,847,321,195,680,818,805,81,364,550,776,317,843,503,634,190,512,731,307,673,42,644,612,89,663,569,934,49,707,555,652,739,848,268,585,506,618,419,377,801,693,254,654,292,575,147,157,559,288,439,215,452,478,137,561,309,626,275,347,484,635,276,203,40,962,474,704,219,61,928,504,204,96,959,188,508,731,285,671,671,809,991,607,827,566,980,41,207,843,283,700,487,971,570,483,822,618,709,436,77,543,962,867,931,148,112,427,1,125,284,526,509,452,83,220,657,561,302,109,519,304,837,967,829,333,252,487,906,921,482,305,781,449,697,606,539,727,513,742,135,349,177,923,330,416,40,499,354,505,798,978,35,6,48,906,328,113,743,313,239,260,508,620,845,120,399,360,470,497,720,244,703,763,569,814,922,940,206,386,37,614,906,389,11,177,266,272,838,244,891,205,123,888,540,841,965,322,528,519,346,338,761,855,433,143,238,662,860,256,34,660,862,926,668,23,30,47,844,175,127,368,744,93,397,670,740,502,290,227,981,57,661,48,1000,460,198,594,3,543,447,41,454,216,690,967,277,911,284,813,801,10,55,996,251,502,113,281,682,915,104,18,776,423,461,890,146,689,127,994,103,717,955,228,540,12,104,887,528,313,711,453,986,845,915,765,565,400,300,600,121,415,977,734,925,968,540,400,311,609,171,692,453,659,242,808,763,588,287,317,310,792,450,290,441,53,7,630,96,975,704,773,719", + "782,57,571,616,636,971,496,60,488,554,603,305,214,982,770,835,275,564,878,100,759,263,31,969,266,846,852,355,382,860,752,789,127,134,93,440,280,973,490,321,504,485,285,957,34,932,969,45,618,487,613,497,714,451,859,462,884,330,11,286,921,46,416,678,580,825,558,205,197,702,718,823,685,884,641,902,342,781,546,378,583,281,67,46,241,234,539,692,142,727,416,367,31,274,666,980,655,707,836,241,840,501,408,340,150,782,779,588,118,997,111,809,392,592,545,96,165,315,365,608,850,653,686,738,425,47,61,650,54,952,725,118,407,609,816,365,536,955,408,326,744,108,552,558,650,676,69,414,203,827,979,843,865,376,664,625,841,925,331,320,262,349,586,631,74,627,437,365,79,738,274,300,249,842,564,540,475,901,922,301,762,906,852,70,206,768,412,446,238,687,53,58,781,752,141,737,593,979,83,300,157,596,50,302,733,550,423,288,533,628,817,254,209,555,736,88,649,759,300,706,24,580,969,679,610,225,834,640,43,541,408,480,343,426,809,386,580,508,869,586,893,941,447,857,473,115,672,273,447,102,648,147,946,725,340,51,959,624,827,862,659,240,299,268,667,624,226,669,882,972,301,799,563,435,317,14,541,230,279,458,898,299,380,180,365,300,702,672,321,33,236,344,108,67,683,101,429,379,467,902,721,198,854,195,31,676,809,312,23,875,927,471,587,179,478,333,909,772,160,675,16,706,95,848,754,962,723,994,671,646,356,562,172,23,485,794,40,563,760,799,615,844,900,670,640,363,594,689,332,903,404,768,641,373,43,766,744,376,736,791,157,597,874,975,866,194,723,411,791,297,956,397,595,51,799,222,497,883,788,832,335,332,992,313,698,592,8,193,370,787,495,166,197,30,282,737,948,509,740,255,652,707,130,508,878,950,285,49,474,881,729,952,181,593,818,21,745,539,247,164,763,849,578,180,672,39,943,745,156,816,177,79,425,688,791,538,926,219,31,293,13,364,674,483,0,464,874,936,195,396,824,423,949,938,628,842,483,804,430,761,88,539,67,875,15,820,426,248,112,508,615,518,180,920,232,985,272,656,946,530,208,388,860,840,731,436,862,976,213,681,212,353,783,8,942,431,120,837,950,424,939,552,351,454,257,737,835,304,625,930,599,816,120,196,853,71,915,774,425,415,47,68,485,397,356,370,540,947,929,357,524,991,126,923,20,600,284,137,781,624,160,836,500,890,2,323,921,185,7,599,843,610,571,57,668,11,907,247,340,906,528,429,524,300,650,829,268,71,623,487,683,142,337,87,388,635,606,797,535,226,839,3,250,398,332,438,823,344,652,623,497,316,682,840,642,783,757,89,683,881,338,242,160,384,416,108,205,595,749,10,603,981,575,965,958,247,740,757,519,359,254,729,962,250,631,466,70,340,450,763,750,772,465,464,836,214,516,811,608,67,395,360,71,716,408,999,846,999,544,610,352,177,994,276,748,78,89,946,431,509,419,53,622,50,950,927,675,759,422,258,766,901,479,409,765,877,851,558,200,534,692,363,684,280,948,972,601,342,548,965,569,916,81,767,292,394,162,237,861,617,462,591,622,67,552,539,726,103,3,931,781,342,96,351,351,348,779,177,526,582,897,991,310,737,514,809,826,16,889,714,154,294,920,672,561,326,768,308,237,714,115,323,198,498,430,830,803,697,631,508,166,125,23,603,752,217,842,882,329,388,410,161,481,999,155,501,604,635,962,143,117,859,546,308,688,74,47,6,222,240,409,421,521,72,485,306,316,407,6,242,849,636,301,293,881,862,590,758,971,253,184,247,925,974,930,910,548,770,579,283,197,544,329,271,211,468,574,45,654,317,640,47,155,786,625,661,538,659,260,267,160,963,270,673,154,767,712,867,32,93,557,314,665,611,891,689,276,18,788,144,855,218,876,456,534,7,522,800,586,659,772,834,550,732,277,984,406,295,404,270,749,174,918,362,520,573,58,343,466,805,587,996,896,146,477,894,53,598,309,986,590,907,63,639,987,462,416,344,889,392,834,114,616,373,911,905,198,792,952,575,676,985,486,658,406,648,444,988,188,704,926,798,681,452,687,622,654,34,925,647,334,278,519,940,67,844,384,302,680,973,820,860,521,272,497,847,107,619,800,798,786,245,160,635,730,390,14,848,688,676,940,284,622,831,984,196,295,683,38,836,996,586,759,699,770,47,137,56,780,9,965,647,986,851,262,554,678,840,671,411,775,2,292,197,350,207,941,933,784,796", + "307,300,881,56,479,911,11,55,468,308,219,249,615,754,616,795,889,20,601,184,557,107,376,54,117,943,934,373,885,519,537,194,534,83,119,136,315,851,915,88,180,460,332,401,357,6,164,489,268,369,710,562,335,366,688,880,920,696,827,664,310,363,504,504,770,791,913,599,640,957,468,581,860,670,716,258,307,94,361,224,413,350,889,200,360,279,839,287,990,31,831,56,337,907,12,468,99,294,551,551,165,431,2,276,368,16,49,165,40,377,18,756,516,983,585,556,411,324,642,186,993,412,264,571,756,917,995,106,328,368,937,634,994,954,204,861,820,806,109,313,59,321,201,992,888,657,418,45,42,290,52,359,963,756,262,748,792,162,280,196,885,176,668,605,578,247,915,43,654,694,484,831,671,805,796,98,932,930,963,379,824,855,170,630,346,914,274,181,686,781,518,706,964,195,419,52,934,33,740,207,613,937,260,974,518,98,692,357,175,459,909,433,700,67,391,631,114,343,292,501,922,677,476,589,235,936,734,491,372,208,174,965,995,109,624,383,607,363,56,309,686,613,309,892,406,863,461,582,967,492,539,308,135,535,652,919,297,288,900,882,344,988,495,811,656,169,324,141,652,2,989,363,909,761,291,125,343,236,277,325,420,440,142,26,856,33,656,347,616,368,455,509,702,673,955,996,924,152,977,286,22,647,504,103,998,655,6,305,414,675,320,971,151,510,900,284,538,929,931,788,784,322,653,83,230,879,537,85,137,793,431,291,175,312,244,83,808,131,959,100,876,73,476,448,52,182,893,43,111,668,875,370,382,265,970,702,595,148,629,870,475,114,192,268,749,239,846,102,721,234,864,988,355,221,298,234,852,370,179,246,226,900,930,352,500,534,654,420,835,803,421,756,927,181,109,383,533,390,643,816,866,946,668,302,649,802,124,488,389,116,741,445,436,672,266,551,331,542,872,706,61,969,528,493,570,568,160,984,807,382,655,115,972,910,994,544,415,649,701,322,718,379,663,874,464,0,644,851,595,711,827,319,936,265,974,986,23,529,566,549,777,870,833,552,691,169,900,342,189,387,33,116,410,180,679,726,862,893,643,284,904,82,140,395,332,734,784,222,772,848,777,878,100,222,805,593,84,664,31,500,942,531,714,761,899,461,811,146,776,470,551,21,600,128,201,840,532,132,9,226,460,233,287,925,762,58,749,459,336,484,561,651,357,912,887,300,911,168,420,352,467,907,520,636,494,385,745,613,561,897,651,558,13,681,224,595,675,498,780,577,909,333,337,128,308,854,594,285,23,55,824,389,604,391,4,146,644,300,647,778,290,909,832,255,424,987,618,771,372,794,869,882,995,35,989,707,877,767,243,155,524,807,342,534,710,706,716,188,393,856,639,680,495,980,592,392,393,290,230,925,591,970,237,896,745,641,665,285,138,885,802,532,945,336,751,854,278,506,227,961,495,2,884,691,997,337,229,518,896,17,261,235,44,220,888,458,257,15,962,109,93,247,530,634,625,162,764,814,390,941,241,114,12,67,564,349,620,945,230,889,529,767,261,354,414,310,807,866,585,665,299,940,117,587,275,296,119,568,950,169,179,368,759,874,242,922,112,938,286,551,750,270,10,269,580,668,393,595,553,254,173,890,503,961,319,741,177,287,169,404,920,485,762,681,379,473,781,161,927,409,958,85,15,538,200,465,430,650,167,391,26,301,781,64,401,869,627,958,252,776,802,763,804,438,693,825,336,105,377,747,535,786,471,383,278,306,752,494,54,353,844,777,185,699,171,577,472,561,54,804,491,11,440,289,146,390,316,814,409,964,399,482,21,242,895,753,733,191,273,794,71,849,518,569,230,662,769,20,373,354,374,534,136,201,619,513,628,975,45,923,485,300,980,23,984,608,963,952,436,138,933,515,446,252,833,919,501,27,800,633,282,856,989,1000,447,371,938,574,642,637,809,913,744,129,228,351,213,232,586,464,33,522,96,568,637,191,244,762,419,246,474,768,165,721,439,50,502,912,145,436,671,530,289,105,106,881,994,173,415,685,242,682,864,184,487,853,258,972,554,135,771,648,12,38,469,785,960,362,370,350,728,998,101,58,549,527,364,903,993,163,304,185,724,457,265,588,603,494,684,871,171,801,791,191,683,785,585,267,998,212,791,745,888,791,483,710,912,750,290,667,49,648,228,924,773,500,278,239,791,214,743,556,996,662,602,541,883,200,498,879,167,279,971,55,725,268,136,600,141,98,714,412,547,758,627,618,505,381,777,601", + "217,25,136,840,5,75,736,644,882,765,116,866,806,830,285,476,782,282,181,760,90,810,337,190,569,782,587,63,355,992,269,17,111,776,559,573,45,618,233,411,579,646,652,497,341,935,150,758,900,879,184,331,173,617,541,350,645,377,62,68,395,258,122,476,163,655,442,546,318,156,971,768,553,750,337,677,719,985,430,253,450,631,67,893,23,15,899,879,423,31,120,323,938,365,390,185,245,924,863,4,836,117,711,627,558,43,760,68,692,887,725,786,99,37,133,911,813,735,612,884,924,931,249,146,480,450,865,396,815,336,279,860,699,983,124,881,346,42,27,585,171,621,120,417,318,64,123,892,175,699,739,593,899,522,536,896,824,783,189,478,443,113,271,728,130,218,382,652,323,775,376,162,941,311,315,110,800,103,757,954,768,228,479,651,917,402,126,709,748,230,900,908,438,520,840,261,5,112,42,437,294,64,504,303,662,384,564,292,401,387,879,50,146,594,878,898,92,94,270,212,576,424,758,505,991,248,550,598,633,13,32,541,379,242,386,989,308,630,942,150,930,471,546,521,606,696,470,111,488,141,484,270,724,806,347,614,248,541,297,684,789,403,933,439,209,337,767,420,525,386,474,988,47,198,953,123,672,223,541,866,677,19,16,911,302,904,852,89,445,860,946,719,665,700,1,660,715,867,998,344,707,224,694,791,746,963,799,192,687,716,534,864,286,620,472,790,648,102,770,224,232,949,260,781,984,532,378,672,934,949,748,504,21,530,526,318,264,274,130,10,187,206,566,223,129,17,308,67,242,839,578,481,404,32,765,410,205,664,612,518,539,413,889,26,214,307,327,236,756,631,675,188,569,790,952,533,170,33,254,234,50,214,24,38,614,277,828,252,635,667,537,966,18,970,612,982,891,708,3,829,808,187,896,359,694,862,126,39,51,66,32,600,349,404,148,526,630,256,952,585,25,548,965,941,791,166,739,879,493,535,20,623,5,948,455,376,216,513,784,881,210,739,869,287,874,644,0,243,887,707,355,670,883,133,106,303,488,887,246,440,460,976,831,439,118,5,623,562,499,427,683,869,77,583,919,219,653,75,801,108,423,457,166,239,755,95,575,153,356,817,770,25,869,58,628,299,124,824,823,277,410,392,296,136,944,136,5,501,248,895,549,57,724,957,920,88,74,363,428,990,65,832,291,372,902,447,646,240,852,468,879,737,20,346,45,955,484,457,994,357,860,704,134,11,354,714,103,414,915,661,409,85,706,752,286,40,928,46,545,417,454,115,619,872,218,61,592,148,929,915,382,762,793,914,52,977,278,365,291,677,457,6,491,488,826,662,586,305,703,259,842,211,815,586,179,541,555,797,680,913,997,283,154,996,134,194,44,574,50,110,862,989,575,888,181,851,948,21,897,446,986,52,853,810,937,189,183,127,749,348,107,979,104,666,616,274,588,554,11,8,480,59,812,919,36,870,143,186,335,246,517,357,455,169,657,636,480,284,815,455,523,945,939,961,757,816,391,906,358,615,792,103,960,894,626,132,582,87,515,628,590,295,664,940,559,486,784,845,750,833,621,460,272,287,982,162,831,988,468,393,921,183,267,742,350,177,787,485,332,437,599,43,271,989,358,613,744,880,730,670,67,502,697,314,61,925,108,805,949,964,960,985,325,49,388,604,548,153,84,901,775,731,454,67,807,824,85,623,156,727,990,888,391,428,103,385,914,225,857,753,915,624,935,211,745,136,251,697,702,906,713,546,444,293,859,93,245,826,835,382,518,509,939,924,184,799,957,57,757,470,140,582,500,309,595,818,64,113,287,383,818,339,526,381,484,375,189,863,139,797,484,276,218,80,484,625,116,53,352,537,684,191,546,170,555,192,903,596,550,419,664,372,314,638,59,574,976,149,705,97,234,117,790,52,986,548,347,575,471,834,586,709,332,695,953,867,583,846,360,88,627,150,850,729,992,150,98,75,598,248,580,164,706,560,614,630,194,782,449,353,596,226,900,34,224,435,576,500,245,884,130,582,822,570,415,976,962,243,538,372,713,218,566,533,265,953,969,386,64,878,207,610,45,680,345,57,93,683,826,948,849,900,469,78,890,380,857,423,34,337,689,274,55,732,582,614,881,451,496,224,724,240,544,404,828,80,50,158,868,342,312,201,319,805,621,294,162,510,250,369,828,866,871,907,284,406,299,456,988,881,393,396,324,60,783,8,520,28,143,286,923,451,75,154,956,375,799,383,729,157,709,193,935,16,529,701,757,938,113,487", + "300,764,929,279,507,372,304,75,55,21,700,917,995,347,53,438,111,239,67,948,236,726,941,765,848,4,181,426,856,431,534,71,140,666,730,551,946,170,310,666,823,646,723,954,915,715,917,882,283,180,734,422,57,742,431,167,439,225,749,429,674,600,282,956,516,454,254,228,278,895,911,770,986,744,274,931,216,312,533,160,684,581,676,314,338,883,956,343,394,272,564,678,747,612,838,779,167,421,722,401,206,927,860,687,74,54,728,933,72,30,75,738,25,585,53,352,375,804,9,735,3,814,105,182,981,141,166,179,6,764,709,321,576,880,761,975,651,225,67,668,158,288,187,876,838,942,782,207,707,784,193,862,238,411,412,387,167,431,572,397,998,918,103,962,533,124,691,149,880,770,101,720,972,671,259,36,465,239,320,468,429,987,554,281,3,843,751,315,341,202,447,984,469,770,813,689,819,280,910,870,752,359,512,84,385,197,335,24,641,36,122,969,287,905,854,926,39,85,401,410,653,560,611,126,761,617,792,199,894,145,149,207,29,713,102,689,517,534,585,227,657,581,487,596,107,262,58,707,52,588,514,975,678,421,823,55,255,751,540,607,924,97,647,472,60,464,556,661,765,895,689,188,202,901,111,59,309,508,93,930,880,896,113,70,747,743,610,776,551,305,323,480,312,865,897,71,693,421,798,928,184,939,556,251,150,964,948,246,697,228,165,515,317,116,207,764,845,692,317,987,468,46,220,147,101,242,257,33,686,304,489,946,872,185,624,220,566,19,746,286,721,516,432,59,886,859,128,680,463,192,301,687,542,479,279,505,206,134,345,621,947,345,204,765,230,831,857,253,501,117,353,653,43,928,521,176,309,750,572,529,828,514,28,23,972,890,67,128,123,140,491,737,921,318,591,538,592,716,894,559,115,894,65,855,397,642,918,284,350,202,617,152,916,653,297,757,941,309,43,613,129,960,155,240,656,403,508,482,195,760,218,283,891,823,220,714,665,247,748,986,541,778,983,758,936,851,243,0,273,132,575,545,444,13,957,917,128,842,218,73,640,966,639,127,251,95,334,987,822,368,828,305,165,63,421,614,169,235,41,419,828,802,937,116,789,56,23,963,672,671,798,683,583,312,994,546,585,980,352,313,272,242,460,442,258,884,545,824,66,526,434,805,995,267,946,179,674,450,915,111,682,763,458,319,864,397,562,132,414,261,795,441,809,433,647,114,221,864,68,830,340,250,373,993,984,959,711,509,616,625,749,702,125,917,247,868,896,432,341,691,159,463,126,957,610,516,798,306,571,90,577,266,627,550,991,65,696,215,338,550,145,933,832,974,270,468,618,415,921,789,923,372,42,787,777,725,340,835,889,143,409,269,935,878,485,983,806,685,701,291,127,629,386,784,89,452,733,910,215,160,399,415,503,327,198,198,983,407,335,511,493,295,286,527,415,532,128,402,857,319,684,688,815,480,445,33,954,430,554,885,121,869,530,624,2,55,950,347,84,239,219,197,448,186,160,326,168,24,313,275,36,422,429,696,229,967,788,278,215,74,8,56,425,669,990,341,444,513,902,122,366,582,402,955,410,400,989,241,125,226,977,605,934,325,761,989,741,379,651,638,945,570,256,334,708,751,957,474,911,814,803,722,602,750,571,120,723,49,425,218,332,671,299,2,577,297,213,206,721,437,75,241,55,728,9,456,51,259,679,522,328,934,411,789,986,921,413,210,332,791,309,626,474,194,988,522,529,130,871,633,265,637,616,26,232,587,47,376,12,471,952,179,770,172,636,234,110,284,341,440,250,772,974,945,111,335,562,224,183,63,419,612,571,54,62,536,793,672,529,516,194,992,579,476,571,751,536,817,960,874,957,511,110,692,566,99,470,576,282,440,874,775,56,704,219,192,111,364,169,171,602,505,945,173,883,369,670,53,524,616,846,795,650,542,326,739,734,129,660,639,247,823,723,979,593,456,384,815,638,938,609,288,45,308,938,467,884,330,364,884,89,490,917,429,504,733,844,190,642,567,129,379,181,136,882,651,131,917,305,162,827,185,280,790,836,201,494,249,449,533,947,99,181,176,161,89,731,665,942,27,651,7,959,840,801,122,142,617,32,228,718,938,340,618,686,34,781,831,627,814,294,341,486,985,171,35,27,647,739,846,238,5,557,973,819,422,890,445,367,572,744,25,262,333,655,456,311,161,957,886,911,7,996,302,347,922,302,804,535,204,37,28,661,226,437,131,874,739,989,487,656,878,258,393,360,603,14,188,290,497", + "921,822,603,360,903,893,833,828,957,90,81,643,342,307,328,863,513,124,392,417,31,401,164,333,29,9,150,759,482,249,749,346,94,238,577,512,498,822,207,622,552,736,774,711,969,705,757,410,575,385,656,773,969,763,160,230,144,254,428,398,978,159,580,910,58,874,109,461,248,40,401,537,828,406,440,718,404,269,791,923,446,715,376,104,420,486,77,33,162,424,412,658,232,555,570,893,257,679,695,199,404,426,923,573,592,589,705,431,678,279,975,466,527,968,257,189,67,175,931,822,993,447,87,866,522,430,624,185,714,768,55,250,978,610,916,663,666,979,745,212,100,234,311,684,383,358,515,156,949,185,398,377,644,92,970,206,285,415,508,643,480,35,746,160,113,171,663,287,993,436,431,142,850,953,897,373,886,995,138,704,62,312,546,868,724,431,187,581,702,721,867,665,428,52,183,953,542,273,394,483,722,252,205,232,636,906,56,882,736,158,485,132,717,268,354,216,258,15,965,314,776,613,684,521,846,893,125,585,50,895,962,350,23,995,4,87,879,230,447,670,562,576,344,485,771,234,387,999,191,884,735,982,859,651,659,819,134,893,705,97,909,40,168,436,916,186,878,27,188,997,529,526,113,502,778,230,588,209,296,287,169,836,940,499,911,67,741,893,962,686,546,124,211,973,220,993,607,422,36,254,809,506,907,670,5,631,14,772,27,518,215,13,488,925,135,989,532,83,895,416,558,234,989,257,632,874,23,573,308,593,377,66,153,207,399,562,455,89,22,133,932,866,301,665,645,795,246,914,890,848,943,633,126,433,535,457,549,569,687,479,59,198,721,103,649,432,183,514,837,799,900,26,291,481,398,603,726,839,220,83,166,287,913,638,115,443,650,254,144,763,955,991,459,468,671,694,665,861,718,550,781,879,612,682,600,428,199,640,352,920,213,551,220,183,509,433,583,795,676,25,466,36,964,897,113,222,535,556,832,929,685,178,250,735,27,443,68,109,197,460,234,17,224,117,195,595,887,273,0,640,113,257,734,359,849,616,392,167,369,181,754,28,812,886,493,24,693,302,884,690,225,480,750,30,180,657,392,484,368,809,599,561,207,857,634,367,371,796,82,688,980,720,150,584,308,854,723,249,703,370,116,758,948,28,448,635,880,494,901,324,465,283,176,735,887,236,245,314,913,807,771,922,533,257,674,692,631,759,395,599,447,588,365,572,744,746,983,698,515,124,396,260,163,34,142,855,995,406,786,688,983,109,986,968,986,7,812,501,503,129,948,383,620,968,325,723,398,818,454,395,824,859,368,107,439,522,741,585,931,983,186,785,586,190,857,955,562,256,969,593,439,467,813,111,979,279,771,712,62,952,356,690,757,295,840,821,459,694,174,8,361,479,68,583,789,652,345,93,561,471,433,95,93,475,694,172,629,625,40,430,369,330,66,459,189,887,230,187,489,134,808,175,905,467,265,965,742,242,874,42,428,146,636,929,141,370,515,8,122,85,777,489,762,122,894,186,588,371,207,120,3,234,473,629,443,472,532,171,648,294,786,803,293,679,573,115,511,880,711,98,976,739,499,434,486,472,550,268,961,538,575,864,740,128,791,877,46,599,376,787,357,962,911,60,354,916,932,84,665,675,621,631,989,735,672,122,662,951,300,408,532,655,948,286,855,864,977,872,61,664,32,663,816,521,474,407,760,930,197,679,137,711,813,71,9,488,617,997,789,935,935,533,796,802,508,953,788,127,148,518,126,939,28,225,803,898,252,63,3,242,665,252,886,417,474,992,577,721,203,943,68,123,293,771,255,909,329,864,355,841,431,695,913,693,23,508,120,464,795,568,977,30,472,271,495,74,134,608,701,19,678,306,803,315,863,196,686,48,233,468,499,816,930,290,845,737,438,478,439,188,436,901,515,683,574,473,142,456,766,903,454,322,28,609,827,870,814,270,906,700,491,948,151,577,900,729,953,794,654,516,712,646,806,811,200,380,558,744,170,814,386,104,96,972,718,20,372,716,404,849,647,970,134,778,656,66,894,4,89,291,246,410,69,422,868,203,512,159,227,396,327,503,255,575,453,378,816,808,157,688,438,484,120,216,138,501,531,802,886,517,746,424,507,28,183,175,175,289,251,717,753,250,868,581,806,146,104,284,820,822,594,507,33,607,572,640,63,811,100,623,214,424,617,787,446,636,701,34,503,722,687,829,494,348,812,552,867,97,15,504,399,977,421,78,171,498,468,384,134,804,785,845,666,199,639,671,75,236,199,605", + "699,924,541,881,582,645,818,940,676,896,797,376,454,907,586,968,612,132,420,32,662,701,970,29,912,250,108,41,935,153,690,433,763,476,305,121,696,343,709,516,797,920,525,560,325,142,801,610,250,757,368,240,753,653,559,370,684,640,828,218,776,38,714,924,44,790,973,448,68,6,454,413,355,511,584,170,667,365,337,836,247,467,308,205,650,460,974,1,634,28,829,282,164,666,692,643,982,339,710,760,31,777,38,903,132,707,572,233,623,982,20,314,29,710,396,526,338,660,509,273,860,991,361,160,275,365,11,829,851,66,377,454,104,66,457,803,131,91,443,307,387,409,13,830,203,442,86,778,935,101,87,988,769,163,185,150,28,828,873,909,700,480,757,165,147,979,989,286,17,886,498,937,73,418,151,150,658,955,741,128,621,515,689,237,22,85,248,666,278,144,930,607,5,83,658,31,405,568,280,260,46,646,644,734,503,268,491,104,247,574,128,834,493,478,57,738,48,55,372,429,853,10,542,222,86,361,158,301,167,434,341,559,352,603,743,881,545,525,768,760,758,616,27,476,771,948,222,898,904,61,582,967,579,104,997,510,969,40,465,736,524,590,752,467,450,535,106,520,380,786,399,949,657,739,36,1,122,861,154,295,305,650,51,591,306,367,179,184,959,133,652,136,368,381,501,465,270,174,342,615,233,224,596,553,884,92,322,550,872,990,988,482,727,720,796,610,798,19,67,304,829,773,565,734,114,347,836,964,6,246,609,293,654,775,501,869,355,8,466,551,64,103,530,923,222,978,128,124,574,1000,940,469,222,45,942,987,695,297,387,348,184,537,265,752,146,889,358,563,527,778,845,931,268,504,924,753,487,985,668,909,105,898,720,562,659,601,42,87,983,818,239,102,321,560,593,220,714,312,728,82,23,153,569,917,803,772,432,921,951,971,461,365,751,426,485,436,88,826,165,984,931,639,508,153,453,377,522,91,874,285,882,397,357,581,96,281,275,744,659,682,577,380,714,482,396,711,707,132,640,0,644,651,491,933,168,845,866,419,93,555,108,127,957,795,804,576,632,933,72,205,952,678,383,621,825,249,426,159,911,558,133,783,346,664,169,143,466,436,930,2,508,64,369,520,176,421,148,537,679,68,787,292,784,38,845,367,811,802,480,728,219,999,376,978,115,881,529,91,567,218,583,794,341,12,392,569,854,168,976,425,274,39,296,852,570,936,889,554,17,464,675,955,30,764,405,278,219,517,168,492,394,453,817,220,943,480,873,943,997,156,179,769,563,233,424,402,734,547,512,36,24,547,787,22,887,199,120,727,160,670,965,324,235,302,895,899,55,947,840,214,139,970,177,627,576,902,342,969,611,141,789,88,808,389,780,224,621,529,409,400,292,441,525,60,707,345,741,116,438,785,113,290,984,793,341,988,712,449,629,147,491,932,165,793,209,799,107,616,649,434,959,555,634,699,354,881,847,288,309,886,507,270,273,168,987,874,190,97,210,407,464,266,485,510,12,661,548,523,6,434,570,171,88,377,773,800,38,471,649,782,847,939,952,444,604,824,125,473,667,398,118,62,67,924,614,633,15,375,866,547,48,765,377,499,451,246,956,130,966,494,759,884,200,69,23,172,175,816,266,781,35,396,674,163,624,372,978,876,524,989,321,36,378,94,1,90,387,111,283,974,600,918,954,331,981,507,738,438,11,528,140,521,690,106,374,457,226,27,850,598,939,453,676,563,751,458,176,885,496,927,747,382,884,928,896,750,650,454,725,534,820,617,215,944,957,428,158,370,346,148,496,428,977,498,144,196,341,773,863,406,751,151,667,468,717,434,783,250,712,430,242,648,439,798,932,518,636,984,513,576,248,902,725,821,510,158,931,545,616,565,439,498,601,690,601,973,61,936,751,896,803,395,694,17,753,271,724,108,314,629,614,760,388,672,572,780,319,726,28,816,569,479,754,142,653,765,786,488,121,746,385,132,162,993,435,81,610,390,841,4,86,380,973,500,822,590,106,909,696,730,67,277,232,436,562,909,108,829,717,285,724,234,36,919,606,875,822,222,676,891,42,340,949,940,868,752,730,697,712,14,795,812,368,734,495,619,482,846,764,47,93,348,571,792,205,234,221,761,734,810,145,711,889,321,343,656,654,63,245,241,300,22,135,868,641,469,649,281,467,833,343,15,986,226,63,301,774,278,745,957,895,583,745,700,827,698,228,425,824,230,675,510,926,483,516,207,510,49,624,469,108,473,220,389,633,437,625,878,452,474", + "664,415,608,322,708,46,393,472,962,523,552,830,80,272,148,418,587,854,237,105,587,386,893,140,235,699,327,484,310,479,798,920,234,108,271,319,882,784,536,927,640,528,275,608,606,41,354,677,256,762,38,606,370,669,92,11,776,527,547,907,777,219,893,742,194,791,7,611,529,898,813,596,786,242,437,94,436,22,97,374,900,691,82,953,671,172,451,212,205,281,734,777,198,936,301,434,530,890,383,341,743,494,803,199,945,468,165,655,365,454,630,443,3,484,644,179,322,231,536,559,743,87,914,748,73,402,334,126,382,413,416,766,222,251,829,574,455,754,57,77,699,711,790,460,465,53,650,145,827,621,919,348,777,903,944,756,700,688,78,472,686,816,354,856,938,185,894,927,670,37,215,603,496,780,510,674,919,66,54,759,308,562,495,628,475,694,365,747,745,280,758,976,42,425,838,666,940,481,606,958,134,610,155,226,704,249,510,979,348,450,509,633,432,864,465,64,415,922,866,356,534,173,958,264,373,784,253,152,565,478,340,335,740,456,175,701,821,902,351,891,964,897,440,991,822,646,548,983,161,975,633,641,813,193,684,900,117,430,170,278,187,640,346,686,793,612,365,435,326,433,989,186,355,137,815,223,596,671,948,294,621,784,843,516,344,989,193,126,268,355,486,317,39,677,121,223,970,372,796,442,76,810,548,128,803,385,939,231,89,744,697,914,950,418,639,298,677,436,881,356,696,702,927,77,718,303,56,179,112,197,915,790,175,550,359,672,99,107,958,454,178,78,443,836,415,803,763,686,541,964,841,955,160,903,354,256,976,993,204,131,359,94,499,280,372,940,912,824,847,267,532,634,906,171,448,958,356,155,406,496,670,42,28,565,545,748,936,329,659,698,606,151,285,65,497,84,309,495,657,912,322,459,183,8,428,648,808,366,400,786,585,239,784,89,272,142,814,372,7,314,323,117,14,469,623,65,720,507,285,509,756,63,593,616,129,103,478,465,637,693,762,471,513,460,824,827,355,575,113,644,0,425,713,905,330,179,301,756,670,437,365,795,517,16,261,666,483,922,19,904,611,37,974,694,30,509,206,429,572,158,645,155,744,123,343,257,890,666,894,227,417,619,429,71,460,50,138,310,280,719,457,508,951,678,426,92,678,525,119,42,426,227,80,942,800,827,492,193,834,425,677,594,630,166,679,36,29,68,452,391,43,993,634,392,181,302,522,621,954,231,527,246,162,874,292,507,51,277,228,773,384,463,595,274,118,929,972,689,285,910,408,583,474,823,731,370,352,19,1000,652,891,748,670,457,946,44,486,797,501,420,536,359,93,88,248,161,16,798,191,744,521,171,470,808,113,270,957,344,127,729,104,968,8,289,248,289,265,224,825,569,429,851,715,305,869,306,50,466,461,112,733,205,758,128,484,540,267,971,943,71,929,323,659,345,63,923,264,514,556,757,632,649,23,310,420,467,532,419,240,90,138,988,613,207,514,467,84,682,716,438,306,928,324,80,486,433,160,865,779,752,212,862,179,299,413,159,374,132,853,711,635,985,150,771,549,192,652,636,572,623,950,109,419,40,813,554,839,337,280,900,222,483,30,962,771,403,515,861,52,441,936,389,510,641,740,821,82,286,484,426,479,704,727,699,308,111,871,605,51,710,348,403,810,789,753,542,343,436,599,229,112,507,685,551,599,178,94,425,371,574,499,167,480,58,107,704,574,617,196,676,129,781,556,363,373,956,382,636,352,779,295,655,238,7,740,259,583,796,379,576,348,984,141,608,637,528,759,864,673,220,855,824,68,535,614,373,31,396,509,463,136,912,358,792,608,413,275,150,281,235,391,261,152,925,331,429,917,494,805,755,362,5,390,675,204,480,414,727,879,658,713,81,638,7,449,620,663,865,315,48,50,161,475,80,160,458,507,968,672,409,542,50,599,494,776,179,356,626,782,622,211,180,106,848,329,244,557,798,876,562,960,629,906,970,747,950,670,259,666,181,237,47,753,953,121,524,625,337,664,731,242,981,596,403,950,223,275,610,578,553,127,766,382,303,266,507,153,70,664,439,803,77,850,387,256,381,720,710,238,994,929,843,287,949,904,257,325,890,401,30,327,414,874,438,147,259,150,20,802,186,803,138,386,222,53,699,933,794,426,488,516,523,570,778,564,862,123,450,863,842,695,90,214,554,438,427,517,65,703,574,137,700,301,355,730,788,557,466,387,495,767,569,655,69,884,704,783,152,750,596,175,479,816,53,838,334,613,280,621,298", + "638,526,192,51,988,588,83,291,686,627,261,70,419,5,573,596,75,215,683,936,896,504,714,194,107,235,810,671,228,16,523,377,412,940,3,114,50,44,635,196,771,84,310,849,24,143,808,631,346,958,996,95,632,563,648,147,768,917,878,171,374,167,108,90,842,84,495,970,32,587,453,224,34,971,183,861,403,372,577,108,536,248,964,590,88,52,308,204,31,59,44,428,868,134,791,904,495,602,255,735,289,746,215,569,326,223,377,431,751,96,211,259,32,64,84,307,49,908,997,356,440,907,494,708,861,424,154,708,266,191,738,478,624,188,92,244,345,757,314,998,945,543,604,333,625,196,82,142,375,677,621,968,113,7,825,461,27,908,595,648,348,482,107,105,667,188,696,461,62,421,155,985,849,720,494,498,309,327,875,399,411,369,765,46,195,996,46,250,835,548,757,638,345,266,882,825,881,265,504,519,862,520,834,463,494,43,650,345,461,900,984,55,500,833,615,714,945,233,763,852,444,113,54,767,692,509,645,883,27,161,627,142,478,947,897,631,884,770,609,51,32,960,584,799,595,549,893,571,75,345,713,223,458,208,163,190,660,963,916,869,877,594,243,248,205,969,652,443,496,937,228,966,400,932,922,771,212,721,873,751,745,770,674,464,890,911,442,784,716,241,894,21,563,298,919,139,948,380,989,576,181,348,102,836,918,156,740,13,420,92,607,666,81,758,492,457,452,370,555,810,582,516,46,11,906,681,768,462,537,849,601,347,261,460,950,138,243,889,719,596,140,407,681,71,506,41,554,993,660,293,714,453,479,720,410,635,698,496,71,772,825,873,314,101,837,100,273,173,979,678,241,787,630,660,540,571,462,138,101,311,116,965,354,748,127,890,96,29,743,72,750,292,542,357,917,507,826,334,662,428,876,249,498,989,580,626,914,116,436,956,818,385,196,727,197,241,757,9,887,994,576,597,87,427,765,29,854,492,921,41,818,706,976,93,348,214,925,243,397,72,32,417,730,195,423,319,670,545,257,651,425,0,782,771,246,820,976,490,899,697,447,279,332,434,300,629,644,500,160,842,464,507,998,610,281,653,484,910,961,46,777,667,440,842,827,914,835,20,687,903,380,83,47,16,937,977,377,707,936,999,729,496,705,820,880,801,896,209,756,504,770,626,199,445,524,471,200,902,553,969,253,813,210,519,361,5,176,375,83,149,966,697,487,360,515,481,917,938,248,18,811,905,702,173,890,319,205,960,425,559,354,942,193,116,617,547,15,727,40,777,581,268,383,218,123,568,337,822,648,397,19,591,360,60,436,54,793,550,531,362,649,344,75,631,424,184,639,493,595,907,35,201,953,40,390,600,522,19,518,177,72,851,980,716,32,314,670,860,753,346,556,765,741,870,347,314,746,867,241,901,308,835,960,88,731,219,803,897,752,316,208,271,11,133,153,696,491,129,324,530,416,353,382,275,937,640,666,776,410,989,33,270,115,295,116,663,407,735,590,566,202,194,348,651,720,212,717,967,452,759,503,916,755,840,924,1,467,54,791,509,555,62,692,85,826,194,115,805,969,87,818,350,812,778,110,506,707,855,28,430,578,570,265,835,983,360,115,698,648,171,838,983,534,999,305,585,999,805,450,298,785,6,500,375,148,523,398,479,980,454,379,50,888,429,24,430,968,339,476,485,730,91,503,618,714,2,495,894,223,117,462,78,48,729,2,23,918,762,131,181,369,535,528,743,500,338,345,703,720,14,279,878,349,321,935,720,574,463,428,87,658,894,707,160,70,758,47,721,818,4,433,107,382,337,742,761,137,435,356,344,169,960,15,378,162,339,867,752,858,274,326,485,110,839,100,412,687,447,295,263,673,345,447,873,673,819,927,671,207,710,779,328,368,710,55,528,889,805,765,659,969,44,588,753,417,663,904,930,610,409,678,285,594,449,786,617,96,928,423,188,418,114,901,241,466,202,635,824,487,772,80,24,875,834,382,978,932,410,956,526,416,148,406,713,761,325,329,144,114,780,827,356,370,596,369,657,368,189,890,320,157,380,679,38,527,83,274,361,783,190,237,255,779,980,91,130,535,749,855,84,386,764,144,40,177,248,178,816,387,673,463,803,557,552,758,447,893,552,813,413,683,562,356,15,761,738,305,854,830,731,315,590,94,452,703,527,555,730,631,892,890,19,434,239,540,760,13,96,236,348,260,556,468,553,577,392,146,956,76,453,876,143,465,508,18,690,395,879,552,342,756,814,772,581,427,314,664,568,413,1000", + "862,689,118,34,190,209,161,410,734,549,428,754,980,844,76,620,509,617,27,276,571,103,880,802,968,357,440,616,455,948,877,243,319,181,842,682,969,664,64,441,42,867,23,432,257,419,319,367,46,347,268,594,939,247,146,620,612,662,169,22,982,282,776,49,923,711,657,204,106,294,932,401,792,377,701,581,287,600,534,868,588,362,243,184,359,917,162,975,755,730,602,45,909,282,860,178,720,947,600,405,768,913,126,398,41,16,409,708,177,857,43,498,20,403,654,612,586,53,133,393,225,41,554,119,195,288,295,437,430,501,345,932,261,467,927,25,503,439,672,946,575,563,597,270,418,927,191,187,858,779,226,818,739,657,55,457,745,411,888,622,398,553,360,813,708,521,225,921,695,138,933,462,296,901,892,397,677,165,78,174,414,623,31,209,31,684,60,137,950,453,600,948,809,626,914,85,111,452,568,983,846,173,415,678,761,899,440,97,299,466,141,18,371,123,475,813,826,408,985,741,898,685,871,864,524,884,76,521,376,135,579,342,839,308,650,813,358,546,393,474,605,925,630,186,70,666,203,171,541,78,549,506,778,88,803,696,765,903,350,348,202,959,893,627,396,323,717,64,579,72,309,143,677,588,721,485,478,563,549,477,172,540,713,388,826,659,827,350,727,705,320,221,829,476,46,56,125,385,365,319,187,436,450,314,398,571,724,703,267,875,610,364,144,349,190,819,374,447,137,745,467,64,822,373,21,353,67,585,242,302,752,793,171,647,206,538,714,227,349,42,856,96,184,863,17,14,376,403,924,564,914,292,436,349,693,762,710,304,377,856,627,561,96,725,935,539,22,374,803,193,962,807,525,603,562,975,95,385,920,278,657,849,190,685,664,411,570,268,132,354,10,624,841,768,876,301,207,700,347,343,890,544,404,303,529,850,241,379,308,210,474,302,834,500,681,558,40,661,461,562,230,629,267,328,173,473,94,643,774,33,812,760,459,465,546,854,149,242,486,989,681,455,571,731,949,936,883,444,734,491,713,782,0,491,316,550,702,383,413,197,565,560,382,670,397,645,809,206,682,790,176,546,976,330,151,977,666,197,926,959,743,544,422,242,553,432,803,700,841,6,415,119,812,184,978,164,739,855,507,830,395,609,901,116,291,927,897,515,929,988,630,449,253,582,508,866,912,469,92,996,771,716,509,893,115,632,410,209,834,732,838,715,262,210,933,156,656,823,454,675,363,551,969,517,602,959,543,579,14,993,632,879,247,7,557,7,232,614,418,571,800,582,193,312,928,477,135,745,996,933,4,112,765,472,592,146,541,481,198,668,668,316,968,59,835,645,467,963,646,820,811,693,972,279,151,990,223,627,827,893,191,36,423,839,421,971,533,533,373,52,827,199,820,199,767,177,976,331,202,438,757,21,443,286,237,935,889,796,643,885,505,473,657,815,534,147,270,906,119,504,112,569,132,787,642,526,560,984,89,523,477,201,933,101,841,524,922,236,618,218,894,769,450,859,973,176,864,46,989,657,405,625,460,694,438,4,719,637,637,476,493,275,223,40,216,857,553,645,94,635,390,676,934,776,514,947,429,748,781,905,844,303,800,96,803,506,21,887,502,793,88,6,189,952,519,332,306,677,78,917,636,741,216,617,246,676,952,204,376,141,586,219,596,141,642,12,112,388,178,891,751,325,261,321,627,127,248,252,134,682,581,447,510,545,307,376,797,601,680,573,238,705,349,533,166,465,704,638,55,709,74,535,187,613,787,765,362,287,508,286,879,709,633,205,925,562,68,289,172,631,863,112,145,684,571,945,847,896,876,159,778,756,959,646,241,962,890,132,141,726,54,815,200,602,230,623,328,566,360,797,246,493,2,547,896,720,155,305,79,560,671,647,708,413,414,887,740,710,290,714,506,277,784,708,861,302,479,201,976,352,421,720,346,792,772,293,3,409,127,306,469,221,298,622,428,11,864,626,258,670,135,993,346,439,452,123,26,591,979,302,790,699,291,34,172,696,828,919,784,913,268,207,260,464,328,825,659,432,593,821,306,647,104,614,570,632,420,858,775,661,870,718,436,300,753,668,789,188,592,654,248,356,603,846,132,925,7,8,795,404,895,903,525,50,31,133,649,89,723,275,119,490,908,548,731,225,566,949,122,284,785,73,762,294,707,297,855,377,617,527,286,118,992,751,267,912,327,180,281,421,801,889,579,992,715,635,720,468,646,615,475,513,111,553,248,716,131,637,694,696,871,194,136,926,342,672,67,911,698,948", + "170,858,36,810,983,681,51,912,491,854,759,951,771,213,600,669,178,730,591,696,647,281,498,274,266,954,692,187,288,542,712,644,61,651,960,131,282,491,620,735,432,598,322,352,858,373,590,803,875,124,444,208,784,14,652,757,871,703,28,292,395,159,799,890,987,391,675,628,698,982,185,196,213,76,630,819,816,533,330,494,301,339,144,326,399,240,438,94,478,763,655,889,960,955,747,378,219,942,217,739,667,596,387,165,642,881,481,376,880,384,81,845,873,972,325,884,122,979,85,581,462,132,802,14,434,739,45,397,221,390,919,617,126,885,978,80,20,900,345,575,293,64,394,465,7,962,625,640,996,427,45,571,45,877,883,677,48,567,472,915,565,280,588,21,258,385,271,265,349,998,700,871,585,79,981,669,288,241,456,393,380,859,963,324,602,915,825,834,257,452,419,556,482,269,109,264,699,59,761,656,686,612,279,419,835,428,668,418,42,264,714,499,160,785,864,669,618,106,704,872,428,675,877,265,361,733,532,900,387,397,183,753,105,859,447,210,149,110,44,153,452,493,171,606,349,376,919,911,207,681,375,584,782,629,216,70,207,601,793,463,913,419,985,875,723,119,205,759,656,535,764,7,1000,630,721,74,29,936,737,192,52,907,979,441,765,894,679,242,522,360,768,211,690,130,513,557,664,887,401,478,305,410,992,236,139,8,206,244,92,852,328,714,990,592,449,811,109,406,489,74,777,442,9,544,307,352,62,968,30,452,166,896,69,487,591,492,433,604,700,627,910,916,912,238,298,171,632,651,789,288,806,819,665,872,991,574,628,787,267,412,362,273,534,698,719,834,862,542,552,900,407,176,275,829,942,90,201,926,661,374,839,65,992,310,653,602,976,434,179,322,385,304,654,81,70,101,528,663,938,614,628,39,805,857,150,306,506,800,473,904,237,431,86,814,703,866,465,317,236,195,596,88,108,216,895,574,590,878,604,579,80,219,293,197,638,752,10,328,323,63,343,320,99,317,938,265,133,13,359,933,905,771,491,0,979,458,901,57,246,893,973,525,892,405,8,743,912,319,725,237,924,864,407,769,635,299,199,472,569,926,718,470,64,863,850,846,455,149,512,994,317,641,628,223,156,125,821,779,438,822,86,593,946,277,831,113,807,661,439,729,219,989,86,171,661,349,481,492,26,120,140,501,744,843,900,980,317,19,614,673,774,829,456,366,470,702,69,748,354,458,542,68,487,182,247,940,559,513,487,284,36,181,879,717,39,791,828,679,442,271,886,175,444,119,313,240,242,949,826,67,874,596,178,449,826,901,609,228,383,197,589,914,205,955,166,867,653,273,946,476,339,242,822,945,60,950,296,293,681,417,186,966,511,347,198,882,9,24,135,70,489,805,941,375,973,84,221,782,164,104,780,232,840,209,6,889,708,271,894,795,188,939,612,857,180,917,997,841,201,836,27,771,335,417,867,523,203,412,90,347,375,42,126,660,619,230,956,146,103,879,752,553,832,244,152,802,234,510,535,476,104,580,546,61,584,800,13,318,526,6,410,66,905,12,947,362,605,219,301,347,268,384,4,645,360,221,527,348,616,654,256,129,551,697,246,752,625,537,291,154,896,580,769,498,539,869,599,274,199,25,836,443,344,393,331,690,382,575,615,561,789,754,273,951,94,56,573,351,565,556,616,788,379,261,98,505,615,116,581,696,511,964,488,608,410,29,422,808,880,987,657,356,770,874,359,816,776,779,608,141,524,659,734,390,713,505,354,611,599,860,269,457,497,27,144,291,421,916,960,501,494,876,137,268,821,806,23,258,247,992,701,899,70,261,677,718,426,376,107,58,27,581,568,666,255,677,694,688,991,21,757,956,420,343,716,171,379,51,781,561,105,419,358,662,920,719,972,527,703,518,391,752,778,382,455,620,63,102,404,991,441,884,532,107,792,991,35,657,115,93,186,879,905,797,792,243,117,493,219,831,979,190,723,900,617,479,155,362,463,638,151,973,28,707,925,832,983,670,75,959,792,226,705,422,672,132,280,343,427,627,569,189,1000,597,359,441,673,934,78,96,345,196,735,222,32,26,510,616,329,253,941,249,654,824,247,264,651,226,966,388,44,252,499,962,846,840,925,896,511,932,947,137,914,915,628,959,89,833,152,932,501,262,311,198,672,285,632,524,545,208,801,700,162,762,167,488,773,362,13,838,33,583,342,284,674,445,594,398,157,660,251,769,613,298,786,421,29,585,838,289,413,556,197,129,372,898,562,184,507,417", + "916,224,921,143,55,247,62,479,108,544,522,305,985,812,438,157,542,98,242,482,653,230,424,811,17,275,178,969,92,301,568,26,622,858,873,84,608,418,763,660,829,775,346,271,721,992,560,94,177,477,67,290,88,303,533,795,896,117,221,367,523,13,734,434,425,242,846,522,302,592,977,467,70,930,551,729,521,707,923,977,267,862,484,562,217,554,819,353,885,642,842,353,941,504,925,68,799,402,833,314,946,190,369,192,206,539,8,871,232,669,931,65,429,91,901,797,16,646,34,735,431,503,931,644,911,579,152,151,737,757,390,264,684,795,779,776,495,71,486,530,442,296,89,703,863,90,550,529,426,591,399,455,95,544,60,9,849,933,873,908,223,841,320,786,951,46,571,553,591,33,517,144,811,64,822,650,684,730,677,337,307,172,702,976,423,8,961,239,809,432,759,165,507,93,17,726,921,891,863,223,648,646,908,705,857,332,117,533,777,329,270,820,742,142,742,842,385,598,978,590,841,358,363,593,41,532,210,721,149,399,894,657,943,678,921,805,683,577,590,11,951,648,94,38,886,387,139,548,646,430,330,790,306,937,848,603,94,391,157,378,101,651,692,259,787,598,550,967,917,777,983,416,101,362,138,466,161,490,447,270,67,510,584,290,812,490,854,523,531,973,165,549,975,705,319,9,82,835,142,177,34,664,383,641,658,632,23,466,113,930,64,750,788,13,574,491,590,433,75,126,749,294,576,355,491,871,814,260,437,272,866,696,620,640,216,545,413,853,654,184,62,588,273,621,486,361,443,561,620,841,274,357,194,561,934,273,187,810,311,425,560,325,438,595,303,545,405,7,8,495,646,267,643,317,875,745,324,655,708,425,822,525,819,952,595,489,461,137,636,370,512,740,291,609,773,921,316,25,503,206,723,44,674,838,959,427,33,631,279,631,26,456,953,468,335,300,660,68,847,416,969,831,208,210,851,917,852,715,116,452,726,828,486,511,785,267,907,640,829,79,57,840,957,209,628,974,106,957,849,168,330,246,316,979,0,721,671,98,248,100,764,47,659,918,453,540,633,256,108,827,54,320,981,630,26,491,807,45,503,653,569,131,976,625,397,971,683,132,742,51,794,49,995,729,32,725,214,777,450,321,511,36,218,938,858,287,440,444,523,904,737,419,678,339,126,161,755,365,616,2,717,424,922,876,684,218,677,210,474,300,49,186,316,804,756,256,198,758,78,61,272,763,769,87,662,510,866,795,540,290,507,460,838,346,753,712,449,799,772,367,566,787,655,232,799,681,979,934,380,925,796,752,462,369,179,879,429,194,510,704,100,103,613,928,518,893,728,537,378,944,7,804,240,486,541,742,428,493,530,764,171,744,441,256,409,396,149,110,250,450,700,191,899,854,583,151,525,135,174,537,514,157,690,51,992,367,433,392,210,719,490,472,68,284,970,461,806,554,104,307,669,537,60,468,123,210,670,261,216,5,117,419,378,639,635,15,630,242,470,532,44,983,961,937,210,146,398,321,630,242,271,494,46,473,515,432,532,536,730,190,932,138,246,781,677,367,289,22,300,759,416,712,618,225,912,469,630,878,161,997,277,206,279,196,58,322,352,786,239,173,826,453,72,970,280,999,135,22,969,242,897,684,55,768,409,429,846,517,153,357,155,467,655,689,125,745,864,695,375,651,372,87,251,391,326,641,452,944,37,635,947,884,541,100,60,344,909,972,194,996,34,373,353,129,381,221,159,193,635,892,843,193,676,289,886,779,270,612,566,917,818,495,113,984,125,934,611,725,510,734,42,234,373,543,191,430,583,132,148,711,659,867,936,914,423,861,508,762,900,330,561,436,743,864,896,222,817,457,203,896,452,899,143,562,511,78,762,258,761,446,706,783,186,66,928,602,550,240,39,272,275,325,405,696,443,824,454,367,95,470,345,763,916,843,831,206,308,89,433,718,995,835,806,167,376,259,674,874,929,892,210,535,47,425,408,782,423,901,842,746,120,400,434,196,862,485,187,864,421,964,38,124,261,741,665,21,511,77,463,328,283,511,920,235,580,274,235,587,736,370,393,772,109,854,593,46,547,743,637,485,898,122,612,264,908,728,922,965,114,643,318,695,803,570,346,3,398,178,88,715,284,185,488,329,250,719,476,3,871,685,113,500,310,905,753,113,496,718,504,34,307,676,685,497,72,274,340,945,242,918,97,709,315,914,421,721,181,933,942,677,106,912,535,825,171,707,217,521,57,268,604,856,844,732,867,606,961,976,357,957", + "806,381,715,908,243,154,419,684,990,896,373,431,972,192,195,331,836,61,469,292,620,803,219,687,420,797,707,408,721,326,635,38,516,330,171,880,339,37,28,169,855,950,194,916,145,13,27,898,132,706,647,742,274,393,407,938,790,927,384,48,149,393,807,537,306,294,578,468,23,697,5,20,914,612,175,722,168,257,271,960,780,306,23,618,571,725,738,806,110,838,664,262,313,570,370,70,963,545,532,96,473,749,516,550,19,203,57,517,318,702,537,468,400,134,542,125,921,508,457,13,369,45,634,306,415,517,158,151,75,132,37,477,913,260,324,742,625,998,415,250,465,313,744,985,8,215,609,541,192,202,763,57,692,209,753,940,713,599,703,259,702,409,957,870,778,201,405,240,908,385,785,759,486,177,295,477,979,609,740,203,144,351,745,400,51,991,262,533,357,213,55,874,227,494,108,290,774,667,321,221,942,362,806,445,875,713,277,577,147,96,394,512,95,500,824,48,166,329,350,903,931,192,985,617,49,277,479,340,285,328,706,906,569,954,563,775,363,877,131,64,471,796,222,780,861,287,684,455,104,157,124,482,488,894,518,646,227,609,637,98,291,780,660,918,525,829,336,705,51,573,848,281,901,932,489,137,394,749,463,748,783,896,495,978,452,161,839,584,38,752,47,341,722,756,981,829,166,499,796,529,519,612,995,111,303,541,658,125,473,541,744,149,464,528,525,107,152,409,427,591,608,340,123,114,553,51,787,804,710,2,390,170,241,913,109,404,14,224,336,505,605,719,173,931,352,452,482,519,690,28,46,376,632,565,94,493,946,931,784,419,113,937,268,697,452,399,978,701,312,674,336,694,168,611,62,701,166,538,58,425,921,435,68,932,504,152,926,214,659,471,382,90,520,522,76,515,611,764,185,924,247,169,510,758,845,779,278,407,648,536,136,604,991,397,163,86,6,216,417,318,527,618,856,919,30,50,77,565,207,868,864,289,857,421,807,644,783,120,593,958,713,738,879,322,842,986,303,917,616,845,179,820,550,458,721,0,850,666,101,883,860,41,361,94,577,772,163,166,673,532,925,879,37,411,913,800,206,145,936,902,902,247,584,452,357,89,752,970,13,131,339,944,851,44,962,251,687,674,734,179,212,512,321,472,6,617,780,987,729,399,538,560,517,45,481,318,21,612,790,945,105,719,936,82,166,572,419,781,961,162,759,966,55,277,558,163,747,887,773,835,466,987,411,298,86,776,945,915,563,909,407,991,96,697,729,375,25,898,756,819,39,729,476,369,945,231,180,352,111,36,738,530,988,312,315,579,866,984,849,700,201,534,505,482,678,481,77,119,729,994,365,904,132,723,21,510,242,509,8,534,290,909,430,978,208,282,494,59,213,614,610,965,300,941,178,497,570,875,473,622,520,574,712,136,141,320,725,732,628,202,284,915,491,633,941,248,198,8,113,280,846,360,624,904,251,480,222,483,175,957,753,104,985,994,872,376,625,828,981,660,861,98,713,677,828,673,163,777,895,14,844,55,565,78,51,372,849,209,572,503,126,931,346,638,613,713,431,749,491,503,967,239,562,926,586,792,704,713,655,787,494,51,750,255,424,713,485,621,306,613,715,346,13,545,777,640,30,136,277,624,195,842,628,670,546,452,706,701,492,614,321,84,630,615,111,689,557,636,346,514,260,291,612,95,583,106,798,447,34,12,32,903,734,789,844,668,3,271,493,832,948,146,416,877,106,696,302,791,828,259,21,832,8,990,990,920,174,350,705,89,277,642,216,970,549,486,963,568,603,855,656,110,20,555,455,612,244,600,412,920,67,209,596,715,191,498,534,283,58,171,438,265,498,21,42,22,306,909,965,41,957,845,92,874,984,418,784,516,68,200,465,806,392,428,791,363,199,756,899,199,711,304,380,62,932,100,277,697,684,522,811,681,845,362,393,588,382,270,308,956,981,338,71,23,779,328,806,722,713,880,288,723,445,670,956,363,329,636,192,235,571,505,160,959,908,929,327,285,735,411,746,174,913,849,204,125,270,157,726,350,672,722,670,377,590,164,885,195,925,392,591,670,337,23,798,760,94,578,43,230,762,327,675,200,632,132,984,781,931,708,616,964,322,478,512,957,16,635,19,57,348,982,44,45,929,90,577,411,837,512,236,130,106,223,778,115,612,997,699,280,537,573,2,671,105,47,819,418,452,483,496,147,986,754,758,987,656,90,62,605,700,53,124,318,919,331,347,497,340,710,795,497,416,945,114,662,430,625,822,463", + "721,526,831,482,621,105,496,837,355,12,608,209,855,958,819,781,193,831,630,325,746,994,9,601,108,5,908,160,14,166,197,538,212,418,618,872,501,207,243,96,569,389,41,682,776,617,349,894,31,673,598,364,429,453,859,9,37,951,652,706,933,304,998,327,210,921,447,957,757,105,196,56,126,545,870,328,404,25,462,129,432,489,874,91,756,484,652,903,580,152,125,699,901,26,77,755,841,875,449,8,317,267,696,941,864,873,491,116,986,417,971,989,151,897,920,87,432,688,910,234,155,836,84,99,194,162,1000,664,942,895,929,277,343,729,324,718,536,880,731,631,844,161,558,60,536,790,139,293,162,221,604,894,461,35,74,958,832,617,303,608,951,413,76,104,860,482,46,908,635,136,9,134,297,253,381,748,52,834,149,114,611,747,689,213,846,395,846,940,756,642,598,873,727,901,399,500,432,389,324,2,542,53,377,797,515,839,889,771,947,238,378,167,207,986,974,956,189,702,139,470,14,301,434,714,757,110,206,989,522,236,10,350,259,657,444,306,105,626,43,477,725,44,859,426,121,190,901,410,591,946,935,494,594,642,309,961,708,932,638,916,178,468,464,168,123,694,311,833,688,689,388,297,400,127,841,318,447,49,798,66,449,618,890,533,474,33,612,28,134,424,481,19,365,855,185,157,881,23,634,692,394,276,443,716,850,712,529,183,824,125,540,526,913,903,345,433,356,574,737,319,802,507,448,599,288,914,940,404,986,50,939,945,623,950,313,617,131,963,325,631,890,978,356,358,125,546,741,336,829,262,693,930,261,189,952,818,847,83,695,696,238,323,899,388,3,805,878,405,227,547,652,574,946,915,649,459,496,126,800,875,628,647,473,869,829,5,18,965,789,469,262,614,937,60,714,726,515,839,363,998,625,546,642,148,385,102,269,292,199,681,145,222,161,243,153,628,409,73,290,458,692,952,15,212,802,698,535,759,404,664,611,774,714,644,404,331,734,604,376,196,659,87,21,150,483,23,488,128,392,866,301,976,702,901,671,850,0,109,63,537,332,616,105,132,860,50,271,848,235,266,123,297,1,798,527,85,595,535,308,206,222,723,69,144,725,626,753,461,448,65,858,403,922,908,184,648,286,296,775,471,970,780,367,9,574,307,705,478,781,48,447,760,440,615,914,364,553,780,856,1000,690,104,164,930,171,729,595,881,87,744,104,290,602,139,115,145,733,737,849,419,904,862,911,196,832,249,650,33,208,181,353,98,104,217,115,118,35,974,276,935,663,936,823,274,726,889,565,45,387,476,376,26,894,589,445,819,700,214,422,84,797,820,766,435,287,587,2,366,32,730,121,989,678,42,796,482,809,964,70,340,93,34,655,693,764,745,272,247,355,11,369,77,649,201,417,450,892,426,567,900,665,275,191,30,235,728,413,936,535,659,667,193,78,285,865,197,399,526,858,985,608,778,727,919,352,204,253,927,211,934,577,705,691,746,958,153,557,716,68,683,568,871,765,401,557,806,167,823,333,588,681,53,24,222,881,409,412,111,974,43,39,792,848,739,816,555,584,901,667,981,331,860,746,748,454,86,994,595,762,645,446,124,710,654,259,969,962,281,946,975,872,842,513,913,847,36,479,126,588,749,290,6,1,49,299,146,252,244,896,994,372,891,100,161,15,78,71,101,314,33,582,673,225,733,744,288,652,448,681,358,815,380,45,460,746,515,101,953,55,535,19,695,97,420,447,135,745,701,80,9,271,791,296,656,470,584,111,375,863,546,980,798,135,361,998,700,885,873,24,21,262,468,776,7,373,399,549,444,706,77,532,605,501,147,513,356,569,385,733,541,899,709,514,507,710,931,548,111,274,437,612,726,6,148,731,993,455,904,222,278,88,778,834,268,961,765,255,766,103,730,403,850,760,776,523,85,662,152,771,631,813,850,204,586,150,342,427,219,562,459,889,913,265,958,751,837,849,562,68,285,919,653,745,640,752,711,430,600,922,929,683,921,39,619,214,409,578,807,159,428,781,964,620,455,702,619,708,251,249,162,205,853,351,713,633,3,995,461,159,902,508,280,19,320,728,752,220,933,585,595,79,623,371,98,11,645,251,778,747,635,627,327,305,221,300,613,974,466,453,166,269,867,26,486,521,406,834,176,878,225,530,435,455,929,651,652,958,386,13,40,480,617,400,512,834,173,173,610,234,25,791,950,337,483,81,496,304,965,313,710,43,61,114,852,493,131,759,575,943,435,113,641,520,738,666,782,189,603,28,123", + "100,607,958,932,141,619,372,639,658,168,847,352,710,659,685,552,569,264,347,93,728,9,3,804,286,933,999,790,329,685,789,546,393,882,981,85,875,932,433,792,432,936,635,810,449,518,676,472,898,710,22,122,187,188,17,754,6,625,32,293,657,590,319,90,114,650,726,437,828,128,534,100,729,969,64,59,663,791,852,676,150,624,876,930,569,278,901,625,642,845,754,680,895,679,776,48,682,533,82,307,687,658,26,452,932,954,864,627,26,527,907,668,860,123,457,65,328,222,504,138,846,691,581,264,24,987,671,847,398,914,26,692,865,899,641,842,658,245,106,926,602,532,38,72,299,696,242,210,278,565,408,439,713,86,311,987,850,109,354,582,898,794,294,969,587,689,739,328,850,200,792,815,875,140,670,175,477,753,129,641,681,379,37,833,249,220,15,219,870,164,741,582,605,618,880,807,97,951,887,539,574,456,244,771,235,889,167,959,705,330,187,371,49,184,696,583,904,494,267,273,511,712,449,298,970,304,356,693,285,81,7,881,175,835,208,123,709,34,944,102,282,74,568,557,681,970,930,192,615,939,684,320,19,682,675,396,796,989,768,868,912,904,140,835,815,323,46,504,85,887,687,67,898,470,532,837,835,641,372,149,629,986,807,870,411,734,38,965,325,941,816,362,61,475,465,312,316,475,928,948,583,216,308,160,427,744,866,88,134,407,574,392,740,203,271,864,247,610,556,891,299,706,811,379,444,658,933,504,974,583,279,503,120,686,713,87,191,716,703,769,141,651,390,256,279,24,299,23,509,827,79,749,460,116,996,450,94,557,258,579,839,132,755,334,787,173,985,654,127,358,780,591,588,386,866,554,917,625,769,443,84,523,509,251,221,799,376,77,148,845,293,834,875,396,898,183,495,170,130,907,418,664,962,674,69,961,299,335,989,8,639,543,482,576,869,503,2,202,316,348,409,42,995,240,402,194,45,729,677,974,801,948,420,887,274,273,963,784,793,876,355,563,778,986,804,529,887,842,167,419,756,490,383,57,98,666,109,0,760,282,627,81,555,988,681,471,985,660,925,16,590,380,183,977,920,823,288,58,547,406,693,422,3,97,583,303,243,575,122,25,993,108,675,709,111,955,626,234,603,536,309,75,567,666,864,537,551,553,598,438,213,641,476,918,53,815,997,512,832,794,408,594,970,271,124,582,864,614,518,505,11,726,723,525,981,91,841,628,308,913,323,987,320,485,424,875,985,155,294,249,145,175,360,340,555,495,394,954,626,105,879,43,525,692,412,802,555,938,346,765,96,820,803,16,584,393,831,40,430,724,272,387,278,806,36,570,930,743,649,438,165,261,637,941,370,379,631,414,419,173,751,167,787,622,94,294,211,378,745,332,336,692,151,467,890,151,174,879,575,256,588,428,649,203,444,548,49,192,797,352,595,918,442,610,432,925,537,685,122,309,773,320,148,432,798,155,931,138,654,775,994,126,353,300,491,726,481,258,566,9,73,420,659,934,385,347,347,286,419,242,166,130,538,696,644,913,340,979,148,709,961,943,250,566,123,973,512,215,407,33,23,238,635,665,901,427,252,240,265,842,205,869,713,952,391,632,835,734,849,143,366,568,660,470,56,593,936,587,370,596,907,3,836,396,441,963,498,713,631,89,793,549,676,681,634,540,348,424,397,799,872,759,683,214,361,229,2,447,654,313,939,390,510,443,82,115,739,583,804,10,951,513,856,230,914,882,141,669,900,628,870,646,410,635,493,616,989,619,258,772,459,473,70,800,570,710,795,987,415,617,154,476,70,226,409,331,851,457,793,802,765,212,34,580,440,337,16,547,986,81,596,154,455,307,624,600,178,217,854,26,101,801,934,308,159,617,104,951,32,439,975,151,666,89,562,117,426,335,830,902,993,469,139,189,448,574,167,349,427,345,692,892,747,820,99,305,710,529,534,711,414,798,880,674,528,335,444,823,665,328,383,37,662,948,948,604,561,495,12,701,367,610,753,376,226,930,723,141,851,838,87,380,847,214,848,83,870,720,800,514,902,107,761,690,20,114,670,169,574,32,340,553,191,188,169,451,857,903,299,20,925,656,600,797,341,281,43,578,862,124,815,435,293,50,764,670,131,321,319,928,247,690,183,440,904,403,246,755,401,743,357,879,181,451,358,189,515,492,782,702,843,307,363,246,469,546,600,821,774,501,642,672,948,54,376,874,713,417,531,458,177,175,984,709,755,327,886,212,315,775,614,74,567,608,592,183,321,511,208,411", + "395,119,774,521,25,319,810,560,204,159,401,947,948,136,852,628,923,702,749,623,673,457,89,403,410,542,69,356,587,132,294,601,663,256,177,623,805,881,609,898,988,565,190,805,35,148,314,374,478,142,323,338,737,404,260,60,941,770,469,861,400,770,18,579,387,549,954,741,69,515,897,943,176,719,827,559,981,205,504,338,252,736,430,934,438,546,414,289,61,874,944,685,790,200,13,510,498,313,507,835,247,547,728,974,987,437,72,305,858,929,30,611,314,398,548,137,344,169,11,860,651,439,160,98,816,559,263,220,658,941,209,254,687,769,998,712,407,764,846,219,974,724,464,294,94,144,330,715,943,615,719,262,867,327,86,638,70,385,156,375,662,358,332,152,879,166,300,640,798,981,536,103,26,251,822,573,410,91,48,290,638,263,674,496,333,345,430,948,931,423,138,182,207,68,742,609,992,889,871,436,788,246,935,124,541,775,113,44,78,617,14,617,755,868,403,666,778,795,373,140,816,245,820,762,654,184,954,962,490,485,8,109,104,949,629,759,284,78,571,440,725,822,917,521,193,724,725,520,723,448,295,128,27,371,169,763,361,353,834,190,595,180,859,188,711,45,823,890,336,860,702,43,466,335,819,782,43,675,424,373,318,541,223,7,366,383,340,11,159,619,649,977,493,781,128,307,740,471,20,587,197,871,356,882,311,394,955,577,833,486,701,281,25,297,666,767,741,1,609,956,716,755,943,273,842,35,590,103,789,149,277,400,614,872,72,181,861,286,92,640,523,346,513,440,465,113,218,572,347,899,787,465,562,998,671,762,719,297,842,57,899,833,443,523,295,708,911,315,427,240,989,569,47,650,217,294,733,90,850,644,540,862,651,352,378,739,303,686,833,564,266,135,939,985,309,570,854,906,879,136,635,898,878,827,803,608,388,100,226,194,589,273,585,87,107,529,59,616,17,13,925,799,712,783,751,157,76,167,212,652,444,590,962,774,780,349,155,696,77,389,468,171,12,410,430,566,246,218,369,93,670,899,413,246,248,101,63,760,0,272,828,520,792,384,525,36,666,632,30,364,405,463,562,62,587,328,77,815,637,388,108,333,127,926,695,903,992,80,641,450,495,959,728,761,415,52,84,871,276,331,61,269,12,62,694,716,651,417,305,264,334,687,237,151,797,502,430,400,690,374,367,615,730,68,740,962,272,360,611,233,813,218,904,263,124,823,489,523,168,191,156,510,84,10,110,781,539,40,340,240,905,273,816,834,418,705,242,510,787,494,935,619,930,397,667,502,717,546,996,585,836,729,372,438,64,923,4,749,736,822,532,720,598,394,273,499,887,805,655,666,767,742,430,225,523,519,931,620,411,638,344,355,910,821,919,675,377,178,663,194,918,266,735,724,174,300,457,871,257,118,958,870,216,251,601,251,231,533,377,339,964,45,60,913,894,195,673,448,969,176,422,20,138,67,259,985,430,635,777,180,81,30,507,736,928,88,490,171,860,678,324,999,372,800,137,736,486,141,57,395,63,573,173,442,606,199,387,995,907,996,534,826,186,39,194,149,85,667,909,459,305,389,856,17,752,520,504,719,84,653,429,650,685,21,462,256,725,642,736,912,531,14,635,687,64,117,552,683,648,596,534,252,69,826,806,576,925,530,275,935,285,686,428,306,780,654,869,295,16,291,517,870,431,202,596,590,407,642,37,893,280,452,705,866,496,154,597,8,655,42,405,969,125,669,210,819,355,429,158,61,226,77,825,854,973,694,821,798,806,186,504,253,194,140,996,615,365,160,862,769,727,385,256,148,830,624,594,808,636,499,25,182,901,686,204,262,985,788,700,804,738,508,343,737,497,767,265,725,839,242,314,297,675,439,826,765,237,577,301,388,457,768,614,50,921,626,377,18,546,371,270,690,127,955,310,487,945,107,667,423,739,690,98,515,525,125,632,121,207,927,930,394,629,215,448,1000,176,468,393,607,552,214,731,818,881,746,66,733,190,120,218,657,103,897,88,900,989,525,517,464,669,498,483,621,870,871,435,634,237,929,663,175,471,587,739,956,614,835,558,415,122,658,512,391,297,978,225,725,938,435,961,148,718,980,496,946,852,480,392,547,739,191,11,542,977,575,720,993,883,737,754,228,346,62,166,727,227,339,221,304,706,997,66,58,339,396,838,390,267,508,306,216,264,200,880,122,821,472,724,650,559,701,117,409,464,842,602,437,454,755,620,890,6,486,783,476,578,673,598,969,422,381,613,649,993,676,207,526,379,636", + "800,646,933,535,64,272,953,723,597,342,199,541,213,665,231,693,664,416,650,278,865,973,583,686,995,117,39,29,928,858,809,682,305,491,344,859,108,812,159,118,8,891,968,761,513,624,960,950,849,131,441,266,974,190,628,931,874,189,966,618,559,375,748,886,345,908,711,476,720,40,898,252,798,484,908,209,317,283,347,327,725,170,986,3,88,935,398,2,165,476,56,858,429,845,200,948,617,789,658,193,49,483,868,324,321,658,78,210,976,425,324,251,931,598,22,214,730,454,674,750,246,528,896,973,875,199,478,96,993,130,229,256,995,904,515,311,199,456,203,6,32,902,492,958,810,292,4,698,241,367,684,65,930,456,398,777,675,249,693,776,534,458,748,438,820,150,866,417,239,625,124,819,101,739,73,949,693,772,707,783,904,152,580,942,447,293,408,176,448,540,298,488,488,612,796,749,93,137,189,370,880,279,823,903,905,210,75,733,361,371,314,336,155,377,412,834,725,50,344,335,157,444,272,87,291,704,730,2,792,225,110,167,917,599,181,900,667,999,516,559,265,933,550,354,273,627,398,556,695,903,299,97,699,256,128,528,471,803,835,499,777,520,69,140,662,990,460,875,123,370,251,584,36,505,746,33,855,800,640,381,323,294,622,656,380,160,13,404,798,3,671,316,199,803,317,703,534,771,91,926,90,535,972,460,114,251,173,338,746,459,364,657,716,37,904,935,569,314,879,865,975,190,425,155,124,674,188,214,784,976,836,833,572,402,521,489,243,247,72,742,884,648,247,455,156,671,917,199,101,577,189,232,264,294,586,447,80,124,146,546,760,613,636,589,178,324,482,575,460,944,24,637,799,955,830,419,983,551,706,498,705,238,513,475,82,87,469,357,557,506,885,288,257,129,677,40,134,50,365,567,540,489,882,104,858,559,838,320,303,161,420,222,647,938,725,432,178,854,948,778,960,152,680,640,884,729,277,623,429,835,225,614,530,304,604,112,290,423,988,531,563,75,848,319,761,549,440,73,181,555,437,697,197,893,100,883,537,282,272,0,463,399,354,117,844,469,786,528,801,380,773,195,205,21,319,654,241,688,78,626,591,426,383,445,934,206,958,714,430,747,801,195,979,505,30,726,46,610,705,638,128,700,261,98,234,540,362,193,564,930,142,354,329,102,846,196,658,376,154,848,531,970,713,636,340,506,58,104,332,929,97,558,469,654,195,38,818,994,450,462,22,117,216,669,709,376,628,419,25,11,433,337,493,643,648,237,29,19,197,958,366,498,493,847,215,59,205,35,503,446,180,443,850,464,320,985,801,214,411,122,537,67,84,580,761,235,432,66,401,296,961,201,901,295,796,432,526,838,791,681,682,879,344,500,921,770,113,988,832,173,735,414,62,425,821,856,309,61,597,175,557,477,727,209,558,954,347,232,708,955,445,670,571,63,830,770,732,724,89,800,973,958,919,910,27,846,757,734,624,398,256,13,693,934,975,431,338,270,511,986,756,845,796,446,452,961,650,745,261,538,432,820,774,215,872,53,419,438,849,179,668,396,343,611,579,885,395,302,870,441,700,398,703,318,822,562,826,931,955,838,185,899,502,356,302,224,141,703,841,230,629,913,105,83,714,254,696,625,428,176,151,549,11,247,279,508,775,917,86,596,617,805,534,713,758,838,20,993,563,508,12,65,794,110,580,293,435,7,933,927,375,635,595,517,508,575,942,83,975,846,459,191,768,678,700,721,721,589,208,745,777,410,312,67,536,797,533,902,284,785,602,231,206,360,721,965,711,532,231,334,177,323,412,918,113,971,791,436,321,228,211,699,61,395,29,457,252,220,974,167,238,420,850,768,531,399,616,996,775,214,830,720,448,841,91,420,313,557,460,306,166,525,489,910,361,426,950,28,965,253,947,986,547,378,786,333,442,505,21,155,119,84,833,733,797,730,822,919,468,670,909,591,238,676,541,680,851,555,796,510,576,663,701,656,306,83,395,430,523,875,516,527,396,559,579,162,113,432,427,182,589,476,246,193,247,197,922,106,752,676,184,181,613,929,962,672,310,253,255,819,46,685,802,22,298,565,503,900,560,960,613,205,499,810,48,191,235,561,59,759,780,124,299,474,21,751,77,870,616,924,275,159,329,724,77,55,341,589,540,953,822,156,356,596,463,727,448,248,332,589,645,849,528,155,497,2,260,313,248,652,253,419,826,955,687,386,867,803,586,830,385,72,993,324,156,649,938,258,424,586,463,478,15,159,738,769,46,756,830,420", + "244,544,473,174,537,501,368,704,733,133,675,28,896,156,608,639,93,678,793,289,853,572,57,112,510,687,340,650,78,635,710,986,113,466,361,882,584,274,839,53,924,382,597,330,65,292,774,308,469,146,161,127,687,505,59,422,45,445,677,679,842,958,544,228,283,774,652,760,299,958,82,319,314,91,74,362,611,55,754,858,564,705,158,30,350,666,587,974,234,216,96,186,507,668,16,425,701,260,237,76,588,696,728,517,558,778,199,511,489,891,995,616,52,208,709,150,232,49,385,507,614,796,103,175,145,780,452,913,261,737,435,249,559,486,820,448,630,54,224,496,890,618,19,618,487,747,215,673,676,536,902,194,263,209,430,746,509,410,678,592,998,335,358,836,245,195,299,993,634,528,761,867,389,89,349,203,878,85,60,902,725,594,532,80,779,379,453,263,186,817,910,629,970,927,855,334,841,130,471,725,169,84,709,423,709,942,505,458,749,925,913,596,831,987,81,825,198,917,968,815,469,854,434,309,740,207,583,640,303,57,416,873,122,825,174,27,761,217,76,704,666,834,154,836,56,36,518,93,784,917,583,587,386,233,634,980,130,203,507,527,272,525,194,510,147,154,398,997,255,941,246,240,671,302,26,347,549,144,451,936,7,209,998,9,498,804,822,455,315,254,488,515,337,581,176,183,396,310,529,250,677,552,230,941,801,834,120,973,927,478,536,52,551,686,67,761,40,690,482,729,162,621,701,56,962,487,842,313,566,520,369,197,51,4,384,40,72,497,427,456,651,603,881,330,640,526,190,439,386,451,41,972,69,291,788,790,658,55,749,156,583,37,400,302,865,79,681,921,828,981,608,631,317,661,813,158,748,777,364,532,611,411,469,918,956,279,130,74,968,536,593,519,72,316,514,370,73,859,971,534,956,73,263,950,897,320,214,187,251,725,363,236,157,509,859,483,611,500,654,476,815,152,836,746,398,918,218,447,964,788,59,835,487,966,159,675,836,895,443,760,765,97,517,629,88,777,460,640,754,108,365,447,565,973,764,860,332,627,828,463,0,469,711,191,793,386,466,766,825,756,546,173,533,543,491,82,308,60,929,404,801,89,123,925,5,949,400,104,274,547,669,455,201,257,478,286,363,964,270,244,658,387,873,614,681,987,951,667,982,746,662,890,939,133,780,392,426,835,580,710,528,448,93,10,644,731,17,543,437,415,788,746,972,747,338,634,288,815,316,498,309,991,871,485,477,820,651,835,130,223,969,209,718,514,833,373,856,141,522,367,135,91,412,629,930,310,876,14,113,641,534,980,977,202,895,674,526,540,525,581,475,82,341,856,106,766,279,457,798,595,392,237,199,27,989,577,863,315,955,819,54,640,763,119,878,96,676,286,880,954,96,449,916,682,387,857,131,45,458,813,161,206,148,965,972,432,879,983,591,621,257,580,141,285,356,438,240,62,868,61,729,350,396,583,763,160,967,119,530,407,783,344,678,194,721,447,695,622,708,786,310,362,986,461,211,763,417,526,231,854,532,557,15,124,232,908,285,667,475,676,804,441,469,129,668,311,379,439,502,191,525,64,604,219,221,838,69,670,671,520,519,880,507,982,176,27,857,117,398,345,588,99,838,445,1,319,958,459,438,262,428,253,615,397,374,822,290,839,847,954,972,520,238,480,244,474,596,767,951,487,106,851,536,966,863,307,332,314,298,792,754,404,823,75,824,183,37,143,728,580,605,54,124,791,997,474,342,341,853,578,784,245,444,417,881,305,313,479,935,689,748,115,940,303,582,679,156,367,133,299,991,952,103,376,679,293,45,2,558,350,974,685,614,671,94,644,789,455,891,677,876,271,708,742,158,656,153,59,368,716,859,115,519,482,425,628,499,47,612,559,444,798,582,982,587,527,802,288,748,565,609,584,874,559,497,480,660,399,314,837,952,492,19,189,297,469,614,76,278,142,561,92,217,326,374,784,586,877,654,856,761,782,359,166,952,970,745,573,266,325,29,249,761,321,436,468,607,382,505,536,539,865,282,516,828,212,3,253,443,129,988,78,714,579,11,180,777,395,522,805,612,297,940,453,958,953,544,713,234,565,762,592,922,246,943,412,829,986,760,599,606,909,185,99,473,876,872,555,161,580,242,825,99,824,533,445,712,192,631,192,536,972,199,91,76,566,839,136,46,457,453,36,683,507,468,183,940,720,426,359,981,413,417,421,539,884,702,232,116,690,742,897,677,160,106,733,920,463,621,416,608,990,696,190,905,492,796,136,482,379", + "50,202,588,560,171,367,171,300,88,800,723,442,515,522,585,350,977,830,925,401,320,462,932,509,260,790,662,525,162,789,752,643,168,401,963,929,241,727,903,479,538,799,10,912,34,293,562,795,259,260,223,816,576,566,580,730,681,721,952,503,29,977,812,377,632,846,815,720,571,705,193,675,195,495,905,353,968,573,24,604,219,818,484,353,852,914,210,366,755,339,235,394,518,512,108,12,465,515,396,805,366,912,550,663,315,606,394,915,121,941,930,9,624,512,737,85,36,482,624,120,435,750,293,690,309,582,13,267,388,123,292,682,850,733,672,116,351,749,986,15,552,213,528,265,944,840,789,840,763,809,563,407,47,353,653,876,694,680,534,431,97,786,27,682,141,499,267,317,704,857,722,52,678,89,378,823,563,479,451,703,516,643,170,340,332,375,471,54,464,445,735,295,562,987,552,459,540,656,876,767,89,216,759,108,286,421,142,834,668,204,177,249,651,503,497,831,559,154,385,253,506,778,922,773,687,453,383,384,431,325,881,308,655,870,562,442,375,58,870,782,9,565,547,444,980,72,699,719,612,200,407,308,544,563,842,859,103,313,323,898,141,363,613,146,407,207,124,614,658,606,86,454,499,168,412,749,213,191,162,519,992,430,845,314,411,78,851,623,854,710,712,626,903,548,171,689,427,873,526,18,1000,583,696,861,759,714,989,45,653,939,688,344,943,837,641,936,132,712,877,163,758,357,583,440,424,235,951,741,875,843,235,630,100,557,636,308,179,683,616,623,47,815,294,392,269,894,400,51,989,750,461,839,801,482,489,618,527,744,796,833,420,168,340,83,870,180,674,74,381,770,455,395,632,775,862,517,503,662,4,786,242,298,12,739,202,973,166,414,77,118,434,907,977,694,608,437,232,463,545,942,29,970,581,535,88,237,289,549,353,298,94,80,959,794,972,542,349,402,120,369,5,262,745,156,834,744,730,56,803,467,191,660,757,175,660,465,75,628,572,41,387,251,109,622,539,870,976,966,28,127,795,279,560,525,47,41,616,81,520,399,469,0,39,747,211,339,627,904,519,59,284,727,59,821,368,687,890,189,975,283,695,546,20,50,170,864,608,291,426,676,271,227,83,77,580,111,568,891,259,822,291,447,277,134,273,131,405,355,139,808,253,733,252,198,505,346,859,205,197,749,301,371,547,904,880,680,682,842,596,138,834,497,435,826,218,64,740,3,939,941,411,671,727,47,647,599,416,524,525,846,498,478,677,954,348,936,293,48,439,200,748,86,18,92,743,583,669,616,129,391,628,834,891,353,459,124,876,556,603,968,690,148,862,878,443,607,226,864,114,181,543,731,720,228,448,365,844,114,35,767,882,370,526,186,156,870,804,520,362,57,921,309,155,447,426,290,171,659,693,711,391,254,118,189,405,587,923,519,990,61,695,593,291,724,311,923,920,834,827,645,163,79,900,909,520,936,604,586,190,771,444,649,975,267,961,5,657,340,460,887,830,623,948,476,487,106,850,49,973,4,218,113,212,681,329,823,179,270,18,753,639,454,721,424,832,735,221,794,250,328,349,792,836,600,326,48,154,56,505,645,297,193,847,488,843,701,178,234,435,597,531,553,44,512,170,321,730,195,817,375,655,542,389,226,327,751,180,897,565,453,105,900,193,940,131,973,515,873,771,517,696,472,761,645,863,8,391,200,378,979,17,578,894,720,398,386,16,374,617,269,419,311,723,600,515,766,987,863,39,211,57,202,359,944,407,692,337,239,783,48,369,807,927,18,344,7,966,52,249,619,109,713,61,151,24,886,888,299,350,933,524,631,942,417,153,423,839,532,8,463,995,870,278,94,461,285,846,875,93,93,790,353,442,216,746,794,741,475,443,40,991,620,317,574,84,402,784,149,644,322,190,207,746,738,577,655,263,353,509,160,984,317,790,93,506,781,418,593,869,333,765,642,43,96,16,36,385,753,660,306,826,830,363,108,556,571,628,348,846,690,121,854,976,274,980,859,943,753,14,293,166,141,600,7,389,642,390,438,382,104,553,562,798,376,214,837,74,820,890,10,495,500,87,561,155,121,923,896,628,747,900,634,495,398,924,764,25,144,661,309,505,491,661,269,483,183,885,530,665,179,922,929,852,289,803,361,637,377,348,47,896,195,303,383,746,337,924,4,301,626,836,915,173,627,305,92,991,125,159,663,100,715,571,299,501,260,947,863,938,289,388,341,958,865,262,166,483,834,47,768,333,170,339,920,183,386,511,842,166,666", + "746,365,207,208,714,219,439,499,994,164,134,306,692,97,293,713,978,635,298,34,435,854,746,554,59,854,45,52,9,789,404,700,797,183,800,135,446,735,403,778,801,217,132,313,261,459,790,799,207,921,742,721,968,477,804,991,335,368,656,309,525,284,557,606,406,56,444,995,658,780,153,655,726,234,202,748,869,710,634,323,893,245,99,104,560,889,654,139,370,640,226,769,290,580,13,901,369,667,134,231,882,477,173,978,143,772,981,128,531,642,256,292,235,885,636,786,595,826,276,456,148,702,16,968,148,783,797,949,579,112,50,654,881,648,409,846,951,960,344,520,832,102,998,497,738,222,413,187,916,672,862,538,62,271,897,914,394,656,762,825,593,163,533,302,919,258,796,136,874,852,173,590,669,344,146,752,998,883,9,192,503,116,43,26,625,876,11,349,554,923,228,415,34,666,162,295,277,66,501,553,351,401,128,87,126,278,784,483,528,231,564,957,347,476,598,198,205,544,78,241,947,396,799,334,167,381,951,349,569,887,237,257,195,586,112,655,361,627,31,670,545,65,739,677,363,388,649,162,509,526,500,399,986,562,954,937,807,135,18,386,999,789,409,746,506,153,497,638,803,831,794,362,96,596,213,90,995,14,262,958,867,285,603,424,140,720,184,771,438,826,175,981,177,732,934,523,499,842,639,734,459,281,47,910,108,663,168,103,971,15,359,343,886,482,950,521,702,562,22,7,133,44,639,601,743,391,22,944,873,849,498,311,635,3,903,289,49,435,220,708,618,350,690,118,179,785,801,9,768,285,154,871,183,42,654,916,720,552,174,650,984,156,150,182,930,354,984,657,284,921,150,870,449,332,281,712,334,510,844,930,754,472,963,213,241,844,17,692,124,464,242,55,566,893,821,232,725,793,506,549,822,73,186,664,495,298,877,641,887,354,527,75,104,486,282,261,998,321,222,819,716,410,969,828,389,655,863,128,371,39,347,727,453,864,840,448,245,14,381,149,362,288,962,589,67,833,831,639,812,957,517,332,382,892,659,361,105,555,792,354,711,39,0,714,920,7,558,683,258,775,895,208,591,571,581,515,347,473,551,396,797,677,197,445,904,428,347,664,165,154,961,402,652,870,553,404,242,710,270,370,606,628,339,896,318,731,74,861,31,613,411,101,827,369,832,530,656,840,369,618,175,899,669,274,113,95,275,592,581,515,899,98,502,417,702,771,649,185,20,563,766,816,493,856,986,225,98,474,442,221,613,380,770,416,302,993,71,111,147,820,815,709,879,102,726,179,887,962,354,170,80,12,116,889,952,657,638,497,104,992,550,448,583,392,150,225,819,752,470,564,600,366,9,466,214,633,482,763,82,677,759,147,69,29,736,149,249,624,819,600,255,252,23,985,672,141,289,601,195,609,953,485,926,880,396,496,526,247,61,845,387,596,639,209,569,419,685,261,68,356,807,725,260,746,446,359,96,812,455,674,539,172,720,708,827,914,56,611,765,540,815,133,916,617,412,698,136,546,495,817,713,742,946,13,986,156,116,944,881,897,273,817,486,805,659,345,830,700,441,940,261,376,708,329,345,891,901,903,813,466,337,562,276,984,968,393,810,383,686,473,51,635,779,92,582,1,340,800,398,400,794,359,975,200,978,261,831,359,749,324,559,749,667,766,827,697,767,779,449,434,10,287,107,124,507,848,446,845,906,508,258,88,474,87,527,136,658,178,490,457,497,895,7,479,466,83,539,659,593,224,228,207,99,184,53,705,786,34,250,358,444,9,837,64,827,700,292,777,556,551,306,978,688,467,689,434,7,409,598,566,355,71,280,605,898,161,757,580,877,838,224,847,649,391,176,2,31,892,518,580,229,934,258,385,814,383,939,239,449,206,141,447,675,244,912,699,210,10,392,803,779,244,613,807,300,384,621,541,916,123,726,384,179,807,4,214,897,933,807,628,840,902,807,28,249,567,172,442,514,454,914,136,483,306,120,595,706,874,887,96,694,967,508,882,876,388,81,899,750,602,267,197,589,227,585,931,166,665,789,799,610,948,187,222,185,350,890,654,198,774,215,368,59,218,515,961,996,10,76,272,85,381,286,759,797,303,180,217,94,907,669,350,480,369,61,676,839,491,385,828,188,28,605,386,609,581,36,737,555,912,632,925,895,659,188,987,1000,712,574,603,201,320,484,534,291,106,609,346,427,169,713,396,328,941,532,296,670,981,739,978,662,586,250,419,756,928,555,592,422,825,784,810,321,342,409,561,668,545,803,804", + "500,277,107,277,685,524,698,717,188,413,382,207,364,160,351,400,439,441,923,932,144,197,422,764,912,895,64,529,117,112,784,396,420,178,255,394,249,600,246,872,243,27,406,456,453,640,139,177,770,918,200,31,528,688,504,96,224,417,548,443,162,921,409,18,769,69,187,78,835,440,857,52,9,623,154,685,632,620,522,722,229,922,418,83,91,201,794,870,587,94,121,156,354,270,150,18,617,978,148,266,347,821,589,120,558,134,925,82,857,472,123,70,321,45,716,864,268,307,449,141,929,844,113,7,292,480,876,9,798,648,929,106,127,367,850,443,389,559,913,25,494,100,809,973,773,992,491,15,979,968,423,344,524,789,97,555,548,63,677,585,955,962,561,234,859,968,559,698,699,486,904,87,416,96,923,363,768,910,542,192,590,816,62,550,372,389,955,937,829,137,691,524,546,739,122,884,422,210,928,373,306,573,908,530,115,608,635,786,873,581,666,362,655,17,836,276,224,495,599,360,277,306,231,574,434,230,743,956,78,228,627,152,266,787,746,466,327,838,389,84,509,342,19,988,411,604,401,592,398,762,642,868,745,373,994,651,732,159,865,689,32,772,62,1,619,607,577,560,420,444,428,397,908,458,63,293,980,7,423,309,463,840,512,752,782,994,107,939,157,991,35,110,824,379,170,686,211,281,760,385,907,650,206,888,963,758,379,181,368,407,201,108,868,92,943,882,246,353,760,326,756,971,870,373,512,21,242,572,44,500,153,224,73,458,399,922,545,487,965,414,186,162,195,283,934,564,66,603,999,975,885,886,454,127,40,792,655,348,747,703,965,265,495,951,924,698,584,347,246,396,594,225,785,423,962,614,701,750,873,877,486,657,782,868,249,358,45,143,441,896,707,206,466,852,694,198,559,923,253,209,983,506,777,768,904,974,312,891,169,11,629,672,473,958,329,443,821,457,172,119,328,552,326,32,628,657,386,856,996,58,875,286,519,115,327,434,708,145,201,364,955,300,774,998,875,552,439,127,886,795,16,434,670,405,918,94,132,988,384,117,191,747,714,0,792,989,530,749,863,444,709,183,825,783,467,631,560,613,89,11,205,821,136,662,48,790,979,222,399,566,221,740,100,505,446,403,674,122,208,340,759,826,729,71,999,91,967,28,669,198,715,199,707,355,673,381,70,364,175,373,881,588,358,122,937,5,989,877,39,946,138,900,349,751,38,5,860,709,904,178,17,957,914,597,407,176,515,494,425,890,305,554,382,785,39,360,603,545,168,872,118,844,211,744,145,356,256,295,368,469,585,166,366,929,859,322,581,541,865,937,157,491,16,205,770,174,181,347,823,753,631,141,94,268,389,811,639,30,787,674,449,721,703,837,488,381,167,313,175,585,880,333,890,981,651,630,921,690,928,64,872,510,816,976,602,875,280,553,600,715,759,835,198,630,500,442,474,288,276,706,167,865,216,336,260,584,833,304,648,615,421,623,952,395,698,294,169,375,475,25,29,890,911,202,328,673,533,107,651,784,501,87,987,50,996,701,479,875,182,77,677,520,88,554,226,244,27,301,416,999,402,122,489,336,239,928,43,526,19,295,768,747,145,721,525,770,168,55,132,389,747,201,566,958,906,450,229,474,716,139,606,358,487,439,952,955,440,585,746,671,688,599,721,718,393,819,691,848,546,996,886,259,777,795,248,780,42,567,145,79,324,976,584,494,999,435,752,612,447,994,585,439,885,56,510,29,967,364,634,23,292,453,59,649,326,45,481,383,617,641,908,173,940,26,511,862,683,880,389,620,83,35,811,391,562,35,575,172,642,766,914,347,676,880,767,952,546,903,28,526,545,348,310,273,707,629,946,81,151,872,763,925,503,232,157,503,245,697,555,978,443,108,311,460,711,670,339,957,71,847,372,460,114,46,368,488,956,42,932,399,526,772,202,292,593,161,543,879,757,800,480,892,661,384,35,68,12,511,230,6,385,592,980,608,983,454,924,676,859,308,715,262,704,560,118,769,147,744,903,786,544,328,962,467,43,924,300,499,471,161,77,983,693,332,999,219,746,422,522,526,607,625,565,51,66,415,618,279,666,517,495,30,295,652,882,899,580,233,905,151,665,205,64,419,24,463,414,133,440,60,709,816,762,21,15,127,960,494,591,896,97,422,389,500,657,738,819,749,780,223,335,106,191,188,232,363,516,996,344,300,963,364,666,98,567,349,40,780,673,370,749,657,506,583,334,889,949,328,906,395,84,880,638,246,850,836,912,720,666,772", + "962,556,864,693,820,797,939,614,879,634,672,631,527,951,888,112,471,927,476,152,404,925,584,914,629,686,526,7,948,884,461,510,358,897,569,333,448,288,122,178,198,248,116,894,571,59,564,218,705,457,303,778,375,31,612,713,527,345,140,788,867,576,141,136,676,633,890,725,680,616,976,435,917,866,859,260,667,34,550,412,33,192,501,941,864,686,323,586,843,579,439,457,77,958,714,351,31,322,31,953,185,982,816,939,724,998,772,248,168,981,803,740,150,605,824,950,799,472,175,790,176,853,250,39,270,951,308,59,557,629,694,515,350,881,923,805,835,593,812,325,645,945,739,366,528,798,611,658,532,524,753,186,784,255,791,289,969,622,268,487,69,812,943,214,844,353,434,926,122,321,194,727,139,334,138,239,560,84,287,523,354,840,573,566,33,998,344,991,359,346,938,441,319,578,593,170,228,178,182,190,402,754,844,823,417,523,594,492,258,535,492,277,164,737,431,209,988,840,63,316,616,594,519,877,925,324,803,913,846,935,257,132,54,619,643,438,740,517,927,380,826,615,203,436,217,57,274,969,5,113,575,542,571,176,820,474,84,95,882,112,227,114,577,689,469,75,410,940,981,193,564,562,736,827,232,641,412,468,520,867,583,547,251,339,667,319,563,569,229,772,287,164,615,859,772,796,932,135,738,569,990,111,223,236,143,803,718,726,439,40,252,938,839,370,92,984,307,732,75,519,576,709,672,164,322,939,903,87,824,242,718,589,95,469,981,407,884,230,32,428,911,528,790,232,570,636,481,669,743,213,479,84,351,117,659,339,80,418,434,43,302,527,22,58,171,737,306,794,855,545,571,430,953,795,404,218,658,427,377,526,896,824,264,523,858,129,883,246,766,251,968,854,968,504,555,916,41,98,278,667,551,419,578,672,479,113,520,379,77,980,879,177,222,251,702,174,261,534,426,861,81,356,522,395,783,468,962,221,662,900,81,584,785,21,463,621,676,144,637,486,436,287,3,964,15,691,118,251,493,804,261,300,397,8,453,577,860,681,525,844,793,211,920,792,0,116,10,925,656,766,845,54,895,275,185,59,511,883,491,510,546,79,960,297,20,277,80,947,102,270,224,722,954,499,876,225,814,232,607,999,531,630,782,291,568,537,172,331,609,281,835,553,65,821,760,536,753,427,682,728,349,331,249,205,335,275,243,446,53,896,221,418,10,548,888,935,125,571,24,277,571,648,622,542,533,950,624,195,638,919,679,375,305,686,800,83,967,282,673,735,111,456,794,103,16,215,263,304,164,459,927,94,691,222,464,616,135,166,197,483,911,295,230,204,13,101,930,765,986,313,760,679,184,109,378,501,791,562,41,396,164,202,476,885,922,308,698,869,90,419,327,215,993,892,496,927,45,95,518,344,530,839,311,702,528,407,20,86,650,575,776,41,967,534,130,218,629,286,156,358,299,786,207,168,686,965,639,861,522,254,292,852,525,205,603,996,481,815,99,966,650,544,256,207,437,978,629,154,149,478,785,126,39,617,688,564,449,515,740,360,175,980,245,572,176,504,678,812,323,532,987,666,161,301,649,368,601,426,726,363,451,506,644,61,463,486,4,204,89,417,264,659,11,935,750,314,705,812,811,916,362,225,225,556,168,95,164,484,870,579,365,269,679,196,816,220,353,363,768,419,597,53,243,159,408,63,287,212,175,174,286,613,633,496,662,79,927,53,508,855,553,990,121,115,459,432,857,599,719,824,975,651,632,911,964,40,90,752,428,892,350,793,580,418,322,265,547,488,996,756,371,415,365,178,234,526,920,158,485,817,260,233,472,221,722,761,996,797,447,749,259,572,778,544,162,571,38,244,749,914,894,915,930,151,965,670,695,205,744,416,69,269,760,632,56,236,558,641,234,37,138,993,756,1000,710,111,189,446,903,60,630,558,972,52,968,800,491,125,371,453,874,594,319,851,107,906,999,618,481,239,745,290,926,639,703,7,534,395,947,700,226,309,142,92,206,411,281,603,213,799,259,437,33,919,478,923,254,634,531,645,50,822,916,241,441,288,831,422,427,854,297,164,778,952,921,544,948,144,763,899,268,716,408,931,73,36,175,819,475,917,27,186,696,911,87,978,577,337,678,830,837,742,582,681,416,778,321,321,52,443,155,779,402,862,879,474,954,597,144,457,139,771,382,530,163,185,736,38,540,318,926,388,901,425,295,509,340,187,355,383,543,106,710,20,834,621,180,33,376,652,914,178,398,683,326,777,281,938,82,375", + "753,681,34,95,43,253,370,535,432,517,915,274,415,395,129,318,389,38,953,822,987,338,70,372,209,482,967,196,526,340,443,524,764,885,360,397,744,708,387,641,262,521,220,583,922,644,939,194,782,55,956,340,119,62,524,286,780,946,441,639,872,406,984,798,143,334,744,939,407,438,714,219,378,409,582,387,489,540,85,264,553,718,924,575,650,738,619,880,993,356,410,883,530,32,687,522,49,998,433,54,155,280,938,907,267,964,887,350,301,743,13,243,547,772,430,402,225,787,445,682,951,36,277,906,33,642,542,790,934,817,418,380,495,400,108,518,327,685,182,809,254,386,853,345,327,368,112,802,616,207,995,593,86,712,121,264,487,807,99,752,560,874,501,622,597,60,16,195,546,171,805,437,660,828,216,193,206,801,602,210,94,806,659,834,168,803,26,345,95,779,365,687,841,181,650,523,24,400,778,214,217,860,548,649,920,402,147,885,732,952,92,596,862,426,333,395,803,878,558,107,370,866,774,178,130,888,600,773,731,578,981,967,412,246,702,111,115,959,84,863,866,119,250,150,320,19,185,744,55,735,61,808,83,473,127,633,404,999,391,614,107,883,796,487,65,557,937,597,506,400,204,206,353,392,158,440,650,826,414,960,742,201,554,33,104,194,638,772,94,372,167,794,438,292,241,473,478,563,664,921,780,82,649,706,238,754,513,908,471,797,172,567,89,918,483,430,602,219,733,901,612,766,582,304,374,867,995,134,444,79,989,935,971,234,841,206,775,961,408,216,353,279,533,242,775,890,446,574,399,283,788,135,876,347,4,203,759,103,560,518,180,211,712,503,254,853,290,996,829,437,991,681,259,505,498,406,477,323,747,36,796,508,90,18,979,697,719,252,784,386,595,814,632,479,526,935,314,579,774,874,120,689,65,113,393,454,784,562,488,280,894,591,946,497,527,869,536,856,474,657,643,209,119,841,832,349,484,367,365,380,452,969,774,931,849,200,341,254,457,374,258,43,214,148,820,169,5,95,24,576,666,629,645,743,540,772,50,471,36,469,386,339,7,989,116,0,859,526,768,16,714,44,478,780,981,805,815,951,542,928,487,350,238,206,153,111,406,86,812,267,18,799,466,942,579,530,159,128,144,684,989,398,38,782,530,862,919,104,89,702,772,449,347,930,887,539,816,482,494,607,691,141,893,11,440,334,738,496,822,593,63,379,201,984,600,805,594,114,282,953,10,674,63,248,487,269,478,822,693,560,456,950,137,719,265,487,334,234,299,825,657,43,486,254,821,91,848,386,219,729,803,692,919,379,722,327,904,564,647,952,863,614,431,576,321,13,827,701,847,348,694,988,256,146,619,39,462,206,274,186,225,124,247,112,260,770,128,411,685,851,765,854,691,376,541,386,586,309,234,100,104,102,388,258,291,123,592,688,189,759,118,722,507,220,569,485,37,309,518,400,650,500,400,716,519,597,390,469,414,832,328,986,900,250,629,203,787,473,178,796,609,267,495,515,922,161,329,234,189,575,311,867,255,891,993,797,776,652,642,783,329,512,106,840,326,949,731,243,932,544,890,287,172,156,333,413,1000,346,82,855,205,42,899,542,263,168,370,923,970,357,355,885,632,933,228,568,352,377,154,941,41,3,427,11,704,295,481,755,452,252,760,98,979,626,998,940,407,104,217,119,963,293,803,196,727,71,634,70,955,287,785,412,359,294,632,926,542,464,143,912,694,50,363,346,656,775,245,338,255,552,648,684,304,858,750,858,434,170,430,698,577,121,513,463,272,375,104,796,399,89,137,120,728,200,967,450,67,338,919,722,475,333,722,486,291,391,703,421,788,68,599,195,629,359,74,754,159,840,298,700,283,797,315,839,800,971,873,521,524,207,199,807,648,867,119,67,316,466,682,516,367,858,934,802,154,985,806,172,743,453,802,579,200,860,564,778,975,91,74,573,999,811,180,986,137,301,487,299,177,728,198,750,924,603,736,280,381,939,63,491,33,485,290,353,647,679,568,633,648,195,807,192,194,912,329,621,936,183,158,246,886,577,63,638,712,587,254,831,562,9,79,429,532,517,806,173,861,552,42,223,473,247,776,424,701,929,960,731,113,968,987,809,74,478,888,414,98,270,937,973,980,999,131,443,180,537,415,533,379,103,591,432,745,460,119,556,537,1,106,688,263,616,873,461,734,653,956,75,229,725,448,320,170,969,738,100,987,248,54,584,680,563,307,616,513,205,470,493,875,364,450,495,321,153,720,286,1,952,959,714", + "547,668,556,928,323,589,711,190,637,524,721,337,155,629,948,692,221,809,666,406,606,777,926,842,943,794,446,461,348,637,894,601,23,803,467,963,985,606,368,577,632,254,845,725,1,23,992,523,581,657,564,463,895,137,417,498,451,346,808,720,383,209,209,138,457,787,165,228,351,920,131,71,817,971,925,273,46,875,154,902,619,169,220,342,105,29,486,625,49,576,663,578,706,399,688,796,34,952,109,947,886,578,448,455,567,936,789,261,30,38,817,491,543,525,434,122,97,749,537,843,366,253,980,921,744,884,672,482,73,191,11,12,808,498,159,992,202,193,806,528,428,305,740,7,479,261,58,313,291,738,516,93,495,561,349,875,466,448,257,710,625,328,979,235,559,277,238,810,380,207,438,226,347,625,197,229,627,827,127,24,140,320,916,782,189,99,447,724,913,411,407,512,263,278,914,790,667,94,21,672,448,329,313,295,522,559,461,194,933,745,886,814,857,775,625,322,155,55,660,233,433,591,73,272,830,20,517,937,557,815,852,771,152,915,919,534,265,125,977,916,631,460,718,887,48,8,59,925,589,110,152,130,455,759,131,595,184,353,907,896,186,102,360,687,948,623,791,677,284,275,581,904,860,321,65,188,613,97,573,878,801,156,975,371,385,817,692,70,663,272,712,772,132,711,99,983,80,672,763,953,806,816,754,675,502,985,343,435,965,426,787,694,567,365,32,19,170,889,633,547,404,481,871,301,359,773,910,295,121,38,376,662,793,605,786,268,973,372,72,304,854,920,511,100,442,233,246,334,75,103,126,812,634,969,448,489,165,338,829,379,201,325,473,857,376,574,81,963,260,430,578,599,48,106,819,64,95,453,125,257,515,771,280,997,237,825,711,838,276,644,950,14,349,131,540,92,440,955,800,35,290,791,408,900,792,280,955,186,374,936,326,484,41,2,88,845,506,283,221,719,109,238,396,525,310,850,259,724,710,85,772,868,510,883,996,767,608,626,510,856,532,973,349,392,426,900,623,334,693,632,483,644,809,912,633,163,271,985,666,786,466,627,558,530,10,859,0,577,478,76,268,269,377,982,383,699,418,231,263,107,505,336,260,177,555,428,973,270,901,911,90,82,252,553,366,155,647,44,492,966,59,221,331,838,335,713,226,431,720,131,97,650,476,15,335,454,553,251,370,202,928,801,337,875,454,80,5,707,746,346,844,642,107,893,42,42,507,714,273,398,232,274,819,633,617,423,164,839,774,344,81,890,249,783,396,903,12,794,103,867,424,11,76,296,432,566,704,297,230,676,872,720,408,606,759,89,32,23,113,524,868,912,317,464,94,639,560,102,375,388,675,578,833,434,857,599,88,779,602,611,746,224,28,434,525,890,632,832,397,399,811,660,431,6,723,257,47,277,222,178,488,860,895,948,619,372,317,675,384,753,56,750,212,9,527,780,268,656,105,490,92,613,907,569,286,280,233,886,862,109,121,982,402,252,24,799,501,387,127,122,526,988,584,250,692,497,294,726,974,806,809,997,813,254,326,22,328,297,538,656,352,867,265,385,638,877,204,353,743,541,208,394,274,656,810,111,987,105,152,34,892,72,296,911,595,375,891,140,250,941,307,156,963,827,781,243,105,965,700,292,659,361,164,87,8,710,397,553,994,986,941,980,666,663,275,418,474,375,468,996,794,215,81,21,35,925,873,380,476,231,128,296,432,679,918,408,509,328,823,287,142,836,933,741,988,484,503,444,96,397,366,484,235,407,88,228,88,842,362,140,820,576,880,185,429,233,126,939,581,472,543,369,209,428,299,543,828,454,627,428,440,652,828,752,273,242,294,41,303,187,252,204,696,137,891,481,71,775,560,771,946,415,60,62,324,22,813,604,283,433,561,149,358,280,586,52,793,783,954,590,407,104,26,787,411,654,35,11,812,628,492,324,251,955,302,752,800,604,358,374,911,790,306,607,714,678,527,342,171,850,292,326,965,711,283,209,478,723,561,949,436,690,967,645,726,387,61,491,50,582,347,386,405,717,945,67,620,899,132,745,761,560,23,878,164,639,623,433,663,298,586,517,253,820,828,366,419,114,543,187,454,70,800,704,986,744,3,347,387,945,171,226,121,389,921,155,518,667,166,478,885,884,262,185,882,893,309,236,622,843,638,399,678,959,91,184,175,902,724,873,488,159,352,39,38,753,331,219,205,271,478,390,415,300,515,497,106,669,40,919,201,507,401,483,768,897,485,849,901,569,85,751,183,506,944,377,874,226,925,64", + "889,350,490,461,800,699,482,302,23,198,762,130,801,62,469,181,301,540,549,720,591,366,544,654,654,835,564,174,979,958,53,48,404,772,194,370,335,387,481,525,714,144,217,875,828,176,803,432,702,810,698,689,635,835,664,142,952,459,420,866,738,734,434,747,75,22,660,23,763,841,756,195,653,517,681,658,830,260,215,370,37,944,980,821,475,575,441,874,387,315,456,161,89,124,356,397,440,667,947,888,366,857,832,493,70,703,319,141,681,241,993,507,109,456,224,563,650,131,460,343,176,699,550,316,234,626,601,193,26,458,664,395,762,59,759,476,273,806,470,480,592,907,784,588,965,367,818,729,813,576,360,737,998,323,500,585,842,889,122,854,427,850,958,67,154,658,977,381,906,62,495,476,767,839,615,581,386,12,52,86,434,328,36,502,932,515,930,580,661,753,493,662,315,711,833,844,109,513,414,504,497,416,357,177,243,212,455,512,975,260,720,402,946,677,821,210,667,112,354,809,637,851,139,69,944,670,833,983,980,122,911,613,449,722,745,582,857,77,877,796,502,766,902,884,57,401,329,604,499,944,496,780,774,204,802,837,827,97,646,686,323,929,823,254,770,170,60,332,118,103,847,385,197,192,835,517,484,447,634,343,552,256,152,754,385,179,136,342,913,486,633,218,767,762,430,917,923,660,75,468,546,268,513,937,415,297,970,309,792,555,499,451,603,163,976,621,764,117,634,385,144,208,81,174,955,400,76,851,966,345,268,331,378,876,394,25,751,403,801,198,967,743,931,838,803,98,622,12,113,275,492,672,740,181,622,205,17,55,654,279,401,646,246,643,580,181,984,818,24,366,510,763,836,993,118,829,636,775,975,167,590,912,51,920,726,117,525,191,74,48,397,986,342,640,226,927,540,25,424,507,938,258,975,338,746,533,827,86,949,275,646,913,230,668,196,195,993,804,243,264,407,491,179,803,642,534,745,527,671,798,676,564,644,280,624,477,541,983,514,594,837,998,873,170,248,342,562,987,302,933,922,500,206,319,256,166,848,660,632,528,766,904,683,749,925,526,577,0,947,743,529,765,944,868,94,709,348,94,819,17,444,556,719,421,492,360,517,759,301,529,635,162,963,840,868,104,62,606,521,283,839,122,522,577,252,879,596,680,210,876,858,833,271,555,135,687,823,511,610,673,97,456,161,149,76,404,561,923,818,626,681,800,380,937,697,520,443,942,403,376,366,965,241,495,891,675,300,141,87,639,246,298,158,274,108,936,743,224,781,263,472,383,514,967,17,960,485,171,638,270,44,6,661,833,711,396,112,843,510,343,808,197,461,559,500,179,337,809,945,852,676,470,293,641,812,161,553,74,451,665,906,376,559,904,277,135,590,340,773,269,471,880,898,104,568,925,513,601,159,952,350,856,694,464,238,745,988,365,701,535,435,892,125,76,582,69,152,91,83,903,705,28,507,444,44,20,904,174,426,346,235,474,90,591,120,23,406,222,156,481,488,360,169,663,566,907,50,102,255,852,848,823,653,10,152,88,487,446,525,739,181,683,412,415,2,368,438,899,120,624,840,560,607,258,546,260,796,428,987,998,740,918,627,769,579,616,743,72,869,173,194,921,704,763,501,163,36,390,998,50,616,39,646,189,362,664,830,393,907,651,633,470,333,251,3,23,439,611,271,853,39,880,719,553,334,442,863,125,875,58,426,549,375,711,61,469,147,241,642,786,479,662,658,434,317,271,431,859,950,149,312,676,228,521,389,968,953,924,935,327,430,163,303,422,550,270,285,436,261,990,264,575,633,186,444,782,371,482,151,980,839,486,288,840,908,277,835,856,573,285,511,797,435,710,386,680,724,108,396,160,286,894,281,572,180,223,653,644,509,111,888,666,494,424,701,577,628,847,716,833,593,262,571,129,762,606,298,646,202,20,311,768,867,412,212,39,160,568,489,471,291,339,221,322,609,690,749,205,984,462,408,699,463,568,168,632,504,695,372,982,770,927,240,97,970,712,72,796,1000,205,321,835,377,275,47,215,331,890,972,190,776,858,211,994,659,831,32,801,630,594,191,282,715,761,69,677,968,106,245,451,307,208,352,154,101,26,101,346,509,1,751,902,753,42,168,392,320,426,877,920,819,854,797,722,355,364,868,828,250,827,895,901,703,467,725,622,494,159,348,515,560,642,349,531,630,683,142,526,615,830,979,612,829,767,836,818,700,819,659,766,161,392,45,384,365,126,312,420,333,655,102,898,572,111,233,562,126,135,990,75", + "199,496,890,747,535,340,106,770,527,33,488,265,586,957,477,95,623,66,104,785,322,624,319,824,154,999,530,612,107,394,696,269,17,334,798,311,303,200,4,846,824,88,729,878,775,109,684,823,250,269,819,748,371,178,53,794,945,87,558,62,32,727,234,857,890,610,112,82,650,317,148,995,805,157,481,745,321,217,317,902,872,852,219,687,355,601,105,835,708,686,175,148,992,383,720,510,325,269,251,758,930,321,767,97,31,468,648,702,858,177,496,354,834,102,97,668,957,372,328,603,572,367,462,227,437,624,152,104,937,378,699,984,661,189,107,919,818,40,824,264,191,606,290,734,207,80,711,261,854,374,713,234,571,248,798,200,151,735,738,684,23,469,553,467,584,190,637,363,709,949,695,479,687,725,205,271,811,714,965,688,790,254,121,99,383,873,482,563,410,216,171,53,224,374,790,882,426,670,187,104,767,168,70,778,632,134,13,302,932,170,866,993,186,146,29,770,283,114,946,776,953,824,677,678,425,110,475,979,203,961,699,817,19,848,561,916,195,984,509,627,359,552,966,697,338,613,770,509,330,910,639,552,693,302,535,446,712,843,201,361,915,726,737,868,708,715,981,43,721,4,630,251,28,897,647,551,604,74,118,504,458,992,270,700,98,465,847,592,898,227,41,915,651,415,476,583,658,209,830,727,280,778,492,924,610,118,998,72,227,29,284,344,253,739,784,827,748,271,227,722,681,591,190,240,284,244,674,626,369,178,864,592,62,833,834,385,79,954,850,263,483,260,536,761,716,631,826,847,209,888,845,281,78,897,568,999,372,271,835,614,985,177,247,252,701,844,579,634,970,384,57,725,395,438,276,216,419,354,722,621,30,681,749,949,90,124,317,401,320,289,592,311,508,190,965,2,987,845,772,323,421,21,56,72,348,109,701,37,1000,851,642,633,457,69,423,794,342,261,52,733,922,410,725,616,416,507,914,435,255,162,361,899,921,686,179,865,181,733,180,313,837,22,995,325,112,189,499,822,884,72,19,160,682,725,108,673,235,925,30,801,825,519,258,863,656,768,478,947,0,343,506,891,981,618,911,48,682,195,440,72,421,813,331,208,410,209,280,995,265,285,58,331,908,137,304,45,422,763,32,852,473,492,924,371,706,212,518,72,950,536,531,24,608,832,541,572,742,748,377,93,796,889,31,107,487,7,180,376,981,33,873,329,678,99,269,401,476,888,328,667,629,26,921,413,825,512,127,800,79,849,717,281,957,169,679,889,142,421,280,601,900,537,340,243,978,156,952,556,267,124,728,866,824,493,187,994,140,109,135,784,854,869,257,203,561,886,34,849,474,377,852,244,368,393,81,829,178,7,817,453,286,505,667,303,153,936,548,203,630,430,375,157,146,324,715,259,597,614,929,339,112,7,155,423,789,366,491,435,205,484,321,832,978,754,41,91,979,75,883,377,676,720,666,816,770,828,332,504,910,134,737,459,400,455,829,945,434,791,125,14,570,128,660,341,986,592,630,916,392,860,428,829,333,373,570,347,847,208,855,785,716,867,561,66,523,26,406,918,409,922,158,347,429,565,715,527,614,239,126,92,41,189,261,138,859,927,104,126,13,701,466,473,839,896,736,532,589,211,97,52,361,274,619,201,634,233,646,640,718,404,218,43,844,494,366,356,109,991,613,861,884,488,457,291,190,628,604,176,809,378,824,602,454,569,800,944,854,718,779,662,181,460,641,72,146,705,834,651,684,815,70,59,492,336,954,650,489,653,414,936,359,539,729,512,772,579,389,812,411,643,637,518,629,647,858,526,278,723,794,290,894,72,143,830,352,549,982,291,698,678,607,147,128,304,365,135,260,425,902,700,744,463,506,597,302,259,4,772,982,463,782,323,969,222,71,202,829,650,751,997,411,342,601,168,886,974,672,582,86,750,844,689,700,411,983,608,672,635,192,267,814,808,733,775,733,518,509,981,519,90,990,634,553,780,383,182,729,625,148,279,656,703,396,640,424,977,568,764,625,91,712,268,42,565,656,797,429,90,887,341,103,585,380,519,900,266,105,567,726,547,592,813,845,957,846,647,44,932,699,638,313,417,599,184,110,947,23,669,423,152,311,371,731,929,718,376,355,516,70,855,116,210,548,444,520,886,71,704,45,157,113,239,662,164,175,622,318,299,914,8,953,130,364,135,490,650,397,898,672,97,254,259,406,985,709,765,769,281,349,312,387,11,828,194,597,891,430,297,982,909,994,493,630,14,7,135,966,51,646,905", + "743,113,874,762,249,421,925,874,699,193,497,246,939,688,650,30,159,72,629,98,985,299,265,427,52,120,4,561,932,433,550,598,872,154,769,254,997,244,185,293,679,586,181,412,464,381,149,138,521,104,794,587,165,106,597,979,620,379,18,748,37,987,955,925,192,814,910,379,177,717,793,455,273,808,530,353,212,304,143,69,846,786,983,809,566,65,164,597,626,679,112,196,813,986,281,823,377,429,629,100,417,239,606,515,829,807,372,184,513,554,635,935,9,946,570,465,125,794,703,810,504,483,823,413,184,449,853,72,38,110,651,323,177,700,964,172,60,143,244,251,883,108,527,408,815,385,658,830,918,21,947,299,144,987,524,331,439,959,832,878,290,594,180,934,760,755,861,158,984,81,176,83,561,43,863,860,395,832,663,808,528,497,53,629,782,317,612,668,529,497,45,953,932,95,271,886,198,326,151,119,255,623,6,398,387,164,960,221,446,113,67,123,395,283,25,152,523,786,799,461,418,844,70,215,636,827,949,255,917,322,629,959,897,424,955,508,12,107,523,396,543,384,53,21,728,317,33,266,658,277,423,432,791,377,768,657,889,940,500,438,705,509,77,801,225,771,100,664,540,370,844,455,2,263,505,900,320,883,583,320,500,566,310,980,594,410,164,903,304,698,670,943,464,787,839,198,268,906,391,949,853,143,540,18,15,478,631,502,914,699,601,992,4,949,423,275,755,719,248,59,618,545,418,198,194,186,124,628,896,530,320,888,579,583,187,683,923,874,543,164,362,878,689,17,963,768,655,383,762,283,223,704,6,851,176,39,609,797,81,513,326,460,106,723,345,233,946,735,534,428,868,524,974,214,829,245,359,566,705,407,647,894,778,150,497,361,928,238,655,211,875,822,647,455,300,821,105,68,745,999,226,568,424,444,734,419,721,674,739,707,491,715,472,137,34,268,786,379,706,148,791,506,146,803,207,352,474,217,855,588,263,893,463,170,42,192,471,326,586,117,391,345,202,577,508,387,427,368,690,205,904,842,790,237,827,532,266,16,364,380,756,59,775,444,766,16,76,743,343,0,635,162,631,364,981,807,184,84,881,389,515,200,852,55,446,713,607,865,762,539,277,236,438,274,940,459,996,248,182,318,555,739,590,302,118,469,759,454,37,267,531,572,630,43,432,94,383,136,828,678,708,568,383,199,662,241,395,979,589,936,830,573,921,961,997,613,448,76,689,657,232,57,175,625,266,235,178,468,799,447,268,981,187,632,454,153,204,949,891,247,579,428,31,425,525,516,650,701,219,563,825,467,278,49,473,320,608,605,576,369,918,251,279,269,248,566,969,538,567,690,195,472,942,751,814,921,653,825,591,985,81,569,484,930,310,295,584,530,320,979,235,191,197,859,555,109,114,349,288,375,228,582,787,433,30,795,784,583,524,905,438,780,240,847,853,645,796,775,131,625,780,227,788,894,490,661,368,429,98,319,698,688,906,137,215,242,154,532,13,663,710,553,773,436,746,104,195,294,416,760,453,686,701,830,157,189,684,441,113,718,671,412,551,711,670,62,470,219,502,866,182,431,144,918,686,865,610,702,58,481,172,567,720,130,295,484,737,497,85,647,910,997,927,907,5,9,158,75,823,579,669,990,778,443,462,58,368,151,906,666,208,424,904,866,630,901,869,501,472,35,370,903,834,665,318,126,388,247,916,957,200,925,797,606,160,72,595,941,75,915,754,894,547,74,836,183,211,463,34,957,427,319,7,463,277,415,600,970,536,814,331,153,245,965,794,438,80,937,90,574,344,750,813,795,20,835,985,455,583,915,220,354,208,407,803,545,870,591,477,843,418,933,909,732,270,708,483,732,274,94,463,960,190,285,310,887,239,438,106,47,500,546,788,932,719,171,141,201,361,811,986,809,139,406,535,251,819,889,368,128,345,738,205,216,19,576,902,674,233,968,977,836,129,509,47,856,422,735,439,494,420,96,932,520,81,778,713,456,382,412,630,26,75,923,296,188,954,63,469,576,639,858,803,269,214,898,351,185,698,122,364,449,416,664,56,905,225,115,512,266,981,887,400,663,240,162,189,249,93,241,213,549,703,367,516,166,106,117,333,343,872,643,146,511,816,779,77,928,599,10,814,712,77,685,264,330,660,170,639,748,830,360,22,837,944,983,418,534,136,569,728,29,550,50,826,799,303,391,277,457,466,885,976,747,864,663,416,34,468,408,987,266,355,106,330,114,298,731,296,626,398,303,232,568,250,498,512,256,210,710", + "611,14,642,718,92,192,562,740,195,514,103,287,529,78,898,620,423,236,185,476,74,708,498,625,351,18,552,1,406,184,835,445,874,355,957,271,173,484,535,37,898,544,825,54,68,43,474,370,6,533,698,899,7,618,606,653,158,404,415,583,814,425,788,683,73,682,713,685,282,464,621,153,585,399,75,632,796,549,523,533,282,92,895,522,369,447,64,717,146,841,934,93,852,412,692,36,651,86,558,37,631,503,641,801,710,491,371,611,290,613,373,75,11,950,86,890,735,189,55,116,747,316,86,184,759,690,953,456,9,98,805,850,241,914,123,299,403,719,282,729,692,945,506,631,415,725,922,838,200,610,257,97,44,593,370,849,2,956,350,201,47,693,805,478,856,821,40,502,461,515,617,956,11,65,862,208,486,855,298,601,917,600,619,75,523,848,148,982,586,426,944,965,19,883,343,782,218,898,163,774,48,77,965,916,725,654,717,359,466,685,635,287,164,990,412,783,913,225,147,939,979,582,312,996,755,636,4,700,379,577,844,106,32,47,741,790,578,966,251,61,63,617,552,320,219,77,996,736,532,51,687,840,150,332,990,887,912,998,312,80,741,715,729,126,388,930,815,626,970,815,416,518,401,135,546,560,988,796,614,323,413,616,248,377,923,393,918,92,271,135,701,186,428,270,746,979,871,950,635,395,973,884,296,816,361,165,214,513,82,924,64,873,71,258,881,231,289,354,648,235,971,612,142,634,383,391,562,432,916,933,698,157,659,678,438,509,157,409,949,740,937,128,264,138,793,397,847,906,595,567,262,236,652,635,386,416,465,915,608,93,277,835,138,699,348,666,380,893,85,604,921,419,979,280,25,267,408,247,168,979,333,250,920,333,755,950,203,623,436,528,84,764,45,924,53,800,97,171,212,23,487,260,106,964,107,524,821,462,636,790,112,659,637,323,613,778,418,332,388,732,938,845,390,161,425,909,565,747,702,712,569,43,373,607,71,170,662,626,593,152,150,871,254,997,615,33,683,828,225,952,611,464,176,924,54,925,123,590,405,773,546,284,895,709,845,714,268,529,506,635,0,616,765,740,224,285,898,13,80,845,991,309,21,683,851,547,371,642,93,958,146,727,638,874,760,888,1,374,926,569,407,369,102,617,785,928,604,969,58,26,472,207,761,151,513,251,139,763,350,612,136,597,14,746,22,851,657,835,303,985,334,613,314,326,404,809,38,243,522,620,919,873,544,402,747,655,406,595,263,484,816,603,64,116,680,630,112,979,845,274,727,600,9,537,601,496,147,449,245,813,636,859,819,747,353,404,843,34,898,68,847,798,56,636,664,377,303,338,320,715,99,887,800,421,61,604,530,771,49,638,766,148,302,649,130,273,558,129,967,787,192,617,986,771,727,588,85,901,13,862,344,939,161,527,856,244,51,439,402,646,450,117,484,987,532,363,750,171,933,514,523,73,316,643,984,611,78,219,803,735,352,49,93,87,987,823,462,850,791,39,123,489,77,247,601,421,446,761,906,605,854,321,13,763,147,892,182,338,751,782,913,611,87,372,421,244,429,564,633,172,325,270,6,238,885,715,682,591,808,459,223,44,714,178,299,140,93,216,283,387,665,338,145,342,392,465,863,768,589,359,914,444,503,33,956,124,920,132,554,586,91,973,933,90,937,453,876,163,54,644,921,276,533,821,824,967,358,889,512,574,189,619,255,669,397,884,502,6,384,782,151,663,254,555,766,22,708,613,1,411,847,587,436,41,254,718,986,383,641,26,2,122,433,663,753,9,792,524,275,260,371,885,848,859,611,774,54,560,338,870,550,254,789,412,243,623,271,349,289,529,825,248,511,587,724,656,349,742,914,209,911,789,94,691,952,480,257,283,93,612,790,773,629,288,886,217,343,422,989,38,926,132,37,584,696,356,831,99,813,50,188,971,452,910,59,701,383,499,10,325,858,770,705,273,628,833,848,121,443,587,162,541,149,619,696,91,42,524,881,447,878,933,560,295,953,178,704,891,625,403,404,520,863,148,573,74,556,186,116,628,780,401,797,233,536,862,364,854,888,569,832,470,857,612,283,292,934,496,417,44,266,753,480,210,488,217,145,915,799,958,884,310,353,149,269,706,723,224,282,3,909,511,410,559,231,822,80,622,667,541,994,250,903,26,698,79,23,750,228,325,255,726,97,606,939,923,749,718,11,838,606,836,729,238,324,433,561,312,55,744,67,284,352,321,569,510,674,21,531,388,794,334,737,907,266,709,780,316,630,621", + "357,914,256,635,178,999,341,459,214,909,69,983,88,299,983,46,780,558,153,542,387,523,326,808,411,160,170,415,107,443,310,496,459,42,986,885,520,923,625,19,166,609,315,145,332,142,404,868,784,883,173,816,31,901,624,273,654,787,906,505,833,846,916,465,548,504,96,637,413,184,753,77,650,58,277,196,808,224,816,653,971,33,137,143,51,604,99,198,30,819,977,971,18,959,747,207,530,214,521,282,424,885,415,236,144,411,345,701,785,370,939,993,660,794,150,176,411,47,36,535,132,655,840,799,555,289,403,796,214,255,720,479,963,217,579,434,106,956,661,787,856,991,451,395,656,305,351,278,631,439,228,608,611,765,672,969,242,886,161,122,621,674,299,604,811,353,667,682,296,893,783,366,363,438,95,856,624,42,521,851,212,501,154,402,728,358,842,256,767,681,513,370,136,409,356,304,194,590,73,941,741,775,854,105,174,358,576,34,165,744,532,298,220,984,586,116,670,755,268,800,797,550,254,307,154,316,990,291,568,201,336,170,98,33,825,452,461,380,481,943,947,971,633,30,550,917,556,750,239,545,309,23,778,370,887,266,125,505,93,323,74,319,448,726,480,265,332,645,602,475,435,849,183,244,224,511,564,125,263,582,965,911,313,825,502,473,972,353,839,581,938,419,993,536,731,807,366,3,339,5,642,823,436,550,549,781,61,851,299,239,128,81,293,74,763,190,530,885,907,535,381,536,976,543,257,582,679,688,640,815,996,343,76,678,36,913,951,56,353,118,47,442,84,715,32,732,304,604,123,785,453,237,605,990,232,397,559,66,772,613,304,440,35,348,834,666,934,315,765,870,568,249,375,11,562,738,628,941,505,489,711,249,84,236,351,883,641,884,113,273,578,962,210,524,554,188,640,696,856,598,959,232,87,655,377,947,311,3,170,844,599,804,429,807,537,625,911,545,693,447,508,129,225,485,732,225,155,26,86,204,879,455,309,83,418,136,925,970,967,169,702,950,735,727,518,116,869,305,480,678,37,507,546,864,320,879,297,380,463,195,173,727,208,183,54,44,269,765,891,162,616,0,237,302,501,367,799,838,100,874,331,690,888,265,371,518,630,712,980,505,334,429,787,7,139,476,793,682,618,567,938,80,975,905,665,605,374,690,301,671,260,653,496,504,1000,486,618,927,161,391,352,609,646,409,216,248,451,704,983,215,995,821,342,249,98,372,997,321,614,291,495,442,948,284,409,477,159,26,227,743,263,967,763,638,889,595,647,574,333,903,621,923,731,684,734,620,562,88,515,276,861,450,376,17,468,783,664,484,814,866,534,318,13,701,12,38,711,72,144,995,628,18,906,473,638,369,8,367,92,348,419,593,128,449,700,247,974,864,461,506,622,179,532,892,865,476,816,338,376,490,906,228,557,218,893,402,918,657,329,351,182,111,517,864,726,109,694,384,836,978,548,233,484,139,80,742,52,433,628,893,57,408,372,691,877,192,903,540,149,437,759,429,787,407,649,110,881,993,904,694,378,998,94,877,215,537,138,97,994,926,156,706,278,257,231,662,86,641,304,776,467,174,866,261,872,726,572,105,949,331,174,602,728,702,515,827,958,466,910,518,262,295,514,999,878,282,663,532,74,451,690,523,734,308,822,499,663,451,8,302,552,88,912,72,384,994,100,753,331,51,693,102,407,586,946,256,611,491,176,50,557,489,57,960,793,714,777,561,983,5,128,36,413,683,831,557,78,875,154,382,74,239,747,644,287,220,510,340,481,731,321,723,606,245,94,722,104,416,571,831,975,51,798,460,890,979,100,980,853,633,803,788,841,204,635,264,751,223,744,424,426,484,245,332,883,425,698,728,291,114,982,842,817,439,796,147,606,156,909,757,183,897,730,934,800,113,715,420,315,636,346,689,940,865,38,823,761,878,353,231,138,185,702,371,214,697,545,548,487,991,838,939,765,870,91,602,684,470,859,384,974,860,465,581,380,390,885,768,772,934,674,950,284,709,26,136,224,328,236,992,773,923,268,556,448,63,409,634,611,572,743,31,330,313,538,825,595,989,118,356,153,124,834,8,782,748,17,369,289,467,543,621,114,773,57,101,970,337,251,784,792,181,569,287,980,628,816,50,460,719,29,601,986,976,713,150,722,680,555,49,938,74,528,827,184,348,712,412,1000,567,361,907,961,236,642,668,795,531,661,938,479,800,102,133,170,464,183,511,113,678,495,390,452,967,729,19,665,111,438,934,806,554,561,623,945,770,728,245,164,839", + "952,813,945,225,146,53,529,430,941,285,325,457,612,668,178,124,892,893,355,830,939,754,449,231,660,274,169,182,59,901,291,37,499,231,759,520,10,732,827,351,705,552,937,826,874,36,159,806,18,851,583,666,805,515,549,978,749,650,194,851,489,131,137,529,574,312,832,264,516,808,921,288,53,910,767,729,797,467,395,454,7,861,173,422,427,513,652,480,89,758,717,524,976,930,947,223,174,52,94,149,185,651,679,474,341,840,468,876,814,674,83,993,763,76,976,289,810,93,515,412,354,647,799,550,573,895,63,152,360,452,787,847,480,544,277,374,962,71,583,733,72,881,974,888,991,554,477,230,4,590,402,947,907,536,502,257,904,117,665,847,41,532,65,557,963,328,434,725,822,239,141,684,223,229,744,530,217,379,742,133,304,379,692,69,517,741,902,282,468,23,807,171,972,151,346,154,349,791,964,182,349,101,562,287,267,977,966,396,693,804,109,216,183,183,319,515,361,618,782,828,139,149,878,469,186,529,718,831,385,550,516,551,891,219,414,331,4,434,909,160,426,49,365,824,892,622,237,405,980,419,317,514,645,44,430,172,906,857,94,699,199,800,407,525,363,585,409,595,941,572,406,269,162,619,792,442,621,772,715,740,805,469,51,174,397,665,347,291,185,527,929,974,769,631,169,614,249,826,98,613,222,336,121,572,782,738,198,863,56,295,918,80,845,384,237,409,925,432,253,518,121,168,545,74,418,727,304,162,245,425,213,28,48,388,629,763,189,858,496,553,22,720,605,224,623,107,468,875,49,732,594,823,964,551,816,492,134,546,330,161,509,996,310,548,480,319,126,585,391,365,893,23,550,74,685,772,343,427,767,998,259,815,409,84,358,529,855,600,785,999,444,169,388,521,721,935,465,90,217,947,293,546,223,40,971,644,788,30,739,878,733,950,874,178,46,471,178,881,825,943,500,898,18,855,717,177,196,304,251,409,403,301,80,356,923,577,131,790,580,764,218,251,743,359,180,410,77,165,750,383,974,998,976,407,981,37,1,183,562,205,533,59,591,825,895,478,377,944,981,631,765,237,0,418,214,446,129,919,203,104,9,99,705,75,687,476,184,184,46,513,254,460,609,82,70,293,526,596,109,55,98,377,273,557,311,111,84,316,763,862,729,886,748,789,340,133,979,541,68,94,281,838,98,500,60,343,416,219,666,38,58,211,879,138,479,23,563,290,735,40,162,826,898,333,294,432,612,751,476,103,354,920,709,871,57,411,399,228,11,147,73,854,574,692,237,239,553,632,94,977,906,101,392,726,246,218,957,553,478,820,302,200,411,377,901,433,330,861,417,165,115,883,893,674,17,227,961,168,908,973,786,621,512,935,527,607,501,722,777,862,722,120,410,655,183,925,255,571,616,446,76,922,98,401,727,115,968,272,138,486,100,570,187,947,107,897,168,229,959,277,51,570,961,177,778,284,978,942,419,232,24,818,992,675,538,783,585,148,968,12,680,386,477,275,170,847,927,532,684,756,869,857,805,613,737,14,456,960,2,278,347,72,171,264,722,630,170,972,541,909,122,274,574,818,891,734,134,892,764,458,799,95,97,922,894,182,872,818,63,527,800,894,873,545,78,266,94,996,405,384,488,165,129,194,779,878,468,765,587,922,385,212,328,906,400,934,770,208,665,196,661,350,919,465,194,809,399,223,267,686,572,152,84,7,843,336,973,114,687,464,880,242,368,791,13,623,994,562,240,186,971,783,426,822,519,933,810,454,172,896,583,291,488,253,241,117,341,713,479,679,414,247,571,126,359,374,745,811,773,920,224,298,254,175,607,199,797,644,805,386,577,651,31,303,715,191,85,522,203,700,613,193,838,232,656,95,414,568,277,662,36,234,288,51,499,500,372,465,556,916,642,471,448,589,757,913,260,997,667,559,29,20,906,938,374,34,8,808,642,556,498,269,657,783,705,70,344,752,999,401,503,598,277,861,642,664,706,975,98,968,376,433,676,806,450,234,353,866,770,979,228,157,460,55,501,277,34,241,43,587,735,594,900,592,856,153,34,599,211,83,334,16,984,869,659,733,950,713,913,847,130,500,738,335,396,299,924,62,990,15,283,689,30,399,82,592,618,77,712,762,136,91,358,361,957,121,198,573,474,307,455,786,943,348,81,275,738,707,85,615,183,582,881,354,837,792,807,690,951,683,854,275,792,434,461,497,722,166,463,857,914,517,830,860,952,997,370,891,716,472,578,727,988,327,267,555,722,96,842,758", + "781,974,701,458,125,339,829,217,756,608,282,568,731,803,465,840,408,515,701,807,660,986,507,168,642,855,408,129,861,821,704,279,624,463,257,301,881,80,837,7,380,938,518,114,174,542,63,193,893,944,358,986,51,890,645,806,643,334,365,376,788,253,739,739,815,581,409,57,159,290,100,447,604,741,19,903,308,864,802,655,309,85,470,726,71,300,745,324,617,568,844,805,336,220,37,971,162,805,219,220,240,336,449,5,198,269,373,190,547,322,845,719,156,917,300,554,115,760,115,438,359,764,714,311,628,707,451,872,55,744,846,621,211,869,104,397,892,359,372,484,952,934,87,615,732,123,422,4,437,983,633,182,815,489,870,776,180,897,600,960,592,549,25,111,227,679,92,203,595,708,334,474,489,147,552,170,303,663,378,615,12,589,564,156,774,391,937,460,438,380,803,65,816,210,269,740,101,618,449,305,839,727,20,710,102,440,376,957,279,154,590,782,332,784,519,467,256,401,643,671,374,898,390,26,754,187,861,738,388,162,935,10,939,601,271,654,870,806,301,865,207,133,913,5,854,42,557,160,633,185,380,483,768,18,523,952,156,197,596,312,550,251,152,494,77,722,63,999,944,615,626,627,233,811,189,702,831,166,264,737,828,445,745,845,122,382,955,824,272,335,75,326,77,44,519,924,995,689,324,758,336,103,773,592,214,596,838,38,589,601,283,496,245,312,142,417,735,726,508,802,859,153,963,319,164,746,503,400,451,454,684,942,552,607,722,608,700,68,512,79,341,821,327,814,991,575,324,854,150,56,217,507,258,559,267,649,122,585,732,607,332,339,40,413,615,455,811,992,468,944,114,20,559,845,592,248,301,392,58,348,219,191,584,41,902,240,498,75,2,344,760,499,217,612,652,406,630,9,114,279,679,164,875,637,305,279,23,553,476,246,108,194,814,847,683,504,653,533,222,837,828,489,857,966,658,847,328,224,407,136,127,735,797,651,217,285,705,70,856,850,215,950,363,201,920,180,583,63,30,621,694,610,330,769,630,411,798,977,62,21,543,821,571,783,275,780,982,868,618,364,740,302,418,0,828,386,27,151,851,976,689,271,36,387,24,539,3,972,935,571,732,205,686,937,797,273,119,329,198,730,458,937,24,32,626,568,338,465,78,130,991,413,281,910,5,303,513,159,113,626,324,837,766,111,797,241,826,920,886,18,551,170,875,54,214,794,796,824,772,231,308,737,392,493,355,846,5,230,582,400,183,111,464,976,476,751,707,427,335,575,997,238,571,5,298,177,872,51,549,193,776,964,120,818,403,173,809,98,58,526,798,799,564,842,894,321,496,409,930,190,858,919,586,300,696,163,555,785,969,525,270,582,554,312,53,146,472,1,48,783,378,923,442,557,733,343,656,93,902,833,176,727,444,797,803,844,378,32,438,811,490,931,866,766,392,452,481,591,229,942,305,931,921,4,670,859,737,382,642,221,423,852,362,14,713,483,951,402,27,56,552,868,669,490,716,508,69,796,133,547,964,403,539,626,273,852,307,360,11,383,62,666,672,57,399,803,72,628,296,516,491,444,976,40,919,512,187,749,267,463,528,523,670,238,617,436,787,25,440,92,431,418,753,327,580,380,322,809,864,802,858,890,768,698,73,499,412,867,301,188,329,427,416,834,204,202,94,849,20,336,517,975,712,984,521,765,29,293,822,718,102,431,344,110,17,669,728,248,167,49,652,250,331,394,365,121,638,109,723,599,314,201,790,991,685,540,35,92,725,960,188,926,806,785,757,990,974,785,416,854,728,311,466,186,719,854,188,783,357,868,973,507,851,20,682,718,707,785,872,198,299,411,584,925,177,569,458,850,764,693,705,181,114,570,502,648,789,87,178,920,844,547,720,601,800,363,427,579,795,153,112,816,797,352,521,105,225,47,605,42,184,445,112,880,624,84,272,107,168,651,167,353,830,299,805,37,189,62,990,852,398,176,20,157,786,156,554,159,652,893,141,355,547,994,181,634,71,225,514,426,140,627,963,8,501,184,92,791,331,188,64,572,485,396,992,952,184,343,653,280,973,759,975,222,477,402,966,136,378,407,529,745,566,54,34,147,882,920,139,485,365,447,342,463,738,580,125,701,329,96,211,8,168,234,476,612,961,226,312,860,928,144,533,193,460,146,817,207,498,216,524,567,302,298,606,378,368,728,955,567,630,635,461,99,158,47,506,993,48,955,540,422,57,625,167,225,611,451,795,156,992,765,937,317,690,398,761,313,381,927", + "899,528,214,617,77,250,260,242,230,755,550,370,246,426,947,961,656,978,403,146,84,346,291,792,739,119,482,876,793,699,560,210,718,912,31,240,488,613,232,229,664,205,539,574,474,61,228,943,249,671,133,709,587,934,753,931,425,551,883,266,15,393,596,32,612,16,417,726,487,50,247,349,51,369,835,891,747,153,580,96,113,313,684,23,730,279,19,664,771,25,341,687,722,669,296,397,137,368,331,978,886,453,9,773,954,613,347,320,835,480,248,789,428,248,337,836,687,698,548,697,794,882,669,491,575,320,217,712,443,364,279,865,820,215,624,508,625,437,612,517,686,458,944,518,285,677,409,227,236,522,866,204,993,942,380,330,325,584,597,448,775,913,770,508,963,710,166,657,778,169,493,207,624,291,148,756,747,44,412,974,319,774,151,837,274,231,657,701,215,203,434,875,499,300,169,118,200,70,254,611,805,202,949,770,874,730,970,336,471,980,587,665,266,534,970,250,920,691,357,959,83,470,700,175,256,29,922,869,330,576,510,54,406,56,108,926,373,396,686,557,140,477,839,985,535,837,31,658,126,314,872,830,548,233,623,320,9,144,739,385,489,259,662,53,312,936,843,104,80,286,93,519,409,301,223,118,99,305,672,473,16,256,363,509,489,126,542,90,725,945,637,335,240,356,450,868,679,988,829,55,405,241,548,355,666,250,366,964,265,236,478,407,261,637,640,874,743,542,382,976,445,603,664,112,955,737,98,377,734,410,794,906,59,251,365,914,344,303,974,32,767,665,699,496,112,332,680,776,889,859,837,638,480,24,765,398,505,851,225,337,303,120,86,598,92,170,78,202,801,647,704,689,336,564,910,405,248,744,448,435,804,935,730,952,329,577,957,612,169,500,865,217,187,237,760,742,455,101,742,16,837,931,916,424,353,286,306,128,478,384,58,889,782,887,288,792,283,816,579,626,167,711,374,986,902,670,395,178,805,81,456,864,462,110,791,913,526,719,720,280,17,679,915,205,232,679,919,421,180,825,30,281,151,635,26,913,527,920,587,319,491,368,581,467,185,981,383,94,911,981,224,501,214,828,0,161,708,143,796,802,662,875,680,508,243,827,73,930,993,924,717,696,261,716,229,13,987,872,508,861,909,752,491,585,119,165,857,321,505,124,362,545,629,391,613,726,261,225,484,324,39,560,415,280,872,324,351,414,435,58,862,209,410,214,95,967,374,178,514,340,85,652,21,598,113,427,208,214,424,807,152,755,396,281,669,593,401,698,193,219,788,844,350,481,814,63,34,30,77,594,413,299,758,400,39,39,332,722,181,924,465,175,83,704,206,210,960,861,365,250,32,950,959,600,361,692,587,807,661,252,63,810,639,758,690,48,312,806,188,898,14,283,593,134,218,959,249,675,445,455,152,609,413,427,561,86,410,326,502,469,602,569,517,851,411,859,919,387,206,370,627,484,72,441,139,243,277,223,986,46,710,687,233,467,423,26,449,504,930,913,920,40,715,214,850,855,684,401,58,118,860,749,935,595,334,92,532,174,81,53,518,345,778,953,860,425,868,738,532,20,311,230,263,796,877,706,828,36,18,376,534,430,639,728,841,831,679,145,33,457,50,765,65,973,2,800,21,75,636,620,610,371,940,873,907,590,547,953,900,174,88,674,480,960,96,330,949,752,182,980,124,929,744,410,612,667,842,386,950,846,336,660,805,797,187,708,469,729,59,632,913,501,435,719,960,395,48,282,787,934,133,900,596,954,384,540,77,247,809,280,507,154,607,210,224,642,694,567,383,274,399,525,750,851,291,174,815,341,920,157,269,834,430,27,955,642,958,126,91,30,348,317,523,694,324,236,785,184,34,783,895,698,678,668,380,360,34,502,325,805,272,487,911,695,752,517,165,712,403,93,49,922,295,672,490,641,582,869,346,799,29,387,147,975,361,465,455,261,107,536,665,561,353,536,143,117,116,213,298,109,166,502,992,781,345,421,324,532,364,794,968,272,686,380,343,375,100,528,38,450,310,552,95,544,175,572,904,898,97,457,345,165,148,625,485,659,111,422,191,642,393,395,614,787,786,281,686,705,211,193,506,59,910,372,999,411,301,600,892,99,636,194,1,237,630,394,620,96,350,498,720,107,614,912,379,395,549,849,399,180,875,741,74,649,713,52,79,344,37,655,854,70,980,518,295,882,596,231,36,927,750,325,723,155,3,301,572,22,736,583,993,341,306,73,272,512,537,955,22,964,722,902,461,114,830,476,812,243,320,97", + "548,389,45,128,374,510,941,923,726,137,907,266,649,934,918,822,234,280,234,430,252,908,854,158,892,84,71,583,165,174,895,15,238,600,595,697,16,176,886,390,134,97,130,338,273,990,43,39,653,296,128,285,65,320,387,258,937,964,94,621,927,682,642,334,365,988,312,585,175,591,359,510,716,76,918,135,558,822,236,110,374,354,771,809,354,372,520,21,122,766,158,539,276,510,886,896,771,156,157,557,449,847,204,985,947,3,576,429,419,721,574,479,403,395,709,812,5,651,924,342,52,933,890,23,237,74,897,280,801,153,82,688,9,522,738,41,733,382,422,825,198,523,645,995,125,838,640,870,677,254,685,504,89,619,942,326,512,925,324,531,886,957,653,924,860,633,326,73,531,176,850,255,639,928,371,604,838,580,549,237,328,343,932,575,529,324,681,339,736,293,420,340,808,391,820,420,670,496,121,280,34,73,570,952,363,330,825,314,265,389,708,815,203,382,557,853,30,558,87,267,762,470,854,224,610,490,570,900,989,774,108,582,851,97,852,981,192,947,961,369,579,961,27,199,764,632,277,63,449,782,128,75,528,686,646,119,762,90,762,341,53,952,448,114,766,995,123,976,321,827,857,880,989,446,64,207,419,51,904,65,454,16,107,713,70,86,16,13,557,937,686,737,504,36,499,225,877,464,811,793,373,282,319,16,872,300,851,776,221,255,677,407,938,940,119,683,995,52,933,553,837,210,954,821,868,309,978,219,514,189,312,600,251,176,249,757,289,57,786,117,155,341,320,931,797,485,698,778,157,535,729,311,952,337,925,284,457,201,857,924,133,711,227,183,663,378,431,97,823,493,654,500,758,452,198,638,983,360,456,391,465,579,841,479,992,775,578,798,490,953,166,323,109,409,805,344,243,386,892,596,507,449,617,339,831,197,521,621,540,944,86,318,44,402,147,639,972,574,690,204,978,825,606,64,200,415,792,900,655,118,565,550,739,818,369,782,811,583,725,796,76,446,31,854,985,726,219,614,657,249,509,653,977,299,491,800,85,823,328,654,82,687,515,631,59,805,699,709,48,807,285,367,446,386,161,0,367,764,158,165,807,869,398,484,730,245,315,468,445,884,847,99,372,848,796,122,618,40,554,992,627,797,626,354,575,208,821,276,740,236,340,25,511,281,332,221,17,366,847,830,807,121,809,268,629,728,518,544,792,967,459,145,694,919,111,699,752,558,514,862,884,136,654,206,252,632,961,732,65,159,288,365,929,413,428,174,970,268,532,929,413,198,725,264,262,978,340,168,851,151,123,391,909,588,823,580,727,505,463,123,495,599,992,534,185,688,307,490,915,783,70,124,467,129,331,555,634,286,299,163,998,405,932,79,419,357,438,168,385,531,809,44,122,162,782,626,391,533,102,63,189,629,100,128,688,27,723,458,333,973,62,22,830,31,722,87,476,180,426,535,916,675,208,216,804,729,795,420,394,542,656,272,480,242,928,438,894,990,755,328,30,332,467,962,657,32,266,268,226,236,446,359,930,428,681,291,894,810,677,534,267,885,385,446,70,268,434,802,755,286,631,810,218,882,80,354,903,278,41,661,338,71,971,503,854,737,596,408,790,653,262,79,137,869,593,818,253,834,110,154,54,474,325,548,695,960,761,149,633,593,411,493,642,45,99,2,712,31,298,613,376,339,382,131,285,759,711,681,172,193,565,882,279,510,352,89,986,51,589,947,885,4,878,202,110,965,111,93,723,827,34,722,297,610,300,813,926,802,967,254,419,672,873,198,691,121,139,416,42,401,998,997,724,363,320,582,311,868,69,507,555,631,448,813,164,278,645,472,627,897,433,270,830,402,980,18,919,461,325,136,678,450,314,695,98,581,710,248,922,276,124,943,299,755,215,904,668,230,865,632,167,114,322,791,785,359,814,248,538,924,875,166,636,430,855,905,608,40,618,356,494,787,55,762,636,89,598,798,509,903,478,680,7,775,620,837,540,780,41,617,376,757,306,720,62,975,609,812,637,8,516,947,278,555,127,464,155,174,705,790,699,737,143,849,308,661,671,227,576,954,152,336,361,495,190,188,943,966,802,667,984,800,943,254,588,265,153,254,117,174,515,459,454,700,819,332,345,340,649,343,636,549,432,502,82,967,51,946,609,344,131,84,994,294,281,581,574,649,91,357,394,397,632,265,353,977,218,537,286,29,223,657,739,821,51,990,481,267,660,352,749,640,669,796,552,445,638,280,15,793,575,295,830,104,566,32,263,438,364,210", + "507,490,937,272,432,284,279,541,559,931,718,152,829,877,768,321,454,746,829,907,665,264,591,875,10,519,641,697,811,596,36,446,994,439,52,162,297,458,591,397,959,579,436,389,18,153,879,212,95,821,254,397,657,883,638,127,827,361,674,542,979,609,597,487,717,318,222,860,800,328,491,622,372,990,249,675,418,561,767,407,556,792,984,800,846,230,68,616,38,595,589,575,897,237,339,817,979,301,516,256,704,877,579,57,471,341,731,3,16,89,362,239,168,173,439,781,956,734,472,264,897,768,636,667,73,646,100,685,558,598,595,145,419,428,775,758,710,102,398,226,885,414,27,746,858,785,940,605,490,665,264,603,370,954,891,640,843,858,877,460,629,624,52,230,652,690,642,168,395,26,901,211,817,465,147,485,65,603,836,278,557,319,962,600,540,102,179,567,582,97,194,298,628,220,546,284,911,562,825,471,390,659,793,395,892,86,637,582,682,834,203,797,21,857,935,645,496,729,681,837,212,800,52,656,280,215,347,424,831,139,73,622,308,227,882,611,637,747,681,590,869,615,820,379,903,649,533,284,818,327,148,928,666,235,106,276,830,309,877,497,355,652,198,919,148,9,442,716,962,819,998,386,286,750,889,773,278,910,288,196,927,760,265,346,993,290,625,889,10,717,692,925,663,990,487,672,320,638,376,271,302,858,984,765,518,448,971,131,296,896,345,740,620,336,304,657,77,873,522,929,588,522,510,550,496,52,805,986,636,580,918,798,5,500,212,736,341,83,956,769,543,113,146,847,84,216,587,693,957,813,597,876,190,760,14,245,258,248,977,842,192,286,304,563,803,424,572,21,151,592,652,691,855,186,595,676,176,721,633,741,206,948,270,630,813,681,269,660,641,229,458,244,862,322,657,511,788,789,324,841,313,547,305,55,571,22,59,528,556,939,919,523,702,632,560,860,357,465,202,959,422,935,184,608,509,129,888,50,414,831,625,78,584,492,466,188,84,823,613,474,952,219,701,382,272,862,653,169,392,426,206,484,666,199,807,206,595,288,77,241,308,890,347,560,511,815,418,348,682,184,898,799,129,27,708,367,0,35,433,854,338,514,482,998,193,205,876,160,897,805,651,319,115,899,288,642,60,455,239,233,505,795,537,918,652,636,301,815,259,690,832,268,316,905,947,519,194,956,864,407,973,696,599,115,297,38,325,608,876,4,715,468,587,496,3,41,466,389,961,966,500,19,19,767,599,686,772,217,943,65,249,8,186,626,850,26,198,715,994,559,597,741,652,300,663,268,33,183,41,953,446,246,802,913,669,359,223,217,700,711,43,477,59,333,909,742,856,150,495,702,333,520,552,464,727,549,577,980,478,537,963,596,521,694,489,32,700,597,49,540,573,784,403,307,959,954,581,46,251,353,887,240,745,69,637,311,826,79,697,799,796,88,182,522,416,797,344,526,402,597,669,209,858,951,907,68,404,363,449,386,882,175,777,529,911,495,905,913,479,982,528,19,141,458,814,479,536,61,640,231,610,792,345,624,999,22,926,174,754,791,341,88,431,605,958,487,155,838,324,319,492,412,804,631,62,288,276,35,243,556,163,671,531,177,371,961,140,850,23,450,835,987,67,261,636,614,245,250,963,39,982,658,598,994,349,527,13,741,977,239,892,87,412,683,691,848,730,454,75,587,825,642,24,752,279,750,31,788,957,5,900,840,542,721,508,601,521,227,776,176,800,848,250,849,562,723,357,223,938,505,384,581,824,886,35,20,113,41,494,330,74,891,811,643,532,388,437,539,406,831,485,879,136,231,834,688,544,834,829,142,509,554,52,319,378,829,866,231,488,280,603,276,447,122,984,929,761,446,232,250,565,100,386,323,664,435,107,494,369,897,697,295,847,679,863,689,919,61,75,924,334,456,39,507,575,595,509,166,895,216,533,465,418,307,693,553,941,511,250,556,135,176,129,715,700,127,678,727,62,556,648,341,515,80,853,497,905,93,793,885,887,241,710,178,463,915,890,494,204,373,520,534,95,911,694,826,649,883,528,680,774,672,832,13,713,528,958,472,346,607,142,476,325,219,202,408,803,426,666,348,409,747,344,125,993,583,206,601,520,156,120,45,633,579,735,597,322,341,569,769,994,258,990,701,351,518,933,790,962,981,48,880,986,834,852,189,972,471,695,666,284,585,137,951,250,119,286,237,607,468,174,761,428,346,246,577,353,209,235,949,63,715,626,721,599,987,223,287,285,283,110,448,941,694,302,765,860,849,411,543", + "875,491,929,463,388,43,925,619,17,425,851,738,917,743,422,576,79,663,203,207,329,308,170,661,390,800,988,194,539,648,98,698,353,411,145,920,88,50,948,857,224,796,38,712,835,414,334,975,464,648,161,528,732,484,116,722,44,11,721,590,932,838,147,241,779,331,832,848,909,357,320,679,510,591,232,498,14,702,670,624,336,337,23,983,168,620,283,388,692,882,275,828,728,456,466,68,655,526,269,828,957,49,600,726,231,236,484,120,827,932,629,563,717,359,791,929,630,222,442,555,339,775,366,469,697,540,612,194,875,93,197,148,167,877,195,527,682,418,876,960,863,201,841,60,7,521,817,889,297,507,44,394,205,644,970,387,470,585,36,288,22,511,580,270,204,601,242,320,680,571,798,986,705,33,252,25,681,911,700,732,28,733,226,648,636,398,339,195,943,311,370,457,182,363,250,204,60,440,899,305,862,313,417,237,438,653,206,714,941,958,595,500,70,653,944,810,761,684,354,440,897,141,73,869,958,711,881,302,918,849,984,455,222,24,171,9,35,132,102,74,412,583,371,29,63,466,585,548,643,972,332,47,810,421,384,323,349,947,21,223,604,340,861,101,137,752,710,355,866,950,437,776,543,738,586,804,897,114,313,203,914,865,759,948,922,417,811,920,124,580,109,191,500,122,12,884,485,824,461,174,205,113,549,429,718,58,13,18,684,494,223,361,809,27,108,205,627,543,435,427,505,343,385,963,826,883,417,553,632,941,151,78,716,569,333,171,534,670,406,889,43,800,203,742,620,511,705,172,195,331,2,189,986,766,517,250,247,830,440,884,904,283,35,92,220,364,928,111,817,462,782,111,636,817,195,665,624,511,570,992,162,948,140,266,486,81,690,413,160,268,796,961,531,739,826,677,466,456,202,472,586,767,359,957,292,349,397,908,820,160,215,543,455,289,755,362,987,284,106,704,840,998,485,984,11,984,343,758,813,840,544,14,473,340,913,197,564,179,8,186,499,574,133,640,656,893,75,235,484,159,429,910,197,472,45,145,535,58,815,688,60,189,473,613,883,951,231,94,195,84,13,838,919,151,143,764,35,0,484,662,942,882,617,122,416,858,310,713,754,185,941,536,384,907,71,923,202,810,405,227,315,193,287,64,656,384,296,515,239,322,881,768,42,740,691,715,600,522,929,454,514,235,344,369,678,916,783,274,698,774,896,790,742,680,144,788,178,689,270,529,250,550,562,246,589,991,836,400,668,483,860,459,608,51,550,665,845,565,131,330,469,104,711,26,290,732,605,744,230,173,121,734,814,471,924,879,230,131,486,730,672,346,362,576,982,34,374,574,616,577,286,419,208,133,787,756,744,145,296,373,238,493,797,86,888,688,809,329,940,728,551,221,806,684,345,176,726,583,109,856,229,314,334,858,612,504,529,12,921,623,320,640,367,433,606,212,285,282,993,86,395,699,756,770,862,197,908,790,829,428,779,403,950,176,89,940,646,514,289,28,370,956,319,841,327,213,395,908,81,283,299,359,463,84,724,559,853,379,31,344,692,62,510,635,774,54,631,661,813,885,512,722,465,357,258,766,536,708,168,528,438,337,854,978,392,556,239,947,625,628,606,260,44,115,833,440,671,709,859,708,25,494,934,840,658,387,913,69,595,888,437,628,400,778,519,774,975,307,849,626,208,661,388,565,164,551,622,857,753,434,32,137,415,98,453,999,996,971,431,424,974,655,991,19,262,969,466,352,427,132,920,929,268,470,777,747,249,48,146,859,511,128,587,132,890,872,960,533,22,622,228,953,577,645,942,247,143,889,9,543,578,430,499,424,471,22,770,52,256,340,571,984,700,473,961,576,280,303,681,141,562,639,691,281,84,763,951,892,853,530,616,137,548,581,829,205,988,751,451,922,191,175,692,45,485,756,914,460,76,51,835,710,319,869,114,814,111,772,61,551,47,810,25,233,89,183,901,531,218,886,517,520,1000,98,164,142,790,659,20,805,890,280,209,754,791,427,899,559,241,822,741,145,8,117,206,924,951,412,833,565,831,754,738,661,807,328,239,106,380,245,224,579,645,353,842,441,476,156,988,489,432,217,111,17,807,469,876,38,458,480,347,686,489,757,766,219,868,736,916,369,365,301,958,326,862,62,914,810,446,311,761,594,938,813,64,122,605,207,182,469,257,34,585,198,372,161,99,431,244,432,446,541,496,942,397,297,489,713,449,695,219,615,201,295,182,157,953,864,962,427,798,207,113,286,997,93,846,172,959,57", + "434,550,415,260,758,354,327,92,113,410,888,824,937,344,274,598,553,999,235,495,479,124,475,720,819,573,276,610,344,487,569,133,194,150,289,105,665,278,547,898,577,158,583,913,218,969,771,87,34,625,737,936,620,857,777,814,227,680,956,629,170,450,55,904,191,571,227,544,16,276,676,171,860,731,453,80,287,124,460,191,979,444,826,987,948,705,161,307,388,802,75,809,867,764,74,244,788,77,165,176,218,816,886,934,232,679,945,795,954,949,549,730,4,542,994,235,284,312,133,758,921,776,702,227,42,736,810,911,702,353,688,35,649,175,692,426,280,160,59,872,947,659,31,280,232,894,884,581,233,995,600,911,70,756,307,384,877,950,518,859,92,548,471,134,508,138,417,343,64,563,953,889,59,212,361,262,44,454,570,160,377,595,904,778,861,816,629,382,324,222,702,339,744,984,595,559,652,39,254,540,585,935,569,223,805,298,730,57,158,334,575,644,360,378,763,73,209,838,655,568,891,363,830,527,865,341,178,379,847,642,733,784,288,861,529,403,201,805,683,430,253,221,747,95,172,335,189,485,301,161,498,159,708,115,633,408,933,485,853,16,227,556,389,42,170,83,907,404,792,605,440,788,633,396,155,839,57,342,919,358,23,672,423,413,930,218,6,73,542,636,683,152,503,866,772,979,626,981,90,251,67,310,485,764,197,824,931,495,778,711,740,236,204,263,898,114,971,345,27,143,686,300,717,638,919,588,651,140,467,995,393,195,779,997,160,71,592,834,812,771,151,386,257,319,296,563,568,405,711,740,108,588,914,790,269,592,406,681,94,562,491,407,992,563,979,665,179,66,232,672,831,709,130,39,864,507,266,865,860,232,668,569,349,607,432,61,113,631,383,298,25,972,277,730,751,380,869,285,293,939,107,95,643,733,882,497,399,655,67,559,410,842,457,58,607,961,185,145,720,10,61,596,516,671,214,639,404,870,985,132,421,83,113,549,746,379,134,577,508,275,127,165,343,473,946,643,801,41,368,911,572,961,926,569,503,936,308,547,637,78,929,975,551,89,491,542,263,819,440,881,80,100,203,851,796,158,433,484,0,725,862,762,257,624,850,692,4,229,466,125,634,472,56,119,6,883,153,314,626,804,779,720,105,444,403,599,207,412,613,838,737,807,438,74,531,333,566,192,429,187,768,488,677,580,588,521,659,623,728,270,917,905,818,89,37,55,377,802,41,195,111,856,435,85,998,761,15,915,545,518,997,696,177,286,237,551,546,899,103,622,469,97,909,468,464,397,148,58,275,93,118,551,554,342,628,916,132,410,523,112,383,357,22,601,913,114,738,738,128,949,209,357,879,151,656,727,230,183,248,752,768,448,610,413,241,993,287,241,575,756,378,214,795,366,532,650,403,996,785,521,664,773,116,338,206,676,801,346,587,268,234,578,661,782,86,390,535,7,445,19,567,632,610,673,520,760,450,555,34,651,716,372,763,627,98,885,81,806,396,466,249,608,818,650,778,825,823,794,670,551,778,969,319,100,549,394,96,190,249,102,363,362,489,487,967,111,723,797,403,336,346,936,278,121,810,744,224,201,60,953,250,635,176,834,423,330,117,383,847,662,461,121,166,646,978,310,267,606,897,801,661,193,997,126,269,36,623,708,474,170,458,165,470,390,225,604,602,864,634,445,169,455,382,45,12,70,510,550,534,249,450,987,503,82,495,823,509,408,183,596,777,572,731,199,39,420,84,872,947,900,602,949,211,332,263,361,33,574,102,992,978,306,814,477,15,259,922,859,475,810,930,239,273,848,851,186,297,906,865,119,531,563,163,637,661,546,214,624,625,944,780,961,865,12,335,580,196,20,93,82,68,346,111,757,7,979,620,446,774,686,697,242,482,862,206,68,107,519,606,588,11,112,264,989,891,981,14,897,590,779,242,967,860,854,936,761,279,861,567,132,602,765,781,11,788,442,802,435,51,695,131,377,297,708,761,327,682,263,566,908,593,831,760,877,905,315,113,563,134,576,732,21,909,724,244,137,730,21,560,548,604,431,390,300,210,69,581,313,783,579,668,156,377,48,786,849,949,214,174,494,247,457,809,307,829,265,562,828,181,412,609,939,823,9,206,160,421,564,233,475,564,327,649,989,871,49,754,382,224,564,630,268,322,473,590,598,502,526,338,739,962,201,11,247,434,493,480,9,462,61,919,714,529,239,959,114,926,68,359,310,512,987,17,255,145,898,721,355,260,482,712,352,830,819,418,675,551,517,142,130", + "702,983,221,74,158,49,901,105,670,805,424,383,302,918,489,797,182,39,319,629,684,293,269,976,950,207,463,346,377,977,542,4,454,565,391,14,628,198,671,210,157,576,428,208,562,190,82,423,287,648,942,408,267,657,831,508,333,737,354,389,249,312,266,6,984,909,57,594,975,2,139,791,661,749,387,615,578,29,208,441,624,877,482,719,240,817,431,85,881,421,89,797,973,363,417,123,480,336,288,41,844,333,56,490,956,992,575,946,34,738,954,681,686,636,782,854,237,119,219,24,566,975,440,910,220,645,192,418,483,184,766,406,720,298,203,423,283,988,961,921,701,199,399,547,5,647,150,347,442,62,327,614,731,891,808,316,923,211,927,691,94,391,953,772,877,592,905,885,356,796,817,811,189,794,369,818,955,340,980,687,622,125,79,349,87,955,618,927,286,706,504,77,476,252,731,582,673,790,845,755,481,799,749,60,285,18,644,565,61,965,405,188,303,466,701,627,465,535,494,178,311,636,582,338,908,9,439,847,901,581,81,264,735,319,311,997,157,887,163,975,787,473,983,480,673,112,670,546,664,208,925,839,907,678,386,136,61,469,999,155,344,854,702,710,127,687,89,837,941,74,433,478,131,357,15,481,491,856,450,596,61,305,511,341,638,131,231,102,575,535,658,762,190,519,588,199,942,379,199,997,538,267,63,845,658,478,572,985,438,955,846,14,491,750,557,719,883,937,3,176,808,104,403,851,893,414,977,759,291,774,329,704,594,376,45,152,480,997,286,760,765,156,989,198,76,213,845,586,851,324,435,802,186,512,198,261,902,341,372,599,244,228,249,840,583,656,258,80,958,460,980,316,762,89,167,997,2,466,187,72,739,338,865,638,784,39,858,208,867,832,946,461,582,79,382,326,767,712,227,547,582,575,203,345,927,649,183,977,709,642,788,276,761,789,966,300,567,727,566,487,288,814,128,63,962,912,253,620,688,59,70,362,376,380,476,804,786,847,75,674,554,421,771,937,530,284,108,419,809,558,158,46,959,926,653,902,206,406,388,626,404,283,396,11,510,928,107,17,72,389,845,874,104,976,802,165,854,662,725,0,164,484,953,819,498,779,76,634,843,217,798,930,616,863,230,811,105,552,476,101,381,444,327,510,238,132,727,305,956,841,211,778,205,361,869,684,285,962,843,232,493,975,891,193,268,411,846,143,288,897,74,895,126,517,37,789,711,926,879,584,808,244,334,269,405,835,411,521,660,965,676,322,505,865,875,46,88,535,77,649,593,849,347,438,553,363,594,126,401,774,212,834,118,915,404,709,461,353,250,248,336,416,830,695,30,496,490,400,769,714,500,187,846,98,437,157,161,366,805,210,634,198,262,856,571,429,197,63,476,122,943,772,55,405,876,183,876,156,847,369,417,913,635,259,762,858,250,884,275,217,493,826,405,510,639,19,910,534,928,882,452,282,289,169,992,571,349,141,47,704,390,457,409,118,997,361,738,646,81,232,975,847,777,598,465,823,713,769,175,246,352,285,679,642,368,332,786,662,658,749,567,100,268,734,928,567,850,279,312,613,435,933,61,439,495,982,705,873,349,684,772,318,424,842,893,614,193,688,343,494,185,782,148,140,210,702,398,368,74,57,995,970,719,124,154,389,723,222,337,551,29,783,338,512,627,17,540,139,806,363,102,188,619,594,464,781,12,960,363,272,8,220,927,454,4,233,157,355,249,370,688,381,804,619,622,860,450,305,418,902,298,769,617,153,615,321,698,663,291,915,172,278,80,200,232,71,535,791,461,38,926,571,27,420,414,360,749,641,913,83,662,124,583,806,966,328,604,317,317,424,272,736,112,40,12,591,747,762,231,200,481,196,706,564,707,626,18,696,287,344,354,674,962,970,299,744,757,555,831,144,343,338,325,581,310,759,744,293,332,216,356,668,457,555,634,887,129,21,247,179,209,222,640,909,25,920,218,100,395,917,878,231,122,952,363,288,920,411,953,55,440,878,768,128,969,183,214,15,338,569,737,523,512,663,843,404,112,168,750,417,286,872,839,134,952,173,770,841,554,940,501,143,339,881,594,663,977,65,389,933,879,738,964,604,178,230,976,133,996,849,393,535,132,668,660,164,936,753,500,219,714,296,132,780,327,681,777,718,392,427,750,313,473,169,206,935,95,10,809,782,328,759,265,729,307,997,950,384,182,20,125,498,754,243,869,639,327,76,788,540,860,568,594,216,733,12,745,344,508,320,60,655,582,487,518,604,733,203,199,917", + "109,812,6,531,121,389,56,976,354,829,482,670,998,895,283,292,827,629,385,331,394,418,184,822,899,481,460,764,394,845,92,745,142,153,795,113,720,209,348,184,428,967,430,840,993,255,970,579,128,530,424,190,604,597,366,533,277,360,92,957,323,795,198,744,747,124,364,812,347,906,821,192,4,274,839,507,300,696,191,442,563,139,387,52,392,869,367,862,621,18,540,430,77,173,738,603,731,497,473,659,204,653,126,460,740,414,767,756,163,947,289,862,340,501,378,489,747,722,882,693,735,721,50,128,565,50,250,699,716,677,864,806,385,281,267,632,425,939,126,596,35,546,826,241,706,401,410,390,978,882,712,137,310,64,611,123,122,68,76,438,941,783,358,674,669,461,432,881,115,636,44,692,174,623,960,303,949,995,162,104,620,120,312,430,121,433,405,449,43,177,557,287,549,489,366,202,761,457,689,28,825,396,905,345,411,147,83,27,403,29,540,724,57,567,708,695,940,769,128,178,413,402,786,509,301,591,878,317,83,734,498,632,419,851,303,451,279,238,935,108,588,69,314,161,82,99,398,839,332,46,324,71,56,753,16,31,650,721,476,101,692,557,849,744,340,579,30,354,774,790,403,527,849,846,298,543,242,480,336,65,13,700,210,762,463,48,806,53,413,236,493,646,638,661,416,668,807,623,198,17,398,408,164,465,400,135,324,837,15,578,975,454,878,100,540,243,18,223,369,664,382,919,862,42,855,16,629,495,194,653,322,452,898,790,656,583,459,974,252,827,838,307,124,998,115,300,678,917,532,594,885,374,865,148,410,516,170,920,60,316,267,758,520,406,999,532,28,143,276,180,250,941,959,891,93,638,611,552,767,748,152,265,462,89,162,305,306,147,924,521,589,355,270,896,691,94,156,302,421,207,257,698,213,354,797,512,911,837,289,679,306,424,466,794,653,143,700,816,182,694,500,525,216,333,31,618,916,521,89,539,765,234,847,589,756,834,309,120,523,662,108,180,166,838,208,904,423,828,599,133,645,777,743,718,569,902,222,693,108,591,801,695,797,205,546,487,505,444,421,515,991,331,9,689,662,807,338,942,862,164,0,651,598,219,578,526,387,850,63,751,696,732,87,839,866,34,447,159,238,509,151,46,39,977,95,74,552,834,151,5,327,439,383,839,86,971,856,64,788,227,679,516,882,719,554,34,834,317,359,334,705,227,863,551,991,597,381,839,632,908,549,949,612,858,197,17,458,792,739,346,419,488,884,931,870,412,4,377,958,222,201,663,858,455,275,680,419,68,681,608,313,644,559,340,354,918,937,908,271,824,334,14,730,477,694,305,303,607,881,908,897,862,191,334,863,619,806,411,156,584,630,401,601,916,401,608,883,18,772,604,942,153,474,418,969,732,734,210,511,520,463,460,716,433,33,952,865,241,85,499,360,506,384,56,218,766,543,483,581,253,352,184,568,236,513,708,92,984,86,275,191,662,830,371,462,475,61,787,943,165,768,383,171,677,902,841,765,153,356,386,586,258,352,909,516,898,677,831,117,111,578,767,512,421,813,433,542,480,53,385,92,180,18,381,70,631,664,46,436,701,370,897,912,352,237,205,816,463,635,48,261,274,204,336,701,690,898,789,709,55,207,966,9,55,66,394,706,483,300,129,911,570,297,189,900,279,620,342,189,8,96,831,82,69,749,854,742,660,874,62,123,411,404,850,807,681,452,672,620,614,899,716,717,484,469,722,907,726,752,916,968,33,840,367,738,561,900,726,435,85,672,482,913,616,327,645,622,743,360,991,101,684,154,736,96,865,761,736,586,877,74,407,166,64,257,725,21,723,306,326,516,495,801,523,253,684,211,7,191,237,712,326,906,997,895,421,584,940,165,347,311,847,141,854,477,185,923,123,933,806,365,569,698,963,899,216,568,706,352,135,382,81,974,696,291,353,432,526,445,850,275,377,976,627,559,317,68,422,161,11,857,229,913,615,221,245,200,749,918,283,480,416,937,413,563,188,827,601,171,9,353,699,373,307,69,379,186,77,405,411,103,649,499,850,333,56,610,333,714,548,780,902,678,51,440,515,316,88,399,161,686,256,320,177,415,646,979,842,546,20,164,948,713,261,927,558,868,995,678,830,875,78,187,656,178,800,564,65,245,901,186,152,58,392,596,530,399,242,445,390,733,373,617,606,469,804,465,714,908,597,759,534,359,233,636,424,783,258,136,770,748,214,201,684,518,71,313,696,517,332,990,935,378,413,411,165,217,229,375,285", + "32,652,666,726,868,606,528,429,685,990,735,201,954,12,610,816,290,427,527,877,966,839,332,942,374,68,428,14,439,781,399,457,6,76,891,25,850,949,779,272,453,68,173,159,267,554,595,189,531,673,221,122,797,648,163,846,648,866,126,101,994,385,253,700,313,650,751,901,239,872,217,648,241,98,331,713,394,710,493,107,349,958,458,413,555,694,107,917,70,939,976,408,643,180,797,966,893,328,811,294,63,111,816,994,514,786,406,520,717,997,610,330,896,87,963,74,728,566,343,472,47,863,951,861,397,76,290,535,350,397,294,409,409,522,328,684,615,813,462,622,54,971,415,445,595,975,270,749,822,214,176,977,659,395,879,432,620,410,465,51,999,620,640,845,542,102,702,326,335,625,831,621,43,969,723,550,780,996,170,938,648,483,678,981,73,776,295,497,534,526,671,443,420,641,797,92,885,983,769,701,703,454,106,433,153,410,350,865,530,118,386,879,369,797,762,889,816,119,769,804,855,291,55,878,795,177,83,296,191,808,268,3,113,810,918,171,224,331,48,530,970,936,82,505,590,282,101,55,577,642,27,314,441,213,423,480,895,388,804,995,79,28,487,164,708,565,377,799,14,204,914,524,638,674,339,379,233,439,141,137,727,876,411,985,532,290,58,879,274,483,484,186,331,544,903,400,288,28,940,337,699,901,366,777,353,92,758,326,23,355,113,64,874,738,107,483,862,96,440,732,799,276,67,220,55,950,526,181,376,48,957,691,119,845,526,346,145,885,355,641,851,85,849,88,737,973,431,129,402,949,251,105,922,388,876,272,748,645,764,521,677,579,141,680,485,204,150,148,614,786,176,516,468,775,399,666,538,675,50,627,197,238,42,297,899,796,707,667,618,561,489,772,826,786,996,801,686,761,956,847,875,106,307,624,400,20,98,968,434,579,942,882,35,70,403,540,564,958,440,886,689,602,573,382,515,933,308,944,524,878,658,764,796,615,837,421,273,679,149,847,495,478,641,987,388,82,457,802,561,783,155,667,544,470,131,247,723,422,333,426,89,546,677,821,79,350,336,556,813,200,309,690,99,271,875,869,514,882,762,484,651,0,683,27,33,475,531,561,702,316,53,393,643,389,246,448,823,636,265,108,429,656,935,77,956,881,709,605,884,809,667,244,53,938,598,89,857,401,784,367,471,40,636,203,369,727,95,677,169,634,770,209,346,224,435,40,77,777,106,920,380,73,646,121,554,594,717,149,585,361,609,468,182,853,62,668,677,726,370,790,483,49,882,205,59,479,760,512,747,939,820,522,371,794,577,367,86,687,159,340,659,276,465,886,827,642,835,650,714,611,444,488,126,680,686,133,795,801,673,524,298,132,510,141,856,463,993,143,197,931,549,629,980,186,372,193,255,917,967,785,1,135,438,822,458,197,603,298,311,280,464,780,34,708,696,874,99,460,369,464,513,444,860,552,265,118,274,375,616,840,752,25,717,31,959,642,313,381,135,51,775,858,911,479,930,509,788,298,374,577,509,323,884,34,960,266,785,806,843,707,249,793,895,552,282,894,983,441,753,558,68,116,974,518,136,819,448,747,513,474,104,83,351,650,392,396,319,386,726,150,403,544,518,945,493,433,714,602,733,54,117,500,464,670,586,290,346,118,600,883,599,727,322,912,753,336,721,65,198,333,532,313,153,312,296,389,688,432,228,166,419,768,920,535,421,524,231,357,467,188,212,208,362,928,630,824,416,386,48,213,201,810,619,127,540,585,71,256,309,47,765,120,610,764,46,966,894,836,64,612,98,252,797,671,444,496,764,826,597,95,533,577,575,19,755,615,478,161,736,569,413,494,586,902,597,186,309,980,624,552,716,898,424,674,741,118,931,999,564,174,149,208,531,33,787,430,876,373,186,721,247,809,956,842,304,11,200,994,113,236,914,883,566,801,157,393,819,266,454,672,643,715,543,306,594,1,201,209,899,620,419,509,717,462,623,289,697,507,558,189,435,195,733,353,379,412,135,508,521,311,226,332,806,181,129,233,760,346,61,381,847,963,639,767,846,811,487,248,866,957,190,976,305,734,225,515,340,263,643,760,530,149,433,860,12,479,266,810,971,185,243,950,253,879,747,297,869,641,972,76,366,998,251,100,287,504,359,603,808,174,954,124,12,994,184,277,334,927,565,230,727,871,756,374,571,984,393,15,269,158,975,676,478,213,689,190,698,571,551,657,516,678,70,638,67,934,407,3,941,795,102,804,852,69,795,657,624,487,741,456", + "835,170,263,822,961,522,113,685,345,72,637,572,290,409,876,757,790,306,599,737,887,427,945,816,841,789,958,935,812,865,986,31,716,796,686,345,983,966,442,551,468,611,865,346,329,767,872,440,379,465,65,977,894,995,840,961,429,882,707,666,46,865,295,851,709,880,43,187,744,611,640,566,720,335,967,22,538,206,731,77,916,499,923,640,391,668,380,807,212,719,677,122,300,280,573,996,27,147,235,397,765,887,416,568,772,720,212,540,984,843,749,897,814,219,99,278,395,522,439,62,72,141,807,413,215,155,187,309,684,845,946,842,541,19,825,462,903,409,11,128,961,422,859,151,513,12,372,136,158,605,872,666,556,917,554,58,411,68,212,166,323,923,991,622,750,420,423,604,377,7,782,667,358,812,94,918,68,812,190,38,605,980,659,80,59,68,964,125,907,89,597,632,6,283,625,533,831,226,775,62,779,451,50,585,699,197,47,584,419,864,198,359,465,219,175,128,821,840,192,112,714,871,184,653,922,550,518,729,109,618,473,390,902,624,433,370,888,620,475,409,391,272,626,374,747,1000,862,636,814,123,258,327,447,520,428,621,226,895,776,615,163,81,79,525,274,428,507,962,112,837,160,625,715,592,997,303,869,16,483,892,548,633,661,18,801,32,780,543,566,468,517,746,232,235,86,451,977,435,651,78,138,800,947,675,486,44,605,580,42,189,821,562,460,964,386,866,595,676,538,663,991,885,847,43,454,359,56,954,859,433,963,259,469,255,266,598,886,625,878,365,529,403,213,414,372,234,942,790,32,998,654,88,475,87,259,873,110,906,822,148,718,467,371,984,95,325,384,404,626,870,457,470,808,356,704,469,814,524,919,137,863,94,674,367,493,113,301,366,333,685,12,182,233,367,304,864,226,243,453,504,132,781,973,982,591,984,903,21,968,802,461,41,382,265,786,163,413,710,337,872,324,490,739,761,668,977,602,422,171,431,242,47,414,452,798,480,745,834,126,16,186,853,248,980,860,140,166,937,207,346,744,440,422,64,976,584,69,3,127,383,123,20,197,136,960,238,260,719,331,852,21,888,705,36,680,398,482,617,257,953,598,683,0,999,824,378,716,784,647,49,687,564,8,301,995,309,991,884,413,869,962,582,820,201,251,815,404,179,580,400,774,157,235,187,409,719,638,615,135,758,383,392,211,284,696,407,913,840,868,445,799,110,650,186,271,742,403,302,335,129,972,509,298,831,805,550,809,421,135,613,156,954,80,669,413,840,730,950,396,299,732,89,570,440,750,449,736,472,403,684,995,419,929,10,18,764,201,544,390,317,502,356,772,27,844,663,41,24,333,274,669,497,785,150,835,333,657,754,624,820,494,460,764,807,980,557,337,132,488,436,61,850,967,165,489,42,2,818,904,983,442,864,713,377,556,818,429,469,416,122,746,642,428,245,672,201,839,988,228,210,756,757,657,512,847,579,923,892,393,843,312,785,189,94,748,726,913,632,586,221,570,834,483,985,392,284,857,880,288,361,635,670,909,347,585,598,453,312,370,873,366,379,106,760,491,363,280,309,277,73,268,70,744,699,561,818,767,845,582,771,105,270,459,8,475,590,533,379,249,152,870,635,551,111,921,549,987,871,58,749,471,734,996,74,731,427,374,400,590,380,310,515,785,171,249,473,726,792,85,993,209,177,331,831,731,605,875,882,111,343,656,980,919,292,344,339,618,737,745,513,22,867,294,601,833,803,817,962,155,636,959,392,195,271,242,113,920,258,727,514,647,611,974,823,744,466,240,442,48,965,287,641,376,894,431,773,321,389,646,640,344,925,676,455,200,276,781,573,542,141,495,908,316,528,472,175,230,604,694,59,664,361,7,758,935,748,669,758,201,671,193,499,14,811,170,437,336,517,497,823,353,686,744,897,201,942,598,579,521,879,249,838,809,362,118,434,483,784,433,632,448,702,222,959,828,285,963,865,831,478,379,18,229,255,145,94,728,588,815,303,311,818,470,964,414,62,13,506,229,809,756,105,57,615,798,514,10,941,348,542,122,707,564,751,347,549,107,153,928,155,211,759,151,312,101,42,975,689,630,749,483,903,278,54,418,506,773,695,415,610,633,887,188,402,89,995,670,140,749,515,518,922,207,704,150,329,824,605,780,854,649,172,968,656,697,594,505,797,761,981,156,817,826,381,242,270,914,476,159,992,771,69,220,591,344,341,431,170,203,900,486,558,533,201,931,804,652,655,792,732,985,89,379,428,423,184,734,320,732,36", + "788,618,1,622,959,695,289,303,20,191,656,667,304,851,567,995,736,848,301,577,605,602,930,84,140,927,86,692,441,32,379,462,114,807,365,466,505,534,431,792,96,64,208,359,294,523,870,516,160,474,625,822,877,849,10,851,940,165,154,724,208,73,427,5,55,201,194,600,763,869,918,123,469,352,13,358,30,999,340,58,761,723,591,687,308,956,258,958,189,939,184,614,682,248,389,736,996,114,363,907,398,985,549,735,962,283,706,894,680,821,847,408,190,70,625,184,673,288,778,801,336,677,8,907,40,646,793,36,800,891,436,177,163,11,664,750,527,699,611,929,257,582,520,401,413,484,77,530,108,266,356,975,128,757,880,612,966,679,393,65,803,874,18,577,904,624,263,184,502,738,492,505,611,908,636,172,36,749,907,757,106,797,286,129,864,750,38,81,36,68,839,897,29,173,576,410,139,731,445,212,19,881,107,894,334,611,376,699,883,687,427,305,653,159,32,62,748,462,680,386,942,814,500,898,131,35,421,369,839,311,508,680,385,947,20,889,469,708,788,575,100,827,126,670,67,117,815,138,447,338,756,217,58,949,33,927,812,651,687,566,30,603,943,871,981,935,127,733,943,653,990,503,381,879,910,673,815,664,49,563,915,215,848,74,291,359,326,968,341,854,137,46,757,651,276,660,978,360,64,672,635,231,425,327,764,85,146,223,149,58,91,860,500,271,879,785,834,455,888,573,274,695,908,516,713,962,979,753,925,739,635,141,439,573,490,245,241,775,412,394,463,645,919,547,788,771,493,962,578,891,235,817,108,219,72,919,93,866,488,554,168,450,879,12,868,84,901,868,551,564,945,475,330,625,101,134,412,96,509,673,784,97,727,268,432,641,281,935,804,595,260,716,138,134,389,893,370,755,171,584,345,963,519,845,865,247,754,793,11,560,494,256,597,268,792,729,149,930,716,450,701,980,960,505,475,9,40,766,126,802,217,50,539,441,544,523,58,511,805,489,268,806,130,294,840,395,239,116,857,664,123,842,242,863,625,452,144,97,926,445,925,50,445,662,297,206,177,421,208,55,683,265,75,387,508,484,998,122,624,819,219,27,999,0,94,357,476,440,356,966,728,319,762,242,815,962,315,529,777,203,224,934,356,954,476,239,763,24,210,447,952,721,579,268,47,387,231,79,987,968,426,954,554,332,996,841,176,512,190,81,169,904,989,819,765,434,775,784,686,582,699,194,183,435,682,950,178,759,217,94,667,92,850,213,593,821,394,554,871,699,662,648,340,439,886,382,345,707,792,856,778,917,93,167,916,139,736,852,495,177,563,4,386,506,502,800,980,207,20,482,198,745,808,885,650,300,603,436,863,429,606,171,863,99,286,226,808,934,140,715,430,365,75,306,60,9,711,116,385,874,328,422,658,197,144,873,306,889,465,336,55,837,984,355,637,365,550,779,466,195,216,356,664,347,111,598,88,279,52,87,499,792,521,294,204,484,43,258,696,693,659,358,983,530,889,221,702,164,95,536,529,509,413,278,957,164,313,98,961,56,296,126,581,904,268,881,960,837,411,258,371,201,900,556,471,903,679,412,308,629,515,58,977,55,473,705,368,122,90,652,684,804,571,725,525,7,352,297,521,613,217,550,303,454,51,176,588,878,855,444,13,547,691,626,143,113,32,21,428,771,646,926,250,934,875,278,618,909,555,38,659,555,128,386,558,97,298,756,324,981,655,848,667,583,545,842,939,476,601,457,319,148,7,946,789,593,936,706,777,527,154,27,42,805,26,275,992,106,902,163,259,309,869,87,797,656,780,733,157,265,663,568,132,994,739,343,691,517,244,369,210,604,117,377,294,157,702,832,225,909,943,27,817,464,205,192,597,41,284,617,387,307,7,866,502,158,321,342,8,218,396,26,324,928,678,971,68,75,824,970,376,490,585,426,500,366,30,78,521,348,469,108,346,448,684,613,805,425,352,469,597,678,228,678,108,541,157,705,217,470,162,984,282,295,41,599,677,529,149,75,790,784,205,193,386,845,523,188,887,809,460,29,248,170,765,148,810,522,989,972,508,924,967,821,747,404,183,233,182,149,671,68,727,547,565,94,417,789,366,886,278,467,814,706,143,779,765,537,19,802,767,893,308,21,273,920,439,711,723,721,986,744,476,777,289,787,622,858,864,309,680,416,25,421,171,604,264,878,872,615,664,393,546,581,858,301,45,248,790,34,312,739,404,652,766,716,624,130,496,197,572,754,121,214,941,741,640,179,714,479", + "108,665,314,831,641,531,780,453,78,607,43,809,473,271,960,525,740,669,980,184,298,819,430,901,303,670,100,867,992,343,596,146,710,287,206,803,753,198,423,276,801,938,967,892,940,74,932,983,579,693,46,379,717,898,700,560,716,845,986,61,376,714,134,874,917,554,680,855,729,272,431,528,683,518,198,647,138,580,584,460,379,22,182,683,30,612,969,168,272,485,188,635,615,271,349,329,499,763,567,654,548,874,187,580,297,514,560,469,787,4,514,664,393,86,884,877,359,486,62,19,14,484,830,827,270,6,505,536,370,581,978,18,628,551,327,765,712,678,874,317,777,647,689,899,222,466,123,38,74,241,425,768,676,350,196,961,926,32,383,589,779,816,883,575,650,542,915,873,674,335,430,358,860,15,341,484,865,684,60,803,146,997,47,176,19,245,245,129,975,636,302,408,644,827,629,639,125,697,3,178,477,333,841,669,654,250,71,933,270,26,4,482,191,92,45,807,363,935,968,610,338,593,459,369,701,818,143,854,699,912,882,414,295,502,123,945,91,190,650,792,315,973,452,925,935,621,6,43,112,821,716,122,811,795,943,901,312,834,81,852,424,631,166,359,360,370,905,303,214,200,915,533,396,182,713,177,714,984,878,173,888,512,780,400,105,592,60,951,476,198,457,38,338,72,413,330,151,136,762,124,590,427,694,914,118,269,936,553,552,372,755,704,761,267,948,944,269,228,272,133,389,664,75,843,274,212,923,90,271,105,548,570,469,960,783,809,809,613,765,243,619,438,108,598,150,899,112,879,783,617,919,754,191,533,861,472,121,718,683,282,64,343,947,662,79,644,97,731,707,47,339,861,765,805,891,837,720,313,693,148,727,724,494,815,842,236,516,255,933,496,560,846,556,519,304,953,845,270,149,376,932,519,98,552,227,331,951,583,773,241,867,765,839,705,456,252,642,851,396,324,898,582,859,734,925,406,738,208,683,44,61,298,680,654,969,295,787,48,834,114,811,693,331,702,731,332,755,789,634,169,343,827,553,850,397,357,725,583,695,934,5,170,904,48,20,153,555,492,410,446,851,371,687,24,243,730,193,416,850,498,578,33,824,94,0,604,921,347,428,598,728,657,950,224,576,631,926,429,986,153,638,49,996,66,53,179,441,461,175,905,988,501,385,823,47,150,955,393,449,59,345,400,684,745,660,720,471,689,451,341,733,695,415,197,804,169,771,666,570,274,108,587,492,165,351,35,5,506,337,839,662,681,453,514,261,276,65,252,111,702,220,947,884,940,390,407,703,972,979,645,225,509,38,877,528,894,696,411,232,851,920,881,174,511,671,464,570,884,545,395,226,487,582,987,324,371,133,590,906,75,605,754,320,981,889,34,253,590,451,273,542,717,149,373,496,312,17,147,743,112,764,993,92,841,776,158,143,275,243,834,298,852,20,442,988,189,855,860,541,3,969,159,978,572,658,895,568,911,309,717,885,675,918,208,937,584,470,880,969,227,22,835,555,634,822,33,158,576,465,257,508,644,286,544,404,368,876,595,775,144,673,60,671,34,142,970,931,598,339,166,967,530,14,829,695,529,821,807,8,476,451,839,59,613,358,577,611,585,644,798,791,725,244,15,790,152,410,512,475,113,176,400,571,744,32,743,855,89,70,836,133,972,519,579,552,266,496,293,51,695,917,205,556,635,697,157,949,413,759,574,147,835,878,945,814,233,750,156,295,822,451,861,360,390,963,936,41,242,486,182,929,229,387,781,29,426,569,503,396,800,604,116,513,789,394,887,518,157,713,505,524,369,254,265,810,612,212,794,596,334,718,971,503,253,696,72,21,558,259,337,912,635,886,79,235,457,944,804,484,10,355,380,320,361,101,198,200,859,102,876,459,915,142,239,857,823,905,351,382,639,133,165,135,923,378,127,373,634,485,621,483,296,931,88,389,178,970,396,643,846,436,235,992,775,455,323,539,468,848,158,378,858,767,964,295,599,230,307,874,361,645,440,469,13,123,71,593,567,81,695,838,412,229,27,662,57,739,535,246,949,192,524,917,977,718,569,493,650,215,250,971,475,419,625,473,820,637,782,43,669,29,448,105,854,542,287,768,180,399,53,30,414,571,79,356,31,203,645,673,211,249,780,668,642,403,756,808,493,544,634,709,654,859,191,743,427,229,251,205,322,124,30,664,205,286,900,262,902,739,247,627,712,192,580,929,639,835,207,485,691,382,596,672,428,379,155,450,30,928,565,50,411,598,490,75,862,194,494,159,789", + "469,439,643,442,370,805,181,302,248,492,281,265,492,295,254,728,896,223,911,214,197,391,650,609,867,741,220,513,969,177,586,459,947,65,223,571,952,21,349,288,192,769,169,476,976,259,481,690,408,38,148,289,937,143,997,716,345,96,301,666,890,256,369,865,409,297,120,884,189,555,482,158,619,803,689,893,573,716,921,418,556,939,545,189,266,832,395,844,977,705,256,57,749,385,614,371,511,519,585,791,892,368,526,607,226,754,724,19,229,380,433,893,805,714,577,805,913,311,822,830,178,725,751,701,922,976,288,250,348,169,503,151,435,860,789,405,89,247,166,41,817,720,100,341,26,909,626,630,72,862,104,146,215,90,843,454,404,143,514,401,178,848,871,800,967,931,689,291,206,700,319,370,652,28,431,838,257,882,481,377,1000,713,511,490,758,557,799,82,258,604,156,26,542,494,877,905,278,186,92,637,507,620,107,702,732,66,854,410,42,398,459,216,439,425,609,310,670,397,615,354,929,599,365,75,527,444,784,825,796,580,253,473,491,824,895,745,476,153,137,623,799,797,408,957,91,700,931,431,543,371,659,826,479,783,727,384,566,49,441,97,774,174,837,544,833,738,789,351,880,565,236,166,847,956,879,809,983,994,696,857,353,104,769,447,510,717,934,556,803,179,550,888,63,594,331,453,807,918,986,30,705,177,493,736,439,539,270,203,681,612,929,511,283,445,549,686,861,42,515,837,86,796,93,659,86,198,719,788,274,787,260,995,60,774,590,126,964,340,197,867,751,670,92,776,862,178,757,861,819,893,569,786,249,726,521,223,292,470,347,310,105,573,952,657,482,205,752,183,290,146,672,509,466,701,187,327,703,138,54,940,194,878,581,928,566,409,690,596,165,80,883,470,281,207,329,707,183,880,204,207,399,437,503,99,463,698,284,282,454,611,90,703,308,190,511,147,475,967,750,381,366,20,867,588,235,618,320,60,859,792,844,908,436,114,87,22,717,988,751,451,201,63,790,926,436,734,95,56,367,143,257,914,432,846,971,89,626,303,903,206,949,864,428,790,277,111,428,360,209,713,547,518,476,539,827,245,205,858,692,779,526,475,378,357,604,0,629,87,673,282,287,505,507,440,363,718,785,369,883,544,944,626,167,579,175,390,130,537,515,16,734,121,308,683,478,482,526,716,767,499,56,18,77,659,168,294,531,542,689,823,843,966,831,347,341,350,808,519,963,62,855,397,569,209,556,778,619,364,637,219,180,572,960,276,657,908,389,6,235,840,321,288,439,863,425,778,80,516,427,222,986,622,702,913,391,138,213,667,597,279,409,794,75,509,959,992,903,641,987,19,857,298,678,748,715,126,760,538,192,810,470,581,389,798,355,664,154,776,489,121,965,644,691,419,769,676,105,973,721,550,235,178,809,904,355,830,978,913,41,23,910,643,787,776,199,658,67,530,871,371,305,796,61,411,73,464,808,978,631,809,390,717,167,429,780,254,872,444,86,136,979,129,309,254,847,940,172,852,165,167,361,685,381,666,27,490,363,461,770,922,299,245,824,526,917,888,202,528,389,542,56,232,471,251,372,573,432,155,740,65,43,173,887,678,214,750,858,812,945,726,164,288,109,145,127,283,350,449,341,157,915,757,289,376,709,432,319,598,399,250,896,16,225,82,902,384,991,216,949,949,761,373,443,760,196,177,108,126,678,512,960,953,458,236,172,558,407,478,785,792,124,58,123,41,258,414,875,399,17,208,704,135,351,886,981,151,524,127,832,687,104,804,887,445,383,360,532,312,243,211,795,558,981,36,959,21,608,695,34,569,592,556,209,880,339,438,846,465,294,645,346,228,402,316,430,812,349,714,175,29,551,386,110,433,416,924,814,905,781,994,169,163,736,937,385,791,501,576,696,113,350,670,333,805,236,733,696,312,119,390,464,153,604,998,875,568,502,516,297,490,445,530,751,428,554,389,443,716,283,653,117,664,538,765,792,16,586,708,339,888,383,217,974,209,275,312,187,390,17,844,765,158,182,49,760,468,921,271,28,800,975,188,323,557,12,995,303,301,182,331,345,643,314,189,446,328,162,928,811,908,624,748,534,383,903,289,67,211,725,116,61,435,485,746,367,281,545,119,239,311,881,866,63,701,612,185,11,884,187,663,430,162,803,33,528,464,377,669,222,805,90,606,68,299,92,68,875,38,898,760,655,369,609,483,482,449,768,912,160,328,524,525,564,53,231,732,445,789,994,757,491,48,230,6,235,385,647,978,712,144", + "171,966,299,410,164,144,460,219,12,910,529,732,733,650,230,907,329,323,81,119,995,810,637,883,625,803,915,710,160,823,114,425,6,722,921,931,501,849,215,578,409,658,321,689,875,501,165,568,51,887,218,145,528,832,825,321,347,385,238,437,322,464,196,515,852,439,712,153,880,749,182,724,65,986,802,650,345,855,43,42,785,799,28,505,293,444,196,836,510,133,460,336,175,271,200,758,451,726,359,340,111,51,743,835,637,656,907,806,807,939,254,873,607,3,924,320,175,614,412,292,358,470,793,733,367,635,9,77,601,647,223,730,794,345,966,896,611,491,100,209,112,964,839,577,37,282,862,195,411,32,636,438,381,249,521,7,946,781,566,976,607,937,835,758,269,386,511,825,901,393,878,859,870,904,25,263,866,130,649,139,842,125,256,337,307,160,950,947,86,943,819,533,348,107,876,291,231,345,403,632,522,976,764,233,57,739,206,356,334,626,552,448,89,67,946,194,873,162,712,631,364,13,611,498,493,988,184,242,493,224,794,84,759,858,918,713,937,476,433,994,409,614,257,337,183,299,406,708,509,95,275,370,324,128,433,6,617,847,15,166,115,370,678,873,467,761,836,17,859,18,428,600,840,608,639,603,890,993,777,642,388,247,550,159,858,565,974,936,317,967,842,821,260,468,355,454,962,783,558,614,615,617,741,573,859,192,205,669,689,662,581,148,106,501,18,535,730,210,102,423,47,298,821,795,972,481,900,253,915,946,132,372,782,546,887,907,555,39,364,599,874,685,471,919,610,186,897,764,971,571,129,467,355,946,506,567,999,818,476,964,939,946,638,982,933,535,561,903,288,239,408,851,600,40,495,315,97,470,68,618,719,444,303,655,872,673,910,92,346,869,533,548,999,892,87,863,387,446,808,859,395,522,673,274,297,850,97,207,105,526,680,146,276,735,315,655,216,127,440,260,821,641,737,993,29,349,246,161,429,200,701,423,210,946,974,246,910,829,381,325,847,528,922,520,862,784,575,23,371,466,890,835,803,455,683,752,753,243,992,958,400,608,347,979,80,406,973,517,280,607,371,630,184,3,73,315,876,310,4,76,387,531,716,476,921,629,0,506,705,890,534,482,796,254,111,644,493,95,485,728,549,634,502,312,465,656,531,57,858,670,107,658,318,339,667,269,841,689,291,81,142,76,60,602,86,621,632,168,636,499,906,498,839,67,168,76,404,158,683,860,547,455,282,944,988,426,820,736,320,635,115,518,441,437,886,109,693,48,660,328,575,235,22,160,374,176,15,136,682,10,686,781,754,818,670,605,547,435,790,954,878,921,995,58,621,266,989,82,396,487,701,556,961,801,15,87,778,538,766,917,70,893,516,77,46,756,748,138,290,950,796,664,659,491,582,851,298,766,650,691,377,563,723,832,269,413,918,874,966,959,59,599,746,43,623,823,698,899,407,527,231,698,91,269,355,224,315,795,274,131,986,618,253,271,344,668,98,673,194,899,341,831,415,378,296,990,444,839,907,686,127,170,845,274,885,656,229,721,346,458,221,566,526,973,45,659,683,241,894,759,376,430,445,815,344,241,62,286,733,818,338,951,931,132,76,286,453,361,364,994,302,16,567,385,288,966,473,325,900,236,792,54,658,602,694,376,985,946,483,832,973,994,440,274,110,306,374,213,129,308,737,160,652,338,109,713,280,240,34,753,33,420,695,917,641,912,299,175,178,749,974,275,89,802,311,969,654,507,687,941,531,265,421,604,196,256,219,812,743,52,264,929,346,212,46,271,965,662,738,101,980,70,969,912,4,960,787,144,58,666,424,181,970,260,724,242,273,498,401,925,623,603,98,319,374,541,280,356,561,50,549,234,318,886,772,703,243,793,710,56,472,214,847,739,125,378,727,746,578,77,167,864,821,584,629,807,54,517,145,366,698,332,967,756,599,942,568,750,108,147,638,86,484,606,908,181,959,998,534,963,412,268,790,11,841,652,589,805,677,323,441,29,142,683,138,142,909,174,499,57,472,778,250,904,836,255,817,861,703,613,352,60,883,899,6,483,710,251,363,831,491,913,729,300,621,838,811,80,449,198,823,790,122,80,16,845,960,613,87,397,282,11,317,450,336,687,165,81,913,718,823,907,575,23,327,509,556,609,474,50,444,352,635,1,591,526,963,388,306,144,822,789,263,282,902,495,716,405,165,163,562,756,926,911,710,621,162,967,234,291,345,650,855,118,419,870,897,526,300,213,388,566,493,151,518,794,24,248,450,517", + "993,386,857,74,925,140,640,812,455,410,839,313,921,790,324,334,929,842,319,277,408,814,301,274,776,47,797,726,562,115,946,962,215,403,540,104,602,161,311,913,321,410,814,264,499,118,100,740,598,508,744,99,728,165,688,951,157,273,961,685,241,280,867,45,858,285,703,334,935,896,875,698,486,126,605,313,69,777,727,994,786,783,738,382,516,77,98,817,625,463,728,315,982,336,691,616,554,171,401,531,161,344,564,752,828,598,35,675,239,966,774,612,173,778,580,784,105,713,418,948,805,127,816,558,737,962,975,521,219,646,504,243,472,305,876,18,757,352,545,303,901,740,714,654,587,341,20,115,25,879,545,412,62,219,982,223,303,703,445,73,681,67,816,928,116,117,659,235,638,515,61,772,681,931,855,126,32,131,514,338,555,744,467,870,385,296,57,786,618,991,295,732,873,993,699,17,904,634,20,214,470,667,847,780,846,659,948,403,51,939,824,223,644,292,727,597,241,916,47,252,579,992,181,887,100,898,349,810,937,491,201,390,178,27,54,439,81,634,966,405,330,83,523,409,916,431,35,657,955,148,417,931,635,414,846,170,304,40,345,884,572,636,896,824,661,979,10,490,201,980,148,805,107,415,459,552,243,515,955,681,443,450,299,575,330,728,365,82,201,576,992,385,650,894,958,946,410,860,828,574,770,5,871,347,448,457,15,993,947,3,418,231,632,870,417,177,586,333,623,656,186,77,533,260,601,963,180,291,185,515,177,51,935,191,324,867,76,725,614,160,461,147,197,396,38,356,184,375,781,748,699,516,873,193,204,390,500,858,616,911,375,747,817,479,639,500,26,170,686,482,888,903,404,737,962,45,488,252,682,930,211,509,52,342,347,175,320,482,274,875,157,285,802,674,109,106,9,913,641,533,129,360,239,225,454,205,314,289,966,448,770,801,454,446,933,394,370,205,914,834,863,33,443,552,808,507,257,105,341,950,636,819,492,936,790,192,316,142,988,884,80,313,681,264,976,222,153,963,796,436,666,20,700,149,132,970,461,575,80,714,104,291,664,222,947,86,270,759,995,865,642,712,184,972,930,468,160,713,229,634,850,561,784,440,347,87,506,0,855,994,148,573,199,288,440,333,38,60,324,873,640,83,142,774,530,603,474,100,117,112,486,16,563,890,976,444,188,929,933,574,107,835,871,960,745,346,180,5,931,307,378,523,94,614,460,541,592,805,935,994,538,829,512,18,489,258,702,915,935,322,135,862,808,505,489,205,241,285,984,77,262,677,952,611,406,980,547,52,280,545,911,877,839,839,972,504,158,591,765,139,148,115,945,784,618,105,802,688,23,975,270,251,394,696,812,732,208,565,561,141,544,964,608,490,861,750,670,755,823,645,863,974,225,624,240,706,742,763,165,847,164,834,936,454,428,47,721,85,117,342,80,140,676,354,684,986,639,325,515,939,772,772,588,624,918,869,709,266,520,190,990,42,754,451,779,925,514,345,58,772,191,722,715,512,743,985,716,505,28,448,190,44,232,166,617,225,372,844,712,955,228,132,914,231,946,257,860,41,23,262,436,201,5,470,964,829,585,3,562,534,983,381,136,852,921,816,98,802,263,671,396,547,359,240,454,759,294,649,127,591,964,977,440,758,22,486,660,535,106,206,579,973,144,667,736,783,803,926,11,849,632,672,210,606,797,749,713,633,247,83,862,852,398,205,149,156,718,509,527,301,150,384,870,64,142,194,431,850,247,316,57,795,397,793,884,210,651,652,711,620,349,168,288,647,432,683,436,539,284,275,900,367,687,288,952,511,229,854,682,786,152,186,86,683,731,462,120,624,82,892,911,627,848,431,711,561,808,309,770,136,28,172,953,2,207,892,663,932,360,745,252,427,874,322,31,284,215,842,707,334,813,67,97,411,238,865,262,687,226,825,85,786,673,947,256,287,29,723,389,962,407,226,215,37,456,17,869,13,359,569,207,908,852,370,267,803,485,268,23,134,877,35,986,568,400,692,156,360,912,932,755,709,446,730,598,658,169,368,752,600,542,181,394,608,181,483,143,821,752,674,5,231,138,412,410,174,483,252,801,472,377,842,715,552,19,549,192,241,150,859,213,832,909,573,132,652,281,783,691,306,555,21,291,746,348,798,796,677,544,794,826,519,90,37,290,998,526,175,855,444,889,761,149,271,811,830,353,875,365,196,46,304,117,869,901,335,601,780,813,511,60,882,469,670,938,632,825,655,875,50,982,370,928,947,342,548,500,85,290,730", + "886,512,539,411,454,433,557,514,171,432,90,38,274,368,176,722,462,920,741,717,118,550,562,111,350,279,447,610,24,461,758,251,791,420,689,202,364,343,182,392,334,187,262,537,783,735,426,717,52,395,703,682,796,663,631,572,296,702,463,833,181,469,470,186,210,978,655,288,750,926,385,889,633,985,258,715,545,93,635,206,311,162,994,535,517,730,175,441,485,574,480,545,111,948,140,606,401,288,814,392,935,448,370,338,877,134,975,978,201,335,402,902,351,612,373,949,668,637,138,810,576,471,681,162,430,787,715,263,386,173,819,189,511,110,794,141,400,70,39,345,256,386,744,379,26,752,710,691,373,589,204,774,983,51,347,360,309,368,83,371,235,722,523,420,633,115,320,114,556,445,529,192,45,891,884,993,12,536,234,229,52,574,898,556,903,308,952,657,670,752,427,175,921,226,755,165,699,264,493,815,528,455,458,400,840,493,564,21,230,100,892,543,541,80,136,20,623,443,51,674,165,727,268,644,325,141,149,615,100,835,724,560,877,411,293,741,744,162,557,297,719,637,713,329,841,844,646,455,214,366,805,917,226,404,45,293,350,808,916,318,923,941,558,880,948,103,881,140,344,236,378,545,973,112,30,895,559,738,636,246,599,696,678,71,173,324,288,702,326,557,912,949,970,593,522,744,461,606,596,440,850,79,615,540,652,159,276,377,15,866,387,592,999,480,701,946,610,225,39,453,61,662,771,485,227,983,262,627,84,263,501,641,706,230,667,209,556,770,442,545,93,194,194,74,382,399,220,369,988,206,831,756,619,851,513,420,991,749,560,74,957,951,886,659,53,628,840,523,536,334,114,971,372,486,777,783,699,979,603,952,99,876,359,809,630,250,424,309,741,707,288,132,863,749,716,429,696,757,392,170,289,760,638,348,586,714,834,968,432,786,197,627,712,769,114,630,488,521,14,594,548,738,828,941,399,600,456,661,441,92,44,979,967,318,763,710,619,89,571,773,36,399,100,368,213,772,356,672,82,930,894,687,841,512,742,13,448,122,641,430,274,426,165,399,102,812,901,301,265,762,93,980,46,935,993,445,897,754,466,843,63,702,647,356,428,673,705,855,0,807,952,633,333,999,974,44,916,499,927,540,590,467,467,371,862,407,526,670,423,554,736,199,586,337,705,408,633,550,548,179,402,680,158,640,967,506,139,258,641,557,63,466,389,222,164,544,14,275,382,180,867,191,217,839,615,856,102,970,931,798,961,644,149,326,191,453,140,716,701,456,144,239,628,265,211,781,776,178,254,519,522,550,536,420,671,801,564,63,415,495,284,255,987,116,531,966,524,278,521,286,533,553,490,988,294,111,644,551,805,155,230,54,525,116,507,444,626,20,300,800,933,983,206,930,400,914,332,740,424,188,341,842,221,810,256,348,713,304,306,958,731,548,916,22,361,311,183,14,620,388,526,626,676,997,961,299,121,71,524,271,133,486,439,479,370,76,988,730,217,704,957,122,477,210,50,407,704,231,615,574,167,43,36,807,811,549,203,591,802,439,52,373,574,172,849,218,69,317,1,64,370,965,205,38,788,251,515,18,168,456,959,690,447,742,768,839,464,296,86,374,568,946,869,916,447,754,397,809,481,73,376,361,647,477,574,130,723,674,699,825,810,283,814,126,986,36,482,93,577,632,401,411,422,905,282,384,97,313,812,98,911,286,616,696,209,669,505,705,422,70,477,992,574,28,779,558,236,796,621,981,174,52,575,829,340,30,815,149,955,960,432,243,806,922,467,405,282,462,265,74,8,220,894,150,405,960,376,649,127,770,912,237,642,854,645,851,903,222,48,815,529,316,292,321,537,358,997,441,365,573,277,610,40,831,632,709,447,653,26,861,813,972,530,795,306,883,581,137,632,260,471,407,258,543,321,458,832,180,931,387,283,620,496,923,174,212,405,241,586,163,568,284,282,107,235,88,440,900,882,417,500,923,993,494,196,477,229,661,24,33,646,981,478,987,365,880,661,356,470,483,772,678,330,923,501,317,399,980,835,626,982,18,918,362,589,944,790,44,541,393,951,242,390,852,395,648,401,33,549,187,989,495,556,716,297,907,397,527,737,783,845,590,20,426,694,549,292,661,629,59,810,227,159,585,9,21,796,324,253,628,521,685,110,974,314,372,146,575,632,496,401,822,287,709,150,322,801,668,365,793,262,76,155,222,49,792,869,487,818,759,721,655,696,162,715,690,492,797,166,891,986,117,503,945,813,198,523,329,66,647", + "130,521,210,459,333,396,566,256,23,339,670,963,280,859,738,565,104,200,516,845,931,72,898,661,165,216,827,520,386,780,613,452,151,204,87,946,564,474,896,608,55,28,266,986,101,874,482,177,535,940,802,833,450,538,427,233,109,164,303,44,874,181,179,154,78,550,597,483,785,410,664,418,651,751,203,835,809,74,871,476,908,461,645,555,681,750,252,291,768,650,964,169,437,454,890,829,432,893,596,567,629,978,99,303,475,411,278,816,515,64,648,412,298,994,197,655,121,793,381,798,188,773,44,729,848,717,700,85,393,238,202,437,664,889,649,298,152,485,717,104,949,172,379,991,336,737,317,279,463,993,236,203,418,265,89,862,438,725,272,418,17,150,872,408,499,588,985,810,393,253,390,531,884,13,799,596,866,515,971,160,955,255,141,956,845,755,122,556,878,701,92,334,617,364,665,421,861,421,28,221,663,818,263,93,336,354,111,500,150,109,588,158,361,951,968,964,900,980,141,242,944,437,224,97,184,305,423,589,767,713,195,227,648,40,420,700,519,30,945,464,294,95,749,307,246,93,621,535,949,977,433,960,828,986,672,217,376,379,561,20,284,878,117,341,800,622,929,849,309,895,291,468,704,201,331,948,403,540,386,503,615,21,919,977,823,470,452,523,671,200,411,761,432,921,441,527,981,845,735,644,784,549,35,31,697,428,211,849,522,664,504,703,212,251,128,130,393,896,605,108,861,22,608,882,55,876,447,641,395,449,250,323,834,763,67,267,141,648,342,411,344,433,236,946,823,962,520,66,38,992,341,432,439,453,564,571,416,496,416,174,332,648,876,402,543,775,549,268,707,974,561,938,403,6,618,873,300,868,233,89,955,994,157,338,126,597,791,648,953,202,540,598,491,347,495,499,98,97,887,913,740,744,169,67,52,192,742,516,386,636,420,993,376,573,589,503,900,606,273,981,601,484,907,35,845,752,869,748,511,354,917,830,584,665,969,698,61,369,898,199,233,699,124,77,681,848,817,671,688,2,227,903,6,994,51,131,65,25,450,747,547,676,154,566,270,267,911,529,285,539,958,505,513,571,924,884,805,185,125,217,751,316,49,966,598,282,890,994,807,0,761,662,969,35,332,598,50,674,910,873,904,21,287,656,143,923,89,244,326,84,127,55,968,299,285,304,34,662,491,934,978,790,361,650,270,822,926,97,232,182,618,988,619,107,761,971,299,942,863,273,773,525,862,591,894,12,435,675,117,396,528,970,970,142,230,771,510,623,347,171,34,820,921,639,716,832,16,88,356,212,190,159,742,901,232,966,717,888,820,227,884,507,708,322,216,812,672,204,122,773,577,411,135,145,366,986,783,618,365,292,381,931,585,605,342,91,539,213,8,195,855,916,397,723,955,610,306,479,869,265,192,116,626,494,504,104,213,760,423,452,665,236,340,819,780,609,741,704,937,207,603,400,24,31,646,971,81,887,573,157,329,296,101,173,60,243,913,461,851,484,320,454,24,448,872,465,389,847,208,628,257,823,634,957,511,94,689,379,758,96,161,597,735,444,739,824,739,474,951,53,122,690,95,973,244,506,417,294,642,196,876,190,290,324,326,163,785,709,966,757,171,197,371,254,593,690,428,276,701,886,476,760,964,684,212,612,426,145,387,952,821,17,634,90,633,815,263,826,19,169,25,954,919,120,967,89,449,27,291,457,912,366,139,662,334,785,235,706,214,192,965,82,109,885,672,678,220,359,505,818,10,290,311,560,91,592,652,904,591,113,798,751,495,910,995,137,726,693,311,1000,543,680,484,171,671,203,2,60,72,617,475,588,954,820,3,614,964,80,468,74,286,325,436,867,640,137,39,263,904,173,447,810,105,886,653,782,196,819,428,682,944,755,557,812,932,392,847,155,729,1,292,846,734,300,957,342,498,919,691,237,408,786,438,644,903,571,675,72,690,573,438,186,978,504,546,314,937,59,37,347,249,569,202,204,266,979,347,295,887,124,307,776,539,880,61,211,956,354,273,131,823,850,547,443,130,678,288,406,39,93,304,564,927,71,657,866,196,888,213,461,839,266,660,658,793,815,659,991,477,612,969,688,967,544,88,71,538,755,559,738,621,735,95,918,914,470,868,922,24,764,677,121,281,909,177,342,933,384,919,709,546,918,151,709,111,143,65,604,597,129,97,193,429,400,964,930,710,475,200,855,553,840,363,735,800,22,361,778,480,598,249,546,940,779,581,554,886,783,604,272,952,513,121,887,719,417,972,486,589,100", + "871,589,559,89,458,516,9,41,770,627,442,361,796,246,720,18,230,735,940,197,894,76,669,778,393,493,681,78,911,548,303,910,428,795,933,168,26,373,523,320,247,156,33,249,809,261,383,430,251,197,739,729,968,972,171,35,230,676,946,738,855,824,705,326,904,723,930,745,420,873,708,475,593,330,341,765,829,872,858,162,497,629,620,500,508,875,224,714,806,503,408,346,17,842,693,525,720,615,168,283,740,490,439,961,790,80,425,517,260,477,642,483,536,455,119,33,641,547,779,42,48,531,335,69,486,669,268,671,12,282,376,27,671,854,346,847,120,398,96,19,804,772,964,844,214,730,487,971,100,382,286,499,937,353,613,686,424,179,998,272,168,852,359,653,272,220,461,666,622,714,457,76,515,384,634,77,220,862,232,980,937,766,347,725,360,321,560,148,135,193,248,814,153,430,671,641,917,217,177,459,734,626,479,649,225,73,361,763,505,463,550,51,299,638,717,24,114,415,164,799,362,35,809,161,578,503,957,349,604,521,497,401,449,872,373,718,140,577,515,292,741,622,516,450,129,527,482,999,393,885,608,610,401,865,240,979,854,280,160,902,308,555,906,662,135,365,354,841,315,516,338,46,238,389,922,657,31,33,128,863,157,156,136,826,936,254,868,117,956,108,351,873,275,574,510,146,840,943,812,509,31,852,827,20,106,891,241,382,30,421,963,996,414,772,739,525,121,753,398,980,386,155,575,857,369,284,54,957,465,724,467,899,724,698,947,500,658,410,926,691,336,563,181,330,725,299,255,841,645,737,101,792,999,208,608,196,592,732,587,725,402,173,239,366,775,831,652,148,388,337,765,820,564,807,741,464,871,445,414,961,339,835,453,620,375,596,452,22,177,887,390,474,866,224,510,663,797,441,326,675,512,407,613,793,272,691,701,509,857,47,258,883,748,395,309,95,301,451,365,366,697,296,510,294,23,9,279,676,997,263,471,803,143,741,242,674,442,483,946,500,588,317,494,941,212,777,770,798,980,508,417,380,415,317,794,339,858,993,495,801,669,271,961,221,224,18,90,635,58,277,146,334,254,732,717,847,651,941,634,798,696,53,687,728,728,287,534,148,952,761,0,515,999,694,134,280,882,746,15,294,56,448,451,650,616,6,391,524,456,124,473,963,348,686,216,592,901,178,715,890,354,46,691,173,840,798,512,512,898,305,319,553,845,28,138,668,16,361,31,424,644,825,565,597,485,147,927,293,551,660,911,154,105,584,636,299,51,420,559,411,607,577,414,271,653,635,247,941,56,349,443,727,920,787,559,424,460,164,972,835,220,19,702,533,540,84,798,233,521,562,310,481,491,428,614,345,753,474,554,993,529,917,167,414,603,585,123,873,175,647,899,203,757,840,284,124,184,599,14,501,896,841,903,831,537,343,86,424,655,233,837,336,961,74,121,787,87,397,484,589,53,630,667,994,32,822,433,268,67,961,431,599,285,351,385,136,513,767,97,171,717,826,479,785,450,712,838,334,603,963,465,27,384,518,403,652,901,675,869,520,816,985,776,589,881,272,396,853,571,319,161,602,251,494,708,618,903,689,216,162,816,648,14,632,261,244,908,179,179,548,589,71,921,919,986,406,929,243,862,201,452,34,219,440,359,20,672,144,839,131,659,469,987,257,5,246,236,780,652,523,411,556,91,664,227,376,321,476,355,251,16,686,684,372,898,110,64,561,668,978,338,592,241,665,903,756,199,575,599,557,50,544,548,421,387,669,105,635,949,970,834,70,614,324,791,9,480,790,168,314,550,969,779,791,972,669,30,723,829,348,908,98,277,580,602,927,509,537,452,149,397,424,843,776,879,613,448,669,567,941,734,591,11,630,828,205,906,624,937,582,985,291,979,249,717,383,480,232,824,796,960,746,895,599,534,902,469,158,312,236,349,161,707,818,339,361,689,527,435,917,638,128,344,485,394,327,173,368,227,504,841,128,149,72,859,494,66,285,237,924,263,544,659,876,783,213,26,679,328,20,249,214,191,845,426,118,112,189,304,49,515,268,237,520,135,693,396,402,402,102,1000,713,404,885,89,178,277,411,225,816,481,407,473,403,588,889,212,720,361,789,917,438,500,971,941,934,964,396,159,132,708,139,478,62,210,807,262,92,788,597,400,38,544,330,632,581,866,850,542,236,955,603,504,22,135,849,900,738,209,464,491,937,301,852,162,1000,757,161,104,558,561,314,148,477,624,171,814,679,978,970,500,992,844,72,504,537,19,601,986,889", + "752,218,670,577,739,367,235,821,940,935,842,431,541,106,472,895,358,751,520,513,293,829,697,222,431,222,707,530,550,268,879,986,919,296,764,940,84,807,460,978,134,573,667,947,497,643,579,624,748,678,60,113,814,830,403,874,641,940,492,728,475,323,173,206,757,636,259,29,986,962,604,249,392,853,882,397,887,207,239,965,923,117,885,431,358,605,852,594,832,719,215,780,587,372,376,781,19,253,523,977,806,970,724,658,871,768,35,412,40,307,36,257,2,548,864,173,255,679,309,325,188,512,640,66,528,308,310,458,196,331,285,141,127,771,437,317,264,562,362,19,709,110,944,999,678,291,613,767,619,454,537,640,82,462,499,838,128,282,515,426,725,123,910,501,386,661,214,952,674,722,186,406,7,470,820,713,39,495,292,184,244,598,30,675,228,656,757,124,978,191,907,639,845,136,915,896,803,207,94,604,562,891,283,683,250,48,175,56,447,542,146,413,592,776,998,940,594,794,175,472,943,59,999,925,705,218,990,313,577,467,772,29,558,209,61,643,682,70,798,375,514,261,460,951,541,827,891,520,588,424,827,55,691,161,101,592,184,841,172,50,293,904,666,640,35,516,63,631,26,337,80,917,514,225,654,976,798,126,675,140,240,394,590,970,213,700,265,997,563,49,334,7,155,876,115,954,33,574,619,814,354,385,131,588,388,790,542,800,738,373,315,899,306,53,181,194,737,788,651,672,803,198,442,594,490,21,769,265,67,309,892,688,412,943,754,185,626,374,770,21,215,507,577,378,400,332,915,686,733,205,895,750,961,691,508,140,216,523,415,544,223,618,173,621,857,739,188,175,531,404,765,383,625,285,61,707,325,320,828,345,551,920,955,743,627,592,290,11,240,309,558,558,420,557,420,137,916,855,79,684,825,2,240,460,652,148,160,207,277,31,799,132,959,807,697,249,537,162,213,617,156,978,814,92,895,424,709,617,948,763,399,937,583,328,605,691,342,447,403,298,699,295,389,166,353,878,25,683,720,64,619,83,119,641,49,944,403,108,959,195,455,227,402,740,722,799,82,162,331,236,727,429,460,205,696,99,319,536,472,930,732,393,564,319,657,505,482,573,633,662,515,0,152,26,905,884,949,669,486,273,47,585,529,59,66,743,98,589,698,514,125,882,130,686,536,364,320,771,947,694,162,975,578,837,727,872,325,910,730,344,749,210,984,938,908,307,693,177,339,754,242,459,339,443,812,446,452,51,468,937,151,712,224,720,184,14,263,797,815,482,853,581,271,646,460,120,382,484,440,49,561,93,337,764,589,19,347,805,732,10,46,756,691,328,31,937,770,253,672,233,101,488,746,661,893,953,884,616,983,125,726,184,322,491,57,306,699,221,373,761,323,677,625,607,773,504,624,763,498,992,399,787,270,293,772,133,581,810,307,493,129,940,363,473,222,548,462,323,620,861,223,940,551,696,278,459,198,801,266,423,476,67,25,20,487,44,502,934,873,191,886,941,292,657,215,133,196,172,795,102,728,866,677,429,722,616,886,82,538,155,31,195,208,418,330,666,688,327,764,397,322,567,428,677,810,66,647,199,433,856,968,148,131,723,65,94,894,803,591,562,251,202,659,401,456,426,333,510,73,792,809,12,46,769,99,238,416,616,817,604,454,62,13,563,733,883,874,563,20,477,345,383,594,294,142,930,149,496,171,41,902,506,694,656,116,742,47,250,471,877,733,169,699,493,149,539,274,655,76,765,589,298,280,556,711,820,412,870,486,833,504,546,838,589,400,716,128,405,610,483,967,408,997,877,560,608,769,774,219,410,995,21,173,707,569,264,878,960,172,604,601,416,279,549,949,791,972,592,916,590,721,258,953,164,62,868,878,509,112,67,722,636,201,635,952,432,692,570,223,163,695,307,615,448,379,387,728,553,301,336,168,781,926,197,549,696,179,88,260,440,543,591,902,85,799,708,520,249,118,84,425,617,162,81,547,822,253,221,907,176,657,103,326,493,431,627,899,331,311,916,54,778,636,422,533,829,592,855,721,12,815,693,822,298,636,739,874,180,851,18,12,403,880,799,392,632,643,362,522,85,553,92,313,319,374,769,195,778,783,810,608,6,919,505,562,966,581,276,246,893,118,352,124,113,315,937,657,408,453,432,917,209,717,686,667,37,579,681,61,792,502,529,788,618,202,675,652,319,100,184,732,616,108,717,386,359,503,313,569,502,778,807,552,364,222,777,638,396,184,511,765,917,479,241,863,619,165,30,99,114", + "217,481,477,969,15,764,410,398,972,499,65,537,402,15,523,851,485,438,758,892,65,69,560,674,915,238,923,684,299,83,753,451,539,447,262,466,576,225,422,695,618,746,89,947,703,629,803,494,71,443,695,346,538,514,201,472,371,191,716,83,97,729,874,214,943,692,755,949,838,864,659,665,169,399,31,681,648,841,734,568,257,616,169,361,105,568,627,972,894,514,178,45,165,332,886,227,938,588,898,276,125,296,954,726,697,90,175,368,531,206,531,982,648,549,484,176,405,420,216,621,928,546,919,516,941,933,80,949,542,740,136,763,209,516,496,794,525,714,987,831,989,605,696,364,915,99,296,759,826,240,307,862,521,940,74,725,56,620,402,655,268,546,471,697,985,242,379,713,552,180,34,781,471,751,29,805,314,294,302,41,405,226,611,307,14,225,649,157,920,340,46,458,328,981,337,891,717,257,741,417,422,131,100,985,182,650,955,97,59,512,228,150,927,114,890,476,592,866,281,187,233,876,31,585,839,481,971,63,866,450,418,661,801,519,392,786,674,167,588,2,97,328,538,161,506,939,429,614,80,954,955,34,81,209,171,161,911,656,986,73,952,717,273,97,787,683,571,233,310,121,478,881,243,33,237,677,628,804,120,921,666,641,722,157,528,139,801,632,647,384,532,332,484,96,899,185,423,511,704,61,592,964,618,84,693,252,171,833,470,490,815,100,308,803,965,103,726,923,664,166,189,692,598,887,886,321,659,282,191,601,314,190,384,425,74,125,672,796,476,414,974,876,158,152,989,789,348,975,18,43,642,927,431,945,230,981,530,79,233,308,776,391,482,153,927,201,757,734,41,698,677,825,40,683,651,13,898,232,523,469,312,293,493,888,803,942,910,344,949,997,582,202,522,649,32,368,717,877,716,255,364,396,484,304,704,652,218,459,212,20,61,554,620,749,80,549,375,3,114,619,854,864,910,134,922,371,254,698,978,634,346,734,387,460,247,442,560,476,600,412,897,362,151,569,783,100,869,583,150,369,429,47,812,628,995,851,922,675,728,979,201,83,652,100,954,466,252,963,908,438,638,787,609,686,261,372,115,384,56,616,87,643,8,762,950,507,796,199,333,969,999,152,0,398,432,353,692,948,729,813,649,679,1,615,25,946,173,833,6,186,175,948,735,360,952,507,247,18,539,885,888,760,924,895,783,859,119,143,260,471,262,462,900,31,390,910,619,640,440,185,631,862,413,159,985,348,773,236,590,34,882,738,271,729,549,379,499,658,146,289,198,19,367,675,279,848,299,218,930,412,928,559,12,967,834,868,790,342,156,405,601,265,746,474,967,370,111,810,584,684,583,950,274,772,498,936,25,659,474,706,473,678,691,588,768,84,854,989,93,771,102,636,858,525,722,511,813,944,501,692,388,304,727,199,360,724,209,875,413,175,419,782,358,641,458,177,376,22,461,593,500,191,872,629,841,544,567,948,979,66,730,116,795,393,16,920,265,55,350,859,441,358,33,931,372,222,957,179,725,242,242,356,898,550,256,878,821,619,372,263,781,314,381,916,280,588,592,55,610,460,989,109,395,974,104,106,8,63,86,671,836,277,549,261,655,503,536,529,281,873,138,855,573,138,720,423,121,200,606,317,804,53,43,646,565,233,141,117,898,46,341,823,225,800,395,808,748,268,870,251,522,647,104,536,42,467,971,595,425,382,767,699,564,310,755,34,965,976,764,989,350,701,327,783,344,771,197,768,154,824,68,86,535,466,81,94,154,844,612,664,997,257,46,23,978,718,414,507,468,312,461,546,721,870,10,899,363,354,344,212,36,337,64,120,220,883,386,958,24,263,931,501,311,79,355,670,869,53,55,481,759,806,137,987,836,651,958,813,162,361,309,459,416,277,910,988,211,481,585,247,878,900,160,32,722,317,381,547,345,726,414,633,390,62,623,385,510,442,642,698,839,266,650,180,239,633,296,376,867,260,313,72,587,968,157,701,280,345,75,808,294,956,220,110,45,207,329,7,854,526,597,547,183,11,276,145,359,594,937,572,373,915,134,389,977,928,317,919,874,201,923,992,744,42,870,836,775,826,124,14,646,800,420,397,141,774,682,291,484,993,721,91,577,717,309,167,4,554,763,910,767,21,310,922,502,306,186,994,462,164,499,545,590,334,809,384,682,586,352,108,929,303,873,97,224,592,303,864,490,314,381,235,189,958,21,671,37,614,316,650,610,367,884,674,792,720,878,675,795,647,681,973,569,279,717,917,22,49,180,922", + "896,288,766,74,856,935,959,717,368,73,520,418,456,694,221,479,190,435,257,527,706,311,28,328,840,140,745,515,547,458,437,919,207,948,436,648,301,685,874,44,180,346,934,17,437,478,147,611,910,755,421,499,980,363,101,568,358,690,681,930,246,405,199,668,278,188,478,103,572,613,65,232,487,496,658,512,870,44,754,527,913,563,21,939,475,173,367,293,781,767,309,391,645,45,778,49,350,538,725,758,136,260,746,665,850,203,26,259,466,362,461,357,921,593,579,694,330,478,429,520,861,587,579,974,739,451,209,945,655,310,880,988,709,232,861,3,551,760,455,954,366,590,517,826,260,350,62,910,103,987,941,585,124,416,501,364,855,516,389,503,240,676,148,657,975,114,459,13,432,153,659,404,14,223,333,150,479,684,301,414,19,926,386,549,262,914,342,585,802,208,621,508,691,493,747,408,805,696,860,676,151,203,346,124,53,784,870,656,682,576,91,397,6,296,93,824,617,225,560,100,71,766,989,567,389,259,715,198,628,249,33,540,783,756,357,179,46,65,923,922,81,556,824,572,11,41,882,15,223,498,616,879,976,310,721,381,306,6,682,626,879,738,524,535,275,796,11,553,573,760,136,352,32,471,800,346,37,84,68,834,926,681,208,564,839,861,469,444,59,248,349,723,361,992,366,102,492,963,2,112,401,727,223,20,36,389,895,595,993,517,152,621,777,745,561,803,981,997,893,183,3,199,108,339,490,322,355,676,837,860,669,309,840,667,223,585,826,391,699,130,603,212,138,357,462,527,745,513,766,919,612,844,216,649,468,789,871,767,480,214,947,339,372,177,480,585,697,543,422,844,759,720,10,919,584,367,440,22,490,104,136,758,738,82,465,259,931,880,167,29,181,228,188,889,883,97,681,914,643,841,219,83,636,309,38,706,850,1,414,95,840,460,715,957,402,939,549,280,370,302,29,172,65,806,817,45,14,498,668,410,365,375,979,277,219,125,659,176,994,580,80,928,959,607,8,222,58,312,584,520,71,16,184,223,729,44,908,709,761,505,257,77,870,505,499,942,553,840,137,274,874,7,82,937,716,848,899,907,119,863,839,389,301,242,224,440,254,288,999,35,694,26,398,0,528,534,101,683,861,371,811,467,992,245,846,654,817,789,774,815,269,721,860,71,733,902,508,207,88,150,745,337,796,105,623,483,938,13,383,716,564,805,154,138,159,381,534,476,339,927,976,76,466,672,420,693,231,993,246,214,465,380,300,148,579,426,336,951,983,262,603,260,239,486,242,106,961,679,854,969,374,544,623,553,686,783,692,572,47,152,717,717,94,356,219,818,415,917,424,64,885,649,712,535,325,995,316,23,502,334,568,597,773,342,624,165,362,205,877,896,186,865,832,34,194,810,608,844,234,472,423,849,711,962,908,484,182,479,355,894,851,243,594,398,71,111,484,320,683,916,895,234,923,580,97,673,807,887,134,355,349,261,751,646,995,914,490,526,775,819,326,930,193,556,21,650,158,558,525,1,429,253,331,153,389,634,102,201,314,12,569,595,163,483,207,792,848,67,303,685,231,404,482,995,693,19,560,366,11,412,595,818,429,233,743,318,809,512,814,39,316,655,810,158,342,712,935,559,192,91,424,576,984,718,815,170,99,967,846,445,213,653,828,968,414,712,627,721,60,205,715,236,207,911,74,837,27,320,683,199,800,980,33,860,848,944,863,512,545,860,51,226,795,388,452,219,885,31,857,71,880,374,995,584,72,203,392,706,823,445,820,938,636,724,3,274,834,845,837,894,816,901,122,139,774,999,73,146,287,748,887,227,78,397,216,796,884,46,248,819,639,121,816,3,781,664,818,4,980,194,27,896,191,952,889,211,432,566,212,264,597,631,216,938,718,833,410,645,203,950,383,573,582,368,64,287,909,994,189,596,450,784,405,652,244,849,907,36,555,600,640,464,87,590,870,523,371,703,143,555,48,927,935,190,913,156,741,270,332,563,5,786,537,491,397,538,439,926,232,528,45,161,777,957,280,608,463,7,658,837,937,439,257,409,648,133,784,954,883,811,280,626,48,128,535,945,391,362,881,790,816,5,826,913,545,9,691,446,569,55,331,433,161,262,845,424,589,964,144,922,910,530,925,640,563,697,12,261,861,815,70,608,203,17,961,493,110,50,410,278,700,618,80,413,140,541,428,383,869,485,834,254,573,171,344,556,797,921,917,826,320,135,563,989,356,14,2,253,451,880,781,924,788,513,661,525,961,811,536,473", + "446,995,400,672,35,892,527,885,53,507,320,275,110,233,609,225,164,788,316,20,99,31,841,499,351,447,897,761,189,468,631,429,910,562,585,199,786,310,523,130,603,42,864,634,539,483,310,494,669,363,561,577,506,390,406,987,800,37,276,28,816,494,692,354,488,617,829,550,511,70,138,194,428,25,689,657,882,723,443,717,993,122,942,838,140,463,963,516,354,859,631,521,668,163,329,695,200,457,350,70,513,568,593,564,912,175,762,270,956,284,161,408,790,518,155,845,319,754,490,240,973,699,944,362,726,212,990,914,503,22,145,420,313,739,541,846,694,742,877,248,420,754,534,644,950,732,52,894,714,924,156,228,654,378,720,703,861,8,18,915,281,539,68,687,506,153,628,752,781,32,989,824,810,431,358,256,621,914,260,264,398,244,527,334,450,376,387,278,281,574,64,748,489,553,861,418,558,38,722,861,85,844,754,846,586,794,564,99,340,966,965,954,175,184,900,305,815,76,427,758,242,132,477,224,34,923,994,509,813,727,284,867,575,204,883,739,907,989,694,31,353,210,297,887,505,846,50,954,289,795,569,501,922,532,60,542,408,709,322,264,87,442,925,801,604,475,236,920,316,421,211,633,634,266,226,183,694,973,194,959,818,228,734,584,888,697,660,668,960,555,113,944,239,111,73,149,428,383,59,147,513,358,672,284,357,11,520,235,795,149,534,427,437,893,620,648,871,50,319,247,379,746,716,801,266,486,668,814,332,341,380,122,636,212,296,67,791,45,468,369,276,724,76,840,746,627,967,745,657,8,327,702,865,970,581,177,826,423,525,763,908,916,668,342,139,564,102,428,811,116,573,856,876,546,610,729,557,596,499,332,654,603,602,407,898,522,572,381,62,815,306,354,939,713,799,240,87,940,690,826,817,87,643,622,611,250,365,609,28,747,982,318,136,559,903,129,539,722,779,85,224,189,835,545,888,219,631,599,543,938,150,285,79,576,753,649,269,1,985,340,842,827,95,559,942,805,628,994,308,176,460,937,978,156,32,962,184,111,415,30,478,580,553,446,876,579,366,868,304,940,760,139,70,797,229,796,288,71,6,230,866,246,995,815,576,363,111,440,974,332,134,905,432,528,0,471,930,18,631,955,144,507,121,277,884,450,516,370,834,693,856,237,676,241,730,903,264,755,610,697,974,523,798,172,992,63,608,262,615,187,424,173,512,960,779,746,890,434,438,602,984,923,950,618,178,948,724,73,358,584,283,671,46,78,637,234,381,848,885,627,50,10,17,795,997,595,716,419,832,562,927,71,635,912,615,506,246,439,855,782,443,843,504,99,463,852,37,323,221,28,92,878,396,424,576,245,618,827,296,447,852,914,468,576,983,238,627,458,116,381,381,344,362,168,793,933,211,771,707,241,945,331,427,235,46,500,837,648,89,903,656,134,343,965,743,888,961,525,800,598,806,936,254,558,129,406,164,148,975,571,675,663,860,743,119,139,615,616,388,121,674,89,522,432,675,406,128,576,442,284,566,590,195,50,794,725,93,464,710,129,424,393,10,394,125,62,465,644,444,765,723,903,113,117,636,998,9,827,542,272,898,173,180,9,156,961,876,501,493,143,393,503,275,910,206,842,717,476,18,743,215,972,617,738,122,731,873,903,754,648,439,537,676,327,617,812,409,326,629,411,922,94,528,734,201,28,794,767,677,774,165,381,230,149,782,898,644,611,255,376,258,366,132,926,288,706,654,472,750,671,736,110,950,520,618,130,928,9,466,808,704,289,694,693,128,136,655,225,547,139,19,6,532,557,582,341,468,955,767,383,661,97,71,669,595,258,891,796,790,209,771,538,501,767,294,960,521,657,292,768,103,526,940,409,232,495,606,914,143,119,153,620,986,126,742,349,45,265,399,746,868,766,841,81,69,471,46,861,294,937,380,635,785,162,416,74,737,903,24,706,254,148,143,740,417,234,677,225,609,357,856,46,863,696,409,362,173,358,558,895,970,302,359,996,404,991,663,787,191,559,641,564,709,32,480,335,742,296,289,524,101,242,523,572,257,297,326,861,501,893,738,125,887,798,555,141,816,219,18,121,864,760,546,895,939,68,100,190,213,511,549,4,243,691,363,150,162,548,937,881,225,760,583,625,416,871,121,275,921,949,592,604,455,550,904,57,486,600,673,46,519,508,392,831,32,548,448,948,791,952,445,449,993,689,764,353,618,681,204,780,706,946,128,461,793,164,951,282,417,511,924,210,919,357,318,353,711,356,482,140", + "66,791,17,930,467,78,370,940,785,421,513,295,256,331,45,102,810,290,813,410,577,66,790,811,424,447,663,378,499,349,702,387,184,238,30,6,361,117,139,283,503,343,29,974,554,32,193,771,586,672,684,488,526,34,487,94,569,265,383,550,99,667,380,732,386,949,373,637,410,406,920,494,729,929,98,275,854,145,21,104,242,310,723,230,720,62,978,919,277,973,977,902,86,265,768,245,166,139,410,672,878,733,170,807,445,414,53,125,369,938,451,16,186,457,52,306,158,714,111,541,579,561,765,937,864,764,783,219,84,453,703,171,833,776,350,892,521,663,753,61,413,491,910,215,24,664,271,582,424,695,923,636,677,381,614,100,529,268,931,880,643,791,501,202,371,939,780,131,693,198,290,849,319,33,547,341,203,524,425,673,253,705,988,877,332,430,68,480,552,886,798,849,39,938,284,3,745,90,147,706,479,728,792,299,216,155,902,843,895,248,560,820,222,615,69,726,929,404,682,631,768,925,865,252,438,772,346,34,555,724,121,188,497,714,464,369,995,342,983,742,167,775,367,712,993,468,102,826,558,32,823,409,679,126,524,789,576,990,326,120,352,781,924,818,575,306,511,529,876,675,823,133,26,399,517,115,680,91,350,601,652,740,619,318,417,747,398,706,608,204,122,46,846,294,447,980,261,27,323,280,195,148,109,219,912,278,430,908,194,689,849,760,393,297,61,991,662,256,742,270,226,810,52,979,756,412,71,445,622,683,320,238,377,562,779,260,457,590,54,526,551,282,37,302,372,790,26,767,67,216,231,421,326,508,205,177,277,419,928,948,246,852,796,990,4,287,73,259,123,995,473,322,126,769,287,84,494,250,249,556,706,361,445,880,405,5,327,281,878,231,925,645,468,500,913,671,591,352,387,64,221,113,698,845,698,650,389,94,109,816,942,346,780,780,360,135,560,400,680,855,310,625,10,647,930,860,678,674,186,450,890,971,370,452,767,313,157,643,310,759,89,116,150,257,431,593,299,546,854,421,50,977,164,125,725,251,648,955,52,726,286,111,404,403,225,530,155,104,45,459,888,476,293,273,13,122,642,923,883,811,34,448,309,962,631,718,644,333,44,598,280,884,353,534,471,0,303,518,747,519,415,859,190,398,374,738,662,388,954,544,424,860,530,393,553,87,708,111,889,241,493,231,705,896,85,645,676,436,859,766,216,574,25,489,561,650,644,313,103,395,166,978,108,241,13,724,183,902,135,455,689,522,117,700,860,836,858,486,812,278,216,835,729,71,33,23,257,952,182,274,241,967,94,320,722,221,989,440,814,195,712,229,720,738,725,544,26,613,758,228,591,287,727,735,515,70,427,955,880,604,349,788,843,315,759,464,88,373,369,906,152,506,448,740,118,561,380,829,243,44,127,410,212,204,170,55,409,631,726,785,676,47,738,536,599,796,832,776,575,610,440,222,143,652,609,845,246,397,257,850,948,864,830,792,924,321,859,611,114,640,478,596,30,780,712,369,534,571,432,70,363,762,201,537,962,4,342,246,926,306,410,195,463,351,141,990,444,715,976,965,200,652,495,682,174,570,447,130,467,993,649,943,607,972,652,515,532,818,653,439,489,300,674,214,770,461,451,763,688,329,873,410,830,846,744,802,943,527,802,74,922,17,920,178,582,905,721,589,709,912,549,624,220,380,11,328,27,54,705,920,861,963,318,990,62,173,355,460,81,500,412,602,160,308,532,70,339,819,549,359,199,914,347,171,932,385,935,492,192,937,942,638,351,70,361,708,232,713,84,633,238,27,771,47,844,987,4,322,549,697,489,919,181,356,731,254,268,465,266,596,189,85,758,396,925,87,362,540,385,946,204,401,853,913,409,580,455,525,474,794,471,972,394,699,360,591,388,657,499,547,107,229,193,527,215,922,974,989,781,560,74,913,929,921,316,877,241,116,653,29,180,353,904,288,772,448,555,524,148,601,692,590,243,239,330,253,179,88,401,311,656,159,183,707,430,209,112,280,610,768,835,951,684,329,257,990,177,743,29,433,439,27,211,135,907,516,8,182,955,332,732,930,710,436,624,696,618,562,498,3,718,32,396,909,488,429,227,567,59,485,42,627,119,309,963,346,501,408,207,55,780,515,406,833,388,430,190,939,330,364,254,229,512,26,784,601,749,720,46,589,359,468,606,940,836,327,396,90,773,574,213,462,489,97,875,764,446,454,978,789,51,422,23,615,684,277,697,567,721,429,784,897,987,737,43,477,667,617,888,145", + "223,791,869,663,465,8,646,801,928,693,663,836,983,590,958,368,583,714,569,938,355,298,909,618,951,995,645,859,412,591,779,151,366,121,37,878,68,701,19,524,960,800,870,225,605,2,881,651,401,740,276,402,337,324,751,26,909,362,99,622,407,451,575,468,930,742,294,552,658,546,182,646,78,274,371,62,169,45,88,316,977,627,58,545,327,431,732,137,277,214,208,442,507,706,6,206,184,523,293,543,758,88,400,875,522,11,977,696,52,813,982,884,639,784,614,463,143,139,115,246,727,195,89,8,271,110,598,662,657,826,518,438,355,188,77,119,516,806,225,979,616,701,426,154,925,834,18,903,420,735,397,938,713,931,258,249,315,35,635,3,502,366,596,580,763,163,849,64,963,639,123,59,95,833,784,36,754,942,482,866,341,704,575,470,945,687,84,716,622,3,819,100,488,313,254,731,957,897,160,630,997,710,650,439,471,524,725,943,686,324,451,377,814,607,185,62,914,162,336,759,677,655,348,417,888,244,314,310,963,754,858,65,729,439,523,70,307,514,236,830,594,253,90,843,416,822,318,488,415,805,690,852,260,429,582,610,748,782,951,565,761,210,890,833,640,238,763,923,156,575,935,196,447,140,62,549,622,937,97,470,855,52,279,960,222,205,823,726,947,216,639,58,295,20,219,792,249,772,626,804,879,519,902,326,821,703,949,437,869,708,877,892,200,50,905,671,744,560,878,104,535,790,407,221,559,15,648,657,152,282,585,611,994,982,305,865,597,28,445,484,946,425,624,570,334,399,252,304,903,580,22,460,24,225,257,419,39,814,533,703,765,812,257,6,17,824,44,175,481,436,413,801,597,904,622,405,10,133,132,548,725,841,117,525,352,798,785,891,377,588,390,301,193,953,157,801,753,605,852,186,646,185,706,984,263,361,705,627,273,253,432,524,607,906,754,592,162,440,100,280,20,680,829,267,111,733,220,247,779,416,110,704,994,862,58,502,814,166,477,694,868,383,192,620,120,84,124,585,723,148,138,377,739,821,214,687,286,626,84,46,363,568,242,674,814,159,647,62,422,996,1,793,526,119,987,618,60,202,153,105,447,823,991,315,926,785,493,38,916,50,882,949,692,101,930,303,0,657,823,937,238,616,157,702,982,827,537,36,103,953,527,953,192,248,237,104,447,480,686,479,730,159,664,597,789,45,278,181,818,74,381,527,186,927,52,622,511,315,972,352,284,599,416,371,235,281,856,1,783,355,728,975,26,252,151,105,3,62,427,635,772,630,862,515,211,663,372,270,305,471,713,386,73,412,172,34,182,125,763,206,448,761,861,459,7,636,396,777,377,317,264,528,435,463,498,693,142,491,237,673,907,865,361,795,28,389,601,90,16,976,237,453,52,200,256,773,127,961,55,417,55,990,737,431,415,771,529,975,196,710,905,550,439,878,865,950,48,293,128,955,884,392,219,527,864,469,812,713,451,777,484,229,890,655,783,723,999,249,150,150,46,462,872,918,772,473,114,283,523,582,332,329,969,633,475,384,46,71,92,934,498,793,194,45,685,291,813,565,60,17,528,967,878,397,456,974,331,307,125,808,963,255,816,433,351,642,397,37,649,727,255,513,759,741,653,226,8,571,752,350,878,841,646,792,560,443,365,723,498,29,257,131,279,10,85,568,269,874,282,340,754,823,733,11,448,114,974,736,609,272,632,995,913,542,744,973,881,706,183,238,468,538,62,960,105,98,440,92,499,431,683,424,965,58,826,332,474,703,487,535,717,136,175,234,923,551,407,999,133,411,874,795,371,912,702,360,438,748,264,406,777,162,168,645,197,275,271,305,59,965,141,548,118,102,751,175,798,561,679,756,936,669,461,93,258,617,321,535,315,780,440,563,144,92,183,428,932,452,953,932,62,290,638,530,847,511,300,466,427,12,629,636,53,127,879,125,775,464,746,485,350,586,576,862,547,925,692,925,214,166,331,997,99,28,880,155,137,445,750,724,230,872,685,400,742,619,27,775,4,185,955,938,323,742,323,681,956,910,412,72,369,459,335,601,913,618,642,618,824,316,461,297,873,115,434,5,41,462,566,952,237,206,988,710,343,884,443,439,558,726,174,897,734,450,510,808,451,118,328,891,176,957,807,202,651,216,581,68,438,28,186,459,293,548,804,921,457,276,663,352,296,205,201,547,682,84,569,129,306,302,414,151,899,429,52,92,558,19,10,538,807,550,405,4,423,105,330,983,717,54,208,694,495,187,351,386,670,138,972,699", + "648,674,915,387,404,306,257,971,700,258,396,466,678,181,411,492,943,782,722,793,79,973,836,703,739,200,538,19,351,705,788,655,818,461,711,887,561,77,322,844,394,597,801,540,879,729,372,894,353,683,570,290,631,795,155,258,92,607,24,657,996,168,307,563,926,594,548,828,84,144,448,994,224,370,356,130,852,595,657,763,827,111,315,236,953,967,556,205,913,416,24,475,992,941,840,856,997,340,289,218,409,719,441,23,994,289,761,745,702,108,205,692,423,800,299,86,986,501,482,638,183,845,224,779,246,350,232,274,634,35,1,763,927,212,609,917,96,554,136,848,812,139,185,340,870,641,539,571,930,100,214,892,149,245,993,397,430,561,175,446,618,223,608,582,889,439,296,36,704,200,828,645,616,745,925,508,589,34,754,838,344,790,875,307,921,576,914,46,303,424,593,263,520,703,129,418,741,109,410,133,193,398,499,814,995,608,507,921,234,381,825,190,198,35,786,328,878,175,82,967,981,192,226,482,628,131,326,890,422,607,728,391,505,198,992,87,296,389,302,23,642,888,825,1,512,745,985,711,813,281,473,932,135,171,520,957,261,189,347,653,358,105,550,325,852,485,869,756,481,910,564,606,882,747,886,72,328,996,192,734,592,855,948,567,319,956,664,882,924,68,745,590,122,748,820,7,28,124,558,519,590,339,646,535,336,253,465,13,464,321,98,304,719,139,949,603,316,926,59,842,723,537,532,108,65,383,920,801,438,358,105,67,587,501,169,527,155,479,521,440,421,804,645,125,226,955,73,97,614,210,269,387,849,808,69,106,460,500,7,548,324,879,872,924,843,855,230,832,286,171,16,998,924,871,896,764,480,334,653,48,120,790,799,403,699,199,689,501,974,765,857,29,760,44,721,197,269,516,891,817,657,371,90,119,567,927,824,593,872,368,689,723,689,458,991,52,841,696,514,29,537,774,406,141,962,812,136,519,592,904,905,149,699,529,23,834,705,319,702,492,790,655,121,284,837,664,824,980,249,537,310,707,855,779,777,674,296,234,871,610,964,891,710,122,232,128,44,606,763,248,374,682,596,329,872,40,455,810,314,552,159,636,884,529,429,369,95,60,499,674,746,669,948,683,18,518,657,0,422,110,303,491,104,320,951,442,961,498,417,326,399,255,792,442,824,291,179,549,346,824,137,426,956,37,357,118,639,196,736,27,451,825,344,429,127,541,901,759,654,884,17,112,236,494,956,968,927,285,960,432,920,452,996,106,387,365,496,971,17,637,15,57,93,881,719,930,324,246,912,738,833,908,774,326,640,591,414,739,316,868,482,806,707,525,317,841,398,291,59,452,66,514,515,172,658,546,241,33,621,96,792,151,414,570,723,630,477,462,390,814,897,890,580,87,996,634,961,5,399,21,685,933,200,914,745,124,78,908,453,230,535,867,155,66,638,325,835,915,561,364,599,79,631,739,379,62,379,166,280,266,670,204,178,543,7,107,817,32,727,153,826,604,157,452,807,276,464,966,889,68,60,343,343,306,524,556,227,885,252,593,479,487,736,661,941,419,614,354,685,91,73,618,264,750,948,461,813,626,156,955,2,969,986,894,332,677,596,265,360,611,474,509,792,413,568,38,37,820,730,509,274,39,32,637,104,505,668,268,740,632,469,297,527,552,394,618,787,547,81,104,350,476,3,308,336,618,222,66,166,273,950,408,751,286,205,100,571,903,629,864,148,367,811,77,674,628,66,925,115,325,587,63,583,745,537,45,935,572,949,123,739,744,77,248,943,994,550,201,654,373,466,625,570,845,907,638,64,232,850,729,117,471,221,734,75,825,728,391,257,737,263,522,438,298,938,119,265,723,156,307,241,264,42,510,684,935,834,240,550,185,123,964,381,380,374,94,745,922,258,264,100,658,260,252,482,316,672,886,866,826,275,844,187,532,415,902,163,240,651,500,971,901,553,861,918,529,3,387,189,914,471,579,551,863,132,83,627,888,559,616,207,178,545,359,487,207,214,79,888,709,289,768,389,335,89,448,877,74,696,435,880,327,804,179,165,191,588,662,32,13,596,895,527,471,554,491,66,473,823,802,581,634,253,866,182,125,236,423,781,284,212,463,896,421,186,71,612,251,986,462,377,712,795,534,792,5,765,303,941,57,821,497,445,455,778,481,856,743,606,591,474,493,477,370,234,576,453,171,421,884,428,305,478,189,50,315,196,605,476,280,684,937,439,647,192,899,356,858,316,965,603,79,412,908,175,167,631,850,524,775", + "352,582,361,973,29,72,43,791,666,899,949,365,392,694,265,405,399,725,314,992,293,440,664,420,504,253,208,856,921,689,712,323,445,40,347,219,850,950,585,415,165,94,96,441,992,440,840,642,182,307,324,305,63,733,769,18,843,812,3,135,759,323,44,862,472,49,490,181,954,910,186,673,348,506,127,59,546,487,287,902,350,70,531,587,926,560,979,652,768,319,69,307,524,706,387,909,361,950,837,590,17,428,915,269,164,512,453,50,307,561,120,937,43,96,823,867,881,5,736,332,834,261,764,312,417,605,422,340,731,51,74,239,560,153,722,172,975,796,428,886,853,674,201,775,780,393,43,866,503,871,948,607,184,212,957,695,406,828,483,307,993,252,96,434,759,11,605,145,117,670,425,8,291,347,489,640,880,543,817,127,156,406,602,740,527,560,446,537,386,78,394,93,758,534,644,91,730,396,580,986,999,861,300,786,712,423,60,22,833,675,286,537,400,975,945,822,186,475,45,246,896,146,370,309,529,240,31,344,335,246,891,724,338,477,519,230,277,313,656,710,436,723,315,633,644,4,999,438,280,30,615,82,496,781,159,144,352,572,640,346,560,132,333,377,839,950,906,755,900,195,148,178,523,775,793,292,770,379,995,605,137,315,419,714,367,367,776,293,890,112,634,755,973,912,350,456,402,151,867,107,364,946,433,637,805,32,246,671,87,943,279,834,618,13,47,353,262,619,126,929,550,66,87,353,886,525,262,173,601,634,776,949,744,147,562,59,760,452,343,466,845,176,145,376,347,108,654,111,610,969,684,116,101,290,234,409,206,275,867,778,949,786,499,202,202,514,224,453,793,666,152,773,766,646,379,969,581,957,417,968,272,432,925,396,254,945,581,385,89,87,504,76,358,200,717,518,898,612,959,857,265,731,88,173,673,285,2,432,564,811,430,479,461,811,184,760,689,349,370,92,411,695,711,7,863,728,890,937,545,595,406,830,817,962,110,645,234,56,706,771,416,622,412,503,950,31,823,352,703,679,280,936,507,438,450,734,775,603,276,705,270,259,270,208,607,144,492,521,32,182,926,618,109,198,508,554,239,405,626,476,238,265,413,777,986,883,485,324,927,910,15,486,729,861,631,747,823,422,0,505,724,179,433,363,689,917,555,581,234,385,915,673,810,787,125,427,288,865,728,23,856,139,90,6,842,197,331,44,687,437,478,643,467,41,207,743,472,58,871,560,398,557,688,821,470,617,511,564,164,998,59,685,111,731,92,401,454,180,731,921,554,223,583,328,128,456,82,92,271,755,113,33,608,729,325,83,544,80,167,259,716,566,431,427,983,528,192,115,363,84,784,433,682,317,98,368,132,508,813,569,103,379,231,146,29,489,576,355,809,423,481,984,234,570,22,305,405,750,801,204,499,836,879,36,419,536,185,892,339,84,83,554,319,627,658,828,78,960,400,401,48,314,404,823,720,736,336,441,493,108,579,109,217,327,550,186,172,552,935,683,929,6,498,384,760,670,627,903,166,706,772,351,593,910,164,906,812,385,363,447,10,121,937,658,427,260,466,546,304,312,856,789,153,690,349,908,406,919,726,4,49,754,294,623,969,621,113,940,220,34,387,280,769,3,91,178,207,413,779,2,340,668,807,897,787,217,269,361,84,778,873,669,592,435,265,481,392,172,784,556,57,516,818,924,194,163,411,634,639,319,397,239,906,869,138,15,559,675,391,31,267,270,656,166,225,874,122,788,687,715,809,649,981,187,931,85,64,613,566,74,187,911,739,872,797,107,320,589,176,894,360,321,474,701,388,409,523,84,332,370,808,680,136,149,177,91,917,804,433,106,701,738,833,961,398,598,109,211,467,987,456,740,229,405,885,150,190,788,956,612,971,611,774,60,489,173,431,712,182,656,739,647,578,574,669,885,676,130,792,309,996,130,441,684,366,874,271,25,665,528,47,525,212,20,298,622,897,907,420,578,20,482,675,549,635,69,815,515,149,710,402,63,632,872,903,85,5,865,684,827,59,617,36,685,748,614,657,908,490,998,103,463,358,178,638,326,438,931,685,322,477,134,586,651,782,46,79,753,673,481,33,160,516,46,945,287,726,987,258,442,827,982,137,120,97,211,410,551,13,267,120,420,171,245,419,427,852,655,501,792,473,771,729,336,288,231,254,356,675,284,19,922,945,453,533,905,591,826,901,172,409,563,692,981,245,182,367,850,122,79,324,382,887,391,162,937,546,102,431,608,71,135,256,862,225,207,173,622,900,338", + "497,593,882,674,956,130,710,181,684,381,767,567,730,329,96,536,454,167,843,262,420,391,697,295,522,188,70,589,282,713,537,106,123,726,442,433,416,555,917,30,574,998,197,289,124,431,159,685,912,607,919,356,961,911,400,68,154,589,682,26,477,743,925,512,3,826,765,438,627,813,999,679,243,56,856,869,666,679,712,339,935,296,287,271,830,85,702,601,230,922,821,111,473,526,590,661,68,439,864,9,622,614,354,181,746,936,434,913,72,922,774,626,86,28,139,93,299,83,36,906,815,594,322,898,315,759,96,851,675,583,5,706,691,434,258,882,226,395,555,965,865,277,618,463,184,335,563,279,347,63,492,337,6,590,901,546,987,666,108,630,305,409,369,880,556,629,389,224,156,127,729,327,385,153,873,865,360,68,629,802,613,905,937,281,406,15,710,175,351,867,706,428,821,471,972,540,322,970,720,563,226,577,446,850,763,581,728,742,40,732,623,285,508,101,293,380,861,759,59,282,959,621,902,303,25,362,20,813,152,860,830,303,934,896,320,628,617,248,383,785,263,540,209,979,60,465,460,89,695,962,187,236,746,612,288,619,349,641,602,77,833,969,457,656,719,14,206,309,3,808,951,261,962,845,184,424,397,666,393,320,618,620,678,575,805,875,893,246,372,416,290,910,771,416,502,541,316,23,247,944,327,312,467,405,767,948,391,114,41,356,432,416,369,424,866,392,781,78,421,958,89,570,35,139,727,756,398,616,932,695,872,311,444,426,194,801,418,107,518,126,157,995,101,998,72,915,720,865,254,90,399,537,575,171,351,929,945,432,654,795,237,783,491,275,723,946,298,762,607,887,256,286,392,978,872,132,301,737,454,814,828,544,248,958,838,831,557,208,818,703,684,707,667,733,818,198,309,368,194,85,658,517,164,668,29,540,114,126,894,722,373,90,154,313,993,292,970,85,951,925,435,20,498,340,727,563,841,497,854,89,202,261,836,184,945,278,105,658,477,158,529,468,175,629,424,500,277,313,370,68,719,999,830,822,321,179,471,536,331,638,244,822,370,340,999,684,966,283,852,318,569,567,55,730,861,992,233,227,804,101,509,108,869,203,153,544,728,873,540,873,294,273,813,371,955,519,937,110,505,0,216,664,581,536,832,316,253,966,802,777,490,649,430,378,532,993,584,724,319,533,648,597,815,672,404,705,797,550,782,906,990,661,261,249,756,15,326,451,415,579,567,635,413,658,192,50,599,414,599,213,237,465,686,245,718,458,710,334,826,399,143,44,545,346,958,446,617,668,744,473,11,459,91,983,25,854,291,34,491,606,918,198,20,282,255,671,764,5,885,29,856,663,134,574,443,729,773,262,392,337,487,692,224,616,348,741,121,702,971,201,186,302,383,459,305,509,670,560,732,934,930,284,421,663,629,635,66,384,530,686,525,337,844,614,274,187,395,828,224,585,46,884,296,596,945,30,216,567,292,114,451,801,89,559,177,868,72,887,11,263,146,799,686,175,994,267,518,244,337,671,805,675,589,508,796,811,810,289,205,955,756,208,514,586,544,340,824,84,489,792,241,146,131,384,328,625,989,129,883,578,121,454,720,662,994,114,145,814,707,831,443,475,322,558,60,815,530,899,707,636,888,81,883,868,32,585,120,785,620,113,627,357,803,38,409,384,57,823,859,434,154,335,954,85,172,783,309,38,351,135,735,567,40,823,752,568,335,964,457,530,395,497,531,519,951,499,705,381,248,460,766,740,442,419,344,126,818,964,404,79,152,183,955,201,593,992,965,7,427,867,387,823,35,692,870,632,417,315,315,679,754,998,266,973,733,516,922,159,93,829,717,889,8,849,183,404,197,575,289,710,119,292,165,925,529,870,999,244,563,26,807,518,987,314,555,408,373,176,836,605,666,819,853,590,475,353,535,745,521,218,47,89,118,729,667,670,374,706,265,355,768,832,612,245,361,965,419,587,265,663,55,466,470,573,35,932,310,93,930,34,826,467,557,894,955,475,63,634,679,787,156,531,877,21,501,263,791,799,808,362,287,706,388,33,539,608,735,993,666,801,644,328,737,806,560,195,983,499,68,994,47,864,373,826,64,345,552,863,312,848,770,736,430,551,192,418,371,427,940,713,590,995,115,567,535,674,603,340,696,596,826,166,123,669,792,805,324,721,969,315,928,910,713,108,53,555,703,889,353,940,638,637,697,613,391,957,286,314,927,442,214,818,415,31,214,845,133,678,212,784,646,196,924,845,922,541,154,287,846,429", + "782,29,934,275,215,215,408,38,803,276,15,396,542,414,573,839,365,718,650,931,334,233,149,632,364,964,124,143,497,603,997,833,640,368,608,242,56,973,229,500,207,347,407,202,978,258,820,668,47,152,943,651,743,572,122,79,991,832,469,335,293,305,286,182,528,354,376,115,541,463,666,782,631,751,864,724,159,411,64,953,648,467,27,192,181,671,826,742,798,285,125,300,317,462,460,686,554,689,583,899,829,1000,603,275,389,887,663,442,853,784,126,575,729,142,912,758,761,375,200,102,954,617,346,622,307,927,19,18,547,32,150,52,493,542,11,876,809,123,781,126,681,583,246,989,930,473,752,478,251,630,488,721,540,547,315,827,597,802,349,475,356,813,167,791,164,980,688,872,692,245,521,776,448,313,872,886,156,667,944,614,461,761,644,252,895,823,51,475,332,97,719,762,246,665,172,981,318,771,735,521,38,181,318,745,605,704,596,575,253,33,870,792,59,677,762,434,138,376,894,865,114,230,237,696,843,583,420,19,378,246,921,677,803,364,449,121,666,92,423,673,845,221,304,217,974,815,375,479,760,265,74,797,361,672,592,260,320,905,383,888,27,810,11,287,488,137,470,359,66,828,923,687,899,594,328,435,909,581,494,787,931,783,547,460,164,733,413,924,799,947,164,827,388,178,367,118,925,300,832,663,320,272,627,398,474,915,695,533,869,253,200,809,724,322,294,381,215,594,146,774,624,736,558,7,61,228,767,784,348,669,912,953,324,771,111,992,748,24,910,958,579,914,221,659,678,77,616,75,748,585,476,373,749,921,255,286,107,984,932,100,901,984,494,855,333,520,630,517,946,767,784,169,818,380,957,104,787,526,592,495,236,57,689,997,663,144,554,699,677,708,613,744,496,350,241,947,482,881,335,740,16,200,903,727,618,742,931,439,950,986,918,431,473,203,793,584,788,220,433,71,565,906,180,455,80,196,450,71,308,313,285,999,845,510,134,213,244,585,876,932,326,100,177,732,939,942,410,272,116,787,457,729,395,86,511,212,970,309,61,128,658,291,606,759,531,989,59,839,473,555,407,938,98,458,909,627,505,315,779,381,151,429,962,224,638,944,549,640,590,904,56,47,649,811,144,415,238,303,724,216,0,484,589,876,381,435,430,798,930,948,61,197,592,388,423,971,997,747,616,91,615,697,353,994,459,867,826,828,136,584,213,344,193,518,568,762,160,710,16,863,141,108,918,447,830,922,513,903,973,919,430,34,640,979,232,117,47,156,196,933,737,941,979,46,161,155,594,162,546,921,125,502,246,498,3,421,440,706,601,876,120,900,414,660,812,300,282,399,529,860,701,371,501,156,554,644,129,127,414,42,763,547,873,416,216,953,279,902,605,904,830,572,701,681,100,393,31,117,499,604,182,211,456,22,974,307,242,668,26,455,540,192,809,801,408,128,896,290,779,32,375,830,710,430,859,905,59,902,903,140,449,938,647,825,498,927,785,206,241,22,231,621,939,784,899,882,902,711,183,523,867,496,159,613,896,215,114,264,772,934,14,747,333,886,650,748,729,201,359,757,835,930,867,914,643,970,372,521,807,77,932,818,586,436,672,359,268,925,842,569,643,401,587,479,836,830,313,120,163,490,552,476,104,885,992,538,349,679,37,552,602,109,731,454,355,547,1,824,56,714,339,967,691,261,83,546,957,653,779,623,435,213,685,499,284,558,821,620,852,743,620,404,430,69,769,580,708,921,715,306,762,974,410,354,405,662,356,143,110,895,236,327,645,532,272,672,380,696,894,329,763,708,512,914,163,361,198,329,946,459,423,152,914,479,911,688,780,720,568,78,321,118,699,580,835,806,333,961,744,72,213,459,126,413,629,144,446,267,687,300,450,166,611,719,385,706,524,357,447,592,376,993,504,120,332,516,657,999,718,282,846,406,573,140,85,568,276,641,624,599,117,763,599,401,760,447,231,263,47,419,614,947,400,626,518,917,990,483,808,371,781,560,822,333,608,898,531,537,22,310,946,160,119,34,262,339,688,54,855,715,277,29,202,150,244,985,324,672,800,667,457,767,576,834,568,799,997,332,107,763,118,84,694,309,601,585,286,200,871,186,57,973,276,665,439,817,811,603,235,517,671,699,633,252,214,369,236,366,475,830,222,50,801,176,297,989,864,349,741,61,792,801,410,608,584,627,304,541,684,67,859,487,555,433,274,492,353,446,58,59,88,320,310,653,436,76,899,232,58,266,117,131,487,146,423,84,343,108,325,402", + "182,787,471,791,265,210,205,460,738,995,366,949,569,959,82,180,105,890,896,344,883,157,965,263,977,296,715,306,357,37,917,276,486,828,80,693,719,990,236,781,133,573,577,519,553,669,472,974,759,472,728,530,890,272,956,715,731,277,569,570,264,439,134,272,157,616,122,259,435,555,903,883,964,189,882,231,721,418,277,18,667,105,856,459,867,685,394,798,758,516,715,688,999,522,698,105,908,299,383,433,348,746,624,692,593,600,539,408,123,415,815,152,519,476,524,612,931,186,534,384,236,85,566,594,230,507,575,429,568,622,343,295,374,642,32,939,361,345,119,395,656,192,346,669,630,904,44,290,595,764,869,353,176,798,17,945,752,398,966,5,505,487,87,11,185,498,811,408,280,952,348,926,798,292,394,950,736,421,100,994,486,380,649,494,379,846,991,136,781,566,677,336,633,678,280,489,416,215,806,855,106,798,224,979,859,74,264,938,890,99,903,848,978,40,176,644,950,495,827,915,419,218,412,636,806,672,475,13,458,439,473,913,381,352,862,93,815,361,58,610,921,853,431,980,733,127,151,932,213,747,421,62,274,205,323,11,658,429,714,303,979,7,541,943,585,815,687,764,453,666,479,435,836,545,817,597,434,30,413,383,737,307,836,446,90,648,232,387,256,12,3,337,99,310,922,387,371,271,736,499,926,713,733,954,134,13,170,96,671,235,496,462,247,924,124,215,648,331,818,411,382,27,447,371,700,577,669,834,744,522,852,396,981,81,566,125,141,755,990,178,483,248,371,872,331,201,76,31,817,70,279,19,126,733,588,444,926,549,844,698,947,412,237,532,300,541,570,305,676,538,185,542,910,480,545,267,566,729,134,317,404,734,447,792,413,39,779,119,256,110,398,850,847,500,72,740,354,10,470,606,927,208,18,90,732,201,916,362,528,303,704,831,343,524,541,642,548,869,837,408,30,729,686,766,913,137,294,436,821,833,162,860,486,588,327,910,28,584,25,787,522,675,166,570,552,531,392,242,758,292,508,496,609,593,36,512,780,75,269,700,387,447,628,826,630,398,221,122,492,739,369,80,377,937,752,797,795,193,720,444,46,656,582,934,49,626,634,83,467,21,448,585,679,467,507,859,616,491,179,664,484,0,448,302,672,978,468,106,219,261,887,234,927,363,143,139,603,355,633,2,169,724,14,751,257,387,755,659,70,536,519,383,913,292,16,569,947,493,189,748,276,61,565,467,857,893,395,919,675,861,664,494,689,808,577,439,429,823,547,306,240,992,834,752,695,548,630,560,426,35,903,424,68,15,578,15,37,865,645,371,699,27,754,65,731,495,641,190,343,454,322,495,575,698,768,632,451,606,964,650,178,73,114,232,187,220,123,265,328,855,553,393,742,33,563,241,10,708,724,530,487,497,701,718,278,151,709,660,240,633,332,272,876,229,968,868,866,618,21,188,474,857,863,750,848,441,1000,283,30,813,557,35,329,643,796,745,898,688,178,245,46,137,921,846,151,53,116,671,108,892,227,49,182,460,15,28,235,484,106,996,454,92,309,758,805,638,526,510,491,682,475,115,941,92,412,606,245,807,88,770,510,27,915,681,601,58,363,20,860,979,506,616,958,812,458,560,722,918,854,609,316,20,455,952,88,813,136,638,742,107,161,632,164,301,951,490,761,915,558,566,381,892,339,88,759,590,156,655,75,154,636,529,926,177,967,312,912,344,62,996,652,621,262,69,317,619,443,262,637,465,525,363,311,106,69,583,250,850,461,439,814,182,806,42,442,196,679,124,320,838,602,849,827,214,274,498,590,580,184,4,195,213,668,327,374,451,167,127,365,561,291,453,672,290,631,738,445,29,895,964,456,100,911,304,239,734,383,440,729,638,436,657,747,70,303,793,525,918,507,350,520,778,684,577,172,921,782,909,99,343,118,167,858,919,90,361,871,416,118,202,91,928,571,806,20,63,235,140,463,933,549,347,236,161,72,257,455,875,7,570,787,851,233,517,105,475,926,299,831,834,755,543,230,20,29,546,421,229,803,46,336,657,313,923,127,186,94,300,888,855,615,12,748,512,922,703,860,613,140,45,144,936,822,596,592,205,234,424,298,889,578,838,44,696,47,243,668,940,199,257,107,184,352,217,298,637,432,548,296,677,975,261,671,197,21,674,836,291,241,477,76,814,695,249,13,819,678,228,7,526,475,892,185,83,567,285,388,137,586,556,225,303,409,841,395,253,398,954,147,448,184,13,349,889,329,33,782,574,321,563", + "463,687,397,723,533,312,74,713,861,86,975,529,286,801,493,677,605,116,722,805,200,336,751,770,108,598,535,733,173,764,716,145,369,944,3,131,990,639,149,137,504,56,919,356,679,708,2,877,296,691,38,56,697,3,171,665,653,535,587,985,428,593,997,787,245,365,167,88,957,712,791,577,404,15,443,770,271,188,749,559,766,675,310,857,695,225,475,691,213,557,924,4,466,7,854,146,530,225,265,576,792,873,885,34,185,451,688,565,373,339,785,644,678,913,898,180,359,258,31,811,200,105,216,188,783,148,829,950,260,684,234,248,716,816,645,789,278,882,568,379,453,519,289,825,84,625,63,537,157,895,503,998,728,542,824,239,380,145,353,11,784,617,553,609,222,571,462,120,420,779,989,417,406,321,697,481,724,815,340,432,333,340,298,175,641,893,113,247,73,150,959,184,951,99,996,815,340,929,319,249,120,852,771,200,841,548,128,859,554,301,317,904,187,161,772,593,98,33,456,776,686,204,550,898,920,469,767,27,17,177,27,315,902,896,657,465,389,454,946,603,406,333,626,598,279,178,927,2,370,388,963,435,303,868,670,276,754,86,418,323,646,704,909,658,10,135,497,850,396,558,159,741,159,236,462,192,908,674,919,846,3,189,980,454,963,879,84,137,8,752,218,895,140,631,941,80,586,74,591,953,159,416,928,560,891,998,222,411,779,745,387,50,126,742,905,850,306,870,416,624,52,682,359,447,147,533,982,447,252,822,359,40,16,238,502,623,605,594,747,131,409,260,762,806,407,618,106,150,704,41,14,510,648,415,362,109,911,592,864,556,691,83,922,440,129,334,631,119,172,244,576,202,562,374,630,100,797,864,38,851,412,225,978,850,906,485,366,904,860,254,591,676,906,247,862,607,743,602,602,71,940,925,945,936,114,93,737,114,852,938,898,892,385,938,968,345,949,826,379,892,359,134,170,636,866,455,743,356,635,60,839,225,597,438,709,150,76,721,372,899,301,681,493,557,351,714,296,460,948,784,951,705,901,946,218,321,367,567,12,261,873,277,339,729,782,38,331,522,924,590,102,975,273,24,491,626,537,287,105,327,39,935,820,356,996,167,502,142,467,287,451,529,1,992,121,190,157,104,433,581,589,448,0,941,758,202,38,492,206,350,432,990,800,46,97,418,327,45,759,304,640,734,63,712,456,426,740,676,662,806,987,546,422,490,770,409,868,137,161,279,760,134,360,889,996,449,703,745,636,362,571,809,360,429,452,426,381,207,792,631,856,115,685,174,589,565,747,322,558,491,468,74,947,808,410,280,674,639,121,562,350,587,947,736,299,847,509,152,655,681,444,562,197,23,259,951,343,633,332,524,949,416,150,308,271,568,304,600,302,724,361,857,514,674,252,10,406,57,610,523,467,4,794,245,398,537,70,710,244,414,309,444,215,207,134,554,643,450,11,107,942,665,978,594,841,588,841,829,446,245,838,874,388,563,214,532,386,261,816,20,888,761,885,882,723,347,390,1000,150,704,89,2,842,685,404,219,432,106,918,354,493,284,282,648,751,968,547,764,757,173,699,496,943,351,767,910,274,266,981,495,77,570,283,365,307,841,523,556,249,539,862,943,289,884,814,705,429,89,988,503,341,373,251,373,74,124,175,191,707,281,661,492,224,7,40,490,113,175,947,903,620,5,477,554,296,412,887,455,260,278,197,531,879,635,771,748,571,814,254,510,761,453,369,781,24,311,115,372,895,885,673,663,78,356,964,443,583,606,716,360,62,644,865,767,742,264,596,510,764,893,545,695,691,478,849,961,745,413,9,742,584,229,831,251,406,392,442,571,26,332,538,111,516,864,196,644,725,834,930,987,770,870,509,478,312,844,293,872,225,663,736,351,529,431,406,614,503,706,317,539,519,177,402,630,450,86,933,763,143,294,775,946,212,828,127,473,444,323,331,114,985,344,513,582,218,133,307,885,23,308,138,687,712,467,242,417,87,51,714,726,499,613,586,794,466,99,531,698,711,226,599,19,415,292,17,788,671,931,8,975,371,539,608,846,206,71,316,518,920,39,381,174,349,368,450,594,207,258,56,638,989,775,71,505,143,292,406,769,823,700,260,601,157,713,791,666,269,594,279,541,371,700,695,305,946,546,255,796,543,779,172,876,892,471,598,662,620,128,238,198,599,54,398,205,771,111,614,103,194,804,574,371,802,784,745,65,267,660,609,254,505,479,142,827,180,675,672,521,291,146,167,634,429,415,48,164,384,554,854,20", + "557,878,92,360,307,635,150,75,263,969,497,181,795,128,323,462,96,664,22,778,478,778,439,148,337,924,95,419,548,913,684,251,684,256,919,938,101,185,413,973,76,121,865,974,66,679,18,904,208,793,639,373,62,292,834,183,928,661,221,702,438,21,111,90,766,662,328,539,384,649,647,660,373,244,926,298,894,123,189,756,754,228,166,149,123,509,851,784,885,410,968,646,607,363,351,798,511,433,448,367,247,878,63,240,660,380,785,61,652,146,329,348,891,243,93,831,553,544,643,380,298,592,538,430,48,706,283,26,171,155,613,872,757,303,471,652,473,629,258,842,75,259,404,795,615,287,325,944,640,839,791,186,993,258,331,878,936,284,485,599,7,222,5,683,472,760,171,953,149,289,512,912,538,975,805,514,888,625,225,800,80,850,529,31,711,269,29,978,438,66,211,145,395,944,109,631,758,180,798,380,420,369,925,253,101,944,956,494,866,636,739,98,55,69,848,588,328,255,214,772,372,769,993,454,148,788,224,583,959,868,287,273,349,145,703,469,240,516,101,708,349,950,950,333,97,506,889,154,953,745,960,994,322,861,465,713,285,921,785,799,229,16,972,96,680,368,447,619,428,286,254,195,36,182,788,228,326,241,197,173,828,484,743,487,193,876,119,416,346,256,628,545,303,195,845,492,181,559,856,453,269,298,511,734,504,162,207,983,898,335,143,774,36,992,700,39,635,218,985,281,572,491,441,308,87,411,262,213,20,234,653,254,539,957,987,62,621,292,655,456,892,646,430,235,5,615,320,510,23,417,956,791,456,886,953,298,100,267,353,653,3,702,353,527,825,96,590,58,348,179,106,719,295,470,571,184,830,345,605,745,821,574,258,881,959,85,600,873,354,491,536,153,849,927,598,398,221,33,19,250,756,392,40,935,975,418,3,534,457,101,357,851,481,235,180,517,805,561,314,11,242,36,258,845,463,440,562,684,667,65,426,480,75,486,69,768,780,945,950,547,605,950,97,458,454,761,136,442,28,38,678,820,116,277,938,472,9,666,62,98,614,134,896,71,291,782,838,577,371,302,617,905,557,32,585,354,918,64,444,510,977,77,201,954,66,579,312,774,371,656,650,59,615,245,277,398,702,320,363,536,876,302,941,0,314,400,799,831,24,745,317,699,992,233,419,28,758,673,604,412,642,527,75,683,215,172,603,609,948,551,373,323,273,364,910,23,75,549,547,176,246,172,121,659,737,548,996,167,16,896,404,483,680,753,423,988,994,580,183,618,260,946,70,414,302,315,877,578,734,883,605,517,816,570,627,654,813,797,896,556,553,999,326,76,20,844,706,439,833,946,711,292,874,304,509,622,534,887,70,826,933,426,670,525,409,583,382,121,81,822,163,649,858,244,101,605,668,887,142,90,376,944,471,402,466,887,238,850,772,236,514,881,809,586,804,752,546,933,982,384,493,821,673,636,186,444,388,245,386,358,789,480,258,813,732,919,45,764,17,4,764,982,988,102,702,210,152,370,72,986,343,395,346,948,278,388,944,240,431,130,745,51,348,724,22,576,88,294,97,468,848,22,592,156,858,466,919,623,212,620,111,978,231,19,500,214,495,716,541,814,703,987,465,498,135,727,104,900,494,524,861,826,769,956,656,600,605,250,28,400,901,888,344,774,22,534,27,771,627,235,459,107,369,179,177,263,569,410,490,472,503,841,111,134,446,916,270,929,325,632,105,985,467,859,630,582,134,428,530,352,721,676,470,865,199,746,341,815,164,320,349,607,68,17,947,776,815,987,41,303,709,56,753,334,210,860,399,404,309,903,100,776,934,674,707,57,938,835,597,325,901,412,109,105,310,98,798,262,728,615,361,219,116,238,471,424,210,393,765,64,803,82,573,256,77,247,88,743,902,10,432,550,192,790,612,650,715,917,874,152,195,612,593,596,905,671,511,288,806,438,603,730,397,133,256,648,840,18,492,831,29,643,595,613,732,705,123,434,909,41,242,76,62,201,116,311,987,737,636,989,31,290,739,218,285,260,416,394,188,365,447,168,347,434,265,340,472,924,634,687,4,310,946,871,434,168,846,232,677,229,125,117,688,121,823,33,366,317,998,183,684,891,920,464,276,325,410,198,998,59,856,545,775,698,671,747,407,505,304,965,212,501,772,195,109,960,117,858,935,474,196,967,996,281,680,501,663,551,467,387,947,167,214,124,297,77,140,134,167,909,28,254,947,605,292,849,2,779,492,43,968,526,571,432,311,945,531,709,458,413", + "20,640,714,238,424,595,496,367,3,802,685,303,596,170,461,2,81,303,237,701,663,712,286,99,92,849,408,348,815,18,159,950,601,604,35,278,697,490,996,422,983,283,455,643,338,559,810,590,212,167,341,125,290,474,176,513,491,573,856,69,904,886,80,726,754,862,363,425,633,506,323,793,154,42,526,598,555,773,687,129,578,103,742,84,811,234,925,864,523,657,347,164,749,802,842,204,222,252,368,948,584,285,459,76,9,567,784,23,589,156,650,464,401,892,379,999,521,917,214,462,873,948,100,158,589,267,174,533,12,372,964,281,117,457,936,67,157,533,291,201,706,617,7,798,626,110,904,667,985,285,293,20,591,739,141,618,944,470,839,436,584,515,792,487,93,532,774,699,408,858,953,373,981,548,522,431,670,696,100,466,982,654,888,434,403,99,635,261,314,967,394,596,322,468,996,463,726,620,297,767,37,644,171,530,78,643,485,113,585,129,506,44,595,212,42,876,313,72,979,3,76,36,60,880,148,32,113,921,756,296,898,502,54,106,651,962,818,473,214,936,775,705,62,228,511,365,802,6,191,474,551,802,869,364,405,390,616,130,982,471,274,901,957,471,436,528,303,949,944,821,66,879,705,254,934,727,329,779,487,671,559,939,252,954,517,188,308,191,513,951,390,937,726,427,268,336,332,927,759,63,832,951,367,658,57,327,938,697,135,39,655,32,210,75,763,637,344,298,368,81,653,735,643,195,915,669,955,441,106,833,184,527,303,763,831,551,973,298,667,694,581,536,551,330,630,854,616,956,846,266,829,329,949,580,78,814,26,702,318,89,981,178,926,129,841,716,402,378,816,130,925,71,73,268,51,142,593,523,926,835,321,44,115,299,922,227,692,976,772,68,331,963,575,108,846,648,686,796,178,979,306,32,733,3,520,790,931,590,185,294,425,993,885,600,200,130,314,44,55,607,809,959,651,550,746,694,662,86,164,479,79,55,205,229,911,75,898,904,108,532,410,762,364,50,257,899,944,258,448,845,426,880,291,831,858,6,574,864,694,234,681,273,318,999,568,530,335,252,706,118,785,665,311,626,119,575,652,656,403,238,95,956,251,476,53,175,465,530,862,143,616,66,25,846,884,374,982,951,689,832,381,672,758,314,0,703,515,886,407,726,29,833,923,172,600,772,853,889,6,50,407,553,661,860,561,878,53,773,318,922,451,940,948,54,716,430,230,769,5,249,732,205,811,767,788,313,909,20,37,776,148,762,646,108,630,606,130,692,188,934,285,539,115,15,580,354,455,364,374,493,276,546,248,221,256,747,721,594,717,306,788,200,275,825,832,56,951,967,538,776,713,599,518,355,623,582,186,288,918,384,768,722,652,886,551,763,680,764,100,707,291,769,57,523,636,377,693,46,460,873,452,124,464,79,230,969,774,478,345,180,449,279,608,170,646,296,720,288,665,843,325,454,741,114,853,15,185,790,88,853,194,58,8,281,885,947,819,335,105,676,513,6,65,582,507,201,267,195,481,139,319,473,754,38,921,474,948,347,580,262,341,963,30,994,606,638,291,522,899,977,921,653,969,547,6,182,540,939,826,659,453,383,731,394,449,387,773,87,342,615,112,592,843,451,525,583,365,811,98,228,491,245,629,652,494,433,490,958,804,561,277,827,47,440,579,714,684,75,105,712,843,914,683,384,949,283,407,133,23,440,820,201,25,756,714,633,251,935,805,919,820,39,863,275,664,341,250,343,507,758,501,22,562,233,554,730,146,514,140,995,757,114,120,502,872,420,372,352,969,949,220,390,697,430,125,119,747,875,973,146,274,548,33,181,290,502,756,361,498,886,522,291,208,453,506,553,495,363,270,660,906,851,165,744,181,660,666,525,184,983,141,147,684,560,328,261,826,577,619,454,302,233,324,569,140,102,76,571,505,863,383,192,785,70,755,892,557,302,416,51,211,55,514,201,888,138,582,400,580,96,448,745,279,361,562,90,119,496,81,975,75,239,429,213,882,199,165,590,413,218,739,241,516,247,6,406,954,376,587,365,754,823,555,59,946,895,249,22,815,720,443,324,739,454,107,329,238,714,646,590,536,409,911,677,222,68,192,140,645,3,690,936,209,132,540,200,639,207,266,172,167,603,589,168,512,671,83,852,825,688,819,829,171,630,706,925,916,349,348,732,704,378,970,9,729,666,928,923,526,606,144,615,275,461,997,947,712,954,778,350,787,325,439,462,596,603,836,2,383,459,35,863,212,260,61,338,912,990,747,257", + "849,11,569,270,501,79,805,249,893,410,160,627,11,390,942,494,746,521,768,373,469,450,223,702,80,303,578,39,778,698,748,884,394,438,161,511,699,990,42,338,851,795,185,253,463,336,762,979,414,994,104,673,834,990,119,671,244,625,527,854,16,702,759,891,326,488,863,868,74,467,984,798,888,173,343,367,571,333,276,832,985,972,591,524,497,474,142,3,459,867,829,935,475,791,970,762,295,120,65,303,281,270,445,459,568,951,482,397,525,755,989,510,147,488,28,636,429,119,352,215,198,723,835,159,844,790,214,295,72,699,819,426,614,280,264,104,201,204,597,698,641,442,342,615,44,66,915,466,630,142,219,639,897,259,771,764,624,29,174,293,327,718,541,303,88,898,182,611,694,994,566,754,785,996,334,866,709,62,811,783,262,880,329,507,741,355,334,506,311,711,671,631,650,329,831,403,109,66,49,271,508,888,380,924,697,791,317,26,950,13,669,595,80,101,764,451,206,53,873,655,466,255,595,76,33,138,892,392,760,224,758,99,819,971,282,880,275,606,306,238,849,305,348,248,986,978,555,690,447,701,645,391,579,777,306,607,601,561,15,904,733,896,926,343,112,862,613,416,152,875,779,554,217,625,850,286,421,821,140,392,11,541,8,813,397,535,145,749,197,491,592,288,931,81,734,904,513,264,462,401,719,258,310,943,385,695,913,54,277,214,835,563,325,988,994,203,771,285,999,268,399,550,219,319,783,859,574,1,39,126,907,870,416,504,870,213,909,484,78,716,424,33,862,331,933,212,394,265,904,756,325,917,848,244,31,566,242,916,63,971,146,550,487,894,701,41,163,686,383,414,912,275,870,714,767,229,158,311,591,749,600,884,211,905,821,558,760,825,155,385,449,436,163,13,707,7,160,295,285,517,975,816,589,676,641,726,327,419,165,627,376,392,49,205,12,896,253,603,584,17,175,453,812,803,211,601,408,923,962,700,656,279,893,204,831,807,487,848,964,827,585,915,358,780,737,461,136,884,635,367,92,801,927,113,287,617,307,537,716,540,987,131,731,91,537,862,713,879,212,469,928,605,111,568,165,208,636,384,599,132,74,881,815,239,179,390,656,603,407,923,6,743,946,654,450,738,827,442,917,316,435,978,202,400,703,0,687,976,967,484,894,2,264,813,843,89,291,591,127,499,490,564,376,668,871,835,720,467,64,619,342,886,365,422,588,518,25,124,625,784,724,989,974,573,99,487,787,617,427,357,477,465,120,759,81,251,651,412,156,738,599,509,836,623,459,721,449,871,546,371,606,141,704,204,17,268,351,906,436,826,651,739,290,609,237,247,212,289,397,158,306,785,851,915,705,116,751,507,103,862,745,408,865,156,951,496,506,985,479,353,548,86,178,374,716,954,598,954,610,680,958,404,47,309,267,318,571,919,916,852,373,948,433,946,63,765,121,543,545,53,8,147,240,672,442,251,323,816,921,67,934,305,472,207,217,54,381,71,702,390,263,737,165,575,958,305,560,884,599,267,44,621,707,335,143,261,927,176,192,761,100,189,2,974,297,488,30,757,634,900,883,250,475,994,609,85,584,476,190,663,746,36,912,25,820,661,489,909,755,108,78,821,48,113,163,286,692,931,877,329,474,445,150,377,876,207,505,782,520,478,238,324,85,742,322,303,419,977,189,580,967,797,745,331,639,700,370,384,784,636,425,6,145,777,816,609,23,797,914,646,328,855,755,232,602,562,875,813,40,226,450,706,574,850,234,803,552,251,630,139,179,427,617,894,92,401,302,203,363,161,448,29,403,561,65,149,14,377,506,972,83,793,310,969,323,62,838,966,475,986,77,656,742,144,427,738,720,97,76,896,153,679,238,185,566,473,292,540,39,522,994,68,667,394,200,797,130,704,666,823,645,158,362,440,440,695,676,263,83,60,159,912,611,325,51,523,54,600,392,488,725,306,33,257,746,122,968,770,663,355,437,589,883,532,377,62,879,801,547,230,893,146,984,676,411,290,387,458,537,657,357,50,319,353,544,235,319,31,243,727,260,55,821,148,721,620,126,774,536,624,726,969,406,975,465,542,696,118,538,541,422,693,302,629,821,68,858,540,213,127,568,77,486,952,590,622,606,394,243,96,211,995,934,341,798,324,723,294,919,224,535,462,38,660,513,883,73,102,981,973,26,829,429,818,955,858,607,716,76,353,87,777,937,286,992,741,476,832,603,728,433,475,432,557,371,688,167,859,284,477,420,664,896,371,786,71,525,61,649,214", + "685,883,886,588,166,226,363,36,121,411,766,738,713,227,589,456,828,848,34,377,426,229,125,681,819,846,985,635,657,282,176,156,636,552,375,661,248,886,468,36,819,212,864,989,321,384,624,478,739,352,597,499,821,769,682,307,247,170,379,395,260,820,819,637,747,241,351,77,250,115,166,282,570,934,366,488,689,33,744,830,143,652,537,348,850,301,800,850,511,233,505,763,522,615,493,84,5,706,861,585,235,408,57,158,268,840,569,207,876,810,824,967,989,902,68,781,677,220,554,455,587,948,118,140,294,189,297,712,967,42,528,174,723,580,125,269,877,866,79,595,708,424,458,637,349,930,898,432,804,161,859,51,318,115,507,80,941,132,765,46,57,339,517,634,666,432,657,661,838,303,151,318,692,192,802,552,297,232,633,220,464,309,512,191,500,613,492,777,72,510,668,480,259,532,805,974,876,258,778,996,984,805,71,223,556,61,959,130,745,863,365,932,569,86,688,893,835,480,815,722,513,149,681,979,817,995,286,218,947,513,161,585,134,61,647,115,125,577,159,354,584,994,867,547,848,288,917,912,836,694,282,917,877,891,183,995,576,40,282,460,391,406,183,581,364,247,713,771,801,54,429,677,238,964,848,742,804,666,159,64,749,880,889,487,262,152,548,361,743,568,952,768,322,688,736,78,474,566,288,272,564,58,674,994,212,536,729,238,375,297,957,576,404,918,45,282,405,987,434,690,985,135,452,57,795,144,334,70,769,813,3,399,120,672,347,82,370,568,320,696,891,764,357,705,415,119,596,64,669,88,661,914,106,697,996,496,247,31,378,708,871,778,763,296,680,543,116,156,716,362,236,191,384,24,959,407,100,449,857,685,374,205,499,331,646,684,916,640,740,262,292,99,724,807,498,254,37,225,391,260,143,851,842,162,827,876,46,536,764,95,67,937,773,371,756,835,733,532,162,177,630,179,11,359,368,926,685,465,681,868,929,518,895,750,791,866,503,876,410,383,283,42,758,95,835,811,5,545,880,811,678,896,897,807,440,780,705,551,651,362,951,405,74,967,172,919,226,596,518,759,604,374,84,338,857,821,301,296,207,727,552,709,404,763,441,130,531,474,526,89,391,98,173,817,516,662,537,961,555,253,430,468,38,799,515,687,0,272,742,752,953,434,539,690,733,187,63,342,875,876,716,263,589,396,428,866,83,904,663,922,37,583,150,449,622,449,8,137,288,634,950,497,25,677,533,465,231,44,676,511,337,550,269,907,883,464,193,526,415,15,583,948,935,3,766,619,882,444,424,355,123,737,556,873,481,353,585,208,958,34,707,995,437,982,543,719,818,635,168,968,441,695,477,9,934,939,238,103,373,129,612,751,255,521,132,455,142,317,947,84,662,369,514,905,615,518,994,764,390,911,961,181,141,254,263,148,668,11,536,995,425,57,953,352,222,976,927,328,841,974,107,284,510,314,633,899,701,629,276,230,311,330,685,982,331,434,584,774,526,430,179,612,120,891,43,633,747,59,901,610,167,520,867,747,169,840,712,827,408,748,472,48,152,973,681,692,20,460,313,688,77,303,978,922,93,775,37,788,283,429,368,94,871,158,566,965,921,616,517,478,161,401,384,712,368,487,934,816,72,53,829,161,393,571,912,422,29,748,110,307,233,701,240,51,285,716,794,624,860,846,718,556,82,881,389,576,787,549,248,935,461,35,732,625,372,752,271,138,378,970,842,237,635,288,134,101,583,364,144,519,855,451,16,289,647,116,66,886,421,818,973,596,330,815,730,188,275,112,292,706,935,346,505,758,200,574,424,234,671,304,683,878,525,213,566,945,670,404,293,7,756,570,89,755,183,132,822,39,432,123,866,288,720,288,379,444,601,455,660,31,629,225,925,39,107,833,391,131,486,580,906,881,377,93,617,238,27,684,794,70,704,451,999,522,739,8,626,939,711,715,475,932,759,935,771,108,624,328,281,92,24,858,906,724,123,948,478,45,373,453,569,637,68,65,256,696,849,991,654,299,145,24,683,510,586,545,17,444,856,300,110,892,88,515,268,12,72,596,394,324,431,897,129,579,526,950,815,290,199,368,748,473,35,606,551,909,90,453,14,992,989,450,740,893,431,671,984,317,73,482,251,735,902,972,880,408,997,221,590,225,300,173,224,247,62,714,508,896,529,674,482,329,595,52,396,717,49,856,539,385,958,30,392,138,904,227,954,342,785,985,225,801,95,203,604,703,135,283,727,401,55,49,486,861,756,702,55,392,542,274", + "956,827,133,401,501,990,333,64,402,77,906,486,601,191,453,835,962,809,401,837,838,728,669,995,639,943,557,824,720,10,151,25,807,296,253,246,45,377,610,406,904,25,747,422,494,487,731,469,835,575,696,737,390,183,552,923,974,24,905,709,600,764,218,875,907,895,502,636,258,70,311,480,872,446,849,280,451,508,446,555,578,473,486,775,915,316,75,219,985,839,581,583,186,477,647,409,272,439,76,92,595,51,96,951,934,302,679,971,433,338,321,620,738,972,831,519,40,939,807,945,750,643,167,681,592,618,662,527,935,150,376,201,481,593,55,498,631,952,306,337,621,736,459,39,436,58,481,528,675,900,895,446,7,910,792,751,854,222,298,629,208,506,779,709,32,465,850,105,386,552,701,401,842,513,422,552,149,156,125,549,458,972,861,139,716,149,217,757,517,796,510,947,427,840,747,83,725,551,876,654,877,575,626,439,134,799,257,367,232,969,740,839,116,676,403,110,218,725,781,787,434,26,225,330,837,881,173,533,774,364,493,748,339,40,269,153,271,713,52,517,710,684,550,14,621,280,18,989,783,4,715,996,446,489,58,802,14,965,275,146,906,79,251,104,220,598,990,951,284,757,263,421,765,416,526,869,162,671,464,830,569,647,328,905,499,439,501,49,280,280,539,506,121,787,856,789,684,539,891,753,839,60,205,415,629,468,389,187,979,323,522,525,897,2,124,984,141,394,128,221,425,253,682,215,295,750,502,599,3,681,693,343,861,61,824,931,955,629,603,58,379,427,557,599,729,883,696,216,584,915,443,807,190,259,265,870,982,908,318,436,120,330,15,148,461,62,208,739,190,256,704,176,865,845,799,685,873,113,945,106,687,171,349,969,566,609,587,276,849,549,76,151,625,86,350,83,604,816,195,827,943,174,193,79,786,469,509,820,112,511,788,631,529,648,539,679,862,751,701,799,448,128,338,523,478,838,966,189,84,958,923,870,399,49,79,161,899,16,276,527,442,647,934,901,304,146,501,824,494,802,525,209,515,661,444,987,478,553,417,193,667,355,861,28,331,104,431,680,72,454,969,690,316,465,321,276,815,515,412,305,834,605,179,24,461,537,57,100,670,244,524,589,833,789,370,388,36,498,581,966,798,106,492,831,886,976,272,0,68,408,565,311,29,364,697,890,50,692,215,115,856,194,574,331,693,818,226,948,634,813,681,249,134,141,878,473,228,857,370,340,946,363,19,740,850,645,251,714,68,57,614,327,520,823,7,250,348,549,915,272,283,569,879,575,403,520,430,613,682,327,9,550,421,800,558,93,322,139,525,116,220,883,623,474,100,429,392,916,652,641,664,613,850,106,499,527,981,628,355,678,294,904,916,889,128,682,905,64,983,383,115,790,28,783,693,378,891,697,470,409,693,588,995,62,215,129,815,940,954,308,365,273,640,55,747,71,180,788,329,501,986,130,471,251,168,585,72,124,405,370,208,158,865,742,684,230,434,767,891,293,606,182,888,145,594,3,266,166,260,73,531,257,29,668,733,112,976,35,294,264,445,292,27,347,718,909,218,568,242,644,470,885,294,43,456,979,312,233,319,815,564,286,66,380,871,806,459,4,190,691,375,552,498,829,186,206,419,275,716,487,115,607,681,892,551,401,505,121,793,524,776,329,658,938,469,933,110,183,146,929,633,603,879,14,521,258,862,192,424,463,675,642,38,62,650,438,165,923,112,924,218,817,83,51,49,140,165,588,510,387,45,224,815,774,829,355,475,304,984,607,289,774,177,13,319,228,523,133,810,25,857,53,132,820,116,569,670,529,743,565,885,836,468,479,609,923,628,368,664,683,927,297,523,474,730,274,892,975,189,742,222,259,860,826,390,239,541,142,938,779,195,685,294,734,12,587,175,421,791,759,897,972,898,612,926,567,968,378,172,714,687,674,200,581,462,334,396,862,208,142,568,586,111,346,645,95,312,981,585,119,764,259,272,414,365,529,31,701,789,981,243,569,338,587,620,789,908,356,763,815,315,284,201,990,426,666,299,577,249,651,654,141,734,851,16,620,762,585,325,691,790,642,137,877,701,541,839,867,802,330,864,362,187,191,162,693,773,912,851,681,137,787,469,38,621,55,82,227,194,241,878,800,673,347,542,50,474,514,644,489,903,533,855,411,789,444,720,866,571,893,814,74,954,512,305,759,469,92,222,298,255,676,62,220,425,454,472,517,536,283,384,276,387,142,715,831,361,874,456,102,898,490,139,415,362,193,903,388,672,151", + "834,723,47,704,87,395,577,734,932,203,475,281,402,157,269,454,63,334,475,362,928,922,870,343,455,845,689,383,956,557,496,798,633,302,510,642,681,228,665,597,221,581,434,141,190,400,287,255,713,693,338,985,122,854,508,20,884,917,998,202,944,806,857,959,35,857,801,415,442,460,34,438,782,67,699,473,742,676,734,330,876,290,792,754,275,171,324,767,665,859,129,372,560,352,447,951,208,316,967,126,117,221,615,461,67,616,16,596,633,403,928,317,861,422,175,32,883,268,930,666,11,13,303,952,540,307,712,559,788,795,584,952,619,879,351,915,60,395,62,597,271,184,476,879,527,865,163,571,934,775,129,641,918,304,524,546,235,272,833,47,676,62,726,69,406,646,179,152,893,173,727,887,676,123,419,729,21,177,4,933,671,965,629,633,422,682,141,750,3,675,282,450,741,947,655,24,455,771,588,538,475,398,41,742,931,734,801,585,398,387,939,462,375,704,9,610,549,238,854,338,16,262,121,403,236,499,134,606,429,217,587,855,100,223,80,670,771,214,252,608,22,815,737,565,422,879,673,599,181,492,372,27,282,733,368,490,676,251,54,146,316,133,285,395,834,249,519,535,906,471,828,689,906,683,483,11,631,896,596,314,990,903,455,85,975,117,985,667,846,917,256,417,6,404,265,981,175,655,324,893,812,291,790,197,925,907,431,479,410,590,84,641,309,284,941,115,189,336,658,370,63,668,548,978,831,440,256,970,255,716,475,721,722,349,313,773,292,313,3,422,367,219,723,766,68,704,664,607,237,422,747,160,332,17,944,813,76,538,858,90,378,911,453,98,636,166,165,701,638,124,216,860,896,243,415,116,972,261,642,897,469,459,139,970,79,585,733,847,244,82,112,846,912,618,223,88,466,304,649,447,971,131,324,517,66,618,673,511,839,240,365,314,541,209,427,640,713,998,872,148,478,464,842,140,494,111,967,123,350,836,497,38,481,424,152,427,75,675,567,42,602,139,60,98,625,776,248,66,901,480,119,756,929,439,523,729,781,598,305,564,982,139,31,669,609,89,720,210,950,37,58,301,763,78,505,740,259,239,613,956,151,884,580,210,175,515,858,117,423,326,456,698,6,774,834,954,103,417,234,802,930,219,206,24,407,967,742,68,0,269,602,270,504,720,796,156,458,851,336,522,435,361,605,128,145,303,461,922,478,650,384,539,547,461,633,409,798,217,430,834,41,495,865,468,323,200,113,899,545,286,410,574,15,709,144,214,495,585,28,850,948,64,64,180,136,111,400,204,105,259,103,799,914,126,159,129,51,199,62,394,355,262,89,581,725,765,842,554,437,925,815,510,988,714,785,208,161,731,135,851,56,596,464,912,509,759,437,220,464,272,826,408,912,100,384,843,855,370,848,711,521,684,505,375,616,778,353,464,45,77,594,182,340,806,280,826,952,815,122,181,845,119,218,983,456,376,379,310,821,266,783,571,122,922,33,907,843,270,770,184,927,976,8,769,200,690,167,335,411,194,174,675,40,656,843,430,631,423,13,256,362,943,526,603,474,506,869,999,810,292,12,147,125,371,333,409,609,85,673,146,717,591,906,723,328,646,399,180,482,991,300,359,142,992,20,717,594,107,372,373,323,695,190,495,741,830,704,67,581,64,343,616,895,573,889,400,506,118,150,171,164,154,969,314,355,550,738,819,956,466,635,342,80,842,610,330,183,597,554,323,196,447,936,547,922,606,46,118,776,800,611,722,389,951,338,57,859,505,491,565,362,592,9,227,346,449,78,626,882,385,162,142,461,955,170,344,932,746,535,99,50,50,860,515,809,100,167,218,923,299,480,687,711,729,441,45,590,300,597,865,588,250,902,514,734,957,898,761,628,161,578,577,736,173,444,325,21,438,930,248,970,672,829,986,866,331,542,548,351,154,59,633,203,561,176,193,343,676,879,104,910,405,567,58,67,116,568,470,450,943,858,704,275,30,726,482,841,526,367,675,194,57,345,183,444,446,938,435,465,383,720,775,523,258,793,580,582,297,785,494,892,816,893,845,449,228,163,441,948,652,901,523,509,736,294,617,358,144,264,554,466,730,196,297,938,896,377,929,665,500,350,789,660,489,651,921,548,971,275,770,894,855,915,988,500,736,626,717,419,311,259,657,612,448,195,509,60,96,1,489,421,764,788,120,722,985,839,811,181,13,445,873,5,871,454,48,721,475,531,953,558,900,651,310,436,238,499,603,887,160,464,482,486,625,813,501,24,702,977,256", + "676,884,370,258,268,307,154,534,644,991,725,897,589,208,158,190,61,87,511,468,57,360,674,66,413,701,219,234,57,932,90,302,189,690,732,527,575,255,188,48,728,678,923,621,209,510,293,635,23,153,686,394,148,123,913,16,790,139,971,841,452,469,805,388,624,436,627,91,901,907,961,771,729,82,564,398,456,435,851,896,190,266,400,661,794,756,45,326,427,638,290,914,383,641,770,773,597,356,247,91,615,111,580,495,207,999,419,301,39,622,983,403,174,927,718,401,427,833,476,511,973,313,657,948,954,644,957,138,528,556,387,703,823,771,44,824,376,265,718,378,484,49,618,977,89,760,76,436,900,226,145,747,524,280,577,667,303,161,35,913,675,756,427,145,620,696,782,505,683,839,505,615,662,633,547,662,220,126,952,25,707,166,370,56,800,175,610,738,499,165,27,885,838,262,197,798,834,347,745,379,977,523,772,905,914,179,86,954,520,499,883,699,280,584,540,352,928,12,632,285,649,319,984,201,199,732,277,379,720,784,4,10,263,463,740,999,145,851,883,962,876,845,759,865,451,922,366,602,474,590,790,679,862,532,120,702,848,197,764,407,993,304,945,236,2,923,127,496,413,738,58,60,38,464,218,662,306,749,864,805,929,243,954,27,15,895,627,796,592,361,311,33,677,372,674,442,676,276,588,390,116,181,906,498,186,542,559,824,42,474,776,464,690,819,41,221,440,860,837,902,169,178,687,318,123,583,572,995,340,467,122,387,680,221,784,401,275,583,491,754,980,256,508,227,287,305,341,506,760,817,852,811,673,313,330,976,864,497,947,969,451,294,294,928,831,5,756,708,755,65,654,984,838,511,24,461,391,452,476,962,769,912,366,487,241,913,113,144,565,854,74,355,831,281,393,44,958,590,739,188,586,971,172,932,996,416,275,824,473,784,501,571,784,700,630,565,46,233,306,740,510,760,476,448,869,105,463,780,520,638,403,654,534,57,973,817,329,768,405,273,567,665,129,845,930,470,895,526,324,728,42,504,988,729,904,399,48,438,264,930,746,808,613,198,281,702,131,876,536,267,26,671,862,130,124,236,690,322,838,841,5,809,400,447,905,16,670,112,554,84,124,514,186,815,693,544,953,326,385,777,948,261,350,745,726,484,752,408,269,0,481,242,134,219,871,278,87,484,251,607,826,268,82,654,355,487,380,912,216,743,160,887,391,114,693,447,510,698,910,532,178,678,626,506,99,751,645,991,432,414,159,728,188,212,961,323,395,704,558,113,53,625,709,450,368,487,117,175,729,25,675,790,928,769,462,495,829,215,995,337,206,794,392,623,220,454,305,367,522,257,827,624,744,697,538,806,131,585,995,702,334,596,678,366,109,433,455,627,55,170,390,148,884,50,940,943,441,550,606,206,273,22,275,465,475,810,390,643,394,844,66,518,848,792,820,55,362,11,390,603,35,351,45,125,465,174,163,452,153,462,944,658,563,923,732,825,193,528,886,65,228,110,9,6,706,19,742,453,328,190,17,680,878,596,865,561,529,802,723,957,976,602,686,593,864,95,141,848,413,154,443,200,254,321,640,986,643,593,331,849,389,433,904,960,83,362,721,738,536,844,941,630,906,460,580,914,769,994,432,370,459,340,367,822,925,170,629,945,777,708,699,854,247,288,690,544,686,962,935,48,87,777,623,444,194,252,414,39,220,198,809,603,542,397,225,23,920,549,100,724,235,140,262,938,968,406,342,489,637,165,442,405,771,669,264,183,378,378,921,478,670,330,741,114,284,244,597,625,602,458,417,278,189,613,101,161,857,586,349,983,234,594,658,56,146,575,555,636,364,29,201,733,129,108,216,843,987,902,104,188,111,968,983,543,272,866,958,35,76,462,694,939,328,928,246,403,942,117,664,408,819,229,560,144,335,1,615,213,349,58,145,946,436,914,246,354,261,980,555,407,79,567,649,741,198,672,844,940,203,632,201,579,195,800,143,784,221,812,976,817,912,747,77,457,811,98,335,397,736,64,890,106,322,942,797,154,336,823,393,292,547,356,721,591,391,868,51,723,242,55,801,346,414,615,950,310,189,811,234,445,435,223,194,402,993,956,69,547,566,304,398,946,751,973,178,285,985,550,921,175,55,113,227,735,457,246,341,675,769,511,822,606,28,935,104,582,939,272,685,170,544,193,812,502,631,738,732,72,418,190,120,836,660,294,733,372,61,354,940,272,325,812,784,797,628,435,636,730,939,818,165,489,657,446,779,545,158,990,266,226", + "28,670,801,575,363,630,471,8,444,625,906,858,23,708,463,697,342,579,519,704,460,584,711,125,218,542,977,450,526,44,700,432,813,570,489,296,314,489,238,61,187,179,155,362,841,910,642,552,407,526,474,65,540,537,615,655,407,592,71,260,330,993,196,691,841,268,100,714,726,667,274,971,828,630,381,576,702,410,611,382,546,232,607,204,306,942,686,568,88,735,177,143,442,816,798,901,690,128,219,700,107,27,743,781,468,18,953,40,639,667,623,301,468,529,47,548,895,560,762,662,209,362,670,953,566,604,904,636,755,206,444,137,280,323,799,704,777,889,102,951,761,260,336,538,336,46,653,119,781,28,79,425,657,667,524,820,97,219,547,796,133,211,564,687,121,343,64,93,186,76,417,26,94,986,337,771,138,178,746,29,412,748,181,367,619,840,841,264,548,318,406,30,517,24,273,150,664,941,247,286,774,310,670,703,416,499,36,362,607,293,261,807,352,137,85,219,559,569,169,983,937,351,588,298,346,601,413,28,457,149,638,716,909,45,779,359,412,650,253,800,583,371,222,719,190,445,915,577,640,102,601,969,184,239,472,371,710,377,518,230,104,895,84,30,112,94,211,946,224,458,965,128,593,634,204,517,712,288,812,983,583,933,341,355,267,781,638,134,942,100,705,908,644,690,132,835,579,299,254,318,462,918,370,498,600,923,703,76,155,18,892,250,22,564,462,511,538,914,632,306,185,988,887,165,208,587,890,71,616,514,597,989,182,737,26,206,867,346,375,749,905,208,24,453,883,122,643,910,143,1000,529,234,625,784,721,546,679,747,280,98,137,529,197,555,269,640,893,887,383,342,484,798,636,447,732,592,471,123,888,127,99,287,742,197,909,971,737,782,389,431,262,579,226,332,410,921,428,215,612,579,561,47,94,505,515,312,99,773,502,507,359,471,674,291,420,827,848,714,541,219,675,967,79,346,672,946,44,526,883,165,553,79,548,546,608,293,691,357,61,145,198,232,849,974,599,551,549,434,465,219,426,770,630,219,737,538,447,213,334,142,662,253,411,715,835,772,97,858,531,531,472,260,729,991,362,340,832,881,737,211,327,667,774,952,988,734,107,486,736,127,473,125,175,269,856,424,527,399,915,490,61,887,432,317,29,894,953,565,602,481,0,937,294,871,547,228,784,998,421,639,760,589,68,401,27,674,28,779,242,160,936,1000,581,964,670,57,450,104,57,367,239,963,49,971,97,749,255,823,367,602,513,559,683,133,158,664,810,654,720,893,257,511,890,507,312,96,727,983,989,912,362,838,432,16,224,259,537,692,157,423,416,59,115,481,916,239,64,632,16,615,685,133,453,953,280,917,449,682,475,536,788,982,422,369,400,830,768,571,470,24,640,493,427,590,909,536,892,456,801,616,42,143,456,707,858,285,647,613,219,594,907,348,188,219,50,856,426,822,860,228,865,362,810,169,252,328,267,40,606,881,583,218,406,309,73,945,705,845,464,805,738,964,755,137,336,905,808,466,957,654,618,332,121,520,910,45,727,286,557,226,919,756,781,652,384,958,828,96,474,216,156,614,405,543,861,417,71,992,612,433,780,527,555,253,682,314,792,199,76,795,939,411,291,586,160,98,82,227,865,494,317,152,272,158,452,390,801,724,784,962,962,382,351,390,279,856,72,859,753,550,564,40,56,665,2,186,833,986,712,800,510,699,14,607,375,810,443,370,492,374,854,27,225,846,399,850,131,774,713,295,942,972,198,192,489,970,22,892,235,481,376,703,615,558,534,819,313,146,232,306,251,725,652,285,292,348,611,414,123,329,186,766,284,456,327,775,40,586,353,668,251,478,5,367,675,942,869,66,948,787,659,848,458,184,790,993,902,989,767,996,473,671,695,785,695,653,832,382,193,926,749,488,951,422,833,114,612,897,296,248,183,113,971,26,591,671,653,794,122,997,970,430,631,259,74,828,517,839,953,526,140,958,428,674,523,33,805,573,612,904,351,865,507,178,1,849,342,486,796,778,542,602,640,372,254,865,748,596,296,659,651,430,761,843,898,978,649,971,33,327,333,691,175,452,452,817,942,260,514,75,652,26,423,759,714,230,470,142,820,430,89,553,600,295,302,510,333,660,587,186,485,991,779,573,603,327,625,499,619,581,404,298,189,51,895,201,224,990,462,741,248,688,592,818,544,349,446,891,395,953,325,674,282,533,102,69,461,354,433,246,487,104,554,445,250,490,59,589,213,789,487,283,780,87,114,201,8,19,748,297", + "533,129,455,407,134,279,906,291,352,843,948,566,810,670,987,473,837,245,644,59,408,107,976,131,132,670,765,382,264,763,437,640,588,927,298,886,405,42,395,925,297,858,642,707,413,700,366,525,73,444,232,287,217,549,3,213,294,908,909,606,68,584,644,318,188,813,779,58,891,311,8,569,33,501,999,510,730,612,709,118,941,554,970,730,151,51,819,784,972,492,852,939,443,120,253,394,792,529,668,461,553,11,487,380,895,433,501,791,690,476,756,640,959,134,351,72,912,800,725,254,553,656,975,159,163,788,936,768,724,935,56,95,269,439,250,390,355,99,334,554,470,355,699,687,273,992,728,68,770,134,990,819,768,652,898,732,518,599,360,978,504,729,874,898,573,661,818,430,509,560,787,799,365,506,621,641,431,716,643,204,779,883,774,257,207,479,213,247,672,685,375,931,595,353,376,376,555,79,83,62,196,464,946,268,420,913,409,78,309,638,514,827,283,326,623,842,394,884,238,565,359,690,624,807,967,529,920,66,642,713,799,63,695,377,658,211,562,407,667,874,681,18,715,391,807,515,94,33,142,445,859,37,962,359,565,368,9,650,652,440,798,258,701,689,342,239,120,518,433,709,256,546,160,826,960,322,865,16,852,946,581,729,735,714,595,799,432,68,150,921,749,849,902,520,172,554,697,711,984,229,459,161,347,884,277,612,618,9,970,747,724,516,836,218,878,969,155,53,64,614,273,974,391,859,981,47,782,851,643,64,670,539,953,610,630,509,905,930,596,342,485,301,798,68,90,716,299,40,595,429,849,978,293,414,353,486,377,474,716,386,342,94,550,84,39,684,422,143,925,22,296,747,770,690,132,239,310,767,949,303,672,136,151,494,531,689,123,247,473,91,8,556,301,418,183,698,542,37,453,131,990,371,210,575,59,276,998,307,99,63,95,173,316,374,836,892,758,792,673,113,50,598,480,165,92,532,932,707,791,393,876,292,742,4,622,765,554,865,63,262,287,264,853,77,816,21,57,805,283,999,227,626,449,989,419,560,760,641,687,354,890,733,101,199,553,449,650,833,24,572,207,653,886,413,545,25,268,768,807,778,439,244,157,721,501,121,658,16,199,55,963,882,948,721,237,860,953,255,673,649,197,234,990,699,833,2,434,311,270,242,937,0,995,176,681,577,43,983,117,832,629,252,582,880,619,994,331,909,879,893,729,721,993,591,326,852,501,698,164,898,938,853,284,694,566,460,412,393,317,8,290,822,636,826,526,888,565,229,80,795,297,696,969,184,340,112,171,564,976,543,357,202,716,858,645,428,339,443,974,154,832,237,952,761,158,829,13,97,762,640,268,913,249,555,125,555,130,229,566,359,929,515,341,649,250,495,265,68,27,540,846,598,844,537,578,276,57,399,945,107,886,722,486,925,892,312,668,863,283,911,522,787,265,352,569,942,155,840,814,365,488,380,759,240,431,517,30,865,67,16,268,438,116,785,342,33,56,448,967,922,308,841,782,338,217,69,57,321,316,721,48,365,308,489,856,826,742,300,705,82,12,106,932,650,539,509,512,352,298,2,10,71,189,430,340,595,845,101,762,443,778,565,319,343,319,460,419,606,766,524,625,571,474,892,405,267,989,818,428,942,407,14,284,2,12,37,279,194,607,679,186,609,20,142,296,557,933,602,99,703,640,673,149,266,702,477,407,911,850,755,64,65,939,458,681,72,108,144,785,24,555,169,467,791,949,884,996,184,183,802,529,256,690,935,682,91,591,223,691,94,592,556,906,135,146,246,49,262,216,107,969,124,147,731,806,24,323,125,876,33,46,26,998,235,467,628,411,339,461,223,729,264,424,225,380,285,434,977,699,300,147,761,442,844,923,434,319,239,232,347,581,330,657,40,974,635,327,522,79,540,528,692,160,384,475,616,150,896,601,330,722,735,666,130,33,405,707,909,602,966,259,712,549,312,895,547,611,973,718,236,352,920,288,515,960,852,456,839,663,985,59,601,194,604,985,706,371,115,679,14,470,66,291,268,197,219,320,976,389,787,569,700,763,1000,842,737,610,69,312,844,489,924,224,276,792,741,549,778,340,840,486,473,959,555,396,428,933,64,675,936,228,234,781,516,647,232,638,107,573,125,573,347,771,807,922,371,767,221,887,173,363,536,974,336,598,171,876,634,424,438,477,816,760,58,380,118,728,87,750,925,964,837,944,400,217,928,728,596,693,57,83,238,486,315,859,583,937,667,244,360,177,863,142,24,621,473,769,551,924,293", + "256,831,849,823,415,938,921,254,652,538,145,569,440,742,353,499,586,2,443,136,403,425,507,263,13,765,189,684,925,326,723,914,842,586,120,414,478,709,152,839,979,362,153,940,269,704,485,221,529,954,439,417,655,913,955,851,750,855,803,442,645,124,442,541,345,55,498,822,325,338,552,983,294,665,628,117,743,173,696,630,578,909,45,881,267,829,999,718,751,851,440,616,325,397,790,345,628,573,355,698,315,657,970,585,36,150,725,206,814,76,721,23,283,188,489,517,142,131,130,730,848,107,805,640,190,3,338,508,274,317,593,810,809,695,788,971,352,797,208,746,384,652,675,603,524,620,962,987,874,909,272,574,772,22,461,964,133,296,162,161,81,941,5,839,355,578,257,69,484,702,526,193,494,67,968,821,11,10,75,462,67,347,244,398,411,231,425,373,285,225,387,668,40,992,896,945,227,752,189,492,856,420,917,420,195,960,430,594,977,883,720,280,928,740,95,323,449,112,58,933,332,166,706,479,244,442,197,510,779,386,741,187,613,883,813,733,634,120,908,685,952,622,88,223,61,476,326,283,852,524,783,169,154,241,475,87,720,192,743,267,487,99,113,261,935,667,864,967,845,616,42,333,105,505,492,173,625,191,753,62,761,544,854,642,997,855,556,533,75,263,990,682,421,640,401,666,735,552,513,952,582,871,334,958,9,742,883,101,756,206,307,477,849,473,373,137,185,707,968,147,890,664,412,284,423,919,632,152,828,730,627,143,81,344,356,381,173,768,270,114,679,989,431,170,963,518,236,513,758,569,423,401,26,305,575,442,969,323,563,123,411,235,747,445,648,73,674,359,992,623,739,118,888,84,585,345,124,476,376,436,352,836,343,367,268,103,894,666,841,331,74,838,797,829,921,508,210,461,707,507,380,104,866,312,424,778,309,984,118,930,382,403,705,196,739,325,494,965,931,952,491,973,49,914,53,417,678,370,711,368,22,810,733,222,617,891,241,540,40,406,764,643,674,567,120,600,724,995,176,376,80,199,253,86,678,517,440,476,237,329,939,252,827,707,65,347,476,271,608,630,761,496,748,281,629,511,316,42,438,205,383,53,235,579,385,308,318,563,586,968,348,130,735,860,676,530,192,792,810,430,592,927,800,992,923,264,539,29,504,134,294,995,0,767,572,993,931,420,17,439,709,538,586,284,529,540,828,716,866,792,535,863,475,257,122,268,576,14,813,539,595,709,524,78,895,879,915,264,174,314,361,724,426,416,71,60,225,489,857,962,284,217,665,46,617,62,943,259,669,836,378,589,929,185,723,950,292,449,707,910,478,956,786,553,8,772,387,978,779,761,144,670,325,212,800,644,828,756,874,66,18,64,586,106,546,730,883,45,267,107,694,490,231,614,905,381,649,282,312,983,823,583,566,492,377,751,65,865,797,313,430,197,713,445,178,691,962,669,399,328,788,605,764,10,666,61,668,221,788,990,158,735,102,494,837,898,649,120,776,220,998,488,40,910,273,202,673,656,659,793,506,647,336,470,831,681,221,291,810,152,497,118,336,697,668,682,330,34,979,562,790,869,448,810,216,652,730,918,517,397,337,340,352,921,764,296,615,867,664,802,172,149,731,448,375,466,261,14,248,793,806,156,540,806,487,276,540,228,904,472,474,645,342,79,886,796,922,225,562,168,968,632,441,637,750,690,973,591,386,261,524,375,274,43,764,607,215,62,760,347,598,532,698,962,147,679,13,207,594,578,291,183,987,9,95,253,131,639,166,39,309,464,692,755,505,581,826,856,867,770,261,299,810,453,199,151,929,761,729,234,694,368,102,533,978,276,894,955,191,673,199,740,356,853,881,865,824,715,646,307,702,230,408,942,650,902,532,436,110,363,793,131,792,542,912,351,256,913,928,395,668,434,131,959,761,844,530,291,834,248,883,634,646,830,985,521,458,499,97,984,221,990,731,454,21,459,448,874,456,833,237,702,742,602,213,865,533,593,913,404,214,343,642,936,130,794,521,695,745,617,192,403,780,304,604,388,130,346,760,548,915,871,399,12,551,876,756,194,340,307,683,664,985,49,494,372,458,784,27,166,353,287,774,868,379,819,172,34,551,845,266,664,419,850,658,132,677,505,254,297,817,422,555,81,614,89,955,183,798,700,237,447,223,189,405,885,358,691,803,99,311,354,483,137,454,105,733,410,779,606,198,314,211,837,906,324,861,836,761,908,989,212,507,232,76,959,163,575,506,514,559,744,890,488,28,893,158,51,752,920", + "904,500,326,406,175,203,504,471,525,103,128,834,126,219,581,987,807,243,803,190,748,45,32,228,178,545,480,309,647,892,272,458,580,202,885,44,365,648,61,641,662,168,614,356,769,346,718,963,101,287,790,814,462,97,124,193,488,152,527,290,180,294,55,191,251,751,939,440,155,37,214,112,368,848,188,417,229,504,125,907,274,877,488,464,100,715,742,856,279,583,388,880,571,55,719,281,326,263,371,114,193,171,528,879,141,292,7,22,597,201,122,614,203,446,75,486,254,503,886,801,565,35,540,244,416,518,345,642,677,879,216,694,840,664,546,172,448,803,709,88,896,627,605,62,697,942,539,107,422,485,892,228,176,730,544,828,646,772,781,751,743,603,987,209,256,979,763,950,636,77,515,782,508,560,448,811,911,474,800,384,81,616,514,940,602,64,29,961,992,874,931,147,714,837,737,146,688,846,585,825,916,349,387,981,29,529,641,921,772,360,417,539,679,830,937,812,536,495,664,211,760,569,112,114,160,889,337,117,993,231,364,448,697,332,930,447,688,916,762,526,779,404,376,34,674,622,690,605,382,924,566,747,997,47,903,825,493,407,341,414,543,611,141,67,670,848,856,817,784,816,863,684,722,139,107,548,915,979,102,563,247,286,176,720,665,444,957,503,491,430,151,158,431,745,743,832,122,786,174,455,372,64,439,952,792,705,641,902,707,758,661,796,149,40,333,527,174,194,589,298,37,796,12,866,26,645,74,623,142,947,637,642,895,647,70,956,116,990,37,308,528,719,422,920,751,35,86,867,734,810,626,211,995,309,349,680,666,792,346,928,446,972,156,509,499,61,166,301,158,680,546,328,844,770,715,717,552,338,205,214,725,857,141,23,941,661,977,535,870,283,726,421,172,658,178,519,666,365,285,431,511,802,46,809,617,261,575,807,848,262,196,584,319,901,757,666,697,891,282,230,975,269,902,188,724,804,61,672,524,215,296,3,480,891,281,217,277,141,550,184,996,747,315,829,196,128,957,267,735,978,942,445,582,171,339,45,615,918,151,102,133,198,369,355,821,930,15,555,832,43,151,504,789,910,391,281,905,740,74,361,839,938,187,268,823,683,339,890,337,299,686,686,360,71,241,393,248,442,787,378,388,363,46,233,172,813,690,364,720,219,871,176,767,0,207,610,547,836,702,954,90,892,123,667,408,138,496,222,911,14,981,370,955,196,280,623,257,627,476,153,24,892,546,173,823,371,265,715,99,251,758,812,167,443,53,425,467,503,711,130,928,841,224,819,741,360,710,492,584,228,579,613,732,367,703,535,271,835,135,156,771,530,829,956,588,878,425,574,5,668,373,847,378,407,82,469,851,461,318,181,177,587,684,131,159,30,799,29,10,826,286,14,74,350,870,619,70,95,107,754,472,105,783,715,972,193,77,970,629,286,898,198,989,393,871,535,268,58,594,826,736,876,311,37,248,915,990,558,689,34,396,954,266,437,362,936,124,428,111,615,110,150,57,974,230,845,183,155,343,431,936,743,739,707,479,880,889,531,816,66,739,904,483,401,624,392,442,926,978,133,401,812,202,334,231,362,527,242,271,89,271,635,395,181,815,484,908,51,851,319,648,933,714,434,472,831,570,121,143,292,70,691,811,632,264,813,683,881,742,807,164,163,51,376,663,494,863,413,943,276,26,572,648,180,649,584,4,723,438,241,774,572,270,83,449,533,527,291,330,510,327,540,825,784,811,533,747,885,819,121,211,974,387,226,601,667,506,924,44,506,857,697,295,459,631,524,514,997,667,632,30,857,570,344,898,891,746,212,98,978,529,663,707,532,550,700,169,52,513,190,337,911,290,179,242,108,626,748,879,259,865,568,86,104,372,144,616,206,178,614,88,465,169,892,133,54,237,71,776,111,350,997,129,73,194,135,850,405,300,246,922,742,420,228,768,928,359,579,496,26,113,925,226,894,446,848,93,990,182,287,422,294,905,193,224,475,210,21,259,276,274,734,762,465,491,842,921,87,354,761,332,286,786,36,749,48,12,232,380,846,112,511,781,982,560,454,99,654,317,507,673,723,211,566,589,107,711,325,501,81,218,995,189,266,656,811,783,861,442,285,627,539,790,735,991,766,337,51,943,826,266,821,292,500,115,655,596,583,690,790,947,123,472,695,307,72,329,656,286,751,70,79,110,374,773,351,694,601,688,704,147,753,871,53,922,412,785,168,961,537,14,864,700,479,153,30,224,944,914,978,838,68,644,528,727,809,560,623,701,272", + "606,422,32,50,483,728,752,879,215,736,281,860,430,755,448,704,190,306,359,843,715,243,339,148,815,716,811,622,612,557,943,172,332,28,481,649,291,267,97,108,460,504,316,929,158,686,836,45,852,358,658,928,187,763,281,724,989,481,721,536,151,408,877,888,911,89,590,889,300,153,952,498,286,860,165,289,64,560,494,28,604,136,178,800,827,940,948,213,786,103,140,390,89,846,608,746,480,361,987,994,920,906,690,62,502,197,220,813,19,991,470,199,370,186,362,80,717,855,123,950,609,58,104,808,860,149,238,760,49,935,660,739,241,656,943,3,352,128,323,23,586,856,898,407,584,252,769,844,787,503,624,801,626,785,738,529,706,951,895,63,476,296,674,139,125,665,831,832,840,202,453,253,695,865,396,206,623,664,378,396,361,547,886,35,823,59,556,34,759,263,832,229,731,987,885,514,920,9,12,966,616,577,247,226,928,961,812,426,577,969,384,342,824,208,333,537,112,820,42,584,259,938,413,127,924,863,268,227,877,82,350,808,494,424,806,421,283,723,874,270,526,461,69,812,485,945,282,806,770,193,100,828,949,75,126,90,222,842,512,700,807,245,887,469,23,826,775,452,937,818,289,110,665,274,915,600,114,905,763,957,150,173,937,124,406,71,87,235,63,855,927,947,797,994,913,939,759,806,203,189,80,760,67,718,563,294,341,920,656,335,704,477,901,772,226,503,585,426,959,936,410,538,968,524,550,53,301,987,297,419,906,214,962,495,847,866,266,786,363,559,804,822,89,413,828,757,46,181,524,147,813,292,158,542,86,60,307,257,555,631,684,289,829,518,196,302,777,1000,630,951,675,984,225,494,65,43,889,560,867,40,256,9,183,248,863,89,442,444,112,809,931,562,87,559,295,932,680,354,105,642,386,225,330,78,693,410,973,381,349,756,175,322,38,741,60,991,927,277,349,726,559,821,312,625,280,650,507,312,184,652,731,806,95,298,571,941,986,207,176,543,623,209,225,742,853,201,920,946,887,115,800,524,508,661,126,481,914,53,797,846,780,505,832,673,760,887,335,135,541,432,513,1000,340,5,613,332,947,691,531,869,86,598,409,47,47,478,667,976,705,285,216,536,952,733,730,553,237,824,125,532,423,143,97,419,600,843,733,697,796,871,547,681,572,207,0,333,392,947,883,662,738,790,663,556,119,217,310,295,91,119,962,307,89,752,311,334,222,687,929,650,237,999,559,529,539,660,502,218,693,148,144,121,238,427,437,441,505,229,935,70,295,871,441,304,344,807,682,280,746,915,669,262,107,870,327,965,440,57,709,550,359,885,528,166,852,450,494,234,154,468,843,874,414,12,895,178,301,526,993,225,708,381,679,800,206,99,630,611,878,505,189,466,100,768,854,168,698,230,975,555,283,531,733,252,82,443,587,821,799,889,14,662,934,230,593,332,572,92,982,272,755,940,696,812,105,27,518,482,868,916,202,346,444,155,344,773,34,894,819,204,567,259,852,826,727,919,888,196,133,583,858,424,783,988,672,433,650,147,456,974,288,13,85,18,611,233,479,629,769,682,351,515,342,132,626,163,198,178,682,118,666,195,92,875,991,793,588,819,935,410,895,133,899,328,286,780,854,615,211,963,50,558,550,11,168,393,626,641,388,339,821,79,246,168,146,208,145,69,885,503,708,210,171,564,206,744,191,836,466,582,78,149,243,232,852,902,961,574,320,885,265,51,947,797,388,251,15,383,843,118,872,101,525,686,692,21,479,69,657,880,183,75,779,373,862,666,765,95,569,904,708,85,360,304,424,528,87,684,602,179,784,493,148,652,551,264,651,448,69,689,498,800,189,353,53,979,899,891,814,626,744,974,865,875,668,788,304,287,244,488,522,974,305,973,756,162,705,930,980,941,834,286,295,928,174,87,845,772,367,720,244,318,699,273,883,929,785,215,913,763,692,573,336,812,598,6,270,631,165,917,332,981,876,874,953,96,793,552,599,31,340,74,199,674,603,620,514,562,721,701,232,557,500,13,139,616,633,896,858,110,741,124,678,161,248,985,200,369,911,179,389,430,429,718,803,17,18,49,6,394,351,312,96,348,125,83,303,807,738,646,617,396,292,657,480,577,584,489,52,116,810,310,830,21,260,436,581,832,370,867,420,801,172,435,312,41,922,677,266,120,421,443,41,447,223,995,578,60,159,179,587,946,911,1,144,960,63,994,611,707,312,650,325,831,179,275,973,12,211,435,663,799,557,747,384,918,595,953,69,366", + "334,196,329,451,103,848,302,91,90,200,19,576,20,156,850,618,765,466,783,623,545,254,68,299,739,807,682,671,882,42,188,671,117,798,831,562,969,39,608,198,86,503,925,499,50,953,135,915,655,206,458,334,911,496,273,305,524,615,952,589,93,59,386,23,901,415,486,600,187,985,834,729,764,794,88,865,843,952,528,486,505,584,808,714,519,53,250,280,277,182,440,488,438,374,171,835,853,337,504,11,363,940,729,507,796,22,132,786,348,774,671,759,147,400,704,188,562,998,517,86,858,975,422,490,181,799,450,60,859,640,890,127,115,103,115,713,114,576,860,103,391,128,799,147,50,530,510,307,550,192,466,889,123,134,804,214,695,401,3,15,983,560,135,534,318,194,884,677,580,188,325,553,449,832,514,479,662,889,802,460,481,60,605,169,814,764,591,798,859,744,594,796,499,464,410,112,82,616,590,583,897,732,330,18,530,861,521,166,870,760,143,761,664,784,590,321,271,332,805,806,482,297,839,74,114,748,259,688,440,480,154,123,653,346,729,347,925,63,507,239,178,956,664,203,108,695,717,276,408,358,640,513,57,236,960,455,171,118,218,379,279,283,375,694,223,223,642,767,332,966,21,646,339,816,240,484,735,632,54,886,787,787,347,712,723,78,140,642,51,782,127,755,431,256,237,583,25,414,210,887,297,647,718,580,399,211,365,346,667,678,545,581,266,941,524,240,846,244,6,193,765,492,567,551,921,448,760,876,268,812,848,99,381,442,23,849,698,542,884,840,650,84,155,365,72,229,945,4,474,590,85,620,989,965,655,924,592,148,862,868,523,123,503,927,937,674,392,215,93,177,614,984,993,593,883,382,30,658,958,94,168,969,226,562,772,162,389,41,570,951,186,400,718,121,935,512,779,587,818,742,705,918,991,859,690,441,162,186,50,90,439,41,489,122,909,698,27,479,735,498,527,26,266,970,702,270,754,309,526,434,682,599,487,656,58,988,111,396,425,931,718,290,796,791,71,840,88,179,236,881,827,471,866,349,161,318,364,815,502,196,392,346,530,381,536,539,454,687,572,94,251,486,133,303,726,221,519,715,333,684,971,89,719,387,150,482,269,444,408,304,592,364,507,902,903,87,104,291,427,993,971,139,418,28,772,89,187,890,156,278,228,577,993,610,333,0,459,523,824,431,168,46,883,294,577,518,344,201,401,941,910,653,866,77,748,188,541,557,795,305,107,828,409,229,155,232,693,710,618,634,240,638,236,894,87,274,234,706,633,426,84,320,44,875,624,181,130,265,61,97,839,587,39,396,995,173,635,268,836,412,738,119,240,270,104,51,198,931,424,181,95,837,230,777,881,671,664,850,67,922,769,718,861,452,810,296,729,585,44,292,78,863,899,415,945,911,340,645,731,798,388,694,284,8,618,973,278,529,841,359,289,714,224,399,470,305,997,159,917,704,703,974,544,734,955,224,712,735,373,962,510,358,286,797,838,542,504,486,325,555,489,833,661,465,16,236,877,7,357,956,804,728,177,312,440,725,713,870,634,273,610,617,471,693,496,109,382,886,268,405,834,509,366,56,500,578,590,438,851,250,414,656,276,825,538,556,986,403,925,389,157,136,962,394,72,26,683,533,937,467,203,54,221,47,208,381,841,910,135,839,46,144,584,507,560,947,528,450,143,249,820,144,491,772,16,747,475,434,62,992,595,167,179,601,203,781,810,416,972,59,480,45,128,588,605,100,312,104,387,329,946,149,920,448,253,337,69,733,143,746,632,580,579,530,198,286,700,686,704,202,519,159,44,412,892,551,136,818,403,296,754,443,209,504,595,273,6,109,588,551,485,205,420,364,721,178,549,977,516,871,952,398,31,519,178,963,592,981,890,80,539,639,134,461,538,543,86,993,403,895,774,449,783,387,769,222,271,317,2,860,657,254,242,854,175,771,561,678,981,146,609,109,237,135,214,758,618,237,184,91,871,675,94,337,490,152,206,54,897,449,580,673,647,3,835,277,515,937,331,751,516,970,838,867,235,673,407,834,50,835,334,292,66,742,467,870,289,837,914,325,253,494,62,385,794,719,158,93,471,139,251,523,137,809,721,519,66,741,7,127,562,409,651,578,335,308,757,81,986,104,499,236,201,564,433,535,148,326,931,999,796,774,733,370,797,474,276,986,211,238,510,219,591,344,877,597,525,729,759,927,584,619,368,653,576,726,912,321,865,368,213,106,671,406,341,760,107,526,119,747,145,538,444,278,670,600,948,990,693,627", + "472,936,750,566,983,258,415,435,757,601,434,244,858,252,215,420,575,455,698,580,504,905,753,239,375,434,579,68,470,863,670,459,169,346,283,614,748,706,945,271,693,127,266,193,825,944,584,476,786,204,9,505,980,236,895,195,240,773,239,310,115,290,329,602,799,446,185,917,456,505,50,712,89,476,568,94,842,19,789,247,785,914,149,818,78,289,180,167,55,604,738,401,137,426,327,287,268,484,871,760,232,104,158,988,287,733,589,246,262,886,715,215,874,285,594,140,185,273,913,155,210,87,893,673,969,358,583,194,516,188,845,845,52,617,405,853,390,460,796,564,44,856,576,254,130,800,257,17,210,568,892,888,79,922,143,622,39,102,206,874,944,757,580,87,610,190,555,515,811,81,788,839,640,723,572,650,233,595,715,338,286,980,828,953,960,856,660,294,116,148,512,393,547,871,150,251,194,567,540,108,14,896,781,154,167,982,780,609,594,699,378,449,348,293,604,123,944,473,776,474,506,477,932,907,638,760,102,579,528,178,766,643,436,573,105,521,863,137,645,165,856,355,979,515,415,632,96,786,323,657,936,49,530,272,761,523,892,825,748,952,17,778,855,529,975,407,758,745,551,490,599,997,549,745,697,725,444,65,858,331,394,356,433,449,911,637,461,40,139,497,542,506,72,157,53,561,785,284,65,536,893,501,50,56,932,672,947,425,919,233,511,184,355,778,919,190,470,12,397,572,207,996,878,171,804,171,111,536,602,821,842,353,225,256,264,268,112,317,237,621,863,449,974,599,718,842,474,109,111,450,804,576,59,340,400,532,66,268,504,513,327,214,158,980,820,779,867,379,510,195,391,836,479,550,452,90,856,150,389,992,653,941,818,105,653,410,993,410,129,917,941,797,875,119,133,637,392,796,868,102,390,545,793,668,658,137,310,426,864,39,802,388,841,795,86,94,199,545,451,947,552,37,791,171,816,130,299,297,382,893,836,295,41,631,124,20,563,451,505,497,512,712,66,228,915,532,74,674,245,529,492,200,912,481,755,21,553,997,430,658,426,859,656,70,753,816,553,823,742,383,139,618,979,513,261,17,194,600,566,285,856,857,638,231,955,526,841,188,633,34,901,320,247,508,264,708,447,179,288,584,997,603,327,758,853,291,63,50,458,87,784,43,931,547,392,459,0,508,452,920,989,977,328,51,613,476,517,681,773,289,3,999,282,928,118,588,803,202,657,792,595,972,23,779,729,539,210,542,703,834,207,288,230,909,438,859,761,344,219,672,491,368,787,495,166,15,627,637,488,465,18,156,804,322,25,617,317,488,556,211,393,523,35,431,65,992,635,199,481,169,987,425,349,222,421,135,869,236,869,916,92,196,641,489,141,157,838,563,502,334,799,972,683,416,162,267,865,582,659,898,525,3,999,188,94,237,914,963,554,909,460,69,223,449,65,872,251,597,506,411,373,323,418,492,831,283,158,660,671,646,711,560,516,97,978,317,181,44,13,164,475,986,248,340,484,405,652,91,414,574,249,186,450,756,453,92,464,114,710,879,7,346,134,613,574,941,573,263,935,971,776,410,760,50,608,393,872,461,183,747,308,163,572,966,738,232,821,303,856,678,267,106,584,323,618,244,161,362,727,633,879,420,451,119,665,957,508,548,942,967,832,405,888,252,405,473,14,565,200,228,208,780,883,595,223,936,267,179,969,938,167,136,541,743,216,838,190,738,840,108,418,221,989,574,695,701,498,514,545,791,567,747,360,159,761,649,902,295,215,243,275,205,418,999,134,122,267,282,594,63,882,296,189,129,502,528,829,764,916,603,212,498,587,226,128,256,156,104,864,601,408,14,55,150,607,437,277,180,135,894,784,372,756,475,668,156,822,701,393,416,413,345,775,954,492,790,33,818,904,949,518,873,584,811,385,851,943,530,564,973,545,512,492,945,847,764,671,609,559,77,876,950,976,294,586,899,125,950,205,783,625,329,89,266,123,668,512,72,349,613,910,507,970,29,819,873,794,56,274,9,47,800,770,965,113,6,333,255,380,795,547,634,296,94,44,612,347,111,572,86,525,647,606,557,605,584,104,276,104,675,706,977,357,112,467,504,903,370,493,677,369,458,186,627,561,146,115,77,584,8,165,900,63,903,622,585,443,358,976,438,561,179,839,39,200,790,767,688,618,673,568,455,605,924,168,995,646,882,304,449,282,291,759,206,536,248,561,389,706,77,482,232,995,591,596,310,228,334,756,987,124,696,855,953,561,952,992,430,535,587", + "206,719,458,20,327,574,329,325,863,453,451,613,964,403,832,879,97,116,824,747,928,322,938,303,222,707,611,859,248,136,239,682,773,962,78,652,374,265,291,578,114,643,626,751,458,617,154,326,49,151,561,811,510,939,647,139,442,582,70,494,811,267,770,624,618,579,407,634,893,985,216,40,151,574,698,385,881,700,682,364,269,264,241,458,138,924,382,639,461,417,354,158,533,747,421,245,786,450,813,171,815,882,844,28,515,435,4,926,413,267,151,886,777,756,11,487,994,48,73,906,823,872,844,506,588,855,647,912,611,44,605,995,162,752,989,183,235,736,439,715,580,670,214,408,842,354,10,598,537,895,686,145,295,709,376,846,799,854,505,194,142,605,665,674,505,199,132,891,458,656,756,991,718,240,409,136,562,432,537,751,650,760,694,399,579,773,710,534,88,986,511,642,306,465,973,629,836,903,368,813,952,168,446,767,693,397,714,433,946,117,876,746,724,408,521,708,879,375,89,457,945,294,415,880,696,89,287,179,568,792,97,505,317,296,428,866,87,943,738,616,362,662,262,619,269,98,871,390,983,883,590,519,328,300,335,915,385,226,39,905,690,796,715,627,93,381,982,482,451,355,468,71,790,87,792,465,716,978,114,324,921,62,221,985,363,590,383,812,833,910,345,985,173,97,259,977,485,787,641,623,293,292,688,812,548,523,773,239,776,388,650,852,819,996,506,441,270,887,185,305,731,540,886,428,92,572,193,70,241,10,823,7,887,439,178,275,347,621,297,114,941,736,585,26,257,231,175,973,360,961,738,41,347,651,587,988,356,590,206,291,641,138,485,165,53,235,592,735,588,911,212,578,518,535,481,247,396,455,703,224,376,789,458,61,243,205,249,503,537,611,67,527,59,302,747,626,487,604,29,516,196,840,440,647,294,854,122,877,536,435,249,132,429,858,129,767,348,82,355,619,543,424,348,416,56,719,854,368,212,850,706,185,889,346,602,650,670,113,401,894,708,112,72,149,774,132,363,450,314,91,193,902,469,492,365,612,780,512,400,376,835,205,840,364,427,482,251,511,748,136,763,927,541,159,225,366,956,522,192,962,64,401,615,79,393,716,689,929,550,662,178,771,18,207,755,111,480,549,865,724,747,355,45,673,889,591,342,692,851,484,998,983,420,836,947,523,508,0,421,953,495,566,535,433,459,33,669,108,501,144,220,470,345,608,67,996,958,526,109,47,787,787,316,373,232,323,463,916,998,275,923,509,532,87,653,513,94,664,304,844,832,767,673,897,104,425,496,516,392,948,366,293,264,799,716,691,756,579,564,433,724,545,491,364,308,309,593,936,802,631,636,805,8,287,708,374,658,351,480,413,14,829,439,341,570,736,183,756,925,863,34,332,690,482,529,645,60,320,955,291,421,790,789,426,852,583,633,526,887,388,509,531,746,494,962,590,795,178,744,364,131,759,306,373,832,911,977,690,456,588,313,789,638,180,967,574,575,669,380,28,663,864,932,315,184,146,677,425,501,793,200,263,751,487,249,634,930,471,651,180,763,337,544,762,406,420,201,507,303,935,781,783,427,183,791,902,590,205,129,16,71,897,50,353,246,639,964,60,872,77,563,831,980,629,65,884,88,218,448,147,803,368,627,649,654,351,294,491,579,655,614,864,538,406,27,499,604,757,549,501,362,689,180,56,203,623,796,949,310,667,903,619,24,344,341,856,215,613,555,293,370,943,103,975,448,641,434,339,625,954,226,11,134,795,827,338,558,511,473,266,75,18,498,168,238,757,864,464,182,245,46,9,959,323,476,408,458,205,591,82,378,102,715,648,587,892,235,902,895,183,811,62,581,557,928,382,563,395,703,256,329,724,883,258,894,228,453,581,513,575,69,155,860,105,24,547,416,742,666,496,945,137,177,211,120,764,328,675,35,82,844,40,417,266,128,393,180,161,211,833,115,705,95,35,241,243,441,262,686,178,252,708,356,5,252,801,174,968,459,85,716,733,630,414,452,804,529,106,834,54,964,830,401,410,351,446,539,5,918,543,81,723,803,894,495,928,760,262,712,483,681,333,138,459,468,569,871,347,519,93,195,283,941,146,186,313,727,973,665,923,121,93,84,284,834,906,107,860,710,654,982,635,820,10,473,419,891,203,364,911,901,957,485,14,35,525,458,346,897,97,538,621,598,898,175,104,267,787,76,614,421,13,343,655,965,78,408,136,967,714,503,938,232,132,417,187,3,499,330,176,112,528,993,836,445,854,302,253,990,622", + "942,10,445,547,45,425,592,501,604,834,809,746,379,367,968,746,725,189,266,412,192,499,450,396,36,247,200,39,628,680,294,767,477,602,575,291,217,988,31,863,205,329,12,506,281,935,729,962,838,209,88,515,641,643,325,115,778,103,339,617,962,451,377,929,955,626,260,843,926,938,395,812,805,314,719,601,451,626,732,991,613,221,215,415,676,115,40,817,798,615,6,601,426,935,771,252,499,259,302,428,463,302,772,996,986,755,358,686,860,675,437,850,144,20,862,742,356,313,16,238,578,101,32,351,678,765,44,135,758,49,513,727,846,223,659,21,137,219,297,459,159,129,501,441,561,703,788,658,604,407,968,270,502,588,727,493,985,631,587,402,329,20,38,290,733,919,792,747,152,938,586,158,630,350,92,123,955,408,445,289,691,304,139,305,239,609,866,567,868,491,844,486,870,874,39,208,730,371,449,259,788,212,828,437,981,519,502,287,528,430,588,479,31,86,158,456,78,162,733,998,61,78,243,634,564,530,815,700,771,314,806,399,229,92,308,549,651,632,190,537,425,538,781,549,346,259,10,293,918,254,492,976,802,947,219,414,883,156,264,103,702,280,744,680,704,531,272,762,319,450,398,722,174,628,738,199,719,755,330,258,297,825,545,483,848,584,777,424,89,835,427,919,131,902,734,958,556,423,335,614,63,37,481,966,442,252,474,30,755,373,344,767,540,360,865,357,710,876,768,326,17,662,916,918,904,826,372,694,295,599,660,22,83,258,886,311,60,179,723,283,712,794,321,40,300,11,721,194,935,803,393,207,928,659,502,809,251,48,223,466,737,15,400,567,942,49,423,347,876,82,402,196,528,872,19,181,682,198,518,847,963,405,968,617,901,792,457,140,830,518,450,453,306,723,964,137,94,454,77,41,590,351,494,594,817,965,737,403,309,281,477,543,662,499,864,798,958,652,820,728,285,673,183,683,372,813,79,416,352,22,235,168,6,952,665,418,364,766,469,807,463,621,711,584,425,9,428,915,913,567,834,553,92,26,616,790,856,832,690,154,580,197,369,175,682,494,370,610,377,828,350,161,68,113,484,847,864,929,429,843,788,784,135,987,449,767,291,933,548,491,715,947,539,88,610,889,686,346,728,319,616,633,759,604,6,127,875,215,336,251,421,117,17,702,883,824,452,421,0,880,450,309,323,977,204,65,562,262,574,288,661,576,640,884,558,476,678,348,359,99,6,609,403,962,561,303,438,254,193,513,340,757,837,61,919,248,781,668,284,625,592,585,164,295,508,198,567,824,298,902,535,325,373,788,928,971,569,174,17,91,434,171,326,817,427,893,438,251,32,388,368,782,486,861,592,499,820,238,814,620,255,26,480,775,778,501,775,252,495,528,50,984,373,876,666,200,492,100,55,958,980,453,580,200,953,5,509,772,237,607,753,525,476,9,220,157,537,694,802,110,43,375,376,807,656,310,925,921,280,603,340,280,909,831,34,363,624,504,374,772,213,469,645,854,478,56,507,230,157,5,111,63,364,733,368,379,319,939,16,674,364,238,209,150,425,625,633,28,525,791,644,957,325,83,912,203,590,705,24,217,294,228,464,442,415,562,62,892,628,747,287,529,980,632,299,236,487,350,827,233,629,91,632,718,351,876,451,390,319,253,944,166,639,512,181,840,524,122,481,76,319,727,649,447,673,287,447,417,119,417,154,402,576,872,902,206,765,615,50,218,285,174,751,139,108,303,91,461,53,37,80,284,400,852,241,150,500,200,92,783,173,184,212,367,932,155,872,479,140,26,807,786,164,44,288,819,888,584,298,185,303,685,57,559,524,209,953,300,412,436,621,704,268,58,890,86,885,9,32,476,471,240,75,56,94,546,278,89,829,177,627,957,852,150,294,400,773,516,767,562,332,264,420,544,249,73,817,674,572,20,339,143,473,595,515,500,226,743,480,391,940,342,15,152,951,592,228,291,380,705,9,280,492,29,502,368,665,421,738,105,915,734,240,877,109,64,446,639,558,905,703,901,179,746,493,479,110,844,894,129,955,709,92,578,919,206,81,909,734,43,606,710,908,850,737,859,207,169,611,685,602,204,390,819,820,66,286,535,331,474,386,728,425,932,784,628,228,378,93,990,740,549,374,683,646,112,588,260,455,373,698,931,353,336,446,500,908,778,406,535,692,740,619,437,367,918,358,812,924,881,6,788,844,534,193,445,201,485,729,562,883,410,801,194,146,217,550,215,569,446,222,241,768,599,983,573,571,50,568,542", + "166,736,665,237,527,63,628,301,762,216,35,887,2,968,425,517,257,281,659,426,597,583,856,792,247,326,450,41,239,592,195,144,244,177,290,583,260,788,781,40,284,791,600,427,507,448,142,298,352,972,976,656,904,412,832,971,849,512,230,837,375,530,986,866,437,871,315,668,778,426,78,900,888,880,828,540,937,350,431,301,434,141,153,340,842,503,758,136,103,758,42,860,57,822,399,88,312,66,584,575,493,743,415,2,538,533,319,318,497,500,94,870,625,245,440,523,333,969,114,589,636,344,464,565,675,867,160,104,604,205,915,48,71,979,469,841,921,219,714,130,670,862,984,869,267,768,985,909,306,650,716,217,811,65,300,640,234,33,120,502,170,951,494,828,736,801,302,922,156,926,58,504,81,739,123,660,466,511,31,406,145,748,414,937,709,181,756,547,324,678,123,830,539,94,491,59,514,409,940,860,360,450,434,19,929,601,383,812,164,937,783,582,850,923,178,656,994,983,232,450,428,791,522,196,122,38,529,761,342,122,914,104,490,626,554,53,939,630,159,46,700,655,777,369,743,52,21,374,981,176,943,148,131,835,587,894,300,228,443,707,976,88,453,34,476,188,134,656,420,238,22,132,70,636,54,351,462,417,764,89,167,250,496,74,540,232,612,361,22,712,803,751,954,818,411,887,98,120,664,133,480,147,373,583,569,295,841,160,877,102,914,657,121,993,344,938,322,988,294,934,516,801,633,190,14,608,76,469,670,971,344,833,668,797,728,797,395,236,264,646,433,39,351,609,839,237,150,368,737,520,365,447,468,431,678,326,167,246,354,818,239,199,91,86,346,940,275,664,700,451,259,307,56,536,674,52,91,143,356,79,342,609,379,308,609,511,557,929,862,156,720,991,315,87,807,328,907,36,585,495,318,401,19,249,646,624,138,626,848,984,78,180,185,709,36,443,500,412,288,396,682,413,947,689,292,892,89,924,446,941,517,615,711,920,50,894,661,906,441,301,400,286,137,361,415,226,990,111,807,218,425,969,996,120,2,945,1000,794,374,848,710,749,618,373,728,607,202,673,93,678,612,391,94,626,324,830,407,454,187,232,227,367,758,968,59,499,81,574,179,934,890,694,885,150,697,241,479,824,23,533,91,2,304,412,50,499,876,115,522,607,639,832,439,954,662,431,920,953,880,0,920,96,520,32,281,254,504,8,917,297,712,258,686,922,192,734,43,229,570,935,949,209,167,277,150,856,986,720,788,244,466,679,209,567,860,642,3,586,813,773,92,445,758,867,792,998,242,674,115,729,489,21,948,371,21,158,328,462,364,604,858,532,430,539,554,604,924,159,292,720,577,941,173,767,47,414,445,705,647,465,301,283,969,724,742,99,462,821,794,338,20,601,762,221,70,726,106,917,307,973,608,218,119,357,450,828,673,7,5,935,853,956,38,572,665,35,968,123,823,953,78,370,675,325,650,421,444,393,867,506,956,700,105,461,168,765,800,993,148,57,455,195,957,378,819,48,716,902,690,993,682,18,129,679,701,191,792,706,114,939,404,589,693,816,153,418,889,230,237,620,413,19,580,713,785,970,851,939,129,36,392,393,635,127,421,882,337,683,477,978,344,300,778,348,583,642,970,640,873,287,992,962,218,610,183,546,298,846,609,361,445,988,823,816,340,721,477,690,217,623,169,341,541,142,33,375,847,517,243,802,20,500,436,47,935,833,136,183,892,962,224,917,410,437,20,920,163,304,882,286,28,174,386,662,715,380,948,340,802,606,435,459,719,428,120,270,30,271,253,848,795,950,457,54,647,833,593,367,607,532,440,988,661,362,730,487,341,115,100,971,840,159,322,729,319,924,369,453,986,753,22,346,909,59,944,218,403,178,188,286,131,707,985,490,120,938,257,748,165,936,542,629,913,842,734,268,663,285,298,145,360,494,542,540,173,359,927,171,331,631,944,616,323,328,461,209,82,139,392,305,997,395,164,269,650,298,555,473,832,674,634,231,881,724,18,581,883,240,620,981,109,451,348,426,964,207,186,29,350,884,437,131,272,568,812,685,112,518,909,962,356,581,796,951,861,465,342,751,862,741,879,952,861,291,550,156,461,397,54,734,57,229,448,857,653,134,436,892,295,201,378,813,731,494,981,463,321,152,64,330,768,976,722,417,176,646,590,857,18,237,422,90,122,72,763,595,122,854,842,418,106,979,419,807,755,228,569,530,568,128,219,161,188,390,486,380,560,146,297,827,533,713,701,393,358,845,697,752,170,910", + "38,641,420,307,311,396,305,586,915,490,439,759,471,97,507,86,6,989,752,127,886,61,33,523,612,772,144,348,133,292,410,217,476,814,47,792,343,791,322,135,300,743,644,255,207,263,987,177,257,687,244,600,256,148,432,58,865,145,933,986,113,589,39,300,382,787,723,122,559,311,568,78,163,753,977,893,410,372,948,677,161,259,412,793,522,678,571,734,916,871,882,116,357,431,604,360,95,561,317,605,954,622,314,167,995,283,320,42,690,71,230,975,19,116,269,774,405,845,538,503,247,38,105,6,95,909,165,662,836,113,4,498,152,953,760,608,532,576,730,584,253,990,117,371,592,569,774,884,229,406,766,381,739,408,311,862,416,500,136,711,578,771,711,643,379,16,449,297,411,635,773,861,798,654,737,848,372,256,350,297,455,364,327,919,515,948,52,817,520,182,501,316,289,856,284,35,915,85,187,546,105,91,866,917,341,669,191,563,919,210,303,951,8,938,127,803,610,152,280,429,442,153,40,277,584,274,658,105,844,722,685,737,518,143,148,662,93,909,647,195,576,109,246,746,785,48,214,61,356,798,676,667,307,820,708,939,347,451,972,584,698,497,338,15,342,504,602,93,874,337,400,653,169,69,960,594,261,31,78,388,948,163,303,746,746,725,470,420,754,953,724,181,308,752,575,858,203,884,216,826,373,719,343,839,114,9,997,215,336,690,254,515,862,606,711,834,269,734,492,579,773,592,810,640,527,167,138,47,525,964,558,963,543,835,472,316,9,155,565,483,22,574,328,364,513,864,884,98,489,620,889,441,262,90,420,187,446,436,570,703,28,183,697,283,897,461,249,210,511,87,705,832,18,209,894,489,685,909,678,85,423,549,455,745,134,608,29,626,669,614,226,854,685,71,982,120,520,946,234,356,410,820,775,298,369,736,512,791,153,72,621,547,237,224,220,829,231,935,303,273,813,960,715,952,56,440,410,580,874,563,514,66,248,643,11,81,820,877,199,538,703,423,951,268,47,460,65,682,771,583,677,253,771,140,717,105,690,408,367,531,528,301,175,881,349,691,928,97,796,708,136,352,281,324,39,807,973,514,768,493,679,471,383,426,345,56,142,107,402,978,354,162,888,745,974,493,730,137,856,648,615,169,640,642,407,490,716,856,435,826,760,629,709,90,738,168,989,495,450,920,0,158,432,394,651,106,536,328,164,651,539,939,386,683,445,41,796,461,562,956,864,270,747,315,505,75,302,691,92,760,721,102,485,226,266,540,876,792,531,396,827,588,535,610,884,722,752,690,115,488,444,410,650,264,821,423,5,782,310,197,677,808,465,389,352,858,791,594,976,675,170,545,518,918,556,937,194,285,553,700,435,460,914,252,76,174,898,658,864,94,443,422,917,651,347,902,78,744,996,385,934,9,305,571,921,826,986,967,566,454,54,26,220,891,681,770,812,877,348,906,159,58,775,836,353,520,122,17,707,324,481,189,243,13,913,103,104,718,193,886,958,508,375,418,280,542,996,222,535,423,7,317,337,175,707,534,958,970,454,932,942,715,768,863,996,753,249,386,845,534,277,281,1000,832,486,551,579,575,312,530,762,719,871,120,305,965,874,153,368,801,155,366,385,731,967,386,260,647,578,701,519,274,39,864,829,544,447,517,550,524,574,800,685,505,217,57,107,329,159,867,429,213,912,200,790,583,971,15,765,259,773,195,13,89,229,203,163,914,645,189,734,379,106,455,142,521,852,311,311,881,802,333,672,976,470,211,874,281,877,115,387,108,186,406,460,410,56,704,401,817,376,175,133,548,539,808,428,767,925,334,741,517,90,292,623,719,208,395,202,600,827,958,505,952,314,192,977,525,481,106,700,842,565,219,153,85,585,413,870,593,505,329,138,132,892,263,215,660,128,898,928,600,669,144,102,463,175,113,316,486,586,140,254,433,402,156,59,573,539,681,288,341,391,156,863,774,563,490,855,524,599,941,776,526,563,58,414,213,882,424,896,199,584,565,402,713,655,556,986,385,776,337,929,972,42,174,552,359,688,314,29,959,509,993,279,937,750,544,480,995,911,757,561,992,817,409,76,533,150,895,958,93,737,346,358,925,375,786,655,558,882,528,212,588,110,634,640,568,939,579,470,352,890,546,900,960,877,267,381,986,578,149,833,874,163,354,653,870,391,359,127,849,329,410,106,453,461,35,762,116,479,192,683,871,632,437,610,315,164,58,428,96,430,691,11,466,355,568,938,190,231,646,943,609,597,102,732,527,78,23", + "203,227,613,430,248,478,919,186,527,821,684,772,786,18,900,426,150,455,313,725,251,578,118,842,77,49,762,971,729,232,105,440,961,935,287,61,198,149,598,222,401,749,441,792,610,935,601,935,148,246,278,876,247,508,886,481,374,371,450,914,456,753,385,426,233,862,871,759,181,579,348,381,906,264,443,811,442,595,379,258,395,952,861,432,960,913,832,355,989,622,706,795,434,658,265,636,144,730,635,148,485,255,391,346,127,592,651,900,803,616,401,670,669,247,971,350,963,928,450,471,123,346,257,566,289,557,542,613,811,266,308,609,375,952,273,445,740,70,910,645,551,125,673,60,487,636,888,10,598,371,156,247,552,30,457,491,908,738,986,663,316,558,382,41,91,158,45,356,863,575,843,419,39,285,930,470,817,446,792,53,394,541,770,132,198,895,969,21,614,250,778,85,812,907,741,670,278,382,523,753,803,547,474,534,301,980,502,643,381,542,65,723,904,58,126,906,806,415,711,343,524,985,216,477,336,134,509,147,588,230,777,326,881,900,345,506,51,757,116,466,822,80,876,476,911,875,868,51,938,414,891,731,760,523,639,672,711,409,679,949,711,990,680,745,928,348,742,297,236,891,101,260,481,3,645,777,57,870,152,522,415,894,335,673,227,965,54,990,832,414,369,579,514,107,140,368,817,527,406,410,935,46,675,401,708,313,894,704,309,826,577,745,279,191,106,212,758,975,320,902,475,975,723,470,920,144,847,834,919,552,4,744,576,871,636,502,791,68,990,389,485,934,349,91,386,567,431,139,529,754,750,93,7,71,664,787,966,972,914,152,981,475,71,429,721,814,676,767,420,215,74,339,182,187,403,811,837,200,93,824,533,585,29,218,97,564,800,73,397,458,370,844,329,52,423,527,934,859,297,545,224,453,509,720,897,73,886,825,731,399,921,825,650,853,764,706,691,518,225,211,99,853,319,252,491,967,398,45,429,432,67,910,81,221,698,39,564,449,553,51,100,702,920,201,68,233,832,763,922,794,594,813,716,501,424,719,104,594,615,970,448,371,899,588,331,141,801,456,889,568,597,609,838,837,560,121,696,235,488,975,516,40,392,954,400,18,76,835,680,790,46,975,760,337,523,231,159,426,139,597,697,724,734,527,553,564,263,194,361,268,589,252,538,892,790,46,977,566,309,96,158,0,637,802,438,326,570,719,887,277,94,40,475,519,476,597,183,25,91,854,984,291,580,561,323,680,106,929,246,312,212,772,79,150,800,141,929,925,924,433,704,887,639,254,426,499,103,970,462,132,133,199,212,998,871,121,587,796,104,316,506,291,944,310,667,527,773,227,709,165,798,186,145,448,566,304,377,354,935,944,369,249,818,154,191,660,539,55,509,263,761,190,220,647,676,381,588,699,61,878,890,266,390,931,927,321,65,269,738,601,929,827,132,326,363,760,762,886,322,22,321,479,472,136,336,303,193,750,921,982,11,938,31,690,477,679,70,160,170,718,70,798,3,30,635,894,733,427,755,899,454,866,342,102,466,18,96,993,35,729,209,958,837,142,962,279,855,140,301,274,38,587,641,93,57,29,52,93,829,874,547,888,934,609,99,207,866,577,242,444,171,152,250,413,822,522,87,970,518,434,704,20,326,729,299,890,99,720,725,133,928,73,704,594,22,600,305,71,925,751,365,481,447,772,47,519,639,231,292,268,484,920,283,441,703,730,96,983,318,833,76,856,671,854,233,719,574,90,188,797,332,699,378,140,848,33,71,312,13,830,351,797,772,964,922,25,995,175,389,42,235,774,611,757,853,689,915,97,356,291,412,848,244,220,485,806,919,861,535,339,969,370,15,932,519,300,656,984,88,499,873,977,271,440,612,186,326,885,393,330,306,323,100,967,701,113,28,609,574,696,374,214,42,407,141,6,946,229,870,778,965,64,774,3,804,767,95,267,411,126,1,934,762,848,649,127,350,502,558,376,310,27,718,766,677,41,723,736,890,681,160,810,672,920,283,242,524,664,789,346,810,726,355,624,111,420,395,19,979,859,316,221,585,521,742,866,708,168,339,174,579,284,144,241,702,606,386,294,913,289,921,352,991,163,756,921,26,246,658,219,823,263,252,679,693,768,133,541,326,750,26,545,807,993,959,489,554,783,407,885,46,402,988,544,405,576,521,728,854,954,868,667,68,309,574,574,804,741,97,931,551,636,432,368,895,696,731,331,138,636,204,951,419,97,265,281,339,886,23,13,696,231,171,448,191,38,637,946,564,487", + "953,538,596,331,973,171,521,747,478,323,251,712,759,933,227,169,771,791,159,339,211,979,398,385,461,679,238,251,281,65,784,397,866,621,829,960,768,613,146,962,72,417,198,283,504,77,281,537,887,262,45,112,831,200,693,920,102,594,142,282,634,613,320,638,9,625,108,449,646,683,565,726,436,251,804,392,230,753,501,263,294,597,94,335,941,171,766,34,420,898,2,508,697,75,328,769,125,395,358,597,775,556,987,575,754,764,698,875,672,292,722,607,429,88,150,192,960,169,434,493,213,98,192,142,866,115,54,935,601,957,916,365,903,25,845,162,360,113,743,563,986,679,807,144,237,946,576,981,385,105,355,844,281,581,64,579,512,460,587,690,990,761,172,658,290,689,150,1000,12,539,339,198,80,661,84,661,9,469,377,281,40,581,120,379,947,251,763,523,812,815,789,57,709,133,749,798,972,701,612,144,897,776,72,74,377,55,657,301,732,169,52,621,246,403,907,765,844,870,664,917,203,734,990,177,614,275,513,668,818,108,452,102,640,339,784,386,375,809,787,243,219,641,56,332,243,838,240,450,498,449,842,125,933,649,459,49,157,356,788,15,889,97,171,601,878,119,367,959,99,236,907,681,390,392,880,376,779,240,308,567,806,54,456,737,957,119,338,698,560,992,100,831,716,529,870,729,24,583,645,69,438,453,705,337,204,418,114,160,568,840,590,871,777,666,841,714,169,29,997,722,854,137,847,811,413,473,443,284,58,676,172,753,197,114,176,927,939,917,914,288,809,982,166,724,846,600,398,244,403,232,268,964,428,81,243,649,128,530,657,56,504,107,348,258,415,40,458,848,446,793,202,706,664,705,316,337,47,335,615,775,948,706,440,212,61,536,416,282,335,883,851,299,936,814,855,439,677,850,974,529,970,587,854,186,698,110,120,629,535,769,635,12,723,142,598,62,759,406,853,368,173,848,853,16,449,596,28,786,413,327,243,640,548,46,874,349,131,8,659,884,936,210,30,541,485,287,291,458,533,341,630,210,509,744,922,936,164,970,730,713,93,547,669,358,249,893,337,161,31,383,14,646,98,766,415,809,599,344,677,891,882,636,211,554,684,77,60,871,158,361,691,578,924,796,798,705,664,956,90,815,353,14,63,75,661,376,589,574,605,82,68,582,586,123,663,883,328,535,323,520,432,637,0,220,942,387,247,148,227,228,650,470,313,414,770,309,921,340,888,957,696,644,947,254,193,300,285,740,277,7,229,711,199,265,584,795,868,179,116,663,886,553,979,951,552,222,442,889,699,761,993,501,20,467,410,787,639,151,654,596,45,217,736,50,608,436,243,19,780,710,454,57,784,169,617,769,286,260,924,368,185,243,428,982,362,537,808,719,98,76,539,406,237,905,934,287,467,205,561,154,209,33,891,846,588,360,136,877,373,302,300,650,526,341,83,954,803,599,904,933,788,372,791,892,819,153,974,157,12,598,930,758,442,803,330,305,808,265,890,56,131,219,597,107,311,410,496,790,7,44,426,813,666,52,654,431,569,931,452,809,998,113,572,853,96,355,824,709,445,603,534,284,627,527,693,619,801,949,577,660,102,918,83,537,981,850,211,103,488,404,14,309,37,704,643,132,575,63,286,8,132,570,885,159,81,330,70,296,435,379,25,210,950,430,481,47,711,381,416,864,795,650,439,864,353,981,348,498,31,151,718,570,640,85,728,800,801,943,812,828,946,636,473,704,987,436,739,896,357,180,824,709,505,42,791,831,120,773,862,64,919,735,753,97,33,183,913,409,754,901,542,767,791,291,747,784,976,434,226,310,487,627,652,984,306,269,412,235,374,651,715,537,991,536,41,886,243,25,308,162,798,5,585,216,345,78,823,462,266,568,743,935,705,235,412,370,146,596,755,518,517,722,31,446,999,479,166,524,124,970,985,811,200,951,898,632,751,921,977,38,915,5,680,928,48,69,688,59,85,139,80,455,500,19,868,738,629,731,981,682,369,191,237,769,26,601,718,381,918,608,986,566,396,706,545,339,29,450,82,718,683,226,614,311,239,598,719,165,312,632,487,454,2,486,406,635,323,920,961,257,177,258,297,42,815,332,795,905,102,239,911,391,904,687,367,627,210,424,944,989,556,590,812,777,515,763,945,363,341,365,687,847,471,755,635,722,585,247,890,728,611,271,975,53,717,936,169,817,336,881,254,86,215,208,962,234,85,237,828,788,350,36,522,689,687,396,357,193,604,856,830,213,934,208,543,772,197,175,941,766", + "201,609,755,176,862,348,285,745,960,760,242,463,810,516,126,861,923,37,505,922,101,660,228,418,459,785,125,57,530,788,402,185,768,123,332,102,905,690,748,807,222,609,37,414,120,915,54,909,105,29,993,730,645,930,857,980,205,129,788,679,320,497,162,415,679,162,593,271,446,710,280,125,112,692,482,627,483,213,991,906,625,658,372,801,73,488,567,736,926,278,393,337,95,236,856,498,636,152,211,123,102,215,477,469,110,384,88,748,677,347,914,882,900,312,439,182,489,330,806,392,911,589,137,972,686,730,138,793,728,63,787,615,166,435,601,419,713,88,39,746,572,113,783,962,493,402,760,159,635,848,477,176,338,864,618,327,447,752,18,68,624,106,481,105,877,337,577,230,870,546,100,427,453,204,753,323,751,573,110,185,183,445,282,890,218,33,694,391,352,72,576,232,918,492,536,930,733,331,401,227,463,977,690,75,445,403,338,585,983,654,644,419,620,929,379,633,575,484,509,95,888,200,259,670,186,505,237,22,151,891,559,134,289,742,466,846,589,265,862,707,387,112,142,759,784,267,808,668,89,989,955,801,689,766,921,693,602,862,794,179,407,670,102,901,393,394,545,658,412,309,650,256,56,296,399,265,194,297,218,864,530,939,681,539,707,150,318,620,910,280,875,613,314,713,59,964,865,207,312,864,864,714,453,468,526,273,875,825,575,801,89,786,619,376,181,227,840,554,297,721,259,404,75,279,676,352,884,114,135,84,339,11,563,6,532,789,627,61,809,972,888,532,231,70,350,553,859,825,840,505,444,409,426,752,127,50,265,510,213,174,434,12,287,290,444,804,426,226,447,970,948,77,363,203,415,185,503,151,576,392,139,213,274,514,906,130,612,528,374,31,736,228,844,819,72,363,637,599,659,775,541,499,442,6,442,656,285,425,125,83,216,999,641,976,658,22,467,922,200,850,809,597,321,628,124,414,844,629,779,643,760,796,54,924,815,744,255,200,40,626,215,182,261,841,397,925,372,319,257,12,166,519,893,843,876,82,930,271,68,636,10,904,274,122,205,11,875,149,107,199,746,409,500,111,280,268,115,369,580,193,719,203,284,332,745,659,602,960,640,650,173,837,895,105,172,896,597,37,6,672,994,751,712,683,860,668,396,331,128,654,401,880,284,667,556,294,51,433,977,32,394,802,220,0,204,366,167,466,707,469,335,936,752,224,137,430,835,989,321,268,920,691,595,89,710,377,635,714,686,965,928,585,682,573,714,455,602,767,227,971,740,425,352,559,565,974,986,247,242,564,789,543,403,471,603,293,475,311,691,843,226,81,846,122,452,396,138,606,647,480,383,433,802,498,822,322,230,682,599,134,44,828,482,612,971,883,359,477,29,103,430,775,765,879,158,604,438,752,57,597,185,350,571,636,840,393,63,234,491,31,989,922,361,544,224,8,274,67,444,302,23,941,522,800,432,957,192,371,108,247,586,872,766,140,263,158,362,633,347,224,5,855,421,235,947,509,873,749,131,54,523,333,305,866,361,557,975,896,88,964,722,808,959,230,86,562,414,465,901,750,342,383,418,706,536,586,355,430,524,272,884,952,524,704,508,186,654,564,332,640,354,246,317,583,714,28,43,343,562,84,757,664,36,347,265,552,772,697,344,738,920,494,454,33,991,295,986,157,645,716,873,889,164,34,364,577,923,195,126,511,273,630,974,61,493,997,390,749,448,159,216,569,802,81,748,859,395,694,247,224,273,577,581,535,620,683,442,422,190,659,766,736,448,794,16,287,123,845,44,401,516,383,912,341,525,471,975,854,188,876,858,172,597,425,76,970,344,918,327,763,277,501,730,968,468,895,10,796,31,880,644,320,916,853,275,135,79,854,586,244,281,599,292,822,681,901,972,272,590,729,154,593,501,477,650,198,839,238,768,107,569,775,164,929,844,494,987,558,672,751,85,614,619,478,615,456,228,144,159,63,822,38,48,253,541,446,632,594,152,462,41,896,781,318,369,620,978,748,457,846,736,752,112,209,392,546,574,297,405,463,407,316,760,999,697,242,632,530,826,787,669,659,905,57,696,119,138,701,549,10,812,595,211,273,440,16,381,135,99,388,612,83,298,50,517,623,447,865,330,38,747,573,283,158,141,208,521,849,895,140,936,866,361,560,284,212,897,413,767,848,986,168,818,944,757,971,751,82,168,121,760,5,40,168,820,870,52,719,596,234,226,439,907,903,363,56,777,674,963,996,959,269,913,659,163,912,514,957,278,340", + "566,954,870,121,683,37,545,731,288,607,84,781,104,203,9,106,602,968,545,900,277,28,348,317,911,893,861,109,143,146,149,581,510,735,559,516,960,224,585,500,357,59,268,319,975,74,42,928,10,737,939,11,966,365,192,231,177,446,937,391,119,631,695,379,129,54,290,531,309,198,965,633,760,62,209,566,589,962,677,718,519,29,111,204,162,992,754,380,999,303,348,308,859,122,706,253,695,493,641,218,575,108,240,688,561,227,335,23,343,790,671,153,328,181,6,728,1,990,503,482,629,34,471,640,193,559,950,21,954,32,246,327,684,464,268,538,963,527,447,645,666,468,540,292,383,369,675,883,672,759,740,323,664,721,899,340,866,921,189,200,212,124,406,689,151,788,869,319,507,807,248,359,334,216,108,148,432,157,891,544,544,339,80,720,447,541,511,672,777,218,937,831,591,20,142,857,347,504,498,610,470,543,8,434,403,333,931,102,343,796,250,320,408,900,384,231,777,486,273,960,949,405,54,218,75,123,169,162,455,267,370,323,21,617,729,585,58,812,420,104,576,974,540,243,656,632,26,484,891,370,713,361,497,644,776,223,745,711,227,123,523,306,600,826,450,998,306,829,124,573,155,408,31,758,210,991,142,776,729,592,447,129,745,550,25,186,818,404,19,111,776,74,264,774,391,531,60,783,991,592,849,798,86,482,15,891,413,686,574,438,408,918,303,729,800,851,561,49,165,136,214,354,216,316,855,426,284,505,920,551,147,886,94,703,576,442,982,379,946,14,230,571,388,104,977,970,152,324,292,859,909,105,721,262,984,296,285,370,149,367,732,284,421,476,804,713,146,223,538,673,279,594,245,386,738,705,914,328,473,927,497,369,725,8,681,73,571,64,923,195,389,628,694,550,115,288,489,522,874,815,589,21,874,639,74,604,926,457,514,934,372,622,62,477,202,146,142,863,583,177,323,268,822,95,127,209,109,335,893,488,170,83,999,837,258,773,770,848,825,566,55,110,17,123,356,762,902,864,674,392,679,361,115,900,684,166,171,124,740,340,644,880,113,937,335,440,454,76,487,662,22,216,60,797,872,629,297,678,588,268,554,369,696,996,660,168,86,745,967,270,840,727,783,623,992,85,789,357,842,404,459,257,456,215,561,871,428,693,145,355,27,619,529,408,119,577,613,459,204,281,651,438,942,204,0,654,26,740,850,328,326,957,693,878,912,875,33,643,44,965,834,126,117,345,241,954,873,422,93,859,712,290,994,694,231,246,797,489,880,17,151,501,568,673,866,634,3,530,415,93,816,278,690,212,743,365,136,547,279,503,744,248,120,902,492,973,517,200,438,277,939,663,270,787,141,214,474,798,777,903,758,567,501,210,781,378,857,571,845,533,25,372,866,186,404,202,576,191,717,527,776,516,330,975,715,591,921,455,590,413,126,230,572,122,847,591,57,516,310,423,604,470,279,585,785,652,876,583,360,571,562,844,672,171,548,811,65,952,234,388,672,951,554,618,19,154,875,987,917,302,314,79,412,923,92,516,145,666,242,659,877,692,341,740,118,490,23,852,367,564,332,165,306,240,543,750,444,236,922,514,670,956,385,527,281,140,13,491,447,474,743,827,617,962,470,42,557,637,342,34,114,265,544,947,117,852,335,27,826,5,203,319,938,779,479,346,985,241,581,248,55,100,377,474,157,873,812,242,66,127,389,499,452,527,474,99,836,643,747,874,605,722,215,43,45,809,820,160,597,265,123,987,848,147,976,512,983,128,172,714,233,641,48,346,88,758,398,481,308,122,654,673,998,825,209,704,549,927,387,412,949,347,53,490,435,975,236,1000,631,537,497,879,11,121,884,831,411,514,966,316,398,352,714,672,808,962,20,351,446,592,96,327,371,98,666,924,601,387,964,570,103,785,726,792,62,989,675,624,226,415,132,173,24,258,588,291,94,6,942,425,773,287,660,847,223,254,546,972,255,829,800,126,149,761,578,383,6,742,960,694,123,663,421,59,216,648,454,144,594,779,412,901,357,70,433,848,842,517,966,710,981,403,628,236,205,714,964,59,985,641,286,65,32,964,901,676,679,944,45,626,821,160,521,733,212,565,723,350,855,446,884,361,313,835,944,549,446,65,810,549,870,341,712,94,406,530,266,147,16,622,688,10,831,982,675,384,180,711,151,520,610,554,501,185,348,91,277,346,477,521,263,232,382,68,903,739,378,51,777,16,561,453,575,184,98,395,461,462,408,757,51,254,697,698,814,428,66,804,446,918", + "409,84,406,682,951,64,342,715,649,431,503,529,222,475,488,57,350,551,333,127,492,65,470,93,4,685,232,956,388,283,737,733,121,108,637,947,29,701,219,544,101,694,662,82,448,441,891,651,346,508,700,895,55,930,362,910,847,615,571,80,679,652,87,826,519,324,373,84,792,157,570,215,173,883,428,275,223,171,262,133,19,824,809,213,682,102,655,915,859,171,128,850,488,846,941,19,112,760,303,518,884,750,812,756,793,10,227,864,970,647,433,885,837,668,151,39,187,291,210,324,21,917,663,876,265,804,342,563,606,444,976,133,874,572,810,897,361,506,887,890,635,299,584,451,762,903,9,139,131,441,150,249,728,895,802,521,294,770,157,646,550,901,847,601,955,567,809,463,506,176,489,909,953,155,975,442,263,574,368,715,898,475,408,310,350,409,190,137,615,90,370,877,800,884,677,620,396,375,834,574,240,287,763,111,415,281,111,345,249,505,341,3,127,944,737,490,689,421,180,750,684,575,809,840,278,767,114,411,961,662,988,84,402,816,544,779,257,695,665,123,256,438,290,73,753,786,279,609,299,970,352,12,301,719,507,852,508,54,256,409,445,659,837,224,15,198,94,915,922,275,599,818,430,83,981,411,500,536,621,886,599,895,831,558,252,964,987,481,525,967,464,93,298,958,902,718,626,89,246,636,246,80,939,86,98,862,863,190,644,817,282,631,619,230,706,60,915,892,270,294,255,875,685,204,423,793,550,392,377,475,917,930,815,341,138,914,6,594,216,570,93,963,162,365,467,680,370,482,215,616,17,66,70,840,832,344,362,56,148,159,674,422,235,569,623,293,887,92,29,496,751,540,912,615,595,928,625,109,479,599,702,9,198,763,426,762,467,520,155,312,289,447,946,46,538,859,996,832,965,464,617,850,654,267,17,857,418,993,756,825,465,270,42,506,796,836,828,404,572,2,727,53,898,949,920,368,443,543,981,863,612,771,708,255,790,371,654,532,446,259,689,433,461,479,370,58,447,397,692,569,36,5,632,980,218,572,729,582,962,506,731,680,95,5,275,334,80,404,7,241,851,248,343,241,324,728,38,916,521,411,34,727,407,841,720,294,621,346,506,822,798,872,859,483,63,645,45,118,197,705,867,387,426,172,878,835,866,818,303,487,674,994,540,138,217,518,476,33,65,254,106,326,387,366,654,0,47,173,91,142,347,549,41,448,525,900,17,345,887,272,521,540,205,496,872,596,915,288,967,631,808,886,398,924,166,342,972,970,197,997,515,814,245,351,227,233,704,222,227,645,67,152,413,503,176,264,897,873,258,364,24,10,390,393,391,90,929,63,938,306,555,663,366,600,262,184,143,241,445,262,587,240,239,68,794,451,607,772,36,155,931,630,513,447,328,956,420,794,698,922,659,892,511,204,231,454,682,781,163,357,593,209,447,229,353,883,965,651,504,442,170,184,590,397,820,763,91,141,353,121,417,418,250,174,414,707,692,812,103,259,908,412,937,475,718,984,73,548,641,698,134,604,682,379,908,185,800,43,368,238,576,190,878,41,796,412,928,360,370,933,402,799,730,30,789,76,646,946,181,871,546,87,41,877,169,601,28,536,706,338,702,150,537,271,478,876,80,577,944,887,251,638,569,688,876,585,627,122,521,969,556,481,265,910,21,716,342,557,149,83,16,356,63,830,943,810,272,461,906,368,992,549,146,819,254,789,194,215,430,81,273,324,136,893,711,731,233,978,446,993,402,272,35,6,653,918,351,748,889,869,268,3,706,185,984,80,622,480,156,734,152,248,874,809,533,567,229,589,335,929,888,974,785,169,657,99,378,925,319,582,641,376,639,547,310,202,235,620,377,701,294,29,2,91,472,686,54,633,191,266,815,89,215,514,38,286,620,626,846,457,262,651,355,681,948,135,492,838,305,758,283,397,315,719,90,96,631,551,950,200,147,779,671,212,279,648,184,371,557,626,597,113,590,535,74,30,920,128,902,67,488,855,350,813,892,301,279,124,103,627,947,677,778,648,438,862,199,684,249,183,372,304,742,255,209,299,103,366,866,889,896,551,535,251,202,614,478,627,713,552,622,482,394,210,764,238,702,29,657,109,131,265,294,201,194,690,223,790,348,907,760,16,615,398,751,760,94,842,937,904,381,471,753,175,654,400,920,730,613,84,786,816,701,823,348,42,998,210,330,812,747,881,136,207,303,574,610,323,573,938,553,955,495,384,200,143,632,962,125,519,148,64,200,114,603,129,578,840,35,898", + "64,304,727,696,91,461,934,762,899,439,513,397,127,112,335,412,810,392,286,435,552,230,676,724,487,261,753,127,433,331,29,15,701,333,308,991,283,954,225,390,265,637,779,446,193,870,614,221,286,894,968,830,234,435,629,593,278,533,14,125,3,832,102,226,859,141,253,965,304,500,529,735,151,322,310,515,713,22,982,977,822,268,119,989,382,394,537,915,631,713,706,329,184,844,503,392,576,686,986,225,158,963,882,825,624,198,622,1,658,307,30,293,875,531,689,314,6,838,510,64,275,450,708,471,763,372,838,325,121,928,2,463,906,820,596,490,350,508,962,89,899,393,457,567,75,273,670,994,800,426,243,494,345,880,853,442,806,82,95,691,533,140,612,758,320,385,765,881,823,434,914,118,252,37,157,207,784,235,278,122,377,756,219,711,585,968,13,811,724,968,182,381,173,729,898,949,356,359,423,954,520,583,917,277,337,204,208,707,975,849,76,753,531,419,190,571,161,323,280,691,655,639,292,994,859,393,677,613,833,352,57,718,302,999,152,175,231,844,966,208,326,812,902,323,723,955,596,457,949,920,358,612,603,790,569,735,347,861,921,452,458,721,91,1000,576,315,244,525,624,515,774,975,473,666,766,773,751,620,627,668,222,733,828,471,583,625,324,10,566,955,504,738,917,546,125,871,247,441,24,149,15,308,375,598,919,141,202,398,894,803,238,91,853,72,658,858,584,129,914,725,2,446,946,685,972,912,348,639,521,376,341,498,731,971,420,476,486,794,871,115,801,694,300,715,708,547,361,577,61,978,427,906,886,300,166,920,694,215,32,648,593,794,249,93,106,119,774,340,86,214,54,886,895,712,822,767,696,102,577,901,345,703,22,196,344,18,50,2,350,5,240,482,461,439,371,457,66,612,999,514,600,22,196,452,756,652,642,69,969,81,113,786,429,20,951,484,322,357,142,890,21,358,382,473,282,733,132,765,553,59,233,640,936,233,585,403,153,689,649,891,137,405,279,51,540,749,646,562,631,854,29,176,410,317,677,419,595,864,272,58,17,682,275,989,243,738,5,561,180,395,657,451,416,826,351,518,325,783,659,846,834,95,913,176,471,531,632,180,139,926,512,325,119,938,608,676,278,639,331,797,826,755,740,603,53,720,83,226,461,380,28,331,828,496,310,344,517,669,562,504,536,570,247,167,26,47,0,219,175,673,51,840,463,113,648,208,795,757,36,625,350,10,433,855,121,685,703,389,741,183,817,731,935,683,330,782,693,183,920,558,611,672,544,664,387,277,470,594,297,925,410,651,157,512,427,621,5,242,361,407,284,556,393,797,882,578,866,590,159,153,756,767,541,411,884,798,767,171,839,422,621,434,876,798,649,50,70,658,992,428,75,988,639,955,8,947,898,577,708,693,449,577,974,731,963,347,315,781,561,339,448,680,31,963,6,107,712,635,730,644,539,105,732,731,296,808,997,603,236,850,52,649,140,581,876,506,964,408,779,271,128,859,1000,628,960,815,733,583,748,958,297,342,270,654,778,549,899,897,381,576,954,423,871,103,297,312,177,394,282,187,319,335,848,782,396,412,458,863,273,337,546,649,299,329,991,307,235,900,454,182,551,50,665,299,934,41,85,344,535,473,706,483,9,414,896,834,354,647,120,997,684,401,218,131,31,987,630,561,539,585,685,220,237,70,238,830,863,326,32,946,399,805,136,765,468,549,240,528,104,893,932,631,710,961,343,113,483,585,268,16,424,605,717,762,555,457,531,961,380,832,582,301,541,397,985,147,708,269,454,982,669,286,229,120,164,974,716,873,901,238,207,393,140,368,413,543,828,897,786,593,217,216,205,833,109,330,388,135,610,914,86,822,127,11,335,459,953,844,529,187,928,746,343,120,677,734,993,843,822,102,943,646,588,788,476,822,505,625,702,581,825,634,152,577,292,387,746,593,751,478,11,367,246,877,655,354,178,631,459,233,116,1,286,674,10,604,529,8,931,299,442,983,46,744,589,891,269,310,696,179,701,753,18,748,633,430,366,24,250,387,95,141,532,659,281,253,517,675,967,661,796,750,858,177,896,728,548,986,907,773,830,523,498,640,588,685,362,321,758,569,697,512,601,385,76,549,184,733,853,177,517,950,503,849,884,447,404,310,759,700,439,170,183,818,177,604,774,405,237,86,909,209,238,380,50,321,241,289,5,471,767,241,690,492,374,742,109,840,332,681,92,248,194,604,55,379,424,460,249,639,414,948,199,648,641,469,551,859,214,703", + "833,961,935,25,681,50,653,349,269,767,511,242,521,211,839,535,873,28,359,957,689,600,423,122,793,373,930,985,628,512,904,204,218,269,413,161,866,22,107,40,527,365,618,302,826,110,815,251,162,813,57,711,656,108,773,928,329,194,91,699,327,648,343,671,348,211,826,701,457,704,10,312,515,66,485,120,222,921,889,175,97,154,302,419,372,544,767,508,843,209,721,551,885,669,358,5,79,386,315,277,938,358,611,150,304,669,350,330,417,336,71,830,376,371,868,174,94,387,883,58,890,837,496,541,669,650,839,996,412,17,201,632,673,478,684,559,444,39,451,905,843,688,839,19,917,375,9,462,382,365,932,516,579,934,501,982,242,517,186,374,321,608,405,239,320,188,126,68,645,9,589,833,532,884,293,152,736,528,197,392,452,32,706,465,700,391,867,644,477,337,207,826,376,738,43,24,678,614,594,650,592,435,328,594,71,457,957,320,666,474,92,650,671,177,541,155,656,190,433,930,595,563,327,121,4,934,695,678,538,600,784,815,111,584,461,21,403,301,836,605,699,53,427,642,52,899,95,336,811,841,391,395,897,794,96,501,122,922,827,885,513,428,839,149,989,596,384,206,288,983,240,536,769,937,28,562,970,643,953,301,119,400,252,181,927,671,944,206,758,619,655,334,612,35,675,956,759,425,251,466,7,761,258,625,136,8,641,676,659,701,643,990,630,8,670,509,74,503,868,863,437,900,4,958,452,995,842,80,621,872,612,570,848,674,693,820,243,48,872,699,576,238,472,359,435,330,434,788,846,894,800,224,126,503,528,703,445,192,883,297,519,558,884,749,861,922,206,559,993,355,216,301,666,441,854,221,232,258,634,611,750,627,675,438,97,955,269,240,853,579,268,565,730,125,367,95,853,495,486,520,389,473,949,904,647,999,535,498,977,397,884,693,880,188,938,952,23,532,841,837,979,629,34,657,533,349,489,165,112,432,836,607,542,68,953,202,205,973,492,347,669,991,522,435,947,459,240,132,759,168,68,375,209,19,210,781,881,614,360,104,543,842,592,877,446,496,707,923,376,979,835,704,219,920,414,544,608,274,623,143,317,677,840,512,689,542,168,5,258,97,512,910,143,13,262,436,181,196,44,550,828,659,676,609,773,467,904,948,922,912,779,909,716,222,295,201,681,108,262,8,328,719,148,466,740,173,219,0,943,466,945,151,679,66,204,981,8,909,86,14,696,363,803,650,989,298,826,139,996,285,253,293,732,2,397,337,228,286,208,536,806,853,872,711,301,331,901,419,888,599,871,135,233,606,646,751,550,529,483,821,731,736,450,926,914,173,962,361,22,754,608,431,966,886,514,430,202,64,586,799,717,435,874,254,967,39,13,878,834,596,961,59,771,272,351,316,945,891,226,864,6,946,873,711,603,724,209,326,985,220,675,887,707,977,808,912,469,795,970,135,729,853,825,68,125,146,196,94,745,250,267,681,225,845,613,582,890,768,579,885,176,344,171,921,568,218,961,237,154,197,275,187,344,92,492,38,603,727,373,92,877,134,584,224,330,521,294,472,1,449,755,843,970,811,217,58,645,383,821,437,193,172,828,973,629,407,661,910,525,891,292,612,278,556,675,90,790,494,325,573,408,151,110,825,954,480,312,634,758,272,832,260,42,533,579,116,602,790,331,416,43,392,91,935,9,623,497,287,200,477,800,422,916,90,155,468,237,890,745,261,430,224,576,909,104,697,803,354,816,208,230,921,183,603,476,110,190,683,819,445,475,92,654,190,686,909,399,980,126,73,66,515,658,254,121,996,442,464,159,153,714,10,369,157,943,92,355,771,978,767,934,431,873,913,444,136,828,572,541,210,768,27,464,931,973,22,683,446,210,14,372,994,864,780,758,37,75,579,276,596,303,221,149,332,425,263,112,347,244,794,504,412,363,566,748,899,137,23,154,784,294,681,65,306,861,11,931,374,179,541,529,359,126,268,909,432,595,259,312,398,939,6,97,847,757,334,436,178,980,558,538,47,718,550,590,97,201,229,523,8,325,928,545,522,554,219,109,908,418,885,26,975,653,687,906,825,303,690,887,839,140,108,701,423,623,652,889,328,234,575,595,487,603,155,185,746,399,933,650,752,343,929,309,860,321,816,735,432,250,35,607,390,94,347,30,858,936,445,157,420,434,790,582,324,628,610,895,569,99,854,465,877,444,826,29,315,720,391,753,909,833,609,180,272,699,758,75,760,193,394,685,826,358,192,79,364,751,600,103,215", + "958,667,530,379,381,753,696,608,961,210,728,302,897,518,724,479,81,34,467,681,951,825,812,869,994,960,35,560,768,291,593,253,405,602,585,560,863,795,464,391,715,973,537,671,978,28,3,367,305,244,573,400,363,545,355,698,685,660,571,935,678,645,483,794,350,420,791,816,26,528,588,667,702,304,368,177,70,82,65,723,421,449,809,372,63,174,399,749,450,255,620,322,889,29,825,187,28,539,789,694,666,117,450,158,47,678,936,6,777,426,315,534,53,451,266,375,706,635,624,352,214,334,803,876,885,478,952,38,375,286,359,129,845,45,505,885,668,369,104,718,416,202,14,99,386,633,842,401,285,446,900,431,671,77,769,420,361,317,760,679,485,286,754,895,882,709,464,546,305,87,190,496,525,210,370,391,534,201,369,42,706,140,819,932,516,617,978,532,833,79,427,249,948,164,741,219,319,891,886,380,606,246,422,504,754,271,587,457,65,549,613,232,465,101,482,113,510,376,313,309,964,323,142,560,682,29,331,954,364,163,712,550,268,547,644,406,99,839,532,324,56,262,803,872,442,459,278,549,772,149,617,156,414,791,470,85,758,120,777,474,615,962,883,218,96,694,750,558,224,691,255,535,204,692,898,18,239,330,951,832,73,472,965,599,66,175,957,268,81,972,212,339,928,666,782,68,800,190,101,111,580,724,432,856,294,463,52,503,227,405,24,760,867,698,611,511,587,751,632,281,932,947,88,826,675,958,169,658,333,740,153,696,14,361,142,219,561,910,605,941,545,38,144,42,267,865,171,809,74,634,779,826,515,492,205,476,768,700,773,542,715,707,401,870,194,781,668,677,808,817,136,684,661,88,860,813,29,323,847,724,285,800,441,280,158,354,309,750,432,38,135,709,142,796,274,147,146,832,233,480,889,287,467,637,536,858,238,907,419,685,400,192,359,463,837,791,719,257,698,852,214,329,992,288,525,537,686,558,730,210,101,616,848,752,509,786,747,987,298,507,9,618,645,720,929,336,852,414,395,976,452,83,834,614,474,961,87,518,611,332,437,596,581,39,53,822,746,818,981,589,303,983,666,886,435,792,876,698,728,288,359,169,868,190,451,689,636,931,641,232,898,730,260,383,615,859,818,736,687,782,136,70,662,948,318,64,663,634,478,216,242,879,866,911,91,401,773,501,574,917,164,887,227,707,850,91,175,943,0,615,794,96,351,251,572,362,679,452,384,448,839,335,867,646,231,139,863,926,98,304,822,737,233,614,239,159,942,252,378,475,524,279,9,722,308,193,110,480,410,763,167,213,727,354,486,984,75,772,451,5,307,342,106,646,5,72,698,329,632,876,383,600,620,84,115,269,551,132,780,33,839,127,638,402,26,316,186,226,707,422,889,409,560,593,20,774,143,534,515,861,671,750,136,161,969,275,185,172,155,766,327,179,9,103,448,534,445,880,725,231,365,566,621,739,29,553,607,484,438,12,342,135,729,538,145,456,996,567,226,817,320,295,976,724,359,274,410,646,28,974,118,719,88,265,494,554,858,387,450,407,84,382,298,365,104,98,15,285,702,773,513,926,329,89,289,925,375,82,987,918,990,981,649,778,980,460,630,390,452,50,581,483,282,288,468,805,829,768,270,181,38,214,853,49,209,47,309,336,669,339,599,221,651,540,692,66,90,696,640,246,88,185,123,10,133,242,267,457,632,151,667,862,329,226,318,976,838,61,864,774,17,976,317,199,804,41,301,91,506,5,988,132,537,737,534,491,241,433,588,349,440,342,486,884,374,399,143,247,267,395,754,316,581,896,732,739,283,723,398,520,685,578,769,970,624,412,47,330,963,495,12,72,42,822,509,913,331,792,807,810,665,6,275,914,964,689,182,272,948,892,266,39,756,497,337,780,221,33,982,637,181,549,224,2,462,38,172,700,835,759,281,271,677,102,350,585,163,45,373,17,328,343,3,593,142,871,706,340,872,993,42,150,606,226,737,518,231,434,410,525,241,620,335,314,304,834,641,385,234,159,66,156,775,65,960,73,452,129,370,372,981,575,783,101,921,732,951,484,623,446,326,666,837,724,522,215,709,987,433,231,552,667,608,445,202,592,421,135,324,876,999,590,961,383,680,183,594,644,5,779,540,490,196,208,498,975,343,245,114,134,918,444,336,617,161,431,806,204,919,755,237,57,421,989,446,47,821,671,198,810,861,188,699,65,89,326,76,515,734,581,629,77,201,744,483,82,239,583,331,905,71,82,8,182,199,394,67,634,136,182", + "784,781,366,450,923,587,267,775,876,165,502,445,426,484,907,928,755,857,568,354,537,864,567,8,900,156,504,773,294,640,240,552,686,887,567,858,137,443,251,303,388,685,110,293,134,878,144,393,440,731,740,749,350,399,320,724,454,694,794,406,589,33,905,980,625,728,355,572,767,338,175,431,329,144,467,936,441,831,179,958,85,606,402,960,345,186,68,40,519,594,912,162,486,813,612,744,210,292,34,958,820,909,659,398,893,414,234,207,181,329,909,823,936,895,169,351,296,712,800,39,19,166,187,471,859,287,925,413,629,845,259,603,325,80,735,163,22,971,791,59,888,67,855,934,132,807,691,103,994,220,804,969,975,811,829,822,305,930,896,203,630,366,922,851,227,825,969,47,290,535,715,857,902,671,713,100,215,608,345,533,756,989,180,34,734,990,22,913,945,44,629,609,320,629,690,267,33,887,529,306,282,880,122,591,715,198,749,981,336,610,346,160,196,337,391,92,863,522,335,602,633,624,555,884,580,947,183,475,108,972,8,549,256,492,928,934,422,310,249,948,704,525,531,182,919,123,125,816,861,700,842,531,171,462,54,341,757,589,701,878,644,379,626,386,327,872,769,733,40,429,284,759,782,354,479,748,858,15,89,34,81,672,954,716,319,756,794,458,655,459,131,734,730,192,610,451,438,596,290,967,41,291,385,259,578,835,31,708,775,602,945,395,499,578,515,727,966,247,100,150,289,234,530,565,566,88,1,523,987,297,710,169,72,884,805,485,905,652,451,650,110,953,759,10,448,767,192,953,971,251,319,391,659,966,120,647,417,240,891,925,353,206,87,618,762,601,138,487,38,152,757,728,498,630,431,731,44,563,598,793,282,702,626,49,43,629,686,496,249,4,526,455,649,868,820,907,605,603,136,32,486,955,725,276,727,908,447,451,893,481,889,49,338,138,862,112,92,969,797,485,668,670,576,85,229,350,613,387,957,245,770,816,481,925,734,532,894,528,368,420,367,663,705,307,357,484,468,261,599,425,391,149,732,673,300,162,744,505,233,929,415,138,515,946,896,593,346,626,33,936,985,215,38,18,58,967,4,774,270,897,334,634,445,81,341,823,499,307,557,182,305,344,471,716,187,766,74,27,437,906,584,536,806,551,922,619,922,813,650,743,160,893,792,14,119,941,289,144,288,297,651,277,228,469,328,142,673,466,615,0,645,479,730,550,573,161,841,490,415,861,827,667,753,158,333,263,34,41,540,60,681,18,373,87,424,789,146,252,471,768,954,905,112,871,380,880,522,143,310,711,360,441,511,548,743,103,587,57,331,844,588,799,322,932,825,592,312,481,314,858,431,681,446,460,17,752,509,911,628,697,783,419,357,886,537,296,824,656,21,362,86,357,414,221,694,491,867,576,986,241,202,465,168,431,737,625,299,320,69,39,708,521,14,14,54,29,63,605,732,51,274,173,240,570,3,52,206,575,194,223,21,212,929,458,583,10,395,551,600,710,738,7,81,656,15,342,962,452,143,998,986,507,636,870,48,158,453,562,353,609,100,251,271,275,880,890,57,163,901,656,184,507,296,284,107,10,517,175,386,410,887,716,215,772,837,719,95,213,295,435,973,862,729,827,19,456,755,277,307,725,105,409,700,940,711,323,194,620,281,207,795,407,171,289,990,720,168,919,658,744,273,457,995,688,133,485,651,361,346,956,400,792,718,886,162,276,518,770,471,474,212,648,996,366,965,76,819,452,634,218,769,263,195,374,924,987,728,548,615,908,827,754,193,800,105,559,267,544,265,844,113,690,887,107,280,621,994,904,419,11,702,34,347,312,579,51,79,909,39,814,410,207,967,352,663,835,397,135,501,777,218,411,196,107,342,285,765,75,149,997,979,680,86,712,225,768,175,232,885,933,573,855,466,325,515,911,133,213,995,822,219,793,830,156,418,964,29,821,157,9,425,622,547,359,392,810,419,253,649,892,244,716,739,16,381,743,805,490,110,213,696,842,210,765,905,79,215,538,630,258,553,74,283,556,481,361,380,568,612,206,364,76,744,361,528,134,591,810,587,990,6,976,455,526,257,778,92,856,872,979,97,922,662,318,42,77,284,459,72,3,701,776,344,386,398,596,908,32,954,572,877,412,407,215,817,845,992,349,707,306,656,322,871,944,656,386,519,593,677,107,959,657,32,184,535,519,232,646,816,240,323,295,173,266,661,589,553,31,84,584,629,128,68,530,843,420,154,298,515,383,531,912,116,247,565,332,389,555,675,878", + "852,137,822,458,869,751,167,367,862,664,794,175,222,331,442,227,33,853,13,604,567,347,134,244,677,325,572,651,724,613,679,543,573,586,324,923,860,741,79,620,354,509,77,346,687,962,31,652,989,960,756,160,64,219,459,922,623,446,164,408,410,476,280,624,415,104,409,917,150,943,380,464,551,939,238,615,799,465,942,558,169,764,735,200,591,585,975,252,774,320,518,410,52,627,505,493,210,478,517,650,308,515,936,996,725,672,663,144,998,697,226,971,431,691,285,117,47,181,346,37,217,461,581,687,305,547,62,15,82,980,961,25,939,631,86,885,366,360,999,700,998,610,507,573,233,362,467,102,710,607,502,324,95,640,793,656,412,543,860,453,332,578,587,694,833,43,488,496,448,644,64,59,563,576,737,402,539,766,963,366,385,733,849,407,967,70,436,23,587,332,894,874,797,770,766,78,227,115,793,166,429,464,773,744,565,131,397,998,590,827,398,546,234,867,920,222,844,375,328,344,558,807,471,840,529,821,991,878,776,768,339,821,456,992,216,356,594,255,322,28,725,635,554,88,93,676,950,92,144,271,171,753,909,337,837,554,95,339,604,846,518,226,100,213,333,64,687,203,300,91,319,672,728,900,697,865,736,349,378,909,358,568,613,113,814,341,407,791,359,77,237,615,903,424,82,871,561,56,694,545,250,800,924,569,180,518,105,378,576,582,543,374,565,329,823,545,411,297,415,488,360,18,482,205,961,15,542,60,446,945,569,235,949,673,870,520,505,45,184,522,409,585,710,424,812,443,423,425,89,879,44,788,272,692,993,789,991,83,118,730,464,950,407,425,173,25,997,529,997,394,253,404,520,228,861,905,125,919,714,121,332,486,216,411,775,440,31,363,482,967,965,118,268,996,415,594,608,849,428,343,35,441,833,533,486,997,655,826,924,864,123,889,604,405,718,392,977,162,722,836,927,508,702,771,363,936,874,253,756,930,306,295,489,456,454,940,858,778,157,494,318,267,508,54,524,561,879,795,447,274,43,966,838,774,49,759,104,11,813,97,788,834,899,138,221,63,844,681,873,830,334,995,58,551,862,459,715,896,917,74,705,770,799,169,733,843,906,378,63,618,319,749,262,564,424,216,381,451,478,990,213,519,987,373,451,342,37,681,384,160,936,729,535,981,962,910,3,220,661,712,539,94,650,335,326,347,51,945,794,645,0,872,446,196,137,175,1,451,576,18,965,900,104,723,394,660,942,634,606,927,668,739,444,468,481,918,786,997,796,415,724,748,636,665,164,721,789,361,746,3,876,455,885,764,231,208,107,375,501,226,739,455,233,94,557,386,399,509,740,300,943,483,707,90,773,790,305,921,749,658,865,556,335,896,871,735,909,78,568,817,155,774,677,424,911,745,405,733,462,447,220,348,625,14,348,364,394,448,291,11,496,661,107,954,478,454,385,660,593,469,908,695,469,508,71,297,236,572,127,316,205,264,483,750,897,222,671,574,726,967,515,913,407,500,284,97,579,19,251,875,926,978,508,336,161,987,994,519,851,202,426,820,236,841,820,387,486,760,190,745,742,170,894,608,447,187,704,913,606,594,983,67,377,49,290,453,415,410,659,691,65,400,686,451,150,992,424,764,642,186,23,855,158,643,501,982,367,117,791,355,272,246,925,882,571,143,856,490,691,628,787,152,987,593,70,13,484,664,258,894,117,714,116,312,746,889,71,424,333,527,895,168,582,679,387,816,861,379,933,959,469,141,503,481,884,528,208,926,262,233,522,126,50,491,19,258,697,800,195,801,746,882,638,761,35,447,49,2,764,429,251,21,769,479,153,746,633,221,775,497,329,593,747,528,455,336,325,694,62,715,306,730,217,852,764,941,873,880,886,149,693,422,953,832,187,396,36,714,187,713,353,94,326,604,373,34,620,647,548,524,554,5,343,952,9,172,912,994,698,61,438,137,338,184,635,724,358,983,973,933,50,364,398,490,507,887,324,436,868,777,882,894,805,484,755,640,66,292,640,385,96,558,670,583,260,557,973,234,107,76,648,656,343,102,530,563,763,534,68,245,661,399,900,723,599,584,967,104,361,244,366,111,894,423,247,204,931,986,847,690,669,450,834,682,110,872,504,938,201,417,19,749,151,744,103,469,435,22,65,842,864,721,940,38,338,852,65,989,969,222,903,556,156,937,816,543,595,157,736,686,154,719,264,409,766,650,118,181,266,67,718,332,4,327,771,218,763,873,137,950,238,29,806,661,413,407,457,364,282,273", + "817,842,203,28,307,573,699,320,100,770,618,155,366,633,618,802,447,663,201,166,632,937,460,960,503,215,440,444,213,593,428,773,583,4,943,219,501,369,5,129,462,24,297,881,283,180,700,750,564,127,948,685,790,63,232,973,290,907,425,574,347,665,24,459,175,695,143,93,460,829,624,224,580,330,520,930,27,328,771,87,792,475,463,688,78,913,212,489,460,55,839,824,900,320,450,217,590,206,855,977,697,669,290,228,755,641,303,437,287,211,265,127,372,410,857,971,943,857,302,44,555,80,49,680,319,297,291,624,782,788,378,415,567,365,26,166,104,555,811,513,330,924,646,831,487,622,153,136,30,954,136,173,245,846,181,740,155,728,380,233,524,17,224,9,235,69,634,562,542,121,707,176,54,636,135,186,491,911,258,962,152,185,252,992,100,188,507,540,360,749,778,795,599,536,960,64,532,721,818,141,663,993,820,974,547,480,116,303,516,377,197,332,455,480,217,942,775,835,914,481,938,897,196,240,1000,441,606,375,689,639,534,676,483,749,926,981,500,427,554,493,736,177,3,986,512,767,255,639,384,556,380,511,601,781,874,502,547,824,386,642,167,70,668,968,100,768,372,511,681,230,909,726,287,607,876,624,581,847,784,627,405,304,756,719,667,492,991,44,772,67,425,502,223,63,307,204,396,646,471,943,884,167,484,746,22,404,714,852,448,498,904,637,806,528,669,80,475,159,156,558,88,646,733,658,991,404,544,497,503,351,216,604,269,695,291,296,54,638,783,612,290,581,399,466,856,257,589,155,67,821,852,237,862,695,538,780,57,621,505,272,548,627,378,782,245,599,970,55,8,865,405,714,556,339,870,17,627,748,231,226,667,399,521,782,311,273,573,860,126,607,745,698,766,932,541,90,79,745,769,81,953,92,22,95,786,367,235,193,986,612,858,234,595,597,163,227,45,170,85,849,583,347,303,965,897,700,108,22,906,468,85,158,99,6,843,942,249,849,603,695,368,697,63,79,991,651,737,441,588,39,993,697,715,829,186,966,290,726,218,558,746,497,98,900,418,379,642,800,329,573,613,821,211,170,209,145,468,790,905,895,227,209,110,904,695,966,498,523,466,988,553,210,462,805,173,574,527,825,643,661,344,383,546,323,940,886,583,249,539,887,1000,721,863,370,307,653,999,470,576,258,939,40,470,936,957,549,840,151,96,479,872,0,325,582,647,98,590,508,660,346,897,764,885,664,947,774,498,708,765,437,158,310,883,988,311,998,778,727,562,662,900,402,145,255,799,612,830,459,266,602,164,991,225,819,309,606,795,454,166,672,321,632,605,719,344,133,560,491,368,469,826,356,501,914,273,502,841,623,483,80,71,772,264,347,191,303,307,243,764,690,965,650,190,860,714,606,206,398,968,400,100,210,616,957,750,989,435,312,679,827,945,727,709,572,520,941,583,460,106,968,797,148,499,684,478,136,264,478,471,971,493,133,498,215,971,673,821,867,727,942,803,832,371,960,165,403,973,456,130,33,483,783,186,92,289,555,293,941,982,218,983,748,366,696,729,220,302,462,522,681,893,897,325,290,170,663,837,446,250,323,356,508,266,760,619,675,91,592,116,939,778,374,20,841,439,953,702,684,250,904,530,457,352,899,99,165,109,426,627,694,508,196,632,928,648,984,631,811,377,549,808,31,839,369,246,107,818,489,902,973,392,832,957,136,645,411,438,57,603,319,485,186,230,437,133,211,208,612,382,527,115,592,542,209,312,233,187,447,972,869,730,223,476,368,23,439,634,320,516,96,220,716,666,974,614,927,63,855,613,648,591,727,190,478,342,278,305,660,564,856,821,514,128,850,420,576,208,346,365,345,106,779,189,201,541,793,993,400,183,455,452,671,28,332,918,647,730,694,952,388,590,840,638,912,969,233,591,826,288,495,938,395,255,472,200,961,555,718,771,154,146,268,938,183,328,149,200,526,621,649,494,513,342,117,150,289,903,210,309,241,139,847,453,20,866,404,41,832,124,210,943,411,172,385,128,913,411,852,708,23,455,756,477,402,970,986,807,205,98,822,421,58,619,480,811,358,903,446,147,491,232,22,950,264,271,348,206,966,108,625,361,669,928,988,118,906,374,954,712,444,298,569,22,496,808,123,521,886,74,601,412,289,110,947,573,439,994,964,91,701,151,977,646,293,787,24,463,857,480,501,846,360,367,220,102,598,913,143,324,611,837,892,217,677,114,223,994,785,851,503,134,892,42,737,986,775,913,154,550,645", + "835,79,704,899,21,947,775,980,417,60,915,588,49,920,311,604,575,936,581,286,690,378,857,367,399,958,733,748,945,845,335,718,657,130,239,118,839,188,711,459,268,929,889,557,740,203,75,105,392,194,524,529,760,732,476,173,150,330,311,313,477,715,646,900,6,182,957,154,543,378,880,476,180,984,593,570,843,988,168,24,832,593,692,179,39,6,40,670,479,258,938,255,730,387,524,278,496,228,963,45,380,210,512,263,9,372,970,537,9,166,996,593,710,573,785,36,121,224,128,623,672,357,265,766,553,360,539,788,533,239,436,3,895,231,544,921,452,728,213,540,145,694,63,462,107,392,825,616,368,279,165,50,559,94,361,50,227,17,853,140,56,660,899,522,760,115,805,922,175,840,334,699,857,503,827,322,206,948,380,230,997,352,131,576,558,702,351,741,54,381,171,558,375,240,843,554,955,279,293,817,176,83,704,183,96,572,693,478,569,264,998,900,546,877,37,915,725,741,274,400,557,793,534,96,335,464,226,886,25,419,101,16,226,213,917,338,378,714,302,225,490,2,621,497,3,4,856,815,401,681,137,817,247,415,824,872,768,832,735,463,979,509,503,620,977,471,333,716,580,505,330,69,799,514,137,259,31,995,600,572,398,978,771,741,391,113,53,435,985,660,472,664,637,727,813,829,958,177,600,431,99,516,23,576,94,472,38,532,78,629,668,427,803,268,679,663,704,618,22,1,562,290,418,432,554,694,723,806,988,162,133,523,979,873,997,209,661,604,594,665,380,522,151,638,833,467,769,585,640,167,340,515,480,705,815,153,154,224,949,422,87,99,339,721,864,325,248,339,421,281,269,28,711,300,124,28,518,701,712,801,514,492,25,829,397,62,558,412,678,27,801,814,441,53,148,779,713,254,250,101,506,730,231,596,596,890,505,831,282,474,51,120,6,763,387,377,944,862,743,638,941,45,645,983,761,213,157,901,810,733,341,455,379,819,153,121,929,321,948,428,925,739,856,122,126,357,20,809,365,296,634,487,262,456,316,55,602,723,904,469,972,435,502,349,10,201,107,380,678,921,314,342,879,875,410,694,587,742,818,126,863,346,650,989,415,831,839,94,389,619,845,984,900,154,512,25,186,344,467,261,193,913,422,273,948,365,150,134,547,391,581,993,475,955,89,866,282,345,640,686,386,475,313,752,693,41,463,679,351,730,446,325,0,298,614,702,376,468,14,553,744,586,465,383,522,582,532,653,744,184,183,199,246,295,65,338,705,348,793,632,989,295,726,598,901,584,633,754,375,343,927,431,924,426,586,552,177,213,929,947,62,203,957,713,964,212,129,561,773,277,450,865,231,87,937,275,682,708,351,672,893,397,28,76,805,484,517,151,280,888,697,400,746,420,546,163,932,1,180,742,331,928,845,426,817,599,125,3,725,926,959,218,467,583,796,147,125,484,77,482,57,558,563,878,615,836,897,449,634,179,710,259,617,623,133,529,642,96,7,726,4,694,525,41,995,398,104,31,727,408,800,990,762,555,148,897,854,421,857,212,75,430,286,655,629,369,161,352,122,439,681,369,914,39,346,874,789,33,36,431,966,848,230,151,320,617,976,610,34,170,561,36,130,459,456,853,717,163,286,125,583,838,153,623,325,475,205,99,198,310,773,496,557,477,552,721,181,209,85,205,493,179,929,705,366,970,148,805,546,462,53,614,380,48,140,961,80,404,595,578,13,980,351,396,705,8,685,980,245,525,725,989,528,50,960,67,39,485,647,990,623,520,639,561,698,904,306,54,742,5,528,403,561,717,756,460,651,226,280,168,623,369,715,974,226,386,924,484,214,457,742,196,92,789,776,138,436,17,507,730,713,550,489,322,125,619,151,967,240,423,312,51,259,848,227,922,845,543,223,43,725,629,885,376,475,470,564,530,417,508,398,384,538,111,364,422,847,726,732,485,727,359,948,949,771,690,766,734,590,268,191,201,298,42,661,331,609,364,249,476,501,406,897,643,492,804,938,273,248,189,884,358,465,571,841,553,326,142,283,808,34,179,490,614,834,233,714,482,427,325,116,781,339,447,52,281,348,35,386,970,541,287,444,976,565,864,259,44,726,750,858,163,877,348,20,620,629,739,781,490,545,278,475,281,19,971,238,164,343,908,398,831,488,177,33,131,906,55,635,45,154,936,202,32,899,898,364,76,771,838,896,367,191,324,943,805,76,3,975,157,927,330,876,350,204,163,283,472,811,848,265,829,311,415,913,229,458,398,690,126", + "829,937,449,169,469,221,723,478,548,884,205,718,177,226,106,479,33,943,520,724,213,754,130,870,296,101,812,881,145,729,862,918,485,454,976,641,585,978,819,516,485,890,830,386,768,776,618,48,447,899,452,121,999,698,563,998,798,282,34,848,17,613,516,495,6,865,806,695,224,384,532,52,560,752,688,787,636,967,738,882,888,681,643,383,722,776,599,954,538,512,650,395,232,55,17,169,874,268,746,470,193,796,32,94,254,806,604,293,638,912,107,631,385,568,913,193,921,271,328,987,123,948,966,895,991,491,980,598,97,325,836,514,12,924,809,899,151,577,703,668,991,602,905,921,258,225,903,520,240,290,466,302,920,859,157,391,742,103,594,92,805,906,581,787,529,430,944,302,769,690,612,112,671,69,328,268,497,203,925,484,879,600,319,13,437,20,402,208,582,570,485,325,944,707,273,179,107,623,440,416,202,966,768,250,156,997,642,761,58,586,274,197,105,941,752,779,439,799,427,645,24,894,260,383,125,141,787,229,244,386,168,263,13,129,651,303,391,702,538,370,892,589,766,726,49,743,797,80,117,671,875,73,237,69,187,788,42,660,44,964,322,783,424,4,340,427,686,838,184,921,579,237,225,26,520,94,179,735,771,186,21,989,126,111,303,292,6,373,947,550,228,718,384,863,267,557,916,284,660,374,56,400,393,320,892,963,217,59,121,572,898,659,329,466,600,558,572,208,2,890,539,982,164,751,26,64,73,124,222,794,178,806,864,923,74,280,443,676,930,901,131,147,281,369,716,310,778,39,961,215,582,10,91,401,800,135,633,108,565,102,699,874,203,542,394,43,582,187,868,391,715,429,700,274,368,613,892,165,813,905,960,499,606,848,801,754,918,564,597,320,531,402,447,795,584,643,818,236,950,990,567,975,710,785,515,806,961,699,120,726,512,741,321,641,32,389,223,625,338,316,528,517,743,576,632,70,512,395,104,139,888,676,996,480,129,40,48,308,201,40,479,318,993,553,923,912,346,433,572,852,392,360,210,366,804,277,139,525,263,654,747,826,417,751,548,984,893,937,99,961,326,249,138,54,214,919,496,680,89,517,551,224,186,819,197,347,67,614,222,107,28,938,31,138,960,489,927,429,41,249,518,292,490,364,54,422,449,141,461,114,964,591,257,196,752,77,928,608,884,922,683,519,414,224,878,448,113,66,251,550,196,582,298,0,906,575,457,953,32,225,383,157,725,882,707,633,858,153,219,408,707,729,88,466,545,991,235,734,336,781,542,128,111,560,592,968,72,200,340,511,653,260,928,643,568,663,916,574,288,325,86,591,706,876,189,807,255,623,250,47,304,164,572,783,674,470,375,765,355,329,696,241,37,849,111,403,490,780,275,141,845,625,521,169,688,268,369,512,687,518,455,124,981,8,382,807,233,988,374,108,34,4,8,904,487,167,919,397,476,630,940,906,810,489,219,245,267,271,775,149,672,103,262,405,99,219,936,974,349,272,701,372,211,610,141,968,301,534,243,183,526,677,387,345,953,671,542,993,935,503,883,566,29,560,8,567,785,752,390,767,801,965,116,370,797,264,570,663,700,562,355,353,263,468,78,35,664,623,54,940,284,199,449,627,714,445,24,511,794,741,734,895,144,862,600,614,832,589,781,206,396,405,348,556,583,27,520,782,387,702,456,857,79,949,234,656,523,431,585,525,667,211,263,222,588,638,312,581,175,589,242,686,171,979,871,403,587,138,865,248,839,477,177,274,299,361,28,867,464,279,15,897,200,248,756,2,783,625,484,389,757,503,887,645,193,488,642,867,422,928,370,481,610,76,268,816,738,542,910,581,289,575,365,434,793,868,871,219,549,170,168,581,628,432,477,731,765,865,355,485,850,436,298,875,582,568,893,954,790,253,626,909,527,418,101,937,663,229,51,91,720,471,336,963,425,880,643,216,70,449,101,929,673,521,45,77,245,878,940,85,904,964,271,992,887,297,400,346,351,472,304,168,91,426,383,707,38,606,165,280,576,487,794,803,563,68,393,271,640,953,293,571,821,975,326,695,612,753,815,178,588,949,848,981,576,573,562,628,115,20,969,862,177,587,695,702,849,671,303,193,568,58,357,221,960,416,539,388,752,803,630,381,694,774,285,747,958,972,233,852,792,223,871,142,270,797,559,521,535,987,646,116,395,489,223,11,564,31,77,475,500,36,287,918,317,54,649,689,261,866,529,934,161,816,532,327,123,944,69,8,786,667,685,251,243,252,542,980,680,619", + "911,810,665,627,992,624,274,217,423,394,675,803,177,766,321,222,422,410,811,206,675,475,818,755,255,385,832,704,885,272,126,713,886,403,121,852,125,576,411,879,875,335,980,961,835,773,281,863,100,943,575,339,736,465,740,206,468,681,726,227,138,446,460,42,330,9,381,580,300,265,354,917,177,374,651,210,832,714,740,770,390,799,307,410,805,479,898,458,277,814,689,299,502,350,289,186,92,325,511,709,842,167,794,341,925,438,163,114,326,59,923,956,447,169,413,631,832,256,177,251,752,611,73,896,59,910,399,58,708,134,247,724,780,498,657,257,833,160,190,739,548,347,766,209,975,549,696,505,553,947,212,826,90,92,211,24,458,717,364,446,368,216,789,142,340,322,697,324,291,381,958,293,722,815,378,54,834,210,381,943,719,10,528,689,410,142,123,715,20,909,411,553,69,294,203,996,295,874,532,235,44,975,546,992,598,416,85,682,703,225,529,801,817,375,412,710,98,313,508,494,1,499,563,859,782,272,876,413,639,725,214,794,385,199,731,779,297,872,578,382,617,359,401,645,500,900,916,898,252,261,608,922,711,933,601,640,575,703,954,378,99,941,453,766,916,564,474,653,768,6,503,511,698,91,742,807,189,144,219,211,984,630,626,819,195,365,778,79,389,599,204,330,907,622,394,805,393,711,791,722,124,265,185,140,920,573,344,811,920,31,262,587,211,24,778,993,923,504,337,778,821,223,925,939,758,349,779,194,504,396,552,171,175,236,459,43,98,522,21,332,130,255,16,287,754,644,300,892,38,462,696,456,497,597,519,104,112,355,96,68,624,130,600,356,690,321,740,227,903,510,324,683,628,11,689,825,718,352,672,976,854,985,901,727,561,816,185,749,816,753,710,808,255,189,66,562,681,628,650,102,933,553,103,881,889,828,942,782,363,80,278,51,198,294,742,620,25,362,983,974,950,539,682,587,17,606,537,313,299,521,345,241,657,139,653,329,646,724,781,386,991,521,99,831,20,887,45,647,744,570,181,515,933,470,756,558,115,981,124,195,338,218,702,38,888,600,42,697,269,997,404,98,479,214,95,111,3,144,37,37,991,435,271,765,804,341,168,460,164,761,138,908,390,159,779,561,52,127,207,756,568,16,770,910,716,588,622,878,633,693,670,326,122,280,311,748,118,67,558,192,445,476,770,137,912,525,648,204,572,573,137,647,614,906,0,370,984,879,702,29,931,78,991,190,832,402,398,647,64,289,47,96,185,907,383,487,251,504,410,350,44,686,1,765,471,767,770,188,355,383,871,519,934,56,795,661,616,711,507,625,252,980,613,36,741,784,603,921,181,779,552,627,424,960,102,581,168,608,34,626,143,8,790,847,267,813,702,153,789,800,498,992,139,150,530,332,598,41,445,351,73,280,812,573,9,652,570,352,411,18,76,782,741,643,687,976,572,838,187,386,831,527,840,257,317,821,144,84,307,400,746,400,937,911,604,374,119,379,215,424,244,63,433,647,715,193,729,870,898,497,542,918,552,698,388,902,375,320,732,546,627,642,56,491,223,469,373,756,596,932,427,7,676,122,869,853,189,978,278,183,174,207,354,336,860,838,377,768,117,246,104,35,535,953,585,208,535,254,701,588,690,336,446,703,153,645,106,964,926,389,168,238,214,74,868,651,437,853,801,980,365,12,299,545,917,125,791,893,466,485,971,710,874,381,806,756,922,647,309,273,36,874,377,547,450,999,560,310,621,440,943,87,553,370,83,997,397,26,781,526,331,509,584,205,136,659,964,882,989,228,619,354,238,175,482,23,619,526,960,810,136,638,216,123,232,935,615,895,831,846,402,813,605,453,432,327,928,615,268,341,799,593,737,862,882,178,508,605,949,509,221,675,117,237,575,205,616,137,798,861,739,95,266,726,535,716,302,450,151,626,404,898,372,188,627,694,239,608,858,866,994,505,717,555,489,845,236,120,335,21,611,863,371,582,791,292,111,901,908,759,260,495,371,490,483,351,4,770,589,359,296,16,143,882,395,258,234,169,408,716,193,713,595,806,274,37,930,190,258,256,950,431,58,581,396,333,649,726,668,661,289,330,279,482,413,782,1000,471,920,486,629,364,551,322,247,299,100,565,77,837,389,460,30,752,726,756,854,321,746,888,720,463,470,412,186,964,208,547,3,360,81,448,267,107,308,945,946,402,9,355,800,898,211,127,136,242,455,493,336,683,821,541,153,45,577,574,271,485,681,558,293,811,684,185,983,177,740,512,308,628", + "254,56,158,879,196,363,910,344,462,127,682,615,907,981,849,758,915,480,100,173,76,130,230,146,806,530,11,951,239,870,921,122,271,260,263,753,170,577,893,752,650,472,191,933,810,609,424,611,626,924,917,876,258,566,645,603,342,508,876,949,351,548,744,844,468,871,866,49,371,415,353,157,920,989,801,886,766,190,992,557,296,161,102,985,997,225,345,148,541,80,853,368,995,487,5,946,675,578,353,812,384,390,100,904,585,560,339,607,623,530,549,176,155,835,530,323,294,235,884,65,107,930,406,684,544,916,433,971,32,331,461,931,232,392,169,185,114,913,457,703,697,171,296,269,730,599,73,483,320,379,147,99,187,190,508,347,533,35,901,730,748,159,365,759,604,698,2,623,504,133,856,187,511,377,885,158,476,593,45,148,109,574,158,18,989,348,749,808,446,273,239,939,442,685,809,832,760,839,734,98,286,350,851,765,594,920,278,327,257,337,83,861,265,948,326,777,743,659,410,382,518,639,516,65,225,237,608,255,842,324,717,599,3,744,999,104,956,230,284,398,265,781,502,574,668,258,249,366,206,390,436,252,269,314,74,394,704,772,42,629,392,384,756,687,212,936,439,418,744,213,306,230,633,201,368,689,75,970,634,886,688,647,831,171,418,546,618,610,539,348,808,464,579,936,477,402,916,110,694,159,776,206,343,729,895,10,356,856,247,665,777,586,659,541,203,117,55,450,411,33,179,548,656,275,799,494,214,348,178,715,553,117,43,417,434,870,675,702,373,190,841,20,509,154,961,97,922,92,670,95,715,811,10,766,188,708,937,250,370,857,63,845,798,52,442,595,885,560,28,340,136,907,884,254,121,698,248,998,702,968,254,274,907,839,757,304,351,974,758,25,65,178,467,939,911,224,981,313,517,614,29,906,215,602,65,605,472,127,202,186,920,997,624,923,709,835,323,726,771,167,608,950,850,8,293,643,622,688,8,523,411,490,485,357,160,670,325,808,878,215,781,93,838,250,600,300,955,114,746,936,302,481,156,702,256,163,145,91,823,38,634,64,771,5,935,805,42,520,401,613,809,372,23,794,967,699,41,788,55,789,597,40,742,434,169,350,76,541,544,971,668,307,910,381,746,650,622,541,743,15,762,569,409,23,430,518,449,473,409,447,57,852,268,623,334,188,588,996,476,734,41,597,309,430,875,900,208,981,362,161,175,98,702,575,370,0,706,986,332,592,894,705,252,715,406,936,735,120,674,106,231,850,25,145,435,160,923,776,568,143,628,33,429,790,859,144,918,782,610,923,506,463,460,765,371,523,393,363,747,493,436,50,948,972,372,129,477,942,655,808,243,968,437,374,643,930,292,305,710,722,934,17,387,78,499,44,547,608,487,460,314,539,856,185,373,589,583,372,608,289,631,558,416,505,420,56,763,966,199,426,566,857,970,890,431,50,506,189,276,285,645,347,519,992,559,867,362,598,94,879,764,901,45,10,836,932,987,405,336,539,90,390,717,485,398,411,949,743,881,203,655,713,145,119,498,728,663,843,502,887,972,188,462,907,343,852,206,862,412,849,553,410,400,18,368,206,419,303,55,457,860,436,5,992,14,435,714,36,836,684,702,455,948,347,26,747,570,854,896,581,880,960,453,498,406,532,884,377,764,852,560,611,729,447,227,397,29,112,717,237,898,712,745,926,959,132,114,463,34,756,979,393,602,815,510,106,64,188,907,866,857,990,435,359,206,223,466,159,939,955,949,635,775,826,737,222,500,262,334,793,772,879,758,519,157,370,682,596,275,567,167,476,931,571,961,39,704,894,222,466,487,410,183,248,641,458,934,7,218,956,624,328,19,77,682,356,214,197,896,939,820,906,412,225,140,230,287,277,772,387,728,163,236,703,125,309,955,318,421,250,272,547,739,885,155,8,538,741,621,498,125,918,519,906,797,858,703,974,364,638,980,610,937,749,398,291,406,926,822,95,889,72,578,93,112,466,235,937,428,680,926,685,106,797,359,812,121,796,302,89,81,520,670,131,864,64,129,627,523,721,654,593,543,184,17,739,316,546,460,396,734,66,272,210,542,354,752,982,186,296,577,634,746,231,656,474,683,196,279,429,440,54,690,534,274,691,568,194,247,725,643,675,789,71,317,698,275,767,944,316,422,534,112,428,800,206,694,372,708,124,51,695,142,198,347,293,213,800,97,168,773,149,904,260,330,707,364,168,965,449,242,224,279,626,805,39,844,875,272,957,953,800,126,450,117,759,720,81,68,35", + "917,179,322,97,617,693,535,820,298,512,134,292,649,422,156,618,215,407,152,169,9,76,476,727,411,164,913,940,150,953,511,936,884,980,217,808,46,433,762,776,101,775,263,292,531,6,450,883,777,599,606,789,943,360,766,195,493,720,938,587,108,57,244,359,163,645,246,236,921,166,172,787,514,128,449,478,44,674,711,136,122,850,648,164,504,65,878,592,214,282,33,838,994,721,816,346,701,81,805,411,286,792,547,252,113,949,488,547,225,910,418,365,621,501,256,68,274,189,989,168,138,778,535,21,492,439,785,50,345,702,580,920,117,581,764,765,53,227,334,630,596,797,993,927,300,774,159,150,809,828,123,603,358,729,891,560,457,31,766,756,297,221,730,973,863,533,769,418,530,697,134,572,594,739,930,734,760,156,192,598,261,565,64,596,120,157,108,688,967,955,745,426,193,397,554,770,73,628,660,755,539,327,631,261,141,8,480,562,371,172,776,32,773,708,745,779,548,349,693,866,153,650,93,233,871,691,901,85,90,998,149,150,66,852,679,635,43,100,402,95,777,543,700,42,179,208,908,513,241,622,62,786,699,393,915,18,395,391,897,235,869,310,796,578,825,705,395,315,950,161,962,940,234,975,791,40,938,684,528,289,594,253,145,769,737,841,493,770,595,816,649,866,407,244,36,453,20,98,648,851,745,278,563,731,191,764,623,302,374,110,542,897,547,185,725,249,424,944,930,577,643,594,480,961,93,535,989,787,371,936,893,522,998,917,975,170,899,324,808,420,52,92,688,922,786,479,298,748,766,878,996,664,834,254,983,905,427,462,467,550,86,244,714,761,10,423,928,830,965,846,630,454,118,740,134,986,632,48,997,682,23,402,942,976,795,175,43,479,687,869,921,126,773,244,241,997,578,905,440,565,495,958,165,141,486,228,884,416,272,54,832,86,577,869,498,703,874,907,257,697,643,984,404,559,623,941,615,83,460,283,400,581,348,620,617,879,353,789,956,751,84,474,36,56,284,911,484,221,983,889,522,917,656,69,198,747,733,841,489,818,288,740,649,860,125,594,507,443,476,448,38,997,563,796,374,752,466,178,377,711,381,77,403,775,771,808,404,592,14,299,16,693,619,534,890,644,511,901,472,326,160,947,868,75,230,25,8,228,798,510,450,501,576,257,222,541,803,958,678,43,796,183,921,835,33,17,795,8,679,841,1,590,376,457,984,706,0,178,535,19,672,827,664,783,158,89,178,914,934,664,80,575,119,606,551,787,993,827,484,76,59,854,922,589,606,557,452,922,436,597,445,743,329,271,961,352,983,544,469,110,481,801,893,371,729,83,578,293,328,564,415,421,782,171,266,677,528,266,441,328,941,310,253,17,500,482,907,912,524,266,46,939,318,762,250,97,382,637,244,273,52,854,156,667,801,78,46,86,809,67,384,650,959,156,40,47,276,143,942,629,423,2,53,757,241,83,871,877,952,336,215,1,364,531,962,618,139,841,310,270,777,449,50,110,325,399,838,893,766,288,284,340,54,248,440,201,532,486,888,85,116,373,232,613,84,529,196,716,151,702,828,360,177,634,246,716,665,117,514,467,888,750,162,656,127,823,192,334,285,982,350,737,727,295,181,265,705,441,593,978,714,532,478,751,952,372,647,226,442,532,474,858,703,205,530,4,585,564,667,440,420,874,295,135,196,407,320,277,671,216,242,736,302,508,777,323,575,984,85,845,947,895,816,578,488,868,655,145,23,141,683,556,369,254,776,511,141,520,423,551,353,278,994,527,989,346,446,981,776,967,844,766,956,682,398,48,969,876,332,985,598,476,787,799,996,799,737,437,760,636,378,76,21,506,788,646,23,828,334,899,337,357,618,703,923,730,906,842,502,38,445,205,735,672,728,546,487,19,483,461,417,598,101,210,12,531,170,874,367,327,770,795,909,638,945,621,238,368,765,802,262,367,513,96,727,461,794,216,698,19,510,707,480,943,352,486,715,393,660,136,842,116,986,995,282,769,274,875,650,476,237,417,950,439,429,701,861,788,480,104,876,593,549,170,958,157,560,518,215,927,211,57,993,703,269,650,516,793,936,746,469,949,44,593,35,675,516,778,85,718,268,298,355,338,830,188,318,253,223,677,661,193,590,959,575,884,672,459,923,357,758,823,286,335,570,442,803,384,653,61,558,808,761,661,617,750,165,197,932,128,758,203,56,953,372,797,467,110,330,188,64,485,876,866,112,910,222,514,285,631,40,471,861,948,381,542,682,360,952,405", + "706,335,293,84,598,442,893,636,834,403,82,686,653,821,307,20,331,296,797,759,169,148,79,867,991,236,675,30,305,298,293,35,669,7,283,303,277,906,885,647,224,455,42,22,652,405,624,706,874,490,54,558,713,68,794,823,407,802,896,986,240,746,399,543,618,439,563,216,377,128,466,660,21,253,746,666,104,272,239,898,258,194,549,288,92,586,3,581,266,603,468,172,628,938,136,557,280,896,838,772,37,394,268,884,480,383,245,808,824,332,557,752,481,701,401,222,984,599,189,714,426,116,502,936,117,630,983,792,758,144,455,436,332,277,897,611,624,394,888,93,481,447,883,175,399,929,405,969,956,811,276,633,330,188,835,438,144,870,245,830,105,265,343,131,522,578,662,867,10,757,398,752,861,866,788,571,497,507,660,342,794,858,288,784,322,500,743,798,604,626,452,872,663,535,277,421,374,901,778,724,394,197,212,332,678,496,700,846,619,261,922,592,586,100,724,716,361,257,791,303,744,729,511,249,610,359,634,535,676,491,155,504,850,508,448,891,971,249,155,81,306,537,308,591,344,216,697,448,956,582,822,830,239,823,287,958,741,981,273,690,112,110,882,668,339,570,532,51,970,375,555,814,640,531,286,138,34,242,776,894,178,174,30,271,124,137,642,480,105,846,63,888,365,563,808,976,160,409,416,986,269,716,433,726,444,627,12,549,868,716,665,673,505,329,469,677,775,24,919,589,843,946,400,889,739,246,982,908,69,912,498,529,1,277,841,190,638,891,187,338,646,951,675,126,766,135,908,914,461,621,370,430,780,983,646,655,551,639,887,438,57,321,488,543,408,553,338,548,876,498,923,736,556,187,331,143,301,190,582,580,840,744,729,16,413,360,140,538,851,332,245,355,713,939,784,837,233,602,500,547,2,801,627,496,453,521,973,990,907,336,2,522,889,560,48,896,28,899,546,358,879,415,241,345,984,212,364,558,843,727,684,962,615,369,494,151,552,961,455,951,84,875,480,878,137,168,457,864,698,554,621,938,823,748,758,887,737,628,523,994,815,3,185,709,571,114,714,942,888,76,243,321,290,824,178,558,389,689,802,926,839,777,302,784,666,519,158,805,275,942,361,177,640,476,434,313,315,759,58,451,710,493,137,549,769,124,137,857,217,698,104,698,14,627,687,557,202,526,348,229,461,25,340,989,643,345,757,909,452,490,451,508,468,953,879,986,178,0,501,570,791,120,644,646,281,842,489,621,670,320,759,150,752,929,456,740,727,158,546,38,32,460,196,981,297,745,297,233,183,163,302,221,695,799,511,757,438,989,627,931,827,280,264,459,152,56,155,502,803,243,660,511,398,458,658,719,954,183,90,110,49,98,275,856,649,587,468,275,376,739,559,726,549,460,430,992,958,80,987,28,54,366,455,96,822,38,720,652,583,502,507,773,555,134,561,614,894,815,866,286,484,526,479,54,66,693,490,305,877,169,83,463,147,673,832,902,498,448,610,2,554,593,179,720,653,46,21,514,84,648,992,587,730,346,987,702,688,883,687,344,393,182,260,495,414,180,816,678,808,669,534,250,484,717,580,617,475,262,826,875,872,464,52,45,433,797,759,853,486,580,395,567,833,367,402,13,471,852,775,224,141,334,827,605,771,446,758,52,613,430,877,172,31,742,532,685,150,929,751,107,621,156,698,200,325,445,807,338,820,559,216,769,403,925,780,89,178,663,274,300,999,507,614,561,583,324,572,308,621,439,843,871,970,245,449,943,432,970,885,178,207,277,47,172,178,923,494,663,625,509,344,59,530,732,588,512,832,525,559,988,387,838,757,99,93,331,794,515,27,622,306,32,556,946,539,107,805,876,910,201,820,782,967,840,750,722,595,606,116,947,85,481,970,454,336,553,540,200,519,144,152,722,193,528,548,434,853,99,199,698,284,997,732,900,506,712,699,629,297,600,4,487,369,813,961,586,101,90,307,482,375,308,803,306,739,682,665,189,638,855,772,719,305,183,988,443,35,202,104,463,530,600,933,425,213,724,204,990,55,734,670,920,986,506,259,196,29,914,371,192,603,56,819,309,270,404,573,954,3,893,966,724,42,286,471,879,945,99,706,693,233,849,102,961,911,113,365,468,446,952,391,781,947,157,318,477,324,250,163,43,57,843,347,214,327,592,62,469,594,895,9,988,650,99,788,948,964,376,110,48,129,796,621,825,670,611,747,274,29,748,932,683,701,301,156,986,946,34,37,403,993,493,740,552,562,21,156,216,938,846", + "681,760,927,702,60,41,644,555,146,270,307,184,881,494,666,385,340,118,321,735,886,341,982,587,371,696,306,765,315,223,556,406,423,102,269,272,209,848,177,932,406,721,498,619,380,235,602,620,280,542,246,127,134,63,704,714,198,401,653,597,770,326,78,109,555,561,49,411,677,912,29,19,519,262,77,399,382,539,701,750,999,122,897,230,937,900,538,795,173,977,436,47,431,427,648,748,643,304,518,413,753,316,309,251,486,851,259,845,17,888,206,934,216,622,28,291,510,84,774,431,934,484,136,204,665,699,208,942,697,198,59,751,209,360,948,110,1000,752,962,630,735,568,398,177,741,427,177,979,734,227,715,352,272,676,479,807,881,650,810,110,625,432,340,355,211,45,9,336,737,34,651,813,83,625,811,206,878,433,742,212,788,225,217,89,968,992,839,980,731,948,163,294,847,617,311,882,461,817,469,100,753,945,130,540,531,705,666,624,875,695,573,647,673,368,248,896,405,734,15,498,742,890,997,536,319,115,598,430,321,740,21,859,970,544,53,157,237,780,237,80,770,70,995,781,966,714,288,378,853,602,106,568,287,315,999,190,748,991,704,909,765,96,238,336,703,29,704,172,142,922,930,973,645,567,617,371,560,609,116,530,63,660,950,27,147,342,50,628,816,724,192,197,941,64,146,371,406,816,199,368,494,421,56,169,122,921,270,589,843,560,12,406,898,30,158,945,116,444,119,732,202,806,551,447,736,570,787,91,956,23,661,823,295,391,3,907,135,910,626,326,513,890,55,465,726,577,148,675,641,320,916,955,218,114,370,605,131,149,528,877,792,293,410,447,806,890,656,613,850,429,459,918,421,364,670,446,219,64,266,440,766,964,583,277,719,734,846,618,815,591,200,155,215,737,126,746,815,935,199,805,652,47,848,16,541,460,418,283,879,136,538,390,15,137,282,681,535,728,95,444,446,725,608,721,714,710,200,529,792,428,38,993,614,22,931,376,318,202,25,59,732,286,161,222,781,420,994,68,515,17,954,248,454,354,78,773,849,308,168,450,316,939,20,904,24,282,273,403,328,689,522,614,735,772,514,514,961,270,41,879,632,106,335,686,570,963,683,935,382,863,31,339,440,339,438,103,972,654,871,415,16,189,161,547,5,625,288,370,430,910,57,164,813,476,929,795,657,109,359,570,562,91,888,321,44,887,36,86,384,415,576,660,14,32,702,332,535,501,0,706,432,563,906,977,161,183,264,250,15,582,91,451,221,108,179,463,501,18,227,47,364,658,220,843,954,658,614,276,87,306,614,857,70,960,353,491,763,49,254,667,777,279,644,243,517,437,794,837,363,894,595,314,26,775,633,830,154,593,406,62,617,405,40,192,756,902,563,965,126,211,535,197,901,542,557,580,402,938,248,230,545,119,230,35,542,527,989,910,444,431,635,663,760,859,870,979,887,412,742,342,514,366,969,822,117,557,453,360,818,811,548,532,222,698,438,617,183,4,876,956,347,917,795,831,720,399,794,789,182,117,86,719,583,767,870,545,441,81,882,551,461,107,983,570,526,872,360,101,592,786,882,411,144,367,380,724,530,555,453,41,49,688,195,834,657,230,889,908,719,414,489,670,112,190,629,924,370,370,614,297,238,463,412,164,864,59,808,456,482,504,809,978,414,152,769,189,286,1000,404,361,658,684,294,427,136,296,651,27,896,963,846,444,85,582,563,492,196,387,619,94,216,637,394,666,811,22,24,493,939,562,262,784,484,1,441,550,517,591,995,332,482,73,240,229,410,288,203,223,991,816,164,209,998,488,736,698,852,602,635,303,266,857,172,661,948,824,400,114,502,177,768,995,753,445,692,987,746,7,508,428,377,747,870,260,110,565,46,732,298,92,255,972,4,732,14,442,643,643,511,538,927,699,843,627,269,544,859,124,846,775,656,88,117,53,466,720,563,615,921,426,512,171,622,902,84,926,311,818,645,407,603,139,403,844,920,519,989,189,126,390,300,619,983,962,849,707,686,824,662,836,343,562,610,45,215,738,749,400,781,724,139,366,183,564,355,998,916,365,736,224,328,285,396,898,597,221,396,392,939,148,13,717,268,724,478,374,187,284,739,364,662,793,476,73,262,465,672,187,20,504,405,933,976,774,301,895,439,612,40,879,510,475,878,786,151,533,547,856,436,701,190,697,361,166,969,693,555,872,811,729,360,827,149,679,10,477,825,198,592,679,277,397,314,738,726,596,710,630,333,247,548,26,658,759,235,894,677,311,665,938", + "35,197,98,720,70,858,818,611,935,641,695,896,894,408,315,207,503,985,884,694,274,385,437,835,578,178,101,88,932,351,191,931,756,398,471,836,346,81,334,764,467,908,21,313,383,168,829,545,185,646,652,331,529,164,160,593,479,987,94,409,65,118,781,137,327,321,847,69,149,54,404,451,140,960,691,954,881,305,851,29,144,24,201,679,77,985,883,676,388,320,568,191,515,706,186,722,916,752,453,420,449,568,744,885,550,821,882,135,340,582,234,870,242,276,939,176,136,841,931,165,696,984,429,443,107,99,45,463,310,134,116,294,815,99,674,409,741,922,85,686,652,439,462,359,650,959,215,736,833,992,619,585,883,94,103,618,515,438,736,70,468,298,519,369,446,567,874,368,875,710,962,925,467,998,721,588,67,406,367,449,378,40,168,214,902,473,155,255,390,589,205,183,149,62,472,393,118,546,931,897,178,820,581,887,253,184,910,487,978,989,428,650,882,812,430,384,50,721,555,273,457,926,877,694,359,42,162,798,964,513,857,465,426,972,597,987,55,269,522,313,89,41,921,902,902,433,131,192,661,376,365,224,838,712,520,920,30,100,178,885,69,715,939,528,672,307,102,628,280,942,799,962,747,672,312,821,748,553,810,110,684,870,952,390,334,273,449,214,998,75,707,452,111,123,280,724,757,651,31,831,196,438,735,390,373,993,778,575,329,897,665,299,437,372,160,312,883,715,987,210,387,17,494,71,881,839,129,518,601,70,129,679,449,56,702,58,31,902,785,965,709,500,304,997,444,965,31,505,556,534,721,739,801,767,102,344,386,840,98,901,158,453,118,995,170,917,932,815,876,172,846,202,60,816,935,761,876,626,446,353,787,658,418,824,444,733,333,495,397,896,261,991,759,387,738,948,917,732,757,646,854,973,906,220,594,297,756,815,265,181,786,444,641,698,979,53,36,734,587,478,58,208,129,310,937,904,56,530,188,752,627,421,806,367,440,648,622,298,8,208,710,873,308,13,624,352,357,830,124,464,231,18,675,458,61,835,419,913,191,462,498,941,563,178,277,953,398,376,667,657,620,291,40,231,340,862,966,529,195,584,908,920,129,582,274,62,860,994,180,273,424,754,185,927,602,395,352,884,560,579,863,748,279,176,249,784,634,340,834,532,367,898,539,153,650,305,792,47,99,935,956,854,957,268,965,272,625,14,448,861,18,346,553,225,29,592,19,570,706,0,250,244,479,991,860,492,526,435,590,619,447,912,389,278,190,456,914,137,99,322,267,928,43,464,682,705,95,437,163,681,451,626,914,738,378,497,499,311,422,40,829,510,168,466,302,766,573,945,596,548,23,361,212,325,15,62,34,229,200,875,779,978,579,325,764,312,15,383,49,67,375,94,212,45,98,84,193,449,441,493,432,678,801,205,875,809,80,111,862,99,663,256,160,155,18,974,179,927,796,550,147,246,96,628,396,74,708,230,948,963,846,254,501,258,441,427,857,372,465,349,678,97,629,153,497,747,746,434,53,160,756,229,215,943,581,625,983,687,155,958,132,345,63,394,427,221,916,256,742,979,387,542,483,341,129,745,128,915,188,222,375,469,110,51,140,525,667,405,569,889,622,896,844,255,344,422,306,382,808,859,884,152,59,557,816,762,75,901,889,419,456,769,372,922,210,183,225,391,187,675,214,876,408,795,223,219,959,882,990,992,984,6,345,192,717,62,951,158,363,463,516,385,106,613,792,762,703,227,575,507,858,690,392,411,383,222,227,172,915,714,314,694,419,834,682,19,89,815,947,416,183,534,445,428,456,248,483,567,240,525,131,224,190,123,616,139,965,647,419,30,229,809,264,281,255,466,305,220,926,693,920,948,200,954,261,776,114,779,432,926,661,783,626,172,257,796,922,963,885,57,63,44,877,174,453,167,169,568,284,710,8,3,719,413,400,738,587,860,818,905,194,275,476,266,70,829,777,409,109,971,443,862,189,143,456,883,666,548,805,675,809,985,920,332,155,294,823,818,677,466,465,625,442,126,567,582,14,913,515,579,384,311,278,222,908,471,630,695,299,85,302,36,657,372,281,864,29,56,922,491,301,137,800,899,719,451,89,240,164,773,710,143,82,634,659,540,744,311,203,683,768,186,682,72,914,251,132,115,906,881,616,695,139,197,394,7,822,521,723,242,180,44,224,288,34,232,638,433,180,267,677,507,969,871,872,235,204,423,497,691,633,736,475,895,115,542,859,562,18,726,669,838,365,447,647,600,571,560,499,200", + "456,991,165,820,57,767,917,932,674,497,390,213,930,776,434,402,207,68,830,199,147,734,679,303,768,634,848,588,644,493,526,614,749,218,654,830,128,226,545,254,708,530,120,819,172,80,752,790,508,27,744,820,227,351,523,92,549,27,336,626,327,903,202,100,971,752,606,296,550,152,598,325,87,932,281,163,443,175,51,305,672,633,897,732,610,326,56,211,337,147,53,426,946,147,840,620,454,900,790,673,443,785,693,64,629,94,556,577,822,21,408,803,727,439,783,182,825,182,299,668,584,737,899,53,356,664,360,700,686,410,864,418,573,548,408,437,200,504,332,766,518,713,958,43,393,386,749,742,517,645,764,394,927,848,326,391,104,746,934,148,132,714,715,823,979,66,879,192,720,547,658,579,88,578,960,196,47,150,488,469,909,542,552,704,406,411,133,115,407,636,168,121,637,402,740,932,220,718,724,997,127,146,637,460,830,979,511,95,156,832,312,757,624,730,435,919,529,120,58,487,273,673,81,366,361,186,744,421,740,538,510,990,192,645,873,612,204,368,346,361,950,352,742,589,662,334,977,636,825,204,14,812,579,319,285,964,491,466,298,69,579,851,333,240,109,99,572,158,453,566,785,404,984,918,663,816,588,329,756,266,788,743,275,73,347,994,867,488,565,337,613,796,57,386,973,688,316,52,220,896,725,16,797,633,70,486,141,586,844,938,82,497,445,603,438,930,392,281,953,127,206,937,103,401,824,497,272,783,611,279,286,285,922,600,669,883,208,987,994,967,222,533,904,127,528,978,957,992,743,363,882,141,696,406,324,217,157,19,600,399,700,835,95,154,807,571,997,361,948,273,76,26,47,357,364,224,31,594,268,660,634,487,142,793,484,256,67,289,760,749,995,721,69,920,945,523,40,501,874,649,860,673,670,663,79,486,729,740,589,124,143,73,612,681,394,223,953,458,811,80,456,355,529,33,407,802,819,813,76,224,94,246,318,55,351,604,60,847,863,162,488,655,734,814,160,467,860,340,396,675,527,811,363,542,272,466,904,323,156,22,309,411,766,17,571,10,232,366,629,232,919,495,162,308,85,884,500,250,111,808,549,380,972,699,108,855,547,538,867,773,644,242,631,976,984,166,284,17,398,567,141,276,760,246,732,724,950,946,41,178,239,938,595,24,237,107,595,787,6,949,864,984,696,920,834,521,350,696,839,827,965,897,744,383,931,894,672,791,432,250,0,488,335,158,712,37,781,197,895,433,809,612,499,902,841,186,224,489,172,468,143,63,973,772,611,743,49,337,491,111,820,828,781,989,350,77,96,579,422,590,327,81,740,943,530,931,514,473,796,248,54,685,451,459,471,699,658,556,710,74,810,829,904,376,831,716,639,512,76,987,501,461,927,301,76,944,112,30,435,955,430,838,663,86,469,292,164,431,433,917,420,443,251,587,495,651,730,914,925,225,983,414,210,168,796,146,349,358,653,67,642,515,351,936,807,504,25,291,455,11,616,736,119,109,18,593,924,184,828,268,54,495,511,28,143,803,202,530,220,301,701,343,728,452,732,423,948,118,648,672,944,693,819,909,147,992,353,253,751,400,389,682,751,611,96,730,137,744,203,307,649,513,649,197,226,376,569,219,827,796,77,963,904,140,685,819,159,226,755,212,298,763,182,655,548,162,64,518,444,592,986,636,642,181,512,948,959,491,510,693,815,312,943,777,509,807,424,65,276,833,792,897,818,441,946,547,611,775,708,419,144,508,92,611,642,31,105,510,489,126,512,953,100,706,854,213,327,950,602,815,260,720,81,362,761,395,107,274,508,371,791,761,687,376,459,441,351,586,828,992,736,432,282,965,120,171,114,347,994,602,569,553,408,84,741,266,878,610,764,823,905,497,857,287,932,189,580,292,600,436,685,827,128,259,891,511,636,420,712,629,662,978,516,575,842,669,677,429,490,779,430,686,6,50,426,694,373,518,207,497,784,437,265,53,526,119,976,516,517,374,114,758,60,418,602,391,199,987,627,643,217,108,519,684,24,539,916,275,727,921,835,579,38,577,945,420,439,475,790,758,92,383,323,16,740,736,454,142,33,812,378,881,32,713,73,125,317,344,26,192,743,227,648,831,919,456,990,417,831,7,498,287,409,491,769,20,17,853,679,690,877,80,630,231,838,768,946,63,463,457,808,200,852,272,350,536,257,270,136,746,648,534,585,657,186,257,529,207,699,852,170,113,830,407,670,398,526,293,364,381,546,71,983,594,788,906,888,26,106,259", + "795,995,409,766,62,632,306,505,536,654,385,558,890,625,966,862,705,42,556,604,656,306,185,288,436,12,978,720,726,762,215,884,38,323,658,479,234,19,982,918,947,438,148,231,171,848,235,138,193,691,343,114,773,855,246,327,809,40,331,789,704,358,818,429,498,452,201,494,955,940,967,27,764,627,859,51,199,618,856,51,931,153,209,989,976,2,31,410,701,372,787,127,290,932,864,940,961,881,63,864,718,803,606,501,587,823,264,819,544,749,753,273,46,639,797,316,354,675,127,973,56,776,394,115,833,487,742,945,746,690,138,417,799,49,843,762,884,941,335,173,39,404,118,781,237,380,5,40,176,425,862,535,532,506,644,742,573,733,766,229,43,237,428,815,987,439,487,615,960,704,332,949,324,965,551,388,125,737,222,374,952,448,474,377,553,294,164,492,851,165,473,756,561,730,130,386,577,168,200,531,356,263,73,884,311,548,578,872,963,143,196,205,190,341,634,508,744,795,569,748,127,720,592,103,976,907,946,984,496,445,109,867,638,73,392,989,573,326,256,797,466,176,148,619,840,956,90,280,515,173,828,955,896,950,385,972,632,129,217,613,566,911,830,905,100,314,841,304,678,340,231,762,452,347,706,84,403,320,54,781,302,61,325,476,748,554,107,123,49,67,426,729,636,954,158,410,279,712,933,97,962,859,981,889,181,796,937,426,706,355,506,497,635,218,585,237,540,174,743,464,879,220,13,18,393,889,257,188,637,880,600,766,713,216,158,296,730,433,938,470,199,678,305,811,449,935,960,405,428,730,718,292,266,862,646,581,619,658,678,133,360,389,159,602,907,618,904,59,150,457,746,42,204,935,226,933,911,281,85,100,223,896,800,685,947,158,656,285,943,16,517,348,415,480,642,27,68,706,553,102,512,383,442,629,429,961,302,248,399,85,634,717,107,99,707,833,152,864,623,173,759,347,494,733,547,310,283,929,6,294,313,186,506,903,691,342,403,703,350,84,166,287,707,252,836,907,704,250,260,955,246,905,551,68,763,987,862,987,510,117,991,671,816,957,648,674,274,965,26,57,873,442,826,737,652,136,19,550,856,244,949,73,509,194,587,397,455,829,191,525,825,459,862,76,923,978,599,112,557,635,108,61,134,172,205,989,497,363,495,678,963,853,709,892,999,828,972,787,609,209,270,291,644,691,126,540,10,363,335,667,900,764,586,157,78,705,827,120,563,244,488,0,208,312,161,360,128,782,129,806,777,423,819,445,123,954,881,627,419,771,941,913,177,215,177,690,484,651,563,451,824,580,664,381,534,774,979,974,54,215,774,824,477,258,73,123,93,447,998,492,794,196,206,139,693,69,720,83,49,246,147,145,118,369,818,755,333,247,773,769,144,539,104,283,654,655,787,707,285,655,685,335,237,534,172,878,565,322,988,434,852,577,463,306,32,25,616,251,479,394,322,595,723,160,55,133,302,416,165,975,806,530,270,49,374,459,958,747,520,854,720,529,716,378,909,884,500,778,262,250,653,601,562,375,345,935,985,337,212,366,597,475,847,673,757,878,293,262,635,449,653,644,144,394,316,211,622,909,212,178,18,98,6,826,444,332,306,786,686,960,440,89,410,15,576,389,349,307,930,316,848,290,778,219,7,512,490,197,561,417,572,32,484,933,151,945,979,22,153,318,306,100,857,793,52,682,917,264,276,19,493,999,482,685,464,88,654,127,737,977,664,374,145,131,522,2,587,96,418,298,127,766,120,26,189,111,556,672,307,384,723,5,235,942,614,718,425,187,721,339,58,588,927,103,584,654,731,146,574,567,277,736,606,884,984,243,546,364,681,976,543,795,98,366,507,773,997,425,77,542,42,117,541,47,735,602,744,629,652,882,461,511,844,724,212,941,830,565,386,826,848,727,588,707,267,682,354,634,970,116,191,494,83,743,396,955,746,904,566,411,615,352,624,618,710,616,729,559,589,904,753,917,902,61,359,656,15,395,531,90,629,571,523,493,267,942,624,182,328,701,560,317,678,940,265,37,258,698,431,79,424,377,959,90,469,620,774,628,634,611,778,887,644,826,334,319,513,597,604,150,568,786,96,46,453,184,813,494,582,140,754,417,521,394,19,221,454,725,395,341,57,157,633,830,392,952,299,273,29,638,823,222,338,80,821,857,614,797,299,861,387,338,277,84,890,284,218,756,940,414,592,93,562,537,977,893,581,849,629,225,245,816,865,150,742,29,419,147,139,264,679,79,833,500,986,705,512,458,524,282", + "615,876,238,328,893,994,400,746,660,658,848,157,128,24,203,935,568,497,257,829,891,312,900,782,444,466,263,310,97,841,769,774,900,826,559,769,357,564,416,709,874,27,273,293,818,211,428,374,659,165,334,827,151,209,267,410,928,875,376,174,126,377,216,480,494,103,957,884,653,960,508,492,747,902,240,789,532,251,749,783,687,112,390,99,65,150,742,481,864,629,648,159,540,775,192,422,449,265,556,308,312,6,226,937,516,986,725,86,225,344,386,856,124,872,673,747,549,227,605,987,220,567,700,411,211,88,32,987,361,104,275,280,302,265,576,124,788,902,180,961,633,532,338,25,935,401,99,225,974,852,339,410,506,283,216,174,844,527,58,344,399,993,177,3,135,57,525,299,156,25,723,816,268,875,792,461,127,593,240,618,700,114,190,553,644,4,539,434,205,568,43,832,778,402,857,767,908,925,950,537,580,634,73,606,132,890,791,740,305,940,639,866,885,958,657,264,678,639,968,187,582,551,622,850,255,139,220,65,766,322,937,498,762,335,579,274,220,133,668,236,578,347,662,755,820,311,150,549,43,894,855,675,662,40,420,313,348,497,982,365,611,217,795,53,7,955,30,158,258,822,598,122,712,302,674,271,18,403,570,847,150,232,411,911,942,378,308,599,74,495,117,486,614,489,703,377,382,146,475,279,41,496,630,555,143,411,372,762,263,19,768,666,66,888,716,715,840,854,565,56,184,259,626,270,334,104,829,235,938,32,351,234,985,169,397,489,781,4,465,739,318,361,16,331,927,618,301,546,626,574,176,313,688,980,82,679,348,592,66,88,362,622,5,732,439,170,642,334,32,141,258,554,875,763,780,618,988,19,869,226,216,685,469,578,59,19,38,692,8,237,691,63,616,607,285,526,986,534,216,819,547,872,793,595,861,65,122,778,199,194,460,740,855,39,440,926,522,123,85,944,743,941,790,4,266,341,697,24,534,251,489,417,995,810,340,870,659,97,529,745,407,357,954,695,500,520,134,373,163,30,162,702,969,487,769,411,911,320,84,216,871,727,493,914,622,63,819,241,921,175,544,948,898,392,21,654,19,562,435,334,612,646,298,183,492,569,282,512,217,862,565,339,413,466,950,108,416,236,688,413,918,565,360,121,811,974,25,19,865,626,49,284,524,546,559,409,23,316,403,167,747,580,947,595,117,205,433,803,867,753,104,885,465,725,991,252,664,644,906,479,335,208,0,867,755,227,498,218,81,79,986,338,911,824,477,690,772,862,304,48,641,789,691,565,455,209,816,882,746,613,656,628,275,893,151,513,167,753,298,551,705,477,133,429,20,564,320,180,870,10,742,441,577,256,186,607,193,138,719,992,779,980,332,218,783,681,647,352,981,341,463,136,183,509,104,652,459,461,555,965,172,702,932,247,205,468,713,684,946,253,454,445,163,391,528,272,788,1000,655,288,119,389,462,889,561,924,933,217,402,529,793,155,582,9,603,190,928,797,614,381,323,695,150,296,250,712,468,233,35,557,899,602,485,36,346,546,627,528,259,525,567,75,129,720,843,755,486,850,389,797,126,214,712,56,711,674,946,914,479,161,534,970,910,598,582,128,727,914,705,678,976,618,65,619,694,523,529,708,994,646,171,686,77,657,836,870,19,504,358,832,465,664,99,998,850,936,905,389,35,637,327,113,883,684,764,490,454,47,662,607,598,819,394,500,34,875,985,92,962,197,592,932,9,95,417,85,907,187,739,298,907,273,817,485,577,604,866,564,590,645,42,931,395,444,306,67,287,40,652,731,325,304,861,631,595,572,511,345,864,120,104,753,450,904,448,524,426,309,297,231,188,18,898,979,654,954,893,85,893,917,88,356,517,78,934,632,966,186,34,708,122,129,662,751,100,909,435,625,696,29,278,257,651,445,913,30,648,965,695,538,133,272,89,790,184,259,627,82,548,463,403,526,862,682,808,619,675,515,585,346,134,674,726,548,872,692,420,224,111,585,275,770,841,540,186,388,136,196,590,846,718,876,633,282,431,942,848,801,258,157,395,633,314,874,803,611,82,384,553,351,259,104,606,984,161,425,573,343,942,120,263,84,840,337,985,591,20,519,727,695,461,749,124,594,691,110,94,476,257,500,221,355,973,446,836,178,790,542,731,824,314,209,228,758,957,872,722,250,873,965,437,320,885,614,321,309,101,750,119,500,745,266,898,170,886,218,83,878,450,884,70,608,259,84,924,282,398,221,414,267,427,684,26,675,277,460,558,626,70,839", + "349,5,94,198,315,759,694,334,640,987,126,171,196,845,313,250,307,97,302,468,616,7,751,750,457,918,157,242,671,306,255,195,163,295,393,557,355,38,71,190,932,120,316,710,676,782,331,162,245,950,439,150,2,646,265,1000,537,177,517,124,552,44,148,928,948,269,502,983,812,683,43,996,522,126,395,726,903,645,822,523,106,861,483,10,88,712,999,850,868,639,427,205,919,34,29,69,960,782,667,366,948,307,694,89,963,519,407,158,908,94,870,349,767,5,702,765,624,375,748,796,568,22,677,771,956,273,500,628,98,641,159,779,323,221,363,432,541,331,372,437,946,945,156,646,530,884,881,80,97,640,757,377,797,380,663,307,638,790,596,782,987,906,719,748,240,470,67,127,820,327,631,882,79,831,253,690,748,372,388,554,90,565,646,53,400,611,522,96,186,121,267,529,153,313,213,227,905,71,588,529,547,794,646,80,446,389,274,523,724,117,443,152,559,936,629,799,808,674,843,425,51,128,405,315,715,640,772,339,931,897,241,109,21,528,857,965,223,971,790,677,249,232,718,1,779,674,566,638,705,20,254,823,221,312,355,313,845,185,438,137,67,395,919,326,917,718,458,903,610,166,415,855,376,881,493,590,260,956,127,786,859,81,672,912,231,143,990,26,29,313,787,55,618,652,127,714,96,369,239,651,95,98,85,801,3,336,53,79,53,342,119,938,764,750,376,815,43,971,463,846,714,549,993,713,957,162,760,159,391,868,359,232,319,759,542,408,730,534,927,30,492,687,405,996,844,904,809,702,773,251,889,380,29,120,448,633,258,836,378,340,161,50,809,10,574,212,923,285,699,204,493,767,866,830,925,522,108,367,405,87,892,970,42,772,455,244,161,792,110,305,1000,796,57,559,574,661,119,433,517,246,47,115,145,608,810,276,593,454,243,472,900,704,749,884,755,419,45,248,749,35,351,817,714,383,223,406,121,216,349,678,161,589,912,755,950,518,300,315,545,804,212,556,292,9,890,636,11,993,34,764,874,173,517,182,87,298,196,485,10,669,485,47,856,597,542,248,633,495,413,625,402,284,333,493,598,206,767,246,85,269,858,121,831,435,165,209,944,18,839,591,597,443,159,672,618,241,371,494,821,658,447,467,889,659,767,573,677,740,468,506,971,694,78,173,529,229,779,373,962,277,315,561,254,89,345,496,855,650,646,158,723,664,383,882,190,715,783,646,977,991,158,312,867,0,496,407,696,884,338,487,451,842,636,182,233,855,283,556,571,729,523,814,851,448,469,868,609,973,465,692,726,220,678,20,618,195,941,58,897,256,773,788,117,751,695,457,751,258,712,542,253,138,966,771,308,227,47,398,210,531,95,852,560,94,918,202,835,519,988,839,316,506,461,736,772,720,124,572,634,396,465,886,38,218,594,449,190,985,970,43,300,240,890,546,807,419,384,855,572,997,643,938,989,449,25,217,230,168,930,254,984,999,102,621,143,643,704,62,41,919,916,891,736,408,471,670,274,177,295,742,15,96,246,643,191,304,595,397,106,26,770,965,738,494,719,245,992,709,798,678,275,140,731,762,183,893,860,815,699,757,808,894,883,72,430,415,86,769,878,379,423,376,258,224,30,370,826,905,548,693,614,194,790,112,571,839,945,310,897,760,736,341,294,760,607,375,707,457,617,486,930,515,971,77,397,561,263,179,692,172,3,967,221,247,993,205,830,885,975,921,496,341,202,578,519,730,939,836,48,273,375,453,288,906,918,415,66,607,105,52,737,294,974,321,951,915,168,101,214,978,835,545,845,619,418,255,223,417,825,757,355,526,622,228,987,773,128,953,493,462,6,602,290,873,483,435,727,104,168,615,434,876,229,243,702,530,628,393,89,595,804,2,924,841,627,284,473,839,233,979,837,130,709,474,832,527,52,50,496,661,928,313,900,581,420,498,196,836,9,559,308,991,341,225,861,213,432,285,459,86,437,165,55,522,142,149,707,812,886,980,201,206,188,936,361,657,444,796,534,45,629,808,786,318,336,113,613,828,909,377,13,840,797,371,715,40,73,809,886,742,496,441,772,8,327,363,104,530,69,444,313,855,359,792,922,949,381,822,651,596,441,640,356,672,631,771,854,948,397,377,213,976,688,847,621,691,39,764,95,369,455,57,928,21,395,378,205,383,697,960,31,689,467,538,809,786,765,393,470,327,699,558,298,919,147,275,416,307,569,704,703,627,249,694,769,32,259,294,523,78,468,947,587,705,651,791,186,957,827,349", + "597,342,442,794,76,462,43,864,843,812,265,583,55,930,835,621,922,430,546,174,664,966,96,964,592,606,693,896,381,925,421,94,268,341,600,331,24,9,822,241,630,603,427,47,578,282,660,47,212,802,649,832,352,480,345,112,672,717,46,390,470,105,421,545,320,836,976,45,394,603,680,494,395,551,28,894,514,753,525,705,700,702,606,738,287,822,600,538,544,607,897,329,195,418,45,47,88,431,414,389,377,248,60,553,113,694,725,329,745,325,222,528,481,264,342,639,966,266,638,500,868,525,982,996,472,241,474,324,139,533,325,336,528,557,967,781,204,361,801,418,113,754,217,61,801,814,771,807,491,525,127,562,2,542,722,215,379,134,376,333,360,328,123,466,58,949,474,115,980,537,605,42,278,871,397,678,800,894,438,561,889,846,270,159,842,718,827,583,988,526,403,85,372,288,595,378,105,208,436,699,855,418,106,488,524,734,568,402,807,583,283,592,57,158,511,999,560,676,868,242,113,399,265,110,229,374,367,620,332,791,297,990,446,834,439,833,595,835,120,904,876,942,880,331,506,726,165,69,592,133,335,511,211,486,111,474,540,629,971,547,262,925,468,981,183,149,935,334,354,7,296,297,51,466,582,984,937,94,701,370,256,241,571,72,764,881,392,409,621,983,11,359,261,606,905,309,419,58,362,300,262,469,147,673,439,610,106,120,494,500,668,168,400,534,77,725,884,150,348,211,49,196,626,160,873,942,349,128,660,330,628,377,191,147,792,925,996,407,886,847,20,624,289,977,946,231,256,732,885,490,398,58,734,59,64,950,386,45,817,459,513,233,26,949,54,525,253,170,473,83,134,315,145,964,388,382,942,729,308,407,47,1000,945,647,405,193,924,190,575,808,684,424,614,656,730,510,905,387,302,279,369,916,170,223,44,662,562,949,950,318,97,992,941,813,496,284,876,997,88,196,586,481,807,862,111,485,605,287,849,251,630,657,233,654,858,894,669,404,222,862,82,550,420,791,2,494,354,984,142,405,292,890,602,247,662,86,832,424,110,709,477,647,986,407,533,487,617,891,825,266,747,409,294,355,113,252,599,589,998,405,197,554,805,682,351,556,988,489,615,894,485,812,985,420,178,13,235,956,470,192,830,857,996,737,788,99,533,850,323,99,97,566,895,823,539,155,729,232,561,150,505,323,193,710,241,872,121,989,231,333,394,947,522,707,832,406,158,281,161,860,712,161,755,496,0,975,514,598,748,696,24,902,914,850,276,530,712,801,13,12,723,359,617,817,746,816,210,3,800,446,965,64,553,621,316,235,220,104,505,486,461,941,709,584,216,290,278,652,806,456,684,876,606,839,347,778,568,949,674,45,634,660,618,295,108,660,612,381,252,335,171,622,311,809,664,740,710,467,952,745,34,421,992,197,767,69,621,851,428,288,21,175,978,152,944,470,791,738,257,450,123,87,471,934,136,655,503,657,183,430,440,60,371,16,706,159,672,127,257,474,223,129,981,148,32,975,511,344,492,799,920,150,685,663,972,857,286,595,705,66,954,68,822,224,229,225,659,833,801,400,193,958,140,610,933,707,385,43,179,22,734,496,523,73,524,694,108,858,818,820,81,804,71,776,589,475,536,813,97,37,402,838,240,462,14,485,124,878,633,325,23,101,174,970,775,408,541,686,772,563,884,114,98,485,881,942,945,851,491,614,135,674,795,523,358,807,616,397,677,267,65,249,716,700,119,502,529,518,592,678,898,307,568,467,619,222,960,326,457,807,546,36,962,415,72,491,703,728,304,843,617,177,239,457,526,516,236,697,546,404,684,257,37,788,486,550,968,232,715,65,51,96,371,335,452,508,267,923,476,620,840,661,477,452,919,707,109,259,679,722,598,876,921,89,941,895,794,987,115,717,508,755,459,514,61,958,423,641,83,443,943,175,16,121,477,573,496,491,96,737,18,740,342,229,652,825,934,691,487,147,936,604,381,878,414,191,815,479,79,188,149,504,616,230,907,818,979,980,664,93,892,937,687,79,755,892,387,541,268,179,278,984,583,249,558,704,989,888,804,140,615,793,887,303,474,839,746,478,439,632,693,218,34,655,535,826,835,792,570,919,109,861,304,90,859,969,708,801,82,953,568,178,28,316,603,140,373,43,129,394,376,387,545,523,84,218,56,83,131,456,748,816,889,891,110,246,682,905,317,682,984,513,190,626,870,461,713,81,846,306,411,884,483,426,236,503,876,57,958,895,517,352,60,571,307,474,972,948,254,225", + "198,379,877,41,635,559,679,711,880,875,341,437,870,893,948,260,537,780,736,289,267,73,460,881,427,280,829,607,431,16,337,854,741,980,558,832,451,726,673,827,81,397,725,311,207,716,512,23,723,675,950,559,801,256,674,417,795,99,983,808,887,165,229,858,239,1000,128,422,961,947,282,410,907,410,346,291,652,858,964,210,254,354,66,285,359,697,243,242,886,15,319,481,929,12,168,258,700,463,193,171,172,474,699,591,900,919,314,691,80,813,494,81,972,17,415,689,901,947,165,731,283,237,840,340,635,692,932,7,85,354,705,330,985,199,392,738,706,800,921,58,416,112,676,899,755,513,322,922,956,112,836,13,758,752,11,770,338,583,749,300,171,308,657,474,945,525,340,931,80,653,10,831,764,139,911,994,476,689,978,907,943,997,990,573,19,791,380,399,8,67,265,781,511,597,91,634,193,8,465,948,593,345,925,178,952,279,661,745,595,151,446,570,901,307,313,430,426,319,330,277,766,867,682,770,529,475,44,597,858,335,551,736,785,620,577,507,677,693,976,519,189,587,311,223,119,630,584,724,335,789,752,69,718,740,12,568,697,996,32,685,889,933,795,423,818,195,182,800,224,128,388,813,740,924,295,283,35,298,623,829,944,791,284,65,312,237,554,162,859,994,988,567,991,664,769,483,898,981,498,871,725,658,928,48,683,946,533,724,425,824,242,364,647,740,280,688,820,385,676,615,295,449,685,668,453,197,190,160,427,33,357,671,396,159,293,388,438,100,515,492,269,741,611,441,573,514,543,820,560,646,781,123,586,549,279,657,303,889,499,417,160,253,398,317,94,452,482,819,400,234,967,223,532,350,996,6,494,364,547,863,166,163,197,953,309,812,407,900,752,691,439,182,182,545,352,227,262,489,15,205,381,73,127,725,591,520,894,647,990,664,606,616,518,680,777,338,967,899,373,86,385,732,238,279,210,987,241,254,495,474,702,215,792,359,442,956,813,904,933,717,294,765,792,946,323,385,714,959,855,278,507,319,959,940,510,776,249,875,781,376,820,599,225,176,950,269,423,675,512,235,655,477,432,846,427,632,686,991,761,835,17,594,550,950,35,778,426,258,856,12,147,446,348,693,948,724,281,968,617,50,922,893,449,548,313,487,465,645,200,751,749,460,879,371,660,232,539,323,303,856,75,680,300,377,954,596,685,298,139,263,660,774,582,633,402,936,89,842,183,492,37,360,227,407,975,0,695,382,813,605,692,431,424,760,13,754,906,806,272,929,184,32,76,819,737,4,442,292,14,641,298,599,130,250,171,750,577,645,812,422,866,549,300,401,407,413,770,234,822,647,884,735,171,35,329,832,405,64,130,989,880,984,622,137,182,916,759,200,153,800,762,516,181,729,58,246,611,868,176,297,415,5,142,226,940,273,593,111,747,290,880,889,354,471,618,429,422,22,837,592,765,282,549,858,839,308,730,495,414,751,345,678,633,524,925,297,600,553,154,931,237,192,966,208,765,517,402,569,999,246,737,646,689,610,588,243,15,819,442,209,565,721,748,126,874,122,24,855,495,235,829,917,848,700,396,509,639,798,740,750,212,546,811,364,164,825,509,1000,696,36,889,167,318,113,824,676,245,659,942,966,530,869,651,867,227,115,763,392,468,675,971,408,810,438,419,715,974,698,485,427,340,106,40,645,973,168,69,964,433,27,720,538,443,18,35,21,641,567,218,454,749,79,204,586,109,317,377,975,371,899,49,728,896,565,457,599,537,190,562,882,973,792,168,64,407,977,706,933,979,289,323,859,698,706,485,780,5,400,870,761,470,570,955,728,400,561,656,189,289,614,223,416,207,899,591,724,636,438,836,883,496,808,912,753,239,403,31,431,744,810,650,265,740,462,358,911,843,162,396,372,430,146,788,37,856,26,708,509,879,768,548,252,426,896,28,778,162,606,343,440,242,530,969,77,495,611,826,530,461,384,420,221,525,708,91,298,221,564,514,480,586,5,252,988,147,929,98,259,189,95,769,84,863,285,830,468,837,354,347,72,448,124,321,975,106,145,135,578,739,898,952,68,430,442,681,192,436,239,735,360,458,36,675,900,888,497,802,70,81,934,920,180,892,272,790,199,523,295,437,137,429,24,586,951,418,724,807,981,713,861,240,268,977,229,763,343,601,903,257,399,682,633,390,35,426,744,321,428,441,536,394,151,222,117,38,84,375,606,526,507,275,326,295,592,905,587,985,473,686,54,882,361,221,645,14,372,644,594,159,397", + "643,132,445,970,477,678,826,840,180,528,492,629,167,992,182,655,349,207,619,854,653,245,185,654,446,887,505,367,354,753,521,607,795,541,466,256,908,881,450,818,126,528,830,453,447,656,841,787,397,390,920,149,676,55,584,816,265,541,699,373,304,24,29,369,745,644,463,586,523,1,521,425,783,260,556,89,287,933,854,81,603,183,445,91,53,968,888,407,272,75,506,181,966,963,383,400,992,661,533,200,155,272,117,87,73,776,850,451,739,689,308,48,545,984,257,412,253,261,124,485,739,102,156,423,132,798,354,202,527,46,594,567,453,105,750,274,988,132,774,726,775,279,948,259,141,318,4,38,9,35,546,212,786,510,307,700,558,387,83,500,753,502,512,422,575,768,954,733,244,635,896,720,295,352,67,753,65,735,877,530,617,329,883,945,274,668,43,814,576,640,779,882,338,254,786,555,678,284,545,601,837,603,926,662,330,115,572,388,359,220,678,611,758,19,880,134,439,816,162,27,723,227,366,782,961,639,253,695,151,568,866,607,568,439,885,244,576,243,716,828,396,120,700,908,484,275,196,890,519,704,535,621,730,18,770,630,209,321,271,725,77,585,203,379,620,736,896,880,469,904,693,851,14,7,341,254,550,714,264,213,263,278,6,796,517,630,863,802,240,869,746,378,628,968,500,401,840,221,452,780,364,940,247,316,254,832,634,276,731,418,283,668,574,337,991,943,980,834,184,174,560,491,931,727,647,431,362,935,936,668,483,502,248,584,400,63,143,548,234,142,753,763,626,261,915,244,244,584,778,985,776,627,32,541,404,124,498,361,994,112,841,52,744,721,277,377,831,569,56,558,346,459,340,631,801,259,183,809,970,257,200,536,581,45,830,754,535,892,338,38,222,424,358,436,92,66,623,688,247,754,606,564,292,201,114,214,734,303,62,243,608,981,176,824,139,154,207,509,952,94,995,211,929,23,710,272,205,672,609,200,691,491,585,659,929,939,561,810,791,863,699,254,523,511,921,745,103,711,995,219,51,205,543,559,866,945,650,985,539,628,651,416,98,515,624,478,164,300,127,178,406,159,612,5,208,961,772,836,15,411,458,717,809,178,5,619,820,702,102,435,927,452,773,231,724,183,856,927,511,599,513,395,703,996,909,787,231,251,113,645,255,412,915,265,502,693,210,463,438,986,302,106,285,635,873,915,703,826,863,34,942,498,532,858,398,735,178,489,264,526,781,128,498,696,514,695,0,817,988,167,668,142,765,156,259,529,518,239,503,541,755,546,256,685,965,523,850,93,632,391,882,760,812,606,5,24,177,826,179,100,270,728,938,157,835,172,91,76,475,53,452,292,194,627,919,509,553,426,640,380,738,523,383,987,179,673,645,852,312,137,689,365,827,448,12,362,454,971,568,268,220,35,999,539,361,392,414,355,293,238,569,726,689,58,594,487,572,152,779,727,604,265,663,249,250,829,493,264,854,426,256,774,920,20,796,244,885,710,245,809,564,100,597,811,488,949,4,107,44,473,547,618,192,665,844,638,6,4,27,626,917,743,668,458,674,321,181,953,870,249,97,991,549,324,899,900,969,86,894,77,66,201,608,955,108,418,373,554,86,954,747,157,751,932,901,444,835,724,687,759,572,514,722,146,496,945,237,485,687,693,162,567,676,683,257,980,429,766,27,276,526,999,401,24,686,124,470,717,747,625,984,403,955,95,434,114,136,385,542,644,59,385,717,366,215,167,482,674,903,909,874,851,303,425,223,92,134,438,814,559,544,736,323,656,147,114,215,139,494,591,834,63,894,917,114,930,775,29,942,56,612,741,843,256,756,266,549,142,339,350,346,818,566,115,708,970,375,590,429,132,368,734,831,276,207,447,986,453,101,705,334,147,929,470,395,326,554,326,687,537,485,507,169,904,951,892,499,455,47,514,393,739,989,198,897,443,602,951,926,506,327,343,420,835,545,151,912,988,906,52,648,950,287,45,940,444,844,52,959,727,402,89,825,426,447,375,179,27,707,801,144,952,15,410,676,876,877,544,944,544,449,848,356,332,178,730,73,923,849,268,469,428,7,917,771,454,959,195,616,922,93,709,442,772,841,122,777,582,803,427,565,676,351,526,61,300,696,94,466,191,461,594,632,507,619,954,743,165,442,328,434,157,87,249,129,267,175,367,144,71,913,95,221,586,925,760,564,57,19,725,985,878,646,848,677,224,544,875,373,686,317,180,494,478,421,906,412,375,45,41,157,984,892,45,966,572,481,356,364,940", + "18,231,266,978,538,625,866,680,466,948,686,184,669,331,395,196,556,142,894,691,628,607,84,379,462,148,492,894,17,271,368,840,236,378,825,255,182,152,618,366,217,615,937,678,469,956,376,999,735,680,962,47,236,283,51,688,194,739,93,177,505,779,926,707,278,307,223,418,478,872,224,398,727,280,586,111,263,697,123,238,752,119,348,671,777,448,206,950,629,901,728,130,921,97,103,732,366,1,143,214,139,942,229,247,638,656,804,441,258,398,850,531,15,840,786,482,699,471,750,90,154,210,769,216,579,416,20,63,655,614,698,499,997,131,348,409,567,409,803,865,609,492,154,522,593,380,859,982,669,107,329,669,210,937,533,491,856,302,341,179,659,855,78,313,548,893,793,860,100,12,66,994,68,499,992,940,547,459,352,24,145,76,754,123,77,315,712,114,314,871,859,233,374,780,651,969,19,345,163,604,921,529,795,762,796,672,870,189,250,445,258,968,760,689,365,393,767,111,679,173,117,548,495,269,11,840,666,441,632,816,17,617,554,632,54,512,27,34,511,484,93,230,605,671,731,338,22,892,651,169,440,363,2,111,47,341,280,884,56,182,859,274,722,893,137,304,588,640,231,123,138,213,847,655,996,683,690,468,616,317,299,263,399,903,123,32,866,966,823,594,889,603,747,846,467,242,304,412,475,557,779,226,857,54,40,690,272,997,938,789,854,958,910,840,365,676,137,263,33,628,975,12,606,883,356,896,468,603,387,936,873,78,628,31,779,251,767,120,214,237,333,384,313,816,654,716,359,794,503,588,425,639,351,696,148,812,309,953,529,555,849,953,98,970,729,552,237,135,651,429,240,685,616,328,260,763,593,51,180,719,728,53,848,25,347,757,955,728,902,316,70,509,382,760,311,351,485,874,641,572,770,847,558,149,233,555,60,442,298,136,551,217,391,269,516,390,118,307,175,906,431,618,248,803,815,877,15,554,894,318,101,348,530,947,648,43,443,649,844,539,873,483,908,758,185,613,414,509,406,517,277,960,579,513,795,915,33,155,40,419,835,524,474,494,195,822,839,141,800,468,595,26,751,230,214,732,217,400,915,521,792,149,421,759,506,364,736,915,970,675,293,51,236,993,73,902,1,285,564,414,903,919,745,167,20,617,44,714,899,991,823,393,264,715,218,710,542,916,254,720,691,929,740,714,422,288,389,139,926,41,634,708,653,153,647,120,914,621,250,435,197,782,218,884,598,382,817,0,140,963,850,444,325,560,361,950,301,433,117,784,381,114,674,925,573,115,85,772,335,651,198,424,289,628,164,575,269,240,483,702,381,863,323,177,315,862,674,745,369,630,320,830,614,861,197,477,662,541,901,254,292,755,656,931,192,13,611,451,700,379,278,934,845,69,56,266,403,907,281,898,942,25,316,686,591,271,154,720,914,589,932,951,150,602,189,24,34,979,324,115,109,609,489,232,887,537,986,824,682,409,221,102,728,982,307,916,555,532,634,344,387,571,394,862,869,222,190,724,998,647,973,389,371,929,532,506,302,467,159,129,758,558,856,676,56,64,282,652,592,577,130,339,693,945,886,21,493,463,471,714,372,314,220,25,713,460,246,393,673,109,940,76,770,603,742,776,3,179,273,861,269,625,566,213,896,901,12,946,998,233,374,427,232,248,595,373,875,553,803,217,85,950,320,245,680,112,828,953,872,567,743,127,562,966,540,255,926,360,541,684,116,432,120,109,465,490,257,78,573,63,444,509,165,799,994,794,613,379,790,136,37,483,245,327,475,659,491,595,588,987,435,550,608,208,68,28,782,660,598,904,479,645,886,77,910,200,817,78,958,637,144,479,693,365,206,26,775,832,759,948,252,7,469,913,923,250,195,82,213,119,515,327,382,95,696,162,485,753,458,890,48,925,240,410,671,825,668,716,389,645,433,194,200,236,22,973,154,570,289,90,357,694,244,196,799,111,964,400,897,263,183,688,518,289,545,400,188,420,390,796,946,776,123,181,887,800,747,422,948,526,749,355,645,889,791,38,92,499,849,64,614,354,500,936,329,567,825,721,350,779,54,51,312,108,403,388,977,857,158,353,543,794,628,845,646,152,556,607,137,966,928,711,616,877,526,920,118,413,306,433,669,244,720,115,867,771,217,864,480,951,320,668,277,386,107,861,998,463,439,287,929,149,301,83,79,414,468,895,420,37,779,736,729,891,417,910,198,861,547,459,635,532,45,590,143,824,86,629,917,165,228,433,140,304,693,770,651,954,960,177", + "955,783,706,175,938,692,837,945,994,782,760,445,509,267,213,941,739,574,229,903,209,959,916,187,991,189,301,887,278,323,526,22,772,905,413,228,508,201,462,170,764,848,127,459,787,360,789,458,475,827,800,322,421,737,274,379,880,691,290,158,885,660,22,526,103,625,797,205,802,48,47,366,858,923,790,168,500,391,100,384,578,697,145,39,796,188,738,944,683,35,826,354,143,277,772,644,744,148,942,441,810,322,648,821,303,604,801,79,381,942,297,492,678,566,580,365,819,614,84,159,430,370,216,806,934,604,924,457,212,81,364,880,104,422,801,309,78,192,382,429,942,794,55,526,614,671,606,523,313,970,351,948,46,6,21,481,54,721,216,172,971,633,103,964,945,246,138,347,726,708,826,319,20,373,55,890,388,621,134,80,773,555,131,159,539,578,769,74,520,723,114,538,321,810,431,298,415,709,184,804,328,884,958,461,61,672,209,720,150,863,197,750,131,960,449,523,904,350,611,942,673,190,270,338,495,548,761,672,583,306,350,168,359,213,341,489,449,663,891,66,98,256,226,823,349,312,183,115,413,143,435,174,20,902,617,581,50,983,300,7,816,271,43,791,247,857,153,460,834,404,589,326,99,434,657,558,248,427,23,632,778,210,936,788,925,801,855,892,558,751,962,649,637,666,609,655,883,641,707,992,951,368,870,169,226,750,832,302,281,625,618,230,665,370,986,234,363,461,401,172,186,387,63,878,157,951,47,739,246,358,569,832,509,387,400,792,105,900,300,37,966,697,600,79,262,125,540,734,914,945,499,648,343,247,447,531,855,409,852,345,850,832,250,168,261,848,517,815,560,53,17,938,885,478,548,817,141,262,477,36,997,438,137,113,909,515,185,693,547,210,247,745,133,11,379,365,186,961,288,627,553,528,403,120,899,737,583,736,1000,42,909,240,4,766,859,847,313,829,631,712,730,326,222,827,942,50,126,706,565,773,628,715,205,399,806,335,848,952,563,284,808,614,85,31,7,561,915,616,786,168,228,425,14,487,540,563,208,294,340,25,130,525,442,425,638,693,774,87,79,799,263,227,476,582,424,65,943,668,545,660,739,585,135,217,337,637,320,935,931,117,551,468,590,246,358,135,783,960,164,599,973,675,636,16,37,427,676,68,545,432,367,317,174,99,693,618,703,998,193,788,92,246,277,686,93,967,741,996,98,540,606,765,744,219,64,674,934,670,15,590,895,129,81,338,748,813,988,140,0,600,305,793,940,783,502,283,390,581,584,689,342,872,714,584,692,378,983,247,284,803,895,512,653,807,505,331,926,550,155,716,849,9,533,456,505,862,157,630,919,337,707,306,222,344,67,99,553,212,289,779,16,86,229,664,522,129,207,367,191,502,528,959,867,618,361,195,81,678,155,454,110,379,941,545,652,712,311,268,246,346,661,724,849,512,331,662,495,880,921,494,153,357,533,585,970,641,684,958,367,962,672,225,796,79,365,924,64,557,477,988,695,774,654,116,379,357,379,812,492,342,714,943,600,92,997,339,724,775,415,91,392,586,326,663,832,836,244,320,626,767,92,139,994,766,94,825,510,217,985,613,786,381,732,758,260,485,458,235,302,881,296,625,335,770,917,596,206,994,479,783,660,13,363,60,69,37,305,96,550,535,710,11,460,810,804,964,84,69,563,704,225,230,905,749,709,608,816,433,49,7,106,49,764,417,926,651,284,396,822,892,586,619,276,278,637,27,139,852,465,819,872,692,95,548,685,68,628,365,187,494,455,560,423,222,714,308,470,651,965,406,169,802,397,398,88,658,971,194,736,571,293,381,390,588,54,997,62,479,708,541,806,784,164,348,370,570,170,194,572,79,526,854,683,180,787,719,896,327,368,41,179,849,512,362,670,585,738,145,344,192,785,70,632,514,69,488,90,925,612,208,731,21,990,657,78,117,85,520,754,59,576,809,60,340,961,23,45,129,55,50,294,495,668,190,473,975,489,904,171,908,349,717,837,424,208,392,485,535,546,911,966,402,266,686,801,621,800,188,332,843,720,949,580,770,993,974,584,762,793,883,717,403,549,629,328,15,963,817,960,25,64,813,60,752,330,340,388,896,947,934,930,867,463,966,886,457,965,506,713,212,228,489,725,525,604,686,26,160,192,14,703,376,629,756,416,835,735,761,713,215,285,34,914,348,206,448,91,643,301,894,129,636,204,760,587,617,470,244,710,405,982,860,383,395,365,933,350,312,621,489,479,698,912,897,912,846,750,591,565,212", + "531,59,312,847,757,897,311,8,894,713,525,787,715,642,237,112,366,680,388,562,656,143,529,646,666,416,633,569,940,13,496,834,489,532,150,668,877,219,399,847,44,576,241,935,326,886,999,561,558,631,985,272,904,978,91,155,51,513,52,979,850,609,633,809,509,403,203,718,323,686,805,544,663,21,216,200,922,169,830,233,989,944,975,279,987,970,150,938,288,861,242,815,181,905,639,483,248,991,825,314,87,134,538,260,802,447,518,270,711,655,88,86,124,124,716,496,32,928,824,210,343,521,216,29,944,518,167,173,160,756,385,293,345,564,822,608,634,860,834,236,964,786,149,804,20,776,624,780,632,654,389,33,343,14,857,763,385,135,607,948,667,259,934,628,616,121,956,209,286,577,410,325,14,671,771,928,663,315,267,273,370,418,246,10,104,950,634,881,273,183,466,91,387,211,228,65,777,931,690,242,769,605,277,820,723,281,170,52,638,222,409,572,741,767,784,539,442,803,548,881,877,796,941,860,409,45,858,525,885,931,759,409,399,341,788,341,937,537,7,957,826,808,648,635,728,164,867,498,90,910,849,861,366,60,39,919,817,64,807,963,939,446,652,921,960,544,965,815,70,704,7,693,904,60,327,670,467,858,447,580,258,908,706,171,339,840,536,527,600,730,909,281,500,963,232,678,599,91,730,665,209,58,2,261,525,68,326,886,631,473,148,557,426,225,569,486,17,615,394,348,212,965,472,228,220,242,940,230,393,65,446,825,313,115,925,487,948,28,257,314,401,362,133,704,823,192,788,517,194,885,226,292,671,437,15,123,259,11,461,372,977,539,275,833,680,907,874,197,528,8,151,288,885,409,988,867,411,918,572,598,187,376,366,3,259,78,154,177,346,912,388,190,605,370,534,304,526,776,787,551,991,92,646,22,686,929,165,781,412,850,624,160,740,624,358,794,994,82,857,312,200,663,84,712,746,78,897,319,826,793,182,290,877,678,503,116,670,992,404,658,904,950,933,648,599,897,661,625,688,492,773,559,993,284,290,909,181,249,240,11,223,846,221,890,919,560,344,639,849,447,484,743,103,400,807,159,65,483,518,965,346,361,613,94,839,219,635,322,798,396,660,937,34,214,584,455,355,432,998,213,919,861,362,896,776,357,511,57,286,414,602,8,314,251,148,634,834,275,513,244,760,312,7,965,859,631,183,285,304,60,927,437,184,408,289,106,664,320,582,619,433,806,79,487,696,605,167,963,600,0,594,970,990,664,76,43,309,3,208,818,900,978,896,887,556,701,261,880,362,110,76,558,360,915,739,525,580,961,732,604,648,834,123,690,689,575,162,969,412,131,198,988,867,493,586,171,588,308,782,633,122,515,857,878,56,462,716,321,285,139,529,405,768,99,972,265,367,9,714,564,527,343,456,206,181,469,574,587,171,272,102,249,660,427,170,706,468,191,872,161,345,245,259,807,758,94,414,644,875,316,961,670,428,540,807,536,646,779,357,538,630,755,81,291,315,935,280,250,133,422,989,127,311,223,487,677,514,108,630,34,994,654,142,116,612,575,152,698,398,604,771,430,935,491,29,690,178,829,300,669,829,328,797,460,67,496,238,912,826,180,895,261,29,250,606,499,8,332,642,875,717,882,787,959,364,437,241,380,693,803,335,106,916,729,741,114,66,105,355,439,752,703,146,531,142,385,431,983,542,965,623,911,467,286,735,275,681,779,345,398,125,989,603,742,179,960,190,76,71,837,244,500,239,866,260,373,191,122,431,257,246,956,461,410,6,823,514,106,797,194,641,139,808,240,483,27,820,973,752,910,29,603,550,431,883,656,203,883,932,239,559,63,656,799,542,682,6,942,1000,183,622,631,36,344,642,936,240,164,326,963,502,306,124,269,559,34,460,825,624,688,563,590,436,260,433,860,23,682,26,191,764,485,136,810,548,242,636,289,267,814,720,591,902,458,434,832,916,378,423,246,317,220,840,160,350,92,301,154,786,355,834,181,985,614,915,657,945,986,416,177,51,509,379,553,876,413,882,224,856,245,834,571,164,659,119,498,7,276,725,85,402,498,814,693,679,171,193,246,271,159,449,20,887,74,895,89,218,401,467,484,777,898,393,997,829,52,873,995,292,503,801,947,282,438,189,742,623,634,913,79,317,979,120,17,86,13,108,380,913,772,887,24,5,952,438,967,994,896,257,896,482,801,100,623,572,774,458,6,586,654,574,231,437,167,104,875,285,764,567,206,47,166,662,851,38,284,977,268,839,571", + "431,459,712,324,911,51,263,478,12,878,118,697,482,104,773,815,199,518,105,116,910,335,346,792,920,142,362,440,498,435,81,396,536,535,355,871,430,187,944,20,965,752,966,191,649,94,979,675,742,981,885,606,128,935,112,774,146,887,127,631,250,691,801,700,945,747,785,546,571,362,108,997,399,814,714,22,238,34,965,609,64,631,672,611,987,594,109,539,787,813,131,298,118,435,359,92,765,336,595,218,439,914,260,29,148,806,826,884,206,100,80,413,339,955,5,117,912,584,492,478,337,169,725,76,689,865,813,563,609,254,142,384,274,290,481,782,351,481,46,130,359,320,298,589,503,754,29,833,923,429,231,85,137,46,969,482,398,351,495,492,760,606,767,965,525,53,204,874,634,978,177,797,396,301,922,300,184,243,116,200,714,561,458,929,430,896,242,818,641,837,793,229,225,665,692,54,81,627,488,526,925,478,977,676,214,587,265,801,510,11,870,217,305,317,221,528,647,527,170,46,382,331,881,246,164,984,915,785,784,69,973,512,929,941,53,568,72,578,28,718,98,929,795,445,575,59,94,819,161,448,547,783,570,508,259,243,741,675,106,339,684,278,72,999,209,25,124,13,551,965,284,297,340,314,697,969,879,339,191,381,800,919,67,52,373,528,839,903,235,823,865,665,716,530,785,629,67,839,250,27,416,183,733,688,856,43,628,918,291,430,488,101,73,701,101,786,813,864,856,820,970,504,589,881,112,630,341,526,824,738,304,861,890,547,835,133,350,832,130,747,574,474,938,402,19,679,767,61,794,913,646,203,778,190,859,899,545,766,999,411,130,655,835,328,534,345,330,578,873,101,459,273,77,533,123,673,125,628,722,678,800,587,656,533,994,713,408,355,808,522,205,425,253,66,142,276,114,221,308,384,444,195,601,711,15,611,948,563,228,842,238,106,291,270,161,346,62,181,805,390,622,604,690,824,15,254,269,424,420,291,903,93,110,504,781,726,588,821,471,540,953,382,630,534,843,651,409,749,983,394,384,354,632,36,507,407,353,145,905,433,969,498,613,305,679,456,81,246,717,268,816,263,354,183,152,288,249,860,997,676,419,609,156,667,662,180,115,135,961,528,911,151,882,465,283,689,728,920,59,237,430,664,571,404,148,477,337,614,410,159,513,290,361,758,144,240,207,923,340,466,721,212,229,928,712,808,817,253,822,681,668,158,183,707,47,231,80,759,91,447,809,777,986,451,24,692,668,850,305,594,0,415,246,758,266,733,806,556,794,581,55,114,982,808,470,479,528,64,28,432,959,771,246,982,6,706,32,479,878,769,851,669,502,446,157,353,342,705,425,678,572,512,111,925,604,16,655,294,551,130,31,533,527,209,79,310,149,170,817,558,964,353,114,177,691,228,787,480,85,352,679,73,804,358,3,937,321,146,715,617,410,463,604,926,89,855,580,235,163,534,923,631,430,739,685,682,925,494,436,776,561,692,393,964,191,565,919,555,735,990,695,330,151,432,952,625,531,718,621,942,445,597,288,142,161,660,367,761,71,13,378,821,839,616,126,419,737,297,957,791,180,860,364,546,895,251,285,897,98,428,581,542,142,430,127,670,232,864,772,906,143,975,823,860,101,560,870,734,525,179,418,73,585,385,515,434,997,796,618,24,17,216,387,427,136,835,542,749,647,689,979,777,454,739,52,338,245,727,531,699,631,23,99,522,587,501,854,224,367,986,820,554,245,846,89,862,749,877,882,176,16,142,495,235,873,409,472,46,988,192,468,26,603,982,57,250,461,759,851,852,171,525,784,224,36,782,599,967,551,777,214,974,456,780,783,734,297,178,386,442,896,742,269,33,796,208,625,61,405,542,941,456,771,616,662,735,734,324,592,345,937,148,101,463,251,358,957,366,221,872,536,338,20,676,162,379,616,986,329,947,838,376,375,7,688,715,155,331,309,938,330,944,407,506,986,354,237,482,693,766,70,650,413,729,301,707,45,837,300,202,350,441,637,981,516,374,399,715,473,768,630,258,327,295,925,972,403,911,810,960,593,644,154,427,672,332,275,845,360,533,704,723,519,189,770,571,144,8,745,96,825,204,28,486,798,827,399,235,487,873,985,875,229,162,433,699,175,886,742,507,813,93,307,57,724,610,695,380,601,569,119,612,511,197,162,14,886,80,467,168,985,296,944,743,502,66,544,411,530,273,616,807,319,804,965,494,973,726,839,871,669,879,295,722,570,865,225,473,760,5,912,400,49,713,811,563,897,92,450,600", + "49,932,321,706,414,425,568,40,388,184,32,248,891,444,29,79,642,382,594,241,701,436,645,66,509,418,810,333,460,622,747,917,216,877,575,417,195,337,884,26,138,353,96,230,348,469,452,454,432,301,189,921,930,979,894,552,136,771,872,530,400,635,942,968,773,434,446,591,579,157,533,578,741,605,255,985,632,18,489,722,276,248,164,414,292,927,687,365,863,718,246,174,427,337,981,999,7,522,618,626,527,204,519,308,945,488,788,963,11,27,673,563,464,94,258,406,658,88,830,840,964,504,389,565,972,193,109,939,227,208,799,456,134,527,934,695,200,750,85,187,604,477,755,800,271,552,948,95,37,649,148,131,967,283,619,136,177,966,492,436,725,799,356,720,448,152,55,220,224,494,791,713,260,973,450,311,275,313,164,382,3,916,368,190,327,635,267,930,285,162,294,14,528,163,711,849,15,195,100,666,323,763,235,875,41,444,978,813,732,815,349,533,410,553,780,405,478,896,639,816,525,767,934,496,830,59,770,390,871,463,131,999,319,473,357,762,680,590,417,612,135,310,775,44,528,576,205,861,979,59,210,183,1,50,313,315,94,833,214,501,258,52,816,258,22,559,254,829,771,355,570,369,281,513,168,320,496,795,158,875,254,1000,943,198,830,817,511,428,515,983,918,734,223,154,548,481,949,823,333,755,817,777,107,119,109,229,676,494,623,564,884,277,742,365,950,94,486,545,518,52,835,928,176,825,519,869,492,754,91,545,714,170,184,506,863,37,802,466,800,551,167,424,299,170,608,113,671,306,439,448,52,782,739,640,741,585,156,553,740,823,179,541,202,485,265,589,925,87,830,906,2,865,634,253,721,965,371,665,694,736,548,531,914,898,235,25,855,810,853,974,242,335,384,693,472,823,822,294,639,690,826,24,180,262,153,638,12,226,904,838,853,877,928,723,773,174,213,784,169,547,827,70,113,398,586,50,922,159,102,773,897,413,553,298,254,209,419,314,365,217,154,209,886,919,610,558,85,702,109,453,463,942,879,181,460,991,98,175,273,337,209,478,380,554,375,950,890,298,281,981,603,967,920,111,755,365,8,459,696,322,488,468,954,92,681,572,518,862,644,970,154,712,738,380,671,522,975,452,685,465,34,494,809,483,762,465,550,327,574,728,559,822,724,812,121,638,288,509,757,679,102,772,711,585,290,886,731,293,737,18,739,310,199,729,96,850,575,150,451,912,612,423,338,842,902,431,142,444,793,970,415,0,81,628,675,433,187,120,313,875,239,429,756,962,850,537,656,458,986,789,247,445,711,337,226,35,755,293,517,312,597,634,859,11,235,469,459,138,7,341,507,687,518,823,582,898,822,284,352,943,775,193,20,960,514,723,295,782,433,664,576,406,407,26,914,696,633,409,108,157,576,925,713,31,742,797,255,387,59,812,159,485,919,181,977,718,438,713,216,892,173,86,539,761,83,153,507,544,337,682,459,352,239,638,119,974,106,89,136,101,906,142,284,708,393,429,980,156,265,331,573,743,150,606,216,995,342,816,572,487,629,29,36,368,239,647,722,627,657,796,344,553,649,343,388,882,467,1,65,384,859,884,823,584,393,640,166,31,681,540,618,843,504,785,404,415,515,88,993,98,448,203,472,455,823,963,153,654,244,337,393,304,788,44,629,287,560,466,908,582,186,403,977,892,434,855,469,622,647,45,16,927,816,794,412,271,824,10,644,964,963,118,652,705,42,75,867,896,188,527,516,900,559,505,649,598,195,925,608,164,539,933,749,722,114,635,536,693,729,289,274,197,646,953,841,925,729,436,510,136,331,759,371,632,26,607,888,640,643,186,681,596,669,754,169,866,720,922,394,321,620,265,571,67,728,309,510,853,811,765,262,507,204,756,565,254,841,331,677,652,624,86,725,78,100,906,92,595,665,231,963,992,799,171,664,648,27,749,828,234,533,471,998,159,697,994,127,829,53,847,617,454,877,302,376,460,55,157,940,371,330,441,870,238,133,572,337,268,889,31,799,671,761,621,140,969,247,969,826,974,306,913,129,673,693,711,584,937,855,614,970,889,318,261,839,483,433,928,733,236,217,459,548,734,439,771,394,191,451,389,163,849,164,568,511,278,251,511,449,105,973,344,661,202,462,407,104,585,264,774,212,819,848,865,76,604,606,545,20,543,562,196,325,302,404,114,299,470,600,979,78,751,278,232,924,323,516,121,703,480,22,259,134,909,147,464,678,105,319,596,946,959,652,990,244,119,216,242,616,517", + "80,907,65,885,700,119,957,823,51,588,35,440,536,89,876,973,366,873,4,284,618,931,215,290,57,748,857,239,56,392,457,315,596,839,33,370,96,250,373,831,506,145,153,220,138,941,767,994,768,656,400,884,829,377,946,474,915,327,552,264,354,265,970,149,828,725,444,90,909,847,201,507,441,690,344,8,408,146,267,995,651,126,644,43,733,257,294,476,354,343,51,175,817,775,430,513,386,144,763,376,760,159,622,198,599,865,777,800,460,984,695,385,232,308,176,943,622,940,754,623,998,141,474,37,633,202,353,459,889,771,349,740,665,923,311,146,431,956,458,237,129,43,908,438,886,381,992,77,511,582,385,758,989,366,254,115,192,961,174,729,235,15,448,817,182,659,185,440,809,813,244,605,2,546,543,31,283,903,938,585,628,754,772,300,831,767,296,7,887,216,932,711,622,260,420,512,584,188,108,888,828,337,146,408,515,26,27,830,441,364,93,960,659,923,821,172,319,508,596,671,105,752,497,806,320,743,665,919,223,1000,685,154,47,972,373,929,68,185,268,501,82,705,546,813,834,262,371,444,96,709,216,34,688,896,682,914,809,14,707,238,81,344,29,928,116,936,781,892,456,64,822,35,520,583,996,530,263,769,193,629,120,483,932,332,386,309,886,580,188,592,859,411,226,86,291,211,991,129,922,975,609,53,791,617,350,632,569,470,776,121,105,282,957,932,106,479,60,936,716,77,849,232,558,660,316,599,533,729,811,787,236,468,673,879,691,107,688,29,324,537,339,278,498,185,499,826,849,820,287,357,523,689,753,536,323,348,169,682,421,228,358,941,39,183,986,574,315,824,72,402,185,554,848,26,54,846,630,254,254,411,121,807,471,7,526,557,853,245,428,121,231,195,987,338,880,829,826,913,149,813,979,428,775,336,930,44,293,879,950,328,637,691,675,118,897,557,463,930,790,950,125,790,918,750,860,108,858,84,205,828,937,412,284,402,97,470,611,384,331,882,416,479,928,713,571,13,706,125,986,817,595,193,247,879,838,96,104,360,816,493,718,677,770,382,305,137,249,158,957,187,64,763,709,464,396,929,186,608,177,505,884,182,80,850,453,960,441,808,149,970,105,224,271,300,46,117,26,996,111,686,640,689,360,680,646,120,269,520,15,188,683,636,426,167,238,236,230,532,837,209,485,79,199,682,994,398,935,732,233,373,444,883,246,88,185,25,119,752,221,389,499,819,911,636,914,424,765,325,940,990,246,81,0,37,483,221,366,311,527,612,586,305,192,60,860,185,68,680,687,593,454,93,546,48,810,820,663,749,273,557,245,532,222,857,647,538,347,924,260,899,789,389,66,457,919,775,200,173,137,390,749,491,6,691,893,132,335,532,834,39,93,273,175,869,336,434,945,390,482,133,774,747,480,442,596,694,933,389,385,720,587,167,869,129,760,904,848,992,562,939,409,297,570,278,397,903,741,811,235,669,62,314,100,934,607,108,225,562,439,809,325,242,277,560,134,971,437,72,716,131,397,177,459,766,472,643,562,394,480,356,520,937,75,807,63,464,824,131,537,336,220,651,914,590,690,256,487,457,680,561,284,144,565,317,521,569,205,516,991,45,955,917,685,550,599,874,933,303,308,417,130,716,966,231,274,823,650,864,510,865,286,794,39,162,230,626,759,638,485,163,235,598,614,946,622,129,813,312,495,16,261,213,719,681,337,148,283,408,389,576,349,45,768,922,587,659,520,135,266,374,161,920,461,765,536,347,488,325,916,994,830,371,124,616,271,15,115,712,322,609,217,447,460,389,653,232,620,754,86,483,953,457,173,785,658,550,460,874,242,548,873,532,949,607,60,834,207,556,210,102,376,133,547,817,56,169,201,214,682,486,775,555,846,593,434,683,244,190,893,666,487,62,237,46,169,493,426,973,207,316,394,265,310,795,396,158,843,564,356,225,110,944,940,816,999,478,977,945,2,48,794,279,482,469,828,340,973,741,240,488,523,721,24,934,7,41,509,391,977,301,238,682,839,198,154,409,673,736,449,488,655,165,204,379,598,162,116,862,335,762,165,959,146,70,93,522,511,714,113,721,949,680,964,325,3,388,3,21,767,686,466,806,793,251,103,316,109,158,386,724,147,307,846,344,562,523,968,670,220,143,57,19,97,857,690,798,777,59,69,351,833,851,123,782,575,660,517,218,872,322,353,264,650,463,395,260,61,302,969,911,296,483,921,62,764,95,512,736,637,794,206,335,103,401,647,146,496,39,143,678", + "699,612,914,931,648,567,63,823,106,193,990,908,934,46,195,423,166,826,840,430,126,885,830,933,595,619,272,825,919,477,488,536,810,849,599,441,368,854,129,820,717,41,509,464,116,188,733,5,196,778,5,195,681,574,231,256,897,500,874,253,464,87,510,853,313,6,627,70,526,155,197,37,752,722,114,670,846,947,934,942,288,287,840,212,414,915,114,706,560,850,454,962,277,956,24,623,33,486,545,433,562,752,316,961,770,84,746,861,748,182,318,687,181,697,731,53,370,118,755,541,111,932,693,688,84,852,120,561,541,44,263,838,136,684,469,193,548,877,218,507,43,448,254,582,553,652,796,900,441,957,634,619,484,540,793,210,676,212,930,465,474,74,881,552,587,807,730,87,752,698,746,13,936,168,364,863,12,913,755,251,552,139,190,554,313,232,959,343,453,432,273,725,98,658,269,34,481,97,530,472,691,100,722,347,495,482,816,718,63,242,762,307,584,38,29,133,140,393,322,821,298,738,745,394,781,973,683,732,968,308,223,965,404,289,35,904,955,988,52,726,107,731,195,799,806,57,327,980,937,742,894,920,290,434,302,699,206,542,528,140,177,32,685,92,483,329,754,823,461,494,271,480,803,481,442,499,795,248,933,102,203,921,74,359,119,833,52,667,868,63,497,904,320,853,258,893,176,388,435,307,575,675,68,214,195,634,665,891,330,214,13,482,102,638,950,267,357,581,803,63,211,901,502,622,972,155,288,96,72,945,491,450,723,817,143,239,557,825,820,368,335,668,740,941,895,493,316,140,327,575,21,154,870,732,490,232,94,165,540,186,923,493,817,660,274,202,227,142,57,74,595,931,46,982,363,210,46,806,369,917,718,915,397,902,358,643,836,282,343,632,787,325,319,236,23,976,256,90,1000,628,209,727,137,178,590,699,111,441,558,941,116,153,941,608,212,201,290,264,805,399,491,185,245,662,750,117,401,486,734,496,415,180,272,747,922,263,404,751,99,592,730,832,850,421,57,681,752,917,968,220,274,116,7,717,346,697,217,340,834,643,514,954,416,785,686,719,783,274,169,632,116,638,871,976,281,413,626,51,286,865,931,853,669,213,514,276,437,505,326,142,584,720,729,148,78,700,252,106,731,245,979,808,429,753,108,759,907,823,709,212,133,826,416,443,427,894,909,87,61,567,226,150,265,573,694,924,683,2,614,87,468,988,295,466,907,145,606,929,108,278,902,445,824,182,850,760,156,560,783,664,758,628,37,0,990,423,916,380,567,673,955,541,670,509,84,65,189,989,661,387,178,895,516,234,230,120,176,916,212,915,599,684,491,847,931,36,979,518,151,162,273,471,725,831,800,474,210,232,988,999,734,134,545,382,224,772,377,428,239,500,296,686,397,540,147,110,664,53,24,429,184,892,586,439,277,360,945,238,435,147,452,313,448,215,587,602,553,733,18,285,892,198,37,635,822,459,188,528,817,220,193,361,993,840,544,704,46,415,306,846,560,295,153,732,447,343,550,630,924,455,296,109,459,919,926,182,554,502,844,698,736,874,709,352,552,263,454,981,578,607,440,569,632,31,899,792,876,16,185,266,699,893,308,265,367,756,144,364,477,127,713,417,198,478,879,973,941,386,424,119,834,790,139,196,15,644,662,416,945,30,730,904,791,435,286,387,882,75,230,304,718,969,479,448,28,137,866,678,763,648,139,796,104,187,150,852,91,297,767,311,237,429,395,811,92,756,22,897,61,681,118,451,452,627,692,463,910,532,92,885,276,252,398,759,880,565,541,9,812,26,169,530,955,99,227,928,463,515,5,696,88,726,848,350,789,798,602,925,741,204,356,493,642,210,105,905,218,744,304,59,828,995,794,422,226,360,487,40,747,301,324,675,719,505,946,34,630,884,239,236,859,430,677,25,490,414,178,694,934,275,121,622,835,991,497,50,955,617,107,937,464,354,442,782,173,15,738,424,592,490,267,439,795,579,984,899,14,897,414,744,781,303,62,697,352,311,432,230,427,238,545,765,233,208,632,976,179,483,377,522,130,91,318,249,130,585,94,231,837,129,163,568,515,329,470,519,617,593,632,972,363,378,85,602,744,535,877,302,338,953,124,443,734,477,338,105,937,439,100,567,854,489,633,644,792,78,79,983,9,772,58,446,672,730,229,520,743,786,119,333,420,686,186,32,453,965,708,857,698,190,609,79,664,155,719,292,994,571,899,605,192,612,929,134,288,627,918,364,81,218,904,308,628,688,61,750,557,987,887,318", + "35,40,962,724,266,895,260,141,569,129,752,327,483,416,86,852,547,157,736,271,561,532,999,270,823,638,764,794,455,835,912,371,941,1000,909,161,373,948,248,351,862,201,951,354,591,673,243,11,557,299,608,985,658,546,760,916,88,300,720,567,500,304,890,778,309,608,731,445,888,86,908,538,644,411,723,649,723,46,314,624,207,885,527,661,346,548,707,447,72,400,305,410,694,760,217,228,623,79,945,733,739,903,265,232,681,754,288,847,813,354,332,546,395,665,343,311,287,567,816,726,889,327,100,731,16,883,101,263,657,949,457,45,17,9,93,217,939,562,265,545,393,350,656,387,333,268,348,617,453,797,492,249,190,861,456,416,739,346,695,702,835,640,434,143,265,206,311,219,581,149,766,868,244,323,602,800,651,874,128,754,272,577,906,984,203,152,736,953,793,96,79,760,150,868,324,443,933,823,899,796,104,273,282,950,394,428,265,234,54,408,362,258,452,684,106,193,822,88,643,478,547,743,377,142,168,820,240,557,616,916,712,793,272,827,785,49,374,944,253,714,441,820,709,523,1,936,175,819,167,899,17,311,87,884,820,298,590,286,502,208,945,902,718,11,351,769,545,767,582,400,826,276,62,211,371,898,895,436,183,977,881,747,829,524,1000,22,523,398,843,328,663,85,224,243,132,566,925,483,653,607,736,613,879,579,463,17,801,196,311,99,842,833,23,167,93,858,681,785,245,865,861,692,871,782,884,192,794,427,837,660,663,184,985,948,249,201,291,197,601,378,343,697,243,355,683,290,105,470,156,79,587,53,278,626,279,38,185,610,802,739,25,541,381,341,874,519,170,726,956,700,438,135,748,256,76,180,992,743,289,750,527,446,736,909,97,531,278,294,74,66,830,337,514,339,372,925,522,844,23,999,546,318,816,334,763,509,491,771,137,635,824,424,962,859,588,732,48,244,2,780,195,266,588,114,459,214,373,439,554,845,393,123,661,11,462,577,136,22,217,218,292,989,770,304,668,224,286,247,986,943,118,617,557,39,753,729,115,555,418,648,833,348,302,39,800,265,396,108,679,454,680,889,57,476,669,428,850,550,237,875,870,62,413,593,261,657,886,489,191,230,636,184,549,579,637,860,151,387,92,718,232,577,452,423,630,81,883,7,144,961,158,526,71,53,437,87,438,653,919,860,266,800,584,714,231,166,330,397,239,424,481,311,65,545,383,435,551,456,179,190,841,123,477,233,276,13,259,361,502,76,266,675,483,990,0,722,888,250,324,489,938,476,536,32,251,740,598,458,962,56,716,972,343,550,461,251,978,806,455,937,734,63,799,330,916,553,110,162,979,668,844,715,511,379,793,520,149,446,989,524,909,242,984,912,994,174,796,327,336,383,850,569,162,23,668,609,665,943,422,422,732,328,324,843,506,263,231,695,277,125,180,568,448,348,971,947,415,38,657,170,111,166,273,134,369,911,19,937,563,943,329,920,871,194,823,570,193,139,535,142,987,88,949,765,230,791,709,279,804,389,587,985,309,38,678,398,478,195,53,448,941,942,411,308,257,777,817,628,671,807,660,692,54,206,78,980,626,906,621,283,157,987,535,744,633,538,85,277,729,313,959,300,159,775,248,166,262,146,856,166,736,650,352,40,885,673,752,735,537,406,772,39,577,343,58,527,658,839,569,667,952,556,823,938,418,874,644,499,528,800,670,841,756,437,555,9,60,63,860,507,389,9,778,897,894,897,398,233,974,183,11,169,437,673,741,743,755,470,425,850,765,609,632,84,7,493,763,56,52,962,12,161,76,713,634,225,478,294,29,369,445,572,54,483,35,211,23,230,204,805,801,435,528,884,965,4,375,985,165,275,551,403,279,848,358,308,651,665,777,107,179,524,151,988,401,15,363,597,103,982,942,493,734,640,478,715,863,8,502,824,813,499,687,844,299,663,506,663,273,483,802,912,858,646,414,65,771,394,679,462,510,470,729,428,236,722,449,763,968,675,977,315,501,387,302,311,598,323,633,20,881,346,109,398,278,763,565,846,328,749,791,297,642,950,169,503,777,308,986,984,100,949,942,495,623,27,426,574,733,686,429,648,109,388,850,204,230,448,149,139,339,940,828,205,817,815,203,345,778,447,920,768,603,685,289,841,406,101,753,151,728,764,882,185,349,240,871,961,333,745,369,792,60,493,490,601,612,23,494,866,771,687,482,974,291,444,188,643,228,30,36,932,562,286,650,277,460,947,712,864,383,998,972,818,85,609,50,270,894,494", + "345,138,71,124,682,664,523,401,90,681,752,558,749,589,826,983,941,915,105,119,466,295,839,559,487,907,392,211,491,367,557,943,945,677,440,32,279,990,385,116,967,754,171,753,271,968,742,939,435,902,85,617,991,196,908,299,388,761,311,880,150,373,182,425,984,744,379,275,998,443,856,882,374,386,898,32,870,900,172,765,225,189,602,271,442,622,990,775,968,207,982,116,680,700,238,975,48,55,968,217,22,16,431,756,809,315,952,577,821,737,575,584,134,433,973,505,464,193,103,310,305,194,417,361,489,442,900,155,678,532,827,457,975,286,506,463,463,478,872,604,693,467,320,896,522,671,357,813,131,478,611,375,825,234,945,838,770,767,33,825,570,786,17,264,126,241,117,380,280,54,265,360,76,445,33,39,326,980,401,150,266,823,504,893,131,780,900,446,326,286,392,718,434,672,275,728,641,495,227,969,336,108,900,203,33,36,98,940,94,849,208,879,695,556,21,753,791,152,696,808,160,723,513,331,635,246,557,515,632,947,334,792,97,78,131,548,636,626,815,369,159,47,190,395,940,613,706,817,710,734,16,638,669,344,121,848,657,770,864,217,85,13,50,926,422,427,356,961,739,795,277,762,849,525,983,869,977,515,186,544,644,933,748,178,356,71,564,661,366,544,968,366,389,866,228,237,449,130,148,789,762,996,296,301,84,886,61,508,47,875,950,905,808,84,915,568,939,162,21,44,995,459,870,698,38,380,236,860,20,498,33,630,994,61,814,825,252,859,745,446,812,620,792,478,501,703,258,983,24,771,622,48,178,689,194,562,400,91,986,451,58,614,946,954,914,828,668,425,403,326,316,189,336,685,560,829,3,338,966,502,10,747,545,392,400,206,490,952,460,964,97,535,161,887,566,485,410,990,211,157,766,968,575,103,218,124,807,832,454,297,619,323,672,156,145,824,931,858,107,276,254,270,860,651,700,507,368,744,774,582,69,538,779,909,655,640,234,143,943,961,331,792,230,869,11,595,40,868,7,480,929,547,7,791,712,375,118,495,705,237,373,936,993,360,83,487,903,936,889,153,630,595,411,751,593,174,26,665,551,46,412,668,840,821,276,908,109,205,453,771,299,14,379,426,234,836,105,365,401,458,117,439,426,988,606,251,464,250,214,323,664,888,60,425,441,274,859,513,248,642,540,141,795,455,246,342,782,337,159,789,918,998,338,991,487,160,787,740,463,456,186,954,690,855,530,754,529,950,283,43,733,433,221,423,722,0,958,214,878,59,585,303,765,405,676,827,707,43,167,164,469,350,449,151,650,305,349,236,498,788,729,913,162,232,126,436,231,23,574,405,402,906,851,780,973,127,281,945,805,251,846,886,851,573,264,303,331,219,974,951,239,750,732,600,16,167,954,993,589,955,325,806,432,829,567,204,601,558,552,646,704,925,55,830,534,734,169,881,17,765,709,410,924,231,957,839,342,772,880,881,522,272,215,36,857,888,276,689,819,34,87,301,297,282,590,489,210,56,945,574,789,511,998,694,472,193,128,206,59,376,184,639,630,646,442,942,30,179,882,563,206,393,431,128,140,995,23,13,730,401,524,344,427,848,319,945,253,873,982,708,215,826,67,327,516,2,915,260,858,557,225,894,17,689,144,574,858,784,986,421,266,56,673,568,897,589,658,159,998,977,108,137,339,873,756,497,163,668,319,850,565,666,774,703,408,637,242,449,28,278,369,201,791,117,164,367,325,795,401,263,327,566,298,284,239,60,394,610,240,697,806,359,82,543,796,120,40,184,870,11,13,271,158,109,186,579,265,156,615,54,6,529,322,336,37,602,263,496,184,364,651,203,823,595,336,231,241,811,847,293,825,780,789,544,150,111,247,90,254,800,338,652,224,87,750,760,459,40,968,594,32,191,957,570,359,916,8,467,248,889,658,147,569,156,634,528,681,382,460,934,642,769,32,234,755,246,126,516,81,914,924,635,347,708,377,480,830,737,423,570,832,631,926,383,662,542,821,496,260,118,178,585,423,207,425,178,458,926,766,945,733,390,395,430,52,164,576,11,419,854,76,671,713,377,155,152,996,301,178,287,781,327,495,107,315,74,192,473,430,309,681,727,896,181,100,907,468,356,751,612,328,540,727,133,521,643,487,835,618,235,202,416,407,541,525,316,427,51,436,468,391,451,91,564,364,20,953,498,401,774,552,175,912,4,698,77,139,501,746,62,699,984,52,867,390,672,818,501,883,622,340,252,576,499,959,98,91,886,760,246", + "830,857,172,423,578,536,834,352,572,980,690,310,466,278,335,101,176,51,10,206,650,774,131,293,308,911,741,569,1000,20,597,43,122,920,753,892,614,181,986,143,172,366,268,987,564,298,479,559,801,65,814,513,773,833,163,37,657,569,913,804,647,60,103,345,845,568,892,354,219,322,104,636,831,597,530,67,894,125,49,647,302,243,683,740,901,115,218,681,943,848,383,286,801,358,381,876,457,870,829,933,303,177,752,992,808,968,736,648,798,798,901,581,178,574,512,739,608,856,695,846,901,49,970,224,808,885,430,803,316,235,501,964,536,873,212,901,416,570,937,371,294,702,13,98,188,606,320,995,91,194,94,153,627,605,530,973,460,204,267,685,161,320,798,240,878,522,510,179,973,518,945,575,349,417,566,388,129,961,562,616,433,55,209,30,733,769,437,925,754,586,768,21,783,150,750,217,497,143,886,474,115,989,442,148,477,414,386,416,643,933,60,340,445,33,327,946,760,304,75,663,456,706,636,887,655,674,727,554,417,930,980,495,582,698,106,978,643,733,712,39,563,257,907,78,840,774,281,339,918,600,19,363,474,564,502,355,17,865,976,934,672,724,880,272,937,375,84,967,315,924,189,379,937,977,987,939,326,833,371,997,524,185,111,13,62,650,845,957,596,707,459,604,399,470,574,780,892,303,987,145,893,184,887,797,835,646,424,396,123,785,100,881,830,594,116,301,215,46,138,901,104,589,236,440,849,647,755,303,406,490,81,803,995,951,290,357,36,536,955,626,448,305,722,795,445,761,915,59,321,144,263,938,588,200,427,86,461,564,404,31,289,46,167,768,181,217,800,943,742,948,377,806,736,164,471,314,376,228,891,423,613,721,257,488,40,638,296,794,275,728,444,84,920,462,690,792,981,954,874,774,321,376,589,342,513,65,666,491,969,680,785,371,252,311,741,450,105,564,449,967,405,533,872,505,906,168,560,455,206,759,706,563,62,280,42,390,966,833,685,542,864,395,695,436,907,675,928,896,812,873,972,15,232,828,449,25,35,394,242,29,856,293,71,603,967,334,12,743,142,204,112,647,399,707,401,970,198,845,546,88,4,677,730,394,65,389,693,241,140,510,51,263,499,336,381,858,3,496,454,710,47,429,381,994,130,651,193,348,495,395,810,565,225,467,505,234,761,94,781,3,876,929,868,602,797,972,693,228,942,146,786,778,705,235,251,923,993,727,501,914,224,881,772,283,712,906,518,301,390,309,806,187,366,916,888,958,0,668,956,755,383,104,191,627,444,43,364,501,642,460,498,394,144,941,549,768,368,871,6,52,500,650,721,207,258,511,776,922,675,493,471,471,860,639,887,598,94,941,626,56,971,44,729,174,404,336,845,384,862,89,43,97,51,729,227,886,309,445,388,121,39,763,93,629,992,448,727,344,286,55,410,835,30,325,724,674,566,987,123,363,432,730,854,281,623,885,24,754,399,327,815,957,161,952,832,551,841,323,8,596,877,233,41,861,539,258,323,755,715,542,122,181,421,468,164,433,361,625,866,227,588,577,132,61,39,590,459,297,488,654,193,504,772,986,796,660,920,552,566,232,119,553,122,708,697,496,532,421,777,888,576,398,544,205,123,216,767,58,268,243,551,781,50,853,502,690,794,872,270,46,327,389,880,723,271,315,980,282,472,432,11,904,294,577,756,159,398,429,811,498,931,916,38,871,193,189,956,80,945,897,321,549,185,119,408,929,198,421,913,167,48,135,813,481,808,180,841,12,220,144,911,327,538,54,906,244,764,448,739,301,75,399,585,288,407,699,70,270,194,528,341,131,138,335,58,170,890,730,173,976,5,82,645,722,690,266,713,730,867,508,877,356,879,356,147,515,937,556,64,487,602,629,439,345,806,967,768,538,113,472,314,610,562,592,468,137,514,802,428,686,200,469,404,450,208,597,534,381,520,734,512,388,517,606,241,873,283,307,640,364,129,835,542,556,204,964,305,770,40,115,546,907,702,387,545,973,215,574,237,693,808,844,40,372,184,746,540,902,344,937,796,451,904,550,105,493,304,73,340,543,755,721,76,773,560,660,86,17,65,733,775,825,401,702,337,730,312,42,937,458,318,434,728,766,667,376,759,380,919,203,453,189,541,561,553,292,191,438,34,149,796,641,386,862,123,263,552,394,896,80,327,990,313,815,539,424,530,179,502,507,777,955,490,781,334,456,948,112,22,496,601,86,642,46,982,834,437,603,151,982,344,366,545,185,688,410,736,516,105,835", + "687,958,795,731,597,207,747,426,66,786,13,806,521,230,679,62,338,582,207,64,141,634,90,19,453,366,18,774,744,293,277,496,662,946,400,672,260,622,786,459,390,233,188,689,397,843,149,773,139,307,221,431,785,272,201,224,313,469,912,911,971,256,490,938,128,895,119,520,901,265,833,520,578,932,519,529,577,877,511,545,862,818,139,24,161,846,819,853,962,665,356,398,463,230,244,785,339,533,391,729,444,842,486,636,139,154,804,692,37,362,693,796,364,998,351,43,193,15,772,545,694,94,731,594,950,823,485,338,413,228,48,908,938,23,169,885,701,557,383,448,457,529,318,442,635,524,170,865,779,120,338,351,428,696,267,584,63,180,713,103,120,755,598,114,123,12,732,972,461,514,686,481,953,65,157,615,235,575,678,136,877,261,525,803,604,170,80,708,69,808,308,685,284,317,279,647,962,459,896,76,247,691,782,357,589,728,282,349,376,55,400,548,568,902,936,267,315,852,202,392,479,43,961,373,781,919,491,731,902,847,327,181,433,213,377,14,462,771,59,654,307,501,183,943,631,560,680,351,410,485,676,624,811,760,356,188,556,905,797,68,134,162,394,524,965,928,810,743,10,709,880,720,668,432,367,498,445,565,925,633,928,918,481,53,261,654,806,780,466,623,122,838,106,100,201,714,543,976,560,15,367,846,380,438,816,461,409,241,648,436,437,674,955,225,405,122,2,426,700,798,855,48,940,786,30,341,820,667,787,464,593,205,638,562,580,147,698,713,699,893,59,897,156,382,190,287,535,697,712,512,40,231,915,28,597,701,60,245,703,46,814,349,621,508,923,745,697,979,784,835,385,896,996,943,297,148,256,59,599,780,976,894,648,399,711,400,760,222,466,575,561,453,3,808,552,926,434,877,791,681,429,959,586,415,458,801,960,434,792,534,711,392,98,423,28,702,522,647,555,512,125,786,419,638,181,316,354,714,14,145,670,492,417,832,636,397,136,708,821,764,903,346,2,13,247,498,46,432,501,943,689,727,614,679,799,898,974,954,510,19,141,48,111,545,282,234,794,224,421,949,979,574,228,427,698,268,715,565,899,535,377,726,950,554,252,6,48,285,716,623,420,797,658,951,848,486,62,971,180,334,156,823,207,580,692,412,526,549,585,704,654,229,489,503,229,706,344,664,668,586,792,925,179,767,489,970,183,286,252,252,997,727,348,734,504,776,827,158,18,137,489,627,862,556,801,806,239,433,581,3,556,120,311,380,250,214,668,0,882,69,887,921,992,387,436,709,238,704,730,179,760,68,304,91,493,10,993,856,512,545,884,800,266,111,688,728,651,638,875,293,745,41,176,203,751,85,289,779,691,902,891,434,609,78,865,589,830,495,831,876,576,996,335,731,804,36,200,994,624,301,887,945,46,841,808,397,867,825,110,13,414,702,140,136,900,622,978,291,192,170,118,195,703,338,251,422,957,169,609,209,523,466,874,853,599,429,2,291,947,854,390,241,411,712,375,140,694,787,428,939,977,169,126,52,692,65,617,232,64,236,112,444,26,696,990,106,730,963,457,77,787,633,9,903,733,394,300,798,634,42,208,193,203,76,443,813,280,933,818,637,606,499,588,992,896,732,288,142,144,251,682,270,33,774,20,696,288,690,229,166,619,243,246,314,348,853,58,562,160,169,453,174,425,752,891,493,731,267,123,580,714,324,158,333,620,81,518,420,680,331,917,512,396,35,48,720,999,992,680,201,663,511,968,928,368,755,724,538,405,840,652,154,401,163,356,705,80,254,505,62,768,384,425,379,598,415,546,305,980,98,235,115,445,995,276,905,71,825,502,387,745,906,102,423,968,865,634,380,891,147,617,706,543,890,564,18,757,495,391,608,511,917,885,440,822,83,89,526,837,178,602,471,32,858,467,755,489,184,462,750,862,328,527,555,920,326,282,745,32,861,463,802,437,118,601,787,829,392,700,550,625,508,566,238,470,21,948,797,42,85,490,552,164,285,234,208,472,436,841,333,985,377,716,637,691,551,861,920,834,879,669,272,175,336,499,321,615,443,258,804,311,949,801,80,114,521,170,153,268,46,29,522,308,313,51,642,441,720,54,333,923,391,855,398,992,101,830,988,207,222,575,359,691,875,337,74,668,953,193,439,206,541,442,377,228,693,460,199,575,40,884,842,239,42,18,459,587,955,481,993,328,417,738,482,244,713,29,461,522,433,390,398,721,74,52,776,922,821,241,758,540,707,265,863,133,653,661,388,386,382", + "406,614,973,15,447,162,627,905,622,667,746,334,745,113,233,49,558,79,158,116,910,218,389,232,201,288,591,986,32,912,234,967,55,491,468,294,326,753,191,645,485,190,386,362,416,892,598,703,630,131,198,788,207,6,924,948,350,872,393,544,496,437,559,581,764,505,727,804,238,688,772,423,631,837,464,926,596,360,762,984,927,476,26,973,714,352,277,728,1000,110,155,463,889,169,393,119,602,545,145,978,635,991,115,428,650,736,291,403,83,254,483,312,929,547,653,872,747,507,935,670,446,164,272,290,951,799,177,715,501,700,501,95,456,963,643,228,360,590,855,70,245,529,568,19,836,748,60,551,164,878,637,260,524,133,547,389,910,937,348,634,713,923,670,531,51,613,536,948,761,153,449,176,947,769,526,747,292,826,229,685,168,518,478,279,124,542,285,97,491,113,477,818,37,684,761,60,497,249,474,604,519,222,713,824,438,673,420,957,593,327,242,464,282,682,500,701,615,744,281,213,315,491,198,412,109,137,875,545,929,216,112,687,622,862,63,237,581,334,629,71,456,594,841,787,274,285,673,836,29,386,723,11,685,680,560,986,452,657,145,959,825,128,140,610,263,377,288,448,224,899,822,534,714,849,289,838,682,347,396,363,14,131,815,329,431,547,581,589,920,476,245,395,814,262,797,272,468,959,458,293,933,217,88,321,606,64,683,695,385,687,231,59,732,991,492,940,63,368,943,183,930,812,492,987,266,887,591,240,620,137,797,182,581,910,100,524,180,654,805,980,727,339,641,307,257,109,621,728,834,761,644,404,343,53,819,225,349,3,417,977,667,963,653,81,64,761,908,633,635,394,667,155,455,16,661,44,85,885,956,205,975,20,815,640,789,677,9,68,53,699,814,654,418,292,322,214,480,719,637,512,151,282,617,469,748,419,212,442,678,806,256,544,208,887,597,128,41,845,342,918,603,202,159,193,264,569,33,22,938,339,526,24,587,172,447,213,463,659,527,484,110,617,817,666,340,780,545,341,503,997,285,40,418,442,772,756,276,626,787,197,522,439,147,168,673,299,103,781,280,891,845,333,11,335,193,532,994,131,103,77,958,370,396,871,111,235,660,984,701,347,559,815,146,983,885,812,427,17,731,826,196,547,792,183,188,156,415,915,28,558,720,80,857,711,935,633,219,304,284,813,531,924,116,227,880,197,920,208,378,471,796,562,793,336,410,568,484,546,227,99,172,419,304,571,13,272,503,117,584,208,794,313,527,567,324,878,956,882,0,136,377,151,77,385,321,651,94,681,69,827,642,455,808,651,41,340,347,315,807,369,987,519,69,140,21,628,525,357,649,260,459,259,795,700,26,880,176,512,819,424,483,506,158,324,475,655,661,827,496,632,265,50,216,616,581,662,410,54,437,356,513,574,836,480,217,872,290,582,599,209,382,305,149,914,304,848,639,704,323,87,808,86,690,16,662,432,255,173,888,432,17,286,945,187,159,169,123,946,509,871,206,95,430,780,532,619,24,606,937,813,314,701,344,419,325,294,414,374,979,437,27,519,227,261,443,757,11,725,333,607,425,787,296,485,916,701,438,581,92,730,573,233,721,305,960,191,488,837,903,434,477,7,373,441,439,632,821,280,502,101,71,817,435,159,584,906,800,633,558,984,138,569,697,848,973,68,110,614,221,178,967,261,505,20,348,49,410,244,394,337,959,947,232,209,7,413,245,900,283,32,757,425,387,725,815,907,739,661,725,816,210,326,888,769,247,124,428,359,85,411,24,632,330,817,267,287,28,999,127,913,914,294,352,126,795,56,589,98,442,23,74,984,47,958,274,340,137,913,866,866,299,971,71,724,220,2,316,492,916,279,123,883,728,853,598,234,700,668,187,591,281,639,639,231,16,272,43,191,815,16,192,226,190,688,548,38,979,109,175,719,725,154,382,49,898,132,236,16,839,663,95,586,695,272,763,676,803,796,664,391,715,347,107,825,625,632,747,916,619,898,612,101,313,717,237,514,89,802,891,37,558,619,47,282,324,420,66,533,765,969,206,460,118,970,21,88,484,355,585,506,356,79,589,831,629,929,428,862,646,34,627,250,905,293,348,268,407,965,915,382,965,377,52,658,652,703,732,416,690,658,394,401,901,857,921,451,75,473,788,169,838,601,683,589,757,406,709,826,552,881,652,663,448,276,572,875,610,468,562,895,884,332,506,648,547,779,237,47,806,744,779,872,674,178,83,704,838,641,19,610,972,436,159,13,319,564,333,266,974,245", + "605,164,430,553,734,841,863,647,101,71,626,809,358,281,344,336,718,432,283,937,235,358,929,353,176,658,618,818,349,857,600,71,800,34,759,746,192,756,330,824,244,133,223,632,882,363,694,448,217,106,395,609,458,508,121,8,137,259,921,649,98,134,46,889,506,856,423,962,725,868,492,661,654,940,252,437,148,351,685,660,23,478,883,478,310,959,535,618,326,677,699,540,94,547,460,218,96,834,298,835,622,249,650,626,454,957,550,421,357,148,688,807,486,795,588,411,381,198,985,973,509,833,107,531,429,371,430,10,282,853,221,815,634,367,809,272,450,291,393,861,782,463,380,569,752,627,136,698,299,477,966,348,476,199,866,386,177,458,295,12,852,965,469,531,508,150,594,746,586,899,362,750,340,570,41,99,879,308,360,287,475,176,863,908,433,351,3,925,825,88,912,76,550,797,633,18,862,216,882,672,148,920,612,591,849,474,80,496,36,399,159,872,376,359,971,19,404,214,39,359,356,312,907,36,550,57,512,189,41,152,420,637,6,300,844,831,727,776,742,449,776,607,155,119,547,803,965,659,754,123,560,699,850,321,450,346,674,675,312,148,834,413,536,355,355,985,676,885,599,289,484,902,479,465,46,770,974,776,30,653,966,185,157,711,794,728,765,798,765,359,951,559,180,694,168,126,278,20,800,214,447,521,822,725,299,981,186,637,654,663,586,2,678,275,307,480,653,554,148,560,933,769,462,815,267,155,892,97,116,594,399,28,133,649,955,997,204,875,549,184,368,167,450,719,512,248,881,802,932,118,574,411,985,549,365,106,931,156,507,408,802,609,536,833,923,498,234,606,727,971,865,764,338,582,201,64,19,621,69,923,212,157,942,249,485,159,419,531,333,720,810,327,359,707,525,347,121,163,315,699,982,234,133,602,393,298,342,391,741,198,946,696,53,877,261,204,267,980,325,509,376,331,952,423,405,51,472,378,732,557,913,494,553,506,988,537,525,210,427,333,795,826,227,401,906,577,417,691,129,156,910,777,571,271,367,819,935,105,494,958,367,200,820,872,735,825,867,263,601,247,274,903,147,575,219,929,559,330,622,649,222,790,299,699,702,840,328,77,456,171,411,482,289,262,627,278,635,637,921,399,933,306,631,618,934,738,15,272,850,113,893,795,962,130,70,426,672,844,625,773,396,433,663,971,17,997,558,536,475,768,415,662,632,781,350,143,76,38,47,322,468,771,48,729,12,929,541,784,689,818,581,875,612,673,489,59,755,69,136,0,789,494,9,623,573,325,596,825,484,626,349,254,239,237,188,691,444,52,496,630,623,69,260,750,649,655,666,990,598,83,476,517,222,881,901,623,327,229,48,464,841,563,248,47,459,602,52,583,928,115,155,734,390,363,591,755,292,879,554,288,174,64,522,271,221,752,180,908,63,408,972,70,217,648,65,99,335,28,247,120,598,794,868,731,577,116,74,944,952,498,427,693,948,303,627,929,602,774,238,232,849,808,662,129,487,10,887,289,812,714,591,986,2,51,395,650,572,277,451,149,166,303,501,355,591,669,886,388,816,363,404,900,902,796,265,909,721,567,290,769,54,963,841,893,678,570,692,753,712,80,61,59,415,796,960,311,476,761,637,96,298,389,540,352,125,924,89,716,634,328,215,170,114,625,617,231,821,977,571,869,434,489,732,297,419,201,30,249,507,865,123,972,75,756,310,923,266,784,561,450,603,94,239,174,860,121,353,335,760,82,829,227,476,123,452,229,138,732,287,480,729,550,202,572,719,604,450,937,120,409,388,729,921,316,634,548,686,412,161,273,487,171,138,739,510,135,408,180,988,949,603,907,166,797,502,20,81,236,321,841,50,243,184,728,908,931,949,953,535,185,173,972,392,532,251,272,216,310,931,551,955,744,420,458,91,22,146,301,236,319,650,824,517,977,139,924,643,931,497,506,710,347,203,825,494,173,574,24,55,311,104,687,981,702,333,499,912,517,495,475,650,802,321,304,652,867,305,418,830,962,628,803,561,726,521,390,635,341,167,894,49,298,711,363,968,796,201,890,504,187,612,905,386,508,308,747,453,5,915,59,422,189,933,879,14,567,959,987,492,424,135,148,18,878,147,27,918,843,487,993,679,122,636,334,434,214,443,877,898,70,837,735,579,553,524,846,466,831,489,628,770,226,492,494,161,29,129,62,650,325,485,48,180,638,951,542,166,38,995,698,524,409,931,650,210,787,137,576,915,116,464,327,627,345,404,117,291,552,418,292", + "872,338,355,949,570,227,691,757,335,666,492,494,538,107,808,613,53,84,238,663,548,387,211,796,27,528,809,262,529,761,390,971,918,73,824,106,551,267,398,562,743,704,150,867,938,710,774,180,608,249,725,769,747,203,976,470,242,86,94,288,289,199,719,330,625,917,877,567,264,526,232,344,145,994,208,949,16,459,795,674,596,895,723,976,554,256,187,280,375,326,394,294,412,368,976,360,293,119,173,593,560,436,889,358,984,372,8,66,958,946,887,590,200,611,803,787,310,7,391,641,207,529,476,776,699,442,50,627,660,721,383,670,409,240,642,584,682,323,19,914,915,135,937,161,731,585,408,317,506,167,14,26,498,198,926,820,38,3,439,393,49,205,953,156,959,464,254,257,696,527,503,506,589,324,764,938,286,600,648,282,248,698,451,604,866,491,44,126,120,903,367,531,384,646,348,121,784,5,854,892,804,488,603,256,573,966,222,283,254,802,642,372,717,596,954,245,111,750,198,936,663,484,887,776,481,824,147,696,551,405,639,49,122,836,779,882,326,773,799,745,71,694,993,946,168,636,963,994,733,908,835,418,720,657,445,409,962,577,798,420,776,42,668,934,137,491,380,907,339,870,468,746,75,546,166,604,139,874,738,121,287,840,569,927,650,198,344,60,612,435,653,380,182,18,360,518,6,417,120,915,531,951,19,724,889,260,94,652,132,722,786,233,144,513,30,381,448,684,368,426,126,397,825,271,228,158,69,49,690,897,133,175,402,185,473,747,793,166,394,178,624,185,801,567,639,752,651,151,803,244,558,982,905,50,389,942,405,688,271,931,596,287,391,235,336,271,840,453,743,879,169,902,98,752,524,173,94,910,196,587,877,125,941,443,540,101,809,353,377,952,689,939,461,623,293,851,422,22,148,227,643,617,432,348,687,808,995,167,505,110,758,319,427,587,636,468,504,707,469,78,862,768,215,76,234,385,357,834,148,33,894,296,976,309,280,779,539,35,539,43,391,846,60,335,528,909,454,159,948,179,408,581,800,886,566,39,663,879,935,366,135,748,815,118,111,657,424,472,900,579,727,621,73,997,788,413,597,469,469,593,201,483,732,662,220,321,575,262,144,34,607,853,198,603,50,216,772,15,554,143,737,240,856,260,285,599,583,283,948,53,257,297,284,928,295,84,491,832,592,92,827,704,886,740,151,515,611,806,524,954,724,900,989,542,44,628,59,32,364,267,143,941,641,523,723,184,755,381,342,900,55,239,586,955,938,585,383,887,377,789,0,665,350,405,16,221,70,153,35,905,464,424,200,572,795,592,344,417,323,864,418,864,409,69,722,187,586,518,315,287,557,280,912,827,237,284,395,390,717,850,83,808,444,616,119,792,937,199,937,250,292,701,396,244,937,265,265,508,502,697,77,600,865,110,87,584,171,97,121,801,666,854,933,963,124,830,749,317,150,841,553,449,388,321,586,154,46,743,162,50,407,348,500,119,905,277,967,350,796,248,533,30,55,133,87,645,322,73,899,879,423,321,693,738,395,587,4,291,969,779,838,855,534,837,521,80,899,266,641,307,116,999,67,50,768,995,473,452,966,696,60,472,465,670,295,76,243,512,485,852,117,993,86,26,568,802,437,385,124,572,468,509,272,582,629,170,267,545,796,551,236,728,913,216,922,167,960,186,838,655,130,576,30,96,325,303,796,711,594,978,266,636,642,304,214,549,90,812,985,566,388,967,8,858,952,145,861,47,610,652,493,461,731,305,927,804,738,923,664,145,599,704,147,267,158,384,173,181,153,305,394,887,698,811,869,391,208,470,153,347,982,831,646,690,116,693,697,945,478,587,183,235,186,247,655,496,863,746,91,372,749,873,848,415,685,870,793,246,793,128,747,850,382,246,316,151,80,530,913,343,852,578,497,12,788,484,715,413,910,300,762,651,104,17,142,512,686,284,940,524,830,623,417,178,204,145,834,162,961,194,727,691,352,729,79,156,849,498,327,671,834,816,417,131,37,882,48,528,234,472,401,153,891,534,563,405,30,953,780,868,3,229,773,390,790,9,941,538,491,772,474,202,502,568,539,204,141,244,708,473,883,252,741,845,740,720,977,128,13,295,394,572,882,289,450,867,870,977,789,611,951,481,93,720,401,733,668,939,263,305,437,870,695,318,219,690,748,441,506,776,671,344,696,188,888,484,250,823,927,167,895,390,317,572,808,37,757,961,311,172,725,865,371,449,98,232,187,250,446,972,331,540,617,191,73,547,455,600,199,24", + "293,5,969,79,236,760,192,950,319,663,320,601,815,962,105,505,407,182,872,149,512,407,534,554,962,939,270,832,121,294,994,101,179,680,491,524,61,603,298,229,134,154,318,174,798,400,13,205,993,53,877,537,77,524,43,661,513,17,550,59,450,349,442,484,255,300,426,378,759,899,651,494,603,397,159,153,98,517,548,200,630,188,680,256,667,828,289,634,246,700,707,646,760,276,953,436,670,869,545,36,885,888,929,511,476,164,214,192,599,7,717,304,234,386,898,56,723,239,623,58,574,810,756,370,497,626,672,771,566,698,581,661,480,894,28,730,248,521,44,392,601,171,783,491,412,802,142,657,5,587,326,290,455,134,673,845,915,676,510,26,522,39,989,980,167,823,783,969,839,907,450,661,98,204,586,133,682,467,668,873,379,67,691,391,131,628,885,886,210,393,582,547,571,47,282,164,610,979,192,349,946,434,704,915,837,974,156,636,773,121,774,29,954,870,377,417,4,125,508,117,35,207,212,415,351,30,639,273,188,57,613,174,364,104,637,190,495,109,74,878,52,664,985,347,182,332,184,609,477,149,579,576,968,572,97,419,194,569,23,963,938,683,111,943,874,580,526,353,753,50,834,454,505,902,901,952,806,526,211,36,290,343,20,629,17,623,804,824,878,123,108,652,712,332,666,418,392,904,914,212,98,519,798,806,235,131,211,684,180,843,524,742,797,917,924,12,58,713,354,414,768,654,729,491,278,200,523,387,150,842,826,821,102,401,239,126,232,375,865,442,157,205,609,70,256,895,259,829,105,624,102,685,36,648,284,217,161,493,45,224,803,432,923,667,375,32,293,990,411,234,544,420,393,229,476,274,446,655,143,30,862,719,883,117,315,929,786,843,25,800,224,808,996,353,706,210,318,902,71,402,667,435,507,419,978,889,95,122,125,612,706,141,724,927,340,651,994,612,604,877,752,88,661,899,731,39,891,294,467,663,930,685,557,788,576,305,615,44,389,703,531,468,383,337,429,333,115,463,383,769,583,268,582,175,787,729,936,43,619,498,91,86,709,844,456,43,11,383,537,428,600,923,854,238,844,198,741,104,97,849,663,49,89,648,947,288,235,677,239,820,577,581,19,260,10,835,630,57,223,44,941,992,115,946,539,509,948,569,64,625,511,696,217,841,871,320,368,767,585,445,588,887,553,425,501,814,672,853,279,905,748,402,295,128,686,33,854,460,658,928,63,913,789,814,359,32,546,114,872,978,114,429,305,541,476,303,104,921,151,494,665,0,863,645,876,269,967,978,15,621,73,180,401,562,449,350,457,666,952,819,878,418,658,48,433,786,325,726,100,386,330,367,660,631,702,792,685,792,976,920,171,125,457,361,833,517,546,571,289,521,54,339,378,886,725,716,667,332,268,141,62,110,417,831,732,746,253,135,704,802,841,949,283,944,252,833,720,906,555,134,45,977,2,574,330,534,479,696,595,103,31,821,66,921,781,669,51,317,879,440,89,863,390,296,188,751,876,469,952,863,125,13,740,547,878,251,477,90,44,423,859,654,497,776,599,244,593,879,377,974,306,734,795,175,224,306,225,656,307,588,163,63,410,300,809,97,373,458,804,794,302,489,303,131,392,766,270,248,554,955,406,29,784,321,854,176,972,503,817,734,656,835,277,512,16,914,377,429,285,263,525,137,148,165,272,974,722,673,843,777,636,811,731,823,398,841,181,205,810,291,583,284,998,668,583,187,472,74,394,403,256,219,42,234,479,704,507,547,875,40,862,380,482,588,335,244,561,333,381,728,877,922,279,403,347,471,236,492,441,276,822,685,162,392,749,714,670,537,608,80,993,566,51,163,187,768,307,777,705,166,672,293,333,395,589,847,911,542,125,41,77,713,486,243,201,50,780,852,571,933,444,406,553,38,185,343,776,570,401,266,438,973,130,470,31,498,544,890,443,301,711,921,109,862,505,777,770,53,480,809,891,489,495,524,32,15,644,321,888,990,462,947,431,177,15,221,506,566,522,930,324,485,303,948,65,280,521,972,786,984,740,986,181,778,997,676,564,643,902,415,324,841,774,706,929,817,81,186,904,319,745,616,719,471,345,831,521,124,520,811,636,225,714,319,475,47,857,809,495,108,518,722,575,602,362,378,608,974,355,59,204,638,586,272,185,135,913,919,337,345,303,169,690,585,614,398,344,509,339,201,382,312,192,526,214,67,243,993,750,536,161,55,454,148,139,786,410,25,947,421,344,498,728,648,949,92,42,749,710,849", + "697,467,510,979,559,143,189,351,528,909,526,503,396,560,482,617,250,444,8,612,707,298,568,170,981,243,950,466,238,302,438,271,611,618,926,246,933,892,495,301,931,839,747,919,491,378,582,23,825,544,864,768,939,288,354,559,557,449,397,454,182,704,773,377,865,166,968,398,577,466,646,613,457,32,102,515,432,948,432,271,719,917,124,919,547,854,305,792,96,192,198,470,335,845,690,433,311,271,896,955,120,614,7,551,214,552,814,934,692,190,446,641,944,857,661,21,166,659,971,391,758,822,21,533,36,289,636,11,942,468,853,460,619,272,560,317,50,584,963,117,979,323,35,923,42,616,741,181,786,237,362,288,71,326,610,673,540,620,66,310,779,283,862,303,372,275,275,390,109,998,939,973,800,696,24,754,309,380,351,593,590,596,679,691,499,247,737,785,950,134,671,491,634,644,645,911,41,942,255,141,841,280,595,207,975,843,14,319,329,855,363,620,622,906,997,902,790,617,688,728,588,556,594,420,370,272,228,694,569,594,55,923,950,566,902,362,723,925,742,19,272,559,336,936,935,856,844,410,187,945,927,170,221,876,626,358,54,11,115,908,835,350,271,335,300,770,897,449,188,850,969,234,816,733,297,753,161,5,952,324,120,467,538,70,778,175,625,371,606,271,898,603,749,821,665,737,324,18,482,780,113,583,706,538,260,347,605,469,353,689,417,694,523,413,779,494,907,999,409,753,310,586,731,449,681,498,626,162,236,833,650,275,224,625,474,115,911,127,634,839,129,152,253,925,447,713,311,666,423,100,977,598,180,293,400,330,499,462,748,382,276,885,242,730,159,958,568,902,884,569,215,35,457,965,17,944,28,931,467,174,485,20,436,601,148,688,439,150,710,607,851,566,667,473,246,365,499,281,683,259,67,113,51,272,504,368,258,680,59,606,774,723,749,395,110,483,231,236,22,292,451,841,82,956,317,585,7,239,99,137,502,673,764,441,338,13,837,372,582,164,122,816,959,604,524,337,619,126,620,563,474,383,193,444,655,476,823,525,930,493,412,18,879,211,794,486,76,514,340,31,9,731,574,571,350,725,652,711,909,347,858,882,570,340,884,439,22,952,628,921,414,271,367,239,17,729,862,93,583,545,979,834,685,70,115,836,935,879,64,709,890,969,665,224,441,44,787,673,164,758,535,639,979,352,568,245,544,872,9,112,636,145,726,111,1,429,922,196,220,43,973,177,691,851,617,76,256,674,714,896,982,756,192,670,536,765,191,992,77,9,350,863,0,117,652,697,443,55,905,214,198,425,937,103,804,28,828,537,140,891,658,513,628,270,522,535,667,936,124,973,257,524,434,430,201,716,503,351,54,176,70,584,636,530,152,359,23,990,785,31,478,361,504,615,747,17,223,850,953,889,981,41,830,728,741,375,484,453,685,47,465,196,80,110,380,127,57,954,763,727,371,796,885,223,62,628,336,943,879,463,234,132,267,220,851,45,981,313,420,445,316,573,188,54,981,480,89,877,599,558,717,546,585,453,415,352,476,503,999,811,701,3,198,715,379,55,553,413,316,184,92,561,590,720,242,985,296,737,636,46,77,681,14,120,696,481,631,259,21,372,887,855,512,236,520,749,488,121,715,415,262,428,105,370,24,997,200,489,298,935,3,707,880,992,988,534,636,831,683,931,312,797,529,918,373,550,369,97,464,213,496,140,783,218,581,607,594,157,439,691,79,446,250,77,58,486,841,634,683,530,837,469,77,18,5,402,565,359,248,402,978,894,95,467,447,111,88,835,19,74,189,896,822,226,544,580,500,148,63,863,131,522,468,27,525,964,111,581,849,39,719,370,604,299,607,811,557,221,308,993,675,505,476,88,263,233,225,341,247,25,252,880,407,428,981,711,714,439,298,772,83,336,320,417,969,373,957,167,440,331,733,595,185,272,598,194,904,605,973,724,418,138,242,635,975,146,993,779,102,321,647,929,193,937,862,908,450,929,973,452,436,191,610,280,462,185,119,138,911,667,378,416,150,330,593,416,124,777,975,465,954,323,879,411,480,931,808,328,948,43,274,54,830,919,397,713,499,321,675,729,992,513,218,218,280,884,117,958,472,775,180,987,862,676,31,6,347,432,434,155,803,658,248,954,804,929,564,830,301,237,104,46,375,766,915,57,591,498,985,112,246,280,16,887,44,364,702,479,458,513,166,139,614,968,449,862,24,151,24,255,685,811,779,827,988,766,156,235,912,161,161,379,527,76,19,353,151,611,928,446", + "348,894,610,134,417,956,555,926,878,411,666,797,147,815,603,348,925,530,111,297,329,161,685,784,265,450,881,910,690,35,872,55,854,78,499,578,128,731,811,194,241,993,838,355,609,477,325,653,73,319,271,214,663,658,876,140,153,734,536,228,167,890,767,86,797,280,767,681,509,459,345,207,28,88,262,75,76,732,509,807,666,315,281,465,384,880,857,515,385,546,468,224,104,576,987,14,173,253,159,583,648,175,136,876,353,629,509,428,311,965,617,874,618,138,880,194,127,773,565,525,389,983,35,705,708,286,781,846,864,150,197,907,593,215,657,21,536,526,655,352,105,761,645,697,946,926,500,680,993,2,810,437,946,198,15,918,667,721,238,389,659,756,1000,310,859,815,877,123,417,577,117,108,53,388,167,101,208,242,752,816,967,583,595,577,318,220,32,980,469,795,857,327,65,4,966,84,164,472,58,748,864,246,421,390,24,582,141,491,794,65,366,374,650,352,147,896,268,611,719,827,735,184,138,912,971,857,676,151,125,882,452,998,61,826,762,703,225,292,10,892,585,960,260,29,561,517,194,369,256,590,356,368,887,423,832,705,933,836,697,890,338,831,93,968,778,605,574,155,722,645,901,585,384,857,520,667,382,807,101,922,313,714,381,714,134,771,209,506,316,538,113,290,355,950,64,676,880,98,106,679,877,876,647,314,651,591,23,632,856,906,276,452,988,80,166,574,333,927,704,457,641,499,234,386,919,517,113,663,945,538,521,876,366,232,955,805,903,962,617,702,859,983,190,545,591,968,323,818,495,804,806,803,917,409,953,727,804,466,874,383,170,836,186,195,746,968,384,434,952,694,908,433,725,17,564,687,274,274,872,702,650,199,74,505,826,923,303,104,14,105,728,478,392,663,884,53,543,293,517,668,391,179,325,296,786,175,746,387,644,179,487,670,427,255,896,863,211,799,431,414,376,919,106,765,147,122,360,674,722,71,109,356,232,664,161,589,663,170,69,568,998,942,808,232,300,128,872,957,968,233,823,218,312,119,232,369,274,692,397,847,629,92,102,744,103,254,296,967,243,425,537,684,692,5,481,264,300,26,468,438,455,205,440,439,940,863,160,611,265,639,271,646,675,486,795,71,515,881,328,346,46,752,174,414,15,623,3,575,180,450,507,184,46,819,304,875,495,897,295,867,610,254,951,559,673,351,664,711,722,871,665,255,598,560,765,790,589,981,843,464,772,215,565,448,817,819,685,925,584,887,808,962,60,509,32,405,627,387,385,623,405,645,117,0,896,203,883,544,286,954,764,382,231,34,576,827,839,835,151,442,768,934,818,905,89,831,646,66,25,191,67,835,447,705,554,798,182,568,312,938,446,778,425,481,92,174,630,856,371,564,799,116,477,33,260,208,60,25,281,826,108,319,916,211,536,423,728,158,563,143,419,18,943,115,633,46,840,136,653,362,937,561,243,827,793,798,682,838,181,355,360,818,974,926,739,302,102,834,251,393,285,144,265,945,836,321,754,358,318,999,971,486,960,940,463,583,750,204,346,627,989,494,907,898,262,508,411,327,568,653,892,379,970,200,271,793,887,983,380,606,417,10,590,206,400,781,550,471,679,638,41,586,966,914,887,188,116,690,724,195,307,785,716,804,33,57,143,409,757,5,776,863,748,204,262,545,628,997,882,127,758,522,794,126,525,404,719,152,240,536,846,541,237,756,587,560,582,414,204,785,66,950,413,95,419,636,710,698,203,133,51,103,143,59,548,531,432,993,573,567,555,693,595,253,496,197,490,650,603,650,408,762,315,405,438,183,362,469,420,31,660,513,352,997,728,445,995,219,873,254,715,886,857,359,263,20,617,64,103,60,456,470,999,265,557,410,930,73,664,974,994,369,761,50,358,589,153,485,3,506,770,359,986,503,273,782,670,305,286,862,245,630,387,26,998,328,439,153,811,845,378,162,593,448,698,244,866,775,440,469,610,701,115,379,323,509,155,287,934,490,7,355,668,909,187,742,369,557,849,434,356,523,998,207,590,531,20,159,973,76,983,824,957,289,941,130,109,374,71,589,209,906,757,852,833,896,36,740,960,150,606,885,657,139,566,931,637,201,645,384,449,702,525,107,147,577,236,95,325,529,820,847,883,906,432,229,366,626,822,622,685,259,950,814,30,537,500,412,207,834,349,630,267,212,677,731,808,507,934,202,141,222,783,32,288,965,433,703,669,633,926,692,135,867,215,43,721,559,414,735,317,117,829,208,729,158,5,943,277,972", + "296,513,957,926,419,426,88,400,751,221,551,247,807,936,189,339,411,614,454,273,597,306,473,238,223,766,789,144,184,706,960,126,791,936,831,783,670,658,908,746,639,81,638,702,869,71,570,183,243,228,768,42,173,984,809,558,768,342,364,641,76,710,804,671,323,978,854,889,94,328,382,132,851,825,586,596,274,439,560,792,858,450,57,190,316,551,784,112,423,998,546,934,56,560,499,343,705,47,124,8,547,126,606,846,8,157,226,468,194,80,858,79,264,165,323,499,389,628,56,285,415,95,784,772,35,182,469,377,868,477,872,993,727,46,616,221,24,553,570,150,118,693,220,770,585,413,838,213,775,427,471,64,546,968,96,61,526,451,935,613,512,853,330,604,42,103,722,917,995,763,592,984,45,845,756,544,730,704,102,353,647,623,929,594,629,196,202,908,986,594,650,628,187,822,454,513,234,493,130,598,886,832,978,696,398,426,779,575,294,713,859,912,989,595,333,183,30,207,368,459,111,398,259,798,383,303,294,440,286,645,53,60,971,512,453,744,261,211,711,910,444,152,243,708,987,8,787,612,779,497,577,898,373,882,89,97,584,426,988,567,224,219,845,461,244,844,532,650,724,287,801,759,824,814,697,566,502,738,107,842,642,757,614,487,394,255,485,368,182,608,248,169,164,836,218,430,154,779,738,201,439,365,967,225,477,824,490,692,824,428,864,388,543,680,921,658,523,821,604,678,508,528,173,567,511,696,439,360,880,672,81,266,620,775,531,226,933,944,497,975,448,364,723,298,86,62,911,204,450,292,930,408,706,774,105,891,361,936,828,452,847,556,125,300,700,969,612,601,519,474,762,49,703,788,228,721,570,359,834,179,727,237,640,126,682,268,101,972,769,206,772,864,924,858,942,249,788,19,351,104,515,850,457,314,938,956,324,891,154,10,190,464,948,35,590,458,883,576,786,443,870,419,396,924,645,315,209,717,76,422,685,903,999,465,713,565,369,834,735,13,603,692,837,669,650,308,218,610,325,424,731,123,928,313,799,945,726,412,667,215,930,743,726,145,16,821,432,17,978,525,601,734,237,298,814,262,663,290,464,553,275,59,750,886,390,425,374,406,211,716,653,460,279,242,997,33,211,719,128,958,161,695,589,302,580,459,766,403,136,368,312,340,617,741,344,624,166,104,508,792,884,426,552,565,866,227,387,301,308,380,164,799,901,592,471,859,606,297,954,682,611,177,455,469,746,737,965,573,692,556,470,850,860,84,251,676,444,436,321,573,16,876,652,896,0,113,972,954,50,558,584,635,879,203,157,861,995,771,670,510,171,17,387,921,551,104,639,861,562,111,632,123,716,457,65,952,245,833,869,896,622,349,883,217,606,689,500,121,938,563,744,870,650,831,998,975,23,51,527,314,235,50,724,692,968,855,602,323,548,962,128,68,829,767,700,157,613,710,658,695,219,546,226,930,71,967,370,981,511,895,898,719,833,518,751,687,468,187,844,19,806,106,999,594,844,957,886,113,700,308,762,775,788,890,652,227,155,111,702,651,302,940,149,376,628,412,895,619,577,679,464,155,695,39,292,188,709,875,867,952,494,299,107,125,905,897,423,160,955,126,890,885,301,430,41,614,961,735,780,297,935,211,748,863,454,661,489,329,395,727,832,347,721,861,830,382,404,130,51,124,74,660,854,886,980,173,84,862,60,30,736,649,565,928,377,832,125,974,103,459,971,575,963,947,608,989,939,117,930,926,675,865,52,964,942,812,627,268,538,277,980,127,642,391,26,836,937,424,888,724,74,575,24,411,197,790,268,69,608,296,366,357,999,231,205,995,746,798,375,121,304,78,48,707,139,108,338,329,877,468,902,994,974,671,947,274,831,809,70,986,848,805,231,447,58,279,373,655,235,190,99,659,896,431,203,884,220,300,710,705,368,318,703,670,415,311,627,793,234,278,54,457,578,615,29,289,71,109,551,221,329,716,204,88,430,444,3,91,510,321,518,910,268,804,432,749,811,97,252,800,894,150,516,322,582,741,491,592,362,622,604,395,797,72,161,481,486,138,795,481,379,28,338,949,620,34,181,988,291,785,439,979,237,287,10,662,289,477,914,251,854,253,275,832,418,326,794,373,702,747,824,591,520,592,989,415,857,477,310,749,241,922,143,782,67,180,843,64,154,533,891,658,166,466,736,295,81,724,784,974,932,465,868,58,973,312,528,236,498,354,410,438,160,642,575,322,490,234,271,214,232,912,628,917,695,336,413,109,108,551", + "472,352,696,103,971,241,41,169,825,23,158,352,230,460,487,469,920,208,476,733,724,831,48,248,598,23,820,655,611,520,168,426,102,480,942,511,546,875,116,14,300,670,790,499,21,656,976,749,429,527,666,415,425,944,597,54,254,887,227,738,604,534,194,970,196,393,365,83,281,716,115,980,99,366,247,200,908,635,326,704,866,790,281,173,202,899,149,624,14,678,114,312,905,311,625,615,867,145,595,420,342,675,137,661,689,963,235,274,528,816,289,610,821,415,364,90,79,71,372,154,503,727,189,927,323,522,858,235,834,19,395,798,875,206,902,257,357,20,568,481,429,631,400,831,333,404,79,821,768,604,68,718,428,363,882,477,720,34,737,179,449,719,650,745,810,478,349,443,424,563,32,287,724,418,966,583,304,42,765,380,206,356,173,438,746,688,122,674,784,208,996,568,893,865,670,768,50,971,147,728,920,867,347,196,221,293,497,992,350,633,498,339,610,893,948,334,849,41,630,403,556,869,624,129,579,484,774,263,605,948,510,221,108,910,877,630,295,45,729,957,602,914,461,870,369,848,112,763,422,176,576,98,688,860,25,596,14,448,545,265,496,628,53,364,60,617,828,980,26,398,520,964,36,654,47,603,771,186,591,61,752,59,446,202,220,233,72,321,801,31,993,52,356,32,664,514,388,589,138,427,266,368,348,157,113,904,666,341,972,827,737,376,920,365,231,476,370,384,892,311,854,621,716,591,451,916,162,600,84,428,584,26,554,509,917,532,397,812,942,130,432,12,816,832,868,979,61,515,705,542,473,200,571,571,703,283,593,774,645,616,915,212,550,884,994,794,167,805,365,803,791,701,140,204,530,115,978,906,440,138,175,620,113,653,748,802,117,958,538,470,310,947,266,47,464,273,230,746,630,194,585,573,641,561,970,58,63,772,355,815,638,87,441,613,382,859,528,963,384,824,70,547,988,771,251,509,724,730,176,663,102,961,261,164,716,719,832,924,348,741,729,714,296,756,829,854,61,516,723,402,370,568,477,240,681,231,889,802,502,59,310,583,179,356,215,91,566,960,156,516,496,620,239,177,63,978,268,732,397,363,680,479,449,382,407,778,176,980,781,832,635,120,848,106,595,23,663,930,456,446,155,548,565,315,354,721,619,520,111,487,96,112,62,360,807,181,15,425,198,998,722,499,222,974,634,233,277,331,193,880,721,612,584,968,767,144,557,745,658,705,743,690,209,868,816,4,523,115,378,701,479,537,185,65,740,827,43,709,651,325,221,269,697,203,113,0,264,58,864,442,855,756,308,941,567,604,633,109,973,583,259,591,12,496,365,608,518,614,672,381,763,782,372,914,697,319,228,271,114,524,124,374,92,534,242,80,832,867,893,356,477,115,442,62,910,944,931,873,354,735,364,942,421,995,281,3,77,26,729,219,621,841,73,661,428,810,314,334,253,131,4,830,285,93,169,108,924,789,921,318,17,942,138,925,526,651,860,664,517,629,615,913,695,283,699,579,372,250,74,802,418,783,592,95,934,709,712,730,822,64,904,521,442,102,631,274,692,640,331,714,962,704,241,50,1000,362,481,831,646,813,689,73,722,874,936,478,342,694,454,593,208,399,239,355,96,677,293,523,946,943,600,145,195,418,70,205,888,142,332,867,868,250,914,825,664,550,463,161,610,804,669,619,287,297,185,313,10,684,441,791,874,481,859,372,874,494,450,622,602,930,328,761,161,870,546,820,435,887,756,489,337,481,351,269,919,109,757,178,991,370,335,144,6,996,557,392,339,404,382,57,452,529,23,793,301,260,72,852,463,466,163,627,15,264,412,928,606,31,235,243,630,425,872,68,588,561,518,898,53,966,530,640,368,194,538,628,804,402,204,549,970,273,960,864,892,851,676,876,701,281,615,564,811,104,904,425,873,10,451,59,741,766,954,64,496,630,195,198,651,435,592,383,277,508,168,733,490,747,734,106,702,786,407,675,763,166,554,21,14,713,218,392,590,858,440,513,134,311,344,556,193,180,921,82,795,316,352,72,238,949,400,714,180,745,429,338,317,890,303,4,826,112,69,463,570,682,203,648,165,649,286,397,255,792,424,841,320,531,81,7,98,492,92,359,894,829,222,772,398,439,92,673,601,47,179,509,825,370,168,604,366,664,315,685,756,171,260,993,501,93,717,211,578,389,119,362,344,575,612,991,658,900,880,623,928,800,981,908,201,44,848,292,722,985,491,276,950,859,359,369,635,8,428,756,427,623,412,97,418,486", + "951,630,505,578,269,20,663,612,756,829,72,651,875,313,510,458,674,823,201,132,591,386,891,108,249,793,165,415,386,574,349,82,504,436,994,699,646,259,852,236,164,918,164,140,483,610,19,672,827,964,986,293,887,179,117,463,228,348,1,592,434,985,297,728,995,153,125,50,17,557,575,222,393,804,369,497,567,278,525,857,440,759,812,667,594,542,221,389,178,418,673,884,614,978,841,909,613,839,914,808,413,430,37,654,515,181,522,447,834,13,828,274,507,465,743,7,504,529,670,107,403,304,446,873,549,209,582,501,272,249,653,145,990,860,887,731,510,830,267,334,322,580,276,200,126,405,334,341,169,743,720,283,966,922,943,582,190,155,619,306,650,459,119,404,404,365,656,462,307,902,88,778,865,878,296,248,706,665,165,226,932,232,840,849,595,524,50,735,762,796,66,600,599,516,408,439,737,157,631,115,627,475,316,237,386,316,229,696,206,423,595,554,234,511,963,893,789,505,786,712,749,207,786,316,271,316,454,208,563,484,270,139,985,302,308,685,789,78,512,490,233,717,968,160,708,724,342,622,13,177,544,125,101,398,286,440,411,354,856,207,251,815,158,538,319,310,893,654,893,470,308,586,68,896,312,51,919,97,790,567,557,297,39,652,686,900,797,140,508,120,500,484,854,928,159,136,883,226,97,519,625,746,93,214,157,913,726,67,6,753,913,613,282,757,483,665,782,765,620,113,175,973,922,843,210,718,187,441,349,458,894,814,344,531,453,396,419,766,526,645,600,787,711,709,658,795,101,513,887,274,256,272,864,134,720,315,24,883,927,499,923,941,176,371,956,752,221,992,573,393,508,842,10,499,607,952,422,481,116,167,427,568,855,784,47,245,449,695,816,380,602,414,863,255,827,190,943,432,233,402,37,618,359,558,644,357,705,125,96,686,299,673,531,679,170,69,261,961,451,127,209,780,617,91,242,340,599,132,210,835,486,251,232,718,862,984,474,997,701,299,396,209,56,580,268,594,592,798,398,734,352,337,135,242,979,180,565,555,717,205,876,669,887,256,263,848,704,485,952,650,147,562,553,872,34,340,33,605,148,594,419,760,736,345,703,80,15,547,776,16,247,382,299,961,716,257,372,324,82,617,594,630,747,877,455,449,882,430,400,117,727,171,943,710,682,130,627,496,567,242,752,103,442,986,3,704,470,901,110,522,789,830,633,72,770,918,452,297,614,95,49,484,816,609,210,442,850,85,983,261,528,656,68,189,598,707,364,238,94,596,70,967,443,883,972,264,0,93,76,850,220,96,750,521,393,618,268,500,39,335,943,656,71,703,362,806,858,212,848,573,602,248,105,987,630,528,124,693,693,24,566,148,425,314,775,606,233,425,926,516,62,301,883,945,456,73,536,707,240,470,254,160,926,703,825,122,581,792,425,798,102,227,387,157,941,332,154,526,978,836,355,600,151,893,744,621,628,460,670,562,248,34,965,550,529,69,724,164,252,244,288,345,866,655,957,741,85,945,815,334,603,887,839,375,489,628,580,280,949,437,733,353,411,783,467,506,73,487,886,204,802,462,382,833,912,697,144,838,444,47,212,245,760,760,760,38,444,401,676,936,285,444,610,387,830,930,301,116,753,120,40,463,308,57,341,726,266,283,55,804,639,580,898,693,544,526,579,99,849,61,285,923,634,340,6,182,612,716,184,114,175,795,29,396,671,621,380,795,134,214,128,498,877,686,122,680,691,402,251,536,640,183,667,176,754,511,921,793,523,765,11,580,372,205,405,112,511,126,262,377,430,440,289,208,662,581,746,950,59,438,807,544,21,120,240,55,185,178,815,515,977,856,934,796,773,113,818,540,939,103,364,389,912,210,18,976,600,885,862,644,633,691,208,546,436,653,931,766,362,125,841,318,529,37,662,696,514,606,327,40,847,454,79,320,777,307,421,256,907,422,569,335,310,223,770,322,309,852,687,168,453,439,298,908,589,407,721,605,34,356,983,772,342,211,206,619,738,950,191,236,709,288,438,48,714,199,751,381,75,389,670,99,94,368,667,235,933,318,802,519,376,249,850,863,112,914,768,325,783,266,684,694,907,679,688,107,228,395,923,365,109,850,780,821,488,450,146,967,996,806,185,89,413,274,673,9,615,244,859,752,87,500,575,497,141,793,762,507,508,326,903,13,601,291,633,821,824,316,543,541,325,936,677,121,678,68,202,800,132,507,973,824,765,470,61,77,772,415,595,29,947,825,374,339,531,456,108,76,287,13", + "117,460,533,97,858,569,150,600,957,125,20,104,996,990,380,602,411,908,110,468,157,128,652,228,949,838,14,601,817,896,230,616,718,932,702,267,742,629,167,380,580,152,560,405,175,427,950,185,481,731,947,641,64,611,393,574,793,968,777,964,225,602,81,726,390,556,138,201,525,443,271,453,69,127,961,704,186,345,99,375,798,273,915,422,788,715,834,55,39,596,798,509,822,688,838,125,991,311,294,712,164,970,163,902,436,554,215,828,497,802,889,787,710,75,553,626,52,233,985,557,377,707,316,963,640,235,796,689,211,730,838,601,764,96,753,641,8,366,342,843,429,465,810,57,758,298,305,314,588,814,186,548,292,84,848,729,540,809,94,139,38,236,404,587,756,402,610,89,913,183,320,615,611,608,622,939,100,264,246,186,238,816,984,121,271,365,326,139,685,708,76,434,631,655,608,337,981,483,485,136,699,745,654,800,202,663,960,437,172,259,678,357,635,74,541,921,313,881,782,767,469,873,22,209,278,205,675,490,101,313,966,226,258,18,909,866,841,234,791,575,223,189,954,37,632,565,191,813,674,59,97,284,743,416,547,784,150,820,866,680,64,414,10,686,518,275,308,676,568,641,545,940,581,526,419,774,438,530,24,68,873,160,907,408,926,998,450,208,671,875,362,213,832,410,250,82,177,599,334,461,150,329,591,420,569,370,858,866,814,848,989,111,401,424,811,368,96,894,802,333,332,508,612,278,794,472,193,760,239,655,98,809,740,766,448,975,949,445,579,778,833,106,932,395,945,725,752,54,781,887,121,51,902,525,333,216,876,894,4,86,694,144,639,158,898,180,804,167,268,744,533,484,857,673,20,498,618,865,930,992,11,503,259,169,418,19,16,529,166,26,73,667,455,15,782,279,12,22,973,636,102,438,469,871,639,728,899,490,365,667,692,256,667,445,121,728,341,563,402,215,43,839,289,57,324,907,585,597,72,981,373,941,588,796,777,437,650,505,75,677,658,791,269,368,71,285,148,306,818,547,19,822,745,949,934,352,45,938,546,35,14,616,962,295,304,386,297,171,556,701,449,88,632,51,30,168,183,744,58,126,68,512,472,707,972,516,136,52,178,88,941,484,218,679,419,952,270,246,92,668,162,560,322,578,364,871,444,613,204,175,983,564,259,492,280,265,637,516,824,674,690,970,889,247,530,222,594,419,480,143,361,459,754,200,188,782,922,233,276,437,337,651,882,973,3,292,93,772,247,880,64,458,680,989,458,43,501,704,681,825,153,978,55,544,954,58,93,0,55,698,856,36,443,109,404,864,991,13,327,212,854,535,823,21,115,504,842,415,396,827,202,413,342,532,777,339,167,166,975,272,175,964,416,599,824,206,886,244,681,899,408,401,427,984,555,796,525,648,488,635,365,14,747,427,61,106,160,180,168,736,388,30,370,303,759,830,888,551,833,655,82,744,87,588,225,74,482,341,302,447,460,799,756,277,236,59,504,129,556,392,798,11,310,278,352,634,865,282,475,476,558,26,240,699,150,769,259,205,262,755,281,622,860,823,563,24,846,902,28,107,216,987,947,186,164,762,501,448,456,772,44,709,633,854,951,776,283,566,654,257,775,49,246,671,489,543,361,4,124,725,806,489,814,668,7,457,954,879,428,730,539,909,117,315,945,329,768,690,844,658,84,66,688,356,738,558,442,865,908,527,33,594,534,269,519,477,35,315,203,15,66,963,574,583,93,319,495,102,832,845,562,577,867,866,721,268,139,776,491,61,136,444,372,820,596,622,735,50,138,445,683,567,629,863,45,462,308,155,106,48,180,740,357,243,449,737,969,156,594,28,491,110,267,370,168,943,965,471,444,529,416,453,380,462,75,17,83,469,382,376,176,445,273,851,274,41,610,992,707,85,44,126,344,58,762,549,847,333,280,130,571,464,244,717,907,667,162,866,353,384,669,102,39,210,494,490,621,795,95,501,456,231,377,319,742,8,831,922,544,976,934,157,187,247,272,418,874,568,642,836,448,425,295,453,995,549,152,192,807,185,691,235,294,267,888,499,533,936,273,927,945,682,795,704,966,537,78,705,570,886,522,982,117,232,508,509,683,732,674,838,146,236,706,622,919,355,78,146,218,725,349,876,788,877,151,740,935,13,722,940,841,42,216,671,173,319,278,382,68,576,509,273,389,274,87,93,785,264,615,125,80,43,877,235,259,54,962,178,547,224,612,181,818,633,52,927,163,357,552,145,795,337,4,300,770,816,813,806,142,629", + "464,511,884,905,28,828,13,322,821,549,631,462,189,157,658,340,169,547,299,710,445,163,412,498,436,862,198,118,209,259,946,61,392,323,441,596,320,757,859,892,92,955,476,273,944,635,172,586,319,251,272,390,57,565,858,967,756,767,442,861,875,870,760,548,36,769,593,948,911,175,312,209,913,875,125,905,947,380,69,506,226,222,376,449,135,146,737,782,811,337,858,456,376,965,62,166,525,598,624,404,678,265,612,903,991,966,304,912,137,87,337,35,746,152,969,207,66,562,744,391,681,146,970,458,730,778,869,16,152,734,806,353,748,570,775,925,933,36,164,557,714,870,39,505,645,661,301,591,738,564,154,435,649,888,240,553,289,635,707,453,978,758,174,775,272,573,703,284,412,558,498,168,697,672,517,643,123,301,118,525,289,539,900,375,602,833,935,268,17,670,110,504,8,459,395,183,391,30,960,257,294,480,381,685,362,920,184,8,646,510,101,973,17,664,4,841,751,123,558,460,433,606,706,399,549,193,595,609,291,449,152,836,760,948,383,894,429,549,473,580,122,293,305,232,883,679,927,151,194,966,850,690,933,228,286,833,873,949,72,95,418,327,308,196,811,334,394,608,775,240,493,457,164,619,673,53,404,917,233,46,711,35,646,455,683,996,842,743,249,215,700,576,580,570,661,282,255,234,443,892,230,129,972,620,930,120,119,283,682,325,468,2,652,374,313,740,92,332,708,702,56,270,721,463,445,39,761,125,846,509,336,302,109,938,192,437,3,103,291,946,97,86,793,645,351,854,909,231,923,439,986,910,181,446,682,762,663,822,719,777,702,311,323,122,598,265,457,129,256,994,472,167,876,843,164,181,191,317,135,399,373,235,523,613,679,675,310,346,503,781,806,111,669,551,227,49,4,909,201,181,611,871,359,189,13,927,663,503,925,834,625,972,870,443,199,606,568,834,204,672,41,539,317,957,677,830,221,841,385,826,989,844,246,338,755,293,241,218,616,386,843,194,783,154,623,23,929,571,454,512,1000,648,996,826,380,111,387,346,996,503,113,129,354,368,164,219,230,638,267,219,245,515,94,549,77,851,41,230,275,401,681,747,403,792,979,427,682,280,254,356,56,440,930,854,832,182,305,912,271,744,546,426,558,734,374,546,424,682,105,729,989,976,669,584,746,61,488,392,298,115,115,462,699,242,415,227,297,888,410,310,746,266,375,340,355,610,436,183,87,163,491,563,746,465,800,14,632,335,284,362,28,986,687,661,962,167,642,730,69,484,35,15,905,286,50,864,76,55,0,482,19,958,571,324,25,29,249,561,240,725,349,257,624,914,93,706,626,582,963,552,264,490,24,450,741,906,645,671,997,762,553,531,268,191,166,572,324,460,806,424,690,866,46,252,995,603,790,395,84,331,281,572,677,194,459,715,410,496,14,204,66,972,781,412,312,194,505,250,106,701,549,83,437,361,644,300,729,241,976,98,699,205,925,819,909,997,347,67,666,903,13,42,50,961,171,641,632,977,22,611,59,163,52,965,104,974,69,210,44,560,98,564,175,11,874,788,275,500,689,764,112,525,780,498,691,565,341,678,995,390,372,236,48,913,241,985,787,367,926,617,257,642,323,458,196,27,468,224,506,197,839,576,726,135,491,901,34,774,775,241,167,700,447,58,257,793,407,225,968,353,117,316,185,738,701,909,592,356,791,111,842,306,347,327,476,325,603,705,477,378,679,857,938,498,974,582,122,225,774,801,691,227,197,170,600,613,199,485,843,34,302,478,971,33,37,253,942,392,633,824,406,45,869,923,546,548,548,268,861,292,565,955,580,994,708,920,940,59,6,191,445,300,388,254,454,395,651,171,309,59,665,960,8,733,600,706,915,73,342,167,213,577,114,735,545,123,392,662,275,29,298,191,941,876,471,958,44,889,184,811,158,52,356,609,189,706,794,96,56,626,837,600,529,764,333,274,61,943,206,534,6,965,96,241,746,674,770,917,688,449,390,35,102,260,423,596,252,660,276,659,285,625,126,160,221,662,721,950,213,476,227,828,343,206,595,943,284,607,917,445,407,514,651,886,729,52,443,350,989,664,448,386,395,634,839,800,660,819,623,440,992,73,235,789,55,192,134,216,470,561,889,342,209,94,866,171,629,427,910,607,955,431,466,257,242,132,247,350,668,909,586,734,131,169,235,590,607,77,142,378,641,501,977,585,280,410,797,525,33,102,887,302,517,245,552,780,826,633,44,858,132,396,111,549,455,527,706,91,586,649", + "843,179,754,866,151,373,367,451,500,323,751,920,557,398,387,538,633,116,913,80,470,471,144,337,759,322,405,119,114,367,945,263,651,306,811,914,410,78,439,395,412,464,69,426,591,946,454,411,43,893,697,830,76,208,628,869,341,675,527,445,790,305,490,558,308,254,635,884,686,237,501,346,999,280,260,135,970,781,57,400,299,830,612,248,453,17,799,602,409,944,34,32,460,337,639,527,700,106,924,793,877,895,524,396,386,496,793,253,518,49,326,701,905,129,153,675,674,124,349,937,849,167,135,118,251,281,818,522,945,744,190,327,431,477,334,479,842,311,239,462,175,299,560,958,719,253,190,738,930,84,75,190,973,202,743,493,599,326,950,558,969,407,707,918,68,601,71,907,142,966,461,391,660,29,135,607,671,989,488,495,435,926,496,539,14,244,77,740,373,221,359,286,584,54,24,919,365,542,493,517,768,709,807,134,752,126,595,100,867,289,278,632,314,606,40,548,730,350,569,780,879,756,377,261,930,296,709,971,707,566,432,964,536,131,967,234,301,79,987,506,920,401,244,718,75,645,365,633,383,404,695,822,944,861,910,406,535,288,328,701,178,588,687,321,643,781,787,634,804,202,13,465,749,422,216,357,604,753,331,693,358,288,869,352,44,212,407,283,558,792,846,173,36,562,907,866,240,250,115,623,534,618,160,567,922,255,978,666,547,252,944,544,123,153,259,943,259,336,24,527,509,169,304,515,262,596,909,454,746,187,432,293,886,822,547,874,350,352,899,564,663,105,708,402,902,513,241,583,927,722,456,956,326,549,627,522,391,465,870,261,567,161,481,242,766,575,868,718,642,807,289,897,620,965,759,351,715,311,563,756,527,707,140,229,619,533,841,681,145,309,444,890,415,72,952,660,663,199,810,258,616,723,538,98,438,295,81,320,799,907,384,997,94,958,13,164,874,557,975,517,577,881,19,468,489,872,278,438,263,287,504,903,442,373,101,808,710,827,985,739,988,768,657,890,487,55,915,90,395,36,652,397,933,67,925,36,476,765,585,446,641,391,170,469,459,729,676,270,124,563,813,276,977,193,594,151,953,173,93,774,608,939,684,856,645,222,10,545,519,212,349,49,412,969,562,274,471,738,755,473,921,35,491,883,493,371,355,327,259,25,912,543,836,228,915,97,465,948,902,729,488,132,761,564,93,645,925,599,763,711,3,602,343,511,383,923,597,163,306,681,111,451,613,692,446,641,391,651,803,110,432,789,593,387,56,164,460,179,827,626,905,621,214,954,558,442,850,698,482,0,989,42,987,341,757,112,143,220,800,624,536,355,325,630,168,635,702,873,577,617,881,224,949,834,152,249,336,847,386,866,278,265,493,585,851,946,256,21,746,182,131,587,901,743,375,472,489,705,989,909,757,338,491,466,538,53,773,961,544,411,397,657,790,736,143,868,336,765,288,383,504,926,820,152,811,804,104,640,757,884,732,944,318,323,253,958,761,807,734,759,59,788,436,448,9,244,284,977,641,748,562,274,484,58,368,814,406,752,711,677,29,285,501,292,46,57,846,167,241,454,512,245,894,802,436,638,352,970,270,913,8,987,64,431,513,468,95,534,158,382,291,334,630,344,504,820,290,360,267,910,372,397,167,436,307,429,963,457,69,977,79,679,816,713,327,130,78,992,507,353,482,146,543,941,188,794,814,47,878,865,876,694,973,118,892,484,411,204,962,780,810,649,992,607,592,398,394,448,560,968,384,815,875,2,261,88,221,828,404,707,988,849,789,251,904,478,109,347,84,626,85,893,157,901,666,223,932,153,966,3,370,549,335,437,665,44,787,626,244,694,185,476,259,547,452,799,385,615,890,567,928,71,834,662,493,30,56,235,430,397,960,247,616,402,591,226,448,153,422,204,547,529,695,800,510,302,199,523,175,720,565,999,507,971,932,167,702,34,591,803,91,34,647,694,148,292,367,831,465,686,922,816,426,351,913,77,688,31,974,923,432,802,601,818,726,873,56,961,685,78,206,821,228,474,814,948,789,134,267,149,633,184,586,400,515,324,848,201,974,372,280,827,224,743,766,299,525,587,215,340,401,207,817,630,68,970,10,587,148,908,289,465,728,997,361,850,512,1000,704,31,902,189,497,951,598,292,878,288,605,294,551,581,738,491,583,981,94,287,988,217,902,726,574,765,748,537,503,557,525,221,989,790,281,273,600,398,210,631,601,261,230,726,647,124,278,80,206,184,403,956,836,53,807,661,701,861,957,515,579,769", + "96,419,968,443,504,843,747,321,192,190,43,821,149,678,774,551,900,922,395,408,648,525,371,609,498,454,968,470,104,527,874,498,838,117,71,227,70,873,736,785,187,108,121,337,765,521,831,661,561,671,125,161,201,303,363,640,83,667,334,806,192,846,953,97,24,125,436,477,386,899,827,288,261,495,953,429,38,239,370,522,736,495,684,224,317,373,328,73,329,584,244,713,668,806,511,75,868,267,681,504,644,152,309,948,716,126,709,628,117,928,806,707,678,733,648,164,735,209,628,340,826,48,779,122,497,852,912,249,402,271,322,132,129,898,68,815,793,645,403,127,871,831,923,133,473,452,175,582,83,473,895,989,953,963,68,994,893,919,839,930,963,114,451,506,325,957,988,572,236,741,523,412,754,410,226,767,188,532,417,279,754,922,994,315,963,338,229,30,184,993,274,96,38,414,845,434,788,140,498,215,323,579,262,55,936,936,759,235,698,64,216,813,107,810,177,953,720,139,923,903,102,125,456,276,438,505,722,204,19,394,287,254,263,398,317,478,863,119,91,195,373,447,145,206,659,689,170,710,506,319,153,10,381,596,418,623,200,32,862,868,527,926,345,936,526,5,985,433,43,430,171,378,802,531,467,426,208,506,178,916,627,74,220,452,285,808,28,403,266,962,693,271,256,10,780,350,435,114,234,727,955,871,761,869,681,278,828,70,862,942,30,886,747,528,225,276,343,592,75,750,474,774,396,864,900,933,859,672,647,166,208,236,440,264,858,913,450,750,221,514,901,466,445,413,190,991,992,706,182,137,526,646,486,944,51,642,992,922,690,933,110,759,376,892,74,968,814,763,940,305,966,895,227,107,625,119,685,867,363,143,147,631,911,1000,911,619,678,272,90,315,980,318,763,421,193,731,660,214,715,137,45,526,989,6,881,790,665,924,887,480,261,346,191,362,757,483,504,349,94,995,934,85,645,228,827,497,182,967,56,96,51,128,311,54,50,252,1000,751,985,711,319,99,794,789,683,824,382,577,824,24,891,19,4,874,796,738,376,96,836,180,534,628,80,585,927,803,872,44,728,825,636,861,906,776,413,123,446,121,118,212,313,820,995,778,225,986,686,911,522,190,443,561,928,374,927,241,713,833,113,11,125,903,468,605,276,606,123,9,103,675,362,357,378,579,669,839,18,366,535,489,444,133,993,789,816,67,410,871,167,360,876,164,927,653,871,506,445,302,614,451,820,824,656,726,965,298,882,198,895,76,959,247,454,178,716,469,498,760,642,349,464,73,198,764,584,855,220,856,19,989,0,449,969,248,763,642,153,981,88,784,257,296,426,362,193,49,952,113,935,509,535,950,811,530,432,62,120,948,702,943,471,878,956,576,399,984,231,366,952,269,226,248,653,802,738,977,325,532,990,183,321,444,38,225,508,191,246,608,99,73,296,325,373,996,598,39,111,401,441,289,249,837,466,457,386,430,569,360,792,383,829,406,308,735,846,539,836,466,964,361,297,977,614,432,829,570,377,22,363,73,814,32,728,720,338,264,176,439,61,253,931,469,462,585,685,623,152,47,843,804,96,989,680,427,668,189,545,256,329,737,35,105,724,140,39,385,550,927,10,428,554,457,32,325,294,301,954,282,199,103,963,79,484,7,237,492,560,720,976,737,416,149,325,679,900,7,177,141,274,13,779,721,878,331,99,788,10,845,943,955,986,466,801,751,776,322,164,421,44,426,55,841,462,543,640,827,687,238,386,684,796,155,489,69,356,463,12,29,638,953,359,251,672,950,925,188,888,14,248,610,712,228,922,459,47,68,575,507,307,716,725,80,434,834,681,781,714,162,469,314,606,499,934,842,673,673,713,681,623,367,48,263,556,310,450,863,981,758,515,637,474,936,595,649,543,9,652,829,416,211,109,714,153,357,32,932,574,515,727,973,256,824,710,15,374,616,60,986,202,616,699,560,96,379,297,816,339,652,784,621,556,702,8,617,275,924,262,82,659,674,998,710,47,44,916,598,839,60,428,470,75,155,662,477,536,36,959,806,183,29,601,610,164,250,671,566,649,414,305,948,90,78,473,825,724,860,83,511,448,515,773,691,704,598,764,728,960,388,855,563,656,411,420,246,854,140,70,52,577,926,794,509,921,787,794,889,462,501,686,663,472,860,261,529,677,676,491,490,532,285,316,99,705,494,624,832,156,660,684,123,200,78,171,962,544,751,384,22,741,564,890,306,469,333,408,979,88,954,110,719,781,73,391,661,732,339,113,897,670,60", + "359,826,998,885,236,870,765,604,755,433,417,839,112,602,581,351,320,556,645,313,505,559,340,561,687,516,908,559,750,423,999,640,406,771,596,977,555,97,234,622,562,32,756,661,301,363,487,408,835,283,863,517,303,644,413,370,427,468,106,951,457,423,522,798,258,842,503,847,557,95,935,208,677,4,32,117,609,336,956,218,675,455,504,820,509,231,752,74,496,159,486,574,937,385,303,261,602,773,81,209,598,519,756,13,483,77,794,547,133,638,485,765,97,815,4,24,455,142,428,398,864,733,104,939,208,425,803,10,102,266,406,529,929,439,245,94,533,222,669,206,392,412,153,447,201,90,17,565,82,195,477,104,220,608,77,703,441,21,362,657,329,515,156,344,751,505,400,143,447,36,588,683,646,776,567,294,698,678,754,984,964,449,536,395,759,370,698,526,875,867,338,886,541,96,28,630,103,656,796,354,194,57,390,135,679,634,957,907,368,431,990,207,770,942,791,234,132,56,665,164,343,182,388,820,477,205,570,895,83,315,528,766,113,200,917,65,889,887,217,283,874,6,31,710,735,127,621,294,82,814,541,263,310,409,346,498,220,270,959,79,727,950,859,304,634,566,43,181,184,904,758,804,310,722,249,450,25,644,995,145,405,183,452,641,243,458,709,471,972,794,52,128,935,953,285,95,903,863,8,523,392,696,843,209,793,935,973,381,308,576,253,256,981,587,939,745,676,748,204,500,34,515,930,402,664,378,198,958,839,885,965,675,591,598,43,605,865,222,150,744,230,817,287,665,882,436,14,651,985,972,653,105,977,646,350,282,768,86,166,996,551,189,83,687,755,693,343,190,76,270,800,332,44,172,404,123,699,33,341,332,438,71,415,36,687,665,858,936,276,695,518,793,113,625,449,875,726,839,299,312,222,99,720,890,638,639,179,433,682,794,946,159,838,181,729,452,385,550,27,813,261,887,801,660,16,954,546,806,233,636,743,635,716,771,579,526,470,726,636,904,550,592,384,309,142,389,762,266,859,547,748,591,112,596,752,530,26,820,729,443,980,834,12,166,94,692,720,6,866,467,859,450,101,964,299,391,246,734,551,834,644,522,419,917,509,622,781,877,550,159,727,93,559,544,71,967,386,908,33,459,502,424,74,517,546,141,737,550,799,790,838,202,589,613,262,587,156,293,325,21,410,199,501,543,278,152,651,135,213,441,455,991,431,260,519,463,743,221,857,626,828,580,628,220,64,599,760,424,512,558,771,445,93,895,972,350,394,68,455,254,424,180,425,382,635,756,96,36,958,42,449,0,699,220,948,15,75,559,919,334,974,823,813,746,556,709,428,906,829,869,420,184,342,137,621,881,206,214,160,995,433,891,443,963,898,373,111,230,685,234,823,635,583,777,793,964,974,954,707,984,193,346,424,409,479,522,275,205,129,873,706,149,591,184,573,921,119,864,382,249,410,107,758,834,953,800,293,592,969,38,24,922,939,132,419,793,789,804,953,381,961,661,926,191,536,462,522,662,388,348,187,125,873,138,982,453,334,600,944,990,802,851,24,871,598,903,145,365,729,200,637,256,11,4,667,957,808,930,392,969,582,853,671,825,120,879,450,973,474,753,253,128,524,760,290,309,64,848,519,361,77,125,151,568,907,450,442,428,795,497,572,729,628,969,42,315,52,362,373,577,22,38,89,66,362,159,93,769,291,272,349,825,554,958,602,591,197,181,46,348,776,440,876,156,293,776,273,454,236,73,181,323,472,359,994,549,375,864,866,872,649,896,310,525,941,633,741,733,197,868,959,553,853,979,139,946,778,713,199,730,756,51,582,561,370,701,54,439,229,576,843,557,26,910,184,976,216,79,241,865,546,580,697,706,374,729,817,254,114,714,537,899,622,729,346,837,565,562,434,108,910,201,966,690,252,116,985,864,128,860,978,814,917,862,623,505,212,542,640,290,860,706,393,136,894,803,289,984,114,852,679,184,971,341,421,618,112,305,630,927,877,428,740,599,412,452,535,552,253,183,709,89,640,898,619,716,563,697,233,38,355,532,866,957,40,795,686,606,168,508,870,478,705,926,977,606,149,555,446,322,328,916,115,7,282,153,257,991,401,903,461,745,756,511,802,908,370,855,149,373,251,647,771,262,293,337,30,535,204,595,668,981,361,779,783,502,383,831,340,726,832,967,790,584,715,967,40,144,24,79,71,994,768,424,189,231,963,799,700,712,498,991,785,439,162,778,199,311,246,549,250,231,695,495,362,534,568,354,345,159", + "945,155,994,11,19,284,810,201,582,957,60,926,359,814,252,450,953,811,329,768,820,730,384,604,749,90,921,500,810,781,22,987,764,400,95,995,689,37,936,200,509,60,53,551,737,873,146,93,672,241,889,319,488,461,654,273,172,215,361,880,896,771,614,34,690,62,318,886,730,601,144,688,991,869,581,684,467,192,952,841,715,884,419,1000,182,523,99,343,319,68,70,820,761,415,641,877,563,667,686,420,658,802,457,143,783,416,924,529,57,92,455,385,440,199,630,771,494,446,355,751,637,411,647,691,994,980,626,902,221,754,169,990,399,332,66,541,279,6,874,745,760,865,244,123,957,775,893,787,129,967,28,388,635,413,400,116,908,993,93,732,355,636,904,35,44,125,56,81,537,449,26,848,357,524,23,156,468,339,52,176,634,999,647,848,481,359,664,402,839,696,913,39,967,514,895,925,88,26,25,450,383,937,436,770,198,51,954,109,64,400,281,830,758,792,225,860,698,50,941,957,956,861,152,130,99,42,714,699,101,319,810,77,822,511,594,165,600,505,7,773,886,613,511,41,481,316,437,729,938,935,834,133,966,604,506,432,233,180,890,597,673,574,468,100,20,870,176,878,150,607,505,959,206,151,547,692,801,325,526,971,792,299,130,746,543,708,765,885,114,753,871,339,106,868,531,629,121,132,704,668,959,92,934,965,776,260,124,295,997,342,823,539,896,760,346,381,670,85,236,543,447,548,388,921,801,955,394,188,582,110,236,488,108,684,326,812,823,456,798,709,743,658,430,977,12,602,676,899,260,110,218,739,928,825,311,62,960,732,720,736,847,613,745,704,76,540,749,276,518,199,777,273,402,289,161,66,568,479,774,524,490,490,991,724,524,270,47,7,735,55,402,554,30,9,476,711,84,852,280,5,656,335,79,777,361,803,918,736,702,240,155,630,681,606,841,301,84,346,647,42,553,958,720,775,208,877,540,48,347,819,238,233,582,827,758,909,118,192,679,625,829,948,457,591,337,604,793,627,368,787,670,360,765,178,462,988,894,803,372,850,977,891,116,366,691,919,408,661,824,278,819,376,392,120,758,909,802,814,554,118,559,371,929,93,38,702,754,839,536,742,920,337,12,623,635,94,73,774,608,91,246,68,947,816,248,704,556,421,914,928,432,716,929,732,107,39,804,264,373,948,650,212,20,403,690,413,157,233,727,511,885,225,924,928,934,460,329,695,70,914,781,664,275,678,553,130,812,289,653,360,246,711,546,516,343,449,144,304,808,239,200,401,937,231,879,308,750,443,571,987,969,699,0,866,342,498,246,401,276,365,906,650,10,756,96,344,25,779,512,300,552,817,726,155,190,822,933,76,4,622,36,124,648,548,407,555,996,310,200,203,686,737,105,368,549,376,756,298,898,227,405,870,811,533,456,936,511,618,983,783,241,286,461,878,932,628,925,438,564,743,679,506,555,100,747,296,86,140,127,758,698,542,312,644,72,780,7,508,554,534,177,929,228,166,259,74,910,734,990,56,5,248,141,95,657,631,364,306,312,87,59,810,452,249,298,559,270,110,195,542,696,71,846,1,499,224,759,896,504,287,464,798,366,861,914,277,231,840,15,618,567,132,112,709,114,997,578,306,792,240,908,412,406,195,638,885,207,633,880,515,400,318,848,804,387,841,15,753,949,204,387,502,911,299,318,93,52,544,591,499,278,324,241,675,200,679,180,678,277,774,904,388,380,447,354,163,208,310,234,178,775,63,795,847,281,718,965,217,676,416,64,761,959,733,166,757,809,801,914,621,811,884,968,290,14,502,256,344,956,485,673,966,856,613,734,300,43,270,508,311,638,137,533,836,614,789,980,934,215,312,788,702,176,17,124,217,874,107,194,560,133,338,639,869,187,319,62,446,784,29,145,352,727,662,245,26,97,159,475,861,344,331,276,113,931,388,837,665,727,602,717,749,500,270,97,949,642,353,4,267,64,397,842,100,163,6,443,144,660,826,358,996,455,981,504,760,621,725,922,190,374,457,918,87,116,501,657,708,284,665,438,293,81,448,11,201,343,459,541,183,840,223,130,436,319,733,98,945,844,520,757,770,779,912,594,371,584,819,531,628,877,94,346,644,426,413,413,344,23,558,680,35,529,590,907,54,304,154,738,13,171,555,761,996,750,298,889,222,302,652,431,202,116,898,988,26,283,695,764,484,600,668,497,221,956,511,678,124,823,957,803,130,940,636,189,134,74,127,871,463,928,496,917,110,473,267,217,108,567,421", + "388,584,214,984,941,246,952,733,653,530,954,871,521,881,192,417,777,866,580,384,454,179,759,176,51,960,869,161,599,387,914,630,28,187,586,513,298,817,457,19,790,243,385,794,252,144,646,62,109,719,439,753,794,985,781,633,137,503,895,819,932,603,843,834,542,333,618,607,788,289,569,881,868,228,322,634,602,559,153,759,677,620,406,638,585,947,947,699,482,580,696,676,751,615,778,366,875,731,842,617,668,373,805,290,508,837,92,239,203,843,854,299,933,547,205,767,351,525,794,135,936,48,443,613,753,848,417,172,249,568,578,717,885,40,650,312,589,976,781,395,648,467,583,647,801,563,696,157,399,688,723,895,669,553,121,915,758,152,839,830,628,320,700,56,460,67,712,25,164,510,789,594,499,491,2,118,956,158,736,474,15,59,952,979,270,651,39,288,367,96,687,321,272,225,171,837,455,491,126,542,498,668,796,703,366,367,217,89,871,96,363,551,911,143,953,706,293,247,457,670,250,637,257,607,314,33,220,709,910,416,783,182,501,651,241,584,233,817,708,814,65,790,668,913,727,63,924,896,21,413,147,911,129,215,69,630,961,11,525,274,392,137,314,558,916,213,540,512,522,673,105,868,946,115,398,922,914,39,472,177,889,12,332,863,843,943,455,94,989,532,826,429,28,391,960,225,100,933,122,812,663,874,585,209,795,546,474,936,388,299,988,827,117,282,140,850,399,147,365,832,723,254,621,821,863,952,256,643,584,441,783,270,978,125,595,491,193,733,947,945,343,700,804,429,299,860,371,959,831,78,636,700,941,569,117,477,522,206,616,217,550,111,294,595,572,461,597,779,739,568,50,941,883,522,863,496,871,615,140,741,383,42,399,56,64,146,645,964,517,632,793,839,491,303,370,907,888,87,515,405,172,493,663,897,304,996,246,351,646,262,927,688,878,855,363,450,36,311,380,810,963,220,470,388,7,907,665,345,702,301,848,736,782,384,780,381,889,178,382,516,932,472,316,622,87,391,914,550,107,22,457,60,472,449,369,312,589,16,438,464,202,353,889,929,222,379,606,833,493,49,747,17,726,818,400,588,913,471,342,915,340,794,10,167,877,913,818,839,420,901,787,764,967,553,912,320,412,326,729,983,498,15,808,570,221,204,873,800,126,769,16,858,185,367,870,396,322,799,788,371,264,998,467,471,212,503,512,606,354,548,764,819,426,643,56,765,271,799,960,738,989,381,893,20,621,250,606,628,807,915,982,337,48,234,550,151,941,91,651,237,572,562,103,34,203,941,521,109,324,341,248,220,866,0,788,477,767,731,705,795,813,918,886,608,344,450,381,81,494,255,647,800,706,639,515,940,725,697,967,772,811,314,636,922,396,982,363,17,749,648,488,839,519,390,432,871,993,795,710,40,637,334,86,399,147,54,919,240,454,229,833,534,983,811,360,590,762,100,976,950,309,392,357,553,545,682,815,478,716,456,318,304,33,953,961,349,549,449,582,483,894,91,827,396,303,290,578,769,614,140,468,357,533,161,731,280,542,118,393,373,120,933,937,427,630,605,207,116,316,939,206,945,840,856,587,318,676,750,115,603,67,139,21,41,855,585,362,652,834,846,286,230,806,432,349,156,855,506,296,554,263,144,836,461,145,898,545,346,676,448,982,933,130,797,515,294,844,836,926,794,379,323,95,743,213,117,166,687,135,866,932,83,711,431,452,639,974,114,357,983,148,953,181,348,928,882,304,622,698,830,678,368,298,754,23,590,733,265,690,265,544,630,923,395,628,531,84,211,873,439,29,673,276,671,917,457,556,22,31,349,575,846,515,383,731,960,216,124,407,378,628,437,273,80,55,470,190,87,232,145,348,483,947,602,219,887,853,515,299,768,815,280,215,128,705,5,673,862,289,298,309,12,39,114,683,963,596,788,390,169,413,285,158,596,981,634,510,561,908,297,63,222,611,828,637,910,463,131,559,261,61,699,511,643,168,283,547,116,972,753,715,852,624,318,804,930,116,510,147,629,253,542,393,30,911,876,227,399,115,503,81,748,866,395,953,376,206,770,571,82,158,637,542,59,976,221,566,48,512,644,796,143,528,461,951,296,930,619,502,424,531,850,4,773,413,712,400,940,325,309,457,784,808,433,817,537,916,44,719,288,136,908,670,382,432,351,840,792,453,779,640,101,229,94,935,923,213,729,655,205,987,796,221,689,689,573,222,671,898,755,668,365,533,672,484,636,316,607,22,125,255,50,913,952,357,904,683,315,542,574", + "226,448,388,698,499,152,697,147,834,270,53,482,701,427,531,108,204,321,774,383,796,274,312,639,626,743,509,967,631,233,194,145,204,485,173,464,769,938,719,260,628,793,207,218,541,176,625,795,661,608,396,115,151,271,720,77,159,304,876,526,558,893,68,934,759,171,38,740,879,381,284,222,340,433,818,285,557,229,209,686,472,951,310,67,50,560,576,389,529,642,455,907,450,994,862,890,532,658,943,406,29,703,108,395,627,150,584,627,406,708,493,66,455,403,21,743,891,238,581,161,642,863,813,537,689,734,156,836,477,121,346,985,91,750,501,799,337,553,229,181,891,945,8,39,423,947,564,337,126,700,841,749,257,41,50,319,953,482,555,679,325,170,15,326,944,382,542,37,395,293,648,902,230,570,922,233,837,719,312,492,486,814,971,715,708,759,684,579,300,314,982,811,246,380,435,199,136,443,418,191,185,567,691,124,570,833,450,630,536,781,36,625,395,217,170,252,16,421,159,411,589,615,542,194,69,241,206,56,165,760,456,546,923,750,221,269,856,316,649,397,327,271,158,142,667,577,184,229,753,248,577,495,232,242,184,296,798,741,401,101,299,837,920,682,908,744,273,542,811,796,412,3,337,43,14,763,713,913,58,183,545,316,490,658,55,405,37,125,209,449,865,795,174,369,972,656,205,324,631,230,269,32,810,146,93,727,680,24,518,871,614,951,643,964,750,446,537,579,465,122,256,115,692,825,386,562,555,461,333,930,71,449,95,963,225,89,453,740,606,878,885,731,763,321,543,624,76,913,177,247,728,205,48,834,71,59,445,382,30,350,812,850,805,443,178,145,818,370,666,440,889,350,570,876,787,718,453,900,619,296,441,965,421,446,406,508,925,242,999,895,861,273,75,672,973,480,367,408,483,152,283,532,941,242,714,196,924,740,176,266,1000,486,644,252,375,146,927,334,44,620,840,283,987,994,199,2,748,202,689,949,725,428,838,517,448,275,782,958,640,860,672,906,636,361,388,4,52,991,439,887,946,436,592,826,179,315,445,584,64,320,895,459,952,859,464,722,759,711,187,473,353,468,246,403,39,823,669,924,628,404,354,577,18,916,528,391,670,972,671,232,559,589,834,686,615,722,172,640,325,25,3,578,410,627,256,17,481,558,159,462,224,645,723,703,327,995,25,716,928,21,821,871,410,603,743,176,427,646,486,743,231,309,586,568,795,371,961,511,353,378,350,534,151,618,316,171,5,164,505,739,6,226,810,230,461,650,549,493,41,188,795,449,804,576,157,567,393,404,25,757,763,948,342,788,0,993,216,449,73,831,90,26,240,398,879,766,761,835,6,100,362,89,456,81,293,576,640,619,503,125,248,674,596,436,607,39,869,256,456,470,284,139,321,412,550,296,38,265,770,657,299,934,170,931,375,842,581,310,439,433,961,829,448,496,399,395,480,200,678,630,86,434,949,350,582,723,395,68,973,12,603,868,80,1,496,693,334,130,572,489,805,140,483,948,23,712,220,45,44,662,191,763,221,613,520,617,406,333,226,268,132,81,575,597,58,554,780,30,738,673,278,870,976,125,24,158,650,129,686,35,687,709,628,728,270,318,742,463,791,568,189,416,274,450,532,553,715,107,566,530,283,519,979,7,299,171,126,425,861,485,239,214,327,617,385,665,902,391,429,720,52,517,230,161,209,649,768,574,608,146,404,236,460,156,392,650,896,625,69,702,526,198,836,82,388,984,954,889,888,187,812,546,789,948,229,716,781,389,911,827,282,673,803,980,524,875,494,502,259,707,605,735,794,261,270,283,229,268,304,477,53,198,61,706,307,17,191,135,170,103,934,505,858,778,366,280,520,996,211,94,57,733,427,862,658,748,610,441,354,826,480,654,910,660,248,275,898,728,507,670,18,964,830,675,555,955,122,579,446,882,68,828,289,522,434,35,32,725,815,52,27,532,851,523,119,423,164,493,64,17,807,567,321,19,448,373,462,903,494,43,354,316,777,937,807,22,88,78,502,281,334,173,573,21,889,278,394,929,969,950,235,125,116,877,387,215,402,363,563,39,546,716,405,7,727,943,567,496,820,799,733,253,282,910,42,726,604,982,176,793,904,546,972,190,595,354,841,981,157,810,245,556,616,534,318,548,313,560,936,864,797,463,69,255,238,784,299,342,142,471,919,957,921,787,607,88,340,114,961,205,105,474,780,708,61,225,689,147,566,659,862,866,692,936,899,296,799,576,407,215,522,59,698,545,834,256,339,416,849,95", + "338,16,509,613,760,87,811,459,552,933,106,172,214,237,838,863,382,130,987,360,277,196,415,268,564,797,33,259,394,260,503,162,364,762,47,540,237,718,515,970,716,608,830,658,226,939,869,16,344,497,699,675,483,684,494,966,308,996,101,150,250,252,416,787,461,455,421,869,325,289,389,467,690,368,23,849,346,175,588,359,340,656,709,6,223,693,332,326,503,925,258,553,908,867,662,718,858,613,88,848,673,484,877,141,621,110,956,14,481,257,655,480,215,202,531,668,425,301,61,161,559,438,624,668,103,323,734,874,659,896,343,730,789,417,382,111,540,229,729,136,627,664,463,116,567,856,420,615,665,17,907,961,764,234,194,916,511,259,487,782,378,365,223,270,95,981,785,432,818,527,518,68,95,359,597,580,537,30,735,970,786,356,410,490,657,696,795,836,661,904,250,832,445,909,10,555,796,627,910,517,575,268,392,715,800,340,809,562,837,866,339,820,179,613,836,132,63,752,443,80,3,465,801,169,376,208,875,645,224,226,943,323,581,948,951,444,187,955,134,159,712,221,384,408,854,60,512,21,168,297,234,311,138,44,447,725,813,319,865,100,46,967,749,571,907,57,108,867,174,645,579,251,555,29,896,355,618,776,612,23,372,56,914,943,654,452,785,317,869,680,402,64,595,202,125,659,7,358,686,738,511,660,472,620,340,602,63,217,427,528,56,489,242,689,356,99,24,946,728,626,66,900,335,7,416,966,622,5,647,724,588,802,950,756,758,178,947,415,813,222,963,459,805,899,30,444,486,395,925,555,383,113,84,345,893,240,185,622,109,493,749,602,613,640,274,475,929,424,765,952,1000,488,93,786,733,169,144,248,242,679,296,907,13,725,903,551,620,72,137,190,921,875,872,5,865,203,718,29,649,490,514,566,861,878,538,640,236,184,173,269,280,90,787,956,776,782,784,568,888,884,776,137,207,966,918,95,517,800,718,784,205,720,719,443,245,723,706,925,433,174,369,164,772,542,635,146,977,65,522,199,44,54,146,901,879,579,819,393,923,985,674,124,657,322,616,327,89,396,994,320,404,783,218,173,39,580,359,879,916,709,918,367,764,139,894,138,605,504,801,966,424,19,868,783,506,221,34,591,83,854,421,15,280,654,747,268,353,93,129,495,259,428,950,535,965,173,617,691,971,158,423,121,787,293,365,264,621,751,984,103,208,606,552,663,661,523,352,757,491,497,77,774,513,195,235,750,24,575,331,525,706,35,820,120,251,305,768,10,340,691,592,350,28,827,861,604,618,864,29,112,642,15,498,477,993,0,316,111,989,632,36,318,222,283,52,521,859,183,94,768,298,427,894,606,238,187,203,204,226,752,154,773,162,59,253,484,861,163,36,327,671,893,775,759,432,281,733,495,348,541,116,545,457,664,994,859,976,606,432,624,356,330,872,471,108,329,104,76,212,357,414,771,777,679,96,283,339,702,724,343,754,759,598,923,165,156,248,562,670,772,631,657,853,985,128,973,457,122,225,634,97,398,512,232,408,149,87,80,836,266,461,881,33,859,318,859,175,862,309,161,50,802,540,797,79,492,664,556,909,901,42,3,876,418,8,104,19,976,329,116,522,264,405,792,846,741,292,929,318,79,618,952,433,876,988,688,594,930,13,631,631,960,394,404,240,994,767,485,561,193,919,799,445,605,51,835,259,455,563,210,910,779,757,910,715,337,910,64,204,410,166,488,134,451,946,731,614,494,544,169,886,910,60,946,835,455,135,873,988,933,34,831,213,226,757,443,784,141,378,5,547,100,147,941,965,513,834,163,960,566,673,228,411,196,476,605,840,222,955,714,869,742,520,70,456,10,721,90,160,829,719,555,452,655,682,258,312,773,656,334,121,973,186,505,562,453,812,499,238,400,602,388,585,452,532,555,748,643,127,28,205,96,799,402,158,727,587,6,910,370,448,53,342,304,753,497,432,687,738,43,10,528,37,601,446,756,881,899,186,451,331,981,523,205,408,380,826,390,727,6,55,33,452,370,474,701,838,974,834,692,117,247,373,357,291,297,713,355,276,925,448,952,490,836,388,473,645,259,67,866,133,94,348,542,460,271,741,105,986,960,685,213,689,343,575,956,276,416,307,532,934,601,540,412,814,620,386,998,584,474,753,603,434,69,621,37,426,611,457,823,709,116,455,670,472,913,928,85,962,781,642,1000,778,976,238,349,341,875,901,274,613,373,799,947,702,644,307,608,818,207,541,159,688,833,139,747,634,472,954,550", + "41,82,980,689,963,106,909,106,272,601,133,571,503,741,762,226,478,867,96,536,332,531,921,583,236,841,793,34,774,727,808,811,614,900,945,274,703,840,208,841,276,162,533,973,442,11,909,794,307,244,999,186,416,477,432,540,280,6,78,539,893,596,286,890,719,282,988,441,701,465,555,741,727,460,898,56,962,281,283,370,684,331,292,117,955,595,672,575,375,545,444,716,361,526,253,794,423,509,552,958,418,585,478,44,734,538,816,708,663,655,784,323,431,381,17,977,847,477,69,56,79,802,552,841,5,411,860,613,415,435,340,189,162,756,584,825,660,962,572,552,446,577,425,547,852,367,468,933,274,258,197,490,404,838,987,541,597,390,930,512,115,765,457,367,119,91,102,876,552,148,279,392,850,258,523,870,927,357,802,334,752,316,25,96,766,851,322,118,894,636,441,453,769,706,176,834,784,840,453,182,225,680,961,824,171,828,419,787,542,563,938,354,389,493,578,539,283,199,86,496,236,539,483,22,715,706,409,813,302,402,194,976,19,60,225,565,129,905,649,582,255,461,880,998,320,267,374,950,553,909,685,552,749,746,32,570,496,535,712,276,351,77,522,363,208,294,55,849,979,610,857,583,303,388,308,655,26,728,470,895,294,542,861,2,313,126,754,739,48,150,728,358,697,414,568,906,203,998,581,137,993,512,248,839,310,544,338,919,866,306,792,470,857,522,479,15,32,966,189,795,111,48,627,832,162,48,364,476,681,838,316,745,476,770,732,278,916,532,566,980,728,340,627,977,91,430,142,58,824,128,236,8,847,534,278,894,840,332,975,562,337,711,338,38,744,826,855,965,2,875,300,828,453,561,858,427,227,893,637,564,397,552,158,258,896,24,812,865,333,353,115,919,772,812,17,349,126,816,927,261,201,716,712,736,535,569,33,52,907,34,760,765,784,236,66,753,5,369,55,441,774,555,738,723,766,707,814,237,639,814,817,268,956,67,366,986,932,233,283,33,600,640,222,301,606,644,278,696,741,120,486,793,541,609,429,866,700,831,4,801,526,876,638,581,135,904,32,112,140,608,843,664,957,809,332,727,223,230,132,461,937,86,201,736,696,213,547,158,564,717,460,347,790,692,246,989,182,414,544,291,440,37,674,813,721,351,585,322,51,829,537,339,292,271,440,635,317,756,569,328,5,587,639,475,136,897,5,550,75,587,107,795,177,916,616,393,983,438,763,499,96,979,167,941,220,577,177,269,926,580,32,755,663,176,978,349,368,993,347,444,344,457,828,839,995,633,268,991,249,143,153,75,246,767,216,316,0,390,770,182,857,251,337,839,823,1000,990,421,668,913,958,330,269,973,245,304,293,795,272,319,846,163,447,8,988,495,682,751,141,277,72,211,396,174,348,705,302,165,377,896,847,281,31,981,612,603,898,630,799,173,444,84,778,242,658,450,427,858,23,516,955,480,530,765,429,576,628,268,837,249,52,582,880,998,544,343,272,410,139,402,693,893,186,728,106,317,409,983,588,239,216,343,130,571,183,957,485,94,463,422,759,295,697,916,708,236,421,939,867,256,493,252,918,142,364,105,864,749,518,502,285,71,317,927,764,649,479,263,251,333,508,433,237,264,101,852,774,122,906,388,267,863,960,117,732,349,731,449,822,794,389,422,49,979,750,13,464,268,707,67,46,758,805,410,895,586,871,998,52,641,129,503,440,398,303,411,848,904,133,292,907,733,224,660,574,306,354,29,626,915,271,168,170,249,234,296,443,844,24,664,451,591,334,273,510,350,366,870,635,638,398,471,307,476,227,470,570,183,297,165,206,34,164,740,452,71,902,529,89,621,360,49,588,322,647,22,578,149,813,671,66,698,675,394,405,832,975,484,699,48,16,828,140,288,880,747,553,490,911,882,380,915,353,474,184,165,702,569,260,20,781,909,205,473,865,827,27,987,665,601,610,806,326,153,914,364,545,799,798,199,939,381,958,410,140,957,745,444,393,871,791,315,735,512,892,419,361,115,382,512,650,672,201,61,800,935,351,60,365,67,524,237,257,399,28,630,311,322,313,920,789,265,514,713,397,803,983,329,974,702,421,687,851,172,59,904,2,258,278,694,795,226,455,670,185,940,852,477,644,580,844,825,805,150,151,963,219,328,936,913,639,653,433,141,164,585,770,752,600,411,677,183,10,906,82,74,497,36,784,723,185,287,905,677,598,703,284,337,221,311,689,534,839,306,178,622,8,427,688,266,11,508,953,220,219,95,656,671,675,814", + "429,909,622,931,163,801,895,271,661,243,261,164,807,270,913,67,870,937,200,586,172,787,516,479,400,407,384,141,44,224,755,472,430,182,996,595,608,464,291,482,323,377,250,800,286,58,378,867,437,256,454,53,685,196,50,162,503,289,337,448,982,339,150,557,170,422,852,954,970,845,377,312,670,399,541,920,560,231,931,247,214,14,780,17,25,330,899,550,48,998,451,866,341,635,607,130,916,687,822,441,820,465,379,23,949,31,180,931,96,761,284,915,83,274,376,868,946,821,344,79,632,315,779,483,247,444,305,273,82,121,503,189,538,49,887,45,53,328,858,486,450,339,905,517,840,206,677,409,739,962,367,97,243,473,512,202,251,897,433,495,366,202,136,875,2,839,366,291,709,871,655,606,258,333,394,221,507,575,723,412,36,792,812,828,142,337,634,403,483,179,350,389,943,637,317,618,196,912,540,209,545,131,653,942,316,307,205,514,2,75,213,753,548,588,954,397,94,938,556,744,474,509,997,120,295,231,133,63,597,98,628,405,815,944,115,124,547,826,665,434,345,761,545,844,509,734,62,328,755,810,354,615,209,418,295,529,788,152,257,914,591,155,751,585,507,588,836,763,652,776,16,540,447,783,729,438,134,553,490,734,139,22,773,255,804,704,9,39,147,102,67,272,23,692,526,879,289,261,30,207,756,813,615,260,853,510,887,627,127,947,264,216,173,242,693,561,236,286,260,498,39,656,699,739,623,252,988,241,659,753,637,395,493,298,437,908,808,596,230,715,216,381,452,882,454,715,267,808,954,340,72,958,800,16,568,994,460,341,522,29,104,149,543,151,978,668,186,385,253,762,723,138,896,272,342,65,921,510,10,355,620,328,598,623,868,798,565,443,743,445,471,41,425,212,375,35,438,115,631,72,394,962,316,271,908,109,921,454,830,194,723,95,346,860,342,751,239,733,633,481,129,345,692,860,403,379,434,690,418,705,551,516,383,362,106,959,322,960,606,503,795,170,109,869,797,300,365,215,585,727,797,550,481,228,194,984,214,40,749,214,540,556,497,541,166,564,23,843,109,605,34,484,553,98,722,505,217,131,410,353,908,687,544,852,411,667,435,591,63,888,164,805,342,572,439,440,125,739,80,34,706,865,639,797,594,906,208,139,199,215,692,443,449,835,57,268,488,579,174,462,782,796,151,311,547,873,242,529,772,57,375,454,213,574,711,363,544,989,49,311,579,974,753,58,104,645,826,240,550,961,479,293,749,916,806,236,871,856,315,52,417,666,537,835,771,109,500,13,561,220,981,559,401,731,449,111,390,0,351,691,67,231,933,950,42,428,261,121,543,755,6,873,477,692,607,47,263,223,397,986,223,274,769,866,178,518,74,572,216,50,394,613,842,902,918,442,192,246,796,576,435,241,226,978,194,708,849,428,600,965,852,784,141,836,277,529,808,370,5,933,320,28,966,793,263,926,241,836,159,183,298,572,613,165,125,518,361,518,824,204,700,691,116,14,409,533,640,704,32,120,745,724,440,114,693,763,491,408,764,93,806,62,644,792,101,913,19,174,726,164,254,360,412,641,932,435,275,393,514,298,615,479,895,106,432,118,25,80,705,16,618,946,355,489,764,821,545,650,761,969,270,668,891,345,577,50,249,766,452,205,544,134,555,73,643,359,961,79,564,8,775,226,623,551,643,313,270,114,927,816,829,12,677,614,333,497,687,655,829,787,82,673,513,505,751,855,855,476,836,565,205,934,202,203,372,574,955,137,214,737,252,782,886,747,673,226,83,918,279,81,893,798,997,58,346,511,943,353,262,721,206,517,400,472,310,359,128,848,169,28,607,623,371,490,52,967,648,620,496,734,410,193,939,249,258,28,824,96,926,628,742,544,358,701,502,574,354,515,172,15,180,878,649,669,90,61,556,384,999,340,275,559,644,751,115,269,198,846,670,633,580,143,561,964,894,470,715,181,601,17,31,283,210,208,57,419,425,564,890,206,92,297,106,871,967,579,429,534,527,260,87,228,510,398,237,783,80,275,696,521,454,879,129,806,980,110,444,359,903,896,423,737,223,474,197,994,421,965,426,915,712,789,860,471,368,413,738,783,221,433,937,671,536,449,57,828,9,873,401,467,160,903,872,371,300,154,350,557,819,199,455,537,202,323,380,115,977,967,812,922,391,425,828,438,807,935,438,265,57,914,199,604,865,443,764,588,364,445,327,586,778,190,419,419,306,448,666,458,744,613,411,511,274,65,791,939,78,411,591,910", + "367,104,353,623,332,876,375,562,312,429,812,85,865,825,128,386,742,667,459,393,134,859,519,671,802,370,899,594,240,255,761,101,904,335,901,482,585,638,194,389,807,238,992,185,932,150,772,319,839,268,191,350,818,209,243,831,570,417,531,245,941,566,687,680,347,750,294,738,379,350,805,22,725,974,443,365,78,264,204,64,932,27,992,387,624,683,59,776,488,565,27,901,415,698,678,780,117,883,329,793,952,171,920,740,651,491,383,14,305,526,133,482,781,731,227,484,943,604,195,68,819,657,985,593,751,11,783,662,455,446,348,226,782,622,736,426,919,552,613,451,882,729,497,620,765,695,16,620,540,182,410,927,577,455,13,608,226,779,343,389,877,164,91,608,181,704,673,521,493,64,965,419,335,618,21,420,12,496,854,237,733,397,874,876,701,590,955,597,873,240,146,95,333,713,945,23,753,652,776,736,765,482,73,383,130,163,805,601,617,179,636,163,827,893,545,427,939,121,270,955,918,573,370,766,861,772,468,844,495,300,656,657,415,392,916,270,78,202,354,690,640,785,858,846,597,830,825,522,78,260,24,603,290,853,8,645,109,648,505,231,969,300,393,463,742,241,407,611,905,949,507,389,647,406,225,838,403,966,821,311,333,925,666,211,68,412,340,238,558,389,51,29,798,772,589,899,525,142,292,582,181,949,269,99,200,623,218,925,936,835,806,553,274,103,30,937,479,734,133,819,468,501,757,362,171,978,194,371,644,132,826,389,975,743,115,807,155,106,264,618,845,458,343,416,370,240,924,867,584,658,419,995,236,535,842,128,619,152,423,875,276,888,309,388,927,297,837,60,798,92,656,203,308,74,88,483,205,722,275,413,485,484,777,445,810,510,454,194,108,416,942,13,407,194,122,808,840,119,96,514,583,210,323,50,853,381,774,217,696,123,645,222,646,150,800,781,313,957,33,37,890,577,465,226,29,619,540,63,529,458,566,259,444,753,736,869,525,647,341,624,897,69,378,491,535,647,291,338,931,160,501,531,198,383,510,849,422,430,736,411,525,603,104,865,197,647,113,510,135,576,898,814,478,58,181,463,700,486,523,250,271,159,390,495,232,597,790,765,415,820,972,732,156,47,855,814,763,316,167,491,601,645,121,896,717,436,958,525,62,995,157,974,707,135,709,836,556,564,17,364,310,104,654,691,279,258,361,483,451,331,501,166,929,288,507,747,469,627,254,422,422,54,298,897,505,812,179,483,155,732,878,517,273,212,455,498,6,512,807,496,323,952,140,151,670,973,39,327,240,800,88,919,276,705,73,989,770,351,0,431,623,116,806,988,914,79,644,570,672,546,576,80,130,50,185,909,868,695,840,686,628,808,340,694,654,90,959,422,606,443,452,41,108,14,772,431,239,110,319,20,403,106,849,893,715,322,961,897,681,108,391,585,638,447,706,250,504,507,340,988,325,7,240,670,145,940,849,316,883,441,241,751,792,889,937,302,68,341,844,792,127,872,383,152,205,756,276,721,360,939,831,710,315,59,175,299,721,521,596,332,439,64,941,503,856,494,407,825,711,744,355,756,630,840,528,418,1000,823,945,161,942,528,710,565,283,223,428,21,682,417,194,385,938,136,885,103,482,681,481,792,676,10,43,598,170,172,271,922,660,28,396,723,198,192,371,931,987,453,754,354,783,956,359,771,898,578,576,669,767,948,416,982,385,313,909,105,12,799,213,573,374,891,314,990,40,481,563,430,206,962,139,26,197,301,781,526,613,309,761,924,33,430,252,832,36,49,913,906,478,961,602,711,606,378,813,62,630,14,415,688,897,745,698,54,737,179,971,752,946,784,913,236,3,588,116,155,250,87,992,657,197,853,828,344,986,619,786,638,995,406,997,918,432,864,224,380,190,589,301,849,602,749,184,212,26,700,250,332,258,508,297,744,471,537,148,120,24,688,873,221,524,534,123,826,517,299,618,226,664,308,23,661,627,657,817,636,519,660,57,14,711,848,498,37,385,886,897,453,606,496,348,983,291,348,778,575,749,431,534,579,704,869,788,494,142,862,139,915,160,740,565,664,777,803,346,132,167,662,229,21,632,587,434,275,539,732,707,613,525,154,350,151,700,861,553,860,924,876,941,257,425,920,521,271,392,178,104,3,458,880,392,984,711,153,876,128,51,825,652,329,673,408,372,414,865,426,558,667,239,287,865,323,857,151,606,597,406,963,583,565,392,284,818,512,56,404,465,171,207,660,844,750,108,635,558,469,299,127,453,383", + "940,608,233,390,910,249,608,518,470,208,379,333,752,790,642,654,907,311,665,51,905,307,705,203,577,468,810,903,351,422,543,365,895,468,560,685,923,666,666,767,270,957,478,105,425,564,806,682,61,661,686,648,380,149,752,567,30,526,255,669,47,348,719,12,253,274,864,801,740,603,331,754,294,8,505,463,536,838,689,687,237,898,28,712,500,345,411,94,41,289,715,297,929,446,361,841,447,457,786,616,400,674,187,769,202,799,600,707,957,970,268,811,426,773,283,455,845,924,700,289,400,6,264,639,291,661,111,38,48,283,672,666,350,876,432,417,58,955,235,900,244,101,572,718,564,638,918,553,979,198,184,656,960,414,524,310,448,168,958,516,532,359,627,700,321,736,270,142,450,931,243,705,268,635,47,113,602,406,84,834,191,830,471,80,764,944,230,9,121,144,683,343,658,499,2,663,910,630,393,683,705,487,837,957,358,297,730,920,403,936,377,285,400,623,728,576,204,188,213,446,616,96,679,964,665,989,381,493,993,97,853,127,999,909,94,327,49,29,909,864,782,380,803,355,909,512,949,758,816,70,900,544,385,670,824,473,739,33,909,994,102,398,723,572,588,601,21,936,284,685,663,876,399,812,802,54,370,697,860,868,12,853,142,459,172,650,254,423,221,331,522,900,560,642,297,665,731,724,709,993,698,117,602,367,149,942,480,607,18,623,677,652,167,514,82,830,922,497,133,574,578,180,811,201,856,170,792,412,598,532,141,937,443,618,844,788,949,831,988,442,84,542,898,666,311,308,902,55,605,320,911,418,211,785,773,928,248,430,365,65,303,447,421,586,600,17,826,186,400,904,307,785,398,78,621,782,994,21,700,317,636,530,475,189,574,626,64,610,684,541,178,91,188,97,870,868,405,22,380,116,41,527,231,736,75,37,748,160,997,98,593,277,593,790,182,284,717,420,591,746,131,383,600,498,83,189,229,527,311,236,644,648,990,806,768,904,883,741,469,107,182,133,1000,746,226,778,677,550,983,670,420,362,668,197,704,700,84,724,822,122,581,968,992,937,483,952,524,343,784,369,68,866,820,526,924,123,711,730,112,248,824,340,317,177,851,279,954,139,495,227,835,10,405,152,782,195,206,868,259,606,876,371,562,556,306,826,34,116,394,337,423,154,910,156,550,412,211,433,91,604,197,316,596,843,503,364,407,821,5,844,226,672,947,325,625,493,110,931,667,40,590,215,551,256,486,422,100,702,716,604,769,312,557,915,937,788,52,545,369,630,864,819,891,442,510,583,335,212,725,624,784,334,365,795,831,632,182,691,431,0,395,79,129,319,650,9,300,394,754,738,681,505,681,675,235,99,751,701,453,402,817,13,989,398,920,708,860,717,577,400,475,280,803,49,802,546,509,181,29,586,472,425,368,640,919,817,820,513,333,197,902,506,654,702,945,72,816,549,653,262,171,315,320,867,917,592,913,53,622,638,623,375,453,816,607,711,187,381,365,455,751,358,777,217,749,577,647,865,167,769,6,198,986,129,174,630,430,622,660,103,871,536,190,939,154,45,306,379,925,271,680,154,495,828,209,369,96,936,813,771,355,724,396,246,334,814,177,41,128,20,236,704,962,559,789,533,758,294,690,509,316,250,36,761,855,621,553,221,336,513,270,637,138,124,612,114,203,218,771,543,976,940,814,660,713,989,960,95,83,456,663,222,984,762,680,498,764,834,577,290,447,763,917,769,500,922,844,840,579,457,41,665,701,196,170,892,399,173,864,68,665,573,380,15,241,538,161,375,679,835,7,340,392,211,725,464,917,158,832,532,737,705,309,886,431,115,478,859,764,888,450,646,861,648,802,496,275,373,858,675,904,942,278,603,553,255,9,101,712,351,627,258,473,803,174,160,677,325,14,892,406,170,429,942,434,79,181,814,736,226,805,571,373,201,666,740,105,47,932,823,5,658,968,559,797,766,521,309,116,683,153,89,692,96,802,703,478,181,17,71,60,10,863,716,519,763,698,564,766,752,631,296,762,241,92,861,971,323,781,632,37,279,933,865,764,896,440,716,557,722,80,798,778,904,698,432,944,104,461,129,283,664,560,132,609,208,635,621,706,182,537,15,172,353,559,847,586,40,401,97,697,746,974,875,376,345,974,317,122,195,370,618,730,583,445,51,656,975,553,892,947,32,898,233,71,948,932,1000,534,280,167,982,677,390,548,895,529,701,723,553,668,547,239,198,60,290,938,98,437,956,968,396,841,423,262,984,678,354,964,294", + "474,900,496,532,877,802,664,443,488,877,808,983,386,74,36,78,84,218,526,65,896,357,294,764,910,9,238,379,380,655,384,688,795,811,496,697,899,772,236,576,624,7,210,592,570,31,807,266,618,462,109,583,487,127,426,67,32,923,679,111,738,712,361,773,590,218,311,417,401,856,254,949,413,893,534,712,355,128,484,726,383,484,197,833,700,488,443,149,591,503,33,945,503,197,59,644,1,924,750,319,434,350,320,632,337,335,133,592,162,16,951,674,821,912,670,975,549,719,488,899,722,243,17,231,602,613,929,950,217,833,64,440,799,991,81,515,455,282,31,451,241,429,599,580,389,633,889,648,584,276,17,830,807,492,741,669,102,107,412,442,607,839,339,45,711,856,836,554,903,296,641,554,205,825,390,472,374,839,5,324,226,717,599,475,379,807,421,131,774,211,920,452,864,555,55,337,1000,674,416,721,716,278,416,78,562,819,550,651,32,485,403,369,223,141,557,473,563,803,518,382,436,120,250,828,251,910,132,965,388,629,33,890,510,794,535,925,660,684,677,548,241,306,336,87,455,831,935,461,341,141,414,758,196,999,703,805,213,696,767,849,481,929,38,67,977,89,302,888,177,782,564,126,359,628,747,791,287,850,474,157,742,672,459,138,414,906,890,58,415,617,134,727,371,45,31,213,175,755,366,241,286,532,905,371,263,569,247,120,477,862,559,190,392,989,49,85,471,576,411,611,964,815,920,651,812,327,348,892,178,634,287,126,612,129,510,493,79,107,760,347,430,522,480,941,921,804,355,787,151,664,688,534,139,153,715,8,96,548,34,810,300,519,475,726,379,527,398,718,461,371,103,629,533,336,141,487,82,16,405,505,2,653,977,591,971,677,659,936,568,45,3,929,391,248,472,233,155,155,953,200,551,758,652,877,140,279,509,914,393,413,593,724,107,225,219,635,145,395,888,581,98,183,141,500,980,851,431,477,176,834,8,57,184,58,726,215,396,50,636,832,230,464,859,260,839,290,457,145,186,965,536,649,668,589,100,201,797,272,532,537,475,690,550,157,911,863,868,808,854,918,847,534,302,798,465,495,43,672,383,336,334,659,502,563,920,409,878,148,284,884,220,46,601,717,443,712,448,482,716,918,120,699,350,553,788,651,707,220,355,206,416,832,478,771,359,738,393,724,434,858,677,506,45,226,744,24,284,731,307,588,739,321,62,86,252,436,481,827,777,829,327,774,705,773,461,866,270,381,849,648,851,597,245,599,734,729,500,884,987,623,418,878,658,768,171,259,943,854,349,536,257,974,906,813,90,36,857,67,623,395,0,704,460,505,879,951,65,839,560,276,175,872,717,59,585,146,992,265,817,632,436,22,960,482,977,53,391,567,689,401,136,581,743,914,745,153,928,875,177,250,617,724,95,947,170,824,776,115,689,174,534,221,725,834,922,454,702,31,164,70,56,513,730,67,559,367,658,826,717,899,109,87,580,274,330,289,834,608,832,141,541,558,12,222,996,189,211,395,222,631,81,302,93,477,133,84,4,313,862,442,957,994,24,645,28,488,129,880,197,804,946,382,392,959,413,897,706,661,25,917,83,354,77,534,115,633,754,420,661,671,306,362,116,793,177,170,178,922,925,369,894,158,605,188,32,967,823,471,153,658,646,364,426,220,47,583,431,376,538,363,987,330,487,541,473,191,157,132,428,68,28,170,829,349,312,817,179,182,766,718,684,487,472,506,504,963,121,438,820,472,935,48,450,484,932,849,900,878,343,91,700,916,218,370,927,521,104,504,872,233,954,552,375,96,312,489,407,733,176,482,275,157,533,330,381,71,279,581,564,370,222,602,655,548,78,361,482,479,628,293,245,146,140,672,931,971,787,147,275,864,374,489,151,792,581,674,299,335,678,95,257,800,313,27,302,706,415,379,406,757,47,285,508,795,475,623,685,124,172,381,509,450,889,670,857,603,732,899,669,357,400,682,511,411,212,984,674,267,161,994,650,242,571,605,904,338,209,865,875,151,741,865,942,502,123,581,809,34,127,370,310,36,293,353,537,789,647,116,609,236,679,224,583,688,681,697,537,545,658,987,890,746,473,633,734,207,495,412,583,257,372,751,143,650,917,138,748,351,809,550,283,481,839,523,32,937,34,951,528,347,574,475,535,961,972,706,978,624,284,271,319,380,522,871,723,561,986,313,530,770,821,480,869,222,775,865,833,279,377,172,521,555,619,659,284,598,978,957,478,150,243,880,681,90,531,20,155,106,705,405", + "477,971,178,752,116,529,496,953,109,786,600,343,397,222,61,181,154,88,639,280,906,164,935,883,762,176,77,529,493,126,530,931,753,991,682,873,282,299,800,318,547,986,947,708,575,717,815,181,739,639,998,194,794,353,801,679,812,665,67,490,512,518,746,489,79,130,624,604,507,543,136,434,921,598,458,285,826,818,723,108,570,523,613,254,824,942,104,829,516,202,397,642,994,743,190,469,676,707,141,343,272,798,909,381,299,373,388,998,142,664,46,493,136,475,933,523,21,288,18,494,733,430,831,335,493,411,652,168,531,599,296,850,463,231,633,567,795,136,606,358,989,723,802,20,186,992,618,867,110,342,527,204,511,619,703,93,780,711,186,932,366,216,163,947,253,870,787,254,211,280,537,279,331,477,54,424,636,808,112,609,722,969,559,102,81,39,243,698,655,21,627,713,586,519,810,967,566,674,738,199,516,639,83,687,154,270,539,51,851,453,749,539,928,130,676,562,817,775,836,765,97,580,663,517,811,524,507,908,266,908,998,711,272,996,278,124,233,868,474,594,17,231,660,309,246,860,965,609,123,635,639,437,439,426,774,191,775,807,555,532,40,6,167,236,710,928,666,723,960,136,602,137,165,79,281,715,706,421,174,523,491,907,158,384,753,337,412,777,236,765,207,56,247,869,946,471,196,373,727,999,749,65,249,697,402,462,391,128,818,230,812,396,142,109,625,574,811,85,479,639,369,313,766,794,36,946,326,654,401,627,275,410,389,690,592,92,845,356,148,817,75,970,981,259,527,766,804,598,833,308,970,235,22,967,515,404,43,206,657,391,198,517,189,228,578,739,101,922,857,539,443,223,348,772,637,792,726,209,669,464,681,333,440,798,745,173,122,407,779,51,805,616,160,914,499,354,651,403,522,871,697,39,41,63,791,70,817,164,542,935,33,732,545,210,753,910,773,701,195,366,396,265,907,3,431,229,266,844,822,503,840,558,348,857,463,561,111,466,570,365,554,642,311,825,3,909,6,933,785,324,359,344,316,914,103,534,820,387,720,67,82,148,448,491,295,614,912,197,869,251,798,318,200,799,175,599,477,346,357,416,14,276,356,4,881,794,921,115,255,507,19,756,265,717,843,229,761,806,566,198,900,27,587,999,200,739,995,883,262,794,59,237,956,530,885,119,523,545,171,532,808,291,217,81,248,10,556,736,342,799,455,632,203,591,980,50,801,280,279,510,81,824,477,788,941,549,728,863,9,834,669,634,532,684,63,913,650,800,519,69,864,418,513,934,17,591,656,535,257,355,296,823,650,918,26,318,251,231,116,79,704,0,707,971,80,873,775,450,140,605,922,690,149,265,683,915,885,46,929,420,776,780,735,103,264,475,199,82,14,541,458,920,880,604,910,563,885,462,369,679,519,707,552,586,552,896,855,220,569,655,616,745,126,845,266,592,478,560,580,145,835,177,603,125,424,521,583,290,932,329,745,984,923,352,637,764,294,479,400,368,813,23,154,9,491,752,37,232,816,742,728,391,732,691,81,715,885,947,59,565,810,96,230,386,583,452,887,998,976,635,311,116,657,779,510,290,241,907,336,926,580,632,396,23,612,18,124,190,353,663,233,788,16,996,36,740,267,534,488,211,218,668,125,207,56,764,164,398,657,981,411,777,204,901,636,744,862,974,494,912,635,509,587,508,990,755,625,663,743,659,648,955,210,972,934,207,607,364,374,675,794,256,600,909,927,52,610,445,711,417,209,9,834,35,409,887,39,76,705,806,233,720,318,948,143,734,594,889,51,176,875,941,744,189,516,238,61,486,561,324,881,329,153,620,534,10,768,643,303,31,544,938,108,201,574,82,504,542,609,3,594,880,868,422,103,721,140,898,219,736,505,167,423,581,590,86,298,41,585,94,297,79,412,714,469,317,440,663,681,356,919,912,124,694,897,292,483,843,784,451,942,1,33,496,658,491,4,188,189,612,434,232,280,337,84,593,395,132,782,786,452,944,163,601,90,774,154,787,73,243,268,115,819,413,145,195,884,369,272,170,172,713,296,179,895,901,420,500,540,450,268,212,393,599,780,539,721,236,196,692,803,703,273,388,294,853,888,909,352,772,667,719,240,413,927,968,112,120,274,532,310,380,203,236,845,988,944,804,881,375,547,280,331,283,821,229,432,467,385,569,101,199,802,35,647,841,228,530,700,470,450,850,289,187,558,532,445,457,882,982,802,529,876,321,384,815,766,166,818,663,42,439,596,89,601,426,943,777,701,556", + "978,763,988,456,41,722,128,990,516,323,452,591,293,12,494,231,436,18,101,341,747,406,486,690,318,160,612,277,806,666,247,91,956,825,853,89,924,650,656,396,419,286,516,625,188,480,923,931,215,846,403,180,12,176,624,167,253,181,107,925,300,842,23,878,349,170,724,202,974,809,501,684,576,824,78,866,655,147,383,837,767,291,300,794,801,289,299,949,778,589,698,882,391,566,387,572,822,835,759,789,430,892,812,634,83,769,77,202,957,740,715,212,649,122,510,305,82,873,104,665,612,556,318,796,477,926,844,942,962,448,818,439,163,367,9,61,12,24,769,413,192,169,961,484,517,588,238,491,552,219,660,854,883,793,285,856,811,28,521,236,248,239,523,739,618,271,160,515,788,601,153,739,35,472,802,782,619,274,650,158,922,482,344,432,39,470,248,193,902,937,111,434,346,862,858,645,81,724,106,577,703,62,289,728,7,423,241,801,935,288,462,451,997,25,780,757,749,31,718,106,76,618,554,725,493,416,406,642,780,211,127,173,375,16,852,388,782,439,756,465,152,777,127,922,781,146,286,615,451,105,166,131,306,93,990,132,611,233,403,389,619,929,472,637,953,987,65,917,956,971,443,282,447,507,123,207,805,232,606,157,96,244,139,188,342,302,617,808,418,424,895,623,662,114,982,442,173,680,771,128,759,501,744,291,564,350,643,67,795,136,261,84,89,74,818,484,662,424,516,517,375,149,127,20,864,77,750,931,428,135,651,110,922,358,33,854,861,370,934,314,136,829,267,931,602,612,538,496,549,511,731,267,411,531,996,309,926,705,1,74,24,520,839,108,440,474,627,47,870,574,273,91,861,633,7,526,804,413,66,335,387,409,886,118,920,291,142,182,104,221,322,247,642,801,776,408,784,173,234,269,841,741,396,511,753,732,908,24,149,187,496,959,14,862,122,112,182,288,272,142,99,746,126,636,109,55,26,564,955,545,904,723,909,585,729,507,580,870,282,114,754,666,491,532,250,832,491,832,586,235,93,75,968,205,613,505,766,278,598,84,341,862,583,16,230,431,317,461,257,279,56,13,411,564,83,992,59,362,22,830,730,465,772,386,174,75,995,945,987,708,702,691,746,94,504,720,861,707,431,20,414,754,947,326,275,290,437,623,89,392,115,952,786,829,528,240,35,491,326,430,465,944,736,846,120,390,393,450,106,322,233,605,957,706,613,948,893,264,644,168,740,477,133,117,709,300,938,323,533,123,502,859,222,491,799,162,721,266,69,260,409,658,628,818,387,12,71,823,624,325,426,813,10,886,240,222,337,933,806,129,460,707,0,905,769,974,74,522,802,38,775,984,801,925,775,544,443,174,66,782,591,495,681,389,59,388,654,468,178,262,809,192,556,76,457,661,197,999,814,577,690,652,90,976,839,427,851,707,3,355,723,901,720,376,999,486,919,63,429,274,301,420,831,714,122,112,769,439,656,89,476,323,68,89,385,792,744,655,790,172,196,945,696,343,957,978,100,437,942,681,426,396,464,319,418,598,848,562,24,110,779,558,723,422,257,218,378,726,171,179,793,693,273,616,578,231,407,789,238,533,829,37,489,822,988,885,26,113,444,378,456,155,257,756,827,884,47,407,927,848,44,276,466,914,161,533,89,210,717,864,13,534,231,667,908,332,307,868,247,571,206,551,532,609,666,289,296,23,226,211,762,704,261,455,327,50,923,858,332,238,837,536,727,557,481,132,634,308,510,881,534,304,782,215,868,298,119,766,692,35,507,186,635,909,40,988,45,924,729,991,9,782,201,964,866,416,298,909,967,967,936,874,929,891,442,214,176,570,535,357,19,938,758,975,403,874,609,131,832,69,243,372,155,373,141,272,379,101,693,59,388,760,879,589,770,624,190,590,389,502,721,470,58,458,971,92,510,393,19,477,903,761,441,605,265,295,841,386,607,628,487,419,287,702,980,997,513,140,592,811,764,279,97,839,860,759,403,917,178,467,102,614,991,649,273,237,485,723,801,236,729,676,847,491,962,286,299,874,105,533,315,580,26,843,690,906,648,434,188,199,252,933,856,824,1000,287,823,912,482,149,544,611,612,745,333,145,694,320,915,366,85,392,337,5,503,739,377,966,919,616,494,386,184,581,844,1000,524,225,114,524,752,846,638,878,940,170,550,673,385,364,159,613,909,66,88,646,277,567,282,562,400,89,53,564,8,509,713,535,112,257,788,798,2,112,931,196,409,949,672,575,95,654,373,257,186,581,575,992,427,329", + "867,98,344,497,128,154,100,485,770,11,899,287,268,29,38,587,516,880,935,691,130,964,733,606,115,568,223,407,897,465,225,195,643,438,622,742,853,349,440,421,361,862,808,201,493,300,903,752,792,112,618,307,377,618,641,965,341,160,27,52,745,759,967,384,783,900,281,758,366,751,441,525,123,514,323,601,66,670,753,438,739,170,432,872,889,587,17,173,628,853,108,245,196,382,120,207,896,343,974,287,98,846,210,789,816,518,398,893,973,861,848,54,600,168,591,735,840,959,241,611,716,644,283,816,586,147,922,329,403,273,340,996,298,513,422,386,753,520,809,695,617,121,317,492,11,706,484,679,826,770,715,165,333,290,245,466,343,248,434,473,157,593,67,563,237,611,190,21,56,913,935,515,764,75,507,384,839,560,905,195,540,48,741,900,348,791,196,86,450,563,390,588,226,604,349,243,723,363,100,160,790,187,481,75,50,450,318,709,407,641,928,163,894,626,15,204,375,937,477,74,771,937,5,919,532,674,966,89,223,688,667,159,140,121,763,105,388,436,856,382,663,456,786,899,950,47,596,590,618,667,648,206,138,221,6,94,134,492,514,425,780,560,248,34,959,781,513,379,185,639,607,576,672,655,336,256,282,863,976,715,365,434,327,474,384,460,442,6,579,352,612,439,612,977,211,87,152,844,175,245,438,75,342,197,779,442,538,431,233,172,990,712,556,591,652,906,5,589,332,508,117,503,415,352,710,323,642,543,277,524,378,117,58,834,791,20,858,326,368,528,325,740,412,244,153,672,212,158,213,793,368,201,946,767,813,661,625,998,820,282,340,769,500,440,32,341,373,192,755,250,27,15,944,941,864,114,321,898,776,683,401,260,459,418,162,654,495,223,425,71,735,444,92,776,616,867,75,232,99,120,163,985,389,649,117,44,726,121,115,992,468,362,382,171,803,266,474,959,870,537,953,233,206,426,240,321,896,285,202,355,236,785,851,951,881,976,484,232,350,811,914,635,518,584,398,255,488,974,190,302,88,631,59,955,928,482,435,806,394,580,856,878,392,205,204,576,464,559,203,269,636,701,377,842,704,534,333,576,601,695,477,886,27,506,511,509,58,784,116,322,533,328,474,356,99,738,459,525,427,282,660,65,736,76,825,609,982,474,581,623,481,761,553,956,166,270,431,364,817,539,389,310,50,122,902,393,797,926,646,932,94,719,713,876,36,972,371,459,243,466,943,258,429,751,584,401,157,177,456,690,446,11,857,847,330,232,207,111,140,750,69,48,270,905,921,496,703,21,914,630,362,746,756,608,398,283,839,950,988,319,505,971,905,0,832,633,583,515,310,323,29,610,424,912,268,793,567,240,904,905,200,273,745,866,969,137,203,715,300,672,108,799,567,770,856,68,80,931,915,570,280,100,16,664,663,241,154,644,480,411,185,163,843,185,518,582,113,680,946,913,330,739,389,504,484,870,748,436,696,96,481,440,433,919,493,462,658,650,169,495,351,919,442,92,248,488,285,746,728,840,896,203,207,490,298,48,172,3,951,632,893,701,213,723,889,219,503,679,171,875,883,575,370,420,891,130,949,75,547,24,571,423,387,557,169,101,747,89,770,563,797,128,489,38,425,264,535,172,122,226,786,625,570,144,562,156,928,453,702,544,70,627,373,783,998,528,442,902,516,471,652,54,921,328,499,385,805,391,123,411,595,522,421,811,611,785,975,158,127,860,514,180,404,368,418,282,293,831,538,426,405,784,812,976,218,416,905,657,235,536,648,635,157,740,33,978,364,269,969,909,558,312,741,825,152,173,744,892,858,393,259,734,237,88,86,834,671,526,155,276,560,703,605,361,606,309,467,197,673,806,223,803,143,503,26,837,335,463,804,106,783,116,12,59,276,326,468,376,928,530,350,729,766,733,792,218,743,631,472,520,969,448,396,53,499,901,390,795,606,969,124,458,220,986,384,51,161,576,408,690,414,812,127,307,153,554,835,891,823,499,241,671,209,273,863,843,32,827,629,48,58,787,7,749,638,96,546,245,939,886,246,281,962,7,894,206,913,668,691,426,935,884,885,566,985,646,722,660,760,784,424,119,269,230,956,991,498,86,116,804,139,640,419,590,992,67,892,179,357,619,569,853,972,116,852,955,472,616,120,237,832,106,751,982,834,878,494,519,836,974,323,165,610,325,932,984,806,941,338,114,153,207,278,220,32,295,580,689,853,81,234,141,751,337,68,621,6,711,22,694,745,744,244,442,80,745,882,495,46,983", + "975,464,445,438,146,263,210,380,281,234,75,3,339,505,176,892,229,154,891,733,141,408,268,247,786,809,176,604,197,617,685,442,393,554,672,490,677,282,535,31,498,280,392,198,112,58,511,398,836,337,511,283,436,710,521,942,24,411,135,65,684,11,86,614,249,989,310,215,843,748,903,258,611,608,659,618,288,307,558,810,800,131,76,345,826,380,336,648,571,669,734,303,11,789,907,467,966,625,925,542,649,241,794,917,881,152,852,342,780,96,499,278,966,954,168,516,910,426,833,474,274,285,169,367,822,987,46,340,650,375,961,868,262,58,626,259,634,215,125,621,988,624,580,439,550,669,862,814,103,44,166,489,623,521,260,188,515,495,446,435,999,956,674,683,519,533,118,388,499,964,151,916,963,505,584,393,663,639,674,328,350,906,640,224,155,528,257,479,938,934,853,352,74,196,378,533,280,415,745,59,139,852,191,335,439,833,292,768,804,201,219,224,932,494,413,605,610,512,258,648,386,694,993,752,260,659,38,651,543,137,65,8,769,577,420,695,979,807,511,177,957,887,591,87,182,439,344,571,906,1,400,172,840,613,211,818,283,151,624,601,237,128,309,901,434,203,90,799,592,333,837,778,988,289,358,79,43,203,322,944,632,835,27,887,818,146,483,875,47,905,913,141,672,49,211,393,232,974,155,80,641,42,264,219,321,162,402,230,951,718,687,973,596,365,70,130,767,716,699,361,152,32,919,609,151,105,22,897,966,751,709,823,868,616,537,606,253,616,306,301,858,231,38,276,363,963,35,480,3,200,375,829,732,964,960,718,643,436,458,82,790,343,639,969,355,318,9,776,608,251,863,712,53,13,924,477,409,943,486,558,241,855,199,56,226,623,597,309,219,873,451,487,960,788,742,413,473,289,878,919,443,608,639,504,450,612,701,351,438,262,934,630,930,709,575,732,90,154,210,12,823,709,444,112,345,879,49,135,112,409,411,276,540,478,280,364,397,294,401,815,152,580,373,166,332,424,826,270,857,895,248,424,835,166,518,678,287,36,273,761,106,443,150,770,13,321,94,500,561,248,664,12,901,894,206,185,909,982,913,30,694,827,844,502,671,959,621,618,531,216,540,31,967,219,463,725,7,317,983,255,812,731,299,20,832,237,543,100,725,220,916,158,8,588,852,104,65,308,427,554,352,667,608,452,492,391,882,914,5,825,557,344,964,189,741,372,729,152,517,302,530,73,20,695,216,407,835,315,505,689,157,235,647,931,916,126,258,688,21,649,722,433,522,89,551,365,362,115,93,168,193,556,96,344,879,52,823,42,914,650,879,80,769,832,0,450,871,728,826,792,59,209,864,650,846,515,346,946,378,511,883,816,922,847,992,338,793,418,443,187,12,202,791,510,388,28,845,239,161,98,215,825,817,848,512,252,933,294,120,707,605,659,94,921,318,156,963,12,16,387,126,637,569,542,477,511,570,604,624,207,230,280,673,660,294,40,647,739,625,328,488,58,583,793,132,375,625,656,742,41,421,940,497,774,523,108,862,686,363,857,972,736,361,103,298,210,654,720,585,581,382,388,782,756,470,595,202,592,100,38,920,340,182,879,476,969,725,666,192,867,35,558,482,572,624,823,517,485,58,603,437,336,421,531,574,727,756,808,178,94,441,378,979,153,623,699,277,253,297,393,244,405,12,388,442,679,53,456,221,635,763,194,839,397,669,744,651,347,316,882,19,359,577,464,952,643,844,891,251,164,356,479,317,198,765,91,652,436,928,505,780,226,329,300,747,651,697,818,222,199,807,164,16,584,577,580,9,474,75,198,456,839,839,629,515,850,834,418,372,853,162,836,348,41,824,795,829,416,421,397,292,635,134,51,254,567,887,106,643,398,547,514,668,874,215,522,478,580,441,664,880,374,422,427,41,42,870,395,850,240,627,618,162,274,577,186,783,305,197,133,609,700,388,152,226,393,35,37,344,55,455,204,91,953,721,256,341,878,624,772,781,391,366,751,99,773,758,708,807,534,81,186,13,8,902,652,532,323,185,319,556,388,943,701,474,845,887,759,341,930,59,835,75,489,349,511,78,719,879,809,326,404,941,324,969,441,389,781,861,368,505,431,478,468,692,34,733,223,129,719,165,160,714,236,48,579,666,933,390,140,494,296,579,177,285,30,37,217,465,424,210,839,565,539,301,318,162,611,526,541,437,19,211,764,396,517,845,427,87,281,116,95,646,387,559,529,620,617,641,673,421,945,668,955,939,791,120,875,596,382", + "632,955,890,363,582,891,631,723,224,71,474,652,351,311,278,95,525,335,925,290,852,43,731,555,401,752,442,198,708,554,674,994,904,298,660,511,978,743,817,31,177,791,911,600,806,722,361,53,108,195,278,920,522,817,803,225,556,912,272,797,634,947,150,623,693,917,262,959,68,126,735,860,493,638,729,495,407,508,622,122,957,827,475,546,731,730,401,682,563,556,15,567,44,533,224,808,125,206,89,59,607,663,849,709,440,315,619,84,913,816,281,442,853,902,874,78,703,957,148,542,608,184,99,324,415,206,795,321,689,343,630,127,950,497,884,494,215,157,319,401,288,593,58,821,354,21,690,575,205,163,251,810,51,793,222,213,245,332,714,481,779,135,967,698,9,673,984,618,344,194,48,720,179,599,933,903,766,87,577,621,591,284,88,719,2,948,758,594,337,402,502,209,871,968,629,912,212,825,999,164,309,829,627,467,359,310,102,521,650,680,215,65,247,889,572,709,372,82,702,765,283,238,998,412,63,898,332,846,4,961,554,741,4,282,607,30,315,233,538,180,246,984,491,460,516,914,404,479,941,10,320,672,745,656,828,33,744,458,673,666,189,508,674,731,976,523,542,722,309,575,993,884,814,157,213,427,49,600,109,774,398,75,386,585,891,554,892,261,595,623,208,184,152,729,388,149,870,581,527,946,779,379,584,657,9,875,598,581,461,541,920,323,993,758,833,599,290,364,818,949,581,413,235,998,924,174,378,970,719,498,903,936,451,757,699,554,278,358,930,254,178,856,638,461,924,488,704,246,354,35,874,309,794,487,520,323,926,934,258,765,867,563,340,958,642,106,73,742,652,192,210,758,580,513,48,94,966,319,571,72,734,243,966,781,495,250,963,735,561,839,357,74,960,849,901,344,686,138,806,273,192,9,414,38,796,15,259,12,415,837,993,468,496,976,590,850,284,41,200,683,125,557,506,590,118,142,211,42,806,41,86,57,893,336,666,172,650,203,509,627,795,477,345,321,438,987,662,468,955,899,161,184,645,867,893,481,587,570,499,235,766,607,225,174,101,13,639,179,886,566,377,38,433,321,210,688,742,34,114,496,305,642,663,800,464,992,266,105,966,812,84,937,370,818,852,544,636,841,528,671,300,495,847,844,56,247,719,429,765,454,239,829,772,878,450,51,992,309,893,604,858,527,436,396,973,90,578,173,72,592,386,133,212,807,784,129,83,56,437,766,931,123,564,457,290,413,172,862,862,575,353,469,538,36,553,436,511,728,628,655,187,786,535,831,104,608,806,504,706,635,49,709,344,450,766,521,1000,428,79,9,951,873,974,633,450,0,261,821,987,33,298,791,103,735,28,104,132,167,67,788,978,193,875,852,479,727,180,577,935,130,224,428,227,850,126,132,596,929,216,346,138,375,700,624,865,464,830,104,775,86,79,674,428,756,410,397,479,380,395,896,348,556,239,273,531,853,375,491,925,67,868,842,965,621,5,491,476,75,561,480,706,128,972,399,96,441,73,50,570,913,973,763,206,983,770,519,263,588,430,504,361,882,358,470,868,170,581,144,742,373,299,796,196,577,244,633,195,936,324,753,294,830,424,422,236,82,83,198,860,737,236,256,996,976,154,252,426,900,488,113,821,75,995,728,600,23,594,591,524,944,450,892,129,846,669,879,940,911,863,833,159,801,665,339,357,844,823,407,481,967,527,786,678,339,488,370,440,399,903,789,75,421,886,603,36,214,194,332,178,218,946,517,250,467,584,950,382,131,410,28,430,56,202,556,662,852,937,77,312,110,915,884,300,32,676,281,991,393,224,412,89,490,937,107,994,262,818,387,660,964,625,686,281,743,334,608,497,771,285,966,763,953,605,537,773,268,235,732,809,937,567,150,931,311,653,464,983,871,999,752,705,483,370,105,734,534,922,368,183,183,574,838,883,154,182,389,466,964,121,297,450,346,139,385,404,885,811,283,575,789,120,179,487,191,351,178,400,424,250,245,794,96,830,785,995,578,211,886,418,314,935,669,7,329,77,952,435,656,23,305,829,200,141,540,188,550,897,434,560,13,239,537,894,234,617,356,698,929,857,828,325,739,205,399,369,143,639,229,405,623,263,391,553,565,776,923,375,815,330,827,115,733,112,938,236,60,660,200,815,641,836,464,9,759,976,443,945,935,828,416,580,238,18,663,874,116,613,60,909,504,292,551,437,334,341,844,58,366,426,487,416,513,959,915,785,746,394,918,619,989,68,253,348,674,455,927,194,674,322,823", + "388,314,50,701,11,703,702,618,746,861,766,167,891,333,763,604,262,718,714,78,329,433,198,499,410,471,33,594,325,420,321,219,795,770,928,663,938,808,167,44,224,146,139,19,869,848,295,724,894,563,345,605,173,743,262,79,480,735,208,608,264,437,25,333,589,154,9,261,113,789,771,126,730,391,779,271,364,537,165,301,716,314,618,155,327,347,222,956,50,728,565,559,467,653,818,619,761,625,871,554,875,963,814,390,339,619,598,183,996,493,899,888,427,218,32,727,781,61,952,436,359,813,334,928,29,805,248,47,685,233,547,296,731,478,905,752,89,819,474,826,630,944,920,936,214,247,349,706,137,266,962,510,89,35,844,995,981,546,729,819,560,35,281,29,88,160,554,842,121,785,529,531,39,306,873,914,565,393,75,398,384,289,845,309,23,574,383,442,991,440,111,571,505,992,277,359,691,953,42,193,854,490,487,552,130,835,169,968,917,352,561,927,755,645,868,617,836,417,677,987,828,34,510,456,508,447,233,241,223,289,26,580,844,300,492,4,627,552,629,91,112,902,731,67,252,566,410,567,482,456,883,85,408,272,242,673,687,308,594,402,487,630,284,495,505,864,549,340,585,397,378,998,644,609,939,754,222,682,664,947,26,512,718,415,981,986,531,723,537,865,877,30,437,404,779,370,234,419,255,643,795,899,949,971,690,853,577,195,359,935,551,103,302,636,701,85,423,86,797,370,15,160,121,198,508,755,482,756,156,929,803,554,541,917,269,736,810,844,638,417,160,316,138,712,71,619,658,984,87,602,864,143,785,271,648,716,640,593,861,237,853,271,77,327,659,218,917,159,926,947,821,537,147,561,62,993,978,865,331,890,761,37,46,151,18,840,483,442,462,804,771,808,756,701,288,853,997,734,747,709,868,475,574,122,480,703,992,625,157,552,231,246,10,462,951,317,956,30,145,418,484,50,262,658,216,455,62,608,533,903,895,621,646,132,164,328,81,546,547,478,906,202,895,360,823,618,586,618,562,55,16,639,467,653,728,77,2,930,887,432,279,226,819,181,930,827,560,337,34,969,303,711,330,496,960,307,856,374,738,490,303,835,41,980,570,903,989,802,524,672,798,770,111,415,37,26,396,398,192,764,282,641,509,706,951,212,818,392,842,305,64,13,387,425,494,198,635,593,438,924,791,773,243,138,517,929,866,962,698,312,399,560,129,255,603,477,578,155,794,573,514,93,320,751,278,770,91,674,157,162,342,459,347,979,110,231,776,651,525,666,586,325,667,646,639,518,858,842,626,702,952,428,25,381,761,859,990,261,644,300,65,775,74,583,871,261,0,741,714,458,24,272,394,989,494,990,550,608,226,750,978,864,424,675,724,910,14,619,88,476,790,162,546,245,879,756,819,676,694,933,586,478,630,91,536,260,566,116,568,458,343,381,201,482,976,506,614,127,604,181,682,981,731,949,93,463,704,383,965,859,9,261,105,681,148,384,204,203,200,801,322,250,2,648,717,700,991,171,417,10,948,951,595,929,62,217,311,154,691,961,759,131,504,190,576,478,236,419,505,152,655,568,978,172,744,662,818,687,342,352,703,605,774,578,727,117,722,595,243,451,709,872,220,82,654,522,975,282,204,886,31,898,900,730,176,771,938,535,657,83,13,528,200,200,556,160,255,21,21,123,904,320,286,71,689,154,476,776,292,796,379,22,45,307,73,120,243,890,665,594,27,749,27,991,801,863,963,48,513,596,727,928,681,127,761,998,371,433,971,151,2,309,110,852,790,154,59,595,625,383,390,829,277,671,377,384,627,653,569,802,11,460,934,945,902,58,824,22,771,261,895,54,552,641,931,839,102,613,554,829,889,29,965,637,911,570,823,521,260,518,380,358,159,678,103,547,387,827,564,36,269,18,18,896,277,887,23,344,278,362,180,504,273,904,937,829,10,502,648,390,610,880,998,497,494,688,589,140,886,608,146,815,231,160,889,361,620,655,193,264,650,785,736,811,859,752,834,814,751,981,871,404,397,198,327,346,456,975,460,202,954,890,793,470,828,272,311,55,837,175,132,560,709,555,776,704,803,817,920,632,597,678,704,340,905,783,335,759,14,900,750,762,819,98,970,842,84,984,46,603,880,179,948,794,585,975,95,68,412,962,39,537,532,911,19,897,821,662,669,302,693,468,262,67,870,929,32,173,374,984,955,302,412,414,684,143,25,950,882,870,48,744,962,323,587,786,313,312,601,395,647,185,275,767,478,928,464,617,11,958", + "319,12,376,198,573,650,553,987,734,757,606,283,977,503,610,387,171,720,617,775,685,146,55,216,538,968,703,561,597,53,593,319,544,878,841,347,110,130,33,913,54,670,911,3,637,176,363,602,634,707,603,130,222,564,81,860,987,779,941,396,265,250,709,152,222,308,908,176,733,354,295,967,904,21,938,320,840,764,673,521,124,630,511,210,90,818,320,27,726,880,345,247,574,817,140,786,101,920,611,287,218,241,911,477,839,428,799,414,203,330,401,613,715,335,934,910,556,770,515,997,240,438,136,85,972,698,413,513,475,807,922,753,56,427,338,58,560,663,181,108,809,458,945,658,161,760,488,358,927,397,459,530,673,3,100,299,732,838,38,637,401,536,695,382,145,640,654,664,790,666,798,86,98,97,830,527,370,762,146,548,375,169,45,538,494,327,593,705,380,185,359,331,972,943,431,281,216,757,882,276,577,956,524,641,486,18,137,480,4,20,711,888,916,511,157,227,358,64,265,540,633,424,108,755,585,674,939,219,233,879,135,676,630,343,785,536,912,827,815,184,622,462,543,13,688,548,270,929,188,676,641,364,375,902,383,184,775,479,172,260,729,792,904,267,980,480,42,598,549,592,523,550,427,1000,606,605,550,222,350,359,582,349,366,34,340,938,587,266,977,370,517,493,362,276,557,861,643,345,178,632,251,726,753,386,433,930,699,698,564,499,189,37,573,396,675,632,291,36,589,810,943,468,385,358,234,473,970,174,485,77,751,697,760,508,874,665,599,363,947,980,136,844,105,703,434,427,552,182,854,301,910,806,32,958,532,784,610,23,924,759,130,769,274,839,985,197,291,869,932,499,474,414,912,14,197,898,632,589,228,387,545,562,889,411,228,863,518,610,719,752,260,853,398,129,338,539,248,645,892,800,826,550,352,83,272,107,802,149,748,939,805,61,973,688,124,626,523,867,565,922,178,356,370,222,822,175,627,771,846,431,521,885,737,357,806,980,889,507,293,413,415,285,454,379,344,771,305,415,256,947,798,493,963,273,537,119,366,743,805,66,457,864,752,347,765,701,102,809,849,538,338,72,861,409,861,490,150,574,738,400,607,650,24,207,884,641,82,688,278,204,233,253,810,917,323,613,777,291,115,5,399,190,152,439,967,289,635,916,554,367,632,97,978,574,234,931,199,936,251,159,594,227,19,606,200,63,590,361,329,481,509,491,561,623,921,942,293,502,837,945,473,447,180,258,652,234,76,745,630,969,705,138,924,518,162,23,922,638,357,990,518,726,936,66,861,614,212,415,582,873,113,906,779,81,835,183,421,121,570,394,839,450,522,515,728,821,741,0,707,377,861,264,34,509,929,817,684,699,958,510,361,60,965,360,660,501,529,198,5,676,848,325,484,332,320,545,671,403,947,386,459,889,928,400,615,441,386,642,896,776,91,721,665,147,823,240,369,882,887,358,480,930,233,441,39,633,838,938,286,909,64,734,446,920,89,228,802,29,393,494,409,397,930,824,773,559,170,494,366,566,479,801,599,418,536,752,142,571,327,183,185,60,538,28,327,577,621,213,846,781,431,413,177,503,662,432,766,227,157,551,154,901,954,184,595,671,800,709,179,777,943,112,4,853,812,809,240,994,272,720,161,516,504,331,742,243,891,839,791,362,687,285,496,415,801,737,598,754,297,128,430,146,454,17,536,123,512,97,432,260,398,361,458,60,166,878,379,732,419,760,113,751,320,836,264,473,659,190,408,700,737,512,813,64,35,62,243,846,760,193,22,277,323,385,960,681,145,289,512,443,611,738,194,71,147,71,960,747,138,428,938,611,177,176,619,638,904,608,221,426,976,158,651,963,78,649,579,684,108,81,20,801,856,736,744,94,645,57,560,725,209,166,539,445,299,582,13,45,647,329,367,48,544,682,360,748,236,39,769,577,478,234,330,614,228,573,974,292,855,689,6,755,745,436,779,164,67,698,683,203,483,687,865,222,603,206,582,874,57,790,245,356,704,127,3,151,160,396,83,610,549,183,416,581,556,937,467,616,863,349,67,797,46,343,150,595,359,545,600,836,652,494,434,415,482,464,819,739,465,863,857,435,998,575,528,779,131,62,609,570,616,59,111,384,987,191,255,400,508,683,274,397,260,277,758,527,598,447,196,270,216,319,67,830,201,117,776,99,456,305,435,675,91,775,440,519,3,113,988,288,820,61,759,784,248,900,236,959,242,343,893,816,823,118,835,551,99,599,730,685,458,121,830,573,169,458,24,507,633,271", + "999,618,620,900,432,872,779,457,822,141,792,156,536,347,342,518,539,988,665,556,567,706,670,508,951,735,119,129,474,670,175,202,836,347,77,110,726,236,463,882,662,857,157,940,968,89,888,922,793,592,171,467,576,850,406,757,31,620,150,247,632,510,304,675,802,104,193,700,954,227,276,762,862,868,955,681,925,247,115,5,747,333,526,404,876,871,170,603,280,631,512,159,568,638,895,53,255,68,113,336,69,549,869,917,884,174,222,339,391,924,912,411,436,639,493,775,902,768,224,326,389,17,322,950,651,807,719,15,287,317,725,334,545,331,70,200,849,924,770,586,385,588,345,587,20,437,132,789,758,625,303,269,314,359,977,824,812,311,265,112,420,915,94,139,324,896,337,830,436,417,446,426,885,923,725,350,516,657,416,246,13,261,266,52,663,160,964,844,974,671,409,987,769,24,731,961,65,444,4,541,985,859,522,655,466,905,471,278,840,543,886,118,236,929,448,394,848,195,121,334,921,566,355,657,120,205,601,59,316,427,208,812,967,137,985,673,908,614,10,805,530,986,78,823,324,552,755,336,208,181,279,963,812,996,569,218,676,291,240,299,865,294,344,402,558,365,972,877,678,827,111,279,310,827,745,416,105,539,851,193,843,882,995,823,989,800,854,573,345,988,269,17,406,646,802,549,586,588,672,739,136,825,308,551,966,771,280,93,755,37,265,922,347,118,632,729,693,809,75,890,215,582,660,156,795,400,253,821,821,502,131,81,628,584,752,848,625,466,293,238,281,908,396,948,738,235,484,468,328,880,216,237,675,981,948,125,545,930,732,618,252,199,974,413,673,399,374,704,861,47,790,81,321,453,893,324,276,849,597,66,555,153,681,59,695,185,462,605,483,216,93,107,830,468,744,65,170,197,456,611,886,943,430,777,867,876,639,312,438,687,77,775,188,31,36,804,558,559,812,856,890,506,143,89,630,106,90,64,231,786,145,317,978,3,703,207,687,788,271,330,540,858,424,751,652,372,703,921,969,840,191,595,646,946,378,729,32,649,655,401,798,114,470,823,986,847,375,945,474,567,320,144,417,930,365,915,495,616,128,769,881,714,333,20,545,987,396,23,521,122,521,672,584,424,221,758,377,59,363,885,529,343,655,833,538,397,168,652,437,522,16,762,779,5,154,424,481,802,32,292,976,709,780,647,438,938,159,22,632,314,740,368,773,250,181,655,328,803,363,596,796,998,870,712,806,822,475,369,919,412,425,7,260,151,979,574,675,875,649,598,315,100,124,25,562,672,848,396,963,577,935,829,512,494,6,94,668,543,672,754,560,140,802,310,826,987,714,707,0,359,112,492,128,527,713,825,799,860,605,455,544,459,115,696,20,135,961,265,495,36,182,887,82,499,173,145,111,504,283,621,749,306,509,535,412,129,639,703,98,476,508,732,272,970,983,238,325,506,366,192,884,585,837,259,70,317,717,529,654,89,976,910,319,414,69,390,803,720,197,393,302,375,350,214,288,769,622,160,634,648,852,18,745,912,18,587,60,897,392,458,123,783,479,130,142,748,566,860,891,779,908,576,106,761,779,377,870,154,679,537,20,818,764,306,688,338,971,938,855,121,980,394,714,37,597,303,269,269,151,325,543,186,760,95,930,539,904,523,156,707,198,829,104,551,892,800,614,569,695,920,927,584,393,402,498,385,752,545,762,345,1000,792,118,170,862,412,277,49,6,763,102,412,107,509,213,422,374,368,547,520,206,468,992,470,619,514,943,444,528,14,301,368,873,303,766,379,479,440,742,483,685,244,429,536,895,432,189,74,906,828,36,244,18,657,671,639,448,926,978,312,829,678,377,34,792,508,661,205,137,789,193,882,746,577,795,204,661,130,660,539,172,917,712,359,837,86,64,813,598,82,26,878,861,137,214,947,243,324,263,182,508,842,204,921,914,829,335,855,561,395,807,624,661,86,56,386,486,875,506,171,876,243,436,542,671,592,231,673,577,948,612,28,97,209,148,885,837,157,624,444,333,621,152,140,681,165,162,806,220,4,316,620,924,80,100,349,585,841,833,610,866,355,791,446,923,493,548,406,194,390,288,394,82,419,828,898,373,591,617,598,495,789,116,180,350,534,203,341,498,315,516,829,797,182,811,573,687,890,608,314,671,325,292,115,933,287,897,556,512,672,397,993,859,170,602,158,153,463,401,135,669,611,529,397,913,960,617,301,752,282,502,700,336,141,683,5,928,258,430,176,904,15,214,549,712,630,931,620,952,882", + "409,150,766,928,919,155,629,97,298,25,879,374,253,230,572,277,457,429,820,797,600,160,270,77,734,158,591,455,279,178,481,524,163,230,407,659,677,472,506,331,827,569,972,856,335,760,546,847,402,712,647,436,219,829,325,7,279,856,296,37,676,410,522,746,679,279,633,625,633,736,669,41,143,890,526,921,596,274,190,307,992,112,460,336,253,168,166,797,633,851,134,690,256,805,115,823,930,539,437,370,855,279,949,134,384,607,96,484,815,583,134,110,170,622,483,867,181,856,283,457,392,561,970,168,150,60,114,673,662,33,722,462,789,575,725,269,168,836,412,251,514,796,280,459,832,5,975,694,771,386,807,142,446,257,996,89,46,16,820,54,691,562,815,284,526,606,199,818,223,758,219,568,456,331,448,998,591,638,960,779,911,776,528,11,673,628,45,366,349,831,803,486,229,624,32,285,385,959,874,21,309,253,549,208,650,963,435,844,311,418,270,880,610,504,236,715,483,55,133,177,341,473,909,825,982,474,328,501,255,652,940,856,522,703,824,685,527,127,791,670,618,556,534,119,556,959,722,206,721,657,231,173,131,617,619,637,318,614,826,263,715,430,176,806,670,760,592,51,770,520,386,989,291,956,367,455,566,783,368,46,146,57,341,602,809,751,922,692,229,815,493,51,471,478,217,425,503,735,661,133,230,564,584,737,222,106,65,123,889,956,856,754,582,470,532,343,483,901,94,939,779,179,308,422,496,98,70,203,635,446,530,365,227,819,909,385,751,872,570,529,954,972,913,612,750,192,722,696,613,997,766,899,685,788,458,468,909,230,54,753,322,708,573,804,323,37,129,291,36,778,212,883,195,218,30,794,101,343,706,600,782,277,987,103,423,70,880,165,784,740,271,968,163,854,177,778,91,750,744,921,719,484,57,286,915,357,191,21,251,396,71,959,633,786,103,281,349,355,338,476,361,376,241,789,628,761,677,389,824,348,184,706,729,425,936,928,589,896,451,968,728,274,392,100,623,794,259,789,593,214,744,907,820,476,944,994,730,438,666,296,595,181,564,753,313,348,388,852,377,690,715,995,165,190,250,783,702,577,949,714,908,611,274,482,395,19,487,975,286,773,562,233,684,64,28,228,317,452,84,29,860,454,681,946,776,158,968,641,925,257,615,640,761,668,468,181,169,631,388,720,675,165,710,480,277,306,153,754,876,858,300,469,277,47,779,808,564,243,894,548,248,492,10,542,456,647,53,630,337,131,678,341,899,162,668,405,493,293,260,83,287,386,973,191,111,381,573,827,552,617,509,869,300,255,100,768,913,755,546,738,276,605,38,323,792,33,458,377,359,0,953,269,64,758,238,888,832,16,946,615,882,542,347,549,801,455,43,196,599,270,183,803,127,565,723,682,962,31,280,906,833,286,538,273,432,316,239,519,835,104,290,851,701,906,63,157,515,116,95,946,879,55,439,733,997,581,380,281,490,280,389,803,207,851,776,646,653,406,334,189,122,335,498,626,176,213,919,816,190,42,855,573,120,761,752,249,484,913,818,576,92,444,952,172,913,604,332,986,917,822,871,584,113,229,878,594,810,127,254,484,153,374,627,401,78,527,317,629,72,164,598,49,349,686,337,551,272,203,545,851,277,714,305,842,735,550,960,120,124,102,66,966,105,631,803,934,573,47,187,490,597,838,528,1,69,193,210,641,230,471,99,414,475,977,468,243,90,927,602,577,671,864,906,501,568,515,973,779,980,894,292,938,553,244,912,224,83,418,644,98,665,278,991,962,743,534,711,681,990,926,846,385,505,914,652,176,210,469,201,620,394,895,833,161,258,888,874,882,203,576,84,23,861,281,63,733,105,407,302,905,807,565,845,391,716,432,626,714,894,41,992,887,60,968,394,334,245,432,701,393,348,430,491,142,855,129,542,410,147,763,275,854,708,984,393,790,339,423,242,243,122,217,72,343,592,762,389,692,90,594,596,263,772,902,510,150,324,584,509,8,780,272,923,599,670,429,282,472,380,652,553,784,10,46,134,862,382,910,480,180,872,485,633,276,617,531,463,523,652,10,843,210,770,865,223,812,492,208,945,152,760,742,744,315,228,269,398,421,386,980,945,161,10,373,961,962,132,333,822,372,751,434,354,80,797,703,294,359,503,805,219,907,161,697,349,360,353,476,710,678,717,631,164,354,933,573,538,275,889,660,67,394,470,355,460,353,21,328,450,362,378,818,991,955,328,142,751,492,313,258,227,479,881,773,900,252,90,818,929,557", + "145,252,552,344,207,196,532,926,854,239,499,976,610,480,664,467,947,26,388,144,524,752,165,81,53,368,255,809,924,210,556,141,892,28,878,108,329,881,929,742,504,525,274,311,874,589,645,683,653,935,157,781,262,874,389,14,26,919,951,839,730,823,559,776,23,816,630,670,191,510,18,608,882,764,163,805,76,932,909,599,763,248,914,456,181,984,528,352,413,295,637,939,405,413,660,250,215,684,184,892,352,715,645,471,85,447,603,225,892,445,929,643,765,858,297,846,306,423,698,952,410,491,980,655,989,545,892,216,171,350,966,40,592,100,691,137,739,986,268,833,285,55,551,764,388,720,454,194,656,675,893,765,23,679,528,465,388,381,850,380,193,980,50,260,128,968,302,930,430,134,968,161,622,465,637,986,179,464,76,320,850,878,721,304,377,891,839,699,547,169,708,357,547,257,504,71,137,691,607,936,664,843,749,787,151,795,814,379,794,826,806,222,765,939,421,580,491,387,833,623,561,653,414,857,696,219,947,428,885,432,614,645,712,449,717,713,504,927,662,217,317,975,905,52,292,533,816,830,660,304,286,645,347,956,418,751,684,666,532,971,925,870,38,653,47,266,517,960,180,623,763,746,382,580,559,946,753,637,320,749,528,291,978,996,17,763,883,188,290,881,766,744,569,105,732,52,869,997,302,240,227,665,395,129,988,349,247,315,599,31,206,378,682,613,527,590,356,571,271,468,363,189,739,854,497,211,809,117,404,488,205,295,925,92,399,974,31,861,609,992,706,199,310,630,177,635,541,400,710,865,938,90,942,384,222,213,773,456,452,641,735,417,124,942,232,358,277,528,415,439,686,904,764,718,308,225,408,378,431,971,591,297,137,241,337,777,222,608,274,572,971,579,197,384,486,17,424,933,976,625,947,115,891,333,567,772,249,227,616,292,317,743,83,525,968,789,230,123,929,101,23,943,469,260,799,858,708,281,721,981,717,263,457,765,262,594,879,32,296,188,802,950,709,169,497,869,842,923,439,139,521,35,811,339,7,365,121,165,767,961,392,543,600,631,760,694,675,676,852,195,99,628,115,858,32,70,333,286,209,500,897,444,669,198,226,857,701,270,533,577,310,101,583,885,92,591,264,66,784,856,701,322,444,711,713,306,441,664,815,827,685,268,144,373,843,95,987,636,368,577,170,798,454,383,939,555,756,608,383,431,943,826,450,304,552,243,415,660,595,23,54,794,742,253,684,884,452,320,707,198,572,507,789,273,844,402,471,745,459,476,557,330,257,67,632,763,602,202,264,881,535,420,552,647,362,298,958,6,576,681,175,922,775,29,59,298,24,861,112,953,0,597,526,44,829,995,485,604,67,769,716,464,878,27,502,254,889,332,97,550,877,878,511,201,169,844,202,937,862,294,623,397,155,103,472,857,750,237,446,355,260,548,995,400,874,703,507,144,847,212,870,898,733,135,922,438,19,356,467,208,280,433,927,278,430,328,515,527,35,108,913,15,254,254,881,577,853,29,27,666,444,466,136,220,643,151,827,342,752,535,759,564,126,274,397,244,609,607,213,239,740,877,871,13,586,81,742,699,525,385,555,661,418,662,247,72,417,682,860,12,920,976,838,190,737,113,931,711,999,173,980,458,855,713,4,655,637,879,89,943,426,351,845,419,347,690,44,514,860,176,575,824,283,352,128,60,749,162,232,70,831,975,812,812,216,349,242,160,14,830,406,144,530,152,389,13,128,972,762,57,638,527,563,489,977,138,634,646,174,284,703,959,313,831,282,311,706,438,91,345,984,829,256,516,245,242,852,886,866,233,247,570,969,943,308,74,414,351,902,120,870,209,136,568,980,270,146,420,816,606,595,620,824,588,625,150,37,300,97,455,524,504,866,607,151,63,220,771,258,705,997,946,232,221,10,182,439,278,375,44,712,819,218,48,859,309,851,933,668,872,909,775,51,829,20,727,162,770,520,912,937,645,495,457,432,128,392,945,824,598,352,47,91,397,490,538,269,387,274,825,967,636,957,587,573,560,849,533,664,312,585,205,980,628,705,36,561,302,82,708,669,791,879,45,734,737,196,373,741,83,517,75,250,317,409,778,788,566,548,738,165,108,374,382,716,890,223,547,44,635,257,891,457,687,497,56,359,590,393,855,525,456,914,698,608,27,338,102,517,543,949,276,453,351,971,382,846,512,414,223,6,101,902,751,996,114,984,688,513,253,94,186,801,415,917,32,151,677,802,929,593,194,868,712,112,184,11,608,196,601", + "748,880,98,688,846,749,989,439,620,670,599,598,620,188,450,788,73,677,90,632,726,76,849,198,439,695,67,887,319,186,451,161,240,77,751,99,913,973,550,856,81,780,191,288,691,428,428,586,756,631,975,948,371,105,884,755,245,978,821,525,880,552,946,3,90,606,467,920,10,412,301,473,808,218,628,487,948,854,165,142,861,878,894,999,51,515,957,147,878,974,947,23,878,236,208,184,886,351,841,234,212,886,766,196,712,265,16,982,175,315,106,671,723,478,390,902,891,568,137,553,700,832,146,416,528,599,471,767,421,90,92,239,448,558,76,751,560,168,215,691,593,642,250,513,987,932,706,190,872,444,984,34,367,224,669,311,774,106,405,313,784,267,390,848,644,882,942,631,873,32,195,295,217,556,244,684,908,599,642,649,340,223,791,459,597,669,541,644,265,73,667,634,331,908,366,116,970,656,831,695,747,524,821,693,800,772,866,618,937,80,275,966,209,921,698,970,960,570,634,619,323,363,447,253,653,18,164,946,118,663,178,856,244,322,260,742,314,528,638,25,650,346,532,909,799,490,476,644,375,67,825,660,501,324,509,734,52,608,819,315,595,517,654,367,636,207,754,171,621,40,804,176,863,133,859,223,611,902,217,321,742,907,905,261,886,78,184,212,597,814,783,709,54,154,400,814,673,894,431,525,544,993,557,691,635,369,264,270,153,327,541,867,895,83,987,988,693,631,800,513,165,402,848,953,814,571,819,348,584,279,905,498,437,346,368,387,854,296,456,363,785,517,674,197,646,201,259,100,72,619,514,732,687,778,103,796,812,582,240,568,298,368,322,739,924,214,943,387,759,63,397,195,114,610,817,600,206,512,639,237,729,938,150,701,779,20,201,399,646,678,470,588,687,584,782,998,350,550,240,604,680,353,842,809,721,10,125,75,417,491,360,404,340,541,162,194,753,588,101,192,287,471,879,677,372,152,969,308,556,226,83,849,583,527,459,617,361,620,147,294,280,856,905,938,316,882,211,372,467,970,171,201,693,242,804,904,989,261,742,201,237,731,366,141,679,988,578,470,244,472,887,18,883,919,950,124,520,419,357,187,862,488,497,745,487,298,556,251,553,411,481,488,950,649,878,287,528,514,433,663,371,495,562,292,599,785,695,613,510,624,133,913,670,847,874,837,425,805,782,941,545,186,57,433,663,663,767,431,600,681,483,356,865,164,627,968,421,511,314,361,685,196,441,138,876,735,292,830,306,988,512,687,389,471,715,906,471,41,259,517,280,367,524,835,123,782,248,413,490,224,950,184,817,800,89,427,330,873,80,505,872,690,984,610,209,791,272,264,492,269,597,0,226,241,216,788,454,988,462,186,247,131,410,799,226,371,531,80,427,85,698,482,487,599,104,39,141,728,516,551,205,359,912,409,691,425,396,520,801,765,131,703,78,369,133,369,143,838,810,31,72,896,941,283,92,503,53,414,805,314,723,790,43,666,818,925,4,512,517,571,72,420,830,135,515,689,478,882,300,594,649,708,349,98,141,900,971,519,912,927,804,748,445,399,453,256,920,461,467,571,58,357,251,295,33,27,560,292,189,954,319,422,334,752,30,417,441,273,665,381,316,846,844,709,46,242,751,693,43,595,140,648,903,774,182,299,57,772,968,49,258,962,507,447,760,398,795,112,482,647,937,339,110,745,189,74,365,370,479,503,765,942,111,861,842,959,582,137,417,345,21,681,673,921,80,496,918,219,753,344,474,400,601,660,66,202,818,654,136,889,686,566,568,187,652,105,222,505,774,164,369,510,49,340,804,217,583,232,191,132,599,612,642,778,996,603,61,210,24,892,946,378,620,611,590,10,963,426,441,769,99,702,852,401,976,343,161,77,320,947,526,511,788,687,464,393,796,371,962,947,501,256,498,49,898,527,132,854,525,803,451,577,792,692,9,148,481,878,622,629,491,438,738,530,984,231,902,657,375,713,379,680,676,370,494,153,865,769,586,568,665,995,804,544,305,838,963,46,284,535,178,842,57,486,243,774,784,543,719,760,694,702,623,733,598,361,330,662,516,465,141,334,832,111,316,351,998,141,178,793,180,596,486,553,274,193,534,260,203,968,573,537,937,308,653,737,190,489,831,214,831,830,467,119,223,712,813,731,11,759,931,638,575,521,844,843,258,453,470,442,943,902,227,342,308,381,159,751,489,893,724,536,177,319,109,82,664,287,784,417,972,84,422,155,519,959,733,39,994,317,842,378,855,692,748,194,857,323,882,150", + "136,429,392,842,584,154,160,14,471,315,627,920,748,347,226,297,992,525,185,973,678,815,357,184,61,703,997,939,871,597,955,45,870,182,696,536,466,130,765,208,462,753,185,895,377,232,270,370,44,11,251,94,8,606,789,520,27,580,13,579,187,181,821,417,704,597,20,636,713,776,485,194,50,237,910,437,843,64,230,991,624,443,74,631,987,752,449,850,59,997,271,219,876,66,815,19,205,475,357,848,669,474,538,948,695,922,889,812,322,201,241,528,694,48,676,694,838,521,944,622,82,983,827,837,967,921,107,293,899,222,329,928,354,143,985,600,911,694,944,774,549,381,13,945,434,952,54,744,745,123,391,70,361,281,577,367,986,171,387,240,474,668,548,908,810,377,259,358,1000,382,609,77,254,448,145,943,762,890,262,185,184,354,417,279,175,411,388,336,108,42,161,852,82,267,119,210,48,881,576,528,97,949,118,707,780,769,740,217,644,366,541,691,355,876,722,934,21,967,811,583,95,695,191,990,769,455,240,384,120,466,463,795,63,687,76,589,630,325,701,546,65,875,84,623,304,407,365,111,946,519,670,497,213,980,288,813,685,109,463,878,741,228,435,615,98,642,641,175,534,729,292,931,535,578,652,219,608,333,172,778,894,694,588,79,716,413,615,407,772,952,875,100,920,470,405,480,10,866,75,312,438,164,100,273,294,958,107,281,388,812,635,570,273,302,898,724,665,28,29,612,504,971,243,563,503,622,244,781,542,107,525,866,595,886,692,361,399,606,118,309,860,263,419,25,395,602,231,649,112,464,845,456,851,754,840,859,632,516,82,10,907,224,274,909,962,689,725,777,181,349,478,600,797,49,305,761,808,584,538,726,34,340,692,389,102,61,671,949,950,414,332,784,906,776,41,134,292,217,491,386,597,45,351,14,312,300,834,494,642,427,626,43,573,616,497,750,829,217,502,425,716,828,661,797,632,465,756,828,958,220,824,673,528,580,17,718,73,269,152,866,261,986,26,15,682,995,815,42,813,177,470,953,972,822,240,132,678,637,430,901,199,720,9,94,184,256,833,293,368,942,800,906,893,586,959,467,552,208,879,846,191,126,785,808,582,678,961,394,490,135,491,746,274,712,396,727,435,515,682,134,501,575,197,874,518,851,477,850,988,744,453,249,325,378,414,230,349,8,486,173,518,145,784,802,270,366,541,966,620,446,707,501,231,572,424,437,782,398,26,212,451,206,577,966,606,171,194,614,222,867,111,518,66,725,511,851,860,176,795,222,912,660,434,447,716,372,105,342,24,949,811,342,726,706,456,894,269,477,130,681,717,149,801,424,864,103,394,34,128,64,526,226,0,20,334,59,94,894,836,260,435,466,51,866,814,726,403,794,422,304,471,182,79,906,314,418,469,787,561,579,396,875,957,728,993,187,629,99,768,385,459,868,95,204,958,275,932,415,220,408,644,24,773,328,311,198,768,144,610,845,392,681,635,851,748,928,15,496,233,298,807,240,449,162,967,679,968,237,28,211,938,227,473,342,971,679,19,164,835,900,623,41,13,656,347,755,632,219,915,592,234,539,63,262,149,411,705,190,733,123,648,99,989,476,319,964,433,639,207,199,630,121,316,993,426,350,210,352,244,211,917,13,946,789,196,185,594,561,172,944,794,367,60,894,153,317,929,442,708,290,694,153,371,580,183,770,763,998,472,868,463,693,996,319,497,873,835,472,354,548,114,610,252,723,760,695,51,7,490,782,426,406,638,513,637,210,94,680,32,131,318,229,758,501,942,681,287,171,979,156,979,978,470,126,938,628,989,498,960,325,964,418,356,952,620,466,168,867,672,14,449,476,468,753,135,663,275,871,375,175,613,477,530,71,870,889,692,339,593,32,14,718,530,872,412,975,985,74,314,125,531,93,895,279,563,625,466,830,493,52,493,777,858,973,151,992,415,22,229,143,460,111,575,835,950,168,354,659,186,785,436,23,266,580,863,75,482,573,769,675,934,113,371,376,356,803,798,961,98,761,405,237,198,188,598,340,709,853,393,761,632,963,9,417,391,6,962,583,644,38,176,703,613,431,826,959,877,204,102,55,693,773,631,986,15,343,437,847,733,695,908,946,960,491,317,653,887,567,339,951,472,660,548,574,459,836,137,249,884,982,863,389,34,480,111,174,891,278,278,642,418,245,80,71,364,32,968,981,482,286,88,820,195,333,826,56,647,23,296,546,241,313,208,681,515,215,242,297,968,686,482,694,46,879,122,965,137,436,71,159", + "226,309,700,506,704,16,198,653,312,445,991,966,379,631,67,7,980,852,179,558,743,707,211,304,532,570,154,705,57,186,570,862,803,54,236,757,878,565,984,466,12,772,265,749,610,345,618,57,683,559,252,605,542,845,416,636,70,394,855,409,142,357,526,751,361,430,523,440,343,335,255,384,771,393,161,465,249,42,373,594,788,884,756,764,481,142,99,82,30,857,238,975,518,73,781,187,7,104,210,67,411,670,880,475,249,368,563,565,673,66,862,164,145,646,385,650,461,145,12,152,662,898,94,898,761,469,709,64,474,731,545,751,324,988,23,576,487,443,540,676,981,402,249,992,625,589,246,257,504,264,59,400,784,639,739,870,990,18,847,536,576,617,4,866,869,233,237,30,352,914,702,960,160,400,918,173,660,102,571,517,80,893,451,62,42,839,794,708,184,71,826,886,863,126,814,636,429,546,91,897,338,74,668,890,978,9,69,298,719,303,904,651,119,282,138,288,611,909,612,894,347,371,231,235,274,647,80,354,632,964,385,377,200,324,325,69,233,59,198,783,550,966,390,68,146,926,435,603,976,150,925,854,655,943,868,506,811,560,238,62,400,220,782,922,204,901,169,869,546,48,55,469,381,369,371,764,149,774,754,155,622,463,960,784,458,563,454,171,111,900,778,79,387,485,158,469,974,856,914,820,263,393,885,825,993,851,373,328,544,430,86,804,517,915,341,374,584,850,909,721,915,158,174,254,195,663,571,665,640,758,394,750,746,521,95,946,248,770,94,26,691,828,304,595,94,42,70,15,882,681,167,950,161,616,854,117,583,327,189,467,252,245,168,533,241,497,103,736,939,9,28,195,648,781,769,900,161,279,501,811,663,467,168,802,816,542,502,81,163,878,836,658,423,626,367,490,527,738,694,225,967,737,328,962,944,905,298,834,460,591,857,242,104,973,644,523,546,938,113,533,603,671,863,943,435,22,568,603,944,646,846,493,550,461,98,501,452,868,439,476,525,616,253,673,840,35,586,787,111,627,808,40,279,945,486,723,42,941,225,295,27,228,466,268,109,146,434,641,393,751,421,473,674,300,600,129,464,133,151,98,334,680,150,885,987,748,801,696,988,145,428,661,772,535,424,735,463,172,317,574,156,698,23,304,355,915,9,106,714,697,953,555,212,407,12,777,222,287,861,767,918,448,169,498,787,600,411,886,84,460,90,914,87,783,960,374,171,458,775,325,459,139,256,771,839,35,627,861,344,493,925,823,457,831,379,780,639,203,700,881,827,631,430,705,457,914,987,532,450,834,530,137,155,639,81,606,973,692,50,675,59,265,925,912,650,735,989,509,527,758,44,241,20,0,581,597,504,7,641,722,567,373,745,952,593,768,614,142,373,284,968,298,422,355,563,534,807,769,425,915,874,100,251,952,961,797,816,200,408,710,23,11,191,807,30,257,167,674,412,138,385,719,67,420,668,244,527,234,280,627,498,38,908,195,882,800,303,964,886,267,112,96,540,835,20,942,322,803,429,104,573,313,368,559,762,436,29,466,18,296,352,678,655,240,367,402,620,499,744,320,509,710,703,866,102,355,941,874,323,111,297,784,756,521,472,455,333,493,653,344,780,675,583,603,695,293,403,377,482,298,835,432,500,104,929,809,151,590,34,354,4,774,525,555,160,608,494,255,593,713,939,297,84,470,767,176,851,321,474,548,192,699,8,391,379,605,309,454,506,992,829,4,805,59,393,648,574,206,486,192,390,747,1000,175,728,268,857,908,551,588,434,973,44,925,784,58,251,52,355,923,364,816,900,191,279,385,805,696,452,875,725,580,280,596,60,662,805,469,777,837,96,206,387,546,939,195,305,689,161,740,794,15,832,296,125,422,803,594,438,158,782,609,92,28,359,391,918,667,191,730,30,298,358,457,889,459,164,876,924,852,419,421,972,476,111,906,944,488,409,71,354,908,780,136,699,711,860,644,986,494,554,817,427,92,993,230,218,974,407,568,800,359,315,658,384,963,307,759,914,923,92,795,907,929,103,348,512,740,631,874,219,299,56,494,431,785,134,519,992,319,202,963,803,535,219,786,154,953,880,90,869,341,453,907,723,195,836,549,293,112,910,48,887,354,262,404,701,286,555,548,812,657,675,188,993,828,718,979,538,815,881,598,197,503,706,701,832,680,819,794,855,830,590,599,359,995,217,130,799,145,27,789,814,927,912,993,988,228,987,287,326,596,565,791,51,710,965,680,737,944,86,908,589,224,161,891,18,97,585,340", + "853,539,723,946,118,648,455,477,524,578,450,35,66,44,419,126,442,421,111,287,404,965,708,339,667,420,129,998,773,983,264,162,533,871,423,180,884,232,307,456,449,117,387,30,134,89,386,86,696,509,2,592,193,387,803,762,580,430,347,739,704,911,548,803,450,41,100,549,447,632,673,13,663,87,629,936,389,691,283,563,420,998,836,613,322,572,106,980,891,51,265,641,309,531,480,490,54,849,653,848,339,471,694,290,975,107,665,848,168,895,836,351,780,965,846,685,333,258,657,418,255,947,337,187,789,530,81,212,633,265,239,562,984,48,461,188,295,332,273,437,766,973,251,707,326,911,205,347,649,56,208,409,102,23,960,606,446,926,575,390,352,835,343,564,515,62,241,447,637,740,569,840,222,508,774,294,16,598,901,54,745,719,623,101,89,329,475,693,206,967,815,663,408,351,392,754,942,860,598,185,334,414,227,508,201,181,540,592,850,641,747,621,286,700,388,691,85,17,760,860,549,228,51,322,689,31,20,623,549,191,497,763,134,596,783,254,171,198,604,228,929,490,307,85,188,409,561,393,364,20,921,341,967,766,997,361,648,692,76,211,151,171,40,882,207,232,418,621,154,627,912,452,787,934,160,724,215,889,908,365,965,352,682,278,126,49,397,265,383,338,431,924,92,36,270,405,329,749,446,284,443,998,791,51,871,844,523,749,282,778,144,864,449,812,99,59,524,157,807,568,828,811,496,457,347,216,348,40,996,13,103,702,941,665,557,478,944,189,396,997,592,168,781,68,399,944,507,940,536,835,272,671,225,512,766,935,380,782,35,178,270,94,224,860,254,731,464,14,710,985,943,901,525,481,879,788,41,165,526,160,616,89,317,210,519,917,510,974,22,299,724,509,790,264,994,984,126,695,270,99,761,902,873,204,775,547,134,682,135,522,372,882,216,632,691,214,865,937,566,961,658,920,885,841,861,402,488,711,999,417,399,784,467,471,55,695,785,735,758,481,50,743,826,735,642,989,179,777,979,576,113,390,151,60,541,21,796,370,523,796,989,448,214,389,378,619,857,812,81,814,61,638,17,696,361,331,727,787,656,437,863,686,835,650,324,715,15,812,294,366,614,893,498,325,576,515,498,658,98,443,554,768,259,509,623,705,934,499,785,538,280,125,800,82,895,881,421,708,592,47,556,566,617,822,141,262,884,514,115,17,773,273,937,674,102,643,266,658,633,15,471,693,186,308,347,329,919,197,67,586,604,582,919,800,793,973,887,751,26,901,237,702,201,554,65,697,630,777,741,152,432,621,190,515,293,238,245,607,185,235,585,683,775,268,846,28,494,929,713,238,829,216,334,581,0,172,837,804,582,595,472,837,427,742,788,381,769,382,808,460,796,283,785,383,707,700,107,157,943,291,255,299,314,960,602,142,518,218,60,543,886,40,381,130,928,307,359,430,303,153,148,856,903,475,742,494,762,969,404,883,671,17,573,289,713,938,910,812,693,291,524,11,659,72,268,266,352,579,698,424,516,512,821,344,170,976,730,391,637,50,870,762,356,537,743,771,103,318,762,193,680,623,913,646,390,515,870,552,282,560,986,962,502,280,802,797,307,693,843,394,556,656,133,653,715,929,388,883,692,590,239,105,843,485,189,736,147,949,780,46,273,675,193,966,198,171,684,141,944,216,938,984,877,104,5,638,144,862,342,902,709,742,834,208,234,324,351,813,746,788,165,183,121,492,319,114,358,393,835,190,945,637,465,419,934,599,432,567,429,512,490,265,581,622,681,5,634,399,807,705,739,336,483,697,806,984,792,360,26,404,48,233,841,245,898,420,558,677,521,250,392,391,462,328,978,663,864,666,864,956,548,219,275,511,358,179,987,580,394,253,601,647,108,202,237,590,23,462,39,384,203,33,93,514,928,297,905,637,312,345,751,382,959,692,285,867,734,51,473,809,987,451,898,986,863,554,291,481,931,514,608,403,167,692,109,926,777,873,853,2,22,855,479,775,547,816,810,348,297,747,702,11,666,457,194,316,174,183,39,144,350,505,549,28,879,748,511,554,585,849,723,438,557,695,861,696,361,44,638,458,736,873,283,124,926,825,135,731,402,481,881,903,459,571,270,95,610,589,444,304,877,567,72,262,879,391,826,56,943,125,743,140,218,159,397,978,397,159,631,680,907,102,546,840,591,856,411,747,33,455,470,612,430,9,783,689,470,155,764,805,177,394,173,667,836,815,766,603,571,102,652,501,338,204,353,588,487,926,513,610", + "21,687,753,19,44,11,258,548,830,607,83,52,570,521,514,65,186,493,440,703,830,141,710,856,623,957,409,915,296,772,747,977,528,676,927,876,698,887,320,818,292,575,182,68,91,114,128,634,346,502,203,78,771,914,643,485,965,220,348,962,383,546,640,531,118,598,520,131,655,820,7,752,981,149,870,218,726,553,673,696,882,671,338,818,656,304,230,44,753,918,249,703,562,322,434,759,345,598,193,335,170,680,741,117,867,451,299,49,125,435,491,826,405,474,404,177,908,136,153,17,745,862,202,782,174,955,906,27,373,900,46,536,365,813,414,444,128,377,681,12,825,259,321,123,544,22,817,676,968,646,58,878,893,541,290,161,285,182,541,512,437,282,886,488,473,773,328,746,883,850,74,417,447,515,412,783,270,154,44,640,518,90,560,323,543,885,478,809,246,563,368,483,137,816,397,793,60,293,797,441,871,914,296,278,40,116,732,522,589,889,749,606,747,480,523,984,627,383,87,718,635,688,294,771,165,985,383,839,797,640,282,241,628,666,90,628,577,109,45,350,109,262,662,583,78,6,707,151,493,381,732,259,99,292,538,398,717,101,792,164,410,976,597,693,745,835,284,669,249,585,764,307,865,529,445,565,536,571,731,808,665,5,884,964,33,670,701,704,200,795,588,989,607,13,531,982,509,278,263,642,711,933,696,792,696,622,183,358,374,372,553,959,183,37,19,126,90,936,715,93,669,373,297,537,792,603,821,799,46,797,490,156,147,833,244,414,658,157,358,274,449,543,967,151,379,96,735,159,274,116,219,819,243,842,255,835,756,690,557,781,619,219,164,412,369,787,397,890,200,67,109,260,870,998,551,141,878,789,27,613,263,718,195,173,610,97,237,331,490,64,617,151,560,695,2,209,103,882,261,468,838,512,84,438,799,977,812,477,927,495,362,215,861,899,786,35,957,443,602,268,29,826,831,685,987,170,188,555,811,532,300,42,795,814,184,434,327,484,44,704,108,577,512,828,783,707,541,725,279,902,270,600,990,950,742,510,482,379,519,432,577,365,633,811,501,39,599,161,829,921,604,369,227,163,692,555,549,756,727,157,619,133,333,300,371,126,87,732,111,986,345,953,936,995,245,70,693,546,368,729,644,632,951,622,582,116,939,527,208,806,917,555,644,469,178,671,135,374,499,414,937,304,769,322,214,184,798,430,269,752,790,502,275,470,581,930,677,719,830,62,699,69,607,227,778,832,509,477,99,171,16,898,775,474,520,127,598,85,880,623,284,792,716,798,952,319,528,339,906,249,62,881,822,940,576,187,304,47,909,99,146,915,544,793,515,104,990,817,825,888,995,788,59,597,172,0,696,466,730,353,861,206,604,257,902,19,490,35,188,581,881,894,151,490,181,314,562,860,211,474,205,115,393,530,674,796,304,731,506,309,347,540,608,332,782,789,246,256,63,680,493,745,126,291,709,360,124,29,416,966,746,736,26,332,526,84,5,111,618,412,4,120,949,531,179,331,427,915,901,443,320,490,911,91,586,405,352,150,670,107,509,789,756,293,901,67,890,408,578,26,945,916,775,928,341,275,868,894,351,527,622,997,82,715,757,659,811,113,173,936,987,227,246,854,557,756,600,14,741,845,104,450,371,868,243,738,517,510,259,508,273,52,840,226,554,154,537,551,801,965,687,385,760,865,833,420,904,85,363,270,418,241,189,899,82,207,546,633,961,829,65,474,818,593,998,784,636,314,537,842,479,673,83,408,398,470,356,754,242,398,589,311,271,83,565,635,660,847,205,176,210,583,387,716,29,898,859,794,533,304,846,372,130,856,78,64,661,940,496,294,496,493,207,16,873,744,555,791,999,676,170,988,124,327,805,345,889,348,12,488,562,695,185,955,212,12,369,246,952,349,726,452,863,566,366,109,339,361,57,177,951,975,526,189,744,614,16,877,475,53,317,490,151,387,746,365,614,306,645,789,810,925,482,444,446,783,587,559,497,491,639,482,445,124,561,832,515,81,478,846,166,786,409,230,566,345,160,727,109,501,231,181,526,696,446,920,163,909,350,696,804,417,994,720,636,864,443,116,59,306,465,803,141,511,815,861,59,361,664,182,957,473,440,9,741,123,865,826,777,226,562,475,494,721,10,477,652,329,855,460,366,270,327,64,676,191,109,740,164,539,340,357,738,539,865,350,740,58,671,367,814,24,864,7,631,298,564,746,440,801,506,108,368,711,594,88,658,880,923,690,972,410,114,500,461,538,617,839,758,727", + "620,681,83,933,731,383,144,290,339,104,236,324,141,785,377,339,871,425,137,276,856,247,39,275,651,512,492,839,888,474,98,999,811,647,398,245,86,452,677,14,959,576,151,83,784,487,185,88,82,363,523,285,169,137,275,458,261,436,475,766,255,366,763,684,194,642,896,939,715,468,683,709,531,692,602,675,486,184,889,419,624,2,555,72,700,30,878,977,975,390,42,587,488,337,584,695,64,82,439,297,237,795,272,216,889,821,69,893,203,735,801,107,702,916,717,159,817,776,86,545,99,947,343,980,972,616,440,312,545,852,775,329,640,978,918,585,493,356,864,763,634,759,412,335,631,597,400,855,395,907,216,949,358,864,489,524,684,969,237,411,143,780,346,395,879,405,12,202,134,879,542,722,976,100,616,640,379,947,964,799,889,401,330,740,69,151,550,822,230,999,247,20,256,637,593,641,951,236,693,669,915,818,494,212,777,148,470,863,305,31,967,932,7,394,648,104,343,279,413,801,829,941,578,816,99,198,161,485,757,569,764,199,880,930,985,470,867,825,937,591,276,438,145,172,898,202,926,300,294,907,947,573,455,461,449,314,629,242,685,266,493,669,647,416,985,636,428,351,859,581,37,957,399,585,822,796,710,576,933,930,424,974,626,741,203,284,893,764,355,56,797,34,725,350,3,626,227,809,917,914,590,165,41,460,289,658,766,823,861,418,327,81,10,789,224,810,112,212,582,422,839,562,405,337,11,516,778,585,907,684,672,184,229,252,690,727,886,551,114,986,514,143,63,679,176,464,884,23,974,283,255,33,421,498,779,687,399,285,636,995,109,664,356,548,856,229,740,328,385,680,713,730,763,818,412,387,48,299,284,942,636,561,250,777,29,257,602,530,502,145,529,656,329,503,657,356,20,863,286,740,955,609,323,926,358,123,883,397,822,714,248,731,375,89,890,556,564,119,475,244,124,92,659,547,969,452,983,582,909,631,854,554,153,591,909,490,826,295,893,38,414,468,384,2,757,877,555,340,771,342,957,522,223,296,428,242,809,631,931,526,863,844,482,639,791,462,88,553,178,653,530,8,961,555,587,634,577,744,230,161,806,795,657,603,133,760,778,208,644,783,753,884,25,316,618,427,142,241,132,773,129,451,343,534,186,751,238,981,161,131,449,130,828,851,301,664,869,658,820,445,194,377,286,230,474,143,767,202,551,509,305,841,682,375,168,292,528,954,154,34,658,720,193,47,568,405,553,662,553,588,655,822,200,210,149,281,94,289,176,327,395,685,503,182,245,228,124,167,645,336,120,206,933,725,640,203,293,263,868,751,992,885,443,567,346,132,550,684,799,832,485,454,94,504,837,696,0,660,886,754,210,560,909,422,525,306,528,980,657,288,31,774,535,799,504,808,741,496,839,204,546,277,557,564,912,259,206,318,253,896,695,236,846,41,70,414,142,343,735,831,966,602,477,881,865,761,595,769,868,346,438,829,172,173,967,472,296,36,151,443,653,239,702,557,113,19,595,452,689,167,848,685,327,613,870,252,924,188,119,267,261,310,341,393,963,401,781,650,235,624,766,669,531,585,702,523,370,44,846,666,944,516,560,208,790,450,527,370,882,160,356,1000,746,598,902,430,773,263,620,577,786,685,154,322,793,49,197,671,751,375,874,864,199,972,200,320,540,130,760,45,375,557,233,63,650,538,457,579,377,920,567,207,359,791,899,994,567,905,864,32,527,219,722,975,346,917,653,229,150,857,537,219,592,905,749,423,29,556,806,680,169,53,554,402,57,644,130,46,551,360,825,911,514,978,61,332,801,968,121,407,62,355,247,134,421,166,189,300,514,116,655,967,672,338,478,442,426,499,124,606,597,153,20,278,782,473,337,583,968,257,582,437,785,698,7,736,912,957,106,462,513,698,888,3,555,579,775,974,750,777,911,151,713,216,321,439,68,404,156,587,733,866,934,788,316,589,417,789,177,22,557,251,357,679,114,911,381,401,402,205,407,961,487,625,55,737,119,367,938,8,643,191,628,309,644,52,688,313,618,252,653,290,588,325,465,985,311,918,148,972,870,992,127,359,5,903,765,163,443,680,178,882,280,533,364,340,848,629,310,123,458,409,914,788,31,198,456,849,748,657,703,578,379,25,277,57,281,979,182,400,573,242,309,639,365,860,526,150,247,694,195,378,717,784,106,622,777,635,842,475,205,568,258,436,26,979,860,845,205,356,542,707,218,502,32,9,38,869,569,458,449,315,768,924,831,36,116,25,218,756", + "89,883,245,650,780,482,518,458,453,109,868,884,53,376,364,430,218,713,894,686,201,352,584,981,635,854,252,794,438,690,470,941,122,50,710,310,862,667,307,873,991,398,531,404,830,655,287,86,233,230,425,759,749,181,111,253,968,167,515,409,101,225,206,45,391,483,149,277,38,433,24,931,39,687,742,187,58,23,409,502,201,738,337,735,868,213,356,248,442,200,294,618,428,967,981,364,301,419,392,166,690,309,530,58,346,85,513,60,105,533,783,471,304,843,783,459,675,726,612,847,492,404,955,724,421,545,417,260,317,140,774,619,150,150,246,716,161,105,284,431,380,869,545,788,76,296,426,392,679,351,458,65,888,215,27,843,640,54,976,464,767,419,558,19,330,247,968,200,408,710,627,239,968,888,164,725,724,132,361,372,280,350,958,470,537,6,902,34,483,200,504,407,313,638,771,202,961,980,854,915,869,707,224,471,456,990,451,562,993,803,39,575,413,595,691,654,787,775,323,787,392,129,983,876,289,7,407,518,184,622,87,209,541,135,36,538,580,411,153,161,897,17,572,565,420,932,295,624,703,242,791,301,31,699,564,689,326,437,392,539,542,286,800,484,488,236,621,114,313,976,648,529,864,864,79,24,163,630,762,803,869,132,487,880,634,782,443,433,30,358,743,170,288,672,818,578,457,451,327,79,281,562,768,611,644,411,849,330,405,845,306,421,856,457,173,441,62,181,244,366,322,445,555,349,681,610,830,908,498,304,685,803,995,449,722,153,730,612,74,297,937,689,913,556,13,108,81,283,433,655,327,356,766,828,744,583,443,987,729,36,419,287,643,149,88,146,923,544,996,654,765,497,725,950,286,274,307,334,543,5,382,81,846,48,835,101,665,106,35,204,103,384,985,584,16,291,212,575,986,273,672,375,801,594,296,288,530,672,397,312,236,741,470,190,741,701,747,908,127,823,255,336,646,410,770,290,185,500,130,595,158,755,663,251,925,920,180,338,481,602,897,730,939,547,89,767,797,835,712,969,344,19,627,293,493,509,964,414,620,838,315,114,763,30,562,206,779,74,7,825,771,367,168,785,807,286,980,145,183,366,411,801,754,436,590,538,538,565,551,618,474,616,659,23,827,955,491,33,508,262,127,606,633,887,288,507,103,628,731,585,682,229,756,461,526,850,236,351,238,705,285,354,260,682,798,241,171,64,132,911,921,623,708,765,608,305,266,183,593,229,556,83,138,398,949,64,426,541,212,308,294,284,173,232,446,945,941,779,512,229,390,792,351,568,833,271,693,166,671,847,948,214,76,697,619,204,795,223,695,701,265,46,174,240,946,167,608,699,860,16,604,988,894,7,804,466,660,0,453,687,537,577,723,421,675,87,770,60,981,806,239,158,685,380,515,450,781,608,896,311,988,91,685,70,791,906,130,981,688,522,808,909,722,16,808,650,789,83,356,266,534,157,406,325,755,72,155,609,13,703,27,832,474,464,91,604,860,661,62,153,674,229,962,281,710,123,512,352,241,647,516,721,456,556,156,351,253,873,519,802,711,750,248,144,394,172,277,331,280,347,125,627,958,217,988,151,512,234,936,504,833,289,72,835,436,806,674,479,531,367,574,191,970,308,94,36,8,393,180,736,814,218,999,231,100,554,753,15,43,419,165,277,958,239,309,668,918,278,291,683,353,701,471,51,158,389,856,493,607,87,944,882,849,599,438,544,303,274,78,940,147,245,863,627,484,626,868,442,830,798,96,603,501,677,660,680,963,786,662,278,494,650,278,466,329,432,708,484,533,549,492,377,391,220,757,249,95,865,131,698,591,300,962,424,84,964,199,701,313,330,944,287,380,427,410,879,675,872,605,779,580,663,571,475,626,985,356,531,413,563,942,825,455,897,472,157,637,249,531,862,207,511,608,837,110,83,667,140,914,135,271,282,231,92,628,30,552,165,620,1000,355,42,696,783,198,395,211,213,906,40,234,915,444,217,650,122,165,968,281,244,979,967,569,768,224,668,746,237,965,911,428,336,886,596,89,887,530,906,811,527,470,774,70,528,268,873,377,435,596,120,389,592,746,315,702,391,997,638,791,646,132,257,218,69,416,906,501,789,517,948,723,140,321,758,758,257,13,573,946,664,293,263,183,645,594,219,615,772,825,566,381,195,945,551,877,576,717,339,821,661,919,120,678,635,709,68,291,661,523,840,555,734,681,454,135,513,596,32,963,735,11,712,673,528,777,571,868,253,928,211,238,112,654,312,986,833,670,831,924,647", + "319,888,967,97,416,235,979,762,510,824,375,702,681,694,212,420,939,923,405,588,401,118,174,403,385,819,300,280,760,583,56,153,635,762,28,696,962,389,630,371,253,429,290,604,45,584,223,906,73,211,431,873,31,690,520,31,53,474,617,355,195,179,833,196,27,190,120,834,525,765,334,599,101,678,683,89,33,420,824,408,850,333,293,938,104,361,515,343,645,214,9,84,409,304,46,874,67,389,920,781,454,996,414,195,550,162,47,473,72,852,990,614,888,220,255,989,665,138,157,220,70,592,254,167,165,284,595,348,994,937,998,743,395,199,698,34,517,344,182,640,61,259,826,721,91,453,230,450,447,737,87,1000,905,19,552,8,752,352,163,890,861,860,984,615,629,156,684,323,544,694,1000,670,965,110,913,133,610,246,410,119,462,13,716,369,609,194,202,910,182,786,548,462,756,19,497,711,341,923,59,925,221,870,701,526,763,224,43,485,100,688,635,500,414,913,365,467,911,12,660,968,57,617,572,427,382,61,407,160,268,821,304,763,507,372,876,913,188,507,211,406,932,470,444,776,290,649,773,979,730,312,454,49,384,284,269,160,234,687,408,594,183,343,422,572,835,840,84,465,920,64,966,289,492,470,870,835,765,625,698,856,440,185,795,519,62,119,9,265,592,489,364,199,604,441,576,424,468,736,757,218,801,271,295,98,574,180,394,272,147,176,719,391,458,330,900,802,927,388,634,927,535,138,465,785,698,985,400,956,940,129,99,99,405,18,638,265,374,354,154,187,349,547,927,596,405,119,939,221,861,4,464,839,78,439,772,623,326,25,7,296,202,238,910,451,884,266,79,992,319,99,530,583,115,156,106,290,912,101,370,178,295,469,619,606,503,995,392,716,782,675,165,669,499,966,360,101,381,403,6,444,553,655,404,726,135,7,689,17,806,270,749,469,578,593,292,536,874,463,825,735,227,277,335,335,113,678,667,486,560,308,12,494,264,26,588,987,598,424,355,974,514,673,652,682,683,243,680,889,62,611,127,518,827,681,530,8,70,419,411,791,955,35,82,787,41,274,602,451,817,591,49,92,908,969,661,299,478,296,248,805,156,673,624,863,906,192,766,561,805,365,554,983,474,502,296,880,237,621,813,392,414,964,332,70,918,103,373,355,135,995,475,566,874,318,993,67,869,480,814,647,553,935,924,599,777,445,839,586,780,628,749,483,351,355,34,710,441,90,406,200,710,49,719,210,674,130,640,901,289,782,551,352,137,988,989,805,626,691,819,48,717,976,54,312,869,114,693,975,997,386,702,160,4,967,503,226,272,397,840,453,817,929,66,904,378,67,226,958,605,946,67,462,836,641,582,730,886,453,0,30,645,452,144,695,182,368,42,13,572,393,742,284,837,146,206,308,329,60,355,815,512,718,790,852,130,386,492,795,73,361,619,949,448,422,133,593,322,161,265,580,571,965,882,490,829,731,966,439,725,371,327,486,803,153,919,991,502,438,656,75,929,4,253,718,103,624,810,7,802,343,289,961,285,560,79,959,543,758,181,385,132,797,225,53,51,976,593,791,525,342,283,633,553,898,833,749,194,149,401,131,935,744,150,474,447,53,525,439,112,820,121,815,553,50,698,492,736,499,440,391,243,851,779,712,447,516,924,865,630,350,375,959,641,454,56,228,356,190,45,242,874,672,296,940,170,926,713,116,630,92,866,885,122,883,655,150,810,795,378,988,40,92,995,189,478,408,508,497,677,571,303,866,687,219,527,951,475,915,125,242,909,112,992,604,613,571,901,922,396,150,542,406,844,40,87,246,586,854,407,561,200,853,207,665,468,219,321,730,652,909,921,28,144,522,86,931,756,714,449,484,823,496,974,122,986,753,545,41,725,425,427,143,216,366,661,981,347,431,972,165,106,790,914,783,72,889,705,413,493,922,142,845,950,297,65,685,55,80,337,489,90,129,647,676,942,590,977,290,637,925,769,164,205,414,643,634,737,306,331,558,786,64,444,325,63,514,114,809,668,90,343,589,666,564,941,865,948,889,153,742,965,535,1000,822,344,217,630,271,131,653,345,519,339,286,237,871,442,395,212,34,961,830,821,963,667,569,602,103,885,36,460,197,347,992,489,430,701,9,955,492,61,177,896,665,907,441,708,967,617,962,377,955,669,790,579,169,397,365,314,291,383,471,942,547,47,307,778,594,760,47,681,517,652,485,927,445,852,934,303,545,467,996,128,708,515,557,767,843,807,928,275,724,109,255,119,159,474,185,853,292", + "557,13,253,166,806,373,486,361,86,523,52,264,855,912,820,553,80,568,87,71,356,203,529,470,680,167,205,819,860,802,829,420,617,312,540,405,254,980,469,319,865,34,424,359,714,174,21,908,510,56,661,839,115,964,688,340,836,801,187,200,363,669,542,537,517,827,576,526,145,447,396,81,270,452,776,838,67,358,62,822,739,770,317,818,336,427,990,879,914,653,90,728,993,130,709,848,270,38,357,232,320,518,798,483,652,33,898,181,540,256,707,758,454,952,467,252,529,512,741,996,612,339,212,619,485,10,998,978,484,842,238,312,712,830,804,953,357,469,345,956,438,628,83,35,651,56,981,90,775,185,441,290,886,150,362,880,768,34,509,377,91,892,66,246,947,387,933,675,466,114,979,863,240,876,119,711,381,678,339,798,773,32,28,951,146,286,467,230,22,931,791,960,221,842,511,168,581,534,497,256,536,441,80,57,160,911,361,992,624,176,333,603,924,48,526,352,549,228,154,213,342,981,31,84,846,406,3,457,971,833,84,572,885,835,893,16,870,180,675,885,777,502,872,497,280,308,428,752,145,433,862,818,149,216,438,693,389,194,227,659,800,452,873,175,656,814,481,911,863,601,579,698,140,957,316,274,917,304,204,710,637,762,843,309,93,15,382,52,339,779,724,443,38,577,258,178,323,862,95,638,258,412,924,955,677,690,395,392,66,32,636,161,159,234,602,80,386,649,894,788,328,611,65,683,330,613,524,571,458,350,423,736,977,890,390,513,312,31,91,8,548,372,81,755,129,631,651,489,987,362,616,105,13,549,97,398,477,827,976,762,889,410,526,408,534,143,724,251,271,895,858,20,749,857,531,246,288,522,72,346,394,586,660,146,200,37,309,387,787,39,53,933,276,101,438,664,672,448,599,131,661,692,41,481,761,552,251,125,89,85,589,591,136,138,364,824,42,718,655,61,624,998,980,956,313,277,596,122,629,538,953,769,902,937,146,236,841,433,359,708,76,895,179,293,881,155,913,143,952,141,729,177,893,417,764,534,340,173,638,681,819,767,677,674,396,186,611,665,453,985,638,348,973,525,252,163,537,373,752,210,584,524,820,429,75,810,917,141,155,292,993,125,706,334,447,604,673,96,569,337,42,650,524,826,384,862,129,678,851,702,536,359,66,181,225,922,916,413,620,465,700,944,368,134,903,262,422,799,33,697,658,80,672,329,626,722,328,110,62,875,74,246,992,531,45,989,380,254,779,633,130,943,390,999,524,251,56,902,424,464,850,920,176,938,896,524,24,272,762,866,943,995,622,772,125,752,319,986,686,402,632,420,782,905,511,788,750,510,455,615,769,186,260,722,595,353,754,687,30,0,790,62,966,786,136,278,343,629,778,861,844,915,460,459,844,929,925,341,655,977,110,639,724,665,761,342,41,496,111,739,990,747,682,670,308,749,385,828,368,208,796,983,859,340,533,900,718,235,132,219,753,555,50,560,663,129,125,611,959,258,230,571,692,291,654,140,7,733,173,934,252,814,815,857,999,446,112,161,228,640,340,916,119,371,708,70,956,568,322,614,813,913,204,530,585,684,679,792,825,401,525,209,606,7,735,302,454,75,453,330,669,896,109,261,409,883,260,678,298,243,379,333,532,291,520,565,512,562,393,678,973,719,517,391,596,990,478,323,738,904,280,141,748,571,881,747,204,969,886,805,937,685,522,9,687,949,191,1000,785,430,718,820,994,44,344,267,381,455,910,735,791,233,673,553,914,877,865,616,867,331,487,177,933,479,662,877,61,347,318,17,105,794,411,38,230,469,390,313,468,8,260,98,392,684,393,17,369,34,493,627,383,553,859,116,371,280,690,528,149,93,495,686,899,99,281,966,785,121,742,776,217,783,281,5,467,10,620,21,388,76,518,983,134,426,842,899,531,856,775,881,268,37,643,826,199,25,476,666,870,695,929,686,921,812,851,934,599,559,230,99,294,971,29,864,947,828,747,304,177,95,63,693,508,539,940,572,824,666,462,361,229,107,247,405,235,632,151,470,790,67,826,382,571,359,232,514,177,558,483,837,380,407,87,817,165,717,611,819,54,3,909,903,248,869,859,292,821,852,307,481,36,405,632,597,796,22,485,488,799,597,5,919,536,296,286,665,877,656,975,611,88,484,604,596,4,25,630,104,410,432,861,659,62,232,739,451,650,701,108,554,317,242,428,71,207,99,469,957,800,76,919,652,468,764,398,646,382,198,959,17,176,476,237,550,798,179,766,843,331,300", + "602,931,563,439,885,648,159,102,936,462,19,995,506,179,530,219,64,946,5,402,546,364,855,250,128,894,729,927,264,290,957,203,274,233,812,359,846,84,404,348,877,661,700,699,563,802,652,151,378,966,854,321,510,928,275,918,172,902,453,462,900,268,467,295,375,224,791,238,955,267,946,514,425,591,528,581,856,877,418,359,570,623,413,46,930,991,589,558,939,931,827,304,281,413,441,81,220,118,681,801,939,643,288,51,517,269,965,56,372,861,329,156,588,227,993,700,755,274,335,74,645,787,470,44,269,602,496,944,554,629,822,981,116,474,966,80,925,264,723,403,717,644,880,606,29,727,561,491,572,340,570,747,912,366,502,943,977,384,917,923,551,715,407,20,54,817,427,37,76,241,604,55,634,15,584,174,699,309,943,457,179,700,565,585,462,604,121,182,198,862,674,69,915,948,197,766,84,649,112,850,399,506,70,110,650,774,638,792,260,186,693,920,377,476,511,432,820,613,791,16,427,818,106,239,339,566,70,861,232,2,203,89,83,302,162,939,549,243,323,134,770,659,9,235,313,676,245,708,162,965,854,524,572,981,55,196,686,203,831,657,870,147,172,971,187,234,570,302,383,848,825,776,678,912,452,337,766,618,306,572,825,335,829,133,542,226,802,647,559,283,405,165,615,48,508,851,885,570,177,493,872,205,574,514,523,395,150,272,799,800,503,132,678,715,500,850,999,741,268,90,19,147,321,754,715,630,676,269,223,658,711,594,974,671,855,851,856,419,677,587,319,110,21,197,19,69,577,262,196,349,867,208,768,347,911,640,147,616,73,513,429,18,640,443,504,145,559,126,123,162,730,80,913,510,222,162,401,735,726,510,20,168,597,3,743,507,621,526,844,392,856,285,747,981,718,330,666,316,859,681,159,225,63,917,928,799,107,821,477,111,21,805,357,457,840,697,167,403,89,825,332,744,221,927,767,4,257,423,722,428,36,400,590,272,274,678,4,734,57,668,47,908,151,343,338,524,997,409,356,789,104,72,191,186,171,290,93,751,344,682,54,882,759,449,164,225,746,906,286,81,766,419,786,270,63,998,963,238,768,634,630,298,494,606,605,470,70,544,230,381,529,726,473,568,852,349,907,792,103,487,763,178,949,933,768,745,612,294,56,334,788,929,18,177,708,769,92,14,255,301,435,369,185,44,758,587,621,717,839,783,865,71,893,696,143,934,941,49,617,779,810,147,779,95,634,880,738,292,16,122,31,775,749,734,909,846,971,891,483,841,83,171,70,446,622,124,566,175,553,278,471,433,36,811,248,154,846,223,628,817,436,776,591,200,883,978,978,361,544,882,716,247,435,567,472,861,210,537,645,790,0,205,811,100,263,280,835,547,744,438,336,410,467,534,908,662,974,824,524,691,758,697,303,276,545,193,707,37,732,51,976,251,150,745,859,764,918,396,394,426,502,342,143,796,408,738,275,288,397,733,579,339,457,483,397,253,75,735,147,960,808,31,94,464,421,754,300,590,536,788,764,786,842,671,543,459,139,816,906,214,503,872,826,249,703,342,100,427,439,24,792,683,81,131,261,525,707,215,247,468,516,219,108,13,979,886,387,563,81,850,317,666,899,693,205,450,488,463,322,759,599,230,994,196,495,724,377,992,492,450,489,623,45,324,987,331,721,716,232,859,237,172,838,77,975,61,960,82,795,402,225,857,609,153,739,589,473,83,242,442,27,461,779,609,156,793,118,277,410,935,483,985,970,646,653,282,20,107,43,497,476,10,870,354,157,435,69,146,426,101,791,478,383,460,146,408,880,168,834,343,248,986,421,574,719,420,998,944,956,49,588,282,468,946,787,391,218,86,306,248,168,895,968,776,582,398,444,798,36,771,489,767,930,575,228,143,731,992,678,1000,380,14,901,286,103,577,690,420,771,754,202,865,602,996,61,355,152,929,227,555,535,925,397,242,13,715,901,115,102,138,940,388,997,552,586,923,36,929,491,785,974,607,131,92,990,650,664,919,887,187,856,480,705,856,629,619,973,526,455,813,867,530,993,517,7,465,743,484,111,384,765,858,890,953,307,725,396,605,533,919,153,54,727,63,731,290,134,851,474,82,896,453,553,224,265,311,193,660,313,323,906,529,821,470,127,949,318,308,743,441,322,631,124,437,537,425,18,128,508,391,812,545,96,264,431,684,81,747,60,929,772,938,385,11,387,34,89,109,630,674,692,611,176,169,646,910,633,630,603,844,658,581,177,411,801,163,266,150,53,637", + "206,804,736,746,332,206,89,840,575,792,495,898,410,624,428,722,193,776,888,836,127,424,990,869,34,215,341,343,889,49,678,192,742,777,589,871,92,799,240,421,898,756,116,603,664,543,174,19,917,319,961,619,802,824,588,415,376,233,484,947,235,479,278,641,461,273,392,568,43,203,798,920,710,174,349,512,558,513,352,471,873,951,658,321,925,583,22,989,562,520,388,230,747,400,843,338,475,776,199,991,281,498,965,886,141,473,310,996,105,555,249,600,556,518,461,590,623,807,959,283,585,526,28,676,114,820,275,718,12,826,943,642,572,446,948,300,700,310,856,656,897,57,70,103,21,87,157,438,616,152,78,921,881,222,487,246,56,705,539,823,5,159,754,423,56,708,845,917,364,243,227,812,422,682,887,423,592,357,365,867,755,521,363,61,788,150,316,928,292,51,199,22,392,904,544,823,266,135,397,721,416,777,618,940,598,73,142,778,317,565,85,445,979,233,843,266,846,332,817,399,306,505,287,481,787,543,647,592,67,66,936,15,282,909,176,38,253,45,631,707,700,21,392,776,882,200,91,392,807,792,997,55,4,944,653,491,628,411,451,458,10,391,420,894,595,915,335,32,577,280,257,66,722,39,221,856,318,13,370,717,477,575,189,687,50,148,631,545,748,321,814,778,61,647,741,417,571,865,691,556,381,393,317,617,672,256,517,821,646,45,701,520,598,456,911,941,515,281,269,602,334,138,90,716,962,418,718,82,530,442,754,512,680,665,666,125,378,21,596,348,97,772,350,391,326,708,634,122,899,277,425,293,885,227,149,155,126,685,573,746,235,772,659,703,573,883,534,190,964,274,29,634,480,137,639,799,748,35,278,460,672,773,603,731,51,389,199,685,949,188,26,603,4,944,828,271,454,715,424,558,504,742,208,785,970,611,313,169,175,837,767,52,776,359,201,754,145,704,496,242,252,212,548,145,524,401,234,912,995,186,100,596,178,905,604,956,20,738,398,419,90,424,932,593,242,807,283,269,690,88,968,851,36,966,744,909,34,167,355,879,640,370,147,721,202,124,224,376,505,569,148,593,621,582,810,405,596,493,448,198,401,132,460,171,754,581,893,964,54,931,917,184,678,597,914,788,865,151,379,692,547,73,416,426,722,408,751,904,596,596,982,515,64,587,381,718,196,829,26,283,460,249,243,828,567,240,434,435,127,419,556,772,397,241,8,17,310,98,405,978,829,145,980,852,660,984,523,755,86,515,533,193,491,134,242,886,44,434,506,563,808,125,584,778,349,374,148,964,531,265,878,891,124,314,674,773,163,274,808,13,22,780,495,273,816,193,864,60,459,542,464,131,466,373,837,206,560,577,452,62,205,0,441,217,98,295,178,986,709,755,837,736,521,888,313,912,367,672,261,366,237,513,918,466,376,103,856,116,974,676,690,617,948,527,853,341,877,444,231,572,414,457,308,287,394,943,943,70,811,449,654,990,779,119,327,195,362,247,881,866,452,576,360,778,306,413,22,23,753,758,3,501,609,346,984,413,635,58,389,688,216,414,713,796,996,117,510,975,442,646,792,485,297,49,43,990,519,637,66,253,207,502,366,918,464,600,979,245,599,845,567,775,375,128,340,54,475,105,34,405,526,392,456,568,400,328,735,673,522,110,275,142,411,604,594,26,940,188,517,993,942,40,853,134,856,147,120,6,631,469,515,616,831,103,138,138,771,166,84,243,912,140,266,927,139,621,28,868,454,186,499,784,909,82,454,879,771,701,260,814,595,857,717,970,727,710,689,136,808,255,400,825,144,232,302,209,369,417,571,707,898,836,244,675,582,804,909,283,914,407,510,62,170,705,117,948,891,544,643,814,733,56,3,492,664,798,129,662,602,124,487,617,857,271,773,50,859,346,415,77,626,406,818,725,174,737,302,95,721,16,432,974,306,744,268,745,950,287,695,218,919,16,543,526,330,148,892,991,217,215,210,734,666,604,380,186,692,68,789,569,991,725,253,829,882,595,173,333,537,918,11,406,128,336,18,505,272,210,37,161,419,822,470,171,223,362,361,451,975,759,626,235,825,190,657,359,125,757,625,738,450,811,208,50,283,255,454,398,374,520,233,660,732,9,792,140,470,145,312,28,649,668,928,499,700,596,108,149,805,481,535,97,427,270,425,624,937,84,879,879,628,596,360,453,870,971,826,428,976,602,11,44,773,648,616,674,654,943,471,898,741,656,382,199,871,820,280,445,185,625,939,184,973,922,309,286,642,909,151,299", + "759,158,880,837,663,249,91,516,882,39,503,149,781,802,632,125,554,602,630,374,483,151,665,161,806,527,663,172,384,558,76,820,306,858,532,853,542,406,844,398,162,890,410,991,277,178,69,480,67,35,639,294,761,262,223,381,808,145,838,678,549,230,231,425,527,897,81,629,783,404,667,708,826,890,622,941,30,219,669,950,302,677,273,574,571,831,318,263,700,222,567,995,713,836,565,245,495,442,821,992,954,73,987,642,850,309,918,792,286,299,54,765,346,183,23,746,824,470,126,78,270,854,73,202,751,894,802,599,821,151,602,676,127,598,341,847,58,339,479,413,985,110,828,62,801,622,343,260,301,913,592,59,87,918,242,739,845,478,448,616,829,655,345,282,785,804,619,462,23,321,547,317,320,428,321,861,681,74,938,672,997,421,712,852,591,400,333,636,841,46,515,443,658,345,766,510,417,770,415,164,366,113,633,922,919,609,910,152,493,448,566,136,618,623,933,541,53,170,86,204,379,768,869,527,356,281,194,11,773,446,869,491,197,886,867,18,260,52,880,209,118,141,374,233,579,707,928,102,104,95,184,381,853,944,702,751,680,529,622,217,71,960,65,506,899,702,751,800,730,653,603,807,343,359,126,118,326,157,158,114,691,551,180,502,305,63,70,227,243,520,362,45,113,754,796,403,892,425,904,542,982,927,281,122,857,436,823,316,20,998,561,263,597,961,723,28,513,194,122,48,795,740,799,229,285,375,636,561,654,941,760,962,851,655,306,457,753,890,963,228,123,31,761,676,920,101,951,372,85,704,56,647,382,964,54,633,861,238,657,484,323,681,221,330,447,166,534,861,276,794,99,65,277,196,897,580,448,276,153,665,402,211,513,798,878,71,647,609,390,268,347,457,390,593,129,381,255,945,814,920,950,107,754,855,537,41,632,531,311,182,354,160,272,261,402,859,975,102,623,45,396,173,895,480,997,54,269,284,102,513,705,566,680,910,819,204,383,913,799,151,622,442,390,384,160,342,154,935,757,808,8,980,423,511,441,430,655,787,910,344,763,526,69,703,476,247,28,559,667,484,302,128,512,554,639,932,521,797,610,262,601,510,764,863,320,389,516,608,525,585,167,322,691,773,468,843,361,414,231,224,873,114,150,670,652,865,255,916,464,678,422,341,586,684,679,861,641,439,480,969,914,818,428,482,501,239,876,874,638,357,335,264,28,37,790,387,253,275,40,579,904,118,332,560,618,622,383,656,229,857,527,20,6,545,984,851,729,609,158,248,444,457,636,425,883,92,425,416,268,493,956,443,648,636,596,162,447,769,340,989,960,735,681,745,922,875,424,965,115,347,878,410,51,745,427,604,909,723,144,966,811,441,0,630,155,683,288,86,30,888,515,160,790,400,701,45,872,594,360,148,72,92,363,988,708,591,136,814,53,926,295,640,730,634,607,374,790,818,434,151,622,122,182,933,812,538,793,203,735,981,368,252,870,326,83,100,741,669,561,788,326,492,958,547,27,356,366,41,633,766,556,835,252,526,452,465,606,169,732,52,584,480,88,883,814,243,636,164,345,598,549,242,46,7,616,304,944,25,178,758,62,674,289,459,377,155,414,555,882,90,225,622,433,849,927,263,219,491,229,287,17,979,365,78,666,896,443,525,513,752,731,498,134,22,628,710,575,372,758,890,71,772,654,424,560,113,920,90,175,772,564,679,771,374,600,431,393,5,77,982,233,574,782,193,182,71,208,488,100,252,881,837,69,913,893,439,511,207,61,610,231,678,989,583,342,58,1000,506,745,638,764,636,631,454,860,682,344,432,51,649,958,354,550,812,493,722,189,906,273,154,503,694,562,331,683,104,646,386,419,102,744,774,732,964,950,184,38,691,583,143,61,765,843,577,628,477,443,418,909,189,262,858,228,164,994,275,540,689,159,22,967,771,838,307,210,912,185,315,280,434,378,914,840,949,46,884,377,535,271,881,773,183,854,556,338,452,353,861,214,483,841,745,572,770,166,198,889,829,888,44,271,135,603,590,537,244,643,919,34,657,534,694,856,630,645,276,511,897,723,797,50,456,589,233,129,454,777,178,356,775,88,292,256,491,487,438,725,999,684,411,176,874,424,354,626,85,251,277,121,749,340,350,856,714,38,43,554,239,322,401,737,77,462,534,386,360,406,462,986,530,257,292,249,986,907,126,848,335,309,667,414,129,213,902,969,49,496,43,563,793,901,26,52,793,80,499,37,654,156,857,330,972,860,570,100,606,171,415,23,87", + "638,451,519,697,999,417,168,904,18,937,458,493,464,145,408,239,572,832,135,416,55,709,746,989,148,374,368,191,675,232,648,505,242,434,540,994,600,183,308,13,886,90,162,841,429,778,770,807,257,463,471,462,36,3,311,315,187,109,822,954,524,24,544,570,562,862,640,701,844,468,797,157,627,845,402,17,297,783,971,746,726,887,876,143,518,993,199,105,273,554,490,549,531,248,394,692,515,699,528,491,854,287,124,108,228,559,681,395,276,437,298,777,540,965,957,625,834,52,697,697,255,836,356,484,2,921,756,779,651,642,500,457,384,687,426,452,790,997,872,523,687,476,905,746,726,928,929,959,223,390,840,555,133,543,930,665,187,600,324,342,114,63,750,130,655,780,822,76,895,958,240,626,822,961,15,635,37,72,500,380,187,161,95,707,224,44,854,716,712,330,928,585,613,459,758,111,617,872,481,633,23,192,839,259,724,191,959,884,552,566,14,51,178,619,197,156,300,43,743,460,617,791,476,491,931,791,9,499,951,816,209,773,239,926,102,789,132,247,519,607,648,715,652,748,186,533,452,572,466,80,206,557,697,20,8,53,949,508,359,545,542,587,143,76,848,599,768,801,139,267,890,632,554,533,575,718,822,584,70,969,508,384,583,686,801,358,33,607,573,899,623,345,226,215,553,777,53,913,485,100,892,336,717,325,148,428,548,932,800,27,631,408,347,549,24,664,649,88,244,538,422,440,81,439,249,300,497,106,337,576,556,984,599,529,946,367,431,447,33,76,185,249,185,998,653,30,834,526,658,337,532,519,549,991,500,405,678,577,84,111,953,577,94,420,183,667,928,502,884,841,388,885,313,692,748,62,971,508,97,419,53,676,442,94,892,985,800,926,64,750,81,670,222,305,221,298,440,236,862,184,321,63,335,373,400,655,986,293,973,941,7,828,439,724,991,724,317,468,925,686,372,490,617,333,637,143,913,669,957,820,528,954,343,478,685,384,398,925,801,994,342,642,966,829,384,534,996,878,295,389,289,716,839,347,256,978,693,622,821,500,119,186,29,837,885,112,434,904,303,930,649,449,935,312,758,79,694,86,413,856,916,141,807,99,981,798,77,490,116,605,414,491,588,342,576,315,795,570,146,616,416,232,308,525,886,156,521,889,912,366,369,649,106,131,800,452,489,341,775,724,252,154,982,612,210,68,798,254,402,886,896,347,76,849,847,78,17,856,192,325,376,369,218,94,295,137,987,931,664,878,209,960,691,382,912,573,174,78,324,47,616,361,530,481,217,534,314,599,191,585,576,963,548,922,436,59,8,866,694,398,482,103,389,866,847,852,675,360,696,549,27,799,866,952,742,257,422,421,695,786,100,217,630,0,535,124,768,716,821,265,904,921,5,520,843,911,43,150,919,868,66,990,11,52,343,906,600,758,512,982,875,164,536,151,368,984,980,395,714,625,847,717,58,245,980,270,159,140,432,676,677,543,5,973,334,759,398,399,396,513,587,366,657,34,987,409,650,243,308,272,470,640,548,160,743,743,532,317,216,717,495,690,309,771,255,316,440,398,308,97,891,368,742,192,534,627,889,447,46,151,75,492,434,567,865,963,133,280,669,64,113,359,511,661,370,695,888,25,200,152,536,537,92,383,305,240,2,262,188,998,158,990,25,595,630,31,429,134,243,216,207,588,178,248,922,665,806,622,134,676,952,272,440,568,940,555,888,212,934,553,18,147,941,76,806,687,744,784,644,20,625,296,554,369,729,854,942,809,556,373,764,184,919,400,171,444,621,368,30,362,478,519,90,81,240,880,867,35,623,522,444,74,844,79,75,525,627,289,868,206,737,762,778,944,673,817,874,430,482,250,419,954,797,214,83,398,48,80,885,73,541,211,564,340,806,180,789,618,395,127,489,107,762,55,358,610,870,180,522,117,228,19,760,544,956,807,172,745,669,152,761,162,797,974,104,852,889,998,468,751,45,347,997,748,381,764,164,51,641,601,610,511,436,223,922,256,428,716,488,754,377,811,772,104,811,247,888,938,689,670,875,81,436,694,455,990,915,37,771,720,210,406,242,921,167,89,177,42,325,627,196,816,619,239,881,863,758,516,102,846,507,136,658,15,301,418,341,805,830,859,248,164,653,960,533,670,715,970,57,338,928,867,610,107,705,218,321,791,612,238,708,634,173,867,306,506,636,720,4,58,618,179,909,216,569,949,401,706,328,69,428,439,893,575,604,198,458,179,741,581,24,952,70,224,244,440,132,342,392,517", + "977,768,76,444,915,712,178,344,572,991,400,454,463,808,16,953,690,73,813,332,898,888,629,597,243,337,606,881,286,260,627,792,319,337,914,737,95,297,522,235,214,540,42,613,89,811,119,142,733,489,837,97,942,862,307,378,910,229,112,833,259,700,536,677,50,769,90,274,928,327,754,546,12,316,719,290,87,495,49,484,400,346,777,268,335,84,816,189,124,39,559,613,277,462,197,147,640,856,917,547,456,709,912,869,446,940,670,470,169,69,754,312,350,557,859,308,633,469,873,116,769,11,533,751,625,947,213,334,569,940,821,443,636,972,542,403,175,379,283,653,725,841,348,241,400,179,551,483,764,75,600,339,288,958,388,431,452,382,964,266,405,480,508,819,463,547,859,2,104,16,998,174,882,572,54,859,655,555,194,757,962,817,647,355,909,983,597,219,213,431,455,900,609,895,429,701,273,775,825,5,238,798,952,743,927,457,744,939,814,725,912,924,852,10,871,167,323,736,904,422,692,615,964,497,487,529,278,907,72,905,654,969,625,771,449,947,976,879,249,207,102,457,866,55,815,709,276,566,803,532,763,752,199,820,334,969,78,352,93,648,211,652,766,733,712,642,902,690,224,339,610,657,168,530,986,133,360,958,333,550,982,218,993,213,558,13,939,915,645,297,57,766,500,246,410,895,485,668,704,41,128,220,336,104,109,925,264,417,50,294,327,805,606,750,99,939,345,108,327,800,894,725,686,815,222,586,571,263,924,3,817,147,884,784,123,45,703,771,61,641,314,218,288,735,6,423,35,682,106,924,964,886,608,858,456,213,856,784,516,949,476,251,642,860,852,300,913,488,285,276,92,999,812,516,189,521,74,674,348,110,762,285,121,456,112,254,996,371,894,107,111,865,533,871,623,702,96,331,29,621,193,154,785,108,667,133,198,881,168,136,523,266,860,391,659,470,83,735,639,822,704,349,464,635,801,404,303,806,226,380,532,59,565,141,556,403,486,137,819,438,137,199,599,841,416,710,134,485,840,780,248,32,421,198,409,208,764,94,919,921,878,156,736,488,922,260,525,277,153,310,130,700,527,53,690,419,489,888,241,571,401,856,980,286,889,355,46,861,507,342,603,57,768,624,983,759,28,723,29,348,216,187,271,409,551,951,132,128,509,109,400,250,546,159,206,810,141,570,778,742,76,191,362,971,781,794,649,967,26,537,871,191,805,111,267,499,500,649,756,764,831,818,783,918,108,182,179,192,522,56,79,514,893,224,994,264,404,865,475,459,119,833,152,92,606,242,775,824,166,851,399,898,407,396,607,253,988,178,654,920,977,264,59,969,992,479,724,660,20,801,502,226,814,593,788,902,525,675,182,136,263,98,155,535,0,17,367,146,452,937,273,892,300,992,453,591,403,712,799,521,455,753,304,835,986,569,943,358,497,409,96,737,443,993,928,489,268,530,521,103,703,182,364,343,158,291,525,207,385,20,570,670,384,571,177,298,907,803,385,145,389,111,993,517,948,108,310,791,905,12,363,581,735,626,210,346,971,585,106,626,44,37,77,528,539,802,776,370,16,844,616,685,325,623,388,455,236,595,82,199,303,72,925,526,519,380,79,360,689,512,608,300,783,128,605,797,627,349,369,887,392,630,645,132,779,729,588,705,239,539,710,331,470,930,269,893,172,834,28,482,651,954,722,640,490,99,243,560,850,582,618,815,720,686,202,670,159,654,648,445,512,468,561,65,932,683,354,146,932,44,327,33,415,787,266,509,231,42,446,140,915,441,953,504,531,919,232,210,371,496,298,99,563,134,14,309,115,89,801,444,772,931,362,890,239,355,494,452,43,497,627,501,905,767,30,692,92,71,826,96,901,699,176,407,611,289,224,761,327,577,677,48,195,179,87,200,992,879,705,681,119,143,566,474,436,600,215,187,484,911,773,781,265,608,750,77,968,271,365,576,109,872,312,711,283,45,145,125,235,165,757,731,785,608,906,733,762,137,948,768,670,153,488,586,148,988,871,836,444,928,582,515,969,785,407,745,709,248,49,987,545,10,700,516,942,102,125,774,833,849,25,430,646,525,91,178,589,733,955,87,981,366,8,289,773,728,829,940,863,35,245,906,932,38,530,161,119,670,669,477,639,869,471,638,941,516,325,716,180,78,752,724,592,929,305,573,960,413,925,459,45,903,815,123,565,447,561,853,656,780,504,401,291,76,160,260,471,500,25,838,240,339,344,401,191,737,446,259,935,505,189,190,437,636,716,81,196,33,519,677", + "499,954,3,208,174,517,429,158,901,103,841,50,979,991,826,777,417,659,389,741,529,267,843,583,714,283,572,68,282,962,82,698,474,34,260,650,463,444,408,330,966,922,622,415,322,925,642,825,359,3,991,296,40,528,3,234,804,607,75,605,835,426,746,194,783,772,722,373,201,509,596,841,332,639,425,220,419,440,378,784,490,493,37,646,227,70,91,752,269,357,481,324,169,818,929,993,400,146,393,660,200,935,555,308,407,658,212,22,787,893,529,926,626,772,697,934,362,651,622,533,870,621,331,10,495,510,375,330,288,479,493,95,275,864,903,159,466,823,443,872,22,25,995,127,27,260,869,107,253,165,616,974,479,492,406,934,32,430,225,852,904,246,90,655,391,287,147,454,106,126,330,382,783,901,342,757,84,559,484,941,725,869,199,601,37,860,165,836,884,276,266,770,885,102,295,654,572,98,210,770,665,641,703,926,525,127,459,821,787,833,712,635,798,122,730,243,48,329,44,581,438,856,591,829,453,634,923,298,979,97,302,691,173,514,507,982,404,805,579,88,294,318,86,63,361,573,758,888,712,329,545,589,296,421,602,330,678,689,92,390,829,227,31,151,547,113,712,993,651,952,549,914,121,461,99,481,492,806,810,308,412,873,699,717,57,858,268,384,739,292,694,349,186,93,629,254,983,523,823,471,929,122,991,259,797,29,96,700,507,326,445,86,732,513,64,103,792,44,351,577,997,122,944,740,279,246,165,370,943,718,858,34,320,773,749,613,757,535,552,60,151,940,152,792,115,108,577,842,964,773,707,774,332,915,759,129,373,517,261,196,268,404,494,60,285,623,404,227,701,390,544,279,154,751,685,169,363,478,665,673,366,6,701,78,166,396,772,262,460,89,265,549,629,992,852,54,912,860,8,436,769,708,878,751,179,509,941,371,142,568,317,310,160,428,695,765,620,614,726,938,834,858,102,666,366,849,118,718,874,917,276,915,996,109,522,754,592,260,366,581,58,907,9,575,108,706,194,983,821,224,289,314,971,882,396,282,745,294,675,770,96,870,149,381,308,770,890,135,936,295,273,247,607,146,48,357,32,688,993,429,608,463,557,226,34,664,756,750,444,91,585,306,84,165,238,464,389,630,489,741,953,220,568,583,763,496,455,682,759,433,830,495,730,30,99,296,157,736,501,99,174,660,537,883,378,451,50,39,316,296,735,303,484,403,813,44,482,587,902,312,716,755,681,202,660,916,673,13,129,462,310,723,132,772,174,303,336,589,655,602,792,517,359,174,689,80,606,206,572,946,984,373,555,982,39,484,495,518,90,708,53,475,388,137,338,727,910,501,135,455,254,371,726,768,381,19,306,87,368,278,280,295,683,124,17,0,563,968,437,128,311,322,374,616,321,791,925,926,126,332,86,805,778,813,135,494,174,53,236,753,758,54,809,879,890,258,58,174,17,170,502,624,169,116,230,793,402,24,580,30,57,130,951,310,901,781,490,514,959,529,831,850,684,882,413,940,488,963,239,328,709,624,677,180,777,400,911,383,62,315,368,614,945,538,143,331,996,20,603,570,191,32,318,502,980,124,572,879,289,382,880,950,441,435,228,697,194,276,898,470,500,122,505,191,7,863,947,686,460,508,305,181,161,179,863,50,186,617,690,816,592,784,649,544,353,841,565,169,716,75,964,431,838,763,798,226,161,71,405,443,720,306,620,358,976,455,119,105,228,497,702,219,692,209,365,758,491,216,634,51,143,388,757,667,40,918,152,383,343,632,513,298,134,217,111,973,914,53,307,978,51,27,687,855,659,607,399,438,936,650,580,443,861,453,740,666,873,465,348,887,672,27,904,236,116,693,419,899,143,940,114,945,102,600,684,695,346,626,23,670,954,728,160,673,410,639,295,981,295,318,11,783,623,173,935,571,288,423,533,471,478,775,540,140,832,648,126,668,143,961,607,180,53,306,464,793,363,880,66,888,329,231,813,489,125,100,851,357,919,743,441,809,568,833,886,909,77,946,988,856,909,767,899,135,955,901,228,121,852,435,413,80,489,544,620,648,629,453,912,235,397,697,963,83,676,884,727,407,400,213,547,190,386,909,719,421,859,635,52,273,957,282,62,651,727,610,125,101,245,701,482,723,611,61,143,477,533,135,333,688,999,153,433,346,113,69,152,407,655,996,415,736,388,436,730,103,877,854,518,584,656,107,496,135,928,39,243,351,102,87,913,889,864,476,908,133,896,693,70,224,154,56,672,774,365,933,155,23,825,498", + "723,695,624,346,549,492,621,27,252,134,679,697,729,427,788,569,762,425,990,797,166,429,279,30,788,539,807,578,783,195,654,548,404,635,21,431,516,380,371,402,641,132,557,671,207,457,467,71,110,227,289,121,427,135,261,97,544,852,786,531,961,887,258,658,792,198,9,818,794,951,320,805,199,811,806,558,687,679,554,499,918,735,957,243,178,235,591,190,2,704,280,346,137,491,455,533,931,558,206,132,506,308,237,777,936,830,590,533,584,970,44,984,225,773,613,689,431,674,153,142,520,405,785,508,725,948,437,272,262,912,245,107,369,889,551,908,762,536,183,977,483,44,324,157,39,805,375,792,986,315,269,739,972,899,399,188,546,441,961,422,561,174,839,684,696,137,328,476,719,450,617,249,133,894,482,667,387,25,65,373,488,496,866,752,482,454,473,76,748,566,916,607,358,766,400,603,962,819,677,46,464,510,30,875,555,158,693,213,645,452,631,927,89,458,228,994,274,430,37,461,667,658,573,449,119,850,965,24,765,825,578,626,727,814,65,778,703,663,484,382,812,326,346,729,597,354,128,580,589,159,678,396,31,861,108,497,486,83,522,26,180,869,197,936,277,30,36,293,377,242,106,648,448,204,90,360,122,274,156,667,937,871,349,185,312,369,738,54,813,332,156,869,85,791,701,151,804,320,321,739,686,45,602,436,995,612,781,747,758,847,839,723,947,482,772,654,215,321,317,62,257,463,437,106,302,990,48,456,930,530,295,789,722,700,295,944,735,742,242,883,498,978,532,730,168,113,255,499,1000,58,763,85,550,9,636,639,397,134,241,200,592,64,136,865,224,957,841,528,43,405,259,149,162,959,50,428,860,439,67,889,299,703,915,288,355,88,594,80,827,77,482,381,37,54,478,537,187,587,918,98,235,528,233,336,741,40,306,982,654,377,47,656,368,89,89,550,230,41,451,266,309,665,516,889,195,399,679,524,28,700,59,188,658,574,398,749,287,233,104,804,143,53,483,364,205,716,44,806,459,621,265,670,533,9,149,494,272,211,377,113,676,804,249,167,698,128,632,590,548,584,558,974,501,472,312,438,700,809,287,197,883,993,337,808,253,154,748,670,626,539,123,699,854,362,627,88,601,477,576,121,279,123,304,382,680,506,142,905,437,455,768,265,883,799,630,729,838,183,775,462,898,539,808,359,857,607,70,13,186,824,909,307,517,490,702,547,907,468,563,15,639,333,647,835,612,759,645,611,207,716,149,295,335,377,796,331,845,830,661,52,937,546,23,630,500,832,233,886,324,256,231,111,996,363,869,861,682,74,959,860,391,199,654,203,793,180,14,529,961,43,889,531,403,614,769,490,528,770,42,343,835,178,288,768,367,563,0,962,80,650,331,66,498,645,871,537,732,742,942,301,169,563,190,470,415,41,940,875,596,325,691,880,253,24,807,785,260,437,530,129,269,273,644,770,940,584,269,906,615,143,30,663,595,35,121,292,601,395,7,726,731,651,906,690,528,911,859,885,188,736,839,818,350,22,399,439,775,730,330,966,273,698,39,508,571,881,2,601,998,978,342,711,175,117,528,240,453,584,955,983,212,803,256,58,706,461,10,16,8,804,743,198,420,348,159,513,449,680,765,422,286,973,697,881,200,216,204,843,847,953,668,137,289,985,631,703,671,289,587,414,928,774,474,140,382,398,186,329,887,473,871,595,675,317,438,688,353,725,747,169,603,488,451,490,541,787,897,841,124,470,99,816,586,81,957,997,693,344,765,717,546,917,92,179,13,865,45,959,197,406,208,115,810,686,115,930,151,291,432,309,480,477,508,299,313,345,118,324,578,497,999,907,974,387,961,111,417,62,646,443,111,462,810,827,735,164,349,961,917,913,835,405,41,412,993,344,948,274,288,353,537,726,639,647,1000,83,35,703,686,165,180,490,151,344,562,890,840,606,702,876,775,86,313,456,796,124,316,947,149,92,343,62,24,466,573,258,326,560,796,906,446,254,578,374,679,422,729,241,918,119,619,233,712,196,86,864,474,310,382,731,854,725,445,172,144,670,274,489,812,551,798,577,652,729,350,572,262,530,824,186,646,287,112,769,818,474,551,108,867,29,120,787,696,574,941,324,671,373,492,130,216,549,1000,416,72,733,882,667,935,905,829,912,237,416,177,403,211,6,821,71,316,69,663,682,339,70,5,774,635,746,531,853,758,478,150,718,297,368,563,903,78,671,135,857,302,66,338,658,477,911,710,743,816,227,421,556,536,856,784,672", + "381,751,102,711,545,251,286,158,131,271,147,117,968,645,766,394,572,254,98,650,98,157,728,587,634,52,801,850,781,615,721,17,746,577,177,243,373,404,870,561,902,731,979,841,605,322,381,83,269,837,665,815,511,559,914,880,304,891,152,537,983,536,750,449,286,55,400,119,832,9,726,911,682,388,238,678,13,601,747,268,316,783,947,109,777,678,777,550,730,275,422,877,903,514,205,17,100,531,151,352,139,780,310,338,966,417,409,584,887,309,538,214,298,982,75,357,851,494,856,765,139,61,479,952,870,341,699,513,255,801,263,438,748,970,118,719,690,989,74,21,824,158,838,807,272,510,811,459,415,14,20,765,259,672,119,540,563,476,769,446,390,189,693,65,287,256,658,875,226,733,298,910,467,589,302,625,745,569,142,311,463,101,908,249,606,207,947,796,142,145,676,721,226,926,101,390,267,105,269,880,182,544,57,487,453,962,446,834,225,979,536,152,587,997,628,457,76,176,732,873,371,989,297,524,936,751,584,707,94,164,602,468,414,679,708,225,141,159,938,534,579,565,313,563,556,118,420,894,97,104,644,74,155,23,391,713,325,592,473,365,202,520,33,890,587,490,496,549,420,881,51,721,879,399,777,240,589,743,195,613,790,552,471,96,354,773,185,260,993,501,534,258,835,555,568,653,463,195,824,530,733,338,102,540,71,175,435,642,717,357,508,706,395,895,609,979,403,358,503,228,614,948,833,228,551,22,538,426,3,334,225,684,594,446,70,153,850,189,267,627,362,262,480,565,727,356,351,750,2,4,44,237,602,866,24,813,531,179,288,844,180,425,517,198,667,526,102,495,951,756,66,92,132,37,361,80,488,934,185,579,364,523,792,22,465,180,56,671,771,146,197,650,269,744,812,211,337,312,886,940,264,509,774,571,865,414,562,857,920,542,112,497,442,563,371,478,549,692,831,764,78,825,241,134,96,722,571,65,601,626,125,126,565,957,844,239,111,246,610,994,998,520,759,78,595,188,574,685,694,529,224,860,533,24,110,59,247,378,178,988,286,520,624,313,869,411,832,340,203,530,129,864,722,1,806,168,597,329,241,63,18,143,132,934,590,776,138,755,20,213,873,221,989,205,458,373,90,462,355,702,902,265,600,121,764,985,317,64,220,627,571,68,45,29,611,585,563,756,252,821,658,55,719,477,571,772,658,878,226,656,78,243,151,780,153,608,912,275,965,383,512,247,352,519,381,200,852,451,367,321,170,782,532,428,327,219,384,495,827,583,199,571,990,856,121,867,425,244,460,21,366,230,310,17,256,163,751,572,422,717,567,82,468,715,418,577,619,198,265,196,332,80,794,142,382,35,980,60,13,629,547,986,86,716,146,968,962,0,117,749,253,767,636,850,62,290,434,474,586,244,225,470,82,334,136,990,854,751,257,858,833,12,281,980,673,411,619,412,571,248,966,140,371,258,289,708,490,454,259,523,850,719,375,504,875,214,996,8,794,925,283,476,977,905,294,241,459,797,794,932,608,792,356,783,162,922,805,140,274,669,947,949,417,183,85,3,543,853,392,901,507,950,994,27,804,46,633,318,596,590,316,152,660,894,394,781,282,610,122,960,826,849,999,851,136,847,495,112,994,493,431,887,889,940,697,219,902,173,81,160,947,277,736,302,116,538,259,394,139,673,675,40,256,818,522,318,581,140,815,641,222,735,642,68,889,506,446,98,627,42,781,114,470,33,329,401,92,212,580,702,758,348,169,949,505,716,361,590,884,163,199,955,794,232,514,312,521,139,150,317,279,849,313,22,449,665,137,440,753,82,133,302,155,936,320,830,416,452,618,452,203,750,441,833,996,208,466,976,302,844,562,855,103,57,297,565,808,273,32,306,785,895,583,869,416,449,712,560,738,293,762,91,452,212,938,488,678,970,268,551,530,244,966,957,246,426,772,501,929,129,652,269,382,955,96,899,132,102,95,940,744,156,527,671,624,683,988,502,301,540,665,15,529,834,143,536,154,307,990,724,187,250,356,159,519,380,552,230,581,530,88,429,304,937,122,802,819,300,510,232,934,624,723,694,355,544,719,586,96,456,351,255,813,776,143,774,281,35,524,638,683,676,868,849,136,463,343,922,577,682,730,946,621,670,910,959,93,41,496,615,328,958,567,783,968,261,675,825,723,272,885,215,598,103,908,636,976,391,108,902,759,174,143,432,268,283,889,290,289,174,416,427,470,223,459,787,457,10,358,12,832,545,33,914,611,994,559,23,978,697", + "223,230,254,674,430,137,95,786,135,408,416,151,492,400,788,324,996,712,318,736,493,911,249,306,274,133,518,966,33,885,171,616,381,545,99,903,140,141,669,237,828,181,74,970,405,19,430,24,803,186,235,190,554,547,106,412,209,942,955,227,97,990,122,351,23,989,875,326,803,107,719,677,370,100,833,868,599,468,777,841,358,933,804,936,761,373,155,901,494,149,938,364,618,266,619,375,138,872,329,3,696,663,880,865,4,724,33,562,914,237,318,469,622,844,196,909,587,657,708,553,259,301,689,683,685,886,123,651,577,444,462,545,580,459,823,114,324,750,57,638,178,300,642,535,230,994,82,46,109,903,763,159,700,389,889,744,259,362,142,857,164,246,705,158,303,498,741,569,88,973,91,518,642,390,415,4,177,521,161,188,990,649,318,418,199,636,513,62,474,489,358,219,352,670,444,591,94,432,322,795,622,528,322,487,901,390,985,785,354,802,383,371,970,429,262,893,394,431,730,178,90,256,270,72,65,625,715,699,796,679,349,878,604,150,238,47,275,887,308,246,148,651,380,330,635,987,186,141,286,155,714,920,547,484,835,542,994,191,235,916,268,676,495,58,5,823,611,751,260,692,246,202,353,190,836,38,425,137,170,388,726,705,864,809,419,812,146,419,174,979,447,677,908,154,545,856,285,642,243,257,505,270,271,716,622,391,334,955,854,859,454,371,685,301,327,811,742,188,667,222,489,531,877,952,914,200,163,320,727,923,599,943,53,774,216,409,103,198,584,804,579,726,958,175,458,529,895,96,481,147,866,968,842,758,129,215,209,77,355,392,313,201,162,436,923,395,391,651,472,128,413,706,727,994,19,706,940,489,793,877,468,903,283,254,174,625,675,836,298,149,707,367,279,647,975,420,125,478,516,285,941,92,361,503,3,939,438,818,924,85,878,128,369,505,959,820,268,828,657,314,216,234,535,253,596,390,516,900,303,648,468,194,711,386,528,225,27,410,506,468,424,797,826,731,749,393,50,701,174,409,825,753,373,135,250,213,355,745,663,832,880,362,819,175,90,685,397,773,630,320,967,461,777,48,188,385,49,940,575,476,772,197,488,140,451,489,290,823,300,8,175,373,93,877,116,369,16,390,809,971,605,328,302,81,100,479,947,983,464,55,470,27,267,10,878,44,502,925,495,794,864,509,98,29,845,36,992,834,707,21,568,764,280,275,789,487,524,376,126,49,76,773,981,988,252,153,312,700,191,285,817,433,834,239,336,974,862,831,496,928,937,289,785,371,938,893,926,681,806,746,952,685,200,749,456,36,141,216,606,577,689,14,178,300,443,935,88,5,495,599,97,427,422,373,808,188,657,981,572,778,744,709,30,821,452,437,80,117,0,274,672,161,177,303,179,805,294,831,82,199,385,101,280,401,423,621,312,267,946,825,651,614,410,987,502,304,15,143,157,250,773,906,67,615,760,937,156,380,971,936,314,891,702,365,937,477,538,963,895,568,283,919,563,338,376,910,743,461,342,17,770,455,802,785,365,952,156,10,631,527,714,175,820,703,675,318,528,366,243,962,48,895,776,262,795,744,798,968,62,429,130,997,336,823,927,547,55,152,154,935,551,290,242,779,466,944,851,703,740,277,118,425,385,908,485,236,707,238,305,534,181,269,572,207,136,475,5,896,476,596,312,903,706,194,886,46,724,29,32,712,230,796,815,557,261,555,204,237,982,985,859,428,690,462,612,202,565,74,39,851,13,789,119,27,257,263,687,756,251,325,53,908,365,914,357,295,219,212,109,112,107,267,591,707,437,201,217,726,933,889,721,781,242,800,578,131,473,182,831,558,452,813,357,636,48,338,710,77,394,480,56,678,790,553,25,654,157,246,492,576,484,40,303,434,297,301,5,963,602,370,566,492,97,615,493,723,634,466,648,381,269,208,442,380,46,478,598,112,445,369,653,197,626,188,877,349,249,586,23,951,829,49,694,409,567,703,853,859,830,943,147,683,269,251,367,178,797,153,365,962,142,705,719,116,127,45,568,263,848,34,500,16,683,251,832,215,755,682,279,487,295,402,415,693,837,201,644,102,396,102,201,526,255,885,21,912,956,286,81,262,376,809,445,973,988,130,81,248,768,239,100,486,22,481,727,532,496,125,925,131,971,954,924,504,373,218,916,718,587,478,390,166,88,140,367,168,645,821,282,603,171,481,417,185,128,850,541,670,919,192,10,921,97,693,201,242,749,339,483,618,981,53,484,373,456,523,973,972,53,749", + "299,61,8,198,738,559,574,24,146,120,610,868,669,702,280,784,427,563,358,152,305,944,131,484,265,715,135,399,237,799,46,647,853,469,811,964,103,330,629,608,446,142,705,851,307,358,551,50,854,939,777,642,305,451,975,168,421,723,918,440,771,935,840,241,406,974,561,51,706,777,536,13,994,901,598,55,785,414,874,499,385,528,86,988,851,497,698,999,727,435,370,135,206,323,458,857,819,119,812,108,964,727,228,20,363,178,694,844,8,903,548,319,56,388,112,844,99,991,355,340,808,151,524,633,581,556,929,251,550,838,471,521,52,856,766,937,823,12,477,948,479,597,575,546,912,90,98,739,46,645,313,811,756,742,999,669,412,826,116,318,820,731,255,880,156,387,324,196,984,199,937,488,561,438,543,253,125,557,268,485,14,395,345,26,816,551,652,480,604,164,830,457,413,186,848,642,687,547,57,888,769,886,209,47,108,508,62,8,625,244,749,860,641,436,667,473,634,693,886,533,42,518,511,819,79,730,847,780,773,714,952,698,925,137,859,462,812,81,873,348,655,403,622,556,120,348,196,578,728,938,969,835,447,773,71,810,16,394,169,914,3,698,125,234,22,326,677,451,452,881,556,839,601,184,506,916,200,347,308,314,949,790,100,134,11,950,763,300,665,982,12,168,207,225,822,957,738,776,114,151,205,425,797,723,905,432,656,672,612,621,842,250,446,655,576,611,715,505,824,106,923,108,79,476,160,434,575,539,984,753,622,651,707,337,155,579,882,55,878,551,96,973,35,307,850,962,781,974,210,84,590,527,135,602,521,64,80,760,985,999,626,881,750,143,776,627,719,207,652,616,996,117,553,30,191,645,654,472,688,368,430,427,611,539,413,220,611,343,11,710,54,307,866,580,252,271,259,270,633,840,172,929,866,257,967,152,632,182,833,364,485,997,833,221,604,276,874,895,401,6,634,224,18,762,263,426,647,866,301,208,885,856,585,133,92,76,106,78,26,60,29,49,695,225,10,856,110,291,8,400,569,346,52,70,450,614,11,332,194,173,954,57,600,585,419,851,399,269,430,979,787,506,862,783,898,531,540,728,756,122,604,931,436,715,273,121,950,645,800,195,647,761,771,896,381,906,976,814,423,201,904,855,724,822,707,353,84,383,272,170,24,540,107,826,505,292,334,863,528,338,94,263,76,103,533,155,428,596,422,362,817,690,888,141,800,460,266,739,211,67,987,769,341,839,335,800,137,379,502,139,558,664,39,500,383,951,89,876,632,115,250,521,31,564,563,356,516,899,424,182,269,234,203,648,470,327,277,50,443,400,401,541,262,672,187,130,476,676,36,270,550,85,304,284,460,581,288,806,393,861,438,755,888,265,937,128,650,749,274,0,882,459,580,148,483,330,848,316,775,874,137,145,708,466,89,910,425,685,220,584,428,327,180,224,307,718,261,579,543,238,180,67,907,358,446,416,68,437,330,931,536,925,332,307,860,381,583,313,557,731,782,789,520,992,168,314,727,115,505,54,592,115,834,234,212,829,186,537,853,264,925,574,859,322,955,957,565,575,299,700,137,625,592,299,370,726,461,17,907,39,2,359,76,863,534,68,277,239,618,707,656,859,150,653,352,55,70,332,107,922,647,227,781,338,295,268,749,103,804,668,211,201,578,791,365,868,942,261,852,671,654,554,5,469,519,219,390,325,86,125,911,940,691,972,945,352,638,893,374,969,500,66,742,419,548,3,664,882,586,533,419,21,67,508,33,565,870,752,91,740,62,295,266,470,101,627,749,121,124,75,661,157,431,390,187,122,392,333,439,946,239,231,207,730,602,317,437,414,62,18,435,763,816,814,556,302,903,956,528,894,425,568,164,216,133,607,318,323,183,764,360,810,939,110,581,438,971,515,501,618,302,17,459,596,410,893,567,582,253,532,437,366,886,67,477,395,932,216,541,265,647,676,495,469,288,217,584,296,987,395,858,980,373,752,836,620,970,620,27,112,758,370,455,179,656,89,578,976,979,581,584,25,652,266,162,93,644,63,265,314,816,86,384,614,155,217,795,9,640,516,353,144,955,173,60,261,191,584,258,468,828,656,145,202,85,857,282,8,434,744,270,944,298,907,889,235,324,560,990,717,282,547,419,130,147,612,341,756,883,404,282,875,297,260,736,12,155,382,681,798,862,779,691,754,136,442,695,372,751,707,553,175,402,843,60,582,870,963,513,826,41,524,499,112,968,605,291,617,726,930,859,725,290,684,821,261,128,127,566,659", + "298,834,574,784,797,974,949,876,616,672,890,292,538,111,362,23,109,111,351,986,438,810,935,503,983,821,646,302,827,575,133,477,964,949,630,273,385,268,580,332,419,688,891,846,162,8,513,153,801,418,461,220,226,607,758,179,462,66,765,706,253,816,622,660,183,129,508,360,561,71,313,547,722,403,161,870,832,629,758,131,879,332,731,17,216,960,4,496,261,851,803,487,806,916,58,699,379,61,115,304,841,426,711,928,97,448,518,644,903,252,412,200,821,362,424,599,977,615,826,903,656,531,366,904,553,803,821,605,387,779,971,905,891,707,885,333,958,602,446,433,157,610,206,449,466,233,81,291,595,232,110,227,576,783,135,952,41,372,646,527,158,939,444,562,878,717,509,794,920,15,101,299,266,212,122,354,41,259,26,232,631,71,227,467,129,22,821,930,555,993,562,692,240,919,459,764,529,600,433,107,438,136,791,399,416,452,477,601,88,427,922,690,340,905,282,769,763,341,797,436,527,983,898,750,418,544,948,888,979,814,968,488,610,275,32,671,335,141,831,803,708,735,22,218,886,981,920,499,259,654,625,617,134,969,301,136,190,379,715,855,696,405,169,536,180,417,420,407,125,31,818,199,521,879,409,58,964,290,175,706,465,132,376,850,307,133,724,890,511,989,576,440,666,574,224,930,846,979,584,131,53,250,551,963,927,881,977,346,226,794,880,192,296,555,399,515,510,96,543,561,763,978,581,357,495,266,655,90,136,979,743,560,419,75,365,540,202,594,141,872,830,536,242,773,980,746,680,488,433,488,453,230,569,921,728,940,632,386,524,19,627,828,1000,573,508,714,577,816,986,3,747,70,758,343,864,851,736,423,33,674,78,251,846,649,106,312,641,214,741,174,878,404,912,236,983,260,519,143,994,506,996,631,615,377,392,809,779,749,372,868,321,619,308,598,369,658,142,884,112,829,671,577,614,518,565,861,11,139,745,670,928,472,95,732,431,262,496,181,486,265,998,11,778,370,603,639,862,127,361,292,429,556,827,489,700,610,369,336,918,735,96,921,255,880,327,765,811,471,375,235,192,622,722,378,14,809,573,551,378,943,942,549,61,430,542,965,796,863,933,855,899,323,102,186,381,152,237,897,481,186,830,553,361,163,291,548,662,115,826,390,640,846,694,286,189,78,799,34,50,20,443,761,539,430,25,931,75,961,889,86,155,965,697,845,498,314,46,559,535,375,501,144,463,316,171,762,689,278,528,529,964,576,93,296,850,239,43,576,265,155,292,54,478,799,744,477,62,408,690,131,226,823,686,488,284,671,72,394,452,475,136,458,809,108,12,224,790,848,182,183,877,698,471,968,796,881,31,239,742,844,336,837,515,904,273,311,331,253,672,882,0,510,575,121,810,782,216,208,954,131,365,643,511,327,720,905,559,263,796,26,628,340,523,764,549,28,573,979,470,937,812,533,857,290,874,777,144,335,980,719,929,623,775,457,206,232,468,28,495,622,86,274,233,549,156,353,209,219,881,485,170,373,554,70,53,220,539,198,180,955,56,632,744,124,9,390,590,537,604,784,337,831,213,696,494,854,390,361,37,862,774,91,407,373,809,661,103,766,552,388,970,981,688,761,500,195,210,225,714,461,68,710,947,70,859,669,273,363,468,387,183,295,585,831,166,771,359,868,99,207,79,35,910,327,357,117,548,768,805,455,583,323,7,259,619,331,996,346,604,219,547,771,691,313,13,687,759,757,561,945,979,237,96,399,125,646,547,628,171,735,595,429,985,206,414,362,905,313,690,129,447,5,460,905,626,422,2,984,501,48,127,758,918,579,865,906,74,860,394,434,217,847,26,119,796,510,486,762,946,231,495,858,181,799,153,123,81,745,676,157,486,707,465,869,408,893,404,474,119,386,502,256,568,195,256,747,389,813,51,377,397,5,738,525,281,778,224,205,313,808,623,118,772,355,73,277,537,289,843,198,506,65,956,248,117,991,77,418,975,898,91,22,16,861,817,173,452,842,647,959,706,671,388,351,395,181,766,146,773,744,342,896,93,964,381,757,491,558,239,185,447,705,432,742,802,966,909,730,568,263,621,457,957,373,859,57,270,241,769,262,348,787,972,764,692,500,847,354,448,551,290,896,389,763,221,550,913,78,565,722,895,695,800,823,270,171,297,456,459,769,888,940,264,970,746,171,85,883,663,705,712,513,912,630,144,723,267,792,608,569,642,936,903,549,134,663,591,739,965,538,542,950,891,199,481,986,421,981,306,94", + "981,940,804,184,127,70,493,311,445,327,648,618,190,132,754,116,755,482,446,757,741,722,566,607,358,661,154,194,125,582,702,696,223,357,229,22,258,379,948,385,895,884,791,516,77,664,367,540,967,312,691,989,522,367,847,283,736,38,404,108,50,471,471,893,386,747,98,745,885,897,418,257,720,640,487,631,850,914,95,518,280,483,644,153,689,268,699,80,167,696,732,230,837,445,489,720,809,468,315,341,294,248,544,513,39,942,786,109,266,863,864,127,25,271,166,587,213,939,101,850,663,355,511,56,182,882,740,282,795,829,295,675,614,539,312,617,428,918,704,492,556,409,388,804,46,821,477,115,548,465,642,141,262,448,893,138,880,454,476,11,50,740,207,898,742,837,221,626,920,327,3,778,278,4,439,31,163,551,397,150,623,723,774,855,542,754,883,868,484,608,926,686,339,994,680,266,342,228,707,616,412,773,11,372,486,737,799,395,775,447,190,444,518,19,557,561,60,49,42,645,675,783,159,273,362,77,802,71,582,869,314,322,803,576,13,748,647,637,18,795,756,518,501,515,9,454,853,80,349,233,232,860,995,221,553,351,866,319,611,527,84,463,823,111,171,830,371,146,963,535,22,730,132,276,915,778,565,820,737,518,923,117,332,834,725,653,251,691,589,606,542,620,879,52,360,193,372,20,784,664,646,389,469,503,386,614,890,457,236,922,949,237,4,847,385,312,495,820,741,7,670,921,891,79,579,41,650,448,104,29,478,887,402,540,314,750,204,100,915,901,561,123,190,412,198,66,841,729,32,214,515,935,760,301,991,145,648,331,990,788,181,569,2,340,435,587,853,483,133,123,603,955,101,701,597,624,652,139,611,720,551,430,85,92,671,958,284,231,380,317,417,681,994,237,515,222,185,225,279,635,433,824,417,870,144,534,114,477,347,697,875,248,261,27,360,702,982,692,200,385,996,685,520,644,879,301,650,615,534,360,81,568,513,883,911,710,829,211,496,814,569,854,479,976,981,680,989,629,479,441,851,765,199,805,191,965,77,692,266,414,449,309,252,333,215,854,660,880,157,191,617,179,120,923,283,44,784,221,214,772,153,629,850,365,717,644,664,974,983,916,203,677,636,865,344,506,453,890,984,302,572,393,857,649,769,86,369,790,408,148,493,598,490,14,466,863,972,332,984,601,422,190,406,775,372,630,988,59,409,357,774,650,400,625,992,539,939,726,197,94,461,539,136,506,622,516,365,934,959,405,353,406,273,686,569,750,97,996,50,734,701,339,361,116,870,115,301,401,866,587,248,635,737,839,139,893,211,613,41,280,581,920,192,799,202,428,162,325,887,803,878,482,182,298,283,894,774,158,284,915,410,736,160,921,892,322,66,767,161,459,510,0,764,571,141,728,457,744,884,574,720,604,150,158,813,69,544,783,753,404,301,716,464,547,914,614,695,156,369,994,600,538,806,657,55,112,652,848,953,976,597,792,98,753,471,171,946,690,311,876,299,737,728,332,325,542,17,931,384,303,933,38,113,80,456,616,166,691,973,291,164,929,498,917,711,486,81,433,477,529,801,994,417,710,671,587,317,729,19,939,280,262,772,982,135,203,971,889,823,670,507,328,66,539,727,961,769,418,408,281,375,209,525,654,538,809,361,690,55,21,764,716,553,143,844,527,354,647,760,611,136,536,236,868,971,585,872,936,532,156,905,350,860,991,39,261,170,877,422,416,129,464,454,171,205,835,433,835,325,848,104,594,70,256,302,568,253,883,715,529,726,197,90,833,86,610,458,468,382,42,942,212,747,598,41,724,325,783,872,127,592,288,669,445,923,293,255,965,673,908,133,530,67,795,127,813,62,965,761,79,149,849,109,826,633,87,952,230,680,102,387,212,164,816,306,213,241,676,550,777,667,391,188,108,90,686,248,249,206,550,573,788,717,64,483,572,543,846,919,996,843,809,230,482,383,622,261,932,72,654,62,413,398,717,43,580,178,973,53,523,168,32,495,849,450,420,311,672,174,738,738,41,442,449,303,624,115,203,125,534,166,545,223,317,913,938,950,79,511,858,606,975,5,598,766,225,947,585,959,716,58,154,409,229,69,981,476,707,236,982,61,885,439,318,305,623,650,758,822,513,903,253,584,851,548,69,561,563,370,885,932,388,721,143,88,449,436,973,752,53,579,604,272,17,637,44,29,70,826,975,65,663,791,981,769,745,791,539,635,296,92,483,534,465,750,29,993,212,13,374,545,681,775,779,237,101,756,916,897,288", + "642,156,798,159,576,306,175,54,725,455,28,642,97,856,691,738,18,264,834,50,697,530,104,837,716,384,767,815,660,190,955,168,154,401,83,505,226,374,134,342,480,225,978,694,452,192,956,603,880,432,595,113,503,614,946,498,792,723,948,395,662,908,18,631,980,491,968,135,782,57,753,637,805,882,908,800,88,718,639,822,538,899,10,642,294,669,644,340,202,305,140,155,955,355,991,793,581,529,999,943,324,294,740,178,810,326,722,246,92,1,318,428,52,65,850,266,608,617,45,736,699,328,27,675,110,366,738,781,970,721,335,32,571,404,234,806,677,712,592,519,725,145,109,699,499,654,588,948,675,606,485,500,963,203,907,606,619,23,869,420,150,242,428,488,511,416,126,678,235,152,278,523,440,878,322,363,296,76,750,667,366,874,949,725,907,555,290,993,835,479,928,149,278,412,907,128,538,479,402,227,273,558,130,10,714,337,589,550,682,236,337,763,947,997,453,852,88,5,790,929,610,41,962,4,321,124,850,166,960,225,764,637,842,203,398,922,333,760,35,109,177,31,590,24,222,754,341,676,787,423,46,690,989,939,751,185,372,768,690,555,537,404,75,271,183,818,976,540,296,17,110,725,83,931,895,967,310,433,654,790,722,399,349,542,238,342,136,949,197,245,893,75,116,638,745,71,218,371,756,237,381,209,16,295,41,88,65,363,158,832,529,939,88,272,934,656,816,108,573,682,989,58,636,79,102,535,186,45,10,933,75,357,431,575,289,720,336,380,895,828,813,137,254,342,448,928,68,368,789,128,962,451,122,76,858,151,636,130,188,587,616,358,184,732,875,492,278,245,958,32,517,645,924,121,793,640,907,325,984,975,785,379,795,470,236,358,197,502,262,785,751,499,49,211,57,927,650,371,34,787,799,938,662,117,739,743,522,634,967,251,26,655,930,385,907,22,563,623,950,504,934,568,217,921,153,136,214,880,253,995,604,960,269,328,425,573,822,302,823,191,413,889,103,137,575,495,575,386,68,525,715,741,820,941,899,300,649,151,735,62,916,155,23,890,993,691,431,898,146,197,986,532,410,442,593,122,403,806,795,55,474,980,967,75,149,691,659,225,206,397,757,625,858,832,362,448,52,580,234,383,701,742,514,858,57,178,514,28,912,884,427,844,231,74,100,899,683,690,373,762,917,220,237,765,866,513,639,771,560,414,677,190,746,521,139,856,318,549,901,212,927,104,183,461,311,181,827,845,867,768,114,407,175,397,162,732,51,335,216,390,396,378,504,477,650,442,883,427,46,901,653,583,105,519,321,775,396,842,108,803,743,880,556,567,791,227,546,484,82,127,511,487,79,422,785,151,535,685,837,460,467,521,790,5,300,374,498,636,177,580,575,764,0,26,806,250,833,237,251,26,747,169,982,901,442,903,442,122,10,46,830,467,133,81,515,354,374,11,210,51,720,440,607,918,787,61,395,657,631,238,961,834,808,271,461,14,392,463,807,130,1,271,541,192,280,387,609,146,855,493,367,256,217,501,257,537,112,551,543,267,857,573,340,558,846,125,78,898,524,467,179,175,671,200,399,569,519,504,17,740,658,801,120,414,76,792,185,412,533,165,859,678,718,353,82,900,852,808,243,242,781,269,781,305,301,24,900,923,443,371,614,804,418,607,314,455,79,332,419,150,341,820,739,278,46,102,174,207,444,950,645,586,896,431,933,388,383,683,305,354,659,819,526,414,283,717,803,609,644,767,102,746,152,144,975,883,221,34,498,798,518,338,239,805,369,893,361,256,309,812,984,283,448,602,279,59,152,414,130,58,837,742,695,203,487,237,741,286,577,681,412,188,35,382,942,375,638,338,868,441,824,296,545,914,904,116,738,953,939,526,856,293,290,474,793,335,138,32,773,18,168,801,781,550,588,756,971,85,271,785,673,942,631,513,236,424,781,982,495,740,665,58,768,803,549,412,201,58,841,504,751,317,220,209,909,361,703,349,193,87,935,643,831,926,625,468,4,194,94,480,117,139,648,920,890,377,89,854,742,655,322,505,828,864,427,258,496,137,536,217,232,2,7,395,762,197,432,369,463,62,347,730,787,319,195,465,452,369,721,992,772,974,698,612,655,487,927,456,492,843,638,33,3,522,267,556,136,955,582,485,83,167,481,141,221,270,361,418,277,791,157,733,988,265,400,841,671,797,433,878,660,205,667,924,673,236,934,134,442,731,375,270,927,942,887,706,209,462,694,43,150,627,881,817,883,551,586,441,213,209", + "100,410,832,845,100,933,153,227,318,770,474,566,262,149,790,505,454,429,515,857,642,277,518,197,920,187,572,534,28,581,816,709,474,215,624,114,932,963,348,557,255,254,108,602,411,674,989,848,225,995,212,314,380,826,621,887,68,806,912,555,880,681,481,91,908,822,106,143,900,196,685,368,771,184,402,417,768,934,418,270,78,471,604,351,910,131,384,867,403,86,763,83,796,665,365,258,930,933,476,72,328,100,245,112,780,88,823,354,881,444,256,809,974,259,978,265,41,643,471,667,915,153,555,923,565,774,237,960,189,678,548,91,185,15,26,895,517,235,633,704,870,954,987,910,642,18,215,915,679,280,674,431,945,198,773,791,224,341,357,649,771,194,15,595,812,312,269,383,149,111,169,982,326,746,45,696,456,176,786,886,211,29,781,872,716,525,34,68,917,801,612,304,654,609,254,393,687,25,510,451,881,284,199,9,811,213,768,849,718,943,979,780,598,320,646,420,966,214,711,163,567,244,366,712,660,44,826,182,680,726,882,497,132,435,762,572,329,671,442,603,397,399,595,793,755,556,310,846,62,724,305,697,674,181,265,960,205,281,87,124,324,973,639,2,108,635,48,105,92,234,487,456,825,485,979,116,405,618,849,33,812,269,72,340,81,936,64,398,574,101,824,440,455,399,217,705,549,542,915,154,416,310,315,924,982,700,334,541,34,188,918,951,35,872,220,175,584,529,691,426,979,941,317,790,868,763,784,912,535,561,976,593,464,510,960,440,759,304,960,970,718,309,880,327,4,127,217,2,239,463,43,728,736,239,727,934,221,891,269,535,999,184,259,72,312,810,943,630,747,730,711,780,367,470,574,685,405,419,415,818,510,469,642,828,874,607,754,642,624,727,727,273,625,117,135,164,422,763,487,738,8,343,726,4,515,138,625,161,319,783,153,402,564,398,192,664,349,516,33,381,636,796,279,211,365,86,19,628,251,116,69,830,799,930,153,740,982,59,76,574,780,778,232,251,965,980,888,784,583,60,305,870,199,375,854,941,201,467,724,425,682,447,985,981,892,376,6,104,324,859,771,892,655,557,134,162,307,684,366,405,418,186,165,306,373,419,491,624,930,723,840,607,525,34,168,740,200,87,570,459,681,33,674,244,523,374,905,783,100,50,590,537,614,350,768,415,416,482,876,221,651,647,905,879,186,447,955,272,593,221,424,860,420,169,150,185,762,460,542,45,301,283,509,736,809,729,448,69,618,99,177,26,869,540,23,600,729,731,616,363,244,886,615,33,831,62,945,984,252,743,802,777,368,390,412,759,174,902,14,49,914,604,76,770,510,850,245,332,499,565,201,599,906,355,383,490,799,380,146,459,534,888,400,520,992,616,645,850,303,148,121,571,26,0,136,11,256,64,682,515,979,262,677,509,741,916,792,860,380,111,424,950,396,606,735,463,421,668,765,583,885,458,472,10,587,256,243,441,908,537,15,792,975,436,669,890,567,963,122,756,984,761,99,614,612,165,348,536,843,841,891,370,347,795,7,276,984,651,971,279,394,324,547,487,596,698,432,496,692,301,788,681,466,280,402,828,677,819,790,740,223,781,331,887,628,2,341,481,206,504,658,663,349,305,465,123,732,438,120,942,579,29,19,121,875,73,718,753,34,888,932,349,936,822,365,512,149,860,438,426,178,749,979,716,109,144,205,244,651,115,904,245,751,64,428,522,922,672,605,252,231,332,767,414,185,237,505,696,976,377,96,382,770,161,676,935,605,804,770,857,2,734,730,666,235,421,489,385,52,395,894,803,82,529,786,719,586,687,576,550,841,260,250,533,963,191,813,625,254,239,59,455,901,867,307,590,193,955,262,541,213,345,522,347,605,360,723,688,17,928,545,801,571,938,952,559,394,8,57,674,363,792,46,799,803,344,460,880,733,193,955,50,283,729,476,87,505,155,718,933,682,233,962,517,863,736,602,912,310,632,827,863,127,69,314,356,177,685,360,369,19,37,224,740,275,328,591,339,721,622,26,60,651,301,30,696,494,236,141,110,481,559,286,718,130,233,105,146,452,181,70,96,259,68,514,103,765,847,142,719,276,246,257,63,759,856,206,160,714,975,504,399,432,347,205,156,622,281,959,461,647,259,923,277,558,390,186,262,662,35,694,568,731,252,600,700,20,503,506,319,836,400,633,720,137,961,188,295,350,935,505,656,56,239,990,123,743,629,771,216,356,575,782,473,767,246,611,123,701,713,968,394,507,369,195,94,426,286,812,498", + "95,734,883,876,980,457,273,577,562,134,394,973,598,449,115,463,227,200,820,325,631,660,609,691,922,914,64,968,539,556,294,949,480,850,684,314,384,204,992,693,793,106,728,454,995,381,594,459,847,268,642,39,832,436,961,153,613,218,874,881,309,304,657,92,379,822,76,368,743,356,998,62,544,413,384,491,154,485,804,434,872,595,110,299,661,785,621,999,510,789,300,206,200,686,973,668,200,293,186,242,392,193,498,910,763,737,737,863,367,172,657,503,961,540,408,752,423,425,173,543,524,465,285,858,140,164,412,181,512,897,779,248,551,43,237,458,620,233,683,832,275,557,547,306,545,910,824,553,74,880,121,336,886,800,182,326,666,336,454,628,488,322,4,841,746,295,259,894,934,636,403,142,371,52,142,467,557,281,233,358,936,573,366,342,166,437,273,380,672,242,873,70,883,852,986,720,574,41,781,16,248,480,150,466,239,426,342,735,421,511,576,18,172,395,513,363,200,681,732,901,762,943,650,303,598,185,452,706,254,783,233,573,666,18,711,728,630,515,479,946,973,466,431,784,419,194,929,870,364,110,861,39,390,279,331,940,908,636,276,627,776,103,840,908,397,152,681,94,756,130,533,918,800,396,843,832,918,115,290,728,124,486,944,132,75,921,576,369,247,411,22,867,787,800,60,121,120,677,520,172,809,270,125,254,549,210,408,607,749,754,867,810,639,726,236,384,796,427,594,831,764,445,182,776,29,410,133,50,124,67,676,714,363,857,480,128,724,77,38,949,352,608,623,209,737,570,882,802,129,924,442,405,627,367,494,403,14,955,700,572,354,88,604,355,87,127,270,753,749,632,161,516,138,814,948,655,714,836,528,663,788,213,699,29,64,750,203,328,171,525,588,227,273,301,965,735,331,947,676,456,762,735,106,783,583,931,879,57,258,840,624,454,22,494,568,728,763,511,973,902,132,818,961,300,236,645,937,754,408,601,236,651,697,721,907,454,283,527,459,279,30,293,707,898,958,592,181,89,789,707,869,347,767,973,583,178,417,890,174,821,387,426,672,651,496,541,723,568,715,555,727,865,183,733,218,782,959,345,532,876,969,372,489,60,496,769,582,240,400,955,284,773,722,194,793,118,256,996,22,305,100,563,252,101,636,716,615,693,384,940,909,578,905,870,854,945,162,529,666,70,347,676,934,158,404,328,8,351,20,694,911,714,546,688,530,373,250,430,557,98,76,654,104,772,664,58,12,56,361,972,691,914,336,147,668,16,227,804,581,591,937,725,747,260,998,910,456,555,995,375,738,793,549,432,550,432,348,918,772,802,745,910,457,856,388,126,879,320,173,723,169,104,314,563,707,181,504,515,206,844,908,313,701,843,453,321,871,62,179,483,810,141,806,136,0,582,351,295,998,346,662,837,39,327,855,765,519,601,776,682,416,111,845,15,683,80,867,548,105,593,192,936,49,995,457,679,733,132,77,222,761,759,161,276,191,638,952,800,659,157,57,523,149,730,632,401,78,751,792,626,892,262,288,5,863,959,684,185,707,302,593,299,73,925,615,738,165,593,117,369,515,345,463,238,515,422,161,154,981,235,550,189,842,49,498,460,764,535,849,60,94,265,279,209,392,157,30,580,5,450,422,63,454,680,670,931,140,3,849,910,75,607,20,151,766,527,848,91,283,266,501,692,917,135,471,342,963,583,992,889,161,171,872,437,252,877,336,332,884,16,70,743,628,144,609,655,148,171,168,322,613,567,990,890,239,111,756,583,992,284,874,845,359,401,574,585,240,890,549,692,302,431,860,622,588,879,149,259,64,252,253,113,205,69,82,911,446,946,258,880,422,830,348,722,980,382,900,228,517,500,310,365,160,234,478,285,242,759,302,350,335,483,278,287,155,799,379,736,613,107,103,523,959,728,242,166,243,925,25,25,937,694,520,545,810,410,834,698,879,3,689,396,912,631,642,724,923,574,539,435,850,663,526,779,76,231,563,493,90,85,266,209,691,304,167,280,684,75,542,374,207,6,796,533,485,933,702,154,28,232,276,818,71,589,416,138,972,588,708,407,16,288,157,356,290,786,331,961,90,428,429,818,139,351,865,941,634,417,496,833,955,575,591,966,486,293,229,423,630,153,798,903,611,627,856,927,105,277,152,812,380,456,759,104,181,23,266,627,636,792,544,431,102,327,275,156,128,945,292,127,814,700,319,153,150,809,561,441,735,3,220,975,11,505,25,339,629,829,730,282,767,39,785,28,978,166,588,488,371,865", + "828,599,137,87,867,864,73,339,571,842,51,932,657,658,921,857,897,835,395,227,728,23,27,201,286,386,297,956,843,703,734,679,411,881,661,676,195,58,312,517,620,215,145,538,181,107,106,654,355,116,710,965,811,539,503,145,698,623,392,556,582,915,925,330,558,80,980,393,249,143,610,145,775,99,102,838,699,138,886,712,881,631,989,518,305,204,893,215,148,238,659,480,826,464,522,916,106,782,710,980,939,316,668,169,996,611,849,459,969,209,651,965,164,478,449,686,651,362,28,893,252,466,708,599,992,174,411,978,739,631,920,283,802,994,207,615,536,344,204,245,118,17,348,776,141,177,16,305,949,615,370,779,901,888,461,921,650,126,171,289,435,986,105,735,479,353,783,898,344,79,208,416,963,399,473,289,447,142,888,688,717,995,70,716,790,886,861,819,637,404,637,961,441,100,113,290,459,735,755,448,130,460,299,736,606,903,372,861,894,826,673,192,941,680,761,194,225,757,253,437,769,940,419,969,773,272,794,503,349,686,561,932,387,180,839,426,206,181,443,585,920,351,885,416,434,849,495,257,261,322,42,276,134,425,684,670,577,857,521,29,983,247,387,12,323,143,940,595,926,591,126,622,714,557,356,376,916,825,480,744,559,691,45,998,328,565,430,595,580,573,361,309,167,251,109,841,386,274,133,447,415,474,93,144,543,459,790,916,506,594,82,187,10,45,312,992,383,401,421,374,348,579,520,791,462,30,635,671,761,949,353,282,114,860,494,460,696,24,939,764,381,466,328,429,771,513,256,10,907,640,541,854,285,905,525,560,276,325,206,307,599,395,826,256,56,39,548,706,489,166,420,666,706,965,149,76,486,136,758,206,52,829,544,454,736,769,827,97,905,331,787,855,444,81,417,534,225,588,445,283,948,970,217,450,660,646,952,122,765,287,194,73,455,688,357,286,686,954,945,581,779,933,381,117,888,279,520,420,183,854,286,632,3,52,689,179,921,511,395,622,638,772,977,440,247,392,851,452,652,345,306,314,177,84,151,497,450,151,300,856,857,290,141,630,927,386,257,925,259,109,588,476,925,343,959,626,954,176,650,183,732,193,42,9,312,676,851,706,914,610,124,504,511,810,933,561,773,634,305,509,393,241,10,605,377,954,518,378,843,943,536,276,381,619,168,911,267,645,200,726,902,381,287,604,202,956,947,316,774,491,745,606,163,268,332,589,97,992,580,84,944,655,652,720,740,246,362,266,195,265,228,696,434,110,609,167,886,36,662,755,265,716,17,208,975,944,73,796,603,472,977,964,376,871,296,281,705,442,431,546,153,563,661,68,28,132,756,545,145,682,844,39,418,534,700,314,808,450,308,929,662,912,45,911,591,791,537,290,805,330,782,728,250,11,582,0,809,849,628,614,786,966,920,593,145,605,238,173,242,685,907,638,237,990,722,129,73,257,281,379,111,403,964,897,270,449,737,901,903,357,562,808,316,701,707,685,755,595,924,842,315,934,802,455,745,721,19,758,773,514,756,518,936,751,754,894,906,43,576,365,791,177,984,881,927,721,516,608,709,626,960,849,510,769,583,980,278,948,358,156,48,147,908,408,7,756,998,688,981,874,671,140,920,780,627,367,804,268,431,186,527,893,39,30,69,969,901,328,174,518,952,745,817,115,14,386,738,13,231,759,258,579,587,607,239,670,63,7,496,686,583,62,1,671,579,534,401,877,453,264,774,596,415,499,511,138,186,113,730,120,93,776,216,647,529,179,223,143,367,264,521,852,823,776,138,19,503,418,390,933,673,322,493,2,334,935,648,398,438,937,792,843,786,377,429,302,69,61,703,6,268,156,3,661,795,559,892,449,808,567,931,925,373,492,453,103,725,915,684,274,567,668,835,253,570,100,226,19,37,358,964,797,698,743,984,624,407,915,237,371,404,288,749,432,649,775,462,471,880,11,423,482,328,886,921,277,157,630,445,702,554,459,29,13,392,463,111,692,341,941,922,380,433,634,849,975,286,407,740,184,310,858,162,869,984,401,765,446,392,666,468,518,778,218,963,566,102,738,380,401,480,687,787,887,465,555,637,878,362,34,448,783,861,746,163,338,134,991,608,909,634,605,843,350,757,624,941,975,286,71,965,932,973,98,226,98,886,565,853,621,655,884,420,895,926,757,820,321,900,524,717,849,462,537,69,182,77,462,414,364,109,820,67,39,456,351,762,783,882,477,380,960,350,165,397,928,614,872,44,164,905,489,559,72,164,915,118,93,49,630", + "794,444,694,817,204,437,276,537,801,329,926,51,916,151,508,663,626,815,281,254,294,756,674,192,982,484,346,607,415,52,952,681,356,942,912,247,343,486,556,287,490,718,795,534,386,947,559,870,182,871,769,771,993,649,703,358,591,722,771,747,308,793,297,296,415,833,979,849,596,137,242,416,843,106,377,824,803,378,313,615,778,355,780,979,24,958,334,617,263,372,927,787,328,28,204,893,446,276,397,908,474,735,70,579,371,224,568,39,600,315,349,730,642,831,286,964,775,636,220,642,899,684,400,70,566,405,752,129,747,60,11,423,58,296,596,462,782,507,505,643,198,967,154,495,818,194,387,614,457,192,598,145,505,773,984,891,276,737,332,545,330,289,580,597,368,469,61,685,793,443,833,999,374,192,415,195,144,195,570,880,839,304,908,785,19,95,501,693,377,279,934,23,824,384,538,703,428,724,694,294,263,620,505,871,933,356,64,257,332,742,833,272,157,214,406,237,861,717,818,517,569,962,969,322,143,758,88,690,497,271,231,363,347,200,378,45,36,396,333,250,13,881,790,950,244,70,913,319,261,975,112,104,156,75,295,956,588,447,31,260,493,406,864,443,228,400,227,694,47,844,87,923,604,557,557,592,75,423,460,413,115,598,771,868,248,648,759,336,579,365,262,487,73,247,863,702,924,203,105,859,814,428,481,208,205,560,502,351,196,654,723,453,654,781,41,578,246,841,681,824,39,430,921,76,148,104,275,541,955,872,480,701,465,154,364,974,444,483,444,288,534,769,512,784,112,714,287,361,214,476,811,440,427,446,968,790,820,698,449,927,236,271,778,491,75,558,766,580,288,516,809,663,659,282,93,115,785,575,251,935,424,540,871,647,322,352,354,380,669,282,309,265,637,632,917,935,210,799,162,481,33,388,1,529,76,988,936,274,532,385,63,928,755,505,787,236,87,520,33,127,540,145,864,587,123,391,40,671,273,890,523,973,223,463,701,844,739,353,444,716,152,43,674,278,740,393,948,733,345,741,50,746,976,221,525,570,892,174,457,309,131,171,289,921,45,586,47,513,597,114,85,816,255,656,249,391,581,726,403,876,734,255,2,711,17,105,298,742,332,306,184,624,813,608,211,380,127,961,405,670,31,10,406,668,693,598,994,891,855,441,892,57,649,70,698,340,865,60,492,106,78,588,467,438,576,420,898,945,143,867,405,206,932,369,598,583,382,958,402,193,112,787,459,124,710,611,454,403,81,367,787,633,945,664,665,954,309,200,410,292,265,667,223,60,23,931,536,525,790,489,325,974,756,993,38,733,302,192,239,509,928,885,197,80,845,596,819,671,111,962,202,141,469,807,107,562,741,781,329,925,974,367,872,43,403,925,732,434,294,848,216,457,833,256,351,809,0,860,112,803,200,634,816,822,552,957,476,381,927,225,957,842,622,70,136,474,17,73,619,943,505,192,645,184,353,602,327,922,735,715,879,474,426,733,732,981,303,518,859,372,622,144,838,267,637,534,631,992,362,322,484,53,299,242,180,373,337,236,455,645,456,366,725,757,772,491,539,699,68,902,936,475,447,59,249,810,810,810,658,549,913,937,406,932,652,311,706,61,690,820,657,323,544,528,711,893,953,879,943,682,361,132,424,598,869,354,720,411,880,890,495,366,876,656,309,850,519,134,926,757,943,837,762,902,718,211,71,651,15,11,304,931,753,96,267,138,939,252,368,663,468,637,638,645,826,224,206,539,94,106,330,464,368,225,467,280,63,858,671,523,652,692,860,213,698,441,727,753,632,45,665,28,472,60,675,733,50,713,668,211,607,158,233,151,697,337,354,563,748,273,427,32,373,596,730,840,521,208,82,314,11,527,375,591,198,656,559,891,680,75,965,700,195,861,119,900,625,584,608,188,799,500,66,170,774,556,38,825,267,592,67,106,42,622,88,333,796,529,185,898,403,380,643,41,995,49,617,739,466,453,749,755,845,459,683,60,749,424,324,242,33,200,349,750,322,22,433,6,812,819,200,720,692,147,143,420,648,85,23,666,78,493,317,676,465,919,412,350,753,135,911,586,952,435,260,827,206,211,52,274,298,389,882,122,141,586,427,149,192,24,582,802,232,981,498,451,853,961,817,255,99,823,252,366,466,966,468,953,434,442,397,799,198,747,692,150,416,697,180,561,761,275,655,428,488,620,605,453,388,83,788,243,243,453,263,715,192,433,82,512,405,37,886,131,333,513,901,845,476,596,664,972,112,688,747,385,102,862,104,322", + "689,399,608,726,620,910,353,115,724,994,197,782,147,542,841,202,720,874,100,59,861,697,675,893,699,738,238,134,282,758,584,948,544,937,429,761,499,292,140,377,682,257,389,279,648,911,257,986,662,344,719,103,211,106,120,536,420,508,162,28,493,220,111,488,764,604,720,63,74,486,428,951,250,51,725,795,564,966,407,878,224,461,649,430,514,654,673,969,55,306,766,499,475,643,195,991,556,639,651,733,521,354,985,434,281,108,680,866,737,559,819,152,384,940,764,325,708,530,142,420,479,847,459,297,738,663,422,435,352,217,467,52,219,204,380,734,195,388,823,563,621,377,42,490,378,674,891,663,308,464,937,224,786,808,568,746,465,414,693,415,175,481,459,283,415,903,72,958,370,498,409,879,314,777,596,882,40,828,210,257,983,704,561,997,584,202,678,776,626,750,970,875,779,695,891,96,437,507,700,247,559,721,519,66,741,834,718,512,478,132,483,680,734,244,948,698,55,769,36,783,457,798,846,88,665,761,144,690,166,269,751,497,599,894,78,17,188,355,736,813,108,40,72,833,169,185,412,222,47,842,870,273,49,902,675,694,86,425,231,959,607,797,19,315,305,169,602,576,549,96,550,526,325,910,691,98,736,764,660,815,58,95,123,18,357,891,24,548,404,956,198,896,393,122,733,962,507,881,738,912,997,359,535,558,6,309,228,260,75,51,18,463,726,384,171,741,18,870,775,587,20,666,315,768,456,930,884,636,869,571,564,31,327,228,18,855,899,5,534,892,903,798,552,725,596,595,36,866,921,229,370,791,690,183,981,570,594,443,49,271,396,673,931,837,94,607,872,276,659,256,573,830,533,936,867,917,268,516,801,443,128,479,487,558,661,780,64,667,341,788,339,372,127,395,152,244,797,676,763,721,845,932,832,211,810,392,669,619,259,175,689,798,11,118,320,575,434,12,172,174,996,511,583,212,473,962,336,68,86,793,801,69,141,8,71,69,906,8,788,303,457,777,680,928,757,290,21,910,93,116,466,867,331,782,135,875,426,879,871,61,45,659,601,690,95,309,277,601,614,349,901,338,571,93,675,533,46,583,996,156,210,917,818,116,147,973,766,763,740,479,599,763,944,844,771,829,961,5,750,560,117,708,57,887,46,954,764,697,370,550,456,399,282,95,230,645,582,320,100,917,744,699,205,752,191,794,577,891,534,576,733,398,1,512,41,372,637,80,938,449,30,707,461,572,467,868,971,907,678,9,480,409,390,53,943,993,445,994,54,879,508,332,850,25,51,873,707,648,395,705,532,954,298,795,265,495,165,246,110,181,875,462,999,931,239,929,676,403,504,31,937,728,787,769,157,860,496,608,60,341,824,672,594,150,712,926,742,474,831,316,208,744,237,64,295,849,860,0,882,202,252,271,767,733,778,793,593,926,295,604,428,839,690,694,691,937,131,646,881,657,973,60,419,883,738,35,795,910,422,148,261,603,846,287,266,826,581,499,989,270,628,243,929,778,803,496,3,646,637,944,329,247,157,965,193,772,964,585,953,864,476,275,547,205,86,968,328,285,555,502,846,681,803,261,879,62,90,85,738,392,831,451,899,569,745,604,724,406,616,732,74,412,448,459,690,36,6,170,380,632,63,322,777,670,625,950,987,423,334,430,746,459,724,24,635,787,106,317,362,886,61,992,30,720,781,903,909,60,388,124,51,236,624,757,780,420,179,61,264,557,580,451,545,927,586,448,61,359,625,906,418,323,846,393,293,120,55,90,59,104,383,544,387,712,222,214,164,323,974,785,92,976,94,679,109,686,425,996,368,465,551,163,445,13,15,298,536,806,931,541,858,947,486,313,624,564,343,833,22,412,745,306,165,270,496,87,135,217,545,997,914,652,411,568,218,251,341,811,381,147,229,474,960,743,418,186,688,244,641,238,336,712,922,134,118,892,23,387,447,73,256,241,316,406,759,429,16,262,80,804,797,747,27,632,424,477,879,786,216,465,721,888,239,435,273,802,726,826,841,44,507,284,731,498,135,530,67,220,485,238,949,631,375,220,654,782,740,211,290,616,236,244,668,867,999,491,685,631,899,250,543,574,190,779,905,754,177,707,812,792,471,976,338,607,710,91,637,744,339,292,69,467,40,853,764,546,239,800,132,733,17,691,222,621,801,413,425,654,25,557,918,611,41,100,125,365,964,961,791,785,678,386,339,353,445,182,964,281,885,601,291,217,284,469,289,41,73,651,90,534,900,270,473,837,772,179,811,155,184,988", + "778,956,28,301,287,834,224,226,916,902,56,355,669,523,665,665,392,389,25,820,684,357,315,247,593,995,997,557,834,967,106,248,562,865,830,759,127,337,420,79,149,403,602,433,983,338,170,248,84,922,587,836,377,139,879,190,515,264,740,263,216,837,263,754,950,152,788,288,408,256,638,435,834,321,569,549,250,302,458,692,599,424,507,643,653,271,489,47,334,287,524,716,89,110,71,197,461,838,660,289,394,573,872,703,757,284,615,383,139,368,262,275,581,988,897,686,175,284,442,193,400,261,796,961,880,966,114,568,721,823,262,873,589,11,519,703,590,902,790,456,79,289,504,10,422,78,812,978,457,497,498,888,666,3,530,148,33,577,26,731,271,500,959,907,560,938,524,260,887,18,740,418,376,434,2,512,635,208,439,155,432,201,741,897,504,204,484,212,395,18,668,577,754,352,57,768,380,860,466,908,884,146,492,879,537,777,477,825,103,749,745,353,19,124,321,175,318,263,780,910,605,888,120,627,743,165,91,770,574,181,711,38,831,138,924,511,244,16,632,845,61,416,969,417,168,709,559,975,37,681,344,575,401,258,957,204,5,773,198,790,907,228,495,683,477,798,667,36,88,523,702,110,962,140,498,164,237,433,726,972,436,280,513,153,875,117,727,702,492,674,582,958,259,776,702,66,580,834,998,869,103,765,999,535,519,641,329,464,391,272,937,119,805,896,513,788,514,480,714,194,784,65,562,370,254,269,8,771,566,176,726,938,951,134,754,852,940,705,614,898,593,933,474,828,496,260,39,464,499,237,272,40,316,329,422,3,606,224,645,862,170,781,168,961,911,435,597,549,167,965,299,55,817,550,243,201,747,229,646,22,931,53,269,942,620,688,334,210,411,693,845,262,443,872,592,681,544,131,726,977,127,385,962,233,259,829,598,385,12,850,10,338,108,702,451,315,102,792,710,971,740,535,447,409,648,448,233,213,771,379,348,132,966,65,832,284,371,935,993,430,488,694,502,665,519,230,897,215,561,438,461,241,202,164,174,473,567,575,257,597,458,693,195,928,518,234,222,159,929,288,13,376,616,902,445,102,251,109,785,847,511,967,904,385,743,721,650,165,424,869,14,498,501,234,707,243,55,399,801,732,499,724,610,142,460,610,390,470,848,606,801,945,312,107,975,731,659,955,55,307,996,61,561,57,717,698,708,226,515,986,462,968,180,687,445,608,244,987,248,441,435,285,555,634,952,176,568,281,155,714,85,108,482,24,422,589,388,624,437,554,502,268,953,281,527,354,240,488,84,989,990,707,898,710,770,348,377,796,319,29,177,369,814,915,161,216,694,947,283,280,862,516,561,425,943,211,839,896,355,655,524,261,360,919,799,126,942,586,82,775,954,884,251,682,998,628,112,882,0,183,204,572,358,838,779,128,330,387,560,979,853,595,201,598,672,65,721,38,771,338,699,586,413,770,162,638,13,191,417,161,520,432,525,407,84,806,209,93,748,825,571,767,875,611,769,550,598,940,803,74,317,812,961,405,401,922,790,543,568,641,22,100,98,67,48,194,636,800,932,473,420,714,976,477,749,651,671,185,606,210,494,453,191,290,115,468,322,528,407,793,939,730,92,274,564,622,451,870,501,819,42,391,454,41,304,189,123,395,329,887,258,754,975,541,102,15,150,672,781,821,738,607,387,348,691,900,530,225,350,756,303,870,768,28,405,210,203,430,477,837,625,889,781,491,287,816,754,70,258,376,682,916,574,14,793,652,849,181,935,192,616,444,759,633,875,281,252,807,351,125,732,552,442,616,805,311,699,13,746,644,650,725,334,976,538,454,947,763,256,534,716,415,373,414,245,171,677,272,966,927,28,974,362,63,86,276,340,392,970,796,861,567,74,392,302,579,584,511,444,49,309,313,854,933,488,19,427,631,389,906,456,82,139,362,615,997,99,777,208,634,240,825,860,19,326,927,497,637,936,255,786,35,377,195,383,284,754,297,779,77,783,865,337,593,271,354,855,835,983,608,505,781,495,194,990,930,486,205,745,628,724,577,875,99,989,535,527,367,304,897,370,187,416,993,678,460,312,810,171,214,993,10,79,21,700,114,945,29,745,909,235,731,873,983,980,147,292,423,956,961,470,369,721,242,327,981,729,970,481,809,505,321,43,473,502,107,263,571,567,213,386,974,134,615,503,840,690,580,584,610,958,31,268,319,361,461,961,259,896,578,702,407,98,265,965,475,128,80,150,84,427,939,540,752,703,245,326,843,173,46", + "983,210,318,895,178,181,468,983,513,899,960,771,256,243,632,70,231,619,147,502,190,456,927,728,978,869,940,383,826,416,564,585,899,315,552,372,465,530,153,208,750,710,21,446,896,804,794,3,407,996,357,31,647,178,192,747,203,399,566,536,166,654,501,713,580,127,634,986,561,571,552,692,579,824,862,183,695,543,21,783,410,12,54,522,338,965,919,672,813,408,497,559,814,641,954,161,732,940,659,642,448,465,100,412,248,758,920,117,377,507,322,503,95,541,248,884,299,446,629,619,556,453,631,109,213,263,361,436,459,253,170,723,118,342,802,4,423,25,677,518,275,20,923,769,152,83,595,414,36,305,262,621,915,680,445,769,920,9,715,744,288,739,963,93,817,29,328,355,580,334,901,406,23,59,468,979,877,401,435,613,680,475,995,508,793,73,397,657,153,341,740,65,493,189,325,69,610,894,414,413,319,219,80,537,774,663,392,23,330,48,248,6,260,343,859,89,24,507,691,247,619,269,987,677,979,463,461,830,797,308,859,796,627,611,779,615,704,788,247,486,797,354,120,710,957,878,221,523,87,667,726,554,88,231,216,368,9,853,526,394,234,193,343,405,425,938,284,909,392,858,178,284,673,557,283,190,37,879,35,755,245,790,805,625,638,128,342,424,941,924,133,131,814,466,232,260,58,33,764,481,297,661,911,426,965,591,950,472,232,413,891,637,893,556,690,425,200,508,194,625,319,954,945,369,727,877,826,956,403,37,688,252,485,408,227,622,630,372,881,256,612,343,485,714,533,577,379,704,118,169,896,738,482,563,602,613,284,635,251,424,631,372,781,472,554,508,122,52,929,857,239,290,684,969,82,921,29,265,53,907,637,793,186,661,612,31,424,311,797,761,606,532,215,603,469,359,959,467,142,771,746,860,284,369,850,245,924,946,390,797,538,274,652,879,87,239,287,454,836,427,125,54,264,895,23,23,914,732,32,394,554,59,311,430,16,755,196,620,97,35,660,647,866,297,359,925,446,160,471,785,112,901,438,104,537,622,900,256,118,175,813,711,609,64,344,100,178,952,339,375,862,490,446,833,455,63,353,856,521,369,520,785,983,874,112,550,691,847,188,265,501,992,692,472,241,44,417,21,204,934,604,530,523,90,873,680,911,409,711,206,616,107,983,754,555,798,898,291,958,973,385,878,154,597,527,922,693,864,861,241,447,400,742,518,351,289,273,28,230,493,955,655,965,396,745,297,268,898,454,564,352,157,133,429,422,955,121,301,356,288,697,141,889,826,314,735,470,635,331,909,183,984,227,40,657,541,896,576,20,586,250,679,577,570,98,346,933,386,621,906,294,551,579,915,291,474,204,311,815,977,691,366,148,868,521,332,301,244,199,874,131,574,26,515,346,614,803,202,183,0,1000,927,187,639,416,761,795,317,894,32,79,640,896,461,90,309,768,631,59,598,817,643,215,18,98,509,546,504,98,28,137,83,323,321,51,310,724,86,255,334,534,338,52,512,748,499,608,164,357,382,552,438,770,834,299,991,795,72,932,532,372,446,475,139,619,653,659,362,362,303,824,237,305,989,371,739,355,583,47,815,105,700,755,709,577,973,766,975,654,457,180,962,460,15,615,576,771,296,977,187,179,925,339,65,756,263,702,919,704,275,110,821,102,473,158,292,368,767,287,847,370,102,918,830,870,645,797,853,798,569,569,614,760,937,51,560,648,162,811,590,562,782,454,704,441,670,16,899,612,607,745,280,747,499,823,481,902,679,233,196,622,326,340,747,551,131,147,826,108,7,656,870,652,902,591,582,837,291,712,628,817,672,621,224,262,815,908,607,764,977,938,953,169,881,886,247,968,327,644,639,720,443,429,831,907,49,411,460,931,455,874,398,82,142,908,5,119,615,213,621,924,271,887,143,883,655,730,15,698,254,584,81,54,736,932,255,587,140,103,279,304,807,201,766,655,199,4,680,72,585,234,975,961,89,12,880,601,936,244,475,297,672,475,918,230,252,267,774,402,47,509,302,174,515,655,408,21,580,930,81,471,451,811,532,514,245,573,614,683,60,992,117,830,721,252,762,182,164,790,49,737,595,924,555,791,492,671,681,352,423,897,653,911,847,680,831,405,44,989,487,84,563,131,223,50,145,180,730,282,977,462,194,522,37,128,166,704,807,692,698,323,670,219,839,34,795,698,743,7,987,721,529,914,236,383,947,890,495,248,634,99,370,680,387,598,386,859,774,87,32,351,657,695,963,134,119,750,795,858,266", + "201,290,326,295,803,348,914,481,758,116,330,275,318,382,771,843,512,125,349,594,688,121,325,420,655,166,369,979,660,386,221,895,117,861,875,58,705,748,405,236,874,210,748,285,684,908,808,870,338,430,563,976,305,868,321,558,948,806,704,652,194,588,688,989,692,870,77,40,874,7,289,619,524,67,690,738,780,211,578,550,176,555,69,9,412,467,675,709,346,260,970,936,110,727,855,926,293,66,274,108,32,334,749,27,813,242,918,73,494,860,885,348,613,164,290,924,15,441,327,592,982,531,627,865,946,263,499,886,8,716,23,208,217,83,268,864,282,617,523,718,341,522,80,434,614,96,56,776,439,493,303,954,699,400,165,574,680,254,93,48,174,875,727,930,515,942,757,55,263,623,330,186,803,815,366,603,9,240,224,432,758,745,834,471,938,902,515,96,162,206,925,926,982,903,627,227,628,611,731,722,943,360,466,880,365,660,414,118,839,517,962,703,999,364,922,491,417,949,759,983,775,434,955,67,779,893,808,214,393,511,329,427,164,45,744,259,641,415,593,927,865,147,936,729,734,31,425,720,373,391,781,483,231,642,12,261,405,429,959,796,889,428,654,294,545,863,368,645,996,885,260,56,990,936,721,949,187,287,989,74,464,567,279,808,549,188,692,596,297,140,813,336,1,993,746,697,362,874,757,771,816,832,79,302,337,45,20,129,550,834,745,494,908,30,435,405,406,84,589,319,931,114,938,101,13,811,28,596,844,588,675,695,778,106,316,595,565,358,418,518,31,43,794,851,468,420,788,372,74,607,232,103,513,657,126,973,63,641,393,105,237,895,224,173,995,829,742,880,458,632,904,578,807,515,938,861,851,695,983,203,592,82,166,401,98,700,273,476,208,706,775,777,273,419,519,660,36,218,695,441,837,561,927,902,974,883,278,957,364,962,53,917,827,231,628,569,836,342,981,20,247,423,882,426,119,771,352,843,104,166,363,275,123,411,550,803,158,457,506,675,278,975,713,818,254,591,986,399,433,113,733,308,757,780,514,520,665,588,958,557,161,391,953,872,530,104,488,350,112,228,344,906,76,176,152,189,887,229,664,417,463,1,442,328,764,235,377,164,341,192,896,399,388,423,945,127,55,685,499,930,182,487,467,376,452,958,961,693,521,273,42,886,823,472,283,388,525,421,980,608,934,890,209,185,776,659,449,6,671,202,220,100,331,455,73,631,52,54,545,432,430,685,172,465,34,415,220,942,110,527,679,576,774,184,732,325,39,887,513,174,77,62,981,108,235,364,254,365,281,757,321,193,405,637,299,116,847,435,403,472,617,519,690,280,215,138,586,459,749,833,623,205,396,874,255,205,546,988,512,110,758,237,72,66,455,86,169,225,385,137,365,720,747,979,662,786,200,252,204,1000,0,442,742,866,407,951,589,720,73,402,840,746,965,787,444,615,276,212,436,153,730,95,770,644,442,322,172,892,623,797,296,313,195,907,284,113,70,446,129,679,801,480,524,709,588,789,108,996,740,793,896,539,397,271,661,844,697,70,135,410,548,607,236,223,405,609,8,590,592,861,859,623,718,800,949,169,781,128,846,696,688,360,899,257,237,676,497,486,362,744,828,484,757,562,407,675,599,597,818,598,139,104,71,664,770,970,612,390,335,342,663,664,893,585,159,655,890,60,921,979,286,258,729,389,150,612,218,419,840,387,247,560,114,645,36,626,44,536,447,269,415,864,695,387,259,794,618,134,936,499,543,877,986,812,574,668,657,530,590,184,152,174,93,730,390,700,962,972,831,583,752,590,627,476,330,599,737,706,510,54,17,62,658,999,507,809,380,627,728,943,127,659,582,61,4,797,397,380,282,124,83,38,873,371,501,141,697,421,122,837,491,259,563,184,799,923,453,209,821,771,328,607,320,985,418,641,201,327,652,821,25,660,35,889,264,921,985,791,809,888,371,96,713,739,652,645,710,970,28,618,324,898,790,38,232,886,914,219,313,265,918,107,577,85,835,931,841,562,283,846,449,29,637,476,108,917,701,505,75,796,91,90,114,125,4,326,491,413,118,896,907,77,303,409,84,287,116,505,809,57,820,146,538,463,798,909,430,328,707,950,814,484,129,666,115,579,59,181,148,338,462,309,552,47,804,602,967,150,321,549,992,130,852,275,802,89,710,414,368,651,117,713,971,679,958,517,941,137,703,860,745,408,542,295,487,876,717,64,248,600,587,876,500,288,360,911,603,637,21,975,986,987,494,910,266,234,586,640,438,53", + "195,117,928,810,153,372,910,672,766,90,228,409,105,144,541,314,340,732,606,278,735,222,8,15,245,604,351,105,621,742,915,238,354,456,947,511,152,737,540,6,412,206,25,405,670,510,328,598,789,999,830,443,405,306,466,285,105,112,71,867,889,721,129,144,330,33,314,717,482,979,253,840,949,350,862,159,539,904,953,525,804,355,772,663,624,509,493,654,588,986,823,64,542,640,693,50,775,597,859,462,883,902,681,480,67,468,929,462,781,783,5,483,34,401,474,422,165,966,268,342,499,572,60,569,578,139,64,958,413,519,26,712,181,753,563,192,964,44,622,694,632,487,272,813,714,377,952,467,231,487,126,254,430,196,589,491,270,424,804,378,484,599,201,984,861,337,913,637,8,632,165,211,636,708,626,674,384,716,574,200,886,678,360,359,797,439,633,127,82,710,224,451,389,343,343,940,457,322,712,52,604,647,858,933,635,268,884,660,849,105,209,485,899,463,894,477,458,572,109,330,641,52,699,599,2,266,518,303,697,369,954,858,91,840,191,615,277,960,24,129,870,711,765,893,166,119,455,274,925,491,6,465,864,658,189,121,749,575,808,515,547,54,745,894,78,403,819,843,196,719,478,896,899,651,187,537,786,394,344,134,702,936,814,385,144,637,949,27,282,54,290,638,517,564,478,124,885,536,112,39,231,258,669,599,376,522,789,573,291,31,600,945,430,540,454,640,114,801,714,706,512,998,268,243,65,676,86,891,664,223,537,255,341,403,161,458,861,916,340,597,915,923,462,873,93,628,969,343,788,935,832,679,10,541,717,138,527,613,600,347,306,507,245,135,238,178,877,9,828,185,766,762,999,153,868,244,858,693,784,853,896,675,122,907,394,326,417,764,891,848,340,131,773,622,44,252,20,186,942,384,574,240,909,885,753,907,298,200,958,681,514,334,930,996,446,57,322,426,318,998,158,784,847,977,207,754,215,751,681,682,436,445,121,30,255,924,353,322,78,734,660,226,639,663,729,970,52,415,95,290,205,835,21,232,157,574,275,428,870,477,206,254,485,510,839,102,860,856,7,582,939,228,922,727,609,629,240,314,773,913,460,135,864,422,993,178,563,834,842,116,841,787,304,849,331,410,990,933,836,284,211,497,4,944,124,404,181,588,684,22,143,722,583,105,531,694,3,790,453,218,9,266,33,350,516,892,577,946,750,465,348,210,928,124,280,558,854,366,119,678,838,335,702,886,421,5,35,25,379,343,73,925,747,892,328,806,763,945,574,64,600,110,41,319,50,942,160,14,572,338,444,346,870,334,934,545,281,241,106,425,724,707,652,100,825,375,478,889,306,286,397,359,875,100,299,115,277,91,718,639,697,513,92,990,753,805,563,470,101,145,643,604,169,262,837,966,634,271,572,927,442,0,296,184,539,399,502,87,218,691,419,441,297,527,122,442,937,847,623,807,437,746,184,440,458,318,856,100,321,141,520,861,62,319,173,653,498,537,911,709,860,686,319,895,645,892,349,554,549,916,944,471,123,372,894,362,357,241,660,38,827,399,810,268,434,858,790,500,275,762,14,831,73,873,73,413,699,528,559,127,924,550,496,419,773,582,571,994,907,185,294,664,419,30,30,307,608,938,679,409,450,229,278,396,739,368,125,222,707,747,158,985,467,641,144,56,221,522,591,831,459,917,750,329,678,375,801,330,154,669,374,79,993,240,834,355,844,911,771,315,833,869,316,566,43,105,488,853,365,688,627,571,866,967,261,709,307,391,509,311,167,691,562,627,126,73,588,357,115,175,491,691,434,417,71,909,353,244,299,144,719,391,199,386,877,503,797,363,29,472,114,537,368,459,40,573,136,254,716,815,426,304,645,163,311,155,396,623,915,463,250,538,539,514,147,171,739,993,350,763,918,665,728,688,488,75,620,436,533,628,963,667,268,416,973,585,659,504,937,744,392,311,325,493,638,120,832,908,980,408,671,720,827,809,68,330,733,822,919,795,897,510,116,471,43,396,857,200,818,624,541,114,811,117,106,363,436,951,200,619,55,738,862,627,421,386,521,948,395,160,90,970,9,205,828,725,790,402,331,73,58,384,601,931,146,402,140,85,353,779,265,974,603,472,932,530,2,195,219,731,69,996,914,49,651,400,127,619,605,327,202,864,751,297,715,307,201,14,734,479,591,377,138,223,890,503,445,17,363,36,952,61,780,818,127,702,124,966,350,24,596,257,215,530,441,363,651,315,792,211,763,290,541,238,757,877,888,530,703,461", + "905,878,330,239,696,213,885,120,894,543,556,723,214,975,746,103,132,902,865,793,517,964,209,594,919,662,655,522,577,801,760,743,626,816,272,302,511,44,266,811,967,182,410,898,559,710,691,727,269,737,500,425,450,909,532,70,290,285,923,231,610,248,980,247,325,783,107,367,609,822,88,77,271,79,307,412,603,256,55,277,656,414,281,858,844,371,886,99,154,879,109,798,773,8,549,653,247,128,590,83,783,44,780,51,835,991,962,36,995,681,75,303,458,170,177,793,582,557,509,451,303,110,392,979,343,930,541,60,372,178,302,274,187,191,304,361,725,137,385,924,169,285,501,207,362,643,909,661,897,255,971,188,38,888,762,378,28,421,555,3,857,867,104,892,12,441,938,710,328,837,692,97,695,210,903,860,584,5,880,703,385,688,911,736,298,955,857,865,830,356,480,782,792,286,798,131,487,929,224,576,217,957,719,977,933,887,186,727,365,917,184,416,559,729,817,615,690,721,336,54,588,616,618,303,759,636,291,970,175,581,545,767,145,853,974,440,986,829,785,667,178,550,652,773,719,472,993,34,152,355,62,484,340,356,324,9,831,291,342,957,962,678,763,117,814,17,311,398,336,933,669,543,834,817,585,225,207,355,720,519,407,968,788,473,816,272,190,319,157,829,669,26,716,969,422,820,902,857,886,109,594,2,155,96,968,145,154,48,867,67,147,425,325,143,865,333,731,124,311,481,206,120,132,153,521,821,898,127,809,658,154,278,598,201,749,593,246,101,448,563,937,177,416,246,559,958,437,902,686,372,65,295,780,886,743,71,966,19,423,697,845,704,969,226,389,908,2,302,665,942,103,280,574,223,513,715,519,621,945,312,573,338,710,60,611,348,429,579,583,949,126,697,399,846,580,577,756,792,678,736,372,258,407,677,182,254,620,501,917,586,110,173,941,388,735,988,245,754,908,639,350,781,931,725,945,526,588,244,663,374,750,208,562,968,403,696,81,98,844,691,291,137,465,323,962,237,853,503,93,984,758,960,443,840,690,712,191,649,216,727,148,118,926,816,311,388,895,694,155,787,161,557,98,444,413,100,745,334,116,635,716,438,713,658,92,809,723,936,221,626,903,270,727,711,427,212,737,200,879,421,456,701,794,471,464,47,141,995,505,275,456,486,566,783,733,284,999,789,580,119,305,390,891,571,330,511,974,873,136,168,625,616,845,981,812,416,156,455,230,801,663,237,932,38,992,142,999,316,941,456,804,713,480,586,324,432,93,46,836,522,865,417,830,916,724,421,926,747,677,491,38,424,811,86,170,457,31,226,849,368,95,552,90,16,817,700,630,928,509,538,155,912,957,251,314,393,557,685,790,724,303,918,363,11,304,778,190,82,280,708,511,150,982,677,39,920,816,767,358,187,742,296,0,825,856,142,334,333,459,733,391,855,190,54,400,834,956,517,653,452,508,417,853,948,563,49,782,529,594,976,311,520,924,57,39,512,957,502,246,608,164,360,872,734,221,283,491,420,415,206,836,578,952,348,868,624,168,872,492,415,518,13,963,624,455,9,529,481,991,482,216,268,281,210,563,569,703,422,396,67,940,377,886,73,306,90,860,300,150,217,199,641,414,129,409,968,840,785,618,826,79,760,667,22,425,629,95,122,436,159,602,404,83,277,651,23,640,144,788,360,598,293,858,344,430,725,943,102,146,180,861,480,93,398,681,692,830,604,701,27,436,533,257,214,603,626,730,819,677,757,288,802,62,703,428,553,627,501,890,933,798,125,533,948,271,167,208,897,659,358,135,481,864,29,333,225,974,180,998,511,100,257,488,402,405,197,721,367,367,298,197,794,773,36,449,99,323,401,413,549,348,147,589,676,37,241,720,456,203,358,439,193,222,715,882,536,583,947,62,482,351,386,40,176,301,228,979,890,578,696,714,636,634,87,411,188,230,655,639,455,412,700,152,823,36,843,160,780,139,484,232,50,870,166,211,843,235,950,883,840,194,420,330,353,728,608,921,334,350,421,396,579,158,512,783,583,293,139,931,238,512,208,654,400,22,315,555,787,336,222,109,821,500,296,335,807,738,636,737,846,795,381,617,236,87,604,331,27,681,465,265,445,100,237,865,761,804,731,838,718,96,346,828,774,660,706,110,350,559,44,306,103,419,326,215,724,903,123,781,581,761,486,458,774,588,986,638,13,214,584,154,149,609,496,337,416,74,961,405,189,445,423,954,317,718,318,13,591,725,781,941,324,107,923,129,803,830,271,798,829", + "670,725,987,528,80,48,11,18,541,821,994,183,174,109,729,308,703,704,835,702,850,431,346,457,338,483,8,814,39,307,635,590,4,577,329,895,758,812,643,282,200,140,306,257,375,190,889,325,830,827,928,846,644,982,652,76,787,582,852,120,899,801,990,34,83,237,231,258,791,250,606,36,97,267,895,944,978,880,811,605,445,566,346,477,456,923,886,822,562,336,350,117,145,409,561,23,958,955,463,272,943,836,653,157,216,427,986,806,518,852,261,591,101,106,691,851,959,348,192,579,199,546,666,989,502,200,618,268,292,180,821,886,257,737,127,679,3,435,800,301,753,711,614,153,634,536,292,788,793,450,799,603,965,428,776,600,488,345,784,532,934,5,665,994,779,346,804,402,295,562,149,670,917,417,967,198,768,300,623,904,517,138,242,660,475,285,339,763,879,605,704,303,175,953,16,744,542,69,156,354,412,754,784,402,930,116,650,600,702,29,563,42,778,752,909,19,390,52,120,308,511,26,806,346,852,236,25,720,72,888,904,88,642,326,199,528,300,486,824,240,61,903,147,151,951,600,841,770,746,884,699,819,519,57,588,472,373,902,452,447,858,246,384,987,652,654,965,221,632,747,678,834,998,199,324,919,359,973,466,345,416,81,375,247,883,942,346,909,508,31,563,408,94,927,10,962,656,818,680,239,597,177,216,747,397,570,496,737,393,110,457,382,125,940,118,636,470,991,299,664,630,617,251,593,697,687,576,899,877,598,470,73,882,266,288,769,901,711,343,342,119,198,652,619,222,473,224,873,794,628,705,725,282,192,88,331,80,461,26,469,284,504,185,25,155,402,427,737,282,438,602,333,956,83,667,406,90,370,690,886,25,308,603,34,244,212,327,279,109,208,789,43,455,562,441,415,473,315,973,639,773,553,214,878,421,170,871,856,224,591,416,320,42,752,944,718,592,932,3,934,199,879,338,83,466,730,304,75,875,918,279,455,676,429,4,493,833,636,521,514,794,273,66,799,250,896,810,327,475,793,128,88,286,209,51,136,30,203,251,209,965,189,880,976,702,258,948,464,423,433,527,218,401,797,427,128,69,858,338,259,433,822,377,197,841,904,832,454,810,494,831,293,199,962,235,204,431,914,36,663,22,718,245,402,79,309,254,62,375,465,707,925,492,715,252,8,188,426,200,357,571,931,846,636,975,204,731,711,161,431,14,957,426,8,573,505,667,96,35,205,86,534,247,218,197,226,539,686,545,206,358,31,442,439,843,829,629,841,480,271,110,831,728,211,692,995,703,427,194,466,225,409,533,399,931,664,981,978,893,640,947,586,976,664,848,624,91,400,535,273,103,409,728,952,960,530,564,70,852,665,276,466,988,52,835,813,470,334,401,466,327,158,901,509,327,593,822,733,838,639,866,184,825,0,775,785,386,707,247,740,662,709,622,518,93,819,356,472,993,516,706,967,131,720,710,898,851,65,810,974,797,739,517,367,477,93,448,172,686,852,99,653,269,570,166,721,939,764,8,351,18,749,809,441,253,406,184,957,287,650,475,626,766,249,508,866,778,699,625,609,449,890,878,576,700,615,784,996,408,83,727,111,593,36,253,198,196,291,279,111,729,987,734,482,53,171,591,310,55,56,320,974,814,319,281,661,979,448,691,839,698,114,273,124,951,627,76,253,77,165,474,679,871,295,687,108,367,888,288,636,308,731,293,337,949,274,983,682,38,711,769,600,900,171,733,739,166,317,980,219,84,119,676,67,115,894,664,257,323,370,277,256,867,386,289,415,653,410,322,914,181,768,231,674,834,104,398,692,844,386,161,49,798,618,739,548,332,137,614,864,868,611,720,927,76,550,136,619,280,307,9,225,759,340,304,347,159,362,874,563,702,507,629,435,180,461,51,362,151,691,217,436,782,990,212,390,520,769,848,987,403,671,612,391,722,970,43,328,98,996,242,778,166,144,143,197,411,31,168,300,928,291,648,809,731,683,743,614,306,289,176,382,149,72,991,272,842,681,224,802,227,547,668,978,890,215,742,257,142,840,587,890,11,255,826,333,844,644,900,119,221,924,549,58,32,983,24,755,139,478,953,616,676,931,431,829,81,193,725,806,375,425,563,885,335,483,574,483,649,381,912,748,326,171,644,99,90,933,839,998,961,878,885,443,161,197,242,647,550,922,857,382,539,839,616,120,837,822,81,345,780,776,75,475,648,867,110,426,907,918,966,624,651,281,151,597,182,820,982,879,27,488,137,31,427,994,152,96,777,892", + "313,758,173,531,791,903,85,750,793,211,211,481,381,919,590,67,350,344,885,357,457,503,848,678,270,416,21,551,283,936,35,822,898,934,571,104,395,65,486,893,797,422,600,846,156,16,775,353,30,866,18,306,171,633,822,658,741,881,305,658,799,571,824,673,461,822,601,14,27,190,137,376,278,145,401,590,702,881,894,825,157,959,685,397,670,690,173,721,720,157,967,63,318,572,608,46,277,218,808,140,103,238,670,900,572,191,67,881,499,460,146,503,219,769,51,590,567,656,73,496,548,932,364,347,538,21,409,304,90,325,142,67,966,282,776,951,896,367,949,98,589,323,277,685,597,755,613,902,968,569,31,555,499,626,70,240,634,920,741,613,251,457,758,902,630,692,948,626,885,35,950,492,912,783,47,204,355,739,970,335,371,771,843,923,309,294,592,631,84,198,913,290,158,364,290,511,10,426,975,894,294,906,639,284,771,691,98,242,502,403,82,219,299,631,930,349,660,479,722,124,421,282,725,899,747,296,170,506,949,94,596,870,173,212,634,268,481,979,746,378,671,788,75,959,896,238,601,824,372,711,977,806,642,444,560,450,607,787,212,642,984,737,262,202,932,875,581,743,511,398,211,626,584,726,512,932,379,96,110,792,953,609,324,538,9,546,303,993,574,902,881,380,828,682,589,621,740,728,165,159,456,156,313,109,565,306,310,352,159,541,675,940,259,357,371,348,906,699,688,273,706,777,194,842,114,661,657,576,651,747,905,342,985,60,65,197,429,641,264,805,331,884,805,598,753,800,235,536,172,795,905,327,784,837,767,921,525,48,958,934,319,864,342,300,336,912,51,895,167,66,51,240,845,161,54,97,124,955,103,750,888,674,8,372,686,195,330,617,297,971,833,662,741,303,35,364,739,992,278,607,28,168,520,627,267,482,867,23,333,314,618,281,111,913,409,881,652,15,735,515,560,737,132,92,623,398,406,777,86,411,248,300,131,636,81,179,740,798,530,33,936,157,436,206,631,745,937,198,694,341,484,731,237,6,992,141,235,444,601,558,972,405,396,602,528,291,619,238,789,30,856,893,727,803,561,688,637,612,206,762,33,458,556,144,776,355,269,428,256,504,537,772,360,908,46,170,415,745,419,629,974,278,398,466,230,267,263,215,616,475,858,892,377,972,82,618,94,852,953,450,921,927,588,840,715,231,963,603,969,737,348,750,817,382,9,420,801,822,542,875,469,172,205,594,767,940,361,591,652,181,3,742,596,277,506,567,992,808,217,221,87,732,741,536,968,281,825,61,459,538,508,479,456,147,375,994,612,194,715,919,170,552,839,663,512,865,536,615,412,432,472,691,993,961,602,674,912,791,130,761,545,376,708,343,986,135,415,136,423,89,720,813,442,741,855,145,552,778,779,416,407,539,856,775,0,288,160,61,486,996,929,475,663,351,944,819,351,285,848,704,708,959,743,736,845,490,48,908,65,369,121,720,317,242,262,302,498,623,554,837,880,915,679,36,631,971,403,856,603,42,81,579,969,833,322,879,626,291,654,422,278,623,630,420,999,300,729,932,763,599,972,790,247,752,662,617,296,395,989,157,868,138,681,816,595,645,254,67,102,82,122,952,858,504,706,264,671,952,228,360,331,945,579,151,906,667,177,525,241,912,829,544,646,238,616,523,221,771,467,84,46,411,954,460,206,366,706,887,206,299,416,143,346,265,251,636,418,382,24,678,373,576,491,469,75,287,701,312,126,243,117,892,939,668,638,118,565,864,37,447,461,265,438,975,790,688,610,772,457,635,143,339,624,799,838,595,258,248,514,63,105,379,421,11,967,658,925,646,191,219,646,354,150,628,698,854,156,733,276,197,304,334,493,327,427,320,848,835,30,879,197,106,722,120,746,758,199,549,558,788,752,5,342,951,234,261,282,717,176,897,137,137,752,446,477,948,340,807,288,637,405,500,935,436,352,499,78,794,941,63,92,520,418,59,679,146,761,762,918,994,519,772,311,286,709,322,414,635,735,810,189,699,355,371,883,202,985,573,999,390,691,437,64,516,858,289,7,496,864,375,752,505,738,932,123,156,709,872,849,55,975,319,261,408,392,694,905,196,244,136,915,530,901,860,258,824,357,19,249,91,66,450,664,742,231,187,807,11,754,545,76,796,806,758,131,219,30,208,638,844,244,626,850,835,181,663,959,891,805,405,996,131,454,573,782,963,182,518,372,935,364,656,432,124,159,165,711,148,900,532,127,142,761,730,325,881,592,513,667,761", + "555,453,553,733,526,74,168,538,542,649,800,579,730,467,757,913,254,935,158,689,879,518,301,445,997,198,981,699,439,49,148,394,109,703,169,814,360,849,612,427,824,626,419,776,986,581,781,153,755,986,765,47,322,266,265,711,489,460,397,333,735,258,564,277,66,678,479,711,618,66,776,517,676,975,985,500,180,999,777,486,939,617,754,360,70,751,33,527,935,754,490,199,541,797,93,155,157,866,439,145,863,255,734,475,801,378,13,968,475,244,411,912,291,470,744,209,492,655,312,508,645,497,862,987,578,339,159,560,180,388,792,962,693,36,336,697,94,957,21,686,26,401,341,949,651,462,453,774,894,874,902,903,284,26,744,911,892,794,957,86,469,413,985,649,889,445,216,231,767,473,991,987,612,733,69,645,933,754,75,577,401,37,540,354,762,372,957,80,473,705,874,944,225,194,108,857,107,230,941,776,798,99,818,368,626,475,155,937,617,900,268,532,902,364,462,964,804,382,192,415,298,461,376,190,602,531,348,918,538,195,869,668,917,323,58,129,192,387,169,909,100,538,936,600,819,869,705,3,525,240,352,647,651,909,159,914,96,553,474,89,151,597,644,573,908,569,168,965,613,469,79,802,186,97,470,194,129,374,355,372,319,155,34,998,928,313,500,258,652,589,891,344,986,293,385,60,921,359,65,30,232,753,478,125,621,280,471,876,292,854,926,635,400,79,262,889,326,660,770,35,148,655,940,351,736,826,904,690,441,94,603,729,287,255,112,101,786,180,728,392,525,705,705,363,968,317,902,77,974,89,279,206,668,518,318,240,281,275,785,440,737,129,940,485,59,351,710,8,284,32,786,516,473,528,126,776,82,6,566,883,271,92,326,903,240,853,540,224,483,705,708,341,748,335,486,54,176,873,946,904,248,688,848,784,782,861,225,749,642,879,560,360,910,740,751,868,903,985,567,256,396,454,865,430,983,423,206,729,684,422,162,924,669,661,914,31,941,6,381,667,602,615,593,154,466,641,189,198,172,988,540,219,935,889,367,320,728,548,251,954,432,587,496,875,407,123,372,745,366,795,244,402,115,844,86,27,311,504,676,858,952,197,818,873,158,830,413,47,348,104,343,133,724,484,500,55,771,124,536,635,307,151,537,887,969,318,148,129,778,810,285,312,751,193,443,973,237,583,5,828,826,321,360,393,591,454,347,724,275,625,364,989,599,807,652,56,78,38,527,809,292,878,468,449,69,273,392,271,712,469,937,797,694,360,263,204,448,397,872,752,584,746,375,423,855,3,122,106,715,53,191,522,936,54,842,859,603,708,322,817,824,896,427,241,252,464,260,441,129,316,857,425,187,797,142,796,259,906,386,342,193,103,591,906,569,494,41,990,621,910,905,69,903,916,765,605,957,793,128,761,951,399,142,785,288,0,245,635,906,580,678,689,467,261,548,946,914,243,966,474,36,54,464,659,23,924,393,434,336,163,107,40,135,737,974,733,935,143,192,102,925,147,192,665,906,52,851,785,613,182,853,996,334,172,386,243,137,846,769,793,851,999,889,754,375,737,210,267,620,118,958,641,456,894,271,269,438,963,458,68,457,88,252,270,779,494,531,822,183,427,21,39,142,49,421,782,658,976,208,831,410,714,811,754,544,812,441,422,306,134,139,120,102,941,329,911,943,4,724,543,925,247,159,174,782,343,295,254,276,680,231,770,801,396,977,874,496,384,551,180,475,72,383,301,477,373,972,31,188,734,995,200,273,481,781,446,539,273,811,478,858,240,434,952,464,261,30,990,578,906,80,32,241,599,717,363,949,953,503,530,106,712,432,792,129,215,106,195,394,452,478,603,808,671,477,897,388,317,405,568,145,542,906,247,164,766,968,635,782,650,286,706,221,508,844,376,295,984,848,927,650,177,965,821,58,956,36,585,500,835,564,502,12,921,656,17,526,179,24,382,503,443,58,217,945,998,375,868,641,222,630,428,344,642,458,455,52,630,850,323,545,34,781,562,248,720,659,963,452,17,125,372,115,654,829,486,711,579,398,109,843,198,165,26,729,802,88,108,238,814,953,148,965,650,543,664,810,813,770,641,911,550,801,772,804,279,919,392,826,503,944,260,814,945,862,474,84,271,831,23,568,206,365,872,353,79,386,349,627,572,768,564,259,997,587,137,202,540,765,826,761,399,856,957,955,478,319,107,785,557,471,61,312,468,890,760,352,374,916,782,493,472,737,600,884,752,314,379,982,740,858,904,574,615,938,955,949,73,837,428", + "762,652,181,988,923,969,3,756,433,562,573,966,542,435,63,96,832,736,895,959,614,651,624,206,186,971,280,979,380,33,672,644,943,220,894,50,437,196,617,297,631,937,919,535,463,804,90,19,875,452,130,406,808,881,840,348,27,208,407,517,506,853,339,386,655,523,872,870,378,484,621,10,645,128,263,323,90,300,563,313,399,788,694,787,179,477,538,548,668,968,224,113,224,791,559,525,20,509,372,433,186,576,303,711,288,668,665,571,195,137,452,384,431,700,643,444,713,251,454,19,887,682,914,451,380,87,990,202,969,33,284,105,46,360,250,247,36,262,508,927,704,914,266,679,778,676,561,887,528,366,575,180,86,613,316,408,351,716,313,229,598,692,838,123,937,590,141,491,453,26,546,879,67,443,917,668,88,233,805,446,853,440,127,355,988,237,607,445,97,795,951,171,528,561,883,209,552,411,511,640,495,311,258,670,514,559,654,735,601,505,455,52,487,47,635,837,463,262,287,251,510,541,293,372,898,772,476,832,332,320,29,347,527,368,58,681,755,955,754,721,755,403,428,809,251,370,276,125,485,970,593,596,229,365,484,151,927,538,859,754,73,812,494,967,963,323,205,609,632,820,82,721,776,672,74,9,192,289,881,583,809,792,420,153,137,757,757,904,524,613,425,938,806,589,615,64,116,878,910,363,512,422,416,812,321,476,688,893,276,964,906,907,620,107,203,231,966,424,135,103,405,878,917,903,163,550,106,955,738,751,811,864,816,644,361,514,860,392,828,5,914,762,751,615,899,618,639,562,566,137,490,836,354,491,441,151,984,521,229,580,950,963,90,200,692,285,207,38,776,984,217,226,498,109,241,919,747,950,895,426,90,768,890,299,47,338,750,365,11,150,481,368,549,56,554,282,811,761,78,740,149,690,756,363,288,749,703,711,814,585,426,160,842,209,371,768,538,973,57,898,391,172,317,76,218,452,274,374,929,789,152,973,826,753,346,767,494,790,901,711,322,159,869,549,70,665,183,983,629,712,267,803,889,708,433,725,413,49,231,347,879,923,526,280,20,592,317,988,491,784,51,918,968,378,410,723,826,529,801,250,865,603,429,306,143,978,918,721,713,213,86,581,209,182,837,409,529,78,185,66,242,709,70,238,774,571,668,815,353,390,647,668,65,77,587,278,914,633,509,673,986,65,136,63,921,682,315,209,185,299,394,435,125,233,570,763,46,720,989,80,164,565,713,190,621,593,414,154,311,574,321,255,933,945,231,601,727,867,290,180,171,253,484,728,602,77,581,160,410,773,246,275,511,919,581,976,898,849,961,820,776,855,851,154,933,830,566,386,639,239,750,396,629,816,518,304,206,130,492,41,707,856,136,600,943,174,940,854,312,425,559,544,442,792,519,238,476,593,330,795,589,502,334,386,160,245,0,124,434,644,493,55,721,44,922,35,948,115,933,107,429,983,600,462,161,644,875,428,678,518,744,74,783,649,356,135,721,356,574,688,557,711,367,567,358,955,973,266,991,737,628,441,143,685,342,436,159,173,41,300,123,401,60,997,429,789,165,329,30,70,301,597,600,329,496,722,17,220,96,261,60,560,625,116,661,202,108,68,940,119,117,72,513,197,382,666,785,891,602,356,533,777,270,920,581,792,321,945,549,546,748,727,902,762,329,329,408,176,680,856,344,421,231,689,232,794,729,927,130,93,20,824,846,651,657,522,675,154,542,103,960,274,155,715,590,336,404,199,111,295,696,367,509,980,872,710,33,545,369,158,545,835,531,886,480,708,891,691,232,11,548,47,825,675,848,38,134,950,885,254,959,397,299,428,803,950,52,381,706,773,677,296,649,753,757,836,791,697,645,642,299,429,615,405,816,524,705,314,512,297,384,985,386,158,93,177,238,895,831,569,7,703,884,863,847,252,801,877,17,120,481,61,569,644,780,156,276,621,934,637,614,444,9,586,17,344,959,207,868,638,94,222,904,985,220,556,530,237,348,685,561,977,423,943,411,217,110,811,453,760,116,430,225,114,175,317,454,345,468,896,680,245,926,300,752,580,901,81,892,530,735,543,802,260,272,923,807,674,932,546,743,568,52,210,670,543,106,120,321,839,251,336,86,797,560,964,278,804,205,656,648,488,547,7,257,750,552,392,291,819,244,430,537,35,956,264,238,659,824,441,861,537,587,276,506,22,198,808,735,37,25,686,272,144,218,920,598,253,71,567,355,701,207,983,633,267,672,796,182,318,559,829,105,407,934,587,144,680,867,478", + "962,41,402,941,824,145,38,455,208,588,260,600,115,826,180,326,994,895,453,138,570,699,388,503,719,719,888,252,511,20,95,154,940,63,386,435,39,233,496,309,406,465,445,602,642,747,283,45,828,818,224,589,147,288,681,941,637,405,928,336,482,772,12,415,509,444,478,954,715,191,182,89,246,793,720,867,522,611,264,68,106,695,619,391,805,233,316,766,107,601,378,914,261,995,897,717,761,604,736,164,788,306,354,934,148,955,433,876,473,469,573,12,107,147,943,600,284,242,613,327,655,381,529,955,401,95,37,532,677,915,510,634,484,273,992,553,243,863,748,265,980,390,632,580,148,966,983,854,63,735,43,70,45,674,367,668,443,559,294,140,472,244,617,530,999,832,194,437,949,354,476,373,527,661,120,985,558,202,205,727,152,341,333,779,688,77,92,659,811,648,685,663,419,962,55,308,932,12,758,201,428,990,180,288,871,130,764,117,815,222,291,387,869,942,741,821,156,450,486,855,596,295,344,811,451,377,177,123,675,784,77,417,612,188,503,947,423,823,128,511,321,603,173,737,937,113,690,22,679,995,763,968,48,629,594,717,210,641,133,322,714,982,129,165,811,788,26,283,92,134,41,318,451,883,976,211,262,998,90,571,876,736,865,360,939,656,246,217,822,643,25,319,639,461,773,674,398,630,183,591,612,492,634,495,355,767,303,854,131,998,393,231,570,147,371,733,46,284,230,585,530,274,914,112,645,939,364,974,648,228,376,757,331,67,290,186,713,428,206,422,534,786,506,912,857,262,107,434,478,139,330,619,66,881,590,429,862,218,62,328,882,461,802,649,916,611,687,898,88,107,313,768,26,540,809,477,953,374,185,460,220,636,996,495,895,861,819,198,880,47,561,683,850,760,346,196,97,238,15,230,261,515,924,215,226,889,926,206,234,467,415,905,440,190,650,221,929,481,266,770,696,191,547,867,426,937,397,633,5,492,862,783,266,52,207,371,538,74,588,460,782,695,948,776,340,285,127,407,625,449,971,897,796,271,392,732,936,192,533,232,983,519,247,553,86,688,675,365,435,583,439,657,272,32,326,458,79,12,346,884,241,298,469,889,275,913,874,85,304,760,424,810,875,479,648,631,975,908,892,384,668,660,710,850,478,919,11,940,464,643,613,863,865,970,821,529,963,526,772,7,967,269,877,234,455,781,781,326,172,320,448,312,3,988,352,966,86,652,910,111,431,322,684,985,851,111,355,720,268,587,146,387,389,238,695,558,344,825,582,908,97,135,453,158,323,26,792,180,496,961,608,205,618,240,310,606,630,428,897,513,115,220,707,644,294,104,116,642,703,519,237,520,99,200,218,731,318,981,795,496,37,116,814,758,358,53,875,751,267,685,263,783,122,860,601,173,381,926,387,317,720,87,333,707,61,635,124,0,479,597,404,716,867,870,183,77,932,345,187,818,318,133,842,156,209,509,804,650,2,543,948,528,404,388,70,401,97,91,296,376,191,934,616,873,143,200,831,343,207,625,610,862,250,269,36,980,872,921,360,768,929,459,792,169,315,720,764,562,643,52,818,800,66,797,917,991,821,854,814,495,713,159,421,328,813,291,625,838,218,179,408,239,826,743,272,318,953,131,746,709,592,769,462,735,429,109,576,171,270,836,30,922,190,69,655,455,774,732,175,140,263,595,954,56,632,471,705,117,501,48,196,258,27,544,505,162,780,802,804,128,534,711,297,490,568,165,908,571,946,526,403,180,521,17,161,185,81,743,488,725,761,32,429,711,625,699,917,382,546,743,155,317,90,622,707,437,741,883,459,722,890,595,9,395,495,314,439,945,25,449,127,514,320,164,688,656,378,71,135,419,512,401,130,677,872,530,712,849,891,292,552,267,864,38,96,147,483,97,51,337,214,431,205,514,674,46,427,781,289,390,307,96,619,151,69,911,518,967,699,347,243,427,578,793,747,762,542,127,354,69,475,896,820,111,899,805,199,445,359,31,662,353,253,789,393,14,847,940,57,909,773,604,208,971,64,545,258,364,297,913,965,782,698,821,159,463,927,401,976,868,616,621,131,421,181,568,473,931,828,231,240,16,588,578,461,705,335,82,842,236,267,230,759,102,508,229,626,669,505,136,903,694,351,738,118,816,947,986,769,589,488,120,595,13,656,751,431,107,716,729,734,181,673,378,125,119,141,46,616,21,590,39,119,225,995,244,406,660,287,450,423,755,508,896,388,138,821,597,824,982,901,565,856,509,751,773,24,839,773,445", + "212,207,156,654,658,406,823,860,479,773,853,165,406,730,546,854,708,59,707,231,631,779,87,360,170,311,266,737,756,842,851,348,707,955,921,781,426,107,50,292,182,273,905,567,143,615,322,669,697,646,371,67,708,560,287,951,94,103,608,906,103,164,232,310,129,653,316,309,889,980,240,425,710,817,190,176,795,654,770,416,439,253,729,178,134,396,116,326,535,636,85,863,225,329,406,12,60,24,966,407,94,430,993,957,201,100,629,720,140,782,470,27,661,518,144,517,294,916,908,687,508,689,32,749,244,444,780,151,371,359,447,690,429,705,813,812,483,247,955,644,883,784,450,949,387,895,991,975,900,841,550,551,980,513,490,907,884,651,275,798,239,552,572,269,320,394,712,960,233,343,416,261,351,989,148,90,975,307,395,826,292,522,819,275,752,692,794,112,131,768,905,247,59,36,896,901,367,739,451,332,226,995,733,799,343,815,258,1000,802,815,608,950,487,869,821,354,43,52,391,174,489,43,126,884,341,238,516,791,494,94,989,267,314,619,910,79,147,79,213,706,72,106,764,54,904,875,717,447,580,880,350,892,636,390,801,338,768,465,860,137,804,388,322,291,243,564,607,969,879,102,403,700,9,62,63,814,630,737,345,967,697,89,523,762,719,742,583,864,7,9,759,149,972,78,80,800,956,480,519,373,133,556,301,180,163,536,177,154,521,115,131,829,316,859,844,436,14,359,810,675,395,559,146,160,444,646,143,567,588,655,319,749,648,930,25,931,637,126,318,836,795,459,189,637,150,984,297,625,61,210,417,851,557,802,420,439,114,262,290,862,306,594,532,740,32,913,664,46,942,989,932,484,167,508,128,914,872,649,366,973,598,50,941,514,859,727,731,291,705,229,38,101,387,331,129,613,648,133,119,273,711,349,774,362,364,316,937,155,56,360,973,360,185,877,766,244,7,166,893,296,148,195,787,951,951,711,781,517,975,218,188,743,975,577,485,647,853,839,296,855,752,84,41,212,450,138,749,335,40,629,943,752,643,894,210,628,535,797,377,708,591,990,61,600,650,189,384,701,205,524,402,329,138,438,502,333,697,921,587,275,85,311,416,465,243,41,966,117,306,423,655,307,413,355,89,726,196,453,339,530,26,240,244,772,345,916,536,954,45,394,219,283,797,629,799,841,554,887,237,5,566,738,373,491,590,163,561,985,155,69,291,679,725,374,411,199,809,583,444,862,433,988,946,970,428,747,293,914,246,171,715,59,385,435,277,552,286,110,599,63,121,704,685,563,548,729,425,168,14,544,99,129,983,454,439,432,799,600,681,333,689,569,3,480,120,775,568,896,98,835,446,801,768,408,60,506,253,688,73,111,732,974,53,512,497,236,596,257,946,220,796,753,10,380,776,242,927,295,560,894,73,218,459,247,486,906,434,479,0,944,317,820,87,579,373,487,550,478,461,260,633,11,954,152,76,794,938,923,598,421,898,310,163,55,88,523,32,987,385,733,423,647,696,489,20,303,918,852,574,120,931,812,635,552,754,441,727,850,431,78,468,839,628,513,102,140,684,872,517,233,823,170,754,726,845,313,830,750,341,664,326,295,922,692,208,62,9,483,969,167,782,168,464,546,120,274,961,166,128,161,764,39,981,337,142,529,782,951,851,687,876,337,946,578,421,822,42,393,575,290,829,798,585,597,46,522,760,768,893,85,75,973,703,785,475,875,114,103,100,991,851,714,758,241,254,568,166,489,262,295,910,780,463,672,667,686,341,29,18,440,221,692,339,851,651,707,593,751,256,233,281,564,531,332,791,124,900,49,919,189,90,338,404,422,110,227,577,736,935,857,553,104,212,276,915,951,759,575,648,20,778,905,401,158,291,220,334,531,208,847,457,4,945,19,183,916,968,748,302,553,423,257,901,660,383,884,361,97,39,691,183,401,50,333,650,316,778,63,218,349,199,953,939,432,364,494,825,791,808,561,617,807,626,635,225,408,61,200,787,941,610,931,552,565,972,371,673,529,23,893,359,912,452,267,820,382,676,281,443,273,323,778,692,51,173,198,342,980,721,736,868,957,406,692,938,241,603,429,313,322,537,672,158,582,878,506,860,311,984,970,759,323,924,998,460,367,515,915,69,727,580,911,880,99,652,267,829,847,907,704,297,761,872,203,803,559,631,423,820,696,504,958,174,491,165,724,737,798,124,93,411,824,304,380,111,214,158,210,737,828,462,601,909,247,357,972,123,622,405,354,676,273,134,592,951,195,557,16,870,759", + "311,144,163,334,602,485,572,98,441,349,513,876,813,142,734,224,841,258,658,585,197,531,480,989,593,972,338,42,856,935,807,454,610,91,16,30,89,810,959,552,202,127,900,306,433,408,78,281,22,432,420,579,802,338,388,204,416,617,150,272,373,322,828,787,818,53,54,712,415,902,924,938,912,614,773,758,627,49,310,667,774,48,829,454,581,380,446,988,965,579,913,296,922,233,774,769,375,89,763,839,392,306,937,417,910,153,635,216,487,115,136,427,964,830,316,995,163,449,180,659,483,990,559,855,387,84,349,97,973,793,903,417,641,829,646,575,393,40,216,407,889,437,844,761,208,329,516,54,406,64,366,482,330,102,340,661,91,265,689,241,491,358,14,472,491,226,582,108,547,526,136,181,926,244,299,384,459,471,735,469,227,438,611,332,317,798,580,223,272,872,677,194,717,126,830,105,939,171,306,552,872,967,33,199,823,907,338,536,895,593,300,149,622,692,873,718,784,983,37,741,677,466,973,304,868,705,298,321,976,969,705,840,439,448,82,651,373,903,128,152,168,66,899,965,924,89,718,212,502,920,653,955,199,563,990,237,477,143,916,318,809,795,880,388,972,958,251,677,136,13,181,994,123,963,581,127,743,515,740,516,510,712,186,384,951,393,360,119,356,478,992,781,615,752,174,938,133,428,299,741,980,600,370,570,370,263,358,876,711,69,126,892,267,599,753,846,49,667,181,960,999,628,317,78,316,804,4,107,850,946,352,816,35,134,456,350,451,813,781,48,801,110,878,579,913,289,500,301,373,665,447,327,363,707,467,529,70,179,429,379,821,919,493,744,355,612,899,307,440,160,36,740,880,732,18,567,654,351,115,50,670,551,139,472,971,966,232,313,728,986,640,562,995,677,392,131,364,846,303,265,144,414,128,481,354,812,263,875,988,433,749,382,312,779,266,70,94,718,990,405,761,999,280,670,904,966,632,462,399,158,88,837,766,462,369,660,793,307,698,503,984,971,222,921,763,885,348,511,430,147,71,316,885,795,719,202,659,352,339,955,621,61,845,715,575,759,753,535,484,905,646,351,486,811,469,973,799,623,268,217,499,280,122,336,834,23,959,342,958,452,233,493,175,894,903,785,710,230,84,686,455,633,414,236,180,852,995,308,77,844,594,911,313,286,889,359,909,388,607,935,454,601,302,31,413,357,339,220,766,39,11,827,926,108,18,426,67,502,431,99,917,434,253,43,288,290,238,589,346,272,617,812,720,147,125,646,55,13,209,408,801,802,47,143,962,219,798,736,204,411,73,873,783,229,433,624,173,965,108,197,174,655,355,411,707,86,458,776,476,104,355,765,385,710,543,309,896,522,361,739,51,676,926,982,409,753,325,858,825,584,26,404,46,111,682,685,225,604,979,32,402,691,733,740,996,580,644,597,944,0,264,589,983,43,887,919,142,170,775,727,320,338,882,427,496,818,217,330,609,446,347,789,93,524,644,312,651,376,990,359,1000,93,395,638,76,371,606,329,530,946,604,870,195,942,502,374,648,541,528,679,228,893,4,328,265,388,975,692,286,937,879,303,97,125,895,365,724,516,966,271,113,634,189,617,738,225,541,598,388,146,819,82,73,770,658,43,237,522,276,640,583,541,670,242,567,162,203,531,998,933,42,263,888,468,723,384,292,599,123,315,639,826,917,124,888,544,615,484,59,114,865,744,727,80,375,233,520,12,967,452,174,150,230,676,944,442,10,569,730,993,161,702,94,690,546,129,400,719,129,527,921,49,800,121,521,762,596,372,610,226,499,124,481,931,532,752,918,331,513,438,296,67,43,499,280,396,906,980,946,501,49,600,415,864,236,753,951,615,258,698,173,154,914,523,289,122,66,740,856,791,745,323,215,409,144,637,246,477,863,684,240,206,897,797,880,370,824,118,571,841,94,172,702,238,43,387,423,967,296,464,954,144,800,868,757,29,710,365,876,570,844,243,602,380,99,521,920,207,401,404,468,920,26,444,917,411,706,453,87,434,653,385,90,700,376,790,459,513,906,553,699,271,944,754,910,992,776,373,616,912,418,364,230,290,584,829,145,144,436,397,757,457,463,617,520,444,625,581,91,257,776,292,441,462,508,975,71,311,709,987,77,123,571,602,693,674,444,222,935,393,444,709,599,454,239,354,599,336,520,307,764,485,774,797,166,186,813,729,578,277,838,150,580,866,979,892,433,628,924,454,721,522,374,466,56,414,287,544,592,98,408,11,342,508,257,958,868,543,415,561", + "572,162,331,9,86,253,915,431,256,388,520,667,47,796,233,542,734,216,120,754,974,588,798,695,500,166,320,395,374,570,579,173,780,610,469,831,53,690,232,986,135,136,526,551,13,32,315,493,723,519,3,232,8,452,83,778,308,388,289,318,711,474,649,930,571,317,893,216,276,552,250,431,981,380,518,27,921,643,863,727,768,706,518,328,295,453,32,376,19,850,295,254,506,119,757,128,124,614,365,12,172,499,135,622,397,347,630,895,596,413,726,461,164,872,867,444,219,414,499,191,103,359,774,450,765,835,418,962,636,899,928,863,278,989,175,939,190,570,347,295,457,386,412,26,142,545,43,964,920,80,462,559,652,604,971,961,137,969,401,678,573,671,22,920,67,410,979,148,544,667,869,435,524,938,15,671,105,550,999,587,683,152,15,144,180,90,450,947,120,981,691,66,59,100,417,229,203,989,801,994,198,582,119,841,699,478,654,801,479,88,591,362,462,466,594,742,653,267,458,810,450,315,608,640,801,204,622,645,927,370,164,534,13,677,894,998,42,764,48,146,568,575,98,447,626,948,202,402,299,602,350,642,9,165,828,837,813,928,487,819,637,773,816,543,491,75,917,353,264,781,689,275,931,602,213,217,509,226,877,846,326,744,408,826,446,26,198,292,210,869,740,101,174,770,454,551,808,599,309,146,525,273,663,27,965,491,120,189,336,712,98,344,260,599,827,102,468,700,358,75,323,883,241,92,17,738,467,187,255,391,536,926,905,835,605,827,785,278,187,380,352,825,586,940,295,668,808,573,113,992,412,941,905,621,541,265,240,577,915,483,796,391,509,884,265,936,381,747,431,669,499,65,301,536,104,594,943,830,174,192,937,539,53,808,342,823,831,322,836,124,372,148,840,152,416,667,803,12,711,807,231,854,143,638,719,538,881,992,864,523,970,279,632,899,655,120,525,200,450,945,41,156,643,572,974,279,432,408,233,881,448,755,922,977,326,820,379,165,310,189,141,679,604,176,750,802,107,493,369,491,929,208,505,188,490,284,667,595,964,445,257,695,387,759,776,118,56,435,321,438,450,182,100,490,602,62,796,320,234,493,360,464,746,55,298,910,59,80,731,665,837,129,419,851,656,676,905,535,83,525,540,332,309,514,449,373,425,365,594,66,907,522,430,898,14,289,460,509,753,853,54,929,300,989,126,593,448,675,327,708,496,945,959,34,76,566,384,507,635,663,420,852,454,300,21,880,569,932,661,102,410,159,587,452,180,704,410,414,382,972,666,841,465,419,128,621,102,388,66,397,296,706,241,833,961,356,444,852,391,902,534,616,723,185,605,79,343,91,508,290,260,131,459,23,886,347,695,808,619,990,976,690,295,875,96,758,691,833,651,428,628,301,830,424,416,907,957,428,853,79,840,419,391,662,929,678,493,404,317,264,0,339,521,2,495,2,45,550,34,5,959,497,850,760,395,743,459,763,150,332,247,163,149,524,14,223,601,377,532,244,314,645,181,832,77,522,639,766,439,844,725,562,586,59,129,594,233,19,882,281,642,958,91,813,47,104,993,777,932,974,681,526,779,986,831,459,354,229,604,696,473,112,906,618,242,919,676,337,708,175,644,434,490,459,658,9,848,831,753,770,139,318,331,706,352,730,588,956,339,552,895,468,608,466,864,991,411,901,783,930,899,57,492,242,249,501,671,458,626,928,370,267,262,869,869,848,395,885,665,182,574,963,913,830,66,136,554,373,914,592,869,854,453,567,936,798,106,702,26,107,100,358,7,869,16,469,16,274,477,35,951,696,230,716,529,238,850,663,788,392,316,226,948,362,607,306,878,97,490,631,929,586,727,386,787,490,555,553,265,524,657,114,529,428,121,109,378,102,443,741,346,220,515,368,900,207,761,702,784,763,415,221,796,292,61,703,567,300,230,369,113,947,625,718,516,409,617,924,606,613,594,118,847,795,962,678,436,539,138,358,290,741,470,401,350,61,116,754,510,289,772,574,341,859,241,581,681,396,17,866,817,63,339,79,226,237,986,331,190,447,255,277,549,107,4,984,275,919,466,529,141,805,690,808,773,382,193,423,408,438,486,671,967,58,974,241,150,218,475,2,840,181,169,707,91,957,999,283,768,577,309,913,934,954,18,383,310,577,14,396,796,76,81,797,778,748,978,907,989,717,563,986,400,669,741,360,930,402,621,16,501,444,560,743,623,97,78,954,995,808,77,191,664,323,902,565,324,885,968,408,834,913,424,439,340,296,274,611,526,82", + "852,46,587,294,332,210,41,416,947,245,746,42,270,991,552,859,387,48,427,622,618,550,487,127,701,428,585,798,616,14,833,635,89,751,187,824,368,35,485,373,478,816,100,406,883,570,228,761,403,411,54,266,638,947,166,906,343,303,947,904,71,314,86,592,439,630,984,677,841,988,536,228,160,88,862,687,333,393,641,166,322,277,642,682,131,701,90,853,682,971,282,616,876,531,580,842,980,515,410,389,265,565,853,181,38,476,398,187,985,529,91,621,970,234,924,974,493,833,356,221,590,67,712,367,771,626,173,539,421,204,790,135,496,968,769,22,534,626,382,703,950,797,23,233,796,106,766,937,994,300,945,500,366,811,854,380,937,981,692,189,393,751,133,666,833,948,154,253,663,691,513,849,370,847,645,73,77,93,207,701,184,682,328,390,377,229,277,792,247,568,422,724,757,737,9,497,11,893,997,850,144,462,522,423,686,269,370,521,539,405,699,918,467,719,58,274,555,412,985,49,876,234,540,492,610,247,400,4,508,393,371,972,592,222,65,441,583,351,753,373,572,558,759,91,809,852,725,330,976,761,489,144,663,291,179,27,350,140,859,809,596,986,664,117,766,809,426,449,635,714,525,779,735,347,840,329,140,121,257,497,69,546,753,61,26,900,368,506,151,642,217,738,107,130,324,172,759,404,667,634,135,669,223,563,929,976,882,653,334,976,766,214,511,941,873,75,55,282,995,471,929,45,799,96,438,101,862,401,981,789,134,197,594,695,249,266,890,935,317,658,433,9,18,138,169,713,80,25,986,443,500,931,726,826,86,846,232,321,497,948,234,815,156,97,855,1000,200,797,953,890,592,57,307,945,191,910,572,492,393,486,929,802,659,729,824,864,970,65,336,651,477,22,389,448,848,727,606,836,841,173,762,444,231,846,477,405,337,897,409,321,173,739,556,888,50,618,560,884,393,59,39,984,245,391,10,386,530,109,114,603,159,80,21,299,403,715,58,890,643,157,748,330,119,525,772,532,979,295,330,932,323,271,473,939,472,915,193,918,45,670,580,593,596,835,41,722,750,892,832,780,117,111,570,931,569,22,88,640,578,826,506,780,642,837,852,643,599,140,548,236,336,940,782,243,134,47,550,867,554,337,192,272,444,881,279,948,57,273,182,518,348,787,197,198,662,714,69,531,525,956,26,827,650,922,230,209,680,887,179,521,661,727,218,4,782,857,650,773,663,256,443,577,445,240,175,889,726,951,724,249,463,485,167,313,568,925,835,702,305,70,854,949,196,18,68,841,227,30,972,657,325,149,286,534,829,330,84,784,585,506,221,745,901,163,659,674,381,721,732,851,548,703,868,11,40,540,236,909,949,747,251,617,640,164,737,54,880,12,614,327,340,716,467,950,111,638,842,839,595,640,746,441,855,709,475,689,55,716,820,589,339,0,349,801,783,821,561,891,342,754,648,960,680,635,584,119,684,465,695,994,164,93,401,10,599,412,475,657,947,176,449,789,39,495,640,64,806,822,921,520,416,46,16,230,291,79,37,775,268,713,17,901,493,112,160,672,289,465,660,133,816,136,248,299,847,311,156,224,609,72,99,419,867,873,902,460,8,878,541,928,524,20,71,280,241,937,894,867,541,313,156,560,529,620,913,754,144,216,504,991,679,157,853,229,445,545,275,96,517,691,318,476,881,581,759,658,212,67,670,328,810,216,265,432,48,1,605,719,141,690,876,416,24,436,688,135,423,759,49,138,188,446,274,687,70,7,267,230,407,954,901,236,481,595,16,712,855,348,519,81,514,526,122,574,893,817,941,425,772,290,523,755,692,177,693,97,285,497,281,29,232,774,788,262,398,160,471,923,700,123,460,39,37,597,905,146,805,485,818,713,401,922,234,505,650,690,223,150,274,148,826,2,768,885,870,458,980,133,319,358,741,401,423,808,587,272,193,234,379,942,807,128,376,74,369,959,928,13,985,728,493,142,69,34,984,246,386,2,985,676,792,543,540,303,108,186,803,562,721,356,687,716,784,322,598,77,73,665,201,538,203,555,714,607,393,142,767,594,820,699,84,802,502,475,480,183,27,391,325,656,288,839,245,125,806,575,671,795,105,915,31,929,269,989,803,205,632,421,40,587,901,607,529,775,481,788,319,749,871,380,977,248,50,620,858,832,770,433,657,765,310,376,592,820,309,657,736,525,375,782,642,775,841,252,567,11,373,281,767,744,584,278,184,377,842,574,719,310,212,430,932,695,85,172,623,192,79,816,677,196", + "657,689,771,441,104,338,817,524,998,748,711,450,677,32,886,351,456,619,102,141,656,560,49,403,155,115,635,587,368,420,648,992,110,355,321,930,419,855,414,450,378,717,606,216,475,261,539,579,73,747,858,393,152,111,969,884,68,238,786,127,503,80,9,450,598,756,219,653,1000,414,554,339,963,271,487,615,950,558,725,160,586,559,248,138,677,25,48,422,417,72,981,67,2,908,810,43,101,632,199,659,556,531,12,515,926,80,665,205,115,294,393,251,300,738,245,22,994,675,131,993,693,381,435,44,993,155,282,320,385,398,918,577,351,771,206,255,848,56,42,619,180,198,318,38,853,504,727,291,815,671,324,843,474,763,623,638,623,418,858,681,939,668,191,931,447,664,20,366,474,685,221,129,321,944,739,78,766,764,515,416,144,903,616,430,952,194,992,515,583,811,740,385,510,891,78,280,140,900,478,415,216,131,626,252,153,278,11,22,300,887,722,5,464,6,909,492,620,283,551,561,79,99,141,347,17,975,530,19,130,621,405,956,221,714,725,662,989,605,181,630,236,421,507,574,388,290,696,860,208,481,222,704,836,100,641,269,358,339,235,909,146,875,308,425,461,680,239,100,685,420,758,676,168,933,824,558,846,190,142,865,700,980,908,311,226,321,803,971,144,549,997,613,986,945,249,841,375,809,462,17,857,907,495,410,204,803,568,610,14,287,312,523,228,643,595,98,529,282,593,287,519,287,52,364,299,705,581,950,639,537,146,19,85,393,657,923,130,754,871,330,624,720,603,119,105,246,449,721,486,506,530,542,576,592,336,502,453,319,706,763,606,994,905,524,404,79,761,512,306,861,294,260,591,551,964,97,204,372,903,230,583,285,814,313,378,780,192,352,87,441,400,487,678,285,28,547,481,458,951,565,309,329,390,474,40,195,857,375,822,75,858,813,37,860,745,581,44,167,395,123,343,374,19,134,102,999,796,167,907,451,722,958,530,514,95,376,751,579,511,602,104,72,538,819,465,945,104,286,66,165,659,11,657,612,68,491,78,442,60,571,141,291,639,198,967,507,212,125,978,240,484,517,187,866,517,830,182,367,661,405,384,34,428,984,20,787,746,676,916,340,961,363,358,594,343,738,439,155,319,844,809,876,215,809,608,433,953,640,340,848,188,265,713,989,934,224,223,746,476,38,220,132,526,361,572,447,31,707,9,14,107,709,467,8,741,970,959,555,760,160,251,463,163,890,978,354,689,150,849,660,604,919,869,448,448,55,30,140,149,217,933,283,80,943,829,73,387,370,781,790,373,591,461,983,448,872,778,141,638,654,725,126,720,843,94,428,201,665,272,701,995,78,95,191,381,608,846,722,448,682,150,948,730,536,443,809,253,281,410,180,523,464,133,396,845,237,622,690,201,896,965,297,190,622,663,467,721,867,87,983,521,349,0,194,658,669,20,851,985,654,923,112,444,393,106,7,557,715,783,849,913,359,33,158,613,370,945,905,523,751,632,948,481,150,740,154,865,89,338,589,504,962,686,27,608,397,564,448,875,303,420,120,1,736,824,695,565,609,411,935,240,173,522,967,352,474,408,690,236,924,778,494,751,350,880,629,916,213,744,809,227,997,936,46,612,917,781,49,874,227,462,68,33,871,903,957,508,23,691,765,300,371,954,938,971,550,971,836,530,882,617,269,498,572,16,995,247,161,242,965,635,744,835,521,825,932,121,619,202,83,387,169,896,582,80,540,203,255,254,98,487,94,864,438,214,793,387,111,840,693,677,735,625,810,287,551,950,215,905,274,563,430,742,863,981,870,634,603,925,19,911,352,277,250,281,66,490,569,881,952,971,656,416,922,908,785,133,477,660,142,297,393,538,46,589,601,655,490,525,96,490,788,92,26,774,623,793,587,217,43,304,971,340,616,475,677,584,233,128,762,397,637,973,324,683,816,859,457,553,824,540,758,265,190,203,753,625,534,463,792,348,799,970,429,333,257,324,523,235,735,192,401,426,689,616,579,955,916,518,104,259,857,901,449,978,81,903,879,813,610,274,99,729,310,998,913,647,231,328,953,431,173,15,92,908,84,45,686,173,519,447,504,83,291,688,81,39,318,621,196,747,651,881,463,412,15,277,258,613,14,692,886,735,174,180,626,740,229,788,474,181,566,893,966,554,495,626,777,70,674,689,885,54,339,835,766,60,153,897,932,165,375,442,923,660,176,677,909,887,326,808,747,719,931,160,871,500,270,193,966,225,858,858,887,718,404,810,424,795,280", + "622,775,204,194,689,36,812,629,357,385,548,643,964,413,200,914,467,588,476,126,536,114,225,11,846,931,990,554,496,572,14,876,14,109,922,716,914,921,371,81,770,648,970,198,67,523,503,390,729,603,233,322,458,259,452,395,788,442,918,651,744,750,317,652,269,955,143,53,220,275,925,821,280,223,328,594,528,778,824,665,137,119,586,490,262,182,601,526,280,239,320,266,355,836,611,61,576,946,988,942,98,545,23,288,555,93,402,166,371,62,25,283,456,102,274,568,212,659,398,683,66,665,584,934,681,671,581,866,188,222,761,442,108,179,952,618,763,877,662,132,950,433,58,428,363,575,659,286,155,556,232,520,978,833,120,567,898,756,802,571,490,550,663,832,656,737,655,365,973,101,150,870,106,647,9,13,940,914,314,88,704,707,756,285,100,513,108,439,702,796,409,809,317,589,152,89,949,176,732,750,713,550,554,336,942,92,147,634,435,903,539,814,493,31,845,846,147,763,388,427,931,858,933,395,108,978,806,404,867,5,471,985,782,73,930,687,787,603,138,334,446,416,437,370,234,369,277,671,930,46,885,12,490,282,979,587,989,633,725,206,812,575,71,120,830,697,204,647,671,754,293,523,250,305,31,886,402,25,527,221,664,354,848,827,241,431,882,199,452,159,285,676,834,786,949,665,891,720,552,577,38,180,408,248,173,166,432,867,856,630,174,588,674,50,335,630,664,101,19,943,355,514,780,3,775,973,881,718,564,712,564,499,385,659,557,290,360,835,700,865,995,857,205,552,899,69,149,792,192,928,579,970,981,3,277,722,397,612,333,950,37,55,829,153,573,379,663,683,719,583,118,73,372,398,837,730,496,703,726,645,646,600,537,208,865,951,445,675,832,542,627,323,767,424,988,509,672,860,701,339,70,602,752,153,371,620,247,552,666,280,433,553,756,478,397,783,137,968,849,439,506,959,409,280,59,933,16,842,825,246,61,214,123,553,145,377,55,360,662,7,393,4,735,767,464,336,666,527,459,793,345,133,815,857,284,633,285,610,913,63,285,724,209,630,534,220,9,76,754,847,987,864,947,766,851,31,522,433,782,510,56,708,245,355,442,776,43,354,22,819,74,473,641,398,965,536,878,66,627,614,801,229,207,586,170,946,352,55,806,792,219,352,445,393,230,399,449,494,9,572,891,326,341,544,122,229,963,977,103,14,954,572,583,904,643,890,156,134,859,155,587,306,391,546,152,471,58,602,512,427,926,181,129,215,348,830,325,136,914,648,963,944,110,115,767,661,157,303,412,736,996,184,878,811,496,471,242,836,447,702,834,845,376,185,921,756,482,147,970,906,400,369,204,807,130,332,41,16,422,670,745,527,634,151,993,879,24,980,987,224,764,547,81,606,15,990,70,694,598,461,787,527,54,518,351,261,44,870,579,43,2,801,194,0,965,459,597,57,970,470,405,327,341,479,790,561,633,885,843,277,29,484,837,388,745,605,811,916,269,538,669,401,232,362,948,821,243,217,237,57,442,332,847,25,859,260,95,827,316,42,11,758,42,379,869,792,781,279,965,759,315,270,164,27,738,483,604,709,818,525,614,938,789,107,881,983,466,627,174,187,682,191,842,487,157,662,549,585,821,375,34,811,357,908,667,576,178,245,876,323,230,339,671,745,923,509,3,405,126,175,930,995,113,806,802,762,711,401,801,158,512,700,296,426,135,965,723,344,859,851,390,630,15,871,997,411,722,93,377,878,92,888,304,731,373,256,185,266,968,688,905,381,64,947,244,279,645,779,68,37,362,504,726,137,194,491,211,235,193,722,290,834,619,890,891,982,488,813,884,185,893,929,370,334,802,768,791,781,886,595,536,104,224,513,646,733,334,326,70,296,528,154,24,767,161,829,83,901,180,297,490,127,29,837,298,161,714,489,653,968,121,558,891,858,376,705,864,469,583,429,536,527,411,409,674,823,642,959,127,306,253,936,402,834,597,864,588,989,502,219,450,99,310,166,506,494,509,185,130,437,406,175,402,893,931,330,823,144,172,827,437,50,917,830,151,298,187,280,957,105,224,241,334,649,927,463,274,396,455,317,866,149,635,89,995,687,675,793,467,713,871,634,713,112,631,587,257,992,737,454,114,782,53,101,117,106,902,435,757,798,650,119,536,363,790,649,601,394,397,134,533,375,210,208,624,166,854,859,679,676,25,717,678,801,969,816,879,873,823,59,144,812,351,512,675,596,986,871,213,501,190,981,154,623,11,28,101,450,204,773", + "461,318,607,902,959,277,61,405,184,339,552,538,549,552,91,725,631,653,244,459,870,414,170,522,177,431,571,71,888,254,541,91,953,203,161,762,826,951,773,88,661,662,860,972,384,998,195,632,888,228,713,799,953,304,160,312,743,259,302,256,765,264,890,486,344,378,196,53,146,171,748,284,573,844,292,608,872,54,668,237,66,577,994,790,647,618,60,950,298,43,588,194,831,34,670,548,71,308,955,269,73,134,161,149,831,258,436,959,665,425,355,900,411,474,203,939,94,320,2,47,30,668,917,37,37,840,412,673,501,306,376,773,904,775,18,367,85,659,672,796,318,486,739,416,374,916,625,84,916,262,852,866,402,941,580,45,405,716,862,854,615,501,85,281,560,308,875,737,656,115,287,778,275,908,223,865,408,381,240,427,532,266,498,798,692,829,964,70,309,522,278,508,362,899,455,778,658,975,189,663,518,118,5,401,76,582,750,873,293,869,213,654,410,750,450,928,731,59,27,138,162,294,158,15,815,285,917,841,250,144,117,913,547,370,43,769,677,797,930,628,528,262,797,496,170,364,130,927,323,908,951,387,931,267,97,443,99,702,562,652,566,542,432,461,732,305,783,117,84,549,888,624,524,793,327,818,62,491,178,258,687,631,267,352,341,604,585,369,916,536,274,232,624,433,637,870,285,309,850,31,754,791,546,885,131,269,796,991,33,712,736,939,527,885,60,636,725,230,150,880,73,415,609,530,567,273,837,161,593,937,808,232,226,299,592,74,721,825,881,109,545,499,423,262,616,394,424,453,561,913,387,399,98,963,567,412,933,445,680,115,676,215,183,611,736,20,831,737,296,171,749,878,76,462,793,495,402,264,953,738,655,697,93,913,893,334,551,193,248,278,385,411,753,114,336,30,314,722,503,377,919,309,338,50,199,859,398,647,744,590,349,809,974,250,441,336,836,872,412,875,575,61,887,235,130,698,611,861,525,112,878,271,902,10,949,893,887,595,48,243,332,14,721,298,836,751,616,415,189,209,63,153,534,180,970,941,865,432,894,830,356,311,569,500,130,569,527,582,41,853,532,726,107,392,411,722,416,606,86,639,218,696,672,637,988,199,623,684,361,780,121,222,458,71,743,599,865,638,658,274,408,968,134,804,646,63,222,747,280,820,50,569,178,871,593,470,65,962,220,665,681,363,83,224,847,353,6,808,448,54,478,520,796,487,687,431,40,561,870,18,495,32,528,807,944,618,594,189,331,170,89,977,760,587,971,534,724,900,304,65,124,252,380,633,700,428,941,759,312,143,598,573,932,360,399,108,658,277,706,945,922,266,999,518,318,410,976,823,983,63,874,133,958,30,928,782,70,808,133,308,859,853,607,368,928,890,807,673,502,307,549,914,515,735,683,722,136,691,672,90,444,122,400,93,944,548,922,183,373,887,495,783,658,965,0,416,835,560,256,172,76,143,75,278,933,872,332,610,18,805,5,913,943,776,94,473,675,550,156,614,537,836,451,694,621,194,578,563,697,642,606,505,164,264,234,241,276,983,1000,707,882,117,20,250,790,664,337,678,661,791,412,314,645,629,161,713,290,902,239,695,254,634,36,281,652,829,46,414,800,737,211,92,600,793,780,254,270,582,399,517,859,311,808,609,480,523,992,660,98,968,964,47,898,437,791,128,946,460,930,547,514,419,406,786,770,692,510,290,614,831,567,902,783,849,344,114,856,511,174,841,740,724,46,138,740,410,404,589,363,620,117,668,350,93,941,662,124,461,848,445,576,928,849,603,748,626,647,467,146,950,487,190,385,286,504,621,575,667,732,881,977,580,890,94,181,855,639,846,605,632,550,892,795,9,612,745,518,238,971,698,118,80,852,75,611,643,407,448,511,755,405,541,983,607,265,586,776,707,561,459,345,987,624,894,190,445,378,508,466,864,139,734,721,896,686,607,172,521,377,6,370,997,346,6,562,93,576,32,231,732,375,535,692,176,265,240,160,586,500,656,720,611,805,989,726,425,957,491,155,989,78,332,481,787,798,128,726,149,821,371,137,604,260,454,912,501,169,420,444,976,65,243,142,966,362,233,510,116,532,232,611,584,966,764,177,34,985,417,798,202,800,679,449,864,956,148,122,17,39,890,36,741,480,703,55,752,805,368,599,799,563,991,968,91,207,453,890,410,575,236,844,101,291,963,738,393,525,62,502,696,206,39,19,811,484,22,313,226,439,915,115,596,395,109,293,452,917,543,381,986,368,750,197,500,791,397,841,941,142,149", + "101,311,979,117,217,533,730,827,771,940,964,230,884,785,87,144,783,159,145,112,96,201,324,595,883,339,944,529,884,307,58,676,126,272,335,462,149,821,696,755,229,650,918,643,932,181,117,128,60,424,333,767,568,761,389,480,449,480,814,108,229,945,566,664,848,1,323,819,513,754,906,84,561,264,926,776,576,24,265,108,730,657,863,874,107,737,687,812,17,649,968,737,482,784,475,330,919,337,321,972,901,417,326,300,69,190,820,69,259,32,862,953,91,785,779,154,704,787,49,316,255,970,965,741,914,963,429,346,104,948,592,305,178,599,828,876,927,29,999,966,300,436,199,699,721,689,724,41,296,46,819,791,975,598,100,435,417,340,250,335,556,124,180,384,705,954,578,104,450,171,231,60,851,665,743,485,215,989,136,902,215,907,551,720,89,367,542,560,950,234,503,629,174,16,432,916,517,854,472,871,130,361,897,102,533,243,312,47,235,89,735,610,539,459,17,153,64,740,895,213,825,951,542,134,640,397,353,318,481,403,337,813,406,606,804,495,907,139,608,299,115,298,417,152,756,276,485,164,264,58,188,739,80,911,44,279,968,836,260,656,730,746,829,166,706,608,354,680,304,748,248,526,723,176,545,989,899,272,624,777,48,856,751,781,226,259,501,756,488,555,919,84,23,975,62,8,628,144,666,230,348,89,597,507,56,815,519,995,500,710,166,36,213,167,478,306,732,321,613,174,913,181,281,442,77,21,863,769,43,753,992,795,149,17,936,122,760,168,131,533,874,875,200,89,438,190,191,18,684,60,788,281,179,278,527,146,132,417,859,812,336,750,959,774,55,954,599,614,301,776,561,448,759,533,872,783,479,761,106,619,475,867,463,191,219,266,564,928,229,845,186,498,376,824,805,831,137,245,540,150,718,959,118,221,428,177,65,334,333,282,17,284,691,554,881,556,527,536,416,565,681,226,262,25,101,853,738,826,336,487,708,347,598,898,179,528,930,499,374,121,416,519,630,842,214,854,274,532,887,799,923,696,147,917,461,248,197,925,195,770,438,923,419,442,218,485,780,69,91,645,363,109,897,452,859,87,797,212,390,19,766,874,201,365,189,658,823,986,311,609,787,548,177,111,888,796,950,325,828,187,128,868,554,752,296,765,976,71,826,55,856,942,691,535,332,305,872,590,157,35,770,760,954,8,591,883,107,912,534,29,454,941,147,167,976,50,47,614,979,974,651,25,272,419,470,429,487,24,662,706,855,718,904,602,947,734,674,622,848,99,830,833,127,46,157,810,332,830,194,868,39,921,628,590,395,329,450,529,250,72,454,592,486,582,156,397,506,240,238,157,703,369,275,257,307,789,414,650,593,749,764,341,374,984,489,258,785,411,304,718,28,614,354,463,80,129,474,937,65,309,615,442,834,819,819,946,35,77,487,919,2,821,669,459,416,0,120,28,43,469,283,927,147,956,966,63,687,458,34,348,606,931,380,286,101,243,428,727,937,252,731,601,820,404,540,67,407,338,130,395,563,928,774,86,523,509,473,989,302,566,119,809,838,650,419,236,417,586,147,817,591,836,113,394,178,577,221,779,516,603,626,309,790,508,33,45,517,515,748,917,936,920,54,120,343,744,1000,943,629,66,592,373,706,839,35,754,709,757,666,826,4,265,542,478,492,9,530,736,922,920,331,614,650,19,435,33,998,285,832,669,244,234,883,853,46,678,615,159,309,72,87,687,761,233,809,430,387,871,731,724,663,589,952,938,564,404,303,459,988,807,695,40,220,387,451,625,262,386,789,49,326,931,934,147,471,959,394,63,369,962,308,544,557,428,447,940,997,578,323,165,920,94,566,917,462,664,736,207,241,648,6,155,607,429,495,872,261,80,360,567,185,890,190,158,473,65,762,189,442,383,586,935,636,104,573,47,843,530,259,394,117,64,723,642,341,588,42,563,455,951,265,203,944,447,100,329,863,520,291,167,571,689,74,579,385,821,532,203,179,847,264,96,880,468,45,243,284,167,284,771,11,552,482,477,444,426,583,627,608,876,576,83,920,788,927,511,379,241,411,696,264,836,794,161,338,223,401,45,430,527,538,570,716,286,460,146,208,184,330,14,770,223,230,70,101,924,274,577,656,695,374,909,554,331,265,906,185,674,702,697,288,531,603,377,714,859,897,285,72,933,494,646,505,668,888,321,62,525,719,565,357,108,347,717,255,881,140,291,358,69,202,323,894,904,922,957,439,602,780,658,593,231,283,287,423,224,398,558,268,672", + "771,247,404,969,466,632,597,836,130,8,395,391,412,121,785,44,960,621,808,620,200,562,610,268,559,55,378,797,584,99,665,951,136,73,358,358,695,483,998,520,847,284,709,591,96,725,525,72,556,570,196,968,685,238,263,439,713,442,308,453,9,884,944,970,275,492,641,460,83,258,892,611,555,732,261,296,845,278,767,180,56,751,962,621,515,204,939,74,721,412,40,619,156,343,841,521,301,167,860,439,860,71,754,599,183,423,138,370,995,126,513,703,931,188,561,542,883,60,546,91,716,793,97,518,80,300,296,43,531,229,325,562,758,272,226,41,200,606,661,247,747,56,69,9,689,825,934,669,416,484,304,66,196,942,506,435,711,295,585,438,189,268,372,344,829,714,99,536,845,609,319,221,604,236,619,928,930,413,429,760,177,924,227,609,549,495,773,766,863,312,784,55,344,583,807,47,541,972,835,12,838,731,688,359,574,611,333,708,174,282,578,741,924,174,582,441,421,555,808,292,65,507,701,263,158,582,183,351,869,510,598,715,447,365,728,115,862,851,757,963,383,488,894,322,185,934,865,281,581,926,266,494,902,6,40,521,756,616,893,314,780,256,772,600,453,98,125,906,807,310,5,409,418,632,383,966,548,506,688,605,441,149,343,742,205,179,958,131,224,686,596,499,914,184,414,798,44,103,331,624,168,21,84,450,609,174,672,158,201,93,276,966,816,370,463,169,295,109,192,786,839,73,838,237,218,731,411,579,339,377,95,110,789,27,448,906,658,382,836,628,966,855,741,779,134,803,369,190,577,295,811,990,186,361,462,416,345,295,254,512,170,975,987,379,301,102,131,773,934,389,724,496,943,131,742,864,170,106,909,489,920,162,502,577,725,204,951,664,827,902,890,269,513,990,936,525,899,451,677,182,901,584,402,827,556,216,919,631,890,500,308,508,950,185,901,864,521,661,896,132,955,228,968,784,590,355,31,525,518,241,939,932,138,562,893,792,739,242,700,280,199,969,525,533,516,278,588,128,230,107,264,491,270,997,806,198,399,537,673,732,240,920,685,474,629,37,268,152,979,796,750,694,168,481,919,476,344,285,535,910,543,99,839,550,855,67,698,639,183,741,87,462,376,484,961,832,48,835,78,395,896,866,643,546,720,121,927,180,952,362,426,155,962,268,572,997,251,795,537,968,812,762,803,274,57,965,712,469,445,63,385,583,125,919,572,506,276,894,887,179,730,616,788,384,791,422,572,34,495,468,580,438,848,553,415,169,566,978,639,335,749,720,57,840,613,314,154,888,505,336,111,119,925,762,480,104,427,808,504,816,702,478,919,113,963,479,614,369,325,515,507,143,932,167,359,246,142,789,322,385,918,877,790,980,268,58,260,619,15,261,573,695,374,421,867,73,17,131,721,768,276,937,956,356,351,914,948,932,550,142,45,561,20,597,835,120,0,2,813,963,542,491,533,958,773,883,472,355,592,640,305,65,263,639,495,948,826,320,959,983,310,41,514,108,437,933,680,703,702,233,793,964,478,405,547,270,161,818,944,160,678,296,191,340,926,68,966,927,963,613,594,538,311,704,679,58,866,162,248,926,82,862,230,908,58,757,244,713,799,833,949,597,470,916,691,586,611,766,452,14,499,404,885,76,134,150,593,892,454,556,126,22,658,870,312,235,490,479,982,764,693,927,56,142,359,211,422,731,71,555,694,317,515,799,363,722,200,746,620,681,661,137,165,213,316,274,697,679,435,181,211,354,632,235,927,936,350,3,611,711,650,479,280,469,136,888,319,751,344,781,83,180,160,499,969,385,583,675,751,368,854,958,644,218,494,707,636,278,442,12,976,406,421,664,112,185,783,954,476,199,911,75,334,96,19,765,709,805,408,469,491,58,994,339,146,333,210,619,392,947,840,176,261,147,88,934,593,672,164,767,638,154,516,777,315,722,788,930,702,382,113,934,491,232,627,194,996,579,111,641,157,792,211,34,991,118,332,534,740,514,589,73,100,107,157,344,648,791,788,879,312,62,483,939,251,919,820,878,832,431,484,287,655,909,415,957,68,223,140,863,59,930,767,876,370,572,361,842,732,409,84,897,320,408,38,168,351,693,497,252,291,220,944,768,188,774,619,215,896,95,87,650,977,368,104,892,1000,779,161,824,687,785,291,123,298,801,859,122,488,952,792,541,885,703,840,674,723,566,766,991,7,614,528,911,638,600,598,557,308,454,202,484,909,484,707,449,3,688,126,253,395,254,739,787,850,368,173,909,447,298", + "644,748,137,201,184,420,543,795,663,126,132,306,750,952,657,919,911,909,55,474,422,813,921,296,525,839,448,761,80,730,80,880,940,466,306,755,727,893,160,21,448,30,928,549,36,396,670,667,347,749,216,768,265,894,337,603,457,182,417,951,74,485,543,701,456,655,382,905,131,113,973,596,718,528,551,705,499,138,974,309,743,869,747,620,751,415,216,739,384,588,513,135,252,108,829,809,5,209,682,5,607,474,790,195,394,17,955,350,668,592,377,871,123,510,594,670,54,914,665,814,774,937,713,238,1000,849,373,488,979,81,967,72,279,336,225,906,347,926,561,853,235,438,278,160,796,179,934,151,91,420,101,330,365,464,760,446,590,534,902,415,467,654,203,613,224,215,583,124,150,641,90,641,886,534,818,71,239,624,385,908,420,866,448,646,261,424,247,661,704,219,354,94,88,731,555,337,954,44,531,170,4,780,145,833,636,173,268,602,18,719,707,844,369,775,27,602,127,23,958,384,649,207,231,577,478,106,546,361,371,588,29,69,339,76,524,378,967,401,611,197,989,667,796,328,433,980,385,795,986,322,828,873,290,382,374,708,378,757,223,489,261,68,934,230,612,467,66,156,787,242,197,204,886,9,889,227,686,321,112,195,222,760,117,292,911,464,805,394,470,289,932,418,588,761,568,464,667,725,192,143,904,658,661,285,116,882,329,897,748,535,994,745,366,467,221,887,150,465,173,708,160,620,465,512,911,188,131,86,803,100,656,996,440,72,212,134,976,641,507,445,803,171,747,296,688,466,955,500,219,116,343,217,316,247,609,509,331,563,955,748,662,331,913,757,791,531,786,297,106,128,477,485,83,431,255,960,391,448,373,177,431,462,157,736,253,307,861,804,490,600,623,291,85,323,210,652,709,948,108,549,581,806,511,591,524,34,772,817,780,108,809,833,428,144,975,216,431,735,182,153,632,887,207,222,972,339,288,16,598,468,865,273,432,101,616,247,634,61,750,847,600,871,985,167,811,506,554,402,187,616,514,129,906,841,554,8,526,685,448,724,62,834,261,288,286,309,656,91,75,775,171,384,229,591,387,180,526,282,7,534,483,460,988,779,860,530,899,325,14,704,397,323,22,320,525,776,293,915,960,828,290,618,450,933,288,543,328,788,815,11,822,840,669,58,92,159,597,178,694,123,877,886,599,67,516,651,635,795,880,605,660,460,484,397,838,189,143,815,412,927,914,251,1000,855,738,22,152,979,880,191,235,713,992,733,38,881,987,291,704,28,317,906,954,136,710,334,526,551,250,765,401,864,438,100,200,76,858,370,507,549,31,560,63,680,12,380,127,882,506,116,144,838,415,674,430,256,343,83,161,828,396,444,818,395,530,174,437,412,143,579,979,156,11,668,548,257,73,646,38,631,212,847,517,472,285,243,115,345,478,170,550,891,851,57,560,28,2,0,157,992,949,225,337,989,594,294,660,688,345,913,834,401,454,813,470,325,130,377,462,451,115,664,628,165,601,437,411,215,430,436,677,505,817,595,378,13,953,544,349,332,488,654,281,827,581,177,647,942,647,692,489,436,94,952,831,457,919,245,104,883,507,619,793,137,827,265,236,137,390,785,976,584,984,484,523,7,490,587,809,193,914,618,156,901,548,203,735,897,81,83,510,317,787,508,932,920,705,916,391,995,266,424,493,990,83,536,230,818,60,401,378,728,161,59,94,963,863,589,83,781,655,929,400,731,714,578,502,527,962,772,602,129,649,811,860,756,705,491,297,253,407,379,757,947,20,762,438,132,931,76,42,888,763,886,571,384,371,939,997,539,667,825,726,873,775,590,322,800,346,720,670,423,248,783,575,167,312,612,563,403,250,92,563,267,33,233,147,410,896,562,376,401,895,217,463,869,271,333,506,129,382,504,764,674,197,624,757,493,691,202,207,882,32,34,818,884,519,3,687,22,75,171,857,607,838,848,302,720,686,62,116,989,705,567,547,798,664,298,310,745,460,883,10,861,529,351,807,428,52,935,279,402,780,636,990,178,889,510,208,153,515,337,728,781,909,642,190,478,149,410,204,318,398,544,575,492,664,367,885,518,116,491,857,123,18,697,557,665,358,506,74,119,917,650,895,56,288,32,537,293,62,124,986,554,149,540,731,46,195,399,269,328,296,724,538,927,317,904,589,874,377,862,753,340,873,492,702,537,901,879,855,610,415,573,948,574,725,368,899,886,88,560,817,547,418,990,728,471,581,165,159,964,961,37,890,644,909,872,351,188", + "925,318,688,451,313,213,601,122,498,996,444,929,109,932,786,60,835,474,477,9,355,602,469,976,60,933,768,684,610,561,636,617,3,395,209,29,206,768,512,208,95,410,105,242,884,920,203,344,316,837,675,472,189,528,479,580,180,874,379,745,154,428,84,317,332,22,992,222,991,929,624,944,445,119,956,614,290,439,833,27,689,582,108,834,949,451,635,804,826,365,699,192,696,928,951,346,547,116,599,685,745,23,554,251,17,445,129,241,869,974,465,915,975,854,269,270,579,891,829,980,677,884,674,9,548,943,873,115,111,753,856,643,700,781,194,247,771,25,814,693,227,280,40,461,263,981,582,717,937,929,653,743,768,737,648,883,500,109,870,31,824,173,765,624,922,391,532,718,897,194,788,3,957,370,432,414,670,987,341,821,673,94,123,456,370,320,79,896,803,915,816,72,726,293,753,744,679,602,536,103,558,725,941,93,643,716,170,910,796,926,412,480,21,834,87,255,745,207,913,789,671,710,882,718,684,748,325,707,889,708,893,321,673,178,378,51,673,501,598,266,582,244,325,659,121,100,303,117,600,265,37,843,550,435,998,770,10,850,442,889,364,695,133,266,486,74,574,544,564,903,445,375,79,809,852,982,619,436,892,828,903,978,55,182,124,859,495,835,938,474,83,609,377,500,509,78,30,704,105,65,62,14,430,242,933,8,522,453,198,307,430,275,645,100,140,826,234,950,72,249,628,507,136,351,614,742,176,802,877,706,947,796,300,730,533,515,466,797,552,182,247,429,247,73,679,128,794,398,486,746,875,517,282,794,620,969,441,760,301,871,156,858,905,413,796,724,702,881,999,59,272,954,626,4,761,712,33,417,99,993,701,91,822,953,845,151,347,239,527,531,563,940,129,489,480,648,942,945,160,223,279,116,103,611,565,950,396,489,542,708,294,374,745,174,907,873,774,835,595,544,519,29,411,149,685,110,431,108,846,814,280,221,915,882,146,617,203,687,867,102,855,568,804,436,608,227,11,857,489,649,556,324,119,201,104,113,858,122,969,89,868,827,68,276,156,518,105,83,883,131,933,836,959,229,206,426,402,993,445,928,581,369,228,466,541,871,407,515,620,937,484,620,461,683,800,575,128,561,400,224,779,21,11,982,665,545,841,329,122,390,860,814,399,594,982,917,506,744,802,823,348,322,904,444,310,504,730,970,725,732,593,106,77,476,187,276,942,866,742,796,925,479,655,572,257,837,779,324,921,872,163,216,562,18,657,17,123,192,323,247,150,555,763,653,658,253,978,833,106,288,441,382,564,976,678,212,23,5,340,653,164,580,429,946,16,395,604,887,366,95,847,810,220,412,303,63,735,356,265,368,394,231,434,714,521,17,530,571,157,543,470,369,210,765,105,281,619,881,771,59,436,623,653,993,848,966,933,187,461,775,34,342,985,970,256,43,813,157,0,764,721,377,80,949,853,851,99,570,634,152,112,484,929,785,432,596,146,218,732,910,648,67,671,770,405,697,915,19,38,157,185,177,68,392,961,343,876,33,968,505,448,459,788,160,415,87,74,827,61,992,92,868,990,234,302,950,336,912,957,95,251,989,295,621,59,240,964,507,910,292,277,751,452,809,280,265,495,456,941,919,144,856,825,50,206,194,556,49,81,280,562,880,773,676,433,879,973,545,190,114,640,526,128,155,711,341,870,209,298,979,841,39,90,14,665,702,475,458,934,929,492,959,583,753,401,205,96,155,473,321,178,606,930,768,94,441,326,959,690,162,899,721,767,902,718,631,852,48,752,128,383,383,49,487,337,187,957,533,520,228,552,365,946,809,1000,110,68,166,315,842,815,863,656,747,519,790,302,69,774,589,771,565,271,990,595,536,880,872,694,341,450,573,640,391,89,482,772,493,946,649,467,216,500,918,835,31,947,637,680,666,119,280,888,248,323,174,527,2,703,877,154,296,475,340,864,873,267,309,749,99,235,630,633,59,229,47,326,139,317,250,441,762,973,418,818,521,657,195,115,980,930,479,842,356,397,642,67,631,858,333,899,752,424,1,302,752,131,231,129,254,329,114,448,126,574,322,481,818,191,385,670,81,870,625,712,313,378,248,245,985,693,103,232,41,119,528,981,370,859,462,300,915,425,837,617,651,840,689,628,860,249,985,247,718,254,429,347,327,67,966,290,705,726,447,51,247,90,99,796,651,382,955,588,738,133,853,230,494,625,227,219,95,854,319,798,292,968,60,305,102,301,409,662,471,656,183,387,725,313,156", + "761,828,572,589,774,53,31,296,536,242,154,350,136,600,151,467,213,376,829,770,759,978,550,145,706,191,616,66,221,220,613,399,181,572,499,420,681,187,846,914,818,689,526,978,308,18,576,525,173,607,778,703,568,869,331,440,824,996,878,980,304,29,517,230,402,30,134,766,101,997,846,37,720,772,312,986,610,22,451,175,606,232,777,330,395,922,423,262,479,818,788,429,442,864,400,754,372,477,825,81,23,264,465,501,817,374,941,28,647,519,637,113,419,812,341,346,554,989,896,542,190,780,938,355,730,59,757,177,319,61,778,599,416,313,475,839,130,266,721,63,732,717,443,665,52,850,542,199,325,836,237,909,825,482,311,432,204,688,106,287,763,429,649,173,408,563,515,793,366,187,447,914,229,871,642,36,679,437,80,291,819,352,677,597,309,175,993,172,255,371,344,785,930,44,793,424,703,528,788,658,4,370,959,91,969,817,189,955,23,515,94,21,974,893,826,90,873,264,956,131,543,248,127,929,604,627,342,124,386,187,910,817,611,907,719,576,504,696,418,159,564,158,251,362,93,861,141,159,838,119,1,966,82,520,794,796,647,700,699,108,940,178,648,669,591,832,9,667,158,779,536,392,333,895,346,296,166,923,350,274,62,177,243,761,387,124,42,678,625,168,900,207,349,569,559,955,722,91,379,21,748,778,338,97,669,858,173,480,252,952,607,694,157,6,39,759,822,933,413,670,485,93,738,65,287,674,704,809,167,972,72,516,764,601,441,485,395,905,761,15,443,114,822,453,460,593,499,840,542,99,886,470,733,950,304,309,508,79,984,793,336,786,119,719,13,373,217,339,52,196,226,301,782,511,712,575,319,329,832,972,136,376,346,634,256,921,238,711,539,1000,490,633,280,828,230,546,211,98,336,947,43,303,422,316,602,471,756,216,515,322,753,507,901,491,535,283,247,592,233,210,26,365,420,464,276,58,337,405,155,716,355,416,981,267,581,801,200,860,552,246,32,294,309,180,67,961,8,319,134,434,757,530,504,836,307,280,985,309,176,800,61,645,356,706,358,400,490,903,377,625,514,978,277,942,370,535,597,86,19,882,253,464,210,195,3,371,527,939,388,207,589,861,593,916,598,610,955,364,401,585,32,188,107,384,843,53,974,501,181,603,228,365,328,826,272,704,411,364,110,953,906,22,933,302,423,442,644,135,231,51,469,968,482,630,386,285,629,286,342,550,225,394,288,997,450,592,727,115,494,161,534,892,939,285,170,765,363,170,87,120,841,134,727,362,695,131,836,655,701,383,289,249,743,950,630,357,516,933,988,262,70,145,274,913,387,896,181,358,192,946,212,31,408,138,153,680,831,266,580,208,426,572,151,625,103,170,129,248,250,238,937,994,51,583,593,379,943,657,338,598,153,807,452,516,704,474,107,818,260,727,5,754,654,470,172,469,963,992,764,0,283,628,859,464,747,825,67,366,825,708,538,6,280,92,346,900,471,373,241,473,707,371,843,120,881,470,669,986,450,320,332,360,486,99,741,203,711,229,808,916,51,75,491,268,157,422,308,61,831,588,155,450,957,70,386,105,9,828,241,737,449,112,658,216,288,674,679,888,199,640,998,419,407,453,406,295,88,1000,402,826,267,410,685,292,445,319,234,215,490,233,258,55,524,371,113,984,694,502,194,239,373,459,741,355,599,868,169,660,597,687,406,770,906,510,713,108,910,114,277,360,124,756,897,453,228,965,481,762,147,384,420,624,922,427,282,316,529,306,780,48,684,66,700,601,233,372,739,71,410,430,943,642,573,400,827,215,668,235,577,658,11,797,75,440,402,312,764,775,738,257,849,325,658,884,736,670,394,371,653,497,193,342,924,243,864,243,434,888,7,636,696,162,735,744,559,461,666,524,27,788,374,446,564,815,981,11,837,928,844,403,50,581,643,352,640,59,495,139,534,526,913,539,82,669,239,82,504,264,786,281,236,444,88,745,125,87,878,904,110,654,126,567,740,947,839,485,12,439,656,192,57,109,866,692,538,458,808,739,427,525,178,735,500,123,425,690,219,391,703,878,71,582,159,846,203,924,138,428,517,659,62,391,900,599,377,966,612,627,17,26,436,694,246,840,907,985,668,995,373,446,236,350,671,790,532,702,659,2,396,213,945,253,902,706,873,961,808,451,529,298,938,883,333,638,992,437,467,979,818,220,593,538,672,679,865,939,759,679,840,531,440,348,444,341,676,161,895,764,814,86,559,879,648,344,872,915,448,654,706,974", + "286,500,967,106,735,823,163,953,855,984,203,778,21,147,141,384,302,66,640,149,936,273,306,925,852,378,77,520,899,204,115,763,536,701,285,411,568,350,358,617,398,147,138,82,929,541,967,661,667,335,150,533,545,821,108,104,404,36,166,486,130,920,322,704,228,247,47,255,20,505,59,780,679,370,241,62,955,211,904,583,143,43,246,636,868,110,984,328,239,459,886,38,993,954,769,29,235,810,65,666,284,191,775,41,933,275,911,692,632,650,766,472,627,14,782,328,335,402,798,873,519,542,969,415,766,617,911,896,115,423,616,461,607,789,468,114,722,593,274,446,629,279,105,993,463,69,979,688,240,573,859,232,584,36,858,753,641,43,493,567,815,551,922,722,879,831,330,319,496,968,223,930,427,943,615,563,144,96,761,868,858,464,672,366,926,236,953,835,133,945,846,286,805,38,38,759,412,396,574,104,434,34,443,894,193,409,840,190,718,350,230,742,619,880,190,834,464,950,898,629,168,563,243,830,343,785,644,528,700,629,34,636,727,486,503,523,384,407,82,845,671,152,49,287,419,542,545,101,806,762,518,599,613,546,274,328,879,384,604,637,167,438,995,874,247,187,198,582,323,777,261,305,545,138,848,114,190,934,178,619,247,228,900,873,680,391,711,947,853,320,43,641,587,5,382,513,722,401,844,224,154,514,616,473,97,458,281,851,499,3,985,691,57,882,688,935,6,290,566,840,530,880,249,83,107,515,586,226,873,415,462,314,227,144,215,45,559,506,528,17,238,353,135,622,595,361,661,220,195,149,237,705,591,583,114,938,197,779,843,559,221,437,377,520,313,782,113,437,141,941,95,909,270,321,589,784,80,326,546,346,981,258,596,494,385,465,227,755,838,284,671,436,435,151,241,993,261,17,295,745,113,623,594,251,426,409,683,531,978,258,356,24,66,330,627,194,759,322,352,650,187,531,906,353,268,133,390,704,166,703,922,504,412,750,605,985,751,599,470,566,100,175,43,483,395,495,480,684,808,959,632,416,112,27,669,846,608,773,422,973,729,163,807,167,299,650,92,705,676,780,523,548,51,305,627,916,669,395,567,452,352,513,756,216,969,305,231,772,526,603,53,223,500,895,806,440,884,599,48,46,375,474,942,493,325,8,107,986,845,35,865,488,788,736,755,703,373,131,43,78,159,321,788,23,604,170,539,729,365,274,908,797,57,940,831,645,423,484,514,147,983,322,119,643,123,765,604,109,153,345,923,173,409,892,111,709,432,118,808,598,553,45,371,937,219,4,355,82,549,504,249,410,679,309,86,414,955,320,325,171,56,835,301,330,126,348,682,480,884,879,870,72,644,385,148,493,966,534,571,796,502,414,622,847,703,502,269,966,773,180,812,600,720,885,192,111,505,973,699,817,730,437,508,706,708,36,429,318,633,320,959,648,923,405,76,283,542,949,721,283,0,664,657,471,953,270,401,461,390,23,974,733,727,828,899,952,406,286,362,677,650,247,88,159,573,772,531,392,500,63,679,43,694,801,225,198,497,84,999,48,24,493,170,467,518,426,720,938,576,370,491,863,90,261,684,491,414,927,717,323,305,740,926,712,90,245,705,931,105,307,619,136,464,708,752,646,233,507,681,132,147,913,582,154,740,799,511,979,69,610,418,290,716,92,532,85,913,883,781,344,919,174,858,737,533,614,560,85,100,863,348,162,877,292,454,698,529,914,77,144,7,382,402,861,537,503,240,339,578,515,482,150,394,280,296,462,813,843,931,771,217,958,184,162,457,585,552,120,532,857,730,376,74,503,609,541,671,232,401,70,684,513,715,19,774,13,570,370,307,59,958,735,231,700,859,607,9,589,172,336,468,358,260,756,611,272,344,5,764,57,481,5,567,125,172,127,38,538,439,634,569,254,106,115,244,594,690,820,887,7,511,81,740,883,824,907,854,882,300,74,892,306,60,445,359,78,926,547,184,57,765,95,170,856,308,630,189,703,263,826,513,345,712,274,129,597,849,844,671,129,647,193,169,673,614,904,150,181,135,800,285,921,235,923,923,433,680,506,687,473,214,315,206,439,194,739,645,555,281,418,612,760,318,454,935,316,44,425,263,564,442,340,625,60,806,103,551,668,435,146,98,863,820,21,50,167,667,519,351,509,169,380,182,89,38,358,57,429,969,227,971,90,687,199,325,134,744,873,165,833,595,690,112,217,279,895,30,108,344,758,211,693,937,905,414,872,466,200,299,704,309,435,701,460,985,614,503,299,260,883", + "275,276,206,322,829,430,389,103,230,718,567,677,896,945,107,475,382,369,747,237,358,877,511,364,120,693,337,996,604,814,517,653,654,829,55,884,163,985,450,550,889,714,361,516,402,661,886,164,145,929,613,567,121,853,240,463,50,963,625,246,563,889,73,397,853,649,940,531,808,138,190,629,666,114,896,62,144,422,467,84,861,430,773,259,479,387,688,131,770,911,359,801,933,802,271,21,98,958,136,936,573,345,832,728,654,636,813,303,460,686,402,918,830,500,387,718,593,295,848,127,419,445,972,557,940,863,778,598,379,401,172,157,867,205,631,821,905,193,85,895,574,96,452,751,925,136,713,989,465,632,287,34,147,270,372,181,983,487,324,922,621,958,885,373,427,365,998,680,132,157,190,308,766,222,221,932,359,611,667,187,938,643,881,939,721,231,626,872,154,687,304,219,754,707,678,927,254,33,664,420,775,221,825,484,46,782,542,788,349,442,564,89,237,114,953,751,989,205,960,189,722,700,106,130,541,25,220,230,758,360,695,246,296,743,537,679,549,103,477,98,61,625,743,488,372,9,520,256,611,383,334,300,527,136,811,640,954,569,909,930,318,764,228,704,426,100,693,234,956,630,277,327,433,558,626,52,324,566,628,319,335,522,451,379,510,50,565,692,387,653,307,778,789,599,619,834,411,239,935,574,134,239,630,649,482,146,656,491,446,54,805,171,182,247,223,579,642,245,44,314,176,559,722,588,431,4,489,823,424,217,757,273,527,74,550,902,217,51,783,757,86,741,552,742,256,900,348,996,664,231,759,220,241,53,882,400,487,723,996,5,660,492,321,827,163,527,455,674,82,820,109,968,479,944,230,668,946,12,691,790,68,734,424,285,953,156,487,183,203,751,509,248,64,42,448,378,64,751,4,295,306,517,308,418,608,579,846,492,573,667,449,458,451,925,66,694,799,672,104,205,291,467,53,705,780,284,586,593,750,928,955,546,836,929,718,331,52,882,238,535,458,952,694,143,360,2,59,688,175,555,649,353,569,771,537,360,778,320,20,958,350,79,725,865,786,500,613,28,720,227,73,233,570,931,484,675,209,699,632,282,184,444,757,356,159,796,698,772,626,400,630,940,191,234,936,222,392,79,314,884,830,857,665,821,454,147,284,130,119,351,362,380,605,876,940,974,323,759,375,370,58,479,372,941,470,184,105,853,566,173,695,148,558,906,527,347,2,526,366,246,414,595,389,938,87,282,265,609,357,245,631,86,297,198,166,410,730,195,86,794,449,977,796,561,546,830,600,744,83,926,837,107,506,392,434,771,480,28,7,315,513,177,420,739,637,556,981,930,585,55,898,896,24,719,856,745,602,157,965,983,342,457,122,717,182,624,273,140,906,67,533,538,440,458,936,403,192,60,586,643,95,746,417,967,959,54,983,133,11,338,497,960,112,327,143,927,491,225,377,628,664,0,251,288,442,642,221,706,972,11,761,773,23,296,928,829,859,185,237,452,398,417,410,819,830,431,755,996,247,959,885,555,329,612,34,151,345,141,418,249,29,873,166,165,239,963,871,47,983,238,981,960,704,220,953,938,287,191,370,37,597,487,473,671,534,674,103,601,614,520,862,12,723,599,620,589,891,857,296,862,471,196,349,100,902,584,537,559,690,112,978,64,766,719,229,632,348,259,738,96,892,305,836,310,766,929,741,841,243,950,304,130,616,373,199,43,576,875,797,187,906,218,322,572,88,875,315,823,566,302,89,6,685,82,773,227,920,257,141,398,446,966,454,582,802,639,342,859,519,888,52,221,495,791,571,15,184,147,712,657,490,351,315,969,15,284,550,684,877,983,609,633,611,303,65,906,840,794,897,93,119,376,630,173,841,882,475,182,147,915,573,244,773,823,618,559,327,489,420,63,720,990,383,741,488,350,731,270,651,175,944,322,777,639,637,912,917,114,28,128,665,732,76,641,369,663,179,998,104,320,781,128,464,930,298,535,71,738,497,448,874,744,923,162,696,922,137,284,724,319,875,700,123,42,507,943,735,799,367,359,674,49,765,348,30,416,910,956,724,700,141,771,718,53,200,886,560,260,118,667,410,376,654,484,995,415,492,10,430,718,187,276,525,103,894,937,845,39,871,361,711,527,793,440,896,939,791,146,543,381,232,162,598,549,638,425,653,243,528,176,389,367,702,667,496,200,245,619,520,93,740,355,777,417,408,297,301,239,294,440,618,353,652,833,378,162,558,959,354,350,247,347,700,832,225,787,725,647,986,593", + "297,191,595,482,644,75,26,928,680,795,907,102,200,380,685,122,496,967,489,289,741,967,370,323,330,673,287,302,25,793,48,848,42,823,602,573,891,52,705,517,496,914,181,679,889,670,454,832,94,205,530,232,371,878,56,818,697,517,560,138,271,826,329,162,769,906,604,343,276,710,356,642,198,547,460,537,659,775,220,97,716,1,516,123,187,227,490,866,76,409,529,462,652,138,366,57,283,43,671,864,13,439,692,918,239,297,908,166,3,648,731,380,188,283,811,467,513,956,815,443,180,222,894,264,362,594,705,196,833,748,421,960,649,135,603,803,217,627,156,716,180,723,124,473,162,788,569,221,180,287,667,116,31,98,938,810,333,512,205,442,54,551,78,398,242,523,745,533,429,427,574,679,638,941,901,662,851,371,530,206,607,773,160,944,908,65,865,935,540,286,860,475,443,692,640,776,711,152,325,686,800,840,658,11,609,65,866,364,240,971,825,641,17,4,499,848,784,693,774,235,106,420,574,666,622,703,753,319,216,304,521,414,47,250,903,554,279,670,5,553,721,194,365,193,470,38,122,407,521,69,825,435,159,675,442,361,105,551,664,107,436,45,992,188,313,883,951,308,150,764,663,994,835,629,120,537,850,631,839,846,884,720,809,832,353,299,127,191,618,808,360,394,329,511,695,687,136,748,850,933,299,397,677,23,706,188,870,590,250,171,228,612,385,637,249,122,554,410,767,311,524,435,339,393,266,38,117,932,391,282,809,408,143,838,591,983,278,613,876,35,298,404,862,599,979,45,440,218,814,996,703,976,834,406,363,821,522,466,559,385,318,953,74,335,696,242,22,819,454,812,447,853,533,672,909,757,714,818,667,315,822,674,696,119,590,390,510,247,20,381,504,743,172,532,199,266,786,333,289,862,731,859,869,917,212,319,529,176,670,586,514,145,222,656,777,492,805,623,549,920,354,263,129,243,24,977,521,866,924,602,225,430,454,562,831,525,970,388,83,566,450,905,884,923,71,884,812,815,905,634,23,382,132,335,60,624,727,148,138,919,396,900,260,216,207,400,907,507,666,788,316,484,961,921,72,208,858,756,610,289,568,860,657,664,978,61,91,588,676,24,667,551,872,923,254,143,219,631,404,296,710,863,978,673,741,240,510,471,218,45,810,759,764,311,696,544,418,306,376,675,775,472,791,522,279,590,732,825,621,240,469,499,563,810,840,519,53,479,969,96,210,723,462,989,471,549,663,489,533,259,430,539,570,37,273,924,854,703,690,868,388,2,885,243,226,285,151,87,437,820,466,758,555,357,949,777,530,966,240,320,730,603,831,389,569,239,731,233,837,439,733,941,773,67,903,126,477,406,882,859,143,308,182,58,364,169,644,371,67,907,857,806,607,472,49,964,645,419,413,215,770,184,853,131,743,464,600,842,954,882,850,680,444,341,75,147,533,337,80,859,657,251,0,446,559,783,318,430,505,753,114,970,341,959,915,433,413,759,228,282,395,915,717,654,591,437,436,855,896,102,653,316,698,118,119,186,823,173,665,870,831,648,599,75,393,914,766,957,944,392,931,402,995,597,97,675,349,820,655,506,689,957,824,901,797,413,382,263,768,229,122,613,276,803,256,356,819,617,138,667,761,504,518,672,187,240,255,592,132,369,118,226,222,137,822,941,44,317,550,166,916,27,888,404,289,778,167,12,947,889,760,498,127,453,483,566,441,873,535,426,160,306,628,807,705,139,251,199,75,808,330,586,719,209,741,558,269,936,608,539,988,681,409,874,637,535,393,679,878,457,535,881,981,260,387,635,557,986,962,152,916,149,259,869,623,865,41,877,224,340,276,858,585,193,892,204,762,896,741,472,992,243,670,932,189,276,838,507,237,150,181,303,135,604,63,25,309,485,953,809,51,667,614,240,588,606,83,277,625,967,38,556,844,166,314,300,314,147,53,640,579,926,885,931,973,984,256,953,617,261,847,227,465,581,567,603,220,665,834,179,155,200,886,152,336,883,573,426,187,452,975,289,571,853,712,59,588,145,367,352,149,955,973,974,64,979,895,811,499,569,334,640,535,75,987,173,834,838,428,818,788,230,743,555,509,20,707,318,168,628,586,423,222,99,121,100,38,605,163,869,842,877,506,765,228,564,50,896,467,704,781,505,946,819,65,54,173,757,295,37,811,24,134,639,436,27,2,137,306,830,216,941,211,672,498,339,835,537,832,202,186,697,298,828,755,389,139,163,226,986,843,933,774,56,940,627,749,644,51,271", + "246,218,5,542,115,619,543,855,931,346,724,220,46,128,297,722,983,253,720,836,460,903,798,753,999,67,838,87,416,234,146,460,784,127,298,921,798,657,691,907,67,775,843,543,211,407,51,790,650,12,755,778,109,851,921,125,511,601,17,770,938,322,50,496,354,257,800,350,270,145,727,686,45,276,73,42,756,909,274,438,713,349,138,798,122,825,622,751,120,267,39,553,670,636,895,809,721,684,519,596,36,212,899,866,768,972,164,885,902,61,874,41,201,531,26,457,597,740,553,748,3,175,829,829,9,369,173,902,754,43,900,19,474,692,611,917,463,950,966,556,747,132,21,352,558,484,33,662,315,749,140,227,355,680,116,512,56,691,591,162,373,721,701,974,424,445,408,631,747,510,972,234,825,340,398,521,727,601,836,591,410,65,220,58,271,712,502,44,587,531,502,915,631,905,813,709,317,38,379,825,533,457,345,90,937,138,413,738,759,455,338,53,706,978,933,649,808,219,170,585,108,128,811,139,754,408,338,854,307,348,260,160,763,433,432,552,294,442,382,916,154,580,656,274,888,301,633,608,57,770,17,287,226,530,339,15,568,946,108,382,241,440,603,751,908,175,259,796,653,360,398,813,943,769,123,49,174,29,59,2,434,2,872,829,692,687,26,757,154,983,872,873,587,44,156,601,226,964,791,901,505,12,586,385,797,994,236,990,231,17,51,410,246,623,196,326,880,676,716,505,743,605,192,739,908,482,965,83,440,950,331,97,80,159,276,16,40,662,119,701,72,924,210,725,622,680,484,163,502,564,606,200,165,20,970,343,157,800,903,560,705,689,542,674,130,384,837,974,855,103,855,219,858,7,283,273,507,331,938,434,708,432,459,422,46,8,989,659,603,111,595,315,492,164,750,560,701,593,713,184,145,175,738,813,460,516,360,551,354,524,207,980,953,165,330,111,51,768,367,246,280,124,441,668,295,793,799,807,699,521,501,754,728,999,503,713,500,248,100,410,359,907,994,103,716,691,919,480,467,699,310,275,787,417,468,904,919,432,67,910,583,909,746,336,168,716,569,444,816,894,643,139,177,4,441,216,951,770,673,169,236,552,512,347,572,411,269,624,997,31,994,696,629,580,558,652,527,739,823,596,430,750,594,636,114,672,314,251,983,125,169,240,10,37,812,734,492,373,807,325,836,136,892,800,585,397,731,68,739,570,508,684,878,489,257,992,757,54,822,628,168,160,889,449,934,858,249,232,585,807,739,761,278,635,134,231,281,338,16,731,321,574,223,827,930,93,893,588,361,152,457,834,100,553,350,679,765,793,670,867,67,125,714,504,542,273,949,441,259,733,135,283,328,420,475,291,881,325,490,340,796,287,933,245,343,116,770,258,615,358,290,657,918,10,995,897,184,883,770,18,644,440,948,720,736,659,462,156,152,427,760,635,393,479,278,956,958,989,949,464,471,288,446,0,664,858,119,754,875,334,368,403,750,767,292,11,204,744,186,579,390,367,482,160,594,276,852,846,164,869,494,155,920,205,530,872,764,473,7,804,793,662,792,919,228,821,264,312,172,246,955,689,888,255,870,132,887,444,740,927,505,866,198,608,580,984,607,281,338,791,877,696,253,109,541,890,384,224,193,700,671,520,632,400,578,49,719,803,433,286,289,201,596,62,307,972,787,95,655,416,903,860,259,293,820,481,520,857,271,87,14,793,424,199,769,29,512,797,281,143,49,426,498,448,770,165,561,282,194,728,697,317,175,588,206,918,551,523,383,868,714,973,194,74,924,39,373,860,179,179,584,461,923,643,627,294,419,432,23,832,93,542,910,220,251,647,994,25,868,602,46,340,771,75,422,534,329,729,562,870,351,277,769,279,110,910,514,790,584,510,64,660,69,690,51,190,595,349,562,244,497,239,690,251,358,342,599,417,692,264,759,731,21,40,267,604,290,428,459,190,303,15,832,969,661,535,891,667,713,472,343,696,493,876,726,727,129,109,874,259,12,16,915,130,536,433,294,97,243,437,49,570,78,473,454,947,272,252,260,372,657,957,556,369,70,230,350,738,439,985,426,416,981,348,180,843,378,233,638,815,18,525,42,916,546,137,574,499,766,680,373,655,537,489,379,921,872,550,698,317,143,63,723,597,924,192,135,517,70,183,10,651,262,230,278,322,528,393,80,258,966,271,249,349,143,204,391,9,282,994,181,48,325,567,753,313,862,757,896,84,160,37,329,641,810,362,559,136,904,369,594,216,338,313,13,462,520,484,207,672", + "904,503,895,746,935,463,593,883,594,773,602,511,535,334,353,690,238,717,504,116,348,770,518,805,576,25,695,762,476,293,524,527,753,524,499,914,167,507,55,830,520,347,11,849,474,124,35,549,491,628,484,387,603,582,210,126,459,574,846,701,449,512,504,579,73,516,488,223,335,854,35,742,832,753,212,25,358,407,153,24,525,688,222,787,950,838,657,325,412,910,585,216,896,436,225,554,74,846,165,775,551,762,733,159,748,806,716,875,938,424,95,578,374,41,371,297,36,807,937,363,740,547,77,193,20,319,228,719,910,194,48,318,444,213,382,202,365,296,290,872,125,644,37,598,921,56,797,280,606,629,498,132,196,800,461,436,565,552,643,419,937,243,65,466,968,995,84,831,265,23,380,827,655,994,364,256,113,479,764,870,359,43,916,387,842,120,71,942,133,920,28,512,962,772,928,996,583,580,606,952,936,714,287,149,516,195,722,261,211,207,271,767,436,646,525,671,194,355,626,217,780,135,538,882,267,159,474,442,234,147,315,175,199,254,120,953,178,934,295,403,505,595,422,53,65,637,903,651,533,342,712,9,68,378,77,625,215,638,909,732,988,83,485,834,108,751,194,299,897,877,103,869,631,727,627,975,657,329,155,986,396,487,270,854,595,646,86,419,799,440,721,82,581,798,506,132,884,778,534,940,809,634,50,808,233,300,854,302,689,381,702,839,384,282,546,562,455,477,385,58,158,30,481,81,574,371,517,618,710,756,372,412,491,743,658,942,937,83,279,261,184,753,857,848,159,304,404,856,357,529,205,854,421,754,532,790,956,778,225,622,534,118,233,301,180,911,495,661,553,607,553,699,360,403,361,18,339,243,625,923,816,348,854,455,629,912,313,696,739,596,54,242,589,506,867,156,924,717,839,549,733,380,355,727,960,55,956,52,386,590,561,466,242,395,638,584,195,747,963,2,574,456,630,16,972,70,236,779,299,664,867,517,429,717,571,413,26,172,492,42,917,730,106,449,408,997,36,445,265,354,420,937,642,867,123,251,352,798,259,27,763,520,446,260,686,519,286,44,770,490,984,80,778,670,139,804,907,862,520,992,513,265,847,111,658,73,355,918,961,646,32,278,841,97,129,609,864,379,720,945,859,848,841,186,853,442,633,168,456,465,252,431,666,248,105,955,831,832,656,650,353,336,819,432,785,820,296,125,29,3,71,478,615,219,317,559,241,66,117,396,796,55,561,25,136,839,250,887,970,758,685,83,397,822,369,957,623,251,662,577,586,330,62,793,71,169,744,225,644,811,386,953,747,545,582,96,429,263,145,917,559,424,122,484,477,531,93,39,70,997,922,92,311,668,742,709,865,755,829,533,408,394,812,980,158,230,940,289,760,446,874,55,787,587,457,270,353,738,162,98,442,458,563,710,845,23,161,209,76,496,395,584,106,790,933,966,773,594,853,747,953,442,559,664,0,97,986,905,337,344,463,499,723,698,486,582,845,713,448,318,615,773,920,397,785,805,655,836,234,146,338,827,711,135,791,741,60,970,225,223,220,862,529,268,185,370,664,327,583,990,521,983,451,376,996,502,118,793,120,356,362,754,509,820,265,245,14,39,459,914,377,778,577,842,201,625,934,800,660,524,977,535,779,985,11,609,469,476,2,739,823,488,469,810,656,17,403,596,364,795,574,9,515,165,902,816,356,781,480,190,752,32,35,553,209,673,635,679,459,657,70,147,617,625,682,962,478,216,20,534,965,963,625,364,96,455,851,490,141,730,208,955,336,110,742,396,787,496,114,269,514,448,645,974,345,750,773,382,745,345,549,381,314,501,737,727,666,911,537,42,787,433,396,545,540,465,599,596,298,188,703,704,728,934,694,597,225,154,179,235,588,205,730,72,140,597,171,34,453,588,298,66,616,463,182,443,881,722,204,348,869,489,430,76,65,894,357,913,833,30,372,627,865,444,714,881,141,304,992,538,997,583,974,896,452,936,296,400,860,369,617,132,140,595,681,725,480,828,965,781,271,886,556,221,506,100,939,354,152,907,662,668,96,909,335,548,123,103,410,762,160,15,761,963,860,395,415,539,361,948,384,923,366,673,385,975,314,988,308,540,104,157,199,169,424,623,730,282,289,785,84,576,731,302,190,823,431,663,696,105,483,64,61,338,107,324,106,130,637,302,722,11,582,877,861,448,628,761,784,841,293,493,930,77,158,858,896,320,109,545,581,403,942,737,669,937,678,33,839,64,751,148,49,305,367,732,426,24,14,385", + "24,751,787,391,807,196,847,117,105,259,150,303,366,866,357,676,182,587,350,171,520,491,659,614,938,618,521,501,775,377,794,641,583,892,188,813,723,274,899,79,163,855,927,121,579,243,348,340,307,580,624,742,475,732,211,268,899,325,259,614,669,735,942,460,381,128,498,708,800,953,271,622,325,301,802,885,473,927,892,375,733,814,166,491,179,817,918,33,138,690,202,693,314,823,659,956,815,736,485,710,252,47,80,732,559,459,240,497,645,243,655,655,895,212,199,968,423,414,181,838,342,509,724,78,362,506,156,261,500,389,691,926,644,105,743,441,843,296,384,331,230,750,348,663,946,735,816,85,869,782,455,832,369,604,154,43,263,778,841,293,894,920,465,75,129,624,162,570,258,444,574,760,298,109,976,658,763,70,820,188,245,608,462,870,571,710,607,831,167,916,300,778,799,22,981,375,530,714,759,772,750,80,189,998,249,905,887,386,248,629,396,61,149,300,724,928,359,650,801,247,13,284,20,126,338,83,136,629,230,750,887,865,590,862,659,931,16,78,271,944,189,681,110,904,65,119,842,324,737,562,827,613,643,535,171,186,16,830,55,2,269,732,130,885,609,728,579,957,839,532,861,355,24,24,497,871,42,488,76,586,508,24,732,202,756,38,565,389,929,340,224,185,564,703,998,743,523,292,33,952,712,851,590,274,781,531,70,443,952,319,98,958,664,1,229,15,407,3,333,985,117,899,870,567,714,167,188,806,908,177,114,33,274,434,252,488,169,483,544,919,738,203,191,448,373,618,232,297,296,37,50,886,16,786,831,843,181,388,177,402,618,57,240,534,159,835,651,121,296,656,669,75,617,544,672,123,997,596,287,719,668,550,741,317,25,937,258,919,864,576,15,942,25,544,411,558,579,728,327,421,294,972,462,932,740,377,33,879,887,477,558,481,856,273,595,745,252,135,937,717,897,842,175,339,83,985,905,746,242,803,609,354,831,688,639,730,100,671,745,811,464,695,631,419,999,337,870,33,965,881,467,640,526,523,210,480,204,155,985,846,160,936,359,584,965,597,280,20,828,661,611,742,284,859,243,729,68,197,760,571,708,118,579,598,895,464,224,869,299,971,822,459,544,673,406,845,469,62,736,30,905,441,588,444,15,251,899,585,376,174,328,517,61,915,27,224,283,911,310,421,520,303,153,957,652,763,808,146,553,52,297,136,836,245,821,867,83,693,557,74,146,133,924,217,655,308,829,537,641,94,682,153,903,459,911,839,885,422,432,116,154,534,628,798,967,108,621,74,300,804,430,800,296,682,723,283,576,926,940,592,367,521,112,870,511,853,463,633,317,581,438,503,198,244,494,360,761,72,731,900,738,943,538,270,291,793,584,708,937,416,777,112,61,256,679,449,602,35,638,509,322,318,49,898,490,924,644,509,794,818,743,119,7,561,872,63,883,294,851,825,270,642,783,858,97,0,991,480,901,265,246,391,648,119,187,710,45,35,507,359,646,846,997,582,510,89,501,266,217,121,143,28,475,599,955,304,666,70,196,92,436,670,658,654,483,281,984,665,303,139,283,419,906,112,873,483,349,687,143,16,896,973,472,500,499,905,691,743,640,761,263,633,440,414,178,848,697,14,462,75,37,724,816,805,853,631,315,213,158,870,931,609,160,507,221,921,576,261,277,663,777,876,713,431,115,565,452,576,443,432,957,801,10,839,55,684,109,610,907,629,205,881,464,754,130,835,44,865,590,674,234,871,818,822,511,749,744,25,763,301,601,991,876,349,234,319,586,862,903,380,427,242,404,499,602,131,449,645,363,620,674,494,790,402,989,665,731,334,4,114,707,174,738,510,891,124,468,582,736,384,501,583,186,481,246,793,874,716,17,359,429,485,115,667,523,907,149,316,451,923,425,10,980,58,641,275,528,799,579,722,204,309,921,754,822,929,379,420,711,112,894,242,504,453,224,233,557,591,504,300,853,152,218,590,109,258,654,429,451,6,5,290,28,637,363,243,239,899,743,410,442,104,130,8,560,210,790,696,676,279,471,10,239,555,52,989,504,518,790,355,665,644,229,246,659,460,70,779,507,779,259,314,767,996,336,816,345,314,901,869,817,565,327,544,137,714,196,412,791,315,556,458,878,954,851,16,435,435,205,427,728,475,313,58,691,194,257,11,883,925,262,179,12,322,942,276,324,993,700,487,873,168,582,385,443,149,563,15,549,754,87,108,83,142,648,435,630,406,772,660,485,961,107,818,113,800,952,20,412,396", + "327,994,47,529,283,760,648,45,617,546,442,585,258,16,159,805,303,582,154,757,947,579,195,138,56,81,479,892,613,643,185,529,438,536,831,408,205,686,999,529,352,130,22,300,910,513,832,690,674,921,49,111,4,431,410,894,58,210,342,14,431,90,594,133,915,723,98,499,720,314,639,587,834,52,263,831,535,30,138,579,38,566,490,895,771,221,394,878,306,657,978,388,131,834,57,95,478,796,621,819,707,753,459,411,701,51,98,406,157,554,465,998,637,381,175,428,43,160,117,409,79,130,517,984,166,294,931,642,621,530,903,902,608,372,770,443,780,855,925,832,963,396,936,292,959,853,466,249,442,86,255,549,119,492,110,614,557,263,371,886,14,442,986,578,210,884,638,594,22,693,664,886,35,903,859,223,467,884,381,519,43,189,204,124,780,746,121,570,23,116,696,174,166,796,360,222,704,243,680,544,516,769,93,275,630,187,406,834,421,336,752,288,110,129,80,74,909,937,894,145,557,948,385,945,191,761,798,766,827,153,873,513,256,517,802,276,462,298,571,353,357,259,756,815,390,486,639,12,237,739,599,794,905,679,782,180,961,9,566,308,442,61,230,645,787,899,676,380,881,420,805,634,818,117,316,332,63,961,260,211,208,69,311,67,996,378,84,132,318,139,223,338,64,362,967,43,943,217,364,194,762,814,555,926,594,244,108,501,903,613,630,410,562,920,606,41,75,530,120,233,93,936,211,896,408,280,776,919,253,349,325,278,695,536,908,292,183,219,543,636,218,112,583,308,617,945,226,554,850,382,959,700,234,763,247,719,698,870,353,838,675,965,638,329,913,271,669,928,531,994,410,764,573,887,193,301,377,268,304,76,693,154,823,622,852,551,414,663,863,49,541,550,966,648,369,368,948,586,830,893,351,735,67,532,176,182,771,863,523,339,17,95,917,901,575,582,249,952,72,721,179,113,673,661,438,707,694,220,58,280,177,502,240,2,261,299,149,79,881,545,643,95,100,238,846,229,143,954,742,847,532,666,560,203,670,222,253,931,430,757,967,604,96,833,639,390,233,904,332,368,78,52,978,737,277,795,404,908,450,349,92,274,923,88,568,808,315,709,121,81,433,198,567,807,164,246,812,379,336,216,59,1000,841,388,185,323,701,72,379,163,267,30,668,990,518,712,158,977,925,444,122,193,974,192,876,91,997,196,607,206,236,264,897,267,144,362,871,490,453,708,349,302,933,230,503,730,493,986,684,414,925,507,741,188,19,342,24,957,255,74,46,479,336,682,370,924,628,482,729,104,569,293,86,815,395,339,628,241,849,913,658,583,769,748,570,375,704,838,717,380,19,53,768,527,762,124,595,155,966,718,275,943,793,159,525,402,269,490,156,68,144,652,395,243,733,737,327,795,13,546,172,856,782,851,48,393,875,804,938,217,459,684,557,633,332,687,472,660,99,67,401,221,318,119,986,991,0,581,985,669,360,135,140,232,42,748,995,874,468,866,312,97,496,92,353,400,598,559,357,126,906,908,361,902,266,570,438,713,224,968,954,308,400,178,747,247,366,300,335,379,363,954,109,440,664,165,285,255,150,470,834,78,505,328,9,731,700,387,160,252,710,989,323,19,626,680,331,421,233,348,467,939,300,707,689,201,411,726,651,350,440,781,673,939,794,940,118,169,97,783,60,921,402,822,324,53,747,810,665,814,937,801,203,35,257,80,519,457,59,876,204,715,244,83,298,159,577,43,431,580,547,680,236,199,20,193,357,935,894,854,604,874,605,900,360,474,643,188,981,177,862,728,400,968,724,513,502,515,6,740,495,854,392,978,900,217,534,50,899,29,512,143,128,239,761,694,484,235,406,701,385,401,484,218,820,1000,988,407,388,949,652,132,305,230,734,95,183,83,124,220,429,441,889,611,726,658,303,954,493,353,100,56,570,327,197,705,259,265,761,107,608,677,756,838,987,188,751,985,976,10,765,73,474,709,68,163,972,729,486,48,473,4,930,538,381,852,528,404,473,956,11,452,604,117,675,784,503,379,74,979,7,172,209,570,72,111,526,565,861,695,128,57,660,140,192,870,33,358,327,643,792,330,421,897,184,210,611,669,767,45,25,663,657,891,595,337,569,628,682,853,455,100,833,441,55,458,857,836,455,278,848,234,635,563,975,421,123,281,845,734,90,713,297,243,270,920,424,433,261,689,57,429,606,594,814,735,457,802,4,329,2,745,219,232,666,65,26,746,309,410,347,651,716,431,419,131,667,628,153,362", + "474,171,844,74,48,490,138,955,359,564,336,5,858,356,158,149,380,774,681,111,474,350,752,576,459,673,623,149,505,148,695,585,48,484,457,647,130,955,97,386,230,141,26,520,285,419,965,805,941,177,30,6,750,922,127,203,868,671,551,686,569,834,227,348,774,574,431,692,715,271,951,408,768,330,944,168,960,107,425,942,20,120,600,154,452,404,432,736,99,793,163,627,11,333,507,484,205,619,847,418,881,530,70,759,622,438,522,885,963,595,801,423,647,404,982,449,43,925,96,112,695,693,436,360,652,383,269,580,228,702,219,574,281,626,240,973,752,739,412,130,50,312,212,352,646,879,112,203,818,682,646,698,122,989,121,950,791,670,848,680,440,622,243,858,323,600,324,3,899,388,170,203,749,60,164,89,705,129,155,583,801,487,395,50,853,185,452,550,854,532,457,668,956,175,43,872,501,920,897,406,630,5,105,539,52,52,55,184,47,101,850,367,583,470,559,233,470,663,429,894,32,140,102,550,835,24,860,364,970,257,245,114,949,804,734,176,208,118,161,844,212,337,12,672,814,965,796,26,228,85,830,19,171,591,716,206,142,760,867,33,562,292,335,617,654,450,734,863,152,596,573,627,270,932,657,738,562,635,606,112,305,529,383,959,39,763,103,410,643,345,99,228,76,925,385,614,609,742,574,241,115,274,267,436,642,979,859,284,773,340,312,821,151,93,739,897,868,828,849,531,301,306,193,977,215,243,620,829,630,110,604,298,4,596,788,455,208,160,256,183,283,918,249,175,866,568,855,816,805,140,761,881,868,536,198,53,792,473,56,260,604,945,141,849,244,546,114,857,866,425,206,655,373,344,970,917,383,366,189,12,220,994,479,935,810,45,9,949,135,197,329,194,332,501,647,587,632,14,735,340,924,22,132,155,564,356,286,206,77,305,971,63,618,749,414,799,927,695,694,573,432,598,590,511,896,872,901,402,256,510,238,693,640,708,226,735,421,232,628,960,670,222,848,748,999,518,186,430,242,288,419,776,984,412,261,483,927,138,635,734,119,586,812,304,861,469,886,174,504,429,219,433,942,382,223,420,363,790,555,141,984,375,892,279,911,978,795,266,71,887,268,801,948,887,148,397,713,166,441,567,902,283,829,245,790,816,629,124,310,452,40,865,221,558,482,735,660,690,921,393,17,750,157,371,583,141,603,94,484,575,572,478,449,271,84,598,877,305,360,230,358,416,217,168,657,495,264,824,958,644,494,544,811,528,937,772,754,169,173,944,743,696,943,838,981,789,460,341,241,640,360,592,140,478,68,702,268,836,316,53,826,290,439,436,604,491,383,938,529,281,356,414,144,234,969,29,769,609,439,235,288,70,203,140,207,24,906,454,380,437,335,848,657,441,132,901,922,910,191,504,892,100,529,65,908,434,428,650,923,330,763,465,715,885,610,458,355,688,570,366,461,706,430,754,905,480,581,0,992,825,975,951,899,970,424,444,595,107,646,905,929,305,436,862,862,829,930,436,270,31,197,897,307,275,938,174,704,826,599,547,735,517,745,554,885,510,14,942,628,794,426,5,625,445,908,835,688,911,899,583,65,887,806,368,361,35,3,608,186,920,987,231,916,489,349,211,834,181,920,176,177,489,74,624,372,565,771,349,307,604,852,157,13,788,63,37,102,771,167,115,963,2,23,627,179,718,789,367,679,150,629,195,702,446,616,519,511,642,297,328,414,318,759,312,720,249,767,396,368,682,914,121,450,302,578,716,768,621,68,277,561,277,294,579,420,466,389,583,233,224,121,134,420,213,117,284,489,397,464,590,683,236,342,45,615,79,6,748,104,301,887,595,114,906,29,600,392,406,958,141,947,599,641,601,85,67,526,93,668,753,888,162,362,34,524,598,363,715,520,828,709,181,462,597,832,952,427,46,210,534,376,28,929,958,499,552,977,457,204,526,40,821,144,451,485,546,180,545,331,209,727,466,389,1000,480,603,347,424,386,839,209,451,910,732,366,805,739,716,755,86,731,176,52,679,413,27,883,193,304,669,433,366,198,6,983,897,919,870,236,492,529,977,190,375,816,461,405,951,433,518,33,94,129,344,33,531,140,792,381,362,45,639,420,581,227,558,565,80,558,862,127,165,761,80,98,749,450,576,820,885,975,612,830,331,261,634,279,732,138,117,301,153,994,187,247,655,542,217,173,424,196,649,525,479,323,695,223,855,224,817,812,268,2,641,671,520,252,979,128,284,46,205,33,55,445,428,853,462,612,94", + "455,530,458,858,38,338,134,882,169,265,278,109,980,25,702,491,734,382,564,272,371,880,670,778,822,297,694,11,133,207,220,963,512,235,598,646,769,823,395,768,157,684,972,33,499,336,291,572,760,998,204,453,840,434,808,106,43,18,137,593,957,5,14,826,133,480,787,851,291,548,329,235,335,975,130,4,566,495,879,513,597,184,484,135,685,22,85,314,262,980,504,84,758,812,938,374,235,475,639,332,947,619,438,236,4,721,947,729,714,30,314,700,772,736,790,93,845,186,491,591,315,394,337,442,706,401,359,52,615,28,498,196,874,478,869,476,851,788,395,736,438,607,260,856,728,137,361,639,725,777,173,676,142,649,970,723,746,173,146,150,653,940,74,497,264,135,689,351,786,348,212,348,268,903,82,271,53,427,282,899,911,632,470,367,785,875,282,906,711,828,631,774,25,766,585,591,635,345,939,631,124,811,718,979,51,985,840,89,959,903,546,366,389,285,468,483,117,897,744,215,769,873,143,797,257,170,509,573,485,292,157,289,583,280,185,85,3,289,960,39,334,255,355,302,514,766,468,113,623,544,87,295,342,987,157,480,243,376,718,463,884,881,184,93,575,439,743,492,433,944,515,655,607,569,583,833,305,657,223,998,923,70,432,758,960,190,938,930,858,712,267,98,83,433,503,343,472,757,415,730,497,270,63,108,858,976,449,125,590,473,905,969,16,879,149,191,870,664,877,497,595,629,979,230,118,214,223,578,952,707,670,328,730,897,795,801,595,130,295,889,823,711,944,859,486,42,912,493,9,785,408,105,995,312,191,57,280,263,604,609,316,209,770,350,59,946,847,22,32,148,629,396,925,975,101,579,217,867,431,673,561,432,4,930,30,362,181,908,551,807,567,166,959,906,474,966,884,715,314,529,530,958,581,206,479,798,147,369,917,316,822,807,182,402,726,771,279,817,429,248,734,845,466,421,186,283,765,633,505,906,512,856,596,87,752,202,747,187,948,762,231,25,391,514,544,896,335,554,874,309,240,410,89,90,216,175,211,654,777,624,530,190,455,648,522,414,862,426,910,98,803,628,419,642,986,394,449,829,34,47,86,616,393,52,309,631,274,520,524,573,67,266,979,134,975,257,451,280,493,292,903,30,446,386,88,921,276,405,821,153,606,67,788,689,868,373,671,456,280,867,707,921,12,108,360,353,236,745,438,194,127,471,634,775,307,94,952,877,818,948,653,165,402,930,183,414,854,682,367,875,436,337,235,817,563,880,399,609,888,952,162,595,879,181,511,921,670,302,976,757,792,969,127,716,973,724,837,159,883,622,717,932,656,696,624,925,965,286,654,490,467,805,610,280,404,416,868,13,725,132,397,811,735,432,385,580,615,259,971,330,980,953,631,908,77,903,735,422,417,98,623,321,594,810,65,336,678,2,598,609,150,695,783,843,18,34,592,345,634,825,390,972,505,875,337,901,985,992,0,598,645,259,344,174,360,120,725,837,451,782,41,306,690,220,924,618,687,732,118,188,470,324,803,72,271,18,914,868,438,36,823,716,447,663,422,195,976,59,338,187,532,784,792,200,356,719,229,573,258,320,941,538,719,366,835,46,323,775,892,269,525,51,297,703,490,691,365,18,723,658,107,464,962,922,367,768,592,886,285,318,179,468,803,339,241,70,228,609,383,11,663,887,244,816,386,548,750,945,762,167,68,670,160,708,421,345,272,464,320,456,282,675,458,187,955,198,638,442,883,174,943,836,889,750,488,349,941,839,395,572,924,85,827,245,609,926,365,998,867,610,122,875,483,970,576,261,308,650,164,207,493,349,716,72,747,881,783,982,596,911,106,519,365,206,379,872,550,908,217,757,645,728,498,67,950,957,293,924,322,532,644,281,731,879,748,780,671,646,904,200,831,625,922,200,848,727,363,560,873,969,273,171,956,333,951,233,99,933,186,732,947,379,336,136,813,457,259,548,536,844,297,752,795,864,256,75,581,641,766,626,252,730,825,976,377,620,363,661,940,475,384,893,741,386,481,252,97,553,774,238,334,67,736,499,589,553,503,412,913,731,294,264,203,384,422,605,271,373,997,689,933,923,721,400,899,377,657,915,490,104,498,811,7,486,122,357,268,145,887,80,457,695,272,978,459,980,935,795,257,957,637,685,902,450,719,176,937,270,937,664,271,753,692,750,565,448,807,30,939,102,482,29,973,757,700,744,711,129,328,731,723,69,244,563,421,204,991,796,294,120,878,398,42,873,221,681,18,226,130,186", + "395,884,451,355,796,757,430,877,649,928,813,189,761,366,42,613,349,154,143,479,60,406,763,897,817,243,716,2,40,415,391,347,186,460,440,687,321,903,197,739,492,149,326,19,419,935,942,490,510,359,523,733,31,46,380,729,696,541,452,503,53,206,658,980,360,546,335,415,523,799,618,19,30,467,836,972,986,127,49,227,296,351,111,568,110,642,545,942,244,349,61,760,91,568,362,980,632,408,302,396,7,94,962,347,583,68,751,681,239,956,838,995,720,631,9,767,891,78,57,56,203,845,541,903,72,277,303,168,175,90,334,193,926,535,588,115,303,895,273,199,20,726,787,203,750,515,534,429,889,399,545,368,419,642,530,320,243,732,815,320,613,27,657,693,298,179,507,14,242,71,204,676,381,639,580,526,817,402,118,650,646,24,189,495,263,953,844,586,186,769,922,887,862,193,182,67,822,846,397,221,742,319,190,174,261,129,149,675,250,912,90,946,402,223,601,807,613,36,166,64,612,212,536,894,445,232,251,921,695,648,884,762,123,238,431,475,362,942,195,566,659,488,947,369,566,539,430,557,611,849,454,777,264,918,77,925,581,768,888,681,505,416,233,383,277,272,469,246,880,744,401,953,604,607,586,736,242,318,966,552,767,683,526,70,937,824,315,578,877,517,173,98,804,820,527,265,246,919,374,983,397,926,112,853,417,17,917,866,71,952,393,501,631,9,600,782,607,486,283,752,938,52,623,709,938,891,110,403,575,376,376,859,602,981,470,920,528,927,17,729,872,570,626,40,295,522,466,328,781,18,716,610,458,115,353,883,531,219,776,374,884,655,935,702,73,92,574,984,368,415,611,638,707,296,7,38,510,336,990,355,297,759,585,509,116,156,296,131,77,143,617,97,185,695,951,519,417,809,34,570,886,827,277,67,287,203,436,747,105,290,28,403,245,658,533,716,882,88,934,428,573,491,881,63,88,75,109,386,982,910,275,935,40,95,988,299,879,68,188,949,712,943,569,865,610,17,246,885,42,886,90,989,523,347,5,957,934,775,180,398,407,771,674,615,254,832,109,346,134,319,735,893,232,221,46,542,386,428,651,704,275,840,843,87,717,809,131,190,271,157,961,423,66,355,571,850,777,266,108,114,140,813,245,358,853,67,230,370,266,462,881,16,990,34,916,962,646,588,603,506,324,982,598,247,571,121,850,250,12,223,316,971,179,149,400,879,336,169,811,963,67,975,529,254,430,751,426,409,962,316,776,682,669,220,943,881,327,209,432,498,50,103,463,355,895,318,562,447,98,884,383,38,758,456,12,343,249,183,441,638,899,329,89,96,207,67,859,909,89,280,208,314,845,627,883,966,346,703,371,219,733,449,981,676,20,30,143,523,936,931,719,976,238,537,222,357,715,148,161,28,797,141,976,974,369,163,518,543,421,446,332,994,849,277,805,348,640,913,152,708,23,11,753,334,344,265,669,825,598,0,452,785,665,467,912,705,662,638,355,431,597,296,316,591,675,499,596,615,833,709,118,86,877,669,902,130,37,245,938,536,261,580,219,451,146,135,451,698,416,573,241,297,593,624,980,91,502,240,276,157,363,6,688,83,182,478,695,700,30,188,61,850,334,228,491,64,401,507,222,432,307,151,613,708,581,865,748,299,44,514,266,607,137,235,547,987,248,232,133,103,150,357,267,838,459,595,992,587,301,807,601,82,953,36,236,543,772,79,185,671,658,488,578,657,757,178,19,649,234,344,945,276,351,342,85,798,385,145,115,167,132,523,696,213,151,915,467,546,725,159,927,982,716,706,280,936,18,835,577,668,54,422,746,315,231,383,13,253,494,220,391,318,803,639,654,537,489,865,612,287,471,624,535,548,984,1,209,284,52,781,382,751,827,88,932,428,532,13,721,808,429,874,566,177,102,899,213,232,436,679,319,652,742,222,725,479,430,566,632,309,973,902,829,379,18,119,234,900,760,140,267,321,190,518,33,607,701,663,487,17,714,203,155,200,926,103,811,482,329,342,57,802,746,66,154,245,957,315,993,696,556,73,980,32,641,923,206,827,527,164,460,77,316,413,141,78,430,996,745,588,183,657,521,75,180,874,90,920,587,693,789,258,505,477,681,718,930,133,673,462,459,933,319,130,590,575,307,206,572,961,612,717,958,934,116,831,514,881,906,331,561,292,782,190,455,884,168,359,859,260,192,155,382,505,606,485,910,167,374,429,556,539,184,941,657,891,724,912,460,713,241,771,636,59,950,2,415,130,718,835", + "148,538,269,46,924,161,266,718,80,365,709,859,407,431,715,56,254,261,881,695,291,991,144,621,165,678,14,200,758,471,157,474,455,708,62,834,437,883,779,999,302,56,268,343,445,965,969,184,255,22,176,559,840,805,670,109,895,384,295,410,541,723,284,112,783,406,339,810,833,323,93,575,975,242,671,989,108,838,201,155,515,768,72,15,313,142,700,562,529,577,226,473,704,616,351,545,724,257,432,255,591,767,26,199,753,819,689,538,488,178,528,778,696,920,5,100,221,754,756,248,866,411,356,593,362,265,94,762,204,330,213,75,323,156,34,484,633,607,585,196,518,629,6,447,822,725,764,137,157,25,389,194,884,244,345,106,909,821,535,951,989,415,725,656,920,279,987,851,190,935,938,896,455,386,62,585,475,605,714,388,822,530,775,296,55,939,40,952,341,227,842,852,23,896,79,986,148,819,735,113,676,223,498,640,792,586,58,617,879,671,794,621,438,476,131,587,967,964,619,545,585,6,403,902,714,535,931,696,808,531,686,654,703,592,233,237,143,612,216,284,131,987,795,371,779,312,176,438,547,902,676,166,220,75,61,190,429,680,68,776,942,342,647,782,829,641,790,497,584,92,931,400,364,498,911,840,118,715,956,504,121,498,113,780,137,589,578,725,991,938,855,586,341,981,509,820,969,911,405,978,26,227,786,357,18,657,499,624,467,703,78,93,6,949,760,24,431,59,815,202,140,17,427,568,177,788,426,181,921,877,741,747,533,387,534,946,474,717,782,856,889,535,23,761,2,575,490,809,661,777,292,997,37,877,302,396,976,692,593,36,964,545,465,847,590,484,758,437,407,958,410,345,913,72,740,240,35,261,204,941,352,523,428,267,125,722,364,715,608,9,942,163,785,912,647,732,736,885,783,997,339,260,115,338,794,191,390,428,712,495,607,427,890,363,35,751,447,223,458,86,988,558,151,868,419,310,68,334,433,174,232,7,736,844,600,729,756,169,772,970,730,200,649,360,352,261,517,121,428,507,138,33,477,375,117,753,577,994,81,256,783,444,539,421,292,328,121,235,737,698,352,57,24,423,710,656,882,779,716,390,191,752,312,499,885,390,986,990,133,329,431,476,730,349,675,948,484,670,579,451,449,557,838,789,194,934,311,208,783,944,583,268,158,396,202,510,711,313,340,956,481,11,930,586,562,417,52,267,342,21,205,493,710,672,746,764,215,83,548,846,642,806,793,984,440,345,256,221,672,961,561,459,62,193,329,522,815,523,17,427,407,31,234,360,898,17,248,460,699,732,829,24,698,318,603,754,52,298,241,623,109,745,476,481,230,868,9,64,976,389,280,723,392,498,671,746,438,27,327,753,579,654,368,677,570,57,30,850,314,536,929,597,961,15,761,562,879,261,520,137,296,520,311,797,121,107,744,948,898,347,247,164,913,29,5,606,305,834,112,538,974,761,114,368,463,246,360,975,645,452,0,323,434,5,671,212,159,489,630,581,373,397,372,591,681,178,671,654,931,75,19,100,602,990,922,446,621,349,850,985,918,820,789,602,556,824,407,571,702,458,474,31,792,349,217,276,427,315,689,265,573,574,185,40,388,6,217,971,548,606,58,548,776,483,165,448,952,498,910,777,327,84,157,608,971,709,561,261,162,346,488,422,840,897,946,874,168,20,979,991,883,112,805,92,477,843,608,154,465,148,523,519,714,8,795,730,967,161,875,465,803,657,266,631,621,779,490,412,722,275,225,867,338,666,924,60,478,291,419,375,796,445,449,957,857,631,279,452,754,249,347,258,663,116,751,764,709,789,412,49,761,460,879,332,204,170,36,232,254,266,194,634,532,131,899,611,244,212,693,960,227,978,264,392,114,574,310,627,229,44,521,628,756,946,772,581,586,964,75,731,573,225,51,144,983,645,4,366,523,540,70,408,862,432,164,797,849,451,603,93,934,856,407,354,926,290,870,296,501,169,948,777,935,851,429,339,870,120,870,182,736,249,273,681,369,976,602,277,287,84,383,434,927,404,795,687,968,866,190,841,404,769,23,350,553,417,515,38,893,988,387,310,711,504,843,969,83,564,554,908,530,284,750,471,347,629,440,139,730,763,473,207,594,632,102,498,427,628,563,413,267,158,935,786,18,350,644,688,621,121,210,242,976,229,862,650,35,645,139,95,953,286,821,642,28,221,55,661,412,293,893,229,647,182,720,393,383,174,173,691,353,300,731,775,243,510,791,819,382,379,801,191,180,920,864,649,894,937,570,660", + "330,653,716,530,559,64,439,174,20,612,766,250,951,587,917,281,965,897,130,7,60,568,884,796,798,272,607,266,363,398,808,747,980,991,621,968,985,63,293,214,440,808,10,964,996,684,78,516,716,565,165,930,928,196,404,412,31,927,137,994,879,526,51,993,670,429,233,878,972,722,173,199,640,457,736,552,335,699,394,654,170,257,55,488,342,427,884,386,184,792,578,492,607,41,300,937,327,300,338,338,988,367,106,678,449,548,388,223,518,328,910,543,906,8,204,155,740,35,818,200,685,555,126,967,671,680,12,807,176,537,921,896,376,972,593,304,511,610,571,631,426,57,915,625,183,86,654,206,569,498,923,526,283,907,864,43,595,632,725,710,92,782,534,65,704,339,685,752,357,253,67,848,816,280,29,685,35,61,733,536,179,888,298,262,624,7,933,170,290,554,551,307,80,304,387,24,969,45,652,700,404,388,936,935,877,19,720,438,759,829,945,443,922,89,476,474,685,90,665,100,451,912,508,737,527,959,551,488,16,129,480,409,507,417,34,558,966,80,417,839,245,20,328,707,128,91,963,806,517,897,985,357,660,454,743,440,225,25,154,230,185,862,110,820,444,771,639,923,430,595,865,597,353,942,143,848,900,384,658,807,135,359,884,21,496,209,554,450,585,633,28,124,613,896,669,901,525,924,332,693,478,93,505,391,636,65,51,201,268,926,719,610,244,116,120,539,50,104,670,655,282,524,962,827,448,943,975,40,143,676,874,352,44,625,947,544,383,85,766,511,407,541,820,163,284,618,978,374,148,679,315,114,172,276,553,917,377,428,390,134,292,244,881,727,330,882,767,801,463,588,323,827,208,549,262,659,602,413,80,964,402,490,775,638,83,797,641,775,402,209,609,57,871,604,620,556,675,921,922,523,287,876,675,148,353,236,48,721,29,44,40,928,585,96,676,228,969,121,943,621,327,845,380,702,253,757,852,65,507,889,295,738,864,257,753,881,779,938,201,855,420,571,977,222,177,235,357,869,146,270,988,270,201,42,419,104,705,126,30,13,344,649,172,623,852,986,982,474,459,688,49,408,818,852,687,272,175,403,372,457,662,25,785,792,675,717,618,42,486,296,599,67,116,261,663,864,229,204,109,801,938,35,874,480,58,305,330,158,571,658,218,438,735,954,346,358,560,789,280,700,189,938,758,872,844,418,649,681,135,212,264,133,259,103,400,901,1,463,532,254,515,530,155,999,60,678,774,102,225,670,692,352,314,361,920,272,957,466,286,693,348,821,132,818,719,942,34,799,205,944,406,922,542,304,868,759,582,572,751,375,87,984,323,440,280,842,261,734,910,803,433,790,681,38,17,736,829,832,486,555,339,990,252,543,670,130,663,719,891,925,623,792,834,792,759,808,474,603,432,83,313,861,520,739,720,40,74,528,310,789,163,93,359,484,913,931,65,401,484,6,733,773,970,403,499,391,135,951,259,785,323,0,892,537,726,931,916,80,609,332,905,250,118,363,955,233,777,267,89,405,645,436,525,971,644,255,451,640,326,872,371,756,82,930,689,716,732,264,721,631,353,168,925,389,128,392,26,918,903,563,159,881,428,40,60,425,615,135,519,286,959,39,611,223,141,980,410,694,672,193,646,590,181,764,200,292,485,820,779,928,77,989,115,995,91,254,819,247,737,29,40,253,758,868,996,348,968,957,865,207,780,846,617,327,88,895,665,286,619,463,822,199,32,823,931,38,201,232,536,516,699,232,983,898,684,696,344,700,374,51,582,190,805,607,231,790,464,526,708,287,179,995,284,962,917,42,83,52,111,341,73,557,224,569,103,195,48,957,91,407,230,277,933,723,35,195,744,861,340,359,361,891,933,806,421,286,126,900,603,381,927,950,943,684,109,924,895,686,192,776,362,257,913,986,830,839,836,882,966,512,654,158,474,277,994,572,735,796,846,289,262,60,494,645,516,584,668,522,699,456,336,491,426,967,442,310,278,387,431,32,539,535,834,463,169,586,499,887,489,698,335,349,92,337,584,936,647,827,463,912,615,897,449,508,646,51,928,91,558,703,386,10,53,324,244,958,270,283,907,769,151,97,418,574,273,933,647,813,494,513,398,999,392,382,583,613,878,727,555,282,778,958,593,105,406,431,645,489,775,246,73,98,137,997,220,510,657,758,785,93,381,175,106,937,626,905,601,248,272,3,636,996,312,890,727,241,272,273,923,102,167,978,499,789,248,733,675,178,231,574,587,761,406,891,82,395,222,868,327,735", + "919,69,260,200,160,626,858,536,285,390,238,387,425,677,832,49,224,383,67,550,809,158,764,791,116,330,185,868,632,400,322,577,972,69,857,110,527,234,213,905,256,930,34,876,286,691,222,196,754,718,580,560,536,72,130,258,869,49,315,304,446,592,738,69,101,529,898,753,267,405,863,285,520,288,534,566,146,35,528,174,70,811,566,579,431,959,877,585,78,257,945,552,60,329,700,61,444,255,909,561,98,82,291,824,685,359,893,737,457,504,809,385,374,26,294,417,587,392,323,847,348,565,166,230,792,911,853,362,914,285,628,702,964,286,655,51,530,847,823,827,290,168,171,594,334,725,864,66,974,715,213,830,357,995,395,56,658,886,225,117,210,783,59,861,846,189,467,297,458,247,184,82,841,417,967,113,580,656,282,527,699,142,179,495,334,277,360,842,980,371,739,172,851,418,272,888,172,325,139,588,413,428,951,446,589,636,150,10,792,502,884,647,626,553,642,945,773,829,900,159,610,980,161,165,348,602,178,38,665,433,5,856,804,895,581,813,185,15,566,18,201,822,277,855,927,656,815,961,613,883,814,304,802,587,398,871,207,252,504,507,783,624,736,404,715,866,217,994,635,368,499,611,881,911,768,489,454,133,405,645,190,824,385,202,716,560,612,440,601,363,96,791,910,560,368,189,698,166,45,759,885,358,73,81,120,457,622,829,937,820,344,252,138,603,873,907,791,919,244,547,272,294,417,445,733,72,638,508,775,610,236,447,411,674,473,869,14,171,187,791,908,41,493,235,524,832,601,139,888,648,952,744,404,771,598,573,827,169,437,756,443,171,86,514,322,493,502,450,111,216,259,135,871,575,76,241,819,657,780,437,739,206,212,931,792,430,950,514,538,226,475,867,988,519,913,83,579,469,984,865,189,628,988,344,994,494,692,616,949,918,651,220,718,621,439,614,383,598,43,539,624,864,50,426,344,331,569,82,964,782,848,956,801,661,573,652,251,543,105,593,662,186,207,306,994,44,455,530,636,273,613,115,933,126,378,985,691,353,507,693,678,975,720,952,525,900,402,90,400,906,93,372,992,362,233,480,777,950,763,409,830,717,189,521,918,167,253,754,439,101,285,25,795,751,860,830,890,178,217,89,647,329,388,258,8,472,685,865,122,563,406,116,102,266,444,286,516,638,909,105,243,31,442,766,672,250,140,225,729,929,483,498,617,262,937,45,364,147,222,501,351,270,582,102,371,633,920,728,796,428,393,239,100,993,871,215,161,874,945,948,500,66,267,974,833,138,965,756,925,318,308,939,312,33,80,598,880,613,792,453,580,923,68,433,673,965,105,446,319,207,927,43,635,908,573,26,172,474,803,50,457,779,870,5,384,951,595,375,702,332,775,98,808,975,161,316,426,846,525,323,195,62,924,517,317,135,783,404,163,93,149,401,33,837,943,380,263,454,929,280,727,23,341,750,723,648,140,899,344,665,434,892,0,930,345,614,26,239,200,519,874,713,564,423,237,786,418,148,128,795,282,64,301,908,420,334,989,964,31,606,119,614,345,458,582,82,499,227,638,866,44,251,980,125,666,983,507,192,247,467,651,206,462,349,66,636,734,3,107,17,996,64,466,410,801,878,987,986,733,18,728,897,350,890,949,224,561,950,690,891,48,77,316,595,995,256,952,205,983,657,389,882,170,276,740,210,843,865,420,12,534,88,508,984,65,29,452,612,213,382,686,535,170,915,287,34,966,584,714,987,965,51,725,116,902,825,971,953,213,44,224,632,84,178,385,600,518,889,743,694,958,397,593,310,66,6,895,985,749,876,562,791,194,100,325,714,534,215,957,601,987,938,611,229,533,916,304,225,26,216,686,144,462,680,662,535,452,938,350,368,805,58,485,516,519,361,711,521,467,990,453,489,273,522,85,976,642,481,347,940,184,99,513,513,752,626,22,267,282,524,788,529,279,899,103,901,126,842,77,224,19,930,604,239,381,984,29,300,505,772,511,638,565,628,846,931,653,268,30,176,388,423,823,886,919,888,874,838,291,724,494,789,114,517,865,999,227,695,204,452,803,170,137,133,820,310,58,349,671,964,452,926,715,281,743,663,752,825,54,817,735,782,790,801,650,621,399,267,781,786,693,832,937,665,212,606,775,367,15,89,819,729,439,614,775,838,500,480,700,76,337,36,364,184,625,846,23,939,40,563,109,991,86,662,710,805,904,557,372,930,324,255,682,997,796,750,514,117,335,31,698,789,397,210,98,942,577,982,245,961", + "710,728,849,344,206,395,20,461,548,795,895,921,622,11,59,419,237,639,239,860,822,141,427,617,718,958,675,568,109,963,717,501,756,633,915,531,289,398,970,576,204,24,262,503,897,299,42,62,518,842,897,860,719,13,274,906,602,70,291,984,351,921,391,387,411,896,251,852,937,608,564,153,98,226,664,161,625,277,660,93,229,985,250,387,21,829,149,59,783,449,926,100,836,419,229,932,559,463,922,480,280,332,75,138,480,847,318,77,218,806,475,658,10,174,283,959,61,520,302,73,998,936,540,713,499,913,690,103,377,570,592,323,860,919,866,431,817,924,954,783,345,664,518,122,581,59,186,536,8,146,393,171,744,24,674,472,9,498,153,279,237,212,748,168,213,318,166,91,582,377,817,586,603,838,360,675,546,750,937,836,805,220,957,738,205,693,921,548,60,576,619,768,508,474,246,707,815,85,831,106,978,589,555,792,841,75,369,809,479,739,386,973,475,113,843,569,283,407,132,863,319,52,187,349,214,29,417,833,761,565,286,671,133,380,651,187,992,311,577,391,690,186,378,892,720,463,102,805,310,861,612,891,110,609,330,600,762,210,953,94,735,607,849,202,88,825,761,175,334,328,319,557,162,119,259,255,218,617,583,870,244,588,270,98,89,696,320,740,141,970,842,854,942,547,796,745,381,43,978,955,998,318,505,998,735,825,855,342,584,345,874,790,461,120,731,299,662,695,157,474,724,378,602,917,634,389,417,803,584,322,374,864,888,648,109,756,969,707,461,321,746,402,484,702,720,551,122,890,540,436,995,546,436,517,311,428,570,711,421,364,191,660,95,424,434,190,141,315,620,331,352,256,997,901,485,496,639,167,418,845,613,634,216,780,54,212,566,448,249,845,163,316,638,425,596,183,114,297,375,736,707,491,510,357,569,863,507,521,725,959,942,573,291,343,713,934,756,429,398,86,394,130,698,774,700,126,887,470,716,925,151,168,477,49,821,462,363,921,829,205,845,34,285,879,276,220,169,624,929,168,207,295,101,660,639,994,746,300,736,934,194,267,708,395,205,250,252,591,455,137,87,691,675,14,467,242,529,176,627,118,371,31,94,294,208,429,271,451,479,173,351,20,393,646,743,792,655,543,327,559,825,643,563,813,281,207,982,742,922,923,309,785,494,437,155,797,97,180,831,461,13,690,803,140,171,174,581,845,538,458,750,215,623,405,911,10,531,673,698,258,936,49,9,621,16,524,20,982,79,540,964,638,934,840,194,36,952,853,187,303,119,921,220,926,518,925,550,277,819,323,735,132,644,953,1,923,998,165,889,816,274,352,89,919,660,621,681,920,414,851,278,666,851,195,289,332,173,464,153,560,483,119,326,973,571,310,35,504,365,307,457,753,271,436,276,701,733,287,407,321,907,319,57,367,242,737,649,388,55,524,524,10,158,388,776,286,639,813,785,92,828,296,959,767,698,119,232,970,174,467,5,537,930,0,867,565,127,291,638,1000,120,31,169,49,355,894,361,256,572,618,304,209,117,677,589,485,986,984,340,902,676,664,841,482,810,203,281,658,847,627,69,929,259,577,314,465,132,922,691,564,367,973,422,521,599,985,610,495,52,592,47,947,510,641,432,387,758,4,198,387,326,467,392,40,762,41,680,739,77,179,672,165,315,307,141,701,924,660,203,442,994,591,899,221,371,453,589,334,438,482,283,975,163,636,660,146,609,278,291,462,187,809,370,571,804,439,551,649,624,465,386,388,921,392,386,871,721,488,391,846,674,393,480,24,378,275,442,416,329,523,71,224,370,635,36,658,980,876,905,334,387,617,988,172,532,637,280,595,868,66,254,72,582,949,729,67,284,392,32,856,583,293,349,94,58,178,458,389,570,326,995,601,413,348,995,436,344,599,214,932,477,276,995,329,763,701,914,232,761,768,228,415,336,971,88,486,738,297,352,871,600,877,569,886,233,625,444,988,979,490,454,578,796,564,630,566,879,76,10,485,495,327,628,288,64,53,139,172,500,341,450,433,789,298,180,144,30,463,852,57,993,780,763,169,872,865,528,888,304,468,565,174,519,62,767,446,223,590,201,567,615,405,496,310,424,5,433,105,593,11,677,16,619,192,5,606,172,661,963,592,383,411,354,136,233,282,301,266,183,449,505,540,850,110,233,569,443,371,472,337,231,26,655,733,721,22,605,960,127,823,980,715,757,283,678,699,254,105,474,844,901,886,73,822,700,474,338,550,489,864,935,289,576,888,724,635,291,452,784,803", + "485,14,592,955,490,717,186,461,725,687,704,982,532,138,11,962,712,777,111,253,12,327,101,834,51,617,491,497,2,484,734,376,737,71,536,46,450,43,715,351,564,19,963,283,910,142,565,242,228,563,352,596,261,321,509,15,696,788,888,535,283,903,717,328,794,894,953,158,743,644,145,516,365,243,791,332,631,496,59,879,781,863,476,232,173,445,55,640,250,825,732,384,86,371,498,755,938,767,232,244,235,453,202,296,854,933,513,1,106,331,309,294,362,119,315,909,639,214,211,561,637,590,351,620,260,556,948,442,727,783,257,885,260,962,69,144,564,823,372,832,73,589,541,974,458,698,512,143,860,932,69,16,477,259,797,860,486,188,97,248,923,234,680,886,60,540,145,868,58,900,336,894,327,684,509,222,691,98,460,878,409,579,834,262,819,471,733,255,581,740,699,3,836,356,542,966,592,368,354,959,201,602,406,162,301,906,237,684,424,602,923,650,780,517,680,227,739,383,626,764,650,176,768,432,792,393,811,436,890,842,525,756,994,234,923,145,596,288,701,265,36,329,213,45,173,483,512,222,760,454,953,829,379,304,178,268,409,967,873,847,87,677,128,96,322,840,96,938,526,519,149,331,587,815,742,257,629,13,465,457,592,656,683,349,314,906,403,411,352,748,28,381,175,727,218,347,245,990,434,715,876,969,352,85,75,150,299,284,472,832,732,486,45,840,868,130,889,271,599,501,546,531,251,326,555,222,850,256,451,935,901,855,73,158,637,38,768,282,659,895,633,729,451,643,384,771,130,409,592,820,62,806,936,222,836,998,911,915,171,749,495,598,899,198,619,384,103,21,905,820,996,857,274,188,372,204,968,704,417,123,35,460,368,880,91,957,73,7,954,151,965,913,990,433,13,292,527,974,892,422,618,799,974,53,459,473,28,542,174,279,414,512,733,646,557,979,708,98,187,866,527,751,331,224,984,655,396,517,332,849,529,823,855,824,919,915,565,950,142,298,322,952,411,313,748,888,657,2,141,987,514,116,841,619,635,872,958,491,928,975,721,961,827,698,603,629,24,120,829,215,987,877,538,713,423,928,911,89,98,997,462,959,748,204,937,780,344,779,370,60,385,487,16,995,119,924,783,7,550,177,498,796,214,732,885,217,331,684,33,732,73,342,837,362,344,838,978,967,34,168,913,477,330,263,548,414,876,613,145,583,897,971,133,99,604,836,962,832,438,441,807,374,603,143,706,925,796,307,365,807,191,119,607,544,823,857,832,599,159,627,905,781,851,739,751,526,529,236,909,253,846,419,72,961,496,165,544,125,937,607,330,637,385,493,294,5,148,89,69,776,430,818,748,882,713,526,967,91,919,663,397,327,83,334,177,901,121,875,937,860,206,471,461,669,191,707,732,266,84,51,284,173,39,477,262,974,356,70,88,644,14,599,613,745,94,101,495,470,432,346,899,928,915,292,486,187,42,424,360,912,671,726,345,867,0,187,296,543,234,28,966,375,893,802,996,531,908,303,79,491,466,309,575,550,386,979,857,379,240,448,726,858,702,718,220,746,400,603,138,203,65,388,52,567,377,342,715,970,687,129,50,783,438,243,869,959,17,65,773,602,953,616,166,585,324,842,830,530,81,572,161,640,495,985,616,969,846,212,372,971,433,140,55,885,943,753,193,410,11,380,93,335,868,644,17,90,639,236,884,474,75,516,746,1,828,75,501,721,534,298,315,385,699,162,852,61,855,317,411,158,892,963,608,526,514,991,621,455,837,506,11,790,754,554,590,401,631,620,656,716,179,207,17,287,612,279,16,568,595,496,589,951,312,148,585,655,995,168,183,204,436,361,532,181,244,957,167,280,175,750,139,444,672,659,352,690,349,347,558,7,332,699,848,628,39,275,99,215,222,340,571,384,881,950,903,696,789,839,351,616,930,769,751,63,507,995,552,363,482,81,637,602,625,108,180,26,623,622,442,863,786,792,269,568,109,385,801,353,621,613,692,881,516,883,940,548,560,256,36,436,321,350,783,331,257,387,39,301,272,860,541,957,599,900,649,52,197,563,765,148,902,8,267,106,187,896,692,213,164,679,654,427,685,801,42,371,596,333,71,65,69,915,417,628,782,886,447,226,326,510,101,903,343,368,412,72,205,817,549,982,657,92,719,545,27,438,627,826,783,918,406,880,322,240,522,220,179,682,145,344,832,553,96,147,118,273,693,33,156,965,174,326,700,897,474,183,919,200,14,570,319,660,938,728,214,235,136,789,111,451", + "709,905,462,789,866,79,967,776,454,931,728,251,50,258,977,152,333,451,149,96,450,226,113,475,735,289,480,407,292,288,701,70,513,983,989,668,496,281,669,863,794,745,173,494,804,711,503,784,416,748,972,385,365,693,564,869,355,193,680,648,531,531,893,28,951,221,321,628,767,31,170,516,195,771,822,629,651,832,879,571,453,580,749,598,490,492,246,151,836,154,140,830,482,439,890,164,286,219,919,932,757,339,315,529,608,299,791,597,556,742,660,648,396,935,478,712,432,220,152,263,704,857,578,38,406,168,870,547,628,119,739,621,960,309,756,947,382,892,228,863,471,107,800,107,791,94,687,438,21,560,475,613,542,412,495,886,495,578,339,436,216,513,51,571,130,521,790,948,63,660,75,386,737,527,408,571,128,35,670,287,54,38,49,621,419,47,125,464,163,660,728,743,434,752,245,705,754,241,675,213,227,813,677,734,712,334,208,892,796,486,903,653,717,601,968,710,679,866,962,900,304,296,188,990,141,723,53,503,36,146,453,955,684,758,957,868,685,714,697,959,498,525,777,850,859,971,738,346,487,424,222,221,99,876,359,818,505,691,450,380,68,127,413,350,974,813,415,922,9,629,643,223,872,755,386,585,901,729,304,76,434,324,879,265,645,566,316,759,656,794,964,376,845,307,16,199,312,184,287,788,891,220,118,998,94,652,476,988,641,482,90,871,740,747,50,919,93,669,776,806,428,163,422,773,945,59,97,521,206,81,986,209,458,481,870,418,459,716,438,107,675,465,662,189,244,286,339,455,374,615,563,848,480,214,343,704,429,672,739,553,297,120,727,24,994,950,658,416,824,822,637,186,793,938,700,27,164,260,474,34,604,790,492,982,957,420,967,578,249,241,486,654,629,74,721,599,410,848,584,376,297,487,626,261,88,790,915,11,563,222,76,448,895,252,312,539,139,406,235,626,933,239,206,309,167,947,786,330,696,288,619,585,113,457,508,606,84,314,531,136,74,166,697,873,78,458,636,55,370,874,467,663,524,230,15,376,153,726,88,431,447,5,914,294,996,203,799,23,945,242,823,192,783,483,26,438,495,940,885,361,475,642,726,484,584,254,668,925,76,243,136,44,920,914,139,321,723,107,186,868,927,745,532,919,947,54,434,230,907,825,945,33,898,936,773,542,317,574,363,765,103,679,305,158,811,707,506,582,456,10,222,673,529,219,374,932,618,902,617,427,504,459,190,643,159,297,244,916,924,536,565,974,108,704,570,888,551,429,169,929,277,669,45,302,687,651,69,59,997,958,539,793,780,349,693,156,343,518,302,711,289,764,792,462,40,491,384,228,390,646,328,925,928,800,938,84,472,604,991,129,253,195,100,759,298,781,292,214,477,381,232,171,14,890,638,685,981,826,806,310,113,653,512,93,302,733,135,401,523,312,223,412,370,605,473,243,948,325,596,900,952,829,433,11,582,710,748,444,120,705,212,931,614,565,187,0,610,232,780,345,912,364,925,300,393,335,587,786,689,689,182,600,133,162,617,362,66,147,296,152,288,4,807,354,55,312,295,326,683,69,252,827,146,892,511,152,809,528,858,465,128,865,407,180,923,118,593,50,963,897,794,836,610,597,318,688,719,316,832,931,374,674,451,300,958,512,531,673,204,542,512,26,997,602,365,362,939,431,791,969,955,50,561,929,35,681,613,937,381,348,156,941,390,21,745,207,366,25,121,612,730,835,990,599,402,637,221,586,135,532,204,629,520,941,4,866,170,19,603,629,613,902,867,576,793,684,981,712,76,888,399,891,386,486,746,815,708,71,721,198,588,480,818,656,298,32,25,149,229,361,263,770,556,512,292,757,793,520,323,308,323,785,611,91,879,428,2,803,313,163,902,948,680,31,749,426,314,598,543,600,757,279,754,112,637,31,854,504,420,752,820,400,99,133,123,493,491,937,449,879,306,275,895,845,271,542,426,190,275,801,291,932,805,459,91,826,920,296,263,391,648,122,584,592,67,471,882,745,267,551,213,953,392,129,337,674,80,590,513,866,224,109,288,525,986,296,638,643,302,131,81,298,169,626,95,613,76,185,57,226,702,208,691,905,1000,175,338,336,450,611,260,120,987,680,461,785,367,156,664,484,937,33,816,507,151,52,131,372,685,555,640,57,19,348,990,855,182,747,666,66,13,324,974,737,371,863,885,281,696,245,676,91,766,330,466,62,212,606,6,789,417,77,455,670,192,347,771,228,477,747,939,975,812,387,543,240,433,156,649,387", + "341,147,850,221,432,839,710,643,985,179,335,547,64,135,227,866,39,497,537,744,485,517,507,710,168,912,809,387,431,4,893,787,8,657,868,810,556,819,928,234,755,409,312,768,90,209,400,939,781,353,259,430,336,876,687,413,322,723,761,84,752,809,870,972,149,151,78,284,629,70,62,63,556,966,130,372,655,851,42,110,140,912,177,145,267,735,761,981,734,943,572,675,18,47,470,994,990,889,677,464,886,148,379,691,47,914,973,453,357,809,964,95,147,764,820,308,299,263,986,180,462,981,810,856,589,348,361,47,952,546,781,642,182,825,553,476,288,779,395,658,514,358,52,405,912,506,290,761,670,629,949,983,686,224,172,770,859,60,372,85,975,390,343,110,952,4,233,265,634,811,964,327,974,210,144,201,887,442,838,945,301,128,993,109,365,549,360,665,494,126,559,341,334,781,801,330,699,705,768,23,557,566,483,139,495,954,445,688,71,834,653,986,251,769,16,921,442,411,995,213,556,207,337,836,636,689,701,504,265,970,556,251,157,543,154,721,451,604,155,830,724,474,514,225,351,72,301,902,43,284,903,465,439,358,133,44,74,231,553,733,86,298,621,514,121,516,301,789,171,250,921,934,406,809,438,105,290,988,132,380,954,24,436,219,589,148,744,635,297,572,714,171,771,610,405,470,501,814,704,312,685,789,775,260,401,500,790,123,618,399,208,336,955,615,59,996,739,406,788,190,553,491,574,189,718,344,487,56,571,945,970,486,328,41,714,780,647,194,67,680,245,560,282,930,195,629,286,154,706,562,29,658,659,130,933,989,232,708,628,426,555,674,272,913,359,785,85,982,216,27,518,289,992,883,502,111,16,221,822,657,35,674,838,448,702,136,28,876,235,490,895,184,520,413,675,932,239,123,718,602,854,900,548,848,60,111,395,831,253,275,814,810,318,671,975,383,513,102,564,176,237,973,978,680,512,163,506,347,680,476,393,589,952,15,111,62,639,648,18,457,820,488,502,444,89,257,480,950,515,190,84,407,922,956,630,625,557,481,490,338,695,657,56,169,481,787,501,406,434,154,462,903,585,951,449,894,905,646,81,738,61,313,913,43,470,872,98,514,988,913,513,502,265,490,615,859,999,817,172,72,785,898,386,45,819,381,584,434,843,193,705,56,649,124,34,504,181,575,624,800,104,70,808,362,65,692,964,890,996,395,671,821,642,936,119,987,139,498,183,857,25,958,928,704,672,600,885,555,64,646,919,106,225,46,193,276,841,2,123,602,967,51,981,102,468,860,724,504,347,761,836,789,7,549,334,248,272,361,68,187,834,294,744,658,647,476,204,802,803,653,515,4,15,303,910,5,296,860,502,125,75,362,741,398,907,490,601,996,538,583,468,946,392,567,952,755,303,581,209,724,70,498,957,448,498,935,721,97,32,651,601,475,945,811,675,428,826,130,146,471,406,859,413,204,845,45,995,595,725,662,159,916,26,127,296,610,0,952,664,183,460,876,619,429,700,445,510,28,175,317,269,251,981,502,933,699,985,589,254,343,974,836,939,637,612,822,722,745,278,819,49,216,379,809,422,436,722,989,357,758,506,701,610,256,361,148,601,121,443,709,296,834,63,408,979,869,378,612,352,194,321,872,672,580,58,86,136,573,309,846,228,134,574,905,381,750,953,791,864,170,250,863,787,505,434,721,689,158,283,963,409,238,528,471,840,887,436,531,937,116,622,572,612,614,323,995,469,706,424,753,64,266,530,128,82,411,468,530,176,433,583,277,902,720,73,652,674,592,205,507,580,670,965,391,5,33,969,394,764,614,400,975,897,685,497,629,157,34,538,835,310,339,715,229,735,578,154,709,601,345,335,915,344,29,636,823,648,533,526,678,540,12,346,918,223,688,268,399,853,902,881,530,109,800,662,382,140,819,223,445,454,784,965,139,137,130,597,207,735,140,613,216,251,852,852,464,283,895,955,346,186,425,469,456,850,168,646,297,282,184,27,981,99,774,501,525,226,10,13,432,807,796,173,537,223,900,583,769,244,443,537,359,82,699,450,224,582,718,230,914,840,592,883,982,241,344,509,548,314,901,507,463,688,757,61,402,25,533,977,682,446,305,220,759,457,171,413,705,166,454,7,5,299,595,862,330,479,773,307,641,327,442,381,264,25,821,67,634,887,480,330,873,672,899,71,400,464,344,621,5,962,767,847,405,776,443,114,523,998,259,542,8,891,284,894,174,810,536,722,583,19,547,486,279,787,237,42,231,616,162", + "871,88,840,131,511,274,264,762,321,767,867,555,974,354,879,508,86,329,554,875,872,806,598,291,712,775,942,95,754,295,740,383,331,685,506,866,567,756,721,616,650,625,422,742,764,33,516,893,643,631,938,454,199,899,76,233,142,441,726,50,578,636,217,67,280,494,696,897,77,697,627,958,303,786,280,211,137,968,283,168,985,29,239,335,754,619,543,177,178,901,487,448,131,804,27,464,617,619,157,372,975,686,397,900,396,421,683,927,760,973,63,696,994,489,989,153,320,233,3,912,425,999,896,809,522,39,220,543,507,547,226,513,850,821,85,777,101,977,746,184,384,402,590,711,73,446,700,633,503,379,288,92,492,825,239,517,980,3,314,252,351,783,418,340,489,271,287,787,957,717,689,704,5,956,611,61,965,550,630,175,959,839,74,697,363,524,514,594,45,926,448,227,729,320,887,275,119,349,857,827,209,104,303,970,769,71,872,801,219,981,186,722,520,933,821,977,642,739,696,190,863,392,484,24,768,965,978,130,985,428,877,457,871,335,419,686,393,908,278,37,691,264,332,685,702,464,400,993,55,483,649,443,788,150,441,981,976,849,2,713,596,530,494,591,432,197,744,269,502,315,612,948,405,297,133,427,464,832,332,651,623,971,180,44,413,532,180,136,869,964,519,822,195,866,548,599,129,756,856,630,982,243,531,688,37,698,975,774,991,191,32,498,963,220,910,462,151,749,779,353,946,733,585,735,909,769,720,125,967,578,229,192,253,771,870,273,883,104,671,619,48,680,705,847,194,379,339,158,21,619,594,684,945,156,491,662,255,684,494,285,388,99,465,796,669,413,495,432,215,878,532,147,318,405,900,901,771,944,493,404,154,149,6,91,813,660,940,59,57,927,405,127,747,576,282,753,841,949,993,703,965,286,153,459,178,816,141,334,105,448,309,478,459,719,839,678,824,128,779,170,279,923,461,457,486,184,957,841,947,602,655,136,537,174,134,813,740,943,606,145,925,512,365,909,946,15,284,347,8,97,682,735,236,146,242,828,716,258,171,270,622,340,611,375,815,473,387,222,791,532,850,540,148,402,504,990,913,514,806,646,787,381,632,258,880,444,673,345,730,461,767,934,55,526,616,611,249,32,552,887,206,688,261,764,335,71,774,767,270,528,845,448,120,428,894,486,44,669,504,993,718,160,265,633,952,812,408,768,567,551,574,867,96,974,379,405,841,448,4,372,291,747,797,62,127,553,710,532,557,779,555,89,562,415,139,689,323,291,946,774,350,317,313,834,187,664,164,129,67,807,466,804,508,449,130,562,410,518,341,381,608,479,655,650,739,75,203,29,720,406,527,512,496,964,812,111,36,661,438,611,735,247,669,399,803,514,395,8,963,313,28,690,463,963,800,595,518,499,93,86,446,537,502,172,623,143,356,91,987,376,377,657,905,916,550,727,320,377,218,373,286,185,759,744,713,35,874,107,837,638,489,80,239,291,543,232,952,0,631,259,884,468,839,17,673,569,321,610,969,12,539,476,233,62,857,541,412,683,69,451,18,630,838,128,57,768,712,672,474,352,253,222,341,540,64,290,932,557,134,216,674,105,404,86,754,172,693,86,689,714,721,152,792,335,833,617,407,540,767,913,263,450,747,788,936,881,247,814,873,881,227,895,818,457,270,666,617,56,746,817,753,461,114,343,941,473,428,156,356,16,119,504,822,659,647,130,665,295,648,139,296,210,262,498,271,362,229,143,578,818,906,527,944,765,172,382,724,652,904,136,552,513,268,439,342,768,928,755,933,105,289,190,70,948,178,476,418,882,963,70,944,388,870,394,498,763,666,410,119,326,358,330,436,277,63,75,532,517,670,671,607,505,469,534,843,847,321,629,328,507,670,425,603,80,877,258,779,167,781,435,129,164,267,780,772,477,461,77,447,765,887,49,640,975,918,573,476,826,493,691,689,669,22,620,293,407,990,3,912,927,720,367,511,517,718,643,786,901,700,773,63,787,676,28,111,758,762,835,135,65,2,356,590,95,876,571,358,490,201,224,266,572,459,855,419,32,313,100,790,995,299,277,850,699,401,510,136,911,3,104,977,369,215,728,658,372,788,373,276,451,256,785,381,87,254,564,256,292,151,57,69,144,984,538,741,745,191,156,572,919,966,743,704,961,14,838,869,912,537,296,39,632,300,999,608,937,649,770,403,18,220,87,693,948,704,921,448,856,120,654,636,876,734,837,888,590,496,62,592,30,442,404,743,78,279,71,701,907,798,513", + "669,291,359,555,231,903,802,383,248,518,393,617,735,388,797,937,205,780,191,816,100,584,421,364,903,550,228,954,994,477,834,675,137,973,323,234,973,992,563,952,548,326,521,876,962,826,517,687,844,772,311,143,72,678,288,219,539,434,723,703,332,441,616,469,113,998,617,88,737,672,452,885,20,116,792,892,231,620,628,738,108,32,623,495,694,684,19,469,939,18,679,488,555,336,631,464,599,981,976,67,825,544,703,20,115,452,121,303,667,767,337,539,287,8,135,954,891,72,987,320,56,377,214,837,658,282,400,472,3,758,508,520,376,114,198,476,427,841,411,87,439,28,8,977,202,986,726,697,94,163,375,410,529,853,580,832,710,919,538,847,141,923,143,925,141,243,591,645,831,567,296,846,901,534,772,852,9,325,296,628,188,405,68,563,135,599,29,467,817,981,926,454,389,935,248,829,239,682,707,369,607,155,328,529,744,501,81,572,21,31,967,703,462,201,452,709,172,427,231,404,258,883,362,394,570,434,289,730,308,110,868,832,568,398,803,555,770,266,376,305,917,49,459,793,191,583,156,837,971,327,221,490,749,174,463,134,324,104,969,99,486,916,919,301,342,411,684,378,784,776,123,524,411,632,874,545,59,195,262,129,204,336,707,742,261,50,221,905,750,251,222,848,495,527,636,275,202,353,27,976,874,194,491,496,808,94,506,813,931,883,175,492,4,4,320,460,340,32,903,266,298,139,962,157,349,490,939,379,117,335,168,307,560,421,788,877,318,233,339,914,132,686,855,187,872,797,190,896,946,625,236,1000,448,664,382,144,385,935,408,617,316,977,605,284,895,463,584,126,39,610,660,764,668,125,781,164,244,63,248,58,738,13,191,994,447,556,124,760,68,474,999,552,405,259,837,755,117,159,981,809,51,164,825,800,352,486,66,437,779,581,458,949,298,315,48,891,606,943,747,979,392,592,266,652,442,308,811,21,935,201,403,523,398,548,688,479,196,16,61,848,835,293,411,309,431,962,815,84,122,210,716,590,618,103,470,981,68,566,860,511,708,460,765,475,99,178,127,156,125,13,791,149,968,27,930,755,479,289,396,81,943,135,586,696,969,86,194,58,217,851,97,873,350,775,388,114,150,727,935,11,241,178,816,17,105,702,526,891,770,886,464,967,776,111,819,325,13,380,374,148,193,170,890,347,234,103,779,579,226,600,726,727,7,349,215,336,310,610,876,465,455,520,614,41,257,154,245,634,477,357,735,136,439,306,535,819,8,947,509,238,796,879,420,251,844,517,252,556,666,734,964,953,554,582,572,670,139,824,844,365,832,400,790,169,625,561,200,393,197,334,35,517,233,886,693,618,151,62,656,959,147,881,561,396,385,959,7,794,895,557,495,311,807,122,659,924,859,989,748,255,129,911,246,686,554,192,574,296,385,990,532,947,523,269,156,937,959,462,732,241,362,237,228,186,448,507,468,646,451,355,630,609,200,638,234,780,664,631,0,391,830,954,299,134,662,964,949,877,664,415,86,704,39,320,142,403,385,58,865,507,45,221,546,392,900,505,424,96,693,934,19,630,726,324,314,73,959,728,987,386,975,874,839,841,761,168,149,60,510,705,787,600,584,770,262,742,675,251,306,220,559,553,835,993,868,487,306,273,833,416,341,734,264,724,341,779,522,952,442,430,66,257,123,687,586,876,916,659,952,970,76,203,109,275,223,804,124,52,692,401,733,66,462,615,616,637,276,234,512,967,195,259,272,966,750,927,607,466,365,619,783,226,403,973,378,771,586,34,861,252,515,286,397,634,991,774,573,509,161,53,640,738,166,663,161,673,145,384,182,384,216,602,279,633,747,354,814,230,818,658,146,505,157,447,831,998,51,455,128,790,795,753,871,553,792,334,299,487,706,14,808,309,367,238,707,845,838,482,196,59,222,816,25,738,779,628,207,540,451,291,731,253,237,445,743,696,207,188,848,269,321,70,255,508,817,940,647,183,454,920,21,470,17,269,596,259,428,462,12,592,269,142,341,632,781,338,870,930,835,19,614,677,200,239,780,462,658,155,604,832,131,821,750,934,850,683,391,91,31,197,918,22,343,788,63,569,5,854,181,800,571,769,932,889,45,595,499,432,151,360,40,194,878,218,584,586,40,640,651,257,586,346,377,959,19,337,12,238,800,448,600,532,248,589,186,49,513,553,174,432,158,69,904,491,654,106,366,497,712,781,435,998,901,43,765,23,416,404,129,754,624,718,590,563,486,373,963,701,214,421", + "27,192,296,217,445,630,265,575,40,997,99,146,311,167,9,226,616,515,952,12,147,825,486,632,668,526,322,625,885,330,906,874,866,116,875,190,540,353,6,925,580,335,477,21,724,788,283,968,447,273,305,577,308,754,371,865,460,262,960,528,527,726,583,970,555,482,770,224,380,332,82,541,911,926,519,71,743,893,430,888,500,219,627,805,57,435,307,81,582,745,398,956,557,88,278,908,522,3,450,819,137,969,375,934,569,616,281,135,290,164,896,762,531,730,701,218,729,655,885,651,441,365,567,643,407,647,62,423,404,844,460,624,283,7,156,814,548,536,47,821,599,406,186,653,788,787,348,16,147,779,285,607,188,971,674,307,384,189,132,328,486,279,456,145,652,17,892,742,59,884,853,897,855,339,435,866,476,341,645,649,657,256,327,48,487,351,32,341,571,63,367,464,383,68,471,738,47,649,43,19,699,262,967,522,459,48,684,2,692,111,498,310,708,544,750,778,899,926,84,765,929,91,425,595,472,645,71,181,392,562,876,123,537,220,432,767,3,470,824,27,139,44,353,926,47,733,291,61,796,854,288,968,998,234,971,440,130,967,959,945,287,151,349,419,365,532,675,85,210,241,308,888,24,278,442,557,720,385,649,573,488,781,781,927,764,201,63,225,361,833,355,633,505,773,318,118,16,672,822,124,104,935,912,312,892,849,894,458,273,487,55,714,755,762,944,24,542,855,477,398,929,275,968,310,436,330,75,370,291,50,443,277,912,652,916,603,906,900,158,655,103,237,540,44,569,116,307,838,146,162,878,755,869,594,504,148,407,364,368,974,264,807,311,901,255,83,791,341,284,147,575,279,383,710,976,181,709,84,800,431,229,392,482,737,208,36,935,751,610,483,78,543,628,192,463,227,155,209,457,422,285,438,395,224,178,988,302,12,309,545,721,137,705,920,740,275,975,153,689,741,822,568,435,74,289,25,207,846,996,61,384,408,992,447,986,867,332,382,726,592,38,85,55,489,509,109,455,239,85,407,438,566,218,879,532,660,683,9,678,986,786,887,540,25,966,796,122,481,14,663,39,437,12,56,913,328,982,28,466,232,165,51,221,693,227,136,899,772,704,484,171,191,859,819,121,640,150,153,683,263,22,245,20,4,676,390,430,293,184,65,805,922,220,615,204,555,164,28,772,57,886,718,56,224,388,259,271,885,817,710,967,942,726,272,424,539,270,2,956,349,11,854,381,919,474,931,809,344,988,538,990,101,809,846,142,34,596,854,871,232,248,440,445,393,19,629,244,392,903,759,361,381,534,483,489,772,402,204,792,455,141,368,172,495,328,480,801,494,393,189,108,571,298,267,291,412,443,153,75,258,960,866,788,513,145,529,726,925,568,731,622,876,130,756,157,842,372,270,825,334,679,709,608,852,837,102,688,376,733,359,244,176,751,538,614,252,983,451,910,473,677,452,282,579,318,359,866,905,782,431,581,332,519,1000,28,345,183,259,391,0,948,769,346,313,839,140,325,356,795,65,355,381,924,497,532,811,962,556,494,526,401,813,765,489,523,412,901,78,515,815,794,139,263,683,465,84,646,869,532,356,932,722,2,388,445,916,615,440,437,816,519,470,220,152,987,250,836,652,469,827,762,321,876,717,51,709,625,621,458,152,425,797,908,42,698,336,638,600,829,933,300,308,998,301,833,340,508,691,162,916,791,681,468,402,855,986,850,267,977,290,517,28,670,629,593,183,198,931,663,710,808,500,944,367,265,367,250,395,732,668,670,479,420,633,472,620,825,384,87,143,373,977,901,178,792,1,641,950,980,191,651,887,702,950,788,384,825,656,638,927,363,40,710,74,736,300,799,196,284,763,945,92,909,50,492,223,357,254,827,864,39,614,308,288,637,996,195,948,627,55,235,162,346,709,431,888,198,720,859,323,688,109,271,349,419,20,391,508,33,948,810,181,66,493,894,816,178,21,303,9,878,306,318,343,927,41,114,766,629,89,790,91,439,644,324,219,844,927,798,311,976,903,117,93,274,544,570,419,564,408,825,413,142,936,32,912,440,140,666,518,745,707,147,330,887,109,457,248,895,876,762,821,521,268,282,435,36,501,636,200,104,336,256,8,733,968,475,521,862,411,803,496,783,143,409,505,915,611,172,317,777,683,933,248,336,453,688,21,835,556,626,906,153,679,418,460,444,911,800,373,762,861,128,150,676,211,2,964,387,426,392,704,960,514,858,645,400,690,236,617,248,771,254,869,764,745,72,63,324,687", + "5,669,830,275,841,282,317,503,661,477,942,817,448,186,567,226,689,313,248,249,414,624,917,56,910,187,67,620,65,160,48,131,979,802,484,602,545,263,107,91,532,779,888,284,31,798,564,782,709,376,73,374,312,149,584,385,273,842,632,639,513,640,759,242,507,655,393,400,767,293,870,790,648,211,788,137,405,886,850,811,23,148,857,862,460,33,427,308,618,367,233,690,226,929,223,497,400,601,266,17,273,647,806,269,933,694,321,238,71,680,826,970,914,917,943,555,702,480,65,327,461,814,362,660,475,496,658,492,461,547,849,860,517,71,575,194,579,159,784,476,808,393,510,254,851,466,959,705,527,707,945,316,457,189,60,541,720,347,623,752,227,894,9,654,284,231,985,795,523,844,503,266,135,428,235,358,403,445,826,215,655,810,429,12,799,326,886,878,566,324,691,15,775,725,420,29,33,560,937,559,311,24,680,356,452,172,692,105,851,366,630,216,549,61,821,390,509,42,463,2,381,833,512,191,361,468,695,379,54,417,944,788,947,414,215,808,108,328,991,497,734,370,609,834,495,364,100,633,131,589,187,669,509,686,89,449,735,675,419,945,48,448,320,359,86,332,812,177,349,514,64,697,848,98,486,664,442,587,293,621,874,673,905,605,47,665,509,716,119,293,323,593,638,61,328,259,475,132,952,163,524,675,751,495,227,238,903,787,312,15,324,172,863,818,925,541,641,491,93,817,916,91,487,786,120,768,232,914,417,560,440,526,590,323,585,666,960,737,685,775,513,567,417,66,955,891,680,70,597,854,306,730,148,7,177,730,43,83,149,357,775,828,858,409,621,426,316,863,281,104,618,532,507,983,667,869,843,610,629,712,443,52,633,153,283,552,745,864,31,13,411,469,590,381,748,481,581,528,778,87,718,128,637,570,703,849,404,849,11,698,817,313,920,285,148,785,309,952,376,198,239,83,834,128,572,423,938,672,469,968,686,624,363,907,109,375,41,140,484,226,470,471,795,50,419,93,523,219,777,464,306,202,894,752,44,861,568,73,324,756,310,830,815,29,650,609,526,488,570,710,123,759,680,552,920,30,528,370,249,975,768,775,570,659,22,979,341,191,957,320,717,886,441,326,674,478,46,826,929,146,231,46,888,764,513,263,179,606,927,228,738,308,998,110,567,489,475,663,213,455,958,70,131,5,672,908,128,176,320,738,515,803,4,701,244,90,777,554,347,678,616,720,323,916,223,237,564,387,695,630,695,906,325,560,987,87,877,390,206,849,533,89,316,285,806,615,288,798,13,59,297,961,177,894,805,631,693,700,127,751,541,813,196,351,488,706,322,409,302,122,913,72,807,112,524,4,653,674,929,230,808,452,326,587,389,831,731,283,283,782,86,299,1,984,57,315,622,628,571,534,801,860,164,99,880,925,557,191,423,1000,314,449,632,669,537,731,310,115,648,707,650,398,395,390,615,646,312,929,41,597,373,905,874,120,966,912,460,884,830,948,0,577,919,989,320,158,353,73,586,907,340,681,398,746,71,737,775,439,864,547,833,959,287,784,285,211,322,681,374,931,654,447,164,315,529,192,155,503,510,660,199,819,987,577,424,286,452,370,928,473,648,716,87,995,750,206,147,615,631,19,163,631,797,839,821,863,40,393,66,917,643,139,134,722,536,584,556,288,284,848,413,41,704,36,949,343,456,750,43,985,279,381,853,284,571,557,615,526,379,145,911,850,581,253,47,223,347,445,761,334,835,726,2,175,255,99,282,348,119,521,37,713,11,933,817,829,945,54,59,270,323,212,903,358,644,291,136,44,871,843,927,41,429,935,568,645,883,450,86,545,363,96,763,941,166,467,798,24,411,648,340,99,383,970,116,83,904,449,55,193,57,633,813,727,218,334,996,804,657,989,301,371,403,212,146,960,284,734,764,416,150,175,220,105,100,392,933,632,630,638,962,983,676,401,790,995,925,333,444,575,432,536,595,535,467,513,46,751,316,806,723,57,824,359,399,633,314,634,850,22,668,818,268,12,834,264,881,272,805,340,113,475,865,513,231,94,673,415,69,415,822,212,922,841,240,713,823,60,413,777,474,177,263,980,329,15,838,914,314,605,511,996,295,592,289,320,943,876,409,452,278,200,57,952,861,660,97,660,447,12,878,430,714,515,294,15,73,713,399,740,946,644,735,9,547,573,757,620,12,63,266,701,920,258,173,382,280,213,67,347,828,229,725,896,183,984,516,820,514,300,372,191,636,176,919,421,532,241,52,355", + "643,742,724,964,657,966,325,143,717,624,926,541,227,929,514,943,686,218,383,545,315,504,535,846,621,915,65,340,794,403,619,402,449,539,175,633,244,36,535,356,128,522,787,882,131,818,813,109,942,806,610,241,286,420,20,991,526,685,860,155,593,507,581,29,515,86,8,148,762,234,241,61,965,901,360,48,400,271,653,981,574,351,479,285,121,73,62,660,223,57,346,117,47,101,236,748,312,552,81,945,311,499,124,903,336,665,202,598,809,690,631,313,782,228,561,316,761,645,403,194,873,202,200,391,9,318,732,298,55,604,933,272,93,809,506,893,805,304,649,228,837,788,82,164,647,637,227,279,565,31,622,962,665,126,334,860,965,524,396,908,271,451,632,432,985,222,743,686,564,175,516,900,213,934,143,274,162,408,90,620,114,729,82,319,200,939,692,897,403,409,357,730,275,594,486,332,514,17,712,310,548,948,243,573,919,354,338,164,245,657,668,531,509,456,300,953,189,372,808,498,121,377,161,390,652,444,992,891,683,106,163,36,935,997,999,4,683,411,820,421,75,380,512,681,190,408,48,756,288,488,591,696,376,388,860,644,379,730,165,889,440,707,237,301,156,463,998,340,254,492,437,913,141,960,424,624,656,730,28,341,803,917,51,230,986,869,60,703,339,751,456,348,809,865,514,231,514,686,309,579,601,782,336,945,732,743,585,434,471,788,820,654,979,53,205,658,413,94,815,87,36,94,340,782,673,403,853,769,24,666,926,883,939,931,885,747,425,913,312,670,525,319,533,952,659,243,935,397,608,937,432,467,392,738,749,561,349,300,445,988,995,92,860,254,541,252,419,177,996,705,657,34,339,647,384,774,867,529,774,400,404,409,439,995,851,346,939,894,847,777,467,839,938,628,392,812,780,783,58,26,223,266,376,470,266,106,716,678,707,276,471,71,374,657,146,897,77,604,339,886,7,992,235,89,474,596,490,777,318,701,123,571,161,564,250,978,433,170,708,493,61,74,94,51,53,247,945,197,489,266,928,194,769,553,983,98,871,420,999,845,362,623,133,890,544,267,988,360,128,553,489,429,386,868,40,332,19,956,608,847,383,858,834,358,835,129,831,722,122,454,826,941,358,930,89,596,462,604,6,799,621,137,761,982,6,737,612,182,976,110,964,841,488,150,259,833,986,864,469,195,508,798,219,855,951,412,859,344,295,7,913,832,694,372,63,390,449,593,917,97,736,529,695,891,129,192,100,571,774,755,330,142,242,295,88,301,233,241,95,808,30,863,573,144,106,913,345,11,42,788,977,661,929,91,140,657,893,691,872,358,558,23,945,919,58,128,250,397,375,335,15,420,240,96,11,120,239,229,4,571,31,576,492,366,111,850,651,476,919,789,274,737,271,761,523,934,144,243,767,338,480,686,360,653,915,147,711,934,647,93,645,789,948,401,836,601,41,664,67,371,247,417,915,367,773,846,97,305,306,296,397,250,713,31,375,364,876,468,954,769,577,0,867,514,921,472,436,685,967,163,333,215,886,704,257,95,918,200,691,176,530,537,470,920,968,295,6,419,899,964,579,901,817,802,211,217,226,678,811,489,399,668,356,807,95,454,425,93,996,427,183,103,20,444,914,763,851,433,356,375,499,712,504,890,551,433,602,228,160,493,130,835,399,37,485,928,964,206,783,372,183,481,139,512,501,75,389,792,168,38,810,715,552,935,280,187,526,236,45,394,988,458,713,686,56,524,39,114,317,834,599,444,776,843,143,55,828,462,88,930,878,221,788,685,102,148,939,711,750,565,264,649,278,848,187,589,136,234,916,12,48,99,450,967,394,204,520,277,54,857,636,564,653,610,571,890,975,184,700,649,780,157,961,343,382,175,567,370,810,460,260,478,194,575,949,329,311,760,998,726,882,370,385,167,990,27,164,123,272,362,834,253,812,880,159,842,645,936,422,576,965,50,88,609,682,906,276,868,601,838,338,164,586,665,993,281,53,423,784,235,670,898,769,394,679,399,67,916,41,14,865,655,862,157,851,184,643,306,102,471,638,461,739,42,779,410,285,626,413,720,790,92,77,434,798,156,277,122,764,318,743,67,376,445,854,747,962,944,665,242,635,162,172,888,97,34,118,909,623,675,624,31,151,782,740,995,201,512,727,614,333,596,276,445,277,211,496,585,623,369,497,980,718,77,2,698,847,788,151,961,173,55,406,816,686,716,327,733,425,979,98,749,242,769,582,628,532,798,119,868,963,800,627,966,504,694,201,387,859,746", + "840,260,101,137,468,337,453,421,626,616,591,32,920,55,412,745,759,127,926,823,823,630,740,518,184,106,266,151,328,776,56,865,273,127,297,287,559,599,823,656,194,144,973,872,134,765,840,971,590,561,518,582,964,451,129,979,927,765,993,400,996,656,46,62,193,366,3,948,84,175,398,960,126,474,877,171,890,966,451,437,210,306,969,580,261,482,433,187,15,738,540,796,582,288,478,747,420,18,841,727,900,907,586,622,646,773,833,850,720,808,16,3,972,511,301,906,37,208,342,427,803,244,636,765,338,225,7,610,72,470,234,691,598,29,102,441,175,534,481,745,250,379,239,909,454,754,142,313,960,535,625,7,134,167,643,912,904,503,258,433,667,878,980,772,947,953,107,8,287,238,60,43,998,432,335,122,303,32,410,539,959,211,200,110,908,928,805,451,529,391,314,503,255,797,512,797,259,466,972,793,940,196,179,257,354,271,428,553,447,644,679,905,280,889,734,60,71,944,154,750,859,368,129,461,290,525,476,995,9,369,390,536,309,463,792,621,379,467,458,836,829,275,135,232,589,111,627,700,991,187,446,79,560,914,124,329,493,138,499,581,397,652,661,718,38,858,945,806,495,465,355,278,602,924,412,48,624,46,259,17,314,376,291,382,592,648,689,960,847,211,373,506,617,983,405,7,386,713,994,850,338,248,567,432,492,662,73,430,953,932,586,276,160,334,33,775,541,591,555,814,639,557,721,236,263,5,189,777,589,574,304,929,504,915,475,272,283,408,22,966,198,686,894,95,887,340,358,465,515,171,798,397,103,660,630,855,524,753,491,637,228,769,153,308,350,168,887,983,287,298,163,856,73,562,880,272,923,364,675,441,821,591,257,158,643,936,895,908,791,192,971,521,639,403,936,176,510,315,187,958,807,531,642,780,556,968,75,763,515,176,287,788,85,578,104,251,59,237,933,689,850,47,238,22,276,305,395,323,379,867,492,660,564,745,19,797,131,531,330,950,730,673,244,636,622,530,939,448,762,485,324,348,450,832,961,713,765,659,372,796,986,948,916,911,256,495,584,169,660,773,77,787,477,669,715,467,141,319,818,777,171,911,483,983,555,309,415,715,477,24,479,292,33,193,522,30,872,157,498,686,939,921,885,988,65,165,120,888,8,9,755,782,40,57,852,661,248,932,645,957,375,3,597,421,554,937,1000,171,976,81,407,371,525,211,433,717,50,179,795,629,119,716,150,736,981,966,597,394,654,81,151,284,277,153,949,297,41,411,430,662,55,390,188,265,999,695,866,310,50,436,614,926,228,827,483,853,186,116,383,777,12,154,696,442,583,972,2,930,350,498,254,830,449,540,659,949,702,962,253,692,94,360,958,657,993,684,906,977,563,520,233,728,541,99,149,802,838,929,875,52,524,319,872,269,679,192,367,616,696,395,181,39,481,232,451,820,514,628,671,843,88,410,717,482,920,997,496,436,690,316,372,118,564,169,893,925,619,839,299,346,919,867,0,453,91,72,252,777,985,429,108,762,132,849,959,597,915,926,994,337,236,191,944,913,69,571,609,606,935,715,644,192,610,602,733,161,641,376,779,641,596,435,946,383,607,289,910,555,290,585,725,279,857,566,108,875,624,484,725,326,570,103,447,38,998,169,749,24,924,603,25,545,691,147,314,138,441,335,101,215,612,731,238,265,26,763,936,825,671,555,366,537,384,437,551,134,390,272,351,740,473,550,808,387,195,401,758,714,445,561,260,499,275,695,670,554,915,97,693,225,952,752,999,26,817,135,543,431,245,389,105,420,829,849,754,915,134,710,321,928,146,795,627,172,777,22,239,44,184,26,593,912,754,743,30,495,794,557,710,478,418,41,6,47,706,733,988,779,590,793,217,799,209,546,584,170,738,438,40,332,405,620,672,774,875,203,74,457,459,322,602,650,645,774,471,78,526,997,945,976,669,861,209,559,214,920,11,384,180,197,745,499,391,361,865,638,707,13,782,94,182,209,209,869,303,42,519,338,654,876,505,889,409,546,52,727,938,293,302,798,890,816,949,161,484,7,508,341,201,852,824,94,487,548,865,411,631,555,831,526,155,634,82,756,959,738,640,714,362,384,753,266,460,948,686,561,760,550,329,884,943,725,95,122,129,514,945,180,187,409,297,658,449,336,483,178,882,47,383,748,921,99,149,208,122,405,426,740,943,566,753,579,162,670,426,80,820,217,146,864,27,417,428,553,688,811,517,42,193,936,226,515,787,472,258,489,836,353,578,599", + "999,206,730,204,723,290,549,152,203,270,929,541,685,408,979,85,401,269,617,994,591,866,337,300,692,983,323,704,787,537,279,480,817,943,409,437,182,155,782,131,408,554,265,639,741,900,677,506,691,538,95,505,583,626,629,479,832,407,236,378,137,138,302,959,39,536,42,914,813,64,918,138,358,842,864,95,337,892,729,545,412,11,303,2,571,925,419,647,178,933,415,35,986,218,804,816,502,413,881,810,245,382,365,670,604,255,505,524,366,254,113,178,754,362,329,805,629,700,556,308,449,507,356,762,546,475,504,429,836,274,326,760,298,207,455,340,559,226,247,929,249,953,384,163,577,179,785,799,968,101,580,129,592,875,526,373,781,388,936,162,474,201,93,436,145,619,550,303,390,610,995,221,137,394,491,229,831,944,681,122,845,332,937,147,658,852,720,408,46,204,194,437,796,341,883,167,25,857,371,64,377,696,492,431,674,421,975,782,174,216,387,439,849,907,283,719,251,159,87,228,509,420,315,642,483,452,889,906,702,246,359,479,187,887,198,577,593,533,98,6,386,544,817,335,175,57,673,780,359,87,201,169,652,489,312,639,508,216,358,524,113,709,697,875,907,675,475,990,292,274,826,571,709,98,630,78,545,341,364,697,976,348,494,945,852,18,658,515,243,701,504,181,913,65,934,836,403,369,500,756,865,849,402,552,450,244,247,489,874,227,954,169,390,949,523,953,662,226,979,268,211,182,610,3,36,989,508,214,246,258,537,877,967,52,374,905,428,101,416,568,453,285,405,625,617,123,835,645,252,527,311,1000,461,778,617,562,829,577,926,826,61,576,687,821,586,819,146,930,328,58,450,784,204,257,392,447,117,635,91,531,163,85,519,507,262,527,34,40,615,253,207,110,984,279,501,927,299,920,538,50,711,333,910,719,291,391,443,54,82,859,283,226,992,478,94,11,268,758,760,474,867,330,59,478,683,362,977,453,355,406,463,285,977,804,429,348,795,889,486,209,303,423,156,836,50,634,961,186,122,510,80,651,859,244,937,677,401,934,800,446,461,476,617,202,207,515,250,663,341,436,247,407,275,490,214,962,458,841,650,598,677,479,985,530,634,254,378,512,210,448,785,657,931,556,432,780,918,452,384,175,784,846,882,102,582,575,891,145,769,6,137,338,910,974,826,465,340,315,854,378,418,30,107,235,618,475,628,921,724,656,500,960,41,610,647,485,110,720,831,153,109,378,296,408,148,208,811,862,116,291,432,708,560,732,765,282,861,712,780,129,133,296,54,945,594,283,655,278,961,448,432,191,166,396,948,985,728,14,152,217,222,9,343,92,793,399,648,824,214,626,254,135,162,835,72,531,557,281,718,291,464,778,547,34,517,882,690,905,338,992,549,332,192,614,730,455,267,778,611,512,709,895,734,570,36,665,567,873,489,638,832,495,150,362,694,404,108,165,770,120,159,819,654,160,397,582,92,862,220,591,591,363,423,49,802,300,429,17,134,313,989,514,453,0,55,828,191,824,511,674,340,963,255,270,743,799,232,950,514,636,565,266,90,812,628,894,202,271,734,195,170,730,363,72,507,982,368,178,280,114,727,548,450,671,359,553,944,354,69,449,888,262,862,372,605,96,379,686,938,752,374,614,784,914,968,838,323,775,405,636,762,473,742,988,675,667,89,104,642,658,310,689,403,63,334,184,280,145,206,742,455,49,290,801,751,330,299,17,165,975,725,406,775,597,426,22,904,407,156,395,130,47,714,399,303,387,94,805,605,322,36,85,777,40,186,792,975,667,766,33,616,50,413,131,359,970,28,698,357,359,634,976,352,34,14,937,407,267,119,431,916,583,977,125,343,368,937,141,432,266,980,700,990,854,730,48,263,569,360,539,136,889,176,908,627,13,109,746,791,772,924,861,663,864,400,59,994,236,107,273,167,160,930,217,41,47,922,390,101,131,853,368,494,909,969,679,806,755,792,103,203,991,464,789,414,641,927,674,123,490,476,436,521,926,765,494,151,561,504,366,27,967,913,515,816,242,119,842,381,734,736,749,969,154,414,687,543,945,725,424,467,250,199,240,88,824,309,169,724,997,979,595,40,100,613,427,798,953,630,890,855,544,262,833,842,535,287,389,637,468,522,872,755,882,583,908,681,831,428,978,301,963,979,898,401,897,713,549,338,181,889,175,491,918,637,87,544,859,494,934,387,805,949,276,114,601,465,906,558,177,36,625,499,895,236,208,170,998,957,751,81,618,749,889,154,757,165,860,710,705", + "940,152,795,388,124,656,104,508,709,448,344,397,194,256,872,239,837,238,69,570,571,846,290,559,714,604,530,671,960,813,556,919,509,577,364,347,390,646,375,194,924,405,382,460,701,730,259,544,53,218,444,537,351,34,271,931,443,305,86,864,637,305,71,269,447,644,160,27,549,495,501,976,197,937,611,394,85,647,168,316,242,477,660,240,807,756,130,190,606,768,618,510,874,914,121,509,507,201,674,254,519,642,312,98,465,946,143,285,365,18,32,921,44,919,19,680,159,265,18,331,633,289,7,427,759,63,330,122,946,434,922,445,467,470,675,919,758,148,922,446,632,565,488,90,921,203,197,326,284,225,904,454,413,486,617,954,916,890,108,131,332,822,330,486,626,510,857,869,889,615,28,172,371,710,631,471,934,798,366,844,873,246,479,389,840,755,19,423,904,595,889,835,187,119,326,80,822,861,502,628,470,293,775,858,20,333,430,72,408,124,232,164,883,714,706,968,640,875,600,664,628,518,46,796,809,320,445,728,592,439,989,917,249,880,538,390,508,543,816,466,667,499,174,915,931,254,834,277,939,146,506,331,103,653,365,919,404,663,911,464,750,278,763,980,93,875,22,743,928,148,311,371,667,862,600,473,106,583,879,194,274,169,158,866,143,754,272,126,780,602,800,413,738,57,797,243,927,118,106,37,139,327,738,729,477,623,6,73,859,559,419,346,256,736,877,602,555,864,322,725,853,703,150,326,773,459,646,207,931,211,982,767,824,805,954,994,603,877,385,650,826,908,523,7,400,314,840,693,735,542,548,212,228,205,596,672,934,587,298,342,878,446,526,454,483,354,512,242,877,831,548,415,927,426,832,391,435,881,563,695,506,113,91,2,200,953,421,305,448,727,914,908,820,341,442,7,813,462,422,31,123,553,946,92,720,478,666,678,805,845,661,170,951,824,92,378,364,360,303,951,281,376,211,626,668,388,59,516,606,791,151,160,120,151,648,18,903,154,752,446,268,619,726,372,950,625,757,160,894,12,486,720,973,152,210,828,557,385,137,452,211,487,412,328,437,922,692,566,986,746,601,649,170,716,850,657,814,327,778,465,902,930,392,889,822,847,296,743,50,872,450,215,372,21,675,712,772,807,760,994,899,151,723,702,507,958,43,594,200,706,336,217,273,230,727,16,484,184,478,819,280,635,311,947,19,718,960,568,359,15,284,165,995,141,715,398,325,653,720,497,18,909,250,471,32,765,488,869,379,315,952,393,134,447,230,590,539,375,532,487,87,188,981,836,844,699,957,352,171,9,829,536,259,303,23,128,106,409,205,749,996,491,957,248,132,96,717,773,288,176,881,515,967,20,268,179,113,710,103,654,421,306,27,987,948,413,528,294,376,168,156,325,280,612,632,745,637,803,769,748,588,645,221,166,631,906,358,143,20,76,77,640,740,948,621,540,437,601,405,881,573,830,591,594,785,510,353,862,924,675,681,955,237,355,996,393,700,673,662,839,320,921,91,55,0,494,380,836,151,378,952,205,549,275,938,108,131,11,621,828,243,983,760,974,504,736,343,118,88,164,899,426,35,76,831,158,969,564,611,210,441,165,791,145,955,735,479,376,119,687,582,861,554,77,871,872,645,708,186,301,922,967,857,288,260,764,954,83,395,96,752,327,915,919,716,896,119,999,69,99,94,916,594,27,403,126,70,488,481,891,253,416,998,437,526,395,637,961,340,256,652,160,342,849,438,572,573,875,532,768,857,567,156,97,935,60,533,793,860,273,213,799,64,998,3,385,586,110,888,119,671,36,957,683,981,239,487,508,799,98,979,142,242,750,826,757,793,451,151,178,699,763,329,744,134,105,45,578,763,377,989,40,65,529,553,424,613,579,905,413,9,31,340,952,589,277,938,632,602,120,640,986,919,294,407,275,431,8,369,464,505,907,976,526,860,692,889,58,913,310,47,479,721,720,353,687,594,742,552,895,237,675,221,356,161,912,386,396,484,655,718,377,870,447,42,71,381,342,721,33,240,779,352,59,6,426,980,396,778,586,795,528,23,809,167,300,943,615,925,131,727,816,72,339,451,630,514,41,569,817,802,497,897,13,257,607,979,25,676,718,87,568,301,200,122,865,631,949,43,925,545,874,29,203,96,855,981,708,95,32,25,340,15,989,1000,684,70,88,722,455,384,950,835,515,656,359,390,245,672,214,836,633,495,463,325,728,550,238,787,986,523,369,526,476,971,226,682,389,714,25,435,415,103,865,764,441,652,520,864,137", + "489,419,997,96,940,166,412,839,679,468,523,839,467,194,579,422,417,508,939,767,391,347,452,421,624,768,38,724,780,569,161,258,219,53,10,958,357,865,486,848,710,551,519,527,291,261,273,790,513,8,494,58,404,397,902,960,274,217,831,862,603,58,149,378,488,222,982,853,538,269,690,289,855,558,470,289,979,791,845,340,662,603,316,119,166,735,501,49,836,67,523,428,814,434,910,760,180,752,138,475,704,756,256,720,1,152,595,480,671,535,381,347,325,796,375,861,66,618,823,741,826,668,512,962,519,840,354,463,939,967,588,114,729,306,584,550,971,749,592,868,86,41,914,7,567,176,320,157,660,266,77,918,492,11,981,599,237,33,683,338,631,64,13,607,955,750,753,915,277,605,416,386,665,509,170,869,690,170,261,885,125,952,344,281,483,488,817,780,941,960,651,250,891,325,362,548,873,190,97,77,240,406,577,215,339,890,479,431,516,410,712,193,376,63,106,905,707,477,299,938,369,884,682,430,308,389,156,993,615,985,684,841,523,356,944,240,803,509,577,624,896,255,703,423,407,183,817,812,321,923,797,964,61,503,190,275,85,652,603,390,876,896,557,926,466,496,877,662,891,551,402,881,843,342,926,549,164,701,54,938,502,956,713,172,48,462,575,406,288,565,98,236,857,800,279,387,512,425,220,45,289,363,857,404,589,917,261,350,501,609,787,87,479,166,808,419,521,318,709,146,611,35,809,490,541,551,675,214,463,910,669,297,694,524,594,182,933,778,526,674,135,687,120,936,660,956,593,236,968,585,621,268,160,398,351,70,928,197,339,556,452,183,324,121,59,138,921,755,22,473,71,96,549,635,227,63,743,355,889,648,956,623,175,521,551,441,80,417,847,29,279,251,52,515,271,680,488,414,727,75,260,777,357,723,328,1,675,158,526,991,285,110,330,977,286,48,111,971,309,390,987,349,716,750,818,676,452,449,953,172,637,612,305,146,146,986,250,734,566,844,409,490,31,822,927,162,816,326,186,661,433,212,176,802,146,673,806,347,736,961,763,106,698,673,978,161,497,907,592,104,421,110,847,508,855,32,479,213,825,823,841,509,284,221,33,940,990,985,407,465,712,133,222,650,406,369,473,276,670,267,882,53,347,210,201,305,633,3,690,19,905,69,202,845,919,236,405,146,56,48,542,894,410,509,154,984,815,218,274,342,97,403,398,968,193,411,399,46,399,747,593,884,712,670,975,517,949,222,357,935,625,429,971,343,791,489,258,140,619,10,645,751,480,321,957,579,741,634,641,244,570,462,74,290,712,973,317,533,756,577,189,752,978,488,375,441,700,559,769,213,577,689,679,942,266,331,19,123,624,140,754,413,356,409,108,940,911,241,910,314,353,542,387,165,401,721,534,496,550,499,789,892,283,721,971,52,955,200,303,371,522,64,154,821,194,67,933,437,697,470,772,431,437,276,805,89,400,829,618,499,178,233,786,894,531,335,445,569,964,140,158,472,72,828,494,0,25,206,48,729,11,16,597,323,704,898,300,91,504,908,249,9,612,972,332,926,848,986,592,192,215,836,237,72,624,552,255,18,363,569,393,53,253,921,977,887,265,623,592,365,772,427,626,53,303,386,460,876,991,695,58,9,258,935,177,850,264,557,709,555,300,26,549,206,93,86,567,291,276,919,58,211,345,998,783,614,331,228,243,550,993,12,409,746,476,76,438,318,373,811,406,533,362,845,833,212,211,342,342,597,751,90,460,359,656,406,551,3,953,496,855,861,940,990,967,170,381,330,465,50,652,120,140,256,492,708,379,409,913,299,534,685,155,177,58,136,913,607,698,273,887,113,613,886,696,430,999,84,904,713,243,470,587,596,490,906,143,532,512,256,87,44,993,334,231,708,95,131,90,843,176,434,198,286,780,655,311,380,891,966,130,34,336,609,194,237,868,484,488,724,395,886,460,872,667,534,365,543,936,729,429,96,177,124,394,219,367,800,737,301,530,614,530,279,873,168,750,608,798,234,350,683,287,525,82,925,500,844,260,560,145,711,38,650,626,558,771,376,186,379,205,124,661,162,251,987,395,894,131,686,448,914,264,729,967,178,978,656,666,273,395,751,375,727,159,689,974,601,421,764,810,484,98,312,36,795,3,322,963,923,21,859,356,275,487,372,755,373,17,303,348,74,150,321,953,28,195,859,211,845,782,978,565,444,448,905,219,918,40,348,572,925,29,856,624,590,988,269,268,476,705,671,133,704,339,668,323,831,276,55", + "803,84,795,121,212,637,156,769,367,496,601,568,603,869,630,607,468,661,235,916,846,824,132,736,66,750,889,237,892,762,426,951,174,21,764,183,130,452,582,243,830,454,820,219,864,6,930,865,109,756,918,262,453,563,245,442,494,442,676,836,308,152,271,606,787,904,142,627,815,199,86,390,526,361,169,237,528,979,662,769,448,117,659,142,648,687,367,936,506,383,254,978,660,274,125,391,413,645,231,640,443,16,853,9,659,571,407,602,195,228,500,486,909,759,690,292,609,426,673,658,757,372,421,32,60,764,176,360,732,744,666,740,382,676,560,837,919,708,933,881,433,357,841,4,945,63,376,961,678,780,422,602,675,537,627,249,67,991,907,215,552,8,118,851,583,933,798,887,145,838,629,134,571,51,401,546,92,780,418,292,371,969,270,392,540,325,749,755,453,967,271,306,166,452,909,139,861,44,138,802,554,379,673,319,311,770,770,841,734,800,541,236,712,526,107,42,97,995,481,929,214,464,664,721,254,145,255,398,936,234,333,838,669,628,671,120,834,613,823,149,198,577,610,847,200,117,111,653,91,7,3,18,828,657,255,790,852,642,653,976,297,57,438,760,503,117,281,475,379,896,685,373,675,758,817,337,347,459,545,725,802,631,631,367,924,221,111,303,948,259,208,650,639,310,614,686,761,964,746,440,64,995,750,227,589,457,688,645,125,51,54,594,395,528,412,976,142,142,809,806,420,588,33,848,30,352,370,150,457,737,508,969,683,901,50,671,924,799,30,500,866,958,53,232,207,859,891,311,199,698,921,926,884,204,668,68,29,255,943,927,57,462,443,685,548,26,58,722,681,250,851,408,698,117,434,162,659,930,750,149,611,198,212,904,963,654,228,884,874,949,767,106,477,460,647,723,118,26,124,423,616,561,788,594,708,480,598,76,243,664,850,232,897,531,81,620,464,151,577,742,472,945,98,897,142,209,937,669,31,545,966,73,884,976,882,429,656,534,574,895,142,443,87,805,675,764,391,168,588,548,160,717,864,234,398,163,167,347,486,650,417,850,136,533,629,329,294,50,630,195,446,881,927,69,684,266,536,395,823,713,765,788,857,702,158,172,444,716,704,389,838,196,957,158,128,534,114,464,627,518,902,116,390,152,267,560,747,266,167,742,808,57,673,183,888,877,652,677,507,716,996,733,496,873,875,73,733,961,410,962,579,973,104,301,729,949,838,21,794,746,924,500,468,274,511,402,4,190,379,280,531,980,437,550,709,210,323,694,24,887,322,876,89,754,886,372,85,865,632,284,377,522,910,578,220,457,409,640,276,647,211,37,100,285,625,73,991,170,622,919,853,478,968,322,352,427,595,512,810,7,300,22,366,650,310,488,859,459,743,727,209,17,609,348,78,19,631,3,598,608,108,349,491,939,403,851,973,831,918,606,639,806,865,243,578,407,680,411,915,669,531,755,436,852,655,501,598,930,687,596,671,777,418,361,908,587,510,321,949,325,353,436,252,191,380,25,0,287,95,373,497,341,933,514,779,911,761,693,485,832,104,875,617,819,127,956,513,282,222,110,81,929,72,512,103,656,133,390,84,69,433,436,39,731,526,458,760,324,199,41,860,284,37,226,554,318,769,990,253,235,496,124,240,843,184,87,10,734,759,985,256,560,389,167,220,174,603,439,527,185,784,138,458,210,930,614,372,525,200,94,561,74,676,594,264,635,84,785,733,247,224,22,508,907,571,895,838,354,590,702,818,966,52,130,329,585,621,871,419,451,272,776,189,154,838,961,593,379,487,885,15,403,861,387,787,407,300,229,214,326,496,889,153,207,839,228,386,715,680,305,939,724,804,318,172,911,150,278,6,632,863,718,681,548,830,296,420,79,428,771,948,819,917,826,70,116,344,614,815,657,925,499,290,36,372,201,885,874,571,306,58,785,721,602,106,391,848,926,659,497,256,780,370,811,588,634,984,699,90,564,976,397,811,56,193,425,829,818,383,801,556,662,432,924,932,937,527,357,255,479,380,762,225,446,618,667,430,140,605,669,396,533,692,602,871,147,776,785,296,445,133,473,94,793,80,653,102,50,143,188,194,450,539,951,854,344,354,795,329,983,280,535,96,978,233,642,829,89,873,332,862,631,330,517,939,72,686,734,106,249,52,818,170,321,529,175,906,572,614,953,268,211,905,146,316,319,763,970,446,350,249,175,432,916,178,823,771,133,225,57,341,528,814,48,178,862,506,62,887,600,717,142,665,380,630,677,391,779,723,292", + "164,814,415,329,387,967,54,581,492,102,363,900,838,16,201,799,183,13,663,754,264,633,198,786,746,633,703,463,834,77,81,136,844,738,953,776,668,797,328,828,721,698,656,84,372,907,958,242,658,93,825,731,437,678,19,317,953,967,359,654,839,410,992,967,980,767,264,543,238,570,560,684,558,490,382,363,10,645,565,942,608,434,415,749,236,71,330,984,653,723,373,193,502,192,776,230,596,424,952,280,162,63,378,64,266,419,6,84,684,603,726,382,948,937,45,611,605,563,518,918,156,927,213,621,935,156,811,749,367,86,228,763,204,344,743,310,295,502,311,513,743,485,616,885,383,890,521,988,438,142,198,551,5,227,835,93,208,110,76,321,826,383,763,70,628,780,71,449,616,134,610,250,762,708,747,578,765,707,753,685,68,318,69,988,433,244,626,923,865,635,123,964,397,416,27,965,695,662,888,236,255,451,562,577,799,758,416,924,75,219,288,999,598,739,698,323,318,951,168,163,188,806,859,234,235,18,388,275,850,370,872,21,151,125,865,337,590,509,518,392,606,559,477,145,348,352,661,21,832,816,699,690,955,122,670,780,28,607,326,796,95,962,301,610,419,335,28,876,748,137,70,147,404,533,858,336,786,461,665,526,608,401,213,887,342,852,452,138,927,642,663,557,274,153,943,577,885,581,590,939,325,734,178,208,718,750,345,297,447,812,916,541,631,113,680,722,191,603,485,253,83,78,413,905,519,808,171,885,920,995,447,581,14,955,868,380,566,791,238,462,184,52,234,552,674,127,571,268,254,410,951,268,130,645,74,457,91,682,828,228,161,938,830,737,528,727,253,713,508,521,11,320,394,905,764,459,671,730,777,826,207,278,606,887,861,399,414,244,415,159,697,325,203,461,186,759,292,517,282,252,602,691,902,10,826,294,947,927,910,708,686,227,152,95,316,19,321,996,387,353,706,883,960,808,272,560,205,494,298,694,154,23,988,358,506,405,346,563,526,179,558,216,146,541,759,814,906,24,371,523,865,967,46,510,321,777,823,286,141,745,526,49,546,107,154,234,726,102,916,294,761,993,532,796,401,268,61,908,794,769,153,298,880,164,576,852,839,505,231,847,334,172,179,558,576,571,283,966,903,244,711,671,1000,370,195,884,59,166,335,453,466,321,656,155,196,7,91,425,230,902,222,427,790,749,987,548,583,237,646,452,19,456,31,534,870,743,893,514,789,434,184,778,233,177,344,569,107,724,812,250,718,156,72,630,279,56,755,787,606,289,73,469,877,358,113,250,945,282,977,977,22,662,734,769,45,122,983,704,721,865,395,232,437,746,656,50,171,494,160,816,29,882,237,803,579,915,452,352,7,733,590,23,41,243,791,963,885,797,461,115,219,931,146,536,751,758,992,646,940,164,996,554,420,764,856,785,266,343,852,329,766,822,89,217,563,338,703,215,19,986,392,996,855,846,836,266,559,436,732,615,654,267,148,256,303,786,28,610,877,356,73,685,777,824,836,206,287,0,502,659,210,857,973,888,997,193,214,760,935,734,815,74,26,506,91,395,42,340,911,977,894,967,382,25,842,217,514,980,744,563,811,588,691,299,204,585,452,821,760,174,538,203,406,565,172,435,567,441,626,548,968,141,634,546,943,773,450,615,517,582,445,968,646,268,740,613,352,449,594,162,63,536,403,151,880,60,653,906,256,358,722,483,666,604,312,916,155,340,687,438,287,545,528,342,215,738,349,444,318,382,553,812,791,263,446,928,847,691,363,419,930,953,306,936,446,354,938,215,271,522,729,224,2,296,457,970,598,554,159,205,78,331,10,20,688,944,159,699,953,828,497,910,784,768,461,432,134,103,527,74,586,506,804,756,191,271,73,47,418,349,908,975,965,410,98,965,545,114,962,220,645,365,818,711,835,628,666,600,725,773,174,980,527,690,552,180,210,819,903,538,181,845,368,426,296,460,714,657,106,144,404,202,43,661,943,554,584,6,903,862,564,828,236,332,899,339,475,932,505,940,420,388,211,677,727,9,788,601,347,542,747,877,450,240,850,127,10,490,751,439,564,37,610,224,833,280,979,669,748,427,660,344,83,563,23,101,75,111,511,634,902,758,715,700,965,159,141,364,273,378,894,785,681,967,933,261,217,153,89,979,62,441,727,296,595,89,618,909,532,336,185,107,368,247,318,470,447,704,624,14,541,433,653,236,95,348,790,58,777,244,965,522,931,329,867,155,828,540,524,655,829,666,333,963,286,548,854,487,954,378", + "806,656,475,156,855,735,103,627,964,330,284,639,672,734,903,400,138,101,853,291,556,946,973,918,648,136,859,600,209,985,90,729,76,327,888,464,905,680,365,175,914,408,765,600,662,751,691,847,802,322,795,806,543,645,824,336,915,134,899,891,341,454,446,443,589,186,257,706,219,567,107,885,710,72,297,691,824,986,990,488,396,196,710,21,356,189,627,91,392,282,721,765,605,445,273,598,901,703,498,761,377,957,300,725,788,790,744,404,764,846,465,383,69,688,146,472,622,422,221,985,208,809,91,897,312,783,53,887,151,155,433,758,12,489,644,567,825,733,455,347,71,868,660,682,374,897,81,527,524,309,907,504,39,227,869,75,465,378,494,885,786,80,454,446,719,145,870,438,45,680,802,713,253,893,399,340,393,245,667,463,723,762,421,386,56,194,516,380,632,869,579,382,334,190,159,403,686,148,755,757,948,291,594,268,102,716,992,668,581,508,680,718,859,244,358,335,291,234,943,667,94,580,7,524,448,672,578,12,835,292,785,760,78,72,565,411,690,832,632,906,330,621,31,278,600,200,521,568,407,956,122,596,987,986,431,146,816,300,108,145,339,290,301,915,224,568,63,612,303,89,634,329,324,739,945,406,605,965,417,303,938,971,442,40,336,545,302,362,930,74,918,174,767,133,213,235,371,657,955,716,121,187,730,76,385,734,672,910,716,942,202,50,888,138,4,785,665,875,390,592,470,372,90,231,683,956,171,38,542,863,927,51,49,181,259,228,741,40,594,946,137,77,827,915,769,355,638,292,466,265,677,657,378,650,159,464,728,644,284,272,894,647,739,660,583,366,120,953,649,219,748,480,981,282,918,865,413,597,936,59,798,141,429,977,293,230,293,498,117,964,784,617,493,601,129,888,722,888,97,704,252,825,97,546,782,577,145,166,37,556,943,868,117,421,582,171,198,448,489,303,392,214,648,660,117,964,694,766,491,47,437,348,419,630,389,541,803,693,815,550,426,190,928,862,422,390,358,313,207,6,779,452,989,535,630,895,333,419,57,261,231,973,495,651,149,189,974,255,392,416,906,904,684,133,58,226,640,81,670,175,356,374,288,95,465,165,907,28,615,208,603,795,725,525,442,432,523,889,166,337,183,108,150,72,481,599,901,260,411,328,957,316,659,343,133,357,414,501,157,690,535,755,7,131,917,641,748,154,28,143,251,130,727,243,898,881,766,84,182,53,828,262,35,295,492,999,44,998,492,133,621,265,716,924,804,945,715,428,937,812,899,952,599,318,700,74,815,475,22,641,363,388,990,614,44,225,588,32,360,167,222,816,942,728,742,570,417,366,634,190,27,300,28,429,698,901,689,241,802,173,536,753,633,308,905,239,188,794,342,505,881,384,855,843,792,773,362,637,803,357,740,549,415,8,603,613,991,207,574,530,439,921,338,237,697,130,702,430,38,450,500,247,896,164,234,217,357,270,118,833,931,89,128,572,79,689,175,969,664,795,586,967,985,511,151,48,95,502,0,802,114,887,91,137,577,76,866,32,442,827,569,849,138,32,266,928,244,970,589,610,952,724,973,327,646,615,377,560,570,614,807,473,681,899,941,908,43,398,516,302,190,16,435,507,656,822,819,440,712,780,762,841,22,849,179,459,118,993,330,930,161,974,520,412,806,872,753,92,755,94,71,892,786,215,338,886,620,986,963,982,989,961,658,350,273,917,903,532,736,212,897,65,261,202,788,52,99,292,171,184,809,78,738,950,38,777,399,5,955,748,578,324,305,424,445,673,367,414,170,889,98,64,830,413,934,102,424,72,965,874,466,447,4,695,185,184,59,85,480,104,941,406,841,733,452,684,186,583,865,589,671,781,753,518,883,653,1,45,491,518,226,307,41,104,231,731,977,257,502,604,106,232,438,870,682,906,495,616,271,842,362,604,342,927,856,348,873,475,591,978,919,771,732,385,167,982,957,821,7,869,969,29,449,295,665,264,819,892,369,854,982,25,248,274,18,257,143,476,252,593,482,343,887,797,78,871,137,999,869,283,537,149,542,599,897,226,257,316,295,56,323,894,926,53,548,125,924,628,816,647,204,103,360,199,143,341,736,87,636,211,688,938,692,762,524,669,857,592,249,872,58,459,852,164,364,501,436,366,74,382,33,766,708,141,211,747,602,612,982,90,239,51,101,118,606,221,269,651,941,896,233,987,491,32,868,184,165,155,932,68,280,435,730,692,165,834,864,533,587,935,628,155,728,429,645,993,959,242,515,833", + "187,236,851,488,65,177,668,340,544,547,636,80,776,12,576,724,844,146,543,31,952,837,952,589,409,389,178,503,677,586,909,557,974,352,32,914,546,561,117,772,897,79,353,640,585,630,129,235,847,964,862,323,566,727,220,305,310,651,406,997,850,423,726,329,643,436,263,492,118,13,41,288,973,604,208,819,535,79,24,259,144,643,175,585,4,971,902,208,519,66,907,640,497,761,108,578,143,173,498,672,157,371,982,223,866,563,536,127,510,568,496,371,225,83,423,550,180,69,277,571,588,571,704,973,48,167,821,910,456,783,905,413,817,259,585,613,33,784,374,851,744,901,837,943,497,980,745,540,720,717,780,99,76,493,89,895,298,533,903,852,403,709,293,57,875,237,651,440,443,589,369,234,967,62,792,394,670,234,928,531,516,647,361,490,22,647,951,327,312,802,669,489,578,755,922,898,863,468,117,217,350,400,979,299,299,820,227,855,776,677,666,124,878,76,203,871,917,416,141,232,647,504,438,77,623,641,290,484,22,675,119,952,591,185,481,507,548,402,954,21,375,977,31,989,693,451,615,462,499,771,402,828,443,780,223,482,655,236,299,944,453,179,947,880,816,852,411,434,763,173,603,874,808,708,987,549,836,710,2,512,692,839,152,484,973,921,934,635,702,192,989,564,223,840,581,957,251,57,858,742,337,444,21,237,84,289,845,296,244,756,73,560,984,834,721,800,226,514,465,626,928,357,388,535,376,284,922,681,930,554,297,187,411,964,373,718,629,618,216,348,354,706,100,838,38,140,543,322,197,695,202,381,401,899,801,179,320,129,971,583,316,476,950,512,519,702,658,234,781,925,426,834,13,255,229,456,957,908,472,161,450,571,382,201,475,988,112,998,321,577,942,304,925,968,199,489,495,852,991,435,698,780,852,701,638,960,504,388,353,790,511,693,645,323,173,914,521,686,674,90,124,882,332,164,972,517,780,391,177,52,341,932,596,609,525,677,318,842,386,671,423,284,116,197,258,941,615,275,120,434,752,759,657,476,242,14,588,242,395,538,854,4,817,784,478,575,806,852,860,760,605,694,756,547,118,236,231,283,551,246,386,577,361,536,257,167,686,448,574,628,963,102,242,1,284,70,582,68,706,671,523,892,704,986,139,267,610,73,194,190,654,721,793,431,583,956,574,793,5,993,423,899,44,54,302,698,958,197,974,998,875,33,408,183,497,203,288,648,117,160,268,250,557,742,799,246,473,647,342,422,942,331,131,455,389,574,542,939,813,714,879,863,558,999,308,802,334,476,611,748,73,348,56,140,662,634,239,120,939,769,631,742,681,840,41,913,10,566,648,42,666,594,211,104,424,443,167,647,343,934,788,758,766,272,12,328,736,932,17,54,485,303,493,841,626,514,322,944,74,382,793,916,206,351,42,182,737,625,120,946,844,520,589,57,642,395,233,436,157,320,63,959,102,869,146,121,126,31,188,709,75,405,795,618,491,689,317,12,415,65,907,163,429,674,378,729,373,659,802,0,322,311,992,377,575,244,441,7,725,481,383,837,98,455,406,880,682,357,646,928,178,486,536,849,494,861,601,114,653,570,4,863,375,5,172,884,698,571,622,174,130,98,915,478,1000,17,775,331,91,283,207,522,425,284,981,26,311,244,36,896,69,847,945,517,503,146,116,442,739,198,542,68,301,132,151,672,336,734,487,614,935,393,97,159,157,679,319,784,267,33,12,25,293,709,605,653,724,487,555,355,126,525,87,579,695,444,384,56,134,844,927,748,446,393,843,640,868,555,945,909,176,474,435,232,739,822,663,879,943,897,871,674,321,938,338,515,320,582,880,270,786,149,955,576,849,286,644,322,168,602,767,553,119,905,535,695,702,292,836,374,144,419,279,635,514,338,244,22,955,165,877,209,38,901,411,693,794,900,576,204,848,343,888,682,603,910,660,527,573,551,280,854,227,759,552,902,466,743,838,163,627,288,345,283,102,748,794,223,921,93,944,280,94,388,974,497,609,970,276,878,723,816,562,868,184,471,869,677,356,659,475,77,190,619,133,185,288,796,767,241,3,994,539,529,600,306,427,727,673,141,952,347,79,479,594,731,831,293,544,149,482,658,795,769,460,643,508,183,737,873,467,488,98,498,926,728,443,466,691,874,440,633,966,665,217,803,94,522,511,869,565,526,168,603,116,401,574,481,251,130,782,40,484,99,107,802,516,805,636,884,610,726,52,957,836,539,857,875,845,452,379,524,397,381,342,862,887,67,646,63", + "989,262,274,645,382,766,113,686,852,550,445,617,937,131,577,628,56,208,491,805,693,725,16,389,108,887,491,627,431,341,816,550,566,703,502,928,792,649,289,786,884,654,214,592,625,334,964,954,409,304,910,964,786,914,834,36,297,829,477,112,797,4,327,607,703,80,908,299,965,837,990,66,68,30,179,542,77,849,897,999,462,774,33,284,233,110,714,155,388,71,91,441,214,108,854,550,339,740,230,134,336,685,599,830,114,233,901,843,356,678,132,715,39,693,734,217,510,275,662,213,781,301,890,382,721,89,447,33,375,635,357,280,712,819,214,108,322,594,787,788,789,437,502,505,593,888,573,274,862,180,85,702,173,831,620,739,582,46,993,625,811,595,395,494,455,306,764,289,131,504,424,522,401,882,293,432,143,721,759,906,23,923,111,219,698,342,873,968,275,404,395,866,490,119,67,496,174,225,304,278,632,598,816,866,634,901,414,588,647,328,349,551,332,246,548,494,278,705,953,119,753,712,990,817,121,820,497,934,213,813,442,938,723,720,695,148,18,271,261,922,306,788,204,117,544,281,276,740,614,940,599,146,268,448,481,155,128,266,674,208,21,398,932,331,617,694,649,719,206,626,294,771,448,431,475,516,905,436,247,617,77,468,792,55,643,215,760,467,613,443,661,217,430,403,896,838,796,535,297,150,761,581,490,318,509,528,278,552,519,740,127,594,812,61,92,88,979,659,693,262,714,727,402,9,670,886,498,318,716,90,478,688,677,516,127,819,811,392,571,560,335,412,920,284,52,565,680,697,243,259,628,177,464,519,789,244,853,609,116,56,618,619,278,481,311,671,662,162,697,883,968,126,441,852,797,211,181,36,163,364,873,271,539,671,262,333,113,404,521,583,350,943,20,91,289,705,873,667,488,799,196,220,513,308,861,655,527,275,797,199,193,347,521,924,745,191,249,163,420,947,532,551,733,192,313,876,239,971,923,238,715,180,996,113,132,5,517,374,355,726,121,96,866,287,766,241,792,36,3,570,212,503,405,104,271,844,681,166,63,432,532,218,713,501,785,311,809,848,428,453,854,378,869,964,860,446,610,299,778,352,586,509,635,529,508,361,127,190,167,257,465,728,242,429,566,363,332,60,772,805,867,227,89,343,319,44,167,531,174,17,618,48,506,936,858,804,249,200,111,682,7,454,426,523,314,134,297,275,118,986,926,483,800,526,542,655,284,992,86,756,54,653,899,15,920,737,547,973,714,989,445,573,397,296,587,789,122,977,314,591,423,125,717,971,762,418,603,558,59,562,814,187,5,468,191,97,216,745,831,6,81,728,426,896,421,973,948,479,852,855,444,649,938,573,516,320,848,516,289,252,764,3,556,470,363,709,839,608,770,592,170,933,367,891,892,756,484,329,317,552,896,944,836,18,81,853,628,610,931,604,725,416,504,442,606,563,793,677,185,332,679,885,653,494,338,143,906,197,470,118,19,645,282,304,466,182,269,539,86,355,340,333,108,340,952,11,497,210,114,322,0,246,430,989,897,512,380,976,550,851,513,582,583,329,822,29,988,726,163,15,166,426,645,612,93,790,8,195,41,626,989,896,158,541,958,83,65,139,156,160,631,393,956,976,457,886,171,896,974,372,393,939,872,323,520,963,936,827,423,448,853,293,529,943,968,947,267,396,62,509,313,708,937,146,708,409,409,863,821,614,825,536,682,101,260,839,537,315,282,127,128,344,122,704,377,452,120,337,748,268,495,753,407,424,441,281,364,803,40,344,139,221,651,46,744,812,621,651,392,195,384,366,912,560,306,963,833,101,116,307,951,923,794,394,870,518,132,819,824,12,621,122,213,801,863,813,733,169,969,288,868,858,353,216,868,34,663,641,273,683,88,228,956,462,357,689,399,24,639,687,411,793,946,84,662,609,901,786,443,543,233,223,948,619,522,508,828,888,306,166,751,89,540,645,264,858,855,556,93,805,545,421,894,312,198,148,783,428,833,495,124,881,366,978,803,278,738,252,877,393,381,267,675,159,860,591,987,221,742,401,565,51,477,482,963,765,286,643,524,489,848,119,11,183,572,107,750,461,765,116,844,200,143,104,628,565,340,324,745,72,705,173,47,790,863,203,379,314,405,269,33,898,680,413,469,159,167,662,527,759,154,497,391,209,475,779,475,174,159,464,887,742,391,960,116,478,136,459,108,357,972,664,541,800,913,585,221,46,879,858,8,324,461,351,406,866,567,646,483,761,463,320,464,226,138,455,667,789,842,71", + "178,476,953,398,504,349,700,690,961,336,850,774,989,794,245,969,336,962,791,537,847,391,265,591,285,301,439,851,359,884,802,127,636,250,334,931,68,500,822,528,389,73,91,200,70,473,957,802,782,874,438,747,907,919,40,70,703,976,983,21,43,429,471,357,383,756,894,241,122,813,752,964,480,844,451,271,274,559,629,197,823,66,907,598,297,218,821,892,912,687,507,780,114,107,454,879,849,87,129,885,484,988,507,350,278,317,414,969,79,245,331,339,883,84,510,716,151,667,762,34,528,106,99,749,329,749,315,314,600,111,1,603,439,986,413,99,990,829,162,428,223,132,813,201,932,530,570,967,5,17,879,634,842,267,502,383,544,457,34,284,268,698,14,685,372,399,280,775,393,998,453,223,432,564,570,377,943,629,833,685,405,34,339,237,93,226,4,542,326,899,337,150,805,117,302,35,854,280,800,603,139,830,558,95,875,712,460,621,503,363,95,122,73,297,269,478,443,46,625,71,98,808,263,163,655,808,438,465,464,83,195,302,347,142,645,256,902,975,706,130,164,245,795,835,441,806,982,983,635,511,963,580,916,10,147,680,171,243,286,925,411,300,861,814,298,588,379,795,27,771,22,303,999,184,1,301,662,469,393,911,456,972,701,769,660,763,114,328,524,627,469,941,989,398,338,382,675,100,934,31,194,243,781,356,937,855,364,736,377,850,66,973,927,397,714,959,847,449,231,621,421,29,554,170,443,323,848,557,844,895,145,335,329,274,256,711,204,562,95,334,684,651,438,344,280,549,274,772,872,271,709,338,251,573,552,71,498,746,25,280,879,416,147,952,632,748,92,277,333,894,890,721,61,979,968,288,18,448,967,427,93,933,431,844,208,63,748,574,596,130,435,573,126,183,802,518,992,154,586,589,685,827,761,519,945,695,944,156,751,482,424,28,124,632,850,687,942,517,332,517,799,507,316,177,486,19,155,331,883,275,95,186,544,225,253,722,658,26,559,287,432,13,715,359,901,114,103,422,234,171,862,916,625,580,494,55,53,130,573,820,557,113,742,87,126,867,997,823,829,686,321,998,857,403,749,359,792,359,969,285,258,323,670,509,644,685,170,44,43,823,27,866,356,253,590,762,329,343,351,675,496,49,2,395,473,621,520,257,675,680,332,365,647,743,424,728,186,263,63,18,317,866,813,333,79,604,342,187,719,507,978,783,990,677,918,713,340,587,719,229,495,601,602,96,150,646,618,389,943,127,597,743,177,109,985,511,181,169,701,986,321,13,546,486,775,783,887,26,163,274,32,125,248,357,763,398,343,724,710,198,302,391,396,203,940,763,951,801,18,573,466,708,227,313,512,490,685,721,961,814,786,501,835,640,581,624,818,792,455,115,373,38,256,370,262,518,53,247,812,438,539,471,578,749,579,996,441,862,812,870,562,46,962,332,505,928,964,505,177,360,43,555,316,155,827,28,908,897,324,86,100,436,64,209,309,600,251,476,704,381,681,215,762,963,205,16,341,857,887,311,246,0,327,831,912,280,418,605,140,510,686,125,38,226,614,705,969,378,326,158,902,259,759,442,444,484,78,410,22,653,880,469,868,65,929,677,83,768,35,401,378,743,434,833,894,948,560,623,888,844,709,106,46,468,409,100,665,26,558,114,3,876,744,138,333,324,650,473,648,591,783,199,900,440,431,456,802,139,475,155,324,273,789,829,44,362,237,337,152,24,557,24,204,905,391,171,961,626,445,601,428,903,101,442,834,587,773,184,455,329,571,894,815,748,472,564,443,931,402,433,799,505,645,916,646,259,834,991,232,770,991,146,64,411,873,164,428,109,147,574,547,899,709,168,516,9,920,139,279,646,127,554,278,783,736,520,608,426,523,783,8,954,588,749,770,478,318,723,420,272,61,921,497,532,764,281,637,932,772,718,817,283,888,590,300,95,98,399,346,218,675,351,77,518,866,443,726,581,217,128,563,675,717,600,253,942,861,684,298,241,795,290,806,587,290,498,927,62,548,223,405,264,16,698,589,292,736,68,694,722,609,121,28,782,721,861,660,330,243,602,671,718,282,493,530,733,628,682,417,187,760,773,996,661,348,879,569,635,716,452,431,963,432,293,443,657,559,130,107,19,536,257,880,217,967,706,802,252,24,911,808,25,955,777,262,807,369,451,725,245,174,627,991,124,671,353,887,147,676,608,530,689,16,496,470,4,602,680,706,693,24,116,230,139,712,329,475,116,439,978,792,919,728,379,453,879,145,710,499,555", + "257,806,899,23,586,119,736,248,608,70,798,145,62,153,53,509,354,513,738,766,663,38,351,714,472,689,347,258,374,371,29,415,22,261,990,772,105,318,861,82,573,317,983,345,224,346,349,595,262,790,505,653,560,88,60,543,145,651,89,541,803,86,417,947,106,129,299,794,866,566,104,40,67,634,52,418,365,174,343,737,634,929,723,3,545,744,682,103,400,342,861,52,472,856,376,261,298,115,782,718,831,202,205,531,552,776,666,722,246,200,459,805,209,937,406,728,632,521,886,984,683,742,475,290,896,925,841,927,701,847,927,478,28,831,19,359,693,451,279,987,831,69,598,319,576,923,813,900,754,271,857,899,791,428,862,929,603,294,74,565,824,484,6,792,987,810,935,796,622,762,583,671,532,668,274,334,477,822,724,595,438,11,5,6,925,757,43,8,451,977,357,834,176,692,699,934,869,426,603,180,709,137,167,226,733,499,670,610,691,371,89,730,387,828,823,575,284,746,52,642,985,70,321,118,30,849,175,683,392,545,63,951,498,130,144,398,829,674,421,839,857,278,566,2,161,455,809,124,583,949,180,551,228,520,836,699,896,78,949,207,924,746,772,412,191,113,723,98,338,297,63,516,140,304,518,299,360,279,123,371,496,613,585,48,96,896,667,971,349,231,272,707,558,492,716,300,73,892,81,657,94,948,494,89,939,238,794,771,433,633,924,27,494,371,802,621,169,417,173,507,126,197,371,31,490,185,881,868,581,404,602,242,316,31,491,161,499,321,768,236,739,803,994,915,237,229,715,827,793,230,803,51,659,309,200,262,561,638,59,844,112,304,386,845,238,432,405,231,468,341,398,283,765,644,750,214,708,226,833,801,829,709,254,484,741,528,2,401,782,153,635,441,434,842,159,673,93,772,157,612,566,3,623,668,986,581,887,253,167,151,354,724,386,953,402,445,778,407,808,334,499,190,759,68,859,89,102,948,405,588,951,405,78,786,58,915,617,900,852,723,931,709,903,771,479,12,960,429,473,88,179,755,460,546,46,565,24,538,173,774,15,212,946,987,39,255,813,653,333,701,13,94,805,539,935,930,345,463,319,679,352,884,909,413,286,381,845,232,36,634,384,677,898,331,195,201,969,343,593,589,159,182,842,346,754,707,867,29,40,878,121,308,336,739,783,177,450,751,364,129,337,342,666,305,412,682,270,344,88,636,508,186,762,387,552,145,54,730,583,215,511,562,485,246,685,689,192,371,600,311,288,150,459,459,309,998,421,126,344,2,693,740,585,960,788,592,839,240,52,484,728,873,141,533,221,512,130,440,315,986,93,732,464,207,497,206,595,599,745,120,136,349,473,368,821,911,327,456,285,815,842,609,252,548,735,677,350,356,802,834,554,113,217,347,288,936,299,157,961,770,397,123,952,809,969,334,143,250,635,195,586,16,686,847,164,774,478,817,68,486,694,329,698,920,711,475,361,307,803,877,602,525,301,117,575,133,981,233,39,924,398,886,132,255,549,597,933,973,91,992,430,327,0,256,439,969,344,339,851,315,372,219,575,898,360,512,824,103,829,936,946,599,795,980,691,216,974,403,738,666,448,570,562,631,271,768,291,601,746,323,424,93,517,930,946,851,121,640,965,661,830,535,132,752,593,353,696,295,435,612,137,766,875,220,795,529,416,28,836,889,200,417,101,111,347,173,388,296,342,151,828,653,766,883,734,915,628,572,799,169,722,926,190,136,184,563,56,26,255,694,873,122,878,332,147,586,362,648,766,913,379,400,376,104,291,232,413,230,184,212,850,901,56,543,317,728,341,686,136,858,23,575,729,272,809,514,461,382,470,554,216,877,98,883,280,993,571,932,744,841,461,496,870,931,794,102,390,259,807,64,13,931,636,181,338,157,622,926,229,395,368,154,179,281,218,701,489,216,692,438,720,551,174,557,230,881,319,991,59,504,795,37,9,902,818,96,400,611,217,475,787,302,683,598,992,312,405,837,580,813,778,566,937,247,127,155,539,3,507,445,787,128,999,440,453,6,718,64,312,20,830,940,633,633,520,938,83,736,398,473,918,765,126,779,559,964,745,967,286,723,432,962,615,798,400,538,297,781,582,653,290,255,94,18,666,560,994,574,933,976,311,658,241,51,364,145,639,561,114,316,401,942,283,754,347,191,283,689,541,853,38,11,675,395,530,765,951,260,100,783,847,192,413,839,585,879,140,69,679,822,870,260,454,912,572,716,991,116,997,712,24,338,155,134,818,891,522,976,350,667", + "835,589,29,214,70,493,399,880,115,555,516,633,850,315,764,761,963,566,757,543,171,712,308,825,470,586,168,496,694,381,514,282,345,93,382,932,912,667,12,576,772,478,739,35,24,846,243,289,741,495,516,835,361,612,515,97,680,300,386,360,96,669,291,486,803,436,963,165,672,409,781,974,974,163,552,579,66,35,7,684,309,906,304,974,626,247,929,351,714,208,511,528,472,856,539,525,273,891,988,339,558,990,441,774,96,321,441,893,801,68,894,730,623,764,216,20,816,91,384,198,40,691,640,997,671,945,980,404,829,386,724,997,584,362,173,774,935,822,110,739,50,97,849,680,152,738,414,615,811,435,965,788,532,238,673,490,536,68,843,115,991,672,187,458,573,603,535,116,913,580,230,696,752,57,523,317,427,347,378,796,762,55,428,70,477,672,432,7,233,453,999,351,809,803,903,257,643,568,447,277,339,719,945,480,527,591,840,370,619,903,52,221,798,382,260,720,777,459,419,614,880,826,715,636,842,135,858,891,400,912,533,756,579,717,505,817,288,729,787,290,42,698,830,81,899,4,363,333,751,254,539,137,991,722,897,330,530,295,784,48,47,500,291,945,912,360,788,974,43,721,271,909,966,783,847,937,104,889,943,817,539,150,943,469,554,521,877,935,71,369,933,730,55,575,611,147,742,400,790,879,756,430,441,375,894,58,958,992,881,695,862,421,354,321,830,450,950,306,762,521,491,593,840,679,433,423,478,701,868,569,557,2,197,383,181,878,558,766,85,852,192,415,67,76,755,348,109,871,136,387,979,138,657,400,180,474,929,251,442,778,559,991,935,360,606,289,341,887,846,590,673,181,70,962,748,348,725,687,572,243,347,399,96,806,644,241,284,619,527,988,752,975,777,61,553,491,467,780,919,433,949,70,951,841,63,255,891,553,159,338,215,308,677,170,282,644,901,456,399,421,153,682,779,315,420,347,946,363,85,70,525,363,726,557,739,148,822,446,488,316,411,248,629,558,409,67,894,696,629,377,299,840,694,61,473,78,222,696,442,215,124,681,13,50,617,891,254,10,373,830,763,877,613,626,595,428,624,84,100,642,909,34,347,278,544,666,274,166,807,957,518,429,550,153,50,537,633,306,910,508,613,460,685,948,38,335,747,668,656,596,520,489,470,707,988,312,756,487,733,679,175,102,52,866,923,379,654,92,265,870,336,92,555,345,698,119,248,346,767,943,28,375,36,643,663,610,665,929,92,223,142,606,766,919,38,694,468,52,419,51,738,547,453,940,890,95,375,699,965,58,720,138,95,161,613,232,571,114,59,129,477,691,319,490,774,983,929,418,912,761,220,98,342,559,344,91,613,556,560,857,671,346,526,160,626,180,22,783,785,234,70,80,501,795,5,751,242,965,405,834,271,372,348,441,833,172,685,269,552,942,59,230,27,25,264,86,405,595,392,99,801,612,118,205,135,599,902,275,72,669,990,971,908,677,550,162,502,62,320,497,746,704,849,270,275,323,514,888,137,377,989,831,256,0,583,194,627,199,452,10,780,664,353,660,314,507,29,971,96,743,13,991,577,441,399,951,505,643,357,434,885,336,734,433,21,310,500,784,618,714,419,612,398,841,720,853,255,426,229,189,735,329,270,48,453,71,82,471,485,23,68,613,811,536,635,656,291,619,201,668,772,465,808,429,542,318,71,727,209,636,607,580,345,237,661,156,691,124,666,140,479,769,785,77,672,350,710,478,498,774,256,472,440,727,229,633,814,280,515,429,289,278,435,349,851,614,655,143,479,766,325,474,614,951,207,20,989,352,172,242,436,55,248,799,50,46,624,245,383,346,627,382,377,515,580,181,115,599,74,338,912,560,920,544,974,911,618,927,132,584,992,868,186,853,476,291,581,904,147,203,123,829,643,983,33,552,474,253,504,577,453,103,472,990,312,961,79,498,566,249,177,790,429,622,674,465,169,153,679,843,990,726,232,289,749,158,638,529,854,116,889,166,181,584,558,538,787,717,711,963,114,968,983,347,29,299,926,152,167,65,888,527,12,401,113,519,981,603,3,374,533,40,554,178,657,762,2,407,112,175,829,173,130,215,95,459,73,732,798,900,868,328,419,409,253,228,56,929,867,573,110,747,479,861,784,302,207,110,723,525,500,968,824,357,691,187,609,320,441,178,502,937,437,546,508,792,806,236,902,956,851,739,501,600,791,456,860,677,530,29,750,77,257,385,963,675,266,903,691,112,691,38,315,302,390,464,132,204,793,343", + "516,155,442,709,704,957,458,878,242,305,465,261,262,454,828,278,915,770,903,61,576,21,22,471,730,705,876,856,352,300,883,501,828,538,293,339,88,269,589,959,335,519,990,174,693,184,783,654,797,918,450,2,33,299,930,413,476,924,929,701,635,151,432,201,969,536,778,216,34,182,695,252,272,507,419,857,64,385,32,360,310,973,644,206,815,483,731,387,694,251,796,282,207,498,781,121,182,640,900,439,429,961,851,122,251,122,342,679,569,496,80,984,440,269,335,308,465,4,430,392,699,785,999,833,324,75,329,873,63,12,960,856,743,562,823,33,462,198,834,73,83,312,832,964,676,718,906,613,991,453,762,549,451,299,556,637,625,467,577,21,17,383,942,772,827,823,712,787,942,796,781,109,92,571,662,371,868,282,715,183,132,4,404,80,354,699,994,307,737,709,183,613,46,731,235,312,995,813,232,34,179,676,297,67,388,859,49,55,506,576,830,265,40,190,43,834,264,18,744,246,669,988,617,265,790,586,343,737,949,737,342,253,665,761,715,664,258,159,944,991,2,867,491,998,450,37,640,852,524,499,59,954,198,927,272,153,886,22,691,201,788,926,25,709,264,198,82,503,287,187,61,307,781,868,282,126,204,983,333,565,323,909,665,935,550,90,285,359,591,200,458,796,769,99,561,9,114,915,548,840,785,88,204,334,645,459,531,712,729,505,517,519,540,297,975,344,230,961,456,327,933,470,565,481,944,933,201,898,266,407,825,871,97,354,643,168,349,146,713,210,132,560,529,614,50,735,835,183,296,632,438,107,961,175,840,251,319,127,767,36,829,66,99,574,856,13,307,552,613,550,493,863,944,377,98,806,753,459,656,569,860,124,213,942,543,989,709,195,586,925,978,651,431,810,540,558,540,893,71,511,422,509,256,615,113,674,927,960,149,543,165,144,583,836,614,539,807,613,272,456,952,351,643,669,307,345,657,165,339,427,836,673,959,733,844,617,509,371,490,450,955,68,97,366,765,564,626,229,443,773,413,924,438,584,515,51,881,644,606,872,232,329,986,996,688,993,326,152,570,157,147,215,737,273,334,681,999,724,549,368,516,960,585,957,404,27,885,617,811,511,403,722,256,389,794,962,475,524,164,796,896,15,404,278,921,143,169,733,843,865,910,856,831,479,672,440,453,249,368,701,707,466,654,361,92,908,778,492,494,48,161,289,148,953,388,498,440,987,870,581,143,345,346,191,972,588,844,532,997,487,161,216,472,926,678,472,164,692,325,395,395,878,415,463,652,934,489,150,104,368,338,982,657,731,520,408,183,693,175,174,133,81,418,298,523,770,62,536,18,752,643,141,971,762,170,586,870,156,79,999,543,984,452,743,210,777,399,162,365,212,53,456,257,7,863,754,180,193,401,299,661,894,868,253,322,386,342,36,754,502,129,291,608,859,234,523,547,378,961,741,225,34,119,530,791,955,266,938,271,902,922,644,420,589,386,617,933,857,142,532,71,257,959,743,938,704,779,997,577,575,897,912,439,583,0,928,993,327,530,432,605,823,25,749,716,782,640,85,710,94,447,67,719,734,634,10,715,394,913,746,714,391,259,607,253,449,929,350,95,9,926,329,150,616,336,65,175,823,990,231,962,1000,136,312,313,157,508,789,315,356,447,8,509,724,926,767,357,640,534,408,234,276,132,572,812,216,28,998,437,234,983,121,292,266,624,934,201,208,227,400,66,647,792,996,421,74,154,91,9,835,136,58,833,460,518,63,63,975,657,720,863,504,579,405,784,269,574,359,930,667,589,61,884,342,768,245,818,973,268,398,74,558,557,892,176,438,567,177,164,526,91,514,833,983,584,91,408,801,508,268,356,567,453,99,160,538,367,726,468,715,615,431,35,887,780,247,623,272,725,90,41,546,18,608,547,316,778,807,399,832,90,4,832,967,876,596,465,521,377,695,81,694,319,816,484,418,647,508,764,758,905,948,269,316,989,740,546,504,184,68,264,718,867,24,694,775,284,547,575,437,179,142,870,963,897,761,571,973,861,392,975,94,68,521,312,232,478,738,879,153,665,927,369,454,202,893,264,165,452,171,781,97,164,982,239,258,166,165,993,31,861,301,607,208,438,774,906,294,396,464,396,582,312,637,57,728,623,958,811,123,40,322,463,608,211,858,230,414,117,617,195,701,810,310,620,882,499,500,804,844,828,443,126,160,229,61,233,221,46,302,134,489,83,180,70,383,900,571,256,656,584,874,723,448,71,820,739,353,468,327", + "172,935,830,875,459,388,984,492,783,595,159,825,788,770,902,940,880,64,58,622,825,443,706,477,368,317,362,143,559,351,476,526,577,48,144,822,854,513,750,588,15,829,520,912,83,432,862,576,826,831,214,908,48,54,206,445,196,772,295,239,111,181,102,653,401,405,244,445,564,8,739,420,237,683,739,37,71,521,909,495,177,759,512,267,720,881,479,494,649,548,539,563,256,243,804,710,90,933,212,142,38,815,270,988,49,131,289,337,815,866,538,691,826,326,624,442,550,970,333,806,153,629,201,448,111,16,163,4,901,186,281,479,741,756,995,19,861,204,803,592,17,196,487,885,378,831,986,945,655,969,590,450,840,661,486,242,338,655,734,155,897,334,640,107,233,766,182,558,355,194,209,559,375,653,433,606,337,853,874,786,818,978,910,951,180,229,91,604,520,966,948,209,214,568,75,109,974,771,43,281,268,314,102,457,669,704,914,448,236,206,504,342,563,658,395,304,499,372,473,656,179,791,821,723,690,630,442,691,722,472,924,537,359,716,343,855,487,951,308,529,834,630,336,889,696,407,1000,869,119,341,925,300,787,497,911,971,998,964,848,391,400,103,860,560,850,53,99,648,354,468,542,657,846,486,665,682,401,68,104,462,716,591,821,782,495,688,290,948,997,10,320,973,500,616,52,931,196,755,57,306,910,845,349,882,216,731,495,760,211,388,493,27,565,647,787,431,379,886,576,622,310,736,971,22,154,601,366,83,659,236,797,652,771,115,435,597,833,161,34,53,847,802,778,540,915,824,89,586,678,478,652,498,638,44,950,373,128,486,473,140,967,124,173,789,893,920,148,158,910,537,126,805,564,114,363,64,712,510,535,814,752,69,874,753,709,824,998,231,197,322,605,551,444,882,213,635,442,217,916,879,896,361,901,645,287,185,46,916,285,465,600,39,948,172,811,47,472,201,395,60,856,348,700,241,853,150,192,557,71,156,719,817,969,7,989,32,437,812,313,252,416,404,370,815,877,349,132,967,472,800,159,1,4,800,432,372,409,913,199,53,908,823,156,701,564,797,22,88,347,189,892,537,14,852,92,291,22,559,394,332,898,266,598,164,368,490,656,225,549,94,652,616,878,634,725,4,384,556,906,811,215,28,219,388,474,261,840,112,430,561,45,826,681,880,433,725,92,634,379,191,534,18,431,557,516,185,549,38,554,158,987,555,897,671,902,728,201,702,545,625,803,935,546,304,857,243,638,506,339,677,660,995,643,182,398,193,433,65,294,650,587,251,352,583,227,709,628,769,974,814,264,453,631,280,617,149,957,763,299,630,84,715,598,48,108,519,217,752,587,249,151,900,679,436,976,405,252,351,959,446,459,413,465,743,346,400,439,922,952,829,220,616,537,276,959,894,373,772,922,991,844,362,624,406,879,243,436,980,441,374,594,79,397,260,241,509,270,13,343,203,198,151,186,872,741,304,570,174,18,130,446,255,334,485,979,362,699,541,403,811,737,95,597,799,108,898,911,193,76,244,512,280,969,194,928,0,961,944,494,94,469,721,644,896,841,923,647,553,708,957,752,895,302,787,572,856,281,980,982,951,894,853,300,77,592,815,468,751,82,120,927,744,806,482,784,618,893,864,384,803,330,991,211,964,77,537,160,300,75,515,234,114,7,784,243,875,596,341,392,909,53,589,156,95,72,354,487,457,154,330,197,384,292,227,498,510,963,235,41,521,544,542,444,324,994,879,177,621,766,177,820,8,664,295,712,701,935,257,142,952,559,891,488,590,69,407,597,126,553,978,898,415,100,820,382,700,558,119,406,734,422,239,280,79,439,342,572,182,80,306,954,920,607,729,481,317,141,717,517,150,627,973,192,469,545,722,514,712,924,78,665,593,823,385,258,67,372,940,352,282,425,66,807,713,601,966,261,477,358,765,869,770,26,996,304,552,935,231,314,156,705,547,405,544,316,860,884,895,15,469,868,382,55,532,746,963,741,342,686,822,165,82,860,279,33,716,110,866,731,707,933,582,558,757,633,981,371,286,772,198,280,872,140,312,988,150,593,603,459,862,302,111,246,593,961,423,175,857,794,840,724,4,416,851,955,210,286,212,448,350,348,781,875,435,885,134,444,585,906,766,858,888,257,364,56,212,264,687,754,519,357,603,233,901,571,6,634,915,789,454,217,110,391,162,955,952,426,301,160,769,290,897,440,763,713,709,135,482,78,945,462,316,350,347,23,568,275,201,718,273,431,183,270,505,394,324,804,821,77,253", + "594,197,374,129,831,574,689,914,664,628,259,625,364,441,88,591,802,314,86,366,111,872,327,304,195,729,751,625,9,510,391,907,731,304,243,865,256,742,524,325,790,887,55,517,555,276,360,788,525,615,125,791,907,223,878,421,672,120,713,749,549,746,726,305,982,94,565,674,275,877,697,264,172,377,549,914,198,597,717,707,58,448,264,518,519,477,213,823,343,401,117,62,673,444,669,766,279,702,429,629,572,798,263,395,72,705,709,629,490,665,77,699,541,366,917,647,378,452,124,329,483,370,492,823,557,653,986,905,856,646,280,827,708,784,484,224,338,527,185,530,900,110,499,414,376,830,538,665,323,338,381,732,329,616,82,124,634,120,723,60,576,324,106,34,559,522,927,886,348,388,222,506,226,566,686,830,406,625,612,145,57,638,36,181,295,117,28,347,586,450,971,303,901,871,100,340,829,34,72,209,525,184,463,994,105,364,963,558,804,95,403,512,622,164,2,630,630,254,403,543,542,626,889,220,847,637,700,526,866,963,285,155,288,8,924,29,894,586,345,624,998,81,10,489,496,215,216,101,779,455,197,24,607,869,856,895,129,709,975,708,431,538,613,332,305,730,61,868,632,386,988,273,751,682,586,977,440,811,532,685,547,759,552,12,722,84,952,890,115,150,222,99,431,22,361,975,616,503,790,920,386,136,681,326,936,732,354,583,61,606,158,817,197,880,76,477,815,229,732,367,261,272,714,278,62,135,309,844,939,270,92,667,952,615,931,806,675,669,696,284,313,613,641,154,297,665,362,156,658,424,951,20,441,986,648,114,709,564,416,610,168,805,573,979,738,531,740,552,369,287,301,978,891,108,202,719,453,193,556,445,190,137,708,354,138,288,677,750,146,471,755,491,63,235,698,349,952,476,675,321,988,196,989,71,839,319,121,940,838,955,296,9,745,272,670,518,756,271,599,45,478,907,124,101,695,527,106,601,137,121,720,721,215,815,571,333,880,686,68,961,49,894,624,602,851,620,582,788,532,38,374,467,719,13,532,849,412,340,387,419,285,179,116,479,449,776,328,487,847,684,182,138,456,307,532,894,926,853,96,786,677,785,453,313,876,363,229,372,203,689,901,886,821,102,93,342,46,227,812,810,114,235,432,944,948,927,712,976,631,529,727,742,221,889,650,713,464,930,319,792,958,96,569,975,145,800,899,603,858,453,994,293,854,542,375,663,532,688,441,983,202,985,627,595,286,15,6,302,724,514,367,342,562,554,478,128,361,617,414,572,4,477,476,750,155,712,580,259,69,406,176,334,364,542,406,87,485,491,721,430,4,885,848,172,862,263,311,142,60,484,827,971,19,29,730,352,924,253,543,112,139,635,606,532,971,911,775,805,156,186,539,166,112,984,684,906,337,964,790,795,697,357,168,184,626,137,159,872,727,648,233,37,564,95,276,473,161,953,876,711,497,345,823,764,60,666,438,704,914,37,621,451,989,986,857,66,985,412,385,962,775,918,915,232,131,300,761,214,866,441,380,418,344,627,993,961,0,636,315,563,979,592,620,68,79,309,469,22,70,723,656,517,182,312,116,391,291,249,144,549,973,391,595,405,230,71,935,193,856,910,731,490,955,426,67,620,187,764,881,974,944,697,805,723,394,640,733,263,853,662,172,931,16,583,92,377,343,119,607,987,693,302,86,392,127,31,397,551,25,913,696,80,546,685,885,198,437,850,604,82,266,27,588,655,223,305,498,640,314,347,822,285,520,387,875,69,702,278,345,169,749,383,49,530,582,431,423,209,3,889,668,157,34,794,792,773,801,419,195,913,215,603,405,113,218,600,57,689,500,631,124,435,411,160,176,844,674,73,294,366,572,103,188,783,169,847,193,920,360,577,193,434,678,623,961,454,568,297,299,846,275,856,954,152,75,693,207,647,852,841,912,664,567,388,692,3,832,449,709,178,233,202,310,908,596,642,367,480,827,575,895,993,465,924,436,450,426,360,420,795,420,529,696,820,278,364,662,620,924,521,704,980,209,279,819,238,155,815,722,500,902,898,521,913,460,63,225,983,647,868,614,935,77,967,309,655,206,85,65,742,225,24,230,816,6,252,171,515,881,62,637,657,486,523,100,767,135,224,287,9,13,79,570,645,959,578,832,136,112,180,739,820,997,324,315,997,902,435,130,748,746,200,843,41,459,142,186,520,66,521,499,105,444,784,570,946,696,714,817,292,890,277,831,268,248,225,302,358,489,605,391,541,182,445,816,830,359,960,272,705", + "661,623,754,491,492,422,85,889,917,115,551,821,290,791,631,482,672,836,591,820,908,988,49,448,679,656,831,414,246,902,233,466,164,6,411,206,46,963,234,740,597,441,543,298,878,921,453,539,863,380,184,619,165,532,729,344,399,433,473,170,481,888,937,445,773,479,523,600,922,782,849,885,66,900,687,584,412,970,118,992,854,161,854,838,463,552,642,508,228,107,793,377,876,463,166,210,191,286,884,964,217,407,313,369,250,164,283,379,601,100,150,230,952,114,278,748,814,154,569,547,446,39,743,643,341,622,101,965,244,183,834,441,678,445,319,450,36,986,226,702,496,549,852,871,13,166,498,97,184,228,551,801,860,823,666,78,562,42,333,960,150,763,950,241,290,110,170,160,687,278,614,554,103,249,314,84,557,543,963,190,397,317,806,390,197,702,606,720,820,378,85,535,414,482,778,173,803,404,607,950,395,127,969,865,467,413,12,891,790,73,670,868,471,886,884,251,137,88,638,438,335,319,233,33,118,717,757,997,329,461,822,121,63,25,807,110,251,583,326,127,36,735,236,82,558,153,366,706,119,443,737,54,949,696,214,201,818,249,17,244,721,714,118,383,266,636,674,754,366,187,298,141,849,608,344,355,444,824,93,866,302,676,353,494,858,674,51,811,850,716,733,598,505,48,645,727,492,25,56,920,585,701,333,243,364,790,233,758,83,147,196,582,244,989,950,662,728,433,245,208,282,990,241,175,915,45,395,176,157,682,517,973,900,446,204,897,557,992,724,611,403,483,629,258,763,523,299,800,987,892,613,495,396,826,287,917,304,443,372,457,730,677,178,161,715,936,487,381,489,914,584,403,260,326,755,944,172,149,118,645,595,169,14,304,513,784,470,814,138,152,162,315,585,747,594,749,167,159,142,371,55,914,140,926,846,214,407,893,982,640,857,994,453,741,710,663,342,855,149,396,885,135,625,61,936,245,492,239,456,246,111,957,366,852,938,722,591,908,341,341,470,330,317,9,558,945,87,278,171,471,132,54,637,318,536,209,111,979,995,438,667,270,944,875,515,652,297,446,208,441,338,97,960,360,174,810,174,379,190,662,831,806,312,98,595,461,721,844,591,379,675,82,619,201,464,246,71,885,385,289,264,484,106,240,347,176,827,35,423,802,286,300,291,531,147,870,114,471,939,706,970,993,931,896,666,43,897,727,387,562,519,941,421,993,320,843,486,883,81,687,530,337,528,397,595,819,4,467,775,108,761,816,394,502,195,206,625,232,374,277,291,90,503,204,111,730,280,205,210,752,439,600,306,118,333,80,94,408,521,622,313,947,562,3,686,588,154,571,897,913,342,519,164,466,391,150,188,873,758,161,816,58,169,317,585,383,730,140,10,537,198,691,551,651,185,43,236,585,543,72,70,241,872,957,291,846,173,921,850,541,19,775,448,827,983,989,818,544,33,229,84,141,173,473,970,70,713,826,868,245,349,640,964,984,379,147,589,683,58,556,439,200,926,950,11,91,693,760,32,7,976,605,339,199,327,944,636,0,158,113,573,413,295,163,494,656,488,626,329,145,530,221,392,224,687,110,259,508,901,595,821,282,267,313,852,328,498,110,482,949,276,724,739,656,260,494,39,857,455,912,528,569,272,762,578,583,934,19,148,697,645,75,151,193,328,846,258,6,71,126,485,272,512,231,940,688,533,615,58,907,592,10,888,261,694,794,523,31,623,427,432,674,952,563,863,485,595,913,826,936,808,458,419,755,327,172,124,882,662,598,943,223,843,126,496,571,232,572,663,972,805,314,324,272,272,230,121,661,996,257,3,931,295,684,582,303,436,214,197,991,349,843,71,250,982,663,575,472,524,338,344,483,370,377,589,166,433,764,587,145,911,78,544,736,352,347,798,730,745,208,511,663,759,515,955,904,712,642,928,743,343,935,135,307,302,989,674,789,979,114,531,515,58,818,321,195,434,962,469,924,945,4,790,923,733,92,999,214,304,312,637,202,556,57,742,121,620,684,924,624,491,457,42,264,597,856,51,732,559,379,48,639,182,584,90,837,35,849,157,259,771,376,246,380,186,975,158,877,984,945,728,295,804,233,291,747,895,823,63,675,505,923,96,254,298,672,60,563,835,942,829,698,538,374,730,861,816,468,264,430,16,193,872,291,504,528,637,403,78,460,462,313,218,516,816,955,674,130,995,566,351,989,177,333,258,296,55,498,518,579,432,638,311,585,883,799,337,960,85,2,910,961,678,828,915,332,90,181,363,242", + "77,546,622,668,220,513,738,901,134,522,656,166,783,347,525,571,879,24,709,265,587,14,787,276,15,611,296,749,780,829,329,108,602,929,840,633,336,729,670,986,935,670,829,996,303,908,996,785,431,428,607,904,868,84,11,626,989,985,640,74,108,293,646,461,848,513,693,354,829,940,49,852,691,687,134,651,820,925,553,644,202,796,633,844,514,548,618,408,210,147,576,400,60,84,522,280,556,889,24,512,99,489,749,895,266,337,760,671,136,382,664,119,549,246,996,323,485,548,441,299,378,100,830,321,651,791,509,945,831,190,644,370,323,242,201,960,455,822,859,52,678,880,759,535,653,779,628,62,637,16,65,463,394,405,151,554,113,351,96,697,839,429,480,278,197,107,947,321,501,54,76,180,748,146,955,218,453,672,40,836,488,224,321,999,668,503,550,105,150,422,692,465,868,512,336,500,613,469,35,78,40,867,163,549,959,356,745,138,807,647,829,377,869,544,756,748,498,306,209,689,919,649,216,820,259,866,782,720,760,121,527,716,181,396,160,652,663,737,183,354,466,127,430,772,874,854,441,885,650,523,345,882,759,337,512,389,572,719,101,275,424,675,969,84,229,138,685,762,70,299,736,774,817,535,306,959,297,753,941,596,84,53,206,448,137,245,212,770,826,11,461,592,14,716,524,944,741,465,7,549,614,664,805,786,398,952,412,463,971,537,680,544,959,196,471,724,871,994,558,475,980,378,894,46,437,483,394,545,58,970,5,871,223,323,587,99,244,322,290,666,897,538,815,723,588,941,724,588,519,943,563,535,626,149,508,327,804,192,820,481,25,715,737,273,670,599,589,143,570,257,121,497,235,265,388,499,988,57,571,110,978,296,467,95,967,100,430,124,531,920,148,802,242,995,13,163,24,117,954,925,568,279,648,76,992,147,214,250,915,541,506,882,495,896,7,860,718,189,300,423,766,762,804,687,109,929,272,966,476,253,39,677,799,392,870,138,266,180,56,454,84,664,899,345,200,230,515,215,648,649,853,791,637,526,730,572,974,148,907,849,475,18,881,182,740,642,538,525,855,113,751,994,2,11,81,677,754,31,249,658,117,843,370,961,775,770,346,712,802,758,869,538,372,314,710,926,92,252,363,205,772,106,918,431,580,192,408,294,13,723,557,705,810,816,456,634,710,651,16,114,454,35,452,88,242,368,381,373,450,353,851,982,857,935,732,502,888,687,882,155,220,212,259,106,705,442,27,159,415,630,71,572,480,844,53,59,866,64,979,451,969,44,999,346,702,822,949,262,44,711,61,944,312,393,226,836,463,764,596,660,862,59,24,951,363,430,691,327,392,818,752,912,835,18,637,670,119,519,181,228,906,389,732,216,106,62,330,274,631,853,180,973,543,971,707,576,455,953,568,932,135,660,492,287,654,769,41,360,431,528,882,268,875,316,1000,302,944,349,968,808,999,418,665,7,225,196,224,599,438,938,850,326,31,340,240,296,254,69,865,494,864,691,994,514,621,504,485,935,442,725,550,140,851,452,530,494,315,158,0,888,754,461,74,812,60,643,102,584,59,567,148,290,14,604,926,204,219,799,585,180,166,242,695,757,206,530,344,317,292,853,221,744,80,908,855,921,295,526,474,388,784,349,18,807,49,836,868,144,122,312,237,54,789,534,408,626,282,586,648,144,354,168,547,27,801,213,480,206,191,359,482,891,615,319,498,561,747,914,688,977,716,301,401,538,68,650,429,384,427,791,993,204,281,40,855,217,615,274,666,295,797,21,738,811,951,553,278,698,318,42,972,475,999,157,559,558,776,776,723,947,921,836,619,166,754,421,235,959,119,318,500,685,627,484,571,369,58,273,480,260,534,84,478,881,526,814,726,757,410,504,913,737,239,799,327,224,197,342,117,451,562,485,768,477,684,830,903,763,466,766,424,974,882,451,147,280,453,839,835,520,449,261,367,326,27,700,603,515,28,615,802,480,30,146,537,564,272,678,111,641,984,335,67,234,286,426,409,900,58,283,844,298,38,500,396,861,16,998,429,90,542,56,924,560,20,984,955,530,611,583,441,198,12,882,531,270,430,42,532,266,619,995,388,674,486,702,733,150,61,572,536,433,340,680,979,743,134,897,575,902,252,703,237,117,758,442,181,963,466,346,104,584,765,600,143,575,334,580,529,270,427,610,683,214,456,718,564,737,297,832,620,741,10,399,106,94,211,73,624,827,685,844,189,482,499,13,26,724,646,739,914,988,759,881,993,712,531,114,110,209", + "28,492,73,139,308,339,357,657,698,184,849,802,528,6,376,362,84,242,281,821,49,702,560,291,295,845,73,504,33,183,597,897,632,462,953,828,826,852,541,516,894,212,418,370,475,553,844,916,75,353,526,906,290,628,498,353,425,842,220,327,865,969,602,887,768,753,652,120,54,87,931,868,624,388,268,178,449,93,989,396,672,694,244,308,259,26,87,590,298,582,926,85,973,798,604,748,558,247,844,25,52,646,70,21,115,801,522,634,345,400,402,731,807,180,270,918,585,972,669,158,370,413,328,290,596,723,167,401,65,888,24,322,480,722,943,94,151,920,919,291,656,804,366,979,166,351,400,404,401,467,213,737,9,752,571,989,216,810,810,951,72,278,671,37,404,544,528,325,139,198,365,189,496,536,756,565,407,125,577,244,135,555,827,401,788,599,806,641,614,165,621,843,272,724,525,420,391,524,284,498,311,823,508,234,173,764,99,63,841,335,771,48,192,610,925,623,880,392,500,598,423,530,386,61,452,216,306,420,368,732,56,22,559,675,314,395,950,880,340,123,409,812,671,39,889,761,280,509,570,3,816,188,406,957,294,93,19,569,2,722,869,919,120,888,698,613,530,154,692,799,952,78,193,797,726,829,101,108,263,46,37,346,768,45,286,951,654,531,604,722,895,666,608,327,318,687,882,627,266,722,77,389,296,950,582,444,879,841,376,769,127,511,409,298,610,980,734,88,685,722,439,106,301,278,735,368,21,475,17,798,437,860,947,780,144,704,350,456,956,979,672,967,645,541,954,246,34,48,48,708,772,925,453,146,218,709,462,542,901,138,465,178,488,854,356,945,965,154,803,160,710,898,746,935,692,478,472,206,337,577,339,999,94,926,372,34,866,914,821,333,938,305,696,118,45,897,518,655,798,290,901,795,600,377,10,157,634,45,608,24,531,504,119,342,68,997,173,494,303,381,195,769,89,546,962,816,623,49,585,357,619,442,102,153,162,924,269,991,775,210,730,782,491,847,534,889,628,74,294,782,711,509,476,6,190,503,43,709,996,179,676,753,897,77,360,783,656,739,785,718,782,926,278,383,53,534,791,344,102,749,111,707,873,56,144,922,458,955,439,96,520,155,263,12,129,306,934,593,447,955,934,996,354,130,262,761,748,264,256,957,226,82,152,66,974,273,879,180,674,939,932,729,809,964,659,238,576,92,407,609,202,218,212,503,546,887,85,344,551,958,301,366,525,26,66,209,626,129,91,34,13,487,356,698,448,376,227,236,437,149,779,423,811,627,651,64,437,755,560,677,253,990,87,373,268,266,422,93,332,103,442,565,110,632,857,504,961,183,458,576,535,927,900,296,50,107,267,802,385,640,214,688,52,717,626,315,966,669,527,264,955,291,267,279,302,365,645,864,641,532,410,38,415,650,422,793,300,768,78,679,281,713,303,42,707,566,160,332,505,916,48,249,870,804,223,92,968,547,36,536,985,872,606,902,448,152,343,451,507,526,547,176,337,636,828,908,832,734,827,481,851,510,315,10,432,94,563,113,888,0,651,516,620,496,544,472,620,596,190,574,123,60,656,384,932,405,174,280,12,716,802,505,988,845,745,649,538,458,230,406,438,826,327,206,147,619,783,635,582,603,650,326,43,398,586,385,853,67,417,680,389,384,222,840,133,783,404,753,438,324,328,384,193,584,171,21,969,961,39,103,56,221,280,890,212,493,646,759,558,728,358,111,542,688,412,609,543,142,773,620,548,282,525,776,201,327,61,211,294,837,30,771,409,463,714,95,955,982,33,379,37,794,447,159,100,30,91,945,60,121,497,401,304,208,766,262,684,142,495,595,819,387,894,795,888,469,742,958,721,554,767,166,978,218,646,598,724,756,699,501,592,855,596,396,716,786,656,78,726,883,938,688,150,18,598,51,531,782,45,168,25,767,396,555,949,808,72,251,862,811,718,236,420,959,700,924,423,311,329,117,116,195,273,630,793,36,517,347,798,826,900,347,937,246,630,548,180,445,281,501,530,357,937,132,9,344,805,975,376,870,239,636,702,143,34,935,724,845,677,156,800,307,170,184,277,216,42,389,944,223,152,147,211,214,435,701,198,293,432,212,377,177,731,848,157,193,193,973,114,415,771,28,744,570,595,781,99,220,498,466,97,979,534,870,687,617,474,819,818,95,316,327,713,571,694,961,437,896,183,651,625,867,135,209,674,532,827,346,331,848,432,952,552,17,666,502,233,958,558,348,645,58,635,458,11,675,791,478,259,343", + "961,794,622,276,770,453,148,257,672,166,903,766,473,958,504,908,342,552,454,566,696,745,494,32,95,454,994,320,119,374,3,731,597,462,176,895,320,169,136,381,592,24,323,740,827,781,882,287,441,467,945,447,483,469,253,853,824,410,670,171,649,983,847,630,865,302,395,251,976,949,901,807,315,123,334,906,589,159,7,553,425,416,304,739,198,812,879,531,366,901,74,776,683,704,619,192,935,422,595,887,848,601,837,505,819,358,789,621,683,305,671,144,896,911,745,852,250,314,641,728,779,816,134,906,693,949,94,336,761,784,417,125,948,218,860,147,279,228,402,880,528,300,200,254,139,906,414,454,349,831,958,326,537,822,744,607,175,716,275,600,938,878,370,354,25,837,48,464,318,491,719,494,560,251,919,886,361,213,690,594,112,443,362,522,988,527,760,853,759,630,414,210,773,761,490,481,941,408,993,841,621,293,132,167,365,985,444,352,159,386,97,950,870,365,743,563,972,394,768,671,775,501,436,190,928,603,681,417,559,226,253,891,72,526,488,1,801,323,213,808,210,183,820,356,799,79,384,350,871,222,241,518,662,528,264,838,627,689,756,616,935,417,95,696,384,292,684,715,56,249,730,552,970,280,47,106,878,740,304,974,369,134,868,134,242,679,56,948,224,751,754,779,459,767,929,576,941,194,207,629,704,42,184,494,729,101,267,258,622,246,883,122,119,419,355,299,852,908,108,613,87,145,220,619,678,742,65,800,312,776,38,461,712,455,283,739,335,739,578,847,792,698,193,343,381,206,661,126,713,946,9,283,784,723,684,505,35,837,551,785,838,904,33,773,423,58,28,646,880,798,937,467,142,126,412,49,100,573,782,674,557,645,953,647,437,624,814,566,689,782,831,794,379,838,971,797,981,40,735,140,536,682,392,558,217,526,50,691,518,599,928,718,443,720,23,171,222,964,840,620,464,650,113,220,939,289,618,616,262,763,173,638,259,188,862,707,669,726,738,119,297,349,900,321,692,529,590,8,786,847,635,555,493,410,932,126,39,961,534,668,804,639,273,677,175,329,352,181,716,671,913,156,347,62,518,267,341,692,363,567,578,249,366,296,673,299,221,228,52,161,816,31,781,569,424,410,498,479,10,756,14,454,493,745,341,100,472,445,362,976,919,12,497,739,288,610,7,763,364,404,942,209,998,722,877,576,954,877,84,100,426,983,75,883,627,972,116,393,461,132,701,597,567,770,954,565,917,758,392,994,378,629,520,736,941,184,588,112,27,166,838,859,701,989,302,904,733,281,98,29,931,802,59,120,132,461,759,806,439,871,957,810,779,893,972,361,759,185,123,92,759,804,623,352,870,509,261,711,132,340,503,216,584,495,44,368,273,947,714,925,56,164,857,394,593,791,456,476,22,372,548,827,518,475,278,851,123,929,468,228,642,17,420,11,882,119,678,488,448,51,24,29,831,793,220,436,954,735,823,261,918,371,119,676,726,288,974,18,45,401,833,530,236,565,243,249,104,815,569,383,513,686,372,780,605,469,979,573,754,651,0,741,166,399,176,827,875,268,714,261,484,983,984,165,243,574,246,900,831,957,815,271,538,953,664,937,608,230,679,914,341,440,161,244,800,859,864,462,969,307,957,124,243,10,854,317,678,341,12,517,990,567,251,739,255,79,959,880,393,439,109,9,812,464,580,805,528,893,458,594,160,559,444,578,718,44,457,515,364,917,273,197,410,751,808,643,585,178,905,90,995,11,449,593,101,476,834,338,440,617,140,972,422,309,241,356,114,815,600,766,929,367,710,299,690,825,150,510,918,605,350,825,530,590,646,711,122,123,640,729,786,489,664,718,242,807,997,96,527,642,657,225,771,364,293,205,798,902,881,365,333,170,918,844,771,484,529,728,546,914,26,622,163,139,597,43,654,38,769,206,268,609,946,775,513,220,658,99,132,380,27,458,934,304,503,616,570,910,660,733,945,698,271,339,154,469,31,161,154,690,687,103,904,797,947,236,283,571,110,594,968,99,56,925,493,244,944,320,638,838,691,870,153,65,299,306,66,576,366,466,941,642,629,378,712,507,177,984,94,463,273,394,117,152,891,911,162,899,890,863,123,916,735,381,618,546,94,680,990,306,107,102,882,744,366,995,476,235,155,508,769,123,720,786,848,250,679,785,655,899,890,942,673,798,951,132,810,396,386,768,479,314,536,147,940,362,922,869,767,162,301,774,286,69,52,259,341,683,3,665,428,80,886,454,517,364,825,224,417,964", + "222,179,190,678,832,676,343,545,173,873,467,320,497,627,888,292,438,778,332,988,710,309,530,980,820,294,485,229,444,364,721,206,654,354,73,7,219,385,509,373,404,157,677,662,613,771,319,490,703,1000,476,129,491,94,403,173,258,447,726,672,878,977,873,462,683,486,740,396,89,934,165,409,891,128,951,439,795,31,443,557,279,36,803,792,510,264,325,696,343,115,963,12,677,757,785,413,872,607,824,415,893,154,297,712,377,837,759,666,612,328,647,246,943,694,426,345,97,374,295,773,641,685,955,919,383,445,898,229,750,38,48,752,346,642,27,958,832,346,631,992,124,491,977,374,918,310,693,578,644,47,732,211,128,636,570,848,262,599,646,878,485,657,878,6,248,19,839,795,347,470,823,233,862,142,692,842,513,587,417,758,729,933,424,842,966,974,551,5,427,332,822,476,752,15,224,66,345,212,429,294,911,528,531,742,436,857,77,585,903,225,147,517,430,697,99,679,810,426,853,99,762,148,564,217,166,557,444,828,860,115,641,535,460,745,901,155,751,876,437,178,926,883,909,530,34,666,121,827,666,137,735,964,195,646,885,883,562,228,216,874,310,903,91,812,955,411,443,68,479,974,953,224,829,634,325,392,165,407,71,771,355,398,21,535,692,621,410,781,555,744,332,920,552,681,717,425,860,27,601,537,746,837,343,884,623,626,589,484,126,803,947,142,704,474,306,319,420,395,388,767,785,526,76,138,974,276,412,315,551,54,622,69,217,390,716,699,699,324,757,611,704,46,596,486,912,63,812,153,112,199,49,463,280,232,858,180,637,425,583,199,591,76,991,8,17,327,141,23,870,965,295,206,486,94,239,444,520,744,512,180,496,147,704,52,244,74,855,717,636,607,853,403,742,184,452,931,798,592,502,258,186,187,132,579,531,687,278,929,358,693,985,462,211,632,101,651,478,460,508,409,937,104,359,340,456,24,732,41,629,686,511,46,479,298,285,611,736,834,536,724,493,5,607,195,363,767,295,56,803,939,985,62,275,66,138,931,792,943,826,396,441,454,817,520,980,512,867,683,867,412,611,706,72,666,345,885,88,62,362,100,767,793,379,126,60,245,566,132,373,597,985,195,314,595,393,195,793,487,121,208,747,92,284,51,963,189,48,292,943,602,756,106,118,904,13,617,346,337,238,589,715,958,113,808,692,190,423,134,382,251,820,748,430,566,642,188,373,182,107,345,343,475,75,965,68,721,743,558,586,654,821,29,937,874,942,639,577,444,519,303,855,654,3,494,940,521,353,622,564,285,469,851,810,933,81,881,295,62,64,536,994,96,558,701,736,882,131,60,783,444,564,748,41,678,762,789,310,750,797,916,872,414,480,690,37,614,698,949,175,574,632,929,573,324,299,177,366,275,100,446,607,399,13,626,623,999,401,459,839,893,958,901,120,758,117,809,296,654,459,75,493,873,648,662,862,670,308,517,716,580,820,756,614,664,858,4,836,630,221,813,959,537,191,266,983,9,875,74,849,837,582,125,219,664,823,721,592,413,461,516,741,0,660,127,33,35,173,815,839,711,513,806,628,933,427,293,984,208,195,118,90,625,636,933,604,104,231,493,442,791,211,484,740,668,133,399,997,242,164,949,276,520,827,290,514,175,62,154,190,36,647,622,453,729,407,120,863,744,476,410,591,927,935,498,605,808,754,97,499,266,956,873,798,309,515,354,442,97,833,409,197,956,340,960,716,890,12,341,137,251,480,293,81,899,700,874,898,763,222,823,742,862,281,354,541,459,239,449,270,652,376,171,507,778,126,496,426,88,306,180,473,819,554,239,537,78,808,139,159,69,133,992,839,639,466,935,437,217,450,515,258,671,612,100,518,202,858,450,456,382,982,367,921,551,149,243,633,427,230,733,132,10,797,549,383,29,450,89,429,850,272,82,545,542,749,936,348,778,721,173,285,595,889,314,239,172,676,948,733,243,715,626,785,462,264,88,142,734,653,401,558,365,484,81,537,960,534,114,221,262,837,631,689,593,461,350,279,765,25,182,679,593,845,868,485,524,90,75,805,644,204,5,152,658,982,652,712,883,756,578,969,400,942,874,378,917,7,473,701,200,560,287,276,122,506,911,198,689,712,593,351,966,435,946,782,993,992,449,548,718,255,923,931,700,283,455,782,191,534,531,148,632,163,291,137,978,718,738,282,629,963,986,445,850,57,602,839,946,825,436,728,784,847,649,55,547,854,855,195,998,661,1,153,875,181,682,772,138,516,929", + "953,487,271,673,239,262,992,813,629,566,175,330,432,293,435,860,351,487,660,460,250,975,348,667,90,12,859,335,710,527,279,148,128,741,13,57,765,398,700,702,582,969,96,706,825,148,639,991,669,352,977,734,795,566,46,555,317,598,826,374,191,696,564,944,939,396,788,742,949,365,40,529,363,207,48,32,608,552,184,237,530,239,472,925,294,708,724,261,554,128,622,85,159,565,985,55,160,931,499,303,112,667,539,737,477,232,853,363,530,276,421,482,830,362,662,599,553,199,354,10,718,318,854,584,181,960,237,337,802,696,455,415,639,588,42,72,856,412,662,350,883,929,767,610,594,994,294,436,367,802,248,331,836,727,553,638,844,370,783,60,624,253,507,391,683,33,138,381,830,902,110,622,263,98,409,496,737,928,732,625,596,56,341,261,140,767,431,377,993,979,735,109,784,570,823,892,279,451,520,805,604,749,349,494,787,197,858,530,988,216,902,958,907,598,120,573,294,744,701,640,47,515,870,174,732,167,710,292,63,665,978,179,228,184,266,209,99,640,679,167,903,304,545,200,586,377,394,481,907,692,966,107,210,375,594,277,501,959,447,747,708,677,390,94,556,299,560,713,374,638,605,778,423,549,940,95,218,33,932,565,975,221,797,915,574,749,50,1000,426,442,901,466,14,844,214,772,13,122,307,621,12,867,75,343,85,715,95,485,841,134,870,953,80,582,353,645,366,803,317,582,883,300,877,39,86,739,241,454,840,867,907,954,770,102,739,415,923,7,993,516,663,326,418,248,493,242,465,991,748,337,310,133,512,440,791,257,929,611,16,186,584,744,126,149,254,681,655,752,699,999,656,98,25,235,847,242,522,745,914,514,973,16,333,330,280,471,519,322,856,364,222,21,616,482,539,740,658,740,89,959,144,516,519,37,530,66,371,116,728,524,783,781,34,729,915,994,831,312,318,781,387,517,418,772,659,791,677,529,372,21,913,985,614,980,968,586,979,217,256,184,780,31,559,680,684,261,664,425,293,952,150,692,223,905,246,346,848,250,186,343,469,721,486,88,245,106,265,412,561,551,87,278,171,672,778,385,431,510,489,268,512,895,106,581,671,824,526,914,574,735,776,208,381,163,10,463,194,736,937,514,333,309,282,348,30,2,152,27,526,686,781,932,336,483,85,471,134,544,209,693,768,837,572,959,341,878,871,584,298,271,236,366,286,29,56,462,232,260,983,63,728,847,129,738,822,748,668,856,326,142,839,36,75,709,411,630,132,26,227,501,534,497,198,907,149,442,411,860,175,501,462,24,452,937,575,33,697,644,941,190,24,230,723,213,361,358,504,538,479,952,126,445,13,655,356,756,341,248,225,119,826,713,88,309,77,945,39,417,820,859,744,498,340,547,73,984,725,547,98,475,236,810,963,766,630,889,60,792,628,4,91,493,1,42,20,838,191,281,788,491,170,166,599,792,529,658,400,745,447,219,789,82,345,841,702,807,939,838,546,765,287,470,944,90,760,612,617,26,138,98,583,38,575,353,25,644,620,295,74,620,166,660,0,354,394,679,163,130,341,415,736,942,465,768,388,711,892,413,127,158,797,185,89,736,588,803,190,898,94,96,683,618,470,264,612,649,244,821,441,708,208,588,891,758,723,927,949,20,23,597,704,339,298,338,161,378,217,660,956,517,210,709,251,882,874,551,823,254,859,262,203,689,374,909,257,590,219,418,695,120,38,169,349,814,81,939,71,676,314,584,355,743,951,51,281,464,738,562,58,169,29,552,318,173,657,338,602,156,117,758,44,544,602,543,974,908,317,865,544,806,342,342,505,477,387,596,811,496,84,819,758,4,258,912,70,383,889,305,159,240,739,699,331,756,35,596,594,493,483,437,668,528,36,864,59,146,38,21,949,359,945,313,138,821,552,415,458,232,172,991,157,800,706,859,113,292,929,658,637,337,482,832,656,243,150,949,397,693,273,711,94,94,636,253,862,915,616,49,981,931,341,625,49,212,925,636,963,875,984,332,284,734,404,515,626,943,251,478,853,477,263,488,181,502,143,977,654,181,190,240,18,865,737,974,614,689,451,547,835,581,115,986,140,386,26,225,247,820,324,645,277,729,1000,890,605,319,146,227,534,841,927,528,752,979,752,459,683,296,650,589,374,577,160,102,879,833,317,920,819,432,801,721,873,488,188,275,714,227,18,223,86,443,664,527,475,260,435,747,86,877,70,26,940,913,110,988,851,423,525,755,250,989,750,502,272,591,101,155,523,803", + "604,555,412,94,828,313,903,949,359,122,883,449,853,17,612,577,217,22,947,84,303,6,120,485,68,393,654,234,610,80,397,448,820,621,74,957,28,120,375,551,471,20,516,736,564,295,635,100,318,309,741,411,912,821,390,399,71,387,716,711,707,643,75,118,793,453,3,137,55,316,969,934,971,994,962,389,916,697,416,962,502,173,63,263,601,406,271,647,868,829,302,69,456,771,402,64,956,18,282,650,190,757,208,154,985,851,932,875,536,984,802,879,631,561,87,234,530,719,997,262,636,642,70,963,735,34,353,181,239,303,407,349,223,6,249,174,21,803,612,897,672,150,554,250,448,503,146,675,14,394,120,300,327,44,799,840,76,342,654,383,719,905,231,783,308,478,506,48,203,729,106,578,304,234,983,920,737,223,749,714,303,757,853,957,759,73,941,272,521,505,419,195,720,153,787,886,536,472,571,298,565,451,87,788,189,954,852,305,803,19,353,834,394,70,142,451,863,943,2,358,819,367,690,231,555,701,20,48,884,250,938,636,946,389,449,439,323,70,428,583,543,235,399,606,248,337,67,681,713,319,867,589,458,568,334,589,473,247,492,686,571,826,495,605,155,467,643,478,810,723,17,18,606,962,693,201,635,902,811,358,440,901,954,531,964,850,454,443,429,762,483,4,384,751,997,266,631,312,461,677,181,160,293,384,811,965,214,278,714,749,724,483,552,749,670,354,545,885,180,591,478,789,639,466,333,40,986,971,817,891,391,4,600,311,427,983,195,660,242,194,226,262,42,182,347,103,284,288,55,78,860,542,915,622,23,454,860,275,781,691,37,638,160,379,35,134,241,325,233,5,440,766,517,272,865,5,103,525,896,182,113,484,347,824,595,559,666,624,389,321,758,196,161,785,54,69,537,322,905,950,696,352,82,138,474,104,708,495,238,75,606,781,631,260,267,448,391,36,39,97,878,449,765,898,539,718,674,508,322,540,807,257,289,714,894,960,682,290,241,144,560,374,752,818,280,354,940,669,679,444,771,85,40,12,781,638,739,566,39,611,129,424,805,554,572,840,385,415,66,711,372,257,264,57,953,446,605,635,487,734,421,552,760,904,34,526,973,231,172,444,589,418,916,483,394,351,45,661,658,586,886,758,648,724,994,974,973,347,603,593,652,650,697,401,18,693,613,762,150,816,863,142,853,230,740,41,103,224,365,275,841,696,655,560,491,907,613,495,570,394,452,673,720,494,224,126,458,676,663,116,616,368,807,352,308,646,61,696,261,355,837,776,715,898,376,102,783,823,11,292,585,871,249,427,597,859,916,792,503,939,645,386,422,723,103,470,190,28,130,172,274,399,656,240,537,293,393,144,53,371,249,796,883,771,528,538,508,183,703,322,124,917,558,487,925,881,757,205,67,139,223,268,624,249,420,754,997,169,513,328,813,112,736,379,250,650,340,827,160,268,467,165,75,919,268,654,178,554,663,451,602,930,458,482,718,354,637,128,392,489,784,920,913,812,974,972,819,506,32,455,329,226,898,660,749,896,68,163,812,496,399,127,354,0,871,732,190,651,707,374,543,991,165,613,875,352,20,365,295,416,241,468,689,48,244,642,847,991,243,512,128,863,611,417,163,237,348,186,910,594,531,164,372,120,739,997,644,180,166,866,840,362,614,30,429,697,200,494,918,782,29,218,458,478,846,688,558,133,713,343,161,134,873,806,585,357,782,130,108,489,788,223,305,690,316,803,58,821,435,993,693,22,978,761,49,484,419,299,961,242,85,497,568,57,425,341,91,7,457,599,810,136,730,268,233,986,994,808,988,950,658,879,239,981,739,12,268,617,657,154,238,908,488,719,507,435,731,109,324,243,128,34,912,785,882,417,16,506,510,273,736,865,247,457,592,500,788,589,571,394,882,164,573,18,900,820,626,332,400,796,792,647,864,176,169,483,411,259,617,345,19,309,411,667,592,268,594,607,721,739,280,73,184,705,512,241,814,344,578,107,28,756,490,247,320,379,732,210,462,6,394,655,103,482,992,591,513,822,44,242,585,27,997,654,605,661,287,155,38,451,151,880,198,351,748,107,852,988,806,69,240,918,862,401,178,426,250,685,82,237,605,232,947,764,113,318,513,655,244,372,149,559,191,315,867,25,724,785,562,528,141,572,526,532,384,539,719,877,948,356,45,441,843,839,565,849,923,67,698,832,584,760,585,355,220,720,134,197,951,798,722,880,652,330,46,289,746,942,889,857,680,282,903,229,636,5,254,469,507,292", + "611,710,275,764,764,924,916,616,506,490,697,197,146,672,155,532,942,288,296,859,396,275,322,377,112,562,312,1,28,503,262,849,185,481,31,203,502,595,441,60,201,993,856,312,193,613,568,229,917,698,629,178,244,919,230,105,458,257,320,640,352,155,414,211,155,649,986,397,276,601,166,251,697,150,781,691,113,553,783,867,210,156,84,312,64,998,905,364,925,908,716,222,94,859,41,565,94,93,131,366,57,499,363,552,426,818,871,721,557,648,389,846,246,365,333,577,81,520,518,625,936,237,220,247,232,168,541,259,772,940,221,583,482,497,657,420,555,67,40,232,984,762,47,136,24,409,711,88,50,396,196,565,727,609,2,579,661,855,889,475,139,767,537,796,876,225,629,13,505,235,437,725,15,128,5,400,76,105,307,352,836,825,209,488,932,21,302,926,387,651,775,185,57,514,491,841,986,131,165,601,968,442,83,94,947,935,762,368,536,178,312,957,531,542,667,313,989,549,712,686,529,521,454,727,831,313,14,218,902,780,410,434,464,659,611,638,38,101,371,834,653,241,131,600,349,697,336,769,90,184,709,555,480,369,726,39,618,285,993,627,15,681,382,445,657,822,864,606,870,101,623,413,927,948,203,53,955,400,713,410,930,549,761,649,451,956,219,993,16,887,78,497,931,507,793,974,95,853,171,749,416,701,236,431,374,48,144,642,156,250,418,735,24,739,483,235,990,407,46,65,560,791,289,102,487,560,950,589,321,63,375,357,913,768,124,760,166,794,632,654,936,678,618,12,650,693,545,19,680,12,895,878,137,524,942,963,533,972,681,598,407,415,815,100,691,24,910,718,351,771,703,583,398,511,212,297,597,916,636,917,889,527,532,509,787,450,365,956,560,28,30,683,677,5,412,842,867,432,723,978,550,228,229,588,823,957,69,155,641,245,904,876,723,345,140,855,456,970,96,5,338,223,708,43,473,279,290,377,26,652,182,795,156,529,556,649,116,501,688,492,161,12,871,805,948,414,559,990,573,604,549,826,216,947,677,613,816,123,194,579,668,832,659,226,176,326,638,2,523,670,421,231,722,399,860,70,958,774,967,928,813,282,491,268,142,917,45,946,849,739,881,330,280,207,125,141,685,941,427,544,650,805,751,22,606,297,681,718,474,864,384,539,668,624,611,496,574,406,425,153,996,962,96,86,118,796,297,330,104,880,820,729,629,8,223,343,84,414,526,427,732,757,843,719,229,874,674,56,832,612,126,239,63,552,257,442,39,990,443,591,521,599,379,262,628,631,467,563,874,46,685,598,298,630,58,318,708,101,856,154,28,583,257,889,298,868,576,327,142,913,397,453,347,367,743,901,963,394,51,708,703,996,814,255,539,143,571,85,675,955,9,711,846,596,615,927,772,86,48,619,405,434,455,508,999,375,429,315,102,265,47,160,824,869,790,419,926,581,415,157,518,239,393,228,185,483,747,885,422,146,556,689,582,810,220,55,612,57,900,523,285,968,69,628,504,332,127,91,266,406,822,614,360,314,716,841,79,494,60,544,176,33,394,871,0,234,445,156,134,486,742,833,331,978,503,557,369,2,621,220,377,528,154,269,53,72,749,68,532,478,438,412,667,881,931,577,730,787,678,619,868,16,805,247,244,888,326,369,200,208,436,148,878,639,987,47,965,343,225,110,978,169,954,810,667,413,209,409,427,906,736,549,70,776,839,97,394,836,521,784,577,991,367,888,464,796,723,705,8,608,529,760,974,859,521,522,262,99,93,110,4,812,104,199,962,985,706,464,839,265,982,478,855,362,135,841,862,28,497,917,113,678,709,46,736,907,756,270,510,830,615,439,2,742,824,647,767,751,254,498,832,471,712,460,757,485,646,551,210,222,968,897,642,682,989,15,329,464,777,295,355,285,954,743,986,192,670,636,299,898,553,869,827,940,215,245,778,714,426,158,756,703,699,395,832,194,587,92,713,928,668,237,59,764,293,418,716,255,208,721,285,5,64,43,824,211,256,276,560,437,739,307,675,7,978,135,564,116,135,309,447,816,285,470,421,262,737,206,738,79,819,730,572,304,286,213,454,156,240,46,919,67,809,758,876,198,664,956,686,633,820,72,670,734,506,86,677,715,24,884,828,657,754,468,755,15,268,17,330,997,25,188,593,16,533,676,101,418,979,716,618,951,197,447,535,911,471,268,951,384,566,898,239,976,776,593,404,756,765,452,556,172,110,747,136,187,244,418,879,535,677,263,613,956,271,736,274,547,691,506", + "111,215,427,731,273,444,982,465,410,64,274,832,909,771,147,685,273,773,17,345,40,706,961,884,246,117,414,850,366,938,438,507,737,902,911,321,260,408,622,167,786,29,46,728,60,967,911,83,762,359,2,7,520,875,979,989,914,322,419,776,214,992,289,337,743,444,597,909,197,709,258,645,817,161,140,152,321,454,199,868,231,178,5,938,582,418,512,579,324,207,295,525,657,578,278,795,865,112,288,807,597,697,714,16,796,683,950,548,35,160,220,555,700,357,464,931,410,901,55,687,424,294,329,507,942,822,985,329,913,513,419,689,387,781,968,635,513,53,362,213,672,100,464,248,863,232,384,474,885,666,930,370,677,727,171,360,379,199,177,511,246,174,514,354,54,763,760,808,163,788,569,781,861,443,794,417,792,452,708,565,741,735,200,802,539,696,409,680,204,520,130,96,369,388,370,217,775,77,934,564,489,141,976,835,962,207,845,570,508,594,417,945,604,712,111,430,111,709,599,299,341,445,63,662,518,64,369,933,153,571,623,155,203,554,92,584,473,4,87,732,493,638,622,134,143,10,137,317,37,316,286,794,188,408,226,937,132,555,374,903,682,951,914,959,581,403,850,173,766,69,7,191,784,175,772,756,523,932,216,877,514,216,958,352,308,101,931,281,900,899,661,961,714,845,340,895,386,868,865,451,687,841,276,200,944,522,784,41,498,914,145,353,537,423,341,628,597,372,863,837,754,167,60,280,188,360,388,916,510,710,252,175,236,130,792,948,348,382,431,895,99,59,434,317,742,487,953,789,100,943,510,993,546,55,413,67,377,977,435,864,806,577,741,232,191,244,652,596,858,187,421,549,249,99,858,293,426,457,172,34,381,259,899,928,550,684,568,855,757,372,310,871,1,679,353,99,474,118,717,297,599,942,208,207,42,108,42,762,210,387,154,858,765,677,455,685,912,795,86,78,113,732,968,956,355,69,902,956,31,594,740,277,922,192,26,428,388,520,196,977,867,853,82,81,972,310,486,341,115,824,192,194,857,362,367,713,555,973,149,885,311,735,345,244,504,949,877,368,26,62,244,662,630,803,425,268,487,54,111,567,433,894,363,881,970,888,659,257,218,824,272,666,588,792,62,990,291,419,260,340,748,638,968,576,638,488,692,909,506,95,958,509,682,392,233,109,941,420,625,418,753,279,355,562,490,412,312,521,98,890,387,220,369,567,469,852,529,180,872,221,423,878,755,245,225,122,321,64,836,575,419,647,464,263,777,942,590,106,757,669,80,244,55,508,412,274,506,24,788,57,623,903,559,605,554,859,236,913,494,45,488,452,218,219,210,170,478,577,748,604,244,256,755,402,771,67,401,172,976,70,342,117,243,316,802,331,881,3,318,957,390,486,125,698,738,721,491,968,194,653,609,858,9,866,300,737,789,720,140,388,104,672,695,792,664,236,68,177,87,422,426,963,914,821,370,281,247,510,195,135,824,716,82,203,746,312,822,768,505,412,211,295,571,894,736,926,956,395,928,880,29,705,512,507,782,923,309,656,643,472,827,35,679,732,234,0,722,648,156,771,224,300,317,801,960,117,791,921,383,833,283,221,641,979,796,469,396,475,595,808,202,546,702,99,157,735,597,244,484,554,361,478,1,519,386,834,191,561,269,442,230,166,248,971,788,469,388,234,505,222,509,150,856,719,457,583,130,147,504,298,810,473,757,42,760,819,437,180,974,540,830,776,149,283,42,106,491,821,203,383,249,809,593,482,625,65,729,198,861,59,855,365,416,377,47,125,351,480,855,676,800,873,158,995,461,338,172,918,849,855,775,809,761,371,813,947,554,260,720,387,78,431,39,358,428,16,114,511,792,121,73,525,172,572,46,310,366,967,157,665,490,378,851,936,864,443,14,859,123,133,361,871,262,80,629,857,364,924,273,741,281,363,63,967,583,72,374,749,531,930,401,220,850,113,856,325,877,602,591,790,281,989,82,36,653,206,858,139,87,440,784,240,373,359,885,952,281,514,680,306,547,916,252,713,217,316,218,6,818,105,571,221,192,4,674,347,902,260,298,975,105,130,20,193,785,50,299,668,627,506,544,129,888,511,398,753,84,987,871,482,93,130,996,240,627,238,946,91,556,288,794,398,875,665,791,361,470,525,592,916,624,898,522,788,606,311,695,501,396,108,292,945,216,521,69,843,710,250,743,198,702,652,29,365,596,978,595,437,382,437,528,429,630,746,842,359,980,677,596,755,793,785,751,652,322,335,876,948,728,117", + "296,94,398,778,149,115,428,710,86,682,306,226,192,159,401,844,315,870,926,117,10,165,269,40,731,90,386,518,156,970,181,26,273,942,893,944,446,619,508,20,918,690,416,967,601,801,520,814,502,766,366,554,949,588,881,450,327,653,136,875,43,721,759,587,673,324,565,545,79,920,837,749,52,783,265,347,992,943,94,136,620,307,181,367,893,968,885,662,480,688,530,762,486,286,132,985,827,939,932,368,718,70,115,190,643,65,533,70,621,110,309,899,863,639,139,685,619,549,218,260,103,434,45,309,23,231,691,65,279,589,74,774,161,261,846,556,707,927,281,64,71,73,508,710,365,78,951,354,87,71,409,383,912,246,714,470,187,733,85,206,14,529,395,840,104,508,419,583,182,491,982,594,815,766,880,842,23,412,523,648,562,192,205,721,843,221,741,176,9,965,953,859,108,721,40,32,7,262,636,333,799,840,410,205,71,913,807,883,734,612,703,162,62,672,622,976,593,830,290,462,644,697,109,29,364,753,466,126,288,840,325,481,292,700,525,646,320,94,587,860,245,252,610,212,996,503,506,297,581,34,959,759,393,47,933,161,164,246,226,269,855,964,81,220,128,569,804,35,247,585,247,649,497,216,489,733,721,675,292,193,340,873,881,643,587,387,880,508,785,606,928,12,480,789,102,481,260,786,690,606,112,329,17,259,789,342,302,172,266,612,215,658,809,382,252,916,643,323,979,472,200,686,894,231,508,258,663,736,469,3,794,527,261,560,457,262,139,229,167,471,568,998,610,102,471,225,662,301,333,129,103,974,325,857,127,18,429,949,15,901,298,933,604,890,743,71,591,74,263,966,974,800,151,603,496,257,133,349,677,79,624,754,615,886,507,185,964,588,855,511,715,575,587,734,487,746,982,833,680,808,682,897,996,840,165,266,195,293,850,46,599,35,790,529,850,671,994,635,242,991,511,561,924,130,148,918,248,118,81,392,473,661,44,753,172,858,781,310,349,461,186,882,977,364,601,807,784,444,511,125,652,115,553,605,289,431,584,512,85,395,379,221,830,27,678,731,204,438,406,470,429,86,170,72,868,434,155,631,723,850,542,983,280,960,931,202,683,860,69,739,396,688,592,848,465,444,813,614,466,824,729,526,547,88,291,30,20,218,869,141,828,512,330,442,479,382,573,201,633,889,249,855,824,414,23,928,177,294,15,57,486,302,161,785,373,206,196,816,360,916,948,293,486,992,659,24,181,282,244,152,737,722,824,454,817,30,459,730,11,886,899,593,553,411,895,692,73,846,275,846,152,145,270,207,780,175,421,19,407,306,129,887,378,503,654,581,236,621,566,332,609,920,632,620,103,890,781,277,593,956,100,510,636,440,776,996,2,543,528,565,590,81,78,432,165,516,539,328,636,659,8,790,529,778,729,210,165,764,684,975,993,289,565,781,337,417,966,647,74,308,720,871,766,264,664,984,366,14,976,451,407,732,499,281,400,295,722,712,424,901,322,6,609,202,343,848,513,42,244,682,988,969,824,29,640,647,469,488,102,620,875,173,163,190,445,722,0,571,197,419,755,493,192,774,964,846,138,140,173,247,164,609,223,906,544,688,582,612,803,517,251,884,78,112,627,709,441,724,352,165,449,9,640,585,226,58,203,564,932,470,754,76,224,945,343,564,430,262,146,876,296,581,596,674,352,638,133,491,179,157,225,460,755,668,565,276,312,130,575,416,140,308,500,867,929,143,634,853,77,641,590,328,797,172,292,552,855,430,494,445,751,278,449,825,420,649,153,974,552,602,169,326,876,44,802,588,35,953,566,159,587,910,23,133,164,993,202,656,752,155,4,29,151,850,841,869,875,236,636,434,320,170,79,438,546,794,515,11,959,902,236,710,932,453,273,557,750,977,570,55,732,922,643,598,312,838,753,914,442,650,933,224,954,51,835,820,381,162,956,840,898,736,606,496,216,776,989,177,424,282,491,270,986,670,656,708,951,917,664,611,983,467,250,582,403,339,428,927,460,869,378,401,592,100,756,857,957,560,958,533,219,640,19,297,252,111,492,866,638,747,429,704,928,21,294,811,931,238,114,796,545,144,780,181,635,407,505,881,992,119,637,136,55,330,550,523,87,37,89,758,633,38,861,132,276,589,484,335,14,276,233,118,976,236,24,785,778,229,988,977,319,60,586,219,811,545,482,719,503,367,855,576,527,41,748,439,696,6,863,345,725,892,856,593,619,489,162,51,50,787,961,231,271,711,700,986,876,261,482,254", + "784,707,206,196,191,895,271,828,648,794,415,377,965,788,993,409,128,339,182,890,933,461,437,896,598,258,226,286,391,149,218,656,726,941,521,720,518,471,146,279,951,553,335,567,644,39,260,844,887,260,623,774,247,825,260,231,24,433,436,832,883,994,930,333,970,613,422,760,717,650,597,97,690,405,681,737,919,243,632,584,215,405,98,98,7,859,812,619,352,518,270,74,449,138,8,808,183,66,862,19,97,208,974,834,457,510,622,997,609,208,403,966,612,981,516,56,822,141,583,187,925,384,481,365,491,42,803,59,605,791,547,952,720,641,437,468,925,213,697,762,362,337,570,709,666,738,335,291,285,267,983,205,714,177,581,554,893,569,345,98,513,177,795,823,87,233,246,998,585,478,916,754,876,448,847,334,245,937,108,497,220,872,132,827,124,616,648,772,640,572,667,613,315,92,683,940,756,447,899,692,347,50,457,981,520,32,773,41,12,179,21,823,832,127,915,214,383,315,121,661,236,480,623,352,18,569,273,355,713,689,785,93,475,379,667,768,63,70,951,922,929,497,436,894,637,87,492,609,222,177,724,682,888,887,46,492,531,665,22,164,214,278,360,216,317,526,763,325,397,576,623,461,501,91,3,382,266,504,349,459,491,841,307,941,491,713,143,641,249,141,348,205,879,174,593,433,3,836,521,629,225,396,340,683,139,219,909,324,931,723,732,635,736,971,814,346,517,721,353,486,656,635,248,890,567,242,460,874,117,659,322,690,270,21,280,343,517,640,395,539,38,424,144,996,927,836,617,594,448,974,11,595,330,103,635,11,633,715,951,960,542,59,742,780,614,484,881,741,87,616,655,467,264,417,774,98,987,254,403,783,292,356,137,932,83,138,400,5,481,76,999,603,732,254,246,411,492,264,29,485,104,839,130,294,733,853,680,353,678,489,542,583,212,568,419,450,227,665,666,860,945,429,137,206,304,771,541,657,648,41,270,383,236,595,940,356,920,583,847,598,281,276,431,550,342,866,845,513,880,473,636,805,645,219,22,749,901,215,667,302,439,794,700,301,812,243,353,899,918,219,564,641,972,628,738,802,838,661,797,279,480,441,309,837,598,528,241,41,317,474,853,327,55,67,644,715,565,354,546,84,201,510,764,294,522,757,460,568,999,848,96,352,34,926,629,886,263,507,28,230,386,140,709,465,852,360,394,472,285,163,760,462,352,752,756,862,716,678,101,256,118,262,850,709,833,855,953,652,320,698,297,627,131,981,628,179,297,963,725,388,266,879,413,327,619,640,487,902,500,167,47,365,110,116,30,862,939,174,825,379,880,998,726,679,720,144,419,213,860,986,607,461,219,499,318,408,650,331,791,568,427,975,164,398,370,20,601,853,366,575,537,433,898,496,593,608,699,285,800,362,590,500,481,699,932,267,329,562,872,692,777,465,609,279,678,586,927,942,827,61,938,47,957,312,327,665,300,942,59,698,571,264,227,658,603,326,745,672,96,78,681,419,606,271,118,986,282,340,970,357,726,378,103,971,85,553,22,626,584,596,268,815,130,651,156,648,571,0,75,889,357,845,729,982,678,301,522,383,276,657,164,535,509,477,235,649,366,824,872,808,590,61,871,81,441,74,715,977,663,386,750,633,184,785,239,912,729,424,836,561,606,591,951,545,840,400,506,931,917,774,543,526,325,933,889,643,747,196,560,804,56,460,10,961,315,167,557,74,951,715,751,149,907,537,540,186,552,667,696,12,295,795,7,48,812,125,62,788,19,685,673,868,79,616,722,705,500,148,644,725,51,87,328,657,920,634,553,827,215,515,884,11,810,630,76,245,504,557,314,87,224,787,908,444,165,839,405,727,120,137,120,180,823,595,197,181,262,583,573,171,243,684,214,864,720,380,740,571,303,567,786,651,125,774,915,764,739,33,55,486,940,612,849,201,501,690,566,599,304,187,925,641,763,96,738,474,991,901,826,296,166,138,876,589,425,793,24,734,483,940,516,701,386,286,379,716,123,934,615,208,804,749,411,4,789,192,789,668,913,323,424,582,279,331,758,659,495,745,889,332,269,416,316,547,105,674,188,855,143,836,639,888,808,562,818,334,832,618,821,291,511,647,229,299,46,421,300,21,192,623,399,931,473,75,298,223,795,379,458,122,224,49,745,834,880,763,469,443,310,656,813,304,303,31,760,710,779,797,418,778,101,201,982,722,639,23,845,118,876,107,371,167,407,361,896,477,403,911,307,557,122,164,554,912,705,3,228,878,979,844", + "967,326,953,10,607,53,947,209,22,925,728,350,357,111,473,482,611,916,898,236,92,644,372,359,769,392,544,730,251,977,914,219,213,177,828,362,430,301,106,483,647,664,881,767,592,375,964,161,171,480,956,461,192,189,23,409,714,357,867,918,430,557,913,736,168,395,418,483,77,512,355,688,394,435,208,543,981,432,209,407,223,157,433,143,378,70,316,419,592,385,221,371,478,784,607,180,239,792,57,752,26,731,224,196,171,368,789,722,877,148,997,399,845,200,693,343,533,863,168,706,336,66,917,517,420,54,480,977,718,681,921,286,170,589,72,292,891,858,636,696,173,681,414,941,926,230,564,722,299,771,674,819,656,376,93,381,711,752,667,942,216,863,743,294,397,811,478,399,275,579,275,79,622,389,52,655,786,90,560,150,929,404,431,106,258,91,69,862,420,44,766,600,256,810,677,596,790,905,417,217,994,741,441,100,382,545,248,7,75,559,669,579,9,262,655,95,619,98,566,344,738,455,655,701,138,142,335,748,685,230,869,864,916,433,339,989,732,153,785,6,992,810,354,143,159,737,874,479,108,807,619,706,562,16,417,669,846,132,455,741,527,517,872,493,633,837,902,506,638,803,369,18,403,624,279,383,98,999,96,829,724,420,154,99,481,786,391,893,704,498,256,959,779,367,821,958,7,196,86,213,841,363,517,666,144,248,916,956,934,569,663,165,545,295,220,839,553,225,32,518,339,482,147,160,179,383,76,297,677,946,492,51,978,163,731,644,302,836,770,557,612,168,111,945,439,606,158,128,653,814,872,951,611,545,310,586,943,295,542,327,975,55,701,314,114,364,54,960,858,831,87,548,638,8,378,576,227,566,18,820,262,775,473,704,570,563,158,80,227,928,823,933,302,890,625,213,732,946,638,513,743,23,320,939,276,152,98,884,648,728,488,869,789,462,265,66,345,805,518,977,333,982,60,791,591,332,940,894,281,251,769,42,206,710,841,68,810,462,605,114,151,643,33,776,548,585,750,902,711,667,572,969,94,301,300,491,667,407,909,870,502,250,441,416,323,932,743,120,409,502,633,304,541,296,532,755,324,813,403,312,53,753,277,411,339,389,894,23,1,951,571,764,610,303,444,976,60,685,304,489,359,491,757,97,899,634,313,242,810,413,474,298,979,978,769,268,935,303,525,237,845,301,445,901,367,370,282,1,702,901,190,522,122,390,596,412,151,808,592,742,648,635,389,798,801,495,870,592,626,398,957,657,537,578,671,882,488,457,333,816,641,377,316,568,577,331,886,28,689,241,843,729,195,316,738,309,867,726,711,925,197,976,171,171,585,742,505,846,891,917,213,467,915,744,762,578,235,280,525,322,439,442,345,308,16,603,998,392,243,299,604,477,524,692,117,709,68,555,932,362,592,275,991,625,763,620,30,643,517,286,932,660,411,965,661,147,963,647,61,831,576,983,944,172,583,303,335,628,338,416,702,721,638,847,138,683,278,474,693,515,374,899,935,734,88,592,222,911,589,646,163,326,829,96,710,708,70,329,59,190,714,839,341,707,134,156,197,75,0,758,835,185,321,262,422,550,902,685,635,893,263,371,951,59,637,858,198,218,920,22,757,180,501,789,681,925,661,78,203,523,929,824,486,232,9,358,842,481,920,659,644,83,452,871,297,265,481,186,848,850,249,318,5,30,314,538,358,718,342,181,424,959,456,684,850,343,214,37,896,358,715,888,224,112,536,194,618,868,163,89,213,63,38,766,480,753,420,302,145,354,766,215,715,382,429,287,857,325,664,390,706,720,932,962,636,883,669,726,625,971,274,870,577,994,126,663,937,831,187,49,283,368,735,752,244,738,261,848,918,199,916,448,361,528,373,653,104,103,821,303,838,542,407,821,9,631,334,506,347,564,599,298,242,588,660,782,321,429,232,793,971,481,366,953,88,146,448,917,175,447,909,739,53,194,498,822,817,101,116,472,917,657,809,672,212,266,336,542,882,616,92,443,606,531,985,489,319,165,391,965,223,60,65,964,38,682,30,107,304,740,9,527,885,934,461,362,622,164,740,204,13,147,630,778,404,726,792,198,374,129,429,21,430,621,729,29,212,752,435,505,791,696,506,984,221,769,110,289,281,985,710,148,535,814,643,712,857,141,113,274,974,646,901,13,903,376,474,547,331,982,153,615,505,900,911,760,213,399,501,104,270,307,98,115,926,763,665,525,203,986,365,465,241,892,854,767,897,726,518,256,740,593,474,564,746,497,507,973,152,165", + "175,469,138,87,382,405,383,539,560,557,344,273,529,342,157,860,416,56,144,166,405,560,307,528,969,96,462,803,259,453,4,115,286,36,306,974,156,862,828,245,217,989,911,855,796,36,959,237,422,545,503,650,308,462,19,69,330,40,357,418,917,291,91,913,533,663,887,196,206,876,470,863,62,773,314,981,234,889,976,35,426,133,645,23,79,744,830,516,203,732,76,462,587,590,925,939,435,450,972,903,216,749,864,842,481,623,63,220,702,189,760,705,829,144,303,540,436,309,688,537,608,742,389,712,269,163,154,728,768,916,391,799,478,728,675,864,855,590,970,543,482,135,695,176,749,747,714,933,684,949,92,925,273,740,7,201,736,702,946,183,841,265,139,773,737,106,183,862,608,161,603,531,782,383,118,587,759,54,478,453,823,199,828,289,863,243,353,855,158,121,912,416,947,675,607,545,474,532,890,827,230,72,44,252,467,642,415,690,554,803,41,713,967,326,144,643,179,110,115,718,171,751,611,466,317,898,393,642,884,215,829,274,840,706,266,534,272,780,54,53,130,772,182,582,698,683,619,250,39,806,744,462,863,371,380,978,347,346,634,450,442,221,689,112,377,836,751,952,359,165,145,344,715,320,409,365,128,686,774,99,464,834,34,789,158,176,915,56,312,638,55,909,215,931,570,326,508,32,773,268,980,127,681,857,919,140,987,428,423,394,969,4,690,176,430,312,996,383,286,559,669,858,645,325,520,457,776,840,899,629,491,182,1000,355,317,463,632,361,245,126,709,39,376,713,73,545,517,550,897,113,698,971,632,903,819,386,701,838,341,599,170,218,390,387,558,110,225,77,873,333,569,696,340,511,586,258,656,640,5,938,884,787,367,400,545,613,24,953,386,651,473,349,994,71,27,928,428,737,194,39,921,297,411,25,164,583,591,120,485,167,805,897,552,46,195,512,851,458,531,159,912,43,69,50,30,498,697,965,973,6,967,230,397,130,952,939,657,841,95,275,856,361,47,317,965,665,833,122,98,398,623,87,635,347,759,503,981,33,459,441,191,328,940,999,532,544,541,624,922,866,172,776,909,516,20,286,319,885,336,613,385,558,73,258,166,542,759,262,64,53,319,397,460,685,765,965,17,91,312,792,757,682,173,468,977,900,688,644,292,154,216,2,562,133,682,405,971,935,791,620,534,274,603,750,564,933,187,449,773,656,745,681,439,767,932,849,702,669,786,979,672,449,797,678,400,235,249,577,767,604,791,796,336,607,807,563,654,77,607,363,307,974,184,653,679,714,204,107,764,454,804,200,542,939,673,161,256,164,744,271,804,635,179,875,581,373,152,781,779,822,239,571,592,320,193,26,624,347,342,614,24,646,598,97,844,570,978,901,962,700,784,529,467,301,369,626,902,502,473,303,861,762,482,609,599,118,70,52,233,937,974,133,935,759,791,817,613,692,992,588,370,238,392,246,990,139,379,794,187,573,458,631,866,627,203,69,819,352,934,815,931,964,715,195,164,192,110,977,610,928,15,158,936,743,94,957,723,145,567,574,261,711,415,374,486,771,419,889,758,0,169,441,509,587,754,968,520,792,902,888,674,32,820,147,43,104,836,524,844,401,724,983,582,849,857,220,608,157,93,862,62,804,358,33,581,25,254,620,611,734,463,578,802,633,537,194,241,451,915,714,737,965,575,888,454,987,47,456,972,809,883,858,232,496,653,94,458,880,862,241,660,164,555,391,730,978,250,545,860,388,773,35,493,466,91,823,262,599,23,108,731,939,823,548,777,191,961,786,199,339,414,994,283,319,690,364,961,128,523,27,121,879,211,581,120,740,831,583,967,936,860,26,725,384,523,331,939,934,930,326,969,193,631,679,274,738,975,622,430,463,355,909,700,266,593,80,649,127,354,16,980,676,27,31,418,228,914,668,888,157,964,68,884,846,842,570,818,498,779,963,157,834,313,991,991,570,51,737,167,725,482,911,18,251,935,349,759,934,889,645,188,451,123,412,256,72,602,799,704,678,461,521,228,879,340,431,616,551,301,661,715,420,183,260,991,281,742,940,616,399,571,588,64,588,32,528,946,46,174,541,270,846,25,839,225,36,881,132,675,545,926,439,80,437,396,814,95,344,991,931,839,561,325,34,564,865,929,686,629,276,927,623,364,202,936,834,492,734,719,428,616,886,419,331,382,857,926,178,691,315,568,384,489,60,620,524,609,996,331,488,464,273,974,776,791,290,308,283,980,415,461,468,898,208,830,705,502,10,806,783", + "448,456,198,3,895,463,605,227,793,305,806,446,630,820,655,143,45,861,445,939,865,204,334,173,979,114,644,2,18,576,275,673,138,972,648,381,721,846,502,219,91,634,814,946,830,836,729,114,888,97,685,208,124,530,989,771,154,468,557,903,316,71,136,505,106,293,569,823,494,971,564,518,573,244,347,21,617,989,795,51,335,582,750,660,273,807,927,422,688,684,372,929,363,917,388,298,631,309,297,195,428,297,848,41,778,793,276,970,675,635,961,383,958,757,117,725,416,11,565,679,754,185,674,520,367,413,41,334,999,154,939,42,724,361,582,562,335,81,371,608,871,593,787,125,141,668,583,20,685,413,282,145,80,614,104,8,337,92,982,291,14,838,880,308,60,234,201,734,260,175,841,87,428,481,92,395,818,49,513,55,740,405,573,160,195,135,419,708,398,783,42,395,78,576,115,98,580,475,960,965,285,590,633,827,499,268,529,555,52,362,665,404,930,102,239,583,235,705,881,124,510,584,43,892,997,816,722,322,724,47,689,183,819,292,806,442,621,472,995,254,737,467,732,664,326,175,562,452,424,13,968,117,517,114,412,261,364,87,210,546,839,628,61,794,486,689,66,157,670,250,567,91,78,309,655,270,149,426,827,273,324,643,168,52,275,601,894,945,19,919,390,766,188,253,741,847,195,635,290,960,26,994,287,662,147,509,948,283,180,446,671,830,110,827,660,604,45,735,203,575,224,13,224,138,681,370,692,178,890,946,443,453,770,968,765,295,57,65,407,312,805,345,680,102,67,557,210,902,984,726,233,743,419,709,870,97,211,539,196,908,728,317,425,577,656,630,755,16,889,20,762,870,492,371,775,299,616,763,121,54,191,60,734,550,960,649,314,689,174,108,370,387,216,907,606,763,726,800,30,471,218,935,187,809,585,832,577,188,859,777,327,794,490,690,182,778,234,591,140,560,53,165,657,771,413,368,875,487,743,880,420,142,25,749,365,611,730,14,34,423,769,581,944,843,569,299,621,366,976,118,950,818,390,268,416,967,331,23,305,700,525,349,261,402,987,890,208,840,158,182,325,467,122,491,311,631,492,512,346,435,92,68,268,371,967,56,376,436,370,122,161,322,989,231,723,200,528,73,856,241,835,475,699,848,921,883,77,470,12,443,156,10,790,401,351,834,776,781,644,413,277,38,534,342,332,402,319,755,513,184,742,893,681,801,427,553,828,534,882,387,944,653,126,275,193,829,97,130,92,771,180,344,220,440,660,206,193,787,425,404,116,306,92,892,464,962,802,216,112,512,96,637,696,206,278,50,493,254,355,680,946,311,793,883,382,299,655,431,908,871,740,58,234,509,680,945,766,125,283,813,792,792,549,891,616,191,342,507,48,137,337,801,179,788,515,960,936,846,420,824,859,14,216,449,972,958,301,818,823,879,681,816,240,315,412,591,594,489,92,155,491,981,931,955,521,283,363,426,532,241,474,353,44,69,65,252,49,253,19,794,654,579,644,170,899,215,81,894,952,178,166,902,946,13,447,752,656,530,148,123,484,513,736,543,742,224,755,357,835,169,0,871,97,809,399,530,852,342,132,712,992,384,484,364,862,488,577,550,677,682,41,572,918,904,704,975,473,970,863,623,320,172,365,701,804,807,301,879,409,419,51,710,143,695,761,594,803,65,857,446,417,2,81,530,884,779,798,18,859,782,546,590,259,888,461,129,374,429,218,358,367,973,771,782,948,853,489,877,40,742,880,36,964,771,793,984,560,780,984,396,60,387,691,618,640,23,400,19,468,656,456,914,43,701,795,321,192,686,514,554,618,674,714,636,167,537,571,583,166,326,440,82,204,984,518,971,29,555,400,740,588,635,164,180,145,980,334,554,167,59,638,738,563,496,147,755,45,212,336,925,97,926,800,301,681,285,439,165,763,575,650,626,4,81,604,769,906,308,941,634,351,64,349,467,600,875,227,282,628,246,598,466,129,915,369,245,172,319,431,807,894,983,792,490,803,614,73,756,181,408,757,275,602,730,85,106,162,293,210,795,834,169,338,556,183,61,133,719,223,438,131,592,345,201,756,117,360,403,959,857,220,646,806,436,979,128,738,638,521,607,911,381,144,180,344,340,12,658,547,924,641,946,666,337,422,856,96,218,18,699,606,592,498,417,444,224,777,964,533,891,849,55,217,398,748,799,775,831,943,226,950,321,715,1,908,493,480,484,433,602,584,912,732,316,243,737,413,510,365,330,658,852,701,456,154,272,336,475,335,523", + "130,186,947,644,187,422,606,662,857,609,398,272,68,704,280,128,763,207,314,943,31,34,132,813,807,403,667,40,901,432,123,119,571,727,37,199,169,900,670,103,344,360,247,178,601,386,160,406,572,358,306,517,767,956,169,157,659,183,512,209,230,791,220,340,70,775,842,492,221,423,560,319,408,537,119,288,53,467,531,871,597,308,319,103,548,903,148,697,519,742,567,724,471,822,453,923,384,882,955,461,147,981,863,823,678,752,59,778,657,978,575,468,177,919,284,23,607,682,134,777,682,256,465,579,272,780,841,58,483,955,326,561,7,311,2,413,808,38,822,501,437,918,384,53,184,108,236,186,107,312,838,851,513,131,491,220,152,294,744,153,104,226,722,974,465,941,329,823,281,443,127,25,441,594,948,969,967,411,800,669,296,429,860,192,459,644,12,292,616,241,466,791,679,253,595,367,443,144,727,741,382,970,86,532,248,261,528,70,313,183,454,181,698,467,737,167,305,717,18,920,823,422,193,153,616,191,578,720,434,216,66,724,674,263,330,277,88,418,736,956,449,702,445,404,104,557,818,57,888,443,559,545,210,404,899,349,282,665,482,652,245,395,765,604,2,397,735,160,551,939,447,545,282,295,274,533,921,276,17,301,43,514,361,959,346,893,936,918,331,507,368,263,385,23,160,848,886,415,617,769,618,234,865,941,262,528,670,840,30,132,264,819,305,33,592,98,615,839,559,321,234,334,528,501,500,605,241,944,147,612,401,274,131,736,728,405,517,125,793,479,217,126,504,165,128,184,189,591,261,594,972,128,299,977,473,224,816,936,388,417,165,672,498,832,602,52,399,505,205,339,393,796,937,815,209,899,705,139,85,66,678,989,814,54,862,596,906,471,334,687,18,36,921,175,882,264,930,41,326,938,955,117,335,961,458,808,810,606,920,301,796,371,691,836,61,863,2,465,539,621,301,933,217,656,158,743,123,316,915,763,175,63,742,926,463,757,621,50,589,12,23,499,962,503,916,940,460,582,739,62,109,350,676,384,712,239,860,238,389,398,64,792,376,122,666,287,394,560,347,431,270,174,274,444,230,810,412,722,936,933,180,116,70,201,530,232,430,201,965,690,602,567,109,404,903,652,967,618,789,146,930,115,496,22,653,250,303,885,147,200,614,71,869,812,515,509,410,783,957,19,281,587,284,383,165,799,335,843,926,507,170,897,369,965,7,410,360,250,411,542,693,644,214,140,958,917,991,339,139,430,860,553,651,569,692,393,504,633,787,900,999,734,561,379,155,704,462,987,525,245,989,256,71,945,870,802,252,360,756,154,382,116,693,575,388,796,568,413,576,584,877,357,539,710,623,916,669,627,633,913,683,485,242,368,685,32,711,950,895,625,831,994,175,681,345,849,475,681,714,237,623,831,268,890,790,641,597,800,170,303,526,136,173,270,314,836,538,436,868,450,863,960,402,689,983,419,954,5,784,297,31,168,251,929,388,827,216,222,630,139,447,901,192,730,426,836,929,967,724,486,426,259,599,991,67,895,517,221,290,60,983,806,942,991,833,300,493,845,185,441,871,0,178,210,291,716,924,956,246,756,867,535,739,544,654,224,787,2,711,94,111,415,257,570,374,159,376,159,187,809,465,557,426,239,930,736,856,875,654,924,246,76,864,415,301,218,66,344,700,342,316,728,869,938,580,119,88,109,387,379,730,843,891,707,587,245,746,869,564,160,810,143,641,963,980,469,373,626,954,751,582,158,169,996,142,657,865,985,296,585,836,205,405,331,586,690,320,120,736,233,563,568,616,14,814,689,544,706,230,276,585,391,735,245,895,848,90,165,796,580,470,570,169,819,379,491,574,53,713,408,592,308,689,970,614,513,674,125,913,919,63,122,405,953,564,127,687,456,441,244,822,961,180,51,592,55,787,991,87,514,900,250,855,37,240,704,402,568,588,292,601,675,504,449,297,225,450,187,327,684,705,914,339,117,608,553,961,580,12,838,513,225,461,813,742,405,268,503,264,660,68,79,671,291,280,639,927,463,659,309,431,543,904,315,276,81,741,478,649,191,565,295,718,475,122,559,143,169,291,469,452,366,840,113,543,470,396,174,967,907,396,409,101,893,301,911,857,909,520,102,979,117,752,443,348,680,687,585,686,794,685,354,226,45,868,424,48,333,192,30,461,918,741,916,103,79,590,860,669,643,4,575,21,910,46,931,809,933,711,135,39,996,502,510,476,244,326,8,304,187,123,805,207,927,411,954,377,437,299,30", + "611,82,234,914,513,575,553,925,260,812,342,335,436,353,769,649,220,234,939,515,860,260,797,863,346,222,704,458,114,414,384,814,125,575,722,34,291,930,246,865,717,547,82,266,969,601,900,333,76,115,959,837,428,16,408,564,543,542,887,503,580,638,946,781,743,679,421,980,16,996,175,738,415,711,16,461,827,159,121,883,868,936,797,509,986,593,685,960,116,847,848,915,303,498,786,667,683,177,760,107,900,999,980,262,220,340,821,898,331,166,187,983,89,274,811,801,766,169,428,69,936,510,426,640,596,77,813,123,875,308,640,562,609,942,229,731,658,571,52,280,155,633,50,231,605,129,418,853,830,314,570,34,53,707,481,449,436,263,766,592,276,673,735,219,791,465,909,753,924,162,910,118,627,983,344,345,298,835,40,391,933,689,256,710,592,534,619,939,649,145,588,287,414,217,771,637,715,821,664,227,635,322,19,572,281,807,340,171,530,784,216,717,866,227,834,647,79,684,901,607,803,128,189,589,61,485,88,316,157,994,219,624,536,274,992,972,817,69,290,593,776,26,133,322,822,695,666,411,195,336,92,416,306,253,471,387,205,905,519,925,935,346,199,136,357,810,261,836,749,144,271,725,317,435,796,37,613,769,528,972,738,109,885,928,173,704,971,723,355,242,205,43,838,188,653,268,815,819,2,805,828,226,969,667,360,417,778,617,214,668,399,593,244,923,365,726,223,497,33,185,184,71,906,939,448,368,318,379,151,286,18,617,993,113,806,703,470,724,659,400,335,582,546,89,694,303,412,76,504,524,530,314,508,502,823,440,223,754,493,516,44,829,605,77,894,766,478,498,634,877,77,820,243,176,514,573,772,947,121,277,828,968,243,716,499,933,581,312,279,146,72,797,604,398,296,950,265,230,128,140,194,697,894,964,189,647,872,169,231,435,996,128,677,95,99,627,815,743,653,113,780,749,236,869,371,563,468,877,608,237,988,698,757,611,169,819,757,644,687,819,146,926,824,634,81,117,272,402,499,67,419,812,934,4,618,562,746,635,856,703,604,836,708,489,161,172,274,607,429,144,6,866,574,976,263,218,804,465,278,61,18,974,744,900,14,471,445,5,205,95,251,428,395,482,113,495,878,264,153,131,867,941,943,592,969,475,978,294,125,254,405,189,448,202,342,366,760,427,325,580,1000,641,627,418,306,730,848,970,329,296,894,325,914,116,676,400,177,484,144,483,819,144,712,731,140,848,549,693,994,935,364,649,914,632,54,431,772,9,296,902,67,795,590,970,695,241,382,947,780,894,680,11,846,840,976,540,918,412,630,495,392,657,273,370,782,196,978,177,106,113,871,251,63,703,913,775,531,958,553,204,81,297,46,742,325,318,175,994,776,592,213,417,671,466,463,510,447,803,976,305,718,73,281,878,247,456,600,66,754,97,779,248,522,164,645,113,311,94,990,957,90,704,995,888,451,906,109,625,792,593,792,925,980,259,52,146,379,341,726,263,164,817,610,363,35,237,72,382,973,536,645,759,795,577,719,302,182,392,14,656,984,628,465,165,331,317,192,729,321,509,97,178,0,532,914,953,118,643,725,879,582,837,796,294,819,60,253,516,29,454,900,885,385,153,756,939,30,224,524,732,601,910,341,86,451,86,460,722,310,717,607,422,398,937,321,226,944,937,403,543,386,275,266,13,371,620,372,105,414,102,102,557,503,658,553,896,525,482,432,119,670,375,127,476,224,826,702,884,820,501,213,441,968,34,527,191,591,401,102,727,419,711,158,286,289,930,96,892,555,100,947,693,859,602,7,389,13,550,270,33,87,193,8,828,55,475,855,468,842,143,873,212,2,317,807,620,677,414,348,374,74,100,130,146,476,826,495,642,403,887,496,370,467,616,630,916,141,981,867,908,876,445,93,929,56,770,236,391,78,208,35,557,811,176,726,857,342,904,242,638,545,154,55,827,951,434,998,769,973,366,137,778,376,641,140,773,909,611,915,420,197,953,992,126,146,590,788,440,10,593,78,41,586,921,633,344,602,899,993,208,150,882,219,193,300,23,164,290,916,206,613,836,7,801,607,597,805,963,422,575,580,261,477,327,76,463,568,77,315,287,147,640,991,903,280,396,977,548,231,343,489,96,44,461,329,233,26,213,829,409,971,371,888,702,917,467,574,454,912,681,316,227,174,637,985,498,804,878,847,655,605,174,901,361,75,772,911,833,103,213,407,851,860,639,879,48,905,829,855,356,777,763,850,941,995,568,501,418,667,778", + "998,830,745,500,554,2,287,69,703,675,750,883,958,995,828,239,745,994,95,688,673,719,650,20,820,3,346,457,83,756,950,693,195,893,471,825,384,242,569,950,640,500,128,518,960,486,104,982,304,623,362,868,628,864,974,672,274,617,843,930,944,304,641,163,641,340,587,700,729,12,26,816,289,250,578,670,11,921,343,521,630,532,132,133,625,98,991,700,57,218,138,83,370,919,457,564,400,679,240,799,468,597,941,29,631,78,815,541,161,513,697,324,705,202,514,595,663,803,329,63,142,934,492,258,559,358,121,883,569,751,736,775,591,257,441,108,383,347,534,140,444,43,965,421,92,240,864,717,283,856,61,410,690,281,169,739,247,126,211,697,62,503,211,251,20,893,773,156,304,177,359,251,737,308,538,415,838,247,91,793,50,510,738,388,950,572,262,691,355,8,291,852,603,922,172,132,370,998,810,502,881,402,664,34,804,10,230,151,220,903,300,129,290,789,145,693,254,364,574,697,997,51,650,400,456,861,892,209,565,442,234,588,891,534,16,797,906,974,645,191,451,678,549,141,854,743,507,394,714,69,375,403,811,146,208,640,213,588,278,114,722,56,683,488,74,294,224,991,123,271,201,824,592,172,185,375,665,795,692,916,466,162,976,7,328,525,864,871,139,126,202,171,195,850,316,819,657,819,183,211,391,789,467,980,290,68,370,286,671,180,245,796,125,596,942,929,989,999,346,229,974,572,476,424,382,829,782,755,250,515,443,6,312,253,903,326,788,959,643,182,661,784,829,944,645,732,35,608,520,926,87,73,959,605,792,524,791,333,392,698,781,724,169,598,537,954,45,863,26,888,571,575,715,969,550,3,423,482,931,108,187,762,970,261,391,209,220,86,283,90,175,748,61,771,107,85,509,817,893,547,900,205,299,552,790,823,545,264,533,370,421,161,332,961,660,751,484,267,851,760,867,325,954,986,461,472,899,851,784,74,714,184,692,653,172,436,379,844,869,723,945,765,943,190,767,587,287,955,434,924,40,778,776,645,225,926,748,665,17,318,219,600,329,336,301,156,656,258,565,918,238,261,818,40,796,882,631,357,121,439,381,518,699,556,829,251,815,470,38,973,494,677,974,995,117,682,397,750,690,384,914,92,351,156,547,994,922,43,371,321,543,430,810,334,132,56,50,183,83,713,832,93,527,706,240,30,782,811,89,284,608,290,39,370,122,18,634,717,367,341,909,394,56,762,610,700,324,945,766,491,546,343,590,31,206,128,986,903,485,796,50,175,720,200,39,50,833,186,498,802,427,4,1,856,125,797,142,641,840,828,959,779,616,420,756,577,172,503,761,229,13,295,262,866,646,928,585,217,898,530,131,49,7,192,623,502,117,27,262,299,696,710,200,280,238,769,59,261,477,989,800,873,210,576,752,894,329,797,726,125,986,299,967,27,629,394,704,952,234,70,261,220,597,255,376,112,440,445,200,624,349,389,125,577,567,892,809,540,324,683,315,802,602,72,76,72,512,25,327,849,612,442,980,441,734,787,312,224,604,384,165,933,768,613,978,801,774,982,262,587,809,210,532,0,140,941,242,770,550,313,789,37,262,544,737,246,672,477,431,946,106,288,495,956,932,108,932,914,662,342,809,443,148,597,636,709,661,383,342,158,11,369,205,663,668,722,61,525,60,895,18,281,57,901,175,350,512,272,300,549,454,973,141,627,389,795,713,28,727,727,956,457,675,215,58,250,831,423,72,789,715,574,548,781,333,401,507,500,434,342,154,484,949,677,871,964,72,696,273,567,956,466,487,551,653,269,893,477,821,65,724,765,223,79,180,571,459,767,338,880,270,974,757,819,184,341,326,387,730,271,230,553,390,171,662,646,285,245,910,58,415,439,519,320,172,938,530,131,872,805,847,889,588,684,790,548,573,472,235,199,96,270,531,679,200,176,424,155,869,759,464,758,500,470,17,116,81,201,922,67,970,293,458,398,288,824,835,494,155,899,781,218,239,745,6,103,166,300,303,262,500,843,976,698,235,89,578,67,130,809,138,390,695,558,662,787,619,875,119,232,728,854,746,429,59,416,338,955,823,918,534,667,579,166,113,172,657,238,976,251,693,247,138,268,723,403,248,360,984,361,797,951,718,776,716,166,755,493,327,410,38,675,427,996,387,421,453,329,136,26,576,52,973,783,403,876,721,228,39,839,505,801,225,511,739,826,308,386,145,137,966,605,137,198,975,198,915,929,804,192,526,535,396,607,394,928,189,424,51,284", + "669,22,669,643,997,386,511,78,849,201,525,706,242,512,297,795,871,367,907,860,552,53,483,88,886,428,875,638,85,543,97,726,459,970,496,75,564,574,203,584,820,373,110,30,571,26,649,756,796,249,398,770,100,820,187,482,404,869,441,274,65,366,751,658,348,693,324,691,299,697,743,2,962,756,447,782,797,527,830,439,434,478,340,999,646,632,59,547,607,480,872,552,827,61,699,462,579,501,802,559,108,642,668,607,845,128,399,185,288,799,903,260,653,202,678,610,984,544,720,914,770,178,530,816,698,486,619,409,664,192,453,899,495,994,450,4,115,98,17,118,218,449,174,976,693,841,775,906,179,368,20,280,614,138,722,798,123,891,329,262,183,986,439,525,484,14,65,169,880,368,321,463,792,524,88,70,410,365,206,105,517,694,917,465,752,894,720,841,536,130,255,108,357,808,947,419,960,658,660,889,853,565,211,816,182,913,760,510,88,319,297,998,968,499,585,783,506,512,522,604,356,677,779,419,247,834,608,701,497,396,243,789,538,659,879,749,132,242,443,981,251,173,24,607,65,751,900,30,270,910,953,138,286,483,25,988,321,253,888,313,473,528,309,91,485,912,112,639,953,864,576,276,339,156,320,529,593,626,960,901,422,796,276,220,328,120,847,464,222,579,509,543,960,288,6,375,700,694,993,222,942,952,836,24,96,185,30,851,993,833,394,395,526,609,391,461,467,489,375,358,435,416,830,751,791,852,919,498,670,942,579,326,281,248,187,265,932,269,635,135,308,889,92,482,796,409,950,499,102,32,439,494,98,344,133,632,576,202,59,690,774,45,184,913,255,649,876,528,210,576,258,400,560,947,349,534,696,248,467,817,93,530,112,45,20,499,711,923,123,230,429,648,689,144,969,452,621,147,600,708,579,843,447,69,363,89,378,514,201,544,354,259,570,724,446,719,749,740,409,574,103,907,667,789,476,89,892,603,495,101,420,324,660,982,342,401,902,4,822,476,158,226,383,512,292,275,982,410,486,614,813,110,514,360,912,586,454,901,752,822,221,326,345,239,649,333,810,546,715,686,885,872,891,919,877,80,62,258,810,495,70,136,561,471,695,372,344,964,788,244,708,810,104,693,636,174,456,948,349,328,643,412,767,858,6,609,93,456,333,640,861,340,216,231,626,500,608,791,912,785,486,57,693,536,543,789,396,217,289,107,447,170,346,797,869,368,246,580,380,129,147,316,711,183,933,396,899,886,94,29,895,388,690,899,78,140,796,733,916,265,768,224,242,271,292,1000,912,164,691,436,668,667,499,587,24,79,364,932,528,209,413,510,578,891,470,244,744,662,779,878,586,33,149,102,390,341,702,988,833,585,261,43,616,534,388,980,528,804,795,370,494,671,399,402,515,583,249,879,749,371,949,73,563,700,662,271,496,917,845,895,831,847,352,738,161,178,679,831,302,386,684,953,97,870,996,873,664,908,356,980,217,128,666,314,377,511,422,64,314,465,529,211,733,507,831,624,103,842,646,494,93,444,691,399,634,572,116,687,926,932,243,427,388,875,503,960,964,678,422,754,399,291,914,140,0,438,43,500,82,456,757,382,242,120,814,730,388,508,34,49,173,820,357,592,423,117,582,664,403,57,822,12,112,890,692,755,401,874,596,838,314,251,773,668,525,792,903,152,45,909,122,602,675,128,784,607,190,891,576,415,899,442,619,694,550,799,799,358,315,854,900,282,155,493,513,584,909,551,51,832,241,857,103,540,532,309,134,77,844,49,307,774,819,209,473,509,915,605,746,811,72,605,521,809,240,973,10,147,944,803,766,903,880,10,291,5,506,882,869,342,78,623,316,131,474,874,175,801,184,346,425,194,621,199,603,265,210,588,950,882,294,80,909,909,323,401,558,624,727,372,299,298,976,387,973,534,65,419,333,927,528,997,304,409,390,951,874,734,152,882,713,955,13,967,193,135,246,143,445,986,540,575,729,165,946,706,867,37,936,227,29,789,940,300,363,200,747,716,331,805,584,632,689,938,421,511,877,454,735,376,243,432,685,768,713,32,753,108,308,511,954,617,642,941,296,988,797,448,769,809,689,208,331,590,33,393,623,935,691,967,615,394,230,481,24,28,407,152,357,184,372,203,199,549,403,565,431,527,335,377,589,397,258,308,86,235,471,769,818,244,617,247,551,828,499,875,301,434,616,674,133,741,766,793,665,203,135,848,496,303,138,721,300,935,112,210,499,292,482,373,887,676,726,730,858,667,605,144,802,248", + "350,865,47,579,630,120,891,795,295,556,24,231,54,82,931,536,13,473,368,341,471,480,169,333,630,621,741,78,383,424,762,290,171,326,323,854,423,216,571,914,193,860,704,742,470,153,779,164,607,907,32,152,579,315,993,4,20,824,130,569,875,518,345,547,665,69,4,139,497,93,252,49,459,38,558,676,550,628,39,54,499,762,601,592,128,462,706,466,279,875,5,828,811,844,961,751,53,653,635,6,283,409,514,371,48,520,770,326,84,104,349,943,547,779,548,936,530,541,926,784,722,390,313,599,737,486,690,847,260,834,976,735,940,577,298,594,414,933,273,860,450,497,766,617,80,416,551,883,530,790,318,432,123,919,49,159,118,799,994,593,109,580,371,934,830,401,663,427,146,344,367,592,669,107,515,442,364,823,773,165,195,83,970,744,137,758,922,206,311,659,286,993,459,106,230,287,116,132,566,147,348,223,43,357,557,822,323,79,818,841,335,908,631,77,548,794,131,739,708,796,751,380,340,294,125,8,198,650,909,568,817,879,597,767,970,432,288,963,803,143,846,417,436,418,122,97,514,269,881,42,134,783,188,737,369,300,801,554,460,352,895,312,354,157,734,451,982,510,467,846,424,641,202,38,165,401,149,254,348,143,596,966,857,662,79,418,266,822,359,124,989,97,419,373,80,271,425,993,152,904,929,411,718,805,450,976,589,426,902,512,664,716,643,834,13,289,749,47,578,537,354,5,972,946,303,495,352,371,131,966,301,815,731,389,323,633,637,589,884,582,426,99,945,508,647,359,592,450,905,583,29,207,902,71,306,633,52,252,411,673,507,861,195,591,15,153,73,396,662,594,640,927,9,431,42,203,228,905,259,210,362,912,801,541,277,641,111,597,737,712,329,51,37,246,385,205,464,227,85,803,416,759,424,384,890,227,507,595,438,734,898,167,243,462,539,609,109,384,435,761,728,452,318,390,529,175,720,542,408,321,318,15,316,46,471,558,265,244,772,955,523,321,977,731,394,296,162,400,472,633,554,506,947,221,469,792,86,427,520,562,838,48,891,928,368,413,111,260,527,865,715,726,734,512,706,354,288,766,744,982,631,819,818,903,529,573,241,829,251,506,618,66,106,19,998,570,974,461,908,625,970,606,910,466,182,85,775,979,409,986,417,595,652,362,163,578,393,902,203,970,551,29,619,586,750,76,412,58,925,10,187,663,874,264,853,206,716,617,724,745,992,211,674,893,707,509,900,21,825,690,251,882,256,792,980,995,660,394,701,909,995,306,985,793,188,362,697,762,565,638,189,957,224,318,158,492,105,435,418,369,897,290,231,130,595,633,662,432,377,594,81,27,411,355,515,275,523,151,749,684,525,990,304,627,455,124,240,46,744,726,854,587,569,828,422,980,810,62,651,739,169,413,569,615,617,269,722,991,313,365,459,311,474,483,713,577,58,457,950,105,491,938,675,132,502,483,165,835,719,91,276,392,983,465,342,152,436,290,73,84,192,217,161,982,158,552,656,217,615,861,790,484,216,951,10,856,391,110,204,405,574,293,711,352,557,117,846,301,550,968,530,716,953,941,438,0,192,255,109,491,173,386,60,520,642,806,195,973,146,902,327,719,40,56,426,162,818,892,421,995,832,855,566,355,351,756,14,237,309,522,734,903,780,239,108,152,61,500,999,283,170,417,904,364,197,367,578,351,634,187,619,46,836,834,246,604,376,435,207,844,991,185,745,868,921,803,754,70,296,204,952,688,714,301,315,258,922,536,150,341,322,509,345,72,692,241,458,39,692,696,33,523,434,686,824,329,533,314,716,681,782,120,443,347,143,469,820,334,208,608,718,607,578,263,410,7,933,254,486,932,254,61,97,162,485,748,380,644,709,497,737,161,232,144,266,629,944,864,521,856,636,966,920,876,740,943,806,931,983,408,41,341,963,342,134,860,416,898,972,811,34,78,795,824,876,740,38,408,779,753,768,360,532,604,248,394,139,158,68,812,681,546,941,611,604,843,7,606,596,929,768,512,396,838,666,116,665,423,346,450,644,894,342,286,351,503,893,592,109,605,151,401,955,892,904,650,66,175,818,291,576,659,679,597,673,69,58,196,511,447,540,466,319,373,104,12,708,500,434,513,3,926,314,619,569,215,554,378,238,117,259,980,939,144,753,97,512,956,578,47,404,878,229,973,326,58,252,982,400,457,970,315,546,290,233,293,84,763,612,6,444,662,775,90,349,519,595,959,886,506,353,600,41,244,629,443,252,674,594,831", + "234,589,270,508,52,896,537,821,308,970,147,75,873,226,819,76,933,960,563,742,726,686,383,966,358,353,167,670,960,217,198,653,27,459,797,792,386,425,238,118,48,616,954,217,507,699,908,112,718,868,804,568,874,134,919,662,210,635,81,300,503,687,256,146,389,476,781,497,418,113,359,963,926,311,720,210,857,316,260,300,118,366,43,399,586,474,533,644,364,929,771,903,108,944,968,356,881,343,381,51,727,203,524,908,469,972,247,661,546,432,323,483,108,783,470,522,952,99,460,845,227,177,857,488,131,391,901,462,387,282,941,146,154,363,449,975,814,148,193,398,141,406,986,648,738,403,541,177,662,81,47,319,267,571,674,716,169,963,279,666,461,872,125,598,912,723,588,820,977,508,898,541,198,703,590,752,480,842,718,809,963,85,986,918,805,300,946,545,41,563,168,329,573,911,479,421,64,961,633,545,314,59,284,74,862,781,165,889,205,59,442,342,79,504,496,248,42,971,277,611,458,348,37,71,946,232,756,887,445,559,38,287,287,717,933,935,324,380,669,581,209,724,908,555,986,483,290,489,614,204,364,216,701,955,345,596,869,702,142,747,787,672,698,412,149,736,199,894,180,46,898,727,203,593,388,810,125,817,878,970,291,738,416,820,449,447,488,355,884,342,276,697,160,521,408,723,849,984,921,940,768,504,920,904,209,795,989,69,14,947,861,632,384,366,749,283,30,405,623,569,935,66,59,182,728,953,942,178,708,471,87,407,959,8,61,143,930,139,741,332,873,123,655,418,227,870,538,207,638,226,618,465,312,706,863,793,714,316,26,51,832,75,992,729,810,794,980,716,259,382,834,178,811,575,591,194,670,820,404,243,829,717,808,486,131,60,401,48,668,569,298,941,431,150,923,287,186,834,408,935,70,311,187,520,758,324,955,602,273,829,650,76,21,653,71,61,703,480,178,421,37,369,859,670,944,610,958,128,592,750,109,13,717,490,274,209,936,890,49,917,25,459,776,307,162,119,831,989,550,15,839,707,429,527,630,704,994,252,504,826,69,154,901,43,601,1000,987,796,614,610,682,572,134,187,828,903,276,536,224,705,664,448,767,679,821,432,62,585,515,417,903,647,8,560,9,447,331,813,406,989,372,245,274,919,540,584,37,312,609,643,71,845,730,527,198,590,872,590,590,851,579,52,801,355,444,646,458,645,375,517,704,837,789,570,189,419,665,475,530,128,353,622,946,860,385,639,969,493,510,178,285,467,487,876,626,23,920,300,438,721,473,225,296,887,709,481,144,501,341,352,545,808,759,676,650,664,864,275,1000,96,706,241,407,949,202,195,818,766,870,810,742,560,705,941,870,868,370,512,194,679,707,519,944,889,236,572,453,633,798,461,390,317,519,677,161,278,810,90,671,355,781,699,703,784,296,438,17,821,830,724,354,156,408,604,290,221,866,919,336,9,414,287,349,887,118,349,285,688,229,502,427,26,507,132,715,809,722,932,959,646,155,226,641,368,969,255,133,514,377,601,8,78,974,505,715,281,291,259,219,174,246,984,892,20,369,791,138,522,902,520,852,924,118,242,43,192,0,81,519,220,715,6,836,256,781,398,472,781,988,849,908,154,735,181,841,111,627,562,790,484,6,891,790,459,527,69,472,194,60,533,596,755,823,746,624,105,441,627,771,215,600,616,978,608,444,921,324,352,366,841,653,828,874,828,526,19,157,598,517,964,729,441,807,952,5,835,971,759,951,162,47,793,696,631,979,780,132,532,155,394,408,146,906,32,550,518,668,10,744,68,323,421,499,809,499,525,68,968,370,595,767,519,165,111,215,993,78,606,872,711,178,701,115,855,974,938,8,484,752,722,584,252,278,930,7,159,114,433,40,568,171,618,353,846,32,346,984,257,425,955,11,88,49,913,813,407,23,289,869,832,552,601,188,947,994,678,142,492,628,86,401,323,829,621,270,282,836,268,198,198,434,122,976,995,792,130,627,865,241,92,312,150,224,15,496,556,179,637,478,160,34,198,467,332,667,45,154,782,582,930,165,721,329,405,684,995,957,261,745,612,878,757,316,209,426,13,727,925,746,21,492,888,862,715,731,710,86,669,138,723,767,944,535,723,492,685,118,436,228,507,35,877,466,661,931,162,997,388,939,731,174,668,697,294,63,800,514,304,210,388,41,504,610,838,336,421,942,714,284,177,295,950,597,762,946,827,528,403,205,896,911,322,701,570,259,407,490,207,815,312,955,47,524,601,106,250,405,635,572,477", + "272,375,799,878,938,422,243,888,739,541,834,580,539,686,147,20,436,562,816,318,619,904,654,588,905,150,813,404,90,275,98,419,193,734,447,153,885,110,902,481,801,734,43,877,917,768,159,885,784,809,568,238,177,942,912,83,286,380,672,422,358,929,349,702,585,638,922,958,567,304,610,653,907,57,70,629,520,914,655,232,473,377,610,774,920,754,168,931,556,190,732,36,878,729,877,562,395,838,35,450,250,995,836,590,908,889,2,690,733,799,957,49,798,698,293,761,292,956,715,531,701,317,133,43,506,606,327,343,552,622,406,566,113,584,128,201,779,979,461,223,637,429,180,205,246,376,112,146,390,370,927,827,756,42,149,551,595,250,123,646,954,996,930,65,249,689,752,137,694,949,788,916,994,147,291,84,825,394,120,371,15,21,586,908,699,336,639,565,720,883,309,468,388,247,981,612,779,715,826,994,748,795,937,438,376,219,943,529,246,87,709,182,983,879,583,210,840,261,592,71,584,931,892,25,406,620,545,119,361,874,345,231,90,506,18,99,239,437,771,908,595,720,438,944,707,897,628,184,481,684,220,440,371,627,860,84,146,752,858,731,507,646,410,410,284,540,83,664,837,27,479,34,622,842,92,70,685,735,401,509,337,845,764,118,647,384,658,532,136,738,502,776,47,80,906,198,629,955,66,553,214,905,898,564,967,662,246,566,805,413,598,195,305,356,150,107,886,230,75,144,118,894,14,410,717,723,183,959,203,881,566,992,434,477,539,173,595,741,564,870,165,79,624,495,620,231,623,641,628,778,297,751,177,542,912,693,409,663,287,637,383,91,878,608,167,953,515,555,667,835,830,471,353,709,480,386,382,11,815,299,592,126,830,260,396,170,928,525,46,599,377,536,347,425,33,573,750,149,980,996,957,613,135,893,286,660,446,455,240,557,756,335,699,717,718,63,32,204,422,750,507,150,935,294,760,95,218,764,133,985,753,250,565,348,129,587,463,697,495,269,701,229,171,673,237,568,988,241,268,375,337,855,748,348,878,713,595,240,719,931,670,56,903,526,426,346,105,428,239,702,591,105,892,749,36,278,35,708,201,873,46,747,845,412,807,155,286,3,18,294,689,199,63,366,827,130,307,626,919,129,521,807,266,623,939,476,788,233,85,593,992,101,918,242,178,438,461,205,705,939,575,93,949,430,236,946,863,383,82,175,913,446,33,663,978,303,117,262,555,915,253,909,914,815,43,798,86,463,217,829,897,1,457,16,906,13,552,798,581,567,452,656,737,983,875,831,838,448,678,970,256,930,896,750,129,556,749,393,823,936,661,907,789,75,592,936,687,227,154,127,699,292,190,874,552,894,44,234,149,792,215,637,25,447,595,879,584,318,968,17,361,729,504,819,154,948,810,85,185,583,128,528,422,996,395,963,220,854,750,516,229,224,690,709,902,779,162,245,912,828,927,191,820,444,793,687,255,911,573,240,315,918,192,922,970,528,989,557,728,869,503,678,376,178,564,18,390,980,560,114,195,410,403,643,394,980,249,508,799,280,900,208,413,365,2,921,140,383,685,792,342,956,643,770,500,255,81,0,684,441,165,372,524,685,62,744,514,129,113,295,137,211,653,724,750,678,412,744,826,902,507,92,720,904,769,891,926,675,493,517,447,864,383,795,167,47,778,582,848,6,368,972,607,243,922,359,157,214,212,239,410,160,940,969,421,502,195,304,74,418,197,272,181,437,54,132,438,363,817,295,715,613,306,200,742,910,694,911,773,233,507,747,537,863,963,796,862,802,399,690,653,274,649,937,643,237,669,177,359,842,300,189,875,88,478,201,776,530,8,708,307,29,821,610,718,179,481,339,496,696,666,139,115,439,425,282,161,702,125,998,472,392,336,101,319,925,930,460,16,229,287,861,596,414,823,616,551,846,942,290,742,332,990,330,46,546,880,770,975,799,955,484,20,18,743,159,609,255,457,84,42,502,124,567,396,792,254,745,60,412,145,540,644,150,956,445,784,487,588,244,284,243,347,199,480,795,165,520,615,901,507,120,535,218,895,922,58,1,706,326,911,879,909,424,880,309,968,572,18,146,55,568,430,423,506,542,719,463,945,893,152,883,577,548,283,401,279,931,81,112,399,406,340,561,981,336,980,128,890,788,123,794,119,563,558,197,572,607,158,47,909,532,689,202,551,83,523,260,747,380,542,761,881,293,998,789,171,799,311,248,955,225,148,263,74,70,883,608,377,601,570,197,38,323,224,218,70,196,582,156", + "149,312,300,52,264,569,101,297,534,530,174,380,740,79,123,447,464,393,949,71,730,266,496,174,463,496,184,461,577,460,557,58,6,215,149,103,591,112,148,210,172,949,846,535,631,631,389,303,852,1000,482,143,988,127,220,254,435,4,711,684,665,530,564,243,70,382,523,239,432,248,917,996,937,432,375,31,152,551,306,419,862,607,815,673,184,552,31,910,420,254,593,824,589,934,884,991,460,131,919,377,854,270,134,899,388,316,764,62,84,444,748,366,489,42,572,773,225,266,217,171,479,639,912,683,71,420,652,453,293,993,814,637,551,777,725,852,521,448,274,547,528,863,532,361,414,841,190,676,712,144,138,229,802,328,573,597,238,637,665,568,304,130,232,342,265,49,844,506,72,968,662,589,402,308,623,533,220,313,301,10,109,676,304,31,678,678,93,764,24,501,437,61,670,411,964,713,330,966,729,139,68,238,883,522,70,145,874,945,835,931,383,978,315,267,780,573,136,755,22,445,93,630,163,872,252,479,149,730,802,222,853,437,545,848,262,986,885,443,559,735,356,658,928,14,530,140,606,696,823,496,751,604,29,372,157,649,660,239,312,273,943,916,77,157,933,29,952,974,272,710,160,512,161,142,496,766,254,605,981,182,662,811,257,961,681,221,674,202,702,416,170,329,629,953,749,948,264,992,750,823,414,757,427,507,748,439,614,671,215,438,249,898,810,757,352,948,471,365,916,211,214,784,648,337,320,886,892,618,23,880,717,235,189,363,574,504,538,512,596,637,754,371,795,662,636,485,291,29,825,226,973,22,869,774,948,454,259,594,427,107,413,299,240,230,368,296,275,262,194,596,28,636,138,756,190,327,530,478,476,954,203,204,8,523,254,489,661,281,506,527,54,845,557,185,384,599,686,509,934,548,387,264,751,169,535,667,160,789,590,643,878,973,581,79,500,346,653,404,135,851,264,897,918,322,917,214,755,397,181,864,123,686,531,779,233,557,869,574,914,152,858,895,171,42,861,950,468,125,961,866,280,28,781,616,161,655,762,265,84,955,671,505,813,19,726,82,152,987,126,58,808,949,764,267,18,41,243,168,60,349,436,513,582,308,8,740,733,562,168,642,216,433,86,11,542,467,125,156,726,883,807,88,981,212,826,190,283,319,673,331,612,762,517,271,682,851,183,129,24,129,312,829,577,524,922,181,273,821,987,386,606,250,36,700,278,55,514,826,453,188,751,212,479,699,179,740,894,471,985,300,98,65,680,185,621,730,566,634,92,290,966,307,636,380,867,646,444,456,995,270,329,392,504,115,686,909,518,514,945,813,25,336,238,547,100,324,342,157,679,254,525,189,733,323,282,351,846,936,401,825,247,66,178,46,82,289,955,596,62,907,37,19,17,790,981,358,658,738,606,47,846,559,396,408,989,458,96,814,341,966,604,609,236,818,239,516,248,104,957,241,717,370,655,740,120,143,150,899,258,276,689,903,247,691,687,858,357,134,987,532,510,811,779,280,611,363,84,744,570,653,41,22,738,357,913,982,144,901,585,12,831,195,127,295,621,383,173,276,635,902,132,246,725,550,82,109,519,684,0,320,812,967,814,570,997,285,342,859,378,441,410,212,328,242,845,82,897,602,397,654,874,966,858,598,102,616,440,900,327,9,503,275,428,222,814,450,816,419,770,284,314,66,381,204,770,195,252,725,288,172,410,802,662,647,568,164,106,424,459,574,896,588,799,414,447,35,108,763,393,866,404,976,329,298,17,204,452,489,754,324,811,254,81,742,529,881,872,897,780,830,127,263,910,347,845,477,20,912,884,354,618,816,21,468,255,285,554,61,306,153,459,688,306,316,732,327,927,491,535,297,927,422,138,856,503,720,993,339,907,71,627,605,164,935,517,252,419,63,502,394,68,461,282,646,491,537,413,721,204,722,293,216,137,430,650,568,411,480,292,992,147,585,980,936,907,669,415,888,434,810,635,390,801,333,451,826,562,451,731,696,594,114,544,860,647,774,920,305,242,871,228,55,196,18,756,764,623,920,207,23,162,433,223,299,616,954,422,591,185,949,256,628,997,485,420,976,299,298,743,902,867,913,37,272,198,748,112,90,264,272,600,39,473,524,288,876,383,579,310,68,658,305,830,530,971,233,334,873,439,942,13,32,508,221,634,874,34,485,853,328,988,10,146,516,30,168,979,371,8,104,911,800,861,615,643,408,201,716,182,255,521,733,628,338,81,521,542,998,974,590,280,50,983,716,365,2,423,268,329,9", + "714,626,67,830,872,189,532,479,559,354,439,835,864,511,723,182,457,705,501,675,263,979,620,506,948,940,549,242,910,280,284,823,603,936,846,827,98,144,211,664,885,944,709,270,613,653,887,545,341,409,999,457,677,810,324,100,694,581,609,244,92,656,887,688,583,274,411,740,722,587,421,324,130,93,738,589,946,1000,761,242,519,425,836,846,439,859,420,295,187,389,910,555,440,894,975,561,884,974,772,104,138,988,656,990,943,383,242,730,979,642,381,502,410,876,767,135,103,356,214,831,363,24,846,296,771,623,802,128,501,967,290,348,744,327,117,95,302,743,707,256,302,446,372,176,480,10,994,532,696,896,456,970,998,411,150,543,542,384,188,243,785,510,388,273,710,382,141,975,895,647,513,715,47,369,112,612,721,985,753,929,62,498,983,167,307,912,733,488,642,504,500,33,592,558,592,530,336,851,491,37,531,587,18,713,422,48,759,740,858,990,947,546,25,542,999,132,854,762,711,801,79,873,926,660,415,825,694,92,634,209,79,214,72,227,454,683,767,127,499,112,113,218,615,358,656,644,642,789,877,394,306,346,867,807,112,571,450,203,992,669,201,33,936,182,13,406,910,897,830,170,568,535,186,584,458,892,982,125,85,38,920,564,613,258,163,971,457,300,125,63,333,892,784,94,325,846,948,772,869,921,28,461,542,850,695,810,242,291,651,449,351,151,917,957,392,223,842,364,975,32,277,679,871,348,432,689,567,705,326,859,785,317,129,197,805,738,504,541,277,190,970,177,502,110,433,594,469,214,135,380,614,819,134,936,588,721,569,606,984,509,418,164,740,721,249,361,260,652,170,245,754,489,856,639,579,524,245,700,514,451,885,609,979,855,116,567,972,484,896,615,609,326,209,24,621,126,129,928,788,842,919,716,410,680,325,297,60,452,669,633,767,239,355,508,553,786,178,389,863,446,105,487,219,41,965,685,507,54,109,254,499,106,120,898,268,867,497,494,265,797,790,363,443,644,617,169,393,226,538,547,900,430,905,654,997,787,645,842,653,838,520,645,466,295,363,855,34,998,92,481,459,331,458,463,376,661,556,528,953,684,701,474,771,629,476,65,818,534,456,196,162,856,671,412,272,993,808,955,4,578,77,770,495,620,659,663,429,815,146,849,433,443,397,89,118,250,747,16,217,36,530,874,660,272,514,871,337,437,918,410,594,323,431,562,183,457,467,875,41,222,400,178,161,757,22,750,77,714,613,669,428,384,561,266,283,401,232,42,730,769,696,588,46,606,952,813,47,772,390,913,737,969,287,603,35,901,502,298,161,771,917,926,533,24,38,753,352,551,537,484,385,954,123,111,560,527,666,504,131,401,468,253,758,151,199,382,983,590,429,39,862,939,740,740,235,156,549,392,210,815,696,127,67,83,157,68,261,495,664,271,696,72,924,525,695,603,926,883,95,737,323,37,506,927,356,16,470,583,320,157,265,563,467,564,129,465,758,216,386,356,660,489,641,114,210,569,69,563,614,570,626,653,666,434,746,951,549,595,180,716,957,118,158,416,220,833,247,657,893,888,712,756,879,313,456,491,220,441,320,0,254,192,341,990,256,932,598,429,51,847,44,587,799,548,518,75,739,95,433,843,827,619,819,750,728,557,516,57,682,3,123,450,309,27,458,593,84,570,49,62,139,953,461,388,430,546,316,194,491,118,676,990,789,313,438,279,679,786,144,740,350,867,884,180,369,648,378,669,556,239,162,967,103,275,578,534,575,144,300,151,246,41,747,521,998,169,973,455,34,595,794,429,544,305,802,421,123,738,591,668,672,396,285,507,942,417,590,152,302,601,904,769,875,343,478,244,712,792,983,132,235,855,759,119,248,480,676,287,291,927,55,621,508,976,909,882,902,456,656,699,943,128,87,571,412,427,714,469,426,601,469,530,95,540,149,324,940,287,648,168,429,944,520,53,800,756,346,251,849,741,639,764,838,653,548,83,785,384,691,88,196,489,615,324,189,538,755,340,753,674,152,503,553,468,295,563,706,402,896,311,976,179,279,519,227,635,535,194,659,506,78,363,923,212,58,888,681,381,629,488,504,411,323,322,63,7,178,417,93,943,810,439,812,884,96,990,552,852,771,988,147,694,365,936,191,143,58,471,463,42,804,844,690,916,482,152,343,52,429,519,345,673,675,690,552,323,14,918,56,653,527,74,973,873,547,764,957,727,66,165,832,879,80,736,625,213,277,932,412,533,309,316,896,403,190,251,80,376,499,753", + "942,550,102,363,260,414,262,612,298,509,238,735,938,76,693,367,870,816,467,11,242,607,492,425,586,59,628,881,441,122,927,593,179,510,83,151,542,851,514,151,928,717,228,566,234,471,959,157,251,26,945,931,412,937,762,312,395,592,754,165,528,86,761,19,469,947,73,141,154,908,622,211,979,126,57,628,121,143,792,364,410,247,387,961,431,658,24,961,734,365,501,472,420,731,686,119,679,890,846,395,949,840,785,518,858,191,291,944,174,693,137,732,364,429,389,7,945,864,514,372,44,731,680,294,131,379,69,892,306,152,186,694,92,962,246,841,250,463,207,166,181,316,71,309,82,450,406,94,975,923,393,102,47,792,148,775,78,563,835,564,209,518,156,913,756,385,663,382,642,266,705,333,723,97,964,817,702,386,262,195,944,1,608,393,730,588,918,887,877,500,428,908,94,401,762,585,334,678,581,666,824,809,549,62,396,619,503,206,541,691,61,556,73,965,831,573,877,968,724,594,493,91,562,731,368,797,911,577,241,635,55,452,23,292,42,664,146,406,510,264,887,315,932,675,427,340,811,106,413,537,998,159,809,903,617,452,841,404,141,49,545,982,344,567,163,167,730,390,983,78,153,502,504,995,778,589,759,725,718,685,916,222,290,208,903,890,281,953,56,203,806,517,950,193,623,233,780,613,869,742,649,252,679,54,792,350,101,350,672,354,37,892,920,391,291,229,638,868,677,571,513,201,643,249,642,743,200,626,620,853,239,264,75,625,668,103,992,866,39,944,902,346,635,442,213,998,573,6,221,318,855,173,391,660,874,68,101,344,742,224,461,494,521,30,375,161,678,773,983,580,576,663,62,481,290,137,370,89,299,766,542,230,25,482,254,111,775,257,460,411,940,533,662,987,312,427,796,759,363,919,306,200,802,430,89,44,337,814,146,936,307,717,529,806,633,720,898,190,378,747,900,889,910,753,945,237,454,225,688,30,413,78,291,461,310,644,900,299,451,946,360,700,262,612,462,179,921,977,575,48,222,578,844,256,277,494,446,205,429,185,519,297,337,768,451,205,892,740,41,172,223,174,799,528,534,338,163,438,250,772,370,104,105,515,451,43,338,983,959,876,816,968,836,595,898,649,963,2,49,121,932,510,77,111,453,746,368,564,717,389,780,778,337,271,666,414,308,71,294,392,762,547,102,884,670,546,546,193,990,887,983,356,966,355,174,860,888,872,49,375,389,18,534,808,734,212,66,372,786,829,581,859,284,699,157,524,119,208,573,54,60,163,77,417,494,689,212,44,372,8,35,582,464,67,687,42,285,615,942,355,83,580,829,571,920,294,703,154,20,153,555,319,648,297,986,622,944,833,935,525,516,207,62,75,303,880,212,316,130,2,774,280,658,223,550,48,913,831,494,105,688,924,940,727,868,457,60,713,326,113,473,99,778,614,254,626,82,507,251,449,305,597,689,505,362,896,834,65,941,363,573,159,651,367,50,128,506,674,975,932,199,399,596,727,441,393,433,811,807,4,989,880,448,885,714,894,973,821,166,802,815,90,797,241,377,283,164,164,263,674,992,867,582,789,757,173,715,165,812,254,0,402,877,566,625,859,227,282,467,142,467,495,734,159,304,775,429,240,970,456,7,299,468,926,854,778,593,533,318,842,898,284,10,340,325,472,366,893,140,251,907,779,468,939,653,128,242,7,963,897,570,338,752,371,72,831,520,914,180,444,249,6,408,949,510,639,114,179,975,967,671,690,563,121,715,503,259,939,670,938,29,534,325,674,15,222,202,271,827,777,268,162,208,986,163,321,235,917,662,134,402,749,644,105,541,587,797,926,77,34,108,695,346,758,601,653,6,27,300,772,528,299,500,694,72,213,431,987,465,288,227,394,582,778,573,117,314,737,350,12,854,800,979,242,406,993,94,333,526,439,922,277,517,770,954,829,908,929,289,832,91,684,675,826,942,882,954,478,598,495,42,486,601,188,350,368,308,496,514,271,935,855,273,457,860,643,900,822,439,541,107,978,214,826,788,193,838,607,489,519,412,834,726,85,111,537,91,93,219,966,812,36,507,186,201,1000,200,689,87,484,397,772,331,882,7,93,371,162,50,445,939,114,860,654,766,974,252,579,628,561,164,983,935,451,411,136,365,505,312,169,935,782,276,676,539,750,682,871,808,716,950,320,693,623,309,455,689,932,102,287,919,99,573,529,487,899,267,363,367,566,595,108,701,387,44,322,307,567,177,425,656,376,269,535,978,219,805,456,99,184", + "501,221,566,921,187,596,223,716,623,949,478,161,301,183,781,39,176,133,83,843,862,601,118,737,816,730,714,20,575,227,205,241,198,724,586,544,692,180,328,158,973,64,792,739,814,537,857,618,580,968,782,464,531,744,461,266,237,213,387,505,29,863,653,196,104,948,380,2,851,843,936,518,627,53,634,821,875,718,660,774,713,645,539,544,753,207,311,447,413,763,947,84,22,433,324,866,246,521,543,858,301,210,584,118,770,244,115,346,94,923,144,32,869,745,30,243,908,59,187,297,811,537,417,796,890,735,158,19,681,14,171,848,344,962,443,982,23,725,821,567,71,245,507,332,721,67,772,846,505,42,14,567,890,311,162,690,704,961,722,575,855,470,763,186,529,795,194,702,794,338,910,88,76,150,431,83,363,824,463,913,110,17,57,775,304,486,110,847,136,996,946,618,154,186,763,881,89,683,834,170,835,721,793,590,403,152,887,617,979,697,605,774,716,337,561,311,291,580,718,921,471,277,41,792,328,599,767,257,653,437,36,611,546,100,720,354,56,449,120,666,930,948,94,28,387,70,646,444,868,763,317,979,509,565,905,122,87,972,362,233,411,719,361,428,509,331,646,796,481,483,931,566,224,107,491,934,491,323,60,112,241,82,550,107,158,190,510,230,205,331,819,904,967,718,391,975,431,971,945,73,871,620,853,982,905,257,156,966,499,372,40,717,275,641,436,577,512,151,680,68,196,710,664,849,309,285,578,136,829,148,274,493,519,643,847,737,843,704,276,158,491,972,109,604,507,129,610,55,617,26,135,886,879,729,850,88,324,832,66,27,997,922,333,701,47,450,203,924,642,130,71,832,853,119,165,644,330,191,692,856,376,546,271,839,616,253,618,613,281,711,330,627,53,963,910,101,29,850,592,734,231,823,50,426,257,292,951,348,86,511,620,442,110,932,375,520,220,85,147,915,296,137,893,271,535,590,595,640,90,292,36,348,454,357,701,316,837,998,118,127,862,380,288,89,591,368,183,605,864,765,483,570,303,129,206,51,124,869,650,899,880,193,562,747,506,42,72,918,189,567,44,602,95,523,430,71,671,337,635,318,897,83,270,58,839,173,951,381,690,190,648,148,277,818,173,943,255,969,754,454,818,27,570,978,383,36,94,286,591,433,527,565,340,635,195,656,163,897,228,393,719,888,918,952,956,87,649,172,981,716,67,508,848,353,207,436,750,464,688,469,682,98,970,894,496,546,201,314,381,328,542,884,144,893,987,344,553,193,233,963,472,63,681,10,299,73,245,709,236,987,105,853,798,139,709,3,71,479,528,724,354,632,37,423,340,830,605,901,818,374,661,422,99,784,962,997,516,289,744,209,219,502,674,492,72,950,803,152,997,359,91,262,801,781,189,147,937,451,453,700,360,550,377,111,138,88,560,159,295,634,112,419,494,938,634,309,862,619,989,112,740,487,957,866,754,973,78,887,538,6,574,881,206,973,783,865,701,105,874,722,819,668,435,548,165,53,436,588,473,863,896,469,570,336,391,853,391,282,242,505,271,625,185,468,528,221,609,535,371,32,384,535,837,37,382,386,6,372,967,192,402,0,318,890,402,164,565,344,813,410,527,848,498,423,47,915,363,494,433,381,536,920,337,48,764,50,690,511,230,455,460,339,685,491,454,503,747,88,534,241,115,202,930,175,394,822,547,13,69,549,8,215,187,14,963,77,568,338,925,34,193,330,619,461,598,618,675,430,675,774,242,481,406,290,170,333,69,275,944,286,256,780,972,542,237,946,722,844,642,37,975,243,130,149,524,447,464,824,258,992,206,988,250,724,575,562,242,597,842,91,526,12,124,417,552,394,553,887,367,501,248,429,102,261,828,266,824,927,681,692,704,564,851,626,388,748,464,683,582,244,562,772,558,561,871,648,552,67,198,907,742,990,411,347,112,426,753,163,583,703,154,19,694,508,700,424,705,338,167,98,995,705,86,705,619,711,297,679,516,82,551,65,273,670,64,967,896,446,626,792,53,223,498,327,917,526,316,15,385,634,486,298,787,759,474,530,879,433,658,295,435,292,77,181,418,870,49,871,900,92,805,871,938,309,726,406,107,366,474,844,985,73,552,339,211,2,157,704,74,765,471,492,607,428,230,980,24,751,13,181,713,439,282,942,243,481,936,561,211,133,96,523,872,460,51,374,703,992,436,856,523,737,122,55,440,780,623,544,678,498,246,760,280,302,817,841,401,312,438,212,661,561,285,272,876,717,529,370,372,104", + "378,670,502,839,911,996,948,409,816,266,142,453,983,115,501,144,265,774,328,184,640,898,702,349,523,576,589,345,255,140,87,36,360,233,643,580,618,377,359,538,739,977,227,428,666,758,352,726,233,687,67,363,45,47,573,848,233,658,162,901,731,314,42,587,129,221,968,208,572,265,632,513,354,273,163,993,451,86,377,899,987,558,191,947,552,533,803,510,168,222,637,439,263,956,976,633,685,837,482,465,309,953,867,45,673,367,329,143,410,59,499,245,479,9,431,805,623,331,476,383,799,733,872,774,557,920,863,483,738,919,282,926,390,179,190,932,648,355,411,226,874,691,840,642,875,182,138,933,373,316,883,700,907,787,693,955,17,423,356,457,511,887,303,770,135,679,756,918,216,141,335,981,534,152,665,992,942,278,460,586,889,987,388,531,119,930,387,947,599,634,848,524,194,920,321,436,987,116,843,577,187,549,608,956,103,898,815,121,228,638,644,149,958,901,216,552,900,529,603,532,700,207,195,695,407,991,951,682,921,317,575,726,769,138,438,206,590,25,878,475,686,924,983,260,10,291,609,740,902,402,242,234,438,704,525,904,269,541,992,887,310,560,22,867,469,296,266,964,3,487,438,94,385,983,180,209,587,379,666,11,84,365,68,992,659,459,936,722,359,375,833,915,896,960,133,100,695,504,82,365,738,424,601,36,118,407,769,463,436,672,423,833,543,332,277,334,93,407,890,555,36,738,875,127,251,698,426,427,55,654,139,681,456,41,64,847,857,18,669,738,87,329,961,732,167,855,550,240,628,597,445,882,673,231,255,242,815,807,584,908,218,639,15,897,641,22,763,248,610,601,754,254,243,246,896,743,685,892,834,472,4,734,128,158,313,615,504,358,442,190,389,345,330,497,257,531,232,703,137,173,585,258,904,655,184,724,616,428,478,859,795,710,51,464,170,95,498,728,698,752,811,797,208,265,364,575,714,898,558,741,998,861,30,110,904,487,141,455,371,857,72,120,738,663,622,759,267,934,740,377,30,265,800,551,279,750,710,713,685,502,507,847,276,145,644,899,296,627,261,720,714,728,97,670,639,971,531,854,176,424,912,351,459,977,59,887,931,136,447,290,14,131,549,429,180,607,816,986,294,720,586,915,283,231,731,912,871,66,906,904,555,319,352,395,92,276,572,50,464,635,871,934,83,524,385,41,299,828,649,215,377,266,230,263,354,5,162,52,195,110,751,6,910,883,523,811,608,220,732,797,142,823,565,308,535,427,122,203,721,841,465,410,14,590,107,722,760,633,48,64,724,671,366,21,628,876,317,895,710,396,77,396,489,387,182,424,774,954,764,627,418,334,989,756,502,82,560,72,150,606,108,366,289,434,925,441,256,660,336,76,407,772,120,331,842,908,406,899,191,755,899,496,886,593,681,252,625,421,922,189,906,867,751,789,36,790,230,793,295,658,926,473,824,198,509,472,505,806,719,688,185,428,462,422,438,407,610,404,839,2,987,356,946,450,791,253,39,691,681,375,158,868,562,734,259,300,595,267,695,988,538,636,89,689,154,641,223,509,951,820,484,739,796,262,242,60,836,524,814,341,877,318,0,811,992,188,669,114,529,730,420,124,269,23,896,805,128,159,996,970,639,877,615,766,155,300,195,924,493,990,241,469,711,195,697,355,645,920,882,275,721,270,416,655,771,391,291,7,130,520,726,241,979,24,110,345,628,895,754,746,966,287,319,641,667,50,239,237,157,37,811,732,563,337,133,936,929,294,516,897,360,964,442,204,781,321,43,738,403,805,604,941,916,309,241,67,881,367,55,531,606,195,147,765,660,711,859,505,436,161,433,553,420,161,848,277,627,473,535,684,499,541,636,555,898,115,957,349,530,495,769,576,132,969,958,833,603,121,921,103,266,20,768,917,650,194,372,546,556,481,42,679,656,849,40,666,420,689,266,269,583,993,952,492,96,376,652,427,372,627,804,617,701,749,912,818,840,892,987,963,583,476,493,970,584,633,977,992,920,489,466,97,44,780,620,49,186,193,51,884,115,125,561,389,921,195,774,201,156,940,380,949,629,99,902,814,206,491,779,535,987,873,857,122,514,110,100,556,378,245,625,430,874,190,645,791,146,844,195,60,273,232,240,794,947,443,622,632,453,85,364,736,111,40,965,685,278,886,815,784,88,904,762,378,869,597,826,675,539,429,300,749,893,445,134,715,648,603,287,514,513,148,501,529,811,643,259,539,462,163,37,60,128,830,587,495,511,727,714,420", + "192,295,796,113,918,4,859,362,200,468,983,545,294,514,35,135,545,347,592,611,25,808,4,200,122,45,785,199,901,64,432,293,909,307,476,395,880,300,798,986,963,642,337,113,174,747,560,994,390,876,504,29,606,894,420,606,936,974,494,102,252,383,422,719,117,998,232,217,703,240,145,820,85,87,923,106,479,993,215,334,760,317,963,290,701,460,836,76,560,23,524,766,116,814,883,135,651,723,231,633,833,199,691,847,983,825,113,861,503,82,850,750,185,134,455,407,167,34,966,925,256,845,499,917,472,153,929,718,956,184,617,909,981,398,153,155,82,928,740,760,819,547,952,986,906,112,667,910,69,242,79,853,196,803,559,410,620,67,137,195,180,177,536,548,367,70,262,943,298,69,765,692,440,382,290,925,687,331,989,613,786,354,32,820,955,131,716,565,2,791,286,18,691,887,997,498,453,157,887,89,159,835,878,985,243,826,501,337,572,973,991,974,400,135,540,819,995,854,867,188,742,25,101,77,289,89,276,633,115,326,87,452,301,543,329,935,89,423,577,11,59,158,488,638,741,160,218,943,411,663,282,691,144,105,757,743,347,557,180,614,477,536,645,650,238,253,666,900,254,472,336,136,941,755,841,255,90,794,412,554,976,671,902,113,740,570,185,690,794,727,767,3,799,128,774,361,191,370,67,197,242,716,709,313,319,748,144,39,386,3,74,543,916,202,722,967,862,217,410,992,810,425,829,17,410,278,526,886,858,480,906,788,295,265,384,786,5,70,250,228,563,470,832,426,28,583,688,256,678,9,469,238,817,276,971,906,679,741,569,819,562,489,868,633,41,471,539,120,631,295,545,49,333,776,194,563,461,560,368,401,942,645,941,834,838,286,534,112,627,510,818,55,295,653,797,101,405,740,939,876,666,770,336,898,23,177,658,59,157,155,302,517,386,922,85,17,283,629,440,282,193,334,59,904,887,791,237,464,795,759,562,1000,677,215,142,213,476,461,840,121,782,390,587,569,67,874,742,325,128,499,962,835,96,697,196,255,654,952,21,356,982,488,984,721,61,542,911,769,138,130,178,702,922,238,728,503,177,978,834,842,352,650,8,55,613,678,132,852,742,324,632,723,261,233,9,972,433,894,623,662,436,681,365,19,394,25,158,380,723,960,253,343,921,181,875,825,966,353,442,127,120,609,537,704,527,877,329,973,778,772,49,760,151,468,336,992,656,45,834,51,611,826,598,72,73,364,955,25,758,460,430,584,317,265,744,848,708,76,305,893,670,300,120,206,125,874,760,854,913,431,140,825,861,41,728,418,927,106,565,246,534,23,822,557,879,422,578,184,306,401,662,752,476,521,280,715,208,835,474,7,13,918,459,567,526,435,58,894,823,863,373,982,414,887,49,408,932,569,290,709,257,419,73,36,816,270,116,328,692,617,618,873,350,107,281,508,908,137,621,216,712,671,901,608,820,500,328,368,366,83,40,40,349,521,243,180,256,86,841,388,577,807,383,671,145,921,731,299,899,5,541,65,631,433,607,77,405,313,757,845,953,933,736,48,269,979,906,477,59,147,364,544,294,544,120,520,256,685,570,990,566,890,811,0,211,992,355,585,331,204,980,737,179,758,550,68,3,536,302,990,713,840,474,522,453,67,377,657,435,727,622,936,834,177,215,469,879,687,373,978,384,372,713,751,268,826,265,863,535,943,549,376,445,394,740,178,658,27,992,476,456,259,298,62,280,395,96,151,424,222,798,684,117,269,632,631,172,664,725,46,265,874,777,195,30,957,802,710,73,956,767,99,15,326,621,872,273,201,224,317,588,881,240,970,29,873,521,822,339,468,773,149,912,104,193,653,257,695,442,292,314,942,809,552,656,523,500,81,90,709,733,596,280,69,405,619,26,612,855,488,634,427,42,515,209,281,113,139,75,484,393,930,100,56,312,170,348,355,30,2,993,923,267,898,785,809,226,489,575,693,896,285,814,628,559,990,549,221,755,98,979,821,306,528,428,844,762,837,385,7,726,102,390,840,424,350,970,346,767,799,651,903,807,692,282,585,946,35,885,758,434,473,223,462,655,768,838,197,66,879,943,593,67,831,209,57,384,655,294,488,424,610,318,886,41,676,958,278,105,277,201,428,220,675,672,594,752,964,386,422,70,369,749,102,476,352,29,702,289,171,194,186,252,513,343,129,379,406,774,520,715,503,855,112,972,541,548,56,25,302,626,608,266,664,69,162,542,356,971,232,920,52,177,669,241,612,94,652,380,760", + "28,353,11,129,541,697,463,543,793,392,25,345,118,844,240,150,909,762,952,707,181,121,457,79,876,981,270,777,991,691,981,724,631,885,978,777,400,132,733,920,365,616,373,418,704,652,490,271,833,495,598,601,659,267,779,640,516,92,958,998,87,713,260,241,991,214,869,721,498,414,669,956,701,485,666,497,111,127,309,666,814,604,862,437,522,691,857,109,190,243,239,404,301,228,353,69,883,240,463,239,863,620,468,85,27,171,356,843,36,472,660,361,586,483,771,527,83,394,877,722,391,923,811,525,196,587,431,470,978,165,833,119,198,234,894,702,145,397,959,68,877,351,575,978,636,346,207,529,601,223,469,683,750,765,436,231,497,598,919,175,223,980,914,247,624,627,53,155,855,144,337,46,22,739,952,756,100,806,302,512,428,474,38,428,682,608,717,226,978,193,639,961,112,396,569,789,579,459,874,250,336,6,114,2,613,557,719,365,885,646,870,287,289,68,208,464,368,673,164,852,806,357,810,421,746,887,387,309,219,959,267,144,22,826,794,301,397,504,245,657,243,772,272,617,580,720,448,293,604,772,648,645,23,970,217,218,503,17,850,144,802,13,623,208,196,942,83,852,322,209,538,539,943,785,561,930,932,856,926,950,591,496,107,22,706,24,922,429,719,619,265,30,272,253,94,957,142,155,921,766,570,263,855,286,388,712,288,976,150,379,931,102,251,986,812,663,125,30,890,346,630,905,545,393,154,247,723,864,570,209,273,637,689,38,580,928,360,650,417,309,753,751,911,145,318,785,577,777,720,836,966,891,715,695,996,344,779,399,567,355,59,791,64,529,265,340,802,971,628,796,359,370,334,187,425,97,633,316,324,655,836,449,916,968,946,872,105,494,494,608,586,426,305,336,621,835,654,571,481,682,680,325,732,707,254,518,645,523,959,296,79,302,235,647,989,221,914,167,494,306,592,113,436,637,62,295,549,677,248,32,745,58,71,458,821,181,13,225,608,61,277,27,478,934,552,242,350,761,791,451,771,983,803,246,58,424,259,391,462,302,176,843,968,525,463,263,595,579,859,295,299,515,894,617,841,854,371,392,423,893,237,392,475,473,358,214,76,921,768,326,261,65,655,743,156,652,351,332,969,994,672,601,307,500,449,820,566,871,328,83,682,319,764,815,991,538,738,246,415,421,305,99,981,508,281,169,991,629,980,837,290,619,320,78,860,14,127,433,657,140,96,444,582,430,524,164,108,713,260,67,127,393,521,367,633,319,697,443,960,678,295,809,696,400,905,936,760,951,241,513,39,120,914,855,270,8,764,432,283,334,115,612,988,169,476,236,727,595,688,78,247,30,319,472,802,757,790,436,447,735,979,464,377,865,519,228,706,394,927,534,809,135,76,628,498,7,652,745,115,577,237,773,306,253,595,779,661,813,208,738,242,902,880,881,652,33,58,827,59,288,90,534,797,580,265,499,9,361,835,182,388,60,66,599,869,923,361,754,761,445,424,95,607,359,955,977,526,204,941,172,958,929,271,21,253,592,230,852,206,745,664,604,588,244,53,796,544,235,637,43,862,654,819,737,814,642,781,62,997,256,625,402,992,211,0,422,838,711,8,602,118,305,63,307,794,712,651,23,919,131,653,353,338,170,671,69,684,380,607,675,92,927,535,186,117,340,498,207,160,953,563,643,2,799,896,134,566,337,732,383,768,250,318,992,907,881,639,804,360,392,420,348,771,264,439,943,425,186,348,914,402,715,593,543,585,317,308,915,684,217,478,510,655,186,901,795,201,695,570,995,86,513,138,652,39,780,167,355,694,880,81,700,203,593,350,79,588,137,972,779,202,390,686,942,482,462,768,950,518,106,199,341,536,144,159,536,634,728,937,597,255,324,74,999,808,461,328,318,553,837,629,335,825,282,633,536,31,622,930,478,896,411,411,267,298,999,429,129,540,875,491,975,574,499,664,918,910,410,828,59,924,484,58,420,49,826,754,160,229,768,588,829,871,311,742,379,104,777,841,176,240,498,229,380,725,204,790,57,325,296,929,614,747,983,741,730,342,957,800,411,419,400,943,855,946,756,716,359,37,244,488,168,631,920,902,53,198,12,282,764,757,712,413,40,853,832,301,80,569,129,203,851,630,926,474,43,268,798,361,441,454,632,532,584,47,591,125,717,493,252,214,558,458,671,971,709,593,315,347,847,755,679,476,423,156,621,399,903,605,283,671,713,174,844,638,216,392,503,500,215,590,228,372,38,981,966,345,931,352,771", + "891,690,186,710,328,939,91,452,514,393,864,438,223,964,783,544,457,381,109,256,737,721,50,728,235,546,778,834,254,835,924,690,478,698,213,3,777,595,993,462,828,119,756,183,456,476,354,660,976,233,377,915,776,377,688,364,150,605,475,72,586,134,819,77,843,148,675,745,865,792,387,781,788,162,296,515,593,652,975,942,680,913,327,458,896,295,946,513,260,115,636,30,25,117,919,4,548,490,167,33,251,710,353,668,373,306,806,505,645,735,380,663,899,641,935,835,474,197,330,117,346,714,390,781,609,826,439,60,451,303,810,590,76,236,337,632,546,955,144,833,278,535,670,603,421,898,994,634,74,121,196,82,739,598,84,915,171,356,43,398,165,41,114,453,278,239,897,175,156,670,579,121,931,724,990,722,206,774,540,248,753,503,130,238,455,708,282,366,594,363,316,312,418,337,527,533,908,671,212,29,37,132,133,16,835,169,595,722,83,773,12,327,407,975,964,985,716,873,287,171,8,879,841,205,294,949,861,545,876,864,7,996,440,225,217,1,790,595,442,652,315,521,472,323,609,895,750,657,237,139,625,201,911,379,554,661,250,711,972,926,25,788,413,874,753,9,566,945,742,847,813,398,633,447,465,927,115,723,30,729,192,891,58,636,80,263,260,983,366,923,777,582,545,12,954,373,960,194,45,198,586,589,319,247,42,481,415,817,107,144,432,442,817,692,433,994,23,913,685,666,973,29,634,285,936,330,498,635,889,856,885,520,739,63,634,492,830,128,761,867,948,153,256,400,533,312,316,939,166,54,855,305,594,293,936,94,136,616,581,142,873,419,271,4,737,529,21,106,443,158,624,228,556,493,34,255,475,700,674,686,724,878,352,851,101,161,966,595,680,54,153,585,35,738,549,39,338,896,139,28,231,526,9,935,705,786,582,82,855,350,54,894,330,457,83,284,740,344,616,447,53,718,971,96,251,421,466,845,587,345,416,576,284,416,733,519,89,138,426,949,472,85,95,49,539,922,177,989,877,246,403,360,506,752,322,713,969,632,256,224,27,701,393,770,486,168,375,616,927,484,140,827,182,436,831,737,961,556,330,614,205,396,590,705,577,750,286,816,839,163,244,94,503,318,961,515,642,677,621,114,359,58,841,214,387,661,965,806,646,362,314,460,296,484,793,556,232,639,562,882,965,207,850,186,140,601,307,407,460,719,453,675,617,35,838,435,823,797,230,525,730,332,128,415,694,825,418,460,485,496,670,640,569,756,538,945,496,813,191,570,76,97,481,781,897,478,38,776,985,468,385,879,277,585,318,104,649,118,223,814,633,18,885,101,969,82,117,671,338,527,72,417,964,455,797,659,450,806,53,302,886,600,155,963,380,697,461,781,547,68,661,203,792,2,460,756,311,604,468,973,676,582,90,198,645,494,202,291,62,225,919,460,629,983,829,45,757,265,240,674,245,674,413,984,245,905,731,35,46,478,6,425,636,985,959,118,148,172,168,916,286,454,289,553,735,887,458,585,908,884,83,677,768,310,449,815,71,328,530,649,937,104,803,642,72,469,688,649,858,104,488,224,60,246,730,806,398,744,285,932,859,164,188,992,422,0,388,729,148,156,429,965,156,404,581,43,365,934,25,172,507,901,184,698,377,421,490,819,694,414,606,269,157,276,809,779,102,690,983,651,72,453,886,582,873,569,765,303,107,315,892,906,616,982,737,963,211,466,60,810,246,226,308,303,540,606,672,602,188,499,666,476,490,575,981,97,782,822,174,453,198,172,892,671,460,250,827,989,92,107,288,862,590,537,723,462,186,6,668,908,224,276,997,67,5,121,723,905,465,261,669,977,895,88,292,556,43,781,396,124,361,542,756,107,805,102,682,687,778,950,779,753,541,422,371,237,864,346,321,359,6,924,995,762,571,691,84,383,50,167,573,986,492,153,130,789,952,988,58,875,986,90,376,266,373,892,440,581,925,574,70,794,541,124,40,170,285,191,61,283,980,532,812,155,900,104,448,801,589,809,505,519,941,844,590,332,159,142,688,759,910,737,65,925,669,393,792,576,449,947,646,256,601,621,514,924,609,106,754,412,710,929,833,792,930,99,671,425,676,146,55,628,373,569,166,94,401,26,573,320,640,548,433,198,23,162,342,958,925,176,151,159,463,154,403,907,941,251,51,310,897,759,250,897,8,650,349,489,363,69,342,256,534,14,620,124,46,676,576,809,195,238,154,358,667,271,888,758,721,653,268,691,729,691,484,183,488,997,860,242", + "694,167,127,623,517,246,700,994,228,567,757,308,174,230,638,40,762,350,269,148,397,539,529,823,68,332,212,284,247,478,137,77,646,85,744,245,885,497,427,201,81,449,7,341,198,768,584,444,521,21,837,674,742,729,193,135,786,740,651,547,462,720,583,66,834,451,108,830,308,292,330,857,612,795,620,211,953,205,686,964,919,226,683,16,806,603,363,9,134,669,408,23,379,656,935,600,446,984,710,369,58,430,924,686,761,698,409,867,673,451,773,367,365,223,382,669,658,789,442,793,493,228,674,110,974,523,953,936,697,521,215,203,513,10,530,521,301,865,319,728,887,770,515,661,589,667,204,431,912,860,98,608,491,388,97,394,956,711,938,203,219,444,434,441,55,658,640,266,351,45,592,529,446,249,950,369,311,659,920,554,94,588,758,477,971,422,835,934,46,576,128,463,939,541,535,104,715,479,880,677,783,866,931,719,574,111,553,271,642,184,310,860,236,44,325,280,475,228,221,658,389,347,541,309,323,198,780,273,481,471,389,777,250,348,572,784,955,453,385,613,570,914,456,928,312,516,185,672,520,854,323,423,66,828,41,903,652,182,243,423,984,938,217,672,450,773,979,141,600,795,770,135,706,301,208,597,971,514,557,272,39,28,211,500,876,62,733,688,501,438,991,864,658,585,938,498,865,900,845,582,880,460,665,31,359,87,670,435,510,357,451,861,479,59,894,95,381,717,571,87,505,801,830,715,541,894,488,85,554,837,251,906,268,72,479,377,260,174,695,318,228,792,473,230,962,56,20,185,217,251,806,162,904,1000,83,567,358,231,316,698,607,498,266,515,324,554,692,419,257,24,854,794,670,119,292,484,312,229,63,858,190,922,396,413,403,275,617,11,325,886,20,712,803,795,953,826,892,825,724,579,560,370,203,89,265,896,153,313,175,54,227,980,906,424,697,385,422,543,641,663,377,509,28,866,16,678,734,528,403,45,150,321,224,221,148,719,490,745,475,835,52,717,621,707,726,112,787,741,46,956,515,115,21,625,352,485,962,835,725,141,857,178,810,168,4,370,891,743,104,737,93,958,872,787,679,596,140,239,117,193,816,319,533,368,611,858,453,98,464,785,908,894,536,809,876,532,397,596,113,145,268,363,523,495,773,489,921,459,399,721,792,419,615,908,588,986,821,964,62,337,874,866,211,654,13,28,235,661,630,95,415,91,976,664,377,714,192,759,889,667,137,306,727,86,108,509,373,246,458,238,232,166,205,144,85,253,532,280,488,692,243,373,631,550,423,342,444,283,787,95,550,450,231,362,742,19,479,25,428,177,754,124,26,747,725,83,722,800,971,317,417,441,433,333,307,811,527,674,525,454,387,979,414,133,79,194,10,282,55,277,103,971,185,341,764,998,706,724,322,766,497,571,860,196,254,531,108,625,9,541,676,8,916,466,46,517,244,236,964,679,705,103,382,607,14,691,700,3,323,695,217,615,734,610,17,593,601,693,149,615,452,425,910,944,479,265,760,452,43,698,65,83,291,500,929,468,935,498,344,538,608,231,190,847,749,396,582,366,198,836,577,787,253,672,388,195,472,514,342,598,227,565,669,355,838,388,0,26,619,847,889,425,734,677,892,188,230,32,471,941,499,102,260,871,475,639,658,654,98,475,175,63,403,806,227,234,296,76,655,129,170,167,428,551,54,789,613,180,403,41,345,530,714,219,195,665,179,632,423,333,921,406,203,315,752,536,401,632,17,973,371,975,591,101,398,427,652,91,666,353,916,602,536,193,385,174,984,863,154,257,635,524,962,57,443,178,532,919,104,47,921,924,584,522,924,537,488,801,224,877,557,123,149,564,612,348,414,650,37,319,369,477,868,105,257,775,249,682,99,803,881,302,426,29,164,133,974,336,195,669,7,224,164,216,357,929,7,836,221,556,478,108,566,212,728,780,629,67,36,472,580,53,546,835,4,217,832,656,518,16,184,84,379,906,518,997,256,681,264,637,33,978,625,875,748,425,44,546,850,996,248,673,771,628,481,35,353,808,286,246,665,687,713,750,667,798,209,982,930,40,145,966,132,251,351,659,86,634,374,920,127,840,830,886,227,908,583,231,574,741,751,472,749,687,723,140,212,408,418,62,581,150,626,286,877,630,131,881,128,716,650,855,927,779,415,774,522,906,586,948,514,971,893,561,472,387,814,244,257,255,684,690,293,736,244,109,165,301,543,923,306,540,400,797,707,953,711,901,601,37,779,314,884,493,410,782,160,450,671,791", + "37,99,426,992,743,41,195,374,687,383,810,381,333,914,103,411,448,170,5,906,970,685,374,582,23,110,606,863,577,117,14,438,604,577,342,723,59,955,7,496,484,655,605,123,162,612,848,826,411,552,357,485,347,40,658,276,235,702,502,504,730,110,790,582,310,64,239,123,729,426,955,300,376,530,20,446,551,276,769,921,897,127,244,360,677,534,521,20,517,782,205,774,594,114,668,59,555,787,394,274,522,755,697,692,281,194,543,179,280,166,756,73,753,482,406,729,251,953,974,657,55,111,497,172,582,404,375,414,617,170,481,6,451,245,310,809,496,136,256,989,922,604,985,192,502,695,570,1000,286,497,647,101,610,208,869,227,950,653,768,31,782,201,597,532,712,944,944,269,118,932,250,620,916,177,818,769,357,730,34,789,258,298,475,819,239,585,329,146,949,564,352,184,554,727,274,291,790,736,718,209,761,337,261,984,274,819,660,175,104,772,312,65,916,744,720,965,434,997,873,661,222,149,932,783,713,147,536,214,706,81,707,87,397,710,824,89,94,42,545,207,442,187,359,171,614,985,910,193,282,730,301,416,124,897,966,770,252,525,380,189,171,421,646,860,104,529,708,499,688,63,772,22,388,382,268,929,892,125,438,689,831,477,844,115,385,236,426,294,797,300,376,517,454,378,172,708,945,59,151,813,98,298,882,269,678,452,295,76,456,953,263,852,239,259,923,657,937,873,231,754,483,194,490,638,228,749,597,672,888,310,657,234,365,986,681,130,457,410,205,423,556,140,456,940,944,480,193,294,286,694,914,932,171,609,43,318,710,107,969,876,821,14,365,621,906,112,89,980,481,767,796,773,936,434,106,322,47,600,321,605,21,643,382,955,474,488,483,158,597,393,369,760,865,455,269,708,951,261,925,697,807,65,31,527,317,486,358,288,422,881,580,267,920,868,197,696,585,762,735,749,762,748,983,8,188,42,68,573,757,103,41,879,724,647,764,848,558,484,366,771,543,579,400,555,103,938,485,379,599,130,861,698,887,537,786,621,281,734,642,703,117,234,383,55,204,923,140,72,126,497,216,466,818,25,145,408,850,947,383,688,463,386,379,122,585,812,361,802,296,709,179,803,529,512,501,818,37,265,940,814,925,20,556,716,87,909,616,4,180,738,199,606,867,51,819,403,303,60,892,683,153,577,103,564,491,536,900,910,390,213,410,592,610,623,768,36,334,853,908,405,744,786,914,769,858,1000,554,393,235,912,864,31,516,364,277,873,421,933,837,753,512,458,259,471,160,694,401,566,367,534,927,973,840,652,463,976,263,80,21,41,420,190,113,89,666,198,595,709,938,629,682,273,639,493,693,113,370,479,439,75,563,245,555,280,360,276,16,610,152,239,766,889,412,481,535,688,61,406,528,975,486,994,300,291,67,822,68,838,483,598,337,878,213,627,414,515,713,137,507,888,931,601,263,281,39,743,387,608,775,700,971,135,3,495,65,50,121,86,60,440,370,93,555,354,376,623,324,821,398,571,139,768,601,784,350,751,193,110,317,458,230,493,898,991,68,475,612,824,218,524,550,2,516,477,508,973,781,129,859,429,282,344,114,585,711,729,26,0,373,430,665,277,591,470,740,530,946,255,98,297,776,733,701,569,597,379,823,562,717,37,778,100,15,830,654,605,902,49,270,244,637,878,147,620,785,335,291,11,886,616,656,799,845,534,3,431,458,189,777,224,400,555,661,290,204,625,382,1000,324,427,337,826,712,747,565,360,542,878,539,66,293,564,701,337,818,776,624,927,218,90,926,429,558,390,607,511,704,299,4,240,852,123,874,599,593,635,262,58,367,310,679,225,131,700,589,742,474,305,112,181,556,561,797,510,423,205,507,204,895,616,357,555,67,305,171,246,350,323,484,521,928,203,168,627,223,161,147,317,282,683,623,856,40,292,297,901,566,689,195,543,505,859,590,170,185,267,46,978,859,243,771,998,461,310,789,862,168,321,291,819,434,33,729,906,259,838,520,307,943,5,808,962,387,882,527,759,886,691,13,639,92,771,628,977,941,650,196,643,794,428,617,814,974,409,401,410,881,830,638,322,10,464,407,161,443,870,843,607,897,183,407,714,536,68,44,746,401,421,755,939,971,658,693,987,517,349,690,497,102,755,766,919,425,933,523,325,330,402,189,538,492,916,694,48,755,882,635,952,411,662,70,266,260,54,148,501,51,724,698,693,937,514,871,941,461,119,659,33,740,933,845,863,445,909,55,555,454,371,787,729", + "788,370,656,97,975,657,364,961,745,978,295,80,213,592,343,766,146,126,767,882,523,380,169,666,784,471,495,420,97,943,33,283,826,40,435,911,589,758,97,638,888,490,311,232,196,259,749,970,667,429,542,409,714,482,873,161,225,686,537,309,475,90,756,30,235,186,456,181,966,26,679,100,393,416,444,847,792,654,371,216,858,508,232,539,760,118,929,678,453,192,27,947,427,514,362,212,160,606,937,235,616,554,877,272,708,211,399,351,771,246,836,314,612,394,524,39,474,671,514,364,364,103,952,753,748,802,856,543,898,617,369,213,309,416,348,292,549,305,562,677,434,103,238,342,165,484,419,29,52,398,81,392,469,468,129,230,504,721,787,809,813,978,341,28,192,673,73,125,683,455,604,759,649,232,338,363,679,176,593,152,417,648,587,999,898,761,770,673,328,592,991,14,489,8,721,343,559,636,193,425,954,823,386,8,29,898,531,312,568,438,622,908,511,70,859,267,909,451,613,96,730,61,972,6,88,683,83,75,222,870,507,28,418,993,133,325,707,103,800,629,680,942,308,734,530,945,615,137,389,948,84,742,118,538,465,431,201,43,287,317,324,517,786,543,504,135,781,289,442,867,537,580,569,287,229,397,784,370,475,459,232,840,604,866,370,669,314,375,766,381,561,326,999,319,90,371,925,919,97,594,405,800,787,795,823,304,21,617,923,859,595,140,68,790,150,162,784,393,776,980,803,146,344,285,968,55,167,241,358,464,470,235,93,519,596,798,4,771,153,14,658,942,84,907,150,192,73,33,775,896,644,182,208,408,825,459,822,787,199,257,422,854,94,459,720,522,33,96,247,80,895,302,728,176,263,870,529,646,10,328,776,682,599,401,863,890,144,813,637,158,421,198,770,268,578,584,524,663,231,466,141,543,192,303,61,542,929,6,280,4,794,261,8,707,379,817,106,884,711,586,758,654,716,696,296,809,626,57,6,732,544,725,796,158,534,786,468,814,264,659,833,705,70,652,3,286,332,651,376,966,52,648,502,291,239,306,946,849,736,841,398,435,686,132,89,970,250,869,13,85,283,910,63,440,33,790,23,625,847,343,635,726,249,90,644,945,364,263,86,966,179,591,281,814,493,653,649,360,220,707,842,860,249,541,342,755,517,190,482,536,76,766,664,851,935,925,856,872,628,477,368,242,488,332,447,706,454,525,452,295,659,116,34,54,117,836,285,486,719,569,203,686,705,878,818,696,86,673,302,826,772,681,991,477,729,982,777,818,903,712,485,804,21,679,955,454,676,654,926,158,10,474,15,834,791,329,251,705,682,128,661,353,444,770,192,860,243,179,855,72,860,665,207,653,843,173,882,531,112,453,81,599,882,669,689,898,8,122,154,618,552,823,533,206,849,981,690,616,407,654,362,907,150,279,102,183,940,218,969,388,708,541,744,174,800,748,799,390,910,199,105,614,768,338,459,640,160,186,892,30,548,519,107,52,773,963,443,689,510,437,928,996,290,69,119,592,199,760,516,622,156,35,746,618,95,82,856,482,292,230,679,442,94,243,532,595,803,872,920,844,677,711,29,431,34,146,988,113,378,51,467,813,529,331,8,148,619,373,0,875,697,996,730,257,549,609,814,636,821,722,293,469,139,281,21,117,312,286,708,321,163,517,736,824,208,18,324,299,202,12,749,272,32,615,928,12,781,573,995,12,890,751,978,834,457,716,468,444,851,882,400,260,929,992,766,565,858,967,965,592,614,410,857,551,72,199,351,814,414,418,476,820,468,456,116,679,192,617,817,461,36,681,258,828,661,115,472,505,152,777,516,288,968,526,396,942,221,714,991,691,293,430,888,589,876,245,568,417,44,326,581,825,596,785,290,600,61,777,450,424,678,11,835,888,730,493,457,428,659,750,62,802,858,649,157,561,319,444,254,96,362,864,553,797,906,757,365,789,854,400,946,630,228,847,582,753,438,987,717,932,422,227,633,659,188,338,587,810,626,469,147,825,579,122,584,563,175,611,394,424,146,728,956,407,207,946,905,499,958,482,125,690,276,648,408,823,217,94,76,268,893,214,938,29,208,739,778,829,121,692,813,138,720,919,707,766,892,957,657,542,384,284,356,663,249,556,318,99,269,695,962,618,677,437,190,479,900,468,974,579,873,565,212,747,952,448,563,22,62,870,265,788,572,184,801,201,12,611,737,359,283,858,656,445,519,498,147,345,399,356,811,930,207,796,635,945,69,419,623,523,946,623,10,672,918,867,104,496,228,658", + "495,833,576,807,485,801,942,932,575,81,91,395,338,671,632,20,785,647,37,459,155,533,710,464,900,998,886,531,563,286,623,353,747,543,596,935,624,991,252,306,322,619,622,449,187,861,292,746,618,254,110,185,186,391,845,477,647,432,814,67,484,594,884,669,66,620,650,36,790,780,153,150,384,483,247,39,602,706,613,466,320,119,532,956,743,341,587,476,495,317,383,945,178,528,326,780,102,25,630,58,673,530,990,224,413,991,670,718,246,628,647,716,731,501,184,253,224,901,819,455,991,843,951,533,155,32,790,509,495,175,104,624,565,141,193,684,476,447,623,334,797,523,887,191,641,314,410,941,160,809,762,351,100,352,213,844,833,643,343,346,895,722,791,788,63,881,758,144,458,124,942,746,913,445,315,817,130,421,60,878,92,747,74,147,276,393,672,695,763,890,681,568,851,925,979,981,280,940,144,545,967,929,946,733,342,130,577,848,890,316,303,769,647,857,968,947,248,695,14,505,799,420,937,847,734,947,17,132,711,184,545,558,93,639,489,647,810,293,194,389,826,43,104,3,909,698,706,130,53,535,939,388,436,595,598,424,421,438,202,186,597,966,165,932,345,587,665,180,438,440,166,173,2,786,102,857,484,162,247,534,966,19,247,203,635,841,894,57,866,470,580,150,455,861,5,965,852,10,829,662,406,603,301,88,505,335,918,469,51,625,323,282,823,858,834,621,321,939,752,978,576,33,501,306,594,191,1000,754,727,511,989,323,460,30,716,423,327,903,710,744,570,507,19,125,536,893,962,781,378,447,27,604,924,948,10,703,540,508,658,575,961,203,467,598,284,166,955,891,229,369,681,123,49,447,768,128,646,888,896,635,409,660,459,412,714,358,492,889,46,617,60,401,415,401,158,268,502,196,782,338,338,411,815,955,819,736,407,570,162,613,513,383,695,48,524,447,50,521,114,637,208,384,268,883,679,472,538,411,481,213,260,45,726,771,152,688,182,521,290,561,247,582,667,739,931,551,437,638,787,494,441,171,793,154,173,613,975,143,912,230,345,597,473,389,417,357,941,173,701,647,387,518,527,92,457,653,450,628,662,494,48,150,152,652,798,726,994,671,374,757,548,562,873,39,143,439,727,611,34,831,569,979,539,814,615,108,478,691,991,844,795,524,802,319,410,389,678,77,747,978,801,444,404,640,474,338,182,891,50,435,691,939,170,940,246,684,982,580,414,889,307,960,678,379,820,36,954,109,881,180,906,540,45,127,313,708,888,637,434,80,852,794,372,638,126,593,936,257,617,382,428,753,618,846,568,116,333,16,417,20,671,663,378,563,867,737,451,777,121,164,12,381,199,344,394,936,160,367,820,330,850,845,90,64,512,470,804,960,935,707,388,670,165,504,60,874,820,732,793,457,744,185,217,111,82,427,119,179,167,146,175,928,809,187,737,917,833,785,292,640,307,520,229,791,914,761,252,920,269,188,606,286,17,592,602,897,709,714,705,816,473,427,585,449,687,365,41,174,302,174,160,401,323,714,9,120,910,949,853,406,914,791,96,512,478,808,517,808,22,401,682,94,454,946,49,902,849,295,441,847,142,410,730,204,602,156,847,430,875,0,29,304,907,968,714,895,504,642,320,163,522,283,767,728,783,34,966,437,398,760,774,26,474,257,832,536,845,277,293,71,210,333,898,968,681,982,237,613,37,728,17,49,305,924,705,986,132,458,116,456,348,491,127,610,76,867,182,321,292,664,27,490,868,191,640,915,879,503,796,150,449,54,976,774,287,345,347,427,968,252,132,682,464,66,740,34,880,672,555,506,520,21,217,733,670,441,180,643,300,990,91,893,635,248,892,999,548,221,162,381,776,527,913,478,81,514,190,102,556,353,264,797,496,121,173,92,615,462,436,432,985,686,150,627,717,88,889,361,968,991,976,604,560,581,104,552,37,455,193,931,63,739,371,940,273,438,537,985,992,435,942,771,250,126,598,812,857,400,978,12,345,330,183,500,589,481,902,303,784,523,651,443,955,66,303,167,808,980,391,763,670,26,79,665,451,809,448,490,711,63,886,949,804,356,109,302,386,655,653,954,704,426,179,401,508,860,203,840,27,806,425,234,631,348,18,497,414,831,423,741,772,987,49,433,572,207,336,12,832,450,10,295,620,85,366,575,115,37,838,751,879,824,328,978,412,108,45,669,720,437,308,766,21,950,310,362,261,280,418,161,421,110,662,747,440,343,697,157,553,25,27,345,9,342,287,687,328,180,766,984", + "961,642,398,906,967,12,891,299,547,927,113,927,419,196,901,687,768,114,839,186,562,285,888,97,479,623,500,163,76,600,844,746,932,594,643,540,626,164,706,806,359,396,649,508,311,398,442,584,237,473,309,721,160,529,730,700,684,581,202,157,208,276,464,853,597,441,678,186,336,426,734,132,405,811,521,473,420,712,697,688,591,98,956,348,327,822,741,863,195,96,252,598,579,573,310,1,193,912,754,676,53,478,821,912,457,840,404,671,835,26,922,135,753,382,733,474,577,60,503,120,680,529,78,240,710,685,432,898,584,500,59,690,246,579,627,482,185,443,595,503,929,25,731,49,211,9,209,368,272,2,455,862,520,122,128,360,687,739,755,859,159,173,510,505,519,218,481,656,175,678,55,57,458,590,546,807,310,956,960,933,529,546,258,967,947,286,130,84,19,201,28,340,300,353,423,309,31,176,432,854,554,967,465,559,38,170,383,82,800,935,18,293,165,774,118,457,972,1000,443,515,470,273,823,968,884,191,893,57,497,742,684,961,209,833,946,613,836,565,997,656,959,907,449,950,420,593,109,267,143,149,471,277,949,35,286,247,214,134,417,336,988,889,272,12,28,117,879,723,968,793,730,470,868,510,567,515,206,837,24,468,710,635,387,464,114,576,285,457,860,838,128,902,686,947,657,963,500,997,695,696,651,896,666,158,918,938,551,775,177,163,869,878,776,115,482,506,477,492,64,162,354,968,623,321,845,774,889,312,703,473,478,415,381,838,417,945,188,684,885,599,753,808,767,212,945,513,265,735,386,656,689,773,838,104,111,631,861,188,406,264,3,555,664,475,86,742,18,129,576,883,8,559,959,318,792,873,57,707,90,322,24,768,380,173,14,739,787,325,273,48,454,513,333,698,36,371,249,200,556,263,799,763,71,994,925,57,318,532,551,6,878,912,478,967,502,895,590,515,417,642,329,792,103,639,100,559,441,861,951,929,761,648,97,180,33,434,55,346,435,824,772,249,770,848,781,750,599,945,357,759,936,838,88,896,826,715,872,366,531,629,588,531,51,747,264,355,307,194,466,910,665,262,800,431,50,262,835,606,461,185,261,403,870,684,791,164,302,396,568,171,589,251,138,316,393,489,255,474,387,443,643,506,862,703,112,78,161,375,300,941,939,625,172,648,895,157,267,563,287,344,155,171,14,354,743,702,551,292,581,973,65,778,561,284,104,702,350,395,489,622,649,440,976,423,81,889,747,940,296,895,143,618,955,713,959,215,576,606,477,61,117,302,887,41,890,208,285,775,257,291,554,253,567,286,189,522,508,618,194,236,306,233,456,797,35,236,709,943,980,598,920,316,630,780,556,987,356,574,121,669,317,567,225,113,608,500,743,826,551,656,970,507,859,658,94,671,657,74,939,180,828,294,199,729,122,21,117,408,782,819,644,524,227,682,211,936,949,976,277,998,619,862,122,877,377,263,710,987,525,61,58,959,996,47,953,794,296,721,787,519,648,183,725,888,582,772,860,538,190,130,631,378,424,419,926,927,731,276,221,438,341,211,683,128,438,202,251,590,757,724,41,111,900,106,173,327,908,137,410,44,467,527,420,980,118,429,889,665,697,29,0,401,315,879,334,84,368,310,1000,391,458,472,276,295,807,465,923,814,344,818,337,796,298,803,156,896,245,769,739,769,586,589,40,48,746,705,215,46,912,698,499,329,599,587,957,388,730,387,532,354,614,536,407,585,329,789,920,323,523,959,201,660,396,417,374,965,424,133,939,811,198,53,408,452,88,143,696,421,856,290,921,165,629,698,447,959,216,7,873,450,130,528,876,666,943,732,164,592,397,349,338,151,462,437,270,978,620,469,755,724,725,824,499,765,884,321,385,399,520,831,774,917,674,422,202,157,852,231,369,220,231,182,887,837,598,429,337,345,565,787,341,650,395,212,918,679,574,495,927,405,765,865,517,28,8,509,900,613,902,935,142,993,497,332,24,40,68,309,813,424,757,713,817,124,240,535,699,34,228,582,127,708,451,911,792,312,2,478,943,93,262,176,545,677,757,366,315,503,50,490,2,713,993,418,745,639,161,923,132,957,235,174,696,281,553,81,475,23,657,219,270,56,166,627,180,417,282,152,775,620,300,604,860,833,804,760,78,955,972,599,138,161,713,812,405,608,196,31,781,435,951,667,757,798,93,239,259,863,242,739,850,22,116,424,928,771,674,837,977,488,536,488,749,14,999,454,30,172,365,560,279,781,427,112,156,170,592,664,350,539", + "770,437,723,592,608,28,411,864,772,817,812,41,732,794,548,867,533,986,482,408,814,947,763,982,592,187,63,985,854,458,471,70,156,779,789,219,621,649,129,638,331,737,863,859,984,548,852,443,796,927,186,630,646,918,834,727,296,549,499,964,91,421,687,382,300,29,694,922,653,123,704,503,318,592,557,981,859,823,817,889,181,358,250,780,150,57,770,574,483,828,431,8,739,226,786,84,43,133,764,375,891,980,465,120,408,326,855,761,230,52,405,431,370,183,995,910,525,874,70,344,700,986,746,939,69,515,889,70,258,93,924,547,447,778,971,472,283,826,314,906,932,299,875,227,705,994,80,896,364,723,857,628,405,600,526,899,331,185,147,419,557,292,382,732,471,459,368,593,281,712,905,199,735,951,408,850,32,857,55,2,89,553,870,171,447,694,529,354,933,703,660,728,97,552,249,659,206,897,896,394,601,685,287,937,996,516,227,192,815,403,433,515,186,840,88,380,699,656,316,650,420,22,128,160,186,789,118,351,550,413,14,765,627,231,192,119,657,644,128,769,137,147,738,827,192,254,831,579,570,399,797,13,923,320,841,937,633,229,345,519,194,825,210,219,83,585,635,104,349,219,4,931,636,304,105,918,562,405,668,261,358,584,751,40,414,172,537,38,178,251,399,294,191,75,676,305,138,856,824,132,581,925,309,912,712,413,42,584,731,81,35,266,980,719,218,582,394,575,973,938,581,94,213,366,306,866,297,66,350,639,867,641,375,979,132,528,211,486,716,220,435,164,689,196,840,992,609,894,26,861,725,65,83,642,454,382,998,601,102,628,922,440,327,219,801,227,749,968,761,634,35,569,585,13,880,928,371,366,128,70,9,266,317,791,428,367,266,615,673,822,353,543,586,231,666,552,60,254,469,862,112,613,465,112,207,474,336,137,489,463,809,446,746,474,582,107,567,516,845,577,11,465,955,74,481,467,306,206,748,323,976,39,242,765,104,801,527,105,457,687,599,851,175,268,342,270,43,570,962,884,389,983,6,580,453,346,842,568,14,913,99,553,635,201,659,885,156,921,473,997,338,295,894,418,765,79,987,260,121,782,274,544,635,804,725,288,16,547,946,197,71,202,855,655,503,300,513,509,280,475,401,616,943,987,592,821,401,552,359,630,411,571,149,933,133,136,106,831,529,300,366,152,309,246,827,150,50,612,483,862,400,374,36,199,35,455,737,567,670,896,513,89,618,376,804,167,157,76,625,261,975,843,917,417,300,826,398,499,7,59,993,489,855,586,885,399,444,49,642,334,457,128,132,230,416,264,433,946,385,704,362,788,155,128,558,256,872,112,394,49,976,846,121,675,656,227,1000,191,815,896,666,775,622,359,300,122,198,849,290,859,981,328,678,663,265,140,323,412,730,962,484,664,641,987,952,39,72,239,168,82,434,20,997,191,92,920,597,584,751,419,136,12,613,696,778,633,989,231,51,850,548,39,64,947,616,836,834,152,600,470,716,103,279,262,861,427,284,203,16,98,393,743,93,612,329,744,490,724,744,826,440,484,618,863,412,546,884,61,180,983,572,415,885,288,820,719,154,211,212,587,495,848,124,737,305,965,425,277,996,304,401,0,411,604,907,951,888,558,283,686,18,164,108,107,433,82,896,332,585,40,586,342,953,236,162,199,876,690,327,737,270,874,429,93,778,325,523,199,868,91,496,729,513,678,558,175,406,808,576,931,240,817,899,658,587,750,941,978,321,312,748,20,804,529,96,653,951,726,90,832,895,499,742,922,24,63,681,172,91,550,528,161,680,497,345,581,557,500,117,492,595,535,379,591,201,861,819,841,986,439,819,484,677,302,981,128,174,319,219,986,921,954,74,891,177,490,714,3,235,180,341,419,656,551,211,629,857,270,231,942,748,375,312,934,160,102,715,65,659,212,437,685,400,291,180,34,145,676,365,240,149,252,540,650,110,991,185,499,218,356,897,743,614,828,291,277,203,693,769,545,287,154,519,777,506,160,721,244,9,906,783,685,666,655,951,338,560,120,158,783,10,123,952,397,942,326,246,45,418,575,774,266,264,338,988,33,30,427,190,417,304,23,869,636,708,320,434,380,764,566,81,657,679,542,28,392,269,590,447,404,385,842,754,573,254,832,217,122,582,372,776,826,441,684,882,305,152,461,567,41,763,259,798,379,687,71,692,680,793,640,914,220,586,210,785,424,56,376,284,531,384,441,572,520,953,64,425,798,211,22,470,998,171,264,848,119,149,105,613,111", + "736,746,266,985,24,206,202,24,980,162,506,683,897,297,874,920,954,774,353,342,736,521,527,665,690,487,224,197,554,491,271,485,728,369,82,956,517,354,753,950,544,585,789,255,778,157,85,120,521,853,45,438,159,807,224,9,913,848,299,822,552,908,505,962,82,778,151,48,46,623,319,81,306,466,941,625,435,154,324,6,812,2,278,229,746,217,568,829,496,258,37,477,972,195,82,300,222,690,58,798,14,970,595,984,43,655,444,501,839,494,159,658,849,26,706,119,148,153,973,907,418,13,501,753,956,727,51,284,664,67,823,455,844,860,2,120,345,488,944,129,402,621,435,518,48,616,252,633,813,322,203,133,719,602,650,100,237,465,588,818,29,797,828,531,701,615,597,474,187,380,920,831,942,514,104,866,356,460,124,585,541,593,2,898,726,705,507,751,177,941,873,753,497,880,662,20,462,727,377,236,794,369,375,380,684,793,723,559,202,292,818,919,727,882,26,405,994,819,539,794,403,31,474,414,306,57,280,829,265,579,779,760,329,734,30,752,640,593,622,548,405,319,283,355,538,471,979,181,855,226,346,716,520,791,545,123,121,740,678,837,140,783,404,284,194,719,893,41,423,720,75,136,654,976,221,111,746,865,542,991,12,915,936,330,780,671,167,239,412,150,379,257,296,488,850,941,163,389,62,182,393,585,908,592,572,819,235,851,466,637,876,82,445,242,517,202,787,982,513,417,269,81,112,221,288,128,381,48,964,416,446,433,68,651,871,386,246,58,725,386,812,429,282,627,375,937,634,531,655,266,531,932,276,433,717,297,714,975,134,539,368,375,712,299,721,633,540,368,419,380,895,819,946,302,522,74,501,321,433,492,223,531,774,189,391,673,557,37,551,18,589,418,169,147,519,803,69,411,6,54,183,716,547,940,468,286,988,523,818,56,692,725,206,579,806,350,876,92,513,618,661,711,658,97,207,200,879,960,363,519,617,367,639,654,853,235,229,710,304,49,816,178,595,585,96,10,271,256,911,200,510,534,189,769,72,13,513,660,635,105,838,44,779,566,11,632,963,704,839,927,145,514,873,753,65,137,67,44,166,148,204,518,551,571,244,109,567,359,869,371,921,659,573,810,275,674,759,792,769,322,587,958,289,465,843,48,384,498,142,906,291,474,731,714,899,962,584,980,980,778,385,250,37,317,617,537,665,278,282,729,686,20,130,449,535,948,727,833,112,844,649,410,65,258,71,318,751,770,335,29,823,504,685,198,159,67,544,588,373,415,86,303,512,966,301,239,610,246,323,630,32,524,112,806,274,405,237,355,938,962,116,16,257,489,482,996,220,4,714,349,838,844,316,583,133,246,746,970,553,109,899,375,433,511,783,505,420,999,242,150,688,66,718,349,279,920,544,448,92,460,757,419,414,734,858,142,513,826,464,73,490,71,936,842,600,54,470,984,452,407,464,723,276,253,577,440,323,916,297,334,776,611,466,510,166,610,63,792,584,220,87,20,857,862,554,626,37,406,435,915,956,434,517,398,150,806,955,739,80,327,161,740,470,611,667,702,78,871,501,582,918,257,385,495,357,40,735,653,328,799,734,498,269,179,63,156,734,591,730,907,315,411,0,645,753,85,219,51,151,932,785,82,534,402,415,532,687,597,662,82,448,302,122,408,921,556,96,644,339,84,611,807,906,806,757,591,271,140,216,527,406,732,441,84,265,571,36,497,39,67,611,261,393,883,982,308,576,354,220,509,255,431,602,179,842,360,898,226,9,966,237,276,676,594,665,533,169,933,192,425,126,367,653,366,945,33,655,632,425,119,869,853,169,620,865,590,765,550,825,293,173,359,918,94,350,227,497,99,699,378,661,3,192,347,510,339,238,612,291,552,468,488,146,937,238,118,167,10,32,529,983,215,500,326,236,757,841,501,882,391,927,605,661,598,511,450,891,755,371,679,292,561,366,525,142,640,701,790,534,456,354,659,764,106,463,352,984,46,337,525,893,503,346,528,392,938,641,174,282,280,815,705,321,364,48,376,942,301,79,29,893,352,811,654,950,899,112,913,916,281,99,292,272,701,510,828,184,626,854,421,804,968,378,889,905,964,113,613,47,840,284,977,321,183,993,546,747,700,245,323,794,610,371,158,430,246,763,175,661,307,22,877,760,152,980,181,408,437,901,461,619,310,675,285,858,2,504,837,159,597,600,52,406,392,120,194,492,637,146,86,237,893,811,329,427,380,496,666,987,943,781,313,161,803,187,269,499,854,639,521", + "207,565,895,349,647,396,954,646,640,598,526,528,416,911,784,155,551,826,830,254,18,400,978,655,240,296,736,414,976,904,482,625,289,671,196,610,63,869,633,826,95,304,131,803,627,35,329,254,494,967,536,251,137,224,738,239,452,814,393,184,144,819,442,255,809,246,388,232,970,959,365,934,134,940,672,733,70,765,155,247,104,486,60,87,114,547,442,740,475,47,311,840,540,378,206,409,477,755,421,370,245,871,907,341,57,259,49,748,822,606,528,812,810,725,291,212,532,668,950,299,844,278,300,766,972,656,281,345,292,405,601,284,306,716,903,573,941,16,155,682,545,674,846,856,982,54,718,115,302,968,496,95,384,190,84,583,800,14,308,811,834,999,593,81,367,166,990,722,855,145,117,44,151,786,153,288,862,410,231,766,48,571,719,566,818,56,290,192,10,604,760,807,767,624,885,231,232,944,299,544,815,808,344,455,529,946,901,942,317,785,244,717,264,280,644,181,82,418,488,388,716,960,881,80,204,802,206,118,782,119,223,605,314,935,221,736,2,803,652,734,641,252,91,356,890,383,288,591,150,752,34,223,845,162,110,630,543,486,260,794,253,638,532,337,541,796,306,729,391,231,962,324,393,526,882,725,948,467,227,795,690,717,12,697,301,810,521,411,685,66,81,594,212,181,645,369,652,795,130,781,55,520,443,355,856,359,337,164,330,918,588,522,834,530,266,285,400,625,580,852,672,403,327,464,722,600,819,632,164,273,161,397,277,661,662,643,147,460,547,400,550,876,297,821,278,67,620,879,530,832,679,682,709,15,710,146,15,943,430,464,496,569,806,41,474,627,937,894,221,124,168,847,308,724,988,639,213,199,174,555,935,370,12,842,26,823,11,937,200,47,59,10,455,732,51,11,346,10,358,833,544,273,679,17,184,871,22,179,321,293,287,131,784,737,948,729,974,91,652,737,901,960,241,228,565,495,146,794,982,318,324,354,437,747,996,434,788,659,129,818,801,905,254,506,351,269,989,334,60,69,641,999,952,498,970,545,913,470,687,83,445,512,92,958,935,933,827,763,896,907,342,999,545,327,973,869,261,115,646,140,336,945,111,725,15,145,385,240,916,254,919,401,138,158,910,214,741,413,3,558,479,812,884,498,451,113,712,829,992,460,586,892,448,434,328,394,323,629,632,348,731,413,704,583,962,271,299,556,288,827,451,841,459,627,953,347,295,367,190,255,197,15,619,224,776,113,932,603,770,250,860,785,550,478,775,327,205,992,441,796,26,131,236,914,430,355,387,671,458,344,325,760,709,432,450,792,264,489,136,559,793,996,756,38,572,976,82,853,37,686,190,709,993,603,653,854,598,308,50,261,693,128,849,661,128,191,348,851,779,653,761,539,353,305,209,780,528,459,274,15,562,30,129,482,504,49,197,743,546,770,459,280,46,487,793,120,916,484,809,453,708,599,803,109,842,414,19,489,703,228,483,223,410,641,585,597,408,335,770,152,995,444,566,372,77,53,226,565,507,478,976,833,930,841,616,482,426,656,908,206,244,668,264,417,881,99,112,81,789,849,904,570,153,956,592,56,181,724,242,548,159,423,23,758,307,404,677,470,257,968,879,604,645,0,870,672,625,433,120,934,383,686,240,100,766,178,966,102,720,750,755,79,912,717,684,665,743,659,853,126,613,255,562,551,638,130,127,572,365,154,329,236,734,942,338,882,373,671,81,660,658,995,740,246,384,837,460,882,872,910,90,855,157,651,308,837,229,989,356,88,191,658,306,893,950,360,203,500,436,585,527,223,96,467,61,383,537,418,698,3,248,575,93,829,2,662,301,19,288,418,561,554,636,770,464,858,294,115,436,152,233,764,310,55,206,14,962,464,730,791,434,734,181,16,111,230,203,608,655,118,172,945,961,146,48,53,270,399,915,178,728,593,909,277,410,677,244,162,249,229,193,341,637,587,757,853,398,351,653,992,443,117,862,368,650,519,907,837,934,304,111,643,332,789,237,395,689,639,801,789,951,539,980,337,53,183,887,700,870,55,90,488,916,456,685,960,577,649,655,478,322,291,549,44,892,761,156,240,743,643,765,57,82,446,188,19,327,548,668,165,332,292,425,787,249,780,53,697,551,698,239,601,710,742,742,538,917,965,112,947,474,409,943,865,377,860,696,121,623,493,256,710,37,124,277,423,275,935,425,135,636,9,586,191,107,549,28,73,239,42,1000,653,296,163,52,573,805,836,634,437,264,632,447,938,102,638,16,462,966,488", + "903,23,899,872,760,835,444,476,105,792,282,505,890,208,298,763,11,42,722,405,597,913,126,237,512,26,940,58,863,843,749,825,743,446,167,264,547,309,510,690,847,446,756,813,245,332,875,780,23,976,913,31,62,181,860,734,365,272,590,879,528,607,562,348,322,94,431,704,744,450,380,950,605,712,824,381,115,546,743,582,401,854,377,6,392,726,636,135,99,227,628,489,934,86,329,641,30,358,395,768,814,747,955,258,718,282,779,698,128,841,214,76,129,416,487,79,534,909,363,225,737,384,168,979,840,21,743,395,389,603,491,494,417,787,673,319,152,556,413,199,284,955,846,789,830,662,519,863,68,312,359,877,9,855,352,820,751,916,755,824,756,867,536,827,763,586,95,442,126,179,44,711,303,688,788,520,595,646,87,200,160,531,306,537,922,101,715,309,97,777,195,739,926,540,513,624,368,570,197,447,864,14,61,350,453,685,710,979,244,259,439,467,26,862,905,451,304,202,590,53,26,685,43,202,829,220,726,837,992,518,851,91,443,698,153,225,299,427,561,497,427,48,333,414,153,927,27,136,448,202,447,132,331,913,228,944,45,80,513,208,498,439,56,317,21,796,152,550,441,437,163,209,467,2,781,795,147,591,510,972,877,638,826,733,153,739,90,195,13,55,509,891,41,685,982,415,962,377,557,195,481,56,904,486,603,752,192,92,744,587,957,148,182,280,983,450,921,835,167,450,587,457,943,629,259,87,642,415,679,965,326,397,401,636,682,503,172,427,259,559,173,986,776,550,966,954,867,496,727,292,877,670,413,972,381,261,463,555,226,168,201,454,275,323,14,267,612,253,974,130,359,157,152,102,877,325,532,287,579,976,252,268,995,657,354,301,978,711,307,34,208,115,30,682,267,284,500,983,266,959,178,751,660,60,459,939,872,369,526,332,991,438,920,601,647,222,457,539,575,521,281,309,490,851,174,93,922,364,224,945,464,380,989,384,216,151,578,284,389,1,82,312,654,618,351,580,358,708,354,23,740,305,519,539,280,777,847,56,64,714,1,170,582,906,750,228,781,501,736,5,392,878,78,580,2,593,636,833,978,210,701,493,921,525,790,127,288,454,447,593,986,456,720,342,206,770,653,568,91,60,836,458,814,135,525,163,368,186,20,580,160,405,375,472,286,72,618,65,299,583,967,822,643,714,470,478,934,675,468,19,150,439,456,714,585,26,181,402,629,344,226,576,694,30,589,824,901,742,917,606,101,404,599,879,248,516,123,896,439,960,568,392,520,887,41,96,830,489,196,504,294,290,114,349,532,846,101,764,885,789,177,36,827,425,624,154,654,812,597,337,737,46,426,695,715,557,902,94,698,409,205,340,927,370,605,7,159,136,466,352,500,727,82,465,392,627,711,690,564,615,407,30,409,53,706,421,382,272,120,658,658,241,612,157,780,343,691,523,280,406,752,620,256,541,201,178,626,349,490,491,165,141,801,432,324,318,979,833,262,987,750,914,108,605,871,303,554,172,656,1000,457,894,946,720,336,784,67,260,855,147,800,133,612,163,931,157,627,441,681,857,704,374,756,932,423,426,841,750,845,518,304,47,896,550,794,581,892,740,549,714,334,907,753,870,0,442,857,211,221,871,734,932,488,687,176,997,662,168,557,575,190,477,680,914,934,472,784,201,100,350,89,582,551,508,41,888,788,108,157,682,322,52,226,219,767,216,273,372,355,316,292,128,344,796,156,253,976,760,236,988,712,669,86,847,814,301,774,964,635,760,97,215,895,149,697,971,498,2,631,607,384,551,832,621,564,206,681,102,271,220,387,289,949,851,296,424,96,476,528,670,816,626,979,548,156,689,271,878,723,825,90,247,581,707,324,733,730,255,762,798,911,487,778,87,596,95,799,331,52,698,432,187,564,107,618,297,999,851,265,96,878,81,313,547,499,531,471,714,282,354,308,669,789,313,27,528,831,256,384,110,247,86,400,180,79,638,885,472,845,786,679,769,800,731,454,391,976,732,511,719,306,250,614,583,594,506,256,504,724,454,300,994,260,508,329,803,490,299,544,733,775,800,182,674,9,549,732,44,557,431,633,231,133,852,970,141,37,586,123,224,749,166,981,267,52,779,520,776,736,643,12,223,903,787,496,146,422,768,244,50,824,167,656,523,316,770,748,667,216,449,145,706,117,685,516,666,443,217,713,181,293,271,872,516,252,26,901,92,336,806,773,444,723,889,265,304,201,939,686,768,424,653,150,938,571,388,500,407,78,367", + "664,956,439,383,861,161,548,717,778,79,817,867,754,496,874,843,660,856,891,72,210,816,548,656,335,683,197,850,769,480,701,241,838,254,882,410,424,461,257,489,274,45,500,94,309,27,435,726,618,665,200,138,787,977,17,663,805,512,961,513,272,431,776,351,662,894,286,206,509,301,490,858,724,285,292,410,970,394,357,371,884,80,33,69,937,704,103,510,151,386,433,573,51,746,62,458,311,103,519,654,839,522,131,190,668,17,400,516,668,900,726,912,685,64,108,338,648,865,593,326,676,171,358,329,962,398,272,280,358,417,405,71,764,770,534,70,778,614,559,574,768,849,413,201,270,902,59,787,758,437,172,822,208,417,874,586,520,32,676,708,217,587,364,609,322,851,584,680,614,966,487,35,856,8,579,943,643,324,546,358,997,949,463,259,27,834,5,603,733,452,640,97,706,371,5,112,868,499,98,270,84,362,377,792,820,830,150,513,44,204,796,795,557,262,11,867,461,430,916,77,849,13,55,719,643,245,470,307,725,275,50,655,515,266,383,205,376,433,955,95,320,119,226,584,714,939,513,606,900,554,436,635,177,11,218,614,236,137,14,345,631,600,953,265,684,188,719,509,925,62,23,466,471,621,327,265,244,965,298,240,943,148,37,530,690,273,844,955,142,525,40,253,183,888,769,27,336,95,395,586,295,959,576,715,783,440,858,269,282,819,490,236,392,97,917,678,68,415,915,642,614,723,402,452,152,509,412,274,337,667,589,449,24,670,218,415,652,678,352,112,236,117,213,920,330,854,318,653,864,501,311,265,621,62,402,662,552,599,918,654,646,124,89,74,288,509,460,727,483,234,169,576,608,266,614,644,399,139,232,481,634,75,694,17,367,759,221,850,57,713,600,369,973,682,911,366,188,150,633,360,381,438,770,960,143,609,507,46,294,493,36,222,955,112,441,366,57,747,305,972,27,493,209,58,643,89,835,817,863,800,995,905,162,915,334,275,646,983,242,940,502,624,166,419,348,668,613,751,916,172,821,585,332,869,999,640,36,593,117,254,319,321,1,450,314,568,243,163,532,9,465,282,266,380,800,818,614,440,310,702,690,433,549,7,152,283,966,759,754,690,406,426,423,712,842,461,226,38,178,815,830,560,705,727,583,286,487,206,717,914,98,267,466,831,780,26,244,884,236,642,386,522,132,28,42,876,41,90,805,456,992,953,853,445,208,747,265,13,924,422,376,389,523,370,475,676,444,776,596,499,560,415,874,973,166,2,216,732,632,311,802,766,749,188,614,677,930,543,27,820,301,309,997,156,553,741,852,821,103,533,170,740,884,264,823,252,522,809,303,551,113,242,350,293,929,756,430,36,492,883,450,54,263,695,797,863,513,847,944,55,195,961,900,123,157,367,893,36,622,576,675,307,968,171,264,782,666,318,274,43,9,937,917,662,254,744,586,7,265,295,646,589,356,890,625,848,680,211,691,64,448,980,878,387,842,688,869,617,742,250,206,763,875,96,872,386,318,435,822,17,886,948,851,853,65,618,620,494,921,619,859,399,649,237,577,735,709,74,925,220,975,159,939,108,117,162,111,678,82,75,775,915,805,68,712,43,188,530,609,895,84,951,85,672,442,0,65,154,58,794,504,165,146,781,437,233,666,959,771,209,106,13,694,278,400,622,808,366,232,976,176,292,148,257,491,82,106,969,564,834,323,684,104,450,11,705,56,351,461,69,522,925,52,939,439,542,888,745,732,567,965,784,368,155,422,66,895,149,658,522,560,238,462,144,607,257,416,721,283,710,207,930,825,780,968,511,563,677,727,557,86,197,63,368,376,318,58,298,220,431,444,402,471,12,465,831,899,183,628,819,633,272,657,510,46,508,488,781,14,933,484,917,311,698,231,634,626,214,184,939,405,254,336,860,119,285,586,826,779,289,918,82,322,396,591,847,335,718,557,10,780,965,948,41,558,833,529,860,334,203,918,558,303,347,771,211,194,705,656,908,419,434,699,691,459,263,17,769,842,191,384,286,435,802,917,857,465,473,702,855,898,524,965,718,412,568,227,503,622,184,935,492,4,251,481,743,254,648,444,369,967,141,979,889,661,165,873,628,952,188,906,942,410,365,36,997,341,154,156,914,37,290,734,784,73,265,422,189,565,21,527,405,527,10,268,424,574,739,213,727,13,116,387,102,805,975,99,261,525,819,225,278,718,901,658,432,336,150,76,532,741,561,625,209,350,537,979,53,662,943,376,856,481,200,9,283,913,561,325,682", + "21,830,509,83,226,359,581,856,623,736,237,235,151,483,39,472,257,505,847,423,443,502,252,53,84,280,650,897,157,893,464,968,193,222,900,607,523,629,742,283,369,489,988,815,346,896,893,684,479,306,427,165,545,802,183,198,467,202,773,596,364,300,634,890,233,41,880,744,602,436,229,2,116,152,183,486,67,565,846,943,289,672,756,819,309,988,440,599,615,257,28,769,117,565,53,517,707,374,431,562,63,494,984,94,906,754,257,488,29,491,188,217,965,438,576,50,989,574,170,299,981,177,345,125,325,613,592,923,766,49,246,833,773,747,805,42,295,639,690,583,979,587,307,689,933,260,933,309,168,657,636,252,360,19,825,568,66,518,270,887,48,343,208,842,273,551,632,970,645,928,99,587,191,415,117,498,326,857,33,715,410,788,41,981,42,436,132,316,139,775,302,72,488,289,758,323,844,686,804,805,203,894,234,962,99,481,332,478,638,85,674,906,310,342,834,157,964,135,810,603,518,363,551,577,228,693,96,998,623,273,172,234,414,851,799,326,403,150,169,492,634,170,809,5,864,409,797,397,473,131,95,398,741,778,222,553,197,27,342,258,654,509,77,883,693,165,787,65,822,49,371,284,971,847,150,40,471,899,291,184,889,266,367,701,249,473,656,599,827,672,755,500,656,688,154,763,237,721,592,650,679,212,853,569,724,710,262,344,586,377,146,564,395,495,37,562,707,103,317,795,727,730,397,914,549,327,199,59,23,997,684,189,585,644,273,74,74,307,405,945,703,647,255,672,111,782,951,448,349,982,893,966,925,729,669,629,212,447,948,352,164,340,167,577,761,443,525,861,604,362,569,276,324,349,590,978,301,63,714,490,653,440,169,844,267,553,551,323,401,279,967,281,110,954,451,125,967,606,567,890,369,249,919,467,85,475,506,756,200,648,456,251,337,346,479,738,55,327,687,266,416,436,35,985,294,850,554,796,82,336,929,914,733,660,853,258,527,34,78,189,24,503,116,377,779,393,744,957,932,175,82,999,306,599,135,30,479,936,552,696,958,730,340,229,705,352,105,36,589,158,863,663,94,322,21,253,245,671,267,398,898,714,987,352,410,350,473,294,397,428,929,333,121,935,717,451,8,37,207,530,313,722,429,104,365,692,934,419,594,769,82,989,261,570,854,683,161,88,487,970,260,87,575,43,557,80,85,790,829,755,424,702,717,24,535,570,705,471,370,306,569,349,529,826,536,245,835,3,206,8,870,515,933,941,262,915,767,288,821,476,437,270,488,116,961,293,301,361,468,290,954,64,578,855,715,292,774,545,482,758,178,267,47,535,517,426,975,240,269,272,931,751,210,403,388,600,773,8,736,260,488,475,219,888,627,947,449,495,851,70,210,769,852,732,30,804,953,6,451,771,599,608,840,591,671,658,785,953,961,237,848,894,781,549,270,1000,611,490,495,88,233,891,819,384,934,697,331,834,365,401,952,410,987,758,830,719,378,407,675,836,147,851,624,379,645,460,769,567,819,775,171,560,121,255,175,893,187,39,295,783,864,997,244,348,730,597,441,715,661,608,473,376,30,932,582,818,627,412,897,739,429,363,128,3,651,365,230,946,814,504,368,888,219,625,857,65,0,529,507,509,824,243,264,524,662,189,184,475,687,366,474,634,375,401,824,520,185,392,753,308,436,483,921,249,525,570,926,397,205,383,200,53,367,904,201,298,28,494,931,922,299,937,968,662,566,466,904,980,436,169,700,474,799,72,101,505,520,830,988,214,339,29,236,159,402,990,461,26,215,43,157,254,973,903,661,262,822,407,173,401,847,532,194,776,877,377,203,107,971,809,562,343,397,278,967,361,717,782,362,417,887,625,54,536,152,690,812,314,99,265,544,727,198,620,389,695,843,895,754,657,416,506,172,977,853,547,954,33,223,910,228,582,790,18,794,926,796,501,666,324,861,602,108,538,179,880,513,462,357,289,981,243,795,987,329,766,836,917,184,610,90,608,544,513,261,84,460,431,77,671,205,27,267,771,800,784,692,451,74,217,958,215,229,457,649,647,126,378,760,469,774,271,51,103,256,976,825,859,4,471,200,951,447,54,738,301,225,696,820,757,221,151,476,818,374,205,182,126,527,121,295,612,312,122,922,405,682,538,665,66,75,14,27,271,469,713,222,211,73,97,346,501,135,2,139,309,374,619,476,750,952,385,783,788,538,607,28,556,644,968,284,993,67,813,578,783,709,986,904,414,901,509,729,331,459,863,269,86,294,660", + "345,266,1000,351,362,70,988,871,946,77,607,284,616,695,483,498,421,368,961,732,473,176,680,943,222,474,339,837,954,922,225,123,758,665,840,253,493,743,183,569,668,644,26,443,636,514,135,36,343,923,322,850,978,970,863,504,276,36,483,769,328,547,399,310,857,417,264,807,569,952,845,424,901,255,350,431,362,697,692,87,687,326,736,654,626,800,831,650,460,256,624,832,756,83,998,564,141,91,630,633,338,302,26,225,829,971,317,760,476,642,989,668,676,476,542,662,646,248,692,886,771,89,386,618,748,232,532,901,742,692,320,336,971,378,331,918,879,85,119,177,510,449,712,238,827,565,432,916,77,508,425,334,139,371,333,616,38,885,721,457,674,907,273,279,643,47,173,899,394,211,950,853,619,419,71,180,465,650,931,77,400,303,904,610,918,681,344,387,63,894,886,599,928,983,86,467,458,982,891,901,467,836,639,677,39,346,398,423,683,137,424,326,143,124,445,377,827,8,459,208,794,255,380,339,181,615,716,421,594,250,416,438,33,193,992,207,298,389,175,413,898,525,565,370,10,788,38,419,435,678,347,639,882,934,45,414,352,120,256,39,517,279,547,611,667,966,25,548,186,959,380,15,915,635,92,79,426,884,360,678,41,736,548,348,642,758,497,147,597,689,101,799,630,890,43,157,897,427,495,86,692,68,38,550,485,67,749,367,223,221,612,458,318,639,820,251,586,308,304,22,638,769,545,661,842,203,820,730,151,150,571,129,531,660,879,589,947,314,23,241,234,827,509,952,127,700,276,42,851,419,431,926,581,256,597,244,763,347,975,675,561,706,950,691,679,907,196,575,941,785,220,309,709,421,816,648,482,340,522,320,532,335,249,341,639,226,666,233,763,357,41,695,426,664,134,418,30,112,394,399,70,384,666,520,287,680,498,864,105,321,62,547,677,533,167,701,589,418,125,207,924,731,952,953,418,205,114,619,153,459,449,76,278,918,894,340,167,147,955,8,354,289,914,801,177,595,880,474,84,816,286,805,677,274,22,136,126,587,683,625,459,195,800,474,812,377,965,390,211,75,768,532,996,809,75,834,250,709,606,368,789,602,871,297,512,449,325,649,809,276,243,510,200,559,476,763,571,820,413,899,120,918,89,900,811,931,816,275,107,994,227,818,14,121,615,533,362,218,350,640,647,970,63,343,637,577,344,494,768,277,764,684,163,511,254,854,441,852,370,382,219,307,708,905,813,659,724,179,994,332,734,88,303,386,146,260,58,142,280,761,385,248,121,690,735,523,116,4,224,360,282,848,306,506,107,929,122,650,681,294,922,534,407,172,485,900,282,994,269,203,711,693,352,377,883,14,263,393,499,678,463,105,491,25,349,686,680,112,703,332,225,418,808,438,580,268,879,170,870,296,597,938,785,310,952,976,891,131,166,522,831,867,49,585,582,943,766,587,456,1000,507,857,617,224,800,14,421,181,18,507,498,694,986,4,530,316,612,540,251,652,615,433,484,686,708,876,990,441,440,331,896,623,640,426,823,864,764,857,526,635,462,242,821,186,787,244,724,977,78,157,970,159,224,914,664,892,562,744,602,95,240,494,159,536,23,934,32,255,636,642,310,558,51,433,211,154,529,0,74,16,621,717,790,327,850,379,468,976,961,144,421,274,898,102,641,104,371,257,506,741,376,488,497,944,806,155,859,644,293,537,349,315,325,167,120,465,845,539,592,906,110,503,838,485,874,592,706,264,838,666,487,437,101,126,846,287,798,294,550,953,469,345,176,428,879,577,623,763,148,784,557,838,305,273,786,464,546,31,97,997,383,507,245,561,663,514,895,824,709,294,143,164,697,176,391,400,141,242,707,4,183,771,499,523,755,458,798,209,888,800,182,597,219,676,158,639,281,735,420,810,854,672,450,838,154,6,230,105,61,135,761,314,196,717,896,572,532,299,965,101,396,200,829,444,229,214,898,488,360,655,810,548,174,150,592,549,785,850,811,135,900,282,280,369,646,709,405,308,120,145,327,236,78,904,851,277,352,745,346,526,551,508,103,912,651,277,722,867,863,520,382,867,437,101,866,511,203,10,625,901,558,406,810,640,774,297,489,812,98,663,904,692,54,981,933,68,326,932,753,611,225,89,340,58,441,449,892,298,82,310,282,73,338,756,751,703,18,673,47,155,907,649,750,11,846,695,727,716,637,472,781,924,344,330,676,884,694,282,751,37,91,223,249,883,461,119,47,241,631,759,514,476,891,410,201,604,527,110,440,964", + "480,866,517,431,600,493,562,194,247,212,367,172,581,399,118,518,208,73,801,286,873,251,922,390,70,983,922,462,104,44,859,962,80,137,106,896,608,652,436,662,853,595,985,297,439,736,364,988,751,34,682,573,531,19,797,585,328,691,27,728,440,340,491,201,441,519,646,327,350,46,34,443,196,543,661,388,260,240,844,605,599,592,647,987,260,528,416,448,127,523,943,791,980,432,906,337,125,703,486,29,335,190,382,844,913,834,375,57,623,878,871,340,893,729,873,649,297,180,969,908,28,284,893,642,781,623,266,339,189,140,156,11,196,696,11,995,72,398,314,638,653,578,973,218,901,360,123,7,611,273,727,240,810,275,552,849,278,589,786,415,605,392,836,745,882,944,516,421,300,856,173,68,22,283,250,496,299,931,894,925,455,322,746,837,588,229,99,160,155,71,95,53,674,59,732,279,608,165,560,655,511,551,30,34,773,245,62,712,529,300,90,416,292,53,274,297,988,903,599,842,470,338,476,816,289,567,203,417,252,933,31,44,371,575,751,892,473,203,980,452,73,101,386,452,426,46,562,609,880,896,191,428,613,431,906,425,86,418,233,374,393,353,576,397,622,684,21,931,919,42,677,395,827,853,130,887,525,588,2,993,50,792,561,920,758,681,140,98,98,951,47,501,738,486,251,604,75,195,746,620,736,705,52,479,228,574,471,628,831,356,950,514,192,726,878,975,117,239,30,7,493,558,595,674,341,808,325,192,717,369,488,957,270,993,431,409,41,86,159,320,191,469,900,491,984,514,764,637,89,340,660,495,242,744,332,733,408,522,797,104,897,529,680,810,76,746,915,60,909,756,792,45,464,810,756,785,568,145,291,227,170,498,926,762,553,821,773,163,170,751,402,746,804,897,339,260,279,675,404,304,629,8,634,602,696,526,830,37,867,337,442,368,77,720,244,543,951,352,742,629,657,289,548,243,806,644,40,534,779,409,35,102,646,592,357,182,418,125,364,135,868,992,51,693,526,553,730,911,665,266,484,450,78,199,969,277,588,370,648,428,438,817,398,716,811,154,700,998,97,823,589,74,405,864,636,110,963,859,897,74,709,733,58,521,475,341,900,127,481,701,862,73,606,192,18,688,752,730,779,707,163,854,988,494,98,877,72,716,372,432,865,428,248,143,211,937,727,448,827,873,578,518,286,562,342,944,535,325,270,307,642,250,286,794,701,896,593,775,614,808,827,930,994,548,97,942,687,273,479,642,525,993,308,424,856,858,268,144,502,637,124,554,715,724,780,946,753,124,506,267,199,519,792,296,566,318,906,761,481,690,925,488,927,122,58,488,204,272,151,545,999,43,244,482,692,741,620,180,440,298,322,34,229,200,369,460,765,994,740,107,714,408,243,120,5,431,943,380,501,977,818,679,618,55,228,208,602,746,128,276,753,541,874,821,399,629,452,809,941,402,681,296,138,193,660,462,233,920,723,222,910,672,733,198,81,832,352,767,306,469,631,356,725,938,186,991,253,626,712,91,974,888,965,229,990,384,881,455,474,582,969,164,441,910,678,484,352,663,203,93,863,187,524,662,403,421,790,826,397,433,970,433,996,302,919,25,471,98,821,320,1000,283,151,120,221,58,507,74,0,989,280,62,23,850,211,398,927,34,695,661,496,774,839,192,647,344,804,46,603,612,251,117,289,34,274,686,755,748,936,511,759,706,179,822,533,222,163,769,508,160,348,555,696,809,772,700,791,566,250,50,409,447,565,653,595,922,151,735,368,239,639,349,823,558,369,842,218,279,68,905,284,830,307,756,634,378,843,606,6,261,742,331,336,956,373,890,139,78,405,335,384,457,742,698,894,757,806,363,742,456,689,641,344,255,257,126,809,202,451,453,547,611,911,455,259,855,447,327,704,303,630,353,202,458,575,489,52,426,113,70,98,86,519,568,269,544,467,3,559,168,433,204,965,856,59,571,824,820,410,504,672,630,268,936,776,597,45,751,845,836,486,885,486,363,604,825,17,628,309,425,334,412,907,512,135,323,149,752,340,312,320,24,818,152,983,435,206,790,950,548,701,200,137,212,517,402,257,384,599,646,934,109,401,496,584,587,874,992,686,520,615,90,950,378,163,156,253,120,408,250,989,831,521,387,534,229,945,167,188,89,408,418,688,945,330,345,552,982,70,202,863,283,942,555,153,794,892,86,712,210,372,850,562,125,21,217,408,601,535,951,375,878,846,753,222,348,886,171,368,525,420,812,716,445,76,852,609,320,504,585", + "604,792,991,323,681,509,116,530,967,598,984,379,561,6,625,382,607,33,496,234,960,342,100,893,847,125,964,893,553,55,538,854,359,608,334,534,676,35,927,81,373,785,944,602,484,453,259,671,778,884,356,317,95,60,133,745,659,94,28,38,848,904,147,897,466,845,701,157,201,134,451,549,997,428,288,439,538,267,267,924,608,288,325,360,912,933,34,562,150,66,119,679,419,801,760,290,228,128,116,742,910,49,418,330,773,637,179,977,862,805,402,696,644,964,908,346,941,385,999,277,786,70,631,334,244,56,879,323,345,75,301,679,546,505,150,822,939,977,122,53,157,222,470,633,810,809,639,156,399,293,781,312,133,819,540,766,912,198,580,5,413,969,979,520,62,256,81,854,254,170,691,556,705,798,218,726,941,881,499,756,764,361,801,351,415,181,416,134,881,981,530,420,42,80,447,214,643,320,540,292,770,976,289,391,251,826,482,117,493,410,206,568,165,546,709,256,876,86,234,836,340,780,829,437,125,77,347,523,252,571,291,620,891,608,651,20,418,655,277,582,598,355,576,902,726,448,498,843,416,442,736,45,609,672,155,197,248,120,699,149,125,832,757,500,531,63,708,220,275,421,620,149,954,510,792,229,782,810,816,958,716,80,358,849,975,540,649,445,640,473,550,562,651,806,83,948,44,400,991,963,440,950,144,944,486,237,789,917,420,237,440,331,798,843,513,534,325,927,189,113,292,172,959,191,157,661,75,266,146,481,294,891,156,89,725,910,808,76,429,534,415,528,83,833,138,911,208,99,657,675,323,489,934,46,724,561,128,522,694,314,281,286,531,164,729,10,350,253,479,474,314,153,527,667,917,483,946,611,730,864,908,303,237,595,95,968,454,816,609,151,898,856,654,315,640,987,928,970,135,693,916,604,81,905,348,536,72,411,980,100,460,452,214,393,722,643,574,68,253,651,488,202,86,60,517,153,733,563,316,523,81,960,970,864,215,598,912,656,531,777,324,831,765,254,582,254,670,814,675,781,426,298,917,25,242,624,749,596,596,176,262,375,400,139,916,941,292,50,52,579,359,451,384,802,620,154,39,708,801,57,55,54,749,613,113,157,236,591,73,886,201,792,317,91,743,329,350,509,2,636,490,609,503,524,228,329,53,487,373,370,494,942,793,292,963,467,633,147,233,287,701,434,8,84,34,887,473,573,181,725,186,904,125,741,588,581,978,224,297,859,796,316,646,693,37,966,759,861,783,875,179,98,417,119,166,557,243,251,101,96,572,955,415,195,297,943,120,725,197,910,103,361,240,554,530,79,388,969,792,509,369,211,848,226,603,113,886,720,325,851,173,595,211,298,590,845,577,736,391,243,759,405,287,152,887,508,422,493,277,922,461,281,242,942,450,186,682,632,819,187,598,409,826,56,360,831,356,709,161,640,770,313,227,375,517,66,14,193,919,826,132,862,667,700,524,75,348,176,658,432,777,193,18,387,572,931,194,913,220,827,19,375,326,752,301,695,235,548,780,283,372,844,661,189,231,803,974,912,388,603,307,949,708,594,619,554,165,386,523,862,623,809,732,342,57,995,484,902,654,843,456,381,970,990,131,172,941,297,722,163,391,686,932,934,871,794,509,16,989,0,553,500,370,416,634,430,418,859,136,912,805,945,792,67,867,330,169,97,11,814,484,826,199,2,959,294,648,118,741,881,16,142,538,102,90,537,833,251,283,609,197,810,42,128,856,887,218,700,295,248,59,135,773,839,690,409,161,780,793,398,460,998,579,134,636,132,801,476,635,409,375,126,701,829,535,201,129,916,392,813,59,457,385,424,721,918,789,818,170,377,981,444,500,903,308,155,137,125,304,546,207,609,332,496,714,418,949,523,899,663,723,50,677,21,844,967,758,754,351,224,210,798,577,75,210,928,130,234,587,807,234,723,302,491,380,432,476,597,518,557,551,290,16,149,248,515,502,843,857,882,917,545,791,953,333,746,462,405,320,361,972,735,819,422,859,4,167,186,375,25,877,668,18,802,684,927,344,410,681,234,162,538,89,940,848,243,187,329,154,358,902,983,205,244,361,364,771,252,474,459,558,30,242,937,646,270,59,837,800,697,766,871,965,952,359,4,80,455,873,751,977,710,114,143,938,893,310,787,972,533,257,876,310,236,24,337,666,648,872,325,804,415,797,642,615,340,675,41,204,248,390,194,171,94,743,577,468,293,382,258,940,348,51,756,53,229,397,244,998,306,67,310,773,401,284,887,33,772,674,600", + "451,56,77,391,528,365,400,145,406,555,399,571,259,127,875,471,406,899,634,505,62,449,619,141,333,455,160,713,485,516,750,146,967,388,354,64,584,22,398,555,306,712,154,913,188,561,886,904,299,724,915,931,176,961,170,428,826,623,10,739,909,273,561,346,70,734,867,440,786,925,978,349,377,596,408,854,897,45,255,372,60,938,897,804,468,316,890,727,679,997,722,977,939,879,680,774,120,154,342,475,890,126,352,986,647,118,405,622,20,886,661,797,847,82,515,240,738,934,570,99,745,720,413,718,451,22,285,338,20,403,55,870,254,553,184,24,343,180,843,407,323,48,390,875,663,122,762,359,958,938,33,627,314,644,306,367,957,400,653,542,580,480,100,446,986,806,792,845,69,760,598,131,175,885,561,96,920,699,585,3,198,658,299,434,359,44,304,307,277,154,117,990,883,511,805,901,31,957,832,581,257,183,179,718,915,360,358,272,123,29,469,887,608,919,676,101,866,429,793,762,424,793,849,56,265,138,676,772,65,955,59,224,113,612,496,943,163,417,467,986,726,39,817,748,608,728,439,913,644,117,950,423,17,124,211,57,287,667,102,703,671,96,947,314,634,656,977,392,414,664,10,960,98,416,468,529,687,254,355,182,187,861,522,793,381,543,28,274,8,887,253,464,7,327,53,246,374,990,578,856,681,230,525,448,886,746,297,186,37,139,852,995,207,721,810,395,96,368,937,497,221,336,410,342,514,368,203,488,159,33,188,612,248,55,786,92,269,861,999,402,576,863,687,151,205,156,798,827,77,391,18,917,782,6,320,842,565,994,237,94,558,707,247,994,924,265,778,366,752,97,495,631,243,777,861,198,661,619,184,531,869,511,174,127,337,922,889,285,506,980,277,338,400,421,375,685,582,33,559,832,456,176,206,483,876,914,899,783,919,503,999,932,707,703,388,565,127,410,373,702,752,89,875,174,694,297,524,705,986,949,631,91,944,561,552,9,43,325,340,952,135,659,517,654,897,173,67,803,621,35,479,785,636,836,897,195,290,907,534,151,428,655,794,606,362,41,659,616,361,669,914,690,488,858,610,54,982,25,661,995,207,117,471,217,176,915,792,964,376,476,452,809,804,424,215,873,878,274,340,888,552,316,341,861,491,474,829,115,323,459,317,407,806,70,50,203,879,803,629,992,519,704,132,757,114,251,706,408,38,105,23,530,583,734,690,880,714,141,238,884,77,848,171,614,402,530,572,269,660,717,418,448,130,834,736,225,551,682,71,298,468,406,262,307,935,600,40,806,839,372,963,77,908,263,283,618,267,270,676,316,894,218,44,786,437,821,31,161,543,277,980,140,917,835,239,104,786,814,243,379,599,526,17,536,392,305,286,431,118,647,68,375,781,579,422,527,361,63,42,179,139,450,79,320,331,410,533,592,764,583,139,156,462,34,859,592,499,914,144,267,147,471,761,671,977,37,467,177,107,307,327,646,728,326,161,374,321,263,559,762,163,499,570,374,922,58,496,968,762,207,393,709,830,735,962,330,944,528,784,650,957,276,208,531,868,361,449,750,929,62,320,465,601,809,822,832,6,507,874,827,7,536,639,713,653,507,499,776,293,522,458,18,785,383,734,504,824,621,280,553,0,178,6,999,349,974,991,505,179,920,213,331,156,139,639,317,55,855,954,797,69,174,388,716,814,419,654,417,670,939,89,567,409,361,802,360,928,974,528,309,964,693,653,466,29,533,116,240,678,68,353,159,956,602,844,579,983,435,810,656,436,48,946,466,307,497,426,381,244,607,735,917,353,600,633,161,111,781,965,502,670,683,391,989,706,466,365,54,697,235,810,855,261,964,682,360,99,517,177,505,553,300,204,44,287,560,147,412,73,629,694,563,94,379,744,229,483,909,821,231,190,572,843,884,613,258,486,746,391,844,288,142,848,526,29,658,348,208,159,243,577,145,124,133,42,682,193,637,412,896,435,335,190,588,636,799,504,305,140,322,194,812,642,374,303,267,89,503,445,716,149,101,542,575,878,297,76,311,311,652,654,136,606,595,547,598,972,969,674,258,518,251,867,271,969,459,138,307,740,524,554,844,108,165,616,896,715,865,166,104,935,586,822,839,402,750,310,922,505,815,63,269,168,88,900,56,144,663,978,616,738,736,823,688,620,581,272,610,555,489,963,269,910,916,51,515,85,874,311,905,814,400,320,688,534,923,346,288,342,252,981,73,264,643,580,552,381,641,572,279,162,269,872,609,580,811,258,27,185,539", + "271,337,617,359,416,595,21,879,206,805,973,461,653,936,209,984,527,101,531,920,246,121,36,911,932,566,480,120,842,356,417,80,283,923,273,456,181,75,364,571,622,854,344,106,541,463,710,318,382,416,283,75,598,332,603,878,846,71,716,162,163,799,844,169,625,302,214,603,749,426,183,180,81,215,645,939,563,583,664,250,963,487,100,651,587,916,402,840,466,108,968,381,65,344,484,571,914,274,138,311,862,12,550,836,625,464,904,589,536,366,827,952,127,585,770,647,124,589,181,712,732,253,740,469,941,903,431,875,207,878,583,86,34,808,21,215,30,329,251,794,927,268,380,33,614,430,702,619,271,581,594,103,766,619,179,948,965,673,720,579,113,732,909,418,666,978,387,419,74,846,697,206,838,678,191,149,621,517,905,20,726,186,375,6,267,141,462,905,298,256,592,576,266,782,941,138,827,963,465,73,87,671,532,121,459,308,165,780,173,735,315,901,458,790,256,742,82,536,550,628,704,114,732,977,755,405,86,898,993,622,712,478,798,923,197,737,600,101,186,217,456,132,883,571,221,289,376,871,643,733,558,268,602,363,99,2,372,1,566,945,543,400,204,59,437,292,735,419,530,195,281,509,295,455,872,74,670,722,205,315,884,410,316,328,192,70,729,385,469,640,129,401,250,148,769,143,847,301,413,323,960,857,516,427,452,771,606,831,253,765,795,500,966,726,783,679,201,178,644,197,348,292,91,849,923,840,472,546,618,527,172,210,463,111,237,742,61,483,604,223,314,865,829,272,697,643,536,229,871,91,731,98,465,17,13,329,563,53,427,982,428,875,894,324,227,505,158,987,615,545,631,898,812,686,124,620,310,294,146,101,940,77,363,197,872,550,363,106,881,164,823,704,186,736,390,974,221,645,247,623,129,690,719,387,192,566,437,891,86,85,152,116,55,249,603,527,555,927,148,267,411,966,722,2,998,528,462,88,235,599,547,581,30,559,881,960,974,315,312,908,382,97,205,292,991,890,502,722,631,396,704,6,741,443,684,842,6,3,252,549,253,542,359,358,225,3,361,39,274,990,444,523,165,890,371,474,658,494,193,970,966,500,734,550,400,757,54,977,361,760,34,12,53,576,972,410,841,39,668,81,476,20,373,826,245,445,161,607,695,340,152,14,156,691,558,54,420,368,91,962,274,20,570,664,265,638,483,151,214,409,855,457,838,895,336,960,532,334,463,152,963,290,686,194,838,869,514,625,13,882,73,203,716,790,650,894,781,270,817,389,509,29,428,785,211,145,463,489,576,397,79,125,412,144,519,952,863,668,10,250,158,668,276,625,336,75,898,516,186,714,458,648,13,432,105,450,685,218,851,333,230,392,979,537,630,181,973,887,425,227,710,209,269,29,63,893,132,322,391,925,104,229,760,974,945,714,777,769,39,541,318,560,68,811,311,373,404,618,856,410,913,196,504,520,535,724,939,489,464,151,84,590,897,467,640,674,872,450,553,321,631,712,103,614,967,9,124,141,841,522,939,106,535,329,1000,991,697,569,349,326,124,520,588,164,16,478,9,633,824,804,172,557,910,443,12,855,891,92,966,619,299,920,877,840,353,901,102,733,469,283,472,164,82,686,932,165,243,717,62,500,178,0,797,584,621,148,726,386,380,532,473,184,540,237,917,659,647,879,682,864,685,356,275,986,719,32,562,647,575,397,801,724,64,380,1,215,979,792,519,392,693,15,6,876,723,40,492,219,164,604,200,590,860,223,385,273,914,394,847,870,48,760,47,834,268,161,815,688,510,957,770,184,960,657,463,291,944,15,493,918,268,68,732,381,816,435,914,783,748,939,142,895,559,594,844,315,76,689,898,920,121,541,128,20,516,86,251,849,899,742,545,110,170,662,755,203,547,485,228,38,678,125,167,62,503,916,53,74,370,800,137,207,554,217,569,112,351,724,705,456,804,77,758,658,608,42,929,562,864,453,105,471,40,805,484,473,94,362,535,590,623,38,886,367,832,806,893,670,336,837,561,441,157,640,448,80,850,949,762,798,541,610,418,875,69,523,672,568,640,839,358,662,57,133,553,376,751,520,453,992,953,140,812,974,852,638,462,684,679,398,636,135,216,995,100,958,362,23,79,758,168,336,904,528,290,919,238,993,477,249,596,42,300,677,116,159,985,932,632,25,485,719,330,264,630,192,185,448,158,797,910,518,900,738,32,31,621,62,365,755,363,940,650,177,957,113,648,410,289,83,280,597,355,65,758,622,184,197,277,320", + "99,424,659,930,971,142,111,578,370,173,458,19,951,767,762,876,815,790,252,668,3,160,645,652,359,966,824,516,334,307,963,200,699,958,37,533,623,809,605,45,514,661,94,941,655,958,152,555,393,296,195,249,569,363,659,672,746,73,313,782,329,426,219,595,20,703,220,999,356,357,79,463,147,202,437,209,757,58,110,299,216,326,604,239,420,64,252,559,983,923,166,711,4,492,599,981,91,724,149,386,112,9,146,548,196,458,802,564,708,797,455,318,802,589,775,556,562,584,481,895,16,282,15,295,329,231,654,972,67,950,6,877,713,688,584,762,967,315,217,152,707,180,415,8,356,196,125,977,409,879,231,298,132,361,342,259,910,617,255,199,293,503,976,808,772,336,985,458,340,513,508,770,971,736,730,606,731,255,509,12,406,647,62,436,576,125,425,820,981,231,60,918,495,952,882,647,327,266,358,932,493,159,411,988,45,829,348,250,150,912,78,367,209,593,459,259,872,663,778,362,688,199,436,994,867,352,785,494,251,801,175,814,842,88,883,1000,713,86,513,376,959,694,789,968,585,262,79,834,128,190,193,52,205,537,168,252,188,912,539,697,176,304,307,896,830,840,885,380,754,905,710,223,651,105,341,226,758,359,214,649,637,785,338,544,613,387,264,264,569,776,773,685,65,846,476,817,650,41,365,912,21,878,332,592,539,531,479,700,426,240,831,297,43,534,371,575,456,676,143,199,887,359,138,979,559,789,376,370,223,16,97,742,377,985,610,818,154,443,982,42,791,943,326,208,33,209,40,64,724,179,764,2,653,157,706,622,71,833,871,506,921,988,1000,672,150,611,149,602,793,615,982,336,153,802,842,211,142,321,737,530,856,428,707,351,308,429,706,498,242,975,417,258,546,9,301,74,799,901,64,979,447,831,90,202,849,510,305,999,888,184,667,465,947,527,336,52,646,852,228,316,631,80,702,210,105,292,545,588,647,332,890,604,452,267,840,654,174,294,426,605,759,306,63,575,310,503,697,602,989,674,727,500,216,344,55,628,1,836,69,11,615,389,975,487,225,427,164,646,619,778,503,734,129,768,940,325,598,934,997,719,9,464,996,303,571,289,658,440,647,964,219,46,43,984,617,830,646,32,807,883,104,455,251,769,629,150,393,681,190,367,272,284,540,811,550,221,451,627,632,218,39,326,885,36,544,569,9,110,853,700,158,352,153,144,446,453,478,827,412,59,904,778,77,790,240,651,722,566,363,787,585,472,966,139,352,17,50,33,435,540,272,784,105,716,748,195,308,814,726,167,484,151,406,836,979,433,960,891,43,36,605,125,466,570,421,995,900,504,760,305,855,903,946,500,843,371,154,999,779,532,994,456,365,92,645,161,697,889,385,781,947,525,781,19,454,39,424,777,454,339,71,278,667,814,579,811,270,462,981,670,331,529,33,357,808,706,885,156,825,685,582,349,518,632,779,816,300,74,962,613,157,181,350,392,495,451,672,747,835,876,797,504,447,784,857,258,240,634,22,425,872,46,132,270,136,211,805,272,18,43,243,827,891,372,805,1,640,184,486,358,365,426,341,148,112,566,790,720,858,819,468,337,615,474,338,184,260,701,139,767,276,108,534,240,488,146,264,790,23,370,6,797,0,761,350,35,495,240,758,552,732,238,399,642,288,804,913,56,728,542,208,192,34,571,649,151,523,145,443,612,966,561,220,939,419,365,477,853,215,726,604,317,872,661,306,915,552,969,793,736,509,231,203,687,966,288,49,349,882,483,920,458,440,123,25,273,766,326,457,690,717,333,729,471,607,354,697,668,492,817,830,289,155,984,428,305,102,491,308,573,810,581,503,799,312,80,944,542,403,300,738,879,427,843,672,984,586,123,96,882,19,588,597,992,228,602,895,456,625,283,113,317,691,93,832,858,556,550,342,531,746,587,22,903,592,313,786,519,984,337,861,617,186,793,373,727,879,503,560,932,890,744,185,52,767,259,541,823,11,265,303,349,967,254,282,493,227,547,584,555,347,470,517,783,788,786,623,478,176,403,439,788,722,850,849,248,643,430,816,988,308,603,26,301,234,856,922,95,289,379,957,312,633,691,359,229,272,812,10,808,857,886,470,513,976,373,460,957,785,368,152,39,580,664,21,313,47,60,59,155,874,727,420,441,591,809,344,298,577,490,679,444,925,308,317,145,940,306,700,346,832,503,177,148,628,91,10,120,840,739,829,331,998,540,954,690,606,582,986,71,936,258,728,431,502,901,508,386,820,313", + "81,136,695,967,781,234,369,52,568,312,931,506,485,509,182,446,100,551,553,324,986,488,728,681,508,371,347,454,808,463,459,55,962,280,382,112,675,199,96,244,313,428,586,268,444,21,452,714,458,899,431,1000,142,36,26,588,910,845,653,575,681,70,905,596,177,375,602,156,249,336,693,959,837,351,719,557,794,891,882,651,697,351,352,572,532,764,137,470,349,860,106,367,424,18,795,666,668,152,676,580,357,351,296,33,276,698,485,949,64,773,228,169,572,709,790,161,646,215,518,684,86,466,655,381,856,618,819,736,894,555,480,328,610,479,792,450,765,76,262,690,149,21,469,474,488,782,498,831,454,110,787,996,786,194,673,985,167,923,608,768,840,778,540,619,77,569,3,270,955,322,603,780,723,849,464,180,3,323,782,373,776,597,897,914,827,424,767,767,57,24,461,271,88,345,71,323,149,576,659,112,306,321,586,668,943,914,29,272,73,637,147,278,823,398,404,723,821,634,602,399,193,309,974,769,233,90,745,371,125,347,2,112,518,278,420,102,319,454,28,908,115,649,775,297,290,227,912,119,307,904,798,239,779,972,668,710,396,742,51,739,449,196,13,66,952,375,354,465,632,669,681,736,365,854,370,473,51,5,920,515,325,281,706,26,546,321,795,495,628,745,671,634,716,987,213,622,435,272,129,150,653,7,383,796,654,267,519,279,202,870,851,504,256,225,803,582,43,298,871,290,88,825,654,318,343,956,630,228,325,450,374,699,450,620,511,177,633,70,995,172,971,704,291,101,965,828,937,360,458,230,518,361,634,675,193,91,620,401,916,401,50,703,716,619,773,431,24,73,329,390,335,38,268,284,463,788,686,645,77,825,11,369,418,425,445,936,997,138,150,470,257,269,918,809,977,457,60,223,984,330,975,772,288,208,632,776,929,4,622,64,126,203,754,311,7,547,470,843,807,261,343,536,795,521,727,468,848,779,565,399,42,584,506,478,625,841,602,379,357,703,621,104,313,147,737,961,314,750,735,163,699,375,617,393,768,670,49,396,826,247,397,226,200,439,556,11,87,189,201,443,33,308,194,698,873,548,994,840,126,124,55,670,74,454,744,376,602,758,477,684,440,769,646,718,738,846,792,637,897,868,885,952,373,956,652,377,571,892,495,822,158,2,806,632,11,47,119,649,718,610,864,729,159,347,947,688,414,825,49,940,643,899,623,862,703,498,751,605,164,557,140,219,657,112,462,867,146,213,60,959,385,455,231,196,40,689,853,774,159,352,582,321,370,804,863,418,57,668,135,436,7,568,195,461,7,876,117,345,598,761,188,207,914,144,531,728,730,331,95,842,713,774,789,104,485,868,322,231,712,291,196,568,78,383,132,179,881,940,908,338,70,654,305,121,680,30,598,670,41,65,664,396,22,319,151,754,920,735,337,242,706,620,871,908,609,839,76,901,50,292,154,100,672,400,985,805,707,624,922,708,608,764,890,40,985,300,580,788,993,717,839,890,38,914,288,935,843,546,849,284,323,468,752,48,312,964,723,762,807,398,10,290,758,120,247,519,585,785,232,33,701,239,86,597,890,355,459,904,598,750,926,48,766,522,170,698,871,569,281,728,295,107,402,100,687,781,524,327,850,416,999,584,761,0,937,561,723,101,974,128,642,105,959,425,220,407,575,132,220,539,279,348,524,924,856,690,789,185,41,478,648,134,686,574,564,38,769,908,951,399,840,343,93,758,532,316,503,621,825,642,307,119,267,621,515,170,602,913,568,781,526,700,440,380,156,564,1,110,885,27,914,316,946,416,485,431,497,339,820,92,358,54,16,326,862,279,848,641,480,874,12,954,432,629,61,109,490,557,927,440,115,459,477,622,406,888,83,342,193,725,777,287,137,642,512,447,753,970,103,559,174,536,273,873,437,467,604,598,883,944,386,734,38,941,149,62,620,48,62,644,982,545,190,295,339,530,10,401,932,38,814,631,797,916,88,489,588,301,247,960,367,679,227,162,149,452,149,562,437,644,776,378,512,276,466,221,306,610,283,362,767,116,347,61,486,240,787,208,909,377,981,286,273,307,339,641,97,391,358,107,174,119,256,815,133,106,899,532,489,564,796,810,413,458,330,143,121,453,730,717,6,396,484,794,510,356,851,967,72,882,562,837,215,415,625,859,16,177,345,782,657,852,522,789,622,802,522,999,594,631,604,511,790,168,543,979,942,834,212,636,2,155,473,904,223,500,48,128,440,349,165,32,742,682,416,28,384,75,221,414", + "131,669,334,986,46,819,898,733,80,377,500,892,469,459,504,32,632,769,591,959,749,494,472,910,786,502,158,284,371,196,643,978,664,608,632,823,722,307,722,245,235,625,917,440,568,598,562,295,390,681,87,693,325,246,719,125,407,425,514,777,259,911,294,281,418,906,746,6,551,158,679,562,850,725,868,466,960,321,704,74,594,90,992,225,87,211,524,470,135,447,954,124,552,223,243,242,865,378,423,943,622,670,953,681,83,690,598,756,376,725,291,901,855,891,720,327,857,468,764,261,900,652,534,342,519,147,984,974,633,399,563,181,262,193,483,166,70,361,428,39,211,287,20,787,499,472,742,568,539,807,594,344,97,915,736,740,701,396,478,747,197,720,351,623,336,668,983,566,423,789,836,276,274,485,997,401,409,849,645,286,157,430,935,729,968,32,694,465,242,109,717,507,7,864,216,219,661,382,247,362,436,981,808,116,691,456,73,968,592,443,84,192,97,598,532,854,852,68,388,622,760,537,592,863,697,434,231,768,813,54,895,161,230,663,336,520,357,793,985,562,250,779,973,770,740,112,725,174,17,27,733,471,678,775,638,457,143,64,107,733,845,985,874,276,701,72,890,809,626,558,859,850,237,768,548,586,357,453,566,247,863,541,960,203,435,281,582,703,682,165,187,822,953,165,821,660,404,166,79,829,266,849,908,365,710,468,275,753,449,403,683,917,609,724,615,770,125,204,32,233,717,313,67,733,901,470,58,128,859,400,562,858,29,158,205,862,488,138,97,204,577,485,778,228,398,414,718,303,907,281,380,707,323,992,699,457,269,95,399,854,864,943,915,686,349,751,621,236,418,902,637,289,993,676,317,79,831,259,593,829,135,568,840,602,799,889,617,819,690,414,695,563,59,33,626,79,421,507,609,300,350,90,729,7,846,205,672,211,931,193,626,178,994,743,15,23,44,113,489,996,916,837,965,795,294,45,3,642,331,864,431,222,50,117,972,21,140,566,41,56,201,763,761,157,514,319,61,571,672,624,308,148,246,331,409,546,299,441,806,279,374,327,978,952,168,704,8,362,634,462,956,822,779,73,907,695,349,658,269,154,66,586,731,51,32,709,694,22,574,212,359,99,565,815,122,744,560,104,787,32,992,88,74,656,494,876,912,551,741,925,452,12,487,264,168,208,665,654,351,183,829,299,81,265,117,876,896,954,209,711,501,99,325,600,153,406,952,771,864,816,685,7,836,571,14,227,496,896,69,364,515,823,274,15,885,144,502,20,584,125,629,854,24,33,454,70,341,7,491,307,237,907,638,145,299,988,732,577,170,855,32,56,161,562,574,600,176,742,930,735,4,182,196,929,189,243,793,100,447,520,495,400,666,305,779,863,200,697,485,295,859,538,301,875,670,69,869,625,304,756,770,739,425,281,906,544,581,429,142,567,352,913,903,667,480,35,134,548,206,445,740,902,187,578,11,853,689,372,367,581,971,200,949,762,616,958,58,936,868,51,821,551,998,968,260,177,184,943,179,981,520,409,593,453,313,77,394,578,49,586,854,514,723,739,244,386,226,239,9,581,804,930,451,636,692,351,527,769,102,728,854,764,155,453,671,377,475,597,21,783,807,433,415,766,176,437,662,850,211,634,349,621,350,937,0,501,967,795,909,662,159,444,815,681,939,476,731,69,570,903,919,260,21,323,897,864,478,89,583,275,911,104,898,581,861,506,339,161,230,912,398,988,162,964,388,896,29,973,18,351,671,404,348,157,142,172,306,332,811,158,35,535,442,327,921,1000,911,436,570,76,514,474,574,787,376,896,666,110,449,127,65,647,253,53,299,468,577,917,557,254,74,441,221,219,893,175,388,868,259,175,789,376,586,896,930,71,619,620,373,790,221,286,293,358,751,676,750,539,566,812,748,945,210,171,243,428,119,984,393,7,115,458,11,685,45,641,536,430,32,630,910,432,387,414,437,74,338,562,757,900,401,574,975,534,978,787,209,51,804,150,67,721,520,240,398,843,209,184,502,333,965,559,534,597,820,108,701,420,257,992,417,318,18,743,188,166,571,56,598,139,151,808,161,845,214,581,321,540,271,188,469,365,751,462,998,793,937,638,307,140,907,315,635,625,697,898,56,625,694,858,921,871,428,117,772,44,93,227,754,177,81,151,785,819,619,268,582,557,887,999,570,938,68,224,928,114,417,486,187,238,423,733,37,900,98,963,707,166,452,138,855,566,783,903,784,961,562,855,293,399,15,8,648,134,660,660,497,880,778,175", + "902,2,797,306,230,305,20,158,790,278,355,978,195,894,185,556,964,38,746,410,66,126,468,822,982,835,643,721,726,364,104,830,684,763,365,833,525,298,121,208,202,218,522,680,935,333,755,484,368,543,801,811,463,757,681,448,473,462,569,159,122,951,345,80,380,390,782,440,918,421,144,96,511,26,623,991,907,747,172,896,627,179,52,940,274,619,778,350,498,217,656,16,123,163,622,618,607,630,382,711,106,755,354,595,119,223,703,341,984,987,836,43,848,252,954,747,209,989,830,644,936,434,21,798,694,499,782,41,735,466,288,504,271,589,672,790,574,583,337,522,583,687,523,70,435,99,212,842,377,468,855,693,58,16,47,841,45,472,207,499,847,796,120,862,752,394,461,682,204,978,750,500,100,474,121,49,841,758,651,308,95,750,889,518,889,656,223,251,307,878,299,244,184,714,500,956,731,830,436,25,455,699,677,573,126,160,260,163,137,850,373,337,39,165,620,365,924,798,78,146,575,203,752,848,381,743,181,758,71,487,983,720,126,591,3,374,805,445,960,545,608,156,999,475,678,302,803,894,452,330,114,76,655,893,780,924,110,298,947,172,248,847,364,288,470,970,285,725,558,835,234,53,346,305,291,730,96,562,704,408,597,944,341,946,573,976,497,967,424,856,339,80,437,802,466,887,251,331,496,265,439,50,954,982,311,111,770,506,376,363,831,792,936,988,415,674,619,618,676,484,717,359,409,436,456,502,846,153,912,213,565,178,165,803,351,861,967,921,681,268,845,965,719,769,636,340,14,255,449,533,5,837,205,25,232,544,306,444,300,516,412,335,310,338,180,145,59,163,139,129,535,974,320,84,774,574,18,69,591,380,690,190,69,182,983,243,813,527,399,669,542,358,964,152,753,80,476,358,743,118,46,717,575,663,565,930,464,304,949,542,648,892,647,338,636,722,26,812,979,840,455,82,610,128,356,358,622,812,717,292,271,98,150,449,191,611,709,109,549,148,210,353,286,559,809,741,925,120,122,372,111,523,676,690,429,452,146,963,576,508,822,751,261,955,95,295,710,664,233,58,124,499,878,499,590,960,527,387,36,389,394,290,427,176,743,432,376,486,130,612,20,238,233,170,731,802,443,505,217,585,538,813,124,600,433,207,422,401,830,170,390,37,276,813,393,381,957,351,876,546,544,890,330,552,852,585,834,480,47,323,982,165,475,614,645,532,372,446,59,762,819,512,870,839,485,115,945,901,37,437,434,963,823,644,673,574,690,696,906,924,170,176,997,57,661,205,726,457,901,429,492,450,885,898,171,688,349,50,172,621,967,764,533,156,727,23,771,243,539,550,655,299,185,809,736,738,49,554,516,565,724,328,896,240,729,50,216,219,236,268,669,809,24,73,931,969,354,950,189,263,970,368,629,661,667,812,792,109,529,162,730,754,957,576,523,754,150,203,194,319,799,584,240,49,609,631,201,565,768,865,709,292,224,41,969,512,86,881,487,709,863,433,169,838,764,850,87,773,459,26,963,100,353,71,157,537,640,583,836,385,317,175,927,997,888,834,58,912,358,25,807,736,86,709,755,756,69,891,616,557,778,50,300,67,69,421,639,379,117,34,465,82,532,178,997,233,189,379,398,430,974,148,35,561,501,0,255,63,776,647,685,703,364,449,530,506,210,382,743,8,675,260,551,833,795,554,701,15,271,849,802,277,24,856,742,458,818,65,311,227,388,644,622,680,803,670,690,651,636,764,691,255,764,528,776,885,924,379,250,949,675,78,431,421,41,31,54,733,770,426,596,60,734,380,195,18,82,809,744,211,102,729,973,311,107,875,250,566,441,364,450,984,474,850,854,754,801,708,465,842,308,471,321,657,905,791,994,331,714,691,358,164,215,213,511,768,599,372,851,792,24,322,105,693,500,665,13,267,96,943,377,155,190,834,724,500,290,881,60,292,34,346,418,438,62,941,175,138,843,567,848,899,41,884,465,806,568,373,574,438,79,927,805,666,716,512,855,968,608,391,539,775,271,97,856,239,332,173,768,918,211,845,586,929,783,921,874,177,442,235,687,758,319,199,249,453,523,512,701,90,680,257,894,841,784,849,870,294,801,442,77,229,638,845,945,671,753,694,357,324,403,614,608,141,15,893,211,877,730,957,202,204,399,743,866,583,411,831,501,476,434,124,516,660,69,767,459,619,415,609,792,942,243,434,495,104,519,4,929,622,886,226,727,867,379,235,800,718,770,741,970,232,166,868,639,758,748,958,123,703", + "314,568,375,796,837,924,653,218,262,78,119,606,814,986,327,752,52,771,734,851,552,142,303,387,463,19,632,715,625,36,183,794,782,336,365,423,238,386,676,958,468,540,588,14,696,843,664,553,83,708,545,400,404,886,929,349,550,667,701,73,34,365,283,67,919,871,325,409,474,650,697,209,438,472,855,500,506,182,450,511,116,907,207,179,564,594,502,934,180,750,393,284,49,995,489,323,639,257,892,665,565,205,947,723,492,594,918,55,18,735,253,833,441,682,931,360,705,982,800,854,998,422,92,750,363,144,389,757,494,699,773,548,79,540,967,277,199,150,373,738,358,642,124,284,898,491,570,203,765,808,59,152,580,543,171,170,538,692,476,816,15,811,364,208,9,748,758,40,457,10,648,15,301,494,335,98,990,948,390,272,842,163,668,983,849,806,744,464,257,158,405,836,690,416,480,16,28,927,338,784,584,685,147,160,82,990,414,950,324,202,831,805,523,459,590,218,534,236,881,268,107,467,241,278,580,496,540,739,973,506,952,584,145,255,57,831,134,242,96,283,490,233,935,307,420,951,333,575,832,637,11,507,331,42,938,321,108,226,866,995,944,174,189,84,967,181,396,636,471,287,311,442,285,318,410,221,774,558,974,908,266,714,903,981,770,335,424,155,275,494,512,114,591,672,349,135,162,179,257,851,795,765,587,882,342,870,11,51,434,616,476,648,63,61,532,561,400,622,200,378,196,530,173,732,72,187,381,203,529,172,423,101,57,478,303,855,868,547,912,253,334,502,482,812,399,877,21,555,674,759,88,624,694,552,855,591,454,455,255,173,150,669,399,80,853,537,378,179,273,964,100,430,849,353,789,767,786,181,98,8,742,591,402,277,795,663,921,923,380,591,622,522,13,900,803,46,632,955,418,237,609,310,905,3,272,726,668,190,760,648,839,124,505,200,80,394,48,46,95,2,968,81,317,581,252,32,709,250,148,758,249,229,584,75,888,682,345,885,482,697,457,813,133,288,826,177,108,723,662,978,871,398,952,382,846,706,252,498,925,775,290,180,831,440,164,481,397,830,646,368,920,663,468,412,547,761,13,913,623,723,706,346,374,588,855,319,985,660,723,426,672,416,141,99,873,943,365,668,269,120,349,136,175,605,490,505,29,505,704,629,801,279,540,683,626,841,508,294,451,298,447,99,70,772,335,627,354,312,309,194,367,109,205,832,106,884,647,758,808,75,159,490,19,945,124,763,237,12,305,241,997,153,650,662,752,858,794,288,800,89,267,972,200,143,489,888,266,954,34,963,560,442,207,545,126,594,731,249,271,553,823,164,89,928,756,594,938,891,904,960,637,57,594,151,147,517,197,753,924,512,377,735,443,2,588,186,204,902,707,749,273,361,900,718,140,901,720,987,123,702,612,125,95,979,177,441,321,576,782,203,588,144,508,178,992,709,593,735,556,234,511,537,255,719,469,315,411,771,592,748,561,485,561,680,846,531,136,247,306,625,40,602,749,323,954,264,10,450,118,311,936,665,696,82,508,160,733,934,868,853,678,62,949,644,326,191,203,729,842,254,301,856,460,661,401,14,472,926,440,516,593,690,195,377,684,490,658,823,312,966,923,896,687,966,662,666,184,468,927,418,991,726,495,723,967,255,0,41,935,909,571,156,680,901,290,975,542,975,351,558,493,984,172,933,822,4,910,122,118,852,409,862,545,788,128,138,838,875,327,549,583,61,771,197,481,798,949,541,675,429,926,570,869,696,129,961,924,600,899,586,735,872,130,985,866,664,768,445,704,254,2,426,298,148,515,242,469,179,838,953,363,202,936,207,429,527,47,783,536,450,463,119,591,832,152,73,622,844,626,615,859,399,493,408,554,361,339,821,740,436,355,943,911,77,435,211,424,729,715,263,815,618,904,515,32,809,857,539,122,809,356,450,197,690,141,803,554,131,896,366,468,787,856,622,423,31,75,593,594,756,343,338,596,941,679,683,444,269,404,742,986,901,759,884,715,36,621,871,747,786,443,740,523,163,384,870,866,603,576,210,292,566,944,809,716,293,278,429,517,38,443,981,887,260,615,483,500,838,114,474,836,587,203,364,386,157,694,754,563,446,67,94,857,565,440,822,550,300,143,464,903,429,766,578,969,652,640,712,812,147,305,220,493,442,658,139,299,888,615,603,725,897,11,945,2,503,792,381,472,370,986,130,808,77,270,729,607,781,7,531,45,655,850,765,502,441,760,908,146,213,751,682,679,875,36,312,35,136,871,438", + "436,584,721,625,541,312,498,976,773,33,801,285,112,87,232,39,828,890,87,471,351,598,907,959,380,706,528,137,465,291,459,143,598,376,70,779,629,479,440,111,821,891,498,982,464,906,654,386,200,657,784,982,409,506,324,139,958,210,16,226,291,171,383,65,856,733,484,888,306,890,373,873,713,783,693,446,509,216,276,594,865,667,925,25,433,939,65,692,61,433,655,162,381,315,424,241,530,348,330,363,225,309,894,798,267,860,679,873,733,145,826,548,48,531,528,222,170,326,121,151,507,359,164,665,427,136,319,275,150,532,862,99,150,802,61,207,963,468,844,491,623,863,989,723,456,952,230,324,503,946,287,218,183,818,834,825,780,626,830,773,387,937,506,283,591,797,947,247,694,47,652,202,709,825,253,740,845,345,341,688,9,212,415,505,609,305,988,483,583,915,295,326,446,670,270,919,293,48,430,647,965,475,200,729,238,317,218,186,685,410,471,419,645,546,192,484,487,433,545,173,412,437,449,970,489,329,536,831,360,23,176,805,261,245,426,85,730,989,111,912,19,193,948,635,647,542,984,980,3,683,820,209,620,229,742,425,858,273,40,549,867,148,701,447,285,994,533,291,409,301,379,296,964,115,317,375,976,638,413,271,768,176,721,177,954,639,65,125,462,589,827,555,688,315,502,338,257,222,77,471,946,422,312,555,215,679,886,119,773,463,370,83,142,715,740,712,991,852,504,401,758,248,852,941,599,486,297,627,330,400,710,293,758,978,298,142,250,746,92,694,67,659,653,154,726,140,191,853,870,799,217,868,112,337,21,898,163,711,606,159,945,411,164,161,827,389,883,772,631,725,894,213,789,191,512,436,825,669,763,827,897,863,242,419,935,65,677,113,418,820,9,547,860,145,462,593,943,216,58,207,256,849,389,838,658,422,350,961,298,886,871,930,677,459,748,744,303,637,918,749,287,735,127,104,97,391,547,369,474,467,464,573,172,183,782,980,333,518,154,144,704,223,873,439,16,287,805,49,951,876,605,479,204,575,517,701,244,713,530,917,839,897,359,585,484,755,553,393,640,151,132,451,765,867,953,149,741,69,708,222,483,118,400,878,89,598,946,535,674,145,144,616,117,967,903,527,723,268,361,785,679,638,191,250,958,782,748,121,67,945,724,194,228,881,641,910,548,491,390,846,517,720,296,697,27,122,647,634,336,620,117,426,99,589,964,377,226,52,456,901,226,197,504,310,878,392,485,946,96,380,796,654,864,416,735,784,872,690,633,716,545,503,489,409,329,142,283,879,774,457,720,428,633,346,425,930,449,766,922,221,471,398,210,453,808,591,535,839,523,120,879,772,561,590,949,510,671,15,865,562,992,673,525,262,705,617,843,173,238,103,363,690,923,753,3,328,411,423,395,919,390,222,122,448,525,422,945,171,951,531,956,216,23,245,660,757,892,897,49,215,979,559,592,803,476,213,726,349,886,299,261,820,950,739,212,673,573,814,273,621,393,228,24,775,83,557,734,615,993,244,827,26,295,471,789,300,263,19,144,67,341,154,20,180,369,561,564,424,481,620,879,875,722,383,874,237,194,675,900,57,533,511,924,657,380,819,654,562,286,437,814,332,597,102,168,959,475,976,34,859,505,386,240,101,795,63,41,0,5,696,262,580,105,97,732,754,413,378,586,228,741,152,484,314,171,474,918,79,826,91,869,189,56,114,906,171,893,456,229,124,12,904,602,87,257,408,263,670,715,588,994,377,316,817,83,863,671,727,166,998,218,632,23,426,60,884,931,607,216,569,123,427,115,895,498,933,83,364,410,408,411,972,866,513,756,782,574,67,622,98,815,932,429,191,448,430,501,629,55,232,102,758,548,522,374,468,605,14,317,672,515,598,961,272,323,523,586,324,481,679,532,885,400,247,214,565,112,843,285,471,393,584,603,168,413,282,108,773,33,809,664,128,438,459,578,178,549,22,716,858,82,893,737,656,508,632,179,892,378,946,996,54,79,262,633,447,74,213,551,357,540,601,254,629,610,708,528,920,912,225,807,323,844,298,71,838,105,520,8,271,296,389,54,621,920,767,521,619,150,508,202,706,158,896,60,726,35,232,621,573,660,817,402,617,799,900,605,587,154,252,879,288,745,936,615,979,237,967,535,970,404,386,782,243,787,43,420,860,616,330,518,787,209,141,54,786,395,17,671,315,574,216,689,229,992,569,568,649,896,417,501,996,7,364,700,579,839,791,49,761,327,826,763,719,545,555,397,475,29,484", + "979,294,220,65,235,678,915,574,330,570,781,534,512,578,742,247,162,432,355,629,802,420,175,983,168,454,287,119,30,965,563,402,671,415,627,136,649,265,147,802,954,252,791,215,849,837,635,666,467,572,452,674,908,249,896,39,253,877,893,408,311,644,533,441,65,313,756,70,126,80,475,540,620,446,834,777,581,113,773,149,550,366,530,987,194,467,621,896,13,629,939,51,280,124,88,329,412,177,803,103,291,428,994,975,867,445,269,306,987,708,237,56,283,379,440,887,684,461,585,566,493,128,887,536,356,842,173,761,383,859,160,490,512,941,431,1,810,714,949,781,757,392,905,569,966,247,767,302,927,85,151,228,973,453,261,251,885,87,207,290,589,383,980,256,831,805,671,279,448,965,202,843,355,271,485,218,402,839,405,390,894,453,528,581,778,516,574,755,151,426,568,105,695,159,753,874,407,244,750,854,867,308,445,428,927,892,338,39,201,612,725,824,362,162,727,421,475,937,541,771,243,980,377,434,621,324,762,367,226,598,37,24,940,295,785,669,818,11,566,371,928,568,338,762,796,827,371,999,234,892,598,753,614,318,939,621,179,811,253,670,263,193,185,801,25,969,127,597,604,951,879,239,608,430,81,704,3,746,913,389,384,658,736,9,493,13,817,965,63,621,112,667,987,696,227,32,150,165,501,912,850,448,305,173,679,210,727,299,814,975,254,380,287,554,281,402,232,374,467,451,5,21,982,310,85,950,342,55,483,449,810,147,875,691,89,605,510,379,744,781,210,870,973,225,546,98,236,95,998,524,793,88,916,527,406,362,165,762,943,294,451,81,2,688,880,330,582,892,961,96,438,8,33,357,808,683,902,336,403,99,742,448,637,846,591,557,726,270,802,412,808,650,509,222,104,335,655,596,185,554,88,773,388,309,819,418,85,160,124,480,966,244,375,434,776,82,233,489,471,1,351,138,477,469,367,393,357,388,495,415,376,686,231,478,922,115,179,110,960,408,856,616,992,215,889,169,949,425,300,524,51,980,376,615,153,492,896,631,275,86,847,565,749,746,870,452,994,907,718,906,554,8,587,301,900,633,977,595,474,337,300,600,590,855,70,399,483,106,699,387,839,817,898,846,754,802,498,740,84,620,37,742,707,28,804,520,110,793,581,777,784,607,904,742,388,135,942,579,319,609,550,725,435,344,826,521,120,758,669,281,791,627,198,781,926,764,442,613,482,889,755,561,358,897,633,468,687,998,550,693,618,244,510,945,537,986,270,229,558,634,796,817,298,757,395,332,55,428,775,69,976,795,880,676,861,13,822,452,660,336,153,657,717,702,178,524,657,791,156,124,89,968,172,34,780,259,751,43,630,393,492,522,513,188,239,690,847,81,305,804,468,55,443,34,849,174,880,334,329,704,335,707,436,691,241,306,549,270,851,998,339,504,691,876,98,666,454,81,81,490,69,690,132,433,2,158,651,307,285,44,162,779,690,77,372,204,309,873,833,458,66,160,924,405,395,709,759,517,330,36,423,558,435,485,315,75,853,148,122,417,12,190,23,166,200,269,932,836,920,611,409,654,310,342,596,309,60,493,327,682,318,230,493,435,607,694,98,717,708,398,344,585,662,720,557,771,687,961,695,136,179,380,758,974,909,776,935,5,0,816,427,579,357,939,840,280,334,814,500,365,313,350,208,747,760,600,592,813,169,351,388,42,664,261,522,273,888,156,409,607,666,449,649,771,970,509,138,950,4,60,452,470,675,617,519,873,370,893,915,908,805,433,186,761,531,411,745,375,339,109,422,575,458,999,343,369,817,897,11,193,631,590,313,323,855,629,645,247,946,102,107,351,533,875,524,663,841,826,235,56,875,874,222,334,860,346,118,154,138,821,636,222,402,923,391,928,578,265,890,306,18,247,484,852,308,124,550,908,949,801,26,970,737,625,731,191,698,709,463,656,37,642,201,358,847,456,231,982,352,986,161,44,664,301,363,889,148,258,502,762,139,864,817,399,697,301,324,799,477,453,904,148,809,743,543,832,578,604,229,556,350,604,190,42,365,123,3,644,139,160,578,782,491,561,559,276,515,725,693,915,829,218,671,257,742,395,388,92,710,94,178,773,433,30,540,898,636,327,371,45,37,917,221,98,172,739,373,802,763,696,460,788,328,929,287,235,7,904,919,847,588,254,212,435,463,827,292,594,345,859,433,101,856,778,754,502,229,904,475,548,395,559,381,81,245,743,751,691,964,578,644,253,609,381,299,969,125,331,391,448", + "634,362,739,379,391,123,933,134,839,440,571,717,280,674,702,742,171,513,260,352,515,614,258,278,1000,835,892,448,674,457,397,518,878,982,865,593,968,511,364,80,935,988,928,560,446,250,100,424,363,249,932,139,376,267,565,953,225,613,855,527,570,576,929,319,269,967,426,485,720,299,940,484,233,49,260,947,747,656,701,103,476,894,446,911,509,818,263,499,836,461,946,362,434,498,103,126,608,628,10,560,888,248,626,50,339,45,900,839,766,47,69,171,140,512,755,575,63,64,918,652,221,813,903,433,331,181,336,884,588,991,369,157,997,364,985,148,680,982,438,427,648,996,356,363,815,23,796,263,840,679,747,784,455,400,233,777,268,216,856,790,768,141,943,649,652,705,564,255,345,759,966,603,514,163,194,646,575,172,228,635,563,249,609,844,926,765,889,243,647,462,585,740,962,399,676,444,658,293,803,716,993,611,118,264,30,183,825,466,131,371,919,312,406,853,272,983,21,12,251,666,256,9,607,231,987,609,468,722,772,172,401,187,88,350,853,641,327,525,364,431,383,110,893,989,148,493,752,188,268,514,890,982,112,220,920,890,618,427,925,630,192,848,495,160,995,551,151,761,678,636,341,129,548,898,214,903,884,944,447,632,268,165,633,50,35,458,404,467,743,12,357,391,239,730,991,340,500,922,548,418,691,261,580,482,200,527,130,540,806,183,110,409,284,940,475,991,682,852,364,159,665,476,472,379,853,563,411,88,588,79,30,875,730,786,67,240,741,210,90,330,852,956,896,36,618,905,117,334,644,687,717,849,978,905,660,191,801,972,216,441,832,332,930,652,894,678,458,328,971,159,87,813,25,296,935,483,85,27,601,211,754,464,136,805,541,518,214,233,796,992,496,796,247,686,873,164,672,778,475,606,883,905,530,879,704,501,259,819,664,505,835,531,52,980,161,845,939,918,605,669,610,684,742,197,982,343,388,21,11,196,915,766,522,207,780,954,901,133,30,484,181,929,614,452,714,404,964,218,408,989,710,454,141,561,357,614,994,89,935,596,954,453,324,671,579,252,986,651,404,666,586,302,922,188,174,593,239,888,170,551,129,883,380,444,836,250,832,206,825,952,131,604,46,445,648,74,29,632,778,113,552,107,281,400,561,478,307,524,64,708,962,679,472,807,339,839,967,655,253,361,524,133,379,738,5,969,997,272,339,207,355,694,310,206,389,852,532,430,504,419,212,417,832,760,325,675,693,233,535,803,24,337,865,30,406,421,46,166,984,328,551,734,935,5,727,867,804,730,241,977,737,497,515,448,485,631,794,205,28,513,658,981,864,544,94,944,83,362,707,102,943,49,944,354,46,508,375,419,350,678,450,110,752,998,539,816,953,160,534,668,387,21,371,888,910,518,890,430,887,275,342,747,159,839,912,134,546,836,687,933,552,991,765,323,968,826,556,83,280,233,610,112,369,286,739,870,350,604,318,514,346,928,891,179,971,542,846,881,416,152,917,493,603,636,96,555,985,582,930,896,448,114,612,23,356,515,662,697,312,680,517,36,597,866,208,442,470,561,659,734,419,924,717,158,838,522,533,517,9,3,842,455,990,727,675,414,475,37,321,760,818,40,82,750,575,209,366,144,661,912,920,532,552,128,662,647,909,696,816,0,306,373,928,242,359,726,758,301,248,749,562,883,145,13,46,875,785,896,533,374,310,702,855,698,711,593,554,183,815,920,106,44,393,184,609,482,148,271,3,550,609,713,42,812,289,581,634,715,924,548,135,587,930,486,810,610,1,283,590,830,413,871,986,896,907,961,644,160,92,503,368,993,399,424,456,169,330,575,113,70,252,779,806,858,963,303,659,247,943,868,980,787,167,532,522,590,530,150,183,882,265,103,99,189,565,35,685,941,186,888,288,658,878,927,803,208,630,751,57,994,589,383,110,257,155,54,889,776,439,995,708,898,580,697,289,264,125,402,84,203,322,272,199,64,226,7,881,43,215,581,361,671,370,401,845,483,152,336,50,696,525,975,652,185,443,211,60,419,801,339,620,680,615,785,922,337,892,510,595,483,452,322,704,519,690,168,798,506,725,98,955,325,212,658,392,834,457,421,350,900,780,261,770,209,133,741,306,366,482,91,159,315,704,523,58,67,284,548,820,718,804,205,785,870,603,875,76,360,358,103,29,144,525,720,3,875,911,620,590,843,669,50,794,507,831,129,669,95,201,746,865,787,162,884,376,633,823,783,464,62,361,873,689,884,178,192,771,401,228,237", + "63,421,464,201,594,445,398,895,508,609,800,737,94,972,373,931,234,368,989,873,580,302,568,129,658,588,133,193,538,22,452,451,777,218,949,385,860,911,381,415,813,244,550,649,408,916,575,590,302,99,143,261,30,69,851,953,521,709,213,717,860,210,456,450,554,606,927,548,142,895,846,997,879,616,759,916,237,341,221,369,131,252,712,953,295,441,381,926,907,59,691,404,351,25,468,705,885,547,572,104,593,712,595,326,82,361,692,774,170,179,878,74,412,908,546,449,261,621,707,620,927,286,933,633,200,637,383,136,359,474,364,918,831,761,949,52,220,881,265,684,951,737,936,653,848,344,427,369,45,317,279,760,428,758,705,820,639,317,317,612,188,702,379,527,891,66,89,764,400,802,963,343,383,534,565,338,438,766,748,484,675,593,302,191,290,153,13,686,504,572,521,437,109,199,205,442,575,269,854,780,904,657,897,624,48,744,691,988,468,86,641,555,394,872,355,197,959,767,749,265,594,150,445,368,109,384,784,852,685,83,190,891,620,72,8,87,209,935,773,270,595,822,221,219,342,320,339,754,638,411,301,392,975,809,289,402,572,547,632,853,830,433,680,899,342,344,556,54,900,898,183,316,569,645,512,201,172,546,508,791,389,587,272,454,182,616,690,967,345,947,143,162,643,725,958,435,639,917,754,340,522,37,740,791,121,36,332,45,698,183,25,948,264,778,36,272,931,424,825,875,776,732,665,68,769,332,721,866,692,28,260,142,283,574,846,334,787,39,271,466,939,468,480,22,447,266,190,501,576,148,275,144,192,267,379,261,538,593,742,60,980,954,840,201,252,689,270,835,400,674,811,808,706,856,849,223,874,37,992,681,726,771,413,663,58,635,121,573,542,510,995,485,134,597,419,101,584,163,505,146,846,559,777,140,514,397,545,277,770,441,116,799,94,506,826,305,456,718,501,492,824,728,47,39,483,181,529,3,487,500,949,47,966,236,945,397,850,45,674,426,569,341,292,478,154,920,960,332,532,321,348,379,586,789,155,321,372,793,285,617,972,105,559,688,365,760,941,633,218,208,91,552,385,329,88,411,892,437,458,29,911,599,310,13,133,896,973,579,810,821,659,454,341,213,439,922,257,469,873,627,602,161,661,901,277,238,233,776,343,699,962,186,474,164,821,46,832,614,944,445,574,928,25,920,203,556,684,832,599,795,272,508,773,396,168,560,474,877,809,456,298,572,465,736,23,971,162,374,710,335,17,393,286,730,772,266,327,619,138,215,236,656,3,776,832,868,639,539,167,79,416,572,400,982,239,631,389,544,396,270,646,411,13,70,441,450,13,687,198,66,426,258,794,4,273,273,874,165,375,973,489,275,731,158,710,592,668,947,181,211,183,764,614,932,75,952,495,746,258,110,663,158,602,698,829,139,748,30,876,42,895,679,300,230,964,4,126,510,562,258,418,978,118,289,823,931,440,852,179,266,488,77,48,672,433,512,228,227,341,425,643,130,25,762,752,300,256,445,161,69,853,3,137,68,447,234,172,645,237,389,990,647,704,840,436,230,754,606,644,463,51,246,607,11,314,734,596,447,503,123,898,460,241,622,92,606,175,778,163,774,337,586,448,755,190,106,474,421,496,805,213,473,732,642,159,685,571,262,427,306,0,97,940,927,274,649,74,737,157,817,585,106,801,981,79,652,720,524,140,374,875,558,815,4,39,343,182,91,463,570,549,459,927,323,885,764,795,983,802,225,238,209,500,555,794,887,707,350,446,45,895,843,41,912,498,248,879,854,13,616,753,476,176,111,579,244,881,930,137,831,460,697,332,573,917,448,662,662,264,605,988,693,522,679,20,754,675,952,632,557,461,657,64,867,425,41,175,155,116,569,35,982,750,833,552,137,723,354,220,988,899,588,768,877,574,152,649,604,651,464,503,568,189,706,875,172,371,104,656,603,541,97,415,579,682,755,966,352,709,24,529,157,950,78,948,929,699,291,389,988,971,231,888,186,431,557,807,836,146,574,738,446,387,214,287,150,393,670,931,29,639,372,815,984,691,3,87,288,471,841,898,411,727,573,45,547,179,533,607,61,295,816,327,635,666,389,827,416,17,938,510,786,638,482,909,83,42,465,43,166,20,248,237,89,758,832,570,905,961,833,457,25,94,884,298,556,326,907,383,614,582,114,117,754,761,704,110,591,215,948,177,744,688,461,279,838,427,256,790,918,407,734,259,511,458,656,300,438,993,607,59,771,6,551,854,903,585,816,243,566", + "164,304,67,693,274,105,893,452,660,216,623,217,470,675,982,51,213,587,829,895,556,228,258,694,418,201,501,349,774,479,800,96,524,381,567,794,647,890,81,476,420,76,664,489,27,81,610,782,356,117,856,752,684,582,345,320,511,588,342,731,521,370,62,282,495,832,14,184,245,54,515,485,86,656,546,151,801,969,350,935,218,882,762,410,816,815,993,528,552,248,602,378,425,433,160,853,699,380,343,149,905,168,41,750,943,681,404,321,823,891,984,481,939,496,831,168,322,880,652,3,409,664,892,681,710,35,72,473,776,893,851,442,290,130,664,82,351,308,435,340,49,657,642,399,247,22,296,118,35,231,132,967,4,475,516,625,111,674,674,63,5,986,208,298,514,952,945,533,688,551,860,429,681,874,676,85,352,430,91,15,779,35,321,397,139,194,316,175,620,919,480,679,779,215,104,608,538,16,753,8,630,717,461,544,665,595,52,80,862,691,545,939,436,137,220,789,384,672,516,61,633,850,791,790,581,328,972,157,124,890,540,285,823,729,599,620,720,253,307,889,668,607,991,262,940,116,810,210,364,904,900,985,900,766,293,459,741,456,990,104,273,880,212,925,387,200,563,617,341,112,907,437,775,627,933,479,724,252,135,564,209,181,126,529,431,565,601,402,165,826,70,810,856,385,325,112,55,703,747,553,819,970,229,536,35,715,402,380,891,244,170,621,793,423,82,844,166,321,809,261,925,25,368,8,558,703,222,70,660,447,882,615,830,662,464,261,242,316,749,173,91,191,757,357,205,722,582,17,24,191,629,823,678,86,851,417,5,826,333,674,871,140,889,202,430,659,896,662,321,762,680,691,759,156,735,669,42,295,889,795,48,559,375,509,693,473,865,393,235,891,853,168,898,444,94,131,243,759,434,302,650,116,746,591,653,184,78,30,524,903,848,464,850,786,224,88,96,146,172,491,626,819,71,353,151,740,138,197,171,803,938,3,615,250,33,869,335,241,522,967,225,326,942,137,294,485,985,671,655,36,403,50,219,754,467,84,891,549,686,805,520,900,749,599,269,98,980,470,43,424,973,88,212,427,674,493,87,628,165,783,570,727,515,547,972,16,994,973,283,17,469,62,823,653,537,17,131,297,669,357,109,632,492,888,827,324,701,329,616,854,382,609,645,163,79,144,405,864,166,988,800,73,210,494,319,481,401,260,221,407,246,196,496,405,238,611,858,172,978,769,763,32,664,341,101,408,567,427,11,106,216,304,794,904,39,56,389,243,569,170,728,835,707,863,347,250,580,909,700,679,149,729,318,933,214,960,422,134,723,637,364,777,534,627,378,892,528,285,829,966,351,962,367,774,675,52,864,277,959,719,623,142,498,990,331,784,137,277,269,201,295,716,804,349,607,745,366,459,754,821,664,985,404,114,544,120,727,922,337,263,468,157,371,339,47,265,22,317,880,55,290,64,226,201,488,609,781,157,468,607,422,989,77,165,140,26,134,895,734,797,139,835,545,473,327,26,560,968,974,847,293,876,766,613,8,114,931,75,54,384,567,622,339,362,148,166,76,591,83,578,710,76,422,369,251,903,755,864,275,450,284,339,469,936,927,269,63,100,517,26,796,342,302,79,477,13,634,274,774,945,331,184,238,105,444,703,156,580,579,373,97,0,424,336,129,488,311,645,442,401,287,692,13,605,951,225,793,929,760,610,718,604,247,323,304,682,132,518,542,49,856,752,651,493,553,185,587,752,52,758,612,140,480,744,502,808,354,48,544,553,358,455,958,614,306,595,768,155,875,767,344,719,450,852,833,508,986,274,921,346,577,648,54,576,219,556,490,475,549,656,317,217,657,379,940,153,249,598,338,4,283,721,726,867,502,182,746,615,63,540,859,993,904,233,487,136,508,364,526,498,298,307,402,521,910,199,760,868,678,633,308,281,405,479,909,948,634,559,543,950,412,608,571,190,20,567,788,878,143,419,271,202,432,290,371,515,597,287,958,621,433,663,700,647,825,744,377,980,376,780,467,378,336,159,184,175,954,109,176,78,204,740,588,181,76,411,549,832,305,340,437,323,778,362,370,598,26,948,634,694,960,387,963,952,206,410,209,835,432,227,495,801,25,501,322,780,526,647,155,881,833,911,217,967,316,540,548,627,931,838,362,396,8,440,751,773,702,903,25,635,358,776,326,525,292,721,599,170,518,452,685,456,530,756,599,295,222,480,995,973,824,151,967,701,580,846,42,357,822,731,310,64,923,10,427,187,131,877,764,79", + "849,621,62,135,263,454,140,801,484,533,681,264,748,589,78,616,130,190,725,277,593,869,673,70,241,324,264,544,872,248,574,689,15,400,325,855,926,393,423,535,190,563,354,230,571,325,44,864,309,784,745,148,817,630,869,120,262,474,499,112,187,214,950,695,808,656,456,933,160,748,616,711,220,404,444,816,689,962,813,953,806,324,855,215,765,545,385,280,399,140,971,894,671,710,77,792,987,927,107,495,290,789,164,494,681,477,137,117,345,745,900,117,971,26,357,173,102,683,469,758,725,150,550,56,870,304,334,427,814,819,269,688,17,287,890,792,693,119,783,276,55,835,878,266,677,57,680,639,195,517,486,54,884,263,399,907,229,18,44,765,183,237,5,998,979,281,470,18,90,977,701,852,551,547,103,183,271,64,880,590,100,555,846,168,681,712,866,31,744,23,919,510,482,341,6,862,85,796,423,446,892,647,629,787,167,63,835,37,610,277,467,648,852,103,381,108,542,213,33,344,565,408,379,821,516,441,232,14,840,404,724,397,492,483,973,946,219,434,215,611,137,115,527,300,124,845,254,908,598,856,700,615,465,852,118,142,874,960,937,614,782,933,983,838,793,492,185,181,151,477,778,438,592,115,220,778,475,127,249,153,799,215,202,814,838,634,867,904,172,848,126,98,865,202,996,25,334,883,782,251,362,497,421,196,490,868,714,422,857,624,709,293,861,781,962,511,682,955,57,10,113,196,887,189,416,499,629,863,392,309,108,801,487,407,877,92,232,483,91,268,582,890,454,236,949,146,681,942,803,775,934,92,915,833,86,675,627,401,10,925,619,498,668,961,531,457,931,887,272,837,495,533,409,316,161,392,675,106,516,426,837,939,761,974,927,752,110,419,420,984,818,56,961,94,392,708,453,994,328,304,322,866,336,442,334,189,60,331,329,552,712,989,359,380,708,731,859,238,16,7,16,236,681,443,297,829,331,92,655,367,612,465,795,568,609,294,455,85,29,535,249,251,232,561,920,762,325,299,948,378,810,888,596,273,655,630,100,676,428,534,238,193,667,721,679,979,666,333,844,904,933,912,328,416,480,642,412,400,470,338,297,322,785,691,519,225,440,144,814,634,987,13,225,828,676,920,279,527,592,803,731,164,224,344,47,85,240,658,895,247,351,20,342,51,246,584,888,538,639,823,685,704,950,454,938,265,218,42,651,171,925,632,557,348,214,729,703,31,414,372,182,484,99,294,174,810,676,232,460,916,387,788,39,791,577,673,880,246,697,114,913,277,880,748,721,914,898,117,447,816,325,628,848,130,327,394,49,555,198,138,426,204,231,373,979,129,200,496,104,105,845,507,60,525,193,840,199,958,641,517,45,411,134,25,470,649,289,736,572,578,585,553,418,936,20,817,876,724,975,102,893,467,83,273,646,102,902,190,946,888,608,853,954,671,898,542,658,787,773,524,716,766,222,596,469,160,673,13,803,137,840,115,316,315,55,997,574,818,264,908,134,399,691,742,915,549,389,646,520,945,529,744,875,811,509,7,16,151,789,222,251,453,298,614,878,248,224,951,452,802,143,864,398,205,773,780,823,383,428,309,10,685,711,834,535,157,403,15,736,474,298,953,122,912,680,694,375,898,839,792,156,540,399,959,815,364,680,105,357,928,940,424,0,809,715,452,980,398,724,819,810,647,7,426,945,909,36,376,15,784,778,761,688,126,298,119,984,231,95,580,828,455,580,814,52,447,811,193,598,523,515,304,211,151,632,762,279,251,594,903,998,89,955,608,298,568,904,463,820,132,506,539,748,690,15,24,380,929,405,596,774,715,945,796,232,816,157,271,642,996,915,389,676,609,462,940,701,958,485,432,391,103,239,591,523,589,466,676,788,65,96,155,595,891,110,156,700,890,401,500,236,610,807,619,577,379,849,943,828,377,977,262,855,864,204,214,889,841,171,411,216,387,617,894,564,409,703,978,302,264,200,652,371,74,99,292,955,456,774,805,284,278,699,919,772,271,677,664,924,890,606,827,512,648,555,466,447,293,35,899,54,944,556,882,758,228,755,342,120,828,790,158,309,919,373,714,845,958,877,32,724,505,703,156,128,756,675,288,707,861,321,774,612,573,165,112,729,985,801,422,481,94,248,327,328,540,394,312,794,725,276,980,215,669,785,379,746,333,234,591,638,306,491,431,424,624,264,867,439,905,715,790,529,736,972,188,319,151,581,165,17,832,381,210,214,651,450,48,83,466,472,911,750,554,989,623,322,690,974,243", + "736,582,396,814,372,944,264,450,209,183,54,74,787,526,871,870,853,15,669,112,767,555,888,903,507,586,641,162,391,229,16,541,207,146,433,464,333,857,406,585,890,391,345,136,305,891,723,341,839,352,267,178,631,409,16,907,41,520,280,32,685,143,225,422,584,71,958,545,283,228,170,800,837,822,981,305,102,39,491,274,641,204,490,54,630,926,220,996,908,314,845,587,679,736,476,618,414,374,532,591,739,713,240,667,766,132,693,745,583,664,622,552,556,771,555,182,285,920,721,555,870,175,608,361,895,918,657,620,947,203,254,224,475,357,415,67,185,693,457,513,234,359,939,49,442,856,488,186,303,103,705,891,325,860,833,602,470,680,619,343,449,269,956,948,688,133,696,620,972,841,752,236,469,181,940,232,88,992,613,183,633,569,677,20,494,146,475,145,603,534,315,98,985,279,444,679,197,66,636,75,642,276,256,731,192,886,707,147,220,832,320,28,270,174,629,138,203,674,828,703,588,613,810,448,406,311,991,608,259,154,378,94,265,591,932,549,343,365,131,656,175,109,507,827,662,285,631,978,718,94,411,452,775,408,843,818,582,822,401,462,263,50,47,329,535,462,935,389,796,902,959,806,619,484,12,193,364,953,382,355,327,935,109,353,840,575,226,288,754,406,810,109,748,9,104,96,723,224,321,307,928,247,198,799,672,867,690,545,646,856,44,766,382,817,594,308,734,835,48,491,819,12,786,989,467,980,42,142,413,875,704,349,675,433,612,30,485,946,17,821,714,662,803,470,605,22,497,67,181,859,678,313,422,541,952,301,816,291,70,572,427,692,327,549,786,543,268,304,172,465,349,980,342,203,258,56,876,330,408,646,222,290,454,164,232,778,675,461,171,466,6,840,363,659,797,457,386,173,691,366,215,116,11,937,287,548,731,789,432,958,535,577,330,492,664,865,324,118,927,437,947,836,718,979,931,911,114,881,691,469,93,603,398,735,595,519,192,593,821,652,217,868,153,309,672,681,49,2,286,94,789,429,141,951,689,615,161,681,306,713,480,940,766,718,196,626,663,251,494,866,90,72,906,834,960,45,683,778,390,512,189,912,171,626,579,82,274,667,126,90,257,563,800,968,327,178,10,552,435,38,454,301,7,774,440,742,51,938,573,288,390,142,79,376,168,507,252,406,512,816,505,594,430,33,779,910,131,533,540,289,882,928,477,556,74,447,205,742,152,922,655,933,998,760,970,438,683,248,810,729,427,44,162,435,343,568,723,314,848,625,216,512,992,204,861,825,693,315,58,713,679,969,804,797,617,404,979,73,192,124,220,901,667,783,153,846,200,415,551,631,419,447,894,555,966,226,972,239,454,391,324,604,22,595,930,544,985,302,207,791,831,143,607,822,151,115,656,24,541,473,585,641,277,124,238,941,762,69,578,468,466,229,938,745,437,478,870,508,676,371,92,719,137,62,810,507,939,788,339,235,897,995,595,307,885,602,905,457,724,42,722,37,147,988,919,206,167,268,412,517,943,138,220,536,724,784,583,193,534,840,739,729,338,30,639,971,945,545,871,633,695,415,937,663,668,239,746,795,222,27,340,491,195,177,186,276,806,830,824,257,803,236,408,717,914,278,401,102,192,67,139,237,642,425,681,449,901,97,939,242,927,336,809,0,391,387,936,812,352,636,792,59,619,110,52,462,101,491,844,830,792,30,403,893,711,762,648,277,479,533,920,946,891,781,852,576,861,483,21,88,236,721,772,529,217,510,855,256,225,455,719,138,251,544,728,608,625,80,194,638,881,812,874,214,935,163,586,3,641,149,69,596,364,272,92,183,429,238,371,453,684,789,915,59,101,649,639,269,584,825,938,495,180,303,220,611,393,398,181,105,311,679,934,352,112,67,934,948,131,878,397,442,915,561,878,233,755,779,384,460,429,204,406,112,469,137,168,124,315,486,251,542,352,22,661,527,828,776,299,950,539,602,872,594,633,111,77,131,98,736,379,730,915,292,186,93,496,61,705,334,980,880,316,825,610,891,951,901,287,971,389,443,35,688,348,684,247,742,949,406,357,698,258,825,983,160,181,916,760,89,429,580,946,654,819,560,994,153,630,23,398,543,953,692,109,110,356,383,259,801,897,943,824,369,617,367,74,914,87,851,318,936,900,333,890,916,269,936,177,301,684,615,546,359,431,393,89,909,142,874,244,362,387,938,63,511,105,453,849,488,772,588,326,894,789,264,721,485,820,702,320,261,315,861,67,648,326,293,824,198", + "283,439,530,498,648,221,674,650,615,313,818,141,839,831,815,371,720,531,420,52,678,613,120,169,577,504,961,501,950,742,647,834,323,410,848,697,659,991,797,637,159,456,668,837,801,145,451,461,276,564,250,211,814,410,935,857,853,463,833,137,566,408,86,620,724,752,152,597,390,104,242,418,336,658,490,229,862,814,238,604,410,727,64,598,605,962,413,736,777,734,846,690,867,477,977,553,744,90,422,951,848,11,297,70,174,375,816,300,600,829,950,409,944,27,474,369,582,385,297,454,659,687,730,626,473,890,598,340,747,844,549,569,502,432,425,533,781,56,515,184,208,305,766,209,125,917,978,428,514,319,113,57,944,774,415,779,539,458,767,796,670,701,641,459,114,910,589,995,18,23,187,244,499,822,590,815,928,234,471,678,379,588,805,345,544,501,301,764,927,464,545,252,661,606,64,763,506,340,661,37,448,729,533,465,78,3,272,662,330,353,452,364,266,637,931,97,119,379,27,560,221,276,216,894,96,336,501,964,516,986,940,85,97,11,862,862,367,562,810,377,198,998,316,829,833,231,996,104,563,48,312,526,387,325,900,350,258,630,162,363,767,275,723,266,455,224,343,315,183,930,279,86,41,365,872,807,953,839,6,438,709,649,791,788,561,896,82,958,247,987,534,289,415,118,578,772,542,129,483,967,12,426,833,853,94,404,780,376,233,542,881,912,925,283,759,921,284,197,518,97,59,539,698,23,318,894,767,403,355,498,650,244,388,679,222,499,205,149,262,634,97,300,973,333,619,758,74,65,673,286,251,242,812,837,566,209,959,747,999,76,999,730,902,65,863,374,214,460,947,619,771,960,804,699,765,79,111,499,108,170,133,86,170,602,684,89,94,811,539,248,891,821,769,861,421,285,673,98,718,118,108,134,505,467,118,901,472,78,776,287,526,467,415,373,68,416,998,492,788,939,396,33,949,28,770,306,62,296,67,288,914,764,755,606,380,456,107,288,758,946,203,131,574,626,561,379,388,577,855,1,753,24,642,94,125,111,15,634,780,758,244,131,827,393,816,998,275,3,366,630,937,384,400,204,96,99,691,519,225,627,900,753,249,143,552,902,110,736,986,633,5,733,395,414,617,582,85,394,265,409,355,951,40,22,579,322,285,469,889,690,279,296,886,663,146,560,405,27,181,340,217,22,481,991,479,21,31,579,692,990,571,648,552,583,868,227,530,532,769,210,548,151,850,607,775,419,257,595,804,741,136,629,230,286,58,897,271,348,973,617,922,16,988,262,830,664,544,945,257,327,900,42,387,515,385,240,750,643,371,612,47,636,908,998,623,669,556,801,892,803,347,760,153,160,198,554,200,309,56,596,987,594,628,630,269,353,631,116,136,365,166,844,314,365,766,14,309,635,102,158,159,144,651,951,616,329,329,655,421,723,864,445,971,923,791,492,312,932,433,113,532,229,822,307,656,221,794,63,241,547,946,91,995,141,943,365,381,270,341,698,536,485,314,675,716,93,220,740,806,503,968,333,795,635,926,243,92,328,408,133,255,407,161,429,987,788,343,840,297,537,761,301,321,668,525,108,624,167,814,458,325,454,697,215,117,809,227,654,208,832,156,162,921,684,934,400,824,641,647,867,639,917,288,220,939,530,290,732,840,359,274,129,715,391,0,910,461,373,533,669,732,25,314,624,128,366,273,152,431,442,892,898,870,213,763,495,18,455,602,511,520,634,113,649,468,754,671,425,945,264,259,464,905,106,55,950,826,708,878,400,438,549,931,759,222,56,100,75,850,452,205,281,550,38,362,590,404,454,844,224,194,23,477,854,337,603,647,418,798,918,985,187,840,130,267,995,275,566,725,783,340,318,410,791,904,948,391,64,965,502,279,306,468,112,993,719,666,392,435,247,947,200,312,848,695,117,741,1000,823,393,702,221,702,414,955,951,379,354,281,501,110,171,293,766,587,723,82,743,569,394,29,33,285,887,524,493,465,213,619,244,257,813,716,742,764,140,879,154,485,899,668,244,434,436,737,196,400,30,764,252,505,694,965,614,85,457,894,874,980,971,314,799,883,465,721,114,51,688,328,289,621,933,993,397,651,754,459,41,608,103,754,670,605,748,711,222,996,198,271,356,753,617,579,164,609,25,114,955,821,502,38,437,527,281,242,421,967,246,346,503,278,853,210,854,670,799,628,699,312,228,913,712,362,188,575,753,932,204,874,51,246,33,306,993,458,399,930,578,988,767,753,552,47,275,807,663,546,252,348,831", + "210,825,888,358,593,249,221,953,649,400,365,954,117,542,48,140,811,971,896,805,268,712,282,849,112,173,187,501,53,79,611,978,137,727,737,626,78,155,514,767,191,582,734,970,96,790,593,186,804,804,421,878,712,971,682,686,246,928,59,199,201,892,821,610,631,692,967,205,126,816,693,425,308,165,946,92,779,639,63,921,762,565,427,225,360,810,909,507,708,801,92,844,217,500,554,93,910,71,749,499,455,928,612,106,126,357,110,603,587,562,490,829,930,542,507,862,138,723,82,867,611,992,30,478,671,75,182,565,148,40,744,107,357,840,713,818,771,945,170,575,581,584,771,424,417,905,200,976,232,292,294,392,331,410,579,678,395,617,986,994,541,925,403,960,609,171,732,127,967,980,540,638,760,155,198,209,709,239,374,447,262,609,203,813,198,337,683,10,512,91,304,100,52,595,322,512,699,749,677,865,892,229,199,684,587,664,103,250,647,899,123,553,942,779,540,828,840,28,695,509,652,945,300,461,149,703,999,741,397,537,632,616,340,588,730,798,870,579,830,250,726,959,222,237,310,422,703,826,698,443,414,432,484,337,992,425,260,646,710,990,782,620,33,676,588,364,192,820,671,585,469,55,557,668,164,854,377,820,40,179,863,49,770,675,428,461,501,919,261,980,767,99,975,827,504,427,585,397,346,183,526,367,628,19,486,664,919,81,203,253,639,548,185,190,71,850,941,753,113,938,127,609,502,899,703,517,381,174,870,225,404,443,25,675,147,676,438,230,237,434,713,446,764,273,263,111,360,956,512,471,967,672,377,622,776,651,644,253,210,248,816,383,755,462,216,209,10,831,341,744,545,562,886,964,994,22,857,460,959,419,782,237,248,91,159,236,672,308,4,711,582,615,646,475,843,227,649,122,225,659,775,217,178,530,808,539,733,454,487,820,11,721,236,409,169,452,95,976,493,198,199,107,894,560,525,581,687,682,596,119,126,351,586,83,381,884,11,287,253,512,616,629,816,275,326,473,604,297,864,90,542,430,12,56,745,689,78,540,654,838,474,973,697,819,220,940,418,23,356,901,453,994,934,202,330,2,848,774,604,17,279,336,473,113,266,384,306,783,36,815,246,883,808,712,812,905,568,618,481,384,547,490,490,534,714,303,716,933,400,544,856,557,796,494,208,947,473,499,840,721,57,600,47,295,346,716,987,116,66,720,143,984,721,27,651,397,4,685,189,183,162,945,936,375,408,715,980,373,964,114,835,287,626,387,527,589,315,853,68,231,167,914,534,545,382,550,526,329,793,130,7,315,841,294,665,994,13,359,931,114,583,744,332,528,699,879,160,737,800,934,690,398,317,608,171,154,320,668,228,990,331,26,710,31,893,841,703,538,475,868,771,527,455,512,527,386,850,787,15,292,655,56,23,627,523,911,329,455,822,384,991,545,550,509,128,9,235,920,879,984,85,632,941,972,17,921,940,37,70,987,874,254,256,701,753,362,750,666,779,336,584,928,138,667,896,86,174,613,872,146,947,324,529,656,767,875,377,846,626,783,79,120,378,697,47,469,564,400,265,194,594,218,226,722,792,152,105,47,450,593,472,503,355,469,340,779,234,605,18,536,896,199,556,665,472,622,520,104,344,330,317,659,804,407,476,506,975,754,280,726,649,488,452,387,910,0,281,157,635,504,853,384,882,791,135,427,123,232,204,66,812,867,522,621,155,757,269,700,151,410,398,889,407,862,978,899,374,488,132,942,120,257,234,388,67,328,248,211,861,120,371,830,712,849,122,383,773,585,664,783,564,153,796,901,597,272,359,317,806,8,788,480,260,530,118,990,413,684,362,708,836,149,971,998,353,656,548,529,185,745,94,47,949,393,110,50,756,375,747,756,873,494,414,573,908,437,234,797,165,293,203,936,575,726,556,879,103,690,11,363,198,778,358,284,142,35,40,987,389,665,628,940,536,550,712,454,632,931,775,889,678,724,969,392,729,971,778,307,235,514,413,524,219,742,355,388,330,671,313,865,634,231,307,805,825,43,674,80,64,670,687,997,396,672,269,124,401,654,982,714,280,425,311,344,231,85,10,185,903,100,967,529,885,95,881,805,653,466,248,503,302,942,617,831,315,726,633,623,742,91,369,127,569,648,221,934,315,305,231,566,760,464,623,147,349,633,931,401,230,995,793,901,217,321,945,797,290,909,591,282,518,966,777,119,673,769,552,213,966,821,313,239,515,596,710,31,244,984,843,328,956,235,412,846,846,3,263,28,404,761", + "5,45,346,847,792,131,426,13,202,726,675,99,404,226,809,900,519,729,948,200,834,531,341,217,343,426,836,511,127,351,125,520,127,359,276,268,41,770,441,41,254,644,718,738,546,621,853,149,111,718,733,120,704,501,753,994,510,177,920,129,882,555,435,181,952,873,890,247,630,247,349,599,63,437,875,426,814,882,147,862,834,908,504,235,437,724,200,707,142,513,118,555,337,558,418,879,474,321,790,982,635,506,488,712,205,292,486,212,33,459,996,454,264,75,803,211,781,159,164,69,111,661,928,931,107,184,997,815,996,661,438,48,64,569,518,452,399,280,514,94,585,154,486,236,70,513,445,359,810,782,355,318,729,782,929,969,919,988,326,469,545,914,402,488,551,777,213,304,800,926,826,705,251,929,759,705,610,173,845,459,18,891,799,567,385,757,949,687,328,936,74,708,394,959,462,599,379,485,677,532,155,986,411,362,46,377,173,4,826,990,638,499,590,27,419,958,28,693,821,551,866,528,172,907,497,889,857,576,892,182,759,452,493,913,727,521,707,828,572,54,159,429,617,940,794,412,767,541,24,828,448,659,692,167,856,212,724,793,814,362,62,830,171,885,283,876,209,738,707,542,964,664,150,338,59,36,968,621,266,716,767,712,174,832,56,654,108,927,966,814,109,479,804,912,659,860,155,839,986,332,913,18,593,119,36,173,699,186,854,709,660,533,530,751,87,817,856,543,545,353,853,202,824,280,568,845,157,866,301,760,100,790,463,492,755,736,143,879,819,940,967,858,886,681,945,278,955,919,89,310,952,623,236,97,766,533,449,862,817,275,598,874,128,301,70,106,998,631,694,693,555,643,243,174,434,487,530,690,198,899,599,775,714,424,125,941,824,802,442,970,69,485,918,316,315,132,994,717,192,608,775,729,638,888,683,446,84,985,773,32,728,744,660,775,83,690,79,651,875,313,842,728,882,373,442,884,747,670,287,854,462,651,112,647,289,147,826,149,966,879,160,477,12,347,768,781,548,213,977,387,343,968,112,573,864,557,71,348,869,20,596,515,767,691,353,407,474,439,109,869,876,100,770,94,949,712,730,975,602,540,620,721,726,32,496,991,374,803,482,263,236,874,748,627,409,721,269,787,392,57,1,761,113,27,684,419,794,110,506,686,72,933,922,863,145,528,14,604,524,477,107,305,711,986,985,342,630,602,90,168,856,631,181,520,437,29,585,150,286,225,64,979,905,707,541,974,429,875,84,66,542,560,759,882,658,658,980,58,110,821,960,377,636,628,404,463,579,768,407,78,177,52,15,844,902,767,464,961,987,203,431,862,307,442,277,940,255,598,614,573,44,795,929,494,684,537,540,918,356,478,721,940,575,429,172,565,671,259,5,942,359,354,79,149,848,738,519,106,150,368,890,221,640,76,221,943,408,774,42,292,411,275,971,3,946,530,490,705,973,694,913,348,44,787,403,576,118,102,228,248,168,819,952,924,193,939,953,617,522,638,556,964,441,89,119,567,603,352,753,116,267,650,416,291,357,596,343,258,282,404,959,863,217,200,965,388,430,506,481,241,803,66,944,61,903,61,441,778,816,84,366,747,645,879,498,102,296,902,324,845,245,876,96,743,784,808,185,371,804,169,55,647,913,575,731,210,542,413,334,758,74,311,980,936,461,281,0,123,968,381,206,969,391,977,916,490,685,396,488,359,242,383,867,699,259,388,576,332,597,209,640,434,449,372,436,663,171,818,429,719,251,772,230,920,863,653,115,178,410,780,31,500,724,243,805,266,306,191,959,510,294,448,223,963,386,14,858,393,703,585,369,209,177,640,710,630,692,296,817,989,771,930,7,606,269,952,101,148,187,65,338,760,171,215,688,175,680,854,575,420,234,810,723,896,164,25,249,255,803,122,637,429,197,151,907,66,246,385,305,355,400,129,878,82,465,627,746,920,51,691,588,805,743,916,203,350,171,230,279,745,656,129,984,30,845,736,498,973,659,236,400,119,110,986,630,500,974,670,117,802,741,106,702,888,62,20,944,841,689,777,969,536,702,694,125,550,903,520,159,93,975,380,100,312,789,465,188,72,843,661,553,270,838,890,629,18,307,597,433,255,707,621,279,361,365,560,614,7,542,595,687,589,132,651,744,452,378,570,622,67,489,333,812,806,253,964,910,921,322,922,568,443,560,817,900,1000,681,809,372,63,304,774,910,662,399,62,399,66,151,316,34,395,329,954,473,109,426,312,656,317,51,400,659,481,814,116,462,987,437,494", + "131,208,67,895,626,967,628,720,330,851,20,559,231,561,303,490,496,121,93,937,860,333,627,418,613,579,427,827,407,396,759,223,722,218,284,814,878,405,168,595,706,25,176,896,911,70,904,792,870,890,40,681,870,952,853,10,524,526,182,522,761,35,895,602,407,596,248,656,9,227,529,645,422,245,216,839,560,826,56,330,612,101,524,422,754,960,630,510,353,111,137,7,691,628,355,290,777,714,832,370,140,878,804,652,480,410,229,628,182,859,125,392,799,382,997,455,435,461,972,66,891,300,54,459,449,728,673,502,665,114,948,17,28,630,538,68,166,574,954,903,691,357,848,943,604,769,663,628,700,550,469,51,573,561,659,969,826,964,160,85,182,928,7,295,7,533,31,471,884,210,184,430,485,238,647,145,169,584,409,217,706,530,99,416,775,671,811,23,404,828,320,551,539,80,608,125,301,567,945,818,705,268,666,396,407,408,86,769,200,669,753,862,255,481,206,917,252,627,562,585,591,342,560,579,314,210,399,132,978,283,389,145,775,569,487,297,903,668,327,28,984,986,421,950,223,273,665,714,368,325,66,153,373,595,546,101,112,319,527,36,737,821,38,306,632,444,885,980,292,809,715,113,500,378,570,379,998,271,345,46,195,742,28,434,715,262,432,80,886,558,671,608,628,183,431,811,81,840,252,6,954,393,378,540,998,547,387,52,372,639,259,646,587,164,924,533,896,254,642,696,22,486,393,862,409,565,556,462,553,618,763,511,957,948,944,449,671,32,144,797,800,538,886,221,354,678,173,115,519,979,857,889,632,166,125,382,746,345,581,996,63,698,72,885,18,962,559,943,679,516,317,490,213,480,395,159,572,174,697,611,287,771,729,656,252,237,122,25,163,123,794,851,877,980,997,294,766,858,487,673,986,990,428,299,515,571,952,758,571,980,709,988,403,186,797,618,46,190,670,738,166,38,978,461,114,293,566,595,915,838,209,401,86,331,151,349,699,277,673,999,678,581,105,484,308,161,153,206,872,111,436,339,388,351,695,636,101,424,295,993,767,873,779,848,363,104,375,611,991,501,163,753,208,849,752,31,454,307,864,139,342,65,792,21,293,216,213,926,93,826,780,563,268,721,326,589,874,547,172,823,824,915,175,771,75,977,624,183,118,962,859,602,225,413,69,450,565,757,122,690,329,71,381,157,241,557,561,790,696,919,490,811,209,782,853,112,564,929,1000,391,518,22,389,457,686,698,766,553,69,105,749,466,638,75,839,159,282,562,614,977,186,429,831,997,130,161,99,690,225,992,141,362,753,836,391,485,268,79,453,218,376,974,868,902,253,911,21,754,569,47,514,112,442,255,141,551,130,278,190,323,716,188,372,134,834,169,289,394,896,261,868,647,332,860,91,13,134,317,672,767,60,522,144,253,771,4,176,732,393,599,901,96,836,405,460,736,479,916,545,502,883,259,317,95,596,261,169,771,609,232,20,247,205,660,410,431,791,56,952,600,288,206,335,104,999,291,439,449,92,442,396,473,28,619,640,341,119,6,586,753,880,744,660,494,343,234,262,931,186,451,65,344,937,525,152,500,627,582,419,570,893,88,920,687,207,690,76,49,299,277,769,690,644,659,201,366,392,257,46,97,855,879,56,132,69,382,975,378,814,301,737,645,398,812,373,157,123,0,807,406,263,205,826,509,393,724,621,312,164,183,3,350,168,532,122,765,522,519,190,2,665,533,804,282,6,291,271,998,461,957,498,663,371,712,819,242,178,226,983,583,718,498,633,829,77,101,807,916,186,632,384,211,429,698,659,957,734,581,172,408,832,46,755,261,118,466,330,734,42,174,313,373,184,961,181,476,311,710,966,481,340,882,458,421,903,684,459,751,742,805,82,821,46,660,556,754,704,926,884,408,383,686,220,853,104,366,711,70,385,831,404,125,218,557,62,972,950,185,579,747,479,252,963,488,174,872,266,57,64,61,675,752,791,796,703,465,622,585,932,738,395,514,695,866,198,678,704,400,238,272,797,158,583,566,303,87,475,559,572,586,422,240,938,655,304,296,389,480,228,692,707,522,411,903,896,733,457,276,557,521,986,306,577,27,766,636,769,470,291,538,573,548,574,457,228,89,701,176,121,60,164,297,504,639,742,724,831,328,382,320,243,691,776,842,211,702,281,51,726,449,584,106,176,380,651,759,547,361,837,536,626,640,765,431,986,620,795,875,384,764,415,155,986,954,708,197,570,541,883,417,973,890,233,355,2,189,345,113,172,12", + "117,249,264,906,755,433,639,726,118,599,981,36,260,954,293,456,62,769,572,568,70,938,168,665,827,620,287,837,734,522,656,554,63,920,809,595,497,690,51,837,415,626,800,559,474,577,580,489,734,781,854,47,738,780,680,527,219,300,554,978,293,921,426,927,870,468,564,583,321,579,744,744,107,377,767,625,666,146,230,462,828,783,124,754,668,933,466,113,390,217,967,7,326,981,3,627,813,130,94,883,971,108,326,600,572,819,249,125,918,991,440,943,270,651,277,204,473,875,746,384,161,609,923,276,955,683,458,325,398,444,986,196,25,337,22,663,851,572,260,172,535,830,853,463,619,12,152,140,367,28,996,736,965,134,648,952,624,302,467,476,628,958,535,59,290,533,296,593,638,64,623,573,862,622,866,923,82,958,194,945,138,481,378,260,331,372,680,594,2,344,505,881,926,107,525,209,787,648,848,473,151,123,843,691,166,173,751,799,131,503,267,264,417,719,597,264,809,644,361,66,915,959,252,383,433,540,757,959,738,968,848,836,855,86,874,287,580,601,526,499,779,378,829,886,187,166,420,186,228,664,180,748,842,335,962,497,291,48,270,932,702,667,307,31,254,19,920,155,540,729,816,522,14,229,1000,186,990,866,533,390,85,119,663,174,613,992,715,829,545,115,124,486,383,974,257,643,95,271,687,485,80,655,288,289,103,647,256,88,431,420,834,150,956,36,346,405,781,119,119,693,375,691,528,590,313,977,605,962,160,868,90,865,57,618,508,566,800,614,556,329,163,328,949,220,125,690,725,450,570,442,230,260,403,335,238,976,181,874,584,740,35,201,670,47,750,775,961,758,774,88,389,7,862,175,648,68,342,461,13,340,4,153,778,168,82,305,791,497,105,80,672,401,493,910,533,205,218,787,189,89,406,625,717,88,956,762,83,964,416,856,601,717,111,624,442,938,358,367,25,318,110,559,320,695,741,272,731,118,826,328,411,772,220,622,747,4,779,848,152,186,725,308,705,635,237,927,84,721,61,283,599,476,178,565,375,346,314,397,16,563,951,771,449,546,768,217,468,271,613,472,54,331,665,20,182,298,75,849,634,806,189,198,85,428,51,949,129,11,577,19,652,20,870,60,629,709,282,81,784,859,56,558,947,627,105,189,860,146,150,935,753,99,562,943,885,143,200,549,481,217,159,925,416,645,581,149,539,331,640,658,691,377,85,387,801,717,667,751,404,187,444,153,35,617,772,485,27,803,563,355,647,908,485,230,569,998,472,160,221,571,838,285,683,882,51,610,849,844,968,507,274,373,949,926,429,561,707,564,754,771,538,494,247,516,297,863,21,297,695,187,860,482,708,593,944,801,760,291,45,738,232,517,758,243,28,716,587,139,476,852,99,760,419,438,283,231,926,362,781,287,921,591,788,77,467,724,680,175,575,123,783,517,530,126,930,922,982,391,190,194,781,738,550,655,364,277,97,167,383,133,979,737,983,203,11,791,864,746,442,829,284,783,101,642,69,276,527,594,755,739,62,648,836,201,534,392,607,71,648,438,393,476,956,918,225,505,146,917,848,915,857,700,403,60,45,999,771,848,770,49,140,534,882,373,160,983,655,270,202,293,739,327,339,853,100,232,753,506,603,11,954,682,728,220,570,743,351,586,500,248,157,442,724,352,533,635,968,807,0,17,724,356,336,602,119,170,145,191,247,382,973,400,570,80,122,267,436,300,128,747,96,263,145,368,233,631,592,359,834,942,572,551,503,216,137,833,527,171,945,834,683,209,374,78,941,49,519,850,238,864,913,440,23,200,987,824,125,464,951,808,758,82,680,989,518,885,804,272,448,919,738,899,47,274,410,260,127,992,442,762,123,545,150,621,943,147,782,197,668,866,789,155,615,473,390,606,813,587,48,287,354,318,71,59,306,732,16,469,528,320,824,649,771,564,282,731,195,215,710,167,128,238,859,808,709,253,219,201,694,605,45,39,752,732,580,297,562,606,318,362,489,345,954,277,24,532,36,394,351,272,570,661,410,966,825,763,371,126,686,869,813,259,851,800,241,392,454,107,357,201,466,583,302,939,530,805,268,210,687,786,396,381,455,203,333,899,104,884,246,838,831,556,388,768,86,68,450,730,869,902,126,748,255,623,122,908,267,225,264,632,420,396,752,902,984,323,346,514,162,652,816,355,50,771,199,377,276,921,906,692,675,793,776,160,709,805,930,493,882,828,516,626,343,84,351,659,219,536,785,210,624,739,627,854,388,303,278,273,798,62", + "978,63,744,570,535,694,467,657,847,931,762,988,465,499,187,753,151,307,527,523,466,631,981,824,19,481,694,350,258,335,204,858,532,378,674,500,966,842,667,799,987,858,233,460,592,219,555,376,670,835,186,741,563,162,428,247,167,647,195,505,722,76,599,947,773,529,814,650,268,756,88,593,913,783,306,418,886,691,818,208,245,876,969,689,396,818,964,150,500,326,995,30,922,263,514,474,609,478,116,914,235,288,119,966,623,463,881,661,323,536,105,832,932,169,715,556,547,908,167,214,352,497,855,203,88,754,50,113,276,321,979,943,734,928,903,30,139,19,561,469,611,388,925,368,633,989,395,827,248,447,498,219,394,918,900,700,591,461,433,524,860,904,452,822,919,174,748,730,562,215,439,537,903,243,647,529,809,577,514,309,668,819,479,287,740,136,460,749,172,175,962,296,987,371,308,808,607,758,242,279,360,652,999,57,720,491,983,55,552,6,41,795,82,827,559,540,655,386,440,462,384,75,231,471,776,740,31,537,407,615,173,911,744,267,186,273,585,771,20,126,127,529,519,671,701,64,456,685,887,397,97,312,811,502,475,513,543,125,242,96,628,303,658,577,959,855,665,279,640,271,718,565,266,874,105,990,856,148,96,234,101,426,490,411,491,578,897,224,723,581,555,549,182,600,129,769,729,817,551,484,446,37,333,315,818,767,214,705,224,487,359,347,644,485,793,238,660,245,250,171,43,947,505,721,706,730,436,321,469,999,845,353,557,435,182,727,277,440,748,926,278,497,777,613,412,798,773,403,87,864,372,967,492,443,386,909,195,568,5,222,42,92,361,581,648,755,70,89,701,597,469,46,717,413,609,77,511,908,977,622,857,571,278,954,511,4,289,804,919,55,452,954,750,878,303,241,584,804,817,154,842,104,607,158,286,98,785,890,230,693,132,309,343,256,674,798,43,357,389,651,732,370,4,36,683,128,657,730,466,286,636,357,17,361,43,926,649,223,510,338,355,801,408,276,714,409,901,437,664,974,229,485,891,556,651,514,33,799,291,508,487,517,434,996,419,119,996,853,861,35,644,51,196,336,980,613,587,626,445,363,8,333,993,771,695,949,308,849,632,169,523,477,251,205,411,912,340,104,556,434,714,566,903,235,712,580,846,929,171,48,550,703,168,276,503,249,228,501,76,623,867,751,864,716,248,83,585,416,246,744,628,549,205,702,980,237,440,107,361,675,592,318,637,486,563,427,276,217,704,439,689,582,163,304,667,977,432,169,178,869,655,263,931,127,124,804,61,658,353,353,13,577,204,794,720,193,67,8,354,543,363,912,571,471,393,833,123,128,920,490,176,647,290,713,216,965,45,683,242,904,859,993,890,216,482,75,414,673,596,671,207,611,150,426,266,759,757,886,821,847,979,831,360,165,84,543,856,140,290,315,930,691,882,175,547,920,764,995,114,239,344,96,166,416,795,663,783,115,11,103,991,29,657,442,380,969,170,817,430,933,848,372,215,658,99,919,185,162,94,198,509,591,889,668,408,909,987,126,144,324,439,410,517,782,110,222,876,774,850,714,446,342,543,895,909,283,215,6,284,62,251,241,275,978,953,651,129,244,12,71,769,737,84,126,350,976,308,741,612,814,797,864,542,539,903,8,558,228,365,749,817,401,819,636,669,504,381,406,17,0,192,371,858,652,158,844,113,478,721,419,991,212,875,405,798,613,665,583,722,671,951,12,984,963,200,400,160,918,995,81,683,416,632,633,803,718,331,586,465,79,699,818,920,239,262,193,463,685,66,914,776,164,627,428,305,464,536,423,564,737,292,329,630,509,55,440,719,147,132,491,622,176,971,888,804,717,729,220,370,99,84,370,152,649,195,174,546,742,659,789,483,408,805,974,703,189,699,668,374,810,784,249,731,700,857,57,682,549,880,775,318,517,490,801,818,30,717,932,54,167,793,602,5,340,675,833,927,160,654,460,394,989,907,389,555,652,634,356,397,494,846,860,295,11,194,556,568,946,616,608,69,435,128,471,400,410,971,140,463,421,926,455,828,878,532,425,504,897,629,690,191,686,586,696,190,24,826,719,698,641,509,968,46,800,610,90,26,978,347,346,962,457,697,958,551,391,325,778,41,167,347,172,338,951,795,701,193,886,545,358,429,830,818,401,420,463,74,594,317,734,821,958,754,107,450,118,439,572,176,705,290,35,268,566,221,217,500,437,712,874,95,117,160,31,951,323,269,581,33,763,824,285,258,724,840,952,469,66,681,169", + "379,468,772,936,235,240,614,950,346,269,557,550,128,269,894,896,841,964,742,945,267,967,7,759,37,969,390,347,913,716,433,632,139,716,690,594,869,49,173,931,587,392,610,140,32,858,141,808,143,316,123,284,903,850,963,412,179,745,836,159,434,367,563,450,388,708,706,519,981,453,300,240,376,279,610,689,143,318,113,768,55,922,406,293,845,444,613,68,409,486,589,873,559,797,347,831,585,452,77,602,7,786,461,5,942,202,666,357,569,136,921,357,41,104,6,707,987,63,287,252,227,161,244,994,837,512,528,387,287,898,505,188,844,509,85,249,617,344,432,127,421,718,190,15,252,418,661,707,592,12,648,573,629,860,793,542,734,440,190,710,137,864,237,71,922,560,785,513,229,182,733,561,352,295,696,953,463,229,575,29,2,460,597,235,12,271,853,680,974,426,906,936,51,848,557,327,857,170,908,510,293,783,999,269,296,740,248,312,776,216,144,991,419,668,764,286,602,262,463,34,566,39,384,411,165,915,132,21,209,776,948,18,949,589,15,94,5,908,204,448,852,193,985,3,263,995,756,399,303,789,696,110,738,33,65,653,961,382,301,449,86,909,235,710,649,636,742,103,927,884,954,603,882,787,876,182,657,270,469,769,790,474,264,642,636,851,569,732,834,64,708,746,532,255,407,988,290,216,632,163,707,378,956,745,19,633,811,615,107,321,818,847,177,260,486,952,44,420,581,561,313,78,797,692,982,36,307,412,221,619,649,393,306,206,72,550,937,662,209,187,489,870,609,900,776,773,430,197,13,300,939,263,698,869,414,685,218,474,137,836,244,633,122,781,240,352,183,239,537,983,877,945,712,680,216,45,457,165,814,424,346,541,127,920,990,410,253,835,79,483,264,156,200,258,341,57,135,368,849,266,8,390,329,29,195,966,185,882,557,156,430,145,496,841,804,523,229,131,930,219,244,881,348,5,135,685,23,401,817,305,974,66,945,333,893,200,67,299,47,591,700,528,65,203,115,958,775,75,32,600,112,730,751,616,372,260,582,872,517,12,106,696,10,886,597,963,794,39,884,370,921,693,661,517,124,376,825,208,169,102,96,532,209,646,917,761,737,632,401,25,411,345,522,715,922,549,754,350,57,154,339,381,620,459,843,967,718,633,164,87,564,640,968,26,708,820,208,362,319,169,429,365,795,873,55,16,685,43,88,273,787,808,493,456,365,898,420,621,658,214,986,306,327,930,884,340,526,85,225,752,979,186,235,718,952,108,11,453,967,434,130,525,312,758,74,669,285,84,117,482,779,22,387,379,52,919,46,775,783,976,987,635,206,652,244,159,904,430,927,597,575,937,694,939,938,687,375,353,874,280,237,942,71,207,651,964,928,675,312,654,79,136,341,178,501,258,943,61,738,370,286,459,598,474,46,925,344,263,829,639,899,318,617,930,514,331,693,266,640,373,919,892,916,903,574,777,60,963,663,150,883,40,389,994,93,955,250,753,66,300,413,183,612,310,94,58,784,63,71,542,313,783,200,772,234,53,693,485,354,328,109,591,210,29,978,509,296,543,249,737,417,316,386,18,122,170,600,368,314,139,907,115,721,384,563,72,170,637,749,210,586,270,611,613,89,176,436,376,251,484,69,685,208,279,919,675,493,741,313,562,585,287,810,792,732,853,206,263,724,192,0,904,9,643,139,76,794,738,905,430,909,683,645,250,888,721,638,80,838,147,371,171,420,879,328,948,251,80,26,738,866,768,873,562,270,167,189,693,419,908,580,289,263,810,239,48,323,246,909,561,559,431,733,300,178,197,228,58,110,816,550,138,605,762,888,244,710,969,173,885,72,530,722,367,920,498,779,137,608,48,351,77,992,391,551,416,766,999,672,722,747,403,953,863,50,448,343,621,983,748,70,926,484,658,161,173,225,86,231,940,165,464,751,539,439,606,439,597,819,304,216,652,309,172,459,823,673,618,263,142,886,196,826,671,172,520,503,876,517,97,654,37,426,517,921,558,627,105,565,384,330,539,548,598,977,424,34,425,850,354,311,480,82,549,423,752,480,213,517,312,65,545,535,860,394,444,631,890,548,702,850,715,251,941,469,651,661,776,926,445,814,836,668,312,252,279,665,490,115,362,839,573,356,281,163,855,738,739,212,26,636,339,388,672,526,676,140,163,708,420,235,737,275,678,673,184,364,670,60,611,796,644,450,5,718,796,97,615,681,739,795,709,173,389,998,991,236,494,716,224,826,654,555,400,684,640,503,53,871,395", + "488,764,726,826,739,856,480,637,913,213,244,603,517,969,446,874,880,473,953,941,523,989,14,65,222,526,810,427,817,509,823,484,989,527,392,40,301,599,711,997,578,253,313,549,840,240,299,452,455,563,106,389,47,244,641,524,337,295,125,496,883,900,712,388,706,893,312,343,167,240,280,199,948,724,114,670,964,671,606,234,730,280,152,382,716,79,516,207,358,428,542,768,976,962,827,402,619,559,241,644,382,241,457,719,495,729,296,123,773,521,726,395,309,405,228,508,781,315,756,288,706,826,278,316,542,997,112,342,270,1000,609,140,272,888,621,216,258,700,795,695,5,120,995,81,774,284,998,122,592,967,30,890,129,365,474,732,555,763,286,569,302,470,245,578,456,251,324,931,230,150,853,985,31,567,956,401,669,797,77,361,80,564,723,634,257,116,851,896,821,998,89,767,713,294,682,358,952,191,326,422,808,846,450,851,624,372,858,358,582,693,254,278,349,394,569,460,158,770,712,805,942,274,667,774,986,2,198,544,124,886,370,935,406,3,780,913,289,655,145,146,371,485,516,77,905,663,443,165,156,479,548,299,418,566,826,744,473,189,766,286,51,195,684,495,137,609,989,978,314,343,613,117,220,545,228,147,973,966,298,978,225,578,778,883,273,43,561,932,321,965,112,927,671,493,441,255,767,872,114,609,221,192,947,460,268,113,591,296,306,975,487,836,195,461,878,454,519,159,481,311,579,989,510,298,259,662,611,945,431,632,263,787,61,737,116,912,207,539,210,789,493,366,139,266,675,441,890,20,393,870,958,672,516,784,547,563,422,189,699,133,42,60,359,944,609,818,155,872,89,355,7,888,586,134,865,13,506,383,540,234,998,531,585,486,704,361,902,333,252,498,825,86,254,603,835,333,191,916,989,488,931,909,711,238,469,439,643,369,884,27,604,65,681,266,492,449,937,471,690,981,213,362,949,95,894,650,693,779,545,716,694,967,90,360,206,35,228,814,750,557,46,303,689,40,323,85,731,241,663,918,507,91,325,788,87,291,673,759,870,65,851,472,287,259,53,293,215,880,488,903,276,102,350,975,929,339,642,661,455,188,831,313,177,926,205,373,160,672,411,954,556,383,647,236,94,624,823,476,516,335,967,892,5,107,914,797,556,603,154,777,40,673,632,572,210,144,780,689,727,341,213,481,650,889,100,356,220,392,185,457,152,31,179,857,12,712,874,156,684,876,636,100,113,515,114,106,999,950,230,703,777,403,598,969,556,137,904,174,261,489,576,137,797,522,660,619,923,66,316,146,721,38,502,323,517,799,758,226,956,940,330,509,551,54,405,801,320,146,584,838,824,339,153,297,984,385,557,701,672,141,172,40,772,588,954,431,774,40,903,554,35,536,820,749,692,579,837,992,607,102,258,917,293,679,411,247,421,595,798,826,57,476,269,995,419,614,927,424,526,459,174,305,27,860,9,876,921,2,887,357,112,253,882,591,335,50,863,461,257,308,41,481,731,689,916,211,138,536,892,68,708,199,417,465,276,589,302,272,168,384,9,927,709,218,169,150,581,526,318,965,2,728,275,281,602,417,616,972,66,953,779,202,270,372,643,453,167,878,272,333,589,874,807,255,582,292,483,488,117,826,174,356,192,348,260,260,984,152,350,883,106,692,647,59,25,384,969,205,356,371,904,0,970,457,205,774,60,826,819,140,949,879,388,870,390,103,234,430,755,51,10,972,568,878,728,137,422,333,104,633,359,419,962,324,596,888,225,511,792,675,307,201,529,148,302,943,475,750,189,651,255,922,688,584,445,838,122,120,617,882,885,491,776,73,734,151,63,590,650,332,836,586,391,450,907,102,914,142,770,905,570,107,786,423,369,460,277,514,179,371,926,855,508,734,381,703,165,66,161,746,115,623,20,628,52,200,627,914,481,912,473,410,189,950,476,490,580,221,299,262,325,986,682,442,172,871,728,858,394,833,114,202,697,447,298,603,66,78,151,129,430,702,157,133,311,571,639,590,33,653,860,78,531,768,748,377,710,945,407,822,905,743,667,805,757,909,850,458,129,480,35,547,457,739,967,767,468,552,575,774,402,517,560,152,666,519,513,818,832,931,4,72,966,670,993,726,502,727,928,376,27,138,576,967,417,187,259,605,134,774,106,275,82,934,895,809,781,748,29,192,311,187,336,691,525,56,942,282,4,899,562,483,344,691,801,460,979,120,777,564,713,446,846,661,847,463,191,69,519,351,472,787,600,394,340,987,964,947,888,501", + "392,594,838,397,8,553,89,591,649,940,362,81,464,163,463,504,375,790,672,932,233,416,820,316,735,65,111,400,117,712,183,794,34,566,519,189,28,339,945,304,402,759,777,346,716,911,21,379,899,897,933,23,292,622,479,268,106,703,956,366,597,72,926,949,809,365,516,847,928,56,119,806,672,900,594,755,676,3,292,953,52,219,698,334,66,816,227,288,556,90,973,501,742,76,333,849,246,306,817,810,87,504,789,895,954,476,21,441,996,242,852,649,714,909,857,323,404,133,353,812,157,538,662,171,591,920,945,519,173,544,930,447,763,736,275,879,887,227,138,858,780,481,481,677,799,430,116,568,162,27,731,88,455,73,223,404,760,759,11,612,485,917,974,201,738,835,474,916,615,989,472,433,14,329,343,324,74,175,354,426,308,883,519,882,217,906,761,792,849,616,811,548,105,333,490,484,105,232,199,512,398,569,635,455,648,915,76,599,560,18,861,660,3,188,16,938,889,329,811,336,481,631,325,677,549,801,90,388,993,479,900,795,941,874,271,348,737,4,459,91,186,93,20,312,208,378,911,783,349,790,493,989,791,423,953,211,362,629,376,286,105,173,411,351,44,503,436,581,800,80,742,775,526,776,576,374,82,642,155,448,894,113,914,978,240,778,268,219,921,263,14,723,67,886,277,67,802,412,755,635,512,754,436,963,525,638,186,866,634,149,188,110,537,798,364,528,534,847,919,535,384,20,370,403,279,257,132,653,310,12,543,154,803,762,944,61,257,948,188,504,336,408,18,483,944,254,387,65,562,419,560,200,770,76,474,69,456,752,569,253,90,14,941,737,318,412,196,803,677,450,507,991,425,414,182,195,476,799,289,64,331,907,760,235,633,137,400,819,855,425,140,453,236,572,101,925,52,955,429,517,999,125,724,32,435,706,281,798,278,299,275,829,419,691,637,594,886,264,892,629,638,945,928,322,37,267,294,905,520,661,901,500,32,479,409,767,893,574,911,555,818,55,878,962,198,15,454,55,816,954,685,503,261,379,251,612,225,683,431,794,536,761,107,777,243,803,81,719,457,834,533,407,919,712,744,382,24,388,382,619,82,153,331,250,556,443,652,210,422,919,91,594,104,207,528,220,733,3,818,954,691,339,477,369,683,745,82,879,969,623,56,149,441,648,171,491,883,180,649,541,912,447,439,164,377,63,237,91,123,995,987,839,929,79,299,745,295,698,294,408,642,857,883,971,98,40,401,320,905,146,454,977,614,479,823,339,294,425,505,732,30,148,529,794,854,287,634,688,185,543,878,89,911,95,230,445,805,623,359,814,487,587,532,921,12,665,286,454,393,528,283,110,371,84,877,760,233,471,296,748,838,853,654,178,722,838,474,256,706,5,910,236,739,979,917,587,762,30,387,918,729,750,858,871,954,159,231,954,585,917,492,881,498,113,406,650,56,493,128,741,858,836,888,259,515,713,402,23,244,267,805,758,170,899,868,561,787,114,123,998,704,139,238,403,594,345,458,403,786,301,937,900,101,808,132,156,86,512,547,193,812,935,251,458,954,856,596,325,5,575,81,869,266,57,675,904,978,607,381,461,468,930,416,713,2,886,428,147,32,898,40,429,906,562,551,148,921,497,289,199,388,275,34,524,21,551,172,484,208,145,801,13,7,619,314,882,391,826,336,858,9,970,0,409,985,603,386,636,111,155,543,363,712,228,41,626,563,445,362,695,2,714,657,544,116,503,509,646,15,689,65,106,23,853,513,546,236,411,188,88,829,425,990,839,46,22,459,783,709,558,417,431,920,950,869,69,573,640,608,87,411,910,388,492,292,637,958,282,714,861,973,86,711,452,911,494,661,542,490,284,73,304,790,675,880,714,242,225,681,25,549,23,719,635,215,771,475,599,826,405,907,231,659,243,722,147,54,822,717,273,574,605,526,136,364,961,25,764,304,705,380,264,191,184,945,666,179,569,616,155,778,758,82,854,409,64,339,350,265,283,722,995,640,540,520,212,718,203,829,300,358,548,895,82,446,400,643,5,433,196,155,717,566,26,535,178,727,396,617,82,25,743,947,8,128,249,919,469,848,202,291,352,949,784,751,748,86,323,218,187,585,223,284,197,23,350,656,851,465,430,212,306,74,538,506,353,942,314,465,663,891,430,940,532,996,891,301,960,526,664,113,714,307,345,913,120,968,319,403,622,935,860,168,159,475,696,188,366,661,343,652,31,729,41,471,456,363,389,622,284,264,728,430,415,307,746,191,120,351,251", + "649,90,590,333,808,22,777,669,780,984,998,497,783,133,364,445,881,746,625,612,760,700,596,262,199,958,781,230,969,648,237,152,862,387,654,182,483,674,113,693,944,512,332,762,427,675,616,469,13,312,809,997,368,974,684,517,347,408,730,795,538,998,22,223,374,170,775,893,219,350,617,185,886,255,443,423,732,965,800,841,714,111,211,461,632,323,619,444,441,923,165,572,341,788,56,649,800,833,795,954,504,897,500,983,249,845,123,770,468,50,283,64,911,145,143,11,78,458,507,703,181,336,609,793,504,96,971,460,881,234,427,72,376,63,100,784,127,832,698,15,192,472,167,674,44,78,470,490,302,520,577,974,861,550,157,30,320,107,358,526,992,897,341,335,845,145,110,947,279,789,559,899,485,185,893,804,413,800,264,78,841,806,265,977,242,250,151,75,736,931,806,14,210,36,485,221,463,938,10,198,558,710,198,484,512,443,644,768,420,77,789,788,7,595,118,392,885,718,884,341,700,559,911,659,291,365,694,890,135,545,614,882,199,354,485,199,197,921,920,212,660,703,692,599,535,90,329,375,507,649,575,673,819,426,834,895,808,888,184,874,314,32,202,606,878,352,814,367,143,462,175,605,932,598,181,855,197,142,417,782,794,819,361,74,54,356,173,930,230,610,183,372,46,569,67,872,371,348,599,275,601,104,89,268,468,307,245,789,988,878,440,599,324,898,334,379,577,517,82,289,657,323,721,126,71,101,889,377,521,281,940,846,398,202,420,166,731,869,687,34,336,506,295,743,825,566,899,197,472,724,90,106,233,535,894,690,27,265,844,500,617,119,875,1000,214,54,990,322,47,683,29,445,711,435,995,625,958,567,175,826,30,722,358,876,682,250,490,263,199,263,636,206,985,785,720,177,542,326,600,822,926,130,79,750,827,826,403,974,144,993,95,466,117,12,575,625,216,104,308,156,724,168,566,468,860,186,597,644,242,710,786,812,384,401,168,110,425,687,601,450,822,841,840,474,498,538,67,728,521,331,551,618,321,261,391,95,733,214,202,110,966,645,124,795,159,196,21,553,291,665,821,586,465,984,410,131,752,565,45,594,69,312,831,934,635,760,338,606,905,120,664,294,536,911,734,380,11,308,924,85,261,88,554,179,384,331,881,14,314,444,665,266,637,180,564,772,595,56,447,142,200,772,864,34,474,830,70,935,10,688,593,369,705,949,545,926,135,200,427,795,181,793,684,77,485,645,24,245,749,531,739,892,946,448,938,873,577,752,20,297,96,165,918,126,886,297,340,356,738,941,331,66,299,743,161,605,410,551,771,660,541,508,609,328,388,339,71,17,402,1,352,745,580,470,104,865,63,51,940,571,77,134,424,248,640,763,140,818,194,469,327,868,278,716,135,607,902,720,348,830,389,329,344,295,460,174,689,56,597,124,242,581,572,806,786,19,142,990,155,355,737,310,404,293,165,431,822,627,816,838,92,868,276,221,644,929,505,343,687,301,36,512,265,63,27,998,210,151,215,132,146,440,111,429,572,95,392,231,27,584,464,498,882,478,810,719,674,933,30,888,530,938,13,901,128,364,608,243,204,388,939,175,655,751,799,582,551,620,615,968,48,93,806,551,508,257,249,944,34,2,716,986,571,924,323,833,933,314,747,13,981,605,426,110,624,791,977,509,602,652,643,457,409,0,267,437,522,149,195,215,790,463,479,854,722,315,110,593,836,78,342,485,282,642,855,287,4,113,679,625,914,739,808,476,37,867,293,144,647,683,957,851,278,164,517,904,398,327,420,410,599,94,862,807,307,451,454,167,864,812,348,329,658,505,338,633,52,662,200,649,853,865,742,930,309,153,972,182,624,412,300,316,693,342,848,599,63,904,853,139,981,689,146,164,145,979,77,829,1000,743,722,79,475,600,647,864,26,618,694,272,522,726,117,450,314,835,923,36,48,561,263,703,683,298,103,652,782,952,382,631,178,728,368,137,641,932,434,561,447,128,977,657,959,454,29,174,684,956,230,455,662,702,998,78,145,463,304,945,504,755,652,969,342,575,333,910,53,379,114,66,26,345,200,62,769,861,478,13,62,863,435,723,254,154,273,230,622,689,150,820,250,349,834,17,910,672,584,306,902,101,740,521,157,699,102,117,348,561,394,195,147,660,429,572,563,564,826,819,877,296,968,872,48,410,681,927,845,261,335,281,680,121,659,957,253,100,935,910,512,288,150,759,40,825,179,79,787,862,327,967,234,899,772,46,11,614,628,440,752,627", + "951,745,964,62,65,91,903,814,750,133,915,495,577,937,395,969,578,751,463,88,456,352,569,605,106,14,677,451,761,912,143,392,489,218,697,813,801,805,425,687,428,258,358,735,302,450,686,554,974,274,383,646,582,958,719,293,232,890,354,442,173,602,640,357,846,171,269,410,634,229,245,69,631,310,119,770,625,129,158,826,955,13,410,18,41,414,893,626,710,776,982,802,952,944,176,107,336,719,975,80,815,453,302,164,143,884,977,385,745,305,420,36,749,491,566,637,9,182,549,745,716,522,318,203,817,855,232,481,908,131,841,485,698,905,979,497,569,629,755,427,747,462,878,632,8,641,204,709,227,232,266,137,320,22,399,620,300,482,917,910,61,869,820,438,258,276,135,937,180,668,142,425,235,615,231,698,747,38,698,401,964,792,360,392,635,520,647,762,414,983,160,193,983,516,151,450,222,323,469,227,457,420,554,712,715,605,252,815,731,974,831,24,728,617,262,84,140,825,291,398,937,999,964,271,386,543,322,877,126,357,685,639,141,16,397,100,744,297,22,368,376,13,403,3,810,442,389,897,487,619,509,920,850,428,492,401,250,919,898,30,803,195,221,838,999,431,895,70,365,115,172,230,346,721,425,60,779,905,962,572,334,50,567,372,266,220,552,756,38,463,190,836,697,523,827,237,673,505,230,863,145,493,848,365,443,380,890,895,505,79,338,567,940,902,848,543,288,236,902,152,322,617,206,466,333,980,93,653,141,294,641,677,797,78,688,637,554,218,439,886,172,246,889,741,125,498,546,427,436,8,21,719,919,137,703,524,363,270,948,756,582,461,223,894,949,249,349,880,654,287,669,761,757,877,124,809,58,565,418,289,318,13,62,221,350,456,109,105,289,229,391,760,16,182,564,405,563,263,86,200,493,62,977,344,551,630,343,274,257,461,422,135,592,77,192,303,537,112,699,382,617,363,47,164,772,578,401,244,971,262,935,731,558,147,60,542,836,974,339,380,486,407,721,704,430,200,807,9,474,981,599,714,627,98,326,583,744,361,596,580,863,863,507,248,408,727,35,334,190,318,824,946,194,521,612,285,279,164,12,464,749,296,731,875,697,196,109,797,282,967,227,142,42,74,201,11,448,336,194,172,83,759,296,177,949,639,389,521,355,194,2,702,750,649,206,16,223,203,673,33,790,47,353,364,157,943,238,9,133,133,70,246,366,234,917,959,196,325,136,223,512,52,764,397,881,973,686,680,709,142,52,434,622,28,418,756,756,891,348,419,325,272,373,525,980,185,6,738,701,188,99,362,318,213,209,51,895,643,898,713,473,990,666,499,442,357,689,536,498,69,128,189,183,767,5,833,650,158,170,881,975,856,560,922,490,798,382,522,886,519,357,971,46,109,471,239,718,781,691,870,150,678,430,687,206,782,232,632,46,888,249,759,16,802,770,435,359,83,711,599,533,766,289,820,902,115,324,179,386,459,477,996,740,371,17,35,434,941,586,833,949,501,26,334,403,783,930,880,338,151,708,431,347,542,812,72,127,940,801,171,580,605,874,846,667,457,352,889,314,454,884,580,371,175,784,197,444,922,770,430,653,394,771,268,896,873,54,785,928,681,746,778,757,638,41,491,525,806,274,959,814,719,649,856,897,795,822,171,760,46,79,951,945,52,128,135,916,393,119,158,139,205,985,267,0,399,866,918,359,226,207,214,960,735,198,264,236,317,946,434,563,889,604,320,147,231,882,403,920,520,297,770,240,509,174,454,318,957,937,102,653,157,838,145,251,799,558,862,52,242,240,467,994,124,556,909,29,384,913,505,568,996,973,194,728,711,544,941,404,20,434,953,304,611,415,968,128,265,475,225,628,684,320,333,10,132,683,598,807,811,557,742,176,877,152,213,879,199,480,55,922,18,24,739,545,19,596,393,358,482,413,734,462,184,216,898,805,268,543,811,8,803,994,273,735,251,599,99,156,679,430,947,674,527,389,241,977,627,955,994,572,798,268,920,228,242,515,269,770,488,409,435,295,119,423,95,805,324,400,180,188,567,37,485,355,350,167,590,843,455,483,865,249,848,978,81,613,7,601,680,596,809,61,525,747,810,966,78,709,817,694,98,461,363,597,129,216,709,713,610,804,443,335,110,506,151,291,935,615,647,917,243,543,450,455,669,517,421,946,170,411,179,623,370,426,814,71,568,791,845,247,103,425,477,44,706,247,71,200,498,20,632,54,206,690,759,209,286,818,762,65,44,311,827,530,866,391,211,123,44", + "927,7,760,296,759,684,861,827,454,838,243,342,739,939,791,529,545,484,353,599,652,193,104,541,17,582,867,678,935,428,530,80,777,935,978,239,869,810,599,802,926,333,650,165,472,774,292,292,30,436,264,869,509,122,108,291,846,855,36,369,369,821,812,605,502,705,309,591,547,299,144,546,975,46,953,162,492,311,175,533,99,701,675,269,809,536,688,239,923,379,877,715,712,531,851,161,888,574,778,905,643,304,321,662,316,765,46,423,11,706,13,776,436,768,583,598,734,440,838,929,26,62,236,733,762,75,75,30,165,478,472,919,678,323,271,712,821,712,636,473,507,759,334,136,157,903,113,655,95,24,57,983,626,337,416,181,264,560,76,826,858,232,267,853,676,837,769,155,24,85,204,913,359,380,112,438,835,94,319,210,420,561,474,268,984,75,46,399,126,561,83,215,334,262,152,902,941,208,464,485,655,845,256,54,312,775,264,651,843,94,559,75,826,681,905,393,20,626,988,375,727,959,573,932,676,743,778,49,651,636,646,507,940,663,829,293,768,55,966,57,287,375,180,312,299,437,81,95,523,600,238,989,512,305,518,241,355,739,659,137,735,985,622,871,909,874,601,734,462,687,600,838,874,524,992,617,796,908,59,921,19,522,515,14,607,532,849,816,8,677,247,416,377,168,813,586,523,13,797,280,111,522,451,9,253,321,979,253,239,260,157,769,391,703,199,597,12,232,693,501,793,516,160,499,513,545,153,241,728,789,737,756,654,921,863,11,723,288,347,979,612,470,776,611,682,500,130,849,970,321,32,848,640,151,589,307,361,400,970,478,876,668,520,33,737,867,770,442,178,73,19,415,812,110,540,749,940,448,837,770,128,511,887,57,919,227,170,2,847,829,523,84,55,380,334,14,238,114,212,652,764,955,937,37,212,149,149,518,137,761,404,271,81,538,504,495,17,456,836,777,806,274,198,425,446,661,1000,948,443,612,439,136,372,718,204,554,480,358,466,336,872,79,651,219,830,465,824,456,407,507,178,2,127,505,641,106,288,229,590,293,307,8,848,780,63,71,925,442,628,126,967,256,809,765,667,759,750,551,70,781,854,389,605,278,157,177,713,749,384,89,376,930,467,837,28,328,114,618,163,783,546,590,412,263,283,700,576,258,550,252,186,477,690,584,744,747,936,623,287,375,583,519,981,577,873,810,830,623,242,485,13,107,970,656,125,132,407,445,296,219,948,682,490,561,942,168,124,112,608,385,338,855,129,137,874,497,159,493,49,201,303,974,550,404,173,313,182,558,909,794,788,159,93,117,649,835,586,313,578,989,191,755,289,385,679,844,154,123,385,193,60,74,770,176,638,420,538,389,926,747,61,147,113,665,99,226,398,318,46,219,117,585,102,144,342,670,211,903,900,645,612,375,725,108,366,343,794,471,522,544,501,658,995,762,692,33,211,536,341,868,614,929,778,481,816,565,53,718,548,595,843,348,210,453,90,681,721,473,876,340,343,75,763,184,126,614,614,60,886,672,409,456,173,318,216,354,31,688,213,21,805,808,551,688,413,583,638,643,538,987,779,119,620,350,607,367,921,359,195,546,128,822,391,826,134,569,789,335,12,982,705,325,591,130,888,82,570,155,686,294,419,32,151,690,864,554,4,474,600,875,652,225,909,462,366,427,490,724,170,844,76,774,603,437,399,0,647,715,908,540,536,483,667,918,797,579,375,855,560,991,599,268,31,662,193,229,831,914,974,238,360,276,947,6,243,224,910,397,408,850,503,704,125,287,704,252,737,305,888,609,189,914,916,511,331,162,786,971,319,515,590,405,140,40,918,228,826,407,548,394,509,612,339,992,730,294,950,809,431,769,25,636,462,869,940,648,132,316,52,534,405,611,161,274,627,669,943,395,464,903,531,838,8,735,314,842,982,305,124,810,413,489,576,38,968,677,600,279,384,472,396,76,585,463,969,946,278,328,69,872,420,564,493,682,5,409,591,411,947,881,793,990,760,91,929,26,312,30,489,273,517,146,153,150,716,582,330,848,951,333,333,439,464,865,415,504,56,973,502,555,39,407,327,157,264,125,479,35,103,267,934,269,813,155,185,487,511,801,994,500,751,155,575,98,952,183,519,466,465,399,265,75,981,322,559,236,805,394,665,863,613,153,395,921,342,563,446,964,794,251,88,935,468,591,176,719,188,805,563,599,816,550,726,222,218,349,279,408,972,446,673,192,835,814,692,711,21,529,352,651,752,392,661,520,996,934,957,813,212,929", + "757,24,201,431,13,191,457,582,705,320,509,392,675,488,222,623,244,128,432,273,567,620,281,765,928,145,14,279,685,601,799,389,855,315,96,928,160,716,915,671,993,590,109,361,600,538,503,597,726,953,588,280,12,380,561,141,371,481,166,750,725,952,266,182,769,520,798,968,485,566,2,933,643,598,378,982,568,95,416,724,2,410,279,967,522,933,183,572,839,997,68,496,307,842,477,794,383,459,937,65,141,944,727,894,933,211,802,498,600,732,876,770,564,122,330,369,172,254,600,599,551,510,111,556,188,962,383,2,876,119,442,888,543,224,982,372,106,661,761,563,171,739,710,367,24,514,866,436,584,125,834,542,261,569,554,940,338,287,928,17,436,115,239,75,153,773,221,50,994,379,102,136,544,751,171,412,523,832,94,932,11,554,293,416,162,537,423,715,767,930,191,78,522,819,920,487,260,631,387,243,324,371,660,501,899,561,255,127,446,954,643,829,598,568,680,971,178,538,749,576,355,980,122,509,307,833,992,375,810,840,654,988,870,100,903,567,785,510,738,309,774,591,770,136,889,131,237,584,25,577,307,246,497,48,802,658,35,514,167,147,304,848,410,253,584,333,399,551,844,800,553,833,990,69,722,385,192,694,491,138,846,687,130,970,258,969,436,585,82,695,146,822,655,895,363,930,396,803,223,827,343,598,790,42,754,544,41,677,155,592,882,363,590,806,283,590,263,540,225,696,346,718,318,674,708,751,89,486,494,320,76,198,465,582,411,233,785,984,388,488,588,326,156,516,126,622,829,488,974,141,636,88,509,182,802,169,992,854,628,271,659,318,52,16,688,652,72,410,271,432,804,744,299,982,213,162,170,611,353,125,824,613,269,226,471,81,123,362,231,136,358,976,865,237,311,202,138,467,68,237,707,745,696,598,563,108,520,369,95,787,383,217,945,929,651,926,7,423,742,301,520,471,579,606,789,772,134,686,202,273,218,733,888,25,64,628,18,834,259,797,557,838,363,61,803,430,85,51,760,738,94,495,248,615,452,798,652,2,407,435,332,391,446,42,287,634,873,863,604,388,358,611,399,29,842,711,31,622,510,12,742,688,875,618,949,108,280,713,97,449,321,149,971,27,794,27,974,222,411,309,957,156,887,569,407,370,787,862,738,414,833,407,973,4,191,475,267,796,447,847,971,639,348,923,812,272,863,497,267,651,484,818,148,523,791,114,320,807,651,959,959,917,454,263,945,69,470,828,816,431,245,469,813,866,644,163,398,731,410,30,796,722,369,719,84,10,612,442,592,814,10,93,52,166,768,259,871,270,576,960,157,625,296,805,53,823,476,512,752,210,749,365,763,851,144,904,457,856,713,204,960,120,920,806,243,161,186,581,724,390,548,872,174,205,963,63,71,909,530,797,218,801,943,367,706,295,729,705,760,615,671,212,247,711,510,998,422,230,870,169,560,741,167,520,356,452,747,789,750,992,608,968,843,589,639,613,689,428,916,508,456,389,936,280,70,331,372,653,620,336,409,802,388,71,28,487,397,533,480,969,528,754,823,558,209,130,133,747,358,47,798,88,372,512,190,578,324,157,252,316,242,547,291,265,566,765,613,291,781,237,215,523,271,127,788,106,926,859,755,648,654,562,523,789,478,701,910,918,592,785,720,793,36,101,273,123,685,621,145,113,794,60,386,522,866,647,0,463,958,71,17,838,122,395,522,237,904,480,773,646,399,180,698,36,455,701,765,710,685,482,379,216,205,882,765,755,265,198,833,437,266,534,232,79,305,68,469,612,919,684,191,194,780,922,592,549,146,575,708,931,758,779,33,447,414,718,123,387,675,279,90,622,247,44,552,543,298,233,653,710,653,202,946,976,715,770,351,714,429,48,938,485,461,778,90,905,49,750,443,273,351,603,904,396,567,532,84,579,20,877,788,710,575,572,119,619,840,94,243,660,739,334,65,242,958,81,710,268,734,551,229,219,801,225,399,530,394,711,742,100,448,510,346,71,495,884,203,549,115,307,643,898,643,725,409,469,826,687,354,48,497,609,916,340,130,608,332,779,379,866,68,342,809,452,56,495,378,465,664,669,880,753,696,244,893,423,182,72,630,982,42,440,93,223,710,978,529,68,473,498,569,170,920,432,581,220,180,718,328,939,691,756,166,689,792,74,85,170,39,706,335,288,433,593,157,87,922,428,916,975,83,515,48,508,225,521,614,3,62,910,805,62,862,220,100,126,155,845,244,852,189,47,341,754,513,356,459,265,710,531", + "835,252,16,960,59,882,133,892,780,835,381,329,748,37,877,351,911,566,629,398,264,401,402,876,910,282,56,716,398,710,241,578,737,253,725,684,724,621,959,33,863,279,609,495,908,126,932,348,706,677,234,651,626,508,643,483,134,513,64,57,760,410,589,250,356,187,777,710,537,156,157,714,546,86,801,715,566,279,888,403,384,113,939,511,725,795,407,574,363,481,398,325,637,316,683,739,445,341,518,480,986,15,528,158,959,941,865,202,308,317,202,527,87,879,364,28,195,289,62,420,576,695,118,517,614,885,367,151,283,524,168,20,726,365,323,117,552,336,865,106,860,995,913,935,866,356,533,819,958,728,923,433,854,454,341,299,543,338,175,163,634,607,184,249,243,411,851,314,485,869,435,619,863,973,103,870,168,970,520,455,4,54,875,87,304,711,511,757,56,896,159,298,36,327,364,191,223,750,728,668,583,298,398,436,740,426,201,104,668,991,552,860,275,164,86,310,284,850,77,835,360,537,214,234,533,950,91,788,112,54,305,40,839,624,702,661,596,929,943,602,216,889,553,583,370,209,961,921,120,305,785,47,240,263,824,896,841,115,240,591,450,933,465,115,554,482,933,347,811,729,389,38,218,961,194,631,549,489,596,119,850,612,887,357,589,217,104,185,361,226,378,780,166,658,748,275,101,277,813,789,854,349,685,731,83,908,940,784,720,938,601,240,425,957,877,887,37,876,771,904,961,601,693,163,593,99,201,243,165,936,718,123,216,18,364,208,460,730,915,36,697,968,665,545,269,501,532,188,788,883,832,83,890,860,932,918,988,216,866,392,324,518,518,26,929,767,962,944,622,363,8,67,585,587,897,213,470,714,165,63,857,836,245,465,797,23,490,626,986,412,498,911,175,68,435,695,233,410,311,634,226,928,994,691,895,993,759,688,320,739,976,457,861,931,518,599,41,619,624,372,96,125,126,145,94,863,736,232,930,628,303,99,47,341,815,636,945,118,159,587,80,860,979,928,697,650,623,259,930,438,425,894,252,116,944,447,448,447,642,7,314,200,845,567,212,70,380,125,176,247,889,491,223,293,386,681,788,857,550,960,660,432,882,909,413,126,240,633,313,27,476,496,595,320,767,54,736,66,634,38,653,655,455,410,133,384,549,192,819,39,986,911,591,723,836,434,179,949,417,517,15,231,498,195,242,461,326,287,457,361,664,489,805,431,893,463,277,338,27,882,491,264,47,179,851,964,717,953,433,983,727,622,312,678,499,668,429,267,244,249,711,673,97,152,862,684,716,865,356,47,845,769,544,687,574,455,998,114,669,95,132,663,23,391,456,407,776,97,545,641,162,370,998,321,862,85,579,493,116,969,82,6,90,622,560,71,329,140,29,325,768,936,207,244,583,7,651,60,225,853,419,330,102,888,887,254,927,117,768,484,458,67,161,401,290,285,731,818,209,660,85,841,12,857,781,576,810,367,945,587,154,957,865,334,236,937,158,156,659,691,750,792,825,145,488,228,525,906,986,734,863,139,296,727,998,457,551,615,206,961,893,97,254,133,409,147,491,196,718,456,18,109,105,272,891,351,352,214,725,194,7,13,7,863,337,303,180,11,573,613,46,199,140,572,108,969,397,644,748,118,417,647,145,185,89,15,122,79,813,896,524,929,376,491,152,232,396,312,191,478,738,826,636,149,918,715,463,0,275,860,309,694,179,608,355,193,588,578,898,321,253,119,881,84,988,840,346,853,301,314,64,647,451,282,399,206,755,495,861,579,624,371,323,903,683,332,691,840,527,391,39,134,4,381,241,393,1,261,803,427,368,152,917,649,794,320,20,917,228,375,70,177,29,738,379,314,570,911,4,621,419,396,307,808,439,201,315,57,394,475,800,286,421,435,554,619,440,536,492,176,242,645,619,659,437,835,855,467,751,311,754,656,870,420,875,660,596,218,149,709,454,605,214,298,283,88,670,621,758,19,118,829,313,852,547,842,103,803,613,61,723,523,134,429,371,337,865,653,998,306,827,634,679,754,962,37,520,421,503,238,535,361,52,819,949,540,164,409,646,524,445,743,279,162,590,51,379,830,281,117,288,779,460,708,406,605,262,472,106,480,255,626,972,498,107,239,3,590,106,617,828,570,774,109,171,455,270,344,350,823,850,886,93,161,869,584,18,810,218,638,71,639,50,115,548,335,610,136,950,408,54,389,221,558,345,92,394,604,478,870,320,849,104,118,392,641,122,968,868,615,288,270,520,676,133,965,389,714,603,699", + "567,528,9,424,364,530,711,200,998,760,237,404,729,929,786,773,723,761,494,280,477,775,486,919,754,343,431,821,111,210,584,397,494,741,232,490,411,329,329,963,81,507,257,130,619,126,779,210,68,611,82,524,993,971,592,325,371,364,240,382,604,503,529,440,802,920,528,98,390,733,551,106,215,55,147,624,342,275,749,751,818,632,273,662,340,820,586,72,484,24,497,169,689,431,598,981,847,727,676,197,428,829,436,602,109,245,715,91,607,989,435,84,980,687,144,683,549,852,299,431,865,523,706,674,381,730,754,89,421,600,835,695,392,214,37,217,445,823,463,296,466,305,778,539,297,392,119,683,468,314,647,606,943,273,685,53,486,912,552,950,57,123,824,608,209,334,330,755,372,775,32,589,130,633,535,202,462,224,69,886,479,786,694,445,63,121,377,223,343,494,919,522,514,874,261,493,19,295,498,491,612,735,884,819,526,910,488,760,175,844,375,901,754,887,578,598,880,740,756,298,714,38,320,52,390,711,547,406,729,827,884,638,910,354,237,112,796,456,766,387,873,485,508,459,867,345,11,772,200,298,692,864,616,707,632,715,507,78,68,127,10,450,135,56,466,180,615,530,356,47,906,623,887,28,919,877,976,62,491,218,90,159,525,854,974,722,785,461,642,667,166,643,252,565,984,217,202,99,386,623,946,954,477,644,114,847,501,9,944,334,331,391,996,854,543,36,232,45,790,802,972,348,594,514,508,483,767,158,834,622,973,596,504,923,851,316,192,128,412,888,439,109,990,323,169,78,268,555,534,717,488,915,562,595,367,286,182,988,236,316,38,913,847,1,266,365,892,802,415,506,142,508,61,668,944,814,355,886,358,481,24,787,580,745,592,194,298,336,797,264,853,971,2,606,865,658,89,31,49,352,717,805,440,775,579,993,905,404,749,751,587,950,767,194,411,54,78,152,578,46,252,488,472,499,174,732,840,979,330,701,409,194,818,621,967,599,660,989,585,764,539,941,175,504,631,167,156,679,197,11,371,223,134,581,37,34,681,654,37,933,298,378,906,145,175,955,476,875,809,916,512,176,267,822,950,172,957,753,534,363,874,228,111,555,759,678,34,247,812,291,355,171,425,683,677,705,609,166,639,351,779,75,260,490,23,784,248,424,956,220,712,850,386,438,466,62,969,310,119,243,765,292,31,126,66,906,32,200,632,346,258,902,546,585,466,34,671,820,896,990,510,276,662,692,491,433,747,872,49,542,531,647,495,763,528,319,811,123,394,507,594,843,464,240,60,441,184,908,791,878,943,291,591,135,608,563,52,927,767,83,428,743,226,123,221,481,292,432,762,230,232,479,472,474,342,363,377,607,630,886,795,631,175,134,850,405,887,815,32,86,805,532,444,651,992,496,15,388,350,798,840,154,146,288,206,276,130,501,893,59,626,670,242,801,614,832,71,60,298,597,100,243,947,271,480,443,665,679,762,301,465,865,420,438,884,381,283,356,952,162,43,168,671,206,481,243,200,256,963,487,821,475,342,209,437,154,25,58,191,39,458,499,859,713,427,504,179,560,342,972,859,387,414,300,576,634,366,212,288,491,963,69,130,535,732,107,403,886,995,37,912,868,216,365,157,564,205,293,936,741,670,575,443,41,583,271,118,826,169,533,140,760,15,844,431,204,488,164,247,721,905,819,111,195,359,908,958,275,0,205,540,920,552,803,163,669,332,727,4,986,103,277,520,294,219,280,184,20,766,587,655,218,301,266,163,478,434,21,597,740,885,388,83,203,369,344,513,11,904,10,275,449,793,171,277,980,764,36,434,70,934,539,945,842,665,770,745,9,772,221,664,389,331,211,110,845,714,563,764,261,662,746,88,379,34,866,516,153,417,979,660,339,194,449,446,897,396,515,543,406,423,701,919,245,589,672,61,530,964,691,112,784,658,216,460,7,298,760,89,475,263,158,832,115,526,901,113,55,159,958,469,134,486,208,202,604,206,617,663,512,252,977,297,149,937,544,839,521,376,7,631,738,60,534,64,544,992,677,538,569,971,817,4,156,739,57,349,941,764,320,296,321,683,794,535,424,958,490,68,723,905,92,628,321,197,720,879,609,276,82,396,609,550,538,482,269,659,152,78,478,488,195,116,837,101,745,232,618,548,898,988,16,234,10,603,43,693,127,361,649,64,213,544,923,591,598,439,97,992,538,479,494,129,164,985,575,395,792,58,709,446,512,655,956,247,344,178,291,74,501,794,398,705,835,736,253,956,775,264,38", + "472,973,160,916,50,691,487,473,761,288,662,424,364,259,614,635,714,637,555,265,608,954,745,583,496,744,599,879,566,531,952,119,895,378,551,896,411,974,972,768,603,427,607,756,846,14,807,759,455,191,557,380,683,172,562,972,708,863,701,271,350,63,69,102,720,715,555,287,796,478,590,953,314,567,792,881,26,576,666,209,229,797,353,165,127,31,903,972,68,192,908,418,109,531,599,928,988,873,265,826,198,513,725,202,59,980,555,342,337,587,798,736,388,868,406,780,183,714,999,839,888,589,829,508,377,812,270,929,216,584,43,550,865,878,209,517,402,558,397,894,305,894,549,151,382,713,310,518,615,804,680,728,508,583,926,958,64,250,271,620,862,794,26,268,856,547,170,262,636,383,721,401,651,385,252,498,928,47,633,682,967,779,893,271,594,207,326,597,264,188,385,680,346,73,433,351,677,371,744,996,453,667,136,916,41,211,847,728,571,675,192,27,684,243,17,544,544,363,855,705,318,949,257,777,337,642,839,502,855,256,472,58,117,607,470,314,511,161,470,218,406,639,716,947,668,76,595,503,152,256,314,723,673,897,117,587,512,317,554,943,954,1,672,860,682,809,358,537,205,194,377,90,679,525,170,449,780,290,814,154,240,30,703,662,287,863,56,463,624,201,164,524,928,42,99,288,445,255,14,565,466,868,47,270,67,232,868,989,670,291,805,626,385,679,192,171,957,117,778,149,743,286,321,652,503,323,662,16,360,611,794,647,946,539,613,883,482,39,161,242,258,75,58,985,668,587,105,948,650,644,731,7,82,106,970,293,338,657,115,904,855,146,548,476,221,143,382,747,828,221,63,263,28,336,201,512,409,658,26,540,262,220,976,818,605,29,993,72,713,418,299,64,560,720,629,316,491,112,596,386,36,830,896,833,789,323,513,213,991,623,710,893,32,146,673,710,910,963,485,648,391,234,834,28,927,986,383,420,451,755,448,213,470,420,957,81,840,325,687,269,60,787,505,204,508,391,727,522,679,528,574,117,682,696,635,12,358,313,893,927,792,979,508,79,174,287,231,58,378,957,574,50,686,718,846,193,5,434,249,272,62,166,343,38,574,512,753,83,98,457,251,41,382,199,774,920,272,273,319,135,623,154,278,472,440,636,935,463,466,198,800,755,261,241,582,992,938,667,417,802,259,268,151,511,127,368,946,477,151,956,894,973,462,525,485,756,216,559,963,992,693,19,607,172,614,27,625,567,7,965,699,45,16,648,800,850,498,580,337,865,978,777,213,536,30,791,114,527,111,865,955,272,499,866,146,210,641,816,948,456,68,659,211,411,635,967,796,260,345,471,70,503,868,548,902,270,920,87,92,805,402,469,772,676,582,443,473,641,712,125,455,156,950,115,889,686,11,124,756,569,387,669,180,636,299,680,93,48,85,114,928,328,965,158,831,669,555,401,979,687,863,950,889,87,190,432,814,150,167,807,148,207,12,482,474,348,963,16,970,916,985,38,555,742,891,550,94,358,982,614,614,155,151,636,234,330,913,907,359,103,594,266,262,343,906,298,157,804,181,809,782,379,102,549,415,187,841,239,172,118,897,549,520,943,383,315,41,616,12,728,698,91,527,154,682,834,383,537,511,881,939,397,612,478,275,849,852,91,351,374,374,610,784,830,442,66,359,183,382,419,430,140,155,215,226,540,71,860,205,0,497,718,909,24,506,662,662,536,471,421,482,309,343,131,992,815,217,553,957,926,924,430,540,418,655,996,11,343,2,268,93,228,116,2,606,836,185,7,966,677,145,892,70,528,637,663,985,643,649,463,984,799,759,94,550,253,247,653,19,712,469,271,377,285,512,239,372,96,928,105,105,126,844,219,391,391,385,860,894,886,430,314,464,616,717,581,728,510,520,965,634,372,144,797,852,754,850,784,552,612,894,971,263,905,97,155,33,863,891,745,318,629,711,324,317,642,985,479,49,249,721,794,28,339,18,88,789,972,279,704,557,940,446,123,519,541,103,510,101,980,769,455,820,603,275,895,135,876,569,531,670,69,813,625,714,735,75,461,579,736,162,524,884,518,246,726,805,491,869,94,819,452,527,917,464,38,67,994,553,976,416,134,283,346,829,154,658,529,747,95,507,299,21,411,366,791,649,741,856,639,76,649,517,429,680,302,536,101,983,115,636,266,249,30,944,617,170,998,95,10,895,355,376,850,527,6,726,575,728,394,356,365,182,127,185,540,880,79,700,598,230,953,410,101,389,83,204,347,133,462", + "530,117,868,47,485,712,708,946,392,775,818,309,625,598,348,906,940,251,354,785,772,167,49,692,257,570,115,908,172,2,591,397,63,411,387,128,351,130,399,610,746,830,48,876,420,258,317,283,962,463,451,377,238,933,522,844,600,505,271,197,552,856,552,790,579,395,976,446,338,482,862,411,259,399,332,727,351,615,67,585,743,843,607,895,467,790,32,327,788,351,149,534,487,324,859,573,649,433,335,579,979,979,906,140,684,738,129,309,531,193,948,255,153,472,836,84,840,504,421,324,331,342,275,170,809,817,716,597,541,94,316,833,775,476,161,506,578,675,675,168,522,736,251,562,203,463,872,339,375,178,540,745,462,90,226,806,241,582,991,978,547,851,959,491,943,474,150,451,999,646,448,558,102,279,323,131,547,179,898,681,534,246,291,221,848,675,689,570,182,150,764,621,901,485,550,561,993,190,453,306,636,217,264,289,518,226,38,286,248,387,85,346,758,577,730,724,664,211,101,770,63,612,361,649,864,412,10,251,385,955,717,208,923,290,737,607,635,983,149,544,352,265,508,794,354,879,669,849,985,568,621,743,12,62,107,34,525,654,619,974,521,960,233,297,262,22,507,170,979,573,757,189,51,909,480,871,756,281,202,889,413,812,372,241,158,519,65,467,783,308,41,111,679,484,87,790,239,82,357,727,722,764,200,551,665,625,602,122,602,80,136,44,502,84,608,113,220,623,834,818,371,166,174,556,40,143,289,738,11,814,275,40,767,173,970,819,871,742,729,544,150,300,988,800,240,141,93,228,380,722,472,202,548,887,949,338,337,135,151,372,468,712,463,342,510,875,266,57,130,200,461,748,129,603,884,26,251,27,489,807,204,744,722,64,692,266,197,732,437,566,814,894,863,715,443,196,551,234,954,55,751,246,113,398,442,616,553,554,871,39,799,360,73,492,396,637,835,178,980,231,779,304,670,877,663,554,881,239,130,556,821,388,565,13,783,541,15,198,417,579,360,906,645,96,166,26,990,328,137,140,499,462,581,511,947,32,815,939,280,375,754,17,258,324,286,785,128,426,824,200,189,557,572,102,336,565,900,32,450,8,123,419,656,659,147,960,33,862,911,912,16,902,767,800,165,861,632,950,397,735,435,636,197,503,820,425,461,675,635,809,510,64,524,774,78,595,167,903,154,20,773,484,718,273,389,992,399,800,667,400,117,392,53,667,971,979,242,216,846,984,815,493,598,3,135,720,984,743,106,623,631,16,261,139,670,565,931,714,959,123,266,636,496,846,736,874,175,33,842,876,986,349,278,932,404,910,129,829,416,663,28,648,762,595,763,527,379,398,1000,99,831,765,463,192,709,418,567,944,866,937,225,515,564,952,618,720,871,222,230,911,583,905,645,904,161,583,304,51,303,569,247,374,861,308,416,231,20,196,75,865,370,810,635,512,567,244,694,378,841,406,348,304,760,14,752,957,937,629,68,601,523,780,534,283,75,156,409,119,76,791,279,810,366,455,253,993,561,722,989,935,825,324,828,607,983,197,696,592,482,56,160,956,203,161,736,810,225,56,424,883,546,730,102,454,899,619,653,410,410,676,570,8,726,549,768,892,345,656,890,17,499,496,406,329,322,323,200,349,759,16,89,801,966,648,911,802,409,869,388,310,875,718,778,792,892,812,242,3,973,991,909,949,543,790,207,536,17,309,540,497,0,126,482,448,328,401,497,926,793,371,492,317,239,428,853,573,596,322,842,395,112,130,617,515,136,818,49,461,874,280,607,287,483,288,910,830,184,981,722,777,786,604,497,411,690,533,102,31,143,783,73,679,550,751,207,642,734,984,390,811,117,835,55,399,458,547,757,970,53,273,14,186,426,985,67,84,858,304,679,712,666,1,780,875,14,881,724,770,48,402,967,117,500,62,713,368,700,515,399,23,840,128,833,654,225,304,387,295,223,48,435,363,424,964,952,108,732,5,902,652,690,706,247,254,518,17,363,604,363,862,476,137,519,318,472,71,556,688,24,298,154,740,31,436,197,953,649,711,330,103,159,162,897,39,360,914,788,757,596,597,972,354,990,208,478,573,849,6,583,373,190,945,434,388,678,732,597,930,195,449,387,217,356,184,582,173,649,939,562,642,68,213,393,946,220,571,141,575,6,710,272,407,808,316,172,450,517,152,363,104,938,472,125,679,742,907,329,246,417,735,900,150,841,281,349,8,192,933,680,51,154,738,485,370,728,762,131,160,884,391,13,69,664,707,879,991,328,720,591,849", + "589,290,124,52,393,446,677,765,96,52,814,3,568,775,7,910,659,734,631,678,522,63,787,171,638,299,341,773,873,992,989,490,833,765,221,287,575,257,643,228,269,883,557,508,77,50,4,993,738,485,218,638,756,59,431,532,75,104,66,777,944,47,857,472,52,569,419,604,538,135,69,753,734,128,822,530,590,680,95,207,699,725,216,240,280,672,747,126,766,950,204,131,620,345,473,501,338,19,515,181,351,845,130,648,687,742,358,973,100,595,976,380,180,363,739,126,575,617,179,784,839,585,395,960,270,798,294,86,95,639,859,981,535,844,945,686,546,209,371,480,546,81,815,165,866,641,477,448,234,345,203,187,717,643,867,382,82,876,171,686,900,873,911,897,720,770,553,742,825,569,274,374,501,316,885,737,812,722,451,71,571,594,577,655,154,309,298,868,455,180,777,167,602,748,161,754,842,934,42,331,348,500,474,754,364,217,335,843,372,966,54,284,456,372,348,334,114,156,821,406,526,597,432,692,175,798,165,918,870,977,833,176,948,861,831,103,651,569,370,527,288,2,989,762,467,196,808,83,791,884,644,300,8,400,820,705,149,724,999,691,199,443,458,697,928,977,811,823,356,832,208,898,209,909,36,660,912,746,727,702,88,876,86,245,451,450,503,705,93,886,564,990,171,728,39,838,347,969,733,462,976,345,978,152,764,102,84,231,961,942,530,728,620,625,853,539,714,488,760,741,869,644,857,685,159,1,531,419,236,7,793,830,136,185,270,698,809,31,533,187,150,295,643,888,169,605,144,115,56,12,662,801,322,97,413,793,14,341,899,63,696,526,749,153,780,462,833,244,753,533,134,162,216,698,145,264,601,882,25,389,976,583,232,237,111,810,139,783,755,245,278,86,178,673,498,528,298,41,387,951,792,721,17,213,408,455,757,532,442,206,750,473,367,525,485,315,786,695,755,457,849,903,305,482,221,772,91,56,934,740,659,550,42,279,705,374,226,441,655,581,893,102,640,959,125,301,888,934,711,521,167,78,447,964,884,903,380,390,452,635,404,578,88,976,613,412,296,549,602,925,619,489,152,431,660,882,840,137,987,220,411,768,980,555,835,953,420,852,286,366,686,506,699,980,381,963,995,408,239,567,213,529,531,841,201,6,35,642,342,603,699,65,375,572,149,167,136,619,402,500,195,920,570,630,499,549,805,422,862,792,714,832,614,211,710,393,736,769,444,6,312,999,819,967,674,538,403,127,49,911,23,927,213,796,841,666,916,324,947,972,636,811,140,541,649,481,795,594,306,694,466,825,324,83,236,779,503,12,982,222,170,955,704,522,194,786,22,361,792,414,975,942,693,699,742,241,207,882,885,685,857,616,679,272,815,306,595,735,796,940,323,350,586,245,171,62,931,236,870,614,560,79,480,731,143,770,824,258,973,744,267,216,744,700,902,234,317,728,39,770,162,130,498,793,32,801,801,195,670,82,519,846,88,975,516,941,238,504,203,681,381,715,537,49,416,12,74,483,961,393,536,273,653,580,121,384,80,10,891,221,559,873,689,134,549,473,460,460,959,858,590,843,557,973,442,46,828,160,802,990,338,215,241,376,250,906,530,799,751,49,329,729,732,236,52,684,53,315,706,142,567,724,561,134,104,277,862,189,42,702,558,604,761,30,898,867,383,350,400,212,683,879,363,463,214,483,838,694,920,718,126,0,103,517,164,891,156,903,120,877,289,238,757,88,112,221,375,142,62,863,984,120,910,714,836,904,970,243,849,532,830,265,703,425,416,902,129,153,904,310,84,551,882,79,810,214,479,710,371,833,220,194,924,347,225,311,786,652,196,517,594,500,83,79,185,22,433,939,744,689,825,185,599,86,61,892,652,151,551,503,591,312,278,351,295,757,125,993,377,420,785,443,338,120,787,402,340,498,178,728,314,451,901,772,842,156,322,829,363,167,256,751,216,979,118,564,50,378,882,198,686,884,495,425,31,246,984,432,948,959,566,722,40,878,854,485,536,173,686,738,332,349,744,405,413,101,362,30,113,746,483,301,391,740,767,683,512,831,300,204,524,449,100,131,274,721,660,397,261,905,887,699,831,614,737,680,237,10,941,446,307,817,512,601,315,31,203,808,394,578,209,240,34,751,160,602,417,975,783,988,421,868,603,513,195,641,93,257,772,869,642,503,336,156,103,592,519,534,813,953,197,251,51,829,880,221,496,922,503,388,900,262,881,209,88,753,346,17,868,834,737,975,830,593,168,363,107,781,711,383", + "959,548,267,69,960,837,428,598,468,170,156,330,575,991,772,521,217,798,217,158,506,3,363,139,328,529,786,30,591,289,148,514,438,862,331,16,388,598,112,932,723,10,520,980,68,909,27,56,768,814,721,647,135,777,839,658,160,268,555,223,464,902,580,123,910,763,29,392,800,498,419,473,327,932,263,727,733,798,716,229,940,900,252,119,610,183,16,541,442,374,408,919,898,750,457,617,808,829,749,654,607,478,485,989,760,974,869,981,12,494,198,464,141,415,446,799,774,995,870,576,185,636,562,677,503,290,73,449,575,354,520,444,323,771,926,747,92,413,621,55,910,911,103,919,851,266,991,197,105,376,803,84,686,680,284,467,746,883,475,769,125,909,676,991,294,570,187,928,320,340,727,777,745,510,437,791,865,384,43,703,198,493,154,321,803,437,800,921,423,199,70,480,286,865,671,421,438,786,325,240,278,986,106,257,464,982,437,374,613,627,76,544,498,977,570,957,666,311,568,96,909,765,791,501,88,140,956,231,766,146,325,159,164,796,719,787,192,751,560,933,938,10,327,962,741,637,988,400,614,119,136,255,280,720,368,8,201,106,795,835,445,572,344,31,838,120,475,538,900,565,888,975,639,476,286,388,996,506,475,711,708,23,379,730,762,880,192,79,512,898,197,21,970,105,604,728,850,901,189,881,461,490,809,179,504,470,762,996,81,831,185,151,449,103,700,57,87,449,523,324,767,696,413,870,15,338,233,306,478,534,616,328,823,649,379,380,882,838,298,483,375,436,61,189,843,301,803,768,132,738,60,44,882,338,269,427,971,559,639,770,13,119,455,214,792,626,632,973,443,252,823,599,546,26,698,785,913,167,313,243,915,361,14,613,222,607,445,493,363,971,923,401,580,25,273,359,6,561,345,893,81,44,210,180,1,835,471,184,770,550,310,332,122,811,467,533,531,902,501,717,687,147,485,812,761,119,817,787,358,327,111,755,932,689,440,588,180,471,507,747,829,595,374,188,23,781,391,411,813,690,480,48,510,488,541,734,45,510,705,595,823,894,474,584,633,359,432,375,454,797,255,57,84,344,805,279,542,415,503,927,404,920,919,128,878,458,695,398,616,139,684,694,564,33,230,318,913,751,906,40,685,926,879,111,25,145,732,38,80,542,14,939,274,270,243,179,541,24,576,436,13,283,640,974,452,146,136,916,329,718,116,957,380,263,874,602,302,403,85,345,943,482,394,221,795,443,955,562,764,467,99,816,719,104,756,774,38,158,232,75,642,731,783,237,565,859,29,534,347,973,801,554,241,711,460,757,440,677,385,984,829,210,261,421,839,678,45,458,118,475,812,111,996,8,834,189,359,849,122,522,609,831,771,440,720,620,675,642,815,691,7,860,896,751,872,1,753,624,768,760,114,993,93,293,346,801,846,27,703,727,262,265,835,296,783,883,515,161,90,906,877,616,127,424,35,10,203,702,160,953,714,617,508,163,746,390,528,822,109,468,853,552,384,290,998,409,676,666,658,97,682,789,766,345,292,292,546,888,615,280,444,798,374,873,70,757,755,10,456,232,259,891,503,141,619,836,874,940,662,789,752,187,979,445,318,616,714,845,978,305,599,513,441,734,226,104,367,325,179,538,409,64,220,686,898,24,545,56,664,855,815,247,688,403,870,522,867,168,570,875,645,388,712,479,960,667,122,179,552,909,482,103,0,958,873,179,859,500,301,252,290,223,893,18,878,156,519,478,629,152,653,546,452,394,130,678,938,177,280,722,700,120,938,912,978,421,471,597,80,505,390,734,322,377,952,165,289,912,719,524,894,436,801,667,948,444,309,377,767,705,533,522,76,82,777,151,970,870,846,446,963,37,411,741,305,42,442,533,497,176,22,82,660,13,52,529,714,719,658,869,691,827,752,873,850,921,469,800,490,726,639,808,956,977,857,455,445,136,87,446,369,859,387,396,846,91,7,456,104,128,824,41,544,699,743,518,836,737,124,603,168,458,898,848,522,408,373,811,774,66,545,189,717,619,640,329,690,556,220,791,555,113,291,630,664,943,208,743,540,791,468,827,492,160,37,549,336,838,605,697,465,74,349,559,801,983,148,337,780,701,216,462,8,677,457,353,94,403,16,95,188,269,803,273,396,752,794,689,494,383,973,424,728,969,374,272,228,222,489,702,268,275,637,122,267,662,917,810,623,981,915,912,699,741,827,144,961,211,172,142,842,132,415,881,762,2,398,475,99,698,130,122,981,814,45,577,394,745,750,193", + "213,202,460,164,972,726,159,555,305,422,923,828,473,797,229,365,923,929,888,509,359,572,18,110,461,989,990,268,407,246,955,535,985,474,559,233,232,807,709,762,697,138,54,765,430,486,837,152,149,143,873,958,67,169,462,670,952,793,322,749,8,70,894,516,918,148,397,834,834,491,339,297,353,761,535,692,984,26,936,807,700,266,330,328,797,357,738,722,875,982,652,915,46,25,140,347,794,206,302,611,307,102,556,761,950,14,976,219,962,626,945,328,284,554,896,421,250,581,740,673,698,610,809,314,807,400,104,455,113,161,150,92,67,973,826,533,112,378,455,435,23,534,105,996,477,33,852,676,542,901,860,977,37,659,547,969,353,289,990,767,972,884,108,554,166,106,344,487,253,358,698,10,201,818,714,622,930,227,901,182,864,628,520,156,579,943,832,257,530,904,187,157,723,440,466,798,352,365,514,672,617,433,364,531,552,330,109,328,327,654,642,579,579,624,395,170,711,686,158,198,148,307,499,502,354,838,762,693,695,548,91,636,945,871,665,932,720,97,918,123,196,233,153,159,765,251,246,900,202,974,929,356,608,591,864,966,908,882,223,982,542,420,340,219,922,943,941,964,353,728,461,6,908,977,96,823,363,774,325,353,635,286,739,586,408,257,162,706,268,87,724,815,981,361,532,967,972,792,699,284,488,100,2,830,699,43,532,145,663,845,844,675,695,584,506,550,800,800,982,265,948,22,746,460,858,681,894,653,81,854,668,194,748,54,352,499,43,786,648,149,268,162,719,654,272,906,63,780,431,32,386,102,472,10,86,628,12,653,436,683,290,960,71,830,737,757,173,144,681,41,286,173,315,713,778,958,738,51,592,271,932,328,977,493,730,217,22,423,442,663,401,469,482,779,299,701,189,424,860,605,675,194,435,866,93,803,138,524,428,389,874,838,381,128,80,82,303,375,388,227,191,612,524,498,989,134,548,206,734,503,82,857,443,158,207,571,642,527,198,176,124,417,545,508,603,64,428,789,71,106,58,729,545,608,100,789,460,443,866,517,75,720,87,494,496,294,679,711,569,606,669,960,7,110,797,510,721,98,82,454,850,535,292,386,945,236,917,205,696,662,372,656,310,860,149,990,542,286,869,823,499,177,635,134,756,777,625,62,842,397,607,458,43,83,232,601,743,344,872,47,89,441,85,61,527,819,765,90,226,886,312,136,48,222,381,815,508,925,582,192,777,685,500,247,523,18,95,966,417,286,522,794,681,187,437,703,871,333,209,756,304,823,218,756,928,372,396,269,327,118,751,958,675,431,156,910,398,614,313,762,349,972,455,811,397,339,307,60,170,977,812,861,319,391,208,899,791,599,883,9,153,103,374,568,686,358,317,68,557,972,259,991,431,64,437,671,96,757,28,937,645,240,398,337,265,396,651,544,785,80,869,432,521,426,849,853,799,59,14,510,292,373,453,199,553,839,35,446,708,36,8,327,984,636,1,21,471,659,275,402,284,935,437,801,437,746,594,604,350,159,101,829,883,237,266,227,685,261,319,890,578,309,909,806,776,42,668,961,684,496,888,707,658,627,694,834,828,969,647,313,371,14,24,394,992,982,219,534,834,924,587,678,84,942,219,450,904,167,822,102,361,380,939,574,581,856,788,114,261,698,4,323,126,893,213,621,699,532,80,405,250,870,228,854,735,918,395,608,803,24,448,517,958,0,923,454,292,728,667,713,222,38,798,451,457,780,272,543,487,831,77,178,619,521,142,710,465,899,833,379,783,925,923,287,72,338,569,724,388,653,257,959,457,397,975,155,66,944,661,28,73,352,686,942,316,127,476,213,433,586,232,408,182,437,479,579,497,911,659,833,659,90,515,100,204,324,46,457,135,267,251,725,634,356,5,66,984,820,883,300,374,729,893,246,945,16,887,164,584,784,599,289,999,34,616,133,676,109,144,285,733,100,638,676,133,739,173,95,189,137,343,320,447,12,21,63,597,71,257,298,488,791,238,858,379,847,998,558,7,34,812,536,340,769,167,360,405,3,633,570,366,725,164,422,263,154,487,850,946,787,271,597,870,650,131,87,855,766,491,22,238,855,149,480,946,109,783,412,430,373,510,105,270,519,765,57,28,118,648,24,275,353,474,347,473,569,857,903,955,651,95,893,738,658,25,532,602,547,166,899,473,958,797,859,202,245,829,102,37,466,80,142,733,665,431,623,753,381,457,770,123,535,368,864,35,553,626,358,955,644,566,568,266,723,382,51,700,929,683,902", + "74,264,928,479,970,790,468,503,384,830,657,434,671,321,78,356,877,729,303,186,954,222,526,574,681,449,884,855,814,230,36,556,321,606,466,858,60,857,204,727,278,779,85,382,280,560,437,937,131,628,646,134,655,689,389,443,748,819,861,672,280,671,132,174,58,621,591,768,830,665,67,316,424,556,491,914,221,673,530,522,281,908,892,125,306,782,684,724,77,232,61,866,707,500,233,897,621,669,950,485,687,196,629,319,80,514,450,824,829,147,750,662,71,860,414,100,581,76,256,398,138,602,497,155,332,920,631,274,309,657,838,846,631,276,433,296,605,196,582,419,295,221,97,883,740,405,735,917,530,254,623,239,38,987,115,564,165,446,116,65,835,818,621,484,450,407,775,71,482,528,297,483,35,987,644,680,176,355,379,82,169,306,990,814,708,727,718,103,450,419,711,389,926,679,380,345,347,882,41,754,985,338,276,595,881,182,138,981,564,262,261,247,200,587,112,588,972,947,831,805,452,634,347,902,533,766,808,248,100,439,463,366,132,736,3,422,494,721,393,972,692,97,877,110,3,47,858,885,147,60,844,983,381,489,730,413,235,936,14,509,569,528,195,53,376,669,726,797,930,85,55,852,637,176,720,552,650,974,433,578,830,442,503,22,537,177,817,735,253,728,446,737,748,178,244,560,328,513,974,412,961,262,296,956,940,334,533,290,243,66,287,867,811,138,51,45,305,802,153,430,627,464,253,801,978,546,456,894,448,830,434,154,481,505,10,714,603,636,123,269,541,542,833,736,177,580,482,796,460,824,86,194,661,435,824,902,303,537,474,182,988,353,563,871,704,826,266,616,968,934,491,399,483,787,128,604,523,275,692,911,304,928,919,163,975,878,586,440,933,836,884,559,823,272,919,897,710,70,233,808,628,414,163,51,595,465,420,376,437,652,652,512,687,359,696,434,271,112,270,310,370,684,760,753,116,13,967,135,358,443,566,391,752,778,453,632,515,222,574,992,524,978,71,731,752,401,103,986,9,374,107,2,307,410,60,844,746,82,496,508,824,398,527,999,662,632,918,61,800,160,397,793,843,17,187,352,508,453,495,4,807,421,344,558,814,172,641,149,209,334,898,116,755,848,782,62,744,205,138,752,284,967,771,446,714,816,372,650,610,225,375,681,764,449,852,203,216,341,902,935,229,703,728,493,474,254,468,155,318,162,746,645,140,588,806,510,777,780,563,717,509,464,34,993,358,35,434,540,926,735,587,412,337,150,555,408,193,620,7,310,214,398,581,587,377,874,671,519,476,892,776,602,200,452,392,715,303,333,909,680,312,934,327,611,669,488,73,166,862,468,216,842,497,379,234,82,899,438,655,687,739,138,600,940,202,976,438,889,261,945,619,39,933,428,252,579,267,780,405,51,36,834,681,949,251,977,657,505,475,375,869,48,825,135,344,46,363,94,665,713,454,199,483,769,209,55,257,616,421,236,795,88,65,660,828,745,840,647,223,855,571,280,551,751,526,476,264,312,273,157,260,44,734,661,624,498,885,694,498,212,718,515,257,585,839,760,565,315,850,653,461,587,553,389,550,246,526,421,568,438,72,963,110,740,907,737,195,3,457,705,957,558,265,338,767,11,201,120,533,90,802,1,419,564,861,742,128,906,522,711,39,304,298,711,763,155,259,122,122,798,888,390,41,722,198,797,522,355,163,506,328,164,873,923,0,118,136,898,567,180,749,866,101,363,534,679,950,286,324,776,11,550,881,344,355,766,27,943,785,900,627,590,366,446,933,242,392,714,326,43,937,250,284,464,62,297,663,833,333,884,152,681,774,516,734,531,546,330,114,342,592,287,9,841,699,373,612,121,139,405,704,1000,815,187,900,482,537,899,128,224,239,616,371,231,52,985,552,363,809,342,936,331,834,468,307,609,593,812,142,125,226,122,921,336,423,495,446,479,981,97,348,659,408,640,75,380,862,240,555,16,379,342,622,33,631,91,309,444,421,400,494,273,208,854,115,260,435,965,162,711,136,981,332,121,983,968,915,361,104,55,772,793,991,836,72,190,250,774,950,889,256,43,571,814,622,365,159,634,170,866,290,682,727,530,8,956,108,581,92,768,941,184,638,514,798,136,201,944,196,959,551,29,601,992,479,354,628,667,79,285,737,224,62,521,19,554,25,843,563,781,447,34,222,179,479,869,837,833,87,929,513,525,931,981,932,208,228,784,408,235,464,600,202,181,375,317,693,947,682,816,673,502,182,353,602,181,157,950,756,599", + "904,831,316,380,967,197,675,111,698,998,900,537,924,247,409,389,951,348,738,762,63,471,696,792,569,709,630,754,980,759,259,569,307,340,249,298,342,629,783,844,697,917,153,146,591,706,95,675,206,54,738,591,475,222,939,896,335,74,724,133,188,74,859,159,468,321,556,328,984,400,888,508,658,753,580,926,387,188,96,22,777,587,960,688,781,208,72,501,334,153,700,719,58,425,966,334,390,875,978,621,798,966,680,343,25,526,211,499,138,129,2,530,222,842,883,50,866,598,348,208,505,742,51,378,933,589,406,26,902,16,92,889,436,898,223,166,597,446,358,443,618,200,826,179,52,369,250,65,842,792,625,67,150,167,720,683,263,311,773,883,424,726,916,690,918,454,907,696,868,762,459,937,901,483,904,461,77,627,733,381,575,287,744,177,102,300,696,290,875,756,930,359,385,944,767,712,849,158,87,973,811,602,226,958,668,251,135,938,55,5,390,183,381,895,450,21,659,708,771,620,275,779,424,530,865,185,716,551,443,332,568,275,181,89,993,732,126,436,136,457,274,211,349,165,555,608,328,67,18,649,786,705,595,892,412,137,711,832,739,809,125,879,242,468,538,228,40,402,640,196,875,21,189,831,547,660,791,150,172,499,620,749,342,63,452,375,917,314,544,900,773,814,996,187,270,661,789,812,546,366,649,508,609,29,275,994,69,905,231,668,629,538,22,609,457,891,313,242,58,102,577,186,690,545,394,83,969,265,662,53,246,76,213,972,386,998,29,301,595,549,77,727,501,739,405,954,685,918,914,118,345,508,736,886,451,263,883,648,495,688,590,298,699,165,863,193,45,432,903,69,321,851,341,531,457,521,976,428,836,986,26,197,47,164,864,317,982,881,223,772,196,584,991,625,286,664,991,65,454,547,744,815,575,914,614,103,540,653,790,351,798,557,1000,667,955,42,84,125,466,281,209,486,349,907,162,831,868,513,247,385,38,925,939,588,459,295,7,380,527,49,820,162,927,285,217,869,385,921,488,457,704,23,376,29,344,668,515,115,154,575,183,386,136,435,79,926,408,469,944,72,884,714,336,669,708,89,601,999,823,233,681,524,339,97,233,558,912,156,669,785,110,742,34,944,898,173,973,100,15,568,558,312,748,916,633,609,752,438,330,23,810,72,607,533,902,781,838,856,206,833,203,730,800,997,99,789,549,468,976,276,889,411,961,638,756,106,323,89,492,62,807,88,875,205,807,21,114,255,651,275,501,271,148,852,9,637,189,81,413,923,549,841,607,560,832,494,621,477,325,484,322,591,679,639,650,337,411,497,105,498,817,207,50,785,744,370,120,878,412,243,349,959,873,605,324,207,994,544,150,949,589,138,431,555,670,455,688,506,555,352,331,261,388,522,877,534,138,420,210,560,626,355,692,274,636,874,522,162,875,233,848,1,932,965,114,678,722,963,702,108,698,43,566,29,673,684,80,519,345,543,730,895,29,146,75,207,887,130,804,986,557,187,134,330,395,76,635,916,917,679,839,362,915,156,934,510,198,794,561,493,44,354,590,357,97,819,276,167,343,94,129,245,896,795,799,604,19,502,164,279,831,77,345,178,881,963,665,431,716,986,388,175,571,882,216,705,298,465,222,537,360,215,365,38,506,458,138,171,273,593,343,682,119,762,495,757,388,765,267,613,721,103,626,315,264,579,237,193,669,662,401,891,179,454,118,0,684,412,100,163,777,819,815,268,580,114,617,49,838,241,919,458,526,369,35,831,114,625,152,516,518,871,237,45,3,147,639,724,823,21,519,324,519,737,530,944,179,259,351,889,573,558,365,806,999,419,895,120,442,680,793,911,322,380,208,914,440,989,434,275,616,531,116,715,287,489,369,76,784,193,27,111,595,468,595,489,269,263,773,258,614,15,126,811,349,796,699,675,568,423,962,816,376,817,62,593,894,839,224,429,256,14,695,121,351,789,55,555,580,204,734,385,105,991,352,82,494,812,100,870,324,918,100,668,125,358,490,736,579,665,52,383,697,68,141,208,539,275,874,253,974,928,5,312,38,329,709,99,611,430,540,875,16,498,630,477,867,352,929,289,381,471,876,729,272,98,681,983,320,623,861,252,937,626,668,837,980,682,532,660,477,962,415,919,237,241,404,21,773,486,784,436,798,709,218,833,230,784,238,784,70,670,438,267,779,328,470,423,837,786,413,317,182,153,653,813,80,962,227,995,835,81,794,238,725,867,488,247,499,628,253,721,262,464,698,988,356,43,715,521", + "270,235,325,496,711,263,927,45,777,692,533,392,279,332,538,748,248,231,935,565,216,468,896,100,49,245,896,596,469,98,831,826,491,256,280,532,818,835,833,285,114,441,345,249,108,254,446,46,616,801,205,165,150,643,700,208,116,21,10,411,59,546,495,317,575,323,415,72,223,5,201,354,635,669,992,448,412,602,140,129,514,502,898,691,87,643,520,948,347,199,713,154,388,360,422,23,949,216,983,308,463,634,630,178,468,490,702,410,735,607,469,893,384,865,44,515,541,562,556,425,125,240,82,189,764,213,68,399,995,933,37,377,221,658,937,923,373,474,48,156,898,922,347,18,317,979,84,572,640,227,295,71,860,724,298,687,306,970,960,656,775,965,312,922,15,260,475,75,216,575,613,21,804,60,853,744,494,544,812,958,142,281,495,356,133,229,581,245,31,260,55,240,877,375,422,722,497,525,143,350,283,73,793,171,868,494,104,244,851,734,762,208,147,396,728,105,377,754,948,398,313,373,671,807,653,369,878,398,547,717,6,772,259,403,709,913,394,649,109,141,850,89,362,413,284,815,252,71,698,999,240,94,556,187,483,293,273,941,543,262,172,816,376,446,694,63,501,573,370,499,147,79,652,745,562,29,624,797,161,610,338,215,455,836,510,512,35,456,664,72,637,732,68,36,410,506,856,726,142,310,539,463,508,758,677,710,816,827,668,792,254,792,32,648,468,85,637,453,524,243,977,548,992,369,655,418,778,143,400,211,168,584,689,136,865,149,781,78,651,86,969,617,238,619,110,599,780,618,13,355,973,230,100,643,672,52,414,667,975,895,599,426,219,23,632,979,916,704,151,565,722,467,995,234,996,273,936,134,604,277,956,226,442,449,766,497,678,1,62,707,485,248,83,270,633,76,494,214,561,866,657,377,470,228,482,683,62,993,956,827,51,331,506,256,661,722,616,402,119,434,570,619,199,956,93,56,549,359,541,714,876,776,470,112,886,649,471,804,192,477,384,834,936,671,842,627,914,413,617,226,574,918,797,422,909,3,101,739,597,942,37,16,658,752,927,542,509,147,854,595,502,777,973,728,469,986,521,996,509,157,452,231,618,298,750,407,299,718,505,235,64,47,965,863,644,355,881,571,559,335,821,912,571,270,251,23,271,165,183,920,443,108,215,527,961,810,190,215,765,136,163,96,801,390,836,194,240,237,838,518,71,438,80,312,922,64,575,178,196,951,424,654,985,830,616,641,136,926,284,681,854,824,283,91,60,242,956,518,245,266,90,181,594,582,125,450,380,35,603,411,164,197,180,974,896,910,848,687,12,764,179,607,923,975,651,440,243,379,277,90,242,582,835,309,351,546,567,303,810,191,473,771,393,888,159,119,353,446,204,638,996,170,383,922,336,401,939,179,203,648,44,844,830,983,418,496,675,780,114,520,395,605,121,723,856,615,200,863,475,910,529,576,441,512,635,109,519,511,272,772,967,665,452,609,501,366,436,665,124,850,615,526,390,299,637,438,84,155,903,319,537,237,628,691,201,963,437,523,747,646,457,442,219,782,394,437,312,557,214,458,374,746,525,713,799,376,157,195,106,679,520,568,628,658,639,211,179,458,468,132,730,406,36,373,273,56,28,845,163,833,928,979,477,769,339,818,838,893,888,554,182,132,984,648,18,269,576,522,436,665,638,234,563,110,236,375,904,588,332,662,497,156,859,292,136,684,0,248,460,208,768,804,772,171,554,226,694,748,996,504,774,380,121,364,269,925,629,40,552,742,37,277,696,320,584,313,442,943,736,637,379,646,246,225,442,608,511,409,297,882,404,708,131,482,567,14,766,692,15,480,76,146,738,728,468,26,502,814,432,236,904,216,190,254,688,736,415,412,330,569,596,592,566,407,170,105,345,202,339,185,446,194,737,173,121,756,242,37,660,727,540,993,141,864,356,952,315,546,830,839,783,656,536,177,67,340,192,115,95,155,201,55,580,290,260,537,876,21,826,566,429,563,571,399,195,436,514,46,198,778,645,406,699,15,152,716,732,449,647,404,479,527,929,387,574,68,602,334,925,759,816,469,290,757,66,218,889,552,579,857,376,377,529,91,651,322,3,430,728,907,929,779,467,543,944,231,741,404,915,71,301,481,375,129,961,582,586,229,754,627,15,776,720,946,697,934,337,801,901,714,606,93,497,94,191,571,926,404,711,265,224,605,382,346,334,264,643,705,143,682,574,27,786,242,139,596,918,73,537,914,58,799,89,3,588,780,291,148,143,597", + "677,162,173,455,876,511,897,553,635,788,32,273,950,302,924,268,481,842,85,457,103,968,732,992,31,807,20,701,239,438,896,208,1000,907,759,824,362,118,297,731,57,412,170,968,46,906,811,966,729,735,343,629,389,220,136,353,716,772,831,151,182,869,418,366,85,49,810,567,978,204,771,894,824,958,470,178,37,977,634,781,470,451,2,450,604,350,204,352,372,118,13,101,69,889,82,910,629,926,743,352,988,725,143,26,614,854,323,313,915,939,549,164,632,763,124,90,442,141,815,477,895,100,278,394,513,11,196,785,124,899,805,507,121,107,23,516,216,295,745,980,267,181,773,962,247,157,730,531,128,517,230,124,768,357,873,417,360,745,744,133,279,191,947,457,661,23,185,567,410,903,142,58,405,322,655,704,798,105,325,329,645,497,699,762,858,320,530,60,142,330,231,853,122,868,361,111,171,697,917,271,994,969,600,557,403,124,917,576,450,420,52,554,919,737,703,906,88,36,56,911,275,286,860,573,155,750,73,448,920,818,159,716,230,926,76,986,150,338,49,663,824,317,755,356,109,643,711,309,55,380,164,758,666,50,840,998,720,142,674,372,472,157,199,245,10,405,189,415,174,831,738,703,544,405,454,803,641,721,248,577,552,536,981,769,770,450,915,905,329,205,153,479,100,727,83,879,737,845,771,440,822,438,542,575,379,821,13,676,753,239,572,624,152,244,57,528,968,352,565,953,523,759,355,209,955,502,625,65,332,964,429,224,959,631,136,169,334,354,957,250,595,678,364,878,832,995,792,5,379,95,927,558,549,847,473,259,367,140,771,320,391,365,565,986,338,222,805,758,867,573,546,932,973,482,788,493,243,590,339,863,414,550,687,883,199,335,77,843,102,619,17,939,870,484,589,283,63,450,485,530,643,155,168,323,892,295,830,802,114,686,477,743,767,895,143,817,586,876,872,489,338,829,532,89,634,767,411,334,774,793,252,975,293,31,950,635,140,276,222,833,476,28,466,671,882,958,225,210,997,27,617,762,601,808,972,271,953,583,8,83,143,374,178,612,53,464,328,241,718,941,6,561,114,248,729,51,227,971,408,355,672,357,737,756,156,478,175,509,705,706,561,250,976,512,611,460,706,903,675,964,620,344,814,929,935,797,138,923,597,549,370,144,62,291,574,416,738,613,615,183,914,983,943,749,643,215,528,890,61,770,424,57,404,581,647,188,984,663,387,158,65,127,92,885,397,567,385,360,396,779,224,10,408,297,63,449,80,420,900,784,812,205,157,414,974,622,795,315,705,204,421,181,678,114,625,64,904,655,799,834,182,364,858,158,347,399,890,732,49,927,160,137,472,454,813,633,905,274,795,1000,83,166,5,212,654,105,725,98,237,893,346,877,683,672,332,877,252,61,430,162,536,911,604,682,382,384,154,802,103,12,885,719,619,344,511,159,746,589,458,114,914,875,873,797,679,610,457,642,464,79,161,286,612,278,721,25,531,295,52,267,526,236,272,17,961,318,785,340,532,784,315,337,572,124,208,235,850,31,914,759,515,97,418,130,836,180,130,74,37,880,429,869,482,28,358,435,598,304,424,786,914,338,895,27,804,466,632,189,444,458,387,808,497,671,372,351,494,539,769,251,974,792,853,908,161,65,875,456,156,183,91,518,231,277,455,700,332,519,300,583,80,430,445,593,317,855,480,578,727,536,926,903,500,728,898,412,248,0,488,845,71,653,857,366,915,231,8,333,294,7,637,182,982,314,847,581,942,661,6,408,114,748,158,896,560,794,178,880,442,537,928,43,870,216,436,495,998,230,756,209,974,605,727,986,619,397,151,202,866,805,976,226,973,377,671,174,614,377,319,580,588,766,249,636,300,161,705,844,64,708,960,950,136,40,394,820,508,960,479,345,52,682,490,99,583,715,159,588,764,759,671,337,107,172,507,2,782,486,546,400,81,74,395,47,759,749,134,605,678,571,715,948,347,309,424,28,570,304,525,182,38,644,719,587,460,848,820,267,309,421,647,567,223,756,997,485,262,978,185,991,549,937,675,941,727,703,937,368,16,473,576,170,723,981,513,869,717,712,992,834,342,916,735,130,801,544,256,521,337,229,712,154,755,548,160,803,824,970,685,30,46,537,903,727,505,657,240,42,917,815,831,273,70,901,930,773,700,184,885,467,964,9,778,863,533,903,681,815,315,528,442,288,505,440,959,448,203,96,915,434,673,742,853,539,674,908,742,12,674,230,172,250,572,614,194,524,953,558,106,176", + "787,683,52,615,786,936,216,782,548,113,46,789,482,927,89,585,978,926,377,961,460,719,6,431,828,665,201,557,10,59,981,741,369,767,843,88,742,972,564,449,353,809,350,936,76,653,86,590,533,307,975,420,540,35,664,6,93,14,305,682,308,891,189,596,806,783,514,480,512,186,152,368,161,132,423,453,162,75,178,336,430,473,748,811,553,198,863,26,156,983,984,124,779,479,129,539,124,201,375,862,273,433,578,659,156,682,853,106,970,211,729,402,480,506,476,979,159,340,971,285,171,61,104,946,926,384,779,303,891,426,314,842,563,394,647,438,588,795,789,786,812,156,425,447,518,592,890,88,553,358,223,246,382,122,230,145,60,225,731,796,344,266,924,784,118,252,963,259,423,180,317,223,776,376,308,791,564,977,982,11,744,696,319,114,737,809,137,843,234,278,204,445,322,180,204,67,512,760,329,350,208,954,885,526,69,563,982,267,479,462,240,51,822,91,718,373,235,517,903,2,684,840,354,18,510,312,333,948,259,303,904,73,652,24,566,907,854,120,621,394,264,634,605,270,436,177,875,425,304,167,387,470,539,105,720,61,418,112,419,922,785,15,613,146,433,507,866,610,286,182,988,543,938,529,164,268,450,769,925,38,799,770,276,144,750,518,135,573,169,330,627,342,339,865,911,564,827,456,747,361,543,853,608,57,349,674,842,592,758,97,753,270,535,837,544,768,997,949,41,208,295,653,209,212,154,327,873,705,358,754,589,973,148,65,710,510,206,601,233,141,744,306,468,681,702,289,946,726,487,782,617,718,559,980,393,970,514,723,561,38,389,861,101,324,470,584,270,896,594,921,509,135,101,806,983,971,785,814,531,4,622,810,267,136,959,778,847,423,769,802,489,896,313,531,791,927,356,377,64,54,393,25,726,135,141,183,808,772,246,163,987,676,970,621,320,106,207,472,842,198,438,472,783,50,530,22,269,967,39,820,80,383,936,369,756,23,134,98,947,372,364,995,573,809,329,252,857,332,789,850,196,131,680,880,194,493,55,804,655,975,728,617,490,447,508,143,823,642,779,75,384,983,687,167,59,589,776,431,183,249,620,467,745,324,295,785,178,527,422,214,668,471,764,545,255,81,183,629,391,457,852,62,254,325,805,914,378,112,554,100,492,785,760,330,320,972,840,555,50,892,645,318,812,448,747,430,104,745,864,471,333,603,595,175,309,907,85,274,619,363,276,737,962,975,677,218,542,541,822,345,367,644,389,767,860,28,945,680,283,561,985,810,439,204,103,602,134,203,477,962,44,46,277,357,69,204,133,829,213,577,766,374,332,127,316,903,665,419,6,602,14,417,354,506,746,961,864,78,378,785,242,84,77,934,648,228,747,627,982,374,604,422,305,605,884,453,368,264,477,811,447,771,701,38,24,551,542,804,100,967,665,141,202,859,174,309,620,83,934,277,77,797,535,281,459,907,59,297,320,185,875,619,213,291,534,121,937,648,692,977,379,45,351,165,340,373,733,687,736,267,282,152,799,666,227,41,604,623,688,558,364,833,695,108,521,974,575,951,896,862,218,564,432,727,315,207,517,74,459,144,180,925,754,992,360,60,423,777,851,116,532,576,39,81,355,461,931,592,508,283,528,519,215,951,230,311,327,229,409,815,463,542,95,479,602,151,597,190,128,722,838,755,362,836,946,560,773,898,4,471,793,120,301,667,567,100,460,488,0,836,651,694,84,72,350,358,847,342,10,201,418,742,40,883,486,530,494,530,371,418,589,290,265,862,356,20,946,737,685,976,618,913,62,927,428,816,127,544,347,28,479,152,998,420,230,698,293,84,393,892,518,480,301,798,650,939,98,101,598,937,643,671,315,666,124,71,678,20,190,687,252,830,668,748,112,807,25,420,604,281,938,66,729,506,691,689,587,194,57,99,930,209,529,335,605,312,322,455,486,439,627,963,531,721,9,616,442,768,119,361,734,701,577,418,197,425,189,390,985,547,850,738,554,210,581,571,418,803,954,916,254,685,551,82,715,728,892,427,88,634,478,374,901,734,141,727,388,191,796,981,622,577,799,259,583,226,778,729,569,362,600,25,636,58,386,909,768,887,240,656,357,563,742,37,299,199,304,288,885,462,394,332,3,303,501,670,51,867,463,759,962,945,458,931,934,230,386,163,276,222,732,15,154,193,154,868,525,839,834,77,365,945,527,166,267,704,838,845,379,401,229,946,965,341,913,127,94,781,428,772,98,132,131,92,601,768,154,481,647,112", + "884,648,820,750,423,938,734,755,783,410,190,263,725,556,600,119,408,261,766,107,335,352,66,787,438,279,295,713,635,113,436,276,419,644,142,252,102,277,533,470,629,611,908,821,993,320,935,374,686,302,175,472,678,453,351,901,440,555,797,843,345,577,324,81,868,797,847,977,822,744,544,5,252,889,644,696,80,529,506,559,570,613,829,979,546,904,89,881,738,418,330,652,570,495,523,634,852,251,416,272,236,400,782,521,954,829,16,539,967,776,936,974,823,264,677,523,466,427,24,500,185,814,49,339,435,116,286,182,223,958,592,629,221,914,10,126,742,160,83,249,127,335,460,222,753,404,899,991,307,959,229,106,437,918,271,982,920,993,756,358,681,974,345,741,447,63,548,686,770,482,274,505,222,152,707,44,394,98,299,886,597,845,509,443,87,172,688,899,56,917,326,289,220,642,270,664,695,742,830,335,71,231,538,716,839,313,527,222,75,823,596,329,478,25,86,283,866,252,23,734,773,692,579,628,398,664,263,655,739,967,377,903,623,827,529,824,550,204,233,584,52,184,516,527,86,923,201,67,427,404,685,869,502,487,866,54,956,550,25,206,238,860,645,558,341,867,736,49,150,88,164,494,78,602,343,808,342,265,583,534,521,799,459,368,161,489,671,388,90,424,823,747,967,485,743,328,657,520,160,991,947,650,330,83,73,521,344,409,905,511,818,153,861,645,685,628,450,875,331,80,448,125,776,517,631,154,187,737,755,757,730,203,197,851,972,737,21,995,828,914,692,381,918,476,788,379,492,111,545,201,960,739,700,547,97,37,821,12,543,326,172,455,787,779,651,174,514,240,793,518,720,374,562,495,949,929,833,902,780,945,288,195,846,293,395,60,390,692,909,193,399,21,515,26,229,435,663,480,174,372,850,304,638,643,621,337,737,218,143,723,909,24,343,718,664,16,792,106,251,518,617,808,638,543,134,69,290,519,647,985,360,456,674,25,911,264,60,202,46,174,397,891,811,991,388,776,753,791,935,598,676,181,573,987,996,832,535,10,42,846,580,269,457,994,855,912,287,786,662,915,782,5,464,49,632,947,176,424,596,370,614,188,513,981,822,792,749,301,70,192,978,877,989,860,376,500,238,864,31,530,743,996,510,632,919,646,970,924,323,724,374,24,347,510,885,59,108,293,218,962,189,833,828,159,874,81,893,261,774,474,527,319,578,589,273,866,845,300,94,463,833,977,197,921,267,454,644,684,892,398,986,964,576,311,507,278,897,331,32,450,566,291,691,785,459,930,214,15,378,780,426,348,774,983,702,410,292,787,573,290,718,675,238,860,882,789,594,760,763,577,830,345,548,992,788,829,32,940,988,430,442,243,982,553,445,497,169,42,985,969,219,416,354,252,16,264,663,557,837,590,269,315,27,711,678,180,103,128,991,452,182,690,83,851,841,72,681,781,929,360,144,187,426,143,657,629,876,328,456,671,465,463,382,462,298,612,116,139,401,290,145,394,740,975,256,811,247,438,212,33,127,24,169,140,400,521,82,427,977,728,917,409,120,489,784,540,416,715,358,241,358,160,119,727,854,844,964,418,574,740,444,34,746,476,392,810,333,224,882,456,354,931,67,660,316,69,922,906,160,609,309,392,726,399,912,227,549,124,607,920,570,49,580,533,511,410,209,2,747,671,147,51,695,78,434,991,646,321,986,421,371,877,252,713,180,163,208,845,836,0,760,274,486,45,726,791,227,240,602,452,880,123,166,44,840,749,259,651,238,215,313,510,438,77,434,849,769,53,461,999,170,587,635,251,994,284,414,793,312,202,773,648,685,838,55,140,511,78,259,924,291,179,720,679,80,250,331,445,559,345,750,158,799,426,724,56,830,528,781,639,714,843,123,583,481,288,143,368,398,586,634,868,703,40,363,847,99,25,493,324,298,163,56,633,97,295,420,802,504,873,748,652,293,780,653,939,629,845,509,426,635,510,236,649,554,388,847,995,167,100,895,488,462,251,222,398,677,950,632,604,836,817,284,43,838,406,315,836,460,869,223,233,569,902,881,126,358,773,566,345,505,195,258,71,493,326,701,350,949,884,690,546,52,508,628,487,838,428,651,417,542,319,816,983,314,216,798,934,931,137,932,212,88,152,611,85,735,634,51,195,919,622,977,916,488,21,292,335,574,273,780,192,84,498,647,513,449,543,945,72,80,983,927,295,984,734,692,550,966,251,398,165,674,382,911,747,136,535,486,575,443,866,320,120,619,252,385,60,525,469", + "287,530,394,957,412,427,162,233,382,24,617,151,747,960,101,907,276,440,114,822,784,895,194,528,395,830,655,952,339,778,858,790,280,760,504,142,387,654,37,578,273,601,304,657,272,758,125,247,323,808,904,355,180,106,164,503,546,365,550,675,675,508,356,855,199,442,915,642,71,497,381,15,173,758,889,455,833,168,795,973,822,730,30,391,78,750,878,739,903,69,557,746,318,76,343,580,983,205,338,258,383,651,148,824,31,513,840,257,177,347,963,59,152,504,959,519,515,582,949,565,7,472,796,245,845,395,228,703,426,349,734,569,415,944,113,343,42,304,8,278,505,427,651,479,87,790,305,597,778,243,742,219,170,253,181,219,720,513,79,729,48,327,720,127,746,897,653,220,551,573,416,719,156,977,894,193,461,789,692,764,936,442,31,417,365,726,311,325,206,97,417,430,302,550,312,640,427,199,731,724,999,444,783,147,353,834,386,265,436,552,202,602,967,510,341,723,342,654,796,219,177,608,179,994,851,847,9,153,394,499,262,199,805,479,210,80,475,263,334,659,130,771,488,903,439,466,78,144,508,701,439,791,786,860,728,756,39,609,32,792,928,286,924,348,531,404,22,412,248,779,868,767,418,85,374,288,297,409,613,467,901,262,100,392,605,339,474,173,476,856,57,292,621,96,490,366,104,657,421,565,223,915,472,237,859,774,245,977,406,742,391,102,211,802,780,234,784,708,696,963,2,408,741,20,407,778,950,403,834,883,989,590,606,595,842,972,817,860,47,64,705,888,334,345,910,833,952,415,893,802,30,451,447,735,97,794,312,162,515,870,138,968,328,297,736,423,295,152,275,820,235,28,967,47,315,795,222,453,288,733,123,316,472,431,193,241,614,916,379,703,996,351,937,997,55,393,599,574,211,460,628,559,651,629,959,642,467,346,976,272,679,667,733,548,360,105,571,845,380,314,17,676,534,750,252,363,707,371,604,210,196,123,151,132,389,696,956,479,447,589,130,672,589,607,410,802,915,309,935,939,129,369,238,657,34,948,19,951,405,459,605,419,497,585,553,694,142,479,181,754,151,128,880,652,913,885,800,974,777,688,899,212,22,655,451,124,974,150,477,965,338,733,350,51,258,412,468,148,267,395,620,652,761,105,820,328,842,218,196,235,854,555,598,327,265,480,418,370,285,224,734,76,946,216,605,273,932,430,17,212,895,485,13,242,36,857,947,999,216,516,792,664,592,496,65,749,59,116,586,125,820,963,349,237,389,369,321,917,757,603,388,583,79,66,971,328,128,66,679,810,55,776,904,148,526,166,907,82,374,447,684,794,837,514,19,75,27,113,102,671,406,21,114,829,165,65,527,147,40,718,27,912,233,18,512,702,603,781,859,500,547,129,659,231,70,774,468,580,625,562,415,833,436,769,373,475,960,534,851,174,574,876,387,390,740,87,661,655,492,124,7,906,160,49,70,205,204,414,282,658,803,822,686,187,315,730,622,296,733,517,911,988,473,725,652,406,224,287,897,12,128,557,722,479,66,544,266,432,716,358,273,197,38,788,577,830,140,751,715,660,367,810,670,956,900,991,729,197,896,350,249,193,966,456,420,246,921,400,400,348,614,240,611,658,292,522,299,110,348,197,964,693,604,840,398,388,583,12,666,106,549,856,828,920,520,398,640,665,96,951,371,10,2,342,563,599,399,253,103,482,492,289,290,222,749,777,768,71,651,760,0,873,225,831,755,896,919,403,631,230,749,10,929,382,845,931,75,71,663,278,555,424,297,677,19,926,463,889,621,657,735,557,294,503,892,449,696,392,169,743,273,912,67,458,54,155,865,9,926,759,42,375,746,160,947,278,912,509,591,978,97,606,730,413,408,479,396,873,624,446,690,830,147,779,780,946,805,26,823,101,447,261,91,502,310,352,55,316,815,895,622,221,460,337,748,721,163,278,337,275,313,808,880,38,750,232,341,885,881,229,914,871,882,249,401,680,79,165,671,199,680,812,202,521,513,968,512,674,178,547,301,818,19,780,683,690,73,840,527,849,821,827,319,585,427,352,196,404,83,800,566,377,570,452,526,717,901,195,635,116,687,503,54,459,579,35,789,266,62,939,673,71,736,284,846,362,860,378,499,893,137,670,494,632,579,878,287,919,294,547,171,490,357,93,282,940,676,736,535,131,338,795,234,155,535,852,502,862,820,567,257,91,737,669,39,313,775,266,132,486,546,484,4,245,457,228,688,16,237,489,367,258,868,364,316,995,397,598,778,267", + "569,873,410,397,254,718,769,493,713,303,775,513,700,264,773,598,404,145,966,19,440,859,639,321,484,450,253,932,245,760,117,291,522,238,265,327,855,904,980,644,993,720,874,492,107,310,111,293,489,720,80,915,181,923,308,769,630,695,782,514,284,358,269,11,848,541,295,510,729,621,345,65,170,204,800,406,14,695,735,263,60,107,952,197,425,925,886,837,957,360,445,138,328,912,558,340,442,434,209,864,365,175,800,182,434,815,692,468,156,471,892,148,168,249,992,182,875,284,820,941,426,541,334,420,373,210,372,99,600,358,357,888,667,319,563,309,317,967,925,266,913,519,919,205,121,740,864,553,95,886,369,871,813,631,772,865,529,985,63,678,942,21,328,68,881,613,83,563,723,568,615,758,15,528,344,56,357,663,220,297,15,164,849,63,856,186,292,115,707,489,611,441,274,493,15,452,541,732,527,323,278,304,458,358,911,72,959,895,673,75,329,819,142,689,642,459,917,510,699,798,652,866,772,865,337,199,523,739,558,718,365,986,563,317,569,744,462,44,69,494,97,231,201,919,435,365,318,768,968,22,741,223,857,768,440,274,48,331,634,696,71,990,958,469,528,23,171,975,35,626,119,689,369,830,661,108,910,869,915,55,137,881,43,384,570,382,388,934,817,35,163,393,76,533,793,914,334,21,697,586,757,436,712,719,475,43,734,900,855,919,404,738,377,123,750,600,978,45,359,703,648,91,34,450,708,986,639,590,259,114,350,876,680,92,326,757,645,329,428,298,78,914,845,26,152,532,464,248,598,510,742,780,473,270,192,137,151,287,687,254,472,908,981,921,869,213,604,483,647,964,347,277,733,1000,439,624,394,239,807,282,114,738,895,821,197,679,118,575,688,97,772,917,836,80,553,404,348,294,110,584,568,570,777,960,117,48,822,257,670,94,617,475,751,537,806,523,262,219,299,92,663,445,766,502,217,916,843,84,357,79,954,394,517,435,57,949,108,636,768,360,340,195,276,827,161,763,624,626,533,453,781,535,705,356,373,146,695,513,969,191,54,311,895,439,990,50,836,662,460,894,663,36,242,250,501,4,848,655,572,381,716,208,867,848,861,58,275,384,992,82,592,169,701,226,366,602,538,367,270,497,404,621,453,985,39,855,237,817,447,140,27,169,532,540,51,45,221,943,174,917,379,856,636,569,722,324,631,224,976,648,168,186,980,686,874,990,895,507,637,385,897,374,932,341,249,79,385,432,619,989,554,118,45,429,9,201,549,512,425,94,967,284,446,950,575,761,498,963,857,649,841,440,388,953,198,488,733,673,891,763,487,256,536,180,359,421,749,751,412,864,144,681,610,4,183,474,219,245,92,820,461,140,574,147,468,219,488,114,428,66,771,464,819,332,743,596,637,451,889,782,864,869,533,600,576,72,274,711,714,150,963,416,169,630,724,687,137,929,959,756,382,218,306,426,147,881,715,318,675,488,657,199,535,809,385,835,572,210,66,28,850,458,550,406,160,533,22,545,65,25,344,24,926,769,647,542,27,674,301,111,197,956,169,223,991,776,308,149,888,164,973,143,375,457,282,185,441,272,588,867,6,330,287,259,348,226,406,555,260,491,536,817,261,995,128,925,937,503,555,810,693,15,317,343,988,644,61,904,449,44,459,752,455,946,634,889,434,533,263,12,171,972,714,485,889,268,180,119,277,309,317,238,223,38,866,819,804,653,694,274,873,0,829,940,849,655,856,157,43,931,324,106,653,924,970,869,375,178,832,227,182,470,671,510,871,160,641,900,373,513,7,492,981,39,641,19,689,482,934,370,830,662,302,427,313,388,479,513,240,203,342,894,428,467,374,164,363,456,86,782,554,172,45,308,108,13,577,272,994,871,578,271,429,833,201,584,991,77,538,588,69,235,575,70,131,210,616,831,701,330,898,394,210,729,62,186,587,243,196,263,633,181,320,941,77,513,515,858,273,946,462,64,113,341,263,653,316,359,196,563,853,932,242,546,519,158,465,438,883,310,607,120,61,664,664,437,858,43,530,872,866,369,910,330,256,871,938,124,775,913,896,411,644,555,727,151,490,754,182,962,297,85,943,943,167,748,950,70,735,216,742,739,286,682,302,389,365,986,22,612,953,787,655,936,109,747,959,797,93,536,567,589,658,294,15,857,361,59,551,949,784,999,269,371,585,683,812,166,678,672,150,373,790,820,787,808,24,532,113,167,577,819,630,686,342,626,797,152,292,312,251,457,602,855,428,393,977,517,574,460", + "182,286,759,293,107,186,996,939,672,616,959,605,732,756,834,879,892,354,575,773,390,733,16,122,641,319,281,386,892,622,941,78,496,278,397,132,712,497,448,799,456,401,699,436,868,195,763,556,454,190,749,417,717,180,325,309,973,965,941,163,891,817,901,861,879,403,364,390,902,726,917,385,932,516,480,170,340,266,274,503,371,892,959,799,488,612,368,698,151,881,123,595,898,205,913,898,359,69,565,55,356,225,430,65,722,596,198,422,818,801,692,661,892,136,832,965,173,88,623,929,108,394,751,590,566,154,585,131,989,512,610,163,834,689,186,944,788,722,609,483,486,926,835,738,152,267,779,493,605,264,181,868,263,216,774,761,160,958,543,880,630,327,281,852,927,148,775,59,899,368,298,964,882,582,258,301,306,602,395,393,555,90,933,73,157,995,44,168,227,401,339,284,94,261,291,288,54,255,416,566,28,141,195,605,774,504,221,318,48,213,170,667,632,939,692,421,168,929,259,636,373,510,102,962,336,941,870,930,149,433,141,812,607,406,361,828,159,865,787,801,852,376,786,65,794,250,386,660,112,254,884,406,197,160,39,759,168,708,859,383,367,180,249,215,801,925,467,827,489,43,864,585,244,745,277,600,77,80,33,198,42,253,90,745,675,761,776,596,983,798,785,842,816,22,452,665,580,625,767,415,585,174,357,188,568,402,651,244,953,358,768,826,707,412,215,144,225,476,994,485,531,2,965,582,706,727,729,935,76,5,795,278,51,862,409,324,137,548,620,284,38,202,762,170,150,206,774,270,957,212,328,182,523,757,574,664,301,805,280,44,92,955,471,494,102,382,603,958,358,674,245,675,824,57,797,84,540,555,238,621,314,773,713,980,565,543,30,770,718,218,943,701,978,120,283,798,958,510,977,562,874,91,669,185,942,671,793,603,621,335,219,505,697,522,816,43,585,773,418,185,91,247,714,266,444,448,373,475,618,942,448,311,130,486,561,344,310,304,685,863,618,670,953,566,481,804,935,474,796,676,556,528,349,770,353,416,97,856,125,768,124,723,7,885,121,363,933,658,641,547,254,413,368,331,435,878,250,991,731,804,717,362,294,667,360,123,89,870,574,109,241,699,327,795,132,160,62,811,656,531,430,262,369,467,863,755,635,83,936,262,225,467,698,825,947,128,989,103,751,410,106,671,473,802,215,136,710,576,317,996,582,230,351,171,377,435,816,614,394,106,818,145,9,202,716,204,717,120,276,603,245,652,768,395,778,791,185,396,387,239,8,998,250,413,963,161,877,574,938,992,462,876,380,181,836,134,224,513,314,917,472,600,727,404,577,886,27,320,107,906,530,673,252,805,121,818,722,863,995,994,779,266,782,941,561,692,451,470,690,742,691,454,526,767,628,415,638,545,781,454,695,316,257,900,491,383,155,297,758,230,913,24,896,15,46,761,165,400,583,897,402,322,628,498,617,464,244,759,458,578,266,32,170,370,699,990,612,262,462,670,581,713,808,775,342,362,508,528,261,293,122,204,190,785,792,444,588,952,401,542,410,340,349,305,367,149,500,907,224,555,771,641,127,675,155,745,807,181,799,884,408,619,319,298,771,308,203,661,929,127,407,899,393,740,344,52,968,838,696,42,653,6,872,93,162,622,771,602,649,393,927,651,580,891,113,407,449,804,145,984,420,568,657,282,604,31,698,881,520,343,239,757,893,798,101,815,772,857,84,486,225,829,0,365,955,84,986,196,977,739,120,613,84,789,928,61,855,368,178,879,903,873,641,864,747,943,451,296,637,396,756,83,457,648,580,849,237,262,204,137,664,755,636,981,932,606,443,421,519,110,587,570,706,893,478,519,326,467,580,775,797,785,518,726,689,826,230,791,917,415,612,262,752,656,875,396,330,497,794,555,11,169,984,852,255,477,951,675,47,855,476,436,103,378,574,12,822,305,736,699,600,863,823,460,181,939,978,239,700,598,674,263,933,445,582,174,685,362,611,575,56,348,101,899,520,53,999,488,378,881,153,967,482,859,801,948,319,166,996,311,696,829,559,648,158,118,870,523,754,90,767,73,790,945,478,861,147,627,984,145,181,417,139,958,137,936,383,781,609,523,138,269,112,251,787,542,324,791,762,828,482,337,156,327,330,641,75,765,350,250,866,76,716,905,126,341,906,454,178,764,748,83,963,471,261,779,633,917,795,412,474,254,624,841,220,826,458,930,683,267,704,664,182,756,149,544,539,663,153,23,229,327,438,633,467,394,33,667,31,374", + "11,333,46,645,395,141,168,716,75,926,627,336,1,769,891,821,873,500,987,62,525,323,135,731,306,46,370,11,900,298,209,793,930,68,671,959,306,707,157,133,103,84,849,746,188,663,561,625,381,751,257,281,966,294,466,501,105,905,807,676,54,827,842,61,767,590,45,826,603,123,479,583,733,539,235,15,193,885,575,61,306,357,743,189,621,152,614,674,37,374,398,663,691,660,410,85,616,918,287,977,18,696,328,279,129,594,705,105,977,538,642,960,665,98,295,548,951,129,397,890,78,65,616,355,13,735,288,784,205,40,339,31,204,329,273,234,392,491,835,884,880,181,962,326,904,669,368,845,18,910,690,529,399,626,998,569,557,384,461,188,993,53,223,420,690,440,514,101,962,350,819,640,131,579,44,258,418,612,495,611,604,206,767,14,220,32,28,93,175,214,652,954,585,484,333,853,893,507,642,200,301,439,95,508,478,448,90,125,299,369,428,856,878,443,526,251,380,499,179,56,193,368,790,762,911,272,158,318,940,987,93,289,409,366,970,303,547,332,128,534,387,140,614,705,420,164,589,841,243,956,429,290,372,911,548,722,271,832,481,522,818,995,724,700,596,153,418,876,192,377,459,763,255,397,284,671,849,44,11,835,521,373,820,490,140,268,88,508,471,867,834,373,271,149,807,589,446,807,813,435,515,820,912,931,968,64,12,508,155,719,735,332,736,800,93,481,158,692,914,577,929,169,775,669,506,843,516,188,619,321,617,678,483,602,609,727,32,616,234,196,592,193,245,1000,609,557,945,398,749,53,770,480,958,115,69,174,847,77,729,86,71,524,480,632,438,402,769,147,4,697,421,23,457,438,684,665,63,973,271,236,294,416,912,158,739,9,858,110,838,997,683,842,114,983,52,11,997,985,149,897,292,456,547,97,700,39,628,829,102,861,124,637,376,521,950,359,379,439,93,241,662,286,466,115,393,83,875,692,99,612,388,972,274,570,715,481,898,460,126,339,710,280,243,980,999,438,211,194,802,563,363,743,533,874,129,877,420,230,669,678,791,600,479,56,115,346,741,434,72,74,555,683,791,394,719,202,849,19,199,619,484,928,601,583,390,41,802,64,28,885,665,493,783,388,926,308,960,77,166,519,69,69,781,859,275,232,288,51,547,938,846,791,962,784,797,588,574,975,139,437,455,854,704,81,43,893,961,909,199,366,679,437,396,979,547,359,578,561,666,613,441,131,95,578,700,586,366,109,278,742,846,705,922,811,897,117,119,35,725,174,858,668,77,95,947,870,686,583,498,607,543,156,447,348,82,451,660,505,990,769,506,909,557,368,464,603,991,836,509,501,152,921,723,59,492,593,975,627,189,44,609,927,193,76,65,209,490,33,462,419,313,171,414,414,144,499,645,927,491,704,387,566,214,171,469,301,715,490,241,676,830,436,582,871,138,233,213,731,753,453,861,572,807,448,625,754,83,312,187,657,631,823,915,571,162,599,614,498,615,629,253,686,387,597,849,845,907,342,202,709,704,905,136,77,996,324,655,563,538,688,751,960,814,690,888,283,867,537,112,391,782,963,476,215,493,868,952,437,414,180,949,461,641,62,264,303,315,290,992,610,585,658,883,246,796,939,662,485,809,128,466,876,661,758,964,680,197,87,771,184,323,493,814,781,649,862,372,282,368,963,879,878,544,642,320,662,36,84,294,131,428,88,18,451,363,268,171,366,72,45,831,940,365,0,66,228,213,691,718,657,528,412,756,143,316,321,544,780,356,790,523,4,980,775,249,347,366,710,49,829,472,161,169,935,265,299,253,306,308,348,653,381,806,249,296,248,557,576,32,640,353,30,382,198,500,417,350,617,168,467,521,924,483,680,641,664,862,482,413,80,261,798,500,802,688,711,387,619,376,888,933,238,874,504,368,819,306,799,577,933,159,800,943,960,600,967,512,122,53,339,770,551,484,798,3,322,858,809,687,892,696,139,35,951,668,925,729,822,104,831,965,265,297,211,564,366,600,158,671,420,699,550,182,173,637,510,740,598,180,463,782,161,582,787,88,679,86,890,160,363,796,505,616,111,375,579,309,945,911,34,48,814,355,960,43,432,824,188,392,428,439,115,567,501,432,85,530,491,293,194,31,588,382,497,74,64,160,90,547,999,952,31,910,255,285,604,460,915,172,18,679,30,455,103,559,898,48,103,127,672,305,523,264,163,862,436,909,590,563,198,436,264,436,766,234,299,531,958,101,519,788,354,855,248,84,18,193,940,348,613", + "604,221,246,50,785,274,859,583,73,951,376,329,511,472,714,316,520,551,152,756,609,530,997,643,97,428,281,682,654,308,31,606,923,388,319,220,944,377,490,300,696,525,929,641,675,85,924,877,221,484,199,756,868,867,172,310,197,7,257,872,368,37,499,14,76,589,481,226,928,263,31,410,848,733,537,160,443,30,999,416,471,7,255,56,16,860,346,716,385,697,620,573,888,514,298,815,142,489,877,274,778,795,989,53,465,109,173,26,531,188,569,373,109,281,798,155,784,397,51,783,766,833,495,982,522,758,122,332,804,984,410,745,771,450,233,792,310,859,488,763,957,101,202,252,841,739,570,840,527,86,815,817,693,749,668,516,810,808,702,585,438,877,278,375,358,767,729,973,545,533,463,449,762,100,643,612,716,580,866,525,578,879,417,183,317,656,267,338,191,931,338,474,759,629,609,992,448,585,8,353,550,390,937,656,7,647,121,872,283,628,534,13,697,818,422,242,872,619,149,480,765,446,182,763,650,793,738,507,667,438,781,746,691,844,852,791,422,458,573,108,256,911,835,519,833,322,456,643,696,132,541,938,560,430,829,178,31,473,939,465,42,470,222,828,946,381,260,83,832,58,338,286,925,451,601,475,381,474,732,251,354,47,109,438,8,457,185,85,593,512,625,84,255,444,295,84,295,799,667,801,249,919,218,223,948,974,732,529,508,135,959,43,307,483,41,949,46,68,12,523,59,701,897,186,280,392,324,987,697,190,839,629,552,906,810,573,513,847,513,430,767,284,118,58,436,222,423,228,411,614,862,908,891,611,512,504,654,179,859,584,174,618,677,942,284,661,619,409,546,628,833,545,831,70,484,656,338,10,694,912,539,372,170,853,824,705,42,265,683,178,581,26,414,566,977,942,809,427,825,487,280,834,748,936,8,274,27,742,211,192,781,665,826,198,739,915,326,470,752,880,882,850,35,131,376,241,242,761,668,703,684,939,580,608,934,154,586,322,225,960,902,580,538,41,155,693,745,988,508,751,373,500,166,359,381,106,447,914,210,700,997,515,466,510,459,656,988,317,146,836,766,831,13,365,960,110,562,262,39,622,469,630,833,545,963,258,311,142,779,672,903,149,344,452,288,532,105,674,225,951,769,317,24,630,664,602,134,49,922,968,399,949,147,811,388,605,695,448,108,20,142,233,987,748,45,711,343,104,804,965,387,133,705,871,450,206,488,583,811,792,946,522,417,519,119,109,215,465,637,179,89,42,587,92,894,164,408,48,815,860,952,583,58,419,608,546,122,93,974,592,640,293,354,928,388,946,574,751,40,500,504,927,481,418,952,36,801,264,213,568,389,80,760,393,319,998,346,484,478,344,156,139,182,806,932,365,541,329,612,548,13,205,283,185,609,511,826,586,287,441,259,43,603,733,75,477,590,568,254,944,66,688,80,997,740,809,316,714,401,228,537,88,705,770,682,130,298,720,955,757,621,931,287,804,852,402,323,271,616,593,47,56,195,426,438,833,571,215,788,605,377,391,184,672,421,994,223,863,68,412,808,716,81,316,464,42,929,540,536,730,948,980,224,58,513,921,5,54,447,369,510,598,667,280,439,540,752,204,766,76,329,587,982,384,156,439,566,874,772,856,29,723,306,532,388,803,481,257,970,609,885,553,52,852,468,978,436,6,233,200,328,728,116,855,147,193,455,988,219,992,853,112,878,457,534,580,554,915,350,726,755,849,955,66,0,614,983,167,813,659,567,203,869,353,188,138,352,669,155,570,366,30,197,479,729,848,47,133,915,414,838,298,983,700,472,411,894,721,879,878,743,128,786,486,219,66,685,721,620,477,962,28,504,676,761,556,142,265,422,14,44,906,568,819,940,885,7,82,820,164,85,744,217,608,933,367,410,574,7,972,215,671,901,679,513,145,907,545,794,601,891,126,69,217,430,386,328,570,700,464,824,422,649,40,906,549,663,234,67,825,54,951,179,818,781,670,531,147,975,677,354,691,726,641,859,156,584,457,824,684,176,677,191,275,296,747,286,396,805,263,123,857,236,519,706,863,700,853,968,561,752,148,194,359,907,379,420,633,694,852,895,17,93,23,502,687,819,416,270,565,529,319,550,255,36,388,638,892,441,818,696,350,185,130,91,170,98,853,651,585,865,874,783,22,517,985,29,923,78,945,464,566,597,481,941,795,316,45,381,674,564,146,45,572,76,881,218,936,782,777,423,631,847,475,331,736,533,466,271,575,959,846,541,320,617,100,348,594,514,331", + "384,223,275,469,784,981,901,922,597,760,440,6,369,270,123,835,500,933,629,270,734,981,20,138,115,840,988,919,313,996,904,72,144,156,925,758,486,434,442,159,987,994,223,418,704,801,336,525,386,8,338,615,245,669,114,882,701,972,804,988,938,298,565,512,451,589,484,399,391,15,749,293,143,713,181,840,903,726,471,480,354,328,26,512,932,846,557,920,170,856,594,947,538,558,164,206,77,962,943,128,252,437,514,681,654,344,912,650,850,784,923,872,324,417,144,615,723,552,35,969,834,214,793,961,649,781,164,108,491,652,284,107,138,483,953,890,213,578,900,958,94,847,898,410,899,666,814,269,133,781,941,186,585,894,424,304,994,916,349,960,578,921,353,42,347,177,654,466,971,165,910,946,299,146,803,272,215,374,423,324,928,733,908,397,129,327,161,97,413,698,687,33,644,789,957,676,365,214,641,657,937,212,503,591,380,520,318,373,384,100,656,404,599,144,95,363,228,956,221,898,893,894,896,291,420,896,255,142,925,648,167,955,850,22,653,907,509,486,347,846,940,571,208,171,940,997,902,141,444,836,499,123,777,472,424,155,461,698,720,180,450,198,401,871,488,385,551,752,582,250,263,593,640,357,378,568,169,608,186,476,32,562,465,997,499,937,231,866,320,843,989,843,959,481,199,149,541,902,538,242,137,454,828,708,32,192,949,306,202,621,991,732,89,371,256,345,855,277,243,216,38,548,655,470,84,542,693,902,223,128,929,429,528,695,477,114,678,90,806,551,754,491,166,259,126,212,354,754,628,823,421,969,962,943,405,88,115,423,173,246,15,472,430,3,866,766,387,207,748,613,111,855,79,676,175,300,297,107,448,989,516,529,822,281,441,230,902,117,818,265,367,897,771,279,643,140,914,49,971,527,543,421,594,210,931,294,91,334,472,488,892,486,539,828,498,127,661,455,639,52,251,893,74,186,357,589,182,927,689,995,848,486,9,248,167,537,760,557,151,248,523,154,439,207,501,825,136,522,953,458,956,338,465,816,221,696,135,882,819,721,474,766,83,29,432,775,484,271,705,183,22,557,623,121,395,965,723,969,420,860,722,824,803,842,936,414,969,194,558,678,756,539,771,219,706,70,98,628,874,499,580,619,311,582,341,562,101,140,606,406,850,884,679,533,251,100,701,641,303,920,521,719,436,859,809,731,113,697,41,76,816,211,8,403,999,223,868,324,22,762,547,2,85,730,502,317,167,490,27,960,862,75,659,756,897,367,929,720,907,121,145,187,486,636,989,820,680,319,582,398,827,776,163,882,984,731,306,855,481,922,963,52,132,282,643,214,863,473,422,515,13,496,695,648,114,784,917,626,408,267,793,621,71,687,683,758,787,401,202,3,687,835,717,237,655,138,224,448,816,670,794,105,626,739,287,373,336,165,568,442,136,135,540,411,410,430,274,578,205,965,503,875,139,165,962,835,159,249,198,178,779,38,34,439,61,637,995,362,637,183,223,524,401,22,572,212,895,738,52,653,452,171,563,350,74,879,305,485,650,609,643,890,939,803,796,106,143,186,194,978,853,469,826,250,584,803,835,132,35,648,639,618,50,395,943,606,536,625,565,867,789,750,308,837,253,542,466,592,700,887,533,40,915,316,896,670,798,408,509,482,764,185,447,576,754,899,663,291,631,400,948,137,503,287,231,229,701,840,280,815,573,221,156,780,679,114,226,231,358,791,896,655,84,228,614,0,788,530,780,861,698,234,666,471,165,679,982,311,225,85,758,5,494,44,437,30,455,360,458,692,81,139,526,54,653,275,522,879,404,72,21,154,139,986,56,879,511,91,503,200,115,686,601,608,826,222,167,870,867,466,286,677,430,123,683,717,17,787,627,206,929,8,607,230,881,949,206,169,724,174,689,431,299,176,178,239,998,68,602,392,630,382,344,926,634,616,623,513,914,698,428,185,12,881,301,93,774,228,444,982,93,365,686,973,606,973,305,916,668,912,910,710,417,685,910,167,303,657,93,393,621,586,111,185,431,498,984,363,952,73,755,853,915,117,26,532,961,718,430,531,857,573,197,929,268,911,732,186,493,339,866,983,918,181,256,793,269,226,616,151,886,71,593,767,556,494,78,898,207,504,483,187,586,93,587,423,885,442,373,526,181,852,900,685,836,795,178,607,410,771,646,928,62,559,506,490,296,104,708,493,115,47,352,768,739,986,764,196,841,848,355,76,624,900,132,231,314,359,265,600,972,95,625,765,599,843,162,283,269,823", + "440,95,400,67,220,777,93,471,599,904,289,28,346,248,955,275,220,376,58,601,337,543,882,393,951,695,567,178,910,302,388,445,496,383,688,649,887,844,209,767,843,54,998,38,894,444,540,300,991,984,244,408,96,802,238,262,365,128,645,236,166,542,818,340,681,171,173,126,975,668,161,189,318,63,885,378,811,656,786,324,114,469,876,575,997,951,65,365,292,358,54,727,583,123,516,868,835,652,179,112,886,40,596,873,571,874,804,753,778,873,516,90,9,426,756,75,972,657,597,621,109,764,96,786,883,705,826,62,193,673,624,505,950,638,175,408,252,11,81,581,705,493,909,428,445,303,984,619,623,620,190,121,584,674,341,772,759,518,435,40,871,94,401,246,951,692,299,772,43,66,362,432,498,148,927,338,375,696,157,207,295,377,668,958,884,548,272,970,140,944,39,839,778,905,277,952,658,894,843,14,132,272,872,32,59,928,446,534,576,185,363,918,543,661,402,500,607,922,679,934,336,640,726,687,174,787,101,18,470,736,639,275,848,116,350,434,401,993,104,370,544,770,427,727,55,157,345,406,181,285,417,234,757,693,111,268,80,363,663,730,924,893,710,618,855,445,245,392,409,780,150,591,349,366,522,265,712,864,144,941,174,790,162,844,507,196,585,844,680,250,384,707,223,217,397,764,463,20,200,629,646,168,26,86,676,421,220,521,276,404,985,690,647,19,812,348,657,419,902,968,246,741,294,77,893,281,646,222,611,212,463,223,857,490,439,634,199,26,750,964,340,624,377,660,946,598,257,854,613,203,876,144,751,175,735,617,847,828,597,285,557,263,474,761,436,844,146,160,624,127,909,595,947,288,915,730,234,782,754,946,342,805,7,98,195,934,24,572,574,755,760,700,547,660,461,203,447,515,259,992,430,915,278,544,248,270,628,904,788,331,52,791,55,196,197,727,706,498,985,950,275,876,475,333,625,918,287,418,553,646,11,730,453,968,413,439,286,559,838,410,215,99,641,843,604,336,251,529,788,176,382,345,704,776,159,302,745,141,355,721,342,987,539,967,857,245,503,431,834,211,708,78,994,638,48,111,357,466,84,450,907,416,817,939,41,875,654,431,236,220,199,274,197,885,654,339,440,66,122,705,708,443,115,134,250,875,583,165,46,342,131,996,13,747,15,312,498,434,91,163,852,574,739,395,820,233,483,803,301,819,861,208,685,587,560,466,655,572,24,703,611,587,907,939,529,377,482,257,139,190,749,867,520,22,398,325,198,999,739,353,861,472,841,710,939,435,691,495,122,394,687,273,208,304,954,614,354,855,563,844,121,610,634,293,844,194,963,659,374,973,128,918,51,574,358,636,653,868,508,381,118,28,208,744,354,491,897,92,565,664,759,433,803,505,148,186,206,61,754,16,618,488,730,166,701,972,404,908,166,10,554,423,203,722,404,387,697,502,96,481,240,315,251,561,478,44,577,767,638,19,490,201,966,551,855,221,469,229,276,198,347,39,758,904,573,211,838,349,99,724,120,961,56,710,154,177,498,595,429,543,585,12,71,58,723,491,634,552,618,250,489,373,702,831,909,754,971,438,108,378,114,675,239,96,425,672,401,382,858,182,920,941,576,460,976,888,904,706,791,218,116,492,552,503,29,690,949,263,138,148,795,587,811,861,671,374,171,271,592,160,251,422,509,4,882,831,765,346,184,217,596,375,519,272,950,617,694,8,847,227,919,856,986,213,983,788,0,443,710,851,282,283,859,603,69,616,335,520,963,198,31,91,388,352,906,981,802,771,730,204,190,440,456,433,127,890,545,765,403,335,332,942,921,552,892,424,236,534,463,697,776,879,620,614,706,326,213,149,417,274,479,672,886,266,482,571,960,910,708,322,423,888,98,452,763,21,654,940,430,602,192,610,604,619,683,986,560,935,321,40,285,18,863,330,732,840,680,358,712,272,520,381,737,590,498,754,601,753,288,885,244,827,61,588,505,664,391,492,415,346,389,735,400,126,233,404,318,697,368,66,350,90,50,620,114,983,657,736,965,845,278,362,976,349,548,999,574,407,311,977,102,572,305,757,375,463,675,233,44,976,976,209,337,521,733,890,817,421,619,715,157,488,923,707,139,762,526,986,483,278,861,127,903,561,178,399,371,692,403,937,415,814,604,977,751,310,737,769,603,641,176,940,713,688,731,695,956,617,690,744,27,174,904,764,241,220,293,211,278,842,87,391,642,862,919,635,27,465,738,947,498,345,891,320,76,762,599,11,36,113", + "914,665,664,923,876,558,630,365,951,408,173,906,444,216,852,625,182,235,31,71,213,671,713,130,937,710,629,535,602,17,782,200,365,529,141,68,735,886,86,954,893,977,896,168,291,861,715,664,256,773,554,249,243,72,789,773,855,924,643,751,600,372,77,986,476,595,208,565,205,311,120,1000,975,469,471,860,732,770,503,641,138,628,98,76,240,148,318,930,31,365,730,281,478,506,338,691,545,432,463,943,493,30,90,471,489,913,971,578,587,728,151,236,761,259,665,29,623,313,898,150,242,793,473,836,686,3,328,140,48,785,904,874,192,304,850,153,309,850,458,299,825,923,454,955,570,194,587,626,806,87,756,654,221,954,248,149,328,156,923,748,509,56,311,495,466,552,897,577,630,494,333,344,698,426,275,632,263,962,403,840,396,670,401,776,672,586,215,832,937,516,8,47,106,905,912,398,338,818,362,444,860,952,210,959,561,471,751,630,267,237,527,378,858,372,206,754,144,283,509,491,651,575,875,756,715,844,552,376,199,659,258,272,637,896,581,84,457,181,450,869,697,355,856,363,613,655,257,90,386,538,970,235,471,812,739,978,867,273,409,419,575,784,847,288,13,278,10,285,918,670,679,602,782,316,37,383,200,142,419,577,786,237,894,947,595,580,686,897,232,780,708,114,586,13,994,818,134,812,370,805,615,670,619,583,425,192,502,394,680,464,712,375,541,694,538,50,8,181,285,628,298,304,646,218,584,975,917,241,474,13,711,533,637,36,624,102,41,80,301,633,725,319,782,512,296,832,564,906,445,27,201,236,9,658,338,131,457,152,427,125,249,474,125,335,410,512,203,908,559,475,555,695,943,420,105,294,880,400,818,568,642,453,424,387,682,803,980,776,537,365,370,675,608,455,229,297,256,489,12,504,866,893,346,600,469,487,867,371,249,598,230,372,37,59,555,11,642,47,173,91,258,643,298,186,753,444,510,967,608,360,963,703,124,204,523,187,671,188,634,14,24,886,520,283,635,105,697,130,127,885,636,703,638,779,193,791,701,669,429,589,341,863,659,364,599,338,444,859,651,463,613,875,562,109,282,93,223,352,872,305,726,386,962,476,242,399,507,850,796,359,575,655,768,31,472,819,92,925,788,381,921,262,372,428,343,813,364,588,118,489,774,184,207,885,383,104,514,339,461,304,311,90,896,694,160,978,585,354,91,452,379,612,980,138,310,159,145,308,493,227,775,96,187,836,518,975,674,78,852,76,877,896,135,897,233,795,421,992,661,335,47,74,634,698,117,887,402,102,225,448,238,454,310,622,889,494,29,476,430,840,438,445,308,831,891,332,48,190,368,779,972,219,7,206,393,314,229,442,497,455,277,868,488,784,146,216,841,212,74,882,757,835,609,696,171,113,539,359,70,899,134,853,819,317,312,31,199,571,489,569,373,759,255,93,589,871,679,527,155,762,339,823,199,282,216,865,43,396,442,649,412,232,584,649,317,586,706,143,234,931,445,114,714,407,875,342,354,444,292,487,337,626,26,478,91,621,640,913,384,142,178,341,676,821,705,821,853,667,868,545,877,626,884,423,551,70,759,363,763,669,179,430,237,151,186,602,632,1000,967,321,323,978,354,882,760,745,980,264,566,700,240,219,969,621,973,651,541,670,950,271,983,752,193,483,425,488,818,998,359,918,80,333,646,113,403,914,710,853,20,553,322,142,478,543,286,49,748,333,342,240,403,157,196,691,167,530,443,0,114,148,993,745,979,132,149,74,117,84,435,844,37,267,853,19,945,140,555,696,618,64,951,69,424,444,569,791,721,239,59,627,68,140,791,169,407,344,63,88,790,395,949,702,51,651,493,321,899,791,796,529,993,712,242,245,880,330,554,250,850,721,988,652,160,337,38,638,494,750,650,162,599,198,120,658,467,528,76,188,745,523,902,295,615,106,269,458,766,81,297,726,488,836,43,415,148,920,258,588,793,543,165,249,225,413,716,334,984,466,941,622,478,978,828,309,711,536,304,220,10,159,335,266,14,912,71,446,170,307,16,155,387,491,305,154,236,837,733,913,720,76,263,835,926,443,519,4,159,171,691,931,381,226,462,497,339,539,682,131,836,396,181,185,149,102,98,706,487,66,429,924,563,766,545,149,171,837,600,89,706,46,941,224,125,297,496,181,49,639,749,376,425,787,315,527,54,575,87,398,436,151,113,446,339,435,526,115,800,721,371,929,740,241,66,495,887,370,390,862,846,538,613,103,61,667,873,323,853,185,181,10", + "286,884,787,552,21,152,989,919,499,508,646,258,695,402,209,484,63,593,951,117,37,420,438,112,422,496,648,102,511,899,982,158,130,114,94,480,696,548,751,540,650,709,725,977,117,193,133,152,595,960,513,360,819,866,166,405,705,641,460,244,15,237,575,842,176,971,761,7,504,819,454,962,24,712,629,554,226,704,624,576,86,201,461,491,550,188,292,413,297,608,948,30,207,968,726,586,875,716,488,59,470,246,371,171,470,175,74,349,515,293,346,14,986,285,83,596,49,473,349,940,944,302,522,451,42,219,793,467,466,572,85,543,88,518,976,71,93,3,701,237,366,564,963,945,864,506,820,405,890,251,599,922,116,508,298,791,823,328,741,500,403,662,782,995,810,877,575,433,520,129,805,285,418,864,858,85,472,288,535,944,368,688,440,236,931,845,599,407,520,632,511,822,266,127,608,585,766,46,732,696,782,779,944,331,190,671,42,531,880,165,45,837,105,474,291,543,804,963,884,764,885,12,347,17,55,43,39,233,756,324,256,900,830,90,471,282,600,107,284,573,465,553,688,823,184,101,729,3,738,946,357,128,537,735,21,340,311,612,856,887,712,166,207,535,326,847,829,842,527,159,485,375,835,807,446,357,106,243,62,93,129,572,406,861,641,213,777,328,210,649,420,36,213,751,217,516,580,48,690,794,628,96,428,582,155,630,348,70,120,966,949,762,625,35,607,534,703,763,478,355,924,262,3,328,809,400,846,420,943,363,667,616,731,84,584,711,347,465,747,171,66,503,594,205,375,858,372,771,544,467,874,703,655,581,154,723,212,125,707,800,695,990,907,362,958,926,51,124,39,57,423,854,257,932,729,547,616,140,233,558,280,17,170,953,286,943,220,278,40,696,291,252,245,902,829,965,735,994,549,784,106,51,388,346,740,164,424,554,823,19,710,820,465,873,63,60,445,43,168,382,924,301,109,154,368,399,225,121,60,309,993,365,533,200,485,482,399,607,405,582,351,544,330,700,962,377,702,871,148,496,352,720,55,608,635,828,80,900,158,208,853,39,593,634,719,255,96,950,684,34,1,154,240,723,787,723,938,427,947,418,752,48,155,601,486,17,687,247,621,505,599,76,154,857,750,549,499,115,687,248,715,637,895,530,507,40,144,510,776,637,713,183,594,819,843,387,545,625,53,882,311,188,357,247,597,446,268,816,506,634,933,382,245,865,621,939,23,621,939,575,708,418,739,48,592,371,903,573,465,71,882,188,266,61,974,401,913,680,725,760,610,394,683,203,930,756,251,832,774,560,386,236,234,698,888,544,626,836,206,579,820,711,510,538,251,178,513,408,547,980,762,753,490,486,835,537,150,830,677,910,410,454,100,644,932,634,124,580,39,586,561,325,644,976,168,730,94,625,258,612,936,365,677,980,126,188,111,946,262,730,914,49,254,377,363,731,435,962,473,147,578,566,75,194,20,590,431,368,883,234,722,536,714,624,411,135,424,578,512,663,761,317,445,156,532,342,590,318,171,555,748,445,255,498,9,766,314,826,427,773,905,137,314,435,8,203,77,696,163,860,40,954,820,72,51,296,951,817,393,556,975,675,157,424,348,188,17,324,965,292,523,321,220,872,236,732,436,838,250,295,678,164,793,825,18,636,675,715,4,3,802,52,598,21,945,132,429,461,834,995,26,104,15,679,920,974,685,301,766,957,842,62,629,487,324,838,996,294,10,602,631,43,977,718,813,780,710,114,0,418,868,568,504,326,743,549,246,592,669,724,260,916,953,362,470,30,151,279,434,143,299,611,372,638,359,969,664,298,3,974,921,165,834,528,98,176,873,778,989,316,792,575,427,101,353,719,900,285,830,25,161,111,645,78,324,562,400,695,954,783,927,97,265,137,188,246,525,886,662,400,302,187,787,427,169,530,812,673,740,675,901,831,225,824,586,857,575,900,639,45,803,507,948,26,194,902,33,60,369,160,845,242,37,237,302,611,362,756,38,553,302,636,867,36,229,275,337,66,414,950,280,21,171,819,392,291,190,567,210,156,345,761,369,295,857,200,631,792,619,197,419,783,943,605,732,56,287,422,921,618,265,231,957,529,93,244,968,46,512,75,971,898,755,27,512,631,310,519,182,167,575,355,808,33,637,99,649,955,127,24,379,573,18,209,607,603,591,135,803,812,825,838,137,390,267,703,502,335,425,815,512,596,513,819,424,99,903,299,655,78,495,656,320,144,405,160,485,490,592,516,220,550,712,548,172,103,679,587,130,67", + "110,235,817,198,6,635,343,736,649,516,976,75,742,197,946,251,931,560,76,220,393,904,770,185,97,445,430,827,483,541,365,997,878,439,829,953,318,495,806,446,731,347,101,575,485,108,596,737,683,966,615,919,414,804,266,907,140,832,156,703,968,80,563,676,146,999,621,618,402,391,725,77,506,920,218,429,537,205,369,844,878,854,29,636,793,612,214,124,488,223,902,859,428,455,302,866,870,260,799,246,914,811,635,236,266,185,125,953,460,924,697,678,334,541,404,300,358,241,180,256,88,868,355,779,464,590,66,883,11,696,263,314,968,484,832,457,532,805,792,551,547,81,125,767,460,875,868,505,622,462,102,602,857,837,187,468,625,907,955,799,672,901,273,635,484,177,775,342,425,493,673,566,176,23,381,93,513,879,732,666,332,429,552,175,863,972,990,561,39,729,832,247,811,936,175,728,890,697,794,434,328,539,968,205,292,89,255,503,883,680,524,632,626,745,143,786,591,725,654,744,781,894,795,851,452,871,506,711,217,30,318,883,889,99,656,535,792,279,166,449,882,384,360,811,188,696,300,873,330,291,62,795,637,59,693,33,564,259,876,391,391,394,878,102,129,607,493,95,145,363,645,387,311,814,751,493,261,679,45,758,121,432,412,673,825,965,433,949,263,375,729,732,860,814,201,704,126,720,670,614,59,801,544,541,735,639,230,957,241,400,348,322,230,583,906,186,179,77,375,763,540,792,129,199,443,871,688,897,693,657,343,802,279,322,984,224,374,550,39,794,804,901,80,902,605,435,280,821,150,576,720,203,339,780,213,354,616,558,101,57,250,623,179,190,63,976,220,770,546,71,744,953,617,761,10,798,22,574,420,431,68,286,218,539,142,139,398,91,446,712,856,195,688,977,647,27,560,167,912,531,692,540,408,850,666,690,480,745,304,675,403,203,30,216,845,320,405,587,668,857,549,40,607,217,282,228,379,470,863,668,480,958,150,168,431,208,777,606,751,382,652,404,461,487,143,747,906,633,518,927,779,14,709,141,892,259,9,628,61,745,578,211,224,23,824,552,397,149,815,957,411,382,186,599,934,827,505,132,900,902,916,213,636,457,182,208,941,316,981,818,557,765,824,71,671,359,431,325,715,460,306,465,885,352,758,226,519,387,800,165,295,802,578,121,118,329,791,954,37,286,881,797,180,224,265,993,16,208,5,218,959,527,525,248,440,955,141,439,562,507,419,298,298,273,678,899,909,63,819,837,176,527,374,681,183,263,167,201,816,82,652,403,530,133,926,489,536,845,801,968,684,73,178,830,187,169,915,565,962,457,472,417,881,426,164,218,596,700,520,894,57,344,782,192,190,842,857,798,571,735,935,186,252,20,44,51,470,702,851,533,945,848,767,377,322,120,106,906,376,607,499,688,757,219,243,734,295,526,295,993,592,138,98,878,620,724,181,772,321,384,515,302,808,728,534,674,580,682,174,344,275,516,987,465,158,532,753,818,967,710,334,834,561,395,768,597,702,382,184,355,268,601,694,774,835,177,347,936,791,620,90,251,584,993,608,383,641,12,89,388,742,751,501,789,832,204,162,295,866,239,967,774,37,222,914,499,973,427,592,664,959,312,509,910,988,567,169,666,50,248,68,604,736,642,351,764,429,588,60,550,225,758,523,88,264,942,719,957,942,81,738,633,689,625,520,238,482,314,587,926,395,863,152,831,776,241,504,7,201,452,230,931,739,657,659,861,851,148,418,0,107,9,953,737,790,642,66,35,642,884,164,355,317,521,64,274,400,560,868,331,556,894,581,519,402,987,79,308,849,33,891,450,889,480,637,789,143,263,186,663,303,727,18,918,684,235,184,604,755,776,538,603,928,745,656,212,936,950,996,661,359,573,447,386,381,35,279,491,113,969,569,932,94,874,390,978,160,413,737,64,245,33,816,771,202,802,269,340,624,505,194,569,527,999,209,607,850,706,957,671,698,411,565,414,696,40,663,777,344,541,545,722,721,772,887,811,764,871,830,601,17,506,616,824,549,184,839,931,949,499,810,667,893,176,420,546,140,263,387,252,574,702,96,972,570,463,61,505,987,653,791,843,956,938,464,548,358,122,226,785,293,416,611,399,18,853,4,590,294,625,981,172,444,314,721,873,240,747,435,916,608,431,495,295,245,801,745,858,292,834,212,762,970,199,809,989,200,461,987,813,503,428,650,578,655,706,541,288,756,310,183,321,650,964,241,973,403,446,694,185,921,976,963,935,798,424,976,876,789,333", + "760,8,860,698,904,279,85,251,928,547,201,806,365,460,392,450,212,60,470,756,691,182,281,644,429,129,591,908,326,618,254,623,812,561,49,87,691,352,879,970,460,701,392,271,781,288,806,165,767,579,312,131,713,845,334,376,939,918,368,998,389,761,38,900,606,964,675,369,427,965,655,370,595,992,302,780,873,360,129,230,303,943,429,355,175,259,153,752,328,504,831,159,959,869,810,388,919,935,649,142,65,602,10,369,197,565,224,436,924,799,335,761,518,727,31,420,189,980,784,554,514,131,340,976,98,102,530,161,977,49,644,894,325,69,594,803,388,254,315,694,289,32,674,732,361,483,912,852,764,405,563,989,670,159,143,93,80,827,656,145,223,809,430,421,899,601,41,336,207,610,572,626,590,659,114,508,357,580,642,910,195,282,615,361,243,452,436,933,505,207,770,99,862,332,27,660,478,212,93,392,141,482,810,421,58,350,945,723,220,212,485,741,886,291,205,726,142,693,147,483,617,961,94,515,454,375,186,51,834,962,901,863,198,811,582,79,595,594,85,914,438,623,563,566,994,891,22,328,852,986,412,918,856,932,13,828,871,107,982,116,603,262,331,157,339,849,432,183,60,726,797,383,553,607,419,590,117,740,126,856,526,2,275,152,92,568,184,206,948,680,690,769,285,497,784,143,769,564,568,855,206,500,359,484,271,490,513,641,993,260,551,605,463,142,274,921,831,154,909,28,33,724,672,276,65,48,32,944,546,808,502,105,480,34,998,597,27,769,529,163,653,881,356,213,266,361,629,884,227,580,547,80,675,917,890,989,265,151,674,241,836,258,647,95,175,18,215,433,819,206,994,366,396,844,119,450,13,552,148,75,569,84,231,942,348,774,867,37,959,220,142,789,504,762,499,839,539,706,737,739,705,844,641,911,503,206,962,210,241,148,160,214,982,602,898,861,952,742,409,178,207,936,794,597,774,392,838,589,401,605,177,656,593,978,464,699,597,670,952,667,578,626,582,971,117,535,713,265,126,747,295,279,74,524,843,21,271,870,226,777,784,57,228,292,975,648,366,312,70,427,847,74,971,314,133,34,384,920,602,298,968,201,959,319,929,704,531,57,174,10,50,589,68,880,736,199,683,587,809,766,762,525,673,721,501,450,855,45,611,442,942,529,291,211,872,946,567,226,80,28,802,332,824,273,123,402,424,230,988,769,469,115,725,839,943,949,683,843,262,858,144,127,907,375,898,49,874,444,872,244,16,516,161,118,11,327,48,663,210,829,493,256,837,51,675,337,640,562,691,384,796,181,775,678,812,886,271,205,139,41,935,209,534,405,356,946,727,737,206,292,638,474,426,390,945,479,537,96,303,791,483,499,881,625,327,143,99,758,13,419,979,104,102,96,613,93,330,418,682,745,543,627,288,84,117,995,696,403,910,161,869,188,487,92,117,663,211,602,178,420,482,89,330,697,965,234,547,914,943,945,225,699,965,386,892,204,64,906,195,808,835,599,260,130,857,751,818,553,809,126,495,428,873,256,136,820,822,808,993,548,995,480,355,693,529,249,590,295,213,773,880,582,213,715,241,952,47,715,404,162,671,242,811,798,402,666,371,337,614,27,201,748,255,90,712,965,700,487,409,59,353,200,509,307,671,691,926,994,452,609,238,612,515,236,259,120,251,498,572,683,866,359,65,914,297,360,379,64,655,924,112,984,653,77,11,919,774,637,418,880,749,324,120,528,567,698,282,993,868,107,0,367,196,370,375,68,905,151,607,392,568,182,433,369,523,434,327,678,245,60,272,572,66,119,310,285,644,521,733,670,607,177,145,68,67,574,758,554,385,503,235,284,423,447,617,724,465,12,433,920,405,371,716,393,641,133,485,783,529,707,37,24,435,311,618,684,786,772,78,689,545,452,813,798,414,894,115,505,968,965,470,703,22,192,173,456,419,792,343,290,885,351,56,303,297,743,582,212,660,188,283,572,100,374,927,324,116,89,693,399,478,119,860,747,541,677,331,585,899,130,888,459,472,285,5,130,369,965,3,215,879,646,567,477,506,598,804,840,564,426,165,507,781,342,726,710,897,898,45,390,787,261,654,324,57,240,392,358,780,641,86,268,565,602,655,844,780,651,909,991,767,863,222,788,540,242,552,765,486,674,550,366,847,212,426,290,593,602,687,779,823,322,405,918,17,919,691,149,254,862,457,769,220,705,118,726,873,876,538,299,48,82,263,6,624,986,486,146,220,552,658,342,312,296,10,510,645,289,133,833", + "639,839,333,698,304,862,575,655,252,458,856,145,121,468,151,982,507,281,44,333,438,196,447,997,148,343,624,988,778,43,394,249,261,673,630,846,258,754,222,902,900,765,887,288,145,307,884,410,10,515,784,852,875,249,120,460,847,688,233,765,364,329,87,112,942,708,246,677,471,244,946,532,35,225,514,309,508,728,491,511,858,809,906,532,806,237,691,857,161,683,429,862,823,512,668,103,254,503,489,312,498,214,502,762,86,576,410,324,791,4,788,602,98,108,594,800,960,89,616,752,25,478,620,16,118,761,469,222,82,993,792,612,481,568,110,511,558,258,977,141,330,987,57,639,126,323,805,702,949,45,205,33,711,892,916,232,528,621,86,972,872,764,956,90,252,316,449,982,865,41,915,424,769,239,595,978,605,725,647,240,746,499,123,920,858,300,671,66,979,475,555,95,481,61,694,530,437,430,384,294,616,350,195,114,857,609,990,254,883,62,966,751,327,115,843,40,870,405,987,989,428,2,41,151,128,992,903,395,591,783,51,116,664,908,304,143,152,185,634,884,551,201,70,831,172,523,455,854,170,39,731,613,150,363,182,996,142,486,784,802,677,928,366,30,506,218,746,629,953,840,704,475,179,482,749,263,345,11,248,933,446,749,435,694,247,655,654,24,634,556,746,823,976,301,129,560,912,354,181,499,816,30,977,288,264,567,588,817,142,316,960,59,603,224,509,846,135,296,299,900,453,553,370,445,666,881,109,276,128,129,205,165,717,267,256,554,886,446,684,831,50,945,216,491,505,500,273,72,817,443,435,171,240,300,402,21,547,249,254,9,280,210,519,629,827,615,886,541,717,335,423,566,835,258,648,378,118,409,997,18,710,796,370,29,915,155,728,140,14,757,775,622,471,103,718,645,998,314,47,136,668,519,207,245,719,461,288,327,43,489,308,718,483,807,718,923,863,558,870,207,18,720,561,522,861,564,921,116,432,525,413,331,562,778,886,518,146,318,735,233,512,772,201,570,859,786,546,637,939,382,655,878,535,659,193,832,791,646,77,410,245,202,207,453,651,684,484,676,59,319,587,239,783,201,900,722,581,929,949,769,33,810,392,148,229,135,265,795,52,290,544,298,86,374,110,914,424,63,649,740,974,363,663,676,22,706,451,224,722,405,972,256,183,974,101,149,747,11,284,174,333,699,709,577,987,272,605,921,132,263,141,592,989,477,87,635,556,871,784,690,508,766,273,453,307,728,851,509,692,500,142,900,920,451,169,566,135,511,326,227,461,219,469,103,865,481,183,577,227,815,155,323,63,368,546,910,168,934,26,665,48,9,304,784,479,517,928,512,468,938,527,400,406,747,637,673,219,603,866,233,985,784,837,296,33,388,816,348,789,21,237,594,746,382,567,776,464,323,916,280,877,571,802,119,892,200,367,180,780,702,854,446,94,888,668,589,354,129,606,624,150,6,586,317,963,871,680,121,836,276,867,232,51,388,963,629,266,527,259,500,726,444,499,47,567,90,966,812,78,525,753,903,122,472,58,8,285,458,204,282,11,293,743,22,760,809,328,795,63,35,36,158,441,574,857,688,793,613,976,967,690,481,732,684,715,476,975,826,410,490,660,20,431,855,669,784,474,437,447,135,159,590,231,119,404,255,570,377,470,713,209,140,304,721,464,257,772,663,551,416,768,419,106,739,770,276,216,647,218,430,130,120,546,178,550,458,380,182,742,123,10,106,613,412,203,234,283,745,568,9,367,0,385,342,488,690,752,784,609,972,418,99,494,367,674,863,847,176,120,23,734,859,617,605,624,868,761,389,975,174,396,507,174,757,10,646,905,635,435,948,526,780,677,890,624,817,926,224,911,166,193,344,431,21,751,56,609,63,743,645,849,627,521,319,31,401,386,428,17,909,775,414,651,968,440,421,987,79,319,397,921,57,956,187,125,447,527,866,714,902,809,918,9,413,681,942,375,963,436,597,682,160,397,934,11,886,938,866,53,27,612,213,259,982,997,480,390,974,918,656,953,915,500,966,851,371,365,585,363,734,410,809,6,806,893,133,522,389,252,106,800,142,92,748,702,62,849,14,150,8,52,919,375,205,398,166,411,686,567,567,588,653,724,488,2,744,588,69,117,85,992,191,62,260,623,62,837,529,385,648,142,160,203,944,507,728,168,197,128,525,627,301,884,884,692,73,402,736,699,979,705,185,81,38,985,307,174,378,736,32,988,415,957,586,347,415,141,868,447,352,515,855,509,253,202,92,534,175,784,280", + "284,225,452,741,305,988,415,422,127,473,567,735,332,144,357,547,818,808,439,791,954,381,866,213,368,749,613,138,487,675,936,992,709,342,657,589,614,990,680,349,180,765,661,20,781,959,950,689,318,797,360,75,513,761,701,511,483,17,44,736,718,420,602,22,441,198,217,337,105,250,623,124,995,909,772,840,304,460,829,120,445,490,757,972,912,777,473,249,356,723,831,878,777,950,184,472,569,104,520,264,928,831,795,376,686,917,868,986,457,500,203,741,509,569,52,630,730,728,913,440,489,973,183,754,913,543,491,902,458,531,478,203,620,874,294,219,658,332,121,93,319,363,909,445,307,33,241,580,95,422,351,643,388,448,337,849,698,123,733,726,958,165,869,940,420,184,298,389,641,599,81,102,329,301,313,359,453,816,739,165,908,485,940,972,144,629,917,776,661,59,72,928,214,944,459,163,782,334,304,534,753,837,378,655,5,970,179,953,166,903,747,574,677,30,68,977,237,281,95,895,428,193,517,832,134,32,779,2,830,459,789,737,289,806,432,430,764,556,17,291,457,87,81,273,3,623,643,268,115,827,820,623,926,6,72,830,707,604,343,8,775,48,84,879,845,358,602,770,747,332,388,611,208,173,886,578,835,154,833,19,565,481,508,898,612,485,112,465,508,894,939,609,534,171,308,18,45,444,819,518,736,107,863,377,970,756,628,179,142,316,934,42,78,448,836,73,169,980,561,467,740,210,774,85,387,379,455,492,100,816,538,303,109,602,821,142,325,4,857,656,750,44,844,220,553,884,623,474,720,290,230,436,480,519,695,615,665,695,972,299,556,42,485,705,510,238,261,386,133,457,457,767,246,776,774,359,829,718,464,539,685,989,405,868,396,893,402,899,89,305,574,614,64,717,261,514,535,449,280,869,763,709,589,64,784,390,597,242,868,766,240,922,339,83,520,384,862,836,734,994,572,688,110,220,612,651,32,663,15,512,665,40,993,354,841,718,351,106,974,155,687,801,580,483,546,471,444,616,28,884,238,349,187,734,676,8,296,410,825,312,444,359,99,59,632,304,235,228,492,7,436,747,426,790,596,297,824,268,211,617,840,619,195,7,387,351,421,397,575,311,548,280,535,995,950,347,965,583,981,442,410,311,78,470,562,574,16,815,389,771,198,690,987,387,525,920,360,134,400,386,672,378,505,581,848,35,717,183,537,195,503,542,528,177,553,775,369,970,484,392,92,120,817,288,568,896,303,165,95,239,495,559,461,452,437,298,813,968,888,476,731,42,77,143,52,351,667,867,197,875,489,472,795,298,789,60,170,202,197,701,450,834,782,812,317,250,681,813,992,553,563,601,638,1000,465,83,592,501,687,673,970,909,69,554,415,757,586,169,119,67,96,70,152,770,990,216,368,846,574,747,986,866,62,676,939,273,509,521,463,94,453,274,864,304,350,952,632,649,930,922,394,685,719,175,625,818,236,450,889,351,338,983,725,921,608,520,530,944,272,944,2,776,275,714,156,460,52,791,738,87,407,101,878,440,833,664,520,419,281,525,449,81,951,978,974,593,797,7,38,493,964,169,968,548,103,714,696,306,329,103,563,406,563,117,593,490,591,712,857,868,396,804,602,157,86,368,799,101,565,773,956,860,203,267,348,764,869,316,675,42,500,480,211,772,905,234,230,371,503,632,873,962,23,808,240,947,205,451,301,540,617,910,452,619,881,526,121,982,40,166,929,653,84,756,869,666,859,979,504,953,196,385,0,636,107,735,823,947,627,677,332,86,767,542,746,711,831,586,901,31,912,831,164,381,830,683,957,388,312,728,522,934,829,29,335,975,359,609,484,864,107,443,327,4,334,944,395,884,263,394,998,479,380,953,946,928,42,628,157,697,364,376,145,419,785,69,627,420,21,679,575,421,799,523,828,792,307,390,634,944,850,689,658,957,421,765,3,915,122,246,28,279,413,94,997,51,402,898,96,355,290,228,418,173,554,532,935,400,398,316,14,996,289,656,617,143,730,665,268,684,25,524,593,498,698,804,72,801,856,682,485,849,218,88,645,118,420,481,758,17,890,855,793,313,420,789,589,324,815,927,865,853,138,296,164,851,558,603,661,176,824,67,492,578,127,694,32,109,496,724,430,513,503,510,317,297,512,918,993,470,797,627,18,30,929,253,757,770,270,227,679,242,496,293,828,771,61,193,332,893,894,304,722,539,221,953,607,796,133,916,998,67,416,178,41,346,408,935,120,986,615,304,511,674,229,198,656,940,13,779", + "3,756,897,676,809,779,907,606,872,702,104,959,343,404,927,253,745,676,587,715,309,711,34,225,576,926,117,203,623,83,381,491,687,211,953,399,269,567,107,185,670,217,737,261,124,796,51,643,772,897,739,743,915,766,972,356,395,297,49,613,286,590,66,847,233,282,629,156,955,302,334,185,649,75,854,868,588,902,228,793,624,218,88,432,372,859,443,945,827,578,196,503,771,793,904,412,937,106,61,21,177,482,508,436,233,233,977,362,997,689,817,959,300,700,322,303,362,31,489,379,4,331,494,171,598,474,2,574,253,925,832,825,876,893,402,453,782,603,92,301,84,853,17,511,720,774,930,164,65,388,678,721,281,790,31,408,7,360,550,766,925,830,295,850,217,158,708,784,888,410,952,881,491,479,673,184,151,801,295,509,294,279,658,378,887,356,190,172,699,703,396,706,680,887,727,672,728,155,79,135,693,392,520,63,608,971,640,613,460,71,588,919,590,667,147,597,413,706,51,566,661,554,139,736,520,543,825,477,475,898,830,530,485,438,139,699,864,623,11,346,685,74,969,926,987,704,461,409,126,606,558,88,512,150,501,162,546,277,893,380,206,750,232,779,808,266,991,280,580,956,953,658,213,308,508,207,866,685,837,694,769,718,949,285,583,246,174,101,620,718,232,574,123,965,582,762,463,176,916,941,23,553,773,516,945,978,262,946,614,395,606,41,844,449,396,916,107,337,95,523,452,18,87,716,807,758,375,451,822,232,522,430,657,463,940,615,193,453,556,549,506,942,847,764,426,401,987,689,145,921,972,175,544,664,978,67,227,712,363,48,476,969,135,112,167,964,197,154,477,430,734,662,957,128,527,744,889,522,575,690,203,869,335,188,478,703,926,878,229,698,41,120,88,767,751,973,658,333,620,327,918,487,971,566,936,660,152,158,996,904,691,708,413,349,947,665,419,535,184,760,801,575,697,395,757,638,689,6,389,255,831,924,38,71,855,994,607,296,221,510,25,125,586,822,308,383,293,26,225,928,7,321,613,390,289,990,656,635,854,67,417,944,184,649,911,858,407,521,336,463,41,644,822,991,954,610,886,470,332,153,367,127,271,946,781,886,604,793,829,560,421,556,466,584,520,171,58,745,187,419,354,106,356,865,233,850,289,774,951,669,192,935,9,226,686,448,159,795,852,662,976,140,42,535,147,6,762,603,737,374,481,209,50,274,370,826,254,245,1,411,611,26,485,906,467,565,425,799,548,866,235,505,765,627,673,284,481,928,769,123,305,234,18,59,964,269,176,866,170,2,69,359,847,754,948,946,249,203,301,196,484,35,215,976,198,467,127,64,470,244,489,660,513,175,419,408,905,677,219,553,646,82,913,369,787,667,81,949,27,508,399,256,144,161,890,647,225,393,14,499,812,967,703,67,668,481,980,17,672,690,567,687,438,731,93,938,235,811,768,427,280,82,209,588,364,822,199,302,750,342,666,898,116,392,526,941,128,765,966,367,175,843,695,399,97,359,130,263,950,579,424,442,332,727,460,295,387,755,40,776,593,899,51,761,859,482,172,48,766,466,771,996,34,781,540,301,631,200,298,275,121,290,337,269,543,575,101,747,551,191,417,529,179,651,847,155,72,126,653,839,602,223,687,621,157,528,696,817,617,812,555,744,151,529,106,388,920,712,216,633,562,324,853,476,509,6,882,282,266,418,515,714,394,521,344,369,364,314,883,44,382,924,789,143,353,471,603,132,326,737,370,342,636,0,675,707,408,295,385,701,16,945,480,891,207,766,525,473,992,418,466,920,298,680,902,58,474,912,126,153,478,561,521,4,629,422,634,737,570,737,898,124,249,579,100,166,730,590,385,672,552,865,818,274,308,457,652,423,926,211,846,889,535,834,982,426,847,635,381,992,973,853,834,561,317,104,810,898,159,42,718,809,566,687,270,503,553,955,629,458,447,786,447,575,195,236,168,464,281,129,749,629,251,947,604,225,391,905,92,393,178,623,768,385,779,456,850,858,6,733,603,928,934,369,547,865,202,589,527,660,302,401,576,624,54,74,524,764,170,561,609,946,279,192,91,846,269,517,286,383,351,975,714,759,479,124,309,747,97,889,341,884,211,447,65,763,114,785,40,837,11,390,707,35,35,884,593,110,139,61,78,185,443,602,285,831,177,948,650,133,567,88,392,204,162,416,429,556,927,60,543,371,188,352,890,303,547,378,656,217,554,169,734,298,708,973,632,742,29,36,65,907,960,429,313,6,853,349,738,900", + "523,840,618,831,359,683,24,133,913,850,40,754,245,77,847,425,614,741,789,433,294,152,459,70,256,31,479,267,448,191,581,967,766,989,417,430,133,696,192,615,665,798,740,526,287,215,598,665,789,376,599,428,277,435,132,888,621,643,68,561,946,87,36,574,548,296,332,69,653,345,294,773,845,47,166,261,627,66,253,948,710,613,512,492,1,244,846,928,511,81,325,668,657,691,580,482,683,872,31,876,67,35,90,494,903,468,246,730,54,653,758,593,676,573,106,848,869,985,690,636,794,611,873,865,704,922,658,83,240,570,981,360,877,23,750,96,734,543,383,454,510,189,462,906,613,356,510,348,652,387,13,35,341,559,415,122,591,977,801,410,446,150,907,399,55,530,774,930,790,200,586,211,276,528,34,486,707,979,902,488,538,42,742,193,954,843,642,675,787,93,163,276,386,746,266,890,450,742,823,443,728,244,820,353,697,237,360,376,846,346,495,330,989,66,601,919,916,610,825,418,937,577,606,273,394,100,537,8,499,501,977,255,965,142,785,227,409,945,582,250,491,218,705,803,637,701,528,726,730,282,793,883,564,762,304,504,757,98,173,896,980,771,560,148,668,799,602,341,475,458,701,98,326,820,812,904,72,176,309,284,843,148,577,884,122,518,277,911,204,765,735,986,153,176,627,185,798,780,915,466,783,306,519,938,288,326,416,549,779,819,539,477,337,26,486,543,647,878,88,129,125,696,266,565,924,392,932,944,874,343,438,288,979,447,357,769,905,72,632,320,905,653,180,668,228,339,59,27,659,752,518,360,980,73,359,729,170,451,311,33,3,823,256,947,278,602,509,56,206,175,732,568,14,336,883,364,600,532,374,299,449,624,807,785,831,273,391,371,856,94,727,948,58,312,513,7,168,914,80,277,160,7,434,444,906,238,612,664,651,509,476,141,745,10,266,842,932,892,800,742,234,296,871,923,659,964,408,830,233,591,661,978,453,153,462,122,942,680,653,363,317,412,869,618,688,278,859,232,803,896,740,935,787,713,886,990,470,493,973,536,881,407,53,326,964,750,88,389,954,277,254,287,519,685,384,300,35,777,263,615,738,540,242,789,29,981,196,884,340,91,387,711,81,72,618,932,826,537,931,344,405,69,964,199,554,234,647,829,338,264,489,682,95,601,692,253,761,827,241,715,470,848,791,620,976,653,555,476,534,924,884,312,960,299,83,737,776,449,441,383,642,189,577,918,619,457,223,994,685,260,873,649,536,692,741,239,808,368,247,452,927,479,5,548,942,919,754,721,600,261,356,994,281,23,229,835,234,372,781,170,932,409,868,218,765,584,761,35,619,912,977,66,637,728,934,398,749,660,527,914,653,454,893,729,266,40,957,505,257,33,125,302,975,676,239,529,467,293,793,823,574,261,428,115,638,781,872,161,667,546,936,70,214,373,941,564,927,860,94,282,296,773,741,206,96,511,20,578,488,85,924,684,902,386,514,4,82,172,750,265,255,143,670,303,935,656,329,446,38,695,441,834,147,229,518,712,875,327,855,201,101,700,281,49,521,625,292,812,480,91,793,142,527,333,532,315,979,742,17,578,715,170,133,632,585,981,398,565,72,640,374,96,842,308,814,422,101,846,595,690,844,385,966,515,142,776,129,83,519,289,794,502,632,217,55,67,863,819,137,803,270,596,513,37,174,243,765,399,163,655,136,836,130,142,355,35,269,847,486,840,845,970,928,316,188,165,69,149,743,790,375,488,107,675,0,784,560,336,845,376,656,301,870,540,63,541,380,540,267,975,388,263,374,346,979,183,122,768,668,286,176,536,764,60,894,766,97,278,298,391,296,349,946,134,359,837,805,97,209,206,138,603,245,919,165,482,467,735,781,504,590,771,454,488,777,490,522,894,911,73,627,984,820,906,399,884,993,865,269,811,585,441,955,565,165,954,589,860,588,745,999,964,428,763,822,376,725,760,840,622,995,59,478,536,368,656,259,447,203,948,726,690,45,251,21,609,470,7,619,5,886,307,952,283,720,988,67,426,616,771,776,90,798,447,803,802,240,375,142,384,60,882,1,897,205,931,259,675,671,570,602,959,829,245,331,526,782,621,888,399,363,50,665,652,167,499,480,485,127,706,823,761,584,264,315,695,927,517,177,626,273,503,316,382,222,809,250,461,355,549,797,196,64,811,698,4,484,790,949,695,129,803,545,574,86,442,168,469,954,311,139,205,553,363,369,309,674,816,786,505,879,593,506,380,557,787,708,833,139,428", + "275,748,760,92,276,555,35,710,713,807,914,481,609,729,290,538,298,169,210,860,957,580,159,877,992,484,587,766,160,949,179,223,3,540,788,76,706,267,837,362,465,331,391,801,505,4,617,817,354,106,367,629,192,492,438,186,450,599,4,100,223,132,96,645,536,280,666,986,686,726,476,721,53,748,272,327,584,485,362,14,253,371,351,1,330,351,875,543,980,823,159,553,565,243,51,997,840,507,180,618,875,605,385,131,793,911,755,1000,137,128,259,447,794,544,922,117,768,322,870,597,336,29,585,207,890,172,737,332,935,679,799,21,686,376,1000,544,472,597,236,198,499,37,936,982,493,207,647,118,901,413,734,158,827,956,164,397,530,878,837,819,856,38,787,535,472,732,327,719,26,252,374,427,723,470,45,787,479,320,957,807,613,498,635,259,585,335,420,871,413,381,990,834,628,249,800,583,424,935,728,64,467,182,717,96,930,108,99,687,753,101,225,748,879,832,297,984,20,209,747,718,147,731,799,509,86,309,11,320,130,418,353,334,378,665,301,169,170,473,637,435,720,765,493,845,92,144,401,225,434,17,293,33,313,750,547,576,476,72,264,334,250,985,187,68,69,855,528,182,27,101,681,750,907,119,331,105,358,390,719,26,39,612,728,937,435,910,611,584,360,206,608,961,390,464,909,634,487,534,938,238,430,295,72,263,586,87,729,575,201,594,199,170,414,62,870,416,584,61,393,141,592,442,933,702,677,974,396,532,808,360,864,767,839,206,336,27,867,379,985,577,549,664,73,293,114,495,602,317,324,682,117,729,644,168,461,462,610,18,964,291,340,613,540,302,635,187,649,564,555,417,261,238,494,920,945,814,746,625,290,650,856,359,106,980,263,521,88,638,342,819,302,573,617,707,370,155,743,760,648,423,946,512,573,209,504,69,449,754,506,100,733,817,421,657,91,948,773,526,97,274,583,306,682,532,529,651,52,368,587,21,684,347,83,610,95,757,682,887,78,734,24,254,24,709,74,306,93,587,898,750,259,720,765,505,779,920,584,616,694,797,305,692,705,45,40,858,228,968,650,415,718,220,933,540,540,813,20,747,361,321,561,585,113,593,426,151,256,210,30,592,669,820,94,203,130,385,332,45,85,126,662,583,443,746,730,803,116,355,57,183,970,91,253,667,21,337,649,338,150,380,211,33,831,683,512,918,457,110,491,987,528,233,67,361,997,222,511,943,550,222,31,111,604,415,222,599,92,794,68,373,409,598,347,463,743,60,180,755,124,229,804,704,402,531,812,109,511,268,613,88,463,549,718,590,716,455,296,574,526,892,849,887,298,416,91,950,998,62,514,224,138,202,210,268,599,470,423,680,951,877,282,879,439,854,509,918,997,716,263,565,646,568,883,935,111,179,280,120,652,481,668,709,553,894,118,446,710,185,686,129,798,7,793,256,662,404,936,756,441,316,462,227,558,918,455,749,193,716,349,798,60,696,825,871,991,866,411,382,927,367,99,55,554,387,60,406,585,928,777,444,281,587,586,633,63,701,69,172,217,327,476,874,464,484,522,65,552,125,753,823,984,657,191,401,309,258,780,910,204,534,503,333,936,631,317,97,427,360,199,915,965,653,360,837,301,66,505,287,922,409,579,273,288,170,172,885,961,863,873,581,887,808,762,510,950,328,653,242,833,718,167,888,546,867,454,224,755,206,478,996,818,904,678,710,766,831,925,581,530,749,931,869,61,321,138,679,616,74,549,642,68,690,735,707,784,0,401,946,634,265,46,321,584,544,728,218,697,478,363,437,881,777,458,322,982,75,65,679,667,287,352,332,96,990,793,349,823,175,855,210,145,43,773,436,417,251,290,861,46,840,211,876,329,704,302,85,884,83,350,652,376,406,796,150,169,758,422,72,399,633,118,352,429,997,799,469,518,125,417,531,866,408,501,925,54,291,248,409,692,653,802,896,107,524,555,352,365,200,144,75,48,189,410,263,734,250,516,69,546,446,186,187,466,598,751,40,25,260,297,820,522,24,956,835,859,791,488,765,362,166,151,492,382,737,587,487,777,408,750,600,79,41,741,850,401,456,451,421,624,434,717,660,496,951,593,693,112,171,105,688,790,917,785,211,212,877,428,412,338,176,49,347,835,657,441,385,100,888,787,788,93,566,425,886,536,697,877,245,34,981,284,639,817,288,599,876,770,247,975,191,598,493,555,618,319,242,431,542,890,287,23,728,750,627,494,704,645,978,967,630,162,197,780,361,203,934,41,673,74,264", + "968,901,943,846,533,710,537,763,304,79,983,890,918,585,718,733,792,701,827,994,279,406,796,882,258,676,876,994,229,946,105,994,777,985,630,785,65,522,729,43,359,895,764,364,981,731,332,701,655,321,849,915,16,415,642,308,123,957,372,817,307,23,581,329,68,158,526,65,778,307,862,2,347,863,948,665,231,810,918,139,456,530,520,131,967,447,726,267,997,318,984,225,891,518,378,958,472,106,784,63,625,889,520,611,146,664,385,793,356,898,498,57,350,939,831,503,858,440,247,838,286,850,927,327,924,702,693,834,966,632,305,785,335,848,926,863,824,300,945,82,262,238,718,565,726,7,951,123,680,586,322,543,674,460,196,944,459,952,800,880,841,485,111,561,158,280,171,661,479,58,196,191,947,503,82,524,432,671,746,734,350,184,817,242,40,466,917,478,220,287,18,207,902,718,973,954,324,154,831,642,590,610,258,451,254,626,851,697,143,693,436,666,16,677,324,767,92,185,884,741,928,49,653,818,26,441,333,312,440,36,348,360,727,944,949,885,475,853,295,893,279,674,687,226,927,752,19,982,354,564,339,689,313,384,129,386,827,898,144,801,201,877,738,911,331,762,533,515,176,872,620,246,842,708,210,420,730,434,120,867,273,414,728,462,452,538,479,470,113,191,766,226,167,309,661,568,625,280,188,653,981,441,323,567,440,486,353,11,607,223,175,122,743,423,427,56,554,718,11,108,389,913,998,615,485,971,895,433,95,896,661,427,570,547,843,988,46,800,518,620,208,778,939,237,315,461,810,922,123,690,317,891,190,236,300,322,662,510,977,627,49,43,315,877,932,804,339,912,953,813,751,583,245,791,65,894,193,812,663,574,508,98,176,944,519,195,912,472,564,611,5,401,135,33,933,919,49,177,528,819,782,236,925,839,418,944,720,223,207,264,525,124,768,121,870,837,838,371,344,694,836,729,733,463,340,931,449,313,814,592,215,599,375,348,392,682,395,307,75,248,748,139,444,436,47,752,245,47,252,650,583,574,362,354,270,174,111,989,821,533,313,337,786,481,90,434,88,953,489,600,986,510,810,35,77,926,113,249,33,698,900,71,920,936,569,524,219,651,815,652,105,412,154,392,928,935,474,935,64,818,356,250,583,341,146,552,66,475,859,378,22,591,131,506,479,69,902,558,500,948,874,71,120,442,983,351,531,190,241,728,208,187,39,28,397,500,141,432,517,227,105,556,866,66,960,537,134,613,628,191,472,195,488,910,755,394,841,724,428,138,738,507,565,432,627,757,921,139,199,221,12,375,965,733,781,135,443,955,613,399,900,39,119,905,652,382,371,243,943,83,634,818,94,857,432,356,29,963,475,865,20,771,511,942,231,152,693,361,687,870,547,253,221,605,756,223,63,55,849,902,657,307,627,664,565,539,33,81,341,400,106,267,387,185,124,303,350,705,326,529,813,920,269,551,851,744,357,768,941,385,478,344,971,721,621,170,468,724,607,250,282,828,915,94,533,551,621,847,399,384,364,773,362,814,63,935,702,124,615,61,834,898,738,419,262,729,855,62,420,262,560,865,591,507,134,922,132,694,452,575,259,69,929,172,308,782,652,542,351,879,424,951,898,229,774,895,520,798,151,161,983,914,49,602,306,924,924,671,370,634,707,354,279,855,826,248,115,178,527,331,189,225,236,293,318,910,265,755,434,11,49,970,938,465,27,114,629,942,494,259,75,375,855,544,352,982,335,117,246,66,905,752,823,408,560,401,0,589,411,925,807,370,702,826,46,561,277,157,348,978,472,517,893,906,917,588,706,953,581,786,623,53,235,414,543,430,239,582,947,969,138,407,513,463,51,671,482,379,189,972,563,638,612,59,588,500,451,841,859,328,478,594,271,618,970,714,409,775,259,424,151,569,154,883,16,312,941,397,348,890,693,395,419,963,554,880,483,396,486,300,565,626,420,774,931,500,719,479,223,200,522,133,493,553,105,966,130,625,125,751,304,754,193,826,912,213,122,117,18,796,754,648,358,468,360,223,335,578,785,734,741,35,427,249,140,238,245,819,454,675,365,718,833,40,906,657,170,136,956,160,564,47,366,304,682,816,397,497,319,971,342,314,147,388,699,839,142,617,69,457,458,532,150,315,913,191,60,294,378,831,846,234,714,371,64,511,989,517,534,723,353,166,471,492,670,217,104,127,460,446,620,107,773,773,318,285,964,45,335,558,680,152,490,589,972,916,505,59,891,325,885,309,108,281,901,34,177,462,880,501", + "342,385,24,775,921,68,311,302,195,891,394,916,317,36,777,775,616,869,471,143,714,149,499,172,448,432,554,547,898,365,101,909,711,379,446,223,652,254,121,635,233,585,190,228,928,332,684,928,491,985,380,242,900,384,590,234,242,961,476,81,183,36,204,593,352,428,951,664,352,481,648,79,866,929,95,500,836,369,399,665,669,232,259,664,424,834,561,913,910,490,287,710,366,142,266,665,409,833,725,102,767,701,569,257,863,98,144,656,997,379,779,207,144,226,845,768,728,911,941,134,420,296,882,348,838,661,664,427,316,384,6,433,531,298,39,722,422,324,846,544,666,881,941,657,781,563,144,599,231,491,964,483,46,161,164,71,250,255,94,525,555,16,95,753,142,689,898,331,857,681,773,29,651,417,74,957,760,905,790,582,976,112,97,125,669,934,223,612,858,92,87,74,729,150,591,511,278,128,598,384,111,155,908,957,181,790,322,565,227,512,925,800,403,267,572,981,435,122,929,283,573,205,818,185,698,85,640,368,222,636,384,267,953,73,643,304,39,319,715,975,486,474,155,957,857,247,168,14,859,317,683,199,318,464,465,304,907,660,243,888,15,487,661,584,334,25,886,912,754,685,477,32,546,912,878,489,504,197,637,530,885,72,824,297,393,313,476,712,739,190,393,255,248,438,240,184,70,316,324,262,293,464,656,943,180,742,477,841,792,902,495,468,546,273,200,823,629,200,891,130,450,488,839,628,789,267,280,78,423,765,934,532,8,265,829,995,396,34,710,783,670,604,742,332,914,595,172,191,473,809,624,527,831,521,47,232,117,452,223,705,37,124,877,183,434,380,846,309,187,101,614,411,352,727,231,377,834,955,371,563,794,650,576,531,204,456,106,187,582,278,498,185,802,539,484,466,4,384,409,883,965,525,767,20,588,15,697,14,67,29,276,220,664,189,423,404,844,267,773,362,182,321,611,171,325,5,878,574,210,39,216,728,740,880,894,862,556,333,509,950,853,465,254,77,6,494,826,376,63,454,796,463,287,611,612,350,375,619,798,902,479,239,34,383,752,170,842,924,653,970,383,340,454,92,247,802,41,48,574,663,726,256,258,706,503,127,812,652,149,904,635,870,844,706,9,492,703,572,613,964,143,850,606,815,514,251,886,304,505,378,892,223,639,924,69,733,295,511,200,340,281,312,773,422,128,748,961,683,433,548,926,447,485,867,26,262,520,970,591,172,510,672,564,607,326,190,438,379,365,122,46,925,325,532,470,610,12,538,359,732,923,547,359,993,268,178,793,776,485,828,29,864,217,265,389,873,844,137,309,173,878,76,766,657,436,131,433,846,444,418,646,654,680,908,567,754,556,786,915,616,107,701,207,809,42,383,344,590,756,752,628,883,34,804,583,143,858,90,181,679,530,391,501,257,864,273,545,743,29,719,702,230,111,266,461,459,3,491,959,306,843,257,936,523,490,25,935,621,839,145,291,700,953,488,455,19,530,652,466,395,348,462,97,805,793,3,871,691,5,56,803,184,648,280,975,257,278,882,274,211,338,763,562,299,99,198,430,788,302,599,780,985,401,500,77,536,532,911,489,144,939,275,294,664,915,822,91,878,814,503,133,726,226,989,964,149,830,294,735,780,435,394,349,913,332,379,600,727,893,715,350,48,251,256,708,211,178,226,171,586,693,511,411,144,957,397,198,495,21,343,461,243,177,899,943,625,40,661,530,651,71,178,368,780,669,311,520,84,592,35,151,784,947,295,336,946,589,0,881,276,232,839,80,618,310,64,357,204,468,499,81,536,197,404,246,642,598,364,448,40,168,706,45,770,709,150,269,18,154,798,271,966,92,502,382,222,989,148,373,417,513,507,290,644,993,688,646,521,362,501,930,124,964,369,471,790,226,522,786,476,974,999,88,453,603,556,680,964,499,326,137,334,486,563,857,707,127,765,750,354,156,261,175,541,157,695,507,22,825,289,332,335,144,361,161,347,614,82,468,553,869,372,315,927,29,723,135,25,338,782,239,11,254,734,127,877,387,228,523,202,970,698,774,863,394,31,560,121,151,929,289,223,543,491,704,886,945,49,478,236,664,177,982,546,515,920,340,930,152,463,217,546,763,11,415,350,246,649,341,127,97,246,108,808,194,9,526,931,718,535,364,873,951,297,162,724,994,266,427,887,375,775,50,683,6,6,473,694,280,800,110,929,293,509,398,110,538,722,114,263,827,28,956,59,985,349,790,734,637,418,201,377,493,921,360,141,22,655,540,260", + "759,514,834,142,150,186,783,548,235,683,939,648,355,546,714,857,755,274,946,741,886,731,448,942,66,961,219,699,343,756,270,303,382,248,319,305,693,874,584,150,895,877,75,229,29,14,736,981,574,2,786,397,473,303,61,6,107,465,134,34,387,314,28,503,445,210,348,848,58,979,312,544,322,146,542,606,426,513,510,799,804,243,409,666,80,615,483,287,815,183,142,758,891,932,775,749,79,374,333,799,222,535,802,234,903,152,836,334,948,334,326,520,122,604,376,253,937,360,140,269,467,894,446,673,887,569,156,241,675,338,671,38,365,92,640,807,706,899,419,197,860,785,691,533,583,652,595,359,549,784,829,717,223,908,317,543,372,315,613,767,459,894,813,628,265,771,257,496,808,530,7,970,893,479,257,446,986,851,7,700,863,563,405,982,521,874,794,699,575,825,130,923,352,659,843,711,204,685,48,116,313,189,59,222,35,213,371,49,183,488,336,343,852,636,161,221,623,719,887,207,987,426,510,397,765,59,651,938,597,303,867,278,516,383,825,665,470,935,457,240,80,300,170,992,744,988,836,511,960,953,653,322,421,28,6,693,593,974,613,261,87,996,1,175,124,752,46,634,747,209,523,319,823,17,909,974,773,345,283,285,60,839,334,393,214,207,963,430,327,6,89,291,161,563,265,538,264,759,461,66,402,371,53,598,603,421,400,830,857,546,240,339,565,812,889,934,912,328,110,158,231,590,482,415,94,189,854,781,634,101,216,585,706,966,88,453,881,341,430,702,151,738,313,284,517,344,795,166,850,265,235,768,290,262,652,733,684,602,666,21,263,351,712,879,105,612,266,373,792,902,586,407,802,541,401,873,105,566,819,463,709,651,365,490,451,449,2,688,235,321,611,95,359,331,443,667,264,170,117,122,659,217,905,727,655,685,992,180,204,114,367,468,136,291,976,200,714,513,888,696,934,114,723,609,673,369,378,26,873,764,775,637,908,348,107,805,962,340,565,571,718,214,720,543,222,54,835,12,3,725,379,428,508,599,566,705,863,258,806,284,935,783,250,617,428,430,362,935,414,536,641,481,172,725,809,967,494,146,102,291,435,309,727,777,396,832,743,711,955,591,949,486,612,823,466,192,487,949,566,404,110,461,716,164,140,630,421,984,491,921,235,691,166,44,657,143,215,473,92,802,877,13,862,190,172,889,380,819,588,615,262,972,647,464,781,334,423,885,995,915,489,307,590,105,457,562,814,790,187,431,988,608,916,92,425,240,220,405,85,287,664,875,248,573,538,991,523,491,843,404,638,866,676,690,911,988,24,214,761,864,343,705,692,235,928,410,971,760,528,644,174,136,32,551,429,242,806,662,125,867,43,260,61,556,446,343,765,884,251,91,171,715,498,770,992,367,671,59,935,233,590,509,890,323,37,811,369,488,18,129,26,407,840,968,848,988,611,297,690,780,931,141,608,383,141,763,894,68,395,115,419,374,213,391,837,603,176,904,365,732,119,88,693,605,860,953,419,363,955,134,40,455,766,515,657,142,345,662,666,294,440,222,58,961,93,861,494,19,145,23,984,296,102,434,844,150,155,773,754,300,670,944,516,725,684,174,666,539,414,796,939,90,9,356,635,658,988,550,368,793,810,847,882,568,811,250,899,166,915,924,446,544,594,225,878,861,410,983,945,465,419,792,188,647,937,408,833,861,597,2,874,849,280,833,785,152,552,6,371,238,663,832,178,356,155,225,963,435,669,642,607,609,627,385,845,634,411,881,0,411,475,716,354,563,855,856,496,999,949,672,22,714,265,530,880,321,792,44,435,922,436,620,2,291,501,58,710,975,13,463,557,974,897,282,648,4,163,67,774,343,629,232,903,322,619,915,371,677,695,395,667,18,720,422,106,582,194,501,293,321,694,220,789,115,633,590,265,830,527,758,585,169,345,594,162,231,49,132,284,165,528,994,78,756,781,650,997,531,171,771,579,548,88,418,723,808,207,640,769,83,227,704,511,839,326,382,548,482,815,539,863,905,612,848,652,686,474,995,728,459,147,556,754,12,657,705,950,201,453,247,815,3,245,466,637,261,999,98,571,600,212,668,503,950,852,215,575,769,796,268,662,733,794,603,546,484,904,797,897,854,501,440,535,286,479,763,352,980,156,553,548,654,256,551,83,803,330,301,11,148,317,185,261,657,272,765,769,820,542,350,806,164,490,88,604,241,166,350,309,633,206,110,128,105,35,402,473,756,76,359,620,512,282,336,935,488,527,276,446,813", + "765,720,426,839,496,640,799,843,708,448,358,678,222,154,154,98,650,120,997,320,892,308,354,934,102,205,607,702,94,599,582,833,671,3,555,893,438,612,84,266,22,818,266,104,949,895,970,421,179,376,229,955,709,80,729,93,139,710,470,35,571,800,582,899,908,393,152,540,448,718,831,918,85,541,165,491,60,24,841,487,859,276,944,929,256,685,466,958,895,954,58,410,959,748,214,618,471,281,676,976,122,283,832,27,633,725,22,770,102,446,581,30,113,424,347,485,910,157,290,770,88,92,269,756,766,179,443,222,643,606,860,163,931,808,977,666,395,700,67,553,122,770,723,337,90,756,121,439,948,796,853,744,156,183,991,62,999,24,325,428,58,99,919,774,582,43,634,953,516,599,984,23,440,745,465,136,44,307,94,981,553,977,424,900,520,191,539,881,998,401,764,203,15,385,74,603,119,271,500,153,113,232,403,291,876,29,906,813,759,385,638,809,547,541,786,920,200,616,461,185,877,396,675,749,585,287,312,50,408,69,890,886,898,824,308,343,217,739,307,499,913,184,390,495,658,245,752,253,808,477,480,496,342,110,534,362,811,279,581,810,592,668,654,711,808,673,299,154,605,77,382,4,233,862,114,168,919,76,232,151,332,940,928,372,743,499,583,488,9,319,500,545,866,234,153,225,191,424,427,491,890,536,990,49,923,907,684,336,682,712,238,374,332,959,633,476,608,707,647,743,246,136,659,312,39,473,183,747,995,81,994,301,17,583,63,459,252,558,179,280,862,213,158,235,938,815,468,653,996,593,783,830,252,263,277,607,381,439,887,481,546,844,115,964,344,301,865,304,429,792,391,129,704,88,733,542,809,427,834,446,661,773,395,650,530,483,528,49,112,99,566,122,461,33,309,367,291,448,642,465,693,214,680,400,784,249,97,312,87,592,708,63,163,883,595,810,597,121,235,712,639,323,884,615,203,298,262,757,244,685,912,818,23,304,229,788,987,182,121,136,863,805,424,962,240,353,382,471,242,534,576,87,286,860,917,89,546,772,186,785,689,48,358,641,892,698,140,327,936,814,26,731,896,960,280,254,330,859,992,915,85,47,514,527,800,687,52,620,960,113,970,833,664,445,808,937,535,123,74,79,895,439,360,320,995,139,818,607,565,478,481,94,39,506,880,746,243,266,783,606,115,830,64,659,714,869,832,445,349,908,233,869,990,279,526,793,551,178,332,714,126,384,645,52,807,882,559,136,494,257,192,164,994,885,850,697,144,840,411,480,145,40,402,567,277,370,765,61,34,707,953,872,416,265,827,933,664,737,924,68,91,806,35,536,505,28,151,193,14,98,284,889,131,588,512,398,680,278,242,331,497,814,610,373,140,632,717,163,325,740,735,529,798,857,284,264,523,104,192,196,184,311,933,370,447,478,158,725,440,527,107,954,693,688,445,807,711,253,162,48,771,398,539,868,730,301,854,277,572,167,375,51,44,846,506,629,433,136,619,668,521,930,225,322,273,496,451,419,748,844,344,329,913,429,720,952,169,598,295,837,617,823,169,242,110,59,445,685,354,108,396,585,727,342,49,341,394,233,324,151,938,286,897,46,217,453,353,66,418,150,811,832,966,88,760,522,214,953,239,398,656,870,483,781,158,949,586,998,908,548,45,553,903,455,400,120,780,583,834,79,908,675,88,683,102,850,437,579,740,268,280,532,722,379,900,516,742,408,418,215,278,227,879,790,570,85,198,844,724,884,392,972,677,701,376,265,925,276,411,0,509,899,855,439,140,882,829,266,310,397,280,183,994,996,338,878,531,256,172,910,847,163,696,19,685,710,507,607,600,314,45,722,737,114,935,753,705,5,637,68,981,245,988,922,134,637,230,804,712,182,708,149,545,384,331,370,402,946,698,44,451,350,763,744,126,401,927,735,120,742,672,570,411,24,220,503,886,569,838,326,117,768,503,465,930,986,750,437,969,256,384,101,17,377,307,188,523,817,678,175,818,671,632,309,115,977,489,778,733,639,437,468,535,11,542,922,468,721,838,757,277,38,30,523,338,521,601,907,312,726,857,364,319,313,513,617,845,97,110,212,354,795,383,81,485,209,841,963,500,569,206,440,660,2,147,765,278,959,284,63,525,356,127,140,264,898,101,563,215,83,414,394,816,46,716,845,500,365,604,725,969,526,407,634,352,592,973,932,13,594,106,137,390,116,824,773,343,125,865,645,760,665,963,518,279,861,316,22,602,669,631,70,934,138,704,76,634,706,530,872", + "907,113,894,268,606,200,657,55,176,559,665,152,572,983,628,12,655,37,228,625,9,71,566,288,100,547,348,266,474,479,995,868,344,824,31,44,44,228,444,398,248,663,720,132,835,604,699,44,870,167,80,495,368,401,837,456,639,495,423,469,996,290,538,149,234,996,505,530,591,508,17,436,233,265,446,20,131,782,318,708,637,501,928,527,83,572,179,860,385,565,84,301,615,100,712,425,356,115,611,206,739,683,887,505,298,713,14,394,341,859,616,756,801,100,855,265,351,950,32,307,303,157,195,458,340,167,336,513,949,809,655,656,770,447,208,166,579,682,333,98,750,47,55,625,156,237,610,263,902,178,103,113,170,412,374,292,505,306,215,390,529,800,217,668,531,513,459,354,130,578,198,688,160,721,724,86,925,425,53,673,679,201,667,952,289,939,168,877,605,711,314,292,578,403,572,412,642,797,356,954,810,409,41,463,238,730,681,146,247,663,183,642,738,422,119,938,308,852,42,150,71,213,988,159,303,867,297,12,741,877,416,37,54,987,384,94,131,443,941,216,730,663,548,270,181,91,27,408,951,978,11,928,1,200,221,650,814,297,414,746,898,919,151,969,347,799,877,423,579,861,977,690,724,679,384,378,683,846,151,9,999,64,772,673,585,787,959,536,221,655,690,563,846,183,362,272,343,661,813,110,845,790,511,638,535,35,911,625,720,604,31,233,810,805,489,568,227,129,649,185,858,355,925,624,322,440,153,734,1,441,279,277,951,520,346,492,784,949,23,640,957,944,392,388,960,107,419,987,500,818,55,653,290,881,5,963,447,727,871,65,65,868,358,55,940,423,796,995,755,850,499,659,109,448,968,64,654,429,397,992,378,467,771,246,28,694,874,546,100,262,900,450,355,140,7,252,693,641,92,236,564,68,76,808,786,710,145,807,543,217,4,117,322,427,819,234,100,280,986,132,76,632,685,609,808,329,73,943,350,926,485,729,475,764,287,356,593,580,354,679,7,642,542,867,409,844,518,952,665,820,348,658,879,269,818,277,980,459,504,602,748,369,444,908,350,577,820,430,359,331,2,321,583,188,507,419,74,511,978,172,672,765,647,154,604,104,264,349,432,798,834,504,997,820,704,942,717,739,187,152,236,814,62,349,757,179,973,289,362,670,376,592,309,857,183,632,275,75,173,435,387,351,919,766,233,268,582,475,440,827,522,730,623,15,331,772,353,207,482,314,512,723,42,737,546,973,544,37,455,246,468,539,830,276,765,806,911,652,24,729,599,862,978,555,980,335,11,136,302,988,359,649,64,544,282,34,451,252,33,665,700,233,507,648,780,430,2,22,301,665,703,686,318,434,490,589,169,494,909,487,476,595,231,764,915,513,546,199,53,62,595,726,518,2,874,521,652,383,616,622,152,167,798,277,461,858,545,761,221,921,100,901,677,905,576,695,650,407,899,684,217,446,988,714,208,601,604,561,924,132,796,582,224,674,11,613,583,552,783,670,37,878,952,36,213,855,272,930,578,927,139,571,379,289,863,559,749,943,797,30,140,742,29,85,4,855,751,673,766,731,60,836,419,154,307,322,408,507,811,246,29,256,360,265,478,198,916,293,476,449,198,895,237,191,97,560,339,469,639,460,436,48,920,526,35,675,735,218,805,135,895,358,998,719,438,371,31,718,683,699,580,307,829,957,653,503,266,624,885,93,607,830,700,783,627,518,37,114,589,313,555,182,903,523,366,758,31,37,260,164,568,418,332,16,656,46,807,232,475,509,0,170,397,926,292,766,59,81,706,440,38,598,460,705,773,859,637,211,451,975,643,562,609,509,356,837,344,60,154,727,891,229,582,769,889,350,492,204,377,42,752,95,639,8,699,952,165,466,395,547,975,646,20,4,78,16,829,588,887,231,809,137,82,660,282,817,745,254,930,378,455,546,220,239,961,860,142,920,7,443,675,428,940,809,976,858,202,637,380,970,856,826,136,162,546,449,4,113,929,710,822,358,776,488,861,392,682,12,851,89,955,634,847,183,311,136,987,410,469,233,254,729,759,708,113,890,87,758,974,706,682,989,553,657,398,918,776,590,372,619,874,610,746,659,110,799,607,635,194,734,627,839,285,360,21,341,880,998,913,460,663,594,141,441,227,605,601,761,563,622,187,439,601,420,500,764,118,907,514,346,340,488,259,482,928,604,115,210,691,160,743,986,479,806,797,178,977,670,852,411,787,78,187,670,204,92,305,382,454,949,337,461,919,8,107,684,729,428,991,796", + "624,972,126,538,147,301,11,568,495,195,474,116,437,58,885,11,430,958,312,567,911,206,103,446,864,314,761,424,734,931,180,381,845,731,517,840,232,775,41,405,237,727,258,680,5,178,867,256,70,212,204,533,538,842,664,444,658,959,280,819,448,296,120,130,244,127,166,413,923,601,408,786,165,442,715,948,561,139,851,908,409,91,597,136,28,661,894,824,345,319,155,785,804,161,599,669,449,697,399,189,505,668,516,137,901,765,433,767,275,289,17,210,89,928,455,205,696,960,720,162,117,718,683,769,524,363,143,559,48,519,991,378,974,83,631,380,567,643,718,4,74,645,86,692,860,487,609,987,143,508,851,86,685,158,908,491,744,618,533,230,309,215,715,761,556,268,891,302,870,255,237,200,95,432,814,639,113,966,181,783,109,905,829,798,447,715,606,564,559,355,362,444,704,501,737,876,315,155,683,808,574,186,460,517,753,43,128,463,706,392,762,181,568,106,659,70,556,708,468,518,323,262,914,804,687,51,333,987,501,273,681,855,535,650,892,666,114,885,218,137,86,26,387,638,525,245,892,138,206,76,709,583,224,940,235,584,750,65,134,580,668,716,244,263,201,802,906,94,848,91,568,477,788,496,500,584,241,694,234,746,266,806,987,468,82,265,797,995,8,803,551,823,519,643,558,32,962,934,970,670,675,514,307,913,876,155,128,501,262,522,755,39,310,962,106,167,63,608,334,719,54,979,118,498,60,213,419,521,841,664,161,828,642,94,779,3,246,958,694,137,547,52,549,614,104,895,262,651,294,656,898,152,467,58,219,628,665,137,447,389,296,899,392,247,635,970,428,236,296,807,147,690,581,289,674,31,426,280,683,70,317,762,824,758,865,737,981,972,787,380,794,314,750,152,339,473,906,384,931,192,904,270,245,927,594,404,363,950,15,394,686,760,687,137,656,503,836,336,206,817,348,208,397,425,232,228,269,115,5,338,857,160,377,636,50,424,730,757,221,582,640,562,986,931,421,777,509,179,252,617,984,894,709,457,495,642,798,473,253,231,115,807,9,173,793,121,576,163,539,153,122,723,291,926,154,672,891,128,306,278,482,120,611,27,116,804,929,168,243,751,70,546,257,938,289,638,136,744,911,183,327,182,644,607,114,427,596,774,592,330,703,556,464,697,75,580,205,18,184,459,108,797,735,736,641,3,301,92,342,754,126,223,520,897,509,879,278,277,73,694,953,5,931,294,36,792,736,483,560,956,26,933,371,252,609,359,327,154,632,550,704,380,894,693,127,144,580,444,478,849,251,896,761,630,673,831,591,782,430,573,916,720,186,635,226,56,309,277,368,278,959,566,229,973,265,311,53,650,112,177,10,857,678,184,441,298,917,955,908,295,429,197,338,734,845,852,692,544,444,326,174,691,125,256,265,240,835,32,692,49,358,236,735,381,928,40,479,379,721,66,958,966,681,973,955,991,874,277,85,523,445,190,632,393,790,902,277,513,226,479,713,221,752,85,799,861,776,953,324,748,221,894,400,278,504,891,383,223,21,771,972,862,552,497,812,365,278,868,215,939,387,205,711,484,774,509,146,747,254,41,534,780,964,874,510,172,602,564,820,54,53,499,276,658,215,238,29,345,349,998,48,760,458,700,535,78,872,632,433,587,843,455,89,138,549,830,500,498,209,818,289,201,425,851,157,704,534,371,388,228,287,265,120,925,590,871,277,748,290,510,424,470,873,4,30,5,91,267,916,355,182,99,86,945,301,321,370,839,716,899,170,0,781,177,418,404,167,543,607,136,121,548,119,395,578,343,632,667,101,259,495,103,194,568,52,95,152,98,54,940,825,891,182,518,713,823,553,280,342,119,105,800,844,657,854,44,108,663,143,855,261,387,978,159,399,331,86,651,802,561,167,60,626,690,349,668,283,482,307,484,536,756,232,334,645,463,567,647,616,355,524,97,713,327,993,522,843,710,144,66,64,670,956,370,373,409,329,820,210,163,23,976,894,585,188,42,427,730,240,324,245,984,660,158,966,204,836,399,638,368,943,907,200,784,198,538,685,394,944,95,211,195,95,451,509,472,779,866,876,570,613,604,753,652,983,145,748,938,833,787,715,50,973,344,182,59,280,458,767,325,281,726,954,394,153,608,155,723,268,145,108,786,203,51,203,110,277,888,172,499,334,815,624,898,203,822,749,203,938,470,378,683,798,520,764,554,117,297,10,696,375,298,207,924,835,515,731,781,539,729,394,44,672,299,427,414,265,898,61,543", + "468,196,413,803,111,599,792,560,552,184,512,432,188,329,360,688,514,970,12,574,423,995,986,848,696,171,396,206,916,682,44,336,529,685,717,324,30,364,439,371,226,719,916,833,16,401,428,369,952,317,341,853,205,306,552,187,609,415,610,953,183,271,322,173,906,336,310,955,453,53,962,608,855,503,442,670,520,402,304,672,360,256,116,988,535,250,909,46,216,468,342,236,243,845,2,405,659,952,414,663,650,388,124,592,465,437,788,449,793,814,642,83,111,781,434,62,209,981,920,263,985,617,698,908,542,402,502,871,307,69,774,110,929,662,840,45,856,288,692,278,591,405,210,595,222,91,22,341,763,806,539,604,8,371,103,295,737,343,843,577,141,273,612,270,691,71,584,473,500,611,857,28,884,744,773,818,28,853,503,174,869,597,861,155,292,464,872,241,484,530,142,777,231,737,748,820,67,364,37,16,343,273,6,979,2,25,971,52,140,431,965,724,813,152,252,202,31,191,780,186,12,436,442,919,969,871,459,438,366,734,485,252,662,538,775,109,721,66,233,318,602,764,811,66,816,62,968,608,316,134,596,547,352,987,24,821,943,173,317,946,984,69,319,878,93,547,964,285,657,735,82,33,45,741,697,864,143,19,722,458,265,110,826,587,462,70,540,45,102,321,333,510,208,935,190,739,759,73,371,443,972,216,811,41,739,760,703,905,293,817,222,962,95,713,52,636,741,539,83,386,210,705,896,535,880,168,7,518,410,328,971,761,729,779,92,204,862,82,158,647,744,874,415,560,551,980,879,352,502,583,738,124,281,109,776,270,362,860,735,783,297,351,54,95,590,120,135,715,117,618,16,641,891,702,879,245,968,497,948,164,469,657,457,19,817,453,865,272,750,194,755,515,972,949,683,452,206,432,85,852,547,168,996,471,317,755,967,651,194,254,364,762,674,918,533,811,836,91,660,729,602,860,254,569,948,251,197,338,787,922,760,760,539,969,797,728,1,6,484,310,631,348,985,148,521,185,939,770,886,215,141,707,633,497,113,216,135,70,194,206,940,927,837,940,580,513,880,303,729,245,433,606,488,806,607,873,811,587,814,80,913,610,974,42,513,887,346,288,806,495,614,838,46,636,694,351,175,77,739,955,645,806,865,68,120,617,330,177,9,741,615,906,692,295,779,579,418,498,212,719,186,772,753,448,48,706,541,654,486,193,50,476,639,200,584,758,994,47,240,419,100,235,395,974,962,168,323,245,423,461,603,749,124,398,632,82,538,401,330,202,147,482,95,595,642,6,372,372,971,789,672,310,959,923,803,213,334,886,252,380,218,318,635,157,329,202,110,323,873,991,313,568,758,44,581,271,554,278,992,933,870,717,989,919,953,134,92,794,365,266,985,90,239,730,359,823,860,387,759,340,93,562,533,867,438,434,531,429,339,800,7,481,625,64,849,220,280,757,767,700,184,454,409,194,336,876,605,294,827,696,449,805,84,480,754,867,902,268,403,420,11,788,999,777,64,940,189,306,305,446,651,815,376,435,579,488,49,843,738,409,422,281,318,568,104,416,449,79,715,823,691,405,158,949,819,345,906,537,81,747,325,972,442,777,655,892,536,701,468,976,408,742,676,306,895,462,236,176,823,579,946,47,440,440,442,431,130,23,186,930,41,958,955,251,931,712,724,633,374,920,263,529,990,278,838,125,232,323,83,116,483,703,938,923,366,237,696,158,265,438,297,671,641,980,197,494,388,853,953,317,433,494,767,480,870,584,702,80,354,855,397,781,0,955,551,720,549,171,844,769,199,758,266,485,139,69,909,399,215,228,167,8,529,467,819,469,389,480,257,449,731,789,721,837,966,861,919,169,246,879,434,474,144,106,636,112,118,243,989,142,484,987,112,390,431,29,92,138,386,119,329,361,963,273,121,79,136,525,600,278,447,420,342,882,971,658,540,588,442,272,98,601,524,391,807,61,843,149,841,274,318,78,917,712,61,794,576,419,713,170,509,556,614,339,819,367,66,141,260,159,725,728,632,282,263,349,528,216,976,929,30,442,275,606,455,246,51,376,22,964,843,596,630,767,429,325,525,122,730,519,31,408,514,124,316,573,45,138,700,730,102,460,421,21,846,498,228,619,81,885,926,21,251,265,539,904,649,159,849,9,244,493,468,963,113,271,257,66,927,344,296,936,227,684,178,507,800,444,108,179,106,393,129,984,58,464,530,536,698,717,479,846,781,46,579,579,59,457,875,899,77,788,947,967,937,767,940,832,115,855", + "674,509,484,695,541,320,52,640,809,424,946,497,745,522,705,482,388,195,699,55,489,956,925,314,336,109,963,263,155,667,249,230,443,407,894,399,483,101,236,669,101,386,395,457,598,389,175,741,32,28,820,322,473,595,304,10,414,176,255,62,411,316,884,109,948,805,167,705,237,353,683,180,770,355,740,236,315,336,965,564,63,740,297,16,140,282,450,672,942,951,998,601,627,708,554,753,421,147,514,673,86,252,645,814,693,729,100,291,604,404,603,573,623,141,473,261,445,714,367,466,717,975,802,226,755,28,18,351,853,844,695,264,976,752,318,952,40,368,543,601,301,644,794,450,829,470,961,777,207,48,498,490,517,774,222,606,981,535,383,597,895,983,995,682,979,514,831,124,103,56,823,402,921,880,254,898,456,532,614,530,308,306,423,9,137,200,501,538,692,976,104,242,968,548,603,141,482,979,998,817,753,292,48,201,512,136,769,189,183,846,993,927,124,866,82,92,171,470,27,605,277,717,891,62,786,946,624,241,342,13,468,890,457,33,126,507,906,847,361,548,133,566,502,659,816,712,841,378,188,26,420,112,966,134,616,555,43,597,780,207,213,378,498,59,681,943,220,227,510,517,892,891,548,427,425,78,698,966,61,807,270,730,55,186,407,884,358,968,826,468,137,934,374,280,193,59,102,204,854,431,452,302,685,352,100,846,862,372,244,856,156,956,822,155,909,802,328,698,811,861,193,864,218,186,70,290,739,234,178,63,987,207,380,930,408,627,682,255,992,155,787,309,252,184,373,514,34,684,987,21,62,691,622,883,138,551,816,41,838,98,169,925,887,480,81,693,125,894,372,65,719,446,17,655,468,913,206,382,381,762,778,942,468,791,869,351,949,101,17,722,149,439,99,14,735,903,112,523,268,435,80,134,743,521,844,865,663,338,156,141,228,740,993,877,251,782,610,124,47,362,128,871,905,520,801,761,459,296,876,261,905,959,373,532,458,756,738,363,603,298,909,301,126,112,72,699,924,172,417,944,608,160,205,27,984,970,361,800,140,360,303,18,64,26,418,463,185,422,512,965,663,245,253,785,210,198,643,132,477,200,616,764,823,805,789,445,212,647,922,910,324,589,23,724,693,70,234,248,872,201,532,42,767,17,502,894,815,13,227,114,558,135,755,459,373,530,999,168,367,428,406,964,97,794,346,185,397,190,884,800,491,368,561,248,205,519,527,172,229,834,706,942,444,321,415,64,656,327,222,410,982,722,616,759,84,543,54,163,817,572,267,588,467,253,391,996,205,820,33,251,950,525,733,395,980,226,273,747,832,15,370,948,909,740,300,556,852,385,303,962,831,187,501,925,622,83,402,466,604,479,354,970,583,400,504,217,179,232,914,470,206,833,805,666,401,776,213,712,633,747,730,627,948,386,975,952,886,711,851,121,869,595,810,947,603,387,469,947,902,601,162,582,874,74,110,349,900,579,245,213,957,607,178,24,554,576,720,439,973,633,933,685,26,40,998,990,154,936,424,393,46,748,104,349,405,590,530,126,811,463,309,354,173,57,199,377,825,616,382,548,618,331,286,677,209,72,32,863,742,521,674,542,204,195,186,671,193,337,456,774,452,922,594,893,149,144,159,428,558,134,466,834,123,380,327,421,985,426,761,486,912,614,608,544,759,849,243,829,78,239,810,148,839,164,145,287,79,903,203,2,288,425,912,287,446,45,320,896,862,77,677,510,864,775,479,44,352,19,362,521,369,367,542,891,540,544,826,618,563,439,926,177,955,0,277,413,204,583,533,985,797,688,816,942,221,861,462,92,821,48,352,458,590,61,430,973,652,664,119,242,171,621,878,733,614,504,611,230,466,845,783,891,860,900,891,281,666,254,442,350,834,141,413,14,104,740,621,97,295,768,110,559,966,860,985,164,561,285,349,641,175,623,311,633,122,418,147,104,443,47,773,218,246,970,599,642,901,759,887,116,767,960,186,186,484,404,310,535,506,119,991,576,145,373,41,619,101,14,363,959,14,325,823,632,155,816,602,435,273,402,249,380,201,90,722,995,427,444,680,480,142,852,93,332,626,260,629,318,616,984,469,235,197,189,894,445,982,762,694,472,860,304,528,465,345,678,589,702,689,951,108,954,835,216,905,165,604,310,18,538,471,92,377,942,922,525,723,482,503,614,722,517,942,750,340,468,27,429,829,523,696,45,54,59,668,998,27,290,278,868,617,776,863,467,321,840,190,786,9,214,586,649,913,673,964,458,492,563,276,876", + "891,601,412,765,85,466,935,778,188,857,936,580,371,833,656,43,797,1000,631,133,773,808,765,409,78,189,682,785,372,366,439,186,211,187,734,742,492,213,206,192,612,367,634,918,706,38,377,427,435,670,624,30,159,817,104,607,150,156,382,865,263,553,760,312,624,723,11,845,254,996,408,165,431,737,159,830,861,74,623,879,165,264,342,891,929,109,781,109,709,565,836,329,626,885,15,832,832,76,859,624,706,796,151,322,534,903,78,163,230,888,23,186,135,758,488,802,894,603,677,617,159,913,78,205,940,191,13,526,171,778,889,288,348,199,621,877,452,881,56,981,638,846,292,573,53,607,538,190,299,908,864,615,880,570,147,265,251,7,125,782,306,481,849,148,841,457,714,56,631,519,844,900,515,809,485,751,486,516,280,894,196,594,312,269,122,770,104,243,501,283,609,105,852,396,567,790,667,641,578,959,47,611,894,30,212,390,14,912,611,443,116,813,9,544,553,207,687,679,427,695,905,3,572,342,109,966,293,308,668,612,931,201,146,599,956,848,691,937,154,605,688,526,193,834,251,787,183,840,404,474,508,173,797,928,624,519,570,879,170,907,818,486,165,963,706,428,851,228,965,671,333,826,163,76,389,599,341,427,998,241,462,813,277,489,53,569,166,436,924,630,683,193,86,487,467,719,881,583,660,29,136,379,248,431,265,23,984,593,424,79,734,125,674,786,913,126,142,414,659,451,654,348,737,383,527,493,807,15,155,622,181,685,395,867,321,63,423,993,244,162,450,375,288,626,225,243,366,82,451,250,326,804,305,112,578,644,914,193,6,673,435,403,510,449,575,310,722,714,149,162,165,442,51,357,325,455,922,752,260,336,547,628,680,795,400,831,618,429,251,176,115,367,16,202,219,538,405,871,560,373,401,611,877,262,157,17,4,419,438,976,289,891,910,292,68,229,158,460,520,835,881,275,707,990,693,508,766,208,918,271,462,744,555,798,273,183,16,578,83,995,171,289,634,427,485,171,184,636,474,957,637,70,925,144,125,549,998,570,996,721,582,344,827,511,322,272,429,550,772,794,753,94,241,757,224,691,532,890,15,232,327,46,744,26,394,383,46,432,467,995,791,400,978,3,128,361,923,943,797,593,272,442,742,947,872,92,730,319,346,284,534,146,505,631,862,198,134,238,932,120,460,922,33,16,88,984,985,686,374,105,19,23,698,756,136,157,989,178,410,682,854,614,306,951,72,407,147,475,714,6,57,114,271,880,7,796,906,356,267,719,158,335,447,496,26,557,405,596,37,904,925,941,166,628,524,757,510,673,36,241,927,143,40,33,747,662,790,960,766,743,282,652,942,784,681,565,57,329,613,662,157,727,342,171,531,111,13,514,357,101,414,86,369,235,574,138,698,222,875,551,390,126,271,289,790,464,480,625,651,521,16,16,287,244,748,451,136,20,718,233,457,802,637,924,742,234,360,420,609,151,857,231,385,378,590,793,73,342,378,472,817,102,817,186,3,967,838,446,445,843,744,472,291,851,784,69,582,496,951,714,241,541,657,425,962,47,420,722,429,777,640,586,289,871,473,692,550,963,529,998,15,237,781,30,901,460,385,818,116,287,88,24,665,950,697,607,402,879,369,636,307,268,25,156,921,41,866,60,531,810,498,306,298,728,222,122,805,77,941,262,239,302,46,517,251,704,305,683,369,606,910,416,978,72,933,3,584,560,356,434,19,871,747,249,729,437,906,945,470,64,523,674,746,207,63,728,46,310,855,140,292,418,551,277,0,283,830,386,640,578,214,177,523,831,929,954,631,598,916,433,653,699,136,960,626,2,90,933,675,714,736,365,904,191,387,146,884,671,469,880,610,296,815,200,221,399,723,19,426,338,606,636,790,667,756,216,100,927,297,286,645,490,442,294,399,691,680,333,773,931,184,295,345,684,725,203,969,753,462,632,670,931,969,607,563,437,587,838,41,308,40,258,889,811,95,482,876,764,893,491,276,570,19,796,772,969,57,678,150,882,143,975,388,128,660,224,66,852,838,552,323,506,425,93,30,716,902,611,291,629,245,49,922,441,882,61,268,935,228,98,534,370,269,278,773,271,236,646,55,637,397,82,981,456,233,245,692,48,289,238,374,809,967,294,595,64,343,182,32,544,306,789,753,129,499,752,554,344,427,360,717,331,734,72,987,212,417,471,750,892,911,362,650,902,213,439,159,100,930,400,364,945,857,781,113,794,118,340,223,94,66,837,854,839,669,515,262,350,781,710", + "81,160,769,125,646,344,669,249,428,108,313,301,737,822,72,583,834,130,578,861,399,645,423,169,755,766,184,316,978,644,833,289,249,622,757,891,979,241,506,50,884,913,347,939,735,787,309,397,798,400,806,696,110,127,14,709,222,825,825,888,497,2,933,262,284,842,603,232,454,680,461,278,170,771,718,217,803,172,561,526,494,861,896,342,924,840,374,921,950,855,737,274,178,826,585,275,767,406,327,973,527,651,383,579,948,388,758,100,997,536,743,72,534,932,289,86,662,960,760,291,503,473,961,674,142,864,554,430,397,672,180,167,831,998,748,668,242,621,562,409,803,106,876,909,972,244,625,699,941,425,765,9,237,640,911,260,985,52,204,939,900,809,845,762,22,795,36,356,98,571,857,351,172,604,601,630,38,679,661,9,862,62,852,539,337,953,791,941,737,355,220,814,551,657,312,326,546,289,313,645,178,578,996,981,803,19,560,152,80,954,981,99,28,32,129,773,451,471,510,338,835,692,303,221,759,590,452,487,862,622,543,63,101,89,651,851,667,552,631,452,296,69,243,95,259,334,921,832,155,981,387,966,109,973,525,725,996,958,34,331,695,129,811,226,999,426,460,920,13,972,606,875,462,860,243,748,221,191,94,691,87,707,243,972,990,527,982,494,112,728,704,651,565,269,783,920,472,768,944,851,871,969,605,279,663,891,861,240,82,135,71,813,666,151,272,712,203,190,624,492,792,181,949,116,229,63,242,636,353,374,981,653,655,512,144,911,466,180,225,751,782,938,563,608,876,369,830,851,305,629,761,222,305,442,127,344,230,354,502,948,300,87,873,42,93,397,677,831,919,461,980,325,481,577,496,68,890,501,802,581,34,505,476,663,757,616,634,115,28,358,920,836,271,192,609,433,235,597,498,587,761,161,271,975,415,392,223,322,622,470,148,455,470,700,169,9,446,449,859,900,238,5,819,706,809,216,15,790,327,50,925,211,466,750,770,739,864,414,546,640,214,692,834,1,306,577,799,234,992,428,528,758,562,291,934,486,700,710,615,965,679,7,700,862,265,375,233,270,579,438,9,722,117,990,642,121,388,872,259,71,645,966,466,275,887,360,271,683,405,137,9,716,718,274,136,708,551,994,107,992,672,196,264,776,420,401,188,228,449,244,819,246,581,524,666,286,122,757,155,270,410,25,183,287,758,80,147,909,399,559,258,439,904,2,659,370,346,923,288,19,213,718,67,915,491,977,114,659,308,823,250,635,15,565,493,120,244,705,287,604,384,244,111,197,836,392,112,622,253,478,188,633,757,531,875,443,350,226,49,538,521,734,988,978,651,852,154,681,379,534,311,105,681,58,5,635,644,432,571,877,435,710,58,444,919,973,865,312,295,627,362,610,893,421,585,19,441,214,281,131,700,73,167,415,688,261,708,699,707,762,469,712,551,279,626,625,888,762,631,372,585,639,535,39,396,319,474,466,926,915,631,790,600,275,401,684,652,768,771,620,829,148,135,792,385,170,961,354,673,640,812,564,232,614,269,407,431,571,553,95,356,459,338,341,985,125,649,705,287,191,23,690,930,964,509,241,518,796,881,169,222,946,321,957,795,250,174,776,679,345,143,63,533,360,971,257,990,577,842,132,497,161,273,564,1000,31,664,884,411,610,248,595,568,608,56,383,266,101,49,193,48,943,22,904,799,252,68,332,344,836,830,902,421,338,242,147,313,794,20,849,926,160,943,347,848,30,981,140,30,274,434,863,711,766,541,218,561,64,856,882,766,404,720,413,283,0,120,612,459,493,914,690,739,635,123,247,176,359,756,9,331,794,959,425,245,486,389,945,88,405,33,544,418,73,874,321,724,791,888,809,674,57,866,616,300,76,782,308,39,871,722,156,903,201,498,813,928,70,577,103,44,860,152,734,445,791,40,253,874,644,745,822,788,380,984,471,801,457,378,764,790,165,76,972,607,970,583,266,292,822,189,87,840,958,267,327,895,927,357,250,546,169,703,236,838,427,378,183,981,775,863,107,524,614,106,190,1000,578,270,25,662,414,15,876,377,375,766,8,500,48,89,313,232,854,785,247,340,694,19,81,585,105,729,125,46,402,944,812,10,416,163,947,939,97,253,466,639,459,331,68,572,28,136,548,331,716,463,961,523,890,731,75,607,878,883,62,248,347,92,753,696,26,666,740,607,945,891,806,873,990,921,385,905,299,327,649,815,653,534,785,736,164,310,866,712,33,467,635,33,34,17,864,68,607,329,547,305,12,94,282", + "205,133,301,263,710,123,542,485,171,226,897,105,506,184,26,935,703,68,583,485,648,526,85,754,986,969,108,782,840,543,307,918,699,425,705,256,954,799,560,841,424,2,403,335,234,684,161,978,213,180,44,46,589,329,838,847,359,413,328,833,405,445,211,863,399,656,426,659,348,356,17,824,191,625,206,492,710,204,293,845,458,785,825,632,34,872,293,79,424,429,476,758,184,338,335,844,500,374,420,939,715,712,528,675,396,808,521,66,716,534,807,908,202,763,967,785,657,410,909,378,402,881,531,473,432,80,809,562,141,316,362,813,531,705,366,235,718,690,103,296,191,744,678,434,70,833,71,263,690,643,610,4,48,533,921,85,661,397,434,39,889,442,949,476,373,581,87,14,33,610,319,932,531,594,30,269,226,107,446,465,345,738,903,677,308,434,796,81,938,730,130,974,888,48,47,122,214,879,959,701,906,336,631,959,283,321,823,288,150,725,784,732,618,452,548,225,590,244,117,587,49,592,484,834,138,97,321,11,598,184,757,768,62,506,763,917,690,259,165,846,87,115,664,17,155,638,48,994,43,803,149,231,172,835,828,279,592,152,523,509,500,874,446,629,807,263,18,55,324,282,889,102,169,354,69,267,116,890,262,267,618,957,316,498,718,988,580,30,760,8,291,292,174,74,450,725,57,256,607,386,377,981,877,963,92,617,469,227,460,134,671,919,235,369,574,902,835,113,242,764,339,973,566,285,988,329,566,607,462,459,867,653,175,985,901,302,788,433,591,386,752,975,964,236,775,997,325,959,322,574,797,920,469,4,945,860,4,896,857,37,170,505,29,983,358,592,291,966,897,346,856,55,967,465,749,724,801,84,413,317,788,363,892,220,507,486,934,394,412,58,277,11,184,937,285,482,262,798,137,699,481,437,291,983,246,486,273,841,284,525,40,104,624,596,87,653,588,994,253,804,657,841,150,394,90,816,120,898,601,972,18,383,745,208,640,958,917,810,289,710,520,867,370,125,316,472,957,110,577,158,759,47,68,421,611,963,885,795,365,711,156,966,292,683,547,104,126,285,389,80,792,104,341,974,694,139,437,960,922,535,622,894,240,992,518,532,965,436,282,726,480,128,414,834,655,232,407,550,320,965,380,679,596,815,372,302,275,523,78,597,313,49,826,514,765,700,267,864,872,30,56,995,913,123,398,622,708,399,143,267,697,634,306,783,964,682,446,494,203,89,327,425,287,168,703,706,215,491,470,514,461,536,115,541,763,40,764,80,28,450,173,561,88,490,937,339,511,735,942,109,888,741,809,84,494,784,366,83,913,161,104,594,45,364,697,937,59,145,479,711,706,222,287,251,634,660,130,708,901,61,69,689,1000,621,232,914,45,521,219,749,905,458,361,489,240,503,727,164,252,147,962,588,208,653,610,30,891,917,593,596,16,855,950,645,647,262,319,438,852,739,552,342,393,373,787,586,643,389,365,467,279,464,518,442,631,981,674,928,586,825,945,939,543,975,586,381,593,938,367,868,621,443,413,655,574,597,423,232,278,955,114,239,602,91,706,351,153,500,857,961,400,320,96,72,915,458,668,862,872,973,202,722,43,802,201,827,984,624,192,347,696,681,169,203,498,416,461,623,218,801,426,815,766,1,911,54,768,931,745,1,879,768,904,625,100,773,306,807,519,463,323,475,459,398,558,737,469,691,513,185,184,129,471,569,392,639,442,178,946,769,463,641,451,366,47,455,802,555,151,400,327,847,831,525,380,697,277,357,496,829,59,167,549,204,830,120,0,288,538,585,736,960,543,697,114,240,933,733,142,71,603,511,252,319,169,559,917,500,446,912,345,50,692,771,923,823,304,430,989,907,459,576,318,921,591,271,475,228,697,271,123,36,470,870,332,383,431,581,903,326,834,690,627,46,518,327,27,645,583,176,193,200,561,661,386,480,690,398,984,540,612,568,99,76,890,252,466,465,109,746,50,901,764,994,419,437,710,948,261,652,174,270,275,145,965,516,8,635,898,680,182,760,865,416,448,316,221,847,158,202,113,171,185,909,658,237,348,610,738,376,994,562,68,464,193,932,402,784,45,190,201,52,97,311,330,822,66,843,553,963,196,494,423,632,526,901,737,674,541,317,734,600,987,302,488,520,424,812,463,193,527,373,114,528,381,772,421,192,392,901,162,715,751,455,238,625,385,564,974,610,288,722,199,449,886,916,501,767,883,21,864,533,495,424,519,617,201,912,304,818,2,536,477,264,958,784,215,680,775,654", + "226,350,349,627,749,342,311,294,804,359,450,922,32,255,186,601,127,503,210,631,940,828,604,894,251,851,742,335,684,858,495,304,772,269,835,424,837,938,452,27,611,326,504,342,205,902,257,543,87,567,482,301,603,85,41,288,741,428,722,73,784,256,549,88,218,380,694,202,995,182,961,120,116,760,63,66,298,708,643,622,998,546,836,486,14,453,841,526,726,887,962,325,226,683,222,542,210,412,232,926,52,744,887,270,215,692,274,423,601,894,662,543,691,3,144,893,985,18,22,148,975,102,426,275,695,491,237,615,609,729,230,494,328,281,225,225,310,179,436,311,813,147,430,566,214,314,854,905,770,562,872,632,504,811,346,540,558,312,712,24,712,446,707,805,950,538,561,946,535,379,202,678,574,628,88,855,875,277,177,521,137,919,902,609,492,808,202,759,959,994,685,546,767,587,640,516,94,452,284,657,450,841,247,51,503,258,370,180,180,574,933,661,560,637,38,514,742,885,118,757,857,63,882,539,97,565,143,400,64,415,252,827,955,40,749,372,227,824,243,448,782,422,286,691,279,922,720,827,117,661,898,292,955,193,125,204,197,461,18,522,847,661,736,117,484,161,63,594,907,752,963,74,798,98,532,580,750,606,817,924,304,660,439,143,782,97,510,881,765,791,764,343,214,765,281,877,480,832,315,529,133,904,131,450,846,798,70,743,952,929,572,976,364,855,888,304,440,350,487,502,930,959,27,456,354,954,905,112,617,733,283,897,647,273,844,122,877,954,104,866,839,994,734,813,749,541,882,508,792,235,829,483,559,954,102,979,819,777,587,264,231,382,852,624,138,73,2,952,216,179,813,730,622,261,438,884,496,280,775,115,235,986,721,194,818,769,228,613,75,709,395,498,42,280,40,344,909,547,777,95,245,346,651,905,614,598,941,789,369,739,438,395,333,342,533,958,829,262,910,809,404,533,145,977,220,241,292,402,432,769,433,966,742,309,770,646,58,886,37,467,831,38,131,284,407,561,57,284,721,370,864,721,289,916,725,568,873,987,160,532,367,52,777,880,488,796,939,436,812,937,524,416,713,785,567,416,539,533,859,791,743,836,442,106,157,312,662,539,462,693,790,405,507,845,225,713,999,201,589,7,696,124,510,987,352,203,112,133,626,625,146,262,856,997,95,686,282,464,479,271,704,175,409,845,481,480,269,980,247,544,800,320,54,625,882,596,981,663,223,815,950,187,40,101,728,933,139,595,651,106,759,693,712,9,56,184,448,254,999,937,181,333,835,650,424,404,126,50,392,347,14,733,801,211,502,141,870,918,906,375,504,889,924,269,818,77,595,289,440,681,438,505,171,52,399,847,46,484,922,347,146,136,506,368,210,53,959,139,212,121,313,468,256,385,890,418,753,323,807,826,972,357,897,410,772,990,691,382,751,372,274,348,215,779,467,386,751,132,48,71,120,859,679,860,496,862,188,583,998,546,452,526,889,416,620,712,592,755,34,384,54,711,431,667,110,330,379,215,414,555,651,931,230,143,359,126,209,572,698,982,815,449,156,7,464,480,974,148,325,786,19,120,892,696,605,39,10,802,897,455,271,844,738,710,695,989,863,927,617,427,421,172,933,500,2,721,26,763,279,476,381,688,326,110,436,733,445,607,375,283,854,155,463,80,75,585,191,916,850,685,246,750,783,327,862,305,612,840,11,7,981,153,597,724,714,724,943,880,737,53,889,900,296,710,133,360,771,696,279,560,678,176,586,473,540,478,157,204,999,266,81,543,171,583,386,612,288,0,179,567,133,403,41,135,425,460,64,902,641,706,826,339,209,923,239,926,915,797,236,949,428,978,320,977,798,306,568,629,444,772,135,763,55,849,568,879,503,693,879,262,648,418,505,965,750,106,640,647,555,326,932,943,846,153,44,974,840,724,123,816,155,361,630,555,219,783,958,682,541,499,208,908,186,150,396,821,48,316,203,648,238,493,382,456,750,821,473,646,98,154,200,357,619,779,832,607,532,8,366,941,847,952,864,82,149,985,259,613,239,229,220,524,453,221,582,916,413,836,602,683,715,955,689,624,901,286,319,98,254,281,472,804,473,417,1000,873,569,846,354,457,364,909,946,874,119,411,401,970,595,650,744,483,787,265,296,582,62,169,101,885,326,960,768,411,281,556,111,857,53,620,89,439,227,323,972,310,261,50,664,904,260,562,781,152,901,538,648,461,149,38,683,727,261,262,437,357,717,817,736,530,648,932,247,84,918,508,26,865,337,734", + "907,444,973,877,708,449,687,495,703,900,881,128,54,433,107,797,949,72,49,292,959,141,561,152,328,952,890,834,257,362,434,288,577,774,858,384,915,284,41,25,610,50,297,709,48,638,84,564,742,548,494,57,1,528,812,769,192,367,91,245,196,918,144,593,442,597,379,827,806,437,693,818,917,156,740,635,127,752,342,372,231,474,467,428,562,151,23,827,683,629,612,795,735,932,206,769,278,896,26,251,531,733,854,656,789,774,334,402,322,757,160,350,316,608,769,732,935,857,117,323,473,916,623,726,733,888,929,713,730,634,239,391,807,854,174,793,405,702,183,431,919,279,91,171,367,905,779,44,416,748,40,281,57,926,762,248,245,273,839,96,961,489,84,910,627,743,262,815,698,391,429,397,939,21,60,92,959,637,276,296,646,192,258,456,256,486,11,628,299,499,594,745,211,118,569,405,916,647,179,29,116,252,66,420,246,237,61,785,312,452,88,662,837,233,593,249,137,561,183,779,131,8,32,591,760,491,21,583,108,71,930,254,460,849,35,204,720,455,823,818,792,766,349,124,477,763,911,149,96,690,420,98,463,11,85,938,493,87,67,950,805,27,271,779,702,474,884,564,109,638,689,343,315,180,382,764,799,734,948,128,771,556,841,429,719,947,627,511,284,425,27,712,360,900,230,115,639,332,560,162,565,468,941,267,96,596,250,296,695,109,758,842,594,200,440,89,431,705,843,685,559,240,891,938,761,314,690,240,406,604,76,129,838,528,676,293,315,723,874,776,454,627,237,419,879,498,250,964,233,83,141,322,136,80,954,753,681,797,72,51,328,23,148,18,817,326,723,818,486,140,208,716,645,926,348,697,833,475,45,336,659,41,722,886,406,166,500,743,794,414,788,554,611,399,465,320,456,919,516,252,871,122,226,252,641,110,569,484,408,153,895,41,612,377,975,955,835,421,311,903,953,54,926,166,5,394,165,243,885,104,465,93,570,466,29,631,317,773,588,152,213,814,224,526,6,54,757,341,203,346,673,818,172,960,510,603,24,415,862,231,133,249,556,389,996,399,581,261,411,90,275,571,479,416,383,42,406,22,475,461,360,64,48,902,713,243,738,284,265,311,168,610,468,837,547,84,133,654,176,427,894,320,764,41,969,363,292,810,882,602,232,216,867,667,569,704,594,182,140,253,401,389,754,44,308,156,454,126,267,265,195,516,742,484,989,275,776,625,991,947,602,721,652,214,304,979,494,588,965,797,851,729,322,812,52,870,739,505,127,120,153,381,19,603,888,382,262,138,633,84,248,197,914,873,259,378,635,279,478,679,872,51,729,969,222,312,625,512,742,990,91,774,979,355,807,205,551,533,396,318,426,808,745,30,371,307,197,150,109,124,690,382,309,52,549,390,632,974,351,108,831,115,659,322,457,578,232,546,256,610,477,519,905,68,146,789,344,931,752,410,532,519,878,179,114,903,981,233,867,725,754,708,743,329,656,76,205,933,861,87,59,750,245,766,888,465,487,271,170,945,392,402,184,479,930,553,3,663,318,33,600,270,117,457,839,855,552,644,664,199,468,736,555,273,746,692,744,399,780,34,827,642,403,73,570,92,154,218,817,968,856,91,192,436,631,283,215,148,68,635,244,510,457,885,570,770,704,216,339,590,13,875,820,194,850,664,959,186,238,66,909,189,709,420,52,888,919,527,904,966,722,904,80,388,326,823,736,442,685,461,621,373,637,49,915,458,730,618,434,868,245,120,901,992,267,363,348,468,949,310,706,607,844,533,640,459,538,179,0,332,254,37,327,853,844,614,945,599,746,813,358,93,592,741,800,518,825,219,420,287,748,750,801,440,556,974,780,99,206,331,650,994,987,234,818,364,113,384,886,989,775,721,428,551,141,866,760,999,402,953,176,942,391,457,832,714,40,397,713,820,414,807,700,710,540,147,192,514,487,389,933,460,538,852,433,932,236,899,97,86,110,755,935,894,766,569,307,829,509,821,300,182,643,85,323,575,749,215,876,717,575,844,690,543,72,738,322,197,464,556,426,329,587,522,270,508,668,138,873,887,616,566,902,422,593,655,12,80,614,979,289,997,554,395,128,506,78,12,388,489,616,64,692,536,678,15,760,52,818,578,411,61,127,201,837,509,407,586,953,421,20,422,97,480,529,766,639,85,482,935,212,779,741,318,445,475,995,991,219,444,905,304,630,987,636,816,570,273,534,829,822,241,410,19,516,328,983,70,588,545,330,1000,684,147,648,438,786,168,286,156", + "158,846,720,119,357,638,757,598,346,558,979,194,73,301,581,113,248,185,624,685,129,754,869,860,279,492,634,521,295,487,812,847,656,379,604,225,112,669,27,45,216,682,517,609,794,104,818,144,291,542,304,501,896,479,714,189,628,598,338,31,576,873,61,915,441,164,918,474,647,151,541,257,976,908,837,702,421,497,885,130,343,777,337,628,702,644,870,696,214,718,921,63,3,31,321,668,362,133,58,869,36,829,289,206,209,742,295,839,952,371,248,867,430,482,992,429,200,726,23,889,800,67,778,684,588,963,667,364,617,901,831,7,629,787,455,853,895,384,965,506,498,769,366,225,970,238,838,548,206,512,144,96,485,487,652,521,294,790,606,978,407,112,683,905,518,243,928,351,737,493,319,855,410,548,239,616,729,776,319,892,352,265,835,586,923,642,758,64,930,686,701,961,414,509,660,248,801,285,972,623,123,550,475,713,119,172,789,296,616,915,117,379,279,724,174,573,492,319,801,53,428,529,94,142,43,10,612,546,409,354,871,939,356,612,124,501,900,542,181,460,607,554,944,248,849,959,895,67,508,426,525,70,281,453,36,842,536,231,453,892,92,473,629,655,191,940,421,147,151,275,741,540,55,818,6,574,143,13,933,639,708,847,912,630,847,795,900,360,257,215,961,867,872,897,283,963,839,56,223,841,161,78,385,372,461,390,112,891,161,864,169,74,353,935,872,941,474,603,406,80,232,499,935,155,601,271,999,316,763,693,573,322,175,717,67,782,280,388,342,360,167,727,998,221,374,585,315,921,847,468,158,983,13,661,659,726,384,210,896,915,261,998,993,833,26,671,670,637,281,855,227,806,588,310,377,163,981,207,238,340,392,814,309,563,787,731,4,499,119,60,500,648,887,788,658,73,390,805,403,202,169,418,911,418,824,199,401,178,941,443,269,828,384,460,823,60,677,788,830,149,621,542,501,297,86,299,262,106,535,536,68,181,213,416,924,79,231,19,741,94,194,402,219,509,242,804,470,440,943,148,220,4,631,501,734,855,21,617,769,334,299,619,551,620,756,89,472,990,643,574,260,831,679,854,274,401,831,622,810,38,991,612,965,163,505,211,101,275,74,1000,314,483,312,894,139,633,411,373,894,867,329,838,893,303,949,161,706,25,385,458,306,107,770,632,904,202,63,245,26,848,817,42,901,401,122,734,982,73,395,844,801,96,5,389,228,567,967,509,816,416,815,339,731,978,843,289,591,987,406,194,852,289,609,26,962,11,301,62,913,409,305,728,74,650,724,57,377,445,824,626,610,868,621,439,707,5,638,81,961,835,233,176,991,909,199,110,383,443,483,926,345,164,156,923,705,176,360,549,150,17,101,255,638,362,496,978,406,317,112,75,129,42,812,395,692,933,45,785,125,7,583,175,358,914,635,906,11,743,233,226,35,81,274,37,950,49,781,76,128,430,857,888,457,179,269,380,177,224,610,159,249,287,694,523,716,888,507,105,252,143,270,565,389,33,119,50,885,522,889,909,195,433,212,766,667,978,889,972,42,379,766,652,758,599,265,676,602,725,390,339,656,233,100,567,811,696,68,690,830,595,777,37,805,956,995,107,257,90,461,252,290,550,425,585,607,710,43,784,905,409,607,957,690,27,76,426,254,569,109,830,616,767,132,638,452,783,510,632,864,914,561,651,558,410,242,609,684,391,10,677,777,310,505,653,43,21,637,537,976,999,657,513,396,829,414,692,204,64,143,331,60,23,31,418,975,437,978,499,672,397,440,136,769,985,578,493,585,567,332,0,247,508,576,375,89,458,277,881,865,291,569,987,158,78,247,814,13,710,416,712,450,845,824,896,770,979,261,572,707,739,113,142,256,573,752,661,628,198,846,921,913,547,827,126,318,643,939,921,355,690,840,876,932,309,216,525,834,467,920,101,717,905,108,124,407,242,238,796,141,767,380,551,693,214,275,849,142,254,88,912,512,70,49,73,518,572,238,123,770,567,361,122,227,699,138,502,41,427,875,875,14,312,882,510,117,369,9,658,298,850,769,21,980,126,293,765,769,877,176,424,607,53,166,506,474,470,248,520,316,429,566,160,715,619,146,823,222,658,779,10,589,458,92,257,884,848,825,419,386,507,846,37,883,346,199,112,131,752,670,603,854,858,247,826,734,455,528,509,606,471,728,378,101,515,696,726,56,382,61,281,858,636,700,220,848,945,772,903,230,525,838,343,888,865,691,894,616,796,156,986,927,97,636,592,793,955,232,135,582,114", + "473,464,343,195,354,124,47,224,613,474,117,728,780,573,430,41,438,288,408,612,401,902,950,577,646,373,231,898,141,569,253,444,417,364,264,136,349,922,687,301,534,167,939,743,346,562,607,656,555,21,419,331,884,866,70,871,426,636,766,381,211,877,802,857,104,372,623,504,873,500,734,378,479,286,282,723,354,469,650,75,107,338,212,474,751,349,915,762,868,581,402,317,543,563,419,588,56,245,306,759,449,15,866,340,840,761,816,171,996,60,399,951,258,368,788,665,399,911,419,357,354,880,400,451,924,925,920,856,222,807,809,53,848,147,636,126,735,304,831,601,298,935,630,974,742,372,443,560,288,140,325,467,530,283,244,231,890,401,404,571,78,782,701,238,259,377,572,650,807,989,324,618,930,149,135,906,968,722,817,352,843,358,6,715,43,281,976,381,17,269,888,694,392,784,546,716,831,161,703,313,568,291,882,290,538,788,208,232,583,464,5,167,71,283,690,66,409,56,37,663,577,46,799,599,100,677,609,53,886,20,93,875,69,70,83,683,367,781,35,932,633,5,232,4,905,741,823,794,59,357,433,809,609,386,699,806,59,947,311,978,661,151,429,231,380,453,678,818,977,724,646,465,215,755,491,460,641,912,941,953,71,47,235,688,52,373,822,115,916,548,364,715,36,619,513,94,559,871,789,74,484,217,39,416,255,746,400,22,54,291,203,465,135,408,524,240,874,578,554,92,991,355,235,239,71,964,833,303,948,714,736,333,51,41,969,833,433,546,482,850,936,334,596,566,521,957,581,86,635,102,93,841,390,181,369,175,699,757,627,715,30,414,162,606,390,335,942,261,53,918,855,199,682,425,537,473,472,180,815,136,706,608,762,103,460,498,413,276,559,900,217,183,673,225,954,327,322,649,934,952,216,843,8,727,367,767,673,482,963,605,274,752,487,598,162,30,242,341,281,805,372,788,413,76,249,195,612,537,630,312,516,367,579,96,434,815,392,117,809,102,179,535,612,452,849,491,140,250,68,496,855,433,863,494,42,656,262,154,727,177,991,109,306,83,371,137,543,264,637,344,371,975,414,728,399,998,485,228,930,926,101,98,287,259,524,795,980,900,8,543,550,967,461,816,19,238,874,466,360,387,763,602,545,709,220,448,935,857,162,417,251,969,261,30,708,519,882,46,807,795,376,235,542,516,654,152,669,66,754,113,746,220,528,757,619,167,844,344,164,183,260,58,325,835,617,323,834,435,169,641,171,274,217,169,12,13,75,768,914,388,394,877,189,408,74,452,430,683,406,85,712,959,811,29,605,547,398,893,602,7,954,875,9,558,807,915,390,611,685,846,984,369,979,364,739,210,825,492,542,105,791,400,764,478,298,51,208,279,107,661,447,942,984,894,302,673,665,92,732,656,752,491,135,181,143,80,548,155,281,499,951,514,563,362,487,326,83,42,383,943,730,52,535,584,514,427,862,121,122,927,347,179,958,71,179,399,580,289,515,373,323,264,105,616,671,652,15,729,98,176,384,799,850,325,589,898,668,805,972,37,929,376,44,810,982,800,169,51,706,414,456,563,947,956,72,33,323,653,127,794,268,975,604,767,86,288,635,926,36,132,921,528,126,527,384,207,157,557,284,375,735,770,717,914,514,596,2,123,422,413,753,344,506,881,205,564,294,384,913,776,559,255,417,599,240,189,191,39,275,145,786,84,390,257,937,519,379,928,618,170,735,7,756,472,838,81,190,951,299,556,272,734,912,466,388,881,472,81,22,280,38,121,199,797,214,914,736,133,254,247,0,717,897,773,446,27,702,715,972,64,597,954,418,29,717,134,688,492,312,650,573,458,993,411,160,565,493,780,732,145,406,378,690,335,789,819,180,972,871,788,246,434,922,604,581,701,138,318,618,294,68,875,516,533,915,474,203,611,991,514,728,966,425,626,5,93,574,653,767,142,416,208,213,158,485,122,50,651,152,735,767,334,591,95,345,262,73,305,867,847,40,938,183,443,402,779,783,932,708,989,604,165,524,560,600,922,941,727,114,429,857,745,699,241,4,189,646,56,731,918,160,809,219,429,631,5,903,514,159,435,986,688,705,300,682,67,249,269,990,168,498,437,220,466,199,150,236,704,281,690,314,957,572,792,426,689,979,154,920,684,165,909,490,715,554,56,517,938,652,604,774,544,48,423,825,728,86,162,190,194,46,850,779,755,994,158,112,30,456,327,275,502,685,372,486,36,289,817,397,833,211,245,61,75,850,230,886,195,876,444", + "622,507,210,596,33,667,551,178,160,496,506,440,712,341,722,416,631,448,297,725,660,775,226,771,658,843,954,442,964,935,868,7,192,937,694,936,97,988,754,361,108,404,569,370,7,570,460,693,154,951,477,33,501,611,856,287,693,64,777,428,526,954,470,778,572,308,485,777,788,550,142,900,569,261,495,394,109,336,221,697,350,650,240,804,19,117,593,832,813,106,377,635,391,697,920,734,372,907,766,493,9,777,302,47,337,971,520,254,601,637,493,785,159,380,583,115,673,405,572,779,376,138,616,3,827,683,873,981,135,42,572,726,233,627,984,566,623,447,391,707,709,973,549,261,451,704,580,458,266,633,949,354,620,225,365,691,420,580,925,64,339,901,90,648,290,148,563,444,904,664,286,268,998,991,857,878,274,325,906,532,76,430,329,396,395,975,397,657,279,320,864,315,551,765,128,767,446,376,356,576,668,963,547,182,136,796,614,387,465,232,232,81,379,744,294,486,527,329,86,790,733,530,468,321,80,12,701,515,151,488,43,819,234,419,319,138,594,790,656,274,557,187,471,555,882,204,157,820,431,478,830,568,561,891,789,963,516,95,669,89,565,33,181,466,898,15,425,107,755,127,915,902,775,852,69,598,274,118,489,209,504,185,636,55,265,509,715,950,563,781,749,79,429,783,143,383,841,257,720,228,334,679,733,323,653,485,504,534,702,645,59,501,827,154,696,366,744,444,61,483,756,637,201,603,692,899,121,503,14,518,629,300,276,375,478,523,800,19,447,576,671,770,552,656,412,420,587,71,473,367,523,13,497,546,893,640,636,549,381,484,718,489,280,292,657,997,861,187,296,393,42,904,643,930,233,534,183,325,992,782,485,453,351,875,320,495,680,11,868,63,719,316,806,130,68,519,580,462,636,307,230,25,895,853,875,630,35,89,740,992,418,866,410,421,428,365,833,535,307,139,338,654,376,238,327,974,391,383,291,654,322,882,966,958,38,397,745,837,477,616,302,150,504,83,636,11,582,772,123,428,824,107,112,876,234,110,468,476,385,323,952,713,978,35,415,120,369,575,518,750,885,51,247,311,525,997,879,953,239,571,684,252,641,309,369,558,70,367,220,680,969,408,546,901,6,27,795,625,321,823,708,849,695,56,390,29,346,53,142,278,725,124,299,857,85,159,296,9,786,950,175,774,767,383,673,248,286,515,316,690,882,716,403,503,354,476,766,59,209,534,720,588,304,545,177,859,63,550,802,139,525,197,447,530,161,271,399,384,294,729,887,922,896,762,575,529,440,567,45,893,228,553,884,673,735,100,471,798,711,340,552,941,782,312,164,884,829,738,244,385,829,510,978,816,336,583,911,377,406,794,478,825,636,519,99,27,115,849,267,157,5,212,283,803,431,322,28,976,552,870,590,691,481,768,339,32,47,317,564,124,696,526,430,504,190,931,180,888,383,642,376,221,881,461,448,242,728,134,875,982,258,995,397,224,207,891,670,190,286,977,212,649,420,50,36,120,403,224,64,474,366,505,901,474,61,415,157,314,475,794,367,171,544,136,478,873,326,87,720,994,914,568,693,466,605,523,421,274,263,429,162,243,941,99,513,862,524,429,681,682,165,161,367,223,551,930,254,838,830,126,917,184,333,316,474,60,426,427,575,871,476,719,539,812,281,153,448,211,440,164,431,922,431,94,467,914,194,134,449,892,604,551,734,959,250,324,646,43,913,587,557,492,83,161,298,139,440,69,611,894,572,859,831,920,263,777,517,536,714,183,598,548,758,688,177,690,960,403,37,508,717,0,152,629,446,153,422,572,518,45,389,766,982,68,72,195,665,910,936,999,837,276,671,573,261,633,891,419,998,298,160,783,797,128,349,946,118,981,488,533,616,697,186,249,167,78,751,915,491,226,809,453,904,817,997,766,517,618,8,930,368,172,922,660,885,878,848,100,421,928,322,923,814,66,392,456,370,62,600,916,481,414,545,194,711,614,64,903,448,557,305,228,101,324,793,457,981,285,65,93,505,914,722,907,123,760,912,755,477,723,819,268,554,312,726,880,114,36,58,755,735,865,316,910,602,733,470,607,301,475,13,615,454,579,610,254,95,923,40,641,207,983,63,86,846,686,783,43,369,815,293,374,994,118,88,654,895,382,830,210,365,802,27,766,968,510,892,219,828,826,62,563,520,669,720,909,896,385,989,399,426,394,829,582,973,195,837,197,951,713,171,89,549,43,871,454,726,186,348,651,845,961,768,462,111,491,766,242,797,930", + "67,733,915,480,80,105,106,939,124,244,954,897,560,731,773,209,966,103,274,476,755,853,302,874,811,163,418,371,712,620,546,264,514,820,77,763,447,361,637,216,92,226,244,15,283,942,482,30,773,435,648,205,291,515,982,183,789,726,286,173,853,746,867,647,526,770,111,156,96,552,706,778,232,211,400,593,781,419,711,796,720,691,657,707,143,658,813,326,799,480,807,502,704,269,249,773,214,821,186,796,350,725,322,111,287,753,693,672,376,157,46,686,277,517,890,819,977,590,866,153,389,390,789,310,477,569,44,778,569,139,344,150,647,452,822,489,614,426,281,562,361,991,311,177,469,414,329,280,843,901,493,302,758,855,439,14,306,98,521,606,162,930,903,639,102,727,11,275,531,216,57,385,177,234,943,741,293,485,822,728,331,835,25,581,827,137,157,994,867,925,190,353,921,139,201,116,412,273,778,479,630,806,861,371,215,213,839,789,238,409,999,224,600,457,240,41,690,651,543,311,389,30,30,729,289,498,639,810,715,253,618,662,729,316,789,861,548,967,65,862,909,15,648,88,624,261,614,895,633,289,724,15,522,190,18,645,349,99,767,366,301,48,504,667,587,740,30,773,226,886,118,501,812,272,406,360,405,741,480,941,58,329,271,851,3,892,498,11,198,755,611,228,242,964,324,721,235,167,280,101,305,775,985,777,402,815,595,888,87,603,72,487,427,566,183,319,222,34,860,780,395,462,557,321,461,996,853,600,135,6,380,505,830,953,838,510,908,802,656,45,185,674,275,148,318,736,565,597,496,568,859,742,539,118,268,906,696,928,877,156,834,256,468,516,598,30,563,663,362,947,802,816,290,327,764,887,808,794,981,999,61,509,455,616,44,192,474,933,844,340,705,426,981,585,194,592,88,958,844,975,935,329,974,297,488,676,498,35,907,135,807,211,27,223,631,491,114,315,499,513,337,220,252,533,375,921,27,780,544,113,257,309,180,871,681,361,955,544,649,124,861,169,280,220,301,440,500,974,293,977,68,382,145,137,373,20,776,70,256,412,103,61,688,811,365,728,209,633,629,813,848,798,571,466,750,724,136,577,273,27,154,797,376,869,254,981,969,687,894,484,779,997,721,122,532,771,371,570,474,35,512,827,691,753,697,403,505,132,461,189,652,147,810,570,360,44,189,959,164,457,133,611,791,912,998,874,229,658,581,887,638,666,561,887,238,931,956,530,998,445,81,927,861,845,239,698,894,608,397,808,784,646,460,955,76,158,585,425,352,921,698,279,822,315,24,23,289,629,869,157,922,853,968,276,794,147,307,997,606,392,375,744,201,741,16,300,277,194,429,505,256,49,470,900,483,387,514,391,844,411,383,144,631,90,563,687,810,313,591,431,460,747,448,82,860,493,472,94,442,652,627,434,864,231,624,241,825,90,531,481,230,122,742,726,385,934,160,763,49,573,74,495,981,923,645,404,400,420,483,716,663,284,593,370,17,386,965,70,397,901,903,278,829,413,957,140,861,2,830,435,912,645,56,614,884,100,34,324,999,447,710,507,602,730,855,158,876,328,932,283,43,616,859,487,521,434,499,649,910,544,208,130,916,15,138,590,962,558,258,464,629,680,653,96,832,825,973,305,307,701,353,960,729,946,574,734,298,115,458,986,176,450,748,874,550,796,223,429,23,627,733,688,920,862,994,916,780,4,793,70,497,882,322,457,284,519,246,870,62,635,294,981,457,169,983,526,456,424,372,581,66,617,164,298,374,458,893,197,265,994,460,119,266,816,523,739,543,41,327,576,897,152,0,432,630,891,478,662,712,637,706,294,535,90,698,399,802,281,810,602,938,177,4,708,341,224,452,109,98,268,776,878,64,384,953,190,544,419,278,139,776,339,502,986,46,686,221,989,805,744,4,633,627,666,962,133,308,540,291,333,97,438,346,276,174,365,960,521,166,142,777,150,730,864,487,328,192,886,275,934,257,57,305,605,983,541,207,928,199,487,940,580,625,111,225,359,280,6,563,908,93,583,192,413,574,731,637,70,125,64,846,522,95,399,738,756,860,573,985,803,933,244,78,890,178,984,774,153,559,278,872,905,1,379,919,955,200,543,167,988,44,518,28,583,850,721,188,687,893,195,998,554,197,691,600,760,716,506,449,356,152,856,880,68,899,988,389,190,520,611,335,14,863,5,199,656,906,582,967,989,483,883,104,288,425,873,442,102,39,109,661,554,48,69,68,916,917,792,922,511,935,401,550,524,247,468,311,13,958,343", + "981,303,640,138,28,180,87,526,98,437,861,278,532,379,253,25,630,558,302,860,101,976,214,936,20,493,138,437,26,692,429,228,633,770,218,166,500,992,659,335,506,723,813,601,217,864,198,207,428,937,697,871,575,179,822,206,271,269,968,599,657,473,873,987,138,901,654,232,779,387,349,482,500,262,309,564,757,339,698,324,64,194,445,256,394,355,53,130,729,717,543,326,750,726,225,326,602,845,984,248,822,206,557,849,884,403,705,674,752,530,487,303,545,364,351,58,955,333,325,919,617,625,711,449,171,713,535,115,240,715,771,287,496,832,289,323,112,586,467,306,630,538,643,759,137,409,76,979,624,437,457,785,239,269,84,347,614,287,585,87,981,537,664,182,389,50,50,767,180,342,493,883,603,984,45,495,933,592,841,770,848,620,769,70,85,581,183,500,125,286,279,293,384,823,355,359,290,770,249,273,485,221,739,253,951,102,540,781,970,216,249,460,956,166,484,846,891,827,763,589,503,94,172,673,997,727,368,100,363,863,879,139,405,951,874,9,936,325,979,905,847,233,764,115,446,103,315,620,320,191,573,380,627,413,672,624,707,838,620,406,727,314,663,790,534,985,59,287,835,349,10,709,106,782,374,375,714,113,222,658,33,627,19,126,767,199,400,123,732,848,121,993,857,389,245,68,825,241,39,127,976,632,103,280,434,83,226,637,370,742,627,884,26,970,253,18,814,259,518,207,199,824,172,385,264,368,771,973,270,139,712,722,671,455,864,711,45,518,605,171,823,467,510,758,410,200,714,404,93,433,510,898,878,685,907,573,122,53,554,119,862,140,126,159,692,33,814,13,693,507,542,999,466,484,394,572,158,946,162,995,728,968,965,707,466,239,537,146,131,294,265,952,172,334,258,542,167,677,184,261,194,176,298,304,638,899,640,632,179,647,455,125,308,837,788,626,427,67,709,361,729,120,644,604,544,453,887,511,362,191,784,758,477,32,21,779,578,977,865,641,447,670,893,657,293,289,309,945,771,498,535,337,684,268,543,555,7,226,148,918,376,151,467,391,178,200,428,186,647,795,859,460,126,186,851,363,231,645,848,420,736,671,894,87,265,36,912,288,150,171,791,877,870,139,557,47,912,845,701,692,914,214,478,334,430,561,758,820,955,613,285,731,453,344,304,412,129,323,44,54,548,757,291,341,825,809,120,254,896,107,761,974,717,645,175,571,682,732,488,428,362,103,631,619,457,706,917,208,398,240,224,953,389,99,713,109,288,379,126,316,811,403,226,405,411,793,208,863,923,901,459,979,290,671,261,941,476,58,378,211,96,189,964,825,584,32,671,71,536,914,516,340,126,191,697,716,978,220,40,38,460,232,454,81,134,855,686,22,707,390,905,598,602,529,622,2,60,679,616,902,476,417,29,674,799,599,675,622,332,931,716,574,863,137,286,147,499,886,487,400,503,791,260,643,974,499,968,213,970,706,116,962,310,635,287,486,391,948,634,178,358,848,849,131,683,256,387,296,413,232,560,916,543,951,342,820,794,272,157,159,299,778,543,268,362,995,44,657,962,319,701,14,602,551,809,686,809,937,347,305,986,149,309,326,652,537,57,390,828,66,698,497,366,467,621,780,903,273,756,829,600,657,471,416,787,380,148,895,999,896,111,852,690,214,38,901,963,698,200,428,300,584,950,807,124,511,922,381,171,528,411,79,377,397,464,737,225,216,927,251,503,39,648,935,700,54,433,444,638,519,119,605,381,680,346,322,906,404,530,996,705,395,485,942,831,635,697,135,853,375,773,629,432,0,600,755,767,487,43,979,419,914,282,107,412,45,661,644,34,632,655,528,423,117,247,302,546,452,205,509,923,128,374,262,559,655,409,549,442,150,846,670,846,332,527,262,743,710,355,845,401,354,439,217,715,308,949,661,717,270,434,581,395,417,679,77,137,472,819,471,403,59,132,980,551,357,341,570,254,387,258,565,901,112,424,120,954,242,163,440,605,222,572,811,336,285,434,441,350,640,388,952,432,251,603,128,291,579,979,356,448,65,313,209,354,890,384,825,600,568,532,583,181,323,831,601,861,831,436,230,682,329,408,646,944,114,797,762,170,447,929,839,350,16,556,651,914,659,609,10,611,901,162,43,562,13,359,869,200,418,63,844,649,997,945,692,847,224,631,948,762,81,410,222,886,277,415,973,154,474,941,143,977,386,651,983,595,884,176,645,190,604,769,287,810,974,404,275,172,225,927,589,922,892,753,974,956,389,296,769", + "858,597,221,858,356,965,70,442,222,596,94,3,510,997,527,804,133,448,884,810,675,314,552,653,294,370,19,163,872,486,965,397,244,330,303,746,371,469,261,58,567,95,655,50,783,352,70,511,201,954,750,220,527,875,970,618,102,364,952,698,287,980,755,130,397,50,361,247,583,710,720,748,128,55,860,705,849,886,263,685,486,343,179,207,100,937,80,472,86,394,806,813,54,527,919,156,611,906,43,577,923,217,73,226,319,200,546,30,997,308,522,553,844,154,558,370,378,480,41,197,363,237,840,968,625,843,509,407,560,788,297,354,425,158,237,717,143,173,492,635,21,603,800,230,619,878,769,296,222,361,574,37,499,958,43,193,857,258,267,667,786,284,752,449,264,81,235,690,630,580,554,41,105,129,129,339,646,87,201,816,503,845,938,799,995,25,722,679,754,317,901,150,971,791,577,431,638,677,68,675,868,341,30,179,753,704,182,766,385,303,752,88,302,345,253,193,399,311,711,358,644,810,662,27,111,273,998,167,330,807,486,522,669,328,108,348,935,332,948,110,384,344,715,224,713,623,643,895,850,882,34,679,38,708,263,275,841,919,187,252,380,848,569,722,910,859,381,649,95,941,655,343,441,635,816,198,514,858,20,250,214,144,406,314,802,47,305,309,783,113,687,138,268,5,428,948,18,641,669,52,906,52,515,625,407,602,988,408,143,493,335,692,895,32,365,414,279,308,356,758,168,447,236,34,911,285,920,393,686,590,534,257,560,470,271,333,460,881,89,12,102,151,44,622,671,102,21,155,425,177,340,189,466,183,582,334,961,441,417,363,304,401,68,896,498,347,644,998,323,247,955,597,836,438,644,678,632,669,775,800,296,404,829,506,184,471,771,978,720,270,195,296,340,603,214,250,921,661,161,515,694,474,804,251,467,397,387,379,706,578,106,790,775,243,922,822,464,53,974,320,800,411,788,966,864,286,808,101,546,637,869,415,78,681,369,666,1000,510,148,99,428,903,218,561,881,146,595,111,255,144,614,742,571,821,191,455,373,409,830,113,679,24,689,562,234,967,299,444,858,20,611,890,359,719,291,320,834,942,851,414,96,444,431,797,810,959,4,952,405,671,972,560,10,774,582,844,702,907,388,870,163,274,849,210,125,65,200,116,170,101,292,806,199,898,424,892,502,476,288,647,539,853,747,525,209,533,164,121,732,280,35,614,756,193,482,961,398,588,736,456,761,584,595,418,526,485,114,68,88,483,36,841,653,227,634,186,407,598,795,634,869,347,544,438,197,301,662,45,546,666,47,139,14,917,270,965,227,346,813,725,312,516,866,152,577,676,377,147,895,652,245,804,938,279,806,29,61,757,87,230,146,302,860,240,14,659,115,449,437,187,626,41,279,786,588,334,675,109,805,591,330,71,333,834,838,717,848,707,791,532,529,893,981,194,504,471,969,571,337,827,609,571,387,627,345,602,724,117,576,280,751,917,66,36,612,746,5,178,991,792,644,187,754,359,981,492,787,457,934,739,306,646,317,207,768,382,792,272,559,100,690,126,974,233,135,461,802,920,636,690,795,814,7,653,240,824,499,643,845,802,163,524,241,621,39,723,443,607,661,740,447,345,945,61,564,968,661,786,634,535,633,463,607,485,376,195,515,498,343,907,579,833,15,935,362,597,386,659,987,305,178,445,869,307,556,331,592,241,277,637,690,810,952,975,62,530,442,436,428,994,892,641,580,265,472,653,127,569,359,402,310,624,830,902,979,982,917,246,880,338,773,578,139,221,929,123,114,425,844,89,446,446,630,600,0,772,809,985,47,287,630,992,659,262,897,932,574,521,930,802,241,884,416,558,135,131,624,670,196,803,605,140,277,252,701,943,173,689,301,282,829,459,929,963,166,412,58,381,752,499,829,301,212,527,228,96,242,272,232,105,444,112,904,203,378,717,768,901,404,638,33,197,615,200,247,210,90,498,317,670,658,653,697,157,664,868,237,117,488,6,46,773,645,315,536,252,629,351,40,398,708,325,496,811,137,573,711,730,78,466,996,510,706,54,965,6,788,774,63,288,804,926,508,24,101,472,11,5,217,408,4,648,568,63,718,764,951,577,879,824,751,13,142,993,524,260,183,770,952,526,692,483,719,548,289,457,289,23,97,291,213,748,271,474,559,778,352,945,610,452,238,563,339,958,812,163,516,306,864,499,408,966,968,429,702,122,333,586,338,220,784,81,138,296,536,799,881,995,770,456,17,101,360,991,655,811,782,101,258,369", + "790,568,94,596,181,56,111,371,934,295,395,84,773,865,798,569,305,374,941,238,875,915,948,276,742,341,290,509,851,703,613,309,641,312,857,705,403,342,886,712,321,760,831,710,358,878,936,340,621,155,317,727,744,535,702,756,193,844,175,633,115,346,715,85,344,221,725,740,982,721,87,150,391,790,465,668,380,804,606,968,953,989,806,621,976,545,377,802,852,898,731,333,569,693,422,876,491,682,905,90,834,646,619,571,981,585,81,876,903,748,982,377,13,772,506,997,466,782,548,871,642,634,948,245,313,944,119,145,662,380,951,595,871,318,274,895,616,300,322,179,724,318,969,585,929,107,458,353,360,741,522,55,371,559,990,675,895,985,123,440,534,427,286,135,700,709,137,414,440,220,77,854,244,208,752,32,582,458,786,65,384,21,998,931,762,455,966,181,571,213,635,178,678,16,287,761,887,933,915,424,813,641,192,434,967,649,730,926,497,534,942,856,68,113,479,397,623,64,926,345,380,857,332,21,179,699,425,932,601,65,677,11,340,385,885,132,713,131,561,245,998,283,130,556,142,31,629,387,6,443,597,13,930,937,695,431,908,702,241,631,393,254,369,158,140,762,884,308,519,109,907,245,218,503,487,457,81,108,848,906,927,241,764,825,304,369,852,558,780,425,775,913,961,316,864,716,884,445,807,242,866,619,460,746,491,777,441,736,773,135,74,367,150,672,867,405,597,981,155,547,891,365,620,60,648,57,808,460,238,872,973,526,477,499,809,863,681,85,644,947,715,290,771,570,306,216,97,618,986,393,439,201,499,81,952,284,402,298,628,924,736,169,150,146,375,203,85,571,349,890,66,787,360,338,152,183,64,32,442,753,417,352,762,479,465,17,769,196,343,475,97,792,485,803,382,892,412,224,336,945,812,414,3,595,84,336,730,432,591,559,816,694,611,800,726,813,413,257,404,699,293,123,147,756,496,699,455,375,445,961,919,918,712,543,121,677,244,600,809,211,640,839,238,302,862,390,818,335,909,196,373,761,945,806,430,612,399,331,624,971,293,886,434,35,526,450,543,782,526,835,774,979,374,854,174,582,688,247,186,360,865,496,773,656,612,21,960,511,960,203,669,608,899,999,341,987,360,638,409,632,361,498,961,860,119,149,574,569,344,161,348,24,151,891,528,551,528,408,819,833,808,689,784,471,704,567,974,996,739,621,447,927,460,488,23,39,48,512,698,248,395,654,572,255,516,780,930,28,658,27,782,925,232,928,225,579,699,415,56,548,391,471,580,183,790,260,581,462,548,223,68,946,502,457,283,513,470,511,62,464,489,238,416,173,580,281,384,71,432,176,242,217,628,385,984,898,332,249,246,469,408,209,682,880,309,607,930,665,201,122,422,724,59,719,879,935,733,686,311,582,599,909,225,104,595,363,38,437,124,752,238,817,870,491,621,959,385,384,187,215,541,15,635,294,750,131,513,284,261,936,764,42,6,658,279,815,33,476,774,1,291,589,915,970,239,708,407,970,102,822,963,259,728,20,245,700,773,230,558,30,825,496,908,986,841,338,588,634,883,364,321,689,389,269,973,329,525,237,477,421,321,447,67,872,780,462,178,511,115,34,959,581,33,383,206,511,262,464,378,201,161,291,354,431,896,18,242,933,369,961,244,508,24,163,590,272,14,957,824,464,197,838,69,451,909,162,549,393,980,663,533,214,165,155,297,944,608,495,816,284,449,19,849,299,411,275,890,791,969,987,285,868,683,58,183,75,588,642,321,878,859,343,69,861,954,247,240,460,614,458,27,153,891,755,772,0,872,80,176,945,100,80,701,618,6,230,171,849,649,201,150,773,761,647,660,793,304,659,134,353,893,945,521,58,348,319,645,412,204,190,427,218,550,405,804,871,176,496,684,549,852,164,222,963,709,648,74,591,644,705,993,447,145,118,730,22,60,757,778,264,833,198,190,821,775,165,55,493,853,662,129,168,599,486,807,285,522,137,308,330,363,102,290,640,789,954,645,1000,472,235,79,490,177,76,314,920,304,523,240,432,292,204,508,722,439,212,167,466,129,777,638,741,170,233,882,486,452,782,281,463,100,196,113,966,728,286,881,493,550,4,774,15,195,342,617,981,792,277,282,834,545,119,110,412,293,659,658,806,300,243,467,945,448,524,491,834,435,336,662,348,728,701,976,328,178,183,414,500,631,704,8,617,770,427,518,459,173,690,260,960,724,316,737,741,370,151,988,83,921,869,953,343,193,916,581,20,3,50,799,366", + "268,640,937,439,864,446,628,532,211,730,893,166,695,153,733,553,998,987,338,279,35,660,465,203,67,461,481,638,829,322,399,473,121,991,80,222,800,435,144,768,912,504,303,685,559,5,548,365,398,906,615,522,187,842,664,835,529,242,265,202,262,47,419,138,501,117,88,596,926,587,154,164,721,604,185,816,705,708,842,433,328,69,294,15,586,741,452,72,110,358,328,21,303,706,240,371,274,70,495,508,609,873,313,305,827,749,298,973,678,588,645,685,316,562,456,62,785,644,27,908,917,935,256,583,861,382,143,690,366,857,381,102,361,492,427,652,244,458,157,974,195,200,506,193,19,576,337,760,256,525,544,158,811,136,432,849,552,860,809,575,573,722,98,361,875,764,591,209,5,632,372,151,994,578,752,151,463,69,675,786,614,671,133,164,288,290,222,100,38,901,67,76,401,331,193,411,866,789,259,378,248,798,501,78,578,181,61,128,534,260,542,519,366,243,606,125,129,962,709,499,774,89,227,505,499,785,400,873,747,244,227,119,369,555,216,687,386,724,531,775,354,546,54,803,279,373,504,341,9,708,955,642,388,192,435,711,721,735,90,679,780,924,212,877,167,464,524,338,706,553,173,766,745,414,118,705,602,909,675,745,119,191,657,782,904,404,449,186,990,670,386,618,573,953,542,994,925,747,481,945,646,452,520,185,715,151,157,211,754,242,561,87,124,244,40,323,818,418,348,557,828,653,951,609,887,258,242,334,967,495,40,203,466,277,566,449,68,765,751,338,21,226,453,74,937,611,798,198,171,837,96,288,648,671,926,65,783,814,593,526,862,51,211,536,407,24,204,52,654,339,635,795,278,237,832,759,709,517,516,875,797,594,231,871,274,287,732,204,598,110,721,644,610,368,870,787,804,948,748,646,116,948,336,650,999,491,42,656,105,206,39,602,54,57,785,793,83,487,979,431,182,509,607,731,723,785,994,688,640,453,869,875,761,752,834,139,24,890,639,519,485,33,615,109,590,316,64,562,329,341,31,137,847,23,583,244,549,851,594,791,45,888,7,575,920,67,828,371,278,985,54,100,745,188,815,311,544,143,297,749,761,764,321,780,212,608,787,229,376,2,30,769,363,73,468,4,438,64,523,417,198,590,745,399,747,14,424,670,932,857,611,323,929,746,87,136,829,458,888,593,428,915,976,975,549,229,716,442,283,994,49,63,651,642,619,704,969,832,852,483,107,731,511,223,236,5,775,782,971,820,599,729,620,463,478,265,70,546,589,686,208,236,500,362,268,72,746,308,548,932,575,778,256,556,229,834,570,943,630,917,407,61,298,744,9,991,627,960,189,210,852,583,989,805,792,859,801,95,586,390,880,369,344,867,115,399,151,137,217,392,2,325,152,586,149,648,50,425,699,837,737,353,974,398,258,949,134,741,900,918,850,941,634,211,575,394,583,371,957,668,671,184,557,419,773,449,502,489,308,18,709,83,895,980,16,708,969,418,573,641,136,136,134,28,487,379,300,598,424,663,833,834,341,989,818,558,801,121,776,91,150,426,317,994,862,172,35,553,669,961,192,544,13,893,10,533,68,669,20,123,235,464,881,273,167,186,532,704,472,880,216,557,655,537,681,563,822,546,843,129,111,944,697,497,666,82,469,83,817,644,881,986,380,586,404,359,858,734,125,536,228,122,573,454,29,786,146,1,764,985,102,479,289,66,663,179,511,998,127,414,696,689,237,253,894,522,545,721,664,79,644,761,957,474,122,65,706,598,792,531,637,632,909,462,631,176,933,64,945,277,702,422,478,767,809,872,0,812,949,853,822,474,363,632,648,417,162,882,460,218,473,304,156,794,557,270,396,771,294,936,55,174,848,66,893,312,346,924,67,646,601,509,636,255,148,165,176,364,664,656,196,387,748,364,475,357,283,765,147,546,914,722,654,151,255,685,129,317,424,84,691,934,523,54,796,713,464,655,430,596,363,40,606,707,747,866,445,159,384,221,253,550,692,830,849,443,190,762,275,126,543,545,450,185,369,822,33,426,253,684,588,851,335,692,964,71,659,588,689,300,697,938,112,986,154,825,976,275,350,398,595,107,850,866,111,305,21,374,141,316,714,21,911,443,96,79,607,868,952,750,767,768,19,372,26,78,691,956,269,289,387,301,635,849,642,153,48,415,376,500,839,938,193,788,761,428,434,590,341,887,222,672,287,875,911,120,60,804,301,234,952,474,686,970,223,772,926,275,242,564,640,667,649,726,247,723,541,799,761,637", + "176,328,576,930,889,9,694,871,423,969,280,566,695,161,798,726,437,402,749,799,865,355,662,638,786,210,460,858,553,566,411,394,434,895,878,258,123,515,246,722,668,935,81,267,289,251,846,268,769,244,507,633,624,592,141,458,241,711,926,658,114,976,9,422,604,728,756,333,41,984,521,689,110,176,611,871,573,50,946,950,187,626,494,494,991,28,797,342,115,419,993,46,88,662,861,561,325,227,514,60,490,678,315,474,711,602,395,724,564,448,689,570,20,104,107,543,598,880,191,746,571,334,477,106,832,205,121,759,54,781,377,488,516,315,527,185,314,199,189,620,882,254,465,7,394,166,642,891,202,698,714,705,910,42,114,106,128,293,355,874,625,289,167,888,501,843,788,762,573,299,231,930,214,568,497,577,393,174,496,659,162,945,168,317,649,10,763,386,484,506,385,968,250,600,880,770,509,804,250,365,568,70,640,971,224,742,906,887,409,317,287,679,470,253,930,551,803,366,358,304,979,791,656,544,229,53,544,861,394,523,261,15,945,575,702,392,12,611,801,416,58,35,375,865,49,27,410,249,426,582,631,650,489,260,51,523,261,359,804,559,426,405,957,483,536,841,949,422,417,923,929,178,104,771,285,866,739,640,751,480,932,575,839,619,161,852,683,520,645,563,149,769,427,647,375,131,973,810,446,586,295,517,760,782,917,687,545,156,223,925,176,717,281,418,923,431,601,932,858,671,456,367,692,516,986,96,33,913,684,539,343,448,677,273,446,425,542,729,314,914,164,147,783,287,532,969,373,429,657,439,862,573,415,339,743,35,36,195,464,466,56,348,621,627,111,793,568,737,347,874,877,429,128,861,61,569,756,932,103,15,108,903,525,696,405,817,732,549,424,707,420,619,768,251,762,844,47,357,190,295,576,263,468,311,683,69,665,351,331,806,861,445,710,628,14,48,167,463,957,895,737,43,219,11,14,837,702,401,285,290,235,705,127,528,266,148,72,590,114,136,487,212,113,519,758,814,113,224,864,773,396,435,896,258,132,600,444,457,808,436,2,299,409,172,158,338,454,482,723,455,560,980,811,783,341,868,834,889,906,641,736,826,389,733,794,695,144,854,649,60,723,774,354,146,955,322,748,232,84,315,329,580,413,404,875,377,234,529,746,586,414,125,761,212,684,818,764,205,584,367,767,97,434,854,927,589,873,464,723,904,2,855,226,867,526,894,876,525,602,567,274,146,345,417,697,400,29,660,194,973,967,436,754,515,294,156,270,305,98,412,470,492,148,469,69,852,950,155,268,153,507,713,344,22,268,163,183,353,14,158,733,486,909,892,474,393,653,747,74,469,886,232,498,696,360,794,968,865,854,313,168,417,432,35,89,438,291,440,726,333,984,783,414,687,259,398,713,996,13,291,706,244,180,692,248,953,950,883,49,331,663,425,603,235,667,63,675,939,533,235,232,147,986,432,382,645,515,397,650,835,789,52,985,876,568,71,394,882,509,950,44,234,710,698,508,409,229,554,72,879,101,991,686,352,973,119,419,661,776,945,510,88,865,808,28,918,953,827,726,128,686,706,550,477,147,314,968,177,912,738,917,824,367,201,355,6,919,299,505,672,7,500,632,418,102,677,407,31,606,916,781,15,668,339,110,809,179,364,897,160,930,274,929,3,454,317,393,581,464,423,58,120,640,167,384,971,575,261,36,643,31,710,912,944,833,259,409,230,544,793,392,482,262,306,721,879,765,239,298,308,521,389,388,912,768,679,953,364,44,256,211,667,399,92,598,359,733,902,599,881,715,572,662,487,985,80,812,0,488,908,543,964,981,126,258,753,405,892,225,657,442,903,663,974,796,535,977,673,63,440,450,472,35,192,820,290,906,254,484,146,415,836,113,849,107,673,706,983,40,901,862,576,499,759,892,522,571,784,447,318,420,263,199,52,551,646,395,632,353,382,779,234,827,64,440,123,955,167,622,447,822,810,37,11,134,258,86,520,900,188,342,117,545,796,416,927,789,234,184,215,914,968,119,211,209,432,832,977,244,760,37,335,311,891,383,913,776,586,223,72,455,186,651,938,654,700,251,773,868,605,176,43,699,500,990,446,579,276,300,570,632,512,729,907,371,775,970,254,622,685,777,349,211,199,84,785,497,340,366,498,726,911,81,716,538,54,233,775,925,631,242,185,86,864,464,885,572,67,36,491,388,700,813,321,965,966,75,6,760,189,615,277,599,527,993,632,960,65,947,202,238,419,848,911,259,349,500,684,603,377", + "998,932,995,922,143,568,514,618,177,926,764,850,391,43,253,341,614,637,93,870,50,350,160,152,35,862,485,895,363,458,240,911,429,391,14,406,505,394,945,253,543,632,496,399,584,824,17,258,412,86,495,660,823,313,430,989,717,120,877,244,785,350,509,755,168,466,272,553,138,894,858,226,39,216,137,799,900,217,469,359,759,143,53,649,861,630,321,980,436,297,100,58,58,15,571,7,292,607,249,909,358,372,17,512,251,27,54,410,854,61,609,612,397,853,256,470,114,601,992,124,631,827,496,439,988,173,364,892,290,455,215,576,671,697,100,435,661,156,619,34,705,709,471,420,836,739,614,674,780,122,342,921,150,611,405,815,851,494,551,778,948,766,625,613,505,570,524,757,282,919,341,907,864,214,280,10,3,661,242,612,31,357,41,406,681,815,412,616,268,127,266,921,35,933,751,708,642,226,363,90,857,121,462,26,651,233,221,487,454,15,760,422,944,256,526,516,102,446,523,98,725,816,975,129,273,331,962,338,132,220,404,986,626,813,999,812,563,897,453,439,485,244,336,68,446,328,225,427,150,184,338,689,864,554,866,217,250,88,311,562,570,542,380,621,393,848,531,806,288,121,881,597,122,711,301,506,587,996,964,96,616,621,274,349,41,374,889,30,245,958,529,758,515,199,723,521,630,593,290,184,53,242,672,966,241,20,95,492,511,530,366,550,17,599,35,732,281,462,45,208,315,253,723,864,962,687,788,256,623,318,607,465,396,927,111,160,801,912,727,611,156,111,529,302,341,992,875,917,348,852,448,148,989,718,725,863,499,502,460,755,53,497,886,412,295,79,436,671,504,371,861,648,795,358,659,425,532,201,247,406,759,442,723,246,936,561,231,437,902,914,501,372,792,18,97,580,776,565,569,793,460,489,633,407,16,198,789,470,966,830,709,347,676,565,333,46,868,934,620,469,231,751,163,866,786,658,532,964,799,474,220,75,146,396,895,792,806,557,999,91,517,199,928,304,971,409,287,183,355,863,509,356,876,247,148,412,706,793,636,321,558,350,598,642,485,919,627,151,794,583,338,853,773,357,920,69,829,9,865,913,586,597,646,157,596,34,58,682,127,72,829,219,344,287,767,549,264,850,332,315,946,184,9,309,973,506,671,743,535,349,123,876,729,98,602,403,916,591,298,607,925,356,226,188,387,335,901,159,398,419,764,613,280,422,960,222,332,559,635,240,508,574,864,825,546,870,942,598,736,752,551,510,86,5,29,615,194,980,442,161,153,441,63,420,608,463,59,106,861,966,307,199,956,31,304,960,297,262,415,832,176,561,967,858,75,224,569,138,906,201,866,191,960,452,26,533,121,131,407,468,834,571,51,623,801,936,432,753,933,439,501,872,130,576,64,438,668,368,746,712,510,299,998,844,514,503,885,459,919,513,788,772,925,193,732,369,751,997,520,577,401,712,962,23,745,363,6,464,164,577,412,111,749,905,595,721,764,963,161,980,871,916,321,357,799,913,214,159,965,943,116,232,136,172,268,406,195,996,723,60,918,306,544,988,497,849,566,215,625,523,514,230,270,821,944,716,370,359,884,591,662,258,55,224,694,668,104,4,152,555,873,117,425,698,271,727,173,97,6,392,965,493,492,820,449,744,838,410,11,92,137,921,405,641,844,806,703,172,951,564,110,617,608,864,913,319,708,803,434,649,143,371,719,661,333,351,297,756,347,312,169,934,204,308,879,404,403,59,3,849,733,975,312,126,668,667,581,448,435,172,451,101,215,821,916,756,142,641,746,865,972,518,712,43,47,176,949,488,0,543,783,553,344,839,892,40,288,298,359,645,107,976,744,178,656,283,979,518,633,908,918,407,556,944,96,846,751,953,634,137,144,62,617,459,735,675,817,638,521,313,498,85,731,447,169,365,149,503,320,448,876,639,237,571,526,571,962,597,802,965,346,496,554,960,433,27,258,357,950,125,715,809,139,777,83,199,609,28,838,106,79,755,801,77,956,604,611,560,752,109,547,175,914,336,567,596,156,200,143,176,132,221,234,627,674,990,18,504,778,399,194,216,538,370,304,479,432,925,839,886,596,24,536,38,727,384,565,919,26,500,118,762,363,265,867,250,587,159,713,931,640,615,782,752,906,923,51,115,494,172,728,65,216,742,713,340,97,266,11,448,928,967,498,954,778,403,989,956,399,198,132,835,911,123,323,36,837,729,527,206,584,231,985,75,512,366,67,515,436,233,894,289,255,27,443,11,639,537,150,289", + "811,520,751,316,916,837,117,852,423,313,231,713,891,573,327,378,602,698,809,420,127,805,733,515,265,332,107,463,572,470,646,780,144,716,728,884,258,795,636,116,307,663,202,332,472,828,818,940,398,319,631,544,751,335,306,729,108,959,152,551,860,441,351,199,166,150,491,759,168,602,50,841,785,815,693,630,844,833,827,171,598,649,250,78,90,804,928,616,50,542,733,109,689,808,306,762,655,8,821,453,924,289,197,655,252,206,773,972,975,581,445,19,618,127,499,904,922,353,838,405,899,298,980,818,378,553,288,559,912,853,361,837,987,701,386,137,495,3,101,956,379,996,508,286,904,325,185,596,788,183,648,29,731,473,803,527,432,333,146,20,594,382,817,366,355,738,279,671,14,943,635,186,368,998,94,792,235,651,643,526,305,850,238,8,252,207,811,622,550,332,486,849,509,722,26,668,426,208,570,120,416,697,690,54,362,515,217,791,270,5,115,364,314,197,71,206,19,608,430,316,464,825,578,99,841,217,150,374,158,726,978,593,64,718,651,163,184,934,558,794,616,303,689,585,4,536,309,342,631,720,753,593,905,418,110,332,236,661,347,985,166,19,146,258,279,129,692,391,442,832,831,618,611,633,641,505,571,431,606,56,139,789,78,102,147,587,114,264,653,465,599,749,473,450,143,849,507,185,745,937,54,416,325,910,849,707,307,206,306,214,716,698,823,24,314,128,384,478,425,975,562,117,198,564,816,230,828,793,124,267,226,541,442,157,343,516,171,622,916,447,424,296,5,259,258,278,702,147,769,375,527,378,346,382,544,14,286,747,751,244,447,373,706,132,280,525,728,958,18,438,306,480,183,955,641,768,501,359,675,291,96,953,211,460,804,524,681,460,567,520,905,249,308,559,953,310,668,208,121,712,333,726,373,241,629,797,497,855,873,165,537,729,541,620,616,359,150,635,962,143,888,514,830,434,477,769,35,891,391,609,271,991,306,380,931,5,621,774,891,378,715,328,488,837,253,964,383,63,841,406,463,344,159,992,711,920,77,802,499,228,350,933,566,766,817,722,428,980,290,915,870,633,920,868,157,507,142,543,119,83,877,95,640,265,334,569,666,786,770,617,348,410,212,748,383,697,406,729,370,679,459,4,742,903,146,972,304,565,99,983,329,33,234,978,179,296,603,82,185,532,334,291,310,876,412,929,238,153,520,11,429,648,168,928,810,466,985,988,303,525,371,567,120,757,404,761,56,904,571,910,777,136,483,696,369,54,528,98,23,273,347,276,863,31,296,466,438,48,292,3,716,730,485,349,477,566,165,721,688,532,482,324,967,393,198,412,802,428,828,620,233,132,325,875,404,304,407,698,561,8,343,707,649,522,444,650,309,82,889,946,48,127,58,550,252,937,211,465,644,628,54,144,511,386,63,530,254,722,189,438,392,290,19,722,881,962,368,539,228,658,70,657,152,832,345,620,740,590,207,668,49,341,876,334,496,198,614,70,53,191,843,12,928,359,98,299,326,205,874,897,307,770,858,242,398,734,913,257,947,121,605,180,806,950,917,855,159,515,971,27,554,276,33,65,803,681,595,842,354,668,134,992,531,317,880,908,47,240,777,506,450,492,119,3,220,557,401,997,261,813,502,918,817,92,127,211,953,408,193,503,831,346,596,149,224,8,585,408,808,737,816,882,87,812,505,515,931,427,70,463,783,833,524,28,884,889,882,209,28,202,743,370,137,348,878,72,335,627,974,33,670,174,728,153,286,287,786,40,922,910,975,259,228,48,433,9,71,706,813,291,64,45,637,979,287,945,853,908,543,0,915,757,102,954,566,244,61,677,829,572,936,194,581,281,386,353,990,459,228,374,502,154,200,600,872,129,327,388,332,695,164,838,847,489,887,990,22,211,972,7,973,512,119,151,824,669,290,232,242,193,767,459,82,776,777,637,975,573,427,803,419,547,334,298,218,233,529,204,979,251,294,99,90,967,899,631,440,105,528,382,437,322,319,995,978,2,399,782,850,840,682,310,236,755,650,846,297,407,586,419,212,869,220,506,830,309,556,472,979,49,845,855,240,752,849,789,727,512,377,493,810,613,207,603,957,151,932,902,49,824,642,607,903,994,654,20,459,226,15,228,406,677,133,702,755,557,164,330,28,602,565,10,397,567,271,61,871,208,645,491,39,50,101,952,83,393,389,190,113,639,701,627,623,853,731,239,266,465,64,419,916,924,936,719,198,338,742,728,883,601,957,366,713,342,934,80,953,76,889,768", + "987,288,235,917,455,211,617,992,250,755,276,735,325,924,947,690,270,566,60,652,356,507,435,799,75,941,564,55,801,938,850,468,357,736,922,729,437,508,62,346,510,733,320,779,182,8,373,235,827,151,703,598,90,811,719,87,985,317,15,779,254,186,731,934,579,294,699,635,252,22,879,193,6,832,887,245,12,604,275,249,338,172,202,53,321,170,772,621,500,729,549,303,831,927,230,826,760,552,749,462,514,64,522,142,866,957,259,236,912,285,880,948,542,783,47,598,398,992,543,205,445,403,89,149,617,112,127,916,997,316,852,738,1000,659,571,203,743,99,53,13,1,348,454,303,657,161,397,93,261,72,319,861,15,270,332,608,274,470,484,640,346,614,777,506,214,782,361,235,355,272,359,900,590,72,897,246,263,380,908,278,574,349,347,879,798,557,340,971,797,887,284,23,390,449,830,725,348,749,48,754,565,623,605,76,890,133,681,272,775,192,757,95,267,103,917,726,336,175,10,475,927,796,740,885,65,829,486,506,876,287,84,399,723,474,559,473,616,966,463,966,464,379,758,193,179,140,524,918,188,769,798,844,297,32,246,913,982,168,591,415,732,127,10,430,162,916,79,509,192,959,684,687,807,634,306,782,246,760,937,185,938,365,974,246,693,958,240,843,566,882,585,304,759,434,832,62,36,766,406,610,683,726,887,582,662,896,551,642,815,800,122,968,708,23,933,561,942,139,868,321,621,537,217,779,396,609,482,419,787,246,42,289,395,594,447,69,879,828,504,279,27,889,408,729,222,156,23,938,434,271,791,214,751,347,472,749,73,229,893,971,672,400,734,262,954,776,942,25,159,337,869,489,355,761,608,782,118,410,514,254,424,34,507,740,850,423,167,557,352,971,28,406,187,788,994,974,1000,773,553,557,203,186,916,988,60,81,21,773,3,275,343,676,857,716,850,909,108,487,678,452,599,20,227,19,951,39,630,532,595,805,667,732,504,702,342,881,269,226,692,139,961,845,618,967,184,399,818,419,431,751,136,169,778,701,659,67,532,765,25,211,974,524,355,914,260,475,440,839,894,220,550,803,224,973,269,555,509,578,531,662,74,533,344,663,718,592,424,152,912,475,908,995,36,887,661,489,777,117,808,754,423,195,584,100,274,83,683,885,50,234,186,46,694,529,784,754,212,378,303,440,741,412,487,858,949,888,207,714,685,702,251,591,623,370,136,487,598,387,266,131,791,277,104,355,684,470,612,479,293,29,214,331,953,88,445,6,341,235,74,487,982,822,131,660,366,163,807,180,565,370,725,756,673,575,53,673,206,206,897,737,275,881,936,259,456,89,11,938,36,394,247,599,964,725,48,846,62,591,200,260,248,898,958,444,772,580,480,133,721,239,127,592,837,841,253,792,607,551,650,817,17,719,100,161,105,106,959,890,90,296,316,523,911,290,977,308,854,667,552,11,684,490,916,93,549,674,495,683,493,54,761,73,562,387,589,588,400,944,640,651,927,48,146,634,979,534,496,78,466,871,951,991,23,436,74,422,215,3,921,497,350,473,342,658,113,775,587,884,274,121,618,585,87,724,766,782,767,300,618,672,402,206,606,588,81,224,921,852,516,520,130,595,869,248,387,86,847,383,742,59,670,268,830,358,65,102,363,411,631,368,460,577,774,69,194,788,369,832,758,292,550,885,411,348,568,590,758,368,934,984,73,220,894,73,152,573,404,974,479,773,273,830,664,653,743,21,332,68,921,891,607,396,522,478,176,352,623,168,436,847,643,495,167,352,653,331,603,826,358,569,597,389,706,419,630,100,822,543,783,915,0,612,924,640,642,532,181,909,354,456,752,336,677,773,605,251,108,967,283,342,588,488,954,193,667,865,482,701,265,284,62,460,365,684,837,761,485,526,554,9,793,949,407,803,18,61,441,346,385,974,792,944,524,693,669,722,531,704,944,555,174,438,484,344,131,744,740,590,674,496,852,234,318,559,479,788,543,722,453,582,488,541,180,752,153,91,353,900,89,150,685,81,948,11,130,927,43,318,710,721,917,789,78,774,846,165,770,331,304,785,70,344,779,717,565,387,295,357,229,71,121,276,457,945,817,572,505,322,735,520,654,634,501,521,854,955,420,823,531,674,939,994,558,635,601,735,622,122,93,925,48,871,325,351,827,863,451,905,544,373,812,922,721,168,526,908,982,785,895,512,806,673,629,571,519,276,589,699,173,840,143,789,583,156,134,456,690,719,816,143,795,678,838,799,61,323,663,159,926,584", + "130,663,914,751,731,865,239,84,523,791,637,63,714,692,595,231,470,702,509,678,400,200,460,359,926,613,719,813,972,748,586,887,441,661,881,486,330,599,138,217,334,768,522,594,139,801,318,127,534,357,837,292,541,873,474,190,352,139,832,98,674,526,44,894,213,533,365,263,496,183,748,651,83,483,770,209,432,701,150,683,855,1,948,614,991,389,434,261,617,998,413,270,141,295,689,870,725,840,645,212,231,573,343,643,839,142,656,760,589,507,88,430,881,718,970,317,274,335,664,162,373,516,806,825,529,915,524,469,101,812,892,369,118,955,880,155,262,492,280,234,252,320,419,340,102,310,327,297,823,993,9,433,104,760,690,24,835,71,242,236,569,421,535,636,958,470,858,74,564,877,616,611,248,394,990,962,919,302,537,707,779,812,438,681,264,213,79,879,440,51,901,881,89,221,815,676,254,273,493,80,783,525,66,109,591,886,731,172,693,425,485,140,216,703,883,537,536,737,458,612,855,104,439,822,549,592,344,253,163,587,28,978,844,810,729,188,884,131,359,655,731,916,554,651,70,395,765,306,403,213,329,874,952,585,949,968,366,401,717,489,987,819,64,112,381,675,246,314,154,448,943,553,720,108,945,41,682,924,389,767,575,809,715,259,366,683,598,385,103,756,771,195,554,939,261,833,613,193,308,329,818,62,96,616,379,294,876,662,100,148,318,862,716,90,218,817,738,687,600,725,553,363,813,611,153,969,702,399,345,811,972,215,31,611,470,607,597,352,892,187,562,341,308,387,533,989,541,760,980,714,91,673,92,882,310,114,689,764,374,399,661,984,418,152,225,904,549,781,580,840,240,470,423,587,846,63,906,723,512,749,82,112,91,564,833,415,265,862,867,236,131,956,953,48,373,286,120,275,590,546,666,439,597,324,625,528,881,966,362,537,681,114,328,257,82,67,545,321,318,327,887,656,891,957,823,280,312,794,276,118,491,534,714,692,736,7,993,115,873,268,306,16,62,829,247,482,339,612,695,151,912,960,756,899,867,209,605,212,182,699,685,631,71,347,233,333,652,486,72,354,254,788,298,507,834,631,554,430,563,124,407,577,925,568,971,556,181,186,237,588,98,21,337,227,97,919,162,471,680,998,152,213,229,776,548,793,878,836,50,594,766,26,368,663,493,443,498,102,685,988,517,848,627,172,347,974,393,10,578,34,21,727,369,481,638,410,476,838,857,224,761,736,753,526,257,570,741,645,381,603,974,759,457,726,572,529,131,115,984,171,831,685,522,513,357,627,544,740,955,549,80,51,966,846,198,228,34,517,745,705,157,329,874,734,839,490,460,611,244,895,570,612,418,580,233,372,355,300,853,98,986,836,354,74,931,443,477,302,781,231,758,288,742,260,113,843,158,163,725,672,62,391,257,49,379,712,397,595,338,67,226,755,352,834,580,544,958,825,365,797,513,351,149,542,381,494,854,236,349,422,460,557,791,617,951,480,975,388,738,887,41,99,795,976,142,685,889,331,447,674,923,146,575,55,558,239,603,931,836,401,825,819,342,879,678,809,910,11,870,879,674,391,193,765,903,120,519,189,816,396,749,988,195,881,700,276,924,123,288,21,528,535,853,575,289,197,532,507,331,457,683,68,289,54,647,729,202,972,590,993,697,648,715,596,23,480,209,46,82,329,138,491,910,329,996,405,779,152,539,799,679,194,436,352,681,558,708,605,152,648,912,662,755,381,128,154,942,140,165,450,177,507,934,561,536,332,53,706,620,163,562,103,8,458,699,794,511,339,93,987,954,766,294,914,992,80,474,964,553,757,612,0,741,779,31,989,230,588,876,161,26,683,653,154,770,140,331,622,392,752,755,7,174,28,587,504,658,370,181,189,616,373,750,119,110,780,932,326,150,34,513,752,738,516,391,87,891,101,368,672,236,354,867,215,835,749,284,320,86,590,30,28,757,744,520,158,827,725,949,546,789,390,127,371,157,714,535,643,445,111,172,125,515,3,338,238,430,459,671,666,844,511,709,607,43,309,744,149,617,511,777,745,710,638,452,587,394,264,504,401,75,783,748,569,150,753,111,233,569,972,533,691,530,371,350,555,705,861,208,92,866,380,646,517,211,226,179,357,64,341,875,206,580,646,727,425,139,531,337,898,90,576,889,789,488,976,125,516,795,816,633,558,598,555,522,317,484,861,320,851,144,552,36,482,15,31,12,277,286,752,66,521,238,147,123,15,467,110,259,780,994,195,587,224,8,82,440,922,524,783", + "307,519,855,203,655,280,425,430,750,579,655,627,929,17,4,168,190,848,593,119,376,507,638,134,927,200,932,913,203,35,173,787,273,710,149,177,79,740,930,523,685,531,131,844,333,595,192,676,359,470,637,292,29,270,145,161,550,538,645,425,95,26,134,149,808,515,538,165,293,566,416,642,932,672,357,470,605,353,388,610,669,411,66,463,215,293,309,114,371,16,930,130,91,970,846,184,340,545,278,927,446,763,760,807,661,305,877,983,80,812,818,815,86,790,942,237,174,108,138,209,887,812,32,336,108,905,810,101,84,695,389,552,565,345,15,878,434,454,742,852,646,734,839,293,808,776,762,998,55,151,802,776,52,459,790,644,622,974,394,657,831,240,59,979,139,69,640,324,83,393,543,248,356,610,10,237,276,8,973,582,695,412,834,682,186,782,469,650,882,52,483,922,934,848,630,351,773,393,88,624,111,281,476,429,159,311,582,713,180,225,229,9,880,172,710,813,878,720,474,139,592,234,101,817,374,160,546,179,883,889,79,729,515,561,652,694,234,959,575,641,68,465,100,766,603,200,657,920,394,940,348,634,847,751,443,992,234,796,744,322,551,859,28,195,117,479,536,742,102,656,811,413,421,802,916,561,485,432,544,87,501,762,135,686,58,718,835,979,349,301,166,819,629,913,417,348,541,677,565,326,957,132,280,838,530,339,951,123,467,465,900,176,507,675,200,681,276,984,482,266,297,377,291,638,959,512,228,581,677,762,165,698,973,586,829,851,502,879,439,744,626,198,650,530,489,584,183,926,890,612,103,714,581,738,873,149,845,318,973,988,136,649,458,187,26,522,346,161,915,733,92,674,944,690,291,262,344,896,351,308,861,545,608,811,263,433,487,517,175,898,239,312,822,185,345,40,351,376,120,35,203,686,356,825,818,494,450,446,247,568,508,342,637,332,722,480,386,960,906,346,570,907,170,577,282,974,16,851,300,318,828,290,488,494,769,761,57,441,5,44,149,925,926,333,925,21,526,571,913,667,358,15,959,70,936,596,501,34,901,61,614,942,280,676,472,722,828,288,143,208,789,841,254,851,430,448,52,499,163,583,166,575,676,132,503,209,970,86,642,954,277,173,64,78,71,181,168,221,136,266,914,668,831,934,33,310,525,468,860,658,284,998,102,707,148,209,587,715,57,661,90,244,652,597,53,785,140,369,769,347,769,190,715,610,216,183,787,757,172,190,687,606,450,622,37,955,843,886,390,550,456,371,173,848,54,322,138,445,47,138,646,162,468,352,999,15,21,357,580,335,434,582,856,515,61,411,164,400,698,309,533,153,929,237,839,937,934,177,18,833,969,642,356,280,841,130,247,962,207,392,421,244,550,844,362,861,508,155,242,207,918,669,695,250,205,786,233,445,334,621,658,199,488,798,421,432,299,9,404,43,948,692,277,619,890,557,644,726,946,75,715,315,259,910,314,790,392,342,716,746,879,224,194,988,312,818,897,870,166,702,429,450,627,352,242,155,153,10,4,321,794,64,729,248,557,280,405,295,619,304,530,554,505,239,709,761,23,810,577,211,714,735,8,223,880,443,165,875,21,285,644,250,147,240,203,997,584,874,968,217,876,379,169,93,949,63,194,245,336,385,391,732,155,16,253,973,936,866,313,399,332,54,945,364,477,260,177,755,680,630,605,776,388,658,973,140,33,917,945,759,550,924,801,686,774,365,131,727,998,685,67,302,636,806,786,139,921,791,834,889,145,174,829,521,764,96,235,45,2,696,609,194,529,590,136,959,252,209,592,158,418,982,535,282,659,701,363,981,344,102,924,741,0,1000,144,191,675,661,59,86,698,918,937,796,367,175,666,97,981,116,776,21,611,354,634,409,5,926,378,200,530,337,567,889,911,933,455,982,864,97,518,277,731,433,703,716,240,585,986,98,101,96,656,350,872,786,152,964,32,138,373,108,223,864,544,30,84,513,997,556,960,64,223,34,354,551,829,647,183,51,151,56,271,929,251,714,660,867,206,761,847,633,665,697,678,556,522,455,73,626,329,114,276,273,569,745,61,542,56,539,73,813,10,117,103,17,264,675,387,866,374,45,63,205,763,374,325,359,521,739,117,775,870,799,315,974,119,666,459,298,731,365,499,66,485,382,787,598,253,230,788,606,727,388,690,300,114,322,732,704,714,772,215,452,261,729,859,844,680,299,100,877,664,310,240,633,225,384,631,713,883,460,541,793,176,764,695,100,460,570,944,845,177,968,821,616,129,859,62,819", + "735,741,548,557,620,10,839,937,186,967,275,516,520,737,886,568,831,664,824,323,627,45,123,254,854,409,463,645,124,25,503,286,723,45,455,78,207,924,588,500,63,392,242,26,764,321,893,31,729,538,313,916,761,472,359,21,98,584,823,368,245,171,448,686,139,823,515,655,550,590,407,831,996,198,897,627,213,459,166,580,197,370,351,510,775,169,742,710,345,648,108,708,569,777,975,169,235,139,801,385,594,667,261,959,994,946,911,712,879,772,425,480,946,276,741,982,707,93,939,3,166,157,777,927,254,688,232,875,359,515,477,844,435,946,99,971,954,7,800,314,225,523,53,720,870,37,373,913,67,38,184,531,731,943,897,392,921,391,473,523,334,674,93,703,130,378,787,290,264,729,748,757,376,78,599,226,822,441,598,817,672,306,940,157,95,445,278,895,756,186,575,508,384,928,345,206,540,924,92,47,615,888,234,289,293,666,546,442,453,509,329,878,501,733,654,633,759,872,425,521,862,697,930,269,567,430,283,451,606,871,963,297,347,118,846,103,543,932,692,157,778,742,750,380,317,60,439,750,389,565,9,860,739,747,906,15,285,905,739,242,545,692,656,374,256,318,662,974,479,92,419,278,721,482,860,105,273,909,374,261,660,385,565,756,706,637,494,874,616,782,448,540,822,298,365,760,848,750,222,511,569,909,819,363,71,710,490,494,267,926,138,353,82,384,644,542,704,946,512,875,168,2,281,394,915,542,240,987,465,962,931,622,671,638,489,496,586,730,482,76,384,200,681,499,571,416,144,386,623,736,260,221,284,642,194,210,986,156,700,128,373,643,529,897,400,772,746,253,49,431,234,973,47,887,669,828,206,198,300,153,648,12,874,674,681,454,685,669,893,647,347,552,70,882,21,500,972,746,353,285,279,97,69,717,19,253,89,813,862,78,557,640,408,511,797,850,295,123,999,411,454,450,39,394,130,61,112,229,361,133,168,367,604,330,616,332,586,649,298,945,78,115,741,252,974,242,381,54,693,468,792,378,646,261,914,715,147,580,686,395,671,417,605,880,221,486,752,840,830,407,412,204,175,20,27,813,319,424,637,806,64,19,455,994,253,880,260,683,854,820,580,707,120,397,669,356,645,734,149,973,479,327,251,674,181,969,213,479,515,56,456,235,533,532,652,504,226,648,559,362,292,220,984,425,490,169,368,157,970,312,479,478,974,76,123,248,799,99,661,123,376,884,904,228,788,728,256,77,588,431,780,632,785,350,483,336,335,995,958,739,690,392,27,997,231,264,120,243,994,437,834,561,613,383,706,196,740,472,54,886,330,620,891,88,629,107,945,176,657,161,943,778,952,596,245,856,134,424,665,684,574,675,812,79,890,453,299,936,800,730,579,445,203,533,69,377,151,13,976,224,999,386,402,618,11,792,428,395,422,499,362,177,250,890,94,428,218,873,809,440,19,969,869,220,501,402,978,45,72,315,332,569,100,172,148,656,685,394,663,950,935,967,172,34,750,177,207,20,695,938,394,411,272,799,892,79,113,684,166,208,590,239,477,981,46,371,133,630,994,581,636,245,828,79,10,347,111,88,468,507,105,724,765,970,593,67,522,599,526,733,666,591,620,829,851,368,776,561,956,424,989,381,984,326,53,311,207,513,323,424,573,576,796,272,854,530,640,261,989,509,762,73,492,505,194,40,447,649,842,94,751,347,667,942,516,806,482,986,420,838,458,427,981,249,486,986,552,169,528,480,68,757,29,4,60,990,414,770,291,19,509,568,467,61,960,425,319,923,741,78,29,68,90,107,262,618,632,126,839,954,640,779,1000,0,295,125,777,776,406,413,691,957,278,963,749,629,801,801,481,770,751,891,756,327,700,999,843,668,141,99,240,168,859,10,234,528,14,963,387,604,743,386,872,92,201,690,309,581,356,193,78,205,909,980,711,241,870,722,882,824,972,924,458,994,853,220,258,766,720,641,661,697,116,434,212,35,59,321,675,41,274,868,69,798,978,739,415,670,995,295,666,967,978,121,617,951,169,379,395,757,180,77,252,495,178,157,103,947,713,239,101,316,729,345,647,502,757,251,141,121,554,33,523,698,988,903,821,541,854,203,49,1000,526,428,95,741,79,944,46,227,444,531,811,968,787,469,447,653,189,263,311,699,371,531,430,754,26,585,677,739,927,151,757,773,63,487,277,669,710,938,92,723,671,194,422,834,500,482,760,521,397,661,760,451,995,870,677,121,320,671,39,992,282,732,527,855,316,928,671,762", + "414,115,434,26,704,144,960,566,537,855,789,19,219,563,288,683,538,121,938,360,383,362,335,20,338,973,890,887,247,874,686,658,201,229,772,622,297,437,528,702,182,274,57,756,74,232,13,439,142,670,952,232,902,674,303,648,366,791,587,16,494,730,754,63,227,719,73,136,847,224,157,42,361,395,591,637,646,273,944,584,203,73,742,643,328,722,810,347,254,17,889,460,278,865,83,381,79,286,995,801,998,296,303,225,983,960,417,385,559,8,768,878,40,928,297,73,33,179,711,84,96,582,717,168,440,620,668,253,991,122,494,970,574,626,376,849,853,454,545,599,743,872,638,671,771,624,901,12,600,56,939,17,364,408,405,993,405,262,775,583,224,240,257,649,313,118,61,363,186,378,999,723,98,476,439,550,647,428,470,836,845,494,953,32,394,63,186,827,121,623,819,302,567,194,692,501,211,218,900,986,652,447,362,592,277,958,398,572,81,976,14,389,824,607,274,902,783,537,907,910,504,601,429,624,247,561,922,356,298,552,691,286,131,341,296,772,808,471,338,977,808,244,532,572,21,388,671,493,540,449,742,582,562,83,143,328,936,791,642,876,295,15,697,592,963,244,293,329,142,774,909,286,515,93,804,589,961,612,990,739,438,299,349,188,634,492,143,543,202,662,804,578,440,540,570,386,537,128,973,355,988,523,904,18,592,699,684,382,77,268,756,921,89,387,405,394,853,658,325,377,541,746,433,702,131,558,402,425,600,465,657,236,870,126,480,327,480,455,251,719,46,698,267,241,749,416,54,896,533,68,798,789,610,929,57,727,815,245,555,601,751,601,170,33,876,826,247,257,564,782,881,991,774,649,674,832,876,429,977,117,443,653,767,957,499,398,508,145,973,379,710,408,99,706,907,993,705,407,451,388,750,280,47,60,942,196,944,760,255,731,407,593,384,668,274,303,577,606,638,996,812,865,766,795,705,826,877,772,255,146,159,979,986,726,202,870,52,794,76,460,947,743,732,487,930,895,484,62,23,717,608,162,241,677,423,191,513,440,204,29,94,153,898,767,722,291,273,908,352,803,243,635,607,682,955,164,378,471,661,966,257,755,200,739,696,339,724,731,645,3,602,569,220,216,595,731,197,75,177,733,911,374,406,707,290,323,566,609,809,146,327,467,978,550,551,595,128,587,524,730,623,485,306,76,435,657,413,943,624,579,153,342,226,268,232,641,996,93,948,616,459,984,448,987,486,400,756,910,54,883,783,26,658,789,35,37,58,276,274,510,116,749,525,728,205,412,240,449,708,665,681,370,734,731,307,476,452,310,737,431,381,534,442,86,515,994,902,619,671,258,308,996,620,60,898,78,421,84,468,393,719,582,493,75,239,740,313,320,578,602,865,923,487,963,82,429,697,15,538,262,507,877,405,739,967,129,803,495,110,280,607,693,281,891,181,447,494,775,1000,402,774,15,623,251,737,989,900,615,747,231,204,103,325,532,585,298,497,498,161,788,568,394,777,14,826,58,839,688,185,338,870,873,809,50,176,439,218,582,754,766,646,537,387,739,736,813,164,76,126,120,167,895,55,180,291,143,215,478,255,942,541,575,660,29,350,5,924,593,396,670,943,201,865,2,296,376,877,663,373,721,706,816,428,862,299,107,429,756,855,456,917,219,232,92,337,118,710,118,518,55,888,734,292,338,728,918,414,794,665,550,207,225,948,316,734,999,567,619,230,55,54,313,932,296,219,56,892,407,98,637,67,10,335,629,894,793,543,709,501,685,356,52,819,430,626,245,169,239,800,247,717,72,698,412,897,6,648,258,892,566,642,31,144,295,0,798,514,326,574,37,923,675,863,663,168,687,89,815,673,44,797,102,509,963,520,621,149,947,889,519,590,413,287,363,15,464,69,541,843,63,791,624,624,728,793,85,970,570,206,771,520,707,262,627,581,84,204,554,48,113,684,62,804,365,279,954,816,758,579,677,559,159,810,888,545,129,802,750,177,74,966,801,26,45,994,355,23,262,737,210,675,186,417,944,732,178,760,301,867,618,562,559,183,842,430,151,261,945,380,143,854,505,178,798,273,91,781,108,730,264,929,438,239,145,400,727,210,83,79,717,78,172,771,383,695,36,662,587,24,674,161,154,194,486,279,611,118,331,307,554,765,201,710,375,752,362,278,704,177,513,847,661,173,692,70,347,548,131,333,630,517,40,140,430,860,190,656,482,873,492,104,846,236,806,994,657,467,299,224,727,714,713,355,304,496,85,529,407,63,991", + "822,152,415,735,544,488,52,711,209,424,636,975,296,943,525,906,302,314,389,400,142,470,919,83,930,902,331,860,993,654,150,537,817,625,762,282,91,601,153,808,563,490,919,878,993,454,79,886,202,747,700,914,877,152,420,24,601,801,431,861,134,208,829,250,238,755,937,980,571,940,639,664,99,154,146,958,513,277,527,521,88,961,546,695,438,720,231,6,487,747,323,291,648,339,868,310,391,829,840,66,388,616,292,196,808,902,404,251,408,863,452,249,146,722,763,65,296,832,796,509,820,829,322,195,609,949,878,952,576,179,304,705,603,642,194,396,655,319,566,491,347,640,872,459,525,719,362,336,792,447,814,675,205,795,937,194,756,475,298,805,499,808,330,697,413,410,72,177,828,684,773,487,887,57,896,932,980,305,364,815,136,789,549,784,54,607,401,580,476,203,26,202,526,72,944,787,789,508,593,509,167,345,978,371,273,393,99,849,232,545,416,439,43,480,9,834,283,643,248,609,465,742,410,216,859,765,225,722,597,492,816,616,469,622,103,179,814,590,928,63,98,96,151,824,20,253,688,15,903,432,573,789,344,3,602,875,401,296,482,437,168,269,592,603,541,475,792,333,957,447,385,813,605,792,111,634,25,440,256,939,298,362,234,708,654,112,451,252,906,354,805,32,276,15,64,198,356,834,98,201,681,683,940,713,860,197,83,501,25,622,815,537,54,605,445,513,880,694,413,542,362,627,489,491,121,920,161,953,335,361,425,68,696,928,772,794,500,335,594,494,970,111,806,619,111,640,871,351,60,876,884,477,768,35,761,686,254,570,307,872,595,998,698,449,639,84,54,309,94,263,490,819,538,486,75,387,312,516,396,176,903,475,720,515,56,77,867,641,560,209,276,58,333,23,848,728,616,654,86,678,629,514,676,727,275,461,964,74,677,74,162,132,546,437,854,737,934,530,636,507,32,504,475,475,162,527,512,940,561,742,196,383,46,647,678,665,12,34,735,867,638,362,239,906,910,753,375,536,508,434,413,339,962,718,861,498,356,337,262,457,644,423,161,952,761,391,242,277,549,545,623,264,199,718,642,278,829,22,546,328,725,615,276,343,72,438,242,462,851,614,927,264,883,796,258,254,275,825,91,516,688,451,392,57,502,62,945,923,100,575,775,628,276,700,264,273,256,892,209,487,719,806,269,970,975,99,543,92,412,51,746,278,386,816,935,458,799,331,824,139,441,243,524,773,550,561,266,200,997,656,734,607,550,798,211,602,170,905,340,135,693,714,964,445,995,928,55,737,920,44,781,701,300,960,17,605,71,359,179,115,71,10,214,834,850,262,58,638,639,888,74,603,466,662,420,64,166,964,219,17,420,804,722,525,355,666,345,830,131,317,906,293,237,191,911,302,337,298,454,815,809,503,197,548,658,215,950,314,227,396,306,97,66,982,855,940,707,590,110,312,13,284,865,647,727,665,217,79,881,383,170,195,714,637,655,32,629,763,673,384,645,204,22,937,757,136,228,944,184,515,518,164,514,46,438,342,600,303,421,262,711,78,596,12,907,947,993,245,663,740,537,848,475,571,5,469,993,201,285,417,587,562,711,873,79,121,537,635,942,441,732,861,590,662,424,318,377,514,890,918,466,435,305,279,468,875,527,782,629,169,448,556,816,183,603,990,630,466,885,440,244,151,637,633,711,228,718,320,770,253,642,311,444,127,531,419,14,397,698,140,155,388,606,248,66,879,424,344,176,789,574,646,975,422,766,349,430,150,58,710,837,95,469,973,2,486,559,926,518,814,134,195,399,45,932,230,417,753,40,244,532,989,191,125,798,0,293,840,86,659,968,162,795,844,954,443,93,233,703,169,593,410,150,623,783,600,490,24,677,786,552,899,447,609,586,968,432,117,306,712,964,179,591,343,931,46,458,444,544,176,726,268,516,535,724,245,543,741,973,58,512,949,136,602,471,829,948,493,820,34,55,968,804,384,899,504,528,14,362,244,805,984,284,413,420,50,119,656,564,361,182,379,523,889,727,764,805,726,177,275,939,486,269,953,125,914,632,119,35,352,749,230,165,986,909,106,936,299,8,812,59,980,916,125,240,909,232,116,838,223,293,296,310,864,505,135,817,807,552,820,293,990,797,344,66,500,759,311,939,557,126,761,208,278,372,583,983,766,788,458,517,490,331,892,931,982,902,543,587,11,112,82,180,199,798,103,229,996,178,66,645,422,668,957,134,333,588,745,426,946,163,502,276,168,554,781,553,737,155,515", + "625,722,280,95,462,270,415,801,209,872,585,336,231,830,488,121,53,756,774,792,262,254,733,823,45,51,622,897,781,983,443,881,535,459,324,96,430,4,58,991,245,377,885,122,633,41,821,563,852,607,498,982,762,641,343,517,119,550,881,818,390,645,402,635,813,306,588,740,94,321,882,690,692,43,268,449,697,538,63,670,737,546,196,972,351,634,839,957,800,967,902,900,94,352,587,98,59,257,243,701,550,334,64,633,578,806,540,104,732,594,767,175,518,322,235,918,272,844,170,626,50,650,660,415,624,980,290,444,341,757,781,319,771,768,864,998,517,273,192,665,684,204,26,257,238,508,180,466,167,324,867,278,681,801,935,510,774,810,968,462,740,510,110,55,687,370,180,521,907,903,291,181,656,688,880,436,729,774,830,407,232,977,633,220,536,782,70,975,56,69,639,979,598,212,532,766,847,891,35,296,541,26,845,757,658,759,643,800,822,507,646,176,651,995,22,83,70,476,864,398,778,190,50,104,800,97,811,181,171,614,299,495,940,70,645,863,558,772,216,333,649,539,179,1000,633,356,263,189,246,925,674,960,660,187,987,377,188,817,239,194,535,448,606,488,599,653,836,821,669,395,574,458,303,418,574,884,837,149,300,341,791,74,571,509,578,37,234,832,239,915,196,737,451,859,554,140,511,680,232,398,483,742,393,167,965,565,503,772,882,296,925,957,869,771,976,704,634,306,427,876,382,459,425,934,862,66,30,888,879,355,612,202,763,709,964,190,320,928,772,404,821,564,852,81,837,473,965,551,308,884,390,962,486,923,463,220,897,430,754,755,852,430,155,883,269,137,287,777,960,160,620,378,896,960,894,228,396,796,531,392,53,837,966,140,912,978,687,524,736,37,521,960,345,711,17,652,141,61,482,501,893,959,913,78,451,628,353,850,308,627,650,326,889,555,189,822,454,56,196,207,820,109,880,75,243,666,547,313,693,678,12,33,614,351,541,977,890,521,819,924,537,738,135,921,548,733,189,793,120,783,275,867,890,426,508,534,569,16,985,252,789,839,757,546,996,703,294,835,982,870,271,751,797,707,958,645,866,770,214,604,21,478,781,691,21,846,273,120,903,964,509,878,386,884,891,268,271,728,917,922,780,167,442,938,756,838,670,628,167,555,40,411,894,169,651,6,156,235,953,341,208,919,412,344,236,378,828,355,47,79,633,305,924,738,615,934,737,794,400,965,351,546,426,128,968,656,549,817,62,203,297,888,460,602,23,263,890,71,137,408,697,670,111,995,746,606,185,969,940,787,714,54,43,216,191,840,902,128,971,478,279,768,176,671,834,818,824,904,448,874,414,61,168,805,558,661,189,199,321,369,998,909,189,627,494,873,118,416,473,437,74,255,741,813,446,69,354,536,947,908,380,797,721,332,925,106,52,439,577,906,878,285,490,488,639,997,636,322,68,764,570,550,41,994,666,731,534,6,783,13,36,48,534,280,995,25,157,666,145,825,883,520,239,407,793,913,386,159,59,320,132,428,461,624,567,572,57,436,235,684,122,808,811,268,756,554,202,504,937,831,571,90,855,459,506,820,78,776,554,590,797,242,859,521,588,723,488,262,221,180,164,819,765,301,96,58,203,895,139,789,365,914,102,848,577,250,47,574,645,330,662,490,157,429,647,413,692,330,804,719,710,63,958,52,544,826,123,20,745,247,734,786,309,476,546,895,766,151,293,511,865,479,443,557,685,511,236,63,873,143,758,905,359,634,97,823,239,269,710,507,344,152,389,652,90,389,917,915,825,13,688,665,802,661,574,171,162,405,288,61,181,230,675,777,514,293,0,458,595,844,942,978,740,595,266,459,678,681,26,708,210,575,403,525,593,436,703,90,659,589,937,460,24,713,414,34,656,858,822,851,474,710,276,45,921,680,888,569,59,446,917,858,763,405,459,295,889,280,257,637,661,904,391,77,86,494,958,64,710,517,257,567,850,454,48,256,799,862,699,774,611,708,210,564,493,751,146,718,276,365,665,834,459,194,914,891,317,613,289,689,79,246,834,27,979,751,291,534,260,258,876,253,495,789,222,983,885,888,29,190,917,184,264,35,774,348,471,298,573,513,109,452,41,737,622,874,60,489,400,508,600,937,598,234,145,574,712,98,510,873,600,143,244,823,650,18,613,451,723,975,647,929,913,708,485,265,407,588,376,706,254,402,417,539,286,984,617,134,470,511,29,961,867,454,332,611,508,684,933,647,538,967,643,846,491,769,870,774,732,887", + "147,948,83,549,593,187,810,425,175,918,570,147,919,587,357,716,385,116,744,899,782,261,880,29,373,541,241,275,536,489,83,956,913,301,819,605,452,407,674,13,930,217,56,10,764,435,455,929,783,349,946,548,220,521,163,250,977,870,830,688,748,380,255,670,755,788,685,253,2,827,426,705,752,148,893,584,562,521,497,669,489,189,61,745,835,507,200,724,590,65,322,803,530,548,670,689,612,275,592,515,495,141,621,600,555,577,71,946,804,760,106,890,409,68,809,649,948,410,785,463,263,881,640,340,24,814,522,327,971,338,757,608,197,621,928,673,851,185,581,78,378,910,120,501,285,690,283,235,649,518,942,394,608,992,836,926,975,648,314,526,875,750,164,290,949,833,848,801,842,70,285,844,564,261,122,873,142,650,309,423,477,291,715,974,203,642,896,458,275,585,954,943,224,735,539,745,247,298,416,330,907,976,357,118,376,7,743,60,611,887,745,635,69,758,987,191,701,815,492,300,360,858,617,568,390,847,245,637,658,376,971,175,27,985,44,760,655,962,669,598,433,702,884,144,361,671,793,427,258,852,708,15,120,371,153,893,932,367,349,31,834,871,630,811,109,930,974,233,329,389,353,443,66,885,588,192,147,895,2,939,954,130,390,166,790,530,951,484,323,645,76,62,338,362,490,261,562,906,521,455,177,358,229,978,497,352,528,670,459,160,925,442,292,492,201,9,996,351,465,200,742,394,632,549,319,438,190,168,646,579,20,314,567,913,819,69,147,989,369,284,857,895,719,885,901,435,48,912,159,546,645,545,964,249,908,469,190,385,207,992,245,262,882,93,914,953,115,214,597,511,667,315,637,925,829,592,3,892,523,950,411,166,90,381,237,166,352,818,902,279,837,656,576,590,612,450,422,909,239,431,867,743,138,796,466,317,310,178,787,125,950,560,73,353,244,794,907,269,877,208,157,835,392,963,721,230,684,297,548,930,193,458,270,755,791,106,933,662,405,648,596,972,354,482,770,191,863,672,464,250,150,752,132,376,762,283,385,547,788,220,455,532,580,903,797,421,41,856,291,591,349,223,644,785,126,472,231,52,624,317,723,161,573,517,558,465,498,624,222,80,537,960,958,46,796,465,305,391,804,159,720,127,571,835,361,966,404,368,218,636,586,339,955,52,448,109,104,902,300,115,395,861,235,918,1000,925,897,771,330,909,221,660,484,542,895,7,437,515,114,647,586,364,309,953,232,189,142,78,479,883,178,640,874,925,230,496,730,825,913,180,945,537,581,219,798,31,178,156,59,626,162,439,270,124,135,222,529,848,752,859,581,643,570,526,418,387,22,608,926,882,351,210,867,469,677,940,300,701,730,34,944,283,906,289,452,465,324,452,182,414,860,965,286,625,946,61,563,806,763,607,627,363,367,137,646,195,381,945,736,980,97,497,569,813,846,578,278,800,166,775,370,684,877,25,911,334,50,748,982,253,232,957,215,595,168,149,34,410,384,656,450,277,44,267,451,607,715,699,85,582,819,109,382,245,177,182,689,214,959,142,123,139,496,617,270,260,656,557,831,583,583,165,468,767,882,334,606,530,61,152,926,597,505,822,137,905,801,58,714,643,592,841,550,19,476,298,107,824,78,818,54,783,491,641,917,566,783,67,247,575,662,475,271,238,418,684,296,734,272,147,969,590,282,662,941,407,387,917,9,653,984,652,377,213,330,120,692,202,84,78,9,513,421,576,721,91,534,88,778,263,554,635,609,737,278,175,582,18,975,607,60,98,480,664,933,945,500,797,219,710,492,910,281,644,521,849,882,892,298,677,909,588,661,776,326,840,458,0,481,535,565,511,69,3,146,978,488,883,138,131,717,363,219,214,515,873,627,76,490,999,209,754,273,257,17,741,739,599,134,794,96,374,858,107,391,877,236,522,348,374,181,73,624,814,494,211,15,552,31,152,644,106,275,853,723,995,556,323,70,590,295,461,330,721,604,131,300,275,410,383,954,127,46,799,402,167,893,362,922,122,290,370,103,714,6,57,403,188,924,717,44,261,751,967,23,279,413,615,504,421,254,111,651,469,59,473,855,416,616,673,900,988,628,670,267,251,283,428,318,647,763,951,272,769,693,604,622,751,792,39,103,487,966,813,807,212,868,166,399,696,799,724,517,550,869,988,45,556,63,770,686,618,787,159,630,562,930,724,156,822,262,490,468,985,872,220,310,300,197,955,450,290,226,281,790,798,793,551,651,916,893,29,679,752,185,682,432,847,292,891", + "210,318,405,702,295,147,85,70,10,643,294,654,943,55,280,168,191,121,208,372,112,507,21,744,16,100,155,370,759,168,749,980,910,533,845,440,651,468,97,110,169,76,231,297,96,898,624,472,624,867,295,934,170,958,67,469,286,816,380,914,430,550,137,135,297,249,331,290,523,15,24,785,773,619,877,478,109,369,624,106,73,767,123,627,908,813,578,234,628,575,774,770,19,567,779,794,655,995,92,767,844,431,461,443,615,263,927,386,225,509,693,488,555,810,420,866,385,177,947,254,185,402,487,406,956,563,224,407,534,241,432,4,104,94,564,663,451,35,491,217,292,454,879,497,41,72,875,346,772,710,800,157,474,840,398,804,682,57,347,236,854,833,578,307,647,648,203,673,970,32,737,445,185,984,306,934,302,410,17,477,761,710,880,758,397,431,761,64,328,267,630,586,969,878,814,648,546,181,410,289,879,815,113,747,424,28,707,51,309,506,580,381,273,262,488,433,965,256,784,913,842,548,404,643,16,554,692,110,289,950,81,136,894,182,837,533,692,479,921,396,401,109,315,653,767,46,66,96,430,441,361,94,358,446,701,322,125,773,805,312,1,275,566,314,456,136,892,584,577,979,492,469,857,930,183,117,132,750,255,872,551,309,697,169,136,350,258,732,577,207,419,637,243,365,786,811,405,766,760,153,160,504,487,714,244,889,752,907,266,302,86,800,300,394,670,433,741,541,621,474,763,822,540,354,486,128,751,356,872,559,561,239,609,834,739,338,325,805,344,610,482,231,135,763,218,272,94,160,491,110,94,429,846,553,52,763,570,374,719,987,878,709,752,192,682,650,703,571,811,219,158,542,820,929,634,301,29,558,637,647,664,216,572,778,347,239,564,932,317,733,296,94,547,277,18,53,468,567,854,980,457,166,246,826,777,527,665,915,997,236,334,415,216,60,659,743,814,512,650,500,889,999,752,280,477,689,560,76,596,365,983,533,847,100,97,230,732,178,527,935,347,784,286,305,579,273,139,529,795,712,281,858,141,107,900,58,733,986,700,974,891,8,877,28,447,788,303,573,698,477,289,744,805,872,91,627,488,256,625,317,306,736,542,244,259,294,401,82,48,468,452,172,24,248,790,266,59,257,433,93,568,365,26,597,498,475,293,664,923,364,353,461,191,513,69,588,864,895,412,100,202,535,374,327,631,319,786,978,963,39,775,564,214,910,831,218,760,27,502,419,828,681,297,493,715,289,339,958,708,932,386,643,242,741,204,184,173,502,866,988,478,608,849,873,375,235,815,594,6,244,469,229,508,407,170,955,89,169,946,764,564,303,535,155,372,660,771,221,978,203,902,24,672,777,521,496,514,313,652,493,956,914,273,868,43,348,578,618,831,62,394,673,577,254,258,703,748,931,256,764,728,29,367,614,191,394,706,25,935,946,490,281,881,884,605,323,442,346,315,738,307,877,224,868,537,4,899,104,596,494,254,91,957,868,183,229,538,119,182,638,86,54,184,119,151,698,680,953,480,880,824,147,470,383,164,80,500,197,119,495,640,159,84,657,510,720,752,314,187,967,166,796,842,338,869,208,872,8,306,302,77,842,436,339,972,465,224,367,991,300,397,986,825,288,528,220,971,709,405,170,697,748,308,480,557,441,536,622,946,113,264,549,642,371,798,362,817,42,448,132,173,650,714,200,404,548,675,228,772,19,390,196,767,433,114,442,15,866,393,259,926,240,519,32,620,503,463,790,989,186,385,435,484,570,298,855,947,154,13,600,154,54,257,119,675,88,446,236,420,416,312,936,810,34,930,649,460,225,359,829,354,876,59,406,574,86,595,481,0,679,679,315,281,545,548,229,377,486,827,78,282,716,510,886,41,308,521,986,200,878,67,46,91,310,724,527,458,88,371,57,239,695,735,212,897,486,241,693,838,708,230,987,193,357,584,971,476,834,449,894,797,73,255,401,681,251,849,447,236,683,544,783,194,386,746,173,566,41,574,243,230,622,314,146,908,367,688,3,825,287,662,295,996,484,190,791,380,532,427,65,45,467,805,349,221,143,404,328,630,270,238,986,213,393,12,486,244,830,340,646,378,363,485,489,111,137,594,23,410,723,458,586,169,107,649,645,959,123,505,258,961,133,542,828,776,609,56,143,589,611,641,543,637,68,481,154,287,370,914,565,719,942,747,186,220,296,593,533,177,918,873,393,872,875,435,86,70,124,531,24,905,81,660,612,476,632,887,106,645,351,698,528,527,535,218,991,904,143,166,81", + "875,60,104,424,507,263,178,50,997,808,174,895,860,334,137,708,718,779,113,925,316,265,483,68,645,147,105,990,538,602,424,380,801,612,435,597,708,304,187,740,230,385,693,62,478,904,106,646,543,59,780,52,222,491,285,846,211,767,987,898,830,7,284,479,363,888,926,216,284,95,510,354,276,200,40,550,707,691,423,212,766,161,908,147,58,270,686,62,723,376,838,349,118,151,99,101,139,30,293,361,347,484,792,729,538,68,986,538,431,723,947,232,287,349,941,205,597,564,666,444,433,595,628,772,526,888,642,669,876,494,442,891,769,166,496,935,205,469,158,23,162,154,752,255,634,891,286,157,380,156,479,262,469,356,688,417,553,442,566,7,186,339,664,854,192,772,926,273,491,79,660,883,215,438,353,811,123,370,398,74,977,947,214,60,144,281,661,99,12,316,53,9,812,610,999,190,964,369,182,754,247,677,111,48,424,129,158,991,519,681,793,184,646,524,264,765,323,290,757,866,983,639,924,123,707,263,554,192,701,833,74,188,767,388,951,192,407,863,127,871,734,473,390,621,748,960,261,354,786,805,746,694,567,544,612,347,827,164,920,499,886,858,135,398,164,175,531,862,618,330,408,319,783,136,76,646,942,191,959,323,480,975,197,90,954,29,97,51,661,36,961,929,902,843,589,88,579,655,425,694,315,793,525,47,962,322,513,401,919,221,447,445,979,348,382,575,759,877,380,342,194,530,158,108,682,709,129,113,304,936,6,868,162,602,353,649,877,669,300,625,270,44,346,48,697,156,700,912,56,55,861,610,272,743,166,120,120,250,343,174,592,312,959,93,29,486,845,53,55,767,197,144,580,288,173,489,781,335,150,137,266,688,353,545,392,62,53,949,786,846,302,759,342,25,689,860,571,635,855,671,924,769,479,821,229,590,578,783,341,761,163,218,550,714,236,920,125,747,317,950,672,406,702,565,690,685,176,450,330,647,502,962,997,929,392,365,907,308,959,42,269,360,264,781,283,794,797,516,568,430,235,274,726,58,330,171,541,81,804,167,677,463,838,526,749,68,187,285,678,843,529,424,386,198,30,897,280,340,944,424,326,569,141,369,337,645,925,892,815,74,149,604,263,819,209,596,965,737,106,829,78,561,332,325,886,986,7,683,299,29,668,223,673,190,689,551,601,183,436,971,600,339,651,763,537,582,593,767,495,814,497,856,457,581,846,956,636,622,177,30,992,976,231,462,65,614,350,637,541,239,442,186,548,204,805,364,976,387,866,949,587,80,39,254,121,243,515,28,191,694,314,576,311,378,103,714,621,28,784,888,370,31,357,276,853,964,261,426,312,576,120,892,14,837,250,294,116,330,909,627,49,407,154,206,497,887,497,452,558,18,434,908,681,239,880,6,273,541,534,977,943,472,298,864,219,452,773,449,857,501,631,29,952,185,632,165,12,720,842,257,59,983,340,602,42,114,29,301,911,220,266,407,601,66,204,361,835,326,384,927,545,857,26,431,178,273,305,828,104,270,12,574,554,346,526,306,631,991,318,595,729,69,819,154,830,387,155,87,49,936,326,580,143,880,342,608,711,708,153,601,34,91,161,468,779,261,877,310,691,990,349,439,293,418,670,431,809,294,335,377,235,939,573,874,254,364,450,98,102,70,605,656,996,453,918,708,989,174,919,491,885,332,861,649,20,394,279,375,221,712,811,517,705,586,342,680,480,805,892,924,759,203,110,640,477,200,697,395,316,663,503,948,864,737,391,210,969,798,463,314,727,940,449,242,714,405,912,949,287,712,650,999,602,632,802,201,218,657,645,572,456,161,86,413,37,659,844,535,679,0,771,453,693,31,182,762,56,473,421,81,684,840,365,392,107,787,369,919,966,932,291,515,827,502,37,813,171,370,369,686,159,866,24,948,5,462,286,695,94,785,306,421,450,287,663,875,465,846,356,249,584,628,595,711,469,984,20,999,39,108,583,393,810,230,84,930,282,557,371,13,66,681,981,659,589,880,992,479,540,796,496,675,951,72,961,635,525,33,599,2,562,255,968,760,169,291,38,35,705,968,121,795,588,222,594,207,686,437,43,287,944,764,200,658,57,382,173,92,44,590,167,957,102,14,291,87,329,810,655,129,953,782,568,131,288,234,253,952,963,192,874,960,367,187,275,262,851,960,130,622,813,545,15,628,714,458,312,804,864,227,64,952,187,103,891,548,107,267,285,817,290,939,503,808,817,455,751,537,480,258,55,632,584,306,308,207,706,118,848,104", + "778,973,197,479,389,664,937,711,640,577,692,748,999,762,829,933,833,768,196,721,36,475,187,444,934,307,789,775,994,462,905,845,296,695,483,961,274,399,648,440,649,559,565,255,980,233,901,866,261,665,378,300,446,669,868,557,694,749,234,937,941,348,638,846,18,83,418,882,207,638,536,211,317,683,747,872,11,267,150,58,199,164,346,3,189,457,141,139,302,695,539,1000,632,288,747,483,552,387,122,34,2,166,872,26,934,649,506,65,788,150,89,881,433,717,911,70,336,336,645,272,277,844,791,751,589,538,200,313,72,342,134,951,786,978,570,504,312,382,995,243,882,430,505,803,33,229,591,390,373,475,427,389,354,517,709,72,610,838,673,720,189,331,562,152,610,613,382,939,273,972,502,695,286,525,149,958,896,794,523,262,998,310,306,390,326,840,994,780,417,787,295,51,646,154,127,471,974,714,756,124,86,79,860,570,721,555,604,271,865,57,410,381,336,372,612,255,661,580,517,845,580,217,770,79,112,874,190,696,555,475,663,170,489,713,319,869,70,10,555,717,945,442,271,463,108,345,883,53,957,654,468,927,304,255,813,122,236,603,929,106,303,931,835,61,119,225,484,37,274,19,518,706,886,251,750,376,335,475,504,202,287,71,822,610,759,862,613,855,510,634,758,191,712,486,750,561,876,808,269,379,20,75,629,243,228,219,727,452,230,191,747,86,53,457,469,747,130,229,614,691,574,507,400,269,44,149,159,908,528,931,214,246,39,531,659,975,567,854,18,441,151,315,378,772,150,506,963,581,898,575,565,555,636,96,550,165,153,112,110,152,397,605,975,939,854,473,734,856,291,395,421,403,394,788,587,369,428,103,44,978,553,243,497,264,933,883,241,91,176,98,715,157,526,174,80,654,597,655,763,199,618,956,997,667,732,753,64,407,820,430,442,739,285,861,182,719,719,587,546,865,116,677,667,754,94,169,342,116,711,116,579,684,102,448,408,578,968,697,711,969,721,308,890,449,197,71,484,194,977,242,391,326,54,27,561,438,899,596,738,238,876,995,224,545,259,599,252,511,607,418,825,426,577,299,348,433,603,571,780,272,516,413,495,210,912,346,623,911,529,286,397,601,931,639,771,189,141,263,701,717,321,291,538,901,522,77,756,927,480,201,251,729,199,337,498,485,408,811,621,840,827,969,715,277,497,641,217,934,12,410,329,821,742,289,402,624,378,306,768,229,736,543,188,6,51,223,346,144,806,559,896,681,873,356,801,651,5,745,299,603,183,993,719,715,304,630,977,491,445,185,606,843,638,628,934,869,360,607,913,450,222,544,19,560,162,625,895,976,829,84,870,946,449,96,392,496,655,944,921,383,588,510,503,737,627,672,999,203,452,435,217,133,412,59,422,268,427,858,716,938,127,114,197,868,646,478,677,127,553,49,929,232,971,893,550,920,976,670,815,849,958,609,276,46,787,707,512,887,106,391,194,230,987,254,436,263,310,358,216,363,363,636,593,916,699,887,939,497,941,786,621,547,216,627,91,954,124,349,500,819,786,133,758,238,615,78,4,224,283,860,440,470,873,270,78,718,178,307,459,904,108,526,433,773,202,669,557,679,293,91,338,819,173,561,816,444,562,143,384,981,810,142,810,12,74,450,463,815,107,252,988,317,915,684,985,836,771,313,738,622,72,836,973,853,434,509,90,70,664,469,117,594,533,232,592,793,76,976,518,291,42,342,587,353,962,115,776,949,792,303,235,526,107,898,296,145,138,271,557,45,891,825,731,171,736,33,345,428,748,450,573,837,938,655,241,150,473,442,107,936,752,26,698,691,923,968,942,565,679,771,0,184,922,612,389,439,682,140,666,488,55,756,907,23,832,580,272,293,579,333,860,50,694,699,158,697,922,136,324,762,672,788,752,363,790,293,706,272,141,233,661,328,710,509,725,182,101,616,822,950,754,574,525,570,259,956,228,223,210,97,478,442,845,952,298,294,926,825,238,655,866,237,4,630,670,109,993,497,60,755,145,761,497,40,856,440,536,206,553,60,941,843,23,675,57,617,835,187,411,265,912,598,167,202,681,500,599,887,645,659,196,442,944,401,487,800,675,719,434,491,542,665,243,607,842,654,564,427,653,588,614,136,886,339,46,203,876,329,700,770,260,474,784,438,453,50,701,817,92,248,430,653,278,999,94,354,409,292,33,555,358,53,86,797,582,21,770,928,515,866,203,6,249,506,534,397,329,369,164,719,833,419,218,647,548,516,952,293,350,50", + "175,239,213,674,530,695,760,828,328,723,54,3,258,122,280,669,537,898,357,496,148,246,653,575,330,10,319,824,249,732,532,988,166,962,302,959,821,650,646,991,381,789,974,747,92,121,432,15,333,491,898,277,318,351,402,672,765,381,955,908,768,277,816,724,37,369,57,566,392,77,530,63,629,944,454,212,547,999,156,204,532,571,798,362,129,788,80,150,118,836,131,477,931,507,115,29,384,552,674,232,667,292,786,46,684,312,789,471,835,986,399,724,376,44,88,892,639,546,833,323,616,64,633,525,85,57,230,361,517,349,296,853,262,416,864,41,504,16,776,318,202,474,807,843,700,231,378,493,954,616,153,170,202,724,723,229,52,922,915,956,353,580,352,641,357,207,671,144,403,756,697,826,431,423,695,116,604,500,601,790,323,381,820,553,64,3,894,575,788,152,998,717,394,718,355,887,565,410,387,77,554,185,956,299,484,41,863,628,409,14,458,751,377,442,910,329,713,116,21,777,357,250,634,237,908,846,191,162,344,306,446,121,15,319,937,253,580,729,399,50,229,145,491,367,991,641,89,890,368,599,817,599,875,252,658,75,927,845,433,200,655,511,393,657,202,282,586,299,788,709,914,727,232,72,610,809,206,513,818,369,973,559,532,426,199,115,324,621,382,50,471,60,796,135,791,802,148,228,814,76,725,924,891,521,337,190,315,268,236,597,503,42,379,613,352,782,436,138,237,575,393,322,52,230,155,578,611,606,920,130,156,818,401,290,3,763,604,21,668,558,547,629,342,658,535,626,152,512,653,294,793,958,177,835,736,375,698,322,926,154,166,300,647,741,437,50,984,140,615,636,437,271,748,634,191,223,476,891,43,286,835,452,173,876,795,72,956,16,671,896,185,822,679,306,232,962,234,506,978,723,93,270,881,67,298,411,981,548,232,791,866,705,26,552,127,959,972,552,855,977,193,270,1000,690,585,811,899,423,120,99,598,690,516,176,809,367,631,656,421,242,895,95,476,697,544,849,276,992,30,648,261,485,815,581,436,265,709,154,508,420,271,870,847,348,572,195,204,797,147,933,248,484,651,411,317,270,276,984,961,736,495,494,908,604,635,228,603,627,316,325,424,416,501,121,538,85,548,522,738,889,118,453,111,412,291,656,570,297,687,733,478,264,740,911,800,205,14,62,704,159,958,370,537,501,879,376,216,431,72,207,593,514,196,575,813,328,76,32,995,809,432,795,18,602,96,416,818,479,784,63,742,596,532,493,435,203,82,906,971,907,235,566,370,886,78,425,856,110,300,476,499,557,137,437,505,742,49,623,236,646,602,938,938,703,836,686,54,158,678,23,209,378,476,206,391,493,967,287,28,553,282,62,694,762,501,27,907,750,813,763,847,530,188,455,830,156,32,947,415,953,659,537,794,611,354,603,296,514,104,600,586,774,656,929,892,94,406,423,863,325,735,633,858,340,433,174,143,595,519,318,634,277,938,72,361,770,339,330,602,40,96,564,912,583,763,113,724,910,406,149,122,899,877,382,514,920,435,843,685,387,489,992,4,908,439,431,29,787,368,26,82,570,212,974,623,607,701,29,688,769,695,12,553,149,390,977,123,225,430,893,151,484,359,554,626,402,343,164,457,444,855,895,581,954,441,984,119,932,351,779,693,217,389,789,187,149,930,373,899,176,530,586,86,865,953,612,622,177,389,271,835,500,522,408,287,911,146,226,480,179,375,894,570,30,28,686,879,702,575,727,284,780,443,124,349,43,407,966,974,722,229,891,789,621,365,544,50,978,750,845,458,276,177,528,884,773,304,903,976,194,336,683,918,957,675,162,978,511,315,453,184,0,542,835,918,528,113,448,163,116,710,825,428,606,714,566,619,886,454,188,524,565,908,873,752,498,733,895,919,844,453,370,932,897,99,761,581,2,302,945,432,411,988,139,845,241,25,105,909,279,767,577,793,870,501,25,747,962,139,884,190,610,160,475,186,443,142,313,986,575,614,571,707,910,480,262,171,215,999,142,525,522,214,775,193,304,662,466,913,942,565,549,149,624,609,526,134,590,916,421,825,242,453,578,343,817,762,897,483,376,390,168,197,475,849,654,475,568,199,503,234,567,470,504,442,899,528,843,686,93,11,901,42,318,969,407,458,475,51,313,505,873,973,437,755,771,967,529,221,686,366,133,62,334,654,233,980,419,595,590,544,102,449,867,544,401,429,348,107,619,419,869,992,306,134,492,784,426,35,600,530,56,89,619,133,869,185,48,764,325", + "388,488,852,86,650,592,98,727,917,31,25,638,119,419,511,338,936,821,404,820,319,879,38,442,796,494,144,239,653,656,507,406,188,34,754,625,780,889,856,448,796,673,852,425,493,130,793,355,215,544,23,135,940,833,896,428,346,250,33,473,590,247,399,732,142,662,760,600,545,764,445,870,483,394,362,245,272,330,144,829,249,463,89,422,559,734,996,973,865,669,408,48,921,443,870,473,941,991,651,568,631,417,67,938,129,991,832,621,225,974,161,405,644,957,925,557,40,385,277,580,651,2,133,892,554,99,420,954,84,476,320,577,259,501,176,308,920,990,392,256,549,58,486,266,63,359,98,607,38,604,727,227,770,250,931,893,153,900,335,924,359,493,570,150,873,279,806,880,950,761,899,30,36,807,834,147,355,369,495,860,444,74,304,286,421,937,585,702,14,784,15,241,114,871,326,919,621,243,968,680,995,578,395,780,174,770,783,222,657,215,613,573,244,395,800,937,77,139,144,756,255,275,686,965,400,41,666,104,433,970,383,41,543,402,228,466,505,385,365,804,673,266,772,614,274,589,827,508,991,66,120,319,627,226,754,337,989,350,57,430,335,329,795,189,560,813,204,389,359,947,300,328,338,174,208,496,228,709,22,580,488,173,891,815,34,735,602,630,503,631,669,385,140,899,650,350,534,815,494,261,565,816,622,488,909,228,362,141,841,629,161,353,844,122,379,921,548,935,855,258,688,278,21,371,138,5,587,426,232,547,5,98,944,959,231,336,29,170,538,274,236,20,830,542,547,193,661,667,681,686,297,237,504,887,186,373,717,755,478,277,168,734,40,433,96,934,708,626,480,477,563,167,575,573,875,801,782,259,171,221,380,20,38,223,392,115,624,601,812,8,448,415,776,956,158,372,219,124,979,785,248,620,497,815,269,551,335,560,830,558,36,357,71,111,902,172,876,66,550,168,663,271,308,302,6,15,715,406,720,478,955,965,551,711,911,934,650,498,176,893,785,541,443,606,329,518,218,579,472,439,152,110,200,568,743,498,514,455,343,850,708,278,649,310,778,629,696,435,128,909,511,245,31,584,523,830,447,700,865,112,801,586,316,117,886,402,98,848,292,436,843,279,311,816,501,758,118,438,833,8,699,672,516,109,208,742,89,523,711,129,5,424,356,290,189,420,55,581,268,322,505,15,991,730,11,639,205,873,42,967,747,128,92,365,605,19,21,556,753,264,282,98,898,290,371,207,566,693,164,656,269,669,949,642,528,823,645,102,71,166,186,51,604,857,48,872,934,267,388,259,934,26,533,273,858,520,588,371,3,861,655,108,758,605,348,281,552,651,377,861,136,620,468,387,462,207,672,380,144,859,468,170,562,778,905,904,974,441,357,816,26,67,35,901,348,3,373,486,373,169,582,368,773,720,150,808,649,320,212,415,727,788,416,370,795,566,421,248,656,658,231,611,585,771,396,738,128,114,365,803,532,933,611,582,532,556,715,436,279,710,763,653,754,977,329,613,804,784,841,955,213,709,98,377,833,607,411,71,627,894,664,839,258,488,2,39,151,908,735,725,204,169,2,757,316,578,115,821,306,875,346,124,420,912,686,895,149,131,888,635,462,677,918,636,979,471,397,697,742,500,261,559,503,432,221,474,591,429,533,806,522,657,676,915,840,971,7,184,47,971,722,391,711,742,304,339,247,29,331,377,55,83,76,182,9,322,738,973,301,720,746,428,706,382,504,601,620,51,427,18,423,677,327,249,946,773,513,92,897,737,582,182,721,878,904,418,692,320,801,824,993,671,4,423,416,761,156,663,744,581,677,653,937,278,863,795,740,69,281,693,922,542,0,891,601,76,780,307,299,627,584,703,211,108,817,615,932,236,927,444,716,703,207,705,877,181,405,248,772,855,995,746,361,712,450,54,826,885,877,464,576,645,987,565,585,89,262,895,100,41,320,696,57,43,928,573,517,627,360,76,970,240,404,499,778,695,886,26,531,262,487,971,240,971,827,435,998,755,785,404,631,599,857,120,79,293,939,87,24,267,960,863,756,393,422,760,166,567,131,745,166,948,49,708,230,183,103,948,848,657,641,409,910,28,917,494,412,760,744,186,820,774,572,112,567,675,326,228,686,317,432,837,376,116,274,895,787,310,403,7,647,511,401,187,909,851,854,783,185,968,207,726,83,723,873,213,903,10,481,658,342,280,168,101,396,378,786,889,370,55,452,803,187,681,553,312,236,971,252,479,842,361,963,65,158,230,550,965,994,650", + "671,813,907,978,938,990,193,395,698,871,298,648,88,574,436,236,56,443,530,173,266,306,33,25,250,651,690,775,353,401,174,494,178,566,82,706,673,228,555,584,56,377,603,824,262,333,302,568,871,428,128,737,956,353,506,77,819,444,825,571,118,384,256,75,207,79,825,21,961,443,875,217,338,418,366,615,401,340,435,23,855,572,854,401,704,187,615,975,37,602,653,754,908,996,169,291,742,551,697,35,379,964,6,688,294,752,795,947,831,952,550,352,374,268,630,661,308,5,7,26,159,623,965,938,442,592,658,706,272,584,501,516,947,738,776,625,498,931,762,346,554,144,713,496,439,305,49,561,635,905,136,505,667,704,508,635,455,215,293,880,182,958,707,946,87,144,855,515,394,664,781,217,307,773,541,565,853,841,395,302,899,202,633,341,15,529,325,250,123,891,355,570,368,915,979,585,331,801,166,321,859,478,878,266,764,861,583,701,786,848,562,493,825,902,922,574,49,150,11,552,852,305,957,370,698,308,907,430,207,429,970,692,393,990,384,88,314,286,313,693,356,2,889,808,327,397,454,359,933,174,216,621,825,230,217,892,458,113,113,97,439,298,44,919,47,933,546,968,838,487,550,216,676,354,385,934,705,409,112,52,394,535,671,89,300,955,770,844,488,33,461,814,440,749,699,841,944,186,263,701,285,173,155,441,132,851,882,643,259,796,551,14,996,422,276,529,95,794,25,933,854,507,951,123,605,456,296,607,474,812,710,473,988,149,46,162,189,209,145,637,669,402,641,736,258,863,874,672,750,380,719,987,463,644,124,231,517,245,137,42,431,677,693,370,429,270,26,153,68,133,897,187,391,355,416,637,682,400,479,423,845,751,661,170,925,682,786,223,569,765,939,657,770,606,735,48,792,995,389,905,923,319,21,301,864,305,981,157,214,66,522,574,777,231,40,840,610,242,456,98,38,636,657,192,543,869,93,137,741,673,397,96,862,727,934,444,418,218,169,347,914,747,850,539,271,569,80,476,271,798,925,839,602,666,864,21,507,307,737,768,742,94,391,273,544,359,137,710,304,732,587,332,303,925,694,402,122,473,12,40,523,902,528,377,79,316,319,431,321,867,776,549,79,3,767,396,102,298,961,849,580,290,864,105,453,144,755,474,729,108,367,225,853,179,353,364,150,557,58,729,952,932,536,968,121,547,833,913,822,352,528,850,789,434,453,77,506,946,445,281,965,366,979,873,335,899,115,365,348,799,33,754,607,210,884,595,722,423,724,797,247,163,299,359,707,68,796,370,254,547,842,910,836,80,778,70,322,490,588,648,548,201,975,361,41,743,641,963,34,281,568,611,753,546,328,16,338,427,522,116,946,705,331,944,767,236,387,833,636,814,119,795,382,867,722,661,596,313,414,881,61,459,36,927,628,671,753,164,276,864,386,262,922,334,9,917,664,783,747,884,700,303,193,75,545,510,239,906,206,639,131,723,229,949,181,512,229,277,633,74,941,610,743,125,744,886,318,768,733,576,801,168,883,515,983,729,160,250,484,795,718,639,912,719,742,358,850,444,752,384,984,819,317,819,131,263,855,610,316,343,758,417,161,104,942,88,564,700,589,248,437,302,94,770,548,12,278,176,698,903,964,594,799,629,219,850,832,191,875,858,679,379,609,59,130,998,606,961,274,888,367,450,452,930,611,992,44,738,211,285,399,79,82,437,841,380,728,377,798,679,160,467,893,198,676,608,614,651,101,918,447,890,4,579,134,436,463,502,282,114,769,518,837,733,191,73,771,977,440,896,411,573,708,117,558,647,794,974,178,281,773,154,796,963,663,844,595,3,545,31,612,835,891,0,180,713,60,292,861,211,875,367,83,467,224,585,974,953,817,55,655,978,547,436,559,72,881,602,166,588,885,997,698,921,438,756,982,719,160,125,214,143,535,338,50,754,207,920,63,21,567,942,818,686,242,609,316,569,178,145,226,165,61,35,381,680,732,272,361,702,68,111,881,450,655,664,119,192,435,592,828,665,325,952,991,98,158,872,660,441,718,507,659,882,29,466,633,641,894,898,544,314,658,880,277,601,151,710,676,788,985,486,357,158,831,340,708,821,702,565,857,495,970,372,969,789,201,429,876,493,436,265,630,901,840,447,292,272,363,119,2,272,628,953,124,451,838,478,127,245,675,693,732,483,553,792,946,259,211,227,788,906,613,902,220,411,966,198,962,721,112,989,719,974,693,288,38,245,205,670,381,858,988,993,485,899,281,977,470,806", + "762,322,357,189,349,950,574,233,909,427,54,498,845,719,749,216,501,653,120,352,461,104,338,706,306,825,217,726,485,204,679,170,237,205,989,963,499,325,669,173,814,957,87,611,128,713,933,42,782,813,946,78,662,979,414,288,346,675,88,59,477,375,314,11,554,710,471,953,353,164,407,461,232,201,249,279,410,94,820,589,314,990,947,281,149,957,38,207,200,682,114,527,16,748,505,370,380,983,837,615,901,460,302,288,490,856,923,232,795,192,426,260,311,763,882,865,138,454,676,213,222,68,811,289,62,412,570,429,824,156,983,267,785,162,143,158,416,192,343,518,145,572,386,22,413,716,557,796,772,502,132,794,348,373,115,783,36,392,907,758,704,815,170,460,293,930,536,737,263,793,736,486,348,390,757,909,706,632,284,805,657,944,311,361,196,256,149,579,958,435,362,66,521,996,646,713,936,105,483,624,803,9,77,128,815,596,248,234,508,434,196,338,321,421,299,874,107,343,171,66,39,176,460,232,312,785,538,111,469,650,744,400,803,307,395,726,148,689,396,451,631,930,282,299,834,865,679,607,927,372,327,4,291,932,752,28,216,112,889,484,516,739,640,481,289,966,523,766,194,404,722,862,438,952,892,32,738,260,110,254,727,65,504,336,671,905,958,108,45,984,606,284,914,692,907,683,220,834,448,884,487,805,38,577,798,744,119,623,323,120,802,837,823,101,376,936,230,788,852,291,307,936,18,430,444,72,842,353,897,223,145,815,524,121,40,47,957,927,549,504,959,316,36,90,30,112,54,362,762,140,558,936,495,304,672,808,746,364,527,899,115,93,946,23,568,725,69,545,158,913,265,625,545,224,270,907,934,454,588,28,684,609,677,785,349,800,596,957,152,611,548,272,209,430,220,66,212,385,793,674,47,795,201,636,87,921,65,425,322,681,539,680,111,782,12,715,608,846,347,155,281,801,342,933,405,291,24,43,630,923,741,971,565,335,209,695,367,569,809,249,110,311,698,727,211,230,484,571,495,932,331,100,230,255,896,42,710,624,497,531,158,461,176,707,162,74,891,386,365,270,724,883,715,177,324,980,984,961,335,12,253,597,472,294,235,430,374,711,537,640,879,949,355,781,294,925,751,938,398,183,835,631,196,310,506,427,183,730,441,216,675,380,881,242,53,721,607,928,890,319,314,519,41,468,884,310,109,444,509,663,455,420,776,793,432,682,788,539,692,255,120,507,654,483,452,591,708,206,370,542,796,169,60,105,965,336,690,968,220,502,655,187,607,263,139,588,773,168,454,452,673,184,614,55,366,456,647,52,116,802,78,574,403,606,824,334,931,78,792,63,980,590,135,939,978,873,478,410,86,371,787,117,683,673,30,116,961,996,48,556,796,127,942,307,980,795,730,624,245,886,4,40,449,76,698,477,757,688,915,236,787,398,908,802,612,462,112,575,519,736,859,65,892,422,540,891,761,29,379,654,899,35,533,729,244,292,735,63,747,736,166,571,30,343,134,696,172,461,452,849,863,516,280,580,584,481,176,982,571,888,242,466,70,507,824,428,841,165,244,523,518,379,807,184,474,410,974,718,732,478,601,552,848,193,482,292,612,589,876,892,270,981,350,464,156,465,967,391,894,308,682,844,312,61,893,854,152,448,524,963,20,940,462,101,267,353,269,181,410,804,920,907,911,309,415,730,552,379,110,512,458,185,777,479,699,208,468,671,650,80,947,374,478,500,761,826,706,493,353,684,617,624,334,100,359,417,51,382,648,935,889,713,966,614,387,874,923,798,556,770,160,261,341,247,135,660,557,796,656,386,605,770,367,749,168,954,266,146,548,182,389,918,601,180,0,303,489,118,163,206,92,544,26,543,78,646,69,660,242,854,896,692,539,276,910,72,164,622,485,827,159,212,204,729,395,69,219,404,763,770,786,779,73,296,416,374,982,571,493,181,825,780,160,978,824,679,680,710,75,154,557,307,834,465,30,72,752,108,116,643,501,265,295,74,154,73,731,366,316,987,741,237,418,463,728,948,236,371,213,951,841,377,159,401,221,804,819,324,900,578,502,421,271,832,479,493,647,896,732,235,963,976,228,219,736,500,795,901,577,914,400,646,786,444,878,214,555,778,469,49,616,788,957,926,954,609,836,646,84,461,435,345,172,313,48,468,219,866,321,410,159,97,715,469,463,811,563,791,937,727,616,890,573,454,639,516,542,63,845,39,499,250,205,150,605,213,456,952,234,652,518,188,662,55,525,892,978,443,586,425", + "352,616,4,763,42,790,301,692,565,86,905,718,319,479,218,679,143,884,110,605,32,424,436,515,788,399,271,979,575,93,699,556,722,44,574,969,159,44,269,437,832,517,573,14,635,483,787,723,448,582,296,691,729,205,61,294,442,397,400,205,278,931,62,743,930,102,308,933,889,658,292,111,837,855,376,662,11,342,123,206,780,833,877,739,279,229,463,733,913,570,324,336,995,843,246,108,584,694,823,284,974,353,491,212,545,532,455,210,846,869,948,561,919,109,997,527,909,679,114,895,910,783,947,944,14,519,980,680,947,446,304,647,614,207,713,714,440,724,910,879,606,21,221,416,564,673,95,455,609,621,914,743,728,953,266,713,364,962,896,840,272,200,859,147,886,27,232,206,896,405,166,307,805,123,121,661,826,50,426,522,224,300,698,121,772,54,281,222,405,766,793,381,954,857,650,656,433,219,224,697,664,213,294,169,754,755,425,11,860,419,788,661,777,69,151,482,954,195,754,155,262,650,267,222,170,921,805,993,294,13,536,697,713,298,317,208,190,172,742,213,210,966,285,801,731,264,701,887,539,904,908,844,500,110,970,677,644,234,858,598,487,801,949,907,967,155,716,670,114,117,932,759,79,574,770,435,50,863,547,731,82,465,610,386,850,862,725,739,440,601,646,41,704,401,735,887,785,333,703,46,816,642,270,266,914,973,330,749,964,210,525,771,421,115,408,166,982,478,301,945,236,343,783,574,832,43,744,266,910,178,951,655,683,650,662,821,526,939,646,666,633,820,561,41,975,381,240,211,369,430,766,221,928,892,960,122,675,570,378,600,667,967,393,427,578,432,276,612,811,591,843,504,725,485,385,672,411,485,914,175,482,390,417,457,682,934,935,76,12,655,910,175,208,112,763,645,397,199,168,195,177,263,111,38,979,695,425,171,977,157,445,565,808,448,283,664,73,833,745,611,565,498,61,419,866,109,59,100,953,291,410,884,966,260,640,473,818,583,718,441,579,751,644,513,468,662,625,751,74,518,429,412,623,677,222,22,931,600,767,399,656,285,2,629,571,754,481,680,135,708,656,425,191,569,236,18,929,576,580,591,684,186,175,157,457,812,541,561,358,137,613,791,670,664,960,87,175,119,598,404,806,738,644,98,553,738,132,274,45,843,942,285,865,108,979,178,437,382,86,924,192,300,886,895,831,202,330,136,913,835,336,576,138,868,327,356,646,107,987,466,171,773,954,435,508,724,970,26,570,682,208,866,834,905,4,231,266,865,2,20,496,768,811,20,108,561,113,943,395,799,673,976,789,470,280,10,22,967,155,496,361,82,874,309,795,608,839,649,508,733,270,10,663,195,663,744,442,879,931,280,391,948,104,817,692,693,111,208,338,302,510,813,375,590,382,559,840,564,171,247,797,573,99,550,854,897,836,656,951,753,490,160,785,768,745,664,185,167,790,670,607,906,204,534,465,124,694,600,872,537,611,195,916,67,957,757,578,75,354,300,467,890,495,368,105,430,911,432,684,286,813,9,993,181,91,317,844,663,369,469,807,935,383,435,647,16,869,839,738,331,971,491,620,341,874,7,938,179,327,244,653,394,277,653,462,556,348,742,245,999,978,128,227,858,689,831,361,400,757,155,360,315,80,109,175,754,73,430,663,303,754,153,940,649,995,656,952,476,260,717,498,102,494,153,968,294,543,314,845,239,547,22,151,579,373,914,26,174,939,250,278,164,519,417,556,222,326,321,719,235,724,817,944,166,837,251,671,222,4,753,350,823,861,504,146,321,823,306,974,979,565,633,224,302,131,793,270,535,283,353,251,140,175,629,687,443,459,978,229,762,439,528,76,713,303,0,862,310,968,94,694,474,906,89,310,39,567,37,181,315,996,375,105,141,954,870,149,771,159,538,322,41,370,621,394,511,536,462,592,575,337,491,325,48,113,981,482,503,799,791,461,391,592,334,257,322,489,219,157,659,856,490,684,921,649,347,58,784,738,121,79,731,571,429,781,45,207,238,607,17,678,309,467,550,563,290,345,184,939,103,580,701,333,799,192,722,471,957,697,141,39,432,867,534,617,151,409,747,171,667,798,600,414,548,283,830,718,571,343,222,753,512,164,692,564,197,151,250,381,320,243,121,249,377,499,461,727,53,369,683,372,20,611,543,119,517,983,236,656,934,313,720,707,519,969,159,746,710,669,382,622,641,947,954,725,913,977,162,561,647,38,372,722,758,973,571,677,954,130,864,315,446,223,63,90,510,247,525,906,259", + "550,336,99,34,308,235,863,640,837,145,895,101,63,422,697,913,540,768,640,513,2,186,336,126,313,93,180,914,367,466,592,479,895,402,1,827,309,917,158,533,468,866,419,309,429,452,807,171,860,653,526,249,324,731,48,818,36,816,502,401,896,270,609,254,262,823,868,613,599,142,892,868,59,549,933,190,275,717,819,321,451,365,985,928,882,457,183,765,377,834,60,74,664,54,610,411,523,923,355,654,747,262,951,356,96,39,781,718,105,81,827,296,93,960,27,749,323,283,493,37,928,699,107,342,271,120,152,88,879,142,768,292,11,12,101,804,101,659,890,461,785,426,312,920,441,121,114,633,798,735,659,679,901,931,434,344,258,877,592,61,446,226,289,549,932,808,943,731,889,196,266,396,594,107,572,245,221,357,861,937,928,259,16,727,709,647,677,387,553,757,130,9,400,974,862,283,601,534,636,97,692,33,338,779,244,812,832,348,373,844,648,527,712,289,544,941,878,55,340,314,256,866,835,650,973,733,939,265,156,16,75,539,390,412,877,208,303,438,157,175,743,947,412,929,489,627,969,341,136,543,256,703,26,996,874,35,306,908,763,641,785,501,837,450,203,190,955,533,125,913,341,50,681,139,284,274,149,863,350,422,87,696,283,525,747,749,505,99,341,503,117,871,344,854,642,98,663,136,103,135,464,885,410,209,277,811,20,799,978,166,148,66,508,403,880,828,123,996,98,703,229,759,329,896,342,286,138,150,458,909,32,419,658,370,464,325,475,644,938,479,690,290,56,218,367,664,479,93,260,812,562,744,925,206,602,264,772,681,256,418,555,90,811,853,768,966,658,250,173,169,300,823,792,353,811,190,41,654,185,574,649,14,631,441,5,854,530,535,331,63,860,974,11,110,634,247,902,549,51,118,991,141,150,46,902,428,518,226,635,246,66,192,454,274,57,41,148,208,745,406,504,116,364,146,802,294,611,263,367,342,298,779,827,95,702,602,453,57,200,589,929,407,277,742,574,769,116,536,134,636,917,687,328,694,817,306,548,178,265,616,153,846,31,946,38,159,71,724,260,483,349,698,85,458,785,919,761,280,196,747,211,309,230,702,944,349,280,808,997,39,448,972,869,818,521,362,798,265,109,197,333,445,725,798,495,720,822,892,590,987,869,434,824,626,899,549,277,563,885,369,977,656,243,10,411,235,388,828,331,397,325,208,436,871,928,214,23,805,746,305,114,997,893,727,267,636,375,775,170,6,625,720,207,218,375,241,713,634,316,81,863,307,557,617,338,518,818,965,651,385,713,216,980,190,520,721,578,648,250,275,482,504,609,467,829,497,102,579,661,105,146,963,275,305,864,555,426,675,756,690,218,891,646,874,92,419,417,466,710,903,486,62,638,193,900,892,521,343,677,968,397,136,323,136,156,388,791,378,759,951,555,471,133,791,518,736,783,312,302,394,9,840,762,329,599,468,484,392,550,489,244,744,304,284,167,793,154,532,814,799,798,975,794,937,45,999,150,134,186,644,733,920,571,115,408,141,674,575,58,742,997,437,889,731,767,114,875,405,261,939,29,574,677,326,175,933,8,481,927,712,6,553,627,257,768,43,414,474,568,548,620,174,497,294,271,899,717,141,806,137,99,76,944,490,388,801,622,501,841,659,675,249,701,639,275,548,101,311,127,729,779,914,661,972,128,950,298,570,714,372,757,433,970,497,612,440,502,614,98,331,912,363,326,350,142,167,213,899,900,184,465,926,395,730,805,290,482,989,163,705,492,553,919,611,884,724,304,568,780,261,493,891,452,546,624,304,396,977,979,990,108,331,666,801,89,93,678,488,377,56,682,113,780,60,489,862,0,837,960,79,474,365,337,111,856,31,304,390,228,550,63,310,77,886,745,616,389,152,366,474,154,367,263,530,378,417,311,723,868,547,501,181,694,702,772,667,44,60,271,65,843,901,683,760,439,914,546,359,141,879,716,792,941,73,139,856,472,693,203,365,195,148,788,215,553,58,784,853,799,909,123,147,833,444,475,412,844,752,350,76,468,463,871,318,470,455,230,553,418,647,174,8,751,968,553,479,299,873,680,733,46,900,658,574,664,668,149,570,464,834,479,309,675,593,159,941,831,198,328,197,240,800,79,544,984,384,290,914,825,955,439,307,513,352,38,772,910,904,674,962,158,618,528,20,898,67,379,255,66,454,948,729,978,295,331,854,910,326,832,784,140,459,357,252,572,48,613,525,151,454,270,861,469,406,319,339,379,370,599,61", + "496,241,969,950,910,528,431,934,908,468,926,546,235,194,401,311,971,58,514,804,235,240,603,46,161,124,732,890,268,14,630,482,15,828,811,488,701,416,933,180,196,544,750,961,517,663,627,750,191,926,540,291,528,245,202,626,62,245,645,940,500,608,621,350,601,577,317,108,557,252,709,422,566,452,51,819,299,557,356,872,994,714,268,70,430,721,166,843,119,198,815,217,27,591,216,567,822,805,835,94,721,59,77,147,567,321,360,586,106,630,434,908,783,374,594,154,278,542,234,77,185,160,496,450,440,706,314,124,477,798,551,89,978,984,86,897,976,322,501,854,399,448,886,457,514,645,851,788,58,671,871,195,492,871,627,901,109,564,104,224,964,471,582,221,467,52,850,694,312,763,222,556,947,779,518,128,453,82,881,725,780,885,989,920,171,627,230,246,837,62,853,50,807,454,8,971,514,963,40,72,897,679,31,208,847,402,549,372,554,993,813,444,722,448,817,725,90,728,460,716,598,990,874,700,592,154,378,987,639,66,381,599,890,382,857,826,902,681,237,111,774,70,253,697,358,399,470,341,171,164,141,927,366,737,409,70,286,879,305,386,607,622,58,71,368,519,831,515,730,666,288,446,424,276,678,663,878,369,787,247,161,594,437,677,462,372,263,923,778,224,342,648,857,12,505,65,59,187,921,850,161,242,706,458,239,959,256,211,876,437,532,1,148,431,442,587,253,849,511,769,441,520,359,637,222,979,278,319,493,17,555,93,291,72,75,22,921,525,655,315,590,329,23,339,265,518,251,826,162,812,727,103,41,36,786,867,445,550,103,177,995,31,693,879,633,407,619,763,723,937,185,189,301,583,554,32,42,685,20,695,992,941,294,940,446,173,85,812,223,36,478,718,947,811,687,18,952,712,859,943,238,483,111,939,395,590,373,807,926,106,127,103,170,19,215,868,774,22,205,182,306,709,560,603,94,993,889,130,711,469,799,655,686,523,752,953,135,319,31,53,124,134,406,135,45,20,53,817,608,984,494,447,566,688,457,909,111,217,725,996,59,875,892,81,244,840,775,108,425,732,742,728,522,850,184,461,446,303,20,762,7,980,604,832,804,714,356,309,441,263,669,592,53,4,657,540,561,723,211,575,961,29,834,262,363,97,39,975,300,902,66,977,715,748,891,977,180,395,9,453,525,984,25,796,514,620,135,572,792,135,694,346,17,219,615,197,828,876,7,220,347,425,85,104,923,438,590,832,194,942,61,922,556,744,985,811,730,380,492,236,746,777,221,64,329,898,540,471,171,615,681,79,934,87,996,90,149,620,87,373,479,542,131,197,416,771,613,684,205,407,420,426,871,689,666,791,499,872,714,528,86,544,386,430,71,899,62,976,77,956,762,965,338,955,228,449,208,833,272,327,380,254,401,619,733,317,697,71,575,615,553,923,477,781,238,207,954,612,69,371,589,794,896,729,596,582,235,406,908,865,212,861,225,392,280,520,709,517,230,196,24,184,557,141,578,84,278,103,583,322,169,139,932,599,801,717,73,472,273,958,96,217,305,109,751,511,236,727,848,934,555,53,414,387,801,254,484,339,491,792,27,887,473,695,950,781,650,305,417,221,469,319,99,115,878,183,782,242,363,125,517,689,542,557,868,708,844,629,826,247,952,598,958,269,566,529,148,710,992,220,137,142,542,182,265,809,233,911,563,96,970,939,870,911,121,989,814,377,101,445,509,456,467,617,265,870,149,791,285,604,12,224,884,590,97,861,379,148,67,5,204,280,169,230,671,791,430,629,99,572,780,419,109,452,670,659,771,673,518,459,967,622,97,801,815,233,681,883,486,473,140,448,307,292,118,310,837,0,680,532,879,631,861,242,314,239,866,26,81,196,991,67,895,558,644,817,603,216,488,354,496,996,234,349,353,551,229,579,536,460,559,666,918,106,49,473,491,293,8,727,259,943,390,716,133,792,510,838,623,768,43,345,605,432,20,476,869,525,179,86,220,508,680,318,614,649,902,260,39,608,800,621,813,321,650,167,484,735,807,170,844,302,993,905,472,847,410,675,381,523,140,643,199,826,162,225,535,915,755,96,946,687,514,255,586,299,631,87,858,403,571,989,285,525,727,838,632,927,558,178,416,485,959,676,942,990,445,649,929,613,285,434,553,505,477,877,312,627,275,144,377,249,359,885,404,192,945,636,506,207,25,179,770,348,367,299,64,957,363,236,28,868,755,282,166,276,102,295,599,120,478,251,199,822,186,22,38,48,29,274", + "82,957,116,927,587,992,611,642,967,338,348,786,23,395,525,307,45,40,720,463,128,278,555,489,252,450,786,822,620,59,255,437,954,502,933,450,394,690,451,951,519,749,797,572,299,449,998,666,783,53,248,639,804,44,817,907,234,323,940,866,737,592,608,498,812,921,481,847,533,336,176,581,455,191,208,29,685,911,466,183,537,717,457,601,484,749,433,223,935,134,758,637,555,326,831,691,145,185,424,979,873,668,321,396,40,848,788,489,827,94,118,956,564,209,169,787,339,309,743,240,121,154,23,207,548,217,455,467,548,667,856,106,375,806,412,392,934,70,439,138,769,581,763,918,10,846,819,77,231,392,407,48,69,275,777,958,524,924,150,194,757,56,28,255,540,395,488,999,985,534,767,293,714,1,310,708,764,420,299,951,833,617,259,460,477,696,614,211,116,925,820,403,736,87,609,800,56,110,943,324,116,512,735,679,457,227,24,644,949,824,378,227,128,456,831,866,624,86,763,203,80,921,491,847,396,581,26,119,108,204,940,832,110,974,369,134,673,8,718,634,870,164,415,322,583,624,473,999,685,901,110,733,768,770,570,308,746,67,246,781,298,928,879,90,371,7,582,363,616,471,681,47,819,949,345,246,917,670,445,887,919,377,626,771,133,161,626,969,707,928,842,184,916,148,382,494,442,895,935,343,387,243,459,719,691,229,596,71,622,765,461,538,707,815,482,904,27,226,172,695,925,93,666,192,965,566,677,93,343,483,287,645,504,389,559,315,453,970,954,396,66,146,134,425,718,806,621,160,25,455,978,159,795,427,290,859,447,355,692,411,665,613,570,928,953,305,368,708,49,4,180,95,747,683,578,763,750,4,850,811,493,312,53,233,629,758,17,721,103,874,190,670,724,478,432,780,655,53,472,12,977,711,33,82,317,880,126,984,572,117,22,816,523,117,833,918,942,658,277,648,165,263,837,304,599,434,701,846,65,749,875,843,336,214,957,648,583,458,743,1000,663,545,236,349,654,373,352,960,701,513,805,295,360,991,203,965,274,854,839,775,368,93,518,151,749,298,560,396,902,274,914,291,203,764,34,325,232,681,93,231,191,624,694,225,484,175,561,770,365,904,567,916,55,980,292,385,679,156,467,289,744,895,930,728,270,76,432,189,597,104,948,699,646,879,814,516,135,703,32,986,481,88,308,31,966,377,610,541,807,501,62,365,507,549,268,896,334,910,508,926,994,77,893,168,476,836,429,759,572,1000,405,394,210,304,165,847,867,891,916,321,91,705,308,103,877,53,939,444,309,890,623,241,215,232,211,160,813,496,992,858,628,609,832,673,421,285,554,108,137,302,816,441,375,161,864,999,124,605,449,149,306,643,419,482,826,143,646,302,394,528,946,761,868,262,517,808,82,22,966,644,282,716,413,280,276,405,645,135,648,258,265,700,660,886,971,241,476,563,774,653,172,897,741,562,298,736,406,958,217,612,693,340,26,32,175,323,601,670,818,284,411,700,710,432,763,904,6,527,865,168,969,279,744,74,508,517,294,524,480,721,527,450,159,324,254,792,636,120,918,930,400,713,348,730,184,486,752,496,535,983,300,367,535,442,518,396,37,112,44,162,755,219,699,436,723,628,362,707,742,304,177,898,403,927,259,465,626,55,235,943,632,338,485,584,725,185,187,966,442,370,608,770,490,624,475,431,653,4,764,928,53,744,846,659,139,434,432,319,598,559,591,86,580,168,422,867,417,796,830,755,433,911,263,385,209,46,189,373,774,637,377,342,246,466,469,888,989,444,206,707,732,998,98,205,196,134,294,63,633,228,283,392,981,481,673,703,26,138,827,421,666,163,299,861,163,968,960,680,0,873,665,776,852,890,462,811,245,333,515,510,461,333,641,741,918,315,479,576,446,875,535,211,695,448,615,179,397,833,948,319,993,617,536,391,725,890,521,821,109,52,248,299,339,495,142,749,487,479,751,185,337,314,841,677,634,447,598,855,344,769,502,221,888,783,70,540,766,729,188,854,803,20,264,715,136,150,486,850,983,477,666,283,356,342,797,782,523,48,987,363,769,212,531,801,316,196,647,439,184,504,839,924,576,473,187,535,232,736,571,886,299,202,76,23,410,264,420,797,376,249,223,408,796,499,50,874,279,157,821,672,734,240,526,177,749,214,986,573,221,426,350,946,268,83,982,465,696,940,693,934,372,218,547,862,899,987,553,293,766,912,272,522,875,196,123,749,773,506,875,79,136,351,622,464,833,460,330,594,596,376", + "985,892,474,895,124,108,1,14,83,593,189,801,648,369,19,651,925,629,173,83,896,648,711,881,925,417,886,883,777,339,722,773,397,165,326,701,998,652,249,695,923,783,624,226,924,671,668,46,380,29,501,495,756,316,37,595,100,594,994,620,490,860,491,240,654,91,75,615,521,398,255,818,380,479,972,545,68,180,827,689,762,583,763,504,475,161,663,369,846,37,60,126,989,79,862,938,741,982,594,872,809,500,94,268,890,599,270,654,670,901,360,885,187,145,640,690,842,934,360,216,356,203,334,355,774,371,395,498,548,830,450,484,213,424,210,825,200,763,707,605,801,315,303,941,527,546,873,628,469,750,400,447,147,290,481,457,76,925,651,88,679,55,621,266,209,430,196,966,275,587,974,18,44,734,737,467,257,40,903,72,172,149,393,662,590,630,947,62,393,833,890,484,689,9,863,448,157,440,522,318,405,488,941,42,463,144,815,112,795,918,812,765,340,262,199,139,741,108,440,758,4,506,538,876,879,282,95,6,924,657,80,688,132,249,657,172,511,81,613,126,395,70,421,71,618,695,719,850,405,398,682,193,522,231,890,121,315,464,198,851,655,510,186,541,179,905,208,181,831,751,847,611,860,279,660,970,342,743,134,675,390,870,616,901,860,871,534,292,860,653,435,823,651,313,526,866,896,922,85,265,670,275,830,854,348,113,596,145,824,865,309,875,682,787,136,150,433,451,131,916,781,711,382,332,781,814,823,708,567,535,18,514,249,560,345,141,875,607,462,726,968,115,498,501,719,205,192,849,749,747,288,669,33,241,742,877,281,275,373,648,802,964,666,440,16,645,676,179,344,781,299,683,686,121,767,612,865,834,436,917,568,315,855,314,832,519,942,808,914,822,717,612,317,678,680,306,532,75,424,800,285,970,532,259,218,239,607,860,592,441,239,610,749,215,772,934,785,287,872,504,988,67,623,403,909,175,154,570,300,799,981,878,745,763,141,248,813,454,102,36,382,123,291,177,317,354,537,874,19,576,755,263,797,21,896,41,437,26,242,214,716,93,580,872,914,700,771,160,700,94,209,114,700,693,783,136,250,141,82,200,237,552,59,909,10,29,50,136,573,173,941,590,481,194,768,946,756,307,987,710,72,964,987,615,660,896,123,742,865,188,787,300,307,259,626,871,894,256,476,753,106,499,162,880,316,701,914,210,810,777,715,345,730,170,341,939,899,201,428,693,602,542,917,615,620,883,132,948,79,183,542,321,102,59,275,293,508,147,279,841,372,166,993,60,468,966,103,529,59,567,367,865,312,145,94,829,671,734,657,675,293,3,69,806,397,966,829,81,789,905,606,769,175,740,956,676,606,779,484,93,248,814,102,250,96,940,443,844,480,894,231,79,441,541,500,567,314,412,927,639,124,815,549,307,197,568,642,419,20,698,524,123,142,595,698,648,199,403,589,497,336,93,472,870,188,384,701,141,757,287,960,359,216,856,750,308,345,671,658,763,648,649,478,266,377,713,632,74,589,602,288,646,841,338,268,150,366,338,260,554,642,515,240,243,498,121,434,137,199,326,740,408,374,271,346,932,722,696,297,132,772,501,684,292,106,124,319,181,326,381,724,986,378,152,825,819,417,4,456,546,505,920,300,440,175,842,615,232,56,868,557,4,432,825,783,745,65,481,762,99,48,905,284,412,225,769,710,621,261,105,273,689,446,833,405,275,236,580,937,345,978,782,775,467,14,466,274,529,25,776,920,166,394,672,206,840,972,417,343,68,42,119,879,845,880,809,907,772,331,739,145,298,268,509,803,353,936,440,908,374,342,752,116,770,44,169,708,131,78,81,488,116,627,211,206,94,79,532,873,0,315,1000,845,516,23,406,712,744,424,6,500,73,914,271,681,651,118,185,855,703,451,372,210,697,320,896,558,773,269,888,318,658,897,133,510,549,485,108,999,881,709,219,244,571,352,65,113,593,391,852,280,315,190,479,77,922,663,723,956,638,947,49,609,908,257,211,904,942,111,349,8,936,130,98,667,854,594,321,191,543,375,409,743,418,266,640,804,969,560,198,550,107,463,823,143,971,469,549,290,762,712,419,348,996,21,843,834,862,296,775,96,734,105,935,259,610,711,667,912,349,532,580,736,421,772,706,266,186,293,850,368,678,16,647,914,770,127,260,484,396,217,825,898,759,592,909,289,686,985,892,262,447,444,470,649,84,641,35,150,460,156,911,864,408,678,727,741,111,439,966,519,377,937,793,925,72,754,795,960,868", + "340,196,421,947,492,543,193,455,800,796,611,156,965,591,732,499,625,804,466,459,102,692,983,636,463,165,879,616,647,542,397,252,24,20,310,882,877,761,872,266,578,215,421,526,120,832,175,866,7,575,945,992,506,510,813,706,261,207,400,518,303,901,35,543,621,298,327,130,521,693,809,814,785,298,994,186,397,713,164,860,594,872,324,485,275,667,26,351,670,712,815,879,559,275,534,903,480,320,767,93,427,258,384,281,950,663,816,881,81,344,402,208,919,19,262,154,907,225,912,350,253,484,133,155,481,366,123,629,604,286,664,381,64,578,190,289,849,256,131,681,841,23,585,117,500,305,664,156,311,525,733,996,194,522,376,400,446,723,648,995,613,823,9,918,672,507,698,292,825,40,445,36,251,639,488,297,595,268,320,274,391,69,913,266,675,913,205,638,55,516,43,317,441,390,538,547,851,787,676,488,948,723,621,142,470,753,107,267,509,649,481,850,229,789,371,194,518,957,575,974,978,13,135,271,149,635,670,192,372,962,36,562,89,670,720,249,94,317,238,128,58,56,377,148,845,119,273,233,998,198,149,376,113,660,644,925,810,456,509,72,969,287,933,930,564,683,451,811,203,214,263,239,759,527,722,479,754,798,995,709,491,865,718,251,487,612,771,41,820,449,876,398,328,841,769,221,791,522,615,341,416,911,361,522,335,854,714,918,400,983,741,467,797,859,437,134,22,913,421,280,798,418,40,840,841,214,61,77,276,537,352,166,381,533,769,278,27,700,291,904,800,927,574,867,292,383,896,225,509,138,691,279,475,26,674,551,334,492,876,641,557,484,507,374,476,315,929,659,755,359,879,168,865,83,473,358,719,647,961,311,431,165,46,563,755,889,736,624,65,588,957,541,566,131,333,301,750,322,177,818,467,140,899,135,264,169,439,516,509,701,125,651,279,953,272,214,926,902,58,569,720,346,758,952,936,39,355,594,697,810,501,852,955,544,363,533,216,82,603,685,693,504,363,923,640,374,684,957,678,248,362,673,246,757,452,957,612,101,314,830,859,790,229,763,894,283,946,286,744,463,911,982,613,705,895,678,565,562,68,481,712,716,664,943,355,551,549,28,277,447,734,721,759,27,103,204,936,241,456,119,213,456,770,361,906,153,866,222,588,111,659,147,702,865,744,952,784,329,471,22,700,873,798,644,398,294,86,768,665,218,306,106,713,168,799,820,337,820,377,920,569,42,88,434,840,496,368,252,526,622,941,620,376,828,551,825,877,617,123,50,749,672,675,456,902,530,364,416,665,928,48,546,788,348,57,719,66,410,197,904,245,594,243,223,292,763,889,20,193,807,595,99,613,794,548,170,597,580,823,495,168,733,744,419,901,114,111,562,56,425,495,149,824,213,310,931,11,745,28,720,83,426,348,9,304,145,299,512,778,173,657,460,297,536,118,6,911,250,771,193,468,119,992,351,703,501,385,947,645,471,227,361,686,583,139,323,335,607,146,945,340,780,418,980,989,243,863,586,671,767,868,127,461,912,356,627,572,344,534,767,657,258,739,128,832,73,320,120,916,969,588,592,74,230,425,254,584,666,927,235,528,248,499,314,199,361,369,556,581,776,725,921,661,233,90,633,887,183,689,207,553,121,738,115,789,308,859,102,875,980,461,283,391,938,340,94,338,340,123,84,351,570,73,300,628,25,653,419,662,105,14,825,963,659,704,616,904,588,643,750,97,554,797,521,44,286,479,993,161,538,405,193,998,552,138,211,563,513,629,981,752,105,434,783,610,674,459,135,650,113,406,160,776,923,605,893,55,450,918,502,588,755,776,751,797,593,210,717,282,684,55,710,584,875,92,694,474,879,665,315,0,329,882,805,970,231,791,238,557,194,667,311,355,852,978,475,166,157,991,409,863,741,190,276,327,182,699,585,549,697,362,47,405,572,252,98,639,684,470,543,949,354,237,215,86,365,752,578,308,137,675,539,486,205,294,616,555,479,102,524,717,922,423,831,920,214,438,42,387,740,792,747,86,954,439,919,550,750,611,629,956,356,598,467,318,310,852,807,695,913,858,163,995,768,759,283,357,568,69,306,394,450,61,295,469,476,818,324,855,997,166,716,483,484,368,672,633,610,460,413,930,972,253,573,362,433,900,311,35,649,379,914,861,312,845,664,826,28,277,920,196,367,621,251,198,511,764,274,302,832,591,171,743,777,808,369,233,353,419,786,13,79,411,473,879,374,508,577,259,49,727,148,602,51,137,690,131,640,746,643", + "915,691,86,759,893,239,832,254,125,498,442,10,903,510,265,901,131,741,325,282,493,804,574,14,390,866,575,135,851,108,200,901,932,996,742,807,743,400,973,494,541,36,364,745,822,207,860,769,453,970,829,462,475,407,614,182,782,765,932,510,528,505,450,712,637,352,73,250,178,303,630,618,264,717,51,931,303,339,824,694,658,359,363,927,727,663,656,685,819,953,550,414,765,614,371,831,781,761,996,556,693,976,361,271,897,143,718,124,872,894,25,443,440,353,11,19,358,381,592,835,631,598,62,334,91,237,876,183,746,430,99,160,194,937,909,188,923,586,470,212,48,102,677,82,315,407,738,73,928,282,569,136,428,23,459,646,316,60,481,933,747,485,353,911,393,142,655,86,250,317,800,114,848,669,512,71,371,936,555,317,677,277,547,756,764,205,628,261,134,525,384,520,785,794,970,668,680,937,830,388,254,708,406,889,552,216,139,291,285,940,563,818,218,731,140,421,878,590,364,541,397,423,159,122,929,365,40,100,490,400,811,491,422,276,812,371,907,624,76,386,229,267,366,369,122,568,644,419,42,328,645,71,24,104,697,974,196,668,587,507,873,832,608,421,92,755,345,452,602,64,302,74,19,908,923,15,630,664,989,107,819,944,464,818,938,955,542,714,313,707,501,166,909,665,606,664,782,170,355,983,225,13,449,165,117,311,516,420,483,704,90,530,117,380,577,732,665,516,112,545,725,791,623,157,573,557,728,64,943,184,105,898,858,230,148,228,358,764,347,392,430,935,826,943,609,269,266,556,858,75,594,934,373,292,74,348,281,986,775,436,715,778,204,539,530,303,506,507,777,385,575,202,47,468,969,948,913,370,150,140,403,197,441,626,845,320,353,159,778,188,371,715,751,612,662,205,368,978,547,343,970,930,5,469,839,188,433,18,777,32,802,331,580,173,465,437,635,238,629,267,636,803,711,490,579,467,258,126,934,269,867,594,427,411,234,961,795,243,138,838,388,622,205,330,47,534,191,511,306,902,5,345,493,956,899,845,726,801,297,720,115,353,934,925,915,797,415,894,463,960,789,842,193,181,698,450,100,639,346,196,326,898,361,27,380,386,234,172,610,810,591,258,806,896,526,401,669,264,740,292,459,100,870,219,851,679,288,259,250,968,848,761,230,568,974,398,372,724,240,346,842,977,5,320,352,29,822,27,6,411,730,779,550,581,593,906,357,782,747,948,553,117,356,876,661,808,734,7,854,631,456,265,133,995,403,780,356,706,883,243,873,293,505,470,994,640,389,453,960,71,263,580,702,483,733,555,698,193,853,942,146,880,372,803,635,953,29,801,882,565,620,702,477,15,219,988,153,663,496,686,895,56,774,954,699,945,462,855,678,568,858,849,296,345,365,925,527,306,974,443,38,304,147,225,334,542,429,401,905,154,114,39,393,104,80,155,75,92,565,342,358,376,243,277,704,583,401,599,728,624,978,891,144,293,444,785,915,505,505,92,99,157,41,700,40,470,718,506,781,553,858,554,496,560,567,973,103,483,84,166,225,671,699,34,471,525,170,180,448,193,635,308,100,553,194,61,252,139,422,855,299,429,541,942,341,542,477,561,825,527,824,954,3,764,247,272,625,771,641,609,300,541,879,459,376,471,399,758,874,787,657,721,103,495,318,47,760,882,545,370,77,107,304,316,684,636,202,396,746,126,186,185,37,90,1000,531,216,766,671,158,606,172,785,924,906,677,672,712,111,603,371,344,479,865,603,876,638,507,232,245,95,800,474,891,296,57,576,763,994,142,378,783,878,128,140,945,174,472,407,154,488,7,21,891,102,410,575,363,716,840,756,825,703,367,544,474,365,631,776,1000,329,0,644,809,340,24,963,409,408,154,573,677,470,579,780,437,719,517,909,996,461,538,346,802,184,776,456,5,298,798,809,419,892,202,362,482,304,763,577,325,283,764,278,591,400,18,231,714,704,393,652,125,162,568,428,812,852,795,352,834,401,955,346,206,576,106,698,869,152,552,543,480,739,236,164,720,942,545,957,394,372,184,45,204,671,955,665,480,534,98,775,781,849,900,463,701,144,155,873,932,360,659,435,734,916,413,307,561,658,588,558,896,388,968,723,920,972,306,336,692,79,313,836,350,781,961,599,628,776,550,572,777,374,282,55,322,949,370,83,217,821,20,969,515,566,65,12,383,774,634,944,489,292,296,653,724,729,539,790,460,916,111,567,60,406,387,30,64,560,376,321,748,375,265,680,150,705,511,632,721", + "946,424,950,83,574,161,447,998,901,512,995,413,155,564,261,787,79,427,81,596,609,932,786,951,942,108,375,524,802,439,343,490,191,57,995,782,333,502,648,740,98,163,301,59,317,86,130,194,608,253,478,747,475,123,473,676,694,731,10,65,968,388,137,245,699,234,633,428,247,892,329,875,183,424,514,224,517,3,901,315,652,5,209,798,909,262,970,797,976,180,857,939,161,328,79,194,603,281,562,45,639,30,141,501,669,75,169,635,434,523,405,389,609,729,984,245,850,928,711,179,619,634,416,915,143,631,500,809,515,725,785,737,786,774,478,341,388,411,696,307,152,361,407,994,711,297,506,633,159,64,469,438,92,437,934,878,716,302,800,627,927,326,54,553,372,718,164,695,508,131,680,306,329,402,355,458,866,512,155,293,454,874,453,769,112,276,806,799,747,806,571,474,634,855,243,182,700,219,271,403,980,809,710,677,38,921,699,742,257,938,269,976,884,547,875,945,528,706,796,118,435,35,639,603,386,549,771,706,13,62,811,385,786,404,419,130,105,881,249,586,690,3,75,760,433,882,166,462,990,596,660,274,708,585,841,39,815,617,713,182,636,171,460,299,616,386,270,309,685,167,294,488,841,215,509,713,634,484,361,194,959,685,929,451,464,520,721,461,308,188,681,366,492,289,103,197,682,862,256,495,540,566,28,244,168,377,426,220,337,902,323,571,568,560,849,172,547,345,227,749,56,456,683,265,842,735,375,568,212,372,494,603,394,537,934,708,511,824,556,954,893,691,208,915,911,707,517,709,349,335,101,613,847,717,718,995,500,689,913,701,929,694,115,38,953,649,434,586,87,197,448,848,910,978,473,331,28,446,78,478,770,775,171,712,384,385,11,260,727,586,227,485,437,741,678,719,875,610,904,50,84,316,150,973,596,741,706,535,853,261,52,893,618,322,935,237,243,258,832,477,482,185,868,911,604,514,762,269,62,841,316,333,927,743,469,93,946,407,84,279,955,249,408,416,155,136,546,110,803,725,390,447,2,420,143,92,6,934,675,448,519,442,258,503,930,315,60,281,506,190,94,817,838,114,678,314,386,691,111,706,906,424,7,817,320,110,318,953,40,105,11,953,137,191,940,853,461,42,229,165,126,911,509,116,165,238,720,860,902,983,458,442,408,86,865,31,756,883,75,909,565,271,585,916,714,2,127,464,275,196,217,189,489,628,737,412,618,967,870,200,408,541,517,229,477,912,831,469,683,36,771,571,547,794,279,789,879,543,728,184,848,333,476,999,974,368,912,380,8,834,556,697,176,947,427,452,675,939,828,278,140,868,155,143,134,605,965,856,746,845,824,852,530,832,275,124,20,571,974,899,968,3,732,797,176,102,810,103,790,164,181,109,545,522,160,373,375,165,362,429,873,645,589,759,493,906,615,130,401,914,529,37,538,224,852,607,334,563,271,924,260,630,670,769,728,186,484,641,498,535,264,933,462,349,672,611,344,469,157,909,383,961,6,990,65,587,681,804,753,119,353,278,870,920,453,192,188,370,478,978,771,612,331,912,712,172,79,823,361,631,164,689,130,390,621,97,278,115,138,759,500,102,636,809,536,756,868,797,596,913,499,74,192,310,581,657,54,499,344,332,204,128,427,477,586,321,493,548,222,167,64,726,239,180,410,949,171,458,150,152,992,786,790,693,320,462,946,307,88,844,426,599,411,515,815,116,190,249,315,799,730,45,518,483,568,430,886,242,645,928,716,431,380,818,245,329,612,290,903,988,639,844,144,860,815,866,318,55,987,256,690,797,64,374,277,521,848,35,556,200,954,174,611,756,509,150,403,219,510,365,907,428,211,83,26,906,337,861,852,845,882,644,0,234,489,902,670,290,723,466,193,671,9,714,277,572,53,109,526,960,191,325,995,383,99,373,547,243,659,790,161,144,187,605,751,619,99,202,246,20,236,214,451,296,772,643,79,68,832,717,887,240,651,354,795,539,673,876,73,439,505,961,856,386,844,665,634,286,925,651,135,834,158,16,955,103,19,201,981,318,726,894,71,723,844,90,589,483,171,966,744,724,109,368,329,264,314,637,447,935,658,169,758,220,607,146,253,348,230,552,508,62,819,38,516,385,666,194,952,86,526,964,439,81,472,511,172,695,558,797,708,784,94,680,782,942,250,460,323,606,684,411,301,86,446,658,921,687,953,935,126,117,39,602,998,587,555,868,185,509,796,616,418,515,377,169,370,622,508,857,45,336,381,606,590,225,348,539,117,931", + "803,249,62,330,341,592,18,1,958,923,338,132,799,542,398,251,608,555,330,35,611,568,596,497,214,190,502,613,378,839,968,890,254,89,141,242,852,801,403,393,68,14,530,172,730,72,918,530,729,886,564,337,63,590,943,863,677,678,466,828,648,353,23,652,825,919,496,201,786,88,393,754,697,562,710,891,379,412,850,893,88,920,536,633,252,960,59,729,206,413,638,366,856,754,866,638,152,518,284,939,379,209,214,486,7,7,159,159,126,707,511,182,822,100,614,412,314,373,552,341,592,423,568,121,177,296,985,270,489,920,748,847,764,649,645,376,522,621,829,791,845,545,886,296,635,750,369,114,641,136,707,14,135,236,775,986,715,772,87,930,590,812,436,65,649,855,79,969,298,675,835,302,450,652,639,298,889,2,551,314,213,762,129,326,334,359,461,570,588,860,200,78,334,430,927,534,920,591,678,222,684,538,132,631,975,683,478,623,80,165,163,976,309,755,558,250,304,522,503,607,727,123,927,670,114,778,541,238,427,383,176,601,826,37,861,498,513,931,783,924,964,865,918,540,46,943,226,887,743,71,742,33,871,370,54,903,55,909,660,916,854,413,656,472,602,951,98,710,928,260,409,107,35,538,743,757,793,402,468,445,384,166,546,650,953,440,701,833,701,979,958,392,920,853,878,722,457,406,310,28,539,552,238,36,262,802,142,253,859,67,497,850,758,567,872,668,410,627,835,122,872,764,701,297,750,934,551,429,353,138,134,433,737,809,861,933,210,137,233,723,413,121,313,940,422,663,90,182,645,901,680,482,633,703,690,653,833,64,104,197,529,610,595,46,76,905,297,990,887,189,546,751,876,65,464,869,455,18,335,164,874,553,336,56,157,512,467,634,20,883,413,457,702,447,764,317,190,596,172,915,634,942,824,811,907,182,790,854,589,272,406,378,443,157,301,244,492,467,419,697,558,628,9,30,415,770,829,116,168,927,73,173,758,561,365,590,986,383,815,531,757,866,671,40,786,201,170,692,315,821,675,873,547,343,562,874,148,308,439,841,482,216,385,232,151,839,62,572,597,285,691,439,232,570,668,695,323,281,757,564,997,674,758,464,361,433,886,2,831,886,630,164,987,952,409,913,93,510,405,925,413,304,478,238,744,185,288,826,514,543,184,844,942,104,875,519,475,258,56,59,219,440,216,853,672,91,11,931,914,107,852,201,322,432,862,225,703,840,260,954,84,47,78,243,452,753,276,913,180,344,616,67,817,422,848,544,356,890,853,728,415,395,88,265,671,194,210,462,733,662,310,706,17,602,862,655,394,249,344,603,672,422,373,503,51,537,637,736,577,391,588,401,71,296,511,327,278,475,122,99,776,492,964,214,407,600,827,57,553,216,799,826,914,347,234,492,591,270,63,831,371,163,676,340,327,247,405,677,158,523,428,597,46,513,75,429,96,267,990,243,756,173,932,279,934,481,218,601,67,548,392,806,680,94,659,91,29,534,447,50,970,343,47,854,529,596,548,756,518,905,216,783,931,544,99,469,783,377,881,218,364,100,756,785,460,572,438,595,528,679,180,970,146,171,199,162,930,439,856,119,694,261,555,552,144,107,105,510,785,478,765,891,347,55,707,510,536,523,255,496,44,20,843,622,896,657,408,522,334,532,867,867,591,303,791,393,215,421,621,649,391,423,675,342,333,869,976,808,379,219,985,86,741,100,187,715,254,636,666,426,413,308,726,680,819,123,266,245,78,745,393,21,953,274,919,704,59,644,322,922,8,657,106,900,200,616,921,849,234,573,335,128,384,262,252,58,66,192,944,600,193,28,354,327,963,623,525,214,886,392,23,606,108,467,543,89,111,242,890,516,805,809,234,0,254,387,200,247,175,578,602,335,918,608,894,237,614,505,207,62,828,5,179,914,368,23,7,986,371,412,666,39,485,250,286,959,241,111,578,952,480,50,690,940,738,997,988,496,934,703,56,202,176,69,318,813,790,108,123,865,312,492,332,522,875,99,608,195,437,900,338,886,992,856,855,1000,790,560,730,508,664,316,88,6,853,112,896,359,959,365,972,56,313,42,965,616,747,944,67,522,608,333,86,515,150,492,929,19,331,432,969,179,255,226,807,385,627,150,983,679,617,98,357,555,219,947,928,886,368,553,8,729,206,65,724,26,75,152,601,364,872,83,980,17,708,879,111,156,134,60,630,856,59,362,387,241,854,209,227,875,346,317,362,271,316,397,254,634,62,610,512,171,647,994,537,154,553,464,292,732", + "441,932,216,348,652,124,333,755,632,500,133,164,844,66,160,197,806,755,868,961,396,3,39,918,7,189,953,241,970,525,553,415,391,404,418,876,765,797,783,637,233,508,120,850,907,305,729,933,477,899,595,911,287,268,597,734,220,348,811,691,415,41,413,565,972,297,299,616,561,612,892,806,780,75,950,35,629,930,876,922,280,929,460,421,158,141,726,847,214,75,602,476,388,128,19,986,521,657,79,489,196,189,99,828,430,20,727,50,333,731,665,867,600,255,145,100,987,132,560,577,917,811,681,298,271,665,781,699,629,767,3,154,891,790,120,168,695,322,237,28,406,678,539,251,418,921,683,278,2,261,276,858,853,825,456,95,388,139,673,159,747,241,618,466,475,180,860,742,878,747,263,727,216,893,164,409,799,598,126,456,409,160,438,961,215,591,941,336,890,794,887,700,552,99,554,338,535,869,137,960,336,640,892,607,264,215,377,606,828,566,823,796,392,573,309,772,144,461,201,573,820,447,850,383,656,581,542,214,394,237,500,867,39,337,536,927,808,412,223,566,920,48,949,396,851,947,363,622,113,921,547,827,850,361,904,321,151,353,816,54,396,333,92,274,359,337,265,456,521,271,116,286,345,343,147,224,303,485,925,983,215,433,101,774,244,38,819,863,249,829,641,498,305,113,699,709,995,963,411,223,156,677,499,137,477,235,496,513,475,257,232,733,44,773,973,179,141,313,59,109,784,575,680,236,546,713,29,378,680,803,701,209,275,477,92,597,11,889,548,449,565,908,596,497,284,304,20,183,444,455,944,527,870,488,198,944,117,978,602,162,212,720,798,148,681,531,631,230,986,25,256,667,61,212,431,156,693,50,254,572,373,625,237,867,472,453,433,934,473,776,512,658,576,482,234,764,506,329,568,364,526,927,31,927,966,476,72,230,81,668,418,842,594,85,542,770,973,140,959,898,783,495,215,236,737,289,406,322,888,311,953,632,288,480,970,515,588,341,705,787,162,700,9,499,625,619,555,566,863,510,204,673,896,716,511,984,731,159,826,91,425,746,814,157,965,800,324,180,302,310,952,796,656,502,380,98,664,84,7,707,895,741,935,205,101,416,772,207,632,653,828,62,836,889,232,409,258,684,885,529,629,239,312,471,181,566,379,390,734,272,790,923,650,372,668,178,668,894,94,944,153,612,345,275,808,472,335,973,964,342,764,541,125,477,882,140,923,750,110,261,741,735,934,702,919,239,207,923,787,642,662,728,56,226,358,150,147,564,598,908,685,589,263,557,947,538,18,75,600,493,450,374,124,219,658,682,405,258,986,553,931,103,141,26,254,773,911,744,795,716,625,976,870,125,358,805,782,626,986,281,582,664,950,83,611,684,735,297,25,133,153,633,904,605,478,453,198,496,86,907,501,311,37,304,427,164,816,872,291,289,121,905,589,646,611,495,19,33,595,864,611,841,189,110,694,246,820,85,950,984,114,421,662,58,352,879,636,843,831,492,116,382,706,730,553,490,830,191,883,535,868,736,794,974,160,545,169,589,526,646,293,518,35,882,757,46,546,197,373,274,145,614,476,662,603,485,7,425,503,248,72,828,898,656,159,805,257,423,290,81,884,177,510,206,324,46,152,755,257,714,287,516,672,406,930,905,554,374,860,522,425,502,523,220,904,110,688,903,943,195,551,369,880,848,10,940,715,439,34,391,67,61,305,204,900,287,688,300,124,724,408,108,689,641,940,683,482,880,324,656,641,751,946,308,165,302,588,993,619,134,699,854,636,891,221,300,591,568,818,752,789,349,953,559,701,348,893,820,96,872,667,587,634,700,520,783,593,515,41,107,832,714,817,224,78,310,856,314,462,23,970,340,489,254,0,283,990,898,843,653,37,620,657,831,438,602,352,34,919,627,310,185,97,843,191,558,205,571,18,817,718,125,72,918,238,772,37,991,255,706,115,226,859,99,322,717,584,543,315,277,24,338,714,895,306,673,644,36,958,823,776,742,452,518,161,25,699,729,637,348,54,975,665,628,246,337,679,652,503,116,861,196,230,407,272,613,499,182,866,941,409,170,403,857,746,945,84,353,256,576,190,498,761,43,951,3,887,85,312,823,418,643,60,803,386,434,406,788,657,6,873,117,42,892,674,254,18,339,130,935,865,577,666,512,413,404,728,315,645,30,663,595,621,847,500,817,588,904,46,125,475,328,562,307,38,480,915,707,101,991,947,193,400,76,842,26,759,442,809,467,359,29,790,663,863,129,723,281,354,877", + "822,603,409,651,447,348,493,565,998,865,900,923,513,18,828,337,862,953,345,343,437,811,325,391,928,808,937,370,830,775,751,697,804,492,688,277,710,140,406,437,441,374,729,286,120,743,529,828,60,813,940,907,836,801,434,193,690,172,696,941,624,539,354,862,137,263,175,418,50,18,678,521,762,353,778,33,63,501,987,438,888,397,454,45,702,36,423,501,721,399,464,204,280,854,650,286,266,145,75,163,160,62,773,437,476,269,371,221,90,174,166,328,763,621,330,321,141,566,623,787,453,661,103,599,614,696,754,60,129,369,725,282,778,455,335,60,737,554,327,441,261,567,208,233,126,999,241,17,630,333,252,683,111,755,348,74,129,514,890,490,127,987,556,976,26,193,270,307,938,985,352,896,644,705,406,201,845,364,16,863,52,265,876,678,843,743,717,12,609,925,476,375,909,32,812,231,313,843,174,895,557,539,886,883,15,150,819,452,104,223,201,912,45,623,174,798,646,633,673,467,279,721,564,434,771,32,899,436,376,755,383,993,758,899,463,682,389,580,103,922,269,537,967,926,879,999,224,967,252,343,35,91,209,472,228,368,39,910,986,916,325,79,582,427,216,775,880,112,933,897,402,53,400,685,825,967,66,285,586,27,164,665,736,652,932,345,409,652,224,932,685,501,8,346,799,215,38,979,436,446,594,119,609,423,115,882,867,507,591,777,133,316,668,80,315,569,417,811,29,858,997,597,206,677,624,881,415,403,490,85,192,437,846,624,179,940,707,304,908,610,302,676,883,30,615,585,671,194,426,614,443,198,949,938,91,42,96,816,802,206,295,139,991,745,394,160,234,410,557,309,78,881,46,619,764,40,175,290,15,996,926,707,462,464,126,520,692,136,97,818,534,33,18,27,595,654,382,591,931,808,394,838,662,188,721,824,918,631,53,156,715,839,342,598,172,930,808,414,297,97,92,514,380,872,407,750,64,991,962,24,802,947,842,874,782,986,254,329,38,288,18,547,789,354,661,513,192,99,196,158,480,819,720,171,78,418,993,617,765,420,628,794,383,503,670,971,22,223,259,887,480,147,95,648,360,581,435,763,979,626,421,118,748,192,198,924,703,892,709,782,205,868,651,211,495,580,617,935,150,870,144,734,844,424,660,473,444,239,957,866,993,434,902,144,788,963,156,228,546,218,85,186,78,135,962,686,459,22,689,285,941,793,619,731,178,230,730,722,565,776,266,602,632,530,707,403,447,250,719,936,735,309,169,360,308,111,515,18,234,931,870,847,233,410,274,628,976,17,706,30,863,729,217,887,748,258,832,28,619,255,971,721,272,837,567,268,570,94,204,432,150,343,889,422,179,345,473,985,753,966,398,798,184,398,289,695,164,565,654,607,123,87,116,360,285,103,656,87,276,49,141,155,241,347,320,766,524,530,220,122,109,146,601,733,643,872,765,233,536,243,272,882,276,910,597,793,1000,67,957,1,574,286,535,178,690,428,823,847,998,223,83,175,733,48,424,906,296,271,653,695,34,520,102,911,538,722,847,166,814,598,205,202,596,417,485,310,794,181,653,738,980,513,826,646,265,748,159,282,720,480,213,266,115,523,536,102,775,205,600,514,321,490,339,14,733,508,690,458,126,418,560,86,984,888,71,791,361,468,346,590,41,182,589,611,948,50,175,684,147,174,416,460,714,599,132,648,770,201,866,391,84,892,42,324,482,489,736,161,71,56,479,13,826,664,885,717,571,330,562,212,133,56,928,457,482,85,500,688,915,637,952,44,112,281,399,76,271,879,364,661,819,946,190,655,943,319,312,290,846,129,865,504,409,999,621,600,436,873,308,787,580,566,615,585,646,39,31,239,811,406,231,24,902,387,283,0,757,161,824,813,827,466,584,832,37,54,764,139,504,727,888,997,635,143,902,347,766,419,609,817,858,156,175,110,976,93,685,350,44,533,50,131,376,161,482,413,600,709,926,128,978,413,17,205,80,939,948,278,725,830,275,522,211,473,759,63,351,585,686,882,221,198,650,823,183,510,397,358,28,81,314,425,574,388,401,293,720,224,532,941,504,47,723,591,74,351,1,511,102,548,471,74,322,861,805,91,165,921,347,211,287,251,589,368,616,145,728,378,161,744,259,719,587,171,861,135,977,496,518,452,884,787,214,16,883,570,11,2,725,550,385,883,65,459,966,611,149,242,86,530,103,675,825,424,302,87,658,73,556,48,772,200,144,63,584,366,260,746,853,248,163,231,588,981,433,207,131,47,442,500", + "142,677,559,773,701,117,773,161,959,303,990,252,388,62,382,179,869,242,441,395,23,216,688,52,5,394,593,519,753,737,558,760,905,694,623,521,502,582,698,898,864,519,804,934,33,46,216,91,284,649,363,257,857,807,96,276,858,343,312,802,552,848,519,48,811,789,195,736,171,897,375,48,35,561,183,389,329,479,464,509,77,68,87,576,541,21,974,971,374,535,704,824,543,136,231,43,968,821,706,708,430,743,104,864,734,109,688,547,708,141,655,51,754,607,885,562,947,740,258,219,609,202,282,284,758,939,419,478,519,790,483,531,593,512,207,709,402,807,556,95,595,770,270,778,187,433,329,113,764,839,943,235,325,305,257,764,34,188,380,285,756,135,759,659,530,541,666,526,927,699,606,778,846,342,765,915,198,890,539,435,376,576,503,584,927,745,951,792,551,634,727,295,708,297,692,269,699,777,111,657,364,704,747,776,653,709,759,50,418,451,993,686,595,898,182,859,624,792,81,58,647,222,10,619,551,627,502,879,300,481,893,628,516,539,106,279,820,218,81,593,437,505,819,324,344,348,727,922,697,194,603,641,807,483,440,495,103,40,227,192,667,968,40,576,660,320,632,211,358,380,735,352,846,616,812,967,325,739,835,222,712,156,299,342,874,364,367,650,872,847,244,721,797,818,96,585,84,32,533,52,518,266,452,414,101,717,750,917,482,593,910,96,675,574,837,856,849,333,616,951,847,428,472,994,699,818,121,851,224,490,748,548,550,972,193,377,899,174,90,114,747,968,296,725,295,279,807,179,545,380,83,783,735,770,66,42,225,395,420,408,360,538,860,44,426,20,299,478,84,10,620,965,454,713,592,196,599,867,486,313,402,248,806,411,343,186,954,826,628,263,637,468,985,718,383,125,767,125,81,905,226,669,437,946,881,137,539,878,152,626,656,766,939,377,573,562,154,773,597,492,186,743,452,439,59,122,227,996,522,498,466,373,981,28,35,78,290,800,125,856,277,779,25,505,538,628,903,470,686,931,414,927,155,379,762,784,455,104,237,313,499,741,939,245,695,873,813,653,4,239,257,606,414,789,34,710,107,951,620,18,584,931,669,597,200,814,243,663,447,196,906,878,958,432,606,455,321,834,190,999,446,383,293,210,666,292,601,541,898,958,902,319,532,616,304,592,822,453,278,403,585,326,823,79,20,54,953,683,182,765,873,993,151,765,508,287,906,595,46,114,878,744,966,628,109,31,986,195,896,240,734,510,201,487,651,247,937,757,700,949,793,911,225,930,831,804,600,83,915,56,981,817,874,853,610,312,975,824,786,9,787,140,379,335,887,235,823,645,661,626,37,161,692,803,987,889,337,356,545,785,444,129,38,48,224,346,349,808,157,318,81,952,738,723,242,725,559,135,340,411,697,396,720,159,848,968,705,712,334,66,378,805,655,334,407,261,709,147,880,434,344,475,838,514,225,874,988,526,293,209,310,126,452,458,349,2,648,321,51,357,904,567,988,263,613,143,420,73,1,702,663,608,390,618,367,514,193,433,726,724,798,858,594,16,646,366,515,262,104,975,334,674,495,285,210,380,114,161,993,676,431,824,957,500,634,682,249,507,61,190,385,714,238,962,730,488,812,798,809,949,147,251,586,83,619,994,339,605,118,530,175,746,466,393,391,756,680,459,782,546,766,277,242,63,683,132,351,315,516,385,858,652,442,46,537,369,415,705,678,830,396,577,230,862,7,17,960,554,400,936,485,609,42,652,467,884,451,646,371,230,165,108,118,666,723,782,475,503,113,628,180,118,544,409,173,645,346,906,751,327,482,658,5,843,149,490,703,627,521,369,272,619,932,974,69,567,304,866,245,712,791,963,670,200,990,757,0,499,938,348,447,503,26,147,360,775,588,178,379,591,251,715,928,633,195,508,270,291,49,868,622,220,652,659,218,673,42,685,807,397,381,910,852,39,518,227,870,250,432,636,463,846,361,953,488,540,527,156,693,999,484,525,869,673,825,647,383,240,980,234,590,361,554,714,397,875,292,319,54,133,338,772,32,212,871,894,589,360,633,25,975,14,903,489,399,714,627,406,853,891,866,962,928,656,474,666,634,335,168,187,146,47,66,485,987,284,313,317,225,350,858,746,462,699,54,53,579,43,433,690,630,843,654,672,201,886,653,282,816,250,178,645,678,534,492,810,133,84,715,693,289,818,68,101,887,212,335,782,497,182,457,690,585,823,832,599,718,549,603,455,989,402,676,655,433,473,316,654,485,140", + "297,122,488,914,258,779,40,400,632,486,133,132,187,904,929,465,8,484,468,356,978,137,714,940,653,23,782,876,731,366,859,652,75,136,187,443,450,799,582,117,87,932,787,769,873,953,280,436,642,899,723,282,913,355,486,376,753,517,235,66,79,804,304,185,576,626,537,706,140,264,901,638,515,150,378,238,504,242,38,488,398,438,765,626,227,801,9,661,979,756,614,200,95,782,24,487,968,402,816,375,378,912,887,457,749,692,973,848,25,363,258,574,276,271,924,283,979,185,443,810,194,125,822,726,844,769,72,17,562,633,555,442,406,920,872,660,575,72,624,418,592,287,49,808,105,372,28,730,567,674,76,862,505,712,532,565,92,313,207,409,637,196,743,283,43,531,694,929,219,57,976,271,28,154,397,76,629,79,118,998,936,24,263,477,608,878,130,196,426,411,527,247,448,846,843,578,87,495,712,247,713,241,10,146,346,124,621,444,211,632,241,890,311,970,897,462,41,350,786,945,388,704,250,485,957,574,580,400,411,42,872,889,859,139,777,266,249,128,175,623,407,763,733,154,302,278,629,52,723,685,612,790,555,446,57,450,778,896,29,170,94,279,414,964,429,352,259,236,415,723,341,872,352,901,64,627,370,811,177,688,733,123,227,673,400,364,453,263,967,85,56,53,252,980,630,906,781,516,379,754,216,109,281,607,646,369,761,45,273,148,349,65,609,873,856,863,762,393,878,116,73,988,127,16,890,440,256,47,889,336,235,930,639,159,310,166,936,766,609,783,594,973,343,730,28,72,969,856,209,868,244,786,953,799,63,282,421,86,587,87,335,133,640,818,759,853,450,290,270,722,501,423,336,984,339,383,886,413,432,53,530,654,250,366,382,373,473,79,403,531,326,826,479,584,670,556,112,761,737,580,363,193,11,8,679,967,867,114,257,770,211,758,68,188,724,882,169,273,458,297,631,741,920,49,263,435,108,531,845,483,825,646,515,188,845,475,802,103,887,954,131,514,292,798,659,975,596,576,48,545,727,671,305,51,258,516,904,951,577,557,47,475,239,697,205,521,604,644,772,438,283,156,568,87,502,248,494,892,446,696,940,999,758,41,859,905,793,932,653,819,624,509,813,566,914,525,535,240,788,244,267,440,872,393,525,540,455,142,761,35,989,239,436,206,287,981,701,581,89,178,413,885,462,854,351,633,844,446,272,75,880,400,967,865,605,277,842,606,732,779,610,629,186,393,259,431,453,82,327,164,324,853,214,40,665,90,556,495,668,953,246,542,341,73,809,402,885,469,73,235,758,254,107,515,441,773,484,96,638,101,147,898,101,463,106,732,521,57,130,714,300,77,339,594,580,348,583,531,41,121,798,662,691,80,761,626,961,273,246,323,745,230,953,688,759,915,891,217,392,460,421,623,456,362,835,635,314,849,531,740,102,485,490,326,448,80,805,410,872,888,5,182,507,790,154,716,407,93,924,284,627,900,938,389,347,803,533,629,455,254,449,370,779,569,579,532,79,47,45,292,641,426,259,927,726,712,920,764,757,756,902,450,493,506,551,967,11,583,103,622,554,125,642,245,588,644,433,702,339,287,987,927,349,81,728,687,682,204,777,102,399,3,612,464,255,781,314,209,202,523,412,849,123,342,620,331,821,14,154,150,155,615,676,398,64,375,854,751,197,742,999,514,225,904,598,316,714,57,153,860,304,151,533,457,899,76,412,844,20,528,873,272,791,482,82,787,910,250,695,950,783,63,628,423,735,83,841,521,677,804,466,663,243,254,19,308,228,693,384,198,972,981,419,549,689,412,924,254,953,388,701,370,926,668,947,24,90,76,986,919,293,886,236,953,660,37,390,26,333,744,238,409,290,247,898,161,499,0,174,914,224,414,850,264,549,610,132,450,850,503,469,840,265,499,702,387,465,542,251,531,783,385,935,660,551,836,193,206,934,967,849,65,951,708,556,387,9,188,474,139,699,299,211,18,168,34,974,442,378,441,112,254,453,600,505,537,38,592,643,730,829,544,704,215,106,516,172,370,50,49,503,24,257,195,388,695,437,24,541,715,347,730,989,869,455,521,355,463,212,168,76,616,346,94,892,522,80,942,728,359,494,43,356,873,62,327,222,932,283,790,550,403,105,986,601,420,429,484,728,767,675,301,270,400,553,352,272,859,764,467,687,349,320,233,429,162,717,941,971,48,353,730,153,368,521,527,185,537,717,42,634,719,896,339,372,241,997,78,327,787,440,966,955,374,981,58,694,745,206,84", + "409,731,511,494,565,827,129,423,45,87,261,857,724,989,255,196,30,237,862,439,884,950,159,383,77,399,38,662,622,40,495,101,194,369,786,395,193,153,36,778,807,866,836,858,982,542,148,665,28,500,226,440,776,354,707,363,156,148,348,985,143,559,25,643,962,855,305,171,136,823,273,378,397,942,141,531,3,523,166,904,384,652,554,437,184,585,568,13,775,690,302,969,303,726,95,561,825,988,98,649,770,551,801,485,674,435,49,342,748,290,198,543,351,822,907,116,490,37,291,304,846,865,921,984,129,346,231,874,441,270,347,278,689,828,459,501,57,144,275,713,916,480,272,320,324,744,216,70,256,221,420,385,69,243,657,794,221,139,346,338,162,505,144,567,970,999,388,984,727,526,826,232,993,261,882,918,169,355,666,294,175,590,664,44,538,108,429,29,553,416,904,701,390,384,461,44,718,961,255,785,670,344,882,750,986,979,44,191,655,403,695,297,595,855,685,504,351,958,354,320,349,15,458,969,811,237,594,754,556,583,481,646,994,427,714,381,374,864,130,32,392,112,46,286,903,727,196,206,131,185,66,7,338,476,312,294,129,534,710,345,390,767,520,301,719,705,580,926,581,274,934,745,942,729,108,938,534,956,59,880,960,774,369,715,784,389,219,754,288,987,574,853,423,391,733,915,82,315,935,987,454,956,715,430,242,296,590,307,179,703,653,867,940,934,495,49,731,970,9,193,175,86,865,980,751,428,872,691,691,843,205,797,658,386,390,657,177,402,835,935,985,199,623,548,479,200,611,344,87,601,113,335,66,745,937,62,257,692,85,871,239,176,455,879,659,342,827,243,823,441,696,238,6,398,227,181,478,95,231,862,568,495,601,914,214,264,259,19,193,414,358,36,111,441,917,687,955,885,773,122,775,680,78,617,955,541,264,956,841,425,583,151,778,654,112,74,934,740,622,463,61,551,279,482,544,900,123,849,280,792,695,280,20,231,620,592,899,141,219,880,914,989,483,978,260,45,550,282,233,616,879,207,79,781,761,68,222,32,301,460,612,443,449,555,744,524,283,509,982,106,93,909,277,178,325,922,369,853,774,287,165,564,201,284,102,781,710,360,26,428,937,112,162,212,143,474,315,550,956,563,687,729,225,765,184,39,660,938,628,76,767,232,110,178,244,890,393,513,829,188,870,393,266,586,446,191,529,210,948,149,886,183,240,355,949,772,502,116,298,432,764,652,34,89,679,744,101,213,368,326,592,811,682,747,777,254,64,391,187,535,793,125,247,664,70,204,862,382,342,430,515,114,194,299,354,656,699,926,995,712,275,219,693,804,643,809,260,560,660,894,97,320,593,438,394,12,968,413,725,742,36,602,583,885,327,23,917,32,492,183,676,680,939,17,302,684,680,545,970,931,122,915,203,874,30,782,512,891,208,856,443,818,525,70,511,360,408,896,694,7,764,147,237,584,179,17,388,668,322,52,229,603,350,570,558,313,526,328,128,827,55,810,590,360,905,512,428,418,491,836,273,523,807,132,468,924,360,587,410,699,881,456,483,510,210,157,959,573,821,430,167,913,403,910,950,709,40,125,907,291,465,681,530,90,937,778,99,895,450,556,520,235,291,730,762,14,99,888,451,899,73,899,96,193,373,714,740,317,138,183,116,63,788,181,965,747,575,742,668,659,672,179,681,853,807,52,429,394,417,894,679,551,497,135,128,784,330,64,190,781,624,994,917,413,820,627,708,850,954,996,529,743,157,926,781,350,859,362,695,712,395,143,989,442,426,39,697,879,886,846,871,488,278,442,301,204,67,484,634,332,265,181,378,141,889,677,659,490,200,966,579,454,927,817,242,181,228,81,515,424,557,408,723,175,843,824,938,174,0,644,977,172,545,114,611,888,586,617,153,277,284,829,203,383,552,323,282,900,883,463,392,443,837,238,804,81,551,204,328,382,734,303,92,646,583,328,493,177,943,890,316,907,752,447,985,928,473,591,712,10,124,86,367,688,19,686,289,258,507,479,171,309,463,213,280,314,282,522,946,613,227,291,12,538,703,299,751,681,973,408,457,749,286,173,176,826,150,796,707,190,667,366,789,63,676,957,562,673,196,917,681,114,634,541,393,225,866,901,300,948,446,468,578,969,813,452,218,555,288,701,64,416,797,285,80,694,785,352,741,249,903,67,474,802,477,344,614,980,814,180,131,836,905,194,536,743,161,77,434,296,835,302,415,733,773,576,284,409,823,500,249,797,924,267,437,968,664,876,212,487", + "773,939,618,387,510,951,638,114,673,321,770,122,928,475,88,127,319,29,205,286,587,957,565,248,644,883,665,192,228,827,848,219,356,827,496,814,875,679,909,779,219,181,417,809,137,458,142,196,13,940,594,620,477,136,844,959,287,904,342,475,241,990,213,561,40,964,341,43,655,305,714,25,84,199,724,187,984,359,218,816,497,484,260,565,160,631,707,880,746,191,821,248,644,18,296,649,436,479,123,941,624,966,699,244,124,595,727,235,353,844,20,615,207,147,306,312,253,380,516,993,550,368,616,224,296,524,493,33,954,589,176,745,845,619,451,273,560,468,873,601,342,685,405,754,406,543,378,738,217,420,845,320,557,552,556,872,109,920,120,726,920,921,611,9,398,751,783,18,971,665,978,379,320,667,881,762,553,15,228,418,563,233,76,623,901,95,782,598,539,123,434,640,641,853,715,90,888,888,68,970,670,471,558,745,205,967,564,757,992,888,410,79,862,1,863,316,725,246,245,579,489,650,81,180,744,933,731,526,535,313,25,202,979,180,628,378,182,699,367,407,617,484,382,697,463,505,765,622,455,792,584,329,55,793,494,19,281,315,168,91,218,237,235,914,529,706,313,452,382,645,718,515,841,680,214,416,840,727,673,222,419,494,258,408,498,541,311,838,597,139,846,362,722,774,405,228,81,386,108,589,306,56,797,467,90,48,539,924,126,164,179,266,749,595,309,852,699,129,986,757,297,731,435,449,977,81,849,520,828,778,181,474,920,719,63,888,299,88,55,258,548,298,151,747,158,668,721,200,430,558,464,611,402,641,886,588,90,723,285,304,175,780,874,415,134,861,224,388,867,241,429,223,201,209,851,102,933,808,564,728,999,101,800,682,763,834,258,683,192,491,721,43,21,347,550,726,809,236,364,93,746,273,127,348,629,339,220,940,374,873,136,815,463,856,278,148,430,62,296,654,955,71,967,854,624,785,453,612,914,895,778,602,182,291,662,588,301,710,260,531,294,191,39,35,267,923,419,440,468,565,658,710,560,561,446,200,278,439,388,306,559,40,206,978,416,207,433,111,463,47,612,757,662,920,805,276,897,530,686,344,347,174,671,617,876,994,56,745,861,682,582,67,361,264,119,794,780,185,612,26,300,638,663,64,983,522,31,779,161,462,996,347,363,614,488,80,416,575,177,286,593,330,568,244,592,266,187,14,892,997,149,455,423,485,509,387,38,947,92,926,823,882,708,595,722,810,705,119,41,963,345,765,486,301,107,800,487,608,591,185,128,41,25,974,986,549,644,376,167,397,637,714,560,768,826,334,48,628,406,351,864,736,59,106,398,937,518,725,539,41,455,947,32,158,253,488,257,563,425,776,771,124,143,73,577,670,913,306,576,764,157,102,526,928,350,274,75,997,796,455,837,463,358,563,879,650,297,292,847,791,741,713,96,296,755,567,469,562,341,636,57,915,150,510,235,359,949,753,532,781,44,381,368,326,7,163,678,507,790,864,193,460,793,539,413,256,771,349,518,374,683,783,64,584,715,78,577,145,504,501,365,382,437,273,222,665,902,171,303,463,59,919,887,58,882,497,568,998,71,927,288,692,495,709,597,950,803,616,424,353,831,180,552,791,798,933,265,800,453,663,629,742,882,725,790,691,436,672,821,882,569,540,65,105,502,756,420,805,866,789,722,371,25,139,811,534,48,475,979,886,712,503,176,267,224,193,569,708,687,639,446,871,415,80,164,206,322,721,783,661,707,645,697,211,504,652,328,501,395,182,547,855,142,350,338,871,271,262,989,921,788,533,139,150,282,190,646,146,137,695,284,189,200,99,519,786,589,999,878,932,333,188,444,55,854,315,550,196,510,6,194,154,466,578,653,813,348,914,644,0,845,135,945,659,791,103,839,224,860,1000,553,895,107,451,439,960,183,215,72,71,570,194,458,215,433,319,408,840,733,821,174,540,64,886,91,268,109,837,889,473,48,953,374,832,982,682,442,185,787,722,912,959,23,153,501,918,47,705,207,219,268,978,647,749,305,548,680,829,814,531,259,315,933,280,275,360,198,203,373,392,344,220,375,937,175,775,926,847,378,913,356,745,968,651,754,98,813,831,813,142,75,407,73,424,341,906,765,96,967,868,230,274,711,832,440,242,84,868,532,625,799,713,84,962,835,757,918,144,593,962,59,465,93,648,755,191,221,484,228,966,450,5,704,729,704,778,977,77,21,412,728,777,433,455,257,326,306,587,938,701,347,905,817,309,712,151,402,7,671,316", + "356,960,766,644,804,762,642,114,814,859,834,400,953,495,356,906,605,119,448,341,494,397,779,742,394,87,927,123,321,629,607,108,594,740,470,293,629,664,696,363,440,294,535,988,834,196,445,504,384,922,403,870,358,250,942,821,984,530,34,792,591,32,175,667,428,941,820,973,219,467,286,90,554,253,383,30,561,988,926,285,64,335,214,916,976,661,633,916,217,501,76,720,54,184,377,129,684,331,355,74,285,543,115,304,722,799,760,689,569,703,935,898,709,438,210,864,342,795,755,575,821,886,355,281,107,225,364,73,962,496,90,144,572,366,521,546,420,806,616,706,652,212,247,479,554,630,257,759,8,327,259,418,664,11,128,148,865,198,246,543,832,806,270,353,36,562,963,22,916,138,19,918,103,737,221,669,240,117,699,781,565,318,783,814,199,137,52,820,751,565,215,274,128,480,651,12,779,438,481,804,867,755,757,356,949,876,597,376,328,725,887,767,58,276,678,530,414,529,410,593,350,179,962,755,478,366,190,104,608,177,629,751,837,956,328,909,74,139,729,895,651,623,491,316,279,72,562,147,573,369,413,685,942,827,671,842,306,72,684,999,159,521,134,384,357,752,679,783,158,479,235,551,644,388,161,545,456,783,510,195,78,499,872,428,111,366,791,360,195,973,950,402,448,877,715,367,665,456,612,242,41,312,573,721,766,579,194,197,812,19,702,415,319,619,895,409,998,337,581,747,32,867,354,98,181,794,303,565,616,309,459,466,947,588,24,976,20,521,832,971,645,307,468,442,410,807,770,347,355,459,891,78,751,268,507,184,690,184,365,827,751,224,298,611,913,147,746,932,39,18,306,785,731,112,775,388,24,223,949,610,549,522,175,955,973,109,949,510,796,237,598,47,423,721,195,16,516,366,248,940,28,901,626,221,904,319,33,282,113,155,178,722,174,465,608,382,276,731,115,47,632,34,664,43,893,912,331,325,136,919,494,22,606,467,30,323,837,718,92,306,344,440,112,6,160,485,664,874,499,439,713,779,671,105,706,465,88,975,457,166,444,991,141,443,69,199,561,888,782,500,790,183,36,844,272,124,697,616,697,354,311,149,193,387,459,169,472,252,813,944,985,722,309,597,153,471,440,123,971,807,450,436,736,803,141,994,629,195,578,694,473,581,793,88,522,539,413,69,627,131,505,306,743,281,96,815,928,372,266,979,693,452,312,850,221,728,445,85,255,661,905,461,122,804,598,650,334,515,179,502,937,262,775,324,179,338,602,511,281,173,747,77,252,994,848,970,633,176,213,960,474,537,133,815,480,121,16,742,997,627,374,505,388,783,547,567,380,209,172,992,524,526,14,782,601,562,582,942,427,217,489,487,61,541,677,954,835,785,484,360,486,387,856,545,335,567,965,914,861,874,491,250,439,702,197,286,384,552,457,745,346,401,490,528,405,185,491,376,450,696,481,573,181,64,588,429,652,888,644,382,521,927,805,995,332,902,540,670,795,39,57,260,217,136,9,87,948,908,226,144,88,8,13,992,615,665,193,911,913,592,333,982,668,736,968,490,236,243,838,355,638,63,496,415,294,737,171,472,627,55,227,704,769,733,255,779,881,357,678,264,774,341,468,434,911,484,544,182,547,723,694,545,19,777,221,358,355,515,636,265,35,859,96,311,279,873,234,82,789,483,747,926,549,981,557,405,938,800,660,430,666,591,22,251,239,27,596,960,252,714,690,578,612,261,85,929,423,988,927,359,37,849,364,846,590,376,478,930,667,708,975,261,484,834,606,722,123,648,775,913,246,616,776,846,829,427,601,415,144,164,62,616,530,240,590,552,937,209,67,291,860,524,716,655,896,996,63,991,461,500,667,573,193,602,37,827,447,224,977,845,0,427,421,564,285,499,634,567,738,182,305,865,280,789,906,364,246,185,407,225,713,32,284,281,130,875,662,219,395,569,337,373,315,247,975,735,141,33,737,261,32,390,237,721,401,316,198,822,451,552,41,421,86,707,573,438,147,439,904,887,925,291,390,178,810,384,143,975,137,454,197,198,443,651,91,569,910,902,272,341,200,418,131,332,342,262,263,747,228,341,653,560,768,143,581,328,339,155,280,480,679,149,659,231,510,324,136,899,371,333,565,908,495,704,37,478,427,880,498,723,166,694,553,223,266,29,934,894,157,605,727,455,89,186,30,551,901,114,966,503,687,45,609,797,927,194,825,191,413,255,107,102,564,377,445,726,955,461,462,658,246,143,441,773,6,869,973,162,281,818", + "890,571,232,66,90,679,914,875,924,363,318,608,555,47,153,654,631,598,107,563,71,43,451,203,352,883,110,841,579,435,402,773,220,119,629,419,731,38,569,635,673,752,278,861,544,204,143,250,472,184,811,430,741,656,138,442,562,590,592,833,746,818,952,100,569,649,209,912,40,998,879,44,326,247,800,878,931,59,769,575,883,571,705,856,119,446,488,974,685,784,357,439,266,590,382,677,795,448,79,943,576,398,636,569,663,180,623,292,234,230,140,534,995,715,356,888,361,401,409,712,305,663,33,495,539,899,599,689,632,195,584,782,775,645,123,797,161,463,519,81,480,410,143,549,240,183,468,574,447,497,490,915,935,150,899,543,969,330,377,751,12,304,806,958,443,177,669,655,964,55,444,154,575,708,634,129,971,297,920,28,40,574,447,725,752,321,623,432,322,737,166,761,678,432,531,320,944,855,371,219,595,680,531,222,104,665,418,862,606,812,258,666,729,454,855,591,132,136,766,205,915,450,191,122,404,207,819,758,941,913,22,28,172,596,213,722,622,845,886,648,343,844,321,452,497,288,551,619,566,857,606,114,873,264,488,270,472,878,204,19,659,13,396,710,174,188,393,886,866,339,786,385,239,680,72,379,286,328,430,703,890,813,460,674,774,769,464,482,565,557,30,151,974,679,974,398,820,897,487,465,534,749,739,61,733,823,371,636,596,168,599,338,248,533,100,379,773,218,910,101,498,840,238,721,668,873,89,99,987,502,693,994,181,823,59,899,604,537,664,208,816,567,965,989,496,733,775,991,229,786,245,554,806,638,601,625,912,875,81,296,476,877,333,386,233,96,377,613,42,216,731,886,178,850,365,515,567,397,63,860,660,208,329,863,841,868,92,450,701,89,6,727,183,100,927,198,949,188,675,78,884,379,345,423,962,974,563,591,186,866,225,220,329,576,210,1,708,135,234,619,927,593,541,339,306,602,777,621,884,560,18,232,697,113,879,652,137,804,958,376,983,184,43,48,963,300,372,775,816,498,81,328,647,419,783,806,778,151,768,525,798,620,447,108,269,807,149,666,323,546,773,897,234,547,487,943,295,137,242,674,847,208,499,307,915,163,214,427,972,755,291,636,459,631,620,972,563,964,611,518,166,657,351,82,147,68,225,685,577,939,671,330,131,465,974,639,345,155,957,707,329,323,935,599,327,89,746,994,39,680,422,671,51,436,675,163,205,481,972,783,497,511,129,2,876,265,147,327,849,306,148,507,555,675,524,652,629,917,639,972,850,713,880,369,805,273,691,445,577,247,936,899,338,280,654,973,828,544,918,258,489,167,760,116,514,150,358,166,917,887,504,511,718,609,647,695,437,825,143,783,767,617,765,211,48,728,405,895,40,810,707,212,293,801,483,668,700,652,567,398,259,538,193,507,106,706,985,267,4,323,220,922,788,154,541,890,58,401,573,162,5,244,303,660,205,485,132,162,281,751,628,950,58,601,699,948,12,425,753,614,633,478,799,889,31,44,819,975,307,419,228,954,931,868,431,593,434,78,737,855,170,367,528,865,897,378,710,684,542,909,738,122,370,439,80,161,618,392,605,621,394,564,576,596,324,753,302,555,11,797,917,419,488,734,487,917,727,597,611,50,563,110,588,287,286,164,943,598,222,103,982,993,155,679,306,494,810,821,155,408,403,855,23,689,742,611,485,286,339,314,1,312,82,725,616,111,592,950,830,843,830,271,262,798,744,8,888,652,97,573,24,627,376,889,771,406,594,124,18,149,646,387,987,141,636,156,36,418,721,547,434,697,339,670,459,218,509,836,62,838,460,373,337,168,413,899,460,754,46,515,50,565,703,978,692,375,310,67,333,73,311,677,671,335,620,466,503,414,172,135,427,0,616,998,885,816,677,94,870,131,138,831,989,552,837,703,296,171,57,161,654,610,192,867,24,846,923,47,342,28,707,733,930,707,745,714,622,768,68,358,456,65,527,252,163,921,908,598,265,989,783,838,492,820,946,461,101,72,517,884,342,823,388,183,271,553,524,68,916,529,530,637,929,152,496,153,605,509,986,115,25,529,950,97,927,615,964,752,2,278,384,199,826,500,313,50,38,668,593,924,850,32,706,724,794,181,235,777,815,369,8,724,358,889,417,10,774,997,142,752,504,307,977,841,54,890,19,419,343,758,106,817,978,424,807,188,984,800,468,745,804,538,911,935,429,270,514,527,344,651,676,349,543,935,435,432,171,11,978,450,235,819,225,209,94,429,399,991,690,608", + "170,430,239,219,290,837,908,963,838,180,217,818,453,885,785,850,613,340,317,338,176,313,644,828,443,189,375,483,761,257,700,705,600,646,150,936,475,260,450,720,369,121,346,763,128,795,686,429,176,222,565,906,593,562,648,183,590,156,288,49,681,191,774,812,725,774,424,869,179,294,510,610,826,528,358,716,703,914,142,804,835,29,673,804,276,364,209,758,757,105,587,46,196,44,693,944,318,343,527,491,850,133,304,914,583,353,682,221,135,665,93,535,301,578,264,855,498,347,358,978,206,9,60,879,258,230,83,25,86,306,973,741,241,957,563,143,437,983,181,355,319,996,948,596,217,604,719,104,887,100,617,161,356,601,502,705,720,727,443,30,684,120,117,89,453,297,578,315,111,648,643,545,326,371,421,667,297,837,360,856,787,551,589,587,413,562,249,223,747,193,830,120,874,333,859,347,761,917,639,230,887,765,252,842,300,859,794,457,761,726,213,331,808,786,676,619,972,188,213,421,685,281,220,924,220,528,997,24,973,975,347,281,89,302,516,47,390,434,543,248,779,13,453,367,805,978,973,239,777,950,268,462,731,235,839,264,110,476,847,630,482,459,215,202,66,868,236,200,606,99,928,225,622,262,902,208,159,604,881,588,998,187,967,32,778,631,437,587,77,657,900,98,842,47,738,543,805,166,749,354,874,231,42,744,440,165,808,623,390,733,831,117,462,556,691,711,738,395,768,456,286,895,523,714,958,877,470,624,89,776,602,285,626,314,801,196,511,624,915,531,486,614,923,390,948,655,233,72,332,766,715,508,637,508,897,555,427,187,243,655,808,578,426,556,591,165,653,564,5,84,839,459,467,425,578,690,246,281,623,829,171,996,308,72,875,775,993,845,378,364,581,752,798,172,225,113,301,627,396,157,850,598,481,928,299,957,694,192,958,214,47,907,582,453,5,519,552,870,638,818,128,109,76,948,369,104,96,170,892,881,166,682,4,169,686,911,212,469,99,892,964,627,908,906,270,980,314,56,930,601,638,368,708,358,186,392,834,666,614,489,582,317,675,311,760,648,358,494,969,788,629,730,288,720,911,299,847,548,482,962,141,531,14,7,142,736,847,874,530,557,979,201,416,216,986,394,144,381,774,987,611,747,529,573,684,667,925,294,736,328,695,657,792,169,305,134,775,860,852,985,138,100,705,292,371,215,343,864,756,86,953,28,259,298,117,236,735,970,4,626,857,844,662,924,921,740,929,382,512,124,101,204,846,719,151,224,439,885,639,392,382,486,407,761,231,960,208,273,114,616,595,622,639,215,910,186,140,358,432,473,151,423,879,12,668,931,159,539,712,60,866,788,530,92,108,185,785,455,216,281,930,857,843,564,195,160,41,583,303,939,465,164,290,571,278,835,195,411,74,82,563,539,222,629,722,221,386,864,945,215,515,234,92,24,983,190,994,895,640,735,567,773,135,69,730,115,305,362,731,827,756,943,485,413,848,680,346,603,871,308,813,194,209,176,340,993,917,965,41,279,956,588,636,186,35,823,678,544,239,596,918,921,36,247,642,851,932,214,407,700,563,405,467,519,909,232,353,336,164,508,582,851,132,280,74,541,426,67,835,496,674,656,146,181,778,311,198,219,911,677,94,170,597,137,293,215,911,961,402,99,750,904,595,934,468,414,723,46,615,805,953,508,719,146,176,161,461,421,194,464,780,278,660,634,371,595,566,136,668,123,147,429,752,500,217,607,98,160,265,447,435,521,145,535,454,796,271,964,720,545,20,978,112,413,790,903,470,505,428,827,922,186,502,846,929,550,636,113,617,847,365,750,567,859,287,447,24,273,91,827,694,908,207,547,539,105,77,895,641,914,355,470,9,918,657,584,26,850,545,945,421,616,0,131,138,779,305,732,540,722,780,724,691,938,283,465,355,608,420,455,470,965,221,307,741,749,167,123,153,574,901,388,740,656,157,126,724,521,841,101,447,729,561,877,489,898,893,827,363,966,319,711,964,834,825,806,845,90,39,646,2,454,726,477,989,726,782,132,484,663,526,684,864,378,183,838,757,523,344,360,217,865,487,984,144,127,61,801,328,972,425,227,706,825,559,632,630,123,826,204,654,835,725,889,733,948,785,581,495,892,299,682,999,52,988,959,266,581,159,386,950,204,201,965,449,693,513,348,131,571,11,450,702,671,950,786,137,296,828,436,533,474,187,911,666,915,320,508,8,706,173,822,137,252,110,656,637,625,769,616,182,411,399,15,209,312,386,306,507,310", + "201,280,591,333,221,892,880,88,324,204,435,644,604,878,402,426,605,402,485,65,748,902,360,72,669,432,422,165,637,140,615,283,153,155,582,599,633,597,682,222,582,143,445,982,550,714,437,948,414,425,435,166,656,184,850,535,279,890,637,993,455,181,972,961,481,353,743,149,228,607,731,747,456,498,813,780,616,485,15,346,177,557,697,721,693,72,213,728,180,671,919,771,353,998,661,328,707,226,758,258,270,866,171,404,873,891,824,707,572,690,117,936,641,372,889,256,127,293,803,528,215,466,205,270,570,83,298,973,311,989,840,274,72,745,658,120,24,201,241,35,319,305,287,593,832,790,445,706,908,136,292,401,145,564,577,28,341,421,396,623,396,139,280,803,77,253,543,570,618,250,207,392,146,355,346,749,254,684,208,196,339,866,340,976,99,492,919,825,44,839,887,157,257,32,773,548,397,884,969,714,402,591,504,400,183,793,153,494,40,706,184,570,924,565,417,52,973,614,354,257,55,395,211,982,669,614,78,236,756,916,931,93,293,680,785,232,791,145,384,634,892,675,218,585,90,381,971,583,932,256,432,388,48,217,970,636,526,746,1,274,557,615,865,95,626,968,710,67,166,323,912,512,579,65,267,273,990,297,808,22,61,277,153,164,206,921,930,732,850,628,521,940,80,194,456,974,343,655,162,355,989,928,249,879,338,393,70,511,49,410,120,397,509,983,825,457,940,350,894,443,913,321,209,556,981,541,214,552,170,215,117,77,883,338,534,992,113,467,513,861,198,938,55,893,251,47,325,47,465,391,382,562,746,998,367,820,916,483,671,183,166,633,247,98,948,337,145,489,287,604,485,656,841,17,431,394,661,644,515,643,319,531,949,640,89,367,203,154,29,11,512,81,356,638,920,935,107,304,988,350,593,984,493,613,440,666,366,331,879,796,678,602,105,755,459,127,258,476,323,877,905,548,931,268,615,274,322,32,772,155,653,279,342,592,709,987,852,847,797,443,410,265,389,328,673,23,638,704,290,690,7,710,413,662,66,428,268,89,50,910,982,574,244,460,632,867,280,424,222,932,288,934,51,601,695,755,679,581,862,970,854,33,811,866,239,937,739,322,795,812,249,635,277,938,126,699,92,380,60,314,719,70,431,256,560,394,39,734,173,928,785,40,542,892,973,461,954,105,150,490,132,967,235,822,98,514,120,780,497,712,832,332,848,875,237,703,672,454,732,172,287,724,751,841,89,462,470,95,362,269,463,756,593,505,988,87,345,440,231,532,246,243,428,50,447,864,546,851,735,402,649,729,869,128,660,505,288,701,864,803,792,581,589,59,874,311,678,445,359,968,607,687,872,28,202,955,698,897,366,5,575,271,577,340,179,673,412,869,434,110,869,816,474,938,287,253,861,568,392,142,184,514,715,435,120,508,158,38,19,409,368,505,26,767,607,158,339,217,391,744,125,823,604,690,72,667,230,34,879,88,946,684,516,348,628,31,918,80,553,288,727,575,546,908,952,334,826,410,104,635,462,749,181,853,887,385,623,736,799,396,844,551,864,457,682,936,453,864,821,266,496,953,616,320,909,144,846,101,935,976,778,626,969,69,999,422,29,305,888,121,422,551,937,16,87,698,620,676,455,21,379,662,992,642,358,213,77,272,923,189,833,233,891,352,112,573,896,660,473,974,863,734,635,164,877,274,778,435,449,616,875,351,13,356,231,468,407,40,748,583,779,833,656,802,608,230,452,337,137,386,311,319,419,834,488,150,618,369,422,384,4,159,390,14,667,201,870,965,551,126,604,249,986,332,963,405,255,849,459,489,684,119,889,10,363,609,713,257,310,502,699,873,705,436,276,141,886,558,741,271,852,579,714,608,831,832,147,264,114,659,564,998,131,0,2,338,778,621,543,113,527,452,327,13,387,937,802,931,781,677,132,751,613,922,966,831,314,860,715,919,551,492,541,704,918,471,959,674,298,951,743,601,977,86,411,265,62,609,191,108,334,505,258,301,52,725,169,604,518,276,812,692,455,436,781,683,507,536,592,904,43,117,789,375,775,827,366,790,109,418,359,594,64,966,128,272,808,267,966,318,974,397,917,346,920,765,792,515,926,764,47,373,889,581,18,559,387,102,449,116,461,228,72,242,177,467,517,173,989,171,125,138,191,644,833,947,85,258,909,838,214,261,341,293,59,774,740,201,486,647,253,262,277,31,949,515,535,826,153,486,616,423,244,835,827,903,636,649,270,179,239,760,849,59,415,242,74,458,603,789", + "815,976,556,87,926,640,163,645,994,535,235,319,205,650,488,710,893,346,816,381,618,367,940,32,793,74,698,478,854,176,126,946,194,543,345,5,284,595,194,817,356,348,222,616,59,772,40,233,496,445,783,85,840,456,494,835,775,357,49,892,361,578,115,753,596,817,25,576,623,824,303,348,71,923,368,337,890,370,21,205,981,454,560,260,953,395,159,761,453,439,855,647,571,793,35,535,860,533,413,14,113,710,759,355,757,67,69,197,386,258,671,273,778,737,508,147,735,354,283,21,292,250,657,810,246,945,536,168,674,881,701,64,703,274,727,272,16,506,148,395,48,433,979,475,324,643,406,942,746,680,71,77,511,238,383,899,390,977,499,954,989,70,756,688,298,730,530,398,111,466,820,759,563,509,881,196,400,868,477,658,821,658,198,198,236,216,120,152,963,977,718,162,149,772,958,619,562,138,278,741,423,551,189,433,862,385,104,748,698,887,473,262,384,264,9,329,207,871,58,251,279,139,477,241,734,682,189,117,835,790,991,122,46,874,575,731,258,859,833,19,758,89,98,965,814,8,924,941,100,898,474,718,490,646,7,79,616,468,348,148,777,785,12,978,808,25,837,949,555,635,16,190,811,38,263,526,515,226,24,915,190,257,870,994,882,244,58,387,984,259,627,735,948,489,187,245,901,610,899,413,726,303,405,544,769,68,840,127,939,72,283,213,815,960,299,922,929,713,792,433,452,727,651,374,445,176,811,874,662,676,294,598,875,750,326,356,304,78,330,91,6,247,363,586,959,944,580,985,930,799,774,429,575,69,170,276,110,707,993,692,447,373,784,954,458,736,601,284,66,633,885,114,123,910,601,284,901,982,419,706,973,156,895,289,767,216,609,22,769,914,945,158,935,455,770,531,938,552,146,634,95,533,744,598,452,573,838,385,100,515,602,458,589,450,233,236,417,339,742,580,47,928,668,179,290,724,894,859,520,392,64,496,805,712,938,276,446,274,814,715,234,166,984,113,154,984,59,219,845,601,449,55,414,920,928,791,961,562,921,361,587,84,912,711,56,119,586,701,71,719,886,800,499,800,752,215,863,829,206,299,477,787,170,502,857,385,125,31,306,932,717,952,910,718,742,360,183,374,489,555,385,303,406,77,328,200,107,12,444,246,695,974,912,133,756,538,492,24,294,120,892,701,412,681,666,38,677,758,337,225,187,918,227,582,575,125,728,336,14,257,932,212,100,627,941,358,395,696,670,559,251,565,434,946,401,750,806,822,16,251,316,201,981,358,58,892,436,274,545,591,543,346,187,705,248,562,880,502,224,174,581,590,770,276,215,653,103,299,837,394,151,464,412,359,237,212,7,472,661,467,228,773,628,806,87,410,993,416,297,581,408,306,793,952,155,570,119,218,302,908,799,147,882,180,746,844,93,96,183,144,900,650,774,161,265,473,146,463,89,559,172,618,63,51,140,523,734,524,748,932,772,109,519,995,39,749,223,877,792,637,218,949,584,627,589,231,70,98,231,514,357,770,338,476,780,258,961,352,327,716,771,149,59,592,989,864,273,720,9,593,147,564,630,172,323,266,32,319,517,909,573,388,958,405,808,371,164,171,730,173,202,211,238,111,596,231,389,158,259,844,744,755,228,512,751,511,435,323,391,565,552,487,110,112,993,908,164,556,390,703,50,381,215,145,152,627,90,554,446,717,14,295,52,5,52,595,170,394,112,481,780,201,875,688,933,881,763,38,188,381,618,31,785,982,777,169,970,471,106,331,78,399,431,104,756,498,332,750,141,318,581,167,46,527,166,804,148,107,735,887,837,110,911,234,15,586,414,17,724,37,158,752,877,559,910,954,745,644,918,681,978,780,277,894,438,37,360,549,611,791,285,885,138,2,0,858,284,380,721,344,730,214,990,479,398,830,978,973,752,826,507,264,603,176,246,365,813,604,903,954,153,957,97,528,857,164,460,474,361,370,759,238,113,75,891,430,777,369,156,723,46,973,184,537,220,93,301,511,671,344,643,548,514,39,747,713,786,956,884,703,863,193,23,78,526,778,493,485,811,897,156,958,286,879,388,779,427,592,754,576,193,295,229,600,456,595,976,746,903,58,993,728,433,59,990,349,944,314,924,542,277,458,553,953,324,828,927,51,507,802,692,63,533,796,662,446,766,905,490,721,493,120,995,279,975,115,552,786,314,605,602,978,507,13,60,358,581,828,936,157,451,432,945,919,748,172,377,319,464,946,777,172,650,7,51,468,105,180,417,288", + "931,144,351,427,273,722,240,482,837,931,185,198,397,296,137,33,652,914,31,971,787,537,678,949,217,703,291,945,928,426,825,813,892,817,915,283,514,664,977,637,733,546,613,919,567,417,885,337,360,285,418,373,642,342,541,694,775,390,275,630,759,350,846,984,476,92,755,673,893,569,700,610,138,842,953,163,469,843,981,233,735,164,517,25,391,613,246,107,662,827,60,426,764,275,790,214,195,820,73,171,497,444,451,991,479,992,482,609,2,97,378,102,537,594,38,521,892,782,875,768,968,958,993,882,173,354,212,127,682,242,913,976,128,594,527,120,691,926,540,644,815,512,308,238,31,973,748,693,444,84,862,763,269,349,526,142,247,511,451,172,943,328,599,993,839,68,155,954,257,932,873,799,705,753,416,753,669,88,529,444,851,206,392,935,55,911,571,202,28,234,206,43,516,192,346,18,711,586,426,9,921,78,504,271,561,914,247,546,400,897,747,3,732,304,696,989,786,475,797,295,407,508,169,724,391,390,270,104,377,830,392,747,238,324,787,778,340,691,51,443,48,813,112,134,778,767,67,522,694,94,712,259,165,609,693,977,332,47,369,550,965,728,275,250,103,348,89,702,5,137,69,317,320,830,707,38,776,451,491,306,430,815,155,807,637,959,797,610,943,541,667,746,271,396,616,458,960,143,26,207,521,967,489,559,94,159,67,894,76,244,367,640,20,721,557,908,113,712,626,592,597,184,475,89,770,947,437,132,804,374,364,751,57,121,687,756,204,72,858,858,871,426,20,851,569,781,293,506,41,152,550,129,714,158,747,982,856,583,355,964,493,732,133,226,235,493,242,302,660,986,688,637,848,828,248,512,461,508,315,210,505,812,4,404,164,871,943,680,46,574,967,285,244,704,852,479,916,230,601,651,304,32,272,690,803,638,603,412,843,294,485,65,816,244,963,996,267,36,397,298,543,603,703,527,994,157,523,721,246,882,498,973,863,385,938,58,804,980,202,84,602,299,882,743,767,608,574,192,737,973,620,528,887,719,602,363,765,117,626,426,527,402,699,670,236,67,52,577,202,171,217,113,500,363,517,904,689,205,68,744,185,430,437,158,823,791,378,284,883,392,383,432,988,833,349,591,428,94,173,408,706,793,614,247,261,797,833,587,325,403,653,635,351,54,162,543,790,547,400,938,263,113,370,901,924,286,734,37,780,768,396,647,922,568,205,309,546,553,442,796,189,941,909,284,895,911,326,162,585,34,358,254,683,34,15,760,967,83,272,272,151,50,711,589,279,851,653,41,123,226,9,837,319,5,275,453,747,574,380,160,674,86,624,326,522,464,547,582,86,334,63,393,975,391,590,12,736,157,981,10,143,50,477,180,200,639,344,449,301,438,893,213,335,559,799,100,900,251,579,5,923,171,536,461,758,376,177,147,916,637,207,690,623,829,586,65,333,869,482,461,127,559,25,190,597,907,95,598,780,428,581,924,361,436,275,426,688,258,334,996,334,329,170,13,277,708,116,965,731,338,689,478,157,291,247,67,454,347,224,786,484,243,146,500,15,443,557,380,631,80,755,127,916,938,401,629,346,925,252,882,117,748,833,619,461,237,133,246,493,92,157,629,118,230,95,634,695,639,855,967,229,203,602,447,676,768,211,523,928,35,137,136,156,67,719,437,25,754,606,189,448,703,771,979,213,669,905,619,897,581,881,757,529,66,985,489,105,820,807,288,946,584,396,711,367,949,21,638,246,35,684,401,69,426,490,758,714,790,582,370,16,331,29,740,216,813,383,106,866,643,701,78,686,262,412,871,165,673,675,990,761,780,933,528,464,968,34,741,527,813,697,498,181,72,72,870,616,817,315,651,475,437,572,237,602,54,775,610,888,103,499,816,779,338,858,0,323,768,674,730,174,480,974,259,600,296,231,963,531,642,192,788,5,505,737,585,817,446,665,56,935,110,878,304,612,428,245,361,719,229,708,67,956,413,51,376,117,180,550,856,883,58,491,94,148,916,336,260,637,814,708,16,199,115,136,353,981,647,133,506,691,466,67,54,475,251,629,580,683,163,107,300,377,87,845,808,206,546,183,616,592,154,931,393,18,427,148,658,900,501,825,532,208,462,644,152,12,661,761,677,527,717,215,581,910,74,844,676,51,869,664,846,897,88,692,346,485,779,794,317,810,432,712,685,614,866,91,860,128,40,129,395,495,795,369,354,184,291,10,985,798,327,315,850,358,159,966,392,161,251,960,942,357,590,524,332,326,5,308,818", + "486,894,839,163,147,154,558,717,758,77,571,81,864,490,781,556,658,663,744,797,555,310,342,174,100,634,279,711,627,224,336,974,540,557,708,112,690,947,447,63,732,135,864,847,481,72,938,794,166,593,5,143,127,686,801,684,750,624,243,369,197,692,356,945,394,847,889,319,651,895,809,762,911,157,348,604,574,740,719,16,688,642,576,163,680,167,233,922,546,511,577,56,549,669,446,410,324,679,129,976,91,691,568,183,50,945,128,463,842,486,800,999,695,511,80,834,493,316,628,322,503,132,934,459,908,918,25,199,426,271,260,221,736,505,312,597,906,329,649,192,753,129,359,850,299,388,76,174,463,227,47,294,831,848,301,203,919,836,737,433,68,732,607,700,938,65,667,968,789,658,708,861,984,291,91,332,762,50,652,220,829,378,328,393,277,809,906,996,551,580,733,329,920,442,506,454,778,334,241,132,296,427,163,580,557,841,363,22,47,551,216,860,614,172,458,188,850,685,235,688,641,66,672,892,836,248,879,119,869,854,395,825,659,546,305,986,320,724,941,395,610,998,416,864,30,279,721,127,409,285,647,367,819,486,289,125,30,276,997,341,284,252,132,601,9,801,425,697,307,273,320,120,844,987,465,275,242,725,846,838,577,912,908,28,502,698,344,577,512,591,27,93,78,414,76,591,141,900,292,491,748,390,136,205,549,17,483,548,365,762,643,626,121,114,593,37,836,226,624,146,428,193,925,866,907,226,430,741,162,305,53,273,237,238,784,935,921,994,548,798,696,467,570,448,407,327,954,869,993,263,378,363,32,92,655,900,480,894,498,918,986,949,747,724,514,581,75,475,337,161,170,947,153,114,64,672,186,616,487,592,274,505,770,144,3,251,109,218,518,143,689,17,574,516,140,933,985,406,980,839,503,11,381,110,409,230,382,126,758,19,162,501,448,150,553,341,90,427,154,998,639,744,917,244,463,829,564,618,659,501,356,169,981,219,29,894,916,280,149,836,491,696,619,313,712,963,976,111,438,61,663,889,740,972,550,199,255,426,377,950,802,784,210,339,558,316,793,628,829,141,343,715,372,427,165,668,919,988,107,757,923,876,336,321,905,501,727,215,581,847,480,692,211,410,45,388,932,745,431,373,524,525,503,88,826,130,391,175,21,942,832,327,256,237,705,86,33,416,773,257,215,28,146,972,601,620,993,75,221,175,36,730,845,893,616,955,487,540,643,922,580,830,435,473,794,843,554,485,738,460,957,841,244,630,363,459,768,89,43,216,80,780,714,153,373,676,931,610,392,448,652,565,62,673,898,812,553,354,190,677,299,298,190,468,478,983,387,13,64,245,220,796,985,918,23,369,912,637,347,620,731,859,443,789,992,295,948,712,5,971,404,241,138,394,379,226,625,341,584,119,453,739,583,51,199,295,238,483,968,246,761,223,793,83,776,762,210,271,772,666,38,327,309,595,171,149,183,363,671,532,586,895,711,344,99,314,268,779,299,195,996,311,738,109,938,95,344,545,977,244,399,318,622,581,623,372,568,798,197,656,529,633,38,788,329,14,750,740,334,649,45,687,141,530,558,944,984,930,419,902,314,464,603,26,328,864,974,350,457,615,852,857,167,203,799,626,843,281,447,758,483,547,895,753,750,599,424,586,578,685,723,508,700,934,666,234,249,704,813,699,343,165,475,77,879,943,49,440,396,728,724,125,714,984,552,269,345,508,25,143,805,991,330,387,410,206,654,494,525,279,786,386,627,847,522,422,409,226,194,402,829,86,92,621,100,928,431,640,760,939,138,751,221,743,58,176,176,706,817,22,485,932,455,14,69,432,656,739,458,171,922,733,405,881,164,149,389,603,479,118,166,719,53,614,352,764,588,132,586,839,634,677,305,778,284,323,0,186,468,469,320,469,905,327,658,5,9,863,197,334,540,771,21,765,551,65,694,458,77,428,824,850,951,693,690,531,365,142,830,144,566,22,331,881,538,669,215,304,203,648,908,776,286,758,901,182,254,585,382,331,77,435,77,519,427,710,602,801,97,642,79,934,23,533,761,968,740,307,123,725,878,181,62,221,59,126,308,330,566,525,10,403,326,346,227,187,265,665,550,984,414,936,668,571,569,170,343,707,109,960,68,323,352,324,948,875,261,307,628,717,346,928,965,514,921,635,925,278,996,553,807,850,353,15,259,638,890,565,280,386,361,764,153,750,445,749,43,278,428,697,461,534,714,851,929,448,57,248,29,473,496,369,889,934,449,338,986,884,42,522", + "626,356,689,279,725,730,485,975,915,981,798,473,356,435,30,174,292,616,648,886,440,717,662,961,476,512,27,146,722,378,422,631,445,699,43,2,295,784,445,315,869,536,784,988,140,29,414,355,816,409,873,96,798,853,361,192,31,373,295,234,15,23,637,667,555,794,789,394,325,610,139,412,36,402,620,601,318,928,107,317,463,335,548,291,593,25,114,943,623,35,706,954,332,235,576,837,910,175,660,398,881,767,255,888,889,878,869,744,752,636,922,319,42,441,880,161,137,613,141,746,985,889,289,557,111,614,415,193,916,361,761,770,508,803,270,630,165,267,229,871,656,910,491,992,643,472,195,219,549,367,530,998,444,959,954,688,893,663,42,84,62,74,871,813,769,306,550,591,715,28,519,177,753,262,264,296,247,491,50,681,482,685,150,6,319,94,634,94,32,490,526,33,671,927,82,787,507,572,740,427,731,559,527,131,665,171,727,200,978,485,972,949,942,199,413,948,41,256,780,672,72,845,54,168,107,468,987,787,460,841,153,319,981,937,575,257,527,187,320,738,546,538,566,122,174,279,733,700,210,169,129,585,288,33,782,853,348,988,238,348,22,238,24,525,24,454,518,95,26,328,350,638,587,440,677,454,180,252,491,134,771,623,302,69,510,829,292,334,107,804,749,13,694,991,480,847,217,549,199,365,400,993,45,727,492,931,790,501,500,41,732,397,78,991,379,215,63,989,873,433,589,820,45,558,170,702,298,189,453,801,509,722,817,941,457,19,534,734,144,233,479,205,853,858,141,49,556,316,477,658,123,408,183,613,199,146,554,577,448,441,829,753,814,748,243,62,866,10,480,152,648,876,272,979,205,856,75,679,66,100,60,408,119,591,217,827,779,759,548,661,18,276,587,240,253,887,120,679,225,201,577,120,13,604,518,106,341,424,351,805,745,98,303,888,884,873,391,671,873,703,189,264,28,758,367,25,180,586,186,731,649,702,56,230,594,211,752,361,259,693,659,449,647,239,867,952,149,364,478,936,865,805,710,527,240,756,766,335,18,28,288,149,10,957,641,466,783,847,650,201,422,420,465,579,712,230,61,751,519,555,123,373,517,342,351,576,746,842,137,155,232,570,481,645,265,657,452,922,712,176,357,918,706,743,577,704,131,421,438,117,382,522,913,71,930,993,818,742,516,748,660,609,596,272,387,626,843,579,33,232,714,694,543,954,137,318,19,200,643,963,292,565,625,839,987,162,326,753,145,825,366,331,190,884,597,40,538,526,191,310,530,852,439,485,655,876,766,992,662,153,829,562,446,862,728,499,490,515,589,325,335,41,590,376,580,871,827,45,813,432,771,371,74,667,462,246,957,249,431,21,992,346,418,618,879,981,274,560,963,515,474,676,32,8,736,19,584,811,511,615,209,993,947,362,549,984,895,97,748,477,702,150,587,901,707,189,619,333,493,524,538,489,485,349,34,316,83,715,646,13,964,686,521,599,215,598,399,167,487,948,804,760,438,746,632,131,614,114,257,22,24,723,926,904,272,940,297,730,342,78,728,427,21,589,464,859,977,571,506,127,212,456,981,131,624,864,257,460,63,456,737,683,121,612,318,346,336,323,428,462,231,270,10,608,331,214,895,735,327,754,909,485,456,970,539,372,729,324,265,941,354,364,890,948,392,797,255,926,587,668,621,66,599,829,199,395,750,536,515,510,770,993,719,820,363,263,202,960,420,368,26,77,497,619,574,169,940,750,886,491,772,428,420,635,894,72,775,522,501,946,588,651,138,97,927,70,581,647,999,921,318,915,989,710,381,496,364,983,638,211,526,326,982,963,541,117,858,599,88,370,136,895,248,602,622,771,152,216,576,185,157,517,109,505,34,139,178,450,617,224,567,94,732,621,380,768,186,0,268,557,819,585,485,195,873,856,546,315,504,614,984,650,562,421,249,395,727,400,209,901,310,702,433,387,306,575,214,382,470,958,520,101,379,135,776,881,432,125,175,37,263,922,773,81,583,953,266,918,698,328,675,417,410,784,426,245,467,844,371,691,92,454,309,324,343,728,472,731,882,123,782,779,918,568,51,646,508,297,402,673,301,477,395,14,121,701,663,970,208,153,72,19,274,741,778,68,275,284,419,676,862,741,790,129,9,921,762,597,244,554,447,767,209,273,465,683,723,605,965,646,105,608,140,218,528,347,263,579,369,226,386,662,984,29,772,112,679,100,402,203,755,264,580,115,944,859,124,971,741,264,319,272,284,429,416,712,657,518,481,513", + "223,855,387,443,871,412,621,320,236,545,510,56,718,620,908,795,888,794,475,834,720,867,255,739,574,156,779,16,270,330,486,995,220,512,690,937,273,830,445,583,776,320,309,897,499,191,544,879,667,591,363,986,660,565,81,497,130,498,210,987,59,88,295,910,887,527,472,31,308,675,250,288,866,355,215,240,463,371,862,886,978,88,251,491,965,280,810,546,749,637,460,126,902,17,863,973,935,251,860,736,394,358,214,836,901,820,630,287,873,961,376,470,18,139,360,258,367,499,360,48,638,242,181,231,742,246,167,729,194,459,907,188,336,224,411,499,279,94,147,279,315,198,892,861,867,333,167,831,504,967,523,757,882,56,163,755,512,827,290,382,365,197,237,348,111,837,387,481,600,333,127,998,378,165,808,538,67,357,943,542,191,515,139,553,930,385,695,871,67,444,675,424,94,115,397,264,297,579,486,199,295,883,396,951,679,696,438,638,355,155,24,554,770,733,296,331,803,76,754,273,616,239,894,867,565,84,92,525,170,223,430,6,246,537,634,373,702,719,349,71,461,394,571,428,207,591,833,484,674,398,262,212,855,357,964,823,674,605,875,866,999,577,328,278,5,565,51,788,204,535,245,433,870,829,925,680,763,725,639,770,516,663,230,328,427,595,206,711,668,593,455,651,796,125,623,118,378,97,325,670,318,225,955,694,426,535,325,919,126,126,468,671,733,811,767,32,549,534,216,310,579,149,840,510,599,760,291,150,11,8,747,619,34,90,654,437,660,360,418,913,793,478,204,564,543,575,39,934,992,804,356,873,251,970,52,849,237,198,880,333,212,647,48,312,315,908,729,142,676,753,722,466,278,838,238,869,905,454,843,245,36,832,805,578,531,469,635,521,53,618,609,525,221,619,523,516,314,775,748,623,663,581,833,757,60,23,801,562,438,179,72,145,997,879,194,222,190,995,86,890,566,841,861,24,214,452,26,684,70,691,204,293,887,431,658,568,224,147,248,59,665,243,52,260,32,436,705,169,439,751,315,765,290,703,39,899,103,830,546,965,748,644,392,71,234,682,954,716,751,361,989,315,556,795,403,865,75,451,606,831,933,186,497,8,382,696,578,707,632,729,824,223,585,203,399,499,953,258,182,836,447,507,317,902,619,666,486,791,930,664,193,79,928,776,980,403,904,666,767,165,128,574,755,590,964,846,822,276,982,885,187,952,223,790,798,421,483,519,511,885,600,386,696,233,115,396,687,458,344,624,221,677,893,239,103,968,113,837,815,931,913,571,298,3,235,701,362,707,275,422,416,434,784,289,507,238,911,172,301,14,678,585,389,928,441,999,564,647,598,701,258,962,314,191,39,952,106,531,972,388,678,415,909,395,705,295,288,738,602,501,119,550,773,57,613,37,608,381,444,213,821,350,62,151,558,848,831,51,302,863,784,274,217,180,561,442,392,506,946,27,439,420,953,562,453,451,124,520,904,721,75,192,467,214,222,543,853,781,706,627,657,998,40,791,602,90,815,962,502,955,639,420,229,147,725,352,299,745,117,726,546,230,949,571,777,123,570,303,347,354,336,441,867,872,727,521,425,16,502,656,350,582,921,855,553,321,195,484,659,436,369,231,32,655,52,184,754,420,704,351,821,228,625,103,566,851,715,481,890,186,220,526,401,131,435,165,803,884,48,374,983,161,826,1000,480,464,443,492,543,520,48,377,658,883,809,773,339,479,604,398,823,538,794,376,7,724,430,650,662,113,78,17,21,381,911,399,259,786,293,698,887,802,386,295,297,577,903,555,402,355,618,491,805,355,752,684,664,40,521,972,554,150,864,387,843,306,822,134,371,369,324,919,772,166,485,159,366,488,446,855,991,909,526,207,919,504,379,850,153,860,738,870,540,543,721,674,468,268,0,228,72,639,222,762,684,100,69,581,989,319,599,419,153,185,268,23,442,37,323,474,439,226,586,40,88,209,72,964,944,448,331,450,553,968,83,854,267,206,871,104,750,693,896,532,343,441,427,378,674,49,406,132,577,368,316,713,465,501,403,761,585,380,363,761,645,941,816,998,137,75,371,228,717,378,960,101,201,481,610,51,386,607,679,938,751,658,177,272,889,91,9,127,186,470,460,227,835,442,251,960,952,409,462,701,291,816,140,516,991,806,637,563,706,906,524,748,642,774,831,604,149,250,740,577,227,588,866,449,273,923,845,607,595,319,384,644,461,16,220,999,402,90,563,241,119,885,734,261,432,458,503,147,121,956,4,614,773,892,156,297", + "290,794,944,445,507,269,217,42,970,875,469,306,444,841,898,326,941,320,769,388,765,387,532,809,354,799,411,372,784,440,708,901,428,542,871,131,344,323,501,245,92,669,403,764,972,553,558,286,305,773,20,207,322,413,686,90,783,798,324,896,336,277,236,147,188,591,340,762,146,960,150,183,552,803,585,301,475,765,56,452,140,907,154,911,865,490,250,35,299,994,79,716,241,308,75,892,319,941,982,872,542,3,743,531,112,667,7,852,780,610,460,688,686,170,212,765,676,697,194,979,989,726,352,766,309,959,412,365,919,946,404,498,775,916,380,352,476,515,192,182,998,939,72,736,252,446,398,785,672,588,22,342,842,735,667,906,731,755,558,809,10,346,441,710,724,824,427,170,324,242,72,105,557,613,962,938,640,472,570,464,553,432,957,454,953,594,783,742,689,362,916,502,490,910,941,877,455,244,87,205,784,894,732,342,329,97,465,427,424,910,62,526,972,856,167,249,509,466,562,558,389,734,522,289,995,263,419,150,730,736,477,299,152,238,979,745,410,649,638,892,977,974,130,62,219,594,47,18,818,490,524,958,355,56,166,311,482,340,921,820,712,254,178,394,276,2,121,290,413,373,198,663,276,466,904,807,690,678,48,600,700,784,450,135,374,774,947,375,327,823,247,318,342,139,411,295,758,727,232,729,299,325,312,644,823,570,516,180,612,355,866,613,456,835,727,268,37,493,81,187,369,88,297,975,20,641,221,742,778,37,399,187,481,870,938,418,16,179,712,733,386,846,674,667,209,995,262,399,653,12,4,216,116,145,504,758,838,569,22,596,555,889,646,751,231,718,513,579,841,489,951,995,642,210,398,125,377,291,774,677,691,814,872,771,801,628,95,707,402,384,309,866,947,223,697,29,507,374,13,867,652,353,141,204,370,8,756,994,163,896,497,362,961,113,883,778,631,562,630,991,144,224,903,855,34,902,721,176,712,95,551,775,769,185,256,423,650,529,5,236,223,398,853,508,93,138,97,171,188,896,48,659,714,518,272,199,730,902,371,253,565,322,803,847,37,516,590,833,997,811,38,636,916,153,93,632,924,922,588,144,806,721,823,218,639,113,77,334,260,1,796,163,247,950,746,547,932,264,656,605,592,350,539,10,454,823,580,759,248,408,926,540,395,111,941,895,949,496,562,936,898,696,518,729,570,457,102,596,637,933,713,388,43,253,861,250,461,144,538,57,436,826,29,979,717,372,537,890,192,688,872,652,666,236,982,594,472,178,16,551,343,933,772,506,190,281,125,85,29,204,211,108,29,298,670,400,882,15,849,892,95,94,502,530,664,752,36,329,82,393,705,947,125,730,384,349,462,862,165,76,1000,77,189,127,681,318,353,293,370,618,386,777,18,674,107,358,188,147,49,621,771,763,482,691,788,927,569,337,553,684,763,148,43,297,459,383,947,129,649,788,634,63,809,244,588,923,220,828,200,808,731,776,990,932,340,600,902,435,14,55,989,726,332,772,120,843,657,220,604,165,687,272,395,203,90,282,846,208,451,883,914,733,359,394,295,133,55,567,564,16,925,244,908,805,372,856,955,229,394,699,12,244,103,488,837,359,669,521,750,432,220,942,529,118,698,939,657,810,303,224,231,38,283,559,812,792,263,679,306,888,988,498,500,878,247,293,122,408,287,810,748,746,405,743,55,903,273,176,406,965,402,420,869,300,342,258,185,345,281,586,101,588,555,888,972,174,602,162,400,969,689,909,679,992,73,633,424,476,321,44,231,561,119,768,286,103,326,326,953,690,294,226,744,845,499,549,656,901,313,7,9,34,97,604,63,712,851,794,57,686,762,844,855,588,827,538,474,354,875,703,409,996,960,62,627,727,591,503,277,1000,182,131,722,113,344,730,469,557,228,0,739,500,496,87,475,295,824,133,285,616,226,518,727,78,304,404,234,259,885,740,112,273,937,924,211,76,910,731,73,352,726,770,127,952,362,729,952,11,750,673,306,178,51,169,263,304,939,55,988,728,572,379,386,837,639,728,901,146,645,241,708,321,473,611,453,866,452,574,239,791,819,838,507,180,982,190,725,874,33,943,27,867,655,820,535,642,257,931,501,382,960,94,21,464,865,370,91,380,467,954,132,434,776,477,916,417,135,375,725,413,383,696,338,524,350,205,636,174,557,14,387,512,838,815,887,807,618,793,104,426,782,433,319,295,368,430,712,523,81,910,536,31,280,51,51,761,991,945,676,412,967,384,747,55,129,515,627,56,274,255", + "722,830,336,189,777,81,825,761,350,941,926,981,102,921,504,536,386,70,569,224,594,102,407,154,615,1,350,508,693,760,838,267,159,190,707,544,921,929,681,925,859,141,439,404,297,423,381,605,864,601,571,391,89,931,310,622,66,804,114,546,663,802,546,410,623,115,105,917,502,242,994,47,636,468,90,655,689,572,919,228,966,948,560,389,970,845,632,283,159,635,429,311,436,782,496,514,357,588,820,238,456,923,429,662,761,422,279,710,579,232,872,444,711,696,475,494,92,989,275,553,63,323,135,469,601,952,151,651,329,963,968,924,936,597,51,904,801,785,748,571,946,727,563,698,921,237,115,264,387,966,821,199,888,55,245,138,432,899,350,715,554,263,235,841,55,471,238,801,351,145,804,424,592,201,38,357,272,208,55,459,210,907,365,33,571,728,506,39,889,963,14,838,980,974,728,476,217,695,972,598,77,289,143,832,545,69,970,943,711,172,104,232,835,795,145,997,520,533,15,17,601,576,259,365,258,222,825,676,260,933,994,784,538,164,643,703,523,855,333,972,773,355,687,53,973,498,878,796,677,255,32,545,566,75,359,786,182,679,511,679,604,908,932,238,747,787,779,108,825,158,602,48,189,650,613,796,876,142,657,91,496,993,907,186,546,888,904,202,536,155,490,174,647,904,764,844,446,239,278,438,729,955,335,340,895,11,603,419,643,226,791,671,816,687,208,571,286,591,337,418,795,968,479,631,409,654,101,932,467,29,260,562,571,500,268,753,156,216,727,564,928,698,149,272,336,137,505,591,826,898,68,648,404,868,973,897,806,623,312,1,469,161,817,698,330,924,632,510,317,809,533,455,908,331,867,579,449,817,495,758,183,459,813,556,329,369,697,435,374,357,16,859,856,188,918,629,170,364,807,534,707,112,456,195,123,717,387,744,809,669,195,391,995,161,356,140,130,505,287,187,349,872,135,770,508,446,119,469,116,883,779,212,918,791,474,802,555,303,176,2,910,410,610,620,557,933,234,602,436,803,50,969,506,391,275,711,403,993,270,947,609,190,779,372,138,367,407,593,411,986,926,346,642,112,49,167,334,191,11,343,365,247,353,396,133,350,167,813,471,292,960,695,878,383,868,107,62,100,739,666,376,520,519,432,302,645,906,897,970,819,749,528,668,350,834,774,518,945,332,542,928,374,517,154,103,262,943,303,181,573,353,590,725,626,739,272,417,152,927,63,685,848,278,837,508,430,485,48,785,563,536,624,487,859,942,32,314,602,192,955,852,444,83,770,99,615,841,44,298,547,109,910,145,309,18,602,380,180,602,406,257,297,721,350,880,705,269,367,26,348,997,501,531,30,203,726,513,207,106,518,380,626,262,489,119,11,537,762,566,302,502,667,168,363,103,964,799,229,309,924,328,918,351,217,752,650,7,214,423,240,415,826,304,490,345,586,840,382,467,374,569,720,51,497,298,425,429,709,831,429,573,362,453,477,571,757,881,129,808,235,301,882,405,924,640,176,925,645,106,877,411,61,368,123,41,425,275,511,562,938,26,132,945,882,355,361,732,786,599,980,97,822,876,847,299,636,11,287,68,943,854,562,266,634,629,6,7,928,62,985,231,748,983,172,432,405,416,854,630,210,190,678,113,174,748,24,815,532,18,288,899,298,236,397,947,203,637,383,354,784,70,115,907,722,922,531,351,242,423,634,967,785,691,374,936,614,446,52,938,634,447,69,11,933,215,689,192,599,302,569,545,775,575,973,627,118,151,974,694,451,809,167,329,110,645,44,834,932,176,840,68,809,4,401,829,852,196,862,498,973,793,513,518,743,791,964,474,96,239,159,672,453,995,885,159,322,154,496,535,451,863,461,191,828,310,888,251,469,284,553,305,138,780,527,730,174,320,819,72,739,0,32,912,32,789,188,953,775,696,510,637,770,856,487,327,328,917,873,774,294,464,326,14,762,304,129,215,76,961,779,585,514,720,955,937,738,975,459,796,922,137,7,905,11,38,427,466,748,77,977,84,480,579,837,103,113,525,349,567,639,755,255,206,643,835,16,508,234,541,381,13,473,213,379,382,26,263,919,898,590,100,408,346,287,538,329,688,293,686,302,571,271,672,450,31,578,901,607,568,271,562,112,509,330,606,988,711,82,442,376,775,199,116,366,792,5,150,700,303,745,344,360,793,402,751,161,715,81,249,390,164,827,831,35,786,722,955,653,570,179,813,494,782,928,374,443,672,703,24,33,748,691,592,293,600,191,916,166,768,467", + "178,721,262,148,462,203,76,595,420,959,77,500,396,297,931,748,506,316,953,923,47,148,366,107,492,1,603,878,50,931,43,734,781,666,462,34,818,35,922,549,461,986,986,743,922,285,286,791,851,918,281,712,214,710,585,458,248,21,562,733,515,417,109,165,433,420,943,918,253,391,403,30,372,299,729,257,411,17,474,568,694,490,185,707,747,488,593,588,320,612,724,308,172,237,432,114,301,392,994,25,544,790,816,923,339,102,18,905,607,374,585,15,29,460,664,430,353,158,523,798,161,296,302,668,120,670,726,220,877,503,382,53,99,884,911,186,324,61,845,228,319,203,820,592,824,715,142,71,762,4,487,308,955,867,396,470,975,372,322,781,738,416,38,454,288,95,54,392,448,662,13,471,124,186,273,541,2,104,737,854,19,740,251,941,755,660,163,744,139,909,316,334,964,611,118,606,819,518,720,861,907,617,109,814,567,419,273,872,898,704,701,1000,955,410,49,794,280,881,17,469,515,145,206,333,427,302,267,332,987,633,667,684,766,830,480,678,465,311,914,944,974,166,895,702,780,974,559,452,997,918,428,544,785,840,822,224,217,241,55,367,789,475,348,812,578,435,176,231,397,797,774,159,581,676,996,975,707,6,339,44,500,666,971,679,661,489,902,280,930,709,905,607,693,791,61,555,303,272,595,275,136,473,506,136,841,289,652,764,425,493,164,177,853,745,99,447,173,372,468,597,541,980,62,394,826,55,12,915,485,121,60,200,856,688,691,524,154,837,844,379,708,147,501,71,326,670,244,331,960,384,315,405,838,939,727,609,276,531,422,896,24,684,913,380,87,289,649,838,480,214,446,447,734,355,240,664,600,228,345,838,420,52,998,2,409,501,311,92,810,311,657,275,639,138,678,953,302,608,747,162,332,242,882,730,731,362,836,477,24,961,859,534,171,206,405,218,343,221,70,878,313,210,874,770,538,452,496,21,116,955,519,953,604,992,209,334,604,430,659,273,546,570,547,845,314,515,117,505,901,395,161,44,277,752,325,304,850,469,690,986,584,207,244,460,993,858,104,262,342,809,132,689,471,816,922,114,456,175,112,338,569,809,686,26,165,670,864,67,407,846,746,307,900,573,766,229,290,658,647,819,993,778,177,550,233,158,881,972,672,229,488,692,434,997,286,449,873,137,264,629,600,214,722,593,785,651,646,221,549,855,94,840,629,909,95,547,598,722,699,44,827,727,257,130,755,146,507,925,70,590,338,86,62,430,493,191,610,471,226,744,578,406,336,359,659,564,318,126,191,529,714,201,352,12,964,388,915,878,749,170,800,79,470,729,374,483,18,48,878,430,946,256,93,298,33,452,698,511,790,983,14,406,858,107,143,783,726,91,492,17,256,391,801,792,523,797,500,474,313,271,607,665,386,436,5,177,703,431,257,206,221,2,971,127,987,935,176,504,216,446,254,990,667,239,66,10,441,181,625,874,225,257,489,276,384,279,530,164,309,162,371,370,620,861,986,434,499,365,232,209,793,921,154,829,546,66,856,663,485,688,622,10,313,164,285,871,922,651,298,676,926,961,445,889,298,966,88,861,461,128,800,772,20,427,335,924,224,203,802,686,182,375,215,945,187,254,506,672,353,798,572,125,317,536,945,322,618,885,247,658,588,307,610,442,200,936,429,686,318,249,926,623,231,79,18,838,603,645,701,372,117,443,827,729,331,15,194,682,66,868,261,235,169,238,671,431,610,198,187,932,452,414,421,853,984,352,569,999,220,350,137,60,361,559,490,860,690,943,942,876,875,453,633,354,301,164,387,576,85,512,949,752,277,386,624,179,710,374,695,866,788,370,746,997,212,41,367,996,211,372,741,538,325,5,185,997,715,840,829,895,865,831,724,452,214,480,469,585,639,500,32,0,784,517,1,157,860,544,41,289,189,32,45,205,4,198,23,974,302,998,951,860,190,82,493,852,995,941,796,50,503,456,588,106,885,767,780,17,564,201,639,931,224,616,51,58,598,240,299,214,743,702,255,637,898,742,651,33,287,68,731,38,745,379,965,254,807,435,126,302,452,867,441,376,777,808,761,988,908,780,33,169,884,35,856,457,76,218,595,106,6,1000,396,413,10,273,607,470,900,943,728,472,74,77,144,736,590,846,530,816,887,166,106,417,505,790,856,382,344,214,775,657,598,931,95,219,534,369,25,222,701,253,181,639,188,51,227,907,999,745,58,951,349,622,771,45,64,748,874,636,954,289,588,106,270,84,186,328,318,89", + "39,988,156,665,209,201,898,12,309,367,100,394,154,155,648,925,782,941,947,763,65,638,580,490,987,131,895,427,607,75,66,44,930,878,521,304,935,112,117,294,870,947,643,75,415,461,977,404,244,39,705,576,538,713,897,595,891,360,472,236,736,269,240,116,851,860,855,760,53,421,984,561,258,494,766,342,765,49,754,362,348,310,820,312,185,567,658,14,52,836,940,306,93,300,37,804,878,407,914,3,28,242,719,759,497,668,84,194,297,341,359,754,931,570,461,204,398,949,75,183,965,346,674,265,379,501,601,6,652,985,461,997,537,46,943,672,955,443,481,600,50,43,22,633,638,625,93,229,353,716,295,980,222,196,742,219,892,209,585,921,816,106,787,430,253,155,455,492,477,576,486,835,542,284,819,29,427,445,958,863,3,870,341,751,69,737,501,947,474,455,55,507,88,354,546,139,929,478,940,837,369,643,674,763,413,520,174,125,224,222,320,520,171,936,880,760,570,637,763,62,185,887,320,459,594,124,577,885,336,140,348,770,906,758,44,845,728,695,482,351,586,394,127,953,542,310,165,839,662,671,68,640,766,569,159,932,965,929,191,388,242,285,11,572,734,455,145,528,118,296,402,14,249,867,109,1,979,335,346,774,123,374,166,699,714,906,428,31,887,138,980,925,835,300,18,977,629,619,268,233,414,417,682,420,891,127,293,951,950,734,259,3,783,636,7,626,111,550,528,788,719,412,305,322,543,112,202,236,295,286,228,519,578,310,974,722,34,271,634,270,242,923,575,157,205,868,430,937,462,645,525,460,807,924,547,975,987,425,210,308,209,778,406,610,169,252,862,89,15,483,474,184,126,171,654,689,188,109,170,248,807,112,187,98,813,192,658,539,961,476,607,97,440,158,94,988,41,380,228,73,146,611,296,785,30,248,242,239,193,400,818,224,739,297,254,126,579,845,353,714,521,16,746,934,675,938,842,611,894,128,700,969,137,116,478,330,164,189,873,211,939,209,711,120,665,446,790,945,515,694,475,588,784,778,405,380,760,139,127,547,874,746,613,114,756,934,26,571,601,139,37,940,448,797,295,322,39,692,264,325,698,956,744,324,135,333,821,97,258,734,895,615,160,582,841,193,638,260,578,853,504,684,402,192,324,362,377,898,829,560,951,160,131,129,295,783,584,177,420,913,669,42,31,501,726,355,588,149,224,466,326,638,885,527,266,739,101,193,843,877,128,588,651,709,459,788,169,240,632,436,20,725,237,677,734,957,562,32,190,420,497,553,320,986,896,811,529,344,941,695,153,966,727,39,830,585,353,649,184,429,313,412,58,766,422,370,18,544,861,491,232,498,895,358,93,863,888,608,914,134,901,818,228,762,566,623,639,452,97,459,568,188,781,46,959,698,66,960,854,887,320,728,40,782,342,965,884,205,901,897,796,768,340,29,624,636,261,764,500,564,106,383,614,690,616,980,889,462,922,566,51,913,273,995,881,754,109,267,367,346,403,385,672,663,919,198,290,818,438,38,946,497,179,643,18,807,954,759,768,150,163,797,138,573,954,262,643,125,242,27,800,180,93,588,976,920,49,596,282,87,979,558,768,42,825,995,164,168,858,150,887,312,500,961,564,336,172,450,202,577,843,167,691,273,210,105,904,400,484,878,768,402,807,915,312,575,197,220,71,731,484,20,659,475,24,8,904,619,919,144,500,338,752,893,834,126,737,490,729,703,91,575,984,874,901,299,604,120,787,94,813,651,799,834,820,429,154,88,789,763,82,626,963,966,442,152,627,846,391,932,516,904,627,439,212,222,748,499,731,119,407,738,731,872,624,591,276,858,735,24,752,932,361,698,204,370,263,234,695,210,190,346,995,179,97,635,928,265,203,107,280,989,691,327,990,974,905,485,222,496,912,784,0,798,32,583,563,735,409,755,180,11,25,656,367,399,84,877,725,351,998,225,193,955,713,191,287,58,129,468,131,340,710,56,330,699,588,234,237,349,935,710,29,272,999,221,970,859,205,494,979,989,920,180,258,641,872,176,253,69,3,887,342,335,232,308,859,205,306,935,786,841,142,292,711,48,914,913,575,380,526,254,127,225,91,164,869,603,496,644,69,450,849,325,956,683,321,201,853,56,295,621,995,501,80,147,796,129,995,723,548,691,102,53,307,352,822,107,661,36,945,543,43,262,740,87,19,722,455,420,225,2,253,47,864,836,190,639,499,361,605,580,70,425,458,409,488,235,851,846,558,387,894,566,846,380,941,166,432,768", + "873,887,978,866,996,59,172,256,790,842,214,805,855,590,19,835,206,875,916,152,469,454,724,815,667,725,811,758,34,584,287,173,895,988,490,318,689,992,99,765,105,587,854,531,392,937,671,906,592,757,952,887,336,800,663,230,858,561,920,374,407,121,545,245,323,536,252,405,970,801,596,782,580,817,902,756,473,186,868,870,409,685,51,97,620,172,209,777,533,664,634,592,568,219,739,576,410,305,950,569,719,987,421,746,7,218,696,123,925,592,543,730,583,18,734,276,344,420,964,946,816,666,566,818,57,721,425,487,133,429,498,727,335,327,437,889,669,445,795,953,368,620,37,238,245,267,358,860,413,496,236,482,872,229,288,877,461,419,416,661,466,965,359,412,860,397,309,48,67,887,790,898,508,857,839,623,956,400,907,372,524,87,619,385,56,412,584,713,487,797,517,755,58,541,975,44,767,654,567,560,845,400,417,453,170,542,406,296,254,667,645,801,517,717,635,8,914,633,457,259,651,41,963,235,818,261,755,710,346,476,679,776,428,586,165,74,99,357,784,513,288,520,266,780,818,379,211,747,540,672,920,359,127,162,932,147,67,511,385,256,936,546,232,730,884,752,512,759,671,783,672,994,272,486,518,735,473,647,914,664,856,449,233,788,287,304,132,807,195,795,627,586,514,511,419,432,184,609,111,920,180,543,990,459,491,846,930,162,971,255,810,313,273,506,2,856,73,950,987,350,524,854,891,138,154,897,21,618,65,603,204,44,390,525,215,932,411,355,402,217,448,426,589,102,527,112,755,627,206,558,833,665,748,71,481,6,911,12,902,973,87,285,925,966,996,970,60,954,368,120,962,301,235,454,344,942,693,284,546,236,294,887,918,254,161,749,853,264,660,821,83,425,551,562,180,886,567,381,357,700,430,621,434,701,888,960,945,329,213,939,143,807,239,264,845,938,464,652,106,581,666,561,396,418,383,251,660,9,450,264,370,569,118,37,417,395,362,480,8,984,333,298,491,399,611,252,52,173,683,17,80,753,708,382,696,62,776,189,955,378,559,738,807,46,1000,802,787,129,168,406,584,865,589,352,672,791,507,45,989,581,963,842,897,928,923,805,584,411,543,300,599,448,32,368,81,527,530,252,574,590,120,577,630,790,569,440,93,612,986,144,422,384,959,73,928,387,811,211,544,842,144,407,446,477,792,681,788,332,2,325,604,912,376,418,726,885,210,528,627,174,259,707,445,474,514,37,904,410,514,260,676,78,46,25,640,570,592,858,688,458,12,38,417,503,431,104,37,58,876,800,357,690,662,114,675,452,474,669,212,942,27,714,458,733,427,105,896,682,137,142,221,49,279,457,514,566,3,837,783,426,286,725,164,55,474,173,647,212,615,596,195,108,550,799,728,743,170,743,933,143,985,688,176,990,951,821,863,514,660,797,292,885,616,837,894,104,147,674,918,815,115,741,240,251,463,58,611,597,200,177,144,986,522,329,950,112,800,780,238,709,212,167,774,864,294,286,36,711,870,901,84,532,281,983,608,713,152,515,477,18,139,549,821,18,743,80,598,774,588,31,301,51,929,684,387,876,913,414,646,571,242,561,917,515,282,762,216,627,649,627,837,934,326,146,107,860,977,838,458,75,884,62,93,873,171,693,515,247,852,927,877,521,619,561,848,726,151,853,59,700,658,628,243,600,739,735,396,659,245,797,62,120,873,246,468,811,173,99,506,40,502,70,852,504,679,176,619,658,427,874,798,968,523,561,906,997,883,453,115,744,660,690,273,860,294,734,46,153,457,309,533,817,666,217,527,963,364,759,447,151,803,516,433,92,728,343,45,107,212,948,363,897,712,921,729,621,530,349,448,697,276,802,383,914,843,143,633,499,383,451,789,552,938,13,479,259,327,195,762,87,32,517,798,0,54,514,215,26,481,848,317,929,399,835,603,238,901,865,169,894,229,52,683,967,115,443,90,812,793,433,668,896,69,956,833,950,849,493,919,347,311,224,694,587,527,341,325,249,106,924,916,693,50,989,872,532,11,684,351,989,862,102,916,966,585,63,949,876,941,44,148,596,823,866,746,701,306,174,10,382,989,378,953,744,954,663,424,667,466,397,76,440,449,889,204,250,70,843,111,415,75,675,433,469,899,735,97,532,336,177,396,440,418,850,868,423,847,299,312,2,528,722,485,814,696,331,881,758,453,112,445,256,623,100,295,584,544,374,765,266,68,209,222,554,357,796,832,351,91,879,687,578,154,729,194,983,77,438,462,331", + "601,318,879,855,989,764,816,972,497,474,518,824,947,925,194,61,208,304,659,854,69,968,166,509,385,697,894,932,757,806,84,962,176,138,474,873,419,527,648,884,143,886,944,951,355,404,754,297,982,521,260,673,252,975,706,293,379,883,227,873,964,743,205,297,310,651,478,42,87,744,866,546,247,295,456,136,21,21,343,477,284,820,486,143,978,745,490,144,956,750,344,640,733,917,79,84,797,692,163,74,84,571,680,254,551,516,124,999,145,685,414,72,725,4,236,752,360,347,852,545,411,327,787,51,883,652,252,63,612,19,780,561,100,973,132,32,613,884,486,115,894,91,234,216,942,165,162,469,499,27,792,247,526,466,347,964,828,612,810,241,82,711,477,412,147,664,689,674,103,121,947,303,100,976,644,299,522,169,381,827,728,16,804,202,249,919,831,869,178,846,979,143,228,660,378,881,818,171,498,686,880,663,641,405,455,241,599,355,88,862,414,972,243,410,400,84,335,366,346,742,494,3,971,618,215,754,669,613,293,10,491,535,666,78,260,625,604,562,848,588,176,316,439,726,531,859,151,152,108,936,589,655,714,612,474,409,668,785,751,546,355,513,408,620,840,493,377,256,367,920,329,40,31,847,358,875,179,820,389,509,584,999,829,820,392,312,303,489,4,437,329,275,338,279,390,292,929,516,329,901,175,790,328,189,608,604,469,961,743,944,968,155,878,714,706,234,446,419,90,612,777,727,884,386,151,226,981,134,452,748,94,587,671,219,242,444,768,450,45,969,826,423,311,846,797,90,855,945,403,977,62,789,964,981,552,210,660,128,877,974,737,679,623,869,830,983,94,38,737,959,52,937,162,42,76,374,678,539,317,408,24,460,680,95,729,441,899,892,664,720,95,155,329,683,9,314,127,650,821,473,597,327,542,985,111,278,921,762,628,780,741,641,207,365,141,480,541,379,341,581,109,780,420,107,692,70,34,923,838,380,612,203,50,759,494,816,659,887,120,151,201,21,729,360,891,833,986,883,574,753,160,417,861,455,443,932,523,448,310,786,497,577,300,368,710,154,411,762,886,535,696,38,757,521,490,785,575,485,891,310,899,304,201,678,378,236,629,238,321,957,534,379,722,64,69,215,847,482,669,475,332,172,450,612,140,440,617,926,866,335,833,475,761,194,174,769,385,120,249,734,102,141,999,650,62,948,476,425,462,515,373,969,475,101,535,155,12,548,269,453,891,267,913,832,61,856,951,671,69,433,162,100,169,490,478,359,468,467,548,91,788,185,969,273,203,904,662,762,471,510,32,252,245,683,555,532,184,90,26,434,302,469,971,792,41,734,277,360,214,855,10,898,563,889,928,366,555,110,72,842,103,174,994,358,436,935,1000,938,493,410,256,90,588,803,242,984,774,418,488,883,418,488,301,212,234,58,847,674,383,880,61,870,475,298,190,573,88,197,835,981,244,488,588,358,182,641,726,832,848,102,983,830,85,763,903,637,662,772,707,431,146,990,875,400,407,780,372,835,682,411,662,764,218,33,547,601,75,955,684,598,597,383,552,900,986,629,312,915,660,418,681,592,56,790,973,740,813,823,491,412,406,871,650,209,633,571,357,223,157,717,598,160,236,48,618,119,853,154,575,210,613,503,832,437,243,500,32,214,308,803,574,910,577,878,695,556,907,104,306,857,161,52,722,647,545,314,567,437,589,852,713,787,850,945,307,349,121,583,691,363,310,131,255,368,513,178,683,467,169,390,414,440,828,317,399,799,16,603,633,126,282,349,121,985,399,445,518,44,832,216,915,997,962,715,228,709,475,892,169,824,18,391,703,201,793,931,921,391,897,5,790,99,450,438,395,394,378,353,615,320,327,184,99,368,191,902,195,702,552,439,906,837,283,387,398,600,658,873,684,475,789,1,32,54,0,4,921,640,594,614,801,330,436,227,744,630,283,488,28,884,468,859,672,196,291,98,865,521,410,191,978,791,365,347,647,309,617,586,146,211,166,30,642,113,660,284,563,16,178,484,289,263,92,243,540,46,62,319,316,190,759,111,295,311,220,746,625,777,108,910,404,21,162,740,945,198,209,235,789,950,778,886,227,605,275,225,847,968,64,874,156,715,38,318,315,125,646,549,140,935,661,288,534,916,898,14,184,523,822,373,450,419,84,407,256,990,921,29,349,595,724,982,344,337,92,246,743,15,541,468,893,384,92,963,178,180,869,43,519,727,988,526,450,741,742,68,446,38,469,930,687,417,396,504,292,338,867,844,997,778", + "741,723,623,267,491,616,165,462,496,385,657,490,907,870,587,343,965,954,462,424,363,220,340,969,912,738,434,537,899,382,766,479,167,135,749,633,391,265,855,768,958,959,2,739,922,92,957,773,120,935,161,537,592,615,670,377,780,942,966,473,503,625,636,236,467,979,191,929,821,472,511,754,374,713,524,912,333,795,66,32,907,625,222,678,876,109,508,664,848,14,599,437,558,962,402,832,87,749,334,429,669,839,693,676,825,894,958,501,146,204,285,986,146,577,708,266,618,779,441,767,476,50,212,29,346,643,988,909,181,916,570,264,980,231,227,40,778,659,651,5,70,951,908,854,736,713,163,700,56,830,661,9,148,162,669,256,537,644,838,534,31,49,451,704,101,393,322,255,997,325,349,306,857,588,141,782,31,948,411,782,84,148,941,95,71,372,724,415,959,570,232,746,175,699,647,825,708,341,425,562,837,51,167,778,788,793,765,517,162,104,765,722,553,271,839,35,467,963,162,349,109,665,70,515,903,536,709,938,945,835,810,498,378,706,627,505,161,852,837,125,426,274,839,292,694,529,298,227,914,193,906,256,734,993,124,977,278,594,322,374,80,843,773,737,458,881,39,988,716,480,469,273,128,748,835,602,923,155,76,339,546,837,133,86,766,412,306,166,244,973,682,775,54,268,383,678,113,845,864,272,27,725,660,817,817,138,759,959,301,981,730,331,264,444,252,270,487,366,308,701,734,349,979,504,567,635,927,360,198,776,986,277,736,956,537,635,539,419,867,980,485,473,563,443,891,145,648,958,546,45,529,20,357,177,404,930,295,7,846,819,730,577,873,409,705,343,983,329,16,675,272,29,575,253,624,635,467,857,862,94,630,735,933,740,827,32,928,337,689,676,295,173,945,129,288,864,397,30,118,674,310,11,517,195,287,145,336,190,441,888,118,672,847,318,765,47,577,789,955,55,979,977,517,172,852,417,118,681,441,763,384,150,129,880,592,757,36,409,153,820,432,180,604,470,689,919,548,369,473,271,458,663,302,620,824,100,85,574,487,333,480,655,384,488,111,985,654,606,974,251,356,823,913,105,641,359,595,756,981,759,216,11,942,971,127,733,807,865,458,342,902,387,317,287,471,922,511,316,885,353,516,921,86,650,102,695,238,567,331,1,114,616,844,135,87,222,851,764,73,268,463,6,479,198,989,135,822,263,38,911,34,233,470,937,716,8,531,434,544,167,511,682,30,527,958,26,892,825,488,860,379,906,493,414,715,916,137,755,38,22,484,343,373,782,884,425,696,549,958,302,932,116,26,963,955,555,165,61,700,79,706,317,92,218,42,534,887,748,947,129,182,527,625,459,297,109,579,83,889,899,577,737,275,610,600,571,83,488,723,893,747,686,756,344,166,624,556,186,19,655,641,75,228,390,261,956,252,46,884,370,703,458,677,161,445,47,934,624,31,11,594,350,606,342,443,275,658,952,727,899,645,839,976,701,696,31,382,477,845,888,960,27,203,59,275,655,201,628,906,693,609,281,701,552,316,966,693,904,830,51,43,29,415,820,192,857,838,764,782,228,285,55,770,548,534,943,407,616,537,427,993,648,194,281,536,691,929,161,561,88,429,102,757,53,297,285,547,6,489,928,258,916,858,467,428,665,809,565,124,208,152,199,379,233,117,879,66,366,732,57,173,200,147,864,19,842,532,835,672,754,368,402,921,16,609,796,756,715,689,847,352,210,477,819,145,239,986,528,530,978,894,421,792,104,884,469,312,556,590,401,817,668,79,164,691,791,327,974,714,525,474,766,133,308,96,648,357,522,365,669,61,87,716,690,85,46,680,877,486,462,293,761,54,756,69,511,417,551,179,896,182,776,373,23,558,347,508,387,323,960,364,703,465,937,830,296,5,856,100,295,188,157,583,514,4,0,609,592,339,76,137,709,186,942,805,546,20,414,284,232,509,933,959,806,346,991,926,788,768,373,909,550,797,319,757,543,33,767,778,410,400,328,959,451,127,528,211,768,421,627,550,710,755,170,569,472,860,192,384,925,326,822,666,347,942,118,251,128,512,359,565,59,389,427,180,819,933,624,601,115,382,723,631,17,500,582,789,36,976,655,43,512,452,319,753,746,726,482,156,237,545,439,505,11,667,411,873,399,668,626,341,392,578,944,320,834,630,441,915,808,673,135,31,574,992,540,383,847,743,379,728,332,427,368,324,237,292,931,935,635,647,60,727,279,4,700,462,811,130,196,203,583,510,19,299,126,946,311,933,227", + "88,560,634,417,232,170,36,173,291,76,476,40,725,788,318,9,497,870,61,248,19,606,677,74,778,984,234,627,232,769,138,398,189,727,743,107,468,640,664,983,775,213,522,303,318,690,687,23,278,513,149,11,870,217,724,796,663,484,409,388,854,924,501,937,467,328,431,290,304,324,617,382,335,955,326,904,231,63,786,557,890,11,117,367,167,27,488,369,927,897,613,294,324,546,505,583,695,59,207,34,600,801,64,324,345,574,757,924,399,635,648,207,344,773,56,783,58,858,924,719,584,134,126,920,565,683,139,720,654,974,97,60,205,719,126,911,144,34,976,685,420,701,449,392,467,524,175,971,926,377,126,859,398,844,957,634,916,873,893,476,733,545,409,839,429,454,405,777,490,384,785,205,127,786,479,993,134,230,410,491,271,820,263,954,311,487,951,751,200,3,859,893,130,745,485,896,248,605,949,985,676,808,952,363,106,230,616,950,18,996,165,174,269,704,948,544,561,93,548,275,215,925,277,296,891,96,319,574,62,368,934,696,754,750,434,512,293,145,883,473,270,831,964,786,582,929,276,75,391,498,806,313,468,291,387,600,657,908,128,507,323,802,656,302,628,855,954,965,168,644,266,613,925,55,400,511,4,570,355,444,580,191,943,903,90,499,292,442,677,487,516,587,814,939,613,599,590,98,255,829,687,574,995,962,874,940,597,254,602,500,368,50,909,67,915,71,690,993,462,800,929,584,867,550,285,924,922,146,435,897,105,810,698,366,784,25,160,158,689,628,526,335,972,878,625,85,327,812,591,540,689,569,437,273,457,928,578,728,521,154,833,574,555,680,637,697,742,586,399,666,438,333,648,620,312,614,743,418,974,730,44,248,808,34,186,262,91,35,189,594,273,165,984,891,432,687,310,518,254,753,961,611,931,250,820,133,362,895,879,925,806,989,765,924,734,821,38,80,245,627,904,619,60,968,108,129,790,612,95,947,631,55,250,304,714,514,485,740,232,712,862,535,902,497,276,501,347,670,142,724,507,904,479,63,454,277,662,167,945,442,660,263,621,956,189,806,35,298,672,819,831,761,260,225,582,814,509,914,14,744,568,200,598,68,373,696,54,262,832,498,469,728,381,909,46,974,300,672,676,535,657,782,933,715,76,676,27,968,542,615,612,150,530,850,845,271,943,328,817,663,175,946,166,839,675,492,505,112,172,133,620,591,564,663,302,538,170,853,859,169,636,354,648,52,423,708,499,668,90,23,616,92,426,178,863,8,514,489,979,146,715,776,957,670,220,873,514,847,44,199,574,985,97,596,122,748,702,556,250,181,415,440,510,743,870,922,23,236,243,542,439,132,466,164,905,339,775,667,705,531,690,302,540,870,215,288,35,678,634,567,389,248,971,460,243,407,38,688,427,730,201,620,979,520,282,36,801,427,361,824,567,980,584,714,378,843,593,757,947,837,690,731,83,599,881,528,303,427,363,213,4,836,642,914,789,854,140,461,838,198,284,164,74,994,431,311,885,666,495,794,901,637,489,474,778,261,207,712,903,531,654,450,458,626,670,364,753,739,321,914,439,787,236,573,65,806,23,551,413,714,94,552,372,113,31,84,7,147,319,889,337,715,841,270,999,586,954,230,52,130,486,53,556,604,119,13,857,112,550,630,649,760,849,755,741,103,246,711,16,682,225,627,54,26,596,982,84,855,61,850,700,340,469,887,593,699,242,159,587,99,55,616,951,306,907,998,560,76,812,160,115,987,307,810,993,518,941,680,265,927,745,283,136,561,680,40,27,840,40,834,203,517,308,949,242,74,283,571,149,290,441,891,240,309,970,458,888,236,241,286,706,581,826,982,219,536,311,229,397,558,699,456,547,7,205,766,270,465,282,183,246,296,355,802,978,231,9,546,69,824,953,860,563,215,921,609,0,219,138,470,528,998,324,564,232,867,308,646,146,210,270,32,839,668,398,26,665,236,776,209,522,188,463,433,426,13,191,394,362,196,768,690,194,550,899,991,40,860,774,883,194,713,986,403,388,945,929,917,780,966,504,39,28,786,53,448,390,935,748,367,224,303,42,958,674,229,440,940,316,382,148,190,139,467,426,330,896,563,677,462,818,721,56,584,282,725,837,508,77,223,282,44,114,65,33,691,108,111,440,607,174,421,741,958,814,491,66,262,927,995,160,692,78,567,361,275,258,109,913,960,409,924,143,680,930,505,897,527,64,801,920,953,187,898,265,231,974,303,762,465,393,26,610,744,840,646,876,724,74,890", + "690,688,258,553,39,292,51,377,830,171,484,236,980,161,379,526,663,573,219,888,65,752,237,485,183,166,597,331,415,534,840,967,700,734,603,664,785,944,767,854,82,41,274,493,381,979,776,599,365,549,510,448,511,380,144,682,868,724,78,439,549,513,122,615,417,567,732,387,16,821,859,532,891,161,21,466,244,551,842,901,939,879,699,816,705,361,462,483,467,170,582,194,549,566,539,445,724,325,824,262,300,11,376,963,155,884,461,779,585,129,557,107,533,977,174,252,424,191,586,931,596,567,821,823,870,8,718,222,943,929,788,837,9,544,59,108,437,528,645,907,435,825,488,94,262,250,64,395,980,768,686,191,407,925,691,715,710,430,880,562,683,819,711,885,597,392,422,237,45,115,700,363,137,623,223,67,195,312,838,161,474,958,298,49,712,191,26,938,670,838,81,270,157,835,916,633,664,736,253,899,961,392,421,211,762,870,546,304,326,59,672,386,34,245,634,66,169,998,276,969,732,531,455,711,361,699,800,894,290,793,243,37,42,114,37,255,356,949,787,166,890,576,595,575,901,685,106,222,825,301,189,57,527,189,560,296,152,764,208,872,447,735,770,691,668,603,586,22,11,295,767,488,251,52,653,546,675,559,777,979,760,909,620,201,82,664,73,646,7,425,407,533,557,537,600,421,302,206,705,3,55,339,22,697,214,65,857,623,921,762,357,192,539,901,583,950,701,81,877,996,35,272,931,45,571,880,613,831,331,827,142,800,700,707,884,393,290,946,881,997,411,208,37,89,928,758,544,687,414,679,602,301,381,676,389,438,283,781,92,670,477,438,43,62,267,103,141,866,988,450,993,519,177,954,799,642,349,44,710,814,956,606,958,92,304,879,407,892,106,594,812,753,30,912,43,874,49,920,527,721,383,785,214,141,701,854,353,334,507,141,798,469,261,13,846,914,939,398,249,163,262,28,975,967,502,927,116,925,186,286,168,183,893,31,719,91,498,951,510,479,502,526,207,720,18,27,575,53,456,108,968,930,201,102,367,697,152,349,107,505,399,353,541,42,446,172,11,646,582,889,99,878,997,47,869,248,166,460,897,293,706,994,579,75,634,312,517,687,180,919,158,553,547,994,861,989,466,886,130,745,999,909,763,917,571,263,684,378,548,213,897,896,291,405,772,317,530,675,674,285,113,229,524,238,624,838,625,347,700,213,647,826,530,229,450,741,874,99,124,568,420,634,965,50,641,509,455,716,925,682,986,595,973,694,8,467,802,184,109,301,413,570,167,305,300,10,606,333,889,523,515,864,159,788,579,643,569,384,332,814,379,663,393,631,395,368,344,39,324,410,278,854,830,876,637,361,974,140,413,856,420,95,689,180,187,423,703,970,466,582,813,249,85,880,925,915,825,244,631,15,327,436,890,769,717,585,877,781,97,118,300,133,233,489,508,530,672,493,637,928,820,270,277,417,722,799,954,46,560,232,366,882,481,232,839,504,819,77,482,720,734,123,457,236,8,380,874,600,616,900,786,932,216,253,807,477,647,642,763,782,38,89,232,332,636,924,914,33,429,668,165,991,391,472,419,931,289,846,721,469,333,67,546,139,622,383,836,317,444,361,345,65,501,399,851,826,33,105,426,234,746,74,550,598,984,267,539,843,908,751,604,868,943,779,1000,690,385,70,469,549,86,914,822,618,393,305,579,467,530,784,515,498,800,164,812,675,37,588,194,25,316,831,675,799,545,68,935,188,673,413,505,79,390,898,865,125,397,964,830,735,254,482,525,285,333,253,645,724,397,467,611,618,540,661,272,591,765,784,503,232,346,101,585,581,570,444,569,522,693,695,272,2,885,719,404,462,723,579,833,773,585,5,243,986,571,419,291,542,900,215,185,171,608,931,973,963,863,315,581,133,775,544,735,26,640,592,219,0,266,106,565,151,334,592,182,811,492,825,987,854,143,572,352,13,318,289,515,92,468,65,967,159,325,963,580,925,778,14,24,449,816,55,862,632,789,643,67,983,261,459,861,307,522,574,477,100,538,512,106,247,135,905,935,457,826,65,419,822,341,194,871,524,157,116,196,971,539,826,535,75,859,563,146,774,524,770,802,269,939,162,630,939,189,109,957,390,967,463,432,673,831,518,35,234,199,20,553,307,524,358,74,68,750,172,339,249,195,84,620,57,423,988,619,25,736,13,540,333,125,933,705,909,920,490,114,48,251,644,320,853,229,204,797,986,281,819,330,163,933,866,512,130,180,77,808,272,277,747,527,11", + "295,644,805,94,221,254,509,969,948,494,39,571,23,549,463,377,816,555,764,804,986,6,202,810,24,24,850,246,784,155,339,669,670,68,264,107,80,926,859,170,592,180,717,89,753,994,272,76,860,466,588,633,481,496,920,359,891,457,135,963,863,953,688,421,946,973,600,354,879,359,672,364,758,365,260,280,175,301,762,854,184,550,832,267,997,995,551,94,283,949,802,288,157,550,529,324,712,543,740,45,50,684,901,643,326,615,821,35,716,885,75,837,953,520,661,954,273,116,334,977,77,470,752,845,283,838,638,224,527,497,421,438,7,856,453,170,236,976,997,92,671,403,230,832,70,503,926,826,766,234,510,735,835,23,7,544,861,610,908,795,410,624,54,499,408,883,627,595,630,171,919,925,244,431,236,408,98,315,484,582,98,12,224,752,789,139,802,421,968,336,761,817,503,950,17,243,598,479,546,545,79,501,336,731,735,649,245,274,433,379,203,563,781,627,667,67,104,843,365,360,946,282,550,242,278,551,52,326,961,309,771,405,762,341,165,881,27,409,344,295,403,167,258,263,972,155,834,271,746,730,620,65,590,899,213,216,946,286,214,814,188,325,100,69,790,986,441,703,286,892,220,484,608,631,951,327,23,920,275,597,182,309,406,840,650,893,283,170,342,826,696,212,962,57,901,769,949,71,248,451,34,630,472,106,856,632,496,721,154,955,542,602,689,772,105,634,318,241,831,863,914,895,836,406,5,975,100,842,298,821,177,222,390,624,244,49,74,26,119,882,696,653,237,654,292,285,458,277,333,920,560,858,660,725,572,710,431,69,517,318,436,26,89,440,126,175,74,367,6,432,758,299,144,59,892,370,811,735,668,957,33,694,578,475,387,66,851,142,152,948,621,156,130,505,508,790,39,856,96,891,570,323,929,823,981,968,827,150,593,40,817,933,773,593,297,849,126,875,942,710,387,544,492,679,275,209,529,390,931,830,797,625,145,558,169,272,918,441,453,453,516,642,659,244,788,800,471,524,766,314,672,610,976,404,95,684,771,427,667,21,314,509,916,932,903,743,812,202,86,368,813,353,667,605,346,538,895,76,590,332,352,113,521,824,485,119,145,226,931,691,312,301,345,189,294,781,427,866,792,521,718,99,143,874,505,83,794,172,351,349,296,601,834,300,367,2,564,35,572,298,316,870,124,768,226,305,702,244,835,995,548,288,417,51,151,621,367,199,846,284,712,970,695,496,83,879,47,389,612,26,329,665,207,934,502,248,428,462,175,236,910,401,440,286,710,451,327,280,184,175,727,128,475,390,446,127,260,999,258,736,406,681,19,472,850,183,278,769,263,147,375,525,493,924,312,57,750,914,493,775,771,721,159,522,484,533,686,268,648,253,51,206,271,733,25,237,267,641,389,698,652,533,578,848,176,500,17,289,39,571,230,319,128,653,466,259,164,691,680,844,887,651,625,692,204,579,493,210,873,436,523,966,347,761,351,420,223,447,196,859,764,272,459,107,369,891,571,725,271,576,443,772,692,504,399,358,852,928,466,45,769,429,172,400,299,273,442,55,232,888,763,87,78,235,333,983,869,942,204,426,526,198,556,75,930,50,221,282,254,968,565,659,882,915,265,779,223,61,113,587,391,370,342,883,393,96,122,285,949,57,651,678,828,384,823,11,305,385,528,880,231,481,717,694,358,124,20,751,964,552,399,178,490,584,142,568,660,764,57,493,815,701,47,577,794,602,321,745,740,737,968,319,634,159,269,417,348,499,527,120,930,307,600,349,773,874,583,123,713,920,991,8,291,717,232,644,147,447,320,242,385,368,986,356,206,544,59,348,838,94,141,302,877,160,763,592,868,536,948,269,549,298,659,371,18,609,49,251,883,72,407,57,420,781,752,531,197,504,989,285,696,41,409,481,594,339,138,266,0,268,233,564,152,666,797,800,533,774,132,141,610,393,368,38,325,45,806,576,910,462,243,230,558,37,712,57,844,422,910,339,50,985,109,265,561,621,196,893,418,157,873,7,818,395,837,855,859,955,25,15,5,239,980,193,972,514,512,984,959,644,446,44,686,176,909,465,259,996,165,437,931,341,744,495,76,959,43,194,420,210,575,991,420,696,286,237,431,466,493,712,527,417,624,895,920,919,322,869,753,709,62,388,327,199,562,317,830,367,794,903,152,907,256,230,981,446,618,494,608,24,703,879,81,347,536,323,777,169,417,978,549,1000,130,499,710,442,48,311,11,506,363,905,486,293,377,301,486,403,84,213", + "272,44,64,423,962,306,123,277,226,751,39,662,955,951,416,305,411,551,890,174,56,144,920,831,219,520,784,575,796,38,184,543,941,370,834,977,530,118,583,119,634,585,834,416,763,65,957,912,646,346,690,781,8,492,201,538,842,659,146,967,693,564,601,183,445,525,416,736,891,395,477,564,231,234,118,540,479,446,25,898,646,720,387,902,699,474,88,464,758,878,80,67,49,862,373,75,910,718,508,552,263,229,804,784,933,751,392,81,697,856,38,817,746,399,381,630,377,381,356,930,418,282,480,373,359,419,308,944,833,333,136,528,88,369,716,115,743,657,77,717,417,283,476,711,789,763,693,142,94,197,522,933,150,713,918,476,556,374,717,537,577,837,382,915,980,513,848,725,552,3,99,211,634,386,505,695,234,205,157,420,565,818,332,106,549,918,541,386,45,458,366,994,105,839,145,251,90,19,694,954,416,193,679,160,451,758,426,816,682,609,909,484,517,345,276,78,172,585,90,541,536,558,543,294,469,744,74,219,285,285,617,828,498,828,192,381,430,510,69,450,380,231,261,352,276,520,184,114,531,874,591,750,523,892,12,84,856,708,641,297,287,833,145,904,669,341,450,586,348,977,352,487,180,376,525,380,897,344,750,668,381,110,305,95,884,147,216,598,300,92,414,804,470,562,338,186,379,117,225,13,854,765,51,975,73,391,808,554,836,102,48,485,650,358,987,787,658,287,139,295,815,555,947,2,349,735,15,116,192,630,368,253,189,13,7,296,446,734,604,354,302,875,365,480,290,308,256,138,906,501,545,593,650,392,448,364,341,330,324,337,55,701,65,300,18,831,896,651,200,470,547,282,145,876,761,804,498,634,550,498,447,229,661,667,940,991,451,382,231,885,420,544,710,165,952,244,61,616,126,250,306,548,918,194,66,271,161,244,875,392,988,951,115,990,658,459,333,656,454,806,486,562,251,518,539,613,234,887,288,801,194,272,278,946,174,241,563,641,588,560,818,791,548,703,144,633,834,616,903,629,409,409,352,991,470,522,631,345,423,155,837,160,123,399,60,453,628,20,750,128,50,231,559,42,799,924,216,51,779,216,135,236,879,970,621,390,366,825,387,237,236,336,726,596,937,560,12,826,309,218,282,343,294,152,863,60,70,714,154,58,248,330,248,246,720,860,973,82,20,145,486,778,970,107,415,758,581,794,759,822,524,495,508,91,626,498,327,698,775,710,629,116,538,661,443,768,514,645,208,191,947,231,316,275,824,889,686,750,719,319,300,266,331,862,705,59,40,130,811,720,973,860,861,169,882,28,20,340,508,226,757,356,477,520,240,183,362,577,182,763,44,803,52,852,345,177,777,135,922,881,754,16,22,117,911,471,165,551,381,532,377,550,785,193,25,371,592,238,906,254,821,628,696,987,897,835,120,390,691,841,369,358,762,968,864,394,767,202,666,403,7,175,967,264,348,722,353,534,969,679,540,512,940,768,616,752,445,765,59,323,416,362,322,273,464,966,306,773,842,204,543,718,438,577,832,765,841,743,766,168,206,850,991,796,898,741,650,486,793,157,575,514,208,199,927,408,832,290,722,601,439,907,481,484,478,167,556,683,96,991,787,212,391,178,96,289,910,135,70,807,844,800,531,944,7,943,809,471,801,994,464,633,377,460,393,363,355,831,320,775,940,912,273,272,482,810,877,311,691,612,23,728,726,784,125,423,727,759,99,324,895,330,855,933,601,392,40,523,675,64,965,397,944,42,811,531,890,326,758,742,378,484,278,641,931,644,176,816,820,101,514,930,333,270,105,705,546,318,448,193,974,672,98,193,771,176,446,374,708,785,233,945,464,125,770,575,547,460,319,888,697,798,790,412,817,817,868,531,463,71,225,161,455,677,826,642,334,614,319,616,510,289,755,848,614,76,470,106,268,0,196,465,761,16,537,858,628,498,773,250,738,218,825,581,138,87,153,208,466,811,539,563,696,572,923,781,718,531,670,969,570,225,595,48,622,839,299,893,469,235,454,261,850,805,151,151,867,850,60,243,516,78,552,636,988,233,731,556,367,296,270,846,920,596,94,847,939,531,365,789,471,676,83,511,963,37,397,952,648,388,303,648,333,887,197,735,855,283,880,327,712,177,544,70,781,143,589,993,811,477,296,348,961,796,623,778,561,730,922,306,913,296,285,820,162,718,899,944,81,484,591,23,850,304,616,671,628,639,676,715,522,988,365,917,171,664,546,631,173,249,823,27,173,993,204,700,584,216,569,374", + "189,946,603,992,152,43,198,295,136,248,172,880,200,204,586,356,939,429,769,148,562,601,193,146,836,562,722,262,299,185,638,115,488,2,555,294,376,317,251,292,820,959,215,583,371,671,480,384,843,148,967,838,469,777,582,707,299,16,462,835,323,76,979,983,294,725,233,598,764,381,994,230,300,727,864,10,818,725,97,922,912,18,491,462,792,378,321,214,286,79,327,983,630,110,557,824,565,284,190,403,10,291,328,695,535,378,822,175,657,577,218,780,154,223,106,969,694,499,325,904,891,717,313,273,603,950,339,143,31,97,329,785,817,766,786,998,320,864,543,216,129,482,635,55,406,664,227,228,660,624,917,732,146,690,899,801,925,326,677,609,21,93,438,30,481,648,951,376,662,928,694,195,113,157,506,608,549,509,140,342,161,912,282,550,78,857,656,268,709,629,221,75,238,592,671,289,721,962,991,422,652,347,7,751,147,380,24,335,739,714,100,141,631,256,264,393,238,955,55,95,297,22,239,249,44,824,794,722,238,121,50,60,203,880,535,403,689,515,86,610,350,684,876,704,808,5,101,289,610,81,82,397,164,161,778,458,786,742,79,579,99,593,381,141,900,310,599,264,610,196,546,482,301,13,478,659,408,845,651,568,265,175,170,280,323,934,583,505,286,265,65,327,434,467,672,482,913,108,419,777,107,369,535,687,198,740,889,535,160,134,660,958,164,108,33,316,198,348,507,560,928,90,715,979,580,117,480,378,55,926,584,339,701,677,262,915,700,821,805,509,230,659,659,156,820,743,584,452,258,847,365,536,283,624,332,876,885,829,656,28,137,720,293,570,188,191,415,72,249,743,849,754,636,185,231,99,591,761,827,405,392,644,623,437,771,896,505,188,542,950,478,988,609,239,319,923,914,545,527,820,175,716,127,587,505,934,123,729,386,367,893,755,730,921,478,562,168,284,115,724,686,798,114,690,184,540,43,404,583,24,519,753,139,115,909,358,312,850,624,810,350,126,70,763,855,282,586,846,454,614,542,678,421,441,345,811,813,692,739,119,952,984,726,526,630,802,492,311,844,345,188,138,29,184,29,875,533,835,242,356,382,914,249,376,483,464,698,85,283,408,349,168,414,450,380,74,629,275,996,47,846,118,775,195,383,159,704,687,59,145,183,722,883,922,244,657,545,844,339,360,586,965,985,569,132,283,825,504,281,219,554,938,398,720,404,125,770,284,656,8,662,191,133,928,943,548,393,433,731,764,838,963,394,121,813,658,200,862,725,650,762,438,733,245,368,741,847,571,158,565,256,978,344,413,68,205,781,275,297,805,47,919,903,969,627,574,180,478,508,275,712,451,493,419,751,951,911,271,142,268,202,432,967,228,773,478,180,530,269,437,397,573,673,955,937,404,67,336,456,584,25,963,714,403,137,564,481,307,183,94,113,741,397,121,139,117,638,207,119,50,511,944,38,759,869,204,100,376,273,319,70,654,184,228,930,820,454,887,222,688,150,834,602,167,505,130,58,174,362,848,233,817,720,453,90,869,912,343,424,25,268,272,157,792,553,281,933,940,971,964,650,900,35,96,528,41,552,742,293,469,922,742,42,393,896,573,478,623,362,976,341,437,927,728,878,918,228,761,98,234,288,137,746,386,115,377,356,393,26,589,503,308,977,429,702,198,400,404,824,318,165,473,574,522,413,413,788,754,112,894,840,314,639,599,226,962,540,671,930,298,622,898,476,159,891,630,285,902,901,245,470,921,850,718,585,866,693,137,585,672,455,536,447,175,184,745,193,155,414,717,728,368,97,434,444,993,914,420,876,767,792,236,101,78,520,726,917,181,230,306,661,432,576,214,786,337,501,559,993,318,362,809,161,666,718,858,622,783,392,570,713,654,470,132,507,192,540,984,599,226,637,189,180,317,801,137,528,565,233,196,0,249,414,23,707,56,339,492,165,33,601,431,465,721,536,711,124,375,581,960,576,486,136,698,516,628,182,702,212,120,414,80,294,901,969,471,357,303,91,520,601,736,648,124,715,510,707,15,185,844,918,397,40,103,672,630,360,733,848,768,568,392,891,533,689,461,579,153,62,78,633,852,732,927,582,957,986,48,805,761,708,117,181,293,665,24,550,969,176,798,801,415,961,49,131,863,343,591,925,865,872,739,531,154,135,833,68,218,445,557,10,4,579,639,638,252,486,996,647,329,373,339,272,437,608,769,363,609,83,379,670,43,677,336,692,459,67,184,150,375,833,921,558,428,707,188,951,651,916,274", + "397,988,919,97,667,547,645,103,903,596,880,304,875,545,130,404,687,47,997,103,276,392,917,744,480,21,913,496,80,49,366,871,14,720,480,604,194,662,192,915,617,239,821,336,334,146,732,747,39,493,467,603,683,20,512,741,619,669,128,420,798,464,861,380,612,226,801,316,494,558,180,599,830,688,753,879,153,379,305,373,69,391,134,963,961,32,424,182,803,621,465,299,857,443,428,855,856,261,465,453,567,878,225,359,693,832,159,815,530,499,145,755,420,785,71,787,988,394,999,344,918,908,248,221,844,247,919,247,698,982,839,99,1,306,837,871,169,798,837,992,124,139,880,826,656,735,336,150,903,609,76,756,653,420,104,497,381,108,645,103,836,819,855,789,364,535,882,411,742,816,784,826,443,128,495,771,575,749,471,293,302,991,567,390,66,357,582,114,778,877,278,520,597,353,534,984,845,881,646,838,606,117,74,623,273,285,64,156,310,703,222,435,427,540,163,753,847,539,329,227,594,659,15,162,307,126,131,996,526,36,758,936,869,859,261,283,88,286,459,21,638,120,628,94,670,696,578,656,611,591,877,482,916,884,140,602,197,962,159,568,642,941,9,102,308,227,488,487,308,328,335,399,366,187,648,472,992,835,3,913,219,615,636,391,367,170,693,155,246,106,500,944,967,250,937,620,438,749,154,46,539,972,242,818,917,382,251,185,881,231,345,551,925,462,872,509,44,25,902,50,523,860,331,134,474,61,348,52,528,62,785,764,582,658,696,762,308,287,164,406,300,772,313,23,888,816,278,98,949,920,502,493,117,918,457,832,701,674,729,51,111,159,353,839,65,456,518,365,990,206,954,504,499,393,131,166,423,711,90,649,916,494,150,338,838,23,613,786,783,45,97,52,905,718,105,881,719,538,398,424,206,857,692,83,587,597,574,767,278,238,470,593,635,245,246,98,851,986,50,398,170,765,797,926,980,334,455,48,6,529,570,941,636,325,180,120,110,542,771,858,515,2,202,569,218,856,709,795,322,760,50,285,720,884,763,681,850,892,690,84,492,317,384,772,558,579,324,768,689,738,971,185,20,445,387,166,465,710,967,668,81,883,838,490,296,153,332,786,620,786,161,781,633,784,635,913,636,844,130,89,406,167,946,612,192,912,451,674,633,946,113,735,634,742,318,254,512,40,143,494,140,64,811,775,173,397,634,412,271,793,5,395,384,471,898,918,795,997,88,3,978,494,272,313,175,252,739,194,21,485,376,992,265,622,499,147,469,328,154,824,651,973,595,630,318,766,454,464,52,999,824,814,331,285,828,96,909,559,744,571,285,912,761,448,618,838,504,234,842,854,819,577,777,421,382,975,151,282,845,37,865,974,771,19,781,775,490,244,208,366,5,788,942,50,694,288,106,712,82,81,660,667,636,671,137,502,61,96,401,172,947,401,637,558,734,64,154,882,280,581,81,322,556,731,489,309,56,28,171,652,408,158,99,415,769,400,784,49,816,109,175,253,650,160,907,34,785,980,604,343,223,283,551,103,4,770,664,935,974,767,609,82,800,647,869,363,224,612,481,68,626,250,557,270,997,341,601,332,216,530,277,990,679,930,411,986,108,856,864,604,650,685,605,593,81,82,582,314,86,723,142,207,587,734,458,155,450,584,970,383,568,281,262,204,221,778,129,125,649,517,464,410,605,726,734,489,710,656,784,971,128,451,808,289,122,816,993,337,209,163,221,394,436,800,126,382,18,295,831,33,703,57,689,809,441,408,395,334,169,570,546,756,420,623,295,822,200,361,807,905,966,172,438,581,112,447,722,263,639,459,944,354,96,205,707,268,858,73,987,421,328,411,645,143,779,491,181,666,617,658,47,419,144,39,125,156,220,385,443,194,32,610,965,751,264,788,771,650,419,518,770,32,11,929,330,709,998,151,564,465,249,0,959,913,803,918,111,915,161,986,568,340,869,759,727,100,97,123,102,452,89,875,45,359,775,97,216,495,188,449,268,745,260,940,191,782,208,970,373,120,215,132,348,354,443,986,689,148,915,900,689,569,378,329,110,525,250,566,925,806,845,445,423,754,958,324,431,733,425,519,372,446,229,364,326,223,348,57,298,115,339,633,30,784,521,67,421,533,59,753,852,185,98,128,813,994,67,224,664,210,877,590,565,46,202,574,384,10,822,242,800,188,624,943,778,212,866,56,339,562,912,793,641,42,896,480,732,716,772,316,796,326,980,936,97,726,597,284,911,402,138,778,621,290,573,213,609,111,96,51", + "631,512,87,737,200,950,880,708,924,509,209,279,95,205,797,774,228,724,927,548,153,546,748,538,291,535,518,471,193,970,885,114,760,492,586,751,259,333,960,505,303,413,936,155,506,97,150,575,576,622,795,639,98,357,327,947,788,3,482,728,648,601,27,957,8,396,16,283,996,196,632,580,734,239,827,163,563,326,999,119,777,338,308,434,223,117,527,257,725,594,913,409,93,115,646,381,746,576,962,386,966,577,910,113,936,375,682,318,373,858,235,301,980,902,729,96,476,487,62,487,890,115,28,518,168,653,929,432,273,319,468,989,294,366,316,117,112,555,451,710,367,871,526,61,118,645,42,229,479,810,40,31,967,38,581,197,879,183,49,502,362,746,771,882,679,716,454,275,812,493,801,900,387,625,84,415,541,230,276,460,256,5,205,835,655,560,927,284,500,114,278,596,405,933,597,846,116,460,389,8,324,981,597,248,771,796,826,577,613,255,687,494,66,753,326,673,3,594,528,540,375,204,351,689,106,218,326,426,540,114,310,906,600,98,44,19,473,809,892,79,317,247,733,919,700,444,756,106,104,346,437,916,298,529,996,408,990,311,802,34,451,271,876,193,268,632,638,933,514,835,302,777,989,265,200,895,284,30,461,74,953,307,417,983,370,285,358,468,239,24,205,797,940,80,153,237,727,837,809,386,142,656,833,140,926,247,828,543,558,16,604,950,468,452,810,866,246,786,878,867,80,436,713,852,384,366,662,494,909,830,12,352,113,701,688,589,677,562,313,674,417,587,682,688,211,856,368,5,407,614,61,675,515,48,958,10,630,731,278,88,465,185,320,222,547,907,552,617,790,3,917,167,85,197,708,850,79,342,179,139,611,95,958,901,345,257,649,26,222,254,40,860,247,861,152,45,453,163,982,255,796,592,451,975,300,281,234,683,966,631,223,965,950,597,714,283,411,272,256,555,173,831,432,875,608,977,111,74,14,147,524,841,199,679,678,593,692,120,27,784,223,773,948,814,876,989,332,650,28,388,599,594,346,532,916,845,204,747,98,833,19,790,179,202,972,200,251,867,700,205,452,702,906,112,147,636,418,319,860,457,974,566,809,585,931,604,967,673,496,438,707,926,390,405,785,929,53,187,441,118,573,858,212,593,785,611,999,200,203,436,971,666,646,420,699,242,492,417,473,542,254,774,200,164,24,315,152,363,677,830,343,255,538,336,372,519,909,732,117,719,516,83,89,900,16,426,989,200,990,136,375,799,310,835,687,569,404,527,382,517,104,130,185,387,703,954,79,244,356,507,710,917,276,158,289,799,205,644,471,373,508,124,441,396,162,883,273,330,204,708,218,792,858,972,959,526,713,231,950,643,602,306,838,760,265,540,151,966,442,886,738,717,631,283,520,749,42,922,139,54,35,268,634,612,752,12,569,619,50,702,625,423,973,891,721,723,516,32,888,643,740,777,844,21,430,921,570,929,956,742,862,474,513,336,751,99,965,640,25,271,220,812,645,930,976,336,721,527,342,888,948,888,174,472,832,26,567,135,882,396,946,545,706,864,827,63,954,849,366,884,4,855,811,531,304,963,188,990,137,95,517,411,656,100,411,492,566,40,553,560,395,400,661,909,313,322,790,196,519,302,848,554,22,38,11,190,197,603,737,110,189,405,855,406,702,358,878,218,771,490,751,189,526,117,462,576,575,870,658,263,833,901,956,999,921,376,141,107,529,56,460,210,103,943,69,344,863,615,225,816,22,956,658,566,955,501,419,486,345,411,220,232,342,311,345,788,561,630,700,108,425,922,346,395,904,145,654,199,237,82,524,867,656,909,262,516,763,624,193,450,710,988,987,535,73,325,694,918,536,897,405,892,187,485,72,175,652,935,837,458,284,192,221,613,603,5,21,562,153,727,856,45,25,399,436,186,324,334,152,761,414,959,0,169,790,159,518,437,622,199,352,845,558,413,932,610,761,25,274,378,549,198,400,790,285,841,788,1,656,902,25,823,935,914,131,466,950,288,15,889,789,237,364,246,277,392,442,177,428,107,818,295,606,21,645,831,588,787,93,931,937,470,592,215,786,854,264,735,913,260,208,120,829,527,988,74,570,336,49,945,612,778,394,805,973,380,370,188,582,93,744,394,672,506,958,751,834,958,154,238,961,478,167,384,467,499,155,947,862,699,86,8,222,763,921,469,218,794,764,420,859,874,615,86,22,574,304,372,785,225,923,301,637,457,429,247,138,99,466,294,440,250,502,408,21,146,999,82,246,616", + "546,979,809,177,311,8,628,292,464,678,135,701,449,199,958,260,396,777,946,155,132,631,955,263,931,878,495,201,627,13,705,434,793,456,412,987,224,40,427,158,437,424,860,599,3,767,847,642,825,312,272,456,340,446,706,683,904,730,480,898,948,892,530,179,704,452,322,448,217,696,690,593,348,267,898,654,34,269,449,906,414,623,300,949,61,234,811,446,588,280,128,199,947,365,8,31,326,308,700,383,855,396,213,501,13,374,99,742,803,164,431,344,579,524,395,28,751,76,295,690,502,716,181,452,871,852,868,457,655,493,645,488,30,483,218,658,245,389,586,374,365,919,989,325,321,444,424,681,92,586,877,477,382,243,969,342,75,220,345,268,841,888,565,851,469,33,659,543,179,553,22,681,182,474,850,278,556,686,333,306,986,482,109,387,797,353,72,424,927,746,265,91,73,713,2,863,314,91,508,297,413,457,43,188,192,500,231,435,348,565,841,970,857,157,193,183,69,953,764,689,262,540,174,571,249,704,99,169,860,837,55,807,902,462,796,67,664,618,234,26,698,139,679,505,248,871,844,311,683,736,327,635,71,161,330,61,577,167,752,144,83,451,52,298,693,707,645,327,964,968,357,511,717,9,149,139,546,310,922,411,470,758,831,592,558,381,462,430,909,885,416,15,579,394,145,440,648,612,850,685,719,684,281,316,388,958,304,66,85,677,376,357,973,448,971,339,1,858,725,264,476,398,456,528,771,878,935,815,10,276,5,499,794,470,82,528,44,986,546,116,960,780,358,240,198,713,703,963,598,975,282,999,878,422,144,184,934,738,182,373,554,11,841,8,351,646,122,374,928,833,59,698,489,156,244,916,407,130,960,248,209,173,83,470,977,943,152,910,857,223,619,166,686,902,177,756,337,281,328,144,484,100,854,628,655,985,576,966,48,329,616,236,992,461,784,149,916,31,141,626,40,253,566,147,554,306,415,306,571,364,328,530,585,567,584,708,571,653,433,139,751,226,645,922,456,1000,695,542,609,672,494,449,792,107,843,362,586,820,515,733,189,93,807,292,52,860,955,412,411,216,910,371,938,880,975,430,307,869,854,555,696,801,362,426,88,998,756,947,923,644,818,197,62,652,162,921,127,532,684,729,140,919,828,596,70,325,522,581,561,914,26,130,830,228,273,854,945,266,595,540,433,3,951,929,258,719,577,566,102,156,952,472,111,963,188,906,638,900,53,413,575,743,790,581,121,896,198,236,657,810,7,171,795,991,844,156,450,555,49,977,17,470,272,26,670,64,320,717,609,971,15,862,113,596,522,402,473,751,537,201,795,694,605,53,274,154,904,614,921,984,48,692,973,476,692,189,216,92,297,826,996,744,307,544,608,140,344,957,380,67,525,64,513,729,545,432,622,134,362,736,889,416,87,391,446,921,644,151,333,238,718,808,324,858,896,642,777,34,248,352,883,639,166,40,76,754,327,958,333,222,432,277,513,971,63,133,139,975,738,349,105,880,774,217,526,609,602,690,927,682,619,590,557,990,967,996,388,307,451,555,775,542,859,176,940,967,51,201,953,846,81,37,176,679,409,342,947,330,430,540,770,347,849,56,267,153,212,292,797,581,212,291,598,277,547,396,18,717,568,491,526,217,903,941,685,834,690,168,625,257,706,479,864,112,414,284,82,557,564,801,539,950,136,450,184,38,572,420,216,905,654,772,977,34,336,817,864,172,335,633,337,729,378,960,217,926,330,106,824,771,192,187,957,687,565,925,963,563,594,24,239,334,882,633,684,380,661,555,710,124,626,660,276,417,203,118,151,52,571,776,693,215,350,980,627,535,405,814,357,287,509,139,565,338,296,48,702,106,391,133,572,202,605,250,918,110,659,660,238,215,281,867,307,922,176,505,765,421,185,78,487,205,656,835,227,942,564,592,666,16,23,913,169,0,109,298,84,696,894,33,845,24,755,31,957,256,477,372,7,899,883,731,696,695,186,939,462,257,514,90,498,833,402,807,764,951,717,497,450,718,570,468,684,953,484,400,902,863,868,871,370,797,432,833,945,288,397,916,292,943,135,476,854,980,509,221,919,95,100,376,349,296,618,154,651,997,20,674,14,800,238,139,702,543,724,508,34,560,998,710,954,805,111,915,618,1,529,736,648,448,630,531,191,550,579,607,833,995,656,575,923,113,10,968,916,649,44,66,516,452,415,170,238,150,757,677,767,887,910,427,97,83,122,679,260,119,611,734,371,844,469,673,26,505,937,506,908,975,723,181", + "178,431,605,97,195,63,331,231,66,420,762,113,806,95,824,39,628,477,233,88,201,852,767,34,190,40,862,503,478,683,599,357,628,38,44,520,298,953,629,792,492,293,553,103,154,510,238,444,843,644,276,758,67,149,686,570,395,841,91,81,479,679,927,711,537,818,381,677,767,216,306,342,98,657,227,648,10,702,582,51,716,227,931,673,563,941,931,34,715,329,373,448,771,219,736,229,879,224,465,819,640,774,133,77,653,244,709,45,499,146,560,974,452,3,431,799,200,620,302,845,226,383,168,262,819,388,245,700,689,424,945,142,355,463,512,838,619,28,404,662,671,650,92,696,711,441,43,997,305,160,699,520,396,995,381,738,170,977,750,259,929,135,570,215,724,579,326,161,353,615,69,247,332,763,427,931,598,426,438,209,996,357,532,923,816,331,406,846,256,568,622,40,782,740,745,473,995,20,812,127,732,813,713,861,210,852,998,96,204,714,742,28,264,461,172,12,502,300,327,991,189,483,288,130,635,908,157,889,686,520,848,405,376,916,408,439,443,270,965,335,49,545,77,938,665,916,50,699,439,317,62,143,955,239,921,582,469,565,567,64,780,931,991,267,956,603,134,350,179,666,204,95,850,637,935,40,181,600,320,98,752,112,794,162,604,254,546,700,311,406,294,958,37,162,627,25,72,902,751,277,274,236,558,529,401,923,345,950,903,434,711,926,571,886,234,99,127,422,265,529,827,868,934,640,557,904,188,262,343,228,279,795,564,959,877,849,681,592,615,47,868,193,883,241,475,542,28,430,130,192,540,828,991,508,899,558,974,375,30,712,367,370,796,833,268,804,813,240,105,355,187,258,980,920,442,867,696,475,744,832,431,601,328,575,972,353,436,881,794,264,485,103,750,128,730,223,487,64,672,518,534,295,756,742,305,409,227,712,422,951,778,473,190,71,331,404,518,972,39,950,552,139,404,673,655,580,292,400,736,458,33,438,655,576,181,614,994,85,758,390,656,736,621,940,534,447,953,326,827,572,776,786,772,792,831,393,150,99,525,797,297,506,4,593,968,564,302,212,983,19,59,214,374,624,361,855,693,114,936,634,291,157,118,500,389,875,599,256,174,903,339,549,623,244,416,316,879,415,366,667,85,90,127,905,755,51,739,462,176,246,591,33,985,768,883,175,847,128,515,173,402,804,898,844,588,90,292,748,350,418,9,200,364,425,627,797,945,506,466,400,842,396,184,420,477,28,897,22,78,548,688,664,396,497,299,634,208,920,898,139,142,31,598,998,415,496,777,907,189,932,374,623,931,981,434,158,865,115,148,666,475,897,265,499,577,182,937,228,914,393,859,9,151,111,285,744,321,628,65,199,61,268,210,956,750,832,562,246,46,477,281,483,236,476,810,649,88,118,615,932,264,973,411,722,477,656,780,69,650,43,516,587,683,376,686,341,315,818,323,640,824,637,314,267,65,822,197,499,951,725,164,994,752,88,507,123,137,918,779,419,100,159,471,41,860,194,106,552,856,603,522,300,230,312,876,304,692,302,147,949,513,749,113,169,215,583,835,501,88,842,604,240,726,200,390,134,994,46,650,149,954,112,40,312,298,130,728,297,906,104,918,180,511,410,499,591,794,896,269,380,29,569,592,149,45,724,141,413,731,155,875,909,204,469,955,142,465,62,282,818,439,476,364,314,216,968,119,875,460,97,225,842,857,616,423,62,356,507,605,97,748,62,574,600,430,634,732,269,586,202,173,125,421,270,165,54,554,857,162,220,961,645,971,122,725,984,386,219,540,407,5,885,174,679,378,730,255,551,526,777,669,835,872,711,581,724,459,494,584,663,725,845,585,50,416,113,772,49,725,510,252,362,751,286,238,976,218,551,804,433,130,24,741,966,246,737,551,249,268,304,327,4,367,603,744,805,232,182,797,537,707,803,790,109,0,247,16,446,814,574,694,77,385,134,937,824,145,539,31,917,137,505,690,725,394,770,301,584,300,61,146,530,96,347,895,59,693,24,927,688,765,217,968,457,9,204,865,95,2,274,227,902,301,64,299,547,521,133,821,21,301,399,919,876,186,808,752,443,456,414,199,519,606,241,390,665,914,869,487,504,293,612,392,691,405,404,795,561,122,287,771,387,821,872,328,435,481,170,130,83,253,965,117,957,501,624,909,890,862,322,734,639,452,152,361,937,462,982,136,827,705,994,4,537,917,523,106,665,611,940,357,296,373,105,685,227,786,927,376,221,571,135,653,37,358,354,231,291,735,950", + "718,640,36,858,652,73,591,356,249,213,351,834,349,833,664,121,845,93,866,371,932,790,876,332,319,86,942,824,402,918,782,797,186,432,269,906,555,731,911,725,40,509,845,455,805,451,233,937,207,990,452,451,682,12,118,403,757,632,266,304,51,805,560,50,554,606,776,837,931,555,402,400,20,205,603,596,610,835,993,668,429,870,435,464,442,636,216,16,336,350,998,713,991,698,420,674,980,36,829,95,692,976,989,209,208,760,539,388,726,519,327,624,188,959,623,297,478,759,965,666,740,679,173,825,471,385,746,147,635,75,473,629,706,721,657,638,783,903,415,366,124,798,482,410,632,500,579,433,990,261,558,374,600,5,10,31,79,545,626,206,524,167,748,958,644,375,66,496,458,74,556,764,664,212,778,323,738,103,707,39,398,408,8,677,219,70,527,885,511,577,217,799,205,78,631,990,866,649,387,463,992,792,923,467,901,595,657,668,214,492,21,407,83,293,103,188,870,380,139,450,381,352,73,236,583,337,514,253,198,160,935,415,267,928,756,440,451,376,260,215,524,124,195,429,786,489,134,580,410,436,842,614,57,678,882,641,3,903,862,745,600,174,508,36,236,682,149,741,199,869,367,635,648,713,569,393,832,669,490,481,112,273,483,657,645,829,355,926,328,384,405,309,44,582,207,321,446,105,282,20,910,213,927,553,39,8,613,678,693,826,149,327,236,320,684,767,869,508,544,971,685,199,745,424,579,262,576,169,481,937,128,617,741,682,2,606,863,776,870,413,958,671,894,327,908,984,268,812,183,339,960,692,671,684,240,737,544,712,900,36,870,213,906,616,440,644,791,955,708,976,485,866,698,754,775,929,631,928,5,317,484,91,764,527,130,898,392,549,728,52,743,667,450,446,814,786,676,118,766,823,945,511,840,257,110,567,498,78,597,519,552,268,176,517,408,999,498,955,352,966,253,725,431,430,715,446,792,628,376,687,647,801,271,9,949,830,823,498,982,141,974,966,167,206,7,371,867,739,870,780,179,617,293,991,206,588,342,305,125,730,469,781,214,161,800,778,752,39,608,576,701,697,34,84,465,905,553,814,761,887,353,393,434,366,178,568,942,287,212,571,361,696,385,849,74,877,125,902,874,670,568,361,473,671,892,523,8,334,193,354,671,405,521,928,929,771,764,393,500,359,156,767,632,494,291,96,387,899,585,964,172,961,422,880,694,858,621,712,720,738,669,955,259,498,573,778,443,973,117,242,715,648,158,50,663,528,597,326,132,924,512,498,194,328,311,630,307,667,706,167,616,505,388,634,35,727,827,269,120,740,623,292,295,901,186,389,829,573,829,790,309,148,992,906,867,614,439,30,685,25,355,745,912,807,77,648,890,426,478,395,778,572,424,87,410,775,333,892,997,255,921,585,188,970,948,17,156,911,316,387,409,272,816,705,607,588,722,884,174,59,907,912,300,604,894,929,705,552,233,479,797,572,626,486,995,493,130,573,628,20,392,842,78,47,692,237,391,180,348,910,508,95,881,961,596,552,3,989,280,808,220,936,292,483,245,72,820,690,146,570,769,704,857,176,951,860,678,546,568,324,829,426,666,170,999,789,780,901,757,552,679,34,450,677,531,847,926,572,544,432,658,112,313,62,641,500,803,282,191,54,172,948,214,137,951,35,627,972,731,30,606,490,961,835,898,677,619,660,7,155,304,156,455,133,495,593,952,2,312,295,721,186,12,967,386,616,840,458,857,802,456,447,765,503,954,291,880,707,231,503,860,463,658,418,203,471,480,783,147,242,93,878,365,77,717,22,685,646,571,637,722,749,786,241,84,245,295,211,971,875,182,241,89,754,374,981,667,473,890,549,98,482,619,959,772,93,673,836,81,319,875,846,749,831,365,585,65,395,23,404,328,198,399,238,630,546,867,811,800,858,56,918,159,298,247,0,578,536,40,698,17,609,509,403,155,797,25,807,25,146,937,479,95,378,361,5,753,240,629,351,718,900,894,538,26,252,313,348,952,281,456,446,990,444,643,299,18,661,895,821,322,767,709,423,727,184,335,230,514,374,378,92,106,466,606,981,426,914,297,348,14,391,754,140,642,890,404,971,722,370,362,160,114,885,456,400,710,614,465,498,954,864,339,893,456,821,851,978,597,644,405,324,27,886,86,735,353,11,420,562,595,947,603,749,641,111,658,997,150,800,875,555,203,62,323,397,803,390,727,948,984,361,847,773,571,301,826,481,65,185,16,101,117,986,538,419,593,110,805,39", + "124,688,197,890,81,889,964,780,132,168,375,394,129,448,782,707,855,188,178,424,660,426,336,62,679,554,451,756,982,328,950,28,736,848,461,767,355,833,805,178,122,825,606,242,34,768,902,771,325,680,234,882,2,546,686,857,447,273,658,148,740,266,701,228,727,120,873,561,48,254,344,235,187,497,572,309,818,314,68,569,63,426,581,548,282,643,250,809,564,778,866,59,634,181,812,511,20,983,229,863,95,66,242,167,244,699,143,905,436,339,59,885,773,921,627,990,699,278,236,151,571,645,159,389,315,108,988,412,313,988,244,410,947,150,821,733,341,81,391,337,644,908,249,707,945,92,631,485,567,848,455,288,369,41,541,11,885,581,119,649,44,410,52,828,831,752,88,428,61,331,226,819,954,168,122,351,451,28,217,611,765,555,20,224,789,961,819,26,141,245,169,893,242,463,890,165,956,695,807,78,359,593,596,679,112,987,666,302,731,8,629,414,855,424,635,387,13,844,441,51,827,698,689,148,879,552,969,931,492,834,932,533,511,112,100,628,756,412,61,191,689,781,82,186,878,335,895,621,610,280,789,765,626,138,352,512,730,588,537,865,334,191,190,11,419,798,612,41,235,251,85,198,585,265,316,649,73,44,661,424,807,328,783,461,478,461,889,160,150,954,48,325,80,569,666,987,762,203,990,74,907,221,499,495,215,412,806,831,820,171,767,438,866,305,488,597,605,591,34,645,332,434,975,294,128,919,851,505,881,103,57,151,285,874,74,598,238,735,191,757,286,988,33,526,677,263,119,486,163,381,667,374,294,449,20,843,507,210,321,174,244,222,804,109,321,268,846,848,167,301,982,2,44,346,486,159,657,937,741,815,334,581,679,815,556,5,285,199,420,503,926,584,697,9,818,887,110,895,756,917,707,560,886,484,947,82,369,500,822,654,527,650,636,148,277,486,430,332,866,733,358,615,518,443,209,730,810,30,220,499,596,839,319,123,498,975,403,207,62,157,759,373,657,386,522,938,583,734,814,319,356,96,3,35,308,382,427,710,632,822,614,418,897,543,491,975,800,160,672,902,383,545,8,272,455,608,941,111,279,129,432,819,483,30,970,502,568,29,405,675,689,179,510,907,737,241,775,163,271,374,276,871,444,511,557,54,626,396,343,261,653,707,458,359,785,561,671,180,226,927,59,95,751,987,94,631,746,137,163,29,912,555,847,643,239,703,238,699,563,587,677,746,627,196,496,162,602,154,85,636,155,27,843,955,506,681,534,282,236,643,686,544,904,439,627,195,421,162,794,702,60,212,837,510,32,587,27,198,24,105,685,483,841,390,783,466,10,974,335,339,851,481,415,944,734,16,68,552,55,476,152,950,185,172,968,126,840,772,598,932,224,543,781,505,834,462,796,23,99,587,985,659,230,43,340,526,276,518,778,423,617,193,859,864,172,42,788,519,527,495,854,917,314,290,357,379,259,977,99,430,849,735,22,738,552,491,597,476,207,391,933,645,526,922,889,868,848,210,873,660,828,98,319,79,465,935,832,674,453,72,658,348,929,411,778,374,381,566,448,818,906,402,342,424,874,416,142,880,411,940,908,753,420,348,429,952,629,566,365,37,574,145,891,244,471,335,796,532,467,476,348,351,786,620,536,290,554,108,698,889,371,634,889,168,379,40,746,950,195,717,439,580,25,923,805,600,840,596,298,33,387,322,445,676,446,894,315,782,322,420,163,587,822,512,328,623,680,766,575,269,419,527,3,553,589,248,483,127,49,886,142,567,540,147,969,801,690,958,192,238,574,848,960,137,768,60,129,395,962,975,531,284,152,870,204,543,889,15,476,465,101,25,262,207,982,482,44,491,521,485,639,304,99,241,37,685,42,193,551,408,662,923,167,314,813,817,694,727,442,234,917,23,84,901,283,20,308,492,533,628,339,111,518,84,16,578,0,180,259,815,715,387,273,164,569,633,769,594,166,660,540,134,29,296,557,786,614,682,330,705,249,36,371,492,441,602,441,478,796,164,794,43,561,914,289,238,162,55,605,769,511,192,874,440,966,26,203,30,686,54,799,511,712,941,852,516,758,339,462,320,590,872,427,833,170,41,794,703,13,704,181,218,673,655,633,957,87,382,533,601,616,172,18,225,293,274,126,381,73,798,724,237,770,424,646,174,396,667,63,318,776,483,33,803,740,386,657,270,369,680,125,369,906,665,102,342,967,492,255,2,553,991,288,726,649,615,721,625,294,969,803,436,65,895,638,231,344,854,942,778", + "397,805,183,591,95,91,91,5,882,606,856,319,921,773,243,487,416,26,192,563,843,95,642,826,121,255,44,350,990,343,618,549,124,244,912,631,473,273,257,581,166,886,556,55,826,73,301,404,317,769,963,347,352,796,173,832,764,872,287,924,384,850,737,609,985,808,528,822,72,77,614,805,86,433,371,958,962,545,991,41,620,679,505,172,485,110,82,20,567,202,428,302,94,710,697,93,672,816,453,336,867,29,76,371,540,854,315,710,705,546,418,876,604,73,854,676,687,729,86,875,210,773,117,954,315,250,747,682,560,905,895,320,687,204,672,323,775,112,901,912,951,448,447,777,282,673,366,954,291,581,211,400,661,733,45,974,191,31,295,794,407,181,994,454,592,984,624,924,339,412,358,313,805,73,269,535,212,60,396,90,864,908,837,524,895,903,135,691,853,74,178,151,544,139,340,840,24,604,797,740,522,19,619,490,384,186,405,108,311,581,397,679,666,586,690,210,295,782,456,12,498,212,596,556,883,969,697,490,969,641,632,5,905,790,990,685,300,521,245,887,622,172,387,558,822,158,796,218,640,205,809,162,895,241,809,880,542,471,239,696,812,283,397,445,83,364,413,785,602,48,799,383,966,648,121,305,922,619,998,59,445,655,526,645,333,239,273,505,262,159,246,760,914,181,124,417,306,503,473,796,461,729,940,502,882,423,723,485,873,896,895,392,103,929,985,747,697,707,454,687,404,879,77,562,985,781,96,336,219,569,121,503,718,510,80,271,150,18,848,257,968,402,778,391,804,821,491,263,522,703,74,360,509,674,273,148,997,955,55,827,488,714,893,219,479,167,246,498,745,722,475,420,961,349,680,901,732,223,13,159,574,770,988,203,845,426,81,645,570,234,588,793,53,825,179,2,654,644,437,583,408,133,14,731,61,481,41,883,442,407,427,999,152,481,936,422,63,520,626,859,435,113,237,7,312,300,495,604,339,903,673,989,383,179,984,993,266,911,494,541,190,377,849,37,800,574,846,129,270,726,626,928,409,657,89,270,219,529,121,919,76,593,933,879,125,91,604,568,635,674,499,548,808,107,261,40,511,772,861,21,526,266,784,78,396,516,750,723,241,72,527,88,442,36,903,116,464,240,25,706,641,416,323,288,302,600,939,862,676,980,794,909,499,579,215,678,609,161,743,171,573,267,921,558,6,551,593,23,45,821,994,718,726,216,608,974,368,629,615,860,429,904,82,836,491,606,951,570,520,289,331,749,564,617,663,382,381,745,16,931,284,890,605,153,793,198,256,866,96,34,986,542,665,561,725,6,987,846,688,47,124,843,386,795,305,964,502,292,855,423,933,878,22,488,51,877,404,165,80,666,929,287,315,745,271,668,606,501,112,216,205,846,982,155,698,471,529,387,777,140,791,504,655,328,807,179,621,967,63,967,924,234,457,469,521,563,930,3,2,139,882,114,147,428,913,420,265,457,933,566,451,796,267,297,363,937,207,826,540,508,632,936,997,390,58,484,926,819,475,527,888,399,991,498,521,231,449,789,839,251,99,778,658,259,714,749,162,599,917,498,308,568,904,155,734,898,492,770,480,287,929,163,689,355,129,988,67,689,789,455,495,676,755,162,714,718,501,299,3,597,208,724,519,48,430,881,131,773,709,776,104,559,841,124,354,987,920,185,215,932,597,221,764,36,268,279,94,218,760,863,295,829,136,109,479,839,546,486,455,802,278,243,305,122,570,513,358,81,900,340,792,866,915,955,860,409,396,765,132,569,920,647,588,104,753,457,398,682,514,796,653,100,521,472,901,757,317,632,597,573,704,320,964,722,554,741,280,552,834,846,616,105,895,920,571,503,60,293,821,108,684,763,202,111,991,350,685,206,204,840,219,47,123,860,604,446,458,400,37,259,873,974,877,865,488,414,646,825,774,498,492,915,437,696,446,536,180,0,674,427,610,449,92,530,892,965,152,979,462,972,46,351,880,913,476,254,785,536,562,348,860,194,603,151,978,948,221,140,72,928,879,862,293,131,363,877,176,913,537,149,699,397,241,386,717,397,370,830,940,428,63,114,185,352,86,363,302,3,582,727,369,159,546,324,322,309,589,232,515,358,180,994,224,378,842,921,556,955,606,162,231,270,516,113,414,80,593,246,102,963,30,408,667,957,966,960,808,957,990,632,409,998,418,850,488,276,951,755,400,927,861,796,447,615,53,869,357,429,901,715,984,478,658,663,292,450,125,78,269,823,848,853,132,943,149,920,266,271,657,495", + "234,386,639,23,307,873,823,718,320,39,300,251,428,327,161,572,881,244,325,334,232,772,638,456,856,233,246,958,95,891,666,258,356,457,293,520,961,834,184,895,517,66,891,840,92,385,897,658,489,612,474,928,649,768,275,536,682,424,278,607,917,4,760,190,263,206,88,916,595,834,892,521,717,268,721,634,887,461,189,629,611,534,367,673,487,493,281,281,926,637,360,594,518,103,685,259,162,829,709,250,791,368,648,986,319,956,533,217,582,146,415,368,639,454,349,325,484,481,399,873,827,54,738,180,317,347,806,466,519,594,746,849,781,740,711,398,921,258,222,856,895,494,255,421,315,295,458,618,596,184,884,772,530,441,303,927,280,920,714,252,599,706,811,509,517,983,849,918,798,941,415,885,431,246,586,894,57,612,227,876,957,590,106,826,272,269,64,479,365,956,705,399,893,760,811,937,818,166,512,953,457,987,846,727,574,888,365,879,870,666,249,82,749,266,432,531,379,396,238,343,3,800,613,977,995,86,55,746,452,743,812,622,455,173,411,312,648,867,559,497,522,333,943,8,189,338,202,396,435,794,402,556,600,618,659,993,786,10,816,283,725,176,404,518,651,376,537,776,812,532,902,613,463,664,871,307,728,313,664,308,449,509,969,297,820,63,494,176,399,949,281,886,345,803,165,757,704,485,643,933,316,860,890,991,276,716,128,628,743,13,378,512,497,911,157,649,120,67,584,404,407,681,382,608,527,597,202,254,32,676,237,793,520,513,477,522,685,136,239,420,829,223,865,472,731,71,312,243,523,700,191,584,677,173,455,6,391,949,829,630,693,100,384,435,19,238,267,384,979,908,76,729,688,175,188,639,134,692,215,141,224,360,80,948,208,188,181,368,295,376,70,702,767,37,219,534,182,885,36,775,713,581,177,972,780,110,304,148,272,238,692,790,830,347,157,462,74,549,485,132,924,666,884,1,509,290,146,762,898,293,670,62,182,406,512,32,434,447,484,562,387,797,895,614,586,642,360,660,906,28,782,423,127,115,433,308,562,534,207,468,278,869,807,757,371,74,358,489,192,233,10,487,642,168,107,618,250,61,567,247,445,454,433,521,643,297,108,389,586,690,435,260,642,555,24,653,746,651,665,265,624,118,331,806,416,392,711,208,879,555,122,602,97,496,913,981,559,211,480,331,539,411,977,672,942,950,751,154,373,157,698,771,732,70,858,364,765,297,921,818,490,566,548,9,96,343,926,289,754,267,309,828,356,107,273,460,520,32,839,497,940,443,973,811,234,651,907,353,56,591,202,640,727,908,815,910,665,670,873,932,172,784,607,606,197,121,648,855,561,242,668,622,229,409,473,475,156,620,337,870,227,695,280,669,365,143,702,929,445,541,313,919,495,718,879,880,185,447,208,103,809,937,639,98,288,24,934,699,218,296,606,379,553,583,377,455,702,687,703,534,300,28,53,459,833,711,761,204,186,632,603,846,282,352,482,449,735,493,451,33,630,422,945,101,913,488,659,903,591,573,306,346,59,566,377,314,709,979,835,862,132,721,637,617,426,531,956,304,175,779,941,588,242,869,152,972,628,975,292,648,289,583,266,30,540,58,36,195,854,193,927,365,371,249,282,557,666,965,559,518,159,705,984,62,32,60,896,33,463,439,656,543,171,315,281,389,51,579,710,54,819,299,304,48,543,384,243,149,89,891,223,363,87,144,981,224,830,546,486,504,337,196,736,53,700,914,712,297,639,624,343,714,122,629,588,692,486,750,284,838,7,616,442,443,462,378,984,541,487,141,767,421,166,819,404,778,424,353,802,427,944,86,32,882,48,973,257,31,449,356,822,909,100,63,493,799,271,8,109,999,470,577,246,578,255,44,807,934,328,733,395,342,153,715,903,665,77,209,323,885,774,302,725,169,28,284,146,987,132,773,165,161,622,894,814,40,259,674,0,896,547,259,136,216,115,738,510,861,907,835,738,103,503,235,487,468,838,800,872,330,738,468,179,317,390,177,588,348,44,883,939,812,347,998,163,528,351,803,759,525,789,824,44,972,503,445,627,497,651,794,620,320,39,248,842,347,554,432,117,56,113,969,563,828,845,118,581,469,570,175,703,746,802,167,766,865,744,944,183,932,616,923,859,599,265,366,224,267,271,786,831,687,527,809,163,366,466,794,714,628,290,160,116,312,736,326,173,584,858,884,115,675,983,717,745,822,209,930,606,230,279,711,871,161,739,194,60,488,117,457,92,339,728,909,515,829,300,145,376,892", + "251,809,333,84,739,829,41,752,215,836,833,534,881,973,238,524,196,138,521,992,134,433,451,643,763,932,22,540,308,219,542,558,80,796,545,744,306,872,428,915,95,312,167,881,109,740,728,485,655,73,515,375,159,611,880,522,154,123,706,848,685,689,379,828,158,259,76,933,823,265,292,716,914,113,306,318,662,731,11,734,456,809,757,522,176,583,3,812,109,518,814,546,771,166,274,358,960,761,691,599,206,323,153,409,202,160,233,659,675,785,200,287,570,753,147,422,861,23,206,237,707,768,433,647,857,500,520,548,677,808,660,863,650,662,876,656,763,110,36,840,933,504,699,838,89,474,10,61,508,796,781,63,166,768,752,373,189,459,461,103,79,790,799,961,109,123,268,193,678,848,617,47,352,132,464,225,58,147,845,715,360,424,733,899,900,488,771,302,631,579,861,813,638,883,95,860,625,167,41,282,979,785,49,926,415,236,579,498,195,696,774,105,494,16,434,58,841,634,143,380,680,987,911,858,824,948,554,10,763,581,680,279,345,897,622,886,468,214,686,535,799,179,635,737,671,521,110,736,561,197,207,551,738,583,211,510,661,569,515,439,3,241,432,982,409,314,296,992,221,828,227,275,113,289,959,126,56,38,24,730,292,408,550,565,164,77,866,830,762,897,24,233,118,351,616,524,824,768,483,455,963,61,974,682,585,381,651,617,202,330,107,54,295,5,37,779,325,943,745,71,861,756,369,588,223,930,682,387,419,377,911,527,560,416,814,766,265,861,934,864,275,17,62,783,823,140,244,54,837,151,536,117,719,563,850,144,645,956,660,796,247,657,379,604,185,143,712,670,898,531,154,816,43,347,655,125,508,262,990,505,935,53,434,85,478,452,859,822,27,858,63,826,667,117,839,38,836,641,557,900,614,593,466,491,809,18,448,198,437,282,632,462,770,180,871,883,473,143,341,991,822,704,618,188,721,883,784,634,328,852,562,644,161,706,777,976,211,603,904,931,65,668,938,906,659,637,88,639,700,816,622,188,306,93,718,956,459,711,927,670,142,333,628,800,453,573,374,471,267,968,325,991,556,651,536,356,556,551,132,179,850,672,632,348,846,490,147,962,163,573,917,440,698,600,706,29,485,500,528,355,599,202,114,438,51,488,715,142,104,407,997,966,984,26,763,146,77,833,391,631,681,126,38,751,425,200,478,784,17,9,61,154,485,449,866,638,802,600,426,905,779,411,463,559,737,440,506,90,59,814,938,234,225,937,483,934,734,861,663,506,524,301,724,845,278,435,422,384,626,803,616,290,602,297,52,370,601,633,221,823,381,451,628,969,133,297,390,689,395,243,872,629,143,71,809,53,587,1000,489,695,555,218,434,152,576,961,876,129,369,265,808,996,740,933,3,11,898,73,634,279,888,744,455,996,637,382,637,347,349,464,613,942,824,429,6,951,382,22,877,526,74,128,640,190,30,112,107,526,732,309,93,289,524,871,81,879,140,691,291,948,638,576,976,131,310,724,497,538,978,551,166,218,504,249,695,156,178,114,520,811,380,173,337,345,158,930,840,187,447,963,634,292,638,759,882,811,86,799,992,168,832,703,269,2,875,875,472,543,400,931,405,240,679,229,354,10,324,101,168,557,243,456,337,644,630,292,366,809,656,995,603,950,411,486,501,665,691,747,167,167,304,262,705,561,811,472,660,709,475,745,48,167,446,285,97,429,839,400,439,873,275,263,699,339,464,698,272,726,45,505,290,902,246,458,745,653,300,354,165,326,443,355,272,47,632,764,540,499,389,767,142,928,142,471,638,264,84,382,965,803,555,590,138,824,113,58,637,152,894,249,950,279,41,21,181,791,65,727,52,881,543,325,20,952,706,533,397,967,382,821,569,28,574,919,954,56,428,901,474,740,294,998,351,894,884,232,210,854,141,250,33,986,199,33,574,698,815,427,896,0,283,735,979,642,689,588,156,50,959,897,54,247,295,824,553,905,583,605,740,203,226,46,831,605,405,961,609,473,397,410,329,834,99,110,834,834,229,775,463,856,946,8,869,807,372,294,35,463,94,576,227,305,141,24,640,669,101,948,770,669,432,977,514,502,676,94,976,761,679,819,438,903,982,848,676,756,269,664,301,611,123,366,121,463,359,782,350,457,754,474,344,547,41,543,84,242,395,885,858,686,236,716,886,737,294,712,316,940,562,870,746,782,799,450,712,864,997,329,177,830,714,327,825,524,109,833,600,821,453,368,563,463,256,275,509,291,408,995,932,981", + "503,863,991,945,685,512,843,608,351,27,588,247,201,853,325,689,801,246,32,908,654,84,847,675,68,478,526,146,149,92,873,223,109,877,982,494,987,927,558,534,964,580,10,326,503,738,238,165,365,86,874,641,258,461,778,98,572,117,789,700,955,70,806,336,362,985,758,101,302,396,833,735,73,30,736,588,33,478,142,493,994,247,374,770,369,55,902,737,457,375,152,139,340,385,662,916,158,246,553,957,339,571,233,871,670,679,190,115,677,757,127,723,335,846,563,208,397,717,612,232,101,158,96,46,369,550,37,622,374,774,941,419,522,132,987,295,950,127,699,389,467,625,439,547,203,167,240,725,115,244,227,243,440,731,83,113,683,20,765,292,33,292,462,801,818,700,883,718,505,442,745,677,945,506,361,110,334,42,832,553,633,129,731,39,736,106,257,876,759,820,101,164,403,202,69,684,696,368,440,609,960,505,675,530,925,978,27,365,193,320,489,109,324,628,716,754,698,62,396,121,542,429,312,196,304,122,356,857,422,575,926,692,555,171,80,349,25,625,151,527,462,193,203,853,367,254,368,436,522,646,399,38,458,139,888,424,603,442,6,221,879,384,645,217,446,970,524,88,508,257,563,94,991,787,419,636,953,756,328,983,298,315,693,352,169,687,342,942,915,638,684,349,204,608,390,992,739,80,116,873,181,384,143,980,699,570,643,303,4,861,90,97,493,810,926,191,414,852,65,199,573,811,805,960,73,977,206,382,776,244,250,683,273,948,584,33,636,906,691,886,556,645,358,648,316,511,853,973,998,728,146,333,455,465,487,809,794,213,130,811,359,172,273,188,768,782,177,116,352,311,519,339,186,997,276,866,112,766,110,922,158,796,279,669,268,136,201,974,193,353,979,108,796,419,234,292,618,859,661,918,787,691,659,842,211,416,494,396,391,263,263,313,909,64,440,714,495,587,180,874,559,449,814,211,418,649,208,176,529,854,830,283,587,825,293,960,770,797,954,837,73,192,762,389,772,809,627,247,491,569,211,418,469,186,995,981,889,414,930,909,561,765,840,480,874,999,911,291,814,977,858,838,498,167,665,494,135,47,602,209,275,643,448,469,436,445,638,407,568,438,638,543,839,640,254,180,350,971,47,768,117,91,985,603,211,725,475,568,910,79,970,259,221,113,692,609,876,115,940,944,288,1,915,85,773,147,11,294,328,425,438,146,727,101,994,980,262,4,512,194,430,615,403,308,18,242,327,357,576,720,330,533,110,464,802,642,512,463,95,710,830,711,418,378,54,592,569,669,837,91,699,860,717,63,27,448,610,580,524,5,509,942,487,124,609,450,610,6,807,122,909,491,460,354,987,317,733,355,90,929,535,919,378,761,109,607,775,652,653,647,623,843,665,682,689,423,403,256,240,304,371,392,412,242,405,503,614,243,199,954,594,807,540,536,370,265,113,75,154,913,892,665,579,303,372,894,608,40,947,973,934,262,788,600,637,306,613,689,731,810,962,965,669,853,47,395,256,181,919,280,751,675,795,177,81,705,233,531,449,718,27,285,482,19,756,401,898,925,909,157,351,601,545,464,713,34,401,955,147,429,91,154,583,993,491,986,580,505,946,63,765,149,292,193,308,780,861,396,433,551,577,804,861,982,910,34,468,664,37,708,541,412,216,251,110,628,588,479,128,793,216,325,380,263,8,396,739,454,263,318,435,256,369,733,348,256,783,81,627,748,313,633,600,770,824,428,520,488,803,194,885,809,28,447,999,802,565,156,528,117,675,524,98,773,670,790,612,208,933,380,416,322,777,403,33,833,691,779,346,419,174,30,373,972,684,512,661,644,797,584,754,767,320,567,825,461,843,259,248,709,949,283,236,480,115,50,381,849,734,174,337,707,901,551,153,935,824,310,439,112,464,951,998,229,468,509,270,143,610,738,601,568,352,845,694,17,715,610,547,283,0,362,104,420,857,79,307,301,131,441,134,449,323,469,679,87,58,224,532,819,472,781,414,103,189,961,477,354,215,607,467,799,429,845,307,556,132,921,78,830,615,863,728,746,286,388,397,871,429,638,65,966,118,76,822,366,922,694,268,316,908,453,483,715,836,605,13,918,52,682,447,363,695,710,431,767,878,299,534,774,115,417,374,772,966,21,202,789,964,42,914,126,550,778,530,448,246,92,66,919,838,365,78,269,220,606,888,782,403,701,740,16,870,652,609,129,504,873,39,393,256,542,831,602,199,3,323,127,408,430,761,711,678,572,383,863,623,545,767,142", + "64,329,644,621,403,3,605,417,191,625,591,725,718,399,824,289,835,379,573,948,308,700,480,894,682,758,121,422,461,822,437,139,312,67,986,753,200,465,78,393,381,621,208,717,618,750,493,363,450,979,142,77,756,454,604,359,287,24,925,314,953,277,211,990,114,362,419,355,743,288,925,431,424,722,926,865,138,619,914,821,16,998,257,36,884,411,722,505,495,301,691,326,701,221,357,528,326,653,793,513,575,208,86,781,455,130,990,211,142,95,695,757,947,567,544,201,305,196,391,409,828,345,92,987,230,366,820,947,519,720,446,771,669,567,509,683,849,327,818,730,908,131,88,407,131,474,688,352,939,939,515,208,210,664,939,453,502,498,22,738,529,146,754,602,956,635,232,80,109,741,992,929,993,828,565,944,73,405,626,634,460,392,456,430,284,307,431,571,143,212,29,373,658,714,508,928,249,389,245,643,790,645,770,459,372,377,756,336,499,163,251,760,613,960,301,84,906,420,642,379,3,147,535,772,908,739,622,660,837,448,327,884,949,280,916,980,87,962,670,652,422,725,131,545,311,321,695,386,757,698,896,610,97,590,271,370,405,471,917,571,976,776,215,877,391,102,829,380,450,326,346,489,953,479,532,10,877,357,311,715,487,821,907,395,869,669,410,990,549,36,882,684,586,833,288,200,629,896,750,588,658,964,634,926,851,791,119,947,637,464,562,103,131,708,748,495,82,316,880,40,801,872,679,551,331,457,288,227,134,452,250,501,221,683,411,705,695,345,610,812,907,545,404,293,992,161,741,845,273,110,30,831,841,734,249,306,285,38,208,804,691,8,189,224,315,325,553,492,765,786,415,855,998,874,828,458,576,511,809,397,705,194,234,6,684,14,728,652,800,861,7,126,658,726,640,569,939,850,105,369,923,994,516,579,472,244,966,344,824,399,623,516,445,723,467,72,732,609,286,554,685,378,152,607,581,882,944,366,111,715,422,216,61,824,387,613,892,437,526,897,822,223,597,11,834,913,150,823,948,479,180,114,221,879,835,338,913,798,394,591,92,642,902,892,594,811,790,339,808,836,770,939,269,353,561,787,176,810,765,222,377,715,702,108,235,530,86,226,284,186,128,591,266,464,148,353,586,901,525,832,763,928,344,730,55,306,932,586,405,567,430,712,990,925,573,109,950,705,342,616,341,934,5,614,287,779,367,681,343,622,137,268,359,929,505,610,367,487,171,275,686,352,526,991,740,530,343,694,809,591,944,471,944,354,912,769,388,802,586,347,623,921,138,162,457,383,335,102,600,34,560,706,749,222,532,53,806,143,534,658,450,1,419,458,700,346,880,755,624,217,775,438,111,908,451,490,866,42,129,686,925,16,914,162,872,180,86,269,197,676,118,809,58,233,396,482,380,241,825,807,96,311,700,778,500,443,444,427,953,144,118,128,758,527,997,203,934,171,296,539,306,732,926,15,627,242,677,821,379,902,856,60,529,877,602,275,216,669,253,181,983,50,861,368,479,886,780,845,771,854,89,351,37,790,694,547,202,515,261,236,458,595,832,309,703,220,736,641,739,834,64,675,154,758,955,78,323,484,585,944,684,19,993,923,975,90,53,859,630,739,865,252,561,341,669,965,602,200,204,290,145,77,617,545,432,346,787,128,642,898,97,608,387,542,171,940,805,252,238,602,652,986,264,703,803,76,334,605,158,629,363,751,859,100,659,14,656,74,963,652,808,181,863,551,422,185,381,836,507,569,351,918,279,786,964,896,626,261,994,768,428,97,601,218,931,165,568,908,460,551,208,923,150,59,197,198,934,234,496,547,438,28,108,924,62,949,904,106,73,628,574,577,696,942,780,391,901,943,299,219,354,764,214,50,226,131,910,65,303,540,373,733,388,492,957,110,850,702,226,273,326,860,225,52,859,933,32,572,393,218,431,340,845,24,77,609,387,449,259,735,362,0,641,339,731,104,361,504,694,423,457,730,875,325,496,23,905,581,266,934,360,773,611,388,733,778,438,361,855,942,713,802,883,399,411,18,234,384,887,488,605,615,399,305,969,280,966,93,602,99,298,527,834,994,896,523,84,430,56,554,123,811,205,754,641,254,643,678,516,88,618,531,646,10,5,181,100,720,819,951,254,781,101,616,619,952,54,911,698,152,942,325,437,613,933,928,823,732,43,281,944,500,20,955,682,806,489,156,204,604,835,781,970,776,975,29,252,326,792,850,837,864,461,574,748,657,588,24,890,124,877,799,423,303,847,169,250,471,135,886", + "990,152,570,755,955,769,449,928,265,777,563,882,895,179,653,220,895,251,352,421,458,435,348,462,923,448,854,175,576,179,215,155,978,78,328,187,639,908,404,971,727,963,924,839,315,618,999,161,724,608,851,912,193,416,112,224,292,637,81,965,560,779,673,259,181,990,350,963,791,214,402,993,327,457,610,866,375,817,255,428,740,888,916,871,319,619,870,500,93,341,426,515,757,834,748,422,25,467,648,41,408,484,122,411,843,595,148,49,480,31,711,224,764,68,427,516,126,767,952,743,166,524,606,184,711,576,219,302,703,247,867,958,275,646,566,293,381,97,969,348,122,407,981,156,663,618,978,5,615,892,519,777,21,488,639,673,286,939,321,701,279,131,459,420,524,996,176,81,447,21,578,163,780,293,349,897,426,206,949,871,918,587,852,397,265,729,173,888,118,840,943,640,251,986,150,935,960,868,615,406,177,105,568,890,372,28,649,39,173,201,19,340,296,952,891,927,216,786,9,948,608,37,876,863,804,454,717,630,727,912,612,482,666,440,323,252,374,501,184,685,80,639,832,159,592,755,382,267,855,271,875,499,47,945,431,486,781,475,111,527,566,890,700,895,489,543,980,877,632,999,221,135,965,560,514,437,43,3,316,35,443,246,703,884,307,941,606,911,37,173,947,885,727,484,85,667,177,331,498,330,530,967,281,994,448,139,846,534,270,85,678,748,414,100,396,359,209,103,246,464,592,55,687,376,470,449,514,419,992,575,373,23,575,251,410,171,867,429,877,661,340,230,412,482,320,156,865,727,817,55,840,238,794,979,161,524,452,726,681,815,556,577,968,898,611,764,635,833,188,173,53,198,988,26,874,702,373,862,802,197,101,847,561,619,188,914,515,251,646,476,197,488,246,925,661,528,139,921,846,797,609,155,615,450,657,417,272,144,238,272,606,59,264,506,265,70,197,735,483,786,316,398,620,95,704,976,101,26,620,933,599,382,211,644,390,576,353,822,394,868,387,782,882,177,550,744,850,723,151,754,106,901,298,905,806,71,265,880,629,238,217,43,807,661,319,180,306,221,733,129,705,765,657,830,353,55,129,25,781,640,976,543,222,346,992,751,484,215,282,978,344,902,650,87,143,904,576,553,212,612,599,571,513,397,514,33,759,111,567,649,631,549,731,226,336,237,976,95,15,323,391,762,680,619,660,671,246,65,3,547,338,938,948,673,717,937,513,369,622,476,6,624,862,341,342,969,420,244,60,902,407,998,940,442,858,32,517,437,695,203,417,109,242,593,578,277,310,39,529,647,96,393,500,611,851,342,326,561,123,968,889,33,287,220,388,139,998,745,661,72,51,738,575,780,898,151,934,696,647,921,397,543,840,797,312,53,313,382,626,495,772,230,768,962,912,328,643,316,860,201,713,325,152,166,935,58,9,578,939,800,847,376,265,411,346,944,491,857,475,82,60,76,885,832,865,504,756,144,336,829,407,494,279,569,625,895,251,22,237,66,676,88,209,494,721,460,370,368,732,227,540,77,9,429,319,405,310,58,367,420,934,889,656,411,699,850,606,763,53,313,349,504,55,500,13,795,829,20,980,520,675,694,952,267,574,376,546,590,228,371,517,540,366,637,789,948,108,829,965,16,124,758,186,190,387,418,856,438,201,580,415,571,617,352,293,536,743,963,859,5,309,682,191,683,994,585,65,214,832,711,424,216,387,638,408,695,536,395,531,293,880,320,823,484,649,12,737,43,948,527,56,9,413,447,428,107,420,175,78,503,940,713,524,246,969,76,99,186,538,693,213,814,730,132,615,190,523,827,554,334,484,757,223,458,804,136,391,275,255,595,525,793,57,818,160,592,683,390,339,244,237,278,451,690,859,376,852,951,92,64,315,930,740,541,97,878,951,433,586,937,14,190,193,683,672,959,839,352,368,825,465,869,558,755,385,509,273,92,136,979,104,641,0,707,424,890,554,881,46,936,755,730,564,62,936,537,21,285,885,531,655,317,476,600,784,129,927,198,316,620,6,831,102,440,315,180,976,468,572,759,659,10,774,500,212,757,347,181,457,641,107,81,940,269,60,328,58,285,109,297,307,572,468,94,956,674,153,244,762,702,117,55,722,733,800,687,884,525,445,284,577,927,991,652,290,539,830,461,524,991,903,463,37,353,35,501,165,616,830,777,111,837,465,706,542,42,746,659,247,738,384,826,838,178,639,656,864,296,234,143,717,312,51,340,578,163,278,434,915,265,364,363,191,529,397,91,839,804,13,484", + "295,131,761,459,525,862,123,129,690,4,882,884,656,252,595,44,798,173,171,350,899,516,313,764,435,21,836,775,434,553,450,787,105,854,484,645,443,668,172,922,216,737,153,600,24,518,171,234,496,431,81,614,392,968,726,431,573,133,234,228,385,92,991,913,564,851,105,509,89,916,430,442,595,879,325,646,953,349,878,819,366,494,62,114,589,590,804,47,508,728,79,693,428,218,726,360,770,29,611,486,235,514,789,2,646,244,568,786,741,715,82,415,381,580,530,732,595,979,2,944,992,145,894,852,779,937,823,419,416,3,997,648,858,708,318,175,909,219,710,504,448,897,669,734,753,111,557,565,300,834,642,856,11,982,934,373,893,673,794,672,728,224,803,832,776,604,218,176,785,275,299,649,187,627,811,147,743,831,925,859,765,822,961,486,93,639,170,312,877,341,572,61,547,883,791,25,158,603,894,703,348,895,456,180,200,872,134,670,713,513,329,585,651,650,256,293,209,547,182,510,433,927,229,367,440,370,471,652,306,46,22,779,420,319,878,11,932,457,644,908,375,246,154,240,957,282,848,506,497,388,672,576,204,194,129,888,79,981,263,984,329,341,669,237,568,118,216,354,915,988,227,702,211,124,203,927,633,870,415,186,579,778,871,188,655,492,325,734,448,249,169,123,155,135,538,47,62,52,918,418,541,24,97,187,325,776,474,268,711,54,21,941,204,848,809,81,465,444,502,350,453,950,173,419,965,2,834,428,117,51,675,392,374,500,88,793,756,917,717,795,305,150,806,138,185,359,6,17,560,313,168,879,607,811,388,536,935,999,945,428,435,186,881,271,52,810,897,904,931,623,94,790,348,340,525,23,113,762,85,200,981,450,650,826,154,43,907,395,112,525,986,541,603,448,987,398,243,84,842,559,969,899,615,41,833,286,742,698,454,2,699,841,119,966,865,38,489,759,51,118,795,572,857,424,396,969,757,122,592,538,123,798,275,638,92,133,499,848,913,469,118,633,736,266,732,129,729,979,577,142,848,241,622,797,167,23,958,674,215,676,326,96,28,384,851,986,607,322,775,509,273,870,783,299,536,762,715,233,11,909,627,306,959,448,775,428,606,37,107,504,485,85,180,590,740,288,862,861,20,245,401,806,582,133,201,257,935,346,58,741,259,312,454,894,812,135,294,35,152,328,156,848,928,478,847,212,877,306,593,359,184,183,949,521,555,749,96,813,902,266,50,618,682,225,229,77,835,196,340,458,506,159,816,782,646,234,606,118,272,825,178,862,635,448,615,508,223,210,764,694,379,136,270,828,523,304,153,964,826,559,670,496,702,986,152,385,497,436,86,343,829,530,835,136,986,387,788,783,676,812,242,526,949,974,711,306,456,955,188,469,355,482,803,517,631,886,41,406,19,766,739,493,823,144,436,217,586,793,432,868,795,74,190,409,6,447,232,607,340,669,445,641,931,969,444,453,838,451,136,379,354,645,899,886,108,845,852,620,445,493,401,609,559,909,720,872,811,426,385,759,645,518,902,622,816,544,908,818,326,959,304,314,243,667,395,113,496,96,194,991,467,449,827,470,967,824,621,18,936,53,826,508,492,898,499,266,835,170,847,940,28,650,525,587,313,41,538,444,856,149,133,658,793,295,414,438,622,459,358,697,579,190,894,22,766,550,916,488,808,340,172,442,184,298,273,463,242,298,115,324,964,979,396,676,640,121,177,47,721,780,38,941,460,798,40,881,590,415,26,999,303,413,94,575,763,524,774,541,756,465,809,327,391,970,607,972,76,150,852,214,158,66,864,980,200,821,54,64,960,298,344,744,864,994,365,602,77,853,401,711,570,870,43,686,978,334,760,716,495,571,215,591,296,940,99,161,39,708,646,886,247,707,656,704,528,304,693,387,40,924,762,82,955,967,196,806,668,13,38,581,721,759,413,31,134,403,164,530,216,642,420,339,707,0,917,812,790,288,662,731,939,418,920,63,398,617,227,39,671,142,716,751,733,399,100,752,82,405,919,81,832,214,414,171,224,31,773,408,968,621,8,70,970,230,617,749,32,783,956,191,221,592,744,278,943,187,699,220,494,11,20,653,2,542,374,415,55,752,340,382,5,352,408,46,52,304,289,356,67,349,803,913,778,942,534,285,870,744,920,868,155,892,24,465,150,303,660,797,951,956,530,552,892,973,333,214,959,603,346,478,329,860,875,298,238,415,386,735,353,922,683,480,510,660,781,373,567,36,902,150,486,18,404,154,48,888,584,228,976,1000", + "733,603,180,536,289,225,361,191,28,392,661,828,742,271,180,789,393,197,259,474,808,521,643,984,164,152,954,634,609,554,566,641,623,645,182,934,812,611,913,229,333,992,839,785,388,815,810,310,959,988,758,329,335,54,603,509,672,690,868,351,787,645,932,289,339,102,767,549,357,350,332,410,49,751,261,24,354,562,585,447,802,279,893,484,180,83,650,347,133,896,285,323,608,101,378,26,777,737,611,633,580,579,844,175,68,982,583,845,959,734,875,696,12,609,630,948,760,225,909,24,467,381,12,805,414,733,53,24,119,813,263,795,389,592,814,445,151,472,629,878,150,26,819,141,380,865,862,295,538,861,988,680,558,491,751,377,865,298,376,949,122,968,136,514,407,915,244,173,661,327,780,433,104,401,594,771,914,554,41,810,556,575,302,814,595,60,538,329,828,78,657,500,771,29,734,282,358,110,606,518,227,159,465,355,189,922,397,736,342,457,878,976,303,859,576,692,606,55,84,443,941,613,635,555,960,670,37,842,86,173,858,535,942,454,67,155,545,462,436,38,532,818,603,175,853,607,156,840,715,795,512,454,886,693,918,163,573,105,942,570,173,765,997,782,990,179,54,92,507,64,86,187,184,868,827,787,348,769,947,928,966,794,316,780,957,218,870,390,86,290,11,682,69,439,451,480,338,963,570,556,168,366,214,215,781,508,712,889,275,43,284,867,145,81,306,319,210,23,343,852,808,723,544,901,911,651,564,777,969,905,706,709,537,392,707,255,695,34,158,740,297,940,765,403,198,399,17,618,920,116,893,903,667,731,90,998,958,61,825,235,74,208,915,674,613,471,37,994,393,870,303,701,161,877,543,685,391,212,94,768,225,302,672,770,430,256,270,783,631,378,51,352,519,420,619,103,203,564,323,857,859,522,381,631,296,514,791,583,811,263,911,933,722,373,100,610,392,678,135,775,854,492,409,205,453,888,571,573,888,426,81,885,543,999,424,502,886,442,208,575,209,26,265,272,277,228,992,593,900,653,329,466,428,792,376,779,751,528,448,541,374,16,249,35,107,137,714,609,733,47,628,91,705,805,143,636,700,89,788,25,559,594,828,684,455,554,908,456,235,546,394,799,239,870,417,772,547,918,298,361,760,20,218,256,888,746,771,645,67,198,74,895,21,446,598,214,586,241,951,461,863,649,48,615,223,279,655,861,142,392,635,328,771,45,489,398,727,961,84,70,426,710,808,861,652,495,545,799,961,434,986,697,999,173,414,755,241,601,763,494,204,505,975,698,29,168,770,494,333,148,297,894,97,637,119,753,914,894,517,797,857,658,980,384,226,404,494,779,56,592,20,984,950,699,863,746,316,198,942,851,13,330,46,104,283,464,796,96,877,288,73,383,549,863,642,921,995,759,326,655,652,638,36,143,352,945,17,747,364,757,962,369,203,674,562,100,627,838,864,239,359,369,973,661,714,224,987,485,813,18,926,516,103,233,180,271,852,293,743,894,790,682,214,969,353,667,588,296,167,552,264,866,818,674,484,316,596,321,27,700,503,239,150,592,832,856,216,738,498,991,600,297,951,17,193,876,270,743,907,800,942,700,96,785,664,373,4,185,582,273,8,110,142,757,27,558,179,229,59,248,42,608,373,339,437,62,423,578,847,289,682,20,564,661,587,712,203,174,709,675,459,172,945,103,735,969,958,283,526,317,952,118,846,133,75,351,67,759,9,653,750,77,181,3,906,301,498,148,194,209,297,681,997,195,822,555,931,157,781,930,976,993,807,599,563,607,890,396,433,275,485,392,487,551,247,775,796,440,433,218,131,520,544,853,279,471,86,723,681,469,259,501,928,242,824,257,439,133,142,352,86,400,772,738,322,482,518,556,583,91,975,745,157,918,857,612,690,306,88,211,304,493,713,115,291,346,398,318,325,138,536,727,932,957,937,155,569,892,115,689,857,731,424,917,0,115,873,440,331,670,309,341,927,34,190,302,710,260,466,440,864,478,829,805,202,135,998,452,233,6,901,231,97,353,964,734,362,1000,19,429,439,224,989,14,588,248,997,273,812,852,8,342,647,585,463,252,993,308,558,674,105,378,184,377,324,154,774,554,386,781,509,614,172,969,524,164,619,368,149,341,223,778,291,691,75,884,837,547,207,267,117,353,593,945,230,435,39,479,316,641,442,528,262,239,97,720,251,327,93,515,313,555,402,395,371,340,762,385,724,579,915,454,189,916,739,319,560,488,538,61,399,342,926,793,80,999,98,125,572,205", + "948,77,673,719,474,147,833,462,363,337,74,378,29,181,608,186,843,80,890,862,931,909,153,188,35,665,749,789,146,431,87,820,314,926,112,553,481,310,981,612,496,814,346,121,175,40,826,721,655,850,624,961,980,42,704,446,757,150,851,837,443,848,870,214,190,666,538,872,550,156,980,712,862,299,439,404,166,524,250,729,832,961,607,736,440,713,560,504,392,876,308,211,846,411,378,131,864,428,321,73,808,70,46,339,930,661,996,444,373,733,886,907,646,863,386,239,7,471,677,788,353,494,197,884,164,856,654,299,176,137,512,725,22,785,452,14,211,51,102,401,36,778,753,942,837,37,580,119,50,403,178,166,909,788,801,135,732,194,534,444,52,375,507,824,353,687,398,483,124,166,441,304,56,634,886,746,606,84,744,451,665,116,780,139,969,49,594,961,557,527,548,719,42,499,261,202,905,113,591,931,308,776,530,562,647,379,108,363,105,644,313,86,672,310,208,460,925,148,659,710,578,944,348,120,674,223,21,395,265,503,378,369,146,69,768,516,883,261,800,540,415,476,461,71,548,655,270,501,4,558,430,407,470,634,755,701,884,616,518,573,694,808,305,947,85,206,326,71,470,252,325,774,397,791,606,925,502,418,28,726,479,815,560,935,804,575,182,331,25,939,525,864,735,873,963,203,987,165,554,807,543,435,117,3,304,951,685,806,165,581,626,764,578,330,762,45,389,191,138,6,718,816,538,409,23,932,180,51,971,569,940,490,534,984,543,923,443,785,549,426,926,955,146,11,98,505,728,807,18,392,601,889,396,431,153,527,490,781,51,260,391,645,495,699,972,366,692,777,992,84,551,168,964,403,868,59,545,825,957,594,357,601,326,44,103,330,254,139,584,75,359,589,896,736,344,264,163,874,349,934,168,569,443,66,162,858,842,943,198,329,590,886,469,585,183,104,825,378,514,315,671,503,474,614,622,248,906,667,377,131,609,920,180,399,941,112,106,473,688,33,531,735,483,838,984,351,150,456,729,765,244,202,11,243,259,328,837,335,1000,680,784,36,567,68,906,301,678,690,518,856,833,602,70,37,117,89,127,183,442,920,317,1,285,613,323,389,181,17,88,314,327,708,633,523,234,448,925,529,622,965,447,63,133,648,138,122,108,95,116,672,828,547,459,848,6,758,899,243,592,209,774,127,69,456,254,648,354,11,871,810,724,149,690,77,845,291,461,586,926,829,694,616,619,213,825,611,151,111,23,832,354,994,478,15,65,246,873,787,676,173,145,777,146,244,289,733,322,490,274,292,816,803,949,910,423,497,364,470,299,766,603,491,997,51,393,885,688,164,386,762,727,231,168,711,554,365,589,395,590,934,715,148,884,852,45,793,124,899,349,217,277,622,412,736,724,277,49,429,927,199,645,120,843,197,499,998,344,762,494,29,678,959,753,823,93,329,194,848,873,82,78,663,984,535,881,233,188,546,457,119,290,584,901,625,26,542,464,407,696,816,995,906,920,679,687,534,634,460,982,902,858,443,96,465,418,860,642,195,700,924,616,172,949,268,194,325,776,474,822,570,875,225,434,116,135,740,282,159,669,756,882,424,376,809,918,892,217,267,753,438,509,991,640,853,528,833,880,214,571,515,682,42,727,530,74,941,31,178,456,264,755,567,409,527,723,454,350,872,253,833,823,871,666,652,251,946,81,88,901,642,108,564,91,739,380,789,340,749,616,939,232,513,939,322,549,93,754,920,902,607,743,942,51,236,376,352,500,695,650,986,858,522,61,642,437,970,252,821,932,849,122,456,328,357,210,165,713,123,27,233,744,158,30,220,954,829,494,995,251,984,956,25,573,609,679,322,914,792,749,65,365,18,643,997,717,413,227,387,328,268,735,714,126,471,164,428,531,575,209,76,129,852,191,443,98,991,26,289,45,87,711,100,610,256,824,797,633,965,738,588,79,104,890,812,115,0,598,776,977,578,357,704,890,150,738,950,607,44,412,942,775,797,484,405,83,823,449,422,857,624,180,240,264,532,530,421,590,727,943,432,38,290,713,468,185,308,640,976,123,227,837,674,428,216,547,557,77,258,915,527,667,266,925,346,417,873,228,973,922,828,944,330,552,543,165,130,752,857,139,574,430,768,464,245,846,124,184,972,610,245,426,606,104,539,262,334,411,642,929,519,858,256,550,463,425,188,453,999,98,134,969,172,119,985,924,435,144,12,592,189,701,865,218,304,921,151,854,784,814,580,386,522,642,184,138,879,382,11,852,498", + "449,781,802,128,172,221,977,625,463,711,875,531,921,589,937,946,794,186,761,405,734,170,616,482,628,734,678,969,687,249,155,594,596,370,546,777,685,461,722,307,934,521,884,947,628,402,840,630,513,905,547,48,972,94,351,665,573,112,719,974,790,11,528,303,753,523,432,591,745,814,90,917,135,633,281,4,142,524,933,378,699,874,146,473,498,695,757,237,970,271,9,175,694,824,782,197,170,90,426,877,13,102,447,130,661,145,938,955,248,45,28,900,557,527,492,837,615,838,531,155,658,739,993,37,650,95,502,641,954,908,468,639,622,476,546,140,389,793,999,863,881,842,660,851,10,638,58,443,54,215,620,626,114,899,888,164,196,856,635,233,919,808,376,837,483,50,604,505,286,523,822,482,84,42,205,764,663,406,439,658,263,366,858,887,589,152,780,25,64,852,769,224,55,993,855,972,564,927,15,190,591,737,757,768,254,150,185,108,149,366,384,583,834,131,914,795,24,312,360,716,122,569,271,113,552,525,882,445,378,672,135,985,336,17,811,887,419,18,822,257,883,256,138,112,380,465,812,980,388,84,307,836,521,810,980,605,837,791,428,959,863,527,401,541,214,344,106,153,341,933,702,844,798,175,992,290,802,363,722,601,78,607,862,160,896,325,215,618,476,331,887,800,134,176,478,397,738,170,63,937,586,772,180,317,637,554,580,151,720,926,147,616,940,697,435,654,955,259,140,458,917,837,68,618,723,852,439,720,550,353,176,383,145,753,882,633,993,874,484,534,860,72,646,268,487,869,389,372,11,110,319,65,544,49,140,137,535,182,284,658,853,952,725,641,417,611,876,973,884,801,325,924,777,185,24,841,591,745,87,302,660,298,188,211,789,634,989,226,523,301,132,625,946,240,522,37,942,610,464,168,684,655,906,51,191,811,244,349,200,151,177,758,472,205,268,943,992,798,118,633,56,963,218,308,364,133,432,162,311,213,231,324,690,696,653,234,708,353,43,199,801,442,172,244,406,213,98,384,953,786,557,635,864,117,674,806,849,444,176,851,586,385,172,12,999,487,527,749,509,422,848,684,344,189,116,598,678,901,802,218,68,201,963,805,539,443,959,869,440,937,173,520,296,371,677,555,692,3,897,419,231,235,307,840,582,968,624,312,568,844,517,611,448,93,270,618,125,441,228,82,563,350,688,228,546,184,178,931,706,419,358,200,766,245,236,406,794,101,311,777,373,729,675,432,934,826,912,964,45,916,237,127,977,738,771,126,283,829,803,574,834,770,993,866,71,490,309,621,61,367,339,289,642,463,164,432,545,715,618,521,732,4,513,161,35,811,589,67,486,389,162,902,354,860,291,614,417,211,977,599,901,892,377,889,145,363,316,132,249,584,537,261,201,602,923,157,617,16,497,4,710,832,160,411,78,375,959,542,825,710,436,928,625,642,576,863,996,302,267,504,926,179,256,891,141,557,751,180,259,234,870,668,126,444,623,426,283,990,207,178,925,276,11,806,594,365,984,714,957,466,855,726,400,169,647,884,367,434,603,423,570,676,397,594,587,877,989,991,817,51,227,450,998,81,246,38,836,609,415,346,954,705,652,226,910,440,832,46,438,537,900,185,701,398,831,529,513,898,824,502,193,929,879,10,338,175,75,549,231,125,966,788,703,828,82,632,171,266,219,927,673,728,179,782,599,278,710,670,113,985,732,50,7,173,862,55,192,134,442,629,341,515,978,858,663,774,601,258,33,850,582,375,402,168,725,365,719,507,997,750,202,843,843,901,587,583,466,48,236,142,50,370,192,341,90,55,464,955,258,529,740,827,84,258,816,948,958,556,849,20,228,747,517,316,680,489,546,510,487,113,752,231,79,988,584,600,870,9,493,109,141,622,724,959,460,245,365,214,72,910,215,995,287,90,865,926,665,515,806,153,124,97,761,477,145,25,769,152,510,156,307,361,554,790,873,598,0,873,468,434,174,682,564,311,946,374,848,350,486,558,449,669,431,952,171,121,471,256,766,719,289,508,534,196,89,333,141,910,635,731,900,684,425,36,520,387,927,540,270,973,545,379,506,627,176,27,416,294,105,471,696,736,472,41,460,845,24,594,409,806,806,778,321,926,331,344,618,535,115,104,956,540,930,470,842,199,287,358,660,839,615,841,641,761,460,37,720,580,687,568,527,360,333,840,906,274,927,430,965,258,933,997,417,579,265,954,698,941,329,140,321,366,733,814,317,445,607,783,244,675,647,76,331,241,24,992,394,592,191,773", + "540,325,137,992,634,373,39,216,671,157,788,869,30,671,121,114,940,560,747,924,609,786,132,304,76,509,195,944,2,405,710,429,936,177,495,872,293,274,357,634,979,297,361,211,772,955,815,955,659,597,966,754,824,91,753,583,266,833,124,672,623,81,710,943,103,691,21,854,632,131,434,586,822,265,14,60,730,974,58,80,688,900,609,26,342,52,883,687,769,762,567,254,459,69,919,148,722,518,850,949,277,336,40,517,485,840,147,23,581,405,328,192,293,941,914,381,456,634,594,55,493,905,203,470,201,352,832,922,728,652,588,605,360,787,594,858,962,602,206,106,982,909,388,274,867,412,95,387,675,23,463,326,694,763,919,808,857,343,126,611,417,736,259,182,242,543,474,730,66,892,438,74,213,49,772,274,993,511,83,572,742,133,242,736,860,571,402,330,849,790,542,241,224,111,802,59,67,870,535,818,875,712,110,445,407,482,986,845,298,874,565,405,367,347,943,769,370,808,22,136,481,589,963,829,345,289,174,236,703,7,562,512,586,897,8,680,761,970,307,306,653,849,786,732,826,775,45,26,249,576,25,782,720,548,141,789,624,273,765,416,466,557,867,607,512,506,942,832,142,979,794,649,709,182,903,772,127,539,307,531,744,29,998,694,809,461,664,203,798,947,484,184,914,989,41,500,684,724,930,400,44,724,809,54,112,353,597,591,126,609,105,762,298,387,62,707,193,190,185,564,532,448,774,969,681,286,658,921,574,847,45,360,661,77,285,348,624,356,159,520,55,80,984,686,894,250,324,194,718,432,582,494,371,155,907,384,935,496,256,843,164,37,240,677,434,261,724,442,503,599,488,237,778,813,120,317,160,547,717,600,767,83,330,345,499,287,324,476,442,64,510,123,388,160,6,589,133,497,874,317,356,891,406,227,390,608,556,243,237,464,607,271,61,98,827,64,323,657,242,84,174,968,371,173,171,55,348,216,863,649,180,446,857,559,222,58,665,393,574,703,127,987,263,891,295,232,75,815,794,488,798,824,626,493,874,722,562,823,468,555,877,753,442,511,618,299,342,205,981,735,121,470,752,62,213,798,727,531,435,100,422,209,865,425,468,716,998,13,900,59,368,249,376,703,225,524,925,387,907,587,263,140,885,18,400,770,328,981,470,940,839,973,874,990,631,237,950,262,291,139,490,502,59,144,972,371,631,374,340,253,983,526,734,878,120,926,216,90,818,409,518,559,515,285,691,530,988,400,129,378,482,829,945,424,394,516,307,392,796,24,162,53,779,775,109,747,852,795,943,831,652,984,353,131,493,687,799,181,226,309,899,188,140,576,37,283,140,698,875,692,770,657,659,644,481,306,789,213,290,559,115,991,535,998,125,880,947,102,586,296,289,932,58,912,574,630,739,262,637,680,970,908,780,31,794,868,207,127,791,365,539,13,534,959,32,520,579,720,309,264,547,998,953,667,304,591,985,545,548,900,296,522,842,988,622,190,895,3,188,21,333,868,384,755,742,543,699,657,821,743,556,581,611,153,508,895,480,962,515,311,910,948,693,607,92,602,177,901,101,737,282,187,769,201,143,408,268,255,888,251,478,338,427,489,410,581,656,978,987,985,613,499,790,351,256,860,462,488,820,843,637,562,503,401,562,138,593,22,982,402,352,878,978,776,743,931,230,57,201,160,618,858,569,952,99,328,268,621,55,479,5,378,456,95,240,555,115,605,768,845,885,858,239,809,234,228,753,588,60,706,212,963,898,464,760,200,479,22,531,437,637,710,149,759,838,266,465,316,899,254,651,62,886,570,498,493,655,167,357,204,590,725,513,766,758,493,64,323,447,999,223,962,627,569,710,219,359,838,479,593,578,714,68,496,543,709,250,188,177,837,33,768,521,674,474,361,142,382,964,731,76,941,58,812,521,788,236,92,576,208,375,123,25,372,539,807,594,979,861,50,301,504,881,288,440,776,873,0,170,610,60,441,301,419,340,531,9,67,924,426,429,968,524,865,693,110,728,624,900,580,711,894,807,416,895,974,440,20,531,209,841,609,642,308,93,169,927,35,633,659,888,946,902,28,840,559,44,319,6,765,190,134,971,39,12,576,83,266,245,136,59,793,663,854,546,554,970,749,211,118,167,883,288,619,185,998,831,156,232,518,281,466,798,516,715,334,913,257,244,251,814,950,735,692,658,185,861,352,357,721,155,86,989,461,251,875,768,261,111,865,784,321,929,719,138,808,272,984,387,828,368,577,975,575,297,623,805,244,439,209", + "728,321,78,591,987,886,382,200,973,976,86,884,4,295,278,382,210,123,134,29,841,995,361,244,805,499,972,847,308,888,676,678,856,339,377,850,794,36,859,859,962,169,201,28,988,619,623,935,214,779,455,120,660,596,653,391,822,901,238,351,366,676,369,445,794,486,819,501,162,268,921,780,398,778,398,245,845,556,774,166,126,251,437,808,563,28,266,903,546,758,609,169,880,120,767,577,507,603,315,53,1,515,360,84,202,592,661,820,493,556,898,180,424,9,867,173,429,23,239,332,872,967,765,885,357,506,453,733,498,699,808,465,181,698,991,845,287,794,149,648,983,642,955,108,309,247,248,641,337,102,134,344,235,518,124,562,498,503,770,593,318,615,963,928,46,216,929,803,318,793,590,540,247,622,468,966,140,307,422,856,403,605,15,145,68,499,195,261,778,297,975,868,847,35,536,450,54,794,837,617,494,706,753,304,963,119,234,643,406,473,987,329,831,841,476,538,903,965,664,426,290,85,934,622,965,502,603,364,709,901,174,186,71,118,132,211,40,252,354,435,957,740,126,332,988,270,628,299,89,338,778,639,793,153,446,89,623,728,129,386,344,572,992,974,783,105,126,586,531,660,632,172,990,430,21,94,282,274,710,713,637,383,935,368,450,166,73,208,272,148,737,650,287,974,861,6,508,560,247,957,37,237,831,564,17,497,592,705,67,250,688,842,750,182,734,593,247,464,790,574,293,870,254,525,599,232,480,35,555,779,67,944,441,726,457,45,71,316,220,189,448,861,542,243,334,770,636,747,320,170,414,659,581,57,232,231,362,870,928,333,862,35,547,873,88,934,413,391,334,976,414,123,743,468,227,29,728,683,239,679,844,503,715,368,313,803,6,199,162,140,220,304,172,70,944,289,796,227,288,132,238,423,597,277,213,5,482,740,821,197,272,704,396,655,53,956,158,539,289,427,64,724,937,251,788,485,854,323,3,58,916,933,988,887,439,609,995,811,827,406,254,662,353,205,404,586,598,638,654,121,876,487,258,219,929,713,68,665,393,796,654,660,514,230,481,177,171,984,519,439,443,859,999,990,298,509,62,218,51,395,161,899,831,352,848,283,534,359,882,37,227,118,867,143,609,148,214,189,420,265,47,463,23,492,580,663,281,585,450,203,953,718,456,182,165,184,205,686,380,392,855,558,85,159,255,557,459,179,872,649,973,621,590,940,335,822,698,307,645,109,207,589,585,459,487,461,906,897,55,423,693,53,2,592,679,81,640,700,664,55,961,480,102,440,551,734,687,95,206,465,784,114,4,559,64,738,798,601,664,116,669,189,592,408,344,575,886,683,506,90,520,375,186,986,931,645,177,906,637,230,102,217,271,468,235,66,149,95,23,987,843,72,841,310,539,445,466,80,936,72,28,980,139,168,941,641,868,354,808,876,138,985,463,127,231,291,111,686,749,786,184,104,617,713,992,504,976,331,536,760,501,699,77,979,442,275,955,912,848,303,444,601,180,792,552,936,90,106,7,838,93,217,217,679,764,15,827,469,28,329,660,733,273,721,713,591,424,826,116,167,628,327,973,922,445,779,198,457,434,849,598,167,372,575,828,925,518,859,717,992,902,218,534,653,384,334,357,360,410,857,412,864,560,932,757,843,594,716,352,84,709,143,302,299,569,775,279,64,694,654,263,394,616,382,156,69,734,758,159,49,902,882,104,189,555,580,95,678,119,509,881,273,700,687,67,444,288,793,369,957,660,436,96,281,840,144,223,825,171,969,380,144,841,887,41,292,109,203,97,88,152,600,275,254,317,853,430,622,950,979,674,949,997,720,579,820,710,70,236,39,210,139,360,178,75,157,141,623,751,391,308,704,832,934,315,926,432,474,943,889,737,68,841,298,361,719,830,470,944,73,961,796,129,793,410,768,776,468,910,466,581,102,274,7,31,25,166,462,907,959,131,694,46,662,331,977,468,170,0,832,431,219,125,268,97,129,783,741,978,386,510,804,952,59,332,537,130,762,494,927,28,311,83,563,273,177,214,857,903,170,990,340,500,898,323,123,561,164,893,768,996,816,139,965,424,72,966,584,56,341,801,172,342,395,176,239,520,686,411,480,28,670,121,659,187,207,53,44,659,460,23,532,432,771,861,709,874,628,731,84,740,189,559,516,782,682,386,419,379,479,802,597,532,616,337,236,725,118,786,506,451,268,613,282,323,155,986,36,94,847,120,784,676,970,472,428,569,804,430,195,963,586,730,594,120,463,58,343,455,168", + "801,501,680,861,30,830,466,968,836,138,753,873,724,600,785,657,952,732,810,312,927,892,421,317,797,963,201,261,209,284,644,97,427,752,661,314,253,509,668,619,880,451,476,993,790,107,183,571,721,67,604,920,920,944,966,657,490,752,787,509,120,527,856,868,11,530,713,421,587,775,187,626,770,601,846,93,931,804,390,320,845,842,393,940,603,866,724,1,339,760,901,859,275,951,990,174,754,528,413,926,314,15,185,963,741,59,382,386,115,679,701,78,752,997,671,612,725,634,818,928,822,870,793,44,378,152,158,714,338,714,835,157,380,269,880,354,298,909,560,258,83,100,498,625,35,960,529,567,371,800,364,342,125,3,159,560,823,93,991,367,124,495,972,28,704,663,288,507,253,265,251,955,724,206,204,154,213,512,234,181,96,221,119,966,29,636,573,870,644,869,938,452,731,254,820,419,323,536,255,637,335,919,682,987,504,65,317,50,918,236,547,185,812,909,627,340,845,351,541,689,719,778,227,479,859,209,198,156,443,506,412,667,261,57,551,881,841,989,743,984,599,433,98,416,563,306,559,734,720,835,865,296,6,223,667,157,682,407,814,903,766,256,213,75,245,248,309,360,717,775,159,394,455,996,738,167,946,354,269,485,613,47,259,51,845,248,995,104,891,712,915,845,10,449,979,820,777,16,465,688,880,802,762,296,599,382,988,728,763,348,618,721,245,126,658,1,360,317,855,864,795,693,13,187,671,15,622,96,784,56,729,835,815,383,536,813,258,104,372,170,636,551,182,978,58,7,961,585,25,106,484,526,507,661,394,152,480,130,132,237,811,869,479,377,584,830,147,651,62,279,679,752,258,439,651,210,873,694,225,417,301,385,172,67,967,654,333,266,491,504,269,443,565,407,310,362,872,508,586,173,271,53,116,290,183,301,496,522,765,3,696,508,597,333,14,204,931,915,956,769,860,579,781,24,736,685,878,615,735,244,974,479,590,302,458,253,778,102,969,79,434,166,762,123,270,464,248,938,516,746,562,772,670,831,892,880,285,328,607,510,856,306,454,6,239,728,850,462,90,494,587,384,401,852,109,903,556,886,695,917,11,620,478,469,158,653,963,569,417,347,504,84,260,555,357,601,166,914,578,663,419,933,308,831,96,355,92,119,943,632,526,236,833,287,917,91,783,178,705,305,524,376,139,63,829,626,233,541,993,892,933,649,268,85,21,95,19,482,407,971,497,904,346,86,147,384,52,263,50,246,766,847,48,490,462,914,364,550,391,311,194,809,321,469,221,106,168,501,534,686,621,852,267,261,17,43,199,17,308,683,357,612,811,690,55,789,608,203,171,594,912,713,785,494,514,789,22,40,925,99,138,215,881,751,165,888,92,940,951,395,198,654,504,632,435,702,453,804,255,585,618,408,484,300,63,222,638,69,561,570,358,728,792,306,732,167,641,62,99,281,57,320,261,472,538,300,10,209,844,140,169,456,224,490,863,801,346,927,269,9,575,838,197,103,895,729,564,144,869,163,805,128,475,843,758,469,575,924,615,117,733,243,711,739,928,790,282,296,472,725,246,684,366,67,986,753,198,84,810,741,495,98,627,693,59,574,16,243,932,435,935,356,456,992,110,203,289,655,504,882,896,453,932,38,900,567,756,858,986,203,24,419,264,950,394,889,745,61,605,460,142,833,155,631,679,872,551,19,958,249,652,198,128,137,16,204,155,571,361,426,229,946,598,892,825,982,885,543,160,671,188,597,355,129,622,75,200,289,771,256,970,66,274,116,308,822,746,648,86,912,735,916,934,387,670,662,596,447,125,251,496,546,556,641,677,34,517,590,683,108,97,884,76,145,154,659,879,768,185,852,137,393,717,703,277,128,636,139,890,473,261,358,101,951,370,229,144,958,448,352,779,50,468,433,191,373,209,65,462,811,960,452,378,899,917,146,660,972,835,897,441,423,936,731,670,578,434,610,832,0,197,942,742,322,437,330,906,327,774,338,890,412,258,60,570,948,203,552,261,615,378,141,84,561,850,337,158,473,129,54,534,781,391,857,299,537,362,748,780,545,239,98,398,297,189,150,717,449,746,678,779,647,784,430,643,198,170,733,756,594,590,104,287,256,506,384,130,569,795,399,137,54,967,995,957,825,100,879,446,496,337,206,837,352,171,943,702,801,707,469,993,293,255,12,943,63,402,694,391,349,153,950,998,576,795,611,51,748,371,315,607,342,680,335,432,203,183,451,343,65,212,906,972,863,817,125,530,949,677,929", + "351,876,825,91,171,290,605,875,330,658,760,211,250,152,358,442,116,948,808,78,87,437,680,438,899,373,976,358,958,490,820,272,896,286,496,264,41,701,582,37,604,892,271,366,237,643,950,884,865,657,2,443,538,512,71,343,961,111,926,248,911,634,953,261,11,251,226,242,931,504,844,204,712,469,474,918,295,30,329,106,540,141,299,625,931,383,488,559,468,486,549,352,760,870,374,971,354,186,665,160,612,938,881,703,599,710,147,83,905,231,19,559,60,273,784,918,763,362,22,250,979,874,926,587,654,44,593,175,122,393,435,934,551,69,614,694,564,623,314,462,15,134,698,792,623,320,347,251,91,953,854,68,271,826,90,28,917,787,397,926,6,998,992,14,311,70,479,189,84,711,128,654,28,934,758,853,483,396,763,717,732,770,727,746,626,671,164,222,296,625,540,140,732,661,221,309,745,314,721,709,943,786,441,728,242,736,576,718,107,990,143,694,932,316,404,407,16,685,458,513,409,176,758,627,842,388,890,536,125,338,421,428,405,726,462,469,464,338,970,721,593,190,878,97,232,614,618,340,537,9,483,806,255,16,211,971,51,268,39,265,429,566,949,225,39,889,696,60,957,215,272,391,12,451,816,266,708,969,145,124,293,757,591,984,562,197,635,643,792,730,980,894,29,973,605,654,548,456,632,436,764,918,556,801,216,351,76,414,719,941,726,76,266,677,245,950,495,778,86,11,443,472,244,978,994,759,800,881,377,823,686,964,763,661,633,855,31,613,854,132,341,802,996,776,633,110,858,150,882,188,631,532,118,936,525,405,524,80,247,213,163,66,97,807,450,180,311,983,588,420,396,584,70,711,562,113,608,473,737,366,975,191,736,21,976,94,749,490,267,476,16,714,798,15,751,130,678,272,902,337,236,531,470,353,734,260,989,994,696,372,77,106,781,75,386,623,350,985,841,450,57,756,544,251,265,745,669,630,175,707,973,28,469,918,78,769,129,808,102,255,723,547,926,888,749,33,580,609,712,385,960,80,135,979,210,288,919,383,552,576,761,826,914,385,745,198,292,408,990,420,162,974,503,398,166,478,648,517,131,878,857,419,379,597,378,117,412,207,500,249,841,425,313,48,856,692,331,471,20,55,614,549,138,29,448,437,24,764,858,201,140,352,237,422,332,871,625,252,9,997,599,310,80,822,800,597,116,529,42,244,50,494,191,904,611,889,510,375,603,443,784,753,134,437,936,420,648,183,294,317,70,617,794,267,510,924,129,625,715,104,727,891,647,610,329,702,453,456,6,922,556,679,64,61,807,10,939,31,23,153,400,434,764,414,455,120,146,483,876,596,937,379,436,554,608,810,557,234,769,294,940,210,773,45,757,329,343,744,829,858,506,62,751,827,850,554,749,797,786,234,324,671,232,928,92,630,94,475,617,844,290,493,348,253,375,571,157,116,235,236,765,781,847,343,997,853,765,727,297,267,948,336,19,454,786,291,186,720,321,878,432,338,745,203,237,429,976,404,969,627,545,563,787,990,905,868,895,945,802,116,945,715,94,280,668,281,491,166,917,482,598,705,137,970,540,768,434,42,635,639,42,995,804,896,924,70,184,771,422,942,142,897,354,443,247,918,981,810,672,917,435,105,890,814,401,848,343,82,161,322,529,271,200,539,29,678,656,675,45,394,886,114,778,178,430,420,229,118,469,721,690,686,824,343,379,734,201,715,734,635,914,462,674,696,54,93,244,165,845,698,283,682,290,749,995,48,522,332,579,384,856,64,318,767,40,189,50,238,110,512,767,481,257,258,658,129,363,822,715,294,852,789,960,661,559,55,257,295,544,583,478,190,970,226,557,856,716,43,337,280,675,652,887,56,24,978,463,699,316,48,32,456,447,743,759,708,566,520,331,726,585,503,131,668,978,909,522,967,243,539,576,89,549,883,137,937,540,46,738,54,134,457,755,939,309,357,174,60,431,197,0,483,403,662,286,263,464,722,7,140,823,58,821,738,790,305,372,949,974,691,169,269,403,860,345,84,639,342,796,925,75,749,181,419,36,658,318,682,309,848,250,554,381,636,532,393,66,468,795,381,463,626,859,921,78,697,66,391,588,836,618,980,228,350,663,429,682,383,447,534,751,634,632,425,23,364,625,38,137,508,180,430,138,352,607,618,455,518,400,911,109,892,3,49,557,11,372,97,374,923,467,191,667,221,981,56,273,396,85,602,934,792,322,26,496,778,480,996,129,52,560,570,506,702,333,234,942,253,606,899", + "2,240,283,261,900,344,22,425,595,146,749,401,425,838,170,611,453,710,998,830,804,480,131,348,104,626,794,806,440,901,535,861,627,593,173,188,163,36,608,11,78,156,37,715,131,608,109,685,827,82,157,205,52,92,687,516,63,462,135,932,598,713,999,29,993,607,975,783,137,611,295,379,406,566,468,893,955,106,97,88,649,356,398,104,597,421,141,541,241,519,136,767,853,591,712,710,107,709,356,137,178,699,437,157,586,216,582,746,893,867,247,716,822,75,356,643,786,298,855,682,152,394,159,643,472,194,726,327,475,757,233,739,55,778,82,407,493,980,556,950,815,51,318,906,666,662,701,375,923,401,280,454,257,346,27,846,826,777,543,227,78,144,324,984,840,891,16,214,120,555,984,187,695,698,263,177,849,495,338,861,77,78,666,581,886,383,661,342,317,742,549,251,461,447,627,673,310,313,565,148,488,395,671,839,146,749,698,633,961,899,872,352,293,185,212,937,47,164,964,639,790,485,269,114,777,804,352,715,491,932,599,877,470,324,29,372,314,32,145,882,671,832,729,754,710,460,820,168,156,635,980,751,583,94,898,68,271,908,202,765,333,351,827,33,857,744,37,825,154,743,395,572,871,102,801,966,4,930,889,116,541,123,465,1,503,647,669,479,524,866,808,385,382,277,908,25,46,386,697,590,669,195,584,98,540,243,780,153,45,358,548,552,954,667,478,956,191,951,775,516,175,259,903,635,153,938,525,852,360,250,406,131,622,918,73,639,920,406,297,372,616,531,271,363,41,602,859,258,325,624,32,493,223,100,52,703,385,767,488,201,49,351,126,500,284,814,644,662,263,238,517,880,938,553,829,212,377,637,25,426,204,67,792,384,487,533,660,740,863,713,322,258,824,890,344,988,462,235,184,462,712,182,615,690,429,5,569,310,951,293,473,429,308,191,557,612,504,479,802,99,361,112,959,240,321,604,834,468,64,837,415,240,836,150,631,37,244,83,184,853,209,908,132,540,174,522,164,288,646,132,629,24,993,190,535,723,653,37,214,663,782,830,136,592,290,750,326,699,634,96,541,860,598,176,502,680,341,520,377,231,229,509,18,678,858,664,268,908,923,569,128,617,72,927,46,590,997,579,482,466,947,347,687,643,745,589,858,259,704,579,958,920,702,294,981,675,329,708,280,395,941,27,455,38,126,113,1,359,150,716,364,513,201,964,863,72,707,308,139,862,437,917,674,165,604,221,950,688,495,220,650,454,279,439,470,635,835,508,347,687,691,489,929,701,716,786,439,231,965,816,702,184,397,699,567,528,381,283,661,89,682,232,279,812,204,179,815,687,243,263,645,680,23,817,403,925,251,915,164,971,388,734,183,347,731,231,62,156,49,980,65,413,317,863,663,459,755,747,35,975,898,720,50,291,520,428,222,896,807,243,741,142,799,936,535,689,792,989,630,444,95,128,227,696,583,152,73,466,752,321,777,491,930,578,792,932,425,367,70,306,536,164,499,991,675,96,397,202,29,288,421,675,302,726,948,382,993,4,480,195,698,626,94,73,237,989,270,138,657,911,466,914,778,293,575,360,122,502,390,764,486,705,617,285,484,794,84,998,227,771,993,743,659,117,86,558,243,548,630,545,335,471,744,631,574,899,338,893,44,272,157,202,652,602,33,724,129,752,39,989,196,202,758,728,947,564,219,829,134,794,706,884,41,320,342,385,55,948,701,510,871,64,263,139,951,365,827,249,242,411,572,160,228,629,59,189,133,335,548,101,826,670,78,960,258,87,901,493,755,70,334,414,57,565,653,168,40,810,809,99,234,390,64,697,159,968,567,461,783,393,442,610,240,165,307,490,792,345,314,315,539,125,240,202,338,413,846,299,907,953,390,65,729,601,238,67,22,101,450,770,514,456,340,896,791,550,188,159,230,563,486,875,198,731,505,479,134,351,103,247,449,730,730,418,341,704,682,441,219,942,483,0,870,796,66,1,503,317,914,116,227,200,386,651,758,181,962,128,613,553,85,710,280,569,525,586,375,533,906,655,793,649,129,767,812,624,648,914,378,662,284,921,688,740,166,778,548,198,702,380,430,292,572,138,232,645,990,307,721,648,358,975,914,912,926,627,616,350,713,198,688,57,498,550,92,774,864,227,603,845,174,569,228,504,538,494,930,971,454,554,618,389,867,149,511,693,789,384,531,499,187,587,399,34,84,861,518,911,903,505,491,138,134,254,987,643,109,644,175,459,342,380,743,49,499,517,714,745,974,38", + "553,152,630,411,638,379,574,519,127,177,549,280,192,929,436,45,566,589,663,91,522,516,285,41,566,801,660,629,61,388,678,648,125,61,667,214,481,381,784,955,969,581,992,513,679,126,15,136,369,107,615,873,659,86,714,829,794,319,974,497,181,538,61,265,507,142,894,32,697,838,971,577,542,961,338,453,986,445,260,233,1,12,895,935,636,162,339,748,109,730,546,299,709,834,818,474,209,897,11,138,658,944,773,180,293,19,816,473,535,152,927,127,985,780,567,71,3,592,448,9,579,960,492,783,712,131,822,806,25,701,308,599,536,362,787,642,396,426,943,445,942,741,124,227,755,752,191,753,269,570,162,652,774,59,328,666,625,221,108,27,849,484,845,35,425,370,437,175,977,788,908,911,575,918,62,595,448,924,394,828,694,292,375,661,357,839,428,290,662,815,435,607,874,200,67,685,141,676,139,640,772,747,289,305,926,734,497,179,348,626,590,366,502,993,712,266,141,428,418,220,291,779,827,32,452,103,598,846,91,395,834,268,73,231,504,444,17,274,233,250,534,721,141,761,946,337,517,838,426,182,943,230,300,413,925,60,347,108,107,715,581,599,784,503,972,263,518,974,393,987,320,371,614,734,608,186,343,785,50,861,968,368,865,282,508,872,335,179,199,559,512,219,206,982,735,54,909,720,819,768,220,958,750,201,428,461,330,691,55,647,289,432,345,686,433,623,221,558,753,935,574,367,477,309,844,611,760,154,146,385,464,236,829,601,452,552,862,387,448,370,235,34,112,954,501,890,518,464,622,155,667,484,484,587,612,96,488,456,666,864,351,988,888,430,13,942,963,492,104,630,984,873,559,461,353,881,831,7,380,47,211,952,352,114,80,128,94,37,53,159,541,860,819,302,606,175,571,533,382,310,614,259,861,236,164,384,465,351,946,809,337,843,43,915,302,928,421,800,907,356,810,33,64,746,542,565,575,530,338,574,784,771,354,239,611,967,136,515,309,212,836,554,373,841,918,96,706,45,806,162,906,875,346,723,47,445,745,662,731,701,359,363,483,980,926,924,965,463,553,932,149,465,277,20,992,7,515,1000,297,122,913,717,229,228,767,538,790,852,993,202,149,162,587,935,863,243,99,551,675,470,400,236,712,595,279,883,906,272,275,195,428,288,742,905,876,94,89,356,492,164,776,718,500,48,149,590,286,126,606,739,398,342,298,271,371,578,480,803,403,189,265,902,726,55,381,525,287,518,668,840,413,877,482,795,729,347,542,566,107,981,352,495,193,115,204,407,298,377,96,426,8,971,842,511,321,37,958,210,627,692,511,280,97,127,91,487,231,865,436,772,495,676,266,427,167,482,357,444,205,29,997,666,854,997,785,813,24,527,694,373,956,398,220,127,526,29,845,27,377,961,790,827,870,648,418,344,904,820,626,602,470,69,970,402,692,74,211,705,633,88,170,464,465,493,974,218,474,389,795,190,935,426,604,796,269,805,469,511,255,318,595,586,391,464,221,177,811,43,449,345,894,717,683,232,269,55,465,790,30,273,271,785,636,184,59,82,986,876,809,18,129,339,376,458,729,532,976,124,801,838,601,86,701,814,58,541,379,461,633,250,497,614,764,862,400,303,795,174,268,791,190,40,185,797,975,41,596,737,664,199,950,432,371,872,285,969,984,791,752,907,826,697,82,368,674,493,801,313,486,28,247,495,544,447,622,105,580,347,577,236,882,113,933,35,179,686,61,225,37,565,100,397,418,251,478,410,493,144,88,17,136,956,917,186,889,840,764,382,935,49,591,545,305,901,697,599,606,37,139,90,318,127,223,116,810,804,850,330,194,810,845,160,404,61,834,684,941,605,841,190,486,162,651,176,714,17,361,211,752,374,237,527,561,977,113,956,331,379,553,127,720,588,710,69,365,797,463,325,558,696,136,45,400,696,690,95,29,880,503,295,323,875,564,920,927,890,564,301,125,742,403,870,0,606,151,800,313,735,47,22,594,985,133,157,419,829,518,949,270,781,740,343,477,260,700,473,179,800,361,719,731,808,109,372,691,110,318,682,959,867,370,936,807,325,241,633,971,406,993,727,627,875,78,281,624,835,858,746,527,353,416,229,719,829,112,352,498,448,630,683,220,992,769,798,463,398,776,348,687,579,828,835,513,147,771,923,980,592,778,23,337,512,794,562,205,296,312,971,242,692,333,543,396,458,304,519,184,446,526,224,697,121,809,424,366,908,82,123,662,168,558,899,871,319,103,302,19,50,324,421", + "75,734,661,717,276,174,750,939,270,817,657,705,926,369,487,519,510,446,254,74,281,516,27,171,646,74,691,666,808,963,43,264,813,55,486,466,6,76,704,6,368,694,942,7,122,628,322,893,282,77,758,366,874,970,17,414,15,849,980,659,919,4,742,705,31,122,239,981,909,929,358,5,529,622,314,46,513,683,161,217,426,220,462,705,755,494,701,552,824,106,330,222,671,131,984,537,606,880,756,698,873,464,454,491,569,539,805,12,183,194,482,8,75,358,397,480,536,229,875,833,966,947,575,500,493,129,117,662,559,44,984,325,354,535,739,791,273,619,870,925,60,735,928,376,166,11,104,932,634,174,745,742,416,126,322,692,28,346,264,636,793,531,459,853,192,768,673,798,605,697,58,883,636,894,428,39,751,145,534,213,770,879,690,107,315,371,446,985,734,96,323,284,471,825,727,622,696,88,90,613,804,540,846,488,759,182,133,205,413,811,206,271,180,893,502,833,758,937,220,814,346,780,333,864,798,104,980,873,710,265,734,657,952,240,615,435,760,279,144,59,679,137,126,805,724,405,662,695,298,380,778,480,558,799,192,347,43,822,278,853,3,536,970,677,320,230,186,538,479,174,796,164,705,191,425,275,590,104,315,318,450,175,7,160,1000,207,908,313,24,807,938,591,892,939,440,694,379,55,345,877,918,572,505,826,533,796,343,448,473,820,455,989,407,258,99,611,282,732,584,568,360,459,204,54,721,318,491,719,828,271,574,337,735,672,988,222,892,436,435,489,737,728,227,899,771,897,845,263,175,575,280,457,367,982,360,981,644,412,764,321,38,523,454,667,126,483,335,343,967,809,200,82,885,41,995,675,643,602,878,84,222,511,217,994,968,156,311,456,233,671,176,849,31,290,407,931,177,483,817,933,279,172,4,371,468,784,109,490,14,602,51,264,7,103,869,282,282,202,990,44,142,755,48,908,820,544,286,574,675,194,135,610,56,266,523,480,549,629,830,466,32,310,253,965,362,568,560,308,811,993,970,834,439,900,425,670,640,948,818,656,166,108,306,608,639,603,711,568,780,520,619,581,861,157,781,775,80,98,708,952,615,462,255,678,964,765,11,370,494,204,72,81,968,190,696,239,28,863,549,573,626,161,467,613,361,532,724,414,30,800,674,515,602,193,874,337,266,5,29,269,526,766,19,253,761,535,674,268,226,16,490,117,42,992,582,93,943,306,844,143,53,61,548,522,878,708,45,289,190,160,729,302,469,579,428,708,556,238,825,702,729,524,937,379,88,675,908,319,241,351,617,341,100,643,19,601,410,208,657,96,411,337,839,307,953,191,160,222,542,902,457,370,580,92,692,444,679,217,414,864,552,604,556,748,608,489,466,671,409,752,248,717,209,69,779,13,459,632,195,89,38,809,166,809,59,642,985,111,635,380,401,34,429,834,176,579,34,567,59,745,856,930,581,876,896,590,709,1000,864,518,851,967,239,564,568,459,456,517,508,343,535,665,361,789,356,124,56,661,295,283,312,600,598,289,316,532,924,923,146,630,339,462,253,705,764,36,670,589,672,251,915,117,641,398,165,604,995,567,333,653,188,705,749,628,420,124,906,310,659,126,332,828,106,368,180,347,987,150,936,953,588,805,52,916,534,884,941,656,301,64,78,290,74,594,887,392,30,796,732,389,671,447,854,137,527,682,225,852,208,339,254,425,699,12,33,991,290,309,418,649,249,341,445,951,818,973,588,413,237,414,374,934,173,947,536,263,553,361,418,377,162,370,712,186,811,958,994,456,894,73,95,194,605,112,157,486,707,11,777,967,559,371,34,434,888,384,454,721,386,230,952,475,499,35,465,921,73,432,677,479,205,568,354,69,895,205,953,18,447,832,721,252,877,86,75,413,881,135,968,952,955,106,56,956,347,319,433,963,37,572,698,359,790,695,725,378,296,913,235,824,469,325,62,63,34,150,311,419,268,322,662,796,606,0,314,71,881,115,721,39,531,730,83,587,154,809,626,973,148,27,618,764,503,534,414,341,818,231,498,703,933,773,566,156,172,960,338,675,482,475,607,48,852,275,928,576,141,948,68,711,893,504,459,296,324,552,949,793,699,254,150,136,2,644,288,345,885,373,467,878,929,902,997,752,247,838,700,297,418,132,155,832,159,470,14,374,514,518,474,902,85,321,116,22,250,468,796,512,849,73,549,947,408,625,967,90,959,855,478,567,545,472,965,413,175,377,186,279,216,618,205,798,183,852,545,472,64,89,184,838", + "595,13,843,702,703,273,443,924,968,204,207,815,488,942,968,755,80,476,253,292,60,863,640,665,922,688,203,96,141,838,583,829,585,90,447,967,166,945,327,663,201,527,918,476,274,431,552,469,13,186,638,146,511,664,826,618,829,329,758,22,42,105,695,568,253,31,301,426,712,997,205,873,344,111,433,94,758,435,35,561,953,850,431,218,953,674,669,21,439,350,242,334,592,863,46,965,361,13,676,568,659,305,304,549,232,364,423,153,257,566,793,98,361,174,470,684,713,892,490,482,323,543,132,279,365,434,496,63,387,554,854,625,978,359,470,669,12,959,83,103,843,721,811,134,969,663,243,870,450,790,803,867,612,522,679,71,842,291,28,715,471,358,749,754,795,797,324,453,628,678,7,452,721,20,523,748,996,384,306,834,186,96,380,267,698,748,875,746,387,41,891,7,848,855,957,845,243,407,241,131,539,702,862,851,799,213,555,989,139,116,840,19,387,15,924,576,244,825,149,894,268,355,704,347,381,523,462,24,406,499,551,374,882,295,160,927,145,837,316,344,101,200,422,829,560,26,44,656,395,602,363,288,96,196,388,447,520,385,77,984,725,351,417,2,239,843,281,185,827,436,20,260,983,644,123,873,836,17,409,288,756,718,497,942,618,777,147,447,443,810,661,44,275,92,592,936,587,212,411,875,574,644,161,564,358,320,194,584,650,812,967,115,349,345,773,176,365,676,173,519,346,341,419,700,456,583,220,322,987,502,964,454,176,198,704,404,444,528,180,813,725,612,79,53,708,924,436,329,953,187,10,318,442,309,707,162,64,687,854,343,197,854,858,117,703,77,817,60,619,761,405,246,690,301,963,69,183,112,991,962,525,589,78,889,888,348,568,641,176,463,398,393,199,766,805,241,361,416,98,223,434,340,661,259,205,21,685,71,175,904,463,525,692,353,439,928,506,635,999,514,950,209,119,202,930,681,618,490,674,144,845,311,976,839,166,865,350,96,401,344,279,633,794,322,520,637,614,938,200,435,747,382,452,617,408,956,752,948,881,306,952,556,120,983,703,736,283,168,383,81,696,380,642,786,345,620,853,164,761,363,221,623,145,108,295,792,841,267,196,266,859,547,157,913,409,330,880,132,635,35,518,72,242,732,562,377,123,365,726,143,523,960,213,224,953,490,123,252,502,650,563,677,868,541,578,74,10,909,737,381,507,150,661,887,791,112,352,739,920,456,526,359,872,142,414,91,940,545,473,350,301,376,828,984,236,377,204,470,625,333,79,32,862,323,430,763,589,742,746,913,275,421,163,168,448,446,140,57,817,802,212,84,860,153,721,351,889,603,671,510,432,494,863,993,109,446,114,650,643,947,586,380,338,381,906,125,573,624,567,836,117,43,909,314,76,392,683,424,383,12,232,68,211,731,679,458,220,899,225,99,350,984,333,597,265,385,991,547,229,125,308,298,567,726,452,109,68,480,256,33,429,442,381,630,109,91,850,718,817,927,467,993,865,414,161,394,193,943,665,102,198,253,992,749,989,746,436,733,537,793,154,264,862,512,293,653,656,425,212,935,369,608,140,288,946,248,792,396,451,548,350,619,912,559,49,40,518,789,188,598,24,291,463,650,79,771,329,592,776,333,636,484,767,88,978,465,679,508,363,226,948,371,99,633,524,729,845,703,580,555,172,298,409,641,389,5,399,547,202,18,518,31,743,21,631,352,260,424,197,554,401,263,582,668,781,606,505,716,302,696,927,11,554,604,368,734,105,161,723,307,546,373,61,484,95,267,419,750,766,518,345,711,983,424,664,807,747,134,83,899,479,157,354,212,545,899,48,604,746,84,298,186,778,381,30,649,139,20,634,77,294,428,795,318,306,80,488,168,985,982,401,163,489,411,891,51,538,776,83,362,937,885,330,833,647,757,426,580,712,923,516,775,285,186,394,361,557,476,487,553,679,496,936,398,190,738,946,340,97,437,286,66,151,314,0,785,53,921,327,202,421,772,994,970,851,177,937,386,363,350,794,769,739,350,661,12,333,369,709,837,556,136,876,604,155,181,46,221,998,992,402,20,181,285,891,82,322,401,905,420,21,390,347,979,616,677,121,975,966,960,187,633,391,36,419,348,732,824,481,829,307,523,245,3,784,858,622,776,739,427,45,985,473,563,698,152,754,374,544,364,784,987,645,561,337,532,821,439,280,548,608,566,879,952,193,445,76,63,284,453,278,423,154,206,491,476,520,195,396,67,134,551,959,854,487,346,659,65,156,199", + "907,707,964,901,265,988,385,447,972,801,400,644,301,140,898,587,216,28,14,105,719,965,342,969,402,836,642,982,687,655,786,845,60,787,117,22,419,605,492,288,352,714,140,362,491,727,861,380,441,941,846,264,894,326,791,727,794,836,734,690,147,840,158,865,764,38,491,415,301,732,257,434,980,457,916,802,194,571,774,648,561,415,120,963,814,119,518,6,855,974,842,177,874,62,382,142,326,673,796,608,588,999,549,409,311,480,341,799,344,41,828,615,325,839,924,3,549,537,150,140,341,272,687,418,910,992,706,68,342,534,791,499,799,798,469,838,686,337,269,879,541,855,545,160,204,164,828,639,288,363,395,964,182,729,388,848,228,887,737,328,633,547,583,57,490,174,339,974,428,96,929,764,529,620,697,505,909,155,334,636,789,821,791,536,198,431,262,669,851,388,120,26,348,289,230,227,953,217,141,470,505,771,164,118,28,937,976,631,542,196,248,887,968,507,757,76,906,399,795,299,902,218,337,896,999,968,112,770,831,895,976,56,826,300,307,206,998,304,759,865,424,768,138,440,383,959,452,678,45,19,706,633,43,40,24,609,23,934,925,252,443,993,126,437,359,304,930,607,15,407,533,896,118,348,407,701,469,383,481,776,934,771,178,470,68,299,265,498,78,826,481,597,38,41,205,674,42,870,663,596,669,568,63,555,48,554,101,169,957,836,722,264,799,387,708,446,129,848,791,554,370,119,66,975,820,820,707,918,558,159,507,715,73,243,837,649,969,551,586,79,857,672,672,371,609,108,205,773,506,734,641,166,763,670,987,113,995,227,306,617,840,203,77,96,483,870,76,144,247,555,830,582,411,28,523,210,275,594,268,422,42,536,737,739,970,991,616,963,747,373,368,462,441,270,189,177,862,2,162,722,192,329,896,789,630,296,301,264,857,147,995,322,819,590,102,924,992,200,898,324,891,665,400,255,649,176,686,891,385,200,231,426,845,654,73,455,725,493,774,50,675,779,20,528,573,191,630,467,380,81,950,978,123,479,782,363,711,604,746,83,970,571,595,454,7,280,209,632,182,778,91,390,664,156,421,837,497,142,327,288,245,289,94,541,599,16,652,803,477,979,494,822,701,156,362,253,155,83,69,932,917,257,417,705,90,62,948,529,482,784,33,852,865,475,96,152,668,801,368,298,58,41,738,446,383,30,604,432,518,743,887,289,331,297,292,466,486,682,519,883,119,656,692,149,191,298,444,400,975,92,707,460,340,899,722,480,964,21,632,499,156,15,908,509,444,166,407,8,674,77,924,618,6,283,373,756,957,419,636,703,984,593,759,554,256,178,361,206,592,150,128,153,75,230,926,783,911,122,634,828,923,186,452,764,733,100,258,683,703,620,991,580,361,356,231,463,60,477,284,880,886,330,843,683,146,455,556,805,408,521,61,246,257,864,240,821,118,798,47,87,630,535,603,727,936,258,163,603,75,607,339,310,984,566,385,826,168,643,940,41,513,281,638,641,912,219,425,554,264,748,148,942,312,158,740,963,450,92,564,36,469,88,915,241,418,206,708,793,266,349,245,553,773,824,706,394,130,792,826,83,368,711,818,990,826,170,997,862,338,812,40,277,352,519,638,211,766,549,597,746,799,473,259,489,787,806,683,632,889,7,929,515,292,111,493,971,736,465,297,652,520,603,64,932,241,409,530,842,604,88,17,246,518,63,91,82,537,28,425,388,680,653,174,925,670,973,664,334,611,40,324,886,532,225,656,250,966,347,808,188,449,409,794,404,482,327,437,821,569,572,262,614,541,120,868,285,866,258,199,631,788,714,551,35,129,504,256,131,173,930,294,443,695,680,72,347,856,476,447,922,616,812,539,813,673,939,540,34,928,682,316,921,898,265,430,376,669,881,854,729,738,767,699,950,309,543,13,925,57,781,628,97,841,939,770,5,786,254,468,905,87,23,537,617,302,950,374,531,129,330,263,1,800,71,785,0,458,823,21,648,341,173,896,394,81,677,337,275,791,836,344,255,908,903,378,234,800,141,102,123,671,546,572,765,486,383,709,575,108,234,519,922,436,177,843,631,615,460,870,646,449,440,668,355,467,455,706,569,677,367,585,101,612,678,265,20,474,17,926,818,769,100,316,176,58,531,253,234,394,521,947,858,451,895,176,353,244,539,818,963,936,278,332,46,807,490,573,866,385,889,589,644,58,34,579,889,125,67,864,400,58,945,994,768,297,277,377,547,421,215,434,549,784,975,939,918,781,675,896,468", + "299,607,443,488,664,561,172,356,718,600,129,923,306,231,623,2,722,524,475,690,263,660,777,106,776,185,301,270,385,618,337,696,133,739,997,9,654,813,428,879,654,307,895,108,134,993,432,13,115,706,966,568,197,515,200,260,240,377,120,504,6,814,552,330,235,250,900,662,204,58,670,979,897,100,267,224,538,74,619,685,75,698,86,247,967,684,545,673,996,790,964,758,985,676,850,283,153,537,958,697,554,314,862,94,266,93,850,702,219,829,910,830,849,574,36,449,499,892,681,314,196,849,648,716,330,689,29,119,432,962,496,951,523,848,911,610,440,559,402,861,539,685,713,534,292,208,591,942,401,451,565,620,595,89,306,351,280,590,54,930,280,128,855,689,407,955,484,92,146,939,97,244,280,60,152,99,46,767,71,322,252,558,304,443,445,176,89,432,468,216,571,458,253,693,72,443,992,292,948,427,765,315,922,580,602,91,886,20,191,189,653,373,25,129,780,477,22,156,875,366,332,166,525,550,344,822,300,797,183,868,277,725,131,677,382,176,899,670,326,510,580,18,264,160,600,56,392,499,129,919,854,439,178,94,464,713,917,426,112,700,793,786,171,777,447,305,83,982,512,105,66,228,924,701,962,656,710,640,784,682,963,683,332,747,880,713,869,148,956,658,301,917,803,798,379,39,232,577,57,349,984,945,354,546,207,428,86,716,639,987,776,493,342,973,958,299,380,29,694,444,777,384,577,480,384,51,508,787,561,858,879,225,482,937,733,215,997,818,870,486,564,148,924,102,297,596,707,166,626,379,40,947,982,420,483,852,747,768,331,756,949,318,772,764,925,259,470,904,499,455,159,423,486,472,245,807,426,83,666,594,114,374,442,848,499,242,275,28,990,580,513,927,106,710,289,480,102,369,550,801,450,270,772,750,401,453,197,49,263,922,22,408,63,652,952,823,698,845,987,36,2,619,263,331,856,647,245,137,423,199,357,319,757,270,12,912,262,338,294,520,428,944,781,519,58,244,194,884,558,610,670,932,26,155,423,329,430,561,66,395,745,628,706,924,534,381,478,504,729,713,42,885,706,554,324,540,905,790,682,920,200,697,728,157,230,586,589,485,229,347,66,253,280,741,173,179,137,627,815,310,990,455,87,123,119,879,478,31,841,221,805,456,533,210,793,206,512,174,665,555,414,723,629,632,6,920,529,595,231,805,324,903,609,400,111,235,715,665,989,666,976,15,420,707,815,221,844,188,489,301,45,55,973,14,449,830,305,948,747,912,849,644,450,155,3,554,721,831,770,688,262,112,443,547,462,881,745,425,519,478,674,395,403,835,341,400,620,582,231,324,392,865,482,218,777,587,381,165,737,747,36,692,353,164,762,851,326,988,853,970,77,178,703,177,563,111,749,879,754,601,914,733,235,743,761,52,530,199,61,920,116,386,324,588,160,532,332,664,326,878,189,71,220,129,296,654,972,347,581,701,870,278,29,879,801,920,646,786,647,114,46,53,707,927,386,367,829,584,819,794,783,861,405,638,546,741,426,999,272,517,31,142,616,814,716,858,951,24,336,759,172,961,909,835,867,139,627,254,562,785,308,297,840,549,754,285,256,168,587,857,68,203,984,907,885,194,836,785,45,462,504,94,541,588,209,568,444,179,148,881,699,597,955,77,465,778,498,622,562,634,503,66,339,434,977,591,394,103,206,789,363,984,836,597,309,494,876,570,189,847,79,316,685,729,531,305,391,984,362,663,116,938,935,391,259,516,130,614,207,523,4,329,576,310,876,895,710,473,307,238,73,64,207,954,237,522,445,86,609,440,543,535,829,59,802,528,799,300,566,282,926,142,886,732,752,58,472,869,598,663,555,852,673,790,644,948,527,974,473,442,198,908,893,62,777,117,215,432,267,952,975,780,588,849,617,33,191,778,844,718,182,216,788,462,301,753,614,785,838,583,58,905,21,227,710,607,848,9,783,906,464,503,313,881,53,458,0,245,418,201,633,920,919,276,201,124,681,255,395,199,453,895,58,454,937,163,550,107,142,777,110,979,817,835,838,777,849,418,232,77,536,453,366,423,843,106,292,338,28,939,170,806,953,478,801,641,339,554,519,798,42,33,73,173,487,440,695,754,628,789,509,898,911,570,277,433,105,283,231,51,537,324,369,69,970,646,212,177,716,377,851,150,2,146,198,945,671,204,357,742,703,371,73,240,167,510,40,596,96,761,934,353,865,692,215,268,761,648,46,125,357,953,258,551,136,564,699,323,607,967", + "469,375,945,350,944,899,167,988,188,145,268,221,145,550,637,265,378,270,609,887,54,450,479,950,735,803,457,63,290,439,94,837,702,313,841,303,298,924,484,560,604,341,502,742,51,807,713,236,514,61,339,826,771,417,846,315,733,703,869,437,691,82,856,679,199,101,316,385,61,155,232,710,702,444,992,468,70,622,175,597,592,20,470,269,68,601,448,399,32,761,560,356,452,16,946,910,550,902,275,557,492,327,756,580,579,748,296,562,466,698,203,809,430,333,147,527,519,425,737,71,140,553,169,50,594,357,418,367,883,330,76,419,150,995,948,846,273,969,905,159,190,290,733,325,921,712,344,783,184,145,984,75,251,611,515,747,117,810,625,533,563,721,756,775,820,473,244,608,850,604,482,349,652,565,809,74,365,26,491,87,419,893,376,127,602,996,87,798,264,786,187,44,59,598,582,369,540,711,128,330,671,101,910,422,170,324,277,917,276,633,717,382,283,34,94,309,354,274,60,636,813,651,517,373,503,54,19,414,546,892,364,76,651,864,376,421,597,535,208,659,596,684,857,769,606,345,79,359,409,671,624,704,645,367,889,542,720,358,662,603,324,906,510,76,420,79,938,284,787,960,121,320,314,159,116,189,608,247,20,929,155,125,276,364,626,222,395,606,232,488,120,444,13,184,201,684,363,197,271,796,486,414,111,287,249,511,275,871,592,84,667,549,787,560,933,340,394,209,211,586,818,768,409,359,694,774,701,30,576,401,930,180,690,442,9,230,932,19,361,811,44,946,56,393,534,341,671,245,596,238,816,843,189,832,232,750,801,691,36,256,731,654,412,702,52,171,586,720,634,919,705,533,269,773,895,327,855,171,292,880,443,427,583,419,363,357,546,36,8,553,355,472,895,767,881,959,860,299,558,668,877,30,623,107,549,676,542,713,346,512,530,69,768,888,12,695,574,191,841,100,815,393,464,837,831,611,419,176,777,477,252,255,166,714,656,583,836,341,811,394,730,547,73,346,343,762,782,330,744,390,259,410,591,362,901,636,600,495,733,430,573,348,874,676,395,939,723,695,625,456,524,768,975,159,532,780,93,659,263,411,749,507,588,705,307,708,805,268,661,295,285,221,345,270,358,88,445,888,515,93,483,875,51,434,496,801,45,701,526,812,573,839,593,21,552,54,72,968,421,473,213,736,731,594,742,128,8,259,434,490,436,210,364,346,901,937,393,189,189,548,516,395,224,812,479,564,52,420,904,154,837,157,741,897,763,737,770,797,916,517,498,321,929,287,91,21,605,922,917,31,82,305,144,116,903,899,444,564,660,181,267,132,917,891,878,424,655,874,673,584,945,769,573,974,873,559,401,968,306,304,929,68,861,51,137,357,560,502,859,620,418,973,349,685,493,692,424,786,297,936,219,822,950,614,762,630,237,445,200,207,754,2,523,989,586,203,534,298,139,904,703,738,665,109,400,429,729,424,641,663,120,387,300,76,353,296,297,901,183,766,751,423,13,674,396,800,818,6,892,223,428,684,837,529,504,342,360,214,678,347,161,734,49,344,255,139,917,734,542,934,319,580,611,494,37,158,865,745,451,384,496,679,892,221,160,191,681,321,810,400,309,693,46,837,472,705,917,850,751,405,305,362,823,301,51,373,269,892,258,43,291,287,456,131,213,307,973,585,606,356,876,78,350,561,627,411,711,803,617,972,604,432,737,71,444,812,21,304,390,995,165,359,362,822,147,916,492,466,756,777,89,866,400,905,447,69,625,82,640,817,113,820,419,535,764,927,948,646,829,123,305,903,928,242,117,137,159,520,28,105,722,643,647,321,750,14,862,275,41,557,825,313,26,272,108,784,693,525,855,723,479,795,876,108,36,278,156,442,591,185,822,598,827,609,369,180,304,125,206,11,459,17,234,493,586,767,394,14,422,531,702,495,1,257,584,240,682,536,800,605,224,581,285,39,260,44,350,67,741,327,722,317,735,115,921,823,245,0,120,151,365,395,516,926,795,125,694,949,186,825,192,726,609,787,719,928,258,31,657,211,360,870,777,868,606,5,920,625,241,418,955,927,38,618,910,239,733,243,754,82,964,926,484,418,978,459,704,104,789,10,693,728,327,421,452,396,645,813,592,207,897,239,104,102,287,353,849,191,340,136,579,321,450,86,616,522,394,673,458,821,854,70,961,160,542,768,440,450,204,925,820,331,765,329,476,405,326,619,298,205,253,197,84,905,457,289,780,674,116,958,555,587,940,392,757,964,519,729,934,33", + "258,159,868,620,563,397,470,725,214,904,58,642,527,846,833,28,383,951,148,907,54,131,20,497,559,185,923,939,735,282,32,715,921,411,753,24,939,170,982,137,232,344,306,906,812,985,615,244,622,156,954,159,683,223,779,429,391,863,30,491,915,906,163,904,965,272,516,455,797,499,982,516,935,799,943,978,307,330,939,161,271,880,80,286,858,799,92,515,853,728,875,703,268,560,561,316,474,37,327,712,467,114,359,812,363,121,476,687,753,606,72,726,178,698,577,713,884,861,211,11,235,86,183,863,329,460,104,143,842,402,662,402,479,170,453,800,427,350,306,411,880,206,554,925,866,950,85,457,943,832,335,163,298,505,227,57,925,604,486,122,575,12,356,510,273,44,728,408,153,144,744,924,504,384,297,655,874,180,597,811,582,854,675,958,307,125,593,307,351,240,916,136,714,268,54,578,820,326,57,739,894,357,719,733,929,939,776,237,251,278,422,375,170,980,343,289,225,986,984,581,970,711,332,559,274,365,915,595,91,57,834,494,383,315,434,619,791,586,495,339,78,934,542,171,25,455,165,828,582,507,466,707,560,647,406,240,609,26,234,107,885,164,971,358,950,163,63,571,678,883,116,154,173,724,268,571,297,121,504,659,371,686,703,283,192,988,388,139,678,471,605,547,854,587,924,867,816,127,60,873,844,579,57,383,161,789,942,501,391,425,387,894,259,740,458,34,895,436,420,454,693,991,733,26,704,91,150,204,985,718,201,262,687,115,314,905,260,318,457,902,820,810,533,562,869,896,630,833,212,969,192,542,856,343,491,360,757,96,411,204,59,597,153,628,983,232,304,817,811,981,621,60,630,346,347,15,494,823,886,817,2,278,345,460,27,521,18,121,412,489,101,272,970,4,398,785,217,152,23,412,587,969,934,283,332,323,706,917,981,870,698,190,462,657,241,113,683,174,891,817,528,657,724,887,733,285,110,814,989,866,68,834,38,146,378,213,350,185,213,521,165,509,396,338,466,419,449,364,170,841,666,956,979,463,842,192,922,12,190,523,266,846,887,859,947,63,561,372,148,382,881,772,98,652,364,41,793,20,566,953,918,558,815,217,874,339,677,23,24,887,237,907,75,332,558,401,750,559,149,930,808,7,714,909,81,547,373,789,367,976,612,663,913,259,599,897,349,459,738,832,882,890,981,152,960,902,931,312,410,110,868,309,249,351,908,428,660,638,126,805,517,531,111,886,79,514,959,390,171,786,300,940,240,414,968,423,40,42,619,495,327,888,973,934,510,14,34,544,688,974,659,630,660,972,494,186,393,890,57,17,161,782,178,823,624,250,193,57,577,509,824,586,769,407,853,497,402,281,331,177,491,789,214,641,948,919,796,301,830,27,975,53,193,360,90,341,324,216,779,244,313,919,883,306,918,850,348,359,787,401,510,985,235,502,500,179,740,310,317,110,263,497,834,874,860,451,486,386,766,487,870,431,505,10,621,263,282,700,454,629,316,784,782,123,484,737,383,903,369,921,833,298,580,854,184,686,420,304,111,798,154,653,981,578,208,87,664,483,882,889,431,12,915,155,936,68,241,60,731,691,514,516,987,755,229,61,264,291,626,978,813,769,337,934,845,656,184,811,845,320,140,535,11,247,804,574,404,378,502,215,389,958,774,98,619,235,659,932,318,397,517,151,265,447,955,947,742,613,663,279,363,948,124,257,421,100,826,525,985,167,671,196,611,104,975,668,415,941,38,344,693,53,398,92,203,546,125,468,769,678,929,210,713,506,893,357,261,98,509,770,867,448,199,163,488,308,384,900,838,528,453,445,183,675,177,362,699,410,574,371,238,986,531,361,116,738,203,179,344,956,102,352,73,123,958,725,693,378,712,787,451,265,363,191,156,550,203,175,871,750,796,564,237,919,146,778,362,24,910,670,212,188,656,514,300,629,330,562,872,740,532,266,885,671,466,412,486,924,978,774,7,914,47,721,327,21,418,120,0,734,899,430,71,59,948,382,72,644,12,521,508,759,576,850,790,288,116,163,73,792,858,8,753,729,310,164,770,200,346,70,797,937,611,929,95,294,94,704,246,710,841,396,110,563,405,235,502,781,502,952,951,794,849,472,711,105,694,399,970,168,456,962,840,908,307,558,998,62,256,953,238,834,59,430,237,371,478,433,878,331,525,285,310,670,509,506,373,750,296,346,402,379,584,275,711,899,859,937,560,45,283,826,999,691,154,709,615,690,640,294,779,318,860,78,83,868,214,430,740,751", + "40,446,455,526,128,739,539,461,425,365,512,128,132,582,726,969,567,462,709,212,789,771,506,837,724,884,453,758,564,95,148,58,621,502,276,369,808,923,646,570,719,120,137,595,213,651,319,337,204,241,187,945,813,316,263,814,86,919,551,956,874,499,936,686,638,449,793,499,520,13,940,446,80,355,868,734,230,951,267,506,444,293,835,703,49,637,908,610,33,864,397,656,187,474,427,797,243,761,207,44,292,676,242,132,885,471,841,794,275,287,512,583,874,662,412,409,793,698,425,146,718,333,100,239,194,171,882,861,74,598,137,402,376,157,98,27,911,564,981,304,883,463,460,977,215,399,221,771,420,779,523,366,689,16,207,580,202,689,750,837,905,140,43,170,54,808,691,733,476,892,352,874,181,624,557,322,90,921,752,533,422,804,217,245,414,271,750,82,936,444,938,420,513,902,121,956,143,814,245,143,372,512,587,59,364,966,974,812,899,761,161,783,861,810,284,274,67,395,914,495,819,14,907,301,278,319,782,985,52,214,886,470,662,34,198,666,719,836,196,863,482,923,19,930,880,255,673,601,297,89,306,645,545,996,312,342,880,472,283,940,121,665,91,397,317,122,264,628,312,968,850,777,38,546,36,450,640,729,940,977,320,183,963,156,195,276,260,743,946,706,201,338,612,232,470,583,684,61,546,856,901,170,767,844,396,267,217,70,961,768,449,457,89,347,372,351,632,695,881,25,195,117,417,676,195,928,215,186,523,492,877,956,847,753,469,605,816,614,529,226,100,818,851,282,18,251,50,371,119,465,941,627,560,64,652,816,558,990,527,174,823,79,691,497,945,303,26,33,317,655,406,158,500,181,175,723,520,430,271,691,117,322,724,571,605,732,700,904,388,311,647,463,136,620,224,284,725,409,458,977,793,449,634,467,632,149,506,673,678,209,70,287,194,43,990,123,542,10,893,56,893,313,226,110,758,383,762,122,349,431,422,152,672,342,112,249,482,287,610,367,638,124,632,761,805,246,353,884,814,4,181,526,302,638,746,235,929,701,120,875,325,690,96,308,700,491,949,982,279,412,447,934,968,893,794,617,885,805,908,55,283,189,303,470,361,888,323,134,33,124,924,176,808,563,895,311,724,616,710,34,371,570,726,41,975,230,453,981,675,817,904,985,404,276,31,449,613,85,105,674,424,681,682,462,694,67,299,398,525,213,777,241,476,472,759,680,136,855,390,675,374,90,585,980,188,480,727,796,908,355,202,371,488,744,675,570,115,85,898,475,671,990,452,490,321,713,356,976,449,923,674,927,826,753,43,451,871,206,14,71,994,786,467,499,772,245,264,790,948,8,598,568,675,568,2,491,205,244,558,95,785,569,483,601,768,743,906,540,943,112,898,523,87,369,85,941,242,465,77,475,265,795,840,289,994,323,685,31,941,404,289,676,735,219,656,847,514,745,250,654,826,448,179,259,369,6,48,839,626,17,182,32,772,485,613,391,184,773,920,89,806,235,94,490,655,301,801,862,854,93,495,241,813,116,68,822,795,312,641,826,690,401,931,107,721,440,611,940,616,645,807,838,420,899,227,812,92,412,696,88,271,82,963,98,768,283,637,819,469,12,424,545,525,304,786,908,610,135,836,361,322,590,265,960,150,438,742,946,762,581,988,621,805,736,244,514,236,738,362,494,97,129,283,128,994,881,100,61,512,704,862,959,603,298,400,870,566,182,547,100,199,563,575,831,677,912,346,622,553,541,399,27,316,393,948,446,751,553,83,175,710,163,170,119,491,250,652,154,821,567,847,557,487,440,6,330,221,188,106,382,582,111,51,41,74,244,774,383,243,13,655,575,262,702,643,121,365,86,769,638,524,834,439,865,823,830,999,441,10,722,552,989,966,108,723,856,648,37,104,673,922,201,349,347,211,410,196,449,339,969,120,449,902,90,61,351,705,348,330,203,819,934,531,142,440,942,558,426,386,338,140,116,22,39,202,648,201,151,734,0,174,613,92,954,152,965,834,54,912,925,453,357,227,72,865,421,917,251,184,265,128,337,194,767,541,621,711,522,769,67,415,518,417,732,292,793,812,726,379,447,835,348,379,254,656,144,483,342,734,519,45,828,521,50,259,36,719,87,922,572,676,663,178,524,244,567,673,731,252,275,141,325,892,899,413,131,727,214,4,44,830,507,325,774,20,868,500,136,306,297,469,319,160,49,615,237,202,790,200,711,589,387,751,351,904,308,470,925,458,648,512,509,709,484,997,726,187,90,648,760", + "524,415,470,733,263,169,881,17,585,76,281,162,952,279,423,453,642,331,566,802,667,281,491,548,92,788,826,515,629,206,777,981,532,434,943,671,637,52,356,82,151,486,983,810,887,724,281,798,746,674,605,736,184,799,52,727,980,282,974,145,669,165,382,575,483,929,387,291,386,129,407,396,196,584,449,783,742,178,568,653,326,498,627,75,578,382,194,43,164,659,367,450,944,957,946,96,116,109,614,933,763,373,359,671,628,844,985,856,775,715,952,164,714,400,839,719,719,244,439,480,210,674,165,792,675,8,82,915,450,115,637,857,650,959,11,879,724,104,118,419,562,961,980,677,749,700,537,507,897,89,68,720,868,994,940,837,371,769,660,98,442,284,512,346,135,78,883,389,740,643,632,612,763,746,872,906,942,413,906,116,783,285,835,856,322,657,906,234,922,912,285,827,635,334,696,760,148,915,774,77,211,420,965,35,867,893,966,133,168,866,890,659,307,527,350,387,153,986,513,145,553,502,785,61,130,156,809,786,211,824,429,586,569,102,15,415,119,279,413,110,363,258,205,15,660,349,738,343,603,591,367,309,825,416,700,642,383,934,388,454,174,224,672,250,388,639,521,619,356,285,473,241,939,860,317,120,581,439,164,342,480,912,404,562,598,838,23,534,652,692,532,609,451,288,55,876,31,481,760,824,959,451,725,650,289,573,638,870,266,617,678,39,703,984,179,633,792,753,650,314,972,817,741,18,210,426,315,879,516,648,221,376,199,848,14,461,41,449,956,492,63,485,349,559,716,361,813,228,952,299,351,694,548,449,934,243,864,976,397,116,116,527,259,46,848,73,590,199,985,977,183,655,945,150,731,893,487,458,833,989,6,994,898,148,238,608,672,731,80,726,894,124,70,314,585,117,226,209,397,898,863,280,678,237,922,770,402,770,286,708,18,852,3,99,725,748,241,16,704,920,339,649,440,712,628,477,670,721,762,344,766,815,675,65,100,467,112,208,60,709,41,499,450,855,587,474,596,89,386,86,237,416,790,151,120,571,683,367,218,516,29,121,694,715,226,33,436,770,656,630,878,674,376,141,968,376,887,890,593,440,480,435,311,162,645,383,441,877,646,307,263,657,294,5,970,656,230,207,402,826,781,787,499,242,75,893,569,243,194,912,351,59,214,274,340,580,910,716,915,634,896,160,369,41,123,488,442,939,241,696,882,139,501,304,260,926,842,772,300,809,114,629,275,201,149,586,402,946,349,834,350,330,523,781,977,832,546,490,612,650,834,462,436,7,518,218,983,934,390,432,998,877,358,715,354,331,791,92,711,60,650,452,102,241,781,794,650,245,612,780,352,665,934,800,22,639,407,979,786,63,974,991,841,610,670,441,446,665,147,758,91,168,935,19,266,922,33,721,783,297,918,897,194,176,519,545,561,662,610,468,772,792,192,450,720,264,589,460,441,126,513,874,155,12,617,5,473,209,252,714,736,539,511,495,692,648,27,63,21,790,723,670,182,476,718,530,556,564,982,944,124,795,778,889,264,165,420,637,984,900,687,558,341,28,285,784,983,516,92,188,894,513,197,781,29,681,312,145,594,196,935,551,583,979,588,980,33,434,147,345,757,287,893,111,679,419,90,900,486,972,194,623,303,367,67,79,986,996,139,361,971,433,284,379,257,413,400,395,489,846,654,430,722,977,572,793,448,723,252,557,476,566,168,488,494,324,429,38,850,895,680,853,56,965,354,910,389,478,302,545,478,612,14,178,726,186,304,869,227,818,822,23,509,991,276,546,174,200,300,361,40,305,940,605,46,363,253,342,79,437,488,172,151,274,966,805,611,954,230,66,866,614,487,68,501,79,195,220,502,947,717,401,505,312,776,275,484,112,124,912,41,783,319,334,46,883,908,263,750,306,137,639,935,311,166,400,768,816,50,570,414,268,25,498,146,718,249,860,738,226,472,360,655,716,864,775,449,429,510,890,823,227,594,531,421,341,633,365,899,174,0,944,735,309,62,325,963,79,538,939,51,300,619,193,719,16,408,233,411,76,121,407,853,995,24,122,49,481,960,549,797,744,423,603,518,672,715,590,853,520,276,964,303,988,662,717,314,557,913,742,21,725,449,270,227,957,707,908,690,21,917,431,5,875,47,109,399,350,245,202,195,106,7,703,81,595,786,986,899,926,749,658,816,717,407,875,209,856,541,510,303,386,620,582,905,571,415,977,382,812,852,226,810,966,324,250,785,615,138,941,448,504,638,273,52,95,149,648,231,480", + "845,422,458,350,453,137,2,361,437,895,953,500,584,830,743,430,41,872,364,519,869,339,47,776,558,88,233,653,840,749,958,607,212,129,82,229,12,767,367,605,352,623,527,154,894,361,543,67,867,195,530,132,36,421,543,421,469,274,484,110,110,372,505,618,96,871,642,104,470,541,209,849,978,415,860,579,227,842,594,847,811,705,753,825,101,440,580,207,191,846,289,194,520,106,364,526,367,757,541,303,719,429,112,395,118,404,437,96,856,988,833,682,395,695,167,48,659,161,823,682,135,324,950,989,336,214,550,367,79,208,882,787,816,146,14,79,733,742,639,811,709,784,683,564,579,893,496,721,839,455,460,876,529,918,623,414,829,517,656,806,66,269,850,700,505,410,479,808,320,152,981,910,234,225,931,445,394,327,932,752,154,41,188,689,67,66,905,361,623,681,220,498,230,640,779,472,942,815,18,209,19,52,990,627,12,83,635,294,538,706,681,566,463,977,813,387,399,206,972,156,323,72,653,665,448,302,435,809,377,623,4,968,995,426,875,128,463,85,589,41,321,884,545,746,669,221,621,575,922,511,740,766,468,77,381,874,547,26,246,220,840,783,784,580,586,493,705,618,623,715,324,142,461,154,514,919,419,898,155,566,951,821,608,222,829,719,923,67,568,371,105,515,802,14,635,474,86,362,982,996,369,181,499,939,433,921,255,351,333,423,538,584,218,872,786,322,186,228,362,447,609,652,805,93,642,3,678,841,981,957,364,666,358,500,298,166,367,809,465,985,692,194,520,173,527,73,58,113,89,632,579,91,358,538,94,166,357,598,730,266,292,578,85,104,842,91,581,887,346,894,748,945,906,472,520,608,532,932,490,418,159,666,797,743,648,481,938,344,984,4,339,46,472,172,653,429,528,127,604,972,963,912,955,62,75,871,66,381,532,14,462,879,457,198,622,968,458,564,688,990,717,166,232,899,387,505,378,809,462,624,759,708,819,322,177,786,456,88,502,899,773,751,729,433,996,768,226,490,104,380,47,148,699,973,400,505,921,610,657,527,249,854,967,262,309,485,690,927,703,26,933,950,433,355,272,757,241,280,831,878,416,195,818,984,440,217,29,35,981,776,544,103,956,786,302,159,872,178,63,467,560,851,613,76,239,146,637,569,57,747,865,601,343,734,74,673,507,733,734,231,199,810,191,896,663,855,983,6,620,842,894,847,406,168,495,685,116,719,619,985,758,571,770,206,504,5,89,776,717,181,441,441,721,303,315,631,907,552,101,802,816,947,191,355,910,392,772,157,35,802,710,428,996,852,316,981,315,297,848,10,242,944,614,671,391,96,785,356,28,272,47,995,113,359,855,482,961,967,64,693,607,725,745,511,153,809,254,15,683,370,22,32,643,37,209,380,200,888,865,672,107,510,420,382,772,34,977,353,931,920,574,543,401,99,611,96,73,883,762,567,345,744,200,16,132,290,4,451,730,203,249,535,638,327,881,122,981,787,470,91,57,898,209,436,377,614,662,828,25,280,881,290,566,166,718,82,529,202,335,347,103,365,625,756,5,240,467,701,443,451,983,225,953,218,789,546,150,540,114,489,855,65,476,821,829,532,978,33,825,330,713,154,503,643,769,434,608,282,885,735,812,38,349,679,721,927,901,54,864,671,231,663,278,730,813,524,119,514,345,860,37,702,995,657,798,990,510,523,977,940,137,722,458,791,273,918,563,644,738,488,812,932,348,265,691,710,735,978,636,722,119,213,996,623,690,187,754,372,704,671,358,976,556,576,570,169,270,357,182,122,938,228,580,222,773,102,550,117,755,322,541,125,56,868,801,984,708,127,622,681,237,571,971,111,265,731,148,508,221,49,922,955,961,492,742,522,525,254,86,959,421,838,711,505,973,58,776,922,693,178,7,931,710,224,30,328,690,55,985,225,80,745,823,833,530,900,36,194,468,46,781,773,317,751,478,797,669,968,804,412,58,200,985,730,772,173,920,395,430,613,944,0,717,375,70,914,995,949,268,429,168,506,490,74,795,143,550,796,323,704,191,321,393,358,753,513,538,788,536,721,33,710,46,710,221,204,841,344,122,602,166,901,41,186,210,920,804,969,719,877,74,612,829,410,590,324,439,227,285,300,597,25,602,471,590,451,760,435,716,25,43,171,691,677,269,170,797,486,596,648,462,937,832,79,769,201,286,610,899,546,57,517,97,456,470,136,654,90,901,225,73,501,650,43,495,279,819,615,808,387,659,744,489,286,974,535,423,396,846,757", + "281,808,710,364,400,866,760,52,249,886,539,830,433,942,995,379,464,22,932,99,986,360,180,322,162,17,701,840,852,276,409,807,849,499,714,255,403,773,117,103,62,298,553,512,841,772,175,73,896,493,102,373,140,408,941,86,711,852,827,995,499,858,955,868,637,993,942,168,395,834,452,562,386,488,660,735,349,952,120,739,852,197,777,259,288,106,411,726,904,983,459,882,419,727,856,224,658,669,746,618,567,158,615,988,858,975,479,505,355,333,133,854,209,878,511,814,415,607,856,376,384,43,352,158,537,229,90,73,312,561,520,479,140,411,109,178,949,823,665,505,634,37,411,153,971,672,818,261,335,822,722,840,382,23,474,718,45,344,436,238,878,656,736,825,259,163,14,932,230,713,572,423,621,601,337,178,900,907,455,851,283,540,370,778,455,552,469,407,83,493,386,619,872,487,727,125,198,244,352,994,980,190,714,695,371,346,422,220,78,829,453,924,912,140,360,569,508,497,692,245,733,865,643,382,109,203,260,262,362,740,955,151,985,168,165,723,863,925,529,42,156,817,15,799,82,990,193,140,102,406,936,540,301,177,251,676,141,846,400,502,581,697,439,33,165,966,344,532,734,583,8,471,849,829,217,333,400,439,281,579,530,817,818,777,126,883,97,669,219,225,920,175,279,494,554,871,872,515,244,752,892,61,786,27,345,415,286,295,937,220,771,89,169,174,856,423,77,307,740,241,867,169,940,319,544,308,912,755,642,842,250,779,25,901,59,761,966,398,236,213,537,441,633,722,594,125,863,143,244,794,439,398,842,423,174,957,534,535,520,451,634,582,923,122,331,648,512,854,460,912,892,393,124,526,958,749,541,601,522,185,134,890,949,284,735,642,28,931,41,496,680,735,153,824,874,91,907,268,216,979,986,626,919,66,99,353,476,708,982,189,590,81,376,106,461,232,651,949,857,207,866,871,103,173,994,762,782,327,821,422,498,383,759,989,240,810,603,291,737,708,920,771,784,143,896,165,900,917,96,973,753,406,291,28,434,160,39,753,103,396,761,976,508,704,142,290,967,240,396,75,560,284,676,547,686,306,710,209,760,768,937,733,470,282,469,974,142,986,478,539,659,326,220,537,359,183,685,545,632,557,822,233,586,62,429,984,68,338,345,77,507,194,642,762,199,647,970,630,240,881,584,672,237,781,421,350,46,97,335,210,805,453,897,91,371,106,986,305,983,920,60,523,841,188,616,252,825,123,837,985,637,870,24,62,501,926,702,164,313,321,417,431,610,668,268,590,342,187,102,601,47,740,455,624,777,523,735,106,498,863,571,163,991,209,366,830,736,704,97,923,91,804,371,315,479,445,487,569,444,508,131,253,572,436,488,568,578,529,269,455,16,495,831,224,691,433,349,239,337,475,577,116,330,149,311,781,423,253,552,26,341,540,426,310,805,880,100,10,973,740,712,923,886,915,140,28,930,910,825,155,273,834,565,628,516,584,99,676,17,439,824,769,209,521,870,530,432,236,248,94,366,806,937,181,867,860,696,556,67,937,904,484,49,490,64,373,250,386,606,123,792,461,992,239,940,941,224,644,544,615,273,273,493,306,871,812,625,729,579,183,817,519,346,332,800,699,544,280,486,819,642,886,967,227,520,805,759,79,817,370,888,700,699,915,716,219,110,695,954,295,426,157,640,959,268,760,346,134,297,446,519,40,898,238,208,100,571,719,554,462,202,242,101,297,726,417,400,828,867,721,860,259,289,768,45,466,193,315,511,632,776,894,614,145,19,703,275,619,643,227,183,101,625,572,645,290,692,545,801,319,180,515,271,69,26,284,210,46,314,981,4,707,240,881,295,571,788,680,888,609,423,346,856,332,452,211,869,453,367,23,86,492,964,258,184,491,286,773,896,51,905,224,29,694,642,959,194,862,109,595,294,260,935,402,96,894,371,603,179,831,414,611,476,733,829,484,431,524,952,258,821,386,133,83,994,896,919,516,71,92,735,717,0,845,667,15,986,266,549,637,886,243,937,16,305,877,396,827,5,349,535,239,728,696,959,910,388,187,208,636,400,26,689,584,356,733,450,886,935,814,963,991,548,373,461,674,20,71,739,864,60,556,627,736,335,888,283,797,127,182,697,436,828,531,105,583,489,557,583,976,945,655,421,58,557,500,415,944,982,773,554,673,982,419,775,270,553,269,655,982,665,867,310,5,635,928,50,948,935,167,201,491,249,286,991,986,279,724,574,637,363,155,54,670,86,200,198,835,772,242", + "892,798,493,31,748,383,855,857,164,907,603,294,735,927,283,442,252,503,209,392,572,381,197,61,312,710,734,520,698,761,157,4,945,719,596,250,853,893,922,781,508,687,639,889,231,444,606,231,416,115,802,444,231,728,315,791,169,131,482,50,632,816,974,473,933,786,193,128,845,518,475,242,579,717,679,706,756,820,810,432,400,903,307,709,326,46,617,934,881,434,91,935,578,200,757,370,287,859,66,366,115,159,495,871,245,656,30,216,988,273,302,369,789,804,228,164,871,220,919,317,8,269,55,983,214,231,436,162,629,16,968,926,43,119,634,855,561,506,868,356,861,607,808,789,960,564,453,522,613,809,347,885,774,317,171,963,145,290,746,811,279,491,707,681,881,685,770,99,236,989,494,929,52,524,583,135,43,650,639,307,564,450,889,549,860,250,198,191,199,262,841,998,94,438,535,381,482,518,569,20,273,341,500,946,580,732,33,527,767,525,612,178,701,148,275,82,699,682,380,811,260,835,500,973,514,72,738,426,727,479,797,819,763,726,353,939,480,25,496,49,812,192,835,286,853,764,932,868,540,649,866,965,400,47,50,34,811,953,117,125,436,366,223,945,685,32,422,459,671,316,159,370,404,545,941,73,962,421,438,820,18,565,828,99,30,731,298,41,215,747,193,541,82,726,358,996,212,90,918,525,844,100,556,756,892,954,484,718,808,923,988,778,654,930,236,298,806,906,641,482,9,513,696,673,963,63,5,235,705,961,830,920,675,766,883,674,35,622,306,556,84,243,576,315,768,376,837,552,506,438,198,188,346,278,42,584,688,530,208,162,692,748,965,824,974,911,844,12,105,852,594,692,398,519,8,447,85,129,790,62,636,751,129,55,748,670,739,636,699,341,692,207,517,633,348,752,693,463,811,905,358,776,80,246,755,164,488,440,600,227,757,250,198,968,483,442,497,784,233,72,510,857,181,387,221,469,103,946,218,660,736,11,907,30,462,40,649,675,796,235,950,861,192,238,146,721,34,429,972,500,953,713,34,707,196,959,619,376,897,559,321,274,882,560,92,353,645,97,640,923,295,709,806,994,380,720,178,754,877,128,413,353,964,295,13,209,683,568,987,880,876,493,110,491,996,707,400,359,872,894,333,517,794,201,213,676,65,587,183,457,178,604,936,465,674,3,29,414,877,724,565,920,769,318,59,813,744,847,314,765,484,20,643,426,490,797,995,183,962,332,418,493,540,936,230,988,426,181,424,614,981,238,934,697,387,383,387,285,717,304,131,177,280,909,804,858,211,247,260,818,44,599,981,318,937,205,512,871,37,716,605,601,649,273,751,785,811,127,209,599,397,544,376,658,775,124,625,768,325,539,92,829,770,223,586,833,374,834,251,179,861,849,926,740,304,634,750,435,593,918,85,471,353,72,286,562,943,789,565,444,859,303,689,166,989,468,107,861,418,947,274,162,152,130,595,637,538,732,976,200,681,463,628,288,883,592,774,28,269,644,359,394,869,926,447,279,924,332,274,388,978,587,247,584,24,279,820,57,234,246,797,81,212,247,43,359,582,286,531,412,490,813,126,745,300,611,15,150,860,324,457,670,970,528,311,155,875,906,122,500,124,777,528,789,731,691,513,369,363,422,374,367,254,162,240,666,884,262,399,401,186,647,919,292,742,742,986,866,277,11,517,133,540,454,920,91,71,429,149,123,318,878,848,858,854,668,399,587,210,251,521,546,899,211,641,685,126,309,36,772,747,982,656,385,251,598,826,927,839,309,488,585,339,373,796,236,145,779,85,699,443,324,111,811,315,640,830,796,77,995,752,3,929,798,45,413,564,799,146,659,630,910,971,450,74,429,215,318,783,908,831,206,386,522,518,473,673,600,688,153,707,820,834,301,537,94,758,81,532,169,11,616,272,587,113,451,550,632,265,48,901,940,914,807,347,538,492,151,317,605,103,388,600,399,805,405,952,865,59,60,738,651,157,587,970,394,276,926,59,954,309,375,845,0,413,391,34,162,935,136,673,532,819,191,666,319,477,489,692,552,405,377,61,618,198,996,548,778,368,588,302,111,515,262,480,81,35,724,92,584,830,573,618,489,83,871,187,895,949,893,139,86,811,682,285,340,283,314,710,393,209,522,342,138,913,871,130,908,391,728,99,343,953,453,875,395,529,47,949,184,623,655,317,584,487,152,942,231,584,144,179,47,375,631,582,824,342,562,152,787,64,988,115,756,467,653,505,795,606,875,784,329,641,83,852,235,858,389,255,921", + "64,299,378,590,515,219,126,637,304,254,697,348,348,767,517,516,154,668,768,633,347,327,690,746,82,111,331,440,981,876,412,812,631,655,436,558,405,700,985,648,795,809,672,683,384,159,388,534,799,41,91,302,663,345,662,71,388,916,111,265,271,695,99,643,382,646,59,165,388,404,253,816,156,537,261,748,356,796,831,442,675,246,595,459,959,169,454,502,157,732,826,410,123,462,560,83,307,791,663,765,955,554,361,626,512,434,157,935,362,701,263,212,699,580,849,949,513,660,326,37,846,846,900,26,748,510,94,316,306,870,425,474,558,519,282,136,772,731,397,287,104,696,697,434,225,175,850,356,655,779,898,103,183,720,380,866,130,852,648,595,742,425,361,733,197,525,12,485,146,572,117,740,895,616,861,800,993,785,34,353,503,226,683,616,317,506,395,551,621,344,34,975,840,649,992,698,5,815,27,132,798,445,758,500,220,513,810,84,444,249,326,268,951,886,535,551,561,898,52,391,284,266,705,405,589,215,653,861,685,706,111,588,668,242,374,104,62,521,471,485,228,64,514,248,848,255,236,899,296,672,833,136,887,241,689,535,709,681,89,859,768,449,547,856,260,148,35,697,767,49,943,529,701,570,22,107,278,852,562,507,390,235,710,763,375,541,809,165,522,382,755,378,537,945,992,297,629,953,802,734,430,299,234,636,644,733,482,804,887,808,459,859,555,510,166,72,258,831,617,699,497,393,675,561,245,978,992,415,835,10,734,687,324,479,328,573,82,491,852,645,57,925,456,965,588,976,303,934,486,108,6,295,629,398,419,667,650,235,658,429,319,793,417,528,529,135,633,677,932,694,144,909,644,679,53,555,99,81,570,778,365,303,765,692,435,648,60,475,685,986,307,789,936,462,761,40,847,958,804,185,39,546,209,650,175,600,973,492,571,369,791,988,49,101,726,829,223,922,980,781,770,340,6,68,676,737,10,291,203,647,2,434,673,613,601,977,695,621,16,551,288,594,363,662,477,439,224,504,718,822,121,761,172,925,862,908,214,226,88,579,436,980,876,118,206,647,726,970,424,296,953,26,450,181,343,62,463,791,905,969,563,379,414,41,123,275,138,400,365,61,783,431,45,397,404,430,742,487,903,955,608,105,466,116,882,411,256,620,444,811,1,985,130,491,603,835,819,452,109,18,402,283,26,369,216,892,589,757,304,905,755,866,492,383,483,359,282,988,849,155,602,267,186,361,907,147,447,887,208,915,516,133,7,352,302,662,545,234,237,652,37,15,462,187,432,440,206,272,423,726,916,412,504,804,807,408,892,967,385,519,904,90,273,863,99,995,859,3,148,670,490,305,356,384,547,561,55,224,63,940,990,882,166,922,148,886,679,143,367,656,817,450,625,275,167,849,322,273,271,230,835,43,728,991,709,248,411,393,972,917,241,108,616,506,726,45,157,529,818,839,129,696,336,536,681,363,381,366,377,926,369,169,846,64,940,67,501,111,596,324,399,679,303,765,42,873,932,899,18,974,803,290,127,558,694,33,278,742,286,630,947,537,925,320,824,885,403,379,985,256,803,742,146,6,363,604,496,956,647,189,860,64,584,428,742,900,748,259,584,589,240,506,392,237,454,459,261,646,604,859,303,832,282,149,398,716,715,633,697,845,431,825,772,186,764,355,630,198,24,194,921,311,520,29,228,929,495,371,937,519,472,854,522,379,115,125,195,460,581,222,513,519,520,564,859,910,233,711,229,887,541,997,617,779,21,751,912,29,326,115,861,188,819,41,772,838,965,832,323,138,402,793,225,336,536,789,849,416,956,978,153,338,251,978,994,420,493,402,908,589,670,480,827,655,154,781,553,614,70,257,920,576,844,875,161,759,825,505,19,501,573,946,825,52,220,148,901,583,343,263,38,51,999,527,660,127,899,789,561,622,969,191,131,764,895,26,441,978,390,405,189,733,784,100,202,83,171,693,332,570,790,758,419,154,851,81,201,795,948,152,62,70,667,413,0,467,74,23,711,747,965,877,530,279,46,397,313,434,201,45,124,394,498,768,409,143,313,822,79,299,837,909,205,222,68,702,933,430,809,51,976,534,984,69,791,274,87,968,386,870,598,689,856,62,933,523,696,649,930,488,176,31,127,752,501,677,206,225,146,824,440,701,734,616,506,436,506,278,492,501,799,128,931,627,445,67,431,420,222,40,67,269,649,606,130,549,425,666,503,277,483,938,686,375,412,666,610,58,549,737,911,766,854,777,22,274,812,740,608,826", + "50,683,467,971,777,304,747,424,867,354,982,910,497,138,905,330,221,536,668,124,642,290,732,802,888,92,862,999,739,92,138,622,758,830,344,306,438,730,52,202,333,488,515,428,350,782,863,98,631,836,684,402,470,266,838,639,302,644,611,720,464,876,872,110,896,50,140,344,862,525,9,697,146,782,914,474,762,528,285,483,813,990,485,96,228,993,677,276,742,340,230,504,277,77,860,612,121,563,297,553,853,691,39,55,812,500,771,642,989,275,220,901,201,266,737,503,749,998,948,428,584,266,910,721,794,842,545,782,262,614,482,621,386,695,844,335,408,976,949,65,271,496,877,459,275,511,36,15,936,303,18,324,808,723,626,537,12,564,856,681,633,22,878,905,369,75,878,864,225,827,390,996,534,395,411,988,456,890,354,654,930,38,749,45,681,810,933,418,588,783,121,398,626,15,933,515,256,534,804,480,534,946,951,449,338,914,425,234,328,324,278,615,648,688,999,793,722,857,481,443,544,153,566,582,904,653,953,583,603,712,355,859,889,42,554,845,888,637,307,937,148,759,285,839,735,273,670,836,570,180,852,935,18,53,79,478,740,559,699,431,418,527,407,746,30,364,552,484,59,463,161,112,515,331,885,313,736,330,31,729,5,294,377,186,274,655,708,373,256,599,284,49,300,268,190,614,917,803,625,331,524,774,106,926,830,34,91,998,558,454,672,377,187,909,437,709,451,541,433,328,479,432,763,87,537,178,328,783,167,549,393,898,667,74,353,879,350,706,469,762,74,570,198,548,21,411,4,432,947,102,749,51,426,913,289,163,213,935,969,280,729,788,714,296,662,204,72,261,369,644,950,795,210,185,208,511,127,287,45,831,455,301,190,203,519,694,182,935,935,571,902,25,523,424,809,375,740,83,820,975,773,824,889,327,851,47,31,111,475,101,555,888,576,558,233,467,111,242,869,789,954,65,222,180,818,562,895,248,984,307,399,762,834,469,669,964,303,849,113,348,907,4,98,860,894,50,435,733,20,590,524,325,696,832,485,929,409,930,900,162,468,859,388,769,411,679,387,712,977,188,178,136,234,634,375,975,915,427,315,183,188,412,62,599,71,312,142,692,880,211,213,627,207,538,991,209,619,207,85,475,898,475,99,311,199,290,696,789,446,98,849,706,794,842,620,277,873,804,64,581,713,242,601,620,648,301,891,334,834,79,640,404,804,707,351,812,769,443,707,294,391,942,388,657,818,929,375,800,392,657,374,572,41,311,311,542,973,208,514,867,882,221,185,742,749,513,619,418,596,873,598,452,760,930,22,380,419,579,886,763,338,774,237,843,773,578,752,151,885,429,538,838,803,963,816,832,737,668,514,572,650,595,198,256,988,909,422,536,178,89,173,420,468,328,280,975,22,802,354,252,931,396,608,272,322,720,217,14,371,411,581,186,579,494,425,243,344,351,521,485,597,922,883,433,725,243,852,805,620,103,976,586,931,53,548,471,525,758,259,219,633,399,42,494,71,168,937,339,257,497,278,498,155,538,775,716,364,121,426,548,236,960,636,379,211,952,339,716,489,72,614,405,590,103,200,843,556,445,774,538,643,967,633,844,379,104,425,838,563,481,535,160,938,395,391,263,84,709,825,4,267,806,493,452,843,512,36,447,301,483,557,744,271,93,140,388,500,678,532,556,558,571,212,174,242,26,884,337,544,541,71,485,408,847,260,358,436,848,571,398,968,158,53,366,156,167,404,536,275,811,677,480,143,456,609,40,213,723,382,977,392,42,367,619,969,427,516,607,575,502,779,457,359,285,252,954,443,927,604,2,91,238,714,739,355,50,751,167,367,880,109,262,435,664,73,45,58,649,540,211,214,106,665,99,25,63,647,537,686,918,438,461,806,725,93,916,182,953,441,304,427,58,221,341,284,528,991,643,621,839,471,782,466,951,59,252,602,948,177,961,961,778,129,752,135,823,121,110,537,948,305,181,829,809,177,677,124,125,382,965,325,914,15,391,467,0,348,205,545,636,636,194,439,13,512,194,413,601,176,956,56,209,474,724,732,732,145,470,331,161,169,10,135,134,22,243,970,551,797,749,13,764,365,357,904,275,795,830,670,249,991,982,494,80,460,836,232,180,479,79,94,965,799,76,155,591,667,189,732,9,384,135,362,555,347,940,354,356,797,303,58,770,179,303,100,183,964,515,890,547,540,439,473,995,820,873,220,262,897,513,752,103,619,228,991,465,199,167,588,923,17,846,272,406,920,227,791,741,87,765", + "994,47,194,381,114,546,839,587,500,219,271,203,743,775,6,652,177,751,183,632,393,321,966,352,886,518,923,584,230,32,668,355,263,29,718,953,838,156,784,869,775,66,628,932,779,965,98,389,868,974,571,486,839,176,165,579,291,532,918,391,717,407,480,815,92,996,364,544,612,106,397,676,559,941,956,653,350,14,858,142,221,487,717,883,104,630,492,808,714,976,638,686,294,149,175,284,784,338,953,561,99,680,810,988,354,993,984,598,624,765,870,865,330,362,590,424,249,478,964,384,164,840,301,186,636,984,914,534,415,174,616,98,522,635,898,231,425,124,880,191,856,531,689,510,83,156,730,578,199,920,874,201,775,256,865,767,902,274,553,625,859,831,531,932,564,119,630,637,551,316,708,336,158,613,859,182,26,268,325,686,482,591,625,13,318,261,546,812,562,260,842,828,862,409,386,331,513,627,669,48,604,352,933,965,220,597,453,812,430,394,531,382,294,981,522,624,800,840,279,347,495,390,213,578,738,18,496,97,988,653,814,565,761,566,254,156,88,250,28,368,207,398,533,244,544,568,212,537,371,685,434,889,880,875,446,807,294,388,146,174,944,986,819,643,245,751,980,980,149,427,426,930,634,832,767,553,170,517,752,825,360,248,51,658,575,315,368,606,266,7,671,765,846,267,441,344,188,749,851,153,276,131,735,639,303,558,392,700,574,799,70,852,338,657,849,437,534,130,955,880,238,342,191,690,378,406,372,891,881,350,529,472,818,212,750,82,717,822,306,408,271,831,54,874,242,49,423,773,865,860,317,598,384,15,214,629,352,43,50,452,578,601,706,702,718,740,466,758,522,251,218,959,646,689,165,140,931,284,831,161,591,245,69,402,917,992,217,15,620,33,987,868,803,334,114,226,391,302,549,69,271,174,894,950,455,429,444,724,745,530,796,823,427,669,40,905,589,739,229,154,853,614,233,233,600,820,944,634,325,796,555,742,985,69,88,546,374,822,471,7,619,756,273,256,53,502,576,844,372,106,625,329,828,983,187,327,578,723,989,113,607,943,81,147,281,568,61,72,568,954,704,224,353,71,100,609,890,899,113,214,827,135,13,677,593,187,909,156,661,956,26,899,329,439,663,112,27,214,5,63,531,926,531,987,165,387,849,908,938,335,342,371,521,921,514,515,794,529,446,883,655,524,718,978,454,279,269,436,641,215,66,41,938,38,4,121,274,35,686,823,199,624,136,444,979,98,179,747,485,945,399,337,509,432,598,821,215,472,89,305,48,506,119,369,811,134,738,874,252,56,839,535,621,116,88,826,361,429,897,698,209,154,485,32,758,211,834,160,837,282,269,963,798,307,810,515,119,746,114,824,664,173,889,428,871,77,729,154,797,578,452,311,4,591,684,286,433,726,855,267,841,857,921,842,414,659,110,847,673,706,681,803,955,509,957,284,648,807,657,12,849,137,573,294,480,239,528,739,363,811,602,499,653,139,560,882,226,762,428,844,314,67,519,151,381,750,527,475,143,609,738,927,539,787,284,110,662,620,409,180,283,534,963,732,256,281,428,123,319,602,73,268,788,166,747,7,179,784,920,755,900,896,977,762,104,448,44,520,175,902,699,721,641,689,976,17,460,405,17,167,89,893,227,149,209,855,621,74,324,152,807,377,677,496,879,330,974,704,36,568,627,639,718,684,515,312,203,865,839,103,556,536,373,998,435,490,514,820,418,677,512,465,999,600,584,303,318,304,337,764,331,390,730,850,470,25,122,135,548,489,682,427,66,101,57,378,8,532,749,41,783,981,280,434,629,645,190,789,611,399,353,430,660,415,23,119,146,893,688,992,993,171,998,119,731,207,784,902,766,904,438,698,634,608,699,351,383,38,289,47,147,101,845,169,301,336,254,266,427,939,466,598,970,325,563,211,40,67,196,299,357,208,950,717,693,313,441,221,588,609,477,438,927,82,998,449,471,728,130,203,372,962,518,626,937,337,681,694,72,834,963,995,986,34,74,348,0,244,394,302,638,965,73,680,372,771,900,767,445,663,481,295,744,693,371,183,881,608,376,142,767,409,782,539,818,875,190,6,267,557,50,339,358,648,847,494,660,311,213,415,93,270,163,903,712,450,731,823,355,517,663,306,517,564,774,100,227,163,157,970,404,70,38,824,749,989,325,898,77,208,671,314,320,830,517,143,10,235,33,325,855,512,77,745,27,692,549,327,867,945,648,260,123,660,522,620,365,738,765,894,292,312,751,984,874,995,14,444,134,160", + "630,260,984,803,893,576,402,424,212,744,78,898,258,731,730,752,375,588,869,702,987,571,255,152,523,172,164,768,195,604,773,856,895,183,609,913,950,401,468,124,590,413,652,930,181,407,886,558,329,342,586,274,60,835,319,737,575,269,379,158,672,651,551,970,764,199,940,305,800,185,599,68,88,291,323,670,861,35,267,777,623,222,552,38,635,479,86,630,922,686,217,305,965,711,352,426,849,989,276,589,21,731,139,495,496,32,476,125,600,695,797,472,768,928,758,649,698,323,22,811,375,231,425,545,698,163,982,509,22,417,713,570,288,692,935,28,743,267,334,993,619,234,695,456,702,969,62,674,82,901,727,139,440,355,596,961,525,168,406,106,551,856,551,657,277,224,364,123,558,799,607,632,619,307,501,627,854,72,632,119,594,386,271,248,931,327,834,217,872,736,323,354,256,85,865,736,881,977,443,865,5,709,256,75,231,810,180,185,483,435,409,845,110,611,906,352,867,576,187,120,674,567,705,8,387,851,486,207,815,827,97,627,136,654,566,792,386,371,497,189,333,437,82,518,669,811,36,15,484,576,258,236,611,952,617,35,502,403,924,310,95,169,847,394,839,716,294,515,810,658,762,988,986,793,71,503,968,24,259,433,535,374,564,648,243,121,489,237,786,617,528,83,329,266,643,867,677,558,190,33,211,892,872,174,432,545,52,38,821,404,64,388,1,902,856,893,867,669,304,37,323,360,958,69,241,329,922,190,109,980,578,406,688,325,439,85,724,940,306,910,454,947,338,782,857,995,500,27,189,437,677,214,538,878,573,960,851,192,584,76,65,997,345,255,727,843,374,486,104,911,222,916,997,55,294,523,114,573,615,918,164,652,976,374,137,364,644,327,93,118,658,753,552,259,840,47,450,767,877,684,408,753,968,339,558,388,461,980,767,771,159,265,113,244,24,247,977,120,435,349,290,616,568,807,694,374,906,109,831,233,30,969,947,720,162,746,677,960,815,111,894,813,269,34,598,912,500,190,716,909,337,144,919,670,864,285,807,141,525,432,382,753,899,744,603,633,491,796,764,63,891,328,866,225,528,812,494,559,563,15,601,508,506,529,567,390,174,360,356,354,679,331,7,926,787,280,775,79,865,634,537,299,698,737,590,458,991,356,435,397,486,115,695,87,562,937,56,106,639,240,556,664,381,748,144,124,310,178,385,538,292,832,273,606,770,796,875,202,824,818,987,182,196,796,980,259,27,422,535,986,715,268,391,230,323,496,574,436,802,418,528,566,138,557,97,311,950,568,660,961,60,552,725,510,78,390,115,534,453,564,865,787,723,827,708,886,814,396,157,472,387,46,961,759,348,81,367,237,809,666,919,333,829,716,836,946,241,307,153,976,842,672,194,339,75,407,6,826,835,774,562,200,334,681,635,963,811,940,529,453,396,562,916,185,491,167,791,428,195,439,844,284,426,97,828,899,404,716,661,482,277,887,268,172,256,745,10,835,462,927,634,916,338,561,342,608,357,932,476,970,252,62,3,717,547,866,620,684,900,445,571,114,875,210,276,514,927,934,165,799,756,503,440,300,716,606,637,487,305,340,822,446,992,837,777,801,546,307,611,303,34,244,174,639,732,769,431,308,628,186,503,670,547,562,184,968,871,213,799,336,836,980,664,61,154,671,670,400,394,946,105,590,203,956,269,30,549,653,521,510,688,173,811,558,965,736,46,267,803,950,674,438,488,158,457,657,697,220,66,871,585,974,665,858,7,260,117,25,482,778,12,730,141,14,678,183,635,8,215,427,932,285,6,441,351,1000,762,234,560,782,900,459,867,670,262,656,718,362,3,479,497,215,755,192,366,238,853,260,729,942,42,869,286,195,729,585,240,592,258,705,439,72,90,604,511,260,585,918,378,55,748,240,859,249,16,768,860,983,893,893,303,970,288,497,24,348,478,140,348,473,354,361,198,405,452,422,256,624,762,552,949,128,949,973,386,275,255,949,644,54,79,949,266,162,23,205,244,0,912,848,789,253,699,933,543,87,936,323,69,774,272,600,195,524,321,131,921,791,854,862,832,414,160,104,184,177,64,259,153,271,304,412,103,845,896,145,597,392,874,513,969,366,319,390,181,118,340,508,613,266,400,654,666,320,173,358,442,497,486,67,109,812,286,182,917,241,451,874,925,117,80,180,170,322,258,996,143,162,389,359,580,857,122,69,821,643,618,900,479,999,44,553,257,827,50,896,400,668,370,916,583,195,325,845,674,667,398,117,864,604", + "380,871,178,419,20,342,158,820,69,842,908,456,797,616,328,60,905,545,755,190,368,635,94,843,591,798,189,26,953,543,812,651,989,599,336,75,654,439,540,139,875,295,903,996,355,517,20,603,923,432,624,547,115,679,490,72,658,135,676,662,945,912,832,558,127,836,510,547,593,311,82,24,918,158,962,142,959,130,506,311,36,350,17,316,486,845,697,587,733,157,515,766,771,975,268,447,71,987,891,798,927,422,25,414,707,769,335,191,610,825,103,388,153,279,659,181,760,775,711,846,446,6,527,222,982,468,537,743,763,882,248,482,207,282,967,221,221,890,85,458,244,138,338,837,990,563,695,352,122,581,592,378,135,277,757,730,308,373,100,543,393,252,797,783,196,688,20,211,107,681,79,588,983,360,797,115,326,275,596,741,101,945,141,658,367,200,967,894,366,260,320,624,445,156,127,73,556,687,376,666,678,508,28,992,879,487,5,226,241,572,492,194,141,431,635,459,838,396,711,943,722,805,946,502,322,783,692,915,167,503,147,955,266,278,15,787,196,11,515,534,200,924,359,457,76,950,196,795,411,153,68,908,297,542,81,108,327,26,285,918,384,804,934,457,935,730,517,373,223,478,553,686,712,650,303,916,636,555,955,70,901,232,468,372,54,684,510,370,777,463,88,218,534,947,18,866,831,189,8,107,188,521,906,12,590,997,390,14,162,16,893,954,969,648,633,668,582,722,312,520,919,133,325,449,805,586,614,71,860,170,39,921,786,937,845,280,665,812,157,457,162,759,658,276,76,195,39,20,333,566,457,149,791,50,148,704,485,747,359,764,601,142,373,709,500,728,38,435,613,698,203,747,114,311,985,625,909,292,554,617,275,23,478,907,691,177,947,660,903,983,262,893,89,836,630,426,548,924,48,629,633,990,530,180,428,99,584,453,91,336,125,546,237,167,514,16,414,894,108,928,102,111,409,997,477,373,398,60,398,183,316,593,180,483,812,25,733,724,883,254,552,468,18,660,309,145,245,642,404,696,664,114,784,75,421,735,159,851,517,427,505,14,750,903,213,648,50,1000,625,469,625,236,770,514,38,637,204,241,134,338,171,521,229,149,81,17,499,912,470,273,328,311,854,232,191,610,4,888,684,679,22,831,711,636,413,537,654,763,465,736,796,679,745,354,721,331,274,834,558,620,986,789,918,457,594,103,696,980,234,630,640,124,248,165,589,302,650,104,662,677,627,328,590,534,664,189,707,948,546,416,473,889,977,427,633,260,237,841,891,830,234,522,911,849,252,344,191,642,276,685,428,253,922,147,502,727,382,527,606,766,875,73,801,629,807,418,751,83,624,380,274,284,98,914,297,478,938,965,668,462,887,537,888,488,444,988,918,990,365,979,647,174,94,721,542,740,812,841,983,402,283,818,350,224,735,452,453,57,23,87,17,721,518,130,155,284,788,52,115,656,671,724,187,243,965,743,473,755,940,329,287,489,30,500,36,267,13,135,12,798,850,41,654,504,721,798,255,505,252,276,877,548,507,711,575,731,924,924,58,281,110,221,984,462,560,680,460,615,391,704,181,264,10,303,331,596,478,588,242,753,439,626,920,385,841,589,850,943,394,784,228,9,282,801,511,842,77,120,309,375,445,336,584,437,502,608,747,551,477,50,146,376,924,705,485,313,117,238,351,616,565,33,829,230,770,489,115,998,376,101,24,686,774,7,162,579,198,309,954,632,178,883,378,671,824,93,368,10,414,830,899,918,268,6,619,297,18,338,815,733,851,240,260,363,150,981,898,366,876,875,708,65,563,350,40,472,275,184,752,850,89,671,206,995,737,564,276,922,825,540,60,999,785,435,316,607,799,39,188,111,387,152,925,437,637,686,980,643,507,207,904,517,39,518,671,637,382,698,674,988,77,299,205,106,178,421,774,261,418,469,91,373,15,450,927,952,796,72,44,397,215,855,316,919,233,857,766,900,494,261,974,613,270,148,363,791,395,186,12,912,538,268,549,935,711,545,394,912,0,411,789,904,748,931,647,67,724,229,229,398,394,755,420,799,594,880,436,321,762,182,983,299,915,340,705,291,857,336,286,741,852,275,692,468,242,101,825,386,825,475,473,365,249,853,484,361,435,383,508,172,911,347,356,499,268,301,606,2,273,510,755,703,179,161,610,522,539,128,298,189,593,160,219,331,606,993,758,745,426,445,229,36,461,944,701,912,607,933,600,825,239,252,681,973,673,313,295,311,777,170,344,496,951,51,999,302,122,596,624,184", + "785,344,44,488,299,500,193,616,839,205,673,327,644,459,777,402,72,184,598,206,400,331,71,306,129,28,316,34,456,498,522,512,513,297,535,59,243,581,250,916,93,109,63,41,325,721,253,774,828,275,706,556,402,467,735,837,70,683,660,131,320,866,951,877,295,357,453,705,963,278,480,97,688,249,779,259,632,457,47,605,523,771,489,895,25,273,709,691,233,221,903,688,732,591,698,509,790,406,363,569,259,214,616,437,915,611,974,689,714,590,126,143,191,530,543,258,48,461,89,524,312,41,797,668,766,960,240,631,529,623,858,395,368,314,732,304,584,767,537,88,997,16,326,678,403,632,945,231,407,171,568,313,952,33,996,865,806,989,110,777,531,768,514,365,752,257,598,544,850,635,379,227,340,842,650,276,205,877,557,631,785,808,971,760,768,263,377,626,530,570,649,780,409,939,682,126,333,278,34,120,916,346,313,955,755,932,217,191,379,197,541,254,827,234,179,130,29,976,186,109,39,286,384,759,761,838,109,854,511,930,12,769,492,74,67,186,756,857,437,743,927,544,405,351,139,566,547,978,27,375,628,645,240,758,578,541,868,507,52,65,903,341,270,907,389,469,305,277,413,585,847,235,703,90,302,476,624,90,716,295,256,862,71,292,675,329,912,542,687,422,473,734,518,283,50,567,641,813,490,851,649,995,246,865,347,905,698,104,880,813,672,231,160,283,146,371,28,732,421,758,961,906,492,922,203,689,710,361,483,37,107,762,138,657,556,953,347,591,539,831,696,563,200,723,135,881,866,358,727,74,438,636,208,877,180,819,957,363,988,625,452,618,39,306,559,580,727,364,997,195,323,972,48,262,452,598,580,620,554,48,95,434,822,603,833,79,817,894,381,890,288,107,792,703,753,590,993,779,926,876,914,12,64,75,712,366,555,820,897,47,653,64,441,894,664,510,764,965,927,639,300,905,712,73,48,409,659,242,645,920,329,585,785,539,587,652,87,280,101,5,169,672,773,862,986,436,884,567,849,730,731,780,913,959,964,411,428,838,464,182,536,293,602,786,799,195,582,205,91,576,403,992,979,426,450,8,373,822,576,569,9,311,809,75,695,844,57,932,483,131,20,916,526,528,559,768,185,709,827,787,310,834,226,989,218,657,299,815,383,64,778,14,617,761,701,751,9,54,905,981,385,346,608,846,779,627,179,558,159,258,385,210,189,280,359,89,476,463,836,466,643,701,846,45,93,95,801,526,911,177,768,31,301,238,20,118,693,333,37,962,472,930,667,434,800,556,236,836,659,78,470,183,190,629,281,6,512,260,496,752,151,243,236,48,534,314,981,610,444,652,825,535,761,923,747,846,8,911,90,361,187,918,44,754,928,856,119,724,962,581,959,738,480,622,374,184,819,44,608,47,846,624,421,802,810,17,760,909,893,434,866,356,104,437,989,771,879,935,980,192,129,319,452,437,781,410,956,86,475,342,84,698,176,341,436,551,432,65,592,311,22,14,876,366,33,234,479,940,593,878,393,223,445,963,437,707,521,624,283,501,594,262,332,6,437,306,869,208,965,678,408,660,593,262,805,929,160,244,871,674,541,792,489,7,176,809,996,5,424,523,582,906,280,789,719,191,671,145,425,25,716,837,555,644,333,391,786,357,453,696,574,780,890,334,899,865,802,272,272,608,384,653,300,455,488,273,307,306,7,980,298,738,66,34,711,665,778,421,916,604,547,310,881,420,684,393,66,159,950,601,130,656,684,733,5,820,796,782,539,639,89,324,159,959,882,775,680,941,717,875,989,93,908,640,398,235,126,215,109,840,150,666,761,295,210,361,365,122,287,796,755,142,404,592,987,17,909,608,854,349,740,552,651,900,348,882,234,730,479,219,887,884,646,276,344,814,331,328,49,728,977,214,494,924,484,627,883,459,157,235,520,120,889,718,688,281,164,928,883,410,607,942,620,81,6,624,719,580,927,615,691,553,781,27,350,836,199,825,521,925,939,429,637,136,747,636,302,848,411,0,996,967,17,20,855,870,479,269,897,696,121,301,651,429,477,721,424,749,746,412,859,785,870,90,536,399,841,209,578,482,255,868,956,178,411,475,628,903,986,908,906,638,194,376,657,246,340,983,811,17,976,126,522,194,232,223,908,643,810,594,861,110,960,859,974,713,793,585,167,40,182,162,739,283,284,751,326,739,282,553,620,89,789,620,563,38,198,817,768,183,609,92,483,667,855,23,865,135,165,558,540,498,539,173,79,687,311,110,100,935", + "60,638,765,319,530,682,933,400,938,307,214,138,52,752,290,719,284,782,770,920,243,846,22,793,863,474,844,767,81,63,98,659,203,903,915,843,870,874,245,811,89,889,896,661,386,815,996,781,503,251,405,249,12,926,491,244,334,815,511,520,937,158,496,332,843,210,269,647,831,298,950,345,947,502,308,916,958,797,122,839,68,230,811,99,365,687,950,132,553,781,142,716,671,825,504,57,607,997,646,326,642,245,643,841,164,401,324,94,82,874,916,396,462,293,623,438,336,501,974,29,207,19,805,262,931,395,773,993,356,853,318,711,285,114,810,354,903,524,3,249,620,219,892,925,955,594,475,145,496,995,226,794,42,712,701,646,583,281,308,654,182,889,746,515,845,662,509,133,538,6,992,902,422,891,111,857,879,754,457,177,5,946,297,386,132,982,633,57,494,654,588,852,370,957,831,1,298,37,35,974,133,408,334,631,172,245,260,968,640,447,355,778,304,203,700,122,699,46,51,206,415,436,668,331,523,860,950,992,426,13,905,467,169,704,709,250,454,152,779,897,363,975,259,19,970,8,241,793,305,96,373,444,291,303,460,611,384,823,230,386,69,953,54,928,260,433,286,298,379,118,751,850,731,123,945,692,360,875,267,918,743,174,81,307,369,706,953,63,22,743,735,463,367,893,212,125,442,770,739,159,401,854,374,963,808,224,485,709,800,793,123,678,612,628,815,893,693,241,284,832,448,548,515,880,867,744,827,770,482,355,864,75,3,662,514,172,885,737,450,269,737,905,528,585,257,518,774,218,1000,739,875,819,812,411,524,664,580,257,384,254,624,561,941,701,645,939,254,695,226,124,488,542,733,496,528,594,203,235,673,106,126,724,41,92,832,894,948,554,69,426,393,483,776,23,581,277,756,296,189,795,387,895,263,841,465,466,818,460,24,735,257,426,641,387,770,117,204,242,694,29,176,873,549,739,927,782,919,265,346,996,857,639,886,408,195,908,49,528,754,163,78,494,353,926,590,671,130,129,647,67,242,827,268,792,38,746,781,87,669,589,539,166,267,544,259,807,347,321,712,639,404,773,228,140,310,516,520,741,732,737,353,226,756,790,838,765,472,755,772,823,249,54,597,45,641,835,955,289,59,156,946,755,599,31,739,357,145,315,720,890,542,470,192,332,232,516,47,964,703,109,776,810,986,736,412,947,701,538,66,553,96,943,884,576,296,81,237,530,343,465,217,560,718,629,892,769,144,749,966,51,630,799,238,545,881,178,808,985,558,628,401,324,378,356,894,193,709,448,285,206,75,709,374,253,334,55,650,87,348,631,741,268,729,58,81,935,871,549,333,553,967,178,405,92,702,166,643,428,343,229,856,11,271,377,582,909,619,187,142,584,706,738,117,26,207,310,200,507,505,509,449,541,396,227,189,125,116,773,359,653,817,687,259,406,78,11,312,279,930,57,647,875,975,49,271,442,11,731,384,57,383,335,388,450,321,213,807,2,269,976,668,865,505,27,240,350,380,420,482,723,381,405,787,114,179,933,704,491,844,530,968,837,284,394,739,547,378,804,223,461,757,68,78,500,584,768,34,284,228,152,107,53,466,726,240,505,248,808,146,651,127,783,815,951,306,384,205,327,334,877,149,561,347,776,965,539,443,540,904,525,738,467,606,980,668,634,741,797,570,69,330,860,358,662,409,517,643,827,631,769,154,332,545,812,136,52,645,647,254,836,301,607,153,699,176,621,350,335,280,17,888,953,25,603,886,522,754,239,863,437,955,245,725,14,143,863,182,847,575,14,604,505,93,388,708,79,543,914,547,682,685,844,847,666,675,182,665,290,662,496,145,525,631,828,741,678,123,800,803,8,792,543,135,338,54,221,590,829,171,268,925,342,2,812,643,708,77,675,406,572,84,743,979,916,289,550,194,861,873,454,601,215,789,570,765,456,794,879,939,329,467,713,6,832,901,180,289,711,28,378,169,85,740,618,794,344,453,192,508,453,51,168,886,673,965,636,638,789,789,996,0,12,307,993,399,19,591,190,281,388,551,877,805,913,388,69,984,447,947,476,202,872,852,681,467,258,583,611,740,827,149,202,361,712,615,531,192,759,126,809,696,314,785,905,422,468,612,536,115,959,382,515,59,509,907,867,594,654,763,839,254,463,837,850,859,458,185,960,198,591,864,849,821,883,918,6,252,52,357,899,953,7,729,669,149,479,546,649,213,180,427,89,97,229,392,688,26,646,115,958,972,957,373,435,230,300,196,634,795,562", + "341,799,755,131,472,873,445,126,689,277,78,492,94,168,708,75,758,995,218,421,788,186,863,161,712,983,214,601,637,887,732,291,840,537,694,523,925,871,359,556,584,545,150,711,130,159,449,870,428,394,859,120,515,38,664,847,304,379,458,431,631,323,736,882,82,430,90,387,70,230,926,244,943,680,958,874,755,428,708,973,891,585,311,419,727,589,29,429,94,219,543,639,757,258,588,123,522,382,832,923,749,874,459,445,504,331,309,876,574,368,305,88,468,560,34,809,18,336,70,47,317,82,384,471,227,556,125,207,517,925,712,844,928,408,616,808,665,203,518,412,759,696,259,855,648,128,366,690,550,555,189,986,994,174,642,448,642,964,772,150,247,532,144,906,145,210,720,944,589,623,521,813,765,189,398,719,161,445,201,182,17,959,998,625,697,257,278,860,856,706,42,754,505,679,833,370,675,662,500,275,791,415,600,107,742,5,521,387,621,542,731,42,275,220,366,893,952,433,949,854,991,415,540,457,810,524,252,483,490,899,351,349,954,391,16,635,318,561,405,33,984,56,290,238,785,767,5,326,315,192,81,138,759,331,923,670,131,792,228,679,219,481,749,89,129,163,468,403,795,606,809,503,515,918,786,935,532,62,512,375,951,371,147,6,76,844,999,336,872,922,783,844,880,924,181,6,528,810,117,587,919,914,546,767,280,181,800,15,900,903,951,624,954,625,136,729,801,611,461,401,249,712,10,615,405,377,940,501,933,859,32,807,166,814,675,931,493,603,704,817,593,152,219,237,278,421,915,532,956,392,360,610,917,636,224,482,657,660,192,742,849,178,474,897,736,155,78,509,466,46,192,961,312,662,801,358,194,713,654,67,234,438,746,715,334,872,893,386,989,792,649,476,771,403,76,859,573,248,736,557,526,342,404,769,907,850,776,859,478,55,232,840,754,979,550,246,633,230,387,420,202,915,466,404,119,433,109,252,656,744,34,683,845,347,562,418,911,440,602,108,347,369,520,668,907,530,582,379,970,277,981,356,207,226,124,174,964,380,498,476,865,141,197,328,437,192,386,835,268,858,520,923,157,627,552,947,534,145,21,523,699,332,105,784,412,158,778,709,678,850,214,778,547,161,564,951,938,768,617,531,160,543,19,290,241,50,24,284,775,106,602,66,403,286,557,970,800,830,901,451,337,726,566,752,901,677,753,47,156,74,558,411,358,487,16,520,417,600,562,625,108,317,876,808,937,84,952,355,402,509,258,671,682,765,346,585,844,377,619,803,153,485,416,523,150,180,288,425,625,821,155,89,457,542,173,33,672,228,983,296,865,115,676,787,186,669,404,183,621,784,636,842,237,795,11,786,191,336,589,107,480,406,135,811,515,767,233,250,705,25,671,41,139,60,6,858,720,284,781,302,29,114,579,547,699,372,430,604,912,385,63,716,857,175,332,552,62,402,479,109,193,700,289,570,886,104,452,176,893,802,434,349,423,433,350,953,796,356,142,903,818,655,889,967,779,683,762,388,343,816,267,264,128,968,142,582,980,457,298,357,99,631,734,655,307,916,401,749,60,521,275,79,41,843,632,512,198,243,55,503,978,223,97,102,498,519,673,962,728,443,708,685,705,539,250,286,27,236,412,668,101,441,470,378,559,775,740,601,148,975,446,378,827,880,244,231,106,158,661,435,539,78,548,702,435,146,898,634,738,455,740,349,189,536,981,383,406,567,685,817,818,120,967,550,677,586,90,266,21,506,459,915,524,928,307,24,648,11,905,468,634,984,728,325,975,107,760,952,844,312,165,914,583,952,325,490,545,968,175,310,81,511,633,967,186,379,834,370,295,675,761,522,599,665,237,309,147,621,20,936,747,480,834,886,975,198,361,544,309,978,291,823,454,692,548,16,435,417,132,379,480,702,989,693,263,710,713,307,7,261,736,132,237,468,217,446,43,862,812,834,799,802,831,214,231,240,508,894,311,141,269,710,343,764,769,255,895,726,759,357,300,506,243,532,877,194,965,253,904,967,12,0,861,636,138,820,905,173,501,691,573,423,993,959,160,321,714,918,454,747,764,479,630,119,439,495,453,780,496,229,709,880,851,532,840,588,477,466,334,200,491,670,939,430,770,101,902,799,436,796,816,344,312,896,937,929,88,872,959,280,915,404,281,640,383,682,885,611,803,588,521,145,896,454,709,254,247,106,206,845,497,529,822,402,414,572,379,730,452,901,125,146,673,841,900,977,262,95,275,584,457,573,786,797,946,75,491,625,665,618", + "278,881,523,741,598,424,478,331,883,245,727,723,398,978,925,173,765,223,434,718,177,398,767,109,986,458,499,623,275,907,265,766,726,579,278,374,901,579,616,553,417,624,313,67,864,157,890,89,572,572,406,638,482,521,235,42,936,129,563,691,20,248,909,191,649,390,848,692,807,242,939,546,909,115,169,692,789,803,339,129,930,715,780,46,905,955,456,424,173,96,821,225,169,959,243,159,101,584,394,607,781,346,546,839,156,164,393,781,897,688,577,274,578,93,963,513,163,92,371,980,546,490,256,974,872,468,281,843,944,767,411,785,692,347,436,242,521,728,519,919,667,884,52,513,505,46,642,800,909,258,904,728,456,313,911,881,768,538,330,886,887,650,43,22,956,127,737,163,215,537,586,178,77,112,839,250,8,76,58,547,854,132,781,98,430,737,3,338,835,474,170,730,251,19,156,942,576,151,345,813,130,235,765,691,17,608,758,115,518,53,891,95,180,716,739,625,964,20,164,926,186,456,394,718,503,568,87,990,969,272,758,960,87,613,15,471,400,992,346,836,503,550,204,954,633,708,88,418,387,580,157,917,121,719,994,988,23,460,641,476,739,755,533,517,766,983,21,248,62,247,643,351,107,549,229,639,98,566,567,114,893,589,97,679,239,1,791,738,103,994,898,160,127,826,618,825,378,359,470,957,427,221,64,353,509,130,103,711,345,564,29,580,742,108,606,34,153,49,345,110,515,116,917,1000,1,55,974,682,727,729,213,614,429,975,244,123,169,818,802,548,622,216,723,776,149,753,732,953,206,123,110,608,122,483,454,481,833,980,514,687,107,814,954,382,41,34,174,195,31,830,329,959,606,596,436,18,803,112,451,114,885,447,746,371,964,670,832,384,219,418,696,81,62,497,870,359,509,672,578,284,461,328,618,909,190,371,876,293,716,624,689,915,549,119,843,255,450,789,901,337,987,270,657,238,405,411,840,773,59,830,979,847,591,414,319,107,255,41,757,621,206,919,456,23,63,289,822,181,134,232,596,370,260,705,261,913,620,847,483,246,282,600,589,962,33,194,405,377,42,803,863,268,460,963,95,278,95,8,909,512,373,806,57,205,229,182,250,446,330,547,191,636,183,777,709,684,323,389,36,877,119,230,415,739,516,319,683,201,523,322,640,291,780,786,500,838,770,401,179,348,929,355,396,112,357,778,18,718,775,283,670,172,465,794,143,670,950,933,610,442,519,678,633,786,687,863,15,645,266,379,327,761,839,233,109,423,40,716,47,561,891,303,150,998,516,921,438,295,126,228,662,640,918,393,573,452,201,510,291,762,942,819,847,7,13,7,397,416,152,10,957,57,198,907,666,409,628,886,666,247,705,128,603,772,969,899,712,356,719,652,388,442,648,651,796,162,692,731,495,174,637,811,158,668,355,115,225,208,452,90,339,784,901,402,481,482,483,780,842,866,169,123,571,78,556,130,604,52,741,746,927,92,823,789,783,392,173,590,341,117,268,862,409,913,352,287,225,211,887,562,675,16,999,983,870,558,209,42,38,937,56,689,404,103,675,252,592,411,65,228,602,671,586,976,689,396,467,347,196,553,214,498,44,390,229,941,771,387,956,955,451,666,321,980,614,435,267,78,907,18,542,157,517,512,534,271,523,254,809,652,387,336,512,316,434,307,702,583,410,128,548,531,895,998,295,153,643,679,60,820,31,744,717,340,332,697,699,223,551,284,19,61,482,182,191,111,50,14,171,616,472,500,593,934,952,956,358,254,612,535,847,660,632,823,388,524,865,864,690,882,524,722,192,432,496,177,450,119,914,236,948,709,665,978,417,523,459,103,996,951,497,214,857,325,418,467,833,813,264,130,86,739,158,992,665,650,554,704,463,647,390,388,726,455,514,199,77,410,577,386,579,255,920,50,92,755,986,522,818,850,648,348,364,684,968,990,561,293,347,99,429,883,102,414,97,264,534,807,83,84,403,280,477,503,739,908,58,609,576,227,619,490,937,819,530,439,73,699,748,17,307,861,0,773,58,865,223,852,941,905,867,909,773,585,6,995,395,313,159,73,363,745,241,936,881,78,75,991,446,814,280,727,545,338,31,637,416,822,788,495,734,780,41,913,195,127,767,886,172,689,986,822,620,916,45,805,489,184,978,604,371,350,321,145,197,485,25,869,627,301,909,757,688,431,718,654,938,838,448,381,638,507,236,686,5,909,923,506,185,404,371,340,437,470,922,570,658,505,112,480,786,797,136,552,856,72,975,445,69,829", + "468,997,121,671,381,61,20,229,837,495,962,592,708,489,189,270,727,606,172,24,204,98,269,353,412,207,867,570,714,415,902,450,72,531,504,902,897,894,727,297,556,199,620,562,870,169,800,105,33,873,930,355,275,808,703,118,987,582,914,307,645,898,592,11,384,825,772,699,100,23,669,790,398,160,493,353,932,944,135,216,158,174,508,9,628,865,920,984,490,287,731,311,700,152,933,149,480,793,819,53,996,223,813,575,507,869,126,55,600,724,214,501,581,877,476,445,6,636,679,797,382,160,295,638,528,606,790,440,718,467,829,36,582,766,376,647,302,765,118,519,31,966,582,478,340,467,493,534,683,173,974,893,604,740,248,323,220,368,638,872,311,998,852,229,154,215,956,410,246,272,343,571,38,697,362,240,369,420,445,316,353,767,246,551,632,267,474,141,250,50,144,798,542,112,655,910,961,364,836,294,493,341,568,631,913,204,87,20,670,848,258,238,784,228,583,677,260,430,5,74,566,953,345,879,943,844,19,788,92,417,670,316,216,515,329,642,456,102,910,275,604,307,164,745,631,984,189,432,301,477,711,559,861,333,500,323,653,278,776,775,83,29,154,807,636,196,69,821,549,641,23,425,878,400,272,936,827,140,528,823,153,430,979,95,872,304,455,768,685,146,82,953,252,78,136,520,907,141,45,146,296,882,664,552,204,838,369,762,377,852,888,974,656,353,102,86,32,463,810,309,583,435,535,683,215,617,70,924,651,283,973,335,661,59,231,258,503,843,817,802,274,391,173,631,602,523,504,472,463,910,162,699,480,972,41,958,189,550,991,55,592,99,895,806,578,378,109,945,39,457,354,993,730,322,615,186,505,771,559,185,798,5,400,483,621,838,959,695,405,687,51,665,740,865,167,825,399,485,647,797,214,209,290,51,248,651,418,933,801,819,4,105,782,716,986,173,512,53,863,488,388,237,472,834,391,398,689,705,857,424,741,839,959,132,671,510,331,563,375,499,593,25,946,30,639,105,570,136,778,436,403,596,464,422,741,849,455,214,621,193,516,7,227,467,919,912,717,275,565,269,148,556,55,8,544,555,911,117,724,663,307,181,615,193,27,49,904,730,923,443,845,422,11,957,32,329,742,335,685,21,34,20,292,218,247,353,510,990,258,942,372,268,304,36,13,867,965,410,746,426,972,624,706,209,70,648,748,550,65,556,583,385,571,803,882,131,439,425,45,126,684,940,282,318,79,285,410,889,686,553,295,621,198,208,398,207,372,637,282,726,534,948,330,207,322,82,48,453,160,474,477,898,87,30,21,370,61,398,348,241,502,413,491,749,8,329,198,581,140,46,587,486,188,929,457,230,309,596,564,405,856,336,590,104,785,135,196,159,116,266,351,449,920,301,533,869,147,498,194,515,476,117,512,978,371,654,114,971,267,700,79,322,449,893,787,477,939,636,356,692,673,42,853,473,221,8,117,679,386,66,404,337,886,298,331,129,537,95,632,93,12,157,546,515,59,525,446,677,797,868,159,698,440,347,963,757,279,264,500,132,925,593,515,482,7,713,100,4,964,879,730,291,921,698,938,838,332,199,18,468,826,327,780,840,380,844,628,882,407,66,911,655,364,337,583,802,771,904,512,802,575,640,783,276,597,97,163,629,743,185,214,159,648,825,436,805,888,566,966,471,598,768,82,78,119,150,725,754,534,603,436,405,619,769,121,68,15,756,82,43,780,664,859,173,275,185,620,912,819,824,285,966,498,369,283,835,468,734,848,11,183,158,282,632,128,614,416,82,543,510,560,907,413,251,811,76,185,211,336,755,11,607,697,121,944,889,194,714,484,72,40,775,120,952,463,550,444,321,715,98,954,236,16,856,628,823,714,215,213,749,178,183,477,436,39,115,519,784,368,837,837,637,180,989,243,170,403,574,395,805,124,354,246,953,457,444,914,131,998,110,845,399,440,171,353,532,196,416,563,561,860,569,260,534,350,903,454,787,850,72,193,74,16,191,279,13,680,933,931,20,993,636,773,0,748,956,90,353,951,33,365,208,719,265,646,857,643,832,856,60,69,699,526,630,531,236,291,621,204,172,528,991,399,557,726,908,317,327,654,742,668,636,564,482,408,402,62,772,983,544,356,679,91,711,252,198,628,649,968,541,29,118,119,277,735,945,197,67,177,322,193,293,976,652,746,357,361,605,885,814,82,51,667,844,815,470,74,867,397,584,974,282,923,303,733,180,125,246,500,826,946,76,80,563,115,302,218,693,819,61", + "828,342,834,756,288,156,311,968,411,265,605,401,364,891,493,218,591,630,752,365,492,134,961,407,383,890,822,995,951,534,937,474,272,393,685,739,619,857,350,344,186,40,603,851,954,280,700,679,160,983,261,579,242,433,385,241,643,377,364,170,8,524,912,615,302,149,660,871,822,269,211,654,761,165,822,890,574,204,204,590,219,110,112,169,557,393,33,581,853,381,844,919,142,244,812,486,884,463,109,410,91,770,151,644,823,433,751,74,369,864,662,477,887,799,748,626,997,588,989,430,85,851,893,571,682,978,906,536,162,415,432,855,760,567,349,807,820,130,516,264,592,962,838,459,217,493,332,910,45,69,472,485,823,122,9,303,926,657,794,980,52,128,759,681,571,834,663,919,23,265,549,800,114,622,375,774,729,11,739,423,479,57,336,71,91,820,911,395,607,281,866,804,205,87,459,26,861,699,274,725,229,340,710,25,965,965,98,933,797,156,894,781,65,497,770,213,32,366,978,716,94,716,673,638,623,109,372,285,506,202,526,671,152,516,308,808,539,645,511,435,22,526,583,426,874,302,664,779,442,69,512,607,196,818,645,53,916,809,847,349,869,56,740,225,158,332,635,101,747,894,246,573,642,17,138,810,609,682,225,806,705,720,518,915,806,135,120,771,968,216,284,429,112,683,767,375,475,244,960,625,22,330,725,196,859,470,532,307,190,269,475,994,636,368,614,431,64,841,981,104,957,422,543,94,337,951,459,758,785,708,273,671,737,680,398,317,712,634,870,158,581,389,541,368,324,36,278,361,947,211,979,609,634,284,981,556,228,810,987,575,606,382,480,788,152,389,908,837,721,850,802,243,526,10,246,294,703,40,373,130,95,685,462,777,768,841,49,702,600,724,562,799,58,12,205,651,796,486,328,646,580,423,257,102,434,314,973,427,688,339,790,119,182,24,897,225,62,419,173,239,478,698,806,165,358,529,372,654,449,449,81,192,668,303,331,32,526,23,454,621,575,455,106,47,987,106,415,882,656,562,950,369,328,672,665,204,702,848,870,247,828,389,585,43,478,329,945,47,656,214,573,448,501,501,175,127,694,206,244,843,69,129,798,386,662,760,836,598,501,130,426,533,276,280,480,257,323,89,748,501,262,29,17,285,6,544,586,426,793,797,254,197,604,749,139,235,113,351,493,964,42,111,545,392,433,438,633,590,960,481,260,128,841,563,395,864,429,213,215,567,24,265,431,336,755,830,676,791,801,876,925,140,154,632,278,425,184,691,324,521,563,65,593,590,582,795,714,995,221,814,536,619,116,911,889,474,800,237,778,92,123,145,962,638,902,77,327,556,681,134,573,243,598,103,194,566,644,89,941,235,629,18,537,811,407,955,86,519,127,162,395,303,890,30,485,984,143,135,990,655,108,106,783,890,883,829,175,64,820,376,226,598,978,931,798,444,251,990,397,538,614,507,712,454,506,560,675,413,481,154,795,584,919,180,257,337,223,876,781,274,834,851,52,816,6,82,618,727,78,184,860,589,453,29,897,633,819,597,396,9,493,461,626,992,978,217,756,789,38,340,85,280,633,235,421,666,667,480,756,295,788,917,620,424,725,590,481,527,207,303,792,951,48,53,594,917,800,851,135,684,878,448,788,466,820,856,384,610,543,443,287,184,555,610,737,825,62,303,825,400,977,748,446,145,423,716,409,962,64,275,197,413,640,167,983,141,152,997,715,838,683,664,801,637,296,431,114,71,392,549,5,851,698,547,720,859,360,127,652,542,311,966,263,155,660,106,448,149,72,117,600,123,574,603,137,314,369,209,567,650,130,43,678,617,732,727,914,6,190,961,856,193,79,991,728,563,475,650,136,667,439,164,955,855,246,183,397,106,280,305,810,271,989,781,747,136,427,426,316,639,103,898,258,872,540,569,388,477,837,151,715,443,277,484,9,643,289,363,163,834,307,411,315,224,964,530,89,895,273,850,345,525,700,414,661,378,937,719,790,865,719,795,305,666,46,512,372,543,647,855,399,138,58,748,0,101,548,114,485,773,55,464,516,685,503,538,846,182,107,242,437,929,10,728,245,279,159,956,630,775,43,946,308,920,274,596,578,97,432,454,115,839,374,926,174,804,474,148,811,9,87,902,362,232,772,533,189,333,285,649,93,514,195,722,571,969,513,705,356,642,65,181,552,742,609,237,54,952,779,502,262,520,692,999,132,473,19,741,166,695,66,752,534,638,683,346,201,368,106,139,644,262,880,815,753,333,334,564,832,824", + "213,572,711,970,224,632,54,225,608,251,789,786,646,601,875,221,635,574,329,665,574,398,686,380,333,541,856,8,67,587,204,745,226,112,818,414,436,9,647,387,391,59,616,269,983,577,52,945,631,146,430,437,892,987,921,471,547,985,611,859,546,574,256,66,687,752,230,70,310,463,514,777,616,287,858,454,26,620,69,181,948,913,984,968,273,347,433,865,364,748,64,800,922,32,168,839,951,163,527,684,548,636,394,512,780,993,845,241,303,455,257,249,790,444,552,911,833,381,5,455,202,253,430,233,30,316,793,473,310,232,801,679,189,444,773,245,776,746,716,474,141,545,452,984,518,305,615,343,671,419,838,487,49,929,696,97,588,219,119,615,733,895,796,430,661,629,490,771,804,781,447,184,766,142,281,214,796,474,937,954,391,310,884,78,651,264,806,779,800,384,454,654,964,95,5,413,607,703,462,57,948,287,110,519,230,902,391,741,607,260,679,950,168,794,179,321,322,837,103,358,977,826,851,508,836,981,46,196,67,728,829,845,610,848,311,672,910,303,391,940,451,968,712,309,322,990,490,920,179,351,556,580,673,71,869,470,642,78,543,76,717,778,420,156,235,514,553,494,38,576,384,722,502,238,716,140,993,609,637,552,438,999,18,446,396,972,287,134,644,198,319,237,485,472,417,907,726,110,97,202,127,30,774,130,860,822,618,882,353,276,521,117,355,880,721,132,498,691,821,7,23,576,77,566,939,446,101,133,282,242,943,206,620,48,132,20,987,747,688,377,493,483,169,838,219,612,983,311,339,528,606,160,573,550,809,932,211,530,123,800,645,993,263,509,387,409,63,998,579,961,994,965,965,437,326,492,327,899,324,729,860,654,527,678,429,406,789,821,228,478,708,459,856,850,924,693,329,697,428,882,29,346,306,654,123,415,497,678,730,133,906,461,49,457,735,701,678,476,846,534,364,162,511,10,840,898,609,326,597,903,69,491,10,173,910,141,568,683,129,996,253,338,650,844,462,881,976,651,66,909,223,657,825,132,21,125,619,83,871,197,212,642,931,924,923,621,67,215,797,898,74,63,277,184,572,464,826,924,137,404,379,233,514,845,57,468,255,658,317,678,118,829,145,608,335,990,681,448,614,263,339,546,788,260,406,235,545,666,580,154,865,219,388,48,616,673,6,446,479,207,174,420,339,546,848,862,430,97,73,361,557,913,553,68,258,64,701,724,738,582,539,37,942,113,892,468,876,38,621,413,972,969,409,976,763,178,746,551,420,390,405,280,416,531,741,316,199,549,662,948,36,716,501,876,278,701,935,783,575,861,581,195,286,96,652,952,346,937,165,862,560,774,340,348,316,345,52,887,865,632,619,505,244,247,745,901,864,380,45,93,181,624,377,696,933,401,420,530,930,408,917,363,583,215,202,486,317,545,382,790,237,77,81,330,128,426,919,178,642,458,904,943,59,947,100,210,784,27,252,245,687,936,888,144,387,674,900,571,338,544,264,184,727,242,426,925,667,9,871,471,591,292,6,299,761,981,238,856,861,344,244,350,943,591,135,316,857,192,682,431,106,639,344,89,511,116,45,795,764,563,193,526,49,350,204,332,35,759,946,167,312,338,376,183,506,857,784,277,323,927,297,80,786,221,108,239,870,708,832,211,150,175,466,891,196,43,20,87,763,410,424,377,400,463,95,582,469,37,544,895,953,101,329,360,968,208,716,485,728,406,690,437,948,510,747,498,983,446,291,184,130,371,804,865,988,791,223,877,686,922,136,204,349,816,224,190,316,985,738,369,922,760,731,128,573,920,822,432,596,846,927,309,556,951,178,764,891,57,791,635,440,304,293,98,948,290,412,167,150,854,919,720,103,1000,337,510,875,516,314,548,384,553,726,683,713,353,710,245,713,728,113,742,641,532,46,472,945,100,855,151,510,986,392,400,204,299,238,877,528,834,556,18,180,31,734,421,333,974,177,337,84,586,473,341,12,234,163,928,288,421,16,143,877,319,397,194,771,87,67,870,19,820,865,956,101,0,525,252,507,717,448,101,201,917,909,673,586,919,27,522,163,791,646,467,849,235,668,495,8,735,551,568,121,127,902,85,685,627,418,54,193,683,878,913,186,676,567,968,725,516,911,891,320,657,917,925,453,536,865,137,719,796,942,988,938,975,396,72,294,633,569,652,252,878,733,997,453,774,444,462,229,720,27,657,198,880,103,750,32,565,325,862,383,513,722,673,518,6,843,400,826,420,977,776,252,286,952,134,844,939", + "711,487,136,751,610,802,448,537,866,849,421,357,258,525,287,931,229,208,898,489,693,806,415,791,557,252,489,888,764,896,777,994,539,177,719,547,303,739,152,85,502,12,312,692,919,838,193,313,952,641,19,410,487,563,733,267,924,765,253,402,957,190,594,664,694,507,992,960,164,587,445,462,169,966,254,124,499,793,653,576,564,380,627,988,314,735,522,748,567,841,417,256,852,908,252,232,556,191,248,526,276,955,119,548,768,700,985,152,312,160,145,359,279,177,427,685,767,656,532,322,827,890,793,993,669,509,440,120,978,799,748,725,600,924,566,152,160,940,521,589,965,584,386,610,857,987,759,807,245,743,587,290,856,497,29,15,69,220,416,684,139,415,229,87,224,829,284,242,575,474,565,279,904,594,132,139,416,911,433,932,32,489,139,327,606,19,975,867,821,831,352,40,679,829,456,60,219,622,777,357,352,840,667,761,680,100,53,808,764,405,816,436,827,264,228,129,333,800,950,641,833,906,650,619,245,791,878,3,480,963,218,805,44,955,144,743,80,227,875,990,406,159,86,254,723,813,226,711,264,667,354,719,307,968,243,997,999,739,524,673,986,279,403,629,210,806,939,197,332,399,151,691,382,286,856,926,496,935,459,59,684,659,791,270,183,201,590,36,597,951,748,71,344,91,201,1000,231,862,575,116,513,190,829,627,251,27,239,640,928,129,787,471,559,9,628,113,20,303,194,983,41,509,346,67,596,294,416,985,530,62,497,875,644,83,499,479,852,619,911,315,718,810,652,612,505,88,48,707,878,864,638,412,966,142,998,303,861,232,598,575,832,140,181,962,161,177,205,843,715,305,662,261,707,786,88,527,419,476,936,203,610,25,537,50,347,595,296,302,812,722,169,666,966,563,340,582,7,803,859,863,77,593,87,470,227,464,751,658,606,488,559,75,460,662,587,688,27,584,455,601,285,417,490,75,397,364,432,975,1,674,249,577,878,84,910,634,625,647,594,752,619,723,283,175,416,994,962,131,894,108,275,368,659,280,511,270,708,870,435,922,3,390,166,300,254,936,620,331,429,351,556,409,34,92,904,155,649,951,730,112,186,760,10,523,739,921,817,169,399,288,112,592,359,463,742,177,956,877,657,791,688,421,671,416,954,319,17,299,582,336,748,320,130,12,633,407,333,539,110,186,552,395,29,574,842,199,366,201,452,380,973,411,326,393,234,129,861,204,749,14,916,258,848,613,387,837,877,92,800,882,403,247,673,179,565,458,540,861,66,635,30,521,124,20,491,352,751,152,721,789,959,563,657,227,394,838,351,80,749,971,809,884,299,546,532,435,456,467,162,382,849,784,709,512,174,160,688,530,948,151,973,272,643,888,709,228,474,552,568,644,766,115,89,494,702,765,648,67,486,21,701,436,293,742,985,711,454,258,676,459,986,73,903,823,726,583,820,889,67,808,150,735,588,272,939,790,503,883,97,957,968,647,874,30,39,80,583,358,870,570,881,643,938,119,980,500,430,788,137,869,987,736,718,926,571,371,155,51,16,805,944,279,251,513,564,218,957,789,30,616,162,927,602,578,877,665,154,165,623,706,838,316,186,970,790,159,353,886,905,808,2,560,942,887,256,465,692,352,149,344,76,850,623,306,701,332,866,528,578,60,393,954,447,951,400,674,944,475,371,971,34,710,643,304,805,330,826,520,992,135,649,362,690,405,915,539,732,262,892,315,73,858,319,740,286,984,657,170,190,839,369,365,72,202,67,488,335,387,474,468,987,836,528,602,66,1000,221,259,322,9,941,912,637,291,711,304,33,832,156,297,43,744,522,169,760,805,317,403,380,525,536,662,939,158,236,345,844,484,486,594,550,942,19,790,679,397,292,172,282,680,143,524,782,507,786,981,602,467,465,901,525,651,872,11,62,860,929,538,859,867,707,689,442,902,865,18,162,176,351,229,132,234,976,773,362,590,141,440,214,158,639,375,179,818,333,800,550,258,116,917,408,550,396,477,313,413,900,936,724,479,591,905,223,90,548,525,0,168,166,146,274,757,915,792,406,48,897,584,770,4,926,689,299,249,517,998,262,275,378,470,843,602,426,929,525,58,839,29,479,294,316,146,167,816,552,719,767,606,608,43,215,976,154,682,494,809,847,271,381,555,992,8,164,385,570,889,984,497,865,418,976,405,54,849,112,64,929,301,416,587,944,69,420,59,739,979,615,781,423,959,577,181,777,443,762,436,316,704,1,318,506,600,62,267,76,225,983,806,510,506", + "17,984,668,675,115,549,144,182,638,29,430,428,15,991,371,769,59,577,123,734,846,901,498,541,966,319,768,211,445,714,21,638,268,257,476,597,112,980,711,998,208,243,289,400,937,249,714,494,909,312,653,173,532,6,203,97,504,470,307,420,392,38,122,446,783,877,336,642,367,330,574,45,570,744,539,146,651,615,347,932,947,226,656,993,302,433,582,812,199,519,410,655,406,703,459,759,172,200,261,20,662,419,210,285,221,285,586,971,798,146,80,670,618,577,956,806,46,855,631,845,142,304,747,63,428,634,167,925,829,720,814,264,167,580,726,163,648,116,721,823,402,568,396,574,566,681,440,780,385,325,903,251,546,86,389,710,360,168,899,101,694,624,422,445,859,143,836,421,337,67,925,658,124,974,52,584,116,296,957,721,181,774,828,46,189,903,382,523,756,361,547,931,64,456,562,361,716,469,864,727,838,784,135,143,343,401,362,518,450,340,772,935,224,205,776,620,380,831,765,930,647,463,328,67,908,930,851,432,995,202,629,955,39,339,313,834,83,53,191,69,642,194,966,571,603,359,226,572,908,823,243,16,779,680,550,827,641,242,946,383,337,603,588,670,144,473,154,921,762,347,177,183,897,44,261,178,653,437,248,60,957,911,595,247,731,546,696,585,992,900,225,109,432,449,483,460,523,204,166,229,406,337,668,633,524,778,115,92,137,708,316,5,988,571,497,75,560,515,674,755,971,415,378,903,414,436,302,890,17,738,38,643,150,781,302,71,649,268,158,700,122,902,929,510,125,298,595,234,619,929,95,890,848,746,912,35,522,773,372,107,602,471,665,476,119,157,102,19,120,714,834,595,685,670,149,238,223,639,316,439,389,92,727,657,544,555,48,17,443,17,376,530,642,877,553,348,942,657,702,818,978,916,444,242,27,883,615,275,475,515,470,595,561,163,579,796,486,116,311,342,628,322,858,313,405,61,674,519,864,469,977,773,224,686,765,869,731,447,147,502,980,331,701,127,344,173,243,917,4,829,610,189,432,343,77,157,251,720,634,106,253,438,665,499,634,183,899,890,90,185,186,634,241,791,898,174,883,412,21,168,77,346,941,188,535,271,861,368,980,406,189,855,594,7,296,743,910,74,908,799,54,229,931,394,376,31,444,577,297,823,596,976,346,232,896,834,255,5,844,29,359,19,450,297,517,684,24,229,129,568,234,852,142,271,169,627,788,990,400,913,275,698,801,828,541,354,544,499,188,224,911,969,736,483,846,926,902,920,533,341,953,972,777,159,592,72,381,192,950,134,806,697,708,399,929,974,60,275,431,323,34,369,874,245,323,656,975,616,806,910,533,543,853,740,183,727,313,906,889,470,526,210,919,938,248,121,310,230,263,63,146,203,854,236,154,446,85,220,205,580,505,951,139,257,573,579,345,364,281,513,331,665,879,144,149,627,878,510,631,739,181,799,145,252,354,696,379,193,553,315,866,827,838,463,301,590,769,490,930,419,272,306,293,842,396,844,140,601,999,677,221,68,64,152,973,286,815,732,998,975,320,765,478,822,116,6,560,668,107,551,293,463,899,67,454,423,782,520,920,402,607,15,193,346,57,142,808,691,499,980,478,120,301,700,504,473,451,745,752,410,311,949,478,610,420,173,603,920,604,419,670,109,293,901,30,80,841,559,126,140,425,945,5,945,324,848,687,421,677,876,711,30,556,3,361,275,449,978,427,836,840,43,166,598,396,363,736,307,567,931,965,585,801,589,426,765,578,228,995,721,410,399,216,435,852,578,847,613,197,658,727,755,70,579,730,523,426,977,200,407,318,149,455,379,301,726,613,188,532,33,206,466,87,872,371,184,752,735,850,321,750,545,201,560,652,358,319,370,522,829,975,68,132,536,956,647,801,844,501,146,349,33,176,684,319,192,917,512,955,850,15,148,177,863,95,661,55,913,803,775,921,384,468,408,1000,727,910,20,857,473,342,533,800,231,369,141,107,31,163,251,233,796,827,489,434,601,767,323,229,269,190,173,852,353,114,252,168,0,249,4,826,144,428,435,309,234,100,647,730,950,297,581,80,367,55,126,221,369,125,896,98,334,501,690,847,990,936,953,253,408,657,68,669,267,182,710,794,562,199,24,582,328,502,980,477,137,637,681,708,160,982,577,997,107,980,773,494,68,360,649,769,276,948,159,610,880,739,859,915,891,770,35,501,589,531,994,311,719,304,585,291,330,287,833,857,256,129,740,532,361,608,809,475,386,653,838,123,505,231,997", + "190,96,888,855,941,15,272,852,464,632,856,883,791,862,740,886,747,807,795,858,196,302,81,382,242,710,723,775,783,884,874,853,557,503,769,529,897,757,498,581,101,884,343,613,474,328,409,937,793,404,33,700,884,618,846,843,862,427,288,614,269,956,884,15,382,442,878,929,772,414,492,814,448,237,132,357,201,452,954,45,190,754,5,449,51,283,667,270,120,338,59,400,486,447,683,720,179,385,549,221,668,300,4,435,148,17,603,948,101,478,302,732,299,662,597,607,342,992,329,446,667,182,252,39,141,27,866,720,671,279,684,123,769,582,887,487,118,884,142,346,345,380,906,737,648,752,228,233,158,443,768,647,388,279,718,454,931,541,194,570,433,944,380,636,507,390,38,820,864,159,867,335,994,354,289,221,30,357,55,26,681,855,851,193,97,615,865,864,473,801,741,538,583,240,890,820,302,465,565,542,724,664,541,507,417,308,4,226,648,954,340,447,572,490,692,173,437,934,82,538,816,89,50,452,777,464,38,194,946,616,923,550,795,275,261,253,1,534,998,410,250,646,221,680,87,714,332,246,365,167,618,521,160,791,559,70,406,362,681,669,867,576,758,633,645,475,464,3,571,530,867,605,312,194,809,414,995,313,225,357,97,778,193,722,598,536,263,196,205,414,278,976,694,900,205,576,181,6,456,377,811,95,786,431,70,344,547,70,264,99,654,462,802,925,902,790,586,315,891,563,119,20,343,16,758,56,491,957,758,865,116,746,653,158,274,583,229,476,211,439,224,801,386,443,350,217,284,400,535,20,424,777,500,959,625,172,912,68,677,842,728,58,956,828,207,824,11,898,192,873,237,276,890,276,891,576,450,673,107,647,640,785,358,571,30,878,247,529,650,391,739,548,157,888,578,394,902,148,789,468,169,449,952,484,471,210,559,864,421,421,623,898,526,368,359,562,637,146,676,690,639,811,540,80,802,754,69,638,696,462,419,771,744,435,905,792,818,164,232,94,585,909,384,368,889,415,538,305,89,717,578,890,593,427,463,726,249,800,237,752,443,382,789,471,531,158,132,972,887,698,116,611,43,331,97,705,528,833,560,750,405,61,348,887,246,28,703,752,835,39,304,721,937,658,289,29,412,696,490,808,855,803,8,188,587,243,856,249,785,393,296,389,760,380,858,50,380,918,894,350,688,979,82,405,966,249,250,523,370,612,107,708,283,640,408,523,480,55,781,515,727,431,258,909,268,347,944,849,332,856,810,826,449,377,328,766,344,834,765,167,780,786,975,973,362,238,75,807,213,267,183,233,284,115,969,834,365,696,534,781,127,272,105,939,185,23,460,863,220,480,664,719,393,631,39,109,618,811,153,790,455,37,34,689,49,852,382,581,848,265,773,125,742,141,28,392,23,485,745,930,75,200,931,142,999,398,468,297,443,906,190,201,813,172,821,608,832,208,858,427,135,367,367,260,152,676,74,304,774,993,190,463,291,852,272,513,244,201,835,564,805,102,302,381,778,260,605,347,869,356,742,694,312,167,861,772,722,559,429,376,638,25,853,44,135,818,958,913,304,301,210,659,993,130,735,346,582,615,207,896,489,385,51,767,325,688,286,13,958,391,943,158,79,870,724,702,74,346,340,681,311,762,176,283,257,768,576,912,229,801,931,176,35,287,764,64,689,572,686,463,850,407,433,504,400,951,354,503,538,569,330,113,220,633,104,874,647,185,88,460,527,530,996,180,805,952,965,16,210,949,3,363,856,527,616,362,785,523,728,838,469,638,976,273,838,270,158,239,464,298,114,477,125,979,78,240,253,244,143,586,710,617,73,395,867,177,289,924,427,599,553,913,24,660,213,939,350,807,983,191,611,957,981,730,503,28,54,50,946,814,137,916,484,592,884,133,97,371,403,645,567,287,253,351,316,384,780,106,25,60,185,915,428,868,2,895,605,537,759,463,78,887,572,968,19,943,635,531,903,129,796,906,361,498,709,102,142,657,73,184,411,323,5,692,201,176,445,69,229,897,281,501,941,951,485,507,166,249,0,95,420,149,772,403,930,420,872,976,256,78,200,813,675,893,245,619,131,595,335,875,340,824,621,628,377,10,992,243,835,223,672,272,981,594,793,92,446,714,852,633,258,262,569,344,484,826,629,747,697,351,662,629,166,485,452,815,652,433,501,799,552,795,34,339,268,533,147,802,249,130,334,203,373,679,7,459,141,321,487,934,310,452,716,630,997,556,91,111,43,166,683,923,528,523,907,276,261,79,458,201", + "952,757,467,933,795,535,144,159,297,823,663,66,33,112,904,647,729,902,531,653,534,326,660,775,14,151,55,147,143,837,829,829,256,710,513,646,420,543,416,821,88,681,840,337,191,600,756,703,763,407,473,133,847,773,261,667,326,339,986,621,73,208,298,585,744,162,784,713,946,454,144,604,711,132,118,518,790,310,559,326,97,358,992,888,452,879,683,838,599,557,641,573,874,566,238,794,365,163,788,908,375,362,285,749,646,523,508,453,473,505,586,258,869,467,718,448,56,603,713,911,864,133,483,956,699,803,596,684,323,478,150,509,943,702,84,680,560,343,654,853,473,580,947,957,618,140,205,504,245,638,247,504,107,109,458,879,540,712,928,314,692,65,575,845,456,108,586,610,445,449,527,945,596,282,294,866,203,893,131,100,125,88,22,402,460,855,361,562,521,260,86,339,394,784,564,498,690,758,152,248,77,246,178,929,24,982,459,686,794,812,329,681,716,437,432,605,640,909,862,990,761,430,938,308,210,991,149,975,431,522,594,626,826,815,82,595,661,754,601,544,333,922,726,442,286,184,343,188,699,333,228,688,466,380,915,365,228,982,603,145,774,40,672,259,370,153,821,87,255,730,450,838,811,769,940,728,724,158,519,297,672,99,848,543,870,153,923,45,182,210,999,875,688,146,8,804,524,39,570,145,936,330,962,151,545,949,851,775,290,857,735,34,330,597,635,487,738,847,765,584,42,651,883,299,747,238,886,179,889,494,635,951,685,572,704,661,476,2,6,221,410,775,101,72,604,892,740,183,794,42,32,189,519,640,705,254,448,990,527,738,502,719,324,142,202,235,159,106,133,156,57,111,170,497,357,882,822,270,480,925,237,37,47,433,115,458,146,732,503,471,54,427,747,10,279,856,840,478,566,17,82,325,77,98,272,173,513,688,34,800,563,246,758,174,522,399,800,846,520,637,265,935,105,172,292,714,519,292,433,958,387,231,106,498,816,752,512,349,363,303,831,875,271,744,392,685,372,162,291,285,553,320,821,627,328,350,162,514,929,676,129,104,799,161,645,246,745,190,341,122,628,572,587,188,457,790,680,565,548,417,411,381,542,809,949,800,613,600,626,93,49,12,572,837,524,433,72,435,998,362,715,46,975,365,365,727,300,651,494,292,659,787,548,846,110,835,795,543,129,884,314,859,718,463,710,183,387,8,372,206,76,23,808,953,716,721,104,734,724,579,921,79,157,377,179,72,544,64,843,245,960,974,488,522,749,945,937,879,969,894,868,984,465,76,622,949,389,185,476,149,29,38,665,503,950,692,67,521,579,632,370,170,533,886,319,305,202,349,4,180,312,760,761,874,144,501,252,527,742,67,813,161,657,670,987,435,731,530,34,314,744,534,655,110,232,666,666,238,628,81,796,619,238,840,390,109,896,913,273,553,447,538,610,827,371,876,431,153,333,525,800,359,352,372,907,279,979,669,238,696,841,912,724,57,860,866,443,224,19,408,340,471,798,734,586,560,669,542,283,659,401,722,20,65,392,198,500,379,90,870,838,182,477,242,309,105,533,323,740,661,795,309,208,809,376,450,930,901,23,311,519,634,884,799,296,759,246,639,482,763,93,783,29,55,454,855,217,526,312,234,652,798,403,362,992,918,210,225,556,339,29,78,899,971,252,670,777,586,869,421,354,822,196,755,180,333,48,238,569,531,103,746,791,570,55,253,404,991,634,869,849,872,311,463,263,73,845,155,156,499,215,734,682,660,771,166,734,202,459,757,233,368,929,402,552,25,202,229,556,850,429,723,64,356,466,432,684,760,176,419,721,511,626,757,618,275,689,717,65,2,60,942,267,441,951,103,76,170,477,543,629,394,318,508,116,81,133,49,613,531,454,529,663,904,703,506,642,691,761,241,639,68,69,989,190,925,966,247,15,243,844,900,107,871,274,821,769,149,525,856,830,488,759,621,429,432,731,209,170,54,925,655,719,703,837,123,777,211,792,265,76,704,349,552,45,956,663,774,398,696,388,691,905,33,773,717,146,4,95,0,868,155,573,250,220,658,776,127,589,841,405,191,477,356,175,23,459,643,627,787,573,166,925,348,777,936,590,963,198,875,619,875,531,258,180,715,581,831,598,288,921,17,245,453,443,700,17,926,640,966,826,358,822,16,566,372,332,33,285,813,413,410,678,237,957,972,171,448,838,638,13,339,837,557,377,477,570,322,931,811,961,198,191,127,638,57,745,454,947,969,610,232,608,440,788,822,682,684,616,605", + "370,77,799,133,565,981,895,225,72,196,139,282,461,577,100,196,716,742,255,921,839,922,719,504,378,140,776,437,972,215,171,803,870,435,854,370,109,811,328,440,619,786,986,524,156,859,726,44,387,74,987,990,659,825,691,498,528,412,133,845,986,427,425,252,571,967,481,942,106,989,908,26,93,539,339,523,381,975,84,826,453,955,453,139,766,483,25,208,36,748,842,986,956,310,802,963,30,236,786,282,625,695,920,809,905,619,237,107,111,605,255,529,247,581,416,892,833,755,941,683,899,216,458,767,682,988,279,486,909,58,394,656,827,813,461,318,174,85,754,945,934,654,189,331,955,80,507,367,791,917,610,490,199,384,327,748,37,432,735,649,365,97,363,997,408,994,143,731,956,810,968,421,369,793,883,806,969,927,334,173,975,673,140,493,242,201,237,14,697,365,314,395,341,730,342,600,854,813,414,792,785,44,798,454,436,685,956,969,20,238,335,759,74,135,484,392,800,775,863,764,911,317,414,367,980,926,959,501,713,462,321,332,912,946,363,113,587,408,454,271,600,343,228,994,112,207,946,183,222,858,542,515,88,300,541,82,61,946,833,235,50,31,663,547,595,431,218,852,656,550,22,969,198,480,847,298,454,86,107,715,699,505,89,403,582,645,770,310,797,415,317,198,787,319,574,123,574,106,785,519,703,8,937,506,626,674,34,388,416,776,350,805,895,884,814,380,557,599,342,166,327,306,122,940,754,16,74,372,180,268,766,723,116,66,147,244,355,996,242,812,183,677,871,112,879,481,579,105,954,118,518,15,149,759,679,458,182,770,231,303,915,632,843,973,256,623,999,524,959,670,473,346,943,289,203,559,880,113,443,150,729,20,49,760,88,528,847,362,984,990,397,627,329,176,624,21,225,454,775,810,426,24,687,526,978,988,454,312,681,727,963,399,488,119,342,827,587,165,694,958,28,48,63,523,246,948,37,59,895,817,19,696,290,510,210,598,233,958,59,485,720,397,595,93,834,242,713,827,246,724,127,157,306,569,283,672,205,902,663,184,988,553,610,77,50,886,761,776,103,364,780,743,735,64,345,699,774,831,604,286,103,847,122,460,192,975,352,542,982,304,515,815,373,937,101,439,369,880,103,287,277,336,371,447,754,260,110,654,892,547,651,569,915,112,741,334,547,81,955,437,29,316,683,407,981,372,95,325,981,364,648,455,34,293,193,654,876,670,139,384,835,424,395,13,278,448,449,614,720,834,593,306,655,130,791,733,796,669,206,49,3,740,954,983,604,400,670,691,227,633,601,355,438,81,235,117,524,454,704,37,310,172,315,246,556,829,954,67,316,872,585,694,632,219,350,231,653,470,965,826,867,419,534,875,545,413,854,88,500,816,342,166,322,481,276,468,78,949,724,471,91,55,512,587,691,843,680,965,323,699,255,203,274,437,137,576,484,515,899,178,285,674,149,657,662,471,7,433,334,556,404,615,494,993,541,224,537,266,614,825,113,638,890,736,795,145,396,747,537,475,565,609,830,888,975,280,902,48,542,239,691,679,263,585,447,571,219,424,9,715,834,431,150,138,243,644,165,507,162,976,412,486,115,651,929,910,665,92,125,670,262,10,893,90,300,898,958,551,320,162,654,541,439,767,417,211,292,807,350,620,639,204,54,389,505,687,969,422,813,926,311,905,155,652,188,333,497,535,971,670,159,483,555,366,772,974,479,549,478,223,821,866,696,782,123,755,278,387,345,810,879,410,485,302,776,151,741,970,147,277,254,943,30,249,323,662,113,220,426,769,857,819,846,448,996,292,588,37,132,212,917,777,329,180,562,939,79,44,45,562,941,565,960,718,841,580,468,844,666,375,956,372,726,664,861,314,338,503,227,259,197,530,526,43,863,691,79,92,585,708,755,731,3,862,759,326,504,135,5,516,918,689,818,370,227,322,511,699,789,946,615,605,659,8,439,38,900,841,990,534,75,793,731,933,556,671,110,360,858,128,121,191,535,405,124,56,481,272,394,121,551,573,867,365,55,448,274,826,420,868,0,418,169,935,533,616,169,985,798,417,693,836,45,350,438,444,83,850,864,327,89,128,635,736,270,820,232,641,805,491,475,676,473,862,86,74,700,325,412,485,990,633,627,894,296,177,568,122,681,872,653,994,59,51,611,238,927,413,906,564,508,370,956,364,487,559,899,958,488,617,475,74,796,195,812,515,834,135,102,708,926,746,706,373,301,63,954,692,336,548,183,513,394,294,31,34,242,39,91,265", + "464,843,429,489,101,21,336,774,375,477,334,832,487,958,25,838,825,823,235,868,524,371,154,787,135,522,767,691,428,975,609,482,340,24,331,432,217,348,491,952,557,649,399,858,344,980,980,524,463,951,357,724,69,252,825,33,985,235,830,237,98,745,312,172,527,111,603,827,464,854,690,570,209,169,778,637,229,822,626,340,784,66,133,325,344,125,808,662,461,989,378,457,729,577,296,698,328,368,136,893,298,312,643,220,699,666,379,70,607,151,252,519,814,558,161,662,238,738,12,998,639,158,468,585,711,369,683,691,99,960,994,495,862,98,135,500,926,497,22,961,944,96,831,842,790,922,948,49,779,73,890,494,26,179,478,25,585,316,134,198,858,937,212,787,172,368,185,741,728,178,301,346,302,959,198,596,179,760,67,306,823,477,852,981,335,534,931,454,601,601,973,367,98,935,511,608,973,760,418,922,253,720,477,480,206,798,941,666,871,478,3,378,612,856,116,396,565,638,387,209,232,455,960,35,528,846,8,721,722,444,146,976,583,366,401,16,453,907,339,488,457,629,338,362,945,157,172,67,239,990,528,993,964,609,956,941,666,728,521,80,599,93,99,595,468,716,494,472,214,98,969,985,729,535,672,680,918,133,361,895,594,486,601,599,518,711,399,325,707,913,601,773,129,343,950,990,192,894,943,846,196,888,947,833,434,204,415,336,688,647,910,266,826,511,972,487,678,231,691,249,4,835,462,429,461,525,942,792,467,39,150,276,282,469,314,462,381,112,476,544,297,808,952,367,248,213,36,894,690,549,509,642,868,895,117,63,452,873,178,437,418,450,794,183,731,387,291,340,748,358,830,157,367,157,974,853,546,303,299,707,433,823,763,627,266,376,91,38,368,247,586,123,387,123,733,485,872,328,236,206,638,889,104,82,432,550,674,225,818,976,226,458,307,133,592,661,510,85,26,462,210,793,683,942,575,971,833,651,755,848,481,180,325,314,448,103,171,277,374,253,633,243,31,397,114,682,218,185,410,234,766,380,647,189,511,722,853,107,175,181,78,562,948,983,822,577,560,858,585,449,401,31,594,572,165,737,672,754,431,872,649,963,707,29,524,188,60,181,18,564,268,693,915,439,242,27,459,327,463,706,29,657,539,168,823,55,892,141,816,356,430,700,871,511,124,292,634,723,709,131,959,221,226,316,403,304,141,928,575,76,656,756,179,571,713,593,593,920,366,311,579,377,633,840,984,124,848,354,949,571,644,913,165,91,297,390,451,272,460,298,229,986,323,824,395,714,99,235,828,184,610,532,293,748,125,247,237,879,869,279,36,713,580,281,388,200,890,797,620,485,205,702,963,299,505,181,290,774,535,382,530,822,694,81,10,80,725,429,16,86,896,545,505,559,818,518,493,631,577,451,90,738,208,890,437,198,245,782,778,271,277,555,99,50,604,83,287,337,752,735,921,49,955,957,668,10,172,366,67,73,769,897,789,780,957,109,359,572,677,413,475,461,816,749,528,711,533,877,149,77,51,121,940,527,94,872,898,639,56,636,870,593,488,27,816,221,640,582,527,420,169,543,882,390,432,894,721,120,433,179,834,298,125,903,614,737,687,771,690,26,176,123,352,488,994,524,215,508,24,538,136,610,788,116,318,845,566,323,604,680,372,740,944,443,694,997,536,240,259,455,480,743,717,969,567,439,609,361,817,69,162,301,113,725,793,928,527,937,374,233,827,369,829,161,857,853,362,491,761,667,646,809,849,401,90,492,35,698,556,38,729,907,442,380,506,414,171,524,329,21,745,268,522,65,510,204,851,335,221,869,789,745,114,77,559,486,246,261,467,255,843,549,863,507,377,701,463,302,283,409,356,184,894,316,196,425,772,24,291,315,198,637,684,117,193,466,934,454,380,321,255,38,887,102,111,822,39,905,239,78,397,569,295,797,902,767,192,397,824,8,863,615,10,70,224,290,684,609,340,781,749,649,808,773,136,546,979,870,8,337,407,321,239,377,394,209,295,600,755,301,877,423,909,208,464,101,757,144,149,155,418,0,366,546,781,537,563,98,505,537,286,86,444,933,896,55,590,517,302,621,280,410,972,800,799,76,114,271,651,922,771,722,936,724,450,216,938,598,249,583,562,972,513,357,777,164,841,297,38,275,801,13,578,603,857,981,469,585,547,951,504,557,483,326,427,903,881,649,426,125,476,482,689,963,736,149,526,874,521,465,517,946,942,641,318,974,622,225,385,765,625,177,665,78,409,79,918,167,496,463", + "291,367,25,195,837,921,630,929,203,122,548,563,94,338,77,211,237,25,634,796,781,177,586,367,767,601,928,633,120,848,331,86,461,394,41,743,404,389,275,885,87,804,161,378,82,975,331,125,940,898,820,575,12,871,439,63,687,244,932,148,49,984,34,665,954,241,54,859,145,788,820,599,665,704,686,567,231,384,152,780,704,872,754,179,633,951,804,855,341,240,977,534,570,568,558,845,264,241,194,412,500,943,372,744,147,516,253,456,827,530,129,98,242,524,500,86,653,958,50,547,809,41,349,593,488,672,281,627,458,142,268,637,923,725,413,397,919,398,690,909,885,983,898,596,938,117,277,302,281,414,33,180,585,632,828,819,943,640,416,815,492,644,979,304,546,83,874,826,245,880,213,400,56,816,179,543,621,846,922,571,828,455,402,662,397,148,594,267,847,590,57,421,681,326,560,595,514,588,557,865,10,707,346,834,330,398,826,967,209,200,113,681,931,270,277,808,141,247,152,894,918,992,122,205,615,549,438,341,700,396,130,765,830,687,453,557,718,90,372,509,372,469,679,785,511,805,832,312,224,389,210,436,550,389,341,736,58,806,342,494,753,729,497,940,990,328,614,654,555,743,807,488,799,70,167,822,649,889,362,666,740,146,100,384,288,493,468,725,828,297,297,707,77,361,81,569,144,819,22,196,684,794,721,673,519,192,105,113,308,555,289,576,278,462,816,344,542,876,590,760,597,537,971,825,780,69,429,698,813,392,871,207,606,504,474,99,799,686,685,314,858,129,370,238,677,790,980,221,513,180,966,366,892,421,870,921,364,8,236,189,627,264,62,826,339,607,192,645,454,255,9,321,816,719,951,296,498,42,104,391,699,656,846,530,851,824,773,102,845,899,310,447,606,791,997,316,894,333,320,521,244,64,267,347,959,327,991,639,445,602,838,191,606,692,425,657,473,533,688,916,250,535,464,269,329,130,666,100,989,121,823,573,189,532,367,894,154,53,347,8,454,628,199,670,616,864,566,280,69,36,382,679,104,1000,920,670,351,761,471,613,714,798,187,693,916,63,23,211,380,416,797,330,900,485,148,143,832,738,390,839,499,639,564,248,917,323,883,394,918,927,237,822,134,257,523,211,335,804,358,388,202,313,608,347,555,821,88,734,893,721,761,763,399,781,678,66,296,803,92,272,509,585,614,760,628,742,532,545,783,744,343,477,490,821,595,543,549,986,183,278,38,959,314,797,583,321,356,500,580,164,154,129,204,318,642,395,904,175,118,711,773,181,879,957,797,180,94,294,343,586,164,866,81,866,116,373,257,129,788,933,293,296,26,962,943,141,793,46,924,633,980,623,9,56,549,526,588,70,1000,571,993,470,856,436,700,489,445,304,683,384,93,223,828,286,71,778,317,375,875,811,114,862,654,11,64,165,926,698,692,944,549,714,729,917,260,920,655,728,424,500,235,765,973,556,96,239,209,198,736,980,23,449,114,763,599,288,82,459,200,142,865,739,949,969,23,38,692,450,542,190,477,28,633,12,68,140,521,182,924,702,153,845,181,997,285,192,19,279,885,183,338,904,219,695,685,342,329,535,223,279,726,787,561,807,747,65,713,628,276,79,545,952,811,916,260,965,229,103,818,89,606,418,722,347,18,586,944,844,190,615,815,588,556,35,965,396,702,938,851,828,82,667,566,342,37,464,916,52,4,813,897,391,291,164,991,5,929,675,901,569,319,910,559,582,236,915,976,305,369,893,567,6,218,576,798,382,427,774,754,30,759,200,275,201,425,15,185,453,587,980,699,554,95,313,706,508,335,311,234,220,78,710,276,252,183,269,834,751,805,968,23,149,756,659,159,333,871,993,356,743,598,45,71,88,230,574,32,257,12,933,443,929,864,789,23,67,23,309,363,473,206,745,342,916,295,666,28,935,980,552,40,378,606,432,301,709,874,241,44,869,728,399,774,970,989,713,425,642,500,391,181,129,109,566,876,572,817,777,753,194,853,393,728,61,498,474,744,195,420,651,805,993,773,719,516,201,915,428,772,573,169,366,0,616,890,273,395,383,911,367,913,430,523,57,503,358,687,679,901,904,675,538,900,451,977,294,564,760,300,25,388,923,899,297,942,377,874,230,619,274,822,743,972,543,47,80,130,856,750,234,738,332,668,733,336,205,252,8,488,929,358,884,969,975,698,478,752,156,234,598,197,280,686,696,767,64,384,404,586,516,992,257,428,187,906,838,48,384,184,551,289,901,912,145,652,872,509,560,976,499", + "918,32,817,268,655,188,716,482,869,35,278,204,376,19,458,867,555,826,454,469,282,510,967,950,483,241,609,49,599,159,828,523,947,935,401,805,639,291,719,110,413,565,615,27,625,975,4,828,388,857,205,189,995,809,599,138,138,180,640,943,843,899,819,728,113,324,878,631,209,509,820,566,314,720,441,644,303,525,591,106,713,628,806,510,454,899,146,443,877,129,19,943,788,248,314,163,388,168,748,779,886,168,703,268,337,569,948,464,395,380,561,894,637,63,664,949,338,994,680,982,129,430,385,404,499,350,80,239,896,942,530,626,786,213,451,627,245,850,52,116,778,336,368,900,557,34,304,521,52,975,261,328,632,421,942,379,672,943,150,722,136,889,717,68,684,177,569,965,744,99,249,345,180,894,659,909,763,298,702,452,49,231,119,579,83,310,351,640,857,133,552,782,678,506,174,873,814,381,38,256,571,490,69,852,654,565,417,129,327,55,822,168,977,671,853,702,246,994,957,802,225,97,278,232,284,670,705,490,285,854,795,803,837,675,543,10,821,142,60,693,98,264,982,476,579,656,441,354,651,457,465,235,341,751,178,916,982,841,766,120,706,844,64,743,334,979,747,254,955,852,395,238,70,900,721,601,121,362,443,999,629,161,76,950,993,964,607,954,830,334,407,845,791,529,954,211,486,746,821,490,965,202,78,754,632,953,844,364,939,914,210,441,557,718,178,65,542,828,260,260,200,737,308,992,597,237,38,280,691,248,145,482,325,788,522,745,63,576,628,133,733,498,871,956,987,847,580,922,416,562,412,370,901,611,427,277,59,81,338,719,972,591,128,446,869,499,739,364,595,165,552,560,44,689,389,745,913,431,851,257,617,676,684,101,156,636,465,588,144,627,746,356,445,772,668,343,801,84,5,379,884,625,153,101,590,819,781,524,732,51,514,963,280,73,104,324,808,415,957,476,777,463,296,423,821,431,340,532,735,741,745,417,607,784,845,568,981,952,952,855,582,81,990,740,373,184,533,790,422,919,303,38,614,597,235,377,713,690,587,929,579,376,222,332,241,638,878,994,519,664,233,313,592,396,625,849,13,661,300,134,850,767,751,170,977,557,899,608,362,71,520,298,389,409,572,135,601,179,178,33,150,923,846,434,59,148,515,851,845,591,843,1000,12,982,161,742,94,894,578,568,993,521,311,999,236,255,659,522,101,361,102,402,614,975,806,184,170,506,564,222,577,90,874,371,249,975,332,936,770,659,427,673,379,249,950,430,550,336,970,363,390,778,411,289,72,745,368,267,206,400,250,957,448,395,877,357,399,806,494,865,353,179,843,7,701,540,470,343,80,276,628,733,417,494,28,696,325,528,822,359,517,171,630,694,516,544,172,937,251,614,964,317,864,718,589,218,676,220,99,532,125,627,400,255,516,26,300,821,51,754,107,607,310,830,454,788,909,781,1,123,923,348,974,369,909,555,570,6,499,32,350,508,517,169,900,525,699,855,239,936,513,42,161,154,809,650,602,240,599,619,482,782,633,401,521,312,913,584,560,143,65,868,502,654,470,4,297,331,934,260,556,315,193,558,768,286,405,218,299,519,85,759,389,692,983,925,750,977,648,665,677,397,654,456,508,718,457,912,152,940,595,875,850,61,743,929,809,298,42,785,984,181,882,688,614,672,694,655,800,878,549,805,26,575,485,865,340,819,156,625,39,740,630,422,836,312,387,941,734,902,585,330,648,787,519,117,349,154,295,176,477,806,88,624,447,737,249,863,12,523,708,784,606,90,93,876,909,221,522,126,241,312,399,209,54,722,692,891,627,506,774,638,273,495,842,953,27,967,349,760,675,624,393,882,401,799,318,905,342,418,467,204,723,6,407,388,212,195,538,280,651,152,378,375,78,54,533,324,761,611,643,379,335,966,311,347,786,457,193,636,103,329,21,833,64,423,440,386,972,807,746,305,500,230,14,468,36,308,898,857,419,767,372,156,604,765,835,868,729,767,995,358,696,618,768,724,693,524,799,429,913,959,585,265,685,917,792,435,403,250,935,546,616,0,954,20,404,546,907,71,709,532,95,717,986,622,534,806,601,491,520,980,788,625,156,804,264,129,183,371,221,920,749,221,671,70,254,465,757,571,391,739,223,278,171,111,262,574,656,552,821,963,971,655,142,661,943,538,380,284,343,350,435,694,677,319,256,291,397,163,515,104,56,741,20,490,386,517,910,528,40,295,861,19,906,674,751,4,743,317,956,984,124,785,284,186,560,680,208,862", + "454,840,322,776,613,345,119,146,838,504,401,155,402,132,31,370,873,920,374,602,632,718,120,128,612,74,543,407,789,298,325,26,165,321,98,973,306,730,281,188,52,470,795,765,489,686,429,78,590,831,431,74,371,451,691,831,708,270,916,207,84,138,785,64,409,922,77,942,686,904,278,240,868,20,716,842,445,173,940,213,188,688,396,302,819,60,321,545,834,781,401,734,392,415,869,665,694,400,185,187,608,487,359,131,564,54,675,497,665,696,52,591,686,985,412,29,264,219,639,99,714,397,61,285,246,358,14,899,572,59,980,154,628,789,46,140,750,795,278,234,668,711,28,433,442,402,364,130,202,558,388,280,772,194,502,22,144,155,563,513,111,850,925,928,622,848,424,898,495,84,768,939,655,23,951,541,272,973,409,981,337,854,776,556,413,426,7,561,416,417,245,439,879,683,494,806,700,7,217,34,980,284,529,283,235,733,269,732,585,111,152,762,658,839,585,906,428,914,78,660,537,913,918,99,775,39,286,607,559,850,120,801,338,837,122,289,779,441,525,314,884,219,947,860,134,600,177,322,186,589,194,623,606,147,321,464,221,67,424,259,540,805,91,575,606,754,822,556,66,655,150,615,37,191,926,661,580,965,800,13,377,153,993,625,492,13,896,736,678,867,884,753,975,148,75,894,715,201,408,950,425,193,431,139,824,495,368,663,89,952,987,766,150,413,158,224,996,606,47,888,398,674,2,516,961,905,331,365,412,238,115,530,212,252,513,189,697,452,922,716,49,847,243,148,19,54,556,806,725,687,980,673,359,949,191,65,522,653,905,806,320,153,264,531,581,522,340,422,607,686,257,706,76,440,305,995,438,605,995,260,515,180,896,15,232,811,664,322,822,453,323,372,371,684,631,616,414,197,470,635,193,465,765,118,330,726,395,689,785,454,510,706,227,930,116,524,906,335,389,585,859,790,430,663,516,177,737,418,899,780,815,641,910,932,297,403,251,954,214,576,57,758,938,502,911,487,265,836,868,606,266,527,570,359,580,590,633,20,739,962,11,214,185,999,441,712,164,659,900,56,536,538,856,992,485,308,713,807,210,952,333,846,347,765,718,12,6,181,589,657,135,636,977,648,257,907,913,165,638,539,244,127,206,265,946,721,268,16,449,391,898,842,551,560,248,467,44,495,919,812,279,742,239,697,205,209,281,554,921,528,530,970,834,326,274,17,958,259,355,908,945,469,803,715,558,106,178,329,993,119,672,693,598,130,169,52,105,499,21,968,790,997,480,941,161,429,667,888,595,515,671,40,11,953,387,291,28,980,142,764,537,895,690,894,474,188,828,150,100,617,705,598,391,431,879,446,465,268,344,232,7,223,645,455,942,620,144,122,832,155,381,913,427,130,416,963,465,654,989,514,4,421,22,826,858,729,752,159,173,910,4,393,998,151,912,927,415,909,302,425,923,30,64,70,335,52,72,983,589,641,553,646,865,872,649,986,450,419,780,32,231,779,484,414,167,626,871,850,897,133,963,721,520,113,312,988,460,90,20,34,299,485,143,605,421,674,252,758,461,991,183,276,300,662,713,351,684,895,616,227,111,474,921,282,741,669,667,941,408,451,757,942,950,685,329,412,649,651,983,848,547,69,849,486,188,783,716,71,365,922,691,76,758,348,85,269,125,304,241,532,423,757,535,333,355,415,130,949,739,714,360,767,664,263,72,38,574,727,141,881,427,256,158,88,706,26,548,236,857,420,506,893,645,54,803,587,140,394,657,338,113,198,455,722,30,377,658,582,270,293,4,726,738,354,965,439,964,383,674,830,846,452,569,178,430,125,979,23,221,169,57,609,422,29,221,192,470,472,797,266,318,671,844,853,272,401,871,388,703,275,91,496,183,775,526,475,761,343,645,453,835,965,232,585,220,942,53,826,972,988,672,110,645,945,299,727,966,717,503,372,286,969,212,617,588,185,520,93,323,299,36,812,691,172,155,486,838,606,310,541,24,753,959,198,409,732,371,321,594,477,388,160,6,646,503,909,406,309,930,220,533,781,890,954,0,847,830,126,428,348,925,744,376,124,847,139,367,859,963,281,170,14,892,560,82,521,255,304,827,809,840,251,313,646,245,592,327,675,49,251,736,291,684,185,928,530,890,783,288,994,414,974,171,512,225,182,700,849,732,223,132,614,567,721,45,148,958,130,642,51,819,460,254,366,909,691,895,862,802,167,23,381,845,729,563,776,890,389,39,71,975,61,732,277,301,265,447,739,675,406", + "239,777,339,634,991,152,529,103,115,698,840,662,68,554,211,318,723,445,737,735,431,347,260,990,372,426,175,716,271,662,635,856,49,742,707,796,202,999,556,661,542,130,640,702,173,920,773,541,360,30,717,6,783,877,127,625,365,163,303,656,181,876,960,719,209,453,198,484,779,207,804,572,225,196,788,659,526,461,462,170,78,973,398,545,376,729,254,85,353,239,144,111,116,860,277,503,836,905,19,38,964,576,321,32,186,996,63,701,821,195,302,681,965,170,353,25,867,260,605,627,103,678,628,429,741,623,739,353,665,451,268,66,987,978,535,858,970,901,969,682,943,580,833,338,603,845,317,804,599,823,433,37,349,629,668,210,827,245,930,148,426,468,818,439,868,156,401,823,745,982,646,563,65,988,871,260,151,828,29,996,195,713,982,935,279,628,879,984,4,47,924,437,742,863,485,879,48,890,471,948,823,311,233,781,525,15,369,404,381,582,60,600,648,491,416,945,259,670,466,372,188,187,839,610,837,24,21,593,637,296,637,372,301,491,830,461,483,264,896,2,475,439,502,299,464,889,123,324,368,272,755,619,700,173,466,842,503,685,353,838,348,358,193,561,500,686,407,44,878,504,419,351,632,12,76,369,643,709,630,390,928,215,700,355,891,776,826,269,92,438,159,374,918,578,19,594,672,180,960,374,885,820,951,847,642,780,146,259,198,560,597,428,994,269,974,438,540,673,244,736,755,35,339,453,273,78,522,350,161,834,348,854,211,33,676,962,888,248,492,932,70,868,545,309,556,982,995,985,501,998,999,595,122,108,355,697,223,138,131,517,895,469,937,758,443,664,709,698,930,126,801,571,930,654,861,694,267,879,760,525,368,789,687,682,405,108,916,964,488,409,400,503,39,759,29,153,483,366,605,229,203,893,791,311,851,411,267,304,652,583,39,996,627,536,879,904,656,778,594,469,986,944,200,268,77,513,911,248,535,469,228,812,906,959,503,80,628,252,541,666,185,461,102,290,905,853,953,201,203,875,507,83,632,441,274,164,3,114,956,672,180,837,350,219,288,587,639,831,266,905,862,825,153,952,659,661,528,328,69,173,56,811,549,148,569,995,483,483,944,866,693,739,928,133,297,516,618,191,326,608,985,186,71,340,895,620,12,620,228,868,978,737,876,454,985,870,612,928,206,685,937,866,598,242,714,299,253,219,732,134,563,986,233,695,37,739,157,196,998,471,420,620,611,40,704,145,730,567,974,498,332,711,162,585,503,164,493,321,88,796,9,676,931,130,481,338,235,499,943,324,566,795,201,376,215,297,630,110,862,896,789,901,906,206,845,550,272,595,349,531,36,361,6,785,748,920,985,873,217,514,465,362,276,990,102,648,670,802,215,217,757,938,258,233,138,566,919,782,535,245,326,386,315,333,289,802,580,463,198,992,984,142,913,298,501,511,957,642,752,690,433,416,979,230,548,989,111,897,553,923,417,51,999,865,52,296,224,32,462,912,94,410,7,687,300,558,147,127,226,185,765,861,938,519,232,150,63,837,984,935,306,524,977,661,262,347,111,659,362,281,61,81,23,787,32,503,995,922,954,635,537,530,195,585,730,393,798,650,823,809,366,326,899,960,803,568,647,277,435,243,598,523,248,240,166,921,293,838,123,337,3,411,228,684,457,124,550,296,392,425,752,909,178,910,350,504,608,540,57,735,914,683,943,154,190,329,68,703,727,126,352,871,118,679,863,532,999,837,200,546,598,133,118,74,802,487,238,31,705,521,890,538,246,995,716,375,237,916,508,765,189,880,756,890,6,212,71,913,990,309,165,587,745,157,151,914,751,279,143,291,617,526,760,466,804,722,455,847,782,640,310,955,90,112,613,293,894,695,299,360,569,153,838,827,778,251,968,728,941,866,16,254,308,63,746,118,448,65,514,233,630,525,831,288,547,184,26,397,445,294,388,280,757,749,248,308,387,169,123,537,658,624,110,960,181,383,777,5,164,621,122,513,910,996,143,732,183,131,880,721,69,321,995,857,538,673,48,234,420,658,616,537,273,20,847,0,421,977,485,367,369,78,956,617,797,116,719,496,527,915,20,911,440,521,876,742,359,609,748,343,752,879,379,854,261,820,37,318,167,771,746,514,429,241,654,366,812,827,231,83,888,105,574,703,432,220,635,929,695,955,47,336,65,408,147,933,803,31,583,592,798,912,288,2,668,729,600,319,426,639,182,536,310,686,298,50,925,270,184,437,710,541,485,471,439,200,197,545,144,232", + "399,640,141,871,940,612,869,346,343,724,641,450,678,279,694,460,962,927,322,178,100,235,162,209,827,295,265,49,626,273,567,8,298,978,844,224,801,767,222,388,991,94,821,96,351,434,30,982,736,847,949,899,527,925,146,275,455,20,536,748,401,427,205,576,219,150,779,970,86,592,886,847,916,756,967,275,118,593,57,320,370,299,998,3,449,85,349,406,384,861,327,624,165,656,190,941,173,330,804,605,97,796,852,849,299,685,389,817,436,874,716,795,562,312,324,107,699,991,109,745,699,235,801,795,919,339,47,138,713,708,194,673,24,437,787,599,134,869,980,892,141,432,32,997,351,573,775,98,629,464,284,699,232,892,868,522,533,975,913,780,33,348,615,227,194,588,943,127,396,739,860,870,382,24,759,622,958,481,611,123,76,353,314,149,719,170,981,285,338,567,31,278,73,894,551,594,456,781,713,866,854,610,543,883,968,584,957,499,36,295,204,670,53,155,481,546,951,828,743,612,83,407,463,322,466,983,604,395,182,802,583,938,87,336,670,731,347,698,160,60,925,784,604,798,80,316,376,486,717,664,64,552,931,538,267,443,311,648,593,112,873,256,711,791,62,439,69,501,728,579,290,421,297,128,614,8,949,840,796,849,16,833,790,175,944,586,322,436,767,196,902,53,721,250,285,594,750,788,662,315,771,214,249,885,256,837,850,981,134,723,555,171,427,988,63,806,112,36,462,813,293,16,222,914,483,777,730,896,727,963,471,106,722,489,135,159,40,601,579,65,733,72,30,89,683,513,454,385,735,250,305,481,579,446,416,824,207,837,847,984,399,465,264,568,136,665,801,836,122,560,920,857,432,337,156,146,143,447,33,689,22,50,801,46,774,914,56,886,567,62,413,193,64,658,878,257,725,184,911,896,274,895,44,478,187,918,844,862,133,70,754,729,953,289,190,227,944,867,959,155,630,458,856,995,970,76,280,907,148,221,776,591,695,870,621,435,703,582,622,616,723,157,86,227,198,258,969,494,512,822,153,274,420,673,235,885,995,670,614,310,777,74,890,746,831,254,623,32,105,225,364,595,34,184,111,671,958,239,581,770,610,487,107,810,493,303,710,143,790,196,396,874,317,784,326,8,642,588,438,735,324,94,316,472,249,126,72,762,163,51,649,610,756,99,200,289,347,760,81,112,750,708,719,632,964,103,517,109,951,591,763,807,714,612,930,316,560,29,916,630,439,774,82,73,989,135,73,825,584,7,275,584,116,94,777,576,304,615,484,201,941,564,808,109,486,317,933,533,284,848,649,686,343,206,402,713,311,444,139,440,647,420,648,913,887,897,311,359,585,463,561,330,962,134,511,163,311,377,630,177,743,361,511,915,125,629,274,819,755,795,491,950,496,105,972,102,412,740,527,573,491,521,555,844,7,88,901,927,342,776,275,767,647,187,169,379,68,190,131,219,680,910,895,350,123,504,526,919,503,206,515,928,227,528,197,638,582,313,658,440,673,285,508,543,943,771,776,10,257,288,286,660,83,981,478,593,225,35,955,724,66,90,654,287,737,902,492,495,622,742,133,741,164,619,753,893,957,58,422,535,91,879,774,946,342,792,209,196,217,448,315,246,112,577,490,227,126,722,206,187,972,672,643,787,571,874,278,105,3,892,87,549,755,247,894,401,903,389,454,504,480,850,727,53,167,56,332,164,349,75,788,512,208,487,250,709,602,937,388,358,196,938,870,86,700,961,574,733,631,140,804,522,420,524,240,777,245,560,950,601,87,685,51,427,902,766,348,413,668,769,646,114,860,384,788,167,659,776,18,556,770,394,61,103,261,632,291,413,404,38,835,134,166,633,819,471,230,410,523,804,852,665,589,896,499,720,589,437,751,198,910,605,757,366,493,629,740,472,816,452,508,807,859,949,625,251,390,419,512,731,360,250,588,397,521,335,203,370,627,35,397,966,347,32,997,640,927,927,561,362,318,648,318,338,46,709,849,920,770,711,49,538,388,548,313,145,881,921,436,424,984,714,395,643,846,586,897,100,872,776,169,563,395,404,830,421,0,29,267,367,973,765,113,831,791,155,261,243,332,1000,845,372,748,968,708,377,1000,280,151,895,152,101,190,581,857,153,810,966,664,974,706,494,767,980,811,327,16,192,510,209,42,55,769,571,917,666,388,777,97,126,403,440,340,644,985,682,834,586,717,701,617,339,190,589,302,35,334,636,134,354,474,928,70,317,639,376,402,238,867,857,957,406,649,870,421,984,872,259,455,3", + "914,38,662,454,305,888,350,260,492,445,195,248,199,710,881,593,365,381,285,595,825,322,550,857,224,371,754,387,253,314,611,819,731,880,215,527,835,201,805,650,352,611,985,696,244,538,157,949,877,776,449,292,846,523,414,49,912,363,914,329,567,22,127,663,920,56,978,904,795,499,706,321,736,175,373,31,632,891,47,345,2,121,238,567,935,31,644,197,546,146,932,311,90,865,95,763,448,372,550,657,772,730,124,733,409,383,734,440,679,409,578,295,813,965,50,863,358,14,862,228,332,950,146,38,702,490,296,475,119,329,158,52,860,107,172,51,856,423,693,884,109,716,526,178,691,557,175,629,236,623,937,985,807,544,113,363,807,893,906,366,12,442,130,456,333,757,223,983,527,893,503,904,864,353,715,413,455,595,714,382,991,510,864,158,44,5,964,669,587,123,861,701,615,877,806,497,257,366,789,913,853,307,533,416,556,425,903,506,324,219,873,696,734,977,758,88,758,381,175,951,159,819,658,338,722,672,144,290,670,744,755,7,852,568,216,768,134,909,478,885,214,819,385,137,577,232,547,877,535,465,911,112,925,61,663,699,81,66,772,804,538,637,611,916,190,408,86,432,39,657,259,843,643,955,158,259,562,784,311,681,518,309,67,720,356,492,601,229,720,667,332,368,291,340,249,257,185,510,767,682,451,92,36,383,706,278,138,582,975,171,952,450,775,227,949,379,222,881,168,893,962,970,555,918,354,559,919,849,218,847,441,829,895,816,512,483,855,590,226,596,933,199,387,816,928,25,60,240,33,822,650,834,440,994,183,569,857,510,758,376,638,183,617,254,265,365,657,890,717,824,736,878,666,519,215,963,892,496,509,950,456,450,270,845,686,966,72,332,2,636,901,914,36,424,510,465,701,210,837,387,877,688,682,153,417,191,7,251,582,296,222,69,567,559,863,198,99,262,447,890,135,446,123,469,376,894,436,863,582,325,802,278,157,869,596,478,995,927,521,556,609,989,891,981,792,972,386,249,159,222,70,361,858,934,587,195,461,169,835,253,395,820,654,422,422,831,433,801,567,115,854,989,599,343,422,227,472,106,313,841,333,248,153,522,650,301,251,821,44,888,402,180,919,954,861,182,618,662,931,993,672,300,518,924,22,774,596,585,441,723,971,69,194,654,369,837,111,262,909,518,544,168,165,530,59,366,675,908,484,810,534,205,482,753,190,546,518,914,365,695,475,628,384,809,888,578,923,721,762,276,845,937,862,231,308,11,73,443,355,890,538,643,328,374,138,890,318,936,607,201,414,606,459,770,363,355,322,359,915,716,116,500,434,668,759,434,55,545,841,523,302,662,583,519,554,909,918,435,271,558,484,451,897,37,774,453,489,300,682,9,558,79,137,146,588,738,350,211,367,614,413,948,787,644,496,108,81,401,980,373,919,594,231,280,420,241,223,478,231,391,506,956,811,738,103,518,565,870,412,827,38,91,695,888,563,643,718,100,155,140,415,626,341,945,615,376,785,490,316,796,643,330,736,603,738,603,983,849,530,845,576,75,181,155,206,260,866,745,164,940,719,478,290,875,108,592,261,1,591,194,93,433,201,35,957,576,982,643,94,490,503,45,913,649,299,503,378,867,790,329,969,568,430,208,56,177,429,520,644,510,288,832,342,742,874,654,520,480,107,897,213,458,396,379,590,973,779,409,941,461,757,831,743,850,774,99,334,368,191,773,404,124,523,890,853,718,407,913,792,263,840,389,481,764,375,408,819,121,201,907,758,394,376,444,611,8,610,836,138,877,56,36,573,825,774,466,588,586,504,472,331,264,542,947,945,119,534,615,328,35,187,590,567,641,324,957,553,675,48,969,807,480,483,359,182,224,360,24,681,203,902,509,523,790,485,580,307,731,998,574,234,435,205,876,777,128,935,822,984,556,733,566,787,916,133,230,30,830,497,463,871,93,181,783,273,976,540,35,164,748,682,914,682,675,221,575,418,625,200,522,481,788,187,778,822,470,608,791,321,749,447,918,313,832,182,919,584,647,976,127,985,98,383,546,126,977,29,0,625,132,571,839,58,773,586,583,928,218,283,458,694,382,497,542,35,895,570,594,145,395,791,687,552,11,491,146,941,165,355,924,659,658,522,312,980,112,281,495,331,641,257,953,684,395,759,172,384,473,1000,897,140,992,88,862,773,913,93,761,900,338,829,672,872,426,607,539,225,95,10,193,829,757,842,409,204,400,400,436,550,955,89,403,605,234,419,613,993,942,689,780", + "451,541,560,976,438,224,462,114,122,628,596,775,26,565,220,874,273,970,75,41,988,874,493,427,967,474,856,220,170,909,988,995,970,663,909,343,942,872,994,197,91,746,465,801,445,465,996,618,542,340,713,679,52,27,862,11,461,166,953,189,338,488,600,364,375,821,229,325,375,885,783,708,283,856,776,889,277,698,163,962,608,50,627,625,4,79,797,799,279,97,17,947,856,402,169,957,492,177,25,945,462,967,427,655,959,142,299,582,101,570,120,171,507,439,591,958,259,412,463,97,730,675,874,605,518,99,530,96,436,589,411,934,327,468,475,755,671,838,112,193,83,242,175,614,685,236,208,599,678,299,633,952,508,584,550,954,148,411,869,512,614,33,435,398,545,363,363,170,105,144,195,112,556,981,220,759,136,114,984,422,640,991,841,86,404,239,557,105,240,374,476,838,240,680,81,724,370,567,365,484,20,372,494,942,448,279,218,210,650,594,983,180,654,408,867,437,424,183,641,121,445,581,464,723,171,224,175,978,874,495,542,555,251,819,623,848,76,444,110,640,382,803,829,810,359,186,82,441,746,487,983,271,892,723,126,955,531,400,461,650,634,435,485,645,161,959,866,714,681,554,884,207,106,271,757,443,152,258,761,113,751,6,426,821,473,150,651,961,418,37,466,994,885,120,950,661,570,509,384,327,532,11,572,313,671,450,754,597,845,292,256,90,500,226,588,756,388,464,446,656,65,45,637,772,905,247,489,190,486,497,797,555,400,235,561,834,18,749,189,767,993,153,880,164,32,782,147,616,275,994,942,934,754,671,49,478,784,865,506,36,107,552,575,381,302,774,327,69,742,498,309,96,956,923,882,490,199,784,558,933,821,562,91,554,871,373,282,725,355,974,785,719,202,225,968,615,892,600,850,780,237,26,805,196,367,336,980,837,948,382,963,621,916,224,441,335,743,477,996,247,653,51,631,60,466,600,636,257,332,147,872,174,831,243,749,493,516,832,881,272,27,193,873,57,952,554,64,449,227,676,664,783,775,78,736,925,159,574,558,255,522,890,198,522,427,562,663,630,726,512,888,118,211,653,191,576,346,380,783,554,714,866,928,989,215,182,363,752,541,213,402,851,874,883,501,955,824,32,685,666,800,888,920,634,815,536,394,325,948,242,33,312,340,317,911,914,572,712,734,909,480,339,312,826,985,866,967,418,623,587,68,98,427,815,258,460,215,371,736,299,790,634,553,886,804,739,849,350,793,725,360,855,335,837,986,419,340,258,585,504,491,902,948,71,795,303,802,273,917,974,305,168,541,571,563,276,313,903,160,557,609,540,188,691,341,560,837,600,833,652,82,516,644,992,585,350,148,596,131,483,111,975,723,771,833,912,812,510,279,640,239,511,536,452,708,380,753,290,304,683,118,395,336,900,864,238,892,976,721,616,466,820,328,957,444,411,140,149,129,703,687,724,499,439,410,790,861,236,913,527,893,558,204,304,765,302,230,790,604,666,69,413,201,725,925,186,296,751,295,767,524,243,398,3,879,459,647,157,611,677,366,805,190,38,738,298,638,889,740,616,223,649,916,119,308,109,745,706,185,659,219,658,156,885,800,449,930,794,76,711,50,418,916,655,544,622,760,863,950,154,674,640,816,909,598,442,517,8,139,595,471,305,120,949,980,982,159,228,357,629,517,129,617,114,843,502,379,646,764,579,596,300,540,946,950,611,925,16,796,566,83,775,754,160,968,430,311,720,619,387,564,252,758,170,142,750,454,151,453,312,974,944,22,680,291,500,738,602,873,176,731,58,985,600,63,129,689,223,778,979,304,504,56,713,380,35,260,504,630,705,411,916,131,894,900,697,418,381,987,560,695,534,171,959,866,532,633,541,973,373,272,986,344,109,811,683,123,882,137,239,541,126,306,941,108,512,748,341,959,367,848,925,93,292,821,514,686,940,651,94,429,602,457,956,812,123,270,633,893,780,309,378,959,482,998,108,232,241,346,769,960,536,208,368,79,331,376,854,762,746,947,454,159,856,107,27,770,730,256,589,798,505,911,907,428,485,267,625,0,945,857,21,829,917,158,23,213,384,312,400,128,572,182,522,259,606,267,6,358,479,742,782,729,714,268,307,165,300,118,366,875,796,204,185,257,484,323,992,121,853,944,853,810,477,174,797,674,554,317,817,489,7,534,983,308,755,745,161,963,732,675,353,361,930,506,97,327,666,798,606,667,341,271,566,994,498,917,29,268,514,367,569,271,209,271,90,93,56,417,625", + "281,59,647,605,9,529,867,131,14,746,242,649,560,339,215,253,890,907,415,76,928,775,388,649,151,674,883,855,551,767,661,463,533,33,639,621,369,857,123,453,746,558,232,917,895,727,717,381,431,528,703,267,50,703,355,253,30,833,452,61,959,777,54,399,973,740,98,148,649,121,814,335,3,991,718,167,600,700,112,692,494,505,688,813,751,790,32,997,25,598,255,223,653,686,856,987,915,428,342,403,478,440,200,280,781,993,832,171,461,321,61,908,878,296,118,288,12,339,338,809,732,8,230,347,421,56,298,694,421,303,343,269,923,711,514,983,882,161,895,823,340,42,260,848,40,122,242,22,69,7,81,778,289,701,493,837,349,653,517,451,453,302,825,281,77,46,462,585,443,433,378,558,870,391,129,76,224,721,929,651,458,469,231,896,801,645,23,844,569,612,516,766,53,121,177,57,938,855,265,367,663,480,241,673,825,324,543,324,405,156,473,562,303,538,951,794,662,895,312,994,705,560,819,40,925,688,183,400,109,647,896,253,317,623,141,977,303,111,388,477,458,302,454,187,34,67,516,611,38,157,489,747,637,599,271,441,199,452,288,857,431,817,534,992,73,531,825,973,519,276,544,508,594,6,445,976,503,648,87,44,743,803,811,296,70,343,551,243,352,118,123,101,744,530,979,573,45,202,613,766,580,331,734,55,293,630,527,244,611,323,732,764,883,753,434,523,51,252,943,590,372,19,562,359,500,351,870,149,852,871,525,187,837,413,701,689,80,779,599,581,970,916,2,293,203,162,926,309,52,805,108,850,877,687,936,241,436,635,148,568,357,370,58,946,129,314,976,497,279,779,183,140,415,365,34,83,819,349,309,419,959,609,457,534,881,14,292,200,405,152,554,153,739,792,487,118,225,783,26,883,38,426,949,200,686,968,765,154,257,182,999,106,192,434,60,973,436,209,543,123,433,840,497,115,420,324,864,505,912,602,40,697,811,841,127,6,806,42,772,364,619,924,383,661,575,135,878,533,396,891,439,190,661,96,370,392,902,32,415,819,805,10,774,526,854,9,298,594,547,266,569,356,83,280,642,954,607,245,579,940,548,957,155,972,250,331,831,674,393,461,102,18,201,811,893,332,316,13,322,801,667,855,39,687,720,624,324,691,652,55,327,844,307,507,179,325,86,483,43,962,995,174,632,787,641,889,661,885,446,990,245,822,325,178,256,396,927,192,224,85,758,611,351,742,140,898,268,779,883,85,533,614,762,129,984,854,543,804,506,187,772,415,43,589,481,4,519,927,445,372,948,508,183,82,39,925,920,896,740,722,236,450,199,426,930,13,175,836,610,10,708,465,38,319,849,696,972,120,653,837,384,759,797,720,849,235,551,232,487,516,185,858,217,181,407,401,135,616,897,60,896,160,222,119,375,814,530,868,736,912,529,699,953,105,976,696,863,410,254,878,473,700,569,985,762,355,695,492,731,164,988,703,452,468,148,131,914,995,832,518,415,720,852,424,131,379,445,439,56,241,489,602,473,374,153,862,868,259,583,156,466,644,240,451,79,975,747,332,204,399,438,191,206,232,511,605,612,326,949,506,966,295,940,758,411,947,40,428,268,63,490,575,281,478,733,184,469,520,548,358,258,839,988,377,139,235,38,271,160,483,841,340,828,406,971,714,93,692,201,690,312,480,82,66,455,555,866,524,320,736,597,204,791,787,889,430,759,473,981,345,800,913,90,363,561,531,977,76,197,252,426,106,17,561,384,600,675,929,247,726,706,95,964,480,629,48,376,683,887,424,918,755,803,568,288,777,300,72,399,49,785,401,539,239,143,352,258,421,270,968,265,421,745,898,578,141,647,523,363,198,913,98,966,365,941,941,25,715,408,392,341,115,360,418,897,163,725,123,75,791,381,302,935,44,910,359,367,194,644,296,768,806,931,943,21,374,54,428,794,576,638,99,641,191,852,227,973,659,768,545,848,662,867,475,992,234,77,418,70,67,549,721,636,588,299,161,142,862,182,412,476,747,73,60,242,522,4,950,78,841,417,537,367,71,348,367,367,132,945,0,346,601,869,105,441,30,925,746,478,89,641,399,466,594,438,7,166,385,854,43,609,922,784,401,159,807,198,164,972,917,727,649,438,609,566,520,58,640,377,118,500,351,263,576,616,6,479,558,209,668,850,330,936,218,412,98,823,585,830,238,511,258,437,587,995,826,519,965,415,873,763,660,219,793,151,463,16,563,755,55,224,494,911,527,642,181,539,392,666,286", + "720,160,840,380,902,445,382,981,815,987,530,51,946,286,335,924,535,411,158,895,171,928,852,330,459,130,110,789,699,885,453,305,253,257,839,573,507,469,320,999,302,885,397,761,84,125,37,404,406,337,151,176,42,793,315,595,616,284,908,29,860,260,566,328,306,224,755,456,723,718,443,372,777,861,699,571,365,692,90,5,595,489,230,377,786,414,649,681,885,313,464,496,605,407,498,969,807,423,650,286,39,528,38,387,164,638,389,321,482,6,346,848,455,279,255,713,924,380,199,979,152,226,961,866,470,727,928,691,976,688,272,721,484,884,313,672,102,993,953,112,238,369,33,18,389,158,196,800,388,743,311,901,477,782,836,654,318,180,162,657,928,569,386,682,764,543,487,76,206,160,161,312,643,391,654,975,177,59,669,518,468,313,863,313,678,612,289,133,869,53,24,48,702,243,632,776,852,809,553,940,221,338,111,618,725,859,620,280,963,597,513,135,453,264,40,149,493,334,512,82,71,29,69,362,354,934,666,328,581,543,2,299,74,852,369,574,771,758,33,197,784,258,56,388,264,937,677,114,631,137,214,853,304,950,804,782,811,38,981,164,826,163,920,67,776,912,363,939,837,665,546,713,442,896,642,167,519,895,754,889,616,350,279,248,907,479,690,394,773,784,736,496,988,728,555,439,716,922,2,870,795,420,323,677,410,779,166,753,938,170,222,386,326,900,76,313,395,491,53,525,811,747,92,69,253,226,411,355,561,729,77,471,860,874,431,848,571,953,451,344,384,706,490,175,505,42,436,99,723,317,72,839,148,606,898,343,201,325,600,460,537,928,672,405,912,952,856,576,22,218,289,884,930,931,476,737,135,875,720,857,657,729,638,703,408,280,716,131,144,477,240,439,806,67,529,246,518,635,139,243,482,439,972,280,171,341,30,253,540,14,472,638,616,376,882,856,630,276,650,179,581,140,730,307,508,64,731,748,260,561,171,815,897,695,366,529,682,434,103,448,147,90,595,48,676,771,207,947,327,42,803,237,870,345,393,591,508,340,122,46,612,495,215,607,297,79,586,191,592,981,832,153,334,973,393,152,142,224,668,501,780,190,211,508,971,345,491,5,951,839,1000,12,923,280,738,732,461,596,477,644,457,615,381,4,443,726,431,790,901,801,333,489,683,673,389,253,525,681,606,356,911,579,487,669,286,896,796,26,326,6,661,421,116,588,950,734,211,603,328,302,92,778,259,496,615,952,469,54,717,402,704,970,165,163,100,76,755,311,356,612,474,324,274,209,379,826,376,945,407,280,90,870,840,158,546,448,789,423,565,80,679,268,252,935,59,239,132,652,866,843,669,141,176,202,723,804,870,389,345,380,765,626,50,210,25,397,798,934,295,353,447,606,232,70,16,480,911,236,370,992,907,90,109,221,752,953,735,616,868,418,141,84,431,224,65,264,59,204,329,71,214,141,334,426,160,665,128,529,294,460,387,386,803,565,902,81,840,299,131,745,822,790,824,467,727,205,133,564,323,3,848,671,918,533,665,302,614,771,441,800,941,204,18,151,819,105,429,269,13,571,131,565,613,728,954,151,878,911,256,78,812,435,380,434,419,646,145,617,893,886,2,774,99,322,775,935,774,382,701,902,518,358,308,981,151,687,443,296,578,452,898,437,790,357,314,280,975,707,466,191,65,35,25,26,483,39,68,445,296,162,972,524,468,271,256,540,816,576,622,505,566,896,767,796,752,857,102,263,419,574,165,800,890,609,60,79,365,289,815,857,682,211,843,142,245,89,994,715,616,607,160,735,933,532,804,638,697,455,194,845,70,75,73,101,854,749,876,254,238,121,912,825,166,544,502,39,174,140,769,550,858,775,744,972,409,504,975,347,457,344,200,25,217,359,156,107,878,782,371,819,13,452,786,148,404,565,224,871,446,270,568,845,937,135,301,378,799,63,620,227,65,298,107,221,8,837,545,888,996,239,250,284,370,607,402,519,536,955,797,415,797,33,400,302,837,169,767,832,983,859,202,764,363,69,437,163,926,297,200,405,693,286,913,709,925,369,973,571,857,346,0,255,790,909,520,41,965,326,447,519,195,98,679,413,517,50,566,320,979,501,586,558,455,675,896,674,913,719,962,758,330,85,192,510,627,921,675,362,605,83,228,873,404,716,458,897,414,79,652,848,134,498,353,436,809,609,887,341,99,983,725,373,830,129,381,648,564,516,35,540,369,374,37,410,631,94,811,36,739,933,876,359,839,835,423,372,201,347,314,465", + "215,765,462,868,863,486,686,380,258,528,557,205,370,429,229,360,261,568,616,311,173,284,721,392,675,691,489,258,608,314,93,510,680,873,883,498,105,307,534,515,562,40,698,814,580,671,317,66,126,9,392,898,361,259,444,812,643,800,724,841,860,149,142,495,344,699,214,851,367,524,989,366,611,825,902,655,500,887,50,431,53,433,53,70,720,263,735,575,141,294,770,549,843,591,857,157,721,619,726,760,557,356,91,33,722,365,248,809,341,966,534,373,873,530,551,989,437,3,972,648,179,338,686,113,708,959,304,354,411,53,459,631,197,681,398,998,608,650,11,596,49,471,154,186,224,173,177,766,552,993,947,285,611,763,934,38,427,105,270,465,918,528,736,308,865,747,802,395,250,727,45,596,698,556,195,66,238,477,427,813,283,161,201,572,266,788,393,795,97,590,698,117,553,471,809,835,20,348,484,916,932,238,928,832,476,619,402,155,163,952,959,904,718,602,611,374,793,481,783,15,179,859,638,302,834,937,69,493,741,59,500,103,4,517,358,486,114,426,739,852,772,883,855,829,602,691,325,947,139,829,86,98,478,190,913,234,637,647,585,827,413,608,697,369,552,129,852,989,559,958,723,984,366,695,980,475,511,683,433,874,864,499,343,204,108,626,647,64,943,422,692,402,49,695,70,919,953,893,359,554,470,42,841,922,711,469,305,378,207,204,122,296,481,662,329,473,59,199,533,984,13,193,134,354,890,960,388,904,138,178,432,62,881,681,360,891,983,551,429,897,709,169,999,714,264,968,815,739,696,344,733,371,655,646,538,787,589,437,156,31,311,112,947,725,180,314,263,668,684,925,812,547,20,514,816,682,34,762,336,935,899,278,85,456,666,436,180,656,157,745,529,282,463,598,110,31,448,549,663,506,909,599,667,789,712,909,589,746,235,410,819,868,98,867,466,507,627,845,991,306,143,875,614,556,291,802,122,218,118,841,468,984,183,287,177,243,43,165,791,370,533,852,160,1000,985,648,610,99,503,340,77,255,718,196,772,670,280,553,658,685,297,500,368,625,164,429,517,282,813,887,470,124,16,759,395,336,476,579,156,143,902,976,759,924,475,643,913,231,242,266,713,403,992,626,125,930,297,895,134,328,767,12,174,310,324,969,897,642,523,346,691,924,664,723,430,494,647,333,710,581,757,284,454,659,65,551,750,975,666,976,399,58,781,949,431,66,57,56,285,36,383,887,104,441,793,68,428,51,403,498,723,889,959,568,949,671,721,949,79,905,202,841,54,906,28,112,249,682,514,827,78,478,223,637,716,952,265,737,664,798,224,212,933,884,835,537,560,494,355,210,791,334,703,963,438,417,992,592,519,407,858,235,456,406,430,697,577,624,402,144,705,975,2,96,288,687,586,244,187,117,77,970,821,924,505,148,543,621,957,364,805,802,173,241,243,836,930,318,114,582,315,771,640,416,15,644,57,977,264,77,310,10,170,174,8,298,592,277,821,707,212,92,94,250,816,124,473,37,894,994,119,718,765,40,927,111,935,376,198,307,642,5,865,880,730,130,704,416,147,588,592,295,836,854,617,401,757,879,628,363,36,292,949,473,400,256,966,814,214,949,713,266,292,291,800,492,271,867,200,983,251,662,603,286,808,758,981,389,782,322,411,323,158,698,799,425,380,522,583,686,545,547,743,345,865,407,342,743,321,524,354,449,827,597,43,875,469,170,577,195,377,411,73,505,148,573,572,835,783,702,507,142,855,946,882,41,718,223,3,364,989,195,596,852,49,313,562,955,566,53,809,865,244,583,926,741,938,186,216,855,344,783,813,316,505,230,253,111,986,795,598,242,948,314,421,432,8,643,212,107,163,781,724,56,170,47,14,730,749,220,418,529,865,594,958,300,181,779,228,838,473,867,841,596,21,59,303,524,44,846,392,445,470,476,399,92,511,114,320,305,966,527,81,592,342,674,379,946,816,98,554,921,936,48,20,922,453,927,937,518,744,710,26,111,909,10,409,414,299,785,872,479,745,699,929,791,689,581,813,191,836,86,430,532,744,78,765,839,21,601,255,0,605,334,970,774,878,465,906,405,269,341,409,499,610,696,221,448,114,119,284,208,64,235,973,764,703,815,789,765,862,549,454,574,976,479,277,343,55,739,691,892,595,470,74,251,234,244,72,367,78,658,571,466,177,616,914,992,664,194,699,565,306,336,683,577,572,436,809,325,555,202,879,772,952,474,201,559,325,740,805,479,439,521,502,326,145,931,4,529", + "62,92,761,472,58,727,65,927,606,315,196,640,722,350,822,119,9,412,90,531,841,366,870,655,319,29,352,821,152,347,708,625,816,42,876,975,676,773,772,145,92,365,544,286,856,646,600,507,660,755,264,216,973,848,469,261,719,71,810,369,459,976,70,437,303,998,89,139,752,644,621,258,235,943,567,366,828,826,743,370,519,953,27,490,137,21,686,525,369,437,88,622,800,860,977,194,122,271,149,766,47,840,470,794,135,100,914,899,437,966,608,287,891,262,371,947,348,226,230,35,770,408,701,333,234,666,156,874,258,771,693,193,425,377,581,175,253,204,665,579,762,502,710,653,612,627,382,248,158,49,947,575,927,604,898,600,40,938,191,693,766,276,751,457,150,77,703,879,176,760,107,673,79,309,762,505,841,659,60,966,882,990,951,263,966,982,765,415,93,328,708,844,262,608,516,245,803,966,198,861,479,194,328,532,647,469,263,332,403,710,731,800,788,330,383,783,984,627,581,247,198,243,812,712,741,586,913,860,210,901,765,473,478,644,790,270,200,509,777,431,926,318,732,663,17,991,729,993,510,32,395,851,990,764,719,404,570,681,168,943,904,519,441,497,932,563,426,798,982,287,63,603,601,765,805,56,796,281,937,286,4,930,939,29,667,995,985,998,147,684,97,338,883,490,24,838,669,533,579,870,140,925,608,908,774,816,573,220,507,292,316,627,521,793,349,364,163,737,32,390,933,367,747,270,65,453,706,24,438,663,623,675,626,256,627,665,372,159,536,33,767,289,884,391,816,429,344,518,35,618,671,888,905,238,856,711,301,893,743,42,915,508,651,297,825,720,920,385,536,599,26,397,341,267,568,412,26,567,184,486,914,462,948,731,156,58,352,268,81,327,320,439,942,930,654,182,342,911,935,219,622,792,711,924,130,133,1000,574,820,70,711,580,729,756,181,8,264,207,359,246,683,476,249,66,692,869,920,987,226,759,920,76,102,314,698,217,428,339,226,829,611,773,259,460,486,12,45,181,255,949,850,779,436,735,109,337,19,191,512,802,940,87,59,565,778,532,253,715,845,400,857,834,984,975,614,361,325,645,377,339,678,305,151,967,419,314,729,138,390,660,404,880,744,48,887,710,873,527,586,737,576,748,349,946,739,406,129,137,509,414,175,224,985,211,429,62,606,138,908,796,561,144,2,905,32,535,858,653,837,455,900,619,339,848,58,272,993,819,396,657,323,644,606,772,887,430,7,312,549,814,519,318,146,515,942,713,76,801,589,386,502,774,830,757,338,69,850,795,651,224,473,705,130,542,405,490,514,223,777,778,583,393,856,885,75,894,709,434,791,770,879,832,613,803,557,994,127,746,339,87,890,825,589,242,646,963,652,723,415,955,432,5,7,259,157,787,952,668,416,830,303,9,500,549,738,965,802,131,406,230,690,502,15,334,142,794,767,398,448,159,206,718,535,981,761,229,660,190,203,316,711,53,137,519,267,169,883,850,750,147,922,77,487,199,72,661,94,610,926,539,11,282,126,554,369,246,77,246,12,170,629,152,737,198,572,20,928,316,630,64,345,718,7,746,642,955,316,909,997,923,507,77,629,223,943,601,132,974,938,804,993,264,272,549,182,4,51,437,137,205,867,57,26,273,161,319,887,54,491,704,727,778,309,258,883,311,100,411,302,586,535,457,947,200,249,327,809,279,683,884,990,100,492,870,571,16,290,723,799,258,570,644,790,616,194,197,305,926,943,96,781,92,793,279,1,741,833,543,245,319,553,95,630,93,922,232,68,689,902,166,219,316,78,181,508,170,112,651,538,240,779,748,10,729,178,165,495,651,213,588,167,453,49,658,271,867,751,199,531,463,995,849,109,313,403,723,903,989,286,375,131,950,487,64,286,377,62,918,717,507,213,441,142,823,162,389,42,157,686,920,891,423,592,854,919,106,712,185,39,141,118,834,940,744,647,428,506,902,139,398,381,688,807,852,181,436,366,38,611,417,423,46,689,515,205,135,782,160,915,870,852,630,241,526,10,646,299,80,675,477,45,444,523,95,376,956,113,58,829,869,790,605,0,532,552,391,804,928,721,317,912,638,459,551,547,27,694,945,512,199,696,257,63,517,770,432,370,876,791,267,936,381,22,127,344,766,833,574,572,340,210,425,436,785,136,884,166,558,536,330,871,953,44,816,488,316,577,197,604,515,78,734,961,836,163,414,153,129,179,757,81,787,910,905,908,254,682,312,785,968,845,927,660,492,968,93,991,862,667,121", + "962,32,410,410,951,165,561,238,127,531,480,87,527,486,23,417,613,489,767,617,69,436,208,213,342,180,266,148,430,442,603,111,224,293,1000,660,335,111,839,507,264,655,350,416,256,368,754,169,399,469,183,688,80,784,804,270,585,61,354,265,731,555,567,898,297,954,199,420,499,488,944,570,664,201,9,151,64,55,547,448,274,227,287,333,112,125,244,717,586,962,487,506,234,624,911,583,587,660,209,536,533,233,798,42,226,684,423,747,789,149,903,687,253,914,30,347,77,12,85,548,956,212,22,245,881,124,3,542,663,168,808,358,502,587,591,580,349,735,72,45,3,929,233,192,166,220,239,766,149,950,774,337,477,512,530,975,481,367,22,573,943,493,991,151,33,825,332,264,6,533,941,154,950,196,269,813,593,92,504,688,978,425,26,13,175,133,538,527,120,844,614,327,22,560,231,843,820,250,739,656,192,424,758,531,253,598,231,766,192,19,324,581,311,84,929,993,443,448,692,488,324,459,743,217,193,953,319,100,511,165,851,375,694,754,533,795,513,278,428,21,831,343,808,325,641,969,903,860,162,973,104,303,491,971,976,954,74,3,78,968,833,89,740,570,603,761,766,492,525,21,578,187,13,82,700,740,455,16,748,982,815,869,71,594,477,609,934,808,868,730,212,621,235,814,338,59,563,811,844,418,426,203,683,534,810,30,185,64,864,941,244,292,715,951,193,481,93,456,239,821,254,683,9,973,38,826,839,428,135,919,296,446,578,255,819,417,361,375,474,897,340,985,104,451,491,331,438,961,578,751,263,703,668,444,158,489,234,874,628,119,493,955,590,574,432,839,966,264,959,950,959,32,654,98,678,482,872,589,857,919,683,196,105,135,494,7,808,943,866,297,813,791,146,694,951,980,479,277,1,968,797,488,209,847,185,975,500,686,509,852,348,484,614,945,814,493,41,698,337,856,825,785,214,77,771,971,259,714,226,577,810,942,237,274,41,420,575,166,233,978,923,133,525,198,658,38,680,176,575,940,387,980,300,222,854,23,320,188,391,22,453,561,218,51,952,517,820,761,957,663,612,8,869,222,787,495,219,353,48,881,51,734,312,821,625,189,300,412,852,658,885,799,42,128,798,436,115,471,651,806,834,512,368,871,454,975,579,877,736,615,452,276,49,566,718,385,557,459,850,951,992,241,486,57,964,251,177,687,724,526,723,480,447,981,581,210,703,309,898,372,16,826,984,8,303,442,917,108,629,693,189,261,70,329,495,377,773,80,831,508,568,706,919,852,949,463,863,704,886,743,825,926,436,59,7,836,713,474,803,904,688,599,824,566,489,234,555,415,446,865,45,111,431,535,695,720,359,315,286,817,953,190,233,921,525,83,729,694,693,173,742,598,395,68,356,887,435,867,993,721,409,205,296,58,932,650,260,421,692,290,808,475,92,649,966,161,876,544,126,846,439,53,75,348,963,246,140,375,384,413,504,324,133,62,106,626,982,699,934,330,841,434,548,240,339,162,793,224,53,529,183,493,779,178,454,593,967,380,882,184,378,658,974,351,304,193,21,547,778,588,201,475,801,429,941,892,209,424,485,212,186,181,99,462,855,621,251,409,29,356,418,338,701,44,674,251,103,101,212,244,271,133,301,307,845,199,260,621,561,519,573,362,919,825,465,344,312,903,939,696,860,739,8,62,848,157,452,162,794,518,208,131,160,650,814,498,757,981,259,71,452,555,945,111,359,929,757,443,605,972,342,748,313,192,897,850,40,491,466,313,657,451,767,332,441,854,464,624,422,506,429,910,890,323,24,233,986,938,370,752,717,569,117,345,798,986,789,469,393,222,202,578,708,880,832,534,968,826,801,823,768,900,368,42,857,591,489,869,173,937,332,97,984,966,879,87,221,568,378,180,379,376,292,866,740,427,958,116,176,596,533,754,215,980,876,466,941,352,248,24,76,994,269,278,585,216,627,28,965,297,636,740,325,275,285,177,423,618,929,732,603,710,584,262,222,134,539,104,340,90,681,119,936,630,728,467,249,367,893,356,350,933,57,717,124,617,831,773,917,105,909,334,532,0,830,285,307,318,623,201,937,356,834,856,522,718,90,677,811,51,870,871,498,706,270,609,67,555,320,304,56,510,644,104,725,697,698,936,546,628,762,778,138,469,997,784,565,382,818,449,879,595,500,175,642,490,332,143,990,853,726,473,92,717,208,908,132,576,733,282,915,839,834,411,238,365,701,970,65,928,332,651,894,808,126,890,138,239,634,462", + "8,56,764,549,266,94,989,594,39,374,301,729,133,594,914,946,516,191,97,537,963,622,128,636,988,156,747,684,693,72,629,306,690,337,263,204,356,556,914,765,588,471,426,742,805,712,933,402,770,985,477,781,702,259,652,721,222,656,549,358,392,765,690,495,217,342,716,10,400,191,455,84,821,136,283,816,972,705,435,409,858,653,925,457,363,758,569,832,892,809,121,778,646,435,981,363,266,382,4,623,584,285,377,998,123,162,727,414,241,312,535,98,423,746,489,46,274,589,525,217,134,238,583,732,500,451,22,609,880,482,400,650,620,192,19,734,222,557,802,984,267,767,748,450,613,816,384,810,161,119,575,752,332,358,290,993,824,826,826,604,747,978,641,631,487,280,37,38,299,10,318,943,246,80,369,593,775,485,33,299,788,97,448,446,243,759,891,489,54,237,753,809,118,531,914,997,33,764,125,19,45,522,670,597,889,149,730,184,240,820,703,979,596,542,412,807,600,840,636,709,514,444,804,553,432,865,587,400,809,669,71,756,285,793,138,269,310,184,538,575,422,277,943,489,677,165,388,653,616,423,229,783,106,978,514,890,531,705,138,990,20,502,189,928,362,148,664,364,45,488,256,889,521,866,250,472,412,83,840,808,554,226,58,224,964,299,606,442,852,416,718,665,366,837,802,685,69,638,114,787,108,587,355,115,665,41,442,646,317,524,288,202,484,283,879,617,620,999,461,730,161,832,486,355,355,25,776,807,524,393,549,390,647,901,662,903,482,423,36,17,624,234,738,735,33,377,791,738,274,218,409,656,308,348,414,719,97,791,651,104,489,672,185,860,613,426,550,721,751,134,342,414,527,679,991,861,716,601,644,936,447,36,744,816,448,618,623,182,689,536,657,318,380,329,220,205,775,206,362,436,759,849,366,690,194,267,732,785,973,919,143,533,150,673,992,757,38,912,733,910,75,862,936,949,218,966,437,245,717,911,804,9,249,196,500,149,646,550,912,621,986,387,672,594,406,469,345,161,453,868,256,91,753,32,593,798,728,169,297,298,958,155,515,66,921,806,828,69,846,240,283,782,659,477,786,190,202,842,786,594,440,225,101,747,473,446,621,410,395,793,89,392,870,535,555,624,434,554,782,560,568,922,450,434,107,465,526,701,294,950,452,792,494,589,803,794,605,468,737,861,817,702,406,696,901,202,896,906,522,257,599,811,52,576,396,542,269,270,597,281,740,334,161,327,474,681,771,403,328,679,770,839,93,470,623,155,560,114,629,308,539,929,397,833,620,570,112,966,729,766,724,977,319,976,727,388,397,197,346,698,681,780,1000,985,349,617,776,482,923,223,734,316,826,219,861,636,5,702,237,165,307,657,129,167,91,676,350,355,837,60,802,766,762,514,290,465,260,999,678,252,84,828,335,32,123,543,272,181,938,584,773,480,908,927,362,338,370,575,574,203,194,200,987,180,860,659,192,816,422,141,843,244,820,767,187,95,241,401,850,887,240,798,865,88,451,251,80,833,548,600,572,530,559,657,202,961,309,186,531,277,712,982,614,748,286,785,294,105,404,32,756,122,607,59,296,904,426,880,420,58,201,418,902,655,946,514,351,401,208,109,745,988,510,892,9,481,256,866,517,361,969,553,234,339,214,249,615,920,559,690,45,370,373,983,721,231,789,896,530,190,394,967,128,769,978,264,56,590,535,246,478,274,37,131,622,630,66,513,583,493,526,727,478,375,907,268,375,519,732,570,726,702,420,91,205,401,906,704,637,513,398,509,429,626,882,785,193,901,593,474,631,602,178,831,101,882,154,654,304,849,565,150,103,647,273,909,222,59,12,594,681,343,230,277,479,617,553,162,316,143,759,463,329,965,746,74,399,455,176,175,342,927,144,128,388,845,59,51,960,982,382,777,711,746,945,180,674,196,909,94,689,958,786,509,186,606,852,86,842,640,822,896,60,943,463,547,176,840,424,189,532,166,241,928,891,843,843,910,95,292,518,221,356,480,68,22,818,184,705,536,467,439,881,531,245,849,517,55,245,175,438,896,503,986,847,797,791,586,158,441,520,970,552,830,0,91,297,275,446,238,795,945,650,674,417,914,82,349,526,464,288,375,170,330,811,643,744,359,109,886,830,744,629,491,292,8,393,993,12,78,847,945,428,670,30,793,670,947,349,409,406,137,73,989,170,927,933,728,277,375,171,56,597,639,485,900,483,162,342,770,930,341,371,864,518,885,344,453,398,322,648,71,747,560,78,805,184,492,575,751", + "208,662,177,277,135,23,337,5,868,428,528,538,821,73,968,660,597,27,263,737,552,998,56,51,434,875,11,797,509,959,904,331,659,377,137,194,510,999,570,815,507,755,972,690,436,625,927,761,355,444,11,920,569,391,509,26,770,596,917,645,333,561,165,318,243,904,45,439,38,636,221,63,278,106,185,98,572,910,141,386,402,906,269,126,256,915,454,914,825,971,140,112,2,316,624,958,535,946,67,708,780,282,508,403,19,729,596,174,314,615,37,521,336,115,201,977,129,649,681,103,828,271,30,283,918,352,536,180,813,622,956,421,742,119,164,571,604,902,859,442,139,521,523,52,51,889,977,559,694,139,143,426,199,939,69,477,753,284,891,960,771,509,191,558,672,418,380,659,519,362,826,970,794,700,102,42,726,101,16,360,689,612,980,869,989,799,620,664,308,287,893,119,744,71,236,254,426,382,925,893,817,390,334,401,926,141,155,593,927,473,383,97,944,718,643,956,785,564,893,986,250,924,995,475,100,431,867,214,957,914,280,132,475,670,332,827,185,469,77,363,535,369,254,248,378,885,326,684,181,17,225,324,319,314,85,891,58,29,749,517,830,585,295,898,598,132,135,816,162,7,633,469,316,135,44,405,85,514,449,682,566,985,947,786,507,25,879,176,157,617,634,687,67,385,925,143,359,93,272,783,716,904,559,69,884,167,460,959,362,529,208,851,297,107,763,104,834,757,159,218,820,101,50,490,82,216,86,272,737,842,445,688,649,607,970,491,484,237,309,425,233,817,955,349,451,708,34,959,662,430,598,631,301,831,859,47,626,407,910,681,719,198,936,527,938,382,731,480,898,548,446,339,643,33,124,274,435,52,540,298,270,171,185,159,582,275,753,657,66,517,902,820,991,487,706,538,967,88,817,995,960,170,828,519,955,125,196,202,519,204,355,608,861,340,474,244,623,804,302,497,398,277,271,860,398,409,754,511,621,49,429,766,730,120,626,518,636,669,763,744,352,60,341,3,648,785,57,89,378,752,381,130,668,26,46,760,752,451,978,565,953,121,961,415,544,173,366,677,647,162,292,748,733,402,281,188,408,441,849,663,515,515,42,404,820,328,838,174,648,815,178,632,836,945,141,696,5,491,46,195,799,703,594,168,329,542,950,541,617,310,817,741,372,107,17,719,584,569,859,465,409,606,635,119,676,614,728,825,215,778,584,358,281,573,333,354,650,404,221,864,736,319,425,363,839,192,454,388,15,171,571,483,522,519,27,152,660,521,929,747,204,817,713,896,34,682,914,537,52,299,860,606,733,221,943,473,803,994,132,432,697,539,287,646,511,356,704,464,493,812,737,351,959,786,696,864,903,391,871,717,725,359,454,89,178,884,572,544,201,261,966,225,197,103,786,555,827,491,460,762,287,725,807,983,156,664,923,568,241,829,382,183,84,463,233,223,572,492,322,924,739,886,173,843,395,460,870,461,605,78,969,958,310,446,896,613,344,510,683,109,713,156,411,824,630,987,653,280,125,306,107,733,964,762,893,423,655,975,270,216,507,652,689,107,213,50,811,674,726,528,117,559,597,416,988,650,13,309,976,888,1000,870,814,768,756,924,659,410,739,302,639,33,828,761,549,743,976,511,402,364,459,376,856,641,581,453,483,767,276,168,547,598,714,160,114,85,465,733,805,24,444,767,249,861,81,125,495,51,424,726,573,721,549,87,365,477,218,869,226,326,717,151,861,579,379,911,463,4,56,463,710,62,789,846,931,456,657,886,261,617,918,472,325,260,61,247,932,286,655,470,5,733,984,601,472,486,825,700,479,789,387,753,17,502,91,106,983,473,486,207,500,817,183,601,493,151,479,225,196,971,283,701,264,616,945,351,714,521,826,775,262,615,127,272,779,808,126,646,101,190,26,808,48,701,198,819,229,971,465,847,461,324,854,221,808,981,516,363,347,669,366,523,328,187,252,557,27,559,72,150,393,778,633,576,82,631,106,239,294,793,672,204,733,81,702,243,875,177,291,399,258,495,78,236,279,235,998,126,619,23,444,55,358,622,139,116,155,583,23,30,41,774,391,285,91,0,564,430,740,15,143,100,632,259,567,742,664,702,33,321,74,792,455,31,57,887,945,869,707,390,884,501,999,449,708,969,846,403,380,777,414,105,258,63,858,744,609,620,893,770,817,834,835,259,71,463,486,171,472,682,816,107,261,137,660,998,97,485,17,304,993,842,48,474,777,368,162,227,342,296,604,755,602,727,995,98,590,496,906,131", + "617,451,39,392,131,53,754,9,750,942,438,295,546,25,13,446,626,888,552,877,649,763,64,212,857,778,293,444,188,793,964,75,596,708,436,245,879,128,403,832,924,518,644,498,915,630,62,250,132,711,968,63,832,669,817,1,498,357,529,948,546,399,51,672,193,771,145,756,877,913,636,582,316,297,83,589,250,101,761,696,862,239,314,174,349,566,188,689,737,538,2,825,148,724,651,357,711,717,69,1,330,532,691,431,898,582,528,433,143,206,679,579,532,480,208,920,982,623,842,264,526,77,148,398,833,823,228,777,68,510,685,425,522,874,649,128,24,460,978,334,473,359,242,835,9,398,49,262,336,608,654,702,706,583,654,881,784,299,394,42,97,3,596,334,649,460,109,865,997,170,701,248,317,414,295,743,222,475,812,43,48,743,312,654,889,322,99,331,372,752,338,899,122,247,836,171,176,96,777,633,319,539,584,640,304,96,569,610,590,934,40,47,828,275,38,175,987,664,794,116,926,896,233,1000,287,587,373,679,315,571,776,517,5,121,394,242,156,941,393,696,85,246,396,566,678,471,447,365,756,387,231,57,977,915,931,308,411,853,354,980,881,93,601,979,607,650,293,17,680,616,632,604,562,793,549,437,163,560,884,34,27,735,847,150,473,742,909,671,293,253,780,258,261,967,181,311,963,866,670,301,617,509,854,641,261,116,323,50,241,943,366,514,607,690,143,331,477,98,502,632,484,947,312,814,542,658,186,28,9,664,989,37,544,748,608,853,499,899,746,590,829,96,876,922,861,511,509,753,314,192,488,249,719,304,577,496,509,14,794,684,679,82,65,628,922,218,304,918,776,749,300,178,957,305,119,907,287,69,957,54,318,193,599,105,378,534,563,372,166,143,554,590,288,742,178,920,863,999,238,464,897,251,983,872,734,682,895,615,177,913,770,714,955,361,19,196,235,291,169,491,596,10,463,697,347,135,35,328,287,595,704,951,609,375,204,305,712,145,776,685,715,474,878,543,444,960,93,731,816,730,720,535,789,510,547,94,220,857,225,503,544,923,996,618,948,861,419,968,44,189,934,17,950,966,686,943,803,476,949,977,316,340,975,183,637,162,811,483,401,659,277,643,775,391,816,618,41,66,79,983,997,860,207,846,238,696,815,839,358,189,942,549,458,711,18,158,104,871,207,342,76,386,323,138,679,478,548,303,709,92,967,903,348,562,649,752,516,573,396,29,454,513,573,104,746,436,959,977,963,193,144,433,511,617,426,996,86,170,428,453,141,81,499,36,181,203,768,78,443,525,83,149,98,566,567,645,983,421,167,944,537,721,823,722,78,698,803,819,548,492,196,998,877,154,361,443,765,997,442,611,396,125,777,177,589,727,262,719,644,191,909,947,432,765,331,637,206,685,312,182,116,790,738,24,709,810,807,473,603,145,193,27,45,274,510,401,361,664,481,138,645,560,834,378,415,70,33,405,271,430,83,270,58,223,692,76,509,136,391,457,823,277,631,309,514,395,102,979,924,427,750,628,745,2,264,175,206,158,430,42,177,712,451,852,454,299,931,188,792,946,360,143,805,338,797,66,727,968,299,681,200,49,206,838,716,609,86,881,778,386,161,30,184,156,732,254,825,203,257,771,138,751,922,97,321,523,500,521,515,798,179,26,845,181,51,10,188,457,268,826,631,468,919,478,613,479,378,379,958,805,849,660,336,855,159,867,889,717,778,701,901,490,147,309,420,732,675,159,287,61,897,849,589,269,259,451,170,945,999,845,776,779,525,629,268,340,402,319,12,248,903,470,774,861,11,452,976,251,432,727,295,111,264,757,781,936,885,855,244,686,599,762,103,151,647,409,299,535,647,469,357,144,314,747,84,1,627,355,150,926,263,964,61,808,427,206,308,508,201,725,263,761,914,306,209,933,440,539,259,939,579,431,264,919,752,426,758,302,554,101,922,84,58,699,993,77,416,44,966,717,66,548,971,141,322,615,292,733,94,812,715,841,450,35,933,970,190,64,857,841,583,453,75,291,159,668,262,221,131,459,83,590,687,534,367,719,261,928,213,925,965,878,804,307,297,564,0,111,675,418,371,473,738,799,307,790,947,118,260,77,596,283,740,158,466,750,189,967,371,858,592,601,262,829,21,302,68,314,519,290,36,105,669,533,696,546,116,533,13,701,979,350,482,366,47,689,833,216,164,106,711,991,251,513,340,460,277,518,304,910,981,476,346,901,8,531,81,287,917,628,308,99,349,896,619,304,262,869,565,589", + "285,449,138,907,44,415,901,877,36,806,492,166,213,987,814,484,974,55,870,823,203,257,274,605,569,247,273,629,319,316,759,851,217,49,112,854,217,667,371,248,148,466,3,840,703,921,185,975,608,340,893,455,794,254,547,229,360,362,18,138,307,25,69,895,259,426,961,308,935,812,130,347,179,98,897,720,507,344,727,643,300,333,27,894,261,893,813,744,343,582,312,615,400,191,737,756,727,579,653,733,704,586,456,707,420,716,970,975,880,617,567,242,689,969,210,427,80,689,322,991,285,650,995,783,939,984,983,100,706,892,239,517,238,76,575,258,948,268,384,544,469,347,492,985,969,140,861,878,721,48,606,486,187,460,657,966,742,170,73,225,746,20,341,483,621,851,93,880,82,335,864,334,60,136,868,743,942,425,260,552,24,159,483,98,604,720,932,413,661,958,195,153,166,974,79,372,710,27,475,199,350,435,909,27,542,493,214,267,970,751,214,492,66,191,599,313,686,108,192,329,539,747,996,450,265,679,77,67,998,373,634,651,322,947,793,365,319,482,714,257,424,76,977,372,44,962,453,190,841,814,604,434,469,768,48,803,286,346,511,907,261,105,335,948,190,137,424,917,613,1,280,310,926,478,16,728,280,63,449,38,828,865,875,505,178,6,387,691,122,31,445,235,36,450,552,909,409,855,397,847,844,429,472,685,832,237,38,868,41,371,901,388,560,710,851,488,149,913,181,797,107,357,904,847,160,308,692,108,168,84,970,239,514,880,329,942,588,204,135,8,287,235,786,6,87,97,173,24,681,545,531,530,530,511,140,185,302,874,479,573,363,541,921,465,532,212,527,138,839,943,825,761,401,855,349,826,329,853,523,847,203,995,368,341,755,935,727,914,99,155,897,326,916,429,231,224,240,616,960,456,881,505,485,728,860,514,873,440,774,198,616,186,835,436,373,206,888,319,370,345,685,528,74,511,321,678,365,886,84,826,593,322,954,403,657,80,851,251,928,554,220,795,655,447,988,362,683,665,808,697,710,749,188,616,743,578,933,903,725,900,713,896,10,279,144,552,114,106,932,249,496,369,713,136,705,966,426,156,214,65,88,263,689,233,782,928,80,252,33,991,411,362,826,362,219,562,462,473,753,499,332,613,258,232,714,118,290,867,144,811,260,778,784,325,49,93,276,347,169,751,533,294,920,701,944,627,986,690,987,856,104,446,35,628,726,982,793,954,392,56,142,597,343,530,478,239,195,857,817,246,8,928,714,593,574,301,17,153,862,5,244,186,321,740,988,648,325,705,350,587,511,555,945,48,496,259,329,965,662,104,545,236,912,660,719,929,817,739,406,208,373,141,204,953,44,116,163,638,395,819,605,757,178,42,733,407,530,586,102,584,730,585,369,847,961,878,211,631,810,164,505,402,636,755,872,813,674,931,429,144,423,391,686,396,116,45,842,367,818,428,555,260,838,233,539,779,358,951,373,996,564,283,349,590,213,185,548,911,91,248,60,122,555,169,41,894,50,669,628,727,461,682,967,407,165,857,85,877,42,389,984,883,547,988,156,668,238,855,198,46,403,169,963,955,448,175,925,572,298,381,689,871,491,197,359,106,634,830,829,655,923,427,626,240,44,648,859,10,384,252,307,520,95,391,540,512,838,619,725,506,533,948,958,916,688,185,72,276,210,719,890,552,469,13,7,35,465,830,490,491,6,397,838,766,634,352,552,712,729,350,195,754,627,945,633,186,233,171,422,505,898,14,324,517,675,421,136,49,98,97,590,866,122,318,935,694,784,98,80,520,514,607,153,831,5,782,275,773,925,512,357,233,675,251,108,299,888,416,830,437,887,897,948,710,896,747,873,915,439,549,568,155,637,944,353,511,406,463,796,847,747,752,801,267,592,546,330,297,481,874,919,988,913,174,235,624,940,826,996,531,153,733,735,95,443,914,339,3,432,948,694,430,285,220,308,258,294,319,584,449,468,198,406,948,401,460,338,243,704,726,590,344,886,724,430,551,6,259,336,209,611,780,991,621,956,495,275,369,595,643,850,517,679,806,859,496,243,218,384,746,326,465,928,318,275,430,111,0,230,142,730,943,338,501,197,225,891,353,192,617,892,858,188,540,678,871,975,865,294,100,280,460,796,566,752,29,602,334,138,809,120,343,840,853,888,584,253,735,799,122,864,15,588,9,745,371,94,481,971,876,276,832,664,248,878,489,145,215,980,304,50,977,158,697,458,839,966,95,955,194,381,189,628,869,960,977,211,502,577,587", + "391,517,974,893,133,16,348,943,308,533,381,363,957,161,218,41,950,485,984,379,792,305,160,337,531,771,286,63,198,160,278,143,874,706,827,974,951,208,81,128,360,489,850,487,873,607,561,789,492,966,337,660,355,997,198,770,247,13,318,498,413,35,984,152,988,588,80,885,822,974,979,900,634,161,869,452,345,335,934,953,932,58,934,878,103,982,505,164,632,683,945,67,372,675,366,817,500,261,518,644,264,627,599,258,659,454,247,154,432,589,957,935,903,343,520,49,45,806,298,172,768,392,80,33,486,998,937,192,555,792,189,433,926,864,472,558,843,443,573,455,374,220,494,711,202,199,163,252,196,456,744,969,964,914,257,533,898,314,362,868,499,170,632,199,408,175,879,157,177,977,175,945,799,547,827,798,616,13,6,912,458,52,951,119,554,239,929,979,932,45,185,365,316,738,19,505,883,503,888,39,897,155,459,450,296,553,694,934,999,4,286,436,228,993,409,173,983,236,12,549,208,933,919,373,954,869,200,429,107,104,174,660,540,684,244,641,853,176,269,593,569,943,956,929,832,350,709,920,815,339,773,619,888,108,168,89,67,824,949,879,383,305,236,974,282,444,405,492,27,841,306,395,237,396,199,911,824,660,378,711,282,298,663,8,220,651,766,225,749,395,311,996,143,307,895,286,42,19,499,611,423,123,54,111,494,962,726,985,746,60,416,636,598,724,409,947,104,393,961,918,23,427,572,981,268,288,955,255,995,775,552,218,921,596,654,21,509,954,725,723,593,963,907,163,328,334,642,923,80,450,299,553,312,610,915,632,881,689,135,666,192,646,312,430,501,967,914,846,995,792,339,563,495,523,899,87,755,934,199,227,461,13,618,263,40,380,798,132,385,662,181,59,965,531,413,370,246,176,939,856,476,705,201,902,769,900,884,905,197,817,434,136,988,221,976,36,938,493,79,51,253,210,281,769,584,526,42,790,853,635,921,153,744,208,280,456,103,33,73,206,842,410,905,41,188,370,826,942,157,712,238,855,592,329,637,43,585,299,938,560,234,628,76,666,763,42,543,245,699,93,417,289,913,378,211,802,666,988,174,389,399,643,630,182,43,811,449,801,549,477,225,522,124,881,18,498,566,823,673,68,107,140,56,677,646,538,199,802,264,234,514,340,27,501,6,471,104,519,611,862,150,913,961,549,45,713,907,887,433,872,361,147,386,115,668,186,936,3,939,922,33,604,942,69,439,735,616,158,960,271,745,733,113,632,733,178,65,268,646,915,708,904,675,960,291,165,783,570,989,215,448,446,844,512,820,67,974,426,229,461,658,196,482,760,879,857,920,465,194,945,741,178,102,880,638,59,443,791,212,54,533,625,356,325,955,400,824,96,396,258,568,959,463,142,90,362,52,899,171,790,809,331,737,139,849,770,932,828,313,436,408,325,173,455,532,430,732,885,191,517,281,118,428,638,361,507,327,433,997,745,554,907,671,201,164,57,314,3,31,895,413,764,831,724,569,131,143,748,816,673,765,417,286,112,452,794,65,984,532,944,94,756,835,806,240,627,114,143,374,174,959,291,422,823,769,818,746,18,743,629,87,900,779,66,37,754,374,638,121,653,132,190,854,743,557,444,4,625,599,474,740,453,289,358,271,701,114,150,693,725,607,634,877,760,328,903,843,557,687,698,548,575,848,62,601,103,664,281,68,869,583,261,605,491,170,929,579,992,569,949,635,182,984,911,694,493,44,691,921,987,45,150,815,286,671,624,956,478,571,110,372,876,730,616,228,19,45,254,614,316,159,301,559,436,217,281,350,868,839,377,229,569,387,141,730,8,29,616,340,43,645,483,848,676,732,171,680,755,184,290,69,873,447,67,256,102,853,212,707,378,228,2,328,966,754,183,566,402,610,33,898,908,575,10,789,601,316,535,165,365,62,425,913,100,456,297,462,582,117,770,268,56,109,494,558,915,105,6,56,746,795,702,993,68,905,870,28,754,246,379,853,122,935,92,809,797,267,153,286,578,740,496,446,204,630,8,378,125,335,627,864,302,901,601,963,527,332,283,312,478,447,906,721,623,446,740,675,230,0,675,143,52,949,918,186,981,801,711,136,198,564,639,728,72,238,293,563,588,463,817,380,402,39,434,632,541,699,396,231,728,616,312,93,290,962,80,864,935,85,418,697,85,951,339,793,272,296,719,646,411,412,659,675,890,355,208,932,733,584,733,432,950,257,669,543,522,412,349,367,170,264,322,942,982,437,738,543,780,289,107", + "544,476,919,987,411,109,599,539,603,646,352,996,708,99,303,893,343,492,520,804,416,384,306,490,983,358,757,776,847,735,252,346,58,691,798,44,63,543,340,192,836,27,506,911,447,760,215,611,387,811,172,205,864,8,857,268,529,904,806,555,458,476,988,669,916,77,75,960,7,115,338,320,733,875,4,451,345,715,456,946,423,895,573,768,118,895,899,92,84,445,54,620,733,674,218,917,918,794,117,222,24,385,388,379,468,860,659,947,483,462,21,119,636,845,546,559,647,851,595,272,409,394,120,601,182,844,497,909,591,999,885,945,629,295,727,126,456,274,219,808,401,376,920,402,160,939,83,183,908,954,284,169,229,227,404,713,241,634,102,84,375,830,655,232,979,258,447,598,15,74,416,766,165,794,503,860,642,589,25,475,928,685,823,874,91,80,434,373,378,569,605,768,764,985,680,74,755,649,506,888,780,966,658,195,25,481,864,163,197,852,495,267,319,753,877,722,57,548,85,532,369,578,336,372,564,134,389,63,804,989,619,225,528,807,686,786,975,447,498,79,536,904,930,160,694,120,963,277,504,40,548,535,205,735,309,290,771,627,746,131,775,61,985,54,768,88,820,255,962,359,111,6,644,754,740,98,871,276,705,75,480,771,810,594,473,684,638,772,337,576,102,350,846,651,394,876,574,678,468,948,37,254,952,752,802,917,747,202,239,575,462,990,736,196,792,508,732,374,949,712,314,967,54,34,348,964,881,727,93,465,918,473,604,123,452,520,750,310,661,558,812,30,398,912,845,422,3,661,244,972,758,46,269,133,320,932,626,224,592,184,46,916,633,903,865,183,226,376,173,228,355,268,410,999,5,702,7,68,457,506,795,279,962,62,157,517,731,997,107,144,898,218,911,209,246,361,169,518,560,950,471,848,632,266,53,514,842,626,240,10,298,538,545,721,384,240,921,442,65,624,569,252,140,703,485,383,925,945,993,924,856,668,963,28,636,338,272,623,27,559,206,991,120,454,704,350,948,27,688,14,994,84,654,253,485,230,595,20,435,960,565,747,272,517,899,223,187,451,638,241,44,467,847,407,193,667,348,489,494,933,161,760,749,149,669,908,198,472,187,612,816,85,14,790,121,3,952,802,481,994,763,45,638,229,590,541,368,330,554,445,75,840,166,81,394,139,675,93,685,741,895,289,257,10,626,552,773,839,231,979,244,491,970,20,661,296,746,893,148,491,812,150,120,444,632,360,922,353,25,159,96,236,721,972,686,287,733,46,34,59,473,319,729,150,785,649,266,886,664,340,515,322,520,644,799,866,702,915,21,129,987,692,149,784,809,828,632,863,390,152,83,793,55,90,458,306,680,646,34,3,919,738,775,627,87,213,186,456,102,468,263,716,62,719,428,34,274,250,214,49,57,73,846,478,55,641,546,231,322,397,438,656,519,317,232,527,409,518,385,659,418,667,818,815,948,779,643,518,689,588,908,769,964,567,679,226,901,104,197,876,777,318,526,997,817,686,188,427,647,141,116,187,723,175,171,840,742,945,266,223,463,578,581,69,46,506,796,836,129,541,857,469,575,918,809,291,21,146,902,488,484,92,535,879,244,412,920,322,692,954,957,417,421,643,431,369,471,901,646,459,524,992,379,107,188,90,474,508,915,98,61,694,32,89,289,100,661,521,786,641,702,774,202,863,680,267,669,117,723,94,373,905,697,22,866,289,857,834,362,884,116,962,145,34,852,339,976,931,618,653,390,8,927,383,570,434,160,236,600,212,619,570,519,984,98,81,190,281,979,429,435,475,278,230,408,463,398,605,886,493,71,972,866,121,264,812,190,673,646,287,659,376,657,788,235,667,733,96,504,762,306,932,935,522,576,548,891,168,190,913,341,278,972,318,576,616,525,673,51,943,590,780,380,382,950,115,382,75,437,789,78,519,260,376,414,348,320,727,56,669,316,554,297,11,674,527,471,765,341,678,381,380,727,711,420,646,939,82,710,447,520,602,814,584,51,749,557,271,741,482,827,229,814,172,775,735,470,896,875,787,327,621,904,491,281,915,1000,458,400,89,519,405,317,201,238,15,418,142,675,0,152,560,747,718,939,589,380,140,491,317,265,686,520,655,346,319,861,442,774,647,751,509,640,256,319,156,31,348,814,324,411,728,403,272,288,62,125,36,66,338,556,994,753,369,94,991,551,652,133,854,875,621,368,204,82,166,121,726,979,899,895,174,416,737,874,114,663,714,404,388,161,280,38,811,421,834,584,269,241,35", + "521,672,138,408,77,392,209,538,933,167,737,788,726,680,976,401,953,275,76,994,581,640,962,393,270,569,820,894,536,735,832,704,410,143,48,633,947,319,242,668,931,766,293,92,41,481,845,764,836,750,151,987,506,7,18,966,736,902,722,588,784,965,331,707,404,434,779,679,358,815,540,476,610,873,573,995,962,760,414,251,214,891,177,850,489,369,978,440,630,804,204,736,813,12,684,256,578,283,606,575,492,838,478,502,4,432,460,488,691,75,137,111,513,776,491,58,697,670,601,819,80,89,573,635,187,653,853,105,136,206,759,240,938,234,296,922,252,773,993,883,669,835,424,623,834,2,881,120,673,395,997,232,11,42,798,518,585,637,771,550,472,728,539,739,278,962,690,886,998,100,882,65,492,446,293,800,273,91,997,499,718,839,280,54,889,446,759,690,271,91,594,849,508,476,41,474,984,632,706,683,137,360,503,606,92,901,39,357,293,477,987,318,861,55,436,667,937,809,882,985,202,694,874,385,240,424,415,817,42,202,716,511,83,364,636,586,874,821,649,407,33,38,387,76,166,559,83,17,779,508,230,281,917,36,385,205,396,607,716,202,814,395,810,156,511,412,571,280,770,11,127,486,397,377,789,225,597,538,266,985,846,929,788,73,877,268,279,385,903,194,403,175,625,539,311,864,838,707,969,365,547,365,766,959,166,355,702,950,33,729,266,996,929,946,241,313,626,543,436,794,915,125,425,364,408,722,488,435,835,707,305,792,776,233,470,548,22,212,114,87,704,7,295,490,146,756,560,288,230,853,181,869,114,123,259,359,182,227,735,868,312,86,445,139,434,695,933,297,215,145,429,252,718,953,175,816,92,452,979,378,721,826,396,546,75,992,583,171,498,426,457,90,864,15,183,988,566,436,433,251,277,14,955,929,157,938,487,927,233,861,508,134,724,509,667,760,129,74,8,260,843,581,769,542,467,282,338,399,480,839,858,863,628,29,300,870,48,431,164,394,20,413,764,216,926,728,849,651,438,795,929,386,248,941,898,762,79,925,961,613,762,900,85,495,268,473,454,307,313,213,266,543,130,529,506,984,409,432,247,879,686,530,483,671,29,624,823,377,989,969,481,553,646,816,864,718,237,581,33,47,118,144,989,125,536,422,748,864,466,435,652,486,353,218,351,251,706,195,602,879,958,921,177,812,821,622,830,140,552,97,366,232,541,969,289,577,469,966,13,301,378,568,263,313,693,458,93,543,64,449,825,217,949,363,429,781,775,29,627,422,883,745,992,606,439,286,684,522,448,401,773,328,757,796,733,133,421,712,632,283,890,803,544,424,326,325,597,857,288,760,517,180,693,869,736,465,178,132,961,909,153,450,88,196,981,547,646,351,201,828,621,58,347,276,429,448,298,543,993,737,820,58,795,953,975,911,743,240,537,757,486,288,447,866,611,538,84,116,670,62,612,410,788,18,384,259,792,33,933,183,530,151,452,615,654,702,507,977,918,762,474,743,155,979,802,448,194,660,204,952,844,760,432,829,781,724,225,728,619,152,273,969,115,240,919,544,545,639,429,270,220,452,580,534,689,576,492,55,867,504,397,805,987,943,488,710,127,10,813,704,235,304,804,765,633,967,200,558,934,558,554,953,957,174,469,680,836,202,829,955,295,960,724,429,621,967,553,986,396,509,850,402,291,435,596,934,880,288,905,819,190,887,465,238,290,381,376,342,600,690,687,297,181,48,895,866,976,381,265,791,787,52,865,351,602,717,564,664,212,354,874,613,31,469,534,585,201,472,289,566,986,13,872,682,4,100,595,176,596,810,121,533,374,554,929,59,917,900,378,944,196,390,641,985,963,798,46,946,839,712,394,360,658,608,190,471,866,76,667,356,653,384,425,974,193,592,10,301,386,27,100,33,526,989,778,382,148,859,931,471,633,372,208,349,199,14,590,369,113,432,908,123,307,20,105,667,696,190,801,779,463,430,627,893,21,449,170,964,841,835,276,166,963,830,976,13,50,304,852,255,149,709,280,528,43,551,843,98,340,573,89,280,675,520,170,20,845,694,128,641,195,269,912,937,795,143,371,730,143,152,0,72,375,366,779,611,316,397,194,939,453,338,347,301,273,224,494,718,492,61,651,935,618,901,602,761,496,924,720,596,353,435,113,39,388,333,965,288,982,929,700,473,994,281,789,422,23,867,834,471,731,100,881,700,390,582,177,843,993,827,975,372,599,263,267,909,251,290,408,566,857,916,691,351,129,549,114,220,529,972", + "254,902,965,739,961,569,545,76,296,626,160,301,74,773,578,187,880,799,963,642,285,329,181,837,103,742,592,255,337,302,809,640,930,228,304,380,550,602,856,126,64,529,60,225,345,863,974,928,656,791,541,614,538,385,853,938,751,712,977,311,859,745,338,632,851,233,917,171,905,205,464,512,49,302,991,625,764,393,51,250,662,283,398,399,399,823,17,785,803,630,738,478,654,176,877,827,587,680,44,912,516,5,392,881,953,372,56,695,36,570,652,130,525,732,392,674,81,649,892,638,572,914,842,210,602,426,387,674,950,740,995,695,157,586,95,381,145,899,341,244,244,157,5,514,651,719,263,284,220,761,863,151,508,869,525,775,940,899,868,682,605,573,826,202,558,161,647,367,318,538,426,760,73,565,657,704,597,974,451,786,971,288,348,965,117,354,45,32,234,910,339,716,775,687,437,867,290,36,384,350,53,643,719,875,989,858,546,534,317,170,87,431,126,142,222,236,791,392,619,623,895,129,809,460,331,787,678,19,539,22,789,418,249,181,37,306,999,702,890,770,19,393,797,504,827,357,115,225,300,841,287,469,303,892,733,180,894,635,898,438,564,862,771,867,706,995,485,364,636,734,919,193,306,899,762,385,341,311,489,602,933,90,307,96,825,316,12,260,983,575,524,91,977,719,574,964,640,663,529,97,880,487,262,865,326,718,367,861,250,640,584,686,166,705,248,455,235,368,660,114,214,421,668,495,886,516,917,757,310,606,467,356,872,542,357,614,491,415,975,27,375,945,221,811,385,889,465,570,355,383,887,114,918,620,570,289,101,32,28,623,800,113,705,587,247,470,7,246,546,343,571,514,299,614,338,419,750,281,278,871,571,841,937,946,566,492,753,740,224,589,407,4,189,346,702,288,108,688,816,463,913,286,467,895,929,921,936,9,396,531,879,594,961,972,6,672,599,171,884,989,711,901,754,124,606,550,705,275,316,473,596,770,87,269,870,250,326,220,844,825,907,669,375,690,798,998,900,7,484,812,843,764,356,249,122,327,623,656,148,205,592,634,381,30,716,247,70,208,417,549,753,621,500,745,59,800,747,217,457,738,256,149,903,68,448,748,790,842,495,688,407,92,800,5,760,32,206,634,160,864,84,936,775,117,409,693,473,362,730,223,26,473,287,995,312,523,977,283,204,952,93,352,258,595,160,482,523,108,667,922,111,22,287,862,330,634,949,724,717,137,881,786,84,855,218,36,709,794,813,20,204,459,680,378,648,327,825,522,250,189,252,616,513,885,979,397,694,982,386,207,691,916,770,143,253,94,687,789,587,664,746,703,611,119,404,739,678,435,394,742,75,596,773,341,873,803,882,257,830,903,54,811,292,816,366,190,287,255,526,656,457,154,730,246,818,783,389,574,10,595,146,384,381,616,319,550,568,16,672,457,671,839,504,149,584,570,897,491,81,391,760,376,230,525,923,314,330,94,923,657,284,97,926,405,427,208,463,369,22,821,177,67,634,595,497,914,450,344,103,347,200,773,962,173,97,4,24,295,995,147,394,400,986,918,67,129,144,888,21,846,646,366,261,667,208,659,888,568,913,411,772,871,873,593,168,929,840,464,138,426,174,23,968,57,231,141,951,406,109,30,844,140,312,119,365,257,587,706,218,325,816,387,505,580,933,529,270,306,381,968,715,517,352,723,809,269,753,779,92,452,945,699,74,855,682,471,377,916,25,546,503,85,417,814,17,983,209,226,231,843,261,919,853,975,959,660,47,177,668,795,610,604,408,235,370,105,52,804,997,160,688,615,905,329,648,196,107,43,24,613,276,691,45,33,438,980,184,988,363,764,442,168,409,486,976,600,900,687,924,419,450,659,169,333,498,74,962,616,366,745,560,199,227,397,295,154,403,477,607,867,408,169,254,378,886,723,190,563,341,676,852,446,120,296,519,391,872,159,969,977,453,811,572,653,378,266,736,134,172,647,626,292,875,504,390,440,806,926,396,348,964,901,991,573,534,764,339,412,275,868,202,880,727,991,946,568,602,334,824,166,128,410,538,980,14,911,372,382,572,399,98,341,638,356,945,100,473,943,52,560,72,0,784,584,350,115,818,670,97,592,344,734,201,445,110,493,872,470,826,850,945,780,48,883,44,441,261,302,245,29,700,246,910,694,588,93,488,221,171,103,515,195,565,49,353,278,332,180,142,941,310,240,574,858,863,509,59,234,143,240,761,564,563,176,600,68,704,532,13,767,611,951,467,659,62,808,559,588,657,560", + "215,22,727,799,778,650,229,257,878,436,374,947,441,809,449,757,231,159,785,374,476,504,881,52,401,638,563,445,575,838,776,129,272,979,333,834,939,266,707,210,844,912,684,484,386,288,24,624,834,858,586,352,218,751,358,858,85,561,233,936,735,924,101,976,547,801,661,817,386,919,754,760,775,897,945,458,913,273,462,190,607,25,856,535,72,844,435,553,488,491,861,197,499,743,752,739,995,782,174,149,884,998,219,331,808,957,803,810,833,922,96,975,434,427,272,46,684,445,937,351,306,433,368,467,905,395,686,266,456,125,410,258,930,207,847,502,400,268,762,332,33,246,609,579,852,60,45,594,84,951,53,558,159,361,408,696,588,350,295,190,368,901,303,408,545,444,292,988,590,536,186,871,791,469,450,599,779,130,819,739,373,501,29,366,357,316,47,330,819,402,262,375,523,787,237,530,963,793,450,933,543,817,438,924,375,676,521,928,695,550,247,767,282,133,222,831,232,316,800,359,350,245,765,410,193,369,175,31,947,846,153,476,407,719,158,586,131,87,976,181,590,800,941,478,570,818,843,936,998,815,42,363,920,43,280,665,931,105,505,716,430,142,75,568,189,78,655,935,290,622,384,194,327,548,181,726,281,956,299,828,602,873,6,250,184,430,687,578,242,771,515,95,884,855,785,162,23,746,432,641,811,509,202,479,107,721,394,764,737,617,573,2,444,518,285,293,837,846,555,203,599,937,526,316,825,148,721,767,893,610,817,451,478,333,632,880,176,585,288,359,451,939,447,744,852,627,426,119,14,444,511,258,584,432,635,728,39,743,266,277,840,214,85,264,255,68,847,245,650,572,697,404,591,421,30,193,942,752,868,467,410,422,546,38,897,139,858,968,994,215,915,120,687,342,270,534,469,370,208,190,990,671,620,586,677,778,851,418,114,793,664,571,976,239,856,932,722,857,917,828,493,959,949,334,876,465,626,310,380,841,355,61,356,54,149,93,921,352,874,772,469,805,409,967,681,101,469,959,120,368,287,144,603,654,612,675,371,600,718,499,922,495,286,295,408,776,800,352,599,703,480,114,738,566,910,943,344,111,809,964,320,433,278,727,105,534,122,715,556,967,473,313,420,826,546,396,988,253,516,373,694,822,71,688,911,302,35,187,196,194,423,959,774,189,96,137,357,941,390,861,737,991,297,211,521,394,498,701,608,662,894,950,444,177,279,746,44,42,268,800,32,96,840,359,34,675,442,628,60,887,28,548,964,85,109,495,401,308,905,933,741,719,218,657,237,255,907,117,395,817,704,115,779,528,282,348,851,860,434,560,473,273,612,269,941,205,704,998,82,744,250,486,631,453,283,141,280,218,821,248,727,208,256,619,8,386,112,813,255,145,957,409,787,257,139,861,882,190,79,924,538,601,617,676,261,801,52,588,158,463,967,245,83,635,966,716,320,857,870,900,318,654,743,42,366,767,421,129,721,521,750,418,715,496,685,691,688,215,343,521,263,376,82,40,897,264,539,83,360,79,143,996,615,130,164,416,230,804,388,211,117,942,140,862,809,888,780,808,430,25,806,840,477,579,331,679,862,430,37,323,331,938,857,67,631,833,830,407,720,179,696,869,378,82,133,979,447,810,401,242,108,812,633,256,751,894,203,158,671,212,327,963,703,946,993,885,838,577,455,46,251,560,949,254,61,813,696,460,628,527,434,831,349,149,727,876,529,735,636,52,54,943,139,355,93,918,337,462,957,956,654,375,138,714,829,496,366,982,503,383,746,753,514,197,269,729,97,473,554,715,705,454,1,408,568,113,850,699,536,207,457,530,63,523,239,916,264,628,485,200,944,197,910,357,228,414,658,514,576,348,61,435,758,86,761,322,928,346,789,968,768,826,706,917,229,931,326,395,679,655,346,884,127,953,227,631,139,146,744,83,732,229,829,618,606,754,427,546,563,514,483,205,468,2,184,925,472,971,342,784,859,572,78,459,347,668,953,484,110,379,303,41,548,618,984,365,358,103,692,956,361,851,545,399,308,121,426,501,621,925,635,972,900,788,892,440,748,497,182,466,679,409,459,834,650,632,738,338,949,747,375,784,0,993,670,515,770,902,38,973,708,267,667,419,762,966,116,647,780,94,615,722,174,619,768,256,366,951,147,982,329,512,755,413,958,566,748,395,368,583,336,75,789,653,131,667,108,675,492,692,2,328,829,345,193,547,136,116,797,701,221,886,802,764,257,877,533,41,362,262,288,192,987,376,40,474,492,744,702,297", + "559,352,270,175,84,117,847,554,683,213,154,6,833,901,136,294,600,678,740,593,714,75,851,307,740,112,534,887,803,618,632,968,59,972,103,395,551,312,569,737,90,139,21,452,100,260,591,285,112,531,641,484,724,855,809,592,234,22,157,253,924,982,658,311,205,290,657,534,296,975,907,563,719,746,418,920,352,839,852,441,175,35,241,419,30,992,68,888,503,722,466,972,53,413,946,397,316,189,676,837,450,71,250,708,699,124,531,950,450,53,540,604,810,235,570,774,790,151,624,898,621,235,679,282,915,614,629,635,920,366,907,698,34,494,803,686,747,26,288,270,986,515,71,490,849,355,847,281,259,477,485,886,609,229,518,730,691,538,135,503,939,891,656,678,454,491,964,532,226,109,846,328,235,625,201,611,852,308,73,208,532,564,499,979,298,196,332,358,399,54,722,47,599,369,188,213,541,847,855,925,269,865,992,750,23,593,647,445,626,214,636,500,569,240,269,576,750,300,289,993,347,15,263,14,667,134,680,558,87,821,785,496,484,520,347,911,142,457,615,338,845,758,381,677,777,495,569,739,123,255,559,99,888,433,287,144,432,960,934,573,898,328,345,738,467,574,492,449,381,718,656,356,992,264,112,184,35,580,537,504,394,744,395,986,866,434,573,187,203,750,690,78,101,84,342,291,633,366,154,590,369,382,62,323,545,236,909,381,121,260,548,421,208,824,359,329,742,414,532,430,686,12,516,181,648,290,869,55,244,58,604,793,62,838,439,667,310,284,358,643,273,336,345,971,452,254,41,148,350,220,626,796,572,398,423,698,124,487,504,667,952,258,348,905,967,432,717,371,535,121,828,185,793,8,824,232,87,75,75,706,556,508,450,993,544,910,888,658,232,630,243,318,386,204,100,126,719,96,355,717,348,38,926,948,330,765,661,346,449,45,744,647,960,118,896,118,768,611,7,310,27,389,668,235,572,519,669,40,482,738,845,812,122,601,894,836,425,350,311,881,419,701,405,277,452,58,78,840,216,734,949,40,846,824,264,200,98,797,980,810,246,398,759,652,931,424,704,154,184,367,210,773,335,54,372,254,125,17,307,604,177,860,54,547,854,383,80,552,716,544,403,319,397,913,895,909,710,866,46,826,309,596,505,121,677,629,606,191,297,402,759,555,868,266,348,809,112,146,819,291,346,163,42,273,733,210,640,423,445,318,423,264,976,587,482,231,593,286,724,899,713,46,337,792,655,900,772,845,752,74,486,734,325,602,388,107,702,313,293,879,845,471,218,139,287,792,679,232,634,630,598,7,912,461,910,542,172,471,275,132,633,388,745,230,324,399,340,575,419,315,317,553,986,907,124,511,533,69,963,869,63,50,491,239,289,909,769,776,885,202,373,229,319,63,351,746,122,779,21,555,463,931,236,931,408,772,210,578,582,617,58,125,291,89,764,286,408,123,625,599,454,484,555,916,673,996,897,344,400,75,471,574,281,310,801,905,757,728,788,268,980,445,756,100,13,729,951,563,199,479,104,661,798,215,982,851,816,233,674,214,152,874,386,401,758,511,181,562,621,839,436,113,327,166,590,597,715,423,272,322,882,309,122,831,920,792,886,161,919,401,281,636,889,446,852,889,54,640,496,937,165,974,691,815,462,841,364,896,257,658,635,952,156,654,397,95,890,27,203,800,941,152,784,154,525,155,244,708,321,917,388,614,559,480,530,729,91,130,58,508,459,943,958,960,23,181,521,497,529,938,324,205,296,759,245,951,304,546,950,81,659,652,124,189,278,125,311,417,395,619,300,579,379,646,63,966,866,500,38,603,945,371,205,698,145,125,35,670,489,658,401,475,28,158,219,548,574,255,473,996,295,734,220,515,43,861,656,94,63,651,143,500,825,346,600,393,346,14,938,820,287,35,225,744,605,17,467,774,495,511,927,364,527,154,241,140,833,324,828,502,715,754,94,542,377,346,41,39,395,430,921,138,281,296,979,355,478,418,563,254,988,186,373,489,69,357,648,845,468,178,712,532,338,557,920,127,929,690,628,348,736,800,451,625,560,521,968,542,522,594,413,499,551,856,674,259,799,501,918,718,366,584,993,0,602,543,713,255,864,370,936,393,811,677,64,771,496,996,920,597,705,945,185,430,554,493,552,924,917,456,990,134,526,511,615,942,165,850,853,846,819,359,274,176,859,606,980,473,256,397,573,39,679,474,218,811,851,535,763,766,513,638,884,201,998,726,362,726,746,768,224,279,722,652,551,67,399,797,832,130", + "184,970,191,752,857,589,542,170,909,460,921,945,296,116,685,968,36,227,137,445,724,306,892,353,332,511,304,51,375,43,860,489,142,809,997,655,224,103,71,217,668,560,463,895,703,848,875,742,50,595,27,366,154,682,196,605,259,976,624,293,567,513,270,101,408,396,531,774,795,852,530,839,99,376,51,611,111,352,943,360,829,936,905,704,16,597,424,373,313,76,467,848,771,725,402,288,239,966,867,990,787,276,694,961,422,179,359,850,848,951,781,707,588,827,747,856,321,196,264,187,260,807,81,960,90,397,675,745,685,571,90,805,595,714,549,219,607,547,994,353,488,310,100,656,476,430,993,570,399,916,199,40,772,895,734,564,613,39,28,89,712,768,435,881,499,105,620,434,610,401,83,319,656,409,948,241,786,436,182,453,608,785,953,334,76,523,606,886,30,574,175,525,476,438,461,592,650,669,996,400,543,748,819,297,470,510,864,324,383,146,97,136,111,720,905,701,607,501,348,739,290,795,300,810,458,388,331,712,582,454,683,331,18,130,74,764,241,245,844,125,77,826,192,273,663,748,315,789,761,581,638,884,614,442,517,816,720,17,597,277,130,546,144,115,725,378,154,925,57,19,939,60,375,516,187,555,62,570,908,637,484,728,345,873,483,889,338,887,410,71,485,462,109,634,975,221,700,390,549,932,905,132,427,445,361,950,315,305,465,503,126,760,562,142,573,368,78,840,473,482,355,500,231,773,782,942,129,751,226,957,151,205,586,976,165,416,730,903,608,143,880,730,34,5,424,144,56,891,280,472,157,549,482,498,48,331,173,81,839,939,595,289,860,343,308,614,561,671,131,949,625,543,600,44,797,611,399,60,649,349,100,195,122,626,918,631,158,363,296,48,674,458,477,23,205,257,887,210,480,460,168,658,938,984,926,608,808,531,129,49,577,205,743,896,152,182,123,235,764,234,393,700,478,831,864,873,844,395,834,858,855,372,451,308,103,338,961,816,444,104,697,382,797,911,687,549,890,801,138,495,904,177,132,247,908,632,11,341,496,48,943,924,797,882,73,701,986,101,110,516,488,57,396,34,999,588,993,807,829,178,415,12,418,565,542,903,16,19,297,88,588,374,141,545,939,488,343,182,945,64,601,592,143,823,222,821,551,162,938,993,714,396,379,656,125,721,467,186,820,550,358,756,815,440,212,764,588,623,202,42,247,271,565,695,413,656,35,471,478,719,73,453,985,922,535,888,841,646,330,895,798,439,3,744,850,315,337,51,348,14,740,345,280,566,10,424,688,508,839,68,764,282,594,951,42,460,59,368,539,609,734,294,333,956,969,369,905,528,828,228,409,274,15,723,926,815,364,416,667,859,731,283,487,881,773,719,818,143,21,85,859,69,195,759,865,163,141,905,700,791,798,146,87,431,392,804,670,461,878,520,974,806,688,995,177,460,38,18,712,377,935,995,509,546,385,336,184,33,899,180,347,273,743,424,42,1000,61,658,63,282,329,854,959,613,257,967,854,23,143,594,628,348,400,95,239,955,6,291,486,435,891,378,26,178,876,398,635,818,729,225,979,543,76,113,33,673,731,506,198,63,7,726,514,209,902,930,227,443,707,508,553,708,905,188,970,661,738,774,584,646,616,852,359,133,998,784,386,60,742,392,666,206,128,819,651,881,629,766,333,610,469,666,751,273,747,185,893,406,197,464,678,737,801,946,8,272,651,801,386,628,579,167,137,43,502,256,733,339,93,464,57,398,164,479,331,593,682,515,852,485,110,983,316,894,773,46,330,1000,128,146,682,610,919,944,718,728,111,990,727,957,817,350,763,988,400,240,774,267,111,57,487,849,917,831,736,283,664,586,187,21,469,916,607,150,951,805,474,892,676,754,581,313,559,920,456,18,227,121,751,535,538,856,91,954,275,500,426,524,76,963,582,326,988,651,390,642,170,322,845,676,836,641,956,374,324,417,460,12,176,643,78,232,624,324,616,467,801,978,405,656,662,210,461,83,791,904,847,896,242,411,615,840,31,726,274,902,525,847,377,777,270,799,977,156,82,876,708,35,259,438,517,610,547,522,417,567,307,197,186,939,779,350,670,602,0,599,368,887,919,733,446,795,514,534,515,534,103,706,85,428,347,109,906,365,715,418,901,148,973,935,957,278,74,624,355,55,557,441,813,187,575,541,377,445,514,706,801,632,466,101,692,103,31,678,520,781,379,256,680,447,634,153,543,457,766,221,958,382,523,514,399,290,942,145,113,136,586,245,64,947", + "805,140,780,288,877,546,484,815,928,34,531,40,69,93,148,252,528,626,249,470,721,69,923,110,17,979,416,819,944,619,822,998,909,818,263,90,440,294,46,211,406,603,598,244,603,850,381,740,937,813,432,935,774,113,598,209,605,238,597,352,415,900,327,882,326,194,531,156,746,210,561,841,824,418,975,836,135,960,695,784,319,9,297,280,101,610,75,16,596,871,803,66,259,665,968,437,815,731,982,251,437,656,846,146,83,100,54,496,928,231,213,169,218,39,664,391,15,815,719,357,158,944,538,611,706,114,859,189,499,763,891,335,454,624,736,8,926,404,380,866,182,672,362,304,436,319,811,420,233,4,172,296,692,82,663,714,332,969,845,461,884,971,183,311,85,5,491,598,471,874,966,597,87,94,219,747,780,906,974,383,384,381,928,494,691,503,52,917,124,241,781,846,18,125,485,941,429,479,345,201,702,35,279,872,178,888,496,986,194,298,40,962,352,105,141,607,751,747,985,696,321,701,910,881,592,4,984,601,370,714,761,675,539,897,12,452,356,447,234,152,575,134,892,421,852,449,296,725,586,308,631,235,161,796,455,235,742,715,712,228,375,952,390,847,253,733,644,847,656,565,834,579,650,468,640,963,110,120,6,243,34,590,340,2,393,808,916,668,971,693,270,349,304,136,702,890,140,619,784,417,802,584,858,752,208,540,112,70,707,181,161,343,653,953,113,339,999,86,600,223,578,14,127,300,229,969,808,31,696,473,205,675,825,956,885,469,488,22,33,600,332,4,492,934,10,768,288,607,587,806,346,601,609,631,116,149,48,982,941,522,759,26,819,34,564,973,788,60,584,50,151,660,873,610,145,781,40,82,315,464,957,526,202,559,135,809,982,389,924,441,289,953,158,836,327,690,175,571,569,609,539,709,885,538,881,799,83,402,145,393,965,722,429,744,605,535,239,429,290,229,858,716,134,1000,51,460,626,854,773,149,437,409,565,225,409,67,50,934,667,529,761,70,107,284,622,527,380,122,501,619,257,248,925,264,728,132,645,281,946,191,412,764,303,899,36,929,744,26,947,166,217,101,299,147,411,265,583,469,265,230,646,479,506,94,287,289,845,549,907,71,889,769,774,9,68,429,884,125,287,345,585,205,292,33,68,68,909,693,896,956,230,428,819,811,83,519,504,313,66,156,925,921,332,16,565,238,685,652,592,77,204,348,864,702,782,474,675,879,374,451,125,184,591,949,826,497,122,152,340,89,827,771,388,535,204,74,730,642,268,567,720,831,884,931,662,841,107,509,800,970,728,153,371,296,726,271,904,413,732,208,207,853,145,991,441,143,783,779,898,269,778,193,343,195,825,861,340,906,569,292,290,255,438,863,728,421,474,774,912,857,57,981,465,856,941,338,586,754,114,492,909,402,604,829,694,279,543,705,506,444,241,575,81,687,34,146,168,697,313,966,316,415,20,137,975,816,210,531,377,874,629,933,663,5,371,175,402,372,569,435,15,747,738,427,607,178,344,101,341,731,565,879,538,459,258,210,252,747,702,701,911,917,225,426,198,753,407,334,29,36,128,470,463,172,393,69,710,542,748,7,93,406,110,57,53,99,908,870,766,860,81,320,964,19,141,165,301,297,587,270,896,638,229,106,793,849,157,726,395,834,389,410,756,560,754,805,18,636,899,90,651,519,748,230,810,487,423,605,720,38,732,680,983,109,956,98,322,544,909,487,35,748,936,432,687,793,890,539,244,548,240,166,851,124,526,693,816,920,215,209,799,145,573,445,271,402,822,873,506,823,67,254,955,114,764,286,305,446,384,151,572,555,374,903,727,909,348,251,137,382,800,654,494,340,500,830,668,299,535,843,476,413,146,492,3,91,666,522,957,98,328,50,632,765,595,427,187,701,658,642,329,457,164,663,225,582,330,770,959,37,957,223,74,997,665,890,41,309,118,94,605,254,674,415,154,873,845,576,239,198,697,645,835,552,677,455,641,459,235,144,717,920,674,871,274,275,494,145,101,475,531,588,637,908,596,85,58,990,10,936,820,76,294,804,521,742,377,895,606,7,50,696,27,718,914,742,790,225,981,589,611,115,515,543,599,0,274,560,252,622,217,169,975,471,589,816,970,581,876,138,798,759,202,673,422,242,149,881,835,521,862,654,14,117,614,706,141,266,134,864,54,807,112,41,691,980,621,61,956,203,445,267,513,472,384,227,252,309,923,961,944,508,331,283,486,478,200,284,924,355,378,780,796,372,491,532,669,629,774,814", + "737,513,59,861,378,981,350,886,555,753,412,611,896,356,789,581,284,255,484,920,543,466,662,187,707,819,810,129,722,562,995,757,247,657,508,854,209,759,396,544,779,663,217,689,376,384,445,917,516,677,587,551,497,78,508,380,858,963,958,928,786,493,596,825,819,422,742,761,103,708,488,653,991,790,757,45,497,610,750,205,919,442,157,598,85,951,152,483,977,808,419,211,443,565,853,165,96,725,149,486,979,403,407,82,109,94,143,565,415,93,41,957,139,270,122,669,608,752,434,393,111,789,290,79,280,319,236,555,637,252,947,734,897,656,144,12,520,964,369,874,581,592,877,751,193,877,98,118,488,145,982,887,123,227,590,974,704,375,231,920,152,5,287,472,625,422,476,718,405,950,150,21,537,749,218,176,63,427,51,259,88,475,757,887,175,150,569,608,36,666,595,997,397,713,238,130,210,614,52,282,946,768,915,386,437,520,988,639,57,251,432,924,311,437,944,982,446,893,758,627,12,630,89,828,605,37,828,347,509,524,829,803,353,578,493,496,561,707,715,842,882,405,91,297,278,412,418,392,408,611,556,85,833,787,388,631,295,96,78,42,864,973,970,87,362,531,372,729,712,830,43,141,497,762,486,628,270,187,512,337,696,818,490,653,404,869,28,423,107,57,916,844,491,842,880,539,691,71,153,790,461,483,853,390,592,563,266,602,158,888,341,740,435,44,514,664,366,484,995,292,382,361,142,117,561,901,482,727,985,952,136,239,151,55,544,499,327,38,29,957,190,728,573,530,867,890,359,532,730,252,57,946,649,388,419,773,901,400,323,958,416,500,571,235,529,631,131,850,168,875,203,779,926,403,464,437,701,512,783,385,9,159,51,289,698,970,859,434,480,196,293,236,187,9,439,160,669,725,569,328,502,732,840,967,291,385,899,71,670,684,303,602,470,874,337,238,585,530,801,465,857,889,219,542,549,373,271,551,865,623,316,822,716,300,429,242,993,206,24,160,573,901,736,813,654,364,857,142,531,482,325,178,7,651,922,984,251,43,852,235,829,25,180,580,175,960,3,101,23,106,145,970,924,882,301,153,206,876,562,976,979,266,773,417,768,67,960,192,397,538,212,195,682,691,100,227,443,236,726,552,286,234,406,366,192,858,90,773,377,69,470,933,172,783,303,66,903,727,286,461,375,26,795,381,723,702,362,889,421,284,931,206,259,849,1000,683,516,945,187,89,317,813,20,381,835,802,777,556,388,218,399,394,3,877,230,192,312,441,407,959,977,521,117,637,289,320,228,683,660,10,960,257,584,930,604,741,2,738,707,635,495,888,694,498,389,639,335,131,373,398,788,534,437,836,135,59,848,501,602,821,134,454,725,758,829,859,551,281,956,282,270,476,452,206,634,134,427,177,945,671,430,140,331,81,905,919,106,335,860,625,150,671,39,675,985,208,351,557,378,612,44,492,707,574,314,345,611,140,657,90,440,647,752,433,596,338,25,788,5,36,838,962,640,798,979,978,354,75,736,831,340,569,297,73,166,286,171,895,733,198,162,7,247,250,664,84,505,832,212,881,738,396,568,657,623,58,86,719,112,178,371,107,100,384,198,671,583,843,892,203,475,434,113,327,37,873,225,489,874,59,715,462,272,899,937,870,694,35,388,457,827,209,675,994,459,653,307,769,104,26,661,513,86,622,966,511,182,262,879,67,597,237,148,783,108,681,3,256,768,838,789,950,383,824,819,269,817,682,968,358,392,411,558,309,782,112,397,340,575,841,607,748,45,982,236,944,66,569,78,222,249,95,200,797,951,881,21,579,565,932,505,705,325,821,210,232,471,283,594,173,675,475,412,708,795,718,149,631,232,834,818,307,253,929,887,165,634,80,562,813,339,38,630,792,976,148,265,663,177,257,688,76,869,424,847,789,896,802,43,397,986,348,570,20,914,404,794,589,581,976,13,643,153,55,774,228,24,83,520,170,66,990,858,949,121,706,339,704,502,483,314,804,20,187,87,795,660,597,825,628,192,477,416,317,578,685,839,936,992,590,232,114,564,264,255,359,1000,570,267,166,566,221,694,90,82,664,947,891,801,380,316,818,770,713,368,274,0,585,919,300,952,687,262,714,572,752,119,713,801,4,581,349,453,213,580,959,682,351,865,846,347,957,253,96,918,974,833,92,22,567,121,37,328,27,751,387,603,926,846,67,827,570,932,281,814,172,354,845,161,357,637,197,830,897,357,260,709,320,194,769,826,161,625,915,843,997,950,44,897,724", + "774,198,213,39,987,572,678,334,662,14,878,907,595,155,974,759,785,159,89,356,342,719,956,617,675,569,471,476,101,961,173,573,527,471,134,307,44,721,556,382,7,380,782,370,121,303,508,630,30,718,178,872,736,967,972,82,410,745,20,111,779,424,375,117,490,459,593,131,664,967,119,356,835,800,572,8,770,314,968,89,161,713,197,840,572,631,199,847,54,509,402,923,969,760,36,194,174,755,602,167,531,248,43,708,922,310,29,364,949,727,65,969,340,578,66,467,444,913,441,534,549,382,737,161,614,633,252,259,562,582,349,500,746,32,877,907,621,458,541,902,482,791,180,710,836,705,599,67,833,535,411,733,35,988,488,493,559,519,972,546,799,927,273,13,90,142,116,920,632,946,70,43,644,112,64,67,544,392,451,730,181,199,719,932,304,44,461,725,145,547,113,429,697,218,861,924,897,3,451,731,584,749,395,707,536,10,988,329,366,837,391,663,258,645,105,611,762,35,956,646,127,860,236,555,232,922,671,261,908,275,940,940,532,700,904,769,822,126,115,992,989,591,541,201,66,49,619,710,859,332,168,639,854,544,50,479,635,960,413,370,262,272,138,168,794,707,118,666,892,845,386,252,637,409,646,690,434,589,395,551,872,616,976,224,518,126,973,175,833,965,468,185,908,671,16,318,387,267,546,485,944,825,395,329,472,766,352,481,725,868,344,907,862,9,174,966,235,657,562,55,802,555,105,869,722,748,975,234,761,187,659,42,832,236,637,178,636,754,805,859,280,800,422,652,356,780,605,157,233,861,326,137,67,192,955,828,167,466,174,787,698,677,611,180,200,158,790,663,165,256,460,584,652,137,851,197,301,644,857,62,404,971,677,183,941,861,683,104,125,515,158,709,163,215,764,556,108,172,70,14,615,972,117,759,394,668,100,192,390,220,5,804,529,313,148,996,283,457,638,791,575,621,425,95,35,732,825,306,209,502,599,588,819,36,613,112,802,205,586,13,173,789,308,801,34,903,423,617,802,846,890,816,8,226,965,781,778,578,480,561,986,144,217,233,819,731,347,346,669,117,915,337,62,920,600,254,601,38,828,133,842,810,695,789,180,211,613,241,527,755,720,778,291,446,190,567,439,423,987,863,200,424,769,317,140,540,453,912,929,547,142,64,34,861,807,741,370,973,535,397,786,246,905,135,350,29,321,328,135,459,986,966,44,671,471,196,778,99,284,240,344,494,519,822,792,70,582,607,896,401,235,191,21,302,448,473,42,720,965,987,128,124,958,201,477,531,395,732,819,587,388,991,819,619,982,105,258,783,613,621,412,909,320,86,781,229,759,62,591,421,566,260,847,549,731,361,629,789,103,852,851,398,999,516,940,635,108,35,286,8,241,707,369,160,417,991,149,707,29,681,328,85,27,193,196,392,120,82,311,581,218,795,318,793,417,184,693,665,248,627,425,10,318,499,988,314,669,792,915,920,139,813,825,105,333,336,533,373,854,501,914,944,714,953,25,656,795,111,87,293,324,635,781,732,165,212,515,823,150,293,899,473,820,685,956,987,881,618,752,132,638,174,77,238,935,196,669,463,90,417,162,366,556,655,12,425,231,607,957,840,23,380,613,548,586,628,696,812,992,837,865,684,812,532,638,294,754,232,92,421,416,835,288,153,41,466,597,470,884,978,776,818,323,689,78,801,72,472,609,994,930,10,337,412,581,983,430,521,887,428,266,70,781,188,416,226,421,131,46,122,358,686,603,747,621,171,497,930,769,963,635,938,138,762,646,812,843,846,12,658,269,923,543,762,577,493,374,276,919,902,322,861,359,541,83,116,298,428,23,92,719,568,760,821,901,571,570,87,736,862,324,561,348,19,85,921,335,942,673,831,155,668,123,515,746,658,665,970,272,931,293,218,603,667,968,36,563,269,194,952,48,57,336,674,869,971,703,232,469,761,918,678,244,752,554,973,594,266,686,733,391,307,746,793,975,569,554,104,781,342,557,969,71,895,968,830,311,392,386,903,759,466,822,327,97,627,29,953,243,963,641,271,760,129,304,609,280,594,6,385,320,448,945,677,349,702,118,353,711,140,397,670,902,255,887,560,585,0,824,596,585,443,140,114,37,705,131,272,29,945,649,809,824,962,980,177,519,933,919,400,559,934,130,224,780,9,279,786,834,697,763,492,49,783,626,153,371,845,442,647,262,875,871,673,905,285,970,626,574,339,725,283,254,903,541,381,500,859,529,632,911,351,940,152,774,61,118,616,766,519", + "661,595,694,40,612,213,98,878,809,142,387,214,33,936,534,997,581,979,91,843,15,323,725,668,569,869,547,890,228,578,817,673,78,780,309,94,853,936,251,568,892,568,640,817,657,219,617,970,186,389,670,127,570,225,376,228,591,912,775,343,985,967,747,906,590,411,347,524,102,858,901,570,191,645,617,485,716,752,59,167,688,632,951,897,929,756,584,88,509,728,361,578,638,80,838,598,852,929,200,135,957,91,67,275,14,499,119,893,775,161,370,374,565,982,817,619,733,311,745,948,400,442,446,391,274,903,509,151,962,192,516,619,563,442,996,410,497,850,702,317,918,623,187,169,572,256,38,608,178,168,98,182,877,68,2,10,592,424,862,665,464,865,115,35,542,138,202,505,258,425,817,816,837,183,704,152,876,376,319,445,803,452,630,33,882,747,646,417,854,212,884,376,318,248,558,519,255,431,742,47,238,355,956,815,561,957,727,480,437,98,387,896,682,834,141,785,6,66,538,643,422,839,160,587,468,219,516,83,789,682,832,658,376,388,850,704,821,971,385,483,893,585,300,410,209,516,552,759,184,490,729,332,68,906,617,708,475,397,307,907,264,557,450,569,968,89,604,928,623,508,564,371,127,270,150,163,310,781,430,555,26,935,545,727,561,689,201,110,398,281,544,660,613,575,171,916,246,254,537,756,773,253,148,855,630,645,287,442,58,777,853,563,807,276,653,102,38,234,761,859,396,162,8,473,56,123,365,982,580,45,131,908,702,766,617,275,739,483,979,452,326,468,99,553,579,734,328,234,458,520,103,800,265,547,146,92,222,113,328,812,999,86,707,407,241,660,773,665,587,121,941,99,623,359,598,645,850,728,775,606,666,704,296,78,799,478,768,746,326,546,223,521,960,830,490,165,491,651,115,577,178,449,712,340,438,971,752,103,526,492,538,362,164,37,746,450,898,527,974,605,533,625,469,81,366,241,939,78,664,728,274,657,848,726,259,980,3,370,236,133,566,12,369,10,925,993,34,32,886,764,401,387,795,966,114,931,747,862,392,59,760,661,94,905,475,113,387,509,423,333,799,251,990,139,892,117,520,458,181,996,546,971,415,366,399,725,87,150,737,559,361,783,484,569,213,59,558,781,258,312,871,298,823,998,645,213,14,851,665,566,820,675,551,442,738,7,493,665,331,54,655,658,102,99,855,657,758,234,324,72,847,108,726,303,920,279,85,706,739,164,26,582,727,651,570,81,803,137,947,467,487,451,767,338,149,430,937,54,915,492,13,520,472,645,914,81,923,674,623,148,855,401,531,502,176,986,278,221,525,706,583,352,915,116,861,405,14,609,617,386,548,203,733,293,402,664,310,517,885,307,474,374,684,102,863,52,867,524,81,434,769,236,721,714,496,608,192,812,745,352,707,353,681,725,244,826,321,842,984,91,475,105,621,467,798,330,497,358,245,17,263,430,168,766,308,901,767,381,490,587,730,494,54,593,71,450,977,276,181,636,314,665,362,630,676,666,329,511,636,544,745,716,582,798,993,448,881,63,61,432,890,701,324,82,686,871,992,821,435,675,521,967,315,976,691,511,138,945,264,93,50,474,378,294,282,676,574,897,657,27,657,764,47,668,123,952,820,98,686,800,166,679,10,489,307,801,563,621,710,350,17,432,707,630,608,248,433,291,246,347,926,832,218,150,709,994,630,106,276,553,195,941,780,430,92,320,728,337,240,651,62,735,609,392,270,616,619,836,512,226,780,567,661,97,888,105,319,152,796,500,194,833,700,694,55,10,553,354,388,779,990,40,167,170,879,550,141,300,26,49,735,208,521,854,79,838,573,318,410,44,434,199,744,702,577,343,464,858,571,296,855,658,230,331,312,347,168,728,196,813,280,593,826,926,903,900,550,208,889,501,686,595,496,466,64,976,677,939,420,648,805,298,49,14,487,722,13,515,570,679,52,516,762,340,386,922,409,245,411,756,588,721,527,699,966,677,519,789,502,734,913,719,739,949,386,670,213,874,825,986,126,334,788,654,432,418,479,253,835,198,805,651,300,183,827,748,151,145,358,854,979,114,512,811,526,33,260,192,136,491,194,97,38,864,919,252,919,824,0,288,97,717,36,613,471,928,281,880,158,342,822,446,140,758,281,953,934,773,978,404,762,443,717,757,429,460,45,461,51,151,138,979,441,688,400,439,282,981,100,695,168,871,630,884,675,36,195,325,102,106,268,759,962,423,200,20,996,871,644,297,481,815,211,631,988,86,33,580,571,243", + "784,85,381,346,313,572,302,421,410,362,444,218,880,168,697,495,481,364,170,110,430,401,849,570,589,719,572,540,161,225,952,339,151,137,853,758,96,940,619,409,828,23,138,260,701,337,632,14,965,273,348,307,834,51,116,146,829,961,331,887,406,194,220,271,363,425,365,787,92,119,363,616,807,21,295,465,843,997,194,240,537,152,916,291,583,242,19,628,596,670,902,754,575,209,579,310,584,482,276,301,894,257,587,700,847,572,125,30,106,509,623,86,581,408,913,556,694,388,937,64,467,969,100,608,41,721,164,389,836,521,562,812,433,79,424,161,550,805,805,997,335,331,444,462,966,858,372,515,761,7,833,600,714,37,760,299,713,726,330,895,26,149,630,129,853,683,913,930,701,913,537,896,744,956,639,211,579,509,959,699,828,437,300,686,257,824,415,122,527,504,312,781,831,541,844,893,421,889,146,588,131,227,244,599,609,943,891,883,503,524,648,501,739,268,60,734,987,850,869,516,393,620,584,249,837,252,242,865,947,393,572,773,394,773,314,476,46,172,439,708,114,559,5,523,275,847,724,960,376,689,741,355,608,145,526,743,558,119,206,261,944,562,950,500,361,662,818,518,59,597,260,160,855,483,203,641,808,310,589,579,804,356,762,437,794,137,381,697,942,175,746,968,652,307,232,597,768,93,776,681,9,822,542,290,449,672,138,150,891,15,946,510,620,442,83,869,197,69,813,763,516,208,380,811,790,397,646,587,987,323,589,951,561,459,69,517,989,84,535,919,265,409,737,875,593,564,243,902,573,77,482,478,685,157,896,24,230,408,480,604,832,471,877,336,927,329,83,808,643,393,112,41,730,600,957,221,1000,698,7,512,105,621,638,658,652,6,308,604,172,35,297,115,47,922,505,441,963,989,674,717,126,396,737,562,42,396,221,924,985,164,149,677,825,76,352,531,80,147,767,90,674,444,517,468,311,343,377,199,332,209,471,121,756,251,994,394,675,977,168,514,97,31,199,55,647,163,337,228,517,47,30,673,404,388,643,708,635,124,547,759,599,309,907,151,917,968,945,1,152,343,958,784,15,485,99,174,156,480,412,849,20,185,610,886,53,116,397,859,783,738,789,810,993,55,511,485,726,284,442,848,186,889,700,183,3,127,992,681,500,304,430,936,845,285,646,127,677,923,474,734,558,219,239,388,446,109,569,575,876,3,690,625,750,193,486,429,718,693,364,773,192,140,695,596,919,934,427,966,934,484,873,389,686,953,139,309,458,333,382,424,295,811,775,384,251,7,365,838,440,908,563,903,628,424,793,960,694,433,154,182,257,772,366,804,368,623,900,570,598,980,738,968,695,112,481,182,123,948,36,481,82,520,411,846,35,273,29,638,262,744,262,982,992,975,833,909,24,792,909,423,950,779,465,806,136,503,839,236,970,257,2,915,196,713,202,14,252,506,985,26,564,718,628,680,540,869,45,362,104,693,763,513,817,11,65,611,682,451,800,200,605,242,384,890,718,273,983,634,211,149,72,452,653,900,31,350,62,675,572,212,863,200,645,237,633,482,119,291,505,545,607,907,287,251,967,447,723,893,272,943,445,844,245,488,764,146,741,183,542,806,219,566,840,165,224,188,757,663,520,697,104,398,808,564,140,442,446,573,94,900,938,227,861,23,103,503,255,538,838,346,445,931,187,820,817,500,982,480,82,976,449,446,701,373,768,623,907,229,656,417,939,216,523,428,565,151,715,396,75,785,641,567,176,889,399,688,971,463,268,569,734,787,730,472,637,416,963,457,489,10,168,641,988,447,824,4,316,570,500,824,520,92,739,203,717,223,513,647,723,590,491,503,186,565,914,222,834,403,886,775,997,588,552,432,823,211,187,359,917,142,480,924,204,764,58,501,984,153,91,382,302,106,644,397,874,655,462,162,210,388,761,115,945,800,504,370,704,358,175,819,682,88,702,382,781,828,806,136,480,594,836,648,353,254,960,367,798,10,952,519,742,877,864,893,870,249,415,513,475,908,809,200,495,742,454,54,294,408,223,875,491,922,25,371,809,343,895,395,479,43,501,119,199,51,464,321,77,617,198,317,939,592,973,370,733,622,300,596,288,0,854,540,631,523,48,637,940,427,183,446,156,261,526,3,763,723,275,270,383,57,843,248,241,650,599,854,523,891,504,219,537,229,713,939,351,123,303,469,915,330,609,433,940,487,18,295,892,498,283,902,223,565,573,561,699,747,427,839,827,675,936,962,282,300,605,613,874,485,298,246", + "206,601,534,963,8,239,503,543,121,412,129,853,3,191,963,21,783,280,299,647,254,657,521,69,501,344,932,732,746,948,519,137,766,805,134,246,243,495,544,502,103,589,295,175,383,58,217,863,893,272,729,342,364,923,745,902,700,978,43,250,966,881,434,365,263,939,660,239,635,975,423,691,937,430,824,93,19,115,376,205,41,62,778,566,32,523,682,177,977,441,300,322,878,583,83,917,688,41,799,105,794,503,860,561,216,131,171,353,60,357,847,437,421,669,51,597,549,225,56,319,127,933,80,708,617,313,9,965,142,935,598,449,4,419,323,397,696,129,206,792,817,400,828,427,848,130,922,372,375,324,402,715,900,73,607,563,521,66,958,332,514,948,469,968,141,925,184,168,916,164,651,267,167,121,426,847,610,691,768,129,776,173,794,310,677,143,971,337,271,412,968,513,598,909,233,746,169,678,529,241,661,133,305,843,193,560,138,320,257,41,332,626,647,697,678,187,430,429,359,251,663,268,658,725,506,988,199,213,743,230,912,929,888,498,906,815,604,177,159,578,885,687,249,67,805,208,771,709,868,304,720,301,785,559,879,201,22,868,600,90,991,119,358,864,357,409,540,738,523,583,891,198,154,350,354,273,185,445,754,403,96,262,556,746,256,18,159,88,362,754,245,744,267,798,511,320,237,880,100,290,541,594,713,327,979,716,46,314,50,458,265,431,782,861,776,233,208,195,289,984,132,735,392,398,845,863,562,762,75,604,3,638,288,648,316,573,18,838,711,968,157,432,630,229,550,517,829,610,42,157,961,432,255,652,988,1,560,45,665,562,730,94,126,746,486,731,827,685,90,688,461,748,989,15,335,341,882,380,663,526,421,772,600,470,602,357,595,30,206,425,799,417,162,991,72,136,893,23,435,150,75,955,138,352,124,859,195,505,695,217,406,612,43,485,311,51,758,399,751,406,548,502,495,151,388,38,489,952,328,422,156,856,763,94,306,663,530,533,896,725,177,894,884,996,334,304,689,718,746,93,327,463,895,44,318,616,627,815,739,780,606,505,669,665,27,987,171,751,311,872,884,792,283,365,636,515,120,347,609,393,164,243,633,278,30,61,282,213,845,621,917,608,721,331,549,42,174,212,827,770,57,578,260,684,690,568,989,137,350,398,89,228,266,627,617,562,369,121,386,57,882,823,911,612,884,131,697,595,999,701,669,361,858,568,629,440,268,233,662,710,743,754,461,441,109,920,565,928,930,777,985,163,466,124,339,681,318,923,965,135,394,636,180,449,854,98,109,146,992,289,656,461,877,531,904,685,795,937,350,537,372,667,85,139,505,263,750,616,495,945,165,573,908,910,881,957,458,723,460,36,896,233,176,507,245,957,120,683,376,270,348,61,772,504,955,634,582,471,235,897,814,265,265,375,915,944,251,267,759,776,840,31,747,871,800,770,291,74,693,436,442,187,586,373,104,817,25,45,498,789,473,398,735,677,69,260,446,256,571,104,511,635,753,855,87,395,280,902,688,482,705,431,290,868,861,348,637,505,536,377,123,560,277,605,820,93,637,511,791,926,911,396,147,693,615,540,767,152,600,810,939,985,625,424,757,55,751,407,384,425,270,81,284,332,749,906,221,904,615,766,935,636,857,796,907,77,67,660,178,780,510,495,321,398,754,302,707,573,831,962,814,4,585,250,694,751,42,255,396,416,387,307,216,510,941,861,929,712,357,542,673,742,138,439,529,886,157,181,971,293,86,588,824,341,363,790,342,217,662,206,627,715,102,860,397,163,196,364,616,589,498,207,44,929,751,774,714,632,118,642,654,866,117,49,78,293,109,763,458,167,542,234,820,857,400,753,479,571,299,96,166,558,508,969,418,287,146,494,681,75,679,850,654,47,993,825,414,72,9,960,571,6,69,76,156,43,818,630,575,303,708,339,612,238,293,362,181,180,703,438,447,618,117,5,509,944,806,59,28,590,618,358,416,150,187,585,42,693,951,45,21,74,60,139,598,991,93,969,473,906,696,491,734,668,115,193,316,657,672,619,475,771,388,221,840,752,152,791,742,609,586,284,696,870,288,74,596,892,564,265,453,344,708,936,446,217,952,585,97,854,0,547,487,861,868,444,105,243,803,651,563,427,245,956,574,906,95,553,28,778,563,737,700,211,361,433,801,367,484,992,39,51,537,519,605,585,144,17,960,149,735,996,740,447,314,853,130,539,196,816,743,200,999,937,484,380,202,625,691,394,436,357,393,799,922,675,807,550,479,422", + "345,341,970,861,855,522,792,234,478,882,307,895,625,450,782,887,68,378,174,753,232,386,449,977,854,531,837,357,235,743,352,110,337,418,569,17,58,214,251,162,529,470,387,183,165,895,801,932,699,288,829,301,800,911,477,722,611,643,276,814,17,293,758,65,831,850,79,630,86,183,345,653,397,490,717,454,903,334,760,174,885,513,437,66,437,562,527,259,426,274,48,776,5,236,410,328,415,171,910,782,887,695,156,796,838,837,758,367,927,801,370,438,349,751,754,757,33,888,884,677,672,859,184,721,232,295,389,126,870,929,90,592,836,325,169,485,833,344,591,653,615,665,342,817,507,703,109,361,260,880,986,753,751,196,227,796,240,257,288,735,965,700,680,532,709,295,1,897,926,698,68,356,319,126,292,416,738,986,25,143,447,382,238,291,217,782,329,476,486,836,264,553,439,156,845,473,531,769,253,909,313,85,749,144,502,589,112,292,791,916,707,880,136,740,220,111,336,881,707,229,320,691,519,205,420,977,702,346,562,218,835,239,49,76,999,794,956,659,856,626,775,326,464,93,200,104,821,516,86,6,155,209,888,943,626,533,420,505,173,662,423,40,306,120,698,673,611,82,332,160,162,650,694,873,168,804,513,835,237,432,721,20,240,22,164,830,53,909,984,202,352,914,777,983,753,446,917,894,852,153,435,635,401,447,754,778,756,393,786,996,597,835,792,65,125,558,310,441,836,963,834,198,185,163,763,770,875,371,943,120,873,275,44,346,749,784,855,537,86,9,274,682,161,959,614,714,771,23,278,898,974,52,393,32,495,206,581,962,704,263,182,649,112,919,824,400,224,733,232,855,389,15,311,183,672,168,713,996,383,378,842,454,338,360,279,442,484,290,935,749,906,95,226,756,332,576,889,151,157,800,89,215,960,659,121,356,148,330,3,106,552,472,764,875,204,81,390,291,763,675,156,699,105,291,515,494,527,237,735,908,190,977,688,924,358,947,751,49,573,123,683,110,477,251,278,185,274,938,424,348,414,803,903,252,695,964,327,435,191,124,909,491,350,205,186,809,226,902,371,643,310,181,689,447,194,459,45,686,939,535,948,950,887,467,414,435,11,832,590,735,438,6,91,433,4,627,897,463,982,736,973,838,601,891,936,77,450,787,789,946,553,234,664,539,396,409,458,93,728,229,528,263,391,83,361,265,512,487,590,776,450,669,163,58,364,54,298,849,793,143,227,417,749,640,861,180,676,711,867,898,875,849,806,443,940,727,434,391,377,148,572,225,987,702,253,492,850,236,73,465,411,745,94,850,546,213,226,671,151,15,751,719,392,640,431,391,762,59,789,161,108,537,946,48,903,473,409,140,197,405,453,660,874,136,906,282,787,676,809,944,787,885,974,399,575,605,802,976,731,653,484,974,445,425,530,260,336,230,323,292,181,929,651,634,679,223,220,119,103,694,340,276,423,655,157,565,663,639,811,258,207,999,782,16,915,120,305,785,769,336,996,162,266,544,568,751,535,758,938,658,173,963,255,328,301,781,657,923,433,177,916,287,729,232,72,130,136,647,696,439,381,409,640,247,394,466,944,883,39,439,114,73,430,610,712,628,472,714,284,234,56,657,977,292,166,942,151,692,90,871,586,135,886,810,315,229,94,817,773,261,786,801,774,543,670,942,621,548,556,457,836,72,223,349,98,155,440,626,609,134,217,817,462,105,184,252,779,154,563,319,71,739,269,115,319,71,488,185,898,416,268,653,67,884,50,917,314,546,733,440,839,50,460,304,82,947,494,909,64,458,437,983,518,839,13,15,21,512,762,607,634,380,775,1000,172,296,452,951,586,957,665,567,774,495,646,512,309,989,202,734,716,896,62,179,643,251,47,43,114,407,149,32,835,373,728,532,936,19,127,94,271,1000,450,440,715,512,721,939,991,648,117,633,778,139,612,160,218,994,746,903,363,531,55,352,614,330,778,793,670,104,980,975,229,136,633,101,33,728,794,828,725,612,556,86,689,982,270,366,365,638,314,670,780,636,839,683,146,68,272,875,676,722,923,920,251,879,101,687,782,922,558,208,257,871,375,792,283,858,639,686,338,734,267,393,795,169,687,443,717,540,547,0,914,612,34,394,742,561,591,420,883,932,618,611,898,929,149,756,40,227,999,179,572,903,834,243,67,656,796,221,970,791,425,510,550,180,676,107,587,850,605,654,580,875,928,580,109,682,212,900,501,267,578,680,500,711,551,123,953,502,115,459,67,712,703,714,66,636,264,860", + "994,719,20,481,543,559,528,231,514,727,921,692,933,467,218,366,600,682,696,381,886,40,798,818,667,783,427,526,123,235,764,667,805,987,656,790,960,258,265,16,335,52,690,845,716,806,471,745,137,338,964,494,776,37,84,715,586,956,612,440,830,341,613,190,973,290,182,609,25,836,892,321,744,194,479,621,471,561,889,110,894,510,747,79,853,638,322,134,752,812,734,708,274,693,410,338,693,948,429,267,616,495,155,538,571,514,516,910,350,264,89,243,651,295,571,429,173,577,447,830,353,724,36,767,608,922,166,911,476,725,689,909,125,584,52,745,123,740,600,185,839,753,823,503,948,812,524,778,443,138,81,972,63,562,287,511,442,322,608,258,284,841,237,827,246,607,546,438,321,234,659,846,466,25,643,346,347,792,770,812,152,53,977,378,461,246,623,737,655,643,915,65,102,220,984,407,974,899,795,333,542,462,305,381,159,389,570,891,183,249,775,187,834,109,293,966,499,809,898,672,992,288,603,305,819,821,625,827,772,743,696,64,959,726,862,121,259,397,276,874,940,953,672,544,425,878,492,658,100,212,802,187,71,974,463,649,574,376,836,137,24,942,967,503,391,157,443,277,463,687,196,781,47,144,96,118,244,367,793,516,202,771,218,878,381,974,209,463,789,596,288,243,570,92,215,874,576,616,157,454,434,537,202,693,782,463,949,699,935,23,135,641,816,456,998,847,828,169,179,734,251,977,766,545,748,304,178,495,887,803,154,468,249,250,926,443,495,105,802,375,464,436,887,995,141,667,511,44,550,379,839,451,188,91,915,408,923,270,319,444,662,925,926,509,27,610,326,156,508,924,235,671,506,782,357,446,509,703,148,663,297,463,972,414,545,685,457,744,765,499,81,170,721,902,347,770,316,699,922,185,437,173,2,741,848,207,537,146,472,396,29,636,823,223,740,886,249,236,171,483,152,779,519,199,507,875,3,830,367,510,999,37,828,94,555,124,53,585,831,189,494,436,728,502,519,724,55,340,507,571,874,557,525,499,803,322,305,293,11,299,185,661,480,64,696,74,121,753,731,146,353,569,30,342,1,454,633,489,823,132,713,253,188,814,571,485,317,909,20,95,500,919,577,161,243,119,734,896,137,430,276,44,157,920,209,486,740,469,660,751,600,781,419,790,292,651,186,84,425,448,212,252,904,298,313,294,601,603,961,344,834,928,877,357,551,690,355,102,476,82,648,521,124,356,304,892,351,616,463,393,229,164,793,734,828,896,728,855,52,18,882,714,862,525,275,92,780,706,235,728,420,756,346,4,972,689,455,536,700,172,143,240,337,419,478,553,819,111,116,10,374,937,960,887,459,440,914,321,347,632,553,732,424,658,932,62,696,868,445,298,972,439,698,432,591,843,232,338,873,911,129,603,100,563,901,814,86,759,924,441,169,269,881,713,449,230,944,917,232,246,625,525,222,537,199,327,657,420,7,505,594,392,790,619,417,987,220,381,932,256,295,172,460,262,301,375,96,715,692,795,47,432,94,419,607,875,486,96,340,731,735,276,1000,947,670,996,55,229,506,80,144,101,991,138,230,319,535,577,473,812,860,552,874,318,413,373,749,536,356,631,166,679,321,425,981,410,476,54,950,965,822,216,470,413,635,638,857,402,433,770,638,25,612,953,605,617,279,574,388,697,668,966,284,834,461,575,93,972,550,283,356,512,8,270,638,937,467,755,742,816,736,286,112,567,550,593,923,149,755,611,565,724,492,211,665,785,147,763,794,660,285,973,421,528,981,939,423,946,692,92,220,63,28,350,142,195,911,729,363,903,501,646,870,526,771,310,41,272,169,102,243,470,572,970,786,164,675,285,76,105,483,388,819,255,60,589,66,356,634,73,659,706,725,889,433,208,668,274,186,21,672,396,849,449,38,452,56,189,420,333,181,30,394,702,392,114,673,224,802,982,695,646,722,408,172,552,321,663,121,287,228,914,719,2,391,612,73,327,849,521,449,829,627,811,856,494,163,319,249,194,785,939,41,564,374,878,167,669,981,531,473,936,899,749,313,379,190,552,729,784,455,64,63,498,170,455,740,188,728,520,347,201,667,811,514,975,262,140,36,631,487,914,0,14,184,70,231,422,402,941,554,485,196,881,647,453,400,778,206,639,11,158,209,224,727,471,635,958,11,326,48,137,54,876,23,192,721,780,650,165,923,187,336,109,373,336,232,398,755,962,536,425,379,979,123,332,102,749,418,590,973,7,903,239,369,768,937,93,762,920", + "238,608,39,800,461,932,681,687,791,698,414,351,433,490,317,252,876,346,298,31,449,173,353,717,803,752,859,670,652,874,852,939,748,365,70,630,162,531,516,184,90,934,209,167,527,116,373,536,400,251,845,913,363,957,365,23,484,746,791,194,358,246,269,399,982,20,574,301,261,445,833,367,549,58,797,612,985,205,343,104,608,971,465,688,300,74,9,581,109,891,656,159,81,213,517,831,576,499,315,898,498,765,173,264,550,421,630,738,881,587,958,972,443,657,975,620,52,366,24,927,754,244,141,765,650,545,645,560,165,154,233,881,989,696,516,523,203,61,18,689,552,88,862,655,868,469,255,390,247,527,946,560,985,927,305,807,251,775,773,466,622,978,583,969,119,205,202,672,545,500,378,392,632,503,396,964,93,328,67,784,229,279,410,426,472,492,847,746,378,287,151,486,383,121,504,331,356,130,248,807,541,14,628,497,216,590,38,500,920,572,799,446,816,602,33,618,936,566,131,114,609,345,694,759,602,338,411,230,426,708,718,790,209,851,83,507,456,47,156,762,110,527,537,596,24,997,985,113,251,346,422,736,550,416,833,964,517,216,777,288,743,995,527,386,886,452,173,984,403,663,603,771,56,847,744,779,482,936,922,364,762,444,464,780,577,495,968,412,553,681,758,594,844,699,720,714,930,359,737,109,151,448,399,397,309,566,203,369,540,498,730,771,178,749,518,270,533,187,72,462,246,449,616,851,293,781,307,89,134,9,507,197,303,28,343,195,377,965,292,770,416,551,393,561,382,237,259,652,666,359,870,33,18,664,213,882,870,389,202,536,46,275,980,302,770,400,46,185,589,217,144,429,618,199,787,210,821,533,271,410,291,452,998,37,656,796,37,305,412,180,451,488,730,666,728,66,887,29,832,975,587,366,551,880,916,985,948,613,404,473,361,879,780,336,913,233,990,671,423,834,126,372,202,989,902,843,823,991,809,864,44,330,502,453,141,53,654,793,493,42,668,804,957,113,940,457,732,618,28,792,438,552,50,962,570,478,221,50,542,474,99,269,369,419,911,478,389,42,929,511,149,287,399,463,237,700,579,757,9,668,261,879,402,706,79,746,450,573,426,918,971,505,717,262,691,309,450,421,120,551,665,696,713,464,132,952,893,38,489,973,295,516,850,735,657,578,627,284,932,857,588,679,687,50,835,201,385,155,383,386,682,988,348,221,322,534,338,961,73,634,831,394,594,672,90,272,526,877,966,997,162,568,251,477,205,181,766,398,658,878,289,319,676,107,832,359,821,622,789,997,246,511,644,773,190,343,670,449,861,353,650,413,5,590,468,565,98,384,180,373,382,308,491,354,571,9,788,758,992,597,224,9,354,15,38,651,574,849,973,907,764,318,612,347,966,350,981,607,983,847,666,472,237,885,860,945,797,102,998,462,707,989,463,112,864,70,768,650,41,840,60,103,99,489,169,544,891,581,486,477,632,382,801,192,628,680,759,87,889,8,592,888,948,833,200,727,978,700,762,769,790,293,18,409,208,435,523,254,680,848,381,122,890,764,734,240,330,299,984,437,180,893,903,268,481,373,723,548,524,884,654,339,190,886,40,569,687,68,663,348,627,542,183,787,267,365,818,981,378,952,839,995,513,458,625,845,565,617,30,209,482,501,573,692,748,831,361,457,768,958,312,670,197,17,363,98,223,498,538,346,184,601,677,519,514,626,543,548,37,983,284,682,251,501,255,767,707,102,27,399,602,488,578,447,652,211,388,11,603,2,360,344,21,465,456,97,632,874,536,257,466,86,583,16,993,342,443,907,265,994,521,517,799,428,383,864,737,769,107,14,607,504,112,372,444,692,593,525,23,935,484,968,38,226,803,368,485,873,541,424,231,724,889,581,59,462,571,741,470,464,450,413,325,889,318,319,584,109,696,887,293,784,805,543,691,885,655,378,167,848,710,10,733,46,969,543,926,854,659,256,350,912,829,644,36,678,173,421,472,50,270,410,736,682,62,80,903,390,853,376,905,430,913,482,926,913,816,267,594,258,862,724,297,221,646,854,581,11,714,401,675,235,517,706,330,31,158,540,72,655,301,445,419,677,534,471,714,114,613,523,861,612,14,0,990,810,872,598,182,96,295,588,664,12,802,804,519,601,249,785,905,608,704,227,943,128,397,193,60,34,629,673,532,288,137,166,70,693,243,224,462,714,716,396,73,542,167,54,724,637,808,451,596,785,575,590,80,795,602,908,987,107,910,593,222,188,997,617,508,916", + "979,663,952,907,724,672,137,732,436,390,131,771,430,32,931,86,349,26,336,566,269,11,984,68,118,430,18,463,971,4,516,115,708,193,570,137,249,221,754,248,593,597,81,133,532,307,315,32,331,904,620,980,567,334,927,686,657,531,134,285,102,566,940,367,474,733,727,293,413,621,18,744,601,721,917,15,398,493,944,339,130,819,37,768,146,171,525,347,136,498,295,399,264,756,541,743,812,117,659,446,52,777,710,208,186,472,977,886,519,848,136,191,267,853,199,447,599,111,147,319,827,505,733,386,529,129,219,326,401,119,610,197,652,23,841,551,719,479,998,317,870,497,878,24,820,114,362,646,815,137,103,895,493,622,619,866,269,745,447,124,594,52,3,706,446,550,843,244,441,14,751,215,416,809,60,686,542,636,986,59,142,961,477,144,769,655,143,895,783,326,691,363,505,815,328,485,773,828,451,603,253,40,495,224,851,820,231,174,457,630,474,326,925,240,926,378,306,427,784,834,106,838,188,114,930,349,188,686,507,238,523,22,106,847,81,330,76,479,797,85,722,377,753,95,612,58,956,768,190,918,550,831,390,90,605,721,988,87,239,227,37,756,7,973,243,719,862,540,119,68,62,97,883,143,986,93,752,429,292,885,346,961,397,428,579,829,561,235,672,477,78,231,101,454,285,692,78,816,565,890,492,349,3,867,619,780,413,608,386,137,723,697,266,527,966,912,267,267,251,650,824,946,807,952,342,348,188,721,337,624,370,262,26,380,904,414,493,268,664,407,363,57,519,651,438,456,99,36,268,607,980,332,661,689,227,553,421,673,148,880,823,702,182,710,271,883,344,794,293,876,437,851,170,31,415,775,896,608,450,299,398,695,404,237,78,416,883,658,354,821,181,370,906,38,898,552,757,282,842,323,26,343,463,551,773,450,360,594,437,294,168,806,911,926,771,146,200,680,128,384,307,203,326,901,530,266,14,332,264,287,131,349,895,151,163,449,452,911,119,161,924,556,117,281,67,265,582,686,183,205,147,758,31,846,346,512,300,764,977,21,473,483,61,24,87,888,921,168,718,816,269,980,82,738,630,819,735,766,206,660,927,747,89,143,356,367,336,132,694,914,941,562,309,845,363,963,510,186,97,192,439,47,791,276,540,590,431,621,651,178,302,647,658,991,480,335,561,834,784,653,110,693,367,517,944,194,76,185,680,398,110,118,20,960,247,274,830,911,262,659,919,19,691,631,859,790,61,526,886,829,433,511,103,338,817,100,667,992,652,147,450,475,31,147,418,894,488,919,55,361,854,802,426,413,595,575,185,57,553,559,917,927,503,992,692,776,970,987,350,961,716,653,317,262,270,741,31,758,489,796,265,792,626,301,530,727,941,136,988,889,692,305,655,205,486,757,498,710,980,680,115,932,865,335,258,862,560,508,460,508,91,803,412,631,956,101,188,895,119,907,806,894,121,379,424,137,595,227,122,681,102,583,650,5,782,461,457,254,45,733,289,97,686,842,122,159,233,965,524,460,863,443,666,253,438,885,100,298,979,157,618,506,605,113,506,627,550,46,221,396,344,301,280,723,24,104,492,283,288,96,766,211,645,41,853,166,723,44,249,18,180,28,993,249,52,36,374,933,163,359,402,100,976,330,697,945,440,799,540,133,909,322,165,109,711,315,365,228,86,551,252,993,23,910,597,952,710,107,482,829,582,315,457,765,798,668,944,160,299,314,846,302,787,432,36,556,139,98,512,18,655,2,127,65,167,212,699,415,546,147,21,182,846,345,233,253,526,119,678,884,199,846,850,556,524,617,96,371,867,654,854,211,315,95,695,505,622,693,649,291,842,442,567,969,878,564,159,727,410,259,368,723,516,807,386,616,987,62,393,341,510,794,733,18,990,644,569,778,460,865,31,10,956,204,315,753,282,957,286,197,665,521,973,724,405,456,633,842,766,676,431,5,800,52,524,165,331,546,187,506,663,926,112,288,419,265,487,452,711,259,227,590,335,285,933,460,712,181,484,657,422,770,195,408,174,186,552,182,793,180,86,450,942,671,245,261,857,491,268,159,896,973,770,270,811,57,466,678,238,346,273,110,762,64,515,589,572,37,471,48,868,34,184,990,0,676,237,577,448,315,216,310,105,248,342,354,226,134,344,276,287,802,122,808,91,90,613,113,8,935,87,780,170,341,958,722,323,780,249,315,181,41,239,160,29,383,137,590,145,513,201,718,926,872,890,422,199,516,367,651,793,392,75,44,370,116,291,929,923,353", + "394,861,195,122,511,394,733,578,918,713,509,494,876,609,159,256,736,394,22,578,765,767,775,883,355,843,626,42,857,952,481,653,154,755,584,552,458,2,751,822,941,19,937,58,693,505,314,783,144,200,91,595,812,50,232,266,359,725,749,770,527,469,552,235,176,429,777,872,730,960,500,980,695,54,682,38,315,570,236,847,831,701,917,124,41,410,387,151,649,440,158,359,483,434,357,893,360,786,380,323,309,537,783,64,576,29,188,772,21,803,167,391,189,890,130,64,203,498,655,74,24,562,472,730,832,506,325,862,854,136,593,522,800,124,766,148,76,637,35,776,508,134,498,931,434,503,958,213,988,638,171,272,406,854,350,597,423,841,874,595,979,758,711,762,848,56,61,837,14,35,67,105,296,309,366,717,686,135,405,829,181,373,715,281,867,93,650,946,874,814,416,796,876,427,34,627,73,741,79,124,166,674,294,632,692,188,110,722,347,34,598,525,307,640,690,491,912,310,653,144,475,936,558,44,754,871,159,804,32,189,495,61,632,573,157,405,244,50,943,763,593,467,323,843,579,958,543,110,338,97,534,921,988,636,554,247,474,456,724,201,701,574,172,32,536,95,899,578,21,982,142,548,161,510,704,614,813,51,103,349,398,387,833,34,86,230,227,866,375,95,85,863,362,163,823,946,852,583,91,678,65,436,215,438,218,483,310,252,763,44,101,113,968,261,921,572,518,180,614,566,541,530,747,603,425,337,339,904,325,572,442,760,84,17,953,640,297,441,751,997,116,10,996,640,269,87,263,7,986,619,720,974,414,191,855,971,659,987,146,358,136,820,329,107,830,483,119,10,487,561,746,639,666,545,383,237,719,524,384,861,858,583,692,816,315,824,561,198,951,333,693,48,195,620,741,168,27,364,572,29,203,173,253,669,216,994,918,393,978,964,846,847,316,117,951,892,960,589,845,449,724,287,595,254,11,370,186,254,465,35,706,782,339,818,890,701,842,674,503,848,165,470,71,682,844,588,614,34,175,234,259,447,133,840,3,957,613,670,575,751,876,183,676,463,978,414,155,392,376,779,706,628,592,580,394,332,597,219,160,164,558,297,995,779,31,281,687,652,549,470,934,966,167,424,150,346,808,71,211,418,817,243,666,325,200,622,671,55,921,285,510,232,132,766,577,308,146,906,628,134,634,768,627,623,549,690,549,746,183,596,872,906,620,416,299,691,188,113,465,540,456,221,110,771,969,199,300,920,457,52,699,278,316,105,815,907,376,101,703,27,867,47,6,577,326,829,450,355,192,850,140,908,413,712,354,956,940,828,860,847,138,968,739,67,34,923,842,191,534,962,890,737,653,404,95,123,198,257,430,22,311,140,85,418,161,610,324,463,130,235,500,623,487,156,293,624,451,91,147,831,579,530,761,483,824,474,964,229,367,975,957,205,15,587,148,924,774,56,528,985,103,937,100,921,623,714,337,558,357,718,498,613,621,606,886,785,171,564,595,968,320,34,561,535,865,689,642,159,669,643,203,657,560,228,774,134,767,672,743,193,546,911,319,318,86,238,523,421,769,814,340,911,396,403,28,12,685,401,876,990,974,2,791,676,832,94,140,746,556,497,417,392,546,780,779,997,205,68,156,4,750,958,373,143,898,671,822,900,898,741,83,780,112,110,222,726,560,89,68,391,279,726,350,672,129,183,978,239,269,154,173,31,353,57,136,837,231,803,199,216,362,389,542,85,388,494,762,706,631,853,844,744,694,763,499,877,839,350,484,765,341,59,498,678,245,466,901,411,15,848,150,686,721,651,260,981,79,775,250,20,955,226,974,741,36,135,874,604,645,87,654,899,675,789,214,197,941,838,264,610,672,920,385,385,434,145,284,327,225,906,324,181,948,559,349,152,170,68,227,370,578,273,683,250,125,746,725,390,237,735,24,67,380,508,404,400,957,921,865,756,767,181,687,304,164,130,344,554,207,384,429,627,352,345,348,20,440,396,105,36,957,324,888,340,523,836,450,118,361,246,468,101,127,402,804,676,719,710,92,715,74,216,377,70,592,820,153,146,307,807,674,764,432,609,643,887,750,871,293,319,224,493,966,771,534,816,752,705,928,637,444,394,70,810,676,0,37,322,21,991,594,29,641,506,448,398,348,461,30,834,746,110,478,302,760,774,548,714,835,14,754,483,345,559,383,2,550,159,185,720,398,675,301,409,751,972,905,838,349,110,379,646,596,933,941,831,144,279,522,655,172,770,335,350,800,99,271,925,580,639", + "685,509,784,455,154,734,843,132,397,588,360,19,921,968,800,672,742,682,197,995,591,787,504,516,806,360,766,624,247,463,691,248,408,136,42,487,506,179,507,343,448,785,321,316,187,770,905,419,439,98,789,960,660,83,869,379,474,459,203,268,831,338,828,434,484,830,530,661,788,523,855,832,678,415,71,833,474,5,624,119,35,782,321,982,489,456,630,630,478,143,876,890,3,449,535,201,638,385,11,526,865,197,191,452,146,83,45,524,202,238,236,564,661,281,802,735,315,334,293,720,397,71,606,686,314,262,868,457,908,520,913,492,746,570,976,788,858,316,960,891,920,239,211,338,398,858,404,915,843,641,646,592,854,640,647,533,381,873,888,56,181,448,434,825,194,356,599,683,633,700,851,453,855,961,986,866,861,102,747,914,875,873,246,233,447,489,820,732,92,297,871,404,614,873,665,636,36,189,557,165,81,664,347,325,958,828,221,42,470,409,464,116,615,981,875,976,360,643,181,139,816,662,606,522,115,544,794,252,974,176,335,720,942,4,417,305,538,604,361,962,269,249,29,111,466,800,890,917,724,202,535,866,199,717,852,419,314,161,733,454,697,573,232,52,490,88,773,335,259,576,734,28,45,763,692,862,219,261,78,920,189,705,686,744,590,726,196,53,983,645,549,832,16,257,527,769,227,126,934,483,949,766,241,763,308,105,59,183,669,407,922,493,118,332,587,512,670,856,803,428,518,461,375,361,96,800,721,891,800,456,956,606,51,685,91,324,519,377,987,458,757,892,110,800,376,376,501,981,436,437,966,146,696,540,581,166,725,857,781,606,911,736,918,48,889,559,519,934,695,122,863,719,609,124,220,849,661,582,991,229,683,108,468,80,342,967,636,976,626,328,610,644,809,473,169,500,335,665,699,53,113,130,960,825,574,508,408,51,712,97,716,73,920,34,455,106,658,499,617,679,418,813,75,393,501,115,550,618,932,546,824,517,409,637,877,14,961,76,77,649,621,652,657,915,384,603,881,781,175,221,150,893,649,925,398,16,974,131,720,77,872,885,839,414,577,98,518,320,355,77,723,816,618,125,620,345,322,868,421,936,868,869,670,765,203,545,165,281,292,868,964,581,4,589,162,501,451,612,410,371,811,668,269,410,639,606,984,82,548,985,333,638,677,337,584,757,115,107,228,436,640,133,210,447,446,223,184,399,594,908,504,374,629,539,100,568,318,365,672,744,990,454,94,854,708,523,696,118,965,873,175,251,109,937,203,468,759,830,732,918,870,857,347,236,794,222,146,78,134,512,70,370,413,400,841,276,852,9,924,586,748,112,377,892,733,375,84,255,203,132,223,190,887,701,610,865,456,13,701,485,193,470,251,341,119,125,671,343,81,324,847,650,927,622,229,941,853,637,292,405,59,2,804,574,357,84,278,626,515,71,999,632,277,257,122,274,619,288,981,668,551,845,38,872,730,196,569,565,268,930,427,878,399,172,447,367,413,256,499,475,943,118,760,287,631,974,829,141,857,508,379,559,994,56,906,444,135,60,134,193,94,198,146,513,677,946,87,300,110,95,12,857,977,248,407,708,118,279,383,552,252,157,146,958,301,401,212,401,318,414,282,269,747,53,520,341,182,326,253,80,310,362,460,121,56,753,550,605,636,306,42,526,729,356,996,633,614,701,450,325,665,502,656,584,216,519,529,3,659,658,649,203,94,28,201,980,741,824,304,798,860,365,324,530,638,78,526,487,310,4,780,588,32,114,480,428,142,246,904,278,880,280,228,589,692,639,737,401,760,825,236,783,188,914,183,792,607,970,587,459,420,179,119,79,662,817,60,622,959,329,564,528,326,201,555,151,831,632,420,711,633,972,666,627,406,728,313,222,866,765,136,235,785,387,944,12,343,275,835,91,901,607,321,70,646,726,837,967,431,855,550,421,370,34,795,710,87,556,744,269,878,100,884,289,619,752,618,970,53,130,682,616,498,885,732,474,695,645,694,719,707,439,283,283,696,232,731,340,435,340,612,902,767,62,474,567,767,794,446,581,700,938,874,254,327,37,810,941,165,198,913,703,370,67,744,945,189,975,563,861,494,872,116,496,103,970,119,131,281,940,105,742,231,872,237,37,0,314,772,177,188,258,768,966,679,480,238,304,880,825,79,279,893,946,424,551,542,843,962,355,356,417,549,330,462,323,361,567,833,252,359,443,244,475,9,613,162,485,405,15,726,234,523,856,218,899,347,592,548,458,1,880,476,510,271,169,83,990,569,909", + "131,621,683,8,900,883,101,379,907,773,626,454,391,247,606,967,338,699,690,352,554,64,319,934,404,89,859,137,971,240,429,2,991,24,910,653,453,460,665,19,200,693,706,855,379,484,71,798,102,28,467,391,384,120,411,624,523,531,657,213,892,635,967,402,98,363,248,36,894,616,6,820,238,957,500,278,501,351,525,332,272,253,945,51,526,114,139,453,693,511,959,313,557,884,454,687,281,861,278,790,275,487,789,704,717,255,661,579,429,398,698,255,113,847,217,498,997,911,937,397,60,48,170,559,945,199,662,109,158,731,125,370,952,600,689,174,860,846,281,903,210,509,816,576,828,858,1,928,701,124,195,412,915,902,681,467,112,288,196,623,896,679,660,706,57,785,354,228,871,422,212,743,961,747,146,230,556,141,71,902,366,35,237,692,520,648,109,888,816,148,946,552,536,338,349,829,120,930,441,802,586,684,867,145,195,353,844,297,938,497,105,894,299,470,643,437,703,327,343,638,218,701,838,989,295,984,332,601,862,998,815,999,73,727,682,653,65,98,486,880,479,523,366,421,698,399,223,268,30,225,773,798,867,740,847,529,65,911,165,396,856,984,107,415,482,771,99,527,896,92,177,611,123,566,222,305,519,307,919,584,576,941,902,823,135,993,141,300,376,887,310,838,201,551,135,501,805,900,843,769,313,130,777,123,987,765,751,430,406,305,396,393,451,977,747,813,138,140,890,677,345,370,827,71,821,793,53,381,894,319,796,286,580,703,485,508,941,752,303,604,67,850,531,539,173,178,663,537,467,197,32,452,907,209,785,181,235,240,653,809,461,197,386,135,89,769,254,156,730,280,652,630,783,160,45,42,530,149,601,344,458,84,966,570,814,249,898,446,563,889,291,886,270,760,917,9,265,435,382,304,470,352,862,196,481,114,742,622,280,224,882,911,171,886,312,938,841,462,215,697,598,810,178,390,205,267,965,393,139,338,63,346,549,790,440,748,630,850,724,919,75,37,147,104,302,494,451,831,289,761,20,552,89,896,178,635,466,321,993,870,555,530,491,133,337,270,667,426,516,928,224,50,77,701,96,340,341,736,564,753,995,641,140,537,645,119,81,783,661,922,396,276,554,964,548,408,118,251,551,427,603,940,594,198,207,394,317,227,971,550,660,107,505,51,489,81,77,860,378,892,568,541,424,865,65,790,733,933,644,32,938,954,739,388,565,194,253,468,187,311,417,725,476,948,801,295,94,413,506,995,886,511,158,439,345,356,380,988,416,843,977,809,432,95,373,772,967,146,216,1000,52,855,344,940,981,416,477,873,876,40,351,120,966,179,223,815,984,400,341,333,547,489,567,286,589,826,849,573,9,488,660,145,277,805,670,101,373,922,248,560,354,758,456,281,423,975,961,744,423,44,181,195,731,483,19,271,804,669,915,311,283,421,258,992,17,577,215,32,370,995,668,39,605,550,282,412,628,80,145,133,628,727,267,661,226,156,705,292,432,521,876,909,550,389,949,601,89,364,592,183,314,130,574,929,294,585,224,563,897,973,680,689,227,655,715,91,37,21,289,344,658,909,548,360,152,500,436,931,579,852,579,704,844,278,80,26,408,421,99,831,152,590,700,697,776,154,126,932,120,455,922,23,957,453,625,694,300,587,327,366,465,647,985,383,198,623,7,176,730,778,490,727,851,306,709,466,68,590,152,529,939,808,403,118,944,682,404,970,288,934,378,986,791,491,892,898,986,66,519,590,651,69,109,785,485,412,617,649,797,959,998,458,619,702,48,459,674,970,52,419,704,43,687,659,770,277,868,254,159,226,823,357,666,944,587,807,489,751,123,810,427,843,228,429,778,250,198,927,797,667,610,306,194,150,788,378,317,932,901,96,899,777,581,102,314,661,707,284,442,380,607,470,201,843,549,482,508,463,466,283,969,533,188,560,561,614,382,955,944,664,299,720,525,356,368,857,535,749,44,569,383,350,448,373,824,17,754,813,399,87,908,227,797,314,649,180,823,508,383,983,536,799,886,772,148,968,606,562,714,831,325,598,230,465,675,318,966,165,300,164,719,815,876,555,359,869,967,865,588,442,718,470,647,996,706,581,713,272,880,427,243,561,422,598,577,322,314,0,247,331,201,174,716,560,79,26,940,602,580,852,472,459,835,97,457,35,733,540,425,333,571,676,160,588,440,463,114,342,894,377,835,726,515,728,570,310,884,440,268,745,137,227,606,389,766,424,14,540,607,855,181,222,517,225,553,245,831,537,842,456", + "822,813,218,770,464,703,754,23,156,621,436,916,252,891,593,195,119,399,624,396,246,856,499,109,415,852,809,727,947,532,471,666,996,624,458,763,787,949,154,620,406,706,556,926,883,881,969,174,309,854,807,563,331,941,747,59,404,144,660,498,353,353,929,881,886,958,374,522,195,112,699,566,378,470,921,571,35,526,484,142,718,714,432,837,122,494,419,427,940,97,404,848,447,298,645,429,187,773,53,92,25,829,428,845,876,230,4,962,38,683,395,198,646,338,525,809,439,893,411,496,405,670,296,856,660,497,259,728,309,300,688,747,11,549,974,626,485,900,214,506,974,926,472,307,151,320,667,991,887,99,19,863,776,496,289,909,103,951,419,650,543,386,49,444,467,599,759,801,448,120,336,160,956,599,839,896,791,489,914,740,144,389,294,473,411,411,252,390,351,821,246,379,769,264,414,271,383,111,140,634,509,921,891,710,431,528,640,348,346,553,344,610,318,807,986,221,419,550,456,970,971,450,659,783,455,204,972,297,768,461,485,823,748,446,998,39,313,435,843,683,634,821,128,456,453,804,579,354,117,897,370,835,752,710,651,231,912,676,944,356,579,923,644,661,721,734,534,496,18,223,914,731,278,798,62,307,410,499,118,127,359,708,998,451,680,527,347,182,728,50,252,146,296,247,593,452,978,744,781,493,198,567,236,428,271,197,706,403,598,285,782,26,360,585,468,925,782,969,134,36,92,134,102,908,54,360,253,244,232,13,347,464,615,361,807,369,161,503,797,672,504,922,108,121,707,299,432,323,575,740,181,406,3,900,994,889,37,646,959,62,60,750,145,147,517,780,861,356,609,243,98,609,453,796,956,143,369,910,764,83,571,987,578,895,574,859,501,113,342,734,670,353,270,733,418,164,731,784,974,61,824,168,78,923,887,594,967,133,253,741,243,688,506,328,625,402,651,973,607,865,645,441,728,196,824,869,497,726,227,48,989,54,838,774,787,546,918,510,170,374,611,78,292,18,680,684,496,627,251,734,802,813,723,511,88,19,453,319,883,616,161,665,385,440,678,937,166,877,70,599,282,460,712,329,350,649,569,916,233,500,678,972,749,19,673,239,913,691,629,24,159,246,763,144,937,207,328,986,13,940,235,199,279,998,266,243,73,194,275,921,587,573,254,943,52,986,584,710,93,295,939,326,944,330,810,348,853,650,5,954,201,712,781,752,77,247,223,446,20,203,831,395,257,397,82,437,466,306,713,292,742,449,386,100,778,751,919,207,690,487,789,495,434,325,702,398,996,218,470,704,577,149,23,325,157,307,644,401,941,401,809,274,919,357,129,330,46,508,498,822,44,831,339,555,444,777,748,946,955,799,313,312,121,830,669,245,492,577,768,990,448,822,492,959,630,286,817,339,956,989,148,219,838,649,249,831,205,505,69,709,768,40,613,737,39,656,896,537,859,373,435,871,163,698,289,791,682,558,887,673,563,555,781,963,326,664,166,151,151,862,409,623,329,637,43,421,873,273,249,737,405,107,933,867,396,906,287,835,575,114,990,712,534,244,24,556,89,192,281,991,547,520,231,984,357,434,228,81,310,771,628,74,195,105,569,573,418,755,269,423,775,447,245,551,736,156,527,753,408,873,505,79,785,730,694,357,143,154,371,482,43,155,801,259,271,742,542,121,869,41,115,928,465,902,713,465,473,106,78,747,562,394,16,648,196,532,915,685,885,931,499,22,762,293,441,207,483,429,182,294,909,117,496,40,127,338,69,341,897,284,913,767,81,689,289,331,541,595,818,386,281,369,893,609,952,282,952,622,713,15,531,64,459,46,24,552,400,792,505,655,653,686,686,876,469,381,328,558,376,912,460,336,952,983,657,161,225,283,300,967,371,815,495,449,924,761,109,419,251,467,568,900,853,111,140,156,77,432,493,880,176,59,582,998,122,465,533,606,183,301,534,819,445,67,149,139,115,211,659,795,447,713,630,467,481,926,628,592,970,922,690,285,127,710,930,479,355,613,508,811,115,436,172,983,811,725,608,199,852,598,412,249,619,757,49,167,664,355,118,972,962,789,791,320,109,707,371,294,463,774,492,826,780,920,85,876,801,29,158,183,803,591,402,182,448,21,772,247,0,722,986,437,938,615,722,481,888,119,680,751,223,994,177,247,738,900,635,971,484,81,178,881,729,210,52,155,418,226,360,413,428,589,353,133,643,92,732,604,930,968,239,949,421,236,230,677,239,492,166,743,250,248,634,981,818,520,620,393,666,510", + "717,37,146,153,356,758,678,637,422,626,947,655,588,331,416,93,235,932,347,772,541,476,582,490,841,475,655,269,742,577,684,78,298,686,253,929,511,512,297,625,550,603,54,95,187,135,92,153,246,565,728,775,734,566,544,841,58,741,884,327,711,565,84,901,380,156,663,206,788,295,475,84,394,927,560,712,458,842,342,942,896,334,547,7,267,842,517,110,290,350,788,19,991,932,418,54,1000,521,140,52,905,608,598,950,712,255,800,732,467,568,828,478,413,534,766,343,72,67,876,732,126,129,679,457,244,707,500,866,258,746,784,537,634,97,988,685,226,203,901,128,838,186,735,987,334,698,933,72,989,128,811,194,669,662,154,567,357,614,688,850,107,218,967,695,364,72,79,860,286,606,727,12,398,909,7,634,764,164,485,773,627,482,502,966,738,149,707,333,397,401,421,969,966,933,744,888,62,575,497,6,515,78,298,657,399,359,775,133,962,153,499,907,134,770,116,534,111,896,679,232,721,402,955,322,825,429,961,53,838,940,455,730,902,618,872,154,504,921,445,419,599,438,779,164,541,601,259,171,562,305,862,204,184,121,66,337,279,326,579,292,251,256,158,189,292,192,765,153,814,601,186,609,909,186,728,125,103,188,27,371,812,348,597,426,539,6,735,742,217,910,933,250,406,811,626,308,908,52,464,767,496,745,275,396,416,169,665,994,695,576,551,374,913,422,634,956,558,164,411,932,862,824,716,982,393,871,46,23,943,502,668,542,428,162,110,654,187,657,114,601,262,450,46,818,784,470,786,115,73,709,49,814,820,617,542,537,980,159,352,889,68,754,81,424,612,54,181,38,153,221,533,157,761,808,265,144,519,332,875,16,824,418,74,636,680,235,693,403,561,964,306,363,436,723,313,782,685,321,253,340,890,710,675,988,295,986,888,53,914,21,110,259,201,946,301,600,698,398,779,148,381,545,636,696,269,37,191,167,294,77,657,498,80,904,980,650,482,688,137,289,175,556,107,776,973,871,224,814,717,810,186,413,275,932,715,57,166,928,737,924,580,179,828,60,830,973,478,920,855,10,3,719,762,96,498,343,769,369,475,219,830,76,515,802,211,311,718,306,59,764,132,893,910,922,881,55,891,462,267,713,517,257,541,59,172,96,482,241,770,175,186,125,297,826,116,104,8,654,990,201,579,750,989,38,549,907,177,752,779,572,417,444,490,803,837,725,677,952,504,683,7,341,500,377,953,137,191,433,212,503,507,105,724,567,447,612,203,222,658,993,611,108,155,529,747,439,806,725,561,31,926,373,558,309,810,532,580,467,257,97,550,532,616,619,719,827,603,683,315,372,635,214,951,548,304,226,657,664,492,597,323,28,749,859,477,701,130,682,239,717,551,513,843,461,153,71,255,292,961,487,338,731,718,381,91,23,656,136,727,987,577,587,14,454,890,695,95,293,462,446,146,361,869,317,785,315,853,862,80,462,413,282,786,592,510,484,454,57,360,411,452,675,884,468,925,764,332,378,872,873,269,19,976,573,464,766,9,942,902,415,306,593,841,372,884,288,758,623,985,931,924,102,343,361,184,513,507,112,68,988,561,765,60,277,129,320,62,939,695,741,620,404,323,698,643,914,121,611,250,751,815,758,368,717,858,324,464,252,45,91,166,881,422,801,356,91,595,60,902,167,362,376,430,101,610,399,498,617,478,95,642,578,95,24,959,660,71,30,462,137,893,612,828,194,818,504,278,924,167,625,991,85,724,837,706,176,457,127,854,63,460,325,885,951,238,68,317,650,578,507,690,815,195,10,526,834,750,685,931,228,674,341,298,227,674,820,508,39,258,129,588,93,317,493,49,320,197,178,249,349,413,692,86,679,6,744,350,790,948,868,333,369,892,116,542,677,960,676,960,954,271,943,56,415,935,237,223,673,712,327,798,753,93,710,287,498,601,162,932,611,774,951,284,349,341,574,104,118,460,399,534,198,683,878,829,818,789,207,168,572,21,300,182,393,488,79,517,266,172,17,959,796,689,544,9,516,43,24,633,288,485,583,274,571,251,771,974,924,366,917,758,765,267,304,886,390,858,100,817,647,61,850,94,597,428,138,4,945,342,446,651,420,941,96,315,991,177,331,722,0,482,951,580,286,144,487,708,387,664,716,790,245,510,15,429,606,710,953,364,852,221,755,534,406,789,22,748,220,967,414,145,37,176,880,385,239,909,495,848,856,431,579,522,646,830,984,600,421,895,217,918,845,257,253,342,647,472,124,906,577", + "397,195,915,338,42,609,573,106,988,560,928,317,244,897,553,523,654,961,462,241,351,391,735,444,265,223,639,646,142,128,968,787,908,866,607,29,667,599,115,828,885,812,824,303,22,325,425,436,591,705,196,358,882,960,735,895,691,532,1,348,834,725,342,879,921,259,369,852,201,307,457,386,191,123,613,437,109,65,82,970,591,931,691,554,146,434,440,42,471,644,339,177,113,677,814,260,785,617,457,521,812,104,683,259,533,475,258,414,956,333,549,911,42,353,386,607,870,169,358,763,941,78,689,590,982,831,747,578,800,382,957,390,793,79,363,126,517,320,658,955,539,358,217,858,700,413,585,129,375,243,18,678,42,800,24,181,589,566,53,65,177,497,553,8,279,403,527,229,423,460,636,61,110,853,572,729,821,959,39,161,518,720,619,44,602,638,841,839,968,515,594,435,854,49,238,650,244,925,622,987,874,339,433,686,92,707,460,365,587,236,754,513,786,215,395,8,779,170,599,339,540,736,234,691,188,103,274,727,751,126,811,26,413,999,24,78,569,241,243,723,247,582,91,747,866,166,116,342,767,703,920,11,617,588,116,374,952,875,526,472,36,78,895,693,819,654,214,599,892,867,424,732,8,916,355,894,222,352,579,611,725,857,633,794,840,710,93,790,88,591,354,748,724,214,664,379,712,18,360,509,615,729,284,793,262,635,662,642,933,791,639,354,823,866,112,445,314,409,905,390,721,591,177,219,147,174,761,118,208,372,655,662,424,262,146,498,435,974,906,323,859,697,382,826,444,625,760,502,761,758,943,373,147,255,324,701,196,460,254,984,790,389,49,260,27,763,899,64,536,595,330,927,347,861,241,638,893,935,9,861,359,312,775,894,914,389,514,503,328,613,498,58,804,289,443,85,46,306,91,717,647,943,951,12,327,138,906,689,181,335,358,212,795,819,158,256,413,238,194,361,773,796,824,473,283,317,231,459,84,711,721,881,288,799,681,719,816,454,12,26,490,631,562,423,820,171,724,294,753,145,803,683,119,947,284,348,269,247,754,275,242,922,188,709,837,980,885,819,116,814,909,29,136,211,720,636,994,365,564,714,875,366,518,767,249,881,823,555,810,677,708,118,767,910,225,780,176,377,120,590,671,107,371,856,167,211,251,878,894,55,485,573,817,266,810,499,165,982,740,378,470,26,556,747,870,760,517,343,540,877,19,298,545,630,389,643,661,391,405,768,498,57,221,213,568,429,461,669,228,801,813,973,147,854,920,328,453,575,394,679,951,518,803,820,824,92,185,349,889,902,794,251,680,457,245,934,844,160,425,697,283,310,494,569,165,115,880,274,516,751,257,831,472,812,877,562,703,293,61,5,906,649,340,248,639,482,216,730,100,282,290,903,638,647,798,965,99,69,470,84,462,69,96,912,66,568,648,903,580,77,309,901,692,114,36,374,87,62,300,236,98,711,842,143,84,556,455,127,457,459,267,778,693,383,101,937,7,69,40,803,278,624,943,522,545,810,862,894,58,467,33,536,311,110,396,858,13,829,252,771,107,351,927,149,828,794,633,399,710,839,641,979,489,797,372,3,35,399,658,147,164,471,273,201,203,640,581,971,962,772,300,385,794,239,12,37,295,225,989,977,63,168,152,6,921,403,903,879,37,159,20,833,481,897,753,369,687,164,126,347,839,27,212,740,804,265,569,828,488,507,68,209,188,275,551,477,301,46,394,932,137,953,482,31,696,483,861,563,575,981,767,992,430,11,823,49,458,97,501,525,663,281,926,108,374,572,734,744,411,846,314,293,998,611,692,545,767,777,640,406,939,875,731,444,161,293,600,103,961,953,614,11,432,436,616,243,240,416,223,532,930,79,526,617,873,259,858,550,446,230,565,8,299,461,277,527,68,862,952,132,562,728,295,75,661,545,282,831,527,712,801,852,744,954,771,954,616,231,616,123,115,254,577,803,223,430,956,167,23,137,751,688,220,929,307,769,509,897,456,676,917,597,697,209,176,94,663,400,911,976,382,816,986,356,87,911,215,582,258,921,990,562,822,391,736,746,706,659,875,727,330,862,936,56,830,884,592,280,380,751,651,945,615,705,347,798,581,649,822,156,563,883,554,295,216,594,188,201,986,482,0,143,97,985,726,877,957,525,21,476,730,293,757,524,642,480,297,1,659,398,474,876,52,921,67,744,53,453,830,352,403,976,498,54,685,549,760,30,25,35,413,3,249,398,576,768,633,896,915,652,211,398,165,642,396,588,571,505,88,616", + "715,915,520,773,972,942,221,478,279,90,717,992,160,939,604,400,715,199,583,879,252,540,211,592,815,907,109,300,598,276,767,541,514,302,201,172,145,539,407,298,788,986,220,426,742,893,985,786,239,292,11,894,778,351,887,772,984,230,462,22,557,222,475,638,120,819,496,443,717,886,928,516,908,226,77,45,771,714,945,330,470,614,630,590,213,572,272,41,654,887,158,501,388,406,112,850,516,961,556,294,911,494,130,7,767,260,656,382,698,181,898,827,542,463,529,635,461,428,635,671,226,892,921,976,824,553,852,361,554,572,296,784,283,736,715,560,525,137,458,854,412,706,294,438,346,372,855,172,128,801,189,164,541,728,171,175,946,242,323,469,13,735,475,344,925,217,928,606,279,959,771,189,417,854,551,490,665,813,982,79,84,549,982,878,457,56,251,384,219,886,243,551,110,780,496,466,929,210,249,559,116,817,779,308,341,346,16,89,252,790,273,901,936,258,306,898,404,370,938,431,498,840,974,720,477,120,120,567,902,142,528,919,993,526,488,767,192,360,664,961,529,222,119,66,582,527,429,48,53,3,698,595,140,895,318,560,440,787,643,182,323,469,216,737,848,710,21,693,157,990,686,269,868,675,893,371,130,14,898,194,948,92,47,859,349,507,184,677,431,25,461,578,492,724,235,535,418,347,30,659,793,427,116,5,327,183,171,38,959,358,541,700,753,623,687,154,583,782,728,723,243,344,72,700,112,467,267,665,81,222,438,612,605,4,176,61,511,248,238,398,916,166,586,649,599,65,950,395,807,849,790,736,799,268,599,789,616,785,799,792,26,442,471,647,51,657,184,661,430,770,696,165,308,503,260,466,846,346,872,114,959,962,452,676,394,781,659,83,399,153,972,517,278,175,936,814,750,335,142,468,956,888,32,160,136,815,268,114,98,915,323,485,384,306,509,431,739,871,323,334,945,196,50,839,612,674,952,682,795,670,215,299,427,811,402,427,48,280,935,618,919,422,805,461,860,801,240,341,250,711,138,562,490,137,185,982,867,690,228,159,825,929,28,816,742,999,884,854,210,712,511,601,91,8,107,549,258,301,327,296,78,998,922,893,780,866,907,21,227,121,139,352,21,530,760,515,957,712,420,995,699,184,700,545,603,995,735,800,855,113,991,347,422,821,310,236,900,635,549,813,352,545,590,573,341,16,950,929,490,412,749,569,278,381,460,675,193,781,933,186,287,157,355,976,178,24,594,244,489,947,93,344,307,489,768,540,189,359,401,122,481,722,658,847,591,673,89,876,342,189,509,647,35,784,556,601,825,903,920,746,481,380,386,853,160,733,179,397,829,434,891,830,660,657,567,475,578,263,177,919,529,668,350,164,869,723,549,946,486,547,896,253,33,259,903,932,823,467,369,563,309,996,346,748,450,206,488,694,911,123,913,607,886,782,741,909,650,124,915,350,863,527,877,63,576,458,100,165,695,933,158,958,832,411,903,33,5,144,194,496,200,31,725,872,874,484,631,785,459,488,898,257,658,747,582,888,79,698,703,28,102,966,528,559,657,398,38,931,148,561,946,117,96,951,203,926,877,406,305,694,983,492,232,428,851,548,150,658,618,987,604,842,610,601,223,290,612,89,831,710,269,336,39,396,871,614,429,288,917,315,248,911,94,943,617,127,589,297,748,172,573,138,306,521,443,75,170,570,195,299,213,240,269,353,29,962,481,537,332,212,670,787,337,588,350,187,127,766,355,172,863,191,513,390,761,347,532,246,440,356,594,726,21,954,809,28,600,483,61,37,957,374,554,901,483,119,768,349,615,677,994,206,365,531,154,990,937,487,133,782,136,901,837,265,788,121,800,485,408,580,972,313,964,98,117,719,746,403,468,274,908,724,682,228,458,717,323,741,409,434,112,472,621,675,288,439,44,518,417,177,415,185,394,805,387,864,172,270,923,366,417,781,927,913,778,768,540,883,532,54,634,57,992,902,523,100,898,239,962,663,431,25,436,522,31,965,306,654,347,126,515,344,822,679,902,891,976,328,262,17,633,972,743,739,291,514,494,658,796,649,85,549,381,510,744,501,601,460,402,509,935,780,722,945,109,759,349,809,446,261,427,932,485,588,310,29,258,174,437,951,143,0,92,222,566,88,327,830,173,885,616,593,532,146,645,258,502,79,341,117,628,182,409,943,835,667,568,479,483,574,602,989,826,33,491,993,4,651,962,897,43,1,478,12,603,250,867,620,531,684,265,849,828,942,727,353,249,898,456,566", + "607,662,335,13,42,128,962,763,705,954,749,874,152,414,46,7,94,51,667,362,167,692,214,790,155,521,15,945,248,66,384,236,973,947,48,482,666,790,749,599,105,104,838,151,565,365,481,424,705,46,764,809,25,191,298,345,655,605,508,916,534,401,171,517,591,44,405,715,566,825,278,121,526,662,340,905,24,818,150,576,457,93,573,694,485,769,934,296,598,937,113,565,232,770,416,666,427,985,342,33,740,391,836,286,369,755,858,430,196,23,63,186,522,309,891,253,186,808,523,72,39,748,791,183,49,598,666,458,214,965,952,869,485,217,497,92,705,999,723,594,954,220,737,429,708,934,682,488,997,926,599,95,595,843,62,880,803,248,635,712,888,399,361,225,673,796,519,221,881,171,54,849,864,653,532,864,473,575,273,574,191,105,541,765,831,645,185,182,278,987,683,750,378,86,779,291,161,987,427,480,318,149,130,828,697,316,610,229,992,582,847,891,103,439,828,998,839,510,664,819,918,914,606,427,158,259,697,570,797,899,983,742,580,459,30,676,947,979,465,241,352,503,573,114,585,402,162,690,973,300,239,356,732,247,363,389,204,810,997,454,846,148,217,402,899,407,261,93,494,264,416,89,909,493,930,848,338,583,534,391,423,932,904,369,891,270,73,563,168,215,253,739,452,151,187,791,569,277,537,853,493,124,273,134,301,683,50,558,72,443,337,997,809,649,180,719,363,891,393,559,238,437,293,787,873,59,54,518,751,691,998,75,436,8,662,136,392,75,599,900,331,703,193,294,743,363,257,226,37,618,915,500,525,947,421,203,42,857,918,962,59,390,532,329,742,823,342,246,886,166,685,367,800,212,414,259,622,555,71,153,446,684,370,647,333,839,707,407,704,264,845,920,411,743,303,538,720,928,253,556,913,480,993,6,205,132,186,307,608,623,402,520,995,637,128,732,840,492,410,359,207,396,559,174,221,590,157,832,636,570,904,832,908,718,682,338,420,383,936,590,927,603,954,890,521,791,544,486,868,889,386,356,908,914,488,44,26,183,346,329,99,852,605,762,582,131,262,797,548,77,410,986,358,168,614,432,990,958,649,132,187,251,207,308,668,63,575,291,159,281,478,124,310,925,583,406,807,795,171,115,633,352,695,775,589,934,902,673,915,227,779,771,555,292,830,201,63,820,374,731,890,807,812,283,712,615,503,309,196,407,151,22,475,694,30,789,590,947,976,682,409,633,973,688,28,586,632,720,725,282,307,661,846,633,603,727,541,691,901,636,93,575,248,883,520,601,413,788,209,497,921,771,529,808,616,540,805,872,521,974,839,203,184,972,714,112,948,260,797,354,457,467,548,675,72,494,379,183,896,536,821,928,856,653,471,611,1000,621,22,419,389,584,3,923,611,973,252,40,721,131,552,914,828,326,664,365,547,351,880,571,934,529,735,53,480,554,977,986,425,671,820,793,506,723,731,878,833,761,272,319,935,593,937,354,343,816,299,984,878,783,57,151,95,755,29,98,330,681,852,98,680,880,241,479,312,257,570,538,237,744,882,435,752,191,754,875,861,473,535,325,666,752,44,718,199,314,466,340,830,365,935,607,240,220,630,433,626,693,677,49,860,754,371,710,903,734,312,340,521,114,168,904,580,484,428,608,766,745,221,704,237,217,248,824,579,569,132,504,255,338,356,576,74,157,335,981,920,774,116,21,393,34,803,474,601,415,375,903,3,88,494,655,156,382,185,586,903,545,808,444,222,62,503,707,584,835,150,108,535,127,141,954,251,835,967,136,987,787,127,883,572,994,197,162,719,110,19,211,782,133,558,580,499,811,194,797,598,966,542,568,886,42,376,630,957,249,79,959,796,736,253,836,439,357,42,587,462,105,578,711,495,358,999,72,553,215,352,790,462,776,509,74,995,433,534,505,114,35,624,544,961,98,672,111,821,339,18,516,859,121,374,101,991,778,291,464,930,288,432,967,632,498,769,997,245,316,911,104,840,178,5,602,828,342,127,799,517,666,356,522,59,312,620,91,362,320,154,502,569,245,627,513,972,223,684,429,767,522,204,438,192,454,22,644,629,999,262,796,39,640,618,48,174,185,906,202,453,824,140,526,245,618,196,664,105,641,768,716,938,580,97,92,0,993,504,971,854,121,56,236,73,165,580,101,120,957,391,387,375,829,766,979,67,660,962,858,680,198,86,6,548,534,61,827,654,194,401,902,220,292,591,797,410,27,884,723,949,977,534,371,372,397,670,226,765,292,304,418,8,973", + "502,284,561,374,463,811,393,842,775,781,468,73,358,548,266,763,447,136,713,464,781,699,147,42,946,133,57,168,958,328,207,364,994,395,332,986,41,487,671,35,887,713,328,862,385,675,242,865,2,140,633,694,407,850,169,47,895,944,606,820,654,382,418,500,221,25,43,33,629,562,468,6,103,835,297,415,463,115,206,288,55,60,727,566,47,430,201,92,878,821,175,23,172,151,386,540,599,87,442,785,917,947,872,892,598,308,154,725,337,780,328,608,849,304,513,779,72,859,14,664,889,834,5,278,839,357,121,794,856,68,951,656,879,978,847,264,28,883,327,778,36,474,185,816,873,661,913,268,516,263,722,409,365,646,60,807,639,782,959,367,941,639,377,187,183,710,68,524,463,506,804,207,741,255,679,957,315,317,643,775,353,13,352,254,167,943,733,295,186,394,733,433,502,198,198,61,313,216,455,444,710,556,828,333,313,799,628,539,515,278,75,119,800,611,541,520,605,405,983,258,83,369,205,93,808,160,594,48,64,904,29,504,597,719,58,150,856,746,194,781,746,300,402,374,99,367,222,906,502,281,5,9,841,785,85,424,545,687,186,868,598,269,183,505,99,716,978,506,849,96,958,403,382,590,482,774,649,699,376,698,317,86,793,658,734,58,743,99,499,641,381,949,43,410,499,450,950,749,612,590,202,54,540,130,702,521,39,73,969,184,161,20,741,701,730,789,304,537,90,573,711,781,562,446,814,325,412,78,359,467,87,717,287,658,124,132,354,536,760,456,392,972,218,106,157,115,489,422,289,97,283,851,424,177,718,184,945,326,272,185,839,590,564,735,47,529,419,61,62,877,816,695,790,505,386,714,933,202,373,378,249,781,316,783,737,790,605,131,13,173,706,654,605,875,248,893,988,418,537,650,403,11,165,120,385,924,309,195,592,313,868,832,926,943,942,478,86,508,934,457,218,684,146,48,167,85,568,82,118,74,190,89,543,672,132,365,673,226,146,512,522,614,233,146,272,191,404,985,581,321,222,15,548,915,329,45,486,440,62,724,824,289,386,21,681,443,185,722,444,685,559,976,361,234,912,502,701,326,989,780,656,100,704,21,642,701,23,746,585,909,62,113,922,640,625,833,202,534,245,567,252,217,305,698,168,341,972,347,988,735,573,807,81,500,21,564,903,10,683,494,546,993,777,158,94,398,849,860,208,215,744,496,281,774,752,71,959,157,774,72,491,830,446,847,316,951,507,115,525,438,57,202,344,644,685,133,561,875,857,334,720,602,954,906,592,47,274,877,94,951,787,262,590,433,534,412,150,371,271,875,523,236,581,116,236,938,794,277,182,80,687,119,574,188,262,721,25,645,665,296,470,499,714,960,638,61,416,670,481,130,763,851,522,277,627,98,366,853,242,223,47,49,774,171,742,872,7,738,99,602,954,775,174,101,703,331,368,554,837,790,21,440,765,597,302,954,441,80,978,130,786,105,665,136,368,507,595,538,218,143,952,782,122,882,203,312,517,967,164,498,413,217,51,861,637,364,645,374,117,570,744,946,979,315,468,665,132,75,814,34,337,443,461,776,549,619,661,561,530,936,451,428,794,675,926,198,286,987,437,433,833,573,158,742,787,784,122,58,387,143,88,528,664,794,117,141,578,936,98,523,89,967,327,369,164,648,651,639,623,951,281,967,538,699,110,322,432,109,837,411,946,751,273,347,992,919,129,727,303,152,632,936,327,497,130,93,561,149,33,314,788,260,510,35,264,657,315,808,286,140,441,394,265,216,294,548,302,265,201,346,792,118,691,43,548,412,372,199,752,702,635,646,66,968,486,344,234,813,828,131,339,318,116,901,926,377,544,676,499,421,573,350,81,555,892,171,699,986,969,832,704,889,52,242,953,581,324,129,701,477,330,77,501,469,916,11,65,234,895,70,49,128,506,915,872,893,225,113,599,463,772,616,652,942,691,245,470,619,771,995,425,550,798,752,3,176,570,102,908,524,875,471,531,138,752,76,564,320,499,194,509,896,916,711,232,657,682,980,344,453,894,357,543,278,185,241,980,312,185,609,510,574,127,104,491,449,829,566,434,256,901,883,619,430,365,673,213,962,758,3,956,611,881,12,248,506,966,560,615,286,985,222,993,0,645,526,561,333,725,24,682,940,354,316,47,562,701,285,110,248,871,110,146,739,86,330,786,169,654,119,741,805,132,412,389,736,742,424,547,617,876,351,879,985,283,133,285,84,653,917,923,859,869,995,260,290,586,90,11,24", + "400,749,873,709,353,998,64,479,980,841,259,547,759,918,676,869,732,251,268,590,737,20,769,310,692,77,592,122,679,68,286,85,107,93,204,318,484,635,814,813,943,600,432,493,823,255,904,423,973,776,598,416,94,205,408,314,689,79,851,110,465,367,457,747,573,923,176,831,337,991,937,391,42,254,348,533,742,224,12,780,676,297,654,621,860,527,627,718,515,523,175,589,313,433,362,965,458,884,60,116,180,343,444,837,524,572,517,892,720,189,70,847,507,221,336,568,730,916,75,652,687,242,732,101,34,538,304,872,918,622,140,727,454,24,240,476,819,767,399,971,949,984,613,640,729,444,324,324,337,254,312,246,291,353,261,274,186,373,59,8,682,803,976,368,596,691,274,93,173,201,63,56,44,196,835,38,137,720,46,3,426,690,944,344,173,919,319,278,29,993,300,947,78,104,401,90,901,751,853,304,459,705,907,368,300,624,998,903,85,763,598,17,443,610,62,975,956,454,776,778,332,791,98,309,428,900,910,868,6,547,164,661,780,913,692,677,582,402,795,726,486,292,492,947,360,805,962,72,47,100,840,947,781,643,490,802,69,716,62,962,298,64,780,104,729,640,256,93,406,965,395,815,844,201,468,393,253,131,592,759,843,985,783,878,898,511,681,192,277,522,37,708,885,192,980,84,22,473,169,236,907,392,314,951,91,87,151,35,315,644,520,529,214,14,298,986,676,676,65,932,359,95,851,138,597,305,461,906,22,721,774,410,592,320,158,445,738,49,593,60,959,603,734,200,640,749,400,418,955,951,355,764,365,31,863,872,628,151,62,105,827,736,471,559,960,667,838,954,101,749,779,860,903,171,532,247,567,496,243,141,742,494,74,552,850,450,572,261,770,827,53,973,42,266,237,792,781,479,656,882,944,583,740,493,180,780,965,580,659,582,214,340,764,724,857,748,315,514,91,955,42,80,734,182,501,194,961,12,502,519,180,789,527,887,390,828,800,12,410,781,226,366,2,689,497,683,828,171,806,343,53,761,731,628,250,929,521,904,166,77,533,803,609,15,416,180,882,355,520,264,231,713,957,476,379,82,351,862,871,327,178,287,150,273,403,612,327,348,9,177,210,315,502,563,416,388,651,792,419,535,214,298,946,671,512,798,880,542,500,457,603,922,614,115,260,433,622,473,646,981,900,959,515,141,406,751,884,321,498,817,103,808,19,285,726,317,575,318,301,914,769,392,836,621,603,418,619,867,604,189,724,462,562,792,289,521,553,337,921,434,401,362,804,432,989,179,673,151,866,598,794,293,907,817,318,814,151,300,392,376,32,845,844,852,48,236,585,758,811,797,497,223,459,993,879,10,277,594,907,286,127,700,38,533,941,143,72,910,727,147,221,548,267,558,856,226,466,764,327,50,804,651,660,644,231,353,257,118,652,693,18,481,180,117,55,265,104,149,617,532,50,896,228,924,190,851,55,98,459,590,18,406,212,233,412,151,862,741,584,409,861,740,129,583,96,36,939,933,364,926,469,967,364,784,57,56,959,730,758,595,366,782,752,867,755,791,276,298,643,564,422,348,329,716,403,569,931,981,971,191,411,230,947,672,474,23,877,517,190,572,804,254,430,742,496,73,922,441,534,938,900,290,21,510,772,15,969,615,172,58,758,316,328,617,609,221,744,742,122,795,163,417,506,102,506,559,581,171,101,366,220,160,396,473,479,237,961,505,501,611,579,109,330,74,91,587,178,171,637,721,540,623,317,35,315,441,913,194,479,264,227,153,539,905,595,331,488,296,837,199,426,88,600,562,289,293,26,84,906,755,601,727,485,787,279,66,145,807,776,288,46,969,274,840,954,499,984,942,50,772,362,781,472,219,674,861,54,601,813,440,37,417,988,177,324,910,948,9,291,916,606,144,80,899,898,667,33,199,920,781,131,813,958,618,328,456,293,414,265,359,966,619,290,534,75,846,842,185,861,957,23,92,463,247,784,58,277,287,307,244,47,590,105,913,501,155,774,173,268,232,907,937,45,252,772,917,494,477,484,443,296,777,47,171,928,654,811,980,257,566,627,976,344,725,292,708,21,752,632,319,602,44,768,554,715,422,580,980,281,763,574,898,647,802,342,448,679,79,722,144,726,566,504,645,0,523,39,72,644,772,887,985,955,473,308,455,624,549,142,23,516,292,418,984,699,363,793,586,103,62,332,876,433,325,12,577,490,350,412,25,475,624,471,529,779,333,712,208,740,128,445,490,252,671,819,321,289,233,908,661", + "937,33,916,839,417,103,522,185,820,49,366,295,727,936,615,740,413,645,108,828,587,313,452,149,457,229,991,28,254,351,208,793,989,897,342,224,712,770,859,55,990,912,910,87,379,958,422,447,454,701,718,627,809,777,178,830,988,459,858,330,78,322,768,410,240,232,193,176,424,130,59,316,426,329,590,793,41,312,799,858,965,314,671,405,424,884,71,715,51,217,564,654,217,432,834,311,851,534,565,120,106,74,737,2,977,345,587,563,751,721,124,680,849,553,238,691,636,285,434,937,276,957,991,64,135,260,697,69,247,372,721,354,759,326,969,482,361,567,610,254,662,856,207,196,218,990,509,365,566,163,429,21,448,866,944,815,539,484,427,755,500,782,452,244,373,305,829,738,833,90,175,399,90,981,7,769,837,49,302,452,312,830,127,487,67,631,629,301,427,470,171,537,599,683,825,254,348,253,130,119,136,657,898,323,214,166,847,263,261,372,903,410,475,846,57,111,138,390,139,722,219,121,177,43,591,907,144,998,528,730,689,265,518,450,456,286,581,157,60,196,214,980,205,475,984,914,78,303,450,383,213,480,383,499,279,463,748,751,325,133,993,153,530,459,330,345,949,379,717,476,296,290,1000,178,557,534,796,711,704,166,298,295,999,187,267,657,764,610,157,385,222,755,552,606,554,307,390,119,733,101,126,598,631,894,104,153,250,207,154,746,572,813,207,211,570,639,380,122,275,781,349,760,809,65,840,838,636,38,930,406,797,492,601,693,924,23,470,204,692,248,888,44,355,127,515,599,807,128,770,606,747,463,477,964,62,502,532,727,457,496,488,41,241,391,625,693,582,349,526,224,979,692,479,463,757,476,566,281,450,989,519,157,362,378,927,839,800,354,390,674,599,300,827,276,56,124,947,780,526,381,604,404,14,152,27,877,805,76,584,652,665,404,208,93,675,550,387,140,784,987,49,972,556,199,498,250,747,705,863,429,197,595,601,718,309,11,391,150,555,620,450,754,535,127,847,785,80,35,146,656,699,738,225,959,719,90,406,403,727,55,445,361,581,127,778,537,893,364,886,330,822,150,121,612,395,967,518,62,49,681,800,504,329,920,756,185,509,798,21,342,807,937,306,697,871,430,216,5,427,674,369,637,546,747,671,324,408,50,736,246,327,371,89,655,436,535,585,419,112,463,960,489,763,208,530,760,447,816,975,845,469,123,971,747,756,698,884,477,895,251,20,952,178,691,140,724,954,771,686,742,610,407,523,78,841,643,292,74,451,214,733,378,929,229,415,509,9,740,171,292,889,337,54,537,548,620,963,154,178,345,937,988,1000,955,579,60,975,527,573,703,56,712,836,828,391,477,57,219,441,665,949,596,43,670,516,477,733,959,532,612,550,69,556,390,927,98,966,546,981,145,602,400,706,99,187,79,750,816,267,674,383,788,626,106,752,906,892,540,651,702,167,939,564,192,823,16,458,749,980,575,350,431,606,282,72,52,330,745,586,505,660,995,514,908,855,795,72,261,501,728,159,706,145,302,728,212,578,861,442,781,995,993,459,25,15,361,589,223,712,865,856,680,233,166,565,215,162,336,233,143,136,980,443,594,43,162,630,349,479,207,760,832,246,538,146,265,405,449,229,893,56,919,313,356,44,893,652,979,739,67,832,540,540,367,25,934,452,724,908,701,855,187,353,117,151,236,220,455,745,791,571,602,752,569,354,241,582,657,670,85,878,747,641,64,170,423,399,837,99,873,242,62,297,884,695,385,191,9,763,898,605,608,904,165,64,716,520,582,509,112,689,654,760,13,457,659,78,785,923,557,735,425,382,469,611,500,574,212,609,234,203,407,895,447,609,461,384,990,874,706,433,961,511,947,254,135,53,420,452,242,478,10,959,467,828,74,875,921,816,417,988,736,147,735,14,411,691,20,919,143,863,994,751,1,435,821,274,80,366,782,21,952,539,285,884,124,199,998,709,825,364,774,398,838,858,531,433,353,558,567,109,451,583,871,677,591,100,358,301,223,867,929,805,198,533,925,809,137,826,700,177,164,80,111,530,366,327,112,484,520,921,479,766,697,8,969,302,29,541,156,761,441,256,493,418,242,959,177,953,723,906,929,453,804,354,398,480,26,481,487,877,88,971,526,523,0,418,5,512,926,489,893,790,70,953,981,861,144,618,643,213,62,926,883,283,253,420,281,932,341,261,721,486,968,93,903,21,549,948,906,500,306,178,232,440,500,227,446,466,812,727,176,788,84,759,186,231,988,910,578", + "653,812,478,956,733,821,277,97,673,876,427,776,755,159,956,15,501,466,425,182,62,273,513,5,543,548,176,826,77,768,950,266,630,84,417,503,389,650,885,435,833,328,628,845,35,552,589,520,320,943,374,675,662,846,102,504,583,531,124,821,101,188,705,783,522,545,900,706,554,910,779,82,552,118,683,931,457,615,112,317,26,68,847,462,752,940,52,613,744,30,297,42,575,416,989,979,14,623,311,380,275,251,931,237,140,720,397,150,977,212,827,936,557,854,310,592,162,760,756,36,680,273,321,594,246,256,918,428,531,940,340,776,122,370,126,384,675,320,409,894,171,449,445,778,640,224,577,896,498,510,808,333,28,874,772,283,983,287,132,128,66,82,357,57,20,266,842,878,958,961,602,179,897,168,328,785,95,827,519,648,570,352,339,990,77,856,259,205,915,491,597,584,578,800,715,475,923,234,464,422,812,385,534,533,86,152,89,315,671,464,995,826,235,400,155,952,410,513,983,987,703,681,631,118,153,527,260,300,954,849,547,471,263,570,34,287,159,1000,610,793,198,458,788,854,832,759,633,280,469,663,506,36,755,888,946,643,549,181,349,126,999,75,795,151,807,629,865,358,385,990,655,202,716,894,498,801,633,115,117,430,724,559,944,534,641,656,119,660,500,505,314,18,573,354,1,295,300,525,368,250,84,832,669,224,423,105,708,231,224,508,318,458,728,713,355,736,844,902,420,498,440,767,579,711,139,423,112,558,643,342,854,344,299,799,692,656,758,941,399,795,349,164,724,479,903,407,258,306,409,863,982,3,352,616,609,49,403,676,167,774,225,622,484,98,531,365,434,432,50,635,669,800,672,145,214,708,713,738,634,93,710,449,245,210,538,359,928,662,172,782,929,740,366,54,456,974,878,266,106,300,335,41,328,884,498,359,657,854,60,658,999,322,345,220,936,915,242,674,418,9,765,5,867,795,452,773,759,957,405,443,570,620,421,419,966,450,493,315,198,951,228,303,902,994,107,585,50,27,104,654,933,305,566,89,476,577,834,246,227,341,712,637,36,960,321,415,309,868,71,660,80,722,198,961,549,51,933,914,754,777,564,359,824,439,808,11,556,796,796,933,262,657,186,12,121,190,581,765,852,603,236,432,255,407,83,723,997,474,626,341,625,767,955,596,581,148,443,891,588,321,877,554,945,521,266,94,404,735,343,992,435,521,238,958,854,275,672,324,439,132,17,299,790,39,373,807,743,217,26,623,695,104,968,79,406,487,191,668,75,443,668,608,564,366,857,825,615,935,629,878,462,30,304,916,313,386,219,350,104,974,34,944,524,472,666,660,95,598,687,294,359,813,137,718,826,652,281,615,708,877,318,108,554,715,325,533,882,93,496,341,913,561,136,186,105,886,468,239,729,180,967,127,110,90,807,386,552,947,829,444,310,319,740,902,805,185,1000,731,840,659,667,791,50,135,431,435,857,450,935,307,644,645,775,301,205,131,479,191,40,915,97,201,945,681,981,3,686,217,436,443,167,802,639,207,623,264,832,816,181,99,476,992,683,724,268,470,484,795,857,929,96,687,26,755,431,554,997,980,334,58,365,24,622,752,268,342,131,690,900,336,78,217,763,917,422,422,682,892,945,310,144,238,47,851,93,211,640,237,373,284,570,548,394,74,114,315,378,831,267,193,738,259,942,348,291,805,180,270,232,649,141,417,794,857,628,404,586,240,51,735,287,959,75,160,98,885,371,600,649,240,552,837,512,593,927,100,60,526,352,101,601,155,649,604,343,463,424,62,407,131,979,895,716,359,289,658,691,497,51,164,622,139,787,447,118,759,712,868,56,253,876,458,787,292,836,727,290,445,279,266,900,599,172,928,18,977,579,429,218,84,427,774,266,517,927,844,261,762,140,135,711,590,796,97,184,873,108,553,322,589,343,67,834,529,481,851,126,593,224,350,202,54,830,870,837,184,287,831,874,100,625,864,776,700,622,253,105,849,998,673,399,760,489,130,206,667,227,442,606,908,594,88,489,628,189,453,847,637,629,17,568,841,130,262,890,812,16,281,323,58,675,277,833,698,393,846,68,602,699,31,496,261,366,552,901,149,682,519,934,275,95,149,400,519,226,348,238,940,888,708,957,327,854,561,39,418,0,46,302,693,80,940,473,69,779,258,562,926,832,529,72,633,361,753,493,953,438,902,873,268,31,106,874,515,832,435,265,670,515,123,90,979,883,985,883,223,344,891,931,700,291,831,558,138,704,144,858,816,135,481", + "653,480,11,600,999,190,372,907,505,372,458,975,850,70,822,227,421,690,820,291,487,219,883,692,276,279,745,477,723,810,537,182,537,676,958,942,925,92,220,579,868,52,164,155,654,614,243,821,62,153,792,119,487,355,526,360,280,542,969,361,619,320,131,4,569,829,679,646,701,337,386,470,327,961,297,591,550,461,140,639,445,283,853,573,396,975,717,696,5,208,721,67,90,634,320,635,644,456,922,611,222,568,956,304,313,386,128,648,638,12,530,918,832,52,849,894,751,591,579,3,477,424,165,253,810,448,255,856,960,760,341,326,933,849,276,443,364,560,694,36,782,179,820,503,131,571,167,983,909,980,228,408,447,661,808,885,521,396,226,666,973,93,28,197,526,174,780,178,673,556,276,430,136,584,535,616,564,275,317,852,917,801,576,560,839,623,99,921,822,736,421,764,856,412,247,450,765,867,960,216,324,225,25,978,195,232,239,631,763,596,929,134,178,244,714,67,763,944,578,52,365,163,175,145,117,777,91,98,716,472,517,807,217,612,731,160,704,767,985,701,233,158,212,175,537,289,581,773,878,360,265,206,852,649,862,898,387,463,457,563,891,900,427,106,212,549,530,176,789,67,21,735,802,112,144,323,812,622,833,457,168,389,328,629,172,218,962,35,3,155,383,688,753,486,721,209,107,16,109,503,168,272,579,306,105,866,750,924,562,438,562,834,263,182,55,63,436,80,647,255,669,214,805,27,958,131,132,536,362,720,210,643,217,723,239,630,728,567,33,233,36,929,343,629,618,803,671,631,936,191,831,76,472,132,578,754,269,322,947,555,766,859,35,53,269,337,641,560,458,586,605,103,101,718,798,2,691,891,739,936,923,240,478,739,182,198,675,428,899,341,75,896,322,105,786,178,532,263,327,172,925,427,354,956,773,274,139,820,126,703,534,169,483,865,765,674,299,606,105,138,830,111,986,388,473,329,688,779,574,388,997,640,254,46,270,762,574,886,803,307,542,756,370,103,619,267,158,647,284,63,794,854,949,833,3,411,176,755,339,589,192,377,737,494,321,533,236,828,704,170,622,680,573,226,849,946,790,810,382,718,65,603,605,711,493,884,609,677,324,384,92,408,994,261,275,939,68,303,655,340,366,548,796,505,852,294,221,514,717,675,499,221,183,583,832,326,358,203,260,152,267,783,363,849,147,842,310,432,245,349,22,886,164,972,321,767,459,250,612,115,853,273,542,764,43,981,165,864,160,634,380,585,670,983,101,835,438,953,473,877,939,974,830,626,477,370,244,13,427,288,501,535,154,44,560,998,328,557,3,317,951,804,225,616,933,200,68,447,890,359,590,731,249,979,56,329,979,772,967,656,308,149,239,970,716,135,667,41,125,756,78,563,955,262,277,565,953,800,970,730,150,619,350,933,11,349,392,986,847,222,577,749,229,435,368,674,779,46,689,2,519,146,896,517,663,435,836,576,795,206,688,489,367,266,817,372,773,156,640,611,660,512,180,831,708,322,734,153,366,466,662,252,561,110,958,687,136,468,963,220,235,449,296,785,17,525,335,379,141,686,218,585,213,493,527,378,388,128,873,471,505,751,632,964,798,958,881,497,468,12,955,122,175,965,768,189,538,298,167,787,663,993,60,967,227,877,712,967,802,548,905,627,312,914,955,305,570,328,225,886,739,605,314,561,935,394,718,344,618,741,575,975,689,903,667,21,229,42,867,634,919,797,765,90,853,442,692,89,955,747,765,529,918,110,517,888,294,931,980,563,761,723,159,310,182,961,812,169,586,752,154,382,506,869,23,806,956,340,115,330,122,531,598,653,331,311,98,166,143,952,329,475,310,272,646,53,914,649,157,186,311,628,695,886,339,496,43,484,555,868,880,997,581,173,51,676,307,597,516,375,82,846,129,532,523,399,111,307,869,993,591,224,958,736,170,978,381,246,267,457,789,911,461,744,547,972,358,156,628,879,38,227,348,297,776,234,283,191,62,731,350,435,557,908,225,189,163,497,2,643,654,872,184,649,333,536,271,681,747,926,122,297,856,574,783,827,192,495,992,640,362,343,574,936,993,403,314,334,396,348,924,302,951,924,148,881,351,933,773,270,553,756,778,601,134,461,304,602,119,387,525,830,121,333,72,5,46,0,635,206,149,434,157,519,58,436,297,197,460,345,494,22,637,658,539,258,90,718,162,187,436,247,498,833,718,192,345,796,445,787,277,539,675,179,453,647,469,712,126,424,230,195,702,954,35,440,442,38,973,899", + "352,949,470,429,854,73,660,373,679,873,908,291,676,312,879,741,75,188,626,143,328,212,975,752,414,961,930,523,999,970,133,156,958,324,583,580,415,512,468,369,898,46,98,876,338,389,527,867,348,760,639,32,592,787,443,889,358,348,13,723,888,593,728,953,822,212,857,761,959,65,253,258,449,704,268,816,838,165,744,923,869,342,982,22,770,473,888,278,211,34,666,490,346,40,61,851,97,790,115,798,110,24,573,625,104,838,440,263,642,893,789,794,197,167,726,953,529,693,648,763,46,368,512,938,619,389,797,393,258,365,889,604,513,14,342,448,781,33,364,767,157,673,500,9,300,117,893,26,822,615,173,209,659,92,328,98,788,553,643,79,542,66,339,749,755,511,198,696,98,73,615,597,173,694,550,21,89,892,692,11,988,307,980,28,272,896,668,231,613,589,867,344,313,399,31,421,459,439,493,756,532,676,577,883,646,240,354,992,822,555,251,18,319,618,643,782,1,998,871,489,938,13,565,142,61,778,323,41,299,479,678,718,73,541,767,874,513,385,173,399,433,338,107,113,926,920,931,776,14,982,975,666,180,57,399,375,372,982,167,499,661,188,505,134,408,912,992,129,486,219,38,920,297,64,5,346,742,490,641,367,77,127,460,104,395,535,185,980,363,858,572,804,141,754,594,964,114,516,232,838,9,311,94,855,583,202,968,743,431,669,467,842,404,566,279,803,88,472,392,705,277,298,376,904,789,418,243,661,866,48,270,523,387,470,631,724,639,438,583,908,464,249,732,774,800,554,413,797,856,118,176,269,453,956,60,690,962,320,322,548,59,817,34,4,702,611,621,417,657,645,655,675,804,862,39,83,762,173,351,458,401,806,363,278,400,324,83,277,406,935,688,688,9,758,605,94,469,550,796,679,644,655,23,959,195,81,992,389,255,717,104,63,856,143,950,764,33,575,870,458,689,669,431,959,863,186,221,342,99,15,940,814,439,348,61,515,354,190,447,485,620,542,463,717,800,998,868,739,820,245,426,830,122,152,871,837,878,401,221,540,631,348,555,591,52,379,622,250,45,639,667,555,474,312,399,609,962,446,224,392,245,808,780,723,544,187,474,544,253,919,788,453,462,861,921,330,438,941,501,696,475,296,543,304,825,919,590,644,419,769,619,887,798,690,370,931,976,364,455,64,381,407,341,895,16,937,759,250,114,707,65,74,343,233,746,944,923,163,40,906,679,29,731,95,129,713,442,480,192,913,601,264,220,9,753,618,34,193,788,898,263,355,301,822,310,168,859,722,910,605,686,204,738,719,936,584,936,819,458,122,528,881,114,120,390,815,412,196,608,503,393,11,884,538,943,855,182,825,617,975,743,805,322,57,180,333,935,496,925,883,565,370,582,662,152,853,434,132,481,282,321,605,559,839,754,627,291,769,907,935,14,871,788,757,599,702,161,195,628,396,351,543,467,70,696,205,455,820,257,572,621,775,15,183,549,685,307,572,651,172,447,727,187,428,95,963,106,89,74,691,527,24,114,723,811,754,112,264,466,498,155,548,650,562,330,592,14,458,113,629,18,686,829,327,335,238,939,890,439,463,312,13,453,386,361,925,128,102,974,832,972,582,661,112,244,565,665,82,188,972,978,477,59,72,754,730,812,535,763,820,961,931,794,87,821,231,622,382,264,545,212,134,465,394,615,665,328,350,548,856,6,783,494,955,79,773,754,917,463,51,294,93,350,547,651,373,403,706,127,435,486,385,993,139,177,787,378,718,156,215,563,268,849,18,32,523,463,101,953,670,920,830,449,200,97,300,269,366,494,28,93,337,253,189,307,939,510,399,589,963,700,51,403,363,84,369,825,929,821,293,35,776,558,368,130,518,433,728,288,532,498,142,159,989,507,51,628,244,991,725,442,530,995,336,822,668,440,524,753,811,925,664,154,648,130,597,73,102,271,754,964,698,524,920,207,610,660,232,731,446,137,603,687,418,739,394,231,340,256,252,245,716,583,391,146,732,157,486,273,810,763,959,978,968,285,865,381,708,697,640,681,38,750,656,288,231,510,331,121,377,605,55,572,546,12,380,519,138,231,814,720,245,147,917,973,835,865,919,978,383,28,40,206,249,344,30,880,580,680,664,21,173,56,725,644,512,302,635,0,769,877,552,216,212,635,847,259,485,514,736,491,122,912,22,532,490,497,682,978,769,186,650,206,951,533,392,356,860,672,817,948,843,89,940,718,522,987,645,450,542,763,113,779,133,338,268,189,79,994,798", + "619,133,583,600,307,647,484,969,351,354,297,52,4,721,10,790,103,849,391,8,908,47,290,644,859,680,929,11,176,917,371,738,437,519,40,444,988,655,294,89,141,960,986,980,702,352,29,776,690,187,532,362,954,632,393,614,667,271,500,16,662,633,835,372,280,58,742,890,780,820,882,710,373,402,130,375,700,300,814,726,166,75,629,515,634,358,622,920,948,358,356,125,124,629,235,274,989,591,115,51,399,285,510,868,144,795,818,78,306,623,386,80,736,961,76,796,571,12,645,106,820,777,710,122,472,513,750,479,688,392,855,590,577,865,334,918,658,106,222,13,807,568,470,131,964,221,570,698,815,573,622,140,259,865,137,232,278,458,152,619,653,162,792,45,816,548,136,281,512,153,114,332,534,319,131,804,33,32,346,413,629,195,569,386,229,7,4,486,495,662,518,210,406,661,4,157,200,572,958,380,753,166,102,882,824,702,907,75,17,505,20,569,299,696,198,585,990,557,114,554,507,956,590,180,377,208,413,836,494,738,311,655,916,709,345,204,848,294,307,49,286,62,883,662,152,96,16,293,713,453,769,678,93,690,645,3,771,601,77,445,875,549,401,620,54,871,320,435,542,784,873,620,305,324,797,674,231,722,739,311,921,303,813,17,698,938,676,105,345,300,144,617,58,820,466,873,504,708,405,93,837,667,903,939,853,802,384,669,455,391,132,783,456,464,875,508,833,95,723,190,661,966,966,487,181,502,386,281,415,994,865,645,591,561,398,873,674,116,190,540,369,227,23,243,310,311,427,378,674,452,608,426,752,188,744,413,205,209,759,984,685,71,732,521,566,326,707,109,999,869,30,997,17,146,829,363,802,4,599,848,661,972,251,888,915,874,28,782,821,152,603,418,157,105,130,885,102,73,181,693,692,774,878,301,621,654,82,573,700,151,91,13,518,493,607,648,15,503,209,822,287,635,451,973,440,255,720,499,63,499,358,168,374,975,40,910,449,923,61,705,902,376,127,955,798,212,342,846,822,241,488,731,284,932,685,512,225,743,304,953,192,47,912,896,443,103,843,827,157,748,541,49,307,860,180,344,981,311,564,427,901,174,854,721,634,663,50,794,628,709,597,432,164,815,949,364,28,57,792,596,830,677,779,965,688,224,225,489,311,511,581,173,700,790,867,999,438,911,373,330,986,885,365,140,622,904,700,35,134,306,842,601,908,852,888,316,357,43,879,881,690,638,824,369,394,861,328,951,14,79,569,774,143,772,151,235,149,439,169,70,305,59,237,622,749,604,752,940,607,294,663,595,13,288,864,474,913,199,880,195,347,375,524,237,140,641,962,270,314,805,855,759,982,815,125,460,400,566,962,611,441,481,401,338,78,688,905,615,131,404,722,885,485,35,812,621,442,733,809,977,549,327,44,998,545,572,819,589,704,393,396,380,474,798,799,697,824,399,860,213,509,381,704,183,105,427,278,885,957,961,121,246,89,449,982,555,641,919,257,317,12,614,409,978,32,923,249,979,382,874,759,911,316,525,123,519,180,430,346,466,508,718,589,528,997,916,276,122,274,276,699,794,409,410,377,117,731,788,942,42,169,181,85,422,441,176,716,755,579,450,599,372,307,947,50,21,66,310,89,533,616,249,155,882,177,957,147,970,696,718,833,838,725,851,502,566,67,320,632,358,26,774,663,195,647,863,939,823,898,639,710,988,383,651,285,486,627,815,759,195,547,536,250,999,585,526,937,46,24,916,674,648,470,61,626,788,831,535,553,83,622,145,9,538,544,890,193,885,421,603,684,210,356,418,291,243,289,498,172,602,925,898,230,263,554,557,873,696,611,192,770,313,7,119,461,683,955,613,672,850,649,550,797,553,935,452,690,767,701,625,723,752,386,171,802,869,717,554,806,413,376,816,723,177,373,626,607,358,709,477,865,210,238,448,83,644,798,963,786,474,42,152,991,868,267,245,839,518,84,496,508,845,579,132,427,521,51,136,953,275,202,25,976,728,824,9,970,67,510,594,839,280,604,541,649,137,555,160,351,966,872,275,234,552,994,83,209,641,853,118,83,739,340,628,78,777,290,809,728,324,596,29,982,456,935,521,846,400,404,57,778,227,639,785,276,834,825,852,751,716,476,885,236,24,772,926,693,206,769,0,674,374,156,491,90,687,456,997,360,378,708,337,551,955,14,167,582,919,873,941,641,857,918,107,922,86,296,16,511,302,313,322,40,91,695,560,57,446,239,657,455,94,434,862,178,570,96,884,57,145", + "733,947,601,92,510,715,5,19,31,78,67,57,250,883,351,5,473,285,927,866,772,932,153,612,743,612,320,800,589,157,573,581,409,375,630,827,545,754,657,438,293,55,239,350,831,225,882,885,332,238,562,49,533,764,74,488,112,405,334,743,802,953,397,367,952,893,659,981,143,605,856,875,16,541,191,853,682,304,640,918,512,180,77,451,614,548,406,461,248,619,130,639,511,570,158,510,940,531,737,170,538,693,756,560,77,386,224,398,951,501,524,503,78,635,488,405,433,986,768,197,842,709,920,236,428,330,387,865,967,369,881,98,292,471,727,194,164,402,202,514,9,381,573,433,491,171,433,185,264,563,65,859,445,752,76,742,300,158,701,974,259,444,945,94,418,128,604,990,245,467,848,397,244,542,737,24,595,161,111,190,502,611,481,514,607,987,332,196,701,802,579,853,277,908,291,40,980,351,920,377,599,401,812,214,486,251,654,80,691,140,308,712,623,533,264,444,865,453,318,899,521,434,589,131,952,890,858,340,841,247,251,789,155,773,748,698,829,757,812,894,924,757,667,956,706,455,188,245,89,440,327,410,249,825,615,462,56,390,784,879,745,731,897,640,230,261,978,502,390,292,980,276,880,481,555,478,441,943,446,38,201,509,486,779,776,776,174,155,408,777,601,257,879,785,560,994,787,759,35,912,884,313,990,47,242,528,907,109,876,724,432,905,38,885,141,231,111,715,884,442,965,801,693,496,646,340,933,396,82,215,709,231,9,63,904,918,910,496,719,440,886,706,274,195,829,821,42,613,815,588,473,75,976,762,480,987,675,854,450,872,225,437,73,81,334,676,110,991,726,142,682,892,703,210,287,98,678,533,224,920,217,987,252,486,667,494,755,165,590,428,88,756,594,841,494,646,638,865,524,380,461,708,98,529,588,321,40,112,584,261,678,283,595,450,365,507,45,869,820,719,980,327,496,254,92,330,767,73,671,60,285,92,685,562,20,8,573,69,352,218,711,507,558,228,786,791,312,238,594,300,516,315,785,501,113,236,530,357,706,822,536,896,632,97,155,591,638,895,113,830,994,938,455,928,875,131,48,761,630,750,186,954,649,986,709,430,444,826,521,546,400,917,499,70,592,254,186,821,473,826,222,975,172,212,819,535,300,903,259,822,404,363,237,947,420,796,561,901,698,768,578,46,687,936,688,381,439,607,918,656,864,412,398,792,720,422,758,57,510,616,877,823,314,455,376,240,434,320,703,317,119,212,57,58,728,202,796,206,838,837,437,204,104,685,241,366,87,841,955,551,472,668,171,136,797,753,639,455,392,370,574,547,752,832,494,836,39,216,671,219,525,931,863,881,743,366,573,381,377,88,322,535,737,928,752,999,829,328,971,282,895,932,83,694,380,655,397,17,505,462,992,202,306,961,76,768,244,488,297,444,796,977,181,650,563,288,687,269,249,945,169,232,781,10,483,728,848,975,637,612,210,73,819,505,657,640,327,966,586,777,878,333,297,301,25,21,52,62,33,440,154,808,401,500,40,357,739,16,104,97,769,255,374,141,25,624,233,224,974,927,606,685,971,38,589,259,174,123,13,804,935,713,364,70,454,151,650,766,873,10,138,776,22,474,824,527,75,282,408,257,738,596,874,562,81,202,305,404,460,804,457,362,276,318,38,760,489,243,420,429,636,106,891,147,917,613,691,850,988,76,272,421,973,95,737,784,15,831,962,919,171,567,866,952,865,181,415,941,379,608,550,142,797,78,273,93,846,364,548,414,187,108,244,471,306,731,527,326,20,854,165,365,152,63,213,467,387,726,728,565,48,90,788,311,765,126,600,799,641,874,260,505,647,2,435,372,439,285,734,368,379,572,708,8,865,884,630,675,64,799,166,504,950,125,692,664,346,447,637,383,775,887,548,396,450,341,174,74,62,296,872,877,961,630,253,405,724,30,831,344,914,942,903,155,117,426,615,281,740,337,180,174,828,155,45,947,537,579,238,141,195,43,945,99,440,384,404,109,755,861,254,915,371,29,93,719,992,982,662,826,653,801,738,821,414,888,42,257,944,500,228,691,210,762,847,414,36,120,616,411,353,700,329,990,957,862,347,559,762,843,563,999,11,905,287,746,79,472,223,790,730,616,73,682,887,489,80,149,877,674,0,311,172,602,140,20,599,787,575,471,289,388,606,786,839,543,634,720,514,945,984,604,796,189,406,925,228,549,374,315,221,465,947,961,264,414,452,867,650,410,243,625,750,762,565,387,150,746,378,225", + "275,204,973,276,421,315,758,346,667,52,492,991,921,62,188,759,23,452,55,611,813,586,414,34,364,221,756,448,429,670,704,445,854,137,417,369,403,228,268,845,759,967,110,314,283,533,491,886,183,750,219,200,347,239,2,939,303,960,224,338,609,940,670,821,383,528,859,808,147,692,984,479,524,28,863,615,529,63,136,275,172,858,39,441,30,250,616,533,327,346,393,264,902,13,299,250,883,938,937,168,276,498,452,370,749,279,678,856,455,383,478,334,818,831,612,517,170,210,245,453,924,318,481,608,729,435,244,61,316,679,418,975,239,933,474,862,724,720,955,575,720,722,999,646,615,431,727,146,59,480,187,384,570,454,810,453,821,658,602,9,397,628,549,453,459,875,182,813,155,563,597,294,154,421,716,479,986,774,376,341,325,395,951,566,441,684,264,894,156,639,96,12,143,976,306,406,757,619,151,155,14,625,902,708,107,473,362,807,350,896,855,389,11,556,589,306,580,140,575,530,756,868,276,413,190,94,851,838,897,106,736,299,104,778,49,873,167,275,63,671,80,589,757,595,234,965,406,332,629,157,853,458,340,410,735,648,995,922,219,930,740,726,86,631,758,786,70,70,359,491,326,956,209,238,778,101,950,866,356,736,145,374,440,804,192,300,810,490,963,765,689,142,939,825,984,799,216,629,60,614,442,689,412,913,368,928,698,808,49,908,424,131,126,264,618,400,515,411,843,489,122,445,606,875,657,334,341,250,940,792,383,959,528,856,715,222,320,623,928,701,521,697,612,18,424,270,848,323,371,656,437,374,526,823,778,35,733,411,184,38,995,899,759,230,589,78,26,554,410,842,493,629,873,595,363,760,740,43,921,605,280,223,252,355,340,893,270,333,663,813,20,79,939,540,10,130,949,618,668,70,56,282,111,187,726,828,191,205,59,4,44,968,493,561,400,166,487,630,718,310,207,617,213,480,82,147,528,254,910,347,558,674,841,935,520,163,921,273,912,781,363,479,259,540,245,745,201,5,507,22,523,590,73,262,500,130,435,879,997,156,972,195,925,422,779,432,399,901,239,360,250,74,786,144,741,84,880,594,268,313,152,124,172,744,654,162,352,519,685,918,38,209,545,608,604,229,459,497,771,166,50,261,876,501,829,462,173,533,657,606,298,536,447,123,801,774,179,957,931,976,149,402,847,866,10,471,170,390,444,322,721,289,831,223,463,534,823,843,475,695,80,222,209,57,387,268,157,668,376,979,612,819,19,446,764,416,641,541,601,735,870,638,46,259,922,664,500,42,431,581,860,981,555,908,463,603,653,537,984,618,475,280,846,106,296,464,537,319,325,907,456,638,389,598,140,270,242,195,955,484,631,97,77,867,724,153,912,958,954,875,695,388,167,568,456,884,799,691,321,194,130,864,103,878,796,564,430,120,761,709,76,248,566,119,991,531,785,328,985,253,380,162,505,651,64,475,234,612,685,717,242,98,729,540,92,57,442,743,346,683,430,596,658,963,340,859,818,441,766,633,497,25,942,968,322,603,820,193,584,979,123,923,577,572,188,898,118,49,646,623,592,354,371,675,397,980,668,794,32,844,782,439,736,369,632,159,855,919,565,295,161,826,877,409,167,405,14,73,418,876,736,42,727,837,151,204,220,386,788,205,25,396,980,936,437,464,333,691,396,830,339,275,430,660,243,153,756,886,16,649,407,868,424,893,224,436,776,273,945,622,490,589,76,31,874,852,814,224,573,431,366,160,627,185,503,566,234,873,654,394,439,786,493,92,789,75,373,960,422,858,909,802,856,844,748,945,301,911,65,10,871,576,606,699,201,761,143,724,543,960,474,873,511,272,345,20,307,434,240,678,914,777,784,729,577,787,843,301,416,713,694,307,204,138,63,846,928,767,563,696,199,166,691,440,419,392,421,68,388,348,739,590,478,531,965,324,237,408,687,547,126,325,463,892,353,606,841,466,189,206,430,569,835,832,985,858,324,321,834,325,106,171,655,343,701,135,70,812,703,110,463,404,350,118,514,796,8,577,629,358,994,13,332,963,974,105,55,953,853,351,873,892,425,778,945,105,105,343,312,728,435,246,512,134,278,654,957,934,443,248,737,179,158,608,802,110,279,459,994,245,293,593,165,940,985,893,940,434,552,374,311,0,608,843,904,172,92,803,26,607,102,635,576,88,895,565,859,973,166,627,421,240,208,193,77,708,160,174,817,909,827,136,66,610,146,790,21,551,587,596,432,377,911,907,173,352,755,68,886,983", + "753,246,266,650,702,877,35,504,103,980,983,281,413,997,125,122,954,81,854,620,174,14,393,831,554,782,634,181,523,385,585,523,564,58,786,17,320,441,847,578,470,143,1,667,814,683,930,124,121,247,273,822,914,360,508,16,734,322,172,776,605,347,777,245,710,129,196,541,485,97,246,78,55,304,659,917,542,507,707,953,395,844,677,321,696,917,512,333,185,411,118,474,264,600,359,898,612,924,647,617,675,77,683,589,745,55,393,954,296,309,409,22,594,440,389,770,898,551,208,601,255,61,770,201,511,835,577,589,77,193,741,317,781,521,755,416,335,661,2,555,70,404,693,293,812,561,636,751,243,362,114,612,127,334,657,721,828,714,801,901,886,335,703,993,976,363,484,845,633,239,192,580,599,922,861,839,634,631,293,84,616,969,936,91,470,705,25,250,657,817,426,29,974,266,226,197,695,101,456,619,7,895,126,422,747,736,951,784,309,57,20,207,898,944,724,374,290,474,686,642,68,10,889,326,151,692,811,853,192,204,859,774,577,628,449,367,264,146,905,731,659,401,530,793,62,577,597,755,837,843,317,635,386,8,284,424,27,513,477,318,128,621,422,83,568,47,562,359,397,137,81,953,554,162,719,387,382,278,707,89,186,593,514,525,59,56,443,582,862,925,675,924,461,779,515,522,344,846,461,997,152,990,489,804,345,208,464,752,169,579,556,395,456,429,906,170,714,589,37,918,72,248,587,264,388,882,178,569,734,514,805,293,484,939,296,954,16,813,392,929,887,945,748,624,827,790,489,31,985,135,560,758,968,17,161,952,678,839,792,720,85,168,886,517,592,99,418,432,709,898,942,473,778,18,40,419,302,116,53,35,493,286,664,901,379,313,63,782,481,30,788,236,923,875,521,5,239,470,894,471,634,943,918,128,31,809,702,655,917,782,541,931,745,863,291,764,692,994,684,217,639,128,825,522,356,391,154,799,605,921,141,357,854,776,93,607,597,754,992,218,306,64,294,12,160,888,319,557,33,135,570,94,762,311,310,106,455,181,66,356,199,303,895,389,402,745,678,703,662,22,903,528,943,533,74,994,986,938,322,473,58,12,968,476,859,803,635,90,110,151,544,717,590,203,455,512,293,445,729,123,801,671,892,772,171,38,224,855,612,28,189,974,223,472,172,733,839,485,353,722,833,988,471,361,831,753,183,94,336,871,940,110,488,871,470,112,286,347,878,139,630,338,228,928,545,977,87,277,629,120,511,848,97,672,882,407,386,442,683,579,695,586,375,950,143,315,575,216,466,738,261,361,761,670,69,434,433,202,711,730,535,331,638,751,579,9,532,67,292,161,914,575,34,197,218,327,309,945,669,604,124,427,462,610,592,433,237,567,924,297,800,721,481,731,759,420,198,222,43,522,852,751,419,885,806,259,537,595,872,599,81,50,893,536,968,603,291,296,247,902,182,598,946,262,61,313,635,830,902,958,976,137,439,850,719,19,381,704,377,933,714,276,449,979,15,356,170,727,708,966,391,955,283,824,463,233,997,872,765,534,720,931,160,526,593,522,976,745,901,364,498,226,888,427,258,939,697,119,508,690,276,282,111,749,532,463,927,425,212,620,713,441,760,943,656,527,27,338,688,310,823,300,420,215,785,399,493,782,328,785,94,8,215,900,527,623,812,776,752,818,388,82,940,429,543,395,166,93,234,517,808,603,728,738,62,798,720,70,458,977,357,658,716,910,783,900,604,125,18,495,847,203,18,443,316,425,714,951,256,816,601,203,468,377,753,607,114,768,97,247,490,27,880,649,271,448,635,81,216,397,325,889,727,371,710,208,244,517,637,367,784,973,401,628,172,611,513,553,526,16,861,374,94,206,666,214,654,270,797,84,553,977,201,191,533,897,965,209,706,338,116,106,102,418,84,578,741,750,327,961,531,565,167,191,117,27,770,667,527,41,550,437,37,24,593,104,641,798,559,837,138,228,513,159,473,451,369,450,59,892,7,691,421,953,734,362,38,286,179,960,837,281,321,119,195,942,164,997,166,822,59,578,668,971,171,574,769,684,810,263,404,595,436,138,428,258,669,840,93,403,113,910,755,526,74,14,253,130,717,241,700,572,209,704,122,478,893,835,177,510,757,532,580,354,955,790,473,157,216,156,172,608,0,118,772,562,167,574,15,841,696,520,98,647,712,238,886,289,478,627,99,69,193,220,745,662,685,145,220,13,63,484,999,458,943,617,384,995,662,353,604,895,562,502,631,722,662,688,45,251", + "257,782,88,489,158,162,707,455,362,212,411,359,590,28,869,168,94,303,483,643,709,309,556,516,874,715,807,764,748,290,146,969,992,94,221,186,95,728,175,643,508,802,386,798,914,581,853,924,469,701,420,550,516,649,916,376,520,295,850,319,431,786,606,79,813,289,237,771,918,8,518,262,724,316,441,684,830,769,651,436,665,494,362,829,894,237,933,474,446,282,229,141,394,300,172,507,641,439,804,632,321,415,866,650,479,65,249,324,606,327,708,725,568,71,156,711,156,141,69,35,964,443,292,999,393,65,387,989,774,84,772,769,884,610,894,142,421,80,936,265,279,62,602,577,551,294,557,931,947,35,418,716,182,998,841,572,623,211,395,796,210,804,205,875,992,443,852,593,850,534,581,845,464,654,359,25,239,737,413,104,924,891,880,613,568,701,283,162,459,676,548,847,763,751,146,787,9,961,868,305,630,457,388,523,770,704,720,524,385,112,407,759,883,606,111,399,162,257,914,545,91,413,458,879,886,43,589,484,868,759,952,691,640,3,39,274,695,474,597,68,513,821,149,21,413,442,94,662,30,262,938,598,63,377,404,84,465,339,381,50,566,890,612,477,847,460,579,362,994,719,823,32,853,684,402,498,329,339,728,883,157,58,80,921,683,192,362,168,557,508,167,121,592,770,618,19,205,402,105,783,156,103,658,909,485,990,1,513,136,635,501,136,488,20,597,460,245,823,78,209,410,419,639,742,366,822,399,694,965,812,490,605,305,635,415,577,868,964,781,670,351,996,344,749,884,693,989,846,874,54,371,533,394,998,884,533,365,590,941,297,981,298,291,746,379,742,847,120,524,751,738,140,347,502,881,798,459,116,81,442,119,54,790,17,798,885,852,328,449,821,515,320,585,150,656,598,991,165,955,612,466,590,842,524,597,52,294,753,719,632,178,934,813,251,249,717,21,875,412,426,171,48,716,696,61,727,343,513,928,679,591,924,180,875,296,270,903,445,83,695,187,244,452,104,635,791,805,973,607,868,778,452,294,198,905,223,929,451,58,596,91,383,659,500,862,460,959,467,164,837,26,827,348,193,649,294,834,813,473,169,392,994,656,777,191,33,1,37,974,709,330,686,334,17,550,26,548,455,336,669,176,197,471,195,630,660,247,411,448,935,51,336,189,695,435,370,39,14,336,417,874,544,755,560,982,175,818,347,617,944,38,947,177,142,412,428,335,214,786,197,231,80,758,21,523,229,249,386,756,17,197,865,857,730,185,541,862,377,589,553,318,272,766,814,782,685,497,671,257,491,529,779,996,382,255,69,141,323,153,583,961,283,878,982,177,759,911,830,115,697,698,521,480,503,159,64,639,551,790,596,437,270,534,107,929,346,416,783,504,260,823,143,141,252,104,895,747,621,473,37,275,297,326,443,758,997,35,13,203,454,797,620,966,363,91,377,123,724,718,706,89,549,819,230,338,58,563,331,450,934,229,997,614,110,545,348,264,961,959,248,515,445,336,898,989,275,321,296,141,665,209,777,754,357,608,901,324,291,600,870,786,700,102,532,16,788,236,834,13,202,417,45,702,996,308,144,294,563,221,916,676,942,40,102,584,154,779,933,747,85,812,684,152,865,523,10,271,756,945,236,688,677,441,415,819,743,442,243,929,870,884,440,669,333,281,147,806,842,902,401,672,934,532,572,450,921,689,161,10,429,316,513,969,658,521,709,946,901,931,916,93,294,905,255,22,685,977,297,209,295,212,944,30,602,382,886,371,297,551,46,420,51,963,942,129,878,528,411,480,826,715,766,68,997,474,524,849,716,742,567,351,789,388,531,375,278,823,550,68,187,438,437,187,953,313,543,352,505,177,647,312,282,680,65,512,16,672,400,285,962,223,841,965,644,796,88,514,273,906,524,366,417,53,850,407,944,958,172,199,796,154,46,384,550,957,886,424,957,809,543,778,613,353,465,945,539,761,516,516,352,352,504,147,470,563,895,69,86,430,899,703,677,58,453,616,555,824,182,161,859,850,640,145,277,722,988,385,107,485,16,51,603,733,655,512,703,571,395,477,576,716,470,785,469,670,63,533,853,290,272,39,694,413,511,624,117,96,224,757,650,211,903,224,227,808,302,946,97,247,15,524,146,101,316,473,70,69,519,212,491,602,843,118,0,939,867,708,417,389,993,434,735,264,621,433,808,149,174,669,970,828,942,814,891,542,223,262,420,554,191,43,945,204,76,704,178,963,315,527,134,539,431,409,828,926,627,552,239,172,561", + "766,244,141,804,19,417,982,941,311,943,6,819,278,187,910,139,759,303,105,793,796,643,621,959,623,904,115,871,398,920,745,587,421,996,798,373,477,259,172,217,289,530,501,899,520,444,797,959,676,849,895,692,250,170,355,887,966,825,605,132,92,613,692,568,111,758,229,93,125,858,616,790,232,733,349,960,371,617,442,475,171,824,501,222,394,924,932,454,393,188,484,455,445,58,868,632,737,946,45,180,741,681,673,389,333,638,394,672,982,480,456,237,61,810,360,283,643,959,649,923,469,337,278,297,963,38,423,170,655,399,765,418,849,894,289,684,61,647,970,639,28,628,552,857,19,728,400,271,222,105,53,714,272,746,674,406,518,740,290,507,701,179,767,875,243,885,616,312,602,328,326,715,972,255,404,788,453,427,852,859,841,191,809,299,443,975,742,442,38,555,666,722,43,328,361,124,295,828,326,168,538,572,845,758,199,566,860,177,537,192,378,281,988,767,798,403,894,204,787,521,151,738,49,853,985,27,653,81,164,714,223,47,551,693,141,381,158,747,443,60,872,1,783,517,559,215,240,592,853,383,703,542,338,110,800,589,315,892,595,717,866,360,395,256,816,717,68,137,830,900,989,74,121,708,696,549,730,425,313,674,364,978,468,438,378,423,63,557,229,126,726,287,889,376,102,630,708,906,359,962,789,377,881,899,240,378,423,184,965,430,676,882,343,782,926,484,225,382,133,245,495,387,456,536,502,181,376,944,960,781,56,881,988,565,355,56,111,592,262,577,180,76,736,284,926,780,722,54,600,17,497,971,802,807,646,295,43,537,722,747,407,805,595,224,359,230,762,795,59,724,330,452,418,604,747,390,374,597,57,672,876,534,983,925,110,183,223,83,319,170,454,580,678,767,670,206,43,282,942,444,23,288,410,675,952,754,27,717,494,211,409,596,428,967,394,182,60,36,927,213,224,683,158,223,782,616,549,848,997,475,617,996,183,102,268,796,402,177,193,343,127,756,446,887,730,483,621,819,572,641,564,703,707,672,753,778,651,358,339,463,76,746,188,657,879,119,91,725,175,944,698,184,81,460,713,281,852,64,590,206,596,184,697,289,743,528,591,290,314,111,632,667,809,961,904,784,804,778,288,792,297,21,598,109,706,513,62,789,195,104,895,598,405,307,312,797,200,35,446,176,163,405,635,284,675,654,177,30,161,656,338,573,33,270,186,800,570,327,151,394,838,821,957,395,84,763,129,107,416,86,162,76,690,229,349,525,123,228,757,524,219,185,915,30,67,756,141,173,242,583,677,783,750,432,238,621,164,380,876,445,972,821,940,834,285,976,19,201,933,349,608,844,111,706,397,676,365,877,579,4,537,425,386,705,305,113,177,968,373,736,270,88,221,600,181,926,692,801,502,128,802,715,215,161,131,587,956,656,803,239,778,858,554,790,207,714,298,538,254,873,38,638,65,278,107,691,975,261,719,116,862,220,775,233,27,990,25,14,19,336,294,277,483,401,1000,487,529,595,211,217,475,262,347,691,211,571,315,504,143,687,848,283,879,384,533,606,24,880,903,936,444,868,917,387,86,753,63,558,634,482,539,243,965,476,47,403,415,523,952,366,405,882,980,377,316,268,469,751,330,24,620,116,591,625,619,866,658,787,287,603,298,751,785,890,242,349,253,211,984,420,526,895,996,563,455,342,792,869,603,680,172,195,374,25,19,218,697,930,934,488,282,15,126,285,517,836,751,496,607,245,426,507,929,285,222,536,64,162,83,716,500,203,113,922,499,883,381,281,529,734,554,968,899,945,559,491,642,538,713,271,827,488,690,430,752,372,650,869,481,275,453,755,909,124,48,119,38,477,749,914,845,55,782,724,413,883,201,553,80,835,266,54,449,833,662,692,921,465,524,350,792,505,307,868,256,320,814,339,562,623,135,202,467,579,501,86,646,966,163,84,530,933,35,150,230,262,460,715,782,171,607,538,771,14,698,176,970,616,237,413,81,269,557,875,506,347,749,917,610,974,859,383,197,735,571,938,570,980,452,566,611,857,336,142,225,432,917,759,174,616,458,74,136,997,30,858,696,888,962,288,388,588,958,615,355,614,918,780,429,599,361,834,727,943,91,760,424,457,738,429,642,645,120,47,308,953,779,58,635,90,140,904,772,939,0,610,213,895,578,285,824,400,857,868,259,601,515,915,336,428,200,521,870,899,457,343,137,799,107,364,408,396,825,673,375,676,589,349,597,361,883,329,841,35,897,443,315,3,24,990", + "839,810,299,157,960,608,780,844,27,275,276,288,862,817,619,602,880,457,631,455,248,367,760,4,614,7,738,178,618,446,949,647,90,785,286,839,383,468,388,522,698,591,829,973,2,260,628,304,104,896,408,271,158,370,101,664,546,825,927,482,525,42,770,642,860,289,529,878,382,283,656,503,76,688,497,27,825,215,795,377,966,864,293,277,806,396,797,655,291,195,744,57,892,985,560,189,938,908,581,607,516,189,621,648,876,73,200,666,594,504,664,865,31,956,327,853,371,662,98,617,777,764,650,332,521,149,183,153,396,708,990,161,816,22,330,900,803,93,271,19,764,570,768,550,167,377,396,343,921,441,809,827,650,104,198,194,605,899,984,512,63,138,935,603,555,248,396,523,917,724,62,629,870,514,560,696,469,607,21,42,571,966,671,940,896,867,949,845,284,320,127,172,897,75,860,642,166,871,69,79,292,578,513,41,16,636,508,708,295,233,126,890,173,633,101,822,171,29,103,771,332,899,432,559,815,958,289,353,339,476,757,167,613,253,487,13,596,931,783,640,451,10,508,621,64,62,396,11,955,322,908,667,463,297,352,609,755,424,445,866,563,353,800,305,52,74,587,224,939,340,545,822,690,793,276,819,564,842,815,652,207,687,34,128,914,946,835,635,354,519,92,331,403,733,260,930,614,287,955,603,99,808,117,316,543,395,566,182,966,284,172,956,935,855,14,49,164,136,37,901,428,683,691,392,568,39,977,213,207,414,170,405,789,583,599,909,187,940,905,812,955,362,736,678,207,201,28,768,662,107,296,185,351,849,995,891,233,504,777,879,714,163,63,102,916,226,148,366,33,68,905,371,927,249,958,535,446,907,658,95,630,255,576,680,517,73,498,255,420,813,309,811,39,725,357,717,416,414,240,314,766,402,181,811,705,575,864,966,858,791,752,303,816,601,833,997,912,197,413,364,354,150,634,567,588,696,230,829,414,819,443,675,66,34,636,289,57,873,119,257,399,374,729,528,390,710,294,422,640,469,862,527,297,285,113,115,652,189,396,727,566,337,987,738,474,556,184,622,622,983,79,348,275,146,52,581,189,122,598,935,530,277,594,787,427,464,526,998,372,143,581,37,384,493,57,601,921,481,231,805,989,674,662,960,925,883,714,444,509,582,201,171,885,72,41,474,790,525,500,646,354,576,722,212,384,400,604,858,431,386,852,439,131,797,964,206,442,592,533,7,768,857,872,378,218,343,267,861,835,13,14,604,798,520,240,316,263,693,406,846,690,135,57,537,180,171,793,319,132,981,676,502,298,351,784,37,585,115,128,51,706,229,170,878,30,443,897,117,287,360,27,843,174,701,978,191,860,576,169,25,425,624,360,218,573,69,403,261,218,12,171,449,270,700,23,757,150,413,107,166,89,307,724,197,219,137,264,751,559,354,748,832,495,649,453,859,801,927,429,961,358,425,54,322,324,194,421,634,176,831,650,510,838,569,438,855,821,838,337,453,15,211,178,897,684,372,175,89,747,803,779,807,191,187,858,6,997,528,575,617,250,455,833,539,676,311,785,763,376,834,224,424,467,421,235,97,800,197,874,152,750,481,685,352,591,907,774,325,448,575,608,305,181,860,770,424,713,703,345,337,581,159,809,859,268,583,139,43,235,875,556,773,379,916,421,633,964,702,323,463,676,809,891,564,669,563,74,584,43,302,450,641,272,532,554,833,934,773,230,21,940,857,341,604,985,795,310,181,603,801,290,728,253,831,809,697,511,724,803,845,764,110,271,525,752,62,772,556,766,455,56,510,988,692,778,834,153,54,340,61,863,976,300,754,362,583,18,988,154,262,50,771,851,451,468,517,772,877,214,770,664,322,942,26,404,570,886,352,694,757,29,890,693,947,446,346,635,683,748,205,5,790,352,423,990,834,491,249,317,778,833,574,499,607,624,735,174,960,366,242,448,928,501,303,435,334,37,334,682,943,618,494,923,374,152,353,646,522,371,131,595,170,500,395,436,940,989,241,522,713,458,682,485,945,969,975,889,773,815,372,238,981,205,661,182,220,666,172,797,6,897,251,884,784,793,744,546,584,80,62,333,93,566,942,55,706,974,9,460,854,433,243,471,128,90,774,551,35,900,606,480,258,957,562,455,981,258,436,847,687,20,172,562,867,610,0,450,222,635,808,640,556,324,300,55,366,914,674,694,926,341,775,278,759,647,745,609,876,474,419,822,889,320,388,179,705,410,420,55,894,613,992,361,635,747,150,711,22,403,773", + "814,48,916,259,930,215,937,857,906,307,275,43,529,778,946,131,522,379,270,631,49,945,708,948,553,620,847,758,914,614,959,493,945,880,899,57,345,105,305,991,248,613,622,82,352,786,225,184,318,228,706,4,962,696,382,594,395,893,469,779,662,175,153,59,450,478,317,158,313,149,546,846,394,60,699,151,816,587,742,674,821,626,802,256,402,706,300,784,449,114,574,98,843,879,54,814,430,767,840,57,697,494,473,825,468,769,541,552,982,194,911,624,265,381,343,187,906,899,111,694,616,187,918,550,16,124,613,523,604,332,293,466,345,672,61,464,234,141,392,77,156,917,735,40,979,290,277,256,325,602,191,848,646,327,524,516,446,858,290,180,482,917,303,320,457,153,662,397,920,104,742,235,120,969,939,546,181,119,375,146,297,497,855,790,840,68,943,417,485,922,190,449,273,284,852,577,80,27,931,505,549,227,243,506,202,240,861,176,69,457,839,462,660,263,770,190,864,760,995,151,344,198,46,419,708,160,794,854,711,203,34,859,997,812,437,382,845,436,165,569,367,113,126,366,449,184,281,988,873,827,558,279,377,212,826,188,124,809,446,994,399,888,894,800,32,598,377,644,654,170,40,799,410,574,980,214,704,560,897,37,83,372,35,368,297,695,640,535,361,10,776,418,298,389,304,856,382,369,511,368,508,932,302,498,586,266,4,298,79,76,843,14,14,869,110,142,213,278,337,339,870,851,965,723,139,999,706,379,203,492,318,445,214,863,530,139,37,158,608,665,147,977,231,15,482,414,762,440,164,924,874,485,125,798,70,428,899,797,301,263,187,89,850,303,752,766,11,460,126,265,576,201,369,71,635,946,516,877,562,361,609,417,901,235,792,602,9,477,335,638,704,586,294,720,374,617,168,865,271,135,714,748,644,386,61,513,790,328,688,534,563,265,618,480,148,782,445,541,318,97,712,330,36,134,762,924,136,284,668,5,480,273,621,52,684,274,313,718,352,84,934,141,417,313,14,912,162,890,63,649,123,555,855,632,496,612,958,515,838,448,839,924,1000,819,954,537,175,494,318,418,23,712,738,817,79,574,972,605,502,95,399,334,505,622,229,377,963,526,146,65,866,579,682,110,486,749,457,856,254,324,864,836,620,117,916,73,508,720,60,939,224,876,358,329,922,276,767,458,908,590,653,521,585,897,180,920,774,936,806,519,65,994,906,559,208,694,803,62,547,822,946,614,722,205,56,601,175,998,735,108,886,606,777,743,871,427,552,460,709,466,748,913,591,500,843,260,762,278,247,94,491,383,889,840,299,426,770,977,51,656,978,432,550,494,37,945,821,776,897,353,338,258,891,832,397,109,526,717,397,630,18,937,406,321,960,152,211,675,916,155,297,436,361,20,266,820,416,425,263,704,710,201,903,242,30,202,238,431,631,599,978,770,626,601,890,897,859,317,347,808,57,653,173,528,106,257,123,279,937,514,35,657,500,443,627,182,67,869,12,688,73,496,882,713,70,755,906,618,602,94,475,369,283,609,230,634,902,637,334,474,679,782,317,719,101,695,778,469,474,492,777,48,574,453,471,512,514,572,34,343,682,936,278,29,125,941,522,330,563,115,196,152,408,696,748,574,222,18,552,666,272,985,344,16,582,411,299,420,7,76,326,702,746,269,967,931,910,281,346,74,140,781,301,826,517,446,85,18,693,536,517,93,228,602,25,230,337,700,386,292,676,361,906,460,29,178,737,49,591,745,593,168,757,177,250,877,989,994,330,500,118,277,257,723,554,248,421,111,639,528,517,892,389,847,352,435,48,233,97,871,451,125,114,26,278,983,613,45,287,851,701,967,854,838,219,983,910,312,986,127,826,949,250,75,728,11,653,272,785,918,934,19,513,85,766,485,925,723,642,636,150,856,822,847,921,630,66,195,830,561,68,384,155,833,909,353,396,808,466,395,246,823,165,660,39,411,720,913,386,702,455,930,980,514,754,244,212,394,478,727,786,797,415,529,506,354,325,451,539,793,185,885,25,197,513,396,984,494,652,332,927,469,252,943,700,635,388,384,674,479,414,234,166,565,670,609,116,253,864,125,965,488,748,165,557,141,833,279,45,523,801,67,635,397,613,548,542,733,635,710,297,502,391,701,624,861,562,297,259,456,599,92,167,708,213,450,0,281,391,372,494,596,251,335,704,779,844,752,864,341,955,570,715,959,733,998,11,443,435,631,16,376,929,566,813,571,748,510,851,13,90,511,661,40,311,878,987,263,579,555", + "308,661,97,655,522,671,125,9,601,559,818,808,983,28,777,241,562,397,60,569,216,853,152,621,308,850,748,49,814,928,598,346,116,99,553,954,127,447,161,335,754,369,722,948,394,5,942,451,960,963,731,721,433,88,482,327,32,866,70,879,841,976,576,522,828,2,22,11,45,561,978,964,661,999,24,619,386,825,695,940,807,255,443,680,387,225,23,760,169,451,484,869,395,109,143,395,170,830,349,45,88,13,911,314,665,677,532,271,743,3,926,215,235,780,776,571,990,264,647,230,692,32,996,785,378,238,567,544,148,958,548,685,592,625,449,373,337,396,248,145,296,692,442,699,748,323,449,217,471,601,765,989,783,882,727,818,86,931,245,448,105,256,338,61,957,577,55,464,367,815,139,909,443,432,183,741,260,210,552,698,297,236,788,761,791,586,701,646,62,348,388,972,679,827,613,666,585,321,472,913,389,553,249,78,564,402,137,677,792,738,913,129,160,164,183,972,766,804,452,283,769,229,101,35,207,618,903,330,311,248,357,459,519,216,579,490,880,562,733,855,604,350,459,759,420,620,758,537,693,92,844,135,389,130,163,656,544,615,658,900,768,464,171,413,846,593,406,528,989,636,478,28,834,546,440,436,806,520,424,856,156,78,730,113,315,499,164,993,793,195,562,864,817,493,574,265,243,948,551,391,109,967,69,759,392,829,65,886,352,202,558,988,479,977,782,321,955,141,539,529,176,488,355,551,888,441,896,639,906,987,454,615,136,305,934,763,140,826,50,971,704,823,702,195,895,938,420,196,256,91,851,621,900,906,534,661,21,247,248,740,722,105,478,687,364,816,245,362,809,944,375,2,684,877,944,537,89,641,340,95,258,36,293,504,517,308,420,408,717,958,985,104,51,680,634,258,740,498,333,237,96,455,384,331,564,133,896,383,239,560,351,859,40,955,292,473,32,503,166,152,599,552,121,65,244,385,430,666,964,670,666,426,805,85,15,245,97,12,814,515,691,723,934,711,848,750,510,445,811,281,450,730,377,524,718,997,386,492,390,248,136,4,712,749,597,1,902,159,299,534,750,412,707,207,344,649,471,207,526,10,242,927,797,858,251,669,388,175,575,604,850,681,586,50,600,720,276,743,356,721,349,291,128,858,349,102,896,866,96,272,990,634,691,656,677,986,688,346,778,857,870,728,247,413,711,730,405,445,204,593,989,964,55,521,547,372,384,469,856,521,63,797,250,383,83,903,367,463,761,380,80,545,59,786,961,51,394,199,826,831,441,919,498,412,64,993,507,382,350,287,490,831,222,792,342,611,752,967,825,975,624,467,673,519,217,935,662,99,556,476,102,453,278,680,159,740,150,339,365,104,128,84,462,791,413,407,6,825,718,382,456,973,418,503,627,321,697,654,571,807,414,14,123,647,208,540,659,107,423,336,907,433,777,394,410,285,122,904,327,451,429,243,757,393,130,11,281,732,270,881,645,758,480,371,826,747,634,912,238,21,713,585,47,549,88,373,572,909,612,522,174,451,689,320,414,915,435,403,580,819,785,191,920,877,418,501,229,443,547,734,964,333,454,329,769,956,304,607,485,52,871,561,886,702,717,251,906,402,22,37,31,461,437,121,667,739,211,673,982,648,610,932,298,177,557,831,888,860,904,360,907,903,333,936,246,401,921,51,514,594,163,748,960,819,421,964,170,810,127,101,152,257,222,547,843,784,801,184,163,335,736,59,454,915,923,607,769,639,135,858,602,197,770,948,461,245,517,266,301,365,907,888,66,482,344,347,192,857,85,509,938,219,190,224,945,336,415,775,266,208,905,516,322,585,704,766,451,556,370,960,817,529,783,478,866,236,904,627,573,260,28,370,460,152,315,2,282,859,352,144,894,419,348,258,905,779,278,605,774,174,700,382,107,299,29,441,262,84,367,730,218,10,947,995,890,11,667,957,794,885,92,732,616,797,479,642,580,257,419,801,518,971,592,518,374,539,177,673,433,214,986,486,944,47,278,356,898,874,128,585,960,611,869,67,705,72,497,68,433,33,413,585,8,538,849,929,777,473,554,558,79,244,558,382,947,620,533,735,935,36,288,221,395,850,441,266,92,786,461,891,367,656,958,193,113,714,843,540,971,953,1,79,387,285,549,144,926,197,485,997,787,803,574,417,895,222,281,0,218,629,178,786,890,18,355,662,421,288,78,33,907,644,233,675,789,184,94,999,301,113,274,266,528,951,835,248,17,639,359,743,640,231,176,405,730,10,952,464,771,890", + "402,585,951,193,360,160,775,792,928,378,268,69,315,694,900,390,578,887,861,284,161,582,392,300,59,639,29,901,749,532,345,214,585,923,8,200,614,432,352,987,756,584,195,833,299,542,214,339,332,625,446,481,470,870,639,608,648,921,489,891,461,976,603,235,687,408,193,423,793,659,394,175,52,655,43,191,610,144,903,54,762,762,548,899,782,513,985,783,492,938,734,349,602,629,648,236,162,676,93,978,970,850,404,844,846,692,714,280,664,964,172,843,733,425,285,402,913,851,984,500,380,370,894,251,197,173,893,233,766,785,758,907,149,167,183,604,865,367,784,234,699,968,351,183,258,948,404,169,454,616,418,299,878,40,278,589,355,658,342,910,475,244,411,340,779,574,790,286,248,13,85,789,577,439,630,210,700,837,78,637,643,131,638,382,706,146,286,853,237,770,668,500,267,522,956,73,882,607,827,369,656,645,611,603,520,769,737,426,958,372,923,594,580,142,403,815,504,608,574,293,586,460,956,958,65,93,80,784,317,928,546,260,363,135,475,949,153,531,897,700,730,196,879,237,500,701,620,345,906,919,432,42,247,127,752,754,835,526,497,365,960,506,912,280,675,181,414,762,974,226,63,476,856,302,987,455,316,871,252,197,340,163,504,129,3,347,239,443,810,883,459,185,356,836,271,51,210,164,634,503,505,677,648,844,140,940,690,723,775,904,322,255,793,99,758,495,496,387,496,740,541,278,843,952,668,853,869,221,652,195,482,498,259,967,76,739,174,265,224,278,886,376,197,390,957,369,818,200,922,660,327,281,680,99,761,633,602,489,76,585,484,703,179,710,995,272,45,904,290,283,427,60,937,538,187,475,435,644,181,504,395,360,509,699,936,497,400,75,385,21,40,923,274,655,380,323,746,220,581,713,124,305,871,762,699,763,681,734,793,565,189,428,49,146,538,244,337,588,261,502,990,554,16,116,288,183,205,206,560,112,733,355,905,640,141,761,187,596,416,597,809,328,332,453,688,290,250,367,100,467,863,631,617,545,504,699,13,782,267,332,46,301,574,780,144,106,724,348,914,136,228,1000,85,498,37,91,695,182,338,809,445,565,761,864,205,222,306,855,632,597,542,61,352,410,673,46,663,606,675,969,741,241,238,935,348,981,529,571,1,685,462,424,803,286,266,211,618,897,406,18,391,854,890,767,151,613,237,157,919,677,969,91,635,535,3,708,653,594,436,723,463,299,873,697,131,257,144,439,713,913,467,20,69,119,333,436,896,575,552,489,506,337,985,207,154,501,508,68,668,988,532,340,302,453,142,457,600,812,652,553,284,385,385,836,465,828,669,456,512,710,517,470,278,819,631,164,247,821,314,410,508,879,986,612,925,655,821,723,587,681,459,752,277,506,636,900,180,25,567,692,368,734,781,550,638,765,824,716,820,520,989,657,70,397,575,72,488,589,67,529,969,528,295,80,637,883,845,138,937,906,139,785,700,472,783,666,887,537,800,835,399,623,383,338,722,17,614,532,982,511,159,725,541,441,117,789,130,78,529,818,655,534,819,948,979,396,988,310,331,719,533,192,912,136,818,578,210,158,853,429,808,211,815,289,493,51,586,189,62,838,781,567,901,623,216,213,73,47,70,872,555,632,577,345,887,501,615,616,919,358,383,25,234,177,346,230,322,726,162,317,708,29,526,877,946,794,39,218,361,983,363,772,489,166,563,238,901,885,276,574,535,551,178,172,78,410,603,749,803,292,687,128,270,650,355,34,534,427,11,604,514,172,927,503,427,92,392,53,482,606,652,828,520,631,610,662,376,925,11,645,544,795,732,677,177,788,723,63,914,130,92,221,185,127,321,656,674,275,221,484,277,83,323,601,645,725,816,764,741,593,157,343,131,909,490,794,996,965,831,557,303,344,661,312,349,915,927,620,794,922,445,822,862,656,862,420,63,990,714,858,66,43,830,951,316,929,687,244,379,707,400,454,778,474,544,818,716,458,878,4,899,596,982,949,492,797,77,925,298,167,198,803,627,177,356,294,865,360,501,285,906,547,488,380,732,695,97,1000,317,209,652,72,536,818,349,893,13,799,85,66,982,171,368,853,813,134,22,834,51,504,484,796,11,60,8,835,962,425,484,364,659,341,375,110,142,618,832,460,514,360,575,26,15,389,578,635,391,218,0,969,906,849,980,520,575,430,306,634,92,496,410,218,427,691,777,372,334,208,771,71,117,880,388,278,849,501,614,827,879,965,867,356,542,407,959,455,182,971,673,581", + "528,135,306,882,459,235,48,736,266,854,916,693,457,819,261,286,874,129,625,638,101,572,201,559,343,244,941,233,114,80,702,793,798,489,695,157,921,674,190,80,867,115,955,288,542,582,269,638,500,320,579,568,940,66,66,722,75,234,292,184,744,374,349,140,157,299,40,86,69,648,913,444,970,35,560,974,960,511,443,351,146,593,909,759,200,655,581,20,732,555,169,544,274,320,616,580,813,774,653,593,395,5,141,601,345,165,45,892,487,255,890,292,881,625,362,73,367,485,802,379,122,565,596,357,327,192,103,761,484,738,667,691,468,296,951,70,809,691,499,794,442,448,783,898,436,983,118,756,434,197,62,935,380,281,221,988,213,789,34,451,382,286,528,165,271,143,71,290,335,662,34,406,991,551,850,456,720,196,143,927,43,605,307,524,663,770,189,679,593,9,132,464,332,543,856,575,370,417,214,159,164,137,238,552,912,784,220,299,628,513,814,670,640,253,730,601,105,4,921,218,158,353,659,259,482,786,879,746,974,331,179,519,760,514,643,254,875,429,423,855,251,619,193,937,56,386,324,264,405,61,699,820,335,945,99,77,190,35,608,493,607,1000,164,914,231,343,381,600,272,52,162,438,257,132,453,563,473,720,282,996,851,915,452,370,442,71,133,156,398,347,591,30,359,915,200,313,237,722,441,131,923,875,546,217,982,592,151,683,142,515,902,101,506,351,316,801,626,911,595,309,9,751,599,662,702,366,865,270,324,104,596,132,548,241,749,309,488,133,303,557,672,491,826,961,666,64,890,71,134,912,502,715,514,73,783,538,299,504,155,115,903,216,472,767,92,784,960,119,720,487,678,42,316,130,979,887,911,432,29,156,931,572,371,812,609,195,586,654,398,755,318,918,527,29,274,948,303,654,327,298,947,311,48,471,514,899,111,952,413,456,688,913,771,274,467,678,642,990,164,252,502,654,785,895,295,869,686,492,366,998,393,87,139,494,834,246,365,374,628,713,248,358,846,986,676,667,369,572,623,833,842,892,527,208,34,280,40,702,508,589,457,626,603,223,457,688,873,515,8,569,325,567,615,216,655,357,666,469,739,782,390,230,981,309,322,805,144,444,496,129,236,792,108,278,46,589,352,591,284,315,61,477,198,474,732,973,674,893,489,170,741,438,99,751,120,238,673,97,535,237,359,954,728,848,520,84,86,420,755,107,222,701,45,987,360,124,61,895,701,242,457,861,965,960,456,399,71,287,215,772,168,543,351,333,745,468,80,40,881,628,776,345,112,834,533,93,326,576,909,217,285,726,652,779,471,823,411,922,329,892,271,569,364,974,424,416,302,305,672,678,543,442,642,794,680,539,694,661,291,432,391,879,530,238,459,996,71,272,478,798,769,53,791,319,792,524,561,557,213,698,651,479,581,922,844,826,441,729,696,307,717,765,674,134,236,933,952,874,966,298,227,176,37,258,302,925,734,117,664,331,95,93,76,337,918,66,480,296,448,556,740,369,748,181,455,303,953,336,90,869,464,245,853,178,617,454,748,460,270,95,899,531,432,356,716,108,977,656,982,428,891,30,681,26,244,47,388,47,328,519,716,133,784,171,252,310,948,538,870,751,435,41,461,493,449,727,97,155,202,325,489,25,490,782,999,476,603,330,847,103,614,635,591,301,503,995,922,449,652,734,420,192,664,296,170,251,706,638,649,115,104,869,702,899,781,784,714,467,222,273,131,949,764,18,945,771,641,376,812,834,779,525,227,133,549,981,723,887,148,725,346,499,344,614,360,753,901,620,935,471,604,826,611,948,452,348,500,631,448,491,373,816,704,739,513,458,975,770,565,622,248,686,968,245,410,934,962,144,426,396,920,217,606,364,30,550,250,467,249,962,605,758,571,838,721,317,553,646,604,14,745,214,36,2,595,808,995,57,903,306,557,242,699,575,322,562,318,632,628,686,919,281,777,956,641,519,568,251,479,469,911,554,23,902,364,963,377,821,331,44,926,648,773,184,501,303,208,117,189,40,591,588,301,322,642,633,418,649,799,813,564,951,929,284,223,955,126,897,817,668,848,367,330,449,409,770,701,122,418,338,929,103,583,846,187,864,567,697,151,219,992,221,326,34,935,14,355,333,81,852,398,117,829,248,23,643,529,345,736,378,471,607,841,993,285,808,372,629,969,0,695,986,365,205,858,142,378,180,61,547,395,89,588,612,493,137,720,986,5,216,982,718,254,884,214,217,751,343,129,110,572,473,562,826,674,920,917,744,743,632", + "912,99,220,169,142,332,912,13,228,294,845,208,644,677,620,112,610,751,247,124,127,745,384,845,539,136,712,96,539,789,747,675,514,468,854,377,69,171,707,9,526,651,9,811,487,5,326,986,476,112,517,140,642,735,55,495,565,371,839,798,619,414,857,201,920,170,864,983,725,910,34,613,233,983,710,302,887,666,227,734,876,58,467,918,855,289,341,180,846,987,668,352,360,174,917,53,970,817,642,482,19,548,238,34,985,276,992,242,620,528,403,82,484,711,980,603,966,754,780,62,537,475,632,739,937,128,761,35,180,255,390,869,534,186,975,136,47,33,533,668,870,166,795,180,638,801,334,577,170,853,444,748,871,908,265,668,444,342,47,931,676,850,697,614,917,311,428,693,448,910,949,947,704,312,653,750,511,661,529,355,763,964,795,891,48,446,214,961,153,929,391,95,429,953,46,679,736,658,298,883,788,847,410,947,316,567,324,732,569,743,643,748,543,836,650,995,617,428,191,329,28,97,630,474,673,124,16,382,112,434,127,372,990,292,656,224,110,242,660,597,954,550,686,703,657,585,67,483,241,875,852,749,187,392,678,625,801,379,821,390,175,974,555,664,850,711,941,59,681,743,405,220,142,814,453,172,772,916,800,553,517,680,686,654,387,534,833,864,783,899,897,69,893,833,893,372,207,329,39,409,970,657,202,652,234,148,775,223,744,617,358,390,902,275,566,763,534,850,714,600,744,680,916,933,723,571,140,928,65,43,239,792,207,701,496,300,6,781,235,349,336,965,682,24,465,66,826,500,508,365,563,639,928,267,889,884,62,987,125,699,185,169,245,897,241,673,452,374,2,571,95,19,639,529,374,530,867,923,620,532,29,816,524,918,557,798,576,575,254,387,596,7,224,883,957,517,95,329,255,175,243,94,565,667,38,78,508,80,579,291,410,987,525,92,65,550,597,294,657,820,815,493,606,685,988,22,309,845,363,617,742,149,582,320,107,364,503,601,527,682,21,493,324,845,940,49,828,744,214,343,695,890,286,801,307,537,480,843,306,645,453,836,201,335,139,263,488,560,953,728,255,361,183,524,854,394,284,257,962,328,733,727,156,680,124,90,822,889,401,97,955,502,929,700,519,359,296,474,19,928,792,76,599,196,704,26,482,814,421,544,248,477,311,70,421,510,568,538,692,422,127,868,611,986,610,786,909,434,237,959,903,151,154,646,81,51,558,9,190,180,808,387,437,31,748,682,913,929,285,887,985,562,833,420,369,391,327,884,652,770,671,303,246,349,891,717,903,509,586,902,316,832,431,640,919,709,677,391,673,947,319,101,159,323,210,580,693,435,397,717,949,943,418,855,907,340,195,919,383,861,812,628,257,708,45,415,316,885,390,862,888,579,157,836,544,717,761,918,386,323,117,591,761,857,244,761,861,734,504,764,563,310,689,533,844,494,792,377,290,938,971,389,811,966,722,262,90,301,271,561,953,381,337,231,406,13,330,39,600,626,946,497,921,889,384,348,268,185,239,565,887,174,38,502,195,217,746,462,427,316,890,148,801,45,618,292,319,813,153,616,849,461,316,576,617,404,41,909,988,345,950,96,88,194,214,897,514,492,265,879,951,763,619,256,145,13,346,907,863,804,963,485,679,657,570,434,725,518,588,29,582,358,638,684,278,793,568,584,816,821,235,311,113,968,411,88,335,71,64,636,938,642,268,473,447,70,606,964,732,780,338,784,748,679,464,646,176,425,825,212,823,627,679,567,797,284,353,375,317,969,340,334,296,722,717,696,162,89,212,728,774,62,335,762,238,728,839,242,928,39,812,633,714,927,847,517,647,686,719,813,430,366,207,675,159,313,158,377,350,217,196,821,684,872,663,385,178,687,903,59,727,106,11,214,493,810,807,105,149,387,344,775,945,528,724,673,160,423,152,913,10,800,86,923,734,595,776,409,290,236,838,944,111,530,442,858,527,814,802,993,109,618,337,85,784,936,851,854,525,830,749,462,554,623,799,58,671,80,593,182,864,521,909,193,65,569,976,769,552,413,508,504,358,343,132,47,403,140,489,850,134,78,871,879,406,817,979,864,697,556,700,515,336,819,575,54,121,763,138,537,39,970,48,629,87,754,356,571,178,221,474,628,766,871,516,213,72,494,491,708,289,102,696,434,824,640,494,178,906,695,0,429,869,958,546,509,461,86,225,610,690,605,107,352,158,895,158,894,275,35,644,605,260,638,156,377,798,502,118,393,429,67,207,263,740,93,826,630,195,883", + "260,321,434,220,19,30,516,397,148,998,821,488,403,115,973,676,232,383,222,296,508,866,613,41,294,448,723,213,955,604,32,447,854,802,554,554,173,267,422,979,550,887,154,491,282,308,816,798,636,376,700,676,521,568,425,225,817,109,759,256,516,905,419,279,923,123,854,861,31,681,686,32,722,63,895,179,876,422,714,345,102,24,884,187,177,887,120,345,621,347,323,435,923,444,277,357,903,445,276,774,582,292,979,325,219,614,440,474,265,287,547,637,282,94,532,923,347,524,975,661,709,823,121,363,759,466,867,227,928,485,481,389,408,370,572,173,725,360,639,37,288,234,901,149,805,826,393,957,417,211,709,894,477,897,224,615,686,381,21,377,828,178,426,472,467,33,212,56,869,760,377,272,517,983,120,637,960,645,213,229,342,837,764,615,214,880,657,139,105,77,141,638,677,207,421,231,522,934,950,620,249,173,447,377,108,98,465,960,906,178,251,217,414,368,71,926,261,240,785,319,224,241,462,889,830,290,737,101,676,867,790,411,899,448,432,75,200,25,725,995,657,40,863,324,842,559,95,448,361,714,238,605,637,247,155,268,192,688,358,303,127,454,528,313,566,314,157,682,350,718,282,419,646,214,140,253,52,364,294,174,474,401,60,238,124,394,733,521,709,950,678,276,855,738,932,468,168,574,202,99,234,802,412,42,711,896,474,223,441,782,62,550,516,990,84,699,898,374,169,69,669,566,671,520,647,118,360,730,851,12,690,439,857,105,640,417,128,645,397,171,747,617,878,452,640,146,485,235,686,630,329,629,634,245,433,913,407,208,751,875,319,865,568,118,977,738,513,968,936,980,977,993,437,844,348,879,618,615,623,310,443,88,672,508,651,398,743,624,224,479,435,942,373,332,107,138,28,794,946,27,336,828,904,300,216,810,484,30,492,106,802,52,500,405,190,171,920,817,687,954,633,42,902,311,631,599,162,734,862,153,736,666,472,56,853,618,307,570,758,737,52,225,580,915,284,648,866,25,424,15,90,19,118,700,676,573,617,307,216,849,36,915,320,106,771,616,159,642,130,29,726,907,582,567,70,397,585,34,201,759,373,871,817,416,30,606,789,761,822,193,603,529,303,618,508,468,205,493,922,910,801,814,54,967,378,829,329,74,764,193,688,816,354,79,443,219,455,621,740,90,849,667,271,168,554,816,209,790,57,657,556,977,936,116,448,695,808,988,697,44,200,338,320,689,816,633,95,149,34,24,296,196,851,686,792,451,990,842,663,226,344,169,280,630,658,211,13,273,734,726,99,967,202,101,957,116,183,425,408,32,380,199,613,165,839,238,468,675,993,631,276,902,245,830,102,357,378,120,471,659,545,596,292,634,903,736,69,215,166,779,940,604,733,400,431,849,275,611,974,670,713,377,486,382,626,399,537,181,958,485,986,376,885,375,101,646,541,862,705,883,90,367,24,271,11,179,713,153,753,292,286,175,36,26,880,324,873,632,532,906,644,980,99,175,950,74,211,107,51,526,742,627,11,937,701,110,200,313,610,327,942,632,721,441,951,945,60,304,615,886,55,918,227,52,247,878,504,532,10,673,320,523,904,186,558,759,971,916,788,824,667,259,310,710,706,116,501,649,283,415,269,719,444,852,938,124,897,787,254,144,114,776,306,615,853,901,443,106,355,958,737,187,714,872,179,935,288,639,213,266,472,503,275,958,34,670,93,9,15,192,795,999,83,30,566,928,940,787,838,762,322,301,242,88,196,639,166,775,185,526,488,815,936,517,331,26,715,439,779,378,544,563,14,81,563,701,938,185,967,50,922,558,772,151,661,490,929,618,942,545,653,133,726,693,97,720,618,249,946,825,367,20,411,83,595,883,645,349,67,465,455,817,450,261,120,432,850,608,250,512,360,657,543,722,982,135,692,988,907,296,4,188,8,113,639,947,483,998,160,716,365,500,837,552,528,256,360,950,597,293,892,389,512,321,987,278,150,70,285,507,658,937,673,655,128,770,314,180,160,162,849,145,757,293,181,652,405,276,795,410,370,557,884,350,614,336,440,992,7,330,498,658,953,595,137,834,350,15,85,994,473,195,75,359,541,807,37,492,979,229,51,791,137,673,780,483,417,676,881,755,876,182,979,110,292,62,633,22,122,337,388,635,520,735,400,556,596,786,849,986,429,0,403,985,671,320,823,676,167,631,754,408,491,57,126,581,171,115,226,256,681,60,550,258,65,368,628,459,349,158,69,619,871,964,997,52,308,776,927,992", + "754,450,419,309,826,472,36,207,260,990,164,705,974,499,202,560,255,288,239,381,102,104,883,744,412,186,31,878,564,952,955,782,774,711,829,730,419,686,369,415,308,600,776,288,921,25,272,592,293,124,477,817,418,821,472,493,24,889,956,256,824,652,799,797,280,838,391,566,156,600,986,186,535,186,5,221,654,203,682,255,85,167,818,669,373,993,680,15,717,908,484,78,619,284,222,958,772,976,732,200,421,302,379,501,613,801,191,754,294,290,62,47,78,257,136,380,655,794,591,343,638,557,723,150,501,796,654,464,81,687,679,514,279,133,855,940,276,366,198,742,76,344,441,618,502,624,881,421,725,71,706,994,133,154,406,951,577,438,544,487,683,652,911,630,135,517,13,968,345,519,216,788,20,487,652,302,539,806,92,721,982,430,556,832,245,903,780,210,906,206,680,671,149,967,356,723,633,981,297,743,590,38,706,840,296,445,587,815,815,806,169,764,71,491,928,254,972,440,454,988,278,739,194,728,126,501,553,931,330,622,540,734,872,664,5,785,211,514,261,924,618,663,819,169,374,672,844,277,681,16,988,741,664,972,653,779,766,854,782,144,545,901,756,3,84,948,927,452,455,510,662,318,656,874,991,732,838,765,619,848,367,142,251,275,648,832,423,26,732,45,667,119,312,578,818,278,114,486,670,378,9,248,683,518,425,257,161,456,514,819,821,322,873,480,103,693,524,969,508,785,716,730,653,18,620,659,145,921,926,12,379,163,749,419,468,296,470,547,694,433,426,411,425,842,975,219,654,812,505,936,169,542,867,740,982,996,105,830,838,664,373,120,275,798,282,671,840,188,450,686,888,120,129,25,4,77,320,257,376,681,846,5,528,895,506,202,514,83,871,118,780,972,877,657,768,314,454,791,575,880,459,699,394,245,415,868,793,4,393,826,653,846,451,705,213,251,588,31,988,231,394,697,788,218,718,346,974,512,805,617,33,60,637,29,522,796,768,850,191,229,31,730,585,765,622,228,871,262,617,986,214,434,992,162,685,2,400,363,264,528,683,173,484,191,382,873,352,349,364,550,97,961,881,302,980,632,137,585,11,265,617,756,826,25,664,68,263,149,287,429,504,788,873,80,392,606,201,477,945,713,410,695,398,996,970,429,595,954,788,812,592,760,483,110,41,591,605,598,619,122,329,68,975,818,501,701,238,582,421,32,156,646,202,395,267,142,761,650,361,224,852,277,885,467,889,390,221,301,914,5,944,325,123,186,60,91,313,239,448,492,696,690,16,267,166,578,601,389,131,574,705,790,116,229,921,455,10,828,372,898,522,802,909,610,565,18,262,91,859,164,453,227,80,590,546,738,717,678,942,62,96,360,249,173,815,388,663,598,88,691,264,272,988,633,102,462,655,41,134,219,971,138,458,539,850,856,587,673,174,774,400,592,54,210,291,505,885,753,726,333,687,702,134,249,582,12,297,994,692,782,821,106,364,655,322,974,672,300,248,153,735,718,149,491,835,150,905,368,101,168,391,991,675,437,810,391,843,218,683,713,673,163,873,843,197,216,586,303,505,419,217,741,174,973,551,229,610,689,146,675,693,872,762,252,458,250,893,694,572,328,757,798,675,37,117,387,135,750,942,797,910,330,925,522,68,516,11,209,212,525,117,326,491,546,210,217,560,176,50,754,275,336,307,48,623,468,433,50,544,249,125,336,637,797,222,438,497,778,154,84,234,269,963,455,597,62,713,315,137,970,405,884,496,392,64,817,471,50,261,407,259,624,227,942,734,666,751,227,741,101,48,520,863,410,339,976,193,86,498,101,721,598,215,757,173,331,913,787,747,15,278,62,83,732,715,707,528,359,268,898,621,969,301,980,621,65,678,320,474,93,89,978,702,341,995,712,353,140,740,838,793,598,43,485,344,31,78,619,256,285,579,624,222,10,452,603,33,418,116,886,78,20,465,892,262,550,333,735,532,255,3,867,794,116,645,332,2,961,310,325,816,832,982,317,931,179,320,170,219,739,821,896,688,976,552,252,54,948,34,678,956,483,969,435,567,65,340,88,534,936,353,571,44,500,73,835,482,588,951,753,994,565,789,274,377,112,328,49,441,713,537,425,54,532,170,345,549,160,729,534,52,409,67,146,418,926,361,637,912,551,606,576,98,264,857,324,251,890,980,365,869,403,0,63,948,7,466,549,593,114,825,18,756,762,371,857,172,820,721,455,450,287,947,421,10,61,436,472,230,456,269,720,170,595,793,295,1,916,324,38", + "367,513,183,887,580,905,409,848,199,145,599,406,667,498,798,539,977,651,272,607,694,532,674,411,101,747,88,306,511,584,55,431,256,836,41,795,538,745,324,565,263,677,111,198,587,327,249,849,804,592,26,711,123,285,861,229,482,583,405,184,268,332,486,169,146,233,735,501,992,793,239,931,963,442,829,790,135,39,220,680,282,809,644,979,761,25,417,465,241,836,709,489,225,176,656,253,444,746,19,605,699,359,434,837,388,613,958,465,261,447,423,708,394,599,710,345,87,238,76,875,721,630,210,694,695,581,709,788,958,6,100,632,704,706,453,791,981,188,91,872,720,118,519,262,332,230,860,292,308,12,671,239,165,446,864,165,314,372,433,210,500,247,310,749,531,258,29,192,117,354,848,856,743,14,215,908,265,367,65,307,763,401,163,825,829,283,825,388,35,153,859,674,171,342,465,221,319,504,866,261,214,683,988,996,509,286,573,33,512,799,778,346,877,317,600,376,774,160,414,867,322,736,200,997,521,980,225,434,42,216,668,367,457,951,968,761,753,204,479,725,444,287,427,823,715,274,862,215,124,857,94,430,758,533,176,942,724,576,453,308,612,927,887,132,290,83,471,232,685,401,597,270,516,532,734,476,876,495,887,112,362,236,99,132,987,252,510,825,996,372,111,227,251,48,102,793,310,74,428,18,168,979,296,531,879,634,917,938,725,880,153,592,775,675,94,239,542,856,938,693,520,606,664,187,989,489,637,185,778,105,224,483,334,821,436,265,166,903,331,336,872,715,849,921,784,336,767,258,748,651,774,673,537,229,110,527,161,121,580,913,877,576,206,265,271,589,184,223,212,240,839,680,283,168,83,481,715,504,157,431,263,706,704,433,779,772,569,228,375,445,303,81,160,774,585,398,28,500,209,569,315,16,127,680,142,862,163,247,315,552,907,204,55,781,595,431,207,258,603,695,92,502,644,211,384,979,589,423,230,382,766,591,910,790,36,850,807,875,971,126,379,302,925,565,831,924,907,333,787,226,554,239,751,762,497,671,512,246,200,155,507,627,534,188,530,461,39,531,135,50,606,236,354,298,518,265,951,198,247,729,606,374,381,421,205,299,282,271,709,400,22,618,97,413,831,940,547,370,453,108,608,249,205,281,9,818,52,512,120,502,818,58,137,374,447,344,924,898,437,72,410,309,53,944,185,823,380,324,989,184,937,293,32,489,107,198,661,99,166,288,272,84,614,538,891,35,586,83,348,952,743,302,782,32,493,564,815,42,276,494,188,585,887,212,466,389,291,274,169,765,494,584,898,94,787,670,906,438,414,233,871,35,66,325,539,663,67,775,170,354,351,342,71,599,840,539,784,635,547,232,264,453,986,867,123,436,682,103,140,754,970,17,265,720,327,537,428,100,615,839,679,223,774,839,835,957,276,378,491,797,669,820,339,208,963,668,703,340,447,638,199,667,639,349,877,322,243,187,750,190,642,937,184,733,240,737,899,999,589,679,9,77,208,918,515,321,146,247,118,603,960,124,395,546,310,162,41,516,214,571,798,291,488,839,447,521,219,31,900,331,398,916,637,783,828,973,838,202,516,690,623,460,378,513,671,897,561,48,184,978,798,379,285,124,685,102,2,11,555,642,916,264,308,789,224,660,945,141,435,720,754,525,431,359,854,321,817,380,771,107,678,691,345,410,370,591,593,115,923,30,679,156,122,859,179,267,94,863,193,498,155,371,471,103,481,559,688,527,390,199,918,884,293,204,811,288,492,683,657,634,482,898,684,750,72,740,455,323,318,515,423,669,5,222,958,328,788,864,954,952,168,555,452,773,692,892,708,159,186,628,999,334,723,483,469,519,20,885,83,759,251,515,86,17,847,459,534,233,802,648,186,424,671,293,279,685,15,218,577,815,402,931,262,814,337,574,567,25,230,820,639,943,763,968,152,749,803,850,312,737,269,955,706,973,239,463,840,692,616,12,49,149,562,22,561,46,146,160,670,774,717,79,419,584,627,303,830,322,331,283,883,454,431,652,742,878,849,159,339,237,364,326,975,694,721,408,644,862,983,218,436,466,816,175,989,259,366,9,339,369,281,49,653,176,445,41,27,783,688,939,519,510,876,288,341,559,330,588,210,406,921,943,660,739,984,883,753,658,22,955,786,88,647,621,868,300,335,18,520,205,958,985,63,0,630,701,805,185,560,214,532,584,53,676,591,248,488,531,466,282,943,718,922,270,557,156,676,960,413,83,408,647,283,697,472,5,259,336,974,67", + "8,70,307,270,833,503,138,49,11,654,798,56,413,969,280,693,249,600,712,440,98,265,231,593,976,885,214,2,994,94,544,105,151,571,764,770,947,947,824,531,858,655,819,727,94,226,174,144,660,207,286,296,654,515,204,58,813,171,424,109,959,688,132,879,931,47,282,687,878,573,379,523,665,319,759,238,434,234,124,513,242,119,647,900,254,816,752,758,814,227,356,606,27,168,462,947,351,330,388,195,384,792,240,812,683,992,111,772,245,857,687,129,520,478,873,578,471,62,109,924,50,822,399,878,635,74,925,717,476,559,435,17,690,123,92,715,256,531,320,72,605,173,80,438,45,879,652,719,639,744,706,542,643,829,471,465,112,407,473,945,268,485,784,649,659,242,437,325,253,46,924,209,163,276,266,280,906,882,762,479,504,607,423,485,918,715,328,895,201,154,687,584,805,713,898,620,993,394,726,581,939,374,250,126,425,799,380,540,535,821,163,99,811,530,255,821,979,993,319,971,72,724,620,308,898,526,644,963,629,212,329,176,423,4,11,258,705,96,409,560,646,371,157,647,859,608,643,934,356,934,656,683,217,167,766,19,49,819,643,950,713,891,705,511,657,879,87,630,482,762,266,881,654,577,925,435,231,665,573,654,807,597,581,192,749,911,295,245,103,976,834,727,600,768,19,249,449,87,363,298,731,842,333,79,322,329,664,830,446,248,484,201,806,536,545,958,418,312,346,819,223,725,780,991,62,843,6,618,615,885,629,249,611,224,193,952,17,498,689,196,575,960,269,690,301,993,904,728,654,161,835,409,484,594,896,551,2,220,905,31,702,419,664,76,316,653,521,116,634,478,150,242,510,242,869,801,140,369,598,639,848,576,488,542,27,252,816,550,581,607,464,109,81,655,968,280,150,810,944,755,992,422,696,773,737,18,901,477,34,292,399,927,911,586,414,907,774,532,997,654,159,868,657,821,272,752,875,523,439,26,838,425,685,307,773,895,620,96,174,879,225,355,896,400,984,773,284,655,446,63,438,540,267,167,72,105,834,469,880,497,468,305,291,232,163,734,38,630,490,826,939,642,837,606,295,353,250,372,434,307,469,571,242,171,286,92,902,811,150,964,135,202,224,140,32,836,682,234,533,53,584,13,771,680,729,955,396,305,722,631,544,380,454,773,223,877,168,175,367,763,106,574,717,757,348,348,50,628,446,535,816,787,899,223,308,347,617,788,969,34,350,890,321,809,110,426,925,79,206,438,502,404,575,453,490,364,539,18,572,161,888,614,44,677,736,119,633,87,235,748,624,715,988,935,607,472,82,807,865,71,723,647,88,932,301,874,870,440,602,933,971,308,364,359,591,865,106,709,47,739,431,870,907,306,565,730,339,908,367,136,746,637,400,137,275,69,488,125,503,34,958,890,588,616,181,955,506,125,165,166,741,309,835,624,738,888,840,873,51,992,325,496,436,143,861,942,270,247,565,455,28,626,625,721,522,371,71,608,186,418,547,2,122,637,656,953,316,318,606,116,116,671,530,508,620,955,459,816,456,694,951,137,188,565,535,69,811,760,911,382,748,103,985,403,499,326,336,551,30,552,309,51,869,343,971,8,472,755,801,412,93,687,858,277,516,805,139,846,153,615,51,630,317,622,928,69,2,54,463,3,761,292,424,431,670,945,900,651,199,450,673,525,913,681,426,176,157,548,591,944,742,103,267,202,479,779,191,533,154,647,535,585,261,559,941,506,731,54,267,809,17,692,828,162,698,599,670,6,272,352,928,203,178,340,987,607,238,972,445,696,825,720,199,886,812,178,761,464,778,83,526,522,261,63,70,931,485,630,220,714,94,654,873,553,463,969,898,404,982,592,198,566,446,708,500,966,492,429,477,755,30,807,950,59,975,614,259,528,227,887,751,95,740,696,92,992,361,736,981,162,638,778,921,916,361,641,740,488,736,294,220,682,542,333,97,425,906,658,337,943,557,511,205,250,337,807,198,542,509,20,407,769,775,487,445,100,517,258,606,284,918,709,718,746,609,733,112,610,268,957,487,427,698,677,45,147,985,773,308,412,809,177,488,642,170,71,47,745,793,94,789,353,131,859,514,691,751,626,400,351,605,550,23,137,958,383,462,440,52,789,67,835,962,86,699,283,493,539,532,14,839,895,712,433,259,55,704,355,575,858,546,671,948,630,0,308,293,851,225,738,280,713,618,189,376,513,432,501,25,314,629,866,60,120,515,955,738,859,411,267,63,161,711,205,681,766,467,932,420,688", + "301,896,287,963,483,385,140,962,219,829,484,663,189,38,742,885,416,814,857,765,530,554,945,314,387,560,64,537,59,449,25,351,402,762,287,981,278,541,505,201,648,705,857,141,907,693,440,719,657,550,433,362,397,967,344,234,821,361,30,562,560,353,704,643,891,508,519,829,873,3,452,291,872,693,364,61,328,694,961,136,761,852,992,858,416,303,674,293,320,954,938,768,183,540,983,513,965,108,535,326,989,613,902,973,61,723,254,114,526,37,753,130,972,526,447,551,784,380,896,678,474,864,429,973,215,537,576,273,584,597,144,101,112,765,302,257,349,103,740,191,249,468,602,878,335,162,199,538,147,294,52,805,409,633,451,308,621,343,537,521,882,145,975,961,31,479,62,717,918,441,888,43,688,820,760,768,915,144,974,473,776,985,329,923,391,519,719,982,647,420,784,295,136,300,637,976,125,263,81,155,754,930,209,56,690,76,643,186,933,697,507,935,962,584,395,946,604,506,209,759,22,481,106,439,227,583,382,509,236,905,734,501,487,138,342,911,962,983,410,275,476,712,476,716,823,82,888,866,583,155,758,140,460,330,534,715,231,287,159,557,835,518,421,401,434,547,155,813,722,173,564,564,128,589,525,594,25,363,389,868,870,56,414,2,739,713,804,330,467,921,924,477,92,444,404,298,910,168,824,444,231,452,879,93,790,375,743,955,891,458,783,642,307,113,847,297,594,620,28,247,584,73,143,442,836,142,934,237,67,72,678,373,855,367,487,881,586,169,505,39,764,739,837,117,319,715,185,398,460,293,789,633,35,739,902,557,27,145,854,409,37,179,183,681,11,642,215,437,141,444,624,272,448,127,557,39,568,964,537,15,738,672,222,724,157,900,31,63,926,243,597,314,789,249,361,352,775,879,979,674,350,838,416,245,102,309,192,520,981,14,310,12,926,332,524,473,989,859,801,686,897,589,964,796,48,962,972,997,947,101,744,167,166,358,284,357,359,364,795,15,792,878,131,300,196,500,406,456,636,301,427,760,912,488,274,47,173,546,122,2,183,92,106,363,185,653,753,683,650,799,923,668,792,378,882,977,119,161,493,997,804,984,270,604,900,68,495,830,322,930,849,675,592,541,548,327,84,576,905,555,627,819,111,501,666,858,717,759,985,738,349,118,105,351,995,597,995,104,918,595,453,574,936,971,91,42,321,610,47,519,543,24,898,11,945,293,750,948,693,232,536,284,309,786,246,744,760,414,448,967,66,114,660,965,601,20,424,459,875,29,484,398,364,731,295,362,821,93,590,537,832,967,26,923,88,913,74,935,426,948,561,841,646,984,318,116,929,519,158,573,382,381,32,995,856,350,622,68,307,451,684,971,126,506,447,103,70,636,168,442,171,44,841,961,156,182,620,365,840,795,517,503,986,120,663,478,22,119,724,186,360,657,766,166,393,321,674,492,247,437,134,200,27,204,448,276,920,655,448,884,221,905,846,22,220,863,400,937,49,460,573,698,405,87,359,28,319,470,221,401,478,353,765,792,882,952,142,955,718,961,132,978,275,849,911,843,545,710,760,857,799,79,498,876,875,58,421,83,168,323,455,374,597,129,709,650,387,882,201,108,239,71,2,423,666,975,309,695,794,340,515,192,145,802,114,767,503,786,827,875,704,721,624,393,799,797,1000,759,377,118,184,56,120,927,814,719,87,335,598,617,907,592,662,245,869,328,571,903,868,513,852,683,779,898,795,490,695,575,703,989,919,73,771,416,4,876,217,6,765,592,604,822,507,468,212,945,625,310,475,726,728,909,656,277,163,183,428,885,403,393,908,317,729,487,347,982,265,562,296,458,354,233,213,792,811,159,67,192,465,909,511,65,658,879,817,611,810,162,344,191,551,188,786,774,115,866,638,347,588,807,161,219,87,331,246,540,275,13,446,718,252,212,469,649,937,111,386,276,326,712,606,806,42,214,720,188,274,185,236,63,11,693,296,468,532,490,945,768,506,868,875,201,270,152,67,183,143,996,993,751,6,254,654,357,237,997,64,880,533,972,559,903,478,319,148,933,682,913,755,98,609,616,316,490,927,463,689,371,272,991,422,278,667,606,706,980,387,153,439,123,585,180,192,166,722,2,323,463,155,22,744,667,858,330,363,253,953,258,490,167,543,565,238,808,601,366,779,662,430,142,509,320,7,701,308,0,868,820,889,315,353,615,683,48,89,712,881,514,175,704,765,556,903,475,875,440,996,764,954,365,571,65,359,426,213,98,620,263,866,798", + "917,564,216,648,779,772,70,893,609,815,124,598,503,709,940,809,690,680,769,937,562,200,549,470,238,414,274,899,859,683,422,363,104,760,353,128,877,615,301,336,475,823,395,973,134,452,396,328,642,674,386,169,582,832,208,743,319,522,151,986,511,857,309,716,737,603,766,730,869,253,670,476,314,585,293,188,188,929,287,51,399,83,882,604,973,258,563,822,864,193,33,135,90,386,317,321,407,175,116,484,448,229,732,783,240,827,29,595,38,417,246,718,378,633,577,686,489,655,334,46,202,132,26,144,257,61,414,591,326,366,643,333,767,431,671,523,802,213,311,121,374,775,855,143,410,337,188,741,705,248,778,490,734,774,803,907,323,450,307,459,340,161,187,386,933,152,624,195,331,36,145,657,505,954,106,172,505,127,192,936,316,641,828,398,913,909,328,848,6,971,228,519,543,794,866,788,830,554,39,112,12,299,158,299,782,532,422,859,730,678,934,52,916,703,893,352,441,16,53,809,474,17,794,488,322,860,860,589,33,765,170,953,463,628,184,839,199,314,537,118,525,644,214,832,720,441,862,210,978,682,239,895,212,95,322,381,36,958,414,729,315,877,54,390,365,841,274,452,525,610,803,916,150,228,936,399,979,735,762,253,954,526,625,112,843,307,136,351,870,790,657,979,37,862,97,614,647,752,153,444,63,759,94,13,450,295,235,244,898,945,27,692,392,622,589,766,721,59,833,440,886,104,741,187,62,353,803,935,301,806,936,343,189,418,927,15,520,523,419,529,997,500,388,212,691,643,978,76,499,697,596,691,180,424,867,167,48,468,588,627,934,717,104,591,746,143,893,254,722,822,128,302,678,602,350,269,633,937,548,428,452,326,374,359,98,400,927,904,527,925,198,75,409,417,257,804,460,735,276,65,498,494,41,173,812,936,537,607,637,461,604,640,235,349,965,650,365,420,314,142,216,90,956,315,7,225,760,147,593,978,936,206,676,752,383,497,91,782,277,873,428,984,460,600,295,278,299,311,701,774,517,13,327,773,340,819,173,600,821,260,940,991,609,516,736,956,331,142,397,303,749,795,807,368,596,218,286,99,480,950,465,393,914,264,262,875,716,353,801,710,900,652,303,428,448,396,569,453,591,703,304,678,614,663,928,607,49,469,839,732,446,728,733,694,578,525,646,267,358,122,461,804,169,751,277,998,241,895,821,232,595,463,364,564,946,213,165,964,555,638,257,218,101,765,682,321,564,468,91,994,544,299,517,708,612,953,530,587,610,129,250,344,702,808,81,344,824,785,607,503,156,40,283,213,340,928,497,438,558,932,986,228,277,806,162,613,32,3,153,538,846,159,968,217,411,740,777,291,778,650,81,826,848,636,561,877,5,976,645,695,85,29,671,188,128,77,605,964,690,698,941,445,638,837,959,319,198,141,737,813,930,736,60,854,525,62,723,702,90,467,744,245,2,391,628,324,424,542,807,168,55,601,23,605,179,885,464,649,513,444,757,847,426,544,390,195,763,447,269,574,136,887,951,806,499,426,186,674,564,437,810,718,714,923,471,710,482,779,213,926,775,590,804,721,301,252,942,523,979,14,689,703,826,379,593,349,814,635,12,45,259,692,504,275,443,99,374,727,892,675,85,185,940,522,417,459,792,395,292,911,110,599,264,89,628,290,681,547,276,439,364,942,968,845,71,188,922,610,439,170,329,519,917,829,837,470,926,681,525,449,502,812,633,48,316,296,956,87,502,200,691,402,61,429,484,770,104,473,769,973,115,749,800,27,417,891,385,261,995,56,86,896,906,415,516,414,434,572,989,389,982,484,859,277,548,902,407,930,593,312,409,980,903,946,563,746,379,945,696,289,764,12,921,111,588,149,133,717,614,221,901,984,137,740,552,91,890,263,866,618,715,534,19,881,743,383,258,540,618,899,486,866,218,44,462,658,657,951,173,316,888,489,746,959,251,453,927,861,725,402,372,789,312,796,821,573,671,440,373,500,209,286,553,942,431,964,10,143,758,326,252,247,938,361,54,453,929,739,147,171,899,881,752,256,958,803,834,93,745,823,887,914,577,332,933,486,833,94,296,551,23,332,108,980,801,621,603,371,282,303,144,676,721,70,323,550,361,114,418,748,53,568,680,786,793,420,438,90,497,582,634,859,886,149,515,914,844,421,306,378,461,823,466,805,293,868,0,378,702,357,614,211,308,911,237,672,839,141,759,497,348,53,722,313,393,123,904,241,499,179,723,680,264,978,314,482,348,634,783,721", + "351,677,258,658,982,467,5,761,973,627,467,72,755,409,912,652,522,916,101,969,1000,3,860,428,354,906,716,393,441,470,102,571,400,593,725,861,618,411,175,98,593,414,766,384,336,890,9,693,763,930,20,794,126,169,546,166,762,74,757,385,286,366,193,874,538,552,761,810,309,258,111,886,782,128,357,195,335,106,921,441,671,792,632,408,49,589,112,716,616,298,746,106,803,387,172,278,524,65,60,349,55,110,855,912,407,908,827,289,960,352,279,657,792,320,750,453,759,490,83,41,327,879,118,444,523,384,42,159,311,356,552,866,675,830,948,180,434,930,392,254,902,370,251,832,591,482,771,970,105,172,522,588,898,592,531,497,785,281,730,569,246,424,988,578,701,288,226,26,407,252,935,384,751,2,404,233,195,8,307,226,997,921,647,989,18,50,839,698,996,688,742,675,626,859,704,170,40,718,551,496,776,52,386,582,542,898,854,340,922,250,759,149,289,787,910,745,741,255,197,273,168,956,101,93,223,131,519,250,404,857,637,740,160,394,357,87,49,687,782,951,658,397,740,874,24,208,359,504,22,448,203,430,575,102,593,311,434,129,626,992,746,786,42,463,682,373,100,96,34,39,401,299,160,163,749,134,926,102,144,187,833,585,265,100,253,405,85,930,455,307,496,682,805,254,132,551,915,331,904,707,799,344,506,256,142,336,626,206,2,774,701,880,289,794,1000,857,61,238,529,149,278,644,418,438,850,555,271,135,737,251,471,889,800,815,273,112,510,997,280,445,775,86,356,366,54,578,490,333,824,288,307,689,67,615,428,659,184,760,653,535,845,228,158,414,356,896,879,902,450,419,245,231,60,84,891,927,512,111,303,105,373,345,30,820,686,89,709,177,530,56,909,399,604,326,3,431,359,990,488,648,758,121,615,401,161,103,499,495,793,761,707,260,773,42,786,63,317,636,388,7,710,791,211,865,865,623,739,517,117,339,324,217,310,218,338,759,522,862,425,559,64,584,380,121,683,239,456,161,34,278,65,96,180,362,945,418,610,821,472,313,720,125,346,996,38,75,219,526,898,391,718,531,690,728,231,537,237,431,9,384,714,15,476,878,902,38,405,875,668,475,738,319,864,383,948,90,129,171,826,889,541,228,103,551,923,716,856,92,811,72,891,87,410,601,60,729,882,787,812,854,35,741,817,82,346,210,289,569,671,646,157,857,76,31,402,800,197,376,872,433,270,756,750,393,905,428,57,895,643,896,411,470,218,857,23,498,179,955,468,62,823,509,479,507,724,575,316,264,77,557,660,144,695,729,114,85,36,265,667,1000,313,530,567,941,611,60,173,113,463,275,512,751,981,130,747,58,635,661,594,701,747,428,335,720,853,854,774,391,821,372,883,70,797,295,945,462,453,961,580,743,137,17,13,822,891,107,808,46,798,729,402,525,153,859,62,525,566,537,99,979,873,619,137,9,761,993,433,217,30,359,661,248,939,960,682,281,344,770,553,911,620,788,740,859,245,859,970,704,651,481,459,147,260,236,500,301,520,130,737,896,396,738,227,67,268,250,719,797,399,178,831,860,878,228,434,982,714,260,371,918,932,992,675,406,315,489,244,952,611,669,863,680,837,935,217,261,619,716,86,41,874,448,306,999,486,619,381,17,594,620,591,170,867,909,699,909,809,361,921,572,670,282,319,261,568,805,428,136,97,998,246,534,810,102,833,423,404,815,839,543,862,166,917,103,45,104,617,398,335,461,149,736,193,556,790,247,127,694,820,932,210,203,444,429,471,806,564,50,991,382,162,385,582,973,306,500,590,67,956,190,785,861,844,669,131,543,588,724,533,804,292,419,10,259,791,710,255,636,940,686,274,383,687,156,904,242,84,941,980,484,114,800,296,201,786,860,565,579,449,793,81,369,722,758,15,847,109,333,494,944,996,56,794,66,982,997,270,755,584,940,782,156,659,603,327,999,430,352,118,694,97,384,971,512,439,866,204,450,750,136,856,610,269,231,420,515,235,162,745,739,52,106,838,605,952,774,301,859,802,448,958,649,156,291,130,31,586,761,161,585,341,992,197,143,728,171,216,481,719,652,867,180,675,473,632,61,926,845,981,469,17,107,780,693,780,159,567,342,226,220,453,479,198,169,586,281,902,718,682,919,720,973,289,174,915,674,752,288,634,180,86,676,549,185,851,820,378,0,372,332,497,92,731,885,190,104,974,482,810,511,954,267,886,686,722,671,68,664,445,802,294,136,347,618,369,785,751,442,459,247", + "988,490,162,221,61,9,354,467,647,578,240,349,875,327,48,326,800,515,273,606,88,86,263,77,94,228,392,861,546,582,287,456,677,534,674,839,2,306,303,870,111,643,976,270,453,620,6,193,273,269,856,815,295,951,165,885,307,726,820,781,960,226,174,329,915,244,17,864,781,155,371,234,12,408,751,729,64,646,210,21,897,697,772,919,556,8,178,4,766,479,509,7,169,66,868,425,344,170,557,372,889,327,278,635,940,504,871,452,476,804,969,222,237,747,499,111,355,480,788,135,250,662,250,264,907,577,983,810,100,866,487,372,82,804,329,829,255,914,733,836,495,235,350,939,937,906,627,992,993,252,2,839,604,243,911,484,342,209,736,125,488,733,47,609,392,941,530,834,498,504,96,87,356,185,408,515,966,401,765,334,349,913,864,429,211,832,348,142,613,662,374,123,366,668,383,603,112,896,756,65,656,487,640,5,381,127,226,834,37,500,833,284,229,628,524,132,699,831,402,156,768,736,652,814,324,801,515,548,885,918,110,552,653,808,242,304,642,240,801,299,428,366,726,714,281,902,874,404,721,111,187,489,148,604,301,80,469,979,314,556,635,10,115,779,115,854,323,777,247,626,352,737,248,801,898,504,91,548,730,570,454,56,234,716,875,427,498,584,889,569,732,662,148,706,279,178,346,910,344,280,930,165,340,161,652,616,194,214,938,607,746,721,581,567,451,500,250,602,995,966,262,52,111,660,332,914,430,292,388,721,146,575,154,352,520,2,466,162,304,194,185,629,567,210,524,937,695,315,707,596,393,885,784,145,466,906,435,4,345,697,732,577,218,331,818,793,410,313,184,88,772,526,463,548,841,763,891,635,318,370,821,897,764,599,278,269,938,975,854,644,38,604,896,138,1,45,204,646,696,746,459,567,548,262,463,763,280,504,316,435,936,677,121,171,127,316,81,531,215,56,939,652,447,684,895,708,426,131,627,3,793,687,117,877,720,878,228,732,46,444,943,427,486,415,38,791,988,957,503,745,703,236,281,13,242,452,234,774,724,248,426,159,427,344,540,229,205,615,672,277,11,661,951,955,36,286,607,244,462,182,908,269,159,872,739,898,165,365,365,200,209,100,490,869,791,773,306,421,901,353,684,7,194,467,526,76,539,222,181,418,395,750,779,688,159,759,304,76,924,842,762,97,336,168,477,330,5,99,198,816,736,480,771,77,9,97,932,110,811,180,136,940,119,470,317,441,19,420,301,257,530,600,872,698,494,401,502,481,562,650,927,339,458,934,784,612,543,615,142,525,684,24,764,655,961,962,784,57,239,534,530,700,282,338,526,909,374,988,401,889,414,489,482,799,33,671,842,523,760,108,60,976,309,4,656,518,635,108,282,751,663,826,433,350,292,414,388,791,584,7,703,363,214,81,805,785,735,616,124,578,621,375,897,679,502,719,766,901,796,818,165,520,306,282,784,700,261,173,939,859,412,272,40,127,145,696,621,403,174,800,12,151,943,494,672,211,446,624,941,251,108,676,100,902,804,160,66,995,297,183,386,282,18,698,951,743,503,418,501,691,943,669,847,39,616,400,284,747,8,56,102,436,539,774,347,363,257,411,737,720,242,793,159,425,713,525,476,637,712,204,311,158,700,594,187,415,472,671,345,590,215,518,439,142,312,591,372,837,906,176,60,4,403,335,791,563,916,950,992,95,417,813,623,37,87,837,711,315,834,945,820,678,795,127,381,708,690,436,425,987,254,699,332,927,949,975,460,280,542,13,691,938,108,829,750,873,974,664,219,61,190,989,967,154,864,631,341,36,399,113,895,320,680,710,333,587,376,156,177,864,33,595,481,211,937,669,66,506,693,985,302,774,953,134,46,86,715,971,814,228,966,468,828,486,314,128,280,369,273,104,249,25,455,453,541,743,913,125,608,81,647,339,764,516,136,150,369,400,858,562,403,204,247,346,93,98,965,357,786,391,374,531,242,849,280,385,357,204,296,306,541,899,655,584,222,890,33,389,426,282,357,206,448,885,779,444,416,915,249,838,488,426,234,397,642,583,717,900,963,830,99,664,604,990,277,472,164,971,646,133,834,142,492,256,466,956,846,442,100,915,960,587,650,243,249,185,833,894,360,967,830,483,86,654,103,932,873,162,978,873,514,166,478,669,336,694,864,78,92,61,225,167,593,560,225,889,702,372,0,684,349,126,61,79,143,530,210,303,857,16,126,201,153,206,194,712,714,722,493,713,113,604,92,180,444,986,895,747,819,91", + "696,703,249,396,449,739,319,112,418,142,778,515,903,974,769,924,955,334,753,655,413,246,828,137,494,667,486,533,549,84,842,832,434,681,751,917,98,251,679,809,662,758,655,793,755,926,834,955,712,791,449,579,605,799,395,61,253,495,626,216,489,579,369,86,718,2,147,876,925,333,60,49,742,83,939,87,468,753,631,698,484,45,166,104,856,130,460,487,597,813,71,808,348,660,667,375,581,735,909,962,517,350,326,821,816,143,312,302,121,291,217,226,350,52,784,53,3,219,354,156,919,798,919,337,827,552,842,220,945,726,235,153,415,390,33,442,72,61,224,828,374,886,339,211,195,339,264,731,795,574,152,207,770,735,54,12,817,160,534,863,143,502,306,977,651,130,799,753,514,374,53,348,486,104,397,120,909,341,959,35,604,788,849,880,154,519,224,591,353,643,760,824,403,574,821,300,388,67,35,221,909,138,224,927,489,461,334,361,14,692,637,146,853,704,679,422,922,660,549,986,26,1,38,189,835,668,486,496,415,985,647,751,196,819,855,956,621,459,496,330,30,629,792,532,408,545,948,792,816,694,327,720,487,594,329,550,999,907,246,309,611,333,84,148,108,711,414,281,428,40,197,305,80,699,51,331,842,666,306,506,757,479,604,801,108,828,726,149,193,277,396,657,335,150,571,867,340,134,278,363,734,569,164,463,142,701,241,15,180,545,881,893,987,378,382,702,985,169,918,308,720,439,322,91,908,460,48,367,101,204,484,530,344,852,491,184,35,162,98,478,214,595,385,685,177,271,194,352,583,528,570,669,670,560,610,804,810,773,771,545,907,134,377,857,286,926,58,277,852,855,534,419,127,514,216,415,948,693,503,258,337,357,273,711,176,117,837,101,646,430,454,724,868,909,250,188,110,770,832,607,673,589,902,171,696,700,223,746,67,328,785,448,120,761,74,90,499,727,254,854,905,50,919,867,201,423,360,124,727,648,824,841,642,572,400,845,387,215,787,993,892,180,314,977,836,214,881,886,722,957,574,348,421,838,918,483,25,501,650,652,359,663,169,300,318,725,271,830,97,457,838,938,683,567,927,29,468,432,61,20,597,158,992,615,247,760,163,196,793,855,464,184,314,485,952,574,302,884,172,940,67,526,804,387,606,353,385,298,13,190,953,925,606,704,179,927,449,614,881,418,116,931,881,121,521,812,471,854,810,240,686,501,838,475,355,168,128,48,729,267,746,414,500,327,682,536,725,37,894,896,273,979,322,190,866,774,507,993,895,325,167,201,513,202,974,991,541,125,378,221,123,79,484,205,205,781,723,914,287,280,770,470,562,114,541,504,984,288,135,660,223,893,286,145,455,367,475,840,47,554,929,602,667,58,780,584,746,902,603,707,705,975,878,935,127,364,83,785,610,987,860,36,584,345,405,557,37,21,93,277,16,782,932,676,696,565,991,879,651,220,833,93,830,994,841,487,689,424,102,260,293,3,563,823,344,245,5,18,432,373,63,961,566,934,214,845,350,14,896,130,357,608,783,956,844,769,521,566,832,651,768,629,223,832,384,198,367,778,104,315,226,643,655,839,674,457,177,380,104,653,287,856,429,520,847,69,255,662,359,437,739,640,597,135,181,819,750,472,210,248,905,797,346,631,238,609,370,315,859,843,948,452,905,874,228,282,63,536,692,705,611,899,622,281,845,599,975,408,538,10,735,953,981,466,929,786,265,528,77,72,567,672,412,672,674,493,744,151,815,813,862,979,893,60,695,191,446,800,350,594,160,470,179,523,892,990,610,904,444,281,194,399,989,474,499,704,887,491,198,639,512,851,299,938,630,11,706,822,918,227,555,590,658,227,727,382,454,207,934,892,832,634,935,60,125,530,693,48,180,966,503,745,436,647,605,40,386,226,923,426,390,222,420,112,468,379,960,933,24,484,329,562,420,452,827,800,680,927,884,870,701,604,738,478,515,134,258,721,506,349,923,499,692,73,548,889,742,925,346,297,510,546,982,144,40,547,325,359,445,553,899,845,381,814,502,462,587,891,130,638,617,125,598,163,51,592,701,338,732,238,983,194,515,853,375,682,106,876,411,854,471,941,692,397,101,203,67,647,695,330,149,850,165,224,315,720,252,377,413,414,352,574,6,119,62,341,268,187,769,941,945,627,627,970,428,926,341,33,496,547,610,631,114,214,738,315,357,332,684,0,371,710,378,641,707,174,840,154,662,930,107,420,815,696,264,813,864,368,255,681,209,280,463,182,539,411,487,106,196,756", + "570,977,210,15,490,23,351,70,155,921,232,869,779,977,467,995,789,632,838,653,780,443,716,4,13,510,948,572,342,81,554,496,884,187,844,493,358,506,816,810,420,369,25,379,488,850,82,678,16,897,674,632,363,607,296,648,651,176,83,828,991,212,881,124,571,249,61,981,928,447,479,919,535,483,887,641,282,204,711,437,46,457,383,982,696,892,336,898,708,766,479,701,514,573,47,105,177,816,681,766,616,651,479,736,991,637,390,988,38,118,593,625,115,25,255,565,927,390,896,806,598,11,827,253,515,916,505,4,384,577,89,246,239,516,234,720,252,686,133,86,271,859,890,498,202,32,759,933,610,831,926,888,331,919,161,229,51,986,496,855,666,744,85,225,902,8,969,934,920,907,925,373,774,767,848,973,570,422,472,509,532,258,38,460,495,951,755,965,620,82,574,180,72,612,493,235,70,722,746,608,648,683,755,336,165,950,916,719,628,351,762,944,315,298,728,865,618,141,282,872,377,483,991,438,512,511,226,397,372,929,978,629,138,822,731,737,49,79,314,660,12,730,560,110,830,473,654,9,364,642,317,753,522,947,262,407,669,866,453,393,145,680,819,9,377,611,992,320,148,417,335,357,446,664,520,307,856,140,679,625,690,298,956,638,40,46,776,766,661,504,856,431,270,24,488,574,130,917,49,11,601,235,815,466,125,26,275,706,388,46,88,871,498,981,953,957,789,933,257,494,367,436,352,6,520,291,841,40,357,205,813,702,171,927,850,434,201,826,482,666,777,197,986,850,256,589,217,72,319,834,373,897,65,474,958,635,658,968,309,63,277,917,535,35,58,159,878,949,153,59,389,520,266,553,210,997,469,353,358,955,829,290,577,909,315,202,508,195,942,929,535,662,245,278,607,517,409,643,502,776,975,969,797,120,518,110,787,646,820,135,569,176,301,682,420,636,771,298,262,147,559,92,496,381,947,314,555,100,147,512,415,396,284,836,577,149,255,408,519,178,752,972,771,734,996,743,393,911,687,895,137,260,801,33,97,496,791,642,559,253,981,100,713,963,926,448,478,979,254,466,606,479,854,630,750,223,174,446,919,125,759,975,771,664,627,655,562,46,262,553,491,732,381,834,445,213,414,428,409,638,859,475,574,947,144,87,958,255,445,120,325,964,198,147,587,584,282,421,6,106,479,551,254,760,263,747,767,465,861,323,154,846,896,500,800,773,758,129,360,677,648,592,745,699,984,394,985,779,129,482,616,78,353,609,771,552,777,328,884,485,895,382,166,141,932,658,325,80,641,989,200,71,600,987,105,642,185,199,865,167,821,450,400,153,437,292,955,820,669,67,6,724,88,27,470,814,205,555,681,317,772,11,414,618,504,656,531,759,171,553,712,65,660,505,814,109,788,678,958,721,745,952,154,780,996,471,25,590,411,838,501,642,165,25,206,357,7,855,382,593,595,740,216,181,293,873,57,196,482,192,893,636,109,980,832,676,962,220,158,762,266,173,753,387,836,782,249,541,233,782,972,530,847,851,828,290,499,351,620,625,479,963,86,584,566,702,855,101,270,568,950,4,605,505,133,970,295,542,911,527,919,523,300,715,755,342,684,70,283,308,850,914,600,636,293,225,952,781,372,390,814,910,832,604,423,792,986,574,433,669,177,685,715,244,913,518,304,626,675,290,796,562,935,680,247,816,83,54,479,895,900,197,915,80,513,413,224,442,365,80,257,150,474,305,564,115,27,113,512,503,457,705,894,543,129,598,620,110,806,106,743,378,106,696,911,921,288,260,905,858,46,426,483,941,408,8,222,388,132,701,806,144,100,92,517,112,254,262,873,64,358,544,342,788,616,622,948,25,372,262,591,944,126,630,475,103,289,353,131,450,687,804,533,253,602,129,361,386,845,782,164,701,225,445,893,728,409,705,703,591,373,912,859,415,705,875,125,861,115,746,740,835,384,329,313,969,933,155,451,153,467,187,333,549,608,589,703,820,402,469,303,57,665,179,67,540,855,580,229,620,953,497,638,82,262,229,944,770,334,13,475,476,197,515,819,798,617,829,675,511,725,699,78,726,171,816,711,276,412,875,731,310,2,573,692,445,827,262,168,609,735,605,923,462,181,398,359,835,428,145,403,602,548,741,332,261,31,436,186,641,984,421,99,828,200,341,955,907,410,395,690,754,825,532,280,353,614,497,349,371,0,956,140,164,408,482,157,615,852,311,465,738,617,475,140,902,950,772,798,591,712,786,654,646,340,350,735,603,302,857", + "416,243,135,324,271,814,811,763,998,255,867,299,213,568,284,699,974,220,638,934,120,432,470,203,204,228,419,504,401,603,108,509,181,190,234,952,384,798,225,234,719,530,224,9,731,669,945,663,489,19,383,435,168,671,804,229,254,703,601,895,341,754,567,748,277,287,754,809,52,898,864,717,888,315,424,867,186,662,214,368,637,26,615,570,345,865,654,83,874,109,310,877,519,61,36,367,306,64,330,61,607,374,188,138,494,952,165,272,371,214,173,622,28,514,276,610,420,756,735,426,748,322,282,645,372,707,666,835,611,185,816,105,429,752,499,683,575,882,788,949,189,32,84,584,985,87,395,563,476,849,594,165,217,577,352,700,581,371,819,202,236,740,650,676,588,331,539,66,656,989,192,367,485,892,515,284,657,398,684,603,633,828,5,696,187,409,280,938,735,539,662,958,346,525,400,594,901,966,394,1000,866,862,407,260,8,981,167,500,285,767,912,536,62,367,65,481,962,378,712,771,305,741,991,585,997,562,392,527,794,497,845,380,452,740,167,940,631,64,925,242,655,582,820,55,364,343,367,588,742,491,743,822,663,297,237,874,814,243,487,928,87,237,601,411,270,517,909,302,155,889,998,816,307,330,121,136,642,169,731,555,425,91,383,891,170,207,638,517,43,818,347,390,760,937,312,6,382,570,846,47,405,351,535,208,859,182,567,198,86,64,426,275,887,364,886,849,830,812,202,297,581,648,908,203,269,345,260,579,857,202,831,834,803,29,60,967,958,413,388,91,693,596,711,660,671,452,416,989,65,715,615,142,61,860,511,290,557,203,516,538,907,968,652,424,131,862,682,40,749,505,567,398,172,926,331,65,107,33,718,334,156,116,974,160,92,689,731,391,151,448,189,819,625,128,132,523,190,749,5,764,59,84,659,923,262,467,701,153,970,485,947,485,107,755,857,554,750,56,816,666,780,481,134,234,708,464,844,855,372,613,472,690,297,190,714,261,725,49,131,823,18,931,400,925,586,556,396,7,829,583,700,556,889,583,709,147,950,672,701,419,413,715,396,364,388,320,390,612,259,885,836,800,275,635,325,657,761,541,714,498,534,676,69,393,712,369,756,304,76,840,937,616,235,254,449,462,151,305,563,637,487,892,371,167,615,777,30,676,873,836,674,837,314,753,946,619,291,13,788,979,192,636,86,5,232,881,241,877,188,295,719,360,367,36,898,149,203,796,827,507,534,93,266,558,513,151,878,736,636,801,807,751,264,79,687,175,955,417,332,48,390,312,139,222,465,900,936,43,501,790,78,994,668,796,474,1000,287,604,323,982,480,850,89,207,19,551,302,61,611,394,101,536,820,789,612,24,568,734,517,242,938,44,129,179,401,107,853,174,481,175,513,663,205,656,700,820,243,386,31,529,408,61,149,776,131,61,686,39,824,150,444,775,375,717,39,108,614,610,955,538,690,355,941,48,493,168,429,649,29,155,229,996,991,715,553,91,767,87,69,861,701,55,579,805,633,978,175,433,987,40,664,689,192,739,443,897,105,989,741,867,314,986,443,760,898,652,576,201,307,384,321,575,174,801,741,315,950,761,800,74,99,737,749,503,679,256,690,266,858,766,22,220,52,9,271,278,385,924,850,194,400,518,503,511,733,942,130,216,101,50,744,456,790,362,712,966,774,640,793,35,644,483,860,121,103,550,515,389,494,355,150,251,912,142,525,317,605,288,945,983,91,373,254,523,146,47,174,446,596,428,769,185,304,371,803,493,107,929,164,137,986,683,393,45,362,385,722,562,304,636,850,394,883,143,966,617,672,700,835,627,673,552,877,723,40,82,402,490,393,952,53,102,280,906,890,641,729,179,218,447,171,489,117,856,328,675,818,730,836,5,45,538,474,262,978,395,764,662,607,433,827,253,2,256,384,332,924,909,879,23,339,793,874,170,994,555,369,796,675,782,16,781,826,860,555,172,997,86,268,950,191,587,543,947,566,644,371,331,379,319,386,517,867,47,269,439,512,857,36,89,7,529,507,51,520,720,69,35,203,339,74,482,280,104,460,912,339,672,353,258,373,565,734,473,56,107,991,832,659,621,100,240,328,39,103,267,570,875,871,433,996,654,187,714,41,675,443,726,589,37,976,989,534,805,876,721,106,247,650,857,604,240,69,942,521,775,570,644,218,89,605,408,18,584,713,615,211,92,126,710,956,0,174,775,491,631,256,258,117,65,878,344,503,200,409,283,320,333,185,946,887,322,200,327,169,806,171,308,205,873", + "444,630,677,725,884,719,989,222,535,946,289,293,598,402,157,540,104,959,683,547,309,257,634,587,468,197,575,923,475,62,807,736,35,842,669,295,641,165,141,619,298,975,83,59,909,825,820,214,139,694,836,313,235,829,857,200,856,618,683,374,850,298,647,378,632,213,801,261,603,36,884,700,574,855,141,171,927,572,907,676,304,77,27,231,990,792,6,339,573,313,626,100,485,440,956,443,38,963,381,464,595,393,613,426,722,96,326,89,133,656,486,781,477,772,118,497,574,944,612,26,812,285,758,711,652,491,965,965,418,996,178,657,794,18,866,146,861,927,490,413,995,471,213,139,671,583,676,54,841,299,824,417,168,805,219,682,411,454,50,78,98,324,373,694,151,305,779,644,368,450,447,89,646,460,613,60,677,671,383,651,271,615,384,843,829,261,788,222,856,550,503,334,114,572,508,603,835,315,713,639,335,137,294,70,856,134,728,773,931,846,30,197,951,211,861,414,532,62,390,886,401,234,512,631,669,52,430,834,295,622,831,970,599,49,118,500,697,819,950,517,938,131,408,400,534,313,318,727,959,929,837,445,650,476,828,980,384,226,280,314,91,382,928,849,416,36,189,638,481,298,649,604,827,762,662,723,633,957,762,536,204,472,83,663,997,712,228,981,323,178,405,525,483,98,918,124,32,218,561,890,796,471,927,35,694,639,112,934,616,58,436,385,111,257,960,655,926,867,290,143,871,951,553,20,480,269,16,846,139,879,938,721,571,930,774,389,142,474,157,759,478,685,447,889,584,431,218,134,278,655,236,604,448,252,626,972,817,770,402,484,334,755,441,373,135,896,248,219,933,755,670,988,108,855,679,429,440,617,768,694,985,757,340,799,18,474,738,10,465,551,367,212,992,689,592,75,758,510,517,641,941,495,98,880,637,392,939,404,237,906,479,822,993,950,720,236,871,826,920,30,252,594,473,797,151,944,450,592,46,941,101,147,35,650,28,149,5,482,112,892,659,160,917,968,759,996,324,996,494,745,301,468,579,342,315,986,337,948,117,826,417,571,328,666,901,170,415,829,406,976,729,102,792,461,723,739,428,496,529,754,359,478,220,546,192,609,926,117,155,363,301,108,189,573,993,489,899,478,692,697,555,185,802,214,275,937,392,62,5,660,282,944,211,871,911,368,759,343,844,419,683,432,215,40,382,136,690,444,699,173,264,367,191,287,211,904,56,621,149,969,585,562,898,298,190,222,646,729,204,100,319,278,650,664,482,912,490,738,506,180,317,192,614,783,868,880,677,877,977,281,171,768,497,221,780,778,905,865,857,677,869,289,53,278,211,437,412,759,529,470,902,177,195,814,430,864,258,681,652,428,385,773,213,909,291,496,758,143,417,402,912,791,667,56,319,67,243,339,268,914,542,780,609,75,454,312,272,119,304,580,560,841,442,678,19,347,528,415,588,672,112,777,211,325,930,582,606,525,973,382,647,312,86,757,96,766,847,693,904,128,920,406,162,949,495,565,432,653,491,484,541,16,413,501,126,440,444,177,10,135,536,445,664,585,239,29,527,982,98,489,715,21,901,225,766,546,597,881,861,973,573,122,893,855,476,534,293,260,656,21,116,586,406,586,872,718,783,344,562,171,320,900,177,790,37,243,808,689,856,794,688,530,529,387,362,777,910,765,776,268,450,344,168,659,425,726,48,221,129,376,841,51,699,733,931,182,382,505,527,927,737,790,624,264,45,352,904,339,513,650,220,81,722,188,545,555,773,293,490,390,479,798,129,54,650,905,199,781,630,700,779,829,104,977,968,770,287,813,911,623,629,36,664,671,140,180,417,468,872,187,86,449,168,613,573,947,978,770,547,444,743,292,39,59,562,825,68,153,905,704,609,911,187,277,507,495,153,984,595,319,831,181,253,623,92,427,143,920,81,850,272,641,615,238,4,203,906,447,983,799,870,970,838,875,402,119,417,989,613,998,667,399,396,408,879,58,73,765,584,160,620,97,310,375,649,473,77,122,461,789,729,822,236,667,692,27,420,501,373,837,796,689,686,56,254,288,190,872,361,437,830,306,961,92,597,261,251,664,675,368,881,574,829,679,31,513,932,871,630,940,740,580,336,716,239,301,244,515,353,176,498,826,61,132,433,486,874,498,206,918,796,208,193,814,870,278,715,233,427,588,107,491,756,53,618,683,308,731,61,378,140,174,0,882,96,246,514,458,489,541,616,425,117,472,892,717,464,302,648,624,426,910,141,160,729,853,818,732,757,484", + "784,613,290,825,416,862,151,757,751,86,135,167,981,983,52,176,552,304,139,934,119,597,242,574,599,563,482,713,836,940,905,440,623,686,671,87,81,817,718,95,482,451,735,286,77,259,333,380,103,326,720,129,755,279,798,911,87,741,789,174,307,6,475,134,377,157,871,441,459,932,553,785,640,790,58,562,325,299,432,125,316,261,801,611,638,990,48,398,516,490,854,849,993,438,883,634,109,792,748,432,466,520,994,516,481,732,69,215,136,983,901,378,960,884,546,223,214,926,920,197,523,479,491,875,910,610,105,514,448,570,241,852,591,350,555,391,133,535,408,653,798,664,69,227,415,263,339,762,733,605,957,473,591,606,924,716,877,602,125,865,702,952,904,415,109,356,486,200,99,804,949,111,496,479,295,393,608,765,437,126,900,113,446,664,510,337,405,450,739,458,143,206,54,97,123,883,447,365,504,970,697,332,16,68,855,869,613,304,391,378,566,232,160,511,522,752,98,520,550,485,506,468,600,605,865,151,264,8,517,345,451,311,445,370,143,784,528,825,653,859,32,198,407,633,241,144,460,237,185,658,833,542,279,791,765,930,737,256,444,538,433,700,685,739,248,733,295,170,387,463,700,738,680,848,86,879,563,667,127,452,677,452,671,226,912,846,409,250,718,901,383,71,511,711,387,671,968,36,411,867,483,468,943,456,167,123,151,487,440,662,52,903,695,747,176,300,326,499,523,68,403,190,283,495,18,10,503,759,659,595,623,486,343,849,768,855,747,318,577,467,412,2,16,128,758,417,845,181,895,119,150,591,861,311,689,338,454,452,232,931,114,15,73,904,105,584,971,756,166,44,83,137,935,315,976,200,789,858,392,984,948,713,606,192,492,516,978,746,942,102,192,184,80,742,131,908,493,580,756,288,490,633,618,488,100,981,980,444,977,997,334,525,372,476,2,983,415,845,389,453,565,303,242,731,877,174,691,924,349,176,655,366,850,64,4,547,830,81,351,402,362,936,194,540,699,662,60,302,348,700,355,553,992,284,914,754,483,54,409,955,421,299,941,98,425,969,300,767,985,747,238,133,434,99,155,821,346,942,239,243,233,213,591,581,580,483,911,869,222,735,852,717,958,171,689,97,429,189,981,613,433,83,784,124,461,286,138,220,871,294,533,400,837,53,1,653,206,655,534,807,871,368,208,168,68,207,492,826,65,266,409,220,324,918,127,260,953,825,679,871,657,537,170,919,626,117,848,891,760,623,804,232,463,155,974,4,781,482,648,638,572,526,968,32,58,623,121,235,585,273,962,424,221,689,708,976,677,443,151,390,222,187,564,220,764,334,414,784,397,355,751,319,333,927,9,7,436,454,485,71,11,648,902,216,76,135,478,432,185,843,630,981,924,239,153,39,453,353,319,236,295,818,496,475,573,468,144,225,380,866,743,252,923,801,811,717,911,573,738,679,217,417,672,567,77,385,594,479,757,505,182,890,662,283,147,330,405,948,491,150,258,816,670,276,463,444,916,236,32,99,800,496,839,600,160,763,784,333,399,209,147,850,527,355,976,365,41,722,115,60,1,910,361,511,793,290,762,293,615,873,529,55,445,112,423,14,736,54,445,950,424,210,392,191,516,901,788,330,125,94,688,738,148,168,900,434,77,229,778,507,461,756,736,938,188,119,662,431,160,566,5,691,159,957,477,222,508,558,164,850,281,829,741,665,981,153,346,440,166,295,669,820,841,163,572,768,764,435,819,578,705,38,539,352,574,618,773,509,88,116,806,520,984,59,902,299,449,152,987,220,755,582,288,386,429,427,875,321,123,853,571,482,310,194,430,199,539,985,875,103,797,867,101,902,454,954,295,348,862,470,777,296,602,362,307,424,101,368,194,729,797,935,911,31,13,795,750,29,319,295,35,639,47,100,963,368,680,490,347,304,437,42,86,150,537,62,665,615,717,450,652,776,178,298,395,985,579,461,282,576,221,34,458,625,952,34,240,329,275,49,582,456,5,631,606,995,745,69,944,620,669,402,686,844,999,657,59,589,679,557,195,963,696,741,366,2,589,426,930,587,129,336,836,717,639,137,513,248,890,204,700,858,345,474,678,472,281,673,884,487,447,875,109,396,160,409,475,728,133,880,54,33,827,412,325,968,515,833,951,107,189,193,220,891,899,759,959,675,691,612,352,57,762,676,189,48,911,885,79,641,164,775,882,0,773,929,542,187,765,736,900,501,466,389,754,564,326,200,331,30,333,70,727,161,334,636,815,36,346,813", + "581,262,752,479,9,674,615,970,757,61,410,960,11,478,856,520,499,989,815,976,727,209,93,613,84,650,861,393,151,967,163,982,708,941,763,611,27,302,479,197,300,665,689,252,387,254,749,599,547,430,700,875,42,418,635,679,684,455,202,91,181,962,82,486,845,526,314,827,824,572,575,82,283,522,505,474,873,772,997,584,571,356,284,132,611,763,800,565,530,39,129,780,175,835,341,495,533,50,662,55,600,251,519,241,989,685,629,155,24,110,409,131,30,767,903,632,375,63,669,205,286,839,630,307,373,437,105,268,107,951,569,64,720,926,24,690,323,766,1000,620,274,963,222,724,294,365,664,606,367,274,485,13,422,961,954,293,777,47,768,945,969,154,923,601,416,515,745,127,820,234,351,393,496,914,10,325,262,682,363,651,777,364,204,749,615,240,905,668,114,476,638,533,264,651,493,708,380,565,400,767,234,718,199,337,739,457,959,955,908,507,60,781,292,684,637,430,504,885,33,764,56,431,315,564,288,435,660,711,405,610,806,97,351,160,869,630,903,674,26,572,466,304,680,305,335,936,546,349,398,648,558,646,305,167,66,795,301,474,450,654,381,713,979,56,292,81,733,744,725,450,433,826,652,584,687,375,269,458,783,881,391,647,179,288,857,77,500,437,268,262,470,59,264,368,986,965,449,877,188,27,401,456,27,932,610,258,469,306,597,344,355,676,846,494,995,56,670,219,70,165,972,694,796,956,800,454,287,638,575,396,629,402,556,635,393,352,752,95,7,87,809,489,457,368,932,297,52,708,644,510,57,688,709,675,710,149,376,333,107,227,189,65,154,897,483,780,844,813,994,519,156,184,84,345,567,371,74,560,576,849,833,736,905,632,457,168,827,6,413,476,249,909,64,372,995,703,34,920,82,577,772,868,432,379,22,292,956,126,67,759,134,295,591,593,45,738,697,27,797,263,920,770,847,370,962,377,237,599,172,157,811,543,151,280,23,598,554,486,770,451,259,893,151,400,770,602,783,347,812,827,730,577,715,674,421,758,81,376,464,687,539,501,532,567,295,738,515,836,709,864,324,170,461,158,3,51,246,397,959,869,636,689,344,858,929,482,710,901,49,800,162,386,21,344,764,875,52,50,245,391,274,567,745,297,997,992,904,425,454,733,102,217,906,922,144,576,536,965,193,755,632,895,962,820,903,303,374,29,89,661,766,102,943,317,136,330,372,670,10,872,186,977,886,147,870,38,677,417,587,572,965,924,395,719,291,698,334,244,547,951,808,214,449,288,973,928,678,259,280,600,544,189,956,689,61,238,598,764,606,548,775,558,8,32,396,341,684,248,913,460,996,109,826,912,783,631,26,135,927,207,387,616,969,569,160,928,150,268,128,60,144,769,673,990,150,456,263,445,361,383,487,127,337,648,782,890,218,995,111,979,623,567,660,969,484,255,638,948,133,865,279,408,498,753,158,443,814,323,700,606,720,727,710,678,118,466,776,704,654,676,173,686,426,114,325,448,178,95,868,107,913,470,585,791,229,713,570,258,106,674,940,57,475,220,776,596,748,639,926,620,908,46,75,739,665,233,946,998,643,547,487,440,134,972,156,620,244,148,519,310,928,785,120,107,252,658,538,676,21,743,534,32,628,543,98,495,270,992,754,831,279,599,972,63,575,673,399,986,709,221,718,801,475,253,44,218,225,345,985,527,349,880,827,431,932,653,334,959,267,984,39,787,220,862,76,739,241,526,424,655,118,985,221,890,86,319,318,398,604,824,797,764,58,668,213,327,886,901,636,848,994,973,425,651,702,518,911,965,323,731,519,15,240,422,860,798,286,872,435,891,582,544,396,220,639,725,331,367,899,649,808,653,998,387,38,302,887,521,536,704,927,429,666,949,60,369,445,772,384,368,786,188,864,295,178,324,930,114,536,616,608,896,22,757,917,323,102,53,745,712,609,975,639,238,371,924,265,251,323,795,981,84,304,967,193,579,167,476,711,615,905,470,635,582,130,820,27,821,701,563,149,414,5,815,132,198,739,531,7,377,812,736,767,20,909,668,302,607,506,995,381,683,163,208,485,660,340,878,355,82,390,863,193,218,520,384,814,905,675,18,314,928,373,73,29,751,9,570,643,385,685,491,654,389,12,93,832,718,533,922,406,77,745,542,457,647,733,789,777,493,158,126,371,591,376,89,237,190,143,707,408,491,96,773,0,171,134,96,520,687,692,122,205,766,22,814,60,767,478,484,563,160,308,904,699,734,350,895,850,710", + "829,721,535,418,14,138,276,825,991,457,958,56,937,510,437,4,352,658,806,425,447,55,845,5,629,833,467,113,182,256,706,292,392,191,100,880,663,145,392,308,233,298,461,744,756,163,124,842,703,852,584,888,313,799,424,472,137,998,789,570,915,789,151,345,609,828,294,66,709,969,110,135,54,277,551,985,656,169,625,406,541,174,744,33,949,559,149,740,276,877,328,744,106,974,750,993,86,739,252,230,363,775,807,138,544,866,418,836,466,315,514,867,736,556,213,407,971,596,244,775,785,270,542,933,162,758,976,590,75,555,570,980,423,98,16,420,671,874,830,442,832,474,98,543,635,488,529,353,431,599,476,92,958,309,392,388,619,128,706,996,974,727,70,96,861,726,902,149,218,548,826,593,11,852,890,454,506,854,316,952,397,501,752,303,671,704,320,181,537,728,884,389,438,242,125,361,469,184,530,553,577,519,610,355,208,586,84,569,805,502,723,178,626,780,59,511,410,849,705,976,714,289,242,659,19,32,841,577,967,357,18,749,295,471,925,605,736,844,562,758,531,611,705,171,60,994,269,350,742,718,382,671,334,435,795,846,60,889,360,336,242,144,696,75,336,470,437,736,430,21,875,983,541,287,536,785,359,162,37,238,671,607,149,227,875,156,212,314,25,36,694,348,436,427,369,482,723,356,868,514,802,3,210,340,591,310,689,894,124,879,201,37,616,296,939,808,827,20,75,174,414,764,14,820,190,111,276,361,195,420,253,280,666,835,192,905,907,429,457,276,557,615,11,341,941,641,908,555,983,912,287,877,767,458,502,673,782,90,805,374,256,349,732,231,405,915,936,812,59,31,764,340,885,776,638,101,396,42,173,94,275,690,251,971,981,569,549,556,297,423,154,200,797,697,594,350,528,400,367,601,829,47,44,810,141,565,252,750,880,435,804,538,859,253,60,852,821,423,438,284,220,771,631,872,361,714,269,860,423,155,472,834,41,160,863,732,846,551,90,717,469,690,931,311,47,541,8,922,552,698,788,392,635,445,721,987,496,874,842,386,884,260,296,349,509,100,497,818,765,663,433,464,497,47,301,990,577,297,114,639,424,190,341,301,639,449,621,335,792,22,1000,359,671,556,353,764,92,315,182,957,492,285,65,77,947,741,227,454,48,372,69,928,324,412,960,726,248,78,445,228,437,696,234,870,739,574,742,315,326,589,650,598,805,54,242,707,797,611,477,235,257,893,218,275,461,84,224,910,617,774,494,323,260,292,444,77,456,713,779,542,37,67,862,965,312,800,68,54,410,398,751,231,511,573,225,349,703,588,597,895,865,532,509,295,517,844,143,900,960,353,114,82,56,993,689,298,979,513,445,99,34,674,49,949,260,39,718,283,850,582,723,745,236,123,809,351,715,182,461,947,876,702,416,867,963,760,920,244,214,892,97,11,176,816,22,881,600,574,853,939,895,297,339,313,858,149,735,695,744,485,393,241,805,699,273,62,443,921,106,211,382,716,80,601,728,905,823,348,184,802,585,4,879,456,61,709,946,296,94,532,362,602,260,720,593,978,439,23,763,524,493,931,772,826,203,293,827,789,408,764,899,780,715,541,621,124,109,501,498,362,771,424,194,549,26,432,607,884,217,577,923,31,91,979,963,104,729,569,502,129,838,295,188,511,753,769,62,620,805,217,796,460,696,100,706,349,521,92,575,6,8,221,144,623,208,813,264,448,704,734,313,808,826,436,881,986,220,115,99,706,726,307,953,303,442,242,285,110,241,773,178,554,464,998,439,649,916,538,816,945,158,195,873,983,122,459,120,966,36,239,276,31,633,834,190,103,984,220,86,548,21,401,378,411,516,913,854,299,987,84,369,724,587,241,480,87,212,527,743,778,194,270,915,515,358,354,749,112,644,430,722,51,836,584,180,237,505,48,323,671,769,480,574,677,523,397,342,869,822,864,129,29,656,415,340,435,954,875,155,611,56,861,519,90,445,889,510,405,899,237,571,136,928,824,549,873,692,643,912,38,479,572,909,470,473,880,979,994,459,477,515,149,64,490,691,729,35,539,97,826,648,577,414,908,900,998,460,489,208,166,582,509,547,811,781,227,172,285,36,295,853,580,336,542,383,972,613,310,92,239,549,993,194,736,577,903,435,192,392,86,925,708,662,223,343,745,998,184,372,137,895,581,857,248,513,712,672,104,530,174,482,631,246,929,171,0,498,336,285,632,158,224,57,817,97,44,130,792,806,236,901,124,863,392,28,663,484,443,734,100", + "870,100,984,240,178,258,357,24,418,18,52,78,993,68,287,774,189,236,81,715,523,451,767,592,133,672,149,420,360,36,804,960,797,51,443,951,47,652,887,731,750,232,587,450,974,989,866,61,217,912,947,292,244,679,78,751,503,765,726,830,545,75,218,399,77,555,143,397,975,932,905,832,828,415,951,586,349,846,987,31,770,252,296,691,602,146,84,265,221,732,398,546,317,724,707,27,965,304,814,570,439,86,636,988,395,386,495,667,713,983,235,618,732,392,832,53,853,408,387,285,774,10,93,816,443,881,287,220,149,475,635,649,509,196,689,256,133,904,144,863,955,277,46,222,25,494,424,744,458,896,468,792,232,398,149,492,904,345,298,851,91,19,616,656,966,430,387,292,443,325,572,122,784,97,231,572,557,315,423,146,894,966,571,980,572,314,769,411,698,866,74,988,192,897,326,357,581,291,208,953,691,735,371,413,331,422,721,680,712,206,908,517,633,972,718,310,373,373,470,363,161,506,393,261,358,944,156,519,421,602,839,852,913,129,304,775,880,42,154,105,309,950,66,704,208,86,790,838,467,981,630,865,776,572,531,821,924,359,771,452,35,920,399,212,674,465,394,124,907,231,737,145,564,90,510,8,433,648,358,710,912,528,190,286,432,372,451,815,348,609,972,405,509,822,44,577,98,106,511,800,810,130,529,171,671,658,504,566,854,407,244,504,192,9,166,429,207,37,970,54,645,353,500,494,891,502,907,427,438,195,650,627,16,913,248,299,486,674,158,821,323,378,523,700,410,975,512,975,763,454,770,508,58,175,505,208,880,76,595,480,787,656,819,78,551,60,420,607,503,504,770,609,912,472,548,128,526,327,600,224,783,590,134,158,719,927,844,508,980,240,566,430,384,546,420,758,138,26,734,179,684,561,454,233,391,130,76,134,240,154,737,340,89,433,622,731,465,635,78,967,580,554,555,40,471,138,587,334,876,901,475,837,315,591,117,315,771,518,246,121,927,826,663,609,137,883,520,302,867,228,557,146,720,594,181,656,304,713,602,867,702,947,670,40,340,987,106,700,769,416,561,183,722,506,572,481,353,489,926,327,783,698,431,45,835,768,162,601,869,361,757,503,37,797,618,446,558,196,367,286,353,388,267,140,712,476,954,472,721,61,461,728,861,785,63,912,561,408,201,569,610,731,85,52,378,610,109,720,76,553,118,913,76,649,455,364,467,747,825,204,529,581,83,416,713,375,544,198,470,458,973,516,61,994,188,139,948,29,237,166,757,243,24,433,528,981,202,962,797,210,384,963,678,222,689,341,284,364,406,529,833,445,713,580,845,58,25,236,617,21,984,664,647,988,470,564,860,596,852,469,89,654,496,401,471,243,297,889,541,870,267,791,934,743,561,762,192,964,961,890,717,124,74,110,182,352,598,406,158,433,78,373,677,879,313,140,598,725,230,759,30,301,835,862,896,563,457,223,711,910,383,272,904,254,693,212,114,448,366,2,280,327,820,465,550,219,771,790,165,516,221,602,140,860,233,135,696,55,211,827,922,839,435,134,404,595,696,845,665,609,480,809,911,308,135,84,528,171,201,957,267,623,648,548,399,46,165,51,147,261,674,56,492,28,901,336,28,694,408,468,346,621,10,942,707,519,607,568,229,669,427,222,319,105,932,552,399,795,930,500,97,979,188,935,247,279,614,394,395,726,192,496,961,753,228,80,643,203,838,692,775,24,458,909,218,764,293,800,903,541,873,174,607,547,168,431,964,538,166,343,977,117,530,27,159,815,501,648,570,772,112,837,442,595,333,173,60,75,837,266,589,12,225,500,656,229,617,310,70,107,770,429,786,966,542,977,910,64,553,641,233,729,555,854,915,658,335,185,161,977,825,514,320,535,581,184,43,679,461,712,955,227,190,544,869,292,897,251,777,628,363,732,304,767,106,803,967,357,209,997,504,252,864,386,762,144,698,768,986,51,273,518,184,959,76,125,40,326,859,202,415,654,50,342,425,220,549,618,607,198,546,379,923,74,19,103,615,311,141,570,834,526,384,386,895,600,334,225,327,519,564,572,153,132,483,97,277,145,932,121,177,59,136,851,379,252,354,970,195,892,130,109,232,167,137,905,162,884,732,909,760,4,401,742,490,21,265,345,356,296,228,160,685,262,137,609,11,94,334,720,158,171,172,488,432,881,839,974,210,840,157,256,514,542,134,498,0,371,6,827,571,193,787,277,368,261,563,178,521,333,90,132,569,839,250,251,119,773,189,29", + "378,807,861,353,92,562,364,737,474,142,975,930,523,490,253,92,676,740,362,104,861,316,75,591,734,333,106,767,999,965,144,319,981,679,843,50,522,351,723,204,110,592,180,231,803,707,606,486,953,594,560,443,829,869,982,78,663,671,48,490,831,138,64,102,6,178,123,813,876,506,263,102,338,522,35,888,159,581,35,894,876,252,22,764,237,507,830,119,50,454,311,272,436,444,796,135,452,30,272,109,985,56,680,111,451,810,758,351,613,250,167,581,597,29,512,212,738,529,660,475,463,483,229,102,23,625,725,938,43,182,691,792,740,566,255,598,316,336,352,970,324,905,476,516,624,275,372,344,810,210,641,614,779,949,894,660,462,478,324,461,784,946,161,277,402,103,650,848,653,366,386,359,439,234,113,790,890,401,573,527,938,302,521,466,476,323,816,661,420,198,791,468,537,641,939,783,508,303,871,901,328,448,65,629,405,172,755,778,559,219,126,685,321,640,693,86,133,791,909,149,936,515,316,53,763,973,75,13,876,873,922,541,157,11,94,592,425,547,894,597,102,756,673,94,471,567,307,963,914,894,978,593,464,674,593,620,757,776,236,908,398,989,674,642,134,956,661,799,960,867,276,653,764,982,626,180,540,547,740,11,321,167,879,571,843,631,512,29,789,192,647,935,178,190,33,301,808,97,58,49,579,896,438,141,133,834,990,480,188,97,619,792,135,122,357,756,105,221,276,540,340,834,322,740,835,417,245,890,681,416,34,628,65,16,209,539,362,111,174,416,26,699,446,274,729,441,147,382,290,549,276,873,436,711,193,392,786,650,49,298,810,193,712,625,813,639,214,616,103,666,330,832,607,973,216,314,530,194,710,224,560,305,538,74,727,36,313,743,129,351,431,338,493,487,319,444,133,192,564,92,315,370,691,651,253,79,811,864,295,742,489,135,750,772,269,656,831,514,856,217,224,161,613,680,643,808,639,287,211,811,201,702,548,860,65,681,85,820,46,427,936,338,905,171,56,200,28,804,97,425,466,956,468,398,933,90,965,417,437,803,232,863,981,780,187,248,669,819,281,34,312,511,166,993,22,267,209,713,68,76,258,571,170,248,207,912,967,780,487,778,161,313,614,921,681,454,19,605,850,314,446,137,660,134,954,832,342,517,475,354,354,596,836,168,994,321,389,136,485,530,315,331,237,719,51,323,840,391,515,31,181,143,3,689,493,168,110,274,198,423,207,849,878,307,81,606,875,861,244,6,726,121,302,571,643,501,112,461,47,38,961,993,151,703,236,908,800,178,525,631,22,799,124,671,147,875,337,445,963,701,279,457,535,689,427,366,950,959,301,328,688,287,23,228,155,746,845,32,934,957,109,943,43,706,500,351,368,290,670,963,792,539,134,629,441,783,433,281,259,495,64,966,961,426,518,374,253,660,210,628,954,281,909,873,226,291,557,368,494,679,108,239,537,757,320,15,802,855,129,167,174,273,557,105,33,606,523,856,497,964,213,733,217,906,238,918,133,58,155,805,46,680,69,677,221,482,714,498,73,346,869,946,747,197,756,437,6,118,525,996,484,933,833,386,848,763,403,799,716,727,363,544,603,56,903,676,301,724,345,280,837,376,637,73,92,150,556,282,601,293,288,62,120,834,166,4,781,649,904,95,256,480,151,453,204,213,66,875,493,437,615,120,366,910,71,408,3,604,792,575,933,922,211,381,784,962,705,96,845,550,266,532,930,590,936,196,211,721,299,288,876,378,796,378,469,542,45,722,350,125,670,297,536,290,100,653,767,461,273,903,30,197,102,884,586,690,804,6,729,465,699,277,384,482,482,996,134,300,124,267,928,348,889,198,63,162,326,957,293,35,353,539,868,209,707,73,782,537,77,77,191,527,508,826,828,291,278,100,16,523,653,907,639,374,43,931,527,644,169,639,609,716,372,887,665,390,492,429,930,329,873,326,296,735,385,12,941,261,36,748,396,911,446,855,63,67,596,619,937,790,977,90,948,562,666,262,327,900,933,817,649,730,506,867,741,750,781,719,321,322,135,874,404,517,862,319,636,95,666,965,516,436,129,576,162,485,518,215,733,726,843,234,116,535,256,309,845,626,325,498,539,682,398,54,590,838,485,440,604,495,30,651,902,424,350,549,670,796,860,16,549,174,145,420,799,876,443,999,208,986,894,115,820,531,501,514,141,482,303,154,615,258,458,187,96,336,371,0,911,470,921,855,377,289,834,497,650,269,254,961,6,272,188,305,186,352,162,957,406,235", + "368,17,840,110,142,714,656,670,396,18,168,685,679,140,601,945,625,371,109,803,140,935,320,815,560,763,468,832,676,204,76,444,671,751,556,908,773,260,773,17,309,216,840,313,259,164,866,979,192,321,582,104,205,153,815,421,806,777,834,15,104,20,610,715,773,653,82,211,441,636,134,791,875,525,258,729,707,727,972,235,683,789,262,875,83,392,656,802,913,738,244,410,869,875,217,926,326,694,654,701,231,635,414,46,787,570,757,268,847,23,746,640,869,117,483,12,913,980,90,692,371,28,943,392,540,152,662,279,961,156,861,987,313,146,302,939,293,687,126,881,692,985,105,105,463,944,35,735,325,273,528,659,64,286,846,307,532,906,296,292,151,183,460,819,827,742,691,308,847,828,7,845,392,854,719,515,703,82,704,326,509,415,682,26,721,70,391,321,887,682,788,355,20,175,411,985,692,750,280,332,679,641,933,804,227,637,427,837,172,819,477,924,888,978,557,927,480,277,310,290,709,710,863,392,247,384,581,767,147,74,6,250,90,616,889,738,205,183,75,565,376,884,162,262,600,347,489,271,429,762,895,950,145,339,717,18,753,852,410,303,346,96,766,627,781,794,151,57,726,113,34,484,892,110,929,343,411,122,306,981,545,644,192,614,459,689,33,562,975,571,265,298,908,822,769,360,414,451,760,755,873,863,878,248,494,385,439,44,419,907,45,724,29,245,677,604,443,800,951,709,317,440,960,989,763,201,33,975,990,521,49,875,335,571,244,808,137,984,260,155,415,35,144,244,679,191,987,564,713,405,361,335,518,845,867,902,63,688,339,110,509,913,350,818,2,731,421,330,401,559,756,331,352,737,378,143,477,799,476,574,512,925,11,424,775,498,218,146,75,371,406,499,311,447,197,99,44,163,267,151,695,327,950,874,71,586,320,30,70,808,465,334,505,960,797,195,976,939,536,840,968,111,359,160,791,482,483,472,848,293,23,446,809,158,702,881,825,109,227,362,394,425,769,692,780,498,143,535,15,824,387,76,646,157,942,62,313,531,454,586,116,938,739,673,355,54,40,659,349,468,55,113,463,48,736,660,235,449,359,788,136,551,203,790,485,160,234,813,818,480,104,569,316,917,204,978,10,476,122,927,58,586,609,167,778,603,785,536,531,940,433,693,761,961,611,865,706,967,729,568,164,138,828,596,777,573,332,753,734,84,266,324,975,261,336,965,330,29,592,497,699,629,450,569,846,526,373,547,710,586,839,703,969,899,228,746,22,522,806,995,311,750,24,669,498,201,132,547,33,601,741,700,823,898,566,901,221,327,583,723,377,882,112,853,87,426,882,242,752,450,513,784,296,987,764,440,205,963,303,800,630,471,563,328,25,102,563,289,919,513,608,635,442,771,735,882,82,885,896,248,248,350,405,907,372,916,71,287,737,924,995,767,887,823,439,358,308,899,625,840,344,294,832,896,109,549,4,224,328,374,173,923,372,474,156,6,998,120,712,387,67,425,146,558,787,40,225,777,932,636,879,706,679,530,46,78,817,518,624,331,767,825,86,951,765,382,863,876,203,331,433,711,103,145,496,612,205,311,182,66,367,678,287,25,605,576,543,698,399,418,977,284,146,239,336,76,644,751,535,382,342,365,840,212,452,929,7,896,475,201,790,995,581,849,874,966,151,384,882,712,681,777,661,512,200,972,62,478,58,728,680,503,172,457,408,227,143,915,379,966,132,113,683,563,782,841,278,371,655,756,538,736,133,656,954,890,335,114,309,865,852,10,698,278,930,534,883,149,534,230,456,951,39,176,338,260,301,760,527,64,173,286,631,760,873,178,470,197,531,285,515,107,370,962,845,561,832,363,766,150,419,790,185,227,101,556,497,717,434,21,413,344,8,153,936,10,428,402,220,81,570,999,499,765,519,935,64,320,417,676,83,772,785,910,611,727,255,901,606,177,39,792,234,353,724,592,329,111,94,371,85,903,526,478,284,864,96,298,560,200,382,901,935,152,503,897,867,479,600,768,213,452,185,397,166,32,423,304,487,931,102,521,586,910,802,426,134,10,798,415,35,809,179,733,342,17,304,980,584,979,993,143,797,763,680,923,161,574,102,283,196,212,755,724,145,349,405,268,930,848,25,962,220,547,412,948,515,445,672,511,374,817,220,554,107,474,435,301,771,5,275,226,721,466,25,175,759,810,857,662,852,117,489,765,520,285,6,911,0,769,412,787,702,242,841,264,730,680,16,962,793,954,729,276,385,487,284,323,423,687", + "224,24,436,219,576,67,256,493,202,54,642,562,479,441,902,139,742,303,377,933,229,971,931,330,684,548,562,181,750,487,463,772,944,157,66,162,995,790,920,367,433,707,197,674,715,332,493,21,522,611,321,941,918,748,394,83,860,923,220,951,881,7,386,491,213,347,563,624,275,347,811,366,681,328,389,671,253,269,350,600,675,337,582,780,510,287,800,442,285,391,90,124,797,760,439,883,943,177,778,900,444,273,211,361,673,295,817,767,418,439,138,4,551,708,243,158,101,70,299,293,133,173,360,335,565,602,155,994,288,912,879,363,122,284,992,98,888,457,372,487,389,513,919,542,540,538,587,789,161,156,605,39,650,490,107,955,963,14,318,543,31,975,742,891,706,460,729,638,443,453,908,273,346,509,658,73,710,781,284,692,767,548,748,836,984,517,399,230,561,367,917,667,588,682,397,531,157,407,206,636,469,252,514,334,905,823,339,924,837,290,750,261,140,323,139,775,609,196,505,798,626,484,643,984,305,423,583,434,865,389,113,135,359,680,10,512,370,553,108,126,104,671,197,529,193,267,5,207,712,476,866,214,767,627,793,577,886,579,446,685,179,22,751,295,498,424,19,941,350,407,666,31,772,760,240,973,181,560,359,502,375,862,305,778,550,150,116,21,912,522,989,639,110,395,691,431,740,317,271,879,761,311,741,248,379,96,803,75,689,332,987,146,540,649,991,766,544,254,341,272,922,895,580,342,81,784,917,377,565,782,532,286,53,685,927,421,354,380,540,995,661,63,398,742,913,3,762,642,746,306,265,856,352,251,576,35,49,728,302,531,740,588,970,280,198,647,75,516,679,311,916,659,686,337,318,855,338,282,5,806,931,468,85,551,576,364,700,856,307,459,419,729,391,624,950,764,511,526,80,134,918,689,423,649,658,604,179,449,526,748,312,471,210,1000,121,553,50,382,356,102,935,777,956,416,884,108,271,498,245,242,360,343,347,678,520,601,266,408,60,511,177,438,187,453,9,879,286,204,504,230,495,453,615,660,677,605,710,458,755,830,690,289,978,370,383,584,919,766,312,408,744,678,857,955,583,352,949,695,310,540,770,657,900,34,691,328,291,511,759,598,558,502,650,826,780,789,538,280,79,442,59,556,254,909,350,728,985,283,953,272,246,57,908,537,707,368,77,714,562,128,58,636,788,234,16,938,681,909,581,584,67,611,157,866,683,449,188,748,679,691,852,225,884,704,306,507,686,459,405,654,871,480,911,605,30,62,496,433,744,698,172,536,255,633,354,44,507,224,102,261,564,712,957,755,659,274,311,586,565,553,172,982,257,81,281,487,870,343,282,362,253,417,546,287,805,801,356,735,545,76,674,898,793,69,838,87,903,174,192,826,569,296,731,216,3,477,512,601,578,634,600,24,189,918,935,782,567,450,828,454,808,744,326,59,915,69,454,886,227,531,758,440,202,84,545,754,329,817,731,429,691,102,930,844,965,789,259,654,781,426,347,979,864,177,986,348,57,244,68,884,858,693,822,29,302,945,292,579,827,848,162,436,877,798,452,437,345,107,986,488,602,135,213,137,303,6,896,248,255,165,566,498,514,302,283,809,923,693,356,161,488,531,86,42,806,532,968,37,951,258,252,755,739,636,138,622,531,417,548,746,918,973,165,488,51,821,316,764,828,874,739,564,343,288,498,446,910,870,709,394,51,388,142,770,235,995,682,434,401,251,486,167,267,198,777,848,842,929,78,310,299,32,916,217,311,287,558,263,633,645,411,696,717,868,400,785,21,38,829,525,327,713,109,645,220,960,234,189,206,419,840,752,713,521,492,66,511,955,24,817,866,619,55,721,39,647,784,236,912,460,786,460,509,875,991,48,182,42,296,412,255,651,706,486,157,985,697,203,999,910,179,745,361,266,727,635,801,853,978,715,379,316,225,427,940,948,2,715,230,830,393,850,143,922,579,189,140,865,847,315,602,505,224,567,453,400,761,205,45,711,812,225,167,787,277,513,945,999,825,183,180,901,404,584,695,565,959,585,934,811,708,465,516,528,167,639,354,193,606,873,540,325,757,282,770,304,910,304,733,899,827,240,701,766,447,961,357,339,106,902,816,900,962,637,513,110,15,745,968,856,35,897,292,617,25,906,123,787,817,302,315,909,13,191,364,419,631,113,71,216,35,256,455,282,314,704,497,511,16,930,311,65,541,736,687,632,827,470,769,0,223,369,910,291,27,397,546,751,443,894,755,207,720,686,418,513,167,391,41,526", + "956,534,14,78,113,423,629,191,326,808,60,654,753,314,950,221,465,668,319,838,568,693,572,478,39,872,566,5,297,667,641,16,571,260,639,989,976,493,516,260,769,451,636,374,72,649,244,820,152,629,45,339,941,905,700,59,992,325,116,154,536,435,111,863,17,344,686,745,400,83,398,323,22,491,506,719,440,227,54,965,878,914,939,722,397,932,943,203,322,124,436,68,926,881,266,22,914,125,246,967,820,188,914,386,939,588,352,541,23,457,346,286,900,622,154,883,329,189,709,125,417,430,519,133,673,195,501,304,202,408,23,414,710,449,840,212,687,120,396,513,706,25,519,965,997,250,609,631,13,10,235,438,214,886,776,604,930,869,45,80,592,180,685,533,872,606,643,263,634,777,142,685,650,753,419,423,966,413,86,668,872,601,653,131,113,161,393,187,802,970,546,679,151,193,351,804,148,551,940,712,919,429,161,560,541,663,549,436,389,458,87,988,472,292,175,984,119,587,986,922,642,971,123,350,807,22,424,112,88,708,358,394,62,686,95,402,420,576,974,241,348,43,524,173,232,841,471,2,815,89,306,142,906,155,361,29,416,783,502,129,337,917,91,185,14,452,903,5,686,930,940,993,939,438,941,901,806,512,309,241,674,859,994,320,550,820,615,125,89,671,338,356,953,785,516,720,566,295,874,96,663,735,462,249,677,494,66,688,510,594,421,307,312,41,605,46,330,757,707,294,686,397,601,827,539,955,798,792,641,1000,785,869,764,579,452,237,622,230,302,182,381,616,459,477,616,843,3,835,607,206,230,818,359,899,672,568,904,482,607,389,827,587,383,609,788,781,188,897,364,471,631,453,370,749,562,245,820,435,990,413,129,201,869,815,851,688,498,356,677,802,489,414,762,316,653,262,967,253,37,956,386,618,167,492,650,428,230,281,949,667,985,536,164,964,530,414,743,143,795,835,7,159,405,533,308,821,464,553,509,420,611,937,649,990,916,586,296,894,39,297,329,856,678,659,965,167,923,37,399,675,767,876,475,251,106,700,43,177,620,385,742,388,662,749,543,680,201,161,387,987,67,495,914,540,993,749,63,219,512,860,748,516,486,312,382,524,345,60,721,249,561,778,610,320,706,51,807,684,324,214,88,225,505,28,787,433,225,384,558,325,487,83,989,14,312,213,482,503,883,219,428,204,350,226,561,553,92,833,629,629,718,837,927,529,821,242,64,932,277,633,170,245,70,703,411,275,317,635,982,574,669,22,296,192,36,699,601,390,779,524,725,161,685,926,410,848,973,612,887,230,890,498,803,668,862,613,689,778,392,668,521,802,788,234,116,416,48,893,502,378,94,972,241,326,177,506,542,11,467,919,692,741,901,428,240,913,78,416,10,41,642,92,375,356,220,380,405,291,702,99,587,596,445,966,364,493,355,423,462,721,77,584,808,144,115,202,202,88,219,440,211,618,186,160,581,87,2,812,723,556,353,167,324,901,174,417,542,636,435,392,828,98,27,36,523,572,341,965,280,610,8,24,870,750,134,462,890,432,685,432,301,728,70,722,556,528,725,371,365,464,584,39,407,966,138,444,911,955,521,832,595,246,513,626,671,195,306,937,811,421,536,384,237,1000,773,741,284,91,375,940,981,363,829,2,855,886,45,501,395,865,407,824,17,772,246,313,34,415,516,95,795,713,652,150,20,673,805,320,446,356,154,900,842,123,464,835,574,673,229,398,546,577,704,436,423,355,87,740,495,183,48,988,998,554,139,23,680,827,206,760,787,375,479,617,364,736,864,683,822,838,275,171,661,190,784,724,952,615,584,916,143,66,883,397,104,645,29,450,905,290,203,419,452,112,499,38,140,28,272,156,13,916,796,346,947,772,457,634,835,728,107,676,173,616,451,798,461,755,402,536,813,58,605,68,988,647,920,229,549,522,670,796,923,97,357,984,553,984,279,714,256,837,717,683,915,701,321,784,120,607,934,491,697,545,278,58,934,253,283,589,852,73,201,64,483,752,648,44,239,609,427,125,371,974,66,325,577,291,310,961,926,517,992,40,23,182,474,829,667,763,369,555,81,915,930,993,981,50,432,895,975,761,221,513,634,944,637,725,268,223,743,501,536,808,201,379,726,137,239,431,413,43,591,876,475,500,90,277,948,313,221,827,63,43,408,822,16,274,117,982,644,681,450,943,629,765,348,954,126,107,465,878,616,900,692,158,571,921,412,223,0,11,106,319,863,161,775,405,781,283,333,210,917,515,426,643,518,150,101,714", + "237,892,529,229,56,220,151,806,726,306,578,736,19,698,568,825,941,47,296,562,412,16,647,889,730,400,798,833,154,842,642,922,703,232,242,851,190,261,553,903,527,754,537,308,43,514,743,944,7,954,600,624,766,112,630,435,293,874,2,121,930,148,92,925,522,106,781,921,390,569,218,150,782,450,167,214,29,28,415,666,368,747,500,516,850,407,28,731,496,599,712,45,81,861,317,770,654,941,821,283,415,257,45,621,433,622,309,217,376,104,684,560,772,414,250,10,129,14,559,237,251,336,683,381,796,966,530,11,866,187,603,307,608,13,941,153,600,458,742,806,881,102,603,183,622,832,32,346,906,705,687,673,996,292,715,227,793,636,562,481,376,976,138,430,143,737,657,715,484,30,695,241,523,460,888,23,631,166,903,248,226,883,874,783,818,792,867,751,573,478,246,97,698,159,704,652,445,57,209,760,162,329,525,270,540,788,597,794,949,444,997,875,532,554,440,580,700,558,683,13,312,369,49,86,64,825,555,368,867,534,827,173,342,581,385,571,981,500,148,544,277,230,560,513,669,433,834,32,430,532,465,354,714,238,365,435,734,139,175,343,138,566,169,382,719,820,21,277,924,103,269,789,856,971,46,511,405,430,534,657,719,847,773,946,335,867,673,521,601,96,742,84,176,875,951,894,861,423,631,205,675,123,484,66,272,770,634,62,42,600,766,997,460,792,470,774,108,517,710,336,893,419,833,146,930,39,15,438,805,492,207,245,881,384,308,724,794,151,522,840,257,27,102,118,478,532,306,438,908,39,815,271,538,542,423,729,768,699,838,699,750,68,661,129,228,162,338,279,482,699,133,695,796,955,202,877,435,23,246,241,988,615,348,624,157,605,947,874,711,200,960,699,640,496,879,88,900,829,25,347,495,138,132,986,784,989,447,99,437,248,681,798,118,705,67,515,659,55,469,668,652,170,304,621,476,457,773,150,363,419,750,62,111,234,175,41,265,204,762,658,517,894,273,242,647,279,451,28,977,510,569,143,513,769,912,53,61,175,890,72,897,341,586,657,106,563,507,392,11,266,284,390,517,422,341,640,715,615,987,568,214,678,558,739,596,525,650,882,655,546,314,807,367,135,946,422,550,937,382,818,320,303,479,254,325,475,801,276,900,812,104,238,212,864,650,106,232,938,410,161,96,951,36,439,453,955,248,609,77,128,332,892,330,934,541,224,485,683,397,736,113,816,608,627,884,326,180,532,860,231,879,259,483,612,932,984,86,398,872,409,865,55,811,692,438,292,824,181,302,726,306,991,130,365,866,373,534,190,284,547,555,529,798,141,95,513,744,816,700,818,186,84,313,596,394,108,707,712,996,652,611,656,26,439,339,889,671,427,921,524,936,483,270,575,975,960,37,217,407,370,876,257,423,624,656,472,701,755,601,522,191,278,747,812,596,323,484,560,95,348,693,353,697,37,403,108,745,268,69,539,300,978,255,886,326,77,8,876,998,704,229,749,417,625,369,925,528,522,435,726,324,116,260,77,489,316,277,638,844,952,774,784,26,880,172,429,892,167,465,273,912,996,851,605,721,662,322,225,733,879,108,760,148,608,713,238,540,514,930,110,488,441,893,653,444,561,993,223,878,348,73,940,331,155,566,226,655,996,559,787,734,151,832,588,33,239,395,155,626,117,709,446,31,759,632,192,62,849,512,365,738,262,132,535,600,81,27,742,946,165,484,819,664,264,631,76,391,241,656,321,82,415,67,169,205,728,152,28,110,665,78,298,846,776,945,164,533,727,241,343,502,89,554,604,81,316,474,277,231,924,789,521,460,661,846,422,961,290,81,939,6,869,803,989,250,372,459,868,522,911,79,111,616,317,193,200,690,719,302,777,102,349,822,423,432,327,534,264,90,31,494,951,580,209,526,60,953,204,1000,988,43,326,301,83,296,361,991,478,711,327,542,864,312,480,454,865,366,321,784,342,792,138,121,472,423,945,353,197,826,387,226,501,491,988,938,103,260,553,252,92,89,146,340,282,752,862,181,330,452,198,746,946,257,295,381,536,928,757,341,660,374,202,787,839,341,842,476,977,950,174,372,564,886,638,153,508,197,283,759,565,200,267,425,451,718,646,234,227,949,579,3,1,797,351,624,306,979,539,843,322,465,136,484,945,396,889,376,266,880,718,605,60,287,718,866,556,53,267,201,420,738,344,425,501,122,224,193,855,787,369,11,0,670,759,75,864,741,907,611,700,991,537,68,769,174,659,974,422,769,853", + "86,626,762,348,15,485,36,119,45,550,705,739,248,339,105,104,522,770,830,506,449,745,779,900,563,699,31,995,374,431,591,851,630,952,640,474,777,774,916,317,819,634,653,253,65,424,888,498,779,332,916,115,117,612,313,407,593,938,54,508,317,899,521,985,473,57,224,762,980,547,250,676,57,939,281,752,320,361,417,17,66,725,614,560,934,906,88,767,192,364,347,626,692,28,317,867,961,946,773,941,821,952,255,155,53,129,322,21,304,554,458,784,381,412,702,703,327,750,109,253,951,485,586,168,329,257,722,72,86,638,111,644,72,235,58,40,303,40,527,81,974,85,154,893,448,541,503,976,549,76,882,379,68,224,798,687,46,158,250,335,459,244,686,656,770,435,39,953,733,106,427,186,802,337,202,370,706,408,695,184,798,61,695,901,665,666,596,144,274,787,593,724,11,566,704,954,257,826,581,396,31,574,427,656,959,389,580,875,307,658,831,307,309,604,317,609,613,388,161,392,295,114,938,601,948,728,679,960,696,7,398,710,406,847,488,676,582,312,832,337,632,341,84,448,954,811,872,581,689,664,913,263,981,528,365,912,599,460,191,580,344,395,834,317,292,402,984,448,712,313,239,33,408,44,161,500,330,335,530,517,309,419,827,433,838,761,723,276,501,932,579,432,919,686,806,407,483,197,816,403,862,326,279,91,627,894,589,611,893,838,766,905,444,243,736,115,669,578,5,466,894,497,655,92,983,767,867,202,951,963,180,994,409,105,871,774,60,119,584,114,202,320,862,963,943,532,591,977,384,489,778,666,838,632,156,579,586,876,152,513,855,443,525,989,705,782,23,700,880,856,698,506,806,279,347,696,655,29,723,115,715,139,450,441,756,600,849,827,331,968,561,965,35,590,809,140,636,473,897,645,809,339,671,798,321,987,436,898,930,601,348,506,614,884,231,55,807,782,887,366,849,318,598,772,16,443,495,782,673,849,520,128,433,572,532,955,584,676,101,945,334,825,306,808,986,971,75,661,421,926,655,465,111,613,535,124,114,984,6,993,677,958,250,506,710,307,401,45,828,355,352,452,830,57,306,669,626,201,17,594,201,70,533,404,672,564,855,469,696,940,148,552,884,563,128,23,405,439,887,415,310,409,142,947,439,432,95,387,651,784,554,486,507,700,325,671,995,232,801,188,430,419,522,907,575,495,194,180,201,68,4,217,876,161,153,279,876,701,314,475,830,865,259,249,483,295,494,45,383,437,295,134,921,929,562,52,642,721,674,931,371,454,779,135,160,722,765,818,517,647,469,785,940,533,692,799,839,419,818,239,619,876,2,751,646,959,962,823,336,991,801,422,208,565,173,368,218,673,128,468,176,382,52,893,344,864,135,470,97,499,903,534,927,782,11,350,886,284,98,680,500,215,954,651,432,737,207,508,909,374,664,184,719,351,395,894,909,817,854,444,937,652,298,329,942,83,219,2,244,184,731,499,682,73,700,455,891,734,901,960,725,242,428,499,526,29,814,931,730,52,461,230,454,257,83,350,831,311,189,552,286,847,940,652,110,630,856,407,241,974,732,502,860,137,300,775,701,148,628,80,701,280,501,266,174,154,400,871,207,662,749,572,811,296,723,625,67,249,846,51,264,650,998,473,783,727,850,7,381,162,259,967,381,326,306,515,329,986,343,160,173,846,729,40,54,835,862,104,655,182,485,881,415,368,202,794,786,853,965,674,4,630,182,436,847,624,642,66,320,650,263,957,416,734,553,750,490,956,128,963,187,207,781,863,857,310,495,261,410,888,685,549,48,769,138,737,686,599,985,936,583,238,541,760,236,668,867,226,660,503,249,992,187,719,205,722,357,755,875,864,411,567,418,362,400,144,585,896,415,433,564,543,137,244,945,315,714,580,563,280,782,349,70,222,450,727,187,797,130,365,677,980,637,122,373,847,288,658,871,825,831,461,51,510,189,218,733,929,676,680,322,134,809,965,154,994,865,84,999,751,810,650,249,115,686,619,123,257,681,483,97,673,437,923,534,383,777,287,716,191,706,942,428,861,845,310,70,842,271,219,37,879,910,834,371,48,346,158,257,416,599,563,802,884,543,331,830,254,962,573,999,578,379,596,926,596,523,606,421,522,249,478,410,879,471,178,883,675,89,40,947,66,999,204,825,320,929,528,388,254,260,550,947,922,60,903,722,886,153,815,617,503,117,466,205,57,787,377,702,910,106,670,0,488,663,747,484,747,709,270,733,486,232,71,668,858,141,230,29,365", + "648,618,746,141,400,699,31,118,190,691,41,978,616,19,707,518,417,83,846,802,525,623,564,231,97,948,373,657,558,552,980,405,802,60,844,304,264,830,379,302,727,224,361,974,399,719,469,370,96,602,199,899,635,957,336,229,435,876,465,769,579,795,615,83,770,16,901,168,118,372,250,896,922,729,959,916,731,387,823,341,27,272,884,829,3,351,638,395,182,641,857,370,800,110,633,307,859,730,129,943,929,308,335,633,546,568,773,436,192,974,756,349,594,381,275,325,725,229,881,905,24,443,929,297,104,16,598,963,585,531,444,491,156,999,317,282,195,456,808,66,803,906,155,141,758,59,353,925,476,729,103,669,296,119,850,889,679,747,539,292,563,534,614,388,567,492,833,432,338,929,134,408,894,385,746,741,325,269,217,561,477,924,561,49,327,236,510,707,834,195,409,480,368,329,723,773,161,662,674,290,997,194,174,914,45,954,700,889,674,25,400,730,615,871,445,825,80,91,99,754,589,274,77,489,640,887,659,504,369,686,474,900,312,389,687,31,973,47,55,803,477,185,394,433,940,739,465,431,623,637,364,974,581,414,164,193,67,893,963,359,417,690,422,744,819,696,232,431,499,9,350,830,665,700,687,774,775,932,829,210,917,952,348,816,221,422,889,678,603,921,801,556,53,81,218,561,719,481,161,249,39,683,189,53,201,934,555,847,491,699,887,536,28,430,862,277,977,914,586,760,116,206,886,65,408,412,261,917,173,458,954,773,15,935,943,901,683,498,251,821,444,354,350,179,276,205,473,370,30,334,889,462,101,619,295,877,665,92,599,585,183,61,44,168,477,893,806,569,68,319,585,439,77,223,661,988,789,680,719,812,607,424,703,639,49,199,87,332,470,509,980,90,15,274,289,628,318,655,173,642,766,271,81,231,548,148,405,79,96,84,380,460,774,384,392,203,426,321,158,228,761,372,219,761,139,959,580,256,496,863,181,245,392,180,774,689,947,476,143,627,713,853,786,763,851,55,154,226,78,483,69,508,553,298,825,318,852,709,486,324,160,865,419,583,20,616,483,384,194,106,321,967,860,625,73,796,721,295,255,216,684,638,201,652,428,53,118,670,162,779,477,364,674,989,461,615,4,647,391,31,653,841,827,605,462,557,203,142,310,797,445,315,232,479,831,406,591,132,194,390,691,97,689,903,184,384,604,272,744,530,327,677,350,816,45,626,866,301,738,895,407,150,84,694,426,592,478,590,395,167,722,909,62,134,286,867,46,74,178,650,449,148,827,867,642,985,470,633,245,124,333,439,636,672,936,947,306,419,512,198,659,321,112,337,387,915,323,118,141,955,415,155,681,791,667,711,502,528,708,764,169,199,793,575,401,476,857,223,693,112,549,465,942,473,505,165,131,469,265,387,288,530,317,281,124,600,983,896,247,466,323,377,931,512,109,904,484,547,319,341,905,833,828,641,737,142,232,641,563,941,775,789,997,822,897,670,284,837,43,514,896,769,553,895,476,856,48,329,692,957,351,139,912,385,180,347,268,585,482,17,69,649,913,330,747,746,593,361,892,776,316,510,639,198,935,90,570,263,338,736,387,302,529,664,844,358,797,941,796,747,14,520,329,163,889,209,813,883,753,756,643,177,540,904,903,867,765,364,81,884,511,701,210,894,993,596,954,954,84,31,389,661,41,825,206,814,220,118,956,127,370,209,881,864,181,238,242,539,341,382,245,686,756,766,475,900,862,495,144,964,6,586,178,298,363,627,589,59,105,518,670,924,46,467,781,866,424,262,19,865,372,43,69,287,296,741,970,527,75,719,156,147,793,451,806,957,454,281,612,808,506,306,681,974,150,758,252,282,196,408,473,60,515,271,76,63,823,339,733,455,377,935,252,835,919,850,851,115,241,51,928,622,425,554,741,279,898,986,499,917,336,936,457,679,105,773,726,663,161,524,602,574,340,660,916,304,814,719,970,335,26,254,424,413,206,768,692,905,691,351,966,43,286,756,375,228,660,827,973,667,229,841,470,303,638,513,443,833,630,127,373,641,187,19,729,686,317,409,566,793,410,772,905,411,864,474,901,697,669,737,263,176,764,201,457,283,897,903,423,561,937,680,979,785,872,933,856,389,236,646,398,12,27,985,529,232,985,179,940,91,961,610,458,76,673,388,566,951,278,884,638,258,421,270,120,475,313,686,206,696,475,200,472,389,766,817,277,289,242,291,319,759,488,0,914,623,107,709,539,283,723,509,416,629,760,565,360,936,719,181", + "448,59,944,223,212,427,529,591,658,122,560,526,758,152,976,534,298,697,53,515,904,62,303,136,218,917,325,845,206,601,922,502,539,612,382,986,655,60,334,318,826,302,796,56,404,447,988,192,191,139,838,179,686,469,154,9,603,981,842,97,250,644,530,64,803,670,570,605,122,881,32,948,69,255,325,808,707,643,135,608,926,141,716,559,922,376,532,680,64,269,370,546,196,922,284,801,436,380,772,125,139,265,361,566,454,14,104,835,475,127,266,2,685,637,2,487,135,540,849,281,216,252,662,915,849,797,424,609,7,31,509,850,965,927,464,539,622,94,62,744,91,421,619,773,870,992,768,25,841,559,219,977,892,475,973,745,790,140,762,560,700,558,613,739,387,810,850,420,882,526,193,387,900,816,318,959,297,205,380,759,519,646,2,182,268,229,289,191,571,579,293,898,946,913,741,298,436,669,14,838,882,304,966,19,688,289,636,413,581,256,939,93,555,933,598,898,922,535,70,117,51,258,154,193,424,957,128,605,12,739,277,518,737,757,156,643,723,224,410,919,854,558,169,754,814,803,185,92,478,769,461,805,340,102,246,780,700,987,785,22,526,365,121,168,295,991,974,119,602,584,704,351,127,418,215,600,433,801,965,326,340,661,697,869,414,544,418,644,311,912,684,662,732,672,977,514,71,269,875,62,949,845,673,664,903,766,122,425,675,248,943,168,173,172,621,384,410,739,614,925,841,197,118,847,363,706,632,434,566,494,853,353,191,699,775,12,180,646,519,989,142,623,256,557,351,831,942,203,694,228,947,216,276,655,615,625,141,976,808,81,329,122,517,833,947,813,509,811,820,641,131,161,482,291,411,196,703,88,107,167,194,375,788,645,369,642,478,677,856,804,82,570,942,730,844,364,989,746,365,594,795,43,700,750,464,742,302,835,425,435,29,664,505,453,399,27,983,939,335,276,617,44,506,151,47,22,29,490,44,807,807,156,277,363,126,882,199,122,499,487,371,725,723,588,262,725,956,437,171,516,884,18,248,786,171,919,493,755,783,156,106,262,756,334,834,513,768,365,597,330,569,729,952,167,272,552,599,182,145,733,518,67,931,766,379,231,419,938,715,581,624,222,792,356,793,684,423,192,162,214,436,395,180,292,596,371,604,715,436,628,250,859,76,153,179,341,596,417,146,486,11,265,687,363,98,200,55,699,483,843,771,114,204,532,577,805,112,156,726,115,670,742,924,769,236,905,421,143,365,104,570,147,764,288,650,390,982,52,83,210,98,139,988,215,575,491,61,52,552,278,408,162,189,484,899,702,178,306,56,60,284,384,931,68,559,785,587,835,683,328,917,519,515,51,836,594,32,777,515,398,646,871,80,604,191,908,302,459,201,968,134,750,887,767,25,397,333,289,965,598,360,441,718,151,159,884,633,388,357,56,902,842,160,675,293,922,707,418,798,676,414,378,755,810,669,648,666,671,421,657,243,248,796,700,474,192,894,888,765,858,183,582,688,236,971,624,178,867,165,836,406,712,572,963,70,23,248,883,499,666,52,55,110,46,136,842,619,896,854,791,243,476,879,975,112,349,259,74,81,625,44,817,811,69,638,667,707,461,635,440,999,953,427,52,265,350,578,461,222,53,580,957,954,223,784,379,502,700,245,376,458,580,214,789,458,710,473,708,351,951,998,847,471,179,690,692,100,392,247,185,728,88,762,35,375,725,139,674,913,911,457,342,149,234,331,132,919,887,405,241,624,347,41,708,369,494,972,985,35,279,204,835,579,321,113,712,519,437,516,691,486,871,68,810,536,370,223,993,512,198,134,123,176,995,994,134,332,790,476,817,534,134,553,693,605,973,572,166,123,678,879,406,377,316,842,584,832,372,773,257,445,435,110,827,748,358,929,944,119,51,374,771,458,357,742,4,265,281,710,171,692,97,429,260,685,571,649,292,739,109,199,748,578,781,739,921,317,138,472,432,496,987,366,175,491,297,215,457,154,904,324,495,991,467,412,991,522,50,673,855,392,900,922,733,683,722,762,857,997,638,301,318,906,906,563,298,639,204,994,151,631,952,908,238,518,777,8,458,543,874,267,600,257,998,766,486,357,541,200,699,484,500,123,575,890,941,218,766,230,830,576,603,884,283,779,440,883,453,718,695,264,146,943,704,375,179,813,835,849,214,156,65,10,557,515,875,393,722,194,264,140,409,892,754,22,97,368,834,841,27,863,75,663,914,0,142,471,503,811,68,429,989,129,61,750,648,97,39,57,929", + "10,640,873,37,935,752,864,153,609,143,54,481,112,925,93,59,714,787,514,512,313,357,10,995,512,61,492,565,425,768,764,940,529,590,898,525,748,787,157,912,754,356,225,568,226,257,976,352,695,566,964,894,460,613,119,426,655,268,240,795,923,755,961,279,376,204,316,64,473,36,148,250,821,381,412,393,545,638,696,927,973,477,77,608,952,89,761,774,673,443,751,560,815,631,295,503,917,190,576,860,158,876,669,229,693,89,274,816,751,381,141,946,60,418,820,343,272,605,351,93,735,177,252,135,579,299,159,633,16,768,867,149,656,145,6,894,588,679,324,78,487,813,153,276,120,936,909,820,509,31,770,125,556,450,480,239,832,811,437,301,772,464,420,614,669,772,528,952,880,301,24,915,191,900,40,278,684,165,65,314,694,982,95,676,684,644,986,972,267,525,465,347,191,605,431,546,459,133,863,256,341,240,6,862,556,466,13,919,285,235,685,326,149,7,9,900,298,351,801,726,720,590,288,198,174,246,704,740,681,4,435,937,95,333,760,59,613,495,864,797,869,433,158,16,343,486,376,514,844,526,190,633,475,293,436,281,949,243,198,556,89,917,949,271,239,680,323,903,788,963,418,439,872,132,411,42,989,856,307,334,410,378,327,247,759,769,131,999,139,61,353,431,406,890,153,357,682,437,297,337,38,769,865,418,735,97,659,24,861,932,510,681,518,246,45,678,435,824,6,235,29,264,145,496,707,112,766,484,491,435,829,812,836,311,855,197,673,992,244,620,961,853,400,306,318,371,58,621,387,466,393,805,866,407,33,764,333,878,494,90,280,234,161,951,224,193,153,618,144,347,680,589,601,848,263,792,7,464,963,181,857,851,573,216,218,729,397,369,165,254,37,691,31,530,573,834,697,697,945,379,548,700,691,801,685,617,447,908,313,851,940,120,328,804,958,452,380,507,187,534,491,852,955,301,616,777,703,211,822,387,572,112,40,373,976,309,979,741,171,669,676,252,801,287,554,268,375,131,498,207,704,690,716,421,707,331,131,327,476,649,733,166,928,889,621,205,897,126,891,114,510,19,997,225,512,445,987,157,898,12,71,934,804,716,155,732,870,632,690,554,171,777,720,14,164,277,105,899,937,845,76,253,675,849,603,688,703,831,238,435,490,583,959,30,275,760,310,187,217,380,466,281,396,56,395,143,379,758,82,420,218,223,163,327,574,39,910,986,596,542,398,29,282,32,503,587,906,824,933,875,865,464,95,627,277,672,834,776,704,787,232,786,766,43,322,276,77,927,780,80,979,778,134,636,296,644,622,448,404,290,598,815,196,621,529,746,786,551,5,142,32,959,215,710,815,88,9,571,557,646,910,820,499,198,737,133,66,787,242,605,663,29,706,246,339,928,513,41,475,386,911,363,318,597,165,752,267,138,972,414,565,574,871,596,452,957,449,990,292,161,872,162,389,362,937,435,65,520,204,891,510,733,750,474,183,347,174,590,23,645,984,628,811,208,226,590,862,155,834,539,866,329,716,675,383,568,225,799,13,502,259,547,988,289,187,359,489,477,767,290,737,244,48,198,210,519,407,70,521,213,322,841,643,162,216,271,953,119,945,343,454,64,380,573,304,537,783,119,348,229,552,113,690,500,961,235,441,579,743,633,656,846,651,264,399,31,109,197,659,323,991,463,456,79,759,711,126,641,344,540,762,753,2,553,317,867,596,908,127,747,228,626,544,299,736,231,635,370,160,973,986,415,346,973,309,704,916,349,402,861,92,515,579,840,794,33,617,357,328,894,36,454,916,974,799,151,772,632,366,338,456,15,764,870,657,333,611,798,632,455,397,492,312,288,213,571,48,276,749,727,374,387,169,397,26,366,599,241,576,326,726,432,656,903,172,159,448,859,885,761,443,45,409,796,68,700,231,819,442,664,459,726,247,119,227,301,615,450,194,833,3,657,163,373,319,151,445,808,428,203,778,643,908,377,476,277,268,289,709,308,250,279,986,653,666,465,620,896,313,23,688,977,570,180,346,673,436,256,556,57,63,974,838,674,776,50,376,400,498,463,94,474,254,365,885,368,531,839,522,114,909,68,877,726,221,478,260,381,20,747,380,711,332,590,422,831,899,424,677,984,768,250,723,133,333,500,223,647,522,560,414,790,617,178,676,705,571,248,501,217,377,368,61,156,955,440,123,671,712,813,902,283,717,564,814,44,261,497,264,397,161,864,747,623,142,0,899,597,609,345,990,957,803,177,97,286,390,316,144,502", + "856,908,838,50,668,873,676,787,912,837,774,88,687,76,172,404,112,46,779,798,219,476,245,668,525,814,30,615,315,332,875,149,313,607,284,211,424,359,847,792,540,205,415,602,342,246,342,388,413,402,298,972,958,770,859,530,705,677,251,583,301,85,748,762,396,235,910,878,129,225,736,84,318,938,404,885,575,77,113,355,110,833,95,189,833,984,79,32,594,323,509,598,884,822,890,523,299,598,768,837,824,33,572,484,733,684,787,755,228,13,348,203,999,246,355,309,440,503,683,448,707,73,282,519,267,379,829,669,155,885,951,43,302,304,928,870,874,349,967,448,779,139,40,826,233,20,920,515,345,415,476,853,317,681,962,381,282,686,210,173,23,583,170,298,547,811,616,257,387,871,274,66,19,329,98,409,512,266,443,678,52,918,612,444,761,165,308,112,886,433,424,877,421,266,173,278,684,402,770,498,931,668,791,979,118,508,256,849,663,907,930,668,479,354,20,541,27,738,60,884,514,177,894,334,740,219,156,834,261,615,673,39,994,737,597,911,77,797,628,861,653,597,935,627,530,531,427,569,736,366,413,738,946,83,101,257,737,553,804,585,6,338,526,979,704,700,487,134,715,163,329,913,11,962,681,57,561,986,87,396,201,475,899,709,911,884,526,186,232,278,441,230,876,517,417,348,80,989,740,193,871,911,170,523,736,718,327,973,227,217,423,961,553,278,449,734,102,140,846,812,830,141,114,440,236,922,420,284,540,765,484,726,894,82,339,109,891,982,973,414,826,163,616,849,212,966,188,347,576,533,296,747,393,879,89,450,148,931,297,337,201,28,646,113,727,866,568,154,503,530,613,556,769,386,302,593,195,658,102,507,214,646,968,791,442,212,853,674,633,889,330,618,116,264,989,90,483,427,786,318,644,784,580,248,223,677,735,627,557,170,838,263,207,738,978,700,985,817,377,447,787,555,345,133,146,463,945,757,434,899,125,833,406,598,539,503,776,904,55,226,891,100,306,317,678,136,799,874,468,510,783,395,131,29,217,347,759,886,578,938,920,483,555,949,180,470,485,312,430,298,674,665,370,611,537,638,223,953,721,745,313,407,652,624,450,445,897,825,492,886,814,638,878,2,951,697,330,356,546,133,899,398,672,2,836,167,135,361,499,636,59,937,163,224,973,107,228,3,550,560,355,339,357,777,461,632,424,75,239,154,763,994,283,123,271,844,222,946,710,859,526,419,398,259,876,985,412,86,350,285,225,678,512,918,460,818,437,922,838,137,187,410,156,721,490,950,772,163,826,206,88,199,74,316,799,307,8,666,465,938,978,766,409,6,620,394,313,99,928,751,151,733,242,965,766,658,38,868,767,382,633,280,37,458,446,896,338,457,749,291,591,993,209,611,629,614,901,73,128,859,603,651,13,182,711,314,672,821,123,287,324,719,500,986,917,439,3,728,968,895,466,558,139,559,678,630,26,252,991,724,791,675,514,338,919,771,810,496,416,400,516,532,517,170,682,988,506,828,864,857,567,475,991,266,900,275,302,337,26,233,341,854,851,746,244,980,162,403,897,308,413,326,905,915,499,595,490,883,542,277,307,401,259,542,392,888,711,659,69,697,30,425,496,805,201,979,709,47,886,397,381,648,606,48,562,800,760,839,751,823,300,42,450,721,930,244,426,570,219,269,236,191,363,787,209,21,155,122,178,880,131,346,398,626,693,488,918,742,94,136,688,797,539,531,533,314,27,390,485,403,486,141,408,632,674,645,505,790,473,316,305,731,59,190,118,467,201,717,983,616,289,726,917,404,881,988,926,960,67,742,690,467,695,677,467,588,508,793,887,751,329,784,236,38,456,677,613,102,773,741,508,30,370,254,759,260,718,997,284,306,955,171,637,636,377,966,57,124,734,991,672,64,488,832,446,462,974,330,48,546,67,597,138,611,786,826,721,125,60,600,323,588,278,567,560,854,607,272,569,183,480,109,82,186,520,377,761,780,615,470,785,819,279,505,610,199,365,400,295,865,26,262,658,125,201,518,316,129,91,745,954,622,48,751,890,925,402,400,917,16,811,201,682,701,344,162,81,966,412,663,251,704,533,362,958,200,709,500,996,427,202,551,102,80,199,144,347,14,239,600,633,867,949,285,712,227,344,469,987,57,452,21,384,963,589,410,748,17,614,751,798,628,436,676,738,996,904,68,714,864,950,320,464,326,60,130,563,650,730,546,775,741,484,107,471,899,0,904,128,454,911,169,787,433,506,779,37,169,778,235", + "196,996,795,312,332,174,620,944,157,306,940,493,903,681,471,795,508,735,353,349,650,133,904,843,915,222,338,398,817,27,968,252,635,646,968,353,83,121,783,338,50,159,27,79,146,252,508,78,562,164,784,122,237,972,628,51,541,83,866,799,296,2,826,551,559,654,753,523,214,173,887,158,765,939,267,341,532,770,223,583,193,505,623,920,903,657,873,253,319,787,51,426,522,424,722,830,117,337,701,263,873,793,287,735,236,321,782,485,434,440,154,239,772,502,291,500,32,604,585,289,639,365,33,640,232,830,45,884,649,871,635,75,663,414,483,331,676,100,995,837,465,729,305,796,960,641,187,898,549,111,170,250,326,397,90,642,810,912,907,506,497,953,397,624,318,423,461,583,400,676,277,387,414,295,68,844,966,883,133,322,973,87,275,431,619,605,644,147,251,347,344,769,631,787,209,307,536,632,125,239,981,98,542,972,349,879,912,339,620,545,201,102,140,35,779,187,90,522,700,926,860,784,529,455,666,278,987,392,269,401,617,167,669,695,572,275,412,72,217,132,644,981,777,608,603,244,415,232,13,678,296,445,339,629,991,511,10,644,559,989,730,699,356,592,935,219,912,106,590,932,419,696,917,741,123,746,242,31,991,62,613,469,582,532,723,450,735,767,280,511,141,54,895,241,187,589,387,346,428,144,379,845,985,182,816,550,279,858,468,658,935,349,850,835,735,466,110,41,286,18,62,442,772,339,478,621,499,835,56,731,182,405,763,711,626,123,255,730,395,23,248,816,179,953,57,289,315,282,657,8,612,256,541,692,457,172,82,917,640,408,654,554,737,91,724,169,91,771,396,412,996,27,129,128,581,272,714,868,421,969,774,614,96,282,423,309,58,189,879,722,86,336,188,663,831,161,994,780,12,78,708,308,263,225,198,475,56,82,440,682,505,794,102,926,151,806,92,350,431,184,593,918,761,257,514,377,644,35,255,90,824,37,365,715,958,865,387,524,915,663,336,53,461,310,840,600,383,739,384,49,152,879,637,585,521,497,575,212,673,258,463,834,592,328,33,493,849,420,297,731,21,111,891,451,955,280,287,864,355,344,696,3,655,130,30,789,526,655,797,783,679,396,675,253,282,567,983,858,102,678,232,954,521,779,2,859,283,874,603,730,589,667,575,944,12,526,334,499,215,146,568,886,193,674,462,962,460,760,583,298,873,785,472,944,485,875,514,34,630,562,293,147,221,294,57,473,375,629,312,764,473,105,736,364,947,501,603,821,641,576,250,25,235,559,234,859,415,357,633,184,954,311,127,607,576,608,427,458,171,98,957,166,949,711,617,918,312,599,258,492,677,39,297,680,603,880,869,253,843,198,630,445,654,179,259,693,658,10,339,617,739,212,462,123,829,872,845,651,80,774,637,315,591,820,148,379,796,597,622,544,885,310,270,871,543,602,688,471,60,764,200,959,163,136,33,406,746,979,796,912,819,178,117,550,200,228,536,62,404,690,820,798,42,998,389,269,62,540,533,875,646,116,116,903,571,201,358,960,724,958,683,855,423,942,418,677,51,911,726,283,510,8,829,929,292,959,207,608,998,932,567,312,539,356,503,758,901,33,419,157,172,798,666,836,939,53,986,241,171,244,641,410,582,128,855,718,908,791,691,783,438,357,48,485,578,984,312,541,536,581,494,69,389,862,286,529,845,968,291,79,160,17,475,358,947,247,73,12,781,535,16,152,663,958,466,359,465,862,490,446,146,868,935,742,816,978,59,734,756,22,382,781,457,786,340,635,912,817,70,796,817,186,792,275,995,83,275,65,515,728,719,110,100,121,299,745,684,551,106,537,369,426,971,245,952,954,525,295,506,111,577,64,622,634,442,746,549,78,409,587,461,11,625,649,319,392,248,971,261,945,703,748,235,351,38,811,303,163,311,631,184,284,99,734,927,481,625,78,488,821,127,24,434,36,488,784,783,984,804,451,996,644,123,279,195,547,648,674,690,925,615,615,724,795,58,167,738,668,311,135,646,95,505,246,368,6,704,740,111,454,692,225,384,4,389,270,238,436,29,563,36,559,312,970,453,227,287,95,349,714,290,532,41,726,382,284,320,859,871,839,625,123,749,795,516,279,592,540,492,421,896,620,977,84,208,446,891,712,645,446,867,551,995,315,349,420,510,639,827,343,502,459,472,960,859,764,241,664,722,368,772,333,302,200,767,792,178,269,680,751,405,907,747,709,503,597,904,0,718,144,522,929,562,966,848,984,858,268,945,317", + "146,874,296,367,465,771,901,919,875,561,501,422,380,694,11,700,417,558,386,396,157,689,801,366,52,49,519,787,474,563,154,529,315,92,873,128,88,885,198,801,888,665,427,1,191,400,320,165,641,995,714,56,13,265,382,222,242,988,319,502,574,378,171,181,826,296,139,946,268,927,706,756,512,489,239,308,699,708,630,494,129,278,294,949,301,179,298,786,745,868,119,132,888,655,507,527,883,79,739,521,407,625,403,145,219,668,593,660,769,138,151,592,234,238,532,711,893,501,491,973,517,490,55,649,686,906,937,607,107,753,511,695,367,906,297,804,19,605,402,774,560,683,367,116,793,662,792,264,983,826,936,941,701,871,915,167,349,299,417,373,498,296,555,974,632,355,722,936,622,483,88,812,274,40,868,629,177,234,333,15,433,142,669,864,98,841,695,478,158,738,672,200,406,822,679,723,467,300,472,156,858,463,739,929,764,768,365,771,567,820,593,374,954,489,107,291,509,469,76,567,160,618,761,42,607,195,186,495,94,593,524,242,727,134,293,411,166,592,110,682,776,449,89,866,324,353,177,292,277,487,639,178,833,887,266,256,657,416,937,880,472,787,316,751,256,151,874,242,445,854,599,831,634,916,297,72,370,626,845,822,874,444,734,366,287,80,671,557,23,498,100,764,45,984,293,895,279,635,917,458,486,206,183,600,382,125,232,621,962,113,40,838,107,301,680,401,274,206,101,484,323,101,390,270,5,729,674,205,730,760,66,352,891,569,57,330,86,500,938,790,843,420,162,504,36,524,231,937,626,585,440,103,116,852,244,872,2,5,654,71,212,822,706,618,170,960,243,40,413,123,121,745,980,201,264,358,325,485,670,456,253,87,459,546,816,427,383,598,571,951,90,967,525,446,953,624,608,794,499,805,634,6,758,214,805,918,423,488,439,959,668,426,197,954,477,149,480,623,192,110,263,487,6,24,847,104,500,588,665,128,440,710,649,393,541,621,418,184,766,502,981,777,884,792,671,141,729,989,134,624,750,552,694,838,57,340,943,315,598,424,621,47,422,906,376,875,901,333,982,296,531,438,716,795,22,15,285,962,260,508,517,941,792,496,928,994,300,875,166,604,978,184,795,451,417,721,717,316,431,212,58,147,291,492,383,284,727,456,887,939,213,244,506,914,211,119,756,330,569,297,938,23,604,963,408,125,249,193,331,515,137,851,811,69,681,272,285,37,333,18,364,139,414,523,958,686,45,917,621,567,760,319,637,81,712,883,151,241,19,915,446,947,912,414,271,359,595,552,44,403,110,246,871,22,407,818,688,744,207,437,478,818,672,22,641,619,601,730,430,313,802,994,968,737,571,923,569,928,807,959,603,185,156,741,935,70,477,358,483,726,965,13,694,701,730,44,476,90,150,87,21,792,725,982,900,982,182,824,405,592,968,212,193,213,381,780,126,581,305,814,299,354,226,904,839,772,309,128,294,460,382,231,335,489,14,477,722,592,129,236,514,119,193,957,714,268,887,524,587,845,483,439,997,691,256,718,489,85,646,558,3,195,525,889,879,596,50,307,518,980,365,304,855,804,482,886,815,377,974,412,177,438,462,971,500,721,601,740,623,553,365,211,987,634,686,662,904,631,368,998,572,289,986,440,293,770,146,49,964,464,993,822,83,820,988,843,656,883,785,33,716,519,622,327,818,352,244,868,74,700,884,868,99,955,682,499,537,674,428,486,237,292,153,101,271,265,738,846,592,694,220,447,120,29,786,967,891,637,76,602,454,539,875,9,223,33,304,736,588,156,397,348,922,172,770,921,242,947,436,883,816,259,460,320,224,426,933,651,645,480,164,35,252,205,234,130,151,599,875,439,259,560,508,62,809,853,603,327,823,938,462,978,769,270,464,161,29,741,432,676,24,874,851,91,469,130,762,933,11,173,150,911,466,371,376,65,294,269,117,453,408,890,915,902,538,814,244,387,430,343,129,175,662,216,396,421,46,116,640,458,138,808,574,606,549,588,765,370,777,165,115,275,112,500,106,843,1,532,43,947,336,385,184,743,39,184,867,550,268,755,739,325,785,65,398,342,917,955,367,404,408,13,362,746,523,924,194,529,644,827,691,953,418,602,367,522,548,607,166,895,915,531,534,653,740,466,931,126,450,239,650,587,662,527,597,55,851,359,879,129,118,349,230,413,411,954,499,445,493,255,798,185,648,331,478,806,521,254,16,443,781,611,709,539,811,609,128,718,0,304,763,861,915,954,383,375,470,836,512,405", + "484,212,199,307,78,921,788,638,272,793,457,604,224,119,477,100,523,492,707,9,426,824,291,931,172,558,296,288,999,642,768,402,969,752,260,824,690,237,322,523,21,688,97,5,576,820,339,133,722,963,418,12,529,308,539,367,659,484,340,649,979,423,625,998,487,48,65,351,496,483,327,297,959,880,990,43,665,176,48,709,797,963,410,826,83,763,573,974,933,972,7,29,964,381,820,548,969,845,284,993,613,639,528,515,684,732,797,591,14,211,777,757,718,508,425,34,385,340,383,341,251,791,226,129,593,41,957,139,687,345,950,758,865,409,66,63,303,838,441,836,46,250,181,910,213,534,794,325,880,222,341,51,786,304,536,672,896,197,201,692,548,748,789,718,752,272,605,938,588,183,262,510,551,683,30,741,202,742,87,558,62,258,189,715,402,498,37,615,212,530,299,552,923,206,8,159,577,666,621,286,880,813,394,168,161,755,262,118,118,617,525,810,339,886,482,543,315,501,452,603,174,518,609,888,502,133,3,674,917,661,549,760,897,402,396,326,171,228,415,355,962,576,60,767,40,424,365,122,92,610,824,966,625,910,349,144,349,832,950,1,308,202,985,38,107,794,406,58,472,924,440,879,914,822,570,34,33,857,481,306,552,818,711,238,913,240,334,831,933,682,89,128,153,515,809,264,60,14,179,763,993,600,210,405,523,42,359,956,327,412,125,15,310,462,405,731,404,185,485,778,892,612,581,974,307,725,992,239,34,992,38,319,82,749,824,734,602,152,271,416,937,700,808,776,22,828,808,350,52,949,246,850,304,644,846,1000,74,648,467,873,280,237,552,667,612,387,269,752,110,867,276,256,121,281,447,760,232,121,31,671,748,345,485,586,927,270,760,575,7,408,899,275,717,211,953,151,961,90,740,763,640,402,32,818,515,422,581,843,422,834,181,325,185,520,618,650,37,360,338,910,620,516,331,270,435,283,773,444,279,998,641,636,689,359,489,595,721,384,12,57,879,758,343,450,411,98,157,487,804,469,596,342,696,289,268,710,435,775,969,586,416,768,825,395,652,364,569,655,909,626,388,934,472,156,964,793,283,427,482,320,332,795,732,197,565,757,213,50,891,272,970,511,647,880,511,429,54,965,608,784,266,448,146,43,459,477,401,102,160,818,789,360,514,978,435,747,987,176,446,827,190,13,856,996,757,519,639,394,905,383,950,503,848,8,558,957,631,403,247,726,381,264,267,78,895,54,41,165,489,206,5,596,794,218,864,622,982,758,610,116,972,421,161,735,214,369,29,145,858,956,719,549,463,125,215,207,266,613,660,956,150,663,575,694,673,989,395,685,176,258,929,317,686,944,102,690,458,211,928,17,844,625,857,581,505,224,911,12,618,930,538,374,43,713,282,164,596,534,84,32,975,211,781,879,532,740,318,982,354,98,408,430,966,501,986,658,253,165,102,86,704,350,986,369,64,660,410,284,120,713,379,574,31,864,570,747,583,30,754,617,300,868,936,751,25,476,600,655,935,452,761,978,712,112,656,273,605,2,739,348,665,998,755,857,535,755,787,557,256,415,330,187,356,192,373,506,312,601,590,533,425,212,163,232,215,653,37,933,523,25,560,22,943,437,768,943,414,759,525,306,279,83,71,349,399,741,213,761,578,62,607,731,466,702,767,328,317,417,210,763,224,351,284,967,762,651,852,615,501,598,391,834,698,644,816,628,914,230,772,575,489,312,23,519,575,600,947,538,516,185,552,352,986,36,505,630,325,418,359,669,949,729,899,214,94,34,818,530,545,986,833,651,511,225,456,869,564,202,233,601,143,780,570,671,727,946,647,916,351,258,719,600,479,670,652,864,454,120,79,966,49,376,857,610,467,248,455,787,500,701,658,450,616,179,946,251,473,264,458,412,33,636,846,879,930,196,465,866,506,249,375,402,294,844,221,185,969,823,457,368,430,124,265,150,61,580,675,828,195,65,52,459,168,618,67,215,125,958,294,648,941,387,637,875,737,923,894,916,170,558,958,584,480,826,139,400,318,361,166,969,548,765,551,317,71,437,857,955,514,55,933,740,968,928,322,296,628,194,170,388,566,767,262,768,514,355,769,632,297,675,394,502,590,908,651,655,458,855,743,217,652,684,371,917,128,812,700,424,542,657,410,596,353,134,361,894,13,743,965,110,393,158,456,83,267,365,179,802,713,681,591,946,624,30,484,236,333,961,962,894,283,700,270,283,68,345,454,144,304,0,363,296,465,366,886,101,554,676,72,890", + "229,342,149,885,957,89,450,579,354,838,773,806,259,340,810,803,684,267,798,485,416,227,723,664,689,944,755,659,375,996,925,960,182,103,105,599,645,91,847,585,935,517,866,141,723,497,746,590,642,961,892,778,652,295,161,306,976,289,869,530,576,68,692,724,239,912,389,922,179,158,766,762,256,586,953,745,550,944,252,579,170,962,148,644,601,572,172,664,901,288,37,414,181,806,479,42,457,250,32,607,741,40,449,117,964,723,420,843,641,228,765,290,602,963,258,248,690,581,54,705,447,55,553,400,370,483,302,171,377,638,564,487,495,180,893,403,485,742,103,58,710,605,146,628,949,930,312,725,141,748,618,311,955,838,911,520,130,131,969,294,776,47,477,669,808,856,894,191,684,846,401,386,608,684,73,960,370,525,235,882,157,520,741,599,884,625,57,128,549,83,200,492,653,720,539,332,903,49,105,389,488,233,496,792,808,848,608,816,638,980,904,692,619,746,586,84,488,535,918,630,380,608,424,7,129,79,607,124,313,717,112,92,432,228,703,487,918,623,124,548,853,857,252,718,610,11,705,677,336,306,350,766,123,338,492,903,169,746,274,464,620,558,932,821,597,943,289,29,833,780,944,697,275,829,834,562,116,427,924,432,437,183,849,821,629,904,931,63,948,301,413,187,115,503,691,640,291,896,435,755,649,494,152,791,495,827,639,660,874,130,114,536,257,305,76,456,446,966,138,739,257,664,271,617,537,98,999,635,559,725,329,216,628,300,599,371,237,302,619,921,340,917,318,681,917,803,399,726,987,873,629,999,449,144,948,993,43,15,239,339,514,186,403,5,838,143,785,923,951,899,470,764,446,941,460,872,796,545,805,941,87,20,106,825,683,38,597,581,784,285,122,80,310,645,16,812,515,961,75,846,194,124,173,753,709,656,241,757,365,777,131,254,451,687,904,511,828,231,8,546,558,268,183,367,766,569,743,589,26,601,511,235,7,341,514,388,73,230,6,987,363,363,283,290,775,714,709,656,785,108,175,756,871,413,604,795,113,614,422,463,608,333,784,84,914,450,85,102,994,398,794,806,578,992,722,575,110,798,712,60,990,102,985,572,50,491,388,982,986,952,500,765,681,781,924,784,208,603,71,646,117,184,167,968,35,420,55,898,464,165,487,177,559,838,663,145,124,112,222,533,231,696,830,959,51,148,414,685,71,531,238,134,265,786,293,953,40,993,548,669,546,679,427,468,517,882,157,228,479,47,912,946,206,904,383,340,344,540,972,464,331,344,161,317,232,635,947,795,132,836,781,250,928,255,522,541,11,411,844,968,243,42,95,745,421,68,647,458,904,227,593,842,482,86,652,972,449,238,275,176,658,939,330,24,189,154,710,832,981,859,542,545,150,968,767,905,664,900,427,351,986,763,941,27,127,858,559,901,676,408,834,932,225,190,368,593,395,159,301,559,309,247,843,594,751,485,347,46,878,241,801,587,698,935,319,939,19,442,624,248,372,963,226,81,435,705,717,829,628,379,463,792,24,691,584,431,391,910,914,645,428,661,250,680,677,793,961,122,740,461,658,123,777,526,887,353,955,570,280,309,656,661,37,920,590,268,779,845,946,27,279,470,781,264,424,376,901,514,420,67,162,280,936,165,15,970,751,327,644,361,59,310,472,320,753,956,51,973,624,824,826,472,264,234,65,752,189,288,794,230,13,737,130,566,673,253,58,172,98,443,367,251,229,788,959,972,498,613,220,921,658,515,615,65,879,162,885,201,620,631,337,394,77,586,66,17,2,648,330,927,211,845,935,927,17,953,640,238,894,957,795,994,944,39,714,163,538,893,698,55,833,530,842,381,518,315,270,478,136,519,727,321,45,512,359,163,989,440,249,347,246,235,182,239,777,960,496,319,503,967,748,954,558,687,687,203,393,512,363,823,833,138,440,469,571,16,803,848,92,563,761,877,364,486,399,386,647,368,963,212,560,342,558,205,134,434,357,555,779,512,448,659,363,784,911,17,292,583,344,540,972,457,786,946,644,826,506,608,683,610,183,625,289,956,975,710,957,89,367,224,876,805,845,332,648,604,308,381,264,161,857,611,288,224,399,378,826,911,481,936,436,115,973,987,793,172,1,181,250,918,211,265,372,923,445,727,291,230,763,455,243,432,604,539,883,613,90,640,867,572,429,69,269,408,63,571,723,294,113,209,712,887,426,333,563,901,90,6,793,755,333,991,733,723,429,990,911,522,763,363,0,329,820,653,851,673,292,869,264,19", + "344,778,675,215,826,607,981,758,480,805,153,624,908,936,282,313,301,368,648,43,60,858,723,51,511,67,175,179,765,198,205,323,143,914,699,220,31,440,250,388,369,235,650,815,305,172,317,927,717,568,972,566,711,595,423,715,702,896,566,360,931,616,331,337,482,710,624,154,481,537,122,749,624,703,757,798,271,235,294,785,92,901,485,952,115,405,708,650,715,207,115,239,585,65,701,951,31,6,968,435,630,321,87,731,216,72,722,155,367,517,195,14,246,917,243,964,216,313,708,261,906,648,172,302,848,204,39,54,412,586,14,849,576,444,811,985,295,72,427,508,825,774,157,183,965,136,478,938,91,925,768,605,893,115,65,213,787,372,642,679,980,61,697,278,1000,37,482,22,226,11,788,113,226,980,320,27,744,89,775,104,681,547,65,188,883,345,244,749,437,904,385,154,565,121,859,411,837,231,526,471,24,392,637,537,417,844,771,746,935,9,451,517,492,455,753,979,503,347,79,582,846,614,332,359,617,48,262,746,94,833,932,865,342,549,746,605,160,991,133,48,737,738,754,669,48,769,734,887,404,662,688,260,951,80,712,187,235,418,364,260,670,96,42,883,709,446,25,305,716,711,334,442,683,812,212,905,421,421,363,745,282,448,589,7,230,589,103,982,765,908,962,67,688,556,420,118,963,10,305,467,862,247,169,996,118,636,838,512,141,211,413,485,724,451,637,836,363,162,276,213,1000,911,645,540,394,504,63,750,796,374,242,591,637,588,92,392,329,701,266,758,833,527,785,131,285,975,322,599,427,697,616,971,505,93,836,807,64,293,583,737,482,290,404,574,28,789,561,945,395,737,676,31,835,667,57,512,160,861,206,389,283,580,336,64,140,379,666,794,4,211,836,919,359,315,526,970,791,624,759,639,427,722,147,427,267,28,813,937,764,613,849,391,918,974,715,202,80,230,298,934,967,822,606,459,908,804,336,214,332,986,926,982,592,142,570,488,528,593,121,138,533,703,455,441,2,412,193,878,845,473,479,814,194,556,856,497,641,74,381,478,990,170,810,880,178,495,751,898,493,303,334,554,727,765,902,295,448,207,352,655,935,804,89,754,411,48,566,370,117,513,992,917,973,924,210,897,694,79,135,196,131,13,634,526,863,664,49,490,482,489,283,863,744,68,799,538,696,528,241,713,646,231,213,269,254,64,948,826,82,912,29,892,829,667,811,800,471,493,26,838,71,79,684,947,352,361,984,433,698,166,400,959,335,308,998,252,366,707,436,327,540,498,379,117,912,8,825,337,396,53,73,231,496,50,59,159,508,511,750,396,880,439,654,744,945,253,185,121,15,479,194,378,694,908,501,410,315,112,724,476,581,184,972,952,190,56,743,545,53,725,950,681,627,394,39,489,972,270,939,657,987,290,324,488,142,904,829,565,273,11,913,695,858,981,750,231,254,964,409,879,435,347,933,216,148,961,651,205,398,771,191,761,789,289,660,975,547,404,718,771,191,800,515,618,415,671,142,666,155,524,320,919,338,38,874,183,541,961,988,58,80,1,989,282,263,785,231,164,593,468,852,805,763,535,676,600,47,197,50,316,376,561,60,52,228,691,314,863,623,345,781,998,313,632,653,856,509,476,812,310,269,597,258,32,8,232,682,826,253,873,771,64,911,261,552,235,400,890,739,285,654,787,728,899,44,392,47,270,398,953,69,975,122,568,502,721,799,250,132,866,258,457,327,354,846,95,345,103,550,976,342,855,304,907,593,197,309,377,512,70,461,44,788,649,837,864,536,932,1000,97,245,961,401,589,101,343,667,419,289,366,678,195,845,992,713,502,967,29,528,632,419,56,361,858,188,446,861,251,351,377,148,748,336,171,29,231,402,966,797,905,143,819,411,760,172,942,369,272,147,384,691,289,387,578,417,583,26,130,905,27,921,778,250,673,135,101,436,853,339,463,711,799,363,18,342,522,76,577,586,906,570,380,899,798,551,549,953,587,318,509,504,744,155,329,766,846,312,195,496,498,957,573,797,76,262,420,600,809,923,232,513,177,901,984,61,541,406,403,569,494,359,479,927,651,71,755,99,189,322,280,916,951,192,279,290,780,161,351,815,962,357,459,7,107,392,770,880,222,248,845,398,849,397,859,490,176,831,195,113,94,625,377,895,431,329,992,511,231,356,473,67,619,720,647,161,65,680,136,604,280,786,322,910,70,160,124,132,272,954,207,210,537,486,509,989,957,169,929,861,296,329,0,733,760,213,714,470,259,629,120", + "870,657,941,565,559,196,210,75,128,229,171,840,843,567,609,202,33,548,992,934,676,549,881,467,394,664,875,626,354,319,156,739,404,842,899,164,60,95,318,179,617,805,824,371,125,307,426,905,325,305,553,91,109,459,636,686,474,32,604,652,440,992,638,782,130,911,517,527,171,953,924,6,611,456,252,525,984,514,922,932,641,362,995,575,547,978,333,783,537,241,459,623,819,212,700,637,801,99,217,740,60,629,625,963,17,87,64,673,440,710,69,50,956,682,592,407,476,627,31,980,940,175,649,561,260,569,794,619,67,856,632,515,275,686,762,155,867,85,940,220,786,397,935,594,536,765,348,942,474,178,655,940,601,370,320,735,769,804,726,118,46,670,961,119,349,234,47,1000,939,915,851,103,648,129,637,71,352,386,710,594,542,865,301,517,53,265,774,530,420,565,708,422,779,30,780,143,421,14,320,249,157,103,690,975,112,796,132,139,318,221,844,256,122,204,60,376,860,514,175,537,662,603,638,284,883,426,487,239,359,601,657,205,44,990,259,528,474,389,10,842,124,194,590,609,318,308,53,454,709,373,425,34,728,922,907,909,947,167,414,336,280,860,494,437,730,98,543,802,60,274,662,662,694,242,198,942,473,218,296,429,764,345,603,363,479,154,200,285,807,72,733,938,55,946,607,503,677,128,480,152,335,519,181,707,523,306,395,989,586,273,572,210,266,924,170,807,793,718,114,504,482,808,195,789,200,516,625,468,780,5,464,274,358,906,6,255,602,606,218,467,689,456,271,305,567,35,262,355,439,599,276,42,833,989,404,400,105,998,996,845,560,139,635,1,878,826,282,109,161,507,272,499,824,989,815,198,729,739,336,484,686,631,940,260,323,42,839,202,440,886,542,480,253,278,158,206,782,245,502,678,273,44,648,11,76,387,279,798,155,904,985,418,991,413,735,211,679,458,277,435,541,874,582,735,374,509,438,403,29,531,339,42,809,46,812,39,795,895,156,824,499,530,471,53,292,547,935,258,666,220,816,772,136,197,844,416,520,567,613,15,696,339,321,638,398,321,183,572,630,232,737,561,988,937,461,830,941,113,830,582,378,852,379,121,598,230,493,928,503,121,844,479,569,788,919,987,495,412,256,924,487,349,429,571,212,896,486,139,486,657,780,142,890,644,557,444,855,993,768,701,943,171,934,913,697,200,199,358,8,116,806,42,311,685,684,126,861,740,658,365,983,833,26,587,60,221,892,140,912,662,49,652,103,628,972,576,545,265,159,627,617,728,527,829,628,428,374,4,111,807,391,695,917,913,698,688,953,274,108,841,681,596,373,244,668,348,275,830,214,881,868,855,46,589,338,114,768,654,109,237,177,973,860,70,437,672,816,33,484,290,891,775,881,507,785,559,112,473,540,695,494,541,107,137,761,574,105,856,134,342,424,85,858,154,197,283,739,961,662,648,701,700,774,338,49,107,716,33,42,636,180,406,397,576,938,812,486,743,590,254,636,627,787,749,103,133,665,333,728,397,464,728,155,315,723,270,182,678,759,635,886,153,750,903,613,751,271,554,474,898,701,207,850,396,726,41,524,38,983,896,269,285,128,177,372,729,884,445,10,9,427,171,161,447,150,481,729,891,716,773,872,355,728,742,648,166,679,763,609,689,6,923,750,315,47,412,659,233,627,258,555,600,430,772,311,661,341,520,705,410,664,830,981,266,182,262,89,572,131,320,868,602,438,855,541,625,891,61,712,963,312,509,511,960,506,780,108,493,282,934,919,672,947,913,854,68,477,247,684,636,61,768,550,922,360,193,649,848,255,713,838,587,177,282,355,276,643,679,527,584,218,89,963,988,662,223,469,199,622,937,602,375,381,647,790,588,676,955,924,817,441,225,399,849,650,357,889,284,121,747,592,588,894,154,396,510,610,180,486,173,558,621,502,26,653,117,65,132,728,256,678,423,191,404,926,642,331,975,730,972,506,743,871,183,959,784,258,940,860,709,638,489,54,641,854,272,751,325,951,539,373,786,136,80,880,977,62,475,528,608,394,665,912,124,732,485,649,605,271,911,839,439,660,894,747,602,349,628,942,38,691,467,987,722,942,796,625,940,211,282,393,67,903,910,75,335,476,517,634,257,165,828,670,869,252,788,558,702,779,434,750,911,562,409,841,361,661,176,542,562,207,871,170,283,711,359,264,347,92,463,654,200,141,727,308,863,569,188,729,720,917,68,232,416,129,803,787,562,915,465,820,733,0,536,220,501,595,482,893,939", + "673,755,533,658,501,535,594,191,192,418,405,598,909,700,956,319,895,544,935,861,299,415,696,952,472,857,740,723,615,425,984,542,646,553,381,802,872,355,779,511,137,526,478,459,831,4,878,281,382,390,534,124,889,524,259,504,245,950,518,332,165,164,118,546,258,552,1,818,467,474,206,222,851,729,76,129,129,16,885,762,379,68,978,944,648,537,582,251,522,798,426,849,969,148,499,142,910,96,452,84,494,703,81,632,164,941,407,105,545,502,297,755,13,538,100,595,27,81,757,617,869,528,723,55,626,340,441,833,64,892,230,316,607,422,23,386,6,881,311,322,273,359,430,950,596,117,206,696,957,641,806,620,77,914,322,669,252,481,364,694,13,534,202,276,897,273,717,445,804,79,502,370,571,275,272,441,913,313,120,764,306,317,310,445,446,457,527,570,205,847,651,812,48,102,459,115,979,616,830,765,173,882,871,913,68,9,773,339,591,674,209,733,717,691,154,640,256,41,526,58,809,379,667,832,682,128,493,724,553,207,349,325,842,188,986,835,446,840,606,161,505,161,638,17,295,106,732,180,623,903,727,489,245,740,79,995,590,566,613,564,448,13,67,298,351,340,375,91,844,795,575,980,940,693,73,638,16,394,435,520,572,747,634,819,142,380,569,873,806,52,936,634,45,760,617,459,485,639,427,717,573,690,464,802,23,211,682,742,648,392,393,319,896,48,526,61,402,961,891,67,942,437,556,327,755,46,465,411,934,68,504,458,65,804,577,935,257,45,581,763,352,846,798,799,343,987,977,723,561,732,187,301,280,196,588,569,606,286,229,23,845,965,684,878,814,106,880,406,238,897,638,331,200,942,773,185,406,908,316,305,840,796,751,604,859,671,844,834,688,444,112,149,636,648,651,297,187,164,453,768,972,34,497,982,753,578,931,666,341,303,873,939,197,561,517,598,549,207,896,754,598,468,480,69,450,848,525,350,226,843,402,990,730,452,491,325,217,694,539,400,186,156,393,7,197,758,16,393,199,389,53,581,926,129,732,945,738,608,649,159,190,920,342,246,683,153,506,111,14,568,907,623,327,317,114,104,694,286,819,487,413,69,428,214,490,6,151,947,945,887,72,241,279,513,357,737,187,908,862,845,146,889,415,432,260,371,861,415,625,446,87,24,488,528,747,278,953,836,599,393,609,448,208,659,698,114,648,192,182,247,661,737,415,251,185,450,948,552,759,447,594,500,675,705,571,645,45,304,897,851,713,990,401,688,818,499,185,863,13,345,191,648,76,208,917,756,339,300,549,661,661,495,110,952,545,833,220,65,635,423,90,89,257,442,955,674,767,573,549,773,712,692,879,224,204,500,924,312,255,550,411,922,570,224,636,774,227,914,373,684,199,779,817,369,28,72,688,837,752,963,910,238,923,31,730,615,407,509,592,508,439,172,887,623,500,287,787,37,471,344,460,832,56,313,305,818,431,55,873,59,920,891,210,888,728,387,279,78,563,869,176,966,472,889,865,704,380,963,429,381,226,379,134,302,448,505,445,828,881,458,454,875,502,229,956,652,711,912,564,208,456,927,941,607,730,244,601,323,716,403,535,272,830,669,38,691,493,909,672,342,112,264,803,938,938,200,331,410,445,401,609,65,431,682,134,868,875,719,381,884,551,10,554,861,275,846,481,355,854,724,400,394,415,46,827,520,754,676,835,101,707,593,814,723,353,464,3,614,92,120,364,855,633,248,320,765,320,667,548,935,296,253,674,429,380,361,281,921,336,138,8,299,967,673,839,607,264,84,147,592,75,462,524,892,991,916,726,911,27,342,799,224,968,732,304,168,846,752,535,306,647,619,65,993,55,63,406,822,464,793,51,265,606,994,663,981,655,374,267,309,773,209,15,59,7,590,934,429,956,55,293,106,566,729,504,19,744,77,293,993,428,290,408,505,37,986,895,943,909,275,572,303,529,154,793,184,241,575,594,863,702,49,319,852,854,975,551,392,78,484,273,286,670,83,777,406,984,845,51,173,435,797,552,563,815,776,267,386,523,440,294,78,145,785,277,471,870,234,209,527,835,521,492,808,560,727,896,869,982,811,351,659,376,652,145,372,915,152,631,300,799,712,239,593,44,350,510,225,981,253,642,942,226,995,671,84,138,954,133,862,762,907,502,828,35,635,40,405,407,826,263,964,595,697,205,426,978,618,180,182,646,327,160,161,904,392,839,305,276,686,515,769,71,629,61,177,433,966,954,366,653,760,536,0,306,869,543,70,739,138", + "738,777,422,738,195,191,198,543,279,373,94,59,500,346,414,137,529,755,59,212,313,53,138,259,79,71,570,142,824,99,474,466,542,30,407,441,996,215,257,281,359,420,142,23,447,326,748,352,535,22,845,87,90,763,143,997,62,867,645,788,448,721,382,13,219,522,597,35,601,900,223,15,117,521,662,740,929,788,418,496,710,172,348,710,636,329,774,183,729,276,214,755,886,295,327,547,621,867,519,949,246,280,78,471,251,215,46,984,185,925,46,354,679,883,914,344,958,402,788,421,300,198,993,886,753,654,613,919,959,307,533,462,902,157,829,563,973,894,188,498,223,51,691,864,257,984,732,580,905,999,835,868,694,629,574,96,129,213,89,981,929,304,250,637,705,467,821,975,635,793,581,775,535,306,167,152,401,918,882,695,150,87,618,580,271,573,825,518,600,161,165,395,637,937,187,588,500,439,298,451,903,883,910,43,860,291,224,54,340,388,477,339,645,242,221,561,662,102,622,33,116,605,108,80,987,71,718,524,58,399,946,348,508,744,866,233,787,1,824,183,63,878,586,991,831,125,914,720,860,158,826,310,296,691,301,217,967,435,750,744,148,902,783,452,690,531,267,265,474,392,104,707,141,696,653,265,884,346,703,295,586,595,216,218,538,739,877,70,162,663,839,692,409,689,75,799,41,495,660,45,907,288,607,58,194,716,636,192,354,132,922,250,319,590,4,119,971,652,752,646,308,820,376,118,563,817,698,340,66,717,484,385,551,55,364,502,436,845,967,949,228,653,963,267,430,393,388,235,881,633,312,873,633,713,112,201,242,642,514,257,300,853,996,436,695,105,392,456,973,953,492,882,925,718,336,737,47,574,924,449,888,237,368,133,853,493,773,589,220,803,950,653,782,781,827,43,4,843,210,706,49,213,394,964,73,16,681,708,279,58,80,638,780,128,926,873,984,492,47,724,934,140,306,632,767,658,375,810,764,268,63,918,283,911,60,489,176,720,909,146,892,731,63,630,350,627,529,360,639,633,838,427,342,372,867,114,666,592,993,738,905,183,409,850,326,720,944,233,7,250,266,945,267,690,830,566,302,997,418,518,411,795,423,941,75,235,518,342,813,719,504,863,717,661,318,43,351,175,225,922,423,329,48,311,61,786,756,362,813,779,114,621,28,727,384,670,561,445,983,358,597,191,543,163,814,603,641,79,199,565,413,986,913,243,983,117,381,562,235,647,788,986,277,651,307,14,966,693,912,38,811,244,647,61,85,959,688,133,319,404,73,949,19,729,695,427,531,770,455,701,732,362,473,357,834,139,219,791,558,262,531,601,186,80,939,455,478,169,712,900,112,748,122,161,353,461,831,986,119,798,801,309,100,244,716,365,421,611,456,821,481,237,883,195,978,164,747,772,703,134,266,757,129,427,325,938,934,751,951,257,340,623,718,11,791,423,850,890,656,872,985,225,940,13,367,113,419,445,221,950,864,82,98,724,214,543,787,279,486,764,919,504,258,154,764,339,630,286,645,342,138,453,818,390,71,394,816,915,993,11,517,181,272,636,271,322,700,705,746,830,154,411,995,394,858,629,106,224,365,190,978,876,587,241,981,484,410,55,918,287,156,848,187,102,571,9,459,201,76,284,580,758,502,416,660,639,36,545,299,178,854,427,989,67,807,846,814,2,388,840,684,340,307,11,530,996,513,133,736,389,879,168,45,382,602,698,588,194,601,619,316,428,467,84,617,599,76,873,172,798,10,202,229,313,557,203,901,360,935,704,107,427,937,964,669,329,958,918,648,793,850,111,247,753,655,581,247,259,443,934,61,8,821,527,496,554,491,185,218,308,548,133,158,485,525,90,319,186,833,925,137,680,590,537,863,433,433,981,437,712,6,94,209,415,51,524,449,416,4,129,600,270,846,194,292,299,840,808,377,204,707,573,21,937,358,538,638,149,515,509,383,847,397,48,80,138,24,297,120,817,333,499,103,545,487,939,136,757,83,997,52,974,86,852,22,920,874,674,999,79,230,946,856,115,753,252,76,653,907,788,31,409,652,284,301,439,421,419,271,642,423,502,968,126,78,995,619,960,437,421,129,62,40,551,113,491,843,774,988,605,922,703,369,222,370,800,271,553,818,342,396,727,765,260,819,759,704,35,338,178,565,173,631,926,897,747,311,730,959,674,740,997,793,472,681,213,314,369,444,539,340,169,729,334,699,28,250,186,385,418,426,174,668,760,750,97,506,848,383,886,851,213,220,306,0,594,607,823,46,234", + "250,470,227,191,588,89,834,926,878,295,105,286,311,353,349,796,570,250,847,148,317,366,632,852,412,722,945,972,510,541,227,972,102,317,947,142,250,188,342,220,14,151,20,997,465,542,885,941,137,101,378,84,635,790,62,869,741,743,344,288,186,948,20,190,554,873,717,245,586,998,285,945,667,705,93,784,83,722,517,416,469,393,839,98,431,186,767,250,226,420,880,47,101,936,131,309,778,419,293,421,543,934,230,778,934,638,70,103,444,879,369,151,898,307,331,370,450,307,391,324,23,644,404,937,959,779,101,215,49,487,296,629,172,185,197,129,293,449,901,919,33,880,574,552,118,150,7,265,711,93,59,941,353,387,950,269,389,943,656,182,698,124,904,112,601,927,83,866,577,679,831,163,374,228,891,63,274,211,332,786,401,157,81,181,338,444,458,3,743,147,392,638,777,959,398,537,864,42,568,222,175,279,246,476,543,955,887,859,979,699,109,845,189,659,72,716,698,367,743,614,312,914,685,404,755,958,108,144,828,76,237,369,429,855,901,365,977,491,759,485,71,572,325,341,624,401,466,750,549,910,309,971,766,507,841,937,514,730,26,856,607,649,397,474,557,470,925,2,309,277,364,633,827,95,269,732,502,650,209,463,771,111,134,533,955,614,787,805,464,690,701,16,646,931,32,333,464,277,168,518,299,727,177,592,940,566,527,333,274,715,350,770,206,162,495,820,894,842,455,904,111,114,529,692,635,236,761,25,229,152,189,585,512,249,382,865,117,826,744,801,438,349,164,942,421,932,163,329,970,108,412,428,467,397,953,664,78,747,831,983,713,476,736,73,329,821,113,232,676,721,552,326,459,187,517,833,952,896,900,460,908,561,538,650,817,210,7,948,379,567,274,719,897,566,103,138,571,845,407,292,497,588,115,77,15,302,895,856,85,679,371,308,286,999,595,513,406,465,259,56,955,101,780,49,603,587,777,313,247,22,669,845,198,701,318,940,439,987,573,633,23,957,240,96,207,618,701,603,671,437,334,314,672,898,606,662,782,183,676,769,492,386,561,836,777,286,377,562,135,498,709,770,555,398,476,32,765,93,675,604,165,657,184,741,862,385,794,548,198,417,537,619,917,525,353,477,386,167,207,541,84,33,164,945,338,71,702,193,501,545,201,473,893,809,918,600,952,854,573,845,102,38,772,912,428,129,469,364,394,332,407,775,229,252,177,759,542,21,894,600,906,705,460,791,474,372,572,770,846,284,563,119,146,750,609,98,410,653,564,117,547,92,353,158,336,623,456,816,527,861,339,534,267,904,256,747,95,939,469,984,20,426,581,745,791,927,928,458,630,252,184,194,965,891,588,538,36,833,159,179,163,286,606,440,81,933,556,994,523,261,986,101,551,94,166,915,385,179,245,119,234,877,803,994,881,955,587,773,195,958,296,192,404,28,397,224,368,644,183,915,614,787,627,462,732,800,131,428,681,2,649,395,942,635,235,240,237,71,373,745,421,694,489,757,441,668,677,548,993,862,455,879,891,464,820,324,830,332,712,675,364,682,591,5,736,335,986,3,497,705,272,954,568,928,667,443,250,218,2,251,219,717,495,612,966,183,782,555,867,687,170,119,269,638,388,283,863,604,852,887,811,622,901,28,660,758,312,555,969,192,903,187,623,648,663,3,116,189,303,952,640,987,746,614,866,934,356,965,253,83,991,363,577,51,181,988,780,524,768,252,995,393,394,18,100,843,762,323,103,424,510,92,198,6,787,934,34,141,488,76,684,414,767,458,515,547,784,508,438,955,230,491,468,974,811,20,723,349,11,80,323,82,616,855,85,781,769,682,991,207,516,869,230,899,892,510,339,22,460,72,690,150,225,154,129,207,473,58,968,151,869,429,312,242,468,332,338,712,614,515,191,84,380,983,338,126,646,272,301,700,188,213,146,506,354,419,231,920,829,291,863,169,91,888,999,879,992,623,463,125,234,517,302,472,346,918,564,964,868,726,95,535,200,235,274,227,995,667,302,687,300,75,72,302,333,286,225,838,276,822,34,79,872,186,265,200,984,613,90,181,372,326,93,890,805,98,304,977,738,834,549,808,474,67,136,532,997,61,86,613,675,714,768,188,116,99,169,245,520,647,588,353,292,290,321,186,144,440,268,570,387,352,722,627,443,150,878,10,455,920,93,52,295,5,766,98,482,785,986,411,350,806,853,636,734,663,251,352,487,513,643,659,858,565,648,286,779,984,375,101,673,714,501,869,594,0,718,226,115,140", + "949,233,581,136,558,761,984,692,552,501,113,889,890,938,545,278,443,44,425,11,400,208,795,559,556,894,753,722,200,396,499,390,929,756,739,826,984,750,915,154,45,476,675,387,811,846,942,920,924,101,960,738,992,218,791,336,734,280,942,468,299,766,923,272,335,872,207,232,131,86,177,61,676,756,88,202,904,14,638,775,216,815,956,995,444,896,28,593,416,727,506,929,569,239,509,22,316,324,490,533,941,70,24,996,798,835,913,329,61,271,527,147,180,925,358,711,81,619,444,362,163,139,353,925,634,237,730,135,509,612,86,269,794,684,138,753,514,937,161,716,171,627,145,124,767,282,629,449,276,524,665,65,866,47,953,512,761,384,272,511,744,491,66,400,857,366,981,58,643,401,595,188,530,273,380,603,716,651,15,106,81,365,559,667,912,38,738,605,559,16,360,207,421,314,222,673,31,507,173,483,215,203,398,516,220,68,389,557,768,884,623,203,627,963,188,294,230,866,768,170,326,277,197,813,845,36,588,138,978,874,913,810,544,669,617,746,392,227,860,514,395,264,606,260,416,184,565,23,649,606,474,293,407,568,151,577,58,463,818,547,623,140,493,535,978,619,966,269,831,173,712,62,794,537,590,981,904,529,452,711,641,273,200,565,681,379,736,532,38,515,958,934,116,925,851,500,600,614,147,817,846,215,381,149,471,119,230,832,282,398,315,626,913,964,633,732,166,155,932,449,774,294,900,265,423,541,204,50,465,554,581,210,928,754,766,488,241,977,401,655,488,342,473,371,751,767,711,367,15,181,276,501,411,597,864,874,883,126,652,39,353,947,586,65,945,22,668,199,600,899,517,999,860,720,71,917,614,864,863,325,886,223,529,70,302,86,356,749,943,940,864,682,756,710,122,15,685,740,489,418,331,505,386,246,682,439,365,950,536,877,457,885,830,528,872,128,738,716,340,644,350,954,811,480,165,9,371,304,193,398,318,460,351,750,739,898,535,852,706,226,946,336,764,975,941,505,757,14,75,625,613,664,67,562,961,430,189,321,207,46,796,511,668,912,281,1,874,126,966,512,780,728,722,761,812,263,860,846,551,733,217,624,734,640,194,647,24,500,523,972,19,165,22,961,711,667,670,631,173,154,343,782,384,531,912,525,55,903,24,158,8,769,158,560,595,948,992,302,571,697,732,637,197,514,66,578,551,751,67,389,457,913,458,542,740,720,682,156,677,571,888,512,558,186,972,644,481,651,750,977,897,216,496,557,50,91,736,661,333,291,455,42,151,5,413,412,108,813,706,957,113,568,217,683,339,634,656,78,299,678,155,943,575,882,120,194,464,24,931,90,11,857,137,18,487,617,116,670,474,766,266,642,171,132,196,155,536,559,973,128,421,756,586,426,588,118,102,811,326,750,586,888,830,152,592,949,144,24,557,868,274,79,810,101,841,398,173,909,387,448,503,725,749,520,426,952,667,853,18,415,894,222,577,291,136,433,42,701,963,72,532,201,836,165,652,323,391,854,959,887,667,145,522,132,739,804,359,90,531,791,825,772,101,254,274,876,876,228,507,502,336,377,501,189,605,252,405,70,423,80,805,529,511,94,345,488,160,454,104,328,592,149,499,16,500,913,269,527,609,33,258,184,508,384,497,748,35,397,125,771,585,131,322,326,546,263,462,345,278,469,503,964,191,628,391,957,459,389,956,204,328,107,394,700,157,356,291,953,154,385,397,977,33,193,348,162,599,853,679,976,645,534,656,853,708,41,177,22,527,634,729,265,940,492,262,305,215,26,786,232,886,766,311,956,782,3,541,500,639,953,663,440,129,316,529,553,870,432,904,706,952,185,550,281,978,247,379,38,330,754,131,705,348,553,723,131,316,694,664,402,973,399,386,74,105,326,986,657,773,627,916,186,941,77,867,946,876,277,486,584,951,609,999,908,231,593,344,266,300,408,623,250,839,584,98,382,394,805,58,530,942,714,19,64,659,781,699,519,214,187,149,423,198,858,812,791,14,398,122,311,196,491,975,218,334,952,983,123,261,682,242,918,509,560,447,197,872,993,93,539,201,145,991,138,184,590,262,211,543,584,114,559,492,399,586,669,950,118,33,874,807,66,937,997,291,271,83,831,620,472,571,249,304,586,289,231,858,442,189,96,150,755,662,552,315,711,987,952,182,917,826,308,1,259,467,620,348,751,895,487,735,171,818,815,350,484,119,162,284,167,518,974,141,360,97,390,37,858,470,554,292,470,595,543,607,718,0,111,148,996", + "264,547,470,994,952,182,953,111,249,346,50,744,142,415,824,7,314,258,998,943,54,865,664,243,623,213,250,844,475,347,518,668,488,635,102,696,757,537,995,887,687,415,715,259,474,547,9,953,388,970,213,30,279,177,574,152,255,501,898,55,796,82,53,163,355,22,795,514,661,537,48,403,583,234,720,348,402,869,343,81,279,604,911,848,89,999,996,112,218,40,711,800,8,533,268,649,313,229,520,160,914,448,983,454,947,191,611,54,193,378,32,256,498,193,893,945,200,289,98,307,74,141,583,483,925,978,311,473,959,530,404,970,237,456,835,201,826,919,551,890,168,461,932,877,700,832,111,917,351,509,136,950,205,564,284,101,787,308,782,166,115,134,48,570,838,544,42,831,983,525,201,678,385,599,755,155,859,179,792,437,348,816,561,885,412,907,799,538,621,294,298,456,253,486,332,942,885,736,304,438,492,602,639,682,147,672,253,428,529,987,334,807,543,657,413,938,142,543,934,805,708,983,6,52,532,867,198,506,817,813,378,542,626,914,30,563,644,454,290,535,687,480,7,588,510,197,999,185,731,210,2,565,251,509,923,923,992,919,679,448,650,136,492,868,493,351,477,11,704,676,637,140,758,856,888,880,669,63,224,39,411,507,314,517,346,921,542,953,732,262,825,524,301,2,713,801,76,841,347,17,831,62,921,950,151,557,476,401,590,59,566,446,489,327,386,103,531,976,817,21,819,519,784,311,678,536,79,250,628,171,43,838,461,889,161,147,714,685,410,720,826,360,776,963,653,796,466,295,365,997,585,180,712,547,455,419,200,838,26,89,515,416,370,574,583,764,580,157,337,771,877,360,579,381,451,868,715,255,940,641,110,935,23,726,393,850,342,893,148,399,657,235,774,685,899,491,103,992,792,272,872,626,598,403,685,295,234,591,32,890,283,734,586,779,242,660,630,87,32,188,961,85,954,898,525,86,177,455,663,976,641,219,465,985,989,452,948,670,654,657,159,962,37,704,933,381,938,188,236,878,280,568,911,184,976,625,603,511,526,756,136,842,545,720,938,952,226,135,51,256,316,245,96,313,243,438,849,172,517,203,229,487,320,179,494,978,248,85,329,486,601,30,49,811,356,617,138,850,622,287,108,574,554,709,990,61,392,388,702,990,19,551,51,623,953,990,430,253,50,752,527,946,175,957,804,840,859,600,634,555,364,154,398,980,512,81,360,216,311,560,26,458,626,957,948,594,356,954,591,268,92,242,39,987,270,886,516,388,266,552,600,749,611,943,109,97,76,806,91,515,897,354,108,315,416,472,671,411,127,354,106,777,992,495,875,674,617,507,620,818,608,323,436,97,926,839,25,831,185,843,150,909,415,342,33,23,856,23,972,127,981,916,441,286,488,93,862,155,843,795,640,530,271,96,513,73,680,839,16,543,611,816,424,450,941,558,909,872,725,654,299,647,644,484,24,20,628,462,226,130,937,868,982,452,789,156,231,907,701,63,241,387,353,860,520,831,779,487,242,67,789,710,976,204,353,821,960,181,114,478,224,138,155,469,547,948,261,878,973,10,475,437,418,424,144,674,635,196,268,376,456,370,727,652,931,997,450,371,496,180,664,105,854,462,407,561,86,110,320,772,27,197,386,75,880,958,136,475,331,401,816,877,690,293,252,28,987,113,273,66,53,947,120,440,211,813,265,714,775,347,720,781,745,929,950,43,148,558,481,60,598,517,667,940,594,283,11,185,587,876,289,175,940,349,833,673,462,655,276,706,428,898,832,563,350,12,680,865,168,135,195,242,13,389,101,50,799,684,537,76,159,922,859,928,407,737,774,847,143,118,293,48,965,977,443,525,370,48,594,795,640,511,539,464,281,47,654,745,876,7,162,991,306,458,180,5,884,518,892,56,166,328,166,438,844,311,724,747,403,216,651,111,82,975,291,110,854,271,145,995,545,471,804,228,125,11,592,244,343,949,253,745,50,89,65,675,323,729,430,90,648,396,835,389,740,741,444,117,596,110,634,625,445,693,564,134,806,505,79,684,39,167,560,680,739,545,259,942,56,392,347,931,862,239,492,496,869,502,780,269,220,588,744,797,245,629,44,616,580,485,550,636,93,617,929,925,990,537,393,124,505,898,418,90,233,988,816,38,79,884,746,68,688,239,3,22,263,464,971,744,630,776,916,336,932,263,634,442,747,106,603,308,732,36,895,443,773,957,323,391,150,422,230,936,39,316,169,268,836,676,869,259,482,70,823,226,111,0,125,756", + "995,913,328,706,887,869,356,754,407,12,632,711,346,732,765,696,937,478,201,838,888,341,490,17,78,9,919,469,860,216,946,38,507,69,937,229,512,763,985,587,111,224,595,91,714,733,126,292,888,958,273,799,287,816,199,415,216,923,67,571,128,111,273,607,584,903,919,272,67,610,989,582,765,601,367,376,10,68,857,259,993,469,334,191,419,993,880,459,284,628,498,131,204,29,936,430,52,569,559,3,860,360,715,124,93,846,211,291,989,560,309,730,223,294,241,827,912,23,183,403,517,838,643,101,383,292,366,712,313,805,495,936,516,674,383,564,974,658,339,935,153,458,595,275,286,97,126,172,170,503,486,665,578,917,648,123,589,861,968,742,283,460,64,596,789,116,173,392,788,907,330,667,726,302,554,92,234,553,108,110,963,129,796,201,576,647,751,28,892,476,749,409,944,541,637,291,973,771,386,561,792,270,453,691,807,808,246,877,448,576,190,267,691,153,592,44,969,980,869,99,283,385,917,101,20,954,126,402,141,573,919,549,482,438,657,267,914,816,551,321,637,504,172,716,111,322,764,636,539,185,167,474,224,707,913,407,561,413,185,297,85,549,951,137,614,769,888,350,938,606,550,343,154,840,652,99,133,126,68,281,383,211,481,278,628,654,973,779,591,280,608,567,706,150,310,682,740,618,198,845,481,280,671,164,958,983,73,654,40,998,362,979,690,970,857,821,605,623,890,90,537,414,512,869,974,956,719,282,308,835,705,715,736,792,758,663,613,964,469,911,107,653,508,680,591,76,429,766,673,630,599,740,244,645,16,146,45,216,641,931,925,912,384,863,152,457,20,479,980,836,165,443,212,346,377,494,57,970,323,660,444,78,999,256,696,482,607,86,351,145,471,424,245,973,853,114,260,836,115,246,213,442,959,593,136,896,326,873,51,413,536,781,398,859,606,532,515,551,36,424,574,558,291,493,801,800,977,627,551,409,347,302,905,190,778,766,564,645,324,455,932,633,372,773,784,777,113,290,199,452,621,413,698,507,357,822,28,208,379,830,482,166,803,666,82,959,925,990,646,210,630,164,842,381,320,364,411,959,142,199,375,741,732,714,159,712,450,290,66,589,986,99,180,536,482,888,972,524,900,846,325,321,854,458,747,649,542,672,977,266,748,924,752,701,69,693,535,990,568,170,78,564,941,278,446,35,214,103,136,675,282,550,690,680,308,68,952,938,665,499,106,524,70,827,254,159,364,960,565,839,450,616,143,887,894,760,105,386,974,418,199,710,928,277,108,418,287,142,586,579,670,345,567,542,849,954,675,591,453,964,705,701,427,46,596,322,11,633,952,929,196,882,71,585,513,758,218,924,853,331,53,151,23,392,519,825,784,978,53,566,306,897,213,812,371,49,104,184,173,858,438,703,798,777,667,837,867,773,870,415,526,677,795,204,142,268,447,351,313,706,260,986,51,207,14,412,153,612,130,718,570,327,245,784,111,649,616,798,214,324,52,859,578,710,864,276,723,954,515,646,842,499,350,793,468,77,272,363,110,259,417,516,523,507,691,728,482,979,152,806,335,299,667,51,802,594,572,582,329,499,99,372,714,380,352,860,671,787,228,766,350,613,639,966,78,325,294,440,504,674,185,277,820,221,778,123,871,29,391,228,243,764,974,824,348,404,437,172,798,681,871,888,351,752,123,212,710,603,264,133,591,711,750,683,756,715,143,106,647,525,778,574,31,348,514,269,36,181,130,789,133,784,13,738,139,74,880,540,446,530,991,61,115,276,781,94,775,337,286,582,876,797,958,296,258,799,761,603,150,889,926,524,62,671,63,155,732,292,166,848,350,764,994,470,586,906,599,29,596,960,746,632,117,292,354,442,485,206,212,671,281,690,507,603,417,308,42,481,156,274,768,318,432,462,997,933,74,527,84,569,916,96,246,723,735,805,942,657,376,932,767,135,13,976,572,852,191,439,455,677,606,974,324,184,156,896,607,934,740,648,231,846,772,255,608,87,134,864,624,100,795,665,69,819,832,844,510,231,458,616,91,496,976,208,675,144,455,689,417,666,314,4,667,634,575,906,565,577,289,241,529,657,702,832,64,774,897,766,571,298,479,264,762,508,923,580,569,842,666,906,88,456,8,11,908,910,135,973,994,57,378,886,45,172,24,403,579,771,673,743,195,927,324,974,420,866,783,459,819,196,302,205,757,346,850,734,189,406,423,41,101,769,29,719,57,144,778,945,512,72,264,629,893,739,46,115,148,125,0,178", + "873,804,976,299,90,282,615,299,823,509,738,437,999,899,501,303,758,899,69,148,774,947,127,83,684,438,756,264,851,423,653,22,979,697,938,476,835,349,915,966,543,921,590,967,536,647,303,665,776,407,861,136,956,895,714,816,95,248,232,469,342,863,439,446,5,597,578,554,817,694,280,785,433,895,943,111,838,776,945,718,38,592,387,416,150,191,159,679,468,640,82,205,520,91,777,692,275,944,185,906,451,254,461,770,778,253,469,419,250,439,573,600,15,197,465,187,269,872,433,387,560,262,280,665,741,90,735,233,103,641,808,457,944,853,496,38,190,623,124,160,152,872,214,844,868,835,99,147,224,600,328,457,211,453,287,716,216,642,327,47,738,983,570,503,554,235,52,392,409,532,155,563,142,996,683,596,14,351,778,821,564,492,48,344,967,595,861,884,472,531,503,973,116,849,500,944,757,127,67,48,216,361,224,444,479,733,503,356,159,802,964,185,200,690,456,444,447,123,819,784,461,196,430,627,883,260,956,882,747,861,452,255,324,627,644,642,181,823,801,167,366,878,369,792,451,561,244,825,81,905,894,612,576,432,169,776,105,184,181,572,598,807,415,777,188,358,587,921,402,84,784,180,491,220,957,260,207,259,3,875,895,910,605,976,72,786,275,350,858,464,655,829,145,769,725,362,719,880,941,521,595,754,565,605,371,403,459,394,33,763,856,793,356,481,16,297,974,188,248,960,639,524,876,993,791,460,136,83,783,834,165,358,377,195,873,773,242,297,711,232,711,208,201,18,154,88,983,592,35,102,83,696,522,215,404,315,66,673,651,235,397,271,588,54,143,940,689,584,573,505,210,293,418,471,887,961,185,724,361,77,587,699,702,220,394,838,526,560,286,325,612,826,280,881,80,804,184,866,403,404,250,682,522,953,408,199,189,127,477,132,386,648,404,585,177,356,603,523,370,555,398,670,832,533,481,796,966,30,718,178,308,351,863,796,188,132,289,588,713,47,140,785,829,719,796,601,487,497,605,474,298,1000,948,417,957,463,123,411,636,420,379,666,804,772,375,714,64,75,905,710,621,839,758,927,97,210,543,57,130,917,285,456,36,479,789,144,517,730,647,100,889,114,922,473,140,145,699,775,338,429,402,563,20,413,257,214,274,151,256,226,297,293,920,272,366,627,587,622,542,910,23,487,766,340,918,898,703,215,182,878,273,645,126,619,628,35,405,846,938,200,259,282,839,349,225,397,940,177,212,571,600,517,678,318,494,246,835,382,245,292,24,849,446,972,551,486,13,629,649,769,60,159,421,574,95,550,814,910,383,294,405,556,329,983,382,823,958,271,882,557,601,150,159,340,610,727,756,647,292,300,637,299,87,517,677,498,672,697,749,659,94,288,209,498,865,630,322,988,46,266,53,461,829,892,761,428,478,445,759,561,82,196,280,773,149,672,298,188,156,974,883,593,271,672,385,396,362,94,186,835,660,735,961,803,451,387,162,513,421,687,355,746,599,705,137,55,292,378,833,63,71,555,667,343,327,253,705,242,209,343,964,929,803,292,506,117,254,844,165,783,523,30,778,284,248,831,477,156,9,753,184,104,420,760,771,242,791,729,658,984,539,111,521,488,367,682,660,964,585,600,539,320,313,414,175,703,438,484,448,237,566,79,243,198,831,761,494,12,62,169,395,501,251,627,44,929,531,699,38,462,849,383,193,902,599,521,597,176,112,469,267,460,374,613,331,823,113,10,67,333,833,280,779,900,428,264,501,260,813,872,796,543,855,876,710,282,654,734,156,114,444,930,343,769,369,366,637,377,289,768,584,783,819,762,991,515,887,891,81,104,50,325,650,806,425,259,61,274,376,868,643,721,931,732,877,500,140,84,487,316,818,608,310,789,288,818,522,513,297,255,467,89,768,331,778,227,890,11,213,374,274,51,616,181,950,39,778,495,892,981,142,886,484,1000,205,498,773,209,168,929,899,38,421,838,199,468,967,33,751,760,480,757,242,921,826,765,160,604,184,935,562,618,829,61,824,939,506,997,201,605,265,463,499,862,406,232,3,780,625,286,465,529,121,462,751,131,589,587,107,35,972,560,297,130,947,814,724,519,243,246,422,860,920,916,353,639,909,456,510,577,616,566,973,24,661,578,481,899,798,145,225,983,251,561,990,773,555,890,581,632,883,992,38,67,688,798,721,247,91,756,857,873,484,813,710,100,29,235,687,526,714,853,365,181,929,502,235,317,405,890,19,120,939,138,234,140,996,756,178,0") + + val graph = parseData(content) + + fun solve() { + Greedy(graph).solve() + } +} \ No newline at end of file diff --git a/kotlin-native/performance/ring/src/main/kotlin/org/jetbrains/ring/InheritanceBenchmark.kt b/kotlin-native/performance/ring/src/main/kotlin/org/jetbrains/ring/InheritanceBenchmark.kt new file mode 100644 index 00000000000..973e9a75f37 --- /dev/null +++ b/kotlin-native/performance/ring/src/main/kotlin/org/jetbrains/ring/InheritanceBenchmark.kt @@ -0,0 +1,508 @@ +/* + * Copyright 2010-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +package org.jetbrains.ring + +private const val RUNS = 1_000_000 + +open class InheritanceBenchmark { + + open class A() { + fun a(): Int = 0 + + fun a1(): Int = 1 + fun a2(): Int = 2 + fun a3(): Int = 3 + fun a4(): Int = 4 + fun a5(): Int = 5 + fun a6(): Int = 6 + fun a7(): Int = 7 + fun a8(): Int = 8 + open fun a9(): Int = 9 + open fun a10(): Int = 10 + open fun a11(): Int = 11 + open fun a12(): Int = 12 + open fun a13(): Int = 13 + open fun a14(): Int = 14 + open fun a15(): Int = 15 + open fun a16(): Int = 16 + open fun a17(): Int = 17 + open fun a18(): Int = 18 + open fun a19(): Int = 19 + open fun a20(): Int = 20 + open fun a21(): Int = 21 + open fun a22(): Int = 22 + open fun a23(): Int = 23 + open fun a24(): Int = 24 + open fun a25(): Int = 25 + open fun a26(): Int = 26 + open fun a27(): Int = 27 + open fun a28(): Int = 28 + open fun a29(): Int = 29 + open fun a30(): Int = 30 + open fun a31(): Int = 31 + open fun a32(): Int = 32 + open fun a33(): Int = 33 + open fun a34(): Int = 34 + open fun a35(): Int = 35 + open fun a36(): Int = 36 + open fun a37(): Int = 37 + open fun a38(): Int = 38 + open fun a39(): Int = 39 + open fun a40(): Int = 40 + open fun a41(): Int = 41 + open fun a42(): Int = 42 + open fun a43(): Int = 43 + open fun a44(): Int = 44 + open fun a45(): Int = 45 + open fun a46(): Int = 46 + open fun a47(): Int = 47 + open fun a48(): Int = 48 + open fun a49(): Int = 49 + open fun a50(): Int = 50 + open fun a51(): Int = 51 + open fun a52(): Int = 52 + open fun a53(): Int = 53 + open fun a54(): Int = 54 + open fun a55(): Int = 55 + open fun a56(): Int = 56 + open fun a57(): Int = 57 + open fun a58(): Int = 58 + open fun a59(): Int = 59 + open fun a60(): Int = 60 + open fun a61(): Int = 61 + open fun a62(): Int = 62 + open fun a63(): Int = 63 + open fun a64(): Int = 64 + open fun a65(): Int = 65 + open fun a66(): Int = 66 + open fun a67(): Int = 67 + open fun a68(): Int = 68 + open fun a69(): Int = 69 + open fun a70(): Int = 70 + open fun a71(): Int = 71 + open fun a72(): Int = 72 + open fun a73(): Int = 73 + open fun a74(): Int = 74 + open fun a75(): Int = 75 + open fun a76(): Int = 76 + open fun a77(): Int = 77 + open fun a78(): Int = 78 + open fun a79(): Int = 79 + open fun a80(): Int = 80 + open fun a81(): Int = 81 + open fun a82(): Int = 82 + open fun a83(): Int = 83 + open fun a84(): Int = 84 + open fun a85(): Int = 85 + open fun a86(): Int = 86 + open fun a87(): Int = 87 + open fun a88(): Int = 88 + open fun a89(): Int = 89 + open fun a90(): Int = 90 + open fun a91(): Int = 91 + open fun a92(): Int = 92 + open fun a93(): Int = 93 + open fun a94(): Int = 94 + open fun a95(): Int = 95 + open fun a96(): Int = 96 + open fun a97(): Int = 97 + open fun a98(): Int = 98 + open fun a99(): Int = 99 + + } + + open class B() : A() { + override fun a10(): Int = 0 + + fun b1(): Int = 1 + fun b2(): Int = 2 + fun b3(): Int = 3 + fun b4(): Int = 4 + fun b5(): Int = 5 + open fun b6(): Int = 6 + open fun b7(): Int = 7 + open fun b8(): Int = 8 + open fun b9(): Int = 9 + open fun b10(): Int = 10 + open fun b11(): Int = 11 + open fun b12(): Int = 12 + open fun b13(): Int = 13 + open fun b14(): Int = 14 + open fun b15(): Int = 15 + open fun b16(): Int = 16 + open fun b17(): Int = 17 + open fun b18(): Int = 18 + open fun b19(): Int = 19 + open fun b20(): Int = 20 + open fun b21(): Int = 21 + open fun b22(): Int = 22 + open fun b23(): Int = 23 + open fun b24(): Int = 24 + open fun b25(): Int = 25 + open fun b26(): Int = 26 + open fun b27(): Int = 27 + open fun b28(): Int = 28 + open fun b29(): Int = 29 + open fun b30(): Int = 30 + open fun b31(): Int = 31 + open fun b32(): Int = 32 + open fun b33(): Int = 33 + open fun b34(): Int = 34 + open fun b35(): Int = 35 + open fun b36(): Int = 36 + open fun b37(): Int = 37 + open fun b38(): Int = 38 + open fun b39(): Int = 39 + open fun b40(): Int = 40 + open fun b41(): Int = 41 + open fun b42(): Int = 42 + open fun b43(): Int = 43 + open fun b44(): Int = 44 + open fun b45(): Int = 45 + open fun b46(): Int = 46 + open fun b47(): Int = 47 + open fun b48(): Int = 48 + open fun b49(): Int = 49 + open fun b50(): Int = 50 + open fun b51(): Int = 51 + open fun b52(): Int = 52 + open fun b53(): Int = 53 + open fun b54(): Int = 54 + open fun b55(): Int = 55 + open fun b56(): Int = 56 + open fun b57(): Int = 57 + open fun b58(): Int = 58 + open fun b59(): Int = 59 + open fun b60(): Int = 60 + open fun b61(): Int = 61 + open fun b62(): Int = 62 + open fun b63(): Int = 63 + open fun b64(): Int = 64 + open fun b65(): Int = 65 + open fun b66(): Int = 66 + open fun b67(): Int = 67 + open fun b68(): Int = 68 + open fun b69(): Int = 69 + open fun b70(): Int = 70 + open fun b71(): Int = 71 + open fun b72(): Int = 72 + open fun b73(): Int = 73 + open fun b74(): Int = 74 + open fun b75(): Int = 75 + open fun b76(): Int = 76 + open fun b77(): Int = 77 + open fun b78(): Int = 78 + open fun b79(): Int = 79 + open fun b80(): Int = 80 + open fun b81(): Int = 81 + open fun b82(): Int = 82 + open fun b83(): Int = 83 + open fun b84(): Int = 84 + open fun b85(): Int = 85 + open fun b86(): Int = 86 + open fun b87(): Int = 87 + open fun b88(): Int = 88 + open fun b89(): Int = 89 + open fun b90(): Int = 90 + open fun b91(): Int = 91 + open fun b92(): Int = 92 + open fun b93(): Int = 93 + open fun b94(): Int = 94 + open fun b95(): Int = 95 + open fun b96(): Int = 96 + open fun b97(): Int = 97 + open fun b98(): Int = 98 + open fun b99(): Int = 99 + } + + open class C() : B() { + fun c(): Int = 0 + override fun a10(): Int = 100 + + fun c1(): Int = 1 + fun c2(): Int = 2 + fun c3(): Int = 3 + fun c4(): Int = 4 + fun c5(): Int = 5 + fun c6(): Int = 6 + fun c7(): Int = 7 + fun c8(): Int = 8 + open fun c9(): Int = 9 + open fun c10(): Int = 10 + open fun c11(): Int = 11 + open fun c12(): Int = 12 + open fun c13(): Int = 13 + open fun c14(): Int = 14 + open fun c15(): Int = 15 + open fun c16(): Int = 16 + open fun c17(): Int = 17 + open fun c18(): Int = 18 + open fun c19(): Int = 19 + open fun c20(): Int = 20 + open fun c21(): Int = 21 + open fun c22(): Int = 22 + open fun c23(): Int = 23 + open fun c24(): Int = 24 + open fun c25(): Int = 25 + open fun c26(): Int = 26 + open fun c27(): Int = 27 + open fun c28(): Int = 28 + open fun c29(): Int = 29 + open fun c30(): Int = 30 + open fun c31(): Int = 31 + open fun c32(): Int = 32 + open fun c33(): Int = 33 + open fun c34(): Int = 34 + open fun c35(): Int = 35 + open fun c36(): Int = 36 + open fun c37(): Int = 37 + open fun c38(): Int = 38 + open fun c39(): Int = 39 + open fun c40(): Int = 40 + open fun c41(): Int = 41 + open fun c42(): Int = 42 + open fun c43(): Int = 43 + open fun c44(): Int = 44 + open fun c45(): Int = 45 + open fun c46(): Int = 46 + open fun c47(): Int = 47 + open fun c48(): Int = 48 + open fun c49(): Int = 49 + open fun c50(): Int = 50 + open fun c51(): Int = 51 + open fun c52(): Int = 52 + open fun c53(): Int = 53 + open fun c54(): Int = 54 + open fun c55(): Int = 55 + open fun c56(): Int = 56 + open fun c57(): Int = 57 + open fun c58(): Int = 58 + open fun c59(): Int = 59 + open fun c60(): Int = 60 + open fun c61(): Int = 61 + open fun c62(): Int = 62 + open fun c63(): Int = 63 + open fun c64(): Int = 64 + open fun c65(): Int = 65 + open fun c66(): Int = 66 + open fun c67(): Int = 67 + open fun c68(): Int = 68 + open fun c69(): Int = 69 + open fun c70(): Int = 70 + open fun c71(): Int = 71 + open fun c72(): Int = 72 + open fun c73(): Int = 73 + open fun c74(): Int = 74 + open fun c75(): Int = 75 + open fun c76(): Int = 76 + open fun c77(): Int = 77 + open fun c78(): Int = 78 + open fun c79(): Int = 79 + open fun c80(): Int = 80 + open fun c81(): Int = 81 + open fun c82(): Int = 82 + open fun c83(): Int = 83 + open fun c84(): Int = 84 + open fun c85(): Int = 85 + open fun c86(): Int = 86 + open fun c87(): Int = 87 + open fun c88(): Int = 88 + open fun c89(): Int = 89 + open fun c90(): Int = 90 + open fun c91(): Int = 91 + open fun c92(): Int = 92 + open fun c93(): Int = 93 + open fun c94(): Int = 94 + open fun c95(): Int = 95 + open fun c96(): Int = 96 + open fun c97(): Int = 97 + open fun c98(): Int = 98 + open fun c99(): Int = 99 + } + + open class D() : C() { + override fun a10(): Int = 1000 + fun d(): Int = 0 + + fun d1(): Int = 1 + fun d2(): Int = 2 + fun d3(): Int = 3 + fun d4(): Int = 4 + fun d5(): Int = 5 + fun d6(): Int = 6 + fun d7(): Int = 7 + fun d8(): Int = 8 + open fun d9(): Int = 9 + open fun d10(): Int = 10 + open fun d11(): Int = 11 + open fun d12(): Int = 12 + open fun d13(): Int = 13 + open fun d14(): Int = 14 + open fun d15(): Int = 15 + open fun d16(): Int = 16 + open fun d17(): Int = 17 + open fun d18(): Int = 18 + open fun d19(): Int = 19 + open fun d20(): Int = 20 + open fun d21(): Int = 21 + open fun d22(): Int = 22 + open fun d23(): Int = 23 + open fun d24(): Int = 24 + open fun d25(): Int = 25 + open fun d26(): Int = 26 + open fun d27(): Int = 27 + open fun d28(): Int = 28 + open fun d29(): Int = 29 + open fun d30(): Int = 30 + open fun d31(): Int = 31 + open fun d32(): Int = 32 + open fun d33(): Int = 33 + open fun d34(): Int = 34 + open fun d35(): Int = 35 + open fun d36(): Int = 36 + open fun d37(): Int = 37 + open fun d38(): Int = 38 + open fun d39(): Int = 39 + open fun d40(): Int = 40 + open fun d41(): Int = 41 + open fun d42(): Int = 42 + open fun d43(): Int = 43 + open fun d44(): Int = 44 + open fun d45(): Int = 45 + open fun d46(): Int = 46 + open fun d47(): Int = 47 + open fun d48(): Int = 48 + open fun d49(): Int = 49 + open fun d50(): Int = 50 + open fun d51(): Int = 51 + open fun d52(): Int = 52 + open fun d53(): Int = 53 + open fun d54(): Int = 54 + open fun d55(): Int = 55 + open fun d56(): Int = 56 + open fun d57(): Int = 57 + open fun d58(): Int = 58 + open fun d59(): Int = 59 + open fun d60(): Int = 60 + open fun d61(): Int = 61 + open fun d62(): Int = 62 + open fun d63(): Int = 63 + open fun d64(): Int = 64 + open fun d65(): Int = 65 + open fun d66(): Int = 66 + open fun d67(): Int = 67 + open fun d68(): Int = 68 + open fun d69(): Int = 69 + open fun d70(): Int = 70 + open fun d71(): Int = 71 + open fun d72(): Int = 72 + open fun d73(): Int = 73 + open fun d74(): Int = 74 + open fun d75(): Int = 75 + open fun d76(): Int = 76 + open fun d77(): Int = 77 + open fun d78(): Int = 78 + open fun d79(): Int = 79 + open fun d80(): Int = 80 + open fun d81(): Int = 81 + open fun d82(): Int = 82 + open fun d83(): Int = 83 + open fun d84(): Int = 84 + open fun d85(): Int = 85 + open fun d86(): Int = 86 + open fun d87(): Int = 87 + open fun d88(): Int = 88 + open fun d89(): Int = 89 + open fun d90(): Int = 90 + open fun d91(): Int = 91 + open fun d92(): Int = 92 + open fun d93(): Int = 93 + open fun d94(): Int = 94 + open fun d95(): Int = 95 + open fun d96(): Int = 96 + open fun d97(): Int = 97 + open fun d98(): Int = 98 + open fun d99(): Int = 99 + } + + open class E() : D() { + override fun a10(): Int = 200 + open fun e1(): Int = 1 + open fun e2(): Int = 2 + open fun e3(): Int = 3 + open fun e4(): Int = 4 + open fun e5(): Int = 5 + open fun e6(): Int = 6 + open fun e7(): Int = 7 + open fun e8(): Int = 8 + open fun e9(): Int = 9 + open fun e10(): Int = 10 + open fun e11(): Int = 11 + open fun e12(): Int = 12 + open fun e13(): Int = 13 + open fun e14(): Int = 14 + open fun e15(): Int = 15 + } + + open class F() : E() { + open fun f1(): Int = 1 + open fun f2(): Int = 2 + open fun f3(): Int = 3 + open fun f4(): Int = 4 + open fun f5(): Int = 5 + open fun f6(): Int = 6 + open fun f7(): Int = 7 + open fun f8(): Int = 8 + open fun f9(): Int = 9 + open fun f10(): Int = 10 + open fun f11(): Int = 11 + open fun f12(): Int = 12 + open fun f13(): Int = 13 + open fun f14(): Int = 14 + open fun f15(): Int = 15 + } + + open class G() : F() { + open fun g1(): Int = 1 + open fun g2(): Int = 2 + open fun g3(): Int = 3 + open fun g4(): Int = 4 + open fun g5(): Int = 5 + open fun g6(): Int = 6 + open fun g7(): Int = 7 + open fun g8(): Int = 8 + open fun g9(): Int = 9 + open fun g10(): Int = 10 + open fun g11(): Int = 11 + open fun g12(): Int = 12 + open fun g13(): Int = 13 + open fun g14(): Int = 14 + open fun g15(): Int = 15 + } + + val a = A() + val b = B() + val c = C() + val d = D() + val e = E() + val f = F() + val g = G() + + fun baseCalls(): Int { + var x = 0 + for (i in 0 until RUNS) { + x += a.a() + x += b.a10() + x += c.b20() + x += d.c20() + x += e.d10() + x += f.e10() + x += g.f10() + x += g.g3() + } + return x + } +} \ No newline at end of file diff --git a/kotlin-native/performance/ring/src/main/kotlin/org/jetbrains/ring/InlineBenchmark.kt b/kotlin-native/performance/ring/src/main/kotlin/org/jetbrains/ring/InlineBenchmark.kt new file mode 100644 index 00000000000..54f9c07eba7 --- /dev/null +++ b/kotlin-native/performance/ring/src/main/kotlin/org/jetbrains/ring/InlineBenchmark.kt @@ -0,0 +1,73 @@ +/* + * Copyright 2010-2017 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.jetbrains.ring + +fun load(value: Int, size: Int): Int { + var acc = 0 + for (i in 0..size) { + acc = acc xor value.hashCode() + } + return acc +} + +inline fun loadInline(value: Int, size: Int): Int { + var acc = 0 + for (i in 0..size) { + acc = acc xor value.hashCode() + } + return acc +} + +fun loadGeneric(value: T, size: Int): Int { + var acc = 0 + for (i in 0..size) { + acc = acc xor value.hashCode() + } + return acc +} + +inline fun loadGenericInline(value: T, size: Int): Int { + var acc = 0 + for (i in 0..size) { + acc = acc xor value.hashCode() + } + return acc +} + +open class InlineBenchmark { + private var value = 2138476523 + + //Benchmark + fun calculate(): Int { + return load(value, BENCHMARK_SIZE) + } + + //Benchmark + fun calculateInline(): Int { + return loadInline(value, BENCHMARK_SIZE) + } + + //Benchmark + fun calculateGeneric(): Int { + return loadGeneric(value, BENCHMARK_SIZE) + } + + //Benchmark + fun calculateGenericInline(): Int { + return loadGenericInline(value, BENCHMARK_SIZE) + } +} \ No newline at end of file diff --git a/kotlin-native/performance/ring/src/main/kotlin/org/jetbrains/ring/IntArrayBenchmark.kt b/kotlin-native/performance/ring/src/main/kotlin/org/jetbrains/ring/IntArrayBenchmark.kt new file mode 100644 index 00000000000..53e2ff746aa --- /dev/null +++ b/kotlin-native/performance/ring/src/main/kotlin/org/jetbrains/ring/IntArrayBenchmark.kt @@ -0,0 +1,171 @@ +/* + * Copyright 2010-2017 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.jetbrains.ring + +open class IntArrayBenchmark { + private var _data: IntArray? = null + val data: IntArray + get() = _data!! + + init { + val list = IntArray(BENCHMARK_SIZE) + var index = 0 + for (n in intValues(BENCHMARK_SIZE)) + list[index++] = n + _data = list + } + + //Benchmark + fun copy(): List { + return data.toList() + } + + //Benchmark + fun copyManual(): ArrayList { + val list = ArrayList(data.size) + for (item in data) { + list.add(item) + } + return list + } + + //Benchmark + fun filterAndCount(): Int { + return data.filter { filterLoad(it) }.count() + } + + //Benchmark + fun filterSomeAndCount(): Int { + return data.filter { filterSome(it) }.count() + } + + //Benchmark + fun filterAndMap(): List { + return data.filter { filterLoad(it) }.map { mapLoad(it) } + } + + //Benchmark + fun filterAndMapManual(): ArrayList { + val list = ArrayList() + for (it in data) { + if (filterLoad(it)) { + val value = mapLoad(it) + list.add(value) + } + } + return list + } + + //Benchmark + fun filter(): List { + return data.filter { filterLoad(it) } + } + + //Benchmark + fun filterSome(): List { + return data.filter { filterSome(it) } + } + + //Benchmark + fun filterPrime(): List { + return data.filter { filterPrime(it) } + } + + //Benchmark + fun filterManual(): ArrayList { + val list = ArrayList() + for (it in data) { + if (filterLoad(it)) + list.add(it) + } + return list + } + + //Benchmark + fun filterSomeManual(): ArrayList { + val list = ArrayList() + for (it in data) { + if (filterSome(it)) + list.add(it) + } + return list + } + + //Benchmark + fun countFilteredManual(): Int { + var count = 0 + for (it in data) { + if (filterLoad(it)) + count++ + } + return count + } + + //Benchmark + fun countFilteredSomeManual(): Int { + var count = 0 + for (it in data) { + if (filterSome(it)) + count++ + } + return count + } + + //Benchmark + fun countFilteredPrimeManual(): Int { + var count = 0 + for (it in data) { + if (filterPrime(it)) + count++ + } + return count + } + + + //Benchmark + fun countFiltered(): Int { + return data.count { filterLoad(it) } + } + + //Benchmark + fun countFilteredSome(): Int { + return data.count { filterSome(it) } + } + + //Benchmark + fun countFilteredPrime(): Int { + val res = data.count { filterPrime(it) } + //println(res) + return res + } + + //Benchmark + fun countFilteredLocal(): Int { + return data.cnt { filterLoad(it) } + } + + //Benchmark + fun countFilteredSomeLocal(): Int { + return data.cnt { filterSome(it) } + } + + //Benchmark + fun reduce(): Int { + return data.fold(0) { acc, it -> if (filterLoad(it)) acc + 1 else acc } + } +} + diff --git a/kotlin-native/performance/ring/src/main/kotlin/org/jetbrains/ring/IntBaselineBenchmark.kt b/kotlin-native/performance/ring/src/main/kotlin/org/jetbrains/ring/IntBaselineBenchmark.kt new file mode 100644 index 00000000000..32a152f7cd4 --- /dev/null +++ b/kotlin-native/performance/ring/src/main/kotlin/org/jetbrains/ring/IntBaselineBenchmark.kt @@ -0,0 +1,60 @@ +/* + * Copyright 2010-2017 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.jetbrains.ring + +import org.jetbrains.benchmarksLauncher.Blackhole + +open class IntBaselineBenchmark { + + //Benchmark + fun consume() { + for (item in 1..BENCHMARK_SIZE) { + Blackhole.consume(item) + } + } + + //Benchmark + fun allocateList(): List { + val list = ArrayList(BENCHMARK_SIZE) + return list + } + + //Benchmark + fun allocateArray(): IntArray { + val list = IntArray(BENCHMARK_SIZE) + return list + } + + //Benchmark + fun allocateListAndFill(): List { + val list = ArrayList(BENCHMARK_SIZE) + for (item in 1..BENCHMARK_SIZE) { + list.add(item) + } + return list + } + + //Benchmark + fun allocateArrayAndFill(): IntArray { + var index = 0 + val list = IntArray(BENCHMARK_SIZE) + for (item in 1..BENCHMARK_SIZE) { + list[index++] = item + } + return list + } +} \ No newline at end of file diff --git a/kotlin-native/performance/ring/src/main/kotlin/org/jetbrains/ring/IntListBenchmark.kt b/kotlin-native/performance/ring/src/main/kotlin/org/jetbrains/ring/IntListBenchmark.kt new file mode 100644 index 00000000000..337a815cb44 --- /dev/null +++ b/kotlin-native/performance/ring/src/main/kotlin/org/jetbrains/ring/IntListBenchmark.kt @@ -0,0 +1,106 @@ +/* + * Copyright 2010-2017 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.jetbrains.ring + +open class IntListBenchmark { + private var _data: List? = null + val data: List + get() = _data!! + + init { + val list = ArrayList(BENCHMARK_SIZE) + for (n in intValues(BENCHMARK_SIZE)) + list.add(n) + _data = list + } + + //Benchmark + fun copy(): List { + return data.toList() + } + + //Benchmark + fun copyManual(): List { + val list = ArrayList(data.size) + for (item in data) { + list.add(item) + } + return list + } + + //Benchmark + fun filterAndCount(): Int { + return data.filter { filterLoad(it) }.count() + } + + //Benchmark + fun filterAndMap(): List { + return data.filter { filterLoad(it) }.map { mapLoad(it) } + } + + //Benchmark + fun filterAndMapManual(): ArrayList { + val list = ArrayList() + for (it in data) { + if (filterLoad(it)) { + val value = mapLoad(it) + list.add(value) + } + } + return list + } + + //Benchmark + fun filter(): List { + return data.filter { filterLoad(it) } + } + + //Benchmark + fun filterManual(): List { + val list = ArrayList() + for (it in data) { + if (filterLoad(it)) + list.add(it) + } + return list + } + + //Benchmark + fun countFilteredManual(): Int { + var count = 0 + for (it in data) { + if (filterLoad(it)) + count++ + } + return count + } + + //Benchmark + fun countFiltered(): Int { + return data.count { filterLoad(it) } + } + + //Benchmark + fun countFilteredLocal(): Int { + return data.cnt { filterLoad(it) } + } + + //Benchmark + fun reduce(): Int { + return data.fold(0) { acc, it -> if (filterLoad(it)) acc + 1 else acc } + } +} diff --git a/kotlin-native/performance/ring/src/main/kotlin/org/jetbrains/ring/IntStreamBenchmark.kt b/kotlin-native/performance/ring/src/main/kotlin/org/jetbrains/ring/IntStreamBenchmark.kt new file mode 100644 index 00000000000..49b8bb579c3 --- /dev/null +++ b/kotlin-native/performance/ring/src/main/kotlin/org/jetbrains/ring/IntStreamBenchmark.kt @@ -0,0 +1,103 @@ +/* + * Copyright 2010-2017 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.jetbrains.ring + +import org.jetbrains.benchmarksLauncher.Blackhole + +open class IntStreamBenchmark { + private var _data: Iterable? = null + val data: Iterable + get() = _data!! + + init { + _data = intValues(BENCHMARK_SIZE) + } + + //Benchmark + fun copy(): List { + return data.asSequence().toList() + } + + //Benchmark + fun copyManual(): List { + val list = ArrayList() + for (item in data.asSequence()) { + list.add(item) + } + return list + } + + //Benchmark + fun filterAndCount(): Int { + return data.asSequence().filter { filterLoad(it) }.count() + } + + //Benchmark + fun filterAndMap() { + for (item in data.asSequence().filter { filterLoad(it) }.map { mapLoad(it) }) + Blackhole.consume(item) + } + + //Benchmark + fun filterAndMapManual() { + for (it in data.asSequence()) { + if (filterLoad(it)) { + val item = mapLoad(it) + Blackhole.consume(item) + } + } + } + + //Benchmark + fun filter() { + for (item in data.asSequence().filter { filterLoad(it) }) + Blackhole.consume(item) + } + + //Benchmark + fun filterManual(){ + for (it in data.asSequence()) { + if (filterLoad(it)) + Blackhole.consume(it) + } + } + + //Benchmark + fun countFilteredManual(): Int { + var count = 0 + for (it in data.asSequence()) { + if (filterLoad(it)) + count++ + } + return count + } + + //Benchmark + fun countFiltered(): Int { + return data.asSequence().count { filterLoad(it) } + } + + //Benchmark + fun countFilteredLocal(): Int { + return data.asSequence().cnt { filterLoad(it) } + } + + //Benchmark + fun reduce(): Int { + return data.asSequence().fold(0) {acc, it -> if (filterLoad(it)) acc + 1 else acc } + } +} \ No newline at end of file diff --git a/kotlin-native/performance/ring/src/main/kotlin/org/jetbrains/ring/LambdaBenchmark.kt b/kotlin-native/performance/ring/src/main/kotlin/org/jetbrains/ring/LambdaBenchmark.kt new file mode 100644 index 00000000000..eb03c5cfd60 --- /dev/null +++ b/kotlin-native/performance/ring/src/main/kotlin/org/jetbrains/ring/LambdaBenchmark.kt @@ -0,0 +1,108 @@ +/* + * Copyright 2010-2017 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.jetbrains.ring + +import org.jetbrains.benchmarksLauncher.Random + +var globalAddendum = 0 + +open class LambdaBenchmark { + private inline fun runLambda(x: () -> T): T = x() + private fun runLambdaNoInline(x: () -> T): T = x() + + init { + globalAddendum = Random.nextInt(20) + } + + //Benchmark + fun noncapturingLambda(): Int { + var x: Int = 0 + for (i in 0..BENCHMARK_SIZE) { + x += runLambda { globalAddendum } + } + return x + } + + //Benchmark + fun noncapturingLambdaNoInline(): Int { + var x: Int = 0 + for (i in 0..BENCHMARK_SIZE) { + x += runLambdaNoInline { globalAddendum } + } + return x + } + + //Benchmark + fun capturingLambda(): Int { + val addendum = globalAddendum + 1 + var x: Int = 0 + for (i in 0..BENCHMARK_SIZE) { + x += runLambda { addendum } + } + return x + } + + //Benchmark + fun capturingLambdaNoInline(): Int { + val addendum = globalAddendum + 1 + var x: Int = 0 + for (i in 0..BENCHMARK_SIZE) { + x += runLambdaNoInline { addendum } + } + return x + } + + //Benchmark + fun mutatingLambda(): Int { + var x: Int = 0 + for (i in 0..BENCHMARK_SIZE) { + runLambda { x += globalAddendum } + } + return x + } + + //Benchmark + fun mutatingLambdaNoInline(): Int { + var x: Int = 0 + for (i in 0..BENCHMARK_SIZE) { + runLambdaNoInline { x += globalAddendum } + } + return x + } + + //Benchmark + fun methodReference(): Int { + var x: Int = 0 + for (i in 0..BENCHMARK_SIZE) { + x += runLambda(::referenced) + } + return x + } + + //Benchmark + fun methodReferenceNoInline(): Int { + var x: Int = 0 + for (i in 0..BENCHMARK_SIZE) { + x += runLambdaNoInline(::referenced) + } + return x + } +} + +private fun referenced(): Int { + return globalAddendum +} diff --git a/kotlin-native/performance/ring/src/main/kotlin/org/jetbrains/ring/LinkedListWithAtomicsBenchmark.kt b/kotlin-native/performance/ring/src/main/kotlin/org/jetbrains/ring/LinkedListWithAtomicsBenchmark.kt new file mode 100644 index 00000000000..2015191b2fd --- /dev/null +++ b/kotlin-native/performance/ring/src/main/kotlin/org/jetbrains/ring/LinkedListWithAtomicsBenchmark.kt @@ -0,0 +1,90 @@ +/* + * Copyright 2010-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +package org.jetbrains.ring + +import org.jetbrains.benchmarksLauncher.Random + +class ChunkBuffer(var readPosition: Int, var writePosition: Int = readPosition + Random.nextInt(50)) { + private val nextRef: AtomicRef = atomic(null) + + /** + * Reference to next buffer view. Useful to chain multiple views. + * @see appendNext + * @see cleanNext + */ + var next: ChunkBuffer? get() = nextRef.value + set(newValue) { + if (newValue == null) { + cleanNext() + } else { + appendNext(newValue) + } + } + + fun cleanNext(): ChunkBuffer? { + return nextRef.getAndSet(null) + } + + private fun appendNext(chunk: ChunkBuffer) { + if (!nextRef.compareAndSet(null, chunk)) { + throw IllegalStateException("This chunk has already a next chunk.") + } + } + + inline val readRemaining: Int get() = writePosition - readPosition +} + +fun ChunkBuffer.remainingAll(): Long = remainingAll(0L) + +private tailrec fun ChunkBuffer.remainingAll(n: Long): Long { + val rem = readRemaining.toLong() + n + val next = this.next ?: return rem + return next.remainingAll(rem) +} + +class LinkedListOfBuffers(var head: ChunkBuffer = ChunkBuffer(0,0), + var remaining: Long = head.remainingAll()) { + var tailRemaining: Long = remaining - head.readRemaining + set(newValue) { + if (newValue < 0) { + error("tailRemaining is negative: $newValue") + } + val tailSize = head.next?.remainingAll() ?: 0L + if (newValue == 0L) { + if (tailSize != 0L) { + error("tailRemaining is set 0 while there is a tail of size $tailSize") + } + } + + field = newValue + } +} + +open class LinkedListWithAtomicsBenchmark { + val list: LinkedListOfBuffers + init { + val chunks: MutableList = ArrayList() + (0..BENCHMARK_SIZE/2).forEachIndexed { index, i -> + val chunk = ChunkBuffer(Random.nextInt()) + chunks.add(chunk) + if (i > 0) + chunks[i - 1].next = chunk + } + list = LinkedListOfBuffers(chunks[0]) + } + + tailrec fun ensureNext(current: ChunkBuffer = list.head): ChunkBuffer? { + val next = current.next + return when { + next == null -> null + else -> { + list.tailRemaining = Random.nextInt().toLong() + 1 + ensureNext(next) + } + } + } +} + diff --git a/kotlin-native/performance/ring/src/main/kotlin/org/jetbrains/ring/LocalObjectsBenchmark.kt b/kotlin-native/performance/ring/src/main/kotlin/org/jetbrains/ring/LocalObjectsBenchmark.kt new file mode 100644 index 00000000000..01f421f5a9b --- /dev/null +++ b/kotlin-native/performance/ring/src/main/kotlin/org/jetbrains/ring/LocalObjectsBenchmark.kt @@ -0,0 +1,38 @@ +/* + * Copyright 2010-2017 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.jetbrains.ring + +import org.jetbrains.benchmarksLauncher.Blackhole + +open class LocalObjectsBenchmark { + //Benchmark + fun localArray(): Int { + val size = 48 + val array = IntArray(size) + for (i in 1..size) { + array[i - 1] = i * 2 + } + var result = 0 + for (i in 0 until size) { + result += array[i] + } + if (result > 10) { + return 1 + } + return 2 + } +} diff --git a/kotlin-native/performance/ring/src/main/kotlin/org/jetbrains/ring/LoopBenchmark.kt b/kotlin-native/performance/ring/src/main/kotlin/org/jetbrains/ring/LoopBenchmark.kt new file mode 100644 index 00000000000..72de74fb1b5 --- /dev/null +++ b/kotlin-native/performance/ring/src/main/kotlin/org/jetbrains/ring/LoopBenchmark.kt @@ -0,0 +1,80 @@ +/* + * Copyright 2010-2017 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.jetbrains.ring + +import org.jetbrains.benchmarksLauncher.Blackhole + +open class LoopBenchmark { + lateinit var arrayList: List + lateinit var array: Array + + init { + val list = ArrayList(BENCHMARK_SIZE) + for (n in classValues(BENCHMARK_SIZE)) + list.add(n) + arrayList = list + array = list.toTypedArray() + } + + //Benchmark + fun arrayLoop() { + for (x in array) { + Blackhole.consume(x) + } + } + + //Benchmark + fun arrayIndexLoop() { + for (i in array.indices) { + Blackhole.consume(array[i]) + } + } + + //Benchmark + fun rangeLoop() { + for (i in 0..BENCHMARK_SIZE) { + Blackhole.consume(i) + } + } + + //Benchmark + fun arrayListLoop() { + for (x in arrayList) { + Blackhole.consume(x) + } + } + + //Benchmark + fun arrayWhileLoop() { + var i = 0 + val s = array.size + while (i < s) { + Blackhole.consume(array[i]) + i++ + } + } + + //Benchmark + fun arrayForeachLoop() { + array.forEach { Blackhole.consume(it) } + } + + //Benchmark + fun arrayListForeachLoop() { + arrayList.forEach { Blackhole.consume(it) } + } +} \ No newline at end of file diff --git a/kotlin-native/performance/ring/src/main/kotlin/org/jetbrains/ring/MatrixMapBenchmark.kt b/kotlin-native/performance/ring/src/main/kotlin/org/jetbrains/ring/MatrixMapBenchmark.kt new file mode 100644 index 00000000000..c308d85e8b8 --- /dev/null +++ b/kotlin-native/performance/ring/src/main/kotlin/org/jetbrains/ring/MatrixMapBenchmark.kt @@ -0,0 +1,74 @@ +/* + * Copyright 2010-2017 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.jetbrains.ring + +import org.jetbrains.benchmarksLauncher.Blackhole +import org.jetbrains.benchmarksLauncher.Random + +/** + * This class emulates matrix behaviour using a hash map as its implementation + */ +class KMatrix internal constructor(val rows: Int, val columns: Int) { + private val matrix: MutableMap, Double> = HashMap(); + + init { + for (row in 0..rows-1) { + for (col in 0..columns-1) { + matrix.put(Pair(row, col), Random.nextDouble()) + } + } + } + + fun get(row: Int, col: Int): Double { + return get(Pair(row, col)) + } + + fun get(pair: Pair): Double { + return matrix.getOrElse(pair, { 0.0 }) + } + + fun put(pair: Pair, elem: Double) { + matrix.put(pair, elem) + } + + operator fun plusAssign(other: KMatrix) { + for (entry in matrix.entries) { + put(entry.key, entry.value + other.get(entry.key)) + } + } +} + +/** + * This class tests hash map performance + */ +open class MatrixMapBenchmark { + + //Benchmark + fun add(): KMatrix { + var rows = BENCHMARK_SIZE + var cols = 1 + while (rows > cols) { + rows /= 2 + cols *= 2 + } + val a = KMatrix(rows, cols) + val b = KMatrix(rows, cols) + a += b + return a + } + +} \ No newline at end of file diff --git a/kotlin-native/performance/ring/src/main/kotlin/org/jetbrains/ring/OctoTest/basicTest.kt b/kotlin-native/performance/ring/src/main/kotlin/org/jetbrains/ring/OctoTest/basicTest.kt new file mode 100644 index 00000000000..92344939b5d --- /dev/null +++ b/kotlin-native/performance/ring/src/main/kotlin/org/jetbrains/ring/OctoTest/basicTest.kt @@ -0,0 +1,49 @@ +/** + * Created by semoro on 07.07.17. + */ + +import org.jetbrains.benchmarksLauncher.assert + +fun octoTest() { + val tree = OctoTree(4) + val to = (2 shl tree.depth) + + var x = 0 + var y = 0 + var z = 0 + + while (x < to) { + y = 0 + while (y < to) { + z = 0 + while (z < to) { + val c = (z + to * y + to * to * x) % 2 == 0 + + tree.set(x, y, z, c) + z++ + } + y++ + } + x++ + } + + x = 0 + y = 0 + z = 0 + while (x < to) { + y = 0 + while (y < to) { + z = 0 + while (z < to) { + val c = (z + to * y + to * to * x) % 2 == 0 + + val res = tree.get(x, y, z) + + assert(res == c) + z++ + } + y++ + } + x++ + } +} diff --git a/kotlin-native/performance/ring/src/main/kotlin/org/jetbrains/ring/OctoTest/ocTree.kt b/kotlin-native/performance/ring/src/main/kotlin/org/jetbrains/ring/OctoTest/ocTree.kt new file mode 100644 index 00000000000..37ad4f6630e --- /dev/null +++ b/kotlin-native/performance/ring/src/main/kotlin/org/jetbrains/ring/OctoTest/ocTree.kt @@ -0,0 +1,138 @@ + +open class OctoTree(val depth: Int) { + + private var root: Node? = null + private var actual = false + + //-------------------------------------------------------------------------// + + fun get(x: Int, y: Int, z: Int): T? { + var dep = depth + var iter = root + while (true) { + if (iter == null) return null + else if (iter is Node.Leaf) return iter.value + + iter = (iter as Node.Branch).nodes[number(x, y, z, --dep)] + } + } + + //-------------------------------------------------------------------------// + + fun set(x: Int, y: Int, z: Int, value: T) { + if (root == null) root = Node.Branch() + if (root!!.set(x, y, z, value, depth - 1)) { + root = Node.Leaf(value) + } + actual = false + } + + //-------------------------------------------------------------------------// + + override fun toString(): String = root.toString() + + //-------------------------------------------------------------------------// + + sealed class Node { + + abstract fun set(x: Int, y: Int, z: Int, value: T, depth: Int): Boolean + + //---------------------------------------------------------------------// + + class Leaf(var value: T) : Node() { + + override fun set(x: Int, y: Int, z: Int, value: T, depth: Int): Boolean { + throw UnsupportedOperationException("set on Leaf element") + } + + override fun toString(): String = "L{$value}" + } + + //---------------------------------------------------------------------// + + class Branch() : Node() { + + constructor(value: T, exclude: Int) : this() { + + var i = 0 + while (i < 8) { + if (i != exclude) { + nodes[i] = Leaf(value) + } + i++ + } + } + + private fun canClusterize(value: T): Boolean { + var i = 0 + while (i < 8) { + val w = nodes[i] + if (w == null || w !is Leaf || value != w.value) { + return false + } + i++ + } + return true + } + + override fun set(x: Int, y: Int, z: Int, value: T, depth: Int): Boolean { + val branchIndex = number(x, y, z, depth) + val node = nodes[branchIndex] + when (node) { + null -> { + if (depth == 0) { + nodes[branchIndex] = Leaf(value) + return canClusterize(value) + } else { + nodes[branchIndex] = Branch() + } + } + is Leaf -> { + if (node.value == value) { + return false + } else if (depth == 0) { + node.value = value + return canClusterize(value) + } + nodes[branchIndex] = Branch(node.value, number(x, y, z, depth - 1)) + } + } + + if (nodes[branchIndex]!!.set(x, y, z, value, depth - 1)) { + nodes[branchIndex] = Leaf(value) + return canClusterize(value) + } + return false + } + + val nodes = arrayOfNulls>(8) + override fun toString(): String = nodes.joinToString(prefix = "[", postfix = "]") + } + } + + //-------------------------------------------------------------------------// + + companion object { + fun number(x: Int, y: Int, z: Int, depth: Int): Int { + val mask = 1 shl depth + if (x and mask != 0) { + if (y and mask != 0) { + if (z and mask != 0) + return 7 + return 6 + } + if (z and mask != 0) + return 5 + return 4 + } + if (y and mask != 0) { + if (z and mask != 0) + return 3 + return 2 + } + if (z and mask != 0) + return 1 + return 0 + } + } +} diff --git a/kotlin-native/performance/ring/src/main/kotlin/org/jetbrains/ring/ParameterNotNullAssertionBenchmark.kt b/kotlin-native/performance/ring/src/main/kotlin/org/jetbrains/ring/ParameterNotNullAssertionBenchmark.kt new file mode 100644 index 00000000000..daea0211cb2 --- /dev/null +++ b/kotlin-native/performance/ring/src/main/kotlin/org/jetbrains/ring/ParameterNotNullAssertionBenchmark.kt @@ -0,0 +1,77 @@ +/* + * Copyright 2010-2017 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.jetbrains.ring + +val OBJ = Any() + +open class ParameterNotNullAssertionBenchmark { + + fun methodWithOneNotnullParameter(p: Any): Any { + return p + } + + private fun privateMethodWithOneNotnullParameter(p: Any): Any { + return p + } + + fun methodWithTwoNotnullParameters(p: Any, p2: Any): Any { + return p + } + + private fun privateMethodWithTwoNotnullParameters(p: Any, p2: Any): Any { + return p + } + + fun methodWithEightNotnullParameters(p: Any, p2: Any, p3: Any, p4: Any, p5: Any, p6: Any, p7: Any, p8: Any): Any { + return p + } + + private fun privateMethodWithEightNotnullParameters(p: Any, p2: Any, p3: Any, p4: Any, p5: Any, p6: Any, p7: Any, p8: Any): Any { + return p + } + + //Benchmark + fun invokeOneArgWithNullCheck(): Any { + return methodWithOneNotnullParameter(OBJ) + } + + //Benchmark + fun invokeOneArgWithoutNullCheck(): Any { + return privateMethodWithOneNotnullParameter(OBJ) + } + + //Benchmark + fun invokeTwoArgsWithNullCheck(): Any { + return methodWithTwoNotnullParameters(OBJ, OBJ) + } + + //Benchmark + fun invokeTwoArgsWithoutNullCheck(): Any { + return privateMethodWithTwoNotnullParameters(OBJ, OBJ) + } + + //Benchmark + fun invokeEightArgsWithNullCheck(): Any { + return methodWithEightNotnullParameters(OBJ, OBJ, OBJ, OBJ, OBJ, OBJ, OBJ, OBJ) + } + + //Benchmark + fun invokeEightArgsWithoutNullCheck(): Any { + return privateMethodWithEightNotnullParameters(OBJ, OBJ, OBJ, OBJ, OBJ, OBJ, OBJ, OBJ) + } +} + diff --git a/kotlin-native/performance/ring/src/main/kotlin/org/jetbrains/ring/PrimeListBenchmark.kt b/kotlin-native/performance/ring/src/main/kotlin/org/jetbrains/ring/PrimeListBenchmark.kt new file mode 100644 index 00000000000..c0dbbb3bf9c --- /dev/null +++ b/kotlin-native/performance/ring/src/main/kotlin/org/jetbrains/ring/PrimeListBenchmark.kt @@ -0,0 +1,60 @@ +/* + * Copyright 2010-2017 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.jetbrains.ring + +/** + * This class tests linked list performance + * using prime number calculation algorithms + * + * @author Mikhail Glukhikh + */ +open class PrimeListBenchmark { + private var primes: MutableList = mutableListOf() + + //Benchmark + fun calcDirect() { + primes.clear() + primes.add(2) + var i = 3 + while (i <= BENCHMARK_SIZE) { + var simple = true + for (prime in primes) { + if (prime * prime > i) + break + if (i % prime == 0) { + simple = false + break + } + } + if (simple) + primes.add(i) + i += 2 + } + } + + //Benchmark + fun calcEratosthenes() { + primes.clear() + primes.addAll(2..BENCHMARK_SIZE) + var i = 0 + while (i < primes.size) { + val divisor = primes[i] + primes.removeAll { it -> it > divisor && it % divisor == 0 } + i++ + } + } +} \ No newline at end of file diff --git a/kotlin-native/performance/ring/src/main/kotlin/org/jetbrains/ring/SingletonBenchmark.kt b/kotlin-native/performance/ring/src/main/kotlin/org/jetbrains/ring/SingletonBenchmark.kt new file mode 100644 index 00000000000..104b452bc86 --- /dev/null +++ b/kotlin-native/performance/ring/src/main/kotlin/org/jetbrains/ring/SingletonBenchmark.kt @@ -0,0 +1,27 @@ +/* + * Copyright 2010-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +package org.jetbrains.ring + +import org.jetbrains.benchmarksLauncher.Blackhole +import org.jetbrains.benchmarksLauncher.Random + +private object A { + val a = Random.nextInt(100) +} + +open class SingletonBenchmark { + init { + // Make sure A is initialized. + Blackhole.consume(A.a) + } + + // Benchmark + fun access() { + for (i in 0 until BENCHMARK_SIZE) { + Blackhole.consume(A.a) + } + } +} diff --git a/kotlin-native/performance/ring/src/main/kotlin/org/jetbrains/ring/StringBenchmark.kt b/kotlin-native/performance/ring/src/main/kotlin/org/jetbrains/ring/StringBenchmark.kt new file mode 100644 index 00000000000..257c5055d8b --- /dev/null +++ b/kotlin-native/performance/ring/src/main/kotlin/org/jetbrains/ring/StringBenchmark.kt @@ -0,0 +1,78 @@ +/* + * Copyright 2010-2017 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.jetbrains.ring + +import org.jetbrains.benchmarksLauncher.Random + +open class StringBenchmark { + private var _data: ArrayList? = null + val data: ArrayList + get() = _data!! + var csv: String = "" + + init { + val list = ArrayList(BENCHMARK_SIZE) + for (n in stringValues(BENCHMARK_SIZE)) + list.add(n) + _data = list + csv = "" + for (i in 1..BENCHMARK_SIZE-1) { + val elem = Random.nextDouble() + csv += elem + csv += "," + } + csv += 0.0 + } + + //Benchmark + open fun stringConcat(): String? { + var string: String = "" + for (it in data) string += it + return string + } + + //Benchmark + open fun stringConcatNullable(): String? { + var string: String? = "" + for (it in data) string += it + return string + } + + //Benchmark + open fun stringBuilderConcat(): String { + var string : StringBuilder = StringBuilder("") + for (it in data) string.append(it) + return string.toString() + } + + //Benchmark + open fun stringBuilderConcatNullable(): String { + var string : StringBuilder? = StringBuilder("") + for (it in data) string?.append(it) + return string.toString() + } + + //Benchmark + open fun summarizeSplittedCsv(): Double { + val fields = csv.split(",") + var sum = 0.0 + for (field in fields) { + sum += field.toDouble() + } + return sum + } +} \ No newline at end of file diff --git a/kotlin-native/performance/ring/src/main/kotlin/org/jetbrains/ring/SwitchBenchmark.kt b/kotlin-native/performance/ring/src/main/kotlin/org/jetbrains/ring/SwitchBenchmark.kt new file mode 100644 index 00000000000..463cb2b8ce9 --- /dev/null +++ b/kotlin-native/performance/ring/src/main/kotlin/org/jetbrains/ring/SwitchBenchmark.kt @@ -0,0 +1,674 @@ +/* + * Copyright 2010-2017 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.jetbrains.ring + +import org.jetbrains.benchmarksLauncher.Blackhole +import org.jetbrains.benchmarksLauncher.Random + +val SPARSE_SWITCH_CASES = intArrayOf(11, 29, 47, 71, 103, + 149, 175, 227, 263, 307, + 361, 487, 563, 617, 677, + 751, 823, 883, 967, 1031) + +const val V1 = 1 +const val V2 = 2 +const val V3 = 3 +const val V4 = 4 +const val V5 = 5 +const val V6 = 6 +const val V7 = 7 +const val V8 = 8 +const val V9 = 9 +const val V10 = 10 +const val V11 = 11 +const val V12 = 12 +const val V13 = 13 +const val V14 = 14 +const val V15 = 15 +const val V16 = 16 +const val V17 = 17 +const val V18 = 18 +const val V19 = 19 +const val V20 = 20 + + +object Numbers { + const val V1 = 1 + const val V2 = 2 + const val V3 = 3 + const val V4 = 4 + const val V5 = 5 + const val V6 = 6 + const val V7 = 7 + const val V8 = 8 + const val V9 = 9 + const val V10 = 10 + const val V11 = 11 + const val V12 = 12 + const val V13 = 13 + const val V14 = 14 + const val V15 = 15 + const val V16 = 16 + const val V17 = 17 + const val V18 = 18 + const val V19 = 19 + const val V20 = 20 +} + +var VV1 = 1 +var VV2 = 2 +var VV3 = 3 +var VV4 = 4 +var VV5 = 5 +var VV6 = 6 +var VV7 = 7 +var VV8 = 8 +var VV9 = 9 +var VV10 = 10 +var VV11 = 11 +var VV12 = 12 +var VV13 = 13 +var VV14 = 14 +var VV15 = 15 +var VV16 = 16 +var VV17 = 17 +var VV18 = 18 +var VV19 = 19 +var VV20 = 20 + +open class SwitchBenchmark { + fun sparseIntSwitch(u : Int) : Int { + var t : Int + when (u) { + 11 -> { + t = 1 + } + 29 -> { + t = 2 + } + 47 -> { + t = 3 + } + 71 -> { + t = 4 + } + 103 -> { + t = 5 + } + 149 -> { + t = 6 + } + 175 -> { + t = 7 + } + 227 -> { + t = 1 + } + 263 -> { + t = 9 + } + 307 -> { + t = 1 + } + 361 -> { + t = 2 + } + 487 -> { + t = 3 + } + 563 -> { + t = 4 + } + 617 -> { + t = 4 + } + 677 -> { + t = 4 + } + 751 -> { + t = 435 + } + 823 -> { + t = 31 + } + 883 -> { + t = 1 + } + 967 -> { + t = 1 + } + 1031 -> { + t = 1 + } + 20 -> { + t = 1 + } + else -> { + t = 5 + } + } + return t + } + + fun denseIntSwitch(u : Int) : Int { + var t : Int + when (u) { + 1 -> { + t = 1 + } + -1 -> { + t = 2 + } + 2 -> { + t = 3 + } + 3 -> { + t = 4 + } + 4 -> { + t = 5 + } + 5 -> { + t = 6 + } + 6 -> { + t = 7 + } + 7 -> { + t = 1 + } + 8 -> { + t = 9 + } + 9 -> { + t = 1 + } + 10 -> { + t = 2 + } + 11 -> { + t = 3 + } + 12 -> { + t = 4 + } + 13 -> { + t = 4 + } + 14 -> { + t = 4 + } + 15 -> { + t = 435 + } + 16 -> { + t = 31 + } + 17 -> { + t = 1 + } + 18 -> { + t = 1 + } + 19 -> { + t = 1 + } + 20 -> { + t = 1 + } + else -> { + t = 5 + } + } + return t + } + + fun constSwitch(u : Int) : Int { + var t : Int + when (u) { + V1 -> { + t = 1 + } + V2 -> { + t = 3 + } + V3 -> { + t = 4 + } + V4 -> { + t = 5 + } + V5 -> { + t = 6 + } + V6 -> { + t = 7 + } + V7 -> { + t = 1 + } + V8 -> { + t = 9 + } + V9 -> { + t = 1 + } + V10 -> { + t = 2 + } + V11 -> { + t = 3 + } + V12 -> { + t = 4 + } + V13 -> { + t = 4 + } + V14 -> { + t = 4 + } + V15 -> { + t = 435 + } + V16 -> { + t = 31 + } + V17 -> { + t = 1 + } + V18 -> { + t = 1 + } + V19 -> { + t = 1 + } + V20 -> { + t = 1 + } + else -> { + t = 5 + } + } + return t + } + + fun objConstSwitch(u : Int) : Int { + var t : Int + when (u) { + Numbers.V1 -> { + t = 1 + } + Numbers.V2 -> { + t = 3 + } + Numbers.V3 -> { + t = 4 + } + Numbers.V4 -> { + t = 5 + } + Numbers.V5 -> { + t = 6 + } + Numbers.V6 -> { + t = 7 + } + Numbers.V7 -> { + t = 1 + } + Numbers.V8 -> { + t = 9 + } + Numbers.V9 -> { + t = 1 + } + Numbers.V10 -> { + t = 2 + } + Numbers.V11 -> { + t = 3 + } + Numbers.V12 -> { + t = 4 + } + Numbers.V13 -> { + t = 4 + } + Numbers.V14 -> { + t = 4 + } + Numbers.V15 -> { + t = 435 + } + Numbers.V16 -> { + t = 31 + } + Numbers.V17 -> { + t = 1 + } + Numbers.V18 -> { + t = 1 + } + Numbers.V19 -> { + t = 1 + } + Numbers.V20 -> { + t = 1 + } + else -> { + t = 5 + } + } + return t + } + + fun varSwitch(u : Int) : Int { + var t : Int + when (u) { + VV1 -> { + t = 1 + } + VV2 -> { + t = 3 + } + VV3 -> { + t = 4 + } + VV4 -> { + t = 5 + } + VV5 -> { + t = 6 + } + VV6 -> { + t = 7 + } + VV7 -> { + t = 1 + } + VV8 -> { + t = 9 + } + VV9 -> { + t = 1 + } + VV10 -> { + t = 2 + } + VV11 -> { + t = 3 + } + VV12 -> { + t = 4 + } + VV13 -> { + t = 4 + } + VV14 -> { + t = 4 + } + VV15 -> { + t = 435 + } + VV16 -> { + t = 31 + } + VV17 -> { + t = 1 + } + VV18 -> { + t = 1 + } + VV19 -> { + t = 1 + } + VV20 -> { + t = 1 + } + else -> { + t = 5 + } + } + return t + } + + private fun stringSwitch(s: String) : Int { + when(s) { + "ABCDEFG1" -> return 1 + "ABCDEFG2" -> return 2 + "ABCDEFG2" -> return 3 + "ABCDEFG3" -> return 4 + "ABCDEFG4" -> return 5 + "ABCDEFG5" -> return 6 + "ABCDEFG6" -> return 7 + "ABCDEFG7" -> return 8 + "ABCDEFG8" -> return 9 + "ABCDEFG9" -> return 10 + "ABCDEFG10" -> return 11 + "ABCDEFG11" -> return 12 + "ABCDEFG12" -> return 1 + "ABCDEFG13" -> return 2 + "ABCDEFG14" -> return 3 + "ABCDEFG15" -> return 4 + "ABCDEFG16" -> return 5 + "ABCDEFG17" -> return 6 + "ABCDEFG18" -> return 7 + "ABCDEFG19" -> return 8 + "ABCDEFG20" -> return 9 + else -> return -1 + } + } + + lateinit var denseIntData: IntArray + lateinit var sparseIntData: IntArray + + + + //Benchmark + fun testSparseIntSwitch() { + for (i in sparseIntData) { + Blackhole.consume(sparseIntSwitch(i)) + } + } + + //Benchmark + fun testDenseIntSwitch() { + for (i in denseIntData) { + Blackhole.consume(denseIntSwitch(i)) + } + } + + //Benchmark + fun testConstSwitch() { + for (i in denseIntData) { + Blackhole.consume(constSwitch(i)) + } + } + + //Benchmark + fun testObjConstSwitch() { + for (i in denseIntData) { + Blackhole.consume(objConstSwitch(i)) + } + } + + //Benchmark + fun testVarSwitch() { + for (i in denseIntData) { + Blackhole.consume(varSwitch(i)) + } + } + + var data : Array = arrayOf() + + + + //Benchmark + fun testStringsSwitch() { + val n = data.size + for (s in data) { + Blackhole.consume(stringSwitch(s)) + } + } + + enum class MyEnum { + ITEM1, ITEM2, ITEM3, ITEM4, ITEM5, ITEM6, ITEM7, ITEM8, ITEM9, ITEM10, ITEM11, ITEM12, ITEM13, ITEM14, ITEM15, ITEM16, ITEM17, ITEM18, ITEM19, ITEM20, ITEM21, ITEM22, ITEM23, ITEM24, ITEM25, ITEM26, ITEM27, ITEM28, ITEM29, ITEM30, ITEM31, ITEM32, ITEM33, ITEM34, ITEM35, ITEM36, ITEM37, ITEM38, ITEM39, ITEM40, ITEM41, ITEM42, ITEM43, ITEM44, ITEM45, ITEM46, ITEM47, ITEM48, ITEM49, ITEM50, ITEM51, ITEM52, ITEM53, ITEM54, ITEM55, ITEM56, ITEM57, ITEM58, ITEM59, ITEM60, ITEM61, ITEM62, ITEM63, ITEM64, ITEM65, ITEM66, ITEM67, ITEM68, ITEM69, ITEM70, ITEM71, ITEM72, ITEM73, ITEM74, ITEM75, ITEM76, ITEM77, ITEM78, ITEM79, ITEM80, ITEM81, ITEM82, ITEM83, ITEM84, ITEM85, ITEM86, ITEM87, ITEM88, ITEM89, ITEM90, ITEM91, ITEM92, ITEM93, ITEM94, ITEM95, ITEM96, ITEM97, ITEM98, ITEM99, ITEM100 + } + + private fun enumSwitch(x: MyEnum) : Int { + when (x) { + MyEnum.ITEM5 -> return 1 + MyEnum.ITEM10 -> return 2 + MyEnum.ITEM15 -> return 3 + MyEnum.ITEM20 -> return 4 + MyEnum.ITEM25 -> return 5 + MyEnum.ITEM30 -> return 6 + MyEnum.ITEM35 -> return 7 + MyEnum.ITEM40 -> return 8 + MyEnum.ITEM45 -> return 9 + MyEnum.ITEM50 -> return 10 + MyEnum.ITEM55 -> return 11 + MyEnum.ITEM60 -> return 12 + MyEnum.ITEM65 -> return 13 + MyEnum.ITEM70 -> return 14 + MyEnum.ITEM75 -> return 15 + MyEnum.ITEM80 -> return 16 + MyEnum.ITEM85 -> return 17 + MyEnum.ITEM90 -> return 18 + MyEnum.ITEM95 -> return 19 + MyEnum.ITEM100 -> return 20 + else -> return -1 + } + } + + private fun denseEnumSwitch(x: MyEnum) : Int { + when (x) { + MyEnum.ITEM1 -> return 1 + MyEnum.ITEM2 -> return 2 + MyEnum.ITEM3 -> return 3 + MyEnum.ITEM4 -> return 4 + MyEnum.ITEM5 -> return 5 + MyEnum.ITEM6 -> return 6 + MyEnum.ITEM7 -> return 7 + MyEnum.ITEM8 -> return 8 + MyEnum.ITEM9 -> return 9 + MyEnum.ITEM10 -> return 10 + MyEnum.ITEM11 -> return 11 + MyEnum.ITEM12 -> return 12 + MyEnum.ITEM13 -> return 13 + MyEnum.ITEM14 -> return 14 + MyEnum.ITEM15 -> return 15 + MyEnum.ITEM16 -> return 16 + MyEnum.ITEM17 -> return 17 + MyEnum.ITEM18 -> return 18 + MyEnum.ITEM19 -> return 19 + MyEnum.ITEM20 -> return 20 + else -> return -1 + } + } + + lateinit var enumData : Array + lateinit var denseEnumData : Array + + + + //Benchmark + fun testEnumsSwitch() { + val n = enumData.size -1 + val data = enumData + for (i in 0..n) { + Blackhole.consume(enumSwitch(data[i])) + } + } + + //Benchmark + fun testDenseEnumsSwitch() { + val n = denseEnumData.size -1 + val data = denseEnumData + for (i in 0..n) { + Blackhole.consume(denseEnumSwitch(data[i])) + } + } + + sealed class MySealedClass { + class MySealedClass1: MySealedClass() + class MySealedClass2: MySealedClass() + class MySealedClass3: MySealedClass() + class MySealedClass4: MySealedClass() + class MySealedClass5: MySealedClass() + class MySealedClass6: MySealedClass() + class MySealedClass7: MySealedClass() + class MySealedClass8: MySealedClass() + class MySealedClass9: MySealedClass() + class MySealedClass10: MySealedClass() + } + + lateinit var sealedClassData: Array + + init { + data = Array(BENCHMARK_SIZE) { + "ABCDEFG" + Random.nextInt(22) + } + enumData = Array(BENCHMARK_SIZE) { + MyEnum.values()[it % MyEnum.values().size] + } + denseEnumData = Array(BENCHMARK_SIZE) { + MyEnum.values()[it % 20] + } + denseIntData = IntArray(BENCHMARK_SIZE) { Random.nextInt(25) - 1 } + sparseIntData = IntArray(BENCHMARK_SIZE) { SPARSE_SWITCH_CASES[Random.nextInt(20)] } + sealedClassData = Array(BENCHMARK_SIZE) { + when(Random.nextInt(10)) { + 0 -> MySealedClass.MySealedClass1() + 1 -> MySealedClass.MySealedClass2() + 2 -> MySealedClass.MySealedClass3() + 3 -> MySealedClass.MySealedClass4() + 4 -> MySealedClass.MySealedClass5() + 5 -> MySealedClass.MySealedClass6() + 6 -> MySealedClass.MySealedClass7() + 7 -> MySealedClass.MySealedClass8() + 8 -> MySealedClass.MySealedClass9() + 9 -> MySealedClass.MySealedClass10() + else -> throw IllegalStateException() + } + } + } + + private fun sealedWhenSwitch(x: MySealedClass) : Int = + when (x) { + is MySealedClass.MySealedClass1 -> 1 + is MySealedClass.MySealedClass2 -> 2 + is MySealedClass.MySealedClass3 -> 3 + is MySealedClass.MySealedClass4 -> 4 + is MySealedClass.MySealedClass5 -> 5 + is MySealedClass.MySealedClass6 -> 6 + is MySealedClass.MySealedClass7 -> 7 + is MySealedClass.MySealedClass8 -> 8 + is MySealedClass.MySealedClass9 -> 9 + is MySealedClass.MySealedClass10 -> 10 + } + + + //Benchmark + fun testSealedWhenSwitch() { + val n = sealedClassData.size -1 + for (i in 0..n) { + Blackhole.consume(sealedWhenSwitch(sealedClassData[i])) + } + } +} diff --git a/kotlin-native/performance/ring/src/main/kotlin/org/jetbrains/ring/Utils.kt b/kotlin-native/performance/ring/src/main/kotlin/org/jetbrains/ring/Utils.kt new file mode 100644 index 00000000000..ea1c4439b86 --- /dev/null +++ b/kotlin-native/performance/ring/src/main/kotlin/org/jetbrains/ring/Utils.kt @@ -0,0 +1,43 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.jetbrains.ring + +const val BENCHMARK_SIZE = 10000 + +expect class AtomicRef { + /** + * Reading/writing this property maps to read/write of volatile variable. + */ + public var value: T + + /** + * Maps to [AtomicReferenceFieldUpdater.lazySet]. + */ + public fun lazySet(value: T) + + /** + * Maps to [AtomicReferenceFieldUpdater.compareAndSet]. + */ + public fun compareAndSet(expect: T, update: T): Boolean + + /** + * Maps to [AtomicReferenceFieldUpdater.getAndSet]. + */ + public fun getAndSet(value: T): T +} + +public expect fun atomic(initial: T): AtomicRef diff --git a/kotlin-native/performance/ring/src/main/kotlin/org/jetbrains/ring/WithIndiciesBenchmark.kt b/kotlin-native/performance/ring/src/main/kotlin/org/jetbrains/ring/WithIndiciesBenchmark.kt new file mode 100644 index 00000000000..0753393abee --- /dev/null +++ b/kotlin-native/performance/ring/src/main/kotlin/org/jetbrains/ring/WithIndiciesBenchmark.kt @@ -0,0 +1,54 @@ +/* + * Copyright 2010-2017 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.jetbrains.ring + +import org.jetbrains.benchmarksLauncher.Blackhole + +open class WithIndiciesBenchmark { + private var _data: ArrayList? = null + val data: ArrayList + get() = _data!! + + init { + val list = ArrayList(BENCHMARK_SIZE) + for (n in classValues(BENCHMARK_SIZE)) + list.add(n) + _data = list + } + + //Benchmark + fun withIndicies() { + for ((index, value) in data.withIndex()) { + if (filterLoad(value)) { + Blackhole.consume(index) + Blackhole.consume(value) + } + } + } + + //Benchmark + fun withIndiciesManual() { + var index = 0 + for (value in data) { + if (filterLoad(value)) { + Blackhole.consume(index) + Blackhole.consume(value) + } + index++ + } + } +} diff --git a/kotlin-native/performance/ring/src/main/kotlin/org/jetbrains/ring/zdf-win.kt b/kotlin-native/performance/ring/src/main/kotlin/org/jetbrains/ring/zdf-win.kt new file mode 100644 index 00000000000..7b114f65aba --- /dev/null +++ b/kotlin-native/performance/ring/src/main/kotlin/org/jetbrains/ring/zdf-win.kt @@ -0,0 +1,520 @@ +/* + * Copyright 2010-2017 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.jetbrains.ring + +val zdf_win = listOf( +"-де", +"-ка", +"-либо", +"-нибудь", +"-с", +"-таки", +"-то", +"а", +"а-конто", +"а-ля", +"аба", +"абажур", +"абажурный", +"абаз", +"абазин", +"абазинец", +"абазинка", +"абазинский", +"абак", +"абака", +"аббат", +"аббатиса", +"аббатский", +"аббатство", +"аббревиатура", +"аббревиатурный", +"аббревиация", +"абдикация", +"абдомен", +"абдоминальный", +"абдуктор", +"абдукторный", +"абдукция", +"абелит", +"аберрационный", +"аберрация", +"абзац", +"абзацный", +"абиетин", +"абиетиновый", +"абиссальный", +"абиссинец", +"абиссинский", +"абитуриент", +"абитуриентка", +"абитуриентский", +"аблактировать", +"аблактировка", +"аблятив", +"абляут", +"абляция", +"аболиционизм", +"аболиционист", +"аболиционистский", +"аболиция", +"абонемент", +"абонементный", +"абонент", +"абонентка", +"абонентный", +"абонентский", +"абонирование", +"абонировать", +"абонироваться", +"абордаж", +"абордажный", +"абордировать", +"абориген", +"аборигенный", +"аборт", +"абортарий", +"абортивный", +"абортировать", +"абразив", +"абразивный", +"абразионный", +"абразия", +"абракадабра", +"абреже", +"абрек", +"абрикос", +"абрикосный", +"абрикосовка", +"абрикосовый", +"абрикотин", +"абрис", +"абрисный", +"абсент", +"абсентеизм", +"абсентеист", +"абсолют", +"абсолютивный", +"абсолютизирование", +"абсолютизировать", +"абсолютизм", +"абсолютист", +"абсолютистский", +"абсолютность", +"абсолютный", +"абсолюция", +"абсорбент", +"абсорбер", +"абсорбировать", +"абсорбционный", +"абсорбция", +"абстинент", +"абстрагирование", +"абстрагировать", +"абстрагироваться", +"абстракт", +"абстрактность", +"абстрактный", +"абстракционизм", +"абстракционист", +"абстракционистский", +"абстракция", +"абсурд", +"абсурдность", +"абсурдный", +"абсцесс", +"абсцисса", +"абулия", +"абхаз", +"абхазец", +"абхазка", +"абхазский", +"абцуг", +"абштрих", +"абъюрация", +"абы", +"авалист", +"аваль", +"авангард", +"авангардизм", +"авангардист", +"авангардистский", +"авангардный", +"аванзал", +"аванзальный", +"аванкамера", +"аванложа", +"аванпорт", +"аванпост", +"аванпостный", +"аванс", +"авансирование", +"авансировать", +"авансовый", +"авансом", +"авансцена", +"авантаж", +"авантажный", +"авантюра", +"авантюризм", +"авантюрин", +"авантюриновый", +"авантюрист", +"авантюристический", +"авантюристичный", +"авантюристка", +"авантюристский", +"авантюрность", +"авантюрный", +"авар", +"аварец", +"аварийность", +"аварийный", +"аварийщик", +"авария", +"аварка", +"аварский", +"авгиев", +"авгит", +"авгур", +"август", +"августейший", +"августинец", +"августовский", +"авдотка", +"авеню", +"аверс", +"авестийский", +"авиабаза", +"авиабензин", +"авиагоризонт", +"авиадвигатель", +"авиадесант", +"авиадесантный", +"авиазавод", +"авиаконструктор", +"авиалиния", +"авиаматка", +"авиамоделизм", +"авиамоделист", +"авиамодель", +"авиамодельный", +"авиамотор", +"авиамоторный", +"авианосец", +"авиапочта", +"авиаприбор", +"авиапромышленность", +"авиапромышленный", +"авиаразведка", +"авиастроение", +"авиастроитель", +"авиастроительный", +"авиастроительство", +"авиасъёмка", +"авиатехник", +"авиатор", +"авиаторский", +"авиатранспорт", +"авиатранспортный", +"авиатрасса", +"авиационный", +"авиация", +"авиачасть", +"авиашкола", +"авиетка", +"авизировать", +"авизный", +"авизо", +"авитаминоз", +"авитаминозный", +"авифауна", +"авокадо", +"авось", +"авоська", +"аврал", +"авралить", +"авральный", +"авран", +"аврора", +"австралиец", +"австралийка", +"австралийский", +"австралопитек", +"австриец", +"австрийка", +"австрийский", +"австрияк", +"австриячка", +"австро-венгерский", +"автаркический", +"автаркия", +"авто", +"автобаза", +"автобиографический", +"автобиографичность", +"автобиографичный", +"автобиография", +"автоблокировка", +"автоблокировочный", +"автобус", +"автобусник", +"автобусный", +"автовакцина", +"автовесы", +"автовокзал", +"автогамия", +"автоген", +"автогенез", +"автогенератор", +"автогенный", +"автогенщик", +"автогипноз", +"автогонки", +"автогравюра", +"автограф", +"автографический", +"автография", +"автогужевой", +"автодидакт", +"автодоение", +"автодорожник", +"автодорожный", +"автодрезина", +"автодром", +"автожир", +"автозавод", +"автозаводец", +"автозаводский", +"автозаводской", +"автозаправочный", +"автозаправщик", +"автоинспектор", +"автоинспекция", +"автокар", +"автокара", +"автокатализ", +"автокефалия", +"автокефальный", +"автоклав", +"автоклуб", +"автоколонна", +"автокомбинат", +"автокран", +"автократ", +"автократический", +"автократия", +"автокружок", +"автол", +"автолавка", +"автолиз", +"автолитография", +"автолюбитель", +"автолюбительство", +"автомагистраль", +"автомат", +"автоматизация", +"автоматизирование", +"автоматизировать", +"автоматизироваться", +"автоматизм", +"автоматика", +"автоматический", +"автоматичность", +"автоматичный", +"автоматный", +"автоматчик", +"автоматчица", +"автомашина", +"автомашинист", +"автомеханик", +"автомобилестроение", +"автомобилестроитель", +"автомобилестроительный", +"автомобилизация", +"автомобилизм", +"автомобилист", +"автомобилистка", +"автомобиль", +"автомобильный", +"автомобильчик", +"автоморфизм", +"автомотоклуб", +"автомоторный", +"автомотошкола", +"автомотриса", +"автономист", +"автономистский", +"автономический", +"автономия", +"автономность", +"автономный", +"автопарк", +"автоперевозка", +"автопилот", +"автопластика", +"автоплуг", +"автопогрузчик", +"автоподъёмник", +"автопоезд", +"автопоилка", +"автопокрышка", +"автопортрет", +"автопробег", +"автопромышленность", +"автор", +"авторалли", +"авторегулятор", +"авторемонтник", +"авторемонтный", +"автореферат", +"авторефрижератор", +"авторизация", +"авторизованный", +"авторизовать", +"авторитарность", +"авторитарный", +"авторитет", +"авторитетность", +"авторитетный", +"авторота", +"авторские", +"авторский", +"авторство", +"авторулевой", +"авторучка", +"автосани", +"автосборка", +"автосварщик", +"автоспорт", +"автостанция", +"автостоп", +"автострада", +"автостроение", +"автостроитель", +"автосцепка", +"автотележка", +"автотип", +"автотипический", +"автотипия", +"автотипный", +"автотомия", +"автотормоз", +"автотормозной", +"автотракторный", +"автотранспорт", +"автотранспортный", +"автотрансформатор", +"автотрасса", +"автотуризм", +"автотурист", +"автоукладчик", +"автофургон", +"автохозяйство", +"автохром", +"автохромный", +"автохтон", +"автохтонный", +"автоцистерна", +"авточасть", +"автошкола", +"автоштурман", +"авуары", +"ага", +"ага-хан", +"агава", +"агалит", +"агальматолит", +"агама", +"агами", +"агамия", +"агамогония", +"агар-агар", +"агарный", +"агаровый", +"агарянин", +"агат", +"агатный", +"агатовый", +"агглютинативность", +"агглютинативный", +"агглютинация", +"агглютинин", +"агглютинирующий", +"аггравация", +"агент", +"агентский", +"агентство", +"агентура", +"агентурный", +"агиографический", +"агиография", +"агиология", +"агитатор", +"агитаторский", +"агитаторша", +"агитационный", +"агитация", +"агитбригада", +"агитировать", +"агитка", +"агиткампания", +"агитмассовый", +"агитпоезд", +"агитпроп", +"агитпункт", +"аглицкий", +"агломерат", +"агломератчик", +"агломерационный", +"агломерация", +"агломерировать", +"агломерироваться", +"агнат", +"агнец", +"агнозия", +"агностик", +"агностицизм", +"агностический", +"агонизировать", +"агонический", +"агония", +"агорафобия", +"аграмант", +"аграмантовый", +"аграрий", +"аграрник", +"аграрный", +"аграф", +"аграфия", +"агрегат", +"агрегатный", +"агреман", +"агрессивность", +"агрессивный", +"агрессия", +"агрессор", +"агрикультура", +"агрикультурный", +"агробаза", +"агробиолог", +"агробиологический", +"агробиология", +"агроботаника", +"агрозоотехника", +"агромелиорация" +) diff --git a/kotlin-native/performance/scripts/linux_services.list b/kotlin-native/performance/scripts/linux_services.list new file mode 100644 index 00000000000..c31c07c464e --- /dev/null +++ b/kotlin-native/performance/scripts/linux_services.list @@ -0,0 +1,12 @@ +cups.service +cups.socket +cups.path +cups-browsed +avahi-daemon.socket +avahi-daemon.service +whoopsie.service +upower.service +snapd.socket +snapd.service +bluetooth.target +bluetooth.service \ No newline at end of file diff --git a/kotlin-native/performance/scripts/services.sh b/kotlin-native/performance/scripts/services.sh new file mode 100755 index 00000000000..32e79548557 --- /dev/null +++ b/kotlin-native/performance/scripts/services.sh @@ -0,0 +1,42 @@ +#!/usr/bin/env bash +# Command services.sh -mode [on|off] -gui file_with_servers_list. +MODE=ON +CHANGE_GUI_MODE=0 +if [ "$1" = "-mode" ]; then + shift + if [ "$1" = "off" ]; then + MODE=OFF + fi + shift +fi +if [ "$1" = "-gui" ]; then + CHANGE_GUI_MODE=1 + shift +fi + +INPUT_FILE=$1 +if [ ! -f $INPUT_FILE ]; then + echo "File $INPUT_FILE doesn't exist." + exit 1 +fi + +if [ $CHANGE_GUI_MODE = 1 ]; then + # Turn on/off GUI mode. + if [ "$MODE" = ON ]; then + systemctl enable graphical.target --force + systemctl set-default graphical.target + else + systemctl enable multi-user.target --force + systemctl set-default multi-user.target + fi +fi + +while IFS=$'\r' read -r line || [[ -n "$line" ]]; do + if [ "$MODE" = ON ]; then + systemctl enable $line + systemctl start $line + else + systemctl disable $line + systemctl stop $line + fi +done < "$INPUT_FILE" diff --git a/kotlin-native/performance/shared/src/main/kotlin-jvm/org/jetbrains/benchmarksLauncher/Utils.kt b/kotlin-native/performance/shared/src/main/kotlin-jvm/org/jetbrains/benchmarksLauncher/Utils.kt new file mode 100644 index 00000000000..e19e0936965 --- /dev/null +++ b/kotlin-native/performance/shared/src/main/kotlin-jvm/org/jetbrains/benchmarksLauncher/Utils.kt @@ -0,0 +1,74 @@ +/* + * Copyright 2010-2017 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.jetbrains.benchmarksLauncher + +import java.io.File +import java.text.SimpleDateFormat +import java.util.Date + +actual fun writeToFile(fileName: String, text: String) { + File(fileName).printWriter().use { out -> + out.println(text) + } +} + +// Wrapper for assert funtion in stdlib. +actual fun assert(value: Boolean) { + kotlin.assert(value) +} + +// Wrapper for measureNanoTime funtion in stdlib. +actual inline fun measureNanoTime(block: () -> Unit): Long { + return kotlin.system.measureNanoTime(block) +} + +actual fun cleanup() {} + +actual fun printStderr(message: String) { + System.err.print(message) +} + +actual fun currentTime(): String = + SimpleDateFormat("HH:mm:ss").format(Date()) + +actual fun nanoTime(): Long = System.nanoTime() + +actual class Blackhole { + actual companion object { + actual var consumer = 0 + actual fun consume(value: Any) { + consumer += value.hashCode() + } + } +} + +actual class Random actual constructor() { + actual companion object { + actual var seedInt = 0 + actual fun nextInt(boundary: Int): Int { + seedInt = (3 * seedInt + 11) % boundary + return seedInt + } + + actual var seedDouble: Double = 0.1 + actual fun nextDouble(boundary: Double): Double { + seedDouble = (7.0 * seedDouble + 7.0) % boundary + return seedDouble + } + } +} + diff --git a/kotlin-native/performance/shared/src/main/kotlin-native/common/org/jetbrains/benchmarksLauncher/Utils.kt b/kotlin-native/performance/shared/src/main/kotlin-native/common/org/jetbrains/benchmarksLauncher/Utils.kt new file mode 100644 index 00000000000..7de36732996 --- /dev/null +++ b/kotlin-native/performance/shared/src/main/kotlin-native/common/org/jetbrains/benchmarksLauncher/Utils.kt @@ -0,0 +1,79 @@ +/* + * Copyright 2010-2017 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.jetbrains.benchmarksLauncher + +import kotlin.native.internal.GC +import platform.posix.* +import kotlinx.cinterop.* + +actual fun writeToFile(fileName: String, text: String) { + val file = fopen(fileName, "wt") ?: error("Cannot write file '$fileName'") + try { + if (fputs(text, file) == EOF) throw Error("File write error") + } finally { + fclose(file) + } +} + +// Wrapper for assert funtion in stdlib +actual fun assert(value: Boolean) { + kotlin.assert(value) +} + +// Wrapper for measureNanoTime funtion in stdlib +actual inline fun measureNanoTime(block: () -> Unit): Long { + return kotlin.system.measureNanoTime(block) +} + +actual fun cleanup() { + GC.collect() +} + +actual fun printStderr(message: String) { + val STDERR = fdopen(2, "w") + fprintf(STDERR, message) + fflush(STDERR) +} + +actual fun nanoTime(): Long = kotlin.system.getTimeNanos() + +actual class Blackhole { + @kotlin.native.ThreadLocal + actual companion object { + actual var consumer = 0 + actual fun consume(value: Any) { + consumer += value.hashCode() + } + } +} + +actual class Random actual constructor() { + @kotlin.native.ThreadLocal + actual companion object { + actual var seedInt = 0 + actual fun nextInt(boundary: Int): Int { + seedInt = (3 * seedInt + 11) % boundary + return seedInt + } + + actual var seedDouble: Double = 0.1 + actual fun nextDouble(boundary: Double): Double { + seedDouble = (7.0 * seedDouble + 7.0) % boundary + return seedDouble + } + } +} \ No newline at end of file diff --git a/kotlin-native/performance/shared/src/main/kotlin-native/mingw/org/jetbrains/benchmarksLauncher/Utils.kt b/kotlin-native/performance/shared/src/main/kotlin-native/mingw/org/jetbrains/benchmarksLauncher/Utils.kt new file mode 100644 index 00000000000..73ee1a49f31 --- /dev/null +++ b/kotlin-native/performance/shared/src/main/kotlin-native/mingw/org/jetbrains/benchmarksLauncher/Utils.kt @@ -0,0 +1,34 @@ +/* + * Copyright 2010-2017 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.jetbrains.benchmarksLauncher + +import platform.posix.* +import platform.windows.* +import kotlinx.cinterop.* + +actual fun currentTime() = + memScoped { + val timeVal = alloc() + mingw_gettimeofday(timeVal.ptr, null) + val sec = alloc() + sec.value = timeVal.tv_sec.convert() + val nowtm = localtime(sec.ptr) + var timeBuffer = ByteArray(1024) + strftime(timeBuffer.refTo(0), timeBuffer.size.toULong(), "%H:%M:%S", nowtm) + + timeBuffer.toKString() + } diff --git a/kotlin-native/performance/shared/src/main/kotlin-native/posix/org/jetbrains/benchmarksLauncher/Utils.kt b/kotlin-native/performance/shared/src/main/kotlin-native/posix/org/jetbrains/benchmarksLauncher/Utils.kt new file mode 100644 index 00000000000..3960886916d --- /dev/null +++ b/kotlin-native/performance/shared/src/main/kotlin-native/posix/org/jetbrains/benchmarksLauncher/Utils.kt @@ -0,0 +1,33 @@ +/* + * Copyright 2010-2017 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.jetbrains.benchmarksLauncher + +import platform.posix.* +import kotlinx.cinterop.* + +actual fun currentTime() = + memScoped { + val timeVal = alloc() + gettimeofday(timeVal.ptr, null) + val sec = alloc() + sec.value = timeVal.tv_sec + val nowtm = localtime(sec.ptr) + var timeBuffer = ByteArray(1024) + strftime(timeBuffer.refTo(0), timeBuffer.size.toULong(), "%H:%M:%S", nowtm) + + timeBuffer.toKString() + } diff --git a/kotlin-native/performance/shared/src/main/kotlin/org/jetbrains/benchmarksLauncher/BenchmarksCollection.kt b/kotlin-native/performance/shared/src/main/kotlin/org/jetbrains/benchmarksLauncher/BenchmarksCollection.kt new file mode 100644 index 00000000000..71045bccdc3 --- /dev/null +++ b/kotlin-native/performance/shared/src/main/kotlin/org/jetbrains/benchmarksLauncher/BenchmarksCollection.kt @@ -0,0 +1,42 @@ +/* + * Copyright 2010-2017 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.jetbrains.benchmarksLauncher + +import org.jetbrains.report.BenchmarkResult + +interface AbstractBenchmarkEntry { + open val useAutoEvaluatedNumberOfMeasure: Boolean +} + +class BenchmarkEntryWithInit(val ctor: ()->Any, val lambda: (Any) -> Any?): AbstractBenchmarkEntry { + companion object { + inline fun create(noinline ctor: ()->T, crossinline lambda: T.() -> Any?) = BenchmarkEntryWithInit(ctor) { (it as T).lambda() } + } + + override val useAutoEvaluatedNumberOfMeasure: Boolean = true +} + +open class BenchmarkEntry(val lambda: () -> Any?) : AbstractBenchmarkEntry { + override val useAutoEvaluatedNumberOfMeasure: Boolean = true +} + +class BenchmarkEntryManual(lambda: () -> Any?) : BenchmarkEntry(lambda) { + override val useAutoEvaluatedNumberOfMeasure: Boolean = false +} + +class BenchmarksCollection(private val benchmarks: MutableMap = mutableMapOf()) : + MutableMap by benchmarks diff --git a/kotlin-native/performance/shared/src/main/kotlin/org/jetbrains/benchmarksLauncher/JsonReportCreator.kt b/kotlin-native/performance/shared/src/main/kotlin/org/jetbrains/benchmarksLauncher/JsonReportCreator.kt new file mode 100644 index 00000000000..5da9465c67f --- /dev/null +++ b/kotlin-native/performance/shared/src/main/kotlin/org/jetbrains/benchmarksLauncher/JsonReportCreator.kt @@ -0,0 +1,28 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.jetbrains.benchmarksLauncher + +import org.jetbrains.report.BenchmarkResult + +class JsonReportCreator(val data: Iterable) { + fun printJsonReport(jsonReport: String?): Unit { + val reportText = data.joinToString(prefix = "[", postfix = "]") { + it.toJson() + } + jsonReport?.let { writeToFile(it, reportText) } ?: print(reportText) + } +} \ No newline at end of file diff --git a/kotlin-native/performance/shared/src/main/kotlin/org/jetbrains/benchmarksLauncher/SwiftLauncher.kt b/kotlin-native/performance/shared/src/main/kotlin/org/jetbrains/benchmarksLauncher/SwiftLauncher.kt new file mode 100644 index 00000000000..15bd7099b54 --- /dev/null +++ b/kotlin-native/performance/shared/src/main/kotlin/org/jetbrains/benchmarksLauncher/SwiftLauncher.kt @@ -0,0 +1,14 @@ +/* + * Copyright 2010-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +import org.jetbrains.benchmarksLauncher.* +import kotlinx.cli.* + +class SwiftLauncher: Launcher() { + override val benchmarks = BenchmarksCollection( + mutableMapOf( + ) + ) +} \ No newline at end of file diff --git a/kotlin-native/performance/shared/src/main/kotlin/org/jetbrains/benchmarksLauncher/Utils.kt b/kotlin-native/performance/shared/src/main/kotlin/org/jetbrains/benchmarksLauncher/Utils.kt new file mode 100644 index 00000000000..bfa1a4fe350 --- /dev/null +++ b/kotlin-native/performance/shared/src/main/kotlin/org/jetbrains/benchmarksLauncher/Utils.kt @@ -0,0 +1,48 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.jetbrains.benchmarksLauncher + +expect fun writeToFile(fileName: String, text: String) + +expect fun assert(value: Boolean) + +expect inline fun measureNanoTime(block: () -> Unit): Long + +expect fun cleanup() + +expect fun printStderr(message: String) + +expect fun currentTime(): String + +expect fun nanoTime(): Long + +expect class Blackhole { + companion object { + var consumer: Int + fun consume(value: Any) + } +} + +expect class Random() { + companion object { + var seedInt: Int + fun nextInt(boundary: Int = 100): Int + + var seedDouble: Double + fun nextDouble(boundary: Double = 100.0): Double + } +} \ No newline at end of file diff --git a/kotlin-native/performance/shared/src/main/kotlin/org/jetbrains/benchmarksLauncher/launcher.kt b/kotlin-native/performance/shared/src/main/kotlin/org/jetbrains/benchmarksLauncher/launcher.kt new file mode 100644 index 00000000000..e0749222915 --- /dev/null +++ b/kotlin-native/performance/shared/src/main/kotlin/org/jetbrains/benchmarksLauncher/launcher.kt @@ -0,0 +1,199 @@ +/* + * Copyright 2010-2017 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +@file:OptIn(ExperimentalCli::class) +package org.jetbrains.benchmarksLauncher + +import org.jetbrains.report.BenchmarkResult +import kotlinx.cli.* + +data class RecordTimeMeasurement( + val status: BenchmarkResult.Status, + val iteration: Int, + val warmupCount: Int, + val durationNs: Double) + +abstract class Launcher { + abstract val benchmarks: BenchmarksCollection + + fun add(name: String, benchmark: AbstractBenchmarkEntry) { + benchmarks[name] = benchmark + } + + fun runBenchmark(benchmarkInstance: Any?, benchmark: AbstractBenchmarkEntry, repeatNumber: Int): Long { + var i = repeatNumber + return if (benchmark is BenchmarkEntryWithInit) { + cleanup() + measureNanoTime { + while (i-- > 0) benchmark.lambda(benchmarkInstance!!) + cleanup() + } + } else if (benchmark is BenchmarkEntry) { + cleanup() + measureNanoTime { + while (i-- > 0) benchmark.lambda() + cleanup() + } + } else if (benchmark is BenchmarkEntryManual) { + error("runBenchmark cannot run manual benchmark") + } else { + error("Unknown benchmark type $benchmark") + } + } + + enum class LogLevel { DEBUG, OFF } + + class Logger(val level: LogLevel = LogLevel.OFF) { + fun log(message: String, messageLevel: LogLevel = LogLevel.DEBUG, usePrefix: Boolean = true) { + if (messageLevel == level) { + if (usePrefix) { + printStderr("[$level][${currentTime()}] $message") + } else { + printStderr("$message") + } + } + } + } + + fun runBenchmark(logger: Logger, + numWarmIterations: Int, + numberOfAttempts: Int, + name: String, + recordMeasurement: (RecordTimeMeasurement) -> Unit, + benchmark: AbstractBenchmarkEntry) { + val benchmarkInstance = (benchmark as? BenchmarkEntryWithInit)?.ctor?.invoke() + logger.log("Warm up iterations for benchmark $name\n") + runBenchmark(benchmarkInstance, benchmark, numWarmIterations) + val expectedDuration = 2000L * 1_000_000 // 2s + var autoEvaluatedNumberOfMeasureIteration = 1 + if (benchmark.useAutoEvaluatedNumberOfMeasure) { + val time = runBenchmark(benchmarkInstance, benchmark, 1) + if (time < expectedDuration) + // Made auto evaluated number of measurements to be a multiple of 4. + // Loops which iteration number is a multiple of 4 execute optimally, + // because of different optimizations on processor (e.g. LSD) + autoEvaluatedNumberOfMeasureIteration = ((expectedDuration / time).toInt() / 4 + 1) * 4 + } + logger.log("Running benchmark $name ") + for (k in 0.until(numberOfAttempts)) { + logger.log(".", usePrefix = false) + var i = autoEvaluatedNumberOfMeasureIteration + val time = runBenchmark(benchmarkInstance, benchmark, i) + val scaledTime = time * 1.0 / autoEvaluatedNumberOfMeasureIteration + // Save benchmark object + recordMeasurement(RecordTimeMeasurement(BenchmarkResult.Status.PASSED, k, numWarmIterations, scaledTime)) + } + logger.log("\n", usePrefix = false) + } + + fun launch(numWarmIterations: Int, + numberOfAttempts: Int, + prefix: String = "", + filters: Collection? = null, + filterRegexes: Collection? = null, + verbose: Boolean): List { + val logger = if (verbose) Logger(LogLevel.DEBUG) else Logger() + val regexes = filterRegexes?.map { it.toRegex() } ?: listOf() + val filterSet = filters?.toHashSet() ?: hashSetOf() + // Filter benchmarks using given filters, or run all benchmarks if none were given. + val runningBenchmarks = if (filterSet.isNotEmpty() || regexes.isNotEmpty()) { + benchmarks.filterKeys { benchmark -> benchmark in filterSet || regexes.any { it.matches(benchmark) } } + } else benchmarks + if (runningBenchmarks.isEmpty()) { + printStderr("No matching benchmarks found\n") + error("No matching benchmarks found") + } + val benchmarkResults = mutableListOf() + for ((name, benchmark) in runningBenchmarks) { + val recordMeasurement : (RecordTimeMeasurement) -> Unit = { + benchmarkResults.add(BenchmarkResult( + "$prefix$name", + it.status, + it.durationNs / 1000, + BenchmarkResult.Metric.EXECUTION_TIME, + it.durationNs / 1000, + it.iteration + 1, + it.warmupCount)) + } + try { + runBenchmark(logger, numWarmIterations, numberOfAttempts, name, recordMeasurement, benchmark) + } catch (e: Throwable) { + printStderr("Failure while running benchmark $name: $e\n") + benchmarkResults.add(BenchmarkResult( + "$prefix$name", BenchmarkResult.Status.FAILED, 0.0, + BenchmarkResult.Metric.EXECUTION_TIME, 0.0, numberOfAttempts, numWarmIterations) + ) + } + } + return benchmarkResults + } + + fun benchmarksListAction() { + benchmarks.keys.forEach { + println(it) + } + } +} + +abstract class BenchmarkArguments(argParser: ArgParser) + +class BaseBenchmarkArguments(argParser: ArgParser): BenchmarkArguments(argParser) { + val warmup by argParser.option(ArgType.Int, shortName = "w", description = "Number of warm up iterations") + .default(20) + val repeat by argParser.option(ArgType.Int, shortName = "r", description = "Number of each benchmark run"). + default(60) + val prefix by argParser.option(ArgType.String, shortName = "p", description = "Prefix added to benchmark name") + .default("") + val output by argParser.option(ArgType.String, shortName = "o", description = "Output file") + val filter by argParser.option(ArgType.String, shortName = "f", description = "Benchmark to run").multiple() + val filterRegex by argParser.option(ArgType.String, shortName = "fr", + description = "Benchmark to run, described by a regular expression").multiple() + val verbose by argParser.option(ArgType.Boolean, shortName = "v", description = "Verbose mode of running") + .default(false) +} + +object BenchmarksRunner { + fun parse(args: Array, benchmarksListAction: ()->Unit): BenchmarkArguments? { + class List: Subcommand("list", "Show list of benchmarks") { + override fun execute() { + benchmarksListAction() + } + } + + // Parse args. + val argParser = ArgParser("benchmark") + argParser.subcommands(List()) + val argumentsValues = BaseBenchmarkArguments(argParser) + return if (argParser.parse(args).commandName == "benchmark") argumentsValues else null + } + + fun collect(results: List, arguments: BenchmarkArguments) { + if (arguments is BaseBenchmarkArguments) { + JsonReportCreator(results).printJsonReport(arguments.output) + } + } + + fun runBenchmarks(args: Array, + run: (parser: BenchmarkArguments) -> List, + parseArgs: (args: Array, benchmarksListAction: ()->Unit) -> BenchmarkArguments? = this::parse, + collect: (results: List, arguments: BenchmarkArguments) -> Unit = this::collect, + benchmarksListAction: ()->Unit) { + val arguments = parseArgs(args, benchmarksListAction) + arguments?.let { + val results = run(arguments) + collect(results, arguments) + } + } +} diff --git a/kotlin-native/performance/startup/build.gradle.kts b/kotlin-native/performance/startup/build.gradle.kts new file mode 100644 index 00000000000..df66b9598f2 --- /dev/null +++ b/kotlin-native/performance/startup/build.gradle.kts @@ -0,0 +1,27 @@ +import org.jetbrains.kotlin.gradle.plugin.mpp.NativeBuildType +import org.jetbrains.kotlin.RunKotlinNativeTask +import org.jetbrains.kotlin.BenchmarkRepeatingType + +/* + * Copyright 2010-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +plugins { + id("benchmarking") +} + +val defaultBuildType = NativeBuildType.RELEASE + +benchmark { + applicationName = "Startup" + commonSrcDirs = listOf("../../tools/benchmarks/shared/src/main/kotlin/report", "src/main/kotlin", "../shared/src/main/kotlin") + jvmSrcDirs = listOf("../shared/src/main/kotlin-jvm") + nativeSrcDirs = listOf("../shared/src/main/kotlin-native/common") + mingwSrcDirs = listOf("../shared/src/main/kotlin-native/mingw") + posixSrcDirs = listOf("../shared/src/main/kotlin-native/posix") + buildType = (findProperty("nativeBuildType") as String?)?.let { NativeBuildType.valueOf(it) } ?: defaultBuildType + repeatingType = BenchmarkRepeatingType.EXTERNAL + + dependencies.common(project(":endorsedLibraries:kotlinx.cli")) +} diff --git a/kotlin-native/performance/startup/gradle.properties b/kotlin-native/performance/startup/gradle.properties new file mode 100644 index 00000000000..e8944cc8966 --- /dev/null +++ b/kotlin-native/performance/startup/gradle.properties @@ -0,0 +1 @@ +kotlin.native.home=../../dist diff --git a/kotlin-native/performance/startup/src/main/kotlin/main.kt b/kotlin-native/performance/startup/src/main/kotlin/main.kt new file mode 100644 index 00000000000..223c44fe7b6 --- /dev/null +++ b/kotlin-native/performance/startup/src/main/kotlin/main.kt @@ -0,0 +1,27 @@ +/* + * Copyright 2010-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +import org.jetbrains.startup.* +import org.jetbrains.benchmarksLauncher.* +import kotlinx.cli.* + +class StartupLauncher : Launcher() { + override val benchmarks = BenchmarksCollection( + mutableMapOf( + "Singleton.initialize" to BenchmarkEntryManual(::singletonInitialize), + "Singleton.initializeNested" to BenchmarkEntryManual(::singletonInitializeNested), + ) + ) +} + +fun main(args: Array) { + val launcher = StartupLauncher() + BenchmarksRunner.runBenchmarks(args, { arguments: BenchmarkArguments -> + if (arguments is BaseBenchmarkArguments) { + launcher.launch(arguments.warmup, arguments.repeat, arguments.prefix, + arguments.filter, arguments.filterRegex, arguments.verbose) + } else emptyList() + }, benchmarksListAction = launcher::benchmarksListAction) +} diff --git a/kotlin-native/performance/startup/src/main/kotlin/org/jetbrains/startup/SingletonInitBenchmark.kt b/kotlin-native/performance/startup/src/main/kotlin/org/jetbrains/startup/SingletonInitBenchmark.kt new file mode 100644 index 00000000000..bbca3561eec --- /dev/null +++ b/kotlin-native/performance/startup/src/main/kotlin/org/jetbrains/startup/SingletonInitBenchmark.kt @@ -0,0 +1,1539 @@ +/* + * Copyright 2010-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +package org.jetbrains.startup + +import org.jetbrains.benchmarksLauncher.measureNanoTime +import org.jetbrains.benchmarksLauncher.Random +import org.jetbrains.report.BenchmarkResult + +private object A0 { val a = Random.nextInt(100) } +private object A1 { val a = Random.nextInt(100) } +private object A2 { val a = Random.nextInt(100) } +private object A3 { val a = Random.nextInt(100) } +private object A4 { val a = Random.nextInt(100) } +private object A5 { val a = Random.nextInt(100) } +private object A6 { val a = Random.nextInt(100) } +private object A7 { val a = Random.nextInt(100) } +private object A8 { val a = Random.nextInt(100) } +private object A9 { val a = Random.nextInt(100) } +private object A10 { val a = Random.nextInt(100) } +private object A11 { val a = Random.nextInt(100) } +private object A12 { val a = Random.nextInt(100) } +private object A13 { val a = Random.nextInt(100) } +private object A14 { val a = Random.nextInt(100) } +private object A15 { val a = Random.nextInt(100) } +private object A16 { val a = Random.nextInt(100) } +private object A17 { val a = Random.nextInt(100) } +private object A18 { val a = Random.nextInt(100) } +private object A19 { val a = Random.nextInt(100) } +private object A20 { val a = Random.nextInt(100) } +private object A21 { val a = Random.nextInt(100) } +private object A22 { val a = Random.nextInt(100) } +private object A23 { val a = Random.nextInt(100) } +private object A24 { val a = Random.nextInt(100) } +private object A25 { val a = Random.nextInt(100) } +private object A26 { val a = Random.nextInt(100) } +private object A27 { val a = Random.nextInt(100) } +private object A28 { val a = Random.nextInt(100) } +private object A29 { val a = Random.nextInt(100) } +private object A30 { val a = Random.nextInt(100) } +private object A31 { val a = Random.nextInt(100) } +private object A32 { val a = Random.nextInt(100) } +private object A33 { val a = Random.nextInt(100) } +private object A34 { val a = Random.nextInt(100) } +private object A35 { val a = Random.nextInt(100) } +private object A36 { val a = Random.nextInt(100) } +private object A37 { val a = Random.nextInt(100) } +private object A38 { val a = Random.nextInt(100) } +private object A39 { val a = Random.nextInt(100) } +private object A40 { val a = Random.nextInt(100) } +private object A41 { val a = Random.nextInt(100) } +private object A42 { val a = Random.nextInt(100) } +private object A43 { val a = Random.nextInt(100) } +private object A44 { val a = Random.nextInt(100) } +private object A45 { val a = Random.nextInt(100) } +private object A46 { val a = Random.nextInt(100) } +private object A47 { val a = Random.nextInt(100) } +private object A48 { val a = Random.nextInt(100) } +private object A49 { val a = Random.nextInt(100) } +private object A50 { val a = Random.nextInt(100) } +private object A51 { val a = Random.nextInt(100) } +private object A52 { val a = Random.nextInt(100) } +private object A53 { val a = Random.nextInt(100) } +private object A54 { val a = Random.nextInt(100) } +private object A55 { val a = Random.nextInt(100) } +private object A56 { val a = Random.nextInt(100) } +private object A57 { val a = Random.nextInt(100) } +private object A58 { val a = Random.nextInt(100) } +private object A59 { val a = Random.nextInt(100) } +private object A60 { val a = Random.nextInt(100) } +private object A61 { val a = Random.nextInt(100) } +private object A62 { val a = Random.nextInt(100) } +private object A63 { val a = Random.nextInt(100) } +private object A64 { val a = Random.nextInt(100) } +private object A65 { val a = Random.nextInt(100) } +private object A66 { val a = Random.nextInt(100) } +private object A67 { val a = Random.nextInt(100) } +private object A68 { val a = Random.nextInt(100) } +private object A69 { val a = Random.nextInt(100) } +private object A70 { val a = Random.nextInt(100) } +private object A71 { val a = Random.nextInt(100) } +private object A72 { val a = Random.nextInt(100) } +private object A73 { val a = Random.nextInt(100) } +private object A74 { val a = Random.nextInt(100) } +private object A75 { val a = Random.nextInt(100) } +private object A76 { val a = Random.nextInt(100) } +private object A77 { val a = Random.nextInt(100) } +private object A78 { val a = Random.nextInt(100) } +private object A79 { val a = Random.nextInt(100) } +private object A80 { val a = Random.nextInt(100) } +private object A81 { val a = Random.nextInt(100) } +private object A82 { val a = Random.nextInt(100) } +private object A83 { val a = Random.nextInt(100) } +private object A84 { val a = Random.nextInt(100) } +private object A85 { val a = Random.nextInt(100) } +private object A86 { val a = Random.nextInt(100) } +private object A87 { val a = Random.nextInt(100) } +private object A88 { val a = Random.nextInt(100) } +private object A89 { val a = Random.nextInt(100) } +private object A90 { val a = Random.nextInt(100) } +private object A91 { val a = Random.nextInt(100) } +private object A92 { val a = Random.nextInt(100) } +private object A93 { val a = Random.nextInt(100) } +private object A94 { val a = Random.nextInt(100) } +private object A95 { val a = Random.nextInt(100) } +private object A96 { val a = Random.nextInt(100) } +private object A97 { val a = Random.nextInt(100) } +private object A98 { val a = Random.nextInt(100) } +private object A99 { val a = Random.nextInt(100) } +private object A100 { val a = Random.nextInt(100) } +private object A101 { val a = Random.nextInt(100) } +private object A102 { val a = Random.nextInt(100) } +private object A103 { val a = Random.nextInt(100) } +private object A104 { val a = Random.nextInt(100) } +private object A105 { val a = Random.nextInt(100) } +private object A106 { val a = Random.nextInt(100) } +private object A107 { val a = Random.nextInt(100) } +private object A108 { val a = Random.nextInt(100) } +private object A109 { val a = Random.nextInt(100) } +private object A110 { val a = Random.nextInt(100) } +private object A111 { val a = Random.nextInt(100) } +private object A112 { val a = Random.nextInt(100) } +private object A113 { val a = Random.nextInt(100) } +private object A114 { val a = Random.nextInt(100) } +private object A115 { val a = Random.nextInt(100) } +private object A116 { val a = Random.nextInt(100) } +private object A117 { val a = Random.nextInt(100) } +private object A118 { val a = Random.nextInt(100) } +private object A119 { val a = Random.nextInt(100) } +private object A120 { val a = Random.nextInt(100) } +private object A121 { val a = Random.nextInt(100) } +private object A122 { val a = Random.nextInt(100) } +private object A123 { val a = Random.nextInt(100) } +private object A124 { val a = Random.nextInt(100) } +private object A125 { val a = Random.nextInt(100) } +private object A126 { val a = Random.nextInt(100) } +private object A127 { val a = Random.nextInt(100) } +private object A128 { val a = Random.nextInt(100) } +private object A129 { val a = Random.nextInt(100) } +private object A130 { val a = Random.nextInt(100) } +private object A131 { val a = Random.nextInt(100) } +private object A132 { val a = Random.nextInt(100) } +private object A133 { val a = Random.nextInt(100) } +private object A134 { val a = Random.nextInt(100) } +private object A135 { val a = Random.nextInt(100) } +private object A136 { val a = Random.nextInt(100) } +private object A137 { val a = Random.nextInt(100) } +private object A138 { val a = Random.nextInt(100) } +private object A139 { val a = Random.nextInt(100) } +private object A140 { val a = Random.nextInt(100) } +private object A141 { val a = Random.nextInt(100) } +private object A142 { val a = Random.nextInt(100) } +private object A143 { val a = Random.nextInt(100) } +private object A144 { val a = Random.nextInt(100) } +private object A145 { val a = Random.nextInt(100) } +private object A146 { val a = Random.nextInt(100) } +private object A147 { val a = Random.nextInt(100) } +private object A148 { val a = Random.nextInt(100) } +private object A149 { val a = Random.nextInt(100) } +private object A150 { val a = Random.nextInt(100) } +private object A151 { val a = Random.nextInt(100) } +private object A152 { val a = Random.nextInt(100) } +private object A153 { val a = Random.nextInt(100) } +private object A154 { val a = Random.nextInt(100) } +private object A155 { val a = Random.nextInt(100) } +private object A156 { val a = Random.nextInt(100) } +private object A157 { val a = Random.nextInt(100) } +private object A158 { val a = Random.nextInt(100) } +private object A159 { val a = Random.nextInt(100) } +private object A160 { val a = Random.nextInt(100) } +private object A161 { val a = Random.nextInt(100) } +private object A162 { val a = Random.nextInt(100) } +private object A163 { val a = Random.nextInt(100) } +private object A164 { val a = Random.nextInt(100) } +private object A165 { val a = Random.nextInt(100) } +private object A166 { val a = Random.nextInt(100) } +private object A167 { val a = Random.nextInt(100) } +private object A168 { val a = Random.nextInt(100) } +private object A169 { val a = Random.nextInt(100) } +private object A170 { val a = Random.nextInt(100) } +private object A171 { val a = Random.nextInt(100) } +private object A172 { val a = Random.nextInt(100) } +private object A173 { val a = Random.nextInt(100) } +private object A174 { val a = Random.nextInt(100) } +private object A175 { val a = Random.nextInt(100) } +private object A176 { val a = Random.nextInt(100) } +private object A177 { val a = Random.nextInt(100) } +private object A178 { val a = Random.nextInt(100) } +private object A179 { val a = Random.nextInt(100) } +private object A180 { val a = Random.nextInt(100) } +private object A181 { val a = Random.nextInt(100) } +private object A182 { val a = Random.nextInt(100) } +private object A183 { val a = Random.nextInt(100) } +private object A184 { val a = Random.nextInt(100) } +private object A185 { val a = Random.nextInt(100) } +private object A186 { val a = Random.nextInt(100) } +private object A187 { val a = Random.nextInt(100) } +private object A188 { val a = Random.nextInt(100) } +private object A189 { val a = Random.nextInt(100) } +private object A190 { val a = Random.nextInt(100) } +private object A191 { val a = Random.nextInt(100) } +private object A192 { val a = Random.nextInt(100) } +private object A193 { val a = Random.nextInt(100) } +private object A194 { val a = Random.nextInt(100) } +private object A195 { val a = Random.nextInt(100) } +private object A196 { val a = Random.nextInt(100) } +private object A197 { val a = Random.nextInt(100) } +private object A198 { val a = Random.nextInt(100) } +private object A199 { val a = Random.nextInt(100) } +private object A200 { val a = Random.nextInt(100) } +private object A201 { val a = Random.nextInt(100) } +private object A202 { val a = Random.nextInt(100) } +private object A203 { val a = Random.nextInt(100) } +private object A204 { val a = Random.nextInt(100) } +private object A205 { val a = Random.nextInt(100) } +private object A206 { val a = Random.nextInt(100) } +private object A207 { val a = Random.nextInt(100) } +private object A208 { val a = Random.nextInt(100) } +private object A209 { val a = Random.nextInt(100) } +private object A210 { val a = Random.nextInt(100) } +private object A211 { val a = Random.nextInt(100) } +private object A212 { val a = Random.nextInt(100) } +private object A213 { val a = Random.nextInt(100) } +private object A214 { val a = Random.nextInt(100) } +private object A215 { val a = Random.nextInt(100) } +private object A216 { val a = Random.nextInt(100) } +private object A217 { val a = Random.nextInt(100) } +private object A218 { val a = Random.nextInt(100) } +private object A219 { val a = Random.nextInt(100) } +private object A220 { val a = Random.nextInt(100) } +private object A221 { val a = Random.nextInt(100) } +private object A222 { val a = Random.nextInt(100) } +private object A223 { val a = Random.nextInt(100) } +private object A224 { val a = Random.nextInt(100) } +private object A225 { val a = Random.nextInt(100) } +private object A226 { val a = Random.nextInt(100) } +private object A227 { val a = Random.nextInt(100) } +private object A228 { val a = Random.nextInt(100) } +private object A229 { val a = Random.nextInt(100) } +private object A230 { val a = Random.nextInt(100) } +private object A231 { val a = Random.nextInt(100) } +private object A232 { val a = Random.nextInt(100) } +private object A233 { val a = Random.nextInt(100) } +private object A234 { val a = Random.nextInt(100) } +private object A235 { val a = Random.nextInt(100) } +private object A236 { val a = Random.nextInt(100) } +private object A237 { val a = Random.nextInt(100) } +private object A238 { val a = Random.nextInt(100) } +private object A239 { val a = Random.nextInt(100) } +private object A240 { val a = Random.nextInt(100) } +private object A241 { val a = Random.nextInt(100) } +private object A242 { val a = Random.nextInt(100) } +private object A243 { val a = Random.nextInt(100) } +private object A244 { val a = Random.nextInt(100) } +private object A245 { val a = Random.nextInt(100) } +private object A246 { val a = Random.nextInt(100) } +private object A247 { val a = Random.nextInt(100) } +private object A248 { val a = Random.nextInt(100) } +private object A249 { val a = Random.nextInt(100) } +private object A250 { val a = Random.nextInt(100) } +private object A251 { val a = Random.nextInt(100) } +private object A252 { val a = Random.nextInt(100) } +private object A253 { val a = Random.nextInt(100) } +private object A254 { val a = Random.nextInt(100) } +private object A255 { val a = Random.nextInt(100) } +private object A256 { val a = Random.nextInt(100) } +private object A257 { val a = Random.nextInt(100) } +private object A258 { val a = Random.nextInt(100) } +private object A259 { val a = Random.nextInt(100) } +private object A260 { val a = Random.nextInt(100) } +private object A261 { val a = Random.nextInt(100) } +private object A262 { val a = Random.nextInt(100) } +private object A263 { val a = Random.nextInt(100) } +private object A264 { val a = Random.nextInt(100) } +private object A265 { val a = Random.nextInt(100) } +private object A266 { val a = Random.nextInt(100) } +private object A267 { val a = Random.nextInt(100) } +private object A268 { val a = Random.nextInt(100) } +private object A269 { val a = Random.nextInt(100) } +private object A270 { val a = Random.nextInt(100) } +private object A271 { val a = Random.nextInt(100) } +private object A272 { val a = Random.nextInt(100) } +private object A273 { val a = Random.nextInt(100) } +private object A274 { val a = Random.nextInt(100) } +private object A275 { val a = Random.nextInt(100) } +private object A276 { val a = Random.nextInt(100) } +private object A277 { val a = Random.nextInt(100) } +private object A278 { val a = Random.nextInt(100) } +private object A279 { val a = Random.nextInt(100) } +private object A280 { val a = Random.nextInt(100) } +private object A281 { val a = Random.nextInt(100) } +private object A282 { val a = Random.nextInt(100) } +private object A283 { val a = Random.nextInt(100) } +private object A284 { val a = Random.nextInt(100) } +private object A285 { val a = Random.nextInt(100) } +private object A286 { val a = Random.nextInt(100) } +private object A287 { val a = Random.nextInt(100) } +private object A288 { val a = Random.nextInt(100) } +private object A289 { val a = Random.nextInt(100) } +private object A290 { val a = Random.nextInt(100) } +private object A291 { val a = Random.nextInt(100) } +private object A292 { val a = Random.nextInt(100) } +private object A293 { val a = Random.nextInt(100) } +private object A294 { val a = Random.nextInt(100) } +private object A295 { val a = Random.nextInt(100) } +private object A296 { val a = Random.nextInt(100) } +private object A297 { val a = Random.nextInt(100) } +private object A298 { val a = Random.nextInt(100) } +private object A299 { val a = Random.nextInt(100) } +private object A300 { val a = Random.nextInt(100) } +private object A301 { val a = Random.nextInt(100) } +private object A302 { val a = Random.nextInt(100) } +private object A303 { val a = Random.nextInt(100) } +private object A304 { val a = Random.nextInt(100) } +private object A305 { val a = Random.nextInt(100) } +private object A306 { val a = Random.nextInt(100) } +private object A307 { val a = Random.nextInt(100) } +private object A308 { val a = Random.nextInt(100) } +private object A309 { val a = Random.nextInt(100) } +private object A310 { val a = Random.nextInt(100) } +private object A311 { val a = Random.nextInt(100) } +private object A312 { val a = Random.nextInt(100) } +private object A313 { val a = Random.nextInt(100) } +private object A314 { val a = Random.nextInt(100) } +private object A315 { val a = Random.nextInt(100) } +private object A316 { val a = Random.nextInt(100) } +private object A317 { val a = Random.nextInt(100) } +private object A318 { val a = Random.nextInt(100) } +private object A319 { val a = Random.nextInt(100) } +private object A320 { val a = Random.nextInt(100) } +private object A321 { val a = Random.nextInt(100) } +private object A322 { val a = Random.nextInt(100) } +private object A323 { val a = Random.nextInt(100) } +private object A324 { val a = Random.nextInt(100) } +private object A325 { val a = Random.nextInt(100) } +private object A326 { val a = Random.nextInt(100) } +private object A327 { val a = Random.nextInt(100) } +private object A328 { val a = Random.nextInt(100) } +private object A329 { val a = Random.nextInt(100) } +private object A330 { val a = Random.nextInt(100) } +private object A331 { val a = Random.nextInt(100) } +private object A332 { val a = Random.nextInt(100) } +private object A333 { val a = Random.nextInt(100) } +private object A334 { val a = Random.nextInt(100) } +private object A335 { val a = Random.nextInt(100) } +private object A336 { val a = Random.nextInt(100) } +private object A337 { val a = Random.nextInt(100) } +private object A338 { val a = Random.nextInt(100) } +private object A339 { val a = Random.nextInt(100) } +private object A340 { val a = Random.nextInt(100) } +private object A341 { val a = Random.nextInt(100) } +private object A342 { val a = Random.nextInt(100) } +private object A343 { val a = Random.nextInt(100) } +private object A344 { val a = Random.nextInt(100) } +private object A345 { val a = Random.nextInt(100) } +private object A346 { val a = Random.nextInt(100) } +private object A347 { val a = Random.nextInt(100) } +private object A348 { val a = Random.nextInt(100) } +private object A349 { val a = Random.nextInt(100) } +private object A350 { val a = Random.nextInt(100) } +private object A351 { val a = Random.nextInt(100) } +private object A352 { val a = Random.nextInt(100) } +private object A353 { val a = Random.nextInt(100) } +private object A354 { val a = Random.nextInt(100) } +private object A355 { val a = Random.nextInt(100) } +private object A356 { val a = Random.nextInt(100) } +private object A357 { val a = Random.nextInt(100) } +private object A358 { val a = Random.nextInt(100) } +private object A359 { val a = Random.nextInt(100) } +private object A360 { val a = Random.nextInt(100) } +private object A361 { val a = Random.nextInt(100) } +private object A362 { val a = Random.nextInt(100) } +private object A363 { val a = Random.nextInt(100) } +private object A364 { val a = Random.nextInt(100) } +private object A365 { val a = Random.nextInt(100) } +private object A366 { val a = Random.nextInt(100) } +private object A367 { val a = Random.nextInt(100) } +private object A368 { val a = Random.nextInt(100) } +private object A369 { val a = Random.nextInt(100) } +private object A370 { val a = Random.nextInt(100) } +private object A371 { val a = Random.nextInt(100) } +private object A372 { val a = Random.nextInt(100) } +private object A373 { val a = Random.nextInt(100) } +private object A374 { val a = Random.nextInt(100) } +private object A375 { val a = Random.nextInt(100) } +private object A376 { val a = Random.nextInt(100) } +private object A377 { val a = Random.nextInt(100) } +private object A378 { val a = Random.nextInt(100) } +private object A379 { val a = Random.nextInt(100) } +private object A380 { val a = Random.nextInt(100) } +private object A381 { val a = Random.nextInt(100) } +private object A382 { val a = Random.nextInt(100) } +private object A383 { val a = Random.nextInt(100) } +private object A384 { val a = Random.nextInt(100) } +private object A385 { val a = Random.nextInt(100) } +private object A386 { val a = Random.nextInt(100) } +private object A387 { val a = Random.nextInt(100) } +private object A388 { val a = Random.nextInt(100) } +private object A389 { val a = Random.nextInt(100) } +private object A390 { val a = Random.nextInt(100) } +private object A391 { val a = Random.nextInt(100) } +private object A392 { val a = Random.nextInt(100) } +private object A393 { val a = Random.nextInt(100) } +private object A394 { val a = Random.nextInt(100) } +private object A395 { val a = Random.nextInt(100) } +private object A396 { val a = Random.nextInt(100) } +private object A397 { val a = Random.nextInt(100) } +private object A398 { val a = Random.nextInt(100) } +private object A399 { val a = Random.nextInt(100) } +private object A400 { val a = Random.nextInt(100) } +private object A401 { val a = Random.nextInt(100) } +private object A402 { val a = Random.nextInt(100) } +private object A403 { val a = Random.nextInt(100) } +private object A404 { val a = Random.nextInt(100) } +private object A405 { val a = Random.nextInt(100) } +private object A406 { val a = Random.nextInt(100) } +private object A407 { val a = Random.nextInt(100) } +private object A408 { val a = Random.nextInt(100) } +private object A409 { val a = Random.nextInt(100) } +private object A410 { val a = Random.nextInt(100) } +private object A411 { val a = Random.nextInt(100) } +private object A412 { val a = Random.nextInt(100) } +private object A413 { val a = Random.nextInt(100) } +private object A414 { val a = Random.nextInt(100) } +private object A415 { val a = Random.nextInt(100) } +private object A416 { val a = Random.nextInt(100) } +private object A417 { val a = Random.nextInt(100) } +private object A418 { val a = Random.nextInt(100) } +private object A419 { val a = Random.nextInt(100) } +private object A420 { val a = Random.nextInt(100) } +private object A421 { val a = Random.nextInt(100) } +private object A422 { val a = Random.nextInt(100) } +private object A423 { val a = Random.nextInt(100) } +private object A424 { val a = Random.nextInt(100) } +private object A425 { val a = Random.nextInt(100) } +private object A426 { val a = Random.nextInt(100) } +private object A427 { val a = Random.nextInt(100) } +private object A428 { val a = Random.nextInt(100) } +private object A429 { val a = Random.nextInt(100) } +private object A430 { val a = Random.nextInt(100) } +private object A431 { val a = Random.nextInt(100) } +private object A432 { val a = Random.nextInt(100) } +private object A433 { val a = Random.nextInt(100) } +private object A434 { val a = Random.nextInt(100) } +private object A435 { val a = Random.nextInt(100) } +private object A436 { val a = Random.nextInt(100) } +private object A437 { val a = Random.nextInt(100) } +private object A438 { val a = Random.nextInt(100) } +private object A439 { val a = Random.nextInt(100) } +private object A440 { val a = Random.nextInt(100) } +private object A441 { val a = Random.nextInt(100) } +private object A442 { val a = Random.nextInt(100) } +private object A443 { val a = Random.nextInt(100) } +private object A444 { val a = Random.nextInt(100) } +private object A445 { val a = Random.nextInt(100) } +private object A446 { val a = Random.nextInt(100) } +private object A447 { val a = Random.nextInt(100) } +private object A448 { val a = Random.nextInt(100) } +private object A449 { val a = Random.nextInt(100) } +private object A450 { val a = Random.nextInt(100) } +private object A451 { val a = Random.nextInt(100) } +private object A452 { val a = Random.nextInt(100) } +private object A453 { val a = Random.nextInt(100) } +private object A454 { val a = Random.nextInt(100) } +private object A455 { val a = Random.nextInt(100) } +private object A456 { val a = Random.nextInt(100) } +private object A457 { val a = Random.nextInt(100) } +private object A458 { val a = Random.nextInt(100) } +private object A459 { val a = Random.nextInt(100) } +private object A460 { val a = Random.nextInt(100) } +private object A461 { val a = Random.nextInt(100) } +private object A462 { val a = Random.nextInt(100) } +private object A463 { val a = Random.nextInt(100) } +private object A464 { val a = Random.nextInt(100) } +private object A465 { val a = Random.nextInt(100) } +private object A466 { val a = Random.nextInt(100) } +private object A467 { val a = Random.nextInt(100) } +private object A468 { val a = Random.nextInt(100) } +private object A469 { val a = Random.nextInt(100) } +private object A470 { val a = Random.nextInt(100) } +private object A471 { val a = Random.nextInt(100) } +private object A472 { val a = Random.nextInt(100) } +private object A473 { val a = Random.nextInt(100) } +private object A474 { val a = Random.nextInt(100) } +private object A475 { val a = Random.nextInt(100) } +private object A476 { val a = Random.nextInt(100) } +private object A477 { val a = Random.nextInt(100) } +private object A478 { val a = Random.nextInt(100) } +private object A479 { val a = Random.nextInt(100) } +private object A480 { val a = Random.nextInt(100) } +private object A481 { val a = Random.nextInt(100) } +private object A482 { val a = Random.nextInt(100) } +private object A483 { val a = Random.nextInt(100) } +private object A484 { val a = Random.nextInt(100) } +private object A485 { val a = Random.nextInt(100) } +private object A486 { val a = Random.nextInt(100) } +private object A487 { val a = Random.nextInt(100) } +private object A488 { val a = Random.nextInt(100) } +private object A489 { val a = Random.nextInt(100) } +private object A490 { val a = Random.nextInt(100) } +private object A491 { val a = Random.nextInt(100) } +private object A492 { val a = Random.nextInt(100) } +private object A493 { val a = Random.nextInt(100) } +private object A494 { val a = Random.nextInt(100) } +private object A495 { val a = Random.nextInt(100) } +private object A496 { val a = Random.nextInt(100) } +private object A497 { val a = Random.nextInt(100) } +private object A498 { val a = Random.nextInt(100) } +private object A499 { val a = Random.nextInt(100) } + +private var singletonInitializeRun = false +// Benchmark +fun singletonInitialize(): Int { + if (singletonInitializeRun) { + error("Function singletonInitialize can be called only once.") + } + singletonInitializeRun = true + + var total = 0 + + total += A0.a + total += A1.a + total += A2.a + total += A3.a + total += A4.a + total += A5.a + total += A6.a + total += A7.a + total += A8.a + total += A9.a + total += A10.a + total += A11.a + total += A12.a + total += A13.a + total += A14.a + total += A15.a + total += A16.a + total += A17.a + total += A18.a + total += A19.a + total += A20.a + total += A21.a + total += A22.a + total += A23.a + total += A24.a + total += A25.a + total += A26.a + total += A27.a + total += A28.a + total += A29.a + total += A30.a + total += A31.a + total += A32.a + total += A33.a + total += A34.a + total += A35.a + total += A36.a + total += A37.a + total += A38.a + total += A39.a + total += A40.a + total += A41.a + total += A42.a + total += A43.a + total += A44.a + total += A45.a + total += A46.a + total += A47.a + total += A48.a + total += A49.a + total += A50.a + total += A51.a + total += A52.a + total += A53.a + total += A54.a + total += A55.a + total += A56.a + total += A57.a + total += A58.a + total += A59.a + total += A60.a + total += A61.a + total += A62.a + total += A63.a + total += A64.a + total += A65.a + total += A66.a + total += A67.a + total += A68.a + total += A69.a + total += A70.a + total += A71.a + total += A72.a + total += A73.a + total += A74.a + total += A75.a + total += A76.a + total += A77.a + total += A78.a + total += A79.a + total += A80.a + total += A81.a + total += A82.a + total += A83.a + total += A84.a + total += A85.a + total += A86.a + total += A87.a + total += A88.a + total += A89.a + total += A90.a + total += A91.a + total += A92.a + total += A93.a + total += A94.a + total += A95.a + total += A96.a + total += A97.a + total += A98.a + total += A99.a + total += A100.a + total += A101.a + total += A102.a + total += A103.a + total += A104.a + total += A105.a + total += A106.a + total += A107.a + total += A108.a + total += A109.a + total += A110.a + total += A111.a + total += A112.a + total += A113.a + total += A114.a + total += A115.a + total += A116.a + total += A117.a + total += A118.a + total += A119.a + total += A120.a + total += A121.a + total += A122.a + total += A123.a + total += A124.a + total += A125.a + total += A126.a + total += A127.a + total += A128.a + total += A129.a + total += A130.a + total += A131.a + total += A132.a + total += A133.a + total += A134.a + total += A135.a + total += A136.a + total += A137.a + total += A138.a + total += A139.a + total += A140.a + total += A141.a + total += A142.a + total += A143.a + total += A144.a + total += A145.a + total += A146.a + total += A147.a + total += A148.a + total += A149.a + total += A150.a + total += A151.a + total += A152.a + total += A153.a + total += A154.a + total += A155.a + total += A156.a + total += A157.a + total += A158.a + total += A159.a + total += A160.a + total += A161.a + total += A162.a + total += A163.a + total += A164.a + total += A165.a + total += A166.a + total += A167.a + total += A168.a + total += A169.a + total += A170.a + total += A171.a + total += A172.a + total += A173.a + total += A174.a + total += A175.a + total += A176.a + total += A177.a + total += A178.a + total += A179.a + total += A180.a + total += A181.a + total += A182.a + total += A183.a + total += A184.a + total += A185.a + total += A186.a + total += A187.a + total += A188.a + total += A189.a + total += A190.a + total += A191.a + total += A192.a + total += A193.a + total += A194.a + total += A195.a + total += A196.a + total += A197.a + total += A198.a + total += A199.a + total += A200.a + total += A201.a + total += A202.a + total += A203.a + total += A204.a + total += A205.a + total += A206.a + total += A207.a + total += A208.a + total += A209.a + total += A210.a + total += A211.a + total += A212.a + total += A213.a + total += A214.a + total += A215.a + total += A216.a + total += A217.a + total += A218.a + total += A219.a + total += A220.a + total += A221.a + total += A222.a + total += A223.a + total += A224.a + total += A225.a + total += A226.a + total += A227.a + total += A228.a + total += A229.a + total += A230.a + total += A231.a + total += A232.a + total += A233.a + total += A234.a + total += A235.a + total += A236.a + total += A237.a + total += A238.a + total += A239.a + total += A240.a + total += A241.a + total += A242.a + total += A243.a + total += A244.a + total += A245.a + total += A246.a + total += A247.a + total += A248.a + total += A249.a + total += A250.a + total += A251.a + total += A252.a + total += A253.a + total += A254.a + total += A255.a + total += A256.a + total += A257.a + total += A258.a + total += A259.a + total += A260.a + total += A261.a + total += A262.a + total += A263.a + total += A264.a + total += A265.a + total += A266.a + total += A267.a + total += A268.a + total += A269.a + total += A270.a + total += A271.a + total += A272.a + total += A273.a + total += A274.a + total += A275.a + total += A276.a + total += A277.a + total += A278.a + total += A279.a + total += A280.a + total += A281.a + total += A282.a + total += A283.a + total += A284.a + total += A285.a + total += A286.a + total += A287.a + total += A288.a + total += A289.a + total += A290.a + total += A291.a + total += A292.a + total += A293.a + total += A294.a + total += A295.a + total += A296.a + total += A297.a + total += A298.a + total += A299.a + total += A300.a + total += A301.a + total += A302.a + total += A303.a + total += A304.a + total += A305.a + total += A306.a + total += A307.a + total += A308.a + total += A309.a + total += A310.a + total += A311.a + total += A312.a + total += A313.a + total += A314.a + total += A315.a + total += A316.a + total += A317.a + total += A318.a + total += A319.a + total += A320.a + total += A321.a + total += A322.a + total += A323.a + total += A324.a + total += A325.a + total += A326.a + total += A327.a + total += A328.a + total += A329.a + total += A330.a + total += A331.a + total += A332.a + total += A333.a + total += A334.a + total += A335.a + total += A336.a + total += A337.a + total += A338.a + total += A339.a + total += A340.a + total += A341.a + total += A342.a + total += A343.a + total += A344.a + total += A345.a + total += A346.a + total += A347.a + total += A348.a + total += A349.a + total += A350.a + total += A351.a + total += A352.a + total += A353.a + total += A354.a + total += A355.a + total += A356.a + total += A357.a + total += A358.a + total += A359.a + total += A360.a + total += A361.a + total += A362.a + total += A363.a + total += A364.a + total += A365.a + total += A366.a + total += A367.a + total += A368.a + total += A369.a + total += A370.a + total += A371.a + total += A372.a + total += A373.a + total += A374.a + total += A375.a + total += A376.a + total += A377.a + total += A378.a + total += A379.a + total += A380.a + total += A381.a + total += A382.a + total += A383.a + total += A384.a + total += A385.a + total += A386.a + total += A387.a + total += A388.a + total += A389.a + total += A390.a + total += A391.a + total += A392.a + total += A393.a + total += A394.a + total += A395.a + total += A396.a + total += A397.a + total += A398.a + total += A399.a + total += A400.a + total += A401.a + total += A402.a + total += A403.a + total += A404.a + total += A405.a + total += A406.a + total += A407.a + total += A408.a + total += A409.a + total += A410.a + total += A411.a + total += A412.a + total += A413.a + total += A414.a + total += A415.a + total += A416.a + total += A417.a + total += A418.a + total += A419.a + total += A420.a + total += A421.a + total += A422.a + total += A423.a + total += A424.a + total += A425.a + total += A426.a + total += A427.a + total += A428.a + total += A429.a + total += A430.a + total += A431.a + total += A432.a + total += A433.a + total += A434.a + total += A435.a + total += A436.a + total += A437.a + total += A438.a + total += A439.a + total += A440.a + total += A441.a + total += A442.a + total += A443.a + total += A444.a + total += A445.a + total += A446.a + total += A447.a + total += A448.a + total += A449.a + total += A450.a + total += A451.a + total += A452.a + total += A453.a + total += A454.a + total += A455.a + total += A456.a + total += A457.a + total += A458.a + total += A459.a + total += A460.a + total += A461.a + total += A462.a + total += A463.a + total += A464.a + total += A465.a + total += A466.a + total += A467.a + total += A468.a + total += A469.a + total += A470.a + total += A471.a + total += A472.a + total += A473.a + total += A474.a + total += A475.a + total += A476.a + total += A477.a + total += A478.a + total += A479.a + total += A480.a + total += A481.a + total += A482.a + total += A483.a + total += A484.a + total += A485.a + total += A486.a + total += A487.a + total += A488.a + total += A489.a + total += A490.a + total += A491.a + total += A492.a + total += A493.a + total += A494.a + total += A495.a + total += A496.a + total += A497.a + total += A498.a + total += A499.a + + return total +} + +private object B0 { val a = Random.nextInt(100) } +private object B1 { val a = B0.a + Random.nextInt(100) } +private object B2 { val a = B1.a + Random.nextInt(100) } +private object B3 { val a = B2.a + Random.nextInt(100) } +private object B4 { val a = B3.a + Random.nextInt(100) } +private object B5 { val a = B4.a + Random.nextInt(100) } +private object B6 { val a = B5.a + Random.nextInt(100) } +private object B7 { val a = B6.a + Random.nextInt(100) } +private object B8 { val a = B7.a + Random.nextInt(100) } +private object B9 { val a = B8.a + Random.nextInt(100) } +private object B10 { val a = B9.a + Random.nextInt(100) } +private object B11 { val a = B10.a + Random.nextInt(100) } +private object B12 { val a = B11.a + Random.nextInt(100) } +private object B13 { val a = B12.a + Random.nextInt(100) } +private object B14 { val a = B13.a + Random.nextInt(100) } +private object B15 { val a = B14.a + Random.nextInt(100) } +private object B16 { val a = B15.a + Random.nextInt(100) } +private object B17 { val a = B16.a + Random.nextInt(100) } +private object B18 { val a = B17.a + Random.nextInt(100) } +private object B19 { val a = B18.a + Random.nextInt(100) } +private object B20 { val a = B19.a + Random.nextInt(100) } +private object B21 { val a = B20.a + Random.nextInt(100) } +private object B22 { val a = B21.a + Random.nextInt(100) } +private object B23 { val a = B22.a + Random.nextInt(100) } +private object B24 { val a = B23.a + Random.nextInt(100) } +private object B25 { val a = B24.a + Random.nextInt(100) } +private object B26 { val a = B25.a + Random.nextInt(100) } +private object B27 { val a = B26.a + Random.nextInt(100) } +private object B28 { val a = B27.a + Random.nextInt(100) } +private object B29 { val a = B28.a + Random.nextInt(100) } +private object B30 { val a = B29.a + Random.nextInt(100) } +private object B31 { val a = B30.a + Random.nextInt(100) } +private object B32 { val a = B31.a + Random.nextInt(100) } +private object B33 { val a = B32.a + Random.nextInt(100) } +private object B34 { val a = B33.a + Random.nextInt(100) } +private object B35 { val a = B34.a + Random.nextInt(100) } +private object B36 { val a = B35.a + Random.nextInt(100) } +private object B37 { val a = B36.a + Random.nextInt(100) } +private object B38 { val a = B37.a + Random.nextInt(100) } +private object B39 { val a = B38.a + Random.nextInt(100) } +private object B40 { val a = B39.a + Random.nextInt(100) } +private object B41 { val a = B40.a + Random.nextInt(100) } +private object B42 { val a = B41.a + Random.nextInt(100) } +private object B43 { val a = B42.a + Random.nextInt(100) } +private object B44 { val a = B43.a + Random.nextInt(100) } +private object B45 { val a = B44.a + Random.nextInt(100) } +private object B46 { val a = B45.a + Random.nextInt(100) } +private object B47 { val a = B46.a + Random.nextInt(100) } +private object B48 { val a = B47.a + Random.nextInt(100) } +private object B49 { val a = B48.a + Random.nextInt(100) } +private object B50 { val a = B49.a + Random.nextInt(100) } +private object B51 { val a = B50.a + Random.nextInt(100) } +private object B52 { val a = B51.a + Random.nextInt(100) } +private object B53 { val a = B52.a + Random.nextInt(100) } +private object B54 { val a = B53.a + Random.nextInt(100) } +private object B55 { val a = B54.a + Random.nextInt(100) } +private object B56 { val a = B55.a + Random.nextInt(100) } +private object B57 { val a = B56.a + Random.nextInt(100) } +private object B58 { val a = B57.a + Random.nextInt(100) } +private object B59 { val a = B58.a + Random.nextInt(100) } +private object B60 { val a = B59.a + Random.nextInt(100) } +private object B61 { val a = B60.a + Random.nextInt(100) } +private object B62 { val a = B61.a + Random.nextInt(100) } +private object B63 { val a = B62.a + Random.nextInt(100) } +private object B64 { val a = B63.a + Random.nextInt(100) } +private object B65 { val a = B64.a + Random.nextInt(100) } +private object B66 { val a = B65.a + Random.nextInt(100) } +private object B67 { val a = B66.a + Random.nextInt(100) } +private object B68 { val a = B67.a + Random.nextInt(100) } +private object B69 { val a = B68.a + Random.nextInt(100) } +private object B70 { val a = B69.a + Random.nextInt(100) } +private object B71 { val a = B70.a + Random.nextInt(100) } +private object B72 { val a = B71.a + Random.nextInt(100) } +private object B73 { val a = B72.a + Random.nextInt(100) } +private object B74 { val a = B73.a + Random.nextInt(100) } +private object B75 { val a = B74.a + Random.nextInt(100) } +private object B76 { val a = B75.a + Random.nextInt(100) } +private object B77 { val a = B76.a + Random.nextInt(100) } +private object B78 { val a = B77.a + Random.nextInt(100) } +private object B79 { val a = B78.a + Random.nextInt(100) } +private object B80 { val a = B79.a + Random.nextInt(100) } +private object B81 { val a = B80.a + Random.nextInt(100) } +private object B82 { val a = B81.a + Random.nextInt(100) } +private object B83 { val a = B82.a + Random.nextInt(100) } +private object B84 { val a = B83.a + Random.nextInt(100) } +private object B85 { val a = B84.a + Random.nextInt(100) } +private object B86 { val a = B85.a + Random.nextInt(100) } +private object B87 { val a = B86.a + Random.nextInt(100) } +private object B88 { val a = B87.a + Random.nextInt(100) } +private object B89 { val a = B88.a + Random.nextInt(100) } +private object B90 { val a = B89.a + Random.nextInt(100) } +private object B91 { val a = B90.a + Random.nextInt(100) } +private object B92 { val a = B91.a + Random.nextInt(100) } +private object B93 { val a = B92.a + Random.nextInt(100) } +private object B94 { val a = B93.a + Random.nextInt(100) } +private object B95 { val a = B94.a + Random.nextInt(100) } +private object B96 { val a = B95.a + Random.nextInt(100) } +private object B97 { val a = B96.a + Random.nextInt(100) } +private object B98 { val a = B97.a + Random.nextInt(100) } +private object B99 { val a = B98.a + Random.nextInt(100) } +private object B100 { val a = B99.a + Random.nextInt(100) } +private object B101 { val a = B100.a + Random.nextInt(100) } +private object B102 { val a = B101.a + Random.nextInt(100) } +private object B103 { val a = B102.a + Random.nextInt(100) } +private object B104 { val a = B103.a + Random.nextInt(100) } +private object B105 { val a = B104.a + Random.nextInt(100) } +private object B106 { val a = B105.a + Random.nextInt(100) } +private object B107 { val a = B106.a + Random.nextInt(100) } +private object B108 { val a = B107.a + Random.nextInt(100) } +private object B109 { val a = B108.a + Random.nextInt(100) } +private object B110 { val a = B109.a + Random.nextInt(100) } +private object B111 { val a = B110.a + Random.nextInt(100) } +private object B112 { val a = B111.a + Random.nextInt(100) } +private object B113 { val a = B112.a + Random.nextInt(100) } +private object B114 { val a = B113.a + Random.nextInt(100) } +private object B115 { val a = B114.a + Random.nextInt(100) } +private object B116 { val a = B115.a + Random.nextInt(100) } +private object B117 { val a = B116.a + Random.nextInt(100) } +private object B118 { val a = B117.a + Random.nextInt(100) } +private object B119 { val a = B118.a + Random.nextInt(100) } +private object B120 { val a = B119.a + Random.nextInt(100) } +private object B121 { val a = B120.a + Random.nextInt(100) } +private object B122 { val a = B121.a + Random.nextInt(100) } +private object B123 { val a = B122.a + Random.nextInt(100) } +private object B124 { val a = B123.a + Random.nextInt(100) } +private object B125 { val a = B124.a + Random.nextInt(100) } +private object B126 { val a = B125.a + Random.nextInt(100) } +private object B127 { val a = B126.a + Random.nextInt(100) } +private object B128 { val a = B127.a + Random.nextInt(100) } +private object B129 { val a = B128.a + Random.nextInt(100) } +private object B130 { val a = B129.a + Random.nextInt(100) } +private object B131 { val a = B130.a + Random.nextInt(100) } +private object B132 { val a = B131.a + Random.nextInt(100) } +private object B133 { val a = B132.a + Random.nextInt(100) } +private object B134 { val a = B133.a + Random.nextInt(100) } +private object B135 { val a = B134.a + Random.nextInt(100) } +private object B136 { val a = B135.a + Random.nextInt(100) } +private object B137 { val a = B136.a + Random.nextInt(100) } +private object B138 { val a = B137.a + Random.nextInt(100) } +private object B139 { val a = B138.a + Random.nextInt(100) } +private object B140 { val a = B139.a + Random.nextInt(100) } +private object B141 { val a = B140.a + Random.nextInt(100) } +private object B142 { val a = B141.a + Random.nextInt(100) } +private object B143 { val a = B142.a + Random.nextInt(100) } +private object B144 { val a = B143.a + Random.nextInt(100) } +private object B145 { val a = B144.a + Random.nextInt(100) } +private object B146 { val a = B145.a + Random.nextInt(100) } +private object B147 { val a = B146.a + Random.nextInt(100) } +private object B148 { val a = B147.a + Random.nextInt(100) } +private object B149 { val a = B148.a + Random.nextInt(100) } +private object B150 { val a = B149.a + Random.nextInt(100) } +private object B151 { val a = B150.a + Random.nextInt(100) } +private object B152 { val a = B151.a + Random.nextInt(100) } +private object B153 { val a = B152.a + Random.nextInt(100) } +private object B154 { val a = B153.a + Random.nextInt(100) } +private object B155 { val a = B154.a + Random.nextInt(100) } +private object B156 { val a = B155.a + Random.nextInt(100) } +private object B157 { val a = B156.a + Random.nextInt(100) } +private object B158 { val a = B157.a + Random.nextInt(100) } +private object B159 { val a = B158.a + Random.nextInt(100) } +private object B160 { val a = B159.a + Random.nextInt(100) } +private object B161 { val a = B160.a + Random.nextInt(100) } +private object B162 { val a = B161.a + Random.nextInt(100) } +private object B163 { val a = B162.a + Random.nextInt(100) } +private object B164 { val a = B163.a + Random.nextInt(100) } +private object B165 { val a = B164.a + Random.nextInt(100) } +private object B166 { val a = B165.a + Random.nextInt(100) } +private object B167 { val a = B166.a + Random.nextInt(100) } +private object B168 { val a = B167.a + Random.nextInt(100) } +private object B169 { val a = B168.a + Random.nextInt(100) } +private object B170 { val a = B169.a + Random.nextInt(100) } +private object B171 { val a = B170.a + Random.nextInt(100) } +private object B172 { val a = B171.a + Random.nextInt(100) } +private object B173 { val a = B172.a + Random.nextInt(100) } +private object B174 { val a = B173.a + Random.nextInt(100) } +private object B175 { val a = B174.a + Random.nextInt(100) } +private object B176 { val a = B175.a + Random.nextInt(100) } +private object B177 { val a = B176.a + Random.nextInt(100) } +private object B178 { val a = B177.a + Random.nextInt(100) } +private object B179 { val a = B178.a + Random.nextInt(100) } +private object B180 { val a = B179.a + Random.nextInt(100) } +private object B181 { val a = B180.a + Random.nextInt(100) } +private object B182 { val a = B181.a + Random.nextInt(100) } +private object B183 { val a = B182.a + Random.nextInt(100) } +private object B184 { val a = B183.a + Random.nextInt(100) } +private object B185 { val a = B184.a + Random.nextInt(100) } +private object B186 { val a = B185.a + Random.nextInt(100) } +private object B187 { val a = B186.a + Random.nextInt(100) } +private object B188 { val a = B187.a + Random.nextInt(100) } +private object B189 { val a = B188.a + Random.nextInt(100) } +private object B190 { val a = B189.a + Random.nextInt(100) } +private object B191 { val a = B190.a + Random.nextInt(100) } +private object B192 { val a = B191.a + Random.nextInt(100) } +private object B193 { val a = B192.a + Random.nextInt(100) } +private object B194 { val a = B193.a + Random.nextInt(100) } +private object B195 { val a = B194.a + Random.nextInt(100) } +private object B196 { val a = B195.a + Random.nextInt(100) } +private object B197 { val a = B196.a + Random.nextInt(100) } +private object B198 { val a = B197.a + Random.nextInt(100) } +private object B199 { val a = B198.a + Random.nextInt(100) } +private object B200 { val a = B199.a + Random.nextInt(100) } +private object B201 { val a = B200.a + Random.nextInt(100) } +private object B202 { val a = B201.a + Random.nextInt(100) } +private object B203 { val a = B202.a + Random.nextInt(100) } +private object B204 { val a = B203.a + Random.nextInt(100) } +private object B205 { val a = B204.a + Random.nextInt(100) } +private object B206 { val a = B205.a + Random.nextInt(100) } +private object B207 { val a = B206.a + Random.nextInt(100) } +private object B208 { val a = B207.a + Random.nextInt(100) } +private object B209 { val a = B208.a + Random.nextInt(100) } +private object B210 { val a = B209.a + Random.nextInt(100) } +private object B211 { val a = B210.a + Random.nextInt(100) } +private object B212 { val a = B211.a + Random.nextInt(100) } +private object B213 { val a = B212.a + Random.nextInt(100) } +private object B214 { val a = B213.a + Random.nextInt(100) } +private object B215 { val a = B214.a + Random.nextInt(100) } +private object B216 { val a = B215.a + Random.nextInt(100) } +private object B217 { val a = B216.a + Random.nextInt(100) } +private object B218 { val a = B217.a + Random.nextInt(100) } +private object B219 { val a = B218.a + Random.nextInt(100) } +private object B220 { val a = B219.a + Random.nextInt(100) } +private object B221 { val a = B220.a + Random.nextInt(100) } +private object B222 { val a = B221.a + Random.nextInt(100) } +private object B223 { val a = B222.a + Random.nextInt(100) } +private object B224 { val a = B223.a + Random.nextInt(100) } +private object B225 { val a = B224.a + Random.nextInt(100) } +private object B226 { val a = B225.a + Random.nextInt(100) } +private object B227 { val a = B226.a + Random.nextInt(100) } +private object B228 { val a = B227.a + Random.nextInt(100) } +private object B229 { val a = B228.a + Random.nextInt(100) } +private object B230 { val a = B229.a + Random.nextInt(100) } +private object B231 { val a = B230.a + Random.nextInt(100) } +private object B232 { val a = B231.a + Random.nextInt(100) } +private object B233 { val a = B232.a + Random.nextInt(100) } +private object B234 { val a = B233.a + Random.nextInt(100) } +private object B235 { val a = B234.a + Random.nextInt(100) } +private object B236 { val a = B235.a + Random.nextInt(100) } +private object B237 { val a = B236.a + Random.nextInt(100) } +private object B238 { val a = B237.a + Random.nextInt(100) } +private object B239 { val a = B238.a + Random.nextInt(100) } +private object B240 { val a = B239.a + Random.nextInt(100) } +private object B241 { val a = B240.a + Random.nextInt(100) } +private object B242 { val a = B241.a + Random.nextInt(100) } +private object B243 { val a = B242.a + Random.nextInt(100) } +private object B244 { val a = B243.a + Random.nextInt(100) } +private object B245 { val a = B244.a + Random.nextInt(100) } +private object B246 { val a = B245.a + Random.nextInt(100) } +private object B247 { val a = B246.a + Random.nextInt(100) } +private object B248 { val a = B247.a + Random.nextInt(100) } +private object B249 { val a = B248.a + Random.nextInt(100) } +private object B250 { val a = B249.a + Random.nextInt(100) } +private object B251 { val a = B250.a + Random.nextInt(100) } +private object B252 { val a = B251.a + Random.nextInt(100) } +private object B253 { val a = B252.a + Random.nextInt(100) } +private object B254 { val a = B253.a + Random.nextInt(100) } +private object B255 { val a = B254.a + Random.nextInt(100) } +private object B256 { val a = B255.a + Random.nextInt(100) } +private object B257 { val a = B256.a + Random.nextInt(100) } +private object B258 { val a = B257.a + Random.nextInt(100) } +private object B259 { val a = B258.a + Random.nextInt(100) } +private object B260 { val a = B259.a + Random.nextInt(100) } +private object B261 { val a = B260.a + Random.nextInt(100) } +private object B262 { val a = B261.a + Random.nextInt(100) } +private object B263 { val a = B262.a + Random.nextInt(100) } +private object B264 { val a = B263.a + Random.nextInt(100) } +private object B265 { val a = B264.a + Random.nextInt(100) } +private object B266 { val a = B265.a + Random.nextInt(100) } +private object B267 { val a = B266.a + Random.nextInt(100) } +private object B268 { val a = B267.a + Random.nextInt(100) } +private object B269 { val a = B268.a + Random.nextInt(100) } +private object B270 { val a = B269.a + Random.nextInt(100) } +private object B271 { val a = B270.a + Random.nextInt(100) } +private object B272 { val a = B271.a + Random.nextInt(100) } +private object B273 { val a = B272.a + Random.nextInt(100) } +private object B274 { val a = B273.a + Random.nextInt(100) } +private object B275 { val a = B274.a + Random.nextInt(100) } +private object B276 { val a = B275.a + Random.nextInt(100) } +private object B277 { val a = B276.a + Random.nextInt(100) } +private object B278 { val a = B277.a + Random.nextInt(100) } +private object B279 { val a = B278.a + Random.nextInt(100) } +private object B280 { val a = B279.a + Random.nextInt(100) } +private object B281 { val a = B280.a + Random.nextInt(100) } +private object B282 { val a = B281.a + Random.nextInt(100) } +private object B283 { val a = B282.a + Random.nextInt(100) } +private object B284 { val a = B283.a + Random.nextInt(100) } +private object B285 { val a = B284.a + Random.nextInt(100) } +private object B286 { val a = B285.a + Random.nextInt(100) } +private object B287 { val a = B286.a + Random.nextInt(100) } +private object B288 { val a = B287.a + Random.nextInt(100) } +private object B289 { val a = B288.a + Random.nextInt(100) } +private object B290 { val a = B289.a + Random.nextInt(100) } +private object B291 { val a = B290.a + Random.nextInt(100) } +private object B292 { val a = B291.a + Random.nextInt(100) } +private object B293 { val a = B292.a + Random.nextInt(100) } +private object B294 { val a = B293.a + Random.nextInt(100) } +private object B295 { val a = B294.a + Random.nextInt(100) } +private object B296 { val a = B295.a + Random.nextInt(100) } +private object B297 { val a = B296.a + Random.nextInt(100) } +private object B298 { val a = B297.a + Random.nextInt(100) } +private object B299 { val a = B298.a + Random.nextInt(100) } +private object B300 { val a = B299.a + Random.nextInt(100) } +private object B301 { val a = B300.a + Random.nextInt(100) } +private object B302 { val a = B301.a + Random.nextInt(100) } +private object B303 { val a = B302.a + Random.nextInt(100) } +private object B304 { val a = B303.a + Random.nextInt(100) } +private object B305 { val a = B304.a + Random.nextInt(100) } +private object B306 { val a = B305.a + Random.nextInt(100) } +private object B307 { val a = B306.a + Random.nextInt(100) } +private object B308 { val a = B307.a + Random.nextInt(100) } +private object B309 { val a = B308.a + Random.nextInt(100) } +private object B310 { val a = B309.a + Random.nextInt(100) } +private object B311 { val a = B310.a + Random.nextInt(100) } +private object B312 { val a = B311.a + Random.nextInt(100) } +private object B313 { val a = B312.a + Random.nextInt(100) } +private object B314 { val a = B313.a + Random.nextInt(100) } +private object B315 { val a = B314.a + Random.nextInt(100) } +private object B316 { val a = B315.a + Random.nextInt(100) } +private object B317 { val a = B316.a + Random.nextInt(100) } +private object B318 { val a = B317.a + Random.nextInt(100) } +private object B319 { val a = B318.a + Random.nextInt(100) } +private object B320 { val a = B319.a + Random.nextInt(100) } +private object B321 { val a = B320.a + Random.nextInt(100) } +private object B322 { val a = B321.a + Random.nextInt(100) } +private object B323 { val a = B322.a + Random.nextInt(100) } +private object B324 { val a = B323.a + Random.nextInt(100) } +private object B325 { val a = B324.a + Random.nextInt(100) } +private object B326 { val a = B325.a + Random.nextInt(100) } +private object B327 { val a = B326.a + Random.nextInt(100) } +private object B328 { val a = B327.a + Random.nextInt(100) } +private object B329 { val a = B328.a + Random.nextInt(100) } +private object B330 { val a = B329.a + Random.nextInt(100) } +private object B331 { val a = B330.a + Random.nextInt(100) } +private object B332 { val a = B331.a + Random.nextInt(100) } +private object B333 { val a = B332.a + Random.nextInt(100) } +private object B334 { val a = B333.a + Random.nextInt(100) } +private object B335 { val a = B334.a + Random.nextInt(100) } +private object B336 { val a = B335.a + Random.nextInt(100) } +private object B337 { val a = B336.a + Random.nextInt(100) } +private object B338 { val a = B337.a + Random.nextInt(100) } +private object B339 { val a = B338.a + Random.nextInt(100) } +private object B340 { val a = B339.a + Random.nextInt(100) } +private object B341 { val a = B340.a + Random.nextInt(100) } +private object B342 { val a = B341.a + Random.nextInt(100) } +private object B343 { val a = B342.a + Random.nextInt(100) } +private object B344 { val a = B343.a + Random.nextInt(100) } +private object B345 { val a = B344.a + Random.nextInt(100) } +private object B346 { val a = B345.a + Random.nextInt(100) } +private object B347 { val a = B346.a + Random.nextInt(100) } +private object B348 { val a = B347.a + Random.nextInt(100) } +private object B349 { val a = B348.a + Random.nextInt(100) } +private object B350 { val a = B349.a + Random.nextInt(100) } +private object B351 { val a = B350.a + Random.nextInt(100) } +private object B352 { val a = B351.a + Random.nextInt(100) } +private object B353 { val a = B352.a + Random.nextInt(100) } +private object B354 { val a = B353.a + Random.nextInt(100) } +private object B355 { val a = B354.a + Random.nextInt(100) } +private object B356 { val a = B355.a + Random.nextInt(100) } +private object B357 { val a = B356.a + Random.nextInt(100) } +private object B358 { val a = B357.a + Random.nextInt(100) } +private object B359 { val a = B358.a + Random.nextInt(100) } +private object B360 { val a = B359.a + Random.nextInt(100) } +private object B361 { val a = B360.a + Random.nextInt(100) } +private object B362 { val a = B361.a + Random.nextInt(100) } +private object B363 { val a = B362.a + Random.nextInt(100) } +private object B364 { val a = B363.a + Random.nextInt(100) } +private object B365 { val a = B364.a + Random.nextInt(100) } +private object B366 { val a = B365.a + Random.nextInt(100) } +private object B367 { val a = B366.a + Random.nextInt(100) } +private object B368 { val a = B367.a + Random.nextInt(100) } +private object B369 { val a = B368.a + Random.nextInt(100) } +private object B370 { val a = B369.a + Random.nextInt(100) } +private object B371 { val a = B370.a + Random.nextInt(100) } +private object B372 { val a = B371.a + Random.nextInt(100) } +private object B373 { val a = B372.a + Random.nextInt(100) } +private object B374 { val a = B373.a + Random.nextInt(100) } +private object B375 { val a = B374.a + Random.nextInt(100) } +private object B376 { val a = B375.a + Random.nextInt(100) } +private object B377 { val a = B376.a + Random.nextInt(100) } +private object B378 { val a = B377.a + Random.nextInt(100) } +private object B379 { val a = B378.a + Random.nextInt(100) } +private object B380 { val a = B379.a + Random.nextInt(100) } +private object B381 { val a = B380.a + Random.nextInt(100) } +private object B382 { val a = B381.a + Random.nextInt(100) } +private object B383 { val a = B382.a + Random.nextInt(100) } +private object B384 { val a = B383.a + Random.nextInt(100) } +private object B385 { val a = B384.a + Random.nextInt(100) } +private object B386 { val a = B385.a + Random.nextInt(100) } +private object B387 { val a = B386.a + Random.nextInt(100) } +private object B388 { val a = B387.a + Random.nextInt(100) } +private object B389 { val a = B388.a + Random.nextInt(100) } +private object B390 { val a = B389.a + Random.nextInt(100) } +private object B391 { val a = B390.a + Random.nextInt(100) } +private object B392 { val a = B391.a + Random.nextInt(100) } +private object B393 { val a = B392.a + Random.nextInt(100) } +private object B394 { val a = B393.a + Random.nextInt(100) } +private object B395 { val a = B394.a + Random.nextInt(100) } +private object B396 { val a = B395.a + Random.nextInt(100) } +private object B397 { val a = B396.a + Random.nextInt(100) } +private object B398 { val a = B397.a + Random.nextInt(100) } +private object B399 { val a = B398.a + Random.nextInt(100) } +private object B400 { val a = B399.a + Random.nextInt(100) } +private object B401 { val a = B400.a + Random.nextInt(100) } +private object B402 { val a = B401.a + Random.nextInt(100) } +private object B403 { val a = B402.a + Random.nextInt(100) } +private object B404 { val a = B403.a + Random.nextInt(100) } +private object B405 { val a = B404.a + Random.nextInt(100) } +private object B406 { val a = B405.a + Random.nextInt(100) } +private object B407 { val a = B406.a + Random.nextInt(100) } +private object B408 { val a = B407.a + Random.nextInt(100) } +private object B409 { val a = B408.a + Random.nextInt(100) } +private object B410 { val a = B409.a + Random.nextInt(100) } +private object B411 { val a = B410.a + Random.nextInt(100) } +private object B412 { val a = B411.a + Random.nextInt(100) } +private object B413 { val a = B412.a + Random.nextInt(100) } +private object B414 { val a = B413.a + Random.nextInt(100) } +private object B415 { val a = B414.a + Random.nextInt(100) } +private object B416 { val a = B415.a + Random.nextInt(100) } +private object B417 { val a = B416.a + Random.nextInt(100) } +private object B418 { val a = B417.a + Random.nextInt(100) } +private object B419 { val a = B418.a + Random.nextInt(100) } +private object B420 { val a = B419.a + Random.nextInt(100) } +private object B421 { val a = B420.a + Random.nextInt(100) } +private object B422 { val a = B421.a + Random.nextInt(100) } +private object B423 { val a = B422.a + Random.nextInt(100) } +private object B424 { val a = B423.a + Random.nextInt(100) } +private object B425 { val a = B424.a + Random.nextInt(100) } +private object B426 { val a = B425.a + Random.nextInt(100) } +private object B427 { val a = B426.a + Random.nextInt(100) } +private object B428 { val a = B427.a + Random.nextInt(100) } +private object B429 { val a = B428.a + Random.nextInt(100) } +private object B430 { val a = B429.a + Random.nextInt(100) } +private object B431 { val a = B430.a + Random.nextInt(100) } +private object B432 { val a = B431.a + Random.nextInt(100) } +private object B433 { val a = B432.a + Random.nextInt(100) } +private object B434 { val a = B433.a + Random.nextInt(100) } +private object B435 { val a = B434.a + Random.nextInt(100) } +private object B436 { val a = B435.a + Random.nextInt(100) } +private object B437 { val a = B436.a + Random.nextInt(100) } +private object B438 { val a = B437.a + Random.nextInt(100) } +private object B439 { val a = B438.a + Random.nextInt(100) } +private object B440 { val a = B439.a + Random.nextInt(100) } +private object B441 { val a = B440.a + Random.nextInt(100) } +private object B442 { val a = B441.a + Random.nextInt(100) } +private object B443 { val a = B442.a + Random.nextInt(100) } +private object B444 { val a = B443.a + Random.nextInt(100) } +private object B445 { val a = B444.a + Random.nextInt(100) } +private object B446 { val a = B445.a + Random.nextInt(100) } +private object B447 { val a = B446.a + Random.nextInt(100) } +private object B448 { val a = B447.a + Random.nextInt(100) } +private object B449 { val a = B448.a + Random.nextInt(100) } +private object B450 { val a = B449.a + Random.nextInt(100) } +private object B451 { val a = B450.a + Random.nextInt(100) } +private object B452 { val a = B451.a + Random.nextInt(100) } +private object B453 { val a = B452.a + Random.nextInt(100) } +private object B454 { val a = B453.a + Random.nextInt(100) } +private object B455 { val a = B454.a + Random.nextInt(100) } +private object B456 { val a = B455.a + Random.nextInt(100) } +private object B457 { val a = B456.a + Random.nextInt(100) } +private object B458 { val a = B457.a + Random.nextInt(100) } +private object B459 { val a = B458.a + Random.nextInt(100) } +private object B460 { val a = B459.a + Random.nextInt(100) } +private object B461 { val a = B460.a + Random.nextInt(100) } +private object B462 { val a = B461.a + Random.nextInt(100) } +private object B463 { val a = B462.a + Random.nextInt(100) } +private object B464 { val a = B463.a + Random.nextInt(100) } +private object B465 { val a = B464.a + Random.nextInt(100) } +private object B466 { val a = B465.a + Random.nextInt(100) } +private object B467 { val a = B466.a + Random.nextInt(100) } +private object B468 { val a = B467.a + Random.nextInt(100) } +private object B469 { val a = B468.a + Random.nextInt(100) } +private object B470 { val a = B469.a + Random.nextInt(100) } +private object B471 { val a = B470.a + Random.nextInt(100) } +private object B472 { val a = B471.a + Random.nextInt(100) } +private object B473 { val a = B472.a + Random.nextInt(100) } +private object B474 { val a = B473.a + Random.nextInt(100) } +private object B475 { val a = B474.a + Random.nextInt(100) } +private object B476 { val a = B475.a + Random.nextInt(100) } +private object B477 { val a = B476.a + Random.nextInt(100) } +private object B478 { val a = B477.a + Random.nextInt(100) } +private object B479 { val a = B478.a + Random.nextInt(100) } +private object B480 { val a = B479.a + Random.nextInt(100) } +private object B481 { val a = B480.a + Random.nextInt(100) } +private object B482 { val a = B481.a + Random.nextInt(100) } +private object B483 { val a = B482.a + Random.nextInt(100) } +private object B484 { val a = B483.a + Random.nextInt(100) } +private object B485 { val a = B484.a + Random.nextInt(100) } +private object B486 { val a = B485.a + Random.nextInt(100) } +private object B487 { val a = B486.a + Random.nextInt(100) } +private object B488 { val a = B487.a + Random.nextInt(100) } +private object B489 { val a = B488.a + Random.nextInt(100) } +private object B490 { val a = B489.a + Random.nextInt(100) } +private object B491 { val a = B490.a + Random.nextInt(100) } +private object B492 { val a = B491.a + Random.nextInt(100) } +private object B493 { val a = B492.a + Random.nextInt(100) } +private object B494 { val a = B493.a + Random.nextInt(100) } +private object B495 { val a = B494.a + Random.nextInt(100) } +private object B496 { val a = B495.a + Random.nextInt(100) } +private object B497 { val a = B496.a + Random.nextInt(100) } +private object B498 { val a = B497.a + Random.nextInt(100) } +private object B499 { val a = B498.a + Random.nextInt(100) } + +private var singletonInitializeNestedRun = false +// Benchmark +fun singletonInitializeNested(): Int { + if (singletonInitializeNestedRun) { + error("Function singletonInitializeNested can be called only once.") + } + singletonInitializeNestedRun = true + + var total = B499.a + + return total +} diff --git a/kotlin-native/performance/swiftinterop/build.gradle.kts b/kotlin-native/performance/swiftinterop/build.gradle.kts new file mode 100644 index 00000000000..e5149a22829 --- /dev/null +++ b/kotlin-native/performance/swiftinterop/build.gradle.kts @@ -0,0 +1,25 @@ +import org.jetbrains.kotlin.gradle.plugin.mpp.NativeBuildType + +/* + * Copyright 2010-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +plugins { + id("swift-benchmarking") +} + +val toolsPath = "../../tools" +val targetExtension = "Macos" +val defaultBuildType = NativeBuildType.RELEASE + +swiftBenchmark { + applicationName = "swiftInterop" + commonSrcDirs = listOf("$toolsPath/benchmarks/shared/src/main/kotlin/report", "src", "../shared/src/main/kotlin") + nativeSrcDirs = listOf("../shared/src/main/kotlin-native/common", "../shared/src/main/kotlin-native/posix") + swiftSources = listOf("$projectDir/swiftSrc/benchmarks.swift", "$projectDir/swiftSrc/main.swift") + compileTasks = listOf("compileKotlinNative", "linkBenchmarkReleaseFrameworkNative") + buildType = (findProperty("nativeBuildType") as String?)?.let { NativeBuildType.valueOf(it) } ?: defaultBuildType + + dependencies.common(project(":endorsedLibraries:kotlinx.cli")) +} \ No newline at end of file diff --git a/kotlin-native/performance/swiftinterop/gradle.properties b/kotlin-native/performance/swiftinterop/gradle.properties new file mode 100644 index 00000000000..d7062dc22a1 --- /dev/null +++ b/kotlin-native/performance/swiftinterop/gradle.properties @@ -0,0 +1 @@ +kotlin.native.home=../../dist \ No newline at end of file diff --git a/kotlin-native/performance/swiftinterop/src/main/kotlin/org/jetbrains/model/CityMap.kt b/kotlin-native/performance/swiftinterop/src/main/kotlin/org/jetbrains/model/CityMap.kt new file mode 100644 index 00000000000..9e8fddd046a --- /dev/null +++ b/kotlin-native/performance/swiftinterop/src/main/kotlin/org/jetbrains/model/CityMap.kt @@ -0,0 +1,122 @@ +/* + * Copyright 2010-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +package org.jetbrains.model + +import org.jetbrains.multigraph.* +import kotlin.comparisons.compareBy + +enum class Transport { CAR, UNDERGROUND, BUS, TROLLEYBUS, TRAM, TAXI, FOOT } +enum class Interest { SIGHT, CULTURE, PARK, ENTERTAINMENT } + +class PlaceAbsenceException(message: String): Exception(message) {} + +data class RouteCost(val moneyCost: Double, val timeCost: Double, val interests: Set, val transport: Set): Cost { + private val comparator = compareBy({ it.moneyCost }, { it.timeCost }, { it.interests.size }, { it.transport.size }) + + override operator fun plus(other: Cost) = + if (other is RouteCost) { + RouteCost(moneyCost + other.moneyCost, timeCost + other.timeCost, + interests.union(other.interests), transport.union(other.transport)) + } else { + error("Expected type is RouteCost") + } + + override operator fun minus(other: Cost) = + if (other is RouteCost) { + RouteCost(if (moneyCost > other.moneyCost) moneyCost - other.moneyCost else 0.0, + if (timeCost > other.timeCost) timeCost - other.timeCost else 0.0, + interests.subtract(other.interests), transport.subtract(other.transport)) + } else { + error("Expected type is RouteCost") + } + + override operator fun compareTo(other: Cost) = + if (other is RouteCost) { + comparator.compare(this, other) + } else { + error("Expected type is RouteCost") + } +} + +internal var placeCounter = 0u + +data class Place(val geoCoordinateX: Double, val geoCoordinateY: Double, val name: String, val interestCategory: Interest) { + private val comparator = compareBy({ it.geoCoordinateX }, { it.geoCoordinateY }) + + val id: UInt + init { + id = placeCounter + placeCounter++ + } + + val fullDescription: String + get() = "Place $name($geoCoordinateX;$geoCoordinateY)" + + fun compareTo(other: Place) = + comparator.compare(this, other) +} + +data class Path(val from: Place, val to: Place, val cost: RouteCost) + +class CityMap { + data class RouteId(val id: UInt, val from: UInt, val to: UInt) + private val graph = Multigraph() + + val allPlaces: Set + get() = graph.allVertexes + val allRoutes: List + get() { + val edges = graph.allEdges + val result = mutableListOf() + edges.forEach { + result.add(RouteId(it, graph.getFrom(it).id, graph.getTo(it).id)) + } + return result + } + + fun addRoute(from: Place, to: Place, cost: RouteCost): UInt { + return graph.addEdge(from, to, cost) + } + + fun getPlaceById(id: UInt): Place { + graph.allVertexes.forEach { + if (it.id == id) { + return it + } + } + throw PlaceAbsenceException("Place with id $id wasn't found.") + } + + fun removePlaceById(id: UInt) { + graph.allVertexes.forEach { + if (it.id == id) { + graph.removeVertex(it) + return + } + } + } + + fun removeRouteById(id: UInt) { + graph.removeEdge(id) + } + + fun getRoutes(start: Place, finish: Place, limits: RouteCost): List> { + val result = graph.searchRoutesWithLimits(start, finish, limits) + return result.map { + it.map { + Path(graph.getFrom(it), graph.getTo(it), graph.getCost(it) as RouteCost) + } + } + } + + fun getRouteById(id: UInt) = + graph.getEdgeById(id) + + fun getAllStraightRoutesFrom(place: Place) = + graph.getEdgesFrom(place).map { Path(graph.getFrom(it.id), graph.getTo(it.id), graph.getCost(it.id) as RouteCost) } + + fun isEmpty() = graph.isEmpty() +} \ No newline at end of file diff --git a/kotlin-native/performance/swiftinterop/src/main/kotlin/org/jetbrains/multigraph/Multigraph.kt b/kotlin-native/performance/swiftinterop/src/main/kotlin/org/jetbrains/multigraph/Multigraph.kt new file mode 100644 index 00000000000..9bab1ea28ca --- /dev/null +++ b/kotlin-native/performance/swiftinterop/src/main/kotlin/org/jetbrains/multigraph/Multigraph.kt @@ -0,0 +1,184 @@ +/* + * Copyright 2010-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +package org.jetbrains.multigraph + +import kotlin.math.pow + +interface Cost { + operator fun plus(other: Cost): Cost + operator fun minus(other: Cost): Cost + override operator fun equals(other: Any?): Boolean + operator fun compareTo(other: Cost): Int +} + +data class Edge(val id: UInt, val from: T, val to: T, val cost: Cost) { + override operator fun equals(other: Any?): Boolean { + return if (other is Edge<*>) (from == other.from && to == other.to && cost == other.cost) else false + } + + override fun hashCode(): Int = + from.hashCode() * 31.0.pow(2.0).toInt() + to.hashCode() * 31 + cost.hashCode() +} + +class EdgeAbsenceMultigraphException(message: String): Exception(message) {} +class VertexAbsenceMultigraphException(message: String): Exception(message) {} + +class Multigraph() { + private var edges = mutableMapOf>>() + private var idCounter = 0u + + val allVertexes: Set + get() { + val outerVertexes = edges.keys + val innerVertexes = edges.map { (_, values) -> + values.map { it.to }.filter { it !in outerVertexes } + }.flatten() + return outerVertexes.union(innerVertexes) + } + + val allEdges: List + get() = edges.values.flatten().map { it.id } + + fun getEdgeById(id: UInt): Edge { + edges.forEach { (_, value) -> + value.forEach { + if (it.id == id) + return it + } + } + throw EdgeAbsenceMultigraphException("Edge with id $id wasn't found.") + } + + fun copyMultigraph(): Multigraph { + val newInstance = Multigraph() + edges.forEach { (vertex, edges) -> + edges.forEach { edge -> + newInstance.addEdge(vertex, edge.to, edge.cost) + } + } + return newInstance + } + + fun addEdge(from: T, to: T, cost: Cost): UInt { + val edge = Edge(idCounter, from, to, cost) + edges.getOrPut(from) { mutableListOf() }.add(edge) + idCounter++ + return edge.id + } + + fun removeEdge(id: UInt) { + try { + val edge = getEdgeById(id) + edges[edge.from]?.remove(edge) + } catch (exception: EdgeAbsenceMultigraphException) { + println("WARNING: no edge with id $id was found.") + } + } + + fun removeVertex(vertex: T) { + edges.remove(vertex) + val edgesToRemove = edges.map { (_, values) -> + values.filter { + it.to == vertex + } + }.flatten() + edgesToRemove.forEach { + removeEdge(it.id) + } + } + + fun checkVertexExistance(vertex: T): Boolean { + return vertex in allVertexes + } + + fun getTo(edgeId: UInt) = + getEdgeById(edgeId).to + + fun getFrom(edgeId: UInt) = + getEdgeById(edgeId).from + + fun getCost(edgeId: UInt) = + getEdgeById(edgeId).cost + + fun getEdgesFrom(vertex: T) = + edges[vertex] ?: listOf>() + + fun isEmpty() = edges.isEmpty() + + fun searchRoutesWithLimits(start: T, finish: T, limits: Cost): List> { + data class WaveStep(val costs: MutableList = mutableListOf(), + val routes: MutableList> = mutableListOf(), + val vertexes: MutableList> = mutableListOf()) + + val currentStepsState = mutableMapOf() + var oldFront = mutableSetOf(start) + val newFront = mutableSetOf() + + if (!checkVertexExistance(start)) { + throw(VertexAbsenceMultigraphException("Start vertex wasn't found in graph.")) + } + if (!checkVertexExistance(finish)) { + throw(VertexAbsenceMultigraphException("Finish vertex wasn't found in graph.")) + } + + allVertexes.forEach { + currentStepsState[it] = WaveStep() + } + while (!oldFront.isEmpty()) { + oldFront.forEach { + val currentStepState = currentStepsState[it] ?: WaveStep() + // Lookup all edges from vertex. + val values = edges.get(it) ?: mutableListOf>() + values.forEach { edge -> + val newRoutes = mutableListOf() + val toStep = currentStepsState[edge.to] ?: WaveStep() + + // Create new pathes and count their costs. + if (currentStepState.routes.isEmpty()) { + val newVertexes = mutableListOf(edge.from, edge.to) + val newCost = edge.cost + if (newCost <= limits && edge.from != edge.to) { + newRoutes.add(edge.id) + toStep.routes.add(newRoutes) + toStep.costs.add(edge.cost) + toStep.vertexes.add(newVertexes) + currentStepsState[edge.to] = toStep + // Add new wave front. + if (edge.to != finish && edge.to !in oldFront) { + newFront.add(edge.to) + } + } + } else { + currentStepState.routes.forEachIndexed { index, it -> + val newRoutes = it.toMutableList() + val oldCost = currentStepState.costs.get(index) + val newCost = edge.cost + oldCost + val newVertexes = currentStepState.vertexes.get(index).toMutableList() + if (newCost <= limits && edge.to !in currentStepState.vertexes.get(index)) { + newRoutes.add(edge.id) + newVertexes.add(edge.to) + var addNewSequence = true + + if (newRoutes !in toStep.routes) { + toStep.routes.add(newRoutes) + toStep.costs.add(newCost) + toStep.vertexes.add(newVertexes) + currentStepsState[edge.to] = toStep + if (edge.to != finish && edge.to !in oldFront) { + newFront.add(edge.to) + } + } + } + } + } + } + } + oldFront = newFront.toMutableSet() + newFront.clear() + } + return currentStepsState[finish]?.routes ?: listOf>() + } +} \ No newline at end of file diff --git a/kotlin-native/performance/swiftinterop/swiftSrc/benchmarks.swift b/kotlin-native/performance/swiftinterop/swiftSrc/benchmarks.swift new file mode 100644 index 00000000000..6b2e02450ef --- /dev/null +++ b/kotlin-native/performance/swiftinterop/swiftSrc/benchmarks.swift @@ -0,0 +1,225 @@ +/* + * Copyright 2010-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +import Foundation +import benchmark + +class SimpleCost: Cost { + let value: Int + + init(cost: Int) { + value = cost + } + + func plus(other: Cost) -> Cost { + let otherInstance = other as! SimpleCost + return SimpleCost(cost: value + otherInstance.value) + } + + func minus(other: Cost) -> Cost { + let otherInstance = other as! SimpleCost + return SimpleCost(cost: value - otherInstance.value) + } + + func compareTo(other: Cost) -> Int32 { + let otherInstance = other as! SimpleCost + if (value < otherInstance.value) { + return -1 + } + if (value == otherInstance.value) { + return 0 + } + return 1 + } +} + +class SwiftInteropBenchmarks { + + let BENCHMARK_SIZE = 10000 + let SMALL_BENCHMARK_SIZE = 50 + let MEDIUM_BENCHMARK_SIZE = 100 + var multigraph = Multigraph() + var cityMap = CityMap() + + func randomInt(border: Int) -> Int { + return Int.random(in: 1 ..< border) + } + + func randomDouble(border: Double) -> Double { + return Double.random(in: 0 ..< border) + } + + func randomString(length: Int) -> String { + let letters = "abcdefghijklmnopqrst" + return String((0.. Transport { + let allValues = [Transport.car, Transport.underground, Transport.bus, Transport.trolleybus, Transport.tram, Transport.taxi, Transport.foot] + return allValues.randomElement()! + } + + func randomInterest() -> Interest { + let allValues = [Interest.sight, Interest.culture, Interest.park, Interest.entertainment] + return allValues.randomElement()! + } + + func randomPlace() -> Place { + return Place(geoCoordinateX: randomDouble(border: 180), geoCoordinateY: randomDouble(border: 90), name: randomString(length: 5), interestCategory: randomInterest()) + } + + func randomRouteCost() -> RouteCost { + let transportCount = randomInt(border: 7) + let interestCount = randomInt(border: 4) + var transports = Set() + var interests = Set() + + for _ in 0...transportCount { + transports.insert(randomTransport()) + } + + for _ in 0...interestCount { + interests.insert(randomInterest()) + } + + return RouteCost(moneyCost: randomDouble(border: 10000), timeCost: randomDouble(border: 24), interests: interests, transport: transports) + } + + func initMultigraph(size: Int) { + multigraph = Multigraph() + for i in 1...size { + multigraph.addEdge(from: NSNumber(value: i), to: NSNumber(value: i + 1), cost: SimpleCost(cost: (i + 1) % i )) + multigraph.addEdge(from: NSNumber(value: i), to: NSNumber(value: i * 2), cost: SimpleCost(cost: (i * 2) % i)) + multigraph.addEdge(from: NSNumber(value: i + 5), to: NSNumber(value: i), cost: SimpleCost(cost: (i + 5) % i)) + } + } + + func createMultigraphOfInt() { + initMultigraph(size: BENCHMARK_SIZE) + } + + func fillCityMap() { + cityMap = CityMap() + for _ in 0...BENCHMARK_SIZE { + cityMap.addRoute(from: randomPlace(), to: randomPlace(), cost: randomRouteCost()) + } + } + + func initCityMap(size: Int) { + cityMap = CityMap() + let allValuesInterests = [Interest.sight, Interest.culture, Interest.park, Interest.entertainment] + let allValuesTransport = [Transport.car, Transport.underground, Transport.bus, Transport.trolleybus, Transport.tram, Transport.taxi, Transport.foot] + for i in 1...size { + let from = Place(geoCoordinateX: Double(i % 180), geoCoordinateY: Double(i % 90 + 90 % i), + name: randomString(length: 5), interestCategory: allValuesInterests[i % allValuesInterests.count]) + let to = Place(geoCoordinateX: Double(i % 180 + 180 % i), geoCoordinateY: Double(i % 90), + name: randomString(length: 5), interestCategory: allValuesInterests[(i + 5) % allValuesInterests.count]) + var transports = Set() + var interests = Set() + for j in 0...i % 2 + 1 { + interests.insert(allValuesInterests[(i + j) % allValuesInterests.count]) + } + for j in 0...i % 2 + 1 { + transports.insert(allValuesTransport[i % allValuesTransport.count]) + } + let cost = RouteCost(moneyCost: Double((i * 2) % 10000), timeCost: Double((i + 3) % 24), interests: interests, transport: transports) + cityMap.addRoute(from: from, to: to, cost: cost) + } + } + + func searchRoutesInSwiftMultigraph() { + initMultigraph(size: SMALL_BENCHMARK_SIZE) + for _ in 0...SMALL_BENCHMARK_SIZE { + var vertexes = Array(multigraph.allVertexes) + var result = multigraph.searchRoutesWithLimits(start: 1, + finish: NSNumber(value: SMALL_BENCHMARK_SIZE / 2 + SMALL_BENCHMARK_SIZE / 4), + limits: SimpleCost(cost: SMALL_BENCHMARK_SIZE / 5)) + var count = result.map{ $0.count }.reduce(0, +) + } + } + + func searchTravelRoutes() { + cityMap = CityMap() + initCityMap(size: BENCHMARK_SIZE) + let transports: Set = [Transport.car, Transport.underground] + let interests: Set = [Interest.sight, Interest.culture] + let cost = RouteCost(moneyCost: 500, timeCost: 6, interests: interests, transport: transports) + for _ in 0...SMALL_BENCHMARK_SIZE { + var result = cityMap.getRoutes(start: Array(cityMap.allPlaces).first!, finish: Array(cityMap.allPlaces).last!, limits: cost) + var totalCost = result.flatMap{ $0 }.map { $0.cost.moneyCost }.reduce(0, +) + } + } + + func availableTransportOnMap() { + cityMap = CityMap() + initCityMap(size: MEDIUM_BENCHMARK_SIZE) + Set(cityMap.allRoutes.map { (cityMap.getRouteById(id: $0.id).cost as! RouteCost).transport }) + } + + func allPlacesMapedByInterests() { + cityMap = CityMap() + initCityMap(size: MEDIUM_BENCHMARK_SIZE) + let placesByInterests = cityMap.allPlaces.reduce([Interest: Array]()) { (dict, place) -> [Interest: Array] in + var dict = dict + if (dict[place.interestCategory] != nil) { + dict[place.interestCategory]?.append(place) + } else { + dict[place.interestCategory] = [place] + } + return dict + } + + } + + func getAllPlacesWithStraightRoutesTo() { + cityMap = CityMap() + initCityMap(size: MEDIUM_BENCHMARK_SIZE) + for _ in 0...SMALL_BENCHMARK_SIZE { + let start = cityMap.allPlaces.randomElement()! + let availableRoutes = cityMap.getAllStraightRoutesFrom(place: start) + var _ = availableRoutes.map { $0.to } + } + } + + func goToAllAvailablePlaces() { + cityMap = CityMap() + initCityMap(size: MEDIUM_BENCHMARK_SIZE) + for _ in 0...SMALL_BENCHMARK_SIZE { + let start = cityMap.allPlaces.randomElement()! + let availableRoutes = cityMap.getAllStraightRoutesFrom(place: start) + availableRoutes.map { 2 * $0.cost.moneyCost } + } + } + + func removeVertexAndEdgesSwiftMultigraph() { + initMultigraph(size: SMALL_BENCHMARK_SIZE) + let multigraphCopy = multigraph.doCopyMultigraph() + var edges = multigraphCopy.allEdges + while (!edges.isEmpty) { + multigraphCopy.removeEdge(id: UInt32(edges.randomElement()!)) + let vertexes = multigraphCopy.allVertexes as! Set + multigraphCopy.removeVertex(vertex: vertexes.randomElement()!) + edges = multigraphCopy.allEdges + } + } + + func stringInterop() { + cityMap = CityMap() + fillCityMap() + let place = cityMap.allPlaces.first! + for _ in 0...BENCHMARK_SIZE { + let _ = place.fullDescription + } + } + + func simpleFunction() { + cityMap = CityMap() + fillCityMap() + let place = cityMap.allPlaces.first! + for _ in 0...BENCHMARK_SIZE { + let _ = place.compareTo(other:place) + } + } +} \ No newline at end of file diff --git a/kotlin-native/performance/swiftinterop/swiftSrc/main.swift b/kotlin-native/performance/swiftinterop/swiftSrc/main.swift new file mode 100644 index 00000000000..9e8116de78e --- /dev/null +++ b/kotlin-native/performance/swiftinterop/swiftSrc/main.swift @@ -0,0 +1,53 @@ +/* + * Copyright 2010-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +import Foundation +import benchmark + +var runner = BenchmarksRunner() +let args = KotlinArray(size: Int32(CommandLine.arguments.count - 1), init: {index in + CommandLine.arguments[Int(truncating: index) + 1] as NSString +}) + +let companion = BenchmarkEntryWithInit.Companion() + +var swiftLauncher = SwiftLauncher() +swiftLauncher.add(name: "createMultigraphOfInt", benchmark: companion.create(ctor: { return SwiftInteropBenchmarks() }, + lambda: { ($0 as! SwiftInteropBenchmarks).createMultigraphOfInt() })) + swiftLauncher.add(name: "fillCityMap", benchmark: companion.create(ctor: { return SwiftInteropBenchmarks() }, + lambda: { ($0 as! SwiftInteropBenchmarks).fillCityMap() })) + swiftLauncher.add(name: "searchRoutesInSwiftMultigraph", benchmark: companion.create(ctor: { return SwiftInteropBenchmarks() }, + lambda: { ($0 as! SwiftInteropBenchmarks).searchRoutesInSwiftMultigraph () })) + swiftLauncher.add(name: "searchTravelRoutes", benchmark: companion.create(ctor: { return SwiftInteropBenchmarks() }, + lambda: { ($0 as! SwiftInteropBenchmarks).searchTravelRoutes() })) + swiftLauncher.add(name: "availableTransportOnMap", benchmark: companion.create(ctor: { return SwiftInteropBenchmarks() }, + lambda: { ($0 as! SwiftInteropBenchmarks).availableTransportOnMap() })) + swiftLauncher.add(name: "allPlacesMapedByInterests", benchmark: companion.create(ctor: { return SwiftInteropBenchmarks() }, + lambda: { ($0 as! SwiftInteropBenchmarks).allPlacesMapedByInterests() })) + swiftLauncher.add(name: "getAllPlacesWithStraightRoutesTo", benchmark: companion.create(ctor: { return SwiftInteropBenchmarks() }, + lambda: { ($0 as! SwiftInteropBenchmarks).getAllPlacesWithStraightRoutesTo() })) + swiftLauncher.add(name: "goToAllAvailablePlaces", benchmark: companion.create(ctor: { return SwiftInteropBenchmarks() }, + lambda: { ($0 as! SwiftInteropBenchmarks).goToAllAvailablePlaces() })) + swiftLauncher.add(name: "removeVertexAndEdgesSwiftMultigraph", benchmark: companion.create(ctor: { return SwiftInteropBenchmarks() }, + lambda: { ($0 as! SwiftInteropBenchmarks).removeVertexAndEdgesSwiftMultigraph() })) + swiftLauncher.add(name: "stringInterop", benchmark: companion.create(ctor: { return SwiftInteropBenchmarks() }, + lambda: { ($0 as! SwiftInteropBenchmarks).stringInterop() })) + swiftLauncher.add(name: "simpleFunction", benchmark: companion.create(ctor: { return SwiftInteropBenchmarks() }, + lambda: { ($0 as! SwiftInteropBenchmarks).simpleFunction() })) +runner.runBenchmarks(args: args, run: { (arguments: BenchmarkArguments) -> [BenchmarkResult] in + if arguments is BaseBenchmarkArguments { + let argumentsList: BaseBenchmarkArguments = arguments as! BaseBenchmarkArguments + return swiftLauncher.launch(numWarmIterations: argumentsList.warmup, + numberOfAttempts: argumentsList.repeat, + prefix: argumentsList.prefix, filters: argumentsList.filter, + filterRegexes: argumentsList.filterRegex, + verbose: argumentsList.verbose) + } + return [BenchmarkResult]() +}, parseArgs: { (args: KotlinArray, benchmarksListAction: (() -> KotlinUnit)) -> BenchmarkArguments? in + return runner.parse(args: args, benchmarksListAction: swiftLauncher.benchmarksListAction) }, + collect: { (benchmarks: [BenchmarkResult], arguments: BenchmarkArguments) -> Void in + runner.collect(results: benchmarks, arguments: arguments) +}, benchmarksListAction: swiftLauncher.benchmarksListAction) \ No newline at end of file diff --git a/kotlin-native/performance/videoplayer/build.gradle.kts b/kotlin-native/performance/videoplayer/build.gradle.kts new file mode 100644 index 00000000000..9ced41dea99 --- /dev/null +++ b/kotlin-native/performance/videoplayer/build.gradle.kts @@ -0,0 +1,85 @@ +/* + * Copyright 2010-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +import org.jetbrains.kotlin.PlatformInfo +import org.jetbrains.kotlin.getCompileOnlyBenchmarksOpts +import org.jetbrains.kotlin.getNativeProgramExtension +import org.jetbrains.kotlin.mingwPath + +plugins { + id("compile-benchmarking") +} + +val dist = file(findProperty("kotlin.native.home") ?: "dist") +val toolSuffix = if (System.getProperty("os.name").startsWith("Windows")) ".bat" else "" +val binarySuffix = getNativeProgramExtension() + +val linkerOpts = when { + PlatformInfo.isMac() -> listOf("-linker-options","-L/opt/local/lib", "-linker-options", "-L/usr/local/lib") + PlatformInfo.isLinux() -> listOf("-linker-options", "-L/usr/lib/x86_64-linux-gnu", "-linker-options", "-L/usr/lib64") + PlatformInfo.isWindows() -> listOf("-linker-options", "-L$mingwPath/lib") + else -> error("Unsupported platform") +} + +var includeDirsFfmpeg = emptyList() +var filterDirsFfmpeg = emptyList() +when { + PlatformInfo.isMac() -> filterDirsFfmpeg = listOf( + "-headerFilterAdditionalSearchPrefix", "/opt/local/include", + "-headerFilterAdditionalSearchPrefix", "/usr/local/include" + ) + PlatformInfo.isLinux() -> filterDirsFfmpeg = listOf( + "-headerFilterAdditionalSearchPrefix", "/usr/include", + "-headerFilterAdditionalSearchPrefix", "/usr/include/x86_64-linux-gnu", + "-headerFilterAdditionalSearchPrefix", "/usr/include/ffmpeg" + ) + PlatformInfo.isWindows() -> includeDirsFfmpeg = listOf("-compiler-option", "-I$mingwPath/include") +} + +var includeDirsSdl = when { + PlatformInfo.isMac() -> listOf( + "-compiler-option", "-I/opt/local/include/SDL2", + "-compiler-option", "-I/usr/local/include/SDL2" + ) + PlatformInfo.isLinux() -> listOf("-compiler-option", "-I/usr/include/SDL2") + PlatformInfo.isWindows() -> listOf("-compiler-option", "-I$mingwPath/include/SDL2") + else -> error("Unsupported platform") +} + +val defaultCompilerOpts = listOf("-g") +val buildOpts = getCompileOnlyBenchmarksOpts(project, defaultCompilerOpts) + +compileBenchmark { + applicationName = "Videoplayer" + repeatNumber = 10 + compilerOpts = buildOpts + buildSteps { + step("runCinteropFfmpeg") { + command = listOf( + "$dist/bin/cinterop$toolSuffix", + "-o", "$dist/../samples/videoplayer/build/classes/kotlin/videoPlayer/main/videoplayer-cinterop-ffmpeg.klib", + "-def", "$dist/../samples/videoplayer/src/nativeInterop/cinterop/ffmpeg.def" + ) + filterDirsFfmpeg + includeDirsFfmpeg + } + step("runCinteropSdl") { + command = listOf( + "$dist/bin/cinterop$toolSuffix", + "-o", "$dist/../samples/videoplayer/build/classes/kotlin/videoPlayer/main/videoplayer-cinterop-sdl.klib", + "-def", "$dist/../samples/videoplayer/src/nativeInterop/cinterop/sdl.def" + ) + includeDirsSdl + } + step("runKonanProgram") { + command = listOf( + "$dist/bin/konanc$toolSuffix", + "-ea", "-p", "program", + "-o", "${buildDir.absolutePath}/program$binarySuffix", + "-l", "$dist/../samples/videoplayer/build/classes/kotlin/videoPlayer/main/videoplayer-cinterop-ffmpeg.klib", + "-l", "$dist/../samples/videoplayer/build/classes/kotlin/videoPlayer/main/videoplayer-cinterop-sdl.klib", + "-Xmulti-platform", "$dist/../samples/videoplayer/src/videoPlayerMain/kotlin", + "-entry", "sample.videoplayer.main" + ) + buildOpts + linkerOpts + } + } +} diff --git a/kotlin-native/performance/videoplayer/gradle.properties b/kotlin-native/performance/videoplayer/gradle.properties new file mode 100644 index 00000000000..d7062dc22a1 --- /dev/null +++ b/kotlin-native/performance/videoplayer/gradle.properties @@ -0,0 +1 @@ +kotlin.native.home=../../dist \ No newline at end of file diff --git a/kotlin-native/platformLibs/build.gradle b/kotlin-native/platformLibs/build.gradle new file mode 100644 index 00000000000..387df4de4e1 --- /dev/null +++ b/kotlin-native/platformLibs/build.gradle @@ -0,0 +1,162 @@ +import org.jetbrains.kotlin.gradle.plugin.konan.tasks.KonanCacheTask +import org.jetbrains.kotlin.KlibInstall +import org.jetbrains.kotlin.konan.target.* +import org.jetbrains.kotlin.konan.util.* + +import static org.jetbrains.kotlin.konan.util.VisibleNamedKt.getVisibleName + +buildscript { + repositories { + maven { + url 'https://cache-redirector.jetbrains.com/maven-central' + } + mavenCentral() + maven { + url buildKotlinCompilerRepo + } + maven { + url kotlinCompilerRepo + } + maven { + url "https://kotlin.bintray.com/kotlinx" + } + } + + dependencies { + classpath "org.jetbrains.kotlin:kotlin-native-gradle-plugin:$gradlePluginVersion" + classpath "org.jetbrains.kotlin:kotlin-native-build-tools:$konanVersion" + } +} +// These properties are used by the 'konan' plugin, thus we set them before applying it. +ext.konanHome = distDir.absolutePath +def jvmArguments = [project.findProperty("platformLibsJvmArgs") ?: "-Xmx6G", *HostManager.defaultJvmArgs] +ext.jvmArgs = jvmArguments.join(" ") +ext.setProperty("org.jetbrains.kotlin.native.home", konanHome) +ext.setProperty("konan.jvmArgs", jvmArgs) + +apply plugin: 'konan' + +//#region Util functions. +private ArrayList targetDefFiles(KonanTarget target) { + file("src/platform/${getVisibleName(target.family)}") + .listFiles() + .findAll { it.name.endsWith(".def") } + // The libz.a/libz.so and zlib.h are missing in MIPS sysroots. + // Just workaround it until we have sysroots corrected. + .findAll { ! ((target in targetsWithoutZlib) && it.name == 'zlib.def') } + .collect { DefFileKt.DefFile(it, target) } +} + +private String defFileToLibName(String target, String name) { + return "$target-$name".toString() +} +//#endregion + +// TODO: I think most for the non-DSL language below can either be incorporated into DSL +// or moved out of .gradle file. +project.rootProject.ext.platformManager.enabled.each { target -> + + def targetName = target.visibleName + + ArrayList installTasks = [] + ArrayList cacheTasks = [] + + if (target in cacheableTargets) { + task "${targetName}StdlibCache"(type: KonanCacheTask) { + it.target = targetName + originalKlib = file("$konanHome/klib/common/stdlib") + cacheRoot = file("$konanHome/klib/cache") + + dependsOn ":${targetName}CrossDistRuntime" + } + } + + targetDefFiles(target).each { df -> + def libName = defFileToLibName(targetName, df.name) + def fileNamePrefix = PlatformLibsInfo.namePrefix + + konanArtifacts { + interop (libName, targets: [targetName]) { + defFile df.file + artifactName "${fileNamePrefix}${df.name}" + noDefaultLibs true + noEndorsedLibs true + libraries { + klibs df.config.depends.collect { + "${fileNamePrefix}${it}".toString() + } + } + extraOpts '-Xpurge-user-libs', "-Xshort-module-name", df.name + compilerOpts "-fmodules-cache-path=${project.buildDir}/clangModulesCache" + } + } + + def libTask = konanArtifacts."$libName"."$targetName" + libTask.dependsOn df.config.depends.collect{ defFileToLibName(targetName, it) } + libTask.dependsOn ":${targetName}CrossDist" + libTask.enableParallel = true + + task "$libName"(type: KlibInstall) { + klib = libTask.artifact + repo = file("$konanHome/klib/platform/$targetName") + it.target = targetName + dependsOn libTask + + } + installTasks.add(tasks[libName]) + + if (target in cacheableTargets) { + task "${libName}Cache"(type: KonanCacheTask) { + it.target = targetName + originalKlib = tasks[libName].installDir + cacheRoot = file("$konanHome/klib/cache") + + dependsOn ":${targetName}StdlibCache" + dependsOn tasks[libName] + dependsOn df.config.depends.collect { + def depName = defFileToLibName(targetName, it) + "${depName}Cache" + } + + cacheTasks.add(it) + } + } + } + + task "${targetName}Install" { + dependsOn installTasks + } + + if (target in cacheableTargets) { + task "${targetName}Cache" { + dependsOn cacheTasks + + group = BasePlugin.BUILD_GROUP + description = "Builds the compilation cache for platform: ${targetName}" + } + } +} + +// TODO: Don't install libraries here - copy them in the distPlatformLibs task +task hostInstall { + dependsOn tasks.withType(KlibInstall.class).findAll { + it.target == HostManager.hostName + } +} + +task hostCache { + dependsOn tasks.withType(KonanCacheTask.class).findAll { + it.target == HostManager.hostName + } +} + +task install { + dependsOn tasks.withType(KlibInstall.class) +} + +task cache { + dependsOn tasks.withType(KonanCacheTask.class) + + group = BasePlugin.BUILD_GROUP + description = "Builds all the compilation caches" +} diff --git a/kotlin-native/platformLibs/src/platform/android/android.def b/kotlin-native/platformLibs/src/platform/android/android.def new file mode 100644 index 00000000000..1dbebedc497 --- /dev/null +++ b/kotlin-native/platformLibs/src/platform/android/android.def @@ -0,0 +1,79 @@ +depends = posix +package = platform.android +headers = jni.h stdbool.h \ + android/NeuralNetworks.h \ + android/api-level.h android/asset_manager.h android/asset_manager_jni.h \ + android/bitmap.h \ + android/choreographer.h android/configuration.h \ + android/data_space.h android/dlext.h \ + android/fdsan.h android/font.h android/font_matcher.h \ + android/hardware_buffer.h android/hardware_buffer_jni.h \ + android/input.h \ + android/keycodes.h \ + android/log.h android/looper.h \ + android/multinetwork.h \ + android/native_activity.h android/native_window.h android/native_window_jni.h android/ndk-version.h \ + android/obb.h \ + android/rect.h \ + android/sensor.h android/set_abort_message.h android/sharedmem.h android/sharedmem_jni.h \ + android/storage_manager.h android/surface_texture.h android/surface_texture_jni.h \ + android/sync.h android/system_fonts.h \ + android/trace.h \ + android/versioning.h \ + android/window.h + +headerFilter = ** +linkerOpts = -landroid -llog -ljnigraphics + +--- + +struct NativeActivityState { + struct ANativeActivity* activity; + void* savedState; + size_t savedStateSize; + struct ALooper* looper; +}; + +void getNativeActivityState(struct NativeActivityState* state); + +void notifySysEventProcessed(); + +#define LOOPER_ID_SYS 1 + +typedef enum NativeActivityEventKind { + UNKNOWN, + DESTROY, + START, + RESUME, + SAVE_INSTANCE_STATE, + PAUSE, + STOP, + CONFIGURATION_CHANGED, + LOW_MEMORY, + WINDOW_GAINED_FOCUS, + WINDOW_LOST_FOCUS, + NATIVE_WINDOW_CREATED, + NATIVE_WINDOW_DESTROYED, + INPUT_QUEUE_CREATED, + INPUT_QUEUE_DESTROYED +} NativeActivityEventKind; + +struct NativeActivityEvent { + NativeActivityEventKind eventKind; +}; + +struct NativeActivitySaveStateEvent { + NativeActivityEventKind eventKind; + void* savedState; + size_t savedStateSize; +}; + +struct NativeActivityWindowEvent { + NativeActivityEventKind eventKind; + struct ANativeWindow* window; +}; + +struct NativeActivityQueueEvent { + NativeActivityEventKind eventKind; + struct AInputQueue* queue; +}; diff --git a/kotlin-native/platformLibs/src/platform/android/builtin.def b/kotlin-native/platformLibs/src/platform/android/builtin.def new file mode 100644 index 00000000000..d7d93621827 --- /dev/null +++ b/kotlin-native/platformLibs/src/platform/android/builtin.def @@ -0,0 +1,97 @@ +package = platform.builtin +headerFilter = +language = C +--- +// See https://github.com/llvm-mirror/clang/blob/master/include/clang/Basic/Builtins.def +// TODO: autogenerate from machine format. + +// Returns x with the order of the bytes reversed; for example, 0xaabb becomes 0xbbaa. Byte here always means exactly 8 bits. +static inline short builtin_bswap16(short x) { + return __builtin_bswap16(x); +} + +static inline int builtin_bswap32(int x) { + return __builtin_bswap32(x); +} + +static inline long long builtin_bswap64(long long x) { + return __builtin_bswap64(x); +} + +// Returns the number of leading 0-bits in x, starting at the most significant bit position. If x is 0, the result is undefined. +static inline int builtin_clzs(unsigned short x) { + return __builtin_clzs(x); +} + +static inline int builtin_clz(unsigned int x) { + return __builtin_clz(x); +} + +static inline int builtin_clzl(unsigned long x) { + return __builtin_clzl(x); +} + +static inline int builtin_clzll(unsigned long long x) { + return __builtin_clzll(x); +} + +// Returns the number of trailing 0-bits in x, starting at the least significant bit position. If x is 0, the result is undefined. +static inline int builtin_ctzs(unsigned short x) { + return __builtin_ctzs(x); +} + +static inline int builtin_ctz(unsigned int x) { + return __builtin_ctz(x); +} + +static inline int builtin_ctzl(unsigned long x) { + return __builtin_ctzl(x); +} + +static inline int builtin_ctzll(unsigned long long x) { + return __builtin_ctzll(x); +} + +// Returns one plus the index of the least significant 1-bit of x, or if x is zero, returns zero. +static inline int builtin_ffs(int x) { + return __builtin_ffs(x); +} + +static inline int builtin_ffsl(long x) { + return __builtin_ffsl(x); +} + +static inline int builtin_ffsll(long long x) { + return __builtin_ffsll(x); +} + +// Returns the parity of x, i.e. the number of 1-bits in x modulo 2. +static inline int builtin_parity(int x) { + return __builtin_parity(x); +} + +static inline int builtin_parityl(unsigned long x) { + return __builtin_parityl(x); +} + +static inline int builtin_parityll(unsigned long long x) { + return __builtin_parityll(x); +} + +// Returns the number of 1-bits in x. +static inline int builtin_popcount(int x) { + return __builtin_popcount(x); +} + +static inline int builtin_popcountl(long x) { + return __builtin_popcountl(x); +} + +static inline int builtin_popcountll(long long x) { + return __builtin_popcountll(x); +} + +// This function is used to flush the processor's instruction cache for the region of memory between begin inclusive and end exclusive. +static inline void builtin_clear_cache(void* begin, void* end) { + __builtin___clear_cache(begin, end); +} \ No newline at end of file diff --git a/kotlin-native/platformLibs/src/platform/android/egl.def b/kotlin-native/platformLibs/src/platform/android/egl.def new file mode 100644 index 00000000000..be095f0806a --- /dev/null +++ b/kotlin-native/platformLibs/src/platform/android/egl.def @@ -0,0 +1,5 @@ +depends = glesCommon posix +package = platform.egl +headers = EGL/egl.h EGL/eglext.h EGL/eglplatform.h +headerFilter = EGL/** +linkerOpts = -lEGL \ No newline at end of file diff --git a/kotlin-native/platformLibs/src/platform/android/gles.def b/kotlin-native/platformLibs/src/platform/android/gles.def new file mode 100644 index 00000000000..e1700b20b0d --- /dev/null +++ b/kotlin-native/platformLibs/src/platform/android/gles.def @@ -0,0 +1,5 @@ +depends = glesCommon posix +package = platform.gles +headers = GLES/gl.h GLES/glext.h GLES/glplatform.h +headerFilter = GLES/** +linkerOpts = -lGLESv1_CM \ No newline at end of file diff --git a/kotlin-native/platformLibs/src/platform/android/gles2.def b/kotlin-native/platformLibs/src/platform/android/gles2.def new file mode 100644 index 00000000000..3a542ccbd41 --- /dev/null +++ b/kotlin-native/platformLibs/src/platform/android/gles2.def @@ -0,0 +1,5 @@ +depends = glesCommon posix +package = platform.gles2 +headers = GLES2/gl2.h GLES2/gl2ext.h GLES2/gl2platform.h +headerFilter = GLES2/** +linkerOpts = -lGLESv2 diff --git a/kotlin-native/platformLibs/src/platform/android/gles3.def b/kotlin-native/platformLibs/src/platform/android/gles3.def new file mode 100644 index 00000000000..579b3b30a55 --- /dev/null +++ b/kotlin-native/platformLibs/src/platform/android/gles3.def @@ -0,0 +1,5 @@ +depends = glesCommon posix +package = platform.gles3 +headers = GLES3/gl3.h GLES3/gl3ext.h GLES3/gl3platform.h +headerFilter = GLES3/** +linkerOpts = -lGLESv3 \ No newline at end of file diff --git a/kotlin-native/platformLibs/src/platform/android/gles31.def b/kotlin-native/platformLibs/src/platform/android/gles31.def new file mode 100644 index 00000000000..f3380643a55 --- /dev/null +++ b/kotlin-native/platformLibs/src/platform/android/gles31.def @@ -0,0 +1,5 @@ +depends = gles3 glesCommon posix +package = platform.gles31 +headers = GLES3/gl31.h +headerFilter = GLES3/** +linkerOpts = -lGLESv3 \ No newline at end of file diff --git a/kotlin-native/platformLibs/src/platform/android/glesCommon.def b/kotlin-native/platformLibs/src/platform/android/glesCommon.def new file mode 100644 index 00000000000..c4ded0d28ae --- /dev/null +++ b/kotlin-native/platformLibs/src/platform/android/glesCommon.def @@ -0,0 +1,4 @@ +depends = posix +package = platform.glescommon +headers = KHR/khrplatform.h +headerFilter = KHR/** diff --git a/kotlin-native/platformLibs/src/platform/android/linux.def b/kotlin-native/platformLibs/src/platform/android/linux.def new file mode 100644 index 00000000000..dd8f80d5694 --- /dev/null +++ b/kotlin-native/platformLibs/src/platform/android/linux.def @@ -0,0 +1,14 @@ +depends = posix +package = platform.linux +headers = byteswap.h elf.h endian.h features.h lastlog.h link.h \ + malloc.h mntent.h termio.h \ + uchar.h \ + sys/epoll.h sys/inotify.h sys/klog.h sys/sendfile.h \ + sys/sysconf.h sys/sysinfo.h \ + linux/if_ether.h linux/utime.h \ + net/if_packet.h netinet/ether.h netinet/in6.h netpacket/packet.h +headers.android_arm32 = time64.h + +headerFilter = ** + +linkerOpts = -ldl diff --git a/kotlin-native/platformLibs/src/platform/android/media.def b/kotlin-native/platformLibs/src/platform/android/media.def new file mode 100644 index 00000000000..7e3d112cb80 --- /dev/null +++ b/kotlin-native/platformLibs/src/platform/android/media.def @@ -0,0 +1,6 @@ +depends = android posix +package = platform.media +headers = media/NdkMediaCodec.h media/NdkMediaCrypto.h media/NdkMediaDrm.h media/NdkMediaError.h \ + media/NdkMediaExtractor.h media/NdkMediaFormat.h media/NdkMediaMuxer.h +headerFilter = media/** +linkerOpts = -lmediandk diff --git a/kotlin-native/platformLibs/src/platform/android/omxal.def b/kotlin-native/platformLibs/src/platform/android/omxal.def new file mode 100644 index 00000000000..5aaaac2cd76 --- /dev/null +++ b/kotlin-native/platformLibs/src/platform/android/omxal.def @@ -0,0 +1,5 @@ +depends = posix +package = platform.omxal +headers = OMXAL/OpenMAXAL.h OMXAL/OpenMAXAL_Android.h OMXAL/OpenMAXAL_Platform.h +headerFilter = OMXAL/** +linkerOpts = -lOpenMAXAL \ No newline at end of file diff --git a/kotlin-native/platformLibs/src/platform/android/posix.def b/kotlin-native/platformLibs/src/platform/android/posix.def new file mode 100644 index 00000000000..a4a074f5cfb --- /dev/null +++ b/kotlin-native/platformLibs/src/platform/android/posix.def @@ -0,0 +1,45 @@ +depends = +package = platform.posix +headers = alloca.h ar.h assert.h complex.h ctype.h dirent.h dlfcn.h err.h errno.h fcntl.h \ + fenv.h fnmatch.h fts.h ftw.h getopt.h grp.h inttypes.h libgen.h limits.h \ + locale.h math.h memory.h netdb.h paths.h poll.h \ + pthread.h pwd.h regex.h resolv.h sched.h search.h semaphore.h setjmp.h signal.h \ + stdatomic.h stdbool.h stdint.h stdio.h stdlib.h string.h strings.h syslog.h termios.h \ + time.h ucontext.h unistd.h utime.h utmp.h wchar.h wctype.h xlocale.h \ + net/ethernet.h net/if.h net/if_arp.h net/route.h \ + netinet/icmp6.h netinet/if_ether.h netinet/in.h netinet/in_systm.h \ + netinet/ip.h netinet/ip6.h netinet/ip_icmp.h netinet/tcp.h netinet/udp.h \ + sys/ioctl.h sys/ipc.h sys/mman.h sys/poll.h sys/ptrace.h \ + sys/queue.h sys/select.h sys/shm.h sys/stat.h \ + sys/time.h sys/times.h sys/utsname.h sys/wait.h + +linkerOpts = -ldl + +--- +// cinterop -target android_arm32 -def klib/src/platform/android/posix.def -o platform.posix.klib + +// Wrapper to access errno variable. +static int posix_errno() { + return errno; +} + +static void set_posix_errno(int value) { + errno = value; +} + + +// Wrapper to access h_errno variable. +static int posix_h_errno() { + return h_errno; +} + +static void set_posix_h_errno(int value) { + h_errno = value; +} + +static int init_sockets() { + return 0; +} + +static void deinit_sockets() { +} diff --git a/kotlin-native/platformLibs/src/platform/android/sles.def b/kotlin-native/platformLibs/src/platform/android/sles.def new file mode 100644 index 00000000000..d5ec2583343 --- /dev/null +++ b/kotlin-native/platformLibs/src/platform/android/sles.def @@ -0,0 +1,6 @@ +depends = posix +package = platform.sles +headers = SLES//OpenSLES.h SLES/OpenSLES_Android.h SLES/OpenSLES_AndroidConfiguration.h \ + SLES/OpenSLES_AndroidMetadata.h SLES/OpenSLES_Platform.h +headerFilter = SLES/** +linkerOpts = -lOpenSLES diff --git a/kotlin-native/platformLibs/src/platform/android/zlib.def b/kotlin-native/platformLibs/src/platform/android/zlib.def new file mode 100644 index 00000000000..69ee2779d23 --- /dev/null +++ b/kotlin-native/platformLibs/src/platform/android/zlib.def @@ -0,0 +1,34 @@ +depends = posix +package = platform.zlib +headers = zconf.h zlib.h +headerFilter = zlib.h +compilerOpts = -DByte=uByte -DBytef=uBytef +linkerOpts = -lz + +--- +#undef deflateInit +static inline int deflateInit(z_streamp strm, int level) { + return deflateInit_(strm, level, ZLIB_VERSION, (int)sizeof(z_stream)); +} + +#undef deflateInit2 +static inline int deflateInit2(z_streamp strm, int level, int method, + int windowBits, int memLevel, int strategy) { + return deflateInit2_(strm, level, method, windowBits, memLevel, + strategy, ZLIB_VERSION, (int)sizeof(z_stream)); +} + +#undef inflateInit +static inline int inflateInit(z_streamp strm) { + return inflateInit_(strm, ZLIB_VERSION, (int)sizeof(z_stream)); +} + +#undef inflateInit2 +static inline int inflateInit2(z_streamp strm, int windowBits) { + return inflateInit2_(strm, windowBits, ZLIB_VERSION, (int)sizeof(z_stream)); +} + +#undef inflateBackInit +static inline int inflateBackInit(z_streamp strm, int windowBits, unsigned char *window) { + return inflateBackInit_(strm, windowBits, window, ZLIB_VERSION, (int)sizeof(z_stream)); +} diff --git a/kotlin-native/platformLibs/src/platform/ios/ARKit.def b/kotlin-native/platformLibs/src/platform/ios/ARKit.def new file mode 100644 index 00000000000..d7cad93187a --- /dev/null +++ b/kotlin-native/platformLibs/src/platform/ios/ARKit.def @@ -0,0 +1,7 @@ +depends = AVFoundation AudioToolbox CFNetwork CoreAudio CoreAudioTypes CoreFoundation CoreGraphics CoreImage CoreLocation CoreMIDI CoreML CoreMedia CoreText CoreVideo EAGL FileProvider Foundation GLKit IOSurface ImageIO MediaToolbox Metal OpenGLESCommon QuartzCore QuickLook SceneKit Security SpriteKit UIKit UniformTypeIdentifiers UserNotifications Vision darwin posix +language = Objective-C +package = platform.ARKit +modules = ARKit + +compilerOpts = -framework ARKit +linkerOpts = -framework ARKit diff --git a/kotlin-native/platformLibs/src/platform/ios/AVFoundation.def b/kotlin-native/platformLibs/src/platform/ios/AVFoundation.def new file mode 100644 index 00000000000..174464d163d --- /dev/null +++ b/kotlin-native/platformLibs/src/platform/ios/AVFoundation.def @@ -0,0 +1,9 @@ +depends = AudioToolbox CFNetwork CoreAudio CoreAudioTypes CoreFoundation CoreGraphics CoreMIDI CoreMedia CoreVideo EAGL Foundation IOSurface ImageIO MediaToolbox Metal OpenGLESCommon QuartzCore Security UniformTypeIdentifiers darwin posix +language = Objective-C +package = platform.AVFoundation +headers = AVFoundation/AVFoundation.h AVFoundation/AVFAudio.h AVFoundation/AVAudioBuffer.h + +headerFilter = AVFoundation/** AVFAudio/** + +compilerOpts = -framework AVFoundation +linkerOpts = -framework AVFoundation diff --git a/kotlin-native/platformLibs/src/platform/ios/AVKit.def b/kotlin-native/platformLibs/src/platform/ios/AVKit.def new file mode 100644 index 00000000000..a28c853fa4d --- /dev/null +++ b/kotlin-native/platformLibs/src/platform/ios/AVKit.def @@ -0,0 +1,7 @@ +depends = AVFoundation AudioToolbox CFNetwork CoreAudio CoreAudioTypes CoreFoundation CoreGraphics CoreImage CoreMIDI CoreMedia CoreText CoreVideo EAGL FileProvider Foundation IOSurface ImageIO MediaToolbox Metal OpenGLESCommon QuartzCore Security UIKit UniformTypeIdentifiers UserNotifications darwin posix +language = Objective-C +package = platform.AVKit +modules = AVKit + +compilerOpts = -framework AVKit +linkerOpts = -framework AVKit diff --git a/kotlin-native/platformLibs/src/platform/ios/Accelerate.def b/kotlin-native/platformLibs/src/platform/ios/Accelerate.def new file mode 100644 index 00000000000..ab422998dc1 --- /dev/null +++ b/kotlin-native/platformLibs/src/platform/ios/Accelerate.def @@ -0,0 +1,7 @@ +depends = CoreFoundation CoreGraphics CoreVideo IOSurface darwin posix +language = Objective-C +package = platform.Accelerate +modules = Accelerate + +compilerOpts = -framework Accelerate +linkerOpts = -framework Accelerate diff --git a/kotlin-native/platformLibs/src/platform/ios/Accessibility.def b/kotlin-native/platformLibs/src/platform/ios/Accessibility.def new file mode 100644 index 00000000000..c7f80f890c8 --- /dev/null +++ b/kotlin-native/platformLibs/src/platform/ios/Accessibility.def @@ -0,0 +1,6 @@ +depends = CFNetwork CoreFoundation CoreGraphics Foundation Security darwin posix +language = Objective-C +package = platform.Accessibility +modules = Accessibility +compilerOpts = -framework Accessibility +linkerOpts = -framework Accessibility diff --git a/kotlin-native/platformLibs/src/platform/ios/Accounts.def b/kotlin-native/platformLibs/src/platform/ios/Accounts.def new file mode 100644 index 00000000000..cd6c0c5240e --- /dev/null +++ b/kotlin-native/platformLibs/src/platform/ios/Accounts.def @@ -0,0 +1,7 @@ +depends = CFNetwork CoreFoundation Foundation Security darwin posix +language = Objective-C +package = platform.Accounts +modules = Accounts + +compilerOpts = -framework Accounts +linkerOpts = -framework Accounts diff --git a/kotlin-native/platformLibs/src/platform/ios/AdSupport.def b/kotlin-native/platformLibs/src/platform/ios/AdSupport.def new file mode 100644 index 00000000000..e12d30d6eba --- /dev/null +++ b/kotlin-native/platformLibs/src/platform/ios/AdSupport.def @@ -0,0 +1,7 @@ +depends = CFNetwork CoreFoundation Foundation Security darwin posix +language = Objective-C +package = platform.AdSupport +modules = AdSupport + +compilerOpts = -framework AdSupport +linkerOpts = -framework AdSupport diff --git a/kotlin-native/platformLibs/src/platform/ios/AddressBook.def b/kotlin-native/platformLibs/src/platform/ios/AddressBook.def new file mode 100644 index 00000000000..404eac6d83e --- /dev/null +++ b/kotlin-native/platformLibs/src/platform/ios/AddressBook.def @@ -0,0 +1,7 @@ +depends = CoreFoundation darwin posix +language = Objective-C +package = platform.AddressBook +modules = AddressBook + +compilerOpts = -framework AddressBook +linkerOpts = -framework AddressBook diff --git a/kotlin-native/platformLibs/src/platform/ios/AddressBookUI.def b/kotlin-native/platformLibs/src/platform/ios/AddressBookUI.def new file mode 100644 index 00000000000..c898cb8035a --- /dev/null +++ b/kotlin-native/platformLibs/src/platform/ios/AddressBookUI.def @@ -0,0 +1,7 @@ +depends = AddressBook CFNetwork CoreFoundation CoreGraphics CoreImage CoreText CoreVideo EAGL FileProvider Foundation IOSurface ImageIO Metal OpenGLESCommon QuartzCore Security UIKit UserNotifications darwin posix +language = Objective-C +package = platform.AddressBookUI +modules = AddressBookUI + +compilerOpts = -framework AddressBookUI +linkerOpts = -framework AddressBookUI diff --git a/kotlin-native/platformLibs/src/platform/ios/AppClip.def b/kotlin-native/platformLibs/src/platform/ios/AppClip.def new file mode 100644 index 00000000000..b47c93cad39 --- /dev/null +++ b/kotlin-native/platformLibs/src/platform/ios/AppClip.def @@ -0,0 +1,6 @@ +depends = CFNetwork CoreFoundation Foundation Security darwin posix +language = Objective-C +package = platform.AppClip +modules = AppClip +compilerOpts = -framework AppClip +linkerOpts = -framework AppClip diff --git a/kotlin-native/platformLibs/src/platform/ios/AppTrackingTransparency.def b/kotlin-native/platformLibs/src/platform/ios/AppTrackingTransparency.def new file mode 100644 index 00000000000..7e368032ce1 --- /dev/null +++ b/kotlin-native/platformLibs/src/platform/ios/AppTrackingTransparency.def @@ -0,0 +1,6 @@ +depends = CFNetwork CoreFoundation Foundation Security darwin posix +language = Objective-C +package = platform.AppTrackingTransparency +modules = AppTrackingTransparency +compilerOpts = -framework AppTrackingTransparency +linkerOpts = -framework AppTrackingTransparency diff --git a/kotlin-native/platformLibs/src/platform/ios/AssetsLibrary.def b/kotlin-native/platformLibs/src/platform/ios/AssetsLibrary.def new file mode 100644 index 00000000000..794db6f1431 --- /dev/null +++ b/kotlin-native/platformLibs/src/platform/ios/AssetsLibrary.def @@ -0,0 +1,7 @@ +depends = CFNetwork CoreFoundation CoreGraphics Foundation Security darwin posix +language = Objective-C +package = platform.AssetsLibrary +modules = AssetsLibrary + +compilerOpts = -framework AssetsLibrary +linkerOpts = -framework AssetsLibrary diff --git a/kotlin-native/platformLibs/src/platform/ios/AudioToolbox.def b/kotlin-native/platformLibs/src/platform/ios/AudioToolbox.def new file mode 100644 index 00000000000..2ff087f8846 --- /dev/null +++ b/kotlin-native/platformLibs/src/platform/ios/AudioToolbox.def @@ -0,0 +1,7 @@ +depends = CFNetwork CoreAudioTypes CoreFoundation CoreMIDI Foundation Security darwin posix +language = Objective-C +package = platform.AudioToolbox +modules = AudioToolbox AudioUnit + +compilerOpts = -framework AudioToolbox +linkerOpts = -framework AudioToolbox diff --git a/kotlin-native/platformLibs/src/platform/ios/AudioUnit.def.disabled b/kotlin-native/platformLibs/src/platform/ios/AudioUnit.def.disabled new file mode 100644 index 00000000000..798b8b62f1c --- /dev/null +++ b/kotlin-native/platformLibs/src/platform/ios/AudioUnit.def.disabled @@ -0,0 +1,6 @@ +language = Objective-C +package = platform.AudioUnit +modules = AudioUnit +compilerOpts = -framework AudioUnit +linkerOpts = -framework AudioUnit +#Disabled: part of AudioToolbox \ No newline at end of file diff --git a/kotlin-native/platformLibs/src/platform/ios/AuthenticationServices.def b/kotlin-native/platformLibs/src/platform/ios/AuthenticationServices.def new file mode 100644 index 00000000000..dbd4e42c0bc --- /dev/null +++ b/kotlin-native/platformLibs/src/platform/ios/AuthenticationServices.def @@ -0,0 +1,7 @@ +depends = CFNetwork CoreFoundation CoreGraphics CoreImage CoreText CoreVideo EAGL FileProvider Foundation IOSurface ImageIO Metal OpenGLESCommon QuartzCore Security UIKit UserNotifications darwin posix +language = Objective-C +package = platform.AuthenticationServices +modules = AuthenticationServices + +compilerOpts = -framework AuthenticationServices +linkerOpts = -framework AuthenticationServices diff --git a/kotlin-native/platformLibs/src/platform/ios/AutomaticAssessmentConfiguration.def b/kotlin-native/platformLibs/src/platform/ios/AutomaticAssessmentConfiguration.def new file mode 100644 index 00000000000..05073c148f3 --- /dev/null +++ b/kotlin-native/platformLibs/src/platform/ios/AutomaticAssessmentConfiguration.def @@ -0,0 +1,7 @@ +depends = CFNetwork CoreFoundation Foundation Security darwin posix +language = Objective-C +package = platform.AutomaticAssessmentConfiguration +modules = AutomaticAssessmentConfiguration + +compilerOpts = -framework AutomaticAssessmentConfiguration +linkerOpts = -framework AutomaticAssessmentConfiguration diff --git a/kotlin-native/platformLibs/src/platform/ios/BackgroundTasks.def b/kotlin-native/platformLibs/src/platform/ios/BackgroundTasks.def new file mode 100644 index 00000000000..969ce3a3948 --- /dev/null +++ b/kotlin-native/platformLibs/src/platform/ios/BackgroundTasks.def @@ -0,0 +1,7 @@ +depends = CFNetwork CoreFoundation Foundation Security darwin posix +language = Objective-C +package = platform.BackgroundTasks +modules = BackgroundTasks + +compilerOpts = -framework BackgroundTasks +linkerOpts = -framework BackgroundTasks diff --git a/kotlin-native/platformLibs/src/platform/ios/BusinessChat.def b/kotlin-native/platformLibs/src/platform/ios/BusinessChat.def new file mode 100644 index 00000000000..8f61a32833d --- /dev/null +++ b/kotlin-native/platformLibs/src/platform/ios/BusinessChat.def @@ -0,0 +1,7 @@ +depends = CFNetwork CoreFoundation CoreGraphics CoreImage CoreText CoreVideo EAGL FileProvider Foundation IOSurface ImageIO Metal OpenGLESCommon QuartzCore Security UIKit UserNotifications darwin posix +language = Objective-C +package = platform.BusinessChat +modules = BusinessChat + +compilerOpts = -framework BusinessChat +linkerOpts = -framework BusinessChat diff --git a/kotlin-native/platformLibs/src/platform/ios/CFNetwork.def b/kotlin-native/platformLibs/src/platform/ios/CFNetwork.def new file mode 100644 index 00000000000..26c50c1200e --- /dev/null +++ b/kotlin-native/platformLibs/src/platform/ios/CFNetwork.def @@ -0,0 +1,11 @@ +depends = CoreFoundation darwin posix +language = Objective-C +package = platform.CFNetwork +modules = CFNetwork + +compilerOpts = -framework CFNetwork +linkerOpts = -framework CFNetwork + +excludedFunctions = kCFHTTPAuthenticationSchemeKerberos \ + kCFNetworkProxiesProxyAutoConfigJavaScript \ + kCFProxyAutoConfigurationHTTPResponseKey diff --git a/kotlin-native/platformLibs/src/platform/ios/CallKit.def b/kotlin-native/platformLibs/src/platform/ios/CallKit.def new file mode 100644 index 00000000000..0aa72eec72e --- /dev/null +++ b/kotlin-native/platformLibs/src/platform/ios/CallKit.def @@ -0,0 +1,7 @@ +depends = CFNetwork CoreFoundation Foundation Security darwin posix +language = Objective-C +package = platform.CallKit +modules = CallKit + +compilerOpts = -framework CallKit +linkerOpts = -framework CallKit diff --git a/kotlin-native/platformLibs/src/platform/ios/CarPlay.def b/kotlin-native/platformLibs/src/platform/ios/CarPlay.def new file mode 100644 index 00000000000..4b00338b555 --- /dev/null +++ b/kotlin-native/platformLibs/src/platform/ios/CarPlay.def @@ -0,0 +1,7 @@ +depends = CFNetwork CoreFoundation CoreGraphics CoreImage CoreLocation CoreText CoreVideo EAGL FileProvider Foundation IOSurface ImageIO MapKit Metal OpenGLESCommon QuartzCore Security UIKit UserNotifications darwin posix +language = Objective-C +package = platform.CarPlay +modules = CarPlay + +compilerOpts = -framework CarPlay +linkerOpts = -framework CarPlay diff --git a/kotlin-native/platformLibs/src/platform/ios/ClassKit.def b/kotlin-native/platformLibs/src/platform/ios/ClassKit.def new file mode 100644 index 00000000000..5353ec57966 --- /dev/null +++ b/kotlin-native/platformLibs/src/platform/ios/ClassKit.def @@ -0,0 +1,7 @@ +depends = CFNetwork CoreFoundation CoreGraphics Foundation Security darwin posix +language = Objective-C +package = platform.ClassKit +modules = ClassKit + +compilerOpts = -framework ClassKit +linkerOpts = -framework ClassKit diff --git a/kotlin-native/platformLibs/src/platform/ios/ClockKit.def b/kotlin-native/platformLibs/src/platform/ios/ClockKit.def new file mode 100644 index 00000000000..64e0b0020c4 --- /dev/null +++ b/kotlin-native/platformLibs/src/platform/ios/ClockKit.def @@ -0,0 +1,6 @@ +depends = CFNetwork CoreFoundation CoreGraphics CoreImage CoreText CoreVideo EAGL FileProvider Foundation IOSurface ImageIO Metal OpenGLESCommon QuartzCore Security UIKit UserNotifications darwin posix +language = Objective-C +package = platform.ClockKit +modules = ClockKit +compilerOpts = -framework ClockKit +linkerOpts = -framework ClockKit diff --git a/kotlin-native/platformLibs/src/platform/ios/CloudKit.def b/kotlin-native/platformLibs/src/platform/ios/CloudKit.def new file mode 100644 index 00000000000..95f7bed6f8f --- /dev/null +++ b/kotlin-native/platformLibs/src/platform/ios/CloudKit.def @@ -0,0 +1,7 @@ +depends = CFNetwork CoreFoundation CoreLocation Foundation Security darwin posix +language = Objective-C +package = platform.CloudKit +modules = CloudKit + +compilerOpts = -framework CloudKit +linkerOpts = -framework CloudKit diff --git a/kotlin-native/platformLibs/src/platform/ios/Combine.def.disabled b/kotlin-native/platformLibs/src/platform/ios/Combine.def.disabled new file mode 100644 index 00000000000..0fde0deb560 --- /dev/null +++ b/kotlin-native/platformLibs/src/platform/ios/Combine.def.disabled @@ -0,0 +1,6 @@ +language = Objective-C +package = platform.Combine +modules = Combine +compilerOpts = -framework Combine +linkerOpts = -framework Combine +#Disabled: Swift-only framework diff --git a/kotlin-native/platformLibs/src/platform/ios/CommonCrypto.def b/kotlin-native/platformLibs/src/platform/ios/CommonCrypto.def new file mode 100644 index 00000000000..92ce70f00ae --- /dev/null +++ b/kotlin-native/platformLibs/src/platform/ios/CommonCrypto.def @@ -0,0 +1,6 @@ +depends = darwin posix +language = Objective-C +package = platform.CoreCrypto +modules = CommonCrypto + +compilerOpts = -D_XOPEN_SOURCE diff --git a/kotlin-native/platformLibs/src/platform/ios/Contacts.def b/kotlin-native/platformLibs/src/platform/ios/Contacts.def new file mode 100644 index 00000000000..640da0adf73 --- /dev/null +++ b/kotlin-native/platformLibs/src/platform/ios/Contacts.def @@ -0,0 +1,7 @@ +depends = CFNetwork CoreFoundation Foundation Security darwin posix +language = Objective-C +package = platform.Contacts +modules = Contacts + +compilerOpts = -framework Contacts +linkerOpts = -framework Contacts diff --git a/kotlin-native/platformLibs/src/platform/ios/ContactsUI.def b/kotlin-native/platformLibs/src/platform/ios/ContactsUI.def new file mode 100644 index 00000000000..7b64b88c8f1 --- /dev/null +++ b/kotlin-native/platformLibs/src/platform/ios/ContactsUI.def @@ -0,0 +1,7 @@ +depends = CFNetwork Contacts CoreFoundation CoreGraphics CoreImage CoreText CoreVideo EAGL FileProvider Foundation IOSurface ImageIO Metal OpenGLESCommon QuartzCore Security UIKit UserNotifications darwin posix +language = Objective-C +package = platform.ContactsUI +modules = ContactsUI + +compilerOpts = -framework ContactsUI +linkerOpts = -framework ContactsUI diff --git a/kotlin-native/platformLibs/src/platform/ios/CoreAudio.def b/kotlin-native/platformLibs/src/platform/ios/CoreAudio.def new file mode 100644 index 00000000000..7f5da857b89 --- /dev/null +++ b/kotlin-native/platformLibs/src/platform/ios/CoreAudio.def @@ -0,0 +1,7 @@ +depends = CoreAudioTypes CoreFoundation darwin posix +language = Objective-C +package = platform.CoreAudio +modules = CoreAudio + +compilerOpts = -framework CoreAudio +linkerOpts = -framework CoreAudio diff --git a/kotlin-native/platformLibs/src/platform/ios/CoreAudioKit.def b/kotlin-native/platformLibs/src/platform/ios/CoreAudioKit.def new file mode 100644 index 00000000000..cd5d31a6cd2 --- /dev/null +++ b/kotlin-native/platformLibs/src/platform/ios/CoreAudioKit.def @@ -0,0 +1,7 @@ +depends = AudioToolbox CFNetwork CoreAudioTypes CoreFoundation CoreGraphics CoreImage CoreText CoreVideo EAGL FileProvider Foundation IOSurface ImageIO Metal OpenGLESCommon QuartzCore Security UIKit UserNotifications darwin posix +language = Objective-C +package = platform.CoreAudioKit +modules = CoreAudioKit + +compilerOpts = -framework CoreAudioKit +linkerOpts = -framework CoreAudioKit diff --git a/kotlin-native/platformLibs/src/platform/ios/CoreAudioTypes.def b/kotlin-native/platformLibs/src/platform/ios/CoreAudioTypes.def new file mode 100644 index 00000000000..2c8891b94d1 --- /dev/null +++ b/kotlin-native/platformLibs/src/platform/ios/CoreAudioTypes.def @@ -0,0 +1,6 @@ +depends = CoreFoundation darwin posix +language = Objective-C +package = platform.CoreAudioTypes +modules = CoreAudioTypes + +compilerOpts = -framework CoreAudioTypes diff --git a/kotlin-native/platformLibs/src/platform/ios/CoreBluetooth.def b/kotlin-native/platformLibs/src/platform/ios/CoreBluetooth.def new file mode 100644 index 00000000000..21fdb92aa38 --- /dev/null +++ b/kotlin-native/platformLibs/src/platform/ios/CoreBluetooth.def @@ -0,0 +1,9 @@ +depends = CFNetwork CoreFoundation Foundation Security darwin posix +language = Objective-C +package = platform.CoreBluetooth +modules = CoreBluetooth + +compilerOpts = -framework CoreBluetooth +linkerOpts = -framework CoreBluetooth + +excludedFunctions = CBConnectPeripheralOptionStartDelayKey diff --git a/kotlin-native/platformLibs/src/platform/ios/CoreData.def b/kotlin-native/platformLibs/src/platform/ios/CoreData.def new file mode 100644 index 00000000000..3f5d7ea0b1d --- /dev/null +++ b/kotlin-native/platformLibs/src/platform/ios/CoreData.def @@ -0,0 +1,7 @@ +depends = CFNetwork CloudKit CoreFoundation CoreLocation Foundation Security darwin posix +language = Objective-C +package = platform.CoreData +modules = CoreData + +compilerOpts = -framework CoreData +linkerOpts = -framework CoreData diff --git a/kotlin-native/platformLibs/src/platform/ios/CoreFoundation.def b/kotlin-native/platformLibs/src/platform/ios/CoreFoundation.def new file mode 100644 index 00000000000..17c65eafa38 --- /dev/null +++ b/kotlin-native/platformLibs/src/platform/ios/CoreFoundation.def @@ -0,0 +1,7 @@ +depends = darwin posix +language = Objective-C +package = platform.CoreFoundation +modules = CoreFoundation + +compilerOpts = -framework CoreFoundation +linkerOpts = -framework CoreFoundation diff --git a/kotlin-native/platformLibs/src/platform/ios/CoreGraphics.def b/kotlin-native/platformLibs/src/platform/ios/CoreGraphics.def new file mode 100644 index 00000000000..3951d09f2bd --- /dev/null +++ b/kotlin-native/platformLibs/src/platform/ios/CoreGraphics.def @@ -0,0 +1,7 @@ +depends = CoreFoundation darwin posix +language = Objective-C +package = platform.CoreGraphics +modules = CoreGraphics + +compilerOpts = -framework CoreGraphics +linkerOpts = -framework CoreGraphics diff --git a/kotlin-native/platformLibs/src/platform/ios/CoreHaptics.def b/kotlin-native/platformLibs/src/platform/ios/CoreHaptics.def new file mode 100644 index 00000000000..a2fd2fa6bf1 --- /dev/null +++ b/kotlin-native/platformLibs/src/platform/ios/CoreHaptics.def @@ -0,0 +1,7 @@ +depends = CoreFoundation Foundation darwin posix +language = Objective-C +package = platform.CoreHaptics +modules = CoreHaptics + +compilerOpts = -framework CoreHaptics +linkerOpts = -framework CoreHaptics diff --git a/kotlin-native/platformLibs/src/platform/ios/CoreImage.def b/kotlin-native/platformLibs/src/platform/ios/CoreImage.def new file mode 100644 index 00000000000..d2780206be8 --- /dev/null +++ b/kotlin-native/platformLibs/src/platform/ios/CoreImage.def @@ -0,0 +1,7 @@ +depends = CFNetwork CoreFoundation CoreGraphics CoreVideo EAGL Foundation IOSurface ImageIO Metal OpenGLESCommon Security darwin posix +language = Objective-C +package = platform.CoreImage +modules = CoreImage + +compilerOpts = -framework CoreImage +linkerOpts = -framework CoreImage diff --git a/kotlin-native/platformLibs/src/platform/ios/CoreLocation.def b/kotlin-native/platformLibs/src/platform/ios/CoreLocation.def new file mode 100644 index 00000000000..34920afd9ee --- /dev/null +++ b/kotlin-native/platformLibs/src/platform/ios/CoreLocation.def @@ -0,0 +1,7 @@ +depends = CFNetwork CoreFoundation Foundation Security darwin posix +language = Objective-C +package = platform.CoreLocation +modules = CoreLocation + +compilerOpts = -framework CoreLocation +linkerOpts = -framework CoreLocation diff --git a/kotlin-native/platformLibs/src/platform/ios/CoreMIDI.def b/kotlin-native/platformLibs/src/platform/ios/CoreMIDI.def new file mode 100644 index 00000000000..908aeec6148 --- /dev/null +++ b/kotlin-native/platformLibs/src/platform/ios/CoreMIDI.def @@ -0,0 +1,7 @@ +depends = CFNetwork CoreFoundation Foundation Security darwin posix +language = Objective-C +package = platform.CoreMIDI +modules = CoreMIDI + +compilerOpts = -framework CoreMIDI +linkerOpts = -framework CoreMIDI diff --git a/kotlin-native/platformLibs/src/platform/ios/CoreML.def b/kotlin-native/platformLibs/src/platform/ios/CoreML.def new file mode 100644 index 00000000000..eb3bdbef75a --- /dev/null +++ b/kotlin-native/platformLibs/src/platform/ios/CoreML.def @@ -0,0 +1,7 @@ +depends = CFNetwork CoreFoundation CoreGraphics CoreVideo Foundation IOSurface ImageIO Security darwin posix +language = Objective-C +package = platform.CoreML +modules = CoreML + +compilerOpts = -framework CoreML +linkerOpts = -framework CoreML diff --git a/kotlin-native/platformLibs/src/platform/ios/CoreMedia.def b/kotlin-native/platformLibs/src/platform/ios/CoreMedia.def new file mode 100644 index 00000000000..e8efa2a915c --- /dev/null +++ b/kotlin-native/platformLibs/src/platform/ios/CoreMedia.def @@ -0,0 +1,7 @@ +depends = CFNetwork CoreAudio CoreAudioTypes CoreFoundation CoreGraphics CoreVideo Foundation IOSurface Metal OpenGLESCommon Security darwin posix +language = Objective-C +package = platform.CoreMedia +modules = CoreMedia + +compilerOpts = -framework CoreMedia +linkerOpts = -framework CoreMedia diff --git a/kotlin-native/platformLibs/src/platform/ios/CoreMotion.def b/kotlin-native/platformLibs/src/platform/ios/CoreMotion.def new file mode 100644 index 00000000000..2c1707ddd61 --- /dev/null +++ b/kotlin-native/platformLibs/src/platform/ios/CoreMotion.def @@ -0,0 +1,7 @@ +depends = CFNetwork CoreFoundation Foundation Security darwin posix +language = Objective-C +package = platform.CoreMotion +modules = CoreMotion + +compilerOpts = -framework CoreMotion +linkerOpts = -framework CoreMotion diff --git a/kotlin-native/platformLibs/src/platform/ios/CoreNFC.def b/kotlin-native/platformLibs/src/platform/ios/CoreNFC.def new file mode 100644 index 00000000000..f3c1b29cf14 --- /dev/null +++ b/kotlin-native/platformLibs/src/platform/ios/CoreNFC.def @@ -0,0 +1,7 @@ +depends = CFNetwork CoreFoundation Foundation Security darwin posix +language = Objective-C +package = platform.CoreNFC +modules = CoreNFC + +compilerOpts = -framework CoreNFC +linkerOpts = -framework CoreNFC diff --git a/kotlin-native/platformLibs/src/platform/ios/CoreServices.def b/kotlin-native/platformLibs/src/platform/ios/CoreServices.def new file mode 100644 index 00000000000..ffd15288ee0 --- /dev/null +++ b/kotlin-native/platformLibs/src/platform/ios/CoreServices.def @@ -0,0 +1,7 @@ +depends = CoreFoundation darwin posix +language = Objective-C +package = platform.CoreServices +modules = CoreServices + +compilerOpts = -framework CoreServices +linkerOpts = -framework CoreServices diff --git a/kotlin-native/platformLibs/src/platform/ios/CoreSpotlight.def b/kotlin-native/platformLibs/src/platform/ios/CoreSpotlight.def new file mode 100644 index 00000000000..a3d7f7d6fa6 --- /dev/null +++ b/kotlin-native/platformLibs/src/platform/ios/CoreSpotlight.def @@ -0,0 +1,7 @@ +depends = CFNetwork CoreFoundation Foundation Security UniformTypeIdentifiers darwin posix +language = Objective-C +package = platform.CoreSpotlight +modules = CoreSpotlight + +compilerOpts = -framework CoreSpotlight +linkerOpts = -framework CoreSpotlight diff --git a/kotlin-native/platformLibs/src/platform/ios/CoreTelephony.def b/kotlin-native/platformLibs/src/platform/ios/CoreTelephony.def new file mode 100644 index 00000000000..746d0a8c96c --- /dev/null +++ b/kotlin-native/platformLibs/src/platform/ios/CoreTelephony.def @@ -0,0 +1,7 @@ +depends = CFNetwork CoreFoundation Foundation Security darwin posix +language = Objective-C +package = platform.CoreTelephony +modules = CoreTelephony + +compilerOpts = -framework CoreTelephony +linkerOpts = -framework CoreTelephony diff --git a/kotlin-native/platformLibs/src/platform/ios/CoreText.def b/kotlin-native/platformLibs/src/platform/ios/CoreText.def new file mode 100644 index 00000000000..3cdfe6f0a47 --- /dev/null +++ b/kotlin-native/platformLibs/src/platform/ios/CoreText.def @@ -0,0 +1,7 @@ +depends = CoreFoundation CoreGraphics darwin posix +language = Objective-C +package = platform.CoreText +modules = CoreText + +compilerOpts = -framework CoreText +linkerOpts = -framework CoreText diff --git a/kotlin-native/platformLibs/src/platform/ios/CoreVideo.def b/kotlin-native/platformLibs/src/platform/ios/CoreVideo.def new file mode 100644 index 00000000000..ce59a982a89 --- /dev/null +++ b/kotlin-native/platformLibs/src/platform/ios/CoreVideo.def @@ -0,0 +1,7 @@ +depends = CFNetwork CoreFoundation CoreGraphics Foundation IOSurface Metal OpenGLESCommon Security darwin posix +language = Objective-C +package = platform.CoreVideo +modules = CoreVideo + +compilerOpts = -framework CoreVideo +linkerOpts = -framework CoreVideo diff --git a/kotlin-native/platformLibs/src/platform/ios/CryptoKit.def.disabled b/kotlin-native/platformLibs/src/platform/ios/CryptoKit.def.disabled new file mode 100644 index 00000000000..1fd5943bf93 --- /dev/null +++ b/kotlin-native/platformLibs/src/platform/ios/CryptoKit.def.disabled @@ -0,0 +1,6 @@ +language = Objective-C +package = platform.CryptoKit +modules = CryptoKit +compilerOpts = -framework CryptoKit +linkerOpts = -framework CryptoKit +#Disabled: Swift-only framework diff --git a/kotlin-native/platformLibs/src/platform/ios/CryptoTokenKit.def b/kotlin-native/platformLibs/src/platform/ios/CryptoTokenKit.def new file mode 100644 index 00000000000..92a710c27ae --- /dev/null +++ b/kotlin-native/platformLibs/src/platform/ios/CryptoTokenKit.def @@ -0,0 +1,7 @@ +depends = CFNetwork CoreFoundation Foundation Security darwin posix +language = Objective-C +package = platform.CryptoTokenKit +modules = CryptoTokenKit + +compilerOpts = -framework CryptoTokenKit +linkerOpts = -framework CryptoTokenKit diff --git a/kotlin-native/platformLibs/src/platform/ios/DeveloperToolsSupport.def.disabled b/kotlin-native/platformLibs/src/platform/ios/DeveloperToolsSupport.def.disabled new file mode 100644 index 00000000000..b3e34c7522b --- /dev/null +++ b/kotlin-native/platformLibs/src/platform/ios/DeveloperToolsSupport.def.disabled @@ -0,0 +1,6 @@ +language = Objective-C +package = platform.DeveloperToolsSupport +modules = DeveloperToolsSupport +compilerOpts = -framework DeveloperToolsSupport +linkerOpts = -framework DeveloperToolsSupport +#Disabled: Swift-only framework diff --git a/kotlin-native/platformLibs/src/platform/ios/DeviceCheck.def b/kotlin-native/platformLibs/src/platform/ios/DeviceCheck.def new file mode 100644 index 00000000000..e056ac13b56 --- /dev/null +++ b/kotlin-native/platformLibs/src/platform/ios/DeviceCheck.def @@ -0,0 +1,7 @@ +depends = CFNetwork CoreFoundation Foundation Security darwin posix +language = Objective-C +package = platform.DeviceCheck +modules = DeviceCheck + +compilerOpts = -framework DeviceCheck +linkerOpts = -framework DeviceCheck diff --git a/kotlin-native/platformLibs/src/platform/ios/EAGL.def b/kotlin-native/platformLibs/src/platform/ios/EAGL.def new file mode 100644 index 00000000000..9937e7c0f0a --- /dev/null +++ b/kotlin-native/platformLibs/src/platform/ios/EAGL.def @@ -0,0 +1,9 @@ +depends = CFNetwork CoreFoundation Foundation Security darwin posix +language = Objective-C +package = platform.EAGL +headers = OpenGLES/EAGL.h OpenGLES/EAGLDrawable.h + +headerFilter = OpenGLES/** + +compilerOpts = -framework OpenGLES +linkerOpts = -framework OpenGLES diff --git a/kotlin-native/platformLibs/src/platform/ios/EventKit.def b/kotlin-native/platformLibs/src/platform/ios/EventKit.def new file mode 100644 index 00000000000..f509d2250d4 --- /dev/null +++ b/kotlin-native/platformLibs/src/platform/ios/EventKit.def @@ -0,0 +1,7 @@ +depends = AddressBook CFNetwork CoreFoundation CoreGraphics CoreLocation Foundation Security darwin posix +language = Objective-C +package = platform.EventKit +modules = EventKit + +compilerOpts = -framework EventKit +linkerOpts = -framework EventKit diff --git a/kotlin-native/platformLibs/src/platform/ios/EventKitUI.def b/kotlin-native/platformLibs/src/platform/ios/EventKitUI.def new file mode 100644 index 00000000000..8222eab0eda --- /dev/null +++ b/kotlin-native/platformLibs/src/platform/ios/EventKitUI.def @@ -0,0 +1,7 @@ +depends = AddressBook CFNetwork CoreFoundation CoreGraphics CoreImage CoreLocation CoreText CoreVideo EAGL EventKit FileProvider Foundation IOSurface ImageIO Metal OpenGLESCommon QuartzCore Security UIKit UserNotifications darwin posix +language = Objective-C +package = platform.EventKitUI +modules = EventKitUI + +compilerOpts = -framework EventKitUI +linkerOpts = -framework EventKitUI diff --git a/kotlin-native/platformLibs/src/platform/ios/ExposureNotification.def b/kotlin-native/platformLibs/src/platform/ios/ExposureNotification.def new file mode 100644 index 00000000000..6e9b7d30a1f --- /dev/null +++ b/kotlin-native/platformLibs/src/platform/ios/ExposureNotification.def @@ -0,0 +1,7 @@ +depends = CFNetwork CoreFoundation Foundation Security darwin posix +language = Objective-C +package = platform.ExposureNotification +modules = ExposureNotification + +compilerOpts = -framework ExposureNotification +linkerOpts = -framework ExposureNotification diff --git a/kotlin-native/platformLibs/src/platform/ios/ExternalAccessory.def b/kotlin-native/platformLibs/src/platform/ios/ExternalAccessory.def new file mode 100644 index 00000000000..bc5c45b70b6 --- /dev/null +++ b/kotlin-native/platformLibs/src/platform/ios/ExternalAccessory.def @@ -0,0 +1,7 @@ +depends = CFNetwork CoreFoundation Foundation Security darwin posix +language = Objective-C +package = platform.ExternalAccessory +modules = ExternalAccessory + +compilerOpts = -framework ExternalAccessory +linkerOpts = -framework ExternalAccessory diff --git a/kotlin-native/platformLibs/src/platform/ios/FileProvider.def b/kotlin-native/platformLibs/src/platform/ios/FileProvider.def new file mode 100644 index 00000000000..1eba4034d87 --- /dev/null +++ b/kotlin-native/platformLibs/src/platform/ios/FileProvider.def @@ -0,0 +1,7 @@ +depends = CFNetwork CoreFoundation CoreGraphics Foundation Security darwin posix +language = Objective-C +package = platform.FileProvider +modules = FileProvider + +compilerOpts = -framework FileProvider +linkerOpts = -framework FileProvider diff --git a/kotlin-native/platformLibs/src/platform/ios/FileProviderUI.def b/kotlin-native/platformLibs/src/platform/ios/FileProviderUI.def new file mode 100644 index 00000000000..5883e750607 --- /dev/null +++ b/kotlin-native/platformLibs/src/platform/ios/FileProviderUI.def @@ -0,0 +1,7 @@ +depends = CFNetwork CoreFoundation CoreGraphics CoreImage CoreText CoreVideo EAGL FileProvider Foundation IOSurface ImageIO Metal OpenGLESCommon QuartzCore Security UIKit UserNotifications darwin posix +language = Objective-C +package = platform.FileProviderUI +modules = FileProviderUI + +compilerOpts = -framework FileProviderUI +linkerOpts = -framework FileProviderUI diff --git a/kotlin-native/platformLibs/src/platform/ios/Foundation.def b/kotlin-native/platformLibs/src/platform/ios/Foundation.def new file mode 100644 index 00000000000..c6b0891cea4 --- /dev/null +++ b/kotlin-native/platformLibs/src/platform/ios/Foundation.def @@ -0,0 +1,7 @@ +depends = CFNetwork CoreFoundation Security darwin posix +language = Objective-C +package = platform.Foundation +modules = Foundation + +compilerOpts = -framework Foundation +linkerOpts = -framework Foundation diff --git a/kotlin-native/platformLibs/src/platform/ios/GLKit.def b/kotlin-native/platformLibs/src/platform/ios/GLKit.def new file mode 100644 index 00000000000..845b9b61170 --- /dev/null +++ b/kotlin-native/platformLibs/src/platform/ios/GLKit.def @@ -0,0 +1,7 @@ +depends = CFNetwork CoreFoundation CoreGraphics CoreImage CoreText CoreVideo EAGL FileProvider Foundation IOSurface ImageIO Metal ModelIO OpenGLES2 OpenGLESCommon QuartzCore Security UIKit UserNotifications darwin posix +language = Objective-C +package = platform.GLKit +modules = GLKit + +compilerOpts = -framework GLKit +linkerOpts = -framework GLKit diff --git a/kotlin-native/platformLibs/src/platform/ios/GSS.def b/kotlin-native/platformLibs/src/platform/ios/GSS.def new file mode 100644 index 00000000000..a8e6204b3a0 --- /dev/null +++ b/kotlin-native/platformLibs/src/platform/ios/GSS.def @@ -0,0 +1,7 @@ +depends = CoreFoundation darwin posix +language = Objective-C +package = platform.GSS +modules = GSS + +compilerOpts = -framework GSS +linkerOpts = -framework GSS diff --git a/kotlin-native/platformLibs/src/platform/ios/GameController.def b/kotlin-native/platformLibs/src/platform/ios/GameController.def new file mode 100644 index 00000000000..cdd6d61dc07 --- /dev/null +++ b/kotlin-native/platformLibs/src/platform/ios/GameController.def @@ -0,0 +1,9 @@ +depends = CFNetwork CoreFoundation CoreGraphics CoreImage CoreText CoreVideo EAGL Foundation IOSurface ImageIO Metal OpenGLESCommon QuartzCore Security UIKit darwin posix +language = Objective-C +package = platform.GameController +modules = GameController + +compilerOpts = -framework GameController +linkerOpts = -framework GameController + +excludedFunctions = GCCurrentExtendedGamepadSnapshotDataVersion GCCurrentMicroGamepadSnapshotDataVersion diff --git a/kotlin-native/platformLibs/src/platform/ios/GameKit.def b/kotlin-native/platformLibs/src/platform/ios/GameKit.def new file mode 100644 index 00000000000..b9958def04b --- /dev/null +++ b/kotlin-native/platformLibs/src/platform/ios/GameKit.def @@ -0,0 +1,7 @@ +depends = AVFoundation AudioToolbox CFNetwork Contacts CoreAudio CoreAudioTypes CoreFoundation CoreGraphics CoreImage CoreMIDI CoreMedia CoreText CoreVideo EAGL FileProvider Foundation GLKit GameController GameplayKit IOSurface ImageIO MediaToolbox Metal MetalKit ModelIO OpenGLESCommon QuartzCore ReplayKit SceneKit Security SpriteKit UIKit UniformTypeIdentifiers UserNotifications darwin posix +language = Objective-C +package = platform.GameKit +modules = GameKit + +compilerOpts = -framework GameKit +linkerOpts = -framework GameKit diff --git a/kotlin-native/platformLibs/src/platform/ios/GameplayKit.def b/kotlin-native/platformLibs/src/platform/ios/GameplayKit.def new file mode 100644 index 00000000000..63dab350987 --- /dev/null +++ b/kotlin-native/platformLibs/src/platform/ios/GameplayKit.def @@ -0,0 +1,7 @@ +depends = CFNetwork CoreFoundation CoreGraphics CoreImage CoreText CoreVideo EAGL FileProvider Foundation GLKit IOSurface ImageIO Metal OpenGLESCommon QuartzCore SceneKit Security SpriteKit UIKit UserNotifications darwin posix +language = Objective-C +package = platform.GameplayKit +modules = GameplayKit + +compilerOpts = -framework GameplayKit +linkerOpts = -framework GameplayKit diff --git a/kotlin-native/platformLibs/src/platform/ios/HealthKit.def b/kotlin-native/platformLibs/src/platform/ios/HealthKit.def new file mode 100644 index 00000000000..2543e8276c6 --- /dev/null +++ b/kotlin-native/platformLibs/src/platform/ios/HealthKit.def @@ -0,0 +1,7 @@ +depends = CFNetwork CoreFoundation Foundation Security darwin posix +language = Objective-C +package = platform.HealthKit +modules = HealthKit + +compilerOpts = -framework HealthKit +linkerOpts = -framework HealthKit diff --git a/kotlin-native/platformLibs/src/platform/ios/HealthKitUI.def b/kotlin-native/platformLibs/src/platform/ios/HealthKitUI.def new file mode 100644 index 00000000000..5f75b109d94 --- /dev/null +++ b/kotlin-native/platformLibs/src/platform/ios/HealthKitUI.def @@ -0,0 +1,7 @@ +depends = CFNetwork CoreFoundation CoreGraphics CoreImage CoreText CoreVideo EAGL FileProvider Foundation HealthKit IOSurface ImageIO Metal OpenGLESCommon QuartzCore Security UIKit UserNotifications darwin posix +language = Objective-C +package = platform.HealthKitUI +modules = HealthKitUI + +compilerOpts = -framework HealthKitUI +linkerOpts = -framework HealthKitUI diff --git a/kotlin-native/platformLibs/src/platform/ios/HomeKit.def b/kotlin-native/platformLibs/src/platform/ios/HomeKit.def new file mode 100644 index 00000000000..0610aefca96 --- /dev/null +++ b/kotlin-native/platformLibs/src/platform/ios/HomeKit.def @@ -0,0 +1,7 @@ +depends = CFNetwork CoreFoundation CoreGraphics CoreImage CoreText CoreVideo EAGL FileProvider Foundation IOSurface ImageIO Metal OpenGLESCommon QuartzCore Security UIKit UserNotifications darwin posix +language = Objective-C +package = platform.HomeKit +modules = HomeKit + +compilerOpts = -framework HomeKit +linkerOpts = -framework HomeKit diff --git a/kotlin-native/platformLibs/src/platform/ios/IOKit.def.disabled b/kotlin-native/platformLibs/src/platform/ios/IOKit.def.disabled new file mode 100644 index 00000000000..d88f4d5cde2 --- /dev/null +++ b/kotlin-native/platformLibs/src/platform/ios/IOKit.def.disabled @@ -0,0 +1,6 @@ +language = Objective-C +package = platform.IOKit +modules = IOKit +compilerOpts = -framework IOKit +linkerOpts = -framework IOKit +#Disabled: Not officially available for ios diff --git a/kotlin-native/platformLibs/src/platform/ios/IOSurface.def b/kotlin-native/platformLibs/src/platform/ios/IOSurface.def new file mode 100644 index 00000000000..a56b69da8fc --- /dev/null +++ b/kotlin-native/platformLibs/src/platform/ios/IOSurface.def @@ -0,0 +1,7 @@ +depends = CFNetwork CoreFoundation Foundation Security darwin posix +language = Objective-C +package = platform.IOSurface +modules = IOSurface + +compilerOpts = -framework IOSurface +linkerOpts = -framework IOSurface diff --git a/kotlin-native/platformLibs/src/platform/ios/IdentityLookup.def b/kotlin-native/platformLibs/src/platform/ios/IdentityLookup.def new file mode 100644 index 00000000000..6df30beeff2 --- /dev/null +++ b/kotlin-native/platformLibs/src/platform/ios/IdentityLookup.def @@ -0,0 +1,7 @@ +depends = CFNetwork CoreFoundation Foundation Security darwin posix +language = Objective-C +package = platform.IdentityLookup +modules = IdentityLookup + +compilerOpts = -framework IdentityLookup +linkerOpts = -framework IdentityLookup diff --git a/kotlin-native/platformLibs/src/platform/ios/IdentityLookupUI.def b/kotlin-native/platformLibs/src/platform/ios/IdentityLookupUI.def new file mode 100644 index 00000000000..dd12a74a756 --- /dev/null +++ b/kotlin-native/platformLibs/src/platform/ios/IdentityLookupUI.def @@ -0,0 +1,7 @@ +depends = CFNetwork CoreFoundation CoreGraphics CoreImage CoreText CoreVideo EAGL FileProvider Foundation IOSurface IdentityLookup ImageIO Metal OpenGLESCommon QuartzCore Security UIKit UserNotifications darwin posix +language = Objective-C +package = platform.IdentityLookupUI +modules = IdentityLookupUI + +compilerOpts = -framework IdentityLookupUI +linkerOpts = -framework IdentityLookupUI diff --git a/kotlin-native/platformLibs/src/platform/ios/ImageCaptureCore.def b/kotlin-native/platformLibs/src/platform/ios/ImageCaptureCore.def new file mode 100644 index 00000000000..060562b41d2 --- /dev/null +++ b/kotlin-native/platformLibs/src/platform/ios/ImageCaptureCore.def @@ -0,0 +1,7 @@ +depends = CFNetwork CoreFoundation CoreGraphics Foundation Security darwin posix +language = Objective-C +package = platform.ImageCaptureCore +modules = ImageCaptureCore + +compilerOpts = -framework ImageCaptureCore +linkerOpts = -framework ImageCaptureCore diff --git a/kotlin-native/platformLibs/src/platform/ios/ImageIO.def b/kotlin-native/platformLibs/src/platform/ios/ImageIO.def new file mode 100644 index 00000000000..635137a80c9 --- /dev/null +++ b/kotlin-native/platformLibs/src/platform/ios/ImageIO.def @@ -0,0 +1,7 @@ +depends = CoreFoundation CoreGraphics darwin posix +language = Objective-C +package = platform.ImageIO +modules = ImageIO + +compilerOpts = -framework ImageIO +linkerOpts = -framework ImageIO diff --git a/kotlin-native/platformLibs/src/platform/ios/Intents.def b/kotlin-native/platformLibs/src/platform/ios/Intents.def new file mode 100644 index 00000000000..1c60e2d0d2b --- /dev/null +++ b/kotlin-native/platformLibs/src/platform/ios/Intents.def @@ -0,0 +1,7 @@ +depends = CFNetwork CoreFoundation CoreGraphics CoreLocation Foundation Security darwin posix +language = Objective-C +package = platform.Intents +modules = Intents + +compilerOpts = -framework Intents +linkerOpts = -framework Intents diff --git a/kotlin-native/platformLibs/src/platform/ios/IntentsUI.def b/kotlin-native/platformLibs/src/platform/ios/IntentsUI.def new file mode 100644 index 00000000000..7686e411332 --- /dev/null +++ b/kotlin-native/platformLibs/src/platform/ios/IntentsUI.def @@ -0,0 +1,7 @@ +depends = CFNetwork CoreFoundation CoreGraphics CoreImage CoreText CoreVideo EAGL FileProvider Foundation IOSurface ImageIO Intents Metal OpenGLESCommon QuartzCore Security UIKit UserNotifications darwin posix +language = Objective-C +package = platform.IntentsUI +modules = IntentsUI + +compilerOpts = -framework IntentsUI +linkerOpts = -framework IntentsUI diff --git a/kotlin-native/platformLibs/src/platform/ios/JavaScriptCore.def b/kotlin-native/platformLibs/src/platform/ios/JavaScriptCore.def new file mode 100644 index 00000000000..f887ee42f4d --- /dev/null +++ b/kotlin-native/platformLibs/src/platform/ios/JavaScriptCore.def @@ -0,0 +1,7 @@ +depends = CFNetwork CoreFoundation CoreGraphics Foundation Security darwin posix +language = Objective-C +package = platform.JavaScriptCore +modules = JavaScriptCore + +compilerOpts = -framework JavaScriptCore +linkerOpts = -framework JavaScriptCore diff --git a/kotlin-native/platformLibs/src/platform/ios/LinkPresentation.def b/kotlin-native/platformLibs/src/platform/ios/LinkPresentation.def new file mode 100644 index 00000000000..c850dc7e6f9 --- /dev/null +++ b/kotlin-native/platformLibs/src/platform/ios/LinkPresentation.def @@ -0,0 +1,7 @@ +depends = CFNetwork CoreFoundation CoreGraphics CoreImage CoreText CoreVideo EAGL FileProvider Foundation IOSurface ImageIO Metal OpenGLESCommon QuartzCore Security UIKit UserNotifications darwin posix +language = Objective-C +package = platform.LinkPresentation +modules = LinkPresentation + +compilerOpts = -framework LinkPresentation +linkerOpts = -framework LinkPresentation diff --git a/kotlin-native/platformLibs/src/platform/ios/LocalAuthentication.def b/kotlin-native/platformLibs/src/platform/ios/LocalAuthentication.def new file mode 100644 index 00000000000..d5ecbbe501b --- /dev/null +++ b/kotlin-native/platformLibs/src/platform/ios/LocalAuthentication.def @@ -0,0 +1,7 @@ +depends = CFNetwork CoreFoundation Foundation Security darwin posix +language = Objective-C +package = platform.LocalAuthentication +modules = LocalAuthentication + +compilerOpts = -framework LocalAuthentication +linkerOpts = -framework LocalAuthentication diff --git a/kotlin-native/platformLibs/src/platform/ios/MLCompute.def b/kotlin-native/platformLibs/src/platform/ios/MLCompute.def new file mode 100644 index 00000000000..d619a15bf29 --- /dev/null +++ b/kotlin-native/platformLibs/src/platform/ios/MLCompute.def @@ -0,0 +1,11 @@ +depends = CFNetwork CoreFoundation Foundation IOSurface Metal Security darwin posix +language = Objective-C +package = platform.MLCompute + +modules.ios_arm32 = MLCompute +compilerOpts.ios_arm32 = -framework MLCompute +linkerOpts.ios_arm32 = -framework MLCompute + +modules.ios_arm64 = MLCompute +compilerOpts.ios_arm64 = -framework MLCompute +linkerOpts.ios_arm64 = -framework MLCompute diff --git a/kotlin-native/platformLibs/src/platform/ios/MapKit.def b/kotlin-native/platformLibs/src/platform/ios/MapKit.def new file mode 100644 index 00000000000..f6d29dccd90 --- /dev/null +++ b/kotlin-native/platformLibs/src/platform/ios/MapKit.def @@ -0,0 +1,7 @@ +depends = CFNetwork CoreFoundation CoreGraphics CoreImage CoreLocation CoreText CoreVideo EAGL FileProvider Foundation IOSurface ImageIO Metal OpenGLESCommon QuartzCore Security UIKit UserNotifications darwin posix +language = Objective-C +package = platform.MapKit +modules = MapKit + +compilerOpts = -framework MapKit +linkerOpts = -framework MapKit diff --git a/kotlin-native/platformLibs/src/platform/ios/MediaAccessibility.def b/kotlin-native/platformLibs/src/platform/ios/MediaAccessibility.def new file mode 100644 index 00000000000..dbbe59f9038 --- /dev/null +++ b/kotlin-native/platformLibs/src/platform/ios/MediaAccessibility.def @@ -0,0 +1,7 @@ +depends = CFNetwork CoreFoundation CoreGraphics CoreText EAGL Foundation Metal QuartzCore Security darwin posix +language = Objective-C +package = platform.MediaAccessibility +modules = MediaAccessibility + +compilerOpts = -framework MediaAccessibility +linkerOpts = -framework MediaAccessibility diff --git a/kotlin-native/platformLibs/src/platform/ios/MediaPlayer.def b/kotlin-native/platformLibs/src/platform/ios/MediaPlayer.def new file mode 100644 index 00000000000..9ab112c4e7f --- /dev/null +++ b/kotlin-native/platformLibs/src/platform/ios/MediaPlayer.def @@ -0,0 +1,9 @@ +depends = AVFoundation CFNetwork CoreFoundation CoreGraphics CoreImage CoreMedia CoreText CoreVideo EAGL FileProvider Foundation IOSurface ImageIO Metal OpenGLESCommon QuartzCore Security UIKit UserNotifications darwin posix +language = Objective-C +package = platform.MediaPlayer +headers = MediaPlayer/MediaPlayer.h + +headerFilter = MediaPlayer/** + +compilerOpts = -framework MediaPlayer +linkerOpts = -framework MediaPlayer diff --git a/kotlin-native/platformLibs/src/platform/ios/MediaSetup.def b/kotlin-native/platformLibs/src/platform/ios/MediaSetup.def new file mode 100644 index 00000000000..d44c91363ce --- /dev/null +++ b/kotlin-native/platformLibs/src/platform/ios/MediaSetup.def @@ -0,0 +1,11 @@ +depends = CFNetwork CoreFoundation CoreGraphics CoreImage CoreText CoreVideo EAGL FileProvider Foundation IOSurface ImageIO Metal OpenGLESCommon QuartzCore Security UIKit UserNotifications darwin posix +language = Objective-C +package = platform.MediaSetup + +modules.ios_arm32 = MediaSetup +compilerOpts.ios_arm32 = -framework MediaSetup +linkerOpts.ios_arm32 = -framework MediaSetup + +modules.ios_arm64 = MediaSetup +compilerOpts.ios_arm64 = -framework MediaSetup +linkerOpts.ios_arm64 = -framework MediaSetup diff --git a/kotlin-native/platformLibs/src/platform/ios/MediaToolbox.def b/kotlin-native/platformLibs/src/platform/ios/MediaToolbox.def new file mode 100644 index 00000000000..f030c0080ed --- /dev/null +++ b/kotlin-native/platformLibs/src/platform/ios/MediaToolbox.def @@ -0,0 +1,7 @@ +depends = AudioToolbox CFNetwork CoreAudio CoreAudioTypes CoreFoundation CoreGraphics CoreMIDI CoreMedia CoreVideo Foundation IOSurface Metal OpenGLESCommon Security darwin posix +language = Objective-C +package = platform.MediaToolbox +modules = MediaToolbox + +compilerOpts = -framework MediaToolbox +linkerOpts = -framework MediaToolbox diff --git a/kotlin-native/platformLibs/src/platform/ios/MessageUI.def b/kotlin-native/platformLibs/src/platform/ios/MessageUI.def new file mode 100644 index 00000000000..2fd0daadd7f --- /dev/null +++ b/kotlin-native/platformLibs/src/platform/ios/MessageUI.def @@ -0,0 +1,7 @@ +depends = CFNetwork CoreFoundation CoreGraphics CoreImage CoreText CoreVideo EAGL FileProvider Foundation IOSurface ImageIO Metal OpenGLESCommon QuartzCore Security UIKit UserNotifications darwin posix +language = Objective-C +package = platform.MessageUI +modules = MessageUI + +compilerOpts = -framework MessageUI +linkerOpts = -framework MessageUI diff --git a/kotlin-native/platformLibs/src/platform/ios/Messages.def b/kotlin-native/platformLibs/src/platform/ios/Messages.def new file mode 100644 index 00000000000..1abc1fc2e73 --- /dev/null +++ b/kotlin-native/platformLibs/src/platform/ios/Messages.def @@ -0,0 +1,7 @@ +depends = CFNetwork CoreFoundation CoreGraphics CoreImage CoreText CoreVideo EAGL FileProvider Foundation IOSurface ImageIO Metal OpenGLESCommon QuartzCore Security UIKit UserNotifications darwin posix +language = Objective-C +package = platform.Messages +modules = Messages + +compilerOpts = -framework Messages +linkerOpts = -framework Messages diff --git a/kotlin-native/platformLibs/src/platform/ios/Metal.def b/kotlin-native/platformLibs/src/platform/ios/Metal.def new file mode 100644 index 00000000000..7eecda98b1f --- /dev/null +++ b/kotlin-native/platformLibs/src/platform/ios/Metal.def @@ -0,0 +1,9 @@ +depends = CFNetwork CoreFoundation Foundation IOSurface Security darwin posix +language = Objective-C +package = platform.Metal +modules = Metal + +compilerOpts = -framework Metal +linkerOpts = -framework Metal + +excludedFunctions = MTLCommandBufferErrorDomain diff --git a/kotlin-native/platformLibs/src/platform/ios/MetalKit.def b/kotlin-native/platformLibs/src/platform/ios/MetalKit.def new file mode 100644 index 00000000000..6044313196d --- /dev/null +++ b/kotlin-native/platformLibs/src/platform/ios/MetalKit.def @@ -0,0 +1,7 @@ +depends = CFNetwork CoreFoundation CoreGraphics CoreImage CoreText CoreVideo EAGL FileProvider Foundation IOSurface ImageIO Metal ModelIO OpenGLESCommon QuartzCore Security UIKit UserNotifications darwin posix +language = Objective-C +package = platform.MetalKit +modules = MetalKit + +compilerOpts = -framework MetalKit +linkerOpts = -framework MetalKit diff --git a/kotlin-native/platformLibs/src/platform/ios/MetalPerformanceShaders.def b/kotlin-native/platformLibs/src/platform/ios/MetalPerformanceShaders.def new file mode 100644 index 00000000000..12872090e42 --- /dev/null +++ b/kotlin-native/platformLibs/src/platform/ios/MetalPerformanceShaders.def @@ -0,0 +1,7 @@ +depends = CFNetwork CoreFoundation CoreGraphics Foundation IOSurface Metal Security darwin posix +language = Objective-C +package = platform.MetalPerformanceShaders +modules = MetalPerformanceShaders + +compilerOpts = -framework MetalPerformanceShaders +linkerOpts = -framework MetalPerformanceShaders diff --git a/kotlin-native/platformLibs/src/platform/ios/MetalPerformanceShadersGraph.def b/kotlin-native/platformLibs/src/platform/ios/MetalPerformanceShadersGraph.def new file mode 100644 index 00000000000..93a7fdd7bb8 --- /dev/null +++ b/kotlin-native/platformLibs/src/platform/ios/MetalPerformanceShadersGraph.def @@ -0,0 +1,6 @@ +depends = CFNetwork CoreFoundation CoreGraphics Foundation IOSurface Metal MetalPerformanceShaders Security darwin posix +language = Objective-C +package = platform.MetalPerformanceShadersGraph +modules = MetalPerformanceShadersGraph +compilerOpts = -framework MetalPerformanceShadersGraph +linkerOpts = -framework MetalPerformanceShadersGraph diff --git a/kotlin-native/platformLibs/src/platform/ios/MetricKit.def b/kotlin-native/platformLibs/src/platform/ios/MetricKit.def new file mode 100644 index 00000000000..32149d94d32 --- /dev/null +++ b/kotlin-native/platformLibs/src/platform/ios/MetricKit.def @@ -0,0 +1,7 @@ +depends = CFNetwork CoreFoundation Foundation Security darwin posix +language = Objective-C +package = platform.MetricKit +modules = MetricKit + +compilerOpts = -framework MetricKit +linkerOpts = -framework MetricKit diff --git a/kotlin-native/platformLibs/src/platform/ios/MobileCoreServices.def b/kotlin-native/platformLibs/src/platform/ios/MobileCoreServices.def new file mode 100644 index 00000000000..bdd5356cc09 --- /dev/null +++ b/kotlin-native/platformLibs/src/platform/ios/MobileCoreServices.def @@ -0,0 +1,7 @@ +depends = CoreFoundation CoreServices darwin posix +language = Objective-C +package = platform.MobileCoreServices +modules = MobileCoreServices + +compilerOpts = -framework MobileCoreServices +linkerOpts = -framework MobileCoreServices diff --git a/kotlin-native/platformLibs/src/platform/ios/ModelIO.def b/kotlin-native/platformLibs/src/platform/ios/ModelIO.def new file mode 100644 index 00000000000..3704a6b73ea --- /dev/null +++ b/kotlin-native/platformLibs/src/platform/ios/ModelIO.def @@ -0,0 +1,7 @@ +depends = CFNetwork CoreFoundation CoreGraphics Foundation Security darwin posix +language = Objective-C +package = platform.ModelIO +modules = ModelIO + +compilerOpts = -framework ModelIO +linkerOpts = -framework ModelIO diff --git a/kotlin-native/platformLibs/src/platform/ios/MultipeerConnectivity.def b/kotlin-native/platformLibs/src/platform/ios/MultipeerConnectivity.def new file mode 100644 index 00000000000..a8ec7cc4ed6 --- /dev/null +++ b/kotlin-native/platformLibs/src/platform/ios/MultipeerConnectivity.def @@ -0,0 +1,7 @@ +depends = CFNetwork CoreFoundation CoreGraphics CoreImage CoreText CoreVideo EAGL FileProvider Foundation IOSurface ImageIO Metal OpenGLESCommon QuartzCore Security UIKit UserNotifications darwin posix +language = Objective-C +package = platform.MultipeerConnectivity +modules = MultipeerConnectivity + +compilerOpts = -framework MultipeerConnectivity +linkerOpts = -framework MultipeerConnectivity diff --git a/kotlin-native/platformLibs/src/platform/ios/NaturalLanguage.def b/kotlin-native/platformLibs/src/platform/ios/NaturalLanguage.def new file mode 100644 index 00000000000..50b22ee36ba --- /dev/null +++ b/kotlin-native/platformLibs/src/platform/ios/NaturalLanguage.def @@ -0,0 +1,7 @@ +depends = CFNetwork CoreFoundation Foundation Security darwin posix +language = Objective-C +package = platform.NaturalLanguage +modules = NaturalLanguage + +compilerOpts = -framework NaturalLanguage +linkerOpts = -framework NaturalLanguage diff --git a/kotlin-native/platformLibs/src/platform/ios/NearbyInteraction.def b/kotlin-native/platformLibs/src/platform/ios/NearbyInteraction.def new file mode 100644 index 00000000000..247955bc39e --- /dev/null +++ b/kotlin-native/platformLibs/src/platform/ios/NearbyInteraction.def @@ -0,0 +1,6 @@ +depends = CFNetwork CoreFoundation Foundation Security darwin posix +language = Objective-C +package = platform.NearbyInteraction +modules = NearbyInteraction +compilerOpts = -framework NearbyInteraction +linkerOpts = -framework NearbyInteraction diff --git a/kotlin-native/platformLibs/src/platform/ios/Network.def b/kotlin-native/platformLibs/src/platform/ios/Network.def new file mode 100644 index 00000000000..d47c63bd0d1 --- /dev/null +++ b/kotlin-native/platformLibs/src/platform/ios/Network.def @@ -0,0 +1,10 @@ +depends = CoreFoundation Security darwin posix +language = Objective-C +package = platform.Network +modules = Network + +compilerOpts = -framework Network +linkerOpts = -framework Network + +excludedFunctions = _nw_data_transfer_report_all_paths +excludedMacros = NW_ALL_PATHS diff --git a/kotlin-native/platformLibs/src/platform/ios/NetworkExtension.def b/kotlin-native/platformLibs/src/platform/ios/NetworkExtension.def new file mode 100644 index 00000000000..96d9a9cd3c4 --- /dev/null +++ b/kotlin-native/platformLibs/src/platform/ios/NetworkExtension.def @@ -0,0 +1,7 @@ +depends = CFNetwork CoreFoundation Foundation Network Security darwin posix +language = Objective-C +package = platform.NetworkExtension +modules = NetworkExtension + +compilerOpts = -framework NetworkExtension +linkerOpts = -framework NetworkExtension diff --git a/kotlin-native/platformLibs/src/platform/ios/NewsstandKit.def b/kotlin-native/platformLibs/src/platform/ios/NewsstandKit.def new file mode 100644 index 00000000000..c2f84bf5ffe --- /dev/null +++ b/kotlin-native/platformLibs/src/platform/ios/NewsstandKit.def @@ -0,0 +1,7 @@ +depends = CFNetwork CoreFoundation Foundation Security darwin posix +language = Objective-C +package = platform.NewsstandKit +modules = NewsstandKit + +compilerOpts = -framework NewsstandKit +linkerOpts = -framework NewsstandKit diff --git a/kotlin-native/platformLibs/src/platform/ios/NotificationCenter.def b/kotlin-native/platformLibs/src/platform/ios/NotificationCenter.def new file mode 100644 index 00000000000..51ea8a81126 --- /dev/null +++ b/kotlin-native/platformLibs/src/platform/ios/NotificationCenter.def @@ -0,0 +1,7 @@ +depends = CFNetwork CoreFoundation CoreGraphics CoreImage CoreText CoreVideo EAGL FileProvider Foundation IOSurface ImageIO Metal OpenGLESCommon QuartzCore Security UIKit UserNotifications darwin posix +language = Objective-C +package = platform.NotificationCenter +modules = NotificationCenter + +compilerOpts = -framework NotificationCenter +linkerOpts = -framework NotificationCenter diff --git a/kotlin-native/platformLibs/src/platform/ios/OSLog.def.disabled b/kotlin-native/platformLibs/src/platform/ios/OSLog.def.disabled new file mode 100644 index 00000000000..23981af9579 --- /dev/null +++ b/kotlin-native/platformLibs/src/platform/ios/OSLog.def.disabled @@ -0,0 +1,6 @@ +language = Objective-C +package = platform.OSLog +modules = OSLog +compilerOpts = -framework OSLog +linkerOpts = -framework OSLog +#Disabled: Not officially available for ios diff --git a/kotlin-native/platformLibs/src/platform/ios/OpenAL.def b/kotlin-native/platformLibs/src/platform/ios/OpenAL.def new file mode 100644 index 00000000000..9c030c99d33 --- /dev/null +++ b/kotlin-native/platformLibs/src/platform/ios/OpenAL.def @@ -0,0 +1,7 @@ +depends = darwin posix +language = Objective-C +package = platform.OpenAL +modules = OpenAL + +compilerOpts = -framework OpenAL +linkerOpts = -framework OpenAL diff --git a/kotlin-native/platformLibs/src/platform/ios/OpenGLES.def b/kotlin-native/platformLibs/src/platform/ios/OpenGLES.def new file mode 100644 index 00000000000..5eb2b3ddb2f --- /dev/null +++ b/kotlin-native/platformLibs/src/platform/ios/OpenGLES.def @@ -0,0 +1,9 @@ +depends = EAGL OpenGLESCommon darwin posix +language = Objective-C +package = platform.gles +headers = OpenGLES/ES1/gl.h OpenGLES/ES1/glext.h + +headerFilter = OpenGLES/ES1/** + +compilerOpts = -framework OpenGLES +linkerOpts = -framework OpenGLES diff --git a/kotlin-native/platformLibs/src/platform/ios/OpenGLES2.def b/kotlin-native/platformLibs/src/platform/ios/OpenGLES2.def new file mode 100644 index 00000000000..6d030e35c48 --- /dev/null +++ b/kotlin-native/platformLibs/src/platform/ios/OpenGLES2.def @@ -0,0 +1,9 @@ +depends = EAGL OpenGLESCommon darwin posix +language = Objective-C +package = platform.gles2 +headers = OpenGLES/ES2/gl.h OpenGLES/ES2/glext.h + +headerFilter = OpenGLES/ES2/** + +compilerOpts = -framework OpenGLES +linkerOpts = -framework OpenGLES diff --git a/kotlin-native/platformLibs/src/platform/ios/OpenGLES3.def b/kotlin-native/platformLibs/src/platform/ios/OpenGLES3.def new file mode 100644 index 00000000000..08e9586476c --- /dev/null +++ b/kotlin-native/platformLibs/src/platform/ios/OpenGLES3.def @@ -0,0 +1,9 @@ +depends = EAGL OpenGLESCommon darwin posix +language = Objective-C +package = platform.gles3 +headers = OpenGLES/ES3/gl.h OpenGLES/ES3/glext.h + +headerFilter = OpenGLES/ES3/** + +compilerOpts = -framework OpenGLES +linkerOpts = -framework OpenGLES diff --git a/kotlin-native/platformLibs/src/platform/ios/OpenGLESCommon.def b/kotlin-native/platformLibs/src/platform/ios/OpenGLESCommon.def new file mode 100644 index 00000000000..2c19d621104 --- /dev/null +++ b/kotlin-native/platformLibs/src/platform/ios/OpenGLESCommon.def @@ -0,0 +1,9 @@ +depends = posix +language = Objective-C +package = platform.glescommon +headers = OpenGLES/gltypes.h + +headerFilter = OpenGLES/gltypes.h + +compilerOpts = -framework OpenGLES +linkerOpts = -framework OpenGLES diff --git a/kotlin-native/platformLibs/src/platform/ios/PDFKit.def b/kotlin-native/platformLibs/src/platform/ios/PDFKit.def new file mode 100644 index 00000000000..ca9378ae4be --- /dev/null +++ b/kotlin-native/platformLibs/src/platform/ios/PDFKit.def @@ -0,0 +1,7 @@ +depends = CFNetwork CoreFoundation CoreGraphics CoreImage CoreText CoreVideo EAGL FileProvider Foundation IOSurface ImageIO Metal OpenGLESCommon QuartzCore Security UIKit UserNotifications darwin posix +language = Objective-C +package = platform.PDFKit +modules = PDFKit + +compilerOpts = -framework PDFKit +linkerOpts = -framework PDFKit diff --git a/kotlin-native/platformLibs/src/platform/ios/PassKit.def b/kotlin-native/platformLibs/src/platform/ios/PassKit.def new file mode 100644 index 00000000000..8235cd2bbc8 --- /dev/null +++ b/kotlin-native/platformLibs/src/platform/ios/PassKit.def @@ -0,0 +1,7 @@ +depends = AddressBook CFNetwork Contacts CoreFoundation CoreGraphics CoreImage CoreText CoreVideo EAGL FileProvider Foundation IOSurface ImageIO Metal OpenGLESCommon QuartzCore Security UIKit UserNotifications darwin posix +language = Objective-C +package = platform.PassKit +modules = PassKit + +compilerOpts = -framework PassKit +linkerOpts = -framework PassKit diff --git a/kotlin-native/platformLibs/src/platform/ios/PencilKit.def b/kotlin-native/platformLibs/src/platform/ios/PencilKit.def new file mode 100644 index 00000000000..88524db4abc --- /dev/null +++ b/kotlin-native/platformLibs/src/platform/ios/PencilKit.def @@ -0,0 +1,7 @@ +depends = CFNetwork CoreFoundation CoreGraphics CoreImage CoreText CoreVideo EAGL FileProvider Foundation IOSurface ImageIO Metal OpenGLESCommon QuartzCore Security UIKit UserNotifications darwin posix +language = Objective-C +package = platform.PencilKit +modules = PencilKit + +compilerOpts = -framework PencilKit +linkerOpts = -framework PencilKit diff --git a/kotlin-native/platformLibs/src/platform/ios/Photos.def b/kotlin-native/platformLibs/src/platform/ios/Photos.def new file mode 100644 index 00000000000..d2ace735439 --- /dev/null +++ b/kotlin-native/platformLibs/src/platform/ios/Photos.def @@ -0,0 +1,10 @@ +depends = AVFoundation AudioToolbox CFNetwork CoreAudio CoreAudioTypes CoreFoundation CoreGraphics CoreImage CoreLocation CoreMIDI CoreMedia CoreText CoreVideo EAGL FileProvider Foundation IOSurface ImageIO MediaToolbox Metal OpenGLESCommon QuartzCore Security UIKit UniformTypeIdentifiers UserNotifications darwin posix +language = Objective-C +package = platform.Photos +modules = Photos + +compilerOpts = -framework Photos +linkerOpts = -framework Photos +--- +// TODO: ugly hack while forwarded enums are supported. +#import diff --git a/kotlin-native/platformLibs/src/platform/ios/PhotosUI.def b/kotlin-native/platformLibs/src/platform/ios/PhotosUI.def new file mode 100644 index 00000000000..b3bfb0759b5 --- /dev/null +++ b/kotlin-native/platformLibs/src/platform/ios/PhotosUI.def @@ -0,0 +1,7 @@ +depends = AVFoundation AudioToolbox CFNetwork CoreAudio CoreAudioTypes CoreFoundation CoreGraphics CoreImage CoreLocation CoreMIDI CoreMedia CoreText CoreVideo EAGL FileProvider Foundation IOSurface ImageIO MediaToolbox Metal OpenGLESCommon Photos QuartzCore Security UIKit UniformTypeIdentifiers UserNotifications darwin posix +language = Objective-C +package = platform.PhotosUI +modules = PhotosUI + +compilerOpts = -framework PhotosUI +linkerOpts = -framework PhotosUI diff --git a/kotlin-native/platformLibs/src/platform/ios/PushKit.def b/kotlin-native/platformLibs/src/platform/ios/PushKit.def new file mode 100644 index 00000000000..4f0aaec4171 --- /dev/null +++ b/kotlin-native/platformLibs/src/platform/ios/PushKit.def @@ -0,0 +1,7 @@ +depends = CFNetwork CoreFoundation Foundation Security darwin posix +language = Objective-C +package = platform.PushKit +modules = PushKit + +compilerOpts = -framework PushKit +linkerOpts = -framework PushKit diff --git a/kotlin-native/platformLibs/src/platform/ios/QuartzCore.def b/kotlin-native/platformLibs/src/platform/ios/QuartzCore.def new file mode 100644 index 00000000000..bf48c159014 --- /dev/null +++ b/kotlin-native/platformLibs/src/platform/ios/QuartzCore.def @@ -0,0 +1,9 @@ +depends = CFNetwork CoreFoundation CoreGraphics EAGL Foundation Metal Security darwin posix +language = Objective-C +package = platform.QuartzCore +headers = QuartzCore/QuartzCore.h + +headerFilter = QuartzCore/** + +compilerOpts = -framework QuartzCore +linkerOpts = -framework QuartzCore diff --git a/kotlin-native/platformLibs/src/platform/ios/QuickLook.def b/kotlin-native/platformLibs/src/platform/ios/QuickLook.def new file mode 100644 index 00000000000..05721bfdc39 --- /dev/null +++ b/kotlin-native/platformLibs/src/platform/ios/QuickLook.def @@ -0,0 +1,7 @@ +depends = CFNetwork CoreFoundation CoreGraphics CoreImage CoreText CoreVideo EAGL FileProvider Foundation IOSurface ImageIO Metal OpenGLESCommon QuartzCore QuickLookThumbnailing Security UIKit UserNotifications darwin posix +language = Objective-C +package = platform.QuickLook +modules = QuickLook + +compilerOpts = -framework QuickLook +linkerOpts = -framework QuickLook diff --git a/kotlin-native/platformLibs/src/platform/ios/QuickLookThumbnailing.def b/kotlin-native/platformLibs/src/platform/ios/QuickLookThumbnailing.def new file mode 100644 index 00000000000..be7f8f77254 --- /dev/null +++ b/kotlin-native/platformLibs/src/platform/ios/QuickLookThumbnailing.def @@ -0,0 +1,7 @@ +depends = CFNetwork CoreFoundation CoreGraphics Foundation Security UniformTypeIdentifiers darwin posix +language = Objective-C +package = platform.QuickLookThumbnailing +modules = QuickLookThumbnailing + +compilerOpts = -framework QuickLookThumbnailing +linkerOpts = -framework QuickLookThumbnailing diff --git a/kotlin-native/platformLibs/src/platform/ios/RealityKit.def.disabled b/kotlin-native/platformLibs/src/platform/ios/RealityKit.def.disabled new file mode 100644 index 00000000000..31a0bfa9ad1 --- /dev/null +++ b/kotlin-native/platformLibs/src/platform/ios/RealityKit.def.disabled @@ -0,0 +1,6 @@ +language = Objective-C +package = platform.RealityKit +modules = RealityKit +compilerOpts = -framework RealityKit +linkerOpts = -framework RealityKit +#Disabled: Swift-only framework diff --git a/kotlin-native/platformLibs/src/platform/ios/ReplayKit.def b/kotlin-native/platformLibs/src/platform/ios/ReplayKit.def new file mode 100644 index 00000000000..eec6fbfa75f --- /dev/null +++ b/kotlin-native/platformLibs/src/platform/ios/ReplayKit.def @@ -0,0 +1,7 @@ +depends = AVFoundation AudioToolbox CFNetwork CoreAudio CoreAudioTypes CoreFoundation CoreGraphics CoreImage CoreMIDI CoreMedia CoreText CoreVideo EAGL FileProvider Foundation IOSurface ImageIO MediaToolbox Metal OpenGLESCommon QuartzCore Security UIKit UniformTypeIdentifiers UserNotifications darwin posix +language = Objective-C +package = platform.ReplayKit +modules = ReplayKit + +compilerOpts = -framework ReplayKit +linkerOpts = -framework ReplayKit diff --git a/kotlin-native/platformLibs/src/platform/ios/SafariServices.def b/kotlin-native/platformLibs/src/platform/ios/SafariServices.def new file mode 100644 index 00000000000..f1f4b468383 --- /dev/null +++ b/kotlin-native/platformLibs/src/platform/ios/SafariServices.def @@ -0,0 +1,7 @@ +depends = CFNetwork CoreFoundation CoreGraphics CoreImage CoreText CoreVideo EAGL FileProvider Foundation IOSurface ImageIO Metal OpenGLESCommon QuartzCore Security UIKit UserNotifications darwin posix +language = Objective-C +package = platform.SafariServices +modules = SafariServices + +compilerOpts = -framework SafariServices +linkerOpts = -framework SafariServices diff --git a/kotlin-native/platformLibs/src/platform/ios/SceneKit.def b/kotlin-native/platformLibs/src/platform/ios/SceneKit.def new file mode 100644 index 00000000000..6cbe80b2b5f --- /dev/null +++ b/kotlin-native/platformLibs/src/platform/ios/SceneKit.def @@ -0,0 +1,7 @@ +depends = CFNetwork CoreFoundation CoreGraphics CoreImage CoreText CoreVideo EAGL FileProvider Foundation GLKit IOSurface ImageIO Metal ModelIO OpenGLESCommon QuartzCore Security UIKit UserNotifications darwin posix +language = Objective-C +package = platform.SceneKit +modules = SceneKit + +compilerOpts = -framework SceneKit +linkerOpts = -framework SceneKit diff --git a/kotlin-native/platformLibs/src/platform/ios/ScreenTime.def b/kotlin-native/platformLibs/src/platform/ios/ScreenTime.def new file mode 100644 index 00000000000..b8fa02bf2f1 --- /dev/null +++ b/kotlin-native/platformLibs/src/platform/ios/ScreenTime.def @@ -0,0 +1,6 @@ +depends = CFNetwork CoreFoundation CoreGraphics CoreImage CoreText CoreVideo EAGL FileProvider Foundation IOSurface ImageIO Metal OpenGLESCommon QuartzCore Security UIKit UserNotifications darwin posix +language = Objective-C +package = platform.ScreenTime +modules = ScreenTime +compilerOpts = -framework ScreenTime +linkerOpts = -framework ScreenTime diff --git a/kotlin-native/platformLibs/src/platform/ios/Security.def b/kotlin-native/platformLibs/src/platform/ios/Security.def new file mode 100644 index 00000000000..de56b282a23 --- /dev/null +++ b/kotlin-native/platformLibs/src/platform/ios/Security.def @@ -0,0 +1,7 @@ +depends = CoreFoundation darwin posix +language = Objective-C +package = platform.Security +modules = Security + +compilerOpts = -framework Security +linkerOpts = -framework Security diff --git a/kotlin-native/platformLibs/src/platform/ios/SensorKit.def b/kotlin-native/platformLibs/src/platform/ios/SensorKit.def new file mode 100644 index 00000000000..b869e8cb3c2 --- /dev/null +++ b/kotlin-native/platformLibs/src/platform/ios/SensorKit.def @@ -0,0 +1,6 @@ +depends = CFNetwork CoreFoundation CoreLocation Foundation Security darwin posix +language = Objective-C +package = platform.SensorKit +modules = SensorKit +compilerOpts = -framework SensorKit +linkerOpts = -framework SensorKit diff --git a/kotlin-native/platformLibs/src/platform/ios/Social.def b/kotlin-native/platformLibs/src/platform/ios/Social.def new file mode 100644 index 00000000000..ec3967b3585 --- /dev/null +++ b/kotlin-native/platformLibs/src/platform/ios/Social.def @@ -0,0 +1,7 @@ +depends = CFNetwork CoreFoundation CoreGraphics CoreImage CoreText CoreVideo EAGL FileProvider Foundation IOSurface ImageIO Metal OpenGLESCommon QuartzCore Security UIKit UserNotifications darwin posix +language = Objective-C +package = platform.Social +modules = Social + +compilerOpts = -framework Social +linkerOpts = -framework Social diff --git a/kotlin-native/platformLibs/src/platform/ios/SoundAnalysis.def b/kotlin-native/platformLibs/src/platform/ios/SoundAnalysis.def new file mode 100644 index 00000000000..b5a396561bd --- /dev/null +++ b/kotlin-native/platformLibs/src/platform/ios/SoundAnalysis.def @@ -0,0 +1,7 @@ +depends = AVFoundation AudioToolbox CFNetwork CoreAudio CoreAudioTypes CoreFoundation CoreGraphics CoreMIDI CoreML CoreMedia CoreVideo EAGL Foundation IOSurface ImageIO MediaToolbox Metal OpenGLESCommon QuartzCore Security UniformTypeIdentifiers darwin posix +language = Objective-C +package = platform.SoundAnalysis +modules = SoundAnalysis + +compilerOpts = -framework SoundAnalysis +linkerOpts = -framework SoundAnalysis diff --git a/kotlin-native/platformLibs/src/platform/ios/Speech.def b/kotlin-native/platformLibs/src/platform/ios/Speech.def new file mode 100644 index 00000000000..cf581fc1773 --- /dev/null +++ b/kotlin-native/platformLibs/src/platform/ios/Speech.def @@ -0,0 +1,7 @@ +depends = AVFoundation AudioToolbox CFNetwork CoreAudio CoreAudioTypes CoreFoundation CoreGraphics CoreMIDI CoreMedia CoreVideo EAGL Foundation IOSurface ImageIO MediaToolbox Metal OpenGLESCommon QuartzCore Security UniformTypeIdentifiers darwin posix +language = Objective-C +package = platform.Speech +modules = Speech + +compilerOpts = -framework Speech +linkerOpts = -framework Speech diff --git a/kotlin-native/platformLibs/src/platform/ios/SpriteKit.def b/kotlin-native/platformLibs/src/platform/ios/SpriteKit.def new file mode 100644 index 00000000000..20ca6311652 --- /dev/null +++ b/kotlin-native/platformLibs/src/platform/ios/SpriteKit.def @@ -0,0 +1,7 @@ +depends = CFNetwork CoreFoundation CoreGraphics CoreImage CoreText CoreVideo EAGL FileProvider Foundation GLKit IOSurface ImageIO Metal OpenGLESCommon QuartzCore Security UIKit UserNotifications darwin posix +language = Objective-C +package = platform.SpriteKit +modules = SpriteKit + +compilerOpts = -framework SpriteKit +linkerOpts = -framework SpriteKit diff --git a/kotlin-native/platformLibs/src/platform/ios/StoreKit.def b/kotlin-native/platformLibs/src/platform/ios/StoreKit.def new file mode 100644 index 00000000000..c4df2a597d0 --- /dev/null +++ b/kotlin-native/platformLibs/src/platform/ios/StoreKit.def @@ -0,0 +1,7 @@ +depends = CFNetwork CoreFoundation CoreGraphics CoreImage CoreText CoreVideo EAGL FileProvider Foundation IOSurface ImageIO Metal OpenGLESCommon QuartzCore Security UIKit UserNotifications darwin posix +language = Objective-C +package = platform.StoreKit +modules = StoreKit + +compilerOpts = -framework StoreKit +linkerOpts = -framework StoreKit diff --git a/kotlin-native/platformLibs/src/platform/ios/SwiftUI.def.disabled b/kotlin-native/platformLibs/src/platform/ios/SwiftUI.def.disabled new file mode 100644 index 00000000000..59c29eff39e --- /dev/null +++ b/kotlin-native/platformLibs/src/platform/ios/SwiftUI.def.disabled @@ -0,0 +1,6 @@ +language = Objective-C +package = platform.SwiftUI +modules = SwiftUI +compilerOpts = -framework SwiftUI +linkerOpts = -framework SwiftUI +#Disabled: Swift-only framework diff --git a/kotlin-native/platformLibs/src/platform/ios/SystemConfiguration.def b/kotlin-native/platformLibs/src/platform/ios/SystemConfiguration.def new file mode 100644 index 00000000000..aeabf1da981 --- /dev/null +++ b/kotlin-native/platformLibs/src/platform/ios/SystemConfiguration.def @@ -0,0 +1,7 @@ +depends = CoreFoundation darwin posix +language = Objective-C +package = platform.SystemConfiguration +modules = SystemConfiguration + +compilerOpts = -framework SystemConfiguration +linkerOpts = -framework SystemConfiguration diff --git a/kotlin-native/platformLibs/src/platform/ios/Twitter.def b/kotlin-native/platformLibs/src/platform/ios/Twitter.def new file mode 100644 index 00000000000..d9df5c40cc2 --- /dev/null +++ b/kotlin-native/platformLibs/src/platform/ios/Twitter.def @@ -0,0 +1,7 @@ +depends = CFNetwork CoreFoundation CoreGraphics CoreImage CoreText CoreVideo EAGL FileProvider Foundation IOSurface ImageIO Metal OpenGLESCommon QuartzCore Security Social UIKit UserNotifications darwin posix +language = Objective-C +package = platform.Twitter +modules = Twitter + +compilerOpts = -framework Twitter +linkerOpts = -framework Twitter diff --git a/kotlin-native/platformLibs/src/platform/ios/UIKit.def b/kotlin-native/platformLibs/src/platform/ios/UIKit.def new file mode 100644 index 00000000000..83a7957cfaa --- /dev/null +++ b/kotlin-native/platformLibs/src/platform/ios/UIKit.def @@ -0,0 +1,8 @@ +depends = CFNetwork CoreFoundation CoreGraphics CoreImage CoreText CoreVideo EAGL FileProvider Foundation IOSurface ImageIO Metal OpenGLESCommon QuartzCore Security UserNotifications darwin posix +language = Objective-C +package = platform.UIKit +modules = UIKit + +compilerOpts = -framework UIKit +linkerOpts = -framework UIKit +excludedFunctions = UISceneErrorDomain diff --git a/kotlin-native/platformLibs/src/platform/ios/UniformTypeIdentifiers.def b/kotlin-native/platformLibs/src/platform/ios/UniformTypeIdentifiers.def new file mode 100644 index 00000000000..3d938bc1d54 --- /dev/null +++ b/kotlin-native/platformLibs/src/platform/ios/UniformTypeIdentifiers.def @@ -0,0 +1,6 @@ +depends = CFNetwork CoreFoundation Foundation Security darwin posix +language = Objective-C +package = platform.UniformTypeIdentifiers +modules = UniformTypeIdentifiers +compilerOpts = -framework UniformTypeIdentifiers +linkerOpts = -framework UniformTypeIdentifiers diff --git a/kotlin-native/platformLibs/src/platform/ios/UserNotifications.def b/kotlin-native/platformLibs/src/platform/ios/UserNotifications.def new file mode 100644 index 00000000000..acd9fb39cec --- /dev/null +++ b/kotlin-native/platformLibs/src/platform/ios/UserNotifications.def @@ -0,0 +1,7 @@ +depends = CFNetwork CoreFoundation Foundation Security darwin posix +language = Objective-C +package = platform.UserNotifications +modules = UserNotifications + +compilerOpts = -framework UserNotifications +linkerOpts = -framework UserNotifications diff --git a/kotlin-native/platformLibs/src/platform/ios/UserNotificationsUI.def b/kotlin-native/platformLibs/src/platform/ios/UserNotificationsUI.def new file mode 100644 index 00000000000..42ae7503a6a --- /dev/null +++ b/kotlin-native/platformLibs/src/platform/ios/UserNotificationsUI.def @@ -0,0 +1,7 @@ +depends = CFNetwork CoreFoundation CoreGraphics CoreImage CoreText CoreVideo EAGL FileProvider Foundation IOSurface ImageIO Metal OpenGLESCommon QuartzCore Security UIKit UserNotifications darwin posix +language = Objective-C +package = platform.UserNotificationsUI +modules = UserNotificationsUI + +compilerOpts = -framework UserNotificationsUI +linkerOpts = -framework UserNotificationsUI diff --git a/kotlin-native/platformLibs/src/platform/ios/VideoSubscriberAccount.def b/kotlin-native/platformLibs/src/platform/ios/VideoSubscriberAccount.def new file mode 100644 index 00000000000..009de3b4cb8 --- /dev/null +++ b/kotlin-native/platformLibs/src/platform/ios/VideoSubscriberAccount.def @@ -0,0 +1,7 @@ +depends = CoreFoundation Foundation darwin posix +language = Objective-C +package = platform.VideoSubscriberAccount +modules = VideoSubscriberAccount + +compilerOpts = -framework VideoSubscriberAccount +linkerOpts = -framework VideoSubscriberAccount diff --git a/kotlin-native/platformLibs/src/platform/ios/VideoToolbox.def b/kotlin-native/platformLibs/src/platform/ios/VideoToolbox.def new file mode 100644 index 00000000000..407c6c6cdd1 --- /dev/null +++ b/kotlin-native/platformLibs/src/platform/ios/VideoToolbox.def @@ -0,0 +1,16 @@ +depends = CFNetwork CoreAudio CoreAudioTypes CoreFoundation CoreGraphics CoreMedia CoreVideo Foundation IOSurface Metal OpenGLESCommon Security darwin posix +language = Objective-C +package = platform.VideoToolbox +modules = VideoToolbox + +compilerOpts = -framework VideoToolbox +linkerOpts = -framework VideoToolbox + +excludedFunctions = kVTCompressionPropertyKey_UsingGPURegistryID \ + kVTDecompressionPropertyKey_MaximizePowerEfficiency \ + kVTDecompressionPropertyKey_UsingGPURegistryID \ + kVTVideoDecoderSpecification_PreferredDecoderGPURegistryID \ + kVTVideoDecoderSpecification_RequiredDecoderGPURegistryID \ + kVTVideoEncoderList_GPURegistryID \ + kVTVideoEncoderSpecification_PreferredEncoderGPURegistryID \ + kVTVideoEncoderSpecification_RequiredEncoderGPURegistryID diff --git a/kotlin-native/platformLibs/src/platform/ios/Vision.def b/kotlin-native/platformLibs/src/platform/ios/Vision.def new file mode 100644 index 00000000000..7d4ce8465df --- /dev/null +++ b/kotlin-native/platformLibs/src/platform/ios/Vision.def @@ -0,0 +1,7 @@ +depends = CFNetwork CoreAudio CoreAudioTypes CoreFoundation CoreGraphics CoreML CoreMedia CoreVideo Foundation IOSurface ImageIO Metal OpenGLESCommon Security darwin posix +language = Objective-C +package = platform.Vision +modules = Vision + +compilerOpts = -framework Vision +linkerOpts = -framework Vision diff --git a/kotlin-native/platformLibs/src/platform/ios/VisionKit.def b/kotlin-native/platformLibs/src/platform/ios/VisionKit.def new file mode 100644 index 00000000000..959f1b8923e --- /dev/null +++ b/kotlin-native/platformLibs/src/platform/ios/VisionKit.def @@ -0,0 +1,7 @@ +depends = CFNetwork CoreFoundation CoreGraphics CoreImage CoreText CoreVideo EAGL FileProvider Foundation IOSurface ImageIO Metal OpenGLESCommon QuartzCore Security UIKit UserNotifications darwin posix +language = Objective-C +package = platform.VisionKit +modules = VisionKit + +compilerOpts = -framework VisionKit +linkerOpts = -framework VisionKit diff --git a/kotlin-native/platformLibs/src/platform/ios/WatchConnectivity.def b/kotlin-native/platformLibs/src/platform/ios/WatchConnectivity.def new file mode 100644 index 00000000000..54a9ae23324 --- /dev/null +++ b/kotlin-native/platformLibs/src/platform/ios/WatchConnectivity.def @@ -0,0 +1,7 @@ +depends = CFNetwork CoreFoundation Foundation Security darwin posix +language = Objective-C +package = platform.WatchConnectivity +modules = WatchConnectivity + +compilerOpts = -framework WatchConnectivity +linkerOpts = -framework WatchConnectivity diff --git a/kotlin-native/platformLibs/src/platform/ios/WebKit.def b/kotlin-native/platformLibs/src/platform/ios/WebKit.def new file mode 100644 index 00000000000..f5070f1c2b4 --- /dev/null +++ b/kotlin-native/platformLibs/src/platform/ios/WebKit.def @@ -0,0 +1,7 @@ +depends = CFNetwork CoreFoundation CoreGraphics CoreImage CoreText CoreVideo EAGL FileProvider Foundation IOSurface ImageIO Metal OpenGLESCommon QuartzCore Security UIKit UserNotifications darwin posix +language = Objective-C +package = platform.WebKit +modules = WebKit + +compilerOpts = -framework WebKit +linkerOpts = -framework WebKit diff --git a/kotlin-native/platformLibs/src/platform/ios/WidgetKit.def.disabled b/kotlin-native/platformLibs/src/platform/ios/WidgetKit.def.disabled new file mode 100644 index 00000000000..c007362810e --- /dev/null +++ b/kotlin-native/platformLibs/src/platform/ios/WidgetKit.def.disabled @@ -0,0 +1,6 @@ +language = Objective-C +package = platform.WidgetKit +modules = WidgetKit +compilerOpts = -framework WidgetKit +linkerOpts = -framework WidgetKit +#Disabled: Swift-only framework diff --git a/kotlin-native/platformLibs/src/platform/ios/_AVKit_SwiftUI.def.disabled b/kotlin-native/platformLibs/src/platform/ios/_AVKit_SwiftUI.def.disabled new file mode 100644 index 00000000000..04754e56b1b --- /dev/null +++ b/kotlin-native/platformLibs/src/platform/ios/_AVKit_SwiftUI.def.disabled @@ -0,0 +1,6 @@ +language = Objective-C +package = platform._AVKit_SwiftUI +modules = _AVKit_SwiftUI +compilerOpts = -framework _AVKit_SwiftUI +linkerOpts = -framework _AVKit_SwiftUI +#Disabled: Unavailable diff --git a/kotlin-native/platformLibs/src/platform/ios/_AuthenticationServices_SwiftUI.def.disabled b/kotlin-native/platformLibs/src/platform/ios/_AuthenticationServices_SwiftUI.def.disabled new file mode 100644 index 00000000000..ff6eb919630 --- /dev/null +++ b/kotlin-native/platformLibs/src/platform/ios/_AuthenticationServices_SwiftUI.def.disabled @@ -0,0 +1,6 @@ +language = Objective-C +package = platform._AuthenticationServices_SwiftUI +modules = _AuthenticationServices_SwiftUI +compilerOpts = -framework _AuthenticationServices_SwiftUI +linkerOpts = -framework _AuthenticationServices_SwiftUI +#Disabled: Unavailable diff --git a/kotlin-native/platformLibs/src/platform/ios/_HomeKit_SwiftUI.def.disabled b/kotlin-native/platformLibs/src/platform/ios/_HomeKit_SwiftUI.def.disabled new file mode 100644 index 00000000000..d5e70d04710 --- /dev/null +++ b/kotlin-native/platformLibs/src/platform/ios/_HomeKit_SwiftUI.def.disabled @@ -0,0 +1,6 @@ +language = Objective-C +package = platform._HomeKit_SwiftUI +modules = _HomeKit_SwiftUI +compilerOpts = -framework _HomeKit_SwiftUI +linkerOpts = -framework _HomeKit_SwiftUI +#Disabled: Unavailable diff --git a/kotlin-native/platformLibs/src/platform/ios/_MapKit_SwiftUI.def.disabled b/kotlin-native/platformLibs/src/platform/ios/_MapKit_SwiftUI.def.disabled new file mode 100644 index 00000000000..3accf28420d --- /dev/null +++ b/kotlin-native/platformLibs/src/platform/ios/_MapKit_SwiftUI.def.disabled @@ -0,0 +1,6 @@ +language = Objective-C +package = platform._MapKit_SwiftUI +modules = _MapKit_SwiftUI +compilerOpts = -framework _MapKit_SwiftUI +linkerOpts = -framework _MapKit_SwiftUI +#Disabled: Unavailable diff --git a/kotlin-native/platformLibs/src/platform/ios/_QuickLook_SwiftUI.def.disabled b/kotlin-native/platformLibs/src/platform/ios/_QuickLook_SwiftUI.def.disabled new file mode 100644 index 00000000000..0baedbbb5dc --- /dev/null +++ b/kotlin-native/platformLibs/src/platform/ios/_QuickLook_SwiftUI.def.disabled @@ -0,0 +1,7 @@ +language = Objective-C +package = platform._QuickLook_SwiftUI + +modules = _QuickLook_SwiftUI +compilerOpts = -framework _QuickLook_SwiftUI +linkerOpts = -framework _QuickLook_SwiftUI +#Disabled: Unavailable diff --git a/kotlin-native/platformLibs/src/platform/ios/_SceneKit_SwiftUI.def.disabled b/kotlin-native/platformLibs/src/platform/ios/_SceneKit_SwiftUI.def.disabled new file mode 100644 index 00000000000..4e18821c3d0 --- /dev/null +++ b/kotlin-native/platformLibs/src/platform/ios/_SceneKit_SwiftUI.def.disabled @@ -0,0 +1,6 @@ +language = Objective-C +package = platform._SceneKit_SwiftUI +modules = _SceneKit_SwiftUI +compilerOpts = -framework _SceneKit_SwiftUI +linkerOpts = -framework _SceneKit_SwiftUI +#Disabled: Unavailable diff --git a/kotlin-native/platformLibs/src/platform/ios/_SpriteKit_SwiftUI.def.disabled b/kotlin-native/platformLibs/src/platform/ios/_SpriteKit_SwiftUI.def.disabled new file mode 100644 index 00000000000..572286b1f66 --- /dev/null +++ b/kotlin-native/platformLibs/src/platform/ios/_SpriteKit_SwiftUI.def.disabled @@ -0,0 +1,6 @@ +language = Objective-C +package = platform._SpriteKit_SwiftUI +modules = _SpriteKit_SwiftUI +compilerOpts = -framework _SpriteKit_SwiftUI +linkerOpts = -framework _SpriteKit_SwiftUI +#Disabled: Unavailable diff --git a/kotlin-native/platformLibs/src/platform/ios/_StoreKit_SwiftUI.def.disabled b/kotlin-native/platformLibs/src/platform/ios/_StoreKit_SwiftUI.def.disabled new file mode 100644 index 00000000000..b45b2dc4cff --- /dev/null +++ b/kotlin-native/platformLibs/src/platform/ios/_StoreKit_SwiftUI.def.disabled @@ -0,0 +1,6 @@ +language = Objective-C +package = platform._StoreKit_SwiftUI +modules = _StoreKit_SwiftUI +compilerOpts = -framework _StoreKit_SwiftUI +linkerOpts = -framework _StoreKit_SwiftUI +#Disabled: Unavailable diff --git a/kotlin-native/platformLibs/src/platform/ios/builtin.def b/kotlin-native/platformLibs/src/platform/ios/builtin.def new file mode 100644 index 00000000000..67e031b1dd3 --- /dev/null +++ b/kotlin-native/platformLibs/src/platform/ios/builtin.def @@ -0,0 +1,101 @@ +depends = posix +package = platform.builtin +headerFilter = ** +language = C + +excludedFunctions.ios_arm32 = builtin_clear_cache +excludedFunctions.ios_arm64 = builtin_clear_cache +--- +// See https://github.com/llvm-mirror/clang/blob/master/include/clang/Basic/Builtins.def +// TODO: autogenerate from machine format. + +// Returns x with the order of the bytes reversed; for example, 0xaabb becomes 0xbbaa. Byte here always means exactly 8 bits. +static inline short builtin_bswap16(short x) { + return __builtin_bswap16(x); +} + +static inline int builtin_bswap32(int x) { + return __builtin_bswap32(x); +} + +static inline long long builtin_bswap64(long long x) { + return __builtin_bswap64(x); +} + +// Returns the number of leading 0-bits in x, starting at the most significant bit position. If x is 0, the result is undefined. +static inline int builtin_clzs(unsigned short x) { + return __builtin_clzs(x); +} + +static inline int builtin_clz(unsigned int x) { + return __builtin_clz(x); +} + +static inline int builtin_clzl(unsigned long x) { + return __builtin_clzl(x); +} + +static inline int builtin_clzll(unsigned long long x) { + return __builtin_clzll(x); +} + +// Returns the number of trailing 0-bits in x, starting at the least significant bit position. If x is 0, the result is undefined. +static inline int builtin_ctzs(unsigned short x) { + return __builtin_ctzs(x); +} + +static inline int builtin_ctz(unsigned int x) { + return __builtin_ctz(x); +} + +static inline int builtin_ctzl(unsigned long x) { + return __builtin_ctzl(x); +} + +static inline int builtin_ctzll(unsigned long long x) { + return __builtin_ctzll(x); +} + +// Returns one plus the index of the least significant 1-bit of x, or if x is zero, returns zero. +static inline int builtin_ffs(int x) { + return __builtin_ffs(x); +} + +static inline int builtin_ffsl(long x) { + return __builtin_ffsl(x); +} + +static inline int builtin_ffsll(long long x) { + return __builtin_ffsll(x); +} + +// Returns the parity of x, i.e. the number of 1-bits in x modulo 2. +static inline int builtin_parity(int x) { + return __builtin_parity(x); +} + +static inline int builtin_parityl(unsigned long x) { + return __builtin_parityl(x); +} + +static inline int builtin_parityll(unsigned long long x) { + return __builtin_parityll(x); +} + +// Returns the number of 1-bits in x. +static inline int builtin_popcount(int x) { + return __builtin_popcount(x); +} + +static inline int builtin_popcountl(long x) { + return __builtin_popcountl(x); +} + +static inline int builtin_popcountll(long long x) { + return __builtin_popcountll(x); +} + +// This function is used to flush the processor's instruction cache for the region of memory between begin inclusive and end exclusive. +static inline void builtin_clear_cache(void* begin, void* end) { + __builtin___clear_cache(begin, end); +} diff --git a/kotlin-native/platformLibs/src/platform/ios/darwin.def b/kotlin-native/platformLibs/src/platform/ios/darwin.def new file mode 100644 index 00000000000..1a4e4b76f47 --- /dev/null +++ b/kotlin-native/platformLibs/src/platform/ios/darwin.def @@ -0,0 +1,45 @@ +depends = posix +language = Objective-C +package = platform.darwin +headers = AppleTextureEncoder.h AssertMacros.h Availability.h AvailabilityInternal.h \ + AvailabilityMacros.h Block.h ConditionalMacros.h MacTypes.h \ + TargetConditionals.h __cxxabi_config.h _locale.h _types.h _wctype.h \ + aio.h asl.h bitstring.h bzlib.h \ + cache.h cache_callbacks.h checkint.h compression.h copyfile.h \ + cpio.h cxxabi.h db.h \ + dns.h dns_sd.h dns_util.h execinfo.h \ + fmtmsg.h fstab.h \ + gethostuuid.h glob.h ifaddrs.h inttypes.h iso646.h \ + langinfo.h \ + libgen.h libunwind.h \ + membership.h monetary.h mpool.h \ + nameser.h ndbm.h nl_types.h \ + notify.h notify_keys.h ntsid.h \ + printf.h \ + readpassphrase.h removefile.h \ + runetype.h sandbox.h standards.h \ + stringlist.h sysdir.h sysexits.h tar.h \ + ttyent.h \ + unwind.h util.h utmpx.h vis.h wordexp.h xattr_flags.h \ + bank/bank_types.h \ + bsm/audit.h \ + os/activity.h os/availability.h os/base.h os/lock.h \ + os/log.h os/object.h os/overflow.h os/signpost.h os/trace.h \ + simd/simd.h sys/sysctl.h + +headerFilter = ** + +excludedFunctions = __tg_promote KERNEL_AUDIT_TOKEN KERNEL_SECURITY_TOKEN \ + asl_decode_buffer asl_encode_buffer asl_remove_index \ + averunnable dbm_forder pidlock ttyaction ttylock ttymsg ttyunlock uuid_generate_early_random \ + vm_stats + +excludedFunctions.ios_arm32 = _Unwind_Backtrace _Unwind_FindEnclosingFunction _Unwind_Find_FDE \ + _Unwind_SjLj_ForcedUnwind __deregister_frame __register_frame + +compilerOpts = -D_XOPEN_SOURCE -DSYSCTL_DEF_ENABLED +linkerOpts = -ldl -lz -lbz2 -lcompression -late + +--- + +// menu.h is excluded so far due to interop issues. diff --git a/kotlin-native/platformLibs/src/platform/ios/iAd.def b/kotlin-native/platformLibs/src/platform/ios/iAd.def new file mode 100644 index 00000000000..a5e43cf8c0f --- /dev/null +++ b/kotlin-native/platformLibs/src/platform/ios/iAd.def @@ -0,0 +1,7 @@ +depends = AVFoundation AVKit AudioToolbox CFNetwork CoreAudio CoreAudioTypes CoreFoundation CoreGraphics CoreImage CoreMIDI CoreMedia CoreText CoreVideo EAGL FileProvider Foundation IOSurface ImageIO MediaToolbox Metal OpenGLESCommon QuartzCore Security UIKit UniformTypeIdentifiers UserNotifications darwin posix +language = Objective-C +package = platform.iAd +modules = iAd + +compilerOpts = -framework iAd +linkerOpts = -framework iAd diff --git a/kotlin-native/platformLibs/src/platform/ios/iconv.def b/kotlin-native/platformLibs/src/platform/ios/iconv.def new file mode 100644 index 00000000000..e52d20f4da0 --- /dev/null +++ b/kotlin-native/platformLibs/src/platform/ios/iconv.def @@ -0,0 +1,5 @@ +depends = posix +package = platform.iconv +headers = iconv.h +headerFilter = ** +linkerOpts = -liconv diff --git a/kotlin-native/platformLibs/src/platform/ios/objc.def b/kotlin-native/platformLibs/src/platform/ios/objc.def new file mode 100644 index 00000000000..20d1b81ca04 --- /dev/null +++ b/kotlin-native/platformLibs/src/platform/ios/objc.def @@ -0,0 +1,13 @@ +depends = darwin posix +language = Objective-C +package = platform.objc +headers = objc/NSObjCRuntime.h objc/NSObject.h objc/message.h objc/objc-api.h \ + objc/objc-exception.h objc/objc-sync.h objc/objc.h objc/runtime.h + +headerFilter = objc/** + +compilerOpts = -D_XOPEN_SOURCE +linkerOpts = -lobjc + +--- +// objc-auto.h is excluded so far due to interop issues. diff --git a/kotlin-native/platformLibs/src/platform/ios/posix.def b/kotlin-native/platformLibs/src/platform/ios/posix.def new file mode 100644 index 00000000000..24bd53f65f6 --- /dev/null +++ b/kotlin-native/platformLibs/src/platform/ios/posix.def @@ -0,0 +1,49 @@ +depends = +package = platform.posix +headers = alloca.h assert.h complex.h ctype.h dirent.h dlfcn.h err.h errno.h fcntl.h \ + fenv.h float.h fnmatch.h fts.h ftw.h getopt.h grp.h inttypes.h libgen.h limits.h \ + locale.h math.h memory.h netdb.h paths.h poll.h \ + pthread.h pwd.h regex.h resolv.h sched.h search.h semaphore.h setjmp.h signal.h \ + stdatomic.h stdint.h stdio.h stdlib.h string.h strings.h syslog.h termios.h \ + time.h ucontext.h unistd.h utime.h wchar.h wctype.h xlocale.h \ + net/ethernet.h net/if.h \ + netinet/icmp6.h netinet/in.h netinet/in_systm.h \ + netinet/ip.h netinet/ip6.h netinet/ip_icmp.h netinet/tcp.h netinet/udp.h \ + sys/acl.h sys/ioctl.h sys/ipc.h sys/mman.h sys/poll.h \ + sys/queue.h sys/select.h sys/shm.h sys/stat.h \ + sys/syslimits.h sys/time.h sys/times.h sys/utsname.h sys/wait.h + +compilerOpts = -D_XOPEN_SOURCE -D_DARWIN_C_SOURCE +linkerOpts = -ldl -lresolv +excludedFunctions = acl_valid_link_np add_profil pfctlinput profil unwhiteout zopen getdirentries \ + uuid_generate_early_random setgrfile \ + in6addr_linklocal_allv2routers +excludedFunctions.ios_arm32 = longjmperror +excludedFunctions.ios_arm64 = longjmperror +excludedFunctions.ios_x64 = pthread_jit_write_protect_np pthread_jit_write_protect_supported_np + +--- +// Wrapper to access errno variable. +static int posix_errno() { + return errno; +} + +static void set_posix_errno(int value) { + errno = value; +} + +// Wrapper to access h_errno variable. +static int posix_h_errno() { + return h_errno; +} + +static void set_posix_h_errno(int value) { + h_errno = value; +} + +static int init_sockets() { + return 0; +} + +static void deinit_sockets() { +} diff --git a/kotlin-native/platformLibs/src/platform/ios/set_depends.sh b/kotlin-native/platformLibs/src/platform/ios/set_depends.sh new file mode 100755 index 00000000000..bfcbaaf14f8 --- /dev/null +++ b/kotlin-native/platformLibs/src/platform/ios/set_depends.sh @@ -0,0 +1,2 @@ +#!/bin/bash +../../../../dist/bin/run_konan defFileDependencies -target ios_arm32 -target ios_arm64 -target ios_x64 *.def diff --git a/kotlin-native/platformLibs/src/platform/ios/zlib.def b/kotlin-native/platformLibs/src/platform/ios/zlib.def new file mode 100644 index 00000000000..8292dd723fa --- /dev/null +++ b/kotlin-native/platformLibs/src/platform/ios/zlib.def @@ -0,0 +1,34 @@ +depends = posix +package = platform.zlib +headers = zconf.h zlib.h +headerFilter = zconf.h zlib.h +compilerOpts = -DByte=uByte -DBytef=uBytef +linkerOpts = -lz + +--- +#undef deflateInit +static inline int deflateInit(z_streamp strm, int level) { + return deflateInit_(strm, level, ZLIB_VERSION, (int)sizeof(z_stream)); +} + +#undef deflateInit2 +static inline int deflateInit2(z_streamp strm, int level, int method, + int windowBits, int memLevel, int strategy) { + return deflateInit2_(strm, level, method, windowBits, memLevel, + strategy, ZLIB_VERSION, (int)sizeof(z_stream)); +} + +#undef inflateInit +static inline int inflateInit(z_streamp strm) { + return inflateInit_(strm, ZLIB_VERSION, (int)sizeof(z_stream)); +} + +#undef inflateInit2 +static inline int inflateInit2(z_streamp strm, int windowBits) { + return inflateInit2_(strm, windowBits, ZLIB_VERSION, (int)sizeof(z_stream)); +} + +#undef inflateBackInit +static inline int inflateBackInit(z_streamp strm, int windowBits, unsigned char *window) { + return inflateBackInit_(strm, windowBits, window, ZLIB_VERSION, (int)sizeof(z_stream)); +} diff --git a/kotlin-native/platformLibs/src/platform/linux/builtin.def b/kotlin-native/platformLibs/src/platform/linux/builtin.def new file mode 100644 index 00000000000..d7d93621827 --- /dev/null +++ b/kotlin-native/platformLibs/src/platform/linux/builtin.def @@ -0,0 +1,97 @@ +package = platform.builtin +headerFilter = +language = C +--- +// See https://github.com/llvm-mirror/clang/blob/master/include/clang/Basic/Builtins.def +// TODO: autogenerate from machine format. + +// Returns x with the order of the bytes reversed; for example, 0xaabb becomes 0xbbaa. Byte here always means exactly 8 bits. +static inline short builtin_bswap16(short x) { + return __builtin_bswap16(x); +} + +static inline int builtin_bswap32(int x) { + return __builtin_bswap32(x); +} + +static inline long long builtin_bswap64(long long x) { + return __builtin_bswap64(x); +} + +// Returns the number of leading 0-bits in x, starting at the most significant bit position. If x is 0, the result is undefined. +static inline int builtin_clzs(unsigned short x) { + return __builtin_clzs(x); +} + +static inline int builtin_clz(unsigned int x) { + return __builtin_clz(x); +} + +static inline int builtin_clzl(unsigned long x) { + return __builtin_clzl(x); +} + +static inline int builtin_clzll(unsigned long long x) { + return __builtin_clzll(x); +} + +// Returns the number of trailing 0-bits in x, starting at the least significant bit position. If x is 0, the result is undefined. +static inline int builtin_ctzs(unsigned short x) { + return __builtin_ctzs(x); +} + +static inline int builtin_ctz(unsigned int x) { + return __builtin_ctz(x); +} + +static inline int builtin_ctzl(unsigned long x) { + return __builtin_ctzl(x); +} + +static inline int builtin_ctzll(unsigned long long x) { + return __builtin_ctzll(x); +} + +// Returns one plus the index of the least significant 1-bit of x, or if x is zero, returns zero. +static inline int builtin_ffs(int x) { + return __builtin_ffs(x); +} + +static inline int builtin_ffsl(long x) { + return __builtin_ffsl(x); +} + +static inline int builtin_ffsll(long long x) { + return __builtin_ffsll(x); +} + +// Returns the parity of x, i.e. the number of 1-bits in x modulo 2. +static inline int builtin_parity(int x) { + return __builtin_parity(x); +} + +static inline int builtin_parityl(unsigned long x) { + return __builtin_parityl(x); +} + +static inline int builtin_parityll(unsigned long long x) { + return __builtin_parityll(x); +} + +// Returns the number of 1-bits in x. +static inline int builtin_popcount(int x) { + return __builtin_popcount(x); +} + +static inline int builtin_popcountl(long x) { + return __builtin_popcountl(x); +} + +static inline int builtin_popcountll(long long x) { + return __builtin_popcountll(x); +} + +// This function is used to flush the processor's instruction cache for the region of memory between begin inclusive and end exclusive. +static inline void builtin_clear_cache(void* begin, void* end) { + __builtin___clear_cache(begin, end); +} \ No newline at end of file diff --git a/kotlin-native/platformLibs/src/platform/linux/iconv.def b/kotlin-native/platformLibs/src/platform/linux/iconv.def new file mode 100644 index 00000000000..49dd9ec0ed2 --- /dev/null +++ b/kotlin-native/platformLibs/src/platform/linux/iconv.def @@ -0,0 +1,3 @@ +depends = posix +package = platform.iconv +headers = iconv.h diff --git a/kotlin-native/platformLibs/src/platform/linux/linux.def b/kotlin-native/platformLibs/src/platform/linux/linux.def new file mode 100644 index 00000000000..d3f12346b48 --- /dev/null +++ b/kotlin-native/platformLibs/src/platform/linux/linux.def @@ -0,0 +1,40 @@ +package = platform.linux +headers = aio.h aliases.h a.out.h argp.h argz.h byteswap.h cpio.h crypt.h \ + elf.h endian.h envz.h error.h execinfo.h features.h fmtmsg.h \ + fpu_control.h \ + fstab.h _G_config.h gconv.h glob.h gnu-versions.h \ + gshadow.h ieee754.h ifaddrs.h langinfo.h lastlog.h \ + libintl.h libio.h link.h malloc.h mcheck.h mntent.h \ + monetary.h mqueue.h \ + nl_types.h nss.h obstack.h \ + printf.h pty.h re_comp.h \ + spawn.h stab.h stdc-predef.h stdio_ext.h syscall.h \ + tar.h termio.h thread_db.h ttyent.h uchar.h ulimit.h \ + ustat.h utmpx.h values.h wait.h wordexp.h \ + arpa/ftp.h arpa/inet.h arpa/nameser_compat.h \ + arpa/nameser.h arpa/telnet.h arpa/tftp.h \ + netinet/if_ether.h net/if_packet.h \ + netinet/ether.h linux/in6.h netpacket/packet.h \ + sys/acct.h sys/auxv.h sys/bitypes.h sys/cdefs.h \ + sys/dir.h sys/epoll.h sys/errno.h \ + sys/eventfd.h sys/fanotify.h sys/fcntl.h \ + sys/file.h sys/fsuid.h sys/gmon.h sys/gmon_out.h \ + sys/inotify.h sys/kd.h sys/klog.h sys/mount.h \ + sys/msg.h sys/mtio.h sys/param.h sys/pci.h \ + sys/personality.h sys/prctl.h sys/procfs.h sys/profil.h \ + sys/raw.h sys/reboot.h sys/resource.h \ + sys/sem.h sys/sendfile.h sys/signalfd.h sys/signal.h \ + sys/socket.h sys/socketvar.h sys/soundcard.h sys/statfs.h \ + sys/statvfs.h sys/stropts.h sys/swap.h sys/syscall.h \ + sys/sysctl.h sys/sysinfo.h sys/syslog.h sys/sysmacros.h sys/termios.h \ + sys/timeb.h sys/timerfd.h sys/timex.h sys/ttychars.h \ + sys/ttydefaults.h sys/types.h sys/ucontext.h sys/uio.h \ + sys/ultrasound.h sys/un.h sys/unistd.h sys/user.h \ + sys/ustat.h utime.h sys/utsname.h sys/vfs.h sys/vlimit.h \ + sys/vt.h sys/vtimes.h sys/xattr.h + +headers.x86-64 = sys/debugreg.h sys/reg.h sys/io.h sys/perm.h sys/kdaemon.h + +compilerOpts = -D_ANSI_SOURCE -D_POSIX_C_SOURCE=199309 -D_BSD_SOURCE -D_XOPEN_SOURCE=700 +depends = posix + diff --git a/kotlin-native/platformLibs/src/platform/linux/posix.def b/kotlin-native/platformLibs/src/platform/linux/posix.def new file mode 100644 index 00000000000..52c26779554 --- /dev/null +++ b/kotlin-native/platformLibs/src/platform/linux/posix.def @@ -0,0 +1,80 @@ +package = platform.posix +headers = alloca.h ar.h assert.h complex.h ctype.h dirent.h dlfcn.h err.h errno.h fcntl.h \ + fenv.h fnmatch.h fts.h ftw.h getopt.h grp.h inttypes.h libgen.h limits.h \ + locale.h math.h memory.h netdb.h paths.h poll.h \ + pthread.h pwd.h regex.h resolv.h sched.h search.h semaphore.h setjmp.h sgtty.h signal.h \ + stdatomic.h stdint.h stdio.h stdlib.h string.h strings.h syslog.h termios.h \ + time.h ucontext.h unistd.h utime.h utmp.h wchar.h wctype.h xlocale.h \ + net/ethernet.h net/if.h net/if_arp.h net/route.h \ + netinet/icmp6.h netinet/if_ether.h netinet/in.h netinet/in_systm.h \ + netinet/ip.h netinet/ip6.h netinet/ip_icmp.h netinet/tcp.h netinet/udp.h \ + sys/ioctl.h sys/ipc.h sys/mman.h sys/poll.h sys/ptrace.h \ + sys/queue.h sys/select.h sys/shm.h sys/stat.h sys/socket.h \ + sys/time.h sys/times.h sys/utsname.h sys/wait.h + +compilerOpts = -D_ANSI_SOURCE -D_POSIX_C_SOURCE=199309 -D_BSD_SOURCE \ + -D_XOPEN_SOURCE=700 -D__need_error_t +linkerOpts = -lresolv -lm -lpthread -lutil -lcrypt -lrt +excludedFunctions = bindresvport6 __p_section __res_nisourserver __res_npquery \ + ns_sign ns_sign2 ns_sign_tcp ns_sign_tcp2 ns_sign_tcp_init \ + ns_find_tsig ns_verify ns_verify_tcp ns_verify_tcp_init \ + __acos __asin __atan __atan2 __cos __sin __tan __cosh __sinh \ + __tanh __acosh __asinh __atanh __exp __frexp __ldexp __log __log10 \ + __modf __expm1 __log1p __logb __exp2 __log2 __pow __sqrt __hypot \ + __cbrt __ceil __fabs __floor __fmod __drem __significand __copysign \ + __nan __j0 __j1 __jn __y0 __y1 __yn __erf __erfc __lgamma __tgamma \ + __gamma __lgamma_r __rint __nextafter __remainder __scalbn __ilogb \ + __scalbln __nearbyint __round __trunc __remquo __lrint __llrint \ + __lround __llround __fdim __fmax __fmin __fma __scalb __acosf __asinf \ + __atanf __atan2f __cosf __sinf __tanf __coshf __sinhf __tanhf __acoshf \ + __asinhf __atanhf __expf __frexpf __ldexpf __logf __log10f __modff \ + __expm1f __log1pf __logbf __exp2f __log2f __powf __sqrtf __hypotf \ + __cbrtf __ceilf __fabsf __floorf __fmodf __dremf __significandf \ + __copysignf __nanf __j0f __j1f __jnf __y0f __y1f __ynf __erff \ + __erfcf __lgammaf __tgammaf __gammaf __lgammaf_r __rintf __nextafterf \ + __remainderf __scalbnf __ilogbf __scalblnf __nearbyintf __roundf __truncf \ + __remquof __lrintf __llrintf __lroundf __llroundf __fdimf __fmaxf __fminf \ + __fmaf __scalbf _ns_flagdata +--- +// cinterop -target linux -def klib/src/platform/linux/posix.def -o platform.posix.klib + +// Wrapper to access errno variable. +static int posix_errno() { + return errno; +} + +static void set_posix_errno(int value) { + errno = value; +} + +// Wrapper to access h_errno variable. +static int posix_h_errno() { + return h_errno; +} + +static void set_posix_h_errno(int value) { + h_errno = value; +} + +static short posix_htons(short x) { + return htons(x); +} + +static void posix_FD_ZERO(fd_set *set) { + FD_ZERO(set); +} + +static void posix_FD_SET(int bit, fd_set *set) { + FD_SET(bit, set); +} + +static int posix_FD_ISSET(int bit, fd_set *set) { + return FD_ISSET(bit, set); +} + +static int init_sockets() { + return 0; +} + +static void deinit_sockets() { +} diff --git a/kotlin-native/platformLibs/src/platform/linux/zlib.def b/kotlin-native/platformLibs/src/platform/linux/zlib.def new file mode 100644 index 00000000000..04eec1ee09e --- /dev/null +++ b/kotlin-native/platformLibs/src/platform/linux/zlib.def @@ -0,0 +1,34 @@ +depends = posix +package = platform.zlib +headers = zconf.h zlib.h +headerFilter = zlib.h +compilerOpts = -DByte=uByte -DBytef=uBytef -D_ANSI_SOURCE -D_POSIX_C_SOURCE=199309 -D_BSD_SOURCE -D_XOPEN_SOURCE=700 +linkerOpts = -lz + +--- +#undef deflateInit +static inline int deflateInit(z_streamp strm, int level) { + return deflateInit_(strm, level, ZLIB_VERSION, (int)sizeof(z_stream)); +} + +#undef deflateInit2 +static inline int deflateInit2(z_streamp strm, int level, int method, + int windowBits, int memLevel, int strategy) { + return deflateInit2_(strm, level, method, windowBits, memLevel, + strategy, ZLIB_VERSION, (int)sizeof(z_stream)); +} + +#undef inflateInit +static inline int inflateInit(z_streamp strm) { + return inflateInit_(strm, ZLIB_VERSION, (int)sizeof(z_stream)); +} + +#undef inflateInit2 +static inline int inflateInit2(z_streamp strm, int windowBits) { + return inflateInit2_(strm, windowBits, ZLIB_VERSION, (int)sizeof(z_stream)); +} + +#undef inflateBackInit +static inline int inflateBackInit(z_streamp strm, int windowBits, unsigned char *window) { + return inflateBackInit_(strm, windowBits, window, ZLIB_VERSION, (int)sizeof(z_stream)); +} diff --git a/kotlin-native/platformLibs/src/platform/mingw/builtin.def b/kotlin-native/platformLibs/src/platform/mingw/builtin.def new file mode 100644 index 00000000000..d7d93621827 --- /dev/null +++ b/kotlin-native/platformLibs/src/platform/mingw/builtin.def @@ -0,0 +1,97 @@ +package = platform.builtin +headerFilter = +language = C +--- +// See https://github.com/llvm-mirror/clang/blob/master/include/clang/Basic/Builtins.def +// TODO: autogenerate from machine format. + +// Returns x with the order of the bytes reversed; for example, 0xaabb becomes 0xbbaa. Byte here always means exactly 8 bits. +static inline short builtin_bswap16(short x) { + return __builtin_bswap16(x); +} + +static inline int builtin_bswap32(int x) { + return __builtin_bswap32(x); +} + +static inline long long builtin_bswap64(long long x) { + return __builtin_bswap64(x); +} + +// Returns the number of leading 0-bits in x, starting at the most significant bit position. If x is 0, the result is undefined. +static inline int builtin_clzs(unsigned short x) { + return __builtin_clzs(x); +} + +static inline int builtin_clz(unsigned int x) { + return __builtin_clz(x); +} + +static inline int builtin_clzl(unsigned long x) { + return __builtin_clzl(x); +} + +static inline int builtin_clzll(unsigned long long x) { + return __builtin_clzll(x); +} + +// Returns the number of trailing 0-bits in x, starting at the least significant bit position. If x is 0, the result is undefined. +static inline int builtin_ctzs(unsigned short x) { + return __builtin_ctzs(x); +} + +static inline int builtin_ctz(unsigned int x) { + return __builtin_ctz(x); +} + +static inline int builtin_ctzl(unsigned long x) { + return __builtin_ctzl(x); +} + +static inline int builtin_ctzll(unsigned long long x) { + return __builtin_ctzll(x); +} + +// Returns one plus the index of the least significant 1-bit of x, or if x is zero, returns zero. +static inline int builtin_ffs(int x) { + return __builtin_ffs(x); +} + +static inline int builtin_ffsl(long x) { + return __builtin_ffsl(x); +} + +static inline int builtin_ffsll(long long x) { + return __builtin_ffsll(x); +} + +// Returns the parity of x, i.e. the number of 1-bits in x modulo 2. +static inline int builtin_parity(int x) { + return __builtin_parity(x); +} + +static inline int builtin_parityl(unsigned long x) { + return __builtin_parityl(x); +} + +static inline int builtin_parityll(unsigned long long x) { + return __builtin_parityll(x); +} + +// Returns the number of 1-bits in x. +static inline int builtin_popcount(int x) { + return __builtin_popcount(x); +} + +static inline int builtin_popcountl(long x) { + return __builtin_popcountl(x); +} + +static inline int builtin_popcountll(long long x) { + return __builtin_popcountll(x); +} + +// This function is used to flush the processor's instruction cache for the region of memory between begin inclusive and end exclusive. +static inline void builtin_clear_cache(void* begin, void* end) { + __builtin___clear_cache(begin, end); +} \ No newline at end of file diff --git a/kotlin-native/platformLibs/src/platform/mingw/gdiplus.def b/kotlin-native/platformLibs/src/platform/mingw/gdiplus.def new file mode 100644 index 00000000000..261709f197e --- /dev/null +++ b/kotlin-native/platformLibs/src/platform/mingw/gdiplus.def @@ -0,0 +1,6 @@ +depends = windows posix +package = platform.gdiplus +headers = wtypes.h minwindef.h wtypes.h gdiplus/gdiplus.h +headerFilter = gdiplus/** +compilerOpts = -DUNICODE +linkerOpts = -lgdiplus \ No newline at end of file diff --git a/kotlin-native/platformLibs/src/platform/mingw/iconv.def b/kotlin-native/platformLibs/src/platform/mingw/iconv.def new file mode 100644 index 00000000000..2bcab5219ee --- /dev/null +++ b/kotlin-native/platformLibs/src/platform/mingw/iconv.def @@ -0,0 +1,24 @@ +depends = posix +package = platform.iconv +headers = iconv.h +headerFilter = NOTHING +linkerOpts = -Wl,-Bstatic -liconv -Wl,-Bdynamic + +--- +#undef iconv_t +typedef void *iconv_t; + +#undef iconv_open +static inline iconv_t iconv_open(const char* tocode, const char* fromcode) { + return libiconv_open(tocode, fromcode); +} + +#undef iconv +static inline size_t iconv(iconv_t cd, char **inbuf, size_t *inbytesleft, char **outbuf, size_t *outbytesleft) { + return libiconv(cd, inbuf, inbytesleft, outbuf, outbytesleft); +} + +#undef iconv_close +static inline int iconv_close(iconv_t cd) { + return libiconv_close(cd); +} diff --git a/kotlin-native/platformLibs/src/platform/mingw/opengl32.def b/kotlin-native/platformLibs/src/platform/mingw/opengl32.def new file mode 100644 index 00000000000..3be3365fd26 --- /dev/null +++ b/kotlin-native/platformLibs/src/platform/mingw/opengl32.def @@ -0,0 +1,5 @@ +package = platform.opengl32 +headers = GL/gl.h GL/glext.h +headerFilter = GL/gl.h GL/glext.h +compilerOpts = -DUNICODE +linkerOpts = -lopengl32 diff --git a/kotlin-native/platformLibs/src/platform/mingw/posix.def b/kotlin-native/platformLibs/src/platform/mingw/posix.def new file mode 100644 index 00000000000..46ff5f2d1d9 --- /dev/null +++ b/kotlin-native/platformLibs/src/platform/mingw/posix.def @@ -0,0 +1,95 @@ +package = platform.posix +headers = assert.h complex.h ctype.h dirent.h errno.h fcntl.h \ + fenv.h float.h ftw.h getopt.h inttypes.h libgen.h limits.h \ + locale.h math.h memory.h pthread.h sched.h search.h semaphore.h \ + setjmp.h signal.h stdint.h stdio.h stdlib.h string.h \ + time.h uchar.h unistd.h utime.h wchar.h wctype.h +noStringConversion = send sendto recv +compilerOpts = -DUNICODE -DWINVER=0x0601 -D_WIN32_WINNT=0x0601 -DWINAPI_FAMILY=3 -DOEMRESOURCE -D_POSIX_C_SOURCE=1 +linkerOpts = -lWs2_32 + +--- +// Wrapper to access errno variable. +static int posix_errno() { + return errno; +} + +static void set_posix_errno(int value) { + errno = value; +} + +static short posix_htons(short x) { + return htons(x); +} + +// Hacks to make MinGW Windows headers look more modular than they are. +#ifdef _WIN64 +#define UINT_PTR unsigned __int64 +#define ULONG_PTR unsigned __int64 +#else +#define UINT_PTR unsigned int +#define ULONG_PTR unsigned long +#endif +#define DWORD_PTR ULONG_PTR +#define BYTE unsigned char +#define WORD unsigned short +#define DWORD unsigned __LONG32 +#define ULONG DWORD +#define INT int +#define UINT unsigned int +#define CHAR char +#define WCHAR WORD +#define LPBYTE BYTE* +#define LPINT INT* +#define LPWORD WORD* +#define LPLONG __LONG32* +#define LPDWORD DWORD* +#define LPTSTR WCHAR* +#define VOID void +#define PVOID void* +#define LPVOID void* +#define LPSTR CHAR* +#define LPWSTR WCHAR* +#define WINBOOL int +#define WPARAM UINT_PTR +#define HANDLE LPVOID +#define LPHANDLE HANDLE* +#define HWND HANDLE +#define FARPROC void* +#define WINAPI __stdcall +#define CALLBACK __stdcall +#define PASCAL __pascal + +#define _INC_WINDOWS +#define RPC_NO_WINDOWS_H +#define COM_NO_WINDOWS_H +#define __INSIDE_CYGWIN__ +#include + +// Wrapper to access h_errno variable. +static int posix_h_errno() { + return h_errno; +} + +static int init_sockets() { + WORD wVersionRequested = 0x202; + WSADATA wsaData; + return WSAStartup(wVersionRequested, &wsaData); +} + +static void deinit_sockets() { + WSACleanup(); + return; +} + +static void posix_FD_ZERO(fd_set *set) { + FD_ZERO(set); +} + +static void posix_FD_SET(int bit, fd_set *set) { + FD_SET(bit, set); +} + +static int posix_FD_ISSET(int bit, fd_set *set) { + return FD_ISSET(bit, set); +} diff --git a/kotlin-native/platformLibs/src/platform/mingw/windows.def b/kotlin-native/platformLibs/src/platform/mingw/windows.def new file mode 100644 index 00000000000..07e3b8c3eaa --- /dev/null +++ b/kotlin-native/platformLibs/src/platform/mingw/windows.def @@ -0,0 +1,8 @@ +package = platform.windows +headers = wtypes.h minwindef.h windows.h commctrl.h dwmapi.h shlobj.h shlwapi.h shobjidl.h \ + urlmon.h usp10.h uxtheme.h vfw.h wininet.h winsock2.h ws2tcpip.h ws2def.h +compilerOpts = -DUNICODE -DWINVER=0x0601 -D_WIN32_WINNT=0x0601 -DWINAPI_FAMILY=3 -DOEMRESOURCE \ + -Wno-incompatible-pointer-types -Wno-deprecated-declarations +linkerOpts = -lcomctl32 -lcrypt32 -lshlwapi -lshell32 -limm32 -lusp10 -lwininet -lgdi32 -luser32 -lkernel32 -lbcrypt -luuid +noStringConversion = LoadCursorA LoadBitmapA LoadIconA LoadImageA LoadCursorW LoadBitmapW LoadIconW LoadImageW +depends = posix diff --git a/kotlin-native/platformLibs/src/platform/mingw/zlib.def b/kotlin-native/platformLibs/src/platform/mingw/zlib.def new file mode 100644 index 00000000000..cdc1db7fc00 --- /dev/null +++ b/kotlin-native/platformLibs/src/platform/mingw/zlib.def @@ -0,0 +1,34 @@ +depends = posix +package = platform.zlib +headers = zconf.h zlib.h +headerFilter = zlib.h +compilerOpts = -DByte=uByte -DBytef=uBytef +linkerOpts = -Wl,-Bstatic -lz -Wl,-Bdynamic + +--- +#undef deflateInit +static inline int deflateInit(z_streamp strm, int level) { + return deflateInit_(strm, level, ZLIB_VERSION, (int)sizeof(z_stream)); +} + +#undef deflateInit2 +static inline int deflateInit2(z_streamp strm, int level, int method, + int windowBits, int memLevel, int strategy) { + return deflateInit2_(strm, level, method, windowBits, memLevel, + strategy, ZLIB_VERSION, (int)sizeof(z_stream)); +} + +#undef inflateInit +static inline int inflateInit(z_streamp strm) { + return inflateInit_(strm, ZLIB_VERSION, (int)sizeof(z_stream)); +} + +#undef inflateInit2 +static inline int inflateInit2(z_streamp strm, int windowBits) { + return inflateInit2_(strm, windowBits, ZLIB_VERSION, (int)sizeof(z_stream)); +} + +#undef inflateBackInit +static inline int inflateBackInit(z_streamp strm, int windowBits, unsigned char *window) { + return inflateBackInit_(strm, windowBits, window, ZLIB_VERSION, (int)sizeof(z_stream)); +} diff --git a/kotlin-native/platformLibs/src/platform/osx/AGL.def.disabled b/kotlin-native/platformLibs/src/platform/osx/AGL.def.disabled new file mode 100644 index 00000000000..2b603e89507 --- /dev/null +++ b/kotlin-native/platformLibs/src/platform/osx/AGL.def.disabled @@ -0,0 +1,6 @@ +language = Objective-C +package = platform.AGL +modules = AGL +compilerOpts = -framework AGL +linkerOpts = -framework AGL +#Disabled: Deprecated. diff --git a/kotlin-native/platformLibs/src/platform/osx/AVFoundation.def b/kotlin-native/platformLibs/src/platform/osx/AVFoundation.def new file mode 100644 index 00000000000..0830fea53a2 --- /dev/null +++ b/kotlin-native/platformLibs/src/platform/osx/AVFoundation.def @@ -0,0 +1,7 @@ +depends = ApplicationServices AudioToolbox CFNetwork CoreAudio CoreAudioTypes CoreFoundation CoreGraphics CoreImage CoreMIDI CoreMedia CoreServices CoreText CoreVideo DiskArbitration Foundation IOKit IOSurface ImageIO MediaToolbox Metal OpenGLCommon QuartzCore Security darwin libkern osx posix +language = Objective-C +package = platform.AVFoundation +modules = AVFoundation + +compilerOpts = -framework AVFoundation +linkerOpts = -framework AVFoundation diff --git a/kotlin-native/platformLibs/src/platform/osx/AVKit.def b/kotlin-native/platformLibs/src/platform/osx/AVKit.def new file mode 100644 index 00000000000..6a61c34355e --- /dev/null +++ b/kotlin-native/platformLibs/src/platform/osx/AVKit.def @@ -0,0 +1,7 @@ +depends = AVFoundation AppKit ApplicationServices AudioToolbox CFNetwork Cocoa CoreAudio CoreAudioTypes CoreData CoreFoundation CoreGraphics CoreImage CoreMIDI CoreMedia CoreServices CoreText CoreVideo DiskArbitration Foundation IOKit IOSurface ImageIO MediaToolbox Metal OpenGLCommon QuartzCore Security darwin libkern osx posix +language = Objective-C +package = platform.AVKit +modules = AVKit + +compilerOpts = -framework AVKit +linkerOpts = -framework AVKit diff --git a/kotlin-native/platformLibs/src/platform/osx/Accelerate.def b/kotlin-native/platformLibs/src/platform/osx/Accelerate.def new file mode 100644 index 00000000000..c8a3afdcffd --- /dev/null +++ b/kotlin-native/platformLibs/src/platform/osx/Accelerate.def @@ -0,0 +1,7 @@ +depends = ApplicationServices CFNetwork CoreFoundation CoreGraphics CoreServices CoreText CoreVideo DiskArbitration IOKit IOSurface ImageIO Security darwin libkern osx posix +language = Objective-C +package = platform.Accelerate +modules = Accelerate + +compilerOpts = -framework Accelerate +linkerOpts = -framework Accelerate diff --git a/kotlin-native/platformLibs/src/platform/osx/Accounts.def b/kotlin-native/platformLibs/src/platform/osx/Accounts.def new file mode 100644 index 00000000000..91cd571f7d8 --- /dev/null +++ b/kotlin-native/platformLibs/src/platform/osx/Accounts.def @@ -0,0 +1,7 @@ +depends = ApplicationServices CFNetwork CoreFoundation CoreGraphics CoreServices CoreText DiskArbitration Foundation IOKit ImageIO Security darwin libkern osx posix +language = Objective-C +package = platform.Accounts +modules = Accounts + +compilerOpts = -framework Accounts +linkerOpts = -framework Accounts diff --git a/kotlin-native/platformLibs/src/platform/osx/AdSupport.def b/kotlin-native/platformLibs/src/platform/osx/AdSupport.def new file mode 100644 index 00000000000..d9a3f58d940 --- /dev/null +++ b/kotlin-native/platformLibs/src/platform/osx/AdSupport.def @@ -0,0 +1,7 @@ +depends = ApplicationServices CFNetwork CoreFoundation CoreGraphics CoreServices CoreText DiskArbitration Foundation IOKit ImageIO Security darwin libkern osx posix +language = Objective-C +package = platform.AdSupport +modules = AdSupport + +compilerOpts = -framework AdSupport +linkerOpts = -framework AdSupport diff --git a/kotlin-native/platformLibs/src/platform/osx/AddressBook.def b/kotlin-native/platformLibs/src/platform/osx/AddressBook.def new file mode 100644 index 00000000000..2523e710caa --- /dev/null +++ b/kotlin-native/platformLibs/src/platform/osx/AddressBook.def @@ -0,0 +1,9 @@ +depends = AppKit ApplicationServices CFNetwork Cocoa CoreData CoreFoundation CoreGraphics CoreImage CoreServices CoreText CoreVideo DiskArbitration Foundation IOKit IOSurface ImageIO Metal OpenGLCommon QuartzCore Security darwin libkern osx posix +language = Objective-C +package = platform.AddressBook +headers = AddressBook/AddressBook.h AddressBook/AddressBookUI.h AddressBook/ABActions.h AddressBook/ABPeoplePickerView.h AddressBook/ABPersonView.h AddressBook/ABPersonPicker.h AddressBook/ABPersonPickerDelegate.h + +headerFilter = AddressBook/** + +compilerOpts = -framework AddressBook +linkerOpts = -framework AddressBook diff --git a/kotlin-native/platformLibs/src/platform/osx/AppKit.def b/kotlin-native/platformLibs/src/platform/osx/AppKit.def new file mode 100644 index 00000000000..f13658a26fe --- /dev/null +++ b/kotlin-native/platformLibs/src/platform/osx/AppKit.def @@ -0,0 +1,7 @@ +depends = ApplicationServices CFNetwork CoreData CoreFoundation CoreGraphics CoreImage CoreServices CoreText CoreVideo DiskArbitration Foundation IOKit IOSurface ImageIO Metal OpenGLCommon QuartzCore Security darwin libkern osx posix +language = Objective-C +package = platform.AppKit +modules = AppKit + +compilerOpts = -framework AppKit +linkerOpts = -framework AppKit diff --git a/kotlin-native/platformLibs/src/platform/osx/AppleScriptKit.def.disabled b/kotlin-native/platformLibs/src/platform/osx/AppleScriptKit.def.disabled new file mode 100644 index 00000000000..5970038a4f7 --- /dev/null +++ b/kotlin-native/platformLibs/src/platform/osx/AppleScriptKit.def.disabled @@ -0,0 +1,6 @@ +language = Objective-C +package = platform.AppleScriptKit +modules = AppleScriptKit +compilerOpts = -framework AppleScriptKit +linkerOpts = -framework AppleScriptKit +#Disabled: Unavailable diff --git a/kotlin-native/platformLibs/src/platform/osx/AppleScriptObjC.def.disabled b/kotlin-native/platformLibs/src/platform/osx/AppleScriptObjC.def.disabled new file mode 100644 index 00000000000..5256b1df0fe --- /dev/null +++ b/kotlin-native/platformLibs/src/platform/osx/AppleScriptObjC.def.disabled @@ -0,0 +1,6 @@ +language = Objective-C +package = platform.AppleScriptObjC +modules = AppleScriptObjC +compilerOpts = -framework AppleScriptObjC +linkerOpts = -framework AppleScriptObjC +#Disabled: Unavailable diff --git a/kotlin-native/platformLibs/src/platform/osx/ApplicationServices.def b/kotlin-native/platformLibs/src/platform/osx/ApplicationServices.def new file mode 100644 index 00000000000..21a01015e98 --- /dev/null +++ b/kotlin-native/platformLibs/src/platform/osx/ApplicationServices.def @@ -0,0 +1,9 @@ +depends = CFNetwork CoreFoundation CoreGraphics CoreServices CoreText DiskArbitration IOKit ImageIO Security darwin libkern osx posix +language = Objective-C +package = platform.ApplicationServices +modules = ApplicationServices ColorSync + +excludedFunctions = kSpeechSynthesizerInfoManufacturer + +compilerOpts = -framework ApplicationServices +linkerOpts = -framework ApplicationServices diff --git a/kotlin-native/platformLibs/src/platform/osx/AudioToolbox.def b/kotlin-native/platformLibs/src/platform/osx/AudioToolbox.def new file mode 100644 index 00000000000..c8107234d9f --- /dev/null +++ b/kotlin-native/platformLibs/src/platform/osx/AudioToolbox.def @@ -0,0 +1,9 @@ +depends = ApplicationServices CFNetwork CoreAudio CoreAudioTypes CoreFoundation CoreGraphics CoreMIDI CoreServices CoreText DiskArbitration Foundation IOKit ImageIO Security darwin libkern osx posix +language = Objective-C +package = platform.AudioToolbox +headers = AudioToolbox/AudioToolbox.h AudioToolbox/DefaultAudioOutput.h AudioToolbox/AUCocoaUIView.h + +headerFilter = AudioToolbox/** + +compilerOpts = -framework AudioToolbox +linkerOpts = -framework AudioToolbox diff --git a/kotlin-native/platformLibs/src/platform/osx/AudioUnit.def b/kotlin-native/platformLibs/src/platform/osx/AudioUnit.def new file mode 100644 index 00000000000..5ef17bdaa15 --- /dev/null +++ b/kotlin-native/platformLibs/src/platform/osx/AudioUnit.def @@ -0,0 +1,9 @@ +depends = ApplicationServices AudioToolbox CFNetwork CoreAudioTypes CoreFoundation CoreGraphics CoreServices CoreText DiskArbitration Foundation IOKit ImageIO Security darwin libkern osx posix +language = Objective-C +package = platform.AudioUnit +headers = AudioUnit/AudioUnit.h + +headerFilter = AudioUnit/** + +compilerOpts = -framework AudioUnit +linkerOpts = -framework AudioUnit diff --git a/kotlin-native/platformLibs/src/platform/osx/AudioVideoBridging.def.disabled b/kotlin-native/platformLibs/src/platform/osx/AudioVideoBridging.def.disabled new file mode 100644 index 00000000000..6452f8342ca --- /dev/null +++ b/kotlin-native/platformLibs/src/platform/osx/AudioVideoBridging.def.disabled @@ -0,0 +1,6 @@ +language = Objective-C +package = platform.AudioVideoBridging +modules = AudioVideoBridging +compilerOpts = -framework AudioVideoBridging +linkerOpts = -framework AudioVideoBridging +#Disabled: Unavailable diff --git a/kotlin-native/platformLibs/src/platform/osx/AuthenticationServices.def b/kotlin-native/platformLibs/src/platform/osx/AuthenticationServices.def new file mode 100644 index 00000000000..005b626f06d --- /dev/null +++ b/kotlin-native/platformLibs/src/platform/osx/AuthenticationServices.def @@ -0,0 +1,7 @@ +depends = AppKit ApplicationServices CFNetwork CoreData CoreFoundation CoreGraphics CoreImage CoreServices CoreText CoreVideo DiskArbitration Foundation IOKit IOSurface ImageIO Metal OpenGLCommon QuartzCore Security darwin libkern osx posix +language = Objective-C +package = platform.AuthenticationServices +modules = AuthenticationServices + +compilerOpts = -framework AuthenticationServices +linkerOpts = -framework AuthenticationServices diff --git a/kotlin-native/platformLibs/src/platform/osx/AutomaticAssessmentConfiguration.def b/kotlin-native/platformLibs/src/platform/osx/AutomaticAssessmentConfiguration.def new file mode 100644 index 00000000000..47a5e3d66a3 --- /dev/null +++ b/kotlin-native/platformLibs/src/platform/osx/AutomaticAssessmentConfiguration.def @@ -0,0 +1,7 @@ +depends = ApplicationServices CFNetwork CoreFoundation CoreGraphics CoreServices CoreText DiskArbitration Foundation IOKit ImageIO Security darwin libkern osx posix +language = Objective-C +package = platform.AutomaticAssessmentConfiguration +modules = AutomaticAssessmentConfiguration + +compilerOpts = -framework AutomaticAssessmentConfiguration +linkerOpts = -framework AutomaticAssessmentConfiguration diff --git a/kotlin-native/platformLibs/src/platform/osx/Automator.def.disabled b/kotlin-native/platformLibs/src/platform/osx/Automator.def.disabled new file mode 100644 index 00000000000..faf949b9f93 --- /dev/null +++ b/kotlin-native/platformLibs/src/platform/osx/Automator.def.disabled @@ -0,0 +1,6 @@ +language = Objective-C +package = platform.Automator +modules = Automator +compilerOpts = -framework Automator +linkerOpts = -framework Automator +#Disabled: depends on Carbon. \ No newline at end of file diff --git a/kotlin-native/platformLibs/src/platform/osx/BackgroundTasks.def b/kotlin-native/platformLibs/src/platform/osx/BackgroundTasks.def new file mode 100644 index 00000000000..14450317b7b --- /dev/null +++ b/kotlin-native/platformLibs/src/platform/osx/BackgroundTasks.def @@ -0,0 +1,7 @@ +depends = ApplicationServices CFNetwork CoreFoundation CoreGraphics CoreServices CoreText DiskArbitration Foundation IOKit ImageIO Security darwin libkern osx posix +language = Objective-C +package = platform.BackgroundTasks +modules = BackgroundTasks + +compilerOpts = -framework BackgroundTasks +linkerOpts = -framework BackgroundTasks diff --git a/kotlin-native/platformLibs/src/platform/osx/BusinessChat.def b/kotlin-native/platformLibs/src/platform/osx/BusinessChat.def new file mode 100644 index 00000000000..45c9ee0938d --- /dev/null +++ b/kotlin-native/platformLibs/src/platform/osx/BusinessChat.def @@ -0,0 +1,7 @@ +depends = AppKit ApplicationServices CFNetwork Cocoa CoreData CoreFoundation CoreGraphics CoreImage CoreServices CoreText CoreVideo DiskArbitration Foundation IOKit IOSurface ImageIO Metal OpenGLCommon QuartzCore Security darwin libkern osx posix +language = Objective-C +package = platform.BusinessChat +modules = BusinessChat + +compilerOpts = -framework BusinessChat +linkerOpts = -framework BusinessChat diff --git a/kotlin-native/platformLibs/src/platform/osx/CFNetwork.def b/kotlin-native/platformLibs/src/platform/osx/CFNetwork.def new file mode 100644 index 00000000000..6394e2e2d50 --- /dev/null +++ b/kotlin-native/platformLibs/src/platform/osx/CFNetwork.def @@ -0,0 +1,10 @@ +depends = CoreFoundation darwin posix +language = Objective-C +package = platform.CFNetwork +modules = CFNetwork + +excludedFunctions = kCFHTTPAuthenticationSchemeKerberos kCFHTTPAuthenticationSchemeOAuth1 kCFNetworkProxiesProxyAutoConfigJavaScript kCFProxyAutoConfigurationHTTPResponseKey + + +compilerOpts = -framework CFNetwork +linkerOpts = -framework CFNetwork diff --git a/kotlin-native/platformLibs/src/platform/osx/CalendarStore.def.disabled b/kotlin-native/platformLibs/src/platform/osx/CalendarStore.def.disabled new file mode 100644 index 00000000000..0b9f6a59057 --- /dev/null +++ b/kotlin-native/platformLibs/src/platform/osx/CalendarStore.def.disabled @@ -0,0 +1,6 @@ +language = Objective-C +package = platform.CalendarStore +modules = CalendarStore +compilerOpts = -framework CalendarStore +linkerOpts = -framework CalendarStore +#Disabled: Unavailable diff --git a/kotlin-native/platformLibs/src/platform/osx/CallKit.def b/kotlin-native/platformLibs/src/platform/osx/CallKit.def new file mode 100644 index 00000000000..8684db2e784 --- /dev/null +++ b/kotlin-native/platformLibs/src/platform/osx/CallKit.def @@ -0,0 +1,7 @@ +depends = ApplicationServices CFNetwork CoreFoundation CoreGraphics CoreServices CoreText DiskArbitration Foundation IOKit ImageIO Security darwin libkern osx posix +language = Objective-C +package = platform.CallKit +modules = CallKit + +compilerOpts = -framework CallKit +linkerOpts = -framework CallKit diff --git a/kotlin-native/platformLibs/src/platform/osx/Carbon.def.disabled b/kotlin-native/platformLibs/src/platform/osx/Carbon.def.disabled new file mode 100644 index 00000000000..1709f7ef5e5 --- /dev/null +++ b/kotlin-native/platformLibs/src/platform/osx/Carbon.def.disabled @@ -0,0 +1,6 @@ +language = Objective-C +package = platform.Carbon +modules = Carbon +compilerOpts = -framework Carbon +linkerOpts = -framework Carbon +#Disabled: Unavailable diff --git a/kotlin-native/platformLibs/src/platform/osx/CloudKit.def b/kotlin-native/platformLibs/src/platform/osx/CloudKit.def new file mode 100644 index 00000000000..8048f4bcdec --- /dev/null +++ b/kotlin-native/platformLibs/src/platform/osx/CloudKit.def @@ -0,0 +1,7 @@ +depends = ApplicationServices CFNetwork CoreFoundation CoreGraphics CoreLocation CoreServices CoreText DiskArbitration Foundation IOKit ImageIO Security darwin libkern osx posix +language = Objective-C +package = platform.CloudKit +modules = CloudKit + +compilerOpts = -framework CloudKit +linkerOpts = -framework CloudKit diff --git a/kotlin-native/platformLibs/src/platform/osx/Cocoa.def b/kotlin-native/platformLibs/src/platform/osx/Cocoa.def new file mode 100644 index 00000000000..913952497d8 --- /dev/null +++ b/kotlin-native/platformLibs/src/platform/osx/Cocoa.def @@ -0,0 +1,7 @@ +depends = AppKit ApplicationServices CFNetwork CoreData CoreFoundation CoreGraphics CoreImage CoreServices CoreText CoreVideo DiskArbitration Foundation IOKit IOSurface ImageIO Metal OpenGLCommon QuartzCore Security darwin libkern osx posix +language = Objective-C +package = platform.Cocoa +modules = Cocoa + +compilerOpts = -framework Cocoa +linkerOpts = -framework Cocoa diff --git a/kotlin-native/platformLibs/src/platform/osx/Collaboration.def b/kotlin-native/platformLibs/src/platform/osx/Collaboration.def new file mode 100644 index 00000000000..309be12b095 --- /dev/null +++ b/kotlin-native/platformLibs/src/platform/osx/Collaboration.def @@ -0,0 +1,7 @@ +depends = AppKit ApplicationServices CFNetwork CoreData CoreFoundation CoreGraphics CoreImage CoreServices CoreText CoreVideo DiskArbitration Foundation IOKit IOSurface ImageIO Metal OpenGLCommon QuartzCore Security darwin libkern osx posix +language = Objective-C +package = platform.Collaboration +modules = Collaboration + +compilerOpts = -framework Collaboration +linkerOpts = -framework Collaboration diff --git a/kotlin-native/platformLibs/src/platform/osx/ColorSync.def.disabled b/kotlin-native/platformLibs/src/platform/osx/ColorSync.def.disabled new file mode 100644 index 00000000000..b44690d4939 --- /dev/null +++ b/kotlin-native/platformLibs/src/platform/osx/ColorSync.def.disabled @@ -0,0 +1,7 @@ +depends = CoreFoundation darwin posix +language = Objective-C +package = platform.ColorSync +modules = ColorSync +compilerOpts = -framework ColorSync +linkerOpts = -framework ColorSync +#Disabled: ColorSync is a part of ApplicationServices framework. \ No newline at end of file diff --git a/kotlin-native/platformLibs/src/platform/osx/Combine.def.disabled b/kotlin-native/platformLibs/src/platform/osx/Combine.def.disabled new file mode 100644 index 00000000000..0fde0deb560 --- /dev/null +++ b/kotlin-native/platformLibs/src/platform/osx/Combine.def.disabled @@ -0,0 +1,6 @@ +language = Objective-C +package = platform.Combine +modules = Combine +compilerOpts = -framework Combine +linkerOpts = -framework Combine +#Disabled: Swift-only framework diff --git a/kotlin-native/platformLibs/src/platform/osx/CommonCrypto.def b/kotlin-native/platformLibs/src/platform/osx/CommonCrypto.def new file mode 100644 index 00000000000..92ce70f00ae --- /dev/null +++ b/kotlin-native/platformLibs/src/platform/osx/CommonCrypto.def @@ -0,0 +1,6 @@ +depends = darwin posix +language = Objective-C +package = platform.CoreCrypto +modules = CommonCrypto + +compilerOpts = -D_XOPEN_SOURCE diff --git a/kotlin-native/platformLibs/src/platform/osx/Contacts.def b/kotlin-native/platformLibs/src/platform/osx/Contacts.def new file mode 100644 index 00000000000..556c923ddb4 --- /dev/null +++ b/kotlin-native/platformLibs/src/platform/osx/Contacts.def @@ -0,0 +1,7 @@ +depends = ApplicationServices CFNetwork CoreFoundation CoreGraphics CoreServices CoreText DiskArbitration Foundation IOKit ImageIO Security darwin libkern osx posix +language = Objective-C +package = platform.Contacts +modules = Contacts + +compilerOpts = -framework Contacts +linkerOpts = -framework Contacts diff --git a/kotlin-native/platformLibs/src/platform/osx/ContactsUI.def b/kotlin-native/platformLibs/src/platform/osx/ContactsUI.def new file mode 100644 index 00000000000..de91c6f0bef --- /dev/null +++ b/kotlin-native/platformLibs/src/platform/osx/ContactsUI.def @@ -0,0 +1,7 @@ +depends = AppKit ApplicationServices CFNetwork CoreData CoreFoundation CoreGraphics CoreImage CoreServices CoreText CoreVideo DiskArbitration Foundation IOKit IOSurface ImageIO Metal OpenGLCommon QuartzCore Security darwin libkern osx posix +language = Objective-C +package = platform.ContactsUI +modules = ContactsUI + +compilerOpts = -framework ContactsUI +linkerOpts = -framework ContactsUI diff --git a/kotlin-native/platformLibs/src/platform/osx/CoreAudio.def b/kotlin-native/platformLibs/src/platform/osx/CoreAudio.def new file mode 100644 index 00000000000..057ef32143a --- /dev/null +++ b/kotlin-native/platformLibs/src/platform/osx/CoreAudio.def @@ -0,0 +1,9 @@ +depends = CoreAudioTypes CoreFoundation darwin posix +language = Objective-C +package = platform.CoreAudio +headers = CoreAudio/CoreAudio.h CoreAudio/CoreAudioTypes.h CoreAudio/AudioServerPlugIn.h CoreAudio/AudioHardware.h + +headerFilter = CoreAudio/** + +compilerOpts = -framework CoreAudio +linkerOpts = -framework CoreAudio diff --git a/kotlin-native/platformLibs/src/platform/osx/CoreAudioKit.def b/kotlin-native/platformLibs/src/platform/osx/CoreAudioKit.def new file mode 100644 index 00000000000..c6a59c16bbb --- /dev/null +++ b/kotlin-native/platformLibs/src/platform/osx/CoreAudioKit.def @@ -0,0 +1,7 @@ +depends = AppKit ApplicationServices AudioToolbox AudioUnit CFNetwork Cocoa CoreAudioTypes CoreData CoreFoundation CoreGraphics CoreImage CoreServices CoreText CoreVideo DiskArbitration Foundation IOKit IOSurface ImageIO Metal OpenGLCommon QuartzCore Security darwin libkern osx posix +language = Objective-C +package = platform.CoreAudioKit +modules = CoreAudioKit + +compilerOpts = -framework CoreAudioKit +linkerOpts = -framework CoreAudioKit diff --git a/kotlin-native/platformLibs/src/platform/osx/CoreAudioTypes.def b/kotlin-native/platformLibs/src/platform/osx/CoreAudioTypes.def new file mode 100644 index 00000000000..2c8891b94d1 --- /dev/null +++ b/kotlin-native/platformLibs/src/platform/osx/CoreAudioTypes.def @@ -0,0 +1,6 @@ +depends = CoreFoundation darwin posix +language = Objective-C +package = platform.CoreAudioTypes +modules = CoreAudioTypes + +compilerOpts = -framework CoreAudioTypes diff --git a/kotlin-native/platformLibs/src/platform/osx/CoreBluetooth.def b/kotlin-native/platformLibs/src/platform/osx/CoreBluetooth.def new file mode 100644 index 00000000000..8dde346166f --- /dev/null +++ b/kotlin-native/platformLibs/src/platform/osx/CoreBluetooth.def @@ -0,0 +1,7 @@ +depends = ApplicationServices CFNetwork CoreFoundation CoreGraphics CoreServices CoreText DiskArbitration Foundation IOKit ImageIO Security darwin libkern osx posix +language = Objective-C +package = platform.CoreBluetooth +modules = CoreBluetooth + +compilerOpts = -framework CoreBluetooth +linkerOpts = -framework CoreBluetooth diff --git a/kotlin-native/platformLibs/src/platform/osx/CoreData.def b/kotlin-native/platformLibs/src/platform/osx/CoreData.def new file mode 100644 index 00000000000..73d2d7d16ec --- /dev/null +++ b/kotlin-native/platformLibs/src/platform/osx/CoreData.def @@ -0,0 +1,7 @@ +depends = ApplicationServices CFNetwork CoreFoundation CoreGraphics CoreServices CoreText DiskArbitration Foundation IOKit ImageIO Security darwin libkern osx posix +language = Objective-C +package = platform.CoreData +modules = CoreData + +compilerOpts = -framework CoreData +linkerOpts = -framework CoreData diff --git a/kotlin-native/platformLibs/src/platform/osx/CoreDisplay.def.disabled b/kotlin-native/platformLibs/src/platform/osx/CoreDisplay.def.disabled new file mode 100644 index 00000000000..7cde6711a82 --- /dev/null +++ b/kotlin-native/platformLibs/src/platform/osx/CoreDisplay.def.disabled @@ -0,0 +1,6 @@ +language = Objective-C +package = platform.CoreDisplay +modules = CoreDisplay +compilerOpts = -framework CoreDisplay +linkerOpts = -framework CoreDisplay +#Disabled: Unavailable diff --git a/kotlin-native/platformLibs/src/platform/osx/CoreFoundation.def b/kotlin-native/platformLibs/src/platform/osx/CoreFoundation.def new file mode 100644 index 00000000000..17c65eafa38 --- /dev/null +++ b/kotlin-native/platformLibs/src/platform/osx/CoreFoundation.def @@ -0,0 +1,7 @@ +depends = darwin posix +language = Objective-C +package = platform.CoreFoundation +modules = CoreFoundation + +compilerOpts = -framework CoreFoundation +linkerOpts = -framework CoreFoundation diff --git a/kotlin-native/platformLibs/src/platform/osx/CoreGraphics.def b/kotlin-native/platformLibs/src/platform/osx/CoreGraphics.def new file mode 100644 index 00000000000..73299585ec4 --- /dev/null +++ b/kotlin-native/platformLibs/src/platform/osx/CoreGraphics.def @@ -0,0 +1,7 @@ +depends = CoreFoundation IOKit darwin libkern posix +language = Objective-C +package = platform.CoreGraphics +modules = CoreGraphics + +compilerOpts = -framework CoreGraphics +linkerOpts = -framework CoreGraphics diff --git a/kotlin-native/platformLibs/src/platform/osx/CoreHaptics.def b/kotlin-native/platformLibs/src/platform/osx/CoreHaptics.def new file mode 100644 index 00000000000..a2fd2fa6bf1 --- /dev/null +++ b/kotlin-native/platformLibs/src/platform/osx/CoreHaptics.def @@ -0,0 +1,7 @@ +depends = CoreFoundation Foundation darwin posix +language = Objective-C +package = platform.CoreHaptics +modules = CoreHaptics + +compilerOpts = -framework CoreHaptics +linkerOpts = -framework CoreHaptics diff --git a/kotlin-native/platformLibs/src/platform/osx/CoreImage.def b/kotlin-native/platformLibs/src/platform/osx/CoreImage.def new file mode 100644 index 00000000000..7e8517bc90b --- /dev/null +++ b/kotlin-native/platformLibs/src/platform/osx/CoreImage.def @@ -0,0 +1,7 @@ +depends = ApplicationServices CFNetwork CoreFoundation CoreGraphics CoreServices CoreText CoreVideo DiskArbitration Foundation IOKit IOSurface ImageIO Metal OpenGLCommon Security darwin libkern osx posix +language = Objective-C +package = platform.CoreImage +modules = CoreImage + +compilerOpts = -framework CoreImage +linkerOpts = -framework CoreImage diff --git a/kotlin-native/platformLibs/src/platform/osx/CoreLocation.def b/kotlin-native/platformLibs/src/platform/osx/CoreLocation.def new file mode 100644 index 00000000000..38255a3abf4 --- /dev/null +++ b/kotlin-native/platformLibs/src/platform/osx/CoreLocation.def @@ -0,0 +1,7 @@ +depends = ApplicationServices CFNetwork CoreFoundation CoreGraphics CoreServices CoreText DiskArbitration Foundation IOKit ImageIO Security darwin libkern osx posix +language = Objective-C +package = platform.CoreLocation +modules = CoreLocation + +compilerOpts = -framework CoreLocation +linkerOpts = -framework CoreLocation diff --git a/kotlin-native/platformLibs/src/platform/osx/CoreMIDI.def b/kotlin-native/platformLibs/src/platform/osx/CoreMIDI.def new file mode 100644 index 00000000000..c8d19fa0116 --- /dev/null +++ b/kotlin-native/platformLibs/src/platform/osx/CoreMIDI.def @@ -0,0 +1,7 @@ +depends = ApplicationServices CFNetwork CoreFoundation CoreGraphics CoreServices CoreText DiskArbitration Foundation IOKit ImageIO Security darwin libkern osx posix +language = Objective-C +package = platform.CoreMIDI +modules = CoreMIDI + +compilerOpts = -framework CoreMIDI +linkerOpts = -framework CoreMIDI diff --git a/kotlin-native/platformLibs/src/platform/osx/CoreMIDIServer.def.disabled b/kotlin-native/platformLibs/src/platform/osx/CoreMIDIServer.def.disabled new file mode 100644 index 00000000000..460dae883cb --- /dev/null +++ b/kotlin-native/platformLibs/src/platform/osx/CoreMIDIServer.def.disabled @@ -0,0 +1,6 @@ +language = Objective-C +package = platform.CoreMIDIServer +modules = CoreMIDIServer +compilerOpts = -framework CoreMIDIServer +linkerOpts = -framework CoreMIDIServer +#Disabled: Unavailable diff --git a/kotlin-native/platformLibs/src/platform/osx/CoreML.def b/kotlin-native/platformLibs/src/platform/osx/CoreML.def new file mode 100644 index 00000000000..044275eaf98 --- /dev/null +++ b/kotlin-native/platformLibs/src/platform/osx/CoreML.def @@ -0,0 +1,7 @@ +depends = ApplicationServices CFNetwork CoreFoundation CoreGraphics CoreServices CoreText CoreVideo DiskArbitration Foundation IOKit IOSurface ImageIO Security darwin libkern osx posix +language = Objective-C +package = platform.CoreML +modules = CoreML + +compilerOpts = -framework CoreML +linkerOpts = -framework CoreML diff --git a/kotlin-native/platformLibs/src/platform/osx/CoreMedia.def b/kotlin-native/platformLibs/src/platform/osx/CoreMedia.def new file mode 100644 index 00000000000..1f739edf996 --- /dev/null +++ b/kotlin-native/platformLibs/src/platform/osx/CoreMedia.def @@ -0,0 +1,7 @@ +depends = ApplicationServices CFNetwork CoreAudio CoreAudioTypes CoreFoundation CoreGraphics CoreServices CoreText CoreVideo DiskArbitration Foundation IOKit IOSurface ImageIO Metal OpenGLCommon Security darwin libkern osx posix +language = Objective-C +package = platform.CoreMedia +modules = CoreMedia + +compilerOpts = -framework CoreMedia +linkerOpts = -framework CoreMedia diff --git a/kotlin-native/platformLibs/src/platform/osx/CoreMediaIO.def.disabled b/kotlin-native/platformLibs/src/platform/osx/CoreMediaIO.def.disabled new file mode 100644 index 00000000000..8a71baf1d4b --- /dev/null +++ b/kotlin-native/platformLibs/src/platform/osx/CoreMediaIO.def.disabled @@ -0,0 +1,6 @@ +language = Objective-C +package = platform.CoreMediaIO +modules = CoreMediaIO +compilerOpts = -framework CoreMediaIO +linkerOpts = -framework CoreMediaIO +#Disabled: Unavailable diff --git a/kotlin-native/platformLibs/src/platform/osx/CoreMotion.def b/kotlin-native/platformLibs/src/platform/osx/CoreMotion.def new file mode 100644 index 00000000000..d9f880f5012 --- /dev/null +++ b/kotlin-native/platformLibs/src/platform/osx/CoreMotion.def @@ -0,0 +1,7 @@ +depends = ApplicationServices CFNetwork CoreFoundation CoreGraphics CoreServices CoreText DiskArbitration Foundation IOKit ImageIO Security darwin libkern osx posix +language = Objective-C +package = platform.CoreMotion +modules = CoreMotion + +compilerOpts = -framework CoreMotion +linkerOpts = -framework CoreMotion diff --git a/kotlin-native/platformLibs/src/platform/osx/CoreServices.def b/kotlin-native/platformLibs/src/platform/osx/CoreServices.def new file mode 100644 index 00000000000..fb2a965aa5b --- /dev/null +++ b/kotlin-native/platformLibs/src/platform/osx/CoreServices.def @@ -0,0 +1,8 @@ +depends = CFNetwork CoreFoundation DiskArbitration IOKit Security darwin libkern osx posix +language = Objective-C +package = platform.CoreServices +modules = CoreServices + +excludedFunctions = MDItemCopyAttributeList MDQueryGetSortOptionFlagsForAttribute +compilerOpts = -framework CoreServices +linkerOpts = -framework CoreServices diff --git a/kotlin-native/platformLibs/src/platform/osx/CoreSpotlight.def b/kotlin-native/platformLibs/src/platform/osx/CoreSpotlight.def new file mode 100644 index 00000000000..f1e47f23204 --- /dev/null +++ b/kotlin-native/platformLibs/src/platform/osx/CoreSpotlight.def @@ -0,0 +1,7 @@ +depends = ApplicationServices CFNetwork CoreFoundation CoreGraphics CoreServices CoreText DiskArbitration Foundation IOKit ImageIO Security darwin libkern osx posix +language = Objective-C +package = platform.CoreSpotlight +modules = CoreSpotlight + +compilerOpts = -framework CoreSpotlight +linkerOpts = -framework CoreSpotlight diff --git a/kotlin-native/platformLibs/src/platform/osx/CoreTelephony.def b/kotlin-native/platformLibs/src/platform/osx/CoreTelephony.def new file mode 100644 index 00000000000..48de692bf51 --- /dev/null +++ b/kotlin-native/platformLibs/src/platform/osx/CoreTelephony.def @@ -0,0 +1,7 @@ +depends = posix +language = Objective-C +package = platform.CoreTelephony +modules = CoreTelephony + +compilerOpts = -framework CoreTelephony +linkerOpts = -framework CoreTelephony diff --git a/kotlin-native/platformLibs/src/platform/osx/CoreText.def b/kotlin-native/platformLibs/src/platform/osx/CoreText.def new file mode 100644 index 00000000000..6f93c0460e1 --- /dev/null +++ b/kotlin-native/platformLibs/src/platform/osx/CoreText.def @@ -0,0 +1,7 @@ +depends = CoreFoundation CoreGraphics IOKit darwin libkern posix +language = Objective-C +package = platform.CoreText +modules = CoreText + +compilerOpts = -framework CoreText +linkerOpts = -framework CoreText diff --git a/kotlin-native/platformLibs/src/platform/osx/CoreVideo.def b/kotlin-native/platformLibs/src/platform/osx/CoreVideo.def new file mode 100644 index 00000000000..e079d777b42 --- /dev/null +++ b/kotlin-native/platformLibs/src/platform/osx/CoreVideo.def @@ -0,0 +1,7 @@ +depends = ApplicationServices CFNetwork CoreFoundation CoreGraphics CoreServices CoreText DiskArbitration Foundation IOKit IOSurface ImageIO Metal OpenGLCommon Security darwin libkern osx posix +language = Objective-C +package = platform.CoreVideo +modules = CoreVideo + +compilerOpts = -framework CoreVideo +linkerOpts = -framework CoreVideo diff --git a/kotlin-native/platformLibs/src/platform/osx/CoreWLAN.def b/kotlin-native/platformLibs/src/platform/osx/CoreWLAN.def new file mode 100644 index 00000000000..b77f191c470 --- /dev/null +++ b/kotlin-native/platformLibs/src/platform/osx/CoreWLAN.def @@ -0,0 +1,7 @@ +depends = ApplicationServices CFNetwork CoreFoundation CoreGraphics CoreServices CoreText DiskArbitration Foundation IOKit ImageIO Security darwin libkern osx posix +language = Objective-C +package = platform.CoreWLAN +modules = CoreWLAN + +compilerOpts = -framework CoreWLAN +linkerOpts = -framework CoreWLAN diff --git a/kotlin-native/platformLibs/src/platform/osx/CryptoKit.def.disabled b/kotlin-native/platformLibs/src/platform/osx/CryptoKit.def.disabled new file mode 100644 index 00000000000..1fd5943bf93 --- /dev/null +++ b/kotlin-native/platformLibs/src/platform/osx/CryptoKit.def.disabled @@ -0,0 +1,6 @@ +language = Objective-C +package = platform.CryptoKit +modules = CryptoKit +compilerOpts = -framework CryptoKit +linkerOpts = -framework CryptoKit +#Disabled: Swift-only framework diff --git a/kotlin-native/platformLibs/src/platform/osx/CryptoTokenKit.def b/kotlin-native/platformLibs/src/platform/osx/CryptoTokenKit.def new file mode 100644 index 00000000000..728b1f36137 --- /dev/null +++ b/kotlin-native/platformLibs/src/platform/osx/CryptoTokenKit.def @@ -0,0 +1,7 @@ +depends = ApplicationServices CFNetwork CoreFoundation CoreGraphics CoreServices CoreText DiskArbitration Foundation IOKit ImageIO Security darwin libkern osx posix +language = Objective-C +package = platform.CryptoTokenKit +modules = CryptoTokenKit + +compilerOpts = -framework CryptoTokenKit +linkerOpts = -framework CryptoTokenKit diff --git a/kotlin-native/platformLibs/src/platform/osx/DVDPlayback.def.disabled b/kotlin-native/platformLibs/src/platform/osx/DVDPlayback.def.disabled new file mode 100644 index 00000000000..05f98b6d94b --- /dev/null +++ b/kotlin-native/platformLibs/src/platform/osx/DVDPlayback.def.disabled @@ -0,0 +1,6 @@ +language = Objective-C +package = platform.DVDPlayback +modules = DVDPlayback +compilerOpts = -framework DVDPlayback +linkerOpts = -framework DVDPlayback +#Disabled: Unavailable diff --git a/kotlin-native/platformLibs/src/platform/osx/DeviceCheck.def b/kotlin-native/platformLibs/src/platform/osx/DeviceCheck.def new file mode 100644 index 00000000000..954e6a1462f --- /dev/null +++ b/kotlin-native/platformLibs/src/platform/osx/DeviceCheck.def @@ -0,0 +1,7 @@ +depends = ApplicationServices CFNetwork CoreFoundation CoreGraphics CoreServices CoreText DiskArbitration Foundation IOKit ImageIO Security darwin libkern osx posix +language = Objective-C +package = platform.DeviceCheck +modules = DeviceCheck + +compilerOpts = -framework DeviceCheck +linkerOpts = -framework DeviceCheck diff --git a/kotlin-native/platformLibs/src/platform/osx/DirectoryService.def.disabled b/kotlin-native/platformLibs/src/platform/osx/DirectoryService.def.disabled new file mode 100644 index 00000000000..cfb20d2609e --- /dev/null +++ b/kotlin-native/platformLibs/src/platform/osx/DirectoryService.def.disabled @@ -0,0 +1,6 @@ +language = Objective-C +package = platform.DirectoryService +modules = DirectoryService +compilerOpts = -framework DirectoryService +linkerOpts = -framework DirectoryService +#Disabled: Unavailable diff --git a/kotlin-native/platformLibs/src/platform/osx/DiscRecording.def.disabled b/kotlin-native/platformLibs/src/platform/osx/DiscRecording.def.disabled new file mode 100644 index 00000000000..824e75ead10 --- /dev/null +++ b/kotlin-native/platformLibs/src/platform/osx/DiscRecording.def.disabled @@ -0,0 +1,6 @@ +language = Objective-C +package = platform.DiscRecording +modules = DiscRecording +compilerOpts = -framework DiscRecording +linkerOpts = -framework DiscRecording +#Disabled: Unavailable diff --git a/kotlin-native/platformLibs/src/platform/osx/DiscRecordingUI.def.disabled b/kotlin-native/platformLibs/src/platform/osx/DiscRecordingUI.def.disabled new file mode 100644 index 00000000000..6259c7ba831 --- /dev/null +++ b/kotlin-native/platformLibs/src/platform/osx/DiscRecordingUI.def.disabled @@ -0,0 +1,6 @@ +language = Objective-C +package = platform.DiscRecordingUI +modules = DiscRecordingUI +compilerOpts = -framework DiscRecordingUI +linkerOpts = -framework DiscRecordingUI +#Disabled: Unavailable diff --git a/kotlin-native/platformLibs/src/platform/osx/DiskArbitration.def b/kotlin-native/platformLibs/src/platform/osx/DiskArbitration.def new file mode 100644 index 00000000000..6a03e9128a9 --- /dev/null +++ b/kotlin-native/platformLibs/src/platform/osx/DiskArbitration.def @@ -0,0 +1,7 @@ +depends = CoreFoundation IOKit darwin libkern posix +language = Objective-C +package = platform.DiskArbitration +modules = DiskArbitration + +compilerOpts = -framework DiskArbitration +linkerOpts = -framework DiskArbitration diff --git a/kotlin-native/platformLibs/src/platform/osx/DriverKit.def.disabled b/kotlin-native/platformLibs/src/platform/osx/DriverKit.def.disabled new file mode 100644 index 00000000000..a174a0d7c0e --- /dev/null +++ b/kotlin-native/platformLibs/src/platform/osx/DriverKit.def.disabled @@ -0,0 +1,6 @@ +language = Objective-C +package = platform.DriverKit +modules = DriverKit +compilerOpts = -framework DriverKit +linkerOpts = -framework DriverKit +#Disabled: part of DriverKit diff --git a/kotlin-native/platformLibs/src/platform/osx/EventKit.def b/kotlin-native/platformLibs/src/platform/osx/EventKit.def new file mode 100644 index 00000000000..9654b117588 --- /dev/null +++ b/kotlin-native/platformLibs/src/platform/osx/EventKit.def @@ -0,0 +1,7 @@ +depends = ApplicationServices CFNetwork CoreFoundation CoreGraphics CoreLocation CoreServices CoreText DiskArbitration Foundation IOKit ImageIO Security darwin libkern osx posix +language = Objective-C +package = platform.EventKit +modules = EventKit + +compilerOpts = -framework EventKit +linkerOpts = -framework EventKit diff --git a/kotlin-native/platformLibs/src/platform/osx/ExceptionHandling.def b/kotlin-native/platformLibs/src/platform/osx/ExceptionHandling.def new file mode 100644 index 00000000000..ff1bb304db1 --- /dev/null +++ b/kotlin-native/platformLibs/src/platform/osx/ExceptionHandling.def @@ -0,0 +1,7 @@ +depends = ApplicationServices CFNetwork CoreFoundation CoreGraphics CoreServices CoreText DiskArbitration Foundation IOKit ImageIO Security darwin libkern osx posix +language = Objective-C +package = platform.ExceptionHandling +modules = ExceptionHandling + +compilerOpts = -framework ExceptionHandling +linkerOpts = -framework ExceptionHandling diff --git a/kotlin-native/platformLibs/src/platform/osx/ExecutionPolicy.def b/kotlin-native/platformLibs/src/platform/osx/ExecutionPolicy.def new file mode 100644 index 00000000000..8fe22f6f020 --- /dev/null +++ b/kotlin-native/platformLibs/src/platform/osx/ExecutionPolicy.def @@ -0,0 +1,7 @@ +depends = ApplicationServices CFNetwork CoreFoundation CoreGraphics CoreServices CoreText DiskArbitration Foundation IOKit ImageIO Security darwin libkern osx posix +language = Objective-C +package = platform.ExecutionPolicy +modules = ExecutionPolicy + +compilerOpts = -framework ExecutionPolicy +linkerOpts = -framework ExecutionPolicy diff --git a/kotlin-native/platformLibs/src/platform/osx/ExternalAccessory.def b/kotlin-native/platformLibs/src/platform/osx/ExternalAccessory.def new file mode 100644 index 00000000000..ec2a2e762d2 --- /dev/null +++ b/kotlin-native/platformLibs/src/platform/osx/ExternalAccessory.def @@ -0,0 +1,7 @@ +depends = ApplicationServices CFNetwork CoreFoundation CoreGraphics CoreServices CoreText DiskArbitration Foundation IOKit ImageIO Security darwin libkern osx posix +language = Objective-C +package = platform.ExternalAccessory +modules = ExternalAccessory + +compilerOpts = -framework ExternalAccessory +linkerOpts = -framework ExternalAccessory diff --git a/kotlin-native/platformLibs/src/platform/osx/FWAUserLib.def b/kotlin-native/platformLibs/src/platform/osx/FWAUserLib.def new file mode 100644 index 00000000000..1b48fe3cf58 --- /dev/null +++ b/kotlin-native/platformLibs/src/platform/osx/FWAUserLib.def @@ -0,0 +1,7 @@ +depends = CoreFoundation IOKit darwin libkern posix +language = Objective-C +package = platform.FWAUserLib +modules = FWAUserLib + +compilerOpts = -framework FWAUserLib +linkerOpts = -framework FWAUserLib diff --git a/kotlin-native/platformLibs/src/platform/osx/FileProvider.def b/kotlin-native/platformLibs/src/platform/osx/FileProvider.def new file mode 100644 index 00000000000..5436536422a --- /dev/null +++ b/kotlin-native/platformLibs/src/platform/osx/FileProvider.def @@ -0,0 +1,7 @@ +depends = ApplicationServices CFNetwork CoreFoundation CoreGraphics CoreServices CoreText DiskArbitration Foundation IOKit ImageIO Security darwin libkern osx posix +language = Objective-C +package = platform.FileProvider +modules = FileProvider + +compilerOpts = -framework FileProvider +linkerOpts = -framework FileProvider diff --git a/kotlin-native/platformLibs/src/platform/osx/FileProviderUI.def b/kotlin-native/platformLibs/src/platform/osx/FileProviderUI.def new file mode 100644 index 00000000000..2fca2298468 --- /dev/null +++ b/kotlin-native/platformLibs/src/platform/osx/FileProviderUI.def @@ -0,0 +1,7 @@ +depends = AppKit ApplicationServices CFNetwork CoreData CoreFoundation CoreGraphics CoreImage CoreServices CoreText CoreVideo DiskArbitration FileProvider Foundation IOKit IOSurface ImageIO Metal OpenGLCommon QuartzCore Security darwin libkern osx posix +language = Objective-C +package = platform.FileProviderUI +modules = FileProviderUI + +compilerOpts = -framework FileProviderUI +linkerOpts = -framework FileProviderUI diff --git a/kotlin-native/platformLibs/src/platform/osx/FinderSync.def b/kotlin-native/platformLibs/src/platform/osx/FinderSync.def new file mode 100644 index 00000000000..9b631b43b3b --- /dev/null +++ b/kotlin-native/platformLibs/src/platform/osx/FinderSync.def @@ -0,0 +1,7 @@ +depends = AppKit ApplicationServices CFNetwork CoreFoundation CoreGraphics CoreServices CoreText DiskArbitration Foundation IOKit ImageIO Security darwin libkern osx posix +language = Objective-C +package = platform.FinderSync +modules = FinderSync + +compilerOpts = -framework FinderSync +linkerOpts = -framework FinderSync diff --git a/kotlin-native/platformLibs/src/platform/osx/ForceFeedback.def b/kotlin-native/platformLibs/src/platform/osx/ForceFeedback.def new file mode 100644 index 00000000000..96219ca54af --- /dev/null +++ b/kotlin-native/platformLibs/src/platform/osx/ForceFeedback.def @@ -0,0 +1,7 @@ +depends = CoreFoundation IOKit darwin libkern posix +language = Objective-C +package = platform.ForceFeedback +modules = ForceFeedback + +compilerOpts = -framework ForceFeedback +linkerOpts = -framework ForceFeedback diff --git a/kotlin-native/platformLibs/src/platform/osx/Foundation.def b/kotlin-native/platformLibs/src/platform/osx/Foundation.def new file mode 100644 index 00000000000..f19c0765524 --- /dev/null +++ b/kotlin-native/platformLibs/src/platform/osx/Foundation.def @@ -0,0 +1,7 @@ +depends = ApplicationServices CFNetwork CoreFoundation CoreGraphics CoreServices CoreText DiskArbitration IOKit ImageIO Security darwin libkern osx posix +language = Objective-C +package = platform.Foundation +modules = Foundation + +compilerOpts = -framework Foundation +linkerOpts = -framework Foundation diff --git a/kotlin-native/platformLibs/src/platform/osx/GLKit.def b/kotlin-native/platformLibs/src/platform/osx/GLKit.def new file mode 100644 index 00000000000..8019b9fe0c8 --- /dev/null +++ b/kotlin-native/platformLibs/src/platform/osx/GLKit.def @@ -0,0 +1,7 @@ +depends = AppKit ApplicationServices CFNetwork CoreData CoreFoundation CoreGraphics CoreImage CoreServices CoreText CoreVideo DiskArbitration Foundation IOKit IOSurface ImageIO Metal ModelIO OpenGL3 OpenGLCommon QuartzCore Security darwin libkern osx posix +language = Objective-C +package = platform.GLKit +modules = GLKit + +compilerOpts = -framework GLKit +linkerOpts = -framework GLKit diff --git a/kotlin-native/platformLibs/src/platform/osx/GLUT.def b/kotlin-native/platformLibs/src/platform/osx/GLUT.def new file mode 100644 index 00000000000..a253fd9fe25 --- /dev/null +++ b/kotlin-native/platformLibs/src/platform/osx/GLUT.def @@ -0,0 +1,16 @@ +depends = OpenGL OpenGLCommon darwin posix +language = Objective-C +package = platform.GLUT +modules = GLUT + +compilerOpts = -framework GLUT +linkerOpts = -framework GLUT +excludedFunctions = __smapDrawSphereMapMeshBack __smapDrawSphereMapMeshSide __smapValidateSphereMapMesh \ + bisecting_plane draw_angle_style_back_cap draw_angle_style_front_cap \ + draw_binorm_segment_c_and_edge_n draw_binorm_segment_c_and_facet_n draw_binorm_segment_edge_n \ + draw_binorm_segment_facet_n draw_raw_style_end_cap draw_round_style_cap_callback \ + draw_segment_c_and_edge_n draw_segment_c_and_facet_n draw_segment_color draw_segment_edge_n \ + draw_segment_facet_n draw_segment_plain extrusion_angle_join extrusion_raw_join \ + extrusion_round_or_cut_join rot_about_axis_d rot_about_axis_f rot_axis_d rot_axis_f \ + rot_omega_d rot_omega_f up_sanity_check urot_about_axis_d urot_about_axis_f urot_axis_d \ + urot_axis_f urot_omega_d urot_omega_f uview_direction_d uview_direction_f uviewpoint_d uviewpoint_f diff --git a/kotlin-native/platformLibs/src/platform/osx/GSS.def b/kotlin-native/platformLibs/src/platform/osx/GSS.def new file mode 100644 index 00000000000..a8e6204b3a0 --- /dev/null +++ b/kotlin-native/platformLibs/src/platform/osx/GSS.def @@ -0,0 +1,7 @@ +depends = CoreFoundation darwin posix +language = Objective-C +package = platform.GSS +modules = GSS + +compilerOpts = -framework GSS +linkerOpts = -framework GSS diff --git a/kotlin-native/platformLibs/src/platform/osx/GameController.def b/kotlin-native/platformLibs/src/platform/osx/GameController.def new file mode 100644 index 00000000000..fd69d40e4c0 --- /dev/null +++ b/kotlin-native/platformLibs/src/platform/osx/GameController.def @@ -0,0 +1,7 @@ +depends = AppKit ApplicationServices CFNetwork CoreData CoreFoundation CoreGraphics CoreServices CoreText DiskArbitration Foundation IOKit ImageIO Security darwin libkern osx posix +language = Objective-C +package = platform.GameController +modules = GameController + +compilerOpts = -framework GameController +linkerOpts = -framework GameController diff --git a/kotlin-native/platformLibs/src/platform/osx/GameKit.def b/kotlin-native/platformLibs/src/platform/osx/GameKit.def new file mode 100644 index 00000000000..615f13f930a --- /dev/null +++ b/kotlin-native/platformLibs/src/platform/osx/GameKit.def @@ -0,0 +1,9 @@ +depends = AppKit ApplicationServices CFNetwork Cocoa CoreData CoreFoundation CoreGraphics CoreImage CoreServices CoreText CoreVideo DiskArbitration Foundation GLKit GameController GameplayKit IOKit IOSurface ImageIO Metal MetalKit ModelIO OpenGLCommon QuartzCore SceneKit Security SpriteKit darwin libkern osx posix +language = Objective-C +package = platform.GameKit +modules = GameKit + +compilerOpts = -framework GameKit +linkerOpts = -framework GameKit + +excludedFunctions = GKVoiceChatServiceErrorDomain diff --git a/kotlin-native/platformLibs/src/platform/osx/GameplayKit.def b/kotlin-native/platformLibs/src/platform/osx/GameplayKit.def new file mode 100644 index 00000000000..740c03dd5fd --- /dev/null +++ b/kotlin-native/platformLibs/src/platform/osx/GameplayKit.def @@ -0,0 +1,7 @@ +depends = AppKit ApplicationServices CFNetwork Cocoa CoreData CoreFoundation CoreGraphics CoreImage CoreServices CoreText CoreVideo DiskArbitration Foundation GLKit IOKit IOSurface ImageIO Metal OpenGLCommon QuartzCore SceneKit Security SpriteKit darwin libkern osx posix +language = Objective-C +package = platform.GameplayKit +modules = GameplayKit + +compilerOpts = -framework GameplayKit +linkerOpts = -framework GameplayKit diff --git a/kotlin-native/platformLibs/src/platform/osx/HIDDriverKit.def.disabled b/kotlin-native/platformLibs/src/platform/osx/HIDDriverKit.def.disabled new file mode 100644 index 00000000000..73a9f5699c4 --- /dev/null +++ b/kotlin-native/platformLibs/src/platform/osx/HIDDriverKit.def.disabled @@ -0,0 +1,6 @@ +language = Objective-C +package = platform.HIDDriverKit +modules = HIDDriverKit +compilerOpts = -framework HIDDriverKit +linkerOpts = -framework HIDDriverKit +#Disabled: part of DriverKit diff --git a/kotlin-native/platformLibs/src/platform/osx/Hypervisor.def b/kotlin-native/platformLibs/src/platform/osx/Hypervisor.def new file mode 100644 index 00000000000..9bdff403baf --- /dev/null +++ b/kotlin-native/platformLibs/src/platform/osx/Hypervisor.def @@ -0,0 +1,7 @@ +depends = darwin posix +language = Objective-C +package = platform.Hypervisor +modules = Hypervisor + +compilerOpts = -framework Hypervisor +linkerOpts = -framework Hypervisor diff --git a/kotlin-native/platformLibs/src/platform/osx/ICADevices.def.disabled b/kotlin-native/platformLibs/src/platform/osx/ICADevices.def.disabled new file mode 100644 index 00000000000..9d134f8df85 --- /dev/null +++ b/kotlin-native/platformLibs/src/platform/osx/ICADevices.def.disabled @@ -0,0 +1,6 @@ +language = Objective-C +package = platform.ICADevices +modules = ICADevices +compilerOpts = -framework ICADevices +linkerOpts = -framework ICADevices +#Disabled: Unavailable diff --git a/kotlin-native/platformLibs/src/platform/osx/IMServicePlugIn.def.disabled b/kotlin-native/platformLibs/src/platform/osx/IMServicePlugIn.def.disabled new file mode 100644 index 00000000000..e0dfb4042bf --- /dev/null +++ b/kotlin-native/platformLibs/src/platform/osx/IMServicePlugIn.def.disabled @@ -0,0 +1,6 @@ +language = Objective-C +package = platform.IMServicePlugIn +modules = IMServicePlugIn +compilerOpts = -framework IMServicePlugIn +linkerOpts = -framework IMServicePlugIn +#Disabled: Unavailable diff --git a/kotlin-native/platformLibs/src/platform/osx/IOBluetooth.def b/kotlin-native/platformLibs/src/platform/osx/IOBluetooth.def new file mode 100644 index 00000000000..4dca6258095 --- /dev/null +++ b/kotlin-native/platformLibs/src/platform/osx/IOBluetooth.def @@ -0,0 +1,7 @@ +depends = ApplicationServices CFNetwork CoreAudio CoreAudioTypes CoreFoundation CoreGraphics CoreServices CoreText DiskArbitration Foundation IOKit ImageIO Security darwin libkern osx posix +language = Objective-C +package = platform.IOBluetooth +modules = IOBluetooth + +compilerOpts = -framework IOBluetooth +linkerOpts = -framework IOBluetooth diff --git a/kotlin-native/platformLibs/src/platform/osx/IOBluetoothUI.def b/kotlin-native/platformLibs/src/platform/osx/IOBluetoothUI.def new file mode 100644 index 00000000000..4121ca80836 --- /dev/null +++ b/kotlin-native/platformLibs/src/platform/osx/IOBluetoothUI.def @@ -0,0 +1,7 @@ +depends = AppKit ApplicationServices CFNetwork Cocoa CoreData CoreFoundation CoreGraphics CoreImage CoreServices CoreText CoreVideo DiskArbitration Foundation IOBluetooth IOKit IOSurface ImageIO Metal OpenGLCommon QuartzCore Security darwin libkern osx posix +language = Objective-C +package = platform.IOBluetoothUI +modules = IOBluetoothUI + +compilerOpts = -framework IOBluetoothUI +linkerOpts = -framework IOBluetoothUI diff --git a/kotlin-native/platformLibs/src/platform/osx/IOKit.def b/kotlin-native/platformLibs/src/platform/osx/IOKit.def new file mode 100644 index 00000000000..2d48e329685 --- /dev/null +++ b/kotlin-native/platformLibs/src/platform/osx/IOKit.def @@ -0,0 +1,9 @@ +depends = CoreFoundation darwin libkern posix +language = Objective-C +package = platform.IOKit +modules = IOKit + +compilerOpts = -framework IOKit +linkerOpts = -framework IOKit + +excludedFunctions = IOURLWriteDataAndPropertiesToResource diff --git a/kotlin-native/platformLibs/src/platform/osx/IOSurface.def b/kotlin-native/platformLibs/src/platform/osx/IOSurface.def new file mode 100644 index 00000000000..28bc2ee0748 --- /dev/null +++ b/kotlin-native/platformLibs/src/platform/osx/IOSurface.def @@ -0,0 +1,7 @@ +depends = ApplicationServices CFNetwork CoreFoundation CoreGraphics CoreServices CoreText DiskArbitration Foundation IOKit ImageIO Security darwin libkern osx posix +language = Objective-C +package = platform.IOSurface +modules = IOSurface + +compilerOpts = -framework IOSurface +linkerOpts = -framework IOSurface diff --git a/kotlin-native/platformLibs/src/platform/osx/IOUSBHost.def b/kotlin-native/platformLibs/src/platform/osx/IOUSBHost.def new file mode 100644 index 00000000000..8d1f08e3abe --- /dev/null +++ b/kotlin-native/platformLibs/src/platform/osx/IOUSBHost.def @@ -0,0 +1,7 @@ +depends = ApplicationServices CFNetwork CoreFoundation CoreGraphics CoreServices CoreText DiskArbitration Foundation IOKit ImageIO Security darwin libkern osx posix +language = Objective-C +package = platform.IOUSBHost +modules = IOUSBHost + +compilerOpts = -framework IOUSBHost +linkerOpts = -framework IOUSBHost diff --git a/kotlin-native/platformLibs/src/platform/osx/IdentityLookup.def b/kotlin-native/platformLibs/src/platform/osx/IdentityLookup.def new file mode 100644 index 00000000000..9119b961fd3 --- /dev/null +++ b/kotlin-native/platformLibs/src/platform/osx/IdentityLookup.def @@ -0,0 +1,7 @@ +depends = ApplicationServices CFNetwork CoreFoundation CoreGraphics CoreServices CoreText DiskArbitration Foundation IOKit ImageIO Security darwin libkern osx posix +language = Objective-C +package = platform.IdentityLookup +modules = IdentityLookup + +compilerOpts = -framework IdentityLookup +linkerOpts = -framework IdentityLookup diff --git a/kotlin-native/platformLibs/src/platform/osx/ImageCaptureCore.def b/kotlin-native/platformLibs/src/platform/osx/ImageCaptureCore.def new file mode 100644 index 00000000000..7af533f8bcf --- /dev/null +++ b/kotlin-native/platformLibs/src/platform/osx/ImageCaptureCore.def @@ -0,0 +1,7 @@ +depends = AppKit ApplicationServices CFNetwork Cocoa CoreData CoreFoundation CoreGraphics CoreImage CoreServices CoreText CoreVideo DiskArbitration Foundation IOKit IOSurface ImageIO Metal OpenGLCommon QuartzCore Security darwin libkern osx posix +language = Objective-C +package = platform.ImageCaptureCore +modules = ImageCaptureCore + +compilerOpts = -framework ImageCaptureCore +linkerOpts = -framework ImageCaptureCore diff --git a/kotlin-native/platformLibs/src/platform/osx/ImageIO.def b/kotlin-native/platformLibs/src/platform/osx/ImageIO.def new file mode 100644 index 00000000000..c1058271987 --- /dev/null +++ b/kotlin-native/platformLibs/src/platform/osx/ImageIO.def @@ -0,0 +1,7 @@ +depends = CoreFoundation CoreGraphics IOKit darwin libkern posix +language = Objective-C +package = platform.ImageIO +modules = ImageIO + +compilerOpts = -framework ImageIO +linkerOpts = -framework ImageIO diff --git a/kotlin-native/platformLibs/src/platform/osx/InputMethodKit.def.disabled b/kotlin-native/platformLibs/src/platform/osx/InputMethodKit.def.disabled new file mode 100644 index 00000000000..4e19befb2e0 --- /dev/null +++ b/kotlin-native/platformLibs/src/platform/osx/InputMethodKit.def.disabled @@ -0,0 +1,6 @@ +language = Objective-C +package = platform.InputMethodKit +modules = InputMethodKit +compilerOpts = -framework InputMethodKit +linkerOpts = -framework InputMethodKit +#Disabled: Deprecated diff --git a/kotlin-native/platformLibs/src/platform/osx/InstallerPlugins.def.disabled b/kotlin-native/platformLibs/src/platform/osx/InstallerPlugins.def.disabled new file mode 100644 index 00000000000..cadd0fb2457 --- /dev/null +++ b/kotlin-native/platformLibs/src/platform/osx/InstallerPlugins.def.disabled @@ -0,0 +1,6 @@ +language = Objective-C +package = platform.InstallerPlugins +modules = InstallerPlugins +compilerOpts = -framework InstallerPlugins +linkerOpts = -framework InstallerPlugins +#Disabled: Unavailable diff --git a/kotlin-native/platformLibs/src/platform/osx/InstantMessage.def.disabled b/kotlin-native/platformLibs/src/platform/osx/InstantMessage.def.disabled new file mode 100644 index 00000000000..22c66d94e94 --- /dev/null +++ b/kotlin-native/platformLibs/src/platform/osx/InstantMessage.def.disabled @@ -0,0 +1,6 @@ +language = Objective-C +package = platform.InstantMessage +modules = InstantMessage +compilerOpts = -framework InstantMessage +linkerOpts = -framework InstantMessage +#Disabled: Unavailable diff --git a/kotlin-native/platformLibs/src/platform/osx/Intents.def b/kotlin-native/platformLibs/src/platform/osx/Intents.def new file mode 100644 index 00000000000..3c5240d114f --- /dev/null +++ b/kotlin-native/platformLibs/src/platform/osx/Intents.def @@ -0,0 +1,6 @@ +depends = ApplicationServices CFNetwork CoreFoundation CoreGraphics CoreLocation CoreServices CoreText DiskArbitration Foundation IOKit ImageIO Security darwin libkern osx posix +language = Objective-C +package = platform.Intents +modules = Intents +compilerOpts = -framework Intents +linkerOpts = -framework Intents diff --git a/kotlin-native/platformLibs/src/platform/osx/JavaFrameEmbedding.def.disabled b/kotlin-native/platformLibs/src/platform/osx/JavaFrameEmbedding.def.disabled new file mode 100644 index 00000000000..dfcfc475fd7 --- /dev/null +++ b/kotlin-native/platformLibs/src/platform/osx/JavaFrameEmbedding.def.disabled @@ -0,0 +1,6 @@ +language = Objective-C +package = platform.JavaFrameEmbedding +modules = JavaFrameEmbedding +compilerOpts = -framework JavaFrameEmbedding +linkerOpts = -framework JavaFrameEmbedding +#Disabled: Unavailable diff --git a/kotlin-native/platformLibs/src/platform/osx/JavaScriptCore.def b/kotlin-native/platformLibs/src/platform/osx/JavaScriptCore.def new file mode 100644 index 00000000000..5bb2c69c8b3 --- /dev/null +++ b/kotlin-native/platformLibs/src/platform/osx/JavaScriptCore.def @@ -0,0 +1,7 @@ +depends = ApplicationServices CFNetwork CoreFoundation CoreGraphics CoreServices CoreText DiskArbitration Foundation IOKit ImageIO Security darwin libkern osx posix +language = Objective-C +package = platform.JavaScriptCore +modules = JavaScriptCore + +compilerOpts = -framework JavaScriptCore +linkerOpts = -framework JavaScriptCore diff --git a/kotlin-native/platformLibs/src/platform/osx/JavaVM.def.disabled b/kotlin-native/platformLibs/src/platform/osx/JavaVM.def.disabled new file mode 100644 index 00000000000..b3be0ccaa3a --- /dev/null +++ b/kotlin-native/platformLibs/src/platform/osx/JavaVM.def.disabled @@ -0,0 +1,6 @@ +language = Objective-C +package = platform.JavaVM +modules = JavaVM +compilerOpts = -framework JavaVM +linkerOpts = -framework JavaVM +#Disabled: Unavailable diff --git a/kotlin-native/platformLibs/src/platform/osx/Kerberos.def.disabled b/kotlin-native/platformLibs/src/platform/osx/Kerberos.def.disabled new file mode 100644 index 00000000000..1da96fd5daa --- /dev/null +++ b/kotlin-native/platformLibs/src/platform/osx/Kerberos.def.disabled @@ -0,0 +1,6 @@ +language = Objective-C +package = platform.Kerberos +modules = Kerberos +compilerOpts = -framework Kerberos +linkerOpts = -framework Kerberos +#Disabled: Unavailable diff --git a/kotlin-native/platformLibs/src/platform/osx/Kernel.def.disabled b/kotlin-native/platformLibs/src/platform/osx/Kernel.def.disabled new file mode 100644 index 00000000000..b218117a8f1 --- /dev/null +++ b/kotlin-native/platformLibs/src/platform/osx/Kernel.def.disabled @@ -0,0 +1,6 @@ +language = Objective-C +package = platform.Kernel +modules = Kernel +compilerOpts = -framework Kernel +linkerOpts = -framework Kernel +#Disabled: Framework without module diff --git a/kotlin-native/platformLibs/src/platform/osx/LDAP.def.disabled b/kotlin-native/platformLibs/src/platform/osx/LDAP.def.disabled new file mode 100644 index 00000000000..08f6caf04a8 --- /dev/null +++ b/kotlin-native/platformLibs/src/platform/osx/LDAP.def.disabled @@ -0,0 +1,6 @@ +language = Objective-C +package = platform.LDAP +modules = LDAP +compilerOpts = -framework LDAP +linkerOpts = -framework LDAP +#Disabled: Unavailable diff --git a/kotlin-native/platformLibs/src/platform/osx/LatentSemanticMapping.def.disabled b/kotlin-native/platformLibs/src/platform/osx/LatentSemanticMapping.def.disabled new file mode 100644 index 00000000000..e32a5461280 --- /dev/null +++ b/kotlin-native/platformLibs/src/platform/osx/LatentSemanticMapping.def.disabled @@ -0,0 +1,6 @@ +language = Objective-C +package = platform.LatentSemanticMapping +modules = LatentSemanticMapping +compilerOpts = -framework LatentSemanticMapping +linkerOpts = -framework LatentSemanticMapping +#Disabled: Framework without module diff --git a/kotlin-native/platformLibs/src/platform/osx/LinkPresentation.def b/kotlin-native/platformLibs/src/platform/osx/LinkPresentation.def new file mode 100644 index 00000000000..5329709f187 --- /dev/null +++ b/kotlin-native/platformLibs/src/platform/osx/LinkPresentation.def @@ -0,0 +1,7 @@ +depends = AppKit ApplicationServices CFNetwork CoreData CoreFoundation CoreGraphics CoreImage CoreServices CoreText CoreVideo DiskArbitration Foundation IOKit IOSurface ImageIO Metal OpenGLCommon QuartzCore Security darwin libkern osx posix +language = Objective-C +package = platform.LinkPresentation +modules = LinkPresentation + +compilerOpts = -framework LinkPresentation +linkerOpts = -framework LinkPresentation diff --git a/kotlin-native/platformLibs/src/platform/osx/LocalAuthentication.def b/kotlin-native/platformLibs/src/platform/osx/LocalAuthentication.def new file mode 100644 index 00000000000..562321c6870 --- /dev/null +++ b/kotlin-native/platformLibs/src/platform/osx/LocalAuthentication.def @@ -0,0 +1,7 @@ +depends = ApplicationServices CFNetwork CoreFoundation CoreGraphics CoreServices CoreText DiskArbitration Foundation IOKit ImageIO Security darwin libkern osx posix +language = Objective-C +package = platform.LocalAuthentication +modules = LocalAuthentication + +compilerOpts = -framework LocalAuthentication +linkerOpts = -framework LocalAuthentication diff --git a/kotlin-native/platformLibs/src/platform/osx/MapKit.def b/kotlin-native/platformLibs/src/platform/osx/MapKit.def new file mode 100644 index 00000000000..fbd4039f09b --- /dev/null +++ b/kotlin-native/platformLibs/src/platform/osx/MapKit.def @@ -0,0 +1,7 @@ +depends = AppKit ApplicationServices CFNetwork CoreData CoreFoundation CoreGraphics CoreImage CoreLocation CoreServices CoreText CoreVideo DiskArbitration Foundation IOKit IOSurface ImageIO Metal OpenGLCommon QuartzCore Security darwin libkern osx posix +language = Objective-C +package = platform.MapKit +modules = MapKit + +compilerOpts = -framework MapKit +linkerOpts = -framework MapKit diff --git a/kotlin-native/platformLibs/src/platform/osx/MediaAccessibility.def b/kotlin-native/platformLibs/src/platform/osx/MediaAccessibility.def new file mode 100644 index 00000000000..de1ef97abec --- /dev/null +++ b/kotlin-native/platformLibs/src/platform/osx/MediaAccessibility.def @@ -0,0 +1,7 @@ +depends = ApplicationServices CFNetwork CoreFoundation CoreGraphics CoreImage CoreServices CoreText CoreVideo DiskArbitration Foundation IOKit IOSurface ImageIO Metal OpenGLCommon QuartzCore Security darwin libkern osx posix +language = Objective-C +package = platform.MediaAccessibility +modules = MediaAccessibility + +compilerOpts = -framework MediaAccessibility +linkerOpts = -framework MediaAccessibility diff --git a/kotlin-native/platformLibs/src/platform/osx/MediaLibrary.def b/kotlin-native/platformLibs/src/platform/osx/MediaLibrary.def new file mode 100644 index 00000000000..399f2c1e9ab --- /dev/null +++ b/kotlin-native/platformLibs/src/platform/osx/MediaLibrary.def @@ -0,0 +1,7 @@ +depends = ApplicationServices CFNetwork CoreFoundation CoreGraphics CoreServices CoreText DiskArbitration Foundation IOKit ImageIO Security darwin libkern osx posix +language = Objective-C +package = platform.MediaLibrary +modules = MediaLibrary + +compilerOpts = -framework MediaLibrary +linkerOpts = -framework MediaLibrary diff --git a/kotlin-native/platformLibs/src/platform/osx/MediaPlayer.def b/kotlin-native/platformLibs/src/platform/osx/MediaPlayer.def new file mode 100644 index 00000000000..5f301259eca --- /dev/null +++ b/kotlin-native/platformLibs/src/platform/osx/MediaPlayer.def @@ -0,0 +1,7 @@ +depends = AVFoundation ApplicationServices CFNetwork CoreFoundation CoreGraphics CoreMedia CoreServices CoreText DiskArbitration Foundation IOKit ImageIO Security darwin libkern osx posix +language = Objective-C +package = platform.MediaPlayer +modules = MediaPlayer + +compilerOpts = -framework MediaPlayer +linkerOpts = -framework MediaPlayer diff --git a/kotlin-native/platformLibs/src/platform/osx/MediaToolbox.def b/kotlin-native/platformLibs/src/platform/osx/MediaToolbox.def new file mode 100644 index 00000000000..05e8276eef9 --- /dev/null +++ b/kotlin-native/platformLibs/src/platform/osx/MediaToolbox.def @@ -0,0 +1,7 @@ +depends = ApplicationServices AudioToolbox CFNetwork CoreAudio CoreAudioTypes CoreFoundation CoreGraphics CoreMIDI CoreMedia CoreServices CoreText CoreVideo DiskArbitration Foundation IOKit IOSurface ImageIO Metal OpenGLCommon Security darwin libkern osx posix +language = Objective-C +package = platform.MediaToolbox +modules = MediaToolbox + +compilerOpts = -framework MediaToolbox +linkerOpts = -framework MediaToolbox diff --git a/kotlin-native/platformLibs/src/platform/osx/Message.def.disabled b/kotlin-native/platformLibs/src/platform/osx/Message.def.disabled new file mode 100644 index 00000000000..482ac491471 --- /dev/null +++ b/kotlin-native/platformLibs/src/platform/osx/Message.def.disabled @@ -0,0 +1,6 @@ +language = Objective-C +package = platform.Message +modules = Message +compilerOpts = -framework Message +linkerOpts = -framework Message +#Disabled: Unavailable diff --git a/kotlin-native/platformLibs/src/platform/osx/Metal.def b/kotlin-native/platformLibs/src/platform/osx/Metal.def new file mode 100644 index 00000000000..24a6db65027 --- /dev/null +++ b/kotlin-native/platformLibs/src/platform/osx/Metal.def @@ -0,0 +1,8 @@ +depends = ApplicationServices CFNetwork CoreFoundation CoreGraphics CoreServices CoreText DiskArbitration Foundation IOKit IOSurface ImageIO Security darwin libkern osx posix +language = Objective-C +package = platform.Metal +modules = Metal + +excludedFunctions = MTLRenderPipelineErrorDomain +compilerOpts = -framework Metal +linkerOpts = -framework Metal diff --git a/kotlin-native/platformLibs/src/platform/osx/MetalKit.def b/kotlin-native/platformLibs/src/platform/osx/MetalKit.def new file mode 100644 index 00000000000..971c00b1e7f --- /dev/null +++ b/kotlin-native/platformLibs/src/platform/osx/MetalKit.def @@ -0,0 +1,7 @@ +depends = AppKit ApplicationServices CFNetwork CoreData CoreFoundation CoreGraphics CoreImage CoreServices CoreText CoreVideo DiskArbitration Foundation IOKit IOSurface ImageIO Metal ModelIO OpenGLCommon QuartzCore Security darwin libkern osx posix +language = Objective-C +package = platform.MetalKit +modules = MetalKit + +compilerOpts = -framework MetalKit +linkerOpts = -framework MetalKit diff --git a/kotlin-native/platformLibs/src/platform/osx/MetalPerformanceShaders.def b/kotlin-native/platformLibs/src/platform/osx/MetalPerformanceShaders.def new file mode 100644 index 00000000000..695554494a5 --- /dev/null +++ b/kotlin-native/platformLibs/src/platform/osx/MetalPerformanceShaders.def @@ -0,0 +1,7 @@ +depends = ApplicationServices CFNetwork CoreFoundation CoreGraphics CoreServices CoreText DiskArbitration Foundation IOKit IOSurface ImageIO Metal Security darwin libkern osx posix +language = Objective-C +package = platform.MetalPerformanceShaders +modules = MetalPerformanceShaders + +compilerOpts = -framework MetalPerformanceShaders +linkerOpts = -framework MetalPerformanceShaders diff --git a/kotlin-native/platformLibs/src/platform/osx/MetricKit.def b/kotlin-native/platformLibs/src/platform/osx/MetricKit.def new file mode 100644 index 00000000000..648212b943f --- /dev/null +++ b/kotlin-native/platformLibs/src/platform/osx/MetricKit.def @@ -0,0 +1,7 @@ +depends = ApplicationServices CFNetwork CoreFoundation CoreGraphics CoreServices CoreText DiskArbitration Foundation IOKit ImageIO Security darwin libkern osx posix +language = Objective-C +package = platform.MetricKit +modules = MetricKit + +compilerOpts = -framework MetricKit +linkerOpts = -framework MetricKit diff --git a/kotlin-native/platformLibs/src/platform/osx/ModelIO.def b/kotlin-native/platformLibs/src/platform/osx/ModelIO.def new file mode 100644 index 00000000000..bc60360caff --- /dev/null +++ b/kotlin-native/platformLibs/src/platform/osx/ModelIO.def @@ -0,0 +1,7 @@ +depends = ApplicationServices CFNetwork CoreFoundation CoreGraphics CoreServices CoreText DiskArbitration Foundation IOKit ImageIO Security darwin libkern osx posix +language = Objective-C +package = platform.ModelIO +modules = ModelIO + +compilerOpts = -framework ModelIO +linkerOpts = -framework ModelIO diff --git a/kotlin-native/platformLibs/src/platform/osx/MorphunAssetsUpdater.def.disabled b/kotlin-native/platformLibs/src/platform/osx/MorphunAssetsUpdater.def.disabled new file mode 100644 index 00000000000..9b3c37da12d --- /dev/null +++ b/kotlin-native/platformLibs/src/platform/osx/MorphunAssetsUpdater.def.disabled @@ -0,0 +1,6 @@ +language = Objective-C +package = platform.MorphunAssetsUpdater +modules = MorphunAssetsUpdater +compilerOpts = -framework MorphunAssetsUpdater +linkerOpts = -framework MorphunAssetsUpdater +#Disabled: Unavailable diff --git a/kotlin-native/platformLibs/src/platform/osx/MultipeerConnectivity.def b/kotlin-native/platformLibs/src/platform/osx/MultipeerConnectivity.def new file mode 100644 index 00000000000..21b3745ea50 --- /dev/null +++ b/kotlin-native/platformLibs/src/platform/osx/MultipeerConnectivity.def @@ -0,0 +1,7 @@ +depends = AppKit ApplicationServices CFNetwork Cocoa CoreData CoreFoundation CoreGraphics CoreImage CoreServices CoreText CoreVideo DiskArbitration Foundation IOKit IOSurface ImageIO Metal OpenGLCommon QuartzCore Security darwin libkern osx posix +language = Objective-C +package = platform.MultipeerConnectivity +modules = MultipeerConnectivity + +compilerOpts = -framework MultipeerConnectivity +linkerOpts = -framework MultipeerConnectivity diff --git a/kotlin-native/platformLibs/src/platform/osx/NaturalLanguage.def b/kotlin-native/platformLibs/src/platform/osx/NaturalLanguage.def new file mode 100644 index 00000000000..0512f5a9e61 --- /dev/null +++ b/kotlin-native/platformLibs/src/platform/osx/NaturalLanguage.def @@ -0,0 +1,7 @@ +depends = ApplicationServices CFNetwork CoreFoundation CoreGraphics CoreServices CoreText DiskArbitration Foundation IOKit ImageIO Security darwin libkern osx posix +language = Objective-C +package = platform.NaturalLanguage +modules = NaturalLanguage + +compilerOpts = -framework NaturalLanguage +linkerOpts = -framework NaturalLanguage diff --git a/kotlin-native/platformLibs/src/platform/osx/NetFS.def.disabled b/kotlin-native/platformLibs/src/platform/osx/NetFS.def.disabled new file mode 100644 index 00000000000..639da2321ed --- /dev/null +++ b/kotlin-native/platformLibs/src/platform/osx/NetFS.def.disabled @@ -0,0 +1,6 @@ +language = Objective-C +package = platform.NetFS +modules = NetFS +compilerOpts = -framework NetFS +linkerOpts = -framework NetFS +#Disabled: Unavailable diff --git a/kotlin-native/platformLibs/src/platform/osx/Network.def b/kotlin-native/platformLibs/src/platform/osx/Network.def new file mode 100644 index 00000000000..b1664c1b04f --- /dev/null +++ b/kotlin-native/platformLibs/src/platform/osx/Network.def @@ -0,0 +1,7 @@ +depends = CoreFoundation Security darwin posix +language = Objective-C +package = platform.Network +modules = Network + +compilerOpts = -framework Network +linkerOpts = -framework Network diff --git a/kotlin-native/platformLibs/src/platform/osx/NetworkExtension.def b/kotlin-native/platformLibs/src/platform/osx/NetworkExtension.def new file mode 100644 index 00000000000..f083171ba7a --- /dev/null +++ b/kotlin-native/platformLibs/src/platform/osx/NetworkExtension.def @@ -0,0 +1,7 @@ +depends = ApplicationServices CFNetwork CoreFoundation CoreGraphics CoreServices CoreText DiskArbitration Foundation IOKit ImageIO Network Security darwin libkern osx posix +language = Objective-C +package = platform.NetworkExtension +modules = NetworkExtension + +compilerOpts = -framework NetworkExtension +linkerOpts = -framework NetworkExtension diff --git a/kotlin-native/platformLibs/src/platform/osx/NetworkingDriverKit.def.disabled b/kotlin-native/platformLibs/src/platform/osx/NetworkingDriverKit.def.disabled new file mode 100644 index 00000000000..5e0160ca6aa --- /dev/null +++ b/kotlin-native/platformLibs/src/platform/osx/NetworkingDriverKit.def.disabled @@ -0,0 +1,6 @@ +language = Objective-C +package = platform.NetworkingDriverKit +modules = NetworkingDriverKit +compilerOpts = -framework NetworkingDriverKit +linkerOpts = -framework NetworkingDriverKit +#Disabled: part of DriverKit diff --git a/kotlin-native/platformLibs/src/platform/osx/NotificationCenter.def b/kotlin-native/platformLibs/src/platform/osx/NotificationCenter.def new file mode 100644 index 00000000000..9d826f7f716 --- /dev/null +++ b/kotlin-native/platformLibs/src/platform/osx/NotificationCenter.def @@ -0,0 +1,7 @@ +depends = AppKit ApplicationServices CFNetwork CoreData CoreFoundation CoreGraphics CoreImage CoreServices CoreText CoreVideo DiskArbitration Foundation IOKit IOSurface ImageIO Metal OpenGLCommon QuartzCore Security darwin libkern osx posix +language = Objective-C +package = platform.NotificationCenter +modules = NotificationCenter + +compilerOpts = -framework NotificationCenter +linkerOpts = -framework NotificationCenter diff --git a/kotlin-native/platformLibs/src/platform/osx/OSAKit.def.disabled b/kotlin-native/platformLibs/src/platform/osx/OSAKit.def.disabled new file mode 100644 index 00000000000..e51ab8871cf --- /dev/null +++ b/kotlin-native/platformLibs/src/platform/osx/OSAKit.def.disabled @@ -0,0 +1,6 @@ +language = Objective-C +package = platform.OSAKit +modules = OSAKit +compilerOpts = -framework OSAKit +linkerOpts = -framework OSAKit +#Disabled: Unavailable diff --git a/kotlin-native/platformLibs/src/platform/osx/OSLog.def b/kotlin-native/platformLibs/src/platform/osx/OSLog.def new file mode 100644 index 00000000000..ce1525f8100 --- /dev/null +++ b/kotlin-native/platformLibs/src/platform/osx/OSLog.def @@ -0,0 +1,7 @@ +depends = ApplicationServices CFNetwork CoreFoundation CoreGraphics CoreServices CoreText DiskArbitration Foundation IOKit ImageIO Security darwin libkern osx posix +language = Objective-C +package = platform.OSLog +modules = OSLog + +compilerOpts = -framework OSLog +linkerOpts = -framework OSLog diff --git a/kotlin-native/platformLibs/src/platform/osx/OpenAL.def.disabled b/kotlin-native/platformLibs/src/platform/osx/OpenAL.def.disabled new file mode 100644 index 00000000000..576aba1f1e3 --- /dev/null +++ b/kotlin-native/platformLibs/src/platform/osx/OpenAL.def.disabled @@ -0,0 +1,6 @@ +language = Objective-C +package = platform.OpenAL +modules = OpenAL +compilerOpts = -framework OpenAL +linkerOpts = -framework OpenAL +#Disabled: Unavailable diff --git a/kotlin-native/platformLibs/src/platform/osx/OpenCL.def.disabled b/kotlin-native/platformLibs/src/platform/osx/OpenCL.def.disabled new file mode 100644 index 00000000000..1a9a8eceb9b --- /dev/null +++ b/kotlin-native/platformLibs/src/platform/osx/OpenCL.def.disabled @@ -0,0 +1,6 @@ +language = Objective-C +package = platform.OpenCL +modules = OpenCL +compilerOpts = -framework OpenCL +linkerOpts = -framework OpenCL +#Disabled: Unavailable diff --git a/kotlin-native/platformLibs/src/platform/osx/OpenDirectory.def b/kotlin-native/platformLibs/src/platform/osx/OpenDirectory.def new file mode 100644 index 00000000000..0c84186016a --- /dev/null +++ b/kotlin-native/platformLibs/src/platform/osx/OpenDirectory.def @@ -0,0 +1,9 @@ +depends = ApplicationServices CFNetwork CoreFoundation CoreGraphics CoreServices CoreText DiskArbitration Foundation IOKit ImageIO Security darwin libkern osx posix +language = Objective-C +package = platform.OpenDirectory +modules = OpenDirectory + +compilerOpts = -framework OpenDirectory +linkerOpts = -framework OpenDirectory + +excludedFunctions = kODAuthenticationTypeClearTextReadOnly kODAuthenticationTypeSetCertificateHashAsCurrent diff --git a/kotlin-native/platformLibs/src/platform/osx/OpenGL.def b/kotlin-native/platformLibs/src/platform/osx/OpenGL.def new file mode 100644 index 00000000000..6a47add878c --- /dev/null +++ b/kotlin-native/platformLibs/src/platform/osx/OpenGL.def @@ -0,0 +1,9 @@ +depends = OpenGLCommon darwin posix +language = Objective-C +package = platform.OpenGL +headers = OpenGL/glu.h + +headerFilter = OpenGL/gl.h OpenGL/glext.h OpenGL/glu.h + +compilerOpts = -framework OpenGL +linkerOpts = -framework OpenGL diff --git a/kotlin-native/platformLibs/src/platform/osx/OpenGL3.def b/kotlin-native/platformLibs/src/platform/osx/OpenGL3.def new file mode 100644 index 00000000000..1d3ba67ea8d --- /dev/null +++ b/kotlin-native/platformLibs/src/platform/osx/OpenGL3.def @@ -0,0 +1,9 @@ +depends = OpenGLCommon darwin posix +language = Objective-C +package = platform.OpenGL3 +headers = OpenGL/gl3.h OpenGL/gl3ext.h + +headerFilter = OpenGL/gl3.h OpenGL/gl3ext.h + +compilerOpts = -framework OpenGL +linkerOpts = -framework OpenGL diff --git a/kotlin-native/platformLibs/src/platform/osx/OpenGLCommon.def b/kotlin-native/platformLibs/src/platform/osx/OpenGLCommon.def new file mode 100644 index 00000000000..df4035ab634 --- /dev/null +++ b/kotlin-native/platformLibs/src/platform/osx/OpenGLCommon.def @@ -0,0 +1,9 @@ +depends = darwin posix +language = Objective-C +package = platform.OpenGLCommon +headers = OpenGL/OpenGL.h + +headerFilter = OpenGL/** + +compilerOpts = -framework OpenGL +linkerOpts = -framework OpenGL diff --git a/kotlin-native/platformLibs/src/platform/osx/PCIDriverKit.def.disabled b/kotlin-native/platformLibs/src/platform/osx/PCIDriverKit.def.disabled new file mode 100644 index 00000000000..b0fbefc1a18 --- /dev/null +++ b/kotlin-native/platformLibs/src/platform/osx/PCIDriverKit.def.disabled @@ -0,0 +1,6 @@ +language = Objective-C +package = platform.PCIDriverKit +modules = PCIDriverKit +compilerOpts = -framework PCIDriverKit +linkerOpts = -framework PCIDriverKit +#Disabled: part of DriverKit diff --git a/kotlin-native/platformLibs/src/platform/osx/PCSC.def.disabled b/kotlin-native/platformLibs/src/platform/osx/PCSC.def.disabled new file mode 100644 index 00000000000..448314c715a --- /dev/null +++ b/kotlin-native/platformLibs/src/platform/osx/PCSC.def.disabled @@ -0,0 +1,6 @@ +language = Objective-C +package = platform.PCSC +modules = PCSC +compilerOpts = -framework PCSC +linkerOpts = -framework PCSC +#Disabled: Unavailable diff --git a/kotlin-native/platformLibs/src/platform/osx/PDFKit.def b/kotlin-native/platformLibs/src/platform/osx/PDFKit.def new file mode 100644 index 00000000000..48cf1ace374 --- /dev/null +++ b/kotlin-native/platformLibs/src/platform/osx/PDFKit.def @@ -0,0 +1,9 @@ +depends = AppKit ApplicationServices CFNetwork Cocoa CoreData CoreFoundation CoreGraphics CoreImage CoreServices CoreText CoreVideo DiskArbitration Foundation IOKit IOSurface ImageIO Metal OpenGLCommon QuartzCore Security darwin libkern osx posix +language = Objective-C +package = platform.PDFKit +headers = PDFKit/PDFKit.h + +headerFilter = PDFKit/** + +compilerOpts = -framework PDFKit +linkerOpts = -framework PDFKit diff --git a/kotlin-native/platformLibs/src/platform/osx/PencilKit.def b/kotlin-native/platformLibs/src/platform/osx/PencilKit.def new file mode 100644 index 00000000000..8e80ee5a72c --- /dev/null +++ b/kotlin-native/platformLibs/src/platform/osx/PencilKit.def @@ -0,0 +1,7 @@ +depends = AppKit ApplicationServices CFNetwork Cocoa CoreData CoreFoundation CoreGraphics CoreImage CoreServices CoreText CoreVideo DiskArbitration Foundation IOKit IOSurface ImageIO Metal OpenGLCommon QuartzCore Security darwin libkern osx posix +language = Objective-C +package = platform.PencilKit +modules = PencilKit + +compilerOpts = -framework PencilKit +linkerOpts = -framework PencilKit diff --git a/kotlin-native/platformLibs/src/platform/osx/Photos.def b/kotlin-native/platformLibs/src/platform/osx/Photos.def new file mode 100644 index 00000000000..25ec05f409e --- /dev/null +++ b/kotlin-native/platformLibs/src/platform/osx/Photos.def @@ -0,0 +1,12 @@ +depends = AVFoundation ApplicationServices AudioToolbox CFNetwork CoreAudio CoreAudioTypes CoreFoundation CoreGraphics CoreImage CoreLocation CoreMIDI CoreMedia CoreServices CoreText CoreVideo DiskArbitration Foundation IOKit IOSurface ImageIO MediaToolbox Metal OpenGLCommon QuartzCore Security darwin libkern osx posix +language = Objective-C +package = platform.Photos +modules = Photos + +compilerOpts = -framework Photos +linkerOpts = -framework Photos +--- +// TODO: ugly hack while forwarded enums are supported. +typedef NS_ENUM(NSInteger, UIImageOrientation) { + UIImageOrientationUnavailableOnMacOS +}; diff --git a/kotlin-native/platformLibs/src/platform/osx/PhotosUI.def b/kotlin-native/platformLibs/src/platform/osx/PhotosUI.def new file mode 100644 index 00000000000..5698e6aa0e3 --- /dev/null +++ b/kotlin-native/platformLibs/src/platform/osx/PhotosUI.def @@ -0,0 +1,7 @@ +depends = AppKit ApplicationServices CFNetwork CoreData CoreFoundation CoreGraphics CoreImage CoreLocation CoreServices CoreText CoreVideo DiskArbitration Foundation IOKit IOSurface ImageIO MapKit Metal OpenGLCommon Photos QuartzCore Security darwin libkern osx posix +language = Objective-C +package = platform.PhotosUI +modules = PhotosUI + +compilerOpts = -framework PhotosUI +linkerOpts = -framework PhotosUI diff --git a/kotlin-native/platformLibs/src/platform/osx/PreferencePanes.def b/kotlin-native/platformLibs/src/platform/osx/PreferencePanes.def new file mode 100644 index 00000000000..c7bd08decfa --- /dev/null +++ b/kotlin-native/platformLibs/src/platform/osx/PreferencePanes.def @@ -0,0 +1,7 @@ +depends = AppKit ApplicationServices CFNetwork Cocoa CoreData CoreFoundation CoreGraphics CoreImage CoreServices CoreText CoreVideo DiskArbitration Foundation IOKit IOSurface ImageIO Metal OpenGLCommon QuartzCore Security darwin libkern osx posix +language = Objective-C +package = platform.PreferencePanes +modules = PreferencePanes + +compilerOpts = -framework PreferencePanes +linkerOpts = -framework PreferencePanes diff --git a/kotlin-native/platformLibs/src/platform/osx/PushKit.def b/kotlin-native/platformLibs/src/platform/osx/PushKit.def new file mode 100644 index 00000000000..d7c50dce7d1 --- /dev/null +++ b/kotlin-native/platformLibs/src/platform/osx/PushKit.def @@ -0,0 +1,7 @@ +depends = ApplicationServices CFNetwork CoreFoundation CoreGraphics CoreServices CoreText DiskArbitration Foundation IOKit ImageIO Security darwin libkern osx posix +language = Objective-C +package = platform.PushKit +modules = PushKit + +compilerOpts = -framework PushKit +linkerOpts = -framework PushKit diff --git a/kotlin-native/platformLibs/src/platform/osx/Python.def.disabled b/kotlin-native/platformLibs/src/platform/osx/Python.def.disabled new file mode 100644 index 00000000000..cb9a556a5e7 --- /dev/null +++ b/kotlin-native/platformLibs/src/platform/osx/Python.def.disabled @@ -0,0 +1,6 @@ +language = Objective-C +package = platform.Python +modules = Python +compilerOpts = -framework Python +linkerOpts = -framework Python +#Disabled: Unavailable diff --git a/kotlin-native/platformLibs/src/platform/osx/QTKit.def.disabled b/kotlin-native/platformLibs/src/platform/osx/QTKit.def.disabled new file mode 100644 index 00000000000..345efc31f8c --- /dev/null +++ b/kotlin-native/platformLibs/src/platform/osx/QTKit.def.disabled @@ -0,0 +1,6 @@ +language = Objective-C +package = platform.QTKit +modules = QTKit +compilerOpts = -framework QTKit +linkerOpts = -framework QTKit +#Disabled: Unavailable diff --git a/kotlin-native/platformLibs/src/platform/osx/Quartz.def b/kotlin-native/platformLibs/src/platform/osx/Quartz.def new file mode 100644 index 00000000000..18a50e0b6de --- /dev/null +++ b/kotlin-native/platformLibs/src/platform/osx/Quartz.def @@ -0,0 +1,9 @@ +depends = AppKit ApplicationServices CFNetwork Cocoa CoreData CoreFoundation CoreGraphics CoreImage CoreServices CoreText CoreVideo DiskArbitration Foundation IOKit IOSurface ImageCaptureCore ImageIO Metal OpenGL OpenGLCommon PDFKit QuartzCore QuickLook Security darwin libkern osx posix +language = Objective-C +package = platform.Quartz +modules = Quartz + +compilerOpts = -framework Quartz +linkerOpts = -framework Quartz + +excludedFunctions = QCCompositionInputRSSArticleDurationKey QCCompositionInputRSSFeedURLKey QCCompositionProtocolRSSVisualizer diff --git a/kotlin-native/platformLibs/src/platform/osx/QuartzCore.def b/kotlin-native/platformLibs/src/platform/osx/QuartzCore.def new file mode 100644 index 00000000000..371b83a0f91 --- /dev/null +++ b/kotlin-native/platformLibs/src/platform/osx/QuartzCore.def @@ -0,0 +1,7 @@ +depends = ApplicationServices CFNetwork CoreFoundation CoreGraphics CoreImage CoreServices CoreText CoreVideo DiskArbitration Foundation IOKit IOSurface ImageIO Metal OpenGLCommon Security darwin libkern osx posix +language = Objective-C +package = platform.QuartzCore +modules = QuartzCore + +compilerOpts = -framework QuartzCore +linkerOpts = -framework QuartzCore diff --git a/kotlin-native/platformLibs/src/platform/osx/QuickLook.def b/kotlin-native/platformLibs/src/platform/osx/QuickLook.def new file mode 100644 index 00000000000..3406a35a306 --- /dev/null +++ b/kotlin-native/platformLibs/src/platform/osx/QuickLook.def @@ -0,0 +1,7 @@ +depends = ApplicationServices CFNetwork CoreFoundation CoreGraphics CoreServices CoreText DiskArbitration IOKit ImageIO Security darwin libkern osx posix +language = Objective-C +package = platform.QuickLook +modules = QuickLook + +compilerOpts = -framework QuickLook +linkerOpts = -framework QuickLook diff --git a/kotlin-native/platformLibs/src/platform/osx/QuickLookThumbnailing.def b/kotlin-native/platformLibs/src/platform/osx/QuickLookThumbnailing.def new file mode 100644 index 00000000000..7126b6b8dac --- /dev/null +++ b/kotlin-native/platformLibs/src/platform/osx/QuickLookThumbnailing.def @@ -0,0 +1,7 @@ +depends = ApplicationServices CFNetwork CoreFoundation CoreGraphics CoreServices CoreText DiskArbitration Foundation IOKit ImageIO Security darwin libkern osx posix +language = Objective-C +package = platform.QuickLookThumbnailing +modules = QuickLookThumbnailing + +compilerOpts = -framework QuickLookThumbnailing +linkerOpts = -framework QuickLookThumbnailing diff --git a/kotlin-native/platformLibs/src/platform/osx/RealityKit.def.disabled b/kotlin-native/platformLibs/src/platform/osx/RealityKit.def.disabled new file mode 100644 index 00000000000..31a0bfa9ad1 --- /dev/null +++ b/kotlin-native/platformLibs/src/platform/osx/RealityKit.def.disabled @@ -0,0 +1,6 @@ +language = Objective-C +package = platform.RealityKit +modules = RealityKit +compilerOpts = -framework RealityKit +linkerOpts = -framework RealityKit +#Disabled: Swift-only framework diff --git a/kotlin-native/platformLibs/src/platform/osx/Ruby.def.disabled b/kotlin-native/platformLibs/src/platform/osx/Ruby.def.disabled new file mode 100644 index 00000000000..20bc5140c22 --- /dev/null +++ b/kotlin-native/platformLibs/src/platform/osx/Ruby.def.disabled @@ -0,0 +1,6 @@ +language = Objective-C +package = platform.Ruby +modules = Ruby +compilerOpts = -framework Ruby +linkerOpts = -framework Ruby +#Disabled: Unavailable diff --git a/kotlin-native/platformLibs/src/platform/osx/SafariServices.def b/kotlin-native/platformLibs/src/platform/osx/SafariServices.def new file mode 100644 index 00000000000..ed088288601 --- /dev/null +++ b/kotlin-native/platformLibs/src/platform/osx/SafariServices.def @@ -0,0 +1,7 @@ +depends = AppKit ApplicationServices CFNetwork CoreData CoreFoundation CoreGraphics CoreServices CoreText DiskArbitration Foundation IOKit ImageIO Security darwin libkern osx posix +language = Objective-C +package = platform.SafariServices +modules = SafariServices + +compilerOpts = -framework SafariServices +linkerOpts = -framework SafariServices diff --git a/kotlin-native/platformLibs/src/platform/osx/SceneKit.def b/kotlin-native/platformLibs/src/platform/osx/SceneKit.def new file mode 100644 index 00000000000..53ca1656f46 --- /dev/null +++ b/kotlin-native/platformLibs/src/platform/osx/SceneKit.def @@ -0,0 +1,7 @@ +depends = AppKit ApplicationServices CFNetwork CoreData CoreFoundation CoreGraphics CoreImage CoreServices CoreText CoreVideo DiskArbitration Foundation GLKit IOKit IOSurface ImageIO Metal ModelIO OpenGLCommon QuartzCore Security darwin libkern osx posix +language = Objective-C +package = platform.SceneKit +modules = SceneKit + +compilerOpts = -framework SceneKit +linkerOpts = -framework SceneKit diff --git a/kotlin-native/platformLibs/src/platform/osx/ScreenSaver.def b/kotlin-native/platformLibs/src/platform/osx/ScreenSaver.def new file mode 100644 index 00000000000..a4094b1d26f --- /dev/null +++ b/kotlin-native/platformLibs/src/platform/osx/ScreenSaver.def @@ -0,0 +1,7 @@ +depends = AppKit ApplicationServices CFNetwork CoreData CoreFoundation CoreGraphics CoreImage CoreServices CoreText CoreVideo DiskArbitration Foundation IOKit IOSurface ImageIO Metal OpenGLCommon QuartzCore Security darwin libkern osx posix +language = Objective-C +package = platform.ScreenSaver +modules = ScreenSaver + +compilerOpts = -framework ScreenSaver +linkerOpts = -framework ScreenSaver diff --git a/kotlin-native/platformLibs/src/platform/osx/ScriptingBridge.def b/kotlin-native/platformLibs/src/platform/osx/ScriptingBridge.def new file mode 100644 index 00000000000..86380141db7 --- /dev/null +++ b/kotlin-native/platformLibs/src/platform/osx/ScriptingBridge.def @@ -0,0 +1,7 @@ +depends = ApplicationServices CFNetwork CoreFoundation CoreGraphics CoreServices CoreText DiskArbitration Foundation IOKit ImageIO Security darwin libkern osx posix +language = Objective-C +package = platform.ScriptingBridge +modules = ScriptingBridge + +compilerOpts = -framework ScriptingBridge +linkerOpts = -framework ScriptingBridge diff --git a/kotlin-native/platformLibs/src/platform/osx/Security.def b/kotlin-native/platformLibs/src/platform/osx/Security.def new file mode 100644 index 00000000000..015354f3542 --- /dev/null +++ b/kotlin-native/platformLibs/src/platform/osx/Security.def @@ -0,0 +1,25 @@ +depends = CoreFoundation darwin posix +language = Objective-C +package = platform.Security +modules = Security + +excludedFunctions = CSSMOID_APPLE_EXTENSION_DEVELOPER_AUTHENTICATION CSSMOID_APPLE_EXTENSION_PROVISIONING_PROFILE_SIGNING \ + CSSMOID_APPLE_EXTENSION_SERVER_AUTHENTICATION CSSMOID_APPLE_TP_PCS_ESCROW_SERVICE \ + CSSMOID_APPLE_TP_PROVISIONING_PROFILE_SIGNING CSSMOID_DES_CBC CSSMOID_DomainComponent CSSMOID_InhibitAnyPolicy \ + CSSM_KR_CreateRecoveryEnablementContext CSSM_KR_CreateRecoveryRegistrationContext CSSM_KR_CreateRecoveryRequestContext \ + CSSM_KR_GenerateRecoveryFields CSSM_KR_GetPolicyInfo CSSM_KR_GetRecoveredObject CSSM_KR_PassThrough \ + CSSM_KR_ProcessRecoveryFields CSSM_KR_QueryPolicyInfo CSSM_KR_RecoveryRequest CSSM_KR_RecoveryRequestAbort \ + CSSM_KR_RecoveryRetrieve CSSM_KR_RegistrationRequest CSSM_KR_RegistrationRetrieve CSSM_KR_SetEnterpriseRecoveryPolicy \ + CSSM_SPI_ModuleAttach CSSM_SPI_ModuleDetach CSSM_SPI_ModuleLoad CSSM_SPI_ModuleUnload ModuleManagerAuthenticate \ + SecDecryptTransformGetTypeID SecDigestTransformGetTypeID SecEncryptTransformGetTypeID kSecACLAuthorizationChangeACL \ + kSecACLAuthorizationChangeOwner kSecCertificateUsageDeriveAndSign kSecCertificateUsageSigning \ + kSecCertificateUsageSigningAndEncrypting kSecCodeInfoPlatformIdentifier kSecGuestAttributeArchitecture \ + kSecGuestAttributeSubarchitecture kSecOAEPMGF1DigestAlgorithmAttributeName kSecOAEPMessageLengthAttributeName \ + kSecOIDAPPLE_EXTENSION_AAI_INTERMEDIATE kSecOIDAPPLE_EXTENSION_APPLEID_INTERMEDIATE \ + kSecOIDAPPLE_EXTENSION_INTERMEDIATE_MARKER kSecOIDAPPLE_EXTENSION_ITMS_INTERMEDIATE \ + kSecOIDAPPLE_EXTENSION_WWDR_INTERMEDIATE kSecPolicyAppleiChat oidAnsip384r1 oidAnsip521r1 oidEcPrime192v1 \ + oidEcPrime256v1 oidExtendedKeyUsageTimeStamping oidNameConstraints AuthorizationPluginCreate + + +compilerOpts = -framework Security +linkerOpts = -framework Security diff --git a/kotlin-native/platformLibs/src/platform/osx/SecurityFoundation.def b/kotlin-native/platformLibs/src/platform/osx/SecurityFoundation.def new file mode 100644 index 00000000000..aa529f3d295 --- /dev/null +++ b/kotlin-native/platformLibs/src/platform/osx/SecurityFoundation.def @@ -0,0 +1,7 @@ +depends = ApplicationServices CFNetwork CoreFoundation CoreGraphics CoreServices CoreText DiskArbitration Foundation IOKit ImageIO Security darwin libkern osx posix +language = Objective-C +package = platform.SecurityFoundation +modules = SecurityFoundation + +compilerOpts = -framework SecurityFoundation +linkerOpts = -framework SecurityFoundation diff --git a/kotlin-native/platformLibs/src/platform/osx/SecurityInterface.def b/kotlin-native/platformLibs/src/platform/osx/SecurityInterface.def new file mode 100644 index 00000000000..790287e1cf1 --- /dev/null +++ b/kotlin-native/platformLibs/src/platform/osx/SecurityInterface.def @@ -0,0 +1,7 @@ +depends = AppKit ApplicationServices CFNetwork Cocoa CoreData CoreFoundation CoreGraphics CoreImage CoreServices CoreText CoreVideo DiskArbitration Foundation IOKit IOSurface ImageIO Metal OpenGLCommon QuartzCore Security SecurityFoundation darwin libkern osx posix +language = Objective-C +package = platform.SecurityInterface +modules = SecurityInterface + +compilerOpts = -framework SecurityInterface +linkerOpts = -framework SecurityInterface diff --git a/kotlin-native/platformLibs/src/platform/osx/ServiceManagement.def b/kotlin-native/platformLibs/src/platform/osx/ServiceManagement.def new file mode 100644 index 00000000000..2d2cb9443ac --- /dev/null +++ b/kotlin-native/platformLibs/src/platform/osx/ServiceManagement.def @@ -0,0 +1,7 @@ +depends = CoreFoundation Security darwin posix +language = Objective-C +package = platform.ServiceManagement +modules = ServiceManagement + +compilerOpts = -framework ServiceManagement +linkerOpts = -framework ServiceManagement diff --git a/kotlin-native/platformLibs/src/platform/osx/Social.def b/kotlin-native/platformLibs/src/platform/osx/Social.def new file mode 100644 index 00000000000..b6fbb826137 --- /dev/null +++ b/kotlin-native/platformLibs/src/platform/osx/Social.def @@ -0,0 +1,7 @@ +depends = AppKit ApplicationServices CFNetwork CoreData CoreFoundation CoreGraphics CoreImage CoreServices CoreText CoreVideo DiskArbitration Foundation IOKit IOSurface ImageIO Metal OpenGLCommon QuartzCore Security darwin libkern osx posix +language = Objective-C +package = platform.Social +modules = Social + +compilerOpts = -framework Social +linkerOpts = -framework Social diff --git a/kotlin-native/platformLibs/src/platform/osx/SoundAnalysis.def b/kotlin-native/platformLibs/src/platform/osx/SoundAnalysis.def new file mode 100644 index 00000000000..a845994d0aa --- /dev/null +++ b/kotlin-native/platformLibs/src/platform/osx/SoundAnalysis.def @@ -0,0 +1,7 @@ +depends = AVFoundation ApplicationServices AudioToolbox CFNetwork CoreAudio CoreAudioTypes CoreFoundation CoreGraphics CoreImage CoreMIDI CoreML CoreMedia CoreServices CoreText CoreVideo DiskArbitration Foundation IOKit IOSurface ImageIO MediaToolbox Metal OpenGLCommon QuartzCore Security darwin libkern osx posix +language = Objective-C +package = platform.SoundAnalysis +modules = SoundAnalysis + +compilerOpts = -framework SoundAnalysis +linkerOpts = -framework SoundAnalysis diff --git a/kotlin-native/platformLibs/src/platform/osx/Speech.def b/kotlin-native/platformLibs/src/platform/osx/Speech.def new file mode 100644 index 00000000000..7ad2c82044c --- /dev/null +++ b/kotlin-native/platformLibs/src/platform/osx/Speech.def @@ -0,0 +1,7 @@ +depends = AVFoundation ApplicationServices AudioToolbox CFNetwork CoreAudio CoreAudioTypes CoreFoundation CoreGraphics CoreImage CoreMIDI CoreMedia CoreServices CoreText CoreVideo DiskArbitration Foundation IOKit IOSurface ImageIO MediaToolbox Metal OpenGLCommon QuartzCore Security darwin libkern osx posix +language = Objective-C +package = platform.Speech +modules = Speech + +compilerOpts = -framework Speech +linkerOpts = -framework Speech diff --git a/kotlin-native/platformLibs/src/platform/osx/SpriteKit.def b/kotlin-native/platformLibs/src/platform/osx/SpriteKit.def new file mode 100644 index 00000000000..1710c7f2968 --- /dev/null +++ b/kotlin-native/platformLibs/src/platform/osx/SpriteKit.def @@ -0,0 +1,7 @@ +depends = AppKit ApplicationServices CFNetwork Cocoa CoreData CoreFoundation CoreGraphics CoreImage CoreServices CoreText CoreVideo DiskArbitration Foundation GLKit IOKit IOSurface ImageIO Metal OpenGLCommon QuartzCore Security darwin libkern osx posix +language = Objective-C +package = platform.SpriteKit +modules = SpriteKit + +compilerOpts = -framework SpriteKit +linkerOpts = -framework SpriteKit diff --git a/kotlin-native/platformLibs/src/platform/osx/StoreKit.def b/kotlin-native/platformLibs/src/platform/osx/StoreKit.def new file mode 100644 index 00000000000..e2755efa6a8 --- /dev/null +++ b/kotlin-native/platformLibs/src/platform/osx/StoreKit.def @@ -0,0 +1,7 @@ +depends = AppKit ApplicationServices CFNetwork CoreData CoreFoundation CoreGraphics CoreImage CoreServices CoreText CoreVideo DiskArbitration Foundation IOKit IOSurface ImageIO Metal OpenGLCommon QuartzCore Security darwin libkern osx posix +language = Objective-C +package = platform.StoreKit +modules = StoreKit + +compilerOpts = -framework StoreKit +linkerOpts = -framework StoreKit diff --git a/kotlin-native/platformLibs/src/platform/osx/SwiftUI.def.disabled b/kotlin-native/platformLibs/src/platform/osx/SwiftUI.def.disabled new file mode 100644 index 00000000000..59c29eff39e --- /dev/null +++ b/kotlin-native/platformLibs/src/platform/osx/SwiftUI.def.disabled @@ -0,0 +1,6 @@ +language = Objective-C +package = platform.SwiftUI +modules = SwiftUI +compilerOpts = -framework SwiftUI +linkerOpts = -framework SwiftUI +#Disabled: Swift-only framework diff --git a/kotlin-native/platformLibs/src/platform/osx/SyncServices.def.disabled b/kotlin-native/platformLibs/src/platform/osx/SyncServices.def.disabled new file mode 100644 index 00000000000..8876f9bab10 --- /dev/null +++ b/kotlin-native/platformLibs/src/platform/osx/SyncServices.def.disabled @@ -0,0 +1,6 @@ +language = Objective-C +package = platform.SyncServices +modules = SyncServices +compilerOpts = -framework SyncServices +linkerOpts = -framework SyncServices +#Disabled: Deprecated in 10.7 diff --git a/kotlin-native/platformLibs/src/platform/osx/System.def.disabled b/kotlin-native/platformLibs/src/platform/osx/System.def.disabled new file mode 100644 index 00000000000..55b772ae7b6 --- /dev/null +++ b/kotlin-native/platformLibs/src/platform/osx/System.def.disabled @@ -0,0 +1,6 @@ +language = Objective-C +package = platform.System +modules = System +compilerOpts = -framework System +linkerOpts = -framework System +#Disabled: Swift-only framework diff --git a/kotlin-native/platformLibs/src/platform/osx/SystemConfiguration.def b/kotlin-native/platformLibs/src/platform/osx/SystemConfiguration.def new file mode 100644 index 00000000000..e9ebe46aa7f --- /dev/null +++ b/kotlin-native/platformLibs/src/platform/osx/SystemConfiguration.def @@ -0,0 +1,7 @@ +depends = CoreFoundation Security darwin posix +language = Objective-C +package = platform.SystemConfiguration +modules = SystemConfiguration + +compilerOpts = -framework SystemConfiguration +linkerOpts = -framework SystemConfiguration diff --git a/kotlin-native/platformLibs/src/platform/osx/SystemExtensions.def b/kotlin-native/platformLibs/src/platform/osx/SystemExtensions.def new file mode 100644 index 00000000000..34f7bba3638 --- /dev/null +++ b/kotlin-native/platformLibs/src/platform/osx/SystemExtensions.def @@ -0,0 +1,7 @@ +depends = ApplicationServices CFNetwork CoreFoundation CoreGraphics CoreServices CoreText DiskArbitration Foundation IOKit ImageIO Security darwin libkern osx posix +language = Objective-C +package = platform.SystemExtensions +modules = SystemExtensions + +compilerOpts = -framework SystemExtensions +linkerOpts = -framework SystemExtensions diff --git a/kotlin-native/platformLibs/src/platform/osx/TWAIN.def.disabled b/kotlin-native/platformLibs/src/platform/osx/TWAIN.def.disabled new file mode 100644 index 00000000000..5395e7255bd --- /dev/null +++ b/kotlin-native/platformLibs/src/platform/osx/TWAIN.def.disabled @@ -0,0 +1,6 @@ +language = Objective-C +package = platform.TWAIN +modules = TWAIN +compilerOpts = -framework TWAIN +linkerOpts = -framework TWAIN +#Disabled: Unavailable diff --git a/kotlin-native/platformLibs/src/platform/osx/Tcl.def.disabled b/kotlin-native/platformLibs/src/platform/osx/Tcl.def.disabled new file mode 100644 index 00000000000..8017b241cc3 --- /dev/null +++ b/kotlin-native/platformLibs/src/platform/osx/Tcl.def.disabled @@ -0,0 +1,6 @@ +language = Objective-C +package = platform.Tcl +modules = Tcl +compilerOpts = -framework Tcl +linkerOpts = -framework Tcl +#Disabled: Unavailable diff --git a/kotlin-native/platformLibs/src/platform/osx/Tk.def.disabled b/kotlin-native/platformLibs/src/platform/osx/Tk.def.disabled new file mode 100644 index 00000000000..011f3080009 --- /dev/null +++ b/kotlin-native/platformLibs/src/platform/osx/Tk.def.disabled @@ -0,0 +1,6 @@ +language = Objective-C +package = platform.Tk +modules = Tk +compilerOpts = -framework Tk +linkerOpts = -framework Tk +#Disabled: Unavailable diff --git a/kotlin-native/platformLibs/src/platform/osx/USBDriverKit.def.disabled b/kotlin-native/platformLibs/src/platform/osx/USBDriverKit.def.disabled new file mode 100644 index 00000000000..17bd8e8b42d --- /dev/null +++ b/kotlin-native/platformLibs/src/platform/osx/USBDriverKit.def.disabled @@ -0,0 +1,6 @@ +language = Objective-C +package = platform.USBDriverKit +modules = USBDriverKit +compilerOpts = -framework USBDriverKit +linkerOpts = -framework USBDriverKit +#Disabled: part of DriverKit diff --git a/kotlin-native/platformLibs/src/platform/osx/UserNotifications.def b/kotlin-native/platformLibs/src/platform/osx/UserNotifications.def new file mode 100644 index 00000000000..761a5d9ee78 --- /dev/null +++ b/kotlin-native/platformLibs/src/platform/osx/UserNotifications.def @@ -0,0 +1,7 @@ +depends = ApplicationServices CFNetwork CoreFoundation CoreGraphics CoreServices CoreText DiskArbitration Foundation IOKit ImageIO Security darwin libkern osx posix +language = Objective-C +package = platform.UserNotifications +modules = UserNotifications + +compilerOpts = -framework UserNotifications +linkerOpts = -framework UserNotifications diff --git a/kotlin-native/platformLibs/src/platform/osx/VideoDecodeAcceleration.def.disabled b/kotlin-native/platformLibs/src/platform/osx/VideoDecodeAcceleration.def.disabled new file mode 100644 index 00000000000..6c0a9c86975 --- /dev/null +++ b/kotlin-native/platformLibs/src/platform/osx/VideoDecodeAcceleration.def.disabled @@ -0,0 +1,6 @@ +language = Objective-C +package = platform.VideoDecodeAcceleration +modules = VideoDecodeAcceleration +compilerOpts = -framework VideoDecodeAcceleration +linkerOpts = -framework VideoDecodeAcceleration +#Disabled: Unavailable diff --git a/kotlin-native/platformLibs/src/platform/osx/VideoSubscriberAccount.def b/kotlin-native/platformLibs/src/platform/osx/VideoSubscriberAccount.def new file mode 100644 index 00000000000..16745b5b379 --- /dev/null +++ b/kotlin-native/platformLibs/src/platform/osx/VideoSubscriberAccount.def @@ -0,0 +1,6 @@ +depends = CoreFoundation Foundation darwin posix +language = Objective-C +package = platform.VideoSubscriberAccount +modules = VideoSubscriberAccount +compilerOpts = -framework VideoSubscriberAccount +linkerOpts = -framework VideoSubscriberAccount diff --git a/kotlin-native/platformLibs/src/platform/osx/VideoToolbox.def b/kotlin-native/platformLibs/src/platform/osx/VideoToolbox.def new file mode 100644 index 00000000000..c2b17106092 --- /dev/null +++ b/kotlin-native/platformLibs/src/platform/osx/VideoToolbox.def @@ -0,0 +1,7 @@ +depends = ApplicationServices CFNetwork CoreAudio CoreAudioTypes CoreFoundation CoreGraphics CoreMedia CoreServices CoreText CoreVideo DiskArbitration Foundation IOKit IOSurface ImageIO Metal OpenGLCommon Security darwin libkern osx posix +language = Objective-C +package = platform.VideoToolbox +modules = VideoToolbox + +compilerOpts = -framework VideoToolbox +linkerOpts = -framework VideoToolbox diff --git a/kotlin-native/platformLibs/src/platform/osx/Vision.def b/kotlin-native/platformLibs/src/platform/osx/Vision.def new file mode 100644 index 00000000000..d826d9910ae --- /dev/null +++ b/kotlin-native/platformLibs/src/platform/osx/Vision.def @@ -0,0 +1,7 @@ +depends = ApplicationServices CFNetwork CoreFoundation CoreGraphics CoreML CoreServices CoreText CoreVideo DiskArbitration Foundation IOKit IOSurface ImageIO Metal Security darwin libkern osx posix +language = Objective-C +package = platform.Vision +modules = Vision + +compilerOpts = -framework Vision +linkerOpts = -framework Vision diff --git a/kotlin-native/platformLibs/src/platform/osx/WebKit.def b/kotlin-native/platformLibs/src/platform/osx/WebKit.def new file mode 100644 index 00000000000..2bdb96aaee9 --- /dev/null +++ b/kotlin-native/platformLibs/src/platform/osx/WebKit.def @@ -0,0 +1,23 @@ +depends = AppKit ApplicationServices CFNetwork CoreData CoreFoundation CoreGraphics CoreImage CoreServices CoreText CoreVideo DiskArbitration Foundation IOKit IOSurface ImageIO JavaScriptCore Metal OpenGLCommon QuartzCore Security darwin libkern osx posix +language = Objective-C +package = platform.WebKit +modules = WebKit + +compilerOpts = -framework WebKit +linkerOpts = -framework WebKit + +excludedFunctions = NPN_Construct NPN_ConvertPoint NPN_CreateObject NPN_DestroyStream NPN_Enumerate \ + NPN_Evaluate NPN_ForceRedraw NPN_GetAuthenticationInfo NPN_GetIntIdentifier \ + NPN_GetJavaEnv NPN_GetJavaPeer NPN_GetProperty NPN_GetStringIdentifier \ + NPN_GetStringIdentifiers NPN_GetURL NPN_GetURLNotify NPN_GetValue NPN_GetValueForURL \ + NPN_HandleEvent NPN_HasMethod NPN_HasProperty NPN_IdentifierIsString NPN_IntFromIdentifier \ + NPN_InvalidateRect NPN_InvalidateRegion NPN_Invoke NPN_InvokeDefault NPN_MemAlloc \ + NPN_MemFlush NPN_MemFree NPN_NewStream NPN_PluginThreadAsyncCall NPN_PopPopupsEnabledState \ + NPN_PopUpContextMenu NPN_PostURL NPN_PostURLNotify NPN_PushPopupsEnabledState NPN_ReleaseObject \ + NPN_ReleaseVariantValue NPN_ReloadPlugins NPN_RemoveProperty NPN_RequestRead NPN_RetainObject \ + NPN_ScheduleTimer NPN_SetException NPN_SetProperty NPN_SetValue NPN_SetValueForURL NPN_Status \ + NPN_URLRedirectResponse NPN_UTF8FromIdentifier NPN_UnfocusInstance NPN_UnscheduleTimer \ + NPN_UserAgent NPN_Version NPN_Write NPP_ClearSiteData NPP_Destroy NPP_DestroyStream \ + NPP_GetJavaClass NPP_GetSitesWithData NPP_GetValue NPP_GotFocus NPP_HandleEvent NPP_Initialize \ + NPP_LostFocus NPP_New NPP_NewStream NPP_Print NPP_SetValue NPP_SetWindow NPP_Shutdown \ + NPP_StreamAsFile NPP_URLNotify NPP_URLRedirectNotify NPP_Write NPP_WriteReady diff --git a/kotlin-native/platformLibs/src/platform/osx/builtin.def b/kotlin-native/platformLibs/src/platform/osx/builtin.def new file mode 100644 index 00000000000..8f0c34815d7 --- /dev/null +++ b/kotlin-native/platformLibs/src/platform/osx/builtin.def @@ -0,0 +1,98 @@ +depends = posix +package = platform.builtin +headerFilter = ** +language = C +--- +// See https://github.com/llvm-mirror/clang/blob/master/include/clang/Basic/Builtins.def +// TODO: autogenerate from machine format. + +// Returns x with the order of the bytes reversed; for example, 0xaabb becomes 0xbbaa. Byte here always means exactly 8 bits. +static inline short builtin_bswap16(short x) { + return __builtin_bswap16(x); +} + +static inline int builtin_bswap32(int x) { + return __builtin_bswap32(x); +} + +static inline long long builtin_bswap64(long long x) { + return __builtin_bswap64(x); +} + +// Returns the number of leading 0-bits in x, starting at the most significant bit position. If x is 0, the result is undefined. +static inline int builtin_clzs(unsigned short x) { + return __builtin_clzs(x); +} + +static inline int builtin_clz(unsigned int x) { + return __builtin_clz(x); +} + +static inline int builtin_clzl(unsigned long x) { + return __builtin_clzl(x); +} + +static inline int builtin_clzll(unsigned long long x) { + return __builtin_clzll(x); +} + +// Returns the number of trailing 0-bits in x, starting at the least significant bit position. If x is 0, the result is undefined. +static inline int builtin_ctzs(unsigned short x) { + return __builtin_ctzs(x); +} + +static inline int builtin_ctz(unsigned int x) { + return __builtin_ctz(x); +} + +static inline int builtin_ctzl(unsigned long x) { + return __builtin_ctzl(x); +} + +static inline int builtin_ctzll(unsigned long long x) { + return __builtin_ctzll(x); +} + +// Returns one plus the index of the least significant 1-bit of x, or if x is zero, returns zero. +static inline int builtin_ffs(int x) { + return __builtin_ffs(x); +} + +static inline int builtin_ffsl(long x) { + return __builtin_ffsl(x); +} + +static inline int builtin_ffsll(long long x) { + return __builtin_ffsll(x); +} + +// Returns the parity of x, i.e. the number of 1-bits in x modulo 2. +static inline int builtin_parity(int x) { + return __builtin_parity(x); +} + +static inline int builtin_parityl(unsigned long x) { + return __builtin_parityl(x); +} + +static inline int builtin_parityll(unsigned long long x) { + return __builtin_parityll(x); +} + +// Returns the number of 1-bits in x. +static inline int builtin_popcount(int x) { + return __builtin_popcount(x); +} + +static inline int builtin_popcountl(long x) { + return __builtin_popcountl(x); +} + +static inline int builtin_popcountll(long long x) { + return __builtin_popcountll(x); +} + +// This function is used to flush the processor's instruction cache for the region of memory between begin inclusive and end exclusive. +static inline void builtin_clear_cache(void* begin, void* end) { + __builtin___clear_cache(begin, end); +} diff --git a/kotlin-native/platformLibs/src/platform/osx/darwin.def b/kotlin-native/platformLibs/src/platform/osx/darwin.def new file mode 100644 index 00000000000..1046f7be415 --- /dev/null +++ b/kotlin-native/platformLibs/src/platform/osx/darwin.def @@ -0,0 +1,42 @@ +depends = posix +language = Objective-C +package = platform.darwin +headers = AppleTextureEncoder.h AssertMacros.h Availability.h AvailabilityInternal.h \ + AvailabilityMacros.h Block.h ConditionalMacros.h MacTypes.h \ + TargetConditionals.h __cxxabi_config.h _locale.h _types.h _wctype.h \ + aio.h asl.h bitstring.h bzlib.h \ + cache.h cache_callbacks.h checkint.h compression.h copyfile.h \ + cpio.h cxxabi.h db.h \ + dns.h dns_sd.h dns_util.h execinfo.h \ + fmtmsg.h fstab.h \ + gethostuuid.h glob.h ifaddrs.h inttypes.h iso646.h \ + langinfo.h \ + libgen.h libunwind.h \ + membership.h monetary.h mpool.h \ + nameser.h ndbm.h nl_types.h \ + notify.h notify_keys.h ntsid.h \ + printf.h \ + readpassphrase.h removefile.h \ + runetype.h sandbox.h standards.h \ + stringlist.h sysdir.h sysexits.h tar.h \ + ttyent.h \ + unwind.h util.h utmpx.h vis.h wordexp.h xattr_flags.h \ + bank/bank_types.h \ + bsm/libbsm.h \ + os/activity.h os/availability.h os/base.h os/lock.h \ + os/log.h os/object.h os/overflow.h os/signpost.h os/trace.h \ + simd/simd.h sys/sysctl.h sys/user.h \ + net/if_media.h sys/disk.h sys/kernel_types.h + +headerFilter = ** + +excludedFunctions = __tg_promote KERNEL_AUDIT_TOKEN KERNEL_SECURITY_TOKEN \ + asl_decode_buffer asl_encode_buffer asl_remove_index \ + averunnable dbm_forder pidlock ttyaction ttylock ttymsg ttyunlock uuid_generate_early_random \ + DebugStr Debugger SysBreak SysBreakFunc SysBreakStr clock_get_res clock_set_res \ + mach_vm_region_info mach_vm_region_info_64 os_trace_info_with_payload safe_gets \ + task_wire vm_map_64 vm_map_exec_lockdown vm_mapped_pages_info vm_region vm_region_recurse \ + xpc_debugger_api_misuse_info + +compilerOpts = -D_XOPEN_SOURCE -DSHARED_LIBBIND -D_DARWIN_NO_64_BIT_INODE -DSYSCTL_DEF_ENABLED +linkerOpts = -ldl -lz -lcurses -lbz2 -lcompression -late -lbsm diff --git a/kotlin-native/platformLibs/src/platform/osx/iTunesLibrary.def b/kotlin-native/platformLibs/src/platform/osx/iTunesLibrary.def new file mode 100644 index 00000000000..ec261fd8826 --- /dev/null +++ b/kotlin-native/platformLibs/src/platform/osx/iTunesLibrary.def @@ -0,0 +1,7 @@ +depends = ApplicationServices CFNetwork CoreFoundation CoreGraphics CoreServices CoreText DiskArbitration Foundation IOKit ImageIO Security darwin libkern osx posix +language = Objective-C +package = platform.iTunesLibrary +modules = iTunesLibrary + +compilerOpts = -framework iTunesLibrary +linkerOpts = -framework iTunesLibrary diff --git a/kotlin-native/platformLibs/src/platform/osx/iconv.def b/kotlin-native/platformLibs/src/platform/osx/iconv.def new file mode 100644 index 00000000000..e52d20f4da0 --- /dev/null +++ b/kotlin-native/platformLibs/src/platform/osx/iconv.def @@ -0,0 +1,5 @@ +depends = posix +package = platform.iconv +headers = iconv.h +headerFilter = ** +linkerOpts = -liconv diff --git a/kotlin-native/platformLibs/src/platform/osx/libkern.def b/kotlin-native/platformLibs/src/platform/osx/libkern.def new file mode 100644 index 00000000000..e8baa05489f --- /dev/null +++ b/kotlin-native/platformLibs/src/platform/osx/libkern.def @@ -0,0 +1,9 @@ +depends = darwin posix +language = Objective-C +package = platform.libkern +headers = libkern/OSTypes.h libkern/OSReturn.h libkern/OSAtomic.h device/device_types.h device/device_types.h + +headerFilter = libkern/** device/** + +compilerOpts = -DIOKIT +linkerOpts = diff --git a/kotlin-native/platformLibs/src/platform/osx/objc.def b/kotlin-native/platformLibs/src/platform/osx/objc.def new file mode 100644 index 00000000000..3a7b04e0c72 --- /dev/null +++ b/kotlin-native/platformLibs/src/platform/osx/objc.def @@ -0,0 +1,15 @@ +depends = darwin posix +language = Objective-C +package = platform.objc +headers = objc/List.h objc/NSObjCRuntime.h objc/NSObject.h objc/Object.h objc/Protocol.h \ + objc/hashtable.h objc/hashtable2.h objc/message.h objc/objc-api.h \ + objc/objc-class.h objc/objc-exception.h objc/objc-load.h objc/objc-runtime.h \ + objc/objc-sync.h objc/objc.h objc/runtime.h + +headerFilter = objc/** +compilerOpts = -D_XOPEN_SOURCE +excludedFunctions = KERNEL_AUDIT_TOKEN KERNEL_SECURITY_TOKEN + +linkerOpts = -lobjc +--- +// objc-auto.h is excluded so far due to interop issues. diff --git a/kotlin-native/platformLibs/src/platform/osx/osx.def b/kotlin-native/platformLibs/src/platform/osx/osx.def new file mode 100644 index 00000000000..27ea2f18600 --- /dev/null +++ b/kotlin-native/platformLibs/src/platform/osx/osx.def @@ -0,0 +1,52 @@ +depends = darwin posix +language = Objective-C +package = platform.osx +headers = NSSystemDirectories.h \ + aliasdb.h bootparams.h bootstrap.h \ + com_err.h \ + crt_externs.h \ + disktab.h dtrace.h \ + emmintrin.h eti.h expat.h \ + expat_external.h form.h fsproperties.h get_compat.h \ + gssapi.h histedit.h \ + krb5.h launch.h lber.h lber_types.h ldif.h libc.h libcharset.h \ + libproc.h localcharset.h \ + mmintrin.h monitor.h \ + nc_tparm.h ncurses.h ncurses_dll.h \ + nlist.h \ + panel.h pcap-bpf.h pcap-namedb.h pcap.h printerdb.h \ + profile.h ranlib.h rune.h \ + stab.h strhash.h \ + struct.h term.h \ + term_entry.h termcap.h tic.h timeconv.h tzfile.h \ + unctrl.h vproc.h \ + xmmintrin.h \ + atm/atm_types.h corpses/task_corpse.h \ + hfs/hfs_format.h hfs/hfs_mount.h hfs/hfs_unistr.h \ + sys/kauth.h + +headerFilter = ** + +exportForwardDeclarations = objcnames.classes.NSObject objcnames.protocols.NSObjectProtocol + +compilerOpts = -D_XOPEN_SOURCE +excludedFunctions = KERNEL_AUDIT_TOKEN KERNEL_SECURITY_TOKEN vm_map_64 vm_mapped_pages_info vm_region_recurse vm_region xpc_debugger_api_misuse_info \ + _dtrace_debug _dtrace_mangled _nc_progname _nc_trace_xnames _nc_tracebits _nc_tracef _traceattr2 _tracechar _tracedump _tracef \ + _tracemouse _traceattr _tracechtype _tracechtype2 trace DebugStr Debugger SysBreak SysBreakFunc SysBreakStr \ + asl_decode_buffer asl_encode_buffer asl_remove_index au_to_kevent ber_bvreplace ber_decode_oid ber_encode_oid \ + ber_flush2 ber_peek_element ber_skip_data ber_skip_element ber_sockbuf_io_debug ber_sockbuf_io_fd \ + ber_sockbuf_io_readahead ber_sockbuf_io_tcp ber_sockbuf_io_udp ber_strndup ber_strnlen clock_get_res \ + clock_set_res dbm_forder dns_search_list_domain_count dtrace_aggregate_walk_sorted dtrace_print \ + error_manager et_asn1_error_table et_k524_error_table et_kdb5_error_table et_krb5_error_table et_kv5m_error_table \ + et_prof_error_table gss_export_name_object gss_import_name_object initialize_asn1_error_table initialize_k524_error_table \ + initialize_kdb5_error_table initialize_krb5_error_table initialize_kv5m_error_table initialize_prof_error_table \ + krb5_c_keylengths krb5_c_prf krb5_c_prf_length krb5_c_random_to_key krb5_cc_get_flags krb5_get_fallback_host_realm \ + ldif_debug libcharset_set_relocation_prefix locale_charset mach_vm_region_info mach_vm_region_info_64 map_fd \ + nlist os_trace_info_with_payload safe_gets task_wire trace \ + pcap_createsrcstr pcap_findalldevs_ex pcap_open pcap_parsesrcstr pcap_remoteact_accept pcap_remoteact_cleanup \ + pcap_remoteact_close pcap_remoteact_list pcap_setsampling + +linkerOpts = -late -lbsm -lbz2 -lcompression -ledit -lexpat -lform -lkrb5 -llber -lldap -lncurses -lpanel -lpcap -ldtrace +--- + +// menu.h is excluded so far due to interop issues. diff --git a/kotlin-native/platformLibs/src/platform/osx/posix.def b/kotlin-native/platformLibs/src/platform/osx/posix.def new file mode 100644 index 00000000000..7644686fdc7 --- /dev/null +++ b/kotlin-native/platformLibs/src/platform/osx/posix.def @@ -0,0 +1,65 @@ +depends = +package = platform.posix +headers = alloca.h ar.h assert.h complex.h ctype.h dirent.h dlfcn.h err.h errno.h fcntl.h \ + fenv.h float.h fnmatch.h fts.h ftw.h getopt.h grp.h inttypes.h libgen.h limits.h \ + locale.h math.h memory.h netdb.h paths.h poll.h \ + pthread.h pwd.h regex.h resolv.h sched.h search.h semaphore.h setjmp.h sgtty.h signal.h \ + stdatomic.h stdint.h stdio.h stdlib.h string.h strings.h syslog.h termios.h \ + time.h ucontext.h unistd.h utime.h utmp.h wchar.h wctype.h xlocale.h \ + net/ethernet.h net/if.h net/if_arp.h net/route.h \ + netinet/icmp6.h netinet/if_ether.h netinet/in.h netinet/in_systm.h \ + netinet/ip.h netinet/ip6.h netinet/ip_icmp.h netinet/tcp.h netinet/udp.h \ + sys/acl.h sys/ioctl.h sys/ipc.h sys/mman.h sys/poll.h sys/ptrace.h \ + sys/queue.h sys/select.h sys/shm.h sys/socket.h sys/stat.h \ + sys/syslimits.h sys/time.h sys/times.h sys/utsname.h sys/wait.h + +compilerOpts = -D_XOPEN_SOURCE -DSHARED_LIBBIND -D_DARWIN_NO_64_BIT_INODE -D_DARWIN_C_SOURCE +# -D_ANSI_SOURCE, sigh, breaks user_addr_t +excludedFunctions = KERNEL_AUDIT_TOKEN KERNEL_SECURITY_TOKEN add_profil \ + addrsel_policy_init \ + in6addr_linklocal_allv2routers \ + pfctlinput regwnexec_l res_send_setqhook res_send_setrhook \ + unwhiteout zopen profil openat acl_valid_link_np uuid_generate_early_random setgrfile +linkerOpts = -ldl -lresolv + +--- +// Wrapper to access errno variable. +static int posix_errno() { + return errno; +} + +static void set_posix_errno(int value) { + errno = value; +} + +// Wrapper to access h_errno variable. +static int posix_h_errno() { + return h_errno; +} + +static void set_posix_h_errno(int value) { + h_errno = value; +} + +static short posix_htons(short x) { + return htons(x); +} + +static void posix_FD_ZERO(fd_set *set) { + FD_ZERO(set); +} + +static void posix_FD_SET(int bit, fd_set *set) { + FD_SET(bit, set); +} + +static int posix_FD_ISSET(int bit, fd_set *set) { + return FD_ISSET(bit, set); +} + +static int init_sockets() { + return 0; +} + +static void deinit_sockets() { +} diff --git a/kotlin-native/platformLibs/src/platform/osx/set_depends.sh b/kotlin-native/platformLibs/src/platform/osx/set_depends.sh new file mode 100755 index 00000000000..4e6c366dfd1 --- /dev/null +++ b/kotlin-native/platformLibs/src/platform/osx/set_depends.sh @@ -0,0 +1,2 @@ +#!/bin/bash +../../../../dist/bin/run_konan defFileDependencies -target macos_x64 *.def diff --git a/kotlin-native/platformLibs/src/platform/osx/vmnet.def b/kotlin-native/platformLibs/src/platform/osx/vmnet.def new file mode 100644 index 00000000000..43a43c7b68b --- /dev/null +++ b/kotlin-native/platformLibs/src/platform/osx/vmnet.def @@ -0,0 +1,7 @@ +depends = darwin posix +language = Objective-C +package = platform.vmnet +modules = vmnet + +compilerOpts = -framework vmnet +linkerOpts = -framework vmnet diff --git a/kotlin-native/platformLibs/src/platform/osx/zlib.def b/kotlin-native/platformLibs/src/platform/osx/zlib.def new file mode 100644 index 00000000000..8292dd723fa --- /dev/null +++ b/kotlin-native/platformLibs/src/platform/osx/zlib.def @@ -0,0 +1,34 @@ +depends = posix +package = platform.zlib +headers = zconf.h zlib.h +headerFilter = zconf.h zlib.h +compilerOpts = -DByte=uByte -DBytef=uBytef +linkerOpts = -lz + +--- +#undef deflateInit +static inline int deflateInit(z_streamp strm, int level) { + return deflateInit_(strm, level, ZLIB_VERSION, (int)sizeof(z_stream)); +} + +#undef deflateInit2 +static inline int deflateInit2(z_streamp strm, int level, int method, + int windowBits, int memLevel, int strategy) { + return deflateInit2_(strm, level, method, windowBits, memLevel, + strategy, ZLIB_VERSION, (int)sizeof(z_stream)); +} + +#undef inflateInit +static inline int inflateInit(z_streamp strm) { + return inflateInit_(strm, ZLIB_VERSION, (int)sizeof(z_stream)); +} + +#undef inflateInit2 +static inline int inflateInit2(z_streamp strm, int windowBits) { + return inflateInit2_(strm, windowBits, ZLIB_VERSION, (int)sizeof(z_stream)); +} + +#undef inflateBackInit +static inline int inflateBackInit(z_streamp strm, int windowBits, unsigned char *window) { + return inflateBackInit_(strm, windowBits, window, ZLIB_VERSION, (int)sizeof(z_stream)); +} diff --git a/kotlin-native/platformLibs/src/platform/tvos/AVFoundation.def b/kotlin-native/platformLibs/src/platform/tvos/AVFoundation.def new file mode 100644 index 00000000000..a5210271415 --- /dev/null +++ b/kotlin-native/platformLibs/src/platform/tvos/AVFoundation.def @@ -0,0 +1,9 @@ +depends = AudioToolbox CFNetwork CoreAudio CoreAudioTypes CoreFoundation CoreGraphics CoreMedia CoreVideo EAGL Foundation IOSurface ImageIO MediaToolbox Metal OpenGLESCommon QuartzCore Security UniformTypeIdentifiers darwin posix +language = Objective-C +package = platform.AVFoundation +headers = AVFoundation/AVFoundation.h AVFoundation/AVFAudio.h AVFoundation/AVAudioBuffer.h + +headerFilter = AVFoundation/** AVFAudio/** + +compilerOpts = -framework AVFoundation +linkerOpts = -framework AVFoundation diff --git a/kotlin-native/platformLibs/src/platform/tvos/AVKit.def b/kotlin-native/platformLibs/src/platform/tvos/AVKit.def new file mode 100644 index 00000000000..76bf5601643 --- /dev/null +++ b/kotlin-native/platformLibs/src/platform/tvos/AVKit.def @@ -0,0 +1,7 @@ +depends = AVFoundation AudioToolbox CFNetwork CoreAudio CoreAudioTypes CoreFoundation CoreGraphics CoreImage CoreMedia CoreText CoreVideo EAGL Foundation IOSurface ImageIO MediaToolbox Metal OpenGLESCommon QuartzCore Security UIKit UniformTypeIdentifiers UserNotifications darwin posix +language = Objective-C +package = platform.AVKit +modules = AVKit + +compilerOpts = -framework AVKit +linkerOpts = -framework AVKit diff --git a/kotlin-native/platformLibs/src/platform/tvos/Accelerate.def b/kotlin-native/platformLibs/src/platform/tvos/Accelerate.def new file mode 100644 index 00000000000..ab422998dc1 --- /dev/null +++ b/kotlin-native/platformLibs/src/platform/tvos/Accelerate.def @@ -0,0 +1,7 @@ +depends = CoreFoundation CoreGraphics CoreVideo IOSurface darwin posix +language = Objective-C +package = platform.Accelerate +modules = Accelerate + +compilerOpts = -framework Accelerate +linkerOpts = -framework Accelerate diff --git a/kotlin-native/platformLibs/src/platform/tvos/Accessibility.def b/kotlin-native/platformLibs/src/platform/tvos/Accessibility.def new file mode 100644 index 00000000000..c7f80f890c8 --- /dev/null +++ b/kotlin-native/platformLibs/src/platform/tvos/Accessibility.def @@ -0,0 +1,6 @@ +depends = CFNetwork CoreFoundation CoreGraphics Foundation Security darwin posix +language = Objective-C +package = platform.Accessibility +modules = Accessibility +compilerOpts = -framework Accessibility +linkerOpts = -framework Accessibility diff --git a/kotlin-native/platformLibs/src/platform/tvos/AdSupport.def b/kotlin-native/platformLibs/src/platform/tvos/AdSupport.def new file mode 100644 index 00000000000..e12d30d6eba --- /dev/null +++ b/kotlin-native/platformLibs/src/platform/tvos/AdSupport.def @@ -0,0 +1,7 @@ +depends = CFNetwork CoreFoundation Foundation Security darwin posix +language = Objective-C +package = platform.AdSupport +modules = AdSupport + +compilerOpts = -framework AdSupport +linkerOpts = -framework AdSupport diff --git a/kotlin-native/platformLibs/src/platform/tvos/AppTrackingTransparency.def b/kotlin-native/platformLibs/src/platform/tvos/AppTrackingTransparency.def new file mode 100644 index 00000000000..7e368032ce1 --- /dev/null +++ b/kotlin-native/platformLibs/src/platform/tvos/AppTrackingTransparency.def @@ -0,0 +1,6 @@ +depends = CFNetwork CoreFoundation Foundation Security darwin posix +language = Objective-C +package = platform.AppTrackingTransparency +modules = AppTrackingTransparency +compilerOpts = -framework AppTrackingTransparency +linkerOpts = -framework AppTrackingTransparency diff --git a/kotlin-native/platformLibs/src/platform/tvos/AudioToolbox.def b/kotlin-native/platformLibs/src/platform/tvos/AudioToolbox.def new file mode 100644 index 00000000000..5ef2e5e3dea --- /dev/null +++ b/kotlin-native/platformLibs/src/platform/tvos/AudioToolbox.def @@ -0,0 +1,7 @@ +depends = CFNetwork CoreAudioTypes CoreFoundation Foundation Security darwin posix +language = Objective-C +package = platform.AudioToolbox +modules = AudioToolbox AudioUnit + +compilerOpts = -framework AudioToolbox +linkerOpts = -framework AudioToolbox diff --git a/kotlin-native/platformLibs/src/platform/tvos/AudioUnit.def.disabled b/kotlin-native/platformLibs/src/platform/tvos/AudioUnit.def.disabled new file mode 100644 index 00000000000..0ad66c4745a --- /dev/null +++ b/kotlin-native/platformLibs/src/platform/tvos/AudioUnit.def.disabled @@ -0,0 +1,7 @@ +depends = AudioToolbox CFNetwork CoreAudioTypes CoreFoundation Foundation Security darwin posix +language = Objective-C +package = platform.AudioUnit +modules = AudioUnit +compilerOpts = -framework AudioUnit +linkerOpts = -framework AudioUnit +#Disabled: part of AudioToolbox \ No newline at end of file diff --git a/kotlin-native/platformLibs/src/platform/tvos/AuthenticationServices.def b/kotlin-native/platformLibs/src/platform/tvos/AuthenticationServices.def new file mode 100644 index 00000000000..5130fced4ab --- /dev/null +++ b/kotlin-native/platformLibs/src/platform/tvos/AuthenticationServices.def @@ -0,0 +1,7 @@ +depends = CFNetwork CoreFoundation CoreGraphics CoreImage CoreText CoreVideo EAGL Foundation IOSurface ImageIO Metal OpenGLESCommon QuartzCore Security UIKit UserNotifications darwin posix +language = Objective-C +package = platform.AuthenticationServices +modules = AuthenticationServices + +compilerOpts = -framework AuthenticationServices +linkerOpts = -framework AuthenticationServices diff --git a/kotlin-native/platformLibs/src/platform/tvos/BackgroundTasks.def b/kotlin-native/platformLibs/src/platform/tvos/BackgroundTasks.def new file mode 100644 index 00000000000..969ce3a3948 --- /dev/null +++ b/kotlin-native/platformLibs/src/platform/tvos/BackgroundTasks.def @@ -0,0 +1,7 @@ +depends = CFNetwork CoreFoundation Foundation Security darwin posix +language = Objective-C +package = platform.BackgroundTasks +modules = BackgroundTasks + +compilerOpts = -framework BackgroundTasks +linkerOpts = -framework BackgroundTasks diff --git a/kotlin-native/platformLibs/src/platform/tvos/CFNetwork.def b/kotlin-native/platformLibs/src/platform/tvos/CFNetwork.def new file mode 100644 index 00000000000..03fbe924cd0 --- /dev/null +++ b/kotlin-native/platformLibs/src/platform/tvos/CFNetwork.def @@ -0,0 +1,7 @@ +depends = CoreFoundation darwin posix +language = Objective-C +package = platform.CFNetwork +modules = CFNetwork + +compilerOpts = -framework CFNetwork +linkerOpts = -framework CFNetwork diff --git a/kotlin-native/platformLibs/src/platform/tvos/CloudKit.def b/kotlin-native/platformLibs/src/platform/tvos/CloudKit.def new file mode 100644 index 00000000000..95f7bed6f8f --- /dev/null +++ b/kotlin-native/platformLibs/src/platform/tvos/CloudKit.def @@ -0,0 +1,7 @@ +depends = CFNetwork CoreFoundation CoreLocation Foundation Security darwin posix +language = Objective-C +package = platform.CloudKit +modules = CloudKit + +compilerOpts = -framework CloudKit +linkerOpts = -framework CloudKit diff --git a/kotlin-native/platformLibs/src/platform/tvos/Combine.def.disabled b/kotlin-native/platformLibs/src/platform/tvos/Combine.def.disabled new file mode 100644 index 00000000000..0fde0deb560 --- /dev/null +++ b/kotlin-native/platformLibs/src/platform/tvos/Combine.def.disabled @@ -0,0 +1,6 @@ +language = Objective-C +package = platform.Combine +modules = Combine +compilerOpts = -framework Combine +linkerOpts = -framework Combine +#Disabled: Swift-only framework diff --git a/kotlin-native/platformLibs/src/platform/tvos/CommonCrypto.def b/kotlin-native/platformLibs/src/platform/tvos/CommonCrypto.def new file mode 100644 index 00000000000..92ce70f00ae --- /dev/null +++ b/kotlin-native/platformLibs/src/platform/tvos/CommonCrypto.def @@ -0,0 +1,6 @@ +depends = darwin posix +language = Objective-C +package = platform.CoreCrypto +modules = CommonCrypto + +compilerOpts = -D_XOPEN_SOURCE diff --git a/kotlin-native/platformLibs/src/platform/tvos/CoreAudio.def b/kotlin-native/platformLibs/src/platform/tvos/CoreAudio.def new file mode 100644 index 00000000000..7f5da857b89 --- /dev/null +++ b/kotlin-native/platformLibs/src/platform/tvos/CoreAudio.def @@ -0,0 +1,7 @@ +depends = CoreAudioTypes CoreFoundation darwin posix +language = Objective-C +package = platform.CoreAudio +modules = CoreAudio + +compilerOpts = -framework CoreAudio +linkerOpts = -framework CoreAudio diff --git a/kotlin-native/platformLibs/src/platform/tvos/CoreAudioKit.def.disabled b/kotlin-native/platformLibs/src/platform/tvos/CoreAudioKit.def.disabled new file mode 100644 index 00000000000..4bfa1036d4c --- /dev/null +++ b/kotlin-native/platformLibs/src/platform/tvos/CoreAudioKit.def.disabled @@ -0,0 +1,7 @@ +language = Objective-C +package = platform.CoreAudioKit + +modules = CoreAudioKit +compilerOpts = -framework CoreAudioKit +linkerOpts = -framework CoreAudioKit +#Disabled: Not officially available for tvos diff --git a/kotlin-native/platformLibs/src/platform/tvos/CoreAudioTypes.def b/kotlin-native/platformLibs/src/platform/tvos/CoreAudioTypes.def new file mode 100644 index 00000000000..2c8891b94d1 --- /dev/null +++ b/kotlin-native/platformLibs/src/platform/tvos/CoreAudioTypes.def @@ -0,0 +1,6 @@ +depends = CoreFoundation darwin posix +language = Objective-C +package = platform.CoreAudioTypes +modules = CoreAudioTypes + +compilerOpts = -framework CoreAudioTypes diff --git a/kotlin-native/platformLibs/src/platform/tvos/CoreBluetooth.def b/kotlin-native/platformLibs/src/platform/tvos/CoreBluetooth.def new file mode 100644 index 00000000000..7560c307d59 --- /dev/null +++ b/kotlin-native/platformLibs/src/platform/tvos/CoreBluetooth.def @@ -0,0 +1,7 @@ +depends = CFNetwork CoreFoundation Foundation Security darwin posix +language = Objective-C +package = platform.CoreBluetooth +modules = CoreBluetooth + +compilerOpts = -framework CoreBluetooth +linkerOpts = -framework CoreBluetooth diff --git a/kotlin-native/platformLibs/src/platform/tvos/CoreData.def b/kotlin-native/platformLibs/src/platform/tvos/CoreData.def new file mode 100644 index 00000000000..3f5d7ea0b1d --- /dev/null +++ b/kotlin-native/platformLibs/src/platform/tvos/CoreData.def @@ -0,0 +1,7 @@ +depends = CFNetwork CloudKit CoreFoundation CoreLocation Foundation Security darwin posix +language = Objective-C +package = platform.CoreData +modules = CoreData + +compilerOpts = -framework CoreData +linkerOpts = -framework CoreData diff --git a/kotlin-native/platformLibs/src/platform/tvos/CoreFoundation.def b/kotlin-native/platformLibs/src/platform/tvos/CoreFoundation.def new file mode 100644 index 00000000000..17c65eafa38 --- /dev/null +++ b/kotlin-native/platformLibs/src/platform/tvos/CoreFoundation.def @@ -0,0 +1,7 @@ +depends = darwin posix +language = Objective-C +package = platform.CoreFoundation +modules = CoreFoundation + +compilerOpts = -framework CoreFoundation +linkerOpts = -framework CoreFoundation diff --git a/kotlin-native/platformLibs/src/platform/tvos/CoreGraphics.def b/kotlin-native/platformLibs/src/platform/tvos/CoreGraphics.def new file mode 100644 index 00000000000..3951d09f2bd --- /dev/null +++ b/kotlin-native/platformLibs/src/platform/tvos/CoreGraphics.def @@ -0,0 +1,7 @@ +depends = CoreFoundation darwin posix +language = Objective-C +package = platform.CoreGraphics +modules = CoreGraphics + +compilerOpts = -framework CoreGraphics +linkerOpts = -framework CoreGraphics diff --git a/kotlin-native/platformLibs/src/platform/tvos/CoreHaptics.def b/kotlin-native/platformLibs/src/platform/tvos/CoreHaptics.def new file mode 100644 index 00000000000..a08920cbfa0 --- /dev/null +++ b/kotlin-native/platformLibs/src/platform/tvos/CoreHaptics.def @@ -0,0 +1,6 @@ +depends = CoreFoundation Foundation darwin posix +language = Objective-C +package = platform.CoreHaptics +modules = CoreHaptics +compilerOpts = -framework CoreHaptics +linkerOpts = -framework CoreHaptics diff --git a/kotlin-native/platformLibs/src/platform/tvos/CoreImage.def b/kotlin-native/platformLibs/src/platform/tvos/CoreImage.def new file mode 100644 index 00000000000..d2780206be8 --- /dev/null +++ b/kotlin-native/platformLibs/src/platform/tvos/CoreImage.def @@ -0,0 +1,7 @@ +depends = CFNetwork CoreFoundation CoreGraphics CoreVideo EAGL Foundation IOSurface ImageIO Metal OpenGLESCommon Security darwin posix +language = Objective-C +package = platform.CoreImage +modules = CoreImage + +compilerOpts = -framework CoreImage +linkerOpts = -framework CoreImage diff --git a/kotlin-native/platformLibs/src/platform/tvos/CoreLocation.def b/kotlin-native/platformLibs/src/platform/tvos/CoreLocation.def new file mode 100644 index 00000000000..34920afd9ee --- /dev/null +++ b/kotlin-native/platformLibs/src/platform/tvos/CoreLocation.def @@ -0,0 +1,7 @@ +depends = CFNetwork CoreFoundation Foundation Security darwin posix +language = Objective-C +package = platform.CoreLocation +modules = CoreLocation + +compilerOpts = -framework CoreLocation +linkerOpts = -framework CoreLocation diff --git a/kotlin-native/platformLibs/src/platform/tvos/CoreML.def b/kotlin-native/platformLibs/src/platform/tvos/CoreML.def new file mode 100644 index 00000000000..eb3bdbef75a --- /dev/null +++ b/kotlin-native/platformLibs/src/platform/tvos/CoreML.def @@ -0,0 +1,7 @@ +depends = CFNetwork CoreFoundation CoreGraphics CoreVideo Foundation IOSurface ImageIO Security darwin posix +language = Objective-C +package = platform.CoreML +modules = CoreML + +compilerOpts = -framework CoreML +linkerOpts = -framework CoreML diff --git a/kotlin-native/platformLibs/src/platform/tvos/CoreMedia.def b/kotlin-native/platformLibs/src/platform/tvos/CoreMedia.def new file mode 100644 index 00000000000..e8efa2a915c --- /dev/null +++ b/kotlin-native/platformLibs/src/platform/tvos/CoreMedia.def @@ -0,0 +1,7 @@ +depends = CFNetwork CoreAudio CoreAudioTypes CoreFoundation CoreGraphics CoreVideo Foundation IOSurface Metal OpenGLESCommon Security darwin posix +language = Objective-C +package = platform.CoreMedia +modules = CoreMedia + +compilerOpts = -framework CoreMedia +linkerOpts = -framework CoreMedia diff --git a/kotlin-native/platformLibs/src/platform/tvos/CoreServices.def b/kotlin-native/platformLibs/src/platform/tvos/CoreServices.def new file mode 100644 index 00000000000..ffd15288ee0 --- /dev/null +++ b/kotlin-native/platformLibs/src/platform/tvos/CoreServices.def @@ -0,0 +1,7 @@ +depends = CoreFoundation darwin posix +language = Objective-C +package = platform.CoreServices +modules = CoreServices + +compilerOpts = -framework CoreServices +linkerOpts = -framework CoreServices diff --git a/kotlin-native/platformLibs/src/platform/tvos/CoreSpotlight.def b/kotlin-native/platformLibs/src/platform/tvos/CoreSpotlight.def new file mode 100644 index 00000000000..a3d7f7d6fa6 --- /dev/null +++ b/kotlin-native/platformLibs/src/platform/tvos/CoreSpotlight.def @@ -0,0 +1,7 @@ +depends = CFNetwork CoreFoundation Foundation Security UniformTypeIdentifiers darwin posix +language = Objective-C +package = platform.CoreSpotlight +modules = CoreSpotlight + +compilerOpts = -framework CoreSpotlight +linkerOpts = -framework CoreSpotlight diff --git a/kotlin-native/platformLibs/src/platform/tvos/CoreText.def b/kotlin-native/platformLibs/src/platform/tvos/CoreText.def new file mode 100644 index 00000000000..3cdfe6f0a47 --- /dev/null +++ b/kotlin-native/platformLibs/src/platform/tvos/CoreText.def @@ -0,0 +1,7 @@ +depends = CoreFoundation CoreGraphics darwin posix +language = Objective-C +package = platform.CoreText +modules = CoreText + +compilerOpts = -framework CoreText +linkerOpts = -framework CoreText diff --git a/kotlin-native/platformLibs/src/platform/tvos/CoreVideo.def b/kotlin-native/platformLibs/src/platform/tvos/CoreVideo.def new file mode 100644 index 00000000000..ce59a982a89 --- /dev/null +++ b/kotlin-native/platformLibs/src/platform/tvos/CoreVideo.def @@ -0,0 +1,7 @@ +depends = CFNetwork CoreFoundation CoreGraphics Foundation IOSurface Metal OpenGLESCommon Security darwin posix +language = Objective-C +package = platform.CoreVideo +modules = CoreVideo + +compilerOpts = -framework CoreVideo +linkerOpts = -framework CoreVideo diff --git a/kotlin-native/platformLibs/src/platform/tvos/CryptoKit.def.disabled b/kotlin-native/platformLibs/src/platform/tvos/CryptoKit.def.disabled new file mode 100644 index 00000000000..1fd5943bf93 --- /dev/null +++ b/kotlin-native/platformLibs/src/platform/tvos/CryptoKit.def.disabled @@ -0,0 +1,6 @@ +language = Objective-C +package = platform.CryptoKit +modules = CryptoKit +compilerOpts = -framework CryptoKit +linkerOpts = -framework CryptoKit +#Disabled: Swift-only framework diff --git a/kotlin-native/platformLibs/src/platform/tvos/CryptoTokenKit.def b/kotlin-native/platformLibs/src/platform/tvos/CryptoTokenKit.def new file mode 100644 index 00000000000..92a710c27ae --- /dev/null +++ b/kotlin-native/platformLibs/src/platform/tvos/CryptoTokenKit.def @@ -0,0 +1,7 @@ +depends = CFNetwork CoreFoundation Foundation Security darwin posix +language = Objective-C +package = platform.CryptoTokenKit +modules = CryptoTokenKit + +compilerOpts = -framework CryptoTokenKit +linkerOpts = -framework CryptoTokenKit diff --git a/kotlin-native/platformLibs/src/platform/tvos/DeveloperToolsSupport.def.disabled b/kotlin-native/platformLibs/src/platform/tvos/DeveloperToolsSupport.def.disabled new file mode 100644 index 00000000000..b3e34c7522b --- /dev/null +++ b/kotlin-native/platformLibs/src/platform/tvos/DeveloperToolsSupport.def.disabled @@ -0,0 +1,6 @@ +language = Objective-C +package = platform.DeveloperToolsSupport +modules = DeveloperToolsSupport +compilerOpts = -framework DeveloperToolsSupport +linkerOpts = -framework DeveloperToolsSupport +#Disabled: Swift-only framework diff --git a/kotlin-native/platformLibs/src/platform/tvos/DeviceCheck.def b/kotlin-native/platformLibs/src/platform/tvos/DeviceCheck.def new file mode 100644 index 00000000000..e056ac13b56 --- /dev/null +++ b/kotlin-native/platformLibs/src/platform/tvos/DeviceCheck.def @@ -0,0 +1,7 @@ +depends = CFNetwork CoreFoundation Foundation Security darwin posix +language = Objective-C +package = platform.DeviceCheck +modules = DeviceCheck + +compilerOpts = -framework DeviceCheck +linkerOpts = -framework DeviceCheck diff --git a/kotlin-native/platformLibs/src/platform/tvos/EAGL.def b/kotlin-native/platformLibs/src/platform/tvos/EAGL.def new file mode 100644 index 00000000000..9937e7c0f0a --- /dev/null +++ b/kotlin-native/platformLibs/src/platform/tvos/EAGL.def @@ -0,0 +1,9 @@ +depends = CFNetwork CoreFoundation Foundation Security darwin posix +language = Objective-C +package = platform.EAGL +headers = OpenGLES/EAGL.h OpenGLES/EAGLDrawable.h + +headerFilter = OpenGLES/** + +compilerOpts = -framework OpenGLES +linkerOpts = -framework OpenGLES diff --git a/kotlin-native/platformLibs/src/platform/tvos/ExposureNotification.def.disabled b/kotlin-native/platformLibs/src/platform/tvos/ExposureNotification.def.disabled new file mode 100644 index 00000000000..569d6d76052 --- /dev/null +++ b/kotlin-native/platformLibs/src/platform/tvos/ExposureNotification.def.disabled @@ -0,0 +1,6 @@ +language = Objective-C +package = platform.ExposureNotification +modules = ExposureNotification +compilerOpts = -framework ExposureNotification +linkerOpts = -framework ExposureNotification +#Disabled: Not officially available for tvos diff --git a/kotlin-native/platformLibs/src/platform/tvos/ExternalAccessory.def b/kotlin-native/platformLibs/src/platform/tvos/ExternalAccessory.def new file mode 100644 index 00000000000..bc5c45b70b6 --- /dev/null +++ b/kotlin-native/platformLibs/src/platform/tvos/ExternalAccessory.def @@ -0,0 +1,7 @@ +depends = CFNetwork CoreFoundation Foundation Security darwin posix +language = Objective-C +package = platform.ExternalAccessory +modules = ExternalAccessory + +compilerOpts = -framework ExternalAccessory +linkerOpts = -framework ExternalAccessory diff --git a/kotlin-native/platformLibs/src/platform/tvos/Foundation.def b/kotlin-native/platformLibs/src/platform/tvos/Foundation.def new file mode 100644 index 00000000000..c6b0891cea4 --- /dev/null +++ b/kotlin-native/platformLibs/src/platform/tvos/Foundation.def @@ -0,0 +1,7 @@ +depends = CFNetwork CoreFoundation Security darwin posix +language = Objective-C +package = platform.Foundation +modules = Foundation + +compilerOpts = -framework Foundation +linkerOpts = -framework Foundation diff --git a/kotlin-native/platformLibs/src/platform/tvos/GLKit.def b/kotlin-native/platformLibs/src/platform/tvos/GLKit.def new file mode 100644 index 00000000000..a6438ad1f9c --- /dev/null +++ b/kotlin-native/platformLibs/src/platform/tvos/GLKit.def @@ -0,0 +1,7 @@ +depends = CFNetwork CoreFoundation CoreGraphics CoreImage CoreText CoreVideo EAGL Foundation IOSurface ImageIO Metal ModelIO OpenGLES2 OpenGLESCommon QuartzCore Security UIKit UserNotifications darwin posix +language = Objective-C +package = platform.GLKit +modules = GLKit + +compilerOpts = -framework GLKit +linkerOpts = -framework GLKit diff --git a/kotlin-native/platformLibs/src/platform/tvos/GameController.def b/kotlin-native/platformLibs/src/platform/tvos/GameController.def new file mode 100644 index 00000000000..fb995bc11bd --- /dev/null +++ b/kotlin-native/platformLibs/src/platform/tvos/GameController.def @@ -0,0 +1,7 @@ +depends = CFNetwork CoreFoundation CoreGraphics CoreImage CoreText CoreVideo EAGL Foundation IOSurface ImageIO Metal OpenGLESCommon QuartzCore Security UIKit darwin posix +language = Objective-C +package = platform.GameController +modules = GameController + +compilerOpts = -framework GameController +linkerOpts = -framework GameController diff --git a/kotlin-native/platformLibs/src/platform/tvos/GameKit.def b/kotlin-native/platformLibs/src/platform/tvos/GameKit.def new file mode 100644 index 00000000000..66e85c8c993 --- /dev/null +++ b/kotlin-native/platformLibs/src/platform/tvos/GameKit.def @@ -0,0 +1,7 @@ +depends = AVFoundation AudioToolbox CFNetwork CoreAudio CoreAudioTypes CoreFoundation CoreGraphics CoreImage CoreMedia CoreText CoreVideo EAGL Foundation GLKit GameController GameplayKit IOSurface ImageIO MediaToolbox Metal MetalKit ModelIO OpenGLESCommon QuartzCore ReplayKit SceneKit Security SpriteKit UIKit UniformTypeIdentifiers UserNotifications darwin posix +language = Objective-C +package = platform.GameKit +modules = GameKit + +compilerOpts = -framework GameKit +linkerOpts = -framework GameKit diff --git a/kotlin-native/platformLibs/src/platform/tvos/GameplayKit.def b/kotlin-native/platformLibs/src/platform/tvos/GameplayKit.def new file mode 100644 index 00000000000..b5fd6ef0b8d --- /dev/null +++ b/kotlin-native/platformLibs/src/platform/tvos/GameplayKit.def @@ -0,0 +1,7 @@ +depends = CFNetwork CoreFoundation CoreGraphics CoreImage CoreText CoreVideo EAGL Foundation GLKit IOSurface ImageIO Metal OpenGLESCommon QuartzCore SceneKit Security SpriteKit UIKit UserNotifications darwin posix +language = Objective-C +package = platform.GameplayKit +modules = GameplayKit + +compilerOpts = -framework GameplayKit +linkerOpts = -framework GameplayKit diff --git a/kotlin-native/platformLibs/src/platform/tvos/HomeKit.def b/kotlin-native/platformLibs/src/platform/tvos/HomeKit.def new file mode 100644 index 00000000000..74fe11f6627 --- /dev/null +++ b/kotlin-native/platformLibs/src/platform/tvos/HomeKit.def @@ -0,0 +1,7 @@ +depends = CFNetwork CoreFoundation CoreGraphics CoreImage CoreText CoreVideo EAGL Foundation IOSurface ImageIO Metal OpenGLESCommon QuartzCore Security UIKit UserNotifications darwin posix +language = Objective-C +package = platform.HomeKit +modules = HomeKit + +compilerOpts = -framework HomeKit +linkerOpts = -framework HomeKit diff --git a/kotlin-native/platformLibs/src/platform/tvos/IOKit.def.disabled b/kotlin-native/platformLibs/src/platform/tvos/IOKit.def.disabled new file mode 100644 index 00000000000..8f3d82e795b --- /dev/null +++ b/kotlin-native/platformLibs/src/platform/tvos/IOKit.def.disabled @@ -0,0 +1,7 @@ +language = Objective-C +package = platform.IOKit + +modules = IOKit +compilerOpts = -framework IOKit +linkerOpts = -framework IOKit +#Disabled: Not officially available for tvos diff --git a/kotlin-native/platformLibs/src/platform/tvos/IOSurface.def b/kotlin-native/platformLibs/src/platform/tvos/IOSurface.def new file mode 100644 index 00000000000..a56b69da8fc --- /dev/null +++ b/kotlin-native/platformLibs/src/platform/tvos/IOSurface.def @@ -0,0 +1,7 @@ +depends = CFNetwork CoreFoundation Foundation Security darwin posix +language = Objective-C +package = platform.IOSurface +modules = IOSurface + +compilerOpts = -framework IOSurface +linkerOpts = -framework IOSurface diff --git a/kotlin-native/platformLibs/src/platform/tvos/ImageIO.def b/kotlin-native/platformLibs/src/platform/tvos/ImageIO.def new file mode 100644 index 00000000000..635137a80c9 --- /dev/null +++ b/kotlin-native/platformLibs/src/platform/tvos/ImageIO.def @@ -0,0 +1,7 @@ +depends = CoreFoundation CoreGraphics darwin posix +language = Objective-C +package = platform.ImageIO +modules = ImageIO + +compilerOpts = -framework ImageIO +linkerOpts = -framework ImageIO diff --git a/kotlin-native/platformLibs/src/platform/tvos/Intents.def b/kotlin-native/platformLibs/src/platform/tvos/Intents.def new file mode 100644 index 00000000000..77576e347d5 --- /dev/null +++ b/kotlin-native/platformLibs/src/platform/tvos/Intents.def @@ -0,0 +1,6 @@ +depends = CFNetwork CoreFoundation CoreGraphics CoreLocation Foundation Security darwin posix +language = Objective-C +package = platform.Intents +modules = Intents +compilerOpts = -framework Intents +linkerOpts = -framework Intents diff --git a/kotlin-native/platformLibs/src/platform/tvos/IntentsUI.def b/kotlin-native/platformLibs/src/platform/tvos/IntentsUI.def new file mode 100644 index 00000000000..76b3d8c83d3 --- /dev/null +++ b/kotlin-native/platformLibs/src/platform/tvos/IntentsUI.def @@ -0,0 +1,6 @@ +depends = CFNetwork CoreFoundation CoreGraphics CoreImage CoreText CoreVideo EAGL Foundation IOSurface ImageIO Intents Metal OpenGLESCommon QuartzCore Security UIKit UserNotifications darwin posix +language = Objective-C +package = platform.IntentsUI +modules = IntentsUI +compilerOpts = -framework IntentsUI +linkerOpts = -framework IntentsUI diff --git a/kotlin-native/platformLibs/src/platform/tvos/JavaScriptCore.def b/kotlin-native/platformLibs/src/platform/tvos/JavaScriptCore.def new file mode 100644 index 00000000000..f887ee42f4d --- /dev/null +++ b/kotlin-native/platformLibs/src/platform/tvos/JavaScriptCore.def @@ -0,0 +1,7 @@ +depends = CFNetwork CoreFoundation CoreGraphics Foundation Security darwin posix +language = Objective-C +package = platform.JavaScriptCore +modules = JavaScriptCore + +compilerOpts = -framework JavaScriptCore +linkerOpts = -framework JavaScriptCore diff --git a/kotlin-native/platformLibs/src/platform/tvos/LinkPresentation.def b/kotlin-native/platformLibs/src/platform/tvos/LinkPresentation.def new file mode 100644 index 00000000000..c8eccfaa738 --- /dev/null +++ b/kotlin-native/platformLibs/src/platform/tvos/LinkPresentation.def @@ -0,0 +1,6 @@ +depends = CFNetwork CoreFoundation CoreGraphics CoreImage CoreText CoreVideo EAGL Foundation IOSurface ImageIO Metal OpenGLESCommon QuartzCore Security UIKit UserNotifications darwin posix +language = Objective-C +package = platform.LinkPresentation +modules = LinkPresentation +compilerOpts = -framework LinkPresentation +linkerOpts = -framework LinkPresentation diff --git a/kotlin-native/platformLibs/src/platform/tvos/LocalAuthentication.def.disabled b/kotlin-native/platformLibs/src/platform/tvos/LocalAuthentication.def.disabled new file mode 100644 index 00000000000..ebfc3ffb00e --- /dev/null +++ b/kotlin-native/platformLibs/src/platform/tvos/LocalAuthentication.def.disabled @@ -0,0 +1,7 @@ +language = Objective-C +package = platform.LocalAuthentication + +modules = LocalAuthentication +compilerOpts = -framework LocalAuthentication +linkerOpts = -framework LocalAuthentication +#Disabled: Not officially available for tvos diff --git a/kotlin-native/platformLibs/src/platform/tvos/MLCompute.def b/kotlin-native/platformLibs/src/platform/tvos/MLCompute.def new file mode 100644 index 00000000000..0e7d7c33ee7 --- /dev/null +++ b/kotlin-native/platformLibs/src/platform/tvos/MLCompute.def @@ -0,0 +1,7 @@ +depends = CFNetwork CoreFoundation Foundation IOSurface Metal Security darwin posix +language = Objective-C +package = platform.MLCompute + +modules.tvos_arm64 = MLCompute +compilerOpts.tvos_arm64 = -framework MLCompute +linkerOpts.tvos_arm64 = -framework MLCompute diff --git a/kotlin-native/platformLibs/src/platform/tvos/MapKit.def b/kotlin-native/platformLibs/src/platform/tvos/MapKit.def new file mode 100644 index 00000000000..60ca75441f1 --- /dev/null +++ b/kotlin-native/platformLibs/src/platform/tvos/MapKit.def @@ -0,0 +1,7 @@ +depends = CFNetwork CoreFoundation CoreGraphics CoreImage CoreLocation CoreText CoreVideo EAGL Foundation IOSurface ImageIO Metal OpenGLESCommon QuartzCore Security UIKit UserNotifications darwin posix +language = Objective-C +package = platform.MapKit +modules = MapKit + +compilerOpts = -framework MapKit +linkerOpts = -framework MapKit diff --git a/kotlin-native/platformLibs/src/platform/tvos/MediaAccessibility.def b/kotlin-native/platformLibs/src/platform/tvos/MediaAccessibility.def new file mode 100644 index 00000000000..dbbe59f9038 --- /dev/null +++ b/kotlin-native/platformLibs/src/platform/tvos/MediaAccessibility.def @@ -0,0 +1,7 @@ +depends = CFNetwork CoreFoundation CoreGraphics CoreText EAGL Foundation Metal QuartzCore Security darwin posix +language = Objective-C +package = platform.MediaAccessibility +modules = MediaAccessibility + +compilerOpts = -framework MediaAccessibility +linkerOpts = -framework MediaAccessibility diff --git a/kotlin-native/platformLibs/src/platform/tvos/MediaPlayer.def b/kotlin-native/platformLibs/src/platform/tvos/MediaPlayer.def new file mode 100644 index 00000000000..f5b620e0f93 --- /dev/null +++ b/kotlin-native/platformLibs/src/platform/tvos/MediaPlayer.def @@ -0,0 +1,9 @@ +depends = AVFoundation CFNetwork CoreFoundation CoreGraphics CoreImage CoreMedia CoreText CoreVideo EAGL Foundation IOSurface ImageIO Metal OpenGLESCommon QuartzCore Security UIKit UserNotifications darwin posix +language = Objective-C +package = platform.MediaPlayer +headers = MediaPlayer/MediaPlayer.h + +headerFilter = MediaPlayer/** + +compilerOpts = -framework MediaPlayer +linkerOpts = -framework MediaPlayer diff --git a/kotlin-native/platformLibs/src/platform/tvos/MediaToolbox.def b/kotlin-native/platformLibs/src/platform/tvos/MediaToolbox.def new file mode 100644 index 00000000000..074f6f811f2 --- /dev/null +++ b/kotlin-native/platformLibs/src/platform/tvos/MediaToolbox.def @@ -0,0 +1,7 @@ +depends = AudioToolbox CFNetwork CoreAudio CoreAudioTypes CoreFoundation CoreGraphics CoreMedia CoreVideo Foundation IOSurface Metal OpenGLESCommon Security darwin posix +language = Objective-C +package = platform.MediaToolbox +modules = MediaToolbox + +compilerOpts = -framework MediaToolbox +linkerOpts = -framework MediaToolbox diff --git a/kotlin-native/platformLibs/src/platform/tvos/MessageUI.def.disabled b/kotlin-native/platformLibs/src/platform/tvos/MessageUI.def.disabled new file mode 100644 index 00000000000..dda3da8a288 --- /dev/null +++ b/kotlin-native/platformLibs/src/platform/tvos/MessageUI.def.disabled @@ -0,0 +1,7 @@ +language = Objective-C +package = platform.MessageUI + +modules = MessageUI +compilerOpts = -framework MessageUI +linkerOpts = -framework MessageUI +#Disabled: Not officially available for tvos diff --git a/kotlin-native/platformLibs/src/platform/tvos/Metal.def b/kotlin-native/platformLibs/src/platform/tvos/Metal.def new file mode 100644 index 00000000000..1fd4753252a --- /dev/null +++ b/kotlin-native/platformLibs/src/platform/tvos/Metal.def @@ -0,0 +1,7 @@ +depends = CFNetwork CoreFoundation Foundation IOSurface Security darwin posix +language = Objective-C +package = platform.Metal +modules = Metal + +compilerOpts = -framework Metal +linkerOpts = -framework Metal diff --git a/kotlin-native/platformLibs/src/platform/tvos/MetalKit.def b/kotlin-native/platformLibs/src/platform/tvos/MetalKit.def new file mode 100644 index 00000000000..aa6932cd6ef --- /dev/null +++ b/kotlin-native/platformLibs/src/platform/tvos/MetalKit.def @@ -0,0 +1,7 @@ +depends = CFNetwork CoreFoundation CoreGraphics CoreImage CoreText CoreVideo EAGL Foundation IOSurface ImageIO Metal ModelIO OpenGLESCommon QuartzCore Security UIKit UserNotifications darwin posix +language = Objective-C +package = platform.MetalKit +modules = MetalKit + +compilerOpts = -framework MetalKit +linkerOpts = -framework MetalKit diff --git a/kotlin-native/platformLibs/src/platform/tvos/MetalPerformanceShaders.def b/kotlin-native/platformLibs/src/platform/tvos/MetalPerformanceShaders.def new file mode 100644 index 00000000000..b38d7f4f7f8 --- /dev/null +++ b/kotlin-native/platformLibs/src/platform/tvos/MetalPerformanceShaders.def @@ -0,0 +1,7 @@ +depends = CFNetwork CoreFoundation CoreGraphics Foundation IOSurface Metal Security darwin posix +language = Objective-C +package = platform.MetalPerformanceShaders +modules.arm64 = MetalPerformanceShaders + +compilerOpts.arm64 = -framework MetalPerformanceShaders +linkerOpts.arm64 = -framework MetalPerformanceShaders diff --git a/kotlin-native/platformLibs/src/platform/tvos/MetalPerformanceShadersGraph.def b/kotlin-native/platformLibs/src/platform/tvos/MetalPerformanceShadersGraph.def new file mode 100644 index 00000000000..6fa67425682 --- /dev/null +++ b/kotlin-native/platformLibs/src/platform/tvos/MetalPerformanceShadersGraph.def @@ -0,0 +1,7 @@ +depends = CFNetwork CoreFoundation CoreGraphics Foundation IOSurface Metal MetalPerformanceShaders Security darwin posix +language = Objective-C +package = platform.MetalPerformanceShadersGraph + +modules.tvos_arm64 = MetalPerformanceShadersGraph +compilerOpts.tvos_arm64 = -framework MetalPerformanceShadersGraph +linkerOpts.tvos_arm64 = -framework MetalPerformanceShadersGraph diff --git a/kotlin-native/platformLibs/src/platform/tvos/MetricKit.def b/kotlin-native/platformLibs/src/platform/tvos/MetricKit.def new file mode 100644 index 00000000000..32149d94d32 --- /dev/null +++ b/kotlin-native/platformLibs/src/platform/tvos/MetricKit.def @@ -0,0 +1,7 @@ +depends = CFNetwork CoreFoundation Foundation Security darwin posix +language = Objective-C +package = platform.MetricKit +modules = MetricKit + +compilerOpts = -framework MetricKit +linkerOpts = -framework MetricKit diff --git a/kotlin-native/platformLibs/src/platform/tvos/MobileCoreServices.def b/kotlin-native/platformLibs/src/platform/tvos/MobileCoreServices.def new file mode 100644 index 00000000000..bdd5356cc09 --- /dev/null +++ b/kotlin-native/platformLibs/src/platform/tvos/MobileCoreServices.def @@ -0,0 +1,7 @@ +depends = CoreFoundation CoreServices darwin posix +language = Objective-C +package = platform.MobileCoreServices +modules = MobileCoreServices + +compilerOpts = -framework MobileCoreServices +linkerOpts = -framework MobileCoreServices diff --git a/kotlin-native/platformLibs/src/platform/tvos/ModelIO.def b/kotlin-native/platformLibs/src/platform/tvos/ModelIO.def new file mode 100644 index 00000000000..3704a6b73ea --- /dev/null +++ b/kotlin-native/platformLibs/src/platform/tvos/ModelIO.def @@ -0,0 +1,7 @@ +depends = CFNetwork CoreFoundation CoreGraphics Foundation Security darwin posix +language = Objective-C +package = platform.ModelIO +modules = ModelIO + +compilerOpts = -framework ModelIO +linkerOpts = -framework ModelIO diff --git a/kotlin-native/platformLibs/src/platform/tvos/MultipeerConnectivity.def b/kotlin-native/platformLibs/src/platform/tvos/MultipeerConnectivity.def new file mode 100644 index 00000000000..90c2f7b121f --- /dev/null +++ b/kotlin-native/platformLibs/src/platform/tvos/MultipeerConnectivity.def @@ -0,0 +1,7 @@ +depends = CFNetwork CoreFoundation CoreGraphics CoreImage CoreText CoreVideo EAGL Foundation IOSurface ImageIO Metal OpenGLESCommon QuartzCore Security UIKit UserNotifications darwin posix +language = Objective-C +package = platform.MultipeerConnectivity +modules = MultipeerConnectivity + +compilerOpts = -framework MultipeerConnectivity +linkerOpts = -framework MultipeerConnectivity diff --git a/kotlin-native/platformLibs/src/platform/tvos/NaturalLanguage.def b/kotlin-native/platformLibs/src/platform/tvos/NaturalLanguage.def new file mode 100644 index 00000000000..50b22ee36ba --- /dev/null +++ b/kotlin-native/platformLibs/src/platform/tvos/NaturalLanguage.def @@ -0,0 +1,7 @@ +depends = CFNetwork CoreFoundation Foundation Security darwin posix +language = Objective-C +package = platform.NaturalLanguage +modules = NaturalLanguage + +compilerOpts = -framework NaturalLanguage +linkerOpts = -framework NaturalLanguage diff --git a/kotlin-native/platformLibs/src/platform/tvos/Network.def b/kotlin-native/platformLibs/src/platform/tvos/Network.def new file mode 100644 index 00000000000..b1664c1b04f --- /dev/null +++ b/kotlin-native/platformLibs/src/platform/tvos/Network.def @@ -0,0 +1,7 @@ +depends = CoreFoundation Security darwin posix +language = Objective-C +package = platform.Network +modules = Network + +compilerOpts = -framework Network +linkerOpts = -framework Network diff --git a/kotlin-native/platformLibs/src/platform/tvos/OSLog.def.disabled b/kotlin-native/platformLibs/src/platform/tvos/OSLog.def.disabled new file mode 100644 index 00000000000..f44c50e433e --- /dev/null +++ b/kotlin-native/platformLibs/src/platform/tvos/OSLog.def.disabled @@ -0,0 +1,6 @@ +language = Objective-C +package = platform.OSLog +modules = OSLog +compilerOpts = -framework OSLog +linkerOpts = -framework OSLog +#Disabled: Not officially available for tvos diff --git a/kotlin-native/platformLibs/src/platform/tvos/OpenAL.def b/kotlin-native/platformLibs/src/platform/tvos/OpenAL.def new file mode 100644 index 00000000000..9c030c99d33 --- /dev/null +++ b/kotlin-native/platformLibs/src/platform/tvos/OpenAL.def @@ -0,0 +1,7 @@ +depends = darwin posix +language = Objective-C +package = platform.OpenAL +modules = OpenAL + +compilerOpts = -framework OpenAL +linkerOpts = -framework OpenAL diff --git a/kotlin-native/platformLibs/src/platform/tvos/OpenGLES.def b/kotlin-native/platformLibs/src/platform/tvos/OpenGLES.def new file mode 100644 index 00000000000..5eb2b3ddb2f --- /dev/null +++ b/kotlin-native/platformLibs/src/platform/tvos/OpenGLES.def @@ -0,0 +1,9 @@ +depends = EAGL OpenGLESCommon darwin posix +language = Objective-C +package = platform.gles +headers = OpenGLES/ES1/gl.h OpenGLES/ES1/glext.h + +headerFilter = OpenGLES/ES1/** + +compilerOpts = -framework OpenGLES +linkerOpts = -framework OpenGLES diff --git a/kotlin-native/platformLibs/src/platform/tvos/OpenGLES2.def b/kotlin-native/platformLibs/src/platform/tvos/OpenGLES2.def new file mode 100644 index 00000000000..6d030e35c48 --- /dev/null +++ b/kotlin-native/platformLibs/src/platform/tvos/OpenGLES2.def @@ -0,0 +1,9 @@ +depends = EAGL OpenGLESCommon darwin posix +language = Objective-C +package = platform.gles2 +headers = OpenGLES/ES2/gl.h OpenGLES/ES2/glext.h + +headerFilter = OpenGLES/ES2/** + +compilerOpts = -framework OpenGLES +linkerOpts = -framework OpenGLES diff --git a/kotlin-native/platformLibs/src/platform/tvos/OpenGLES3.def b/kotlin-native/platformLibs/src/platform/tvos/OpenGLES3.def new file mode 100644 index 00000000000..08e9586476c --- /dev/null +++ b/kotlin-native/platformLibs/src/platform/tvos/OpenGLES3.def @@ -0,0 +1,9 @@ +depends = EAGL OpenGLESCommon darwin posix +language = Objective-C +package = platform.gles3 +headers = OpenGLES/ES3/gl.h OpenGLES/ES3/glext.h + +headerFilter = OpenGLES/ES3/** + +compilerOpts = -framework OpenGLES +linkerOpts = -framework OpenGLES diff --git a/kotlin-native/platformLibs/src/platform/tvos/OpenGLESCommon.def b/kotlin-native/platformLibs/src/platform/tvos/OpenGLESCommon.def new file mode 100644 index 00000000000..2c19d621104 --- /dev/null +++ b/kotlin-native/platformLibs/src/platform/tvos/OpenGLESCommon.def @@ -0,0 +1,9 @@ +depends = posix +language = Objective-C +package = platform.glescommon +headers = OpenGLES/gltypes.h + +headerFilter = OpenGLES/gltypes.h + +compilerOpts = -framework OpenGLES +linkerOpts = -framework OpenGLES diff --git a/kotlin-native/platformLibs/src/platform/tvos/Photos.def b/kotlin-native/platformLibs/src/platform/tvos/Photos.def new file mode 100644 index 00000000000..f4de624828f --- /dev/null +++ b/kotlin-native/platformLibs/src/platform/tvos/Photos.def @@ -0,0 +1,10 @@ +depends = AVFoundation AudioToolbox CFNetwork CoreAudio CoreAudioTypes CoreFoundation CoreGraphics CoreImage CoreLocation CoreMedia CoreText CoreVideo EAGL Foundation IOSurface ImageIO MediaToolbox Metal OpenGLESCommon QuartzCore Security UIKit UniformTypeIdentifiers UserNotifications darwin posix +language = Objective-C +package = platform.Photos +modules = Photos + +compilerOpts = -framework Photos +linkerOpts = -framework Photos +--- +// TODO: ugly hack while forwarded enums are supported. +#import diff --git a/kotlin-native/platformLibs/src/platform/tvos/PhotosUI.def b/kotlin-native/platformLibs/src/platform/tvos/PhotosUI.def new file mode 100644 index 00000000000..993798b6a4e --- /dev/null +++ b/kotlin-native/platformLibs/src/platform/tvos/PhotosUI.def @@ -0,0 +1,7 @@ +depends = AVFoundation AudioToolbox CFNetwork CoreAudio CoreAudioTypes CoreFoundation CoreGraphics CoreImage CoreLocation CoreMedia CoreText CoreVideo EAGL Foundation IOSurface ImageIO MediaToolbox Metal OpenGLESCommon Photos QuartzCore Security UIKit UniformTypeIdentifiers UserNotifications darwin posix +language = Objective-C +package = platform.PhotosUI +modules = PhotosUI + +compilerOpts = -framework PhotosUI +linkerOpts = -framework PhotosUI diff --git a/kotlin-native/platformLibs/src/platform/tvos/QuartzCore.def b/kotlin-native/platformLibs/src/platform/tvos/QuartzCore.def new file mode 100644 index 00000000000..bf48c159014 --- /dev/null +++ b/kotlin-native/platformLibs/src/platform/tvos/QuartzCore.def @@ -0,0 +1,9 @@ +depends = CFNetwork CoreFoundation CoreGraphics EAGL Foundation Metal Security darwin posix +language = Objective-C +package = platform.QuartzCore +headers = QuartzCore/QuartzCore.h + +headerFilter = QuartzCore/** + +compilerOpts = -framework QuartzCore +linkerOpts = -framework QuartzCore diff --git a/kotlin-native/platformLibs/src/platform/tvos/ReplayKit.def b/kotlin-native/platformLibs/src/platform/tvos/ReplayKit.def new file mode 100644 index 00000000000..43b0b18032e --- /dev/null +++ b/kotlin-native/platformLibs/src/platform/tvos/ReplayKit.def @@ -0,0 +1,7 @@ +depends = AVFoundation AudioToolbox CFNetwork CoreAudio CoreAudioTypes CoreFoundation CoreGraphics CoreImage CoreMedia CoreText CoreVideo EAGL Foundation IOSurface ImageIO MediaToolbox Metal OpenGLESCommon QuartzCore Security UIKit UniformTypeIdentifiers UserNotifications darwin posix +language = Objective-C +package = platform.ReplayKit +modules = ReplayKit + +compilerOpts = -framework ReplayKit +linkerOpts = -framework ReplayKit diff --git a/kotlin-native/platformLibs/src/platform/tvos/SceneKit.def b/kotlin-native/platformLibs/src/platform/tvos/SceneKit.def new file mode 100644 index 00000000000..8b5d18f890e --- /dev/null +++ b/kotlin-native/platformLibs/src/platform/tvos/SceneKit.def @@ -0,0 +1,7 @@ +depends = CFNetwork CoreFoundation CoreGraphics CoreImage CoreText CoreVideo EAGL Foundation GLKit IOSurface ImageIO Metal ModelIO OpenGLESCommon QuartzCore Security UIKit UserNotifications darwin posix +language = Objective-C +package = platform.SceneKit +modules = SceneKit + +compilerOpts = -framework SceneKit +linkerOpts = -framework SceneKit diff --git a/kotlin-native/platformLibs/src/platform/tvos/Security.def b/kotlin-native/platformLibs/src/platform/tvos/Security.def new file mode 100644 index 00000000000..de56b282a23 --- /dev/null +++ b/kotlin-native/platformLibs/src/platform/tvos/Security.def @@ -0,0 +1,7 @@ +depends = CoreFoundation darwin posix +language = Objective-C +package = platform.Security +modules = Security + +compilerOpts = -framework Security +linkerOpts = -framework Security diff --git a/kotlin-native/platformLibs/src/platform/tvos/SoundAnalysis.def b/kotlin-native/platformLibs/src/platform/tvos/SoundAnalysis.def new file mode 100644 index 00000000000..84c22f77749 --- /dev/null +++ b/kotlin-native/platformLibs/src/platform/tvos/SoundAnalysis.def @@ -0,0 +1,7 @@ +depends = AVFoundation AudioToolbox CFNetwork CoreAudio CoreAudioTypes CoreFoundation CoreGraphics CoreML CoreMedia CoreVideo EAGL Foundation IOSurface ImageIO MediaToolbox Metal OpenGLESCommon QuartzCore Security UniformTypeIdentifiers darwin posix +language = Objective-C +package = platform.SoundAnalysis +modules = SoundAnalysis + +compilerOpts = -framework SoundAnalysis +linkerOpts = -framework SoundAnalysis diff --git a/kotlin-native/platformLibs/src/platform/tvos/SpriteKit.def b/kotlin-native/platformLibs/src/platform/tvos/SpriteKit.def new file mode 100644 index 00000000000..46fbdd8f4d9 --- /dev/null +++ b/kotlin-native/platformLibs/src/platform/tvos/SpriteKit.def @@ -0,0 +1,7 @@ +depends = CFNetwork CoreFoundation CoreGraphics CoreImage CoreText CoreVideo EAGL Foundation GLKit IOSurface ImageIO Metal OpenGLESCommon QuartzCore Security UIKit UserNotifications darwin posix +language = Objective-C +package = platform.SpriteKit +modules = SpriteKit + +compilerOpts = -framework SpriteKit +linkerOpts = -framework SpriteKit diff --git a/kotlin-native/platformLibs/src/platform/tvos/StoreKit.def b/kotlin-native/platformLibs/src/platform/tvos/StoreKit.def new file mode 100644 index 00000000000..d1c5ffc9f01 --- /dev/null +++ b/kotlin-native/platformLibs/src/platform/tvos/StoreKit.def @@ -0,0 +1,7 @@ +depends = CFNetwork CoreFoundation CoreGraphics CoreImage CoreText CoreVideo EAGL Foundation IOSurface ImageIO Metal OpenGLESCommon QuartzCore Security UIKit UserNotifications darwin posix +language = Objective-C +package = platform.StoreKit +modules = StoreKit + +compilerOpts = -framework StoreKit +linkerOpts = -framework StoreKit diff --git a/kotlin-native/platformLibs/src/platform/tvos/SwiftUI.def.disabled b/kotlin-native/platformLibs/src/platform/tvos/SwiftUI.def.disabled new file mode 100644 index 00000000000..59c29eff39e --- /dev/null +++ b/kotlin-native/platformLibs/src/platform/tvos/SwiftUI.def.disabled @@ -0,0 +1,6 @@ +language = Objective-C +package = platform.SwiftUI +modules = SwiftUI +compilerOpts = -framework SwiftUI +linkerOpts = -framework SwiftUI +#Disabled: Swift-only framework diff --git a/kotlin-native/platformLibs/src/platform/tvos/SystemConfiguration.def b/kotlin-native/platformLibs/src/platform/tvos/SystemConfiguration.def new file mode 100644 index 00000000000..aeabf1da981 --- /dev/null +++ b/kotlin-native/platformLibs/src/platform/tvos/SystemConfiguration.def @@ -0,0 +1,7 @@ +depends = CoreFoundation darwin posix +language = Objective-C +package = platform.SystemConfiguration +modules = SystemConfiguration + +compilerOpts = -framework SystemConfiguration +linkerOpts = -framework SystemConfiguration diff --git a/kotlin-native/platformLibs/src/platform/tvos/TVMLKit.def b/kotlin-native/platformLibs/src/platform/tvos/TVMLKit.def new file mode 100644 index 00000000000..78fca9fce9e --- /dev/null +++ b/kotlin-native/platformLibs/src/platform/tvos/TVMLKit.def @@ -0,0 +1,7 @@ +depends = CFNetwork CoreFoundation CoreGraphics CoreImage CoreText CoreVideo EAGL Foundation IOSurface ImageIO JavaScriptCore Metal OpenGLESCommon QuartzCore Security UIKit UserNotifications darwin posix +language = Objective-C +package = platform.TVMLKit +modules = TVMLKit + +compilerOpts = -framework TVMLKit +linkerOpts = -framework TVMLKit diff --git a/kotlin-native/platformLibs/src/platform/tvos/TVServices.def b/kotlin-native/platformLibs/src/platform/tvos/TVServices.def new file mode 100644 index 00000000000..ca7157978f2 --- /dev/null +++ b/kotlin-native/platformLibs/src/platform/tvos/TVServices.def @@ -0,0 +1,7 @@ +depends = CFNetwork CoreFoundation CoreGraphics Foundation Security darwin posix +language = Objective-C +package = platform.TVServices +modules = TVServices + +compilerOpts = -framework TVServices +linkerOpts = -framework TVServices diff --git a/kotlin-native/platformLibs/src/platform/tvos/TVUIKit.def b/kotlin-native/platformLibs/src/platform/tvos/TVUIKit.def new file mode 100644 index 00000000000..b9da24be510 --- /dev/null +++ b/kotlin-native/platformLibs/src/platform/tvos/TVUIKit.def @@ -0,0 +1,7 @@ +depends = CFNetwork CoreFoundation CoreGraphics CoreImage CoreText CoreVideo EAGL Foundation IOSurface ImageIO Metal OpenGLESCommon QuartzCore Security UIKit UserNotifications darwin posix +language = Objective-C +package = platform.TVUIKit +modules = TVUIKit + +compilerOpts = -framework TVUIKit +linkerOpts = -framework TVUIKit diff --git a/kotlin-native/platformLibs/src/platform/tvos/UIKit.def b/kotlin-native/platformLibs/src/platform/tvos/UIKit.def new file mode 100644 index 00000000000..73fabe8ac33 --- /dev/null +++ b/kotlin-native/platformLibs/src/platform/tvos/UIKit.def @@ -0,0 +1,8 @@ +depends = CFNetwork CoreFoundation CoreGraphics CoreImage CoreText CoreVideo EAGL Foundation IOSurface ImageIO Metal OpenGLESCommon QuartzCore Security UserNotifications darwin posix +language = Objective-C +package = platform.UIKit +modules = UIKit + +compilerOpts = -framework UIKit +linkerOpts = -framework UIKit +excludedFunctions = UISceneErrorDomain diff --git a/kotlin-native/platformLibs/src/platform/tvos/UniformTypeIdentifiers.def b/kotlin-native/platformLibs/src/platform/tvos/UniformTypeIdentifiers.def new file mode 100644 index 00000000000..3d938bc1d54 --- /dev/null +++ b/kotlin-native/platformLibs/src/platform/tvos/UniformTypeIdentifiers.def @@ -0,0 +1,6 @@ +depends = CFNetwork CoreFoundation Foundation Security darwin posix +language = Objective-C +package = platform.UniformTypeIdentifiers +modules = UniformTypeIdentifiers +compilerOpts = -framework UniformTypeIdentifiers +linkerOpts = -framework UniformTypeIdentifiers diff --git a/kotlin-native/platformLibs/src/platform/tvos/UserNotifications.def b/kotlin-native/platformLibs/src/platform/tvos/UserNotifications.def new file mode 100644 index 00000000000..acd9fb39cec --- /dev/null +++ b/kotlin-native/platformLibs/src/platform/tvos/UserNotifications.def @@ -0,0 +1,7 @@ +depends = CFNetwork CoreFoundation Foundation Security darwin posix +language = Objective-C +package = platform.UserNotifications +modules = UserNotifications + +compilerOpts = -framework UserNotifications +linkerOpts = -framework UserNotifications diff --git a/kotlin-native/platformLibs/src/platform/tvos/VideoSubscriberAccount.def b/kotlin-native/platformLibs/src/platform/tvos/VideoSubscriberAccount.def new file mode 100644 index 00000000000..009de3b4cb8 --- /dev/null +++ b/kotlin-native/platformLibs/src/platform/tvos/VideoSubscriberAccount.def @@ -0,0 +1,7 @@ +depends = CoreFoundation Foundation darwin posix +language = Objective-C +package = platform.VideoSubscriberAccount +modules = VideoSubscriberAccount + +compilerOpts = -framework VideoSubscriberAccount +linkerOpts = -framework VideoSubscriberAccount diff --git a/kotlin-native/platformLibs/src/platform/tvos/VideoToolbox.def b/kotlin-native/platformLibs/src/platform/tvos/VideoToolbox.def new file mode 100644 index 00000000000..8ea1eead5a0 --- /dev/null +++ b/kotlin-native/platformLibs/src/platform/tvos/VideoToolbox.def @@ -0,0 +1,7 @@ +depends = CFNetwork CoreAudio CoreAudioTypes CoreFoundation CoreGraphics CoreMedia CoreVideo Foundation IOSurface Metal OpenGLESCommon Security darwin posix +language = Objective-C +package = platform.VideoToolbox +modules = VideoToolbox + +compilerOpts = -framework VideoToolbox +linkerOpts = -framework VideoToolbox diff --git a/kotlin-native/platformLibs/src/platform/tvos/Vision.def b/kotlin-native/platformLibs/src/platform/tvos/Vision.def new file mode 100644 index 00000000000..7d4ce8465df --- /dev/null +++ b/kotlin-native/platformLibs/src/platform/tvos/Vision.def @@ -0,0 +1,7 @@ +depends = CFNetwork CoreAudio CoreAudioTypes CoreFoundation CoreGraphics CoreML CoreMedia CoreVideo Foundation IOSurface ImageIO Metal OpenGLESCommon Security darwin posix +language = Objective-C +package = platform.Vision +modules = Vision + +compilerOpts = -framework Vision +linkerOpts = -framework Vision diff --git a/kotlin-native/platformLibs/src/platform/tvos/_AVKit_SwiftUI.def.disabled b/kotlin-native/platformLibs/src/platform/tvos/_AVKit_SwiftUI.def.disabled new file mode 100644 index 00000000000..04754e56b1b --- /dev/null +++ b/kotlin-native/platformLibs/src/platform/tvos/_AVKit_SwiftUI.def.disabled @@ -0,0 +1,6 @@ +language = Objective-C +package = platform._AVKit_SwiftUI +modules = _AVKit_SwiftUI +compilerOpts = -framework _AVKit_SwiftUI +linkerOpts = -framework _AVKit_SwiftUI +#Disabled: Unavailable diff --git a/kotlin-native/platformLibs/src/platform/tvos/_AuthenticationServices_SwiftUI.def.disabled b/kotlin-native/platformLibs/src/platform/tvos/_AuthenticationServices_SwiftUI.def.disabled new file mode 100644 index 00000000000..ff6eb919630 --- /dev/null +++ b/kotlin-native/platformLibs/src/platform/tvos/_AuthenticationServices_SwiftUI.def.disabled @@ -0,0 +1,6 @@ +language = Objective-C +package = platform._AuthenticationServices_SwiftUI +modules = _AuthenticationServices_SwiftUI +compilerOpts = -framework _AuthenticationServices_SwiftUI +linkerOpts = -framework _AuthenticationServices_SwiftUI +#Disabled: Unavailable diff --git a/kotlin-native/platformLibs/src/platform/tvos/_HomeKit_SwiftUI.def.disabled b/kotlin-native/platformLibs/src/platform/tvos/_HomeKit_SwiftUI.def.disabled new file mode 100644 index 00000000000..d5e70d04710 --- /dev/null +++ b/kotlin-native/platformLibs/src/platform/tvos/_HomeKit_SwiftUI.def.disabled @@ -0,0 +1,6 @@ +language = Objective-C +package = platform._HomeKit_SwiftUI +modules = _HomeKit_SwiftUI +compilerOpts = -framework _HomeKit_SwiftUI +linkerOpts = -framework _HomeKit_SwiftUI +#Disabled: Unavailable diff --git a/kotlin-native/platformLibs/src/platform/tvos/_MapKit_SwiftUI.def.disabled b/kotlin-native/platformLibs/src/platform/tvos/_MapKit_SwiftUI.def.disabled new file mode 100644 index 00000000000..3accf28420d --- /dev/null +++ b/kotlin-native/platformLibs/src/platform/tvos/_MapKit_SwiftUI.def.disabled @@ -0,0 +1,6 @@ +language = Objective-C +package = platform._MapKit_SwiftUI +modules = _MapKit_SwiftUI +compilerOpts = -framework _MapKit_SwiftUI +linkerOpts = -framework _MapKit_SwiftUI +#Disabled: Unavailable diff --git a/kotlin-native/platformLibs/src/platform/tvos/_SceneKit_SwiftUI.def.disabled b/kotlin-native/platformLibs/src/platform/tvos/_SceneKit_SwiftUI.def.disabled new file mode 100644 index 00000000000..4e18821c3d0 --- /dev/null +++ b/kotlin-native/platformLibs/src/platform/tvos/_SceneKit_SwiftUI.def.disabled @@ -0,0 +1,6 @@ +language = Objective-C +package = platform._SceneKit_SwiftUI +modules = _SceneKit_SwiftUI +compilerOpts = -framework _SceneKit_SwiftUI +linkerOpts = -framework _SceneKit_SwiftUI +#Disabled: Unavailable diff --git a/kotlin-native/platformLibs/src/platform/tvos/_SpriteKit_SwiftUI.def.disabled b/kotlin-native/platformLibs/src/platform/tvos/_SpriteKit_SwiftUI.def.disabled new file mode 100644 index 00000000000..572286b1f66 --- /dev/null +++ b/kotlin-native/platformLibs/src/platform/tvos/_SpriteKit_SwiftUI.def.disabled @@ -0,0 +1,6 @@ +language = Objective-C +package = platform._SpriteKit_SwiftUI +modules = _SpriteKit_SwiftUI +compilerOpts = -framework _SpriteKit_SwiftUI +linkerOpts = -framework _SpriteKit_SwiftUI +#Disabled: Unavailable diff --git a/kotlin-native/platformLibs/src/platform/tvos/builtin.def b/kotlin-native/platformLibs/src/platform/tvos/builtin.def new file mode 100644 index 00000000000..330aac43eb1 --- /dev/null +++ b/kotlin-native/platformLibs/src/platform/tvos/builtin.def @@ -0,0 +1,100 @@ +depends = posix +package = platform.builtin +headerFilter = ** +language = C + +excludedFunctions.tvos_arm64 = builtin_clear_cache +--- +// See https://github.com/llvm-mirror/clang/blob/master/include/clang/Basic/Builtins.def +// TODO: autogenerate from machine format. + +// Returns x with the order of the bytes reversed; for example, 0xaabb becomes 0xbbaa. Byte here always means exactly 8 bits. +static inline short builtin_bswap16(short x) { + return __builtin_bswap16(x); +} + +static inline int builtin_bswap32(int x) { + return __builtin_bswap32(x); +} + +static inline long long builtin_bswap64(long long x) { + return __builtin_bswap64(x); +} + +// Returns the number of leading 0-bits in x, starting at the most significant bit position. If x is 0, the result is undefined. +static inline int builtin_clzs(unsigned short x) { + return __builtin_clzs(x); +} + +static inline int builtin_clz(unsigned int x) { + return __builtin_clz(x); +} + +static inline int builtin_clzl(unsigned long x) { + return __builtin_clzl(x); +} + +static inline int builtin_clzll(unsigned long long x) { + return __builtin_clzll(x); +} + +// Returns the number of trailing 0-bits in x, starting at the least significant bit position. If x is 0, the result is undefined. +static inline int builtin_ctzs(unsigned short x) { + return __builtin_ctzs(x); +} + +static inline int builtin_ctz(unsigned int x) { + return __builtin_ctz(x); +} + +static inline int builtin_ctzl(unsigned long x) { + return __builtin_ctzl(x); +} + +static inline int builtin_ctzll(unsigned long long x) { + return __builtin_ctzll(x); +} + +// Returns one plus the index of the least significant 1-bit of x, or if x is zero, returns zero. +static inline int builtin_ffs(int x) { + return __builtin_ffs(x); +} + +static inline int builtin_ffsl(long x) { + return __builtin_ffsl(x); +} + +static inline int builtin_ffsll(long long x) { + return __builtin_ffsll(x); +} + +// Returns the parity of x, i.e. the number of 1-bits in x modulo 2. +static inline int builtin_parity(int x) { + return __builtin_parity(x); +} + +static inline int builtin_parityl(unsigned long x) { + return __builtin_parityl(x); +} + +static inline int builtin_parityll(unsigned long long x) { + return __builtin_parityll(x); +} + +// Returns the number of 1-bits in x. +static inline int builtin_popcount(int x) { + return __builtin_popcount(x); +} + +static inline int builtin_popcountl(long x) { + return __builtin_popcountl(x); +} + +static inline int builtin_popcountll(long long x) { + return __builtin_popcountll(x); +} + +// This function is used to flush the processor's instruction cache for the region of memory between begin inclusive and end exclusive. +static inline void builtin_clear_cache(void* begin, void* end) { + __builtin___clear_cache(begin, end); +} diff --git a/kotlin-native/platformLibs/src/platform/tvos/darwin.def b/kotlin-native/platformLibs/src/platform/tvos/darwin.def new file mode 100644 index 00000000000..2b5ee1c3722 --- /dev/null +++ b/kotlin-native/platformLibs/src/platform/tvos/darwin.def @@ -0,0 +1,42 @@ +depends = posix +language = Objective-C +package = platform.darwin +headers = AppleTextureEncoder.h AssertMacros.h Availability.h AvailabilityInternal.h \ + AvailabilityMacros.h Block.h ConditionalMacros.h MacTypes.h \ + TargetConditionals.h __cxxabi_config.h _locale.h _types.h _wctype.h \ + aio.h asl.h bitstring.h bzlib.h \ + cache.h cache_callbacks.h checkint.h compression.h copyfile.h \ + cpio.h cxxabi.h db.h \ + dns.h dns_sd.h dns_util.h execinfo.h \ + fmtmsg.h fstab.h \ + gethostuuid.h glob.h ifaddrs.h inttypes.h iso646.h \ + langinfo.h \ + libgen.h libunwind.h \ + membership.h monetary.h mpool.h \ + nameser.h ndbm.h nl_types.h \ + notify.h notify_keys.h ntsid.h \ + printf.h \ + readpassphrase.h removefile.h \ + runetype.h sandbox.h standards.h \ + stringlist.h sysdir.h sysexits.h tar.h \ + ttyent.h \ + unwind.h util.h utmpx.h vis.h wordexp.h xattr_flags.h \ + bank/bank_types.h \ + bsm/audit.h \ + os/activity.h os/availability.h os/base.h os/lock.h \ + os/log.h os/object.h os/overflow.h os/signpost.h os/trace.h \ + simd/simd.h sys/sysctl.h + +headerFilter = ** + +excludedFunctions = __tg_promote KERNEL_AUDIT_TOKEN KERNEL_SECURITY_TOKEN \ + asl_decode_buffer asl_encode_buffer asl_remove_index \ + averunnable dbm_forder pidlock ttyaction ttylock ttymsg ttyunlock uuid_generate_early_random \ + vm_stats + +compilerOpts = -D_XOPEN_SOURCE -DSYSCTL_DEF_ENABLED +linkerOpts = -ldl -lz -lbz2 -lcompression -late + +--- + +// menu.h is excluded so far due to interop issues. diff --git a/kotlin-native/platformLibs/src/platform/tvos/iconv.def b/kotlin-native/platformLibs/src/platform/tvos/iconv.def new file mode 100644 index 00000000000..e52d20f4da0 --- /dev/null +++ b/kotlin-native/platformLibs/src/platform/tvos/iconv.def @@ -0,0 +1,5 @@ +depends = posix +package = platform.iconv +headers = iconv.h +headerFilter = ** +linkerOpts = -liconv diff --git a/kotlin-native/platformLibs/src/platform/tvos/objc.def b/kotlin-native/platformLibs/src/platform/tvos/objc.def new file mode 100644 index 00000000000..20d1b81ca04 --- /dev/null +++ b/kotlin-native/platformLibs/src/platform/tvos/objc.def @@ -0,0 +1,13 @@ +depends = darwin posix +language = Objective-C +package = platform.objc +headers = objc/NSObjCRuntime.h objc/NSObject.h objc/message.h objc/objc-api.h \ + objc/objc-exception.h objc/objc-sync.h objc/objc.h objc/runtime.h + +headerFilter = objc/** + +compilerOpts = -D_XOPEN_SOURCE +linkerOpts = -lobjc + +--- +// objc-auto.h is excluded so far due to interop issues. diff --git a/kotlin-native/platformLibs/src/platform/tvos/posix.def b/kotlin-native/platformLibs/src/platform/tvos/posix.def new file mode 100644 index 00000000000..a87c902a459 --- /dev/null +++ b/kotlin-native/platformLibs/src/platform/tvos/posix.def @@ -0,0 +1,48 @@ +depends = +package = platform.posix +headers = alloca.h assert.h complex.h ctype.h dirent.h dlfcn.h err.h errno.h fcntl.h \ + fenv.h float.h fnmatch.h fts.h ftw.h getopt.h grp.h inttypes.h libgen.h limits.h \ + locale.h math.h memory.h netdb.h paths.h poll.h \ + pthread.h pwd.h regex.h resolv.h sched.h search.h semaphore.h setjmp.h signal.h \ + stdatomic.h stdint.h stdio.h stdlib.h string.h strings.h syslog.h termios.h \ + time.h ucontext.h unistd.h utime.h wchar.h wctype.h xlocale.h \ + net/ethernet.h net/if.h \ + netinet/icmp6.h netinet/in.h netinet/in_systm.h \ + netinet/ip.h netinet/ip6.h netinet/ip_icmp.h netinet/tcp.h netinet/udp.h \ + sys/acl.h sys/ioctl.h sys/ipc.h sys/mman.h sys/poll.h \ + sys/queue.h sys/select.h sys/shm.h sys/stat.h \ + sys/syslimits.h sys/time.h sys/times.h sys/utsname.h sys/wait.h + +compilerOpts = -D_XOPEN_SOURCE -D_DARWIN_C_SOURCE +linkerOpts = -ldl -lresolv + +excludedFunctions = acl_valid_link_np pfctlinput profil unwhiteout zopen getdirentries \ + uuid_generate_early_random setgrfile +excludedFunctions.tvos_arm64 = longjmperror +excludedFunctions.tvos_x64 = pthread_jit_write_protect_np pthread_jit_write_protect_supported_np + +--- +// Wrapper to access errno variable. +static int posix_errno() { + return errno; +} + +static void set_posix_errno(int value) { + errno = value; +} + +// Wrapper to access h_errno variable. +static int posix_h_errno() { + return h_errno; +} + +static void set_posix_h_errno(int value) { + h_errno = value; +} + +static int init_sockets() { + return 0; +} + +static void deinit_sockets() { +} diff --git a/kotlin-native/platformLibs/src/platform/tvos/set_depends.sh b/kotlin-native/platformLibs/src/platform/tvos/set_depends.sh new file mode 100755 index 00000000000..4c813c680d1 --- /dev/null +++ b/kotlin-native/platformLibs/src/platform/tvos/set_depends.sh @@ -0,0 +1,2 @@ +#!/bin/bash +../../../../dist/bin/run_konan defFileDependencies -target tvos_arm64 -target tvos_x64 *.def diff --git a/kotlin-native/platformLibs/src/platform/tvos/zlib.def b/kotlin-native/platformLibs/src/platform/tvos/zlib.def new file mode 100644 index 00000000000..8292dd723fa --- /dev/null +++ b/kotlin-native/platformLibs/src/platform/tvos/zlib.def @@ -0,0 +1,34 @@ +depends = posix +package = platform.zlib +headers = zconf.h zlib.h +headerFilter = zconf.h zlib.h +compilerOpts = -DByte=uByte -DBytef=uBytef +linkerOpts = -lz + +--- +#undef deflateInit +static inline int deflateInit(z_streamp strm, int level) { + return deflateInit_(strm, level, ZLIB_VERSION, (int)sizeof(z_stream)); +} + +#undef deflateInit2 +static inline int deflateInit2(z_streamp strm, int level, int method, + int windowBits, int memLevel, int strategy) { + return deflateInit2_(strm, level, method, windowBits, memLevel, + strategy, ZLIB_VERSION, (int)sizeof(z_stream)); +} + +#undef inflateInit +static inline int inflateInit(z_streamp strm) { + return inflateInit_(strm, ZLIB_VERSION, (int)sizeof(z_stream)); +} + +#undef inflateInit2 +static inline int inflateInit2(z_streamp strm, int windowBits) { + return inflateInit2_(strm, windowBits, ZLIB_VERSION, (int)sizeof(z_stream)); +} + +#undef inflateBackInit +static inline int inflateBackInit(z_streamp strm, int windowBits, unsigned char *window) { + return inflateBackInit_(strm, windowBits, window, ZLIB_VERSION, (int)sizeof(z_stream)); +} diff --git a/kotlin-native/platformLibs/src/platform/watchos/AVFoundation.def b/kotlin-native/platformLibs/src/platform/watchos/AVFoundation.def new file mode 100644 index 00000000000..69e9b9240f9 --- /dev/null +++ b/kotlin-native/platformLibs/src/platform/watchos/AVFoundation.def @@ -0,0 +1,7 @@ +depends = CoreAudio CoreAudioTypes CoreFoundation CoreGraphics CoreMedia CoreVideo Foundation ImageIO Security UniformTypeIdentifiers darwin posix +language = Objective-C +package = platform.AVFoundation +modules = AVFoundation + +compilerOpts = -framework AVFoundation +linkerOpts = -framework AVFoundation diff --git a/kotlin-native/platformLibs/src/platform/watchos/AVKit.def b/kotlin-native/platformLibs/src/platform/watchos/AVKit.def new file mode 100644 index 00000000000..bdd1ac0e38b --- /dev/null +++ b/kotlin-native/platformLibs/src/platform/watchos/AVKit.def @@ -0,0 +1,6 @@ +depends = posix +language = Objective-C +package = platform.AVKit +modules = AVKit +compilerOpts = -framework AVKit +linkerOpts = -framework AVKit diff --git a/kotlin-native/platformLibs/src/platform/watchos/Accelerate.def b/kotlin-native/platformLibs/src/platform/watchos/Accelerate.def new file mode 100644 index 00000000000..7a03bd31d63 --- /dev/null +++ b/kotlin-native/platformLibs/src/platform/watchos/Accelerate.def @@ -0,0 +1,7 @@ +depends = CoreFoundation CoreGraphics CoreVideo darwin posix +language = Objective-C +package = platform.Accelerate +modules = Accelerate + +compilerOpts = -framework Accelerate +linkerOpts = -framework Accelerate diff --git a/kotlin-native/platformLibs/src/platform/watchos/Accessibility.def b/kotlin-native/platformLibs/src/platform/watchos/Accessibility.def new file mode 100644 index 00000000000..8bc808e248f --- /dev/null +++ b/kotlin-native/platformLibs/src/platform/watchos/Accessibility.def @@ -0,0 +1,6 @@ +depends = CoreFoundation CoreGraphics Foundation Security darwin posix +language = Objective-C +package = platform.Accessibility +modules = Accessibility +compilerOpts = -framework Accessibility +linkerOpts = -framework Accessibility diff --git a/kotlin-native/platformLibs/src/platform/watchos/AuthenticationServices.def b/kotlin-native/platformLibs/src/platform/watchos/AuthenticationServices.def new file mode 100644 index 00000000000..374f869adbc --- /dev/null +++ b/kotlin-native/platformLibs/src/platform/watchos/AuthenticationServices.def @@ -0,0 +1,7 @@ +depends = CoreFoundation CoreGraphics CoreText Foundation Security UIKit darwin posix +language = Objective-C +package = platform.AuthenticationServices +modules = AuthenticationServices + +compilerOpts = -framework AuthenticationServices +linkerOpts = -framework AuthenticationServices diff --git a/kotlin-native/platformLibs/src/platform/watchos/CFNetwork.def.disabled b/kotlin-native/platformLibs/src/platform/watchos/CFNetwork.def.disabled new file mode 100644 index 00000000000..ea57fb2bc2a --- /dev/null +++ b/kotlin-native/platformLibs/src/platform/watchos/CFNetwork.def.disabled @@ -0,0 +1,6 @@ +language = Objective-C +package = platform.CFNetwork +modules = CFNetwork +compilerOpts = -framework CFNetwork +linkerOpts = -framework CFNetwork +#Disabled: Not officially available for watchos diff --git a/kotlin-native/platformLibs/src/platform/watchos/ClockKit.def b/kotlin-native/platformLibs/src/platform/watchos/ClockKit.def new file mode 100644 index 00000000000..7a28d1d92c9 --- /dev/null +++ b/kotlin-native/platformLibs/src/platform/watchos/ClockKit.def @@ -0,0 +1,9 @@ +depends = CoreFoundation CoreGraphics CoreText Foundation Security UIKit darwin posix +language = Objective-C +package = platform.ClockKit +headers = ClockKit/ClockKit.h + +headerFilter = ClockKit/** + +compilerOpts = -framework ClockKit +linkerOpts = -framework ClockKit diff --git a/kotlin-native/platformLibs/src/platform/watchos/CloudKit.def b/kotlin-native/platformLibs/src/platform/watchos/CloudKit.def new file mode 100644 index 00000000000..05638e6cc1c --- /dev/null +++ b/kotlin-native/platformLibs/src/platform/watchos/CloudKit.def @@ -0,0 +1,7 @@ +depends = CoreFoundation CoreLocation Foundation Security darwin posix +language = Objective-C +package = platform.CloudKit +modules = CloudKit + +compilerOpts = -framework CloudKit +linkerOpts = -framework CloudKit diff --git a/kotlin-native/platformLibs/src/platform/watchos/Combine.def.disabled b/kotlin-native/platformLibs/src/platform/watchos/Combine.def.disabled new file mode 100644 index 00000000000..0fde0deb560 --- /dev/null +++ b/kotlin-native/platformLibs/src/platform/watchos/Combine.def.disabled @@ -0,0 +1,6 @@ +language = Objective-C +package = platform.Combine +modules = Combine +compilerOpts = -framework Combine +linkerOpts = -framework Combine +#Disabled: Swift-only framework diff --git a/kotlin-native/platformLibs/src/platform/watchos/CommonCrypto.def b/kotlin-native/platformLibs/src/platform/watchos/CommonCrypto.def new file mode 100644 index 00000000000..92ce70f00ae --- /dev/null +++ b/kotlin-native/platformLibs/src/platform/watchos/CommonCrypto.def @@ -0,0 +1,6 @@ +depends = darwin posix +language = Objective-C +package = platform.CoreCrypto +modules = CommonCrypto + +compilerOpts = -D_XOPEN_SOURCE diff --git a/kotlin-native/platformLibs/src/platform/watchos/Contacts.def b/kotlin-native/platformLibs/src/platform/watchos/Contacts.def new file mode 100644 index 00000000000..647b379280f --- /dev/null +++ b/kotlin-native/platformLibs/src/platform/watchos/Contacts.def @@ -0,0 +1,7 @@ +depends = CoreFoundation Foundation Security darwin posix +language = Objective-C +package = platform.Contacts +modules = Contacts + +compilerOpts = -framework Contacts +linkerOpts = -framework Contacts diff --git a/kotlin-native/platformLibs/src/platform/watchos/CoreAudio.def b/kotlin-native/platformLibs/src/platform/watchos/CoreAudio.def new file mode 100644 index 00000000000..7f5da857b89 --- /dev/null +++ b/kotlin-native/platformLibs/src/platform/watchos/CoreAudio.def @@ -0,0 +1,7 @@ +depends = CoreAudioTypes CoreFoundation darwin posix +language = Objective-C +package = platform.CoreAudio +modules = CoreAudio + +compilerOpts = -framework CoreAudio +linkerOpts = -framework CoreAudio diff --git a/kotlin-native/platformLibs/src/platform/watchos/CoreAudioTypes.def b/kotlin-native/platformLibs/src/platform/watchos/CoreAudioTypes.def new file mode 100644 index 00000000000..2c8891b94d1 --- /dev/null +++ b/kotlin-native/platformLibs/src/platform/watchos/CoreAudioTypes.def @@ -0,0 +1,6 @@ +depends = CoreFoundation darwin posix +language = Objective-C +package = platform.CoreAudioTypes +modules = CoreAudioTypes + +compilerOpts = -framework CoreAudioTypes diff --git a/kotlin-native/platformLibs/src/platform/watchos/CoreBluetooth.def b/kotlin-native/platformLibs/src/platform/watchos/CoreBluetooth.def new file mode 100644 index 00000000000..7be0b09dd12 --- /dev/null +++ b/kotlin-native/platformLibs/src/platform/watchos/CoreBluetooth.def @@ -0,0 +1,7 @@ +depends = CoreFoundation Foundation Security darwin posix +language = Objective-C +package = platform.CoreBluetooth +modules = CoreBluetooth + +compilerOpts = -framework CoreBluetooth +linkerOpts = -framework CoreBluetooth diff --git a/kotlin-native/platformLibs/src/platform/watchos/CoreData.def b/kotlin-native/platformLibs/src/platform/watchos/CoreData.def new file mode 100644 index 00000000000..fc717655527 --- /dev/null +++ b/kotlin-native/platformLibs/src/platform/watchos/CoreData.def @@ -0,0 +1,7 @@ +depends = CloudKit CoreFoundation CoreLocation Foundation Security darwin posix +language = Objective-C +package = platform.CoreData +modules = CoreData + +compilerOpts = -framework CoreData +linkerOpts = -framework CoreData diff --git a/kotlin-native/platformLibs/src/platform/watchos/CoreFoundation.def b/kotlin-native/platformLibs/src/platform/watchos/CoreFoundation.def new file mode 100644 index 00000000000..17c65eafa38 --- /dev/null +++ b/kotlin-native/platformLibs/src/platform/watchos/CoreFoundation.def @@ -0,0 +1,7 @@ +depends = darwin posix +language = Objective-C +package = platform.CoreFoundation +modules = CoreFoundation + +compilerOpts = -framework CoreFoundation +linkerOpts = -framework CoreFoundation diff --git a/kotlin-native/platformLibs/src/platform/watchos/CoreGraphics.def b/kotlin-native/platformLibs/src/platform/watchos/CoreGraphics.def new file mode 100644 index 00000000000..3951d09f2bd --- /dev/null +++ b/kotlin-native/platformLibs/src/platform/watchos/CoreGraphics.def @@ -0,0 +1,7 @@ +depends = CoreFoundation darwin posix +language = Objective-C +package = platform.CoreGraphics +modules = CoreGraphics + +compilerOpts = -framework CoreGraphics +linkerOpts = -framework CoreGraphics diff --git a/kotlin-native/platformLibs/src/platform/watchos/CoreLocation.def b/kotlin-native/platformLibs/src/platform/watchos/CoreLocation.def new file mode 100644 index 00000000000..341957d1e0c --- /dev/null +++ b/kotlin-native/platformLibs/src/platform/watchos/CoreLocation.def @@ -0,0 +1,7 @@ +depends = CoreFoundation Foundation Security darwin posix +language = Objective-C +package = platform.CoreLocation +modules = CoreLocation + +compilerOpts = -framework CoreLocation +linkerOpts = -framework CoreLocation diff --git a/kotlin-native/platformLibs/src/platform/watchos/CoreML.def b/kotlin-native/platformLibs/src/platform/watchos/CoreML.def new file mode 100644 index 00000000000..12535485a7a --- /dev/null +++ b/kotlin-native/platformLibs/src/platform/watchos/CoreML.def @@ -0,0 +1,7 @@ +depends = CoreFoundation CoreGraphics CoreVideo Foundation ImageIO Security darwin posix +language = Objective-C +package = platform.CoreML +modules = CoreML + +compilerOpts = -framework CoreML +linkerOpts = -framework CoreML diff --git a/kotlin-native/platformLibs/src/platform/watchos/CoreMedia.def b/kotlin-native/platformLibs/src/platform/watchos/CoreMedia.def new file mode 100644 index 00000000000..b6e5c11dd39 --- /dev/null +++ b/kotlin-native/platformLibs/src/platform/watchos/CoreMedia.def @@ -0,0 +1,7 @@ +depends = CoreAudio CoreAudioTypes CoreFoundation CoreGraphics CoreVideo darwin posix +language = Objective-C +package = platform.CoreMedia +modules = CoreMedia + +compilerOpts = -framework CoreMedia +linkerOpts = -framework CoreMedia diff --git a/kotlin-native/platformLibs/src/platform/watchos/CoreMotion.def b/kotlin-native/platformLibs/src/platform/watchos/CoreMotion.def new file mode 100644 index 00000000000..ed274b417ff --- /dev/null +++ b/kotlin-native/platformLibs/src/platform/watchos/CoreMotion.def @@ -0,0 +1,7 @@ +depends = CoreFoundation Foundation Security darwin posix +language = Objective-C +package = platform.CoreMotion +modules = CoreMotion + +compilerOpts = -framework CoreMotion +linkerOpts = -framework CoreMotion diff --git a/kotlin-native/platformLibs/src/platform/watchos/CoreServices.def b/kotlin-native/platformLibs/src/platform/watchos/CoreServices.def new file mode 100644 index 00000000000..ffd15288ee0 --- /dev/null +++ b/kotlin-native/platformLibs/src/platform/watchos/CoreServices.def @@ -0,0 +1,7 @@ +depends = CoreFoundation darwin posix +language = Objective-C +package = platform.CoreServices +modules = CoreServices + +compilerOpts = -framework CoreServices +linkerOpts = -framework CoreServices diff --git a/kotlin-native/platformLibs/src/platform/watchos/CoreText.def b/kotlin-native/platformLibs/src/platform/watchos/CoreText.def new file mode 100644 index 00000000000..3cdfe6f0a47 --- /dev/null +++ b/kotlin-native/platformLibs/src/platform/watchos/CoreText.def @@ -0,0 +1,7 @@ +depends = CoreFoundation CoreGraphics darwin posix +language = Objective-C +package = platform.CoreText +modules = CoreText + +compilerOpts = -framework CoreText +linkerOpts = -framework CoreText diff --git a/kotlin-native/platformLibs/src/platform/watchos/CoreVideo.def b/kotlin-native/platformLibs/src/platform/watchos/CoreVideo.def new file mode 100644 index 00000000000..37362b42c94 --- /dev/null +++ b/kotlin-native/platformLibs/src/platform/watchos/CoreVideo.def @@ -0,0 +1,7 @@ +depends = CoreFoundation CoreGraphics darwin posix +language = Objective-C +package = platform.CoreVideo +modules = CoreVideo + +compilerOpts = -framework CoreVideo +linkerOpts = -framework CoreVideo diff --git a/kotlin-native/platformLibs/src/platform/watchos/CryptoKit.def.disabled b/kotlin-native/platformLibs/src/platform/watchos/CryptoKit.def.disabled new file mode 100644 index 00000000000..1fd5943bf93 --- /dev/null +++ b/kotlin-native/platformLibs/src/platform/watchos/CryptoKit.def.disabled @@ -0,0 +1,6 @@ +language = Objective-C +package = platform.CryptoKit +modules = CryptoKit +compilerOpts = -framework CryptoKit +linkerOpts = -framework CryptoKit +#Disabled: Swift-only framework diff --git a/kotlin-native/platformLibs/src/platform/watchos/DeveloperToolsSupport.def.disabled b/kotlin-native/platformLibs/src/platform/watchos/DeveloperToolsSupport.def.disabled new file mode 100644 index 00000000000..b3e34c7522b --- /dev/null +++ b/kotlin-native/platformLibs/src/platform/watchos/DeveloperToolsSupport.def.disabled @@ -0,0 +1,6 @@ +language = Objective-C +package = platform.DeveloperToolsSupport +modules = DeveloperToolsSupport +compilerOpts = -framework DeveloperToolsSupport +linkerOpts = -framework DeveloperToolsSupport +#Disabled: Swift-only framework diff --git a/kotlin-native/platformLibs/src/platform/watchos/EventKit.def b/kotlin-native/platformLibs/src/platform/watchos/EventKit.def new file mode 100644 index 00000000000..68f02b0a2af --- /dev/null +++ b/kotlin-native/platformLibs/src/platform/watchos/EventKit.def @@ -0,0 +1,7 @@ +depends = CoreFoundation CoreGraphics CoreLocation Foundation Security darwin posix +language = Objective-C +package = platform.EventKit +modules = EventKit + +compilerOpts = -framework EventKit +linkerOpts = -framework EventKit diff --git a/kotlin-native/platformLibs/src/platform/watchos/Foundation.def b/kotlin-native/platformLibs/src/platform/watchos/Foundation.def new file mode 100644 index 00000000000..c6c47e5e642 --- /dev/null +++ b/kotlin-native/platformLibs/src/platform/watchos/Foundation.def @@ -0,0 +1,7 @@ +depends = CoreFoundation Security darwin posix +language = Objective-C +package = platform.Foundation +modules = Foundation + +compilerOpts = -framework Foundation +linkerOpts = -framework Foundation diff --git a/kotlin-native/platformLibs/src/platform/watchos/GameKit.def b/kotlin-native/platformLibs/src/platform/watchos/GameKit.def new file mode 100644 index 00000000000..bac1dd46c3f --- /dev/null +++ b/kotlin-native/platformLibs/src/platform/watchos/GameKit.def @@ -0,0 +1,7 @@ +depends = Contacts CoreFoundation CoreGraphics CoreText Foundation SceneKit Security SpriteKit UIKit darwin posix +language = Objective-C +package = platform.GameKit +modules = GameKit + +compilerOpts = -framework GameKit +linkerOpts = -framework GameKit diff --git a/kotlin-native/platformLibs/src/platform/watchos/HealthKit.def b/kotlin-native/platformLibs/src/platform/watchos/HealthKit.def new file mode 100644 index 00000000000..f45c382b535 --- /dev/null +++ b/kotlin-native/platformLibs/src/platform/watchos/HealthKit.def @@ -0,0 +1,7 @@ +depends = CoreFoundation Foundation Security darwin posix +language = Objective-C +package = platform.HealthKit +modules = HealthKit + +compilerOpts = -framework HealthKit +linkerOpts = -framework HealthKit diff --git a/kotlin-native/platformLibs/src/platform/watchos/HomeKit.def b/kotlin-native/platformLibs/src/platform/watchos/HomeKit.def new file mode 100644 index 00000000000..c9fee4c399d --- /dev/null +++ b/kotlin-native/platformLibs/src/platform/watchos/HomeKit.def @@ -0,0 +1,7 @@ +depends = CoreFoundation CoreGraphics Foundation Security darwin posix +language = Objective-C +package = platform.HomeKit +modules = HomeKit + +compilerOpts = -framework HomeKit +linkerOpts = -framework HomeKit diff --git a/kotlin-native/platformLibs/src/platform/watchos/ImageIO.def b/kotlin-native/platformLibs/src/platform/watchos/ImageIO.def new file mode 100644 index 00000000000..635137a80c9 --- /dev/null +++ b/kotlin-native/platformLibs/src/platform/watchos/ImageIO.def @@ -0,0 +1,7 @@ +depends = CoreFoundation CoreGraphics darwin posix +language = Objective-C +package = platform.ImageIO +modules = ImageIO + +compilerOpts = -framework ImageIO +linkerOpts = -framework ImageIO diff --git a/kotlin-native/platformLibs/src/platform/watchos/Intents.def b/kotlin-native/platformLibs/src/platform/watchos/Intents.def new file mode 100644 index 00000000000..553c94d5094 --- /dev/null +++ b/kotlin-native/platformLibs/src/platform/watchos/Intents.def @@ -0,0 +1,7 @@ +depends = CoreFoundation CoreGraphics CoreLocation Foundation Security darwin posix +language = Objective-C +package = platform.Intents +modules = Intents + +compilerOpts = -framework Intents +linkerOpts = -framework Intents diff --git a/kotlin-native/platformLibs/src/platform/watchos/MapKit.def b/kotlin-native/platformLibs/src/platform/watchos/MapKit.def new file mode 100644 index 00000000000..f299fc52be6 --- /dev/null +++ b/kotlin-native/platformLibs/src/platform/watchos/MapKit.def @@ -0,0 +1,7 @@ +depends = CoreFoundation CoreGraphics CoreLocation CoreText Foundation Security UIKit darwin posix +language = Objective-C +package = platform.MapKit +modules = MapKit + +compilerOpts = -framework MapKit +linkerOpts = -framework MapKit diff --git a/kotlin-native/platformLibs/src/platform/watchos/MediaPlayer.def b/kotlin-native/platformLibs/src/platform/watchos/MediaPlayer.def new file mode 100644 index 00000000000..bf3c20e486f --- /dev/null +++ b/kotlin-native/platformLibs/src/platform/watchos/MediaPlayer.def @@ -0,0 +1,7 @@ +depends = AVFoundation CoreFoundation CoreGraphics CoreMedia Foundation Security darwin posix +language = Objective-C +package = platform.MediaPlayer +modules = MediaPlayer + +compilerOpts = -framework MediaPlayer +linkerOpts = -framework MediaPlayer diff --git a/kotlin-native/platformLibs/src/platform/watchos/MobileCoreServices.def b/kotlin-native/platformLibs/src/platform/watchos/MobileCoreServices.def new file mode 100644 index 00000000000..bdd5356cc09 --- /dev/null +++ b/kotlin-native/platformLibs/src/platform/watchos/MobileCoreServices.def @@ -0,0 +1,7 @@ +depends = CoreFoundation CoreServices darwin posix +language = Objective-C +package = platform.MobileCoreServices +modules = MobileCoreServices + +compilerOpts = -framework MobileCoreServices +linkerOpts = -framework MobileCoreServices diff --git a/kotlin-native/platformLibs/src/platform/watchos/NaturalLanguage.def b/kotlin-native/platformLibs/src/platform/watchos/NaturalLanguage.def new file mode 100644 index 00000000000..64a98081406 --- /dev/null +++ b/kotlin-native/platformLibs/src/platform/watchos/NaturalLanguage.def @@ -0,0 +1,7 @@ +depends = CoreFoundation Foundation Security darwin posix +language = Objective-C +package = platform.NaturalLanguage +modules = NaturalLanguage + +compilerOpts = -framework NaturalLanguage +linkerOpts = -framework NaturalLanguage diff --git a/kotlin-native/platformLibs/src/platform/watchos/Network.def b/kotlin-native/platformLibs/src/platform/watchos/Network.def new file mode 100644 index 00000000000..b1664c1b04f --- /dev/null +++ b/kotlin-native/platformLibs/src/platform/watchos/Network.def @@ -0,0 +1,7 @@ +depends = CoreFoundation Security darwin posix +language = Objective-C +package = platform.Network +modules = Network + +compilerOpts = -framework Network +linkerOpts = -framework Network diff --git a/kotlin-native/platformLibs/src/platform/watchos/NetworkExtension.def b/kotlin-native/platformLibs/src/platform/watchos/NetworkExtension.def new file mode 100644 index 00000000000..e484ae1784b --- /dev/null +++ b/kotlin-native/platformLibs/src/platform/watchos/NetworkExtension.def @@ -0,0 +1,6 @@ +depends = CoreFoundation Foundation Network Security darwin posix +language = Objective-C +package = platform.NetworkExtension +modules = NetworkExtension +compilerOpts = -framework NetworkExtension +linkerOpts = -framework NetworkExtension diff --git a/kotlin-native/platformLibs/src/platform/watchos/PassKit.def b/kotlin-native/platformLibs/src/platform/watchos/PassKit.def new file mode 100644 index 00000000000..29ef56bbe0d --- /dev/null +++ b/kotlin-native/platformLibs/src/platform/watchos/PassKit.def @@ -0,0 +1,7 @@ +depends = Contacts CoreFoundation CoreGraphics Foundation Security darwin posix +language = Objective-C +package = platform.PassKit +modules = PassKit + +compilerOpts = -framework PassKit +linkerOpts = -framework PassKit diff --git a/kotlin-native/platformLibs/src/platform/watchos/PushKit.def b/kotlin-native/platformLibs/src/platform/watchos/PushKit.def new file mode 100644 index 00000000000..56e1bd9daf9 --- /dev/null +++ b/kotlin-native/platformLibs/src/platform/watchos/PushKit.def @@ -0,0 +1,7 @@ +depends = CoreFoundation Foundation Security darwin posix +language = Objective-C +package = platform.PushKit +modules = PushKit + +compilerOpts = -framework PushKit +linkerOpts = -framework PushKit diff --git a/kotlin-native/platformLibs/src/platform/watchos/SceneKit.def b/kotlin-native/platformLibs/src/platform/watchos/SceneKit.def new file mode 100644 index 00000000000..8d578fa9b7a --- /dev/null +++ b/kotlin-native/platformLibs/src/platform/watchos/SceneKit.def @@ -0,0 +1,7 @@ +depends = CoreFoundation CoreGraphics Foundation Security darwin posix +language = Objective-C +package = platform.SceneKit +modules = SceneKit + +compilerOpts = -framework SceneKit +linkerOpts = -framework SceneKit diff --git a/kotlin-native/platformLibs/src/platform/watchos/Security.def b/kotlin-native/platformLibs/src/platform/watchos/Security.def new file mode 100644 index 00000000000..de56b282a23 --- /dev/null +++ b/kotlin-native/platformLibs/src/platform/watchos/Security.def @@ -0,0 +1,7 @@ +depends = CoreFoundation darwin posix +language = Objective-C +package = platform.Security +modules = Security + +compilerOpts = -framework Security +linkerOpts = -framework Security diff --git a/kotlin-native/platformLibs/src/platform/watchos/SoundAnalysis.def b/kotlin-native/platformLibs/src/platform/watchos/SoundAnalysis.def new file mode 100644 index 00000000000..32857754c17 --- /dev/null +++ b/kotlin-native/platformLibs/src/platform/watchos/SoundAnalysis.def @@ -0,0 +1,7 @@ +depends = AVFoundation CoreAudio CoreAudioTypes CoreFoundation CoreGraphics CoreML CoreMedia CoreVideo Foundation ImageIO Security UniformTypeIdentifiers darwin posix +language = Objective-C +package = platform.SoundAnalysis +modules = SoundAnalysis + +compilerOpts = -framework SoundAnalysis +linkerOpts = -framework SoundAnalysis diff --git a/kotlin-native/platformLibs/src/platform/watchos/SpriteKit.def b/kotlin-native/platformLibs/src/platform/watchos/SpriteKit.def new file mode 100644 index 00000000000..766d9c57f5e --- /dev/null +++ b/kotlin-native/platformLibs/src/platform/watchos/SpriteKit.def @@ -0,0 +1,7 @@ +depends = CoreFoundation CoreGraphics CoreText Foundation Security UIKit darwin posix +language = Objective-C +package = platform.SpriteKit +modules = SpriteKit + +compilerOpts = -framework SpriteKit +linkerOpts = -framework SpriteKit diff --git a/kotlin-native/platformLibs/src/platform/watchos/StoreKit.def b/kotlin-native/platformLibs/src/platform/watchos/StoreKit.def new file mode 100644 index 00000000000..98b46db60d3 --- /dev/null +++ b/kotlin-native/platformLibs/src/platform/watchos/StoreKit.def @@ -0,0 +1,7 @@ +depends = CoreFoundation Foundation Security darwin posix +language = Objective-C +package = platform.StoreKit +modules = StoreKit + +compilerOpts = -framework StoreKit +linkerOpts = -framework StoreKit diff --git a/kotlin-native/platformLibs/src/platform/watchos/SwiftUI.def.disabled b/kotlin-native/platformLibs/src/platform/watchos/SwiftUI.def.disabled new file mode 100644 index 00000000000..59c29eff39e --- /dev/null +++ b/kotlin-native/platformLibs/src/platform/watchos/SwiftUI.def.disabled @@ -0,0 +1,6 @@ +language = Objective-C +package = platform.SwiftUI +modules = SwiftUI +compilerOpts = -framework SwiftUI +linkerOpts = -framework SwiftUI +#Disabled: Swift-only framework diff --git a/kotlin-native/platformLibs/src/platform/watchos/UIKit.def b/kotlin-native/platformLibs/src/platform/watchos/UIKit.def new file mode 100644 index 00000000000..4a9ff724ddc --- /dev/null +++ b/kotlin-native/platformLibs/src/platform/watchos/UIKit.def @@ -0,0 +1,7 @@ +depends = CoreFoundation CoreGraphics CoreText Foundation Security darwin posix +language = Objective-C +package = platform.UIKit +modules = UIKit + +compilerOpts = -framework UIKit +linkerOpts = -framework UIKit diff --git a/kotlin-native/platformLibs/src/platform/watchos/UniformTypeIdentifiers.def b/kotlin-native/platformLibs/src/platform/watchos/UniformTypeIdentifiers.def new file mode 100644 index 00000000000..11d64631ed9 --- /dev/null +++ b/kotlin-native/platformLibs/src/platform/watchos/UniformTypeIdentifiers.def @@ -0,0 +1,6 @@ +depends = CoreFoundation Foundation Security darwin posix +language = Objective-C +package = platform.UniformTypeIdentifiers +modules = UniformTypeIdentifiers +compilerOpts = -framework UniformTypeIdentifiers +linkerOpts = -framework UniformTypeIdentifiers diff --git a/kotlin-native/platformLibs/src/platform/watchos/UserNotifications.def b/kotlin-native/platformLibs/src/platform/watchos/UserNotifications.def new file mode 100644 index 00000000000..6ee347f5edb --- /dev/null +++ b/kotlin-native/platformLibs/src/platform/watchos/UserNotifications.def @@ -0,0 +1,9 @@ +depends = CoreFoundation Foundation Security darwin posix +language = Objective-C +package = platform.UserNotifications +headers = UserNotifications/UserNotifications.h + +headerFilter = UserNotifications/** + +compilerOpts = -framework UserNotifications +linkerOpts = -framework UserNotifications diff --git a/kotlin-native/platformLibs/src/platform/watchos/WatchConnectivity.def b/kotlin-native/platformLibs/src/platform/watchos/WatchConnectivity.def new file mode 100644 index 00000000000..70e512b2e42 --- /dev/null +++ b/kotlin-native/platformLibs/src/platform/watchos/WatchConnectivity.def @@ -0,0 +1,7 @@ +depends = CoreFoundation Foundation Security darwin posix +language = Objective-C +package = platform.WatchConnectivity +modules = WatchConnectivity + +compilerOpts = -framework WatchConnectivity +linkerOpts = -framework WatchConnectivity diff --git a/kotlin-native/platformLibs/src/platform/watchos/WatchKit.def b/kotlin-native/platformLibs/src/platform/watchos/WatchKit.def new file mode 100644 index 00000000000..171b2aa8810 --- /dev/null +++ b/kotlin-native/platformLibs/src/platform/watchos/WatchKit.def @@ -0,0 +1,7 @@ +depends = CoreFoundation CoreGraphics CoreLocation CoreText Foundation HomeKit MapKit SceneKit Security UIKit darwin posix +language = Objective-C +package = platform.WatchKit +modules = WatchKit + +compilerOpts = -framework WatchKit +linkerOpts = -framework WatchKit diff --git a/kotlin-native/platformLibs/src/platform/watchos/_AVKit_SwiftUI.def.disabled b/kotlin-native/platformLibs/src/platform/watchos/_AVKit_SwiftUI.def.disabled new file mode 100644 index 00000000000..04754e56b1b --- /dev/null +++ b/kotlin-native/platformLibs/src/platform/watchos/_AVKit_SwiftUI.def.disabled @@ -0,0 +1,6 @@ +language = Objective-C +package = platform._AVKit_SwiftUI +modules = _AVKit_SwiftUI +compilerOpts = -framework _AVKit_SwiftUI +linkerOpts = -framework _AVKit_SwiftUI +#Disabled: Unavailable diff --git a/kotlin-native/platformLibs/src/platform/watchos/_AuthenticationServices_SwiftUI.def.disabled b/kotlin-native/platformLibs/src/platform/watchos/_AuthenticationServices_SwiftUI.def.disabled new file mode 100644 index 00000000000..ff6eb919630 --- /dev/null +++ b/kotlin-native/platformLibs/src/platform/watchos/_AuthenticationServices_SwiftUI.def.disabled @@ -0,0 +1,6 @@ +language = Objective-C +package = platform._AuthenticationServices_SwiftUI +modules = _AuthenticationServices_SwiftUI +compilerOpts = -framework _AuthenticationServices_SwiftUI +linkerOpts = -framework _AuthenticationServices_SwiftUI +#Disabled: Unavailable diff --git a/kotlin-native/platformLibs/src/platform/watchos/_ClockKit_SwiftUI.def.disabled b/kotlin-native/platformLibs/src/platform/watchos/_ClockKit_SwiftUI.def.disabled new file mode 100644 index 00000000000..ea2c3117e9c --- /dev/null +++ b/kotlin-native/platformLibs/src/platform/watchos/_ClockKit_SwiftUI.def.disabled @@ -0,0 +1,6 @@ +language = Objective-C +package = platform._ClockKit_SwiftUI +modules = _ClockKit_SwiftUI +compilerOpts = -framework _ClockKit_SwiftUI +linkerOpts = -framework _ClockKit_SwiftUI +#Disabled: Unavailable diff --git a/kotlin-native/platformLibs/src/platform/watchos/_HomeKit_SwiftUI.def.disabled b/kotlin-native/platformLibs/src/platform/watchos/_HomeKit_SwiftUI.def.disabled new file mode 100644 index 00000000000..d5e70d04710 --- /dev/null +++ b/kotlin-native/platformLibs/src/platform/watchos/_HomeKit_SwiftUI.def.disabled @@ -0,0 +1,6 @@ +language = Objective-C +package = platform._HomeKit_SwiftUI +modules = _HomeKit_SwiftUI +compilerOpts = -framework _HomeKit_SwiftUI +linkerOpts = -framework _HomeKit_SwiftUI +#Disabled: Unavailable diff --git a/kotlin-native/platformLibs/src/platform/watchos/_MapKit_SwiftUI.def.disabled b/kotlin-native/platformLibs/src/platform/watchos/_MapKit_SwiftUI.def.disabled new file mode 100644 index 00000000000..3accf28420d --- /dev/null +++ b/kotlin-native/platformLibs/src/platform/watchos/_MapKit_SwiftUI.def.disabled @@ -0,0 +1,6 @@ +language = Objective-C +package = platform._MapKit_SwiftUI +modules = _MapKit_SwiftUI +compilerOpts = -framework _MapKit_SwiftUI +linkerOpts = -framework _MapKit_SwiftUI +#Disabled: Unavailable diff --git a/kotlin-native/platformLibs/src/platform/watchos/_SceneKit_SwiftUI.def.disabled b/kotlin-native/platformLibs/src/platform/watchos/_SceneKit_SwiftUI.def.disabled new file mode 100644 index 00000000000..4e18821c3d0 --- /dev/null +++ b/kotlin-native/platformLibs/src/platform/watchos/_SceneKit_SwiftUI.def.disabled @@ -0,0 +1,6 @@ +language = Objective-C +package = platform._SceneKit_SwiftUI +modules = _SceneKit_SwiftUI +compilerOpts = -framework _SceneKit_SwiftUI +linkerOpts = -framework _SceneKit_SwiftUI +#Disabled: Unavailable diff --git a/kotlin-native/platformLibs/src/platform/watchos/_SpriteKit_SwiftUI.def.disabled b/kotlin-native/platformLibs/src/platform/watchos/_SpriteKit_SwiftUI.def.disabled new file mode 100644 index 00000000000..572286b1f66 --- /dev/null +++ b/kotlin-native/platformLibs/src/platform/watchos/_SpriteKit_SwiftUI.def.disabled @@ -0,0 +1,6 @@ +language = Objective-C +package = platform._SpriteKit_SwiftUI +modules = _SpriteKit_SwiftUI +compilerOpts = -framework _SpriteKit_SwiftUI +linkerOpts = -framework _SpriteKit_SwiftUI +#Disabled: Unavailable diff --git a/kotlin-native/platformLibs/src/platform/watchos/_WatchKit_SwiftUI.def.disabled b/kotlin-native/platformLibs/src/platform/watchos/_WatchKit_SwiftUI.def.disabled new file mode 100644 index 00000000000..c796f381869 --- /dev/null +++ b/kotlin-native/platformLibs/src/platform/watchos/_WatchKit_SwiftUI.def.disabled @@ -0,0 +1,6 @@ +language = Objective-C +package = platform._WatchKit_SwiftUI +modules = _WatchKit_SwiftUI +compilerOpts = -framework _WatchKit_SwiftUI +linkerOpts = -framework _WatchKit_SwiftUI +#Disabled: Unavailable diff --git a/kotlin-native/platformLibs/src/platform/watchos/builtin.def b/kotlin-native/platformLibs/src/platform/watchos/builtin.def new file mode 100644 index 00000000000..21a9cb18d1d --- /dev/null +++ b/kotlin-native/platformLibs/src/platform/watchos/builtin.def @@ -0,0 +1,100 @@ +depends = posix +package = platform.builtin +headerFilter = ** +language = C + +excludedFunctions.watchos_arm32 = builtin_clear_cache +--- +// See https://github.com/llvm-mirror/clang/blob/master/include/clang/Basic/Builtins.def +// TODO: autogenerate from machine format. + +// Returns x with the order of the bytes reversed; for example, 0xaabb becomes 0xbbaa. Byte here always means exactly 8 bits. +static inline short builtin_bswap16(short x) { + return __builtin_bswap16(x); +} + +static inline int builtin_bswap32(int x) { + return __builtin_bswap32(x); +} + +static inline long long builtin_bswap64(long long x) { + return __builtin_bswap64(x); +} + +// Returns the number of leading 0-bits in x, starting at the most significant bit position. If x is 0, the result is undefined. +static inline int builtin_clzs(unsigned short x) { + return __builtin_clzs(x); +} + +static inline int builtin_clz(unsigned int x) { + return __builtin_clz(x); +} + +static inline int builtin_clzl(unsigned long x) { + return __builtin_clzl(x); +} + +static inline int builtin_clzll(unsigned long long x) { + return __builtin_clzll(x); +} + +// Returns the number of trailing 0-bits in x, starting at the least significant bit position. If x is 0, the result is undefined. +static inline int builtin_ctzs(unsigned short x) { + return __builtin_ctzs(x); +} + +static inline int builtin_ctz(unsigned int x) { + return __builtin_ctz(x); +} + +static inline int builtin_ctzl(unsigned long x) { + return __builtin_ctzl(x); +} + +static inline int builtin_ctzll(unsigned long long x) { + return __builtin_ctzll(x); +} + +// Returns one plus the index of the least significant 1-bit of x, or if x is zero, returns zero. +static inline int builtin_ffs(int x) { + return __builtin_ffs(x); +} + +static inline int builtin_ffsl(long x) { + return __builtin_ffsl(x); +} + +static inline int builtin_ffsll(long long x) { + return __builtin_ffsll(x); +} + +// Returns the parity of x, i.e. the number of 1-bits in x modulo 2. +static inline int builtin_parity(int x) { + return __builtin_parity(x); +} + +static inline int builtin_parityl(unsigned long x) { + return __builtin_parityl(x); +} + +static inline int builtin_parityll(unsigned long long x) { + return __builtin_parityll(x); +} + +// Returns the number of 1-bits in x. +static inline int builtin_popcount(int x) { + return __builtin_popcount(x); +} + +static inline int builtin_popcountl(long x) { + return __builtin_popcountl(x); +} + +static inline int builtin_popcountll(long long x) { + return __builtin_popcountll(x); +} + +// This function is used to flush the processor's instruction cache for the region of memory between begin inclusive and end exclusive. +static inline void builtin_clear_cache(void* begin, void* end) { + __builtin___clear_cache(begin, end); +} diff --git a/kotlin-native/platformLibs/src/platform/watchos/darwin.def b/kotlin-native/platformLibs/src/platform/watchos/darwin.def new file mode 100644 index 00000000000..7a69b07a961 --- /dev/null +++ b/kotlin-native/platformLibs/src/platform/watchos/darwin.def @@ -0,0 +1,48 @@ +depends = posix +language = Objective-C +package = platform.darwin +headers = AssertMacros.h Availability.h AvailabilityInternal.h \ + AvailabilityMacros.h Block.h ConditionalMacros.h MacTypes.h \ + TargetConditionals.h __cxxabi_config.h _locale.h _types.h _wctype.h \ + aio.h asl.h bitstring.h bzlib.h \ + cache.h cache_callbacks.h checkint.h compression.h copyfile.h \ + cpio.h cxxabi.h db.h \ + dns.h dns_sd.h dns_util.h execinfo.h \ + fmtmsg.h fstab.h \ + gethostuuid.h glob.h ifaddrs.h inttypes.h iso646.h \ + langinfo.h \ + libgen.h libunwind.h \ + membership.h monetary.h mpool.h \ + nameser.h ndbm.h nl_types.h \ + notify.h notify_keys.h ntsid.h \ + printf.h \ + readpassphrase.h removefile.h \ + runetype.h sandbox.h standards.h \ + stringlist.h sysdir.h sysexits.h tar.h \ + ttyent.h \ + unwind.h util.h utmpx.h vis.h wordexp.h xattr_flags.h \ + bank/bank_types.h \ + bsm/audit.h \ + os/activity.h os/availability.h os/base.h os/lock.h \ + os/log.h os/object.h os/overflow.h os/signpost.h os/trace.h \ + simd/simd.h sys/sysctl.h + +headerFilter = ** + +excludedFunctions = __tg_promote KERNEL_AUDIT_TOKEN KERNEL_SECURITY_TOKEN \ + asl_decode_buffer asl_encode_buffer asl_remove_index \ + averunnable dbm_forder pidlock ttyaction ttylock ttymsg ttyunlock uuid_generate_early_random \ + vm_stats + +# These functions are depend on __arm__ macro. Include them back +# when our LLVM distribution will gain support for arm64_32 target. +excludedFunctions.watchos_arm64 = _simd_ceil_f4 _simd_ceil_d2 _simd_floor_f4 _simd_floor_d2 \ + _simd_rint_f4 _simd_rint_d2 _simd_trunc_f4 _simd_trunc_d2 \ + __tg_trunc __tg_ceil __tg_rint __tg_floor simd_fract + +compilerOpts = -D_XOPEN_SOURCE -DSYSCTL_DEF_ENABLED +linkerOpts = -ldl -lz -lbz2 -lcompression + +--- +// AppleTextureEncoder.h is not available for WatchOS simulator +// menu.h is excluded so far due to interop issues. diff --git a/kotlin-native/platformLibs/src/platform/watchos/iconv.def b/kotlin-native/platformLibs/src/platform/watchos/iconv.def new file mode 100644 index 00000000000..e52d20f4da0 --- /dev/null +++ b/kotlin-native/platformLibs/src/platform/watchos/iconv.def @@ -0,0 +1,5 @@ +depends = posix +package = platform.iconv +headers = iconv.h +headerFilter = ** +linkerOpts = -liconv diff --git a/kotlin-native/platformLibs/src/platform/watchos/objc.def b/kotlin-native/platformLibs/src/platform/watchos/objc.def new file mode 100644 index 00000000000..96ff037fdf8 --- /dev/null +++ b/kotlin-native/platformLibs/src/platform/watchos/objc.def @@ -0,0 +1,16 @@ +depends = darwin posix +language = Objective-C +package = platform.objc +headers = objc/NSObjCRuntime.h objc/NSObject.h objc/message.h objc/objc-api.h \ + objc/objc-exception.h objc/objc-sync.h objc/objc.h objc/runtime.h + +headerFilter = objc/** + +excludedFunctions.watchos_arm64 = _objc_msgForward_stret \ + class_getMethodImplementation_stret method_invoke_stret + +compilerOpts = -D_XOPEN_SOURCE +linkerOpts = -lobjc + +--- +// objc-auto.h is excluded so far due to interop issues. diff --git a/kotlin-native/platformLibs/src/platform/watchos/posix.def b/kotlin-native/platformLibs/src/platform/watchos/posix.def new file mode 100644 index 00000000000..570b5f93a00 --- /dev/null +++ b/kotlin-native/platformLibs/src/platform/watchos/posix.def @@ -0,0 +1,50 @@ +depends = +package = platform.posix +headers = alloca.h assert.h complex.h ctype.h dirent.h dlfcn.h err.h errno.h fcntl.h \ + fenv.h float.h fnmatch.h fts.h ftw.h getopt.h grp.h inttypes.h libgen.h limits.h \ + locale.h math.h memory.h netdb.h paths.h poll.h \ + pthread.h pwd.h regex.h resolv.h sched.h search.h semaphore.h setjmp.h signal.h \ + stdatomic.h stdint.h stdio.h stdlib.h string.h strings.h syslog.h termios.h \ + time.h ucontext.h unistd.h utime.h wchar.h wctype.h xlocale.h \ + net/ethernet.h net/if.h \ + netinet/icmp6.h netinet/in.h netinet/in_systm.h \ + netinet/ip.h netinet/ip6.h netinet/ip_icmp.h netinet/tcp.h netinet/udp.h \ + sys/acl.h sys/ioctl.h sys/ipc.h sys/mman.h sys/poll.h \ + sys/queue.h sys/select.h sys/shm.h sys/stat.h \ + sys/syslimits.h sys/time.h sys/times.h sys/utsname.h sys/wait.h + +compilerOpts = -D_XOPEN_SOURCE -D_DARWIN_C_SOURCE +linkerOpts = -ldl -lresolv + +excludedFunctions = acl_valid_link_np pfctlinput profil unwhiteout zopen getdirentries \ + uuid_generate_early_random setgrfile \ + getcontext makecontext setcontext swapcontext +excludedFunctions.watchos_arm32 = longjmperror +excludedFunctions.watchos_arm64 = longjmperror +excludedFunctions.watchos_x86 = pthread_jit_write_protect_np pthread_jit_write_protect_supported_np + +--- +// Wrapper to access errno variable. +static int posix_errno() { + return errno; +} + +static void set_posix_errno(int value) { + errno = value; +} + +// Wrapper to access h_errno variable. +static int posix_h_errno() { + return h_errno; +} + +static void set_posix_h_errno(int value) { + h_errno = value; +} + +static int init_sockets() { + return 0; +} + +static void deinit_sockets() { +} diff --git a/kotlin-native/platformLibs/src/platform/watchos/set_depends.sh b/kotlin-native/platformLibs/src/platform/watchos/set_depends.sh new file mode 100755 index 00000000000..78e459849bd --- /dev/null +++ b/kotlin-native/platformLibs/src/platform/watchos/set_depends.sh @@ -0,0 +1,9 @@ +#!/bin/bash +../../../../dist/bin/run_konan defFileDependencies \ + -target watchos_arm32 \ + -target watchos_x86 \ + *.def + +#TODO: Reenable targets +# -target watchos_arm64 \ +# -target watchos_x64 \ diff --git a/kotlin-native/platformLibs/src/platform/watchos/zlib.def b/kotlin-native/platformLibs/src/platform/watchos/zlib.def new file mode 100644 index 00000000000..8292dd723fa --- /dev/null +++ b/kotlin-native/platformLibs/src/platform/watchos/zlib.def @@ -0,0 +1,34 @@ +depends = posix +package = platform.zlib +headers = zconf.h zlib.h +headerFilter = zconf.h zlib.h +compilerOpts = -DByte=uByte -DBytef=uBytef +linkerOpts = -lz + +--- +#undef deflateInit +static inline int deflateInit(z_streamp strm, int level) { + return deflateInit_(strm, level, ZLIB_VERSION, (int)sizeof(z_stream)); +} + +#undef deflateInit2 +static inline int deflateInit2(z_streamp strm, int level, int method, + int windowBits, int memLevel, int strategy) { + return deflateInit2_(strm, level, method, windowBits, memLevel, + strategy, ZLIB_VERSION, (int)sizeof(z_stream)); +} + +#undef inflateInit +static inline int inflateInit(z_streamp strm) { + return inflateInit_(strm, ZLIB_VERSION, (int)sizeof(z_stream)); +} + +#undef inflateInit2 +static inline int inflateInit2(z_streamp strm, int windowBits) { + return inflateInit2_(strm, windowBits, ZLIB_VERSION, (int)sizeof(z_stream)); +} + +#undef inflateBackInit +static inline int inflateBackInit(z_streamp strm, int windowBits, unsigned char *window) { + return inflateBackInit_(strm, windowBits, window, ZLIB_VERSION, (int)sizeof(z_stream)); +} diff --git a/kotlin-native/runtime/CMakeLists.txt b/kotlin-native/runtime/CMakeLists.txt new file mode 100644 index 00000000000..1afc954d167 --- /dev/null +++ b/kotlin-native/runtime/CMakeLists.txt @@ -0,0 +1,99 @@ +# Disclaimer: this is a straw-man attempt to add navigation to Clion or similar tools. +# At the moment it can't be used for real building or debugging. Feel free to contribute + +cmake_minimum_required(VERSION 3.14) +project(runtime) + +set(CMAKE_CXX_STANDARD 14) + +set(SRC_DIR ${CMAKE_SOURCE_DIR}/src) + +set(GOOGLETEST_DIR ${CMAKE_SOURCE_DIR}/googletest) + +include_directories(${SRC_DIR}/main/cpp) +include_directories(${SRC_DIR}/debug/headers) +include_directories(${CMAKE_SOURCE_DIR}/../common/src/hash/headers) + +include_directories(${GOOGLETEST_DIR}/googletest/include) +include_directories(${GOOGLETEST_DIR}/googlemock/include) + +add_executable(runtime + src/main/cpp/Arrays.cpp + src/main/cpp/Atomic.cpp + src/main/cpp/Boxing.cpp + src/main/cpp/Console.cpp + src/main/cpp/CyclicCollector.cpp + src/main/cpp/Exceptions.cpp + src/main/cpp/ExecFormat.cpp + src/main/cpp/Interop.cpp + src/main/cpp/JSInterop.cpp + src/main/cpp/KAssert.cpp + src/main/cpp/KString.cpp + src/main/cpp/KotlinMath.cpp + src/main/cpp/Memory.cpp + src/main/cpp/MemorySharedRefs.cpp + src/main/cpp/Natives.cpp + src/main/cpp/ObjCExceptions.cpp + src/main/cpp/Operator.cpp + src/main/cpp/Porting.cpp + src/main/cpp/Regex.cpp + src/main/cpp/ReturnSlot.cpp + src/main/cpp/Runtime.cpp + src/main/cpp/StdCppStubs.cpp + src/main/cpp/Time.cpp + src/main/cpp/ToString.cpp + src/main/cpp/TypeInfo.cpp + src/main/cpp/Types.cpp + src/main/cpp/Weak.cpp + src/main/cpp/Worker.cpp + src/main/cpp/dlmalloc/malloc.cpp + src/main/cpp/dtoa/cbigint.cpp + src/main/cpp/dtoa/dblparse.cpp + src/main/cpp/dtoa/fltparse.cpp + src/main/cpp/math/fmod.cpp + src/main/cpp/math/fmodf.cpp + src/main/cpp/math/scalbn.cpp + src/main/cpp/snprintf/snprintf.cpp + src/profile_runtime/cpp/ProfileRuntime.cpp + src/relaxed/cpp/MemoryImpl.cpp + src/release/cpp/SourceInfo.cpp + src/strict/cpp/MemoryImpl.cpp + + src/opt_alloc/cpp/AllocImpl.cpp + src/std_alloc/cpp/AllocImpl.cpp + + src/debug/cpp/KDebug.cpp + src/debug/cpp/SourceInfo.cpp + src/exceptions_support/cpp/ExceptionsSupport.cpp + src/launcher/cpp/androidLauncher.cpp + src/launcher/cpp/launcher.cpp + + src/main/cpp/ObjCExport.mm + src/main/cpp/ObjCInterop.mm + src/main/cpp/ObjCInteropUtils.mm + src/main/cpp/ObjCExportCollectionUtils.mm + src/main/cpp/ObjCExportErrors.mm + src/main/cpp/ObjCExportExceptionDetails.mm + + src/objc/cpp/ObjCExportNumbers.mm + src/objc/cpp/ObjCExportClasses.mm + src/objc/cpp/ObjCExportCollections.mm + src/objc/cpp/ObjCInteropUtilsClasses.mm + + # Tests + src/test_support/cpp/CompilerGenerated.cpp + src/test_support/cpp/CompilerGeneratedObjC.mm + src/test_support/cpp/TestLauncher.cpp + + src/main/cpp/ArraysTest.cpp +) + +target_compile_definitions(runtime PUBLIC "-DKONAN_OSX=1") +target_compile_definitions(runtime PUBLIC "-DKONAN_MACOSX=1") +target_compile_definitions(runtime PUBLIC "-DKONAN_X64=1") +target_compile_definitions(runtime PUBLIC "-DKONAN_OBJC_INTEROP") +target_compile_definitions(runtime PUBLIC "-DKONAN_CORE_SYMBOLICATION=1") +target_compile_definitions(runtime PUBLIC "-DKONAN_HAS_CXX11_EXCEPTION_FUNCTIONS=1") +target_compile_definitions(runtime PUBLIC "-DKONAN_REPORT_BACKTRACE_TO_IOS_CRASH_LOG=1") + + diff --git a/kotlin-native/runtime/build.gradle.kts b/kotlin-native/runtime/build.gradle.kts new file mode 100644 index 00000000000..ada106b7faa --- /dev/null +++ b/kotlin-native/runtime/build.gradle.kts @@ -0,0 +1,218 @@ +/* + * Copyright 2010-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ +import org.jetbrains.kotlin.* +import org.jetbrains.kotlin.testing.native.* +import org.jetbrains.kotlin.bitcode.CompileToBitcode + +plugins { + id("compile-to-bitcode") + id("runtime-testing") +} + +googletest { + revision = project.property("gtestRevision") as String + refresh = project.hasProperty("refresh-gtest") +} + +fun CompileToBitcode.includeRuntime() { + headersDirs += files("../common/src/hash/headers", "src/main/cpp") +} + +val hostName: String by project +val targetList: List by project + +bitcode { + create("runtime", file("src/main")) { + dependsOn( + ":common:${target}Hash", + "${target}StdAlloc", + "${target}OptAlloc", + "${target}Mimalloc", + "${target}Launcher", + "${target}Debug", + "${target}Release", + "${target}Strict", + "${target}Relaxed", + "${target}ProfileRuntime", + "${target}Objc", + "${target}ExceptionsSupport", + "${target}LegacyMemoryManager", + "${target}ExperimentalMemoryManager" + ) + includeRuntime() + linkerArgs.add(project.file("../common/build/bitcode/main/$target/hash.bc").path) + } + + create("mimalloc") { + language = CompileToBitcode.Language.C + includeFiles = listOf("**/*.c") + excludeFiles += listOf("**/alloc-override*.c", "**/page-queue.c", "**/static.c", "**/bitmap.inc.c") + srcDirs = files("$srcRoot/c") + compilerArgs.addAll(listOf("-DKONAN_MI_MALLOC=1", "-Wno-unknown-pragmas", "-ftls-model=initial-exec", + "-Wno-unused-function", "-Wno-error=atomic-alignment", + "-Wno-unused-parameter" /* for windows 32*/)) + headersDirs = files("$srcRoot/c/include") + + onlyIf { targetSupportsMimallocAllocator(target) } + } + + create("launcher") { + includeRuntime() + } + + create("debug") { + includeRuntime() + } + + create("std_alloc") + create("opt_alloc") + + create("exceptionsSupport", file("src/exceptions_support")) { + includeRuntime() + } + + create("release") { + includeRuntime() + } + + create("strict") { + includeRuntime() + } + + create("relaxed") { + includeRuntime() + } + + create("profileRuntime", file("src/profile_runtime")) + + create("objc") { + includeRuntime() + } + + create("test_support", outputGroup = "test") { + includeRuntime() + dependsOn("downloadGoogleTest") + headersDirs += googletest.headersDirs + } + + create("legacy_memory_manager", file("src/legacymm")) { + includeRuntime() + } + + create("experimental_memory_manager", file("src/mm")) { + includeRuntime() + } +} + +targetList.forEach { targetName -> + createTestTask( + project, + "StdAlloc", + "${targetName}StdAllocRuntimeTests", + listOf( + "${targetName}Runtime", + "${targetName}LegacyMemoryManager", + "${targetName}Strict", + "${targetName}Release", + "${targetName}StdAlloc" + ) + ) { + includeRuntime() + } + + createTestTask( + project, + "Mimalloc", + "${targetName}MimallocRuntimeTests", + listOf( + "${targetName}Runtime", + "${targetName}LegacyMemoryManager", + "${targetName}Strict", + "${targetName}Release", + "${targetName}Mimalloc", + "${targetName}OptAlloc" + ) + ) { + includeRuntime() + } + + createTestTask( + project, + "ExperimentalMM", + "${targetName}ExperimentalMMRuntimeTests", + listOf( + "${targetName}Runtime", + "${targetName}ExperimentalMemoryManager", + "${targetName}Release", + "${targetName}Mimalloc", + "${targetName}OptAlloc" + ) + ) + + tasks.register("${targetName}RuntimeTests") { + dependsOn("${targetName}StdAllocRuntimeTests") + dependsOn("${targetName}MimallocRuntimeTests") + dependsOn("${targetName}ExperimentalMMRuntimeTests") + } +} + +val hostRuntime by tasks.registering { + dependsOn("${hostName}Runtime") +} + +val hostRuntimeTests by tasks.registering { + dependsOn("${hostName}RuntimeTests") +} + +val hostStdAllocRuntimeTests by tasks.registering { + dependsOn("${hostName}StdAllocRuntimeTests") +} + +val hostMimallocRuntimeTests by tasks.registering { + dependsOn("${hostName}MimallocRuntimeTests") +} + +val hostExperimentalMMRuntimeTests by tasks.registering { + dependsOn("${hostName}ExperimentalMMRuntimeTests") +} + +val assemble by tasks.registering { + dependsOn(tasks.withType(CompileToBitcode::class).matching { + it.outputGroup == "main" + }) +} + +val clean by tasks.registering { + doLast { + delete(buildDir) + } +} + +val generateJsMath by tasks.registering { + dependsOn(":distCompiler") + doLast { + val distDir: File by project + val jsinteropScript = if (PlatformInfo.isWindows()) "jsinterop.bat" else "jsinterop" + val jsinterop = "$distDir/bin/$jsinteropScript" + val targetDir = "$buildDir/generated" + + project.exec { + commandLine( + jsinterop, + "-pkg", "kotlinx.interop.wasm.math", + "-o", "$targetDir/math", + "-target", "wasm32" + ) + } + + val generated = file("$targetDir/math-build/natives/js_stubs.js") + val mathJs = file("src/main/js/math.js") + mathJs.writeText( + "// NOTE: THIS FILE IS AUTO-GENERATED!\n" + + "// Run ':runtime:generateJsMath' to re-generate it.\n\n" + ) + mathJs.appendText(generated.readText()) + } +} diff --git a/kotlin-native/runtime/generator/build.gradle b/kotlin-native/runtime/generator/build.gradle new file mode 100644 index 00000000000..e5d2cfe32b8 --- /dev/null +++ b/kotlin-native/runtime/generator/build.gradle @@ -0,0 +1,20 @@ +configurations { + generatorRuntime +} + +repositories { + maven { url buildKotlinCompilerRepo } +} + +dependencies { + generatorRuntime "org.jetbrains.kotlin:kotlin-stdlib:${kotlinStdlibVersion}" + generatorRuntime "org.jetbrains.kotlin:kotlin-reflect:${kotlinVersion}" + generatorRuntime "org.jetbrains.kotlin:kotlin-stdlib-gen:${kotlinStdlibVersion}" +} + +task run(type: JavaExec) { + group 'application' + main 'generators.GenerateStandardLibKt' + classpath configurations.generatorRuntime + args = ["native", "${project(":runtime").projectDir}/src/main/kotlin/generated"] +} \ No newline at end of file diff --git a/kotlin-native/runtime/src/debug/cpp/KDebug.cpp b/kotlin-native/runtime/src/debug/cpp/KDebug.cpp new file mode 100644 index 00000000000..a535034522b --- /dev/null +++ b/kotlin-native/runtime/src/debug/cpp/KDebug.cpp @@ -0,0 +1,319 @@ +/* + * Copyright 2010-2017 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "KDebug.h" + +#include + +#include "KAssert.h" +#include "KString.h" +#include "Memory.h" +#include "Natives.h" +#include "Porting.h" +#include "Types.h" + +#ifndef KONAN_NO_DEBUG_API + +extern "C" OBJ_GETTER(KonanObjectToUtf8Array, KRef object); + +namespace { + +char debugBuffer[4096]; + +constexpr int runtimeTypeSize[] = { + -1, // INVALID + sizeof(ObjHeader*), // OBJECT + 1, // INT8 + 2, // INT16 + 4, // INT32 + 8, // INT64 + 4, // FLOAT32 + 8, // FLOAT64 + sizeof(void*), // NATIVE_PTR + 1, // BOOLEAN + 16 // VECTOR128 +}; + +constexpr int runtimeTypeAlignment[] = { + -1, // INVALID + alignof(ObjHeader*), // OBJECT + alignof(int8_t), // INT8 + alignof(int16_t), // INT16 + alignof(int32_t), // INT32 + alignof(int64_t), // INT64 + alignof(float), // FLOAT32 + alignof(double), // FLOAT64 + alignof(void*), // NATIVE_PTR + 1, // BOOLEAN + 16 // VECTOR128 +}; + +// Never ever change numbering in this enum, as it will break debugging of older binaries. +enum Konan_DebugOperation { + DO_DebugBuffer = 1, + DO_DebugBufferSize = 2, + DO_DebugBufferWithObject = 3, + DO_DebugBufferSizeWithObject = 4, + DO_DebugObjectToUtf8Array = 5, + DO_DebugPrint = 6, + DO_DebugIsArray = 7, + DO_DebugGetFieldCount = 8, + DO_DebugGetFieldType = 9, + DO_DebugGetFieldAddress = 10, + DO_DebugGetFieldName = 11, + DO_DebugGetTypeName = 12, +}; + +template +F getImpl(KRef obj, Konan_DebugOperation operation) { + if (obj == nullptr) + return nullptr; + auto* typeInfo = obj->type_info(); + auto* extendedTypeInfo = typeInfo->extendedInfo_; + + if (extendedTypeInfo == nullptr) + return nullptr; + if (static_cast(operation) >= extendedTypeInfo->debugOperationsCount_) + return nullptr; + return reinterpret_cast(extendedTypeInfo->debugOperations_[operation]); +} + +// Buffer that can be used by debugger for inspections. +char* Konan_DebugBufferImpl() { + return debugBuffer; +} + +int Konan_DebugBufferSizeImpl() { + return sizeof(debugBuffer); +} + +char* Konan_DebugBufferWithObjectImpl(KRef obj) { + return debugBuffer; +} + +int Konan_DebugBufferSizeWithObjectImpl(KRef obj) { + return sizeof(debugBuffer); +} + +// Auxilary function which can be called by developer/debugger to inspect an object. +int32_t Konan_DebugObjectToUtf8ArrayImpl(KRef obj, char* buffer, int32_t bufferSize) { + ObjHolder stringHolder; + auto data = KonanObjectToUtf8Array(obj, stringHolder.slot())->array(); + if (data == nullptr) return 0; + if (bufferSize < 1) return 0; + KInt toCopy = data->count_ > static_cast(bufferSize - 1) ? bufferSize - 1 : data->count_; + ::memcpy(buffer, ByteArrayAddressOfElementAt(data, 0), toCopy); + buffer[toCopy] = '\0'; + return toCopy + 1; +} + +int32_t Konan_DebugPrintImpl(KRef obj) { + int32_t size = Konan_DebugObjectToUtf8Array(obj, Konan_DebugBuffer(), Konan_DebugBufferSize()); + if (size > 1) + konan::consoleWriteUtf8(Konan_DebugBuffer(), size - 1); + return 0; +} + +int32_t Konan_DebugIsArrayImpl(KRef obj) { + return obj == nullptr || IsArray(obj) ? 1 : 0; +} + +int32_t Konan_DebugGetFieldCountImpl(KRef obj) { + if (obj == nullptr) + return 0; + + auto* typeInfo = obj->type_info(); + auto* extendedTypeInfo = typeInfo->extendedInfo_; + + if (extendedTypeInfo == nullptr) + return 0; + + if (IsArray(obj)) + return obj->array()->count_; + + return extendedTypeInfo->fieldsCount_; +} + +int32_t Konan_DebugGetFieldTypeImpl(KRef obj, int32_t index) { + if (obj == nullptr || index < 0) + return Konan_RuntimeType::RT_INVALID; + + auto typeInfo = obj->type_info(); + auto extendedTypeInfo = typeInfo->extendedInfo_; + + if (extendedTypeInfo == nullptr) + return Konan_RuntimeType::RT_INVALID; + + if (extendedTypeInfo->fieldsCount_ < 0) + return -extendedTypeInfo->fieldsCount_; + + if (index >= extendedTypeInfo->fieldsCount_) + return Konan_RuntimeType::RT_INVALID; + + return extendedTypeInfo->fieldTypes_[index]; +} + +void* Konan_DebugGetFieldAddressImpl(KRef obj, int32_t index) { + if (obj == nullptr || index < 0) + return nullptr; + + auto typeInfo = obj->type_info(); + auto extendedTypeInfo = typeInfo->extendedInfo_; + + if (extendedTypeInfo == nullptr) + return nullptr; + + if (extendedTypeInfo->fieldsCount_ < 0) { + if (static_cast(index) > obj->array()->count_) + return nullptr; + + int32_t typeIndex = -extendedTypeInfo->fieldsCount_; + return reinterpret_cast(obj->array()) + + alignUp(sizeof(struct ArrayHeader), runtimeTypeAlignment[typeIndex]) + + index * runtimeTypeSize[typeIndex]; + } + + if (index >= extendedTypeInfo->fieldsCount_) + return nullptr; + + return reinterpret_cast(obj) + extendedTypeInfo->fieldOffsets_[index]; +} + +// Compute address of field or an array element at the index, or null, if incorrect. +const char* Konan_DebugGetFieldNameImpl(KRef obj, int32_t index) { + if (obj == nullptr || index < 0) + return nullptr; + + auto typeInfo = obj->type_info(); + auto extendedTypeInfo = typeInfo->extendedInfo_; + + if (extendedTypeInfo == nullptr) + return nullptr; + + // For arrays, field name makes not much sense. + if (extendedTypeInfo->fieldsCount_ < 0) + return ""; + + if (index >= extendedTypeInfo->fieldsCount_) + return nullptr; + + return extendedTypeInfo->fieldNames_[index]; +} + +const char* Konan_DebugGetTypeNameImpl(KRef obj) { + if (obj == nullptr) + return nullptr; + + auto type_info = obj->type_info(); + if (type_info == nullptr) + return ""; + + return CreateCStringFromString(type_info->relativeName_); +} + +} // namespace + +extern "C" { + +RUNTIME_USED RUNTIME_WEAK char* Konan_DebugBuffer() { + return Konan_DebugBufferImpl(); +} + +RUNTIME_USED RUNTIME_WEAK int32_t Konan_DebugBufferSize() { + return Konan_DebugBufferSizeImpl(); +} + +RUNTIME_USED RUNTIME_WEAK char* Konan_DebugBufferWithObject(KRef obj) { + auto* impl = getImpl(obj, DO_DebugBufferWithObject); + if (impl == nullptr) return nullptr; + return impl(obj); +} + +RUNTIME_USED RUNTIME_WEAK int32_t Konan_DebugBufferSizeWithObject(KRef obj) { + auto* impl = getImpl(obj, DO_DebugBufferSizeWithObject); + if (impl == nullptr) return 0; + return impl(obj); +} + +// Auxilary function which can be called by developer/debugger to inspect an object. +RUNTIME_USED RUNTIME_WEAK int32_t Konan_DebugObjectToUtf8Array(KRef obj, char* buffer, int32_t bufferSize) { + auto* impl = getImpl(obj, DO_DebugObjectToUtf8Array); + if (impl == nullptr) return 0; + return impl(obj, buffer, bufferSize); +} + +RUNTIME_USED RUNTIME_WEAK int32_t Konan_DebugPrint(KRef obj) { + auto* impl = getImpl(obj, DO_DebugPrint); + if (impl == nullptr) return 0; + return impl(obj); +} + +RUNTIME_USED RUNTIME_WEAK int32_t Konan_DebugIsArray(KRef obj) { + auto* impl = getImpl(obj, DO_DebugIsArray); + if (impl == nullptr) return 0; + return impl(obj); +} + +RUNTIME_USED RUNTIME_WEAK int32_t Konan_DebugGetFieldCount(KRef obj) { + auto* impl = getImpl(obj, DO_DebugGetFieldCount); + if (impl == nullptr) return 0; + return impl(obj); +} + +RUNTIME_USED RUNTIME_WEAK int32_t Konan_DebugGetFieldType(KRef obj, int32_t index) { + auto* impl = getImpl(obj, DO_DebugGetFieldType); + if (impl == nullptr) return 0; + return impl(obj, index); +} + +RUNTIME_USED RUNTIME_WEAK void* Konan_DebugGetFieldAddress(KRef obj, int32_t index) { + auto* impl = getImpl(obj, DO_DebugGetFieldAddress); + if (impl == nullptr) return nullptr; + return impl(obj, index); +} + +// Compute address of field or an array element at the index, or null, if incorrect. +RUNTIME_USED RUNTIME_WEAK const char* Konan_DebugGetFieldName(KRef obj, int32_t index) { + auto* impl = getImpl(obj, DO_DebugGetFieldName); + if (impl == nullptr) return nullptr; + return impl(obj, index); +} + +RUNTIME_USED RUNTIME_WEAK const char* Konan_DebugGetTypeName(KRef obj) { + auto* impl = getImpl(obj, DO_DebugGetTypeName); + if (impl == nullptr) return nullptr; + return impl(obj); +} + +const void* Konan_debugOperationsList[] = { + nullptr, + reinterpret_cast(&Konan_DebugBufferImpl), + reinterpret_cast(&Konan_DebugBufferSizeImpl), + reinterpret_cast(&Konan_DebugBufferWithObjectImpl), + reinterpret_cast(&Konan_DebugBufferSizeWithObjectImpl), + reinterpret_cast(&Konan_DebugObjectToUtf8ArrayImpl), + reinterpret_cast(&Konan_DebugPrintImpl), + reinterpret_cast(&Konan_DebugIsArrayImpl), + reinterpret_cast(&Konan_DebugGetFieldCountImpl), + reinterpret_cast(&Konan_DebugGetFieldTypeImpl), + reinterpret_cast(&Konan_DebugGetFieldAddressImpl), + reinterpret_cast(&Konan_DebugGetFieldNameImpl), + reinterpret_cast(&Konan_DebugGetTypeNameImpl) +}; + +} // extern "C" + +#endif // !KONAN_NO_DEBUG_API diff --git a/kotlin-native/runtime/src/debug/cpp/SourceInfo.cpp b/kotlin-native/runtime/src/debug/cpp/SourceInfo.cpp new file mode 100644 index 00000000000..e036ef8ec66 --- /dev/null +++ b/kotlin-native/runtime/src/debug/cpp/SourceInfo.cpp @@ -0,0 +1,213 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "SourceInfo.h" + +#ifdef KONAN_CORE_SYMBOLICATION +#include +#include +#include +#include +#include +#include + +#define TRACE_SYMBOLICATION 0 +#if TRACE_SYMBOLICATION +#include +#define SYM_LOG(...) fprintf(stderr, __VA_ARGS__) +#define SYM_DUMP(p) CSShow((p)) +#else +#define SYM_LOG(...) +#define SYM_DUMP(p) +#endif + +typedef struct _CSTypeRef { + unsigned long type; + void* contents; +} CSTypeRef; + +typedef CSTypeRef CSSymbolicatorRef; +typedef CSTypeRef CSSymbolOwnerRef; +typedef CSTypeRef CSSymbolRef; +typedef CSTypeRef CSSourceInfoRef; + +typedef struct _CSRange { + unsigned long long location; + unsigned long long length; +} CSRange; + +typedef unsigned long long CSArchitecture; + +constexpr auto kCSNow = std::numeric_limits::max(); + +namespace { + +CSSymbolicatorRef (*CSSymbolicatorCreateWithPid)(pid_t pid); + +CSSymbolOwnerRef (*CSSymbolicatorGetSymbolOwnerWithAddressAtTime)( + CSSymbolicatorRef symbolicator, + unsigned long long address, + long long time +); + +CSSourceInfoRef (*CSSymbolOwnerGetSourceInfoWithAddress)( + CSSymbolOwnerRef owner, + unsigned long long address +); + + +const char* (*CSSourceInfoGetPath)(CSSourceInfoRef info); + +uint32_t (*CSSourceInfoGetLineNumber)(CSSourceInfoRef info); + +uint32_t (*CSSourceInfoGetColumn)(CSSourceInfoRef info); + +bool (*CSIsNull)(CSTypeRef); +CSSymbolRef (*CSSourceInfoGetSymbol)(CSSourceInfoRef info); + +typedef int (^CSSourceInfoIterator)(CSSourceInfoRef); +int (*CSSymbolForeachSourceInfo)(CSSymbolRef, CSSourceInfoIterator); + +CSRange (*CSSourceInfoGetRange)(CSSourceInfoRef); + +CSSymbolRef (*CSSymbolOwnerGetSymbolWithAddress)(CSSymbolOwnerRef, unsigned long long); +CSSymbolicatorRef symbolicator; +/** + * Function used for debug. + */ +#if TRACE_SYMBOLICATION +void (*CSShow)(CSTypeRef); +#endif + +bool TryInitializeCoreSymbolication() { + void* cs = dlopen("/System/Library/PrivateFrameworks/CoreSymbolication.framework/CoreSymbolication", RTLD_LAZY); + if (!cs) return false; + +#define KONAN_CS_LOOKUP(name) name = (decltype(name)) dlsym(cs, #name); if (!name) return false; + + KONAN_CS_LOOKUP(CSSymbolicatorCreateWithPid) + KONAN_CS_LOOKUP(CSSymbolicatorGetSymbolOwnerWithAddressAtTime) + KONAN_CS_LOOKUP(CSSymbolOwnerGetSourceInfoWithAddress) + KONAN_CS_LOOKUP(CSSourceInfoGetPath) + KONAN_CS_LOOKUP(CSSourceInfoGetLineNumber) + KONAN_CS_LOOKUP(CSSourceInfoGetColumn) + KONAN_CS_LOOKUP(CSIsNull) + KONAN_CS_LOOKUP(CSSourceInfoGetSymbol) + KONAN_CS_LOOKUP(CSSymbolForeachSourceInfo) + KONAN_CS_LOOKUP(CSSymbolOwnerGetSymbolWithAddress) + KONAN_CS_LOOKUP(CSSourceInfoGetRange) + +#if TRACE_SYMBOLICATION + KONAN_CS_LOOKUP(CSShow) +#endif +#undef KONAN_CS_LOOKUP + + symbolicator = CSSymbolicatorCreateWithPid(getpid()); + return !CSIsNull(symbolicator); +} + +} // namespace + +typedef struct { + const char * fileName; + int start; + int end; +} SymbolSourceInfoLimits; + +extern "C" struct SourceInfo Kotlin_getSourceInfo(void* addr) { + __block SourceInfo result = { .fileName = nullptr, .lineNumber = -1, .column = -1 }; + __block bool continueUpdateResult = true; + __block SymbolSourceInfoLimits limits = {.start = -1, .end = -1}; + + static bool csIsAvailable = TryInitializeCoreSymbolication(); + + if (csIsAvailable) { + unsigned long long address = static_cast((uintptr_t)addr); + + CSSymbolOwnerRef symbolOwner = CSSymbolicatorGetSymbolOwnerWithAddressAtTime(symbolicator, address, kCSNow); + if (CSIsNull(symbolOwner)) + return result; + CSSymbolRef symbol = CSSymbolOwnerGetSymbolWithAddress(symbolOwner, address); + if (CSIsNull(symbol)) + return result; + SYM_LOG("Kotlin_getSourceInfo: address: %p\n", addr); + SYM_DUMP(symbol); + + + /** + * ASSUMPTION: we assume that the _first_ and the _last_ source infos should belong to real function(symbol) the rest might belong to + * inlined functions. + */ + CSSymbolForeachSourceInfo(symbol, + ^(CSSourceInfoRef ref) { + // Expecting CSSourceInfoGetLineNumber not to overflow int32_t max value. + int32_t lineNumber = CSSourceInfoGetLineNumber(ref); + if (lineNumber == 0) + return 0; + if (limits.start == -1) { + limits.start = lineNumber; + limits.fileName = CSSourceInfoGetPath(ref); + } else { + limits.end = lineNumber; + } + return 0; + }); + + SYM_LOG("limits: {%s %d..%d}\n", limits.fileName, limits.start, limits.end); + result.fileName = limits.fileName; + + CSSymbolForeachSourceInfo(symbol, + ^(CSSourceInfoRef ref) { + // Expecting CSSourceInfoGetLineNumber not to overflow int32_t max value. + int32_t lineNumber = CSSourceInfoGetLineNumber(ref); + if (lineNumber == 0) + return 0; + SYM_DUMP(ref); + CSRange range = CSSourceInfoGetRange(ref); + const char* fileName = CSSourceInfoGetPath(ref); + /** + * We need to change API fo Kotlin_getSourceInfo to return information about inlines, + * but for a moment we have to track that we updating result info _only_ for upper level or _inlined at_ and + * don't go deeper. at deeper level we check only that we at the right _inlined at_ position. + */ + if (continueUpdateResult + && strcmp(limits.fileName, fileName) == 0 + && lineNumber >= limits.start + && lineNumber <= limits.end) { + result.lineNumber = lineNumber; + result.column = CSSourceInfoGetColumn(ref); + } + /** + * if found right inlined function don't bother with + * updating high level inlined _at_ source info + */ + if (continueUpdateResult && (address >= range.location + && address < range.location + range.length)) + continueUpdateResult = false; + + return 0; + }); + } + return result; +} + +#else // KONAN_CORE_SYMBOLICATION + +extern "C" struct SourceInfo Kotlin_getSourceInfo(void* addr) { + return (SourceInfo) { .fileName = nullptr, .lineNumber = -1, .column = -1 }; +} + +#endif // KONAN_CORE_SYMBOLICATION diff --git a/kotlin-native/runtime/src/exceptions_support/cpp/ExceptionsSupport.cpp b/kotlin-native/runtime/src/exceptions_support/cpp/ExceptionsSupport.cpp new file mode 100644 index 00000000000..234df5de640 --- /dev/null +++ b/kotlin-native/runtime/src/exceptions_support/cpp/ExceptionsSupport.cpp @@ -0,0 +1,15 @@ +#include "Memory.h" +#include "Porting.h" +#include + +#ifndef KONAN_NO_EXCEPTIONS + +std::type_info const* ExceptionObjHolderRTTI; + +// Just some DCE-surviving code referencing RTTI of ExceptionObjHolder. +// This is needed during compilation to cache. +void referenceExceptionObjHolderRTTI() { + ExceptionObjHolderRTTI = &typeid(ExceptionObjHolder); +} + +#endif \ No newline at end of file diff --git a/kotlin-native/runtime/src/launcher/cpp/androidLauncher.cpp b/kotlin-native/runtime/src/launcher/cpp/androidLauncher.cpp new file mode 100644 index 00000000000..ebbd8a4d636 --- /dev/null +++ b/kotlin-native/runtime/src/launcher/cpp/androidLauncher.cpp @@ -0,0 +1,240 @@ +/* + * Copyright 2010-2017 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "KString.h" +#include "Memory.h" +#include "Natives.h" +#include "Porting.h" +#include "Runtime.h" +#include "Types.h" + +#ifdef KONAN_ANDROID + +#include +#include +#include +#include +#include + +#include "androidLauncher.h" + +#include + +#define LOGI(...) ((void)__android_log_print(ANDROID_LOG_INFO, "Konan_main", __VA_ARGS__)) +#define LOGE(...) ((void)__android_log_print(ANDROID_LOG_ERROR, "Konan_main", __VA_ARGS__)) + +/* For debug builds, always enable the debug traces in this library */ +#ifndef NDEBUG +# define LOGV(...) ((void)__android_log_print(ANDROID_LOG_VERBOSE, "Konan_main", __VA_ARGS__)) +#else +# define LOGV(...) ((void)0) +#endif + +//--- main --------------------------------------------------------------------// +extern "C" KInt Konan_start(const ObjHeader*); + +namespace { + +typedef struct { + int pipeC; + int pipeKonan; + NativeActivityState nativeActivityState; +} LauncherState; + +LauncherState* launcherState = nullptr; + +} + +extern "C" void getNativeActivityState(NativeActivityState* state) { + state->activity = launcherState->nativeActivityState.activity; + state->savedState = launcherState->nativeActivityState.savedState; + state->savedStateSize = launcherState->nativeActivityState.savedStateSize; + state->looper = launcherState->nativeActivityState.looper; +} + +extern "C" void notifySysEventProcessed() { + int8_t message; + write(launcherState->pipeKonan, &message, sizeof(message)); +} + +namespace { + +void launchMain() { + Kotlin_initRuntimeIfNeeded(); + + { + ObjHolder args; + AllocArrayInstance(theArrayTypeInfo, 0, args.slot()); + Konan_start(args.obj()); + } + + Kotlin_deinitRuntimeIfNeeded(); +} + +void* entry(void* param) { + ALooper* looper = ALooper_prepare(ALOOPER_PREPARE_ALLOW_NON_CALLBACKS); + ALooper_addFd(looper, launcherState->pipeKonan, LOOPER_ID_SYS, ALOOPER_EVENT_INPUT, NULL, NULL); + launcherState->nativeActivityState.looper = looper; + + launchMain(); + + return nullptr; +} + +void runKonan_start(bool startThread) { + if (!startThread) { + launchMain(); + return; + } + + int pipes[2]; + if (socketpair(AF_UNIX, SOCK_STREAM, 0, pipes)) { + LOGE("Could not create pipe: %s", strerror(errno)); + return; + } + launcherState->pipeC = pipes[0]; + launcherState->pipeKonan = pipes[1]; + + LOGE("runKonan_start() %d %d", launcherState->pipeC, launcherState->pipeKonan); + + pthread_attr_t attr; + pthread_attr_init(&attr); + pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED); + pthread_t thread; + pthread_create(&thread, &attr, entry, nullptr); +} + +void putEventSynchronously(void* event) { + auto value = reinterpret_cast(event); + + if (write(launcherState->pipeC, &value, sizeof(value)) != sizeof(value)) { + LOGE("Failure writing event: %s\n", strerror(errno)); + } + int8_t response; + if (read(launcherState->pipeC, &response, sizeof(response)) != sizeof(response)) { + LOGE("Failure reading response: %s\n", strerror(errno)); + } +} + +void onDestroy(ANativeActivity* activity) { + LOGV("onDestroy called"); + NativeActivityEvent event = { DESTROY }; + putEventSynchronously(&event); +} + +void onStart(ANativeActivity* activity) { + LOGV("onStart called"); + NativeActivityEvent event = { START }; + putEventSynchronously(&event); +} + +void onResume(ANativeActivity* activity) { + LOGV("onResume called"); + NativeActivitySaveStateEvent event = { RESUME, nullptr, 0 }; + putEventSynchronously(&event); +} + +void* onSaveInstanceState(ANativeActivity* activity, size_t* outLen) { + LOGV("onSaveInstanceState called"); + NativeActivitySaveStateEvent event = { SAVE_INSTANCE_STATE, nullptr, 0 }; + putEventSynchronously(&event); + *outLen = event.savedStateSize; + return event.savedState; +} + +void onPause(ANativeActivity* activity) { + LOGV("onPause called"); + NativeActivityEvent event = { PAUSE }; + putEventSynchronously(&event); +} + +void onStop(ANativeActivity* activity) { + LOGV("onStop called"); + NativeActivityEvent event = { STOP }; + putEventSynchronously(&event); +} + +void onConfigurationChanged(ANativeActivity* activity) { + LOGV("onConfigurationChanged called"); + NativeActivityEvent event = { CONFIGURATION_CHANGED }; + putEventSynchronously(&event); +} + +void onLowMemory(ANativeActivity* activity) { + LOGV("onLowMemory called"); + NativeActivityEvent event = { LOW_MEMORY }; + putEventSynchronously(&event); +} + +void onWindowFocusChanged(ANativeActivity* activity, int focused) { + LOGV("onWindowFocusChanged called"); + NativeActivityEvent event = { focused ? WINDOW_GAINED_FOCUS : WINDOW_LOST_FOCUS }; + putEventSynchronously(&event); +} + +void onNativeWindowCreated(ANativeActivity* activity, ANativeWindow* window) { + LOGV("onNativeWindowCreated called"); + NativeActivityWindowEvent event = { NATIVE_WINDOW_CREATED, window }; + putEventSynchronously(&event); +} + +void onNativeWindowDestroyed(ANativeActivity* activity, ANativeWindow* window) { + LOGV("onNativeWindowDestroyed called"); + NativeActivityWindowEvent event = { NATIVE_WINDOW_DESTROYED, window }; + putEventSynchronously(&event); +} + +void onInputQueueCreated(ANativeActivity* activity, AInputQueue* queue) { + LOGV("onInputQueueCreated called"); + NativeActivityQueueEvent event = { INPUT_QUEUE_CREATED, queue }; + putEventSynchronously(&event); +} + +void onInputQueueDestroyed(ANativeActivity* activity, AInputQueue* queue) { + LOGV("onInputQueueDestroyed called"); + NativeActivityQueueEvent event = { INPUT_QUEUE_DESTROYED, queue }; + putEventSynchronously(&event); +} +} + +extern "C" void RUNTIME_USED Konan_main( + ANativeActivity* activity, void* savedState, size_t savedStateSize) { + bool launchThread = activity->instance == nullptr; + if (launchThread) { + launcherState = (LauncherState*)konan::calloc(sizeof(LauncherState), 1); + launcherState->nativeActivityState = {activity, savedState, savedStateSize, nullptr}; + activity->instance = launcherState; + activity->callbacks->onDestroy = onDestroy; + activity->callbacks->onStart = onStart; + activity->callbacks->onResume = onResume; + activity->callbacks->onSaveInstanceState = onSaveInstanceState; + activity->callbacks->onPause = onPause; + activity->callbacks->onStop = onStop; + activity->callbacks->onConfigurationChanged = onConfigurationChanged; + activity->callbacks->onLowMemory = onLowMemory; + activity->callbacks->onWindowFocusChanged = onWindowFocusChanged; + activity->callbacks->onNativeWindowCreated = onNativeWindowCreated; + activity->callbacks->onNativeWindowDestroyed = onNativeWindowDestroyed; + activity->callbacks->onInputQueueCreated = onInputQueueCreated; + activity->callbacks->onInputQueueDestroyed = onInputQueueDestroyed; + } else { + launcherState = (LauncherState*)activity->instance; + } + + runKonan_start(launchThread); +} + +#endif // KONAN_ANDROID diff --git a/kotlin-native/runtime/src/launcher/cpp/androidLauncher.h b/kotlin-native/runtime/src/launcher/cpp/androidLauncher.h new file mode 100644 index 00000000000..d1a3cb359ff --- /dev/null +++ b/kotlin-native/runtime/src/launcher/cpp/androidLauncher.h @@ -0,0 +1,85 @@ +/* + * Copyright 2010-2017 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef ANDROID_LAUNCHER_H +#define ANDROID_LAUNCHER_H + +#include + +#include +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +struct NativeActivityState { + struct ANativeActivity* activity; + void* savedState; + size_t savedStateSize; + struct ALooper* looper; +}; + +void getNativeActivityState(struct NativeActivityState* state); + +void notifySysEventProcessed(); + +#define LOOPER_ID_SYS 1 + +typedef enum NativeActivityEventKind { + UNKNOWN, + DESTROY, + START, + RESUME, + SAVE_INSTANCE_STATE, + PAUSE, + STOP, + CONFIGURATION_CHANGED, + LOW_MEMORY, + WINDOW_GAINED_FOCUS, + WINDOW_LOST_FOCUS, + NATIVE_WINDOW_CREATED, + NATIVE_WINDOW_DESTROYED, + INPUT_QUEUE_CREATED, + INPUT_QUEUE_DESTROYED +} NativeActivityEventKind; + +struct NativeActivityEvent { + NativeActivityEventKind eventKind; +}; + +struct NativeActivitySaveStateEvent { + NativeActivityEventKind eventKind; + void* savedState; + size_t savedStateSize; +}; + +struct NativeActivityWindowEvent { + NativeActivityEventKind eventKind; + struct ANativeWindow* window; +}; + +struct NativeActivityQueueEvent { + NativeActivityEventKind eventKind; + struct AInputQueue* queue; +}; + +#ifdef __cplusplus +} +#endif + +#endif // ANDROID_LAUNCHER_H \ No newline at end of file diff --git a/kotlin-native/runtime/src/launcher/cpp/launcher.cpp b/kotlin-native/runtime/src/launcher/cpp/launcher.cpp new file mode 100644 index 00000000000..c102a537106 --- /dev/null +++ b/kotlin-native/runtime/src/launcher/cpp/launcher.cpp @@ -0,0 +1,98 @@ +/* + * Copyright 2010-2017 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "Cleaner.h" +#include "Memory.h" +#include "Natives.h" +#include "Runtime.h" +#include "KString.h" +#include "Types.h" +#include "Worker.h" + +#ifndef KONAN_ANDROID + +//--- Setup args --------------------------------------------------------------// + +OBJ_GETTER(setupArgs, int argc, const char** argv) { + // The count is one less, because we skip argv[0] which is the binary name. + ObjHeader* result = AllocArrayInstance(theArrayTypeInfo, argc - 1, OBJ_RESULT); + ArrayHeader* array = result->array(); + for (int index = 1; index < argc; index++) { + ObjHolder result; + CreateStringFromCString(argv[index], result.slot()); + UpdateHeapRef(ArrayAddressOfElementAt(array, index - 1), result.obj()); + } + return result; +} + +//--- main --------------------------------------------------------------------// +extern "C" KInt Konan_start(const ObjHeader*); + +extern "C" KInt Konan_run_start(int argc, const char** argv) { + ObjHolder args; + setupArgs(argc, argv, args.slot()); + return Konan_start(args.obj()); +} + +extern "C" RUNTIME_USED int Init_and_run_start(int argc, const char** argv, int memoryDeInit) { +#ifdef KONAN_NO_CTORS_SECTION + extern void _Konan_constructors(void); + _Konan_constructors(); +#endif + + Kotlin_initRuntimeIfNeeded(); + + KInt exitStatus = Konan_run_start(argc, argv); + + if (memoryDeInit) { + if (Kotlin_cleanersLeakCheckerEnabled()) { + // Make sure to collect any lingering cleaners. + PerformFullGC(); + // Execute all the cleaner blocks and stop the Cleaner worker. + ShutdownCleaners(true); + } else { + // Stop the cleaner worker without executing remaining cleaner blocks. + ShutdownCleaners(false); + } + if (Kotlin_memoryLeakCheckerEnabled()) WaitNativeWorkersTermination(); + Kotlin_deinitRuntimeIfNeeded(); + } + + return exitStatus; +} + +extern "C" RUNTIME_USED int Konan_main(int argc, const char** argv) { + return Init_and_run_start(argc, argv, 1); +} + +#ifdef KONAN_WASM +// Before we pass control to Konan_main, we need to obtain argv elements +// from the javascript world. +extern "C" int Konan_js_arg_size(int index); +extern "C" int Konan_js_fetch_arg(int index, char* ptr); + +extern "C" RUNTIME_USED int Konan_js_main(int argc, int memoryDeInit) { + char** argv = (char**)konan::calloc(1, argc); + for (int i = 0; i< argc; ++i) { + argv[i] = (char*)konan::calloc(1, Konan_js_arg_size(i)); + Konan_js_fetch_arg(i, argv[i]); + } + return Init_and_run_start(argc, (const char**)argv, memoryDeInit); +} + +#endif + +#endif diff --git a/kotlin-native/runtime/src/launcher/js/index.html b/kotlin-native/runtime/src/launcher/js/index.html new file mode 100644 index 00000000000..6586b142e5a --- /dev/null +++ b/kotlin-native/runtime/src/launcher/js/index.html @@ -0,0 +1,14 @@ + + + + + + + + + + + + diff --git a/kotlin-native/runtime/src/launcher/js/launcher.js b/kotlin-native/runtime/src/launcher/js/launcher.js new file mode 100644 index 00000000000..e63d18bdf25 --- /dev/null +++ b/kotlin-native/runtime/src/launcher/js/launcher.js @@ -0,0 +1,247 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +let instance; +let heap; +let global_arguments; + +function isBrowser() { + return typeof self !== 'undefined'; +} + +let runtime; +if (isBrowser()) { + runtime = { + print: console.log, + stdout: '', + write: function (message) { + this.stdout += message; + const lastNewlineIndex = this.stdout.lastIndexOf('\n'); + if (lastNewlineIndex == -1) return; + this.print(this.stdout.substring(0, lastNewlineIndex)); + this.stdout = this.stdout.substring(lastNewlineIndex + 1) + }, + flush: function () { + this.print(this.stdout); + }, + exit: function (status) { + throw Error("Kotlin process called exit (" + status + ")"); + } + }; +} else { + runtime = { + write: write, + print: print, + flush: function () { + }, + exit: quit + }; +} + +function print_usage() { + // TODO: any reliable way to obtain the current script name? + runtime.print('Usage: d8 --expose-wasm launcher.js -- ...') + quit(1); // TODO: this is d8 specific +} + +function utf8encode(s) { + return unescape(encodeURIComponent(s)); +} + +function utf8decode(s) { + return decodeURIComponent(escape(s)); +} + +function fromString(string, pointer) { + for (let i = 0; i < string.length; i++) { + heap[pointer + i] = string.charCodeAt(i); + } + heap[pointer + string.length] = 0; +} + +function toString(pointer) { + let string = ''; + for (let i = pointer; heap[i] != 0; i++) { + string += String.fromCharCode(heap[i]); + } + return string; +} + +function toUTF16String(pointer, size) { + let string = ''; + for (let i = pointer; i < pointer + size; i += 2) { + string += String.fromCharCode(heap[i] + heap[i + 1] * 256); + } + return string; +} + +function twoIntsToDouble(upper, lower) { + const buffer = new ArrayBuffer(8); + const ints = new Int32Array(buffer); + const doubles = new Float64Array(buffer); + ints[1] = upper; + ints[0] = lower; + return doubles[0]; +} + +function doubleToTwoInts(value) { + const buffer = new ArrayBuffer(8); + const ints = new Int32Array(buffer); + const doubles = new Float64Array(buffer); + doubles[0] = value; + return {upper: ints[1], lower: ints[0]} +} + +function int32ToHeap(value, pointer) { + heap[pointer] = value & 0xff; + heap[pointer + 1] = (value & 0xff00) >>> 8; + heap[pointer + 2] = (value & 0xff0000) >>> 16; + heap[pointer + 3] = (value & 0xff000000) >>> 24; +} + +function doubleToReturnSlot(value) { + const twoInts = doubleToTwoInts(value); + instance.exports.ReturnSlot_setDouble(twoInts.upper, twoInts.lower); +} + +let konan_dependencies = { + env: { + abort: function () { + throw new Error("abort()"); + }, + // TODO: Account for file and size. + fgets: function (str, size, file) { + // TODO: readline can't read lines without a newline. + // Browsers cant read from console at all. + fromString(utf8encode(readline() + '\n'), str); + return str; + }, + read: function (file, str, size) { + let string = utf8encode(readline() + '\n'); + fromString(string.substring(0, size), str); + return string.length; + }, + Konan_notify_memory_grow: function() { + heap = new Uint8Array(instance.exports.memory.buffer); + }, + Konan_abort: function (pointer) { + throw new Error("Konan_abort(" + utf8decode(toString(pointer)) + ")"); + }, + Konan_exit: function (status) { + runtime.exit(status); + }, + Konan_js_arg_size: function (index) { + if (index >= global_arguments.length) return -1; + return global_arguments[index].length + 1; // + 1 for trailing zero. + }, + Konan_js_fetch_arg: function (index, ptr) { + let arg = utf8encode(global_arguments[index]); + fromString(arg, ptr); + }, + Konan_date_now: function (pointer) { + let now = Date.now(); + let high = Math.floor(now / 0xffffffff); + let low = Math.floor(now % 0xffffffff); + int32ToHeap(low, pointer); + int32ToHeap(high, pointer + 4); + }, + // TODO: Account for fd and size. + write: function (fd, str, size) { + if (fd != 1 && fd != 2) throw ("write(" + fd + ", ...)"); + // TODO: There is no writeErr() in d8. + // Approximate it with write() to stdout for now. + runtime.write(utf8decode(toString(str))); + }, + fflush: function(file) { + runtime.flush(); + } + } +}; + +function linkJavaScriptLibraries() { + konan.libraries.forEach(function (library) { + for (const property in library) { + konan_dependencies.env[property] = library[property]; + } + }); +} + +function invokeModule(inst, args) { + if (args.length < 1) print_usage(); + global_arguments = args; + + instance = inst; + + heap = new Uint8Array(instance.exports.memory.buffer); + + let exit_status = 0; + + try { + exit_status = instance.exports.Konan_js_main(args.length, isBrowser() ? 0 : 1); + } catch (e) { + runtime.print("Exception executing entry point: " + e); + runtime.print(e.stack); + exit_status = 1; + } + runtime.flush(); + + return exit_status; +} + +// Instantiate module in Browser. +function instantiateAndRun(arraybuffer, args) { + linkJavaScriptLibraries(); + WebAssembly.instantiate(arraybuffer, konan_dependencies) + .then(resultObject => invokeModule(resultObject.instance, args)); +} + +// Instantiate module in d8 synchronously. +function instantiateAndRunSync(arraybuffer, args) { + const module = new WebAssembly.Module(arraybuffer); + linkJavaScriptLibraries(); + const instance = new WebAssembly.Instance(module, konan_dependencies); + return invokeModule(instance, args) +} + + +// Instantiate module in Browser using streaming instantiation. +function instantiateAndRunStreaming(filename) { + linkJavaScriptLibraries(); + WebAssembly.instantiateStreaming(fetch(filename), konan_dependencies) + .then(resultObject => invokeModule(resultObject.instance, [filename])); +} + +konan.moduleEntry = function (args) { + if (isBrowser()) { + if (!document.currentScript.hasAttribute("wasm")) { + throw new Error('Could not find the wasm attribute pointing to the WebAssembly binary.'); + } + const filename = document.currentScript.getAttribute("wasm"); + if (typeof WebAssembly.instantiateStreaming === 'function') { + instantiateAndRunStreaming(filename); + } else { + fetch(filename) + .then(response => response.arrayBuffer()) + .then(arraybuffer => instantiateAndRun(arraybuffer, [filename])); + } + } else { + // Invoke from d8. + const arrayBuffer = readbuffer(args[0]); + const exitStatus = instantiateAndRunSync(arrayBuffer, args); + quit(exitStatus); + } +}; + diff --git a/kotlin-native/runtime/src/legacymm/cpp/CyclicCollector.cpp b/kotlin-native/runtime/src/legacymm/cpp/CyclicCollector.cpp new file mode 100644 index 00000000000..623abb0a216 --- /dev/null +++ b/kotlin-native/runtime/src/legacymm/cpp/CyclicCollector.cpp @@ -0,0 +1,528 @@ +/* + * Copyright 2010-2020 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#ifndef KONAN_NO_THREADS +#define WITH_WORKERS 1 +#endif + +#include "Alloc.h" +#include "Atomic.h" +#include "KAssert.h" +#include "Memory.h" +#include "MemoryPrivate.hpp" +#include "Natives.h" +#include "Porting.h" +#include "Types.h" + +#if WITH_WORKERS +#include +#include "PthreadUtils.h" +#endif + +#if WITH_WORKERS + +// Define to 1 to print collector traces. +#define TRACE_COLLECTOR 0 + +#if TRACE_COLLECTOR +#define COLLECTOR_LOG(...) konan::consolePrintf(__VA_ARGS__); +#else +#define COLLECTOR_LOG(...) +#endif + +/** + * Theory of operations: + * + * Kotlin/Native runtime has concurrent cyclic garbage collection for the shared mutable objects, + * such as `AtomicReference` and `FreezableAtomicReference` instances (further known as the atomic rootset). + * We perform such analysis by iterating over the transitive closure of the atomic rootset, and computing + * aggregated inner reference counter for rootset elements over this transitive closure. + * Collector runs in its own thread and is started by an explicit request or after certain time interval since last + * collection passes, thus its operation does not affect UI responsiveness in most cases. + * Atomic rootset is built by maintaining the set of all atomic and freezable atomic references objects. + * Elements whose transitive closure inner reference count matches the actual reference count are ones + * belonging to the garbage cycles and thus can be discarded. + * We ignore elements reachable from objects having external references (i.e. inner rc != real rc). + * If during computations of the aggregated RC there were modifications in the reference counts of + * elements of the atomic rootset: + * - if it is being increased, then someone already got an external reference to this element, thus we may not + * end up matching the inner reference count anyway + * - if it is being decreased and object become garbage, it will be collected next time + * If transitive closure of the atomic rootset mutates, it could only happen via changing the atomics references, + * as all elements of this closure are frozen. + * To handle such mutations we keep collector flag, which is cleared before analysis and set on every + * atomic reference value update. If flag's value changes - collector restarts its analysis. + * There are not so much of complications in this algorithm due to the delayed reference counting as if there's a + * stack reference to the shared object - it's reflected in the reference counter (see rememberNewContainer()). + * We release objects found by the collector on a rendezvouz callback, but not on the main thread, + * to keep UI responsive, as taking GC lock can take time, sometimes. + */ +namespace { + +class Locker { + pthread_mutex_t* lock_; + + public: + Locker(pthread_mutex_t* alock): lock_(alock) { + pthread_mutex_lock(lock_); + } + + ~Locker() { + pthread_mutex_unlock(lock_); + } +}; + +template +inline void traverseObjectFields(ObjHeader* obj, func process) { + RuntimeAssert(obj != nullptr, "Must be non null"); + const TypeInfo* typeInfo = obj->type_info(); + if (typeInfo != theArrayTypeInfo) { + for (int index = 0; index < typeInfo->objOffsetsCount_; index++) { + ObjHeader** location = reinterpret_cast( + reinterpret_cast(obj) + typeInfo->objOffsets_[index]); + process(location); + } + } else { + ArrayHeader* array = obj->array(); + for (uint32_t index = 0; index < array->count_; index++) { + process(ArrayAddressOfElementAt(array, index)); + } + } +} + +inline bool isAtomicReference(ObjHeader* obj) { + return (obj->type_info()->flags_ & TF_LEAK_DETECTOR_CANDIDATE) != 0; +} + +#define CHECK_CALL(call, message) RuntimeCheck((call) == 0, message) + +class CyclicCollector { + pthread_mutex_t lock_; + pthread_mutex_t timestampLock_; + pthread_cond_t cond_; + pthread_t gcThread_; + + int currentAliveWorkers_; + int gcRunning_; + int mutatedAtomics_; + int pendingRelease_; + bool shallRunCollector_; + bool terminateCollector_; + int32_t currentTick_; + int32_t lastTick_; + int64_t lastTimestampUs_; + void* mainWorker_; + KStdUnorderedSet rootset_; + KStdUnorderedSet toRelease_; + + public: + CyclicCollector() { + CHECK_CALL(pthread_mutex_init(&lock_, nullptr), "Cannot init collector mutex") + CHECK_CALL(pthread_mutex_init(×tampLock_, nullptr), "Cannot init collector timestamp mutex") + CHECK_CALL(pthread_cond_init(&cond_, nullptr), "Cannot init collector condition") + CHECK_CALL(pthread_create(&gcThread_, nullptr, gcWorkerRoutine, this), "Cannot start collector thread") + } + + void clear() { + Locker lock(&lock_); + rootset_.clear(); + toRelease_.clear(); + } + + void terminate(bool enabled) { + { + Locker locker(&lock_); + terminateCollector_ = true; + if (enabled) shallRunCollector_ = true; + CHECK_CALL(pthread_cond_signal(&cond_), "Cannot signal collector") + } + // TODO: improve waiting for collector termination. + while (atomicGet(&terminateCollector_)) {} + releasePendingUnlocked(nullptr); + } + + ~CyclicCollector() { + pthread_cond_destroy(&cond_); + pthread_mutex_destroy(&lock_); + pthread_mutex_destroy(×tampLock_); + } + + static void* gcWorkerRoutine(void* argument) { + CyclicCollector* thiz = reinterpret_cast(argument); + thiz->gcProcessor(); + return nullptr; + } + + void gcProcessor() { + { + Locker locker(&lock_); + KStdDeque toVisit; + KStdUnorderedSet visited; + KStdUnorderedMap sideRefCounts; + int restartCount = 0; + while (!terminateCollector_) { + CHECK_CALL(pthread_cond_wait(&cond_, &lock_), "Cannot wait collector condition") + if (!shallRunCollector_) continue; + atomicSet(&gcRunning_, 1); + restartCount = 0; + restart: + COLLECTOR_LOG("start cycle GC\n"); + if (restartCount > 10 && !terminateCollector_) { + COLLECTOR_LOG("wait for some time to avoid GC thrashing\n"); + uint64_t nsDelta = 1000LL * 1000LL * (restartCount - 10); + WaitOnCondVar(&cond_, &lock_, nsDelta); + } + atomicSet(&mutatedAtomics_, 0); + visited.clear(); + toVisit.clear(); + sideRefCounts.clear(); + for (auto* root: rootset_) { + // We only care about frozen values here, as only they could become part of shared cycles. + if (!containerFor(root)->frozen()) continue; + COLLECTOR_LOG("process root %p\n", root); + toVisit.push_back(root); + sideRefCounts[root] = 0; + } + while (toVisit.size() > 0) { + if (atomicGet(&mutatedAtomics_) != 0) { + COLLECTOR_LOG("restarted during rootset visit\n") + restartCount++; + goto restart; + } + auto* obj = toVisit.front(); + toVisit.pop_front(); + COLLECTOR_LOG("visit %s%p\n", isAtomicReference(obj) ? "atomic " : "", obj); + auto* objContainer = containerFor(obj); + if (objContainer == nullptr) continue; // Permanent object. + RuntimeCheck(objContainer->shareable(), "Must be shareable"); + if (visited.count(obj) == 0) { + visited.insert(obj); + traverseObjectFields(obj, [&toVisit, obj, &sideRefCounts](ObjHeader** location) { + ObjHeader* ref = *location; + if (ref != nullptr) { + COLLECTOR_LOG("object field %p in %p\n", ref, obj) + int increment; + // We shall not account for edges inside the same frozen container, unless it originates + // from an atomic reference. + if (isAtomicReference(obj) || (containerFor(obj) != containerFor(ref))) { + COLLECTOR_LOG("counting %p -> %p\n", obj, ref) + increment = 1; + } else { + COLLECTOR_LOG("not counting %p -> %p\n", obj, ref) + increment = 0; + } + sideRefCounts[ref] += increment; + toVisit.push_back(ref); + } + }); + } + } + // Now find all elements with external references, and mark objects reachable from them as non suitable + // for collection by setting their side reference count to -1. + toVisit.clear(); + for (auto it: sideRefCounts) { + auto* obj = it.first; + auto* objContainer = containerFor(obj); + if (objContainer == nullptr) continue; // Permanent object. + int refCount; + // If object is in aggregated container - sum up RC for all elements. + if (objContainer->objectCount() != 1) { + RuntimeAssert(objContainer->frozen(), "Must be frozen aggregate"); + ContainerHeader** subContainer = reinterpret_cast(objContainer + 1); + refCount = 0; + for (uint32_t i = 0; i < objContainer->objectCount(); ++i) { + auto* componentObj = reinterpret_cast((*subContainer) + 1); + refCount += sideRefCounts[componentObj]; + subContainer++; + } + } else { + refCount = it.second; + } + RuntimeAssert(refCount <= objContainer->refCount(), "Must properly count inner refs"); + if (refCount != objContainer->refCount()) { + COLLECTOR_LOG("for %p mismatched RC: %d vs %d, adding as possible root\n", obj, refCount, objContainer->refCount()) + toVisit.push_back(it.first); + } + } + visited.clear(); + while (toVisit.size() > 0) { + auto* obj = toVisit.front(); + toVisit.pop_front(); + auto* objContainer = containerFor(obj); + if (objContainer == nullptr) continue; // Permanent object. + RuntimeCheck(objContainer->shareable(), "Must be shareable"); + sideRefCounts[obj] = -1; + visited.insert(obj); + if (atomicGet(&mutatedAtomics_) != 0) { + COLLECTOR_LOG("restarted during reachable visit\n") + restartCount++; + goto restart; + } + traverseObjectFields(obj, [&toVisit, &visited](ObjHeader** location) { + ObjHeader* ref = *location; + if (ref != nullptr && (visited.count(ref) == 0)) { + toVisit.push_back(ref); + } + }); + } + // Now release all atomic roots with matching reference counters, as only their destruction is controlled. + for (auto it: sideRefCounts) { + auto* obj = it.first; + // Only do that for atomic rootset elements. For them we also do not have sum up references from + // other elements of an aggregate, as atomic references are always in single object containers. + if (!isAtomicReference(obj)) { + continue; + } + if (atomicGet(&mutatedAtomics_) != 0) { + COLLECTOR_LOG("restarted during matching check\n") + restartCount++; + goto restart; + } + auto* objContainer = containerFor(obj); + if (!objContainer->frozen()) continue; + RuntimeAssert(objContainer->objectCount() == 1, "Must be single object"); + COLLECTOR_LOG("for %p inner %d actual %d\n", obj, it.second, objContainer->refCount()); + // All references are inner. We compare the number of counted + // inner references with the number of non-stack references and per-thread ownership value + // (see rememberNewContainer()). + if (it.second == objContainer->refCount()) { + COLLECTOR_LOG("adding %p to release candidates\n", it.first); + toRelease_.insert(it.first); + } + } + if (toRelease_.size() > 0) + atomicSet(&pendingRelease_, 1); + atomicSet(&gcRunning_, 0); + shallRunCollector_ = false; + COLLECTOR_LOG("end cycle GC\n"); + } + } + atomicSet(&terminateCollector_, false); + } + + void addWorker(void* worker) { + suggestLockRelease(); + Locker lock(&lock_); + currentAliveWorkers_++; + if (mainWorker_ == nullptr) mainWorker_ = worker; + } + + void removeWorker(void* worker, bool enabled) { + suggestLockRelease(); + Locker lock(&lock_); + // When exiting the worker - we shall collect the cyclic garbage here. + if (enabled) { + shallRunCollector_ = true; + CHECK_CALL(pthread_cond_signal(&cond_), "Cannot signal collector") + } + currentAliveWorkers_--; + } + + void addRoot(ObjHeader* obj) { + COLLECTOR_LOG("add root %p\n", obj); + // TODO: we can only add root when collector is not processing, which looks like a limitation, + // instead we can add elements to the side buffer or have a separate lock for that. + suggestLockRelease(); + Locker lock(&lock_); + rootset_.insert(obj); + } + + void removeRoot(ObjHeader* obj) { + COLLECTOR_LOG("remove root %p\n", obj); + // Note that we can only remove root when the collector is not processing. + suggestLockRelease(); + Locker lock(&lock_); + toRelease_.erase(obj); + rootset_.erase(obj); + } + + void mutateRoot(ObjHeader* newValue) { + // TODO: consider optimization, when clearing value (setting to null) in atomic reference shall not lead + // to invalidation of the collector analysis state. + atomicSet(&mutatedAtomics_, 1); + } + + void suggestLockRelease() { + atomicSet(&mutatedAtomics_, 1); + } + + bool checkIfShallCollect() { + auto tick = atomicAdd(¤tTick_, 1); + auto delta = tick - atomicGet(&lastTick_); + if (delta > 10 || delta < 0) { + auto currentTimestampUs = konan::getTimeMicros(); +#if KONAN_NO_64BIT_ATOMIC + if (currentTimestampUs - *(volatile int64_t*)&lastTimestampUs_ > 10000) { +#else + if (currentTimestampUs - atomicGet(&lastTimestampUs_) > 10000) { +#endif // KONAN_NO_64BIT_ATOMIC + // Do we care if this lock is not here? + Locker locker(×tampLock_); + lastTick_ = currentTick_; + lastTimestampUs_ = currentTimestampUs; + return true; + } + } + return false; + } + + void releasePendingUnlocked(void* worker) { + // We are not doing that on the UI thread, as taking lock is slow, unless + // it happens on deinit of the collector or if there are no other workers. + if ((atomicGet(&pendingRelease_) != 0) && ((worker != mainWorker_) || (currentAliveWorkers_ == 1))) { + KStdVector heapRefsToRelease; + + { + suggestLockRelease(); + Locker locker(&lock_); + COLLECTOR_LOG("clearing %d release candidates on %p\n", toRelease_.size(), worker); + for (auto* it: toRelease_) { + COLLECTOR_LOG("clear references in %p\n", it) + traverseObjectFields(it, [&heapRefsToRelease](ObjHeader** location) { + // Avoid using ZeroHeapRef here: it can provoke garbageCollect() which would then stuck on taking [lock_] + // (which is already taken above). + auto* value = *location; + if (reinterpret_cast(value) > 1) { + *location = nullptr; + heapRefsToRelease.push_back(value); + } + }); + } + toRelease_.clear(); + atomicSet(&pendingRelease_, 0); + } + + for (auto* it: heapRefsToRelease) { + ReleaseHeapRef(it); + } + } + } + + void collectorCallaback(void* worker) { + if (atomicGet(&gcRunning_) != 0) return; + releasePendingUnlocked(worker); + if (checkIfShallCollect()) { + Locker locker(&lock_); + shallRunCollector_ = true; + CHECK_CALL(pthread_cond_signal(&cond_), "Cannot signal collector") + } + } + + void scheduleGarbageCollect() { + if (atomicGet(&gcRunning_) != 0) return; + Locker lock(&lock_); + shallRunCollector_ = true; + CHECK_CALL(pthread_cond_signal(&cond_), "Cannot signal collector") + } + + void localGC() { + // We just need to take GC lock here, to avoid release of object we walk on. + // TODO: consider optimization without taking the lock and just notifying collector via an atomic. + suggestLockRelease(); + Locker locker(&lock_); + } + +}; + +CyclicCollector* cyclicCollector = nullptr; + +} // namespace + +#endif // WITH_WORKERS + +void cyclicInit() { +#if WITH_WORKERS + RuntimeAssert(cyclicCollector == nullptr, "Must be not yet inited"); + cyclicCollector = konanConstructInstance(); +#endif +} + +void cyclicDeinit(bool enabled) { +#if WITH_WORKERS + RuntimeAssert(cyclicCollector != nullptr, "Must be inited"); + auto* local = cyclicCollector; + local->terminate(enabled); + cyclicCollector = nullptr; + // Workaround data race with threads non-atomically reading and then using [cyclicCollector]. + // konanDestructInstance(local); + // Note: memory leaks here indeed, but usually it happens once per application. + // Make best effort to clean some memory: + local->clear(); +#endif // WITH_WORKERS +} + +void cyclicAddWorker(void* worker) { +#if WITH_WORKERS + auto* local = cyclicCollector; + if (local) + local->addWorker(worker); +#endif // WITH_WORKERS +} + +void cyclicRemoveWorker(void* worker, bool enabled) { +#if WITH_WORKERS + auto* local = cyclicCollector; + if (local) + local->removeWorker(worker, enabled); +#endif // WITH_WORKERS +} + +void cyclicCollectorCallback(void* worker) { +#if WITH_WORKERS + auto* local = cyclicCollector; + if (local) + local->collectorCallaback(worker); +#endif // WITH_WORKERS +} + +void cyclicScheduleGarbageCollect() { +#if WITH_WORKERS + auto* local = cyclicCollector; + if (local) + local->scheduleGarbageCollect(); +#endif // WITH_WORKERS +} + +void cyclicAddAtomicRoot(ObjHeader* obj) { +#if WITH_WORKERS + auto* local = cyclicCollector; + if (local) + local->addRoot(obj); +#endif // WITH_WORKERS +} + +void cyclicRemoveAtomicRoot(ObjHeader* obj) { +#if WITH_WORKERS + auto* local = cyclicCollector; + if (local) + local->removeRoot(obj); +#endif // WITH_WORKERS +} + +void cyclicMutateAtomicRoot(ObjHeader* newValue) { +#if WITH_WORKERS + auto* local = cyclicCollector; + if (local) + local->mutateRoot(newValue); +#endif // WITH_WORKERS +} + +void cyclicLocalGC() { +#if WITH_WORKERS + auto* local = cyclicCollector; + if (local) + local->localGC(); +#endif // WITH_WORKERS +} diff --git a/kotlin-native/runtime/src/legacymm/cpp/CyclicCollector.h b/kotlin-native/runtime/src/legacymm/cpp/CyclicCollector.h new file mode 100644 index 00000000000..09764b054f2 --- /dev/null +++ b/kotlin-native/runtime/src/legacymm/cpp/CyclicCollector.h @@ -0,0 +1,17 @@ +#ifndef RUNTIME_CYCLIC_COLLECTOR_H +#define RUNTIME_CYCLIC_COLLECTOR_H + +struct ObjHeader; + +void cyclicInit(); +void cyclicDeinit(bool enabled); +void cyclicAddWorker(void* worker); +void cyclicRemoveWorker(void* worker, bool enabled); +void cyclicAddAtomicRoot(ObjHeader* obj); +void cyclicRemoveAtomicRoot(ObjHeader* obj); +void cyclicMutateAtomicRoot(ObjHeader* newValue); +void cyclicCollectorCallback(void* worker); +void cyclicLocalGC(); +void cyclicScheduleGarbageCollect(); + +#endif // RUNTIME_CYCLIC_COLLECTOR_H \ No newline at end of file diff --git a/kotlin-native/runtime/src/legacymm/cpp/Memory.cpp b/kotlin-native/runtime/src/legacymm/cpp/Memory.cpp new file mode 100644 index 00000000000..b23ed452b96 --- /dev/null +++ b/kotlin-native/runtime/src/legacymm/cpp/Memory.cpp @@ -0,0 +1,3611 @@ +/* + * Copyright 2010-2020 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include + +#include // for offsetof + +// Allow concurrent global cycle collector. +#define USE_CYCLIC_GC 0 + +// CycleDetector internally uses static local with runtime initialization, +// which requires atomics. Atomics are not available on WASM. +#ifdef KONAN_WASM +#define USE_CYCLE_DETECTOR 0 +#else +#define USE_CYCLE_DETECTOR 1 +#endif + +#include "Alloc.h" +#include "KAssert.h" +#include "Atomic.h" +#include "Cleaner.h" +#if USE_CYCLIC_GC +#include "CyclicCollector.h" +#endif // USE_CYCLIC_GC +#include "Exceptions.h" +#include "KString.h" +#include "Memory.h" +#include "MemoryPrivate.hpp" +#include "Natives.h" +#include "Porting.h" +#include "Runtime.h" +#include "Utils.h" +#include "WorkerBoundReference.h" +#include "Weak.h" + +#ifdef KONAN_OBJC_INTEROP +#include "ObjCMMAPI.h" +#endif + +// If garbage collection algorithm for cyclic garbage to be used. +// We are using the Bacon's algorithm for GC, see +// http://researcher.watson.ibm.com/researcher/files/us-bacon/Bacon03Pure.pdf. +#define USE_GC 1 +// Define to 1 to print all memory operations. +#define TRACE_MEMORY 0 +// Define to 1 to print major GC events. +#define TRACE_GC 0 +// Collect memory manager events statistics. +#define COLLECT_STATISTIC 0 +// Define to 1 to print detailed time statistics for GC events. +#define PROFILE_GC 0 + +#if COLLECT_STATISTIC +#include +#endif + +namespace { + +typedef uint32_t container_size_t; + +// Granularity of arena container chunks. +constexpr container_size_t kContainerAlignment = 1024; +// Single object alignment. +constexpr container_size_t kObjectAlignment = 8; + +// Required e.g. for object size computations to be correct. +static_assert(sizeof(ContainerHeader) % kObjectAlignment == 0, "sizeof(ContainerHeader) is not aligned"); + +#if TRACE_MEMORY +#undef TRACE_GC +#define TRACE_GC 1 +#define MEMORY_LOG(...) konan::consolePrintf(__VA_ARGS__); +#else +#define MEMORY_LOG(...) +#endif + +#if TRACE_GC +#define GC_LOG(...) konan::consolePrintf(__VA_ARGS__); +#else +#define GC_LOG(...) +#endif + +#if USE_GC +// Collection threshold default (collect after having so many elements in the +// release candidates set). +constexpr size_t kGcThreshold = 8 * 1024; +// Ergonomic thresholds. +// If GC to computations time ratio is above that value, +// increase GC threshold by 1.5 times. +constexpr double kGcToComputeRatioThreshold = 0.5; +// Never exceed this value when increasing GC threshold. +constexpr size_t kMaxErgonomicThreshold = 32 * 1024; +// Threshold of size for toFree set, triggering actual cycle collector. +constexpr size_t kMaxToFreeSizeThreshold = 8 * 1024; +// Never exceed this value when increasing size for toFree set, triggering actual cycle collector. +constexpr size_t kMaxErgonomicToFreeSizeThreshold = 8 * 1024 * 1024; +// How many elements in finalizer queue allowed before cleaning it up. +constexpr int32_t kFinalizerQueueThreshold = 32; +// If allocated that much memory since last GC - force new GC. +constexpr size_t kMaxGcAllocThreshold = 8 * 1024 * 1024; +// If the ratio of GC collection cycles time to program execution time is greater this value, +// increase GC threshold for cycles collection. +constexpr double kGcCollectCyclesLoadRatio = 0.3; +// Minimum time of cycles collection to change thresholds. +constexpr size_t kGcCollectCyclesMinimumDuration = 200; + +#endif // USE_GC + +typedef KStdUnorderedSet ContainerHeaderSet; +typedef KStdVector ContainerHeaderList; +typedef KStdDeque ContainerHeaderDeque; +typedef KStdVector KRefList; +typedef KStdVector KRefPtrList; +typedef KStdUnorderedSet KRefSet; +typedef KStdUnorderedMap KRefIntMap; +typedef KStdDeque KRefDeque; +typedef KStdDeque KRefListDeque; +typedef KStdUnorderedMap> KThreadLocalStorageMap; + +// A little hack that allows to enable -O2 optimizations +// Prevents clang from replacing FrameOverlay struct +// with single pointer. +// Can be removed when FrameOverlay will become more complex. +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wunused-variable" +FrameOverlay exportFrameOverlay; +#pragma clang diagnostic pop + +// Current number of allocated containers. +volatile int allocCount = 0; +volatile int aliveMemoryStatesCount = 0; + +#if USE_CYCLIC_GC +KBoolean g_hasCyclicCollector = true; +#endif // USE_CYCLIC_GC + +// TODO: Consider using ObjHolder. +class ScopedRefHolder { + public: + ScopedRefHolder() = default; + + explicit ScopedRefHolder(KRef obj); + + ScopedRefHolder(const ScopedRefHolder&) = delete; + + ScopedRefHolder(ScopedRefHolder&& other) noexcept: obj_(other.obj_) { + other.obj_ = nullptr; + } + + ScopedRefHolder& operator=(const ScopedRefHolder&) = delete; + + ScopedRefHolder& operator=(ScopedRefHolder&& other) noexcept { + ScopedRefHolder tmp(std::move(other)); + swap(tmp); + return *this; + } + + ~ScopedRefHolder(); + + void swap(ScopedRefHolder& other) noexcept { + std::swap(obj_, other.obj_); + } + + private: + KRef obj_ = nullptr; +}; + +#if USE_CYCLE_DETECTOR + +struct CycleDetectorRootset { + // Orders roots. + KStdVector roots; + // Pins a state of each root. + KStdUnorderedMap> rootToFields; + // Holding roots and their fields to avoid GC-ing them. + KStdVector heldRefs; +}; + +class CycleDetector { + public: + static void insertCandidateIfNeeded(KRef object) { + if (canBeACandidate(object)) + instance().insertCandidate(object); + } + + static void removeCandidateIfNeeded(KRef object) { + if (canBeACandidate(object)) + instance().removeCandidate(object); + } + + static CycleDetectorRootset collectRootset(); + + private: + CycleDetector() = default; + ~CycleDetector() = default; + CycleDetector(const CycleDetector&) = delete; + CycleDetector(CycleDetector&&) = delete; + CycleDetector& operator=(const CycleDetector&) = delete; + CycleDetector& operator=(CycleDetector&&) = delete; + + static CycleDetector& instance() { + // Only store a pointer to CycleDetector in .bss + static CycleDetector* result = new CycleDetector(); + return *result; + } + + static bool canBeACandidate(KRef object) { + return KonanNeedDebugInfo && + Kotlin_memoryLeakCheckerEnabled() && + (object->type_info()->flags_ & TF_LEAK_DETECTOR_CANDIDATE) != 0; + } + + void insertCandidate(KRef candidate) { + LockGuard guard(lock_); + + auto it = candidateList_.insert(candidateList_.begin(), candidate); + candidateInList_.emplace(candidate, it); + } + + void removeCandidate(KRef candidate) { + LockGuard guard(lock_); + + auto it = candidateInList_.find(candidate); + if (it == candidateInList_.end()) + return; + candidateList_.erase(it->second); + candidateInList_.erase(it); + } + + SimpleMutex lock_; + using CandidateList = KStdList; + CandidateList candidateList_; + KStdUnorderedMap candidateInList_; +}; + +#endif // USE_CYCLE_DETECTOR + +// TODO: can we pass this variable as an explicit argument? +THREAD_LOCAL_VARIABLE MemoryState* memoryState = nullptr; +THREAD_LOCAL_VARIABLE FrameOverlay* currentFrame = nullptr; + +#if COLLECT_STATISTIC +class MemoryStatistic { +public: + // UpdateRef per-object type counters. + uint64_t updateCounters[12][10]; + // Alloc per container type counters. + uint64_t containerAllocs[2]; + // Free per container type counters. + uint64_t objectAllocs[6]; + // Histogram of allocation size distribution. + KStdUnorderedMap* allocationHistogram; + // Number of allocation cache hits. + int allocCacheHit; + // Number of allocation cache misses. + int allocCacheMiss; + // Number of regular reference increments. + uint64_t addRefs; + // Number of atomic reference increments. + uint64_t atomicAddRefs; + // Number of regular reference decrements. + uint64_t releaseRefs; + // Number of atomic reference decrements. + uint64_t atomicReleaseRefs; + // Number of potential cycle candidates. + uint64_t releaseCyclicRefs; + + // Map of array index to human readable name. + static constexpr const char* indexToName[] = { + "local ", "stack ", "perm ", "frozen", "shared", "null " }; + + void init() { + memset(containerAllocs, 0, sizeof(containerAllocs)); + memset(objectAllocs, 0, sizeof(objectAllocs)); + memset(updateCounters, 0, sizeof(updateCounters)); + allocationHistogram = konanConstructInstance>(); + allocCacheHit = 0; + allocCacheMiss = 0; + } + + void deinit() { + konanDestructInstance(allocationHistogram); + allocationHistogram = nullptr; + } + + void incAddRef(const ContainerHeader* header, bool atomic, int stack) { + if (atomic) atomicAddRefs++; else addRefs++; + } + + void incReleaseRef(const ContainerHeader* header, bool atomic, bool cyclic, int stack) { + if (atomic) { + atomicReleaseRefs++; + } else { + if (cyclic) releaseCyclicRefs++; else releaseRefs++; + } + } + + void incUpdateRef(const ObjHeader* objOld, const ObjHeader* objNew, int stack) { + updateCounters[toIndex(objOld, stack)][toIndex(objNew, stack)]++; + } + + void incAlloc(size_t size, const ContainerHeader* header) { + containerAllocs[0]++; + ++(*allocationHistogram)[size]; + } + + void incFree(const ContainerHeader* header) { + containerAllocs[1]++; + } + + void incAlloc(size_t size, const ObjHeader* header) { + objectAllocs[toIndex(header, 0)]++; + } + + static int toIndex(const ObjHeader* obj, int stack) { + if (reinterpret_cast(obj) > 1) + return toIndex(containerFor(obj), stack); + else + return 4 + stack * 6; + } + + static int toIndex(const ContainerHeader* header, int stack) { + if (header == nullptr) return 2 + stack * 6; // permanent. + switch (header->tag()) { + case CONTAINER_TAG_LOCAL : return 0 + stack * 6; + case CONTAINER_TAG_STACK : return 1 + stack * 6; + case CONTAINER_TAG_FROZEN : return 3 + stack * 6; + case CONTAINER_TAG_SHARED : return 4 + stack * 6; + + } + RuntimeAssert(false, "unknown container type"); + return -1; + } + + static double percents(uint64_t value, uint64_t all) { + return all == 0 ? 0 : ((double)value / (double)all) * 100.0; + } + + void printStatistic() { + konan::consolePrintf("\nMemory manager statistic:\n\n"); + konan::consolePrintf("Container alloc: %lld, free: %lld\n", + containerAllocs[0], containerAllocs[1]); + for (int i = 0; i < 6; i++) { + // Only local, shared and frozen can be allocated. + if (i == 0 || i == 3 || i == 4) + konan::consolePrintf("Object %s alloc: %lld\n", indexToName[i], objectAllocs[i]); + } + konan::consolePrintf("\n"); + + uint64_t allUpdateRefs = 0, heapUpdateRefs = 0, stackUpdateRefs = 0; + for (int i = 0; i < 12; i++) { + for (int j = 0; j < 12; j++) { + allUpdateRefs += updateCounters[i][j]; + if (i < 6 && j < 6) + heapUpdateRefs += updateCounters[i][j]; + if (i >= 6 && j >= 6) + stackUpdateRefs += updateCounters[i][j]; + } + } + konan::consolePrintf("Total updates: %lld, stack: %lld(%.2lf%%), heap: %lld(%.2lf%%)\n", + allUpdateRefs, + stackUpdateRefs, percents(stackUpdateRefs, allUpdateRefs), + heapUpdateRefs, percents(heapUpdateRefs, allUpdateRefs)); + for (int i = 0; i < 6; i++) { + for (int j = 0; j < 6; j++) { + if (updateCounters[i][j] != 0) + konan::consolePrintf("UpdateHeapRef[%s -> %s]: %lld (%.2lf%% of all, %.2lf%% of heap)\n", + indexToName[i], indexToName[j], updateCounters[i][j], + percents(updateCounters[i][j], allUpdateRefs), + percents(updateCounters[i][j], heapUpdateRefs)); + } + } + for (int i = 6; i < 12; i++) { + for (int j = 6; j < 12; j++) { + if (updateCounters[i][j] != 0) + konan::consolePrintf("UpdateStackRef[%s -> %s]: %lld (%.2lf%% of all, %.2lf%% of stack)\n", + indexToName[i - 6], indexToName[j - 6], + updateCounters[i][j], + percents(updateCounters[i][j], allUpdateRefs), + percents(updateCounters[i][j], stackUpdateRefs)); + } + } + konan::consolePrintf("\n"); + + konan::consolePrintf("Allocation histogram:\n"); + KStdVector keys(allocationHistogram->size()); + int index = 0; + for (auto& it : *allocationHistogram) { + keys[index++] = it.first; + } + std::sort(keys.begin(), keys.end()); + int perLine = 4; + int count = 0; + for (auto it : keys) { + konan::consolePrintf( + "%d bytes -> %d times ", it, (*allocationHistogram)[it]); + if (++count % perLine == (perLine - 1) || (count == keys.size())) + konan::consolePrintf("\n"); + } + + + uint64_t allAddRefs = addRefs + atomicAddRefs; + uint64_t allReleases = releaseRefs + atomicReleaseRefs + releaseCyclicRefs; + konan::consolePrintf("AddRefs:\t%lld/%lld (%.2lf%% of atomic)\n" + "Releases:\t%lld/%lld (%.2lf%% of atomic)\n" + "ReleaseRefs affecting cycle collector : %lld (%.2lf%% of cyclic)\n", + addRefs, atomicAddRefs, percents(atomicAddRefs, allAddRefs), + releaseRefs, atomicReleaseRefs, percents(atomicReleaseRefs, allReleases), + releaseCyclicRefs, percents(releaseCyclicRefs, allReleases)); + } +}; + +constexpr const char* MemoryStatistic::indexToName[]; + +#endif // COLLECT_STATISTIC + +inline bool isPermanentOrFrozen(ContainerHeader* container) { + return container == nullptr || container->frozen(); +} + +inline bool isShareable(ContainerHeader* container) { + return container == nullptr || container->shareable(); +} + +void setContainerFor(ObjHeader* obj, ContainerHeader* container) { + obj->meta_object()->container_ = container; + obj->typeInfoOrMeta_ = setPointerBits(obj->typeInfoOrMeta_, OBJECT_TAG_NONTRIVIAL_CONTAINER); +} + +} // namespace + +ContainerHeader* containerFor(const ObjHeader* obj) { + unsigned bits = getPointerBits(obj->typeInfoOrMeta_, OBJECT_TAG_MASK); + if ((bits & (OBJECT_TAG_PERMANENT_CONTAINER | OBJECT_TAG_NONTRIVIAL_CONTAINER)) == 0) + return reinterpret_cast(const_cast(obj)) - 1; + if ((bits & OBJECT_TAG_PERMANENT_CONTAINER) != 0) + return nullptr; + return (reinterpret_cast(clearPointerBits(obj->typeInfoOrMeta_, OBJECT_TAG_MASK)))->container_; +} + +ALWAYS_INLINE bool isFrozen(const ObjHeader* obj) { + return containerFor(obj)->frozen(); +} + +ALWAYS_INLINE bool isPermanentOrFrozen(const ObjHeader* obj) { + auto* container = containerFor(obj); + return container == nullptr || container->frozen(); +} + +ALWAYS_INLINE bool isShareable(const ObjHeader* obj) { + return containerFor(obj)->shareable(); +} + +ObjHeader** ObjHeader::GetWeakCounterLocation() { + return &this->meta_object()->WeakReference.counter_; +} + +#if KONAN_OBJC_INTEROP + +void* ObjHeader::GetAssociatedObject() { + if (!has_meta_object()) { + return nullptr; + } + return this->meta_object()->associatedObject_; +} + +void** ObjHeader::GetAssociatedObjectLocation() { + return &this->meta_object()->associatedObject_; +} + +void ObjHeader::SetAssociatedObject(void* obj) { + this->meta_object()->associatedObject_ = obj; +} + +#endif // KONAN_OBJC_INTEROP + +class ForeignRefManager { + public: + static ForeignRefManager* create() { + ForeignRefManager* result = konanConstructInstance(); + result->addRef(); + return result; + } + + void addRef() { + atomicAdd(&refCount, 1); + } + + void releaseRef() { + if (atomicAdd(&this->refCount, -1) == 0) { + // So the owning MemoryState has abandoned [this]. + // Leaving the queued work items would result in memory leak. + // Luckily current thread has exclusive access to [this], + // so it can process the queue pretending like it takes ownership of all its objects: + this->processAbandoned(); + + konanDestructInstance(this); + } + } + + bool tryReleaseRefOwned() { + if (atomicAdd(&this->refCount, -1) == 0) { + if (this->releaseList != nullptr) { + // There are no more holders of [this] to process the enqueued work items in [releaseRef]. + // Revert the reference counter back and notify the caller to process and then retry: + atomicAdd(&this->refCount, 1); + return false; + } + + konanDestructInstance(this); + } + + return true; + } + + void enqueueReleaseRef(ObjHeader* obj) { + ListNode* newListNode = konanConstructInstance(); + newListNode->obj = obj; + while (true) { + ListNode* next = this->releaseList; + newListNode->next = next; + if (compareAndSet(&this->releaseList, next, newListNode)) break; + } + } + + template + void processEnqueuedReleaseRefsWith(func process) { + if (releaseList == nullptr) return; + + ListNode* toProcess = nullptr; + + while (true) { + toProcess = releaseList; + if (compareAndSet(&this->releaseList, toProcess, nullptr)) break; + } + + while (toProcess != nullptr) { + process(toProcess->obj); + ListNode* next = toProcess->next; + konanDestructInstance(toProcess); + toProcess = next; + } + } + +private: + int refCount; + + struct ListNode { + ObjHeader* obj; + ListNode* next; + }; + + ListNode* volatile releaseList; + + void processAbandoned() { + if (this->releaseList != nullptr) { + bool hadNoStateInitialized = (memoryState == nullptr); + + if (hadNoStateInitialized) { + // Disregard request if all runtimes are no longer alive. + if (atomicGet(&aliveMemoryStatesCount) == 0) + return; + + memoryState = InitMemory(); // Required by ReleaseHeapRef. + } + + processEnqueuedReleaseRefsWith([](ObjHeader* obj) { + ReleaseHeapRef(obj); + }); + + if (hadNoStateInitialized) { + // Discard the memory state. + DeinitMemory(memoryState); + } + } + } +}; + +struct MemoryState { +#if TRACE_MEMORY + // Set of all containers. + ContainerHeaderSet* containers; +#endif + + KThreadLocalStorageMap* tlsMap; + KRef* tlsMapLastStart; + void* tlsMapLastKey; + +#if USE_GC + // Finalizer queue - linked list of containers scheduled for finalization. + ContainerHeader* finalizerQueue; + int finalizerQueueSize; + int finalizerQueueSuspendCount; + /* + * Typical scenario for GC is as following: + * we have 90% of objects with refcount = 0 which will be deleted during + * the first phase of the algorithm. + * We could mark them with a bit in order to tell the next two phases to skip them + * and thus requiring only one list, but the downside is that both of the + * next phases would iterate over the whole list of objects instead of only 10%. + */ + ContainerHeaderList* toFree; // List of all cycle candidates. + ContainerHeaderList* roots; // Real candidates excluding those with refcount = 0. + // How many GC suspend requests happened. + int gcSuspendCount; + // How many candidate elements in toRelease shall trigger collection. + size_t gcThreshold; + // How many candidate elements in toFree shall trigger cycle collection. + uint64_t gcCollectCyclesThreshold; + // If collection is in progress. + bool gcInProgress; + // Objects to be released. + ContainerHeaderList* toRelease; + + ForeignRefManager* foreignRefManager; + + bool gcErgonomics; + uint64_t lastGcTimestamp; + uint64_t lastCyclicGcTimestamp; + uint32_t gcEpoque; + + uint64_t allocSinceLastGc; + uint64_t allocSinceLastGcThreshold; +#endif // USE_GC + + // A stack of initializing singletons. + KStdVector> initializingSingletons; + +#if COLLECT_STATISTIC + #define CONTAINER_ALLOC_STAT(state, size, container) state->statistic.incAlloc(size, container); + #define CONTAINER_DESTROY_STAT(state, container) \ + state->statistic.incFree(container); + #define OBJECT_ALLOC_STAT(state, size, object) \ + state->statistic.incAlloc(size, object); \ + state->statistic.incAddRef(containerFor(object), 0, 0); + #define UPDATE_REF_STAT(state, oldRef, newRef, slot, stack) \ + state->statistic.incUpdateRef(oldRef, newRef, stack); + #define UPDATE_ADDREF_STAT(state, obj, atomic, stack) \ + state->statistic.incAddRef(obj, atomic, stack); + #define UPDATE_RELEASEREF_STAT(state, obj, atomic, cyclic, stack) \ + state->statistic.incReleaseRef(obj, atomic, cyclic, stack); + #define INIT_STAT(state) \ + state->statistic.init(); + #define DEINIT_STAT(state) \ + state->statistic.deinit(); + #define PRINT_STAT(state) \ + state->statistic.printStatistic(); + MemoryStatistic statistic; +#else + #define CONTAINER_ALLOC_STAT(state, size, container) + #define CONTAINER_DESTROY_STAT(state, container) + #define OBJECT_ALLOC_STAT(state, size, object) + #define UPDATE_REF_STAT(state, oldRef, newRef, slot, stack) + #define UPDATE_ADDREF_STAT(state, obj, atomic, stack) + #define UPDATE_RELEASEREF_STAT(state, obj, atomic, cyclic, stack) + #define INIT_STAT(state) + #define DEINIT_STAT(state) + #define PRINT_STAT(state) +#endif // COLLECT_STATISTIC +}; + +namespace { + +#if TRACE_MEMORY +#define INIT_TRACE(state) \ + memoryState->containers = konanConstructInstance(); +#define DEINIT_TRACE(state) \ + konanDestructInstance(memoryState->containers); \ + memoryState->containers = nullptr; +#else +#define INIT_TRACE(state) +#define DEINIT_TRACE(state) +#endif +#define CONTAINER_ALLOC_TRACE(state, size, container) \ + MEMORY_LOG("Container alloc %d at %p\n", size, container) +#define CONTAINER_DESTROY_TRACE(state, container) \ + MEMORY_LOG("Container destroy %p\n", container) +#define OBJECT_ALLOC_TRACE(state, size, object) \ + MEMORY_LOG("Object alloc %d at %p\n", size, object) +#define UPDATE_REF_TRACE(state, oldRef, newRef, slot, stack) \ + MEMORY_LOG("UpdateRef %s*%p: %p -> %p\n", stack ? "stack " : "heap ", slot, oldRef, newRef) + +// Events macro definitions. +// Called on worker's memory init. +#define INIT_EVENT(state) \ + INIT_STAT(state) \ + INIT_TRACE(state) +// Called on worker's memory deinit. +#define DEINIT_EVENT(state) \ + DEINIT_STAT(state) +// Called on container allocation. +#define CONTAINER_ALLOC_EVENT(state, size, container) \ + CONTAINER_ALLOC_STAT(state, size, container) \ + CONTAINER_ALLOC_TRACE(state, size, container) +// Called on container destroy (memory is released to allocator). +#define CONTAINER_DESTROY_EVENT(state, container) \ + CONTAINER_DESTROY_STAT(state, container) \ + CONTAINER_DESTROY_TRACE(state, container) +// Object was just allocated. +#define OBJECT_ALLOC_EVENT(state, size, object) \ + OBJECT_ALLOC_STAT(state, size, object) \ + OBJECT_ALLOC_TRACE(state, size, object) +// Object is freed. +#define OBJECT_FREE_EVENT(state, size, object) \ + OBJECT_FREE_STAT(state, size, object) \ + OBJECT_FREE_TRACE(state, object) +// Reference in memory is being updated. +#define UPDATE_REF_EVENT(state, oldRef, newRef, slot, stack) \ + UPDATE_REF_STAT(state, oldRef, newRef, slot, stack) \ + UPDATE_REF_TRACE(state, oldRef, newRef, slot, stack) +// Infomation shall be printed as worker is exiting. +#define PRINT_EVENT(state) \ + PRINT_STAT(state) + +// Forward declarations. +void freeContainer(ContainerHeader* header) NO_INLINE; +#if USE_GC +void garbageCollect(MemoryState* state, bool force) NO_INLINE; +void cyclicGarbageCollect() NO_INLINE; +void rememberNewContainer(ContainerHeader* container); +#endif // USE_GC + +// Class representing arbitrary placement container. +class Container { + public: + ContainerHeader* header() const { return header_; } + protected: + // Data where everything is being stored. + ContainerHeader* header_; + + void SetHeader(ObjHeader* obj, const TypeInfo* type_info) { + obj->typeInfoOrMeta_ = const_cast(type_info); + // Take into account typeInfo's immutability for ARC strategy. + if ((type_info->flags_ & TF_IMMUTABLE) != 0) + header_->refCount_ |= CONTAINER_TAG_FROZEN; + if ((type_info->flags_ & TF_ACYCLIC) != 0) + header_->setColorEvenIfGreen(CONTAINER_TAG_GC_GREEN); + } +}; + +// Container for a single object. +class ObjectContainer : public Container { + public: + // Single instance. + explicit ObjectContainer(MemoryState* state, const TypeInfo* type_info) { + Init(state, type_info); + } + + // Object container shalln't have any dtor, as it's being freed by + // ::Release(). + + ObjHeader* GetPlace() const { + return reinterpret_cast(header_ + 1); + } + + private: + void Init(MemoryState* state, const TypeInfo* type_info); +}; + + +class ArrayContainer : public Container { + public: + ArrayContainer(MemoryState* state, const TypeInfo* type_info, uint32_t elements) { + Init(state, type_info, elements); + } + + // Array container shalln't have any dtor, as it's being freed by ::Release(). + + ArrayHeader* GetPlace() const { + return reinterpret_cast(header_ + 1); + } + + private: + void Init(MemoryState* state, const TypeInfo* type_info, uint32_t elements); +}; + +// Class representing arena-style placement container. +// Container is used for reference counting, and it is assumed that objects +// with related placement will share container. Only +// whole container can be freed, individual objects are not taken into account. +class ArenaContainer; + +struct ContainerChunk { + ContainerChunk* next; + ArenaContainer* arena; + // Then we have ContainerHeader here. + ContainerHeader* asHeader() { + return reinterpret_cast(this + 1); + } +}; + +class ArenaContainer { + public: + void Init(); + void Deinit(); + + // Place individual object in this container. + ObjHeader* PlaceObject(const TypeInfo* type_info); + + // Places an array of certain type in this container. Note that array_type_info + // is type info for an array, not for an individual element. Also note that exactly + // same operation could be used to place strings. + ArrayHeader* PlaceArray(const TypeInfo* array_type_info, container_size_t count); + + ObjHeader** getSlot(); + + private: + void* place(container_size_t size); + + bool allocContainer(container_size_t minSize); + + void setHeader(ObjHeader* obj, const TypeInfo* typeInfo) { + obj->typeInfoOrMeta_ = const_cast(typeInfo); + setContainerFor(obj, currentChunk_->asHeader()); + // Here we do not take into account typeInfo's immutability for ARC strategy, as there's no ARC. + } + + ContainerChunk* currentChunk_; + uint8_t* current_; + uint8_t* end_; + ArrayHeader* slots_; + uint32_t slotsCount_; +}; + +constexpr int kFrameOverlaySlots = sizeof(FrameOverlay) / sizeof(ObjHeader**); + +inline bool isFreeable(const ContainerHeader* header) { + return header != nullptr && header->tag() != CONTAINER_TAG_STACK; +} + +inline bool isArena(const ContainerHeader* header) { + return header != nullptr && header->stack(); +} + +inline bool isAggregatingFrozenContainer(const ContainerHeader* header) { + return header != nullptr && header->frozen() && header->objectCount() > 1; +} + +inline bool isMarkedAsRemoved(ContainerHeader* container) { + return (reinterpret_cast(container) & 1) != 0; +} + +inline ContainerHeader* markAsRemoved(ContainerHeader* container) { + return reinterpret_cast(reinterpret_cast(container) | 1); +} + +inline ContainerHeader* clearRemoved(ContainerHeader* container) { + return reinterpret_cast( + reinterpret_cast(container) & ~static_cast(1)); +} + +inline container_size_t alignUp(container_size_t size, int alignment) { + return (size + alignment - 1) & ~(alignment - 1); +} + +inline ContainerHeader* realShareableContainer(ContainerHeader* container) { + RuntimeAssert(container->shareable(), "Only makes sense on shareable objects"); + return containerFor(reinterpret_cast(container + 1)); +} + +inline uint32_t arrayObjectSize(const TypeInfo* typeInfo, uint32_t count) { + // Note: array body is aligned, but for size computation it is enough to align the sum. + static_assert(kObjectAlignment % alignof(KLong) == 0, ""); + static_assert(kObjectAlignment % alignof(KDouble) == 0, ""); + return alignUp(sizeof(ArrayHeader) - typeInfo->instanceSize_ * count, kObjectAlignment); +} + +inline uint32_t arrayObjectSize(const ArrayHeader* obj) { + return arrayObjectSize(obj->type_info(), obj->count_); +} + +// TODO: shall we do padding for alignment? +inline container_size_t objectSize(const ObjHeader* obj) { + const TypeInfo* type_info = obj->type_info(); + container_size_t size = (type_info->instanceSize_ < 0 ? + // An array. + arrayObjectSize(obj->array()) + : + type_info->instanceSize_); + return alignUp(size, kObjectAlignment); +} + +template +inline void traverseObjectFields(ObjHeader* obj, func process) { + const TypeInfo* typeInfo = obj->type_info(); + if (typeInfo != theArrayTypeInfo) { + for (int index = 0; index < typeInfo->objOffsetsCount_; index++) { + ObjHeader** location = reinterpret_cast( + reinterpret_cast(obj) + typeInfo->objOffsets_[index]); + process(location); + } + } else { + ArrayHeader* array = obj->array(); + for (uint32_t index = 0; index < array->count_; index++) { + process(ArrayAddressOfElementAt(array, index)); + } + } +} + +template +inline void traverseReferredObjects(ObjHeader* obj, func process) { + traverseObjectFields(obj, [process](ObjHeader** location) { + ObjHeader* ref = *location; + if (ref != nullptr) process(ref); + }); +} + +template +inline void traverseContainerObjects(ContainerHeader* container, func process) { + RuntimeAssert(!isAggregatingFrozenContainer(container), "Must not be called on such containers"); + ObjHeader* obj = reinterpret_cast(container + 1); + for (uint32_t i = 0; i < container->objectCount(); ++i) { + process(obj); + obj = reinterpret_cast( + reinterpret_cast(obj) + objectSize(obj)); + } +} + +template +inline void traverseContainerObjectFields(ContainerHeader* container, func process) { + traverseContainerObjects(container, [process](ObjHeader* obj) { + traverseObjectFields(obj, process); + }); +} + +template +inline void traverseContainerReferredObjects(ContainerHeader* container, func process) { + traverseContainerObjectFields(container, [process](ObjHeader** location) { + ObjHeader* ref = *location; + if (ref != nullptr) process(ref); + }); +} + +inline FrameOverlay* asFrameOverlay(ObjHeader** slot) { + return reinterpret_cast(slot); +} + +inline bool isRefCounted(KConstRef object) { + return isFreeable(containerFor(object)); +} + +inline void lock(KInt* spinlock) { + while (compareAndSwap(spinlock, 0, 1) != 0) {} +} + +inline void unlock(KInt* spinlock) { + RuntimeCheck(compareAndSwap(spinlock, 1, 0) == 1, "Must succeed"); +} + +inline bool canFreeze(ContainerHeader* container) { + if (IsStrictMemoryModel) + // In strict memory model we ignore permanent, frozen and shared object when recursively freezing. + return container != nullptr && !container->shareable(); + else + // In relaxed memory model we ignore permanent and frozen object when recursively freezing. + return container != nullptr && !container->frozen(); +} + +inline bool isFreezableAtomic(ObjHeader* obj) { + return obj->type_info() == theFreezableAtomicReferenceTypeInfo; +} + +inline bool isFreezableAtomic(ContainerHeader* container) { + RuntimeAssert(!isAggregatingFrozenContainer(container), "Must be single object"); + ObjHeader* obj = reinterpret_cast(container + 1); + return isFreezableAtomic(obj); +} + +ContainerHeader* allocContainer(MemoryState* state, size_t size) { + ContainerHeader* result = nullptr; +#if USE_GC + // We recycle elements of finalizer queue for new allocations, to avoid trashing memory manager. + ContainerHeader* container = state != nullptr ? state->finalizerQueue : nullptr; + ContainerHeader* previous = nullptr; + while (container != nullptr) { + // TODO: shall it be == instead? + if (container->hasContainerSize() && + container->containerSize() >= size && container->containerSize() <= size + 16) { + MEMORY_LOG("recycle %p for request %d\n", container, size) + result = container; + if (previous == nullptr) + state->finalizerQueue = container->nextLink(); + else + previous->setNextLink(container->nextLink()); + state->finalizerQueueSize--; + memset(container, 0, size); + break; + } + previous = container; + container = container->nextLink(); + } +#endif + if (result == nullptr) { +#if USE_GC + if (state != nullptr) + state->allocSinceLastGc += size; +#endif + result = konanConstructSizedInstance(alignUp(size, kObjectAlignment)); + atomicAdd(&allocCount, 1); + } + if (state != nullptr) { + CONTAINER_ALLOC_EVENT(state, size, result); +#if TRACE_MEMORY + state->containers->insert(result); +#endif + } + return result; +} + +ContainerHeader* allocAggregatingFrozenContainer(KStdVector& containers) { + auto componentSize = containers.size(); + auto* superContainer = allocContainer(memoryState, sizeof(ContainerHeader) + sizeof(void*) * componentSize); + auto* place = reinterpret_cast(superContainer + 1); + for (auto* container : containers) { + *place++ = container; + // Set link to the new container. + auto* obj = reinterpret_cast(container + 1); + setContainerFor(obj, superContainer); + MEMORY_LOG("Set fictitious frozen container for %p: %p\n", obj, superContainer); + } + superContainer->setObjectCount(componentSize); + superContainer->freeze(); + return superContainer; +} + + +#if USE_GC + +void processFinalizerQueue(MemoryState* state) { + // TODO: reuse elements of finalizer queue for new allocations. + while (state->finalizerQueue != nullptr) { + auto* container = state->finalizerQueue; + state->finalizerQueue = container->nextLink(); + state->finalizerQueueSize--; +#if TRACE_MEMORY + state->containers->erase(container); +#endif + CONTAINER_DESTROY_EVENT(state, container) + konanFreeMemory(container); + atomicAdd(&allocCount, -1); + } + RuntimeAssert(state->finalizerQueueSize == 0, "Queue must be empty here"); +} + +bool hasExternalRefs(ContainerHeader* start, ContainerHeaderSet* visited) { + ContainerHeaderDeque toVisit; + toVisit.push_back(start); + while (!toVisit.empty()) { + auto* container = toVisit.front(); + toVisit.pop_front(); + visited->insert(container); + if (container->refCount() > 0) { + MEMORY_LOG("container %p with rc %d blocks transfer\n", container, container->refCount()) + return true; + } + traverseContainerReferredObjects(container, [&toVisit, visited](ObjHeader* ref) { + auto* child = containerFor(ref); + if (!isShareable(child) && (visited->count(child) == 0)) { + toVisit.push_front(child); + } + }); + } + return false; +} + +#endif // USE_GC + +void scheduleDestroyContainer(MemoryState* state, ContainerHeader* container) { +#if USE_GC + RuntimeAssert(container != nullptr, "Cannot destroy null container"); + container->setNextLink(state->finalizerQueue); + state->finalizerQueue = container; + state->finalizerQueueSize++; + // We cannot clean finalizer queue while in GC. + if (!state->gcInProgress && state->finalizerQueueSuspendCount == 0 && + state->finalizerQueueSize >= kFinalizerQueueThreshold) { + processFinalizerQueue(state); + } +#else + konanFreeMemory(container); + atomicAdd(&allocCount, -1); + CONTAINER_DESTROY_EVENT(state, container); +#endif +} + +void freeAggregatingFrozenContainer(ContainerHeader* container) { + auto* state = memoryState; + RuntimeAssert(isAggregatingFrozenContainer(container), "expected fictitious frozen container"); + MEMORY_LOG("%p is fictitious frozen container\n", container); + RuntimeAssert(!container->buffered(), "frozen objects must not participate in GC") +#if USE_GC + // Forbid finalizerQueue handling. + ++state->finalizerQueueSuspendCount; +#endif + // Special container for frozen objects. + ContainerHeader** subContainer = reinterpret_cast(container + 1); + MEMORY_LOG("Total subcontainers = %d\n", container->objectCount()); + for (uint32_t i = 0; i < container->objectCount(); ++i) { + MEMORY_LOG("Freeing subcontainer %p\n", *subContainer); + freeContainer(*subContainer++); + } +#if USE_GC + --state->finalizerQueueSuspendCount; +#endif + scheduleDestroyContainer(state, container); + MEMORY_LOG("Freeing subcontainers done\n"); +} + +// Not inlining this call as it affects deallocation performance for +// all types. +NO_INLINE RUNTIME_NOTHROW void runFinalizers(ObjHeader* obj) { + auto* type_info = obj->type_info(); + if (type_info == theCleanerImplTypeInfo) { + DisposeCleaner(obj); + } + if (type_info == theWorkerBoundReferenceTypeInfo) { + DisposeWorkerBoundReference(obj); + } +} + +// This is called from 2 places where it's unconditionally called, +// so better be inlined. +ALWAYS_INLINE void runDeallocationHooks(ContainerHeader* container) { + ObjHeader* obj = reinterpret_cast(container + 1); + for (uint32_t index = 0; index < container->objectCount(); index++) { + auto* type_info = obj->type_info(); + if ((type_info->flags_ & TF_HAS_FINALIZER) != 0) { + runFinalizers(obj); + } +#if USE_CYCLIC_GC + if ((type_info->flags_ & TF_LEAK_DETECTOR_CANDIDATE) != 0) { + cyclicRemoveAtomicRoot(obj); + } +#endif // USE_CYCLIC_GC +#if USE_CYCLE_DETECTOR + CycleDetector::removeCandidateIfNeeded(obj); +#endif // USE_CYCLE_DETECTOR + if (obj->has_meta_object()) { + ObjHeader::destroyMetaObject(&obj->typeInfoOrMeta_); + } + obj = reinterpret_cast(reinterpret_cast(obj) + objectSize(obj)); + } +} + +void freeContainer(ContainerHeader* container) { + RuntimeAssert(container != nullptr, "this kind of container shalln't be freed"); + + if (isAggregatingFrozenContainer(container)) { + freeAggregatingFrozenContainer(container); + return; + } + + runDeallocationHooks(container); + + // Now let's clean all object's fields in this container. + traverseContainerObjectFields(container, [](ObjHeader** location) { + ZeroHeapRef(location); + }); + + // And release underlying memory. + if (isFreeable(container)) { + container->setColorEvenIfGreen(CONTAINER_TAG_GC_BLACK); + if (!container->buffered()) + scheduleDestroyContainer(memoryState, container); + } +} + +/** + * Do DFS cycle detection with three colors: + * - 'marked' bit as BLACK marker (object and its descendants processed) + * - 'seen' bit as GRAY marker (object is being processed) + * - not 'marked' and not 'seen' as WHITE marker (object is unprocessed) + * When we see GREY during DFS, it means we see cycle. + */ +void depthFirstTraversal(ContainerHeader* start, bool* hasCycles, + KRef* firstBlocker, KStdVector* order) { + ContainerHeaderDeque toVisit; + toVisit.push_back(start); + start->setSeen(); + + while (!toVisit.empty()) { + auto* container = toVisit.front(); + toVisit.pop_front(); + if (isMarkedAsRemoved(container)) { + container = clearRemoved(container); + // Mark BLACK. + container->resetSeen(); + container->mark(); + order->push_back(container); + continue; + } + toVisit.push_front(markAsRemoved(container)); + traverseContainerReferredObjects(container, [container, hasCycles, firstBlocker, &toVisit](ObjHeader* obj) { + if (*firstBlocker != nullptr) + return; + if (obj->has_meta_object() && ((obj->meta_object()->flags_ & MF_NEVER_FROZEN) != 0)) { + *firstBlocker = obj; + return; + } + ContainerHeader* objContainer = containerFor(obj); + if (canFreeze(objContainer)) { + // Marked GREY, there's cycle. + if (objContainer->seen()) *hasCycles = true; + + // Go deeper if WHITE. + if (!objContainer->seen() && !objContainer->marked()) { + // Mark GRAY. + objContainer->setSeen(); + // Here we do rather interesting trick: when doing DFS we postpone processing references going from + // FreezableAtomic, so that in 'order' referred value will be seen as not actually belonging + // to the same SCC (unless there are other edges not going through FreezableAtomic reaching the same value). + if (isFreezableAtomic(container)) { + toVisit.push_back(objContainer); + } else { + toVisit.push_front(objContainer); + } + } + } + }); + } +} + +void traverseStronglyConnectedComponent(ContainerHeader* start, + KStdUnorderedMap> const* reversedEdges, + KStdVector* component) { + ContainerHeaderDeque toVisit; + toVisit.push_back(start); + start->mark(); + + while (!toVisit.empty()) { + auto* container = toVisit.front(); + toVisit.pop_front(); + component->push_back(container); + auto it = reversedEdges->find(container); + RuntimeAssert(it != reversedEdges->end(), "unknown node during condensation building"); + for (auto* nextContainer : it->second) { + if (!nextContainer->marked()) { + nextContainer->mark(); + toVisit.push_front(nextContainer); + } + } + } +} + +template +inline bool tryIncrementRC(ContainerHeader* container) { + return container->tryIncRefCount(); +} + +#if !USE_GC + +template +inline void incrementRC(ContainerHeader* container) { + container->incRefCount(); +} + +template +inline void decrementRC(ContainerHeader* container) { + if (container->decRefCount() == 0) { + freeContainer(container); + } +} + +inline void decrementRC(ContainerHeader* container) { + if (isShareable(container)) + decrementRC(container); + else + decrementRC(container); +} + +template +inline void enqueueDecrementRC(ContainerHeader* container) { + RuntimeCheck(false, "Not yet implemeneted"); +} + +#else // USE_GC + +template +inline void incrementRC(ContainerHeader* container) { + container->incRefCount(); +} + +template +inline void decrementRC(ContainerHeader* container) { + // TODO: enable me, once account for inner references in frozen objects correctly. + // RuntimeAssert(container->refCount() > 0, "Must be positive"); + if (container->decRefCount() == 0) { + freeContainer(container); + } else if (UseCycleCollector) { // Possible root. + RuntimeAssert(container->refCount() > 0, "Must be positive"); + RuntimeAssert(!Atomic && !container->shareable(), "Cycle collector shalln't be used with shared objects yet"); + RuntimeAssert(container->objectCount() == 1, "cycle collector shall only work with single object containers"); + // We do not use cycle collector for frozen objects, as we already detected + // possible cycles during freezing. + // Also do not use cycle collector for provable acyclic objects. + int color = container->color(); + if (color != CONTAINER_TAG_GC_PURPLE && color != CONTAINER_TAG_GC_GREEN) { + container->setColorAssertIfGreen(CONTAINER_TAG_GC_PURPLE); + if (!container->buffered()) { + auto* state = memoryState; + container->setBuffered(); + if (state->toFree != nullptr) { + state->toFree->push_back(container); + MEMORY_LOG("toFree is now %d\n", state->toFree->size()) + if (state->gcSuspendCount == 0 && state->toRelease->size() >= state->gcThreshold) { + GC_LOG("Calling GC from DecrementRC: %d\n", state->toRelease->size()) + garbageCollect(state, false); + } + } + } + } + } +} + +inline void decrementRC(ContainerHeader* container) { + auto* state = memoryState; + RuntimeAssert(!IsStrictMemoryModel || state->gcInProgress, "Must only be called during GC"); + // TODO: enable me, once account for inner references in frozen objects correctly. + // RuntimeAssert(container->refCount() > 0, "Must be positive"); + bool useCycleCollector = container->local(); + if (container->decRefCount() == 0) { + freeContainer(container); + } else if (useCycleCollector && state->toFree != nullptr) { + RuntimeAssert(IsStrictMemoryModel, "No cycle collector in relaxed mode yet"); + RuntimeAssert(container->refCount() > 0, "Must be positive"); + RuntimeAssert(!container->shareable(), "Cycle collector shalln't be used with shared objects yet"); + RuntimeAssert(container->objectCount() == 1, "cycle collector shall only work with single object containers"); + // We do not use cycle collector for frozen objects, as we already detected + // possible cycles during freezing. + // Also do not use cycle collector for provable acyclic objects. + int color = container->color(); + if (color != CONTAINER_TAG_GC_PURPLE && color != CONTAINER_TAG_GC_GREEN) { + container->setColorAssertIfGreen(CONTAINER_TAG_GC_PURPLE); + if (!container->buffered()) { + container->setBuffered(); + state->toFree->push_back(container); + } + } + } +} + +template +inline void enqueueDecrementRC(ContainerHeader* container) { + auto* state = memoryState; + if (CanCollect) { + if (state->toRelease->size() >= state->gcThreshold && state->gcSuspendCount == 0) { + GC_LOG("Calling GC from EnqueueDecrementRC: %d\n", state->toRelease->size()) + garbageCollect(state, false); + } + } + state->toRelease->push_back(container); +} + +inline void initGcThreshold(MemoryState* state, uint32_t gcThreshold) { + state->gcThreshold = gcThreshold; + state->toRelease->reserve(gcThreshold); +} + +inline void initGcCollectCyclesThreshold(MemoryState* state, uint64_t gcCollectCyclesThreshold) { + state->gcCollectCyclesThreshold = gcCollectCyclesThreshold; + state->toFree->reserve(gcCollectCyclesThreshold); +} + +inline void increaseGcThreshold(MemoryState* state) { + auto newThreshold = state->gcThreshold * 3 / 2 + 1; + if (newThreshold <= kMaxErgonomicThreshold) { + initGcThreshold(state, newThreshold); + } +} + +inline void increaseGcCollectCyclesThreshold(MemoryState* state) { + auto newThreshold = state->gcCollectCyclesThreshold * 2; + if (newThreshold <= kMaxErgonomicToFreeSizeThreshold) { + initGcCollectCyclesThreshold(state, newThreshold); + } +} + +#endif // USE_GC + +#if TRACE_MEMORY && USE_GC + +const char* colorNames[] = {"BLACK", "GRAY", "WHITE", "PURPLE", "GREEN", "ORANGE", "RED"}; + +void dumpObject(ObjHeader* ref, int indent) { + for (int i = 0; i < indent; i++) MEMORY_LOG(" "); + auto* typeInfo = ref->type_info(); + auto* packageName = + typeInfo->packageName_ != nullptr ? CreateCStringFromString(typeInfo->packageName_) : nullptr; + auto* relativeName = + typeInfo->relativeName_ != nullptr ? CreateCStringFromString(typeInfo->relativeName_) : nullptr; + MEMORY_LOG("%p %s.%s\n", ref, + packageName ? packageName : "", relativeName ? relativeName : ""); + if (packageName) konan::free(packageName); + if (relativeName) konan::free(relativeName); +} + +void dumpContainerContent(ContainerHeader* container) { + if (container->refCount() < 0) { + MEMORY_LOG("%p has negative RC %d, likely a memory bug\n", container, container->refCount()) + return; + } + if (isAggregatingFrozenContainer(container)) { + MEMORY_LOG("%s aggregating container %p with %d objects rc=%d\n", + colorNames[container->color()], container, container->objectCount(), container->refCount()); + ContainerHeader** subContainer = reinterpret_cast(container + 1); + for (int i = 0; i < container->objectCount(); ++i) { + ContainerHeader* sub = *subContainer++; + MEMORY_LOG(" container %p\n ", sub); + dumpContainerContent(sub); + } + } else { + MEMORY_LOG("%s regular %s%scontainer %p with %d objects rc=%d\n", + colorNames[container->color()], + container->frozen() ? "frozen " : "", + container->stack() ? "stack " : "", + container, container->objectCount(), + container->refCount()); + ObjHeader* obj = reinterpret_cast(container + 1); + dumpObject(obj, 4); + } +} + +void dumpWorker(const char* prefix, ContainerHeader* header, ContainerHeaderSet* seen) { + dumpContainerContent(header); + seen->insert(header); + if (!isAggregatingFrozenContainer(header)) { + traverseContainerReferredObjects(header, [prefix, seen](ObjHeader* ref) { + auto* child = containerFor(ref); + RuntimeAssert(!isArena(child), "A reference to local object is encountered"); + if (child != nullptr && (seen->count(child) == 0)) { + dumpWorker(prefix, child, seen); + } + }); + } +} + +void dumpReachable(const char* prefix, const ContainerHeaderSet* roots) { + ContainerHeaderSet seen; + for (auto* container : *roots) { + dumpWorker(prefix, container, &seen); + } +} + +#endif + +#if USE_GC + +void markRoots(MemoryState*); +void scanRoots(MemoryState*); +void collectRoots(MemoryState*); +void scan(ContainerHeader* container); + +template +void markGray(ContainerHeader* start) { + ContainerHeaderDeque toVisit; + toVisit.push_front(start); + + while (!toVisit.empty()) { + auto* container = toVisit.front(); + MEMORY_LOG("MarkGray visit %p [%s]\n", container, colorNames[container->color()]); + toVisit.pop_front(); + if (useColor) { + int color = container->color(); + if (color == CONTAINER_TAG_GC_GRAY) continue; + // If see an acyclic object not being garbage - ignore it. We must properly traverse garbage, although. + if (color == CONTAINER_TAG_GC_GREEN && container->refCount() != 0) { + continue; + } + // Only garbage green object could be recolored here. + container->setColorEvenIfGreen(CONTAINER_TAG_GC_GRAY); + } else { + if (container->marked()) continue; + container->mark(); + } + + traverseContainerReferredObjects(container, [&toVisit](ObjHeader* ref) { + auto* childContainer = containerFor(ref); + RuntimeAssert(!isArena(childContainer), "A reference to local object is encountered"); + if (!isShareable(childContainer)) { + childContainer->decRefCount(); + toVisit.push_front(childContainer); + } + }); + } +} + +template +void scanBlack(ContainerHeader* start) { + ContainerHeaderDeque toVisit; + toVisit.push_front(start); + while (!toVisit.empty()) { + auto* container = toVisit.front(); + MEMORY_LOG("ScanBlack visit %p [%s]\n", container, colorNames[container->color()]); + toVisit.pop_front(); + if (useColor) { + auto color = container->color(); + if (color == CONTAINER_TAG_GC_GREEN || color == CONTAINER_TAG_GC_BLACK) continue; + container->setColorAssertIfGreen(CONTAINER_TAG_GC_BLACK); + } else { + if (!container->marked()) continue; + container->unMark(); + } + traverseContainerReferredObjects(container, [&toVisit](ObjHeader* ref) { + auto childContainer = containerFor(ref); + RuntimeAssert(!isArena(childContainer), "A reference to local object is encountered"); + if (!isShareable(childContainer)) { + childContainer->incRefCount(); + if (useColor) { + int color = childContainer->color(); + if (color != CONTAINER_TAG_GC_BLACK) + toVisit.push_front(childContainer); + } else { + if (childContainer->marked()) + toVisit.push_front(childContainer); + } + } + }); + } +} + +void collectWhite(MemoryState*, ContainerHeader* container); + +void collectCycles(MemoryState* state) { + markRoots(state); + scanRoots(state); + collectRoots(state); + state->toFree->clear(); + state->roots->clear(); +} + +void markRoots(MemoryState* state) { + for (auto container : *(state->toFree)) { + if (isMarkedAsRemoved(container)) + continue; + // Acyclic containers cannot be in this list. + RuntimeCheck(container->color() != CONTAINER_TAG_GC_GREEN, "Must not be green"); + auto color = container->color(); + auto rcIsZero = container->refCount() == 0; + if (color == CONTAINER_TAG_GC_PURPLE && !rcIsZero) { + markGray(container); + state->roots->push_back(container); + } else { + container->resetBuffered(); + RuntimeAssert(color != CONTAINER_TAG_GC_GREEN, "Must not be green"); + if (color == CONTAINER_TAG_GC_BLACK && rcIsZero) { + scheduleDestroyContainer(state, container); + } + } + } +} + +void scanRoots(MemoryState* state) { + for (auto* container : *(state->roots)) { + scan(container); + } +} + +void collectRoots(MemoryState* state) { + // Here we might free some objects and call deallocation hooks on them, + // which in turn might call DecrementRC and trigger new GC - forbid that. + state->gcSuspendCount++; + for (auto* container : *(state->roots)) { + container->resetBuffered(); + collectWhite(state, container); + } + state->gcSuspendCount--; +} + +void scan(ContainerHeader* start) { + ContainerHeaderDeque toVisit; + toVisit.push_front(start); + + while (!toVisit.empty()) { + auto* container = toVisit.front(); + toVisit.pop_front(); + if (container->color() != CONTAINER_TAG_GC_GRAY) continue; + if (container->refCount() != 0) { + scanBlack(container); + continue; + } + container->setColorAssertIfGreen(CONTAINER_TAG_GC_WHITE); + traverseContainerReferredObjects(container, [&toVisit](ObjHeader* ref) { + auto* childContainer = containerFor(ref); + RuntimeAssert(!isArena(childContainer), "A reference to local object is encountered"); + if (!isShareable(childContainer)) { + toVisit.push_front(childContainer); + } + }); + } +} + +void collectWhite(MemoryState* state, ContainerHeader* start) { + ContainerHeaderDeque toVisit; + toVisit.push_back(start); + + while (!toVisit.empty()) { + auto* container = toVisit.front(); + toVisit.pop_front(); + if (container->color() != CONTAINER_TAG_GC_WHITE || container->buffered()) continue; + container->setColorAssertIfGreen(CONTAINER_TAG_GC_BLACK); + traverseContainerObjectFields(container, [&toVisit](ObjHeader** location) { + auto* ref = *location; + if (ref == nullptr) return; + auto* childContainer = containerFor(ref); + RuntimeAssert(!isArena(childContainer), "A reference to local object is encountered"); + if (isShareable(childContainer)) { + ZeroHeapRef(location); + } else { + toVisit.push_front(childContainer); + } + }); + runDeallocationHooks(container); + scheduleDestroyContainer(state, container); + } +} +#endif + +inline bool needAtomicAccess(ContainerHeader* container) { + return container->shareable(); +} + +inline bool canBeCyclic(ContainerHeader* container) { + if (container->refCount() == 1) return false; + if (container->color() == CONTAINER_TAG_GC_GREEN) return false; + return true; +} + +inline void addHeapRef(ContainerHeader* container) { + MEMORY_LOG("AddHeapRef %p: rc=%d\n", container, container->refCount()) + UPDATE_ADDREF_STAT(memoryState, container, needAtomicAccess(container), 0) + switch (container->tag()) { + case CONTAINER_TAG_STACK: + break; + case CONTAINER_TAG_LOCAL: + RuntimeAssert(container->refCount() > 0, "add ref for reclaimed object"); + incrementRC(container); + break; + /* case CONTAINER_TAG_FROZEN: case CONTAINER_TAG_SHARED: */ + default: + RuntimeAssert(container->refCount() > 0, "add ref for reclaimed object"); + incrementRC(container); + break; + } +} + +inline void addHeapRef(const ObjHeader* header) { + auto* container = containerFor(header); + if (container != nullptr) + addHeapRef(const_cast(container)); +} + +inline bool tryAddHeapRef(ContainerHeader* container) { + switch (container->tag()) { + case CONTAINER_TAG_STACK: + break; + case CONTAINER_TAG_LOCAL: + if (!tryIncrementRC(container)) return false; + break; + /* case CONTAINER_TAG_FROZEN: case CONTAINER_TAG_SHARED: */ + default: + if (!tryIncrementRC(container)) return false; + break; + } + + MEMORY_LOG("AddHeapRef %p: rc=%d\n", container, container->refCount() - 1) + UPDATE_ADDREF_STAT(memoryState, container, needAtomicAccess(container), 0) + return true; +} + +inline bool tryAddHeapRef(const ObjHeader* header) { + auto* container = containerFor(header); + return (container != nullptr) ? tryAddHeapRef(container) : true; +} + +template +inline void releaseHeapRef(ContainerHeader* container) { + MEMORY_LOG("ReleaseHeapRef %p: rc=%d\n", container, container->refCount()) + UPDATE_RELEASEREF_STAT(memoryState, container, needAtomicAccess(container), canBeCyclic(container), 0) + if (container->tag() != CONTAINER_TAG_STACK) { + if (Strict) + enqueueDecrementRC(container); + else + decrementRC(container); + } +} + +template +inline void releaseHeapRef(const ObjHeader* header) { + auto* container = containerFor(header); + if (container != nullptr) + releaseHeapRef(const_cast(container)); +} + +// We use first slot as place to store frame-local arena container. +// TODO: create ArenaContainer object on the stack, so that we don't +// do two allocations per frame (ArenaContainer + actual container). +inline ArenaContainer* initedArena(ObjHeader** auxSlot) { + auto frame = asFrameOverlay(auxSlot); + auto arena = reinterpret_cast(frame->arena); + if (!arena) { + arena = konanConstructInstance(); + MEMORY_LOG("Initializing arena in %p\n", frame) + arena->Init(); + frame->arena = arena; + } + return arena; +} + +inline size_t containerSize(const ContainerHeader* container) { + size_t result = 0; + const ObjHeader* obj = reinterpret_cast(container + 1); + for (uint32_t object = 0; object < container->objectCount(); object++) { + size_t size = objectSize(obj); + result += size; + obj = reinterpret_cast(reinterpret_cast(obj) + size); + } + return result; +} + +#if USE_GC +void incrementStack(MemoryState* state) { + FrameOverlay* frame = currentFrame; + while (frame != nullptr) { + ObjHeader** current = reinterpret_cast(frame + 1) + frame->parameters; + ObjHeader** end = current + frame->count - kFrameOverlaySlots - frame->parameters; + while (current < end) { + ObjHeader* obj = *current++; + if (obj != nullptr) { + auto* container = containerFor(obj); + if (container == nullptr) continue; + if (container->shareable()) { + incrementRC(container); + } else { + incrementRC(container); + } + } + } + frame = frame->previous; + } +} + +void processDecrements(MemoryState* state) { + RuntimeAssert(IsStrictMemoryModel, "Only works in strict model now"); + auto* toRelease = state->toRelease; + state->gcSuspendCount++; + while (toRelease->size() > 0) { + auto* container = toRelease->back(); + toRelease->pop_back(); + if (isMarkedAsRemoved(container)) + continue; + if (container->shareable()) + container = realShareableContainer(container); + decrementRC(container); + } + + state->foreignRefManager->processEnqueuedReleaseRefsWith([](ObjHeader* obj) { + ContainerHeader* container = containerFor(obj); + if (container != nullptr) decrementRC(container); + }); + state->gcSuspendCount--; +} + +void decrementStack(MemoryState* state) { + RuntimeAssert(IsStrictMemoryModel, "Only works in strict model now"); + state->gcSuspendCount++; + FrameOverlay* frame = currentFrame; + while (frame != nullptr) { + ObjHeader** current = reinterpret_cast(frame + 1) + frame->parameters; + ObjHeader** end = current + frame->count - kFrameOverlaySlots - frame->parameters; + while (current < end) { + ObjHeader* obj = *current++; + if (obj != nullptr) { + MEMORY_LOG("decrement stack %p\n", obj) + auto* container = containerFor(obj); + if (container != nullptr) + enqueueDecrementRC(container); + } + } + frame = frame->previous; + } + state->gcSuspendCount--; +} + +void garbageCollect(MemoryState* state, bool force) { + RuntimeAssert(!state->gcInProgress, "Recursive GC is disallowed"); + +#if TRACE_GC + uint64_t allocSinceLastGc = state->allocSinceLastGc; +#endif // TRACE_GC + state->allocSinceLastGc = 0; + + if (!IsStrictMemoryModel) { + // In relaxed model we just process finalizer queue and be done with it. + processFinalizerQueue(state); + return; + } + + GC_LOG(">>> %s GC: threshold = %d toFree %d toRelease %d alloc = %lld\n", \ + force ? "forced" : "regular", state->gcThreshold, state->toFree->size(), + state->toRelease->size(), allocSinceLastGc) + + auto gcStartTime = konan::getTimeMicros(); + + state->gcInProgress = true; + state->gcEpoque++; + + incrementStack(state); +#if USE_CYCLIC_GC + // Block if the concurrent cycle collector is running. + // We must do that to ensure collector sees state where actual RC properly upper estimated. + if (g_hasCyclicCollector) + cyclicLocalGC(); +#endif // USE_CYCLIC_GC +#if PROFILE_GC + auto processDecrementsStartTime = konan::getTimeMicros(); +#endif + processDecrements(state); +#if PROFILE_GC + auto processDecrementsDuration = konan::getTimeMicros() - processDecrementsStartTime; + GC_LOG("||| GC: processDecrementsDuration = %lld\n", processDecrementsDuration); + auto decrementStackStartTime = konan::getTimeMicros(); +#endif + size_t beforeDecrements = state->toRelease->size(); + decrementStack(state); + size_t afterDecrements = state->toRelease->size(); +#if PROFILE_GC + auto decrementStackDuration = konan::getTimeMicros() - decrementStackStartTime; + GC_LOG("||| GC: decrementStackDuration = %lld\n", decrementStackDuration); +#endif + RuntimeAssert(afterDecrements >= beforeDecrements, "toRelease size must not have decreased"); + size_t stackReferences = afterDecrements - beforeDecrements; + if (state->gcErgonomics && stackReferences * 5 > state->gcThreshold) { + increaseGcThreshold(state); + GC_LOG("||| GC: too many stack references, increased threshold to %d\n", state->gcThreshold); + } + + GC_LOG("||| GC: toFree %d toRelease %d\n", state->toFree->size(), state->toRelease->size()) +#if PROFILE_GC + auto processFinalizerQueueStartTime = konan::getTimeMicros(); +#endif + processFinalizerQueue(state); +#if PROFILE_GC + auto processFinalizerQueueDuration = konan::getTimeMicros() - processFinalizerQueueStartTime; + GC_LOG("||| GC: processFinalizerQueueDuration %lld\n", processFinalizerQueueDuration); +#endif + + if (force || state->toFree->size() > state->gcCollectCyclesThreshold) { + auto cyclicGcStartTime = konan::getTimeMicros(); + while (state->toFree->size() > 0) { + collectCycles(state); + #if PROFILE_GC + processFinalizerQueueStartTime = konan::getTimeMicros(); + #endif + processFinalizerQueue(state); + #if PROFILE_GC + processFinalizerQueueDuration += konan::getTimeMicros() - processFinalizerQueueStartTime; + GC_LOG("||| GC: processFinalizerQueueDuration = %lld\n", processFinalizerQueueDuration); + #endif + } + auto cyclicGcEndTime = konan::getTimeMicros(); + #if PROFILE_GC + GC_LOG("||| GC: collectCyclesDuration = %lld\n", cyclicGcEndTime - cyclicGcStartTime); + #endif + auto cyclicGcDuration = cyclicGcEndTime - cyclicGcStartTime; + if (!force && state->gcErgonomics && cyclicGcDuration > kGcCollectCyclesMinimumDuration && + double(cyclicGcDuration) / (cyclicGcStartTime - state->lastCyclicGcTimestamp + 1) > kGcCollectCyclesLoadRatio) { + increaseGcCollectCyclesThreshold(state); + GC_LOG("Adjusting GC collecting cycles threshold to %lld\n", state->gcCollectCyclesThreshold); + } + state->lastCyclicGcTimestamp = cyclicGcEndTime; + } + + state->gcInProgress = false; + auto gcEndTime = konan::getTimeMicros(); + + if (state->gcErgonomics) { + auto gcToComputeRatio = double(gcEndTime - gcStartTime) / (gcStartTime - state->lastGcTimestamp + 1); + if (!force && gcToComputeRatio > kGcToComputeRatioThreshold) { + increaseGcThreshold(state); + GC_LOG("Adjusting GC threshold to %d\n", state->gcThreshold); + } + } + GC_LOG("GC: gcToComputeRatio=%f duration=%lld sinceLast=%lld\n", double(gcEndTime - gcStartTime) / (gcStartTime - state->lastGcTimestamp + 1), (gcEndTime - gcStartTime), gcStartTime - state->lastGcTimestamp); + state->lastGcTimestamp = gcEndTime; + +#if TRACE_MEMORY + for (auto* obj: *state->toRelease) { + MEMORY_LOG("toRelease %p\n", obj) + } +#endif + + GC_LOG("<<< GC: toFree %d toRelease %d\n", state->toFree->size(), state->toRelease->size()) +} + +void rememberNewContainer(ContainerHeader* container) { + if (container == nullptr) return; + // Instances can be allocated before actual runtime init - be prepared for that. + if (memoryState != nullptr) { + incrementRC(container); + // We cannot collect until reference will be stored into the stack slot. + enqueueDecrementRC(container); + } +} + +void garbageCollect() { + garbageCollect(memoryState, true); +} + +#endif // USE_GC + +ForeignRefManager* initLocalForeignRef(ObjHeader* object) { + if (!IsStrictMemoryModel) return nullptr; + + return memoryState->foreignRefManager; +} + +ForeignRefManager* initForeignRef(ObjHeader* object) { + addHeapRef(object); + + if (!IsStrictMemoryModel) return nullptr; + + // Note: it is possible to return nullptr for shared object as an optimization, + // but this will force the implementation to release objects on uninitialized threads + // which is generally a memory leak. See [deinitForeignRef]. + auto* manager = memoryState->foreignRefManager; + manager->addRef(); + return manager; +} + +bool isForeignRefAccessible(ObjHeader* object, ForeignRefManager* manager) { + if (!IsStrictMemoryModel) return true; + + if (manager == memoryState->foreignRefManager) { + // Note: it is important that this code neither crashes nor returns false-negative result + // (although may produce false-positive one) if [manager] is a dangling pointer. + // See BackRefFromAssociatedObject::releaseRef for more details. + return true; + } + + // Note: getting container and checking it with 'isShareable()' is supposed to be correct even for unowned object. + return isShareable(containerFor(object)); +} + +void deinitForeignRef(ObjHeader* object, ForeignRefManager* manager) { + if (IsStrictMemoryModel) { + if (memoryState != nullptr && isForeignRefAccessible(object, manager)) { + releaseHeapRef(object); + } else { + // Prefer this for (memoryState == nullptr) since otherwise the object may leak: + // an uninitialized thread did not run any Kotlin code; + // it may be an externally-managed thread which is not supposed to run Kotlin code + // and not going to exit soon. + manager->enqueueReleaseRef(object); + } + + manager->releaseRef(); + } else { + releaseHeapRef(object); + RuntimeAssert(manager == nullptr, "must be null"); + } +} + +MemoryState* initMemory() { + RuntimeAssert(offsetof(ArrayHeader, typeInfoOrMeta_) + == + offsetof(ObjHeader, typeInfoOrMeta_), + "Layout mismatch"); + RuntimeAssert(offsetof(TypeInfo, typeInfo_) + == + offsetof(MetaObjHeader, typeInfo_), + "Layout mismatch"); + RuntimeAssert(sizeof(FrameOverlay) % sizeof(ObjHeader**) == 0, "Frame overlay should contain only pointers") + RuntimeAssert(memoryState == nullptr, "memory state must be clear"); + memoryState = konanConstructInstance(); + INIT_EVENT(memoryState) +#if USE_GC + memoryState->toFree = konanConstructInstance(); + memoryState->roots = konanConstructInstance(); + memoryState->gcInProgress = false; + memoryState->gcSuspendCount = 0; + memoryState->toRelease = konanConstructInstance(); + initGcThreshold(memoryState, kGcThreshold); + initGcCollectCyclesThreshold(memoryState, kMaxToFreeSizeThreshold); + memoryState->allocSinceLastGcThreshold = kMaxGcAllocThreshold; + memoryState->gcErgonomics = true; +#endif + memoryState->tlsMap = konanConstructInstance(); + memoryState->foreignRefManager = ForeignRefManager::create(); + bool firstMemoryState = atomicAdd(&aliveMemoryStatesCount, 1) == 1; + if (firstMemoryState) { +#if USE_CYCLIC_GC + cyclicInit(); +#endif // USE_CYCLIC_GC + } + return memoryState; +} + +void deinitMemory(MemoryState* memoryState) { + static int pendingDeinit = 0; + atomicAdd(&pendingDeinit, 1); +#if USE_GC + bool lastMemoryState = atomicAdd(&aliveMemoryStatesCount, -1) == 0; + bool checkLeaks = Kotlin_memoryLeakCheckerEnabled() && lastMemoryState; + if (lastMemoryState) { + garbageCollect(memoryState, true); +#if USE_CYCLIC_GC + // If there are other pending deinits (rare situation) - just skip the leak checker. + // This may happen when there're several threads with Kotlin runtimes created + // by foreign code, and that code stops those threads simultaneously. + if (atomicGet(&pendingDeinit) > 1) { + checkLeaks = false; + } + cyclicDeinit(g_hasCyclicCollector); +#endif // USE_CYCLIC_GC + } + // Actual GC only implemented in strict memory model at the moment. + do { + GC_LOG("Calling garbageCollect from DeinitMemory()\n") + garbageCollect(memoryState, true); + } while (memoryState->toRelease->size() > 0 || !memoryState->foreignRefManager->tryReleaseRefOwned()); + RuntimeAssert(memoryState->toFree->size() == 0, "Some memory have not been released after GC"); + RuntimeAssert(memoryState->toRelease->size() == 0, "Some memory have not been released after GC"); + konanDestructInstance(memoryState->toFree); + konanDestructInstance(memoryState->roots); + konanDestructInstance(memoryState->toRelease); + RuntimeAssert(memoryState->tlsMap->size() == 0, "Must be already cleared"); + konanDestructInstance(memoryState->tlsMap); + RuntimeAssert(memoryState->finalizerQueue == nullptr, "Finalizer queue must be empty"); + RuntimeAssert(memoryState->finalizerQueueSize == 0, "Finalizer queue must be empty"); +#endif // USE_GC + + atomicAdd(&pendingDeinit, -1); + +#if TRACE_MEMORY + if (IsStrictMemoryModel && lastMemoryState && allocCount > 0) { + MEMORY_LOG("*** Memory leaks, leaked %d containers ***\n", allocCount); + dumpReachable("", memoryState->containers); + } +#else +#if USE_GC + if (IsStrictMemoryModel && allocCount > 0 && checkLeaks) { + konan::consoleErrorf( + "Memory leaks detected, %d objects leaked!\n" + "Use `Platform.isMemoryLeakCheckerActive = false` to avoid this check.\n", allocCount); + konan::consoleFlush(); + konan::abort(); + } +#endif // USE_GC +#endif // TRACE_MEMORY + + PRINT_EVENT(memoryState) + DEINIT_EVENT(memoryState) + + konanFreeMemory(memoryState); + ::memoryState = nullptr; +} + +void makeShareable(ContainerHeader* container) { + if (!container->frozen()) + container->makeShared(); +} + +template +void setStackRef(ObjHeader** location, const ObjHeader* object) { + MEMORY_LOG("SetStackRef *%p: %p\n", location, object) + UPDATE_REF_EVENT(memoryState, nullptr, object, location, 1); + if (!Strict && object != nullptr) + addHeapRef(object); + *const_cast(location) = object; +} + +template +void setHeapRef(ObjHeader** location, const ObjHeader* object) { + MEMORY_LOG("SetHeapRef *%p: %p\n", location, object) + UPDATE_REF_EVENT(memoryState, nullptr, object, location, 0); + if (object != nullptr) + addHeapRef(const_cast(object)); + *const_cast(location) = object; +} + +void zeroHeapRef(ObjHeader** location) { + MEMORY_LOG("ZeroHeapRef %p\n", location) + auto* value = *location; + if (reinterpret_cast(value) > 1) { + UPDATE_REF_EVENT(memoryState, value, nullptr, location, 0); + *location = nullptr; + ReleaseHeapRef(value); + } +} + +template +void zeroStackRef(ObjHeader** location) { + MEMORY_LOG("ZeroStackRef %p\n", location) + if (Strict) { + *location = nullptr; + } else { + auto* old = *location; + *location = nullptr; + if (old != nullptr) releaseHeapRef(old); + } +} + +template +void updateHeapRef(ObjHeader** location, const ObjHeader* object) { + UPDATE_REF_EVENT(memoryState, *location, object, location, 0); + ObjHeader* old = *location; + if (old != object) { + if (object != nullptr) { + addHeapRef(object); + } + *const_cast(location) = object; + if (reinterpret_cast(old) > 1) { + releaseHeapRef(old); + } + } +} + +template +void updateStackRef(ObjHeader** location, const ObjHeader* object) { + UPDATE_REF_EVENT(memoryState, *location, object, location, 1) + RuntimeAssert(object != reinterpret_cast(1), "Markers disallowed here"); + if (Strict) { + *const_cast(location) = object; + } else { + ObjHeader* old = *location; + if (old != object) { + if (object != nullptr) { + addHeapRef(object); + } + *const_cast(location) = object; + if (old != nullptr) { + releaseHeapRef(old); + } + } + } +} + +template +void updateReturnRef(ObjHeader** returnSlot, const ObjHeader* value) { + updateStackRef(returnSlot, value); +} + +void updateHeapRefIfNull(ObjHeader** location, const ObjHeader* object) { + if (object != nullptr) { +#if KONAN_NO_THREADS + ObjHeader* old = *location; + if (old == nullptr) { + addHeapRef(const_cast(object)); + *const_cast(location) = object; + } +#else + addHeapRef(const_cast(object)); + auto old = __sync_val_compare_and_swap(location, nullptr, const_cast(object)); + if (old != nullptr) { + // Failed to store, was not null. + ReleaseHeapRef(const_cast(object)); + } +#endif + UPDATE_REF_EVENT(memoryState, old, object, location, 0); + } +} + +inline void checkIfGcNeeded(MemoryState* state) { + if (state != nullptr && state->allocSinceLastGc > state->allocSinceLastGcThreshold && state->gcSuspendCount == 0) { + // To avoid GC trashing check that at least 10ms passed since last GC. + if (konan::getTimeMicros() - state->lastGcTimestamp > 10 * 1000) { + GC_LOG("Calling GC from checkIfGcNeeded: %d\n", state->toRelease->size()) + garbageCollect(state, false); + } + } +} + +inline void checkIfForceCyclicGcNeeded(MemoryState* state) { + if (state != nullptr && state->toFree != nullptr && state->toFree->size() > kMaxToFreeSizeThreshold + && state->gcSuspendCount == 0) { + // To avoid GC trashing check that at least 10ms passed since last GC. + if (konan::getTimeMicros() - state->lastGcTimestamp > 10 * 1000) { + GC_LOG("Calling GC from checkIfForceCyclicGcNeeded: %d\n", state->toFree->size()) + garbageCollect(state, true); + } + } +} + +template +OBJ_GETTER(allocInstance, const TypeInfo* type_info) { + RuntimeAssert(type_info->instanceSize_ >= 0, "must be an object"); + auto* state = memoryState; +#if USE_GC + checkIfGcNeeded(state); +#endif // USE_GC + auto container = ObjectContainer(state, type_info); + ObjHeader* obj = container.GetPlace(); +#if USE_GC + if (Strict) { + rememberNewContainer(container.header()); + } else { + makeShareable(container.header()); + } +#endif // USE_GC +#if USE_CYCLE_DETECTOR + CycleDetector::insertCandidateIfNeeded(obj); +#endif // USE_CYCLE_DETECTOR +#if USE_CYCLIC_GC + if ((obj->type_info()->flags_ & TF_LEAK_DETECTOR_CANDIDATE) != 0) { + // Note: this should be performed after [rememberNewContainer] (above). + // Otherwise cyclic collector can observe this atomic root with RC = 0, + // thus consider it garbage and then zero it after initialization. + cyclicAddAtomicRoot(obj); + } +#endif // USE_CYCLIC_GC + RETURN_OBJ(obj); +} + +template +OBJ_GETTER(allocArrayInstance, const TypeInfo* type_info, int32_t elements) { + RuntimeAssert(type_info->instanceSize_ < 0, "must be an array"); + if (elements < 0) ThrowIllegalArgumentException(); + auto* state = memoryState; +#if USE_GC + checkIfGcNeeded(state); +#endif // USE_GC + auto container = ArrayContainer(state, type_info, elements); +#if USE_GC + if (Strict) { + rememberNewContainer(container.header()); + } else { + makeShareable(container.header()); + } +#endif // USE_GC + RETURN_OBJ(container.GetPlace()->obj()); +} + +template +OBJ_GETTER(initInstance, + ObjHeader** location, const TypeInfo* typeInfo, void (*ctor)(ObjHeader*)) { + ObjHeader* value = *location; + if (value != nullptr) { + // OK'ish, inited by someone else. + RETURN_OBJ(value); + } + ObjHeader* object = allocInstance(typeInfo, OBJ_RESULT); + updateHeapRef(location, object); +#if KONAN_NO_EXCEPTIONS + ctor(object); + return object; +#else + try { + ctor(object); + return object; + } catch (...) { + UpdateReturnRef(OBJ_RESULT, nullptr); + ZeroHeapRef(location); + throw; + } +#endif +} + +template +OBJ_GETTER(initSharedInstance, + ObjHeader** location, const TypeInfo* typeInfo, void (*ctor)(ObjHeader*)) { +#if KONAN_NO_THREADS + ObjHeader* value = *location; + if (value != nullptr) { + // OK'ish, inited by someone else. + RETURN_OBJ(value); + } + ObjHeader* object = AllocInstance(typeInfo, OBJ_RESULT); + UpdateHeapRef(location, object); +#if KONAN_NO_EXCEPTIONS + ctor(object); + FreezeSubgraph(object); + return object; +#else + try { + ctor(object); + if (Strict) + FreezeSubgraph(object); + return object; + } catch (...) { + UpdateReturnRef(OBJ_RESULT, nullptr); + ZeroHeapRef(location); + throw; + } +#endif // KONAN_NO_EXCEPTIONS +#else // KONAN_NO_THREADS + // Search from the top of the stack. + for (auto it = memoryState->initializingSingletons.rbegin(); it != memoryState->initializingSingletons.rend(); ++it) { + if (it->first == location) { + RETURN_OBJ(it->second); + } + } + + ObjHeader* initializing = reinterpret_cast(1); + + // Spin lock. + ObjHeader* value = nullptr; + while ((value = __sync_val_compare_and_swap(location, nullptr, initializing)) == initializing); + if (value != nullptr) { + // OK'ish, inited by someone else. + RETURN_OBJ(value); + } + ObjHeader* object = AllocInstance(typeInfo, OBJ_RESULT); + memoryState->initializingSingletons.push_back(std::make_pair(location, object)); +#if KONAN_NO_EXCEPTIONS + ctor(object); + if (Strict) + FreezeSubgraph(object); + UpdateHeapRef(location, object); + synchronize(); + memoryState->initializingSingletons.pop_back(); + return object; +#else // KONAN_NO_EXCEPTIONS + try { + ctor(object); + if (Strict) + FreezeSubgraph(object); + UpdateHeapRef(location, object); + synchronize(); + memoryState->initializingSingletons.pop_back(); + return object; + } catch (...) { + UpdateReturnRef(OBJ_RESULT, nullptr); + zeroHeapRef(location); + memoryState->initializingSingletons.pop_back(); + synchronize(); + throw; + } +#endif // KONAN_NO_EXCEPTIONS +#endif // KONAN_NO_THREADS +} + +/** + * We keep thread affinity and reference value based cookie in the atomic references, so that + * repeating read operation of the same value do not lead to the repeating rememberNewContainer() operation. + * We must invalidate cookie after the local GC, as otherwise fact that container of the `value` is retained + * may change, if the last reference to the value read is lost during GC and we re-read same value from + * the same atomic reference. Thus we also include GC epoque into the cookie. + */ +inline int32_t computeCookie() { + auto* state = memoryState; + auto epoque = state->gcEpoque; + return (static_cast(reinterpret_cast(state))) ^ static_cast(epoque); +} + +OBJ_GETTER(swapHeapRefLocked, + ObjHeader** location, ObjHeader* expectedValue, ObjHeader* newValue, int32_t* spinlock, int32_t* cookie) { + lock(spinlock); + ObjHeader* oldValue = *location; + bool shallRemember = false; + if (IsStrictMemoryModel) { + auto realCookie = computeCookie(); + shallRemember = *cookie != realCookie; + if (shallRemember) *cookie = realCookie; + } + if (oldValue == expectedValue) { +#if USE_CYCLIC_GC + if (g_hasCyclicCollector) + cyclicMutateAtomicRoot(newValue); +#endif // USE_CYCLIC_GC + SetHeapRef(location, newValue); + } + UpdateReturnRef(OBJ_RESULT, oldValue); + + if (IsStrictMemoryModel && shallRemember && oldValue != nullptr && oldValue != expectedValue) { + // Only remember container if it is not known to this thread (i.e. != expectedValue). + rememberNewContainer(containerFor(oldValue)); + } + unlock(spinlock); + + if (oldValue != nullptr && oldValue == expectedValue) { + ReleaseHeapRef(oldValue); + } + return oldValue; +} + +void setHeapRefLocked(ObjHeader** location, ObjHeader* newValue, int32_t* spinlock, int32_t* cookie) { + lock(spinlock); + ObjHeader* oldValue = *location; +#if USE_CYCLIC_GC + if (g_hasCyclicCollector) + cyclicMutateAtomicRoot(newValue); +#endif // USE_CYCLIC_GC + // We do not use UpdateRef() here to avoid having ReleaseRef() on old value under the lock. + SetHeapRef(location, newValue); + *cookie = computeCookie(); + unlock(spinlock); + if (oldValue != nullptr) + ReleaseHeapRef(oldValue); +} + +OBJ_GETTER(readHeapRefLocked, ObjHeader** location, int32_t* spinlock, int32_t* cookie) { + MEMORY_LOG("ReadHeapRefLocked: %p\n", location) + lock(spinlock); + ObjHeader* value = *location; + auto realCookie = computeCookie(); + bool shallRemember = *cookie != realCookie; + if (shallRemember) *cookie = realCookie; + UpdateReturnRef(OBJ_RESULT, value); +#if USE_GC + if (IsStrictMemoryModel && shallRemember && value != nullptr) { + auto* container = containerFor(value); + rememberNewContainer(container); + } +#endif // USE_GC + unlock(spinlock); + return value; +} + +OBJ_GETTER(readHeapRefNoLock, ObjHeader* object, KInt index) { + MEMORY_LOG("ReadHeapRefNoLock: %p index %d\n", object, index) + ObjHeader** location = reinterpret_cast( + reinterpret_cast(object) + object->type_info()->objOffsets_[index]); + ObjHeader* value = *location; +#if USE_GC + if (IsStrictMemoryModel && (value != nullptr)) { + // Maybe not so good to do that under lock. + rememberNewContainer(containerFor(value)); + } +#endif // USE_GC + RETURN_OBJ(value); +} + +template +void enterFrame(ObjHeader** start, int parameters, int count) { + MEMORY_LOG("EnterFrame %p: %d parameters %d locals\n", start, parameters, count) + FrameOverlay* frame = reinterpret_cast(start); + if (Strict) { + frame->previous = currentFrame; + currentFrame = frame; + // TODO: maybe compress in single value somehow. + frame->parameters = parameters; + frame->count = count; + } +} + +template +void leaveFrame(ObjHeader** start, int parameters, int count) { + MEMORY_LOG("LeaveFrame %p: %d parameters %d locals\n", start, parameters, count) + FrameOverlay* frame = reinterpret_cast(start); + if (Strict) { + currentFrame = frame->previous; + } else { + ObjHeader** current = start + parameters + kFrameOverlaySlots; + count -= parameters; + while (count-- > kFrameOverlaySlots) { + ObjHeader* object = *current; + if (object != nullptr) { + releaseHeapRef(object); + } + current++; + } + } +} + +void suspendGC() { + GC_LOG("suspendGC\n") + memoryState->gcSuspendCount++; +} + +void resumeGC() { + GC_LOG("resumeGC\n") + MemoryState* state = memoryState; + if (state->gcSuspendCount > 0) { + state->gcSuspendCount--; + if (state->toRelease != nullptr && + state->toRelease->size() >= state->gcThreshold && + state->gcSuspendCount == 0) { + + garbageCollect(state, false); + } + } +} + +void stopGC() { + GC_LOG("stopGC\n") + if (memoryState->toRelease != nullptr) { + memoryState->gcSuspendCount = 0; + garbageCollect(memoryState, true); + konanDestructInstance(memoryState->toRelease); + konanDestructInstance(memoryState->toFree); + konanDestructInstance(memoryState->roots); + memoryState->toRelease = nullptr; + memoryState->toFree = nullptr; + memoryState->roots = nullptr; + } +} + +void startGC() { + GC_LOG("startGC\n") + if (memoryState->toFree == nullptr) { + memoryState->toFree = konanConstructInstance(); + memoryState->toRelease = konanConstructInstance(); + memoryState->roots = konanConstructInstance(); + memoryState->gcSuspendCount = 0; + } +} + +void setGCThreshold(KInt value) { + GC_LOG("setGCThreshold %d\n", value) + if (value <= 0) { + ThrowIllegalArgumentException(); + } + initGcThreshold(memoryState, value); +} + +KInt getGCThreshold() { + GC_LOG("getGCThreshold\n") + return memoryState->gcThreshold; +} + +void setGCCollectCyclesThreshold(KLong value) { + GC_LOG("setGCCollectCyclesThreshold %d\n", value) + if (value <= 0) { + ThrowIllegalArgumentException(); + } + initGcCollectCyclesThreshold(memoryState, value); +} + +KInt getGCCollectCyclesThreshold() { + GC_LOG("getGCCollectCyclesThreshold\n") + return memoryState->gcCollectCyclesThreshold; +} + +void setGCThresholdAllocations(KLong value) { + GC_LOG("setGCThresholdAllocations %lld\n", value) + if (value <= 0) { + ThrowIllegalArgumentException(); + } + + memoryState->allocSinceLastGcThreshold = value; +} + +KLong getGCThresholdAllocations() { + GC_LOG("getGCThresholdAllocation\n") + return memoryState->allocSinceLastGcThreshold; +} + +void setTuneGCThreshold(KBoolean value) { + GC_LOG("setTuneGCThreshold %d\n", value) + memoryState->gcErgonomics = value; +} + +KBoolean getTuneGCThreshold() { + GC_LOG("getTuneGCThreshold %d\n") + return memoryState->gcErgonomics; +} + +KNativePtr createStablePointer(KRef any) { + if (any == nullptr) return nullptr; + MEMORY_LOG("CreateStablePointer for %p rc=%d\n", any, containerFor(any) ? containerFor(any)->refCount() : 0) + addHeapRef(any); + return reinterpret_cast(any); +} + +void disposeStablePointer(KNativePtr pointer) { + if (pointer == nullptr) return; + KRef ref = reinterpret_cast(pointer); + ReleaseHeapRef(ref); +} + +OBJ_GETTER(derefStablePointer, KNativePtr pointer) { + KRef ref = reinterpret_cast(pointer); + AdoptReferenceFromSharedVariable(ref); + RETURN_OBJ(ref); +} + +OBJ_GETTER(adoptStablePointer, KNativePtr pointer) { + synchronize(); + KRef ref = reinterpret_cast(pointer); + MEMORY_LOG("adopting stable pointer %p, rc=%d\n", \ + ref, (ref && containerFor(ref)) ? containerFor(ref)->refCount() : -1) + UpdateReturnRef(OBJ_RESULT, ref); + DisposeStablePointer(pointer); + return ref; +} + +bool clearSubgraphReferences(ObjHeader* root, bool checked) { +#if USE_GC + MEMORY_LOG("ClearSubgraphReferences %p\n", root) + if (root == nullptr) return true; + auto state = memoryState; + auto* container = containerFor(root); + + if (isShareable(container)) + // We assume, that frozen/shareable objects can be safely passed and not present + // in the GC candidate list. + // TODO: assert for that? + return true; + + // Free cyclic garbage to decrease number of analyzed objects. + checkIfForceCyclicGcNeeded(state); + + ContainerHeaderSet visited; + if (!checked) { + hasExternalRefs(container, &visited); + } else { + // Now decrement RC of elements in toRelease set for reachibility analysis. + for (auto it = state->toRelease->begin(); it != state->toRelease->end(); ++it) { + auto released = *it; + if (!isMarkedAsRemoved(released) && released->local()) { + released->decRefCount(); + } + } + container->decRefCount(); + markGray(container); + auto bad = hasExternalRefs(container, &visited); + scanBlack(container); + // Restore original RC. + container->incRefCount(); + for (auto it = state->toRelease->begin(); it != state->toRelease->end(); ++it) { + auto released = *it; + if (!isMarkedAsRemoved(released) && released->local()) { + released->incRefCount(); + } + } + if (bad) { + return false; + } + } + + // Remove all no longer owned containers from GC structures. + // TODO: not very efficient traversal. + for (auto it = state->toFree->begin(); it != state->toFree->end(); ++it) { + auto container = *it; + if (visited.count(container) != 0) { + MEMORY_LOG("removing %p from the toFree list\n", container) + container->resetBuffered(); + container->setColorAssertIfGreen(CONTAINER_TAG_GC_BLACK); + *it = markAsRemoved(container); + } + } + for (auto it = state->toRelease->begin(); it != state->toRelease->end(); ++it) { + auto container = *it; + if (!isMarkedAsRemoved(container) && visited.count(container) != 0) { + MEMORY_LOG("removing %p from the toRelease list\n", container) + container->decRefCount(); + *it = markAsRemoved(container); + } + } + +#if TRACE_MEMORY + // Forget transferred containers. + for (auto* it: visited) { + state->containers->erase(it); + } +#endif + +#endif // USE_GC + return true; +} + +void freezeAcyclic(ContainerHeader* rootContainer, ContainerHeaderSet* newlyFrozen) { + KStdDeque queue; + queue.push_back(rootContainer); + while (!queue.empty()) { + ContainerHeader* current = queue.front(); + queue.pop_front(); + current->unMark(); + current->resetBuffered(); + current->setColorUnlessGreen(CONTAINER_TAG_GC_BLACK); + // Note, that once object is frozen, it could be concurrently accessed, so + // color and similar attributes shall not be used. + if (!current->frozen()) + newlyFrozen->insert(current); + MEMORY_LOG("freezing %p\n", current) + current->freeze(); + traverseContainerReferredObjects(current, [&queue](ObjHeader* obj) { + ContainerHeader* objContainer = containerFor(obj); + if (canFreeze(objContainer)) { + if (objContainer->marked()) + queue.push_back(objContainer); + } + }); + } +} + +void freezeCyclic(ObjHeader* root, + const KStdVector& order, + ContainerHeaderSet* newlyFrozen) { + KStdUnorderedMap> reversedEdges; + KStdDeque queue; + queue.push_back(root); + while (!queue.empty()) { + ObjHeader* current = queue.front(); + queue.pop_front(); + ContainerHeader* currentContainer = containerFor(current); + currentContainer->unMark(); + reversedEdges.emplace(currentContainer, KStdVector(0)); + traverseContainerReferredObjects(currentContainer, [current, currentContainer, &queue, &reversedEdges](ObjHeader* obj) { + ContainerHeader* objContainer = containerFor(obj); + if (canFreeze(objContainer)) { + if (objContainer->marked()) + queue.push_back(obj); + // We ignore references from FreezableAtomicsReference during condensation, to avoid KT-33824. + if (!isFreezableAtomic(current)) + reversedEdges.emplace(objContainer, KStdVector(0)). + first->second.push_back(currentContainer); + } + }); + } + + KStdVector> components; + MEMORY_LOG("Condensation:\n"); + // Enumerate in the topological order. + for (auto it = order.rbegin(); it != order.rend(); ++it) { + auto* container = *it; + if (container->marked()) continue; + KStdVector component; + traverseStronglyConnectedComponent(container, &reversedEdges, &component); + MEMORY_LOG("SCC:\n"); + #if TRACE_MEMORY + for (auto c: component) + konan::consolePrintf(" %p\n", c); + #endif + components.push_back(std::move(component)); + } + + // Enumerate strongly connected components in reversed topological order. + for (auto it = components.rbegin(); it != components.rend(); ++it) { + auto& component = *it; + int internalRefsCount = 0; + int totalCount = 0; + for (auto* container : component) { + RuntimeAssert(!isAggregatingFrozenContainer(container), "Must not be called on such containers"); + totalCount += container->refCount(); + if (isFreezableAtomic(container)) { + RuntimeAssert(component.size() == 1, "Must be trivial condensation"); + continue; + } + traverseContainerReferredObjects(container, [&internalRefsCount](ObjHeader* obj) { + auto* container = containerFor(obj); + if (canFreeze(container)) + ++internalRefsCount; + }); + } + + // Freeze component. + for (auto* container : component) { + container->resetBuffered(); + container->setColorUnlessGreen(CONTAINER_TAG_GC_BLACK); + if (!container->frozen()) + newlyFrozen->insert(container); + // Note, that once object is frozen, it could be concurrently accessed, so + // color and similar attributes shall not be used. + MEMORY_LOG("freezing %p\n", container) + container->freeze(); + // We set refcount of original container to zero, so that it is seen as such after removal + // meta-object, where aggregating container is stored. + container->setRefCount(0); + } + + // Create fictitious container for the whole component. + auto superContainer = component.size() == 1 ? component[0] : allocAggregatingFrozenContainer(component); + // Don't count internal references. + MEMORY_LOG("Setting aggregating %p rc to %d (total %d inner %d)\n", \ + superContainer, totalCount - internalRefsCount, totalCount, internalRefsCount) + superContainer->setRefCount(totalCount - internalRefsCount); + newlyFrozen->insert(superContainer); + } +} + +// These hooks are only allowed to modify `obj` subgraph. +void runFreezeHooks(ObjHeader* obj) { + if (obj->type_info() == theWorkerBoundReferenceTypeInfo) { + WorkerBoundReferenceFreezeHook(obj); + } +} + +void runFreezeHooksRecursive(ObjHeader* root) { + KStdUnorderedSet seen; + KStdVector toVisit; + seen.insert(root); + toVisit.push_back(root); + while (!toVisit.empty()) { + KRef obj = toVisit.back(); + toVisit.pop_back(); + + runFreezeHooks(obj); + + traverseReferredObjects(obj, [&seen, &toVisit](ObjHeader* field) { + auto wasNotSeenYet = seen.insert(field).second; + // Only iterating on unseen objects which containers will get frozen by freezeCyclic or freezeAcyclic. + if (wasNotSeenYet && canFreeze(containerFor(field))) { + toVisit.push_back(field); + } + }); + } +} + +/** + * Theory of operations. + * + * Kotlin/Native supports object graph freezing, allowing to make certain subgraph immutable and thus + * suitable for safe sharing amongst multiple concurrent executors. This operation recursively operates + * on all objects reachable from the given object, and marks them as frozen. In frozen state object's + * fields cannot be modified, and so, lifetime of frozen objects correlates. Practically, it means + * that lifetimes of all strongly connected components are fully controlled by incoming reference + * counters, and so if we place all members of strongly connected component to the single container + * it could be correctly released by just atomic decrement on reference counter, without additional + * cycle collector run. + * So during subgraph freezing operation, we perform the following steps: + * - run Kosoraju-Sharir algorithm to find strongly connected components + * - put all objects in each strongly connected component into an artificial container + * (we assume that they all were in single element containers initially), single-object + * components remain in the same container + * - artificial container sums up outer reference counters of all its objects (i.e. + * incoming references from the same strongly connected component are not counted) + * - mark all object's headers as frozen + * + * Further reference counting on frozen objects is performed with atomic operations, and so frozen + * references could be passed across multiple threads. + */ +void freezeSubgraph(ObjHeader* root) { + if (root == nullptr) return; + // First check that passed object graph has no cycles. + // If there are cycles - run graph condensation on cyclic graphs using Kosoraju-Sharir. + ContainerHeader* rootContainer = containerFor(root); + if (isPermanentOrFrozen(rootContainer)) return; + + MEMORY_LOG("Run freeze hooks on subgraph of %p\n", root); + + // Note: Actual freezing can fail, but these hooks won't be undone, and moreover + // these hooks will run again on a repeated freezing attempt. + runFreezeHooksRecursive(root); + + MEMORY_LOG("Freeze subgraph of %p\n", root) + + #if USE_GC + auto state = memoryState; + // Free cyclic garbage to decrease number of analyzed objects. + checkIfForceCyclicGcNeeded(state); + #endif + + // Do DFS cycle detection. + bool hasCycles = false; + KRef firstBlocker = root->has_meta_object() && ((root->meta_object()->flags_ & MF_NEVER_FROZEN) != 0) ? + root : nullptr; + KStdVector order; + depthFirstTraversal(rootContainer, &hasCycles, &firstBlocker, &order); + if (firstBlocker != nullptr) { + MEMORY_LOG("See freeze blocker for %p: %p\n", root, firstBlocker) + ThrowFreezingException(root, firstBlocker); + } + ContainerHeaderSet newlyFrozen; + // Now unmark all marked objects, and freeze them, if no cycles detected. + if (hasCycles) { + freezeCyclic(root, order, &newlyFrozen); + } else { + freezeAcyclic(rootContainer, &newlyFrozen); + } + MEMORY_LOG("Graph of %p is %s with %d elements\n", root, hasCycles ? "cyclic" : "acyclic", newlyFrozen.size()) + +#if USE_GC + // Now remove frozen objects from the toFree list. + // TODO: optimize it by keeping ignored (i.e. freshly frozen) objects in the set, + // and use it when analyzing toFree during collection. + for (auto& container : *(state->toFree)) { + if (!isMarkedAsRemoved(container) && container->frozen()) { + RuntimeAssert(newlyFrozen.count(container) != 0, "Must be newly frozen"); + container = markAsRemoved(container); + } + } +#endif +} + +void ensureNeverFrozen(ObjHeader* object) { + auto* container = containerFor(object); + if (container == nullptr || container->frozen()) + ThrowFreezingException(object, object); + // TODO: note, that this API could not not be called on frozen objects, so no need to care much about concurrency, + // although there's subtle race with case, where other thread freezes the same object after check. + object->meta_object()->flags_ |= MF_NEVER_FROZEN; +} + +void shareAny(ObjHeader* obj) { + auto* container = containerFor(obj); + if (isShareable(container)) return; + RuntimeCheck(container->objectCount() == 1, "Must be a single object container"); + container->makeShared(); +} + +ScopedRefHolder::ScopedRefHolder(KRef obj): obj_(obj) { + if (obj_) { + addHeapRef(obj_); + } +} + +ScopedRefHolder::~ScopedRefHolder() { + if (obj_) { + ReleaseHeapRef(obj_); + } +} + +#if USE_CYCLE_DETECTOR + +// static +CycleDetectorRootset CycleDetector::collectRootset() { + auto& detector = instance(); + CycleDetectorRootset rootset; + LockGuard guard(detector.lock_); + for (auto* candidate: detector.candidateList_) { + // Only frozen candidates are to be analyzed. + if (!isPermanentOrFrozen(candidate)) + continue; + rootset.roots.push_back(candidate); + rootset.heldRefs.emplace_back(candidate); + traverseReferredObjects(candidate, [&rootset, candidate](KRef field) { + rootset.rootToFields[candidate].push_back(field); + // TODO: There's currently a race here: + // some other thread might null this field and destroy it in GC before + // we put it in ScopedRefHolder. + rootset.heldRefs.emplace_back(field); + }); + } + return rootset; +} + +KStdVector findCycleWithDFS(KRef root, const CycleDetectorRootset& rootset) { + auto traverseFields = [&rootset](KRef obj, auto process) { + auto it = rootset.rootToFields.find(obj); + // If obj is in the rootset, use it's pinned state. + if (it != rootset.rootToFields.end()) { + const auto& fields = it->second; + for (KRef field: fields) { + if (field != nullptr) { + process(field); + } + } + return; + } + + traverseReferredObjects(obj, process); + }; + + KStdVector> toVisit; + auto appendFieldsToVisit = [&toVisit, &traverseFields](KRef obj, const KStdVector& currentPath) { + traverseFields(obj, [&toVisit, ¤tPath](KRef field) { + auto path = currentPath; + path.push_back(field); + toVisit.emplace_back(std::move(path)); + }); + }; + + appendFieldsToVisit(root, KRefList(1, root)); + + KStdUnorderedSet seen; + seen.insert(root); + while (!toVisit.empty()) { + KStdVector currentPath = std::move(toVisit.back()); + toVisit.pop_back(); + KRef node = currentPath[currentPath.size() - 1]; + + if (node == root) { + // Found a cycle. + return currentPath; + } + + // Already traversed this node. + if (seen.count(node) != 0) + continue; + seen.insert(node); + + appendFieldsToVisit(node, currentPath); + } + + return {}; +} + +template +OBJ_GETTER(createAndFillArray, const C& container) { + auto* result = AllocArrayInstance(theArrayTypeInfo, container.size(), OBJ_RESULT)->array(); + KRef* place = ArrayAddressOfElementAt(result, 0); + for (KRef it: container) { + UpdateHeapRef(place++, it); + } + RETURN_OBJ(result->obj()); +} + +OBJ_GETTER0(detectCyclicReferences) { + auto rootset = CycleDetector::collectRootset(); + + KStdVector cyclic; + + for (KRef root: rootset.roots) { + if (!findCycleWithDFS(root, rootset).empty()) { + cyclic.push_back(root); + } + } + + RETURN_RESULT_OF(createAndFillArray, cyclic); +} + +OBJ_GETTER(findCycle, KRef root) { + auto rootset = CycleDetector::collectRootset(); + + auto cycle = findCycleWithDFS(root, rootset); + if (cycle.empty()) { + RETURN_OBJ(nullptr); + } + RETURN_RESULT_OF(createAndFillArray, cycle); +} + +#endif // USE_CYCLE_DETECTOR + +} // namespace + +MetaObjHeader* ObjHeader::createMetaObject(TypeInfo** location) { + TypeInfo* typeInfo = *location; + RuntimeCheck(!hasPointerBits(typeInfo, OBJECT_TAG_MASK), "Object must not be tagged"); + +#if !KONAN_NO_THREADS + if (typeInfo->typeInfo_ != typeInfo) { + // Someone installed a new meta-object since the check. + return reinterpret_cast(typeInfo); + } +#endif + + MetaObjHeader* meta = konanConstructInstance(); + meta->typeInfo_ = typeInfo; +#if KONAN_NO_THREADS + *location = reinterpret_cast(meta); +#else + TypeInfo* old = __sync_val_compare_and_swap(location, typeInfo, reinterpret_cast(meta)); + if (old != typeInfo) { + // Someone installed a new meta-object since the check. + konanFreeMemory(meta); + meta = reinterpret_cast(old); + } +#endif + return meta; +} + +void ObjHeader::destroyMetaObject(TypeInfo** location) { + MetaObjHeader* meta = clearPointerBits(*(reinterpret_cast(location)), OBJECT_TAG_MASK); + *const_cast(location) = meta->typeInfo_; + if (meta->WeakReference.counter_ != nullptr) { + WeakReferenceCounterClear(meta->WeakReference.counter_); + ZeroHeapRef(&meta->WeakReference.counter_); + } + +#ifdef KONAN_OBJC_INTEROP + Kotlin_ObjCExport_releaseAssociatedObject(meta->associatedObject_); +#endif + + konanFreeMemory(meta); +} + +void ObjectContainer::Init(MemoryState* state, const TypeInfo* typeInfo) { + RuntimeAssert(typeInfo->instanceSize_ >= 0, "Must be an object"); + uint32_t allocSize = sizeof(ContainerHeader) + typeInfo->instanceSize_; + header_ = allocContainer(state, allocSize); + RuntimeCheck(header_ != nullptr, "Cannot alloc memory"); + // One object in this container, no need to set. + header_->setContainerSize(allocSize); + RuntimeAssert(header_->objectCount() == 1, "Must work properly"); + // header->refCount_ is zero initialized by allocContainer(). + SetHeader(GetPlace(), typeInfo); + OBJECT_ALLOC_EVENT(memoryState, typeInfo->instanceSize_, GetPlace()) +} + +void ArrayContainer::Init(MemoryState* state, const TypeInfo* typeInfo, uint32_t elements) { + RuntimeAssert(typeInfo->instanceSize_ < 0, "Must be an array"); + uint32_t allocSize = + sizeof(ContainerHeader) + arrayObjectSize(typeInfo, elements); + header_ = allocContainer(state, allocSize); + RuntimeCheck(header_ != nullptr, "Cannot alloc memory"); + // One object in this container, no need to set. + header_->setContainerSize(allocSize); + RuntimeAssert(header_->objectCount() == 1, "Must work properly"); + // header->refCount_ is zero initialized by allocContainer(). + GetPlace()->count_ = elements; + SetHeader(GetPlace()->obj(), typeInfo); + OBJECT_ALLOC_EVENT(memoryState, arrayObjectSize(typeInfo, elements), GetPlace()->obj()) +} + +// TODO: store arena containers in some reuseable data structure, similar to +// finalizer queue. +void ArenaContainer::Init() { + allocContainer(1024); +} + +void ArenaContainer::Deinit() { + MEMORY_LOG("Arena::Deinit start: %p\n", this) + auto chunk = currentChunk_; + while (chunk != nullptr) { + // freeContainer() doesn't release memory when CONTAINER_TAG_STACK is set. + MEMORY_LOG("Arena::Deinit free chunk %p\n", chunk) + freeContainer(chunk->asHeader()); + chunk = chunk->next; + } + chunk = currentChunk_; + while (chunk != nullptr) { + auto toRemove = chunk; + chunk = chunk->next; + konanFreeMemory(toRemove); + } +} + +bool ArenaContainer::allocContainer(container_size_t minSize) { + auto size = minSize + sizeof(ContainerHeader) + sizeof(ContainerChunk); + size = alignUp(size, kContainerAlignment); + // TODO: keep simple cache of container chunks. + ContainerChunk* result = konanConstructSizedInstance(size); + RuntimeCheck(result != nullptr, "Cannot alloc memory"); + if (result == nullptr) return false; + result->next = currentChunk_; + result->arena = this; + result->asHeader()->refCount_ = (CONTAINER_TAG_STACK | CONTAINER_TAG_INCREMENT); + currentChunk_ = result; + current_ = reinterpret_cast(result->asHeader() + 1); + end_ = reinterpret_cast(result) + size; + return true; +} + +void* ArenaContainer::place(container_size_t size) { + size = alignUp(size, kObjectAlignment); + // Fast path. + if (current_ + size < end_) { + void* result = current_; + current_ += size; + return result; + } + if (!allocContainer(size)) { + return nullptr; + } + void* result = current_; + current_ += size; + RuntimeAssert(current_ <= end_, "Must not overflow"); + return result; +} + +#define ARENA_SLOTS_CHUNK_SIZE 16 + +ObjHeader** ArenaContainer::getSlot() { + if (slots_ == nullptr || slotsCount_ >= ARENA_SLOTS_CHUNK_SIZE) { + slots_ = PlaceArray(theArrayTypeInfo, ARENA_SLOTS_CHUNK_SIZE); + slotsCount_ = 0; + } + return ArrayAddressOfElementAt(slots_, slotsCount_++); +} + +ObjHeader* ArenaContainer::PlaceObject(const TypeInfo* type_info) { + RuntimeAssert(type_info->instanceSize_ >= 0, "must be an object"); + uint32_t size = type_info->instanceSize_; + ObjHeader* result = reinterpret_cast(place(size)); + if (!result) { + return nullptr; + } + OBJECT_ALLOC_EVENT(memoryState, type_info->instanceSize_, result) + currentChunk_->asHeader()->incObjectCount(); + setHeader(result, type_info); + return result; +} + +ArrayHeader* ArenaContainer::PlaceArray(const TypeInfo* type_info, uint32_t count) { + RuntimeAssert(type_info->instanceSize_ < 0, "must be an array"); + container_size_t size = arrayObjectSize(type_info, count); + ArrayHeader* result = reinterpret_cast(place(size)); + if (!result) { + return nullptr; + } + OBJECT_ALLOC_EVENT(memoryState, arrayObjectSize(type_info, count), result->obj()) + currentChunk_->asHeader()->incObjectCount(); + setHeader(result->obj(), type_info); + result->count_ = count; + return result; +} + +// API of the memory manager. +extern "C" { + +// Private memory interface. +bool TryAddHeapRef(const ObjHeader* object) { + return tryAddHeapRef(object); +} + +void ReleaseHeapRefStrict(const ObjHeader* object) { + releaseHeapRef(const_cast(object)); +} +void ReleaseHeapRefRelaxed(const ObjHeader* object) { + releaseHeapRef(const_cast(object)); +} + +void ReleaseHeapRefNoCollectStrict(const ObjHeader* object) { + releaseHeapRef(const_cast(object)); +} +void ReleaseHeapRefNoCollectRelaxed(const ObjHeader* object) { + releaseHeapRef(const_cast(object)); +} + +ForeignRefContext InitLocalForeignRef(ObjHeader* object) { + return initLocalForeignRef(object); +} + +ForeignRefContext InitForeignRef(ObjHeader* object) { + return initForeignRef(object); +} + +void DeinitForeignRef(ObjHeader* object, ForeignRefContext context) { + deinitForeignRef(object, context); +} + +bool IsForeignRefAccessible(ObjHeader* object, ForeignRefContext context) { + return isForeignRefAccessible(object, context); +} + +void AdoptReferenceFromSharedVariable(ObjHeader* object) { +#if USE_GC + if (IsStrictMemoryModel && object != nullptr && isShareable(containerFor(object))) + rememberNewContainer(containerFor(object)); +#endif // USE_GC +} + +// Public memory interface. +MemoryState* InitMemory() { + return initMemory(); +} + +void DeinitMemory(MemoryState* memoryState) { + deinitMemory(memoryState); +} + +void RestoreMemory(MemoryState* memoryState) { + RuntimeAssert((::memoryState == nullptr) || (::memoryState == memoryState), "Must not replace with unrelated memory state"); + ::memoryState = memoryState; +} + +OBJ_GETTER(AllocInstanceStrict, const TypeInfo* type_info) { + RETURN_RESULT_OF(allocInstance, type_info); +} +OBJ_GETTER(AllocInstanceRelaxed, const TypeInfo* type_info) { + RETURN_RESULT_OF(allocInstance, type_info); +} + +OBJ_GETTER(AllocArrayInstanceStrict, const TypeInfo* typeInfo, int32_t elements) { + RETURN_RESULT_OF(allocArrayInstance, typeInfo, elements); +} +OBJ_GETTER(AllocArrayInstanceRelaxed, const TypeInfo* typeInfo, int32_t elements) { + RETURN_RESULT_OF(allocArrayInstance, typeInfo, elements); +} + +OBJ_GETTER(InitInstanceStrict, + ObjHeader** location, const TypeInfo* typeInfo, void (*ctor)(ObjHeader*)) { + RETURN_RESULT_OF(initInstance, location, typeInfo, ctor); +} +OBJ_GETTER(InitInstanceRelaxed, + ObjHeader** location, const TypeInfo* typeInfo, void (*ctor)(ObjHeader*)) { + RETURN_RESULT_OF(initInstance, location, typeInfo, ctor); +} + +OBJ_GETTER(InitSharedInstanceStrict, + ObjHeader** location, const TypeInfo* typeInfo, void (*ctor)(ObjHeader*)) { + RETURN_RESULT_OF(initSharedInstance, location, typeInfo, ctor); +} +OBJ_GETTER(InitSharedInstanceRelaxed, + ObjHeader** location, const TypeInfo* typeInfo, void (*ctor)(ObjHeader*)) { + RETURN_RESULT_OF(initSharedInstance, location, typeInfo, ctor); +} + +void SetStackRefStrict(ObjHeader** location, const ObjHeader* object) { + setStackRef(location, object); +} +void SetStackRefRelaxed(ObjHeader** location, const ObjHeader* object) { + setStackRef(location, object); +} + +void SetHeapRefStrict(ObjHeader** location, const ObjHeader* object) { + setHeapRef(location, object); +} +void SetHeapRefRelaxed(ObjHeader** location, const ObjHeader* object) { + setHeapRef(location, object); +} + +void ZeroHeapRef(ObjHeader** location) { + zeroHeapRef(location); +} + +void ZeroStackRefStrict(ObjHeader** location) { + zeroStackRef(location); +} +void ZeroStackRefRelaxed(ObjHeader** location) { + zeroStackRef(location); +} + +void UpdateStackRefStrict(ObjHeader** location, const ObjHeader* object) { + updateStackRef(location, object); +} +void UpdateStackRefRelaxed(ObjHeader** location, const ObjHeader* object) { + updateStackRef(location, object); +} + +void UpdateHeapRefStrict(ObjHeader** location, const ObjHeader* object) { + updateHeapRef(location, object); +} +void UpdateHeapRefRelaxed(ObjHeader** location, const ObjHeader* object) { + updateHeapRef(location, object); +} + +void UpdateReturnRefStrict(ObjHeader** returnSlot, const ObjHeader* value) { + updateReturnRef(returnSlot, value); +} +void UpdateReturnRefRelaxed(ObjHeader** returnSlot, const ObjHeader* value) { + updateReturnRef(returnSlot, value); +} + +void ZeroArrayRefs(ArrayHeader* array) { + for (uint32_t index = 0; index < array->count_; ++index) { + ObjHeader** location = ArrayAddressOfElementAt(array, index); + zeroHeapRef(location); + } +} + +void UpdateHeapRefIfNull(ObjHeader** location, const ObjHeader* object) { + updateHeapRefIfNull(location, object); +} + +OBJ_GETTER(SwapHeapRefLocked, + ObjHeader** location, ObjHeader* expectedValue, ObjHeader* newValue, int32_t* spinlock, int32_t* cookie) { + RETURN_RESULT_OF(swapHeapRefLocked, location, expectedValue, newValue, spinlock, cookie); +} + +void SetHeapRefLocked(ObjHeader** location, ObjHeader* newValue, int32_t* spinlock, int32_t* cookie) { + setHeapRefLocked(location, newValue, spinlock, cookie); +} + +OBJ_GETTER(ReadHeapRefLocked, ObjHeader** location, int32_t* spinlock, int32_t* cookie) { + RETURN_RESULT_OF(readHeapRefLocked, location, spinlock, cookie); +} + +OBJ_GETTER(ReadHeapRefNoLock, ObjHeader* object, KInt index) { + RETURN_RESULT_OF(readHeapRefNoLock, object, index); +} + +void EnterFrameStrict(ObjHeader** start, int parameters, int count) { + enterFrame(start, parameters, count); +} +void EnterFrameRelaxed(ObjHeader** start, int parameters, int count) { + enterFrame(start, parameters, count); +} + +void LeaveFrameStrict(ObjHeader** start, int parameters, int count) { + leaveFrame(start, parameters, count); +} +void LeaveFrameRelaxed(ObjHeader** start, int parameters, int count) { + leaveFrame(start, parameters, count); +} + +void Kotlin_native_internal_GC_collect(KRef) { +#if USE_GC + garbageCollect(); +#endif +} + +void Kotlin_native_internal_GC_collectCyclic(KRef) { +#if USE_CYCLIC_GC + if (g_hasCyclicCollector) + cyclicScheduleGarbageCollect(); +#else + ThrowIllegalArgumentException(); +#endif +} + +void Kotlin_native_internal_GC_suspend(KRef) { +#if USE_GC + suspendGC(); +#endif +} + +void Kotlin_native_internal_GC_resume(KRef) { +#if USE_GC + resumeGC(); +#endif +} + +void Kotlin_native_internal_GC_stop(KRef) { +#if USE_GC + stopGC(); +#endif +} + +void Kotlin_native_internal_GC_start(KRef) { +#if USE_GC + startGC(); +#endif +} + +void Kotlin_native_internal_GC_setThreshold(KRef, KInt value) { +#if USE_GC + setGCThreshold(value); +#endif +} + +KInt Kotlin_native_internal_GC_getThreshold(KRef) { +#if USE_GC + return getGCThreshold(); +#else + return -1; +#endif +} + +void Kotlin_native_internal_GC_setCollectCyclesThreshold(KRef, KLong value) { +#if USE_GC + setGCCollectCyclesThreshold(value); +#endif +} + +KLong Kotlin_native_internal_GC_getCollectCyclesThreshold(KRef) { +#if USE_GC + return getGCCollectCyclesThreshold(); +#else + return -1; +#endif +} + +void Kotlin_native_internal_GC_setThresholdAllocations(KRef, KLong value) { +#if USE_GC + setGCThresholdAllocations(value); +#endif +} + +KLong Kotlin_native_internal_GC_getThresholdAllocations(KRef) { +#if USE_GC + return getGCThresholdAllocations(); +#else + return -1; +#endif +} + +void Kotlin_native_internal_GC_setTuneThreshold(KRef, KInt value) { +#if USE_GC + setTuneGCThreshold(value); +#endif +} + +KBoolean Kotlin_native_internal_GC_getTuneThreshold(KRef) { +#if USE_GC + return getTuneGCThreshold(); +#else + return false; +#endif +} + +OBJ_GETTER(Kotlin_native_internal_GC_detectCycles, KRef) { +#if USE_CYCLE_DETECTOR + if (!KonanNeedDebugInfo || !Kotlin_memoryLeakCheckerEnabled()) RETURN_OBJ(nullptr); + RETURN_RESULT_OF0(detectCyclicReferences); +#else + RETURN_OBJ(nullptr); +#endif +} + +OBJ_GETTER(Kotlin_native_internal_GC_findCycle, KRef, KRef root) { +#if USE_CYCLE_DETECTOR + RETURN_RESULT_OF(findCycle, root); +#else + RETURN_OBJ(nullptr); +#endif +} + +KNativePtr CreateStablePointer(KRef any) { + return createStablePointer(any); +} + +void DisposeStablePointer(KNativePtr pointer) { + disposeStablePointer(pointer); +} + +OBJ_GETTER(DerefStablePointer, KNativePtr pointer) { + RETURN_RESULT_OF(derefStablePointer, pointer); +} + +OBJ_GETTER(AdoptStablePointer, KNativePtr pointer) { + RETURN_RESULT_OF(adoptStablePointer, pointer); +} + +bool ClearSubgraphReferences(ObjHeader* root, bool checked) { + return clearSubgraphReferences(root, checked); +} + +void FreezeSubgraph(ObjHeader* root) { + freezeSubgraph(root); +} + +// This function is called from field mutators to check if object's header is frozen. +// If object is frozen or permanent, an exception is thrown. +void MutationCheck(ObjHeader* obj) { + if (obj->local()) return; + auto* container = containerFor(obj); + if (container == nullptr || container->frozen()) + ThrowInvalidMutabilityException(obj); +} + +void CheckLifetimesConstraint(ObjHeader* obj, ObjHeader* pointee) { + if (!obj->local() && pointee != nullptr && pointee->local()) { + konan::consolePrintf("Attempt to store a stack object %p into a heap object %p\n", pointee, obj); + konan::consolePrintf("This is a compiler bug, please report it to https://kotl.in/issue\n"); + konan::abort(); + } +} + +void EnsureNeverFrozen(ObjHeader* object) { + ensureNeverFrozen(object); +} + +void Kotlin_Any_share(ObjHeader* obj) { + shareAny(obj); +} + +void AddTLSRecord(MemoryState* memory, void** key, int size) { + auto* tlsMap = memory->tlsMap; + auto it = tlsMap->find(key); + if (it != tlsMap->end()) { + RuntimeAssert(it->second.second == size, "Size must be consistent"); + return; + } + KRef* start = reinterpret_cast(konanAllocMemory(size * sizeof(KRef))); + tlsMap->emplace(key, std::make_pair(start, size)); +} + +void ClearTLSRecord(MemoryState* memory, void** key) { + auto* tlsMap = memory->tlsMap; + auto it = tlsMap->find(key); + if (it != tlsMap->end()) { + KRef* start = it->second.first; + int count = it->second.second; + for (int i = 0; i < count; i++) { + UpdateHeapRef(start + i, nullptr); + } + konanFreeMemory(start); + tlsMap->erase(it); + } +} + +KRef* LookupTLS(void** key, int index) { + auto* state = memoryState; + auto* tlsMap = state->tlsMap; + // In many cases there is only one module, so this one element cache. + if (state->tlsMapLastKey == key) { + return state->tlsMapLastStart + index; + } + auto it = tlsMap->find(key); + RuntimeAssert(it != tlsMap->end(), "Must be there"); + RuntimeAssert(index < it->second.second, "Out of bound in TLS access"); + KRef* start = it->second.first; + state->tlsMapLastKey = key; + state->tlsMapLastStart = start; + return start + index; +} + + +void GC_RegisterWorker(void* worker) { +#if USE_CYCLIC_GC + cyclicAddWorker(worker); +#endif // USE_CYCLIC_GC +} + +void GC_UnregisterWorker(void* worker) { +#if USE_CYCLIC_GC + cyclicRemoveWorker(worker, g_hasCyclicCollector); +#endif // USE_CYCLIC_GC +} + +void GC_CollectorCallback(void* worker) { +#if USE_CYCLIC_GC + if (g_hasCyclicCollector) + cyclicCollectorCallback(worker); +#endif // USE_CYCLIC_GC +} + +KBoolean Kotlin_native_internal_GC_getCyclicCollector(KRef gc) { +#if USE_CYCLIC_GC + return g_hasCyclicCollector; +#else + return false; +#endif // USE_CYCLIC_GC +} + +void Kotlin_native_internal_GC_setCyclicCollector(KRef gc, KBoolean value) { +#if USE_CYCLIC_GC + g_hasCyclicCollector = value; +#else + if (value) + ThrowIllegalArgumentException(); +#endif // USE_CYCLIC_GC +} + +bool Kotlin_Any_isShareable(KRef thiz) { + return thiz == nullptr || isShareable(containerFor(thiz)); +} + +void PerformFullGC() { + garbageCollect(::memoryState, true); +} + +} // extern "C" diff --git a/kotlin-native/runtime/src/legacymm/cpp/MemoryPrivate.hpp b/kotlin-native/runtime/src/legacymm/cpp/MemoryPrivate.hpp new file mode 100644 index 00000000000..034bf339c55 --- /dev/null +++ b/kotlin-native/runtime/src/legacymm/cpp/MemoryPrivate.hpp @@ -0,0 +1,337 @@ +/* + * Copyright 2010-2017 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef RUNTIME_MEMORYPRIVATE_HPP +#define RUNTIME_MEMORYPRIVATE_HPP + +#include "Memory.h" + +typedef enum { + // Those bit masks are applied to refCount_ field. + // Container is normal thread-local container. + CONTAINER_TAG_LOCAL = 0, + // Container is frozen, could only refer to other frozen objects. + // Refcounter update is atomics. + CONTAINER_TAG_FROZEN = 1 | 1, // shareable + // Stack container, no need to free, children cleanup still shall be there. + CONTAINER_TAG_STACK = 2, + // Atomic container, reference counter is atomically updated. + CONTAINER_TAG_SHARED = 3 | 1, // shareable + // Shift to get actual counter. + CONTAINER_TAG_SHIFT = 2, + // Actual value to increment/decrement container by. Tag is in lower bits. + CONTAINER_TAG_INCREMENT = 1 << CONTAINER_TAG_SHIFT, + // Mask for container type. + CONTAINER_TAG_MASK = CONTAINER_TAG_INCREMENT - 1, + + // Shift to get actual object count, if has it. + CONTAINER_TAG_GC_SHIFT = 7, + CONTAINER_TAG_GC_MASK = (1 << CONTAINER_TAG_GC_SHIFT) - 1, + CONTAINER_TAG_GC_INCREMENT = 1 << CONTAINER_TAG_GC_SHIFT, + // Color mask of a container. + CONTAINER_TAG_COLOR_SHIFT = 3, + CONTAINER_TAG_GC_COLOR_MASK = (1 << CONTAINER_TAG_COLOR_SHIFT) - 1, + // Colors. + // In use or free. + CONTAINER_TAG_GC_BLACK = 0, + // Possible member of garbage cycle. + CONTAINER_TAG_GC_GRAY = 1, + // Member of garbage cycle. + CONTAINER_TAG_GC_WHITE = 2, + // Possible root of cycle. + CONTAINER_TAG_GC_PURPLE = 3, + // Acyclic. + CONTAINER_TAG_GC_GREEN = 4, + // Orange and red are currently unused. + // Candidate cycle awaiting epoch. + CONTAINER_TAG_GC_ORANGE = 5, + // Candidate cycle awaiting sigma computation. + CONTAINER_TAG_GC_RED = 6, + // Individual state bits used during GC and freezing. + CONTAINER_TAG_GC_MARKED = 1 << CONTAINER_TAG_COLOR_SHIFT, + CONTAINER_TAG_GC_BUFFERED = 1 << (CONTAINER_TAG_COLOR_SHIFT + 1), + CONTAINER_TAG_GC_SEEN = 1 << (CONTAINER_TAG_COLOR_SHIFT + 2), + // If indeed has more that one object. + CONTAINER_TAG_GC_HAS_OBJECT_COUNT = 1 << (CONTAINER_TAG_COLOR_SHIFT + 3) +} ContainerTag; + +// Header of all container objects. Contains reference counter. +struct ContainerHeader { + // Reference counter of container. Uses CONTAINER_TAG_SHIFT, lower bits of counter + // for container type (for polymorphism in ::Release()). + uint32_t refCount_; + // Number of objects in the container. + uint32_t objectCount_; + + inline bool local() const { + return (refCount_ & CONTAINER_TAG_MASK) == CONTAINER_TAG_LOCAL; + } + + inline bool frozen() const { + return (refCount_ & CONTAINER_TAG_MASK) == CONTAINER_TAG_FROZEN; + } + + inline void freeze() { + refCount_ = (refCount_ & ~CONTAINER_TAG_MASK) | CONTAINER_TAG_FROZEN; + } + + inline void makeShared() { + refCount_ = (refCount_ & ~CONTAINER_TAG_MASK) | CONTAINER_TAG_SHARED; + } + + inline bool shared() const { + return (refCount_ & CONTAINER_TAG_MASK) == CONTAINER_TAG_SHARED; + } + + inline bool shareable() const { + return (tag() & 1) != 0; // CONTAINER_TAG_FROZEN || CONTAINER_TAG_SHARED + } + + inline bool stack() const { + return (refCount_ & CONTAINER_TAG_MASK) == CONTAINER_TAG_STACK; + } + + inline int refCount() const { + return (int)refCount_ >> CONTAINER_TAG_SHIFT; + } + + inline void setRefCount(unsigned refCount) { + refCount_ = tag() | (refCount << CONTAINER_TAG_SHIFT); + } + + template + inline void incRefCount() { +#ifdef KONAN_NO_THREADS + refCount_ += CONTAINER_TAG_INCREMENT; +#else + if (Atomic) + __sync_add_and_fetch(&refCount_, CONTAINER_TAG_INCREMENT); + else + refCount_ += CONTAINER_TAG_INCREMENT; +#endif + } + + template + inline bool tryIncRefCount() { + if (Atomic) { + while (true) { + uint32_t currentRefCount_ = refCount_; + if (((int)currentRefCount_ >> CONTAINER_TAG_SHIFT) > 0) { + if (compareAndSet(&refCount_, currentRefCount_, currentRefCount_ + CONTAINER_TAG_INCREMENT)) { + return true; + } + } else { + return false; + } + } + } else { + // Note: tricky case here is doing this during cycle collection. + // This can actually happen due to deallocation hooks. + // Fortunately by this point reference counts have been made precise again. + if (refCount() > 0) { + incRefCount(); + return true; + } else { + return false; + } + } + } + + template + inline int decRefCount() { +#ifdef KONAN_NO_THREADS + int value = refCount_ -= CONTAINER_TAG_INCREMENT; +#else + int value = Atomic ? + __sync_sub_and_fetch(&refCount_, CONTAINER_TAG_INCREMENT) : refCount_ -= CONTAINER_TAG_INCREMENT; +#endif + return value >> CONTAINER_TAG_SHIFT; + } + + inline int decRefCount() { + #ifdef KONAN_NO_THREADS + int value = refCount_ -= CONTAINER_TAG_INCREMENT; + #else + int value = shareable() ? + __sync_sub_and_fetch(&refCount_, CONTAINER_TAG_INCREMENT) : refCount_ -= CONTAINER_TAG_INCREMENT; + #endif + return value >> CONTAINER_TAG_SHIFT; + } + + inline unsigned tag() const { + return refCount_ & CONTAINER_TAG_MASK; + } + + inline unsigned objectCount() const { + return (objectCount_ & CONTAINER_TAG_GC_HAS_OBJECT_COUNT) != 0 ? + (objectCount_ >> CONTAINER_TAG_GC_SHIFT) : 1; + } + + inline void incObjectCount() { + RuntimeAssert((objectCount_ & CONTAINER_TAG_GC_HAS_OBJECT_COUNT) != 0, "Must have object count"); + objectCount_ += CONTAINER_TAG_GC_INCREMENT; + } + + inline void setObjectCount(int count) { + if (count == 1) { + objectCount_ &= ~CONTAINER_TAG_GC_HAS_OBJECT_COUNT; + } else { + objectCount_ = (count << CONTAINER_TAG_GC_SHIFT) | CONTAINER_TAG_GC_HAS_OBJECT_COUNT; + } + } + + inline unsigned containerSize() const { + RuntimeAssert((objectCount_ & CONTAINER_TAG_GC_HAS_OBJECT_COUNT) == 0, "Must be single-object"); + return (objectCount_ >> CONTAINER_TAG_GC_SHIFT); + } + + inline void setContainerSize(unsigned size) { + RuntimeAssert((objectCount_ & CONTAINER_TAG_GC_HAS_OBJECT_COUNT) == 0, "Must not have object count"); + objectCount_ = (objectCount_ & CONTAINER_TAG_GC_MASK) | (size << CONTAINER_TAG_GC_SHIFT); + } + + inline bool hasContainerSize() { + return (objectCount_ & CONTAINER_TAG_GC_HAS_OBJECT_COUNT) == 0; + } + + inline unsigned color() const { + return objectCount_ & CONTAINER_TAG_GC_COLOR_MASK; + } + + inline void setColorAssertIfGreen(unsigned color) { + RuntimeAssert(this->color() != CONTAINER_TAG_GC_GREEN, "Must not be green"); + setColorEvenIfGreen(color); + } + + inline void setColorEvenIfGreen(unsigned color) { + // TODO: do we need atomic color update? + objectCount_ = (objectCount_ & ~CONTAINER_TAG_GC_COLOR_MASK) | color; + } + + inline void setColorUnlessGreen(unsigned color) { + // TODO: do we need atomic color update? + unsigned objectCount = objectCount_; + if ((objectCount & CONTAINER_TAG_GC_COLOR_MASK) != CONTAINER_TAG_GC_GREEN) + objectCount_ = (objectCount & ~CONTAINER_TAG_GC_COLOR_MASK) | color; + } + + inline bool buffered() const { + return (objectCount_ & CONTAINER_TAG_GC_BUFFERED) != 0; + } + + inline void setBuffered() { + objectCount_ |= CONTAINER_TAG_GC_BUFFERED; + } + + inline void resetBuffered() { + objectCount_ &= ~CONTAINER_TAG_GC_BUFFERED; + } + + inline bool marked() const { + return (objectCount_ & CONTAINER_TAG_GC_MARKED) != 0; + } + + inline void mark() { + objectCount_ |= CONTAINER_TAG_GC_MARKED; + } + + inline void unMark() { + objectCount_ &= ~CONTAINER_TAG_GC_MARKED; + } + + inline bool seen() const { + return (objectCount_ & CONTAINER_TAG_GC_SEEN) != 0; + } + + inline void setSeen() { + objectCount_ |= CONTAINER_TAG_GC_SEEN; + } + + inline void resetSeen() { + objectCount_ &= ~CONTAINER_TAG_GC_SEEN; + } + + // Following operations only work on freed container which is in finalization queue. + // We cannot use 'this' here, as it conflicts with aliasing analysis in clang. + inline void setNextLink(ContainerHeader* next) { + *reinterpret_cast(this + 1) = next; + } + + inline ContainerHeader* nextLink() { + return *reinterpret_cast(this + 1); + } +}; + +ALWAYS_INLINE ContainerHeader* containerFor(const ObjHeader* obj); + +// Header for the meta-object. +struct MetaObjHeader { + // Pointer to the type info. Must be first, to match ArrayHeader and ObjHeader layout. + const TypeInfo* typeInfo_; + // Container pointer. + ContainerHeader* container_; + +#ifdef KONAN_OBJC_INTEROP + void* associatedObject_; +#endif + + // Flags for the object state. + int32_t flags_; + + struct { + // Strong reference to the counter object. + ObjHeader* counter_; + } WeakReference; +}; + +extern "C" { + +#define MODEL_VARIANTS(returnType, name, ...) \ + returnType name##Strict(__VA_ARGS__) RUNTIME_NOTHROW; \ + returnType name##Relaxed(__VA_ARGS__) RUNTIME_NOTHROW; + +OBJ_GETTER(AllocInstanceStrict, const TypeInfo* type_info) RUNTIME_NOTHROW; +OBJ_GETTER(AllocInstanceRelaxed, const TypeInfo* type_info) RUNTIME_NOTHROW; + +OBJ_GETTER(AllocArrayInstanceStrict, const TypeInfo* type_info, int32_t elements); +OBJ_GETTER(AllocArrayInstanceRelaxed, const TypeInfo* type_info, int32_t elements); + +OBJ_GETTER(InitInstanceStrict, + ObjHeader** location, const TypeInfo* typeInfo, void (*ctor)(ObjHeader*)); +OBJ_GETTER(InitInstanceRelaxed, + ObjHeader** location, const TypeInfo* typeInfo, void (*ctor)(ObjHeader*)); + +OBJ_GETTER(InitSharedInstanceStrict, + ObjHeader** location, const TypeInfo* typeInfo, void (*ctor)(ObjHeader*)); +OBJ_GETTER(InitSharedInstanceRelaxed, + ObjHeader** location, const TypeInfo* typeInfo, void (*ctor)(ObjHeader*)); + +MODEL_VARIANTS(void, SetStackRef, ObjHeader** location, const ObjHeader* object); +MODEL_VARIANTS(void, SetHeapRef, ObjHeader** location, const ObjHeader* object); +MODEL_VARIANTS(void, ZeroStackRef, ObjHeader** location); +MODEL_VARIANTS(void, UpdateStackRef, ObjHeader** location, const ObjHeader* object); +MODEL_VARIANTS(void, UpdateHeapRef, ObjHeader** location, const ObjHeader* object); +MODEL_VARIANTS(void, UpdateHeapRefIfNull, ObjHeader** location, const ObjHeader* object); +MODEL_VARIANTS(void, UpdateReturnRef, ObjHeader** returnSlot, const ObjHeader* object); +MODEL_VARIANTS(void, EnterFrame, ObjHeader** start, int parameters, int count); +MODEL_VARIANTS(void, LeaveFrame, ObjHeader** start, int parameters, int count); + +MODEL_VARIANTS(void, ReleaseHeapRef, const ObjHeader* object); +MODEL_VARIANTS(void, ReleaseHeapRefNoCollect, const ObjHeader* object); + +} // extern "C" + +#endif // RUNTIME_MEMORYPRIVATE_HPP diff --git a/kotlin-native/runtime/src/main/cpp/Alloc.h b/kotlin-native/runtime/src/main/cpp/Alloc.h new file mode 100644 index 00000000000..fca43491c32 --- /dev/null +++ b/kotlin-native/runtime/src/main/cpp/Alloc.h @@ -0,0 +1,118 @@ +/* + * Copyright 2010-2017 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef RUNTIME_ALLOC_H +#define RUNTIME_ALLOC_H + +#include +#include + +#include +#include + +#include "Porting.h" + +inline void* konanAllocMemory(size_t size) { + return konan::calloc(1, size); +} + +inline void konanFreeMemory(void* memory) { + konan::free(memory); +} + +template +inline T* konanAllocArray(size_t length) { + return reinterpret_cast(konanAllocMemory(length * sizeof(T))); +} + +template +inline T* konanConstructInstance(A&& ...args) { + return new (konanAllocMemory(sizeof(T))) T(::std::forward(args)...); +} + +template +inline T* konanConstructSizedInstance(size_t size, A&& ...args) { + return new (konanAllocMemory(size)) T(::std::forward(args)...); +} + +template +inline void konanDestructInstance(T* instance) { + instance->~T(); + konanFreeMemory(instance); +} + +template class KonanAllocator { + public: + typedef size_t size_type; + typedef ptrdiff_t difference_type; + typedef T* pointer; + typedef const T* const_pointer; + typedef T& reference; + typedef const T& const_reference; + typedef T value_type; + + KonanAllocator() {} + KonanAllocator(const KonanAllocator&) {} + + pointer allocate(size_type n, const void * = 0) { + return reinterpret_cast(konanAllocMemory(n * sizeof(T))); + } + + void deallocate(void* p, size_type) { + if (p != nullptr) konanFreeMemory(p); + } + + pointer address(reference x) const { return &x; } + + const_pointer address(const_reference x) const { return &x; } + + KonanAllocator& operator=(const KonanAllocator&) { return *this; } + + void construct(pointer p, const T& val) { new ((T*) p) T(val); } + + // C++-11 wants that. + template + void construct(U* const p, A&& ...args) { + new (p) U(::std::forward(args)...); + } + + void destroy(pointer p) { p->~T(); } + + size_type max_size() const { return size_t(-1); } + + template + struct rebind { typedef KonanAllocator other; }; + + template + KonanAllocator(const KonanAllocator&) {} + + template + KonanAllocator& operator=(const KonanAllocator&) { return *this; } +}; + +template +bool operator==( + KonanAllocator const&, KonanAllocator const&) noexcept { + return true; +} + +template +bool operator!=( + KonanAllocator const& x, KonanAllocator const& y) noexcept { + return !(x == y); +} + +#endif // RUNTIME_ALLOC_H diff --git a/kotlin-native/runtime/src/main/cpp/Arrays.cpp b/kotlin-native/runtime/src/main/cpp/Arrays.cpp new file mode 100644 index 00000000000..164a9fd5e88 --- /dev/null +++ b/kotlin-native/runtime/src/main/cpp/Arrays.cpp @@ -0,0 +1,708 @@ +/* + * Copyright 2010-2017 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include + +#include "KAssert.h" +#include "Exceptions.h" +#include "Memory.h" +#include "Natives.h" +#include "Types.h" + +extern "C" void checkRangeIndexes(KInt from, KInt to, KInt size); + +namespace { + +ALWAYS_INLINE inline void mutabilityCheck(KConstRef thiz) { + // TODO: optimize it! + if (!thiz->local() && isFrozen(thiz)) { + ThrowInvalidMutabilityException(thiz); + } +} + +ALWAYS_INLINE inline void boundsCheck(const ArrayHeader* array, KInt index) { + // We couldn't have created an array bigger than max KInt value. + // So if index is < 0, conversion to an unsigned value would make it bigger + // than the array size. + if (static_cast(index) >= array->count_) { + ThrowArrayIndexOutOfBoundsException(); + } +} + +template +inline void fillImpl(KRef thiz, KInt fromIndex, KInt toIndex, T value) { + ArrayHeader* array = thiz->array(); + checkRangeIndexes(fromIndex, toIndex, array->count_); + mutabilityCheck(thiz); + T* address = PrimitiveArrayAddressOfElementAt(array, fromIndex); + for (KInt index = fromIndex; index < toIndex; ++index) { + *address++ = value; + } +} + +template +inline void copyImpl(KConstRef thiz, KInt fromIndex, + KRef destination, KInt toIndex, KInt count) { + const ArrayHeader* array = thiz->array(); + ArrayHeader* destinationArray = destination->array(); + if (count < 0 || + fromIndex < 0 || static_cast(count) + fromIndex > array->count_ || + toIndex < 0 || static_cast(count) + toIndex > destinationArray->count_) { + ThrowArrayIndexOutOfBoundsException(); + } + mutabilityCheck(destination); + memmove(PrimitiveArrayAddressOfElementAt(destinationArray, toIndex), + PrimitiveArrayAddressOfElementAt(array, fromIndex), + count * sizeof(T)); +} + + +template +inline void PrimitiveArraySet(KRef thiz, KInt index, T value) { + ArrayHeader* array = thiz->array(); + boundsCheck(array, index); + mutabilityCheck(thiz); + *PrimitiveArrayAddressOfElementAt(array, index) = value; +} + +template +inline T PrimitiveArrayGet(KConstRef thiz, KInt index) { + const ArrayHeader* array = thiz->array(); + boundsCheck(array, index); + return *PrimitiveArrayAddressOfElementAt(array, index); +} + +} // namespace + +extern "C" { + +// Generated as part of Kotlin standard library. +extern const ObjHeader theEmptyArray; + +// TODO: those must be compiler intrinsics afterwards. + +// Array.kt +OBJ_GETTER(Kotlin_Array_get, KConstRef thiz, KInt index) { + const ArrayHeader* array = thiz->array(); + boundsCheck(array, index); + RETURN_OBJ(*ArrayAddressOfElementAt(array, index)); +} + +void Kotlin_Array_set(KRef thiz, KInt index, KConstRef value) { + ArrayHeader* array = thiz->array(); + boundsCheck(array, index); + mutabilityCheck(thiz); + UpdateHeapRef(ArrayAddressOfElementAt(array, index), value); +} + +KInt Kotlin_Array_getArrayLength(KConstRef thiz) { + const ArrayHeader* array = thiz->array(); + return array->count_; +} + +void Kotlin_Array_fillImpl(KRef thiz, KInt fromIndex, KInt toIndex, KRef value) { + ArrayHeader* array = thiz->array(); + checkRangeIndexes(fromIndex, toIndex, array->count_); + mutabilityCheck(thiz); + for (KInt index = fromIndex; index < toIndex; ++index) { + UpdateHeapRef(ArrayAddressOfElementAt(array, index), value); + } +} + +void Kotlin_Array_copyImpl(KConstRef thiz, KInt fromIndex, + KRef destination, KInt toIndex, KInt count) { + const ArrayHeader* array = thiz->array(); + ArrayHeader* destinationArray = destination->array(); + if (count < 0 || + fromIndex < 0 || static_cast(count) + fromIndex > array->count_ || + toIndex < 0 || static_cast(count) + toIndex > destinationArray->count_) { + ThrowArrayIndexOutOfBoundsException(); + } + mutabilityCheck(destination); + if (fromIndex >= toIndex) { + for (int index = 0; index < count; index++) { + UpdateHeapRef(ArrayAddressOfElementAt(destinationArray, toIndex + index), + *ArrayAddressOfElementAt(array, fromIndex + index)); + } + } else { + for (int index = count - 1; index >= 0; index--) { + UpdateHeapRef(ArrayAddressOfElementAt(destinationArray, toIndex + index), + *ArrayAddressOfElementAt(array, fromIndex + index)); + } + } +} + +// Arrays.kt +OBJ_GETTER0(Kotlin_emptyArray) { + RETURN_OBJ(const_cast(&theEmptyArray)); +} + +KByte Kotlin_ByteArray_get(KConstRef thiz, KInt index) { + const ArrayHeader* array = thiz->array(); + boundsCheck(array, index); + return *ByteArrayAddressOfElementAt(array, index); +} + +void Kotlin_ByteArray_set(KRef thiz, KInt index, KByte value) { + ArrayHeader* array = thiz->array(); + boundsCheck(array, index); + mutabilityCheck(thiz); + *ByteArrayAddressOfElementAt(array, index) = value; +} + +KInt Kotlin_ByteArray_getArrayLength(KConstRef thiz) { + const ArrayHeader* array = thiz->array(); + return array->count_; +} + +KChar Kotlin_ByteArray_getCharAt(KConstRef thiz, KInt index) { + const ArrayHeader* array = thiz->array(); + if (index < 0 || static_cast(index) + 1 >= array->count_) { + ThrowArrayIndexOutOfBoundsException(); + } +#if KONAN_NO_UNALIGNED_ACCESS + const uint8_t* address = reinterpret_cast(ByteArrayAddressOfElementAt(array, index)); + return (static_cast(address[0]) << 0) | (static_cast(address[1]) << 8); +#else + auto result = *reinterpret_cast(ByteArrayAddressOfElementAt(array, index)); +#if __BIG_ENDIAN__ + return __builtin_bswap16(result); +#else + return result; +#endif // __BIG_ENDIAN__ +#endif // KONAN_NO_UNALIGNED_ACCESS +} + +KShort Kotlin_ByteArray_getShortAt(KConstRef thiz, KInt index) { + const ArrayHeader* array = thiz->array(); + if (index < 0 || static_cast(index) + 1 >= array->count_) { + ThrowArrayIndexOutOfBoundsException(); + } +#if KONAN_NO_UNALIGNED_ACCESS + const uint8_t* address = reinterpret_cast(ByteArrayAddressOfElementAt(array, index)); + return (static_cast(address[0]) << 0) | (static_cast(address[1]) << 8); +#else + auto result = *reinterpret_cast(ByteArrayAddressOfElementAt(array, index)); +#if __BIG_ENDIAN__ + return __builtin_bswap16(result); +#else + return result; +#endif // __BIG_ENDIAN__ +#endif // KONAN_NO_UNALIGNED_ACCESS +} + +KInt Kotlin_ByteArray_getIntAt(KConstRef thiz, KInt index) { + const ArrayHeader* array = thiz->array(); + if (index < 0 || static_cast(index) + 3 >= array->count_) { + ThrowArrayIndexOutOfBoundsException(); + } +#if KONAN_NO_UNALIGNED_ACCESS + const uint8_t* address = reinterpret_cast(ByteArrayAddressOfElementAt(array, index)); + return (static_cast(address[0]) << 0) | (static_cast(address[1]) << 8) | + (static_cast(address[2]) << 16) | (static_cast(address[3]) << 24); +#else + auto result = *reinterpret_cast(ByteArrayAddressOfElementAt(array, index)); +#if __BIG_ENDIAN__ + return __builtin_bswap32(result); +#else + return result; +#endif // __BIG_ENDIAN__ +#endif // KONAN_NO_UNALIGNED_ACCESS +} + +KLong Kotlin_ByteArray_getLongAt(KConstRef thiz, KInt index) { + const ArrayHeader* array = thiz->array(); + if (index < 0 || static_cast(index) + 7 >= array->count_) { + ThrowArrayIndexOutOfBoundsException(); + } +#if KONAN_NO_UNALIGNED_ACCESS + const uint8_t* address = reinterpret_cast(ByteArrayAddressOfElementAt(array, index)); + return (static_cast(address[0]) << 0) | (static_cast(address[1]) << 8) | + (static_cast(address[2]) << 16) | (static_cast(address[3]) << 24) | + (static_cast(address[4]) << 32) | (static_cast(address[5]) << 40) | + (static_cast(address[6]) << 48) | (static_cast(address[7]) << 56); +#else + auto result = *reinterpret_cast(ByteArrayAddressOfElementAt(array, index)); +#if __BIG_ENDIAN__ + return __builtin_bswap64(result); +#else + return result; +#endif // __BIG_ENDIAN__ +#endif // KONAN_NO_UNALIGNED_ACCESS +} + +KFloat Kotlin_ByteArray_getFloatAt(KConstRef thiz, KInt index) { + const ArrayHeader* array = thiz->array(); + if (index < 0 || static_cast(index) + 3 >= array->count_) { + ThrowArrayIndexOutOfBoundsException(); + } +#if KONAN_NO_UNALIGNED_ACCESS + const uint8_t* address = reinterpret_cast(ByteArrayAddressOfElementAt(array, index)); + union { + KFloat f; + uint8_t b[4]; + } u; +#if __BIG_ENDIAN__ + u.b[0] = address[3]; + u.b[1] = address[2]; + u.b[2] = address[1]; + u.b[3] = address[0]; +#else + u.b[0] = address[0]; + u.b[1] = address[1]; + u.b[2] = address[2]; + u.b[3] = address[3]; +#endif // __BIG_ENDIAN__ + return u.f; +#else + auto result = *reinterpret_cast(ByteArrayAddressOfElementAt(array, index)); + return result; +#endif // KONAN_NO_UNALIGNED_ACCESS +} + +KDouble Kotlin_ByteArray_getDoubleAt(KConstRef thiz, KInt index) { + const ArrayHeader* array = thiz->array(); + if (index < 0 || static_cast(index) + 7 >= array->count_) { + ThrowArrayIndexOutOfBoundsException(); + } +#if KONAN_NO_UNALIGNED_ACCESS + const uint8_t* address = reinterpret_cast(ByteArrayAddressOfElementAt(array, index)); + union { + KDouble d; + uint8_t b[8]; + } u; +#if __BIG_ENDIAN__ + u.b[0] = address[7]; + u.b[1] = address[6]; + u.b[2] = address[5]; + u.b[3] = address[4]; + u.b[4] = address[3]; + u.b[5] = address[2]; + u.b[6] = address[1]; + u.b[7] = address[0]; +#else + u.b[0] = address[0]; + u.b[1] = address[1]; + u.b[2] = address[2]; + u.b[3] = address[3]; + u.b[4] = address[4]; + u.b[5] = address[5]; + u.b[6] = address[6]; + u.b[7] = address[7]; +#endif // __BIG_ENDIAN__ + return u.d; +#else + return *reinterpret_cast(ByteArrayAddressOfElementAt(array, index)); +#endif // KONAN_NO_UNALIGNED_ACCESS +} + +void Kotlin_ByteArray_setCharAt(KRef thiz, KInt index, KChar value) { + ArrayHeader* array = thiz->array(); + if (index < 0 || static_cast(index) + 1 >= array->count_) { + ThrowArrayIndexOutOfBoundsException(); + } + mutabilityCheck(thiz); +#if KONAN_NO_UNALIGNED_ACCESS + uint8_t* address = reinterpret_cast(ByteArrayAddressOfElementAt(array, index)); + address[0] = (value >> 0) & 0xff; + address[1] = (value >> 8) & 0xff; +#else +#if __BIG_ENDIAN__ + value = __builtin_bswap16(value); +#endif // __BIG_ENDIAN__ + *reinterpret_cast(ByteArrayAddressOfElementAt(array, index)) = value; +#endif // KONAN_NO_UNALIGNED_ACCESS +} + +void Kotlin_ByteArray_setShortAt(KRef thiz, KInt index, KShort value) { + ArrayHeader* array = thiz->array(); + if (index < 0 || static_cast(index) + 1 >= array->count_) { + ThrowArrayIndexOutOfBoundsException(); + } + mutabilityCheck(thiz); +#if KONAN_NO_UNALIGNED_ACCESS + uint8_t* address = reinterpret_cast(ByteArrayAddressOfElementAt(array, index)); + address[0] = (value >> 0) & 0xff; + address[1] = (value >> 8) & 0xff; +#else +#if __BIG_ENDIAN__ + value = __builtin_bswap16(value); +#endif + *reinterpret_cast(ByteArrayAddressOfElementAt(array, index)) = value; +#endif // KONAN_NO_UNALIGNED_ACCESS +} + +void Kotlin_ByteArray_setIntAt(KRef thiz, KInt index, KInt value) { + ArrayHeader* array = thiz->array(); + if (index < 0 || static_cast(index) + 3 >= array->count_) { + ThrowArrayIndexOutOfBoundsException(); + } + mutabilityCheck(thiz); +#if KONAN_NO_UNALIGNED_ACCESS + uint8_t* address = reinterpret_cast(ByteArrayAddressOfElementAt(array, index)); + address[0] = (value >> 0) & 0xff; + address[1] = (value >> 8) & 0xff; + address[2] = (value >> 16) & 0xff; + address[3] = (value >> 24) & 0xff; +#else +#if __BIG_ENDIAN__ + value = __builtin_bswap32(value); +#endif // __BIG_ENDIAN__ + *reinterpret_cast(ByteArrayAddressOfElementAt(array, index)) = value; +#endif // KONAN_NO_UNALIGNED_ACCESS +} + +void Kotlin_ByteArray_setLongAt(KRef thiz, KInt index, KLong value) { + ArrayHeader* array = thiz->array(); + if (index < 0 || static_cast(index) + 7 >= array->count_) { + ThrowArrayIndexOutOfBoundsException(); + } + mutabilityCheck(thiz); +#if KONAN_NO_UNALIGNED_ACCESS + uint8_t* address = reinterpret_cast(ByteArrayAddressOfElementAt(array, index)); + address[0] = (value >> 0) & 0xff; + address[1] = (value >> 8) & 0xff; + address[2] = (value >> 16) & 0xff; + address[3] = (value >> 24) & 0xff; + address[4] = (value >> 32) & 0xff; + address[5] = (value >> 40) & 0xff; + address[6] = (value >> 48) & 0xff; + address[7] = (value >> 56) & 0xff; +#else +#if __BIG_ENDIAN__ + value = __builtin_bswap64(value); +#endif // __BIG_ENDIAN__ + *reinterpret_cast(ByteArrayAddressOfElementAt(array, index)) = value; +#endif // KONAN_NO_UNALIGNED_ACCESS +} + +void Kotlin_ByteArray_setFloatAt(KRef thiz, KInt index, KFloat value) { + ArrayHeader* array = thiz->array(); + if (index < 0 || static_cast(index) + 3 >= array->count_) { + ThrowArrayIndexOutOfBoundsException(); + } + mutabilityCheck(thiz); +#if KONAN_NO_UNALIGNED_ACCESS + uint8_t* address = reinterpret_cast(ByteArrayAddressOfElementAt(array, index)); + union { + KFloat f; + uint8_t b[4]; + } u; + u.f = value; + address[0] = u.b[0]; + address[1] = u.b[1]; + address[2] = u.b[2]; + address[3] = u.b[3]; +#else + *reinterpret_cast(ByteArrayAddressOfElementAt(array, index)) = value; +#endif // KONAN_NO_UNALIGNED_ACCESS +} + +void Kotlin_ByteArray_setDoubleAt(KRef thiz, KInt index, KDouble value) { + ArrayHeader* array = thiz->array(); + if (index < 0 || static_cast(index) + 7 >= array->count_) { + ThrowArrayIndexOutOfBoundsException(); + } + mutabilityCheck(thiz); +#if KONAN_NO_UNALIGNED_ACCESS + uint8_t* address = reinterpret_cast(ByteArrayAddressOfElementAt(array, index)); + union { + KDouble d; + uint8_t b[8]; + } u; + u.d = value; + address[0] = u.b[0]; + address[1] = u.b[1]; + address[2] = u.b[2]; + address[3] = u.b[3]; + address[4] = u.b[4]; + address[5] = u.b[5]; + address[6] = u.b[6]; + address[7] = u.b[7]; +#else + *reinterpret_cast(ByteArrayAddressOfElementAt(array, index)) = value; +#endif // KONAN_NO_UNALIGNED_ACCESS +} + +KChar Kotlin_CharArray_get(KConstRef thiz, KInt index) { + return PrimitiveArrayGet(thiz, index); +} + +void Kotlin_CharArray_set(KRef thiz, KInt index, KChar value) { + PrimitiveArraySet(thiz, index, value); +} + +OBJ_GETTER(Kotlin_CharArray_copyOf, KConstRef thiz, KInt newSize) { + const ArrayHeader* array = thiz->array(); + if (newSize < 0) { + ThrowIllegalArgumentException(); + } + ArrayHeader* result = AllocArrayInstance(array->type_info(), newSize, OBJ_RESULT)->array(); + KInt toCopy = array->count_ < static_cast(newSize) ? array->count_ : newSize; + memcpy( + PrimitiveArrayAddressOfElementAt(result, 0), + PrimitiveArrayAddressOfElementAt(array, 0), + toCopy * sizeof(KChar)); + RETURN_OBJ(result->obj()); +} + +KInt Kotlin_CharArray_getArrayLength(KConstRef thiz) { + const ArrayHeader* array = thiz->array(); + return array->count_; +} + +KShort Kotlin_ShortArray_get(KConstRef thiz, KInt index) { + return PrimitiveArrayGet(thiz, index); +} + +void Kotlin_ShortArray_set(KRef thiz, KInt index, KShort value) { + PrimitiveArraySet(thiz, index, value); +} + +KInt Kotlin_ShortArray_getArrayLength(KConstRef thiz) { + const ArrayHeader* array = thiz->array(); + return array->count_; +} + +KInt Kotlin_IntArray_get(KConstRef thiz, KInt index) { + return PrimitiveArrayGet(thiz, index); +} + +void Kotlin_IntArray_set(KRef thiz, KInt index, KInt value) { + PrimitiveArraySet(thiz, index, value); +} + +KInt Kotlin_IntArray_getArrayLength(KConstRef thiz) { + const ArrayHeader* array = thiz->array(); + return array->count_; +} + +void Kotlin_ByteArray_fillImpl(KRef thiz, KInt fromIndex, KInt toIndex, KByte value) { + fillImpl(thiz, fromIndex, toIndex, value); +} + +void Kotlin_ShortArray_fillImpl(KRef thiz, KInt fromIndex, KInt toIndex, KShort value) { + fillImpl(thiz, fromIndex, toIndex, value); +} + +void Kotlin_CharArray_fillImpl(KRef thiz, KInt fromIndex, KInt toIndex, KChar value) { + fillImpl(thiz, fromIndex, toIndex, value); +} + +void Kotlin_IntArray_fillImpl(KRef thiz, KInt fromIndex, KInt toIndex, KInt value) { + fillImpl(thiz, fromIndex, toIndex, value); +} + +void Kotlin_LongArray_fillImpl(KRef thiz, KInt fromIndex, KInt toIndex, KLong value) { + fillImpl(thiz, fromIndex, toIndex, value); +} + +void Kotlin_FloatArray_fillImpl(KRef thiz, KInt fromIndex, KInt toIndex, KFloat value) { + fillImpl(thiz, fromIndex, toIndex, value); +} + +void Kotlin_DoubleArray_fillImpl(KRef thiz, KInt fromIndex, KInt toIndex, KDouble value) { + fillImpl(thiz, fromIndex, toIndex, value); +} + +void Kotlin_BooleanArray_fillImpl(KRef thiz, KInt fromIndex, KInt toIndex, KBoolean value) { + fillImpl(thiz, fromIndex, toIndex, value); +} + +void Kotlin_ByteArray_copyImpl(KConstRef thiz, KInt fromIndex, + KRef destination, KInt toIndex, KInt count) { + copyImpl(thiz, fromIndex, destination, toIndex, count); +} + +void Kotlin_ShortArray_copyImpl(KConstRef thiz, KInt fromIndex, + KRef destination, KInt toIndex, KInt count) { + copyImpl(thiz, fromIndex, destination, toIndex, count); +} + +void Kotlin_CharArray_copyImpl(KConstRef thiz, KInt fromIndex, + KRef destination, KInt toIndex, KInt count) { + copyImpl(thiz, fromIndex, destination, toIndex, count); +} + +void Kotlin_IntArray_copyImpl(KConstRef thiz, KInt fromIndex, + KRef destination, KInt toIndex, KInt count) { + copyImpl(thiz, fromIndex, destination, toIndex, count); +} + +void Kotlin_LongArray_copyImpl(KConstRef thiz, KInt fromIndex, + KRef destination, KInt toIndex, KInt count) { + copyImpl(thiz, fromIndex, destination, toIndex, count); +} + +void Kotlin_FloatArray_copyImpl(KConstRef thiz, KInt fromIndex, + KRef destination, KInt toIndex, KInt count) { + copyImpl(thiz, fromIndex, destination, toIndex, count); +} + +void Kotlin_DoubleArray_copyImpl(KConstRef thiz, KInt fromIndex, + KRef destination, KInt toIndex, KInt count) { + copyImpl(thiz, fromIndex, destination, toIndex, count); +} + +void Kotlin_BooleanArray_copyImpl(KConstRef thiz, KInt fromIndex, + KRef destination, KInt toIndex, KInt count) { + copyImpl(thiz, fromIndex, destination, toIndex, count); +} + +KLong Kotlin_LongArray_get(KConstRef thiz, KInt index) { + return PrimitiveArrayGet(thiz, index); +} + +void Kotlin_LongArray_set(KRef thiz, KInt index, KLong value) { + PrimitiveArraySet(thiz, index, value); +} + +KInt Kotlin_LongArray_getArrayLength(KConstRef thiz) { + const ArrayHeader* array = thiz->array(); + return array->count_; +} + +KFloat Kotlin_FloatArray_get(KConstRef thiz, KInt index) { + return PrimitiveArrayGet(thiz, index); +} + +void Kotlin_FloatArray_set(KRef thiz, KInt index, KFloat value) { + PrimitiveArraySet(thiz, index, value); +} + +KInt Kotlin_FloatArray_getArrayLength(KConstRef thiz) { + const ArrayHeader* array = thiz->array(); + return array->count_; +} + +KDouble Kotlin_DoubleArray_get(KConstRef thiz, KInt index) { + return PrimitiveArrayGet(thiz, index); +} + +void Kotlin_DoubleArray_set(KRef thiz, KInt index, KDouble value) { + PrimitiveArraySet(thiz, index, value); +} + +KInt Kotlin_DoubleArray_getArrayLength(KConstRef thiz) { + const ArrayHeader* array = thiz->array(); + return array->count_; +} + +KBoolean Kotlin_BooleanArray_get(KConstRef thiz, KInt index) { + return PrimitiveArrayGet(thiz, index); +} + +void Kotlin_BooleanArray_set(KRef thiz, KInt index, KBoolean value) { + PrimitiveArraySet(thiz, index, value); +} + +KInt Kotlin_BooleanArray_getArrayLength(KConstRef thiz) { + const ArrayHeader* array = thiz->array(); + return array->count_; +} + +KNativePtr Kotlin_NativePtrArray_get(KConstRef thiz, KInt index) { + return PrimitiveArrayGet(thiz, index); +} + +void Kotlin_NativePtrArray_set(KRef thiz, KInt index, KNativePtr value) { + PrimitiveArraySet(thiz, index, value); +} + +KInt Kotlin_NativePtrArray_getArrayLength(KConstRef thiz) { + const ArrayHeader* array = thiz->array(); + return array->count_; +} + +OBJ_GETTER(Kotlin_ImmutableBlob_toByteArray, KConstRef thiz, KInt startIndex, KInt endIndex) { + const ArrayHeader* array = thiz->array(); + if (startIndex < 0 || static_cast(endIndex) > array->count_ || startIndex > endIndex) { + ThrowArrayIndexOutOfBoundsException(); + } + KInt count = endIndex - startIndex; + ArrayHeader* result = AllocArrayInstance(theByteArrayTypeInfo, count, OBJ_RESULT)->array(); + memcpy(PrimitiveArrayAddressOfElementAt(result, 0), + PrimitiveArrayAddressOfElementAt(array, startIndex), + count); + RETURN_OBJ(result->obj()); +} + +KNativePtr Kotlin_ImmutableBlob_asCPointerImpl(KRef thiz, KInt offset) { + ArrayHeader* array = thiz->array(); + // We couldn't have created an array bigger than max KInt value. + // So if index is < 0, conversion to an unsigned value would make it bigger + // than the array size. + if (static_cast(offset) > array->count_) { + ThrowArrayIndexOutOfBoundsException(); + } + return PrimitiveArrayAddressOfElementAt(array, offset); +} + +KNativePtr Kotlin_Arrays_getByteArrayAddressOfElement(KRef thiz, KInt index) { + ArrayHeader* array = thiz->array(); + boundsCheck(array, index); + + return AddressOfElementAt(array, index); +} + +KNativePtr Kotlin_Arrays_getCharArrayAddressOfElement (KRef thiz, KInt index) { + ArrayHeader* array = thiz->array(); + boundsCheck(array, index); + + return CharArrayAddressOfElementAt(array, index); +} + +KNativePtr Kotlin_Arrays_getStringAddressOfElement (KRef thiz, KInt index) { + return Kotlin_Arrays_getCharArrayAddressOfElement(thiz, index); +} + +KNativePtr Kotlin_Arrays_getShortArrayAddressOfElement(KRef thiz, KInt index) { + ArrayHeader* array = thiz->array(); + boundsCheck(array, index); + + return AddressOfElementAt(array, index); +} + +KNativePtr Kotlin_Arrays_getIntArrayAddressOfElement(KRef thiz, KInt index) { + ArrayHeader* array = thiz->array(); + boundsCheck(array, index); + + return AddressOfElementAt(array, index); +} + +KNativePtr Kotlin_Arrays_getLongArrayAddressOfElement(KRef thiz, KInt index) { + ArrayHeader* array = thiz->array(); + boundsCheck(array, index); + + return AddressOfElementAt(array, index); +} + +KNativePtr Kotlin_Arrays_getFloatArrayAddressOfElement(KRef thiz, KInt index) { + ArrayHeader* array = thiz->array(); + boundsCheck(array, index); + + return AddressOfElementAt(array, index); +} + +KNativePtr Kotlin_Arrays_getDoubleArrayAddressOfElement(KRef thiz, KInt index) { + ArrayHeader* array = thiz->array(); + boundsCheck(array, index); + + return AddressOfElementAt(array, index); +} + +} // extern "C" diff --git a/kotlin-native/runtime/src/main/cpp/ArraysTest.cpp b/kotlin-native/runtime/src/main/cpp/ArraysTest.cpp new file mode 100644 index 00000000000..978ecdc5d73 --- /dev/null +++ b/kotlin-native/runtime/src/main/cpp/ArraysTest.cpp @@ -0,0 +1,21 @@ +/* + * Copyright 2010-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +#include "gtest/gtest.h" + +#include "Porting.h" + +// TODO: Replace these tests with real ones. + +TEST(ArraysTest, GoodTest) { + konan::consolePrintf("I'm a good test\n"); + EXPECT_EQ(true, true); +} + +TEST(ArraysTest, BadTest) { + GTEST_SKIP(); + konan::consolePrintf("I'm a bad test\n"); + EXPECT_EQ(true, false); +} diff --git a/kotlin-native/runtime/src/main/cpp/Atomic.cpp b/kotlin-native/runtime/src/main/cpp/Atomic.cpp new file mode 100644 index 00000000000..5f059b8a956 --- /dev/null +++ b/kotlin-native/runtime/src/main/cpp/Atomic.cpp @@ -0,0 +1,217 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "Atomic.h" +#include "Common.h" +#include "Exceptions.h" +#include "Memory.h" +#include "Types.h" + +namespace { + +struct AtomicReferenceLayout { + ObjHeader header; + KRef value_; + KInt lock_; + KInt cookie_; +}; + +template struct AtomicPrimitive { + ObjHeader header; + volatile T value_; +}; + +template inline volatile T* getValueLocation(KRef thiz) { + AtomicPrimitive* atomic = reinterpret_cast*>(thiz); + return &atomic->value_; +} + +template void setImpl(KRef thiz, T value) { + volatile T* location = getValueLocation(thiz); + atomicSet(location, value); +} + +template T getImpl(KRef thiz) { + volatile T* location = getValueLocation(thiz); + return atomicGet(location); +} + +template T addAndGetImpl(KRef thiz, T delta) { + volatile T* location = getValueLocation(thiz); + return atomicAdd(location, delta); +} + +template T compareAndSwapImpl(KRef thiz, T expectedValue, T newValue) { + volatile T* location = getValueLocation(thiz); + return compareAndSwap(location, expectedValue, newValue); +} + +template KBoolean compareAndSetImpl(KRef thiz, T expectedValue, T newValue) { + volatile T* location = getValueLocation(thiz); + return compareAndSet(location, expectedValue, newValue); +} + +inline AtomicReferenceLayout* asAtomicReference(KRef thiz) { + return reinterpret_cast(thiz); +} + +} // namespace + +extern "C" { + +KInt Kotlin_AtomicInt_addAndGet(KRef thiz, KInt delta) { + return addAndGetImpl(thiz, delta); +} + +KInt Kotlin_AtomicInt_compareAndSwap(KRef thiz, KInt expectedValue, KInt newValue) { + return compareAndSwapImpl(thiz, expectedValue, newValue); +} + +KBoolean Kotlin_AtomicInt_compareAndSet(KRef thiz, KInt expectedValue, KInt newValue) { + return compareAndSetImpl(thiz, expectedValue, newValue); +} + +void Kotlin_AtomicInt_set(KRef thiz, KInt newValue) { + setImpl(thiz, newValue); +} + +KInt Kotlin_AtomicInt_get(KRef thiz) { + return getImpl(thiz); +} + +KLong Kotlin_AtomicLong_addAndGet(KRef thiz, KLong delta) { + return addAndGetImpl(thiz, delta); +} + +#if KONAN_NO_64BIT_ATOMIC +static int lock64 = 0; +#endif + +KLong Kotlin_AtomicLong_compareAndSwap(KRef thiz, KLong expectedValue, KLong newValue) { +#if KONAN_NO_64BIT_ATOMIC + // Potentially huge performance penalty, but correct. + while (compareAndSwap(&lock64, 0, 1) != 0); + volatile KLong* address = getValueLocation(thiz); + KLong old = *address; + if (old == expectedValue) { + *address = newValue; + } + compareAndSwap(&lock64, 1, 0); + return old; +#else + return compareAndSwapImpl(thiz, expectedValue, newValue); +#endif +} + +KBoolean Kotlin_AtomicLong_compareAndSet(KRef thiz, KLong expectedValue, KLong newValue) { +#if KONAN_NO_64BIT_ATOMIC + // Potentially huge performance penalty, but correct. + KBoolean result = false; + while (compareAndSwap(&lock64, 0, 1) != 0); + volatile KLong* address = getValueLocation(thiz); + KLong old = *address; + if (old == expectedValue) { + result = true; + *address = newValue; + } + compareAndSwap(&lock64, 1, 0); + return result; +#else + return compareAndSetImpl(thiz, expectedValue, newValue); +#endif +} + +void Kotlin_AtomicLong_set(KRef thiz, KLong newValue) { +#if KONAN_NO_64BIT_ATOMIC + // Potentially huge performance penalty, but correct. + while (compareAndSwap(&lock64, 0, 1) != 0); + volatile KLong* address = getValueLocation(thiz); + *address = newValue; + compareAndSwap(&lock64, 1, 0); +#else + setImpl(thiz, newValue); +#endif +} + +KLong Kotlin_AtomicLong_get(KRef thiz) { +#if KONAN_NO_64BIT_ATOMIC + // Potentially huge performance penalty, but correct. + while (compareAndSwap(&lock64, 0, 1) != 0); + volatile KLong* address = getValueLocation(thiz); + KLong value = *address; + compareAndSwap(&lock64, 1, 0); + return value; +#else + return getImpl(thiz); +#endif +} + +KNativePtr Kotlin_AtomicNativePtr_compareAndSwap(KRef thiz, KNativePtr expectedValue, KNativePtr newValue) { + return compareAndSwapImpl(thiz, expectedValue, newValue); +} + +KBoolean Kotlin_AtomicNativePtr_compareAndSet(KRef thiz, KNativePtr expectedValue, KNativePtr newValue) { + return compareAndSetImpl(thiz, expectedValue, newValue); +} + +void Kotlin_AtomicNativePtr_set(KRef thiz, KNativePtr newValue) { + setImpl(thiz, newValue); +} + +KNativePtr Kotlin_AtomicNativePtr_get(KRef thiz) { + return getImpl(thiz); +} + +void Kotlin_AtomicReference_checkIfFrozen(KRef value) { + if (value != nullptr && !isPermanentOrFrozen(value)) { + ThrowInvalidMutabilityException(value); + } +} + +OBJ_GETTER(Kotlin_AtomicReference_compareAndSwap, KRef thiz, KRef expectedValue, KRef newValue) { + Kotlin_AtomicReference_checkIfFrozen(newValue); + // See Kotlin_AtomicReference_get() for explanations, why locking is needed. + AtomicReferenceLayout* ref = asAtomicReference(thiz); + RETURN_RESULT_OF(SwapHeapRefLocked, &ref->value_, expectedValue, newValue, + &ref->lock_, &ref->cookie_); +} + +KBoolean Kotlin_AtomicReference_compareAndSet(KRef thiz, KRef expectedValue, KRef newValue) { + Kotlin_AtomicReference_checkIfFrozen(newValue); + // See Kotlin_AtomicReference_get() for explanations, why locking is needed. + AtomicReferenceLayout* ref = asAtomicReference(thiz); + ObjHolder holder; + auto old = SwapHeapRefLocked(&ref->value_, expectedValue, newValue, + &ref->lock_, &ref->cookie_, holder.slot()); + return old == expectedValue; +} + +void Kotlin_AtomicReference_set(KRef thiz, KRef newValue) { + Kotlin_AtomicReference_checkIfFrozen(newValue); + AtomicReferenceLayout* ref = asAtomicReference(thiz); + SetHeapRefLocked(&ref->value_, newValue, &ref->lock_, &ref->cookie_); +} + +OBJ_GETTER(Kotlin_AtomicReference_get, KRef thiz) { + // Here we must take a lock to prevent race when value, while taken here, is CASed and immediately + // destroyed by an another thread. AtomicReference no longer holds such an object, so if we got + // rescheduled unluckily, between the moment value is read from the field and RC is incremented, + // object may go away. + AtomicReferenceLayout* ref = asAtomicReference(thiz); + RETURN_RESULT_OF(ReadHeapRefLocked, &ref->value_, &ref->lock_, &ref->cookie_); +} + +} // extern "C" diff --git a/kotlin-native/runtime/src/main/cpp/Atomic.h b/kotlin-native/runtime/src/main/cpp/Atomic.h new file mode 100644 index 00000000000..a40d24c023f --- /dev/null +++ b/kotlin-native/runtime/src/main/cpp/Atomic.h @@ -0,0 +1,80 @@ +#ifndef RUNTIME_ATOMIC_H +#define RUNTIME_ATOMIC_H + +#include "Common.h" + +template +ALWAYS_INLINE inline T atomicAdd(volatile T* where, T what) { +#ifndef KONAN_NO_THREADS + return __sync_add_and_fetch(where, what); +#else + return *where += what; +#endif +} + +template +ALWAYS_INLINE inline T compareAndSwap(volatile T* where, T expectedValue, T newValue) { +#ifndef KONAN_NO_THREADS + return __sync_val_compare_and_swap(where, expectedValue, newValue); +#else + T oldValue = *where; + if (oldValue == expectedValue) { + *where = newValue; + } + return oldValue; +#endif +} + +template +ALWAYS_INLINE inline bool compareAndSet(volatile T* where, T expectedValue, T newValue) { +#ifndef KONAN_NO_THREADS + return __sync_bool_compare_and_swap(where, expectedValue, newValue); +#else + T oldValue = *where; + if (oldValue == expectedValue) { + *where = newValue; + return true; + } + return false; +#endif +} + +#pragma clang diagnostic push + +#if (KONAN_ANDROID || KONAN_IOS || KONAN_WATCHOS || KONAN_LINUX) && (KONAN_ARM32 || KONAN_X86 || KONAN_MIPS32 || KONAN_MIPSEL32) +// On 32-bit Android clang generates library calls for "large" atomic operations +// and warns about "significant performance penalty". See more details here: +// https://github.com/llvm/llvm-project/blob/ce56e1a1cc5714f4af5675dd963cfebed766d9e1/clang/lib/CodeGen/CGAtomic.cpp#L775 +// Ignore these warnings: +#pragma clang diagnostic ignored "-Watomic-alignment" +#endif + +template +ALWAYS_INLINE inline void atomicSet(volatile T* where, T what) { +#ifndef KONAN_NO_THREADS + __atomic_store(where, &what, __ATOMIC_SEQ_CST); +#else + *where = what; +#endif +} + +template +ALWAYS_INLINE inline T atomicGet(volatile T* where) { +#ifndef KONAN_NO_THREADS + T what; + __atomic_load(where, &what, __ATOMIC_SEQ_CST); + return what; +#else + return *where; +#endif +} + +#pragma clang diagnostic pop + +static ALWAYS_INLINE inline void synchronize() { +#ifndef KONAN_NO_THREADS + __sync_synchronize(); +#endif +} + +#endif // RUNTIME_ATOMIC_H \ No newline at end of file diff --git a/kotlin-native/runtime/src/main/cpp/Boxing.cpp b/kotlin-native/runtime/src/main/cpp/Boxing.cpp new file mode 100644 index 00000000000..077668166d9 --- /dev/null +++ b/kotlin-native/runtime/src/main/cpp/Boxing.cpp @@ -0,0 +1,121 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "Memory.h" +#include "Types.h" + +// C++ part of box caching. + +template +struct KBox { + ObjHeader header; + const T value; +}; + +// Keep naming of these in sync with codegen part. +extern const KBoolean BOOLEAN_RANGE_FROM; +extern const KBoolean BOOLEAN_RANGE_TO; + +extern const KByte BYTE_RANGE_FROM; +extern const KByte BYTE_RANGE_TO; + +extern const KChar CHAR_RANGE_FROM; +extern const KChar CHAR_RANGE_TO; + +extern const KShort SHORT_RANGE_FROM; +extern const KShort SHORT_RANGE_TO; + +extern const KInt INT_RANGE_FROM; +extern const KInt INT_RANGE_TO; + +extern const KLong LONG_RANGE_FROM; +extern const KLong LONG_RANGE_TO; + +extern KBox BOOLEAN_CACHE[]; +extern KBox BYTE_CACHE[]; +extern KBox CHAR_CACHE[]; +extern KBox SHORT_CACHE[]; +extern KBox INT_CACHE[]; +extern KBox LONG_CACHE[]; + +namespace { + +template +inline bool isInRange(T value, T from, T to) { + return value >= from && value <= to; +} + +template +OBJ_GETTER(getCachedBox, T value, KBox cache[], T from) { + uint64_t index = value - from; + RETURN_OBJ(&cache[index].header); +} + +} // namespace + +extern "C" { + +bool inBooleanBoxCache(KBoolean value) { + return isInRange(value, BOOLEAN_RANGE_FROM, BOOLEAN_RANGE_TO); +} + +bool inByteBoxCache(KByte value) { + return isInRange(value, BYTE_RANGE_FROM, BYTE_RANGE_TO); +} + +bool inCharBoxCache(KChar value) { + return isInRange(value, CHAR_RANGE_FROM, CHAR_RANGE_TO); +} + +bool inShortBoxCache(KShort value) { + return isInRange(value, SHORT_RANGE_FROM, SHORT_RANGE_TO); +} + +bool inIntBoxCache(KInt value) { + return isInRange(value, INT_RANGE_FROM, INT_RANGE_TO); +} + +bool inLongBoxCache(KLong value) { + return isInRange(value, LONG_RANGE_FROM, LONG_RANGE_TO); +} + +OBJ_GETTER(getCachedBooleanBox, KBoolean value) { + RETURN_RESULT_OF(getCachedBox, value, BOOLEAN_CACHE, BOOLEAN_RANGE_FROM); +} + +OBJ_GETTER(getCachedByteBox, KByte value) { + // Remember that KByte can't handle values >= 127 + // so it can't be used as indexing type. + RETURN_RESULT_OF(getCachedBox, value, BYTE_CACHE, BYTE_RANGE_FROM); +} + +OBJ_GETTER(getCachedCharBox, KChar value) { + RETURN_RESULT_OF(getCachedBox, value, CHAR_CACHE, CHAR_RANGE_FROM); +} + +OBJ_GETTER(getCachedShortBox, KShort value) { + RETURN_RESULT_OF(getCachedBox, value, SHORT_CACHE, SHORT_RANGE_FROM); +} + +OBJ_GETTER(getCachedIntBox, KInt value) { + RETURN_RESULT_OF(getCachedBox, value, INT_CACHE, INT_RANGE_FROM); +} + +OBJ_GETTER(getCachedLongBox, KLong value) { + RETURN_RESULT_OF(getCachedBox, value, LONG_CACHE, LONG_RANGE_FROM); +} + +} \ No newline at end of file diff --git a/kotlin-native/runtime/src/main/cpp/Cleaner.cpp b/kotlin-native/runtime/src/main/cpp/Cleaner.cpp new file mode 100644 index 00000000000..5d624433aeb --- /dev/null +++ b/kotlin-native/runtime/src/main/cpp/Cleaner.cpp @@ -0,0 +1,130 @@ +/* + * Copyright 2010-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +#include "Cleaner.h" + +#include "Memory.h" +#include "Runtime.h" +#include "Worker.h" + +// Defined in Cleaner.kt +extern "C" void Kotlin_CleanerImpl_shutdownCleanerWorker(KInt, bool); +extern "C" KInt Kotlin_CleanerImpl_createCleanerWorker(); + +namespace { + +struct CleanerImpl { + ObjHeader header; + KNativePtr cleanerStablePtr; +}; + +constexpr KInt kCleanerWorkerUninitialized = 0; +constexpr KInt kCleanerWorkerInitializing = -1; +constexpr KInt kCleanerWorkerShutdown = -2; + +KInt globalCleanerWorker = kCleanerWorkerUninitialized; + +void disposeCleaner(CleanerImpl* thiz) { + auto worker = atomicGet(&globalCleanerWorker); + RuntimeAssert( + worker != kCleanerWorkerUninitialized && worker != kCleanerWorkerInitializing, + "Cleaner worker must've been initialized by now"); + if (worker == kCleanerWorkerShutdown) { + if (Kotlin_cleanersLeakCheckerEnabled()) { + konan::consoleErrorf( + "Cleaner %p was disposed during program exit\n" + "Use `Platform.isCleanersLeakCheckerActive = false` to avoid this check.\n", + thiz); + RuntimeCheck(false, "Terminating now"); + } + return; + } + + RuntimeAssert(worker > 0, "Cleaner worker must be fully initialized here"); + + bool result = WorkerSchedule(worker, thiz->cleanerStablePtr); + RuntimeAssert(result, "Couldn't find Cleaner worker"); +} + +} // namespace + +RUNTIME_NOTHROW void DisposeCleaner(KRef thiz) { +#if KONAN_NO_EXCEPTIONS + disposeCleaner(reinterpret_cast(thiz)); +#else + try { + disposeCleaner(reinterpret_cast(thiz)); + } catch (...) { + // A trick to terminate with unhandled exception. This will print a stack trace + // and write to iOS crash log. + std::terminate(); + } +#endif +} + +void ShutdownCleaners(bool executeScheduledCleaners) { + KInt worker = 0; + do { + worker = atomicGet(&globalCleanerWorker); + RuntimeAssert(worker != kCleanerWorkerShutdown, "Cleaner worker must not be shutdown twice"); + if (worker == kCleanerWorkerUninitialized) { + if (!compareAndSet(&globalCleanerWorker, kCleanerWorkerUninitialized, kCleanerWorkerShutdown)) { + // Someone is trying to initialize the worker. Try again. + continue; + } + // worker was never initialized. Just return. + return; + } + if (worker == kCleanerWorkerInitializing) { + // Someone is trying to initialize the worker. Try again. + continue; + } + + // Worker is in some proper state. + break; + + } while (true); + + RuntimeAssert(worker > 0, "Cleaner worker must be fully initialized here"); + + atomicSet(&globalCleanerWorker, kCleanerWorkerShutdown); + Kotlin_CleanerImpl_shutdownCleanerWorker(worker, executeScheduledCleaners); + WaitNativeWorkerTermination(worker); +} + +extern "C" KInt Kotlin_CleanerImpl_getCleanerWorker() { + KInt worker = 0; + do { + worker = atomicGet(&globalCleanerWorker); + RuntimeAssert(worker != kCleanerWorkerShutdown, "Cleaner worker must not have been shutdown"); + if (worker == kCleanerWorkerUninitialized) { + if (!compareAndSet(&globalCleanerWorker, kCleanerWorkerUninitialized, kCleanerWorkerInitializing)) { + // Someone else is trying to initialize the worker. Try again. + continue; + } + worker = Kotlin_CleanerImpl_createCleanerWorker(); + if (!compareAndSet(&globalCleanerWorker, kCleanerWorkerInitializing, worker)) { + RuntimeCheck(false, "Someone interrupted worker initializing"); + } + // Worker is initialized. + break; + } + if (worker == kCleanerWorkerInitializing) { + // Someone is trying to initialize the worker. Try again. + continue; + } + + // Worker is in some proper state. + break; + } while (true); + + RuntimeAssert(worker > 0, "Cleaner worker must be fully initialized here"); + + return worker; +} + +void ResetCleanerWorkerForTests() { + atomicSet(&globalCleanerWorker, kCleanerWorkerUninitialized); +} diff --git a/kotlin-native/runtime/src/main/cpp/Cleaner.h b/kotlin-native/runtime/src/main/cpp/Cleaner.h new file mode 100644 index 00000000000..3b5b7f8f5fc --- /dev/null +++ b/kotlin-native/runtime/src/main/cpp/Cleaner.h @@ -0,0 +1,20 @@ +/* + * Copyright 2010-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +#ifndef RUNTIME_CLEANER_H +#define RUNTIME_CLEANER_H + +#include "Common.h" +#include "Types.h" + +RUNTIME_NOTHROW void DisposeCleaner(KRef thiz); + +void ShutdownCleaners(bool executeScheduledCleaners); + +extern "C" KInt Kotlin_CleanerImpl_getCleanerWorker(); + +void ResetCleanerWorkerForTests(); + +#endif // RUNTIME_CLEANER_H diff --git a/kotlin-native/runtime/src/main/cpp/CleanerTest.cpp b/kotlin-native/runtime/src/main/cpp/CleanerTest.cpp new file mode 100644 index 00000000000..4861b9b455f --- /dev/null +++ b/kotlin-native/runtime/src/main/cpp/CleanerTest.cpp @@ -0,0 +1,80 @@ +/* + * Copyright 2010-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +#include "Cleaner.h" + +#include +#include + +#include "gmock/gmock.h" +#include "gtest/gtest.h" + +#include "Atomic.h" +#include "TestSupportCompilerGenerated.hpp" + +using testing::_; + +// TODO: Also test disposal. (This requires extracting Worker interface) + +TEST(CleanerTest, ConcurrentCreation) { + ResetCleanerWorkerForTests(); + + constexpr int threadCount = 100; + constexpr KInt workerId = 42; + + auto createCleanerWorkerMock = ScopedCreateCleanerWorkerMock(); + + EXPECT_CALL(*createCleanerWorkerMock, Call()).Times(1).WillOnce(testing::Return(workerId)); + + int startedThreads = 0; + bool allowRunning = false; + std::vector> futures; + for (int i = 0; i < threadCount; ++i) { + auto future = std::async(std::launch::async, [&startedThreads, &allowRunning]() { + atomicAdd(&startedThreads, 1); + while (!atomicGet(&allowRunning)) { + } + return Kotlin_CleanerImpl_getCleanerWorker(); + }); + futures.push_back(std::move(future)); + } + while (atomicGet(&startedThreads) != threadCount) { + } + atomicSet(&allowRunning, true); + std::vector values; + for (auto& future : futures) { + values.push_back(future.get()); + } + + ASSERT_THAT(values.size(), threadCount); + EXPECT_THAT(values, testing::Each(workerId)); +} + +TEST(CleanerTest, ShutdownWithoutCreation) { + ResetCleanerWorkerForTests(); + + auto createCleanerWorkerMock = ScopedCreateCleanerWorkerMock(); + auto shutdownCleanerWorkerMock = ScopedShutdownCleanerWorkerMock(); + + EXPECT_CALL(*createCleanerWorkerMock, Call()).Times(0); + EXPECT_CALL(*shutdownCleanerWorkerMock, Call(_, _)).Times(0); + ShutdownCleaners(true); +} + +TEST(CleanerTest, ShutdownWithCreation) { + ResetCleanerWorkerForTests(); + + constexpr KInt workerId = 42; + constexpr bool executeScheduledCleaners = true; + + auto createCleanerWorkerMock = ScopedCreateCleanerWorkerMock(); + auto shutdownCleanerWorkerMock = ScopedShutdownCleanerWorkerMock(); + + EXPECT_CALL(*createCleanerWorkerMock, Call()).WillOnce(testing::Return(workerId)); + Kotlin_CleanerImpl_getCleanerWorker(); + + EXPECT_CALL(*shutdownCleanerWorkerMock, Call(workerId, executeScheduledCleaners)); + ShutdownCleaners(executeScheduledCleaners); +} diff --git a/kotlin-native/runtime/src/main/cpp/Common.h b/kotlin-native/runtime/src/main/cpp/Common.h new file mode 100644 index 00000000000..71b44af940e --- /dev/null +++ b/kotlin-native/runtime/src/main/cpp/Common.h @@ -0,0 +1,42 @@ +/* + * Copyright 2010-2017 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef RUNTIME_COMMON_H +#define RUNTIME_COMMON_H + +#define RUNTIME_NOTHROW __attribute__((nothrow)) +#define RUNTIME_NORETURN __attribute__((noreturn)) +#define RUNTIME_CONST __attribute__((const)) +#define RUNTIME_PURE __attribute__((pure)) +#define RUNTIME_USED __attribute__((used)) +#define RUNTIME_WEAK __attribute__((weak)) + +#define ALWAYS_INLINE __attribute__((always_inline)) +#define NO_INLINE __attribute__((noinline)) + +#if KONAN_NO_THREADS +#define THREAD_LOCAL_VARIABLE +#else +#define THREAD_LOCAL_VARIABLE __thread +#endif + +#define ARRAY_SIZE(a) (sizeof(a) / sizeof(a[0])) + +#if KONAN_OBJC_INTEROP +#define KONAN_TYPE_INFO_HAS_WRITABLE_PART 1 +#endif + +#endif // RUNTIME_COMMON_H diff --git a/kotlin-native/runtime/src/main/cpp/CompilerExport.cpp b/kotlin-native/runtime/src/main/cpp/CompilerExport.cpp new file mode 100644 index 00000000000..de52a26e227 --- /dev/null +++ b/kotlin-native/runtime/src/main/cpp/CompilerExport.cpp @@ -0,0 +1,44 @@ +/* + * Copyright 2010-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +#include "Memory.h" + +namespace { + +template +T defaultValue() { + return T(); +} + +template +void ensureUsed(Ret (*f)(Args...)) { + f(defaultValue()...); +} + +} // namespace + +// This is a hack to force clang to emit possibly unused declarations. +// TODO: Make sure this function gets DCE'd in the final binary. +// TODO: Should be done with some sort of annotation on the declaration. +void EnsureDeclarationsEmitted() { + ensureUsed(AllocInstance); + ensureUsed(AllocArrayInstance); + ensureUsed(InitInstance); + ensureUsed(InitSharedInstance); + ensureUsed(UpdateHeapRef); + ensureUsed(UpdateStackRef); + ensureUsed(UpdateReturnRef); + ensureUsed(ZeroHeapRef); + ensureUsed(ZeroArrayRefs); + ensureUsed(EnterFrame); + ensureUsed(LeaveFrame); + ensureUsed(AddTLSRecord); + ensureUsed(ClearTLSRecord); + ensureUsed(LookupTLS); + ensureUsed(MutationCheck); + ensureUsed(CheckLifetimesConstraint); + ensureUsed(FreezeSubgraph); + ensureUsed(FreezeSubgraph); +} diff --git a/kotlin-native/runtime/src/main/cpp/Console.cpp b/kotlin-native/runtime/src/main/cpp/Console.cpp new file mode 100644 index 00000000000..e4b33ca42c8 --- /dev/null +++ b/kotlin-native/runtime/src/main/cpp/Console.cpp @@ -0,0 +1,62 @@ +/* + * Copyright 2010-2017 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#include "KAssert.h" +#include "Memory.h" +#include "Natives.h" +#include "KString.h" +#include "Porting.h" +#include "Types.h" +#include "Exceptions.h" + +#include "utf8.h" + +extern "C" { + +// io/Console.kt +void Kotlin_io_Console_print(KString message) { + if (message->type_info() != theStringTypeInfo) { + ThrowClassCastException(message->obj(), theStringTypeInfo); + } + // TODO: system stdout must be aware about UTF-8. + const KChar* utf16 = CharArrayAddressOfElementAt(message, 0); + KStdString utf8; + utf8.reserve(message->count_); + // Replace incorrect sequences with a default codepoint (see utf8::with_replacement::default_replacement) + utf8::with_replacement::utf16to8(utf16, utf16 + message->count_, back_inserter(utf8)); + konan::consoleWriteUtf8(utf8.c_str(), utf8.size()); +} + +void Kotlin_io_Console_println(KString message) { + Kotlin_io_Console_print(message); +#ifndef KONAN_ANDROID + // On Android single print produces logcat entry, so no need in linefeed. + Kotlin_io_Console_println0(); +#endif +} + +void Kotlin_io_Console_println0() { + konan::consoleWriteUtf8("\n", 1); +} + +OBJ_GETTER0(Kotlin_io_Console_readLine) { + char data[4096]; + if (konan::consoleReadUtf8(data, sizeof(data)) < 0) { + RETURN_OBJ(nullptr); + } + RETURN_RESULT_OF(CreateStringFromCString, data); +} + +} // extern "C" diff --git a/kotlin-native/runtime/src/main/cpp/DoubleConversions.h b/kotlin-native/runtime/src/main/cpp/DoubleConversions.h new file mode 100644 index 00000000000..0fe6a5c5380 --- /dev/null +++ b/kotlin-native/runtime/src/main/cpp/DoubleConversions.h @@ -0,0 +1,63 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef RUNTIME_DOUBLECONVERSIONS_H +#define RUNTIME_DOUBLECONVERSIONS_H + +#include "Types.h" + +namespace { + +typedef union { + KLong l; + KDouble d; +} DoubleAlias; + +typedef union { + KInt i; + KFloat f; +} FloatAlias; + +} + +inline KDouble bitsToDouble(KLong bits) { + DoubleAlias alias; + alias.l = bits; + return alias.d; +} + +inline KLong doubleToBits(KDouble value) { + DoubleAlias alias; + alias.d = value; + return alias.l; +} + +inline KFloat bitsToFloat(KInt bits) { + FloatAlias alias; + alias.i = bits; + return alias.f; +} + +inline KInt floatToBits(KFloat value) { + FloatAlias alias; + alias.f = value; + return alias.i; +} + +extern "C" KInt doubleUpper(KDouble value); +extern "C" KInt doubleLower(KDouble value); + +#endif // RUNTIME_DOUBLECONVERSIONS_H diff --git a/kotlin-native/runtime/src/main/cpp/Exceptions.cpp b/kotlin-native/runtime/src/main/cpp/Exceptions.cpp new file mode 100644 index 00000000000..29501c5d49c --- /dev/null +++ b/kotlin-native/runtime/src/main/cpp/Exceptions.cpp @@ -0,0 +1,347 @@ +/* + * Copyright 2010-2017 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#include +#include +#include +#include + +#include +#include + +#if KONAN_NO_EXCEPTIONS +#define OMIT_BACKTRACE 1 +#endif +#ifndef OMIT_BACKTRACE +#if USE_GCC_UNWIND +// GCC unwinder for backtrace. +#include +#else +// Glibc backtrace() function. +#include +#endif +#endif // OMIT_BACKTRACE + +#include "KAssert.h" +#include "Exceptions.h" +#include "ExecFormat.h" +#include "Memory.h" +#include "Natives.h" +#include "KString.h" +#include "SourceInfo.h" +#include "Types.h" +#include "Utils.h" +#include "ObjCExceptions.h" + +namespace { + +// RuntimeUtils.kt +extern "C" void ReportUnhandledException(KRef throwable); +extern "C" void ExceptionReporterLaunchpad(KRef reporter, KRef throwable); + +KRef currentUnhandledExceptionHook = nullptr; +int32_t currentUnhandledExceptionHookLock = 0; +int32_t currentUnhandledExceptionHookCookie = 0; + +#if USE_GCC_UNWIND +struct Backtrace { + Backtrace(int count, int skip) : index(0), skipCount(skip) { + uint32_t size = count - skipCount; + if (size < 0) { + size = 0; + } + auto result = AllocArrayInstance(theNativePtrArrayTypeInfo, size, arrayHolder.slot()); + // TODO: throw cached OOME? + RuntimeCheck(result != nullptr, "Cannot create backtrace array"); + } + + void setNextElement(_Unwind_Ptr element) { + Kotlin_NativePtrArray_set(obj(), index++, (KNativePtr) element); + } + + ObjHeader* obj() { return arrayHolder.obj(); } + + int index; + int skipCount; + ObjHolder arrayHolder; +}; + +_Unwind_Reason_Code depthCountCallback( + struct _Unwind_Context * context, void* arg) { + int* result = reinterpret_cast(arg); + (*result)++; + return _URC_NO_REASON; +} + +_Unwind_Reason_Code unwindCallback( + struct _Unwind_Context* context, void* arg) { + Backtrace* backtrace = reinterpret_cast(arg); + if (backtrace->skipCount > 0) { + backtrace->skipCount--; + return _URC_NO_REASON; + } + +#if (__MINGW32__ || __MINGW64__) + _Unwind_Ptr address = _Unwind_GetRegionStart(context); +#else + _Unwind_Ptr address = _Unwind_GetIP(context); +#endif + backtrace->setNextElement(address); + + return _URC_NO_REASON; +} +#endif + +THREAD_LOCAL_VARIABLE bool disallowSourceInfo = false; + +SourceInfo getSourceInfo(KConstRef stackTrace, int index) { + return disallowSourceInfo + ? SourceInfo { .fileName = nullptr, .lineNumber = -1, .column = -1 } + : Kotlin_getSourceInfo(*PrimitiveArrayAddressOfElementAt(stackTrace->array(), index)); +} + +} // namespace + +// TODO: this implementation is just a hack, e.g. the result is inexact; +// however it is better to have an inexact stacktrace than not to have any. +NO_INLINE OBJ_GETTER0(Kotlin_getCurrentStackTrace) { +#if OMIT_BACKTRACE + return AllocArrayInstance(theNativePtrArrayTypeInfo, 0, OBJ_RESULT); +#else + // Skips first 2 elements as irrelevant: this function and primary Throwable constructor. + constexpr int kSkipFrames = 2; +#if USE_GCC_UNWIND + int depth = 0; + _Unwind_Backtrace(depthCountCallback, &depth); + Backtrace result(depth, kSkipFrames); + if (result.obj()->array()->count_ > 0) { + _Unwind_Backtrace(unwindCallback, &result); + } + RETURN_OBJ(result.obj()); +#else + const int maxSize = 32; + void* buffer[maxSize]; + + int size = backtrace(buffer, maxSize); + if (size < kSkipFrames) + return AllocArrayInstance(theNativePtrArrayTypeInfo, 0, OBJ_RESULT); + + ObjHolder resultHolder; + ObjHeader* result = AllocArrayInstance(theNativePtrArrayTypeInfo, size - kSkipFrames, resultHolder.slot()); + for (int index = kSkipFrames; index < size; ++index) { + Kotlin_NativePtrArray_set(result, index - kSkipFrames, buffer[index]); + } + RETURN_OBJ(result); +#endif +#endif // !OMIT_BACKTRACE +} + +OBJ_GETTER(GetStackTraceStrings, KConstRef stackTrace) { +#if OMIT_BACKTRACE + ObjHeader* result = AllocArrayInstance(theArrayTypeInfo, 1, OBJ_RESULT); + ObjHolder holder; + CreateStringFromCString("", holder.slot()); + UpdateHeapRef(ArrayAddressOfElementAt(result->array(), 0), holder.obj()); + return result; +#else + uint32_t size = stackTrace->array()->count_; + ObjHolder resultHolder; + ObjHeader* strings = AllocArrayInstance(theArrayTypeInfo, size, resultHolder.slot()); +#if USE_GCC_UNWIND + for (uint32_t index = 0; index < size; ++index) { + KNativePtr address = Kotlin_NativePtrArray_get(stackTrace, index); + char symbol[512]; + if (!AddressToSymbol((const void*) address, symbol, sizeof(symbol))) { + // Make empty string: + symbol[0] = '\0'; + } + char line[512]; + konan::snprintf(line, sizeof(line) - 1, "%s (%p)", symbol, (void*)(intptr_t)address); + ObjHolder holder; + CreateStringFromCString(line, holder.slot()); + UpdateHeapRef(ArrayAddressOfElementAt(strings->array(), index), holder.obj()); + } +#else + if (size > 0) { + char **symbols = backtrace_symbols(PrimitiveArrayAddressOfElementAt(stackTrace->array(), 0), size); + RuntimeCheck(symbols != nullptr, "Not enough memory to retrieve the stacktrace"); + + for (uint32_t index = 0; index < size; ++index) { + auto sourceInfo = getSourceInfo(stackTrace, index); + const char* symbol = symbols[index]; + const char* result; + char line[1024]; + if (sourceInfo.fileName != nullptr) { + if (sourceInfo.lineNumber != -1) { + konan::snprintf(line, sizeof(line) - 1, "%s (%s:%d:%d)", + symbol, sourceInfo.fileName, sourceInfo.lineNumber, sourceInfo.column); + } else { + konan::snprintf(line, sizeof(line) - 1, "%s (%s:)", symbol, sourceInfo.fileName); + } + result = line; + } else { + result = symbol; + } + ObjHolder holder; + CreateStringFromCString(result, holder.slot()); + UpdateHeapRef(ArrayAddressOfElementAt(strings->array(), index), holder.obj()); + } + // Not konan::free. Used to free memory allocated in backtrace_symbols where malloc is used. + free(symbols); + } +#endif + RETURN_OBJ(strings); +#endif // !OMIT_BACKTRACE +} + +void ThrowException(KRef exception) { + RuntimeAssert(exception != nullptr && IsInstance(exception, theThrowableTypeInfo), + "Throwing something non-throwable"); +#if KONAN_NO_EXCEPTIONS + PrintThrowable(exception); + RuntimeCheck(false, "Exceptions unsupported"); +#else + throw ExceptionObjHolder(exception); +#endif +} + +OBJ_GETTER(Kotlin_setUnhandledExceptionHook, KRef hook) { + RETURN_RESULT_OF(SwapHeapRefLocked, + ¤tUnhandledExceptionHook, currentUnhandledExceptionHook, hook, ¤tUnhandledExceptionHookLock, + ¤tUnhandledExceptionHookCookie); +} + +void OnUnhandledException(KRef throwable) { + ObjHolder handlerHolder; + auto* handler = SwapHeapRefLocked(¤tUnhandledExceptionHook, currentUnhandledExceptionHook, nullptr, + ¤tUnhandledExceptionHookLock, ¤tUnhandledExceptionHookCookie, handlerHolder.slot()); + if (handler == nullptr) { + ReportUnhandledException(throwable); + } else { + ExceptionReporterLaunchpad(handler, throwable); + } +} + +namespace { + +class { + /** + * Timeout 5 sec for concurrent (second) terminate attempt to give a chance the first one to finish. + * If the terminate handler hangs for 5 sec it is probably fatally broken, so let's do abnormal _Exit in that case. + */ + unsigned int timeoutSec = 5; + int terminatingFlag = 0; + public: + template RUNTIME_NORETURN void operator()(Fun block) { + if (compareAndSet(&terminatingFlag, 0, 1)) { + block(); + // block() is supposed to be NORETURN, otherwise go to normal abort() + konan::abort(); + } else { + sleep(timeoutSec); + // We come here when another terminate handler hangs for 5 sec, that looks fatally broken. Go to forced exit now. + } + _Exit(EXIT_FAILURE); // force exit + } +} concurrentTerminateWrapper; + +//! Process exception hook (if any) or just printStackTrace + write crash log +void processUnhandledKotlinException(KRef throwable) { + OnUnhandledException(throwable); +#if KONAN_REPORT_BACKTRACE_TO_IOS_CRASH_LOG + ReportBacktraceToIosCrashLog(throwable); +#endif +} + +} // namespace + +RUNTIME_NORETURN void TerminateWithUnhandledException(KRef throwable) { + concurrentTerminateWrapper([=]() { + processUnhandledKotlinException(throwable); + konan::abort(); + }); +} + +// Some libstdc++-based targets has limited support for std::current_exception and other C++11 functions. +// This restriction can be lifted later when toolchains will be updated. +#if KONAN_HAS_CXX11_EXCEPTION_FUNCTIONS + +namespace { +class TerminateHandler { + + // In fact, it's safe to call my_handler directly from outside: it will do the job and then invoke original handler, + // even if it has not been initialized yet. So one may want to make it public and/or not the class member + RUNTIME_NORETURN static void kotlinHandler() { + concurrentTerminateWrapper([]() { + if (auto currentException = std::current_exception()) { + try { + std::rethrow_exception(currentException); + } catch (ExceptionObjHolder& e) { + processUnhandledKotlinException(e.obj()); + konan::abort(); + } catch (...) { + // Not a Kotlin exception - call default handler + instance().queuedHandler_(); + } + } + // Come here in case of direct terminate() call or unknown exception - go to default terminate handler. + instance().queuedHandler_(); + }); + } + + using QH = __attribute__((noreturn)) void(*)(); + QH queuedHandler_; + + /// Use machinery like Meyers singleton to provide thread safety + TerminateHandler() + : queuedHandler_((QH)std::set_terminate(kotlinHandler)) {} + + static TerminateHandler& instance() { + static TerminateHandler singleton [[clang::no_destroy]]; + return singleton; + } + + // Copy, move and assign would be safe, but not much useful, so let's delete all (rule of 5) + TerminateHandler(const TerminateHandler&) = delete; + TerminateHandler(TerminateHandler&&) = delete; + TerminateHandler& operator=(const TerminateHandler&) = delete; + TerminateHandler& operator=(TerminateHandler&&) = delete; + // Dtor might be in use to restore original handler. However, consequent install + // will not reconstruct handler anyway, so let's keep dtor deleted to avoid confusion. + ~TerminateHandler() = delete; +public: + /// First call will do the job, all consequent will do nothing. + static void install() { + instance(); // Use side effect of warming up + } +}; +} // anon namespace + +// Use one public function to limit access to the class declaration +void SetKonanTerminateHandler() { + TerminateHandler::install(); +} + +#else // KONAN_OBJC_INTEROP + +void SetKonanTerminateHandler() { + // Nothing to do. +} + +#endif // KONAN_OBJC_INTEROP + +void DisallowSourceInfo() { + disallowSourceInfo = true; +} diff --git a/kotlin-native/runtime/src/main/cpp/Exceptions.h b/kotlin-native/runtime/src/main/cpp/Exceptions.h new file mode 100644 index 00000000000..551b2d89bcf --- /dev/null +++ b/kotlin-native/runtime/src/main/cpp/Exceptions.h @@ -0,0 +1,77 @@ +/* + * Copyright 2010-2017 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef RUNTIME_EXCEPTIONS_H +#define RUNTIME_EXCEPTIONS_H + +#include "Types.h" + +#ifdef __cplusplus +extern "C" { +#endif + +// Returns current stacktrace as Array. +OBJ_GETTER0(Kotlin_getCurrentStackTrace); + +OBJ_GETTER(GetStackTraceStrings, KConstRef stackTrace); + +OBJ_GETTER(Kotlin_setUnhandledExceptionHook, KRef hook); + +// Throws arbitrary exception. +void ThrowException(KRef exception); + +void OnUnhandledException(KRef throwable); + +RUNTIME_NORETURN void TerminateWithUnhandledException(KRef exception); + +void SetKonanTerminateHandler(); + +// The functions below are implemented in Kotlin (at package kotlin.native.internal). + +// Throws null pointer exception. Context is evaluated from caller's address. +void RUNTIME_NORETURN ThrowNullPointerException(); +// Throws array index out of bounds exception. +// Context is evaluated from caller's address. +void RUNTIME_NORETURN ThrowArrayIndexOutOfBoundsException(); +// Throws class cast exception. +void RUNTIME_NORETURN ThrowClassCastException(const ObjHeader* instance, const TypeInfo* type_info); +// Throws arithmetic exception. +void RUNTIME_NORETURN ThrowArithmeticException(); +// Throws number format exception. +void RUNTIME_NORETURN ThrowNumberFormatException(); +// Throws out of memory error. +void RUNTIME_NORETURN ThrowOutOfMemoryError(); +// Throws not implemented error. +void RUNTIME_NORETURN ThrowNotImplementedError(); +// Throws character coding exception (used in UTF8/UTF16 conversions). +void RUNTIME_NORETURN ThrowCharacterCodingException(); +void RUNTIME_NORETURN ThrowIllegalArgumentException(); +void RUNTIME_NORETURN ThrowIllegalStateException(); +void RUNTIME_NORETURN ThrowInvalidMutabilityException(KConstRef where); +void RUNTIME_NORETURN ThrowIncorrectDereferenceException(); +void RUNTIME_NORETURN ThrowIllegalObjectSharingException(KConstNativePtr typeInfo, KConstNativePtr address); +void RUNTIME_NORETURN ThrowFreezingException(KRef toFreeze, KRef blocker); +// Prints out message of Throwable. +void PrintThrowable(KRef); + +#ifdef __cplusplus +} // extern "C" +#endif + +// It's not always safe to extract SourceInfo during unhandled exception termination. +void DisallowSourceInfo(); + +#endif // RUNTIME_NAMES_H diff --git a/kotlin-native/runtime/src/main/cpp/ExecFormat.cpp b/kotlin-native/runtime/src/main/cpp/ExecFormat.cpp new file mode 100644 index 00000000000..d9f71f54417 --- /dev/null +++ b/kotlin-native/runtime/src/main/cpp/ExecFormat.cpp @@ -0,0 +1,333 @@ +/* + * Copyright 2010-2017 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + + +#include "ExecFormat.h" +#include "Types.h" + +#if USE_ELF_SYMBOLS + +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include "KAssert.h" + +namespace { + +#if !defined(ELFSIZE) +#error "Define ELFSIZE to 32 or 64" +#endif + +#if ELFSIZE == 32 +#define Elf_Ehdr Elf32_Ehdr +#define Elf_Shdr Elf32_Shdr +#define Elf_Sym Elf32_Sym +#elif ELFSIZE == 64 +#define Elf_Ehdr Elf64_Ehdr +#define Elf_Shdr Elf64_Shdr +#define Elf_Sym Elf64_Sym +#else +#error "Impossible ELFSIZE" +#endif + +struct SymRecord { + Elf_Sym* symtabBegin; + Elf_Sym* symtabEnd; + char* strtab; +}; + +typedef KStdVector SymRecordList; + +SymRecordList* symbols = nullptr; + +// Unfortunately, symbol tables are stored in ELF sections not mapped +// during regular execution, so we have to map binary ourselves. +Elf_Ehdr* findElfHeader() { + int fd = open("/proc/self/exe", O_RDONLY); + if (fd < 0) return nullptr; + struct stat fd_stat; + if (fstat(fd, &fd_stat) < 0) return nullptr; + void* result = mmap(nullptr, fd_stat.st_size, PROT_READ, MAP_PRIVATE, fd, 0); + if (result == MAP_FAILED) return nullptr; + return (Elf_Ehdr*)result; +} + +void initSymbols() { + RuntimeAssert(symbols == nullptr, "Init twice"); + symbols = konanConstructInstance(); + Elf_Ehdr* ehdr = findElfHeader(); + if (ehdr == nullptr) return; + RuntimeAssert(strncmp((const char*)ehdr->e_ident, ELFMAG, SELFMAG) == 0, "Must be an ELF"); + char* mapAddress = (char*)ehdr; + Elf_Shdr* shdr = (Elf_Shdr*)(mapAddress + ehdr->e_shoff); + for (int i = 0; i < ehdr->e_shnum; i++) { + if (shdr[i].sh_type == SHT_SYMTAB) { // Static symbol table. + SymRecord record; + record.symtabBegin = (Elf_Sym*)(mapAddress + shdr[i].sh_offset); + record.symtabEnd = (Elf_Sym*)((char*)record.symtabBegin + shdr[i].sh_size); + record.strtab = (char *)(mapAddress + shdr[shdr[i].sh_link].sh_offset); + symbols->push_back(record); + } + if (shdr[i].sh_type == SHT_DYNSYM) { // Dynamic symbol table. + SymRecord record; + record.symtabBegin = (Elf_Sym*)(mapAddress + shdr[i].sh_offset); + record.symtabEnd = (Elf_Sym*)((char*)record.symtabBegin + shdr[i].sh_size); + record.strtab = (char*)(mapAddress + shdr[shdr[i].sh_link].sh_offset); + symbols->push_back(record); + } + } +} + +const char* addressToSymbol(const void* address) { + if (address == nullptr) return nullptr; + + // First, look up in dynamically loaded symbols. + Dl_info info; + if (dladdr(address, &info) != 0 && info.dli_sname != nullptr) { + return info.dli_sname; + } + + // Otherwise, consult symbol table of the file. + if (symbols == nullptr) { + initSymbols(); + } + + unsigned long addressValue = (unsigned long)address; + + for (auto record : *symbols) { + auto begin = record.symtabBegin; + auto end = record.symtabEnd; + while (begin < end) { + // st_value is load address adjusted. + if (addressValue >= begin->st_value && addressValue < begin->st_value + begin->st_size) { + return &record.strtab[begin->st_name]; + } + begin++; + } + } + return nullptr; +} + +} // namespace + +extern "C" bool AddressToSymbol(const void* address, char* resultBuffer, size_t resultBufferSize) { + const char* result = addressToSymbol(address); + if (result == nullptr) { + return false; + } else { + strncpy(resultBuffer, result, resultBufferSize); + resultBuffer[resultBufferSize - 1] = '\0'; + return true; + } +} + +#elif USE_PE_COFF_SYMBOLS + +#include +#include +#include + +#include "KAssert.h" + +namespace { + +static void* mapModuleFile(HMODULE hModule) { + DWORD bufferLength = 64; + wchar_t* buffer = nullptr; + for (;;) { + auto newBuffer = (wchar_t*)konanAllocMemory(sizeof(wchar_t) * bufferLength); + RuntimeAssert(newBuffer != nullptr, "Out of memory"); + if (buffer != nullptr) { + konanFreeMemory(buffer); + } + buffer = newBuffer; + + DWORD res = GetModuleFileNameW(hModule, buffer, bufferLength); + if (res != 0 && res < bufferLength) { + break; + } + const int MAX_BUFFER_SIZE = 32768; // Max path length + 1. + if (res == bufferLength && bufferLength < MAX_BUFFER_SIZE) { + // Buffer is too small, continue: + bufferLength *= 2; + continue; + } + + // Invalid result. + konanFreeMemory(buffer); + return nullptr; + } + + HANDLE hFile = CreateFileW( + /* lpFileName = */ buffer, + /* dwDesiredAccess = */ GENERIC_READ, + /* dwShareMode = */ FILE_SHARE_READ, + /* lpSecurityAttributes = */ nullptr, + /* dwCreationDisposition = */ OPEN_EXISTING, + /* dwFlagsAndAttributes = */ FILE_ATTRIBUTE_NORMAL, + /* hTemplateFile = */ nullptr + ); + konanFreeMemory(buffer); + if (hFile == INVALID_HANDLE_VALUE) { + // Can't open module file. + return nullptr; + } + + HANDLE hFileMappingObject = CreateFileMapping( + hFile, + /* lpAttributes = */ nullptr, + /* flProtect = */ PAGE_READONLY, + /* dwMaximumSizeHigh = */ 0, + /* dwMaximumSizeLow = */ 0, + /* lpName = */ nullptr + ); + if (hFileMappingObject == nullptr) { + // Can't create file mapping. + CloseHandle(hFile); + return nullptr; + } + + LPVOID mapAddress = MapViewOfFile( + hFileMappingObject, + /* dwDesiredAccess = */ FILE_MAP_READ, + /* dwFileOffsetHigh = */ 0, + /* dwFileOffsetLow = */ 0, + /* dwNumberOfBytesToMap = */ 0 + ); + if (mapAddress == nullptr) { + // Failed to create map view. + CloseHandle(hFileMappingObject); + CloseHandle(hFile); + return nullptr; + } + + return mapAddress; +} + +class SymbolTable { + private: + + char* imageBase = nullptr; + IMAGE_SECTION_HEADER* sectionHeaders = nullptr; + IMAGE_SYMBOL* symbols = nullptr; + DWORD numberOfSymbols = 0; + + // Note: it doesn't free resources yet. + ~SymbolTable() {} + + static const int SYMBOL_SHORT_NAME_LENGTH = 8; + + void getSymbolName(IMAGE_SYMBOL* sym, char* resultBuffer, size_t resultBufferSize) { + if (sym->N.Name.Short != 0) { + // ShortName is not zero-terminated if its length exactly equals SYMBOL_SHORT_NAME_LENGTH. + // Copy it to the buffer and zero-terminate explicitly: + size_t bytesToCopy = SYMBOL_SHORT_NAME_LENGTH; + if (bytesToCopy > resultBufferSize - 1) bytesToCopy = resultBufferSize - 1; + + memcpy(resultBuffer, sym->N.ShortName, bytesToCopy); + resultBuffer[bytesToCopy] = '\0'; + } else { + const char* strTable = (const char*)(symbols + numberOfSymbols); + const char* result = strTable + sym->N.Name.Long; + strncpy(resultBuffer, result, resultBufferSize); + resultBuffer[resultBufferSize - 1] = '\0'; + } + } + + const void* getSymbolAddress(IMAGE_SYMBOL* symbol) { + IMAGE_SECTION_HEADER* sectionHeader = §ionHeaders[symbol->SectionNumber - 1]; + return (const void*)(imageBase + sectionHeader->VirtualAddress + symbol->Value); + } + + IMAGE_SYMBOL* findFunctionSymbol(const void* address) { + for (DWORD i = 0; i < numberOfSymbols; ++i) { + IMAGE_SYMBOL* symbol = &symbols[i]; + if (symbol->Type == 0x20 && address == getSymbolAddress(symbol)) { + return symbol; + } + } + return nullptr; + } + + public: + explicit SymbolTable(HMODULE hModule) { + imageBase = (char*)hModule; + IMAGE_DOS_HEADER* dosHeader = (IMAGE_DOS_HEADER*)imageBase; + RuntimeAssert(dosHeader->e_magic == IMAGE_DOS_SIGNATURE, "PE executable e_magic mismatch"); + + IMAGE_NT_HEADERS* ntHeaders = (IMAGE_NT_HEADERS*)(imageBase + dosHeader->e_lfanew); + RuntimeAssert(ntHeaders->Signature == IMAGE_NT_SIGNATURE, "PE executable NT signature mismatch"); + + IMAGE_FILE_HEADER* fileHeader = &ntHeaders->FileHeader; + + sectionHeaders = (IMAGE_SECTION_HEADER*)(((char*)(fileHeader + 1)) + fileHeader->SizeOfOptionalHeader); + if (fileHeader->PointerToSymbolTable == 0 || fileHeader->NumberOfSymbols == 0) { + // No symbols. + return; + } + + // Symbol table doesn't get mapped to the memory, so we have to load it ourselves: + char* mappedModuleFile = (char*)mapModuleFile(hModule); + if (mappedModuleFile != nullptr) { + symbols = (IMAGE_SYMBOL*)(mappedModuleFile + fileHeader->PointerToSymbolTable); + numberOfSymbols = fileHeader->NumberOfSymbols; + } + } + + bool functionAddressToSymbol(const void* address, char* resultBuffer, size_t resultBufferSize) { + IMAGE_SYMBOL* symbol = findFunctionSymbol(address); + if (symbol == nullptr) { + return false; + } else { + getSymbolName(symbol, resultBuffer, resultBufferSize); + return true; + } + } + +}; + +SymbolTable* theExeSymbolTable = nullptr; + +} // namespace + +extern "C" bool AddressToSymbol(const void* address, char* resultBuffer, size_t resultBufferSize) { + if (theExeSymbolTable == nullptr) { + // Note: do not protecting the lazy initialization by critical sections for simplicity; + // this doesn't have any serious consequences. + HMODULE hModule = nullptr; + int rv = GetModuleHandleExW(GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS | GET_MODULE_HANDLE_EX_FLAG_UNCHANGED_REFCOUNT, + reinterpret_cast(&AddressToSymbol), &hModule); + RuntimeAssert(rv != 0, "GetModuleHandleExW fails"); + theExeSymbolTable = konanConstructInstance(hModule); + } + return theExeSymbolTable->functionAddressToSymbol(address, resultBuffer, resultBufferSize); +} + +#else + +extern "C" bool AddressToSymbol(const void* address, char* resultBuffer, size_t resultBufferSize) { + return false; +} + +#endif // USE_ELF_SYMBOLS diff --git a/kotlin-native/runtime/src/main/cpp/ExecFormat.h b/kotlin-native/runtime/src/main/cpp/ExecFormat.h new file mode 100644 index 00000000000..62890df151e --- /dev/null +++ b/kotlin-native/runtime/src/main/cpp/ExecFormat.h @@ -0,0 +1,28 @@ +/* + * Copyright 2010-2017 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef RUNTIME_EXECFORMAT_H +#define RUNTIME_EXECFORMAT_H + +#include + +extern "C" { + +bool AddressToSymbol(const void* address, char* resultBuffer, size_t resultBufferSize); + +} // extern "C" + +#endif // RUNTIME_EXECFORMAT_H diff --git a/kotlin-native/runtime/src/main/cpp/Interop.cpp b/kotlin-native/runtime/src/main/cpp/Interop.cpp new file mode 100644 index 00000000000..4b6c2909110 --- /dev/null +++ b/kotlin-native/runtime/src/main/cpp/Interop.cpp @@ -0,0 +1,45 @@ +/* + * Copyright 2010-2017 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include +#include + +#include "Alloc.h" +#include "Memory.h" +#include "MemorySharedRefs.hpp" +#include "Types.h" + +extern "C" { + +KNativePtr Kotlin_Interop_createStablePointer(KRef any) { + KRefSharedHolder* holder = konanConstructInstance(); + holder->init(any); + return holder; +} + +void Kotlin_Interop_disposeStablePointer(KNativePtr pointer) { + KRefSharedHolder* holder = reinterpret_cast(pointer); + holder->dispose(); + konanDestructInstance(holder); +} + +OBJ_GETTER(Kotlin_Interop_derefStablePointer, KNativePtr pointer) { + KRefSharedHolder* holder = reinterpret_cast(pointer); + RETURN_OBJ(holder->ref()); +} + +} diff --git a/kotlin-native/runtime/src/main/cpp/JSInterop.cpp b/kotlin-native/runtime/src/main/cpp/JSInterop.cpp new file mode 100644 index 00000000000..85a37ae4d8d --- /dev/null +++ b/kotlin-native/runtime/src/main/cpp/JSInterop.cpp @@ -0,0 +1,81 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "Porting.h" +#include "Types.h" + +typedef KInt Arena; +typedef KInt Object; +typedef KInt Pointer; + +#ifndef KONAN_WASM + +extern "C" { + +// These functions are implemented in JS file for WASM and are not available on other platforms. +RUNTIME_NORETURN Arena Konan_js_allocateArena() { + RuntimeAssert(false, "JavaScript interop is disabled"); + konan::abort(); +} + +RUNTIME_NORETURN void Konan_js_freeArena(Arena arena) { + RuntimeAssert(false, "JavaScript interop is disabled"); + konan::abort(); +} + +RUNTIME_NORETURN void Konan_js_pushIntToArena(Arena arena, KInt value) { + RuntimeAssert(false, "JavaScript interop is disabled"); + konan::abort(); +} + +RUNTIME_NORETURN KInt Konan_js_getInt(Arena arena, + Object obj, + Pointer propertyPtr, + KInt propertyLen) { + RuntimeAssert(false, "JavaScript interop is disabled"); + konan::abort(); +} + +RUNTIME_NORETURN KInt Konan_js_getProperty(Arena arena, + Object obj, + Pointer propertyPtr, + KInt propertyLen) { + RuntimeAssert(false, "JavaScript interop is disabled"); + konan::abort(); +} + +RUNTIME_NORETURN void Konan_js_setFunction(Arena arena, + Object obj, + Pointer propertyName, + KInt propertyLength, + KInt function) { + RuntimeAssert(false, "JavaScript interop is disabled"); + konan::abort(); +} + +RUNTIME_NORETURN void Konan_js_setString(Arena arena, + Object obj, + Pointer propertyName, + KInt propertyLength, + Pointer stringPtr, + KInt stringLength) { + RuntimeAssert(false, "JavaScript interop is disabled"); + konan::abort(); +} + +}; // extern "C" + +#endif // #ifndef KONAN_WASM diff --git a/kotlin-native/runtime/src/main/cpp/KAssert.cpp b/kotlin-native/runtime/src/main/cpp/KAssert.cpp new file mode 100644 index 00000000000..ee3ab1fdeaa --- /dev/null +++ b/kotlin-native/runtime/src/main/cpp/KAssert.cpp @@ -0,0 +1,29 @@ +/* + * Copyright 2010-2017 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "KAssert.h" +#include "Porting.h" + +void RuntimeAssertFailed(const char* location, const char* message) { + // TODO: produce stacktrace and such. + char buf[1024]; + if (location != nullptr) + konan::snprintf(buf, sizeof(buf), "%s: runtime assert: %s\n", location, message); + else + konan::snprintf(buf, sizeof(buf), "runtime assert: %s\n", message); + konan::consoleErrorUtf8(buf, konan::strnlen(buf, sizeof(buf))); + konan::abort(); +} diff --git a/kotlin-native/runtime/src/main/cpp/KAssert.h b/kotlin-native/runtime/src/main/cpp/KAssert.h new file mode 100644 index 00000000000..c111c1783fa --- /dev/null +++ b/kotlin-native/runtime/src/main/cpp/KAssert.h @@ -0,0 +1,51 @@ +/* + * Copyright 2010-2017 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef RUNTIME_ASSERT_H +#define RUNTIME_ASSERT_H + +#include "Common.h" + +// To avoid cluttering optimized code with asserts, they could be turned off. +#define KONAN_ENABLE_ASSERT 1 + +#define STRINGIFY(x) #x +#define TOSTRING(x) STRINGIFY(x) + +RUNTIME_NORETURN void RuntimeAssertFailed(const char* location, const char* message); + +// During codegeneration we set this constant to 1 or 0 to allow bitcode optimizer +// to get rid of code behind condition. +extern "C" const int KonanNeedDebugInfo; + +#if KONAN_ENABLE_ASSERT +// Use RuntimeAssert() in internal state checks, which could be ignored in production. +#define RuntimeAssert(condition, message) \ +if (KonanNeedDebugInfo && (!(condition))) { \ + RuntimeAssertFailed( __FILE__ ":" TOSTRING(__LINE__), message); \ +} +#else +#define RuntimeAssert(condition, message) +#endif + +// Use RuntimeCheck() in runtime checks that could fail due to external condition and shall lead +// to program termination. Never compiled out. +#define RuntimeCheck(condition, message) \ + if (!(condition)) { \ + RuntimeAssertFailed(nullptr, message); \ + } + +#endif // RUNTIME_ASSERT_H diff --git a/kotlin-native/runtime/src/main/cpp/KDebug.h b/kotlin-native/runtime/src/main/cpp/KDebug.h new file mode 100644 index 00000000000..ddf69b952bb --- /dev/null +++ b/kotlin-native/runtime/src/main/cpp/KDebug.h @@ -0,0 +1,97 @@ +/* + * Copyright 2010-2017 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef RUNTIME_KDEBUG_H +#define RUNTIME_KDEBUG_H + +#include "Common.h" +#include "Memory.h" +#include "Types.h" +#include "TypeInfo.h" + +#ifndef KONAN_NO_DEBUG_API + +#ifdef __cplusplus +extern "C" { +#endif + +// PLEASE READ: please do not alter signatures of the existing functions, and when adding +// the new function please do not forget to add new functions into the debug operations list. + +// Get memory buffer where debugger can put data in Konan app process. +RUNTIME_USED RUNTIME_WEAK +char* Konan_DebugBuffer(); + +// Same, but runtime-specific. +RUNTIME_USED RUNTIME_WEAK +char* Konan_DebugBufferWithObject(KRef obj); + +// Get size of memory buffer where debugger can put data in Konan app process. +RUNTIME_USED RUNTIME_WEAK +int32_t Konan_DebugBufferSize(); + +// Same, but runtime-specific. +RUNTIME_USED RUNTIME_WEAK +int32_t Konan_DebugBufferSizeWithObject(KRef obj); + +// Put string representation of an object to the provided buffer. +RUNTIME_USED RUNTIME_WEAK +int32_t Konan_DebugObjectToUtf8Array(KRef obj, char* buffer, int32_t bufferSize); + +// Print to console string representation of an object. +RUNTIME_USED RUNTIME_WEAK +int32_t Konan_DebugPrint(KRef obj); + +// Returns 1 if obj refers to an array, string or binary blob and 0 otherwise. +RUNTIME_USED RUNTIME_WEAK +int32_t Konan_DebugIsArray(KRef obj); + +// Returns number of fields in an objects, or elements in an array. +RUNTIME_USED RUNTIME_WEAK +int32_t Konan_DebugGetFieldCount(KRef obj); + +// Compute type of field or an array element at the index, or 0, if incorrect, +// see Konan_RuntimeType. +RUNTIME_USED RUNTIME_WEAK +int32_t Konan_DebugGetFieldType(KRef obj, int32_t index); + +// Compute address of field or an array element at the index, or null, if incorrect. +RUNTIME_USED RUNTIME_WEAK +void* Konan_DebugGetFieldAddress(KRef obj, int32_t index); + +// Compute address of field or an array element at the index, or null, if incorrect. +RUNTIME_USED RUNTIME_WEAK +const char* Konan_DebugGetFieldName(KRef obj, int32_t index); + +// Returns name of type. +RUNTIME_USED RUNTIME_WEAK +const char* Konan_DebugGetTypeName(KRef obj); + +/** + * Given an object finds debugger interface operation suitable for manipulation with this object. + * Important for cases where multiple K/N runtimes coexist in the same address space and debugger + * doesn't know which debug operation to use on particular instance. + */ +RUNTIME_USED RUNTIME_WEAK +void* Konan_DebugGetOperation(KRef obj, /* Konan_DebugOperation */ int32_t operation); + +#ifdef __cplusplus +} +#endif + +#endif // !KONAN_NO_DEBUG_API + +#endif // RUNTIME_KDEBUG_H diff --git a/kotlin-native/runtime/src/main/cpp/KString.cpp b/kotlin-native/runtime/src/main/cpp/KString.cpp new file mode 100644 index 00000000000..bcfcedd7628 --- /dev/null +++ b/kotlin-native/runtime/src/main/cpp/KString.cpp @@ -0,0 +1,1186 @@ +/* + * Copyright 2010-2017 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include + +#include "KAssert.h" +#include "City.h" +#include "Exceptions.h" +#include "Memory.h" +#include "Natives.h" +#include "KString.h" +#include "Porting.h" +#include "Types.h" + +#include "utf8.h" + +namespace { + +typedef std::back_insert_iterator KStdStringInserter; +typedef KChar* utf8to16(const char*, const char*, KChar*); +typedef KStdStringInserter utf16to8(const KChar*,const KChar*, KStdStringInserter); + +KStdStringInserter utf16toUtf8OrThrow(const KChar* start, const KChar* end, KStdStringInserter result) { + TRY_CATCH(result = utf8::utf16to8(start, end, result), + result = utf8::unchecked::utf16to8(start, end, result), + ThrowCharacterCodingException()); + return result; +} + +template +OBJ_GETTER(utf8ToUtf16Impl, const char* rawString, const char* end, uint32_t charCount) { + if (rawString == nullptr) RETURN_OBJ(nullptr); + ArrayHeader* result = AllocArrayInstance(theStringTypeInfo, charCount, OBJ_RESULT)->array(); + KChar* rawResult = CharArrayAddressOfElementAt(result, 0); + conversion(rawString, end, rawResult); + RETURN_OBJ(result->obj()); +} + +template +OBJ_GETTER(unsafeUtf16ToUtf8Impl, KString thiz, KInt start, KInt size) { + RuntimeAssert(thiz->type_info() == theStringTypeInfo, "Must use String"); + const KChar* utf16 = CharArrayAddressOfElementAt(thiz, start); + KStdString utf8; + utf8.reserve(size); + conversion(utf16, utf16 + size, back_inserter(utf8)); + ArrayHeader* result = AllocArrayInstance(theByteArrayTypeInfo, utf8.size(), OBJ_RESULT)->array(); + ::memcpy(ByteArrayAddressOfElementAt(result, 0), utf8.c_str(), utf8.size()); + RETURN_OBJ(result->obj()); +} + +OBJ_GETTER(utf8ToUtf16OrThrow, const char* rawString, size_t rawStringLength) { + const char* end = rawString + rawStringLength; + uint32_t charCount; + TRY_CATCH(charCount = utf8::utf16_length(rawString, end), + charCount = utf8::unchecked::utf16_length(rawString, end), + ThrowCharacterCodingException()); + RETURN_RESULT_OF(utf8ToUtf16Impl, rawString, end, charCount); +} + +OBJ_GETTER(utf8ToUtf16, const char* rawString, size_t rawStringLength) { + const char* end = rawString + rawStringLength; + uint32_t charCount = utf8::with_replacement::utf16_length(rawString, end); + RETURN_RESULT_OF(utf8ToUtf16Impl, rawString, end, charCount); +} + + +// Case conversion is derived work from Apache Harmony. +// Unicode 3.0.1 (same as Unicode 3.0.0) +enum CharacterClass { + /** + * Unicode category constant Cn. + */ + UNASSIGNED = 0, + /** + * Unicode category constant Lu. + */ + UPPERCASE_LETTER = 1, + /** + * Unicode category constant Ll. + */ + LOWERCASE_LETTER = 2, + /** + * Unicode category constant Lt. + */ + TITLECASE_LETTER = 3, + /** + * Unicode category constant Lm. + */ + MODIFIER_LETTER = 4, + /** + * Unicode category constant Lo. + */ + OTHER_LETTER = 5, + /** + * Unicode category constant Mn. + */ + NON_SPACING_MARK = 6, + /** + * Unicode category constant Me. + */ + ENCLOSING_MARK = 7, + /** + * Unicode category constant Mc. + */ + COMBINING_SPACING_MARK = 8, + /** + * Unicode category constant Nd. + */ + DECIMAL_DIGIT_NUMBER = 9, + /** + * Unicode category constant Nl. + */ + LETTER_NUMBER = 10, + /** + * Unicode category constant No. + */ + OTHER_NUMBER = 11, + /** + * Unicode category constant Zs. + */ + SPACE_SEPARATOR = 12, + /** + * Unicode category constant Zl. + */ + LINE_SEPARATOR = 13, + /** + * Unicode category constant Zp. + */ + PARAGRAPH_SEPARATOR = 14, + /** + * Unicode category constant Cc. + */ + CONTROL = 15, + /** + * Unicode category constant Cf. + */ + FORMAT = 16, + /** + * Unicode category constant Co. + */ + PRIVATE_USE = 18, + /** + * Unicode category constant Cs. + */ + SURROGATE = 19, + /** + * Unicode category constant Pd. + */ + DASH_PUNCTUATION = 20, + /** + * Unicode category constant Ps. + */ + START_PUNCTUATION = 21, + /** + * Unicode category constant Pe. + */ + END_PUNCTUATION = 22, + /** + * Unicode category constant Pc. + */ + CONNECTOR_PUNCTUATION = 23, + /** + * Unicode category constant Po. + */ + OTHER_PUNCTUATION = 24, + /** + * Unicode category constant Sm. + */ + MATH_SYMBOL = 25, + /** + * Unicode category constant Sc. + */ + CURRENCY_SYMBOL = 26, + /** + * Unicode category constant Sk. + */ + MODIFIER_SYMBOL = 27, + /** + * Unicode category constant So. + */ + OTHER_SYMBOL = 28, + /** + * Unicode category constant Pi. + */ + INITIAL_QUOTE_PUNCTUATION = 29, + /** + * Unicode category constant Pf. + */ + FINAL_QUOTE_PUNCTUATION = 30 +}; + +constexpr KByte typeValuesCache[] = { + 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, + 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, + 12, 24, 24, 24, 26, 24, 24, 24, 21, 22, 24, 25, 24, 20, 24, 24, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 24, 24, 25, 25, 25, 24, + 24, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 21, 24, 22, 27, 23, + 27, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 21, 25, 22, 25, 15, + 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, + 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, + 12, 24, 26, 26, 26, 26, 28, 28, 27, 28, 2, 29, 25, 16, 28, 27, + 28, 25, 11, 11, 27, 2, 28, 24, 27, 11, 2, 30, 11, 11, 11, 24, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 25, 1, 1, 1, 1, 1, 1, 1, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 25, 2, 2, 2, 2, 2, 2, 2, 2, + 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, + 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, + 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, + 1, 2, 1, 2, 1, 2, 1, 2, 2, 1, 2, 1, 2, 1, 2, 1, + 2, 1, 2, 1, 2, 1, 2, 1, 2, 2, 1, 2, 1, 2, 1, 2, + 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, + 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, + 1, 2, 1, 2, 1, 2, 1, 2, 1, 1, 2, 1, 2, 1, 2, 2, + 2, 1, 1, 2, 1, 2, 1, 1, 2, 1, 1, 1, 2, 2, 1, 1, + 1, 1, 2, 1, 1, 2, 1, 1, 1, 2, 2, 2, 1, 1, 2, 1, + 1, 2, 1, 2, 1, 2, 1, 1, 2, 1, 2, 2, 1, 2, 1, 1, + 2, 1, 1, 1, 2, 1, 2, 1, 1, 2, 2, 5, 1, 2, 2, 2, + 5, 5, 5, 5, 1, 3, 2, 1, 3, 2, 1, 3, 2, 1, 2, 1, + 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 2, 1, 2, + 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, + 2, 1, 3, 2, 1, 2, 1, 1, 1, 2, 1, 2, 1, 2, 1, 2, + 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, + 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, + 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, + 1, 2, 1, 2, 2, 2, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, + 4, 4, 27, 27, 27, 27, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, + 4, 4, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, + 4, 4, 4, 4, 4, 27, 27, 27, 27, 27, 27, 27, 27, 27, 4, 27, + 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, + 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, + 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, + 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, + 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, + 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, + 6, 6, 6, 6, 6, 6, 6, 6, 0, 0, 0, 0, 0, 6, 6, 6, + 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, + 0, 0, 0, 0, 27, 27, 0, 0, 0, 0, 4, 0, 0, 0, 24, 0, + 0, 0, 0, 0, 27, 27, 1, 24, 1, 1, 1, 0, 1, 0, 1, 1, + 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, + 2, 2, 1, 1, 1, 2, 2, 2, 1, 2, 1, 2, 1, 2, 1, 2, + 1, 2, 1, 2, 1, 2, 1, 2 +}; + +constexpr KShort uppercaseValuesCache[] = { + 924, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, 192, 193, 194, 195, 196, + 197, 198, 199, 200, 201, 202, 203, 204, 205, 206, 207, 208, 209, 210, 211, 212, + 213, 214, 215, 216, 217, 218, 219, 220, 221, 222, 223, 192, 193, 194, 195, 196, + 197, 198, 199, 200, 201, 202, 203, 204, 205, 206, 207, 208, 209, 210, 211, 212, + 213, 214, 247, 216, 217, 218, 219, 220, 221, 222, 376, 256, 256, 258, 258, 260, + 260, 262, 262, 264, 264, 266, 266, 268, 268, 270, 270, 272, 272, 274, 274, 276, + 276, 278, 278, 280, 280, 282, 282, 284, 284, 286, 286, 288, 288, 290, 290, 292, + 292, 294, 294, 296, 296, 298, 298, 300, 300, 302, 302, 304, 73, 306, 306, 308, + 308, 310, 310, 312, 313, 313, 315, 315, 317, 317, 319, 319, 321, 321, 323, 323, + 325, 325, 327, 327, 329, 330, 330, 332, 332, 334, 334, 336, 336, 338, 338, 340, + 340, 342, 342, 344, 344, 346, 346, 348, 348, 350, 350, 352, 352, 354, 354, 356, + 356, 358, 358, 360, 360, 362, 362, 364, 364, 366, 366, 368, 368, 370, 370, 372, + 372, 374, 374, 376, 377, 377, 379, 379, 381, 381, 83, 384, 385, 386, 386, 388, + 388, 390, 391, 391, 393, 394, 395, 395, 397, 398, 399, 400, 401, 401, 403, 404, + 502, 406, 407, 408, 408, 410, 411, 412, 413, 544, 415, 416, 416, 418, 418, 420, + 420, 422, 423, 423, 425, 426, 427, 428, 428, 430, 431, 431, 433, 434, 435, 435, + 437, 437, 439, 440, 440, 442, 443, 444, 444, 446, 503, 448, 449, 450, 451, 452, + 452, 452, 455, 455, 455, 458, 458, 458, 461, 461, 463, 463, 465, 465, 467, 467, + 469, 469, 471, 471, 473, 473, 475, 475, 398, 478, 478, 480, 480, 482, 482, 484, + 484, 486, 486, 488, 488, 490, 490, 492, 492, 494, 494, 496, 497, 497, 497, 500, + 500, 502, 503, 504, 504, 506, 506, 508, 508, 510, 510, 512, 512, 514, 514, 516, + 516, 518, 518, 520, 520, 522, 522, 524, 524, 526, 526, 528, 528, 530, 530, 532, + 532, 534, 534, 536, 536, 538, 538, 540, 540, 542, 542, 544, 545, 546, 546, 548, + 548, 550, 550, 552, 552, 554, 554, 556, 556, 558, 558, 560, 560, 562, 562, 564, + 565, 566, 567, 568, 569, 570, 571, 572, 573, 574, 575, 576, 577, 578, 579, 580, + 581, 582, 583, 584, 585, 586, 587, 588, 589, 590, 591, 592, 593, 594, 385, 390, + 597, 393, 394, 600, 399, 602, 400, 604, 605, 606, 607, 403, 609, 610, 404, 612, + 613, 614, 615, 407, 406, 618, 619, 620, 621, 622, 412, 624, 625, 413, 627, 628, + 415, 630, 631, 632, 633, 634, 635, 636, 637, 638, 639, 422, 641, 642, 425, 644, + 645, 646, 647, 430, 649, 433, 434, 652, 653, 654, 655, 656, 657, 439, 659, 660, + 661, 662, 663, 664, 665, 666, 667, 668, 669, 670, 671, 672, 673, 674, 675, 676, + 677, 678, 679, 680, 681, 682, 683, 684, 685, 686, 687, 688, 689, 690, 691, 692, + 693, 694, 695, 696, 697, 698, 699, 700, 701, 702, 703, 704, 705, 706, 707, 708, + 709, 710, 711, 712, 713, 714, 715, 716, 717, 718, 719, 720, 721, 722, 723, 724, + 725, 726, 727, 728, 729, 730, 731, 732, 733, 734, 735, 736, 737, 738, 739, 740, + 741, 742, 743, 744, 745, 746, 747, 748, 749, 750, 751, 752, 753, 754, 755, 756, + 757, 758, 759, 760, 761, 762, 763, 764, 765, 766, 767, 768, 769, 770, 771, 772, + 773, 774, 775, 776, 777, 778, 779, 780, 781, 782, 783, 784, 785, 786, 787, 788, + 789, 790, 791, 792, 793, 794, 795, 796, 797, 798, 799, 800, 801, 802, 803, 804, + 805, 806, 807, 808, 809, 810, 811, 812, 813, 814, 815, 816, 817, 818, 819, 820, + 821, 822, 823, 824, 825, 826, 827, 828, 829, 830, 831, 832, 833, 834, 835, 836, + 921, 838, 839, 840, 841, 842, 843, 844, 845, 846, 847, 848, 849, 850, 851, 852, + 853, 854, 855, 856, 857, 858, 859, 860, 861, 862, 863, 864, 865, 866, 867, 868, + 869, 870, 871, 872, 873, 874, 875, 876, 877, 878, 879, 880, 881, 882, 883, 884, + 885, 886, 887, 888, 889, 890, 891, 892, 893, 894, 895, 896, 897, 898, 899, 900, + 901, 902, 903, 904, 905, 906, 907, 908, 909, 910, 911, 912, 913, 914, 915, 916, + 917, 918, 919, 920, 921, 922, 923, 924, 925, 926, 927, 928, 929, 930, 931, 932, + 933, 934, 935, 936, 937, 938, 939, 902, 904, 905, 906, 944, 913, 914, 915, 916, + 917, 918, 919, 920, 921, 922, 923, 924, 925, 926, 927, 928, 929, 931, 931, 932, + 933, 934, 935, 936, 937, 938, 939, 908, 910, 911, 975, 914, 920, 978, 979, 980, + 934, 928, 983, 984, 984, 986, 986, 988, 988, 990, 990, 992, 992, 994, 994, 996, + 996, 998, 998 +}; + +constexpr KShort lowercaseValuesCache[] = { + 224, 225, 226, 227, 228, 229, 230, 231, 232, 233, 234, 235, 236, 237, 238, 239, + 240, 241, 242, 243, 244, 245, 246, 215, 248, 249, 250, 251, 252, 253, 254, 223, + 224, 225, 226, 227, 228, 229, 230, 231, 232, 233, 234, 235, 236, 237, 238, 239, + 240, 241, 242, 243, 244, 245, 246, 247, 248, 249, 250, 251, 252, 253, 254, 255, + 257, 257, 259, 259, 261, 261, 263, 263, 265, 265, 267, 267, 269, 269, 271, 271, + 273, 273, 275, 275, 277, 277, 279, 279, 281, 281, 283, 283, 285, 285, 287, 287, + 289, 289, 291, 291, 293, 293, 295, 295, 297, 297, 299, 299, 301, 301, 303, 303, + 105, 305, 307, 307, 309, 309, 311, 311, 312, 314, 314, 316, 316, 318, 318, 320, + 320, 322, 322, 324, 324, 326, 326, 328, 328, 329, 331, 331, 333, 333, 335, 335, + 337, 337, 339, 339, 341, 341, 343, 343, 345, 345, 347, 347, 349, 349, 351, 351, + 353, 353, 355, 355, 357, 357, 359, 359, 361, 361, 363, 363, 365, 365, 367, 367, + 369, 369, 371, 371, 373, 373, 375, 375, 255, 378, 378, 380, 380, 382, 382, 383, + 384, 595, 387, 387, 389, 389, 596, 392, 392, 598, 599, 396, 396, 397, 477, 601, + 603, 402, 402, 608, 611, 405, 617, 616, 409, 409, 410, 411, 623, 626, 414, 629, + 417, 417, 419, 419, 421, 421, 640, 424, 424, 643, 426, 427, 429, 429, 648, 432, + 432, 650, 651, 436, 436, 438, 438, 658, 441, 441, 442, 443, 445, 445, 446, 447, + 448, 449, 450, 451, 454, 454, 454, 457, 457, 457, 460, 460, 460, 462, 462, 464, + 464, 466, 466, 468, 468, 470, 470, 472, 472, 474, 474, 476, 476, 477, 479, 479, + 481, 481, 483, 483, 485, 485, 487, 487, 489, 489, 491, 491, 493, 493, 495, 495, + 496, 499, 499, 499, 501, 501, 405, 447, 505, 505, 507, 507, 509, 509, 511, 511, + 513, 513, 515, 515, 517, 517, 519, 519, 521, 521, 523, 523, 525, 525, 527, 527, + 529, 529, 531, 531, 533, 533, 535, 535, 537, 537, 539, 539, 541, 541, 543, 543, + 414, 545, 547, 547, 549, 549, 551, 551, 553, 553, 555, 555, 557, 557, 559, 559, + 561, 561, 563, 563, 564, 565, 566, 567, 568, 569, 570, 571, 572, 573, 574, 575, + 576, 577, 578, 579, 580, 581, 582, 583, 584, 585, 586, 587, 588, 589, 590, 591, + 592, 593, 594, 595, 596, 597, 598, 599, 600, 601, 602, 603, 604, 605, 606, 607, + 608, 609, 610, 611, 612, 613, 614, 615, 616, 617, 618, 619, 620, 621, 622, 623, + 624, 625, 626, 627, 628, 629, 630, 631, 632, 633, 634, 635, 636, 637, 638, 639, + 640, 641, 642, 643, 644, 645, 646, 647, 648, 649, 650, 651, 652, 653, 654, 655, + 656, 657, 658, 659, 660, 661, 662, 663, 664, 665, 666, 667, 668, 669, 670, 671, + 672, 673, 674, 675, 676, 677, 678, 679, 680, 681, 682, 683, 684, 685, 686, 687, + 688, 689, 690, 691, 692, 693, 694, 695, 696, 697, 698, 699, 700, 701, 702, 703, + 704, 705, 706, 707, 708, 709, 710, 711, 712, 713, 714, 715, 716, 717, 718, 719, + 720, 721, 722, 723, 724, 725, 726, 727, 728, 729, 730, 731, 732, 733, 734, 735, + 736, 737, 738, 739, 740, 741, 742, 743, 744, 745, 746, 747, 748, 749, 750, 751, + 752, 753, 754, 755, 756, 757, 758, 759, 760, 761, 762, 763, 764, 765, 766, 767, + 768, 769, 770, 771, 772, 773, 774, 775, 776, 777, 778, 779, 780, 781, 782, 783, + 784, 785, 786, 787, 788, 789, 790, 791, 792, 793, 794, 795, 796, 797, 798, 799, + 800, 801, 802, 803, 804, 805, 806, 807, 808, 809, 810, 811, 812, 813, 814, 815, + 816, 817, 818, 819, 820, 821, 822, 823, 824, 825, 826, 827, 828, 829, 830, 831, + 832, 833, 834, 835, 836, 837, 838, 839, 840, 841, 842, 843, 844, 845, 846, 847, + 848, 849, 850, 851, 852, 853, 854, 855, 856, 857, 858, 859, 860, 861, 862, 863, + 864, 865, 866, 867, 868, 869, 870, 871, 872, 873, 874, 875, 876, 877, 878, 879, + 880, 881, 882, 883, 884, 885, 886, 887, 888, 889, 890, 891, 892, 893, 894, 895, + 896, 897, 898, 899, 900, 901, 940, 903, 941, 942, 943, 907, 972, 909, 973, 974, + 912, 945, 946, 947, 948, 949, 950, 951, 952, 953, 954, 955, 956, 957, 958, 959, + 960, 961, 930, 963, 964, 965, 966, 967, 968, 969, 970, 971, 940, 941, 942, 943, + 944, 945, 946, 947, 948, 949, 950, 951, 952, 953, 954, 955, 956, 957, 958, 959, + 960, 961, 962, 963, 964, 965, 966, 967, 968, 969, 970, 971, 972, 973, 974, 975, + 976, 977, 978, 979, 980, 981, 982, 983, 985, 985, 987, 987, 989, 989, 991, 991, + 993, 993, 995, 995, 997, 997, 999, 999 +}; + +constexpr KChar uppercaseKeys[] = { + 0x61, 0xb5, 0xe0, 0xf8, 0xff, 0x101, 0x131, 0x133, 0x13a, 0x14b, 0x17a, 0x17f, 0x183, 0x188, 0x18c, 0x192, 0x195, 0x199, 0x1a1, 0x1a8, + 0x1ad, 0x1b0, 0x1b4, 0x1b9, 0x1bd, 0x1bf, 0x1c5, 0x1c6, 0x1c8, 0x1c9, 0x1cb, 0x1cc, 0x1ce, 0x1dd, 0x1df, 0x1f2, 0x1f3, 0x1f5, 0x1f9, 0x223, + 0x253, 0x254, 0x256, 0x259, 0x25b, 0x260, 0x263, 0x268, 0x269, 0x26f, 0x272, 0x275, 0x280, 0x283, 0x288, 0x28a, 0x292, 0x345, 0x3ac, 0x3ad, + 0x3b1, 0x3c2, 0x3c3, 0x3cc, 0x3cd, 0x3d0, 0x3d1, 0x3d5, 0x3d6, 0x3db, 0x3f0, 0x3f1, 0x3f2, 0x430, 0x450, 0x461, 0x48d, 0x4c2, 0x4c8, 0x4cc, + 0x4d1, 0x4f9, 0x561, 0x1e01, 0x1e9b, 0x1ea1, 0x1f00, 0x1f10, 0x1f20, 0x1f30, 0x1f40, 0x1f51, 0x1f60, 0x1f70, 0x1f72, 0x1f76, 0x1f78, 0x1f7a, 0x1f7c, 0x1f80, + 0x1f90, 0x1fa0, 0x1fb0, 0x1fb3, 0x1fbe, 0x1fc3, 0x1fd0, 0x1fe0, 0x1fe5, 0x1ff3, 0x2170, 0x24d0, 0xff41 +}; + +constexpr KChar uppercaseValues[] = { + 0x7a, 0xffe0, 0xb5, 0x2e7, 0xf6, 0xffe0, 0xfe, 0xffe0, 0xff, 0x79, 0x812f, 0xffff, 0x131, 0xff18, 0x8137, 0xffff, 0x8148, 0xffff, 0x8177, 0xffff, + 0x817e, 0xffff, 0x17f, 0xfed4, 0x8185, 0xffff, 0x188, 0xffff, 0x18c, 0xffff, 0x192, 0xffff, 0x195, 0x61, 0x199, 0xffff, 0x81a5, 0xffff, 0x1a8, 0xffff, + 0x1ad, 0xffff, 0x1b0, 0xffff, 0x81b6, 0xffff, 0x1b9, 0xffff, 0x1bd, 0xffff, 0x1bf, 0x38, 0x1c5, 0xffff, 0x1c6, 0xfffe, 0x1c8, 0xffff, 0x1c9, 0xfffe, + 0x1cb, 0xffff, 0x1cc, 0xfffe, 0x81dc, 0xffff, 0x1dd, 0xffb1, 0x81ef, 0xffff, 0x1f2, 0xffff, 0x1f3, 0xfffe, 0x1f5, 0xffff, 0x821f, 0xffff, 0x8233, 0xffff, + 0x253, 0xff2e, 0x254, 0xff32, 0x257, 0xff33, 0x259, 0xff36, 0x25b, 0xff35, 0x260, 0xff33, 0x263, 0xff31, 0x268, 0xff2f, 0x269, 0xff2d, 0x26f, 0xff2d, + 0x272, 0xff2b, 0x275, 0xff2a, 0x280, 0xff26, 0x283, 0xff26, 0x288, 0xff26, 0x28b, 0xff27, 0x292, 0xff25, 0x345, 0x54, 0x3ac, 0xffda, 0x3af, 0xffdb, + 0x3c1, 0xffe0, 0x3c2, 0xffe1, 0x3cb, 0xffe0, 0x3cc, 0xffc0, 0x3ce, 0xffc1, 0x3d0, 0xffc2, 0x3d1, 0xffc7, 0x3d5, 0xffd1, 0x3d6, 0xffca, 0x83ef, 0xffff, + 0x3f0, 0xffaa, 0x3f1, 0xffb0, 0x3f2, 0xffb1, 0x44f, 0xffe0, 0x45f, 0xffb0, 0x8481, 0xffff, 0x84bf, 0xffff, 0x84c4, 0xffff, 0x4c8, 0xffff, 0x4cc, 0xffff, + 0x84f5, 0xffff, 0x4f9, 0xffff, 0x586, 0xffd0, 0x9e95, 0xffff, 0x1e9b, 0xffc5, 0x9ef9, 0xffff, 0x1f07, 0x8, 0x1f15, 0x8, 0x1f27, 0x8, 0x1f37, 0x8, + 0x1f45, 0x8, 0x9f57, 0x8, 0x1f67, 0x8, 0x1f71, 0x4a, 0x1f75, 0x56, 0x1f77, 0x64, 0x1f79, 0x80, 0x1f7b, 0x70, 0x1f7d, 0x7e, 0x1f87, 0x8, + 0x1f97, 0x8, 0x1fa7, 0x8, 0x1fb1, 0x8, 0x1fb3, 0x9, 0x1fbe, 0xe3db, 0x1fc3, 0x9, 0x1fd1, 0x8, 0x1fe1, 0x8, 0x1fe5, 0x7, 0x1ff3, 0x9, + 0x217f, 0xfff0, 0x24e9, 0xffe6, 0xff5a, 0xffe0 +}; + +constexpr KChar lowercaseKeys[] = { + 0x41, 0xc0, 0xd8, 0x100, 0x130, 0x132, 0x139, 0x14a, 0x178, 0x179, 0x181, 0x182, 0x186, 0x187, 0x189, 0x18b, 0x18e, 0x18f, 0x190, 0x191, + 0x193, 0x194, 0x196, 0x197, 0x198, 0x19c, 0x19d, 0x19f, 0x1a0, 0x1a6, 0x1a7, 0x1a9, 0x1ac, 0x1ae, 0x1af, 0x1b1, 0x1b3, 0x1b7, 0x1b8, 0x1bc, + 0x1c4, 0x1c5, 0x1c7, 0x1c8, 0x1ca, 0x1cb, 0x1de, 0x1f1, 0x1f2, 0x1f6, 0x1f7, 0x1f8, 0x222, 0x386, 0x388, 0x38c, 0x38e, 0x391, 0x3a3, 0x3da, + 0x400, 0x410, 0x460, 0x48c, 0x4c1, 0x4c7, 0x4cb, 0x4d0, 0x4f8, 0x531, 0x1e00, 0x1ea0, 0x1f08, 0x1f18, 0x1f28, 0x1f38, 0x1f48, 0x1f59, 0x1f68, 0x1f88, + 0x1f98, 0x1fa8, 0x1fb8, 0x1fba, 0x1fbc, 0x1fc8, 0x1fcc, 0x1fd8, 0x1fda, 0x1fe8, 0x1fea, 0x1fec, 0x1ff8, 0x1ffa, 0x1ffc, 0x2126, 0x212a, 0x212b, 0x2160, 0x24b6 +}; + +constexpr KChar lowercaseValues[] = { + 0x5a, 0x20, 0xd6, 0x20, 0xde, 0x20, 0x812e, 0x1, 0x130, 0xff39, 0x8136, 0x1, 0x8147, 0x1, 0x8176, 0x1, 0x178, 0xff87, 0x817d, 0x1, + 0x181, 0xd2, 0x8184, 0x1, 0x186, 0xce, 0x187, 0x1, 0x18a, 0xcd, 0x18b, 0x1, 0x18e, 0x4f, 0x18f, 0xca, 0x190, 0xcb, 0x191, 0x1, + 0x193, 0xcd, 0x194, 0xcf, 0x196, 0xd3, 0x197, 0xd1, 0x198, 0x1, 0x19c, 0xd3, 0x19d, 0xd5, 0x19f, 0xd6, 0x81a4, 0x1, 0x1a6, 0xda, + 0x1a7, 0x1, 0x1a9, 0xda, 0x1ac, 0x1, 0x1ae, 0xda, 0x1af, 0x1, 0x1b2, 0xd9, 0x81b5, 0x1, 0x1b7, 0xdb, 0x1b8, 0x1, 0x1bc, 0x1, + 0x1c4, 0x2, 0x1c5, 0x1, 0x1c7, 0x2, 0x1c8, 0x1, 0x1ca, 0x2, 0x81db, 0x1, 0x81ee, 0x1, 0x1f1, 0x2, 0x81f4, 0x1, 0x1f6, 0xff9f, + 0x1f7, 0xffc8, 0x821e, 0x1, 0x8232, 0x1, 0x386, 0x26, 0x38a, 0x25, 0x38c, 0x40, 0x38f, 0x3f, 0x3a1, 0x20, 0x3ab, 0x20, 0x83ee, 0x1, + 0x40f, 0x50, 0x42f, 0x20, 0x8480, 0x1, 0x84be, 0x1, 0x84c3, 0x1, 0x4c7, 0x1, 0x4cb, 0x1, 0x84f4, 0x1, 0x4f8, 0x1, 0x556, 0x30, + 0x9e94, 0x1, 0x9ef8, 0x1, 0x1f0f, 0xfff8, 0x1f1d, 0xfff8, 0x1f2f, 0xfff8, 0x1f3f, 0xfff8, 0x1f4d, 0xfff8, 0x9f5f, 0xfff8, 0x1f6f, 0xfff8, 0x1f8f, 0xfff8, + 0x1f9f, 0xfff8, 0x1faf, 0xfff8, 0x1fb9, 0xfff8, 0x1fbb, 0xffb6, 0x1fbc, 0xfff7, 0x1fcb, 0xffaa, 0x1fcc, 0xfff7, 0x1fd9, 0xfff8, 0x1fdb, 0xff9c, 0x1fe9, 0xfff8, + 0x1feb, 0xff90, 0x1fec, 0xfff9, 0x1ff9, 0xff80, 0x1ffb, 0xff82, 0x1ffc, 0xfff7, 0x2126, 0xe2a3, 0x212a, 0xdf41, 0x212b, 0xdfba, 0x216f, 0x10, 0x24cf, 0x1a +}; + +constexpr KChar digitKeys[] = { + 0x30, 0x41, 0x61, 0x660, 0x6f0, 0x966, 0x9e6, 0xa66, 0xae6, 0xb66, 0xbe7, 0xc66, 0xce6, 0xd66, 0xe50, 0xed0, 0xf20, 0x1040, 0x1369, 0x17e0, + 0x1810, 0xff10, 0xff21, 0xff41 +}; + +constexpr KChar digitValues[] = { + 0x39, 0x30, 0x5a, 0x37, 0x7a, 0x57, 0x669, 0x660, 0x6f9, 0x6f0, 0x96f, 0x966, 0x9ef, 0x9e6, 0xa6f, 0xa66, 0xaef, 0xae6, 0xb6f, 0xb66, + 0xbef, 0xbe6, 0xc6f, 0xc66, 0xcef, 0xce6, 0xd6f, 0xd66, 0xe59, 0xe50, 0xed9, 0xed0, 0xf29, 0xf20, 0x1049, 0x1040, 0x1371, 0x1368, 0x17e9, 0x17e0, + 0x1819, 0x1810, 0xff19, 0xff10, 0xff3a, 0xff17, 0xff5a, 0xff37 +}; + +constexpr KChar typeKeys[] = { + 0x0, 0x20, 0x22, 0x24, 0x26, 0x28, 0x2a, 0x2d, 0x2f, 0x31, 0x3a, 0x3c, 0x3f, 0x41, 0x5b, 0x5d, 0x5f, 0x61, 0x7b, 0x7d, + 0x7f, 0xa0, 0xa2, 0xa6, 0xa8, 0xaa, 0xac, 0xae, 0xb1, 0xb3, 0xb5, 0xb7, 0xb9, 0xbb, 0xbd, 0xbf, 0xc1, 0xd7, 0xd9, 0xdf, + 0xf7, 0xf9, 0x100, 0x138, 0x149, 0x179, 0x17f, 0x181, 0x183, 0x187, 0x18a, 0x18c, 0x18e, 0x192, 0x194, 0x197, 0x199, 0x19c, 0x19e, 0x1a0, + 0x1a7, 0x1ab, 0x1af, 0x1b2, 0x1b4, 0x1b8, 0x1ba, 0x1bc, 0x1be, 0x1c0, 0x1c4, 0x1c6, 0x1c8, 0x1ca, 0x1cc, 0x1dd, 0x1f0, 0x1f2, 0x1f4, 0x1f7, + 0x1f9, 0x222, 0x250, 0x2b0, 0x2b9, 0x2bb, 0x2c2, 0x2d0, 0x2d2, 0x2e0, 0x2e5, 0x2ee, 0x300, 0x360, 0x374, 0x37a, 0x37e, 0x384, 0x386, 0x389, + 0x38c, 0x38e, 0x390, 0x392, 0x3a3, 0x3ac, 0x3d0, 0x3d2, 0x3d5, 0x3da, 0x3f0, 0x400, 0x430, 0x460, 0x482, 0x484, 0x488, 0x48c, 0x4c1, 0x4c7, + 0x4cb, 0x4d0, 0x4f8, 0x531, 0x559, 0x55b, 0x561, 0x589, 0x591, 0x5a3, 0x5bb, 0x5be, 0x5c2, 0x5d0, 0x5f0, 0x5f3, 0x60c, 0x61b, 0x61f, 0x621, + 0x640, 0x642, 0x64b, 0x660, 0x66a, 0x670, 0x672, 0x6d4, 0x6d6, 0x6dd, 0x6df, 0x6e5, 0x6e7, 0x6e9, 0x6eb, 0x6f0, 0x6fa, 0x6fd, 0x700, 0x70f, + 0x711, 0x713, 0x730, 0x780, 0x7a6, 0x901, 0x903, 0x905, 0x93c, 0x93e, 0x941, 0x949, 0x94d, 0x950, 0x952, 0x958, 0x962, 0x964, 0x966, 0x970, + 0x981, 0x983, 0x985, 0x98f, 0x993, 0x9aa, 0x9b2, 0x9b6, 0x9bc, 0x9be, 0x9c1, 0x9c7, 0x9cb, 0x9cd, 0x9d7, 0x9dc, 0x9df, 0x9e2, 0x9e6, 0x9f0, + 0x9f2, 0x9f4, 0x9fa, 0xa02, 0xa05, 0xa0f, 0xa13, 0xa2a, 0xa32, 0xa35, 0xa38, 0xa3c, 0xa3e, 0xa41, 0xa47, 0xa4b, 0xa59, 0xa5e, 0xa66, 0xa70, + 0xa72, 0xa81, 0xa83, 0xa85, 0xa8d, 0xa8f, 0xa93, 0xaaa, 0xab2, 0xab5, 0xabc, 0xabe, 0xac1, 0xac7, 0xac9, 0xacb, 0xacd, 0xad0, 0xae0, 0xae6, + 0xb01, 0xb03, 0xb05, 0xb0f, 0xb13, 0xb2a, 0xb32, 0xb36, 0xb3c, 0xb3e, 0xb42, 0xb47, 0xb4b, 0xb4d, 0xb56, 0xb5c, 0xb5f, 0xb66, 0xb70, 0xb82, + 0xb85, 0xb8e, 0xb92, 0xb99, 0xb9c, 0xb9e, 0xba3, 0xba8, 0xbae, 0xbb7, 0xbbe, 0xbc0, 0xbc2, 0xbc6, 0xbca, 0xbcd, 0xbd7, 0xbe7, 0xbf0, 0xc01, + 0xc05, 0xc0e, 0xc12, 0xc2a, 0xc35, 0xc3e, 0xc41, 0xc46, 0xc4a, 0xc55, 0xc60, 0xc66, 0xc82, 0xc85, 0xc8e, 0xc92, 0xcaa, 0xcb5, 0xcbe, 0xcc1, + 0xcc6, 0xcc8, 0xcca, 0xccc, 0xcd5, 0xcde, 0xce0, 0xce6, 0xd02, 0xd05, 0xd0e, 0xd12, 0xd2a, 0xd3e, 0xd41, 0xd46, 0xd4a, 0xd4d, 0xd57, 0xd60, + 0xd66, 0xd82, 0xd85, 0xd9a, 0xdb3, 0xdbd, 0xdc0, 0xdca, 0xdcf, 0xdd2, 0xdd6, 0xdd8, 0xdf2, 0xdf4, 0xe01, 0xe31, 0xe33, 0xe35, 0xe3f, 0xe41, + 0xe46, 0xe48, 0xe4f, 0xe51, 0xe5a, 0xe81, 0xe84, 0xe87, 0xe8a, 0xe8d, 0xe94, 0xe99, 0xea1, 0xea5, 0xea7, 0xeaa, 0xead, 0xeb1, 0xeb3, 0xeb5, + 0xebb, 0xebd, 0xec0, 0xec6, 0xec8, 0xed0, 0xedc, 0xf00, 0xf02, 0xf04, 0xf13, 0xf18, 0xf1a, 0xf20, 0xf2a, 0xf34, 0xf3a, 0xf3e, 0xf40, 0xf49, + 0xf71, 0xf7f, 0xf81, 0xf85, 0xf87, 0xf89, 0xf90, 0xf99, 0xfbe, 0xfc6, 0xfc8, 0xfcf, 0x1000, 0x1023, 0x1029, 0x102c, 0x102e, 0x1031, 0x1036, 0x1038, + 0x1040, 0x104a, 0x1050, 0x1056, 0x1058, 0x10a0, 0x10d0, 0x10fb, 0x1100, 0x115f, 0x11a8, 0x1200, 0x1208, 0x1248, 0x124a, 0x1250, 0x1258, 0x125a, 0x1260, 0x1288, + 0x128a, 0x1290, 0x12b0, 0x12b2, 0x12b8, 0x12c0, 0x12c2, 0x12c8, 0x12d0, 0x12d8, 0x12f0, 0x1310, 0x1312, 0x1318, 0x1320, 0x1348, 0x1361, 0x1369, 0x1372, 0x13a0, + 0x1401, 0x166d, 0x166f, 0x1680, 0x1682, 0x169b, 0x16a0, 0x16eb, 0x16ee, 0x1780, 0x17b4, 0x17b7, 0x17be, 0x17c6, 0x17c8, 0x17ca, 0x17d4, 0x17db, 0x17e0, 0x1800, + 0x1806, 0x1808, 0x180b, 0x1810, 0x1820, 0x1843, 0x1845, 0x1880, 0x18a9, 0x1e00, 0x1e96, 0x1ea0, 0x1f00, 0x1f08, 0x1f10, 0x1f18, 0x1f20, 0x1f28, 0x1f30, 0x1f38, + 0x1f40, 0x1f48, 0x1f50, 0x1f59, 0x1f5b, 0x1f5d, 0x1f5f, 0x1f61, 0x1f68, 0x1f70, 0x1f80, 0x1f88, 0x1f90, 0x1f98, 0x1fa0, 0x1fa8, 0x1fb0, 0x1fb6, 0x1fb8, 0x1fbc, + 0x1fbe, 0x1fc0, 0x1fc2, 0x1fc6, 0x1fc8, 0x1fcc, 0x1fce, 0x1fd0, 0x1fd6, 0x1fd8, 0x1fdd, 0x1fe0, 0x1fe8, 0x1fed, 0x1ff2, 0x1ff6, 0x1ff8, 0x1ffc, 0x1ffe, 0x2000, + 0x200c, 0x2010, 0x2016, 0x2018, 0x201a, 0x201c, 0x201e, 0x2020, 0x2028, 0x202a, 0x202f, 0x2031, 0x2039, 0x203b, 0x203f, 0x2041, 0x2044, 0x2046, 0x2048, 0x206a, + 0x2070, 0x2074, 0x207a, 0x207d, 0x207f, 0x2081, 0x208a, 0x208d, 0x20a0, 0x20d0, 0x20dd, 0x20e1, 0x20e3, 0x2100, 0x2102, 0x2104, 0x2107, 0x2109, 0x210b, 0x210e, + 0x2110, 0x2113, 0x2115, 0x2117, 0x2119, 0x211e, 0x2124, 0x212b, 0x212e, 0x2130, 0x2132, 0x2134, 0x2136, 0x2139, 0x2153, 0x2160, 0x2190, 0x2195, 0x219a, 0x219c, + 0x21a0, 0x21a2, 0x21a5, 0x21a8, 0x21ae, 0x21b0, 0x21ce, 0x21d0, 0x21d2, 0x21d6, 0x2200, 0x2300, 0x2308, 0x230c, 0x2320, 0x2322, 0x2329, 0x232b, 0x237d, 0x2400, + 0x2440, 0x2460, 0x249c, 0x24ea, 0x2500, 0x25a0, 0x25b7, 0x25b9, 0x25c1, 0x25c3, 0x2600, 0x2619, 0x266f, 0x2671, 0x2701, 0x2706, 0x270c, 0x2729, 0x274d, 0x274f, + 0x2756, 0x2758, 0x2761, 0x2776, 0x2794, 0x2798, 0x27b1, 0x2800, 0x2e80, 0x2e9b, 0x2f00, 0x2ff0, 0x3000, 0x3002, 0x3004, 0x3006, 0x3008, 0x3012, 0x3014, 0x301c, + 0x301e, 0x3020, 0x3022, 0x302a, 0x3030, 0x3032, 0x3036, 0x3038, 0x303e, 0x3041, 0x3099, 0x309b, 0x309d, 0x30a1, 0x30fb, 0x30fd, 0x3105, 0x3131, 0x3190, 0x3192, + 0x3196, 0x31a0, 0x3200, 0x3220, 0x322a, 0x3260, 0x327f, 0x3281, 0x328a, 0x32c0, 0x32d0, 0x3300, 0x337b, 0x33e0, 0x3400, 0x4e00, 0xa000, 0xa490, 0xa4a4, 0xa4b5, + 0xa4c2, 0xa4c6, 0xac00, 0xd800, 0xe000, 0xf900, 0xfb00, 0xfb13, 0xfb1d, 0xfb20, 0xfb29, 0xfb2b, 0xfb38, 0xfb3e, 0xfb40, 0xfb43, 0xfb46, 0xfbd3, 0xfd3e, 0xfd50, + 0xfd92, 0xfdf0, 0xfe20, 0xfe30, 0xfe32, 0xfe34, 0xfe36, 0xfe49, 0xfe4d, 0xfe50, 0xfe54, 0xfe58, 0xfe5a, 0xfe5f, 0xfe62, 0xfe65, 0xfe68, 0xfe6b, 0xfe70, 0xfe74, + 0xfe76, 0xfeff, 0xff01, 0xff04, 0xff06, 0xff08, 0xff0a, 0xff0d, 0xff0f, 0xff11, 0xff1a, 0xff1c, 0xff1f, 0xff21, 0xff3b, 0xff3d, 0xff3f, 0xff41, 0xff5b, 0xff5d, + 0xff61, 0xff63, 0xff65, 0xff67, 0xff70, 0xff72, 0xff9e, 0xffa0, 0xffc2, 0xffca, 0xffd2, 0xffda, 0xffe0, 0xffe2, 0xffe4, 0xffe6, 0xffe8, 0xffea, 0xffed, 0xfff9, + 0xfffc +}; + +constexpr KChar typeValues[] = { + 0x1f, 0xf, 0x21, 0x180c, 0x23, 0x18, 0x25, 0x181a, 0x27, 0x18, 0x29, 0x1615, 0x2c, 0x1918, 0x2e, 0x1418, 0x30, 0x1809, 0x39, 0x9, + 0x3b, 0x18, 0x3e, 0x19, 0x40, 0x18, 0x5a, 0x1, 0x5c, 0x1518, 0x5e, 0x161b, 0x60, 0x171b, 0x7a, 0x2, 0x7c, 0x1519, 0x7e, 0x1619, + 0x9f, 0xf, 0xa1, 0x180c, 0xa5, 0x1a, 0xa7, 0x1c, 0xa9, 0x1c1b, 0xab, 0x1d02, 0xad, 0x1419, 0xb0, 0x1b1c, 0xb2, 0x190b, 0xb4, 0xb1b, + 0xb6, 0x21c, 0xb8, 0x181b, 0xba, 0xb02, 0xbc, 0x1e0b, 0xbe, 0xb, 0xc0, 0x1801, 0xd6, 0x1, 0xd8, 0x1901, 0xde, 0x1, 0xf6, 0x2, + 0xf8, 0x1902, 0xff, 0x2, 0x137, 0x201, 0x148, 0x102, 0x178, 0x201, 0x17e, 0x102, 0x180, 0x2, 0x182, 0x1, 0x186, 0x201, 0x189, 0x102, + 0x18b, 0x1, 0x18d, 0x2, 0x191, 0x1, 0x193, 0x102, 0x196, 0x201, 0x198, 0x1, 0x19b, 0x2, 0x19d, 0x1, 0x19f, 0x102, 0x1a6, 0x201, + 0x1aa, 0x102, 0x1ae, 0x201, 0x1b1, 0x102, 0x1b3, 0x1, 0x1b7, 0x102, 0x1b9, 0x201, 0x1bb, 0x502, 0x1bd, 0x201, 0x1bf, 0x2, 0x1c3, 0x5, + 0x1c5, 0x301, 0x1c7, 0x102, 0x1c9, 0x203, 0x1cb, 0x301, 0x1dc, 0x102, 0x1ef, 0x201, 0x1f1, 0x102, 0x1f3, 0x203, 0x1f6, 0x201, 0x1f8, 0x1, + 0x21f, 0x201, 0x233, 0x201, 0x2ad, 0x2, 0x2b8, 0x4, 0x2ba, 0x1b, 0x2c1, 0x4, 0x2cf, 0x1b, 0x2d1, 0x4, 0x2df, 0x1b, 0x2e4, 0x4, + 0x2ed, 0x1b, 0x2ee, 0x4, 0x34e, 0x6, 0x362, 0x6, 0x375, 0x1b, 0x37a, 0x4, 0x37e, 0x18, 0x385, 0x1b, 0x388, 0x1801, 0x38a, 0x1, + 0x38c, 0x1, 0x38f, 0x1, 0x391, 0x102, 0x3a1, 0x1, 0x3ab, 0x1, 0x3ce, 0x2, 0x3d1, 0x2, 0x3d4, 0x1, 0x3d7, 0x2, 0x3ef, 0x201, + 0x3f3, 0x2, 0x42f, 0x1, 0x45f, 0x2, 0x481, 0x201, 0x483, 0x61c, 0x486, 0x6, 0x489, 0x7, 0x4c0, 0x201, 0x4c4, 0x102, 0x4c8, 0x102, + 0x4cc, 0x102, 0x4f5, 0x201, 0x4f9, 0x201, 0x556, 0x1, 0x55a, 0x418, 0x55f, 0x18, 0x587, 0x2, 0x58a, 0x1814, 0x5a1, 0x6, 0x5b9, 0x6, + 0x5bd, 0x6, 0x5c1, 0x618, 0x5c4, 0x1806, 0x5ea, 0x5, 0x5f2, 0x5, 0x5f4, 0x18, 0x60c, 0x18, 0x61b, 0x1800, 0x61f, 0x1800, 0x63a, 0x5, + 0x641, 0x504, 0x64a, 0x5, 0x655, 0x6, 0x669, 0x9, 0x66d, 0x18, 0x671, 0x506, 0x6d3, 0x5, 0x6d5, 0x518, 0x6dc, 0x6, 0x6de, 0x7, + 0x6e4, 0x6, 0x6e6, 0x4, 0x6e8, 0x6, 0x6ea, 0x1c06, 0x6ed, 0x6, 0x6f9, 0x9, 0x6fc, 0x5, 0x6fe, 0x1c, 0x70d, 0x18, 0x710, 0x1005, + 0x712, 0x605, 0x72c, 0x5, 0x74a, 0x6, 0x7a5, 0x5, 0x7b0, 0x6, 0x902, 0x6, 0x903, 0x800, 0x939, 0x5, 0x93d, 0x506, 0x940, 0x8, + 0x948, 0x6, 0x94c, 0x8, 0x94d, 0x600, 0x951, 0x605, 0x954, 0x6, 0x961, 0x5, 0x963, 0x6, 0x965, 0x18, 0x96f, 0x9, 0x970, 0x18, + 0x982, 0x608, 0x983, 0x800, 0x98c, 0x5, 0x990, 0x5, 0x9a8, 0x5, 0x9b0, 0x5, 0x9b2, 0x5, 0x9b9, 0x5, 0x9bc, 0x6, 0x9c0, 0x8, + 0x9c4, 0x6, 0x9c8, 0x8, 0x9cc, 0x8, 0x9cd, 0x600, 0x9d7, 0x800, 0x9dd, 0x5, 0x9e1, 0x5, 0x9e3, 0x6, 0x9ef, 0x9, 0x9f1, 0x5, + 0x9f3, 0x1a, 0x9f9, 0xb, 0x9fa, 0x1c, 0xa02, 0x6, 0xa0a, 0x5, 0xa10, 0x5, 0xa28, 0x5, 0xa30, 0x5, 0xa33, 0x5, 0xa36, 0x5, + 0xa39, 0x5, 0xa3c, 0x6, 0xa40, 0x8, 0xa42, 0x6, 0xa48, 0x6, 0xa4d, 0x6, 0xa5c, 0x5, 0xa5e, 0x5, 0xa6f, 0x9, 0xa71, 0x6, + 0xa74, 0x5, 0xa82, 0x6, 0xa83, 0x800, 0xa8b, 0x5, 0xa8d, 0x500, 0xa91, 0x5, 0xaa8, 0x5, 0xab0, 0x5, 0xab3, 0x5, 0xab9, 0x5, + 0xabd, 0x506, 0xac0, 0x8, 0xac5, 0x6, 0xac8, 0x6, 0xac9, 0x800, 0xacc, 0x8, 0xacd, 0x600, 0xad0, 0x5, 0xae0, 0x5, 0xaef, 0x9, + 0xb02, 0x608, 0xb03, 0x800, 0xb0c, 0x5, 0xb10, 0x5, 0xb28, 0x5, 0xb30, 0x5, 0xb33, 0x5, 0xb39, 0x5, 0xb3d, 0x506, 0xb41, 0x608, + 0xb43, 0x6, 0xb48, 0x8, 0xb4c, 0x8, 0xb4d, 0x600, 0xb57, 0x806, 0xb5d, 0x5, 0xb61, 0x5, 0xb6f, 0x9, 0xb70, 0x1c, 0xb83, 0x806, + 0xb8a, 0x5, 0xb90, 0x5, 0xb95, 0x5, 0xb9a, 0x5, 0xb9c, 0x5, 0xb9f, 0x5, 0xba4, 0x5, 0xbaa, 0x5, 0xbb5, 0x5, 0xbb9, 0x5, + 0xbbf, 0x8, 0xbc1, 0x806, 0xbc2, 0x8, 0xbc8, 0x8, 0xbcc, 0x8, 0xbcd, 0x600, 0xbd7, 0x800, 0xbef, 0x9, 0xbf2, 0xb, 0xc03, 0x8, + 0xc0c, 0x5, 0xc10, 0x5, 0xc28, 0x5, 0xc33, 0x5, 0xc39, 0x5, 0xc40, 0x6, 0xc44, 0x8, 0xc48, 0x6, 0xc4d, 0x6, 0xc56, 0x6, + 0xc61, 0x5, 0xc6f, 0x9, 0xc83, 0x8, 0xc8c, 0x5, 0xc90, 0x5, 0xca8, 0x5, 0xcb3, 0x5, 0xcb9, 0x5, 0xcc0, 0x608, 0xcc4, 0x8, + 0xcc7, 0x806, 0xcc8, 0x8, 0xccb, 0x8, 0xccd, 0x6, 0xcd6, 0x8, 0xcde, 0x5, 0xce1, 0x5, 0xcef, 0x9, 0xd03, 0x8, 0xd0c, 0x5, + 0xd10, 0x5, 0xd28, 0x5, 0xd39, 0x5, 0xd40, 0x8, 0xd43, 0x6, 0xd48, 0x8, 0xd4c, 0x8, 0xd4d, 0x600, 0xd57, 0x800, 0xd61, 0x5, + 0xd6f, 0x9, 0xd83, 0x8, 0xd96, 0x5, 0xdb1, 0x5, 0xdbb, 0x5, 0xdbd, 0x500, 0xdc6, 0x5, 0xdca, 0x6, 0xdd1, 0x8, 0xdd4, 0x6, + 0xdd6, 0x6, 0xddf, 0x8, 0xdf3, 0x8, 0xdf4, 0x18, 0xe30, 0x5, 0xe32, 0x605, 0xe34, 0x506, 0xe3a, 0x6, 0xe40, 0x1a05, 0xe45, 0x5, + 0xe47, 0x604, 0xe4e, 0x6, 0xe50, 0x1809, 0xe59, 0x9, 0xe5b, 0x18, 0xe82, 0x5, 0xe84, 0x5, 0xe88, 0x5, 0xe8a, 0x5, 0xe8d, 0x500, + 0xe97, 0x5, 0xe9f, 0x5, 0xea3, 0x5, 0xea5, 0x500, 0xea7, 0x500, 0xeab, 0x5, 0xeb0, 0x5, 0xeb2, 0x605, 0xeb4, 0x506, 0xeb9, 0x6, + 0xebc, 0x6, 0xebd, 0x500, 0xec4, 0x5, 0xec6, 0x4, 0xecd, 0x6, 0xed9, 0x9, 0xedd, 0x5, 0xf01, 0x1c05, 0xf03, 0x1c, 0xf12, 0x18, + 0xf17, 0x1c, 0xf19, 0x6, 0xf1f, 0x1c, 0xf29, 0x9, 0xf33, 0xb, 0xf39, 0x61c, 0xf3d, 0x1615, 0xf3f, 0x8, 0xf47, 0x5, 0xf6a, 0x5, + 0xf7e, 0x6, 0xf80, 0x806, 0xf84, 0x6, 0xf86, 0x1806, 0xf88, 0x605, 0xf8b, 0x5, 0xf97, 0x6, 0xfbc, 0x6, 0xfc5, 0x1c, 0xfc7, 0x1c06, + 0xfcc, 0x1c, 0xfcf, 0x1c00, 0x1021, 0x5, 0x1027, 0x5, 0x102a, 0x5, 0x102d, 0x608, 0x1030, 0x6, 0x1032, 0x806, 0x1037, 0x6, 0x1039, 0x608, + 0x1049, 0x9, 0x104f, 0x18, 0x1055, 0x5, 0x1057, 0x8, 0x1059, 0x6, 0x10c5, 0x1, 0x10f6, 0x5, 0x10fb, 0x1800, 0x1159, 0x5, 0x11a2, 0x5, + 0x11f9, 0x5, 0x1206, 0x5, 0x1246, 0x5, 0x1248, 0x5, 0x124d, 0x5, 0x1256, 0x5, 0x1258, 0x5, 0x125d, 0x5, 0x1286, 0x5, 0x1288, 0x5, + 0x128d, 0x5, 0x12ae, 0x5, 0x12b0, 0x5, 0x12b5, 0x5, 0x12be, 0x5, 0x12c0, 0x5, 0x12c5, 0x5, 0x12ce, 0x5, 0x12d6, 0x5, 0x12ee, 0x5, + 0x130e, 0x5, 0x1310, 0x5, 0x1315, 0x5, 0x131e, 0x5, 0x1346, 0x5, 0x135a, 0x5, 0x1368, 0x18, 0x1371, 0x9, 0x137c, 0xb, 0x13f4, 0x5, + 0x166c, 0x5, 0x166e, 0x18, 0x1676, 0x5, 0x1681, 0x50c, 0x169a, 0x5, 0x169c, 0x1516, 0x16ea, 0x5, 0x16ed, 0x18, 0x16f0, 0xb, 0x17b3, 0x5, + 0x17b6, 0x8, 0x17bd, 0x6, 0x17c5, 0x8, 0x17c7, 0x806, 0x17c9, 0x608, 0x17d3, 0x6, 0x17da, 0x18, 0x17dc, 0x1a18, 0x17e9, 0x9, 0x1805, 0x18, + 0x1807, 0x1814, 0x180a, 0x18, 0x180e, 0x10, 0x1819, 0x9, 0x1842, 0x5, 0x1844, 0x405, 0x1877, 0x5, 0x18a8, 0x5, 0x18a9, 0x600, 0x1e95, 0x201, + 0x1e9b, 0x2, 0x1ef9, 0x201, 0x1f07, 0x2, 0x1f0f, 0x1, 0x1f15, 0x2, 0x1f1d, 0x1, 0x1f27, 0x2, 0x1f2f, 0x1, 0x1f37, 0x2, 0x1f3f, 0x1, + 0x1f45, 0x2, 0x1f4d, 0x1, 0x1f57, 0x2, 0x1f59, 0x100, 0x1f5b, 0x100, 0x1f5d, 0x100, 0x1f60, 0x102, 0x1f67, 0x2, 0x1f6f, 0x1, 0x1f7d, 0x2, + 0x1f87, 0x2, 0x1f8f, 0x3, 0x1f97, 0x2, 0x1f9f, 0x3, 0x1fa7, 0x2, 0x1faf, 0x3, 0x1fb4, 0x2, 0x1fb7, 0x2, 0x1fbb, 0x1, 0x1fbd, 0x1b03, + 0x1fbf, 0x1b02, 0x1fc1, 0x1b, 0x1fc4, 0x2, 0x1fc7, 0x2, 0x1fcb, 0x1, 0x1fcd, 0x1b03, 0x1fcf, 0x1b, 0x1fd3, 0x2, 0x1fd7, 0x2, 0x1fdb, 0x1, + 0x1fdf, 0x1b, 0x1fe7, 0x2, 0x1fec, 0x1, 0x1fef, 0x1b, 0x1ff4, 0x2, 0x1ff7, 0x2, 0x1ffb, 0x1, 0x1ffd, 0x1b03, 0x1ffe, 0x1b, 0x200b, 0xc, + 0x200f, 0x10, 0x2015, 0x14, 0x2017, 0x18, 0x2019, 0x1e1d, 0x201b, 0x1d15, 0x201d, 0x1e1d, 0x201f, 0x1d15, 0x2027, 0x18, 0x2029, 0xe0d, 0x202e, 0x10, + 0x2030, 0xc18, 0x2038, 0x18, 0x203a, 0x1d1e, 0x203e, 0x18, 0x2040, 0x17, 0x2043, 0x18, 0x2045, 0x1519, 0x2046, 0x16, 0x204d, 0x18, 0x206f, 0x10, + 0x2070, 0xb, 0x2079, 0xb, 0x207c, 0x19, 0x207e, 0x1516, 0x2080, 0x20b, 0x2089, 0xb, 0x208c, 0x19, 0x208e, 0x1516, 0x20af, 0x1a, 0x20dc, 0x6, + 0x20e0, 0x7, 0x20e2, 0x607, 0x20e3, 0x700, 0x2101, 0x1c, 0x2103, 0x1c01, 0x2106, 0x1c, 0x2108, 0x11c, 0x210a, 0x1c02, 0x210d, 0x1, 0x210f, 0x2, + 0x2112, 0x1, 0x2114, 0x21c, 0x2116, 0x11c, 0x2118, 0x1c, 0x211d, 0x1, 0x2123, 0x1c, 0x212a, 0x1c01, 0x212d, 0x1, 0x212f, 0x21c, 0x2131, 0x1, + 0x2133, 0x11c, 0x2135, 0x502, 0x2138, 0x5, 0x213a, 0x21c, 0x215f, 0xb, 0x2183, 0xa, 0x2194, 0x19, 0x2199, 0x1c, 0x219b, 0x19, 0x219f, 0x1c, + 0x21a1, 0x1c19, 0x21a4, 0x191c, 0x21a7, 0x1c19, 0x21ad, 0x1c, 0x21af, 0x1c19, 0x21cd, 0x1c, 0x21cf, 0x19, 0x21d1, 0x1c, 0x21d5, 0x1c19, 0x21f3, 0x1c, + 0x22f1, 0x19, 0x2307, 0x1c, 0x230b, 0x19, 0x231f, 0x1c, 0x2321, 0x19, 0x2328, 0x1c, 0x232a, 0x1516, 0x237b, 0x1c, 0x239a, 0x1c, 0x2426, 0x1c, + 0x244a, 0x1c, 0x249b, 0xb, 0x24e9, 0x1c, 0x24ea, 0xb, 0x2595, 0x1c, 0x25b6, 0x1c, 0x25b8, 0x191c, 0x25c0, 0x1c, 0x25c2, 0x191c, 0x25f7, 0x1c, + 0x2613, 0x1c, 0x266e, 0x1c, 0x2670, 0x191c, 0x2671, 0x1c00, 0x2704, 0x1c, 0x2709, 0x1c, 0x2727, 0x1c, 0x274b, 0x1c, 0x274d, 0x1c00, 0x2752, 0x1c, + 0x2756, 0x1c, 0x275e, 0x1c, 0x2767, 0x1c, 0x2793, 0xb, 0x2794, 0x1c, 0x27af, 0x1c, 0x27be, 0x1c, 0x28ff, 0x1c, 0x2e99, 0x1c, 0x2ef3, 0x1c, + 0x2fd5, 0x1c, 0x2ffb, 0x1c, 0x3001, 0x180c, 0x3003, 0x18, 0x3005, 0x41c, 0x3007, 0xa05, 0x3011, 0x1615, 0x3013, 0x1c, 0x301b, 0x1615, 0x301d, 0x1514, + 0x301f, 0x16, 0x3021, 0xa1c, 0x3029, 0xa, 0x302f, 0x6, 0x3031, 0x414, 0x3035, 0x4, 0x3037, 0x1c, 0x303a, 0xa, 0x303f, 0x1c, 0x3094, 0x5, + 0x309a, 0x6, 0x309c, 0x1b, 0x309e, 0x4, 0x30fa, 0x5, 0x30fc, 0x1704, 0x30fe, 0x4, 0x312c, 0x5, 0x318e, 0x5, 0x3191, 0x1c, 0x3195, 0xb, + 0x319f, 0x1c, 0x31b7, 0x5, 0x321c, 0x1c, 0x3229, 0xb, 0x3243, 0x1c, 0x327b, 0x1c, 0x3280, 0x1c0b, 0x3289, 0xb, 0x32b0, 0x1c, 0x32cb, 0x1c, + 0x32fe, 0x1c, 0x3376, 0x1c, 0x33dd, 0x1c, 0x33fe, 0x1c, 0x4db5, 0x5, 0x9fa5, 0x5, 0xa48c, 0x5, 0xa4a1, 0x1c, 0xa4b3, 0x1c, 0xa4c0, 0x1c, + 0xa4c4, 0x1c, 0xa4c6, 0x1c, 0xd7a3, 0x5, 0xdfff, 0x13, 0xf8ff, 0x12, 0xfa2d, 0x5, 0xfb06, 0x2, 0xfb17, 0x2, 0xfb1f, 0x506, 0xfb28, 0x5, + 0xfb2a, 0x1905, 0xfb36, 0x5, 0xfb3c, 0x5, 0xfb3e, 0x5, 0xfb41, 0x5, 0xfb44, 0x5, 0xfbb1, 0x5, 0xfd3d, 0x5, 0xfd3f, 0x1615, 0xfd8f, 0x5, + 0xfdc7, 0x5, 0xfdfb, 0x5, 0xfe23, 0x6, 0xfe31, 0x1418, 0xfe33, 0x1714, 0xfe35, 0x1517, 0xfe44, 0x1516, 0xfe4c, 0x18, 0xfe4f, 0x17, 0xfe52, 0x18, + 0xfe57, 0x18, 0xfe59, 0x1514, 0xfe5e, 0x1516, 0xfe61, 0x18, 0xfe64, 0x1419, 0xfe66, 0x19, 0xfe6a, 0x1a18, 0xfe6b, 0x1800, 0xfe72, 0x5, 0xfe74, 0x5, + 0xfefc, 0x5, 0xfeff, 0x1000, 0xff03, 0x18, 0xff05, 0x181a, 0xff07, 0x18, 0xff09, 0x1615, 0xff0c, 0x1918, 0xff0e, 0x1418, 0xff10, 0x1809, 0xff19, 0x9, + 0xff1b, 0x18, 0xff1e, 0x19, 0xff20, 0x18, 0xff3a, 0x1, 0xff3c, 0x1518, 0xff3e, 0x161b, 0xff40, 0x171b, 0xff5a, 0x2, 0xff5c, 0x1519, 0xff5e, 0x1619, + 0xff62, 0x1815, 0xff64, 0x1618, 0xff66, 0x1705, 0xff6f, 0x5, 0xff71, 0x504, 0xff9d, 0x5, 0xff9f, 0x4, 0xffbe, 0x5, 0xffc7, 0x5, 0xffcf, 0x5, + 0xffd7, 0x5, 0xffdc, 0x5, 0xffe1, 0x1a, 0xffe3, 0x1b19, 0xffe5, 0x1a1c, 0xffe6, 0x1a, 0xffe9, 0x191c, 0xffec, 0x19, 0xffee, 0x1c, 0xfffb, 0x10 +}; + +KInt getType(KChar ch) { + if (ch < 1000) { + return typeValuesCache[ch]; + } + int result = binarySearchRange(typeKeys, ARRAY_SIZE(typeKeys), ch); + int high = typeValues[result * 2]; + if (ch <= high) { + int code = typeValues[result * 2 + 1]; + if (code < 0x100) { + return code; + } + return (ch & 1) == 1 ? code >> 8 : code & 0xff; + } + return UNASSIGNED; +} + +KChar towupper_Konan(KChar ch) { + // Optimized case for ASCII. + if ('a' <= ch && ch <= 'z') { + return ch - ('a' - 'A'); + } + if (ch < 181) { + return ch; + } + if (ch < 1000) { + return uppercaseValuesCache[ch - 181]; + } + int result = binarySearchRange(uppercaseKeys, ARRAY_SIZE(uppercaseKeys), ch); + if (result >= 0) { + bool by2 = false; + KChar start = uppercaseKeys[result]; + KChar end = uppercaseValues[result * 2]; + if ((start & 0x8000) != (end & 0x8000)) { + end ^= 0x8000; + by2 = true; + } + if (ch <= end) { + if (by2 && (ch & 1) != (start & 1)) { + return ch; + } + KChar mapping = uppercaseValues[result * 2 + 1]; + return ch + mapping; + } + } + return ch; +} + +KChar towlower_Konan(KChar ch) { + // Optimized case for ASCII. + if ('A' <= ch && ch <= 'Z') { + return ch + ('a' - 'A'); + } + if (ch < 192) { + return ch; + } + if (ch < 1000) { + return lowercaseValuesCache[ch - 192]; + } + + int result = binarySearchRange(lowercaseKeys, ARRAY_SIZE(lowercaseKeys), ch); + if (result >= 0) { + bool by2 = false; + KChar start = lowercaseKeys[result]; + KChar end = lowercaseValues[result * 2]; + if ((start & 0x8000) != (end & 0x8000)) { + end ^= 0x8000; + by2 = true; + } + if (ch <= end) { + if (by2 && (ch & 1) != (start & 1)) { + return ch; + } + KChar mapping = lowercaseValues[result * 2 + 1]; + return ch + mapping; + } + } + return ch; +} + +int iswdigit_Konan(KChar ch) { + // Optimized case for ASCII. + if ('0' <= ch && ch <= '9') { + return true; + } + if (ch < 1632) { + return false; + } + return getType(ch) == DECIMAL_DIGIT_NUMBER; +} + +int iswalpha_Konan(KChar ch) { + if (('A' <= ch && ch <= 'Z') || ('a' <= ch && ch <= 'z')) { + return true; + } + if (ch < 128) { + return false; + } + int type = getType(ch); + return type >= UPPERCASE_LETTER && type <= OTHER_LETTER; +} + +int iswalnum_Konan(KChar ch) { + int type = getType(ch); + return (type >= UPPERCASE_LETTER && type <= OTHER_LETTER) + || type == DECIMAL_DIGIT_NUMBER; +} + +int iswspace_Konan(KChar ch) { + // FILE, GROUP, RECORD, UNIT separators, # Zs SPACE or # Cc CONTROLs + if ((ch >= 0x1c && ch <= 0x20) || (ch >= 0x9 && ch <= 0xd)) { + return true; + } + // not (# Zs OGHAM SPACE MARK or # Cc or # Zs NO-BREAK SPACE) + if (ch < 0x2000 && !(ch == 0x1680 || ch == 0x85 || ch == 0xA0)) { + return false; + } + // if # Zl LINE SEPARATOR or # Zp PARAGRAPH SEPARATOR or # Zs NARROW NO-BREAK SPACE + // or # Zs MEDIUM MATHEMATICAL SPACE or # Zs IDEOGRAPHIC SPACE + return ch < 0x200b || ch == 0x2028 || ch == 0x2029 || ch == 0x202F || ch == 0x205F || ch == 0x3000; +} + +int iswupper_Konan(KChar ch) { + // Optimized case for ASCII. + if ('A' <= ch && ch <= 'Z') { + return true; + } + if (ch < 128) { + return false; + } + + return getType(ch) == UPPERCASE_LETTER; +} + +int iswlower_Konan(KChar ch) { + // Optimized case for ASCII. + if ('a' <= ch && ch <= 'z') { + return true; + } + if (ch < 128) { + return false; + } + + return getType(ch) == LOWERCASE_LETTER; +} + +} // namespace + +extern "C" { + +OBJ_GETTER(CreateStringFromCString, const char* cstring) { + RETURN_RESULT_OF(utf8ToUtf16, cstring, cstring ? strlen(cstring) : 0); +} + +OBJ_GETTER(CreateStringFromUtf8, const char* utf8, uint32_t lengthBytes) { + RETURN_RESULT_OF(utf8ToUtf16, utf8, lengthBytes); +} + +char* CreateCStringFromString(KConstRef kref) { + if (kref == nullptr) return nullptr; + KString kstring = kref->array(); + const KChar* utf16 = CharArrayAddressOfElementAt(kstring, 0); + KStdString utf8; + utf8.reserve(kstring->count_); + utf8::unchecked::utf16to8(utf16, utf16 + kstring->count_, back_inserter(utf8)); + char* result = reinterpret_cast(konan::calloc(1, utf8.size() + 1)); + ::memcpy(result, utf8.c_str(), utf8.size()); + return result; +} + +void DisposeCString(char* cstring) { + if (cstring) konan::free(cstring); +} + +// String.kt +OBJ_GETTER(Kotlin_String_replace, KString thiz, KChar oldChar, KChar newChar, KBoolean ignoreCase) { + auto count = thiz->count_; + ArrayHeader* result = AllocArrayInstance(theStringTypeInfo, count, OBJ_RESULT)->array(); + const KChar* thizRaw = CharArrayAddressOfElementAt(thiz, 0); + KChar* resultRaw = CharArrayAddressOfElementAt(result, 0); + if (ignoreCase) { + KChar oldCharLower = towlower_Konan(oldChar); + for (uint32_t index = 0; index < count; ++index) { + KChar thizChar = *thizRaw++; + *resultRaw++ = towlower_Konan(thizChar) == oldCharLower ? newChar : thizChar; + } + } else { + for (uint32_t index = 0; index < count; ++index) { + KChar thizChar = *thizRaw++; + *resultRaw++ = thizChar == oldChar ? newChar : thizChar; + } + } + RETURN_OBJ(result->obj()); +} + +OBJ_GETTER(Kotlin_String_plusImpl, KString thiz, KString other) { + RuntimeAssert(thiz != nullptr, "this cannot be null"); + RuntimeAssert(other != nullptr, "other cannot be null"); + RuntimeAssert(thiz->type_info() == theStringTypeInfo, "Must be a string"); + RuntimeAssert(other->type_info() == theStringTypeInfo, "Must be a string"); + RuntimeAssert(thiz->count_ <= static_cast(std::numeric_limits::max()), "this cannot be this large"); + RuntimeAssert(other->count_ <= static_cast(std::numeric_limits::max()), "other cannot be this large"); + // Since thiz and other sizes are bounded by int32_t max value, their sum cannot exceed uint32_t max value - 1. + uint32_t result_length = thiz->count_ + other->count_; + if (result_length > static_cast(std::numeric_limits::max())) { + ThrowArrayIndexOutOfBoundsException(); + } + ArrayHeader* result = AllocArrayInstance(theStringTypeInfo, result_length, OBJ_RESULT)->array(); + memcpy( + CharArrayAddressOfElementAt(result, 0), + CharArrayAddressOfElementAt(thiz, 0), + thiz->count_ * sizeof(KChar)); + memcpy( + CharArrayAddressOfElementAt(result, thiz->count_), + CharArrayAddressOfElementAt(other, 0), + other->count_ * sizeof(KChar)); + RETURN_OBJ(result->obj()); +} + +OBJ_GETTER(Kotlin_String_toUpperCase, KString thiz) { + auto count = thiz->count_; + ArrayHeader* result = AllocArrayInstance(theStringTypeInfo, count, OBJ_RESULT)->array(); + const KChar* thizRaw = CharArrayAddressOfElementAt(thiz, 0); + KChar* resultRaw = CharArrayAddressOfElementAt(result, 0); + for (uint32_t index = 0; index < count; ++index) { + *resultRaw++ = towupper_Konan(*thizRaw++); + } + RETURN_OBJ(result->obj()); +} + +OBJ_GETTER(Kotlin_String_toLowerCase, KString thiz) { + auto count = thiz->count_; + ArrayHeader* result = AllocArrayInstance(theStringTypeInfo, count, OBJ_RESULT)->array(); + const KChar* thizRaw = CharArrayAddressOfElementAt(thiz, 0); + KChar* resultRaw = CharArrayAddressOfElementAt(result, 0); + for (uint32_t index = 0; index < count; ++index) { + *resultRaw++ = towlower_Konan(*thizRaw++); + } + RETURN_OBJ(result->obj()); +} + +OBJ_GETTER(Kotlin_String_unsafeStringFromCharArray, KConstRef thiz, KInt start, KInt size) { + const ArrayHeader* array = thiz->array(); + RuntimeAssert(array->type_info() == theCharArrayTypeInfo, "Must use a char array"); + + if (size == 0) { + RETURN_RESULT_OF0(TheEmptyString); + } + + ArrayHeader* result = AllocArrayInstance(theStringTypeInfo, size, OBJ_RESULT)->array(); + memcpy(CharArrayAddressOfElementAt(result, 0), + CharArrayAddressOfElementAt(array, start), + size * sizeof(KChar)); + RETURN_OBJ(result->obj()); +} + +OBJ_GETTER(Kotlin_String_toCharArray, KString string, KInt start, KInt size) { + ArrayHeader* result = AllocArrayInstance(theCharArrayTypeInfo, size, OBJ_RESULT)->array(); + memcpy(CharArrayAddressOfElementAt(result, 0), + CharArrayAddressOfElementAt(string, start), + size * sizeof(KChar)); + RETURN_OBJ(result->obj()); +} + +OBJ_GETTER(Kotlin_String_subSequence, KString thiz, KInt startIndex, KInt endIndex) { + if (startIndex < 0 || static_cast(endIndex) > thiz->count_ || startIndex > endIndex) { + // TODO: is it correct exception? + ThrowArrayIndexOutOfBoundsException(); + } + if (startIndex == endIndex) { + RETURN_RESULT_OF0(TheEmptyString); + } + KInt length = endIndex - startIndex; + ArrayHeader* result = AllocArrayInstance(theStringTypeInfo, length, OBJ_RESULT)->array(); + memcpy(CharArrayAddressOfElementAt(result, 0), + CharArrayAddressOfElementAt(thiz, startIndex), + length * sizeof(KChar)); + RETURN_OBJ(result->obj()); +} + +KInt Kotlin_String_compareTo(KString thiz, KString other) { + int result = memcmp( + CharArrayAddressOfElementAt(thiz, 0), + CharArrayAddressOfElementAt(other, 0), + (thiz->count_ < other->count_ ? thiz->count_ : other->count_) * sizeof(KChar)); + if (result != 0) return result; + int diff = thiz->count_ - other->count_; + if (diff == 0) return 0; + return diff < 0 ? -1 : 1; +} + +KInt Kotlin_String_compareToIgnoreCase(KString thiz, KConstRef other) { + RuntimeAssert(thiz->type_info() == theStringTypeInfo && + other->type_info() == theStringTypeInfo, "Must be strings"); + // Important, due to literal internalization. + KString otherString = other->array(); + if (thiz == otherString) return 0; + auto count = thiz->count_ < otherString->count_ ? thiz->count_ : otherString->count_; + const KChar* thizRaw = CharArrayAddressOfElementAt(thiz, 0); + const KChar* otherRaw = CharArrayAddressOfElementAt(otherString, 0); + for (uint32_t index = 0; index < count; ++index) { + int diff = towlower_Konan(*thizRaw++) - towlower_Konan(*otherRaw++); + if (diff != 0) + return diff < 0 ? -1 : 1; + } + if (otherString->count_ == thiz->count_) + return 0; + else if (otherString->count_ > thiz->count_) + return -1; + else + return 1; +} + + +KChar Kotlin_String_get(KString thiz, KInt index) { + // We couldn't have created a string bigger than max KInt value. + // So if index is < 0, conversion to an unsigned value would make it bigger + // than the array size. + if (static_cast(index) >= thiz->count_) { + ThrowArrayIndexOutOfBoundsException(); + } + return *CharArrayAddressOfElementAt(thiz, index); +} + +KInt Kotlin_String_getStringLength(KString thiz) { + return thiz->count_; +} + +const char* unsafeByteArrayAsCString(KConstRef thiz, KInt start, KInt size) { + const ArrayHeader* array = thiz->array(); + RuntimeAssert(array->type_info() == theByteArrayTypeInfo, "Must use a byte array"); + return reinterpret_cast(ByteArrayAddressOfElementAt(array, start)); +} + +OBJ_GETTER(Kotlin_ByteArray_unsafeStringFromUtf8OrThrow, KConstRef thiz, KInt start, KInt size) { + if (size == 0) { + RETURN_RESULT_OF0(TheEmptyString); + } + const char* rawString = unsafeByteArrayAsCString(thiz, start, size); + RETURN_RESULT_OF(utf8ToUtf16OrThrow, rawString, size); +} + +OBJ_GETTER(Kotlin_ByteArray_unsafeStringFromUtf8, KConstRef thiz, KInt start, KInt size) { + if (size == 0) { + RETURN_RESULT_OF0(TheEmptyString); + } + const char* rawString = unsafeByteArrayAsCString(thiz, start, size); + RETURN_RESULT_OF(utf8ToUtf16, rawString, size); +} + +OBJ_GETTER(Kotlin_String_unsafeStringToUtf8, KString thiz, KInt start, KInt size) { + RETURN_RESULT_OF(unsafeUtf16ToUtf8Impl, thiz, start, size); +} + +OBJ_GETTER(Kotlin_String_unsafeStringToUtf8OrThrow, KString thiz, KInt start, KInt size) { + RETURN_RESULT_OF(unsafeUtf16ToUtf8Impl, thiz, start, size); +} + +KInt Kotlin_StringBuilder_insertString(KRef builder, KInt distIndex, KString fromString, KInt sourceIndex, KInt count) { + auto toArray = builder->array(); + RuntimeAssert(sourceIndex >= 0 && static_cast(sourceIndex + count) <= fromString->count_, "must be true"); + RuntimeAssert(distIndex >= 0 && static_cast(distIndex + count) <= toArray->count_, "must be true"); + memcpy(CharArrayAddressOfElementAt(toArray, distIndex), + CharArrayAddressOfElementAt(fromString, sourceIndex), + count * sizeof(KChar)); + return count; +} + +KInt Kotlin_StringBuilder_insertInt(KRef builder, KInt position, KInt value) { + auto toArray = builder->array(); + RuntimeAssert(toArray->count_ >= static_cast(11 + position), "must be true"); + char cstring[12]; + auto length = konan::snprintf(cstring, sizeof(cstring), "%d", value); + RuntimeAssert(length >= 0, "This should never happen"); // may be overkill + RuntimeAssert(static_cast(length) < sizeof(cstring), "Unexpectedly large value"); // Can't be, but this is what sNprintf for + auto* from = &cstring[0]; + auto* to = CharArrayAddressOfElementAt(toArray, position); + while (*from) { + *to++ = *from++; + } + return from - cstring; +} + + +KBoolean Kotlin_String_equals(KString thiz, KConstRef other) { + if (other == nullptr || other->type_info() != theStringTypeInfo) return false; + // Important, due to literal internalization. + KString otherString = other->array(); + if (thiz == otherString) return true; + return thiz->count_ == otherString->count_ && + memcmp(CharArrayAddressOfElementAt(thiz, 0), + CharArrayAddressOfElementAt(otherString, 0), + thiz->count_ * sizeof(KChar)) == 0; +} + +KBoolean Kotlin_String_equalsIgnoreCase(KString thiz, KConstRef other) { + RuntimeAssert(thiz->type_info() == theStringTypeInfo && + other->type_info() == theStringTypeInfo, "Must be strings"); + // Important, due to literal internalization. + KString otherString = other->array(); + if (thiz == otherString) return true; + if (thiz->count_ != otherString->count_) return false; + auto count = thiz->count_; + const KChar* thizRaw = CharArrayAddressOfElementAt(thiz, 0); + const KChar* otherRaw = CharArrayAddressOfElementAt(otherString, 0); + for (uint32_t index = 0; index < count; ++index) { + if (towlower_Konan(*thizRaw++) != towlower_Konan(*otherRaw++)) return false; + } + return true; +} + +KBoolean Kotlin_String_regionMatches(KString thiz, KInt thizOffset, + KString other, KInt otherOffset, + KInt length, KBoolean ignoreCase) { + if (length < 0 || + thizOffset < 0 || length > static_cast(thiz->count_) - thizOffset || + otherOffset < 0 || length > static_cast(other->count_) - otherOffset) { + return false; + } + const KChar* thizRaw = CharArrayAddressOfElementAt(thiz, thizOffset); + const KChar* otherRaw = CharArrayAddressOfElementAt(other, otherOffset); + if (ignoreCase) { + for (KInt index = 0; index < length; ++index) { + if (towlower_Konan(*thizRaw++) != towlower_Konan(*otherRaw++)) return false; + } + } else { + for (KInt index = 0; index < length; ++index) { + if (*thizRaw++ != *otherRaw++) return false; + } + } + return true; +} + +KBoolean Kotlin_Char_isDefined(KChar ch) { + // TODO: fixme! + RuntimeAssert(false, "Kotlin_Char_isDefined() is not implemented"); + return true; +} + +KBoolean Kotlin_Char_isLetter(KChar ch) { + return iswalpha_Konan(ch) != 0; +} + +KBoolean Kotlin_Char_isLetterOrDigit(KChar ch) { + return iswalnum_Konan(ch) != 0; +} + +KBoolean Kotlin_Char_isDigit(KChar ch) { + return iswdigit_Konan(ch) != 0; +} + +KBoolean Kotlin_Char_isIdentifierIgnorable(KChar ch) { + RuntimeAssert(false, "Kotlin_Char_isIdentifierIgnorable() is not implemented"); + return false; +} + +KBoolean Kotlin_Char_isISOControl(KChar ch) { + return (ch <= 0x1F) || (ch >= 0x7F && ch <= 0x9F); +} + +KBoolean Kotlin_Char_isHighSurrogate(KChar ch) { + return ((ch & 0xfc00) == 0xd800); +} + +KBoolean Kotlin_Char_isLowSurrogate(KChar ch) { + return ((ch & 0xfc00) == 0xdc00); +} + +KBoolean Kotlin_Char_isWhitespace(KChar ch) { + return iswspace_Konan(ch) != 0; +} + +KBoolean Kotlin_Char_isLowerCase(KChar ch) { + return iswlower_Konan(ch) != 0; +} + +KBoolean Kotlin_Char_isUpperCase(KChar ch) { + return iswupper_Konan(ch) != 0; +} + +KChar Kotlin_Char_toLowerCase(KChar ch) { + return towlower_Konan(ch); +} + +KChar Kotlin_Char_toUpperCase(KChar ch) { + return towupper_Konan(ch); +} + +KInt Kotlin_Char_getType(KChar ch) { + return getType(ch); +} + +constexpr KInt digits[] = { + 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, + -1, -1, -1, -1, -1, -1, -1, + 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, + 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, + 30, 31, 32, 33, 34, 35, + -1, -1, -1, -1, -1, -1, + 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, + 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, + 30, 31, 32, 33, 34, 35 +}; + +// Based on Apache Harmony implementation. +// Radix check is performed on the Kotlin side. +KInt Kotlin_Char_digitOfChecked(KChar ch, KInt radix) { + + KInt result = -1; + if (ch >= 0x30 /* 0 */ && ch <= 0x7a /* z */) { + result = digits[ch - 0x30]; + } else { + int index = -1; + index = binarySearchRange(digitKeys, ARRAY_SIZE(digitKeys), ch); + if (index >= 0 && ch <= digitValues[index * 2]) { + result = ch - digitValues[index * 2 + 1]; + } + } + if (result >= radix) return -1; + return result; +} + +KInt Kotlin_String_indexOfChar(KString thiz, KChar ch, KInt fromIndex) { + if (fromIndex < 0) { + fromIndex = 0; + } + if (static_cast(fromIndex) > thiz->count_) { + return -1; + } + KInt count = thiz->count_; + const KChar* thizRaw = CharArrayAddressOfElementAt(thiz, fromIndex); + while (fromIndex < count) { + if (*thizRaw++ == ch) return fromIndex; + fromIndex++; + } + return -1; +} + +KInt Kotlin_String_lastIndexOfChar(KString thiz, KChar ch, KInt fromIndex) { + if (fromIndex < 0 || thiz->count_ == 0) { + return -1; + } + if (static_cast(fromIndex) >= thiz->count_) { + fromIndex = thiz->count_ - 1; + } + KInt index = fromIndex; + const KChar* thizRaw = CharArrayAddressOfElementAt(thiz, index); + while (index >= 0) { + if (*thizRaw-- == ch) return index; + index--; + } + return -1; +} + +// TODO: or code up Knuth-Moris-Pratt. +KInt Kotlin_String_indexOfString(KString thiz, KString other, KInt fromIndex) { + if (fromIndex < 0) { + fromIndex = 0; + } + if (static_cast(fromIndex) >= thiz->count_) { + return (other->count_ == 0) ? thiz->count_ : -1; + } + if (static_cast(other->count_) > static_cast(thiz->count_) - fromIndex) { + return -1; + } + // An empty string can be always found. + if (other->count_ == 0) { + return fromIndex; + } + const KChar* thizRaw = CharArrayAddressOfElementAt(thiz, fromIndex); + const KChar* otherRaw = CharArrayAddressOfElementAt(other, 0); + void* result = konan::memmem(thizRaw, (thiz->count_ - fromIndex) * sizeof(KChar), + otherRaw, other->count_ * sizeof(KChar)); + if (result == nullptr) return -1; + + return (reinterpret_cast(result) - reinterpret_cast( + CharArrayAddressOfElementAt(thiz, 0))) / sizeof(KChar); +} + +KInt Kotlin_String_lastIndexOfString(KString thiz, KString other, KInt fromIndex) { + KInt count = thiz->count_; + KInt otherCount = other->count_; + + if (fromIndex < 0 || otherCount > count) { + return -1; + } + if (otherCount == 0) { + return fromIndex < count ? fromIndex : count; + } + + KInt start = fromIndex; + if (fromIndex > count - otherCount) + start = count - otherCount; + KChar firstChar = *CharArrayAddressOfElementAt(other, 0); + while (true) { + KInt candidate = Kotlin_String_lastIndexOfChar(thiz, firstChar, start); + if (candidate == -1) return -1; + KInt offsetThiz = candidate; + KInt offsetOther = 0; + while (++offsetOther < otherCount && + *CharArrayAddressOfElementAt(thiz, ++offsetThiz) == + *CharArrayAddressOfElementAt(other, offsetOther)) {} + if (offsetOther == otherCount) { + return candidate; + } + start = candidate - 1; + } +} + +KInt Kotlin_String_hashCode(KString thiz) { + // TODO: consider caching strings hashes. + // TODO: maybe use some simpler hashing algorithm? + // Note that we don't use Java's string hash. + return CityHash64( + CharArrayAddressOfElementAt(thiz, 0), thiz->count_ * sizeof(KChar)); +} + +const KChar* Kotlin_String_utf16pointer(KString message) { + RuntimeAssert(message->type_info() == theStringTypeInfo, "Must use a string"); + const KChar* utf16 = CharArrayAddressOfElementAt(message, 0); + return utf16; +} + +KInt Kotlin_String_utf16length(KString message) { + RuntimeAssert(message->type_info() == theStringTypeInfo, "Must use a string"); + return message->count_ * sizeof(KChar); +} + + +} // extern "C" diff --git a/kotlin-native/runtime/src/main/cpp/KString.h b/kotlin-native/runtime/src/main/cpp/KString.h new file mode 100644 index 00000000000..eaf8139ae6f --- /dev/null +++ b/kotlin-native/runtime/src/main/cpp/KString.h @@ -0,0 +1,57 @@ +/* + * Copyright 2010-2017 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef RUNTIME_KSTRING_H +#define RUNTIME_KSTRING_H + +#include "Common.h" +#include "Memory.h" +#include "Types.h" +#include "TypeInfo.h" + +#ifdef __cplusplus +extern "C" { +#endif + +OBJ_GETTER(CreateStringFromCString, const char* cstring); +OBJ_GETTER(CreateStringFromUtf8, const char* utf8, uint32_t lengthBytes); +char* CreateCStringFromString(KConstRef kstring); +void DisposeCString(char* cstring); + +#ifdef __cplusplus +} +#endif + +template +int binarySearchRange(const T* array, int arrayLength, T needle) { + int bottom = 0; + int top = arrayLength - 1; + int middle = -1; + T value = 0; + while (bottom <= top) { + middle = (bottom + top) / 2; + value = array[middle]; + if (needle > value) + bottom = middle + 1; + else if (needle == value) + return middle; + else + top = middle - 1; + } + return middle - (needle < value ? 1 : 0); +} + +#endif // RUNTIME_KSTRING_H diff --git a/kotlin-native/runtime/src/main/cpp/KotlinMath.cpp b/kotlin-native/runtime/src/main/cpp/KotlinMath.cpp new file mode 100644 index 00000000000..17e19c8e123 --- /dev/null +++ b/kotlin-native/runtime/src/main/cpp/KotlinMath.cpp @@ -0,0 +1,580 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include +#include + +#include "DoubleConversions.h" +#include "Exceptions.h" +#include "KotlinMath.h" +#include "ReturnSlot.h" +#include "Types.h" + +#if (__MINGW32__ || __MINGW64__) +#define KONAN_NEED_ASINH_ACOSH 1 +#else +#define KONAN_NEED_ASINH_ACOSH 0 +#endif + + +#if KONAN_NEED_ASINH_ACOSH +namespace { + + // MinGW's implmenetation of asinh/acosh function returns NaN for large arguments so we use another implementation. + // Both implementations derived from boost special math functions and are also used by Kotlin/JVM. + // Copyright Eric Ford & Hubert Holin 2001. + + constexpr KDouble LN2 = 0.69314718055994530942; + constexpr KDouble SQRT2 = 1.41421356237309504880; + + KDouble taylor_2_bound = sqrt(DBL_EPSILON); + KDouble taylor_n_bound = sqrt(taylor_2_bound); + KDouble upper_taylor_2_bound = 1.0 / taylor_2_bound; + KDouble upper_taylor_n_bound = 1.0 / taylor_n_bound; + + KDouble custom_asinh(KDouble x) { + if (x >= +taylor_n_bound) { + if (x > upper_taylor_n_bound) { + if (x > upper_taylor_2_bound) { + // approximation by laurent series in 1/x at 0+ order from -1 to 0 + return log(x) + LN2; + } else { + // approximation by laurent series in 1/x at 0+ order from -1 to 1 + return log(x * 2 + (1.0 / (x * 2))); + } + } else { + return log(x + sqrt(x * x + 1)); + } + } else if (x <= -taylor_n_bound) { + return -custom_asinh(-x); + } else { + // approximation by taylor series in x at 0 up to order 2 + KDouble result = x; + if (fabs(x) >= taylor_2_bound) { + // approximation by taylor series in x at 0 up to order 4 + result -= (x * x * x) / 6; + } + return result; + } + } + + KDouble custom_acosh(KDouble x) { + if (x < 1) { + return NAN; + } else if (x > upper_taylor_2_bound) { + // approximation by laurent series in 1/x at 0+ order from -1 to 0 + return log(x) + LN2; + } else if (x - 1 >= taylor_n_bound) { + return log(x + sqrt(x * x - 1)); + } else { + KDouble y = sqrt(x - 1); + // approximation by taylor series in y at 0 up to order 2 + KDouble result = y; + if (y >= taylor_2_bound) { + // approximation by taylor series in y at 0 up to order 4 + result -= (y * y * y) / 12; + } + return SQRT2 * result; + } + } +} +#endif + +extern "C" { + +#ifndef KONAN_NO_MATH // We have a platform math library. Call its math functions. + +#ifndef KONAN_WASM // Use libm. + +// region Double math. + +KDouble Kotlin_math_sin(KDouble x) { return sin(x); } +KDouble Kotlin_math_cos(KDouble x) { return cos(x); } +KDouble Kotlin_math_tan(KDouble x) { return tan(x); } +KDouble Kotlin_math_asin(KDouble x) { return asin(x); } +KDouble Kotlin_math_acos(KDouble x) { return acos(x); } +KDouble Kotlin_math_atan(KDouble x) { return atan(x); } +KDouble Kotlin_math_atan2(KDouble y, KDouble x) { return atan2(y, x); } + +KDouble Kotlin_math_sinh(KDouble x) { return sinh(x); } +KDouble Kotlin_math_cosh(KDouble x) { return cosh(x); } +KDouble Kotlin_math_tanh(KDouble x) { return tanh(x); } + +KDouble Kotlin_math_asinh(KDouble x) { +#if (KONAN_NEED_ASINH_ACOSH) + return custom_asinh(x); +#else + return asinh(x); +#endif +} + +KDouble Kotlin_math_acosh(KDouble x) { +#if (KONAN_NEED_ASINH_ACOSH) + return custom_acosh(x); +#else + return acosh(x); +#endif +} + +KDouble Kotlin_math_atanh(KDouble x) { return atanh(x); } + +KDouble Kotlin_math_hypot(KDouble x, KDouble y) { + if (isinf(x) || isinf(y)) return INFINITY; + if (isnan(x) || isnan(y)) return NAN; + return hypot(x, y); +} + +KDouble Kotlin_math_sqrt(KDouble x) { return sqrt(x); } +KDouble Kotlin_math_exp(KDouble x) { return exp(x); } +KDouble Kotlin_math_expm1(KDouble x) { return expm1(x); } + +KDouble Kotlin_math_ln(KDouble x) { return log(x); } +KDouble Kotlin_math_log10(KDouble x) { return log10(x); } +KDouble Kotlin_math_log2(KDouble x) { return log2(x); } +KDouble Kotlin_math_ln1p(KDouble x) { return log1p(x); } + +KDouble Kotlin_math_ceil(KDouble x) { return ceil(x); } +KDouble Kotlin_math_floor(KDouble x) { return floor(x); } +KDouble Kotlin_math_round(KDouble x) { return rint(x); } + +KDouble Kotlin_math_abs(KDouble x) { return fabs(x); } + +// extensions + +KDouble Kotlin_math_Double_pow(KDouble thiz, KDouble x) { + // Kotlin corner cases + if (x == 0.0 || x == -0.0) return 1.0; + if (isinf(x) && (thiz == 1.0 || thiz == -1.0)) return NAN; + return pow(thiz, x); +} + +KDouble Kotlin_math_Double_IEEErem(KDouble thiz, KDouble divisor) { return remainder(thiz, divisor); } +KDouble Kotlin_math_Double_withSign(KDouble thiz, KDouble sign) { return copysign(thiz, sign); } + +KDouble Kotlin_math_Double_nextUp(KDouble thiz) { return nextafter(thiz, HUGE_VAL); } +KDouble Kotlin_math_Double_nextDown(KDouble thiz) { return nextafter(thiz, -HUGE_VAL); } +KDouble Kotlin_math_Double_nextTowards(KDouble thiz, KDouble to) { + return (thiz == to) ? to : nextafter(thiz, to); +} + +KBoolean Kotlin_math_Double_signBit(KDouble thiz) { return signbit(thiz) != 0; } + +// endregion + +// region Float math. + +KFloat Kotlin_math_sinf(KFloat x) { return sinf(x); } +KFloat Kotlin_math_cosf(KFloat x) { return cosf(x); } +KFloat Kotlin_math_tanf(KFloat x) { return tanf(x); } +KFloat Kotlin_math_asinf(KFloat x) { return asinf(x); } +KFloat Kotlin_math_acosf(KFloat x) { return acosf(x); } +KFloat Kotlin_math_atanf(KFloat x) { return atanf(x); } +KFloat Kotlin_math_atan2f(KFloat y, KFloat x) { return atan2f(y, x); } + +KFloat Kotlin_math_sinhf(KFloat x) { return sinhf(x); } +KFloat Kotlin_math_coshf(KFloat x) { return coshf(x); } +KFloat Kotlin_math_tanhf(KFloat x) { return tanhf(x); } + +KFloat Kotlin_math_asinhf(KFloat x) { +#if (KONAN_NEED_ASINH_ACOSH) + return (KFloat)custom_asinh((KDouble)x); +#else + return asinhf(x); +#endif +} + +KFloat Kotlin_math_acoshf(KFloat x) { +#if (KONAN_NEED_ASINH_ACOSH) + return (KFloat)custom_acosh((KDouble)x); +#else + return acoshf(x); +#endif +} + +KFloat Kotlin_math_atanhf(KFloat x) { return atanhf(x); } + +KFloat Kotlin_math_hypotf(KFloat x, KFloat y) { + if (isinf(x) || isinf(y)) return INFINITY; + if (isnan(x) || isnan(y)) return NAN; + return hypotf(x, y); +} + +KFloat Kotlin_math_sqrtf(KFloat x) { return sqrtf(x); } +KFloat Kotlin_math_expf(KFloat x) { return expf(x); } +KFloat Kotlin_math_expm1f(KFloat x) { return expm1f(x); } + +KFloat Kotlin_math_lnf(KFloat x) { return logf(x); } +KFloat Kotlin_math_log10f(KFloat x) { return log10f(x); } +KFloat Kotlin_math_log2f(KFloat x) { return log2f(x); } +KFloat Kotlin_math_ln1pf(KFloat x) { return log1pf(x); } + +KFloat Kotlin_math_ceilf(KFloat x) { return ceilf(x); } +KFloat Kotlin_math_floorf(KFloat x) { return floorf(x); } +KFloat Kotlin_math_roundf(KFloat x) { return rintf(x); } + +KFloat Kotlin_math_absf(KFloat x) { return fabsf(x); } + +// extensions + +KFloat Kotlin_math_Float_pow(KFloat thiz, KFloat x) { + // Kotlin corner cases + if (x == 0.0 || x == -0.0) return 1.0; + if (isinf(x) && (thiz == 1.0 || thiz == -1.0)) return NAN; + return powf(thiz, x); +} + +KFloat Kotlin_math_Float_IEEErem(KFloat thiz, KFloat divisor) { return remainderf(thiz, divisor); } +KFloat Kotlin_math_Float_withSign(KFloat thiz, KFloat sign) { return copysignf(thiz, sign); } + +KFloat Kotlin_math_Float_nextUp(KFloat thiz) { return nextafterf(thiz, HUGE_VALF); } +KFloat Kotlin_math_Float_nextDown(KFloat thiz) { return nextafterf(thiz, -HUGE_VALF); } +KFloat Kotlin_math_Float_nextTowards(KFloat thiz, KFloat to) { + return (thiz == to) ? to : nextafterf(thiz, to); +} + +KBoolean Kotlin_math_Float_signBit(KFloat thiz) { return signbit(thiz) != 0; } + +// endregion + +// region Integer math. + +KInt Kotlin_math_absi(KInt x) { return labs(x); } +KLong Kotlin_math_absl(KLong x) { return llabs(x); } + +// endregion + +#else // KONAN_WASM defined. Use JS math implementation. + +#define RETURN_RESULT_OF_JS_CALL(call, doubleArg) { \ + call(doubleUpper(doubleArg), doubleLower(doubleArg)); \ + return ReturnSlot_getDouble(); \ +} + +#define RETURN_RESULT_OF_JS_CALL2(call, doubleArg1, doubleArg2) { \ + call(doubleUpper(doubleArg1), \ + doubleLower(doubleArg1), \ + doubleUpper(doubleArg2), \ + doubleLower(doubleArg2)); \ + return ReturnSlot_getDouble(); \ +} + +KDouble Kotlin_math_sin(KDouble x) { RETURN_RESULT_OF_JS_CALL(knjs__Math_sin, x); } +KDouble Kotlin_math_cos(KDouble x) { RETURN_RESULT_OF_JS_CALL(knjs__Math_cos, x); } +KDouble Kotlin_math_tan(KDouble x) { RETURN_RESULT_OF_JS_CALL(knjs__Math_tan, x); } +KDouble Kotlin_math_asin(KDouble x) { RETURN_RESULT_OF_JS_CALL(knjs__Math_asin, x); } +KDouble Kotlin_math_acos(KDouble x) { RETURN_RESULT_OF_JS_CALL(knjs__Math_acos, x); } +KDouble Kotlin_math_atan(KDouble x) { RETURN_RESULT_OF_JS_CALL(knjs__Math_atan, x); } + +KDouble Kotlin_math_sinh(KDouble x) { RETURN_RESULT_OF_JS_CALL(knjs__Math_sinh, x); } +KDouble Kotlin_math_cosh(KDouble x) { RETURN_RESULT_OF_JS_CALL(knjs__Math_cosh, x); } +KDouble Kotlin_math_tanh(KDouble x) { RETURN_RESULT_OF_JS_CALL(knjs__Math_tanh, x); } +KDouble Kotlin_math_asinh(KDouble x) { RETURN_RESULT_OF_JS_CALL(knjs__Math_asinh, x); } +KDouble Kotlin_math_acosh(KDouble x) { RETURN_RESULT_OF_JS_CALL(knjs__Math_acosh, x); } +KDouble Kotlin_math_atanh(KDouble x) { RETURN_RESULT_OF_JS_CALL(knjs__Math_atanh, x); } + +KDouble Kotlin_math_sqrt(KDouble x) { RETURN_RESULT_OF_JS_CALL(knjs__Math_sqrt, x); } +KDouble Kotlin_math_exp(KDouble x) { RETURN_RESULT_OF_JS_CALL(knjs__Math_exp, x); } +KDouble Kotlin_math_expm1(KDouble x) { RETURN_RESULT_OF_JS_CALL(knjs__Math_expm1, x); } + +KDouble Kotlin_math_ln(KDouble x) { RETURN_RESULT_OF_JS_CALL(knjs__Math_log, x); } +KDouble Kotlin_math_log10(KDouble x) { RETURN_RESULT_OF_JS_CALL(knjs__Math_log10, x); } +KDouble Kotlin_math_log2(KDouble x) { RETURN_RESULT_OF_JS_CALL(knjs__Math_log2, x); } +KDouble Kotlin_math_ln1p(KDouble x) { RETURN_RESULT_OF_JS_CALL(knjs__Math_log1p, x); } + +KDouble Kotlin_math_ceil(KDouble x) { RETURN_RESULT_OF_JS_CALL(knjs__Math_ceil, x); } +KDouble Kotlin_math_floor(KDouble x) { RETURN_RESULT_OF_JS_CALL(knjs__Math_floor, x); } + +KDouble Kotlin_math_round(KDouble x) { + if (fmod(x, 0.5) != 0.0) { + RETURN_RESULT_OF_JS_CALL(knjs__Math_round, x); + } + KDouble f = floor(x); + return (fmod(f, 2) == 0.0) ? f : ceil(x); +} + +KDouble Kotlin_math_abs(KDouble x) { RETURN_RESULT_OF_JS_CALL(knjs__Math_abs, x); } + +KDouble Kotlin_math_atan2(KDouble y, KDouble x) { RETURN_RESULT_OF_JS_CALL2(knjs__Math_atan2, y, x); } +KDouble Kotlin_math_hypot(KDouble x, KDouble y) { RETURN_RESULT_OF_JS_CALL2(knjs__Math_hypot, x, y); } + +// extensions + +KDouble Kotlin_math_Double_pow(KDouble thiz, KDouble x) { RETURN_RESULT_OF_JS_CALL2(knjs__Math_pow, thiz, x); } + +KDouble Kotlin_math_Double_IEEErem(KDouble thiz, KDouble divisor) { + if (isnan(thiz) || isnan(divisor) || isinf(thiz) || divisor == 0.0) { + return NAN; + } + if (!isinf(thiz) && isinf(divisor)) { + return thiz; + } + KDouble rounded = Kotlin_math_round(thiz / divisor); + return thiz - rounded * divisor; +} + +KDouble Kotlin_math_Double_nextUp(KDouble thiz) { + if (isnan(thiz) || thiz == HUGE_VAL) { + return thiz; + } + if (thiz == 0.0) { + return DBL_TRUE_MIN; + } + return bitsToDouble(doubleToBits(thiz) + (thiz > 0 ? 1 : -1)); +} + +KDouble Kotlin_math_Double_nextDown(KDouble thiz) { + if (isnan(thiz) || thiz == -HUGE_VAL) { + return thiz; + } + if (thiz == 0.0) { + return -DBL_TRUE_MIN; + } + return bitsToDouble(doubleToBits(thiz) - (thiz > 0 ? 1 : -1)); +} + +KDouble Kotlin_math_Double_nextTowards(KDouble thiz, KDouble to) { + if (isnan(thiz) || isnan(to)) { + return NAN; + } + if (to > thiz) { + return Kotlin_math_Double_nextUp(thiz); + } + if (to < thiz) { + return Kotlin_math_Double_nextDown(thiz); + } + // thiz == to + return to; +} + +KBoolean Kotlin_math_Double_signBit(KDouble thiz) { + return (doubleToBits(thiz) & (KLong) 1 << 63) != 0; +} + +KDouble Kotlin_math_Double_withSign(KDouble thiz, KDouble sign) { + bool oldSign = Kotlin_math_Double_signBit(thiz); + bool newSign = Kotlin_math_Double_signBit(sign); + return (oldSign == newSign) ? thiz : -thiz; +} + +// endregion + +// region Float math. + +KFloat Kotlin_math_sinf(KFloat x) { return (KFloat)Kotlin_math_sin (x); } +KFloat Kotlin_math_cosf(KFloat x) { return (KFloat)Kotlin_math_cos (x); } +KFloat Kotlin_math_tanf(KFloat x) { return (KFloat)Kotlin_math_tan (x); } +KFloat Kotlin_math_asinf(KFloat x) { return (KFloat)Kotlin_math_asin (x); } +KFloat Kotlin_math_acosf(KFloat x) { return (KFloat)Kotlin_math_acos (x); } +KFloat Kotlin_math_atanf(KFloat x) { return (KFloat)Kotlin_math_atan (x); } + +KFloat Kotlin_math_sinhf(KFloat x) { return (KFloat)Kotlin_math_sinh (x); } +KFloat Kotlin_math_coshf(KFloat x) { return (KFloat)Kotlin_math_cosh (x); } +KFloat Kotlin_math_tanhf(KFloat x) { return (KFloat)Kotlin_math_tanh (x); } +KFloat Kotlin_math_asinhf(KFloat x) { return (KFloat)Kotlin_math_asinh (x); } +KFloat Kotlin_math_acoshf(KFloat x) { return (KFloat)Kotlin_math_acosh (x); } +KFloat Kotlin_math_atanhf(KFloat x) { return (KFloat)Kotlin_math_atanh (x); } + +KFloat Kotlin_math_sqrtf(KFloat x) { return (KFloat)Kotlin_math_sqrt (x); } +KFloat Kotlin_math_expf(KFloat x) { return (KFloat)Kotlin_math_exp (x); } +KFloat Kotlin_math_expm1f(KFloat x) { return (KFloat)Kotlin_math_expm1 (x); } + +KFloat Kotlin_math_lnf(KFloat x) { return (KFloat)Kotlin_math_ln (x); } +KFloat Kotlin_math_log10f(KFloat x) { return (KFloat)Kotlin_math_log10 (x); } +KFloat Kotlin_math_log2f(KFloat x) { return (KFloat)Kotlin_math_log2 (x); } +KFloat Kotlin_math_ln1pf(KFloat x) { return (KFloat)Kotlin_math_ln1p (x); } + +KFloat Kotlin_math_ceilf(KFloat x) { return (KFloat)Kotlin_math_ceil (x); } +KFloat Kotlin_math_floorf(KFloat x) { return (KFloat)Kotlin_math_floor (x); } +KFloat Kotlin_math_roundf(KFloat x) { return (KFloat)Kotlin_math_round (x); } + +KFloat Kotlin_math_absf(KFloat x) { return (KFloat)Kotlin_math_abs (x); } + +KFloat Kotlin_math_atan2f(KFloat y, KFloat x) { return (KFloat)Kotlin_math_atan2(y, x); } +KFloat Kotlin_math_hypotf(KFloat x, KFloat y) { return (KFloat)Kotlin_math_hypot(x, y); } + +// extensions + +KFloat Kotlin_math_Float_pow(KFloat thiz, KFloat x) { return (KFloat)Kotlin_math_Double_pow(thiz, x); } + +KFloat Kotlin_math_Float_IEEErem(KFloat thiz, KFloat divisor) { + return (KFloat)Kotlin_math_Double_IEEErem(thiz, divisor); +} + +KFloat Kotlin_math_Float_withSign(KFloat thiz, KFloat sign) { + return (KFloat)Kotlin_math_Double_withSign(thiz, sign); +} + +KFloat Kotlin_math_Float_nextUp(KFloat thiz) { + if (isnan(thiz) || thiz == HUGE_VALF) { + return thiz; + } + if (thiz == 0.0) { + return FLT_TRUE_MIN; + } + return bitsToFloat(floatToBits(thiz) + (thiz > 0 ? 1 : -1)); +} + +KFloat Kotlin_math_Float_nextDown(KFloat thiz) { + if (isnan(thiz) || thiz == -HUGE_VALF) { + return thiz; + } + if (thiz == 0.0) { + return -FLT_TRUE_MIN; + } + return bitsToFloat(floatToBits(thiz) - (thiz > 0 ? 1 : -1)); +} + +KFloat Kotlin_math_Float_nextTowards(KFloat thiz, KFloat to) { + if (isnan(thiz) || isnan(to)) { + return NAN; + } + if (to > thiz) { + return Kotlin_math_Float_nextUp(thiz); + } + if (to < thiz) { + return Kotlin_math_Float_nextDown(thiz); + } + // thiz == to + return to; +} + +KBoolean Kotlin_math_Float_signBit(KFloat thiz) { return Kotlin_math_Double_signBit(thiz); } + +// endregion + +// region Integer math + +KInt Kotlin_math_absi(KInt x) { return (x >= 0) ? x : -x; } +KLong Kotlin_math_absl(KLong x) { return (x >= 0) ? x : -x; } + +#endif // #ifndef KONAN_WASM + +#else // KONAN_NO_MATH defined - we have no patform math library. Throw NotImplementedError from math functions. + +namespace { + +RUNTIME_NORETURN void NotImplemented() { + ThrowNotImplementedError(); +} + +} // namespace + +KDouble Kotlin_math_sin(KDouble x) { NotImplemented(); } +KDouble Kotlin_math_cos(KDouble x) { NotImplemented(); } +KDouble Kotlin_math_tan(KDouble x) { NotImplemented(); } +KDouble Kotlin_math_asin(KDouble x) { NotImplemented(); } +KDouble Kotlin_math_acos(KDouble x) { NotImplemented(); } +KDouble Kotlin_math_atan(KDouble x) { NotImplemented(); } +KDouble Kotlin_math_atan2(KDouble y, KDouble x) { NotImplemented(); } + +KDouble Kotlin_math_sinh(KDouble x) { NotImplemented(); } +KDouble Kotlin_math_cosh(KDouble x) { NotImplemented(); } +KDouble Kotlin_math_tanh(KDouble x) { NotImplemented(); } +KDouble Kotlin_math_asinh(KDouble x) { NotImplemented(); } +KDouble Kotlin_math_acosh(KDouble x) { NotImplemented(); } +KDouble Kotlin_math_atanh(KDouble x) { NotImplemented(); } + +KDouble Kotlin_math_hypot(KDouble x, KDouble y) { NotImplemented(); } +KDouble Kotlin_math_sqrt(KDouble x) { NotImplemented(); } +KDouble Kotlin_math_exp(KDouble x) { NotImplemented(); } +KDouble Kotlin_math_expm1(KDouble x) { NotImplemented(); } + +KDouble Kotlin_math_ln(KDouble x) { NotImplemented(); } +KDouble Kotlin_math_log10(KDouble x) { NotImplemented(); } +KDouble Kotlin_math_log2(KDouble x) { NotImplemented(); } +KDouble Kotlin_math_ln1p(KDouble x) { NotImplemented(); } + +KDouble Kotlin_math_ceil(KDouble x) { NotImplemented(); } +KDouble Kotlin_math_floor(KDouble x) { NotImplemented(); } +KDouble Kotlin_math_round(KDouble x) { NotImplemented(); } + +KDouble Kotlin_math_abs(KDouble x) { NotImplemented(); } + +// extensions + +KDouble Kotlin_math_Double_pow(KDouble thiz, KDouble x) { NotImplemented(); } +KDouble Kotlin_math_Double_IEEErem(KDouble thiz, KDouble divisor) { NotImplemented(); } +KDouble Kotlin_math_Double_withSign(KDouble thiz, KDouble sign) { NotImplemented(); } + +KDouble Kotlin_math_Double_nextUp(KDouble thiz) { NotImplemented(); } +KDouble Kotlin_math_Double_nextDown(KDouble thiz) { NotImplemented(); } +KDouble Kotlin_math_Double_nextTowards(KDouble thiz, KDouble to) { NotImplemented(); } + +KBoolean Kotlin_math_Double_signBit(KDouble thiz) { NotImplemented(); } + +// endregion + +// region Float math. + +KFloat Kotlin_math_sinf(KFloat x) { NotImplemented(); } +KFloat Kotlin_math_cosf(KFloat x) { NotImplemented(); } +KFloat Kotlin_math_tanf(KFloat x) { NotImplemented(); } +KFloat Kotlin_math_asinf(KFloat x) { NotImplemented(); } +KFloat Kotlin_math_acosf(KFloat x) { NotImplemented(); } +KFloat Kotlin_math_atanf(KFloat x) { NotImplemented(); } +KFloat Kotlin_math_atan2f(KFloat y, KFloat x) { NotImplemented(); } + +KFloat Kotlin_math_sinhf(KFloat x) { NotImplemented(); } +KFloat Kotlin_math_coshf(KFloat x) { NotImplemented(); } +KFloat Kotlin_math_tanhf(KFloat x) { NotImplemented(); } +KFloat Kotlin_math_asinhf(KFloat x) { NotImplemented(); } +KFloat Kotlin_math_acoshf(KFloat x) { NotImplemented(); } +KFloat Kotlin_math_atanhf(KFloat x) { NotImplemented(); } + +KFloat Kotlin_math_hypotf(KFloat x, KFloat y) { NotImplemented(); } +KFloat Kotlin_math_sqrtf(KFloat x) { NotImplemented(); } +KFloat Kotlin_math_expf(KFloat x) { NotImplemented(); } +KFloat Kotlin_math_expm1f(KFloat x) { NotImplemented(); } + +KFloat Kotlin_math_lnf(KFloat x) { NotImplemented(); } +KFloat Kotlin_math_log10f(KFloat x) { NotImplemented(); } +KFloat Kotlin_math_log2f(KFloat x) { NotImplemented(); } +KFloat Kotlin_math_ln1pf(KFloat x) { NotImplemented(); } + +KFloat Kotlin_math_ceilf(KFloat x) { NotImplemented(); } +KFloat Kotlin_math_floorf(KFloat x) { NotImplemented(); } +KFloat Kotlin_math_roundf(KFloat x) { NotImplemented(); } + +KFloat Kotlin_math_absf(KFloat x) { NotImplemented(); } + +// extensions + +KFloat Kotlin_math_Float_pow(KFloat thiz, KFloat x) { NotImplemented(); } +KFloat Kotlin_math_Float_IEEErem(KFloat thiz, KFloat divisor) { NotImplemented(); } +KFloat Kotlin_math_Float_withSign(KFloat thiz, KFloat sign) { NotImplemented(); } + +KFloat Kotlin_math_Float_nextUp(KFloat thiz) { NotImplemented(); } +KFloat Kotlin_math_Float_nextDown(KFloat thiz) { NotImplemented(); } +KFloat Kotlin_math_Float_nextTowards(KFloat thiz, KFloat to) { NotImplemented(); } + +KBoolean Kotlin_math_Float_signBit(KFloat thiz) { NotImplemented(); } + +// endregion + +// region Integer math + +KInt Kotlin_math_absi(KInt x) { NotImplemented(); } +KInt Kotlin_math_mini(KInt a, KInt b) { NotImplemented(); } +KInt Kotlin_math_maxi(KInt a, KInt b) { NotImplemented(); } + +KLong Kotlin_math_absl(KLong x) { NotImplemented(); } +KLong Kotlin_math_minl(KLong a, KLong b) { NotImplemented(); } +KLong Kotlin_math_maxl(KLong a, KLong b) { NotImplemented(); } + +#endif // #ifndef KONAN_NO_MATH + +} // extern "C" diff --git a/kotlin-native/runtime/src/main/cpp/KotlinMath.h b/kotlin-native/runtime/src/main/cpp/KotlinMath.h new file mode 100644 index 00000000000..3662a38f5c3 --- /dev/null +++ b/kotlin-native/runtime/src/main/cpp/KotlinMath.h @@ -0,0 +1,69 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef RUNTIME_KOTLINMATH_H +#define RUNTIME_KOTLINMATH_H + +#include "Types.h" + +#ifdef KONAN_WASM + +extern "C" { + +// TODO: consider auto-generating this header file. + +// Bridges for JS math. +void knjs__Math_abs(KInt xUpper, KInt xLower); +void knjs__Math_acos(KInt xUpper, KInt xLower); +void knjs__Math_acosh(KInt xUpper, KInt xLower); +void knjs__Math_asin(KInt xUpper, KInt xLower); +void knjs__Math_asinh(KInt xUpper, KInt xLower); +void knjs__Math_atan(KInt xUpper, KInt xLower); +void knjs__Math_atan2(KInt yUpper, KInt yLower, KInt xUpper, KInt xLower); +void knjs__Math_atanh(KInt xUpper, KInt xLower); +void knjs__Math_cbrt(KInt xUpper, KInt xLower); +void knjs__Math_ceil(KInt xUpper, KInt xLower); +void knjs__Math_clz32(KInt xUpper, KInt xLower); +void knjs__Math_cos(KInt xUpper, KInt xLower); +void knjs__Math_cosh(KInt xUpper, KInt xLower); +void knjs__Math_exp(KInt xUpper, KInt xLower); +void knjs__Math_expm1(KInt xUpper, KInt xLower); +void knjs__Math_floor(KInt xUpper, KInt xLower); +void knjs__Math_fround(KInt xUpper, KInt xLower); +void knjs__Math_log(KInt xUpper, KInt xLower); +void knjs__Math_log1p(KInt xUpper, KInt xLower); +void knjs__Math_log10(KInt xUpper, KInt xLower); +void knjs__Math_log2(KInt xUpper, KInt xLower); +void knjs__Math_round(KInt xUpper, KInt xLower); +void knjs__Math_sign(KInt xUpper, KInt xLower); +void knjs__Math_sin(KInt xUpper, KInt xLower); +void knjs__Math_sinh(KInt xUpper, KInt xLower); +void knjs__Math_sqrt(KInt xUpper, KInt xLower); +void knjs__Math_tan(KInt xUpper, KInt xLower); +void knjs__Math_tanh(KInt xUpper, KInt xLower); +void knjs__Math_trunc(KInt xUpper, KInt xLower); + +void knjs__Math_hypot(KInt xUpper, KInt xLower, KInt yUpper, KInt yLower); +void knjs__Math_max(KInt xUpper, KInt xLower, KInt yUpper, KInt yLower); +void knjs__Math_min(KInt xUpper, KInt xLower, KInt yUpper, KInt yLower); + +void knjs__Math_pow(KInt xUpper, KInt xLower, KInt yUpper, KInt yLower); + +} + +#endif // KONAN_WASM + +#endif // RUNTIME_KOTLINMATH_H diff --git a/kotlin-native/runtime/src/main/cpp/Memory.h b/kotlin-native/runtime/src/main/cpp/Memory.h new file mode 100644 index 00000000000..57fa71c511f --- /dev/null +++ b/kotlin-native/runtime/src/main/cpp/Memory.h @@ -0,0 +1,321 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef RUNTIME_MEMORY_H +#define RUNTIME_MEMORY_H + +#include "KAssert.h" +#include "Common.h" +#include "TypeInfo.h" +#include "Atomic.h" +#include "PointerBits.h" + +typedef enum { + // Must match to permTag() in Kotlin. + OBJECT_TAG_PERMANENT_CONTAINER = 1 << 0, + OBJECT_TAG_NONTRIVIAL_CONTAINER = 1 << 1, + // Keep in sync with immTypeInfoMask in Kotlin. + OBJECT_TAG_MASK = (1 << 2) - 1 +} ObjectTag; + +struct ArrayHeader; +struct MetaObjHeader; + +// Header of every object. +struct ObjHeader { + TypeInfo* typeInfoOrMeta_; + + const TypeInfo* type_info() const { + return clearPointerBits(typeInfoOrMeta_, OBJECT_TAG_MASK)->typeInfo_; + } + + bool has_meta_object() const { + auto* typeInfoOrMeta = clearPointerBits(typeInfoOrMeta_, OBJECT_TAG_MASK); + return (typeInfoOrMeta != typeInfoOrMeta->typeInfo_); + } + + MetaObjHeader* meta_object() { + return has_meta_object() ? + reinterpret_cast(clearPointerBits(typeInfoOrMeta_, OBJECT_TAG_MASK)) : + createMetaObject(&typeInfoOrMeta_); + } + + ALWAYS_INLINE ObjHeader** GetWeakCounterLocation(); + +#ifdef KONAN_OBJC_INTEROP + ALWAYS_INLINE void* GetAssociatedObject(); + ALWAYS_INLINE void** GetAssociatedObjectLocation(); + ALWAYS_INLINE void SetAssociatedObject(void* obj); +#endif + + inline bool local() const { + unsigned bits = getPointerBits(typeInfoOrMeta_, OBJECT_TAG_MASK); + return (bits & (OBJECT_TAG_PERMANENT_CONTAINER | OBJECT_TAG_NONTRIVIAL_CONTAINER)) == + (OBJECT_TAG_PERMANENT_CONTAINER | OBJECT_TAG_NONTRIVIAL_CONTAINER); + } + + // Unsafe cast to ArrayHeader. Use carefully! + ArrayHeader* array() { return reinterpret_cast(this); } + const ArrayHeader* array() const { return reinterpret_cast(this); } + + inline bool permanent() const { + return hasPointerBits(typeInfoOrMeta_, OBJECT_TAG_PERMANENT_CONTAINER); + } + + static MetaObjHeader* createMetaObject(TypeInfo** location); + static void destroyMetaObject(TypeInfo** location); +}; + +// Header of value type array objects. Keep layout in sync with that of object header. +struct ArrayHeader { + TypeInfo* typeInfoOrMeta_; + + const TypeInfo* type_info() const { + return clearPointerBits(typeInfoOrMeta_, OBJECT_TAG_MASK)->typeInfo_; + } + + ObjHeader* obj() { return reinterpret_cast(this); } + const ObjHeader* obj() const { return reinterpret_cast(this); } + + // Elements count. Element size is stored in instanceSize_ field of TypeInfo, negated. + uint32_t count_; +}; + +ALWAYS_INLINE bool isFrozen(const ObjHeader* obj); +ALWAYS_INLINE bool isPermanentOrFrozen(const ObjHeader* obj); +ALWAYS_INLINE bool isShareable(const ObjHeader* obj); + +class ForeignRefManager; +typedef ForeignRefManager* ForeignRefContext; + +#ifdef __cplusplus +extern "C" { +#endif + +#define OBJ_RESULT __result__ +#define OBJ_GETTER0(name) ObjHeader* name(ObjHeader** OBJ_RESULT) +#define OBJ_GETTER(name, ...) ObjHeader* name(__VA_ARGS__, ObjHeader** OBJ_RESULT) +#define RETURN_OBJ(value) { ObjHeader* __obj = value; \ + UpdateReturnRef(OBJ_RESULT, __obj); \ + return __obj; } +#define RETURN_RESULT_OF0(name) { \ + ObjHeader* __obj = name(OBJ_RESULT); \ + return __obj; \ + } +#define RETURN_RESULT_OF(name, ...) { \ + ObjHeader* __result = name(__VA_ARGS__, OBJ_RESULT); \ + return __result; \ + } + +struct MemoryState; + +MemoryState* InitMemory(); +void DeinitMemory(MemoryState*); +void RestoreMemory(MemoryState*); + +// +// Object allocation. +// +// Allocation can happen in either GLOBAL, FRAME or ARENA scope. Depending on that, +// Alloc* or ArenaAlloc* is called. Regular alloc means allocation happens in the heap, +// and each object gets its individual container. Otherwise, allocator uses aux slot in +// an implementation-defined manner, current behavior is to keep arena pointer there. +// Arena containers are not reference counted, and is explicitly freed when leaving +// its owner frame. +// Escape analysis algorithm is the provider of information for decision on exact aux slot +// selection, and comes from upper bound esteemation of object lifetime. +// +OBJ_GETTER(AllocInstance, const TypeInfo* type_info) RUNTIME_NOTHROW; + +OBJ_GETTER(AllocArrayInstance, const TypeInfo* type_info, int32_t elements); + +OBJ_GETTER(InitInstance, + ObjHeader** location, const TypeInfo* typeInfo, void (*ctor)(ObjHeader*)); + +OBJ_GETTER(InitSharedInstance, + ObjHeader** location, const TypeInfo* typeInfo, void (*ctor)(ObjHeader*)); + +// +// Object reference management. +// +// Reference management scheme we use assumes significant degree of flexibility, so that +// one could implement either pure reference counting scheme, or tracing collector without +// much ado. +// Most important primitive is Update*Ref() API, which modifies location to use new +// object reference. In pure reference counted scheme it will check old value, +// decrement reference, increment counter on the new value, and store it into the field. +// In tracing collector-like scheme, only field updates counts, and all other operations are +// essentially no-ops. +// +// On codegeneration phase we adopt following approaches: +// - every stack frame has several slots, holding object references (allRefs) +// - those are known by compiler (and shall be grouped together) +// - it keeps all locally allocated objects in such slot +// - all local variables keeping an object also allocate a slot +// - most manipulations on objects happens in SSA variables and do no affect slots +// - exception handlers knowns slot locations for every function, and can update references +// in intermediate frames when throwing +// + +// Controls the current memory model, is compile-time constant. +extern const bool IsStrictMemoryModel; + +// Sets stack location. +void SetStackRef(ObjHeader** location, const ObjHeader* object) RUNTIME_NOTHROW; +// Sets heap location. +void SetHeapRef(ObjHeader** location, const ObjHeader* object) RUNTIME_NOTHROW; +// Zeroes heap location. +void ZeroHeapRef(ObjHeader** location) RUNTIME_NOTHROW; +// Zeroes an array. +void ZeroArrayRefs(ArrayHeader* array) RUNTIME_NOTHROW; +// Zeroes stack location. +void ZeroStackRef(ObjHeader** location) RUNTIME_NOTHROW; +// Updates stack location. +void UpdateStackRef(ObjHeader** location, const ObjHeader* object) RUNTIME_NOTHROW; +// Updates heap/static data location. +void UpdateHeapRef(ObjHeader** location, const ObjHeader* object) RUNTIME_NOTHROW; +// Updates location if it is null, atomically. +void UpdateHeapRefIfNull(ObjHeader** location, const ObjHeader* object) RUNTIME_NOTHROW; +// Updates reference in return slot. +void UpdateReturnRef(ObjHeader** returnSlot, const ObjHeader* object) RUNTIME_NOTHROW; +// Compares and swaps reference with taken lock. +OBJ_GETTER(SwapHeapRefLocked, + ObjHeader** location, ObjHeader* expectedValue, ObjHeader* newValue, int32_t* spinlock, + int32_t* cookie) RUNTIME_NOTHROW; +// Sets reference with taken lock. +void SetHeapRefLocked(ObjHeader** location, ObjHeader* newValue, int32_t* spinlock, + int32_t* cookie) RUNTIME_NOTHROW; +// Reads reference with taken lock. +OBJ_GETTER(ReadHeapRefLocked, ObjHeader** location, int32_t* spinlock, int32_t* cookie) RUNTIME_NOTHROW; +// Called on frame enter, if it has object slots. +void EnterFrame(ObjHeader** start, int parameters, int count) RUNTIME_NOTHROW; +// Called on frame leave, if it has object slots. +void LeaveFrame(ObjHeader** start, int parameters, int count) RUNTIME_NOTHROW; +// Clears object subgraph references from memory subsystem, and optionally +// checks if subgraph referenced by given root is disjoint from the rest of +// object graph, i.e. no external references exists. +bool ClearSubgraphReferences(ObjHeader* root, bool checked) RUNTIME_NOTHROW; +// Creates stable pointer out of the object. +void* CreateStablePointer(ObjHeader* obj) RUNTIME_NOTHROW; +// Disposes stable pointer to the object. +void DisposeStablePointer(void* pointer) RUNTIME_NOTHROW; +// Translate stable pointer to object reference. +OBJ_GETTER(DerefStablePointer, void*) RUNTIME_NOTHROW; +// Move stable pointer ownership. +OBJ_GETTER(AdoptStablePointer, void*) RUNTIME_NOTHROW; +// Check mutability state. +void MutationCheck(ObjHeader* obj); +void CheckLifetimesConstraint(ObjHeader* obj, ObjHeader* pointee) RUNTIME_NOTHROW; +// Freeze object subgraph. +void FreezeSubgraph(ObjHeader* obj); +// Ensure this object shall block freezing. +void EnsureNeverFrozen(ObjHeader* obj); +// Add TLS object storage, called by the generated code. +void AddTLSRecord(MemoryState* memory, void** key, int size) RUNTIME_NOTHROW; +// Clear TLS object storage, called by the generated code. +void ClearTLSRecord(MemoryState* memory, void** key) RUNTIME_NOTHROW; +// Lookup element in TLS object storage. +ObjHeader** LookupTLS(void** key, int index) RUNTIME_NOTHROW; + +// APIs for the async GC. +void GC_RegisterWorker(void* worker) RUNTIME_NOTHROW; +void GC_UnregisterWorker(void* worker) RUNTIME_NOTHROW; +void GC_CollectorCallback(void* worker) RUNTIME_NOTHROW; + +bool Kotlin_Any_isShareable(ObjHeader* thiz); +void PerformFullGC() RUNTIME_NOTHROW; + +bool TryAddHeapRef(const ObjHeader* object); + +void ReleaseHeapRef(const ObjHeader* object) RUNTIME_NOTHROW; +void ReleaseHeapRefNoCollect(const ObjHeader* object) RUNTIME_NOTHROW; + +ForeignRefContext InitLocalForeignRef(ObjHeader* object); + +ForeignRefContext InitForeignRef(ObjHeader* object); +void DeinitForeignRef(ObjHeader* object, ForeignRefContext context); + +bool IsForeignRefAccessible(ObjHeader* object, ForeignRefContext context); + +// Should be used when reference is read from a possibly shared variable, +// and there's nothing else keeping the object alive. +void AdoptReferenceFromSharedVariable(ObjHeader* object); + +#ifdef __cplusplus +} +#endif + +struct FrameOverlay { + void* arena; + FrameOverlay* previous; + // As they go in pair, sizeof(FrameOverlay) % sizeof(void*) == 0 is always held. + int32_t parameters; + int32_t count; +}; + +// Class holding reference to an object, holding object during C++ scope. +class ObjHolder { + public: + ObjHolder() : obj_(nullptr) { + EnterFrame(frame(), 0, sizeof(*this)/sizeof(void*)); + } + + explicit ObjHolder(const ObjHeader* obj) { + EnterFrame(frame(), 0, sizeof(*this)/sizeof(void*)); + ::SetStackRef(slot(), obj); + } + + ~ObjHolder() { + LeaveFrame(frame(), 0, sizeof(*this)/sizeof(void*)); + } + + ObjHeader* obj() { return obj_; } + + const ObjHeader* obj() const { return obj_; } + + ObjHeader** slot() { + return &obj_; + } + + void clear() { ::ZeroStackRef(&obj_); } + + private: + ObjHeader** frame() { return reinterpret_cast(&frame_); } + + FrameOverlay frame_; + ObjHeader* obj_; +}; + +//! TODO Follow the Rule of Zero to prevent dangling on unintented copy ctor +class ExceptionObjHolder { + public: + explicit ExceptionObjHolder(const ObjHeader* obj) { + ::SetHeapRef(&obj_, obj); + } + + ~ExceptionObjHolder() { + ZeroHeapRef(&obj_); + } + + ObjHeader* obj() { return obj_; } + + const ObjHeader* obj() const { return obj_; } + + private: + ObjHeader* obj_; +}; + +#endif // RUNTIME_MEMORY_H diff --git a/kotlin-native/runtime/src/main/cpp/MemorySharedRefs.cpp b/kotlin-native/runtime/src/main/cpp/MemorySharedRefs.cpp new file mode 100644 index 00000000000..c4a1336e42b --- /dev/null +++ b/kotlin-native/runtime/src/main/cpp/MemorySharedRefs.cpp @@ -0,0 +1,216 @@ +/* + * Copyright 2010-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +#include "Exceptions.h" +#include "MemorySharedRefs.hpp" +#include "Runtime.h" +#include "Types.h" + +extern "C" { +// Returns a string describing object at `address` of type `typeInfo`. +OBJ_GETTER(DescribeObjectForDebugging, KConstNativePtr typeInfo, KConstNativePtr address); +} // extern "C" + +namespace { + +inline bool isForeignRefAccessible(ObjHeader* object, ForeignRefContext context) { + // If runtime has not been initialized on this thread, then the object is either unowned or shared. + // In the former case initialized runtime is required to throw exceptions + // in the latter case -- to provide proper execution context for caller. + Kotlin_initRuntimeIfNeeded(); + + return IsForeignRefAccessible(object, context); +} + +RUNTIME_NORETURN inline void throwIllegalSharingException(ObjHeader* object) { + // TODO: add some info about the context. + // Note: retrieving 'type_info()' is supposed to be correct even for unowned object. + ThrowIllegalObjectSharingException(object->type_info(), object); +} + +RUNTIME_NORETURN inline void terminateWithIllegalSharingException(ObjHeader* object) { +#if KONAN_NO_EXCEPTIONS + // This will terminate. + throwIllegalSharingException(object); +#else + try { + throwIllegalSharingException(object); + } catch (...) { + // A trick to terminate with unhandled exception. This will print a stack trace + // and write to iOS crash log. + std::terminate(); + } +#endif +} + +template +bool ensureRefAccessible(ObjHeader* object, ForeignRefContext context) { + static_assert(errorPolicy != ErrorPolicy::kIgnore, "Must've been handled by specialization"); + + if (isForeignRefAccessible(object, context)) { + return true; + } + + switch (errorPolicy) { + case ErrorPolicy::kDefaultValue: + return false; + case ErrorPolicy::kThrow: + throwIllegalSharingException(object); + case ErrorPolicy::kTerminate: + terminateWithIllegalSharingException(object); + } +} + +template <> +bool ensureRefAccessible(ObjHeader* object, ForeignRefContext context) { + return true; +} + +} // namespace + +void KRefSharedHolder::initLocal(ObjHeader* obj) { + RuntimeAssert(obj != nullptr, "must not be null"); + context_ = InitLocalForeignRef(obj); + obj_ = obj; +} + +void KRefSharedHolder::init(ObjHeader* obj) { + RuntimeAssert(obj != nullptr, "must not be null"); + context_ = InitForeignRef(obj); + obj_ = obj; +} + +template +ObjHeader* KRefSharedHolder::ref() const { + if (!ensureRefAccessible(obj_, context_)) { + return nullptr; + } + + AdoptReferenceFromSharedVariable(obj_); + return obj_; +} + +template ObjHeader* KRefSharedHolder::ref() const; +template ObjHeader* KRefSharedHolder::ref() const; +template ObjHeader* KRefSharedHolder::ref() const; + +void KRefSharedHolder::dispose() const { + if (obj_ == nullptr) { + // To handle the case when it is not initialized. See [KotlinMutableSet/Dictionary dealloc]. + return; + } + + DeinitForeignRef(obj_, context_); +} + +OBJ_GETTER0(KRefSharedHolder::describe) const { + // Note: retrieving 'type_info()' is supposed to be correct even for unowned object. + RETURN_RESULT_OF(DescribeObjectForDebugging, obj_->type_info(), obj_); +} + +void BackRefFromAssociatedObject::initAndAddRef(ObjHeader* obj) { + RuntimeAssert(obj != nullptr, "must not be null"); + obj_ = obj; + + // Generally a specialized addRef below: + context_ = InitForeignRef(obj); + refCount = 1; +} + +template +void BackRefFromAssociatedObject::addRef() { + static_assert(errorPolicy != ErrorPolicy::kDefaultValue, "Cannot use default return value here"); + + if (atomicAdd(&refCount, 1) == 1) { + if (obj_ == nullptr) return; // E.g. after [detach]. + + // There are no references to the associated object itself, so Kotlin object is being passed from Kotlin, + // and it is owned therefore. + ensureRefAccessible(obj_, context_); // TODO: consider removing explicit verification. + + // Foreign reference has already been deinitialized (see [releaseRef]). + // Create a new one: + context_ = InitForeignRef(obj_); + } +} + +template void BackRefFromAssociatedObject::addRef(); +template void BackRefFromAssociatedObject::addRef(); + +template +bool BackRefFromAssociatedObject::tryAddRef() { + static_assert(errorPolicy != ErrorPolicy::kDefaultValue, "Cannot use default return value here"); + + if (obj_ == nullptr) return false; // E.g. after [detach]. + + // Suboptimal but simple: + ensureRefAccessible(obj_, context_); + + ObjHeader* obj = obj_; + + if (!TryAddHeapRef(obj)) return false; + RuntimeAssert(isForeignRefAccessible(obj_, context_), "Cannot be inaccessible because of the check above"); + // TODO: This is a very weird way to ask for "unsafe" addRef. + addRef(); + ReleaseHeapRefNoCollect(obj); // Balance TryAddHeapRef. + // TODO: consider optimizing for non-shared objects. + + return true; +} + +template bool BackRefFromAssociatedObject::tryAddRef(); +template bool BackRefFromAssociatedObject::tryAddRef(); + +void BackRefFromAssociatedObject::releaseRef() { + ForeignRefContext context = context_; + if (atomicAdd(&refCount, -1) == 0) { + if (obj_ == nullptr) return; // E.g. after [detach]. + + // Note: by this moment "subsequent" addRef may have already happened and patched context_. + // So use the value loaded before refCount update: + DeinitForeignRef(obj_, context); + // From this moment [context] is generally a dangling pointer. + // This is handled in [IsForeignRefAccessible] and [addRef]. + } +} + +void BackRefFromAssociatedObject::detach() { + RuntimeAssert(atomicGet(&refCount) == 0, "unexpected refCount") + obj_ = nullptr; // Handled in addRef/tryAddRef/releaseRef/ref. +} + +template +ObjHeader* BackRefFromAssociatedObject::ref() const { + RuntimeAssert(obj_ != nullptr, "no valid Kotlin object found"); + + if (!ensureRefAccessible(obj_, context_)) { + return nullptr; + } + + AdoptReferenceFromSharedVariable(obj_); + return obj_; +} + +template ObjHeader* BackRefFromAssociatedObject::ref() const; +template ObjHeader* BackRefFromAssociatedObject::ref() const; +template ObjHeader* BackRefFromAssociatedObject::ref() const; + +extern "C" { +RUNTIME_NOTHROW void KRefSharedHolder_initLocal(KRefSharedHolder* holder, ObjHeader* obj) { + holder->initLocal(obj); +} + +RUNTIME_NOTHROW void KRefSharedHolder_init(KRefSharedHolder* holder, ObjHeader* obj) { + holder->init(obj); +} + +RUNTIME_NOTHROW void KRefSharedHolder_dispose(const KRefSharedHolder* holder) { + holder->dispose(); +} + +RUNTIME_NOTHROW ObjHeader* KRefSharedHolder_ref(const KRefSharedHolder* holder) { + return holder->ref(); +} +} // extern "C" diff --git a/kotlin-native/runtime/src/main/cpp/MemorySharedRefs.hpp b/kotlin-native/runtime/src/main/cpp/MemorySharedRefs.hpp new file mode 100644 index 00000000000..c6d8fc8c82c --- /dev/null +++ b/kotlin-native/runtime/src/main/cpp/MemorySharedRefs.hpp @@ -0,0 +1,72 @@ +/* + * Copyright 2010-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +#ifndef RUNTIME_MEMORYSHAREDREFS_HPP +#define RUNTIME_MEMORYSHAREDREFS_HPP + +#include + +#include "Memory.h" + +// TODO: Generalize for uses outside this file. +enum class ErrorPolicy { + kIgnore, // Ignore any errors. (i.e. unsafe mode) + kDefaultValue, // Return the default value from the function when an error happens. + kThrow, // Throw a Kotlin exception when an error happens. The exact exception is chosen by the callee. + kTerminate, // Terminate immediately when an error happens. +}; + +class KRefSharedHolder { + public: + void initLocal(ObjHeader* obj); + + void init(ObjHeader* obj); + + // Error if called from the wrong worker with non-frozen obj_. + template + ObjHeader* ref() const; + + void dispose() const; + + OBJ_GETTER0(describe) const; + + private: + ObjHeader* obj_; + ForeignRefContext context_; +}; + +static_assert(std::is_trivially_destructible::value, + "KRefSharedHolder destructor is not guaranteed to be called."); + +class BackRefFromAssociatedObject { + public: + void initAndAddRef(ObjHeader* obj); + + // Error if refCount is zero and it's called from the wrong worker with non-frozen obj_. + template + void addRef(); + + // Error if called from the wrong worker with non-frozen obj_. + template + bool tryAddRef(); + + void releaseRef(); + + void detach(); + + // Error if called from the wrong worker with non-frozen obj_. + template + ObjHeader* ref() const; + + private: + ObjHeader* obj_; // May be null before [initAndAddRef] or after [detach]. + ForeignRefContext context_; + volatile int refCount; +}; + +static_assert(std::is_trivially_destructible::value, + "BackRefFromAssociatedObject destructor is not guaranteed to be called."); + +#endif // RUNTIME_MEMORYSHAREDREFS_HPP diff --git a/kotlin-native/runtime/src/main/cpp/Natives.cpp b/kotlin-native/runtime/src/main/cpp/Natives.cpp new file mode 100644 index 00000000000..c0e339c5b66 --- /dev/null +++ b/kotlin-native/runtime/src/main/cpp/Natives.cpp @@ -0,0 +1,84 @@ +/* + * Copyright 2010-2017 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include +#include +#include +#include +#include + +#include "KAssert.h" +#include "Exceptions.h" +#include "Memory.h" +#include "Natives.h" +#include "Types.h" + +extern "C" { + +// Any.kt +KBoolean Kotlin_Any_equals(KConstRef thiz, KConstRef other) { + return thiz == other; +} + +KInt Kotlin_Any_hashCode(KConstRef thiz) { + // Here we will use different mechanism for stable hashcode, using meta-objects + // if moving collector will be used. + return reinterpret_cast(thiz); +} + +OBJ_GETTER(Kotlin_getStackTraceStrings, KConstRef stackTrace) { + RETURN_RESULT_OF(GetStackTraceStrings, stackTrace); +} + +// TODO: consider handling it with compiler magic instead. +OBJ_GETTER0(Kotlin_native_internal_undefined) { + RETURN_OBJ(nullptr); +} + +void* Kotlin_interop_malloc(KLong size, KInt align) { + if (size < 0 || static_cast::type>(size) > std::numeric_limits::max()) { + return nullptr; + } + RuntimeAssert(align > 0, "Unsupported alignment"); + RuntimeAssert((align & (align - 1)) == 0, "Alignment must be power of two"); + + void* result = konan::calloc_aligned(1, size, align); + if ((reinterpret_cast(result) & (align - 1)) != 0) { + // Unaligned! + RuntimeAssert(false, "unsupported alignment"); + } + + return result; +} + +void Kotlin_interop_free(void* ptr) { + konan::free(ptr); +} + +void Kotlin_system_exitProcess(KInt status) { + konan::exit(status); +} + +const void* Kotlin_Any_getTypeInfo(KConstRef obj) { + return obj->type_info(); +} + +void Kotlin_CPointer_CopyMemory(KNativePtr to, KNativePtr from, KInt count) { + memcpy(to, from, count); +} + +} // extern "C" diff --git a/kotlin-native/runtime/src/main/cpp/Natives.h b/kotlin-native/runtime/src/main/cpp/Natives.h new file mode 100644 index 00000000000..f7405679875 --- /dev/null +++ b/kotlin-native/runtime/src/main/cpp/Natives.h @@ -0,0 +1,97 @@ +/* + * Copyright 2010-2017 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef RUNTIME_NATIVES_H +#define RUNTIME_NATIVES_H + +#include "Types.h" +#include "Exceptions.h" +#include "Memory.h" + +constexpr size_t alignUp(size_t size, size_t alignment) { + return (size + alignment - 1) & ~(alignment - 1); +} + +template +inline T* AddressOfElementAt(ArrayHeader* obj, KInt index) { + int8_t* body = reinterpret_cast(obj) + alignUp(sizeof(ArrayHeader), alignof(T)); + return reinterpret_cast(body) + index; +} + +template +inline const T* AddressOfElementAt(const ArrayHeader* obj, KInt index) { + const int8_t* body = reinterpret_cast(obj) + alignUp(sizeof(ArrayHeader), alignof(T)); + return reinterpret_cast(body) + index; +} + +// Optimized versions not accessing type info. +inline KByte* ByteArrayAddressOfElementAt(ArrayHeader* obj, KInt index) { + return AddressOfElementAt(obj, index); +} + +inline const KByte* ByteArrayAddressOfElementAt(const ArrayHeader* obj, KInt index) { + return AddressOfElementAt(obj, index); +} + +inline KChar* CharArrayAddressOfElementAt(ArrayHeader* obj, KInt index) { + return AddressOfElementAt(obj, index); +} + +inline const KChar* CharArrayAddressOfElementAt(const ArrayHeader* obj, KInt index) { + return AddressOfElementAt(obj, index); +} + +inline KInt* IntArrayAddressOfElementAt(ArrayHeader* obj, KInt index) { + return AddressOfElementAt(obj, index); +} + +inline const KInt* IntArrayAddressOfElementAt(const ArrayHeader* obj, KInt index) { + return AddressOfElementAt(obj, index); +} + +// Consider aligning of base to sizeof(T). +template +inline T* PrimitiveArrayAddressOfElementAt(ArrayHeader* obj, KInt index) { + return AddressOfElementAt(obj, index); +} + +template +inline const T* PrimitiveArrayAddressOfElementAt(const ArrayHeader* obj, KInt index) { + return AddressOfElementAt(obj, index); +} + +inline KRef* ArrayAddressOfElementAt(ArrayHeader* obj, KInt index) { + return AddressOfElementAt(obj, index); +} + +inline const KRef* ArrayAddressOfElementAt(const ArrayHeader* obj, KInt index) { + return AddressOfElementAt(obj, index); +} + +#ifdef __cplusplus +extern "C" { +#endif + +OBJ_GETTER0(TheEmptyString); +void Kotlin_io_Console_println0(); +void Kotlin_NativePtrArray_set(KRef thiz, KInt index, KNativePtr value); +KNativePtr Kotlin_NativePtrArray_get(KConstRef thiz, KInt index); + +#ifdef __cplusplus +} +#endif + +#endif // RUNTIME_NATIVES_H diff --git a/kotlin-native/runtime/src/main/cpp/ObjCExceptions.cpp b/kotlin-native/runtime/src/main/cpp/ObjCExceptions.cpp new file mode 100644 index 00000000000..a3c3ebdbec2 --- /dev/null +++ b/kotlin-native/runtime/src/main/cpp/ObjCExceptions.cpp @@ -0,0 +1,125 @@ +#if KONAN_REPORT_BACKTRACE_TO_IOS_CRASH_LOG + +#include +#include +#include +#include +#include "Natives.h" +#include "ObjCExceptions.h" +#include "Types.h" + +extern "C" OBJ_GETTER(Kotlin_Throwable_getStackTrace, KRef throwable); + +static void writeStackTraceToBuffer(KRef throwable, char* buffer, unsigned long bufferSize) { + if (bufferSize < 2) return; + + ObjHolder stackTraceHolder; + ArrayHeader* stackTrace = Kotlin_Throwable_getStackTrace(throwable, stackTraceHolder.slot())->array(); + + char* bufferPointer = buffer; + unsigned long remainingBytes = bufferSize; + + *(bufferPointer++) = '('; + --remainingBytes; + + for (uint32_t index = 0; index < stackTrace->count_; ++index) { + KNativePtr ptr = *PrimitiveArrayAddressOfElementAt(stackTrace, index); + int bytes = snprintf(bufferPointer, remainingBytes, "0x%" PRIxPTR " ", reinterpret_cast(ptr)); + + if (bytes < 0 || static_cast(bytes) >= remainingBytes) { + break; + } + + bufferPointer += bytes; + remainingBytes -= bytes; + } + + *(bufferPointer - 1) = ')'; // Replace last space. + *bufferPointer = '\0'; +} + +#if !defined(MACHSIZE) +#error "Define MACHSIZE to 32 or 64" +#endif + +#if MACHSIZE == 32 + +typedef struct mach_header mach_header_target; +typedef struct segment_command segment_command_target; +typedef struct section section_target; +static const uint32_t MH_MAGIC_TARGET = MH_MAGIC; +static const uint32_t LC_SEGMENT_TARGET = LC_SEGMENT; + +#elif MACHSIZE == 64 + +typedef struct mach_header_64 mach_header_target; +typedef struct segment_command_64 segment_command_target; +typedef struct section_64 section_target; +static const uint32_t MH_MAGIC_TARGET = MH_MAGIC_64; +static const uint32_t LC_SEGMENT_TARGET = LC_SEGMENT_64; + +#else + +#error "Impossible MACHSIZE" + +#endif + +static mach_header_target* findCoreFoundationMachHeader() { + Dl_info info; + if (dladdr(reinterpret_cast(&CFRunLoopRun), &info) == 0) return nullptr; + + return reinterpret_cast(info.dli_fbase); +} + +template +bool bufferEqualsString(const char (&buffer)[n], const char* str) { + return strncmp(buffer, str, n) == 0; +} + +static char* findExceptionBacktraceSection(unsigned long *size) { + mach_header_target* header = findCoreFoundationMachHeader(); + if (header == nullptr) return nullptr; + if (header->magic != MH_MAGIC_TARGET) return nullptr; + + uintptr_t textVmaddr = 0; + + load_command* loadCommand = reinterpret_cast(header + 1); + for (uint32_t loadCommandIndex = 0; loadCommandIndex < header->ncmds; ++loadCommandIndex) { + if (loadCommand->cmd == LC_SEGMENT_TARGET) { + segment_command_target* segmentCommand = reinterpret_cast(loadCommand); + if (bufferEqualsString(segmentCommand->segname, "__TEXT")) { + textVmaddr = segmentCommand->vmaddr; + } + + if (bufferEqualsString(segmentCommand->segname, "__DATA")) { + section_target* sections = reinterpret_cast(segmentCommand + 1); + for (uint32_t sectionIndex = 0; sectionIndex < segmentCommand->nsects; ++sectionIndex) { + section_target* section = §ions[sectionIndex]; + + if (bufferEqualsString(section->sectname, "__cf_except_bt") && bufferEqualsString(section->segname, "__DATA")) { + *size = section->size; + return reinterpret_cast(reinterpret_cast(header) + section->addr - textVmaddr); + } + } + } + } + + loadCommand = reinterpret_cast(reinterpret_cast(loadCommand) + loadCommand->cmdsize); + } + + return nullptr; +} + +void ReportBacktraceToIosCrashLog(KRef throwable) { + unsigned long bufferSize = 0; + char* buffer = findExceptionBacktraceSection(&bufferSize); + if (buffer == nullptr) return; + + // Note: access to this buffer is protected by a lock, but it is not easily accessible. + // Instead assume that typically this buffer is accessed only during termination, and + // rely on caller guaranteeing this code to be executed only before system termination handlers. + + writeStackTraceToBuffer(throwable, buffer, bufferSize); +} + +#endif // KONAN_REPORT_BACKTRACE_TO_IOS_CRASH_LOG diff --git a/kotlin-native/runtime/src/main/cpp/ObjCExceptions.h b/kotlin-native/runtime/src/main/cpp/ObjCExceptions.h new file mode 100644 index 00000000000..6b1d0ae77ad --- /dev/null +++ b/kotlin-native/runtime/src/main/cpp/ObjCExceptions.h @@ -0,0 +1,13 @@ +#ifndef RUNTIME_OBJCEXCEPTIONS_H +#define RUNTIME_OBJCEXCEPTIONS_H + +#if KONAN_REPORT_BACKTRACE_TO_IOS_CRASH_LOG + +#include "Common.h" +#include "Types.h" + +void ReportBacktraceToIosCrashLog(KRef throwable); + +#endif // KONAN_REPORT_BACKTRACE_TO_IOS_CRASH_LOG + +#endif // RUNTIME_OBJCEXCEPTIONS_H \ No newline at end of file diff --git a/kotlin-native/runtime/src/main/cpp/ObjCExport.h b/kotlin-native/runtime/src/main/cpp/ObjCExport.h new file mode 100644 index 00000000000..3ede22a3035 --- /dev/null +++ b/kotlin-native/runtime/src/main/cpp/ObjCExport.h @@ -0,0 +1,44 @@ +#ifndef RUNTIME_OBJCEXPORT_H +#define RUNTIME_OBJCEXPORT_H + +#if KONAN_OBJC_INTEROP + +#import +#import + +#import "Types.h" +#import "Memory.h" + +extern "C" id objc_retain(id self); +extern "C" id objc_retainBlock(id self); +extern "C" void objc_release(id self); + +inline static id GetAssociatedObject(ObjHeader* obj) { + return (id)obj->GetAssociatedObject(); +} + +// Note: this function shall not be used on shared objects. +inline static void SetAssociatedObject(ObjHeader* obj, id value) { + obj->SetAssociatedObject((void*)value); +} + +inline static id AtomicCompareAndSwapAssociatedObject(ObjHeader* obj, id expectedValue, id newValue) { + id* location = reinterpret_cast(obj->GetAssociatedObjectLocation()); + return __sync_val_compare_and_swap(location, expectedValue, newValue); +} + +inline static OBJ_GETTER(AllocInstanceWithAssociatedObject, const TypeInfo* typeInfo, id associatedObject) { + ObjHeader* result = AllocInstance(typeInfo, OBJ_RESULT); + SetAssociatedObject(result, associatedObject); + return result; +} + +extern "C" id Kotlin_ObjCExport_refToObjC(ObjHeader* obj); +extern "C" OBJ_GETTER(Kotlin_ObjCExport_refFromObjC, id obj); + +extern "C" id Kotlin_Interop_CreateNSStringFromKString(KRef str); +extern "C" OBJ_GETTER(Kotlin_Interop_CreateKStringFromNSString, NSString* str); + +#endif // KONAN_OBJC_INTEROP + +#endif // RUNTIME_OBJCEXPORT_H diff --git a/kotlin-native/runtime/src/main/cpp/ObjCExport.mm b/kotlin-native/runtime/src/main/cpp/ObjCExport.mm new file mode 100644 index 00000000000..fde6e386b7b --- /dev/null +++ b/kotlin-native/runtime/src/main/cpp/ObjCExport.mm @@ -0,0 +1,1101 @@ +/* + * Copyright 2010-2017 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "Types.h" +#import "Memory.h" +#include "Natives.h" +#include "ObjCInterop.h" + +#if KONAN_OBJC_INTEROP + +#import +#import +#import +#import +#import +#import +#import +#import +#import +#import +#import +#import + +#import "ObjCExport.h" +#import "ObjCExportInit.h" +#import "ObjCExportPrivate.h" +#import "ObjCMMAPI.h" +#import "Runtime.h" +#import "Utils.h" +#import "Exceptions.h" + +struct ObjCToKotlinMethodAdapter { + const char* selector; + const char* encoding; + IMP imp; +}; + +struct KotlinToObjCMethodAdapter { + const char* selector; + MethodNameHash nameSignature; + ClassId interfaceId; + int itableIndex; + int vtableIndex; + const void* kotlinImpl; +}; + +struct ObjCTypeAdapter { + const TypeInfo* kotlinTypeInfo; + + const void * const * kotlinVtable; + int kotlinVtableSize; + + const MethodTableRecord* kotlinMethodTable; + int kotlinMethodTableSize; + + const InterfaceTableRecord* kotlinItable; + int kotlinItableSize; + + const char* objCName; + + const ObjCToKotlinMethodAdapter* directAdapters; + int directAdapterNum; + + const ObjCToKotlinMethodAdapter* classAdapters; + int classAdapterNum; + + const ObjCToKotlinMethodAdapter* virtualAdapters; + int virtualAdapterNum; + + const KotlinToObjCMethodAdapter* reverseAdapters; + int reverseAdapterNum; +}; + +typedef id (*convertReferenceToObjC)(ObjHeader* obj); +typedef OBJ_GETTER((*convertReferenceFromObjC), id obj); + +struct TypeInfoObjCExportAddition { + /*convertReferenceToObjC*/ void* convert; + Class objCClass; + const ObjCTypeAdapter* typeAdapter; +}; + +struct WritableTypeInfo { + TypeInfoObjCExportAddition objCExport; +}; + + +static char associatedTypeInfoKey; + +extern "C" const TypeInfo* Kotlin_ObjCExport_getAssociatedTypeInfo(Class clazz) { + return (const TypeInfo*)[objc_getAssociatedObject(clazz, &associatedTypeInfoKey) pointerValue]; +} + +static void setAssociatedTypeInfo(Class clazz, const TypeInfo* typeInfo) { + objc_setAssociatedObject(clazz, &associatedTypeInfoKey, [NSValue valueWithPointer:typeInfo], OBJC_ASSOCIATION_RETAIN); +} + +extern "C" id Kotlin_ObjCExport_GetAssociatedObject(ObjHeader* obj) { + return GetAssociatedObject(obj); +} + +extern "C" OBJ_GETTER(Kotlin_ObjCExport_AllocInstanceWithAssociatedObject, + const TypeInfo* typeInfo, id associatedObject) RUNTIME_NOTHROW; + +extern "C" OBJ_GETTER(Kotlin_ObjCExport_AllocInstanceWithAssociatedObject, + const TypeInfo* typeInfo, id associatedObject) { + RETURN_RESULT_OF(AllocInstanceWithAssociatedObject, typeInfo, associatedObject); +} + +static Class getOrCreateClass(const TypeInfo* typeInfo); +static void initializeClass(Class clazz); + +extern "C" id objc_retainAutoreleaseReturnValue(id self); + +extern "C" ALWAYS_INLINE void Kotlin_ObjCExport_releaseAssociatedObject(void* associatedObject) { + if (associatedObject != nullptr) { + auto msgSend = reinterpret_cast(&objc_msgSend); + msgSend(associatedObject, Kotlin_ObjCExport_releaseAsAssociatedObjectSelector); + } +} + +extern "C" id Kotlin_ObjCExport_convertUnit(ObjHeader* unitInstance) { + static dispatch_once_t onceToken; + static id instance = nullptr; + dispatch_once(&onceToken, ^{ + Class unitClass = getOrCreateClass(unitInstance->type_info()); + instance = [[unitClass createWrapper:unitInstance] retain]; + }); + return instance; +} + +extern "C" id Kotlin_ObjCExport_CreateNSStringFromKString(ObjHeader* str) { + KChar* utf16Chars = CharArrayAddressOfElementAt(str->array(), 0); + auto numBytes = str->array()->count_ * sizeof(KChar); + + if (str->permanent()) { + return [[[NSString alloc] initWithBytesNoCopy:utf16Chars + length:numBytes + encoding:NSUTF16LittleEndianStringEncoding + freeWhenDone:NO] autorelease]; + } else { + // TODO: consider making NSString subclass to avoid copying here. + NSString* candidate = [[NSString alloc] initWithBytes:utf16Chars + length:numBytes + encoding:NSUTF16LittleEndianStringEncoding]; + + if (!isShareable(str)) { + SetAssociatedObject(str, candidate); + } else { + id old = AtomicCompareAndSwapAssociatedObject(str, nullptr, candidate); + if (old != nullptr) { + objc_release(candidate); + return objc_retainAutoreleaseReturnValue(old); + } + } + + return objc_retainAutoreleaseReturnValue(candidate); + } +} +static const ObjCTypeAdapter* findAdapterByName( + const char* name, + const ObjCTypeAdapter** sortedAdapters, + int adapterNum +) { + + int left = 0, right = adapterNum - 1; + + while (right >= left) { + int mid = (left + right) / 2; + int cmp = strcmp(name, sortedAdapters[mid]->objCName); + if (cmp < 0) { + right = mid - 1; + } else if (cmp > 0) { + left = mid + 1; + } else { + return sortedAdapters[mid]; + } + } + + return nullptr; +} + +__attribute__((weak)) const ObjCTypeAdapter** Kotlin_ObjCExport_sortedClassAdapters = nullptr; +__attribute__((weak)) int Kotlin_ObjCExport_sortedClassAdaptersNum = 0; + +__attribute__((weak)) const ObjCTypeAdapter** Kotlin_ObjCExport_sortedProtocolAdapters = nullptr; +__attribute__((weak)) int Kotlin_ObjCExport_sortedProtocolAdaptersNum = 0; + +__attribute__((weak)) bool Kotlin_ObjCExport_initTypeAdapters = false; + +static const ObjCTypeAdapter* findClassAdapter(Class clazz) { + return findAdapterByName(class_getName(clazz), + Kotlin_ObjCExport_sortedClassAdapters, + Kotlin_ObjCExport_sortedClassAdaptersNum + ); +} + +static const ObjCTypeAdapter* findProtocolAdapter(Protocol* prot) { + return findAdapterByName(protocol_getName(prot), + Kotlin_ObjCExport_sortedProtocolAdapters, + Kotlin_ObjCExport_sortedProtocolAdaptersNum + ); +} + +static const ObjCTypeAdapter* getTypeAdapter(const TypeInfo* typeInfo) { + return typeInfo->writableInfo_->objCExport.typeAdapter; +} + +static void addProtocolForAdapter(Class clazz, const ObjCTypeAdapter* protocolAdapter) { + Protocol* protocol = objc_getProtocol(protocolAdapter->objCName); + if (protocol != nullptr) { + class_addProtocol(clazz, protocol); + class_addProtocol(object_getClass(clazz), protocol); + } else { + // TODO: construct the protocol in compiler instead, because this case can't be handled easily. + } +} + +static void addProtocolForInterface(Class clazz, const TypeInfo* interfaceInfo) { + const ObjCTypeAdapter* protocolAdapter = getTypeAdapter(interfaceInfo); + if (protocolAdapter != nullptr) { + addProtocolForAdapter(clazz, protocolAdapter); + } +} + +extern "C" const TypeInfo* Kotlin_ObjCInterop_getTypeInfoForClass(Class clazz) { + const TypeInfo* candidate = Kotlin_ObjCExport_getAssociatedTypeInfo(clazz); + + if (candidate != nullptr && (candidate->flags_ & TF_OBJC_DYNAMIC) == 0) { + return candidate; + } else { + return nullptr; + } +} + +extern "C" const TypeInfo* Kotlin_ObjCInterop_getTypeInfoForProtocol(Protocol* protocol) { + const ObjCTypeAdapter* typeAdapter = findProtocolAdapter(protocol); + + return (typeAdapter != nullptr) ? typeAdapter->kotlinTypeInfo : nullptr; +} + +static const TypeInfo* getOrCreateTypeInfo(Class clazz); + +extern "C" void Kotlin_ObjCExport_initializeClass(Class clazz) { + const ObjCTypeAdapter* typeAdapter = findClassAdapter(clazz); + if (typeAdapter == nullptr) { + getOrCreateTypeInfo(clazz); + return; + } + + const TypeInfo* typeInfo = typeAdapter->kotlinTypeInfo; + bool isClassForPackage = typeInfo == nullptr; + if (!isClassForPackage) { + setAssociatedTypeInfo(clazz, typeInfo); + } + + for (int i = 0; i < typeAdapter->directAdapterNum; ++i) { + const ObjCToKotlinMethodAdapter* adapter = typeAdapter->directAdapters + i; + SEL selector = sel_registerName(adapter->selector); + BOOL added = class_addMethod(clazz, selector, adapter->imp, adapter->encoding); + RuntimeAssert(added, "Unexpected selector clash"); + } + + for (int i = 0; i < typeAdapter->classAdapterNum; ++i) { + const ObjCToKotlinMethodAdapter* adapter = typeAdapter->classAdapters + i; + SEL selector = sel_registerName(adapter->selector); + BOOL added = class_addMethod(object_getClass(clazz), selector, adapter->imp, adapter->encoding); + RuntimeAssert(added, "Unexpected selector clash"); + } + + if (isClassForPackage) return; + + for (int i = 0; i < typeInfo->implementedInterfacesCount_; ++i) { + addProtocolForInterface(clazz, typeInfo->implementedInterfaces_[i]); + } + +} + +extern "C" ALWAYS_INLINE OBJ_GETTER(Kotlin_ObjCExport_convertUnmappedObjCObject, id obj) { + const TypeInfo* typeInfo = getOrCreateTypeInfo(object_getClass(obj)); + RETURN_RESULT_OF(AllocInstanceWithAssociatedObject, typeInfo, objc_retain(obj)); +} + +// Initialized by [ObjCExportClasses.mm]. +extern "C" SEL Kotlin_ObjCExport_toKotlinSelector = nullptr; +extern "C" SEL Kotlin_ObjCExport_releaseAsAssociatedObjectSelector = nullptr; + +static OBJ_GETTER(blockToKotlinImp, id self, SEL cmd); +static OBJ_GETTER(boxedBooleanToKotlinImp, NSNumber* self, SEL cmd); + +static OBJ_GETTER(SwiftObject_toKotlinImp, id self, SEL cmd); +static void SwiftObject_releaseAsAssociatedObjectImp(id self, SEL cmd); + +static void initTypeAdaptersFrom(const ObjCTypeAdapter** adapters, int count) { + for (int index = 0; index < count; ++index) { + const ObjCTypeAdapter* adapter = adapters[index]; + const TypeInfo* typeInfo = adapter->kotlinTypeInfo; + if (typeInfo != nullptr) { + typeInfo->writableInfo_->objCExport.typeAdapter = adapter; + } + } +} + +static void initTypeAdapters() { + if (!Kotlin_ObjCExport_initTypeAdapters) return; + + initTypeAdaptersFrom(Kotlin_ObjCExport_sortedClassAdapters, Kotlin_ObjCExport_sortedClassAdaptersNum); + initTypeAdaptersFrom(Kotlin_ObjCExport_sortedProtocolAdapters, Kotlin_ObjCExport_sortedProtocolAdaptersNum); +} + +static void Kotlin_ObjCExport_initializeImpl() { + RuntimeCheck(Kotlin_ObjCExport_toKotlinSelector != nullptr, "unexpected initialization order"); + RuntimeCheck(Kotlin_ObjCExport_releaseAsAssociatedObjectSelector != nullptr, "unexpected initialization order"); + + initTypeAdapters(); + + SEL toKotlinSelector = Kotlin_ObjCExport_toKotlinSelector; + Method toKotlinMethod = class_getClassMethod([NSObject class], toKotlinSelector); + RuntimeAssert(toKotlinMethod != nullptr, ""); + const char* toKotlinTypeEncoding = method_getTypeEncoding(toKotlinMethod); + + SEL releaseAsAssociatedObjectSelector = Kotlin_ObjCExport_releaseAsAssociatedObjectSelector; + Method releaseAsAssociatedObjectMethod = class_getClassMethod([NSObject class], releaseAsAssociatedObjectSelector); + RuntimeAssert(releaseAsAssociatedObjectMethod != nullptr, ""); + const char* releaseAsAssociatedObjectTypeEncoding = method_getTypeEncoding(releaseAsAssociatedObjectMethod); + + Class nsBlockClass = objc_getClass("NSBlock"); + RuntimeAssert(nsBlockClass != nullptr, "NSBlock class not found"); + + // Note: can't add it with category, because it would be considered as private API usage. + BOOL added = class_addMethod(nsBlockClass, toKotlinSelector, (IMP)blockToKotlinImp, toKotlinTypeEncoding); + RuntimeAssert(added, "Unable to add 'toKotlin:' method to NSBlock class"); + + // Note: __NSCFBoolean is not visible to linker, so this case can't be handled with a category too. + Class booleanClass = objc_getClass("__NSCFBoolean"); + RuntimeAssert(booleanClass != nullptr, "__NSCFBoolean class not found"); + + added = class_addMethod(booleanClass, toKotlinSelector, (IMP)boxedBooleanToKotlinImp, toKotlinTypeEncoding); + RuntimeAssert(added, "Unable to add 'toKotlin:' method to __NSCFBoolean class"); + + for (const char* swiftRootClassName : { "SwiftObject", "_TtCs12_SwiftObject" }) { + Class swiftRootClass = objc_getClass(swiftRootClassName); + if (swiftRootClass != nullptr) { + added = class_addMethod(swiftRootClass, toKotlinSelector, (IMP)SwiftObject_toKotlinImp, toKotlinTypeEncoding); + RuntimeAssert(added, "Unable to add 'toKotlin:' method to SwiftObject class"); + + added = class_addMethod( + swiftRootClass, releaseAsAssociatedObjectSelector, + (IMP)SwiftObject_releaseAsAssociatedObjectImp, releaseAsAssociatedObjectTypeEncoding + ); + RuntimeAssert(added, "Unable to add 'releaseAsAssociatedObject' method to SwiftObject class"); + } + } +} + +// Initializes ObjCExport for current process (if not initialized yet). +// Generally this is equal to some "binary patching" (which is usually done at link time +// but postponed until runtime here due to various reasons): +// adds methods to Objective-C classes, initializes static memory with "constant" values etc. +extern "C" void Kotlin_ObjCExport_initialize() { + static dispatch_once_t onceToken; + dispatch_once(&onceToken, ^{ + Kotlin_ObjCExport_initializeImpl(); + }); +} + +static OBJ_GETTER(SwiftObject_toKotlinImp, id self, SEL cmd) { + RETURN_RESULT_OF(Kotlin_ObjCExport_convertUnmappedObjCObject, self); +} + +static void SwiftObject_releaseAsAssociatedObjectImp(id self, SEL cmd) { + objc_release(self); +} + + +extern "C" OBJ_GETTER(Kotlin_boxBoolean, KBoolean value); + +static OBJ_GETTER(boxedBooleanToKotlinImp, NSNumber* self, SEL cmd) { + RETURN_RESULT_OF(Kotlin_boxBoolean, self.boolValue); +} + +struct Block_descriptor_1; + +// Based on https://clang.llvm.org/docs/Block-ABI-Apple.html and libclosure source. +struct Block_literal_1 { + void *isa; // initialized to &_NSConcreteStackBlock or &_NSConcreteGlobalBlock + int flags; + int reserved; + void (*invoke)(void *, ...); + struct Block_descriptor_1 *descriptor; // IFF (1<<25) + // Or: + // struct Block_descriptor_1_without_helpers* descriptor // if hasn't (1<<25). + + // imported variables +}; + +struct Block_literal_1 exportBlockLiteral; + +struct Block_descriptor_1 { + unsigned long int reserved; // NULL + unsigned long int size; // sizeof(struct Block_literal_1) + + // optional helper functions + void (*copy_helper)(void *dst, void *src); + void (*dispose_helper)(void *src); + // required ABI.2010.3.16 + const char *signature; // IFF (1<<30) + const void* layout; // IFF (1<<31) +}; + +struct Block_descriptor_1_without_helpers { + unsigned long int reserved; // NULL + unsigned long int size; // sizeof(struct Block_literal_1) + + // required ABI.2010.3.16 + const char *signature; // IFF (1<<30) + const void* layout; // IFF (1<<31) +}; + +static const char* getBlockEncoding(id block) { + Block_literal_1* literal = reinterpret_cast(block); + + int flags = literal->flags; + RuntimeAssert((flags & (1 << 30)) != 0, "block has no signature stored"); + return (flags & (1 << 25)) != 0 ? + literal->descriptor->signature : + reinterpret_cast(literal->descriptor)->signature; +} + +// Note: defined by compiler. +extern "C" convertReferenceFromObjC* Kotlin_ObjCExport_blockToFunctionConverters; +extern "C" int Kotlin_ObjCExport_blockToFunctionConverters_size; + +static OBJ_GETTER(blockToKotlinImp, id block, SEL cmd) { + const char* encoding = getBlockEncoding(block); + + // TODO: optimize: + NSMethodSignature *signature = [NSMethodSignature signatureWithObjCTypes:encoding]; + int parameterCount = signature.numberOfArguments - 1; // 1 for the block itself. + + for (int i = 1; i <= parameterCount; ++i) { + const char* argEncoding = [signature getArgumentTypeAtIndex:i]; + if (argEncoding[0] != '@') { + [NSException raise:NSGenericException + format:@"Blocks with non-reference-typed arguments aren't supported (%s)", argEncoding]; + } + } + + const char* returnTypeEncoding = signature.methodReturnType; + if (returnTypeEncoding[0] != '@') { + [NSException raise:NSGenericException + format:@"Blocks with non-reference-typed return value aren't supported (%s)", returnTypeEncoding]; + } + + auto converter = parameterCount < Kotlin_ObjCExport_blockToFunctionConverters_size + ? Kotlin_ObjCExport_blockToFunctionConverters[parameterCount] + : nullptr; + + if (converter != nullptr) { + RETURN_RESULT_OF(converter, block); + } else { + // There is no function class for this arity, so resulting object will not be cast to FunctionN class, + // and it is enough to convert block to arbitrary object conforming Function. + RETURN_RESULT_OF(AllocInstanceWithAssociatedObject, theOpaqueFunctionTypeInfo, objc_retainBlock(block)); + } +} + +static id Kotlin_ObjCExport_refToObjC_slowpath(ObjHeader* obj); + +template +static ALWAYS_INLINE id Kotlin_ObjCExport_refToObjCImpl(ObjHeader* obj) { + if (obj == nullptr) return nullptr; + + id associatedObject = GetAssociatedObject(obj); + if (associatedObject != nullptr) { + return retainAutorelease ? objc_retainAutoreleaseReturnValue(associatedObject) : associatedObject; + } + + // TODO: propagate [retainAutorelease] to the code below. + + convertReferenceToObjC converter = (convertReferenceToObjC)obj->type_info()->writableInfo_->objCExport.convert; + if (converter != nullptr) { + return converter(obj); + } + + return Kotlin_ObjCExport_refToObjC_slowpath(obj); +} + +extern "C" id Kotlin_ObjCExport_refToObjC(ObjHeader* obj) { + // TODO: in some cases (e.g. when converting a bridge argument) performing retain-autorelease is not necessary. + return Kotlin_ObjCExport_refToObjCImpl(obj); +} + +extern "C" ALWAYS_INLINE id Kotlin_Interop_refToObjC(ObjHeader* obj) { + return Kotlin_ObjCExport_refToObjCImpl(obj); +} + +extern "C" ALWAYS_INLINE OBJ_GETTER(Kotlin_Interop_refFromObjC, id obj) { + // TODO: consider removing this function. + RETURN_RESULT_OF(Kotlin_ObjCExport_refFromObjC, obj); +} + +extern "C" OBJ_GETTER(Kotlin_Interop_CreateObjCObjectHolder, id obj) { + RuntimeAssert(obj != nullptr, "wrapped object must not be null"); + const TypeInfo* typeInfo = theForeignObjCObjectTypeInfo; + RETURN_RESULT_OF(AllocInstanceWithAssociatedObject, typeInfo, objc_retain(obj)); +} + +extern "C" OBJ_GETTER(Kotlin_ObjCExport_refFromObjC, id obj) { + if (obj == nullptr) RETURN_OBJ(nullptr); + auto msgSend = reinterpret_cast(&objc_msgSend); + RETURN_RESULT_OF(msgSend, obj, Kotlin_ObjCExport_toKotlinSelector); +} + +static id convertKotlinObject(ObjHeader* obj) { + Class clazz = obj->type_info()->writableInfo_->objCExport.objCClass; + RuntimeAssert(clazz != nullptr, ""); + return [clazz createWrapper:obj]; +} + +static convertReferenceToObjC findConverterFromInterfaces(const TypeInfo* typeInfo) { + const TypeInfo* foundTypeInfo = nullptr; + + for (int i = 0; i < typeInfo->implementedInterfacesCount_; ++i) { + const TypeInfo* interfaceTypeInfo = typeInfo->implementedInterfaces_[i]; + if ((interfaceTypeInfo->flags_ & TF_SUSPEND_FUNCTION) != 0) { + // interfaceTypeInfo is a SuspendFunction$N interface. + // So any instance of typeInfo is a suspend lambda or a suspend callable reference + // (user-defined Kotlin classes implementing SuspendFunction$N are prohibited by the compiler). + // + // Such types also actually implement Function${N+1} interface as an optimization + // (see e.g. [startCoroutineUninterceptedOrReturn implementation). + // This fact is not user-visible, so ignoring Function${N+1} interface here + // (and thus not converting such objects to Obj-C blocks) should be safe enough + // (because such objects aren't expected to be passed from Kotlin to Swift + // under formal Function${N+1} type). + // + // On the other hand, this fixes support for SuspendFunction$N type: it is mapped as + // regular Kotlin interface, so its instances should be converted on a general basis + // (i.e. to objects implementing Obj-C representation of SuspendFunction$N, not to Obj-C blocks). + // + // "If typeInfo is a suspend lambda or callable reference type, convert its instances on a regular basis": + return nullptr; + } + + if (interfaceTypeInfo->writableInfo_->objCExport.convert != nullptr) { + if (foundTypeInfo == nullptr || IsSubInterface(interfaceTypeInfo, foundTypeInfo)) { + foundTypeInfo = interfaceTypeInfo; + } else if (!IsSubInterface(foundTypeInfo, interfaceTypeInfo)) { + [NSException raise:NSGenericException + format:@"Can't convert to Objective-C Kotlin object that is '%@' and '%@' and the same time", + Kotlin_Interop_CreateNSStringFromKString(foundTypeInfo->relativeName_), + Kotlin_Interop_CreateNSStringFromKString(interfaceTypeInfo->relativeName_)]; + } + } + } + + return foundTypeInfo == nullptr ? + nullptr : + (convertReferenceToObjC)foundTypeInfo->writableInfo_->objCExport.convert; +} + +static id Kotlin_ObjCExport_refToObjC_slowpath(ObjHeader* obj) { + const TypeInfo* typeInfo = obj->type_info(); + convertReferenceToObjC converter = nullptr; + + converter = findConverterFromInterfaces(typeInfo); + + if (converter == nullptr) { + getOrCreateClass(typeInfo); + converter = (typeInfo == theUnitTypeInfo) ? &Kotlin_ObjCExport_convertUnit : &convertKotlinObject; + } + + typeInfo->writableInfo_->objCExport.convert = (void*)converter; + + return converter(obj); +} + +static void buildITable(TypeInfo* result, const KStdOrderedMap>& interfaceVTables) { + // Check if can use fast optimistic version - check if the size of the itable could be 2^k and <= 32. + bool useFastITable; + int itableSize = 1; + for (; itableSize <= 32; itableSize <<= 1) { + useFastITable = true; + bool used[32]; + memset(used, 0, sizeof(used)); + for (auto& pair : interfaceVTables) { + auto interfaceId = pair.first; + auto index = interfaceId & (itableSize - 1); + if (used[index]) { + useFastITable = false; + break; + } + used[index] = true; + } + if (useFastITable) break; + } + if (!useFastITable) + itableSize = interfaceVTables.size(); + + auto itable_ = konanAllocArray(itableSize); + result->interfaceTable_ = itable_; + result->interfaceTableSize_ = useFastITable ? itableSize - 1 : -itableSize; + + if (useFastITable) { + for (auto& pair : interfaceVTables) { + auto interfaceId = pair.first; + auto index = interfaceId & (itableSize - 1); + itable_[index].id = interfaceId; + } + } else { + // Otherwise: conservative version. + // The table will be sorted since we're using KStdOrderedMap. + int index = 0; + for (auto& pair : interfaceVTables) { + auto interfaceId = pair.first; + itable_[index++].id = interfaceId; + } + } + + for (int i = 0; i < itableSize; ++i) { + auto interfaceId = itable_[i].id; + if (interfaceId == kInvalidInterfaceId) continue; + auto interfaceVTableIt = interfaceVTables.find(interfaceId); + RuntimeAssert(interfaceVTableIt != interfaceVTables.end(), ""); + auto const& interfaceVTable = interfaceVTableIt->second; + int interfaceVTableSize = interfaceVTable.size(); + auto interfaceVTable_ = interfaceVTableSize == 0 ? nullptr : konanAllocArray(interfaceVTableSize); + for (int j = 0; j < interfaceVTableSize; ++j) + interfaceVTable_[j] = interfaceVTable[j]; + itable_[i].vtable = interfaceVTable_; + itable_[i].vtableSize = interfaceVTableSize; + } +} + +static const TypeInfo* createTypeInfo( + const TypeInfo* superType, + const KStdVector& superInterfaces, + const KStdVector& vtable, + const KStdVector& methodTable, + const KStdOrderedMap>& interfaceVTables, + const InterfaceTableRecord* superItable, + int superItableSize, + bool itableEqualsSuper, + const TypeInfo* fieldsInfo +) { + TypeInfo* result = (TypeInfo*)konanAllocMemory(sizeof(TypeInfo) + vtable.size() * sizeof(void*)); + result->typeInfo_ = result; + + result->flags_ = TF_OBJC_DYNAMIC; + + result->superType_ = superType; + if (fieldsInfo == nullptr) { + result->instanceSize_ = superType->instanceSize_; + result->objOffsets_ = superType->objOffsets_; + result->objOffsetsCount_ = superType->objOffsetsCount_; // So TF_IMMUTABLE can also be inherited: + if ((superType->flags_ & TF_IMMUTABLE) != 0) { + result->flags_ |= TF_IMMUTABLE; + } + } else { + result->instanceSize_ = fieldsInfo->instanceSize_; + result->objOffsets_ = fieldsInfo->objOffsets_; + result->objOffsetsCount_ = fieldsInfo->objOffsetsCount_; + } + + result->classId_ = superType->classId_; + + KStdVector implementedInterfaces( + superType->implementedInterfaces_, superType->implementedInterfaces_ + superType->implementedInterfacesCount_ + ); + KStdUnorderedSet usedInterfaces(implementedInterfaces.begin(), implementedInterfaces.end()); + + for (const TypeInfo* interface : superInterfaces) { + if (usedInterfaces.insert(interface).second) { + implementedInterfaces.push_back(interface); + } + } + + const TypeInfo** implementedInterfaces_ = konanAllocArray(implementedInterfaces.size()); + for (size_t i = 0; i < implementedInterfaces.size(); ++i) { + implementedInterfaces_[i] = implementedInterfaces[i]; + } + + result->implementedInterfaces_ = implementedInterfaces_; + result->implementedInterfacesCount_ = implementedInterfaces.size(); + if (superItable != nullptr) { + if (itableEqualsSuper) { + result->interfaceTableSize_ = superItableSize; + result->interfaceTable_ = superItable; + } else { + buildITable(result, interfaceVTables); + } + } + + MethodTableRecord* openMethods_ = konanAllocArray(methodTable.size()); + for (size_t i = 0; i < methodTable.size(); ++i) openMethods_[i] = methodTable[i]; + + result->openMethods_ = openMethods_; + result->openMethodsCount_ = methodTable.size(); + + result->packageName_ = nullptr; + result->relativeName_ = nullptr; // TODO: add some info. + result->writableInfo_ = (WritableTypeInfo*)konanAllocMemory(sizeof(WritableTypeInfo)); + + for (size_t i = 0; i < vtable.size(); ++i) result->vtable()[i] = vtable[i]; + + return result; +} + +static void addDefinedSelectors(Class clazz, KStdUnorderedSet& result) { + unsigned int objcMethodCount; + Method* objcMethods = class_copyMethodList(clazz, &objcMethodCount); + + for (unsigned int i = 0; i < objcMethodCount; ++i) { + result.insert(method_getName(objcMethods[i])); + } + + if (objcMethods != nullptr) free(objcMethods); +} + +static KStdVector getProtocolsAsInterfaces(Class clazz) { + KStdVector result; + KStdUnorderedSet handledProtocols; + KStdVector protocolsToHandle; + + { + unsigned int protocolCount; + Protocol** protocols = class_copyProtocolList(clazz, &protocolCount); + if (protocols != nullptr) { + protocolsToHandle.insert(protocolsToHandle.end(), protocols, protocols + protocolCount); + free(protocols); + } + } + + while (!protocolsToHandle.empty()) { + Protocol* proto = protocolsToHandle[protocolsToHandle.size() - 1]; + protocolsToHandle.pop_back(); + + if (handledProtocols.insert(proto).second) { + const ObjCTypeAdapter* typeAdapter = findProtocolAdapter(proto); + if (typeAdapter != nullptr) result.push_back(typeAdapter->kotlinTypeInfo); + + unsigned int protocolCount; + Protocol** protocols = protocol_copyProtocolList(proto, &protocolCount); + if (protocols != nullptr) { + protocolsToHandle.insert(protocolsToHandle.end(), protocols, protocols + protocolCount); + free(protocols); + } + } + } + + return result; +} + +static const TypeInfo* getMostSpecificKotlinClass(const TypeInfo* typeInfo) { + const TypeInfo* result = typeInfo; + while (getTypeAdapter(result) == nullptr) { + result = result->superType_; + RuntimeAssert(result != nullptr, ""); + } + + return result; +} + +static int getVtableSize(const TypeInfo* typeInfo) { + for (const TypeInfo* current = typeInfo; current != nullptr; current = current->superType_) { + auto typeAdapter = getTypeAdapter(current); + if (typeAdapter != nullptr) return typeAdapter->kotlinVtableSize; + } + + RuntimeAssert(false, ""); + return -1; +} + +static void insertOrReplace(KStdVector& methodTable, MethodNameHash nameSignature, void* entryPoint) { + MethodTableRecord record = {nameSignature, entryPoint}; + + for (int i = methodTable.size() - 1; i >= 0; --i) { + if (methodTable[i].nameSignature_ == nameSignature) { + methodTable[i].methodEntryPoint_ = entryPoint; + return; + } else if (methodTable[i].nameSignature_ < nameSignature) { + methodTable.insert(methodTable.begin() + (i + 1), record); + return; + } + } + + methodTable.insert(methodTable.begin(), record); +} + +static void throwIfCantBeOverridden(Class clazz, const KotlinToObjCMethodAdapter* adapter) { + if (adapter->kotlinImpl == nullptr) { + NSString* reason; + switch (adapter->vtableIndex) { + case -1: reason = @"it is final"; break; + case -2: reason = @"original Kotlin method has more than one selector"; break; + default: reason = @""; break; + } + [NSException raise:NSGenericException + format:@"[%s %s] can't be overridden: %@", + class_getName(clazz), adapter->selector, reason]; + } +} + +static const TypeInfo* createTypeInfo(Class clazz, const TypeInfo* superType, const TypeInfo* fieldsInfo) { + KStdUnorderedSet definedSelectors; + addDefinedSelectors(clazz, definedSelectors); + + const ObjCTypeAdapter* superTypeAdapter = getTypeAdapter(superType); + + const void * const * superVtable = nullptr; + int superVtableSize = getVtableSize(superType); + + const MethodTableRecord* superMethodTable = nullptr; + int superMethodTableSize = 0; + + InterfaceTableRecord const* superITable = nullptr; + int superITableSize = 0; + + if (superTypeAdapter != nullptr) { + // Then super class is Kotlin class. + + // And if it is abstract, then vtable and method table are not available from TypeInfo, + // but present in type adapter instead: + superVtable = superTypeAdapter->kotlinVtable; + superMethodTable = superTypeAdapter->kotlinMethodTable; + superMethodTableSize = superTypeAdapter->kotlinMethodTableSize; + superITable = superTypeAdapter->kotlinItable; + superITableSize = superTypeAdapter->kotlinItableSize; + } + + if (superVtable == nullptr) superVtable = superType->vtable(); + if (superMethodTable == nullptr) { + superMethodTable = superType->openMethods_; + superMethodTableSize = superType->openMethodsCount_; + } + + KStdVector vtable( + superVtable, + superVtable + superVtableSize + ); + + KStdVector methodTable( + superMethodTable, superMethodTable + superMethodTableSize + ); + + if (superITable == nullptr) { + superITable = superType->interfaceTable_; + superITableSize = superType->interfaceTableSize_; + } + KStdOrderedMap> interfaceVTables; + if (superITable != nullptr) { + int actualItableSize = superITableSize >= 0 ? superITableSize + 1 : -superITableSize; + for (int i = 0; i < actualItableSize; ++i) { + auto& record = superITable[i]; + auto interfaceId = record.id; + if (interfaceId == kInvalidInterfaceId) continue; + int vtableSize = record.vtableSize; + KStdVector interfaceVTable(vtableSize); + for (int j = 0; j < vtableSize; ++j) + interfaceVTable[j] = record.vtable[j]; + interfaceVTables.emplace(interfaceId, std::move(interfaceVTable)); + } + } + + KStdVector addedInterfaces = getProtocolsAsInterfaces(clazz); + + KStdVector supers( + superType->implementedInterfaces_, + superType->implementedInterfaces_ + superType->implementedInterfacesCount_ + ); + + for (const TypeInfo* t = superType; t != nullptr; t = t->superType_) { + supers.push_back(t); + } + + auto addToITable = [&interfaceVTables](ClassId interfaceId, int methodIndex, VTableElement entry) { + RuntimeAssert(interfaceId != kInvalidInterfaceId, ""); + auto interfaceVTableIt = interfaceVTables.find(interfaceId); + RuntimeAssert(interfaceVTableIt != interfaceVTables.end(), ""); + auto& interfaceVTable = interfaceVTableIt->second; + RuntimeAssert(methodIndex >= 0 && static_cast(methodIndex) < interfaceVTable.size(), ""); + interfaceVTable[methodIndex] = entry; + }; + + bool itableEqualsSuper = true; + for (const TypeInfo* t : supers) { + const ObjCTypeAdapter* typeAdapter = getTypeAdapter(t); + if (typeAdapter == nullptr) continue; + + for (int i = 0; i < typeAdapter->reverseAdapterNum; ++i) { + const KotlinToObjCMethodAdapter* adapter = &typeAdapter->reverseAdapters[i]; + if (definedSelectors.find(sel_registerName(adapter->selector)) == definedSelectors.end()) continue; + + throwIfCantBeOverridden(clazz, adapter); + + itableEqualsSuper = false; + insertOrReplace(methodTable, adapter->nameSignature, const_cast(adapter->kotlinImpl)); + if (adapter->vtableIndex != -1) vtable[adapter->vtableIndex] = adapter->kotlinImpl; + + if (adapter->itableIndex != -1 && superITable != nullptr) + addToITable(adapter->interfaceId, adapter->itableIndex, adapter->kotlinImpl); + } + } + + for (const TypeInfo* typeInfo : addedInterfaces) { + const ObjCTypeAdapter* typeAdapter = getTypeAdapter(typeInfo); + + if (typeAdapter == nullptr) continue; + + if (superITable != nullptr) { + auto interfaceId = typeInfo->classId_; + int interfaceVTableSize = typeAdapter->kotlinItableSize; + RuntimeAssert(interfaceVTableSize >= 0, ""); + auto interfaceVTablesIt = interfaceVTables.find(interfaceId); + if (interfaceVTablesIt == interfaceVTables.end()) { + itableEqualsSuper = false; + interfaceVTables.emplace(interfaceId, KStdVector(interfaceVTableSize)); + } else { + auto const& interfaceVTable = interfaceVTablesIt->second; + RuntimeAssert(interfaceVTable.size() == static_cast(interfaceVTableSize), ""); + } + } + + for (int i = 0; i < typeAdapter->reverseAdapterNum; ++i) { + itableEqualsSuper = false; + const KotlinToObjCMethodAdapter* adapter = &typeAdapter->reverseAdapters[i]; + throwIfCantBeOverridden(clazz, adapter); + + insertOrReplace(methodTable, adapter->nameSignature, const_cast(adapter->kotlinImpl)); + RuntimeAssert(adapter->vtableIndex == -1, ""); + + if (adapter->itableIndex != -1 && superITable != nullptr) + addToITable(adapter->interfaceId, adapter->itableIndex, adapter->kotlinImpl); + } + } + + // TODO: consider forbidding the class being abstract. + + const TypeInfo* result = createTypeInfo(superType, addedInterfaces, vtable, methodTable, + interfaceVTables, superITable, superITableSize, itableEqualsSuper, + fieldsInfo); + + // TODO: it will probably never be requested, since such a class can't be instantiated in Kotlin. + result->writableInfo_->objCExport.objCClass = clazz; + return result; +} + +static SimpleMutex typeInfoCreationMutex; + +static const TypeInfo* getOrCreateTypeInfo(Class clazz) { + const TypeInfo* result = Kotlin_ObjCExport_getAssociatedTypeInfo(clazz); + if (result != nullptr) { + return result; + } + + Class superClass = class_getSuperclass(clazz); + + const TypeInfo* superType = superClass == nullptr ? + theForeignObjCObjectTypeInfo : + getOrCreateTypeInfo(superClass); + + LockGuard lockGuard(typeInfoCreationMutex); + + result = Kotlin_ObjCExport_getAssociatedTypeInfo(clazz); // double-checking. + if (result == nullptr) { + result = createTypeInfo(clazz, superType, nullptr); + setAssociatedTypeInfo(clazz, result); + } + + return result; +} + +const TypeInfo* Kotlin_ObjCExport_createTypeInfoWithKotlinFieldsFrom(Class clazz, const TypeInfo* fieldsInfo) { + Class superClass = class_getSuperclass(clazz); + RuntimeCheck(superClass != nullptr, ""); + + const TypeInfo* superType = getOrCreateTypeInfo(superClass); + + return createTypeInfo(clazz, superType, fieldsInfo); +} + +static SimpleMutex classCreationMutex; +static int anonymousClassNextId = 0; + +static void addVirtualAdapters(Class clazz, const ObjCTypeAdapter* typeAdapter) { + for (int i = 0; i < typeAdapter->virtualAdapterNum; ++i) { + const ObjCToKotlinMethodAdapter* adapter = typeAdapter->virtualAdapters + i; + SEL selector = sel_registerName(adapter->selector); + + class_addMethod(clazz, selector, adapter->imp, adapter->encoding); + } +} + +static Class createClass(const TypeInfo* typeInfo, Class superClass) { + RuntimeAssert(typeInfo->superType_ != nullptr, ""); + + int classIndex = (anonymousClassNextId++); + KStdString className = Kotlin_ObjCInterop_getUniquePrefix(); + className += "_kobjcc"; + className += std::to_string(classIndex); + + Class result = objc_allocateClassPair(superClass, className.c_str(), 0); + RuntimeCheck(result != nullptr, ""); + + // TODO: optimize by adding virtual adapters only for overridden methods. + + if (getTypeAdapter(typeInfo->superType_) == nullptr) { + // class for super type is also synthesized, no need to add class adapters; + } else { + for (const TypeInfo* superType = typeInfo->superType_; superType != nullptr; superType = superType->superType_) { + const ObjCTypeAdapter* typeAdapter = getTypeAdapter(superType); + if (typeAdapter != nullptr) { + addVirtualAdapters(result, typeAdapter); + } + } + } + + KStdUnorderedSet superImplementedInterfaces( + typeInfo->superType_->implementedInterfaces_, + typeInfo->superType_->implementedInterfaces_ + typeInfo->superType_->implementedInterfacesCount_ + ); + + for (int i = 0; i < typeInfo->implementedInterfacesCount_; ++i) { + const TypeInfo* interface = typeInfo->implementedInterfaces_[i]; + if (superImplementedInterfaces.find(interface) == superImplementedInterfaces.end()) { + const ObjCTypeAdapter* typeAdapter = getTypeAdapter(interface); + if (typeAdapter != nullptr) { + addVirtualAdapters(result, typeAdapter); + addProtocolForAdapter(result, typeAdapter); + } + } + } + + objc_registerClassPair(result); + + // TODO: it will probably never be requested, since such a class can't be instantiated in Objective-C. + setAssociatedTypeInfo(result, typeInfo); + + return result; +} + +static Class getOrCreateClass(const TypeInfo* typeInfo) { + Class result = typeInfo->writableInfo_->objCExport.objCClass; + if (result != nullptr) { + return result; + } + + const ObjCTypeAdapter* typeAdapter = getTypeAdapter(typeInfo); + if (typeAdapter != nullptr) { + result = objc_getClass(typeAdapter->objCName); + RuntimeAssert(result != nullptr, ""); + typeInfo->writableInfo_->objCExport.objCClass = result; + } else { + Class superClass = getOrCreateClass(typeInfo->superType_); + + LockGuard lockGuard(classCreationMutex); // Note: non-recursive + + result = typeInfo->writableInfo_->objCExport.objCClass; // double-checking. + if (result == nullptr) { + result = createClass(typeInfo, superClass); + RuntimeAssert(result != nullptr, ""); + typeInfo->writableInfo_->objCExport.objCClass = result; + } + } + + return result; +} + +extern "C" void Kotlin_ObjCExport_AbstractMethodCalled(id self, SEL selector) { + [NSException raise:NSGenericException + format:@"[%s %s] is abstract", + class_getName(object_getClass(self)), sel_getName(selector)]; +} + +#else + +extern "C" ALWAYS_INLINE void* Kotlin_Interop_refToObjC(ObjHeader* obj) { + RuntimeAssert(false, "Unavailable operation"); + return nullptr; +} + +extern "C" ALWAYS_INLINE OBJ_GETTER(Kotlin_Interop_refFromObjC, void* obj) { + RuntimeAssert(false, "Unavailable operation"); + RETURN_OBJ(nullptr); +} + +#endif // KONAN_OBJC_INTEROP diff --git a/kotlin-native/runtime/src/main/cpp/ObjCExportCollectionUtils.mm b/kotlin-native/runtime/src/main/cpp/ObjCExportCollectionUtils.mm new file mode 100644 index 00000000000..b1f5a7e8e72 --- /dev/null +++ b/kotlin-native/runtime/src/main/cpp/ObjCExportCollectionUtils.mm @@ -0,0 +1,269 @@ +/* + * Copyright 2010-2019 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "Memory.h" +#import "Types.h" + +#if KONAN_OBJC_INTEROP + +#import + +#import +#import +#import + +#import "Exceptions.h" +#import "ObjCExport.h" +#import "ObjCExportCollections.h" + +extern "C" { + +// Imports from ObjCExportUtils.kt: + +OBJ_GETTER0(Kotlin_NSEnumeratorAsKIterator_create); + +void Kotlin_NSEnumeratorAsKIterator_done(KRef thiz); +void Kotlin_NSEnumeratorAsKIterator_setNext(KRef thiz, KRef value); + +void Kotlin_ObjCExport_ThrowCollectionTooLarge(); +void Kotlin_ObjCExport_ThrowCollectionConcurrentModification(); + +} + +static inline KInt objCSizeToKotlinOrThrow(NSUInteger size) { + if (size > std::numeric_limits::max()) { + Kotlin_ObjCExport_ThrowCollectionTooLarge(); + } + + return size; +} + +// Exported to ObjCExportUtils.kt: + +extern "C" KInt Kotlin_NSArrayAsKList_getSize(KRef obj) { + NSArray* array = (NSArray*) GetAssociatedObject(obj); + return objCSizeToKotlinOrThrow([array count]); +} + +extern "C" OBJ_GETTER(Kotlin_NSArrayAsKList_get, KRef obj, KInt index) { + NSArray* array = (NSArray*) GetAssociatedObject(obj); + id element = [array objectAtIndex:index]; + RETURN_RESULT_OF(refFromObjCOrNSNull, element); +} + +extern "C" void Kotlin_NSMutableArrayAsKMutableList_add(KRef thiz, KInt index, KRef element) { + NSMutableArray* mutableArray = (NSMutableArray*) GetAssociatedObject(thiz); + [mutableArray insertObject:refToObjCOrNSNull(element) atIndex:index]; +} + +extern "C" OBJ_GETTER(Kotlin_NSMutableArrayAsKMutableList_removeAt, KRef thiz, KInt index) { + NSMutableArray* mutableArray = (NSMutableArray*) GetAssociatedObject(thiz); + + KRef res = refFromObjCOrNSNull([mutableArray objectAtIndex:index], OBJ_RESULT); + [mutableArray removeObjectAtIndex:index]; + + return res; +} + +extern "C" OBJ_GETTER(Kotlin_NSMutableArrayAsKMutableList_set, KRef thiz, KInt index, KRef element) { + NSMutableArray* mutableArray = (NSMutableArray*) GetAssociatedObject(thiz); + + KRef res = refFromObjCOrNSNull([mutableArray objectAtIndex:index], OBJ_RESULT); + [mutableArray replaceObjectAtIndex:index withObject:refToObjCOrNSNull(element)]; + + return res; +} + +extern "C" void Kotlin_NSEnumeratorAsKIterator_computeNext(KRef thiz) { + NSEnumerator* enumerator = (NSEnumerator*) GetAssociatedObject(thiz); + id next = [enumerator nextObject]; + if (next == nullptr) { + Kotlin_NSEnumeratorAsKIterator_done(thiz); + } else { + ObjHolder holder; + Kotlin_NSEnumeratorAsKIterator_setNext(thiz, refFromObjCOrNSNull(next, holder.slot())); + } +} + +extern "C" KInt Kotlin_NSSetAsKSet_getSize(KRef thiz) { + NSSet* set = (NSSet*) GetAssociatedObject(thiz); + return objCSizeToKotlinOrThrow(set.count); +} + +extern "C" KBoolean Kotlin_NSSetAsKSet_contains(KRef thiz, KRef element) { + NSSet* set = (NSSet*) GetAssociatedObject(thiz); + return [set containsObject:refToObjCOrNSNull(element)]; +} + +extern "C" OBJ_GETTER(Kotlin_NSSetAsKSet_getElement, KRef thiz, KRef element) { + NSSet* set = (NSSet*) GetAssociatedObject(thiz); + id res = [set member:refToObjCOrNSNull(element)]; + RETURN_RESULT_OF(refFromObjCOrNSNull, res); +} + +static inline OBJ_GETTER(CreateKIteratorFromNSEnumerator, NSEnumerator* enumerator) { + RETURN_RESULT_OF(invokeAndAssociate, Kotlin_NSEnumeratorAsKIterator_create, objc_retain(enumerator)); +} + +extern "C" OBJ_GETTER(Kotlin_NSSetAsKSet_iterator, KRef thiz) { + NSSet* set = (NSSet*) GetAssociatedObject(thiz); + RETURN_RESULT_OF(CreateKIteratorFromNSEnumerator, [set objectEnumerator]); +} + +extern "C" KInt Kotlin_NSDictionaryAsKMap_getSize(KRef thiz) { + NSDictionary* dict = (NSDictionary*) GetAssociatedObject(thiz); + return objCSizeToKotlinOrThrow(dict.count); +} + +extern "C" KBoolean Kotlin_NSDictionaryAsKMap_containsKey(KRef thiz, KRef key) { + NSDictionary* dict = (NSDictionary*) GetAssociatedObject(thiz); + return [dict objectForKey:refToObjCOrNSNull(key)] != nullptr; +} + +extern "C" KBoolean Kotlin_NSDictionaryAsKMap_containsValue(KRef thiz, KRef value) { + NSDictionary* dict = (NSDictionary*) GetAssociatedObject(thiz); + id objCValue = refToObjCOrNSNull(value); + for (id key in dict) { + if ([[dict objectForKey:key] isEqual:objCValue]) { + return true; + } + } + + return false; +} + +extern "C" OBJ_GETTER(Kotlin_NSDictionaryAsKMap_get, KRef thiz, KRef key) { + NSDictionary* dict = (NSDictionary*) GetAssociatedObject(thiz); + id value = [dict objectForKey:refToObjCOrNSNull(key)]; + RETURN_RESULT_OF(refFromObjCOrNSNull, value); +} + +extern "C" OBJ_GETTER(Kotlin_NSDictionaryAsKMap_getOrThrowConcurrentModification, KRef thiz, KRef key) { + NSDictionary* dict = (NSDictionary*) GetAssociatedObject(thiz); + id value = [dict objectForKey:refToObjCOrNSNull(key)]; + if (value == nullptr) { + Kotlin_ObjCExport_ThrowCollectionConcurrentModification(); + } + + RETURN_RESULT_OF(refFromObjCOrNSNull, value); +} + +extern "C" KBoolean Kotlin_NSDictionaryAsKMap_containsEntry(KRef thiz, KRef key, KRef value) { + NSDictionary* dict = (NSDictionary*) GetAssociatedObject(thiz); + return [refToObjCOrNSNull(value) isEqual:[dict objectForKey:refToObjCOrNSNull(key)]]; +} + +extern "C" OBJ_GETTER(Kotlin_NSDictionaryAsKMap_keyIterator, KRef thiz) { + NSDictionary* dict = (NSDictionary*) GetAssociatedObject(thiz); + RETURN_RESULT_OF(CreateKIteratorFromNSEnumerator, [dict keyEnumerator]); +} + +extern "C" OBJ_GETTER(Kotlin_NSDictionaryAsKMap_valueIterator, KRef thiz) { + NSDictionary* dict = (NSDictionary*) GetAssociatedObject(thiz); + RETURN_RESULT_OF(CreateKIteratorFromNSEnumerator, [dict objectEnumerator]); +} + +#else // KONAN_OBJC_INTEROP + +extern "C" KInt Kotlin_NSArrayAsKList_getSize(KRef obj) { + RuntimeAssert(false, "Objective-C interop is disabled"); + return -1; +} + +extern "C" OBJ_GETTER(Kotlin_NSArrayAsKList_get, KRef obj, KInt index) { + RuntimeAssert(false, "Objective-C interop is disabled"); + RETURN_OBJ(nullptr); +} + +extern "C" void Kotlin_NSMutableArrayAsKMutableList_add(KRef thiz, KInt index, KRef element) { + RuntimeAssert(false, "Objective-C interop is disabled"); +} + +extern "C" OBJ_GETTER(Kotlin_NSMutableArrayAsKMutableList_removeAt, KRef thiz, KInt index) { + RuntimeAssert(false, "Objective-C interop is disabled"); + RETURN_OBJ(nullptr); +} + +extern "C" OBJ_GETTER(Kotlin_NSMutableArrayAsKMutableList_set, KRef thiz, KInt index, KRef element) { + RuntimeAssert(false, "Objective-C interop is disabled"); + RETURN_OBJ(nullptr); +} + +extern "C" void Kotlin_NSEnumeratorAsKIterator_computeNext(KRef thiz) { + RuntimeAssert(false, "Objective-C interop is disabled"); +} + +extern "C" KInt Kotlin_NSSetAsKSet_getSize(KRef thiz) { + RuntimeAssert(false, "Objective-C interop is disabled"); + return -1; +} + +extern "C" KBoolean Kotlin_NSSetAsKSet_contains(KRef thiz, KRef element) { + RuntimeAssert(false, "Objective-C interop is disabled"); + return false; +} + +extern "C" OBJ_GETTER(Kotlin_NSSetAsKSet_getElement, KRef thiz, KRef element) { + RuntimeAssert(false, "Objective-C interop is disabled"); + RETURN_OBJ(nullptr); +} + +extern "C" OBJ_GETTER(Kotlin_NSSetAsKSet_iterator, KRef thiz) { + RuntimeAssert(false, "Objective-C interop is disabled"); + RETURN_OBJ(nullptr); +} + +extern "C" KInt Kotlin_NSDictionaryAsKMap_getSize(KRef thiz) { + RuntimeAssert(false, "Objective-C interop is disabled"); + return -1; +} + +extern "C" KBoolean Kotlin_NSDictionaryAsKMap_containsKey(KRef thiz, KRef key) { + RuntimeAssert(false, "Objective-C interop is disabled"); + return false; +} + +extern "C" KBoolean Kotlin_NSDictionaryAsKMap_containsValue(KRef thiz, KRef value) { + RuntimeAssert(false, "Objective-C interop is disabled"); + return false; +} + +extern "C" OBJ_GETTER(Kotlin_NSDictionaryAsKMap_get, KRef thiz, KRef key) { + RuntimeAssert(false, "Objective-C interop is disabled"); + RETURN_OBJ(nullptr); +} + +extern "C" OBJ_GETTER(Kotlin_NSDictionaryAsKMap_getOrThrowConcurrentModification, KRef thiz, KRef key) { + RuntimeAssert(false, "Objective-C interop is disabled"); + RETURN_OBJ(nullptr); +} + +extern "C" KBoolean Kotlin_NSDictionaryAsKMap_containsEntry(KRef thiz, KRef key, KRef value) { + RuntimeAssert(false, "Objective-C interop is disabled"); + return false; +} + +extern "C" OBJ_GETTER(Kotlin_NSDictionaryAsKMap_keyIterator, KRef thiz) { + RuntimeAssert(false, "Objective-C interop is disabled"); + RETURN_OBJ(nullptr); +} + +extern "C" OBJ_GETTER(Kotlin_NSDictionaryAsKMap_valueIterator, KRef thiz) { + RuntimeAssert(false, "Objective-C interop is disabled"); + RETURN_OBJ(nullptr); +} + +#endif // KONAN_OBJC_INTEROP \ No newline at end of file diff --git a/kotlin-native/runtime/src/main/cpp/ObjCExportCollections.h b/kotlin-native/runtime/src/main/cpp/ObjCExportCollections.h new file mode 100644 index 00000000000..4711b741dab --- /dev/null +++ b/kotlin-native/runtime/src/main/cpp/ObjCExportCollections.h @@ -0,0 +1,59 @@ +/* + * Copyright 2010-2019 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef RUNTIME_OBJCEXPORTCOLLECTIONS_H +#define RUNTIME_OBJCEXPORTCOLLECTIONS_H + +#if KONAN_OBJC_INTEROP + +#import +#import + +#import "Memory.h" +#import "ObjCExport.h" +#import "Runtime.h" + +// Objective-C collections can't store `nil`, and the common convention is to use `NSNull.null` instead. +// Follow the convention when converting Kotlin `null`: + +static inline id refToObjCOrNSNull(KRef obj) { + if (obj == nullptr) { + return NSNull.null; + } else { + return Kotlin_ObjCExport_refToObjC(obj); + } +} + +static inline OBJ_GETTER(refFromObjCOrNSNull, id obj) { + if (obj == NSNull.null) { + RETURN_OBJ(nullptr); + } else { + RETURN_RESULT_OF(Kotlin_ObjCExport_refFromObjC, obj); + } +} + +static inline OBJ_GETTER(invokeAndAssociate, KRef (*func)(KRef* result), id obj) { + Kotlin_initRuntimeIfNeeded(); + + KRef kotlinObj = func(OBJ_RESULT); + + SetAssociatedObject(kotlinObj, obj); + + return kotlinObj; +} + +#endif // KONAN_OBJC_INTEROP +#endif // RUNTIME_OBJCEXPORTCOLLECTIONS_H \ No newline at end of file diff --git a/kotlin-native/runtime/src/main/cpp/ObjCExportCoroutines.mm b/kotlin-native/runtime/src/main/cpp/ObjCExportCoroutines.mm new file mode 100644 index 00000000000..d041ccf78d1 --- /dev/null +++ b/kotlin-native/runtime/src/main/cpp/ObjCExportCoroutines.mm @@ -0,0 +1,68 @@ +/* + * Copyright 2010-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +#if KONAN_OBJC_INTEROP + +#import +#import +#import + +#import "ObjCExport.h" +#import "ObjCExportErrors.h" + +typedef void (^Completion)(id _Nullable, NSError* _Nullable); + +extern "C" void Kotlin_ObjCExport_runCompletionSuccess(KRef completionHolder, KRef result) { + Completion completion = (Completion)GetAssociatedObject(completionHolder); + completion(Kotlin_ObjCExport_refToObjC(result), nullptr); +} + +extern "C" void Kotlin_ObjCExport_runCompletionFailure( + KRef completionHolder, + KRef exception, + const TypeInfo** exceptionTypes +) { + id error = Kotlin_ObjCExport_ExceptionAsNSError(exception, exceptionTypes); + Completion completion = (Completion)GetAssociatedObject(completionHolder); + completion(nullptr, error); +} + +extern "C" OBJ_GETTER(Kotlin_ObjCExport_createContinuationArgumentImpl, + KRef completionHolder, const TypeInfo** exceptionTypes); + +extern "C" OBJ_GETTER(Kotlin_ObjCExport_createContinuationArgument, id completion, const TypeInfo** exceptionTypes) { + if (pthread_main_np() != 1) { + [NSException raise:NSGenericException + format:@"Calling Kotlin suspend functions from Swift/Objective-C is currently supported only on main thread"]; + } + ObjHolder slot; + KRef completionHolder = AllocInstanceWithAssociatedObject(theForeignObjCObjectTypeInfo, + objc_retainBlock(completion), slot.slot()); + + RETURN_RESULT_OF(Kotlin_ObjCExport_createContinuationArgumentImpl, completionHolder, exceptionTypes); +} + +extern "C" void Kotlin_ObjCExport_resumeContinuationSuccess(KRef continuation, KRef result); +extern "C" void Kotlin_ObjCExport_resumeContinuationFailure(KRef continuation, KRef exception); + +extern "C" void Kotlin_ObjCExport_resumeContinuation(KRef continuation, id result, id error) { + ObjHolder holder; + + if (error != nullptr) { + if (result != nullptr) { + [NSException raise:NSGenericException + format:@"Kotlin completion handler is called with both result (%@) and error (%@) specified", + result, error]; + } + + KRef exception = Kotlin_ObjCExport_NSErrorAsException(error, holder.slot()); + Kotlin_ObjCExport_resumeContinuationFailure(continuation, exception); + } else { + KRef kotlinResult = Kotlin_ObjCExport_refFromObjC(result, holder.slot()); + Kotlin_ObjCExport_resumeContinuationSuccess(continuation, kotlinResult); + } +} + +#endif diff --git a/kotlin-native/runtime/src/main/cpp/ObjCExportErrors.h b/kotlin-native/runtime/src/main/cpp/ObjCExportErrors.h new file mode 100644 index 00000000000..6c9a0af42cd --- /dev/null +++ b/kotlin-native/runtime/src/main/cpp/ObjCExportErrors.h @@ -0,0 +1,9 @@ +/* + * Copyright 2010-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +#import "Types.h" + +extern "C" id Kotlin_ObjCExport_ExceptionAsNSError(KRef exception, const TypeInfo** types); +extern "C" OBJ_GETTER(Kotlin_ObjCExport_NSErrorAsException, id error); diff --git a/kotlin-native/runtime/src/main/cpp/ObjCExportErrors.mm b/kotlin-native/runtime/src/main/cpp/ObjCExportErrors.mm new file mode 100644 index 00000000000..d7c0a273500 --- /dev/null +++ b/kotlin-native/runtime/src/main/cpp/ObjCExportErrors.mm @@ -0,0 +1,137 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#if KONAN_OBJC_INTEROP + +#import +#import +#import + +#import "Exceptions.h" +#import "ObjCExport.h" +#import "Porting.h" +#import "Runtime.h" +#import "Utils.h" + +#import "ObjCExportErrors.h" + +extern "C" OBJ_GETTER(Kotlin_Throwable_getMessage, KRef throwable); +extern "C" OBJ_GETTER(Kotlin_ObjCExport_getWrappedError, KRef throwable); + +static void printlnMessage(const char* message) { + konan::consolePrintf("%s\n", message); +} + +extern "C" RUNTIME_NORETURN void Kotlin_ObjCExport_trapOnUndeclaredException(KRef exception) { + printlnMessage("Function doesn't have or inherit @Throws annotation and thus exception isn't propagated " + "from Kotlin to Objective-C/Swift as NSError.\n" + "It is considered unexpected and unhandled instead. Program will be terminated."); + + TerminateWithUnhandledException(exception); +} + +static char kotlinExceptionOriginChar; + +static bool isExceptionOfType(KRef exception, const TypeInfo** types) { + if (types) for (int i = 0; types[i] != nullptr; ++i) { + // TODO: use fast instance check when possible. + if (IsInstance(exception, types[i])) return true; + } + + return false; +} + +extern "C" id Kotlin_ObjCExport_ExceptionAsNSError(KRef exception, const TypeInfo** types) { + ObjHolder errorHolder; + KRef error = Kotlin_ObjCExport_getWrappedError(exception, errorHolder.slot()); + if (error != nullptr) { + // Thrown originally by Swift/Objective-C. + // Not actually a Kotlin exception, so don't check if it matches [types]. + return Kotlin_ObjCExport_refToObjC(error); + } + + if (!isExceptionOfType(exception, types)) { + printlnMessage("Exception doesn't match @Throws-specified class list and thus isn't propagated " + "from Kotlin to Objective-C/Swift as NSError.\n" + "It is considered unexpected and unhandled instead. Program will be terminated."); + TerminateWithUnhandledException(exception); + } + + NSMutableDictionary* userInfo = [[NSMutableDictionary new] autorelease]; + userInfo[@"KotlinException"] = Kotlin_ObjCExport_refToObjC(exception); + userInfo[@"KotlinExceptionOrigin"] = @(&kotlinExceptionOriginChar); // Support for different Kotlin runtimes loaded. + + ObjHolder messageHolder; + KRef message = Kotlin_Throwable_getMessage(exception, messageHolder.slot()); + NSString* description = Kotlin_Interop_CreateNSStringFromKString(message); + if (description != nullptr) { + userInfo[NSLocalizedDescriptionKey] = description; + } + + return [NSError errorWithDomain:@"KotlinException" code:0 userInfo:userInfo]; +} + +extern "C" void Kotlin_ObjCExport_RethrowExceptionAsNSError(KRef exception, id* outError, const TypeInfo** types) { + id error = Kotlin_ObjCExport_ExceptionAsNSError(exception, types); // Also traps on unexpected exception. + if (outError != nullptr) *outError = error; +} + +extern "C" OBJ_GETTER(Kotlin_ObjCExport_NSErrorAsExceptionImpl, KRef message, KRef error); + +extern "C" OBJ_GETTER(Kotlin_ObjCExport_NSErrorAsException, id error) { + NSString* description; + + NSError* e = (NSError*) error; + if (e != nullptr) { + auto userInfo = e.userInfo; + if (userInfo != nullptr) { + id kotlinException = userInfo[@"KotlinException"]; + id kotlinExceptionOrigin = userInfo[@"KotlinExceptionOrigin"]; + if (kotlinException != nullptr && + kotlinExceptionOrigin != nullptr && [kotlinExceptionOrigin isEqual:@(&kotlinExceptionOriginChar)] + ) { + RETURN_RESULT_OF(Kotlin_ObjCExport_refFromObjC, kotlinException); + } + } + description = e.localizedDescription; + } else { + description = nullptr; + } + + ObjHolder messageHolder, errorHolder; + KRef message = Kotlin_Interop_CreateKStringFromNSString(description, messageHolder.slot()); + KRef kotlinError = Kotlin_ObjCExport_refFromObjC(error, errorHolder.slot()); // TODO: a simple opaque wrapper would be enough. + + RETURN_RESULT_OF(Kotlin_ObjCExport_NSErrorAsExceptionImpl, message, kotlinError); +} + +extern "C" void Kotlin_ObjCExport_RethrowNSErrorAsException(id error) { + ObjHolder holder; + KRef exception = Kotlin_ObjCExport_NSErrorAsException(error, holder.slot()); + ThrowException(exception); +} + +@interface NSError (NSErrorKotlinException) +@end; + +@implementation NSError (NSErrorKotlinException) +-(id)kotlinException { + auto userInfo = self.userInfo; + return userInfo == nullptr ? nullptr : userInfo[@"KotlinException"]; +} +@end; + +#endif diff --git a/kotlin-native/runtime/src/main/cpp/ObjCExportExceptionDetails.h b/kotlin-native/runtime/src/main/cpp/ObjCExportExceptionDetails.h new file mode 100644 index 00000000000..36cae5c2890 --- /dev/null +++ b/kotlin-native/runtime/src/main/cpp/ObjCExportExceptionDetails.h @@ -0,0 +1,28 @@ +/* + * Copyright 2010-2020 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "Memory.h" +#import "Types.h" + +#ifdef __cplusplus +extern "C" { +#endif + +OBJ_GETTER(Kotlin_ObjCExport_ExceptionDetails, KRef thiz, KRef exceptionHolder); + +#ifdef __cplusplus +} +#endif diff --git a/kotlin-native/runtime/src/main/cpp/ObjCExportExceptionDetails.mm b/kotlin-native/runtime/src/main/cpp/ObjCExportExceptionDetails.mm new file mode 100644 index 00000000000..dcb5795dea7 --- /dev/null +++ b/kotlin-native/runtime/src/main/cpp/ObjCExportExceptionDetails.mm @@ -0,0 +1,42 @@ +/* + * Copyright 2010-2020 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "Memory.h" +#import "ObjCExportExceptionDetails.h" +#import "ObjCExport.h" + +#if KONAN_OBJC_INTEROP + +#import + +//! TODO: Use not_null signature. +OBJ_GETTER(Kotlin_ObjCExport_ExceptionDetails, KRef /*thiz*/, KRef exceptionHolder) { + if (NSException* exception = (NSException*)Kotlin_ObjCExport_refToObjC(exceptionHolder)) { + RuntimeAssert([exception isKindOfClass:[NSException class]], "Illegal type: NSException expected"); + NSString* ret = [NSString stringWithFormat: @"%@:: %@", exception.name, exception.reason]; + RETURN_RESULT_OF(Kotlin_Interop_CreateKStringFromNSString, ret); + } + + RETURN_OBJ(nullptr); +} + +#else // KONAN_OBJC_INTEROP + +OBJ_GETTER(Kotlin_ObjCExport_ExceptionDetails, KRef /*thiz*/, KRef /*exceptionHolder*/) { + RETURN_OBJ(nullptr); +} + +#endif diff --git a/kotlin-native/runtime/src/main/cpp/ObjCExportInit.h b/kotlin-native/runtime/src/main/cpp/ObjCExportInit.h new file mode 100644 index 00000000000..142f5e104e0 --- /dev/null +++ b/kotlin-native/runtime/src/main/cpp/ObjCExportInit.h @@ -0,0 +1,15 @@ +/* + * Copyright 2010-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +#ifndef RUNTIME_OBJCEXPORTINIT_H +#define RUNTIME_OBJCEXPORTINIT_H + +#if KONAN_OBJC_INTEROP + +extern "C" void Kotlin_ObjCExport_initialize(void); + +#endif // KONAN_OBJC_INTEROP + +#endif // RUNTIME_OBJCEXPORTINIT_H diff --git a/kotlin-native/runtime/src/main/cpp/ObjCExportPrivate.h b/kotlin-native/runtime/src/main/cpp/ObjCExportPrivate.h new file mode 100644 index 00000000000..b68b33b6d00 --- /dev/null +++ b/kotlin-native/runtime/src/main/cpp/ObjCExportPrivate.h @@ -0,0 +1,31 @@ +/* + * Copyright 2010-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +#ifndef RUNTIME_OBJCEXPORTPRIVATE_H +#define RUNTIME_OBJCEXPORTPRIVATE_H + +#if KONAN_OBJC_INTEROP + +#import + +#import "Types.h" +#import "Memory.h" +#import "ObjCExport.h" + +@interface KotlinBase : NSObject ++(instancetype)createWrapper:(ObjHeader*)obj; +@end; + +extern "C" void Kotlin_ObjCExport_initializeClass(Class clazz); +extern "C" const TypeInfo* Kotlin_ObjCExport_getAssociatedTypeInfo(Class clazz); +extern "C" OBJ_GETTER(Kotlin_ObjCExport_convertUnmappedObjCObject, id obj); +extern "C" SEL Kotlin_ObjCExport_toKotlinSelector; +extern "C" SEL Kotlin_ObjCExport_releaseAsAssociatedObjectSelector; + +const TypeInfo* Kotlin_ObjCExport_createTypeInfoWithKotlinFieldsFrom(Class clazz, const TypeInfo* fieldsInfo); + +#endif // KONAN_OBJC_INTEROP + +#endif // RUNTIME_OBJCEXPORTPRIVATE_H diff --git a/kotlin-native/runtime/src/main/cpp/ObjCInterop.h b/kotlin-native/runtime/src/main/cpp/ObjCInterop.h new file mode 100644 index 00000000000..30df929206a --- /dev/null +++ b/kotlin-native/runtime/src/main/cpp/ObjCInterop.h @@ -0,0 +1,15 @@ +/* + * Copyright 2010-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +#ifndef RUNTIME_OBJCINTEROP_H +#define RUNTIME_OBJCINTEROP_H + +#if KONAN_OBJC_INTEROP + +const char* Kotlin_ObjCInterop_getUniquePrefix(); + +#endif // KONAN_OBJC_INTEROP + +#endif // RUNTIME_OBJCINTEROP_H diff --git a/kotlin-native/runtime/src/main/cpp/ObjCInterop.mm b/kotlin-native/runtime/src/main/cpp/ObjCInterop.mm new file mode 100644 index 00000000000..73a48003f5d --- /dev/null +++ b/kotlin-native/runtime/src/main/cpp/ObjCInterop.mm @@ -0,0 +1,374 @@ +/* + * Copyright 2010-2017 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#if KONAN_OBJC_INTEROP + +#import +#import + +#include +#include +#include +#include +#include + +#include "Memory.h" +#include "MemorySharedRefs.hpp" + +#include "Natives.h" +#include "ObjCInterop.h" +#include "ObjCExportPrivate.h" +#include "Types.h" +#include "Utils.h" + +// Replaced in ObjCExportCodeGenerator. +__attribute__((weak)) const char* Kotlin_ObjCInterop_uniquePrefix = nullptr; + +const char* Kotlin_ObjCInterop_getUniquePrefix() { + auto result = Kotlin_ObjCInterop_uniquePrefix; + RuntimeCheck(result != nullptr, "unique prefix is not initialized"); + return result; +} + +extern "C" id objc_msgSendSuper2(struct objc_super *super, SEL op, ...); + +struct KotlinClassData { + const TypeInfo* typeInfo; + int32_t bodyOffset; +}; + +static inline struct KotlinClassData* GetKotlinClassData(Class clazz) { + void* ivars = object_getIndexedIvars(reinterpret_cast(clazz)); + return static_cast(ivars); +} + +namespace { + +BackRefFromAssociatedObject* getBackRef(id obj, KotlinClassData* classData) { + void* body = reinterpret_cast(reinterpret_cast(obj) + classData->bodyOffset); + return reinterpret_cast(body); +} + +BackRefFromAssociatedObject* getBackRef(id obj) { + // TODO: suboptimal; consider specializing methods for each class. + auto* classData = GetKotlinClassData(object_getClass(obj)); + return getBackRef(obj, classData); +} + +OBJ_GETTER(toKotlinImp, id self, SEL _cmd) { + RETURN_OBJ(getBackRef(self)->ref()); +} + +id allocWithZoneImp(Class self, SEL _cmd, void* zone) { + // [super allocWithZone:zone] + struct objc_super s = {(id)self, object_getClass((id)self)}; + auto messenger = reinterpret_cast(objc_msgSendSuper2); + id result = messenger(&s, _cmd, zone); + + auto* classData = GetKotlinClassData(self); // TODO: suboptimal; consider specializing. + auto* typeInfo = classData->typeInfo; + ObjHolder holder; + auto kotlinObj = AllocInstanceWithAssociatedObject(typeInfo, result, holder.slot()); + + getBackRef(result, classData)->initAndAddRef(kotlinObj); + + return result; +} + +id retainImp(id self, SEL _cmd) { + getBackRef(self)->addRef(); + return self; +} + +BOOL _tryRetainImp(id self, SEL _cmd) { + // TODO: [tryAddRef] currently works only on the owner thread for non-shared objects; + // this is a regression for instances of Kotlin subclasses of Obj-C classes: + // loading a reference to such an object from Obj-C weak reference now fails on "wrong" thread + // unless the object is frozen. + try { + return getBackRef(self)->tryAddRef(); + } catch (ExceptionObjHolder& e) { + // TODO: check for IncorrectDereferenceException and possible weak property access + // Cannot use SourceInfo here, because CoreSymbolication framework (CSSymbolOwnerGetSymbolWithAddress) + // fails at recursive retain lock. Similarly, cannot use objc exception here, because its unhandled + // exception handler might fail at recursive retain lock too. + // TODO: Refactor to be more explicit. Instead of relying on an unhandled exception termination + // (and effectively setting a global to alter its behavior), just call an appropriate termination + // function by hand. + DisallowSourceInfo(); + std::terminate(); + } +} + +void releaseImp(id self, SEL _cmd) { + getBackRef(self)->releaseRef(); +} + +void releaseAsAssociatedObjectImp(id self, SEL _cmd) { + // This function is called by the GC. It made a decision to reclaim Kotlin object, and runs + // deallocation hooks at the moment, including deallocation of the "associated object" ([self]) + // using the [super release] call below. + + // The deallocation involves running [self dealloc] which can contain arbitrary code. + // In particular, this code can retain and release [self]. Obj-C and Swift runtimes handle this + // gracefully (unless the object gets accessed after the deallocation of course), but Kotlin doesn't. + // For example, this happens in https://youtrack.jetbrains.com/issue/KT-41811, provoked by + // UIViewController.dealloc (which retains-releases self._view._viewDelegate == self) and UIView.dealloc. + // Generally retaining and releasing Kotlin object that is being deallocated would lead to + // use-after-dispose and double-dispose problems (with unpredictable consequences) or to an assertion failure. + // To workaround this, detach the back ref from the Kotlin object: + getBackRef(self)->detach(); + // So retain/release/etc. on [self] won't affect the Kotlin object, and an attempt to get + // the reference to it (e.g. when calling Kotlin method on [self]) would crash. + // The latter is generally ok, because by the time superclass dealloc gets launched, subclass state + // should already be deinitialized, and Kotlin methods operate on the subclass. + + // [super release] + Class clazz = object_getClass(self); + struct objc_super s = {self, clazz}; + auto messenger = reinterpret_cast(objc_msgSendSuper2); + messenger(&s, @selector(release)); +} + +} + +extern "C" { + +Class Kotlin_Interop_getObjCClass(const char* name); + +static inline void SetKotlinTypeInfo(Class clazz, const TypeInfo* typeInfo) { + GetKotlinClassData(clazz)->typeInfo = typeInfo; +} + +const TypeInfo* GetObjCKotlinTypeInfo(ObjHeader* obj) RUNTIME_NOTHROW; + +RUNTIME_NOTHROW const TypeInfo* GetObjCKotlinTypeInfo(ObjHeader* obj) { + void* objcPtr = obj->GetAssociatedObject(); + RuntimeAssert(objcPtr != nullptr, ""); + Class clazz = object_getClass(reinterpret_cast(objcPtr)); + return GetKotlinClassData(clazz)->typeInfo; +} + + +static void AddNSObjectOverride(bool isClassMethod, Class clazz, SEL selector, void* imp) { + Class nsObjectClass = Kotlin_Interop_getObjCClass("NSObject"); + + Method nsObjectMethod = class_getInstanceMethod( + isClassMethod ? object_getClass((id)nsObjectClass) : nsObjectClass, selector); + RuntimeCheck(nsObjectMethod != nullptr, "NSObject method not found"); + + const char* nsObjectMethodTypeEncoding = method_getTypeEncoding(nsObjectMethod); + RuntimeCheck(nsObjectMethodTypeEncoding != nullptr, "NSObject method has no encoding provided"); + + // TODO: something of the above can be cached. + + BOOL added = class_addMethod( + isClassMethod ? object_getClass((id)clazz) : clazz, selector, (IMP)imp, nsObjectMethodTypeEncoding); + RuntimeCheck(added, "Unable to add method to Objective-C class"); +} + +struct ObjCMethodDescription { + void* (*imp)(void*, void*, ...); + const char* selector; + const char* encoding; +}; + +struct KotlinObjCClassInfo { + const char* name; + int exported; + + const char* superclassName; + const char** protocolNames; + + const struct ObjCMethodDescription* instanceMethods; + int32_t instanceMethodsNum; + + const struct ObjCMethodDescription* classMethods; + int32_t classMethodsNum; + + int32_t* bodyOffset; + + const TypeInfo* typeInfo; + const TypeInfo* metaTypeInfo; + + void** createdClass; +}; + +static void AddMethods(Class clazz, const struct ObjCMethodDescription* methods, int32_t methodsNum) { + for (int32_t i = 0; i < methodsNum; ++i) { + const struct ObjCMethodDescription* method = &methods[i]; + BOOL added = class_addMethod(clazz, sel_registerName(method->selector), (IMP)method->imp, method->encoding); + RuntimeAssert(added == YES, "Unable to add method to Objective-C class"); + } +} + +static SimpleMutex classCreationMutex; +static int anonymousClassNextId = 0; + +static Class allocateClass(const KotlinObjCClassInfo* info) { + Class superclass = Kotlin_Interop_getObjCClass(info->superclassName); + size_t extraBytes = sizeof(struct KotlinClassData); + + if (info->exported) { + RuntimeCheck(info->name != nullptr, "exported Objective-C class must have a name"); + Class result = objc_allocateClassPair(superclass, info->name, extraBytes); + if (result != nullptr) return result; + // Similar to how Objective-C runtime handles this: + fprintf(stderr, "Class %s has multiple implementations. Which one will be used is undefined.\n", info->name); + } + + KStdString className = Kotlin_ObjCInterop_getUniquePrefix(); + + if (info->name != nullptr) { + className += info->name; + } else { + className += "_kobjc"; + } + + int classId = anonymousClassNextId++; + className += std::to_string(classId); + + Class result = objc_allocateClassPair(superclass, className.c_str(), extraBytes); + RuntimeCheck(result != nullptr, "Failed to allocate Objective-C class"); + return result; +} + +void* CreateKotlinObjCClass(const KotlinObjCClassInfo* info) { + LockGuard lockGuard(classCreationMutex); + + void* createdClass = *info->createdClass; + if (createdClass != nullptr) { + return createdClass; + } + + Class newClass = allocateClass(info); + + RuntimeAssert(newClass != nullptr, "Failed to allocate Objective-C class"); + + Class newMetaclass = object_getClass(reinterpret_cast(newClass)); + + for (size_t i = 0;; ++i) { + const char* protocolName = info->protocolNames[i]; + if (protocolName == nullptr) break; + Protocol* proto = objc_getProtocol(protocolName); + if (proto != nullptr) { + BOOL added = class_addProtocol(newClass, proto); + RuntimeAssert(added == YES, "Unable to add protocol to Objective-C class"); + added = class_addProtocol(newMetaclass, proto); + RuntimeAssert(added == YES, "Unable to add protocol to Objective-C metaclass"); + } + } + + AddNSObjectOverride(false, newClass, Kotlin_ObjCExport_toKotlinSelector, (void*)&toKotlinImp); + AddNSObjectOverride(true, newClass, @selector(allocWithZone:), (void*)&allocWithZoneImp); + AddNSObjectOverride(false, newClass, @selector(retain), (void*)&retainImp); + AddNSObjectOverride(false, newClass, @selector(_tryRetain), (void*)&_tryRetainImp); + AddNSObjectOverride(false, newClass, @selector(release), (void*)&releaseImp); + AddNSObjectOverride(false, newClass, Kotlin_ObjCExport_releaseAsAssociatedObjectSelector, + (void*)&releaseAsAssociatedObjectImp); + + AddMethods(newClass, info->instanceMethods, info->instanceMethodsNum); + AddMethods(newMetaclass, info->classMethods, info->classMethodsNum); + + SetKotlinTypeInfo(newClass, Kotlin_ObjCExport_createTypeInfoWithKotlinFieldsFrom(newClass, info->typeInfo)); + + int bodySize = sizeof(BackRefFromAssociatedObject); + char bodyTypeEncoding[16]; + snprintf(bodyTypeEncoding, sizeof(bodyTypeEncoding), "[%dc]", bodySize); + BOOL added = class_addIvar(newClass, "kotlinBody", bodySize, /* log2(align) = */ 3, bodyTypeEncoding); + RuntimeAssert(added == YES, "Unable to add ivar to Objective-C class"); + + objc_registerClassPair(newClass); + + Ivar body = class_getInstanceVariable(newClass, "kotlinBody"); + RuntimeAssert(body != nullptr, "Unable to get ivar added to Objective-C class"); + int32_t offset = (int32_t)ivar_getOffset(body); + GetKotlinClassData(newClass)->bodyOffset = offset; + *info->bodyOffset = offset; + + *info->createdClass = newClass; + return newClass; +} + +void* objc_autoreleasePoolPush(); +void objc_autoreleasePoolPop(void* ptr); +id objc_allocWithZone(Class clazz); +id objc_retain(id ptr); +void objc_release(id ptr); + +void* Kotlin_objc_autoreleasePoolPush() { + return objc_autoreleasePoolPush(); +} + +void Kotlin_objc_autoreleasePoolPop(void* ptr) { + objc_autoreleasePoolPop(ptr); +} + +id Kotlin_objc_allocWithZone(Class clazz) { + return objc_allocWithZone(clazz); +} + +id Kotlin_objc_retain(id ptr) { + return objc_retain(ptr); +} + +void Kotlin_objc_release(id ptr) { + objc_release(ptr); +} + +Class Kotlin_objc_lookUpClass(const char* name) { + return objc_lookUpClass(name); +} + +} // extern "C" + +#else // KONAN_OBJC_INTEROP + +#include "KAssert.h" + +extern "C" { + +void* Kotlin_objc_autoreleasePoolPush() { + RuntimeAssert(false, "Objective-C interop is disabled"); + return nullptr; +} + +void Kotlin_objc_autoreleasePoolPop(void* ptr) { + RuntimeAssert(false, "Objective-C interop is disabled"); +} + +void* Kotlin_objc_allocWithZone(void* clazz) { + RuntimeAssert(false, "Objective-C interop is disabled"); + return nullptr; +} + +void* Kotlin_objc_retain(void* ptr) { + RuntimeAssert(false, "Objective-C interop is disabled"); + return nullptr; +} + +void Kotlin_objc_release(void* ptr) { + RuntimeAssert(false, "Objective-C interop is disabled"); +} + +void* Kotlin_objc_lookUpClass(const char* name) { + RuntimeAssert(false, "Objective-C interop is disabled"); + return nullptr; +} + +} // extern "C" + +#endif // KONAN_OBJC_INTEROP diff --git a/kotlin-native/runtime/src/main/cpp/ObjCInteropUtils.mm b/kotlin-native/runtime/src/main/cpp/ObjCInteropUtils.mm new file mode 100644 index 00000000000..a5c73c7b743 --- /dev/null +++ b/kotlin-native/runtime/src/main/cpp/ObjCInteropUtils.mm @@ -0,0 +1,174 @@ +/* + * Copyright 2010-2017 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "Natives.h" + +#if KONAN_OBJC_INTEROP + +#import +#import +#import +#import +#import "Memory.h" +#import "ObjCInteropUtilsPrivate.h" + +namespace { + Class nsStringClass = nullptr; + + Class getNSStringClass() { + Class result = nsStringClass; + if (result == nullptr) { + // Lookup dynamically to avoid direct reference to Foundation: + result = objc_getClass("NSString"); + RuntimeAssert(result != nullptr, "NSString class not found"); + nsStringClass = result; + } + return result; + } + + // Note: using @"foo" string literals leads to linkage dependency on frameworks. + NSString* cStringToNS(const char* str) { + return [getNSStringClass() stringWithCString:str encoding:NSUTF8StringEncoding]; + } +} + +extern "C" { + +id Kotlin_ObjCExport_CreateNSStringFromKString(ObjHeader* str); + +id Kotlin_Interop_CreateNSStringFromKString(ObjHeader* str) { + // Note: this function is just a bit specialized [Kotlin_Interop_refToObjC]. + if (str == nullptr) { + return nullptr; + } + + if (void* associatedObject = str->GetAssociatedObject()) { + return (id)associatedObject; + } + + return Kotlin_ObjCExport_CreateNSStringFromKString(str); +} + +OBJ_GETTER(Kotlin_Interop_CreateKStringFromNSString, NSString* str) { + if (str == nullptr) { + RETURN_OBJ(nullptr); + } + + CFStringRef immutableCopyOrSameStr = CFStringCreateCopy(nullptr, (CFStringRef)str); + + auto length = CFStringGetLength(immutableCopyOrSameStr); + CFRange range = {0, length}; + ArrayHeader* result = AllocArrayInstance(theStringTypeInfo, length, OBJ_RESULT)->array(); + KChar* rawResult = CharArrayAddressOfElementAt(result, 0); + + CFStringGetCharacters(immutableCopyOrSameStr, range, rawResult); + + result->obj()->SetAssociatedObject((void*)immutableCopyOrSameStr); + + RETURN_OBJ(result->obj()); +} + +// Note: this body is used for init methods with signatures differing from this; +// it is correct on arm64 and x86_64, because the body uses only the first two arguments which are fixed, +// and returns pointers. +id MissingInitImp(id self, SEL _cmd) { + const char* className = object_getClassName(self); + [self release]; // Since init methods receive ownership on the receiver. + + // Lookup dynamically to avoid direct reference to Foundation: + Class nsExceptionClass = objc_getClass("NSException"); + RuntimeAssert(nsExceptionClass != nullptr, "NSException class not found"); + + [nsExceptionClass raise:cStringToNS("Initializer is not implemented") + format:cStringToNS("%s is not implemented in %s"), + sel_getName(_cmd), className]; + + return nullptr; +} + +// Initialized in [ObjCInteropUtilsClasses.mm]. +id (*Kotlin_Interop_createKotlinObjectHolder_ptr)(KRef any) = nullptr; +KRef (*Kotlin_Interop_unwrapKotlinObjectHolder_ptr)(id holder) = nullptr; + +id Kotlin_Interop_createKotlinObjectHolder(KRef any) { + return Kotlin_Interop_createKotlinObjectHolder_ptr(any); +} + +KRef Kotlin_Interop_unwrapKotlinObjectHolder(id holder) { + return Kotlin_Interop_unwrapKotlinObjectHolder_ptr(holder); +} + +KBoolean Kotlin_Interop_DoesObjectConformToProtocol(id obj, void* prot, KBoolean isMeta) { + BOOL objectIsClass = class_isMetaClass(object_getClass(obj)); + if ((isMeta && !objectIsClass) || (!isMeta && objectIsClass)) return false; + // TODO: handle root classes properly. + + return [((id)obj) conformsToProtocol:(Protocol*)prot]; +} + +KBoolean Kotlin_Interop_IsObjectKindOfClass(id obj, void* cls) { + return [((id)obj) isKindOfClass:(Class)cls]; +} + +OBJ_GETTER((*Konan_ObjCInterop_getWeakReference_ptr), KRef ref) = nullptr; +void (*Konan_ObjCInterop_initWeakReference_ptr)(KRef ref, id objcPtr) = nullptr; + +OBJ_GETTER(Konan_ObjCInterop_getWeakReference, KRef ref) { + RETURN_RESULT_OF(Konan_ObjCInterop_getWeakReference_ptr, ref); +} + +void Konan_ObjCInterop_initWeakReference(KRef ref, id objcPtr) { + Konan_ObjCInterop_initWeakReference_ptr(ref, objcPtr); +} + +} // extern "C" + +#else // KONAN_OBJC_INTEROP + +extern "C" { + +void* Kotlin_Interop_CreateNSStringFromKString(const ArrayHeader* str) { + RuntimeAssert(false, "Objective-C interop is disabled"); + return nullptr; +} + +OBJ_GETTER(Kotlin_Interop_CreateKStringFromNSString, void* str) { + RuntimeAssert(false, "Objective-C interop is disabled"); + RETURN_OBJ(nullptr); +} + +void* Kotlin_Interop_createKotlinObjectHolder(KRef any) { + RuntimeAssert(false, "Objective-C interop is disabled"); + return nullptr; +} + +KRef Kotlin_Interop_unwrapKotlinObjectHolder(void* holder) { + RuntimeAssert(false, "Objective-C interop is disabled"); + return nullptr; +} + +OBJ_GETTER(Konan_ObjCInterop_getWeakReference, KRef ref) { + RuntimeAssert(false, "Objective-C interop is disabled"); + RETURN_OBJ(nullptr); +} + +void Konan_ObjCInterop_initWeakReference(KRef ref, void* objcPtr) { + RuntimeAssert(false, "Objective-C interop is disabled"); +} + +} // extern "C" + +#endif // KONAN_OBJC_INTEROP diff --git a/kotlin-native/runtime/src/main/cpp/ObjCInteropUtilsPrivate.h b/kotlin-native/runtime/src/main/cpp/ObjCInteropUtilsPrivate.h new file mode 100644 index 00000000000..e5081fa4e15 --- /dev/null +++ b/kotlin-native/runtime/src/main/cpp/ObjCInteropUtilsPrivate.h @@ -0,0 +1,23 @@ +/* + * Copyright 2010-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +#ifndef RUNTIME_OBJCINTEROPUTILSPRIVATE_H +#define RUNTIME_OBJCINTEROPUTILSPRIVATE_H + +#if KONAN_OBJC_INTEROP + +#import + +#import "Types.h" +#import "Memory.h" + +extern "C" id (*Kotlin_Interop_createKotlinObjectHolder_ptr)(KRef any); +extern "C" KRef (*Kotlin_Interop_unwrapKotlinObjectHolder_ptr)(id holder); +extern "C" OBJ_GETTER((*Konan_ObjCInterop_getWeakReference_ptr), KRef ref); +extern "C" void (*Konan_ObjCInterop_initWeakReference_ptr)(KRef ref, id objcPtr); + +#endif // KONAN_OBJC_INTEROP + +#endif // RUNTIME_OBJCINTEROPUTILSPRIVATE_H \ No newline at end of file diff --git a/kotlin-native/runtime/src/main/cpp/ObjCMMAPI.h b/kotlin-native/runtime/src/main/cpp/ObjCMMAPI.h new file mode 100644 index 00000000000..2e7d00c95c9 --- /dev/null +++ b/kotlin-native/runtime/src/main/cpp/ObjCMMAPI.h @@ -0,0 +1,17 @@ +/* + * Copyright 2010-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +#ifndef RUNTIME_OBJCMMAPI_H +#define RUNTIME_OBJCMMAPI_H + +#include "Common.h" + +#if KONAN_OBJC_INTEROP + +extern "C" ALWAYS_INLINE void Kotlin_ObjCExport_releaseAssociatedObject(void* associatedObject); + +#endif // KONAN_OBJC_INTEROP + +#endif // RUNTIME_OBJCMMAPI_H diff --git a/kotlin-native/runtime/src/main/cpp/Operator.cpp b/kotlin-native/runtime/src/main/cpp/Operator.cpp new file mode 100644 index 00000000000..1fc2673fabf --- /dev/null +++ b/kotlin-native/runtime/src/main/cpp/Operator.cpp @@ -0,0 +1,81 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include + +#include "DoubleConversions.h" +#include "Natives.h" + +#include "Common.h" + +extern "C" { + +//--- Float -------------------------------------------------------------------// + +KInt Kotlin_Float_toInt(KFloat a) { + if (isnan(a)) return 0; + if (a >= (KFloat) INT32_MAX) return INT32_MAX; + if (a <= (KFloat) INT32_MIN) return INT32_MIN; + return a; +} + +KLong Kotlin_Float_toLong(KFloat a) { + if (isnan(a)) return 0; + if (a >= (KFloat) INT64_MAX) return INT64_MAX; + if (a <= (KFloat) INT64_MIN) return INT64_MIN; + return a; +} + +KByte Kotlin_Float_toByte(KFloat a) { return (KByte) Kotlin_Float_toInt(a); } +KShort Kotlin_Float_toShort(KFloat a) { return (KShort) Kotlin_Float_toInt(a); } + +ALWAYS_INLINE KBoolean Kotlin_Float_isNaN(KFloat a) { return isnan(a); } +ALWAYS_INLINE KBoolean Kotlin_Float_isInfinite(KFloat a) { return isinf(a); } +ALWAYS_INLINE KBoolean Kotlin_Float_isFinite(KFloat a) { return isfinite(a); } + +//--- Double ------------------------------------------------------------------// + +KInt Kotlin_Double_toInt(KDouble a) { + if (isnan(a)) return 0; + if (a >= (KDouble) INT32_MAX) return INT32_MAX; + if (a <= (KDouble) INT32_MIN) return INT32_MIN; + return a; +} + +KLong Kotlin_Double_toLong(KDouble a) { + if (isnan(a)) return 0; + if (a >= (KDouble) INT64_MAX) return INT64_MAX; + if (a <= (KDouble) INT64_MIN) return INT64_MIN; + return a; +} + +ALWAYS_INLINE KBoolean Kotlin_Double_isNaN(KDouble a) { return isnan(a); } +ALWAYS_INLINE KBoolean Kotlin_Double_isInfinite(KDouble a) { return isinf(a); } +ALWAYS_INLINE KBoolean Kotlin_Double_isFinite(KDouble a) { return isfinite(a); } + +//--- Bit operations ---------------------------------------------------------// + +ALWAYS_INLINE KInt Kotlin_Int_countOneBits(KInt value) { return __builtin_popcount(value); } +ALWAYS_INLINE KInt Kotlin_Long_countOneBits(KLong value) { return __builtin_popcountll(value); } + +ALWAYS_INLINE KInt Kotlin_Int_countTrailingZeroBits(KInt value) { return __builtin_ctz(value); } +ALWAYS_INLINE KInt Kotlin_Long_countTrailingZeroBits(KLong value) { return __builtin_ctzll(value); } + +ALWAYS_INLINE KInt Kotlin_Int_countLeadingZeroBits(KInt value) { return __builtin_clz(value); } +ALWAYS_INLINE KInt Kotlin_Long_countLeadingZeroBits(KLong value) { return __builtin_clzll(value); } + +} // extern "C" diff --git a/kotlin-native/runtime/src/main/cpp/PointerBits.h b/kotlin-native/runtime/src/main/cpp/PointerBits.h new file mode 100644 index 00000000000..bfd4ef3c537 --- /dev/null +++ b/kotlin-native/runtime/src/main/cpp/PointerBits.h @@ -0,0 +1,33 @@ +/* + * Copyright 2010-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +#ifndef RUNTIME_POINTER_BITS_H +#define RUNTIME_POINTER_BITS_H + +#include + +#include "Common.h" + +template +ALWAYS_INLINE T* setPointerBits(T* ptr, unsigned bits) { + return reinterpret_cast(reinterpret_cast(ptr) | bits); +} + +template +ALWAYS_INLINE T* clearPointerBits(T* ptr, unsigned bits) { + return reinterpret_cast(reinterpret_cast(ptr) & ~static_cast(bits)); +} + +template +ALWAYS_INLINE unsigned getPointerBits(T* ptr, unsigned bits) { + return reinterpret_cast(ptr) & static_cast(bits); +} + +template +ALWAYS_INLINE bool hasPointerBits(T* ptr, unsigned bits) { + return getPointerBits(ptr, bits) != 0; +} + +#endif // RUNTIME_POINTER_BITS_H diff --git a/kotlin-native/runtime/src/main/cpp/Porting.cpp b/kotlin-native/runtime/src/main/cpp/Porting.cpp new file mode 100644 index 00000000000..953c16cecdd --- /dev/null +++ b/kotlin-native/runtime/src/main/cpp/Porting.cpp @@ -0,0 +1,545 @@ +/* + * Copyright 2010-2017 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifdef KONAN_ANDROID +#include +#endif +#include +#include +#include +#include +#include +#if !KONAN_NO_THREADS +#include +#endif +#include +#if KONAN_WINDOWS +#include +#endif + +#include + +#include "Common.h" +#include "Porting.h" +#include "KAssert.h" + +#if KONAN_WASM || KONAN_ZEPHYR +extern "C" RUNTIME_NORETURN void Konan_abort(const char*); +extern "C" RUNTIME_NORETURN void Konan_exit(int32_t status); +#endif +#ifdef KONAN_ZEPHYR +// In Zephyr's Newlib strnlen(3) is not included from string.h by default. +extern "C" size_t strnlen(const char* buffer, size_t maxSize); +#endif + +namespace konan { + +// Console operations. +void consoleInit() { +#if KONAN_WINDOWS + // Note that this code enforces UTF-8 console output, so we may want to rethink + // how we perform console IO, if it turns out, that UTF-16 is better output format. + ::SetConsoleCP(CP_UTF8); + ::SetConsoleOutputCP(CP_UTF8); + // FIXME: should set original CP back during the deinit of the program. + // Otherwise, this codepage remains in the console. +#endif +} + +void consoleWriteUtf8(const void* utf8, uint32_t sizeBytes) { +#ifdef KONAN_ANDROID + // TODO: use sizeBytes! + __android_log_print(ANDROID_LOG_INFO, "Konan_main", "%s", utf8); +#else + ::write(STDOUT_FILENO, utf8, sizeBytes); +#endif +} + +void consoleErrorUtf8(const void* utf8, uint32_t sizeBytes) { +#ifdef KONAN_ANDROID + // TODO: use sizeBytes! + __android_log_print(ANDROID_LOG_ERROR, "Konan_main", "%s", utf8); +#else + ::write(STDERR_FILENO, utf8, sizeBytes); +#endif +} + +#if KONAN_WINDOWS +int getLastErrorMessage(char* message, uint32_t size) { + auto errCode = ::GetLastError(); + if (errCode) { + auto flags = FORMAT_MESSAGE_FROM_SYSTEM; + auto errMsgBufSize = size / 4; + wchar_t errMsgBuffer[errMsgBufSize]; + ::FormatMessageW(flags, NULL, errCode, 0, errMsgBuffer, errMsgBufSize, NULL); + ::WideCharToMultiByte(CP_UTF8, 0, errMsgBuffer, -1, message, size, NULL, NULL); + } + return errCode; +} +#endif + +int32_t consoleReadUtf8(void* utf8, uint32_t maxSizeBytes) { +#ifdef KONAN_ZEPHYR + return 0; +#elif KONAN_WINDOWS + auto length = 0; + void *stdInHandle = ::GetStdHandle(STD_INPUT_HANDLE); + if (::GetFileType(stdInHandle) == FILE_TYPE_CHAR) { + unsigned long bufferRead; + // In UTF-16 there are surrogate pairs that a 2 * 16-bit long (4 bytes). + auto bufferLength = maxSizeBytes / 4 - 1; + wchar_t buffer[bufferLength]; + if (::ReadConsoleW(stdInHandle, buffer, bufferLength, &bufferRead, NULL)) { + length = ::WideCharToMultiByte(CP_UTF8, 0, buffer, bufferRead, (char*) utf8, + maxSizeBytes - 1, NULL, NULL); + if (!length && KonanNeedDebugInfo) { + char msg[512]; + auto errCode = getLastErrorMessage(msg, sizeof(msg)); + consoleErrorf("UTF-16 to UTF-8 conversion error %d: %s", errCode, msg); + } + ((char*) utf8)[length] = 0; + } else if (KonanNeedDebugInfo) { + char msg[512]; + auto errCode = getLastErrorMessage(msg, sizeof(msg)); + consoleErrorf("Console read failure: %d %s", errCode, msg); + } + } else { + length = ::read(STDIN_FILENO, utf8, maxSizeBytes - 1); + } +#else + auto length = ::read(STDIN_FILENO, utf8, maxSizeBytes - 1); +#endif + if (length <= 0) return -1; + char* start = reinterpret_cast(utf8); + char* current = start + length - 1; + bool isTrimming = true; + while (current >= start && isTrimming) { + switch (*current) { + case '\n': + case '\r': + *current = 0; + length--; + break; + default: + isTrimming = false; + } + current--; + } + return length; +} + +#if KONAN_INTERNAL_SNPRINTF +extern "C" int rpl_vsnprintf(char *, size_t, const char *, va_list); +#define vsnprintf_impl rpl_vsnprintf +#else +#define vsnprintf_impl ::vsnprintf +#endif + +void consolePrintf(const char* format, ...) { + char buffer[1024]; + va_list args; + va_start(args, format); + int rv = vsnprintf_impl(buffer, sizeof(buffer), format, args); + if (rv < 0) return; // TODO: this may be too much exotic, but should i try to print itoa(error) and terminate? + if (static_cast(rv) >= sizeof(buffer)) rv = sizeof(buffer) - 1; // TODO: Consider realloc or report truncating. + va_end(args); + consoleWriteUtf8(buffer, rv); +} + +// TODO: Avoid code duplication. +void consoleErrorf(const char* format, ...) { + char buffer[1024]; + va_list args; + va_start(args, format); + int rv = vsnprintf_impl(buffer, sizeof(buffer), format, args); + if (rv < 0) return; // TODO: this may be too much exotic, but should i try to print itoa(error) and terminate? + if (static_cast(rv) >= sizeof(buffer)) rv = sizeof(buffer) - 1; // TODO: Consider realloc or report truncating. + va_end(args); + consoleErrorUtf8(buffer, rv); +} + +void consoleFlush() { + ::fflush(stdout); + ::fflush(stderr); +} + +// Thread execution. +#if !KONAN_NO_THREADS + +pthread_key_t terminationKey; +pthread_once_t terminationKeyOnceControl = PTHREAD_ONCE_INIT; + +typedef void (*destructor_t)(void*); + +struct DestructorRecord { + struct DestructorRecord* next; + destructor_t destructor; + void* destructorParameter; +}; + +static void onThreadExitCallback(void* value) { + DestructorRecord* record = reinterpret_cast(value); + while (record != nullptr) { + record->destructor(record->destructorParameter); + auto next = record->next; + free(record); + record = next; + } + pthread_setspecific(terminationKey, nullptr); +} + +#if KONAN_LINUX +static pthread_key_t dummyKey; +#endif +static void onThreadExitInit() { +#if KONAN_LINUX + // Due to glibc bug we have to create first key as dummy, to avoid + // conflicts with potentially uninitialized dlfcn error key. + // https://code.woboq.org/userspace/glibc/dlfcn/dlerror.c.html#237 + // As one may see, glibc checks value of the key even if it was not inited (and == 0), + // and so data associated with our legit key (== 0 as being the first one) is used. + // Other libc are not affected, as usually == 0 pthread key is impossible. + pthread_key_create(&dummyKey, nullptr); +#endif + pthread_key_create(&terminationKey, onThreadExitCallback); +} + +#endif // !KONAN_NO_THREADS + +void onThreadExit(void (*destructor)(void*), void* destructorParameter) { +#if KONAN_NO_THREADS +#if KONAN_WASM || KONAN_ZEPHYR + // No way to do that. +#else +#error "How to do onThreadExit()?" +#endif +#else // !KONAN_NO_THREADS + // We cannot use pthread_cleanup_push() as it is lexical scope bound. + pthread_once(&terminationKeyOnceControl, onThreadExitInit); + DestructorRecord* destructorRecord = (DestructorRecord*)calloc(1, sizeof(DestructorRecord)); + destructorRecord->destructor = destructor; + destructorRecord->destructorParameter = destructorParameter; + destructorRecord->next = + reinterpret_cast(pthread_getspecific(terminationKey)); + pthread_setspecific(terminationKey, destructorRecord); +#endif // !KONAN_NO_THREADS +} + +// Process execution. +void abort(void) { + ::abort(); +} + +#if KONAN_WASM || KONAN_ZEPHYR +void exit(int32_t status) { + Konan_exit(status); +} +#else +void exit(int32_t status) { + ::exit(status); +} +#endif + +// String/byte operations. +// memcpy/memmove are not here intentionally, as frequently implemented/optimized +// by C compiler. +void* memmem(const void *big, size_t bigLen, const void *little, size_t littleLen) { +#if KONAN_NO_MEMMEM + for (size_t i = 0; i + littleLen <= bigLen; ++i) { + void* pos = ((char*)big) + i; + if (::memcmp(little, pos, littleLen) == 0) return pos; + } + return nullptr; +#else + return ::memmem(big, bigLen, little, littleLen); +#endif + +} + +// The sprintf family. +int snprintf(char* buffer, size_t size, const char* format, ...) { + va_list args; + va_start(args, format); + int rv = vsnprintf_impl(buffer, size, format, args); + va_end(args); + return rv; +} + +size_t strnlen(const char* buffer, size_t maxSize) { + return ::strnlen(buffer, maxSize); +} + +// Memory operations. +#if KONAN_INTERNAL_DLMALLOC +extern "C" void* dlcalloc(size_t, size_t); +extern "C" void dlfree(void*); +#define calloc_impl dlcalloc +#define free_impl dlfree +#define calloc_aligned_impl(count, size, alignment) dlcalloc(count, size) + +#else +extern "C" void* konan_calloc_impl(size_t, size_t); +extern "C" void konan_free_impl(void*); +extern "C" void* konan_calloc_aligned_impl(size_t count, size_t size, size_t alignment); +#define calloc_impl konan_calloc_impl +#define free_impl konan_free_impl +#define calloc_aligned_impl konan_calloc_aligned_impl +#endif + +void* calloc(size_t count, size_t size) { + return calloc_impl(count, size); +} + +void* calloc_aligned(size_t count, size_t size, size_t alignment) { + return calloc_aligned_impl(count, size, alignment); +} + +void free(void* pointer) { + free_impl(pointer); +} + +#if KONAN_INTERNAL_NOW + +#ifdef KONAN_ZEPHYR +void Konan_date_now(uint64_t* arg) { + // TODO: so how will we support time for embedded? + *arg = 0LL; +} +#else +extern "C" void Konan_date_now(uint64_t*); +#endif + +uint64_t getTimeMillis() { + uint64_t now; + Konan_date_now(&now); + return now; +} + +uint64_t getTimeMicros() { + return getTimeMillis() * 1000ULL; +} + +uint64_t getTimeNanos() { + return getTimeMillis() * 1000000ULL; +} + +#else +// Time operations. +using namespace std::chrono; + +// Get steady clock as a source of time +using steady_time_clock = std::conditional::type; + +uint64_t getTimeMillis() { + return duration_cast(steady_time_clock::now().time_since_epoch()).count(); +} + +uint64_t getTimeNanos() { + return duration_cast(steady_time_clock::now().time_since_epoch()).count(); +} + +uint64_t getTimeMicros() { + return duration_cast(steady_time_clock::now().time_since_epoch()).count(); +} +#endif + +#if KONAN_INTERNAL_DLMALLOC +// This function is being called when memory allocator needs more RAM. + +#if KONAN_WASM + +namespace { + +constexpr uint32_t MFAIL = ~(uint32_t)0; +constexpr uint32_t WASM_PAGESIZE_EXPONENT = 16; +constexpr uint32_t WASM_PAGESIZE = 1u << WASM_PAGESIZE_EXPONENT; +constexpr uint32_t WASM_PAGEMASK = WASM_PAGESIZE-1; + +uint32_t pageAlign(int32_t value) { + return (value + WASM_PAGEMASK) & ~ (WASM_PAGEMASK); +} + +uint32_t inBytes(uint32_t pageCount) { + return pageCount << WASM_PAGESIZE_EXPONENT; +} + +uint32_t inPages(uint32_t value) { + return value >> WASM_PAGESIZE_EXPONENT; +} + +extern "C" void Konan_notify_memory_grow(); + +uint32_t memorySize() { + return __builtin_wasm_memory_size(0); +} + +int32_t growMemory(uint32_t delta) { + int32_t oldLength = __builtin_wasm_memory_grow(0, delta); + Konan_notify_memory_grow(); + return oldLength; +} + +} + +void* moreCore(int32_t delta) { + uint32_t top = inBytes(memorySize()); + if (delta > 0) { + if (growMemory(inPages(pageAlign(delta))) == 0) { + return (void *) MFAIL; + } + } else if (delta < 0) { + return (void *) MFAIL; + } + return (void *) top; +} + +// dlmalloc() wants to know the page size. +long getpagesize() { + return WASM_PAGESIZE; +} + +#else +void* moreCore(int size) { + return sbrk(size); +} + +long getpagesize() { + return sysconf(_SC_PAGESIZE); +} +#endif +#endif + +} // namespace konan + +extern "C" { +// TODO: get rid of these. +#if (KONAN_WASM || KONAN_ZEPHYR) + void _ZNKSt3__120__vector_base_commonILb1EE20__throw_length_errorEv(void) { + Konan_abort("TODO: throw_length_error not implemented."); + } + void _ZNKSt3__220__vector_base_commonILb1EE20__throw_length_errorEv(void) { + Konan_abort("TODO: throw_length_error not implemented."); + } + void _ZNKSt3__121__basic_string_commonILb1EE20__throw_length_errorEv(void) { + Konan_abort("TODO: throw_length_error not implemented."); + } + void _ZNKSt3__221__basic_string_commonILb1EE20__throw_length_errorEv(void) { + Konan_abort("TODO: throw_length_error not implemented."); + } + int _ZNSt3__212__next_primeEj(unsigned long n) { + static unsigned long primes[] = { + 11UL, + 101UL, + 1009UL, + 10007UL, + 100003UL, + 1000003UL, + 10000019UL, + 100000007UL, + 1000000007UL + }; + size_t table_length = sizeof(primes)/sizeof(unsigned long); + + if (n > primes[table_length - 1]) konan::abort(); + + unsigned long prime = primes[0]; + for (unsigned long i=0; i< table_length; i++) { + prime = primes[i]; + if (prime >= n) break; + } + return prime; + } + + int _ZNSt3__212__next_primeEm(int n) { + return _ZNSt3__212__next_primeEj(n); + } + + int _ZNSt3__112__next_primeEj(unsigned long n) { + return _ZNSt3__212__next_primeEj(n); + } + void __assert_fail(const char * assertion, const char * file, unsigned int line, const char * function) { + char buf[1024]; + konan::snprintf(buf, sizeof(buf), "%s:%d in %s: runtime assert: %s\n", file, line, function, assertion); + Konan_abort(buf); + } + int* __errno_location() { + static int theErrno = 0; + return &theErrno; + } + + // Some math.h functions. + + double pow(double x, double y) { + return __builtin_pow(x, y); + } +#endif + +#ifdef KONAN_WASM + // Some string.h functions. + void *memcpy(void *dst, const void *src, size_t n) { + for (size_t i = 0; i != n; ++i) + *((char*)dst + i) = *((char*)src + i); + return dst; + } + + void *memmove(void *dst, const void *src, size_t len) { + if (src < dst) { + for (long i = len; i != 0; --i) { + *((char*)dst + i - 1) = *((char*)src + i - 1); + } + } else { + memcpy(dst, src, len); + } + return dst; + } + + int memcmp(const void *s1, const void *s2, size_t n) { + for (size_t i = 0; i != n; ++i) { + if (*((char*)s1 + i) != *((char*)s2 + i)) { + return *((char*)s1 + i) - *((char*)s2 + i); + } + } + return 0; + } + + void *memset(void *b, int c, size_t len) { + for (size_t i = 0; i != len; ++i) { + *((char*)b + i) = c; + } + return b; + } + + size_t strlen(const char *s) { + for (long i = 0;; ++i) { + if (s[i] == 0) return i; + } + } + + size_t strnlen(const char *s, size_t maxlen) { + for (size_t i = 0; i<=maxlen; ++i) { + if (s[i] == 0) return i; + } + return maxlen; + } +#endif + +#ifdef KONAN_ZEPHYR + RUNTIME_USED void Konan_abort(const char*) { + while(1) {} + } +#endif // KONAN_ZEPHYR + +} // extern "C" diff --git a/kotlin-native/runtime/src/main/cpp/Porting.h b/kotlin-native/runtime/src/main/cpp/Porting.h new file mode 100644 index 00000000000..59693a538c6 --- /dev/null +++ b/kotlin-native/runtime/src/main/cpp/Porting.h @@ -0,0 +1,100 @@ +/* + * Copyright 2010-2017 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef RUNTIME_PORTING_H +#define RUNTIME_PORTING_H + +#include +#include + +#include "Common.h" + +namespace konan { + +// Console operations. +void consoleInit(); +void consolePrintf(const char* format, ...); +void consoleErrorf(const char* format, ...); +void consoleWriteUtf8(const void* utf8, uint32_t sizeBytes); +void consoleErrorUtf8(const void* utf8, uint32_t sizeBytes); +// Negative return value denotes that read wasn't successful. +int32_t consoleReadUtf8(void* utf8, uint32_t maxSizeBytes); +void consoleFlush(); + +// Process control. +RUNTIME_NORETURN void abort(void); +RUNTIME_NORETURN void exit(int32_t status); + +// Thread control. +void onThreadExit(void (*destructor)(void*), void* destructorParameter); + +// String/byte operations. +// memcpy/memmove/memcmp are not here intentionally, as frequently implemented/optimized +// by C compiler. +void* memmem(const void *big, size_t bigLen, const void *little, size_t littleLen); +int snprintf(char* buffer, size_t size, const char* format, ...); +size_t strnlen(const char* buffer, size_t maxSize); + + +// These functions should be marked with RUNTIME_USED attribute for wasm target +// because clang replaces these operations with intrinsics that will be +// replaced back to library calls only on codegen step. And there is no stdlib +// for wasm target for now :( +// Otherwise `opt` will see no usages of these definitions and will remove them. +extern "C" { +#ifdef KONAN_WASM + +RUNTIME_USED +double pow(double x, double y); + +RUNTIME_USED +void *memcpy(void *dst, const void *src, size_t n); + +RUNTIME_USED +void *memmove(void *dst, const void *src, size_t len); + +RUNTIME_USED +int memcmp(const void *s1, const void *s2, size_t n); + +RUNTIME_USED +void *memset(void *b, int c, size_t len); + +#endif +} + +// Memory operations. +void* calloc(size_t count, size_t size); +void* calloc_aligned(size_t count, size_t size, size_t alignment); +void free(void* ptr); + +// Time operations. +uint64_t getTimeMillis(); +uint64_t getTimeMicros(); +uint64_t getTimeNanos(); + +#if KONAN_NO_EXCEPTIONS +#define TRY_CATCH(tryAction, actionWithoutExceptions, catchAction) actionWithoutExceptions; +#else +#define TRY_CATCH(tryAction, actionWithoutExceptions, catchAction) \ +do { \ + try { tryAction; } \ + catch(...) { catchAction; } \ +} while(0) +#endif + +} // namespace konan + +#endif // RUNTIME_PORTING_H diff --git a/kotlin-native/runtime/src/main/cpp/PthreadUtils.cpp b/kotlin-native/runtime/src/main/cpp/PthreadUtils.cpp new file mode 100644 index 00000000000..f89181dc9b7 --- /dev/null +++ b/kotlin-native/runtime/src/main/cpp/PthreadUtils.cpp @@ -0,0 +1,42 @@ +/* + * Copyright 2010-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +#include "PthreadUtils.h" + +#include +#include + +namespace { + +constexpr int64_t kNanosecondsInASecond = 1000000000LL; + +} // namespace + +int WaitOnCondVar( + pthread_cond_t* cond, + pthread_mutex_t* mutex, + uint64_t timeoutNanoseconds, + uint64_t* microsecondsPassed) { + struct timeval tvBefore; + // TODO: Error reporting? + gettimeofday(&tvBefore, nullptr); + + struct timespec ts; + const uint64_t nanoseconds = tvBefore.tv_usec * 1000LL + timeoutNanoseconds; + ts.tv_sec = tvBefore.tv_sec + nanoseconds / kNanosecondsInASecond; + ts.tv_nsec = nanoseconds % kNanosecondsInASecond; + auto result = pthread_cond_timedwait(cond, mutex, &ts); + + if (microsecondsPassed) { + struct timeval tvAfter; + // TODO: Error reporting? + gettimeofday(&tvAfter, nullptr); + + *microsecondsPassed = (tvAfter.tv_sec - tvBefore.tv_sec) * 1000000LL + + tvAfter.tv_usec - tvBefore.tv_usec; + } + + return result; +} diff --git a/kotlin-native/runtime/src/main/cpp/PthreadUtils.h b/kotlin-native/runtime/src/main/cpp/PthreadUtils.h new file mode 100644 index 00000000000..2caa0da9447 --- /dev/null +++ b/kotlin-native/runtime/src/main/cpp/PthreadUtils.h @@ -0,0 +1,20 @@ +/* + * Copyright 2010-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +#ifndef RUNTIME_PTHREAD_UTILS_H +#define RUNTIME_PTHREAD_UTILS_H + +#include +#include + +// Releases mutex and waits on cond for timeoutNanoseconds. +// Returns ETIMEDOUT if timeoutNanoseconds has passed. +int WaitOnCondVar( + pthread_cond_t* cond, + pthread_mutex_t* mutex, + uint64_t timeoutNanoseconds, + uint64_t* microsecondsPassed = nullptr); + +#endif // RUNTIME_PTHREAD_UTILS_H diff --git a/kotlin-native/runtime/src/main/cpp/Regex.cpp b/kotlin-native/runtime/src/main/cpp/Regex.cpp new file mode 100644 index 00000000000..b8371d7ed0a --- /dev/null +++ b/kotlin-native/runtime/src/main/cpp/Regex.cpp @@ -0,0 +1,622 @@ +#include +#include "Types.h" +#include "KString.h" +#include "Natives.h" + +namespace { +/* Contains canonical classes (see http://www.unicode.org/Public/4.0-Update/UnicodeData-4.0.0.txt). */ +constexpr KInt canonicalClassesKeys[] = { + 768, 769, 770, 771, 772, 773, 774, 775, 776, 777, 778, 779, 780, 781, 782, 783, 784, 785, 786, 787, 788, 789, 790, + 791, 792, 793, 794, 795, 796, 797, 798, 799, 800, 801, 802, 803, 804, 805, 806, 807, 808, 809, 810, 811, 812, 813, + 814, 815, 816, 817, 818, 819, 820, 821, 822, 823, 824, 825, 826, 827, 828, 829, 830, 831, 832, 833, 834, 835, 836, + 837, 838, 839, 840, 841, 842, 843, 844, 845, 846, 848, 849, 850, 851, 852, 853, 854, 855, 856, 857, 858, 859, 860, + 861, 862, 863, 864, 865, 866, 867, 868, 869, 870, 871, 872, 873, 874, 875, 876, 877, 878, 879, 1155, 1156, 1157, 1158, + 1425, 1426, 1427, 1428, 1429, 1430, 1431, 1432, 1433, 1434, 1435, 1436, 1437, 1438, 1439, 1440, 1441, 1442, 1443, + 1444, 1445, 1446, 1447, 1448, 1449, 1450, 1451, 1452, 1453, 1454, 1455, 1456, 1457, 1458, 1459, 1460, 1461, 1462, + 1463, 1464, 1465, 1467, 1468, 1469, 1471, 1473, 1474, 1476, 1477, 1479, 1552, 1553, 1554, 1555, 1556, 1557, 1611, + 1612, 1613, 1614, 1615, 1616, 1617, 1618, 1619, 1620, 1621, 1622, 1623, 1624, 1625, 1626, 1627, 1628, 1629, 1630, + 1648, 1750, 1751, 1752, 1753, 1754, 1755, 1756, 1759, 1760, 1761, 1762, 1763, 1764, 1767, 1768, 1770, 1771, 1772, + 1773, 1809, 1840, 1841, 1842, 1843, 1844, 1845, 1846, 1847, 1848, 1849, 1850, 1851, 1852, 1853, 1854, 1855, 1856, + 1857, 1858, 1859, 1860, 1861, 1862, 1863, 1864, 1865, 1866, 2364, 2381, 2385, 2386, 2387, 2388, 2492, 2509, 2620, + 2637, 2748, 2765, 2876, 2893, 3021, 3149, 3157, 3158, 3260, 3277, 3405, 3530, 3640, 3641, 3642, 3656, 3657, 3658, + 3659, 3768, 3769, 3784, 3785, 3786, 3787, 3864, 3865, 3893, 3895, 3897, 3953, 3954, 3956, 3962, 3963, 3964, 3965, + 3968, 3970, 3971, 3972, 3974, 3975, 4038, 4151, 4153, 4959, 5908, 5940, 6098, 6109, 6313, 6457, 6458, 6459, 6679, + 6680, 7616, 7617, 7618, 7619, 8400, 8401, 8402, 8403, 8404, 8405, 8406, 8407, 8408, 8409, 8410, 8411, 8412, 8417, + 8421, 8422, 8423, 8424, 8425, 8426, 8427, 12330, 12331, 12332, 12333, 12334, 12335, 12441, 12442, 43014, 64286, 65056, + 65057, 65058, 65059, 68109, 68111, 68152, 68153, 68154, 68159, 119141, 119142, 119143, 119144, 119145, 119149, 119150, + 119151, 119152, 119153, 119154, 119163, 119164, 119165, 119166, 119167, 119168, 119169, 119170, 119173, 119174, + 119175, 119176, 119177, 119178, 119179, 119210, 119211, 119212, 119213, 119362, 119363, 119364, +}; + +constexpr KInt canonicalClassesValues[] = { + 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 232, 220, + 220, 220, 220, 232, 216, 220, 220, 220, 220, 220, 202, 202, 220, 220, 220, 220, 202, 202, 220, 220, 220, 220, 220, + 220, 220, 220, 220, 220, 220, 1, 1, 1, 1, 1, 220, 220, 220, 220, 230, 230, 230, 230, 230, 230, 230, 230, 240, 230, + 220, 220, 220, 230, 230, 230, 220, 220, 230, 230, 230, 220, 220, 220, 220, 230, 232, 220, 220, 230, 233, 234, 234, + 233, 234, 234, 233, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 220, 230, + 230, 230, 230, 220, 230, 230, 230, 222, 220, 230, 230, 230, 230, 230, 230, 220, 220, 220, 220, 220, 220, 230, 230, + 220, 230, 230, 222, 228, 230, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 230, 220, 18, 230, 230, + 230, 230, 230, 230, 27, 28, 29, 30, 31, 32, 33, 34, 230, 230, 220, 220, 230, 230, 230, 230, 230, 220, 230, 230, 35, + 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 220, 230, 230, 230, 220, 230, 230, 220, 36, 230, 220, 230, 230, + 220, 230, 230, 220, 220, 220, 230, 220, 220, 230, 220, 230, 230, 230, 220, 230, 220, 230, 220, 230, 220, 230, 230, 7, + 9, 230, 220, 230, 230, 7, 9, 7, 9, 7, 9, 7, 9, 9, 9, 84, 91, 7, 9, 9, 9, 103, 103, 9, 107, 107, 107, 107, 118, 118, + 122, 122, 122, 122, 220, 220, 220, 220, 216, 129, 130, 132, 130, 130, 130, 130, 130, 230, 230, 9, 230, 230, 220, 7, 9, + 230, 9, 9, 9, 230, 228, 222, 230, 220, 230, 220, 230, 230, 220, 230, 230, 230, 1, 1, 230, 230, 230, 230, 1, 1, 1, 230, + 230, 230, 1, 1, 230, 220, 230, 1, 1, 218, 228, 232, 222, 224, 224, 8, 8, 9, 26, 230, 230, 230, 230, 220, 230, 230, 1, + 220, 9, 216, 216, 1, 1, 1, 226, 216, 216, 216, 216, 216, 220, 220, 220, 220, 220, 220, 220, 220, 230, 230, 230, 230, + 230, 220, 220, 230, 230, 230, 230, 230, 230, 230, +}; + +/* Symbols that are one symbol decompositions (see http://www.unicode.org/Public/4.0-Update/UnicodeData-4.0.0.txt). */ +constexpr KInt singleDecompositions[] = { + 59, 75, 96, 180, 183, 197, 697, 768, 769, 787, 901, 902, 904, 905, 906, 908, 910, 911, 912, 937, 940, 941, 942, 943, + 944, 953, 972, 973, 974, 8194, 8195, 12296, 12297, 13470, 13497, 13499, 13535, 13589, 14062, 14076, 14209, 14383, + 14434, 14460, 14535, 14563, 14620, 14650, 14894, 14956, 15076, 15112, 15129, 15177, 15261, 15384, 15438, 15667, 15766, + 16044, 16056, 16155, 16380, 16392, 16408, 16441, 16454, 16534, 16611, 16687, 16898, 16935, 17056, 17153, 17204, 17241, + 17365, 17369, 17419, 17515, 17707, 17757, 17761, 17771, 17879, 17913, 17973, 18110, 18119, 18837, 18918, 19054, 19062, + 19122, 19251, 19406, 19662, 19693, 19704, 19798, 19981, 20006, 20018, 20024, 20025, 20029, 20033, 20098, 20102, 20142, + 20160, 20172, 20196, 20320, 20352, 20358, 20363, 20398, 20411, 20415, 20482, 20523, 20602, 20633, 20687, 20698, 20711, + 20800, 20805, 20813, 20820, 20836, 20839, 20840, 20841, 20845, 20855, 20864, 20877, 20882, 20885, 20887, 20900, 20908, + 20917, 20919, 20937, 20940, 20956, 20958, 20981, 20995, 20999, 21015, 21033, 21050, 21051, 21062, 21106, 21111, 21129, + 21147, 21155, 21171, 21191, 21193, 21202, 21214, 21220, 21237, 21242, 21253, 21254, 21271, 21311, 21321, 21329, 21338, + 21363, 21365, 21373, 21375, 21443, 21450, 21471, 21477, 21483, 21489, 21510, 21519, 21533, 21560, 21570, 21576, 21608, + 21662, 21666, 21693, 21750, 21776, 21843, 21845, 21859, 21892, 21895, 21913, 21917, 21931, 21939, 21952, 21954, 21986, + 22022, 22097, 22120, 22132, 22265, 22294, 22295, 22411, 22478, 22516, 22541, 22577, 22578, 22592, 22618, 22622, 22696, + 22700, 22707, 22744, 22751, 22766, 22770, 22775, 22790, 22810, 22818, 22852, 22856, 22865, 22868, 22882, 22899, 23000, + 23020, 23067, 23079, 23138, 23142, 23221, 23304, 23336, 23358, 23429, 23491, 23512, 23527, 23534, 23539, 23551, 23558, + 23586, 23615, 23648, 23650, 23652, 23653, 23662, 23693, 23744, 23833, 23875, 23888, 23915, 23918, 23932, 23986, 23994, + 24033, 24034, 24061, 24104, 24125, 24169, 24180, 24230, 24240, 24243, 24246, 24265, 24266, 24274, 24275, 24281, 24300, + 24318, 24324, 24354, 24403, 24418, 24425, 24427, 24459, 24474, 24489, 24493, 24525, 24535, 24565, 24569, 24594, 24604, + 24705, 24724, 24775, 24792, 24801, 24840, 24900, 24904, 24908, 24910, 24928, 24936, 24954, 24974, 24976, 24996, 25007, + 25010, 25054, 25074, 25078, 25088, 25104, 25115, 25134, 25140, 25181, 25265, 25289, 25295, 25299, 25300, 25340, 25342, + 25405, 25424, 25448, 25467, 25475, 25504, 25513, 25540, 25541, 25572, 25628, 25634, 25682, 25705, 25719, 25726, 25754, + 25757, 25796, 25935, 25942, 25964, 25976, 26009, 26053, 26082, 26083, 26131, 26185, 26228, 26248, 26257, 26268, 26292, + 26310, 26356, 26360, 26368, 26391, 26395, 26401, 26446, 26451, 26454, 26462, 26491, 26501, 26519, 26611, 26618, 26647, + 26655, 26706, 26753, 26757, 26766, 26792, 26900, 26946, 27043, 27114, 27138, 27155, 27304, 27347, 27355, 27396, 27425, + 27476, 27506, 27511, 27513, 27551, 27566, 27578, 27579, 27726, 27751, 27784, 27839, 27852, 27853, 27877, 27926, 27931, + 27934, 27956, 27966, 27969, 28009, 28010, 28023, 28024, 28037, 28107, 28122, 28138, 28153, 28186, 28207, 28270, 28316, + 28346, 28359, 28363, 28369, 28379, 28431, 28450, 28451, 28526, 28614, 28651, 28670, 28699, 28702, 28729, 28746, 28784, + 28791, 28797, 28825, 28845, 28872, 28889, 28997, 29001, 29038, 29084, 29134, 29136, 29200, 29211, 29224, 29227, 29237, + 29264, 29282, 29312, 29333, 29359, 29376, 29436, 29482, 29557, 29562, 29575, 29579, 29605, 29618, 29662, 29702, 29705, + 29730, 29767, 29788, 29801, 29809, 29829, 29833, 29848, 29898, 29958, 29988, 30011, 30014, 30041, 30053, 30064, 30178, + 30224, 30237, 30239, 30274, 30313, 30410, 30427, 30439, 30452, 30465, 30494, 30495, 30528, 30538, 30603, 30631, 30798, + 30827, 30860, 30865, 30922, 30924, 30971, 31018, 31036, 31038, 31048, 31049, 31056, 31062, 31069, 31070, 31077, 31103, + 31117, 31118, 31119, 31150, 31178, 31211, 31260, 31296, 31306, 31311, 31361, 31409, 31435, 31470, 31520, 31680, 31686, + 31689, 31806, 31840, 31867, 31890, 31934, 31954, 31958, 31971, 31975, 31976, 32000, 32016, 32034, 32047, 32091, 32099, + 32160, 32190, 32199, 32244, 32258, 32265, 32311, 32321, 32325, 32574, 32626, 32633, 32634, 32645, 32661, 32666, 32701, + 32762, 32769, 32773, 32838, 32864, 32879, 32880, 32894, 32907, 32941, 32946, 33027, 33086, 33240, 33256, 33261, 33281, + 33284, 33391, 33401, 33419, 33425, 33437, 33457, 33459, 33469, 33509, 33510, 33565, 33571, 33590, 33618, 33619, 33635, + 33709, 33725, 33737, 33738, 33740, 33756, 33767, 33775, 33777, 33853, 33865, 33879, 34030, 34033, 34035, 34044, 34070, + 34148, 34253, 34298, 34310, 34322, 34349, 34367, 34384, 34396, 34407, 34409, 34440, 34473, 34530, 34574, 34600, 34667, + 34681, 34694, 34746, 34785, 34817, 34847, 34892, 34912, 34915, 35010, 35023, 35031, 35038, 35041, 35064, 35066, 35088, + 35137, 35172, 35206, 35211, 35222, 35488, 35498, 35519, 35531, 35538, 35542, 35565, 35576, 35582, 35585, 35641, 35672, + 35712, 35722, 35912, 35925, 36011, 36033, 36034, 36040, 36051, 36104, 36123, 36215, 36284, 36299, 36335, 36336, 36554, + 36564, 36646, 36650, 36664, 36667, 36706, 36766, 36784, 36790, 36899, 36920, 36978, 36988, 37007, 37012, 37070, 37105, + 37117, 37137, 37147, 37226, 37273, 37300, 37324, 37327, 37329, 37428, 37432, 37494, 37500, 37591, 37592, 37636, 37706, + 37881, 37909, 38283, 38317, 38327, 38446, 38475, 38477, 38517, 38520, 38524, 38534, 38563, 38584, 38595, 38626, 38627, + 38646, 38647, 38691, 38706, 38728, 38742, 38875, 38880, 38911, 38923, 38936, 38953, 38971, 39006, 39138, 39151, 39164, + 39208, 39209, 39335, 39362, 39409, 39422, 39530, 39698, 39791, 40000, 40023, 40189, 40295, 40372, 40442, 40478, 40575, + 40599, 40607, 40635, 40654, 40697, 40702, 40709, 40719, 40726, 40763, 40771, 40845, 40846, 40860, 131362, 132380, + 132389, 132427, 132666, 133124, 133342, 133676, 133987, 136420, 136872, 136938, 137672, 138008, 138507, 138724, + 138726, 139651, 139679, 140081, 141012, 141380, 141386, 142092, 142321, 143370, 144056, 144223, 144275, 144284, + 144323, 144341, 144493, 145059, 145575, 146061, 146170, 146620, 146718, 147153, 147294, 147342, 148067, 148395, + 149000, 149301, 149524, 150582, 150674, 151457, 151480, 151620, 151794, 151795, 151833, 151859, 152137, 152605, + 153126, 153242, 153285, 153980, 154279, 154539, 154752, 154832, 155526, 156122, 156200, 156231, 156377, 156478, + 156890, 156963, 157096, 157607, 157621, 158524, 158774, 158933, 159083, 159532, 159665, 159954, 160714, 161383, + 161966, 162150, 162984, 163539, 163631, 165330, 165357, 165678, 166906, 167287, 168261, 168415, 168474, 168970, + 169110, 169398, 170800, 172238, 172293, 172558, 172689, 172946, 173568 +}; + +constexpr KInt decompositionKeys[] = { + 192, 193, 194, 195, 196, 197, 199, 200, 201, 202, 203, 204, 205, 206, 207, 209, 210, 211, 212, 213, 214, 217, 218, + 219, 220, 221, 224, 225, 226, 227, 228, 229, 231, 232, 233, 234, 235, 236, 237, 238, 239, 241, 242, 243, 244, 245, + 246, 249, 250, 251, 252, 253, 255, 256, 257, 258, 259, 260, 261, 262, 263, 264, 265, 266, 267, 268, 269, 270, 271, + 274, 275, 276, 277, 278, 279, 280, 281, 282, 283, 284, 285, 286, 287, 288, 289, 290, 291, 292, 293, 296, 297, 298, + 299, 300, 301, 302, 303, 304, 308, 309, 310, 311, 313, 314, 315, 316, 317, 318, 323, 324, 325, 326, 327, 328, 332, + 333, 334, 335, 336, 337, 340, 341, 342, 343, 344, 345, 346, 347, 348, 349, 350, 351, 352, 353, 354, 355, 356, 357, + 360, 361, 362, 363, 364, 365, 366, 367, 368, 369, 370, 371, 372, 373, 374, 375, 376, 377, 378, 379, 380, 381, 382, + 416, 417, 431, 432, 461, 462, 463, 464, 465, 466, 467, 468, 469, 470, 471, 472, 473, 474, 475, 476, 478, 479, 480, + 481, 482, 483, 486, 487, 488, 489, 490, 491, 492, 493, 494, 495, 496, 500, 501, 504, 505, 506, 507, 508, 509, 510, + 511, 512, 513, 514, 515, 516, 517, 518, 519, 520, 521, 522, 523, 524, 525, 526, 527, 528, 529, 530, 531, 532, 533, + 534, 535, 536, 537, 538, 539, 542, 543, 550, 551, 552, 553, 554, 555, 556, 557, 558, 559, 560, 561, 562, 563, 832, + 833, 835, 836, 884, 894, 901, 902, 903, 904, 905, 906, 908, 910, 911, 912, 938, 939, 940, 941, 942, 943, 944, 970, + 971, 972, 973, 974, 979, 980, 1024, 1025, 1027, 1031, 1036, 1037, 1038, 1049, 1081, 1104, 1105, 1107, 1111, 1116, + 1117, 1118, 1142, 1143, 1217, 1218, 1232, 1233, 1234, 1235, 1238, 1239, 1242, 1243, 1244, 1245, 1246, 1247, 1250, + 1251, 1252, 1253, 1254, 1255, 1258, 1259, 1260, 1261, 1262, 1263, 1264, 1265, 1266, 1267, 1268, 1269, 1272, 1273, + 1570, 1571, 1572, 1573, 1574, 1728, 1730, 1747, 2345, 2353, 2356, 2392, 2393, 2394, 2395, 2396, 2397, 2398, 2399, + 2507, 2508, 2524, 2525, 2527, 2611, 2614, 2649, 2650, 2651, 2654, 2888, 2891, 2892, 2908, 2909, 2964, 3018, 3019, + 3020, 3144, 3264, 3271, 3272, 3274, 3275, 3402, 3403, 3404, 3546, 3548, 3549, 3550, 3907, 3917, 3922, 3927, 3932, + 3945, 3955, 3957, 3958, 3960, 3969, 3987, 3997, 4002, 4007, 4012, 4025, 4134, 7680, 7681, 7682, 7683, 7684, 7685, + 7686, 7687, 7688, 7689, 7690, 7691, 7692, 7693, 7694, 7695, 7696, 7697, 7698, 7699, 7700, 7701, 7702, 7703, 7704, + 7705, 7706, 7707, 7708, 7709, 7710, 7711, 7712, 7713, 7714, 7715, 7716, 7717, 7718, 7719, 7720, 7721, 7722, 7723, + 7724, 7725, 7726, 7727, 7728, 7729, 7730, 7731, 7732, 7733, 7734, 7735, 7736, 7737, 7738, 7739, 7740, 7741, 7742, + 7743, 7744, 7745, 7746, 7747, 7748, 7749, 7750, 7751, 7752, 7753, 7754, 7755, 7756, 7757, 7758, 7759, 7760, 7761, + 7762, 7763, 7764, 7765, 7766, 7767, 7768, 7769, 7770, 7771, 7772, 7773, 7774, 7775, 7776, 7777, 7778, 7779, 7780, + 7781, 7782, 7783, 7784, 7785, 7786, 7787, 7788, 7789, 7790, 7791, 7792, 7793, 7794, 7795, 7796, 7797, 7798, 7799, + 7800, 7801, 7802, 7803, 7804, 7805, 7806, 7807, 7808, 7809, 7810, 7811, 7812, 7813, 7814, 7815, 7816, 7817, 7818, + 7819, 7820, 7821, 7822, 7823, 7824, 7825, 7826, 7827, 7828, 7829, 7830, 7831, 7832, 7833, 7835, 7840, 7841, 7842, + 7843, 7844, 7845, 7846, 7847, 7848, 7849, 7850, 7851, 7852, 7853, 7854, 7855, 7856, 7857, 7858, 7859, 7860, 7861, + 7862, 7863, 7864, 7865, 7866, 7867, 7868, 7869, 7870, 7871, 7872, 7873, 7874, 7875, 7876, 7877, 7878, 7879, 7880, + 7881, 7882, 7883, 7884, 7885, 7886, 7887, 7888, 7889, 7890, 7891, 7892, 7893, 7894, 7895, 7896, 7897, 7898, 7899, + 7900, 7901, 7902, 7903, 7904, 7905, 7906, 7907, 7908, 7909, 7910, 7911, 7912, 7913, 7914, 7915, 7916, 7917, 7918, + 7919, 7920, 7921, 7922, 7923, 7924, 7925, 7926, 7927, 7928, 7929, 7936, 7937, 7938, 7939, 7940, 7941, 7942, 7943, + 7944, 7945, 7946, 7947, 7948, 7949, 7950, 7951, 7952, 7953, 7954, 7955, 7956, 7957, 7960, 7961, 7962, 7963, 7964, + 7965, 7968, 7969, 7970, 7971, 7972, 7973, 7974, 7975, 7976, 7977, 7978, 7979, 7980, 7981, 7982, 7983, 7984, 7985, + 7986, 7987, 7988, 7989, 7990, 7991, 7992, 7993, 7994, 7995, 7996, 7997, 7998, 7999, 8000, 8001, 8002, 8003, 8004, + 8005, 8008, 8009, 8010, 8011, 8012, 8013, 8016, 8017, 8018, 8019, 8020, 8021, 8022, 8023, 8025, 8027, 8029, 8031, + 8032, 8033, 8034, 8035, 8036, 8037, 8038, 8039, 8040, 8041, 8042, 8043, 8044, 8045, 8046, 8047, 8048, 8049, 8050, + 8051, 8052, 8053, 8054, 8055, 8056, 8057, 8058, 8059, 8060, 8061, 8064, 8065, 8066, 8067, 8068, 8069, 8070, 8071, + 8072, 8073, 8074, 8075, 8076, 8077, 8078, 8079, 8080, 8081, 8082, 8083, 8084, 8085, 8086, 8087, 8088, 8089, 8090, + 8091, 8092, 8093, 8094, 8095, 8096, 8097, 8098, 8099, 8100, 8101, 8102, 8103, 8104, 8105, 8106, 8107, 8108, 8109, + 8110, 8111, 8112, 8113, 8114, 8115, 8116, 8118, 8119, 8120, 8121, 8122, 8123, 8124, 8126, 8129, 8130, 8131, 8132, + 8134, 8135, 8136, 8137, 8138, 8139, 8140, 8141, 8142, 8143, 8144, 8145, 8146, 8147, 8150, 8151, 8152, 8153, 8154, + 8155, 8157, 8158, 8159, 8160, 8161, 8162, 8163, 8164, 8165, 8166, 8167, 8168, 8169, 8170, 8171, 8172, 8173, 8174, + 8175, 8178, 8179, 8180, 8182, 8183, 8184, 8185, 8186, 8187, 8188, 8189, 8192, 8193, 8486, 8490, 8491, 8602, 8603, + 8622, 8653, 8654, 8655, 8708, 8713, 8716, 8740, 8742, 8769, 8772, 8775, 8777, 8800, 8802, 8813, 8814, 8815, 8816, + 8817, 8820, 8821, 8824, 8825, 8832, 8833, 8836, 8837, 8840, 8841, 8876, 8877, 8878, 8879, 8928, 8929, 8930, 8931, + 8938, 8939, 8940, 8941, 9001, 9002, 10972, 12364, 12366, 12368, 12370, 12372, 12374, 12376, 12378, 12380, 12382, + 12384, 12386, 12389, 12391, 12393, 12400, 12401, 12403, 12404, 12406, 12407, 12409, 12410, 12412, 12413, 12436, 12446, + 12460, 12462, 12464, 12466, 12468, 12470, 12472, 12474, 12476, 12478, 12480, 12482, 12485, 12487, 12489, 12496, 12497, + 12499, 12500, 12502, 12503, 12505, 12506, 12508, 12509, 12532, 12535, 12536, 12537, 12538, 12542, 63744, 63745, 63746, + 63747, 63748, 63749, 63750, 63751, 63752, 63753, 63754, 63755, 63756, 63757, 63758, 63759, 63760, 63761, 63762, 63763, + 63764, 63765, 63766, 63767, 63768, 63769, 63770, 63771, 63772, 63773, 63774, 63775, 63776, 63777, 63778, 63779, 63780, + 63781, 63782, 63783, 63784, 63785, 63786, 63787, 63788, 63789, 63790, 63791, 63792, 63793, 63794, 63795, 63796, 63797, + 63798, 63799, 63800, 63801, 63802, 63803, 63804, 63805, 63806, 63807, 63808, 63809, 63810, 63811, 63812, 63813, 63814, + 63815, 63816, 63817, 63818, 63819, 63820, 63821, 63822, 63823, 63824, 63825, 63826, 63827, 63828, 63829, 63830, 63831, + 63832, 63833, 63834, 63835, 63836, 63837, 63838, 63839, 63840, 63841, 63842, 63843, 63844, 63845, 63846, 63847, 63848, + 63849, 63850, 63851, 63852, 63853, 63854, 63855, 63856, 63857, 63858, 63859, 63860, 63861, 63862, 63863, 63864, 63865, + 63866, 63867, 63868, 63869, 63870, 63871, 63872, 63873, 63874, 63875, 63876, 63877, 63878, 63879, 63880, 63881, 63882, + 63883, 63884, 63885, 63886, 63887, 63888, 63889, 63890, 63891, 63892, 63893, 63894, 63895, 63896, 63897, 63898, 63899, + 63900, 63901, 63902, 63903, 63904, 63905, 63906, 63907, 63908, 63909, 63910, 63911, 63912, 63913, 63914, 63915, 63916, + 63917, 63918, 63919, 63920, 63921, 63922, 63923, 63924, 63925, 63926, 63927, 63928, 63929, 63930, 63931, 63932, 63933, + 63934, 63935, 63936, 63937, 63938, 63939, 63940, 63941, 63942, 63943, 63944, 63945, 63946, 63947, 63948, 63949, 63950, + 63951, 63952, 63953, 63954, 63955, 63956, 63957, 63958, 63959, 63960, 63961, 63962, 63963, 63964, 63965, 63966, 63967, + 63968, 63969, 63970, 63971, 63972, 63973, 63974, 63975, 63976, 63977, 63978, 63979, 63980, 63981, 63982, 63983, 63984, + 63985, 63986, 63987, 63988, 63989, 63990, 63991, 63992, 63993, 63994, 63995, 63996, 63997, 63998, 63999, 64000, 64001, + 64002, 64003, 64004, 64005, 64006, 64007, 64008, 64009, 64010, 64011, 64012, 64013, 64016, 64018, 64021, 64022, 64023, + 64024, 64025, 64026, 64027, 64028, 64029, 64030, 64032, 64034, 64037, 64038, 64042, 64043, 64044, 64045, 64048, 64049, + 64050, 64051, 64052, 64053, 64054, 64055, 64056, 64057, 64058, 64059, 64060, 64061, 64062, 64063, 64064, 64065, 64066, + 64067, 64068, 64069, 64070, 64071, 64072, 64073, 64074, 64075, 64076, 64077, 64078, 64079, 64080, 64081, 64082, 64083, + 64084, 64085, 64086, 64087, 64088, 64089, 64090, 64091, 64092, 64093, 64094, 64095, 64096, 64097, 64098, 64099, 64100, + 64101, 64102, 64103, 64104, 64105, 64106, 64112, 64113, 64114, 64115, 64116, 64117, 64118, 64119, 64120, 64121, 64122, + 64123, 64124, 64125, 64126, 64127, 64128, 64129, 64130, 64131, 64132, 64133, 64134, 64135, 64136, 64137, 64138, 64139, + 64140, 64141, 64142, 64143, 64144, 64145, 64146, 64147, 64148, 64149, 64150, 64151, 64152, 64153, 64154, 64155, 64156, + 64157, 64158, 64159, 64160, 64161, 64162, 64163, 64164, 64165, 64166, 64167, 64168, 64169, 64170, 64171, 64172, 64173, + 64174, 64175, 64176, 64177, 64178, 64179, 64180, 64181, 64182, 64183, 64184, 64185, 64186, 64187, 64188, 64189, 64190, + 64191, 64192, 64193, 64194, 64195, 64196, 64197, 64198, 64199, 64200, 64201, 64202, 64203, 64204, 64205, 64206, 64207, + 64208, 64209, 64210, 64211, 64212, 64213, 64214, 64215, 64216, 64217, 64285, 64287, 64298, 64299, 64300, 64301, 64302, + 64303, 64304, 64305, 64306, 64307, 64308, 64309, 64310, 64312, 64313, 64314, 64315, 64316, 64318, 64320, 64321, 64323, + 64324, 64326, 64327, 64328, 64329, 64330, 64331, 64332, 64333, 64334, 119134, 119135, 119136, 119137, 119138, 119139, + 119140, 119227, 119228, 119229, 119230, 119231, 119232, 194560, 194561, 194562, 194563, 194564, 194565, 194566, + 194567, 194568, 194569, 194570, 194571, 194572, 194573, 194574, 194575, 194576, 194577, 194578, 194579, 194580, + 194581, 194582, 194583, 194584, 194585, 194586, 194587, 194588, 194589, 194590, 194591, 194592, 194593, 194594, + 194595, 194596, 194597, 194598, 194599, 194600, 194601, 194602, 194603, 194604, 194605, 194606, 194607, 194608, + 194609, 194610, 194611, 194612, 194613, 194614, 194615, 194616, 194617, 194618, 194619, 194620, 194621, 194622, + 194623, 194624, 194625, 194626, 194627, 194628, 194629, 194630, 194631, 194632, 194633, 194634, 194635, 194636, + 194637, 194638, 194639, 194640, 194641, 194642, 194643, 194644, 194645, 194646, 194647, 194648, 194649, 194650, + 194651, 194652, 194653, 194654, 194655, 194656, 194657, 194658, 194659, 194660, 194661, 194662, 194663, 194664, + 194665, 194666, 194667, 194668, 194669, 194670, 194671, 194672, 194673, 194674, 194675, 194676, 194677, 194678, + 194679, 194680, 194681, 194682, 194683, 194684, 194685, 194686, 194687, 194688, 194689, 194690, 194691, 194692, + 194693, 194694, 194695, 194696, 194697, 194698, 194699, 194700, 194701, 194702, 194703, 194704, 194705, 194706, + 194707, 194708, 194709, 194710, 194711, 194712, 194713, 194714, 194715, 194716, 194717, 194718, 194719, 194720, + 194721, 194722, 194723, 194724, 194725, 194726, 194727, 194728, 194729, 194730, 194731, 194732, 194733, 194734, + 194735, 194736, 194737, 194738, 194739, 194740, 194741, 194742, 194743, 194744, 194745, 194746, 194747, 194748, + 194749, 194750, 194751, 194752, 194753, 194754, 194755, 194756, 194757, 194758, 194759, 194760, 194761, 194762, + 194763, 194764, 194765, 194766, 194767, 194768, 194769, 194770, 194771, 194772, 194773, 194774, 194775, 194776, + 194777, 194778, 194779, 194780, 194781, 194782, 194783, 194784, 194785, 194786, 194787, 194788, 194789, 194790, + 194791, 194792, 194793, 194794, 194795, 194796, 194797, 194798, 194799, 194800, 194801, 194802, 194803, 194804, + 194805, 194806, 194807, 194808, 194809, 194810, 194811, 194812, 194813, 194814, 194815, 194816, 194817, 194818, + 194819, 194820, 194821, 194822, 194823, 194824, 194825, 194826, 194827, 194828, 194829, 194830, 194831, 194832, + 194833, 194834, 194835, 194836, 194837, 194838, 194839, 194840, 194841, 194842, 194843, 194844, 194845, 194846, + 194847, 194848, 194849, 194850, 194851, 194852, 194853, 194854, 194855, 194856, 194857, 194858, 194859, 194860, + 194861, 194862, 194863, 194864, 194865, 194866, 194867, 194868, 194869, 194870, 194871, 194872, 194873, 194874, + 194875, 194876, 194877, 194878, 194879, 194880, 194881, 194882, 194883, 194884, 194885, 194886, 194887, 194888, + 194889, 194890, 194891, 194892, 194893, 194894, 194895, 194896, 194897, 194898, 194899, 194900, 194901, 194902, + 194903, 194904, 194905, 194906, 194907, 194908, 194909, 194910, 194911, 194912, 194913, 194914, 194915, 194916, + 194917, 194918, 194919, 194920, 194921, 194922, 194923, 194924, 194925, 194926, 194927, 194928, 194929, 194930, + 194931, 194932, 194933, 194934, 194935, 194936, 194937, 194938, 194939, 194940, 194941, 194942, 194943, 194944, + 194945, 194946, 194947, 194948, 194949, 194950, 194951, 194952, 194953, 194954, 194955, 194956, 194957, 194958, + 194959, 194960, 194961, 194962, 194963, 194964, 194965, 194966, 194967, 194968, 194969, 194970, 194971, 194972, + 194973, 194974, 194975, 194976, 194977, 194978, 194979, 194980, 194981, 194982, 194983, 194984, 194985, 194986, + 194987, 194988, 194989, 194990, 194991, 194992, 194993, 194994, 194995, 194996, 194997, 194998, 194999, 195000, + 195001, 195002, 195003, 195004, 195005, 195006, 195007, 195008, 195009, 195010, 195011, 195012, 195013, 195014, + 195015, 195016, 195017, 195018, 195019, 195020, 195021, 195022, 195023, 195024, 195025, 195026, 195027, 195028, + 195029, 195030, 195031, 195032, 195033, 195034, 195035, 195036, 195037, 195038, 195039, 195040, 195041, 195042, + 195043, 195044, 195045, 195046, 195047, 195048, 195049, 195050, 195051, 195052, 195053, 195054, 195055, 195056, + 195057, 195058, 195059, 195060, 195061, 195062, 195063, 195064, 195065, 195066, 195067, 195068, 195069, 195070, + 195071, 195072, 195073, 195074, 195075, 195076, 195077, 195078, 195079, 195080, 195081, 195082, 195083, 195084, + 195085, 195086, 195087, 195088, 195089, 195090, 195091, 195092, 195093, 195094, 195095, 195096, 195097, 195098, + 195099, 195100, 195101 +}; + +struct Decomposition { + const KInt array[4]; + const KByte length; +}; + +constexpr Decomposition decompositionValues[] = { + {{65, 768}, 2}, {{65, 769}, 2}, {{65, 770}, 2}, {{65, 771}, 2}, {{65, 776}, 2}, {{65, 778}, 2}, {{67, 807}, 2}, + {{69, 768}, 2}, {{69, 769}, 2}, {{69, 770}, 2}, {{69, 776}, 2}, {{73, 768}, 2}, {{73, 769}, 2}, {{73, 770}, 2}, + {{73, 776}, 2}, {{78, 771}, 2}, {{79, 768}, 2}, {{79, 769}, 2}, {{79, 770}, 2}, {{79, 771}, 2}, {{79, 776}, 2}, + {{85, 768}, 2}, {{85, 769}, 2}, {{85, 770}, 2}, {{85, 776}, 2}, {{89, 769}, 2}, {{97, 768}, 2}, {{97, 769}, 2}, + {{97, 770}, 2}, {{97, 771}, 2}, {{97, 776}, 2}, {{97, 778}, 2}, {{99, 807}, 2}, {{101, 768}, 2}, {{101, 769}, 2}, + {{101, 770}, 2}, {{101, 776}, 2}, {{105, 768}, 2}, {{105, 769}, 2}, {{105, 770}, 2}, {{105, 776}, 2}, {{110, 771}, 2}, + {{111, 768}, 2}, {{111, 769}, 2}, {{111, 770}, 2}, {{111, 771}, 2}, {{111, 776}, 2}, {{117, 768}, 2}, {{117, 769}, 2}, + {{117, 770}, 2}, {{117, 776}, 2}, {{121, 769}, 2}, {{121, 776}, 2}, {{65, 772}, 2}, {{97, 772}, 2}, {{65, 774}, 2}, + {{97, 774}, 2}, {{65, 808}, 2}, {{97, 808}, 2}, {{67, 769}, 2}, {{99, 769}, 2}, {{67, 770}, 2}, {{99, 770}, 2}, + {{67, 775}, 2}, {{99, 775}, 2}, {{67, 780}, 2}, {{99, 780}, 2}, {{68, 780}, 2}, {{100, 780}, 2}, {{69, 772}, 2}, + {{101, 772}, 2}, {{69, 774}, 2}, {{101, 774}, 2}, {{69, 775}, 2}, {{101, 775}, 2}, {{69, 808}, 2}, {{101, 808}, 2}, + {{69, 780}, 2}, {{101, 780}, 2}, {{71, 770}, 2}, {{103, 770}, 2}, {{71, 774}, 2}, {{103, 774}, 2}, {{71, 775}, 2}, + {{103, 775}, 2}, {{71, 807}, 2}, {{103, 807}, 2}, {{72, 770}, 2}, {{104, 770}, 2}, {{73, 771}, 2}, {{105, 771}, 2}, + {{73, 772}, 2}, {{105, 772}, 2}, {{73, 774}, 2}, {{105, 774}, 2}, {{73, 808}, 2}, {{105, 808}, 2}, {{73, 775}, 2}, + {{74, 770}, 2}, {{106, 770}, 2}, {{75, 807}, 2}, {{107, 807}, 2}, {{76, 769}, 2}, {{108, 769}, 2}, {{76, 807}, 2}, + {{108, 807}, 2}, {{76, 780}, 2}, {{108, 780}, 2}, {{78, 769}, 2}, {{110, 769}, 2}, {{78, 807}, 2}, {{110, 807}, 2}, + {{78, 780}, 2}, {{110, 780}, 2}, {{79, 772}, 2}, {{111, 772}, 2}, {{79, 774}, 2}, {{111, 774}, 2}, {{79, 779}, 2}, + {{111, 779}, 2}, {{82, 769}, 2}, {{114, 769}, 2}, {{82, 807}, 2}, {{114, 807}, 2}, {{82, 780}, 2}, {{114, 780}, 2}, + {{83, 769}, 2}, {{115, 769}, 2}, {{83, 770}, 2}, {{115, 770}, 2}, {{83, 807}, 2}, {{115, 807}, 2}, {{83, 780}, 2}, + {{115, 780}, 2}, {{84, 807}, 2}, {{116, 807}, 2}, {{84, 780}, 2}, {{116, 780}, 2}, {{85, 771}, 2}, {{117, 771}, 2}, + {{85, 772}, 2}, {{117, 772}, 2}, {{85, 774}, 2}, {{117, 774}, 2}, {{85, 778}, 2}, {{117, 778}, 2}, {{85, 779}, 2}, + {{117, 779}, 2}, {{85, 808}, 2}, {{117, 808}, 2}, {{87, 770}, 2}, {{119, 770}, 2}, {{89, 770}, 2}, {{121, 770}, 2}, + {{89, 776}, 2}, {{90, 769}, 2}, {{122, 769}, 2}, {{90, 775}, 2}, {{122, 775}, 2}, {{90, 780}, 2}, {{122, 780}, 2}, + {{79, 795}, 2}, {{111, 795}, 2}, {{85, 795}, 2}, {{117, 795}, 2}, {{65, 780}, 2}, {{97, 780}, 2}, {{73, 780}, 2}, + {{105, 780}, 2}, {{79, 780}, 2}, {{111, 780}, 2}, {{85, 780}, 2}, {{117, 780}, 2}, {{85, 776, 772}, 3}, + {{117, 776, 772}, 3}, {{85, 776, 769}, 3}, {{117, 776, 769}, 3}, {{85, 776, 780}, 3}, {{117, 776, 780}, 3}, + {{85, 776, 768}, 3}, {{117, 776, 768}, 3}, {{65, 776, 772}, 3}, {{97, 776, 772}, 3}, {{65, 775, 772}, 3}, + {{97, 775, 772}, 3}, {{198, 772}, 2}, {{230, 772}, 2}, {{71, 780}, 2}, {{103, 780}, 2}, {{75, 780}, 2}, + {{107, 780}, 2}, {{79, 808}, 2}, {{111, 808}, 2}, {{79, 808, 772}, 3}, {{111, 808, 772}, 3}, {{439, 780}, 2}, + {{658, 780}, 2}, {{106, 780}, 2}, {{71, 769}, 2}, {{103, 769}, 2}, {{78, 768}, 2}, {{110, 768}, 2}, + {{65, 778, 769}, 3}, {{97, 778, 769}, 3}, {{198, 769}, 2}, {{230, 769}, 2}, {{216, 769}, 2}, {{248, 769}, 2}, + {{65, 783}, 2}, {{97, 783}, 2}, {{65, 785}, 2}, {{97, 785}, 2}, {{69, 783}, 2}, {{101, 783}, 2}, {{69, 785}, 2}, + {{101, 785}, 2}, {{73, 783}, 2}, {{105, 783}, 2}, {{73, 785}, 2}, {{105, 785}, 2}, {{79, 783}, 2}, {{111, 783}, 2}, + {{79, 785}, 2}, {{111, 785}, 2}, {{82, 783}, 2}, {{114, 783}, 2}, {{82, 785}, 2}, {{114, 785}, 2}, {{85, 783}, 2}, + {{117, 783}, 2}, {{85, 785}, 2}, {{117, 785}, 2}, {{83, 806}, 2}, {{115, 806}, 2}, {{84, 806}, 2}, {{116, 806}, 2}, + {{72, 780}, 2}, {{104, 780}, 2}, {{65, 775}, 2}, {{97, 775}, 2}, {{69, 807}, 2}, {{101, 807}, 2}, {{79, 776, 772}, 3}, + {{111, 776, 772}, 3}, {{79, 771, 772}, 3}, {{111, 771, 772}, 3}, {{79, 775}, 2}, {{111, 775}, 2}, {{79, 775, 772}, 3}, + {{111, 775, 772}, 3}, {{89, 772}, 2}, {{121, 772}, 2}, {{768}, 1}, {{769}, 1}, {{787}, 1}, {{776, 769}, 2}, + {{697}, 1}, {{59}, 1}, {{168, 769}, 2}, {{913, 769}, 2}, {{183}, 1}, {{917, 769}, 2}, {{919, 769}, 2}, + {{921, 769}, 2}, {{927, 769}, 2}, {{933, 769}, 2}, {{937, 769}, 2}, {{953, 776, 769}, 3}, {{921, 776}, 2}, + {{933, 776}, 2}, {{945, 769}, 2}, {{949, 769}, 2}, {{951, 769}, 2}, {{953, 769}, 2}, {{965, 776, 769}, 3}, + {{953, 776}, 2}, {{965, 776}, 2}, {{959, 769}, 2}, {{965, 769}, 2}, {{969, 769}, 2}, {{978, 769}, 2}, {{978, 776}, 2}, + {{1045, 768}, 2}, {{1045, 776}, 2}, {{1043, 769}, 2}, {{1030, 776}, 2}, {{1050, 769}, 2}, {{1048, 768}, 2}, + {{1059, 774}, 2}, {{1048, 774}, 2}, {{1080, 774}, 2}, {{1077, 768}, 2}, {{1077, 776}, 2}, {{1075, 769}, 2}, + {{1110, 776}, 2}, {{1082, 769}, 2}, {{1080, 768}, 2}, {{1091, 774}, 2}, {{1140, 783}, 2}, {{1141, 783}, 2}, + {{1046, 774}, 2}, {{1078, 774}, 2}, {{1040, 774}, 2}, {{1072, 774}, 2}, {{1040, 776}, 2}, {{1072, 776}, 2}, + {{1045, 774}, 2}, {{1077, 774}, 2}, {{1240, 776}, 2}, {{1241, 776}, 2}, {{1046, 776}, 2}, {{1078, 776}, 2}, + {{1047, 776}, 2}, {{1079, 776}, 2}, {{1048, 772}, 2}, {{1080, 772}, 2}, {{1048, 776}, 2}, {{1080, 776}, 2}, + {{1054, 776}, 2}, {{1086, 776}, 2}, {{1256, 776}, 2}, {{1257, 776}, 2}, {{1069, 776}, 2}, {{1101, 776}, 2}, + {{1059, 772}, 2}, {{1091, 772}, 2}, {{1059, 776}, 2}, {{1091, 776}, 2}, {{1059, 779}, 2}, {{1091, 779}, 2}, + {{1063, 776}, 2}, {{1095, 776}, 2}, {{1067, 776}, 2}, {{1099, 776}, 2}, {{1575, 1619}, 2}, {{1575, 1620}, 2}, + {{1608, 1620}, 2}, {{1575, 1621}, 2}, {{1610, 1620}, 2}, {{1749, 1620}, 2}, {{1729, 1620}, 2}, {{1746, 1620}, 2}, + {{2344, 2364}, 2}, {{2352, 2364}, 2}, {{2355, 2364}, 2}, {{2325, 2364}, 2}, {{2326, 2364}, 2}, {{2327, 2364}, 2}, + {{2332, 2364}, 2}, {{2337, 2364}, 2}, {{2338, 2364}, 2}, {{2347, 2364}, 2}, {{2351, 2364}, 2}, {{2503, 2494}, 2}, + {{2503, 2519}, 2}, {{2465, 2492}, 2}, {{2466, 2492}, 2}, {{2479, 2492}, 2}, {{2610, 2620}, 2}, {{2616, 2620}, 2}, + {{2582, 2620}, 2}, {{2583, 2620}, 2}, {{2588, 2620}, 2}, {{2603, 2620}, 2}, {{2887, 2902}, 2}, {{2887, 2878}, 2}, + {{2887, 2903}, 2}, {{2849, 2876}, 2}, {{2850, 2876}, 2}, {{2962, 3031}, 2}, {{3014, 3006}, 2}, {{3015, 3006}, 2}, + {{3014, 3031}, 2}, {{3142, 3158}, 2}, {{3263, 3285}, 2}, {{3270, 3285}, 2}, {{3270, 3286}, 2}, {{3270, 3266}, 2}, + {{3270, 3266, 3285}, 3}, {{3398, 3390}, 2}, {{3399, 3390}, 2}, {{3398, 3415}, 2}, {{3545, 3530}, 2}, + {{3545, 3535}, 2}, {{3545, 3535, 3530}, 3}, {{3545, 3551}, 2}, {{3906, 4023}, 2}, {{3916, 4023}, 2}, + {{3921, 4023}, 2}, {{3926, 4023}, 2}, {{3931, 4023}, 2}, {{3904, 4021}, 2}, {{3953, 3954}, 2}, {{3953, 3956}, 2}, + {{4018, 3968}, 2}, {{4019, 3968}, 2}, {{3953, 3968}, 2}, {{3986, 4023}, 2}, {{3996, 4023}, 2}, {{4001, 4023}, 2}, + {{4006, 4023}, 2}, {{4011, 4023}, 2}, {{3984, 4021}, 2}, {{4133, 4142}, 2}, {{65, 805}, 2}, {{97, 805}, 2}, + {{66, 775}, 2}, {{98, 775}, 2}, {{66, 803}, 2}, {{98, 803}, 2}, {{66, 817}, 2}, {{98, 817}, 2}, {{67, 807, 769}, 3}, + {{99, 807, 769}, 3}, {{68, 775}, 2}, {{100, 775}, 2}, {{68, 803}, 2}, {{100, 803}, 2}, {{68, 817}, 2}, + {{100, 817}, 2}, {{68, 807}, 2}, {{100, 807}, 2}, {{68, 813}, 2}, {{100, 813}, 2}, {{69, 772, 768}, 3}, + {{101, 772, 768}, 3}, {{69, 772, 769}, 3}, {{101, 772, 769}, 3}, {{69, 813}, 2}, {{101, 813}, 2}, {{69, 816}, 2}, + {{101, 816}, 2}, {{69, 807, 774}, 3}, {{101, 807, 774}, 3}, {{70, 775}, 2}, {{102, 775}, 2}, {{71, 772}, 2}, + {{103, 772}, 2}, {{72, 775}, 2}, {{104, 775}, 2}, {{72, 803}, 2}, {{104, 803}, 2}, {{72, 776}, 2}, {{104, 776}, 2}, + {{72, 807}, 2}, {{104, 807}, 2}, {{72, 814}, 2}, {{104, 814}, 2}, {{73, 816}, 2}, {{105, 816}, 2}, + {{73, 776, 769}, 3}, {{105, 776, 769}, 3}, {{75, 769}, 2}, {{107, 769}, 2}, {{75, 803}, 2}, {{107, 803}, 2}, + {{75, 817}, 2}, {{107, 817}, 2}, {{76, 803}, 2}, {{108, 803}, 2}, {{76, 803, 772}, 3}, {{108, 803, 772}, 3}, + {{76, 817}, 2}, {{108, 817}, 2}, {{76, 813}, 2}, {{108, 813}, 2}, {{77, 769}, 2}, {{109, 769}, 2}, {{77, 775}, 2}, + {{109, 775}, 2}, {{77, 803}, 2}, {{109, 803}, 2}, {{78, 775}, 2}, {{110, 775}, 2}, {{78, 803}, 2}, {{110, 803}, 2}, + {{78, 817}, 2}, {{110, 817}, 2}, {{78, 813}, 2}, {{110, 813}, 2}, {{79, 771, 769}, 3}, {{111, 771, 769}, 3}, + {{79, 771, 776}, 3}, {{111, 771, 776}, 3}, {{79, 772, 768}, 3}, {{111, 772, 768}, 3}, {{79, 772, 769}, 3}, + {{111, 772, 769}, 3}, {{80, 769}, 2}, {{112, 769}, 2}, {{80, 775}, 2}, {{112, 775}, 2}, {{82, 775}, 2}, + {{114, 775}, 2}, {{82, 803}, 2}, {{114, 803}, 2}, {{82, 803, 772}, 3}, {{114, 803, 772}, 3}, {{82, 817}, 2}, + {{114, 817}, 2}, {{83, 775}, 2}, {{115, 775}, 2}, {{83, 803}, 2}, {{115, 803}, 2}, {{83, 769, 775}, 3}, + {{115, 769, 775}, 3}, {{83, 780, 775}, 3}, {{115, 780, 775}, 3}, {{83, 803, 775}, 3}, {{115, 803, 775}, 3}, + {{84, 775}, 2}, {{116, 775}, 2}, {{84, 803}, 2}, {{116, 803}, 2}, {{84, 817}, 2}, {{116, 817}, 2}, {{84, 813}, 2}, + {{116, 813}, 2}, {{85, 804}, 2}, {{117, 804}, 2}, {{85, 816}, 2}, {{117, 816}, 2}, {{85, 813}, 2}, {{117, 813}, 2}, + {{85, 771, 769}, 3}, {{117, 771, 769}, 3}, {{85, 772, 776}, 3}, {{117, 772, 776}, 3}, {{86, 771}, 2}, {{118, 771}, 2}, + {{86, 803}, 2}, {{118, 803}, 2}, {{87, 768}, 2}, {{119, 768}, 2}, {{87, 769}, 2}, {{119, 769}, 2}, {{87, 776}, 2}, + {{119, 776}, 2}, {{87, 775}, 2}, {{119, 775}, 2}, {{87, 803}, 2}, {{119, 803}, 2}, {{88, 775}, 2}, {{120, 775}, 2}, + {{88, 776}, 2}, {{120, 776}, 2}, {{89, 775}, 2}, {{121, 775}, 2}, {{90, 770}, 2}, {{122, 770}, 2}, {{90, 803}, 2}, + {{122, 803}, 2}, {{90, 817}, 2}, {{122, 817}, 2}, {{104, 817}, 2}, {{116, 776}, 2}, {{119, 778}, 2}, {{121, 778}, 2}, + {{383, 775}, 2}, {{65, 803}, 2}, {{97, 803}, 2}, {{65, 777}, 2}, {{97, 777}, 2}, {{65, 770, 769}, 3}, + {{97, 770, 769}, 3}, {{65, 770, 768}, 3}, {{97, 770, 768}, 3}, {{65, 770, 777}, 3}, {{97, 770, 777}, 3}, + {{65, 770, 771}, 3}, {{97, 770, 771}, 3}, {{65, 803, 770}, 3}, {{97, 803, 770}, 3}, {{65, 774, 769}, 3}, + {{97, 774, 769}, 3}, {{65, 774, 768}, 3}, {{97, 774, 768}, 3}, {{65, 774, 777}, 3}, {{97, 774, 777}, 3}, + {{65, 774, 771}, 3}, {{97, 774, 771}, 3}, {{65, 803, 774}, 3}, {{97, 803, 774}, 3}, {{69, 803}, 2}, {{101, 803}, 2}, + {{69, 777}, 2}, {{101, 777}, 2}, {{69, 771}, 2}, {{101, 771}, 2}, {{69, 770, 769}, 3}, {{101, 770, 769}, 3}, + {{69, 770, 768}, 3}, {{101, 770, 768}, 3}, {{69, 770, 777}, 3}, {{101, 770, 777}, 3}, {{69, 770, 771}, 3}, + {{101, 770, 771}, 3}, {{69, 803, 770}, 3}, {{101, 803, 770}, 3}, {{73, 777}, 2}, {{105, 777}, 2}, {{73, 803}, 2}, + {{105, 803}, 2}, {{79, 803}, 2}, {{111, 803}, 2}, {{79, 777}, 2}, {{111, 777}, 2}, {{79, 770, 769}, 3}, + {{111, 770, 769}, 3}, {{79, 770, 768}, 3}, {{111, 770, 768}, 3}, {{79, 770, 777}, 3}, {{111, 770, 777}, 3}, + {{79, 770, 771}, 3}, {{111, 770, 771}, 3}, {{79, 803, 770}, 3}, {{111, 803, 770}, 3}, {{79, 795, 769}, 3}, + {{111, 795, 769}, 3}, {{79, 795, 768}, 3}, {{111, 795, 768}, 3}, {{79, 795, 777}, 3}, {{111, 795, 777}, 3}, + {{79, 795, 771}, 3}, {{111, 795, 771}, 3}, {{79, 795, 803}, 3}, {{111, 795, 803}, 3}, {{85, 803}, 2}, {{117, 803}, 2}, + {{85, 777}, 2}, {{117, 777}, 2}, {{85, 795, 769}, 3}, {{117, 795, 769}, 3}, {{85, 795, 768}, 3}, {{117, 795, 768}, 3}, + {{85, 795, 777}, 3}, {{117, 795, 777}, 3}, {{85, 795, 771}, 3}, {{117, 795, 771}, 3}, {{85, 795, 803}, 3}, + {{117, 795, 803}, 3}, {{89, 768}, 2}, {{121, 768}, 2}, {{89, 803}, 2}, {{121, 803}, 2}, {{89, 777}, 2}, + {{121, 777}, 2}, {{89, 771}, 2}, {{121, 771}, 2}, {{945, 787}, 2}, {{945, 788}, 2}, {{945, 787, 768}, 3}, + {{945, 788, 768}, 3}, {{945, 787, 769}, 3}, {{945, 788, 769}, 3}, {{945, 787, 834}, 3}, {{945, 788, 834}, 3}, + {{913, 787}, 2}, {{913, 788}, 2}, {{913, 787, 768}, 3}, {{913, 788, 768}, 3}, {{913, 787, 769}, 3}, + {{913, 788, 769}, 3}, {{913, 787, 834}, 3}, {{913, 788, 834}, 3}, {{949, 787}, 2}, {{949, 788}, 2}, + {{949, 787, 768}, 3}, {{949, 788, 768}, 3}, {{949, 787, 769}, 3}, {{949, 788, 769}, 3}, {{917, 787}, 2}, + {{917, 788}, 2}, {{917, 787, 768}, 3}, {{917, 788, 768}, 3}, {{917, 787, 769}, 3}, {{917, 788, 769}, 3}, + {{951, 787}, 2}, {{951, 788}, 2}, {{951, 787, 768}, 3}, {{951, 788, 768}, 3}, {{951, 787, 769}, 3}, + {{951, 788, 769}, 3}, {{951, 787, 834}, 3}, {{951, 788, 834}, 3}, {{919, 787}, 2}, {{919, 788}, 2}, + {{919, 787, 768}, 3}, {{919, 788, 768}, 3}, {{919, 787, 769}, 3}, {{919, 788, 769}, 3}, {{919, 787, 834}, 3}, + {{919, 788, 834}, 3}, {{953, 787}, 2}, {{953, 788}, 2}, {{953, 787, 768}, 3}, {{953, 788, 768}, 3}, + {{953, 787, 769}, 3}, {{953, 788, 769}, 3}, {{953, 787, 834}, 3}, {{953, 788, 834}, 3}, {{921, 787}, 2}, + {{921, 788}, 2}, {{921, 787, 768}, 3}, {{921, 788, 768}, 3}, {{921, 787, 769}, 3}, {{921, 788, 769}, 3}, + {{921, 787, 834}, 3}, {{921, 788, 834}, 3}, {{959, 787}, 2}, {{959, 788}, 2}, {{959, 787, 768}, 3}, + {{959, 788, 768}, 3}, {{959, 787, 769}, 3}, {{959, 788, 769}, 3}, {{927, 787}, 2}, {{927, 788}, 2}, + {{927, 787, 768}, 3}, {{927, 788, 768}, 3}, {{927, 787, 769}, 3}, {{927, 788, 769}, 3}, {{965, 787}, 2}, + {{965, 788}, 2}, {{965, 787, 768}, 3}, {{965, 788, 768}, 3}, {{965, 787, 769}, 3}, {{965, 788, 769}, 3}, + {{965, 787, 834}, 3}, {{965, 788, 834}, 3}, {{933, 788}, 2}, {{933, 788, 768}, 3}, {{933, 788, 769}, 3}, + {{933, 788, 834}, 3}, {{969, 787}, 2}, {{969, 788}, 2}, {{969, 787, 768}, 3}, {{969, 788, 768}, 3}, + {{969, 787, 769}, 3}, {{969, 788, 769}, 3}, {{969, 787, 834}, 3}, {{969, 788, 834}, 3}, {{937, 787}, 2}, + {{937, 788}, 2}, {{937, 787, 768}, 3}, {{937, 788, 768}, 3}, {{937, 787, 769}, 3}, {{937, 788, 769}, 3}, + {{937, 787, 834}, 3}, {{937, 788, 834}, 3}, {{945, 768}, 2}, {{945, 769}, 2}, {{949, 768}, 2}, {{949, 769}, 2}, + {{951, 768}, 2}, {{951, 769}, 2}, {{953, 768}, 2}, {{953, 769}, 2}, {{959, 768}, 2}, {{959, 769}, 2}, {{965, 768}, 2}, + {{965, 769}, 2}, {{969, 768}, 2}, {{969, 769}, 2}, {{945, 787, 837}, 3}, {{945, 788, 837}, 3}, + {{945, 787, 768, 837}, 4}, {{945, 788, 768, 837}, 4}, {{945, 787, 769, 837}, 4}, {{945, 788, 769, 837}, 4}, + {{945, 787, 834, 837}, 4}, {{945, 788, 834, 837}, 4}, {{913, 787, 837}, 3}, {{913, 788, 837}, 3}, + {{913, 787, 768, 837}, 4}, {{913, 788, 768, 837}, 4}, {{913, 787, 769, 837}, 4}, {{913, 788, 769, 837}, 4}, + {{913, 787, 834, 837}, 4}, {{913, 788, 834, 837}, 4}, {{951, 787, 837}, 3}, {{951, 788, 837}, 3}, + {{951, 787, 768, 837}, 4}, {{951, 788, 768, 837}, 4}, {{951, 787, 769, 837}, 4}, {{951, 788, 769, 837}, 4}, + {{951, 787, 834, 837}, 4}, {{951, 788, 834, 837}, 4}, {{919, 787, 837}, 3}, {{919, 788, 837}, 3}, + {{919, 787, 768, 837}, 4}, {{919, 788, 768, 837}, 4}, {{919, 787, 769, 837}, 4}, {{919, 788, 769, 837}, 4}, + {{919, 787, 834, 837}, 4}, {{919, 788, 834, 837}, 4}, {{969, 787, 837}, 3}, {{969, 788, 837}, 3}, + {{969, 787, 768, 837}, 4}, {{969, 788, 768, 837}, 4}, {{969, 787, 769, 837}, 4}, {{969, 788, 769, 837}, 4}, + {{969, 787, 834, 837}, 4}, {{969, 788, 834, 837}, 4}, {{937, 787, 837}, 3}, {{937, 788, 837}, 3}, + {{937, 787, 768, 837}, 4}, {{937, 788, 768, 837}, 4}, {{937, 787, 769, 837}, 4}, {{937, 788, 769, 837}, 4}, + {{937, 787, 834, 837}, 4}, {{937, 788, 834, 837}, 4}, {{945, 774}, 2}, {{945, 772}, 2}, {{945, 768, 837}, 3}, + {{945, 837}, 2}, {{945, 769, 837}, 3}, {{945, 834}, 2}, {{945, 834, 837}, 3}, {{913, 774}, 2}, {{913, 772}, 2}, + {{913, 768}, 2}, {{913, 769}, 2}, {{913, 837}, 2}, {{953}, 1}, {{168, 834}, 2}, {{951, 768, 837}, 3}, {{951, 837}, 2}, + {{951, 769, 837}, 3}, {{951, 834}, 2}, {{951, 834, 837}, 3}, {{917, 768}, 2}, {{917, 769}, 2}, {{919, 768}, 2}, + {{919, 769}, 2}, {{919, 837}, 2}, {{8127, 768}, 2}, {{8127, 769}, 2}, {{8127, 834}, 2}, {{953, 774}, 2}, + {{953, 772}, 2}, {{953, 776, 768}, 3}, {{953, 776, 769}, 3}, {{953, 834}, 2}, {{953, 776, 834}, 3}, {{921, 774}, 2}, + {{921, 772}, 2}, {{921, 768}, 2}, {{921, 769}, 2}, {{8190, 768}, 2}, {{8190, 769}, 2}, {{8190, 834}, 2}, + {{965, 774}, 2}, {{965, 772}, 2}, {{965, 776, 768}, 3}, {{965, 776, 769}, 3}, {{961, 787}, 2}, {{961, 788}, 2}, + {{965, 834}, 2}, {{965, 776, 834}, 3}, {{933, 774}, 2}, {{933, 772}, 2}, {{933, 768}, 2}, {{933, 769}, 2}, + {{929, 788}, 2}, {{168, 768}, 2}, {{168, 769}, 2}, {{96}, 1}, {{969, 768, 837}, 3}, {{969, 837}, 2}, + {{969, 769, 837}, 3}, {{969, 834}, 2}, {{969, 834, 837}, 3}, {{927, 768}, 2}, {{927, 769}, 2}, {{937, 768}, 2}, + {{937, 769}, 2}, {{937, 837}, 2}, {{180}, 1}, {{8194}, 1}, {{8195}, 1}, {{937}, 1}, {{75}, 1}, {{65, 778}, 2}, + {{8592, 824}, 2}, {{8594, 824}, 2}, {{8596, 824}, 2}, {{8656, 824}, 2}, {{8660, 824}, 2}, {{8658, 824}, 2}, + {{8707, 824}, 2}, {{8712, 824}, 2}, {{8715, 824}, 2}, {{8739, 824}, 2}, {{8741, 824}, 2}, {{8764, 824}, 2}, + {{8771, 824}, 2}, {{8773, 824}, 2}, {{8776, 824}, 2}, {{61, 824}, 2}, {{8801, 824}, 2}, {{8781, 824}, 2}, + {{60, 824}, 2}, {{62, 824}, 2}, {{8804, 824}, 2}, {{8805, 824}, 2}, {{8818, 824}, 2}, {{8819, 824}, 2}, + {{8822, 824}, 2}, {{8823, 824}, 2}, {{8826, 824}, 2}, {{8827, 824}, 2}, {{8834, 824}, 2}, {{8835, 824}, 2}, + {{8838, 824}, 2}, {{8839, 824}, 2}, {{8866, 824}, 2}, {{8872, 824}, 2}, {{8873, 824}, 2}, {{8875, 824}, 2}, + {{8828, 824}, 2}, {{8829, 824}, 2}, {{8849, 824}, 2}, {{8850, 824}, 2}, {{8882, 824}, 2}, {{8883, 824}, 2}, + {{8884, 824}, 2}, {{8885, 824}, 2}, {{12296}, 1}, {{12297}, 1}, {{10973, 824}, 2}, {{12363, 12441}, 2}, + {{12365, 12441}, 2}, {{12367, 12441}, 2}, {{12369, 12441}, 2}, {{12371, 12441}, 2}, {{12373, 12441}, 2}, + {{12375, 12441}, 2}, {{12377, 12441}, 2}, {{12379, 12441}, 2}, {{12381, 12441}, 2}, {{12383, 12441}, 2}, + {{12385, 12441}, 2}, {{12388, 12441}, 2}, {{12390, 12441}, 2}, {{12392, 12441}, 2}, {{12399, 12441}, 2}, + {{12399, 12442}, 2}, {{12402, 12441}, 2}, {{12402, 12442}, 2}, {{12405, 12441}, 2}, {{12405, 12442}, 2}, + {{12408, 12441}, 2}, {{12408, 12442}, 2}, {{12411, 12441}, 2}, {{12411, 12442}, 2}, {{12358, 12441}, 2}, + {{12445, 12441}, 2}, {{12459, 12441}, 2}, {{12461, 12441}, 2}, {{12463, 12441}, 2}, {{12465, 12441}, 2}, + {{12467, 12441}, 2}, {{12469, 12441}, 2}, {{12471, 12441}, 2}, {{12473, 12441}, 2}, {{12475, 12441}, 2}, + {{12477, 12441}, 2}, {{12479, 12441}, 2}, {{12481, 12441}, 2}, {{12484, 12441}, 2}, {{12486, 12441}, 2}, + {{12488, 12441}, 2}, {{12495, 12441}, 2}, {{12495, 12442}, 2}, {{12498, 12441}, 2}, {{12498, 12442}, 2}, + {{12501, 12441}, 2}, {{12501, 12442}, 2}, {{12504, 12441}, 2}, {{12504, 12442}, 2}, {{12507, 12441}, 2}, + {{12507, 12442}, 2}, {{12454, 12441}, 2}, {{12527, 12441}, 2}, {{12528, 12441}, 2}, {{12529, 12441}, 2}, + {{12530, 12441}, 2}, {{12541, 12441}, 2}, {{35912}, 1}, {{26356}, 1}, {{36554}, 1}, {{36040}, 1}, {{28369}, 1}, + {{20018}, 1}, {{21477}, 1}, {{40860}, 1}, {{40860}, 1}, {{22865}, 1}, {{37329}, 1}, {{21895}, 1}, {{22856}, 1}, + {{25078}, 1}, {{30313}, 1}, {{32645}, 1}, {{34367}, 1}, {{34746}, 1}, {{35064}, 1}, {{37007}, 1}, {{27138}, 1}, + {{27931}, 1}, {{28889}, 1}, {{29662}, 1}, {{33853}, 1}, {{37226}, 1}, {{39409}, 1}, {{20098}, 1}, {{21365}, 1}, + {{27396}, 1}, {{29211}, 1}, {{34349}, 1}, {{40478}, 1}, {{23888}, 1}, {{28651}, 1}, {{34253}, 1}, {{35172}, 1}, + {{25289}, 1}, {{33240}, 1}, {{34847}, 1}, {{24266}, 1}, {{26391}, 1}, {{28010}, 1}, {{29436}, 1}, {{37070}, 1}, + {{20358}, 1}, {{20919}, 1}, {{21214}, 1}, {{25796}, 1}, {{27347}, 1}, {{29200}, 1}, {{30439}, 1}, {{32769}, 1}, + {{34310}, 1}, {{34396}, 1}, {{36335}, 1}, {{38706}, 1}, {{39791}, 1}, {{40442}, 1}, {{30860}, 1}, {{31103}, 1}, + {{32160}, 1}, {{33737}, 1}, {{37636}, 1}, {{40575}, 1}, {{35542}, 1}, {{22751}, 1}, {{24324}, 1}, {{31840}, 1}, + {{32894}, 1}, {{29282}, 1}, {{30922}, 1}, {{36034}, 1}, {{38647}, 1}, {{22744}, 1}, {{23650}, 1}, {{27155}, 1}, + {{28122}, 1}, {{28431}, 1}, {{32047}, 1}, {{32311}, 1}, {{38475}, 1}, {{21202}, 1}, {{32907}, 1}, {{20956}, 1}, + {{20940}, 1}, {{31260}, 1}, {{32190}, 1}, {{33777}, 1}, {{38517}, 1}, {{35712}, 1}, {{25295}, 1}, {{27138}, 1}, + {{35582}, 1}, {{20025}, 1}, {{23527}, 1}, {{24594}, 1}, {{29575}, 1}, {{30064}, 1}, {{21271}, 1}, {{30971}, 1}, + {{20415}, 1}, {{24489}, 1}, {{19981}, 1}, {{27852}, 1}, {{25976}, 1}, {{32034}, 1}, {{21443}, 1}, {{22622}, 1}, + {{30465}, 1}, {{33865}, 1}, {{35498}, 1}, {{27578}, 1}, {{36784}, 1}, {{27784}, 1}, {{25342}, 1}, {{33509}, 1}, + {{25504}, 1}, {{30053}, 1}, {{20142}, 1}, {{20841}, 1}, {{20937}, 1}, {{26753}, 1}, {{31975}, 1}, {{33391}, 1}, + {{35538}, 1}, {{37327}, 1}, {{21237}, 1}, {{21570}, 1}, {{22899}, 1}, {{24300}, 1}, {{26053}, 1}, {{28670}, 1}, + {{31018}, 1}, {{38317}, 1}, {{39530}, 1}, {{40599}, 1}, {{40654}, 1}, {{21147}, 1}, {{26310}, 1}, {{27511}, 1}, + {{36706}, 1}, {{24180}, 1}, {{24976}, 1}, {{25088}, 1}, {{25754}, 1}, {{28451}, 1}, {{29001}, 1}, {{29833}, 1}, + {{31178}, 1}, {{32244}, 1}, {{32879}, 1}, {{36646}, 1}, {{34030}, 1}, {{36899}, 1}, {{37706}, 1}, {{21015}, 1}, + {{21155}, 1}, {{21693}, 1}, {{28872}, 1}, {{35010}, 1}, {{35498}, 1}, {{24265}, 1}, {{24565}, 1}, {{25467}, 1}, + {{27566}, 1}, {{31806}, 1}, {{29557}, 1}, {{20196}, 1}, {{22265}, 1}, {{23527}, 1}, {{23994}, 1}, {{24604}, 1}, + {{29618}, 1}, {{29801}, 1}, {{32666}, 1}, {{32838}, 1}, {{37428}, 1}, {{38646}, 1}, {{38728}, 1}, {{38936}, 1}, + {{20363}, 1}, {{31150}, 1}, {{37300}, 1}, {{38584}, 1}, {{24801}, 1}, {{20102}, 1}, {{20698}, 1}, {{23534}, 1}, + {{23615}, 1}, {{26009}, 1}, {{27138}, 1}, {{29134}, 1}, {{30274}, 1}, {{34044}, 1}, {{36988}, 1}, {{40845}, 1}, + {{26248}, 1}, {{38446}, 1}, {{21129}, 1}, {{26491}, 1}, {{26611}, 1}, {{27969}, 1}, {{28316}, 1}, {{29705}, 1}, + {{30041}, 1}, {{30827}, 1}, {{32016}, 1}, {{39006}, 1}, {{20845}, 1}, {{25134}, 1}, {{38520}, 1}, {{20523}, 1}, + {{23833}, 1}, {{28138}, 1}, {{36650}, 1}, {{24459}, 1}, {{24900}, 1}, {{26647}, 1}, {{29575}, 1}, {{38534}, 1}, + {{21033}, 1}, {{21519}, 1}, {{23653}, 1}, {{26131}, 1}, {{26446}, 1}, {{26792}, 1}, {{27877}, 1}, {{29702}, 1}, + {{30178}, 1}, {{32633}, 1}, {{35023}, 1}, {{35041}, 1}, {{37324}, 1}, {{38626}, 1}, {{21311}, 1}, {{28346}, 1}, + {{21533}, 1}, {{29136}, 1}, {{29848}, 1}, {{34298}, 1}, {{38563}, 1}, {{40023}, 1}, {{40607}, 1}, {{26519}, 1}, + {{28107}, 1}, {{33256}, 1}, {{31435}, 1}, {{31520}, 1}, {{31890}, 1}, {{29376}, 1}, {{28825}, 1}, {{35672}, 1}, + {{20160}, 1}, {{33590}, 1}, {{21050}, 1}, {{20999}, 1}, {{24230}, 1}, {{25299}, 1}, {{31958}, 1}, {{23429}, 1}, + {{27934}, 1}, {{26292}, 1}, {{36667}, 1}, {{34892}, 1}, {{38477}, 1}, {{35211}, 1}, {{24275}, 1}, {{20800}, 1}, + {{21952}, 1}, {{22618}, 1}, {{26228}, 1}, {{20958}, 1}, {{29482}, 1}, {{30410}, 1}, {{31036}, 1}, {{31070}, 1}, + {{31077}, 1}, {{31119}, 1}, {{38742}, 1}, {{31934}, 1}, {{32701}, 1}, {{34322}, 1}, {{35576}, 1}, {{36920}, 1}, + {{37117}, 1}, {{39151}, 1}, {{39164}, 1}, {{39208}, 1}, {{40372}, 1}, {{20398}, 1}, {{20711}, 1}, {{20813}, 1}, + {{21193}, 1}, {{21220}, 1}, {{21329}, 1}, {{21917}, 1}, {{22022}, 1}, {{22120}, 1}, {{22592}, 1}, {{22696}, 1}, + {{23652}, 1}, {{23662}, 1}, {{24724}, 1}, {{24936}, 1}, {{24974}, 1}, {{25074}, 1}, {{25935}, 1}, {{26082}, 1}, + {{26257}, 1}, {{26757}, 1}, {{28023}, 1}, {{28186}, 1}, {{28450}, 1}, {{29038}, 1}, {{29227}, 1}, {{29730}, 1}, + {{30865}, 1}, {{31038}, 1}, {{31049}, 1}, {{31048}, 1}, {{31056}, 1}, {{31062}, 1}, {{31069}, 1}, {{31117}, 1}, + {{31118}, 1}, {{31296}, 1}, {{31361}, 1}, {{31680}, 1}, {{32244}, 1}, {{32265}, 1}, {{32321}, 1}, {{32626}, 1}, + {{32773}, 1}, {{33261}, 1}, {{33401}, 1}, {{33401}, 1}, {{33879}, 1}, {{35088}, 1}, {{35222}, 1}, {{35585}, 1}, + {{35641}, 1}, {{36051}, 1}, {{36104}, 1}, {{36790}, 1}, {{36920}, 1}, {{38627}, 1}, {{38911}, 1}, {{38971}, 1}, + {{20006}, 1}, {{20917}, 1}, {{20840}, 1}, {{20352}, 1}, {{20805}, 1}, {{20864}, 1}, {{21191}, 1}, {{21242}, 1}, + {{21917}, 1}, {{21845}, 1}, {{21913}, 1}, {{21986}, 1}, {{22618}, 1}, {{22707}, 1}, {{22852}, 1}, {{22868}, 1}, + {{23138}, 1}, {{23336}, 1}, {{24274}, 1}, {{24281}, 1}, {{24425}, 1}, {{24493}, 1}, {{24792}, 1}, {{24910}, 1}, + {{24840}, 1}, {{24974}, 1}, {{24928}, 1}, {{25074}, 1}, {{25140}, 1}, {{25540}, 1}, {{25628}, 1}, {{25682}, 1}, + {{25942}, 1}, {{26228}, 1}, {{26391}, 1}, {{26395}, 1}, {{26454}, 1}, {{27513}, 1}, {{27578}, 1}, {{27969}, 1}, + {{28379}, 1}, {{28363}, 1}, {{28450}, 1}, {{28702}, 1}, {{29038}, 1}, {{30631}, 1}, {{29237}, 1}, {{29359}, 1}, + {{29482}, 1}, {{29809}, 1}, {{29958}, 1}, {{30011}, 1}, {{30237}, 1}, {{30239}, 1}, {{30410}, 1}, {{30427}, 1}, + {{30452}, 1}, {{30538}, 1}, {{30528}, 1}, {{30924}, 1}, {{31409}, 1}, {{31680}, 1}, {{31867}, 1}, {{32091}, 1}, + {{32244}, 1}, {{32574}, 1}, {{32773}, 1}, {{33618}, 1}, {{33775}, 1}, {{34681}, 1}, {{35137}, 1}, {{35206}, 1}, + {{35222}, 1}, {{35519}, 1}, {{35576}, 1}, {{35531}, 1}, {{35585}, 1}, {{35582}, 1}, {{35565}, 1}, {{35641}, 1}, + {{35722}, 1}, {{36104}, 1}, {{36664}, 1}, {{36978}, 1}, {{37273}, 1}, {{37494}, 1}, {{38524}, 1}, {{38627}, 1}, + {{38742}, 1}, {{38875}, 1}, {{38911}, 1}, {{38923}, 1}, {{38971}, 1}, {{39698}, 1}, {{40860}, 1}, {{141386}, 1}, + {{141380}, 1}, {{144341}, 1}, {{15261}, 1}, {{16408}, 1}, {{16441}, 1}, {{152137}, 1}, {{154832}, 1}, {{163539}, 1}, + {{40771}, 1}, {{40846}, 1}, {{1497, 1460}, 2}, {{1522, 1463}, 2}, {{1513, 1473}, 2}, {{1513, 1474}, 2}, + {{1513, 1468, 1473}, 3}, {{1513, 1468, 1474}, 3}, {{1488, 1463}, 2}, {{1488, 1464}, 2}, {{1488, 1468}, 2}, + {{1489, 1468}, 2}, {{1490, 1468}, 2}, {{1491, 1468}, 2}, {{1492, 1468}, 2}, {{1493, 1468}, 2}, {{1494, 1468}, 2}, + {{1496, 1468}, 2}, {{1497, 1468}, 2}, {{1498, 1468}, 2}, {{1499, 1468}, 2}, {{1500, 1468}, 2}, {{1502, 1468}, 2}, + {{1504, 1468}, 2}, {{1505, 1468}, 2}, {{1507, 1468}, 2}, {{1508, 1468}, 2}, {{1510, 1468}, 2}, {{1511, 1468}, 2}, + {{1512, 1468}, 2}, {{1513, 1468}, 2}, {{1514, 1468}, 2}, {{1493, 1465}, 2}, {{1489, 1471}, 2}, {{1499, 1471}, 2}, + {{1508, 1471}, 2}, {{119127, 119141}, 2}, {{119128, 119141}, 2}, {{119128, 119141, 119150}, 3}, + {{119128, 119141, 119151}, 3}, {{119128, 119141, 119152}, 3}, {{119128, 119141, 119153}, 3}, + {{119128, 119141, 119154}, 3}, {{119225, 119141}, 2}, {{119226, 119141}, 2}, {{119225, 119141, 119150}, 3}, + {{119226, 119141, 119150}, 3}, {{119225, 119141, 119151}, 3}, {{119226, 119141, 119151}, 3}, {{20029}, 1}, + {{20024}, 1}, {{20033}, 1}, {{131362}, 1}, {{20320}, 1}, {{20398}, 1}, {{20411}, 1}, {{20482}, 1}, {{20602}, 1}, + {{20633}, 1}, {{20711}, 1}, {{20687}, 1}, {{13470}, 1}, {{132666}, 1}, {{20813}, 1}, {{20820}, 1}, {{20836}, 1}, + {{20855}, 1}, {{132380}, 1}, {{13497}, 1}, {{20839}, 1}, {{20877}, 1}, {{132427}, 1}, {{20887}, 1}, {{20900}, 1}, + {{20172}, 1}, {{20908}, 1}, {{20917}, 1}, {{168415}, 1}, {{20981}, 1}, {{20995}, 1}, {{13535}, 1}, {{21051}, 1}, + {{21062}, 1}, {{21106}, 1}, {{21111}, 1}, {{13589}, 1}, {{21191}, 1}, {{21193}, 1}, {{21220}, 1}, {{21242}, 1}, + {{21253}, 1}, {{21254}, 1}, {{21271}, 1}, {{21321}, 1}, {{21329}, 1}, {{21338}, 1}, {{21363}, 1}, {{21373}, 1}, + {{21375}, 1}, {{21375}, 1}, {{21375}, 1}, {{133676}, 1}, {{28784}, 1}, {{21450}, 1}, {{21471}, 1}, {{133987}, 1}, + {{21483}, 1}, {{21489}, 1}, {{21510}, 1}, {{21662}, 1}, {{21560}, 1}, {{21576}, 1}, {{21608}, 1}, {{21666}, 1}, + {{21750}, 1}, {{21776}, 1}, {{21843}, 1}, {{21859}, 1}, {{21892}, 1}, {{21892}, 1}, {{21913}, 1}, {{21931}, 1}, + {{21939}, 1}, {{21954}, 1}, {{22294}, 1}, {{22022}, 1}, {{22295}, 1}, {{22097}, 1}, {{22132}, 1}, {{20999}, 1}, + {{22766}, 1}, {{22478}, 1}, {{22516}, 1}, {{22541}, 1}, {{22411}, 1}, {{22578}, 1}, {{22577}, 1}, {{22700}, 1}, + {{136420}, 1}, {{22770}, 1}, {{22775}, 1}, {{22790}, 1}, {{22810}, 1}, {{22818}, 1}, {{22882}, 1}, {{136872}, 1}, + {{136938}, 1}, {{23020}, 1}, {{23067}, 1}, {{23079}, 1}, {{23000}, 1}, {{23142}, 1}, {{14062}, 1}, {{14076}, 1}, + {{23304}, 1}, {{23358}, 1}, {{23358}, 1}, {{137672}, 1}, {{23491}, 1}, {{23512}, 1}, {{23527}, 1}, {{23539}, 1}, + {{138008}, 1}, {{23551}, 1}, {{23558}, 1}, {{24403}, 1}, {{23586}, 1}, {{14209}, 1}, {{23648}, 1}, {{23662}, 1}, + {{23744}, 1}, {{23693}, 1}, {{138724}, 1}, {{23875}, 1}, {{138726}, 1}, {{23918}, 1}, {{23915}, 1}, {{23932}, 1}, + {{24033}, 1}, {{24034}, 1}, {{14383}, 1}, {{24061}, 1}, {{24104}, 1}, {{24125}, 1}, {{24169}, 1}, {{14434}, 1}, + {{139651}, 1}, {{14460}, 1}, {{24240}, 1}, {{24243}, 1}, {{24246}, 1}, {{24266}, 1}, {{172946}, 1}, {{24318}, 1}, + {{140081}, 1}, {{140081}, 1}, {{33281}, 1}, {{24354}, 1}, {{24354}, 1}, {{14535}, 1}, {{144056}, 1}, {{156122}, 1}, + {{24418}, 1}, {{24427}, 1}, {{14563}, 1}, {{24474}, 1}, {{24525}, 1}, {{24535}, 1}, {{24569}, 1}, {{24705}, 1}, + {{14650}, 1}, {{14620}, 1}, {{24724}, 1}, {{141012}, 1}, {{24775}, 1}, {{24904}, 1}, {{24908}, 1}, {{24910}, 1}, + {{24908}, 1}, {{24954}, 1}, {{24974}, 1}, {{25010}, 1}, {{24996}, 1}, {{25007}, 1}, {{25054}, 1}, {{25074}, 1}, + {{25078}, 1}, {{25104}, 1}, {{25115}, 1}, {{25181}, 1}, {{25265}, 1}, {{25300}, 1}, {{25424}, 1}, {{142092}, 1}, + {{25405}, 1}, {{25340}, 1}, {{25448}, 1}, {{25475}, 1}, {{25572}, 1}, {{142321}, 1}, {{25634}, 1}, {{25541}, 1}, + {{25513}, 1}, {{14894}, 1}, {{25705}, 1}, {{25726}, 1}, {{25757}, 1}, {{25719}, 1}, {{14956}, 1}, {{25935}, 1}, + {{25964}, 1}, {{143370}, 1}, {{26083}, 1}, {{26360}, 1}, {{26185}, 1}, {{15129}, 1}, {{26257}, 1}, {{15112}, 1}, + {{15076}, 1}, {{20882}, 1}, {{20885}, 1}, {{26368}, 1}, {{26268}, 1}, {{32941}, 1}, {{17369}, 1}, {{26391}, 1}, + {{26395}, 1}, {{26401}, 1}, {{26462}, 1}, {{26451}, 1}, {{144323}, 1}, {{15177}, 1}, {{26618}, 1}, {{26501}, 1}, + {{26706}, 1}, {{26757}, 1}, {{144493}, 1}, {{26766}, 1}, {{26655}, 1}, {{26900}, 1}, {{15261}, 1}, {{26946}, 1}, + {{27043}, 1}, {{27114}, 1}, {{27304}, 1}, {{145059}, 1}, {{27355}, 1}, {{15384}, 1}, {{27425}, 1}, {{145575}, 1}, + {{27476}, 1}, {{15438}, 1}, {{27506}, 1}, {{27551}, 1}, {{27578}, 1}, {{27579}, 1}, {{146061}, 1}, {{138507}, 1}, + {{146170}, 1}, {{27726}, 1}, {{146620}, 1}, {{27839}, 1}, {{27853}, 1}, {{27751}, 1}, {{27926}, 1}, {{27966}, 1}, + {{28023}, 1}, {{27969}, 1}, {{28009}, 1}, {{28024}, 1}, {{28037}, 1}, {{146718}, 1}, {{27956}, 1}, {{28207}, 1}, + {{28270}, 1}, {{15667}, 1}, {{28363}, 1}, {{28359}, 1}, {{147153}, 1}, {{28153}, 1}, {{28526}, 1}, {{147294}, 1}, + {{147342}, 1}, {{28614}, 1}, {{28729}, 1}, {{28702}, 1}, {{28699}, 1}, {{15766}, 1}, {{28746}, 1}, {{28797}, 1}, + {{28791}, 1}, {{28845}, 1}, {{132389}, 1}, {{28997}, 1}, {{148067}, 1}, {{29084}, 1}, {{148395}, 1}, {{29224}, 1}, + {{29237}, 1}, {{29264}, 1}, {{149000}, 1}, {{29312}, 1}, {{29333}, 1}, {{149301}, 1}, {{149524}, 1}, {{29562}, 1}, + {{29579}, 1}, {{16044}, 1}, {{29605}, 1}, {{16056}, 1}, {{16056}, 1}, {{29767}, 1}, {{29788}, 1}, {{29809}, 1}, + {{29829}, 1}, {{29898}, 1}, {{16155}, 1}, {{29988}, 1}, {{150582}, 1}, {{30014}, 1}, {{150674}, 1}, {{30064}, 1}, + {{139679}, 1}, {{30224}, 1}, {{151457}, 1}, {{151480}, 1}, {{151620}, 1}, {{16380}, 1}, {{16392}, 1}, {{30452}, 1}, + {{151795}, 1}, {{151794}, 1}, {{151833}, 1}, {{151859}, 1}, {{30494}, 1}, {{30495}, 1}, {{30495}, 1}, {{30538}, 1}, + {{16441}, 1}, {{30603}, 1}, {{16454}, 1}, {{16534}, 1}, {{152605}, 1}, {{30798}, 1}, {{30860}, 1}, {{30924}, 1}, + {{16611}, 1}, {{153126}, 1}, {{31062}, 1}, {{153242}, 1}, {{153285}, 1}, {{31119}, 1}, {{31211}, 1}, {{16687}, 1}, + {{31296}, 1}, {{31306}, 1}, {{31311}, 1}, {{153980}, 1}, {{154279}, 1}, {{154279}, 1}, {{31470}, 1}, {{16898}, 1}, + {{154539}, 1}, {{31686}, 1}, {{31689}, 1}, {{16935}, 1}, {{154752}, 1}, {{31954}, 1}, {{17056}, 1}, {{31976}, 1}, + {{31971}, 1}, {{32000}, 1}, {{155526}, 1}, {{32099}, 1}, {{17153}, 1}, {{32199}, 1}, {{32258}, 1}, {{32325}, 1}, + {{17204}, 1}, {{156200}, 1}, {{156231}, 1}, {{17241}, 1}, {{156377}, 1}, {{32634}, 1}, {{156478}, 1}, {{32661}, 1}, + {{32762}, 1}, {{32773}, 1}, {{156890}, 1}, {{156963}, 1}, {{32864}, 1}, {{157096}, 1}, {{32880}, 1}, {{144223}, 1}, + {{17365}, 1}, {{32946}, 1}, {{33027}, 1}, {{17419}, 1}, {{33086}, 1}, {{23221}, 1}, {{157607}, 1}, {{157621}, 1}, + {{144275}, 1}, {{144284}, 1}, {{33281}, 1}, {{33284}, 1}, {{36766}, 1}, {{17515}, 1}, {{33425}, 1}, {{33419}, 1}, + {{33437}, 1}, {{21171}, 1}, {{33457}, 1}, {{33459}, 1}, {{33469}, 1}, {{33510}, 1}, {{158524}, 1}, {{33509}, 1}, + {{33565}, 1}, {{33635}, 1}, {{33709}, 1}, {{33571}, 1}, {{33725}, 1}, {{33767}, 1}, {{33879}, 1}, {{33619}, 1}, + {{33738}, 1}, {{33740}, 1}, {{33756}, 1}, {{158774}, 1}, {{159083}, 1}, {{158933}, 1}, {{17707}, 1}, {{34033}, 1}, + {{34035}, 1}, {{34070}, 1}, {{160714}, 1}, {{34148}, 1}, {{159532}, 1}, {{17757}, 1}, {{17761}, 1}, {{159665}, 1}, + {{159954}, 1}, {{17771}, 1}, {{34384}, 1}, {{34396}, 1}, {{34407}, 1}, {{34409}, 1}, {{34473}, 1}, {{34440}, 1}, + {{34574}, 1}, {{34530}, 1}, {{34681}, 1}, {{34600}, 1}, {{34667}, 1}, {{34694}, 1}, {{17879}, 1}, {{34785}, 1}, + {{34817}, 1}, {{17913}, 1}, {{34912}, 1}, {{34915}, 1}, {{161383}, 1}, {{35031}, 1}, {{35038}, 1}, {{17973}, 1}, + {{35066}, 1}, {{13499}, 1}, {{161966}, 1}, {{162150}, 1}, {{18110}, 1}, {{18119}, 1}, {{35488}, 1}, {{35565}, 1}, + {{35722}, 1}, {{35925}, 1}, {{162984}, 1}, {{36011}, 1}, {{36033}, 1}, {{36123}, 1}, {{36215}, 1}, {{163631}, 1}, + {{133124}, 1}, {{36299}, 1}, {{36284}, 1}, {{36336}, 1}, {{133342}, 1}, {{36564}, 1}, {{36664}, 1}, {{165330}, 1}, + {{165357}, 1}, {{37012}, 1}, {{37105}, 1}, {{37137}, 1}, {{165678}, 1}, {{37147}, 1}, {{37432}, 1}, {{37591}, 1}, + {{37592}, 1}, {{37500}, 1}, {{37881}, 1}, {{37909}, 1}, {{166906}, 1}, {{38283}, 1}, {{18837}, 1}, {{38327}, 1}, + {{167287}, 1}, {{18918}, 1}, {{38595}, 1}, {{23986}, 1}, {{38691}, 1}, {{168261}, 1}, {{168474}, 1}, {{19054}, 1}, + {{19062}, 1}, {{38880}, 1}, {{168970}, 1}, {{19122}, 1}, {{169110}, 1}, {{38923}, 1}, {{38923}, 1}, {{38953}, 1}, + {{169398}, 1}, {{39138}, 1}, {{19251}, 1}, {{39209}, 1}, {{39335}, 1}, {{39362}, 1}, {{39422}, 1}, {{19406}, 1}, + {{170800}, 1}, {{39698}, 1}, {{40000}, 1}, {{40189}, 1}, {{19662}, 1}, {{19693}, 1}, {{40295}, 1}, {{172238}, 1}, + {{19704}, 1}, {{172293}, 1}, {{172558}, 1}, {{172689}, 1}, {{40635}, 1}, {{19798}, 1}, {{40697}, 1}, {{40702}, 1}, + {{40709}, 1}, {{40719}, 1}, {{40726}, 1}, {{40763}, 1}, {{173568}, 1} +}; + +KInt getCanonicalClass(KInt ch) { + int index = binarySearchRange(canonicalClassesKeys, ARRAY_SIZE(canonicalClassesKeys), ch); + if (canonicalClassesKeys[index] != ch) { + return 0; + } + return canonicalClassesValues[index]; +} + +const Decomposition* getDecomposition(KInt codePoint) { + int index = binarySearchRange(decompositionKeys, ARRAY_SIZE(decompositionKeys), codePoint); + if (decompositionKeys[index] != codePoint) { + return nullptr; + } + return &decompositionValues[index]; +} + +} // namespace + +extern "C" { + +KInt Kotlin_text_regex_getCanonicalClassInternal(KInt ch) { + return getCanonicalClass(ch); +} + +KBoolean Kotlin_text_regex_hasSingleCodepointDecompositionInternal(KInt ch) { + int index = binarySearchRange(singleDecompositions, ARRAY_SIZE(singleDecompositions), ch); + return singleDecompositions[index] == ch; +} + +OBJ_GETTER(Kotlin_text_regex_getDecompositionInternal, KInt ch) { + const Decomposition* decomposition = getDecomposition(ch); + if (decomposition == nullptr) { + return nullptr; + } + ArrayHeader* result = AllocArrayInstance(theIntArrayTypeInfo, decomposition->length, OBJ_RESULT)->array(); + KInt* resultRaw = IntArrayAddressOfElementAt(result, 0); + for (int i = 0; i < decomposition->length; i++) { + *resultRaw++ = decomposition->array[i]; + } + RETURN_OBJ(result->obj()); +} + +KInt Kotlin_text_regex_decomposeString(ArrayHeader* inputCodePoints, KInt inputLength, ArrayHeader* outputCodePoints) { + RuntimeAssert(inputCodePoints->type_info() == theIntArrayTypeInfo, "Must use an Int array"); + RuntimeAssert(outputCodePoints->type_info() == theIntArrayTypeInfo, "Must use an Int array"); + RuntimeAssert(inputLength >= 0, "Input length must be >= 0"); + if (inputLength == 0) { + return 0; + } + + int outputLength = 0; + const KInt* inputArray = IntArrayAddressOfElementAt(inputCodePoints, 0); + KInt* outputArray = IntArrayAddressOfElementAt(outputCodePoints, 0); + for (int i = 0; i < inputLength; i++) { + const Decomposition* decomposition = getDecomposition(inputArray[i]); + if (decomposition == nullptr) { + outputArray[outputLength++] = inputArray[i]; + } else { + memcpy(outputArray + outputLength, decomposition->array, decomposition->length * sizeof(KInt)); + outputLength+=decomposition->length; + } + } + return outputLength; +} + +KInt Kotlin_text_regex_decomposeCodePoint(KInt codePoint, ArrayHeader* outputCodePoints, KInt fromIndex) { + RuntimeAssert(outputCodePoints->type_info() == theIntArrayTypeInfo, "Must be an Int array"); + RuntimeAssert(fromIndex >= 0 && static_cast(fromIndex) < outputCodePoints->count_, "Start index must be >= 0 and < array size"); + KInt* rawResult = IntArrayAddressOfElementAt(outputCodePoints, fromIndex); + const Decomposition* decomposition = getDecomposition(codePoint); + if (decomposition == nullptr) { + *rawResult = codePoint; + return 1; + } else { + memcpy(rawResult, decomposition->array, decomposition->length * sizeof(KInt)); + return decomposition->length; + } +} + +} // extern "C" diff --git a/kotlin-native/runtime/src/main/cpp/ReturnSlot.cpp b/kotlin-native/runtime/src/main/cpp/ReturnSlot.cpp new file mode 100644 index 00000000000..2c5ac47787e --- /dev/null +++ b/kotlin-native/runtime/src/main/cpp/ReturnSlot.cpp @@ -0,0 +1,40 @@ +/* + * Copyright 2010-2017 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "ReturnSlot.h" + +#ifdef KONAN_WASM +namespace { + +THREAD_LOCAL_VARIABLE long long storage; + +} // namespace + +extern "C" { + +RUNTIME_USED +KDouble ReturnSlot_getDouble() { + return *reinterpret_cast(&::storage); +} + +RUNTIME_USED +void ReturnSlot_setDouble(KInt upper, KInt lower) { + reinterpret_cast(&::storage)[0] = lower; + reinterpret_cast(&::storage)[1] = upper; +} + +} // extern "C" +#endif // KONAN_WASM diff --git a/kotlin-native/runtime/src/main/cpp/ReturnSlot.h b/kotlin-native/runtime/src/main/cpp/ReturnSlot.h new file mode 100644 index 00000000000..547c84a0ef1 --- /dev/null +++ b/kotlin-native/runtime/src/main/cpp/ReturnSlot.h @@ -0,0 +1,32 @@ +/* + * Copyright 2010-2017 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "Types.h" + +#ifdef KONAN_WASM + +#ifdef __cplusplus +extern "C" { +#endif + +KDouble ReturnSlot_getDouble(); +void ReturnSlot_setDouble(KInt upper, KInt lower); + +#ifdef __cplusplus +} // extern "C" +#endif + +#endif // KONAN_WASM diff --git a/kotlin-native/runtime/src/main/cpp/Runtime.cpp b/kotlin-native/runtime/src/main/cpp/Runtime.cpp new file mode 100644 index 00000000000..1457e92e1c1 --- /dev/null +++ b/kotlin-native/runtime/src/main/cpp/Runtime.cpp @@ -0,0 +1,256 @@ +/* + * Copyright 2010-2017 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "Alloc.h" +#include "Atomic.h" +#include "Cleaner.h" +#include "Exceptions.h" +#include "KAssert.h" +#include "Memory.h" +#include "ObjCExportInit.h" +#include "Porting.h" +#include "Runtime.h" +#include "Worker.h" + +typedef void (*Initializer)(int initialize, MemoryState* memory); +struct InitNode { + Initializer init; + InitNode* next; +}; + +namespace { + +InitNode* initHeadNode = nullptr; +InitNode* initTailNode = nullptr; + +enum class RuntimeStatus { + kUninitialized, + kRunning, + kDestroying, +}; + +struct RuntimeState { + MemoryState* memoryState; + Worker* worker; + RuntimeStatus status = RuntimeStatus::kUninitialized; +}; + +enum { + INIT_GLOBALS = 0, + INIT_THREAD_LOCAL_GLOBALS = 1, + DEINIT_THREAD_LOCAL_GLOBALS = 2, + DEINIT_GLOBALS = 3 +}; + +void InitOrDeinitGlobalVariables(int initialize, MemoryState* memory) { + InitNode* currentNode = initHeadNode; + while (currentNode != nullptr) { + currentNode->init(initialize, memory); + currentNode = currentNode->next; + } +} + +KBoolean g_checkLeaks = KonanNeedDebugInfo; +KBoolean g_checkLeakedCleaners = KonanNeedDebugInfo; + +constexpr RuntimeState* kInvalidRuntime = nullptr; + +THREAD_LOCAL_VARIABLE RuntimeState* runtimeState = kInvalidRuntime; +THREAD_LOCAL_VARIABLE int isMainThread = 0; + +inline bool isValidRuntime() { + return ::runtimeState != kInvalidRuntime; +} + +volatile int aliveRuntimesCount = 0; + +RuntimeState* initRuntime() { + SetKonanTerminateHandler(); + RuntimeState* result = konanConstructInstance(); + if (!result) return kInvalidRuntime; + RuntimeCheck(!isValidRuntime(), "No active runtimes allowed"); + ::runtimeState = result; + result->memoryState = InitMemory(); + result->worker = WorkerInit(true); + bool firstRuntime = atomicAdd(&aliveRuntimesCount, 1) == 1; + // Keep global variables in state as well. + if (firstRuntime) { + isMainThread = 1; + konan::consoleInit(); +#if KONAN_OBJC_INTEROP + Kotlin_ObjCExport_initialize(); +#endif + InitOrDeinitGlobalVariables(INIT_GLOBALS, result->memoryState); + } + InitOrDeinitGlobalVariables(INIT_THREAD_LOCAL_GLOBALS, result->memoryState); + RuntimeAssert(result->status == RuntimeStatus::kUninitialized, "Runtime must still be in the uninitialized state"); + result->status = RuntimeStatus::kRunning; + return result; +} + +void deinitRuntime(RuntimeState* state) { + RuntimeAssert(state->status == RuntimeStatus::kRunning, "Runtime must be in the running state"); + state->status = RuntimeStatus::kDestroying; + // This may be called after TLS is zeroed out, so ::memoryState in Memory cannot be trusted. + RestoreMemory(state->memoryState); + bool lastRuntime = atomicAdd(&aliveRuntimesCount, -1) == 0; + InitOrDeinitGlobalVariables(DEINIT_THREAD_LOCAL_GLOBALS, state->memoryState); + if (lastRuntime) + InitOrDeinitGlobalVariables(DEINIT_GLOBALS, state->memoryState); + auto workerId = GetWorkerId(state->worker); + WorkerDeinit(state->worker); + DeinitMemory(state->memoryState); + konanDestructInstance(state); + WorkerDestroyThreadDataIfNeeded(workerId); +} + +void Kotlin_deinitRuntimeCallback(void* argument) { + auto* state = reinterpret_cast(argument); + deinitRuntime(state); +} + +} // namespace + +extern "C" { + +void AppendToInitializersTail(InitNode *next) { + // TODO: use RuntimeState. + if (initHeadNode == nullptr) { + initHeadNode = next; + } else { + initTailNode->next = next; + } + initTailNode = next; +} + +void Kotlin_initRuntimeIfNeeded() { + if (!isValidRuntime()) { + initRuntime(); + // Register runtime deinit function at thread cleanup. + konan::onThreadExit(Kotlin_deinitRuntimeCallback, runtimeState); + } +} + +void Kotlin_deinitRuntimeIfNeeded() { + if (isValidRuntime()) { + deinitRuntime(::runtimeState); + ::runtimeState = kInvalidRuntime; + } +} + +void CheckIsMainThread() { + if (!isMainThread) + ThrowIncorrectDereferenceException(); +} + +KInt Konan_Platform_canAccessUnaligned() { +#if KONAN_NO_UNALIGNED_ACCESS + return 0; +#else + return 1; +#endif +} + +KInt Konan_Platform_isLittleEndian() { +#ifdef __BIG_ENDIAN__ + return 0; +#else + return 1; +#endif +} + +KInt Konan_Platform_getOsFamily() { +#if KONAN_MACOSX + return 1; +#elif KONAN_IOS + return 2; +#elif KONAN_LINUX + return 3; +#elif KONAN_WINDOWS + return 4; +#elif KONAN_ANDROID + return 5; +#elif KONAN_WASM + return 6; +#elif KONAN_TVOS + return 7; +#elif KONAN_WATCHOS + return 8; +#else +#warning "Unknown platform" + return 0; +#endif +} + +KInt Konan_Platform_getCpuArchitecture() { +#if KONAN_ARM32 + return 1; +#elif KONAN_ARM64 + return 2; +#elif KONAN_X86 + return 3; +#elif KONAN_X64 + return 4; +#elif KONAN_MIPS32 + return 5; +#elif KONAN_MIPSEL32 + return 6; +#elif KONAN_WASM + return 7; +#else +#warning "Unknown CPU" + return 0; +#endif +} + +KInt Konan_Platform_getMemoryModel() { + return IsStrictMemoryModel ? 0 : 1; +} + +KBoolean Konan_Platform_isDebugBinary() { + return KonanNeedDebugInfo ? true : false; +} + +void Kotlin_zeroOutTLSGlobals() { + if (runtimeState != nullptr && runtimeState->memoryState != nullptr) + InitOrDeinitGlobalVariables(DEINIT_THREAD_LOCAL_GLOBALS, runtimeState->memoryState); +} + +bool Kotlin_memoryLeakCheckerEnabled() { + return g_checkLeaks; +} + +KBoolean Konan_Platform_getMemoryLeakChecker() { + return g_checkLeaks; +} + +void Konan_Platform_setMemoryLeakChecker(KBoolean value) { + g_checkLeaks = value; +} + +bool Kotlin_cleanersLeakCheckerEnabled() { + return g_checkLeakedCleaners; +} + +KBoolean Konan_Platform_getCleanersLeakChecker() { + return g_checkLeakedCleaners; +} + +void Konan_Platform_setCleanersLeakChecker(KBoolean value) { + g_checkLeakedCleaners = value; +} + +} // extern "C" diff --git a/kotlin-native/runtime/src/main/cpp/Runtime.h b/kotlin-native/runtime/src/main/cpp/Runtime.h new file mode 100644 index 00000000000..1b296f7b7ea --- /dev/null +++ b/kotlin-native/runtime/src/main/cpp/Runtime.h @@ -0,0 +1,45 @@ +/* + * Copyright 2010-2017 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef RUNTIME_RUNTIME_H +#define RUNTIME_RUNTIME_H + +#include "Porting.h" + +struct InitNode; + +#ifdef __cplusplus +extern "C" { +#endif + +void Kotlin_initRuntimeIfNeeded(); +void Kotlin_deinitRuntimeIfNeeded(); + +// Appends given node to an initializer list. +void AppendToInitializersTail(struct InitNode*); + +// Zero out all Kotlin thread local globals. +void Kotlin_zeroOutTLSGlobals(); + +bool Kotlin_memoryLeakCheckerEnabled(); + +bool Kotlin_cleanersLeakCheckerEnabled(); + +#ifdef __cplusplus +} +#endif + +#endif // RUNTIME_RUNTIME_H diff --git a/kotlin-native/runtime/src/main/cpp/SourceInfo.h b/kotlin-native/runtime/src/main/cpp/SourceInfo.h new file mode 100644 index 00000000000..5e92548a1cb --- /dev/null +++ b/kotlin-native/runtime/src/main/cpp/SourceInfo.h @@ -0,0 +1,36 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef RUNTIME_SOURCEINFO_H +#define RUNTIME_SOURCEINFO_H + +struct SourceInfo { + const char* fileName; + int lineNumber; + int column; +}; + +#ifdef __cplusplus +extern "C" { +#endif + +struct SourceInfo Kotlin_getSourceInfo(void* addr); + +#ifdef __cplusplus +} // extern "C" +#endif + +#endif // RUNTIME_SOURCEINFO_H diff --git a/kotlin-native/runtime/src/main/cpp/StdCppStubs.cpp b/kotlin-native/runtime/src/main/cpp/StdCppStubs.cpp new file mode 100644 index 00000000000..09fd4e6a64c --- /dev/null +++ b/kotlin-native/runtime/src/main/cpp/StdCppStubs.cpp @@ -0,0 +1,40 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "KAssert.h" +#include "Porting.h" +#include "Common.h" + +#if KONAN_LINUX || KONAN_WINDOWS +// This function replaces `__cxa_demangle` defined in GNU libstdc++ +// by adding `--defsym` flag in `konan.properties`. +// This allows to avoid linking `__cxa_demangle` and its dependencies, thus reducing binary size. +RUNTIME_USED RUNTIME_WEAK extern "C" char* Konan_cxa_demangle( + const char* __mangled_name, char* __output_buffer, + size_t* __length, int* __status +) { + *__status = -2; // __mangled_name is not a valid name under the C++ ABI mangling rules. + return nullptr; +} + +namespace std { +void __throw_length_error(const char* __s __attribute__((unused))) { + RuntimeAssert(false, __s); +} + +} // namespace std + +#endif // KONAN_LINUX || KONAN_WINDOWS diff --git a/kotlin-native/runtime/src/main/cpp/TestSupportCompilerGenerated.hpp b/kotlin-native/runtime/src/main/cpp/TestSupportCompilerGenerated.hpp new file mode 100644 index 00000000000..d685f32c16e --- /dev/null +++ b/kotlin-native/runtime/src/main/cpp/TestSupportCompilerGenerated.hpp @@ -0,0 +1,66 @@ +/* + * Copyright 2010-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +#include +#include + +#include "gmock/gmock.h" +#include "gtest/gtest.h" + +#include "Types.h" + +template +class ScopedStrictMockFunction { +public: + using Mock = testing::StrictMock>; + + explicit ScopedStrictMockFunction(Mock** globalMockLocation) : globalMockLocation_(globalMockLocation) { + RuntimeCheck(globalMockLocation != nullptr, "ScopedStrictMockFunction needs non-null global mock location"); + RuntimeCheck(*globalMockLocation == nullptr, "ScopedStrictMockFunction needs null global mock"); + // TODO: Use make_unique when sysroots on Linux get updated. + mock_ = std::unique_ptr(new Mock()); + *globalMockLocation_ = mock_.get(); + } + + ScopedStrictMockFunction(const ScopedStrictMockFunction&) = delete; + ScopedStrictMockFunction& operator=(const ScopedStrictMockFunction&) = delete; + + ScopedStrictMockFunction(ScopedStrictMockFunction&& rhs) : globalMockLocation_(rhs.globalMockLocation_), mock_(std::move(rhs.mock_)) { + rhs.globalMockLocation_ = nullptr; + } + + ScopedStrictMockFunction& operator=(ScopedStrictMockFunction&& rhs) { + ScopedStrictMockFunction tmp(std::move(rhs)); + swap(tmp); + return *this; + } + + ~ScopedStrictMockFunction() { + if (!globalMockLocation_) return; + + RuntimeCheck(*globalMockLocation_ == mock_.get(), "unexpected global mock location"); + + testing::Mock::VerifyAndClear(mock_.get()); + mock_.reset(); + + *globalMockLocation_ = nullptr; + } + + void swap(ScopedStrictMockFunction& other) { + std::swap(globalMockLocation_, other.globalMockLocation_); + std::swap(mock_, other.mock_); + } + + Mock& get() { return *mock_; } + Mock& operator*() { return *mock_; } + +private: + // Can be null if moved-out of. + Mock** globalMockLocation_; + std::unique_ptr mock_; +}; + +ScopedStrictMockFunction ScopedCreateCleanerWorkerMock(); +ScopedStrictMockFunction ScopedShutdownCleanerWorkerMock(); diff --git a/kotlin-native/runtime/src/main/cpp/Time.cpp b/kotlin-native/runtime/src/main/cpp/Time.cpp new file mode 100644 index 00000000000..7c14e1f920d --- /dev/null +++ b/kotlin-native/runtime/src/main/cpp/Time.cpp @@ -0,0 +1,35 @@ +/* + * Copyright 2010-2017 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "Natives.h" +#include "Porting.h" +#include "Types.h" + +extern "C" { + +KLong Kotlin_system_getTimeMillis() { + return konan::getTimeMillis(); +} + +KLong Kotlin_system_getTimeNanos() { + return konan::getTimeNanos(); +} + +KLong Kotlin_system_getTimeMicros() { + return konan::getTimeMicros(); +} + +} // extern "C" diff --git a/kotlin-native/runtime/src/main/cpp/ToString.cpp b/kotlin-native/runtime/src/main/cpp/ToString.cpp new file mode 100644 index 00000000000..8123ccb6848 --- /dev/null +++ b/kotlin-native/runtime/src/main/cpp/ToString.cpp @@ -0,0 +1,122 @@ +/* + * Copyright 2010-2017 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include +#include + +#include "KAssert.h" +#include "Exceptions.h" +#include "Memory.h" +#include "Natives.h" +#include "KString.h" +#include "Porting.h" +#include "Types.h" + +namespace { + +char int_to_digit(uint32_t value) { + if (value < 10) { + return '0' + value; + } else { + return 'a' + (value - 10); + } +} + +// Radix is checked on the Kotlin side. +template OBJ_GETTER(Kotlin_toStringRadix, T value, KInt radix) { + if (value == 0) { + RETURN_RESULT_OF(CreateStringFromCString, "0"); + } + // In the worst case, we convert to binary, with sign. + char cstring[sizeof(T) * CHAR_BIT + 2]; + bool negative = (value < 0); + if (!negative) { + value = -value; + } + + int32_t length = 0; + while (value < 0) { + cstring[length++] = int_to_digit(-(value % radix)); + value /= radix; + } + if (negative) { + cstring[length++] = '-'; + } + for (int i = 0, j = length - 1; i < j; i++, j--) { + char tmp = cstring[i]; + cstring[i] = cstring[j]; + cstring[j] = tmp; + } + cstring[length] = '\0'; + RETURN_RESULT_OF(CreateStringFromCString, cstring); +} + +} // namespace + +extern "C" { + +OBJ_GETTER(Kotlin_Byte_toString, KByte value) { + char cstring[8]; + konan::snprintf(cstring, sizeof(cstring), "%d", value); + RETURN_RESULT_OF(CreateStringFromCString, cstring); +} + +OBJ_GETTER(Kotlin_Char_toString, KChar value) { + ArrayHeader* result = AllocArrayInstance(theStringTypeInfo, 1, OBJ_RESULT)->array(); + *CharArrayAddressOfElementAt(result, 0) = value; + RETURN_OBJ(result->obj()); +} + +OBJ_GETTER(Kotlin_Short_toString, KShort value) { + char cstring[8]; + konan::snprintf(cstring, sizeof(cstring), "%d", value); + RETURN_RESULT_OF(CreateStringFromCString, cstring); +} + +OBJ_GETTER(Kotlin_Int_toString, KInt value) { + char cstring[16]; + konan::snprintf(cstring, sizeof(cstring), "%d", value); + RETURN_RESULT_OF(CreateStringFromCString, cstring); +} + +OBJ_GETTER(Kotlin_Int_toStringRadix, KInt value, KInt radix) { + RETURN_RESULT_OF(Kotlin_toStringRadix, value, radix) +} + +OBJ_GETTER(Kotlin_Long_toString, KLong value) { + char cstring[32]; + konan::snprintf(cstring, sizeof(cstring), "%lld", static_cast(value)); + RETURN_RESULT_OF(CreateStringFromCString, cstring); +} + +OBJ_GETTER(Kotlin_Long_toStringRadix, KLong value, KInt radix) { + RETURN_RESULT_OF(Kotlin_toStringRadix, value, radix) +} + +OBJ_GETTER(Kotlin_DurationValue_formatToExactDecimals, KDouble value, KInt decimals) { + char cstring[32]; + konan::snprintf(cstring, sizeof(cstring), "%.*f", decimals, value); + RETURN_RESULT_OF(CreateStringFromCString, cstring) +} + +OBJ_GETTER(Kotlin_DurationValue_formatScientificImpl, KDouble value) { + char cstring[16]; + konan::snprintf(cstring, sizeof(cstring), "%.2e", value); + RETURN_RESULT_OF(CreateStringFromCString, cstring) +} + +} // extern "C" diff --git a/kotlin-native/runtime/src/main/cpp/TypeInfo.cpp b/kotlin-native/runtime/src/main/cpp/TypeInfo.cpp new file mode 100644 index 00000000000..3e226a0add6 --- /dev/null +++ b/kotlin-native/runtime/src/main/cpp/TypeInfo.cpp @@ -0,0 +1,79 @@ +/* + * Copyright 2010-2017 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "KAssert.h" +#include "TypeInfo.h" + +// If one shall use binary search when looking up methods and fields. +// TODO: maybe select strategy basing on number of elements. +#define USE_BINARY_SEARCH 1 + +extern "C" { +#if USE_BINARY_SEARCH + +void* LookupOpenMethod(const TypeInfo* info, MethodNameHash nameSignature) { + int bottom = 0; + int top = info->openMethodsCount_ - 1; + + while (bottom <= top) { + int middle = (bottom + top) / 2; + if (info->openMethods_[middle].nameSignature_ < nameSignature) + bottom = middle + 1; + else if (info->openMethods_[middle].nameSignature_ == nameSignature) + return info->openMethods_[middle].methodEntryPoint_; + else + top = middle - 1; + } + + RuntimeAssert(false, "Unknown open method"); + return nullptr; +} + +#else + +void* LookupOpenMethod(const TypeInfo* info, MethodNameHash nameSignature) { + for (int i = 0; i < info->openMethodsCount_; ++i) { + if (info->openMethods_[i].nameSignature_ == nameSignature) { + return info->openMethods_[i].methodEntryPoint_; + } + } + RuntimeAssert(false, "Unknown open method"); + return nullptr; +} + +#endif + +// Seeks for the specified id. In case of failure returns a valid pointer to some record, never returns nullptr. +// It is the caller's responsibility to check if the search has succeeded or not. +InterfaceTableRecord const* LookupInterfaceTableRecord(InterfaceTableRecord const* interfaceTable, + int interfaceTableSize, ClassId interfaceId) { + if (interfaceTableSize <= 8) { + // Linear search. + int i; + for (i = 0; i < interfaceTableSize - 1 && interfaceTable[i].id < interfaceId; ++i); + return interfaceTable + i; + } + int l = 0, r = interfaceTableSize - 1; + while (l < r) { + int m = (l + r) / 2; + if (interfaceTable[m].id < interfaceId) + l = m + 1; + else r = m; + } + return interfaceTable + l; +} + +} diff --git a/kotlin-native/runtime/src/main/cpp/TypeInfo.h b/kotlin-native/runtime/src/main/cpp/TypeInfo.h new file mode 100644 index 00000000000..669962de6ce --- /dev/null +++ b/kotlin-native/runtime/src/main/cpp/TypeInfo.h @@ -0,0 +1,181 @@ +/* + * Copyright 2010-2017 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef RUNTIME_TYPEINFO_H +#define RUNTIME_TYPEINFO_H + +#include + +#include "Common.h" +#include "Names.h" + +#if KONAN_TYPE_INFO_HAS_WRITABLE_PART +struct WritableTypeInfo; +#endif + +struct ObjHeader; +struct AssociatedObjectTableRecord; + +// An element of sorted by hash in-place array representing methods. +// For systems where introspection is not needed - only open methods are in +// this table. +struct MethodTableRecord { + MethodNameHash nameSignature_; + void* methodEntryPoint_; +}; + +// Type for runtime representation of Konan object. +// Keep in sync with runtimeTypeMap in RTTIGenerator. +enum Konan_RuntimeType { + RT_INVALID = 0, + RT_OBJECT = 1, + RT_INT8 = 2, + RT_INT16 = 3, + RT_INT32 = 4, + RT_INT64 = 5, + RT_FLOAT32 = 6, + RT_FLOAT64 = 7, + RT_NATIVE_PTR = 8, + RT_BOOLEAN = 9, + RT_VECTOR128 = 10 +}; + +// Flags per type. +// Keep in sync with constants in RTTIGenerator. +enum Konan_TypeFlags { + TF_IMMUTABLE = 1 << 0, + TF_ACYCLIC = 1 << 1, + TF_INTERFACE = 1 << 2, + TF_OBJC_DYNAMIC = 1 << 3, + TF_LEAK_DETECTOR_CANDIDATE = 1 << 4, + TF_SUSPEND_FUNCTION = 1 << 5, + TF_HAS_FINALIZER = 1 << 6, +}; + +// Flags per object instance. +enum Konan_MetaFlags { + // If freeze attempt happens on such an object - throw an exception. + MF_NEVER_FROZEN = 1 << 0, +}; + +// Extended information about a type. +struct ExtendedTypeInfo { + // Number of fields (negated Konan_RuntimeType for array types). + int32_t fieldsCount_; + // Offsets of all fields. + const int32_t* fieldOffsets_; + // Types of all fields. + const uint8_t* fieldTypes_; + // Names of all fields. + const char** fieldNames_; + // Number of supported debug operations. + int32_t debugOperationsCount_; + // Table of supported debug operations functions. + void** debugOperations_; +}; + +typedef void const* VTableElement; + +typedef int32_t ClassId; + +const ClassId kInvalidInterfaceId = 0; + +struct InterfaceTableRecord { + ClassId id; + uint32_t vtableSize; + VTableElement const* vtable; +}; + +// This struct represents runtime type information and by itself is the compile time +// constant. +struct TypeInfo { + // Reference to self, to allow simple obtaining TypeInfo via meta-object. + const TypeInfo* typeInfo_; + // Extended RTTI, to retain cross-version debuggability, since ABI version 5 shall always be at the second position. + const ExtendedTypeInfo* extendedInfo_; + // Unused field. + uint32_t unused_; + // Negative value marks array class/string, and it is negated element size. + int32_t instanceSize_; + // Must be pointer to Any for array classes, and null for Any. + const TypeInfo* superType_; + // All object reference fields inside this object. + const int32_t* objOffsets_; + // Count of object reference fields inside this object. + // 1 for kotlin.Array to mark it as non-leaf. + int32_t objOffsetsCount_; + const TypeInfo* const* implementedInterfaces_; + int32_t implementedInterfacesCount_; + // Null for abstract classes and interfaces. + const MethodTableRecord* openMethods_; + uint32_t openMethodsCount_; + int32_t interfaceTableSize_; + InterfaceTableRecord const* interfaceTable_; + + // String for the fully qualified dot-separated name of the package containing class, + // or `null` if the class is local or anonymous. + ObjHeader* packageName_; + + // String for the qualified class name relative to the containing package + // (e.g. TopLevel.Nested1.Nested2), or simple class name if it is local, + // or `null` if the class is anonymous. + ObjHeader* relativeName_; + + // Various flags. + int32_t flags_; + + // Class id built with the whole class hierarchy taken into account. The details are in ClassLayoutBuilder. + ClassId classId_; + +#if KONAN_TYPE_INFO_HAS_WRITABLE_PART + WritableTypeInfo* writableInfo_; +#endif + + // Null-terminated array. + const AssociatedObjectTableRecord* associatedObjects; + + // vtable starts just after declared contents of the TypeInfo: + // void* const vtable_[]; +#ifdef __cplusplus + inline VTableElement const* vtable() const { + return reinterpret_cast(this + 1); + } + + inline VTableElement* vtable() { + return reinterpret_cast(this + 1); + } +#endif +}; + +#ifdef __cplusplus +extern "C" { +#endif +// Find open method by its hash. Other methods are resolved in compile-time. +// Note, that we use attribute const, which assumes function doesn't +// dereference global memory, while this function does. However, it seems +// to be safe, as actual result of this computation depends only on 'type_info' +// and 'hash' numeric values and doesn't really depends on global memory state +// (as TypeInfo is compile time constant and type info pointers are stable). +void* LookupOpenMethod(const TypeInfo* info, MethodNameHash nameSignature) RUNTIME_CONST; + +InterfaceTableRecord const* LookupInterfaceTableRecord(InterfaceTableRecord const* interfaceTable, + int interfaceTableSize, ClassId interfaceId) RUNTIME_CONST; + +#ifdef __cplusplus +} // extern "C" +#endif + +#endif // RUNTIME_TYPEINFO_H diff --git a/kotlin-native/runtime/src/main/cpp/Types.cpp b/kotlin-native/runtime/src/main/cpp/Types.cpp new file mode 100644 index 00000000000..b7defd21d51 --- /dev/null +++ b/kotlin-native/runtime/src/main/cpp/Types.cpp @@ -0,0 +1,111 @@ +/* + * Copyright 2010-2017 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "Types.h" +#include "Exceptions.h" + +extern "C" { + +KBoolean IsInstance(const ObjHeader* obj, const TypeInfo* type_info) { + // We assume null check is handled by caller. + RuntimeAssert(obj != nullptr, "must not be null"); + const TypeInfo* obj_type_info = obj->type_info(); + // If it is an interface - check in list of implemented interfaces. + if ((type_info->flags_ & TF_INTERFACE) != 0) { + for (int i = 0; i < obj_type_info->implementedInterfacesCount_; ++i) { + if (obj_type_info->implementedInterfaces_[i] == type_info) { + return 1; + } + } + return 0; + } + while (obj_type_info != nullptr && obj_type_info != type_info) { + obj_type_info = obj_type_info->superType_; + } + return obj_type_info != nullptr; +} + +KBoolean IsInstanceOfClassFast(const ObjHeader* obj, int32_t lo, int32_t hi) { + // We assume null check is handled by caller. + RuntimeAssert(obj != nullptr, "must not be null"); + const TypeInfo* obj_type_info = obj->type_info(); + // Super type's interval should contain our interval. + return obj_type_info->classId_ >= lo && obj_type_info->classId_ <= hi; +} + +KBoolean IsArray(KConstRef obj) { + RuntimeAssert(obj != nullptr, "Object must not be null"); + return obj->type_info()->instanceSize_ < 0; +} + +KBoolean Kotlin_TypeInfo_isInstance(KConstRef obj, KNativePtr typeInfo) { + return IsInstance(obj, reinterpret_cast(typeInfo)); +} + +OBJ_GETTER(Kotlin_TypeInfo_getPackageName, KNativePtr typeInfo) { + RETURN_OBJ(reinterpret_cast(typeInfo)->packageName_); +} + +OBJ_GETTER(Kotlin_TypeInfo_getRelativeName, KNativePtr typeInfo) { + RETURN_OBJ(reinterpret_cast(typeInfo)->relativeName_); +} + +struct AssociatedObjectTableRecord { + const TypeInfo* key; + OBJ_GETTER0((*getAssociatedObjectInstance)); +}; + +OBJ_GETTER(Kotlin_TypeInfo_findAssociatedObject, KNativePtr typeInfo, KNativePtr key) { + const AssociatedObjectTableRecord* associatedObjects = reinterpret_cast(typeInfo)->associatedObjects; + if (associatedObjects == nullptr) { + RETURN_OBJ(nullptr); + } + + for (int index = 0; associatedObjects[index].key != nullptr; ++index) { + if (associatedObjects[index].key == key) { + RETURN_RESULT_OF0(associatedObjects[index].getAssociatedObjectInstance); + } + } + + RETURN_OBJ(nullptr); +} + +bool IsSubInterface(const TypeInfo* thiz, const TypeInfo* other) { + for (int i = 0; i < thiz->implementedInterfacesCount_; ++i) { + if (thiz->implementedInterfaces_[i] == other) { + return true; + } + } + + return false; +} + +KVector4f Kotlin_Vector4f_of(KFloat f0, KFloat f1, KFloat f2, KFloat f3) { + return {f0, f1, f2, f3}; +} + +/* + * In the current design all simd types are mapped internally to floating type, e.g. <4 x float>. + * However, some platforms (ex. arm32) have different calling convention for <4 x float> and <4 x i32>. + * To avoid illegal bitcast from/to function types the following function + * return type MUST be <4 x float> and explicit type cast is done on the variable type. + */ +KVector4f Kotlin_Vector4i32_of(KInt f0, KInt f1, KInt f2, KInt f3) { + KInt __attribute__ ((__vector_size__(16))) v4i = {f0, f1, f2, f3}; + return (KVector4f)v4i; +} + +} // extern "C" diff --git a/kotlin-native/runtime/src/main/cpp/Types.h b/kotlin-native/runtime/src/main/cpp/Types.h new file mode 100644 index 00000000000..d380584d206 --- /dev/null +++ b/kotlin-native/runtime/src/main/cpp/Types.h @@ -0,0 +1,121 @@ +/* + * Copyright 2010-2017 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef RUNTIME_TYPES_H +#define RUNTIME_TYPES_H + +#include + +#if (KONAN_WASM || KONAN_ZEPHYR) && !defined(assert) +// assert() is needed by STLport. +#define assert(cond) if (!(cond)) abort() +#endif + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "Alloc.h" +#include "Common.h" +#include "Memory.h" +#include "TypeInfo.h" + +// Note that almost all types are signed. +typedef bool KBoolean; +typedef int8_t KByte; +typedef uint16_t KChar; +typedef int16_t KShort; +typedef int32_t KInt; +typedef int64_t KLong; +typedef uint8_t KUByte; +typedef uint16_t KUShort; +typedef uint32_t KUInt; +typedef uint64_t KULong; +typedef float KFloat; +typedef double KDouble; +typedef void* KNativePtr; +typedef KFloat __attribute__ ((__vector_size__ (16))) KVector4f; + +typedef const void* KConstNativePtr; + +typedef ObjHeader* KRef; +typedef const ObjHeader* KConstRef; +typedef const ArrayHeader* KString; + +// Definitions of STL classes used inside Konan runtime. +typedef std::basic_string, + KonanAllocator> KStdString; +template +using KStdDeque = std::deque>; +template +using KStdUnorderedMap = std::unordered_map, std::equal_to, + KonanAllocator>>; +template +using KStdUnorderedSet = std::unordered_set, std::equal_to, + KonanAllocator>; +template> +using KStdOrderedSet = std::set>; +template> +using KStdOrderedMap = std::map>>; +template +using KStdVector = std::vector>; +template +using KStdList = std::list>; + +#ifdef __cplusplus +extern "C" { +#endif + +extern const TypeInfo* theAnyTypeInfo; +extern const TypeInfo* theArrayTypeInfo; +extern const TypeInfo* theBooleanArrayTypeInfo; +extern const TypeInfo* theByteArrayTypeInfo; +extern const TypeInfo* theCharArrayTypeInfo; +extern const TypeInfo* theDoubleArrayTypeInfo; +extern const TypeInfo* theForeignObjCObjectTypeInfo; +extern const TypeInfo* theIntArrayTypeInfo; +extern const TypeInfo* theLongArrayTypeInfo; +extern const TypeInfo* theNativePtrArrayTypeInfo; +extern const TypeInfo* theFloatArrayTypeInfo; +extern const TypeInfo* theForeignObjCObjectTypeInfo; +extern const TypeInfo* theFreezableAtomicReferenceTypeInfo; +extern const TypeInfo* theObjCObjectWrapperTypeInfo; +extern const TypeInfo* theOpaqueFunctionTypeInfo; +extern const TypeInfo* theShortArrayTypeInfo; +extern const TypeInfo* theStringTypeInfo; +extern const TypeInfo* theThrowableTypeInfo; +extern const TypeInfo* theUnitTypeInfo; +extern const TypeInfo* theWorkerBoundReferenceTypeInfo; +extern const TypeInfo* theCleanerImplTypeInfo; + +KBoolean IsInstance(const ObjHeader* obj, const TypeInfo* type_info) RUNTIME_PURE; +KBoolean IsInstanceOfClassFast(const ObjHeader* obj, int32_t lo, int32_t hi) RUNTIME_PURE; +void CheckCast(const ObjHeader* obj, const TypeInfo* type_info); +KBoolean IsArray(KConstRef obj) RUNTIME_PURE; +bool IsSubInterface(const TypeInfo* thiz, const TypeInfo* other) RUNTIME_PURE; + +#ifdef __cplusplus +} +#endif + +#endif // RUNTIME_TYPES_H diff --git a/kotlin-native/runtime/src/main/cpp/Utils.h b/kotlin-native/runtime/src/main/cpp/Utils.h new file mode 100644 index 00000000000..ae3e4952c7e --- /dev/null +++ b/kotlin-native/runtime/src/main/cpp/Utils.h @@ -0,0 +1,55 @@ +/* + * Copyright 2010-2017 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include "KAssert.h" + +class SimpleMutex { + private: + int32_t atomicInt = 0; + + public: + void lock() { + while (!__sync_bool_compare_and_swap(&atomicInt, 0, 1)) { + // TODO: yield. + } + } + + void unlock() { + if (!__sync_bool_compare_and_swap(&atomicInt, 1, 0)) { + RuntimeAssert(false, "Unable to unlock"); + } + } +}; + +// TODO: use std::lock_guard instead? +template +class LockGuard { + public: + explicit LockGuard(Mutex& mutex_) : mutex(mutex_) { + mutex.lock(); + } + + ~LockGuard() { + mutex.unlock(); + } + + private: + Mutex& mutex; + + LockGuard(const LockGuard&) = delete; + LockGuard& operator=(const LockGuard&) = delete; +}; diff --git a/kotlin-native/runtime/src/main/cpp/Weak.cpp b/kotlin-native/runtime/src/main/cpp/Weak.cpp new file mode 100644 index 00000000000..2aca75da176 --- /dev/null +++ b/kotlin-native/runtime/src/main/cpp/Weak.cpp @@ -0,0 +1,106 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "Weak.h" + +#include "Memory.h" +#include "Types.h" + +namespace { + +// TODO: an ugly hack with fixed layout. +struct WeakReferenceCounter { + ObjHeader header; + KRef referred; + KInt lock; + KInt cookie; +}; + +inline WeakReferenceCounter* asWeakReferenceCounter(ObjHeader* obj) { + return reinterpret_cast(obj); +} + +#if !KONAN_NO_THREADS + +inline void lock(int32_t* address) { + RuntimeAssert(*address == 0 || *address == 1, "Incorrect lock state"); + while (__sync_val_compare_and_swap(address, 0, 1) == 1); +} + +inline void unlock(int32_t* address) { + int old = __sync_val_compare_and_swap(address, 1, 0); + RuntimeAssert(old == 1, "Incorrect lock state"); +} + +#endif + +} // namespace + +extern "C" { + +OBJ_GETTER(makeWeakReferenceCounter, void*); +OBJ_GETTER(makeObjCWeakReferenceImpl, void*); +OBJ_GETTER(makePermanentWeakReferenceImpl, ObjHeader*); + +// See Weak.kt for implementation details. +// Retrieve link on the counter object. +OBJ_GETTER(Konan_getWeakReferenceImpl, ObjHeader* referred) { + if (referred->permanent()) { + RETURN_RESULT_OF(makePermanentWeakReferenceImpl, referred); + } + +#if KONAN_OBJC_INTEROP + if (IsInstance(referred, theObjCObjectWrapperTypeInfo)) { + RETURN_RESULT_OF(makeObjCWeakReferenceImpl, referred->GetAssociatedObject()); + } +#endif // KONAN_OBJC_INTEROP + + ObjHeader** weakCounterLocation = referred->GetWeakCounterLocation(); + if (*weakCounterLocation == nullptr) { + ObjHolder counterHolder; + // Cast unneeded, just to emphasize we store an object reference as void*. + ObjHeader* counter = makeWeakReferenceCounter(reinterpret_cast(referred), counterHolder.slot()); + UpdateHeapRefIfNull(weakCounterLocation, counter); + } + RETURN_OBJ(*weakCounterLocation); +} + +// Materialize a weak reference to either null or the real reference. +OBJ_GETTER(Konan_WeakReferenceCounter_get, ObjHeader* counter) { + ObjHeader** referredAddress = &asWeakReferenceCounter(counter)->referred; +#if KONAN_NO_THREADS + RETURN_OBJ(*referredAddress); +#else + auto* weakCounter = asWeakReferenceCounter(counter); + RETURN_RESULT_OF(ReadHeapRefLocked, referredAddress, &weakCounter->lock, &weakCounter->cookie); +#endif +} + +void WeakReferenceCounterClear(ObjHeader* counter) { + ObjHeader** referredAddress = &asWeakReferenceCounter(counter)->referred; + // Note, that we don't do UpdateRef here, as reference is weak. +#if KONAN_NO_THREADS + *referredAddress = nullptr; +#else + int32_t* lockAddress = &asWeakReferenceCounter(counter)->lock; + // Spinlock. + lock(lockAddress); + *referredAddress = nullptr; + unlock(lockAddress); +#endif +} + +} // extern "C" diff --git a/kotlin-native/runtime/src/main/cpp/Weak.h b/kotlin-native/runtime/src/main/cpp/Weak.h new file mode 100644 index 00000000000..00054883cbf --- /dev/null +++ b/kotlin-native/runtime/src/main/cpp/Weak.h @@ -0,0 +1,18 @@ +/* + * Copyright 2010-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +#ifndef RUNTIME_WEAK_H +#define RUNTIME_WEAK_H + +#include "Memory.h" + +extern "C" { + +// Atomically clears counter object reference. +void WeakReferenceCounterClear(ObjHeader* counter); + +} // extern "C" + +#endif // RUNTIME_WEAK_H diff --git a/kotlin-native/runtime/src/main/cpp/Worker.cpp b/kotlin-native/runtime/src/main/cpp/Worker.cpp new file mode 100644 index 00000000000..1da5f31ee9d --- /dev/null +++ b/kotlin-native/runtime/src/main/cpp/Worker.cpp @@ -0,0 +1,1069 @@ +/* + * Copyright 2010-2017 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef KONAN_NO_THREADS +#define WITH_WORKERS 1 +#endif + +#include +#include +#include + +#if WITH_WORKERS +#include +#include "PthreadUtils.h" +#endif + +#include "Alloc.h" +#include "Exceptions.h" +#include "KAssert.h" +#include "Memory.h" +#include "Runtime.h" +#include "Types.h" +#include "Worker.h" + +extern "C" { + +RUNTIME_NORETURN void ThrowWorkerInvalidState(); +RUNTIME_NORETURN void ThrowWorkerUnsupported(); +OBJ_GETTER(WorkerLaunchpad, KRef); + +} // extern "C" + +#if WITH_WORKERS + +namespace { + +class Future; + +enum { + INVALID = 0, + SCHEDULED = 1, + COMPUTED = 2, + CANCELLED = 3, + THROWN = 4 +}; + +enum { + CHECKED = 0, + UNCHECKED = 1 +}; + +enum JobKind { + JOB_NONE = 0, + JOB_TERMINATE = 1, + // Order is important in sense that all job kinds after this one is considered + // processed for APIs returning request process status. + JOB_REGULAR = 2, + JOB_EXECUTE_AFTER = 3, +}; + +enum class WorkerKind { + kNative, // Workers created using Worker.start public API. + kOther, // Any other kind of workers. +}; + +struct Job { + enum JobKind kind; + union { + struct { + KRef (*function)(KRef, ObjHeader**); + KNativePtr argument; + Future* future; + KInt transferMode; + } regularJob; + + struct { + Future* future; + bool waitDelayed; + } terminationRequest; + + struct { + KNativePtr operation; + uint64_t whenExecute; + } executeAfter; + }; +}; + +struct JobCompare { + bool operator() (const Job& lhs, const Job& rhs) const { + RuntimeAssert(lhs.kind == JOB_EXECUTE_AFTER && rhs.kind == JOB_EXECUTE_AFTER, "Must be delayed jobs"); + return lhs.executeAfter.whenExecute < rhs.executeAfter.whenExecute; + } +}; + +typedef KStdOrderedSet DelayedJobSet; + +} // namespace + +class Worker { + public: + Worker(KInt id, bool errorReporting, KRef customName, WorkerKind kind) + : id_(id), + kind_(kind), + errorReporting_(errorReporting) { + name_ = customName != nullptr ? CreateStablePointer(customName) : nullptr; + pthread_mutex_init(&lock_, nullptr); + pthread_cond_init(&cond_, nullptr); + } + + ~Worker(); + + void startEventLoop(); + + void putJob(Job job, bool toFront); + void putDelayedJob(Job job); + + bool waitDelayed(bool blocking); + + Job getJob(bool blocking); + + KLong checkDelayedLocked(); + + bool waitForQueueLocked(KLong timeoutMicroseconds, KLong* remaining); + + JobKind processQueueElement(bool blocking); + + bool park(KLong timeoutMicroseconds, bool process); + + KInt id() const { return id_; } + + bool errorReporting() const { return errorReporting_; } + + KNativePtr name() const { return name_; } + + WorkerKind kind() const { return kind_; } + + pthread_t thread() const { return thread_; } + + private: + KInt id_; + WorkerKind kind_; + KStdDeque queue_; + DelayedJobSet delayed_; + // Stable pointer with worker's name. + KNativePtr name_; + // Lock and condition for waiting on the queue. + pthread_mutex_t lock_; + pthread_cond_t cond_; + // If errors to be reported on console. + bool errorReporting_; + bool terminated_ = false; + pthread_t thread_ = 0; +}; + +#endif // WITH_WORKERS + +namespace { + +#if WITH_WORKERS + +THREAD_LOCAL_VARIABLE Worker* g_worker = nullptr; + +KNativePtr transfer(ObjHolder* holder, KInt mode) { + void* result = CreateStablePointer(holder->obj()); + if (!ClearSubgraphReferences(holder->obj(), mode == CHECKED)) { + DisposeStablePointer(result); + ThrowWorkerInvalidState(); + } + holder->clear(); + return result; +} + +class Locker { + public: + explicit Locker(pthread_mutex_t* lock) : lock_(lock) { + pthread_mutex_lock(lock_); + } + ~Locker() { + pthread_mutex_unlock(lock_); + } + + private: + pthread_mutex_t* lock_; +}; + +class Future { + public: + Future(KInt id) : state_(SCHEDULED), id_(id) { + pthread_mutex_init(&lock_, nullptr); + pthread_cond_init(&cond_, nullptr); + } + + ~Future() { + clear(); + pthread_mutex_destroy(&lock_); + pthread_cond_destroy(&cond_); + } + + void clear() { + Locker locker(&lock_); + if (result_ != nullptr) { + // No one cared to consume result - dispose it. + DisposeStablePointer(result_); + result_ = nullptr; + } + } + + OBJ_GETTER0(consumeResultUnlocked) { + Locker locker(&lock_); + while (state_ == SCHEDULED) { + pthread_cond_wait(&cond_, &lock_); + } + // TODO: maybe use message from exception? + if (state_ == THROWN) + ThrowIllegalStateException(); + auto result = AdoptStablePointer(result_, OBJ_RESULT); + result_ = nullptr; + return result; + } + + void storeResultUnlocked(KNativePtr result, bool ok); + + void cancelUnlocked(); + + // Those are called with the lock taken. + KInt state() const { return state_; } + KInt id() const { return id_; } + + private: + // State of future execution. + KInt state_; + // Integer id of the future. + KInt id_; + // Stable pointer with future's result. + KNativePtr result_; + // Lock and condition for waiting on the future. + pthread_mutex_t lock_; + pthread_cond_t cond_; +}; + +class State { + public: + State() { + pthread_mutex_init(&lock_, nullptr); + pthread_cond_init(&cond_, nullptr); + + currentWorkerId_ = 1; + currentFutureId_ = 1; + currentVersion_ = 0; + } + + ~State() { + // TODO: some sanity check here? + pthread_mutex_destroy(&lock_); + pthread_cond_destroy(&cond_); + } + + Worker* addWorkerUnlocked(bool errorReporting, KRef customName, WorkerKind kind) { + Worker* worker = nullptr; + { + Locker locker(&lock_); + worker = konanConstructInstance(nextWorkerId(), errorReporting, customName, kind); + if (worker == nullptr) return nullptr; + workers_[worker->id()] = worker; + } + GC_RegisterWorker(worker); + return worker; + } + + void removeWorkerUnlocked(KInt id) { + Locker locker(&lock_); + auto it = workers_.find(id); + if (it == workers_.end()) return; + Worker* worker = it->second; + if (worker->kind() == WorkerKind::kNative) { + terminating_native_workers_[id] = worker->thread(); + } + workers_.erase(it); + } + + void destroyWorkerUnlocked(Worker* worker) { + { + Locker locker(&lock_); + auto id = worker->id(); + auto it = workers_.find(id); + if (it != workers_.end()) { + workers_.erase(it); + } + } + GC_UnregisterWorker(worker); + konanDestructInstance(worker); + } + + Future* addJobToWorkerUnlocked( + KInt id, KNativePtr jobFunction, KNativePtr jobArgument, bool toFront, KInt transferMode) { + Future* future = nullptr; + Worker* worker = nullptr; + Locker locker(&lock_); + + auto it = workers_.find(id); + if (it == workers_.end()) return nullptr; + worker = it->second; + + future = konanConstructInstance(nextFutureId()); + futures_[future->id()] = future; + + Job job; + if (jobFunction == nullptr) { + job.kind = JOB_TERMINATE; + job.terminationRequest.future = future; + job.terminationRequest.waitDelayed = !toFront; + } else { + job.kind = JOB_REGULAR; + job.regularJob.function = reinterpret_cast(jobFunction); + job.regularJob.argument = jobArgument; + job.regularJob.future = future; + job.regularJob.transferMode = transferMode; + } + + worker->putJob(job, toFront); + + return future; + } + + bool executeJobAfterInWorkerUnlocked(KInt id, KRef operation, KLong afterMicroseconds) { + Worker* worker = nullptr; + Locker locker(&lock_); + + RuntimeAssert(afterMicroseconds >= 0, "afterMicroseconds cannot be negative"); + + auto it = workers_.find(id); + if (it == workers_.end()) { + return false; + } + worker = it->second; + Job job; + job.kind = JOB_EXECUTE_AFTER; + job.executeAfter.operation = CreateStablePointer(operation); + if (afterMicroseconds == 0) { + worker->putJob(job, false); + } else { + job.executeAfter.whenExecute = konan::getTimeMicros() + afterMicroseconds; + worker->putDelayedJob(job); + } + return true; + } + + bool scheduleJobInWorkerUnlocked(KInt id, KNativePtr operationStablePtr) { + Worker* worker = nullptr; + Locker locker(&lock_); + + auto it = workers_.find(id); + if (it == workers_.end()) { + return false; + } + worker = it->second; + + Job job; + job.kind = JOB_EXECUTE_AFTER; + job.executeAfter.operation = operationStablePtr; + worker->putJob(job, false); + return true; + } + + // Returns `true` if something was indeed processed. + bool processQueueUnlocked(KInt id) { + // Can only process queue of the current worker. + if (::g_worker == nullptr || id != ::g_worker->id()) ThrowWorkerInvalidState(); + JobKind kind = ::g_worker->processQueueElement(false); + return kind != JOB_NONE && kind != JOB_TERMINATE; + } + + bool parkUnlocked(KInt id, KLong timeoutMicroseconds, KBoolean process) { + // Can only park current worker. + if (::g_worker == nullptr || id != ::g_worker->id()) ThrowWorkerInvalidState(); + return ::g_worker->park(timeoutMicroseconds, process); + } + + KInt stateOfFutureUnlocked(KInt id) { + Locker locker(&lock_); + auto it = futures_.find(id); + if (it == futures_.end()) return INVALID; + return it->second->state(); + } + + OBJ_GETTER(consumeFutureUnlocked, KInt id) { + Future* future = nullptr; + { + Locker locker(&lock_); + auto it = futures_.find(id); + if (it == futures_.end()) ThrowWorkerInvalidState(); + future = it->second; + + } + + KRef result = future->consumeResultUnlocked(OBJ_RESULT); + + { + Locker locker(&lock_); + auto it = futures_.find(id); + if (it != futures_.end()) { + futures_.erase(it); + konanDestructInstance(future); + } + } + + return result; + } + + OBJ_GETTER(getWorkerNameUnlocked, KInt id) { + ObjHolder nameHolder; + { + Locker locker(&lock_); + auto it = workers_.find(id); + if (it == workers_.end()) { + ThrowWorkerInvalidState(); + } + DerefStablePointer(it->second->name(), nameHolder.slot()); + } + RETURN_OBJ(nameHolder.obj()); + } + + KBoolean waitForAnyFuture(KInt version, KInt millis) { + Locker locker(&lock_); + if (version != currentVersion_) return false; + + if (millis < 0) { + pthread_cond_wait(&cond_, &lock_); + return true; + } + + uint64_t nsDelta = millis * 1000000LL; + WaitOnCondVar(&cond_, &lock_, nsDelta); + return true; + } + + void signalAnyFuture() { + { + Locker locker(&lock_); + currentVersion_++; + } + pthread_cond_broadcast(&cond_); + } + + KInt versionToken() { + Locker locker(&lock_); + return currentVersion_; + } + + // All those called with lock taken. + KInt nextWorkerId() { return currentWorkerId_++; } + KInt nextFutureId() { return currentFutureId_++; } + + void destroyWorkerThreadDataUnlocked(KInt id) { + Locker locker(&lock_); + auto it = terminating_native_workers_.find(id); + if (it == terminating_native_workers_.end()) return; + // If this worker was not joined, detach it to free resources. + pthread_detach(it->second); + terminating_native_workers_.erase(it); + } + + template + void waitNativeWorkersTerminationUnlocked(bool checkLeaks, F waitForWorker) { + std::vector> workersToWait; + { + Locker locker(&lock_); + + if (checkLeaks) { + checkNativeWorkersLeakLocked(); + } + + for (auto& kvp : terminating_native_workers_) { + RuntimeAssert(!pthread_equal(kvp.second, pthread_self()), "Native worker is joining with itself"); + if (waitForWorker(kvp.first)) { + workersToWait.push_back(kvp); + } + } + for (auto worker : workersToWait) { + terminating_native_workers_.erase(worker.first); + } + } + + for (auto worker : workersToWait) { + pthread_join(worker.second, nullptr); + } + } + + void checkNativeWorkersLeakLocked() { + size_t remainingNativeWorkers = 0; + for (const auto& kvp : workers_) { + Worker* worker = kvp.second; + if (worker->kind() == WorkerKind::kNative) { + ++remainingNativeWorkers; + } + } + + if (remainingNativeWorkers != 0) { + konan::consoleErrorf( + "Unfinished workers detected, %lu workers leaked!\n" + "Use `Platform.isMemoryLeakCheckerActive = false` to avoid this check.\n", + remainingNativeWorkers); + konan::consoleFlush(); + konan::abort(); + } + } + + private: + pthread_mutex_t lock_; + pthread_cond_t cond_; + KStdUnorderedMap futures_; + KStdUnorderedMap workers_; + KStdUnorderedMap terminating_native_workers_; + KInt currentWorkerId_; + KInt currentFutureId_; + KInt currentVersion_; +}; + +State* theState() { + static State* state = nullptr; + + if (state != nullptr) { + return state; + } + + State* result = konanConstructInstance(); + + State* old = __sync_val_compare_and_swap(&state, nullptr, result); + if (old != nullptr) { + konanDestructInstance(result); + // Someone else inited this data. + return old; + } + return state; +} + +void Future::storeResultUnlocked(KNativePtr result, bool ok) { + { + Locker locker(&lock_); + state_ = ok ? COMPUTED : THROWN; + result_ = result; + // Beware here: although manual clearly says that pthread_cond_broadcast() could be called outside + // of the taken lock, it's not on macOS (as of 10.13.1). If moved outside of the lock, + // some notifications are missing. + pthread_cond_broadcast(&cond_); + } + theState()->signalAnyFuture(); +} + +void Future::cancelUnlocked() { + { + Locker locker(&lock_); + state_ = CANCELLED; + result_ = nullptr; + pthread_cond_broadcast(&cond_); + } + theState()->signalAnyFuture(); +} + +// Defined in RuntimeUtils.kt. +extern "C" void ReportUnhandledException(KRef e); + +KInt startWorker(KBoolean errorReporting, KRef customName) { + Worker* worker = theState()->addWorkerUnlocked(errorReporting != 0, customName, WorkerKind::kNative); + if (worker == nullptr) return -1; + worker->startEventLoop(); + return worker->id(); +} + +KInt currentWorker() { + if (g_worker == nullptr) ThrowWorkerInvalidState(); + return ::g_worker->id(); +} + +KInt execute(KInt id, KInt transferMode, KRef producer, KNativePtr jobFunction) { + ObjHolder holder; + WorkerLaunchpad(producer, holder.slot()); + KNativePtr jobArgument = transfer(&holder, transferMode); + Future* future = theState()->addJobToWorkerUnlocked(id, jobFunction, jobArgument, false, transferMode); + if (future == nullptr) ThrowWorkerInvalidState(); + return future->id(); +} + +void executeAfter(KInt id, KRef job, KLong afterMicroseconds) { + if (!theState()->executeJobAfterInWorkerUnlocked(id, job, afterMicroseconds)) + ThrowWorkerInvalidState(); +} + +KBoolean processQueue(KInt id) { + return theState()->processQueueUnlocked(id); +} + +KBoolean park(KInt id, KLong timeoutMicroseconds, KBoolean process) { + return theState()->parkUnlocked(id, timeoutMicroseconds, process); +} + +KInt stateOfFuture(KInt id) { + return theState()->stateOfFutureUnlocked(id); +} + +OBJ_GETTER(consumeFuture, KInt id) { + RETURN_RESULT_OF(theState()->consumeFutureUnlocked, id); +} + +OBJ_GETTER(getWorkerName, KInt id) { + RETURN_RESULT_OF(theState()->getWorkerNameUnlocked, id); +} + +KInt requestTermination(KInt id, KBoolean processScheduledJobs) { + Future* future = theState()->addJobToWorkerUnlocked( + id, nullptr, nullptr, /* toFront = */ !processScheduledJobs, UNCHECKED); + if (future == nullptr) ThrowWorkerInvalidState(); + return future->id(); +} + +KBoolean waitForAnyFuture(KInt version, KInt millis) { + return theState()->waitForAnyFuture(version, millis); +} + +KInt versionToken() { + return theState()->versionToken(); +} + +OBJ_GETTER(attachObjectGraphInternal, KNativePtr stable) { + RETURN_RESULT_OF(AdoptStablePointer, stable); +} + +KNativePtr detachObjectGraphInternal(KInt transferMode, KRef producer) { + ObjHolder result; + WorkerLaunchpad(producer, result.slot()); + if (result.obj() != nullptr) { + return transfer(&result, transferMode); + } else { + return nullptr; + } +} + +#else + +KInt startWorker(KBoolean errorReporting, KRef customName) { + ThrowWorkerUnsupported(); +} + +KInt stateOfFuture(KInt id) { + ThrowWorkerUnsupported(); +} + +KInt execute(KInt id, KInt transferMode, KRef producer, KNativePtr jobFunction) { + ThrowWorkerUnsupported(); +} + +void executeAfter(KInt id, KRef job, KLong afterMicroseconds) { + ThrowWorkerUnsupported(); +} + +KBoolean processQueue(KInt id) { + ThrowWorkerUnsupported(); +} + +KBoolean park(KInt id, KLong timeoutMicroseconds, KBoolean process) { + ThrowWorkerUnsupported(); +} + +KInt currentWorker() { + ThrowWorkerUnsupported(); +} + +OBJ_GETTER(consumeFuture, KInt id) { + ThrowWorkerUnsupported(); +} + +OBJ_GETTER(getWorkerName, KInt id) { + ThrowWorkerUnsupported(); +} + +KInt requestTermination(KInt id, KBoolean processScheduledJobs) { + ThrowWorkerUnsupported(); +} + +KBoolean waitForAnyFuture(KInt versionToken, KInt millis) { + ThrowWorkerUnsupported(); +} + +KInt versionToken() { + ThrowWorkerUnsupported(); +} + +OBJ_GETTER(attachObjectGraphInternal, KNativePtr stable) { + ThrowWorkerUnsupported(); +} + +KNativePtr detachObjectGraphInternal(KInt transferMode, KRef producer) { + ThrowWorkerUnsupported(); +} + +#endif // WITH_WORKERS + +} // namespace + +KInt GetWorkerId(Worker* worker) { +#if WITH_WORKERS + return worker->id(); +#else + return 0; +#endif // WITH_WORKERS +} + +Worker* WorkerInit(KBoolean errorReporting) { +#if WITH_WORKERS + if (::g_worker != nullptr) return ::g_worker; + Worker* worker = theState()->addWorkerUnlocked(errorReporting != 0, nullptr, WorkerKind::kOther); + ::g_worker = worker; + return worker; +#else + return nullptr; +#endif // WITH_WORKERS +} + +void WorkerDeinit(Worker* worker) { +#if WITH_WORKERS + ::g_worker = nullptr; + theState()->destroyWorkerUnlocked(worker); +#endif // WITH_WORKERS +} + +void WorkerDestroyThreadDataIfNeeded(KInt id) { +#if WITH_WORKERS + theState()->destroyWorkerThreadDataUnlocked(id); +#endif +} + +void WaitNativeWorkersTermination() { +#if WITH_WORKERS + theState()->waitNativeWorkersTerminationUnlocked(true, [](KInt worker) { return true; }); +#endif +} + +void WaitNativeWorkerTermination(KInt id) { +#if WITH_WORKERS + theState()->waitNativeWorkersTerminationUnlocked(false, [id](KInt worker) { return worker == id; }); +#endif +} + +bool WorkerSchedule(KInt id, KNativePtr jobStablePtr) { +#if WITH_WORKERS + return theState()->scheduleJobInWorkerUnlocked(id, jobStablePtr); +#else + return false; +#endif // WITH_WORKERS +} + +#if WITH_WORKERS + +Worker::~Worker() { + // Cleanup jobs in the queue. + for (auto job : queue_) { + switch (job.kind) { + case JOB_REGULAR: + DisposeStablePointer(job.regularJob.argument); + job.regularJob.future->cancelUnlocked(); + break; + case JOB_EXECUTE_AFTER: { + // TODO: what do we do here? Shall we execute them? + DisposeStablePointer(job.executeAfter.operation); + break; + } + case JOB_TERMINATE: { + // TODO: any more processing here? + job.terminationRequest.future->cancelUnlocked(); + break; + } + case JOB_NONE: { + RuntimeCheck(false, "Cannot be in queue"); + break; + } + } + } + + for (auto job : delayed_) { + RuntimeAssert(job.kind == JOB_EXECUTE_AFTER, "Must be delayed"); + DisposeStablePointer(job.executeAfter.operation); + } + + if (name_ != nullptr) DisposeStablePointer(name_); + + pthread_mutex_destroy(&lock_); + pthread_cond_destroy(&cond_); +} + +namespace { + +void* workerRoutine(void* argument) { + Worker* worker = reinterpret_cast(argument); + + // Kotlin_initRuntimeIfNeeded calls WorkerInit that needs + // to see there's already a worker created for this thread. + ::g_worker = worker; + Kotlin_initRuntimeIfNeeded(); + + do { + if (worker->processQueueElement(true) == JOB_TERMINATE) break; + } while (true); + + // Runtime deinit callback could be called when TLS is already zeroed out, so clear memory + // here explicitly. to make sure leak detector properly works. + Kotlin_zeroOutTLSGlobals(); + + return nullptr; +} + +} // namespace + +void Worker::startEventLoop() { + pthread_create(&thread_, nullptr, workerRoutine, this); +} + +void Worker::putJob(Job job, bool toFront) { + Locker locker(&lock_); + if (toFront) + queue_.push_front(job); + else + queue_.push_back(job); + pthread_cond_signal(&cond_); +} + +void Worker::putDelayedJob(Job job) { + Locker locker(&lock_); + delayed_.insert(job); + pthread_cond_signal(&cond_); +} + +bool Worker::waitDelayed(bool blocking) { + Locker locker(&lock_); + if (delayed_.size() == 0) return false; + if (blocking) waitForQueueLocked(-1, nullptr); + return true; +} + +Job Worker::getJob(bool blocking) { + Locker locker(&lock_); + RuntimeAssert(!terminated_, "Must not be terminated"); + if (queue_.size() == 0 && !blocking) return Job { .kind = JOB_NONE }; + waitForQueueLocked(-1, nullptr); + auto result = queue_.front(); + queue_.pop_front(); + return result; +} + +KLong Worker::checkDelayedLocked() { + if (delayed_.size() == 0) { + return -1; + } + auto it = delayed_.begin(); + auto job = *it; + RuntimeAssert(job.kind == JOB_EXECUTE_AFTER, "Must be delayed job"); + auto now = konan::getTimeMicros(); + if (job.executeAfter.whenExecute <= now) { + delayed_.erase(it); + queue_.push_back(job); + return 0; + } else { + return job.executeAfter.whenExecute - now; + } +} + +bool Worker::waitForQueueLocked(KLong timeoutMicroseconds, KLong* remaining) { + while (queue_.size() == 0) { + KLong closestToRunMicroseconds = checkDelayedLocked(); + if (closestToRunMicroseconds == 0) { + continue; + } + if (timeoutMicroseconds >= 0) { + closestToRunMicroseconds = (timeoutMicroseconds < closestToRunMicroseconds || closestToRunMicroseconds < 0) + ? timeoutMicroseconds + : closestToRunMicroseconds; + } + if (closestToRunMicroseconds == 0) { + // Just no wait at all here. + } else if (closestToRunMicroseconds > 0) { + // Protect from potential overflow, cutting at 10_000_000 seconds, aka 115 days. + if (closestToRunMicroseconds > 10LL * 1000 * 1000 * 1000 * 1000) + closestToRunMicroseconds = 10LL * 1000 * 1000 * 1000 * 1000; + uint64_t nsDelta = closestToRunMicroseconds * 1000LL; + uint64_t microsecondsPassed = 0; + WaitOnCondVar(&cond_, &lock_, nsDelta, remaining ? µsecondsPassed : nullptr); + if (remaining) { + *remaining = timeoutMicroseconds - microsecondsPassed; + } + } else { + pthread_cond_wait(&cond_, &lock_); + if (remaining) *remaining = 0; + } + if (timeoutMicroseconds >= 0) return queue_.size() != 0; + } + return true; +} + +bool Worker::park(KLong timeoutMicroseconds, bool process) { + { + Locker locker(&lock_); + if (terminated_) { + return false; + } + auto arrived = false; + KLong remaining = timeoutMicroseconds; + do { + arrived = waitForQueueLocked(remaining, &remaining); + } while (remaining > 0 && !arrived); + if (!process) { + return arrived; + } + if (!arrived) { + return false; + } + } + return processQueueElement(false) >= JOB_REGULAR; +} + +JobKind Worker::processQueueElement(bool blocking) { + GC_CollectorCallback(this); + ObjHolder argumentHolder; + ObjHolder resultHolder; + if (terminated_) return JOB_TERMINATE; + Job job = getJob(blocking); + switch (job.kind) { + case JOB_NONE: { + break; + } + case JOB_TERMINATE: { + if (job.terminationRequest.waitDelayed) { + if (waitDelayed(blocking)) { + putJob(job, false); + return JOB_NONE; + } + } + terminated_ = true; + // Termination request, remove the worker and notify the future. + theState()->removeWorkerUnlocked(id()); + job.terminationRequest.future->storeResultUnlocked(nullptr, true); + break; + } + case JOB_EXECUTE_AFTER: { + ObjHolder operationHolder, dummyHolder; + KRef obj = DerefStablePointer(job.executeAfter.operation, operationHolder.slot()); + try { + WorkerLaunchpad(obj, dummyHolder.slot()); + } catch (ExceptionObjHolder& e) { + if (errorReporting()) + ReportUnhandledException(e.obj()); + } + DisposeStablePointer(job.executeAfter.operation); + break; + } + case JOB_REGULAR: { + KRef argument = AdoptStablePointer(job.regularJob.argument, argumentHolder.slot()); + KNativePtr result = nullptr; + bool ok = true; + try { + job.regularJob.function(argument, resultHolder.slot()); + argumentHolder.clear(); + // Transfer the result. + result = transfer(&resultHolder, job.regularJob.transferMode); + } catch (ExceptionObjHolder& e) { + ok = false; + if (errorReporting()) + ReportUnhandledException(e.obj()); + } + // Notify the future. + job.regularJob.future->storeResultUnlocked(result, ok); + break; + } + default: { + RuntimeCheck(false, "Must be exhaustive"); + } + } + return job.kind; +} + +#endif // WITH_WORKERS + +extern "C" { + +KInt Kotlin_Worker_startInternal(KBoolean noErrorReporting, KRef customName) { + return startWorker(noErrorReporting, customName); +} + +KInt Kotlin_Worker_currentInternal() { + return currentWorker(); +} + +KInt Kotlin_Worker_requestTerminationWorkerInternal(KInt id, KBoolean processScheduledJobs) { + return requestTermination(id, processScheduledJobs); +} + +KInt Kotlin_Worker_executeInternal(KInt id, KInt transferMode, KRef producer, KNativePtr job) { + return execute(id, transferMode, producer, job); +} + +void Kotlin_Worker_executeAfterInternal(KInt id, KRef job, KLong afterMicroseconds) { + executeAfter(id, job, afterMicroseconds); +} + +KBoolean Kotlin_Worker_processQueueInternal(KInt id) { + return processQueue(id); +} + +KBoolean Kotlin_Worker_parkInternal(KInt id, KLong timeoutMicroseconds, KBoolean process) { + return park(id, timeoutMicroseconds, process); +} + +OBJ_GETTER(Kotlin_Worker_getNameInternal, KInt id) { + RETURN_RESULT_OF(getWorkerName, id); +} + +KInt Kotlin_Worker_stateOfFuture(KInt id) { + return stateOfFuture(id); +} + +OBJ_GETTER(Kotlin_Worker_consumeFuture, KInt id) { + RETURN_RESULT_OF(consumeFuture, id); +} + +KBoolean Kotlin_Worker_waitForAnyFuture(KInt versionToken, KInt millis) { + return waitForAnyFuture(versionToken, millis); +} + +KInt Kotlin_Worker_versionToken() { + return versionToken(); +} + +OBJ_GETTER(Kotlin_Worker_attachObjectGraphInternal, KNativePtr stable) { + RETURN_RESULT_OF(attachObjectGraphInternal, stable); +} + +KNativePtr Kotlin_Worker_detachObjectGraphInternal(KInt transferMode, KRef producer) { + return detachObjectGraphInternal(transferMode, producer); +} + +void Kotlin_Worker_freezeInternal(KRef object) { + if (object != nullptr) + FreezeSubgraph(object); +} + +KBoolean Kotlin_Worker_isFrozenInternal(KRef object) { + return object == nullptr || isPermanentOrFrozen(object); +} + +void Kotlin_Worker_ensureNeverFrozen(KRef object) { + EnsureNeverFrozen(object); +} + +void Kotlin_Worker_waitTermination(KInt id) { + WaitNativeWorkerTermination(id); +} + +} // extern "C" diff --git a/kotlin-native/runtime/src/main/cpp/Worker.h b/kotlin-native/runtime/src/main/cpp/Worker.h new file mode 100644 index 00000000000..bb99194b61a --- /dev/null +++ b/kotlin-native/runtime/src/main/cpp/Worker.h @@ -0,0 +1,22 @@ +#ifndef RUNTIME_WORKER_H +#define RUNTIME_WORKER_H + +#include "Common.h" +#include "Types.h" + +class Worker; + +KInt GetWorkerId(Worker* worker); + +Worker* WorkerInit(KBoolean errorReporting); +void WorkerDeinit(Worker* worker); +// Clean up all associated thread state, if this was a native worker. +void WorkerDestroyThreadDataIfNeeded(KInt id); +// Wait until all terminating native workers finish termination. Expected to be called at most once. +void WaitNativeWorkersTermination(); +// Wait until terminating native worker `id` finishes termination. Expected to be called at most once for each worker. +void WaitNativeWorkerTermination(KInt id); +// Schedule the job without the result. +bool WorkerSchedule(KInt id, KNativePtr jobStablePtr); + +#endif // RUNTIME_WORKER_H diff --git a/kotlin-native/runtime/src/main/cpp/WorkerBoundReference.cpp b/kotlin-native/runtime/src/main/cpp/WorkerBoundReference.cpp new file mode 100644 index 00000000000..0012212b5d6 --- /dev/null +++ b/kotlin-native/runtime/src/main/cpp/WorkerBoundReference.cpp @@ -0,0 +1,57 @@ +/* + * Copyright 2010-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +#include "WorkerBoundReference.h" + +#include "Alloc.h" +#include "Memory.h" +#include "MemorySharedRefs.hpp" + +namespace { + +struct WorkerBoundReference { + ObjHeader header; + KRefSharedHolder* holder; +}; + +WorkerBoundReference* asWorkerBoundReference(KRef thiz) { + return reinterpret_cast(thiz); +} + +} // namespace + +RUNTIME_NOTHROW void DisposeWorkerBoundReference(KRef thiz) { + // DisposeSharedRef is only called when all references to thiz are gone. + // Can be null if WorkerBoundReference wasn't frozen. + if (auto* holder = asWorkerBoundReference(thiz)->holder) { + holder->dispose(); + konanDestructInstance(holder); + } +} + +// Defined in WorkerBoundReference.kt +extern "C" void Kotlin_WorkerBoundReference_freezeHook(KRef thiz); + +RUNTIME_NOTHROW void WorkerBoundReferenceFreezeHook(KRef thiz) { + Kotlin_WorkerBoundReference_freezeHook(thiz); +} + +extern "C" { + +KNativePtr Kotlin_WorkerBoundReference_create(KRef value) { + auto* holder = konanConstructInstance(); + holder->init(value); + return holder; +} + +OBJ_GETTER(Kotlin_WorkerBoundReference_deref, KNativePtr holder) { + RETURN_OBJ(reinterpret_cast(holder)->ref()); +} + +OBJ_GETTER(Kotlin_WorkerBoundReference_describe, KNativePtr holder) { + RETURN_RESULT_OF0(reinterpret_cast(holder)->describe); +} + +} diff --git a/kotlin-native/runtime/src/main/cpp/WorkerBoundReference.h b/kotlin-native/runtime/src/main/cpp/WorkerBoundReference.h new file mode 100644 index 00000000000..c1c7c51890e --- /dev/null +++ b/kotlin-native/runtime/src/main/cpp/WorkerBoundReference.h @@ -0,0 +1,16 @@ +/* + * Copyright 2010-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +#ifndef RUNTIME_SHAREDREF_H +#define RUNTIME_SHAREDREF_H + +#include "Common.h" +#include "Types.h" + +RUNTIME_NOTHROW void DisposeWorkerBoundReference(KRef thiz); + +RUNTIME_NOTHROW void WorkerBoundReferenceFreezeHook(KRef thiz); + +#endif // RUNTIME_SHAREDREF_H diff --git a/kotlin-native/runtime/src/main/cpp/dlmalloc/malloc.cpp b/kotlin-native/runtime/src/main/cpp/dlmalloc/malloc.cpp new file mode 100644 index 00000000000..4cccd167fa7 --- /dev/null +++ b/kotlin-native/runtime/src/main/cpp/dlmalloc/malloc.cpp @@ -0,0 +1,6309 @@ +// Uses GNU extension on null pointer arithmetic. +#pragma clang diagnostic ignored "-Wnull-pointer-arithmetic" +/* + This is a version (aka dlmalloc) of malloc/free/realloc written by + Doug Lea and released to the public domain, as explained at + http://creativecommons.org/publicdomain/zero/1.0/ Send questions, + comments, complaints, performance data, etc to dl@cs.oswego.edu + +* Version 2.8.6 Wed Aug 29 06:57:58 2012 Doug Lea + Note: There may be an updated version of this malloc obtainable at + ftp://gee.cs.oswego.edu/pub/misc/malloc.c + Check before installing! + +* Quickstart + + This library is all in one file to simplify the most common usage: + ftp it, compile it (-O3), and link it into another program. All of + the compile-time options default to reasonable values for use on + most platforms. You might later want to step through various + compile-time and dynamic tuning options. + + For convenience, an include file for code using this malloc is at: + ftp://gee.cs.oswego.edu/pub/misc/malloc-2.8.6.h + You don't really need this .h file unless you call functions not + defined in your system include files. The .h file contains only the + excerpts from this file needed for using this malloc on ANSI C/C++ + systems, so long as you haven't changed compile-time options about + naming and tuning parameters. If you do, then you can create your + own malloc.h that does include all settings by cutting at the point + indicated below. Note that you may already by default be using a C + library containing a malloc that is based on some version of this + malloc (for example in linux). You might still want to use the one + in this file to customize settings or to avoid overheads associated + with library versions. + +* Vital statistics: + + Supported pointer/size_t representation: 4 or 8 bytes + size_t MUST be an unsigned type of the same width as + pointers. (If you are using an ancient system that declares + size_t as a signed type, or need it to be a different width + than pointers, you can use a previous release of this malloc + (e.g. 2.7.2) supporting these.) + + Alignment: 8 bytes (minimum) + This suffices for nearly all current machines and C compilers. + However, you can define MALLOC_ALIGNMENT to be wider than this + if necessary (up to 128bytes), at the expense of using more space. + + Minimum overhead per allocated chunk: 4 or 8 bytes (if 4byte sizes) + 8 or 16 bytes (if 8byte sizes) + Each malloced chunk has a hidden word of overhead holding size + and status information, and additional cross-check word + if FOOTERS is defined. + + Minimum allocated size: 4-byte ptrs: 16 bytes (including overhead) + 8-byte ptrs: 32 bytes (including overhead) + + Even a request for zero bytes (i.e., malloc(0)) returns a + pointer to something of the minimum allocatable size. + The maximum overhead wastage (i.e., number of extra bytes + allocated than were requested in malloc) is less than or equal + to the minimum size, except for requests >= mmap_threshold that + are serviced via mmap(), where the worst case wastage is about + 32 bytes plus the remainder from a system page (the minimal + mmap unit); typically 4096 or 8192 bytes. + + Security: static-safe; optionally more or less + The "security" of malloc refers to the ability of malicious + code to accentuate the effects of errors (for example, freeing + space that is not currently malloc'ed or overwriting past the + ends of chunks) in code that calls malloc. This malloc + guarantees not to modify any memory locations below the base of + heap, i.e., static variables, even in the presence of usage + errors. The routines additionally detect most improper frees + and reallocs. All this holds as long as the static bookkeeping + for malloc itself is not corrupted by some other means. This + is only one aspect of security -- these checks do not, and + cannot, detect all possible programming errors. + + If FOOTERS is defined nonzero, then each allocated chunk + carries an additional check word to verify that it was malloced + from its space. These check words are the same within each + execution of a program using malloc, but differ across + executions, so externally crafted fake chunks cannot be + freed. This improves security by rejecting frees/reallocs that + could corrupt heap memory, in addition to the checks preventing + writes to statics that are always on. This may further improve + security at the expense of time and space overhead. (Note that + FOOTERS may also be worth using with MSPACES.) + + By default detected errors cause the program to abort (calling + "abort()"). You can override this to instead proceed past + errors by defining PROCEED_ON_ERROR. In this case, a bad free + has no effect, and a malloc that encounters a bad address + caused by user overwrites will ignore the bad address by + dropping pointers and indices to all known memory. This may + be appropriate for programs that should continue if at all + possible in the face of programming errors, although they may + run out of memory because dropped memory is never reclaimed. + + If you don't like either of these options, you can define + CORRUPTION_ERROR_ACTION and USAGE_ERROR_ACTION to do anything + else. And if if you are sure that your program using malloc has + no errors or vulnerabilities, you can define INSECURE to 1, + which might (or might not) provide a small performance improvement. + + It is also possible to limit the maximum total allocatable + space, using malloc_set_footprint_limit. This is not + designed as a security feature in itself (calls to set limits + are not screened or privileged), but may be useful as one + aspect of a secure implementation. + + Thread-safety: NOT thread-safe unless USE_LOCKS defined non-zero + When USE_LOCKS is defined, each public call to malloc, free, + etc is surrounded with a lock. By default, this uses a plain + pthread mutex, win32 critical section, or a spin-lock if if + available for the platform and not disabled by setting + USE_SPIN_LOCKS=0. However, if USE_RECURSIVE_LOCKS is defined, + recursive versions are used instead (which are not required for + base functionality but may be needed in layered extensions). + Using a global lock is not especially fast, and can be a major + bottleneck. It is designed only to provide minimal protection + in concurrent environments, and to provide a basis for + extensions. If you are using malloc in a concurrent program, + consider instead using nedmalloc + (http://www.nedprod.com/programs/portable/nedmalloc/) or + ptmalloc (See http://www.malloc.de), which are derived from + versions of this malloc. + + System requirements: Any combination of MORECORE and/or MMAP/MUNMAP + This malloc can use unix sbrk or any emulation (invoked using + the CALL_MORECORE macro) and/or mmap/munmap or any emulation + (invoked using CALL_MMAP/CALL_MUNMAP) to get and release system + memory. On most unix systems, it tends to work best if both + MORECORE and MMAP are enabled. On Win32, it uses emulations + based on VirtualAlloc. It also uses common C library functions + like memset. + + Compliance: I believe it is compliant with the Single Unix Specification + (See http://www.unix.org). Also SVID/XPG, ANSI C, and probably + others as well. + +* Overview of algorithms + + This is not the fastest, most space-conserving, most portable, or + most tunable malloc ever written. However it is among the fastest + while also being among the most space-conserving, portable and + tunable. Consistent balance across these factors results in a good + general-purpose allocator for malloc-intensive programs. + + In most ways, this malloc is a best-fit allocator. Generally, it + chooses the best-fitting existing chunk for a request, with ties + broken in approximately least-recently-used order. (This strategy + normally maintains low fragmentation.) However, for requests less + than 256bytes, it deviates from best-fit when there is not an + exactly fitting available chunk by preferring to use space adjacent + to that used for the previous small request, as well as by breaking + ties in approximately most-recently-used order. (These enhance + locality of series of small allocations.) And for very large requests + (>= 256Kb by default), it relies on system memory mapping + facilities, if supported. (This helps avoid carrying around and + possibly fragmenting memory used only for large chunks.) + + All operations (except malloc_stats and mallinfo) have execution + times that are bounded by a constant factor of the number of bits in + a size_t, not counting any clearing in calloc or copying in realloc, + or actions surrounding MORECORE and MMAP that have times + proportional to the number of non-contiguous regions returned by + system allocation routines, which is often just 1. In real-time + applications, you can optionally suppress segment traversals using + NO_SEGMENT_TRAVERSAL, which assures bounded execution even when + system allocators return non-contiguous spaces, at the typical + expense of carrying around more memory and increased fragmentation. + + The implementation is not very modular and seriously overuses + macros. Perhaps someday all C compilers will do as good a job + inlining modular code as can now be done by brute-force expansion, + but now, enough of them seem not to. + + Some compilers issue a lot of warnings about code that is + dead/unreachable only on some platforms, and also about intentional + uses of negation on unsigned types. All known cases of each can be + ignored. + + For a longer but out of date high-level description, see + http://gee.cs.oswego.edu/dl/html/malloc.html + +* MSPACES + If MSPACES is defined, then in addition to malloc, free, etc., + this file also defines mspace_malloc, mspace_free, etc. These + are versions of malloc routines that take an "mspace" argument + obtained using create_mspace, to control all internal bookkeeping. + If ONLY_MSPACES is defined, only these versions are compiled. + So if you would like to use this allocator for only some allocations, + and your system malloc for others, you can compile with + ONLY_MSPACES and then do something like... + static mspace mymspace = create_mspace(0,0); // for example + #define mymalloc(bytes) mspace_malloc(mymspace, bytes) + + (Note: If you only need one instance of an mspace, you can instead + use "USE_DL_PREFIX" to relabel the global malloc.) + + You can similarly create thread-local allocators by storing + mspaces as thread-locals. For example: + static __thread mspace tlms = 0; + void* tlmalloc(size_t bytes) { + if (tlms == 0) tlms = create_mspace(0, 0); + return mspace_malloc(tlms, bytes); + } + void tlfree(void* mem) { mspace_free(tlms, mem); } + + Unless FOOTERS is defined, each mspace is completely independent. + You cannot allocate from one and free to another (although + conformance is only weakly checked, so usage errors are not always + caught). If FOOTERS is defined, then each chunk carries around a tag + indicating its originating mspace, and frees are directed to their + originating spaces. Normally, this requires use of locks. + + ------------------------- Compile-time options --------------------------- + +Be careful in setting #define values for numerical constants of type +size_t. On some systems, literal values are not automatically extended +to size_t precision unless they are explicitly casted. You can also +use the symbolic values MAX_SIZE_T, SIZE_T_ONE, etc below. + +WIN32 default: defined if _WIN32 defined + Defining WIN32 sets up defaults for MS environment and compilers. + Otherwise defaults are for unix. Beware that there seem to be some + cases where this malloc might not be a pure drop-in replacement for + Win32 malloc: Random-looking failures from Win32 GDI API's (eg; + SetDIBits()) may be due to bugs in some video driver implementations + when pixel buffers are malloc()ed, and the region spans more than + one VirtualAlloc()ed region. Because dlmalloc uses a small (64Kb) + default granularity, pixel buffers may straddle virtual allocation + regions more often than when using the Microsoft allocator. You can + avoid this by using VirtualAlloc() and VirtualFree() for all pixel + buffers rather than using malloc(). If this is not possible, + recompile this malloc with a larger DEFAULT_GRANULARITY. Note: + in cases where MSC and gcc (cygwin) are known to differ on WIN32, + conditions use _MSC_VER to distinguish them. + +DLMALLOC_EXPORT default: extern + Defines how public APIs are declared. If you want to export via a + Windows DLL, you might define this as + #define DLMALLOC_EXPORT extern __declspec(dllexport) + If you want a POSIX ELF shared object, you might use + #define DLMALLOC_EXPORT extern __attribute__((visibility("default"))) + +MALLOC_ALIGNMENT default: (size_t)(2 * sizeof(void *)) + Controls the minimum alignment for malloc'ed chunks. It must be a + power of two and at least 8, even on machines for which smaller + alignments would suffice. It may be defined as larger than this + though. Note however that code and data structures are optimized for + the case of 8-byte alignment. + +MSPACES default: 0 (false) + If true, compile in support for independent allocation spaces. + This is only supported if HAVE_MMAP is true. + +ONLY_MSPACES default: 0 (false) + If true, only compile in mspace versions, not regular versions. + +USE_LOCKS default: 0 (false) + Causes each call to each public routine to be surrounded with + pthread or WIN32 mutex lock/unlock. (If set true, this can be + overridden on a per-mspace basis for mspace versions.) If set to a + non-zero value other than 1, locks are used, but their + implementation is left out, so lock functions must be supplied manually, + as described below. + +USE_SPIN_LOCKS default: 1 iff USE_LOCKS and spin locks available + If true, uses custom spin locks for locking. This is currently + supported only gcc >= 4.1, older gccs on x86 platforms, and recent + MS compilers. Otherwise, posix locks or win32 critical sections are + used. + +USE_RECURSIVE_LOCKS default: not defined + If defined nonzero, uses recursive (aka reentrant) locks, otherwise + uses plain mutexes. This is not required for malloc proper, but may + be needed for layered allocators such as nedmalloc. + +LOCK_AT_FORK default: not defined + If defined nonzero, performs pthread_atfork upon initialization + to initialize child lock while holding parent lock. The implementation + assumes that pthread locks (not custom locks) are being used. In other + cases, you may need to customize the implementation. + +FOOTERS default: 0 + If true, provide extra checking and dispatching by placing + information in the footers of allocated chunks. This adds + space and time overhead. + +INSECURE default: 0 + If true, omit checks for usage errors and heap space overwrites. + +USE_DL_PREFIX default: NOT defined + Causes compiler to prefix all public routines with the string 'dl'. + This can be useful when you only want to use this malloc in one part + of a program, using your regular system malloc elsewhere. + +MALLOC_INSPECT_ALL default: NOT defined + If defined, compiles malloc_inspect_all and mspace_inspect_all, that + perform traversal of all heap space. Unless access to these + functions is otherwise restricted, you probably do not want to + include them in secure implementations. + +ABORT default: defined as abort() + Defines how to abort on failed checks. On most systems, a failed + check cannot die with an "assert" or even print an informative + message, because the underlying print routines in turn call malloc, + which will fail again. Generally, the best policy is to simply call + abort(). It's not very useful to do more than this because many + errors due to overwriting will show up as address faults (null, odd + addresses etc) rather than malloc-triggered checks, so will also + abort. Also, most compilers know that abort() does not return, so + can better optimize code conditionally calling it. + +PROCEED_ON_ERROR default: defined as 0 (false) + Controls whether detected bad addresses cause them to bypassed + rather than aborting. If set, detected bad arguments to free and + realloc are ignored. And all bookkeeping information is zeroed out + upon a detected overwrite of freed heap space, thus losing the + ability to ever return it from malloc again, but enabling the + application to proceed. If PROCEED_ON_ERROR is defined, the + static variable malloc_corruption_error_count is compiled in + and can be examined to see if errors have occurred. This option + generates slower code than the default abort policy. + +DEBUG default: NOT defined + The DEBUG setting is mainly intended for people trying to modify + this code or diagnose problems when porting to new platforms. + However, it may also be able to better isolate user errors than just + using runtime checks. The assertions in the check routines spell + out in more detail the assumptions and invariants underlying the + algorithms. The checking is fairly extensive, and will slow down + execution noticeably. Calling malloc_stats or mallinfo with DEBUG + set will attempt to check every non-mmapped allocated and free chunk + in the course of computing the summaries. + +ABORT_ON_ASSERT_FAILURE default: defined as 1 (true) + Debugging assertion failures can be nearly impossible if your + version of the assert macro causes malloc to be called, which will + lead to a cascade of further failures, blowing the runtime stack. + ABORT_ON_ASSERT_FAILURE cause assertions failures to call abort(), + which will usually make debugging easier. + +MALLOC_FAILURE_ACTION default: sets errno to ENOMEM, or no-op on win32 + The action to take before "return 0" when malloc fails to be able to + return memory because there is none available. + +HAVE_MORECORE default: 1 (true) unless win32 or ONLY_MSPACES + True if this system supports sbrk or an emulation of it. + +MORECORE default: sbrk + The name of the sbrk-style system routine to call to obtain more + memory. See below for guidance on writing custom MORECORE + functions. The type of the argument to sbrk/MORECORE varies across + systems. It cannot be size_t, because it supports negative + arguments, so it is normally the signed type of the same width as + size_t (sometimes declared as "intptr_t"). It doesn't much matter + though. Internally, we only call it with arguments less than half + the max value of a size_t, which should work across all reasonable + possibilities, although sometimes generating compiler warnings. + +MORECORE_CONTIGUOUS default: 1 (true) if HAVE_MORECORE + If true, take advantage of fact that consecutive calls to MORECORE + with positive arguments always return contiguous increasing + addresses. This is true of unix sbrk. It does not hurt too much to + set it true anyway, since malloc copes with non-contiguities. + Setting it false when definitely non-contiguous saves time + and possibly wasted space it would take to discover this though. + +MORECORE_CANNOT_TRIM default: NOT defined + True if MORECORE cannot release space back to the system when given + negative arguments. This is generally necessary only if you are + using a hand-crafted MORECORE function that cannot handle negative + arguments. + +NO_SEGMENT_TRAVERSAL default: 0 + If non-zero, suppresses traversals of memory segments + returned by either MORECORE or CALL_MMAP. This disables + merging of segments that are contiguous, and selectively + releasing them to the OS if unused, but bounds execution times. + +HAVE_MMAP default: 1 (true) + True if this system supports mmap or an emulation of it. If so, and + HAVE_MORECORE is not true, MMAP is used for all system + allocation. If set and HAVE_MORECORE is true as well, MMAP is + primarily used to directly allocate very large blocks. It is also + used as a backup strategy in cases where MORECORE fails to provide + space from system. Note: A single call to MUNMAP is assumed to be + able to unmap memory that may have be allocated using multiple calls + to MMAP, so long as they are adjacent. + +HAVE_MREMAP default: 1 on linux, else 0 + If true realloc() uses mremap() to re-allocate large blocks and + extend or shrink allocation spaces. + +MMAP_CLEARS default: 1 except on WINCE. + True if mmap clears memory so calloc doesn't need to. This is true + for standard unix mmap using /dev/zero and on WIN32 except for WINCE. + +USE_BUILTIN_FFS default: 0 (i.e., not used) + Causes malloc to use the builtin ffs() function to compute indices. + Some compilers may recognize and intrinsify ffs to be faster than the + supplied C version. Also, the case of x86 using gcc is special-cased + to an asm instruction, so is already as fast as it can be, and so + this setting has no effect. Similarly for Win32 under recent MS compilers. + (On most x86s, the asm version is only slightly faster than the C version.) + +malloc_getpagesize default: derive from system includes, or 4096. + The system page size. To the extent possible, this malloc manages + memory from the system in page-size units. This may be (and + usually is) a function rather than a constant. This is ignored + if WIN32, where page size is determined using getSystemInfo during + initialization. + +USE_DEV_RANDOM default: 0 (i.e., not used) + Causes malloc to use /dev/random to initialize secure magic seed for + stamping footers. Otherwise, the current time is used. + +NO_MALLINFO default: 0 + If defined, don't compile "mallinfo". This can be a simple way + of dealing with mismatches between system declarations and + those in this file. + +MALLINFO_FIELD_TYPE default: size_t + The type of the fields in the mallinfo struct. This was originally + defined as "int" in SVID etc, but is more usefully defined as + size_t. The value is used only if HAVE_USR_INCLUDE_MALLOC_H is not set + +NO_MALLOC_STATS default: 0 + If defined, don't compile "malloc_stats". This avoids calls to + fprintf and bringing in stdio dependencies you might not want. + +REALLOC_ZERO_BYTES_FREES default: not defined + This should be set if a call to realloc with zero bytes should + be the same as a call to free. Some people think it should. Otherwise, + since this malloc returns a unique pointer for malloc(0), so does + realloc(p, 0). + +LACKS_UNISTD_H, LACKS_FCNTL_H, LACKS_SYS_PARAM_H, LACKS_SYS_MMAN_H +LACKS_STRINGS_H, LACKS_STRING_H, LACKS_SYS_TYPES_H, LACKS_ERRNO_H +LACKS_STDLIB_H LACKS_SCHED_H LACKS_TIME_H default: NOT defined unless on WIN32 + Define these if your system does not have these header files. + You might need to manually insert some of the declarations they provide. + +DEFAULT_GRANULARITY default: page size if MORECORE_CONTIGUOUS, + system_info.dwAllocationGranularity in WIN32, + otherwise 64K. + Also settable using mallopt(M_GRANULARITY, x) + The unit for allocating and deallocating memory from the system. On + most systems with contiguous MORECORE, there is no reason to + make this more than a page. However, systems with MMAP tend to + either require or encourage larger granularities. You can increase + this value to prevent system allocation functions to be called so + often, especially if they are slow. The value must be at least one + page and must be a power of two. Setting to 0 causes initialization + to either page size or win32 region size. (Note: In previous + versions of malloc, the equivalent of this option was called + "TOP_PAD") + +DEFAULT_TRIM_THRESHOLD default: 2MB + Also settable using mallopt(M_TRIM_THRESHOLD, x) + The maximum amount of unused top-most memory to keep before + releasing via malloc_trim in free(). Automatic trimming is mainly + useful in long-lived programs using contiguous MORECORE. Because + trimming via sbrk can be slow on some systems, and can sometimes be + wasteful (in cases where programs immediately afterward allocate + more large chunks) the value should be high enough so that your + overall system performance would improve by releasing this much + memory. As a rough guide, you might set to a value close to the + average size of a process (program) running on your system. + Releasing this much memory would allow such a process to run in + memory. Generally, it is worth tuning trim thresholds when a + program undergoes phases where several large chunks are allocated + and released in ways that can reuse each other's storage, perhaps + mixed with phases where there are no such chunks at all. The trim + value must be greater than page size to have any useful effect. To + disable trimming completely, you can set to MAX_SIZE_T. Note that the trick + some people use of mallocing a huge space and then freeing it at + program startup, in an attempt to reserve system memory, doesn't + have the intended effect under automatic trimming, since that memory + will immediately be returned to the system. + +DEFAULT_MMAP_THRESHOLD default: 256K + Also settable using mallopt(M_MMAP_THRESHOLD, x) + The request size threshold for using MMAP to directly service a + request. Requests of at least this size that cannot be allocated + using already-existing space will be serviced via mmap. (If enough + normal freed space already exists it is used instead.) Using mmap + segregates relatively large chunks of memory so that they can be + individually obtained and released from the host system. A request + serviced through mmap is never reused by any other request (at least + not directly; the system may just so happen to remap successive + requests to the same locations). Segregating space in this way has + the benefits that: Mmapped space can always be individually released + back to the system, which helps keep the system level memory demands + of a long-lived program low. Also, mapped memory doesn't become + `locked' between other chunks, as can happen with normally allocated + chunks, which means that even trimming via malloc_trim would not + release them. However, it has the disadvantage that the space + cannot be reclaimed, consolidated, and then used to service later + requests, as happens with normal chunks. The advantages of mmap + nearly always outweigh disadvantages for "large" chunks, but the + value of "large" may vary across systems. The default is an + empirically derived value that works well in most systems. You can + disable mmap by setting to MAX_SIZE_T. + +MAX_RELEASE_CHECK_RATE default: 4095 unless not HAVE_MMAP + The number of consolidated frees between checks to release + unused segments when freeing. When using non-contiguous segments, + especially with multiple mspaces, checking only for topmost space + doesn't always suffice to trigger trimming. To compensate for this, + free() will, with a period of MAX_RELEASE_CHECK_RATE (or the + current number of segments, if greater) try to release unused + segments to the OS when freeing chunks that result in + consolidation. The best value for this parameter is a compromise + between slowing down frees with relatively costly checks that + rarely trigger versus holding on to unused memory. To effectively + disable, set to MAX_SIZE_T. This may lead to a very slight speed + improvement at the expense of carrying around more memory. +*/ + +#if KONAN_INTERNAL_DLMALLOC + +/**** Start of Konan-specific dlmalloc configuration. ****/ +#define USE_DL_PREFIX 1 +#if KONAN_WASM +#define USE_LOCKS 0 +#define LACKS_TIME_H 1 +#define NO_MALLOC_STATS 1 +#define HAVE_MMAP 0 // don't try to allocate large chunks of memory using mmap(). + // It will go to malloc->calloc->sbrk->morecore chain anyways. +#else +#define USE_LOCKS 1 +#endif +#define DLMALLOC_EXPORT extern "C" +#define HAVE_MORECORE 1 +#define MORECORE konan::moreCore +#define malloc_getpagesize konan::getpagesize() +namespace konan { +extern void* moreCore(int size); +extern long getpagesize(); +} // namespace konan + +/**** End of Konan-specific dlmalloc configuration. ****/ + + +/* Version identifier to allow people to support multiple versions */ +#ifndef DLMALLOC_VERSION +#define DLMALLOC_VERSION 20806 +#endif /* DLMALLOC_VERSION */ + +#ifndef DLMALLOC_EXPORT +#define DLMALLOC_EXPORT extern +#endif + +#ifndef WIN32 +#ifdef _WIN32 +#define WIN32 1 +#endif /* _WIN32 */ +#ifdef _WIN32_WCE +#define LACKS_FCNTL_H +#define WIN32 1 +#endif /* _WIN32_WCE */ +#endif /* WIN32 */ +#ifdef WIN32 +#define WIN32_LEAN_AND_MEAN +#include +#include +#define HAVE_MMAP 1 +#define HAVE_MORECORE 0 +#define LACKS_UNISTD_H +#define LACKS_SYS_PARAM_H +#define LACKS_SYS_MMAN_H +#define LACKS_STRING_H +#define LACKS_STRINGS_H +#define LACKS_SYS_TYPES_H +#define LACKS_ERRNO_H +#define LACKS_SCHED_H +#ifndef MALLOC_FAILURE_ACTION +#define MALLOC_FAILURE_ACTION +#endif /* MALLOC_FAILURE_ACTION */ +#ifndef MMAP_CLEARS +#ifdef _WIN32_WCE /* WINCE reportedly does not clear */ +#define MMAP_CLEARS 0 +#else +#define MMAP_CLEARS 1 +#endif /* _WIN32_WCE */ +#endif /*MMAP_CLEARS */ +#endif /* WIN32 */ + +#if defined(DARWIN) || defined(_DARWIN) +/* Mac OSX docs advise not to use sbrk; it seems better to use mmap */ +#ifndef HAVE_MORECORE +#define HAVE_MORECORE 0 +#define HAVE_MMAP 1 +/* OSX allocators provide 16 byte alignment */ +#ifndef MALLOC_ALIGNMENT +#define MALLOC_ALIGNMENT ((size_t)16U) +#endif +#endif /* HAVE_MORECORE */ +#endif /* DARWIN */ + +#ifndef LACKS_SYS_TYPES_H +#include /* For size_t */ +#endif /* LACKS_SYS_TYPES_H */ + +/* The maximum possible size_t value has all bits set */ +#define MAX_SIZE_T (~(size_t)0) + +#ifndef USE_LOCKS /* ensure true if spin or recursive locks set */ +#define USE_LOCKS ((defined(USE_SPIN_LOCKS) && USE_SPIN_LOCKS != 0) || \ + (defined(USE_RECURSIVE_LOCKS) && USE_RECURSIVE_LOCKS != 0)) +#endif /* USE_LOCKS */ + +#if USE_LOCKS /* Spin locks for gcc >= 4.1, older gcc on x86, MSC >= 1310 */ +#if ((defined(__GNUC__) && \ + ((__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 1)) || \ + defined(__i386__) || defined(__x86_64__))) || \ + (defined(_MSC_VER) && _MSC_VER>=1310)) +#ifndef USE_SPIN_LOCKS +#define USE_SPIN_LOCKS 1 +#endif /* USE_SPIN_LOCKS */ +#elif USE_SPIN_LOCKS +#error "USE_SPIN_LOCKS defined without implementation" +#endif /* ... locks available... */ +#elif !defined(USE_SPIN_LOCKS) +#define USE_SPIN_LOCKS 0 +#endif /* USE_LOCKS */ + +#ifndef ONLY_MSPACES +#define ONLY_MSPACES 0 +#endif /* ONLY_MSPACES */ +#ifndef MSPACES +#if ONLY_MSPACES +#define MSPACES 1 +#else /* ONLY_MSPACES */ +#define MSPACES 0 +#endif /* ONLY_MSPACES */ +#endif /* MSPACES */ +#ifndef MALLOC_ALIGNMENT +#define MALLOC_ALIGNMENT ((size_t)(2 * sizeof(void *))) +#endif /* MALLOC_ALIGNMENT */ +#ifndef FOOTERS +#define FOOTERS 0 +#endif /* FOOTERS */ +#ifndef ABORT +#define ABORT abort() +#endif /* ABORT */ +#ifndef ABORT_ON_ASSERT_FAILURE +#define ABORT_ON_ASSERT_FAILURE 1 +#endif /* ABORT_ON_ASSERT_FAILURE */ +#ifndef PROCEED_ON_ERROR +#define PROCEED_ON_ERROR 0 +#endif /* PROCEED_ON_ERROR */ + +#ifndef INSECURE +#define INSECURE 0 +#endif /* INSECURE */ +#ifndef MALLOC_INSPECT_ALL +#define MALLOC_INSPECT_ALL 0 +#endif /* MALLOC_INSPECT_ALL */ +#ifndef HAVE_MMAP +#define HAVE_MMAP 1 +#endif /* HAVE_MMAP */ +#ifndef MMAP_CLEARS +#define MMAP_CLEARS 1 +#endif /* MMAP_CLEARS */ +#ifndef HAVE_MREMAP +#ifdef linux +#define HAVE_MREMAP 1 +#define _GNU_SOURCE /* Turns on mremap() definition */ +#else /* linux */ +#define HAVE_MREMAP 0 +#endif /* linux */ +#endif /* HAVE_MREMAP */ +#ifndef MALLOC_FAILURE_ACTION +#define MALLOC_FAILURE_ACTION errno = ENOMEM; +#endif /* MALLOC_FAILURE_ACTION */ +#ifndef HAVE_MORECORE +#if ONLY_MSPACES +#define HAVE_MORECORE 0 +#else /* ONLY_MSPACES */ +#define HAVE_MORECORE 1 +#endif /* ONLY_MSPACES */ +#endif /* HAVE_MORECORE */ +#if !HAVE_MORECORE +#define MORECORE_CONTIGUOUS 0 +#else /* !HAVE_MORECORE */ +#define MORECORE_DEFAULT sbrk +#ifndef MORECORE_CONTIGUOUS +#define MORECORE_CONTIGUOUS 1 +#endif /* MORECORE_CONTIGUOUS */ +#endif /* HAVE_MORECORE */ +#ifndef DEFAULT_GRANULARITY +#if (MORECORE_CONTIGUOUS || defined(WIN32)) +#define DEFAULT_GRANULARITY (0) /* 0 means to compute in init_mparams */ +#else /* MORECORE_CONTIGUOUS */ +#define DEFAULT_GRANULARITY ((size_t)64U * (size_t)1024U) +#endif /* MORECORE_CONTIGUOUS */ +#endif /* DEFAULT_GRANULARITY */ +#ifndef DEFAULT_TRIM_THRESHOLD +#ifndef MORECORE_CANNOT_TRIM +#define DEFAULT_TRIM_THRESHOLD ((size_t)2U * (size_t)1024U * (size_t)1024U) +#else /* MORECORE_CANNOT_TRIM */ +#define DEFAULT_TRIM_THRESHOLD MAX_SIZE_T +#endif /* MORECORE_CANNOT_TRIM */ +#endif /* DEFAULT_TRIM_THRESHOLD */ +#ifndef DEFAULT_MMAP_THRESHOLD +#if HAVE_MMAP +#define DEFAULT_MMAP_THRESHOLD ((size_t)256U * (size_t)1024U) +#else /* HAVE_MMAP */ +#define DEFAULT_MMAP_THRESHOLD MAX_SIZE_T +#endif /* HAVE_MMAP */ +#endif /* DEFAULT_MMAP_THRESHOLD */ +#ifndef MAX_RELEASE_CHECK_RATE +#if HAVE_MMAP +#define MAX_RELEASE_CHECK_RATE 4095 +#else +#define MAX_RELEASE_CHECK_RATE MAX_SIZE_T +#endif /* HAVE_MMAP */ +#endif /* MAX_RELEASE_CHECK_RATE */ +#ifndef USE_BUILTIN_FFS +#define USE_BUILTIN_FFS 0 +#endif /* USE_BUILTIN_FFS */ +#ifndef USE_DEV_RANDOM +#define USE_DEV_RANDOM 0 +#endif /* USE_DEV_RANDOM */ +#ifndef NO_MALLINFO +#define NO_MALLINFO 0 +#endif /* NO_MALLINFO */ +#ifndef MALLINFO_FIELD_TYPE +#define MALLINFO_FIELD_TYPE size_t +#endif /* MALLINFO_FIELD_TYPE */ +#ifndef NO_MALLOC_STATS +#define NO_MALLOC_STATS 0 +#endif /* NO_MALLOC_STATS */ +#ifndef NO_SEGMENT_TRAVERSAL +#define NO_SEGMENT_TRAVERSAL 0 +#endif /* NO_SEGMENT_TRAVERSAL */ + +/* + mallopt tuning options. SVID/XPG defines four standard parameter + numbers for mallopt, normally defined in malloc.h. None of these + are used in this malloc, so setting them has no effect. But this + malloc does support the following options. +*/ + +#define M_TRIM_THRESHOLD (-1) +#define M_GRANULARITY (-2) +#define M_MMAP_THRESHOLD (-3) + +/* ------------------------ Mallinfo declarations ------------------------ */ + +#if !NO_MALLINFO +/* + This version of malloc supports the standard SVID/XPG mallinfo + routine that returns a struct containing usage properties and + statistics. It should work on any system that has a + /usr/include/malloc.h defining struct mallinfo. The main + declaration needed is the mallinfo struct that is returned (by-copy) + by mallinfo(). The malloinfo struct contains a bunch of fields that + are not even meaningful in this version of malloc. These fields are + are instead filled by mallinfo() with other numbers that might be of + interest. + + HAVE_USR_INCLUDE_MALLOC_H should be set if you have a + /usr/include/malloc.h file that includes a declaration of struct + mallinfo. If so, it is included; else a compliant version is + declared below. These must be precisely the same for mallinfo() to + work. The original SVID version of this struct, defined on most + systems with mallinfo, declares all fields as ints. But some others + define as unsigned long. If your system defines the fields using a + type of different width than listed here, you MUST #include your + system version and #define HAVE_USR_INCLUDE_MALLOC_H. +*/ + +/* #define HAVE_USR_INCLUDE_MALLOC_H */ + +#ifdef HAVE_USR_INCLUDE_MALLOC_H +#include "/usr/include/malloc.h" +#else /* HAVE_USR_INCLUDE_MALLOC_H */ +#ifndef STRUCT_MALLINFO_DECLARED +/* HP-UX (and others?) redefines mallinfo unless _STRUCT_MALLINFO is defined */ +#define _STRUCT_MALLINFO +#define STRUCT_MALLINFO_DECLARED 1 +struct mallinfo { + MALLINFO_FIELD_TYPE arena; /* non-mmapped space allocated from system */ + MALLINFO_FIELD_TYPE ordblks; /* number of free chunks */ + MALLINFO_FIELD_TYPE smblks; /* always 0 */ + MALLINFO_FIELD_TYPE hblks; /* always 0 */ + MALLINFO_FIELD_TYPE hblkhd; /* space in mmapped regions */ + MALLINFO_FIELD_TYPE usmblks; /* maximum total allocated space */ + MALLINFO_FIELD_TYPE fsmblks; /* always 0 */ + MALLINFO_FIELD_TYPE uordblks; /* total allocated space */ + MALLINFO_FIELD_TYPE fordblks; /* total free space */ + MALLINFO_FIELD_TYPE keepcost; /* releasable (via malloc_trim) space */ +}; +#endif /* STRUCT_MALLINFO_DECLARED */ +#endif /* HAVE_USR_INCLUDE_MALLOC_H */ +#endif /* NO_MALLINFO */ + +/* + Try to persuade compilers to inline. The most critical functions for + inlining are defined as macros, so these aren't used for them. +*/ + +#ifndef FORCEINLINE + #if defined(__GNUC__) +#define FORCEINLINE __inline __attribute__ ((always_inline)) + #elif defined(_MSC_VER) + #define FORCEINLINE __forceinline + #endif +#endif +#ifndef NOINLINE + #if defined(__GNUC__) + #define NOINLINE __attribute__ ((noinline)) + #elif defined(_MSC_VER) + #define NOINLINE __declspec(noinline) + #else + #define NOINLINE + #endif +#endif + +#ifdef __cplusplus +extern "C" { +#ifndef FORCEINLINE + #define FORCEINLINE inline +#endif +#endif /* __cplusplus */ +#ifndef FORCEINLINE + #define FORCEINLINE +#endif + +#if !ONLY_MSPACES + +/* ------------------- Declarations of public routines ------------------- */ + +#ifndef USE_DL_PREFIX +#define dlcalloc calloc +#define dlfree free +#define dlmalloc malloc +#define dlmemalign memalign +#define dlposix_memalign posix_memalign +#define dlrealloc realloc +#define dlrealloc_in_place realloc_in_place +#define dlvalloc valloc +#define dlpvalloc pvalloc +#define dlmallinfo mallinfo +#define dlmallopt mallopt +#define dlmalloc_trim malloc_trim +#define dlmalloc_stats malloc_stats +#define dlmalloc_usable_size malloc_usable_size +#define dlmalloc_footprint malloc_footprint +#define dlmalloc_max_footprint malloc_max_footprint +#define dlmalloc_footprint_limit malloc_footprint_limit +#define dlmalloc_set_footprint_limit malloc_set_footprint_limit +#define dlmalloc_inspect_all malloc_inspect_all +#define dlindependent_calloc independent_calloc +#define dlindependent_comalloc independent_comalloc +#define dlbulk_free bulk_free +#endif /* USE_DL_PREFIX */ + +/* + malloc(size_t n) + Returns a pointer to a newly allocated chunk of at least n bytes, or + null if no space is available, in which case errno is set to ENOMEM + on ANSI C systems. + + If n is zero, malloc returns a minimum-sized chunk. (The minimum + size is 16 bytes on most 32bit systems, and 32 bytes on 64bit + systems.) Note that size_t is an unsigned type, so calls with + arguments that would be negative if signed are interpreted as + requests for huge amounts of space, which will often fail. The + maximum supported value of n differs across systems, but is in all + cases less than the maximum representable value of a size_t. +*/ +DLMALLOC_EXPORT void* dlmalloc(size_t); + +/* + free(void* p) + Releases the chunk of memory pointed to by p, that had been previously + allocated using malloc or a related routine such as realloc. + It has no effect if p is null. If p was not malloced or already + freed, free(p) will by default cause the current program to abort. +*/ +DLMALLOC_EXPORT void dlfree(void*); + +/* + calloc(size_t n_elements, size_t element_size); + Returns a pointer to n_elements * element_size bytes, with all locations + set to zero. +*/ +DLMALLOC_EXPORT void* dlcalloc(size_t, size_t); + +/* + realloc(void* p, size_t n) + Returns a pointer to a chunk of size n that contains the same data + as does chunk p up to the minimum of (n, p's size) bytes, or null + if no space is available. + + The returned pointer may or may not be the same as p. The algorithm + prefers extending p in most cases when possible, otherwise it + employs the equivalent of a malloc-copy-free sequence. + + If p is null, realloc is equivalent to malloc. + + If space is not available, realloc returns null, errno is set (if on + ANSI) and p is NOT freed. + + if n is for fewer bytes than already held by p, the newly unused + space is lopped off and freed if possible. realloc with a size + argument of zero (re)allocates a minimum-sized chunk. + + The old unix realloc convention of allowing the last-free'd chunk + to be used as an argument to realloc is not supported. +*/ +DLMALLOC_EXPORT void* dlrealloc(void*, size_t); + +/* + realloc_in_place(void* p, size_t n) + Resizes the space allocated for p to size n, only if this can be + done without moving p (i.e., only if there is adjacent space + available if n is greater than p's current allocated size, or n is + less than or equal to p's size). This may be used instead of plain + realloc if an alternative allocation strategy is needed upon failure + to expand space; for example, reallocation of a buffer that must be + memory-aligned or cleared. You can use realloc_in_place to trigger + these alternatives only when needed. + + Returns p if successful; otherwise null. +*/ +DLMALLOC_EXPORT void* dlrealloc_in_place(void*, size_t); + +/* + memalign(size_t alignment, size_t n); + Returns a pointer to a newly allocated chunk of n bytes, aligned + in accord with the alignment argument. + + The alignment argument should be a power of two. If the argument is + not a power of two, the nearest greater power is used. + 8-byte alignment is guaranteed by normal malloc calls, so don't + bother calling memalign with an argument of 8 or less. + + Overreliance on memalign is a sure way to fragment space. +*/ +DLMALLOC_EXPORT void* dlmemalign(size_t, size_t); + +/* + int posix_memalign(void** pp, size_t alignment, size_t n); + Allocates a chunk of n bytes, aligned in accord with the alignment + argument. Differs from memalign only in that it (1) assigns the + allocated memory to *pp rather than returning it, (2) fails and + returns EINVAL if the alignment is not a power of two (3) fails and + returns ENOMEM if memory cannot be allocated. +*/ +DLMALLOC_EXPORT int dlposix_memalign(void**, size_t, size_t); + +/* + valloc(size_t n); + Equivalent to memalign(pagesize, n), where pagesize is the page + size of the system. If the pagesize is unknown, 4096 is used. +*/ +DLMALLOC_EXPORT void* dlvalloc(size_t); + +/* + mallopt(int parameter_number, int parameter_value) + Sets tunable parameters The format is to provide a + (parameter-number, parameter-value) pair. mallopt then sets the + corresponding parameter to the argument value if it can (i.e., so + long as the value is meaningful), and returns 1 if successful else + 0. To workaround the fact that mallopt is specified to use int, + not size_t parameters, the value -1 is specially treated as the + maximum unsigned size_t value. + + SVID/XPG/ANSI defines four standard param numbers for mallopt, + normally defined in malloc.h. None of these are use in this malloc, + so setting them has no effect. But this malloc also supports other + options in mallopt. See below for details. Briefly, supported + parameters are as follows (listed defaults are for "typical" + configurations). + + Symbol param # default allowed param values + M_TRIM_THRESHOLD -1 2*1024*1024 any (-1 disables) + M_GRANULARITY -2 page size any power of 2 >= page size + M_MMAP_THRESHOLD -3 256*1024 any (or 0 if no MMAP support) +*/ +DLMALLOC_EXPORT int dlmallopt(int, int); + +/* + malloc_footprint(); + Returns the number of bytes obtained from the system. The total + number of bytes allocated by malloc, realloc etc., is less than this + value. Unlike mallinfo, this function returns only a precomputed + result, so can be called frequently to monitor memory consumption. + Even if locks are otherwise defined, this function does not use them, + so results might not be up to date. +*/ +DLMALLOC_EXPORT size_t dlmalloc_footprint(void); + +/* + malloc_max_footprint(); + Returns the maximum number of bytes obtained from the system. This + value will be greater than current footprint if deallocated space + has been reclaimed by the system. The peak number of bytes allocated + by malloc, realloc etc., is less than this value. Unlike mallinfo, + this function returns only a precomputed result, so can be called + frequently to monitor memory consumption. Even if locks are + otherwise defined, this function does not use them, so results might + not be up to date. +*/ +DLMALLOC_EXPORT size_t dlmalloc_max_footprint(void); + +/* + malloc_footprint_limit(); + Returns the number of bytes that the heap is allowed to obtain from + the system, returning the last value returned by + malloc_set_footprint_limit, or the maximum size_t value if + never set. The returned value reflects a permission. There is no + guarantee that this number of bytes can actually be obtained from + the system. +*/ +DLMALLOC_EXPORT size_t dlmalloc_footprint_limit(); + +/* + malloc_set_footprint_limit(); + Sets the maximum number of bytes to obtain from the system, causing + failure returns from malloc and related functions upon attempts to + exceed this value. The argument value may be subject to page + rounding to an enforceable limit; this actual value is returned. + Using an argument of the maximum possible size_t effectively + disables checks. If the argument is less than or equal to the + current malloc_footprint, then all future allocations that require + additional system memory will fail. However, invocation cannot + retroactively deallocate existing used memory. +*/ +DLMALLOC_EXPORT size_t dlmalloc_set_footprint_limit(size_t bytes); + +#if MALLOC_INSPECT_ALL +/* + malloc_inspect_all(void(*handler)(void *start, + void *end, + size_t used_bytes, + void* callback_arg), + void* arg); + Traverses the heap and calls the given handler for each managed + region, skipping all bytes that are (or may be) used for bookkeeping + purposes. Traversal does not include include chunks that have been + directly memory mapped. Each reported region begins at the start + address, and continues up to but not including the end address. The + first used_bytes of the region contain allocated data. If + used_bytes is zero, the region is unallocated. The handler is + invoked with the given callback argument. If locks are defined, they + are held during the entire traversal. It is a bad idea to invoke + other malloc functions from within the handler. + + For example, to count the number of in-use chunks with size greater + than 1000, you could write: + static int count = 0; + void count_chunks(void* start, void* end, size_t used, void* arg) { + if (used >= 1000) ++count; + } + then: + malloc_inspect_all(count_chunks, NULL); + + malloc_inspect_all is compiled only if MALLOC_INSPECT_ALL is defined. +*/ +DLMALLOC_EXPORT void dlmalloc_inspect_all(void(*handler)(void*, void *, size_t, void*), + void* arg); + +#endif /* MALLOC_INSPECT_ALL */ + +#if !NO_MALLINFO +/* + mallinfo() + Returns (by copy) a struct containing various summary statistics: + + arena: current total non-mmapped bytes allocated from system + ordblks: the number of free chunks + smblks: always zero. + hblks: current number of mmapped regions + hblkhd: total bytes held in mmapped regions + usmblks: the maximum total allocated space. This will be greater + than current total if trimming has occurred. + fsmblks: always zero + uordblks: current total allocated space (normal or mmapped) + fordblks: total free space + keepcost: the maximum number of bytes that could ideally be released + back to system via malloc_trim. ("ideally" means that + it ignores page restrictions etc.) + + Because these fields are ints, but internal bookkeeping may + be kept as longs, the reported values may wrap around zero and + thus be inaccurate. +*/ +DLMALLOC_EXPORT struct mallinfo dlmallinfo(void); +#endif /* NO_MALLINFO */ + +/* + independent_calloc(size_t n_elements, size_t element_size, void* chunks[]); + + independent_calloc is similar to calloc, but instead of returning a + single cleared space, it returns an array of pointers to n_elements + independent elements that can hold contents of size elem_size, each + of which starts out cleared, and can be independently freed, + realloc'ed etc. The elements are guaranteed to be adjacently + allocated (this is not guaranteed to occur with multiple callocs or + mallocs), which may also improve cache locality in some + applications. + + The "chunks" argument is optional (i.e., may be null, which is + probably the most typical usage). If it is null, the returned array + is itself dynamically allocated and should also be freed when it is + no longer needed. Otherwise, the chunks array must be of at least + n_elements in length. It is filled in with the pointers to the + chunks. + + In either case, independent_calloc returns this pointer array, or + null if the allocation failed. If n_elements is zero and "chunks" + is null, it returns a chunk representing an array with zero elements + (which should be freed if not wanted). + + Each element must be freed when it is no longer needed. This can be + done all at once using bulk_free. + + independent_calloc simplifies and speeds up implementations of many + kinds of pools. It may also be useful when constructing large data + structures that initially have a fixed number of fixed-sized nodes, + but the number is not known at compile time, and some of the nodes + may later need to be freed. For example: + + struct Node { int item; struct Node* next; }; + + struct Node* build_list() { + struct Node** pool; + int n = read_number_of_nodes_needed(); + if (n <= 0) return 0; + pool = (struct Node**)(independent_calloc(n, sizeof(struct Node), 0); + if (pool == 0) die(); + // organize into a linked list... + struct Node* first = pool[0]; + for (i = 0; i < n-1; ++i) + pool[i]->next = pool[i+1]; + free(pool); // Can now free the array (or not, if it is needed later) + return first; + } +*/ +DLMALLOC_EXPORT void** dlindependent_calloc(size_t, size_t, void**); + +/* + independent_comalloc(size_t n_elements, size_t sizes[], void* chunks[]); + + independent_comalloc allocates, all at once, a set of n_elements + chunks with sizes indicated in the "sizes" array. It returns + an array of pointers to these elements, each of which can be + independently freed, realloc'ed etc. The elements are guaranteed to + be adjacently allocated (this is not guaranteed to occur with + multiple callocs or mallocs), which may also improve cache locality + in some applications. + + The "chunks" argument is optional (i.e., may be null). If it is null + the returned array is itself dynamically allocated and should also + be freed when it is no longer needed. Otherwise, the chunks array + must be of at least n_elements in length. It is filled in with the + pointers to the chunks. + + In either case, independent_comalloc returns this pointer array, or + null if the allocation failed. If n_elements is zero and chunks is + null, it returns a chunk representing an array with zero elements + (which should be freed if not wanted). + + Each element must be freed when it is no longer needed. This can be + done all at once using bulk_free. + + independent_comallac differs from independent_calloc in that each + element may have a different size, and also that it does not + automatically clear elements. + + independent_comalloc can be used to speed up allocation in cases + where several structs or objects must always be allocated at the + same time. For example: + + struct Head { ... } + struct Foot { ... } + + void send_message(char* msg) { + int msglen = strlen(msg); + size_t sizes[3] = { sizeof(struct Head), msglen, sizeof(struct Foot) }; + void* chunks[3]; + if (independent_comalloc(3, sizes, chunks) == 0) + die(); + struct Head* head = (struct Head*)(chunks[0]); + char* body = (char*)(chunks[1]); + struct Foot* foot = (struct Foot*)(chunks[2]); + // ... + } + + In general though, independent_comalloc is worth using only for + larger values of n_elements. For small values, you probably won't + detect enough difference from series of malloc calls to bother. + + Overuse of independent_comalloc can increase overall memory usage, + since it cannot reuse existing noncontiguous small chunks that + might be available for some of the elements. +*/ +DLMALLOC_EXPORT void** dlindependent_comalloc(size_t, size_t*, void**); + +/* + bulk_free(void* array[], size_t n_elements) + Frees and clears (sets to null) each non-null pointer in the given + array. This is likely to be faster than freeing them one-by-one. + If footers are used, pointers that have been allocated in different + mspaces are not freed or cleared, and the count of all such pointers + is returned. For large arrays of pointers with poor locality, it + may be worthwhile to sort this array before calling bulk_free. +*/ +DLMALLOC_EXPORT size_t dlbulk_free(void**, size_t n_elements); + +/* + pvalloc(size_t n); + Equivalent to valloc(minimum-page-that-holds(n)), that is, + round up n to nearest pagesize. + */ +DLMALLOC_EXPORT void* dlpvalloc(size_t); + +/* + malloc_trim(size_t pad); + + If possible, gives memory back to the system (via negative arguments + to sbrk) if there is unused memory at the `high' end of the malloc + pool or in unused MMAP segments. You can call this after freeing + large blocks of memory to potentially reduce the system-level memory + requirements of a program. However, it cannot guarantee to reduce + memory. Under some allocation patterns, some large free blocks of + memory will be locked between two used chunks, so they cannot be + given back to the system. + + The `pad' argument to malloc_trim represents the amount of free + trailing space to leave untrimmed. If this argument is zero, only + the minimum amount of memory to maintain internal data structures + will be left. Non-zero arguments can be supplied to maintain enough + trailing space to service future expected allocations without having + to re-obtain memory from the system. + + Malloc_trim returns 1 if it actually released any memory, else 0. +*/ +DLMALLOC_EXPORT int dlmalloc_trim(size_t); + +/* + malloc_stats(); + Prints on stderr the amount of space obtained from the system (both + via sbrk and mmap), the maximum amount (which may be more than + current if malloc_trim and/or munmap got called), and the current + number of bytes allocated via malloc (or realloc, etc) but not yet + freed. Note that this is the number of bytes allocated, not the + number requested. It will be larger than the number requested + because of alignment and bookkeeping overhead. Because it includes + alignment wastage as being in use, this figure may be greater than + zero even when no user-level chunks are allocated. + + The reported current and maximum system memory can be inaccurate if + a program makes other calls to system memory allocation functions + (normally sbrk) outside of malloc. + + malloc_stats prints only the most commonly interesting statistics. + More information can be obtained by calling mallinfo. +*/ +DLMALLOC_EXPORT void dlmalloc_stats(void); + +/* + malloc_usable_size(void* p); + + Returns the number of bytes you can actually use in + an allocated chunk, which may be more than you requested (although + often not) due to alignment and minimum size constraints. + You can use this many bytes without worrying about + overwriting other allocated objects. This is not a particularly great + programming practice. malloc_usable_size can be more useful in + debugging and assertions, for example: + + p = malloc(n); + assert(malloc_usable_size(p) >= 256); +*/ +size_t dlmalloc_usable_size(void*); + +#endif /* ONLY_MSPACES */ + +#if MSPACES + +/* + mspace is an opaque type representing an independent + region of space that supports mspace_malloc, etc. +*/ +typedef void* mspace; + +/* + create_mspace creates and returns a new independent space with the + given initial capacity, or, if 0, the default granularity size. It + returns null if there is no system memory available to create the + space. If argument locked is non-zero, the space uses a separate + lock to control access. The capacity of the space will grow + dynamically as needed to service mspace_malloc requests. You can + control the sizes of incremental increases of this space by + compiling with a different DEFAULT_GRANULARITY or dynamically + setting with mallopt(M_GRANULARITY, value). +*/ +DLMALLOC_EXPORT mspace create_mspace(size_t capacity, int locked); + +/* + destroy_mspace destroys the given space, and attempts to return all + of its memory back to the system, returning the total number of + bytes freed. After destruction, the results of access to all memory + used by the space become undefined. +*/ +DLMALLOC_EXPORT size_t destroy_mspace(mspace msp); + +/* + create_mspace_with_base uses the memory supplied as the initial base + of a new mspace. Part (less than 128*sizeof(size_t) bytes) of this + space is used for bookkeeping, so the capacity must be at least this + large. (Otherwise 0 is returned.) When this initial space is + exhausted, additional memory will be obtained from the system. + Destroying this space will deallocate all additionally allocated + space (if possible) but not the initial base. +*/ +DLMALLOC_EXPORT mspace create_mspace_with_base(void* base, size_t capacity, int locked); + +/* + mspace_track_large_chunks controls whether requests for large chunks + are allocated in their own untracked mmapped regions, separate from + others in this mspace. By default large chunks are not tracked, + which reduces fragmentation. However, such chunks are not + necessarily released to the system upon destroy_mspace. Enabling + tracking by setting to true may increase fragmentation, but avoids + leakage when relying on destroy_mspace to release all memory + allocated using this space. The function returns the previous + setting. +*/ +DLMALLOC_EXPORT int mspace_track_large_chunks(mspace msp, int enable); + + +/* + mspace_malloc behaves as malloc, but operates within + the given space. +*/ +DLMALLOC_EXPORT void* mspace_malloc(mspace msp, size_t bytes); + +/* + mspace_free behaves as free, but operates within + the given space. + + If compiled with FOOTERS==1, mspace_free is not actually needed. + free may be called instead of mspace_free because freed chunks from + any space are handled by their originating spaces. +*/ +DLMALLOC_EXPORT void mspace_free(mspace msp, void* mem); + +/* + mspace_realloc behaves as realloc, but operates within + the given space. + + If compiled with FOOTERS==1, mspace_realloc is not actually + needed. realloc may be called instead of mspace_realloc because + realloced chunks from any space are handled by their originating + spaces. +*/ +DLMALLOC_EXPORT void* mspace_realloc(mspace msp, void* mem, size_t newsize); + +/* + mspace_calloc behaves as calloc, but operates within + the given space. +*/ +DLMALLOC_EXPORT void* mspace_calloc(mspace msp, size_t n_elements, size_t elem_size); + +/* + mspace_memalign behaves as memalign, but operates within + the given space. +*/ +DLMALLOC_EXPORT void* mspace_memalign(mspace msp, size_t alignment, size_t bytes); + +/* + mspace_independent_calloc behaves as independent_calloc, but + operates within the given space. +*/ +DLMALLOC_EXPORT void** mspace_independent_calloc(mspace msp, size_t n_elements, + size_t elem_size, void* chunks[]); + +/* + mspace_independent_comalloc behaves as independent_comalloc, but + operates within the given space. +*/ +DLMALLOC_EXPORT void** mspace_independent_comalloc(mspace msp, size_t n_elements, + size_t sizes[], void* chunks[]); + +/* + mspace_footprint() returns the number of bytes obtained from the + system for this space. +*/ +DLMALLOC_EXPORT size_t mspace_footprint(mspace msp); + +/* + mspace_max_footprint() returns the peak number of bytes obtained from the + system for this space. +*/ +DLMALLOC_EXPORT size_t mspace_max_footprint(mspace msp); + + +#if !NO_MALLINFO +/* + mspace_mallinfo behaves as mallinfo, but reports properties of + the given space. +*/ +DLMALLOC_EXPORT struct mallinfo mspace_mallinfo(mspace msp); +#endif /* NO_MALLINFO */ + +/* + malloc_usable_size(void* p) behaves the same as malloc_usable_size; +*/ +DLMALLOC_EXPORT size_t mspace_usable_size(const void* mem); + +/* + mspace_malloc_stats behaves as malloc_stats, but reports + properties of the given space. +*/ +DLMALLOC_EXPORT void mspace_malloc_stats(mspace msp); + +/* + mspace_trim behaves as malloc_trim, but + operates within the given space. +*/ +DLMALLOC_EXPORT int mspace_trim(mspace msp, size_t pad); + +/* + An alias for mallopt. +*/ +DLMALLOC_EXPORT int mspace_mallopt(int, int); + +#endif /* MSPACES */ + +#ifdef __cplusplus +} /* end of extern "C" */ +#endif /* __cplusplus */ + +/* + ======================================================================== + To make a fully customizable malloc.h header file, cut everything + above this line, put into file malloc.h, edit to suit, and #include it + on the next line, as well as in programs that use this malloc. + ======================================================================== +*/ + +/* #include "malloc.h" */ + +/*------------------------------ internal #includes ---------------------- */ + +#ifdef _MSC_VER +#pragma warning( disable : 4146 ) /* no "unsigned" warnings */ +#endif /* _MSC_VER */ +#if !NO_MALLOC_STATS +#include /* for printing in malloc_stats */ +#endif /* NO_MALLOC_STATS */ +#ifndef LACKS_ERRNO_H +#include /* for MALLOC_FAILURE_ACTION */ +#endif /* LACKS_ERRNO_H */ +#ifdef DEBUG +#if ABORT_ON_ASSERT_FAILURE +#undef assert +#define assert(x) if(!(x)) ABORT +#else /* ABORT_ON_ASSERT_FAILURE */ +#include +#endif /* ABORT_ON_ASSERT_FAILURE */ +#else /* DEBUG */ +#ifndef assert +#define assert(x) +#endif +#define DEBUG 0 +#endif /* DEBUG */ +#if !defined(WIN32) && !defined(LACKS_TIME_H) +#include /* for magic initialization */ +#endif /* WIN32 */ +#ifndef LACKS_STDLIB_H +#include /* for abort() */ +#endif /* LACKS_STDLIB_H */ +#ifndef LACKS_STRING_H +#include /* for memset etc */ +#endif /* LACKS_STRING_H */ +#if USE_BUILTIN_FFS +#ifndef LACKS_STRINGS_H +#include /* for ffs */ +#endif /* LACKS_STRINGS_H */ +#endif /* USE_BUILTIN_FFS */ +#if HAVE_MMAP +#ifndef LACKS_SYS_MMAN_H +/* On some versions of linux, mremap decl in mman.h needs __USE_GNU set */ +#if (defined(linux) && !defined(__USE_GNU)) +#define __USE_GNU 1 +#include /* for mmap */ +#undef __USE_GNU +#else +#include /* for mmap */ +#endif /* linux */ +#endif /* LACKS_SYS_MMAN_H */ +#ifndef LACKS_FCNTL_H +#include +#endif /* LACKS_FCNTL_H */ +#endif /* HAVE_MMAP */ +#ifndef LACKS_UNISTD_H +#include /* for sbrk, sysconf */ +#else /* LACKS_UNISTD_H */ +#if !defined(__FreeBSD__) && !defined(__OpenBSD__) && !defined(__NetBSD__) +extern void* sbrk(ptrdiff_t); +#endif /* FreeBSD etc */ +#endif /* LACKS_UNISTD_H */ + +/* Declarations for locking */ +#if USE_LOCKS +#ifndef WIN32 +#if defined (__SVR4) && defined (__sun) /* solaris */ +#include +#elif !defined(LACKS_SCHED_H) +#include +#endif /* solaris or LACKS_SCHED_H */ +#if (defined(USE_RECURSIVE_LOCKS) && USE_RECURSIVE_LOCKS != 0) || !USE_SPIN_LOCKS +#include +#endif /* USE_RECURSIVE_LOCKS ... */ +#elif defined(_MSC_VER) +#ifndef _M_AMD64 +/* These are already defined on AMD64 builds */ +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ +LONG __cdecl _InterlockedCompareExchange(LONG volatile *Dest, LONG Exchange, LONG Comp); +LONG __cdecl _InterlockedExchange(LONG volatile *Target, LONG Value); +#ifdef __cplusplus +} +#endif /* __cplusplus */ +#endif /* _M_AMD64 */ +#pragma intrinsic (_InterlockedCompareExchange) +#pragma intrinsic (_InterlockedExchange) +#define interlockedcompareexchange _InterlockedCompareExchange +#define interlockedexchange _InterlockedExchange +#elif defined(WIN32) && defined(__GNUC__) +#define interlockedcompareexchange(a, b, c) __sync_val_compare_and_swap(a, c, b) +#define interlockedexchange __sync_lock_test_and_set +#endif /* Win32 */ +#else /* USE_LOCKS */ +#endif /* USE_LOCKS */ + +#ifndef LOCK_AT_FORK +#define LOCK_AT_FORK 0 +#endif + +/* Declarations for bit scanning on win32 */ +#if defined(_MSC_VER) && _MSC_VER>=1300 +#ifndef BitScanForward /* Try to avoid pulling in WinNT.h */ +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ +unsigned char _BitScanForward(unsigned long *index, unsigned long mask); +unsigned char _BitScanReverse(unsigned long *index, unsigned long mask); +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#define BitScanForward _BitScanForward +#define BitScanReverse _BitScanReverse +#pragma intrinsic(_BitScanForward) +#pragma intrinsic(_BitScanReverse) +#endif /* BitScanForward */ +#endif /* defined(_MSC_VER) && _MSC_VER>=1300 */ + +#ifndef WIN32 +#ifndef malloc_getpagesize +# ifdef _SC_PAGESIZE /* some SVR4 systems omit an underscore */ +# ifndef _SC_PAGE_SIZE +# define _SC_PAGE_SIZE _SC_PAGESIZE +# endif +# endif +# ifdef _SC_PAGE_SIZE +# define malloc_getpagesize sysconf(_SC_PAGE_SIZE) +# else +# if defined(BSD) || defined(DGUX) || defined(HAVE_GETPAGESIZE) + extern size_t getpagesize(); +# define malloc_getpagesize getpagesize() +# else +# ifdef WIN32 /* use supplied emulation of getpagesize */ +# define malloc_getpagesize getpagesize() +# else +# ifndef LACKS_SYS_PARAM_H +# include +# endif +# ifdef EXEC_PAGESIZE +# define malloc_getpagesize EXEC_PAGESIZE +# else +# ifdef NBPG +# ifndef CLSIZE +# define malloc_getpagesize NBPG +# else +# define malloc_getpagesize (NBPG * CLSIZE) +# endif +# else +# ifdef NBPC +# define malloc_getpagesize NBPC +# else +# ifdef PAGESIZE +# define malloc_getpagesize PAGESIZE +# else /* just guess */ +# define malloc_getpagesize ((size_t)4096U) +# endif +# endif +# endif +# endif +# endif +# endif +# endif +#endif +#endif + +/* ------------------- size_t and alignment properties -------------------- */ + +/* The byte and bit size of a size_t */ +#define SIZE_T_SIZE (sizeof(size_t)) +#define SIZE_T_BITSIZE (sizeof(size_t) << 3) + +/* Some constants coerced to size_t */ +/* Annoying but necessary to avoid errors on some platforms */ +#define SIZE_T_ZERO ((size_t)0) +#define SIZE_T_ONE ((size_t)1) +#define SIZE_T_TWO ((size_t)2) +#define SIZE_T_FOUR ((size_t)4) +#define TWO_SIZE_T_SIZES (SIZE_T_SIZE<<1) +#define FOUR_SIZE_T_SIZES (SIZE_T_SIZE<<2) +#define SIX_SIZE_T_SIZES (FOUR_SIZE_T_SIZES+TWO_SIZE_T_SIZES) +#define HALF_MAX_SIZE_T (MAX_SIZE_T / 2U) + +/* The bit mask value corresponding to MALLOC_ALIGNMENT */ +#define CHUNK_ALIGN_MASK (MALLOC_ALIGNMENT - SIZE_T_ONE) + +/* True if address a has acceptable alignment */ +#define is_aligned(A) (((size_t)((A)) & (CHUNK_ALIGN_MASK)) == 0) + +/* the number of bytes to offset an address to align it */ +#define align_offset(A)\ + ((((size_t)(A) & CHUNK_ALIGN_MASK) == 0)? 0 :\ + ((MALLOC_ALIGNMENT - ((size_t)(A) & CHUNK_ALIGN_MASK)) & CHUNK_ALIGN_MASK)) + +/* -------------------------- MMAP preliminaries ------------------------- */ + +/* + If HAVE_MORECORE or HAVE_MMAP are false, we just define calls and + checks to fail so compiler optimizer can delete code rather than + using so many "#if"s. +*/ + + +/* MORECORE and MMAP must return MFAIL on failure */ +#define MFAIL ((void*)(MAX_SIZE_T)) +#define CMFAIL ((char*)(MFAIL)) /* defined for convenience */ + +#if HAVE_MMAP + +#ifndef WIN32 +#define MUNMAP_DEFAULT(a, s) munmap((a), (s)) +#define MMAP_PROT (PROT_READ|PROT_WRITE) +#if !defined(MAP_ANONYMOUS) && defined(MAP_ANON) +#define MAP_ANONYMOUS MAP_ANON +#endif /* MAP_ANON */ +#ifdef MAP_ANONYMOUS +#define MMAP_FLAGS (MAP_PRIVATE|MAP_ANONYMOUS) +#define MMAP_DEFAULT(s) mmap(0, (s), MMAP_PROT, MMAP_FLAGS, -1, 0) +#else /* MAP_ANONYMOUS */ +/* + Nearly all versions of mmap support MAP_ANONYMOUS, so the following + is unlikely to be needed, but is supplied just in case. +*/ +#define MMAP_FLAGS (MAP_PRIVATE) +static int dev_zero_fd = -1; /* Cached file descriptor for /dev/zero. */ +#define MMAP_DEFAULT(s) ((dev_zero_fd < 0) ? \ + (dev_zero_fd = open("/dev/zero", O_RDWR), \ + mmap(0, (s), MMAP_PROT, MMAP_FLAGS, dev_zero_fd, 0)) : \ + mmap(0, (s), MMAP_PROT, MMAP_FLAGS, dev_zero_fd, 0)) +#endif /* MAP_ANONYMOUS */ + +#define DIRECT_MMAP_DEFAULT(s) MMAP_DEFAULT(s) + +#else /* WIN32 */ + +/* Win32 MMAP via VirtualAlloc */ +static FORCEINLINE void* win32mmap(size_t size) { + void* ptr = VirtualAlloc(0, size, MEM_RESERVE|MEM_COMMIT, PAGE_READWRITE); + return (ptr != 0)? ptr: MFAIL; +} + +/* For direct MMAP, use MEM_TOP_DOWN to minimize interference */ +static FORCEINLINE void* win32direct_mmap(size_t size) { + void* ptr = VirtualAlloc(0, size, MEM_RESERVE|MEM_COMMIT|MEM_TOP_DOWN, + PAGE_READWRITE); + return (ptr != 0)? ptr: MFAIL; +} + +/* This function supports releasing coalesed segments */ +static FORCEINLINE int win32munmap(void* ptr, size_t size) { + MEMORY_BASIC_INFORMATION minfo; + char* cptr = (char*)ptr; + while (size) { + if (VirtualQuery(cptr, &minfo, sizeof(minfo)) == 0) + return -1; + if (minfo.BaseAddress != cptr || minfo.AllocationBase != cptr || + minfo.State != MEM_COMMIT || minfo.RegionSize > size) + return -1; + if (VirtualFree(cptr, 0, MEM_RELEASE) == 0) + return -1; + cptr += minfo.RegionSize; + size -= minfo.RegionSize; + } + return 0; +} + +#define MMAP_DEFAULT(s) win32mmap(s) +#define MUNMAP_DEFAULT(a, s) win32munmap((a), (s)) +#define DIRECT_MMAP_DEFAULT(s) win32direct_mmap(s) +#endif /* WIN32 */ +#endif /* HAVE_MMAP */ + +#if HAVE_MREMAP +#ifndef WIN32 +#define MREMAP_DEFAULT(addr, osz, nsz, mv) mremap((addr), (osz), (nsz), (mv)) +#endif /* WIN32 */ +#endif /* HAVE_MREMAP */ + +/** + * Define CALL_MORECORE + */ +#if HAVE_MORECORE + #ifdef MORECORE + #define CALL_MORECORE(S) MORECORE(S) + #else /* MORECORE */ + #define CALL_MORECORE(S) MORECORE_DEFAULT(S) + #endif /* MORECORE */ +#else /* HAVE_MORECORE */ + #define CALL_MORECORE(S) MFAIL +#endif /* HAVE_MORECORE */ + +/** + * Define CALL_MMAP/CALL_MUNMAP/CALL_DIRECT_MMAP + */ +#if HAVE_MMAP + #define USE_MMAP_BIT (SIZE_T_ONE) + + #ifdef MMAP + #define CALL_MMAP(s) MMAP(s) + #else /* MMAP */ + #define CALL_MMAP(s) MMAP_DEFAULT(s) + #endif /* MMAP */ + #ifdef MUNMAP + #define CALL_MUNMAP(a, s) MUNMAP((a), (s)) + #else /* MUNMAP */ + #define CALL_MUNMAP(a, s) MUNMAP_DEFAULT((a), (s)) + #endif /* MUNMAP */ + #ifdef DIRECT_MMAP + #define CALL_DIRECT_MMAP(s) DIRECT_MMAP(s) + #else /* DIRECT_MMAP */ + #define CALL_DIRECT_MMAP(s) DIRECT_MMAP_DEFAULT(s) + #endif /* DIRECT_MMAP */ +#else /* HAVE_MMAP */ + #define USE_MMAP_BIT (SIZE_T_ZERO) + + #define MMAP(s) MFAIL + #define MUNMAP(a, s) (-1) + #define DIRECT_MMAP(s) MFAIL + #define CALL_DIRECT_MMAP(s) DIRECT_MMAP(s) + #define CALL_MMAP(s) MMAP(s) + #define CALL_MUNMAP(a, s) MUNMAP((a), (s)) +#endif /* HAVE_MMAP */ + +/** + * Define CALL_MREMAP + */ +#if HAVE_MMAP && HAVE_MREMAP + #ifdef MREMAP + #define CALL_MREMAP(addr, osz, nsz, mv) MREMAP((addr), (osz), (nsz), (mv)) + #else /* MREMAP */ + #define CALL_MREMAP(addr, osz, nsz, mv) MREMAP_DEFAULT((addr), (osz), (nsz), (mv)) + #endif /* MREMAP */ +#else /* HAVE_MMAP && HAVE_MREMAP */ + #define CALL_MREMAP(addr, osz, nsz, mv) MFAIL +#endif /* HAVE_MMAP && HAVE_MREMAP */ + +/* mstate bit set if continguous morecore disabled or failed */ +#define USE_NONCONTIGUOUS_BIT (4U) + +/* segment bit set in create_mspace_with_base */ +#define EXTERN_BIT (8U) + + +/* --------------------------- Lock preliminaries ------------------------ */ + +/* + When locks are defined, there is one global lock, plus + one per-mspace lock. + + The global lock_ensures that mparams.magic and other unique + mparams values are initialized only once. It also protects + sequences of calls to MORECORE. In many cases sys_alloc requires + two calls, that should not be interleaved with calls by other + threads. This does not protect against direct calls to MORECORE + by other threads not using this lock, so there is still code to + cope the best we can on interference. + + Per-mspace locks surround calls to malloc, free, etc. + By default, locks are simple non-reentrant mutexes. + + Because lock-protected regions generally have bounded times, it is + OK to use the supplied simple spinlocks. Spinlocks are likely to + improve performance for lightly contended applications, but worsen + performance under heavy contention. + + If USE_LOCKS is > 1, the definitions of lock routines here are + bypassed, in which case you will need to define the type MLOCK_T, + and at least INITIAL_LOCK, DESTROY_LOCK, ACQUIRE_LOCK, RELEASE_LOCK + and TRY_LOCK. You must also declare a + static MLOCK_T malloc_global_mutex = { initialization values };. + +*/ + +#if !USE_LOCKS +#define USE_LOCK_BIT (0U) +#define INITIAL_LOCK(l) (0) +#define DESTROY_LOCK(l) (0) +#define ACQUIRE_MALLOC_GLOBAL_LOCK() +#define RELEASE_MALLOC_GLOBAL_LOCK() + +#else +#if USE_LOCKS > 1 +/* ----------------------- User-defined locks ------------------------ */ +/* Define your own lock implementation here */ +/* #define INITIAL_LOCK(lk) ... */ +/* #define DESTROY_LOCK(lk) ... */ +/* #define ACQUIRE_LOCK(lk) ... */ +/* #define RELEASE_LOCK(lk) ... */ +/* #define TRY_LOCK(lk) ... */ +/* static MLOCK_T malloc_global_mutex = ... */ + +#elif USE_SPIN_LOCKS + +/* First, define CAS_LOCK and CLEAR_LOCK on ints */ +/* Note CAS_LOCK defined to return 0 on success */ + +#if defined(__GNUC__)&& (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 1)) +#define CAS_LOCK(sl) __sync_lock_test_and_set(sl, 1) +#define CLEAR_LOCK(sl) __sync_lock_release(sl) + +#elif (defined(__GNUC__) && (defined(__i386__) || defined(__x86_64__))) +/* Custom spin locks for older gcc on x86 */ +static FORCEINLINE int x86_cas_lock(int *sl) { + int ret; + int val = 1; + int cmp = 0; + __asm__ __volatile__ ("lock; cmpxchgl %1, %2" + : "=a" (ret) + : "r" (val), "m" (*(sl)), "0"(cmp) + : "memory", "cc"); + return ret; +} + +static FORCEINLINE void x86_clear_lock(int* sl) { + assert(*sl != 0); + int prev = 0; + int ret; + __asm__ __volatile__ ("lock; xchgl %0, %1" + : "=r" (ret) + : "m" (*(sl)), "0"(prev) + : "memory"); +} + +#define CAS_LOCK(sl) x86_cas_lock(sl) +#define CLEAR_LOCK(sl) x86_clear_lock(sl) + +#else /* Win32 MSC */ +#define CAS_LOCK(sl) interlockedexchange(sl, (LONG)1) +#define CLEAR_LOCK(sl) interlockedexchange (sl, (LONG)0) + +#endif /* ... gcc spins locks ... */ + +/* How to yield for a spin lock */ +#define SPINS_PER_YIELD 63 +#if defined(_MSC_VER) +#define SLEEP_EX_DURATION 50 /* delay for yield/sleep */ +#define SPIN_LOCK_YIELD SleepEx(SLEEP_EX_DURATION, FALSE) +#elif defined (__SVR4) && defined (__sun) /* solaris */ +#define SPIN_LOCK_YIELD thr_yield(); +#elif !defined(LACKS_SCHED_H) +#define SPIN_LOCK_YIELD sched_yield(); +#else +#define SPIN_LOCK_YIELD +#endif /* ... yield ... */ + +#if !defined(USE_RECURSIVE_LOCKS) || USE_RECURSIVE_LOCKS == 0 +/* Plain spin locks use single word (embedded in malloc_states) */ +static int spin_acquire_lock(int *sl) { + int spins = 0; + while (*(volatile int *)sl != 0 || CAS_LOCK(sl)) { + if ((++spins & SPINS_PER_YIELD) == 0) { + SPIN_LOCK_YIELD; + } + } + return 0; +} + +#define MLOCK_T int +#define TRY_LOCK(sl) !CAS_LOCK(sl) +#define RELEASE_LOCK(sl) CLEAR_LOCK(sl) +#define ACQUIRE_LOCK(sl) (CAS_LOCK(sl)? spin_acquire_lock(sl) : 0) +#define INITIAL_LOCK(sl) (*sl = 0) +#define DESTROY_LOCK(sl) (0) +static MLOCK_T malloc_global_mutex = 0; + +#else /* USE_RECURSIVE_LOCKS */ +/* types for lock owners */ +#ifdef WIN32 +#define THREAD_ID_T DWORD +#define CURRENT_THREAD GetCurrentThreadId() +#define EQ_OWNER(X,Y) ((X) == (Y)) +#else +/* + Note: the following assume that pthread_t is a type that can be + initialized to (casted) zero. If this is not the case, you will need to + somehow redefine these or not use spin locks. +*/ +#define THREAD_ID_T pthread_t +#define CURRENT_THREAD pthread_self() +#define EQ_OWNER(X,Y) pthread_equal(X, Y) +#endif + +struct malloc_recursive_lock { + int sl; + unsigned int c; + THREAD_ID_T threadid; +}; + +#define MLOCK_T struct malloc_recursive_lock +static MLOCK_T malloc_global_mutex = { 0, 0, (THREAD_ID_T)0}; + +static FORCEINLINE void recursive_release_lock(MLOCK_T *lk) { + assert(lk->sl != 0); + if (--lk->c == 0) { + CLEAR_LOCK(&lk->sl); + } +} + +static FORCEINLINE int recursive_acquire_lock(MLOCK_T *lk) { + THREAD_ID_T mythreadid = CURRENT_THREAD; + int spins = 0; + for (;;) { + if (*((volatile int *)(&lk->sl)) == 0) { + if (!CAS_LOCK(&lk->sl)) { + lk->threadid = mythreadid; + lk->c = 1; + return 0; + } + } + else if (EQ_OWNER(lk->threadid, mythreadid)) { + ++lk->c; + return 0; + } + if ((++spins & SPINS_PER_YIELD) == 0) { + SPIN_LOCK_YIELD; + } + } +} + +static FORCEINLINE int recursive_try_lock(MLOCK_T *lk) { + THREAD_ID_T mythreadid = CURRENT_THREAD; + if (*((volatile int *)(&lk->sl)) == 0) { + if (!CAS_LOCK(&lk->sl)) { + lk->threadid = mythreadid; + lk->c = 1; + return 1; + } + } + else if (EQ_OWNER(lk->threadid, mythreadid)) { + ++lk->c; + return 1; + } + return 0; +} + +#define RELEASE_LOCK(lk) recursive_release_lock(lk) +#define TRY_LOCK(lk) recursive_try_lock(lk) +#define ACQUIRE_LOCK(lk) recursive_acquire_lock(lk) +#define INITIAL_LOCK(lk) ((lk)->threadid = (THREAD_ID_T)0, (lk)->sl = 0, (lk)->c = 0) +#define DESTROY_LOCK(lk) (0) +#endif /* USE_RECURSIVE_LOCKS */ + +#elif defined(WIN32) /* Win32 critical sections */ +#define MLOCK_T CRITICAL_SECTION +#define ACQUIRE_LOCK(lk) (EnterCriticalSection(lk), 0) +#define RELEASE_LOCK(lk) LeaveCriticalSection(lk) +#define TRY_LOCK(lk) TryEnterCriticalSection(lk) +#define INITIAL_LOCK(lk) (!InitializeCriticalSectionAndSpinCount((lk), 0x80000000|4000)) +#define DESTROY_LOCK(lk) (DeleteCriticalSection(lk), 0) +#define NEED_GLOBAL_LOCK_INIT + +static MLOCK_T malloc_global_mutex; +static volatile LONG malloc_global_mutex_status; + +/* Use spin loop to initialize global lock */ +static void init_malloc_global_mutex() { + for (;;) { + long stat = malloc_global_mutex_status; + if (stat > 0) + return; + /* transition to < 0 while initializing, then to > 0) */ + if (stat == 0 && + interlockedcompareexchange(&malloc_global_mutex_status, (LONG)-1, (LONG)0) == 0) { + InitializeCriticalSection(&malloc_global_mutex); + interlockedexchange(&malloc_global_mutex_status, (LONG)1); + return; + } + SleepEx(0, FALSE); + } +} + +#else /* pthreads-based locks */ +#define MLOCK_T pthread_mutex_t +#define ACQUIRE_LOCK(lk) pthread_mutex_lock(lk) +#define RELEASE_LOCK(lk) pthread_mutex_unlock(lk) +#define TRY_LOCK(lk) (!pthread_mutex_trylock(lk)) +#define INITIAL_LOCK(lk) pthread_init_lock(lk) +#define DESTROY_LOCK(lk) pthread_mutex_destroy(lk) + +#if defined(USE_RECURSIVE_LOCKS) && USE_RECURSIVE_LOCKS != 0 && defined(linux) && !defined(PTHREAD_MUTEX_RECURSIVE) +/* Cope with old-style linux recursive lock initialization by adding */ +/* skipped internal declaration from pthread.h */ +extern int pthread_mutexattr_setkind_np __P ((pthread_mutexattr_t *__attr, + int __kind)); +#define PTHREAD_MUTEX_RECURSIVE PTHREAD_MUTEX_RECURSIVE_NP +#define pthread_mutexattr_settype(x,y) pthread_mutexattr_setkind_np(x,y) +#endif /* USE_RECURSIVE_LOCKS ... */ + +static MLOCK_T malloc_global_mutex = PTHREAD_MUTEX_INITIALIZER; + +static int pthread_init_lock (MLOCK_T *lk) { + pthread_mutexattr_t attr; + if (pthread_mutexattr_init(&attr)) return 1; +#if defined(USE_RECURSIVE_LOCKS) && USE_RECURSIVE_LOCKS != 0 + if (pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE)) return 1; +#endif + if (pthread_mutex_init(lk, &attr)) return 1; + if (pthread_mutexattr_destroy(&attr)) return 1; + return 0; +} + +#endif /* ... lock types ... */ + +/* Common code for all lock types */ +#define USE_LOCK_BIT (2U) + +#ifndef ACQUIRE_MALLOC_GLOBAL_LOCK +#define ACQUIRE_MALLOC_GLOBAL_LOCK() ACQUIRE_LOCK(&malloc_global_mutex); +#endif + +#ifndef RELEASE_MALLOC_GLOBAL_LOCK +#define RELEASE_MALLOC_GLOBAL_LOCK() RELEASE_LOCK(&malloc_global_mutex); +#endif + +#endif /* USE_LOCKS */ + +/* ----------------------- Chunk representations ------------------------ */ + +/* + (The following includes lightly edited explanations by Colin Plumb.) + + The malloc_chunk declaration below is misleading (but accurate and + necessary). It declares a "view" into memory allowing access to + necessary fields at known offsets from a given base. + + Chunks of memory are maintained using a `boundary tag' method as + originally described by Knuth. (See the paper by Paul Wilson + ftp://ftp.cs.utexas.edu/pub/garbage/allocsrv.ps for a survey of such + techniques.) Sizes of free chunks are stored both in the front of + each chunk and at the end. This makes consolidating fragmented + chunks into bigger chunks fast. The head fields also hold bits + representing whether chunks are free or in use. + + Here are some pictures to make it clearer. They are "exploded" to + show that the state of a chunk can be thought of as extending from + the high 31 bits of the head field of its header through the + prev_foot and PINUSE_BIT bit of the following chunk header. + + A chunk that's in use looks like: + + chunk-> +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | Size of previous chunk (if P = 0) | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ |P| + | Size of this chunk 1| +-+ + mem-> +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | | + +- -+ + | | + +- -+ + | : + +- size - sizeof(size_t) available payload bytes -+ + : | + chunk-> +- -+ + | | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ |1| + | Size of next chunk (may or may not be in use) | +-+ + mem-> +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + + And if it's free, it looks like this: + + chunk-> +- -+ + | User payload (must be in use, or we would have merged!) | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ |P| + | Size of this chunk 0| +-+ + mem-> +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | Next pointer | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | Prev pointer | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | : + +- size - sizeof(struct chunk) unused bytes -+ + : | + chunk-> +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | Size of this chunk | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ |0| + | Size of next chunk (must be in use, or we would have merged)| +-+ + mem-> +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | : + +- User payload -+ + : | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + |0| + +-+ + Note that since we always merge adjacent free chunks, the chunks + adjacent to a free chunk must be in use. + + Given a pointer to a chunk (which can be derived trivially from the + payload pointer) we can, in O(1) time, find out whether the adjacent + chunks are free, and if so, unlink them from the lists that they + are on and merge them with the current chunk. + + Chunks always begin on even word boundaries, so the mem portion + (which is returned to the user) is also on an even word boundary, and + thus at least double-word aligned. + + The P (PINUSE_BIT) bit, stored in the unused low-order bit of the + chunk size (which is always a multiple of two words), is an in-use + bit for the *previous* chunk. If that bit is *clear*, then the + word before the current chunk size contains the previous chunk + size, and can be used to find the front of the previous chunk. + The very first chunk allocated always has this bit set, preventing + access to non-existent (or non-owned) memory. If pinuse is set for + any given chunk, then you CANNOT determine the size of the + previous chunk, and might even get a memory addressing fault when + trying to do so. + + The C (CINUSE_BIT) bit, stored in the unused second-lowest bit of + the chunk size redundantly records whether the current chunk is + inuse (unless the chunk is mmapped). This redundancy enables usage + checks within free and realloc, and reduces indirection when freeing + and consolidating chunks. + + Each freshly allocated chunk must have both cinuse and pinuse set. + That is, each allocated chunk borders either a previously allocated + and still in-use chunk, or the base of its memory arena. This is + ensured by making all allocations from the `lowest' part of any + found chunk. Further, no free chunk physically borders another one, + so each free chunk is known to be preceded and followed by either + inuse chunks or the ends of memory. + + Note that the `foot' of the current chunk is actually represented + as the prev_foot of the NEXT chunk. This makes it easier to + deal with alignments etc but can be very confusing when trying + to extend or adapt this code. + + The exceptions to all this are + + 1. The special chunk `top' is the top-most available chunk (i.e., + the one bordering the end of available memory). It is treated + specially. Top is never included in any bin, is used only if + no other chunk is available, and is released back to the + system if it is very large (see M_TRIM_THRESHOLD). In effect, + the top chunk is treated as larger (and thus less well + fitting) than any other available chunk. The top chunk + doesn't update its trailing size field since there is no next + contiguous chunk that would have to index off it. However, + space is still allocated for it (TOP_FOOT_SIZE) to enable + separation or merging when space is extended. + + 3. Chunks allocated via mmap, have both cinuse and pinuse bits + cleared in their head fields. Because they are allocated + one-by-one, each must carry its own prev_foot field, which is + also used to hold the offset this chunk has within its mmapped + region, which is needed to preserve alignment. Each mmapped + chunk is trailed by the first two fields of a fake next-chunk + for sake of usage checks. + +*/ + +struct malloc_chunk { + size_t prev_foot; /* Size of previous chunk (if free). */ + size_t head; /* Size and inuse bits. */ + struct malloc_chunk* fd; /* double links -- used only if free. */ + struct malloc_chunk* bk; +}; + +typedef struct malloc_chunk mchunk; +typedef struct malloc_chunk* mchunkptr; +typedef struct malloc_chunk* sbinptr; /* The type of bins of chunks */ +typedef unsigned int bindex_t; /* Described below */ +typedef unsigned int binmap_t; /* Described below */ +typedef unsigned int flag_t; /* The type of various bit flag sets */ + +/* ------------------- Chunks sizes and alignments ----------------------- */ + +#define MCHUNK_SIZE (sizeof(mchunk)) + +#if FOOTERS +#define CHUNK_OVERHEAD (TWO_SIZE_T_SIZES) +#else /* FOOTERS */ +#define CHUNK_OVERHEAD (SIZE_T_SIZE) +#endif /* FOOTERS */ + +/* MMapped chunks need a second word of overhead ... */ +#define MMAP_CHUNK_OVERHEAD (TWO_SIZE_T_SIZES) +/* ... and additional padding for fake next-chunk at foot */ +#define MMAP_FOOT_PAD (FOUR_SIZE_T_SIZES) + +/* The smallest size we can malloc is an aligned minimal chunk */ +#define MIN_CHUNK_SIZE\ + ((MCHUNK_SIZE + CHUNK_ALIGN_MASK) & ~CHUNK_ALIGN_MASK) + +/* conversion from malloc headers to user pointers, and back */ +#define chunk2mem(p) ((void*)((char*)(p) + TWO_SIZE_T_SIZES)) +#define mem2chunk(mem) ((mchunkptr)((char*)(mem) - TWO_SIZE_T_SIZES)) +/* chunk associated with aligned address A */ +#define align_as_chunk(A) (mchunkptr)((A) + align_offset(chunk2mem(A))) + +/* Bounds on request (not chunk) sizes. */ +#define MAX_REQUEST ((-MIN_CHUNK_SIZE) << 2) +#define MIN_REQUEST (MIN_CHUNK_SIZE - CHUNK_OVERHEAD - SIZE_T_ONE) + +/* pad request bytes into a usable size */ +#define pad_request(req) \ + (((req) + CHUNK_OVERHEAD + CHUNK_ALIGN_MASK) & ~CHUNK_ALIGN_MASK) + +/* pad request, checking for minimum (but not maximum) */ +#define request2size(req) \ + (((req) < MIN_REQUEST)? MIN_CHUNK_SIZE : pad_request(req)) + + +/* ------------------ Operations on head and foot fields ----------------- */ + +/* + The head field of a chunk is or'ed with PINUSE_BIT when previous + adjacent chunk in use, and or'ed with CINUSE_BIT if this chunk is in + use, unless mmapped, in which case both bits are cleared. + + FLAG4_BIT is not used by this malloc, but might be useful in extensions. +*/ + +#define PINUSE_BIT (SIZE_T_ONE) +#define CINUSE_BIT (SIZE_T_TWO) +#define FLAG4_BIT (SIZE_T_FOUR) +#define INUSE_BITS (PINUSE_BIT|CINUSE_BIT) +#define FLAG_BITS (PINUSE_BIT|CINUSE_BIT|FLAG4_BIT) + +/* Head value for fenceposts */ +#define FENCEPOST_HEAD (INUSE_BITS|SIZE_T_SIZE) + +/* extraction of fields from head words */ +#define cinuse(p) ((p)->head & CINUSE_BIT) +#define pinuse(p) ((p)->head & PINUSE_BIT) +#define flag4inuse(p) ((p)->head & FLAG4_BIT) +#define is_inuse(p) (((p)->head & INUSE_BITS) != PINUSE_BIT) +#define is_mmapped(p) (((p)->head & INUSE_BITS) == 0) + +#define chunksize(p) ((p)->head & ~(FLAG_BITS)) + +#define clear_pinuse(p) ((p)->head &= ~PINUSE_BIT) +#define set_flag4(p) ((p)->head |= FLAG4_BIT) +#define clear_flag4(p) ((p)->head &= ~FLAG4_BIT) + +/* Treat space at ptr +/- offset as a chunk */ +#define chunk_plus_offset(p, s) ((mchunkptr)(((char*)(p)) + (s))) +#define chunk_minus_offset(p, s) ((mchunkptr)(((char*)(p)) - (s))) + +/* Ptr to next or previous physical malloc_chunk. */ +#define next_chunk(p) ((mchunkptr)( ((char*)(p)) + ((p)->head & ~FLAG_BITS))) +#define prev_chunk(p) ((mchunkptr)( ((char*)(p)) - ((p)->prev_foot) )) + +/* extract next chunk's pinuse bit */ +#define next_pinuse(p) ((next_chunk(p)->head) & PINUSE_BIT) + +/* Get/set size at footer */ +#define get_foot(p, s) (((mchunkptr)((char*)(p) + (s)))->prev_foot) +#define set_foot(p, s) (((mchunkptr)((char*)(p) + (s)))->prev_foot = (s)) + +/* Set size, pinuse bit, and foot */ +#define set_size_and_pinuse_of_free_chunk(p, s)\ + ((p)->head = (s|PINUSE_BIT), set_foot(p, s)) + +/* Set size, pinuse bit, foot, and clear next pinuse */ +#define set_free_with_pinuse(p, s, n)\ + (clear_pinuse(n), set_size_and_pinuse_of_free_chunk(p, s)) + +/* Get the internal overhead associated with chunk p */ +#define overhead_for(p)\ + (is_mmapped(p)? MMAP_CHUNK_OVERHEAD : CHUNK_OVERHEAD) + +/* Return true if malloced space is not necessarily cleared */ +#if MMAP_CLEARS +#define calloc_must_clear(p) (!is_mmapped(p)) +#else /* MMAP_CLEARS */ +#define calloc_must_clear(p) (1) +#endif /* MMAP_CLEARS */ + +/* ---------------------- Overlaid data structures ----------------------- */ + +/* + When chunks are not in use, they are treated as nodes of either + lists or trees. + + "Small" chunks are stored in circular doubly-linked lists, and look + like this: + + chunk-> +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | Size of previous chunk | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + `head:' | Size of chunk, in bytes |P| + mem-> +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | Forward pointer to next chunk in list | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | Back pointer to previous chunk in list | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | Unused space (may be 0 bytes long) . + . . + . | +nextchunk-> +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + `foot:' | Size of chunk, in bytes | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + + Larger chunks are kept in a form of bitwise digital trees (aka + tries) keyed on chunksizes. Because malloc_tree_chunks are only for + free chunks greater than 256 bytes, their size doesn't impose any + constraints on user chunk sizes. Each node looks like: + + chunk-> +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | Size of previous chunk | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + `head:' | Size of chunk, in bytes |P| + mem-> +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | Forward pointer to next chunk of same size | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | Back pointer to previous chunk of same size | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | Pointer to left child (child[0]) | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | Pointer to right child (child[1]) | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | Pointer to parent | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | bin index of this chunk | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | Unused space . + . | +nextchunk-> +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + `foot:' | Size of chunk, in bytes | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + + Each tree holding treenodes is a tree of unique chunk sizes. Chunks + of the same size are arranged in a circularly-linked list, with only + the oldest chunk (the next to be used, in our FIFO ordering) + actually in the tree. (Tree members are distinguished by a non-null + parent pointer.) If a chunk with the same size an an existing node + is inserted, it is linked off the existing node using pointers that + work in the same way as fd/bk pointers of small chunks. + + Each tree contains a power of 2 sized range of chunk sizes (the + smallest is 0x100 <= x < 0x180), which is is divided in half at each + tree level, with the chunks in the smaller half of the range (0x100 + <= x < 0x140 for the top nose) in the left subtree and the larger + half (0x140 <= x < 0x180) in the right subtree. This is, of course, + done by inspecting individual bits. + + Using these rules, each node's left subtree contains all smaller + sizes than its right subtree. However, the node at the root of each + subtree has no particular ordering relationship to either. (The + dividing line between the subtree sizes is based on trie relation.) + If we remove the last chunk of a given size from the interior of the + tree, we need to replace it with a leaf node. The tree ordering + rules permit a node to be replaced by any leaf below it. + + The smallest chunk in a tree (a common operation in a best-fit + allocator) can be found by walking a path to the leftmost leaf in + the tree. Unlike a usual binary tree, where we follow left child + pointers until we reach a null, here we follow the right child + pointer any time the left one is null, until we reach a leaf with + both child pointers null. The smallest chunk in the tree will be + somewhere along that path. + + The worst case number of steps to add, find, or remove a node is + bounded by the number of bits differentiating chunks within + bins. Under current bin calculations, this ranges from 6 up to 21 + (for 32 bit sizes) or up to 53 (for 64 bit sizes). The typical case + is of course much better. +*/ + +struct malloc_tree_chunk { + /* The first four fields must be compatible with malloc_chunk */ + size_t prev_foot; + size_t head; + struct malloc_tree_chunk* fd; + struct malloc_tree_chunk* bk; + + struct malloc_tree_chunk* child[2]; + struct malloc_tree_chunk* parent; + bindex_t index; +}; + +typedef struct malloc_tree_chunk tchunk; +typedef struct malloc_tree_chunk* tchunkptr; +typedef struct malloc_tree_chunk* tbinptr; /* The type of bins of trees */ + +/* A little helper macro for trees */ +#define leftmost_child(t) ((t)->child[0] != 0? (t)->child[0] : (t)->child[1]) + +/* ----------------------------- Segments -------------------------------- */ + +/* + Each malloc space may include non-contiguous segments, held in a + list headed by an embedded malloc_segment record representing the + top-most space. Segments also include flags holding properties of + the space. Large chunks that are directly allocated by mmap are not + included in this list. They are instead independently created and + destroyed without otherwise keeping track of them. + + Segment management mainly comes into play for spaces allocated by + MMAP. Any call to MMAP might or might not return memory that is + adjacent to an existing segment. MORECORE normally contiguously + extends the current space, so this space is almost always adjacent, + which is simpler and faster to deal with. (This is why MORECORE is + used preferentially to MMAP when both are available -- see + sys_alloc.) When allocating using MMAP, we don't use any of the + hinting mechanisms (inconsistently) supported in various + implementations of unix mmap, or distinguish reserving from + committing memory. Instead, we just ask for space, and exploit + contiguity when we get it. It is probably possible to do + better than this on some systems, but no general scheme seems + to be significantly better. + + Management entails a simpler variant of the consolidation scheme + used for chunks to reduce fragmentation -- new adjacent memory is + normally prepended or appended to an existing segment. However, + there are limitations compared to chunk consolidation that mostly + reflect the fact that segment processing is relatively infrequent + (occurring only when getting memory from system) and that we + don't expect to have huge numbers of segments: + + * Segments are not indexed, so traversal requires linear scans. (It + would be possible to index these, but is not worth the extra + overhead and complexity for most programs on most platforms.) + * New segments are only appended to old ones when holding top-most + memory; if they cannot be prepended to others, they are held in + different segments. + + Except for the top-most segment of an mstate, each segment record + is kept at the tail of its segment. Segments are added by pushing + segment records onto the list headed by &mstate.seg for the + containing mstate. + + Segment flags control allocation/merge/deallocation policies: + * If EXTERN_BIT set, then we did not allocate this segment, + and so should not try to deallocate or merge with others. + (This currently holds only for the initial segment passed + into create_mspace_with_base.) + * If USE_MMAP_BIT set, the segment may be merged with + other surrounding mmapped segments and trimmed/de-allocated + using munmap. + * If neither bit is set, then the segment was obtained using + MORECORE so can be merged with surrounding MORECORE'd segments + and deallocated/trimmed using MORECORE with negative arguments. +*/ + +struct malloc_segment { + char* base; /* base address */ + size_t size; /* allocated size */ + struct malloc_segment* next; /* ptr to next segment */ + flag_t sflags; /* mmap and extern flag */ +}; + +#define is_mmapped_segment(S) ((S)->sflags & USE_MMAP_BIT) +#define is_extern_segment(S) ((S)->sflags & EXTERN_BIT) + +typedef struct malloc_segment msegment; +typedef struct malloc_segment* msegmentptr; + +/* ---------------------------- malloc_state ----------------------------- */ + +/* + A malloc_state holds all of the bookkeeping for a space. + The main fields are: + + Top + The topmost chunk of the currently active segment. Its size is + cached in topsize. The actual size of topmost space is + topsize+TOP_FOOT_SIZE, which includes space reserved for adding + fenceposts and segment records if necessary when getting more + space from the system. The size at which to autotrim top is + cached from mparams in trim_check, except that it is disabled if + an autotrim fails. + + Designated victim (dv) + This is the preferred chunk for servicing small requests that + don't have exact fits. It is normally the chunk split off most + recently to service another small request. Its size is cached in + dvsize. The link fields of this chunk are not maintained since it + is not kept in a bin. + + SmallBins + An array of bin headers for free chunks. These bins hold chunks + with sizes less than MIN_LARGE_SIZE bytes. Each bin contains + chunks of all the same size, spaced 8 bytes apart. To simplify + use in double-linked lists, each bin header acts as a malloc_chunk + pointing to the real first node, if it exists (else pointing to + itself). This avoids special-casing for headers. But to avoid + waste, we allocate only the fd/bk pointers of bins, and then use + repositioning tricks to treat these as the fields of a chunk. + + TreeBins + Treebins are pointers to the roots of trees holding a range of + sizes. There are 2 equally spaced treebins for each power of two + from TREE_SHIFT to TREE_SHIFT+16. The last bin holds anything + larger. + + Bin maps + There is one bit map for small bins ("smallmap") and one for + treebins ("treemap). Each bin sets its bit when non-empty, and + clears the bit when empty. Bit operations are then used to avoid + bin-by-bin searching -- nearly all "search" is done without ever + looking at bins that won't be selected. The bit maps + conservatively use 32 bits per map word, even if on 64bit system. + For a good description of some of the bit-based techniques used + here, see Henry S. Warren Jr's book "Hacker's Delight" (and + supplement at http://hackersdelight.org/). Many of these are + intended to reduce the branchiness of paths through malloc etc, as + well as to reduce the number of memory locations read or written. + + Segments + A list of segments headed by an embedded malloc_segment record + representing the initial space. + + Address check support + The least_addr field is the least address ever obtained from + MORECORE or MMAP. Attempted frees and reallocs of any address less + than this are trapped (unless INSECURE is defined). + + Magic tag + A cross-check field that should always hold same value as mparams.magic. + + Max allowed footprint + The maximum allowed bytes to allocate from system (zero means no limit) + + Flags + Bits recording whether to use MMAP, locks, or contiguous MORECORE + + Statistics + Each space keeps track of current and maximum system memory + obtained via MORECORE or MMAP. + + Trim support + Fields holding the amount of unused topmost memory that should trigger + trimming, and a counter to force periodic scanning to release unused + non-topmost segments. + + Locking + If USE_LOCKS is defined, the "mutex" lock is acquired and released + around every public call using this mspace. + + Extension support + A void* pointer and a size_t field that can be used to help implement + extensions to this malloc. +*/ + +/* Bin types, widths and sizes */ +#define NSMALLBINS (32U) +#define NTREEBINS (32U) +#define SMALLBIN_SHIFT (3U) +#define SMALLBIN_WIDTH (SIZE_T_ONE << SMALLBIN_SHIFT) +#define TREEBIN_SHIFT (8U) +#define MIN_LARGE_SIZE (SIZE_T_ONE << TREEBIN_SHIFT) +#define MAX_SMALL_SIZE (MIN_LARGE_SIZE - SIZE_T_ONE) +#define MAX_SMALL_REQUEST (MAX_SMALL_SIZE - CHUNK_ALIGN_MASK - CHUNK_OVERHEAD) + +struct malloc_state { + binmap_t smallmap; + binmap_t treemap; + size_t dvsize; + size_t topsize; + char* least_addr; + mchunkptr dv; + mchunkptr top; + size_t trim_check; + size_t release_checks; + size_t magic; + mchunkptr smallbins[(NSMALLBINS+1)*2]; + tbinptr treebins[NTREEBINS]; + size_t footprint; + size_t max_footprint; + size_t footprint_limit; /* zero means no limit */ + flag_t mflags; +#if USE_LOCKS + MLOCK_T mutex; /* locate lock among fields that rarely change */ +#endif /* USE_LOCKS */ + msegment seg; + void* extp; /* Unused but available for extensions */ + size_t exts; +}; + +typedef struct malloc_state* mstate; + +/* ------------- Global malloc_state and malloc_params ------------------- */ + +/* + malloc_params holds global properties, including those that can be + dynamically set using mallopt. There is a single instance, mparams, + initialized in init_mparams. Note that the non-zeroness of "magic" + also serves as an initialization flag. +*/ + +struct malloc_params { + size_t magic; + size_t page_size; + size_t granularity; + size_t mmap_threshold; + size_t trim_threshold; + flag_t default_mflags; +}; + +static struct malloc_params mparams; + +/* Ensure mparams initialized */ +#define ensure_initialization() (void)(mparams.magic != 0 || init_mparams()) + +#if !ONLY_MSPACES + +/* The global malloc_state used for all non-"mspace" calls */ +static struct malloc_state _gm_; +#define gm (&_gm_) +#define is_global(M) ((M) == &_gm_) + +#endif /* !ONLY_MSPACES */ + +#define is_initialized(M) ((M)->top != 0) + +/* -------------------------- system alloc setup ------------------------- */ + +/* Operations on mflags */ + +#define use_lock(M) ((M)->mflags & USE_LOCK_BIT) +#define enable_lock(M) ((M)->mflags |= USE_LOCK_BIT) +#if USE_LOCKS +#define disable_lock(M) ((M)->mflags &= ~USE_LOCK_BIT) +#else +#define disable_lock(M) +#endif + +#define use_mmap(M) ((M)->mflags & USE_MMAP_BIT) +#define enable_mmap(M) ((M)->mflags |= USE_MMAP_BIT) +#if HAVE_MMAP +#define disable_mmap(M) ((M)->mflags &= ~USE_MMAP_BIT) +#else +#define disable_mmap(M) +#endif + +#define use_noncontiguous(M) ((M)->mflags & USE_NONCONTIGUOUS_BIT) +#define disable_contiguous(M) ((M)->mflags |= USE_NONCONTIGUOUS_BIT) + +#define set_lock(M,L)\ + ((M)->mflags = (L)?\ + ((M)->mflags | USE_LOCK_BIT) :\ + ((M)->mflags & ~USE_LOCK_BIT)) + +/* page-align a size */ +#define page_align(S)\ + (((S) + (mparams.page_size - SIZE_T_ONE)) & ~(mparams.page_size - SIZE_T_ONE)) + +/* granularity-align a size */ +#define granularity_align(S)\ + (((S) + (mparams.granularity - SIZE_T_ONE))\ + & ~(mparams.granularity - SIZE_T_ONE)) + + +/* For mmap, use granularity alignment on windows, else page-align */ +#ifdef WIN32 +#define mmap_align(S) granularity_align(S) +#else +#define mmap_align(S) page_align(S) +#endif + +/* For sys_alloc, enough padding to ensure can malloc request on success */ +#define SYS_ALLOC_PADDING (TOP_FOOT_SIZE + MALLOC_ALIGNMENT) + +#define is_page_aligned(S)\ + (((size_t)(S) & (mparams.page_size - SIZE_T_ONE)) == 0) +#define is_granularity_aligned(S)\ + (((size_t)(S) & (mparams.granularity - SIZE_T_ONE)) == 0) + +/* True if segment S holds address A */ +#define segment_holds(S, A)\ + ((char*)(A) >= S->base && (char*)(A) < S->base + S->size) + +/* Return segment holding given address */ +static msegmentptr segment_holding(mstate m, char* addr) { + msegmentptr sp = &m->seg; + for (;;) { + if (addr >= sp->base && addr < sp->base + sp->size) + return sp; + if ((sp = sp->next) == 0) + return 0; + } +} + +/* Return true if segment contains a segment link */ +static int has_segment_link(mstate m, msegmentptr ss) { + msegmentptr sp = &m->seg; + for (;;) { + if ((char*)sp >= ss->base && (char*)sp < ss->base + ss->size) + return 1; + if ((sp = sp->next) == 0) + return 0; + } +} + +#ifndef MORECORE_CANNOT_TRIM +#define should_trim(M,s) ((s) > (M)->trim_check) +#else /* MORECORE_CANNOT_TRIM */ +#define should_trim(M,s) (0) +#endif /* MORECORE_CANNOT_TRIM */ + +/* + TOP_FOOT_SIZE is padding at the end of a segment, including space + that may be needed to place segment records and fenceposts when new + noncontiguous segments are added. +*/ +#define TOP_FOOT_SIZE\ + (align_offset(chunk2mem(0))+pad_request(sizeof(struct malloc_segment))+MIN_CHUNK_SIZE) + + +/* ------------------------------- Hooks -------------------------------- */ + +/* + PREACTION should be defined to return 0 on success, and nonzero on + failure. If you are not using locking, you can redefine these to do + anything you like. +*/ + +#if USE_LOCKS +#define PREACTION(M) ((use_lock(M))? ACQUIRE_LOCK(&(M)->mutex) : 0) +#define POSTACTION(M) { if (use_lock(M)) RELEASE_LOCK(&(M)->mutex); } +#else /* USE_LOCKS */ + +#ifndef PREACTION +#define PREACTION(M) (0) +#endif /* PREACTION */ + +#ifndef POSTACTION +#define POSTACTION(M) +#endif /* POSTACTION */ + +#endif /* USE_LOCKS */ + +/* + CORRUPTION_ERROR_ACTION is triggered upon detected bad addresses. + USAGE_ERROR_ACTION is triggered on detected bad frees and + reallocs. The argument p is an address that might have triggered the + fault. It is ignored by the two predefined actions, but might be + useful in custom actions that try to help diagnose errors. +*/ + +#if PROCEED_ON_ERROR + +/* A count of the number of corruption errors causing resets */ +int malloc_corruption_error_count; + +/* default corruption action */ +static void reset_on_error(mstate m); + +#define CORRUPTION_ERROR_ACTION(m) reset_on_error(m) +#define USAGE_ERROR_ACTION(m, p) + +#else /* PROCEED_ON_ERROR */ + +#ifndef CORRUPTION_ERROR_ACTION +#define CORRUPTION_ERROR_ACTION(m) ABORT +#endif /* CORRUPTION_ERROR_ACTION */ + +#ifndef USAGE_ERROR_ACTION +#define USAGE_ERROR_ACTION(m,p) ABORT +#endif /* USAGE_ERROR_ACTION */ + +#endif /* PROCEED_ON_ERROR */ + + +/* -------------------------- Debugging setup ---------------------------- */ + +#if ! DEBUG + +#define check_free_chunk(M,P) +#define check_inuse_chunk(M,P) +#define check_malloced_chunk(M,P,N) +#define check_mmapped_chunk(M,P) +#define check_malloc_state(M) +#define check_top_chunk(M,P) + +#else /* DEBUG */ +#define check_free_chunk(M,P) do_check_free_chunk(M,P) +#define check_inuse_chunk(M,P) do_check_inuse_chunk(M,P) +#define check_top_chunk(M,P) do_check_top_chunk(M,P) +#define check_malloced_chunk(M,P,N) do_check_malloced_chunk(M,P,N) +#define check_mmapped_chunk(M,P) do_check_mmapped_chunk(M,P) +#define check_malloc_state(M) do_check_malloc_state(M) + +static void do_check_any_chunk(mstate m, mchunkptr p); +static void do_check_top_chunk(mstate m, mchunkptr p); +static void do_check_mmapped_chunk(mstate m, mchunkptr p); +static void do_check_inuse_chunk(mstate m, mchunkptr p); +static void do_check_free_chunk(mstate m, mchunkptr p); +static void do_check_malloced_chunk(mstate m, void* mem, size_t s); +static void do_check_tree(mstate m, tchunkptr t); +static void do_check_treebin(mstate m, bindex_t i); +static void do_check_smallbin(mstate m, bindex_t i); +static void do_check_malloc_state(mstate m); +static int bin_find(mstate m, mchunkptr x); +static size_t traverse_and_check(mstate m); +#endif /* DEBUG */ + +/* ---------------------------- Indexing Bins ---------------------------- */ + +#define is_small(s) (((s) >> SMALLBIN_SHIFT) < NSMALLBINS) +#define small_index(s) (bindex_t)((s) >> SMALLBIN_SHIFT) +#define small_index2size(i) ((i) << SMALLBIN_SHIFT) +#define MIN_SMALL_INDEX (small_index(MIN_CHUNK_SIZE)) + +/* addressing by index. See above about smallbin repositioning */ +#define smallbin_at(M, i) ((sbinptr)((char*)&((M)->smallbins[(i)<<1]))) +#define treebin_at(M,i) (&((M)->treebins[i])) + +/* assign tree index for size S to variable I. Use x86 asm if possible */ +#if defined(__GNUC__) && (defined(__i386__) || defined(__x86_64__)) +#define compute_tree_index(S, I)\ +{\ + unsigned int X = S >> TREEBIN_SHIFT;\ + if (X == 0)\ + I = 0;\ + else if (X > 0xFFFF)\ + I = NTREEBINS-1;\ + else {\ + unsigned int K = (unsigned) sizeof(X)*__CHAR_BIT__ - 1 - (unsigned) __builtin_clz(X); \ + I = (bindex_t)((K << 1) + ((S >> (K + (TREEBIN_SHIFT-1)) & 1)));\ + }\ +} + +#elif defined (__INTEL_COMPILER) +#define compute_tree_index(S, I)\ +{\ + size_t X = S >> TREEBIN_SHIFT;\ + if (X == 0)\ + I = 0;\ + else if (X > 0xFFFF)\ + I = NTREEBINS-1;\ + else {\ + unsigned int K = _bit_scan_reverse (X); \ + I = (bindex_t)((K << 1) + ((S >> (K + (TREEBIN_SHIFT-1)) & 1)));\ + }\ +} + +#elif defined(_MSC_VER) && _MSC_VER>=1300 +#define compute_tree_index(S, I)\ +{\ + size_t X = S >> TREEBIN_SHIFT;\ + if (X == 0)\ + I = 0;\ + else if (X > 0xFFFF)\ + I = NTREEBINS-1;\ + else {\ + unsigned int K;\ + _BitScanReverse((DWORD *) &K, (DWORD) X);\ + I = (bindex_t)((K << 1) + ((S >> (K + (TREEBIN_SHIFT-1)) & 1)));\ + }\ +} + +#else /* GNUC */ +#define compute_tree_index(S, I)\ +{\ + size_t X = S >> TREEBIN_SHIFT;\ + if (X == 0)\ + I = 0;\ + else if (X > 0xFFFF)\ + I = NTREEBINS-1;\ + else {\ + unsigned int Y = (unsigned int)X;\ + unsigned int N = ((Y - 0x100) >> 16) & 8;\ + unsigned int K = (((Y <<= N) - 0x1000) >> 16) & 4;\ + N += K;\ + N += K = (((Y <<= K) - 0x4000) >> 16) & 2;\ + K = 14 - N + ((Y <<= K) >> 15);\ + I = (K << 1) + ((S >> (K + (TREEBIN_SHIFT-1)) & 1));\ + }\ +} +#endif /* GNUC */ + +/* Bit representing maximum resolved size in a treebin at i */ +#define bit_for_tree_index(i) \ + (i == NTREEBINS-1)? (SIZE_T_BITSIZE-1) : (((i) >> 1) + TREEBIN_SHIFT - 2) + +/* Shift placing maximum resolved bit in a treebin at i as sign bit */ +#define leftshift_for_tree_index(i) \ + ((i == NTREEBINS-1)? 0 : \ + ((SIZE_T_BITSIZE-SIZE_T_ONE) - (((i) >> 1) + TREEBIN_SHIFT - 2))) + +/* The size of the smallest chunk held in bin with index i */ +#define minsize_for_tree_index(i) \ + ((SIZE_T_ONE << (((i) >> 1) + TREEBIN_SHIFT)) | \ + (((size_t)((i) & SIZE_T_ONE)) << (((i) >> 1) + TREEBIN_SHIFT - 1))) + + +/* ------------------------ Operations on bin maps ----------------------- */ + +/* bit corresponding to given index */ +#define idx2bit(i) ((binmap_t)(1) << (i)) + +/* Mark/Clear bits with given index */ +#define mark_smallmap(M,i) ((M)->smallmap |= idx2bit(i)) +#define clear_smallmap(M,i) ((M)->smallmap &= ~idx2bit(i)) +#define smallmap_is_marked(M,i) ((M)->smallmap & idx2bit(i)) + +#define mark_treemap(M,i) ((M)->treemap |= idx2bit(i)) +#define clear_treemap(M,i) ((M)->treemap &= ~idx2bit(i)) +#define treemap_is_marked(M,i) ((M)->treemap & idx2bit(i)) + +/* isolate the least set bit of a bitmap */ +#define least_bit(x) ((x) & -(x)) + +/* mask with all bits to left of least bit of x on */ +#define left_bits(x) ((x<<1) | -(x<<1)) + +/* mask with all bits to left of or equal to least bit of x on */ +#define same_or_left_bits(x) ((x) | -(x)) + +/* index corresponding to given bit. Use x86 asm if possible */ + +#if defined(__GNUC__) && (defined(__i386__) || defined(__x86_64__)) +#define compute_bit2idx(X, I)\ +{\ + unsigned int J;\ + J = __builtin_ctz(X); \ + I = (bindex_t)J;\ +} + +#elif defined (__INTEL_COMPILER) +#define compute_bit2idx(X, I)\ +{\ + unsigned int J;\ + J = _bit_scan_forward (X); \ + I = (bindex_t)J;\ +} + +#elif defined(_MSC_VER) && _MSC_VER>=1300 +#define compute_bit2idx(X, I)\ +{\ + unsigned int J;\ + _BitScanForward((DWORD *) &J, X);\ + I = (bindex_t)J;\ +} + +#elif USE_BUILTIN_FFS +#define compute_bit2idx(X, I) I = ffs(X)-1 + +#else +#define compute_bit2idx(X, I)\ +{\ + unsigned int Y = X - 1;\ + unsigned int K = Y >> (16-4) & 16;\ + unsigned int N = K; Y >>= K;\ + N += K = Y >> (8-3) & 8; Y >>= K;\ + N += K = Y >> (4-2) & 4; Y >>= K;\ + N += K = Y >> (2-1) & 2; Y >>= K;\ + N += K = Y >> (1-0) & 1; Y >>= K;\ + I = (bindex_t)(N + Y);\ +} +#endif /* GNUC */ + + +/* ----------------------- Runtime Check Support ------------------------- */ + +/* + For security, the main invariant is that malloc/free/etc never + writes to a static address other than malloc_state, unless static + malloc_state itself has been corrupted, which cannot occur via + malloc (because of these checks). In essence this means that we + believe all pointers, sizes, maps etc held in malloc_state, but + check all of those linked or offsetted from other embedded data + structures. These checks are interspersed with main code in a way + that tends to minimize their run-time cost. + + When FOOTERS is defined, in addition to range checking, we also + verify footer fields of inuse chunks, which can be used guarantee + that the mstate controlling malloc/free is intact. This is a + streamlined version of the approach described by William Robertson + et al in "Run-time Detection of Heap-based Overflows" LISA'03 + http://www.usenix.org/events/lisa03/tech/robertson.html The footer + of an inuse chunk holds the xor of its mstate and a random seed, + that is checked upon calls to free() and realloc(). This is + (probabalistically) unguessable from outside the program, but can be + computed by any code successfully malloc'ing any chunk, so does not + itself provide protection against code that has already broken + security through some other means. Unlike Robertson et al, we + always dynamically check addresses of all offset chunks (previous, + next, etc). This turns out to be cheaper than relying on hashes. +*/ + +#if !INSECURE +/* Check if address a is at least as high as any from MORECORE or MMAP */ +#define ok_address(M, a) ((char*)(a) >= (M)->least_addr) +/* Check if address of next chunk n is higher than base chunk p */ +#define ok_next(p, n) ((char*)(p) < (char*)(n)) +/* Check if p has inuse status */ +#define ok_inuse(p) is_inuse(p) +/* Check if p has its pinuse bit on */ +#define ok_pinuse(p) pinuse(p) + +#else /* !INSECURE */ +#define ok_address(M, a) (1) +#define ok_next(b, n) (1) +#define ok_inuse(p) (1) +#define ok_pinuse(p) (1) +#endif /* !INSECURE */ + +#if (FOOTERS && !INSECURE) +/* Check if (alleged) mstate m has expected magic field */ +#define ok_magic(M) ((M)->magic == mparams.magic) +#else /* (FOOTERS && !INSECURE) */ +#define ok_magic(M) (1) +#endif /* (FOOTERS && !INSECURE) */ + +/* In gcc, use __builtin_expect to minimize impact of checks */ +#if !INSECURE +#if defined(__GNUC__) && __GNUC__ >= 3 +#define RTCHECK(e) __builtin_expect(e, 1) +#else /* GNUC */ +#define RTCHECK(e) (e) +#endif /* GNUC */ +#else /* !INSECURE */ +#define RTCHECK(e) (1) +#endif /* !INSECURE */ + +/* macros to set up inuse chunks with or without footers */ + +#if !FOOTERS + +#define mark_inuse_foot(M,p,s) + +/* Macros for setting head/foot of non-mmapped chunks */ + +/* Set cinuse bit and pinuse bit of next chunk */ +#define set_inuse(M,p,s)\ + ((p)->head = (((p)->head & PINUSE_BIT)|s|CINUSE_BIT),\ + ((mchunkptr)(((char*)(p)) + (s)))->head |= PINUSE_BIT) + +/* Set cinuse and pinuse of this chunk and pinuse of next chunk */ +#define set_inuse_and_pinuse(M,p,s)\ + ((p)->head = (s|PINUSE_BIT|CINUSE_BIT),\ + ((mchunkptr)(((char*)(p)) + (s)))->head |= PINUSE_BIT) + +/* Set size, cinuse and pinuse bit of this chunk */ +#define set_size_and_pinuse_of_inuse_chunk(M, p, s)\ + ((p)->head = (s|PINUSE_BIT|CINUSE_BIT)) + +#else /* FOOTERS */ + +/* Set foot of inuse chunk to be xor of mstate and seed */ +#define mark_inuse_foot(M,p,s)\ + (((mchunkptr)((char*)(p) + (s)))->prev_foot = ((size_t)(M) ^ mparams.magic)) + +#define get_mstate_for(p)\ + ((mstate)(((mchunkptr)((char*)(p) +\ + (chunksize(p))))->prev_foot ^ mparams.magic)) + +#define set_inuse(M,p,s)\ + ((p)->head = (((p)->head & PINUSE_BIT)|s|CINUSE_BIT),\ + (((mchunkptr)(((char*)(p)) + (s)))->head |= PINUSE_BIT), \ + mark_inuse_foot(M,p,s)) + +#define set_inuse_and_pinuse(M,p,s)\ + ((p)->head = (s|PINUSE_BIT|CINUSE_BIT),\ + (((mchunkptr)(((char*)(p)) + (s)))->head |= PINUSE_BIT),\ + mark_inuse_foot(M,p,s)) + +#define set_size_and_pinuse_of_inuse_chunk(M, p, s)\ + ((p)->head = (s|PINUSE_BIT|CINUSE_BIT),\ + mark_inuse_foot(M, p, s)) + +#endif /* !FOOTERS */ + +/* ---------------------------- setting mparams -------------------------- */ + +#if LOCK_AT_FORK +static void pre_fork(void) { ACQUIRE_LOCK(&(gm)->mutex); } +static void post_fork_parent(void) { RELEASE_LOCK(&(gm)->mutex); } +static void post_fork_child(void) { INITIAL_LOCK(&(gm)->mutex); } +#endif /* LOCK_AT_FORK */ + +/* Initialize mparams */ +static int init_mparams(void) { +#ifdef NEED_GLOBAL_LOCK_INIT + if (malloc_global_mutex_status <= 0) + init_malloc_global_mutex(); +#endif + + ACQUIRE_MALLOC_GLOBAL_LOCK(); + if (mparams.magic == 0) { + size_t magic; + size_t psize; + size_t gsize; + +#ifndef WIN32 + psize = malloc_getpagesize; + gsize = ((DEFAULT_GRANULARITY != 0)? DEFAULT_GRANULARITY : psize); +#else /* WIN32 */ + { + SYSTEM_INFO system_info; + GetSystemInfo(&system_info); + psize = system_info.dwPageSize; + gsize = ((DEFAULT_GRANULARITY != 0)? + DEFAULT_GRANULARITY : system_info.dwAllocationGranularity); + } +#endif /* WIN32 */ + + /* Sanity-check configuration: + size_t must be unsigned and as wide as pointer type. + ints must be at least 4 bytes. + alignment must be at least 8. + Alignment, min chunk size, and page size must all be powers of 2. + */ + if ((sizeof(size_t) != sizeof(char*)) || + (MAX_SIZE_T < MIN_CHUNK_SIZE) || + (sizeof(int) < 4) || + (MALLOC_ALIGNMENT < (size_t)8U) || + ((MALLOC_ALIGNMENT & (MALLOC_ALIGNMENT-SIZE_T_ONE)) != 0) || + ((MCHUNK_SIZE & (MCHUNK_SIZE-SIZE_T_ONE)) != 0) || + ((gsize & (gsize-SIZE_T_ONE)) != 0) || + ((psize & (psize-SIZE_T_ONE)) != 0)) + ABORT; + mparams.granularity = gsize; + mparams.page_size = psize; + mparams.mmap_threshold = DEFAULT_MMAP_THRESHOLD; + mparams.trim_threshold = DEFAULT_TRIM_THRESHOLD; +#if MORECORE_CONTIGUOUS + mparams.default_mflags = USE_LOCK_BIT|USE_MMAP_BIT; +#else /* MORECORE_CONTIGUOUS */ + mparams.default_mflags = USE_LOCK_BIT|USE_MMAP_BIT|USE_NONCONTIGUOUS_BIT; +#endif /* MORECORE_CONTIGUOUS */ + +#if !ONLY_MSPACES + /* Set up lock for main malloc area */ + gm->mflags = mparams.default_mflags; + (void)INITIAL_LOCK(&gm->mutex); +#endif +#if LOCK_AT_FORK + pthread_atfork(&pre_fork, &post_fork_parent, &post_fork_child); +#endif + + { +#if USE_DEV_RANDOM + int fd; + unsigned char buf[sizeof(size_t)]; + /* Try to use /dev/urandom, else fall back on using time */ + if ((fd = open("/dev/urandom", O_RDONLY)) >= 0 && + read(fd, buf, sizeof(buf)) == sizeof(buf)) { + magic = *((size_t *) buf); + close(fd); + } + else +#endif /* USE_DEV_RANDOM */ +#ifdef WIN32 + magic = (size_t)(GetTickCount() ^ (size_t)0x55555555U); +#elif defined(LACKS_TIME_H) + magic = (size_t)&magic ^ (size_t)0x55555555U; +#else + magic = (size_t)(time(0) ^ (size_t)0x55555555U); +#endif + magic |= (size_t)8U; /* ensure nonzero */ + magic &= ~(size_t)7U; /* improve chances of fault for bad values */ + /* Until memory modes commonly available, use volatile-write */ + (*(volatile size_t *)(&(mparams.magic))) = magic; + } + } + + RELEASE_MALLOC_GLOBAL_LOCK(); + return 1; +} + +/* support for mallopt */ +static int change_mparam(int param_number, int value) { + size_t val; + ensure_initialization(); + val = (value == -1)? MAX_SIZE_T : (size_t)value; + switch(param_number) { + case M_TRIM_THRESHOLD: + mparams.trim_threshold = val; + return 1; + case M_GRANULARITY: + if (val >= mparams.page_size && ((val & (val-1)) == 0)) { + mparams.granularity = val; + return 1; + } + else + return 0; + case M_MMAP_THRESHOLD: + mparams.mmap_threshold = val; + return 1; + default: + return 0; + } +} + +#if DEBUG +/* ------------------------- Debugging Support --------------------------- */ + +/* Check properties of any chunk, whether free, inuse, mmapped etc */ +static void do_check_any_chunk(mstate m, mchunkptr p) { + assert((is_aligned(chunk2mem(p))) || (p->head == FENCEPOST_HEAD)); + assert(ok_address(m, p)); +} + +/* Check properties of top chunk */ +static void do_check_top_chunk(mstate m, mchunkptr p) { + msegmentptr sp = segment_holding(m, (char*)p); + size_t sz = p->head & ~INUSE_BITS; /* third-lowest bit can be set! */ + assert(sp != 0); + assert((is_aligned(chunk2mem(p))) || (p->head == FENCEPOST_HEAD)); + assert(ok_address(m, p)); + assert(sz == m->topsize); + assert(sz > 0); + assert(sz == ((sp->base + sp->size) - (char*)p) - TOP_FOOT_SIZE); + assert(pinuse(p)); + assert(!pinuse(chunk_plus_offset(p, sz))); +} + +/* Check properties of (inuse) mmapped chunks */ +static void do_check_mmapped_chunk(mstate m, mchunkptr p) { + size_t sz = chunksize(p); + size_t len = (sz + (p->prev_foot) + MMAP_FOOT_PAD); + assert(is_mmapped(p)); + assert(use_mmap(m)); + assert((is_aligned(chunk2mem(p))) || (p->head == FENCEPOST_HEAD)); + assert(ok_address(m, p)); + assert(!is_small(sz)); + assert((len & (mparams.page_size-SIZE_T_ONE)) == 0); + assert(chunk_plus_offset(p, sz)->head == FENCEPOST_HEAD); + assert(chunk_plus_offset(p, sz+SIZE_T_SIZE)->head == 0); +} + +/* Check properties of inuse chunks */ +static void do_check_inuse_chunk(mstate m, mchunkptr p) { + do_check_any_chunk(m, p); + assert(is_inuse(p)); + assert(next_pinuse(p)); + /* If not pinuse and not mmapped, previous chunk has OK offset */ + assert(is_mmapped(p) || pinuse(p) || next_chunk(prev_chunk(p)) == p); + if (is_mmapped(p)) + do_check_mmapped_chunk(m, p); +} + +/* Check properties of free chunks */ +static void do_check_free_chunk(mstate m, mchunkptr p) { + size_t sz = chunksize(p); + mchunkptr next = chunk_plus_offset(p, sz); + do_check_any_chunk(m, p); + assert(!is_inuse(p)); + assert(!next_pinuse(p)); + assert (!is_mmapped(p)); + if (p != m->dv && p != m->top) { + if (sz >= MIN_CHUNK_SIZE) { + assert((sz & CHUNK_ALIGN_MASK) == 0); + assert(is_aligned(chunk2mem(p))); + assert(next->prev_foot == sz); + assert(pinuse(p)); + assert (next == m->top || is_inuse(next)); + assert(p->fd->bk == p); + assert(p->bk->fd == p); + } + else /* markers are always of size SIZE_T_SIZE */ + assert(sz == SIZE_T_SIZE); + } +} + +/* Check properties of malloced chunks at the point they are malloced */ +static void do_check_malloced_chunk(mstate m, void* mem, size_t s) { + if (mem != 0) { + mchunkptr p = mem2chunk(mem); + size_t sz = p->head & ~INUSE_BITS; + do_check_inuse_chunk(m, p); + assert((sz & CHUNK_ALIGN_MASK) == 0); + assert(sz >= MIN_CHUNK_SIZE); + assert(sz >= s); + /* unless mmapped, size is less than MIN_CHUNK_SIZE more than request */ + assert(is_mmapped(p) || sz < (s + MIN_CHUNK_SIZE)); + } +} + +/* Check a tree and its subtrees. */ +static void do_check_tree(mstate m, tchunkptr t) { + tchunkptr head = 0; + tchunkptr u = t; + bindex_t tindex = t->index; + size_t tsize = chunksize(t); + bindex_t idx; + compute_tree_index(tsize, idx); + assert(tindex == idx); + assert(tsize >= MIN_LARGE_SIZE); + assert(tsize >= minsize_for_tree_index(idx)); + assert((idx == NTREEBINS-1) || (tsize < minsize_for_tree_index((idx+1)))); + + do { /* traverse through chain of same-sized nodes */ + do_check_any_chunk(m, ((mchunkptr)u)); + assert(u->index == tindex); + assert(chunksize(u) == tsize); + assert(!is_inuse(u)); + assert(!next_pinuse(u)); + assert(u->fd->bk == u); + assert(u->bk->fd == u); + if (u->parent == 0) { + assert(u->child[0] == 0); + assert(u->child[1] == 0); + } + else { + assert(head == 0); /* only one node on chain has parent */ + head = u; + assert(u->parent != u); + assert (u->parent->child[0] == u || + u->parent->child[1] == u || + *((tbinptr*)(u->parent)) == u); + if (u->child[0] != 0) { + assert(u->child[0]->parent == u); + assert(u->child[0] != u); + do_check_tree(m, u->child[0]); + } + if (u->child[1] != 0) { + assert(u->child[1]->parent == u); + assert(u->child[1] != u); + do_check_tree(m, u->child[1]); + } + if (u->child[0] != 0 && u->child[1] != 0) { + assert(chunksize(u->child[0]) < chunksize(u->child[1])); + } + } + u = u->fd; + } while (u != t); + assert(head != 0); +} + +/* Check all the chunks in a treebin. */ +static void do_check_treebin(mstate m, bindex_t i) { + tbinptr* tb = treebin_at(m, i); + tchunkptr t = *tb; + int empty = (m->treemap & (1U << i)) == 0; + if (t == 0) + assert(empty); + if (!empty) + do_check_tree(m, t); +} + +/* Check all the chunks in a smallbin. */ +static void do_check_smallbin(mstate m, bindex_t i) { + sbinptr b = smallbin_at(m, i); + mchunkptr p = b->bk; + unsigned int empty = (m->smallmap & (1U << i)) == 0; + if (p == b) + assert(empty); + if (!empty) { + for (; p != b; p = p->bk) { + size_t size = chunksize(p); + mchunkptr q; + /* each chunk claims to be free */ + do_check_free_chunk(m, p); + /* chunk belongs in bin */ + assert(small_index(size) == i); + assert(p->bk == b || chunksize(p->bk) == chunksize(p)); + /* chunk is followed by an inuse chunk */ + q = next_chunk(p); + if (q->head != FENCEPOST_HEAD) + do_check_inuse_chunk(m, q); + } + } +} + +/* Find x in a bin. Used in other check functions. */ +static int bin_find(mstate m, mchunkptr x) { + size_t size = chunksize(x); + if (is_small(size)) { + bindex_t sidx = small_index(size); + sbinptr b = smallbin_at(m, sidx); + if (smallmap_is_marked(m, sidx)) { + mchunkptr p = b; + do { + if (p == x) + return 1; + } while ((p = p->fd) != b); + } + } + else { + bindex_t tidx; + compute_tree_index(size, tidx); + if (treemap_is_marked(m, tidx)) { + tchunkptr t = *treebin_at(m, tidx); + size_t sizebits = size << leftshift_for_tree_index(tidx); + while (t != 0 && chunksize(t) != size) { + t = t->child[(sizebits >> (SIZE_T_BITSIZE-SIZE_T_ONE)) & 1]; + sizebits <<= 1; + } + if (t != 0) { + tchunkptr u = t; + do { + if (u == (tchunkptr)x) + return 1; + } while ((u = u->fd) != t); + } + } + } + return 0; +} + +/* Traverse each chunk and check it; return total */ +static size_t traverse_and_check(mstate m) { + size_t sum = 0; + if (is_initialized(m)) { + msegmentptr s = &m->seg; + sum += m->topsize + TOP_FOOT_SIZE; + while (s != 0) { + mchunkptr q = align_as_chunk(s->base); + mchunkptr lastq = 0; + assert(pinuse(q)); + while (segment_holds(s, q) && + q != m->top && q->head != FENCEPOST_HEAD) { + sum += chunksize(q); + if (is_inuse(q)) { + assert(!bin_find(m, q)); + do_check_inuse_chunk(m, q); + } + else { + assert(q == m->dv || bin_find(m, q)); + assert(lastq == 0 || is_inuse(lastq)); /* Not 2 consecutive free */ + do_check_free_chunk(m, q); + } + lastq = q; + q = next_chunk(q); + } + s = s->next; + } + } + return sum; +} + + +/* Check all properties of malloc_state. */ +static void do_check_malloc_state(mstate m) { + bindex_t i; + size_t total; + /* check bins */ + for (i = 0; i < NSMALLBINS; ++i) + do_check_smallbin(m, i); + for (i = 0; i < NTREEBINS; ++i) + do_check_treebin(m, i); + + if (m->dvsize != 0) { /* check dv chunk */ + do_check_any_chunk(m, m->dv); + assert(m->dvsize == chunksize(m->dv)); + assert(m->dvsize >= MIN_CHUNK_SIZE); + assert(bin_find(m, m->dv) == 0); + } + + if (m->top != 0) { /* check top chunk */ + do_check_top_chunk(m, m->top); + /*assert(m->topsize == chunksize(m->top)); redundant */ + assert(m->topsize > 0); + assert(bin_find(m, m->top) == 0); + } + + total = traverse_and_check(m); + assert(total <= m->footprint); + assert(m->footprint <= m->max_footprint); +} +#endif /* DEBUG */ + +/* ----------------------------- statistics ------------------------------ */ + +#if !NO_MALLINFO +static struct mallinfo internal_mallinfo(mstate m) { + struct mallinfo nm = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; + ensure_initialization(); + if (!PREACTION(m)) { + check_malloc_state(m); + if (is_initialized(m)) { + size_t nfree = SIZE_T_ONE; /* top always free */ + size_t mfree = m->topsize + TOP_FOOT_SIZE; + size_t sum = mfree; + msegmentptr s = &m->seg; + while (s != 0) { + mchunkptr q = align_as_chunk(s->base); + while (segment_holds(s, q) && + q != m->top && q->head != FENCEPOST_HEAD) { + size_t sz = chunksize(q); + sum += sz; + if (!is_inuse(q)) { + mfree += sz; + ++nfree; + } + q = next_chunk(q); + } + s = s->next; + } + + nm.arena = sum; + nm.ordblks = nfree; + nm.hblkhd = m->footprint - sum; + nm.usmblks = m->max_footprint; + nm.uordblks = m->footprint - mfree; + nm.fordblks = mfree; + nm.keepcost = m->topsize; + } + + POSTACTION(m); + } + return nm; +} +#endif /* !NO_MALLINFO */ + +#if !NO_MALLOC_STATS +static void internal_malloc_stats(mstate m) { + ensure_initialization(); + if (!PREACTION(m)) { + size_t maxfp = 0; + size_t fp = 0; + size_t used = 0; + check_malloc_state(m); + if (is_initialized(m)) { + msegmentptr s = &m->seg; + maxfp = m->max_footprint; + fp = m->footprint; + used = fp - (m->topsize + TOP_FOOT_SIZE); + + while (s != 0) { + mchunkptr q = align_as_chunk(s->base); + while (segment_holds(s, q) && + q != m->top && q->head != FENCEPOST_HEAD) { + if (!is_inuse(q)) + used -= chunksize(q); + q = next_chunk(q); + } + s = s->next; + } + } + POSTACTION(m); /* drop lock */ + fprintf(stderr, "max system bytes = %10lu\n", (unsigned long)(maxfp)); + fprintf(stderr, "system bytes = %10lu\n", (unsigned long)(fp)); + fprintf(stderr, "in use bytes = %10lu\n", (unsigned long)(used)); + } +} +#endif /* NO_MALLOC_STATS */ + +/* ----------------------- Operations on smallbins ----------------------- */ + +/* + Various forms of linking and unlinking are defined as macros. Even + the ones for trees, which are very long but have very short typical + paths. This is ugly but reduces reliance on inlining support of + compilers. +*/ + +/* Link a free chunk into a smallbin */ +#define insert_small_chunk(M, P, S) {\ + bindex_t I = small_index(S);\ + mchunkptr B = smallbin_at(M, I);\ + mchunkptr F = B;\ + assert(S >= MIN_CHUNK_SIZE);\ + if (!smallmap_is_marked(M, I))\ + mark_smallmap(M, I);\ + else if (RTCHECK(ok_address(M, B->fd)))\ + F = B->fd;\ + else {\ + CORRUPTION_ERROR_ACTION(M);\ + }\ + B->fd = P;\ + F->bk = P;\ + P->fd = F;\ + P->bk = B;\ +} + +/* Unlink a chunk from a smallbin */ +#define unlink_small_chunk(M, P, S) {\ + mchunkptr F = P->fd;\ + mchunkptr B = P->bk;\ + bindex_t I = small_index(S);\ + assert(P != B);\ + assert(P != F);\ + assert(chunksize(P) == small_index2size(I));\ + if (RTCHECK(F == smallbin_at(M,I) || (ok_address(M, F) && F->bk == P))) { \ + if (B == F) {\ + clear_smallmap(M, I);\ + }\ + else if (RTCHECK(B == smallbin_at(M,I) ||\ + (ok_address(M, B) && B->fd == P))) {\ + F->bk = B;\ + B->fd = F;\ + }\ + else {\ + CORRUPTION_ERROR_ACTION(M);\ + }\ + }\ + else {\ + CORRUPTION_ERROR_ACTION(M);\ + }\ +} + +/* Unlink the first chunk from a smallbin */ +#define unlink_first_small_chunk(M, B, P, I) {\ + mchunkptr F = P->fd;\ + assert(P != B);\ + assert(P != F);\ + assert(chunksize(P) == small_index2size(I));\ + if (B == F) {\ + clear_smallmap(M, I);\ + }\ + else if (RTCHECK(ok_address(M, F) && F->bk == P)) {\ + F->bk = B;\ + B->fd = F;\ + }\ + else {\ + CORRUPTION_ERROR_ACTION(M);\ + }\ +} + +/* Replace dv node, binning the old one */ +/* Used only when dvsize known to be small */ +#define replace_dv(M, P, S) {\ + size_t DVS = M->dvsize;\ + assert(is_small(DVS));\ + if (DVS != 0) {\ + mchunkptr DV = M->dv;\ + insert_small_chunk(M, DV, DVS);\ + }\ + M->dvsize = S;\ + M->dv = P;\ +} + +/* ------------------------- Operations on trees ------------------------- */ + +/* Insert chunk into tree */ +#define insert_large_chunk(M, X, S) {\ + tbinptr* H;\ + bindex_t I;\ + compute_tree_index(S, I);\ + H = treebin_at(M, I);\ + X->index = I;\ + X->child[0] = X->child[1] = 0;\ + if (!treemap_is_marked(M, I)) {\ + mark_treemap(M, I);\ + *H = X;\ + X->parent = (tchunkptr)H;\ + X->fd = X->bk = X;\ + }\ + else {\ + tchunkptr T = *H;\ + size_t K = S << leftshift_for_tree_index(I);\ + for (;;) {\ + if (chunksize(T) != S) {\ + tchunkptr* C = &(T->child[(K >> (SIZE_T_BITSIZE-SIZE_T_ONE)) & 1]);\ + K <<= 1;\ + if (*C != 0)\ + T = *C;\ + else if (RTCHECK(ok_address(M, C))) {\ + *C = X;\ + X->parent = T;\ + X->fd = X->bk = X;\ + break;\ + }\ + else {\ + CORRUPTION_ERROR_ACTION(M);\ + break;\ + }\ + }\ + else {\ + tchunkptr F = T->fd;\ + if (RTCHECK(ok_address(M, T) && ok_address(M, F))) {\ + T->fd = F->bk = X;\ + X->fd = F;\ + X->bk = T;\ + X->parent = 0;\ + break;\ + }\ + else {\ + CORRUPTION_ERROR_ACTION(M);\ + break;\ + }\ + }\ + }\ + }\ +} + +/* + Unlink steps: + + 1. If x is a chained node, unlink it from its same-sized fd/bk links + and choose its bk node as its replacement. + 2. If x was the last node of its size, but not a leaf node, it must + be replaced with a leaf node (not merely one with an open left or + right), to make sure that lefts and rights of descendents + correspond properly to bit masks. We use the rightmost descendent + of x. We could use any other leaf, but this is easy to locate and + tends to counteract removal of leftmosts elsewhere, and so keeps + paths shorter than minimally guaranteed. This doesn't loop much + because on average a node in a tree is near the bottom. + 3. If x is the base of a chain (i.e., has parent links) relink + x's parent and children to x's replacement (or null if none). +*/ + +#define unlink_large_chunk(M, X) {\ + tchunkptr XP = X->parent;\ + tchunkptr R;\ + if (X->bk != X) {\ + tchunkptr F = X->fd;\ + R = X->bk;\ + if (RTCHECK(ok_address(M, F) && F->bk == X && R->fd == X)) {\ + F->bk = R;\ + R->fd = F;\ + }\ + else {\ + CORRUPTION_ERROR_ACTION(M);\ + }\ + }\ + else {\ + tchunkptr* RP;\ + if (((R = *(RP = &(X->child[1]))) != 0) ||\ + ((R = *(RP = &(X->child[0]))) != 0)) {\ + tchunkptr* CP;\ + while ((*(CP = &(R->child[1])) != 0) ||\ + (*(CP = &(R->child[0])) != 0)) {\ + R = *(RP = CP);\ + }\ + if (RTCHECK(ok_address(M, RP)))\ + *RP = 0;\ + else {\ + CORRUPTION_ERROR_ACTION(M);\ + }\ + }\ + }\ + if (XP != 0) {\ + tbinptr* H = treebin_at(M, X->index);\ + if (X == *H) {\ + if ((*H = R) == 0) \ + clear_treemap(M, X->index);\ + }\ + else if (RTCHECK(ok_address(M, XP))) {\ + if (XP->child[0] == X) \ + XP->child[0] = R;\ + else \ + XP->child[1] = R;\ + }\ + else\ + CORRUPTION_ERROR_ACTION(M);\ + if (R != 0) {\ + if (RTCHECK(ok_address(M, R))) {\ + tchunkptr C0, C1;\ + R->parent = XP;\ + if ((C0 = X->child[0]) != 0) {\ + if (RTCHECK(ok_address(M, C0))) {\ + R->child[0] = C0;\ + C0->parent = R;\ + }\ + else\ + CORRUPTION_ERROR_ACTION(M);\ + }\ + if ((C1 = X->child[1]) != 0) {\ + if (RTCHECK(ok_address(M, C1))) {\ + R->child[1] = C1;\ + C1->parent = R;\ + }\ + else\ + CORRUPTION_ERROR_ACTION(M);\ + }\ + }\ + else\ + CORRUPTION_ERROR_ACTION(M);\ + }\ + }\ +} + +/* Relays to large vs small bin operations */ + +#define insert_chunk(M, P, S)\ + if (is_small(S)) insert_small_chunk(M, P, S)\ + else { tchunkptr TP = (tchunkptr)(P); insert_large_chunk(M, TP, S); } + +#define unlink_chunk(M, P, S)\ + if (is_small(S)) unlink_small_chunk(M, P, S)\ + else { tchunkptr TP = (tchunkptr)(P); unlink_large_chunk(M, TP); } + + +/* Relays to internal calls to malloc/free from realloc, memalign etc */ + +#if ONLY_MSPACES +#define internal_malloc(m, b) mspace_malloc(m, b) +#define internal_free(m, mem) mspace_free(m,mem); +#else /* ONLY_MSPACES */ +#if MSPACES +#define internal_malloc(m, b)\ + ((m == gm)? dlmalloc(b) : mspace_malloc(m, b)) +#define internal_free(m, mem)\ + if (m == gm) dlfree(mem); else mspace_free(m,mem); +#else /* MSPACES */ +#define internal_malloc(m, b) dlmalloc(b) +#define internal_free(m, mem) dlfree(mem) +#endif /* MSPACES */ +#endif /* ONLY_MSPACES */ + +/* ----------------------- Direct-mmapping chunks ----------------------- */ + +/* + Directly mmapped chunks are set up with an offset to the start of + the mmapped region stored in the prev_foot field of the chunk. This + allows reconstruction of the required argument to MUNMAP when freed, + and also allows adjustment of the returned chunk to meet alignment + requirements (especially in memalign). +*/ + +/* Malloc using mmap */ +static void* mmap_alloc(mstate m, size_t nb) { + size_t mmsize = mmap_align(nb + SIX_SIZE_T_SIZES + CHUNK_ALIGN_MASK); + if (m->footprint_limit != 0) { + size_t fp = m->footprint + mmsize; + if (fp <= m->footprint || fp > m->footprint_limit) + return 0; + } + if (mmsize > nb) { /* Check for wrap around 0 */ + char* mm = (char*)(CALL_DIRECT_MMAP(mmsize)); + if (mm != CMFAIL) { + size_t offset = align_offset(chunk2mem(mm)); + size_t psize = mmsize - offset - MMAP_FOOT_PAD; + mchunkptr p = (mchunkptr)(mm + offset); + p->prev_foot = offset; + p->head = psize; + mark_inuse_foot(m, p, psize); + chunk_plus_offset(p, psize)->head = FENCEPOST_HEAD; + chunk_plus_offset(p, psize+SIZE_T_SIZE)->head = 0; + + if (m->least_addr == 0 || mm < m->least_addr) + m->least_addr = mm; + if ((m->footprint += mmsize) > m->max_footprint) + m->max_footprint = m->footprint; + assert(is_aligned(chunk2mem(p))); + check_mmapped_chunk(m, p); + return chunk2mem(p); + } + } + return 0; +} + +/* Realloc using mmap */ +static mchunkptr mmap_resize(mstate m, mchunkptr oldp, size_t nb, int flags) { + size_t oldsize = chunksize(oldp); + (void)flags; /* placate people compiling -Wunused */ + if (is_small(nb)) /* Can't shrink mmap regions below small size */ + return 0; + /* Keep old chunk if big enough but not too big */ + if (oldsize >= nb + SIZE_T_SIZE && + (oldsize - nb) <= (mparams.granularity << 1)) + return oldp; + else { + size_t offset = oldp->prev_foot; + size_t oldmmsize = oldsize + offset + MMAP_FOOT_PAD; + size_t newmmsize = mmap_align(nb + SIX_SIZE_T_SIZES + CHUNK_ALIGN_MASK); + char* cp = (char*)CALL_MREMAP((char*)oldp - offset, + oldmmsize, newmmsize, flags); + if (cp != CMFAIL) { + mchunkptr newp = (mchunkptr)(cp + offset); + size_t psize = newmmsize - offset - MMAP_FOOT_PAD; + newp->head = psize; + mark_inuse_foot(m, newp, psize); + chunk_plus_offset(newp, psize)->head = FENCEPOST_HEAD; + chunk_plus_offset(newp, psize+SIZE_T_SIZE)->head = 0; + + if (cp < m->least_addr) + m->least_addr = cp; + if ((m->footprint += newmmsize - oldmmsize) > m->max_footprint) + m->max_footprint = m->footprint; + check_mmapped_chunk(m, newp); + return newp; + } + } + return 0; +} + + +/* -------------------------- mspace management -------------------------- */ + +/* Initialize top chunk and its size */ +static void init_top(mstate m, mchunkptr p, size_t psize) { + /* Ensure alignment */ + size_t offset = align_offset(chunk2mem(p)); + p = (mchunkptr)((char*)p + offset); + psize -= offset; + + m->top = p; + m->topsize = psize; + p->head = psize | PINUSE_BIT; + /* set size of fake trailing chunk holding overhead space only once */ + chunk_plus_offset(p, psize)->head = TOP_FOOT_SIZE; + m->trim_check = mparams.trim_threshold; /* reset on each update */ +} + +/* Initialize bins for a new mstate that is otherwise zeroed out */ +static void init_bins(mstate m) { + /* Establish circular links for smallbins */ + bindex_t i; + for (i = 0; i < NSMALLBINS; ++i) { + sbinptr bin = smallbin_at(m,i); + bin->fd = bin->bk = bin; + } +} + +#if PROCEED_ON_ERROR + +/* default corruption action */ +static void reset_on_error(mstate m) { + int i; + ++malloc_corruption_error_count; + /* Reinitialize fields to forget about all memory */ + m->smallmap = m->treemap = 0; + m->dvsize = m->topsize = 0; + m->seg.base = 0; + m->seg.size = 0; + m->seg.next = 0; + m->top = m->dv = 0; + for (i = 0; i < NTREEBINS; ++i) + *treebin_at(m, i) = 0; + init_bins(m); +} +#endif /* PROCEED_ON_ERROR */ + +/* Allocate chunk and prepend remainder with chunk in successor base. */ +static void* prepend_alloc(mstate m, char* newbase, char* oldbase, + size_t nb) { + mchunkptr p = align_as_chunk(newbase); + mchunkptr oldfirst = align_as_chunk(oldbase); + size_t psize = (char*)oldfirst - (char*)p; + mchunkptr q = chunk_plus_offset(p, nb); + size_t qsize = psize - nb; + set_size_and_pinuse_of_inuse_chunk(m, p, nb); + + assert((char*)oldfirst > (char*)q); + assert(pinuse(oldfirst)); + assert(qsize >= MIN_CHUNK_SIZE); + + /* consolidate remainder with first chunk of old base */ + if (oldfirst == m->top) { + size_t tsize = m->topsize += qsize; + m->top = q; + q->head = tsize | PINUSE_BIT; + check_top_chunk(m, q); + } + else if (oldfirst == m->dv) { + size_t dsize = m->dvsize += qsize; + m->dv = q; + set_size_and_pinuse_of_free_chunk(q, dsize); + } + else { + if (!is_inuse(oldfirst)) { + size_t nsize = chunksize(oldfirst); + unlink_chunk(m, oldfirst, nsize); + oldfirst = chunk_plus_offset(oldfirst, nsize); + qsize += nsize; + } + set_free_with_pinuse(q, qsize, oldfirst); + insert_chunk(m, q, qsize); + check_free_chunk(m, q); + } + + check_malloced_chunk(m, chunk2mem(p), nb); + return chunk2mem(p); +} + +/* Add a segment to hold a new noncontiguous region */ +static void add_segment(mstate m, char* tbase, size_t tsize, flag_t mmapped) { + /* Determine locations and sizes of segment, fenceposts, old top */ + char* old_top = (char*)m->top; + msegmentptr oldsp = segment_holding(m, old_top); + char* old_end = oldsp->base + oldsp->size; + size_t ssize = pad_request(sizeof(struct malloc_segment)); + char* rawsp = old_end - (ssize + FOUR_SIZE_T_SIZES + CHUNK_ALIGN_MASK); + size_t offset = align_offset(chunk2mem(rawsp)); + char* asp = rawsp + offset; + char* csp = (asp < (old_top + MIN_CHUNK_SIZE))? old_top : asp; + mchunkptr sp = (mchunkptr)csp; + msegmentptr ss = (msegmentptr)(chunk2mem(sp)); + mchunkptr tnext = chunk_plus_offset(sp, ssize); + mchunkptr p = tnext; + int nfences = 0; + + /* reset top to new space */ + init_top(m, (mchunkptr)tbase, tsize - TOP_FOOT_SIZE); + + /* Set up segment record */ + assert(is_aligned(ss)); + set_size_and_pinuse_of_inuse_chunk(m, sp, ssize); + *ss = m->seg; /* Push current record */ + m->seg.base = tbase; + m->seg.size = tsize; + m->seg.sflags = mmapped; + m->seg.next = ss; + + /* Insert trailing fenceposts */ + for (;;) { + mchunkptr nextp = chunk_plus_offset(p, SIZE_T_SIZE); + p->head = FENCEPOST_HEAD; + ++nfences; + if ((char*)(&(nextp->head)) < old_end) + p = nextp; + else + break; + } + assert(nfences >= 2); + + /* Insert the rest of old top into a bin as an ordinary free chunk */ + if (csp != old_top) { + mchunkptr q = (mchunkptr)old_top; + size_t psize = csp - old_top; + mchunkptr tn = chunk_plus_offset(q, psize); + set_free_with_pinuse(q, psize, tn); + insert_chunk(m, q, psize); + } + + check_top_chunk(m, m->top); +} + +/* -------------------------- System allocation -------------------------- */ + +/* Get memory from system using MORECORE or MMAP */ +static void* sys_alloc(mstate m, size_t nb) { + char* tbase = CMFAIL; + size_t tsize = 0; + flag_t mmap_flag = 0; + size_t asize; /* allocation size */ + + ensure_initialization(); + + /* Directly map large chunks, but only if already initialized */ + if (use_mmap(m) && nb >= mparams.mmap_threshold && m->topsize != 0) { + void* mem = mmap_alloc(m, nb); + if (mem != 0) + return mem; + } + + asize = granularity_align(nb + SYS_ALLOC_PADDING); + if (asize <= nb) + return 0; /* wraparound */ + if (m->footprint_limit != 0) { + size_t fp = m->footprint + asize; + if (fp <= m->footprint || fp > m->footprint_limit) + return 0; + } + + /* + Try getting memory in any of three ways (in most-preferred to + least-preferred order): + 1. A call to MORECORE that can normally contiguously extend memory. + (disabled if not MORECORE_CONTIGUOUS or not HAVE_MORECORE or + or main space is mmapped or a previous contiguous call failed) + 2. A call to MMAP new space (disabled if not HAVE_MMAP). + Note that under the default settings, if MORECORE is unable to + fulfill a request, and HAVE_MMAP is true, then mmap is + used as a noncontiguous system allocator. This is a useful backup + strategy for systems with holes in address spaces -- in this case + sbrk cannot contiguously expand the heap, but mmap may be able to + find space. + 3. A call to MORECORE that cannot usually contiguously extend memory. + (disabled if not HAVE_MORECORE) + + In all cases, we need to request enough bytes from system to ensure + we can malloc nb bytes upon success, so pad with enough space for + top_foot, plus alignment-pad to make sure we don't lose bytes if + not on boundary, and round this up to a granularity unit. + */ + + if (MORECORE_CONTIGUOUS && !use_noncontiguous(m)) { + char* br = CMFAIL; + size_t ssize = asize; /* sbrk call size */ + msegmentptr ss = (m->top == 0)? 0 : segment_holding(m, (char*)m->top); + ACQUIRE_MALLOC_GLOBAL_LOCK(); + + if (ss == 0) { /* First time through or recovery */ + char* base = (char*)CALL_MORECORE(0); + if (base != CMFAIL) { + size_t fp; + /* Adjust to end on a page boundary */ + if (!is_page_aligned(base)) + ssize += (page_align((size_t)base) - (size_t)base); + fp = m->footprint + ssize; /* recheck limits */ + if (ssize > nb && ssize < HALF_MAX_SIZE_T && + (m->footprint_limit == 0 || + (fp > m->footprint && fp <= m->footprint_limit)) && + (br = (char*)(CALL_MORECORE(ssize))) == base) { + tbase = base; + tsize = ssize; + } + } + } + else { + /* Subtract out existing available top space from MORECORE request. */ + ssize = granularity_align(nb - m->topsize + SYS_ALLOC_PADDING); + /* Use mem here only if it did continuously extend old space */ + if (ssize < HALF_MAX_SIZE_T && + (br = (char*)(CALL_MORECORE(ssize))) == ss->base+ss->size) { + tbase = br; + tsize = ssize; + } + } + + if (tbase == CMFAIL) { /* Cope with partial failure */ + if (br != CMFAIL) { /* Try to use/extend the space we did get */ + if (ssize < HALF_MAX_SIZE_T && + ssize < nb + SYS_ALLOC_PADDING) { + size_t esize = granularity_align(nb + SYS_ALLOC_PADDING - ssize); + if (esize < HALF_MAX_SIZE_T) { + char* end = (char*)CALL_MORECORE(esize); + if (end != CMFAIL) + ssize += esize; + else { /* Can't use; try to release */ + (void) CALL_MORECORE(-ssize); + br = CMFAIL; + } + } + } + } + if (br != CMFAIL) { /* Use the space we did get */ + tbase = br; + tsize = ssize; + } + else + disable_contiguous(m); /* Don't try contiguous path in the future */ + } + + RELEASE_MALLOC_GLOBAL_LOCK(); + } + + if (HAVE_MMAP && tbase == CMFAIL) { /* Try MMAP */ + char* mp = (char*)(CALL_MMAP(asize)); + if (mp != CMFAIL) { + tbase = mp; + tsize = asize; + mmap_flag = USE_MMAP_BIT; + } + } + + if (HAVE_MORECORE && tbase == CMFAIL) { /* Try noncontiguous MORECORE */ + if (asize < HALF_MAX_SIZE_T) { + char* br = CMFAIL; + char* end = CMFAIL; + ACQUIRE_MALLOC_GLOBAL_LOCK(); + br = (char*)(CALL_MORECORE(asize)); + end = (char*)(CALL_MORECORE(0)); + RELEASE_MALLOC_GLOBAL_LOCK(); + if (br != CMFAIL && end != CMFAIL && br < end) { + size_t ssize = end - br; + if (ssize > nb + TOP_FOOT_SIZE) { + tbase = br; + tsize = ssize; + } + } + } + } + + if (tbase != CMFAIL) { + + if ((m->footprint += tsize) > m->max_footprint) + m->max_footprint = m->footprint; + + if (!is_initialized(m)) { /* first-time initialization */ + if (m->least_addr == 0 || tbase < m->least_addr) + m->least_addr = tbase; + m->seg.base = tbase; + m->seg.size = tsize; + m->seg.sflags = mmap_flag; + m->magic = mparams.magic; + m->release_checks = MAX_RELEASE_CHECK_RATE; + init_bins(m); +#if !ONLY_MSPACES + if (is_global(m)) + init_top(m, (mchunkptr)tbase, tsize - TOP_FOOT_SIZE); + else +#endif + { + /* Offset top by embedded malloc_state */ + mchunkptr mn = next_chunk(mem2chunk(m)); + init_top(m, mn, (size_t)((tbase + tsize) - (char*)mn) -TOP_FOOT_SIZE); + } + } + + else { + /* Try to merge with an existing segment */ + msegmentptr sp = &m->seg; + /* Only consider most recent segment if traversal suppressed */ + while (sp != 0 && tbase != sp->base + sp->size) + sp = (NO_SEGMENT_TRAVERSAL) ? 0 : sp->next; + if (sp != 0 && + !is_extern_segment(sp) && + (sp->sflags & USE_MMAP_BIT) == mmap_flag && + segment_holds(sp, m->top)) { /* append */ + sp->size += tsize; + init_top(m, m->top, m->topsize + tsize); + } + else { + if (tbase < m->least_addr) + m->least_addr = tbase; + sp = &m->seg; + while (sp != 0 && sp->base != tbase + tsize) + sp = (NO_SEGMENT_TRAVERSAL) ? 0 : sp->next; + if (sp != 0 && + !is_extern_segment(sp) && + (sp->sflags & USE_MMAP_BIT) == mmap_flag) { + char* oldbase = sp->base; + sp->base = tbase; + sp->size += tsize; + return prepend_alloc(m, tbase, oldbase, nb); + } + else + add_segment(m, tbase, tsize, mmap_flag); + } + } + + if (nb < m->topsize) { /* Allocate from new or extended top space */ + size_t rsize = m->topsize -= nb; + mchunkptr p = m->top; + mchunkptr r = m->top = chunk_plus_offset(p, nb); + r->head = rsize | PINUSE_BIT; + set_size_and_pinuse_of_inuse_chunk(m, p, nb); + check_top_chunk(m, m->top); + check_malloced_chunk(m, chunk2mem(p), nb); + return chunk2mem(p); + } + } + + MALLOC_FAILURE_ACTION; + return 0; +} + +/* ----------------------- system deallocation -------------------------- */ + +/* Unmap and unlink any mmapped segments that don't contain used chunks */ +static size_t release_unused_segments(mstate m) { + size_t released = 0; + int nsegs = 0; + msegmentptr pred = &m->seg; + msegmentptr sp = pred->next; + while (sp != 0) { + char* base = sp->base; + size_t size = sp->size; + msegmentptr next = sp->next; + ++nsegs; + if (is_mmapped_segment(sp) && !is_extern_segment(sp)) { + mchunkptr p = align_as_chunk(base); + size_t psize = chunksize(p); + /* Can unmap if first chunk holds entire segment and not pinned */ + if (!is_inuse(p) && (char*)p + psize >= base + size - TOP_FOOT_SIZE) { + tchunkptr tp = (tchunkptr)p; + assert(segment_holds(sp, (char*)sp)); + if (p == m->dv) { + m->dv = 0; + m->dvsize = 0; + } + else { + unlink_large_chunk(m, tp); + } + if (CALL_MUNMAP(base, size) == 0) { + released += size; + m->footprint -= size; + /* unlink obsoleted record */ + sp = pred; + sp->next = next; + } + else { /* back out if cannot unmap */ + insert_large_chunk(m, tp, psize); + } + } + } + if (NO_SEGMENT_TRAVERSAL) /* scan only first segment */ + break; + pred = sp; + sp = next; + } + /* Reset check counter */ + m->release_checks = (((size_t) nsegs > (size_t) MAX_RELEASE_CHECK_RATE)? + (size_t) nsegs : (size_t) MAX_RELEASE_CHECK_RATE); + return released; +} + +static int sys_trim(mstate m, size_t pad) { + size_t released = 0; + ensure_initialization(); + if (pad < MAX_REQUEST && is_initialized(m)) { + pad += TOP_FOOT_SIZE; /* ensure enough room for segment overhead */ + + if (m->topsize > pad) { + /* Shrink top space in granularity-size units, keeping at least one */ + size_t unit = mparams.granularity; + size_t extra = ((m->topsize - pad + (unit - SIZE_T_ONE)) / unit - + SIZE_T_ONE) * unit; + msegmentptr sp = segment_holding(m, (char*)m->top); + + if (!is_extern_segment(sp)) { + if (is_mmapped_segment(sp)) { + if (HAVE_MMAP && + sp->size >= extra && + !has_segment_link(m, sp)) { /* can't shrink if pinned */ + size_t newsize = sp->size - extra; + (void)newsize; /* placate people compiling -Wunused-variable */ + /* Prefer mremap, fall back to munmap */ + if ((CALL_MREMAP(sp->base, sp->size, newsize, 0) != MFAIL) || + (CALL_MUNMAP(sp->base + newsize, extra) == 0)) { + released = extra; + } + } + } + else if (HAVE_MORECORE) { + if (extra >= HALF_MAX_SIZE_T) /* Avoid wrapping negative */ + extra = (HALF_MAX_SIZE_T) + SIZE_T_ONE - unit; + ACQUIRE_MALLOC_GLOBAL_LOCK(); + { + /* Make sure end of memory is where we last set it. */ + char* old_br = (char*)(CALL_MORECORE(0)); + if (old_br == sp->base + sp->size) { + char* rel_br = (char*)(CALL_MORECORE(-extra)); + char* new_br = (char*)(CALL_MORECORE(0)); + if (rel_br != CMFAIL && new_br < old_br) + released = old_br - new_br; + } + } + RELEASE_MALLOC_GLOBAL_LOCK(); + } + } + + if (released != 0) { + sp->size -= released; + m->footprint -= released; + init_top(m, m->top, m->topsize - released); + check_top_chunk(m, m->top); + } + } + + /* Unmap any unused mmapped segments */ + if (HAVE_MMAP) + released += release_unused_segments(m); + + /* On failure, disable autotrim to avoid repeated failed future calls */ + if (released == 0 && m->topsize > m->trim_check) + m->trim_check = MAX_SIZE_T; + } + + return (released != 0)? 1 : 0; +} + +/* Consolidate and bin a chunk. Differs from exported versions + of free mainly in that the chunk need not be marked as inuse. +*/ +static void dispose_chunk(mstate m, mchunkptr p, size_t psize) { + mchunkptr next = chunk_plus_offset(p, psize); + if (!pinuse(p)) { + mchunkptr prev; + size_t prevsize = p->prev_foot; + if (is_mmapped(p)) { + psize += prevsize + MMAP_FOOT_PAD; + if (CALL_MUNMAP((char*)p - prevsize, psize) == 0) + m->footprint -= psize; + return; + } + prev = chunk_minus_offset(p, prevsize); + psize += prevsize; + p = prev; + if (RTCHECK(ok_address(m, prev))) { /* consolidate backward */ + if (p != m->dv) { + unlink_chunk(m, p, prevsize); + } + else if ((next->head & INUSE_BITS) == INUSE_BITS) { + m->dvsize = psize; + set_free_with_pinuse(p, psize, next); + return; + } + } + else { + CORRUPTION_ERROR_ACTION(m); + return; + } + } + if (RTCHECK(ok_address(m, next))) { + if (!cinuse(next)) { /* consolidate forward */ + if (next == m->top) { + size_t tsize = m->topsize += psize; + m->top = p; + p->head = tsize | PINUSE_BIT; + if (p == m->dv) { + m->dv = 0; + m->dvsize = 0; + } + return; + } + else if (next == m->dv) { + size_t dsize = m->dvsize += psize; + m->dv = p; + set_size_and_pinuse_of_free_chunk(p, dsize); + return; + } + else { + size_t nsize = chunksize(next); + psize += nsize; + unlink_chunk(m, next, nsize); + set_size_and_pinuse_of_free_chunk(p, psize); + if (p == m->dv) { + m->dvsize = psize; + return; + } + } + } + else { + set_free_with_pinuse(p, psize, next); + } + insert_chunk(m, p, psize); + } + else { + CORRUPTION_ERROR_ACTION(m); + } +} + +/* ---------------------------- malloc --------------------------- */ + +/* allocate a large request from the best fitting chunk in a treebin */ +static void* tmalloc_large(mstate m, size_t nb) { + tchunkptr v = 0; + size_t rsize = -nb; /* Unsigned negation */ + tchunkptr t; + bindex_t idx; + compute_tree_index(nb, idx); + if ((t = *treebin_at(m, idx)) != 0) { + /* Traverse tree for this bin looking for node with size == nb */ + size_t sizebits = nb << leftshift_for_tree_index(idx); + tchunkptr rst = 0; /* The deepest untaken right subtree */ + for (;;) { + tchunkptr rt; + size_t trem = chunksize(t) - nb; + if (trem < rsize) { + v = t; + if ((rsize = trem) == 0) + break; + } + rt = t->child[1]; + t = t->child[(sizebits >> (SIZE_T_BITSIZE-SIZE_T_ONE)) & 1]; + if (rt != 0 && rt != t) + rst = rt; + if (t == 0) { + t = rst; /* set t to least subtree holding sizes > nb */ + break; + } + sizebits <<= 1; + } + } + if (t == 0 && v == 0) { /* set t to root of next non-empty treebin */ + binmap_t leftbits = left_bits(idx2bit(idx)) & m->treemap; + if (leftbits != 0) { + bindex_t i; + binmap_t leastbit = least_bit(leftbits); + compute_bit2idx(leastbit, i); + t = *treebin_at(m, i); + } + } + + while (t != 0) { /* find smallest of tree or subtree */ + size_t trem = chunksize(t) - nb; + if (trem < rsize) { + rsize = trem; + v = t; + } + t = leftmost_child(t); + } + + /* If dv is a better fit, return 0 so malloc will use it */ + if (v != 0 && rsize < (size_t)(m->dvsize - nb)) { + if (RTCHECK(ok_address(m, v))) { /* split */ + mchunkptr r = chunk_plus_offset(v, nb); + assert(chunksize(v) == rsize + nb); + if (RTCHECK(ok_next(v, r))) { + unlink_large_chunk(m, v); + if (rsize < MIN_CHUNK_SIZE) + set_inuse_and_pinuse(m, v, (rsize + nb)); + else { + set_size_and_pinuse_of_inuse_chunk(m, v, nb); + set_size_and_pinuse_of_free_chunk(r, rsize); + insert_chunk(m, r, rsize); + } + return chunk2mem(v); + } + } + CORRUPTION_ERROR_ACTION(m); + } + return 0; +} + +/* allocate a small request from the best fitting chunk in a treebin */ +static void* tmalloc_small(mstate m, size_t nb) { + tchunkptr t, v; + size_t rsize; + bindex_t i; + binmap_t leastbit = least_bit(m->treemap); + compute_bit2idx(leastbit, i); + v = t = *treebin_at(m, i); + rsize = chunksize(t) - nb; + + while ((t = leftmost_child(t)) != 0) { + size_t trem = chunksize(t) - nb; + if (trem < rsize) { + rsize = trem; + v = t; + } + } + + if (RTCHECK(ok_address(m, v))) { + mchunkptr r = chunk_plus_offset(v, nb); + assert(chunksize(v) == rsize + nb); + if (RTCHECK(ok_next(v, r))) { + unlink_large_chunk(m, v); + if (rsize < MIN_CHUNK_SIZE) + set_inuse_and_pinuse(m, v, (rsize + nb)); + else { + set_size_and_pinuse_of_inuse_chunk(m, v, nb); + set_size_and_pinuse_of_free_chunk(r, rsize); + replace_dv(m, r, rsize); + } + return chunk2mem(v); + } + } + + CORRUPTION_ERROR_ACTION(m); + return 0; +} + +#if !ONLY_MSPACES + +void* dlmalloc(size_t bytes) { + /* + Basic algorithm: + If a small request (< 256 bytes minus per-chunk overhead): + 1. If one exists, use a remainderless chunk in associated smallbin. + (Remainderless means that there are too few excess bytes to + represent as a chunk.) + 2. If it is big enough, use the dv chunk, which is normally the + chunk adjacent to the one used for the most recent small request. + 3. If one exists, split the smallest available chunk in a bin, + saving remainder in dv. + 4. If it is big enough, use the top chunk. + 5. If available, get memory from system and use it + Otherwise, for a large request: + 1. Find the smallest available binned chunk that fits, and use it + if it is better fitting than dv chunk, splitting if necessary. + 2. If better fitting than any binned chunk, use the dv chunk. + 3. If it is big enough, use the top chunk. + 4. If request size >= mmap threshold, try to directly mmap this chunk. + 5. If available, get memory from system and use it + + The ugly goto's here ensure that postaction occurs along all paths. + */ + +#if USE_LOCKS + ensure_initialization(); /* initialize in sys_alloc if not using locks */ +#endif + + if (!PREACTION(gm)) { + void* mem; + size_t nb; + if (bytes <= MAX_SMALL_REQUEST) { + bindex_t idx; + binmap_t smallbits; + nb = (bytes < MIN_REQUEST)? MIN_CHUNK_SIZE : pad_request(bytes); + idx = small_index(nb); + smallbits = gm->smallmap >> idx; + + if ((smallbits & 0x3U) != 0) { /* Remainderless fit to a smallbin. */ + mchunkptr b, p; + idx += ~smallbits & 1; /* Uses next bin if idx empty */ + b = smallbin_at(gm, idx); + p = b->fd; + assert(chunksize(p) == small_index2size(idx)); + unlink_first_small_chunk(gm, b, p, idx); + set_inuse_and_pinuse(gm, p, small_index2size(idx)); + mem = chunk2mem(p); + check_malloced_chunk(gm, mem, nb); + goto postaction; + } + + else if (nb > gm->dvsize) { + if (smallbits != 0) { /* Use chunk in next nonempty smallbin */ + mchunkptr b, p, r; + size_t rsize; + bindex_t i; + binmap_t leftbits = (smallbits << idx) & left_bits(idx2bit(idx)); + binmap_t leastbit = least_bit(leftbits); + compute_bit2idx(leastbit, i); + b = smallbin_at(gm, i); + p = b->fd; + assert(chunksize(p) == small_index2size(i)); + unlink_first_small_chunk(gm, b, p, i); + rsize = small_index2size(i) - nb; + /* Fit here cannot be remainderless if 4byte sizes */ + if (SIZE_T_SIZE != 4 && rsize < MIN_CHUNK_SIZE) + set_inuse_and_pinuse(gm, p, small_index2size(i)); + else { + set_size_and_pinuse_of_inuse_chunk(gm, p, nb); + r = chunk_plus_offset(p, nb); + set_size_and_pinuse_of_free_chunk(r, rsize); + replace_dv(gm, r, rsize); + } + mem = chunk2mem(p); + check_malloced_chunk(gm, mem, nb); + goto postaction; + } + + else if (gm->treemap != 0 && (mem = tmalloc_small(gm, nb)) != 0) { + check_malloced_chunk(gm, mem, nb); + goto postaction; + } + } + } + else if (bytes >= MAX_REQUEST) + nb = MAX_SIZE_T; /* Too big to allocate. Force failure (in sys alloc) */ + else { + nb = pad_request(bytes); + if (gm->treemap != 0 && (mem = tmalloc_large(gm, nb)) != 0) { + check_malloced_chunk(gm, mem, nb); + goto postaction; + } + } + + if (nb <= gm->dvsize) { + size_t rsize = gm->dvsize - nb; + mchunkptr p = gm->dv; + if (rsize >= MIN_CHUNK_SIZE) { /* split dv */ + mchunkptr r = gm->dv = chunk_plus_offset(p, nb); + gm->dvsize = rsize; + set_size_and_pinuse_of_free_chunk(r, rsize); + set_size_and_pinuse_of_inuse_chunk(gm, p, nb); + } + else { /* exhaust dv */ + size_t dvs = gm->dvsize; + gm->dvsize = 0; + gm->dv = 0; + set_inuse_and_pinuse(gm, p, dvs); + } + mem = chunk2mem(p); + check_malloced_chunk(gm, mem, nb); + goto postaction; + } + + else if (nb < gm->topsize) { /* Split top */ + size_t rsize = gm->topsize -= nb; + mchunkptr p = gm->top; + mchunkptr r = gm->top = chunk_plus_offset(p, nb); + r->head = rsize | PINUSE_BIT; + set_size_and_pinuse_of_inuse_chunk(gm, p, nb); + mem = chunk2mem(p); + check_top_chunk(gm, gm->top); + check_malloced_chunk(gm, mem, nb); + goto postaction; + } + + mem = sys_alloc(gm, nb); + + postaction: + POSTACTION(gm); + return mem; + } + + return 0; +} + +/* ---------------------------- free --------------------------- */ + +void dlfree(void* mem) { + /* + Consolidate freed chunks with preceeding or succeeding bordering + free chunks, if they exist, and then place in a bin. Intermixed + with special cases for top, dv, mmapped chunks, and usage errors. + */ + + if (mem != 0) { + mchunkptr p = mem2chunk(mem); +#if FOOTERS + mstate fm = get_mstate_for(p); + if (!ok_magic(fm)) { + USAGE_ERROR_ACTION(fm, p); + return; + } +#else /* FOOTERS */ +#define fm gm +#endif /* FOOTERS */ + if (!PREACTION(fm)) { + check_inuse_chunk(fm, p); + if (RTCHECK(ok_address(fm, p) && ok_inuse(p))) { + size_t psize = chunksize(p); + mchunkptr next = chunk_plus_offset(p, psize); + if (!pinuse(p)) { + size_t prevsize = p->prev_foot; + if (is_mmapped(p)) { + psize += prevsize + MMAP_FOOT_PAD; + if (CALL_MUNMAP((char*)p - prevsize, psize) == 0) + fm->footprint -= psize; + goto postaction; + } + else { + mchunkptr prev = chunk_minus_offset(p, prevsize); + psize += prevsize; + p = prev; + if (RTCHECK(ok_address(fm, prev))) { /* consolidate backward */ + if (p != fm->dv) { + unlink_chunk(fm, p, prevsize); + } + else if ((next->head & INUSE_BITS) == INUSE_BITS) { + fm->dvsize = psize; + set_free_with_pinuse(p, psize, next); + goto postaction; + } + } + else + goto erroraction; + } + } + + if (RTCHECK(ok_next(p, next) && ok_pinuse(next))) { + if (!cinuse(next)) { /* consolidate forward */ + if (next == fm->top) { + size_t tsize = fm->topsize += psize; + fm->top = p; + p->head = tsize | PINUSE_BIT; + if (p == fm->dv) { + fm->dv = 0; + fm->dvsize = 0; + } + if (should_trim(fm, tsize)) + sys_trim(fm, 0); + goto postaction; + } + else if (next == fm->dv) { + size_t dsize = fm->dvsize += psize; + fm->dv = p; + set_size_and_pinuse_of_free_chunk(p, dsize); + goto postaction; + } + else { + size_t nsize = chunksize(next); + psize += nsize; + unlink_chunk(fm, next, nsize); + set_size_and_pinuse_of_free_chunk(p, psize); + if (p == fm->dv) { + fm->dvsize = psize; + goto postaction; + } + } + } + else + set_free_with_pinuse(p, psize, next); + + if (is_small(psize)) { + insert_small_chunk(fm, p, psize); + check_free_chunk(fm, p); + } + else { + tchunkptr tp = (tchunkptr)p; + insert_large_chunk(fm, tp, psize); + check_free_chunk(fm, p); + if (--fm->release_checks == 0) + release_unused_segments(fm); + } + goto postaction; + } + } + erroraction: + USAGE_ERROR_ACTION(fm, p); + postaction: + POSTACTION(fm); + } + } +#if !FOOTERS +#undef fm +#endif /* FOOTERS */ +} + +void* dlcalloc(size_t n_elements, size_t elem_size) { + void* mem; + size_t req = 0; + if (n_elements != 0) { + req = n_elements * elem_size; + if (((n_elements | elem_size) & ~(size_t)0xffff) && + (req / n_elements != elem_size)) + req = MAX_SIZE_T; /* force downstream failure on overflow */ + } + mem = dlmalloc(req); + if (mem != 0 && calloc_must_clear(mem2chunk(mem))) + memset(mem, 0, req); + return mem; +} + +#endif /* !ONLY_MSPACES */ + +/* ------------ Internal support for realloc, memalign, etc -------------- */ + +/* Try to realloc; only in-place unless can_move true */ +static mchunkptr try_realloc_chunk(mstate m, mchunkptr p, size_t nb, + int can_move) { + mchunkptr newp = 0; + size_t oldsize = chunksize(p); + mchunkptr next = chunk_plus_offset(p, oldsize); + if (RTCHECK(ok_address(m, p) && ok_inuse(p) && + ok_next(p, next) && ok_pinuse(next))) { + if (is_mmapped(p)) { + newp = mmap_resize(m, p, nb, can_move); + } + else if (oldsize >= nb) { /* already big enough */ + size_t rsize = oldsize - nb; + if (rsize >= MIN_CHUNK_SIZE) { /* split off remainder */ + mchunkptr r = chunk_plus_offset(p, nb); + set_inuse(m, p, nb); + set_inuse(m, r, rsize); + dispose_chunk(m, r, rsize); + } + newp = p; + } + else if (next == m->top) { /* extend into top */ + if (oldsize + m->topsize > nb) { + size_t newsize = oldsize + m->topsize; + size_t newtopsize = newsize - nb; + mchunkptr newtop = chunk_plus_offset(p, nb); + set_inuse(m, p, nb); + newtop->head = newtopsize |PINUSE_BIT; + m->top = newtop; + m->topsize = newtopsize; + newp = p; + } + } + else if (next == m->dv) { /* extend into dv */ + size_t dvs = m->dvsize; + if (oldsize + dvs >= nb) { + size_t dsize = oldsize + dvs - nb; + if (dsize >= MIN_CHUNK_SIZE) { + mchunkptr r = chunk_plus_offset(p, nb); + mchunkptr n = chunk_plus_offset(r, dsize); + set_inuse(m, p, nb); + set_size_and_pinuse_of_free_chunk(r, dsize); + clear_pinuse(n); + m->dvsize = dsize; + m->dv = r; + } + else { /* exhaust dv */ + size_t newsize = oldsize + dvs; + set_inuse(m, p, newsize); + m->dvsize = 0; + m->dv = 0; + } + newp = p; + } + } + else if (!cinuse(next)) { /* extend into next free chunk */ + size_t nextsize = chunksize(next); + if (oldsize + nextsize >= nb) { + size_t rsize = oldsize + nextsize - nb; + unlink_chunk(m, next, nextsize); + if (rsize < MIN_CHUNK_SIZE) { + size_t newsize = oldsize + nextsize; + set_inuse(m, p, newsize); + } + else { + mchunkptr r = chunk_plus_offset(p, nb); + set_inuse(m, p, nb); + set_inuse(m, r, rsize); + dispose_chunk(m, r, rsize); + } + newp = p; + } + } + } + else { + USAGE_ERROR_ACTION(m, chunk2mem(p)); + } + return newp; +} + +static void* internal_memalign(mstate m, size_t alignment, size_t bytes) { + void* mem = 0; + if (alignment < MIN_CHUNK_SIZE) /* must be at least a minimum chunk size */ + alignment = MIN_CHUNK_SIZE; + if ((alignment & (alignment-SIZE_T_ONE)) != 0) {/* Ensure a power of 2 */ + size_t a = MALLOC_ALIGNMENT << 1; + while (a < alignment) a <<= 1; + alignment = a; + } + if (bytes >= MAX_REQUEST - alignment) { + if (m != 0) { /* Test isn't needed but avoids compiler warning */ + MALLOC_FAILURE_ACTION; + } + } + else { + size_t nb = request2size(bytes); + size_t req = nb + alignment + MIN_CHUNK_SIZE - CHUNK_OVERHEAD; + mem = internal_malloc(m, req); + if (mem != 0) { + mchunkptr p = mem2chunk(mem); + if (PREACTION(m)) + return 0; + if ((((size_t)(mem)) & (alignment - 1)) != 0) { /* misaligned */ + /* + Find an aligned spot inside chunk. Since we need to give + back leading space in a chunk of at least MIN_CHUNK_SIZE, if + the first calculation places us at a spot with less than + MIN_CHUNK_SIZE leader, we can move to the next aligned spot. + We've allocated enough total room so that this is always + possible. + */ + char* br = (char*)mem2chunk((size_t)(((size_t)((char*)mem + alignment - + SIZE_T_ONE)) & + -alignment)); + char* pos = ((size_t)(br - (char*)(p)) >= MIN_CHUNK_SIZE)? + br : br+alignment; + mchunkptr newp = (mchunkptr)pos; + size_t leadsize = pos - (char*)(p); + size_t newsize = chunksize(p) - leadsize; + + if (is_mmapped(p)) { /* For mmapped chunks, just adjust offset */ + newp->prev_foot = p->prev_foot + leadsize; + newp->head = newsize; + } + else { /* Otherwise, give back leader, use the rest */ + set_inuse(m, newp, newsize); + set_inuse(m, p, leadsize); + dispose_chunk(m, p, leadsize); + } + p = newp; + } + + /* Give back spare room at the end */ + if (!is_mmapped(p)) { + size_t size = chunksize(p); + if (size > nb + MIN_CHUNK_SIZE) { + size_t remainder_size = size - nb; + mchunkptr remainder = chunk_plus_offset(p, nb); + set_inuse(m, p, nb); + set_inuse(m, remainder, remainder_size); + dispose_chunk(m, remainder, remainder_size); + } + } + + mem = chunk2mem(p); + assert (chunksize(p) >= nb); + assert(((size_t)mem & (alignment - 1)) == 0); + check_inuse_chunk(m, p); + POSTACTION(m); + } + } + return mem; +} + +/* + Common support for independent_X routines, handling + all of the combinations that can result. + The opts arg has: + bit 0 set if all elements are same size (using sizes[0]) + bit 1 set if elements should be zeroed +*/ +static void** ialloc(mstate m, + size_t n_elements, + size_t* sizes, + int opts, + void* chunks[]) { + + size_t element_size; /* chunksize of each element, if all same */ + size_t contents_size; /* total size of elements */ + size_t array_size; /* request size of pointer array */ + void* mem; /* malloced aggregate space */ + mchunkptr p; /* corresponding chunk */ + size_t remainder_size; /* remaining bytes while splitting */ + void** marray; /* either "chunks" or malloced ptr array */ + mchunkptr array_chunk; /* chunk for malloced ptr array */ + flag_t was_enabled; /* to disable mmap */ + size_t size; + size_t i; + + ensure_initialization(); + /* compute array length, if needed */ + if (chunks != 0) { + if (n_elements == 0) + return chunks; /* nothing to do */ + marray = chunks; + array_size = 0; + } + else { + /* if empty req, must still return chunk representing empty array */ + if (n_elements == 0) + return (void**)internal_malloc(m, 0); + marray = 0; + array_size = request2size(n_elements * (sizeof(void*))); + } + + /* compute total element size */ + if (opts & 0x1) { /* all-same-size */ + element_size = request2size(*sizes); + contents_size = n_elements * element_size; + } + else { /* add up all the sizes */ + element_size = 0; + contents_size = 0; + for (i = 0; i != n_elements; ++i) + contents_size += request2size(sizes[i]); + } + + size = contents_size + array_size; + + /* + Allocate the aggregate chunk. First disable direct-mmapping so + malloc won't use it, since we would not be able to later + free/realloc space internal to a segregated mmap region. + */ + was_enabled = use_mmap(m); + disable_mmap(m); + mem = internal_malloc(m, size - CHUNK_OVERHEAD); + if (was_enabled) + enable_mmap(m); + if (mem == 0) + return 0; + + if (PREACTION(m)) return 0; + p = mem2chunk(mem); + remainder_size = chunksize(p); + + assert(!is_mmapped(p)); + + if (opts & 0x2) { /* optionally clear the elements */ + memset((size_t*)mem, 0, remainder_size - SIZE_T_SIZE - array_size); + } + + /* If not provided, allocate the pointer array as final part of chunk */ + if (marray == 0) { + size_t array_chunk_size; + array_chunk = chunk_plus_offset(p, contents_size); + array_chunk_size = remainder_size - contents_size; + marray = (void**) (chunk2mem(array_chunk)); + set_size_and_pinuse_of_inuse_chunk(m, array_chunk, array_chunk_size); + remainder_size = contents_size; + } + + /* split out elements */ + for (i = 0; ; ++i) { + marray[i] = chunk2mem(p); + if (i != n_elements-1) { + if (element_size != 0) + size = element_size; + else + size = request2size(sizes[i]); + remainder_size -= size; + set_size_and_pinuse_of_inuse_chunk(m, p, size); + p = chunk_plus_offset(p, size); + } + else { /* the final element absorbs any overallocation slop */ + set_size_and_pinuse_of_inuse_chunk(m, p, remainder_size); + break; + } + } + +#if DEBUG + if (marray != chunks) { + /* final element must have exactly exhausted chunk */ + if (element_size != 0) { + assert(remainder_size == element_size); + } + else { + assert(remainder_size == request2size(sizes[i])); + } + check_inuse_chunk(m, mem2chunk(marray)); + } + for (i = 0; i != n_elements; ++i) + check_inuse_chunk(m, mem2chunk(marray[i])); + +#endif /* DEBUG */ + + POSTACTION(m); + return marray; +} + +/* Try to free all pointers in the given array. + Note: this could be made faster, by delaying consolidation, + at the price of disabling some user integrity checks, We + still optimize some consolidations by combining adjacent + chunks before freeing, which will occur often if allocated + with ialloc or the array is sorted. +*/ +static size_t internal_bulk_free(mstate m, void* array[], size_t nelem) { + size_t unfreed = 0; + if (!PREACTION(m)) { + void** a; + void** fence = &(array[nelem]); + for (a = array; a != fence; ++a) { + void* mem = *a; + if (mem != 0) { + mchunkptr p = mem2chunk(mem); + size_t psize = chunksize(p); +#if FOOTERS + if (get_mstate_for(p) != m) { + ++unfreed; + continue; + } +#endif + check_inuse_chunk(m, p); + *a = 0; + if (RTCHECK(ok_address(m, p) && ok_inuse(p))) { + void ** b = a + 1; /* try to merge with next chunk */ + mchunkptr next = next_chunk(p); + if (b != fence && *b == chunk2mem(next)) { + size_t newsize = chunksize(next) + psize; + set_inuse(m, p, newsize); + *b = chunk2mem(p); + } + else + dispose_chunk(m, p, psize); + } + else { + CORRUPTION_ERROR_ACTION(m); + break; + } + } + } + if (should_trim(m, m->topsize)) + sys_trim(m, 0); + POSTACTION(m); + } + return unfreed; +} + +/* Traversal */ +#if MALLOC_INSPECT_ALL +static void internal_inspect_all(mstate m, + void(*handler)(void *start, + void *end, + size_t used_bytes, + void* callback_arg), + void* arg) { + if (is_initialized(m)) { + mchunkptr top = m->top; + msegmentptr s; + for (s = &m->seg; s != 0; s = s->next) { + mchunkptr q = align_as_chunk(s->base); + while (segment_holds(s, q) && q->head != FENCEPOST_HEAD) { + mchunkptr next = next_chunk(q); + size_t sz = chunksize(q); + size_t used; + void* start; + if (is_inuse(q)) { + used = sz - CHUNK_OVERHEAD; /* must not be mmapped */ + start = chunk2mem(q); + } + else { + used = 0; + if (is_small(sz)) { /* offset by possible bookkeeping */ + start = (void*)((char*)q + sizeof(struct malloc_chunk)); + } + else { + start = (void*)((char*)q + sizeof(struct malloc_tree_chunk)); + } + } + if (start < (void*)next) /* skip if all space is bookkeeping */ + handler(start, next, used, arg); + if (q == top) + break; + q = next; + } + } + } +} +#endif /* MALLOC_INSPECT_ALL */ + +/* ------------------ Exported realloc, memalign, etc -------------------- */ + +#if !ONLY_MSPACES + +void* dlrealloc(void* oldmem, size_t bytes) { + void* mem = 0; + if (oldmem == 0) { + mem = dlmalloc(bytes); + } + else if (bytes >= MAX_REQUEST) { + MALLOC_FAILURE_ACTION; + } +#ifdef REALLOC_ZERO_BYTES_FREES + else if (bytes == 0) { + dlfree(oldmem); + } +#endif /* REALLOC_ZERO_BYTES_FREES */ + else { + size_t nb = request2size(bytes); + mchunkptr oldp = mem2chunk(oldmem); +#if ! FOOTERS + mstate m = gm; +#else /* FOOTERS */ + mstate m = get_mstate_for(oldp); + if (!ok_magic(m)) { + USAGE_ERROR_ACTION(m, oldmem); + return 0; + } +#endif /* FOOTERS */ + if (!PREACTION(m)) { + mchunkptr newp = try_realloc_chunk(m, oldp, nb, 1); + POSTACTION(m); + if (newp != 0) { + check_inuse_chunk(m, newp); + mem = chunk2mem(newp); + } + else { + mem = internal_malloc(m, bytes); + if (mem != 0) { + size_t oc = chunksize(oldp) - overhead_for(oldp); + memcpy(mem, oldmem, (oc < bytes)? oc : bytes); + internal_free(m, oldmem); + } + } + } + } + return mem; +} + +void* dlrealloc_in_place(void* oldmem, size_t bytes) { + void* mem = 0; + if (oldmem != 0) { + if (bytes >= MAX_REQUEST) { + MALLOC_FAILURE_ACTION; + } + else { + size_t nb = request2size(bytes); + mchunkptr oldp = mem2chunk(oldmem); +#if ! FOOTERS + mstate m = gm; +#else /* FOOTERS */ + mstate m = get_mstate_for(oldp); + if (!ok_magic(m)) { + USAGE_ERROR_ACTION(m, oldmem); + return 0; + } +#endif /* FOOTERS */ + if (!PREACTION(m)) { + mchunkptr newp = try_realloc_chunk(m, oldp, nb, 0); + POSTACTION(m); + if (newp == oldp) { + check_inuse_chunk(m, newp); + mem = oldmem; + } + } + } + } + return mem; +} + +void* dlmemalign(size_t alignment, size_t bytes) { + if (alignment <= MALLOC_ALIGNMENT) { + return dlmalloc(bytes); + } + return internal_memalign(gm, alignment, bytes); +} + +int dlposix_memalign(void** pp, size_t alignment, size_t bytes) { + void* mem = 0; + if (alignment == MALLOC_ALIGNMENT) + mem = dlmalloc(bytes); + else { + size_t d = alignment / sizeof(void*); + size_t r = alignment % sizeof(void*); + if (r != 0 || d == 0 || (d & (d-SIZE_T_ONE)) != 0) + return EINVAL; + else if (bytes <= MAX_REQUEST - alignment) { + if (alignment < MIN_CHUNK_SIZE) + alignment = MIN_CHUNK_SIZE; + mem = internal_memalign(gm, alignment, bytes); + } + } + if (mem == 0) + return ENOMEM; + else { + *pp = mem; + return 0; + } +} + +void* dlvalloc(size_t bytes) { + size_t pagesz; + ensure_initialization(); + pagesz = mparams.page_size; + return dlmemalign(pagesz, bytes); +} + +void* dlpvalloc(size_t bytes) { + size_t pagesz; + ensure_initialization(); + pagesz = mparams.page_size; + return dlmemalign(pagesz, (bytes + pagesz - SIZE_T_ONE) & ~(pagesz - SIZE_T_ONE)); +} + +void** dlindependent_calloc(size_t n_elements, size_t elem_size, + void* chunks[]) { + size_t sz = elem_size; /* serves as 1-element array */ + return ialloc(gm, n_elements, &sz, 3, chunks); +} + +void** dlindependent_comalloc(size_t n_elements, size_t sizes[], + void* chunks[]) { + return ialloc(gm, n_elements, sizes, 0, chunks); +} + +size_t dlbulk_free(void* array[], size_t nelem) { + return internal_bulk_free(gm, array, nelem); +} + +#if MALLOC_INSPECT_ALL +void dlmalloc_inspect_all(void(*handler)(void *start, + void *end, + size_t used_bytes, + void* callback_arg), + void* arg) { + ensure_initialization(); + if (!PREACTION(gm)) { + internal_inspect_all(gm, handler, arg); + POSTACTION(gm); + } +} +#endif /* MALLOC_INSPECT_ALL */ + +int dlmalloc_trim(size_t pad) { + int result = 0; + ensure_initialization(); + if (!PREACTION(gm)) { + result = sys_trim(gm, pad); + POSTACTION(gm); + } + return result; +} + +size_t dlmalloc_footprint(void) { + return gm->footprint; +} + +size_t dlmalloc_max_footprint(void) { + return gm->max_footprint; +} + +size_t dlmalloc_footprint_limit(void) { + size_t maf = gm->footprint_limit; + return maf == 0 ? MAX_SIZE_T : maf; +} + +size_t dlmalloc_set_footprint_limit(size_t bytes) { + size_t result; /* invert sense of 0 */ + if (bytes == 0) + result = granularity_align(1); /* Use minimal size */ + if (bytes == MAX_SIZE_T) + result = 0; /* disable */ + else + result = granularity_align(bytes); + return gm->footprint_limit = result; +} + +#if !NO_MALLINFO +struct mallinfo dlmallinfo(void) { + return internal_mallinfo(gm); +} +#endif /* NO_MALLINFO */ + +#if !NO_MALLOC_STATS +void dlmalloc_stats() { + internal_malloc_stats(gm); +} +#endif /* NO_MALLOC_STATS */ + +int dlmallopt(int param_number, int value) { + return change_mparam(param_number, value); +} + +size_t dlmalloc_usable_size(void* mem) { + if (mem != 0) { + mchunkptr p = mem2chunk(mem); + if (is_inuse(p)) + return chunksize(p) - overhead_for(p); + } + return 0; +} + +#endif /* !ONLY_MSPACES */ + +/* ----------------------------- user mspaces ---------------------------- */ + +#if MSPACES + +static mstate init_user_mstate(char* tbase, size_t tsize) { + size_t msize = pad_request(sizeof(struct malloc_state)); + mchunkptr mn; + mchunkptr msp = align_as_chunk(tbase); + mstate m = (mstate)(chunk2mem(msp)); + memset(m, 0, msize); + (void)INITIAL_LOCK(&m->mutex); + msp->head = (msize|INUSE_BITS); + m->seg.base = m->least_addr = tbase; + m->seg.size = m->footprint = m->max_footprint = tsize; + m->magic = mparams.magic; + m->release_checks = MAX_RELEASE_CHECK_RATE; + m->mflags = mparams.default_mflags; + m->extp = 0; + m->exts = 0; + disable_contiguous(m); + init_bins(m); + mn = next_chunk(mem2chunk(m)); + init_top(m, mn, (size_t)((tbase + tsize) - (char*)mn) - TOP_FOOT_SIZE); + check_top_chunk(m, m->top); + return m; +} + +mspace create_mspace(size_t capacity, int locked) { + mstate m = 0; + size_t msize; + ensure_initialization(); + msize = pad_request(sizeof(struct malloc_state)); + if (capacity < (size_t) -(msize + TOP_FOOT_SIZE + mparams.page_size)) { + size_t rs = ((capacity == 0)? mparams.granularity : + (capacity + TOP_FOOT_SIZE + msize)); + size_t tsize = granularity_align(rs); + char* tbase = (char*)(CALL_MMAP(tsize)); + if (tbase != CMFAIL) { + m = init_user_mstate(tbase, tsize); + m->seg.sflags = USE_MMAP_BIT; + set_lock(m, locked); + } + } + return (mspace)m; +} + +mspace create_mspace_with_base(void* base, size_t capacity, int locked) { + mstate m = 0; + size_t msize; + ensure_initialization(); + msize = pad_request(sizeof(struct malloc_state)); + if (capacity > msize + TOP_FOOT_SIZE && + capacity < (size_t) -(msize + TOP_FOOT_SIZE + mparams.page_size)) { + m = init_user_mstate((char*)base, capacity); + m->seg.sflags = EXTERN_BIT; + set_lock(m, locked); + } + return (mspace)m; +} + +int mspace_track_large_chunks(mspace msp, int enable) { + int ret = 0; + mstate ms = (mstate)msp; + if (!PREACTION(ms)) { + if (!use_mmap(ms)) { + ret = 1; + } + if (!enable) { + enable_mmap(ms); + } else { + disable_mmap(ms); + } + POSTACTION(ms); + } + return ret; +} + +size_t destroy_mspace(mspace msp) { + size_t freed = 0; + mstate ms = (mstate)msp; + if (ok_magic(ms)) { + msegmentptr sp = &ms->seg; + (void)DESTROY_LOCK(&ms->mutex); /* destroy before unmapped */ + while (sp != 0) { + char* base = sp->base; + size_t size = sp->size; + flag_t flag = sp->sflags; + (void)base; /* placate people compiling -Wunused-variable */ + sp = sp->next; + if ((flag & USE_MMAP_BIT) && !(flag & EXTERN_BIT) && + CALL_MUNMAP(base, size) == 0) + freed += size; + } + } + else { + USAGE_ERROR_ACTION(ms,ms); + } + return freed; +} + +/* + mspace versions of routines are near-clones of the global + versions. This is not so nice but better than the alternatives. +*/ + +void* mspace_malloc(mspace msp, size_t bytes) { + mstate ms = (mstate)msp; + if (!ok_magic(ms)) { + USAGE_ERROR_ACTION(ms,ms); + return 0; + } + if (!PREACTION(ms)) { + void* mem; + size_t nb; + if (bytes <= MAX_SMALL_REQUEST) { + bindex_t idx; + binmap_t smallbits; + nb = (bytes < MIN_REQUEST)? MIN_CHUNK_SIZE : pad_request(bytes); + idx = small_index(nb); + smallbits = ms->smallmap >> idx; + + if ((smallbits & 0x3U) != 0) { /* Remainderless fit to a smallbin. */ + mchunkptr b, p; + idx += ~smallbits & 1; /* Uses next bin if idx empty */ + b = smallbin_at(ms, idx); + p = b->fd; + assert(chunksize(p) == small_index2size(idx)); + unlink_first_small_chunk(ms, b, p, idx); + set_inuse_and_pinuse(ms, p, small_index2size(idx)); + mem = chunk2mem(p); + check_malloced_chunk(ms, mem, nb); + goto postaction; + } + + else if (nb > ms->dvsize) { + if (smallbits != 0) { /* Use chunk in next nonempty smallbin */ + mchunkptr b, p, r; + size_t rsize; + bindex_t i; + binmap_t leftbits = (smallbits << idx) & left_bits(idx2bit(idx)); + binmap_t leastbit = least_bit(leftbits); + compute_bit2idx(leastbit, i); + b = smallbin_at(ms, i); + p = b->fd; + assert(chunksize(p) == small_index2size(i)); + unlink_first_small_chunk(ms, b, p, i); + rsize = small_index2size(i) - nb; + /* Fit here cannot be remainderless if 4byte sizes */ + if (SIZE_T_SIZE != 4 && rsize < MIN_CHUNK_SIZE) + set_inuse_and_pinuse(ms, p, small_index2size(i)); + else { + set_size_and_pinuse_of_inuse_chunk(ms, p, nb); + r = chunk_plus_offset(p, nb); + set_size_and_pinuse_of_free_chunk(r, rsize); + replace_dv(ms, r, rsize); + } + mem = chunk2mem(p); + check_malloced_chunk(ms, mem, nb); + goto postaction; + } + + else if (ms->treemap != 0 && (mem = tmalloc_small(ms, nb)) != 0) { + check_malloced_chunk(ms, mem, nb); + goto postaction; + } + } + } + else if (bytes >= MAX_REQUEST) + nb = MAX_SIZE_T; /* Too big to allocate. Force failure (in sys alloc) */ + else { + nb = pad_request(bytes); + if (ms->treemap != 0 && (mem = tmalloc_large(ms, nb)) != 0) { + check_malloced_chunk(ms, mem, nb); + goto postaction; + } + } + + if (nb <= ms->dvsize) { + size_t rsize = ms->dvsize - nb; + mchunkptr p = ms->dv; + if (rsize >= MIN_CHUNK_SIZE) { /* split dv */ + mchunkptr r = ms->dv = chunk_plus_offset(p, nb); + ms->dvsize = rsize; + set_size_and_pinuse_of_free_chunk(r, rsize); + set_size_and_pinuse_of_inuse_chunk(ms, p, nb); + } + else { /* exhaust dv */ + size_t dvs = ms->dvsize; + ms->dvsize = 0; + ms->dv = 0; + set_inuse_and_pinuse(ms, p, dvs); + } + mem = chunk2mem(p); + check_malloced_chunk(ms, mem, nb); + goto postaction; + } + + else if (nb < ms->topsize) { /* Split top */ + size_t rsize = ms->topsize -= nb; + mchunkptr p = ms->top; + mchunkptr r = ms->top = chunk_plus_offset(p, nb); + r->head = rsize | PINUSE_BIT; + set_size_and_pinuse_of_inuse_chunk(ms, p, nb); + mem = chunk2mem(p); + check_top_chunk(ms, ms->top); + check_malloced_chunk(ms, mem, nb); + goto postaction; + } + + mem = sys_alloc(ms, nb); + + postaction: + POSTACTION(ms); + return mem; + } + + return 0; +} + +void mspace_free(mspace msp, void* mem) { + if (mem != 0) { + mchunkptr p = mem2chunk(mem); +#if FOOTERS + mstate fm = get_mstate_for(p); + (void)msp; /* placate people compiling -Wunused */ +#else /* FOOTERS */ + mstate fm = (mstate)msp; +#endif /* FOOTERS */ + if (!ok_magic(fm)) { + USAGE_ERROR_ACTION(fm, p); + return; + } + if (!PREACTION(fm)) { + check_inuse_chunk(fm, p); + if (RTCHECK(ok_address(fm, p) && ok_inuse(p))) { + size_t psize = chunksize(p); + mchunkptr next = chunk_plus_offset(p, psize); + if (!pinuse(p)) { + size_t prevsize = p->prev_foot; + if (is_mmapped(p)) { + psize += prevsize + MMAP_FOOT_PAD; + if (CALL_MUNMAP((char*)p - prevsize, psize) == 0) + fm->footprint -= psize; + goto postaction; + } + else { + mchunkptr prev = chunk_minus_offset(p, prevsize); + psize += prevsize; + p = prev; + if (RTCHECK(ok_address(fm, prev))) { /* consolidate backward */ + if (p != fm->dv) { + unlink_chunk(fm, p, prevsize); + } + else if ((next->head & INUSE_BITS) == INUSE_BITS) { + fm->dvsize = psize; + set_free_with_pinuse(p, psize, next); + goto postaction; + } + } + else + goto erroraction; + } + } + + if (RTCHECK(ok_next(p, next) && ok_pinuse(next))) { + if (!cinuse(next)) { /* consolidate forward */ + if (next == fm->top) { + size_t tsize = fm->topsize += psize; + fm->top = p; + p->head = tsize | PINUSE_BIT; + if (p == fm->dv) { + fm->dv = 0; + fm->dvsize = 0; + } + if (should_trim(fm, tsize)) + sys_trim(fm, 0); + goto postaction; + } + else if (next == fm->dv) { + size_t dsize = fm->dvsize += psize; + fm->dv = p; + set_size_and_pinuse_of_free_chunk(p, dsize); + goto postaction; + } + else { + size_t nsize = chunksize(next); + psize += nsize; + unlink_chunk(fm, next, nsize); + set_size_and_pinuse_of_free_chunk(p, psize); + if (p == fm->dv) { + fm->dvsize = psize; + goto postaction; + } + } + } + else + set_free_with_pinuse(p, psize, next); + + if (is_small(psize)) { + insert_small_chunk(fm, p, psize); + check_free_chunk(fm, p); + } + else { + tchunkptr tp = (tchunkptr)p; + insert_large_chunk(fm, tp, psize); + check_free_chunk(fm, p); + if (--fm->release_checks == 0) + release_unused_segments(fm); + } + goto postaction; + } + } + erroraction: + USAGE_ERROR_ACTION(fm, p); + postaction: + POSTACTION(fm); + } + } +} + +void* mspace_calloc(mspace msp, size_t n_elements, size_t elem_size) { + void* mem; + size_t req = 0; + mstate ms = (mstate)msp; + if (!ok_magic(ms)) { + USAGE_ERROR_ACTION(ms,ms); + return 0; + } + if (n_elements != 0) { + req = n_elements * elem_size; + if (((n_elements | elem_size) & ~(size_t)0xffff) && + (req / n_elements != elem_size)) + req = MAX_SIZE_T; /* force downstream failure on overflow */ + } + mem = internal_malloc(ms, req); + if (mem != 0 && calloc_must_clear(mem2chunk(mem))) + memset(mem, 0, req); + return mem; +} + +void* mspace_realloc(mspace msp, void* oldmem, size_t bytes) { + void* mem = 0; + if (oldmem == 0) { + mem = mspace_malloc(msp, bytes); + } + else if (bytes >= MAX_REQUEST) { + MALLOC_FAILURE_ACTION; + } +#ifdef REALLOC_ZERO_BYTES_FREES + else if (bytes == 0) { + mspace_free(msp, oldmem); + } +#endif /* REALLOC_ZERO_BYTES_FREES */ + else { + size_t nb = request2size(bytes); + mchunkptr oldp = mem2chunk(oldmem); +#if ! FOOTERS + mstate m = (mstate)msp; +#else /* FOOTERS */ + mstate m = get_mstate_for(oldp); + if (!ok_magic(m)) { + USAGE_ERROR_ACTION(m, oldmem); + return 0; + } +#endif /* FOOTERS */ + if (!PREACTION(m)) { + mchunkptr newp = try_realloc_chunk(m, oldp, nb, 1); + POSTACTION(m); + if (newp != 0) { + check_inuse_chunk(m, newp); + mem = chunk2mem(newp); + } + else { + mem = mspace_malloc(m, bytes); + if (mem != 0) { + size_t oc = chunksize(oldp) - overhead_for(oldp); + memcpy(mem, oldmem, (oc < bytes)? oc : bytes); + mspace_free(m, oldmem); + } + } + } + } + return mem; +} + +void* mspace_realloc_in_place(mspace msp, void* oldmem, size_t bytes) { + void* mem = 0; + if (oldmem != 0) { + if (bytes >= MAX_REQUEST) { + MALLOC_FAILURE_ACTION; + } + else { + size_t nb = request2size(bytes); + mchunkptr oldp = mem2chunk(oldmem); +#if ! FOOTERS + mstate m = (mstate)msp; +#else /* FOOTERS */ + mstate m = get_mstate_for(oldp); + (void)msp; /* placate people compiling -Wunused */ + if (!ok_magic(m)) { + USAGE_ERROR_ACTION(m, oldmem); + return 0; + } +#endif /* FOOTERS */ + if (!PREACTION(m)) { + mchunkptr newp = try_realloc_chunk(m, oldp, nb, 0); + POSTACTION(m); + if (newp == oldp) { + check_inuse_chunk(m, newp); + mem = oldmem; + } + } + } + } + return mem; +} + +void* mspace_memalign(mspace msp, size_t alignment, size_t bytes) { + mstate ms = (mstate)msp; + if (!ok_magic(ms)) { + USAGE_ERROR_ACTION(ms,ms); + return 0; + } + if (alignment <= MALLOC_ALIGNMENT) + return mspace_malloc(msp, bytes); + return internal_memalign(ms, alignment, bytes); +} + +void** mspace_independent_calloc(mspace msp, size_t n_elements, + size_t elem_size, void* chunks[]) { + size_t sz = elem_size; /* serves as 1-element array */ + mstate ms = (mstate)msp; + if (!ok_magic(ms)) { + USAGE_ERROR_ACTION(ms,ms); + return 0; + } + return ialloc(ms, n_elements, &sz, 3, chunks); +} + +void** mspace_independent_comalloc(mspace msp, size_t n_elements, + size_t sizes[], void* chunks[]) { + mstate ms = (mstate)msp; + if (!ok_magic(ms)) { + USAGE_ERROR_ACTION(ms,ms); + return 0; + } + return ialloc(ms, n_elements, sizes, 0, chunks); +} + +size_t mspace_bulk_free(mspace msp, void* array[], size_t nelem) { + return internal_bulk_free((mstate)msp, array, nelem); +} + +#if MALLOC_INSPECT_ALL +void mspace_inspect_all(mspace msp, + void(*handler)(void *start, + void *end, + size_t used_bytes, + void* callback_arg), + void* arg) { + mstate ms = (mstate)msp; + if (ok_magic(ms)) { + if (!PREACTION(ms)) { + internal_inspect_all(ms, handler, arg); + POSTACTION(ms); + } + } + else { + USAGE_ERROR_ACTION(ms,ms); + } +} +#endif /* MALLOC_INSPECT_ALL */ + +int mspace_trim(mspace msp, size_t pad) { + int result = 0; + mstate ms = (mstate)msp; + if (ok_magic(ms)) { + if (!PREACTION(ms)) { + result = sys_trim(ms, pad); + POSTACTION(ms); + } + } + else { + USAGE_ERROR_ACTION(ms,ms); + } + return result; +} + +#if !NO_MALLOC_STATS +void mspace_malloc_stats(mspace msp) { + mstate ms = (mstate)msp; + if (ok_magic(ms)) { + internal_malloc_stats(ms); + } + else { + USAGE_ERROR_ACTION(ms,ms); + } +} +#endif /* NO_MALLOC_STATS */ + +size_t mspace_footprint(mspace msp) { + size_t result = 0; + mstate ms = (mstate)msp; + if (ok_magic(ms)) { + result = ms->footprint; + } + else { + USAGE_ERROR_ACTION(ms,ms); + } + return result; +} + +size_t mspace_max_footprint(mspace msp) { + size_t result = 0; + mstate ms = (mstate)msp; + if (ok_magic(ms)) { + result = ms->max_footprint; + } + else { + USAGE_ERROR_ACTION(ms,ms); + } + return result; +} + +size_t mspace_footprint_limit(mspace msp) { + size_t result = 0; + mstate ms = (mstate)msp; + if (ok_magic(ms)) { + size_t maf = ms->footprint_limit; + result = (maf == 0) ? MAX_SIZE_T : maf; + } + else { + USAGE_ERROR_ACTION(ms,ms); + } + return result; +} + +size_t mspace_set_footprint_limit(mspace msp, size_t bytes) { + size_t result = 0; + mstate ms = (mstate)msp; + if (ok_magic(ms)) { + if (bytes == 0) + result = granularity_align(1); /* Use minimal size */ + if (bytes == MAX_SIZE_T) + result = 0; /* disable */ + else + result = granularity_align(bytes); + ms->footprint_limit = result; + } + else { + USAGE_ERROR_ACTION(ms,ms); + } + return result; +} + +#if !NO_MALLINFO +struct mallinfo mspace_mallinfo(mspace msp) { + mstate ms = (mstate)msp; + if (!ok_magic(ms)) { + USAGE_ERROR_ACTION(ms,ms); + } + return internal_mallinfo(ms); +} +#endif /* NO_MALLINFO */ + +size_t mspace_usable_size(const void* mem) { + if (mem != 0) { + mchunkptr p = mem2chunk(mem); + if (is_inuse(p)) + return chunksize(p) - overhead_for(p); + } + return 0; +} + +int mspace_mallopt(int param_number, int value) { + return change_mparam(param_number, value); +} + +#endif /* MSPACES */ + + +/* -------------------- Alternative MORECORE functions ------------------- */ + +/* + Guidelines for creating a custom version of MORECORE: + + * For best performance, MORECORE should allocate in multiples of pagesize. + * MORECORE may allocate more memory than requested. (Or even less, + but this will usually result in a malloc failure.) + * MORECORE must not allocate memory when given argument zero, but + instead return one past the end address of memory from previous + nonzero call. + * For best performance, consecutive calls to MORECORE with positive + arguments should return increasing addresses, indicating that + space has been contiguously extended. + * Even though consecutive calls to MORECORE need not return contiguous + addresses, it must be OK for malloc'ed chunks to span multiple + regions in those cases where they do happen to be contiguous. + * MORECORE need not handle negative arguments -- it may instead + just return MFAIL when given negative arguments. + Negative arguments are always multiples of pagesize. MORECORE + must not misinterpret negative args as large positive unsigned + args. You can suppress all such calls from even occurring by defining + MORECORE_CANNOT_TRIM, + + As an example alternative MORECORE, here is a custom allocator + kindly contributed for pre-OSX macOS. It uses virtually but not + necessarily physically contiguous non-paged memory (locked in, + present and won't get swapped out). You can use it by uncommenting + this section, adding some #includes, and setting up the appropriate + defines above: + + #define MORECORE osMoreCore + + There is also a shutdown routine that should somehow be called for + cleanup upon program exit. + + #define MAX_POOL_ENTRIES 100 + #define MINIMUM_MORECORE_SIZE (64 * 1024U) + static int next_os_pool; + void *our_os_pools[MAX_POOL_ENTRIES]; + + void *osMoreCore(int size) + { + void *ptr = 0; + static void *sbrk_top = 0; + + if (size > 0) + { + if (size < MINIMUM_MORECORE_SIZE) + size = MINIMUM_MORECORE_SIZE; + if (CurrentExecutionLevel() == kTaskLevel) + ptr = PoolAllocateResident(size + RM_PAGE_SIZE, 0); + if (ptr == 0) + { + return (void *) MFAIL; + } + // save ptrs so they can be freed during cleanup + our_os_pools[next_os_pool] = ptr; + next_os_pool++; + ptr = (void *) ((((size_t) ptr) + RM_PAGE_MASK) & ~RM_PAGE_MASK); + sbrk_top = (char *) ptr + size; + return ptr; + } + else if (size < 0) + { + // we don't currently support shrink behavior + return (void *) MFAIL; + } + else + { + return sbrk_top; + } + } + + // cleanup any allocated memory pools + // called as last thing before shutting down driver + + void osCleanupMem(void) + { + void **ptr; + + for (ptr = our_os_pools; ptr < &our_os_pools[MAX_POOL_ENTRIES]; ptr++) + if (*ptr) + { + PoolDeallocate(*ptr); + *ptr = 0; + } + } + +*/ + + +/* ----------------------------------------------------------------------- +History: + v2.8.6 Wed Aug 29 06:57:58 2012 Doug Lea + * fix bad comparison in dlposix_memalign + * don't reuse adjusted asize in sys_alloc + * add LOCK_AT_FORK -- thanks to Kirill Artamonov for the suggestion + * reduce compiler warnings -- thanks to all who reported/suggested these + + v2.8.5 Sun May 22 10:26:02 2011 Doug Lea (dl at gee) + * Always perform unlink checks unless INSECURE + * Add posix_memalign. + * Improve realloc to expand in more cases; expose realloc_in_place. + Thanks to Peter Buhr for the suggestion. + * Add footprint_limit, inspect_all, bulk_free. Thanks + to Barry Hayes and others for the suggestions. + * Internal refactorings to avoid calls while holding locks + * Use non-reentrant locks by default. Thanks to Roland McGrath + for the suggestion. + * Small fixes to mspace_destroy, reset_on_error. + * Various configuration extensions/changes. Thanks + to all who contributed these. + + V2.8.4a Thu Apr 28 14:39:43 2011 (dl at gee.cs.oswego.edu) + * Update Creative Commons URL + + V2.8.4 Wed May 27 09:56:23 2009 Doug Lea (dl at gee) + * Use zeros instead of prev foot for is_mmapped + * Add mspace_track_large_chunks; thanks to Jean Brouwers + * Fix set_inuse in internal_realloc; thanks to Jean Brouwers + * Fix insufficient sys_alloc padding when using 16byte alignment + * Fix bad error check in mspace_footprint + * Adaptations for ptmalloc; thanks to Wolfram Gloger. + * Reentrant spin locks; thanks to Earl Chew and others + * Win32 improvements; thanks to Niall Douglas and Earl Chew + * Add NO_SEGMENT_TRAVERSAL and MAX_RELEASE_CHECK_RATE options + * Extension hook in malloc_state + * Various small adjustments to reduce warnings on some compilers + * Various configuration extensions/changes for more platforms. Thanks + to all who contributed these. + + V2.8.3 Thu Sep 22 11:16:32 2005 Doug Lea (dl at gee) + * Add max_footprint functions + * Ensure all appropriate literals are size_t + * Fix conditional compilation problem for some #define settings + * Avoid concatenating segments with the one provided + in create_mspace_with_base + * Rename some variables to avoid compiler shadowing warnings + * Use explicit lock initialization. + * Better handling of sbrk interference. + * Simplify and fix segment insertion, trimming and mspace_destroy + * Reinstate REALLOC_ZERO_BYTES_FREES option from 2.7.x + * Thanks especially to Dennis Flanagan for help on these. + + V2.8.2 Sun Jun 12 16:01:10 2005 Doug Lea (dl at gee) + * Fix memalign brace error. + + V2.8.1 Wed Jun 8 16:11:46 2005 Doug Lea (dl at gee) + * Fix improper #endif nesting in C++ + * Add explicit casts needed for C++ + + V2.8.0 Mon May 30 14:09:02 2005 Doug Lea (dl at gee) + * Use trees for large bins + * Support mspaces + * Use segments to unify sbrk-based and mmap-based system allocation, + removing need for emulation on most platforms without sbrk. + * Default safety checks + * Optional footer checks. Thanks to William Robertson for the idea. + * Internal code refactoring + * Incorporate suggestions and platform-specific changes. + Thanks to Dennis Flanagan, Colin Plumb, Niall Douglas, + Aaron Bachmann, Emery Berger, and others. + * Speed up non-fastbin processing enough to remove fastbins. + * Remove useless cfree() to avoid conflicts with other apps. + * Remove internal memcpy, memset. Compilers handle builtins better. + * Remove some options that no one ever used and rename others. + + V2.7.2 Sat Aug 17 09:07:30 2002 Doug Lea (dl at gee) + * Fix malloc_state bitmap array misdeclaration + + V2.7.1 Thu Jul 25 10:58:03 2002 Doug Lea (dl at gee) + * Allow tuning of FIRST_SORTED_BIN_SIZE + * Use PTR_UINT as type for all ptr->int casts. Thanks to John Belmonte. + * Better detection and support for non-contiguousness of MORECORE. + Thanks to Andreas Mueller, Conal Walsh, and Wolfram Gloger + * Bypass most of malloc if no frees. Thanks To Emery Berger. + * Fix freeing of old top non-contiguous chunk im sysmalloc. + * Raised default trim and map thresholds to 256K. + * Fix mmap-related #defines. Thanks to Lubos Lunak. + * Fix copy macros; added LACKS_FCNTL_H. Thanks to Neal Walfield. + * Branch-free bin calculation + * Default trim and mmap thresholds now 256K. + + V2.7.0 Sun Mar 11 14:14:06 2001 Doug Lea (dl at gee) + * Introduce independent_comalloc and independent_calloc. + Thanks to Michael Pachos for motivation and help. + * Make optional .h file available + * Allow > 2GB requests on 32bit systems. + * new WIN32 sbrk, mmap, munmap, lock code from . + Thanks also to Andreas Mueller , + and Anonymous. + * Allow override of MALLOC_ALIGNMENT (Thanks to Ruud Waij for + helping test this.) + * memalign: check alignment arg + * realloc: don't try to shift chunks backwards, since this + leads to more fragmentation in some programs and doesn't + seem to help in any others. + * Collect all cases in malloc requiring system memory into sysmalloc + * Use mmap as backup to sbrk + * Place all internal state in malloc_state + * Introduce fastbins (although similar to 2.5.1) + * Many minor tunings and cosmetic improvements + * Introduce USE_PUBLIC_MALLOC_WRAPPERS, USE_MALLOC_LOCK + * Introduce MALLOC_FAILURE_ACTION, MORECORE_CONTIGUOUS + Thanks to Tony E. Bennett and others. + * Include errno.h to support default failure action. + + V2.6.6 Sun Dec 5 07:42:19 1999 Doug Lea (dl at gee) + * return null for negative arguments + * Added Several WIN32 cleanups from Martin C. Fong + * Add 'LACKS_SYS_PARAM_H' for those systems without 'sys/param.h' + (e.g. WIN32 platforms) + * Cleanup header file inclusion for WIN32 platforms + * Cleanup code to avoid Microsoft Visual C++ compiler complaints + * Add 'USE_DL_PREFIX' to quickly allow co-existence with existing + memory allocation routines + * Set 'malloc_getpagesize' for WIN32 platforms (needs more work) + * Use 'assert' rather than 'ASSERT' in WIN32 code to conform to + usage of 'assert' in non-WIN32 code + * Improve WIN32 'sbrk()' emulation's 'findRegion()' routine to + avoid infinite loop + * Always call 'fREe()' rather than 'free()' + + V2.6.5 Wed Jun 17 15:57:31 1998 Doug Lea (dl at gee) + * Fixed ordering problem with boundary-stamping + + V2.6.3 Sun May 19 08:17:58 1996 Doug Lea (dl at gee) + * Added pvalloc, as recommended by H.J. Liu + * Added 64bit pointer support mainly from Wolfram Gloger + * Added anonymously donated WIN32 sbrk emulation + * Malloc, calloc, getpagesize: add optimizations from Raymond Nijssen + * malloc_extend_top: fix mask error that caused wastage after + foreign sbrks + * Add linux mremap support code from HJ Liu + + V2.6.2 Tue Dec 5 06:52:55 1995 Doug Lea (dl at gee) + * Integrated most documentation with the code. + * Add support for mmap, with help from + Wolfram Gloger (Gloger@lrz.uni-muenchen.de). + * Use last_remainder in more cases. + * Pack bins using idea from colin@nyx10.cs.du.edu + * Use ordered bins instead of best-fit threshhold + * Eliminate block-local decls to simplify tracing and debugging. + * Support another case of realloc via move into top + * Fix error occuring when initial sbrk_base not word-aligned. + * Rely on page size for units instead of SBRK_UNIT to + avoid surprises about sbrk alignment conventions. + * Add mallinfo, mallopt. Thanks to Raymond Nijssen + (raymond@es.ele.tue.nl) for the suggestion. + * Add `pad' argument to malloc_trim and top_pad mallopt parameter. + * More precautions for cases where other routines call sbrk, + courtesy of Wolfram Gloger (Gloger@lrz.uni-muenchen.de). + * Added macros etc., allowing use in linux libc from + H.J. Lu (hjl@gnu.ai.mit.edu) + * Inverted this history list + + V2.6.1 Sat Dec 2 14:10:57 1995 Doug Lea (dl at gee) + * Re-tuned and fixed to behave more nicely with V2.6.0 changes. + * Removed all preallocation code since under current scheme + the work required to undo bad preallocations exceeds + the work saved in good cases for most test programs. + * No longer use return list or unconsolidated bins since + no scheme using them consistently outperforms those that don't + given above changes. + * Use best fit for very large chunks to prevent some worst-cases. + * Added some support for debugging + + V2.6.0 Sat Nov 4 07:05:23 1995 Doug Lea (dl at gee) + * Removed footers when chunks are in use. Thanks to + Paul Wilson (wilson@cs.texas.edu) for the suggestion. + + V2.5.4 Wed Nov 1 07:54:51 1995 Doug Lea (dl at gee) + * Added malloc_trim, with help from Wolfram Gloger + (wmglo@Dent.MED.Uni-Muenchen.DE). + + V2.5.3 Tue Apr 26 10:16:01 1994 Doug Lea (dl at g) + + V2.5.2 Tue Apr 5 16:20:40 1994 Doug Lea (dl at g) + * realloc: try to expand in both directions + * malloc: swap order of clean-bin strategy; + * realloc: only conditionally expand backwards + * Try not to scavenge used bins + * Use bin counts as a guide to preallocation + * Occasionally bin return list chunks in first scan + * Add a few optimizations from colin@nyx10.cs.du.edu + + V2.5.1 Sat Aug 14 15:40:43 1993 Doug Lea (dl at g) + * faster bin computation & slightly different binning + * merged all consolidations to one part of malloc proper + (eliminating old malloc_find_space & malloc_clean_bin) + * Scan 2 returns chunks (not just 1) + * Propagate failure in realloc if malloc returns 0 + * Add stuff to allow compilation on non-ANSI compilers + from kpv@research.att.com + + V2.5 Sat Aug 7 07:41:59 1993 Doug Lea (dl at g.oswego.edu) + * removed potential for odd address access in prev_chunk + * removed dependency on getpagesize.h + * misc cosmetics and a bit more internal documentation + * anticosmetics: mangled names in macros to evade debugger strangeness + * tested on sparc, hp-700, dec-mips, rs6000 + with gcc & native cc (hp, dec only) allowing + Detlefs & Zorn comparison study (in SIGPLAN Notices.) + + Trial version Fri Aug 28 13:14:29 1992 Doug Lea (dl at g.oswego.edu) + * Based loosely on libg++-1.2X malloc. (It retains some of the overall + structure of old version, but most details differ.) + +*/ + +#endif // KONAN_INTERNAL_MALLOC diff --git a/kotlin-native/runtime/src/main/cpp/dtoa/cbigint.cpp b/kotlin-native/runtime/src/main/cpp/dtoa/cbigint.cpp new file mode 100644 index 00000000000..136196da0d3 --- /dev/null +++ b/kotlin-native/runtime/src/main/cpp/dtoa/cbigint.cpp @@ -0,0 +1,904 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include "cbigint.h" + +#if defined(LINUX) || defined(FREEBSD) || defined(ZOS) || defined(MACOSX) || defined(AIX) +#define USE_LL +#endif + +#ifdef HY_LITTLE_ENDIAN +#define at(i) (i) +#else +#define at(i) ((i)^1) +/* the sequence for halfAt is -1, 2, 1, 4, 3, 6, 5, 8... */ +/* and it should correspond to 0, 1, 2, 3, 4, 5, 6, 7... */ +#define halfAt(i) (-((-(i)) ^ 1)) +#endif + +#define HIGH_IN_U64(u64) ((u64) >> 32) +#if defined(USE_LL) +#define LOW_IN_U64(u64) ((u64) & 0x00000000FFFFFFFFLL) +#else +#if defined(USE_L) +#define LOW_IN_U64(u64) ((u64) & 0x00000000FFFFFFFFL) +#else +#define LOW_IN_U64(u64) ((u64) & 0x00000000FFFFFFFF) +#endif /* USE_L */ +#endif /* USE_LL */ + +#if defined(USE_LL) +#define TEN_E1 (0xALL) +#define TEN_E2 (0x64LL) +#define TEN_E3 (0x3E8LL) +#define TEN_E4 (0x2710LL) +#define TEN_E5 (0x186A0LL) +#define TEN_E6 (0xF4240LL) +#define TEN_E7 (0x989680LL) +#define TEN_E8 (0x5F5E100LL) +#define TEN_E9 (0x3B9ACA00LL) +#define TEN_E19 (0x8AC7230489E80000LL) +#else +#if defined(USE_L) +#define TEN_E1 (0xAL) +#define TEN_E2 (0x64L) +#define TEN_E3 (0x3E8L) +#define TEN_E4 (0x2710L) +#define TEN_E5 (0x186A0L) +#define TEN_E6 (0xF4240L) +#define TEN_E7 (0x989680L) +#define TEN_E8 (0x5F5E100L) +#define TEN_E9 (0x3B9ACA00L) +#define TEN_E19 (0x8AC7230489E80000L) +#else +#define TEN_E1 (0xA) +#define TEN_E2 (0x64) +#define TEN_E3 (0x3E8) +#define TEN_E4 (0x2710) +#define TEN_E5 (0x186A0) +#define TEN_E6 (0xF4240) +#define TEN_E7 (0x989680) +#define TEN_E8 (0x5F5E100) +#define TEN_E9 (0x3B9ACA00) +#define TEN_E19 (0x8AC7230489E80000) +#endif /* USE_L */ +#endif /* USE_LL */ + +#define TIMES_TEN(x) (((x) << 3) + ((x) << 1)) +#define bitSection(x, mask, shift) (((x) & (mask)) >> (shift)) +#define DOUBLE_TO_LONGBITS(dbl) (*((U_64 *)(&dbl))) +#define FLOAT_TO_INTBITS(flt) (*((U_32 *)(&flt))) +#define CREATE_DOUBLE_BITS(normalizedM, e) (((normalizedM) & MANTISSA_MASK) | (((U_64)((e) + E_OFFSET)) << 52)) + +#if defined(USE_LL) +#define MANTISSA_MASK (0x000FFFFFFFFFFFFFLL) +#define EXPONENT_MASK (0x7FF0000000000000LL) +#define NORMAL_MASK (0x0010000000000000LL) +#define SIGN_MASK (0x8000000000000000LL) +#else +#if defined(USE_L) +#define MANTISSA_MASK (0x000FFFFFFFFFFFFFL) +#define EXPONENT_MASK (0x7FF0000000000000L) +#define NORMAL_MASK (0x0010000000000000L) +#define SIGN_MASK (0x8000000000000000L) +#else +#define MANTISSA_MASK (0x000FFFFFFFFFFFFF) +#define EXPONENT_MASK (0x7FF0000000000000) +#define NORMAL_MASK (0x0010000000000000) +#define SIGN_MASK (0x8000000000000000) +#endif /* USE_L */ +#endif /* USE_LL */ + +#define E_OFFSET (1075) + +#define FLOAT_MANTISSA_MASK (0x007FFFFF) +#define FLOAT_EXPONENT_MASK (0x7F800000) +#define FLOAT_NORMAL_MASK (0x00800000) +#define FLOAT_E_OFFSET (150) + +IDATA +simpleAddHighPrecision (U_64 * arg1, IDATA length, U_64 arg2) +{ + /* assumes length > 0 */ + IDATA index = 1; + + *arg1 += arg2; + if (arg2 <= *arg1) + return 0; + else if (length == 1) + return 1; + + while (++arg1[index] == 0 && ++index < length); + + return (IDATA) index == length; +} + +IDATA +addHighPrecision (U_64 * arg1, IDATA length1, U_64 * arg2, IDATA length2) +{ + /* addition is limited by length of arg1 as it this function is + * storing the result in arg1 */ + /* fix for cc (GCC) 3.2 20020903 (Red Hat Linux 8.0 3.2-7): code generated does not + * do the temp1 + temp2 + carry addition correct. carry is 64 bit because gcc has + * subtle issues when you mix 64 / 32 bit maths. */ + U_64 temp1, temp2, temp3; /* temporary variables to help the SH-4, and gcc */ + U_64 carry; + IDATA index; + + if (length1 == 0 || length2 == 0) + { + return 0; + } + else if (length1 < length2) + { + length2 = length1; + } + + carry = 0; + index = 0; + do + { + temp1 = arg1[index]; + temp2 = arg2[index]; + temp3 = temp1 + temp2; + arg1[index] = temp3 + carry; + if (arg2[index] < arg1[index]) + carry = 0; + else if (arg2[index] != arg1[index]) + carry = 1; + } + while (++index < length2); + if (!carry) + return 0; + else if (index == length1) + return 1; + + while (++arg1[index] == 0 && ++index < length1); + + return (IDATA) index == length1; +} + +void +subtractHighPrecision (U_64 * arg1, IDATA length1, U_64 * arg2, IDATA length2) +{ + /* assumes arg1 > arg2 */ + IDATA index; + for (index = 0; index < length1; ++index) + arg1[index] = ~arg1[index]; + simpleAddHighPrecision (arg1, length1, 1); + + while (length2 > 0 && arg2[length2 - 1] == 0) + --length2; + + addHighPrecision (arg1, length1, arg2, length2); + + for (index = 0; index < length1; ++index) + arg1[index] = ~arg1[index]; + simpleAddHighPrecision (arg1, length1, 1); +} + +U_32 +simpleMultiplyHighPrecision (U_64 * arg1, IDATA length, U_64 arg2) +{ + /* assumes arg2 only holds 32 bits of information */ + U_64 product; + IDATA index; + + index = 0; + product = 0; + + do + { + product = + HIGH_IN_U64 (product) + arg2 * LOW_U32_FROM_PTR (arg1 + index); + LOW_U32_FROM_PTR (arg1 + index) = LOW_U32_FROM_VAR (product); + product = + HIGH_IN_U64 (product) + arg2 * HIGH_U32_FROM_PTR (arg1 + index); + HIGH_U32_FROM_PTR (arg1 + index) = LOW_U32_FROM_VAR (product); + } + while (++index < length); + + return HIGH_U32_FROM_VAR (product); +} + +void +simpleMultiplyAddHighPrecision (U_64 * arg1, IDATA length, U_64 arg2, + U_32 * result) +{ + /* Assumes result can hold the product and arg2 only holds 32 bits + of information */ + U_64 product; + IDATA index, resultIndex; + + index = resultIndex = 0; + product = 0; + + do + { + product = + HIGH_IN_U64 (product) + result[at (resultIndex)] + + arg2 * LOW_U32_FROM_PTR (arg1 + index); + result[at (resultIndex)] = LOW_U32_FROM_VAR (product); + ++resultIndex; + product = + HIGH_IN_U64 (product) + result[at (resultIndex)] + + arg2 * HIGH_U32_FROM_PTR (arg1 + index); + result[at (resultIndex)] = LOW_U32_FROM_VAR (product); + ++resultIndex; + } + while (++index < length); + + result[at (resultIndex)] += HIGH_U32_FROM_VAR (product); + if (result[at (resultIndex)] < HIGH_U32_FROM_VAR (product)) + { + /* must be careful with ++ operator and macro expansion */ + ++resultIndex; + while (++result[at (resultIndex)] == 0) + ++resultIndex; + } +} + +#ifndef HY_LITTLE_ENDIAN +void simpleMultiplyAddHighPrecisionBigEndianFix(U_64 *arg1, IDATA length, U_64 arg2, U_32 *result) { + /* Assumes result can hold the product and arg2 only holds 32 bits + of information */ + U_64 product; + IDATA index, resultIndex; + + index = resultIndex = 0; + product = 0; + + do { + product = HIGH_IN_U64(product) + result[halfAt(resultIndex)] + arg2 * LOW_U32_FROM_PTR(arg1 + index); + result[halfAt(resultIndex)] = LOW_U32_FROM_VAR(product); + ++resultIndex; + product = HIGH_IN_U64(product) + result[halfAt(resultIndex)] + arg2 * HIGH_U32_FROM_PTR(arg1 + index); + result[halfAt(resultIndex)] = LOW_U32_FROM_VAR(product); + ++resultIndex; + } while (++index < length); + + result[halfAt(resultIndex)] += HIGH_U32_FROM_VAR(product); + if (result[halfAt(resultIndex)] < HIGH_U32_FROM_VAR(product)) { + /* must be careful with ++ operator and macro expansion */ + ++resultIndex; + while (++result[halfAt(resultIndex)] == 0) ++resultIndex; + } +} +#endif + +void +multiplyHighPrecision (U_64 * arg1, IDATA length1, U_64 * arg2, IDATA length2, + U_64 * result, IDATA length) +{ + /* assumes result is large enough to hold product */ + U_64 *temp; + U_32 *resultIn32; + IDATA count, index; + + if (length1 < length2) + { + temp = arg1; + arg1 = arg2; + arg2 = temp; + count = length1; + length1 = length2; + length2 = count; + } + + memset (result, 0, sizeof (U_64) * length); + + /* length1 > length2 */ + resultIn32 = (U_32 *) result; + index = -1; + for (count = 0; count < length2; ++count) + { + simpleMultiplyAddHighPrecision (arg1, length1, LOW_IN_U64 (arg2[count]), + resultIn32 + (++index)); +#ifdef HY_LITTLE_ENDIAN + simpleMultiplyAddHighPrecision(arg1, length1, HIGH_IN_U64(arg2[count]), resultIn32 + (++index)); +#else + simpleMultiplyAddHighPrecisionBigEndianFix(arg1, length1, HIGH_IN_U64(arg2[count]), resultIn32 + (++index)); +#endif + } +} + +U_32 +simpleAppendDecimalDigitHighPrecision (U_64 * arg1, IDATA length, U_64 digit) +{ + /* assumes digit is less than 32 bits */ + U_64 arg; + IDATA index = 0; + + digit <<= 32; + do + { + arg = LOW_IN_U64 (arg1[index]); + digit = HIGH_IN_U64 (digit) + TIMES_TEN (arg); + LOW_U32_FROM_PTR (arg1 + index) = LOW_U32_FROM_VAR (digit); + + arg = HIGH_IN_U64 (arg1[index]); + digit = HIGH_IN_U64 (digit) + TIMES_TEN (arg); + HIGH_U32_FROM_PTR (arg1 + index) = LOW_U32_FROM_VAR (digit); + } + while (++index < length); + + return HIGH_U32_FROM_VAR (digit); +} + +void +simpleShiftLeftHighPrecision (U_64 * arg1, IDATA length, IDATA arg2) +{ + /* assumes length > 0 */ + IDATA index, offset; + if (arg2 >= 64) + { + offset = arg2 >> 6; + index = length; + + while (--index - offset >= 0) + arg1[index] = arg1[index - offset]; + do + { + arg1[index] = 0; + } + while (--index >= 0); + + arg2 &= 0x3F; + } + + if (arg2 == 0) + return; + while (--length > 0) + { + arg1[length] = arg1[length] << arg2 | arg1[length - 1] >> (64 - arg2); + } + *arg1 <<= arg2; +} + +IDATA +highestSetBit (U_64 * y) +{ + U_32 x; + IDATA result; + + if (*y == 0) + return 0; + +#if defined(USE_LL) + if (*y & 0xFFFFFFFF00000000LL) + { + x = HIGH_U32_FROM_PTR (y); + result = 32; + } + else + { + x = LOW_U32_FROM_PTR (y); + result = 0; + } +#else +#if defined(USE_L) + if (*y & 0xFFFFFFFF00000000L) + { + x = HIGH_U32_FROM_PTR (y); + result = 32; + } + else + { + x = LOW_U32_FROM_PTR (y); + result = 0; + } +#else + if (*y & 0xFFFFFFFF00000000) + { + x = HIGH_U32_FROM_PTR (y); + result = 32; + } + else + { + x = LOW_U32_FROM_PTR (y); + result = 0; + } +#endif /* USE_L */ +#endif /* USE_LL */ + + if (x & 0xFFFF0000) + { + x = bitSection (x, 0xFFFF0000, 16); + result += 16; + } + if (x & 0xFF00) + { + x = bitSection (x, 0xFF00, 8); + result += 8; + } + if (x & 0xF0) + { + x = bitSection (x, 0xF0, 4); + result += 4; + } + if (x > 0x7) + return result + 4; + else if (x > 0x3) + return result + 3; + else if (x > 0x1) + return result + 2; + else + return result + 1; +} + +IDATA +lowestSetBit (U_64 * y) +{ + U_32 x; + IDATA result; + + if (*y == 0) + return 0; + +#if defined(USE_LL) + if (*y & 0x00000000FFFFFFFFLL) + { + x = LOW_U32_FROM_PTR (y); + result = 0; + } + else + { + x = HIGH_U32_FROM_PTR (y); + result = 32; + } +#else +#if defined(USE_L) + if (*y & 0x00000000FFFFFFFFL) + { + x = LOW_U32_FROM_PTR (y); + result = 0; + } + else + { + x = HIGH_U32_FROM_PTR (y); + result = 32; + } +#else + if (*y & 0x00000000FFFFFFFF) + { + x = LOW_U32_FROM_PTR (y); + result = 0; + } + else + { + x = HIGH_U32_FROM_PTR (y); + result = 32; + } +#endif /* USE_L */ +#endif /* USE_LL */ + + if (!(x & 0xFFFF)) + { + x = bitSection (x, 0xFFFF0000, 16); + result += 16; + } + if (!(x & 0xFF)) + { + x = bitSection (x, 0xFF00, 8); + result += 8; + } + if (!(x & 0xF)) + { + x = bitSection (x, 0xF0, 4); + result += 4; + } + + if (x & 0x1) + return result + 1; + else if (x & 0x2) + return result + 2; + else if (x & 0x4) + return result + 3; + else + return result + 4; +} + +IDATA +highestSetBitHighPrecision (U_64 * arg, IDATA length) +{ + IDATA highBit; + + while (--length >= 0) + { + highBit = highestSetBit (arg + length); + if (highBit) + return highBit + 64 * length; + } + + return 0; +} + +IDATA +lowestSetBitHighPrecision (U_64 * arg, IDATA length) +{ + IDATA lowBit, index = -1; + + while (++index < length) + { + lowBit = lowestSetBit (arg + index); + if (lowBit) + return lowBit + 64 * index; + } + + return 0; +} + +IDATA +compareHighPrecision (U_64 * arg1, IDATA length1, U_64 * arg2, IDATA length2) +{ + while (--length1 >= 0 && arg1[length1] == 0); + while (--length2 >= 0 && arg2[length2] == 0); + + if (length1 > length2) + return 1; + else if (length1 < length2) + return -1; + else if (length1 > -1) + { + do + { + if (arg1[length1] > arg2[length1]) + return 1; + else if (arg1[length1] < arg2[length1]) + return -1; + } + while (--length1 >= 0); + } + + return 0; +} + +KDouble +toDoubleHighPrecision (U_64 * arg, IDATA length) +{ + IDATA highBit; + U_64 mantissa, test64; + U_32 test; + KDouble result; + + while (length > 0 && arg[length - 1] == 0) + --length; + + if (length == 0) + result = 0.0; + else if (length > 16) + { + DOUBLE_TO_LONGBITS (result) = EXPONENT_MASK; + } + else if (length == 1) + { + highBit = highestSetBit (arg); + if (highBit <= 53) + { + highBit = 53 - highBit; + mantissa = *arg << highBit; + DOUBLE_TO_LONGBITS (result) = + CREATE_DOUBLE_BITS (mantissa, -highBit); + } + else + { + highBit -= 53; + mantissa = *arg >> highBit; + DOUBLE_TO_LONGBITS (result) = + CREATE_DOUBLE_BITS (mantissa, highBit); + + /* perform rounding, round to even in case of tie */ + test = (LOW_U32_FROM_PTR (arg) << (11 - highBit)) & 0x7FF; + if (test > 0x400 || ((test == 0x400) && (mantissa & 1))) + DOUBLE_TO_LONGBITS (result) = DOUBLE_TO_LONGBITS (result) + 1; + } + } + else + { + highBit = highestSetBit (arg + (--length)); + if (highBit <= 53) + { + highBit = 53 - highBit; + if (highBit > 0) + { + mantissa = + (arg[length] << highBit) | (arg[length - 1] >> + (64 - highBit)); + } + else + { + mantissa = arg[length]; + } + DOUBLE_TO_LONGBITS (result) = + CREATE_DOUBLE_BITS (mantissa, length * 64 - highBit); + + /* perform rounding, round to even in case of tie */ + test64 = arg[--length] << highBit; + if (test64 > SIGN_MASK || ((test64 == SIGN_MASK) && (mantissa & 1))) + DOUBLE_TO_LONGBITS (result) = DOUBLE_TO_LONGBITS (result) + 1; + else if (test64 == SIGN_MASK) + { + while (--length >= 0) + { + if (arg[length] != 0) + { + DOUBLE_TO_LONGBITS (result) = + DOUBLE_TO_LONGBITS (result) + 1; + break; + } + } + } + } + else + { + highBit -= 53; + mantissa = arg[length] >> highBit; + DOUBLE_TO_LONGBITS (result) = + CREATE_DOUBLE_BITS (mantissa, length * 64 + highBit); + + /* perform rounding, round to even in case of tie */ + test = (LOW_U32_FROM_PTR (arg + length) << (11 - highBit)) & 0x7FF; + if (test > 0x400 || ((test == 0x400) && (mantissa & 1))) + DOUBLE_TO_LONGBITS (result) = DOUBLE_TO_LONGBITS (result) + 1; + else if (test == 0x400) + { + do + { + if (arg[--length] != 0) + { + DOUBLE_TO_LONGBITS (result) = + DOUBLE_TO_LONGBITS (result) + 1; + break; + } + } + while (length > 0); + } + } + } + + return result; +} + +IDATA +tenToTheEHighPrecision (U_64 * result, IDATA length, int e) +{ + /* size test */ + if (length < ((e / 19) + 1)) + return 0; + + memset (result, 0, length * sizeof (U_64)); + *result = 1; + + if (e == 0) + return 1; + + length = 1; + length = timesTenToTheEHighPrecision (result, length, e); + /* bad O(n) way of doing it, but simple */ + /* + do { + overflow = simpleAppendDecimalDigitHighPrecision(result, length, 0); + if (overflow) + result[length++] = overflow; + } while (--e); + */ + return length; +} + +IDATA +timesTenToTheEHighPrecision (U_64 * result, IDATA length, int e) +{ + /* assumes result can hold value */ + U_64 overflow; + int exp10 = e; + + if (e == 0) + return length; + + /* bad O(n) way of doing it, but simple */ + /* + do { + overflow = simpleAppendDecimalDigitHighPrecision(result, length, 0); + if (overflow) + result[length++] = overflow; + } while (--e); + */ + /* Replace the current implementation which performs a + * "multiplication" by 10 e number of times with an actual + * multiplication. 10e19 is the largest exponent to the power of ten + * that will fit in a 64-bit integer, and 10e9 is the largest exponent to + * the power of ten that will fit in a 64-bit integer. Not sure where the + * break-even point is between an actual multiplication and a + * simpleAappendDecimalDigit() so just pick 10e3 as that point for + * now. + */ + while (exp10 >= 19) + { + overflow = simpleMultiplyHighPrecision64 (result, length, TEN_E19); + if (overflow) + result[length++] = overflow; + exp10 -= 19; + } + while (exp10 >= 9) + { + overflow = simpleMultiplyHighPrecision (result, length, TEN_E9); + if (overflow) + result[length++] = overflow; + exp10 -= 9; + } + if (exp10 == 0) + return length; + else if (exp10 == 1) + { + overflow = simpleAppendDecimalDigitHighPrecision (result, length, 0); + if (overflow) + result[length++] = overflow; + } + else if (exp10 == 2) + { + overflow = simpleAppendDecimalDigitHighPrecision (result, length, 0); + if (overflow) + result[length++] = overflow; + overflow = simpleAppendDecimalDigitHighPrecision (result, length, 0); + if (overflow) + result[length++] = overflow; + } + else if (exp10 == 3) + { + overflow = simpleMultiplyHighPrecision (result, length, TEN_E3); + if (overflow) + result[length++] = overflow; + } + else if (exp10 == 4) + { + overflow = simpleMultiplyHighPrecision (result, length, TEN_E4); + if (overflow) + result[length++] = overflow; + } + else if (exp10 == 5) + { + overflow = simpleMultiplyHighPrecision (result, length, TEN_E5); + if (overflow) + result[length++] = overflow; + } + else if (exp10 == 6) + { + overflow = simpleMultiplyHighPrecision (result, length, TEN_E6); + if (overflow) + result[length++] = overflow; + } + else if (exp10 == 7) + { + overflow = simpleMultiplyHighPrecision (result, length, TEN_E7); + if (overflow) + result[length++] = overflow; + } + else if (exp10 == 8) + { + overflow = simpleMultiplyHighPrecision (result, length, TEN_E8); + if (overflow) + result[length++] = overflow; + } + return length; +} + +U_64 +doubleMantissa (KDouble z) +{ + U_64 m = DOUBLE_TO_LONGBITS (z); + + if ((m & EXPONENT_MASK) != 0) + m = (m & MANTISSA_MASK) | NORMAL_MASK; + else + m = (m & MANTISSA_MASK); + + return m; +} + +IDATA +doubleExponent (KDouble z) +{ + /* assumes positive double */ + IDATA k = HIGH_U32_FROM_VAR (z) >> 20; + + if (k) + k -= E_OFFSET; + else + k = 1 - E_OFFSET; + + return k; +} + +UDATA +floatMantissa (KFloat z) +{ + UDATA m = (UDATA) FLOAT_TO_INTBITS (z); + + if ((m & FLOAT_EXPONENT_MASK) != 0) + m = (m & FLOAT_MANTISSA_MASK) | FLOAT_NORMAL_MASK; + else + m = (m & FLOAT_MANTISSA_MASK); + + return m; +} + +IDATA +floatExponent (KFloat z) +{ + /* assumes positive float */ + IDATA k = FLOAT_TO_INTBITS (z) >> 23; + if (k) + k -= FLOAT_E_OFFSET; + else + k = 1 - FLOAT_E_OFFSET; + + return k; +} + +/* Allow a 64-bit value in arg2 */ +U_64 +simpleMultiplyHighPrecision64 (U_64 * arg1, IDATA length, U_64 arg2) +{ + U_64 intermediate, *pArg1, carry1, carry2, prod1, prod2, sum; + IDATA index; + U_32 buf32; + + index = 0; + intermediate = 0; + pArg1 = arg1 + index; + carry1 = carry2 = 0; + + do + { + if ((*pArg1 != 0) || (intermediate != 0)) + { + prod1 = + (U_64) LOW_U32_FROM_VAR (arg2) * (U_64) LOW_U32_FROM_PTR (pArg1); + sum = intermediate + prod1; + if ((sum < prod1) || (sum < intermediate)) + { + carry1 = 1; + } + else + { + carry1 = 0; + } + prod1 = + (U_64) LOW_U32_FROM_VAR (arg2) * (U_64) HIGH_U32_FROM_PTR (pArg1); + prod2 = + (U_64) HIGH_U32_FROM_VAR (arg2) * (U_64) LOW_U32_FROM_PTR (pArg1); + intermediate = carry2 + HIGH_IN_U64 (sum) + prod1 + prod2; + if ((intermediate < prod1) || (intermediate < prod2)) + { + carry2 = 1; + } + else + { + carry2 = 0; + } + LOW_U32_FROM_PTR (pArg1) = LOW_U32_FROM_VAR (sum); + buf32 = HIGH_U32_FROM_PTR (pArg1); + HIGH_U32_FROM_PTR (pArg1) = LOW_U32_FROM_VAR (intermediate); + intermediate = carry1 + HIGH_IN_U64 (intermediate) + + (U_64) HIGH_U32_FROM_VAR (arg2) * (U_64) buf32; + } + pArg1++; + } + while (++index < length); + return intermediate; +} diff --git a/kotlin-native/runtime/src/main/cpp/dtoa/cbigint.h b/kotlin-native/runtime/src/main/cpp/dtoa/cbigint.h new file mode 100644 index 00000000000..38a4c6403e9 --- /dev/null +++ b/kotlin-native/runtime/src/main/cpp/dtoa/cbigint.h @@ -0,0 +1,57 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#if !defined(cbigint_h) +#define cbigint_h +#include "fltconst.h" +#include "../Types.h" +//#include "vmi.h" +#define LOW_U32_FROM_VAR(u64) LOW_U32_FROM_LONG64(u64) +#define LOW_U32_FROM_PTR(u64ptr) LOW_U32_FROM_LONG64_PTR(u64ptr) +#define HIGH_U32_FROM_VAR(u64) HIGH_U32_FROM_LONG64(u64) +#define HIGH_U32_FROM_PTR(u64ptr) HIGH_U32_FROM_LONG64_PTR(u64ptr) +#if defined(__cplusplus) +extern "C" +{ +#endif + void multiplyHighPrecision (U_64 * arg1, IDATA length1, U_64 * arg2, + IDATA length2, U_64 * result, IDATA length); + U_32 simpleAppendDecimalDigitHighPrecision (U_64 * arg1, IDATA length, U_64 digit); + KDouble toDoubleHighPrecision (U_64 * arg, IDATA length); + IDATA tenToTheEHighPrecision (U_64 * result, IDATA length, int e); + U_64 doubleMantissa (KDouble z); + IDATA compareHighPrecision (U_64 * arg1, IDATA length1, U_64 * arg2, IDATA length2); + IDATA highestSetBitHighPrecision (U_64 * arg, IDATA length); + void subtractHighPrecision (U_64 * arg1, IDATA length1, U_64 * arg2, IDATA length2); + IDATA doubleExponent (KDouble z); + U_32 simpleMultiplyHighPrecision (U_64 * arg1, IDATA length, U_64 arg2); + IDATA addHighPrecision (U_64 * arg1, IDATA length1, U_64 * arg2, IDATA length2); + void simpleMultiplyAddHighPrecisionBigEndianFix (U_64 * arg1, IDATA length, U_64 arg2, U_32 * result); + IDATA lowestSetBit (U_64 * y); + IDATA timesTenToTheEHighPrecision (U_64 * result, IDATA length, int e); + void simpleMultiplyAddHighPrecision (U_64 * arg1, IDATA length, U_64 arg2, U_32 * result); + IDATA highestSetBit (U_64 * y); + IDATA lowestSetBitHighPrecision (U_64 * arg, IDATA length); + void simpleShiftLeftHighPrecision (U_64 * arg1, IDATA length, IDATA arg2); + UDATA floatMantissa (KFloat z); + U_64 simpleMultiplyHighPrecision64 (U_64 * arg1, IDATA length, U_64 arg2); + IDATA simpleAddHighPrecision (U_64 * arg1, IDATA length, U_64 arg2); + IDATA floatExponent (KFloat z); +#if defined(__cplusplus) +} +#endif +#endif /* cbigint_h */ diff --git a/kotlin-native/runtime/src/main/cpp/dtoa/dblparse.cpp b/kotlin-native/runtime/src/main/cpp/dtoa/dblparse.cpp new file mode 100644 index 00000000000..3a8fe51175c --- /dev/null +++ b/kotlin-native/runtime/src/main/cpp/dtoa/dblparse.cpp @@ -0,0 +1,878 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include +#include + +#include "cbigint.h" +#include "../Exceptions.h" +#include "../KString.h" +#include "../Natives.h" +#include "../utf8.h" + +#if defined(LINUX) || defined(FREEBSD) || defined(ZOS) || defined(MACOSX) || defined(AIX) +#define USE_LL +#endif + +#define LOW_I32_FROM_VAR(u64) LOW_I32_FROM_LONG64(u64) +#define LOW_I32_FROM_PTR(u64ptr) LOW_I32_FROM_LONG64_PTR(u64ptr) +#define HIGH_I32_FROM_VAR(u64) HIGH_I32_FROM_LONG64(u64) +#define HIGH_I32_FROM_PTR(u64ptr) HIGH_I32_FROM_LONG64_PTR(u64ptr) + +#define MAX_ACCURACY_WIDTH 17 + +#define DEFAULT_WIDTH MAX_ACCURACY_WIDTH + +extern "C" { +KDouble Kotlin_native_FloatingPointParser_parseDoubleImpl (KString s, KInt e); + +void Kotlin_native_NumberConverter_bigIntDigitGeneratorInstImpl (KRef results, + KRef uArray, + KLong f, + KInt e, + KBoolean isDenormalized, + KBoolean mantissaIsZero, + KInt p); + +KDouble Kotlin_native_NumberConverter_ceil(KDouble x) { + return ceil(x); +} + +void Kotlin_IntArray_set(KRef thiz, KInt index, KInt value); + +KDouble Kotlin_native_long_bits_to_double(KLong x); +} + +KDouble Kotlin_native_long_bits_to_double(KLong x) { + union { + int64_t x; + double d; + } tmp; + tmp.x = x; + return tmp.d; +} + +KDouble createDouble (const char *s, KInt e); +KDouble createDouble1 (U_64 * f, IDATA length, KInt e); +KDouble doubleAlgorithm (U_64 * f, IDATA length, KInt e, KDouble z); + +U_64 dblparse_shiftRight64 (U_64 * lp, volatile int mbe); + +static const KDouble tens[] = { + 1.0, + 1.0e1, + 1.0e2, + 1.0e3, + 1.0e4, + 1.0e5, + 1.0e6, + 1.0e7, + 1.0e8, + 1.0e9, + 1.0e10, + 1.0e11, + 1.0e12, + 1.0e13, + 1.0e14, + 1.0e15, + 1.0e16, + 1.0e17, + 1.0e18, + 1.0e19, + 1.0e20, + 1.0e21, + 1.0e22 +}; + +#define tenToTheE(e) (*(tens + (e))) +#define LOG5_OF_TWO_TO_THE_N 23 +#define INV_LOG_OF_TEN_BASE_2 (0.30102999566398114) +#define DOUBLE_MIN_VALUE 5.0e-324 + +#define sizeOfTenToTheE(e) (((e) / 19) + 1) + +#if defined(USE_LL) +#define INFINITE_LONGBITS (0x7FF0000000000000LL) +#else +#if defined(USE_L) +#define INFINITE_LONGBITS (0x7FF0000000000000L) +#else +#define INFINITE_LONGBITS (0x7FF0000000000000) +#endif /* USE_L */ +#endif /* USE_LL */ + +#define MINIMUM_LONGBITS (0x1) + +#if defined(USE_LL) +#define MANTISSA_MASK (0x000FFFFFFFFFFFFFLL) +#define EXPONENT_MASK (0x7FF0000000000000LL) +#define NORMAL_MASK (0x0010000000000000LL) +#else +#if defined(USE_L) +#define MANTISSA_MASK (0x000FFFFFFFFFFFFFL) +#define EXPONENT_MASK (0x7FF0000000000000L) +#define NORMAL_MASK (0x0010000000000000L) +#else +#define MANTISSA_MASK (0x000FFFFFFFFFFFFF) +#define EXPONENT_MASK (0x7FF0000000000000) +#define NORMAL_MASK (0x0010000000000000) +#endif /* USE_L */ +#endif /* USE_LL */ + +#define DOUBLE_TO_LONGBITS(dbl) (*((U_64 *)(&dbl))) + +/* Keep a count of the number of times we decrement and increment to + * approximate the double, and attempt to detect the case where we + * could potentially toggle back and forth between decrementing and + * incrementing. It is possible for us to be stuck in the loop when + * incrementing by one or decrementing by one may exceed or stay below + * the value that we are looking for. In this case, just break out of + * the loop if we toggle between incrementing and decrementing for more + * than twice. + */ +#define INCREMENT_DOUBLE(_x, _decCount, _incCount) \ + { \ + ++DOUBLE_TO_LONGBITS(_x); \ + _incCount++; \ + if( (_incCount > 2) && (_decCount > 2) ) { \ + if( _decCount > _incCount ) { \ + DOUBLE_TO_LONGBITS(_x) += _decCount - _incCount; \ + } else if( _incCount > _decCount ) { \ + DOUBLE_TO_LONGBITS(_x) -= _incCount - _decCount; \ + } \ + break; \ + } \ + } +#define DECREMENT_DOUBLE(_x, _decCount, _incCount) \ + { \ + --DOUBLE_TO_LONGBITS(_x); \ + _decCount++; \ + if( (_incCount > 2) && (_decCount > 2) ) { \ + if( _decCount > _incCount ) { \ + DOUBLE_TO_LONGBITS(_x) += _decCount - _incCount; \ + } else if( _incCount > _decCount ) { \ + DOUBLE_TO_LONGBITS(_x) -= _incCount - _decCount; \ + } \ + break; \ + } \ + } +#define ERROR_OCCURED(x) (HIGH_I32_FROM_VAR(x) < 0) + +#define allocateU64(x, n) if (!((x) = (U_64*) konan::calloc(1, (n) * sizeof(U_64)))) goto OutOfMemory; +#define release(r) if ((r)) konan::free((r)); + +/*NB the Number converter methods are synchronized so it is possible to + *have global data for use by bigIntDigitGenerator */ +#define RM_SIZE 21 +#define STemp_SIZE 22 + +KDouble createDouble (const char *s, KInt e) +{ + /* assumes s is a null terminated string with at least one + * character in it */ + U_64 def[DEFAULT_WIDTH]; + U_64 defBackup[DEFAULT_WIDTH]; + U_64 *f, *fNoOverflow, *g, *tempBackup; + U_32 overflow; + KDouble result; + IDATA index = 1; + int unprocessedDigits = 0; + + f = def; + fNoOverflow = defBackup; + *f = 0; + tempBackup = g = 0; + do + { + if (*s >= '0' && *s <= '9') + { + /* Make a back up of f before appending, so that we can + * back out of it if there is no more room, i.e. index > + * MAX_ACCURACY_WIDTH. + */ + memcpy (fNoOverflow, f, sizeof (U_64) * index); + overflow = + simpleAppendDecimalDigitHighPrecision (f, index, *s - '0'); + if (overflow) + { + f[index++] = overflow; + /* There is an overflow, but there is no more room + * to store the result. We really only need the top 52 + * bits anyway, so we must back out of the overflow, + * and ignore the rest of the string. + */ + if (index >= MAX_ACCURACY_WIDTH) + { + index--; + memcpy (f, fNoOverflow, sizeof (U_64) * index); + break; + } + if (tempBackup) + { + fNoOverflow = tempBackup; + } + } + } + else + index = -1; + } + while (index > 0 && *(++s) != '\0'); + + /* We've broken out of the parse loop either because we've reached + * the end of the string or we've overflowed the maximum accuracy + * limit of a double. If we still have unprocessed digits in the + * given string, then there are three possible results: + * 1. (unprocessed digits + e) == 0, in which case we simply + * convert the existing bits that are already parsed + * 2. (unprocessed digits + e) < 0, in which case we simply + * convert the existing bits that are already parsed along + * with the given e + * 3. (unprocessed digits + e) > 0 indicates that the value is + * simply too big to be stored as a double, so return Infinity + */ + if ((unprocessedDigits = strlen (s)) > 0) + { + e += unprocessedDigits; + if (index > -1) + { + if (e == 0) + result = toDoubleHighPrecision (f, index); + else if (e < 0) + result = createDouble1 (f, index, e); + else + { + DOUBLE_TO_LONGBITS (result) = INFINITE_LONGBITS; + } + } + else + { + LOW_I32_FROM_VAR (result) = -1; + HIGH_I32_FROM_VAR (result) = -1; + } + } + else + { + if (index > -1) + { + if (e == 0) + result = toDoubleHighPrecision (f, index); + else + result = createDouble1 (f, index, e); + } + else + { + LOW_I32_FROM_VAR (result) = -1; + HIGH_I32_FROM_VAR (result) = -1; + } + } + + return result; + +} + +KDouble +createDouble1 (U_64 * f, IDATA length, KInt e) +{ + IDATA numBits; + KDouble result; + +#define APPROX_MIN_MAGNITUDE -309 + +#define APPROX_MAX_MAGNITUDE 309 + + numBits = highestSetBitHighPrecision (f, length) + 1; + numBits -= lowestSetBitHighPrecision (f, length); + if (numBits < 54 && e >= 0 && e < LOG5_OF_TWO_TO_THE_N) + { + return toDoubleHighPrecision (f, length) * tenToTheE (e); + } + else if (numBits < 54 && e < 0 && (-e) < LOG5_OF_TWO_TO_THE_N) + { + return toDoubleHighPrecision (f, length) / tenToTheE (-e); + } + else if (e >= 0 && e < APPROX_MAX_MAGNITUDE) + { + result = toDoubleHighPrecision (f, length) * pow (10.0, (double) e); + } + else if (e >= APPROX_MAX_MAGNITUDE) + { + /* Convert the partial result to make sure that the + * non-exponential part is not zero. This check fixes the case + * where the user enters 0.0e309! */ + result = toDoubleHighPrecision (f, length); + /* Don't go straight to zero as the fact that x*0 = 0 independent of x might + cause the algorithm to produce an incorrect result. Instead try the min value + first and let it fall to zero if need be. */ + + if (result == 0.0) + + DOUBLE_TO_LONGBITS (result) = MINIMUM_LONGBITS; + else + DOUBLE_TO_LONGBITS (result) = INFINITE_LONGBITS; + } + else if (e > APPROX_MIN_MAGNITUDE) + { + result = toDoubleHighPrecision (f, length) / pow (10.0, (double) -e); + } + + if (e <= APPROX_MIN_MAGNITUDE) + { + + result = toDoubleHighPrecision (f, length) * pow (10.0, (double) (e + 52)); + result = result * pow (10.0, (double) -52); + + } + + /* Don't go straight to zero as the fact that x*0 = 0 independent of x might + cause the algorithm to produce an incorrect result. Instead try the min value + first and let it fall to zero if need be. */ + + if (result == 0.0) + + DOUBLE_TO_LONGBITS (result) = MINIMUM_LONGBITS; + + return doubleAlgorithm (f, length, e, result); +} + +U_64 +dblparse_shiftRight64 (U_64 * lp, volatile int mbe) +{ + U_64 b1Value = 0; + U_32 hi = HIGH_U32_FROM_LONG64_PTR (lp); + U_32 lo = LOW_U32_FROM_LONG64_PTR (lp); + int srAmt; + + if (mbe == 0) + return 0; + if (mbe >= 128) + { + HIGH_U32_FROM_LONG64_PTR (lp) = 0; + LOW_U32_FROM_LONG64_PTR (lp) = 0; + return 0; + } + + /* Certain platforms do not handle de-referencing a 64-bit value + * from a pointer on the stack correctly (e.g. MVL-hh/XScale) + * because the pointer may not be properly aligned, so we'll have + * to handle two 32-bit chunks. */ + if (mbe < 32) + { + LOW_U32_FROM_LONG64 (b1Value) = 0; + HIGH_U32_FROM_LONG64 (b1Value) = lo << (32 - mbe); + LOW_U32_FROM_LONG64_PTR (lp) = (hi << (32 - mbe)) | (lo >> mbe); + HIGH_U32_FROM_LONG64_PTR (lp) = hi >> mbe; + } + else if (mbe == 32) + { + LOW_U32_FROM_LONG64 (b1Value) = 0; + HIGH_U32_FROM_LONG64 (b1Value) = lo; + LOW_U32_FROM_LONG64_PTR (lp) = hi; + HIGH_U32_FROM_LONG64_PTR (lp) = 0; + } + else if (mbe < 64) + { + srAmt = mbe - 32; + LOW_U32_FROM_LONG64 (b1Value) = lo << (32 - srAmt); + HIGH_U32_FROM_LONG64 (b1Value) = (hi << (32 - srAmt)) | (lo >> srAmt); + LOW_U32_FROM_LONG64_PTR (lp) = hi >> srAmt; + HIGH_U32_FROM_LONG64_PTR (lp) = 0; + } + else if (mbe == 64) + { + LOW_U32_FROM_LONG64 (b1Value) = lo; + HIGH_U32_FROM_LONG64 (b1Value) = hi; + LOW_U32_FROM_LONG64_PTR (lp) = 0; + HIGH_U32_FROM_LONG64_PTR (lp) = 0; + } + else if (mbe < 96) + { + srAmt = mbe - 64; + b1Value = *lp; + HIGH_U32_FROM_LONG64_PTR (lp) = 0; + LOW_U32_FROM_LONG64_PTR (lp) = 0; + LOW_U32_FROM_LONG64 (b1Value) >>= srAmt; + LOW_U32_FROM_LONG64 (b1Value) |= (hi << (32 - srAmt)); + HIGH_U32_FROM_LONG64 (b1Value) >>= srAmt; + } + else if (mbe == 96) + { + LOW_U32_FROM_LONG64 (b1Value) = hi; + HIGH_U32_FROM_LONG64 (b1Value) = 0; + HIGH_U32_FROM_LONG64_PTR (lp) = 0; + LOW_U32_FROM_LONG64_PTR (lp) = 0; + } + else + { + LOW_U32_FROM_LONG64 (b1Value) = hi >> (mbe - 96); + HIGH_U32_FROM_LONG64 (b1Value) = 0; + HIGH_U32_FROM_LONG64_PTR (lp) = 0; + LOW_U32_FROM_LONG64_PTR (lp) = 0; + } + + return b1Value; +} + +#if defined(WIN32) +/* disable global optimizations on the microsoft compiler for the + * doubleAlgorithm function otherwise it won't compile */ +#pragma optimize("g",off) +#endif + +/* The algorithm for the function doubleAlgorithm() below can be found + * in: + * + * "How to Read Floating-Point Numbers Accurately", William D. + * Clinger, Proceedings of the ACM SIGPLAN '90 Conference on + * Programming Language Design and Implementation, June 20-22, + * 1990, pp. 92-101. + * + * There is a possibility that the function will end up in an endless + * loop if the given approximating floating-point number (a very small + * floating-point whose value is very close to zero) straddles between + * two approximating integer values. We modified the algorithm slightly + * to detect the case where it oscillates back and forth between + * incrementing and decrementing the floating-point approximation. It + * is currently set such that if the oscillation occurs more than twice + * then return the original approximation. + */ +KDouble doubleAlgorithm (U_64 * f, IDATA length, KInt e, KDouble z) +{ + U_64 m; + IDATA k, comparison, comparison2; + U_64 *x, *y, *D, *D2; + IDATA xLength, yLength, DLength, D2Length, decApproxCount, incApproxCount; + //PORT_ACCESS_FROM_ENV (env); + + x = y = D = D2 = 0; + xLength = yLength = DLength = D2Length = 0; + decApproxCount = incApproxCount = 0; + + do + { + m = doubleMantissa (z); + k = doubleExponent (z); + + if (x && x != f) + //jclmem_free_memory (env, x); + release(x); + release (y); + release (D); + release (D2); + + if (e >= 0 && k >= 0) + { + xLength = sizeOfTenToTheE (e) + length; + allocateU64 (x, xLength); + memset (x + length, 0, sizeof (U_64) * (xLength - length)); + memcpy (x, f, sizeof (U_64) * length); + timesTenToTheEHighPrecision (x, xLength, e); + + yLength = (k >> 6) + 2; + allocateU64 (y, yLength); + memset (y + 1, 0, sizeof (U_64) * (yLength - 1)); + *y = m; + simpleShiftLeftHighPrecision (y, yLength, k); + } + else if (e >= 0) + { + xLength = sizeOfTenToTheE (e) + length + ((-k) >> 6) + 1; + allocateU64 (x, xLength); + memset (x + length, 0, sizeof (U_64) * (xLength - length)); + memcpy (x, f, sizeof (U_64) * length); + timesTenToTheEHighPrecision (x, xLength, e); + simpleShiftLeftHighPrecision (x, xLength, -k); + + yLength = 1; + allocateU64 (y, 1); + *y = m; + } + else if (k >= 0) + { + xLength = length; + x = f; + + yLength = sizeOfTenToTheE (-e) + 2 + (k >> 6); + allocateU64 (y, yLength); + memset (y + 1, 0, sizeof (U_64) * (yLength - 1)); + *y = m; + timesTenToTheEHighPrecision (y, yLength, -e); + simpleShiftLeftHighPrecision (y, yLength, k); + } + else + { + xLength = length + ((-k) >> 6) + 1; + allocateU64 (x, xLength); + memset (x + length, 0, sizeof (U_64) * (xLength - length)); + memcpy (x, f, sizeof (U_64) * length); + simpleShiftLeftHighPrecision (x, xLength, -k); + + yLength = sizeOfTenToTheE (-e) + 1; + allocateU64 (y, yLength); + memset (y + 1, 0, sizeof (U_64) * (yLength - 1)); + *y = m; + timesTenToTheEHighPrecision (y, yLength, -e); + } + + comparison = compareHighPrecision (x, xLength, y, yLength); + if (comparison > 0) + { /* x > y */ + DLength = xLength; + allocateU64 (D, DLength); + memcpy (D, x, DLength * sizeof (U_64)); + subtractHighPrecision (D, DLength, y, yLength); + } + else if (comparison) + { /* y > x */ + DLength = yLength; + allocateU64 (D, DLength); + memcpy (D, y, DLength * sizeof (U_64)); + subtractHighPrecision (D, DLength, x, xLength); + } + else + { /* y == x */ + DLength = 1; + allocateU64 (D, 1); + *D = 0; + } + + D2Length = DLength + 1; + allocateU64 (D2, D2Length); + m <<= 1; + multiplyHighPrecision (D, DLength, &m, 1, D2, D2Length); + m >>= 1; + + comparison2 = compareHighPrecision (D2, D2Length, y, yLength); + if (comparison2 < 0) + { + if (comparison < 0 && m == NORMAL_MASK) + { + simpleShiftLeftHighPrecision (D2, D2Length, 1); + if (compareHighPrecision (D2, D2Length, y, yLength) > 0) + { + DECREMENT_DOUBLE (z, decApproxCount, incApproxCount); + } + else + { + break; + } + } + else + { + break; + } + } + else if (comparison2 == 0) + { + if ((LOW_U32_FROM_VAR (m) & 1) == 0) + { + if (comparison < 0 && m == NORMAL_MASK) + { + DECREMENT_DOUBLE (z, decApproxCount, incApproxCount); + } + else + { + break; + } + } + else if (comparison < 0) + { + DECREMENT_DOUBLE (z, decApproxCount, incApproxCount); + break; + } + else + { + INCREMENT_DOUBLE (z, decApproxCount, incApproxCount); + break; + } + } + else if (comparison < 0) + { + DECREMENT_DOUBLE (z, decApproxCount, incApproxCount); + } + else + { + if (DOUBLE_TO_LONGBITS (z) == INFINITE_LONGBITS) + break; + INCREMENT_DOUBLE (z, decApproxCount, incApproxCount); + } + } + while (1); + + if (x && x != f) + //jclmem_free_memory (env, x); + release(x); + release (y); + release (D); + release (D2); + return z; + +OutOfMemory: + if (x && x != f) + //jclmem_free_memory (env, x); + release(x); + release (y); + release (D); + release (D2); + + DOUBLE_TO_LONGBITS (z) = -2; + + return z; +} + +#if defined(WIN32) +#pragma optimize("",on) /*restore optimizations */ +#endif + +KDouble Kotlin_native_FloatingPointParser_parseDoubleImpl (KString s, KInt e) +{ + const KChar* utf16 = CharArrayAddressOfElementAt(s, 0); + KStdString utf8; + utf8.reserve(s->count_); + TRY_CATCH(utf8::utf16to8(utf16, utf16 + s->count_, back_inserter(utf8)), + utf8::unchecked::utf16to8(utf16, utf16 + s->count_, back_inserter(utf8)), + /* Illegal UTF-16 string. */ ThrowNumberFormatException()); + const char *str = utf8.c_str(); + auto dbl = createDouble (str, e); + + if (!ERROR_OCCURED (dbl)) + { + return dbl; + } + else if (LOW_I32_FROM_VAR (dbl) == (I_32) - 1) + { /* NumberFormatException */ + ThrowNumberFormatException(); + } + else + { /* OutOfMemoryError */ + ThrowOutOfMemoryError(); + } + + return 0.0; +} + +/* The algorithm for this particular function can be found in: + * + * Printing Floating-Point Numbers Quickly and Accurately, Robert + * G. Burger, and R. Kent Dybvig, Programming Language Design and + * Implementation (PLDI) 1996, pp.108-116. + * + * The previous implementation of this function combined m+ and m- into + * one single M which caused some inaccuracy of the last digit. The + * particular case below shows this inaccuracy: + * + * System.out.println(new Double((1.234123412431233E107)).toString()); + * System.out.println(new Double((1.2341234124312331E107)).toString()); + * System.out.println(new Double((1.2341234124312332E107)).toString()); + * + * outputs the following: + * + * 1.234123412431233E107 + * 1.234123412431233E107 + * 1.234123412431233E107 + * + * instead of: + * + * 1.234123412431233E107 + * 1.2341234124312331E107 + * 1.2341234124312331E107 + * + */ +void Kotlin_native_NumberConverter_bigIntDigitGeneratorInstImpl (KRef results, + KRef uArray, + KLong f, + KInt e, + KBoolean isDenormalized, + KBoolean mantissaIsZero, + KInt p) +{ + int RLength, SLength, TempLength, mplus_Length, mminus_Length; + int high, low, i; + int k, firstK, U; + int getCount, setCount; + + U_64 R[RM_SIZE], S[STemp_SIZE], mplus[RM_SIZE], mminus[RM_SIZE], Temp[STemp_SIZE]; + + memset (R, 0, RM_SIZE * sizeof (U_64)); + memset (S, 0, STemp_SIZE * sizeof (U_64)); + memset (mplus, 0, RM_SIZE * sizeof (U_64)); + memset (mminus, 0, RM_SIZE * sizeof (U_64)); + memset (Temp, 0, STemp_SIZE * sizeof (U_64)); + + if (e >= 0) + { + *R = f; + *mplus = *mminus = 1; + simpleShiftLeftHighPrecision (mminus, RM_SIZE, e); + if (f != (2 << (p - 1))) + { + simpleShiftLeftHighPrecision (R, RM_SIZE, e + 1); + *S = 2; + /* + * m+ = m+ << e results in 1.0e23 to be printed as + * 0.9999999999999999E23 + * m+ = m+ << e+1 results in 1.0e23 to be printed as + * 1.0e23 (caused too much rounding) + * 470fffffffffffff = 2.0769187434139308E34 + * 4710000000000000 = 2.076918743413931E34 + */ + simpleShiftLeftHighPrecision (mplus, RM_SIZE, e); + } + else + { + simpleShiftLeftHighPrecision (R, RM_SIZE, e + 2); + *S = 4; + simpleShiftLeftHighPrecision (mplus, RM_SIZE, e + 1); + } + } + else + { + if (isDenormalized || (f != (2 << (p - 1)))) + { + *R = f << 1; + *S = 1; + simpleShiftLeftHighPrecision (S, STemp_SIZE, 1 - e); + *mplus = *mminus = 1; + } + else + { + *R = f << 2; + *S = 1; + simpleShiftLeftHighPrecision (S, STemp_SIZE, 2 - e); + *mplus = 2; + *mminus = 1; + } + } + + k = (int) ceil ((e + p - 1) * INV_LOG_OF_TEN_BASE_2 - 1e-10); + + if (k > 0) + { + timesTenToTheEHighPrecision (S, STemp_SIZE, k); + } + else + { + timesTenToTheEHighPrecision (R, RM_SIZE, -k); + timesTenToTheEHighPrecision (mplus, RM_SIZE, -k); + timesTenToTheEHighPrecision (mminus, RM_SIZE, -k); + } + + RLength = mplus_Length = mminus_Length = RM_SIZE; + SLength = TempLength = STemp_SIZE; + + memset (Temp + RM_SIZE, 0, (STemp_SIZE - RM_SIZE) * sizeof (U_64)); + memcpy (Temp, R, RM_SIZE * sizeof (U_64)); + + while (RLength > 1 && R[RLength - 1] == 0) + --RLength; + while (mplus_Length > 1 && mplus[mplus_Length - 1] == 0) + --mplus_Length; + while (mminus_Length > 1 && mminus[mminus_Length - 1] == 0) + --mminus_Length; + while (SLength > 1 && S[SLength - 1] == 0) + --SLength; + TempLength = (RLength > mplus_Length ? RLength : mplus_Length) + 1; + addHighPrecision (Temp, TempLength, mplus, mplus_Length); + + if (compareHighPrecision (Temp, TempLength, S, SLength) >= 0) + { + firstK = k; + } + else + { + firstK = k - 1; + simpleAppendDecimalDigitHighPrecision (R, ++RLength, 0); + simpleAppendDecimalDigitHighPrecision (mplus, ++mplus_Length, 0); + simpleAppendDecimalDigitHighPrecision (mminus, ++mminus_Length, 0); + while (RLength > 1 && R[RLength - 1] == 0) + --RLength; + while (mplus_Length > 1 && mplus[mplus_Length - 1] == 0) + --mplus_Length; + while (mminus_Length > 1 && mminus[mminus_Length - 1] == 0) + --mminus_Length; + } + + getCount = setCount = 0; + do + { + U = 0; + for (i = 3; i >= 0; --i) + { + TempLength = SLength + 1; + Temp[SLength] = 0; + memcpy (Temp, S, SLength * sizeof (U_64)); + simpleShiftLeftHighPrecision (Temp, TempLength, i); + if (compareHighPrecision (R, RLength, Temp, TempLength) >= 0) + { + subtractHighPrecision (R, RLength, Temp, TempLength); + U += 1 << i; + } + } + + low = compareHighPrecision (R, RLength, mminus, mminus_Length) <= 0; + + memset (Temp + RLength, 0, (STemp_SIZE - RLength) * sizeof (U_64)); + memcpy (Temp, R, RLength * sizeof (U_64)); + TempLength = (RLength > mplus_Length ? RLength : mplus_Length) + 1; + addHighPrecision (Temp, TempLength, mplus, mplus_Length); + + high = compareHighPrecision (Temp, TempLength, S, SLength) >= 0; + + if (low || high) + break; + + simpleAppendDecimalDigitHighPrecision (R, ++RLength, 0); + simpleAppendDecimalDigitHighPrecision (mplus, ++mplus_Length, 0); + simpleAppendDecimalDigitHighPrecision (mminus, ++mminus_Length, 0); + while (RLength > 1 && R[RLength - 1] == 0) + --RLength; + while (mplus_Length > 1 && mplus[mplus_Length - 1] == 0) + --mplus_Length; + while (mminus_Length > 1 && mminus[mminus_Length - 1] == 0) + --mminus_Length; + Kotlin_IntArray_set(uArray, setCount++, U); + //uArray[setCount++] = U; + } + while (1); + + simpleShiftLeftHighPrecision (R, ++RLength, 1); + if (low && !high) + Kotlin_IntArray_set(uArray, setCount++, U); + //uArray[setCount++] = U; + else if (high && !low) + Kotlin_IntArray_set(uArray, setCount++, U + 1); + //uArray[setCount++] = U + 1; + else if (compareHighPrecision (R, RLength, S, SLength) < 0) + Kotlin_IntArray_set(uArray, setCount++, U); + //uArray[setCount++] = U; + else + Kotlin_IntArray_set(uArray, setCount++, U + 1); + //uArray[setCount++] = U + 1; + + Kotlin_IntArray_set(results, 0, setCount); +// fid = (*env)->GetFieldID (env, clazz, "setCount", "I"); +// (*env)->SetIntField (env, inst, fid, setCount); + + Kotlin_IntArray_set(results, 1, getCount); +// fid = (*env)->GetFieldID (env, clazz, "getCount", "I"); +// (*env)->SetIntField (env, inst, fid, getCount); + + Kotlin_IntArray_set(results, 2, firstK); +// fid = (*env)->GetFieldID (env, clazz, "firstK", "I"); +// (*env)->SetIntField (env, inst, fid, firstK); + +} diff --git a/kotlin-native/runtime/src/main/cpp/dtoa/fltconst.h b/kotlin-native/runtime/src/main/cpp/dtoa/fltconst.h new file mode 100644 index 00000000000..6ab4c389191 --- /dev/null +++ b/kotlin-native/runtime/src/main/cpp/dtoa/fltconst.h @@ -0,0 +1,160 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#if !defined(fltconst_h) +#define fltconst_h + +#include "hycomp.h" +/* IEEE floats consist of: sign bit, exponent field, significand field + single: 31 = sign bit, 30..23 = exponent (8 bits), 22..0 = significand (23 bits) + double: 63 = sign bit, 62..52 = exponent (11 bits), 51..0 = significand (52 bits) + inf == (all exponent bits set) and (all mantissa bits clear) + nan == (all exponent bits set) and (at least one mantissa bit set) + finite == (at least one exponent bit clear) + zero == (all exponent bits clear) and (all mantissa bits clear) + denormal == (all exponent bits clear) and (at least one mantissa bit set) + positive == sign bit clear + negative == sign bit set +*/ +#define MAX_U32_DOUBLE (ESDOUBLE) (4294967296.0) /* 2^32 */ +#define MAX_U32_SINGLE (ESSINGLE) (4294967296.0) /* 2^32 */ +#define HY_POS_PI (ESDOUBLE)(3.141592653589793) + +#ifdef HY_LITTLE_ENDIAN +#ifdef HY_PLATFORM_DOUBLE_ORDER +#define DOUBLE_LO_OFFSET 0 +#define DOUBLE_HI_OFFSET 1 +#else +#define DOUBLE_LO_OFFSET 1 +#define DOUBLE_HI_OFFSET 0 +#endif +#define LONG_LO_OFFSET 0 +#define LONG_HI_OFFSET 1 +#else +#ifdef HY_PLATFORM_DOUBLE_ORDER +#define DOUBLE_LO_OFFSET 1 +#define DOUBLE_HI_OFFSET 0 +#else +#define DOUBLE_LO_OFFSET 0 +#define DOUBLE_HI_OFFSET 1 +#endif +#define LONG_LO_OFFSET 1 +#define LONG_HI_OFFSET 0 +#endif + +#define RETURN_FINITE 0 +#define RETURN_NAN 1 +#define RETURN_POS_INF 2 +#define RETURN_NEG_INF 3 +#define DOUBLE_SIGN_MASK_HI 0x80000000 +#define DOUBLE_EXPONENT_MASK_HI 0x7FF00000 +#define DOUBLE_MANTISSA_MASK_LO 0xFFFFFFFF +#define DOUBLE_MANTISSA_MASK_HI 0x000FFFFF +#define SINGLE_SIGN_MASK 0x80000000 +#define SINGLE_EXPONENT_MASK 0x7F800000 +#define SINGLE_MANTISSA_MASK 0x007FFFFF +#define SINGLE_NAN_BITS (SINGLE_EXPONENT_MASK | 0x00400000) +typedef union u64u32dbl_tag { + U_64 u64val; + U_32 u32val[2]; + I_32 i32val[2]; + double dval; +} U64U32DBL; +/* Replace P_FLOAT_HI and P_FLOAT_LOW */ +/* These macros are used to access the high and low 32-bit parts of a double (64-bit) value. */ +#define LOW_U32_FROM_DBL_PTR(dblptr) (((U64U32DBL *)(dblptr))->u32val[DOUBLE_LO_OFFSET]) +#define HIGH_U32_FROM_DBL_PTR(dblptr) (((U64U32DBL *)(dblptr))->u32val[DOUBLE_HI_OFFSET]) +#define LOW_I32_FROM_DBL_PTR(dblptr) (((U64U32DBL *)(dblptr))->i32val[DOUBLE_LO_OFFSET]) +#define HIGH_I32_FROM_DBL_PTR(dblptr) (((U64U32DBL *)(dblptr))->i32val[DOUBLE_HI_OFFSET]) +#define LOW_U32_FROM_DBL(dbl) LOW_U32_FROM_DBL_PTR(&(dbl)) +#define HIGH_U32_FROM_DBL(dbl) HIGH_U32_FROM_DBL_PTR(&(dbl)) +#define LOW_I32_FROM_DBL(dbl) LOW_I32_FROM_DBL_PTR(&(dbl)) +#define HIGH_I32_FROM_DBL(dbl) HIGH_I32_FROM_DBL_PTR(&(dbl)) +#define LOW_U32_FROM_LONG64_PTR(long64ptr) (((U64U32DBL *)(long64ptr))->u32val[LONG_LO_OFFSET]) +#define HIGH_U32_FROM_LONG64_PTR(long64ptr) (((U64U32DBL *)(long64ptr))->u32val[LONG_HI_OFFSET]) +#define LOW_I32_FROM_LONG64_PTR(long64ptr) (((U64U32DBL *)(long64ptr))->i32val[LONG_LO_OFFSET]) +#define HIGH_I32_FROM_LONG64_PTR(long64ptr) (((U64U32DBL *)(long64ptr))->i32val[LONG_HI_OFFSET]) +#define LOW_U32_FROM_LONG64(long64) LOW_U32_FROM_LONG64_PTR(&(long64)) +#define HIGH_U32_FROM_LONG64(long64) HIGH_U32_FROM_LONG64_PTR(&(long64)) +#define LOW_I32_FROM_LONG64(long64) LOW_I32_FROM_LONG64_PTR(&(long64)) +#define HIGH_I32_FROM_LONG64(long64) HIGH_I32_FROM_LONG64_PTR(&(long64)) +#define IS_ZERO_DBL_PTR(dblptr) ((LOW_U32_FROM_DBL_PTR(dblptr) == 0) && ((HIGH_U32_FROM_DBL_PTR(dblptr) == 0) || (HIGH_U32_FROM_DBL_PTR(dblptr) == DOUBLE_SIGN_MASK_HI))) +#define IS_ONE_DBL_PTR(dblptr) ((HIGH_U32_FROM_DBL_PTR(dblptr) == 0x3ff00000 || HIGH_U32_FROM_DBL_PTR(dblptr) == 0xbff00000) && (LOW_U32_FROM_DBL_PTR(dblptr) == 0)) +#define IS_NAN_DBL_PTR(dblptr) (((HIGH_U32_FROM_DBL_PTR(dblptr) & DOUBLE_EXPONENT_MASK_HI) == DOUBLE_EXPONENT_MASK_HI) && (LOW_U32_FROM_DBL_PTR(dblptr) | (HIGH_U32_FROM_DBL_PTR(dblptr) & DOUBLE_MANTISSA_MASK_HI))) +#define IS_INF_DBL_PTR(dblptr) (((HIGH_U32_FROM_DBL_PTR(dblptr) & (DOUBLE_EXPONENT_MASK_HI|DOUBLE_MANTISSA_MASK_HI)) == DOUBLE_EXPONENT_MASK_HI) && (LOW_U32_FROM_DBL_PTR(dblptr) == 0)) +#define IS_DENORMAL_DBL_PTR(dblptr) (((HIGH_U32_FROM_DBL_PTR(dblptr) & DOUBLE_EXPONENT_MASK_HI) == 0) && ((HIGH_U32_FROM_DBL_PTR(dblptr) & DOUBLE_MANTISSA_MASK_HI) != 0 || (LOW_U32_FROM_DBL_PTR(dblptr) != 0))) +#define IS_FINITE_DBL_PTR(dblptr) ((HIGH_U32_FROM_DBL_PTR(dblptr) & DOUBLE_EXPONENT_MASK_HI) < DOUBLE_EXPONENT_MASK_HI) +#define IS_POSITIVE_DBL_PTR(dblptr) ((HIGH_U32_FROM_DBL_PTR(dblptr) & DOUBLE_SIGN_MASK_HI) == 0) +#define IS_NEGATIVE_DBL_PTR(dblptr) ((HIGH_U32_FROM_DBL_PTR(dblptr) & DOUBLE_SIGN_MASK_HI) != 0) +#define IS_NEGATIVE_MAX_DBL_PTR(dblptr) ((HIGH_U32_FROM_DBL_PTR(dblptr) == 0xFFEFFFFF) && (LOW_U32_FROM_DBL_PTR(dblptr) == 0xFFFFFFFF)) +#define IS_ZERO_DBL(dbl) IS_ZERO_DBL_PTR(&(dbl)) +#define IS_ONE_DBL(dbl) IS_ONE_DBL_PTR(&(dbl)) +#define IS_NAN_DBL(dbl) IS_NAN_DBL_PTR(&(dbl)) +#define IS_INF_DBL(dbl) IS_INF_DBL_PTR(&(dbl)) +#define IS_DENORMAL_DBL(dbl) IS_DENORMAL_DBL_PTR(&(dbl)) +#define IS_FINITE_DBL(dbl) IS_FINITE_DBL_PTR(&(dbl)) +#define IS_POSITIVE_DBL(dbl) IS_POSITIVE_DBL_PTR(&(dbl)) +#define IS_NEGATIVE_DBL(dbl) IS_NEGATIVE_DBL_PTR(&(dbl)) +#define IS_NEGATIVE_MAX_DBL(dbl) IS_NEGATIVE_MAX_DBL_PTR(&(dbl)) +#define IS_ZERO_SNGL_PTR(fltptr) ((*U32P((fltptr)) & (U_32)~SINGLE_SIGN_MASK) == (U_32)0) +#define IS_ONE_SNGL_PTR(fltptr) ((*U32P((fltptr)) == 0x3f800000) || (*U32P((fltptr)) == 0xbf800000)) +#define IS_NAN_SNGL_PTR(fltptr) ((*U32P((fltptr)) & (U_32)~SINGLE_SIGN_MASK) > (U_32)SINGLE_EXPONENT_MASK) +#define IS_INF_SNGL_PTR(fltptr) ((*U32P((fltptr)) & (U_32)~SINGLE_SIGN_MASK) == (U_32)SINGLE_EXPONENT_MASK) +#define IS_DENORMAL_SNGL_PTR(fltptr) (((*U32P((fltptr)) & (U_32)~SINGLE_SIGN_MASK)-(U_32)1) < (U_32)SINGLE_MANTISSA_MASK) +#define IS_FINITE_SNGL_PTR(fltptr) ((*U32P((fltptr)) & (U_32)~SINGLE_SIGN_MASK) < (U_32)SINGLE_EXPONENT_MASK) +#define IS_POSITIVE_SNGL_PTR(fltptr) ((*U32P((fltptr)) & (U_32)SINGLE_SIGN_MASK) == (U_32)0) +#define IS_NEGATIVE_SNGL_PTR(fltptr) ((*U32P((fltptr)) & (U_32)SINGLE_SIGN_MASK) != (U_32)0) +#define IS_ZERO_SNGL(flt) IS_ZERO_SNGL_PTR(&(flt)) +#define IS_ONE_SNGL(flt) IS_ONE_SNGL_PTR(&(flt)) +#define IS_NAN_SNGL(flt) IS_NAN_SNGL_PTR(&(flt)) +#define IS_INF_SNGL(flt) IS_INF_SNGL_PTR(&(flt)) +#define IS_DENORMAL_SNGL(flt) IS_DENORMAL_SNGL_PTR(&(flt)) +#define IS_FINITE_SNGL(flt) IS_FINITE_SNGL_PTR(&(flt)) +#define IS_POSITIVE_SNGL(flt) IS_POSITIVE_SNGL_PTR(&(flt)) +#define IS_NEGATIVE_SNGL(flt) IS_NEGATIVE_SNGL_PTR(&(flt)) +#define SET_NAN_DBL_PTR(dblptr) HIGH_U32_FROM_DBL_PTR(dblptr) = (DOUBLE_EXPONENT_MASK_HI | 0x00080000); LOW_U32_FROM_DBL_PTR(dblptr) = 0 +#define SET_PZERO_DBL_PTR(dblptr) HIGH_U32_FROM_DBL_PTR(dblptr) = 0; LOW_U32_FROM_DBL_PTR(dblptr) = 0 +#define SET_NZERO_DBL_PTR(dblptr) HIGH_U32_FROM_DBL_PTR(dblptr) = DOUBLE_SIGN_MASK_HI; LOW_U32_FROM_DBL_PTR(dblptr) = 0 +#define SET_PINF_DBL_PTR(dblptr) HIGH_U32_FROM_DBL_PTR(dblptr) = DOUBLE_EXPONENT_MASK_HI; LOW_U32_FROM_DBL_PTR(dblptr) = 0 +#define SET_NINF_DBL_PTR(dblptr) HIGH_U32_FROM_DBL_PTR(dblptr) = (DOUBLE_EXPONENT_MASK_HI | DOUBLE_SIGN_MASK_HI); LOW_U32_FROM_DBL_PTR(dblptr) = 0 +#define SET_NAN_SNGL_PTR(fltptr) *U32P((fltptr)) = ((U_32)SINGLE_NAN_BITS) +#define SET_PZERO_SNGL_PTR(fltptr) *U32P((fltptr)) = 0 +#define SET_NZERO_SNGL_PTR(fltptr) *U32P((fltptr)) = SINGLE_SIGN_MASK +#define SET_PINF_SNGL_PTR(fltptr) *U32P((fltptr)) = SINGLE_EXPONENT_MASK +#define SET_NINF_SNGL_PTR(fltptr) *U32P((fltptr)) = (SINGLE_EXPONENT_MASK | SINGLE_SIGN_MASK) + +#if defined(HY_WORD64) + #define PTR_DOUBLE_VALUE(dstPtr, aDoublePtr) ((U64U32DBL *)(aDoublePtr))->u64val = ((U64U32DBL *)(dstPtr))->u64val + #define PTR_DOUBLE_STORE(dstPtr, aDoublePtr) ((U64U32DBL *)(dstPtr))->u64val = ((U64U32DBL *)(aDoublePtr))->u64val + #define STORE_LONG(dstPtr, hi, lo) ((U64U32DBL *)(dstPtr))->u64val = (((U_64)(hi)) << 32) | (lo) +#else + /* on some platforms (HP720) we cannot reference an unaligned float. Build them by hand, one U_32 at a time. */ + #if defined(ATOMIC_FLOAT_ACCESS) + #define PTR_DOUBLE_STORE(dstPtr, aDoublePtr) HIGH_U32_FROM_DBL_PTR(dstPtr) = HIGH_U32_FROM_DBL_PTR(aDoublePtr); LOW_U32_FROM_DBL_PTR(dstPtr) = LOW_U32_FROM_DBL_PTR(aDoublePtr) + #define PTR_DOUBLE_VALUE(dstPtr, aDoublePtr) HIGH_U32_FROM_DBL_PTR(aDoublePtr) = HIGH_U32_FROM_DBL_PTR(dstPtr); LOW_U32_FROM_DBL_PTR(aDoublePtr) = LOW_U32_FROM_DBL_PTR(dstPtr) + #else + #define PTR_DOUBLE_STORE(dstPtr, aDoublePtr) (*(dstPtr) = *(aDoublePtr)) + #define PTR_DOUBLE_VALUE(dstPtr, aDoublePtr) (*(aDoublePtr) = *(dstPtr)) + #endif + + #define STORE_LONG(dstPtr, hi, lo) HIGH_U32_FROM_LONG64_PTR(dstPtr) = (hi); LOW_U32_FROM_LONG64_PTR(dstPtr) = (lo) +#endif /* HY_WORD64 */ + +#define PTR_SINGLE_VALUE(dstPtr, aSinglePtr) (*U32P(aSinglePtr) = *U32P(dstPtr)) +#define PTR_SINGLE_STORE(dstPtr, aSinglePtr) *((U_32 *)(dstPtr)) = (*U32P(aSinglePtr)) + +#endif /* fltconst_h */ diff --git a/kotlin-native/runtime/src/main/cpp/dtoa/fltparse.cpp b/kotlin-native/runtime/src/main/cpp/dtoa/fltparse.cpp new file mode 100644 index 00000000000..e27da3758ce --- /dev/null +++ b/kotlin-native/runtime/src/main/cpp/dtoa/fltparse.cpp @@ -0,0 +1,563 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include +#include + +#include "cbigint.h" +#include "../Exceptions.h" +#include "../KString.h" +#include "../Natives.h" +#include "../utf8.h" + +#if defined(LINUX) || defined(FREEBSD) || defined(MACOSX) || defined(ZOS) || defined(AIX) +#define USE_LL +#endif + +#ifdef HY_LITTLE_ENDIAN +#define LOW_I32_FROM_PTR(ptr64) (*(I_32 *) (ptr64)) +#else +#define LOW_I32_FROM_PTR(ptr64) (*(((I_32 *) (ptr64)) + 1)) +#endif + +#define MAX_ACCURACY_WIDTH 8 + +#define DEFAULT_WIDTH MAX_ACCURACY_WIDTH + +extern "C" KFloat Kotlin_native_int_bits_to_float(KInt x) { + union { + int32_t x; + float f; + } tmp; + tmp.x = x; + return tmp.f; +} + +KFloat createFloat1 (U_64 * f, IDATA length, KInt e); +KFloat floatAlgorithm (U_64 * f, IDATA length, KInt e, KFloat z); +KFloat createFloat (const char *s, KInt e); + +static const U_32 tens[] = { + 0x3f800000, + 0x41200000, + 0x42c80000, + 0x447a0000, + 0x461c4000, + 0x47c35000, + 0x49742400, + 0x4b189680, + 0x4cbebc20, + 0x4e6e6b28, + 0x501502f9 /* 10 ^ 10 in float */ +}; + +#define tenToTheE(e) (*((KFloat *) (tens + (e)))) + +#define LOG5_OF_TWO_TO_THE_N 11 + +#define sizeOfTenToTheE(e) (((e) / 19) + 1) + +#define INFINITE_INTBITS (0x7F800000) +#define MINIMUM_INTBITS (1) + +#define MANTISSA_MASK (0x007FFFFF) +#define EXPONENT_MASK (0x7F800000) +#define NORMAL_MASK (0x00800000) +#define FLOAT_TO_INTBITS(flt) (*((U_32 *)(&flt))) + +/* Keep a count of the number of times we decrement and increment to + * approximate the double, and attempt to detect the case where we + * could potentially toggle back and forth between decrementing and + * incrementing. It is possible for us to be stuck in the loop when + * incrementing by one or decrementing by one may exceed or stay below + * the value that we are looking for. In this case, just break out of + * the loop if we toggle between incrementing and decrementing for more + * than twice. + */ +#define INCREMENT_FLOAT(_x, _decCount, _incCount) \ + { \ + ++FLOAT_TO_INTBITS(_x); \ + _incCount++; \ + if( (_incCount > 2) && (_decCount > 2) ) { \ + if( _decCount > _incCount ) { \ + FLOAT_TO_INTBITS(_x) += _decCount - _incCount; \ + } else if( _incCount > _decCount ) { \ + FLOAT_TO_INTBITS(_x) -= _incCount - _decCount; \ + } \ + break; \ + } \ + } +#define DECREMENT_FLOAT(_x, _decCount, _incCount) \ + { \ + --FLOAT_TO_INTBITS(_x); \ + _decCount++; \ + if( (_incCount > 2) && (_decCount > 2) ) { \ + if( _decCount > _incCount ) { \ + FLOAT_TO_INTBITS(_x) += _decCount - _incCount; \ + } else if( _incCount > _decCount ) { \ + FLOAT_TO_INTBITS(_x) -= _incCount - _decCount; \ + } \ + break; \ + } \ + } + +#define allocateU64(x, n) if (!((x) = (U_64*) konan::calloc(1, (n) * sizeof(U_64)))) goto OutOfMemory; +#define release(r) if ((r)) konan::free((r)); + +KFloat createFloat(const char *s, KInt e) { + /* assumes s is a null terminated string with at least one + * character in it */ + U_64 def[DEFAULT_WIDTH]; + U_64 defBackup[DEFAULT_WIDTH]; + U_64 *f, *fNoOverflow, *g, *tempBackup; + U_32 overflow; + KFloat result; + IDATA index = 1; + int unprocessedDigits = 0; + + f = def; + fNoOverflow = defBackup; + *f = 0; + tempBackup = g = 0; + do + { + if (*s >= '0' && *s <= '9') + { + /* Make a back up of f before appending, so that we can + * back out of it if there is no more room, i.e. index > + * MAX_ACCURACY_WIDTH. + */ + memcpy (fNoOverflow, f, sizeof (U_64) * index); + overflow = + simpleAppendDecimalDigitHighPrecision (f, index, *s - '0'); + if (overflow) + { + + f[index++] = overflow; + /* There is an overflow, but there is no more room + * to store the result. We really only need the top 52 + * bits anyway, so we must back out of the overflow, + * and ignore the rest of the string. + */ + if (index >= MAX_ACCURACY_WIDTH) + { + index--; + memcpy (f, fNoOverflow, sizeof (U_64) * index); + break; + } + if (tempBackup) + { + fNoOverflow = tempBackup; + } + } + } + else + index = -1; + } + while (index > 0 && *(++s) != '\0'); + + /* We've broken out of the parse loop either because we've reached + * the end of the string or we've overflowed the maximum accuracy + * limit of a double. If we still have unprocessed digits in the + * given string, then there are three possible results: + * 1. (unprocessed digits + e) == 0, in which case we simply + * convert the existing bits that are already parsed + * 2. (unprocessed digits + e) < 0, in which case we simply + * convert the existing bits that are already parsed along + * with the given e + * 3. (unprocessed digits + e) > 0 indicates that the value is + * simply too big to be stored as a double, so return Infinity + */ + if ((unprocessedDigits = strlen (s)) > 0) + { + e += unprocessedDigits; + if (index > -1) + { + if (e <= 0) + { + result = createFloat1 (f, index, e); + } + else + { + FLOAT_TO_INTBITS (result) = INFINITE_INTBITS; + } + } + else + { + result = *(KFloat *) & index; + } + } + else + { + if (index > -1) + { + result = createFloat1 (f, index, e); + } + else + { + result = *(KFloat *) & index; + } + } + + return result; + +} + +KFloat +createFloat1 (U_64 * f, IDATA length, KInt e) +{ + IDATA numBits; + KDouble dresult; + KFloat result; + + numBits = highestSetBitHighPrecision (f, length) + 1; + if (numBits < 25 && e >= 0 && e < LOG5_OF_TWO_TO_THE_N) + { + return ((KFloat) LOW_I32_FROM_PTR (f)) * tenToTheE (e); + } + else if (numBits < 25 && e < 0 && (-e) < LOG5_OF_TWO_TO_THE_N) + { + return ((KFloat) LOW_I32_FROM_PTR (f)) / tenToTheE (-e); + } + else if (e >= 0 && e < 39) + { + result = (KFloat) (toDoubleHighPrecision (f, length) * pow (10.0, (double) e)); + } + else if (e >= 39) + { + /* Convert the partial result to make sure that the + * non-exponential part is not zero. This check fixes the case + * where the user enters 0.0e309! */ + result = (KFloat) toDoubleHighPrecision (f, length); + + if (result == 0.0) + + FLOAT_TO_INTBITS (result) = MINIMUM_INTBITS; + else + FLOAT_TO_INTBITS (result) = INFINITE_INTBITS; + } + else if (e > -309) + { + int dexp; + U_32 fmant, fovfl; + U_64 dmant; + dresult = toDoubleHighPrecision (f, length) / pow (10.0, (double) -e); + if (IS_DENORMAL_DBL (dresult)) + { + FLOAT_TO_INTBITS (result) = 0; + return result; + } + dexp = doubleExponent (dresult) + 51; + dmant = doubleMantissa (dresult); + /* Is it too small to be represented by a single-precision + * float? */ + if (dexp <= -155) + { + FLOAT_TO_INTBITS (result) = 0; + return result; + } + /* Is it a denormalized single-precision float? */ + if ((dexp <= -127) && (dexp > -155)) + { + /* Only interested in 24 msb bits of the 53-bit double mantissa */ + fmant = (U_32) (dmant >> 29); + fovfl = ((U_32) (dmant & 0x1FFFFFFF)) << 3; + while ((dexp < -127) && ((fmant | fovfl) != 0)) + { + if ((fmant & 1) != 0) + { + fovfl |= 0x80000000; + } + fovfl >>= 1; + fmant >>= 1; + dexp++; + } + if ((fovfl & 0x80000000) != 0) + { + if ((fovfl & 0x7FFFFFFC) != 0) + { + fmant++; + } + else if ((fmant & 1) != 0) + { + fmant++; + } + } + else if ((fovfl & 0x40000000) != 0) + { + if ((fovfl & 0x3FFFFFFC) != 0) + { + fmant++; + } + } + FLOAT_TO_INTBITS (result) = fmant; + } + else + { + result = (KFloat) dresult; + } + } + + /* Don't go straight to zero as the fact that x*0 = 0 independent + * of x might cause the algorithm to produce an incorrect result. + * Instead try the min value first and let it fall to zero if need + * be. + */ + if (e <= -309 || FLOAT_TO_INTBITS (result) == 0) + FLOAT_TO_INTBITS (result) = MINIMUM_INTBITS; + + return floatAlgorithm (f, length, e, result); +} + +#if defined(WIN32) +/* disable global optimizations on the microsoft compiler for the + * floatAlgorithm function otherwise it won't properly compile */ +#pragma optimize("g",off) +#endif + +/* The algorithm for the function floatAlgorithm() below can be found + * in: + * + * "How to Read Floating-Point Numbers Accurately", William D. + * Clinger, Proceedings of the ACM SIGPLAN '90 Conference on + * Programming Language Design and Implementation, June 20-22, + * 1990, pp. 92-101. + * + * There is a possibility that the function will end up in an endless + * loop if the given approximating floating-point number (a very small + * floating-point whose value is very close to zero) straddles between + * two approximating integer values. We modified the algorithm slightly + * to detect the case where it oscillates back and forth between + * incrementing and decrementing the floating-point approximation. It + * is currently set such that if the oscillation occurs more than twice + * then return the original approximation. + */ +KFloat +floatAlgorithm (U_64 * f, IDATA length, KInt e, KFloat z) +{ + U_64 m; + IDATA k, comparison, comparison2; + U_64 *x, *y, *D, *D2; + IDATA xLength, yLength, DLength, D2Length; + IDATA decApproxCount, incApproxCount; + //PORT_ACCESS_FROM_ENV (env); + + x = y = D = D2 = 0; + xLength = yLength = DLength = D2Length = 0; + decApproxCount = incApproxCount = 0; + + do + { + m = floatMantissa (z); + k = floatExponent (z); + + if (x && x != f) + //jclmem_free_memory (env, x); + release(x); + release (y); + release (D); + release (D2); + + if (e >= 0 && k >= 0) + { + xLength = sizeOfTenToTheE (e) + length; + allocateU64 (x, xLength); + memset (x + length, 0, sizeof (U_64) * (xLength - length)); + memcpy (x, f, sizeof (U_64) * length); + timesTenToTheEHighPrecision (x, xLength, e); + + yLength = (k >> 6) + 2; + allocateU64 (y, yLength); + memset (y + 1, 0, sizeof (U_64) * (yLength - 1)); + *y = m; + simpleShiftLeftHighPrecision (y, yLength, k); + } + else if (e >= 0) + { + xLength = sizeOfTenToTheE (e) + length + ((-k) >> 6) + 1; + allocateU64 (x, xLength); + memset (x + length, 0, sizeof (U_64) * (xLength - length)); + memcpy (x, f, sizeof (U_64) * length); + timesTenToTheEHighPrecision (x, xLength, e); + simpleShiftLeftHighPrecision (x, xLength, -k); + + yLength = 1; + allocateU64 (y, 1); + *y = m; + } + else if (k >= 0) + { + xLength = length; + x = f; + + yLength = sizeOfTenToTheE (-e) + 2 + (k >> 6); + allocateU64 (y, yLength); + memset (y + 1, 0, sizeof (U_64) * (yLength - 1)); + *y = m; + timesTenToTheEHighPrecision (y, yLength, -e); + simpleShiftLeftHighPrecision (y, yLength, k); + } + else + { + xLength = length + ((-k) >> 6) + 1; + allocateU64 (x, xLength); + memset (x + length, 0, sizeof (U_64) * (xLength - length)); + memcpy (x, f, sizeof (U_64) * length); + simpleShiftLeftHighPrecision (x, xLength, -k); + + yLength = sizeOfTenToTheE (-e) + 1; + allocateU64 (y, yLength); + memset (y + 1, 0, sizeof (U_64) * (yLength - 1)); + *y = m; + timesTenToTheEHighPrecision (y, yLength, -e); + } + + comparison = compareHighPrecision (x, xLength, y, yLength); + if (comparison > 0) + { /* x > y */ + DLength = xLength; + allocateU64 (D, DLength); + memcpy (D, x, DLength * sizeof (U_64)); + subtractHighPrecision (D, DLength, y, yLength); + } + else if (comparison) + { /* y > x */ + DLength = yLength; + allocateU64 (D, DLength); + memcpy (D, y, DLength * sizeof (U_64)); + subtractHighPrecision (D, DLength, x, xLength); + } + else + { /* y == x */ + DLength = 1; + allocateU64 (D, 1); + *D = 0; + } + + D2Length = DLength + 1; + allocateU64 (D2, D2Length); + m <<= 1; + multiplyHighPrecision (D, DLength, &m, 1, D2, D2Length); + m >>= 1; + + comparison2 = compareHighPrecision (D2, D2Length, y, yLength); + if (comparison2 < 0) + { + if (comparison < 0 && m == NORMAL_MASK) + { + simpleShiftLeftHighPrecision (D2, D2Length, 1); + if (compareHighPrecision (D2, D2Length, y, yLength) > 0) + { + DECREMENT_FLOAT (z, decApproxCount, incApproxCount); + } + else + { + break; + } + } + else + { + break; + } + } + else if (comparison2 == 0) + { + if ((m & 1) == 0) + { + if (comparison < 0 && m == NORMAL_MASK) + { + DECREMENT_FLOAT (z, decApproxCount, incApproxCount); + } + else + { + break; + } + } + else if (comparison < 0) + { + DECREMENT_FLOAT (z, decApproxCount, incApproxCount); + break; + } + else + { + INCREMENT_FLOAT (z, decApproxCount, incApproxCount); + break; + } + } + else if (comparison < 0) + { + DECREMENT_FLOAT (z, decApproxCount, incApproxCount); + } + else + { + if (FLOAT_TO_INTBITS (z) == EXPONENT_MASK) + break; + INCREMENT_FLOAT (z, decApproxCount, incApproxCount); + } + } + while (1); + + if (x && x != f) + //jclmem_free_memory (env, x); + release(x); + release (y); + release (D); + release (D2); + return z; + +OutOfMemory: + if (x && x != f) + //jclmem_free_memory (env, x); + release(x); + release (y); + release (D); + release (D2); + + FLOAT_TO_INTBITS (z) = -2; + + return z; +} + +#if defined(WIN32) +#pragma optimize("",on) /*restore optimizations */ +#endif + +extern "C" KFloat +Kotlin_native_FloatingPointParser_parseFloatImpl(KString s, KInt e) +{ + const KChar* utf16 = CharArrayAddressOfElementAt(s, 0); + KStdString utf8; + utf8.reserve(s->count_); + TRY_CATCH(utf8::utf16to8(utf16, utf16 + s->count_, back_inserter(utf8)), + utf8::unchecked::utf16to8(utf16, utf16 + s->count_, back_inserter(utf8)), + /* Illegal UTF-16 string. */ ThrowNumberFormatException()); + const char *str = utf8.c_str(); + auto flt = createFloat(str, e); + + if (((I_32) FLOAT_TO_INTBITS (flt)) >= 0) { + return flt; + } else if (((I_32) FLOAT_TO_INTBITS (flt)) == (I_32) - 1) { + /* NumberFormatException */ + ThrowNumberFormatException(); + } else { + /* OutOfMemoryError */ + ThrowOutOfMemoryError(); + } + + return 0.0f; +} diff --git a/kotlin-native/runtime/src/main/cpp/dtoa/hycomp.h b/kotlin-native/runtime/src/main/cpp/dtoa/hycomp.h new file mode 100644 index 00000000000..9d41319a6a9 --- /dev/null +++ b/kotlin-native/runtime/src/main/cpp/dtoa/hycomp.h @@ -0,0 +1,523 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#if !defined(hycomp_h) +#define hycomp_h +// TODO: Move to settings +#define MACOSX +/** + * USE_PROTOTYPES: Use full ANSI prototypes. + * + * CLOCK_PRIMS: We want the timer/clock prims to be used + * + * LITTLE_ENDIAN: This is for the intel machines or other + * little endian processors. Defaults to big endian. + * + * NO_LVALUE_CASTING: This is for compilers that don't like the left side + * of assigns to be cast. It hacks around to do the + * right thing. + * + * ATOMIC_FLOAT_ACCESS: So that float operations will work. + * + * LINKED_USER_PRIMITIVES: Indicates that user primitives are statically linked + * with the VM executeable. + * + * OLD_SPACE_SIZE_DIFF: The 68k uses a different amount of old space. + * This "legitimizes" the change. + * + * SIMPLE_SIGNAL: For machines that don't use real signals in C. + * (eg: PC, 68k) + * + * OS_NAME_LOOKUP: Use nlist to lookup user primitive addresses. + * + * VMCALL: Tag for all functions called by the VM. + * + * VMAPICALL: Tag for all functions called via the PlatformFunction + * callWith: mechanism. + * + * SYS_FLOAT: For some math functions where extended types (80 or 96 bits) are returned + * Most platforms return as a double + * + * FLOAT_EXTENDED: If defined, the type name for extended precision floats. + * + * PLATFORM_IS_ASCII: Must be defined if the platform is ASCII + * + * EXE_EXTENSION_CHAR: the executable has a delimiter that we want to stop at as part of argv[0]. + */ + + /** + * By default order doubles in the native (that is big/little endian) ordering. + */ + +#define HY_PLATFORM_DOUBLE_ORDER + +/** + * Define common types: + *
    + *
  • U_32 / I_32 - unsigned/signed 32 bits
  • + *
  • U_16 / I_16 - unsigned/signed 16 bits
  • + *
  • U_8 / I_8 - unsigned/signed 8 bits (bytes -- not to be + * confused with char)
  • + *
+ */ + +typedef int I_32; +typedef short I_16; +typedef signed char I_8; /* chars can be unsigned */ +typedef unsigned int U_32; +typedef unsigned short U_16; +typedef unsigned char U_8; + +/** + * Define platform specific types: + *
    + *
  • U_64 / I_64 - unsigned/signed 64 bits
  • + *
+ */ + +#if defined(LINUX) || defined(FREEBSD) || defined(AIX) || defined(MACOSX) + +#define DATA_TYPES_DEFINED + +/* NOTE: Linux supports different processors -- do not assume 386 */ +#if defined(HYX86_64) || defined(HYIA64) || defined(HYPPC64) || defined(HYS390X) + +typedef unsigned long int U_64; /* 64bits */ +typedef long int I_64; +#define TOC_UNWRAP_ADDRESS(wrappedPointer) ((void *) (wrappedPointer)[0]) +#define TOC_STORE_TOC(dest,wrappedPointer) (dest = ((UDATA*)wrappedPointer)[1]) + +#define HY_WORD64 + +#else + +typedef long long I_64; +typedef unsigned long long U_64; + +#endif + +#if defined(HYS390X) || defined(HYS390) || defined(HYPPC64) || defined(HYPPC32) || defined(__MIPSEB__) +#define HY_BIG_ENDIAN +#else +#define HY_LITTLE_ENDIAN +#endif + +#if defined(HYPPC32) && defined(LINUX) +#define VA_PTR(valist) (&valist[0]) +#endif + +typedef double SYS_FLOAT; +#define HYCONST64(x) x##LL +#define NO_LVALUE_CASTING +#define FLOAT_EXTENDED long double +#define PLATFORM_IS_ASCII +#define PLATFORM_LINE_DELIMITER "\012" +#define DIR_SEPARATOR '/' +#define DIR_SEPARATOR_STR "/" +#define PATH_SEPARATOR ':' +#define PATH_SEPARATOR_STR ":" +#if defined(AIX) +#define LIBPATH_ENV_VAR "LIBPATH" +#else +#if defined(MACOSX) +#define LIBPATH_ENV_VAR "DYLD_LIBRARY_PATH" +#else +#define LIBPATH_ENV_VAR "LD_LIBRARY_PATH" +#endif +#endif +#if defined(MACOSX) +#define PLATFORM_DLL_EXTENSION ".dylib" +#else +#define PLATFORM_DLL_EXTENSION ".so" +#endif + +/** + * No priorities on Linux + */ + +#define HY_PRIORITY_MAP {0,0,0,0,0,0,0,0,0,0,0,0} + +typedef U_32 BOOLEAN; + +#endif + +/* Win32 - Windows 3.1 & NT using Win32 */ +#if defined(WIN32) + +#define HY_LITTLE_ENDIAN + +/* Define 64-bit integers for Windows */ +typedef __int64 I_64; +typedef unsigned __int64 U_64; + +typedef double SYS_FLOAT; +#define NO_LVALUE_CASTING +#define VMAPICALL _stdcall +#define VMCALL _cdecl +#define EXE_EXTENSION_CHAR '.' + +#define DIR_SEPARATOR '\\' +#define DIR_SEPARATOR_STR "\\" +#define PATH_SEPARATOR ';' +#define PATH_SEPARATOR_STR ";" +#define LIBPATH_ENV_VAR "PATH" + +/* Modifications for the Alpha running WIN-NT */ +#if defined(_ALPHA_) +#undef small /* defined as char in rpcndr.h */ +typedef double FLOAT_EXTENDED; +#endif + +#define HY_PRIORITY_MAP { \ + THREAD_PRIORITY_IDLE, /* 0 */\ + THREAD_PRIORITY_LOWEST, /* 1 */\ + THREAD_PRIORITY_BELOW_NORMAL, /* 2 */\ + THREAD_PRIORITY_BELOW_NORMAL, /* 3 */\ + THREAD_PRIORITY_BELOW_NORMAL, /* 4 */\ + THREAD_PRIORITY_NORMAL, /* 5 */\ + THREAD_PRIORITY_ABOVE_NORMAL, /* 6 */\ + THREAD_PRIORITY_ABOVE_NORMAL, /* 7 */\ + THREAD_PRIORITY_ABOVE_NORMAL, /* 8 */\ + THREAD_PRIORITY_ABOVE_NORMAL, /* 9 */\ + THREAD_PRIORITY_HIGHEST, /*10 */\ + THREAD_PRIORITY_TIME_CRITICAL /*11 */} + +#endif /* defined(WIN32) */ + +#if defined(ZOS) + +#define HY_BIG_ENDIAN + +#define DATA_TYPES_DEFINED +typedef unsigned int BOOLEAN; +#if defined (HYS390X) +typedef unsigned long U_64; +typedef long I_64; +#else +typedef signed long long I_64; +typedef unsigned long long U_64; +#endif + +typedef double SYS_FLOAT; + +#define HYCONST64(x) x##LL + +#define NO_LVALUE_CASTING +#define PLATFORM_LINE_DELIMITER "\012" +#define DIR_SEPARATOR '/' +#define DIR_SEPARATOR_STR "/" +#define PATH_SEPARATOR ':' +#define PATH_SEPARATOR_STR ":" +#define LIBPATH_ENV_VAR "LIBPATH" + +#define VA_PTR(valist) (&valist[0]) + +typedef struct { +#if !defined(HYS390X) + char stuff[16]; +#endif + char *ada; + void (*rawFnAddress)(); +} HyFunctionDescriptor_T; + +#define TOC_UNWRAP_ADDRESS(wrappedPointer) (((HyFunctionDescriptor_T *) (wrappedPointer))->rawFnAddress) + +#define PLATFORM_DLL_EXTENSION ".so" + +#ifdef HYS390X +#ifndef HY_WORD64 +#define HY_WORD64 +#endif /* ifndef HY_WORD64 */ +#endif /* HYS390X */ + +#endif /* ZOS */ + + +#if !defined(VMCALL) +#define VMCALL +#define VMAPICALL +#endif +#define PVMCALL VMCALL * + +#define GLOBAL_DATA(symbol) ((void*)&(symbol)) +#define GLOBAL_TABLE(symbol) GLOBAL_DATA(symbol) + +/** + * Define platform specific types: + *
    + *
  • UDATA - unsigned data, can be used as an integer or + * pointer storage
  • + *
  • IDATA - signed data, can be used as an integer or + * pointer storage
  • + *
+ */ +/* FIXME: POINTER64 */ +#if defined(HYX86_64) || defined(HYIA64) || defined(HYPPC64) || defined(HYS390X) || defined(POINTER64) + +typedef I_64 IDATA; +typedef U_64 UDATA; + +#else /* this is default for non-64bit systems */ + +typedef I_32 IDATA; +typedef U_32 UDATA; + +#endif /* defined(HYX86_64) */ + +#if !defined(DATA_TYPES_DEFINED) +/* no generic U_64 or I_64 */ + +/* don't typedef BOOLEAN since it's already def'ed on Win32 */ +#define BOOLEAN UDATA + +#ifndef HY_BIG_ENDIAN +#define HY_LITTLE_ENDIAN +#endif + +#endif + +#if !defined(HYCONST64) +#define HYCONST64(x) x##L +#endif + +#if !defined(HY_DEFAULT_SCHED) + +/** + * By default, pthreads platforms use the SCHED_OTHER thread + * scheduling policy. + */ + +#define HY_DEFAULT_SCHED SCHED_OTHER +#endif + +#if !defined(HY_PRIORITY_MAP) + +/** + * If no priority map if provided, priorities will be determined + * algorithmically. + */ + +#endif + +#if !defined(FALSE) +#define FALSE ((BOOLEAN) 0) +#if !defined(TRUE) +#define TRUE ((BOOLEAN) (!FALSE)) +#endif +#endif + +#if !defined(NULL) +#if defined(__cplusplus) +#define NULL (0) +#else +#define NULL ((void *)0) +#endif +#endif +#define USE_PROTOTYPES +#if defined(USE_PROTOTYPES) +#define PROTOTYPE(x) x +#define VARARGS , ... +#else +#define PROTOTYPE(x) () +#define VARARGS +#endif + +/** + * Assign the default line delimiter, if it was not set. + */ + +#if !defined(PLATFORM_LINE_DELIMITER) +#define PLATFORM_LINE_DELIMITER "\015\012" +#endif + +/** + * Set the max path length, if it was not set. + */ + +#if !defined(MAX_IMAGE_PATH_LENGTH) +#define MAX_IMAGE_PATH_LENGTH (2048) +#endif +typedef double ESDOUBLE; +typedef float ESSINGLE; + +/** + * Helpers for U_64s. + */ + +#define CLEAR_U64(u64) (u64 = (U_64)0) +#define LOW_LONG(l) (*((U_32 *) &(l))) +#define HIGH_LONG(l) (*(((U_32 *) &(l)) + 1)) +#define I8(x) ((I_8) (x)) +#define I8P(x) ((I_8 *) (x)) +#define U16(x) ((U_16) (x)) +#define I16(x) ((I_16) (x)) +#define I16P(x) ((I_16 *) (x)) +#define U32(x) ((U_32) (x)) +#define I32(x) ((I_32) (x)) +#define I32P(x) ((I_32 *) (x)) +#define U16P(x) ((U_16 *) (x)) +#define U32P(x) ((U_32 *) (x)) +#define OBJP(x) ((HyObject *) (x)) +#define OBJPP(x) ((HyObject **) (x)) +#define OBJPPP(x) ((HyObject ***) (x)) +#define CLASSP(x) ((Class *) (x)) +#define CLASSPP(x) ((Class **) (x)) +#define BYTEP(x) ((BYTE *) (x)) + +/** + * Test - was conflicting with OS2.h + */ + +#define ESCHAR(x) ((CHARACTER) (x)) +#define FLT(x) ((FLOAT) x) +#define FLTP(x) ((FLOAT *) (x)) +#if defined(NO_LVALUE_CASTING) +#define LI8(x) (*((I_8 *) &(x))) +#define LI8P(x) (*((I_8 **) &(x))) +#define LU16(x) (*((U_16 *) &(x))) +#define LI16(x) (*((I_16 *) &(x))) +#define LU32(x) (*((U_32 *) &(x))) +#define LI32(x) (*((I_32 *) &(x))) +#define LI32P(x) (*((I_32 **) &(x))) +#define LU16P(x) (*((U_16 **) &(x))) +#define LU32P(x) (*((U_32 **) &(x))) +#define LOBJP(x) (*((HyObject **) &(x))) +#define LOBJPP(x) (*((HyObject ***) &(x))) +#define LOBJPPP(x) (*((HyObject ****) &(x)) +#define LCLASSP(x) (*((Class **) &(x))) +#define LBYTEP(x) (*((BYTE **) &(x))) +#define LCHAR(x) (*((CHARACTER) &(x))) +#define LFLT(x) (*((FLOAT) &x)) +#define LFLTP(x) (*((FLOAT *) &(x))) +#else +#define LI8(x) I8((x)) +#define LI8P(x) I8P((x)) +#define LU16(x) U16((x)) +#define LI16(x) I16((x)) +#define LU32(x) U32((x)) +#define LI32(x) I32((x)) +#define LI32P(x) I32P((x)) +#define LU16P(x) U16P((x)) +#define LU32P(x) U32P((x)) +#define LOBJP(x) OBJP((x)) +#define LOBJPP(x) OBJPP((x)) +#define LOBJPPP(x) OBJPPP((x)) +#define LIOBJP(x) IOBJP((x)) +#define LCLASSP(x) CLASSP((x)) +#define LBYTEP(x) BYTEP((x)) +#define LCHAR(x) CHAR((x)) +#define LFLT(x) FLT((x)) +#define LFLTP(x) FLTP((x)) +#endif + +/** + * Macros for converting between words and longs and accessing bits. + */ + +#define HIGH_WORD(x) U16(U32((x)) >> 16) +#define LOW_WORD(x) U16(U32((x)) & 0xFFFF) +#define LOW_BIT(o) (U32((o)) & 1) +#define LOW_2_BITS(o) (U32((o)) & 3) +#define LOW_3_BITS(o) (U32((o)) & 7) +#define LOW_4_BITS(o) (U32((o)) & 15) +#define MAKE_32(h, l) ((U32((h)) << 16) | U32((l))) +#define MAKE_64(h, l) ((((I_64)(h)) << 32) | (l)) +#if defined(__cplusplus) +#define HY_CFUNC "C" +#define HY_CDATA "C" +#else +#define HY_CFUNC +#define HY_CDATA +#endif + +/** + * Macros for tagging functions which read/write the vm thread. + */ + +#define READSVMTHREAD +#define WRITESVMTHREAD +#define REQUIRESSTACKFRAME + +/** + * Macro for tagging functions, which never return. + */ + +#if defined(__GNUC__) + +/** + * On GCC, we can actually pass this information on to the compiler. + */ + +#define NORETURN __attribute__((noreturn)) +#else +#define NORETURN +#endif + +/** + * On some systems va_list is an array type. This is probably in + * violation of the ANSI C spec, but it's not entirely clear. Because of + * this, we end up with an undesired extra level of indirection if we take + * the address of a va_list argument. + * + * To get it right, always use the VA_PTR macro + */ + +#if !defined(VA_PTR) +#define VA_PTR(valist) (&valist) +#endif +#if !defined(TOC_UNWRAP_ADDRESS) +#define TOC_UNWRAP_ADDRESS(wrappedPointer) (wrappedPointer) +#endif + +#if !defined(TOC_STORE_TOC) +#define TOC_STORE_TOC(dest,wrappedPointer) +#endif +/** + * Macros for accessing I_64 values. + */ + +#if defined(ATOMIC_LONG_ACCESS) +#define PTR_LONG_STORE(dstPtr, aLongPtr) ((*U32P(dstPtr) = *U32P(aLongPtr)), (*(U32P(dstPtr)+1) = *(U32P(aLongPtr)+1))) +#define PTR_LONG_VALUE(dstPtr, aLongPtr) ((*U32P(aLongPtr) = *U32P(dstPtr)), (*(U32P(aLongPtr)+1) = *(U32P(dstPtr)+1))) +#else +#define PTR_LONG_STORE(dstPtr, aLongPtr) (*(dstPtr) = *(aLongPtr)) +#define PTR_LONG_VALUE(dstPtr, aLongPtr) (*(aLongPtr) = *(dstPtr)) +#endif + +/** + * Macro used when declaring tables which require relocations. + */ + +#if !defined(HYCONST_TABLE) +#define HYCONST_TABLE const +#endif + +/** + * ANSI qsort is not always available. + */ + +#if !defined(HY_SORT) +#define HY_SORT(base, nmemb, size, compare) qsort((base), (nmemb), (size), (compare)) +#endif + +/** + * Helper macros for storing/restoring pointers to jlong. + */ +#define jlong2addr(a, x) ((a *)((IDATA)(x))) +#define addr2jlong(x) ((jlong)((IDATA)(x))) + +#endif /* hycomp_h */ diff --git a/kotlin-native/runtime/src/main/cpp/math/COPYRIGHT b/kotlin-native/runtime/src/main/cpp/math/COPYRIGHT new file mode 100644 index 00000000000..a8a38a56305 --- /dev/null +++ b/kotlin-native/runtime/src/main/cpp/math/COPYRIGHT @@ -0,0 +1,128 @@ +musl as a whole is licensed under the following standard MIT license: + +---------------------------------------------------------------------- +Copyright © 2005-2014 Rich Felker, et al. + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +---------------------------------------------------------------------- + +Authors/contributors include: + +Anthony G. Basile +Arvid Picciani +Bobby Bingham +Boris Brezillon +Chris Spiegel +Emil Renner Berthing +Hiltjo Posthuma +Isaac Dunham +Jens Gustedt +Jeremy Huntwork +John Spencer +Justin Cormack +Luca Barbato +Luka Perkov +Michael Forney +Nicholas J. Kain +orc +Pascal Cuoq +Pierre Carrier +Rich Felker +Richard Pennington +Solar Designer +Strake +Szabolcs Nagy +Timo Teräs +Valentin Ochs +William Haddon + +Portions of this software are derived from third-party works licensed +under terms compatible with the above MIT license: + +The TRE regular expression implementation (src/regex/reg* and +src/regex/tre*) is Copyright © 2001-2008 Ville Laurikari and licensed +under a 2-clause BSD license (license text in the source files). The +included version has been heavily modified by Rich Felker in 2012, in +the interests of size, simplicity, and namespace cleanliness. + +Much of the math library code (src/math/* and src/complex/*) is +Copyright © 1993,2004 Sun Microsystems or +Copyright © 2003-2011 David Schultz or +Copyright © 2003-2009 Steven G. Kargl or +Copyright © 2003-2009 Bruce D. Evans or +Copyright © 2008 Stephen L. Moshier +and labelled as such in comments in the individual source files. All +have been licensed under extremely permissive terms. + +The ARM memcpy code (src/string/armel/memcpy.s) is Copyright © 2008 +The Android Open Source Project and is licensed under a two-clause BSD +license. It was taken from Bionic libc, used on Android. + +The implementation of DES for crypt (src/misc/crypt_des.c) is +Copyright © 1994 David Burren. It is licensed under a BSD license. + +The implementation of blowfish crypt (src/misc/crypt_blowfish.c) was +originally written by Solar Designer and placed into the public +domain. The code also comes with a fallback permissive license for use +in jurisdictions that may not recognize the public domain. + +The smoothsort implementation (src/stdlib/qsort.c) is Copyright © 2011 +Valentin Ochs and is licensed under an MIT-style license. + +The BSD PRNG implementation (src/prng/random.c) and XSI search API +(src/search/*.c) functions are Copyright © 2011 Szabolcs Nagy and +licensed under following terms: "Permission to use, copy, modify, +and/or distribute this code for any purpose with or without fee is +hereby granted. There is no warranty." + +The x86_64 port was written by Nicholas J. Kain. Several files (crt) +were released into the public domain; others are licensed under the +standard MIT license terms at the top of this file. See individual +files for their copyright status. + +The mips and microblaze ports were originally written by Richard +Pennington for use in the ellcc project. The original code was adapted +by Rich Felker for build system and code conventions during upstream +integration. It is licensed under the standard MIT terms. + +The powerpc port was also originally written by Richard Pennington, +and later supplemented and integrated by John Spencer. It is licensed +under the standard MIT terms. + +All other files which have no copyright comments are original works +produced specifically for use as part of this library, written either +by Rich Felker, the main author of the library, or by one or more +contibutors listed above. Details on authorship of individual files +can be found in the git version control history of the project. The +omission of copyright and license comments in each file is in the +interest of source tree size. + +All public header files (include/* and arch/*/bits/*) should be +treated as Public Domain as they intentionally contain no content +which can be covered by copyright. Some source modules may fall in +this category as well. If you believe that a file is so trivial that +it should be in the Public Domain, please contact the authors and +request an explicit statement releasing it from copyright. + +The following files are trivial, believed not to be copyrightable in +the first place, and hereby explicitly released to the Public Domain: + +All public headers: include/*, arch/*/bits/* +Startup files: crt/* diff --git a/kotlin-native/runtime/src/main/cpp/math/endian.h b/kotlin-native/runtime/src/main/cpp/math/endian.h new file mode 100644 index 00000000000..1bd444518ab --- /dev/null +++ b/kotlin-native/runtime/src/main/cpp/math/endian.h @@ -0,0 +1,82 @@ +#ifndef _ENDIAN_H +#define _ENDIAN_H + +#include + +#define __LITTLE_ENDIAN 1234 +#define __BIG_ENDIAN 4321 +#define __PDP_ENDIAN 3412 + +#if defined(__GNUC__) && defined(__BYTE_ORDER__) +#define __BYTE_ORDER __BYTE_ORDER__ +#else +#include +#endif + +#if defined(_GNU_SOURCE) || defined(_BSD_SOURCE) + +#define BIG_ENDIAN __BIG_ENDIAN +#define LITTLE_ENDIAN __LITTLE_ENDIAN +#define PDP_ENDIAN __PDP_ENDIAN +#define BYTE_ORDER __BYTE_ORDER + +#include + +static __inline uint16_t __bswap16(uint16_t __x) +{ + return __x<<8 | __x>>8; +} + +static __inline uint32_t __bswap32(uint32_t __x) +{ + return __x>>24 | __x>>8&0xff00 | __x<<8&0xff0000 | __x<<24; +} + +static __inline uint64_t __bswap64(uint64_t __x) +{ + return __bswap32(__x)+0ULL<<32 | __bswap32(__x>>32); +} + +#if __BYTE_ORDER == __LITTLE_ENDIAN +#define htobe16(x) __bswap16(x) +#define be16toh(x) __bswap16(x) +#define betoh16(x) __bswap16(x) +#define htobe32(x) __bswap32(x) +#define be32toh(x) __bswap32(x) +#define betoh32(x) __bswap32(x) +#define htobe64(x) __bswap64(x) +#define be64toh(x) __bswap64(x) +#define betoh64(x) __bswap64(x) +#define htole16(x) (uint16_t)(x) +#define le16toh(x) (uint16_t)(x) +#define letoh16(x) (uint16_t)(x) +#define htole32(x) (uint32_t)(x) +#define le32toh(x) (uint32_t)(x) +#define letoh32(x) (uint32_t)(x) +#define htole64(x) (uint64_t)(x) +#define le64toh(x) (uint64_t)(x) +#define letoh64(x) (uint64_t)(x) +#else +#define htobe16(x) (uint16_t)(x) +#define be16toh(x) (uint16_t)(x) +#define betoh16(x) (uint16_t)(x) +#define htobe32(x) (uint32_t)(x) +#define be32toh(x) (uint32_t)(x) +#define betoh32(x) (uint32_t)(x) +#define htobe64(x) (uint64_t)(x) +#define be64toh(x) (uint64_t)(x) +#define betoh64(x) (uint64_t)(x) +#define htole16(x) __bswap16(x) +#define le16toh(x) __bswap16(x) +#define letoh16(x) __bswap16(x) +#define htole32(x) __bswap32(x) +#define le32toh(x) __bswap32(x) +#define letoh32(x) __bswap32(x) +#define htole64(x) __bswap64(x) +#define le64toh(x) __bswap64(x) +#define letoh64(x) __bswap64(x) +#endif + +#endif + +#endif diff --git a/kotlin-native/runtime/src/main/cpp/math/fmod.cpp b/kotlin-native/runtime/src/main/cpp/math/fmod.cpp new file mode 100644 index 00000000000..2579b7d36ce --- /dev/null +++ b/kotlin-native/runtime/src/main/cpp/math/fmod.cpp @@ -0,0 +1,75 @@ +#include +#include + +#ifdef KONAN_WASM +#include "Common.h" +#endif + +#ifdef KONAN_WASM +RUNTIME_USED +#endif +double fmod(double x, double y) +{ + union {double f; uint64_t i;} ux = {x}, uy = {y}; + int ex = ux.i>>52 & 0x7ff; + int ey = uy.i>>52 & 0x7ff; + int sx = ux.i>>63; + uint64_t i; + + /* in the followings uxi should be ux.i, but then gcc wrongly adds */ + /* float load/store to inner loops ruining performance and code size */ + uint64_t uxi = ux.i; + + if (uy.i<<1 == 0 || isnan(y) || ex == 0x7ff) + return (x*y)/(x*y); + if (uxi<<1 <= uy.i<<1) { + if (uxi<<1 == uy.i<<1) + return 0*x; + return x; + } + + /* normalize x and y */ + if (!ex) { + for (i = uxi<<12; i>>63 == 0; ex--, i <<= 1); + uxi <<= -ex + 1; + } else { + uxi &= -1ULL >> 12; + uxi |= 1ULL << 52; + } + if (!ey) { + for (i = uy.i<<12; i>>63 == 0; ey--, i <<= 1); + uy.i <<= -ey + 1; + } else { + uy.i &= -1ULL >> 12; + uy.i |= 1ULL << 52; + } + + /* x mod y */ + for (; ex > ey; ex--) { + i = uxi - uy.i; + if (i >> 63 == 0) { + if (i == 0) + return 0*x; + uxi = i; + } + uxi <<= 1; + } + i = uxi - uy.i; + if (i >> 63 == 0) { + if (i == 0) + return 0*x; + uxi = i; + } + for (; uxi>>52 == 0; uxi <<= 1, ex--); + + /* scale result */ + if (ex > 0) { + uxi -= 1ULL << 52; + uxi |= (uint64_t)ex << 52; + } else { + uxi >>= -ex + 1; + } + uxi |= (uint64_t)sx << 63; + ux.i = uxi; + return ux.f; +} diff --git a/kotlin-native/runtime/src/main/cpp/math/fmodf.cpp b/kotlin-native/runtime/src/main/cpp/math/fmodf.cpp new file mode 100644 index 00000000000..cde03453e05 --- /dev/null +++ b/kotlin-native/runtime/src/main/cpp/math/fmodf.cpp @@ -0,0 +1,72 @@ +#include +#include + +#ifdef KONAN_WASM +#include "Common.h" +#endif + +#ifdef KONAN_WASM +RUNTIME_USED +#endif +float fmodf(float x, float y) +{ + union {float f; uint32_t i;} ux = {x}, uy = {y}; + int ex = ux.i>>23 & 0xff; + int ey = uy.i>>23 & 0xff; + uint32_t sx = ux.i & 0x80000000; + uint32_t i; + uint32_t uxi = ux.i; + + if (uy.i<<1 == 0 || isnan(y) || ex == 0xff) + return (x*y)/(x*y); + if (uxi<<1 <= uy.i<<1) { + if (uxi<<1 == uy.i<<1) + return 0*x; + return x; + } + + /* normalize x and y */ + if (!ex) { + for (i = uxi<<9; i>>31 == 0; ex--, i <<= 1); + uxi <<= -ex + 1; + } else { + uxi &= -1U >> 9; + uxi |= 1U << 23; + } + if (!ey) { + for (i = uy.i<<9; i>>31 == 0; ey--, i <<= 1); + uy.i <<= -ey + 1; + } else { + uy.i &= -1U >> 9; + uy.i |= 1U << 23; + } + + /* x mod y */ + for (; ex > ey; ex--) { + i = uxi - uy.i; + if (i >> 31 == 0) { + if (i == 0) + return 0*x; + uxi = i; + } + uxi <<= 1; + } + i = uxi - uy.i; + if (i >> 31 == 0) { + if (i == 0) + return 0*x; + uxi = i; + } + for (; uxi>>23 == 0; uxi <<= 1, ex--); + + /* scale result up */ + if (ex > 0) { + uxi -= 1U << 23; + uxi |= (uint32_t)ex << 23; + } else { + uxi >>= -ex + 1; + } + uxi |= sx; + ux.i = uxi; + return ux.f; +} diff --git a/kotlin-native/runtime/src/main/cpp/math/libm.h b/kotlin-native/runtime/src/main/cpp/math/libm.h new file mode 100644 index 00000000000..bef69d8cf52 --- /dev/null +++ b/kotlin-native/runtime/src/main/cpp/math/libm.h @@ -0,0 +1,163 @@ +/* origin: FreeBSD /usr/src/lib/msun/src/math_private.h */ +/* + * ==================================================== + * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. + * + * Developed at SunPro, a Sun Microsystems, Inc. business. + * Permission to use, copy, modify, and distribute this + * software is freely granted, provided that this notice + * is preserved. + * ==================================================== + */ + +#ifndef _LIBM_H +#define _LIBM_H + +#include +#include +#include +//#include "endian.h" + +#if LDBL_MANT_DIG == 53 && LDBL_MAX_EXP == 1024 +#elif LDBL_MANT_DIG == 64 && LDBL_MAX_EXP == 16384 && __BYTE_ORDER == __LITTLE_ENDIAN +union ldshape { + long double f; + struct { + uint64_t m; + uint16_t se; + } i; +}; +#elif LDBL_MANT_DIG == 113 && LDBL_MAX_EXP == 16384 && __BYTE_ORDER == __LITTLE_ENDIAN +union ldshape { + long double f; + struct { + uint64_t lo; + uint32_t mid; + uint16_t top; + uint16_t se; + } i; + struct { + uint64_t lo; + uint64_t hi; + } i2; +}; +#else +#error Unsupported long double representation +#endif + +#ifdef __EMSCRIPTEN__ +/* + * asm.js doesn't have user-accessible floating point exceptions, so there's + * no point in trying to force expression evaluations to produce them. + */ +#define FORCE_EVAL(x) +#else +#define FORCE_EVAL(x) do { \ + if (sizeof(x) == sizeof(float)) { \ + volatile float __x; \ + __x = (x); \ + } else if (sizeof(x) == sizeof(double)) { \ + volatile double __x; \ + __x = (x); \ + } else { \ + volatile long double __x; \ + __x = (x); \ + } \ +} while(0) +#endif + +/* Get two 32 bit ints from a double. */ +#define EXTRACT_WORDS(hi,lo,d) \ +do { \ + union {double f; uint64_t i;} __u; \ + __u.f = (d); \ + (hi) = __u.i >> 32; \ + (lo) = (uint32_t)__u.i; \ +} while (0) + +/* Get the more significant 32 bit int from a double. */ +#define GET_HIGH_WORD(hi,d) \ +do { \ + union {double f; uint64_t i;} __u; \ + __u.f = (d); \ + (hi) = __u.i >> 32; \ +} while (0) + +/* Get the less significant 32 bit int from a double. */ +#define GET_LOW_WORD(lo,d) \ +do { \ + union {double f; uint64_t i;} __u; \ + __u.f = (d); \ + (lo) = (uint32_t)__u.i; \ +} while (0) + +/* Set a double from two 32 bit ints. */ +#define INSERT_WORDS(d,hi,lo) \ +do { \ + union {double f; uint64_t i;} __u; \ + __u.i = ((uint64_t)(hi)<<32) | (uint32_t)(lo); \ + (d) = __u.f; \ +} while (0) + +/* Set the more significant 32 bits of a double from an int. */ +#define SET_HIGH_WORD(d,hi) \ +do { \ + union {double f; uint64_t i;} __u; \ + __u.f = (d); \ + __u.i &= 0xffffffff; \ + __u.i |= (uint64_t)(hi) << 32; \ + (d) = __u.f; \ +} while (0) + +/* Set the less significant 32 bits of a double from an int. */ +#define SET_LOW_WORD(d,lo) \ +do { \ + union {double f; uint64_t i;} __u; \ + __u.f = (d); \ + __u.i &= 0xffffffff00000000ull; \ + __u.i |= (uint32_t)(lo); \ + (d) = __u.f; \ +} while (0) + +/* Get a 32 bit int from a float. */ +#define GET_FLOAT_WORD(w,d) \ +do { \ + union {float f; uint32_t i;} __u; \ + __u.f = (d); \ + (w) = __u.i; \ +} while (0) + +/* Set a float from a 32 bit int. */ +#define SET_FLOAT_WORD(d,w) \ +do { \ + union {float f; uint32_t i;} __u; \ + __u.i = (w); \ + (d) = __u.f; \ +} while (0) + +/* fdlibm kernel functions */ + +int __rem_pio2_large(double*,double*,int,int,int); + +int __rem_pio2(double,double*); +double __sin(double,double,int); +double __cos(double,double); +double __tan(double,double,int); +double __expo2(double); + +int __rem_pio2f(float,double*); +float __sindf(double); +float __cosdf(double); +float __tandf(double,int); +float __expo2f(float); + +int __rem_pio2l(long double, long double *); +long double __sinl(long double, long double, int); +long double __cosl(long double, long double); +long double __tanl(long double, long double, int); + +/* polynomial evaluation */ +long double __polevll(long double, const long double *, int); +long double __p1evll(long double, const long double *, int); + +#endif diff --git a/kotlin-native/runtime/src/main/cpp/math/scalbn.cpp b/kotlin-native/runtime/src/main/cpp/math/scalbn.cpp new file mode 100644 index 00000000000..530e07c79f0 --- /dev/null +++ b/kotlin-native/runtime/src/main/cpp/math/scalbn.cpp @@ -0,0 +1,31 @@ +#include +#include + +double scalbn(double x, int n) +{ + union {double f; uint64_t i;} u; + double_t y = x; + + if (n > 1023) { + y *= 0x1p1023; + n -= 1023; + if (n > 1023) { + y *= 0x1p1023; + n -= 1023; + if (n > 1023) + n = 1023; + } + } else if (n < -1022) { + y *= 0x1p-1022; + n += 1022; + if (n < -1022) { + y *= 0x1p-1022; + n += 1022; + if (n < -1022) + n = -1022; + } + } + u.i = (uint64_t)(0x3ff+n)<<52; + x = y * u.f; + return x; +} diff --git a/kotlin-native/runtime/src/main/cpp/snprintf/AUTHORS b/kotlin-native/runtime/src/main/cpp/snprintf/AUTHORS new file mode 100644 index 00000000000..88a1b0fef7f --- /dev/null +++ b/kotlin-native/runtime/src/main/cpp/snprintf/AUTHORS @@ -0,0 +1,9 @@ +Patrick Powell +Brandon Long +Thomas Roessler +Michael Elkins +Andrew Tridgell +Russ Allbery +Hrvoje Niksic +Damien Miller +Holger Weiss diff --git a/kotlin-native/runtime/src/main/cpp/snprintf/COPYING b/kotlin-native/runtime/src/main/cpp/snprintf/COPYING new file mode 100644 index 00000000000..d84962f2342 --- /dev/null +++ b/kotlin-native/runtime/src/main/cpp/snprintf/COPYING @@ -0,0 +1,3 @@ +UNLESS SPECIFIED OTHERWISE IN THE INDIVIDUAL SOURCE FILES INCLUDED WITH +THIS PACKAGE, they may freely be used, modified and/or redistributed for +any purpose. diff --git a/kotlin-native/runtime/src/main/cpp/snprintf/snprintf.cpp b/kotlin-native/runtime/src/main/cpp/snprintf/snprintf.cpp new file mode 100644 index 00000000000..59f309d21a0 --- /dev/null +++ b/kotlin-native/runtime/src/main/cpp/snprintf/snprintf.cpp @@ -0,0 +1,2116 @@ +/* + * Copyright (c) 1995 Patrick Powell. + * + * This code is based on code written by Patrick Powell . + * It may be used for any purpose as long as this notice remains intact on all + * source code distributions. + */ + +/* + * Copyright (c) 2008 Holger Weiss. + * + * This version of the code is maintained by Holger Weiss . + * My changes to the code may freely be used, modified and/or redistributed for + * any purpose. It would be nice if additions and fixes to this file (including + * trivial code cleanups) would be sent back in order to let me include them in + * the version available at . + * However, this is not a requirement for using or redistributing (possibly + * modified) versions of this file, nor is leaving this notice intact mandatory. + */ + +/* + * History + * + * 2008-01-20 Holger Weiss for C99-snprintf 1.1: + * + * Fixed the detection of infinite floating point values on IRIX (and + * possibly other systems) and applied another few minor cleanups. + * + * 2008-01-06 Holger Weiss for C99-snprintf 1.0: + * + * Added a lot of new features, fixed many bugs, and incorporated various + * improvements done by Andrew Tridgell , Russ Allbery + * , Hrvoje Niksic , Damien Miller + * , and others for the Samba, INN, Wget, and OpenSSH + * projects. The additions include: support the "e", "E", "g", "G", and + * "F" conversion specifiers (and use conversion style "f" or "F" for the + * still unsupported "a" and "A" specifiers); support the "hh", "ll", "j", + * "t", and "z" length modifiers; support the "#" flag and the (non-C99) + * "'" flag; use localeconv(3) (if available) to get both the current + * locale's decimal point character and the separator between groups of + * digits; fix the handling of various corner cases of field width and + * precision specifications; fix various floating point conversion bugs; + * handle infinite and NaN floating point values; don't attempt to write to + * the output buffer (which may be NULL) if a size of zero was specified; + * check for integer overflow of the field width, precision, and return + * values and during the floating point conversion; use the OUTCHAR() macro + * instead of a function for better performance; provide asprintf(3) and + * vasprintf(3) functions; add new test cases. The replacement functions + * have been renamed to use an "rpl_" prefix, the function calls in the + * main project (and in this file) must be redefined accordingly for each + * replacement function which is needed (by using Autoconf or other means). + * Various other minor improvements have been applied and the coding style + * was cleaned up for consistency. + * + * 2007-07-23 Holger Weiss for Mutt 1.5.13: + * + * C99 compliant snprintf(3) and vsnprintf(3) functions return the number + * of characters that would have been written to a sufficiently sized + * buffer (excluding the '\0'). The original code simply returned the + * length of the resulting output string, so that's been fixed. + * + * 1998-03-05 Michael Elkins for Mutt 0.90.8: + * + * The original code assumed that both snprintf(3) and vsnprintf(3) were + * missing. Some systems only have snprintf(3) but not vsnprintf(3), so + * the code is now broken down under HAVE_SNPRINTF and HAVE_VSNPRINTF. + * + * 1998-01-27 Thomas Roessler for Mutt 0.89i: + * + * The PGP code was using unsigned hexadecimal formats. Unfortunately, + * unsigned formats simply didn't work. + * + * 1997-10-22 Brandon Long for Mutt 0.87.1: + * + * Ok, added some minimal floating point support, which means this probably + * requires libm on most operating systems. Don't yet support the exponent + * (e,E) and sigfig (g,G). Also, fmtint() was pretty badly broken, it just + * wasn't being exercised in ways which showed it, so that's been fixed. + * Also, formatted the code to Mutt conventions, and removed dead code left + * over from the original. Also, there is now a builtin-test, run with: + * gcc -DTEST_SNPRINTF -o snprintf snprintf.c -lm && ./snprintf + * + * 2996-09-15 Brandon Long for Mutt 0.43: + * + * This was ugly. It is still ugly. I opted out of floating point + * numbers, but the formatter understands just about everything from the + * normal C string format, at least as far as I can tell from the Solaris + * 2.5 printf(3S) man page. + */ + +/* + * ToDo + * + * - Add wide character support. + * - Add support for "%a" and "%A" conversions. + * - Create test routines which predefine the expected results. Our test cases + * usually expose bugs in system implementations rather than in ours :-) + */ + +/* + * Usage + * + * 1) The following preprocessor macros should be defined to 1 if the feature or + * file in question is available on the target system (by using Autoconf or + * other means), though basic functionality should be available as long as + * HAVE_STDARG_H and HAVE_STDLIB_H are defined correctly: + * + * HAVE_VSNPRINTF + * HAVE_SNPRINTF + * HAVE_VASPRINTF + * HAVE_ASPRINTF + * HAVE_STDARG_H + * HAVE_STDDEF_H + * HAVE_STDINT_H + * HAVE_STDLIB_H + * HAVE_FLOAT_H + * HAVE_INTTYPES_H + * HAVE_LOCALE_H + * HAVE_LOCALECONV + * HAVE_LCONV_DECIMAL_POINT + * HAVE_LCONV_THOUSANDS_SEP + * HAVE_LONG_DOUBLE + * HAVE_LONG_LONG_INT + * HAVE_UNSIGNED_LONG_LONG_INT + * HAVE_INTMAX_T + * HAVE_UINTMAX_T + * HAVE_UINTPTR_T + * HAVE_PTRDIFF_T + * HAVE_VA_COPY + * HAVE___VA_COPY + * + * 2) The calls to the functions which should be replaced must be redefined + * throughout the project files (by using Autoconf or other means): + * + * #define vsnprintf rpl_vsnprintf + * #define snprintf rpl_snprintf + * #define vasprintf rpl_vasprintf + * #define asprintf rpl_asprintf + * + * 3) The required replacement functions should be declared in some header file + * included throughout the project files: + * + * #if HAVE_CONFIG_H + * #include + * #endif + * #if HAVE_STDARG_H + * #include + * #if !HAVE_VSNPRINTF + * int rpl_vsnprintf(char *, size_t, const char *, va_list); + * #endif + * #if !HAVE_SNPRINTF + * int rpl_snprintf(char *, size_t, const char *, ...); + * #endif + * #if !HAVE_VASPRINTF + * int rpl_vasprintf(char **, const char *, va_list); + * #endif + * #if !HAVE_ASPRINTF + * int rpl_asprintf(char **, const char *, ...); + * #endif + * #endif + * + * Autoconf macros for handling step 1 and step 2 are available at + * . + */ + +#if KONAN_INTERNAL_SNPRINTF + +/**** Start of Konan-specific c99-snprintf configuration. ****/ + +#define HAVE_FLOAT_H 1 +#define HAVE_STDARG_H 1 +#define HAVE_STDDEF_H 1 +#define HAVE_STDLIB_H 1 +#define HAVE_SNPRINTF 1 +#define HAVE_VASPRINTF 1 +#define HAVE_ASPRINTF 1 +#define HAVE_LONG_LONG_INT 1 +#define HAVE_UNSIGNED_LONG_LONG_INT 1 +#include +#include +extern "C" int rpl_vsnprintf(char *, size_t, const char *, va_list); +#define malloc(size) konan:calloc(1, size) + +/**** End of Konan-specific c99-snprintf configuration. ****/ + +#if HAVE_CONFIG_H +#include +#endif /* HAVE_CONFIG_H */ + +#if TEST_SNPRINTF +#include /* For pow(3), NAN, and INFINITY. */ +#include /* For strcmp(3). */ +#if defined(__NetBSD__) || \ + defined(__FreeBSD__) || \ + defined(__OpenBSD__) || \ + defined(__NeXT__) || \ + defined(__bsd__) +#define OS_BSD 1 +#elif defined(sgi) || defined(__sgi) +#ifndef __c99 +#define __c99 /* Force C99 mode to get included on IRIX 6.5.30. */ +#endif /* !defined(__c99) */ +#define OS_IRIX 1 +#define OS_SYSV 1 +#elif defined(__svr4__) +#define OS_SYSV 1 +#elif defined(__linux__) +#define OS_LINUX 1 +#endif /* defined(__NetBSD__) || defined(__FreeBSD__) || [...] */ +#if HAVE_CONFIG_H /* Undefine definitions possibly done in config.h. */ +#ifdef HAVE_SNPRINTF +#undef HAVE_SNPRINTF +#endif /* defined(HAVE_SNPRINTF) */ +#ifdef HAVE_VSNPRINTF +#undef HAVE_VSNPRINTF +#endif /* defined(HAVE_VSNPRINTF) */ +#ifdef HAVE_ASPRINTF +#undef HAVE_ASPRINTF +#endif /* defined(HAVE_ASPRINTF) */ +#ifdef HAVE_VASPRINTF +#undef HAVE_VASPRINTF +#endif /* defined(HAVE_VASPRINTF) */ +#ifdef snprintf +#undef snprintf +#endif /* defined(snprintf) */ +#ifdef vsnprintf +#undef vsnprintf +#endif /* defined(vsnprintf) */ +#ifdef asprintf +#undef asprintf +#endif /* defined(asprintf) */ +#ifdef vasprintf +#undef vasprintf +#endif /* defined(vasprintf) */ +#else /* By default, we assume a modern system for testing. */ +#ifndef HAVE_STDARG_H +#define HAVE_STDARG_H 1 +#endif /* HAVE_STDARG_H */ +#ifndef HAVE_STDDEF_H +#define HAVE_STDDEF_H 1 +#endif /* HAVE_STDDEF_H */ +#ifndef HAVE_STDINT_H +#define HAVE_STDINT_H 1 +#endif /* HAVE_STDINT_H */ +#ifndef HAVE_STDLIB_H +#define HAVE_STDLIB_H 1 +#endif /* HAVE_STDLIB_H */ +#ifndef HAVE_FLOAT_H +#define HAVE_FLOAT_H 1 +#endif /* HAVE_FLOAT_H */ +#ifndef HAVE_INTTYPES_H +#define HAVE_INTTYPES_H 1 +#endif /* HAVE_INTTYPES_H */ +#ifndef HAVE_LOCALE_H +#define HAVE_LOCALE_H 1 +#endif /* HAVE_LOCALE_H */ +#ifndef HAVE_LOCALECONV +#define HAVE_LOCALECONV 1 +#endif /* !defined(HAVE_LOCALECONV) */ +#ifndef HAVE_LCONV_DECIMAL_POINT +#define HAVE_LCONV_DECIMAL_POINT 1 +#endif /* HAVE_LCONV_DECIMAL_POINT */ +#ifndef HAVE_LCONV_THOUSANDS_SEP +#define HAVE_LCONV_THOUSANDS_SEP 1 +#endif /* HAVE_LCONV_THOUSANDS_SEP */ +#ifndef HAVE_LONG_DOUBLE +#define HAVE_LONG_DOUBLE 1 +#endif /* !defined(HAVE_LONG_DOUBLE) */ +#ifndef HAVE_LONG_LONG_INT +#define HAVE_LONG_LONG_INT 1 +#endif /* !defined(HAVE_LONG_LONG_INT) */ +#ifndef HAVE_UNSIGNED_LONG_LONG_INT +#define HAVE_UNSIGNED_LONG_LONG_INT 1 +#endif /* !defined(HAVE_UNSIGNED_LONG_LONG_INT) */ +#ifndef HAVE_INTMAX_T +#define HAVE_INTMAX_T 1 +#endif /* !defined(HAVE_INTMAX_T) */ +#ifndef HAVE_UINTMAX_T +#define HAVE_UINTMAX_T 1 +#endif /* !defined(HAVE_UINTMAX_T) */ +#ifndef HAVE_UINTPTR_T +#define HAVE_UINTPTR_T 1 +#endif /* !defined(HAVE_UINTPTR_T) */ +#ifndef HAVE_PTRDIFF_T +#define HAVE_PTRDIFF_T 1 +#endif /* !defined(HAVE_PTRDIFF_T) */ +#ifndef HAVE_VA_COPY +#define HAVE_VA_COPY 1 +#endif /* !defined(HAVE_VA_COPY) */ +#ifndef HAVE___VA_COPY +#define HAVE___VA_COPY 1 +#endif /* !defined(HAVE___VA_COPY) */ +#endif /* HAVE_CONFIG_H */ +#define snprintf rpl_snprintf +#define vsnprintf rpl_vsnprintf +#define asprintf rpl_asprintf +#define vasprintf rpl_vasprintf +#endif /* TEST_SNPRINTF */ + +#if !HAVE_SNPRINTF || !HAVE_VSNPRINTF || !HAVE_ASPRINTF || !HAVE_VASPRINTF +#include /* For NULL, size_t, vsnprintf(3), and vasprintf(3). */ +#ifdef VA_START +#undef VA_START +#endif /* defined(VA_START) */ +#ifdef VA_SHIFT +#undef VA_SHIFT +#endif /* defined(VA_SHIFT) */ +#if HAVE_STDARG_H +#include +#define VA_START(ap, last) va_start(ap, last) +#define VA_SHIFT(ap, value, type) /* No-op for ANSI C. */ +#else /* Assume is available. */ +#include +#define VA_START(ap, last) va_start(ap) /* "last" is ignored. */ +#define VA_SHIFT(ap, value, type) value = va_arg(ap, type) +#endif /* HAVE_STDARG_H */ + +#if !HAVE_VASPRINTF +#if HAVE_STDLIB_H +#include /* For malloc(3). */ +#endif /* HAVE_STDLIB_H */ +#ifdef VA_COPY +#undef VA_COPY +#endif /* defined(VA_COPY) */ +#ifdef VA_END_COPY +#undef VA_END_COPY +#endif /* defined(VA_END_COPY) */ +#if HAVE_VA_COPY +#define VA_COPY(dest, src) va_copy(dest, src) +#define VA_END_COPY(ap) va_end(ap) +#elif HAVE___VA_COPY +#define VA_COPY(dest, src) __va_copy(dest, src) +#define VA_END_COPY(ap) va_end(ap) +#else +#define VA_COPY(dest, src) (void)mymemcpy(&dest, &src, sizeof(va_list)) +#define VA_END_COPY(ap) /* No-op. */ +#define NEED_MYMEMCPY 1 +static void *mymemcpy(void *, void *, size_t); +#endif /* HAVE_VA_COPY */ +#endif /* !HAVE_VASPRINTF */ + +#if !HAVE_VSNPRINTF +#include /* For ERANGE and errno. */ +#include /* For *_MAX. */ +#if HAVE_FLOAT_H +#include /* For *DBL_{MIN,MAX}_10_EXP. */ +#endif /* HAVE_FLOAT_H */ +#if HAVE_INTTYPES_H +#include /* For intmax_t (if not defined in ). */ +#endif /* HAVE_INTTYPES_H */ +#if HAVE_LOCALE_H +#include /* For localeconv(3). */ +#endif /* HAVE_LOCALE_H */ +#if HAVE_STDDEF_H +#include /* For ptrdiff_t. */ +#endif /* HAVE_STDDEF_H */ +#if HAVE_STDINT_H +#include /* For intmax_t. */ +#endif /* HAVE_STDINT_H */ + +/* Support for unsigned long long int. We may also need ULLONG_MAX. */ +#ifndef ULONG_MAX /* We may need ULONG_MAX as a fallback. */ +#ifdef UINT_MAX +#define ULONG_MAX UINT_MAX +#else +#define ULONG_MAX INT_MAX +#endif /* defined(UINT_MAX) */ +#endif /* !defined(ULONG_MAX) */ +#ifdef ULLONG +#undef ULLONG +#endif /* defined(ULLONG) */ +#if HAVE_UNSIGNED_LONG_LONG_INT +#define ULLONG unsigned long long int +#ifndef ULLONG_MAX +#define ULLONG_MAX ULONG_MAX +#endif /* !defined(ULLONG_MAX) */ +#else +#define ULLONG unsigned long int +#ifdef ULLONG_MAX +#undef ULLONG_MAX +#endif /* defined(ULLONG_MAX) */ +#define ULLONG_MAX ULONG_MAX +#endif /* HAVE_LONG_LONG_INT */ + +/* Support for uintmax_t. We also need UINTMAX_MAX. */ +#ifdef UINTMAX_T +#undef UINTMAX_T +#endif /* defined(UINTMAX_T) */ +#if HAVE_UINTMAX_T || defined(uintmax_t) +#define UINTMAX_T uintmax_t +#ifndef UINTMAX_MAX +#define UINTMAX_MAX ULLONG_MAX +#endif /* !defined(UINTMAX_MAX) */ +#else +#define UINTMAX_T ULLONG +#ifdef UINTMAX_MAX +#undef UINTMAX_MAX +#endif /* defined(UINTMAX_MAX) */ +#define UINTMAX_MAX ULLONG_MAX +#endif /* HAVE_UINTMAX_T || defined(uintmax_t) */ + +/* Support for long double. */ +#ifndef LDOUBLE +#if HAVE_LONG_DOUBLE +#define LDOUBLE long double +#define LDOUBLE_MIN_10_EXP LDBL_MIN_10_EXP +#define LDOUBLE_MAX_10_EXP LDBL_MAX_10_EXP +#else +#define LDOUBLE double +#define LDOUBLE_MIN_10_EXP DBL_MIN_10_EXP +#define LDOUBLE_MAX_10_EXP DBL_MAX_10_EXP +#endif /* HAVE_LONG_DOUBLE */ +#endif /* !defined(LDOUBLE) */ + +/* Support for long long int. */ +#ifndef LLONG +#if HAVE_LONG_LONG_INT +#define LLONG long long int +#else +#define LLONG long int +#endif /* HAVE_LONG_LONG_INT */ +#endif /* !defined(LLONG) */ + +/* Support for intmax_t. */ +#ifndef INTMAX_T +#if HAVE_INTMAX_T || defined(intmax_t) +#define INTMAX_T intmax_t +#else +#define INTMAX_T LLONG +#endif /* HAVE_INTMAX_T || defined(intmax_t) */ +#endif /* !defined(INTMAX_T) */ + +/* Support for uintptr_t. */ +#ifndef UINTPTR_T +#if HAVE_UINTPTR_T || defined(uintptr_t) +#define UINTPTR_T uintptr_t +#else +#define UINTPTR_T unsigned long int +#endif /* HAVE_UINTPTR_T || defined(uintptr_t) */ +#endif /* !defined(UINTPTR_T) */ + +/* Support for ptrdiff_t. */ +#ifndef PTRDIFF_T +#if HAVE_PTRDIFF_T || defined(ptrdiff_t) +#define PTRDIFF_T ptrdiff_t +#else +#define PTRDIFF_T long int +#endif /* HAVE_PTRDIFF_T || defined(ptrdiff_t) */ +#endif /* !defined(PTRDIFF_T) */ + +/* + * We need an unsigned integer type corresponding to ptrdiff_t (cf. C99: + * 7.19.6.1, 7). However, we'll simply use PTRDIFF_T and convert it to an + * unsigned type if necessary. This should work just fine in practice. + */ +#ifndef UPTRDIFF_T +#define UPTRDIFF_T PTRDIFF_T +#endif /* !defined(UPTRDIFF_T) */ + +/* + * We need a signed integer type corresponding to size_t (cf. C99: 7.19.6.1, 7). + * However, we'll simply use size_t and convert it to a signed type if + * necessary. This should work just fine in practice. + */ +#ifndef SSIZE_T +#define SSIZE_T size_t +#endif /* !defined(SSIZE_T) */ + +/* Either ERANGE or E2BIG should be available everywhere. */ +#ifndef ERANGE +#define ERANGE E2BIG +#endif /* !defined(ERANGE) */ +#ifndef EOVERFLOW +#define EOVERFLOW ERANGE +#endif /* !defined(EOVERFLOW) */ + +/* + * Buffer size to hold the octal string representation of UINT128_MAX without + * nul-termination ("3777777777777777777777777777777777777777777"). + */ +#ifdef MAX_CONVERT_LENGTH +#undef MAX_CONVERT_LENGTH +#endif /* defined(MAX_CONVERT_LENGTH) */ +#define MAX_CONVERT_LENGTH 43 + +/* Format read states. */ +#define PRINT_S_DEFAULT 0 +#define PRINT_S_FLAGS 1 +#define PRINT_S_WIDTH 2 +#define PRINT_S_DOT 3 +#define PRINT_S_PRECISION 4 +#define PRINT_S_MOD 5 +#define PRINT_S_CONV 6 + +/* Format flags. */ +#define PRINT_F_MINUS (1 << 0) +#define PRINT_F_PLUS (1 << 1) +#define PRINT_F_SPACE (1 << 2) +#define PRINT_F_NUM (1 << 3) +#define PRINT_F_ZERO (1 << 4) +#define PRINT_F_QUOTE (1 << 5) +#define PRINT_F_UP (1 << 6) +#define PRINT_F_UNSIGNED (1 << 7) +#define PRINT_F_TYPE_G (1 << 8) +#define PRINT_F_TYPE_E (1 << 9) + +/* Conversion flags. */ +#define PRINT_C_CHAR 1 +#define PRINT_C_SHORT 2 +#define PRINT_C_LONG 3 +#define PRINT_C_LLONG 4 +#define PRINT_C_LDOUBLE 5 +#define PRINT_C_SIZE 6 +#define PRINT_C_PTRDIFF 7 +#define PRINT_C_INTMAX 8 + +#ifndef MAX +#define MAX(x, y) ((x >= y) ? x : y) +#endif /* !defined(MAX) */ +#ifndef CHARTOINT +#define CHARTOINT(ch) (ch - '0') +#endif /* !defined(CHARTOINT) */ +#ifndef ISDIGIT +#define ISDIGIT(ch) ('0' <= (unsigned char)ch && (unsigned char)ch <= '9') +#endif /* !defined(ISDIGIT) */ +#ifndef ISNAN +#define ISNAN(x) (x != x) +#endif /* !defined(ISNAN) */ +#ifndef ISINF +#define ISINF(x) ((x < -1 || x > 1) && x + x == x) +#endif /* !defined(ISINF) */ + +#ifdef OUTCHAR +#undef OUTCHAR +#endif /* defined(OUTCHAR) */ +#define OUTCHAR(str, len, size, ch) \ +do { \ + if (len + 1 < size) \ + str[len] = ch; \ + (len)++; \ +} while (/* CONSTCOND */ 0) + +static void fmtstr(char *, size_t *, size_t, const char *, int, int, int); +static void fmtint(char *, size_t *, size_t, INTMAX_T, int, int, int, int); +static void fmtflt(char *, size_t *, size_t, LDOUBLE, int, int, int, int *); +static void printsep(char *, size_t *, size_t); +static int getnumsep(int); +static int getexponent(LDOUBLE); +static int convert(UINTMAX_T, char *, size_t, int, int); +static UINTMAX_T cast(LDOUBLE); +static UINTMAX_T myround(LDOUBLE); +static LDOUBLE mypow10(int); + +extern int errno; + +int +rpl_vsnprintf(char *str, size_t size, const char *format, va_list args) +{ + LDOUBLE fvalue; + INTMAX_T value; + unsigned char cvalue; + const char *strvalue; + INTMAX_T *intmaxptr; + PTRDIFF_T *ptrdiffptr; + SSIZE_T *sizeptr; + LLONG *llongptr; + long int *longptr; + int *intptr; + short int *shortptr; + signed char *charptr; + size_t len = 0; + int overflow = 0; + int base = 0; + int cflags = 0; + int flags = 0; + int width = 0; + int precision = -1; + int state = PRINT_S_DEFAULT; + char ch = *format++; + + /* + * C99 says: "If `n' is zero, nothing is written, and `s' may be a null + * pointer." (7.19.6.5, 2) We're forgiving and allow a NULL pointer + * even if a size larger than zero was specified. At least NetBSD's + * snprintf(3) does the same, as well as other versions of this file. + * (Though some of these versions will write to a non-NULL buffer even + * if a size of zero was specified, which violates the standard.) + */ + if (str == NULL && size != 0) + size = 0; + + while (ch != '\0') + switch (state) { + case PRINT_S_DEFAULT: + if (ch == '%') + state = PRINT_S_FLAGS; + else + OUTCHAR(str, len, size, ch); + ch = *format++; + break; + case PRINT_S_FLAGS: + switch (ch) { + case '-': + flags |= PRINT_F_MINUS; + ch = *format++; + break; + case '+': + flags |= PRINT_F_PLUS; + ch = *format++; + break; + case ' ': + flags |= PRINT_F_SPACE; + ch = *format++; + break; + case '#': + flags |= PRINT_F_NUM; + ch = *format++; + break; + case '0': + flags |= PRINT_F_ZERO; + ch = *format++; + break; + case '\'': /* SUSv2 flag (not in C99). */ + flags |= PRINT_F_QUOTE; + ch = *format++; + break; + default: + state = PRINT_S_WIDTH; + break; + } + break; + case PRINT_S_WIDTH: + if (ISDIGIT(ch)) { + ch = CHARTOINT(ch); + if (width > (INT_MAX - ch) / 10) { + overflow = 1; + goto out; + } + width = 10 * width + ch; + ch = *format++; + } else if (ch == '*') { + /* + * C99 says: "A negative field width argument is + * taken as a `-' flag followed by a positive + * field width." (7.19.6.1, 5) + */ + if ((width = va_arg(args, int)) < 0) { + flags |= PRINT_F_MINUS; + width = -width; + } + ch = *format++; + state = PRINT_S_DOT; + } else + state = PRINT_S_DOT; + break; + case PRINT_S_DOT: + if (ch == '.') { + state = PRINT_S_PRECISION; + ch = *format++; + } else + state = PRINT_S_MOD; + break; + case PRINT_S_PRECISION: + if (precision == -1) + precision = 0; + if (ISDIGIT(ch)) { + ch = CHARTOINT(ch); + if (precision > (INT_MAX - ch) / 10) { + overflow = 1; + goto out; + } + precision = 10 * precision + ch; + ch = *format++; + } else if (ch == '*') { + /* + * C99 says: "A negative precision argument is + * taken as if the precision were omitted." + * (7.19.6.1, 5) + */ + if ((precision = va_arg(args, int)) < 0) + precision = -1; + ch = *format++; + state = PRINT_S_MOD; + } else + state = PRINT_S_MOD; + break; + case PRINT_S_MOD: + switch (ch) { + case 'h': + ch = *format++; + if (ch == 'h') { /* It's a char. */ + ch = *format++; + cflags = PRINT_C_CHAR; + } else + cflags = PRINT_C_SHORT; + break; + case 'l': + ch = *format++; + if (ch == 'l') { /* It's a long long. */ + ch = *format++; + cflags = PRINT_C_LLONG; + } else + cflags = PRINT_C_LONG; + break; + case 'L': + cflags = PRINT_C_LDOUBLE; + ch = *format++; + break; + case 'j': + cflags = PRINT_C_INTMAX; + ch = *format++; + break; + case 't': + cflags = PRINT_C_PTRDIFF; + ch = *format++; + break; + case 'z': + cflags = PRINT_C_SIZE; + ch = *format++; + break; + } + state = PRINT_S_CONV; + break; + case PRINT_S_CONV: + switch (ch) { + case 'd': + /* FALLTHROUGH */ + case 'i': + switch (cflags) { + case PRINT_C_CHAR: + value = (signed char)va_arg(args, int); + break; + case PRINT_C_SHORT: + value = (short int)va_arg(args, int); + break; + case PRINT_C_LONG: + value = va_arg(args, long int); + break; + case PRINT_C_LLONG: + value = va_arg(args, LLONG); + break; + case PRINT_C_SIZE: + value = va_arg(args, SSIZE_T); + break; + case PRINT_C_INTMAX: + value = va_arg(args, INTMAX_T); + break; + case PRINT_C_PTRDIFF: + value = va_arg(args, PTRDIFF_T); + break; + default: + value = va_arg(args, int); + break; + } + fmtint(str, &len, size, value, 10, width, + precision, flags); + break; + case 'X': + flags |= PRINT_F_UP; + /* FALLTHROUGH */ + case 'x': + base = 16; + /* FALLTHROUGH */ + case 'o': + if (base == 0) + base = 8; + /* FALLTHROUGH */ + case 'u': + if (base == 0) + base = 10; + flags |= PRINT_F_UNSIGNED; + switch (cflags) { + case PRINT_C_CHAR: + value = (unsigned char)va_arg(args, + unsigned int); + break; + case PRINT_C_SHORT: + value = (unsigned short int)va_arg(args, + unsigned int); + break; + case PRINT_C_LONG: + value = va_arg(args, unsigned long int); + break; + case PRINT_C_LLONG: + value = va_arg(args, ULLONG); + break; + case PRINT_C_SIZE: + value = va_arg(args, size_t); + break; + case PRINT_C_INTMAX: + value = va_arg(args, UINTMAX_T); + break; + case PRINT_C_PTRDIFF: + value = va_arg(args, UPTRDIFF_T); + break; + default: + value = va_arg(args, unsigned int); + break; + } + fmtint(str, &len, size, value, base, width, + precision, flags); + break; + case 'A': + /* Not yet supported, we'll use "%F". */ + /* FALLTHROUGH */ + case 'E': + if (ch == 'E') + flags |= PRINT_F_TYPE_E; + /* FALLTHROUGH */ + case 'G': + if (ch == 'G') + flags |= PRINT_F_TYPE_G; + /* FALLTHROUGH */ + case 'F': + flags |= PRINT_F_UP; + /* FALLTHROUGH */ + case 'a': + /* Not yet supported, we'll use "%f". */ + /* FALLTHROUGH */ + case 'e': + if (ch == 'e') + flags |= PRINT_F_TYPE_E; + /* FALLTHROUGH */ + case 'g': + if (ch == 'g') + flags |= PRINT_F_TYPE_G; + /* FALLTHROUGH */ + case 'f': + if (cflags == PRINT_C_LDOUBLE) + fvalue = va_arg(args, LDOUBLE); + else + fvalue = va_arg(args, double); + fmtflt(str, &len, size, fvalue, width, + precision, flags, &overflow); + if (overflow) + goto out; + break; + case 'c': + cvalue = va_arg(args, int); + OUTCHAR(str, len, size, cvalue); + break; + case 's': + strvalue = va_arg(args, char *); + fmtstr(str, &len, size, strvalue, width, + precision, flags); + break; + case 'p': + /* + * C99 says: "The value of the pointer is + * converted to a sequence of printing + * characters, in an implementation-defined + * manner." (C99: 7.19.6.1, 8) + */ + if ((strvalue = (char*)va_arg(args, void *)) == NULL) + /* + * We use the glibc format. BSD prints + * "0x0", SysV "0". + */ + fmtstr(str, &len, size, "(nil)", width, + -1, flags); + else { + /* + * We use the BSD/glibc format. SysV + * omits the "0x" prefix (which we emit + * using the PRINT_F_NUM flag). + */ + flags |= PRINT_F_NUM; + flags |= PRINT_F_UNSIGNED; + fmtint(str, &len, size, + (UINTPTR_T)strvalue, 16, width, + precision, flags); + } + break; + case 'n': + switch (cflags) { + case PRINT_C_CHAR: + charptr = va_arg(args, signed char *); + *charptr = len; + break; + case PRINT_C_SHORT: + shortptr = va_arg(args, short int *); + *shortptr = len; + break; + case PRINT_C_LONG: + longptr = va_arg(args, long int *); + *longptr = len; + break; + case PRINT_C_LLONG: + llongptr = va_arg(args, LLONG *); + *llongptr = len; + break; + case PRINT_C_SIZE: + /* + * C99 says that with the "z" length + * modifier, "a following `n' conversion + * specifier applies to a pointer to a + * signed integer type corresponding to + * size_t argument." (7.19.6.1, 7) + */ + sizeptr = va_arg(args, SSIZE_T *); + *sizeptr = len; + break; + case PRINT_C_INTMAX: + intmaxptr = va_arg(args, INTMAX_T *); + *intmaxptr = len; + break; + case PRINT_C_PTRDIFF: + ptrdiffptr = va_arg(args, PTRDIFF_T *); + *ptrdiffptr = len; + break; + default: + intptr = va_arg(args, int *); + *intptr = len; + break; + } + break; + case '%': /* Print a "%" character verbatim. */ + OUTCHAR(str, len, size, ch); + break; + default: /* Skip other characters. */ + break; + } + ch = *format++; + state = PRINT_S_DEFAULT; + base = cflags = flags = width = 0; + precision = -1; + break; + } +out: + if (len < size) + str[len] = '\0'; + else if (size > 0) + str[size - 1] = '\0'; + + if (overflow || len > INT_MAX) { + errno = EOVERFLOW; + return -1; + } + return (int)len; +} + +static void +fmtstr(char *str, size_t *len, size_t size, const char *value, int width, + int precision, int flags) +{ + int padlen, strln; /* Amount to pad. */ + int noprecision = (precision == -1); + + if (value == NULL) /* We're forgiving. */ + value = "(null)"; + + /* If a precision was specified, don't read the string past it. */ + for (strln = 0; value[strln] != '\0' && + (noprecision || strln < precision); strln++) + continue; + + if ((padlen = width - strln) < 0) + padlen = 0; + if (flags & PRINT_F_MINUS) /* Left justify. */ + padlen = -padlen; + + while (padlen > 0) { /* Leading spaces. */ + OUTCHAR(str, *len, size, ' '); + padlen--; + } + while (*value != '\0' && (noprecision || precision-- > 0)) { + OUTCHAR(str, *len, size, *value); + value++; + } + while (padlen < 0) { /* Trailing spaces. */ + OUTCHAR(str, *len, size, ' '); + padlen++; + } +} + +static void +fmtint(char *str, size_t *len, size_t size, INTMAX_T value, int base, int width, + int precision, int flags) +{ + UINTMAX_T uvalue; + char iconvert[MAX_CONVERT_LENGTH]; + char sign = 0; + char hexprefix = 0; + int spadlen = 0; /* Amount to space pad. */ + int zpadlen = 0; /* Amount to zero pad. */ + int pos; + int separators = (flags & PRINT_F_QUOTE); + int noprecision = (precision == -1); + + if (flags & PRINT_F_UNSIGNED) + uvalue = value; + else { + uvalue = (value >= 0) ? value : -value; + if (value < 0) + sign = '-'; + else if (flags & PRINT_F_PLUS) /* Do a sign. */ + sign = '+'; + else if (flags & PRINT_F_SPACE) + sign = ' '; + } + + pos = convert(uvalue, iconvert, sizeof(iconvert), base, + flags & PRINT_F_UP); + + if (flags & PRINT_F_NUM && uvalue != 0) { + /* + * C99 says: "The result is converted to an `alternative form'. + * For `o' conversion, it increases the precision, if and only + * if necessary, to force the first digit of the result to be a + * zero (if the value and precision are both 0, a single 0 is + * printed). For `x' (or `X') conversion, a nonzero result has + * `0x' (or `0X') prefixed to it." (7.19.6.1, 6) + */ + switch (base) { + case 8: + if (precision <= pos) + precision = pos + 1; + break; + case 16: + hexprefix = (flags & PRINT_F_UP) ? 'X' : 'x'; + break; + } + } + + if (separators) /* Get the number of group separators we'll print. */ + separators = getnumsep(pos); + + zpadlen = precision - pos - separators; + spadlen = width /* Minimum field width. */ + - separators /* Number of separators. */ + - MAX(precision, pos) /* Number of integer digits. */ + - ((sign != 0) ? 1 : 0) /* Will we print a sign? */ + - ((hexprefix != 0) ? 2 : 0); /* Will we print a prefix? */ + + if (zpadlen < 0) + zpadlen = 0; + if (spadlen < 0) + spadlen = 0; + + /* + * C99 says: "If the `0' and `-' flags both appear, the `0' flag is + * ignored. For `d', `i', `o', `u', `x', and `X' conversions, if a + * precision is specified, the `0' flag is ignored." (7.19.6.1, 6) + */ + if (flags & PRINT_F_MINUS) /* Left justify. */ + spadlen = -spadlen; + else if (flags & PRINT_F_ZERO && noprecision) { + zpadlen += spadlen; + spadlen = 0; + } + while (spadlen > 0) { /* Leading spaces. */ + OUTCHAR(str, *len, size, ' '); + spadlen--; + } + if (sign != 0) /* Sign. */ + OUTCHAR(str, *len, size, sign); + if (hexprefix != 0) { /* A "0x" or "0X" prefix. */ + OUTCHAR(str, *len, size, '0'); + OUTCHAR(str, *len, size, hexprefix); + } + while (zpadlen > 0) { /* Leading zeros. */ + OUTCHAR(str, *len, size, '0'); + zpadlen--; + } + while (pos > 0) { /* The actual digits. */ + pos--; + OUTCHAR(str, *len, size, iconvert[pos]); + if (separators > 0 && pos > 0 && pos % 3 == 0) + printsep(str, len, size); + } + while (spadlen < 0) { /* Trailing spaces. */ + OUTCHAR(str, *len, size, ' '); + spadlen++; + } +} + +static void +fmtflt(char *str, size_t *len, size_t size, LDOUBLE fvalue, int width, + int precision, int flags, int *overflow) +{ + LDOUBLE ufvalue; + UINTMAX_T intpart; + UINTMAX_T fracpart; + UINTMAX_T mask; + const char *infnan = NULL; + char iconvert[MAX_CONVERT_LENGTH]; + char fconvert[MAX_CONVERT_LENGTH]; + char econvert[5]; /* "e-300" (without nul-termination). */ + char esign = 0; + char sign = 0; + int leadfraczeros = 0; + int exponent = 0; + int emitpoint = 0; + int omitzeros = 0; + int omitcount = 0; + int padlen = 0; + int epos = 0; + int fpos = 0; + int ipos = 0; + int separators = (flags & PRINT_F_QUOTE); + int estyle = (flags & PRINT_F_TYPE_E); +#if HAVE_LOCALECONV && HAVE_LCONV_DECIMAL_POINT + struct lconv *lc = localeconv(); +#endif /* HAVE_LOCALECONV && HAVE_LCONV_DECIMAL_POINT */ + + /* + * AIX' man page says the default is 0, but C99 and at least Solaris' + * and NetBSD's man pages say the default is 6, and sprintf(3) on AIX + * defaults to 6. + */ + if (precision == -1) + precision = 6; + + if (fvalue < 0.0) + sign = '-'; + else if (flags & PRINT_F_PLUS) /* Do a sign. */ + sign = '+'; + else if (flags & PRINT_F_SPACE) + sign = ' '; + + if (ISNAN(fvalue)) + infnan = (flags & PRINT_F_UP) ? "NAN" : "nan"; + else if (ISINF(fvalue)) + infnan = (flags & PRINT_F_UP) ? "INF" : "inf"; + + if (infnan != NULL) { + if (sign != 0) + iconvert[ipos++] = sign; + while (*infnan != '\0') + iconvert[ipos++] = *infnan++; + fmtstr(str, len, size, iconvert, width, ipos, flags); + return; + } + + /* "%e" (or "%E") or "%g" (or "%G") conversion. */ + if (flags & PRINT_F_TYPE_E || flags & PRINT_F_TYPE_G) { + if (flags & PRINT_F_TYPE_G) { + /* + * If the precision is zero, it is treated as one (cf. + * C99: 7.19.6.1, 8). + */ + if (precision == 0) + precision = 1; + /* + * For "%g" (and "%G") conversions, the precision + * specifies the number of significant digits, which + * includes the digits in the integer part. The + * conversion will or will not be using "e-style" (like + * "%e" or "%E" conversions) depending on the precision + * and on the exponent. However, the exponent can be + * affected by rounding the converted value, so we'll + * leave this decision for later. Until then, we'll + * assume that we're going to do an "e-style" conversion + * (in order to get the exponent calculated). For + * "e-style", the precision must be decremented by one. + */ + precision--; + /* + * For "%g" (and "%G") conversions, trailing zeros are + * removed from the fractional portion of the result + * unless the "#" flag was specified. + */ + if (!(flags & PRINT_F_NUM)) + omitzeros = 1; + } + exponent = getexponent(fvalue); + estyle = 1; + } + +again: + /* + * Sorry, we only support 9, 19, or 38 digits (that is, the number of + * digits of the 32-bit, the 64-bit, or the 128-bit UINTMAX_MAX value + * minus one) past the decimal point due to our conversion method. + */ + switch (sizeof(UINTMAX_T)) { + case 16: + if (precision > 38) + precision = 38; + break; + case 8: + if (precision > 19) + precision = 19; + break; + default: + if (precision > 9) + precision = 9; + break; + } + + ufvalue = (fvalue >= 0.0) ? fvalue : -fvalue; + if (estyle) /* We want exactly one integer digit. */ + ufvalue /= mypow10(exponent); + + if ((intpart = cast(ufvalue)) == UINTMAX_MAX) { + *overflow = 1; + return; + } + + /* + * Factor of ten with the number of digits needed for the fractional + * part. For example, if the precision is 3, the mask will be 1000. + */ + mask = mypow10(precision); + /* + * We "cheat" by converting the fractional part to integer by + * multiplying by a factor of ten. + */ + if ((fracpart = myround(mask * (ufvalue - intpart))) >= mask) { + /* + * For example, ufvalue = 2.99962, intpart = 2, and mask = 1000 + * (because precision = 3). Now, myround(1000 * 0.99962) will + * return 1000. So, the integer part must be incremented by one + * and the fractional part must be set to zero. + */ + intpart++; + fracpart = 0; + if (estyle && intpart == 10) { + /* + * The value was rounded up to ten, but we only want one + * integer digit if using "e-style". So, the integer + * part must be set to one and the exponent must be + * incremented by one. + */ + intpart = 1; + exponent++; + } + } + + /* + * Now that we know the real exponent, we can check whether or not to + * use "e-style" for "%g" (and "%G") conversions. If we don't need + * "e-style", the precision must be adjusted and the integer and + * fractional parts must be recalculated from the original value. + * + * C99 says: "Let P equal the precision if nonzero, 6 if the precision + * is omitted, or 1 if the precision is zero. Then, if a conversion + * with style `E' would have an exponent of X: + * + * - if P > X >= -4, the conversion is with style `f' (or `F') and + * precision P - (X + 1). + * + * - otherwise, the conversion is with style `e' (or `E') and precision + * P - 1." (7.19.6.1, 8) + * + * Note that we had decremented the precision by one. + */ + if (flags & PRINT_F_TYPE_G && estyle && + precision + 1 > exponent && exponent >= -4) { + precision -= exponent; + estyle = 0; + goto again; + } + + if (estyle) { + if (exponent < 0) { + exponent = -exponent; + esign = '-'; + } else + esign = '+'; + + /* + * Convert the exponent. The sizeof(econvert) is 5. So, the + * econvert buffer can hold e.g. "e+999" and "e-999". We don't + * support an exponent which contains more than three digits. + * Therefore, the following stores are safe. + */ + epos = convert(exponent, econvert, 3, 10, 0); + /* + * C99 says: "The exponent always contains at least two digits, + * and only as many more digits as necessary to represent the + * exponent." (7.19.6.1, 8) + */ + if (epos == 1) + econvert[epos++] = '0'; + econvert[epos++] = esign; + econvert[epos++] = (flags & PRINT_F_UP) ? 'E' : 'e'; + } + + /* Convert the integer part and the fractional part. */ + ipos = convert(intpart, iconvert, sizeof(iconvert), 10, 0); + if (fracpart != 0) /* convert() would return 1 if fracpart == 0. */ + fpos = convert(fracpart, fconvert, sizeof(fconvert), 10, 0); + + leadfraczeros = precision - fpos; + + if (omitzeros) { + if (fpos > 0) /* Omit trailing fractional part zeros. */ + while (omitcount < fpos && fconvert[omitcount] == '0') + omitcount++; + else { /* The fractional part is zero, omit it completely. */ + omitcount = precision; + leadfraczeros = 0; + } + precision -= omitcount; + } + + /* + * Print a decimal point if either the fractional part is non-zero + * and/or the "#" flag was specified. + */ + if (precision > 0 || flags & PRINT_F_NUM) + emitpoint = 1; + if (separators) /* Get the number of group separators we'll print. */ + separators = getnumsep(ipos); + + padlen = width /* Minimum field width. */ + - ipos /* Number of integer digits. */ + - epos /* Number of exponent characters. */ + - precision /* Number of fractional digits. */ + - separators /* Number of group separators. */ + - (emitpoint ? 1 : 0) /* Will we print a decimal point? */ + - ((sign != 0) ? 1 : 0); /* Will we print a sign character? */ + + if (padlen < 0) + padlen = 0; + + /* + * C99 says: "If the `0' and `-' flags both appear, the `0' flag is + * ignored." (7.19.6.1, 6) + */ + if (flags & PRINT_F_MINUS) /* Left justifty. */ + padlen = -padlen; + else if (flags & PRINT_F_ZERO && padlen > 0) { + if (sign != 0) { /* Sign. */ + OUTCHAR(str, *len, size, sign); + sign = 0; + } + while (padlen > 0) { /* Leading zeros. */ + OUTCHAR(str, *len, size, '0'); + padlen--; + } + } + while (padlen > 0) { /* Leading spaces. */ + OUTCHAR(str, *len, size, ' '); + padlen--; + } + if (sign != 0) /* Sign. */ + OUTCHAR(str, *len, size, sign); + while (ipos > 0) { /* Integer part. */ + ipos--; + OUTCHAR(str, *len, size, iconvert[ipos]); + if (separators > 0 && ipos > 0 && ipos % 3 == 0) + printsep(str, len, size); + } + if (emitpoint) { /* Decimal point. */ +#if HAVE_LOCALECONV && HAVE_LCONV_DECIMAL_POINT + if (lc->decimal_point != NULL && *lc->decimal_point != '\0') + OUTCHAR(str, *len, size, *lc->decimal_point); + else /* We'll always print some decimal point character. */ +#endif /* HAVE_LOCALECONV && HAVE_LCONV_DECIMAL_POINT */ + OUTCHAR(str, *len, size, '.'); + } + while (leadfraczeros > 0) { /* Leading fractional part zeros. */ + OUTCHAR(str, *len, size, '0'); + leadfraczeros--; + } + while (fpos > omitcount) { /* The remaining fractional part. */ + fpos--; + OUTCHAR(str, *len, size, fconvert[fpos]); + } + while (epos > 0) { /* Exponent. */ + epos--; + OUTCHAR(str, *len, size, econvert[epos]); + } + while (padlen < 0) { /* Trailing spaces. */ + OUTCHAR(str, *len, size, ' '); + padlen++; + } +} + +static void +printsep(char *str, size_t *len, size_t size) +{ +#if HAVE_LOCALECONV && HAVE_LCONV_THOUSANDS_SEP + struct lconv *lc = localeconv(); + int i; + + if (lc->thousands_sep != NULL) + for (i = 0; lc->thousands_sep[i] != '\0'; i++) + OUTCHAR(str, *len, size, lc->thousands_sep[i]); + else +#endif /* HAVE_LOCALECONV && HAVE_LCONV_THOUSANDS_SEP */ + OUTCHAR(str, *len, size, ','); +} + +static int +getnumsep(int digits) +{ + int separators = (digits - ((digits % 3 == 0) ? 1 : 0)) / 3; +#if HAVE_LOCALECONV && HAVE_LCONV_THOUSANDS_SEP + int strln; + struct lconv *lc = localeconv(); + + /* We support an arbitrary separator length (including zero). */ + if (lc->thousands_sep != NULL) { + for (strln = 0; lc->thousands_sep[strln] != '\0'; strln++) + continue; + separators *= strln; + } +#endif /* HAVE_LOCALECONV && HAVE_LCONV_THOUSANDS_SEP */ + return separators; +} + +static int +getexponent(LDOUBLE value) +{ + LDOUBLE tmp = (value >= 0.0) ? value : -value; + int exponent = 0; + + /* + * We check for LDOUBLE_MAX_10_EXP >= exponent >= LDOUBLE_MIN_10_EXP in + * order to work around possible endless loops which could happen (at + * least) in the second loop (at least) if we're called with an infinite + * value. However, we checked for infinity before calling this function + * using our ISINF() macro, so this might be somewhat paranoid. + */ + while (tmp < 1.0 && tmp > 0.0 && --exponent >= LDOUBLE_MIN_10_EXP) + tmp *= 10; + while (tmp >= 10.0 && ++exponent <= LDOUBLE_MAX_10_EXP) + tmp /= 10; + + return exponent; +} + +static int +convert(UINTMAX_T value, char *buf, size_t size, int base, int caps) +{ + const char *digits = caps ? "0123456789ABCDEF" : "0123456789abcdef"; + size_t pos = 0; + + /* We return an unterminated buffer with the digits in reverse order. */ + do { + buf[pos++] = digits[value % base]; + value /= base; + } while (value != 0 && pos < size); + + return (int)pos; +} + +static UINTMAX_T +cast(LDOUBLE value) +{ + UINTMAX_T result; + + /* + * We check for ">=" and not for ">" because if UINTMAX_MAX cannot be + * represented exactly as an LDOUBLE value (but is less than LDBL_MAX), + * it may be increased to the nearest higher representable value for the + * comparison (cf. C99: 6.3.1.4, 2). It might then equal the LDOUBLE + * value although converting the latter to UINTMAX_T would overflow. + */ + if (value >= UINTMAX_MAX) + return UINTMAX_MAX; + + result = value; + /* + * At least on NetBSD/sparc64 3.0.2 and 4.99.30, casting long double to + * an integer type converts e.g. 1.9 to 2 instead of 1 (which violates + * the standard). Sigh. + */ + return (result <= value) ? result : result - 1; +} + +static UINTMAX_T +myround(LDOUBLE value) +{ + UINTMAX_T intpart = cast(value); + + return ((value -= intpart) < 0.5) ? intpart : intpart + 1; +} + +static LDOUBLE +mypow10(int exponent) +{ + LDOUBLE result = 1; + + while (exponent > 0) { + result *= 10; + exponent--; + } + while (exponent < 0) { + result /= 10; + exponent++; + } + return result; +} +#endif /* !HAVE_VSNPRINTF */ + +#if !HAVE_VASPRINTF +#if NEED_MYMEMCPY +void * +mymemcpy(void *dst, void *src, size_t len) +{ + const char *from = (char*)src; + char *to = (char*)dst; + + /* No need for optimization, we use this only to replace va_copy(3). */ + while (len-- > 0) + *to++ = *from++; + return dst; +} +#endif /* NEED_MYMEMCPY */ + +int +rpl_vasprintf(char **ret, const char *format, va_list ap) +{ + size_t size; + int len; + va_list aq; + + VA_COPY(aq, ap); + len = vsnprintf(NULL, 0, format, aq); + VA_END_COPY(aq); + if (len < 0 || (*ret = (char*)malloc(size = len + 1)) == NULL) + return -1; + return vsnprintf(*ret, size, format, ap); +} +#endif /* !HAVE_VASPRINTF */ + +#if !HAVE_SNPRINTF +#if HAVE_STDARG_H +int +rpl_snprintf(char *str, size_t size, const char *format, ...) +#else +int +rpl_snprintf(va_alist) va_dcl +#endif /* HAVE_STDARG_H */ +{ +#if !HAVE_STDARG_H + char *str; + size_t size; + char *format; +#endif /* HAVE_STDARG_H */ + va_list ap; + int len; + + VA_START(ap, format); + VA_SHIFT(ap, str, char *); + VA_SHIFT(ap, size, size_t); + VA_SHIFT(ap, format, const char *); + len = vsnprintf(str, size, format, ap); + va_end(ap); + return len; +} +#endif /* !HAVE_SNPRINTF */ + +#if !HAVE_ASPRINTF +#if HAVE_STDARG_H +int +rpl_asprintf(char **ret, const char *format, ...) +#else +int +rpl_asprintf(va_alist) va_dcl +#endif /* HAVE_STDARG_H */ +{ +#if !HAVE_STDARG_H + char **ret; + char *format; +#endif /* HAVE_STDARG_H */ + va_list ap; + int len; + + VA_START(ap, format); + VA_SHIFT(ap, ret, char **); + VA_SHIFT(ap, format, const char *); + len = vasprintf(ret, format, ap); + va_end(ap); + return len; +} +#endif /* !HAVE_ASPRINTF */ +#else /* Dummy declaration to avoid empty translation unit warnings. */ +int main(int argc, char **argv); +#endif /* !HAVE_SNPRINTF || !HAVE_VSNPRINTF || !HAVE_ASPRINTF || [...] */ + +#if TEST_SNPRINTF +int +main(void) +{ + const char *float_fmt[] = { + /* "%E" and "%e" formats. */ +#if HAVE_LONG_LONG_INT && !OS_BSD && !OS_IRIX + "%.16e", + "%22.16e", + "%022.16e", + "%-22.16e", + "%#+'022.16e", +#endif /* HAVE_LONG_LONG_INT && !OS_BSD && !OS_IRIX */ + "foo|%#+0123.9E|bar", + "%-123.9e", + "%123.9e", + "%+23.9e", + "%+05.8e", + "%-05.8e", + "%05.8e", + "%+5.8e", + "%-5.8e", + "% 5.8e", + "%5.8e", + "%+4.9e", +#if !OS_LINUX /* glibc sometimes gets these wrong. */ + "%+#010.0e", + "%#10.1e", + "%10.5e", + "% 10.5e", + "%5.0e", + "%5.e", + "%#5.0e", + "%#5.e", + "%3.2e", + "%3.1e", + "%-1.5e", + "%1.5e", + "%01.3e", + "%1.e", + "%.1e", + "%#.0e", + "%+.0e", + "% .0e", + "%.0e", + "%#.e", + "%+.e", + "% .e", + "%.e", + "%4e", + "%e", + "%E", +#endif /* !OS_LINUX */ + /* "%F" and "%f" formats. */ +#if !OS_BSD && !OS_IRIX + "% '022f", + "%+'022f", + "%-'22f", + "%'22f", +#if HAVE_LONG_LONG_INT + "%.16f", + "%22.16f", + "%022.16f", + "%-22.16f", + "%#+'022.16f", +#endif /* HAVE_LONG_LONG_INT */ +#endif /* !OS_BSD && !OS_IRIX */ + "foo|%#+0123.9F|bar", + "%-123.9f", + "%123.9f", + "%+23.9f", + "%+#010.0f", + "%#10.1f", + "%10.5f", + "% 10.5f", + "%+05.8f", + "%-05.8f", + "%05.8f", + "%+5.8f", + "%-5.8f", + "% 5.8f", + "%5.8f", + "%5.0f", + "%5.f", + "%#5.0f", + "%#5.f", + "%+4.9f", + "%3.2f", + "%3.1f", + "%-1.5f", + "%1.5f", + "%01.3f", + "%1.f", + "%.1f", + "%#.0f", + "%+.0f", + "% .0f", + "%.0f", + "%#.f", + "%+.f", + "% .f", + "%.f", + "%4f", + "%f", + "%F", + /* "%G" and "%g" formats. */ +#if !OS_BSD && !OS_IRIX && !OS_LINUX + "% '022g", + "%+'022g", + "%-'22g", + "%'22g", +#if HAVE_LONG_LONG_INT + "%.16g", + "%22.16g", + "%022.16g", + "%-22.16g", + "%#+'022.16g", +#endif /* HAVE_LONG_LONG_INT */ +#endif /* !OS_BSD && !OS_IRIX && !OS_LINUX */ + "foo|%#+0123.9G|bar", + "%-123.9g", + "%123.9g", + "%+23.9g", + "%+05.8g", + "%-05.8g", + "%05.8g", + "%+5.8g", + "%-5.8g", + "% 5.8g", + "%5.8g", + "%+4.9g", +#if !OS_LINUX /* glibc sometimes gets these wrong. */ + "%+#010.0g", + "%#10.1g", + "%10.5g", + "% 10.5g", + "%5.0g", + "%5.g", + "%#5.0g", + "%#5.g", + "%3.2g", + "%3.1g", + "%-1.5g", + "%1.5g", + "%01.3g", + "%1.g", + "%.1g", + "%#.0g", + "%+.0g", + "% .0g", + "%.0g", + "%#.g", + "%+.g", + "% .g", + "%.g", + "%4g", + "%g", + "%G", +#endif /* !OS_LINUX */ + NULL + }; + double float_val[] = { + -4.136, + -134.52, + -5.04030201, + -3410.01234, + -999999.999999, + -913450.29876, + -913450.2, + -91345.2, + -9134.2, + -913.2, + -91.2, + -9.2, + -9.9, + 4.136, + 134.52, + 5.04030201, + 3410.01234, + 999999.999999, + 913450.29876, + 913450.2, + 91345.2, + 9134.2, + 913.2, + 91.2, + 9.2, + 9.9, + 9.96, + 9.996, + 9.9996, + 9.99996, + 9.999996, + 9.9999996, + 9.99999996, + 0.99999996, + 0.99999999, + 0.09999999, + 0.00999999, + 0.00099999, + 0.00009999, + 0.00000999, + 0.00000099, + 0.00000009, + 0.00000001, + 0.0000001, + 0.000001, + 0.00001, + 0.0001, + 0.001, + 0.01, + 0.1, + 1.0, + 1.5, + -1.5, + -1.0, + -0.1, +#if !OS_BSD /* BSD sometimes gets these wrong. */ +#ifdef INFINITY + INFINITY, + -INFINITY, +#endif /* defined(INFINITY) */ +#ifdef NAN + NAN, +#endif /* defined(NAN) */ +#endif /* !OS_BSD */ + 0 + }; + const char *long_fmt[] = { + "foo|%0123ld|bar", +#if !OS_IRIX + "% '0123ld", + "%+'0123ld", + "%-'123ld", + "%'123ld", +#endif /* !OS_IRiX */ + "%123.9ld", + "% 123.9ld", + "%+123.9ld", + "%-123.9ld", + "%0123ld", + "% 0123ld", + "%+0123ld", + "%-0123ld", + "%10.5ld", + "% 10.5ld", + "%+10.5ld", + "%-10.5ld", + "%010ld", + "% 010ld", + "%+010ld", + "%-010ld", + "%4.2ld", + "% 4.2ld", + "%+4.2ld", + "%-4.2ld", + "%04ld", + "% 04ld", + "%+04ld", + "%-04ld", + "%5.5ld", + "%+22.33ld", + "%01.3ld", + "%1.5ld", + "%-1.5ld", + "%44ld", + "%4ld", + "%4.0ld", + "%4.ld", + "%.44ld", + "%.4ld", + "%.0ld", + "%.ld", + "%ld", + NULL + }; + long int long_val[] = { +#ifdef LONG_MAX + LONG_MAX, +#endif /* LONG_MAX */ +#ifdef LONG_MIN + LONG_MIN, +#endif /* LONG_MIN */ + -91340, + 91340, + 341, + 134, + 0203, + -1, + 1, + 0 + }; + const char *ulong_fmt[] = { + /* "%u" formats. */ + "foo|%0123lu|bar", +#if !OS_IRIX + "% '0123lu", + "%+'0123lu", + "%-'123lu", + "%'123lu", +#endif /* !OS_IRiX */ + "%123.9lu", + "% 123.9lu", + "%+123.9lu", + "%-123.9lu", + "%0123lu", + "% 0123lu", + "%+0123lu", + "%-0123lu", + "%5.5lu", + "%+22.33lu", + "%01.3lu", + "%1.5lu", + "%-1.5lu", + "%44lu", + "%lu", + /* "%o" formats. */ + "foo|%#0123lo|bar", + "%#123.9lo", + "%# 123.9lo", + "%#+123.9lo", + "%#-123.9lo", + "%#0123lo", + "%# 0123lo", + "%#+0123lo", + "%#-0123lo", + "%#5.5lo", + "%#+22.33lo", + "%#01.3lo", + "%#1.5lo", + "%#-1.5lo", + "%#44lo", + "%#lo", + "%123.9lo", + "% 123.9lo", + "%+123.9lo", + "%-123.9lo", + "%0123lo", + "% 0123lo", + "%+0123lo", + "%-0123lo", + "%5.5lo", + "%+22.33lo", + "%01.3lo", + "%1.5lo", + "%-1.5lo", + "%44lo", + "%lo", + /* "%X" and "%x" formats. */ + "foo|%#0123lX|bar", + "%#123.9lx", + "%# 123.9lx", + "%#+123.9lx", + "%#-123.9lx", + "%#0123lx", + "%# 0123lx", + "%#+0123lx", + "%#-0123lx", + "%#5.5lx", + "%#+22.33lx", + "%#01.3lx", + "%#1.5lx", + "%#-1.5lx", + "%#44lx", + "%#lx", + "%#lX", + "%123.9lx", + "% 123.9lx", + "%+123.9lx", + "%-123.9lx", + "%0123lx", + "% 0123lx", + "%+0123lx", + "%-0123lx", + "%5.5lx", + "%+22.33lx", + "%01.3lx", + "%1.5lx", + "%-1.5lx", + "%44lx", + "%lx", + "%lX", + NULL + }; + unsigned long int ulong_val[] = { +#ifdef ULONG_MAX + ULONG_MAX, +#endif /* ULONG_MAX */ + 91340, + 341, + 134, + 0203, + 1, + 0 + }; + const char *llong_fmt[] = { + "foo|%0123lld|bar", + "%123.9lld", + "% 123.9lld", + "%+123.9lld", + "%-123.9lld", + "%0123lld", + "% 0123lld", + "%+0123lld", + "%-0123lld", + "%5.5lld", + "%+22.33lld", + "%01.3lld", + "%1.5lld", + "%-1.5lld", + "%44lld", + "%lld", + NULL + }; + LLONG llong_val[] = { +#ifdef LLONG_MAX + LLONG_MAX, +#endif /* LLONG_MAX */ +#ifdef LLONG_MIN + LLONG_MIN, +#endif /* LLONG_MIN */ + -91340, + 91340, + 341, + 134, + 0203, + -1, + 1, + 0 + }; + const char *string_fmt[] = { + "foo|%10.10s|bar", + "%-10.10s", + "%10.10s", + "%10.5s", + "%5.10s", + "%10.1s", + "%1.10s", + "%10.0s", + "%0.10s", + "%-42.5s", + "%2.s", + "%.10s", + "%.1s", + "%.0s", + "%.s", + "%4s", + "%s", + NULL + }; + const char *string_val[] = { + "Hello", + "Hello, world!", + "Sound check: One, two, three.", + "This string is a little longer than the other strings.", + "1", + "", + NULL + }; +#if !OS_SYSV /* SysV uses a different format than we do. */ + const char *pointer_fmt[] = { + "foo|%p|bar", + "%42p", + "%p", + NULL + }; + const char *pointer_val[] = { + *pointer_fmt, + *string_fmt, + *string_val, + NULL + }; +#endif /* !OS_SYSV */ + char buf1[1024], buf2[1024]; + double value, digits = 9.123456789012345678901234567890123456789; + int i, j, r1, r2, failed = 0, num = 0; + +/* + * Use -DTEST_NILS in order to also test the conversion of nil values. Might + * segfault on systems which don't support converting a NULL pointer with "%s" + * and lets some test cases fail against BSD and glibc due to bugs in their + * implementations. + */ +#ifndef TEST_NILS +#define TEST_NILS 0 +#elif TEST_NILS +#undef TEST_NILS +#define TEST_NILS 1 +#endif /* !defined(TEST_NILS) */ +#ifdef TEST +#undef TEST +#endif /* defined(TEST) */ +#define TEST(fmt, val) \ +do { \ + for (i = 0; fmt[i] != NULL; i++) \ + for (j = 0; j == 0 || val[j - TEST_NILS] != 0; j++) { \ + r1 = sprintf(buf1, fmt[i], val[j]); \ + r2 = snprintf(buf2, sizeof(buf2), fmt[i], val[j]); \ + if (strcmp(buf1, buf2) != 0 || r1 != r2) { \ + (void)printf("Results don't match, " \ + "format string: %s\n" \ + "\t sprintf(3): [%s] (%d)\n" \ + "\tsnprintf(3): [%s] (%d)\n", \ + fmt[i], buf1, r1, buf2, r2); \ + failed++; \ + } \ + num++; \ + } \ +} while (/* CONSTCOND */ 0) + +#if HAVE_LOCALE_H + (void)setlocale(LC_ALL, ""); +#endif /* HAVE_LOCALE_H */ + + (void)puts("Testing our snprintf(3) against your system's sprintf(3)."); + TEST(float_fmt, float_val); + TEST(long_fmt, long_val); + TEST(ulong_fmt, ulong_val); + TEST(llong_fmt, llong_val); + TEST(string_fmt, string_val); +#if !OS_SYSV /* SysV uses a different format than we do. */ + TEST(pointer_fmt, pointer_val); +#endif /* !OS_SYSV */ + (void)printf("Result: %d out of %d tests failed.\n", failed, num); + + (void)fputs("Checking how many digits we support: ", stdout); + for (i = 0; i < 100; i++) { + value = pow(10, i) * digits; + (void)sprintf(buf1, "%.1f", value); + (void)snprintf(buf2, sizeof(buf2), "%.1f", value); + if (strcmp(buf1, buf2) != 0) { + (void)printf("apparently %d.\n", i); + break; + } + } + return (failed == 0) ? 0 : 1; +} +#endif /* TEST_SNPRINTF */ + +#endif // KONAN_INTERNAL_SNPRINTF +/* vim: set joinspaces noexpandtab textwidth=80 cinoptions=(4,u0: */ diff --git a/kotlin-native/runtime/src/main/cpp/utf8.h b/kotlin-native/runtime/src/main/cpp/utf8.h new file mode 100644 index 00000000000..8c7a1dc694c --- /dev/null +++ b/kotlin-native/runtime/src/main/cpp/utf8.h @@ -0,0 +1,38 @@ +// Copyright 2006 Nemanja Trifunovic + +/* +Permission is hereby granted, free of charge, to any person or organization +obtaining a copy of the software and accompanying documentation covered by +this license (the "Software") to use, reproduce, display, distribute, +execute, and transmit the Software, and to prepare derivative works of the +Software, and to permit third-parties to whom the Software is furnished to +do so, all subject to the following: + +The copyright notices in the Software and this entire statement, including +the above license grant, this restriction and the following disclaimer, +must be included in all copies of the Software, in whole or in part, and +all derivative works of the Software, unless such copies or derivative +works are solely in the form of machine-executable object code generated by +a source language processor. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +DEALINGS IN THE SOFTWARE. +*/ + + +#ifndef UTF8_FOR_CPP_2675DCD0_9480_4c0c_B92A_CC14C027B731 +#define UTF8_FOR_CPP_2675DCD0_9480_4c0c_B92A_CC14C027B731 + +#include "utf8/unchecked.h" +#include "utf8/with_replacement.h" + +#if !KONAN_NO_EXCEPTIONS +#include "utf8/checked.h" +#endif + +#endif // header guard diff --git a/kotlin-native/runtime/src/main/cpp/utf8/checked.h b/kotlin-native/runtime/src/main/cpp/utf8/checked.h new file mode 100644 index 00000000000..32bde58a090 --- /dev/null +++ b/kotlin-native/runtime/src/main/cpp/utf8/checked.h @@ -0,0 +1,341 @@ +// Copyright 2006 Nemanja Trifunovic + +/* +Permission is hereby granted, free of charge, to any person or organization +obtaining a copy of the software and accompanying documentation covered by +this license (the "Software") to use, reproduce, display, distribute, +execute, and transmit the Software, and to prepare derivative works of the +Software, and to permit third-parties to whom the Software is furnished to +do so, all subject to the following: + +The copyright notices in the Software and this entire statement, including +the above license grant, this restriction and the following disclaimer, +must be included in all copies of the Software, in whole or in part, and +all derivative works of the Software, unless such copies or derivative +works are solely in the form of machine-executable object code generated by +a source language processor. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +DEALINGS IN THE SOFTWARE. +*/ + + +#ifndef UTF8_FOR_CPP_CHECKED_H_2675DCD0_9480_4c0c_B92A_CC14C027B731 +#define UTF8_FOR_CPP_CHECKED_H_2675DCD0_9480_4c0c_B92A_CC14C027B731 + +#include "core.h" +#include + +namespace utf8 +{ + // Base for the exceptions that may be thrown from the library + class exception : public ::std::exception { + }; + + // Exceptions that may be thrown from the library functions. + class invalid_code_point : public exception { + uint32_t cp; + public: + invalid_code_point(uint32_t cp) : cp(cp) {} + virtual const char* what() const throw() { return "Invalid code point"; } + uint32_t code_point() const {return cp;} + }; + + class invalid_utf8 : public exception { + uint8_t u8; + public: + invalid_utf8 (uint8_t u) : u8(u) {} + virtual const char* what() const throw() { return "Invalid UTF-8"; } + uint8_t utf8_octet() const {return u8;} + }; + + class invalid_utf16 : public exception { + uint16_t u16; + public: + invalid_utf16 (uint16_t u) : u16(u) {} + virtual const char* what() const throw() { return "Invalid UTF-16"; } + uint16_t utf16_word() const {return u16;} + }; + + class not_enough_room : public exception { + public: + virtual const char* what() const throw() { return "Not enough space"; } + }; + + /// The library API - functions intended to be called by the users + + template + octet_iterator append(uint32_t cp, octet_iterator result) + { + if (!utf8::internal::is_code_point_valid(cp)) + throw invalid_code_point(cp); + + if (cp < 0x80) // one octet + *(result++) = static_cast(cp); + else if (cp < 0x800) { // two octets + *(result++) = static_cast((cp >> 6) | 0xc0); + *(result++) = static_cast((cp & 0x3f) | 0x80); + } + else if (cp < 0x10000) { // three octets + *(result++) = static_cast((cp >> 12) | 0xe0); + *(result++) = static_cast(((cp >> 6) & 0x3f) | 0x80); + *(result++) = static_cast((cp & 0x3f) | 0x80); + } + else { // four octets + *(result++) = static_cast((cp >> 18) | 0xf0); + *(result++) = static_cast(((cp >> 12) & 0x3f) | 0x80); + *(result++) = static_cast(((cp >> 6) & 0x3f) | 0x80); + *(result++) = static_cast((cp & 0x3f) | 0x80); + } + return result; + } + + template + output_iterator replace_invalid(octet_iterator start, octet_iterator end, output_iterator out, uint32_t replacement) + { + while (start != end) { + octet_iterator sequence_start = start; + internal::utf_error err_code = utf8::internal::validate_next(start, end); + switch (err_code) { + case internal::UTF8_OK : + for (octet_iterator it = sequence_start; it != start; ++it) + *out++ = *it; + break; + case internal::NOT_ENOUGH_ROOM: + throw not_enough_room(); + case internal::INVALID_LEAD: + out = utf8::append (replacement, out); + ++start; + break; + case internal::INCOMPLETE_SEQUENCE: + case internal::OVERLONG_SEQUENCE: + case internal::INVALID_CODE_POINT: + out = utf8::append (replacement, out); + ++start; + // just one replacement mark for the sequence + while (start != end && utf8::internal::is_trail(*start)) + ++start; + break; + } + } + return out; + } + + template + inline output_iterator replace_invalid(octet_iterator start, octet_iterator end, output_iterator out) + { + static const uint32_t replacement_marker = utf8::internal::mask16(0xfffd); + return utf8::replace_invalid(start, end, out, replacement_marker); + } + + template + uint32_t next(octet_iterator& it, octet_iterator end) + { + uint32_t cp = 0; + internal::utf_error err_code = utf8::internal::validate_next(it, end, cp); + switch (err_code) { + case internal::UTF8_OK : + break; + case internal::NOT_ENOUGH_ROOM : + throw not_enough_room(); + case internal::INVALID_LEAD : + case internal::INCOMPLETE_SEQUENCE : + case internal::OVERLONG_SEQUENCE : + throw invalid_utf8(*it); + case internal::INVALID_CODE_POINT : + throw invalid_code_point(cp); + } + return cp; + } + + template + uint32_t peek_next(octet_iterator it, octet_iterator end) + { + return utf8::next(it, end); + } + + template + uint32_t prior(octet_iterator& it, octet_iterator start) + { + // can't do much if it == start + if (it == start) + throw not_enough_room(); + + octet_iterator end = it; + // Go back until we hit either a lead octet or start + while (utf8::internal::is_trail(*(--it))) + if (it == start) + throw invalid_utf8(*it); // error - no lead byte in the sequence + return utf8::peek_next(it, end); + } + + /// Deprecated in versions that include "prior" + template + uint32_t previous(octet_iterator& it, octet_iterator pass_start) + { + octet_iterator end = it; + while (utf8::internal::is_trail(*(--it))) + if (it == pass_start) + throw invalid_utf8(*it); // error - no lead byte in the sequence + octet_iterator temp = it; + return utf8::next(temp, end); + } + + template + void advance (octet_iterator& it, distance_type n, octet_iterator end) + { + for (distance_type i = 0; i < n; ++i) + utf8::next(it, end); + } + + /** + * Calculates a count of characters needed to represent the string from first to last in UTF-16 + * taking into account surrogate symbols. Throws an exception if the input is invalid. + */ + template + uint32_t utf16_length(octet_iterator first, octet_iterator last) { + uint32_t dist = 0; + while(first < last) { + uint32_t cp = utf8::next(first, last); + dist += (cp > 0xffff) ? 2 : 1; + } + return dist; + } + + template + typename std::iterator_traits::difference_type + distance (octet_iterator first, octet_iterator last) + { + typename std::iterator_traits::difference_type dist; + for (dist = 0; first < last; ++dist) + utf8::next(first, last); + return dist; + } + + template + octet_iterator utf16to8 (u16bit_iterator start, u16bit_iterator end, octet_iterator result) + { + while (start != end) { + uint32_t cp = utf8::internal::mask16(*start++); + // Take care of surrogate pairs first + if (utf8::internal::is_lead_surrogate(cp)) { + if (start != end) { + uint32_t trail_surrogate = utf8::internal::mask16(*start++); + if (utf8::internal::is_trail_surrogate(trail_surrogate)) + cp = (cp << 10) + trail_surrogate + internal::SURROGATE_OFFSET; + else + throw invalid_utf16(static_cast(trail_surrogate)); + } + else + throw invalid_utf16(static_cast(cp)); + + } + // Lone trail surrogate + else if (utf8::internal::is_trail_surrogate(cp)) + throw invalid_utf16(static_cast(cp)); + + result = utf8::append(cp, result); + } + return result; + } + + template + u16bit_iterator utf8to16 (octet_iterator start, octet_iterator end, u16bit_iterator result) + { + while (start != end) { + uint32_t cp = utf8::next(start, end); + if (cp > 0xffff) { //make a surrogate pair + *result++ = static_cast((cp >> 10) + internal::LEAD_OFFSET); + *result++ = static_cast((cp & 0x3ff) + internal::TRAIL_SURROGATE_MIN); + } + else + *result++ = static_cast(cp); + } + return result; + } + + template + octet_iterator utf32to8 (u32bit_iterator start, u32bit_iterator end, octet_iterator result) + { + while (start != end) + result = utf8::append(*(start++), result); + + return result; + } + + template + u32bit_iterator utf8to32 (octet_iterator start, octet_iterator end, u32bit_iterator result) + { + while (start != end) + (*result++) = utf8::next(start, end); + + return result; + } + + // The iterator class + template + class iterator : public std::iterator { + octet_iterator it; + octet_iterator range_start; + octet_iterator range_end; + public: + iterator () {} + explicit iterator (const octet_iterator& octet_it, + const octet_iterator& range_start, + const octet_iterator& range_end) : + it(octet_it), range_start(range_start), range_end(range_end) + { + if (it < range_start || it > range_end) + throw std::out_of_range("Invalid utf-8 iterator position"); + } + // the default "big three" are OK + octet_iterator base () const { return it; } + uint32_t operator * () const + { + octet_iterator temp = it; + return utf8::next(temp, range_end); + } + bool operator == (const iterator& rhs) const + { + if (range_start != rhs.range_start || range_end != rhs.range_end) + throw std::logic_error("Comparing utf-8 iterators defined with different ranges"); + return (it == rhs.it); + } + bool operator != (const iterator& rhs) const + { + return !(operator == (rhs)); + } + iterator& operator ++ () + { + utf8::next(it, range_end); + return *this; + } + iterator operator ++ (int) + { + iterator temp = *this; + utf8::next(it, range_end); + return temp; + } + iterator& operator -- () + { + utf8::prior(it, range_start); + return *this; + } + iterator operator -- (int) + { + iterator temp = *this; + utf8::prior(it, range_start); + return temp; + } + }; // class iterator + +} // namespace utf8 + +#endif //header guard + + diff --git a/kotlin-native/runtime/src/main/cpp/utf8/core.h b/kotlin-native/runtime/src/main/cpp/utf8/core.h new file mode 100644 index 00000000000..f27b3c494f1 --- /dev/null +++ b/kotlin-native/runtime/src/main/cpp/utf8/core.h @@ -0,0 +1,340 @@ +// Copyright 2006 Nemanja Trifunovic + +/* +Permission is hereby granted, free of charge, to any person or organization +obtaining a copy of the software and accompanying documentation covered by +this license (the "Software") to use, reproduce, display, distribute, +execute, and transmit the Software, and to prepare derivative works of the +Software, and to permit third-parties to whom the Software is furnished to +do so, all subject to the following: + +The copyright notices in the Software and this entire statement, including +the above license grant, this restriction and the following disclaimer, +must be included in all copies of the Software, in whole or in part, and +all derivative works of the Software, unless such copies or derivative +works are solely in the form of machine-executable object code generated by +a source language processor. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +DEALINGS IN THE SOFTWARE. +*/ + + +#ifndef UTF8_FOR_CPP_CORE_H_2675DCD0_9480_4c0c_B92A_CC14C027B731 +#define UTF8_FOR_CPP_CORE_H_2675DCD0_9480_4c0c_B92A_CC14C027B731 + +#include + +namespace utf8 +{ + // The typedefs for 8-bit, 16-bit and 32-bit unsigned integers + // You may need to change them to match your system. + // These typedefs have the same names as ones from cstdint, or boost/cstdint + typedef unsigned char uint8_t; + typedef unsigned short uint16_t; + typedef unsigned int uint32_t; + +// Helper code - not intended to be directly called by the library users. May be changed at any time +namespace internal +{ + // Unicode constants + // Leading (high) surrogates: 0xd800 - 0xdbff + // Trailing (low) surrogates: 0xdc00 - 0xdfff + const uint16_t LEAD_SURROGATE_MIN = 0xd800u; + const uint16_t LEAD_SURROGATE_MAX = 0xdbffu; + const uint16_t TRAIL_SURROGATE_MIN = 0xdc00u; + const uint16_t TRAIL_SURROGATE_MAX = 0xdfffu; + const uint16_t LEAD_OFFSET = LEAD_SURROGATE_MIN - (0x10000 >> 10); + const uint32_t SURROGATE_OFFSET = 0x10000u - (LEAD_SURROGATE_MIN << 10) - TRAIL_SURROGATE_MIN; + + // Maximum valid value for a Unicode code point + const uint32_t CODE_POINT_MAX = 0x0010ffffu; + + template + inline uint8_t mask8(octet_type oc) + { + return static_cast(0xff & oc); + } + template + inline uint16_t mask16(u16_type oc) + { + return static_cast(0xffff & oc); + } + template + inline bool is_trail(octet_type oc) + { + return ((utf8::internal::mask8(oc) >> 6) == 0x2); + } + + template + inline bool is_lead_surrogate(u16 cp) + { + return (cp >= LEAD_SURROGATE_MIN && cp <= LEAD_SURROGATE_MAX); + } + + template + inline bool is_trail_surrogate(u16 cp) + { + return (cp >= TRAIL_SURROGATE_MIN && cp <= TRAIL_SURROGATE_MAX); + } + + template + inline bool is_surrogate(u16 cp) + { + return (cp >= LEAD_SURROGATE_MIN && cp <= TRAIL_SURROGATE_MAX); + } + + template + inline bool is_out_of_unicode_domain(u32 cp) + { + return cp > CODE_POINT_MAX; + } + + template + inline bool is_code_point_valid(u32 cp) + { + return (!utf8::internal::is_out_of_unicode_domain(cp) && !utf8::internal::is_surrogate(cp)); + } + + template + inline typename std::iterator_traits::difference_type + sequence_length(octet_iterator lead_it) + { + uint8_t lead = utf8::internal::mask8(*lead_it); + if (lead < 0x80) + return 1; + else if ((lead >> 5) == 0x6) + return 2; + else if ((lead >> 4) == 0xe) + return 3; + else if ((lead >> 3) == 0x1e) + return 4; + else + return 0; + } + + template + inline bool is_overlong_sequence(uint32_t cp, octet_difference_type length) + { + if (cp < 0x80) { + if (length != 1) + return true; + } + else if (cp < 0x800) { + if (length != 2) + return true; + } + else if (cp < 0x10000) { + if (length != 3) + return true; + } + + return false; + } + + enum utf_error {UTF8_OK, NOT_ENOUGH_ROOM, INVALID_LEAD, INCOMPLETE_SEQUENCE, OVERLONG_SEQUENCE, INVALID_CODE_POINT}; + + /// Helper for get_sequence_x + template + utf_error increase_safely(octet_iterator& it, octet_iterator end) + { + if (++it == end) + return NOT_ENOUGH_ROOM; + + if (!utf8::internal::is_trail(*it)) + return INCOMPLETE_SEQUENCE; + + return UTF8_OK; + } + + #define UTF8_CPP_INCREASE_AND_RETURN_ON_ERROR(IT, END) {utf_error ret = increase_safely(IT, END); if (ret != UTF8_OK) return ret;} + + #define UTF8_CPP_RETURN_ON_OVERLONG_SEQUENCE(CP, LENGTH) {if (utf8::internal::is_overlong_sequence(CP, LENGTH)) return OVERLONG_SEQUENCE;} + + /// get_sequence_x functions decode utf-8 sequences of the length x + template + utf_error get_sequence_1(octet_iterator& it, const octet_iterator end, uint32_t& code_point) + { + if (it == end) + return NOT_ENOUGH_ROOM; + + code_point = utf8::internal::mask8(*it); + + return UTF8_OK; + } + + template + utf_error get_sequence_2(octet_iterator& it, const octet_iterator end, uint32_t& code_point) + { + if (it == end) + return NOT_ENOUGH_ROOM; + + code_point = utf8::internal::mask8(*it); + + UTF8_CPP_INCREASE_AND_RETURN_ON_ERROR(it, end) + + code_point = ((code_point << 6) & 0x7ff) + ((*it) & 0x3f); + + UTF8_CPP_RETURN_ON_OVERLONG_SEQUENCE(code_point, 2) + + return UTF8_OK; + } + + template + utf_error get_sequence_3(octet_iterator& it, const octet_iterator end, uint32_t& code_point) + { + if (it == end) + return NOT_ENOUGH_ROOM; + + code_point = utf8::internal::mask8(*it); + + UTF8_CPP_INCREASE_AND_RETURN_ON_ERROR(it, end) + + code_point = ((code_point << 12) & 0xffff) + ((utf8::internal::mask8(*it) << 6) & 0xfff); + + if (utf8::internal::is_surrogate(code_point)) + return INVALID_CODE_POINT; + + UTF8_CPP_RETURN_ON_OVERLONG_SEQUENCE(code_point, 3) + + UTF8_CPP_INCREASE_AND_RETURN_ON_ERROR(it, end) + + code_point += (*it) & 0x3f; + + return UTF8_OK; + } + + template + utf_error get_sequence_4(octet_iterator& it, const octet_iterator end, uint32_t& code_point) + { + if (it == end) + return NOT_ENOUGH_ROOM; + + code_point = utf8::internal::mask8(*it); + + UTF8_CPP_INCREASE_AND_RETURN_ON_ERROR(it, end) + + code_point = ((code_point << 18) & 0x1fffff) + ((utf8::internal::mask8(*it) << 12) & 0x3ffff); + + if (utf8::internal::is_out_of_unicode_domain(code_point)) + return INVALID_CODE_POINT; + + UTF8_CPP_RETURN_ON_OVERLONG_SEQUENCE(code_point, 4) + + UTF8_CPP_INCREASE_AND_RETURN_ON_ERROR(it, end) + + code_point += (utf8::internal::mask8(*it) << 6) & 0xfff; + + UTF8_CPP_INCREASE_AND_RETURN_ON_ERROR(it, end) + + code_point += (*it) & 0x3f; + + return UTF8_OK; + } + + #undef UTF8_CPP_INCREASE_AND_RETURN_ON_ERROR + + template + utf_error validate_next(octet_iterator& it, const octet_iterator end, uint32_t& code_point) + { + // Save the original value of it so we can go back in case of failure + // Of course, it does not make much sense with i.e. stream iterators + octet_iterator original_it = it; + + uint32_t cp = 0; + // Determine the sequence length based on the lead octet + typedef typename std::iterator_traits::difference_type octet_difference_type; + const octet_difference_type length = utf8::internal::sequence_length(it); + + // Get trail octets and calculate the code point + utf_error err = UTF8_OK; + switch (length) { + case 0: + return INVALID_LEAD; + case 1: + err = utf8::internal::get_sequence_1(it, end, cp); + break; + case 2: + err = utf8::internal::get_sequence_2(it, end, cp); + break; + case 3: + err = utf8::internal::get_sequence_3(it, end, cp); + break; + case 4: + err = utf8::internal::get_sequence_4(it, end, cp); + break; + } + + if (err == UTF8_OK) { + // Decoding succeeded. + code_point = cp; + ++it; + } else { + // Failure branch - restore the original value of the iterator + it = original_it; + } + + return err; + } + + template + inline utf_error validate_next(octet_iterator& it, octet_iterator end) { + uint32_t ignored; + return utf8::internal::validate_next(it, end, ignored); + } + +} // namespace internal + + /// The library API - functions intended to be called by the users + + // Byte order mark + const uint8_t bom[] = {0xef, 0xbb, 0xbf}; + + template + octet_iterator find_invalid(octet_iterator start, octet_iterator end) + { + octet_iterator result = start; + while (result != end) { + utf8::internal::utf_error err_code = utf8::internal::validate_next(result, end); + if (err_code != internal::UTF8_OK) + return result; + } + return result; + } + + template + inline bool is_valid(octet_iterator start, octet_iterator end) + { + return (utf8::find_invalid(start, end) == end); + } + + template + inline bool starts_with_bom (octet_iterator it, octet_iterator end) + { + return ( + ((it != end) && (utf8::internal::mask8(*it++)) == bom[0]) && + ((it != end) && (utf8::internal::mask8(*it++)) == bom[1]) && + ((it != end) && (utf8::internal::mask8(*it)) == bom[2]) + ); + } + + //Deprecated in release 2.3 + template + inline bool is_bom (octet_iterator it) + { + return ( + (utf8::internal::mask8(*it++)) == bom[0] && + (utf8::internal::mask8(*it++)) == bom[1] && + (utf8::internal::mask8(*it)) == bom[2] + ); + } +} // namespace utf8 + +#endif // header guard + + diff --git a/kotlin-native/runtime/src/main/cpp/utf8/unchecked.h b/kotlin-native/runtime/src/main/cpp/utf8/unchecked.h new file mode 100644 index 00000000000..4381f6c395e --- /dev/null +++ b/kotlin-native/runtime/src/main/cpp/utf8/unchecked.h @@ -0,0 +1,242 @@ +// Copyright 2006 Nemanja Trifunovic + +/* +Permission is hereby granted, free of charge, to any person or organization +obtaining a copy of the software and accompanying documentation covered by +this license (the "Software") to use, reproduce, display, distribute, +execute, and transmit the Software, and to prepare derivative works of the +Software, and to permit third-parties to whom the Software is furnished to +do so, all subject to the following: + +The copyright notices in the Software and this entire statement, including +the above license grant, this restriction and the following disclaimer, +must be included in all copies of the Software, in whole or in part, and +all derivative works of the Software, unless such copies or derivative +works are solely in the form of machine-executable object code generated by +a source language processor. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +DEALINGS IN THE SOFTWARE. +*/ + + +#ifndef UTF8_FOR_CPP_UNCHECKED_H_2675DCD0_9480_4c0c_B92A_CC14C027B731 +#define UTF8_FOR_CPP_UNCHECKED_H_2675DCD0_9480_4c0c_B92A_CC14C027B731 + +#include "core.h" + +namespace utf8 +{ + namespace unchecked + { + template + octet_iterator append(uint32_t cp, octet_iterator result) + { + if (cp < 0x80) // one octet + *(result++) = static_cast(cp); + else if (cp < 0x800) { // two octets + *(result++) = static_cast((cp >> 6) | 0xc0); + *(result++) = static_cast((cp & 0x3f) | 0x80); + } + else if (cp < 0x10000) { // three octets + *(result++) = static_cast((cp >> 12) | 0xe0); + *(result++) = static_cast(((cp >> 6) & 0x3f) | 0x80); + *(result++) = static_cast((cp & 0x3f) | 0x80); + } + else { // four octets + *(result++) = static_cast((cp >> 18) | 0xf0); + *(result++) = static_cast(((cp >> 12) & 0x3f)| 0x80); + *(result++) = static_cast(((cp >> 6) & 0x3f) | 0x80); + *(result++) = static_cast((cp & 0x3f) | 0x80); + } + return result; + } + + template + uint32_t next(octet_iterator& it) + { + uint32_t cp = utf8::internal::mask8(*it); + typename std::iterator_traits::difference_type length = utf8::internal::sequence_length(it); + switch (length) { + case 1: + break; + case 2: + it++; + cp = ((cp << 6) & 0x7ff) + ((*it) & 0x3f); + break; + case 3: + ++it; + cp = ((cp << 12) & 0xffff) + ((utf8::internal::mask8(*it) << 6) & 0xfff); + ++it; + cp += (*it) & 0x3f; + break; + case 4: + ++it; + cp = ((cp << 18) & 0x1fffff) + ((utf8::internal::mask8(*it) << 12) & 0x3ffff); + ++it; + cp += (utf8::internal::mask8(*it) << 6) & 0xfff; + ++it; + cp += (*it) & 0x3f; + break; + } + ++it; + return cp; + } + + template + uint32_t peek_next(octet_iterator it) + { + return utf8::unchecked::next(it); + } + + template + uint32_t prior(octet_iterator& it) + { + while (utf8::internal::is_trail(*(--it))) ; + octet_iterator temp = it; + return utf8::unchecked::next(temp); + } + + // Deprecated in versions that include prior, but only for the sake of consistency (see utf8::previous) + template + inline uint32_t previous(octet_iterator& it) + { + return utf8::unchecked::prior(it); + } + + template + void advance (octet_iterator& it, distance_type n) + { + for (distance_type i = 0; i < n; ++i) + utf8::unchecked::next(it); + } + + /** + * Calculates a count of characters needed to represent the string from first to last in UTF-16 + * taking into account surrogate symbols. Doesn't validate the input. + */ + template + uint32_t utf16_length(octet_iterator first, const octet_iterator last) { + uint32_t dist = 0; + while (first < last) { + uint32_t cp = utf8::unchecked::next(first); + dist += (cp > 0xffff) ? 2 : 1; + } + return dist; + } + + template + typename std::iterator_traits::difference_type + distance (octet_iterator first, octet_iterator last) + { + typename std::iterator_traits::difference_type dist; + for (dist = 0; first < last; ++dist) + utf8::unchecked::next(first); + return dist; + } + + template + octet_iterator utf16to8 (u16bit_iterator start, const u16bit_iterator end, octet_iterator result) + { + while (start != end) { + uint32_t cp = utf8::internal::mask16(*start++); + // Take care of surrogate pairs first + if (utf8::internal::is_lead_surrogate(cp)) { + uint32_t trail_surrogate = utf8::internal::mask16(*start++); + cp = (cp << 10) + trail_surrogate + internal::SURROGATE_OFFSET; + } + result = utf8::unchecked::append(cp, result); + } + return result; + } + + template + u16bit_iterator utf8to16 (octet_iterator start, const octet_iterator end, u16bit_iterator result) + { + while (start < end) { + uint32_t cp = utf8::unchecked::next(start); + if (cp > 0xffff) { //make a surrogate pair + *result++ = static_cast((cp >> 10) + internal::LEAD_OFFSET); + *result++ = static_cast((cp & 0x3ff) + internal::TRAIL_SURROGATE_MIN); + } + else + *result++ = static_cast(cp); + } + return result; + } + + template + octet_iterator utf32to8 (u32bit_iterator start, u32bit_iterator end, octet_iterator result) + { + while (start != end) + result = utf8::unchecked::append(*(start++), result); + + return result; + } + + template + u32bit_iterator utf8to32 (octet_iterator start, octet_iterator end, u32bit_iterator result) + { + while (start < end) + (*result++) = utf8::unchecked::next(start); + + return result; + } + + // The iterator class + template + class iterator : public std::iterator { + octet_iterator it; + public: + iterator () {} + explicit iterator (const octet_iterator& octet_it): it(octet_it) {} + // the default "big three" are OK + octet_iterator base () const { return it; } + uint32_t operator * () const + { + octet_iterator temp = it; + return utf8::unchecked::next(temp); + } + bool operator == (const iterator& rhs) const + { + return (it == rhs.it); + } + bool operator != (const iterator& rhs) const + { + return !(operator == (rhs)); + } + iterator& operator ++ () + { + ::std::advance(it, utf8::internal::sequence_length(it)); + return *this; + } + iterator operator ++ (int) + { + iterator temp = *this; + ::std::advance(it, utf8::internal::sequence_length(it)); + return temp; + } + iterator& operator -- () + { + utf8::unchecked::prior(it); + return *this; + } + iterator operator -- (int) + { + iterator temp = *this; + utf8::unchecked::prior(it); + return temp; + } + }; // class iterator + + } // namespace utf8::unchecked +} // namespace utf8 + + +#endif // header guard + diff --git a/kotlin-native/runtime/src/main/cpp/utf8/with_replacement.h b/kotlin-native/runtime/src/main/cpp/utf8/with_replacement.h new file mode 100644 index 00000000000..6347677e31e --- /dev/null +++ b/kotlin-native/runtime/src/main/cpp/utf8/with_replacement.h @@ -0,0 +1,148 @@ +/* + * Copyright 2010-2017 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef UTF_FOR_CPP_WITH_REPLACEMENT_H +#define UTF_FOR_CPP_WITH_REPLACEMENT_H + +#include "core.h" +#include "unchecked.h" + +namespace utf8 { + +namespace with_replacement { + +constexpr uint32_t default_replacement = 0xfffd; + +/* + * Returns the next codepoint replacing any invalid sequence with the replacement codepoint. + */ +template +uint32_t next(octet_iterator &it, const octet_iterator end, uint32_t replacement) { + uint32_t cp = 0; + internal::utf_error err_code = utf8::internal::validate_next(it, end, cp); + switch (err_code) { + case internal::UTF8_OK : + return cp; + case internal::INVALID_LEAD : + case internal::INVALID_CODE_POINT : + case internal::OVERLONG_SEQUENCE : + it++; + return replacement; + case internal::NOT_ENOUGH_ROOM : + case internal::INCOMPLETE_SEQUENCE : + // The whole incomplete sequence is replaced with one replacement codepoint. + for (it++; it < end && utf8::internal::is_trail(*it); it++); + return replacement; + } +} + +// Library API + +/** + * Calculates a count of characters needed to represent the string from first to last in UTF-16 + * taking into account surrogate symbols and invalid sequences. + * Assumes that all invalid sequences in the input will be replaced with `replacement` + * so each invalid sequence increases the result by 1 or 2 depending on `replacement`. + */ +template +uint32_t utf16_length(octet_iterator first, + const octet_iterator last, + const uint32_t replacement = default_replacement) { + uint32_t dist = 0; + while (first < last) { + uint32_t cp = next(first, last, replacement); + dist += (cp > 0xffff) ? 2 : 1; + } + return dist; +} + + +template +typename std::iterator_traits::difference_type +distance(octet_iterator first, const octet_iterator last) { + typename std::iterator_traits::difference_type dist; + uint32_t unused = 0; + for (dist = 0; first < last; dist++) { + next(first, last, unused); + } + return dist; +} + +template +octet_iterator utf16to8(u16bit_iterator start, + const u16bit_iterator end, + octet_iterator result, + const uint32_t replacement) { + while (start != end) { + uint32_t cp = utf8::internal::mask16(*start++); + // Process surrogates. + if (utf8::internal::is_lead_surrogate(cp)) { + if (start != end) { + uint32_t trail_surrogate = utf8::internal::mask16(*start); + if (utf8::internal::is_trail_surrogate(trail_surrogate)) { + // Valid surrogate pair. + cp = (cp << 10) + trail_surrogate + internal::SURROGATE_OFFSET; + start++; + } else { + cp = replacement; // Invalid input: lone lead surrogate. + } + } else { + cp = replacement; // Invalid input: lone lead surrogate at the end of input. + } + } else if (utf8::internal::is_trail_surrogate(cp)) { + cp = replacement; // Invalid input: lone trail surrogate + } + result = utf8::unchecked::append(cp, result); + } + return result; +} + +template +inline octet_iterator utf16to8(u16bit_iterator start, + const u16bit_iterator end, + octet_iterator result) { + return utf16to8(start, end, result, default_replacement); +} + +template +u16bit_iterator utf8to16(octet_iterator start, + const octet_iterator end, + u16bit_iterator result, + const uint32_t replacement) { + while (start != end) { + // The `next` method takes care about replacing invalid sequences. + uint32_t cp = next(start, end, replacement); + if (cp > 0xffff) { //make a surrogate pair + *result++ = static_cast((cp >> 10) + internal::LEAD_OFFSET); + *result++ = static_cast((cp & 0x3ff) + internal::TRAIL_SURROGATE_MIN); + } else + *result++ = static_cast(cp); + } + return result; +} + +template +inline u16bit_iterator utf8to16(octet_iterator start, + const octet_iterator end, + u16bit_iterator result) { + return utf8to16(start, end, result, default_replacement); +} + +} // namespace with_replacement + +} // namespace utf8 + +#endif // UTF_FOR_CPP_WITH_REPLACEMENT_H diff --git a/kotlin-native/runtime/src/main/js/math.js b/kotlin-native/runtime/src/main/js/math.js new file mode 100644 index 00000000000..019aace7d1f --- /dev/null +++ b/kotlin-native/runtime/src/main/js/math.js @@ -0,0 +1,254 @@ +// NOTE: THIS FILE IS AUTO-GENERATED! +// Run ':runtime:generateJsMath' to re-generate it. + +konan.libraries.push ({ + + knjs_get__Math_E: function() { + var result = Math.E; + return doubleToReturnSlot(result); + }, + + knjs_get__Math_LN2: function() { + var result = Math.LN2; + return doubleToReturnSlot(result); + }, + + knjs_get__Math_LN10: function() { + var result = Math.LN10; + return doubleToReturnSlot(result); + }, + + knjs_get__Math_LOG2E: function() { + var result = Math.LOG2E; + return doubleToReturnSlot(result); + }, + + knjs_get__Math_LOG10E: function() { + var result = Math.LOG10E; + return doubleToReturnSlot(result); + }, + + knjs_get__Math_PI: function() { + var result = Math.PI; + return doubleToReturnSlot(result); + }, + + knjs_get__Math_SQRT1_2: function() { + var result = Math.SQRT1_2; + return doubleToReturnSlot(result); + }, + + knjs_get__Math_SQRT2: function() { + var result = Math.SQRT2; + return doubleToReturnSlot(result); + }, + + knjs__Math_abs: function(xUpper, xLower) { + var x = twoIntsToDouble(xUpper, xLower); + var result = Math.abs(x); + return doubleToReturnSlot(result); + }, + + knjs__Math_acos: function(xUpper, xLower) { + var x = twoIntsToDouble(xUpper, xLower); + var result = Math.acos(x); + return doubleToReturnSlot(result); + }, + + knjs__Math_acosh: function(xUpper, xLower) { + var x = twoIntsToDouble(xUpper, xLower); + var result = Math.acosh(x); + return doubleToReturnSlot(result); + }, + + knjs__Math_asin: function(xUpper, xLower) { + var x = twoIntsToDouble(xUpper, xLower); + var result = Math.asin(x); + return doubleToReturnSlot(result); + }, + + knjs__Math_asinh: function(xUpper, xLower) { + var x = twoIntsToDouble(xUpper, xLower); + var result = Math.asinh(x); + return doubleToReturnSlot(result); + }, + + knjs__Math_atan: function(xUpper, xLower) { + var x = twoIntsToDouble(xUpper, xLower); + var result = Math.atan(x); + return doubleToReturnSlot(result); + }, + + knjs__Math_atanh: function(xUpper, xLower) { + var x = twoIntsToDouble(xUpper, xLower); + var result = Math.atanh(x); + return doubleToReturnSlot(result); + }, + + knjs__Math_atan2: function(yUpper, yLower, xUpper, xLower) { + var y = twoIntsToDouble(yUpper, yLower); + var x = twoIntsToDouble(xUpper, xLower); + var result = Math.atan2(y, x); + return doubleToReturnSlot(result); + }, + + knjs__Math_cbrt: function(xUpper, xLower) { + var x = twoIntsToDouble(xUpper, xLower); + var result = Math.cbrt(x); + return doubleToReturnSlot(result); + }, + + knjs__Math_ceil: function(xUpper, xLower) { + var x = twoIntsToDouble(xUpper, xLower); + var result = Math.ceil(x); + return doubleToReturnSlot(result); + }, + + knjs__Math_clz32: function(xUpper, xLower) { + var x = twoIntsToDouble(xUpper, xLower); + var result = Math.clz32(x); + return doubleToReturnSlot(result); + }, + + knjs__Math_cos: function(xUpper, xLower) { + var x = twoIntsToDouble(xUpper, xLower); + var result = Math.cos(x); + return doubleToReturnSlot(result); + }, + + knjs__Math_cosh: function(xUpper, xLower) { + var x = twoIntsToDouble(xUpper, xLower); + var result = Math.cosh(x); + return doubleToReturnSlot(result); + }, + + knjs__Math_exp: function(xUpper, xLower) { + var x = twoIntsToDouble(xUpper, xLower); + var result = Math.exp(x); + return doubleToReturnSlot(result); + }, + + knjs__Math_expm1: function(xUpper, xLower) { + var x = twoIntsToDouble(xUpper, xLower); + var result = Math.expm1(x); + return doubleToReturnSlot(result); + }, + + knjs__Math_floor: function(xUpper, xLower) { + var x = twoIntsToDouble(xUpper, xLower); + var result = Math.floor(x); + return doubleToReturnSlot(result); + }, + + knjs__Math_fround: function(xUpper, xLower) { + var x = twoIntsToDouble(xUpper, xLower); + var result = Math.fround(x); + return doubleToReturnSlot(result); + }, + + knjs__Math_log: function(xUpper, xLower) { + var x = twoIntsToDouble(xUpper, xLower); + var result = Math.log(x); + return doubleToReturnSlot(result); + }, + + knjs__Math_log1p: function(xUpper, xLower) { + var x = twoIntsToDouble(xUpper, xLower); + var result = Math.log1p(x); + return doubleToReturnSlot(result); + }, + + knjs__Math_log10: function(xUpper, xLower) { + var x = twoIntsToDouble(xUpper, xLower); + var result = Math.log10(x); + return doubleToReturnSlot(result); + }, + + knjs__Math_log2: function(xUpper, xLower) { + var x = twoIntsToDouble(xUpper, xLower); + var result = Math.log2(x); + return doubleToReturnSlot(result); + }, + + knjs__Math_pow: function(xUpper, xLower, yUpper, yLower) { + var x = twoIntsToDouble(xUpper, xLower); + var y = twoIntsToDouble(yUpper, yLower); + var result = Math.pow(x, y); + return doubleToReturnSlot(result); + }, + + knjs__Math_random: function() { + var result = Math.random(); + return doubleToReturnSlot(result); + }, + + knjs__Math_round: function(xUpper, xLower) { + var x = twoIntsToDouble(xUpper, xLower); + var result = Math.round(x); + return doubleToReturnSlot(result); + }, + + knjs__Math_sign: function(xUpper, xLower) { + var x = twoIntsToDouble(xUpper, xLower); + var result = Math.sign(x); + return doubleToReturnSlot(result); + }, + + knjs__Math_sin: function(xUpper, xLower) { + var x = twoIntsToDouble(xUpper, xLower); + var result = Math.sin(x); + return doubleToReturnSlot(result); + }, + + knjs__Math_sinh: function(xUpper, xLower) { + var x = twoIntsToDouble(xUpper, xLower); + var result = Math.sinh(x); + return doubleToReturnSlot(result); + }, + + knjs__Math_sqrt: function(xUpper, xLower) { + var x = twoIntsToDouble(xUpper, xLower); + var result = Math.sqrt(x); + return doubleToReturnSlot(result); + }, + + knjs__Math_tan: function(xUpper, xLower) { + var x = twoIntsToDouble(xUpper, xLower); + var result = Math.tan(x); + return doubleToReturnSlot(result); + }, + + knjs__Math_tanh: function(xUpper, xLower) { + var x = twoIntsToDouble(xUpper, xLower); + var result = Math.tanh(x); + return doubleToReturnSlot(result); + }, + + knjs__Math_trunc: function(xUpper, xLower) { + var x = twoIntsToDouble(xUpper, xLower); + var result = Math.trunc(x); + return doubleToReturnSlot(result); + }, + + knjs__Math_hypot: function(xUpper, xLower, yUpper, yLower) { + var x = twoIntsToDouble(xUpper, xLower); + var y = twoIntsToDouble(yUpper, yLower); + var result = Math.hypot(x, y); + return doubleToReturnSlot(result); + }, + + knjs__Math_max: function(xUpper, xLower, yUpper, yLower) { + var x = twoIntsToDouble(xUpper, xLower); + var y = twoIntsToDouble(yUpper, yLower); + var result = Math.max(x, y); + return doubleToReturnSlot(result); + }, + + knjs__Math_min: function(xUpper, xLower, yUpper, yLower) { + var x = twoIntsToDouble(xUpper, xLower); + var y = twoIntsToDouble(yUpper, yLower); + var result = Math.min(x, y); + return doubleToReturnSlot(result); + } +}) + diff --git a/kotlin-native/runtime/src/main/kotlin/generated/_ArraysNative.kt b/kotlin-native/runtime/src/main/kotlin/generated/_ArraysNative.kt new file mode 100644 index 00000000000..6108abb2f27 --- /dev/null +++ b/kotlin-native/runtime/src/main/kotlin/generated/_ArraysNative.kt @@ -0,0 +1,2481 @@ +/* + * Copyright 2010-2020 JetBrains s.r.o. and Kotlin Programming Language contributors. + * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. + */ + +package kotlin.collections + +// +// NOTE: THIS FILE IS AUTO-GENERATED by the GenerateStandardLib.kt +// See: https://github.com/JetBrains/kotlin/tree/master/libraries/stdlib +// + +import kotlin.ranges.contains +import kotlin.ranges.reversed + +/** + * Returns an element at the given [index] or throws an [IndexOutOfBoundsException] if the [index] is out of bounds of this array. + * + * @sample samples.collections.Collections.Elements.elementAt + */ +@kotlin.internal.InlineOnly +public actual inline fun Array.elementAt(index: Int): T { + return get(index) +} + +/** + * Returns an element at the given [index] or throws an [IndexOutOfBoundsException] if the [index] is out of bounds of this array. + * + * @sample samples.collections.Collections.Elements.elementAt + */ +@kotlin.internal.InlineOnly +public actual inline fun ByteArray.elementAt(index: Int): Byte { + return get(index) +} + +/** + * Returns an element at the given [index] or throws an [IndexOutOfBoundsException] if the [index] is out of bounds of this array. + * + * @sample samples.collections.Collections.Elements.elementAt + */ +@kotlin.internal.InlineOnly +public actual inline fun ShortArray.elementAt(index: Int): Short { + return get(index) +} + +/** + * Returns an element at the given [index] or throws an [IndexOutOfBoundsException] if the [index] is out of bounds of this array. + * + * @sample samples.collections.Collections.Elements.elementAt + */ +@kotlin.internal.InlineOnly +public actual inline fun IntArray.elementAt(index: Int): Int { + return get(index) +} + +/** + * Returns an element at the given [index] or throws an [IndexOutOfBoundsException] if the [index] is out of bounds of this array. + * + * @sample samples.collections.Collections.Elements.elementAt + */ +@kotlin.internal.InlineOnly +public actual inline fun LongArray.elementAt(index: Int): Long { + return get(index) +} + +/** + * Returns an element at the given [index] or throws an [IndexOutOfBoundsException] if the [index] is out of bounds of this array. + * + * @sample samples.collections.Collections.Elements.elementAt + */ +@kotlin.internal.InlineOnly +public actual inline fun FloatArray.elementAt(index: Int): Float { + return get(index) +} + +/** + * Returns an element at the given [index] or throws an [IndexOutOfBoundsException] if the [index] is out of bounds of this array. + * + * @sample samples.collections.Collections.Elements.elementAt + */ +@kotlin.internal.InlineOnly +public actual inline fun DoubleArray.elementAt(index: Int): Double { + return get(index) +} + +/** + * Returns an element at the given [index] or throws an [IndexOutOfBoundsException] if the [index] is out of bounds of this array. + * + * @sample samples.collections.Collections.Elements.elementAt + */ +@kotlin.internal.InlineOnly +public actual inline fun BooleanArray.elementAt(index: Int): Boolean { + return get(index) +} + +/** + * Returns an element at the given [index] or throws an [IndexOutOfBoundsException] if the [index] is out of bounds of this array. + * + * @sample samples.collections.Collections.Elements.elementAt + */ +@kotlin.internal.InlineOnly +public actual inline fun CharArray.elementAt(index: Int): Char { + return get(index) +} + +/** + * Returns a [List] that wraps the original array. + */ +public actual fun Array.asList(): List { + return object : AbstractList(), RandomAccess { + override val size: Int get() = this@asList.size + override fun isEmpty(): Boolean = this@asList.isEmpty() + override fun contains(element: T): Boolean = this@asList.contains(element) + override fun get(index: Int): T = this@asList[index] + override fun indexOf(element: T): Int = this@asList.indexOf(element) + override fun lastIndexOf(element: T): Int = this@asList.lastIndexOf(element) + } +} + +/** + * Returns a [List] that wraps the original array. + */ +public actual fun ByteArray.asList(): List { + return object : AbstractList(), RandomAccess { + override val size: Int get() = this@asList.size + override fun isEmpty(): Boolean = this@asList.isEmpty() + override fun contains(element: Byte): Boolean = this@asList.contains(element) + override fun get(index: Int): Byte = this@asList[index] + override fun indexOf(element: Byte): Int = this@asList.indexOf(element) + override fun lastIndexOf(element: Byte): Int = this@asList.lastIndexOf(element) + } +} + +/** + * Returns a [List] that wraps the original array. + */ +public actual fun ShortArray.asList(): List { + return object : AbstractList(), RandomAccess { + override val size: Int get() = this@asList.size + override fun isEmpty(): Boolean = this@asList.isEmpty() + override fun contains(element: Short): Boolean = this@asList.contains(element) + override fun get(index: Int): Short = this@asList[index] + override fun indexOf(element: Short): Int = this@asList.indexOf(element) + override fun lastIndexOf(element: Short): Int = this@asList.lastIndexOf(element) + } +} + +/** + * Returns a [List] that wraps the original array. + */ +public actual fun IntArray.asList(): List { + return object : AbstractList(), RandomAccess { + override val size: Int get() = this@asList.size + override fun isEmpty(): Boolean = this@asList.isEmpty() + override fun contains(element: Int): Boolean = this@asList.contains(element) + override fun get(index: Int): Int = this@asList[index] + override fun indexOf(element: Int): Int = this@asList.indexOf(element) + override fun lastIndexOf(element: Int): Int = this@asList.lastIndexOf(element) + } +} + +/** + * Returns a [List] that wraps the original array. + */ +public actual fun LongArray.asList(): List { + return object : AbstractList(), RandomAccess { + override val size: Int get() = this@asList.size + override fun isEmpty(): Boolean = this@asList.isEmpty() + override fun contains(element: Long): Boolean = this@asList.contains(element) + override fun get(index: Int): Long = this@asList[index] + override fun indexOf(element: Long): Int = this@asList.indexOf(element) + override fun lastIndexOf(element: Long): Int = this@asList.lastIndexOf(element) + } +} + +/** + * Returns a [List] that wraps the original array. + */ +public actual fun FloatArray.asList(): List { + return object : AbstractList(), RandomAccess { + override val size: Int get() = this@asList.size + override fun isEmpty(): Boolean = this@asList.isEmpty() + override fun contains(element: Float): Boolean = this@asList.any { it.toBits() == element.toBits() } + override fun get(index: Int): Float = this@asList[index] + override fun indexOf(element: Float): Int = this@asList.indexOfFirst { it.toBits() == element.toBits() } + override fun lastIndexOf(element: Float): Int = this@asList.indexOfLast { it.toBits() == element.toBits() } + } +} + +/** + * Returns a [List] that wraps the original array. + */ +public actual fun DoubleArray.asList(): List { + return object : AbstractList(), RandomAccess { + override val size: Int get() = this@asList.size + override fun isEmpty(): Boolean = this@asList.isEmpty() + override fun contains(element: Double): Boolean = this@asList.any { it.toBits() == element.toBits() } + override fun get(index: Int): Double = this@asList[index] + override fun indexOf(element: Double): Int = this@asList.indexOfFirst { it.toBits() == element.toBits() } + override fun lastIndexOf(element: Double): Int = this@asList.indexOfLast { it.toBits() == element.toBits() } + } +} + +/** + * Returns a [List] that wraps the original array. + */ +public actual fun BooleanArray.asList(): List { + return object : AbstractList(), RandomAccess { + override val size: Int get() = this@asList.size + override fun isEmpty(): Boolean = this@asList.isEmpty() + override fun contains(element: Boolean): Boolean = this@asList.contains(element) + override fun get(index: Int): Boolean = this@asList[index] + override fun indexOf(element: Boolean): Int = this@asList.indexOf(element) + override fun lastIndexOf(element: Boolean): Int = this@asList.lastIndexOf(element) + } +} + +/** + * Returns a [List] that wraps the original array. + */ +public actual fun CharArray.asList(): List { + return object : AbstractList(), RandomAccess { + override val size: Int get() = this@asList.size + override fun isEmpty(): Boolean = this@asList.isEmpty() + override fun contains(element: Char): Boolean = this@asList.contains(element) + override fun get(index: Int): Char = this@asList[index] + override fun indexOf(element: Char): Int = this@asList.indexOf(element) + override fun lastIndexOf(element: Char): Int = this@asList.lastIndexOf(element) + } +} + +/** + * Returns `true` if the two specified arrays are *deeply* equal to one another, + * i.e. contain the same number of the same elements in the same order. + * + * If two corresponding elements are nested arrays, they are also compared deeply. + * If any of arrays contains itself on any nesting level the behavior is undefined. + * + * The elements of other types are compared for equality with the [equals][Any.equals] function. + * For floating point numbers it means that `NaN` is equal to itself and `-0.0` is not equal to `0.0`. + */ +@SinceKotlin("1.1") +@kotlin.internal.LowPriorityInOverloadResolution +public actual infix fun Array.contentDeepEquals(other: Array): Boolean { + return this.contentDeepEquals(other) +} + +/** + * Returns `true` if the two specified arrays are *deeply* equal to one another, + * i.e. contain the same number of the same elements in the same order. + * + * The specified arrays are also considered deeply equal if both are `null`. + * + * If two corresponding elements are nested arrays, they are also compared deeply. + * If any of arrays contains itself on any nesting level the behavior is undefined. + * + * The elements of other types are compared for equality with the [equals][Any.equals] function. + * For floating point numbers it means that `NaN` is equal to itself and `-0.0` is not equal to `0.0`. + */ +@SinceKotlin("1.4") +public actual infix fun Array?.contentDeepEquals(other: Array?): Boolean { + return contentDeepEqualsImpl(other) +} + +/** + * Returns a hash code based on the contents of this array as if it is [List]. + * Nested arrays are treated as lists too. + * + * If any of arrays contains itself on any nesting level the behavior is undefined. + */ +@SinceKotlin("1.1") +@kotlin.internal.LowPriorityInOverloadResolution +public actual fun Array.contentDeepHashCode(): Int { + return this.contentDeepHashCode() +} + +/** + * Returns a hash code based on the contents of this array as if it is [List]. + * Nested arrays are treated as lists too. + * + * If any of arrays contains itself on any nesting level the behavior is undefined. + */ +@SinceKotlin("1.4") +public actual fun Array?.contentDeepHashCode(): Int { + return contentDeepHashCodeImpl() +} + +/** + * Returns a string representation of the contents of this array as if it is a [List]. + * Nested arrays are treated as lists too. + * + * If any of arrays contains itself on any nesting level that reference + * is rendered as `"[...]"` to prevent recursion. + * + * @sample samples.collections.Arrays.ContentOperations.contentDeepToString + */ +@SinceKotlin("1.1") +@kotlin.internal.LowPriorityInOverloadResolution +public actual fun Array.contentDeepToString(): String { + return this.contentDeepToString() +} + +/** + * Returns a string representation of the contents of this array as if it is a [List]. + * Nested arrays are treated as lists too. + * + * If any of arrays contains itself on any nesting level that reference + * is rendered as `"[...]"` to prevent recursion. + * + * @sample samples.collections.Arrays.ContentOperations.contentDeepToString + */ +@SinceKotlin("1.4") +public actual fun Array?.contentDeepToString(): String { + return contentDeepToStringImpl() +} + +/** + * Returns `true` if the two specified arrays are *structurally* equal to one another, + * i.e. contain the same number of the same elements in the same order. + * + * The elements are compared for equality with the [equals][Any.equals] function. + * For floating point numbers it means that `NaN` is equal to itself and `-0.0` is not equal to `0.0`. + */ +@Deprecated("Use Kotlin compiler 1.4 to avoid deprecation warning.") +@SinceKotlin("1.1") +@DeprecatedSinceKotlin(hiddenSince = "1.4") +public actual infix fun Array.contentEquals(other: Array): Boolean { + return this.contentEquals(other) +} + +/** + * Returns `true` if the two specified arrays are *structurally* equal to one another, + * i.e. contain the same number of the same elements in the same order. + * + * The elements are compared for equality with the [equals][Any.equals] function. + * For floating point numbers it means that `NaN` is equal to itself and `-0.0` is not equal to `0.0`. + */ +@Deprecated("Use Kotlin compiler 1.4 to avoid deprecation warning.") +@SinceKotlin("1.1") +@DeprecatedSinceKotlin(hiddenSince = "1.4") +public actual infix fun ByteArray.contentEquals(other: ByteArray): Boolean { + return this.contentEquals(other) +} + +/** + * Returns `true` if the two specified arrays are *structurally* equal to one another, + * i.e. contain the same number of the same elements in the same order. + * + * The elements are compared for equality with the [equals][Any.equals] function. + * For floating point numbers it means that `NaN` is equal to itself and `-0.0` is not equal to `0.0`. + */ +@Deprecated("Use Kotlin compiler 1.4 to avoid deprecation warning.") +@SinceKotlin("1.1") +@DeprecatedSinceKotlin(hiddenSince = "1.4") +public actual infix fun ShortArray.contentEquals(other: ShortArray): Boolean { + return this.contentEquals(other) +} + +/** + * Returns `true` if the two specified arrays are *structurally* equal to one another, + * i.e. contain the same number of the same elements in the same order. + * + * The elements are compared for equality with the [equals][Any.equals] function. + * For floating point numbers it means that `NaN` is equal to itself and `-0.0` is not equal to `0.0`. + */ +@Deprecated("Use Kotlin compiler 1.4 to avoid deprecation warning.") +@SinceKotlin("1.1") +@DeprecatedSinceKotlin(hiddenSince = "1.4") +public actual infix fun IntArray.contentEquals(other: IntArray): Boolean { + return this.contentEquals(other) +} + +/** + * Returns `true` if the two specified arrays are *structurally* equal to one another, + * i.e. contain the same number of the same elements in the same order. + * + * The elements are compared for equality with the [equals][Any.equals] function. + * For floating point numbers it means that `NaN` is equal to itself and `-0.0` is not equal to `0.0`. + */ +@Deprecated("Use Kotlin compiler 1.4 to avoid deprecation warning.") +@SinceKotlin("1.1") +@DeprecatedSinceKotlin(hiddenSince = "1.4") +public actual infix fun LongArray.contentEquals(other: LongArray): Boolean { + return this.contentEquals(other) +} + +/** + * Returns `true` if the two specified arrays are *structurally* equal to one another, + * i.e. contain the same number of the same elements in the same order. + * + * The elements are compared for equality with the [equals][Any.equals] function. + * For floating point numbers it means that `NaN` is equal to itself and `-0.0` is not equal to `0.0`. + */ +@Deprecated("Use Kotlin compiler 1.4 to avoid deprecation warning.") +@SinceKotlin("1.1") +@DeprecatedSinceKotlin(hiddenSince = "1.4") +public actual infix fun FloatArray.contentEquals(other: FloatArray): Boolean { + return this.contentEquals(other) +} + +/** + * Returns `true` if the two specified arrays are *structurally* equal to one another, + * i.e. contain the same number of the same elements in the same order. + * + * The elements are compared for equality with the [equals][Any.equals] function. + * For floating point numbers it means that `NaN` is equal to itself and `-0.0` is not equal to `0.0`. + */ +@Deprecated("Use Kotlin compiler 1.4 to avoid deprecation warning.") +@SinceKotlin("1.1") +@DeprecatedSinceKotlin(hiddenSince = "1.4") +public actual infix fun DoubleArray.contentEquals(other: DoubleArray): Boolean { + return this.contentEquals(other) +} + +/** + * Returns `true` if the two specified arrays are *structurally* equal to one another, + * i.e. contain the same number of the same elements in the same order. + * + * The elements are compared for equality with the [equals][Any.equals] function. + * For floating point numbers it means that `NaN` is equal to itself and `-0.0` is not equal to `0.0`. + */ +@Deprecated("Use Kotlin compiler 1.4 to avoid deprecation warning.") +@SinceKotlin("1.1") +@DeprecatedSinceKotlin(hiddenSince = "1.4") +public actual infix fun BooleanArray.contentEquals(other: BooleanArray): Boolean { + return this.contentEquals(other) +} + +/** + * Returns `true` if the two specified arrays are *structurally* equal to one another, + * i.e. contain the same number of the same elements in the same order. + * + * The elements are compared for equality with the [equals][Any.equals] function. + * For floating point numbers it means that `NaN` is equal to itself and `-0.0` is not equal to `0.0`. + */ +@Deprecated("Use Kotlin compiler 1.4 to avoid deprecation warning.") +@SinceKotlin("1.1") +@DeprecatedSinceKotlin(hiddenSince = "1.4") +public actual infix fun CharArray.contentEquals(other: CharArray): Boolean { + return this.contentEquals(other) +} + +/** + * Returns `true` if the two specified arrays are *structurally* equal to one another, + * i.e. contain the same number of the same elements in the same order. + * + * The elements are compared for equality with the [equals][Any.equals] function. + * For floating point numbers it means that `NaN` is equal to itself and `-0.0` is not equal to `0.0`. + */ +@SinceKotlin("1.4") +public actual infix fun Array?.contentEquals(other: Array?): Boolean { + if (this === other) return true + if (this === null || other === null) return false + if (size != other.size) return false + for (i in indices) { + if (this[i] != other[i]) return false + } + return true +} + +/** + * Returns `true` if the two specified arrays are *structurally* equal to one another, + * i.e. contain the same number of the same elements in the same order. + * + * The elements are compared for equality with the [equals][Any.equals] function. + * For floating point numbers it means that `NaN` is equal to itself and `-0.0` is not equal to `0.0`. + */ +@SinceKotlin("1.4") +public actual infix fun ByteArray?.contentEquals(other: ByteArray?): Boolean { + if (this === other) return true + if (this === null || other === null) return false + if (size != other.size) return false + for (i in indices) { + if (this[i] != other[i]) return false + } + return true +} + +/** + * Returns `true` if the two specified arrays are *structurally* equal to one another, + * i.e. contain the same number of the same elements in the same order. + * + * The elements are compared for equality with the [equals][Any.equals] function. + * For floating point numbers it means that `NaN` is equal to itself and `-0.0` is not equal to `0.0`. + */ +@SinceKotlin("1.4") +public actual infix fun ShortArray?.contentEquals(other: ShortArray?): Boolean { + if (this === other) return true + if (this === null || other === null) return false + if (size != other.size) return false + for (i in indices) { + if (this[i] != other[i]) return false + } + return true +} + +/** + * Returns `true` if the two specified arrays are *structurally* equal to one another, + * i.e. contain the same number of the same elements in the same order. + * + * The elements are compared for equality with the [equals][Any.equals] function. + * For floating point numbers it means that `NaN` is equal to itself and `-0.0` is not equal to `0.0`. + */ +@SinceKotlin("1.4") +public actual infix fun IntArray?.contentEquals(other: IntArray?): Boolean { + if (this === other) return true + if (this === null || other === null) return false + if (size != other.size) return false + for (i in indices) { + if (this[i] != other[i]) return false + } + return true +} + +/** + * Returns `true` if the two specified arrays are *structurally* equal to one another, + * i.e. contain the same number of the same elements in the same order. + * + * The elements are compared for equality with the [equals][Any.equals] function. + * For floating point numbers it means that `NaN` is equal to itself and `-0.0` is not equal to `0.0`. + */ +@SinceKotlin("1.4") +public actual infix fun LongArray?.contentEquals(other: LongArray?): Boolean { + if (this === other) return true + if (this === null || other === null) return false + if (size != other.size) return false + for (i in indices) { + if (this[i] != other[i]) return false + } + return true +} + +/** + * Returns `true` if the two specified arrays are *structurally* equal to one another, + * i.e. contain the same number of the same elements in the same order. + * + * The elements are compared for equality with the [equals][Any.equals] function. + * For floating point numbers it means that `NaN` is equal to itself and `-0.0` is not equal to `0.0`. + */ +@SinceKotlin("1.4") +public actual infix fun FloatArray?.contentEquals(other: FloatArray?): Boolean { + if (this === other) return true + if (this === null || other === null) return false + if (size != other.size) return false + for (i in indices) { + if (!this[i].equals(other[i])) return false + } + return true +} + +/** + * Returns `true` if the two specified arrays are *structurally* equal to one another, + * i.e. contain the same number of the same elements in the same order. + * + * The elements are compared for equality with the [equals][Any.equals] function. + * For floating point numbers it means that `NaN` is equal to itself and `-0.0` is not equal to `0.0`. + */ +@SinceKotlin("1.4") +public actual infix fun DoubleArray?.contentEquals(other: DoubleArray?): Boolean { + if (this === other) return true + if (this === null || other === null) return false + if (size != other.size) return false + for (i in indices) { + if (!this[i].equals(other[i])) return false + } + return true +} + +/** + * Returns `true` if the two specified arrays are *structurally* equal to one another, + * i.e. contain the same number of the same elements in the same order. + * + * The elements are compared for equality with the [equals][Any.equals] function. + * For floating point numbers it means that `NaN` is equal to itself and `-0.0` is not equal to `0.0`. + */ +@SinceKotlin("1.4") +public actual infix fun BooleanArray?.contentEquals(other: BooleanArray?): Boolean { + if (this === other) return true + if (this === null || other === null) return false + if (size != other.size) return false + for (i in indices) { + if (this[i] != other[i]) return false + } + return true +} + +/** + * Returns `true` if the two specified arrays are *structurally* equal to one another, + * i.e. contain the same number of the same elements in the same order. + * + * The elements are compared for equality with the [equals][Any.equals] function. + * For floating point numbers it means that `NaN` is equal to itself and `-0.0` is not equal to `0.0`. + */ +@SinceKotlin("1.4") +public actual infix fun CharArray?.contentEquals(other: CharArray?): Boolean { + if (this === other) return true + if (this === null || other === null) return false + if (size != other.size) return false + for (i in indices) { + if (this[i] != other[i]) return false + } + return true +} + +/** + * Returns a hash code based on the contents of this array as if it is [List]. + */ +@Deprecated("Use Kotlin compiler 1.4 to avoid deprecation warning.") +@SinceKotlin("1.1") +@DeprecatedSinceKotlin(hiddenSince = "1.4") +public actual fun Array.contentHashCode(): Int { + return this.contentHashCode() +} + +/** + * Returns a hash code based on the contents of this array as if it is [List]. + */ +@Deprecated("Use Kotlin compiler 1.4 to avoid deprecation warning.") +@SinceKotlin("1.1") +@DeprecatedSinceKotlin(hiddenSince = "1.4") +public actual fun ByteArray.contentHashCode(): Int { + return this.contentHashCode() +} + +/** + * Returns a hash code based on the contents of this array as if it is [List]. + */ +@Deprecated("Use Kotlin compiler 1.4 to avoid deprecation warning.") +@SinceKotlin("1.1") +@DeprecatedSinceKotlin(hiddenSince = "1.4") +public actual fun ShortArray.contentHashCode(): Int { + return this.contentHashCode() +} + +/** + * Returns a hash code based on the contents of this array as if it is [List]. + */ +@Deprecated("Use Kotlin compiler 1.4 to avoid deprecation warning.") +@SinceKotlin("1.1") +@DeprecatedSinceKotlin(hiddenSince = "1.4") +public actual fun IntArray.contentHashCode(): Int { + return this.contentHashCode() +} + +/** + * Returns a hash code based on the contents of this array as if it is [List]. + */ +@Deprecated("Use Kotlin compiler 1.4 to avoid deprecation warning.") +@SinceKotlin("1.1") +@DeprecatedSinceKotlin(hiddenSince = "1.4") +public actual fun LongArray.contentHashCode(): Int { + return this.contentHashCode() +} + +/** + * Returns a hash code based on the contents of this array as if it is [List]. + */ +@Deprecated("Use Kotlin compiler 1.4 to avoid deprecation warning.") +@SinceKotlin("1.1") +@DeprecatedSinceKotlin(hiddenSince = "1.4") +public actual fun FloatArray.contentHashCode(): Int { + return this.contentHashCode() +} + +/** + * Returns a hash code based on the contents of this array as if it is [List]. + */ +@Deprecated("Use Kotlin compiler 1.4 to avoid deprecation warning.") +@SinceKotlin("1.1") +@DeprecatedSinceKotlin(hiddenSince = "1.4") +public actual fun DoubleArray.contentHashCode(): Int { + return this.contentHashCode() +} + +/** + * Returns a hash code based on the contents of this array as if it is [List]. + */ +@Deprecated("Use Kotlin compiler 1.4 to avoid deprecation warning.") +@SinceKotlin("1.1") +@DeprecatedSinceKotlin(hiddenSince = "1.4") +public actual fun BooleanArray.contentHashCode(): Int { + return this.contentHashCode() +} + +/** + * Returns a hash code based on the contents of this array as if it is [List]. + */ +@Deprecated("Use Kotlin compiler 1.4 to avoid deprecation warning.") +@SinceKotlin("1.1") +@DeprecatedSinceKotlin(hiddenSince = "1.4") +public actual fun CharArray.contentHashCode(): Int { + return this.contentHashCode() +} + +/** + * Returns a hash code based on the contents of this array as if it is [List]. + */ +@SinceKotlin("1.4") +public actual fun Array?.contentHashCode(): Int { + if (this === null) return 0 + var result = 1 + for (element in this) + result = 31 * result + element.hashCode() + return result +} + +/** + * Returns a hash code based on the contents of this array as if it is [List]. + */ +@SinceKotlin("1.4") +public actual fun ByteArray?.contentHashCode(): Int { + if (this === null) return 0 + var result = 1 + for (element in this) + result = 31 * result + element.hashCode() + return result +} + +/** + * Returns a hash code based on the contents of this array as if it is [List]. + */ +@SinceKotlin("1.4") +public actual fun ShortArray?.contentHashCode(): Int { + if (this === null) return 0 + var result = 1 + for (element in this) + result = 31 * result + element.hashCode() + return result +} + +/** + * Returns a hash code based on the contents of this array as if it is [List]. + */ +@SinceKotlin("1.4") +public actual fun IntArray?.contentHashCode(): Int { + if (this === null) return 0 + var result = 1 + for (element in this) + result = 31 * result + element.hashCode() + return result +} + +/** + * Returns a hash code based on the contents of this array as if it is [List]. + */ +@SinceKotlin("1.4") +public actual fun LongArray?.contentHashCode(): Int { + if (this === null) return 0 + var result = 1 + for (element in this) + result = 31 * result + element.hashCode() + return result +} + +/** + * Returns a hash code based on the contents of this array as if it is [List]. + */ +@SinceKotlin("1.4") +public actual fun FloatArray?.contentHashCode(): Int { + if (this === null) return 0 + var result = 1 + for (element in this) + result = 31 * result + element.hashCode() + return result +} + +/** + * Returns a hash code based on the contents of this array as if it is [List]. + */ +@SinceKotlin("1.4") +public actual fun DoubleArray?.contentHashCode(): Int { + if (this === null) return 0 + var result = 1 + for (element in this) + result = 31 * result + element.hashCode() + return result +} + +/** + * Returns a hash code based on the contents of this array as if it is [List]. + */ +@SinceKotlin("1.4") +public actual fun BooleanArray?.contentHashCode(): Int { + if (this === null) return 0 + var result = 1 + for (element in this) + result = 31 * result + element.hashCode() + return result +} + +/** + * Returns a hash code based on the contents of this array as if it is [List]. + */ +@SinceKotlin("1.4") +public actual fun CharArray?.contentHashCode(): Int { + if (this === null) return 0 + var result = 1 + for (element in this) + result = 31 * result + element.hashCode() + return result +} + +/** + * Returns a string representation of the contents of the specified array as if it is [List]. + * + * @sample samples.collections.Arrays.ContentOperations.contentToString + */ +@Deprecated("Use Kotlin compiler 1.4 to avoid deprecation warning.") +@SinceKotlin("1.1") +@DeprecatedSinceKotlin(hiddenSince = "1.4") +public actual fun Array.contentToString(): String { + return this.contentToString() +} + +/** + * Returns a string representation of the contents of the specified array as if it is [List]. + * + * @sample samples.collections.Arrays.ContentOperations.contentToString + */ +@Deprecated("Use Kotlin compiler 1.4 to avoid deprecation warning.") +@SinceKotlin("1.1") +@DeprecatedSinceKotlin(hiddenSince = "1.4") +public actual fun ByteArray.contentToString(): String { + return this.contentToString() +} + +/** + * Returns a string representation of the contents of the specified array as if it is [List]. + * + * @sample samples.collections.Arrays.ContentOperations.contentToString + */ +@Deprecated("Use Kotlin compiler 1.4 to avoid deprecation warning.") +@SinceKotlin("1.1") +@DeprecatedSinceKotlin(hiddenSince = "1.4") +public actual fun ShortArray.contentToString(): String { + return this.contentToString() +} + +/** + * Returns a string representation of the contents of the specified array as if it is [List]. + * + * @sample samples.collections.Arrays.ContentOperations.contentToString + */ +@Deprecated("Use Kotlin compiler 1.4 to avoid deprecation warning.") +@SinceKotlin("1.1") +@DeprecatedSinceKotlin(hiddenSince = "1.4") +public actual fun IntArray.contentToString(): String { + return this.contentToString() +} + +/** + * Returns a string representation of the contents of the specified array as if it is [List]. + * + * @sample samples.collections.Arrays.ContentOperations.contentToString + */ +@Deprecated("Use Kotlin compiler 1.4 to avoid deprecation warning.") +@SinceKotlin("1.1") +@DeprecatedSinceKotlin(hiddenSince = "1.4") +public actual fun LongArray.contentToString(): String { + return this.contentToString() +} + +/** + * Returns a string representation of the contents of the specified array as if it is [List]. + * + * @sample samples.collections.Arrays.ContentOperations.contentToString + */ +@Deprecated("Use Kotlin compiler 1.4 to avoid deprecation warning.") +@SinceKotlin("1.1") +@DeprecatedSinceKotlin(hiddenSince = "1.4") +public actual fun FloatArray.contentToString(): String { + return this.contentToString() +} + +/** + * Returns a string representation of the contents of the specified array as if it is [List]. + * + * @sample samples.collections.Arrays.ContentOperations.contentToString + */ +@Deprecated("Use Kotlin compiler 1.4 to avoid deprecation warning.") +@SinceKotlin("1.1") +@DeprecatedSinceKotlin(hiddenSince = "1.4") +public actual fun DoubleArray.contentToString(): String { + return this.contentToString() +} + +/** + * Returns a string representation of the contents of the specified array as if it is [List]. + * + * @sample samples.collections.Arrays.ContentOperations.contentToString + */ +@Deprecated("Use Kotlin compiler 1.4 to avoid deprecation warning.") +@SinceKotlin("1.1") +@DeprecatedSinceKotlin(hiddenSince = "1.4") +public actual fun BooleanArray.contentToString(): String { + return this.contentToString() +} + +/** + * Returns a string representation of the contents of the specified array as if it is [List]. + * + * @sample samples.collections.Arrays.ContentOperations.contentToString + */ +@Deprecated("Use Kotlin compiler 1.4 to avoid deprecation warning.") +@SinceKotlin("1.1") +@DeprecatedSinceKotlin(hiddenSince = "1.4") +public actual fun CharArray.contentToString(): String { + return this.contentToString() +} + +/** + * Returns a string representation of the contents of the specified array as if it is [List]. + * + * @sample samples.collections.Arrays.ContentOperations.contentToString + */ +@SinceKotlin("1.4") +public actual fun Array?.contentToString(): String { + return this?.joinToString(", ", "[", "]") ?: "null" +} + +/** + * Returns a string representation of the contents of the specified array as if it is [List]. + * + * @sample samples.collections.Arrays.ContentOperations.contentToString + */ +@SinceKotlin("1.4") +public actual fun ByteArray?.contentToString(): String { + return this?.joinToString(", ", "[", "]") ?: "null" +} + +/** + * Returns a string representation of the contents of the specified array as if it is [List]. + * + * @sample samples.collections.Arrays.ContentOperations.contentToString + */ +@SinceKotlin("1.4") +public actual fun ShortArray?.contentToString(): String { + return this?.joinToString(", ", "[", "]") ?: "null" +} + +/** + * Returns a string representation of the contents of the specified array as if it is [List]. + * + * @sample samples.collections.Arrays.ContentOperations.contentToString + */ +@SinceKotlin("1.4") +public actual fun IntArray?.contentToString(): String { + return this?.joinToString(", ", "[", "]") ?: "null" +} + +/** + * Returns a string representation of the contents of the specified array as if it is [List]. + * + * @sample samples.collections.Arrays.ContentOperations.contentToString + */ +@SinceKotlin("1.4") +public actual fun LongArray?.contentToString(): String { + return this?.joinToString(", ", "[", "]") ?: "null" +} + +/** + * Returns a string representation of the contents of the specified array as if it is [List]. + * + * @sample samples.collections.Arrays.ContentOperations.contentToString + */ +@SinceKotlin("1.4") +public actual fun FloatArray?.contentToString(): String { + return this?.joinToString(", ", "[", "]") ?: "null" +} + +/** + * Returns a string representation of the contents of the specified array as if it is [List]. + * + * @sample samples.collections.Arrays.ContentOperations.contentToString + */ +@SinceKotlin("1.4") +public actual fun DoubleArray?.contentToString(): String { + return this?.joinToString(", ", "[", "]") ?: "null" +} + +/** + * Returns a string representation of the contents of the specified array as if it is [List]. + * + * @sample samples.collections.Arrays.ContentOperations.contentToString + */ +@SinceKotlin("1.4") +public actual fun BooleanArray?.contentToString(): String { + return this?.joinToString(", ", "[", "]") ?: "null" +} + +/** + * Returns a string representation of the contents of the specified array as if it is [List]. + * + * @sample samples.collections.Arrays.ContentOperations.contentToString + */ +@SinceKotlin("1.4") +public actual fun CharArray?.contentToString(): String { + return this?.joinToString(", ", "[", "]") ?: "null" +} + +/** + * Copies this array or its subrange into the [destination] array and returns that array. + * + * It's allowed to pass the same array in the [destination] and even specify the subrange so that it overlaps with the destination range. + * + * @param destination the array to copy to. + * @param destinationOffset the position in the [destination] array to copy to, 0 by default. + * @param startIndex the beginning (inclusive) of the subrange to copy, 0 by default. + * @param endIndex the end (exclusive) of the subrange to copy, size of this array by default. + * + * @throws IndexOutOfBoundsException or [IllegalArgumentException] when [startIndex] or [endIndex] is out of range of this array indices or when `startIndex > endIndex`. + * @throws IndexOutOfBoundsException when the subrange doesn't fit into the [destination] array starting at the specified [destinationOffset], + * or when that index is out of the [destination] array indices range. + * + * @return the [destination] array. + */ +@SinceKotlin("1.3") +@Suppress("ACTUAL_FUNCTION_WITH_DEFAULT_ARGUMENTS") +public actual fun Array.copyInto(destination: Array, destinationOffset: Int = 0, startIndex: Int = 0, endIndex: Int = size): Array { + @Suppress("UNCHECKED_CAST") + arrayCopy(this as Array, startIndex, destination as Array, destinationOffset, endIndex - startIndex) + return destination +} + +/** + * Copies this array or its subrange into the [destination] array and returns that array. + * + * It's allowed to pass the same array in the [destination] and even specify the subrange so that it overlaps with the destination range. + * + * @param destination the array to copy to. + * @param destinationOffset the position in the [destination] array to copy to, 0 by default. + * @param startIndex the beginning (inclusive) of the subrange to copy, 0 by default. + * @param endIndex the end (exclusive) of the subrange to copy, size of this array by default. + * + * @throws IndexOutOfBoundsException or [IllegalArgumentException] when [startIndex] or [endIndex] is out of range of this array indices or when `startIndex > endIndex`. + * @throws IndexOutOfBoundsException when the subrange doesn't fit into the [destination] array starting at the specified [destinationOffset], + * or when that index is out of the [destination] array indices range. + * + * @return the [destination] array. + */ +@SinceKotlin("1.3") +@Suppress("ACTUAL_FUNCTION_WITH_DEFAULT_ARGUMENTS") +public actual fun ByteArray.copyInto(destination: ByteArray, destinationOffset: Int = 0, startIndex: Int = 0, endIndex: Int = size): ByteArray { + arrayCopy(this, startIndex, destination, destinationOffset, endIndex - startIndex) + return destination +} + +/** + * Copies this array or its subrange into the [destination] array and returns that array. + * + * It's allowed to pass the same array in the [destination] and even specify the subrange so that it overlaps with the destination range. + * + * @param destination the array to copy to. + * @param destinationOffset the position in the [destination] array to copy to, 0 by default. + * @param startIndex the beginning (inclusive) of the subrange to copy, 0 by default. + * @param endIndex the end (exclusive) of the subrange to copy, size of this array by default. + * + * @throws IndexOutOfBoundsException or [IllegalArgumentException] when [startIndex] or [endIndex] is out of range of this array indices or when `startIndex > endIndex`. + * @throws IndexOutOfBoundsException when the subrange doesn't fit into the [destination] array starting at the specified [destinationOffset], + * or when that index is out of the [destination] array indices range. + * + * @return the [destination] array. + */ +@SinceKotlin("1.3") +@Suppress("ACTUAL_FUNCTION_WITH_DEFAULT_ARGUMENTS") +public actual fun ShortArray.copyInto(destination: ShortArray, destinationOffset: Int = 0, startIndex: Int = 0, endIndex: Int = size): ShortArray { + arrayCopy(this, startIndex, destination, destinationOffset, endIndex - startIndex) + return destination +} + +/** + * Copies this array or its subrange into the [destination] array and returns that array. + * + * It's allowed to pass the same array in the [destination] and even specify the subrange so that it overlaps with the destination range. + * + * @param destination the array to copy to. + * @param destinationOffset the position in the [destination] array to copy to, 0 by default. + * @param startIndex the beginning (inclusive) of the subrange to copy, 0 by default. + * @param endIndex the end (exclusive) of the subrange to copy, size of this array by default. + * + * @throws IndexOutOfBoundsException or [IllegalArgumentException] when [startIndex] or [endIndex] is out of range of this array indices or when `startIndex > endIndex`. + * @throws IndexOutOfBoundsException when the subrange doesn't fit into the [destination] array starting at the specified [destinationOffset], + * or when that index is out of the [destination] array indices range. + * + * @return the [destination] array. + */ +@SinceKotlin("1.3") +@Suppress("ACTUAL_FUNCTION_WITH_DEFAULT_ARGUMENTS") +public actual fun IntArray.copyInto(destination: IntArray, destinationOffset: Int = 0, startIndex: Int = 0, endIndex: Int = size): IntArray { + arrayCopy(this, startIndex, destination, destinationOffset, endIndex - startIndex) + return destination +} + +/** + * Copies this array or its subrange into the [destination] array and returns that array. + * + * It's allowed to pass the same array in the [destination] and even specify the subrange so that it overlaps with the destination range. + * + * @param destination the array to copy to. + * @param destinationOffset the position in the [destination] array to copy to, 0 by default. + * @param startIndex the beginning (inclusive) of the subrange to copy, 0 by default. + * @param endIndex the end (exclusive) of the subrange to copy, size of this array by default. + * + * @throws IndexOutOfBoundsException or [IllegalArgumentException] when [startIndex] or [endIndex] is out of range of this array indices or when `startIndex > endIndex`. + * @throws IndexOutOfBoundsException when the subrange doesn't fit into the [destination] array starting at the specified [destinationOffset], + * or when that index is out of the [destination] array indices range. + * + * @return the [destination] array. + */ +@SinceKotlin("1.3") +@Suppress("ACTUAL_FUNCTION_WITH_DEFAULT_ARGUMENTS") +public actual fun LongArray.copyInto(destination: LongArray, destinationOffset: Int = 0, startIndex: Int = 0, endIndex: Int = size): LongArray { + arrayCopy(this, startIndex, destination, destinationOffset, endIndex - startIndex) + return destination +} + +/** + * Copies this array or its subrange into the [destination] array and returns that array. + * + * It's allowed to pass the same array in the [destination] and even specify the subrange so that it overlaps with the destination range. + * + * @param destination the array to copy to. + * @param destinationOffset the position in the [destination] array to copy to, 0 by default. + * @param startIndex the beginning (inclusive) of the subrange to copy, 0 by default. + * @param endIndex the end (exclusive) of the subrange to copy, size of this array by default. + * + * @throws IndexOutOfBoundsException or [IllegalArgumentException] when [startIndex] or [endIndex] is out of range of this array indices or when `startIndex > endIndex`. + * @throws IndexOutOfBoundsException when the subrange doesn't fit into the [destination] array starting at the specified [destinationOffset], + * or when that index is out of the [destination] array indices range. + * + * @return the [destination] array. + */ +@SinceKotlin("1.3") +@Suppress("ACTUAL_FUNCTION_WITH_DEFAULT_ARGUMENTS") +public actual fun FloatArray.copyInto(destination: FloatArray, destinationOffset: Int = 0, startIndex: Int = 0, endIndex: Int = size): FloatArray { + arrayCopy(this, startIndex, destination, destinationOffset, endIndex - startIndex) + return destination +} + +/** + * Copies this array or its subrange into the [destination] array and returns that array. + * + * It's allowed to pass the same array in the [destination] and even specify the subrange so that it overlaps with the destination range. + * + * @param destination the array to copy to. + * @param destinationOffset the position in the [destination] array to copy to, 0 by default. + * @param startIndex the beginning (inclusive) of the subrange to copy, 0 by default. + * @param endIndex the end (exclusive) of the subrange to copy, size of this array by default. + * + * @throws IndexOutOfBoundsException or [IllegalArgumentException] when [startIndex] or [endIndex] is out of range of this array indices or when `startIndex > endIndex`. + * @throws IndexOutOfBoundsException when the subrange doesn't fit into the [destination] array starting at the specified [destinationOffset], + * or when that index is out of the [destination] array indices range. + * + * @return the [destination] array. + */ +@SinceKotlin("1.3") +@Suppress("ACTUAL_FUNCTION_WITH_DEFAULT_ARGUMENTS") +public actual fun DoubleArray.copyInto(destination: DoubleArray, destinationOffset: Int = 0, startIndex: Int = 0, endIndex: Int = size): DoubleArray { + arrayCopy(this, startIndex, destination, destinationOffset, endIndex - startIndex) + return destination +} + +/** + * Copies this array or its subrange into the [destination] array and returns that array. + * + * It's allowed to pass the same array in the [destination] and even specify the subrange so that it overlaps with the destination range. + * + * @param destination the array to copy to. + * @param destinationOffset the position in the [destination] array to copy to, 0 by default. + * @param startIndex the beginning (inclusive) of the subrange to copy, 0 by default. + * @param endIndex the end (exclusive) of the subrange to copy, size of this array by default. + * + * @throws IndexOutOfBoundsException or [IllegalArgumentException] when [startIndex] or [endIndex] is out of range of this array indices or when `startIndex > endIndex`. + * @throws IndexOutOfBoundsException when the subrange doesn't fit into the [destination] array starting at the specified [destinationOffset], + * or when that index is out of the [destination] array indices range. + * + * @return the [destination] array. + */ +@SinceKotlin("1.3") +@Suppress("ACTUAL_FUNCTION_WITH_DEFAULT_ARGUMENTS") +public actual fun BooleanArray.copyInto(destination: BooleanArray, destinationOffset: Int = 0, startIndex: Int = 0, endIndex: Int = size): BooleanArray { + arrayCopy(this, startIndex, destination, destinationOffset, endIndex - startIndex) + return destination +} + +/** + * Copies this array or its subrange into the [destination] array and returns that array. + * + * It's allowed to pass the same array in the [destination] and even specify the subrange so that it overlaps with the destination range. + * + * @param destination the array to copy to. + * @param destinationOffset the position in the [destination] array to copy to, 0 by default. + * @param startIndex the beginning (inclusive) of the subrange to copy, 0 by default. + * @param endIndex the end (exclusive) of the subrange to copy, size of this array by default. + * + * @throws IndexOutOfBoundsException or [IllegalArgumentException] when [startIndex] or [endIndex] is out of range of this array indices or when `startIndex > endIndex`. + * @throws IndexOutOfBoundsException when the subrange doesn't fit into the [destination] array starting at the specified [destinationOffset], + * or when that index is out of the [destination] array indices range. + * + * @return the [destination] array. + */ +@SinceKotlin("1.3") +@Suppress("ACTUAL_FUNCTION_WITH_DEFAULT_ARGUMENTS") +public actual fun CharArray.copyInto(destination: CharArray, destinationOffset: Int = 0, startIndex: Int = 0, endIndex: Int = size): CharArray { + arrayCopy(this, startIndex, destination, destinationOffset, endIndex - startIndex) + return destination +} + +/** + * Returns new array which is a copy of the original array. + * + * @sample samples.collections.Arrays.CopyOfOperations.copyOf + */ +public actual fun Array.copyOf(): Array { + return this.copyOfUninitializedElements(size) +} + +/** + * Returns new array which is a copy of the original array. + * + * @sample samples.collections.Arrays.CopyOfOperations.copyOf + */ +public actual fun ByteArray.copyOf(): ByteArray { + return this.copyOfUninitializedElements(size) +} + +/** + * Returns new array which is a copy of the original array. + * + * @sample samples.collections.Arrays.CopyOfOperations.copyOf + */ +public actual fun ShortArray.copyOf(): ShortArray { + return this.copyOfUninitializedElements(size) +} + +/** + * Returns new array which is a copy of the original array. + * + * @sample samples.collections.Arrays.CopyOfOperations.copyOf + */ +public actual fun IntArray.copyOf(): IntArray { + return this.copyOfUninitializedElements(size) +} + +/** + * Returns new array which is a copy of the original array. + * + * @sample samples.collections.Arrays.CopyOfOperations.copyOf + */ +public actual fun LongArray.copyOf(): LongArray { + return this.copyOfUninitializedElements(size) +} + +/** + * Returns new array which is a copy of the original array. + * + * @sample samples.collections.Arrays.CopyOfOperations.copyOf + */ +public actual fun FloatArray.copyOf(): FloatArray { + return this.copyOfUninitializedElements(size) +} + +/** + * Returns new array which is a copy of the original array. + * + * @sample samples.collections.Arrays.CopyOfOperations.copyOf + */ +public actual fun DoubleArray.copyOf(): DoubleArray { + return this.copyOfUninitializedElements(size) +} + +/** + * Returns new array which is a copy of the original array. + * + * @sample samples.collections.Arrays.CopyOfOperations.copyOf + */ +public actual fun BooleanArray.copyOf(): BooleanArray { + return this.copyOfUninitializedElements(size) +} + +/** + * Returns new array which is a copy of the original array. + * + * @sample samples.collections.Arrays.CopyOfOperations.copyOf + */ +public actual fun CharArray.copyOf(): CharArray { + return this.copyOfUninitializedElements(size) +} + +/** + * Returns new array which is a copy of the original array, resized to the given [newSize]. + * The copy is either truncated or padded at the end with zero values if necessary. + * + * - If [newSize] is less than the size of the original array, the copy array is truncated to the [newSize]. + * - If [newSize] is greater than the size of the original array, the extra elements in the copy array are filled with zero values. + * + * @sample samples.collections.Arrays.CopyOfOperations.resizedPrimitiveCopyOf + */ +public actual fun ByteArray.copyOf(newSize: Int): ByteArray { + return this.copyOfUninitializedElements(newSize) +} + +/** + * Returns new array which is a copy of the original array, resized to the given [newSize]. + * The copy is either truncated or padded at the end with zero values if necessary. + * + * - If [newSize] is less than the size of the original array, the copy array is truncated to the [newSize]. + * - If [newSize] is greater than the size of the original array, the extra elements in the copy array are filled with zero values. + * + * @sample samples.collections.Arrays.CopyOfOperations.resizedPrimitiveCopyOf + */ +public actual fun ShortArray.copyOf(newSize: Int): ShortArray { + return this.copyOfUninitializedElements(newSize) +} + +/** + * Returns new array which is a copy of the original array, resized to the given [newSize]. + * The copy is either truncated or padded at the end with zero values if necessary. + * + * - If [newSize] is less than the size of the original array, the copy array is truncated to the [newSize]. + * - If [newSize] is greater than the size of the original array, the extra elements in the copy array are filled with zero values. + * + * @sample samples.collections.Arrays.CopyOfOperations.resizedPrimitiveCopyOf + */ +public actual fun IntArray.copyOf(newSize: Int): IntArray { + return this.copyOfUninitializedElements(newSize) +} + +/** + * Returns new array which is a copy of the original array, resized to the given [newSize]. + * The copy is either truncated or padded at the end with zero values if necessary. + * + * - If [newSize] is less than the size of the original array, the copy array is truncated to the [newSize]. + * - If [newSize] is greater than the size of the original array, the extra elements in the copy array are filled with zero values. + * + * @sample samples.collections.Arrays.CopyOfOperations.resizedPrimitiveCopyOf + */ +public actual fun LongArray.copyOf(newSize: Int): LongArray { + return this.copyOfUninitializedElements(newSize) +} + +/** + * Returns new array which is a copy of the original array, resized to the given [newSize]. + * The copy is either truncated or padded at the end with zero values if necessary. + * + * - If [newSize] is less than the size of the original array, the copy array is truncated to the [newSize]. + * - If [newSize] is greater than the size of the original array, the extra elements in the copy array are filled with zero values. + * + * @sample samples.collections.Arrays.CopyOfOperations.resizedPrimitiveCopyOf + */ +public actual fun FloatArray.copyOf(newSize: Int): FloatArray { + return this.copyOfUninitializedElements(newSize) +} + +/** + * Returns new array which is a copy of the original array, resized to the given [newSize]. + * The copy is either truncated or padded at the end with zero values if necessary. + * + * - If [newSize] is less than the size of the original array, the copy array is truncated to the [newSize]. + * - If [newSize] is greater than the size of the original array, the extra elements in the copy array are filled with zero values. + * + * @sample samples.collections.Arrays.CopyOfOperations.resizedPrimitiveCopyOf + */ +public actual fun DoubleArray.copyOf(newSize: Int): DoubleArray { + return this.copyOfUninitializedElements(newSize) +} + +/** + * Returns new array which is a copy of the original array, resized to the given [newSize]. + * The copy is either truncated or padded at the end with `false` values if necessary. + * + * - If [newSize] is less than the size of the original array, the copy array is truncated to the [newSize]. + * - If [newSize] is greater than the size of the original array, the extra elements in the copy array are filled with `false` values. + * + * @sample samples.collections.Arrays.CopyOfOperations.resizedPrimitiveCopyOf + */ +public actual fun BooleanArray.copyOf(newSize: Int): BooleanArray { + return this.copyOfUninitializedElements(newSize) +} + +/** + * Returns new array which is a copy of the original array, resized to the given [newSize]. + * The copy is either truncated or padded at the end with null char (`\u0000`) values if necessary. + * + * - If [newSize] is less than the size of the original array, the copy array is truncated to the [newSize]. + * - If [newSize] is greater than the size of the original array, the extra elements in the copy array are filled with null char (`\u0000`) values. + * + * @sample samples.collections.Arrays.CopyOfOperations.resizedPrimitiveCopyOf + */ +public actual fun CharArray.copyOf(newSize: Int): CharArray { + return this.copyOfUninitializedElements(newSize) +} + +/** + * Returns new array which is a copy of the original array, resized to the given [newSize]. + * The copy is either truncated or padded at the end with `null` values if necessary. + * + * - If [newSize] is less than the size of the original array, the copy array is truncated to the [newSize]. + * - If [newSize] is greater than the size of the original array, the extra elements in the copy array are filled with `null` values. + * + * @sample samples.collections.Arrays.CopyOfOperations.resizingCopyOf + */ +public actual fun Array.copyOf(newSize: Int): Array { + return this.copyOfNulls(newSize) +} + +/** + * Returns a new array which is a copy of the specified range of the original array. + * + * @param fromIndex the start of the range (inclusive) to copy. + * @param toIndex the end of the range (exclusive) to copy. + * + * @throws IndexOutOfBoundsException if [fromIndex] is less than zero or [toIndex] is greater than the size of this array. + * @throws IllegalArgumentException if [fromIndex] is greater than [toIndex]. + */ +public actual fun Array.copyOfRange(fromIndex: Int, toIndex: Int): Array { + checkCopyOfRangeArguments(fromIndex, toIndex, size) + return copyOfUninitializedElements(fromIndex, toIndex) +} + +/** + * Returns a new array which is a copy of the specified range of the original array. + * + * @param fromIndex the start of the range (inclusive) to copy. + * @param toIndex the end of the range (exclusive) to copy. + * + * @throws IndexOutOfBoundsException if [fromIndex] is less than zero or [toIndex] is greater than the size of this array. + * @throws IllegalArgumentException if [fromIndex] is greater than [toIndex]. + */ +public actual fun ByteArray.copyOfRange(fromIndex: Int, toIndex: Int): ByteArray { + checkCopyOfRangeArguments(fromIndex, toIndex, size) + return copyOfUninitializedElements(fromIndex, toIndex) +} + +/** + * Returns a new array which is a copy of the specified range of the original array. + * + * @param fromIndex the start of the range (inclusive) to copy. + * @param toIndex the end of the range (exclusive) to copy. + * + * @throws IndexOutOfBoundsException if [fromIndex] is less than zero or [toIndex] is greater than the size of this array. + * @throws IllegalArgumentException if [fromIndex] is greater than [toIndex]. + */ +public actual fun ShortArray.copyOfRange(fromIndex: Int, toIndex: Int): ShortArray { + checkCopyOfRangeArguments(fromIndex, toIndex, size) + return copyOfUninitializedElements(fromIndex, toIndex) +} + +/** + * Returns a new array which is a copy of the specified range of the original array. + * + * @param fromIndex the start of the range (inclusive) to copy. + * @param toIndex the end of the range (exclusive) to copy. + * + * @throws IndexOutOfBoundsException if [fromIndex] is less than zero or [toIndex] is greater than the size of this array. + * @throws IllegalArgumentException if [fromIndex] is greater than [toIndex]. + */ +public actual fun IntArray.copyOfRange(fromIndex: Int, toIndex: Int): IntArray { + checkCopyOfRangeArguments(fromIndex, toIndex, size) + return copyOfUninitializedElements(fromIndex, toIndex) +} + +/** + * Returns a new array which is a copy of the specified range of the original array. + * + * @param fromIndex the start of the range (inclusive) to copy. + * @param toIndex the end of the range (exclusive) to copy. + * + * @throws IndexOutOfBoundsException if [fromIndex] is less than zero or [toIndex] is greater than the size of this array. + * @throws IllegalArgumentException if [fromIndex] is greater than [toIndex]. + */ +public actual fun LongArray.copyOfRange(fromIndex: Int, toIndex: Int): LongArray { + checkCopyOfRangeArguments(fromIndex, toIndex, size) + return copyOfUninitializedElements(fromIndex, toIndex) +} + +/** + * Returns a new array which is a copy of the specified range of the original array. + * + * @param fromIndex the start of the range (inclusive) to copy. + * @param toIndex the end of the range (exclusive) to copy. + * + * @throws IndexOutOfBoundsException if [fromIndex] is less than zero or [toIndex] is greater than the size of this array. + * @throws IllegalArgumentException if [fromIndex] is greater than [toIndex]. + */ +public actual fun FloatArray.copyOfRange(fromIndex: Int, toIndex: Int): FloatArray { + checkCopyOfRangeArguments(fromIndex, toIndex, size) + return copyOfUninitializedElements(fromIndex, toIndex) +} + +/** + * Returns a new array which is a copy of the specified range of the original array. + * + * @param fromIndex the start of the range (inclusive) to copy. + * @param toIndex the end of the range (exclusive) to copy. + * + * @throws IndexOutOfBoundsException if [fromIndex] is less than zero or [toIndex] is greater than the size of this array. + * @throws IllegalArgumentException if [fromIndex] is greater than [toIndex]. + */ +public actual fun DoubleArray.copyOfRange(fromIndex: Int, toIndex: Int): DoubleArray { + checkCopyOfRangeArguments(fromIndex, toIndex, size) + return copyOfUninitializedElements(fromIndex, toIndex) +} + +/** + * Returns a new array which is a copy of the specified range of the original array. + * + * @param fromIndex the start of the range (inclusive) to copy. + * @param toIndex the end of the range (exclusive) to copy. + * + * @throws IndexOutOfBoundsException if [fromIndex] is less than zero or [toIndex] is greater than the size of this array. + * @throws IllegalArgumentException if [fromIndex] is greater than [toIndex]. + */ +public actual fun BooleanArray.copyOfRange(fromIndex: Int, toIndex: Int): BooleanArray { + checkCopyOfRangeArguments(fromIndex, toIndex, size) + return copyOfUninitializedElements(fromIndex, toIndex) +} + +/** + * Returns a new array which is a copy of the specified range of the original array. + * + * @param fromIndex the start of the range (inclusive) to copy. + * @param toIndex the end of the range (exclusive) to copy. + * + * @throws IndexOutOfBoundsException if [fromIndex] is less than zero or [toIndex] is greater than the size of this array. + * @throws IllegalArgumentException if [fromIndex] is greater than [toIndex]. + */ +public actual fun CharArray.copyOfRange(fromIndex: Int, toIndex: Int): CharArray { + checkCopyOfRangeArguments(fromIndex, toIndex, size) + return copyOfUninitializedElements(fromIndex, toIndex) +} + +/** + * Returns new array which is a copy of the original array's range between [fromIndex] (inclusive) + * and [toIndex] (exclusive) with new elements filled with **lateinit** _uninitialized_ values. + * Attempts to read _uninitialized_ values from this array work in implementation-dependent manner, + * either throwing exception or returning some kind of implementation-specific default value. + */ +internal fun Array.copyOfUninitializedElements(fromIndex: Int, toIndex: Int): Array { + val newSize = toIndex - fromIndex + if (newSize < 0) { + throw IllegalArgumentException("$fromIndex > $toIndex") + } + val result = arrayOfUninitializedElements(newSize) + this.copyInto(result, 0, fromIndex, toIndex.coerceAtMost(size)) + return result +} + +/** + * Returns new array which is a copy of the original array's range between [fromIndex] (inclusive) + * and [toIndex] (exclusive) with new elements filled with **lateinit** _uninitialized_ values. + * Attempts to read _uninitialized_ values from this array work in implementation-dependent manner, + * either throwing exception or returning some kind of implementation-specific default value. + */ +internal fun ByteArray.copyOfUninitializedElements(fromIndex: Int, toIndex: Int): ByteArray { + val newSize = toIndex - fromIndex + if (newSize < 0) { + throw IllegalArgumentException("$fromIndex > $toIndex") + } + val result = ByteArray(newSize) + this.copyInto(result, 0, fromIndex, toIndex.coerceAtMost(size)) + return result +} + +/** + * Returns new array which is a copy of the original array's range between [fromIndex] (inclusive) + * and [toIndex] (exclusive) with new elements filled with **lateinit** _uninitialized_ values. + * Attempts to read _uninitialized_ values from this array work in implementation-dependent manner, + * either throwing exception or returning some kind of implementation-specific default value. + */ +internal fun ShortArray.copyOfUninitializedElements(fromIndex: Int, toIndex: Int): ShortArray { + val newSize = toIndex - fromIndex + if (newSize < 0) { + throw IllegalArgumentException("$fromIndex > $toIndex") + } + val result = ShortArray(newSize) + this.copyInto(result, 0, fromIndex, toIndex.coerceAtMost(size)) + return result +} + +/** + * Returns new array which is a copy of the original array's range between [fromIndex] (inclusive) + * and [toIndex] (exclusive) with new elements filled with **lateinit** _uninitialized_ values. + * Attempts to read _uninitialized_ values from this array work in implementation-dependent manner, + * either throwing exception or returning some kind of implementation-specific default value. + */ +internal fun IntArray.copyOfUninitializedElements(fromIndex: Int, toIndex: Int): IntArray { + val newSize = toIndex - fromIndex + if (newSize < 0) { + throw IllegalArgumentException("$fromIndex > $toIndex") + } + val result = IntArray(newSize) + this.copyInto(result, 0, fromIndex, toIndex.coerceAtMost(size)) + return result +} + +/** + * Returns new array which is a copy of the original array's range between [fromIndex] (inclusive) + * and [toIndex] (exclusive) with new elements filled with **lateinit** _uninitialized_ values. + * Attempts to read _uninitialized_ values from this array work in implementation-dependent manner, + * either throwing exception or returning some kind of implementation-specific default value. + */ +internal fun LongArray.copyOfUninitializedElements(fromIndex: Int, toIndex: Int): LongArray { + val newSize = toIndex - fromIndex + if (newSize < 0) { + throw IllegalArgumentException("$fromIndex > $toIndex") + } + val result = LongArray(newSize) + this.copyInto(result, 0, fromIndex, toIndex.coerceAtMost(size)) + return result +} + +/** + * Returns new array which is a copy of the original array's range between [fromIndex] (inclusive) + * and [toIndex] (exclusive) with new elements filled with **lateinit** _uninitialized_ values. + * Attempts to read _uninitialized_ values from this array work in implementation-dependent manner, + * either throwing exception or returning some kind of implementation-specific default value. + */ +internal fun FloatArray.copyOfUninitializedElements(fromIndex: Int, toIndex: Int): FloatArray { + val newSize = toIndex - fromIndex + if (newSize < 0) { + throw IllegalArgumentException("$fromIndex > $toIndex") + } + val result = FloatArray(newSize) + this.copyInto(result, 0, fromIndex, toIndex.coerceAtMost(size)) + return result +} + +/** + * Returns new array which is a copy of the original array's range between [fromIndex] (inclusive) + * and [toIndex] (exclusive) with new elements filled with **lateinit** _uninitialized_ values. + * Attempts to read _uninitialized_ values from this array work in implementation-dependent manner, + * either throwing exception or returning some kind of implementation-specific default value. + */ +internal fun DoubleArray.copyOfUninitializedElements(fromIndex: Int, toIndex: Int): DoubleArray { + val newSize = toIndex - fromIndex + if (newSize < 0) { + throw IllegalArgumentException("$fromIndex > $toIndex") + } + val result = DoubleArray(newSize) + this.copyInto(result, 0, fromIndex, toIndex.coerceAtMost(size)) + return result +} + +/** + * Returns new array which is a copy of the original array's range between [fromIndex] (inclusive) + * and [toIndex] (exclusive) with new elements filled with **lateinit** _uninitialized_ values. + * Attempts to read _uninitialized_ values from this array work in implementation-dependent manner, + * either throwing exception or returning some kind of implementation-specific default value. + */ +internal fun BooleanArray.copyOfUninitializedElements(fromIndex: Int, toIndex: Int): BooleanArray { + val newSize = toIndex - fromIndex + if (newSize < 0) { + throw IllegalArgumentException("$fromIndex > $toIndex") + } + val result = BooleanArray(newSize) + this.copyInto(result, 0, fromIndex, toIndex.coerceAtMost(size)) + return result +} + +/** + * Returns new array which is a copy of the original array's range between [fromIndex] (inclusive) + * and [toIndex] (exclusive) with new elements filled with **lateinit** _uninitialized_ values. + * Attempts to read _uninitialized_ values from this array work in implementation-dependent manner, + * either throwing exception or returning some kind of implementation-specific default value. + */ +internal fun CharArray.copyOfUninitializedElements(fromIndex: Int, toIndex: Int): CharArray { + val newSize = toIndex - fromIndex + if (newSize < 0) { + throw IllegalArgumentException("$fromIndex > $toIndex") + } + val result = CharArray(newSize) + this.copyInto(result, 0, fromIndex, toIndex.coerceAtMost(size)) + return result +} + +/** + * Returns new array which is a copy of the original array with new elements filled with **lateinit** _uninitialized_ values. + * Attempts to read _uninitialized_ values from this array work in implementation-dependent manner, + * either throwing exception or returning some kind of implementation-specific default value. + */ +internal fun Array.copyOfUninitializedElements(newSize: Int): Array { + return copyOfUninitializedElements(0, newSize) +} + +/** + * Returns new array which is a copy of the original array with new elements filled with **lateinit** _uninitialized_ values. + * Attempts to read _uninitialized_ values from this array work in implementation-dependent manner, + * either throwing exception or returning some kind of implementation-specific default value. + */ +internal fun ByteArray.copyOfUninitializedElements(newSize: Int): ByteArray { + return copyOfUninitializedElements(0, newSize) +} + +/** + * Returns new array which is a copy of the original array with new elements filled with **lateinit** _uninitialized_ values. + * Attempts to read _uninitialized_ values from this array work in implementation-dependent manner, + * either throwing exception or returning some kind of implementation-specific default value. + */ +internal fun ShortArray.copyOfUninitializedElements(newSize: Int): ShortArray { + return copyOfUninitializedElements(0, newSize) +} + +/** + * Returns new array which is a copy of the original array with new elements filled with **lateinit** _uninitialized_ values. + * Attempts to read _uninitialized_ values from this array work in implementation-dependent manner, + * either throwing exception or returning some kind of implementation-specific default value. + */ +internal fun IntArray.copyOfUninitializedElements(newSize: Int): IntArray { + return copyOfUninitializedElements(0, newSize) +} + +/** + * Returns new array which is a copy of the original array with new elements filled with **lateinit** _uninitialized_ values. + * Attempts to read _uninitialized_ values from this array work in implementation-dependent manner, + * either throwing exception or returning some kind of implementation-specific default value. + */ +internal fun LongArray.copyOfUninitializedElements(newSize: Int): LongArray { + return copyOfUninitializedElements(0, newSize) +} + +/** + * Returns new array which is a copy of the original array with new elements filled with **lateinit** _uninitialized_ values. + * Attempts to read _uninitialized_ values from this array work in implementation-dependent manner, + * either throwing exception or returning some kind of implementation-specific default value. + */ +internal fun FloatArray.copyOfUninitializedElements(newSize: Int): FloatArray { + return copyOfUninitializedElements(0, newSize) +} + +/** + * Returns new array which is a copy of the original array with new elements filled with **lateinit** _uninitialized_ values. + * Attempts to read _uninitialized_ values from this array work in implementation-dependent manner, + * either throwing exception or returning some kind of implementation-specific default value. + */ +internal fun DoubleArray.copyOfUninitializedElements(newSize: Int): DoubleArray { + return copyOfUninitializedElements(0, newSize) +} + +/** + * Returns new array which is a copy of the original array with new elements filled with **lateinit** _uninitialized_ values. + * Attempts to read _uninitialized_ values from this array work in implementation-dependent manner, + * either throwing exception or returning some kind of implementation-specific default value. + */ +internal fun BooleanArray.copyOfUninitializedElements(newSize: Int): BooleanArray { + return copyOfUninitializedElements(0, newSize) +} + +/** + * Returns new array which is a copy of the original array with new elements filled with **lateinit** _uninitialized_ values. + * Attempts to read _uninitialized_ values from this array work in implementation-dependent manner, + * either throwing exception or returning some kind of implementation-specific default value. + */ +internal fun CharArray.copyOfUninitializedElements(newSize: Int): CharArray { + return copyOfUninitializedElements(0, newSize) +} + +/** + * Fills this array or its subrange with the specified [element] value. + * + * @param fromIndex the start of the range (inclusive) to fill, 0 by default. + * @param toIndex the end of the range (exclusive) to fill, size of this array by default. + * + * @throws IndexOutOfBoundsException if [fromIndex] is less than zero or [toIndex] is greater than the size of this array. + * @throws IllegalArgumentException if [fromIndex] is greater than [toIndex]. + */ +@SinceKotlin("1.3") +@Suppress("ACTUAL_FUNCTION_WITH_DEFAULT_ARGUMENTS") +public actual fun Array.fill(element: T, fromIndex: Int = 0, toIndex: Int = size): Unit { + arrayFill(this, fromIndex, toIndex, element) +} + +/** + * Fills this array or its subrange with the specified [element] value. + * + * @param fromIndex the start of the range (inclusive) to fill, 0 by default. + * @param toIndex the end of the range (exclusive) to fill, size of this array by default. + * + * @throws IndexOutOfBoundsException if [fromIndex] is less than zero or [toIndex] is greater than the size of this array. + * @throws IllegalArgumentException if [fromIndex] is greater than [toIndex]. + */ +@SinceKotlin("1.3") +@Suppress("ACTUAL_FUNCTION_WITH_DEFAULT_ARGUMENTS") +public actual fun ByteArray.fill(element: Byte, fromIndex: Int = 0, toIndex: Int = size): Unit { + arrayFill(this, fromIndex, toIndex, element) +} + +/** + * Fills this array or its subrange with the specified [element] value. + * + * @param fromIndex the start of the range (inclusive) to fill, 0 by default. + * @param toIndex the end of the range (exclusive) to fill, size of this array by default. + * + * @throws IndexOutOfBoundsException if [fromIndex] is less than zero or [toIndex] is greater than the size of this array. + * @throws IllegalArgumentException if [fromIndex] is greater than [toIndex]. + */ +@SinceKotlin("1.3") +@Suppress("ACTUAL_FUNCTION_WITH_DEFAULT_ARGUMENTS") +public actual fun ShortArray.fill(element: Short, fromIndex: Int = 0, toIndex: Int = size): Unit { + arrayFill(this, fromIndex, toIndex, element) +} + +/** + * Fills this array or its subrange with the specified [element] value. + * + * @param fromIndex the start of the range (inclusive) to fill, 0 by default. + * @param toIndex the end of the range (exclusive) to fill, size of this array by default. + * + * @throws IndexOutOfBoundsException if [fromIndex] is less than zero or [toIndex] is greater than the size of this array. + * @throws IllegalArgumentException if [fromIndex] is greater than [toIndex]. + */ +@SinceKotlin("1.3") +@Suppress("ACTUAL_FUNCTION_WITH_DEFAULT_ARGUMENTS") +public actual fun IntArray.fill(element: Int, fromIndex: Int = 0, toIndex: Int = size): Unit { + arrayFill(this, fromIndex, toIndex, element) +} + +/** + * Fills this array or its subrange with the specified [element] value. + * + * @param fromIndex the start of the range (inclusive) to fill, 0 by default. + * @param toIndex the end of the range (exclusive) to fill, size of this array by default. + * + * @throws IndexOutOfBoundsException if [fromIndex] is less than zero or [toIndex] is greater than the size of this array. + * @throws IllegalArgumentException if [fromIndex] is greater than [toIndex]. + */ +@SinceKotlin("1.3") +@Suppress("ACTUAL_FUNCTION_WITH_DEFAULT_ARGUMENTS") +public actual fun LongArray.fill(element: Long, fromIndex: Int = 0, toIndex: Int = size): Unit { + arrayFill(this, fromIndex, toIndex, element) +} + +/** + * Fills this array or its subrange with the specified [element] value. + * + * @param fromIndex the start of the range (inclusive) to fill, 0 by default. + * @param toIndex the end of the range (exclusive) to fill, size of this array by default. + * + * @throws IndexOutOfBoundsException if [fromIndex] is less than zero or [toIndex] is greater than the size of this array. + * @throws IllegalArgumentException if [fromIndex] is greater than [toIndex]. + */ +@SinceKotlin("1.3") +@Suppress("ACTUAL_FUNCTION_WITH_DEFAULT_ARGUMENTS") +public actual fun FloatArray.fill(element: Float, fromIndex: Int = 0, toIndex: Int = size): Unit { + arrayFill(this, fromIndex, toIndex, element) +} + +/** + * Fills this array or its subrange with the specified [element] value. + * + * @param fromIndex the start of the range (inclusive) to fill, 0 by default. + * @param toIndex the end of the range (exclusive) to fill, size of this array by default. + * + * @throws IndexOutOfBoundsException if [fromIndex] is less than zero or [toIndex] is greater than the size of this array. + * @throws IllegalArgumentException if [fromIndex] is greater than [toIndex]. + */ +@SinceKotlin("1.3") +@Suppress("ACTUAL_FUNCTION_WITH_DEFAULT_ARGUMENTS") +public actual fun DoubleArray.fill(element: Double, fromIndex: Int = 0, toIndex: Int = size): Unit { + arrayFill(this, fromIndex, toIndex, element) +} + +/** + * Fills this array or its subrange with the specified [element] value. + * + * @param fromIndex the start of the range (inclusive) to fill, 0 by default. + * @param toIndex the end of the range (exclusive) to fill, size of this array by default. + * + * @throws IndexOutOfBoundsException if [fromIndex] is less than zero or [toIndex] is greater than the size of this array. + * @throws IllegalArgumentException if [fromIndex] is greater than [toIndex]. + */ +@SinceKotlin("1.3") +@Suppress("ACTUAL_FUNCTION_WITH_DEFAULT_ARGUMENTS") +public actual fun BooleanArray.fill(element: Boolean, fromIndex: Int = 0, toIndex: Int = size): Unit { + arrayFill(this, fromIndex, toIndex, element) +} + +/** + * Fills this array or its subrange with the specified [element] value. + * + * @param fromIndex the start of the range (inclusive) to fill, 0 by default. + * @param toIndex the end of the range (exclusive) to fill, size of this array by default. + * + * @throws IndexOutOfBoundsException if [fromIndex] is less than zero or [toIndex] is greater than the size of this array. + * @throws IllegalArgumentException if [fromIndex] is greater than [toIndex]. + */ +@SinceKotlin("1.3") +@Suppress("ACTUAL_FUNCTION_WITH_DEFAULT_ARGUMENTS") +public actual fun CharArray.fill(element: Char, fromIndex: Int = 0, toIndex: Int = size): Unit { + arrayFill(this, fromIndex, toIndex, element) +} + +/** + * Returns an array containing all elements of the original array and then the given [element]. + */ +public actual operator fun Array.plus(element: T): Array { + val index = size + val result = copyOfUninitializedElements(index + 1) + result[index] = element + return result +} + +/** + * Returns an array containing all elements of the original array and then the given [element]. + */ +public actual operator fun ByteArray.plus(element: Byte): ByteArray { + val index = size + val result = copyOfUninitializedElements(index + 1) + result[index] = element + return result +} + +/** + * Returns an array containing all elements of the original array and then the given [element]. + */ +public actual operator fun ShortArray.plus(element: Short): ShortArray { + val index = size + val result = copyOfUninitializedElements(index + 1) + result[index] = element + return result +} + +/** + * Returns an array containing all elements of the original array and then the given [element]. + */ +public actual operator fun IntArray.plus(element: Int): IntArray { + val index = size + val result = copyOfUninitializedElements(index + 1) + result[index] = element + return result +} + +/** + * Returns an array containing all elements of the original array and then the given [element]. + */ +public actual operator fun LongArray.plus(element: Long): LongArray { + val index = size + val result = copyOfUninitializedElements(index + 1) + result[index] = element + return result +} + +/** + * Returns an array containing all elements of the original array and then the given [element]. + */ +public actual operator fun FloatArray.plus(element: Float): FloatArray { + val index = size + val result = copyOfUninitializedElements(index + 1) + result[index] = element + return result +} + +/** + * Returns an array containing all elements of the original array and then the given [element]. + */ +public actual operator fun DoubleArray.plus(element: Double): DoubleArray { + val index = size + val result = copyOfUninitializedElements(index + 1) + result[index] = element + return result +} + +/** + * Returns an array containing all elements of the original array and then the given [element]. + */ +public actual operator fun BooleanArray.plus(element: Boolean): BooleanArray { + val index = size + val result = copyOfUninitializedElements(index + 1) + result[index] = element + return result +} + +/** + * Returns an array containing all elements of the original array and then the given [element]. + */ +public actual operator fun CharArray.plus(element: Char): CharArray { + val index = size + val result = copyOfUninitializedElements(index + 1) + result[index] = element + return result +} + +/** + * Returns an array containing all elements of the original array and then all elements of the given [elements] collection. + */ +public actual operator fun Array.plus(elements: Collection): Array { + var index = size + val result = copyOfUninitializedElements(index + elements.size) + for (element in elements) result[index++] = element + return result +} + +/** + * Returns an array containing all elements of the original array and then all elements of the given [elements] collection. + */ +public actual operator fun ByteArray.plus(elements: Collection): ByteArray { + var index = size + val result = copyOfUninitializedElements(index + elements.size) + for (element in elements) result[index++] = element + return result +} + +/** + * Returns an array containing all elements of the original array and then all elements of the given [elements] collection. + */ +public actual operator fun ShortArray.plus(elements: Collection): ShortArray { + var index = size + val result = copyOfUninitializedElements(index + elements.size) + for (element in elements) result[index++] = element + return result +} + +/** + * Returns an array containing all elements of the original array and then all elements of the given [elements] collection. + */ +public actual operator fun IntArray.plus(elements: Collection): IntArray { + var index = size + val result = copyOfUninitializedElements(index + elements.size) + for (element in elements) result[index++] = element + return result +} + +/** + * Returns an array containing all elements of the original array and then all elements of the given [elements] collection. + */ +public actual operator fun LongArray.plus(elements: Collection): LongArray { + var index = size + val result = copyOfUninitializedElements(index + elements.size) + for (element in elements) result[index++] = element + return result +} + +/** + * Returns an array containing all elements of the original array and then all elements of the given [elements] collection. + */ +public actual operator fun FloatArray.plus(elements: Collection): FloatArray { + var index = size + val result = copyOfUninitializedElements(index + elements.size) + for (element in elements) result[index++] = element + return result +} + +/** + * Returns an array containing all elements of the original array and then all elements of the given [elements] collection. + */ +public actual operator fun DoubleArray.plus(elements: Collection): DoubleArray { + var index = size + val result = copyOfUninitializedElements(index + elements.size) + for (element in elements) result[index++] = element + return result +} + +/** + * Returns an array containing all elements of the original array and then all elements of the given [elements] collection. + */ +public actual operator fun BooleanArray.plus(elements: Collection): BooleanArray { + var index = size + val result = copyOfUninitializedElements(index + elements.size) + for (element in elements) result[index++] = element + return result +} + +/** + * Returns an array containing all elements of the original array and then all elements of the given [elements] collection. + */ +public actual operator fun CharArray.plus(elements: Collection): CharArray { + var index = size + val result = copyOfUninitializedElements(index + elements.size) + for (element in elements) result[index++] = element + return result +} + +/** + * Returns an array containing all elements of the original array and then all elements of the given [elements] array. + */ +public actual operator fun Array.plus(elements: Array): Array { + val thisSize = size + val arraySize = elements.size + val result = copyOfUninitializedElements(thisSize + arraySize) + elements.copyInto(result, thisSize) + return result +} + +/** + * Returns an array containing all elements of the original array and then all elements of the given [elements] array. + */ +public actual operator fun ByteArray.plus(elements: ByteArray): ByteArray { + val thisSize = size + val arraySize = elements.size + val result = copyOfUninitializedElements(thisSize + arraySize) + elements.copyInto(result, thisSize) + return result +} + +/** + * Returns an array containing all elements of the original array and then all elements of the given [elements] array. + */ +public actual operator fun ShortArray.plus(elements: ShortArray): ShortArray { + val thisSize = size + val arraySize = elements.size + val result = copyOfUninitializedElements(thisSize + arraySize) + elements.copyInto(result, thisSize) + return result +} + +/** + * Returns an array containing all elements of the original array and then all elements of the given [elements] array. + */ +public actual operator fun IntArray.plus(elements: IntArray): IntArray { + val thisSize = size + val arraySize = elements.size + val result = copyOfUninitializedElements(thisSize + arraySize) + elements.copyInto(result, thisSize) + return result +} + +/** + * Returns an array containing all elements of the original array and then all elements of the given [elements] array. + */ +public actual operator fun LongArray.plus(elements: LongArray): LongArray { + val thisSize = size + val arraySize = elements.size + val result = copyOfUninitializedElements(thisSize + arraySize) + elements.copyInto(result, thisSize) + return result +} + +/** + * Returns an array containing all elements of the original array and then all elements of the given [elements] array. + */ +public actual operator fun FloatArray.plus(elements: FloatArray): FloatArray { + val thisSize = size + val arraySize = elements.size + val result = copyOfUninitializedElements(thisSize + arraySize) + elements.copyInto(result, thisSize) + return result +} + +/** + * Returns an array containing all elements of the original array and then all elements of the given [elements] array. + */ +public actual operator fun DoubleArray.plus(elements: DoubleArray): DoubleArray { + val thisSize = size + val arraySize = elements.size + val result = copyOfUninitializedElements(thisSize + arraySize) + elements.copyInto(result, thisSize) + return result +} + +/** + * Returns an array containing all elements of the original array and then all elements of the given [elements] array. + */ +public actual operator fun BooleanArray.plus(elements: BooleanArray): BooleanArray { + val thisSize = size + val arraySize = elements.size + val result = copyOfUninitializedElements(thisSize + arraySize) + elements.copyInto(result, thisSize) + return result +} + +/** + * Returns an array containing all elements of the original array and then all elements of the given [elements] array. + */ +public actual operator fun CharArray.plus(elements: CharArray): CharArray { + val thisSize = size + val arraySize = elements.size + val result = copyOfUninitializedElements(thisSize + arraySize) + elements.copyInto(result, thisSize) + return result +} + +/** + * Returns an array containing all elements of the original array and then the given [element]. + */ +@kotlin.internal.InlineOnly +public actual inline fun Array.plusElement(element: T): Array { + return plus(element) +} + +/** + * Sorts the array in-place. + * + * @sample samples.collections.Arrays.Sorting.sortArray + */ +public actual fun IntArray.sort(): Unit { + if (size > 1) sortArray(this, 0, size) +} + +/** + * Sorts the array in-place. + * + * @sample samples.collections.Arrays.Sorting.sortArray + */ +public actual fun LongArray.sort(): Unit { + if (size > 1) sortArray(this, 0, size) +} + +/** + * Sorts the array in-place. + * + * @sample samples.collections.Arrays.Sorting.sortArray + */ +public actual fun ByteArray.sort(): Unit { + if (size > 1) sortArray(this, 0, size) +} + +/** + * Sorts the array in-place. + * + * @sample samples.collections.Arrays.Sorting.sortArray + */ +public actual fun ShortArray.sort(): Unit { + if (size > 1) sortArray(this, 0, size) +} + +/** + * Sorts the array in-place. + * + * @sample samples.collections.Arrays.Sorting.sortArray + */ +public actual fun DoubleArray.sort(): Unit { + if (size > 1) sortArray(this, 0, size) +} + +/** + * Sorts the array in-place. + * + * @sample samples.collections.Arrays.Sorting.sortArray + */ +public actual fun FloatArray.sort(): Unit { + if (size > 1) sortArray(this, 0, size) +} + +/** + * Sorts the array in-place. + * + * @sample samples.collections.Arrays.Sorting.sortArray + */ +public actual fun CharArray.sort(): Unit { + if (size > 1) sortArray(this, 0, size) +} + +/** + * Sorts the array in-place according to the natural order of its elements. + * + * The sort is _stable_. It means that equal elements preserve their order relative to each other after sorting. + * + * @sample samples.collections.Arrays.Sorting.sortArrayOfComparable + */ +public actual fun > Array.sort(): Unit { + if (size > 1) sortArray(this, 0, size) +} + +/** + * Sorts a range in the array in-place. + * + * The sort is _stable_. It means that equal elements preserve their order relative to each other after sorting. + * + * @param fromIndex the start of the range (inclusive) to sort, 0 by default. + * @param toIndex the end of the range (exclusive) to sort, size of this array by default. + * + * @throws IndexOutOfBoundsException if [fromIndex] is less than zero or [toIndex] is greater than the size of this array. + * @throws IllegalArgumentException if [fromIndex] is greater than [toIndex]. + * + * @sample samples.collections.Arrays.Sorting.sortRangeOfArrayOfComparable + */ +@SinceKotlin("1.4") +@Suppress("ACTUAL_FUNCTION_WITH_DEFAULT_ARGUMENTS") +public actual fun > Array.sort(fromIndex: Int = 0, toIndex: Int = size): Unit { + AbstractList.checkRangeIndexes(fromIndex, toIndex, size) + sortArray(this, fromIndex, toIndex) +} + +/** + * Sorts a range in the array in-place. + * + * @param fromIndex the start of the range (inclusive) to sort, 0 by default. + * @param toIndex the end of the range (exclusive) to sort, size of this array by default. + * + * @throws IndexOutOfBoundsException if [fromIndex] is less than zero or [toIndex] is greater than the size of this array. + * @throws IllegalArgumentException if [fromIndex] is greater than [toIndex]. + * + * @sample samples.collections.Arrays.Sorting.sortRangeOfArray + */ +@SinceKotlin("1.4") +@Suppress("ACTUAL_FUNCTION_WITH_DEFAULT_ARGUMENTS") +public actual fun ByteArray.sort(fromIndex: Int = 0, toIndex: Int = size): Unit { + AbstractList.checkRangeIndexes(fromIndex, toIndex, size) + sortArray(this, fromIndex, toIndex) +} + +/** + * Sorts a range in the array in-place. + * + * @param fromIndex the start of the range (inclusive) to sort, 0 by default. + * @param toIndex the end of the range (exclusive) to sort, size of this array by default. + * + * @throws IndexOutOfBoundsException if [fromIndex] is less than zero or [toIndex] is greater than the size of this array. + * @throws IllegalArgumentException if [fromIndex] is greater than [toIndex]. + * + * @sample samples.collections.Arrays.Sorting.sortRangeOfArray + */ +@SinceKotlin("1.4") +@Suppress("ACTUAL_FUNCTION_WITH_DEFAULT_ARGUMENTS") +public actual fun ShortArray.sort(fromIndex: Int = 0, toIndex: Int = size): Unit { + AbstractList.checkRangeIndexes(fromIndex, toIndex, size) + sortArray(this, fromIndex, toIndex) +} + +/** + * Sorts a range in the array in-place. + * + * @param fromIndex the start of the range (inclusive) to sort, 0 by default. + * @param toIndex the end of the range (exclusive) to sort, size of this array by default. + * + * @throws IndexOutOfBoundsException if [fromIndex] is less than zero or [toIndex] is greater than the size of this array. + * @throws IllegalArgumentException if [fromIndex] is greater than [toIndex]. + * + * @sample samples.collections.Arrays.Sorting.sortRangeOfArray + */ +@SinceKotlin("1.4") +@Suppress("ACTUAL_FUNCTION_WITH_DEFAULT_ARGUMENTS") +public actual fun IntArray.sort(fromIndex: Int = 0, toIndex: Int = size): Unit { + AbstractList.checkRangeIndexes(fromIndex, toIndex, size) + sortArray(this, fromIndex, toIndex) +} + +/** + * Sorts a range in the array in-place. + * + * @param fromIndex the start of the range (inclusive) to sort, 0 by default. + * @param toIndex the end of the range (exclusive) to sort, size of this array by default. + * + * @throws IndexOutOfBoundsException if [fromIndex] is less than zero or [toIndex] is greater than the size of this array. + * @throws IllegalArgumentException if [fromIndex] is greater than [toIndex]. + * + * @sample samples.collections.Arrays.Sorting.sortRangeOfArray + */ +@SinceKotlin("1.4") +@Suppress("ACTUAL_FUNCTION_WITH_DEFAULT_ARGUMENTS") +public actual fun LongArray.sort(fromIndex: Int = 0, toIndex: Int = size): Unit { + AbstractList.checkRangeIndexes(fromIndex, toIndex, size) + sortArray(this, fromIndex, toIndex) +} + +/** + * Sorts a range in the array in-place. + * + * @param fromIndex the start of the range (inclusive) to sort, 0 by default. + * @param toIndex the end of the range (exclusive) to sort, size of this array by default. + * + * @throws IndexOutOfBoundsException if [fromIndex] is less than zero or [toIndex] is greater than the size of this array. + * @throws IllegalArgumentException if [fromIndex] is greater than [toIndex]. + * + * @sample samples.collections.Arrays.Sorting.sortRangeOfArray + */ +@SinceKotlin("1.4") +@Suppress("ACTUAL_FUNCTION_WITH_DEFAULT_ARGUMENTS") +public actual fun FloatArray.sort(fromIndex: Int = 0, toIndex: Int = size): Unit { + AbstractList.checkRangeIndexes(fromIndex, toIndex, size) + sortArray(this, fromIndex, toIndex) +} + +/** + * Sorts a range in the array in-place. + * + * @param fromIndex the start of the range (inclusive) to sort, 0 by default. + * @param toIndex the end of the range (exclusive) to sort, size of this array by default. + * + * @throws IndexOutOfBoundsException if [fromIndex] is less than zero or [toIndex] is greater than the size of this array. + * @throws IllegalArgumentException if [fromIndex] is greater than [toIndex]. + * + * @sample samples.collections.Arrays.Sorting.sortRangeOfArray + */ +@SinceKotlin("1.4") +@Suppress("ACTUAL_FUNCTION_WITH_DEFAULT_ARGUMENTS") +public actual fun DoubleArray.sort(fromIndex: Int = 0, toIndex: Int = size): Unit { + AbstractList.checkRangeIndexes(fromIndex, toIndex, size) + sortArray(this, fromIndex, toIndex) +} + +/** + * Sorts a range in the array in-place. + * + * @param fromIndex the start of the range (inclusive) to sort, 0 by default. + * @param toIndex the end of the range (exclusive) to sort, size of this array by default. + * + * @throws IndexOutOfBoundsException if [fromIndex] is less than zero or [toIndex] is greater than the size of this array. + * @throws IllegalArgumentException if [fromIndex] is greater than [toIndex]. + * + * @sample samples.collections.Arrays.Sorting.sortRangeOfArray + */ +@SinceKotlin("1.4") +@Suppress("ACTUAL_FUNCTION_WITH_DEFAULT_ARGUMENTS") +public actual fun CharArray.sort(fromIndex: Int = 0, toIndex: Int = size): Unit { + AbstractList.checkRangeIndexes(fromIndex, toIndex, size) + sortArray(this, fromIndex, toIndex) +} + +/** + * Sorts the array in-place according to the order specified by the given [comparator]. + * + * The sort is _stable_. It means that equal elements preserve their order relative to each other after sorting. + */ +public actual fun Array.sortWith(comparator: Comparator): Unit { + if (size > 1) sortArrayWith(this, 0, size, comparator) +} + +/** + * Sorts a range in the array in-place with the given [comparator]. + * + * The sort is _stable_. It means that equal elements preserve their order relative to each other after sorting. + * + * @param fromIndex the start of the range (inclusive) to sort, 0 by default. + * @param toIndex the end of the range (exclusive) to sort, size of this array by default. + * + * @throws IndexOutOfBoundsException if [fromIndex] is less than zero or [toIndex] is greater than the size of this array. + * @throws IllegalArgumentException if [fromIndex] is greater than [toIndex]. + */ +@Suppress("ACTUAL_FUNCTION_WITH_DEFAULT_ARGUMENTS") +public actual fun Array.sortWith(comparator: Comparator, fromIndex: Int = 0, toIndex: Int = size): Unit { + AbstractList.checkRangeIndexes(fromIndex, toIndex, size) + sortArrayWith(this, fromIndex, toIndex, comparator) +} + +/** + * Returns a *typed* object array containing all of the elements of this primitive array. + */ +public actual fun ByteArray.toTypedArray(): Array { + return Array(size) { index -> this[index] } +} + +/** + * Returns a *typed* object array containing all of the elements of this primitive array. + */ +public actual fun ShortArray.toTypedArray(): Array { + return Array(size) { index -> this[index] } +} + +/** + * Returns a *typed* object array containing all of the elements of this primitive array. + */ +public actual fun IntArray.toTypedArray(): Array { + return Array(size) { index -> this[index] } +} + +/** + * Returns a *typed* object array containing all of the elements of this primitive array. + */ +public actual fun LongArray.toTypedArray(): Array { + return Array(size) { index -> this[index] } +} + +/** + * Returns a *typed* object array containing all of the elements of this primitive array. + */ +public actual fun FloatArray.toTypedArray(): Array { + return Array(size) { index -> this[index] } +} + +/** + * Returns a *typed* object array containing all of the elements of this primitive array. + */ +public actual fun DoubleArray.toTypedArray(): Array { + return Array(size) { index -> this[index] } +} + +/** + * Returns a *typed* object array containing all of the elements of this primitive array. + */ +public actual fun BooleanArray.toTypedArray(): Array { + return Array(size) { index -> this[index] } +} + +/** + * Returns a *typed* object array containing all of the elements of this primitive array. + */ +public actual fun CharArray.toTypedArray(): Array { + return Array(size) { index -> this[index] } +} + diff --git a/kotlin-native/runtime/src/main/kotlin/generated/_CollectionsNative.kt b/kotlin-native/runtime/src/main/kotlin/generated/_CollectionsNative.kt new file mode 100644 index 00000000000..776281e0520 --- /dev/null +++ b/kotlin-native/runtime/src/main/kotlin/generated/_CollectionsNative.kt @@ -0,0 +1,30 @@ +/* + * Copyright 2010-2020 JetBrains s.r.o. and Kotlin Programming Language contributors. + * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. + */ + +package kotlin.collections + +// +// NOTE: THIS FILE IS AUTO-GENERATED by the GenerateStandardLib.kt +// See: https://github.com/JetBrains/kotlin/tree/master/libraries/stdlib +// + +import kotlin.ranges.contains +import kotlin.ranges.reversed + +/** + * Reverses elements in the list in-place. + */ +public actual fun MutableList.reverse(): Unit { + val midPoint = (size / 2) - 1 + if (midPoint < 0) return + var reverseIndex = lastIndex + for (index in 0..midPoint) { + val tmp = this[index] + this[index] = this[reverseIndex] + this[reverseIndex] = tmp + reverseIndex-- + } +} + diff --git a/kotlin-native/runtime/src/main/kotlin/generated/_ComparisonsNative.kt b/kotlin-native/runtime/src/main/kotlin/generated/_ComparisonsNative.kt new file mode 100644 index 00000000000..d19edc4f00b --- /dev/null +++ b/kotlin-native/runtime/src/main/kotlin/generated/_ComparisonsNative.kt @@ -0,0 +1,445 @@ +/* + * Copyright 2010-2020 JetBrains s.r.o. and Kotlin Programming Language contributors. + * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. + */ + +package kotlin.comparisons + +// +// NOTE: THIS FILE IS AUTO-GENERATED by the GenerateStandardLib.kt +// See: https://github.com/JetBrains/kotlin/tree/master/libraries/stdlib +// + + +/** + * Returns the greater of two values. + * + * If values are equal, returns the first one. + */ +@SinceKotlin("1.1") +public actual fun > maxOf(a: T, b: T): T { + return if (a >= b) a else b +} + +/** + * Returns the greater of two values. + */ +@SinceKotlin("1.1") +@kotlin.internal.InlineOnly +public actual inline fun maxOf(a: Byte, b: Byte): Byte { + return maxOf(a.toInt(), b.toInt()).toByte() +} + +/** + * Returns the greater of two values. + */ +@SinceKotlin("1.1") +@kotlin.internal.InlineOnly +public actual inline fun maxOf(a: Short, b: Short): Short { + return maxOf(a.toInt(), b.toInt()).toShort() +} + +/** + * Returns the greater of two values. + */ +@SinceKotlin("1.1") +@kotlin.internal.InlineOnly +public actual inline fun maxOf(a: Int, b: Int): Int { + return if (a >= b) a else b +} + +/** + * Returns the greater of two values. + */ +@SinceKotlin("1.1") +@kotlin.internal.InlineOnly +public actual inline fun maxOf(a: Long, b: Long): Long { + return if (a >= b) a else b +} + +/** + * Returns the greater of two values. + * + * If either value is `NaN`, returns `NaN`. + */ +@SinceKotlin("1.1") +@kotlin.internal.InlineOnly +public actual inline fun maxOf(a: Float, b: Float): Float { + return if (a.compareTo(b) >= 0) a else b +} + +/** + * Returns the greater of two values. + * + * If either value is `NaN`, returns `NaN`. + */ +@SinceKotlin("1.1") +@kotlin.internal.InlineOnly +public actual inline fun maxOf(a: Double, b: Double): Double { + return if (a.compareTo(b) >= 0) a else b +} + +/** + * Returns the greater of three values. + * + * If there are multiple equal maximal values, returns the first of them. + */ +@SinceKotlin("1.1") +public actual fun > maxOf(a: T, b: T, c: T): T { + return maxOf(a, maxOf(b, c)) +} + +/** + * Returns the greater of three values. + */ +@SinceKotlin("1.1") +@kotlin.internal.InlineOnly +public actual inline fun maxOf(a: Byte, b: Byte, c: Byte): Byte { + return maxOf(a.toInt(), maxOf(b.toInt(), c.toInt())).toByte() +} + +/** + * Returns the greater of three values. + */ +@SinceKotlin("1.1") +@kotlin.internal.InlineOnly +public actual inline fun maxOf(a: Short, b: Short, c: Short): Short { + return maxOf(a.toInt(), maxOf(b.toInt(), c.toInt())).toShort() +} + +/** + * Returns the greater of three values. + */ +@SinceKotlin("1.1") +@kotlin.internal.InlineOnly +public actual inline fun maxOf(a: Int, b: Int, c: Int): Int { + return maxOf(a, maxOf(b, c)) +} + +/** + * Returns the greater of three values. + */ +@SinceKotlin("1.1") +@kotlin.internal.InlineOnly +public actual inline fun maxOf(a: Long, b: Long, c: Long): Long { + return maxOf(a, maxOf(b, c)) +} + +/** + * Returns the greater of three values. + * + * If any value is `NaN`, returns `NaN`. + */ +@SinceKotlin("1.1") +@kotlin.internal.InlineOnly +public actual inline fun maxOf(a: Float, b: Float, c: Float): Float { + return maxOf(a, maxOf(b, c)) +} + +/** + * Returns the greater of three values. + * + * If any value is `NaN`, returns `NaN`. + */ +@SinceKotlin("1.1") +@kotlin.internal.InlineOnly +public actual inline fun maxOf(a: Double, b: Double, c: Double): Double { + return maxOf(a, maxOf(b, c)) +} + +/** + * Returns the greater of the given values. + * + * If there are multiple equal maximal values, returns the first of them. + */ +@SinceKotlin("1.4") +public actual fun > maxOf(a: T, vararg other: T): T { + var max = a + for (e in other) max = maxOf(max, e) + return max +} + +/** + * Returns the greater of the given values. + */ +@SinceKotlin("1.4") +public actual fun maxOf(a: Byte, vararg other: Byte): Byte { + var max = a + for (e in other) max = maxOf(max, e) + return max +} + +/** + * Returns the greater of the given values. + */ +@SinceKotlin("1.4") +public actual fun maxOf(a: Short, vararg other: Short): Short { + var max = a + for (e in other) max = maxOf(max, e) + return max +} + +/** + * Returns the greater of the given values. + */ +@SinceKotlin("1.4") +public actual fun maxOf(a: Int, vararg other: Int): Int { + var max = a + for (e in other) max = maxOf(max, e) + return max +} + +/** + * Returns the greater of the given values. + */ +@SinceKotlin("1.4") +public actual fun maxOf(a: Long, vararg other: Long): Long { + var max = a + for (e in other) max = maxOf(max, e) + return max +} + +/** + * Returns the greater of the given values. + * + * If any value is `NaN`, returns `NaN`. + */ +@SinceKotlin("1.4") +public actual fun maxOf(a: Float, vararg other: Float): Float { + var max = a + for (e in other) max = maxOf(max, e) + return max +} + +/** + * Returns the greater of the given values. + * + * If any value is `NaN`, returns `NaN`. + */ +@SinceKotlin("1.4") +public actual fun maxOf(a: Double, vararg other: Double): Double { + var max = a + for (e in other) max = maxOf(max, e) + return max +} + +/** + * Returns the smaller of two values. + * + * If values are equal, returns the first one. + */ +@SinceKotlin("1.1") +public actual fun > minOf(a: T, b: T): T { + return if (a <= b) a else b +} + +/** + * Returns the smaller of two values. + */ +@SinceKotlin("1.1") +@kotlin.internal.InlineOnly +public actual inline fun minOf(a: Byte, b: Byte): Byte { + return minOf(a.toInt(), b.toInt()).toByte() +} + +/** + * Returns the smaller of two values. + */ +@SinceKotlin("1.1") +@kotlin.internal.InlineOnly +public actual inline fun minOf(a: Short, b: Short): Short { + return minOf(a.toInt(), b.toInt()).toShort() +} + +/** + * Returns the smaller of two values. + */ +@SinceKotlin("1.1") +@kotlin.internal.InlineOnly +public actual inline fun minOf(a: Int, b: Int): Int { + return if (a <= b) a else b +} + +/** + * Returns the smaller of two values. + */ +@SinceKotlin("1.1") +@kotlin.internal.InlineOnly +public actual inline fun minOf(a: Long, b: Long): Long { + return if (a <= b) a else b +} + +/** + * Returns the smaller of two values. + * + * If either value is `NaN`, returns `NaN`. + */ +@SinceKotlin("1.1") +@kotlin.internal.InlineOnly +public actual inline fun minOf(a: Float, b: Float): Float { + return when { + a.isNaN() -> a + b.isNaN() -> b + else -> if (a.compareTo(b) <= 0) a else b + } +} + +/** + * Returns the smaller of two values. + * + * If either value is `NaN`, returns `NaN`. + */ +@SinceKotlin("1.1") +@kotlin.internal.InlineOnly +public actual inline fun minOf(a: Double, b: Double): Double { + return when { + a.isNaN() -> a + b.isNaN() -> b + else -> if (a.compareTo(b) <= 0) a else b + } +} + +/** + * Returns the smaller of three values. + * + * If there are multiple equal minimal values, returns the first of them. + */ +@SinceKotlin("1.1") +public actual fun > minOf(a: T, b: T, c: T): T { + return minOf(a, minOf(b, c)) +} + +/** + * Returns the smaller of three values. + */ +@SinceKotlin("1.1") +@kotlin.internal.InlineOnly +public actual inline fun minOf(a: Byte, b: Byte, c: Byte): Byte { + return minOf(a.toInt(), minOf(b.toInt(), c.toInt())).toByte() +} + +/** + * Returns the smaller of three values. + */ +@SinceKotlin("1.1") +@kotlin.internal.InlineOnly +public actual inline fun minOf(a: Short, b: Short, c: Short): Short { + return minOf(a.toInt(), minOf(b.toInt(), c.toInt())).toShort() +} + +/** + * Returns the smaller of three values. + */ +@SinceKotlin("1.1") +@kotlin.internal.InlineOnly +public actual inline fun minOf(a: Int, b: Int, c: Int): Int { + return minOf(a, minOf(b, c)) +} + +/** + * Returns the smaller of three values. + */ +@SinceKotlin("1.1") +@kotlin.internal.InlineOnly +public actual inline fun minOf(a: Long, b: Long, c: Long): Long { + return minOf(a, minOf(b, c)) +} + +/** + * Returns the smaller of three values. + * + * If any value is `NaN`, returns `NaN`. + */ +@SinceKotlin("1.1") +@kotlin.internal.InlineOnly +public actual inline fun minOf(a: Float, b: Float, c: Float): Float { + return minOf(a, minOf(b, c)) +} + +/** + * Returns the smaller of three values. + * + * If any value is `NaN`, returns `NaN`. + */ +@SinceKotlin("1.1") +@kotlin.internal.InlineOnly +public actual inline fun minOf(a: Double, b: Double, c: Double): Double { + return minOf(a, minOf(b, c)) +} + +/** + * Returns the smaller of the given values. + * + * If there are multiple equal minimal values, returns the first of them. + */ +@SinceKotlin("1.4") +public actual fun > minOf(a: T, vararg other: T): T { + var min = a + for (e in other) min = minOf(min, e) + return min +} + +/** + * Returns the smaller of the given values. + */ +@SinceKotlin("1.4") +public actual fun minOf(a: Byte, vararg other: Byte): Byte { + var min = a + for (e in other) min = minOf(min, e) + return min +} + +/** + * Returns the smaller of the given values. + */ +@SinceKotlin("1.4") +public actual fun minOf(a: Short, vararg other: Short): Short { + var min = a + for (e in other) min = minOf(min, e) + return min +} + +/** + * Returns the smaller of the given values. + */ +@SinceKotlin("1.4") +public actual fun minOf(a: Int, vararg other: Int): Int { + var min = a + for (e in other) min = minOf(min, e) + return min +} + +/** + * Returns the smaller of the given values. + */ +@SinceKotlin("1.4") +public actual fun minOf(a: Long, vararg other: Long): Long { + var min = a + for (e in other) min = minOf(min, e) + return min +} + +/** + * Returns the smaller of the given values. + * + * If any value is `NaN`, returns `NaN`. + */ +@SinceKotlin("1.4") +public actual fun minOf(a: Float, vararg other: Float): Float { + var min = a + for (e in other) min = minOf(min, e) + return min +} + +/** + * Returns the smaller of the given values. + * + * If any value is `NaN`, returns `NaN`. + */ +@SinceKotlin("1.4") +public actual fun minOf(a: Double, vararg other: Double): Double { + var min = a + for (e in other) min = minOf(min, e) + return min +} + diff --git a/kotlin-native/runtime/src/main/kotlin/generated/_StringsNative.kt b/kotlin-native/runtime/src/main/kotlin/generated/_StringsNative.kt new file mode 100644 index 00000000000..9ed5b20ff09 --- /dev/null +++ b/kotlin-native/runtime/src/main/kotlin/generated/_StringsNative.kt @@ -0,0 +1,23 @@ +/* + * Copyright 2010-2020 JetBrains s.r.o. and Kotlin Programming Language contributors. + * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. + */ + +package kotlin.text + +// +// NOTE: THIS FILE IS AUTO-GENERATED by the GenerateStandardLib.kt +// See: https://github.com/JetBrains/kotlin/tree/master/libraries/stdlib +// + + +/** + * Returns a character at the given [index] or throws an [IndexOutOfBoundsException] if the [index] is out of bounds of this char sequence. + * + * @sample samples.collections.Collections.Elements.elementAt + */ +@kotlin.internal.InlineOnly +public actual inline fun CharSequence.elementAt(index: Int): Char { + return get(index) +} + diff --git a/kotlin-native/runtime/src/main/kotlin/generated/_UArraysNative.kt b/kotlin-native/runtime/src/main/kotlin/generated/_UArraysNative.kt new file mode 100644 index 00000000000..a42075114c8 --- /dev/null +++ b/kotlin-native/runtime/src/main/kotlin/generated/_UArraysNative.kt @@ -0,0 +1,127 @@ +/* + * Copyright 2010-2020 JetBrains s.r.o. and Kotlin Programming Language contributors. + * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. + */ + +package kotlin.collections + +// +// NOTE: THIS FILE IS AUTO-GENERATED by the GenerateStandardLib.kt +// See: https://github.com/JetBrains/kotlin/tree/master/libraries/stdlib +// + +import kotlin.ranges.contains +import kotlin.ranges.reversed + +/** + * Returns an element at the given [index] or throws an [IndexOutOfBoundsException] if the [index] is out of bounds of this array. + * + * @sample samples.collections.Collections.Elements.elementAt + */ +@SinceKotlin("1.3") +@ExperimentalUnsignedTypes +@kotlin.internal.InlineOnly +public actual inline fun UIntArray.elementAt(index: Int): UInt { + return get(index) +} + +/** + * Returns an element at the given [index] or throws an [IndexOutOfBoundsException] if the [index] is out of bounds of this array. + * + * @sample samples.collections.Collections.Elements.elementAt + */ +@SinceKotlin("1.3") +@ExperimentalUnsignedTypes +@kotlin.internal.InlineOnly +public actual inline fun ULongArray.elementAt(index: Int): ULong { + return get(index) +} + +/** + * Returns an element at the given [index] or throws an [IndexOutOfBoundsException] if the [index] is out of bounds of this array. + * + * @sample samples.collections.Collections.Elements.elementAt + */ +@SinceKotlin("1.3") +@ExperimentalUnsignedTypes +@kotlin.internal.InlineOnly +public actual inline fun UByteArray.elementAt(index: Int): UByte { + return get(index) +} + +/** + * Returns an element at the given [index] or throws an [IndexOutOfBoundsException] if the [index] is out of bounds of this array. + * + * @sample samples.collections.Collections.Elements.elementAt + */ +@SinceKotlin("1.3") +@ExperimentalUnsignedTypes +@kotlin.internal.InlineOnly +public actual inline fun UShortArray.elementAt(index: Int): UShort { + return get(index) +} + +/** + * Returns a [List] that wraps the original array. + */ +@SinceKotlin("1.3") +@ExperimentalUnsignedTypes +public actual fun UIntArray.asList(): List { + return object : AbstractList(), RandomAccess { + override val size: Int get() = this@asList.size + override fun isEmpty(): Boolean = this@asList.isEmpty() + override fun contains(element: UInt): Boolean = this@asList.contains(element) + override fun get(index: Int): UInt = this@asList[index] + override fun indexOf(element: UInt): Int = this@asList.indexOf(element) + override fun lastIndexOf(element: UInt): Int = this@asList.lastIndexOf(element) + } +} + +/** + * Returns a [List] that wraps the original array. + */ +@SinceKotlin("1.3") +@ExperimentalUnsignedTypes +public actual fun ULongArray.asList(): List { + return object : AbstractList(), RandomAccess { + override val size: Int get() = this@asList.size + override fun isEmpty(): Boolean = this@asList.isEmpty() + override fun contains(element: ULong): Boolean = this@asList.contains(element) + override fun get(index: Int): ULong = this@asList[index] + override fun indexOf(element: ULong): Int = this@asList.indexOf(element) + override fun lastIndexOf(element: ULong): Int = this@asList.lastIndexOf(element) + } +} + +/** + * Returns a [List] that wraps the original array. + */ +@SinceKotlin("1.3") +@ExperimentalUnsignedTypes +public actual fun UByteArray.asList(): List { + return object : AbstractList(), RandomAccess { + override val size: Int get() = this@asList.size + override fun isEmpty(): Boolean = this@asList.isEmpty() + override fun contains(element: UByte): Boolean = this@asList.contains(element) + override fun get(index: Int): UByte = this@asList[index] + override fun indexOf(element: UByte): Int = this@asList.indexOf(element) + override fun lastIndexOf(element: UByte): Int = this@asList.lastIndexOf(element) + } +} + +/** + * Returns a [List] that wraps the original array. + */ +@SinceKotlin("1.3") +@ExperimentalUnsignedTypes +public actual fun UShortArray.asList(): List { + return object : AbstractList(), RandomAccess { + override val size: Int get() = this@asList.size + override fun isEmpty(): Boolean = this@asList.isEmpty() + override fun contains(element: UShort): Boolean = this@asList.contains(element) + override fun get(index: Int): UShort = this@asList[index] + override fun indexOf(element: UShort): Int = this@asList.indexOf(element) + override fun lastIndexOf(element: UShort): Int = this@asList.lastIndexOf(element) + } +} + diff --git a/kotlin-native/runtime/src/main/kotlin/kotlin/Annotation.kt b/kotlin-native/runtime/src/main/kotlin/kotlin/Annotation.kt new file mode 100644 index 00000000000..a8ea9b76fa7 --- /dev/null +++ b/kotlin-native/runtime/src/main/kotlin/kotlin/Annotation.kt @@ -0,0 +1,13 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +package kotlin + +/** + * Base interface implicitly implemented by all annotation interfaces. + * See [Kotlin language documentation](https://kotlinlang.org/docs/reference/annotations.html) for more information + * on annotations. + */ +public interface Annotation diff --git a/kotlin-native/runtime/src/main/kotlin/kotlin/Annotations.kt b/kotlin-native/runtime/src/main/kotlin/kotlin/Annotations.kt new file mode 100644 index 00000000000..06148e60fb1 --- /dev/null +++ b/kotlin-native/runtime/src/main/kotlin/kotlin/Annotations.kt @@ -0,0 +1,197 @@ +/* + * Copyright 2010-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +package kotlin + +import kotlin.annotation.AnnotationRetention.BINARY +import kotlin.annotation.AnnotationRetention.SOURCE +import kotlin.annotation.AnnotationTarget.* +import kotlin.reflect.KClass + +/** + * Marks the annotated declaration as deprecated. + * + * A deprecated API element is not recommended to use, typically because it's being phased out or a better alternative exists. + * + * To help removing deprecated API gradually, the property [level] could be used. + * Usually a gradual phase-out goes through the "warning", then "error", then "hidden" or "removed" stages: + * - First and by default, [DeprecationLevel.WARNING] is used to notify API consumers, but not to break their compilation or runtime usages. + * - Then, some time later the deprecation level is raised to [DeprecationLevel.ERROR], so that no new Kotlin code can be compiled + * using the deprecated API. + * - Finally, the API is either removed entirely, or hidden ([DeprecationLevel.HIDDEN]) from code, + * so its usages look like unresolved references, while the API remains in the compiled code + * preserving binary compatibility with previously compiled code. + * + * @property message The message explaining the deprecation and recommending an alternative API to use. + * @property replaceWith If present, specifies a code fragment which should be used as a replacement for + * the deprecated API usage. + * @property level Specifies how the deprecated element usages are reported in code. + * See the [DeprecationLevel] enum for the possible values. + */ +@Target(CLASS, FUNCTION, PROPERTY, ANNOTATION_CLASS, CONSTRUCTOR, PROPERTY_SETTER, PROPERTY_GETTER, TYPEALIAS) +@MustBeDocumented +public annotation class Deprecated( + val message: String, + val replaceWith: ReplaceWith = ReplaceWith(""), + val level: DeprecationLevel = DeprecationLevel.WARNING +) + +/** + * Marks the annotated declaration as deprecated. In contrast to [Deprecated], severity of the reported diagnostic is not a constant value, + * but differs depending on the API version of the usage (the value of the `-api-version` argument when compiling the module where + * the usage is located). If the API version is greater or equal than [hiddenSince], the declaration will not be accessible from the code + * (as if it was deprecated with level [DeprecationLevel.HIDDEN]), otherwise if the API version is greater or equal than [errorSince], + * the usage will be marked as an error (as with [DeprecationLevel.ERROR]), otherwise if the API version is greater or equal + * than [warningSince], the usage will be marked as a warning (as with [DeprecationLevel.WARNING]), otherwise the annotation is ignored. + * + * @property warningSince the version, since which this deprecation should be reported as a warning. + * @property errorSince the version, since which this deprecation should be reported as a error. + * @property hiddenSince the version, since which the annotated declaration should not be available in code. + */ +@Target(CLASS, FUNCTION, PROPERTY, ANNOTATION_CLASS, CONSTRUCTOR, PROPERTY_SETTER, PROPERTY_GETTER, TYPEALIAS) +@MustBeDocumented +@SinceKotlin("1.4") +public annotation class DeprecatedSinceKotlin( + val warningSince: String = "", + val errorSince: String = "", + val hiddenSince: String = "" +) + +/** + * Specifies a code fragment that can be used to replace a deprecated function, property or class. Tools such + * as IDEs can automatically apply the replacements specified through this annotation. + * + * @property expression the replacement expression. The replacement expression is interpreted in the context + * of the symbol being used, and can reference members of enclosing classes etc. + * For function calls, the replacement expression may contain argument names of the deprecated function, + * which will be substituted with actual parameters used in the call being updated. The imports used in the file + * containing the deprecated function or property are NOT accessible; if the replacement expression refers + * on any of those imports, they need to be specified explicitly in the [imports] parameter. + * @property imports the qualified names that need to be imported in order for the references in the + * replacement expression to be resolved correctly. + */ +@Target() +@Retention(BINARY) +@MustBeDocumented +public annotation class ReplaceWith(val expression: String, vararg val imports: String) + +/** + * Possible levels of a deprecation. The level specifies how the deprecated element usages are reported in code. + * + * @see Deprecated + */ +public enum class DeprecationLevel { + /** Usage of the deprecated element will be reported as a warning. */ + WARNING, + /** Usage of the deprecated element will be reported as an error. */ + ERROR, + /** Deprecated element will not be accessible from code. */ + HIDDEN +} + +/** + * Signifies that the annotated functional type represents an extension function. + */ +@Target(TYPE) +@MustBeDocumented +public annotation class ExtensionFunctionType + +/** + * Annotates type arguments of functional type and holds corresponding parameter name specified by the user in type declaration (if any). + */ +@Target(TYPE) +@MustBeDocumented +@SinceKotlin("1.1") +public annotation class ParameterName(val name: String) + +/** + * Suppresses the given compilation warnings in the annotated element. + * @property names names of the compiler diagnostics to suppress. + */ +@Target(CLASS, ANNOTATION_CLASS, TYPE_PARAMETER, PROPERTY, FIELD, LOCAL_VARIABLE, VALUE_PARAMETER, + CONSTRUCTOR, FUNCTION, PROPERTY_GETTER, PROPERTY_SETTER, TYPE, EXPRESSION, FILE, TYPEALIAS) +@Retention(SOURCE) +public annotation class Suppress(vararg val names: String) + +/** + * Suppresses errors about variance conflict + */ +@Target(TYPE) +@Retention(SOURCE) +@MustBeDocumented +public annotation class UnsafeVariance + +/** + * Specifies the first version of Kotlin where a declaration has appeared. + * Using the declaration and specifying an older API version (via the `-api-version` command line option) will result in an error. + * + * @property version the version in the following formats: `.` or `..`, where major, minor and patch + * are non-negative integer numbers without leading zeros. + */ +@Target(CLASS, PROPERTY, FIELD, CONSTRUCTOR, FUNCTION, PROPERTY_GETTER, PROPERTY_SETTER, TYPEALIAS) +@Retention(AnnotationRetention.BINARY) +@MustBeDocumented +public annotation class SinceKotlin(val version: String) + +/** + * When applied to annotation class X specifies that X defines a DSL language + * + * The general rule: + * - an implicit receiver may *belong to a DSL @X* if marked with a corresponding DSL marker annotation + * - two implicit receivers of the same DSL are not accessible in the same scope + * - the closest one wins + * - other available receivers are resolved as usual, but if the resulting resolved call binds to such a receiver, it's a compilation error + * + * Marking rules: an implicit receiver is considered marked with @Ann if + * - its type is marked, or + * - its type's classifier is marked + * - or any of its superclasses/superinterfaces + */ +@Target(ANNOTATION_CLASS) +@Retention(BINARY) +@MustBeDocumented +@SinceKotlin("1.1") +public annotation class DslMarker + +/** + * When applied to a class or a member with internal visibility allows to use it from public inline functions and + * makes it effectively public. + * + * Public inline functions cannot use non-public API, since if they are inlined, those non-public API references + * would violate access restrictions at a call site (https://kotlinlang.org/docs/reference/inline-functions.html#public-inline-restrictions). + * + * To overcome this restriction an `internal` declaration can be annotated with the `@PublishedApi` annotation: + * - this allows to call that declaration from public inline functions; + * - the declaration becomes effectively public, and this should be considered with respect to binary compatibility maintaining. + */ +@Target(AnnotationTarget.CLASS, AnnotationTarget.CONSTRUCTOR, AnnotationTarget.FUNCTION, AnnotationTarget.PROPERTY) +@Retention(AnnotationRetention.BINARY) +@MustBeDocumented +@SinceKotlin("1.1") +public annotation class PublishedApi + +/** + * This annotation indicates what exceptions should be declared by a function when compiled to a platform method. + * + * When compiling to Objective-C/Swift framework, non-`suspend` functions having or inheriting + * this annotation are represented as `NSError*`-producing methods in Objective-C + * and as `throws` methods in Swift. Representations for `suspend` functions always have + * `NSError*`/`Error` parameter in completion handler + * + * When Kotlin function called from Swift/Objective-C code throws an exception + * which is an instance of one of the [exceptionClasses] or their subclasses, + * it is propagated as `NSError`. Other Kotlin exceptions reaching Swift/Objective-C + * are considered unhandled and cause program termination. + * + * Note: `suspend` functions without `@Throws` propagate only + * [kotlin.coroutines.cancellation.CancellationException] as `NSError`. + * Non-`suspend` functions without `@Throws` don't propagate Kotlin exceptions at all. + * + * @property exceptionClasses the list of checked exception classes that may be thrown by the function. + */ +@SinceKotlin("1.4") +@Target(AnnotationTarget.FUNCTION, AnnotationTarget.CONSTRUCTOR) +@Retention(AnnotationRetention.BINARY) +public actual annotation class Throws(actual vararg val exceptionClasses: KClass) diff --git a/kotlin-native/runtime/src/main/kotlin/kotlin/Any.kt b/kotlin-native/runtime/src/main/kotlin/kotlin/Any.kt new file mode 100644 index 00000000000..c3b4b927e02 --- /dev/null +++ b/kotlin-native/runtime/src/main/kotlin/kotlin/Any.kt @@ -0,0 +1,50 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +package kotlin + +import kotlin.native.identityHashCode +import kotlin.native.internal.ExportTypeInfo + +/** + * The root of the Kotlin class hierarchy. Every Kotlin class has [Any] as a superclass. + */ +@ExportTypeInfo("theAnyTypeInfo") +public open class Any { + /** + * Indicates whether some other object is "equal to" this one. Implementations must fulfil the following + * requirements: + * + * * Reflexive: for any non-null value `x`, `x.equals(x)` should return true. + * * Symmetric: for any non-null values `x` and `y`, `x.equals(y)` should return true if and only if `y.equals(x)` returns true. + * * Transitive: for any non-null values `x`, `y`, and `z`, if `x.equals(y)` returns true and `y.equals(z)` returns true, then `x.equals(z)` should return true. + * * Consistent: for any non-null values `x` and `y`, multiple invocations of `x.equals(y)` consistently return true or consistently return false, provided no information used in `equals` comparisons on the objects is modified. + * * Never equal to null: for any non-null value `x`, `x.equals(null)` should return false. + * + * Read more about [equality](https://kotlinlang.org/docs/reference/equality.html) in Kotlin. + */ + @SymbolName("Kotlin_Any_equals") + external public open operator fun equals(other: Any?): Boolean + + /** + * Returns a hash code value for the object. The general contract of `hashCode` is: + * + * * Whenever it is invoked on the same object more than once, the `hashCode` method must consistently return the same integer, provided no information used in `equals` comparisons on the object is modified. + * * If two objects are equal according to the `equals()` method, then calling the `hashCode` method on each of the two objects must produce the same integer result. + */ + public open fun hashCode(): Int = this.identityHashCode() + + /** + * Returns a string representation of the object. + */ + public open fun toString(): String { + val kClass = this::class + val className = kClass.qualifiedName ?: kClass.simpleName ?: "" + // TODO: consider using [identityHashCode]. + val unsignedHashCode = this.hashCode().toLong() and 0xffffffffL + val hashCodeStr = unsignedHashCode.toString(16) + return "$className@$hashCodeStr" + } +} diff --git a/kotlin-native/runtime/src/main/kotlin/kotlin/Array.kt b/kotlin-native/runtime/src/main/kotlin/kotlin/Array.kt new file mode 100644 index 00000000000..58eecb7e931 --- /dev/null +++ b/kotlin-native/runtime/src/main/kotlin/kotlin/Array.kt @@ -0,0 +1,95 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +package kotlin + +import kotlin.native.internal.ExportForCompiler +import kotlin.native.internal.ExportTypeInfo +import kotlin.native.internal.PointsTo + +/** + * Represents an array. Array instances can be created using the constructor, [arrayOf], [arrayOfNulls] and [emptyArray] + * standard library functions. + * See [Kotlin language documentation](https://kotlinlang.org/docs/reference/basic-types.html#arrays) + * for more information on arrays. + */ +@ExportTypeInfo("theArrayTypeInfo") +public final class Array { + + /** + * Creates a new array with the specified [size], where each element is calculated by calling the specified + * [init] function. + * + * The function [init] is called for each array element sequentially starting from the first one. + * It should return the value for an array element given its index. + */ + @Suppress("TYPE_PARAMETER_AS_REIFIED") + public constructor(size: Int, init: (Int) -> T): this(size) { + var index = 0 + while (index < size) { + this[index] = init(index) + index++ + } + } + + @PublishedApi + @ExportForCompiler + internal constructor(@Suppress("UNUSED_PARAMETER") size: Int) {} + + /** + * Returns the number of elements in the array. + */ + public val size: Int + get() = getArrayLength() + + /** + * Returns the array element at the specified [index]. This method can be called using the + * index operator. + * ``` + * value = arr[index] + * ``` + * + * If the [index] is out of bounds of this array, throws an [IndexOutOfBoundsException]. + */ + @SymbolName("Kotlin_Array_get") + @PointsTo(0x000, 0x000, 0x002) // ret -> this.intestines + external public operator fun get(index: Int): T + + /** + * Sets the array element at the specified [index] to the specified [value]. This method can + * be called using the index operator. + * ``` + * arr[index] = value + * ``` + * + * If the [index] is out of bounds of this array, throws an [IndexOutOfBoundsException]. + */ + @SymbolName("Kotlin_Array_set") + @PointsTo(0x300, 0x000, 0x000) // this.intestines -> value + external public operator fun set(index: Int, value: T): Unit + + /** + * Creates an [Iterator] for iterating over the elements of the array. + */ + public operator fun iterator(): kotlin.collections.Iterator { + return IteratorImpl(this) + } + + @SymbolName("Kotlin_Array_getArrayLength") + external private fun getArrayLength(): Int +} + +private class IteratorImpl(val collection: Array) : Iterator { + var index : Int = 0 + + public override fun next(): T { + if (!hasNext()) throw NoSuchElementException("$index") + return collection[index++] + } + + public override operator fun hasNext(): Boolean { + return index < collection.size + } +} diff --git a/kotlin-native/runtime/src/main/kotlin/kotlin/Arrays.kt b/kotlin-native/runtime/src/main/kotlin/kotlin/Arrays.kt new file mode 100644 index 00000000000..638019f3594 --- /dev/null +++ b/kotlin-native/runtime/src/main/kotlin/kotlin/Arrays.kt @@ -0,0 +1,583 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +// TODO: Add SortedSet class and implement toSortedSet extensions +// TODO: Add fill and binary search methods for primitive arrays (with tests) + +package kotlin + +import kotlin.internal.PureReifiable +import kotlin.native.internal.ExportTypeInfo +import kotlin.native.internal.IntrinsicType +import kotlin.native.internal.TypedIntrinsic +import kotlin.native.internal.PointsTo + +/** + * An array of bytes. + * @constructor Creates a new array of the specified [size], with all elements initialized to zero. + */ +@ExportTypeInfo("theByteArrayTypeInfo") +public final class ByteArray { + // Constructors are handled with compiler magic. + public constructor(@Suppress("UNUSED_PARAMETER") size: Int) {} + + /** + * Creates a new array of the specified [size], where each element is calculated by calling the specified + * [init] function. + * + * The function [init] is called for each array element sequentially starting from the first one. + * It should return the value for an array element given its index. + */ + public constructor(size: Int, init: (Int) -> Byte): this(size) { + for (i in 0..size - 1) { + this[i] = init(i) + } + } + + public val size: Int + get() = getArrayLength() + + /** + * Returns the array element at the given [index]. This method can be called using the index operator. + * + * If the [index] is out of bounds of this array, throws an [IndexOutOfBoundsException]. + */ + @SymbolName("Kotlin_ByteArray_get") + external public operator fun get(index: Int): Byte + + /** + * Sets the element at the given [index] to the given [value]. This method can be called using the index operator. + * + * If the [index] is out of bounds of this array, throws an [IndexOutOfBoundsException]. + */ + @SymbolName("Kotlin_ByteArray_set") + external public operator fun set(index: Int, value: Byte): Unit + + @SymbolName("Kotlin_ByteArray_getArrayLength") + external private fun getArrayLength(): Int + + /** Creates an iterator over the elements of the array. */ + public operator fun iterator(): ByteIterator { + return ByteIteratorImpl(this) + } +} + +private class ByteIteratorImpl(val collection: ByteArray) : ByteIterator() { + var index : Int = 0 + + public override fun nextByte(): Byte { + if (!hasNext()) throw NoSuchElementException("$index") + return collection[index++] + } + + public override operator fun hasNext(): Boolean { + return index < collection.size + } +} + +/** + * An array of chars. + * @constructor Creates a new array of the specified [size], with all elements initialized to zero. + */ +@ExportTypeInfo("theCharArrayTypeInfo") +public final class CharArray { + // Constructors are handled with the compiler magic. + public constructor(@Suppress("UNUSED_PARAMETER") size: Int) {} + + /** + * Creates a new array of the specified [size], where each element is calculated by calling the specified + * [init] function. + * + * The function [init] is called for each array element sequentially starting from the first one. + * It should return the value for an array element given its index. + */ + public constructor(size: Int, init: (Int) -> Char): this(size) { + for (i in 0..size - 1) { + this[i] = init(i) + } + } + + /** Returns the number of elements in the array. */ + public val size: Int + get() = getArrayLength() + + /** + * Returns the array element at the given [index]. This method can be called using the index operator. + * + * If the [index] is out of bounds of this array, throws an [IndexOutOfBoundsException]. + */ + @SymbolName("Kotlin_CharArray_get") + external public operator fun get(index: Int): Char + + /** + * Sets the element at the given [index] to the given [value]. This method can be called using the index operator. + * + * If the [index] is out of bounds of this array, throws an [IndexOutOfBoundsException]. + */ + @SymbolName("Kotlin_CharArray_set") + external public operator fun set(index: Int, value: Char): Unit + + @SymbolName("Kotlin_CharArray_getArrayLength") + external private fun getArrayLength(): Int + + /** Creates an iterator over the elements of the array. */ + public operator fun iterator(): kotlin.collections.CharIterator { + return CharIteratorImpl(this) + } +} + +private class CharIteratorImpl(val collection: CharArray) : CharIterator() { + var index : Int = 0 + + public override fun nextChar(): Char { + if (!hasNext()) throw NoSuchElementException("$index") + return collection[index++] + } + + public override operator fun hasNext(): Boolean { + return index < collection.size + } +} + +/** + * An array of shorts. + * @constructor Creates a new array of the specified [size], with all elements initialized to zero. + */ +@ExportTypeInfo("theShortArrayTypeInfo") +public final class ShortArray { + // Constructors are handled with the compiler magic. + public constructor(@Suppress("UNUSED_PARAMETER") size: Int) {} + + /** + * Creates a new array of the specified [size], where each element is calculated by calling the specified + * [init] function. + * + * The function [init] is called for each array element sequentially starting from the first one. + * It should return the value for an array element given its index. + */ + public constructor(size: Int, init: (Int) -> Short): this(size) { + for (i in 0..size - 1) { + this[i] = init(i) + } + } + + /** Returns the number of elements in the array. */ + public val size: Int + get() = getArrayLength() + + /** + * Returns the array element at the given [index]. This method can be called using the index operator. + * + * If the [index] is out of bounds of this array, throws an [IndexOutOfBoundsException]. + */ + @SymbolName("Kotlin_ShortArray_get") + external public operator fun get(index: Int): Short + + /** + * Sets the element at the given [index] to the given [value]. This method can be called using the index operator. + * + * If the [index] is out of bounds of this array, throws an [IndexOutOfBoundsException]. + */ + @SymbolName("Kotlin_ShortArray_set") + external public operator fun set(index: Int, value: Short): Unit + + @SymbolName("Kotlin_ShortArray_getArrayLength") + external private fun getArrayLength(): Int + + /** Creates an iterator over the elements of the array. */ + public operator fun iterator(): kotlin.collections.ShortIterator { + return ShortIteratorImpl(this) + } +} + +private class ShortIteratorImpl(val collection: ShortArray) : ShortIterator() { + var index : Int = 0 + + public override fun nextShort(): Short { + if (!hasNext()) throw NoSuchElementException("$index") + return collection[index++] + } + + public override operator fun hasNext(): Boolean { + return index < collection.size + } +} + +/** + * An array of ints. When targeting the JVM, instances of this class are represented as `int[]`. + * @constructor Creates a new array of the specified [size], with all elements initialized to zero. + */ +@ExportTypeInfo("theIntArrayTypeInfo") +public final class IntArray { + // Constructors are handled with the compiler magic. + public constructor(@Suppress("UNUSED_PARAMETER") size: Int) {} + + /** + * Creates a new array of the specified [size], where each element is calculated by calling the specified + * [init] function. + * + * The function [init] is called for each array element sequentially starting from the first one. + * It should return the value for an array element given its index. + */ + public constructor(size: Int, init: (Int) -> Int): this(size) { + for (i in 0..size - 1) { + this[i] = init(i) + } + } + + /** Returns the number of elements in the array. */ + public val size: Int + get() = getArrayLength() + + /** + * Returns the array element at the given [index]. This method can be called using the index operator. + * + * If the [index] is out of bounds of this array, throws an [IndexOutOfBoundsException]. + */ + @SymbolName("Kotlin_IntArray_get") + external public operator fun get(index: Int): Int + + /** + * Sets the element at the given [index] to the given [value]. This method can be called using the index operator. + * + * If the [index] is out of bounds of this array, throws an [IndexOutOfBoundsException]. + */ + @SymbolName("Kotlin_IntArray_set") + external public operator fun set(index: Int, value: Int): Unit + + @SymbolName("Kotlin_IntArray_getArrayLength") + external private fun getArrayLength(): Int + + /** Creates an iterator over the elements of the array. */ + public operator fun iterator(): kotlin.collections.IntIterator { + return IntIteratorImpl(this) + } +} + +private class IntIteratorImpl(val collection: IntArray) : IntIterator() { + var index : Int = 0 + + public override fun nextInt(): Int { + if (!hasNext()) throw NoSuchElementException("$index") + return collection[index++] + } + + public override operator fun hasNext(): Boolean { + return index < collection.size + } +} + +/** + * An array of longs. + * @constructor Creates a new array of the specified [size], with all elements initialized to zero. + */ +@ExportTypeInfo("theLongArrayTypeInfo") +public final class LongArray { + // Constructors are handled with the compiler magic. + public constructor(@Suppress("UNUSED_PARAMETER") size: Int) {} + + /** + * Creates a new array of the specified [size], where each element is calculated by calling the specified + * [init] function. + * + * The function [init] is called for each array element sequentially starting from the first one. + * It should return the value for an array element given its index. + */ + public constructor(size: Int, init: (Int) -> Long): this(size) { + for (i in 0..size - 1) { + this[i] = init(i) + } + } + + /** Returns the number of elements in the array. */ + public val size: Int + get() = getArrayLength() + + /** + * Returns the array element at the given [index]. This method can be called using the index operator. + * + * If the [index] is out of bounds of this array, throws an [IndexOutOfBoundsException]. + */ + @SymbolName("Kotlin_LongArray_get") + external public operator fun get(index: Int): Long + + /** + * Sets the element at the given [index] to the given [value]. This method can be called using the index operator. + * + * If the [index] is out of bounds of this array, throws an [IndexOutOfBoundsException]. + */ + @SymbolName("Kotlin_LongArray_set") + external public operator fun set(index: Int, value: Long): Unit + + @SymbolName("Kotlin_LongArray_getArrayLength") + external private fun getArrayLength(): Int + + /** Creates an iterator over the elements of the array. */ + public operator fun iterator(): kotlin.collections.LongIterator { + return LongIteratorImpl(this) + } +} + +private class LongIteratorImpl(val collection: LongArray) : LongIterator() { + var index : Int = 0 + + public override fun nextLong(): Long { + if (!hasNext()) throw NoSuchElementException("$index") + return collection[index++] + } + + public override operator fun hasNext(): Boolean { + return index < collection.size + } +} + +/** + * An array of floats. + * @constructor Creates a new array of the specified [size], with all elements initialized to zero. + */ +@ExportTypeInfo("theFloatArrayTypeInfo") +public final class FloatArray { + // Constructors are handled with the compiler magic. + public constructor(@Suppress("UNUSED_PARAMETER") size: Int) {} + + /** + * Creates a new array of the specified [size], where each element is calculated by calling the specified + * [init] function. + * + * The function [init] is called for each array element sequentially starting from the first one. + * It should return the value for an array element given its index. + */ + public constructor(size: Int, init: (Int) -> Float): this(size) { + for (i in 0..size - 1) { + this[i] = init(i) + } + } + + /** Returns the number of elements in the array. */ + public val size: Int + get() = getArrayLength() + + /** + * Returns the array element at the given [index]. This method can be called using the index operator. + * + * If the [index] is out of bounds of this array, throws an [IndexOutOfBoundsException]. + */ + @SymbolName("Kotlin_FloatArray_get") + external public operator fun get(index: Int): Float + + /** + * Sets the element at the given [index] to the given [value]. This method can be called using the index operator. + * + * If the [index] is out of bounds of this array, throws an [IndexOutOfBoundsException]. + */ + @SymbolName("Kotlin_FloatArray_set") + external public operator fun set(index: Int, value: Float): Unit + + @SymbolName("Kotlin_FloatArray_getArrayLength") + external private fun getArrayLength(): Int + + /** Creates an iterator over the elements of the array. */ + public operator fun iterator(): kotlin.collections.FloatIterator { + return FloatIteratorImpl(this) + } +} + +private class FloatIteratorImpl(val collection: FloatArray) : FloatIterator() { + var index : Int = 0 + + public override fun nextFloat(): Float { + if (!hasNext()) throw NoSuchElementException("$index") + return collection[index++] + } + + public override operator fun hasNext(): Boolean { + return index < collection.size + } +} + +@ExportTypeInfo("theDoubleArrayTypeInfo") +public final class DoubleArray { + // Constructors are handled with the compiler magic. + public constructor(@Suppress("UNUSED_PARAMETER") size: Int) {} + + /** + * Creates a new array of the specified [size], where each element is calculated by calling the specified + * [init] function. + * + * The function [init] is called for each array element sequentially starting from the first one. + * It should return the value for an array element given its index. + */ + public constructor(size: Int, init: (Int) -> Double): this(size) { + for (i in 0..size - 1) { + this[i] = init(i) + } + } + + /** Returns the number of elements in the array. */ + public val size: Int + get() = getArrayLength() + + /** + * Returns the array element at the given [index]. This method can be called using the index operator. + * + * If the [index] is out of bounds of this array, throws an [IndexOutOfBoundsException]. + */ + @SymbolName("Kotlin_DoubleArray_get") + external public operator fun get(index: Int): Double + + /** + * Sets the element at the given [index] to the given [value]. This method can be called using the index operator. + * + * If the [index] is out of bounds of this array, throws an [IndexOutOfBoundsException]. + */ + @SymbolName("Kotlin_DoubleArray_set") + external public operator fun set(index: Int, value: Double): Unit + + @SymbolName("Kotlin_DoubleArray_getArrayLength") + external private fun getArrayLength(): Int + + /** Creates an iterator over the elements of the array. */ + public operator fun iterator(): kotlin.collections.DoubleIterator { + return DoubleIteratorImpl(this) + } +} + +private class DoubleIteratorImpl(val collection: DoubleArray) : DoubleIterator() { + var index : Int = 0 + + public override fun nextDouble(): Double { + if (!hasNext()) throw NoSuchElementException("$index") + return collection[index++] + } + + public override operator fun hasNext(): Boolean { + return index < collection.size + } +} + +@ExportTypeInfo("theBooleanArrayTypeInfo") +public final class BooleanArray { + // Constructors are handled with the compiler magic. + public constructor(@Suppress("UNUSED_PARAMETER") size: Int) {} + + /** + * Creates a new array of the specified [size], where each element is calculated by calling the specified + * [init] function. + * + * The function [init] is called for each array element sequentially starting from the first one. + * It should return the value for an array element given its index. + */ + public constructor(size: Int, init: (Int) -> Boolean): this(size) { + for (i in 0..size - 1) { + this[i] = init(i) + } + } + + /** Returns the number of elements in the array. */ + public val size: Int + get() = getArrayLength() + + /** + * Returns the array element at the given [index]. This method can be called using the index operator. + * + * If the [index] is out of bounds of this array, throws an [IndexOutOfBoundsException]. + */ + @SymbolName("Kotlin_BooleanArray_get") + external public operator fun get(index: Int): Boolean + + /** + * Sets the element at the given [index] to the given [value]. This method can be called using the index operator. + * + * If the [index] is out of bounds of this array, throws an [IndexOutOfBoundsException]. + */ + @SymbolName("Kotlin_BooleanArray_set") + external public operator fun set(index: Int, value: Boolean): Unit + + @SymbolName("Kotlin_BooleanArray_getArrayLength") + external private fun getArrayLength(): Int + + /** Creates an iterator over the elements of the array. */ + public operator fun iterator(): kotlin.collections.BooleanIterator { + return BooleanIteratorImpl(this) + } +} + +private class BooleanIteratorImpl(val collection: BooleanArray) : BooleanIterator() { + var index : Int = 0 + + public override fun nextBoolean(): Boolean { + if (!hasNext()) throw NoSuchElementException("$index") + return collection[index++] + } + + public override operator fun hasNext(): Boolean { + return index < collection.size + } +} + +/** + * Returns an array of objects of the given type with the given [size], initialized with null values. + */ +public inline fun arrayOfNulls(size: Int): Array = + @Suppress("NON_PUBLIC_CALL_FROM_PUBLIC_INLINE") + arrayOfUninitializedElements(size) + +/** + * Returns an array containing the specified elements. + */ +@TypedIntrinsic(IntrinsicType.IDENTITY) +@PointsTo(0x00, 0x01) // ret -> elements +public external inline fun arrayOf(vararg elements: T): Array + +@SymbolName("Kotlin_emptyArray") +external public fun emptyArray(): Array + +/** + * Returns an array containing the specified [Double] numbers. + */ +@Suppress("NOTHING_TO_INLINE") +public inline fun doubleArrayOf(vararg elements: Double) = elements + +/** + * Returns an array containing the specified [Float] numbers. + */ +@Suppress("NOTHING_TO_INLINE") +public inline fun floatArrayOf(vararg elements: Float) = elements + +/** + * Returns an array containing the specified [Long] numbers. + */ +@Suppress("NOTHING_TO_INLINE") +public inline fun longArrayOf(vararg elements: Long) = elements + +/** + * Returns an array containing the specified [Int] numbers. + */ +@Suppress("NOTHING_TO_INLINE") +public inline fun intArrayOf(vararg elements: Int) = elements + +/** + * Returns an array containing the specified characters. + */ +@Suppress("NOTHING_TO_INLINE") +public inline fun charArrayOf(vararg elements: Char) = elements + +/** + * Returns an array containing the specified [Short] numbers. + */ +@Suppress("NOTHING_TO_INLINE") +public inline fun shortArrayOf(vararg elements: Short) = elements + +/** + * Returns an array containing the specified [Byte] numbers. + */ +@Suppress("NOTHING_TO_INLINE") +public inline fun byteArrayOf(vararg elements: Byte) = elements + +/** + * Returns an array containing the specified boolean values. + */ +@Suppress("NOTHING_TO_INLINE") +public inline fun booleanArrayOf(vararg elements: Boolean) = elements diff --git a/kotlin-native/runtime/src/main/kotlin/kotlin/Assertions.kt b/kotlin-native/runtime/src/main/kotlin/kotlin/Assertions.kt new file mode 100644 index 00000000000..15771859d4a --- /dev/null +++ b/kotlin-native/runtime/src/main/kotlin/kotlin/Assertions.kt @@ -0,0 +1,26 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +package kotlin + +/** + * Throws an [AssertionError] if the [value] is false + * and runtime assertions have been enabled during compilation. + */ +@Suppress("NOTHING_TO_INLINE") +public inline fun assert(value: Boolean) { + assert(value) { "Assertion failed" } +} + +/** + * Throws an [AssertionError] calculated by [lazyMessage] if the [value] is false + * and runtime assertions have been enabled during compilation. + */ +public inline fun assert(value: Boolean, lazyMessage: () -> Any) { + if (!value) { + val message = lazyMessage() + throw AssertionError(message) + } +} diff --git a/kotlin-native/runtime/src/main/kotlin/kotlin/Boolean.kt b/kotlin-native/runtime/src/main/kotlin/kotlin/Boolean.kt new file mode 100644 index 00000000000..5ec2f74b617 --- /dev/null +++ b/kotlin-native/runtime/src/main/kotlin/kotlin/Boolean.kt @@ -0,0 +1,57 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +package kotlin + +import kotlin.native.internal.TypedIntrinsic +import kotlin.native.internal.IntrinsicType + +/** + * Represents a value which is either `true` or `false`. On the JVM, non-nullable values of this type are + * represented as values of the primitive type `boolean`. + */ +public class Boolean private constructor() : Comparable { + + @SinceKotlin("1.3") + companion object {} + + /** + * Returns the inverse of this boolean. + */ + @TypedIntrinsic(IntrinsicType.NOT) + external public operator fun not(): Boolean + + /** + * Performs a logical `and` operation between this Boolean and the [other] one. Unlike the `&&` operator, + * this function does not perform short-circuit evaluation. Both `this` and [other] will always be evaluated. + */ + @TypedIntrinsic(IntrinsicType.AND) + external public infix fun and(other: Boolean): Boolean + + /** + * Performs a logical `or` operation between this Boolean and the [other] one. Unlike the `||` operator, + * this function does not perform short-circuit evaluation. Both `this` and [other] will always be evaluated. + */ + @TypedIntrinsic(IntrinsicType.OR) + external public infix fun or(other: Boolean): Boolean + + /** + * Performs a logical `xor` operation between this Boolean and the [other] one. + */ + @TypedIntrinsic(IntrinsicType.XOR) + external public infix fun xor(other: Boolean): Boolean + + @TypedIntrinsic(IntrinsicType.UNSIGNED_COMPARE_TO) + external public override fun compareTo(other: Boolean): Int + + public fun equals(other: Boolean): Boolean = kotlin.native.internal.areEqualByValue(this, other) + + public override fun equals(other: Any?): Boolean = + other is Boolean && kotlin.native.internal.areEqualByValue(this, other) + + public override fun toString() = if (this) "true" else "false" + + public override fun hashCode() = if (this) 1 else 0 +} \ No newline at end of file diff --git a/kotlin-native/runtime/src/main/kotlin/kotlin/Char.kt b/kotlin-native/runtime/src/main/kotlin/kotlin/Char.kt new file mode 100644 index 00000000000..d3c424e82e2 --- /dev/null +++ b/kotlin-native/runtime/src/main/kotlin/kotlin/Char.kt @@ -0,0 +1,161 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ +@file:Suppress("NOTHING_TO_INLINE") + +package kotlin + +import kotlin.native.internal.TypedIntrinsic +import kotlin.native.internal.IntrinsicType + +/** + * Represents a 16-bit Unicode character. + */ +public class Char private constructor() : Comparable { + /** + * Compares this value with the specified value for order. + * + * Returns zero if this value is equal to the specified other value, a negative number if it's less than other, + * or a positive number if it's greater than other. + */ + @TypedIntrinsic(IntrinsicType.UNSIGNED_COMPARE_TO) + external public override fun compareTo(other: Char): Int + + /** Adds the other Int value to this value resulting a Char. */ + public inline operator fun plus(other: Int): Char = + (this.toInt() + other).toChar() + /** Subtracts the other Char value from this value resulting an Int. */ + public inline operator fun minus(other: Char): Int = + this.toInt() - other.toInt() + /** Subtracts the other Int value from this value resulting a Char. */ + public inline operator fun minus(other: Int): Char = + (this.toInt() - other).toChar() + + /** Increments this value. */ + @TypedIntrinsic(IntrinsicType.INC) + external public operator fun inc(): Char + /** Decrements this value. */ + @TypedIntrinsic(IntrinsicType.DEC) + external public operator fun dec(): Char + + /** Creates a range from this value to the specified [other] value. */ + public operator fun rangeTo(other: Char): CharRange { + return CharRange(this, other) + } + + /** Returns the value of this character as a `Byte`. */ + @TypedIntrinsic(IntrinsicType.INT_TRUNCATE) + external public fun toByte(): Byte + /** Returns the value of this character as a `Char`. */ + public inline fun toChar(): Char = this + /** Returns the value of this character as a `Short`. */ + @TypedIntrinsic(IntrinsicType.ZERO_EXTEND) + external public fun toShort(): Short + /** Returns the value of this character as a `Int`. */ + @TypedIntrinsic(IntrinsicType.ZERO_EXTEND) + external public fun toInt(): Int + /** Returns the value of this character as a `Long`. */ + @TypedIntrinsic(IntrinsicType.ZERO_EXTEND) + external public fun toLong(): Long + /** Returns the value of this character as a `Float`. */ + @TypedIntrinsic(IntrinsicType.UNSIGNED_TO_FLOAT) + external public fun toFloat(): Float + /** Returns the value of this character as a `Double`. */ + @TypedIntrinsic(IntrinsicType.UNSIGNED_TO_FLOAT) + external public fun toDouble(): Double + + @kotlin.native.internal.CanBePrecreated + companion object { + /** + * The minimum value of a character code unit. + */ + @SinceKotlin("1.3") + public const val MIN_VALUE: Char = '\u0000' + + /** + * The maximum value of a character code unit. + */ + @SinceKotlin("1.3") + public const val MAX_VALUE: Char = '\uFFFF' + + /** + * The number of bytes used to represent a Char in a binary form. + */ + @SinceKotlin("1.3") + public const val SIZE_BYTES: Int = 2 + /** + * The number of bits used to represent a Char in a binary form. + */ + @SinceKotlin("1.3") + public const val SIZE_BITS: Int = 16 + + /** + * The minimum value of a Unicode high-surrogate code unit. + */ + public const val MIN_HIGH_SURROGATE: Char = '\uD800' + + /** + * The maximum value of a Unicode high-surrogate code unit. + */ + public const val MAX_HIGH_SURROGATE: Char = '\uDBFF' + + /** + * The minimum value of a Unicode low-surrogate code unit. + */ + public const val MIN_LOW_SURROGATE: Char = '\uDC00' + + /** + * The maximum value of a Unicode low-surrogate code unit. + */ + public const val MAX_LOW_SURROGATE: Char = '\uDFFF' + + /** + * The minimum value of a Unicode surrogate code unit. + */ + public const val MIN_SURROGATE: Char = MIN_HIGH_SURROGATE + + /** + * The maximum value of a Unicode surrogate code unit. + */ + public const val MAX_SURROGATE: Char = MAX_LOW_SURROGATE + + /** + * The minimum value of a supplementary code point, `\u0x10000`. Kotlin/Native specific. + */ + public const val MIN_SUPPLEMENTARY_CODE_POINT: Int = 0x10000 + + /** + * The minimum value of a Unicode code point. Kotlin/Native specific. + */ + public const val MIN_CODE_POINT = 0x000000 + + /** + * The maximum value of a Unicode code point. Kotlin/Native specific. + */ + public const val MAX_CODE_POINT = 0X10FFFF + + /** + * The minimum radix available for conversion to and from strings. + */ + public const val MIN_RADIX: Int = 2 + + /** + * The maximum radix available for conversion to and from strings. + */ + public const val MAX_RADIX: Int = 36 + } + + public fun equals(other: Char): Boolean = this == other + + public override fun equals(other: Any?): Boolean = + other is Char && this.equals(other) + + @SymbolName("Kotlin_Char_toString") + external public override fun toString(): String + + public override fun hashCode(): Int { + return this.toInt(); + } +} + diff --git a/kotlin-native/runtime/src/main/kotlin/kotlin/CharSequence.kt b/kotlin-native/runtime/src/main/kotlin/kotlin/CharSequence.kt new file mode 100644 index 00000000000..f54b904c370 --- /dev/null +++ b/kotlin-native/runtime/src/main/kotlin/kotlin/CharSequence.kt @@ -0,0 +1,32 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +package kotlin + +/** + * Represents a readable sequence of [Char] values. + */ +public interface CharSequence { + /** + * Returns the length of this character sequence. + */ + public val length: Int + + /** + * Returns the character at the specified [index] in this character sequence. + * + * @throws [IndexOutOfBoundsException] if the [index] is out of bounds of this character sequence. + */ + public operator fun get(index: Int): Char + + /** + * Returns a new character sequence that is a subsequence of this character sequence, + * starting at the specified [startIndex] and ending right before the specified [endIndex]. + * + * @param startIndex the start index (inclusive). + * @param endIndex the end index (exclusive). + */ + public fun subSequence(startIndex: Int, endIndex: Int): CharSequence +} \ No newline at end of file diff --git a/kotlin-native/runtime/src/main/kotlin/kotlin/Comparable.kt b/kotlin-native/runtime/src/main/kotlin/kotlin/Comparable.kt new file mode 100644 index 00000000000..bb4d47f2e0a --- /dev/null +++ b/kotlin-native/runtime/src/main/kotlin/kotlin/Comparable.kt @@ -0,0 +1,21 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +package kotlin + +import kotlin.Comparator + +/** + * Classes which inherit from this interface have a defined total ordering between their instances. + */ +public interface Comparable { + /** + * Compares this object with the specified object for order. Returns zero if this object is equal + * to the specified [other] object, a negative number if it's less than [other], or a positive number + * if it's greater than [other]. + */ + public operator fun compareTo(other: T): Int +} + diff --git a/kotlin-native/runtime/src/main/kotlin/kotlin/Comparator.kt b/kotlin-native/runtime/src/main/kotlin/kotlin/Comparator.kt new file mode 100644 index 00000000000..32e0b73e9a6 --- /dev/null +++ b/kotlin-native/runtime/src/main/kotlin/kotlin/Comparator.kt @@ -0,0 +1,10 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +package kotlin + +public actual fun interface Comparator { + public actual fun compare(a: T, b: T): Int +} diff --git a/kotlin-native/runtime/src/main/kotlin/kotlin/Enum.kt b/kotlin-native/runtime/src/main/kotlin/kotlin/Enum.kt new file mode 100644 index 00000000000..406e525e89b --- /dev/null +++ b/kotlin-native/runtime/src/main/kotlin/kotlin/Enum.kt @@ -0,0 +1,44 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +package kotlin + +import kotlin.native.internal.enumValueOfIntrinsic +import kotlin.native.internal.enumValuesIntrinsic + +/** + * The common base class of all enum classes. + * See the [Kotlin language documentation](https://kotlinlang.org/docs/reference/enum-classes.html) for more + * information on enum classes. + */ +public abstract class Enum>(public val name: String, public val ordinal: Int): Comparable { + + public companion object { + } + + public override final fun compareTo(other: E): Int { return ordinal - other.ordinal } + + public override final fun equals(other: Any?): Boolean { + return this === other + } + + public override final fun hashCode(): Int { + return ordinal + } + + public override fun toString(): String { + return name + } +} + +/** + * Returns an enum entry with specified name. + */ +public inline fun > enumValueOf(name: String): T = enumValueOfIntrinsic(name) + +/** + * Returns an array containing enum T entries. + */ +public inline fun > enumValues(): Array = enumValuesIntrinsic() diff --git a/kotlin-native/runtime/src/main/kotlin/kotlin/Exceptions.kt b/kotlin-native/runtime/src/main/kotlin/kotlin/Exceptions.kt new file mode 100644 index 00000000000..db829929c1c --- /dev/null +++ b/kotlin-native/runtime/src/main/kotlin/kotlin/Exceptions.kt @@ -0,0 +1,185 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +package kotlin + +public actual open class Error : Throwable { + + actual constructor() : super() + + actual constructor(message: String?) : super(message) + + actual constructor(message: String?, cause: Throwable?) : super(message, cause) + + actual constructor(cause: Throwable?) : super(cause) +} + +public actual open class Exception : Throwable { + + actual constructor() : super() + + actual constructor(message: String?) : super(message) + + actual constructor(message: String?, cause: Throwable?) : super(message, cause) + + actual constructor(cause: Throwable?) : super(cause) +} + +public actual open class RuntimeException : Exception { + + actual constructor() : super() + + actual constructor(message: String?) : super(message) + + actual constructor(message: String?, cause: Throwable?) : super(message, cause) + + actual constructor(cause: Throwable?) : super(cause) +} + +public actual open class NullPointerException : RuntimeException { + + actual constructor() : super() + + actual constructor(message: String?) : super(message) +} + +public actual open class NoSuchElementException : RuntimeException { + + actual constructor() : super() + + actual constructor(message: String?) : super(message) +} + +public actual open class IllegalArgumentException : RuntimeException { + + actual constructor() : super() + + actual constructor(message: String?) : super(message) + + actual constructor(message: String?, cause: Throwable?) : super(message, cause) + + actual constructor(cause: Throwable?) : super(cause) +} + +public actual open class IllegalStateException : RuntimeException { + + actual constructor() : super() + + actual constructor(message: String?) : super(message) + + actual constructor(message: String?, cause: Throwable?) : super(message, cause) + + actual constructor(cause: Throwable?) : super(cause) +} + +public actual open class UnsupportedOperationException : RuntimeException { + + actual constructor() + + actual constructor(message: String?) : super(message) + + actual constructor(message: String?, cause: Throwable?) : super(message, cause) + + actual constructor(cause: Throwable?) : super(cause) +} + +public actual open class IndexOutOfBoundsException : RuntimeException { + + actual constructor() : super() + + actual constructor(message: String?) : super(message) +} + +public open class ArrayIndexOutOfBoundsException : IndexOutOfBoundsException { + + constructor() : super() + + constructor(message: String?) : super(message) +} + +public actual open class ClassCastException : RuntimeException { + + actual constructor() : super() + + actual constructor(message: String?) : super(message) +} + +public open class TypeCastException : ClassCastException { + + constructor() : super() + + constructor(message: String?) : super(message) +} + +public actual open class ArithmeticException : RuntimeException { + actual constructor() : super() + + actual constructor(message: String?) : super(message) +} + +public actual open class AssertionError : Error { + + actual constructor() + + constructor(cause: Throwable?) : super(cause) + + actual constructor(message: Any?) : super(message?.toString()) + + constructor(message: String?, cause: Throwable?) : super(message, cause) +} + +public actual open class NoWhenBranchMatchedException : RuntimeException { + + actual constructor() : super() + + actual constructor(message: String?) : super(message) + + actual constructor(message: String?, cause: Throwable?) : super(message, cause) + + actual constructor(cause: Throwable?) : super(cause) +} + +public actual open class UninitializedPropertyAccessException : RuntimeException { + + actual constructor() : super() + + actual constructor(message: String?) : super(message) + + actual constructor(message: String?, cause: Throwable?) : super(message, cause) + + actual constructor(cause: Throwable?) : super(cause) +} + +public open class OutOfMemoryError : Error { + + constructor() : super() + + constructor(message: String?) : super(message) +} + +public actual open class NumberFormatException : IllegalArgumentException { + + actual constructor() : super() + + actual constructor(message: String?) : super(message) +} + +@Deprecated("Use CharacterCodingException instead", ReplaceWith("CharacterCodingException"), DeprecationLevel.ERROR) +public open class IllegalCharacterConversionException : IllegalArgumentException { + + constructor(): super() + + constructor(message: String?) : super(message) +} + +public actual open class ConcurrentModificationException actual constructor(message: String?, cause: Throwable?) : + RuntimeException(message, cause) { + + actual constructor() : this(null, null) + + actual constructor(message: String?) : this(message, null) + + actual constructor(cause: Throwable?) : this(null, cause) +} \ No newline at end of file diff --git a/kotlin-native/runtime/src/main/kotlin/kotlin/Experimental.kt b/kotlin-native/runtime/src/main/kotlin/kotlin/Experimental.kt new file mode 100644 index 00000000000..cc5065c55e7 --- /dev/null +++ b/kotlin-native/runtime/src/main/kotlin/kotlin/Experimental.kt @@ -0,0 +1,12 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +/** + * Empty package to avoid unresolved reference errors in bitwiseOp tests + * (e.g. external_codegen_box_binaryOp/bitwiseOp.kt). + * Byte/Short bitwise operations are supported in Kotlin Native by default. + */ + +package kotlin.experimental \ No newline at end of file diff --git a/kotlin-native/runtime/src/main/kotlin/kotlin/Function.kt b/kotlin-native/runtime/src/main/kotlin/kotlin/Function.kt new file mode 100644 index 00000000000..d31153d57dc --- /dev/null +++ b/kotlin-native/runtime/src/main/kotlin/kotlin/Function.kt @@ -0,0 +1,16 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +package kotlin + +import kotlin.native.internal.FixmeReflection + +/** + * Represents a value of a functional type, such as a lambda, an anonymous function or a function reference. + * + * @param R return type of the function. + */ +@FixmeReflection +public interface Function diff --git a/kotlin-native/runtime/src/main/kotlin/kotlin/Lazy.kt b/kotlin-native/runtime/src/main/kotlin/kotlin/Lazy.kt new file mode 100644 index 00000000000..0631116caa2 --- /dev/null +++ b/kotlin-native/runtime/src/main/kotlin/kotlin/Lazy.kt @@ -0,0 +1,54 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +package kotlin + +import kotlin.native.concurrent.FreezeAwareLazyImpl +import kotlin.native.internal.FixmeConcurrency +import kotlin.reflect.KProperty + +/** + * Creates a new instance of the [Lazy] that uses the specified initialization function [initializer] + * and the default thread-safety mode [LazyThreadSafetyMode.SYNCHRONIZED]. + * + * If the initialization of a value throws an exception, it will attempt to reinitialize the value at next access. + * + * Note that the returned instance uses itself to synchronize on. Do not synchronize from external code on + * the returned instance as it may cause accidental deadlock. Also this behavior can be changed in the future. + */ +public actual fun lazy(initializer: () -> T): Lazy = FreezeAwareLazyImpl(initializer) + +/** + * Creates a new instance of the [Lazy] that uses the specified initialization function [initializer] + * and thread-safety [mode]. + * + * If the initialization of a value throws an exception, it will attempt to reinitialize the value at next access. + * + * Note that when the [LazyThreadSafetyMode.SYNCHRONIZED] mode is specified the returned instance uses itself + * to synchronize on. Do not synchronize from external code on the returned instance as it may cause accidental deadlock. + * Also this behavior can be changed in the future. + */ +@FixmeConcurrency +public actual fun lazy(mode: LazyThreadSafetyMode, initializer: () -> T): Lazy = + when (mode) { + LazyThreadSafetyMode.SYNCHRONIZED -> throw UnsupportedOperationException() + LazyThreadSafetyMode.PUBLICATION -> FreezeAwareLazyImpl(initializer) + LazyThreadSafetyMode.NONE -> UnsafeLazyImpl(initializer) + } + +/** + * Creates a new instance of the [Lazy] that uses the specified initialization function [initializer] + * and the default thread-safety mode [LazyThreadSafetyMode.SYNCHRONIZED]. + * + * If the initialization of a value throws an exception, it will attempt to reinitialize the value at next access. + * + * The returned instance uses the specified [lock] object to synchronize on. + * When the [lock] is not specified the instance uses itself to synchronize on, + * in this case do not synchronize from external code on the returned instance as it may cause accidental deadlock. + * Also this behavior can be changed in the future. + */ +@FixmeConcurrency +@Suppress("UNUSED_PARAMETER") +public actual fun lazy(lock: Any?, initializer: () -> T): Lazy = throw UnsupportedOperationException() \ No newline at end of file diff --git a/kotlin-native/runtime/src/main/kotlin/kotlin/Nothing.kt b/kotlin-native/runtime/src/main/kotlin/kotlin/Nothing.kt new file mode 100644 index 00000000000..3c1219ffd80 --- /dev/null +++ b/kotlin-native/runtime/src/main/kotlin/kotlin/Nothing.kt @@ -0,0 +1,12 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +package kotlin + +/** + * Nothing has no instances. You can use Nothing to represent "a value that never exists": for example, + * if a function has the return type of Nothing, it means that it never returns (always throws an exception). + */ +public final class Nothing private constructor() {} diff --git a/kotlin-native/runtime/src/main/kotlin/kotlin/Number.kt b/kotlin-native/runtime/src/main/kotlin/kotlin/Number.kt new file mode 100644 index 00000000000..be065f9a03a --- /dev/null +++ b/kotlin-native/runtime/src/main/kotlin/kotlin/Number.kt @@ -0,0 +1,47 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +package kotlin + +/** + * Superclass for all platform classes representing numeric values. + */ +public abstract class Number { + /** + * Returns the value of this number as a [Double], which may involve rounding. + */ + public abstract fun toDouble(): Double + + /** + * Returns the value of this number as a [Float], which may involve rounding. + */ + public abstract fun toFloat(): Float + + /** + * Returns the value of this number as a [Long], which may involve rounding or truncation. + */ + public abstract fun toLong(): Long + + /** + * Returns the value of this number as an [Int], which may involve rounding or truncation. + */ + public abstract fun toInt(): Int + + /** + * Returns the [Char] with the numeric value equal to this number, truncated to 16 bits if appropriate. + */ + public abstract fun toChar(): Char + + /** + * Returns the value of this number as a [Short], which may involve rounding or truncation. + */ + public abstract fun toShort(): Short + + /** + * Returns the value of this number as a [Byte], which may involve rounding or truncation. + */ + public abstract fun toByte(): Byte +} + diff --git a/kotlin-native/runtime/src/main/kotlin/kotlin/Numbers.kt b/kotlin-native/runtime/src/main/kotlin/kotlin/Numbers.kt new file mode 100644 index 00000000000..9071f4b0d41 --- /dev/null +++ b/kotlin-native/runtime/src/main/kotlin/kotlin/Numbers.kt @@ -0,0 +1,280 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +package kotlin + +import kotlin.native.internal.TypedIntrinsic +import kotlin.native.internal.IntrinsicType + +/** + * Returns `true` if the specified number is a + * Not-a-Number (NaN) value, `false` otherwise. + */ +@SymbolName("Kotlin_Double_isNaN") +public actual external fun Double.isNaN(): Boolean + +/** + * Returns `true` if the specified number is a + * Not-a-Number (NaN) value, `false` otherwise. + */ +@SymbolName("Kotlin_Float_isNaN") +public actual external fun Float.isNaN(): Boolean + +/** + * Returns `true` if this value is infinitely large in magnitude. + */ +@SymbolName("Kotlin_Double_isInfinite") +public actual external fun Double.isInfinite(): Boolean + +/** + * Returns `true` if this value is infinitely large in magnitude. + */ +@SymbolName("Kotlin_Float_isInfinite") +public actual external fun Float.isInfinite(): Boolean + +/** + * Returns `true` if the argument is a finite floating-point value; returns `false` otherwise (for `NaN` and infinity arguments). + */ +@SymbolName("Kotlin_Double_isFinite") +public actual external fun Double.isFinite(): Boolean + +/** + * Returns `true` if the argument is a finite floating-point value; returns `false` otherwise (for `NaN` and infinity arguments). + */ +@SymbolName("Kotlin_Float_isFinite") +public actual external fun Float.isFinite(): Boolean + +/** + * Returns a bit representation of the specified floating-point value as [Long] + * according to the IEEE 754 floating-point "double format" bit layout. + */ +@SinceKotlin("1.2") +@kotlin.internal.InlineOnly +public actual inline fun Double.toBits(): Long = if (isNaN()) Double.NaN.toRawBits() else toRawBits() + +/** + * Returns a bit representation of the specified floating-point value as [Long] + * according to the IEEE 754 floating-point "double format" bit layout, + * preserving `NaN` values exact layout. + */ +@SinceKotlin("1.2") +@kotlin.internal.InlineOnly +public actual inline fun Double.toRawBits(): Long = bits() + +/** + * Returns the [Double] value corresponding to a given bit representation. + */ +@SinceKotlin("1.2") +@kotlin.internal.InlineOnly +public actual inline fun Double.Companion.fromBits(bits: Long): Double = kotlin.fromBits(bits) + +@PublishedApi +@TypedIntrinsic(IntrinsicType.REINTERPRET) +internal external fun fromBits(bits: Long): Double + +/** + * Returns a bit representation of the specified floating-point value as [Int] + * according to the IEEE 754 floating-point "single format" bit layout. + */ +@SinceKotlin("1.2") +@kotlin.internal.InlineOnly +public actual inline fun Float.toBits(): Int = if (isNaN()) Float.NaN.toRawBits() else toRawBits() + +/** + * Returns a bit representation of the specified floating-point value as [Int] + * according to the IEEE 754 floating-point "single format" bit layout, + * preserving `NaN` values exact layout. + */ +@SinceKotlin("1.2") +@kotlin.internal.InlineOnly +public actual inline fun Float.toRawBits(): Int = bits() + +/** + * Returns the [Float] value corresponding to a given bit representation. + */ +@SinceKotlin("1.2") +@kotlin.internal.InlineOnly +public actual inline fun Float.Companion.fromBits(bits: Int): Float = kotlin.fromBits(bits) + +@PublishedApi +@TypedIntrinsic(IntrinsicType.REINTERPRET) +internal external fun fromBits(bits: Int): Float + +// TODO: Replace 32 and 64 literals with Int/Long.SIZE_BITS constants when constant propagation is working + +/** + * Counts the number of set bits in the binary representation of this [Int] number. + */ +@SinceKotlin("1.4") +@WasExperimental(ExperimentalStdlibApi::class) +@SymbolName("Kotlin_Int_countOneBits") +public actual external fun Int.countOneBits(): Int + +/** + * Counts the number of consecutive most significant bits that are zero in the binary representation of [Int] [value]. + * Returns undefined result for zero [value]. + */ +@SymbolName("Kotlin_Int_countLeadingZeroBits") +private external fun countLeadingZeroBits(value: Int): Int + +/** + * Counts the number of consecutive most significant bits that are zero in the binary representation of this [Int] number. + */ +@SinceKotlin("1.4") +@WasExperimental(ExperimentalStdlibApi::class) +public actual fun Int.countLeadingZeroBits(): Int = + if (this == 0) 32 else countLeadingZeroBits(this) + +/** + * Counts the number of consecutive least significant bits that are zero in the binary representation of [Int] [value]. + * Returns undefined result for zero [value]. + */ +@SymbolName("Kotlin_Int_countTrailingZeroBits") +private external fun countTrailingZeroBits(value: Int): Int + +/** + * Counts the number of consecutive least significant bits that are zero in the binary representation of this [Int] number. + */ +@SinceKotlin("1.4") +@WasExperimental(ExperimentalStdlibApi::class) +public actual fun Int.countTrailingZeroBits(): Int = + if (this == 0) 32 else countTrailingZeroBits(this) + +/** + * Returns a number having a single bit set in the position of the most significant set bit of this [Int] number, + * or zero, if this number is zero. + */ +@SinceKotlin("1.4") +@WasExperimental(ExperimentalStdlibApi::class) +public actual fun Int.takeHighestOneBit(): Int = + if (this == 0) 0 else 1.shl(32 - 1 - countLeadingZeroBits(this)) + +/** + * Returns a number having a single bit set in the position of the least significant set bit of this [Int] number, + * or zero, if this number is zero. + */ +@SinceKotlin("1.4") +@WasExperimental(ExperimentalStdlibApi::class) +public actual fun Int.takeLowestOneBit(): Int = + this and -this + +/** + * Rotates the binary representation of this [Int] number left by the specified [bitCount] number of bits. + * The most significant bits pushed out from the left side reenter the number as the least significant bits on the right side. + * + * Rotating the number left by a negative bit count is the same as rotating it right by the negated bit count: + * `number.rotateLeft(-n) == number.rotateRight(n)` + * + * Rotating by a multiple of [Int.SIZE_BITS] (32) returns the same number, or more generally + * `number.rotateLeft(n) == number.rotateLeft(n % 32)` + */ +@SinceKotlin("1.3") +@ExperimentalStdlibApi +public actual fun Int.rotateLeft(bitCount: Int): Int = + shl(bitCount) or ushr(32 - bitCount) + + +/** + * Rotates the binary representation of this [Int] number right by the specified [bitCount] number of bits. + * The least significant bits pushed out from the right side reenter the number as the most significant bits on the left side. + * + * Rotating the number right by a negative bit count is the same as rotating it left by the negated bit count: + * `number.rotateRight(-n) == number.rotateLeft(n)` + * + * Rotating by a multiple of [Int.SIZE_BITS] (32) returns the same number, or more generally + * `number.rotateRight(n) == number.rotateRight(n % 32)` + */ +@SinceKotlin("1.3") +@ExperimentalStdlibApi +public actual fun Int.rotateRight(bitCount: Int): Int = + shl(32 - bitCount) or ushr(bitCount) + + +/** + * Counts the number of set bits in the binary representation of this [Long] number. + */ +@SinceKotlin("1.4") +@WasExperimental(ExperimentalStdlibApi::class) +@SymbolName("Kotlin_Long_countOneBits") +public actual external fun Long.countOneBits(): Int + +/** + * Counts the number of consecutive most significant bits that are zero in the binary representation of [Long] [value]. + * Returns undefined result for zero [value]. + */ +@SymbolName("Kotlin_Long_countLeadingZeroBits") +private external fun countLeadingZeroBits(value: Long): Int + +/** + * Counts the number of consecutive most significant bits that are zero in the binary representation of this [Long] number. + */ +@SinceKotlin("1.4") +@WasExperimental(ExperimentalStdlibApi::class) +public actual fun Long.countLeadingZeroBits(): Int = + if (this == 0L) 64 else countLeadingZeroBits(this) + +/** + * Counts the number of consecutive least significant bits that are zero in the binary representation of [Long] [value]. + * Returns undefined result for zero [value]. + */ +@SymbolName("Kotlin_Long_countTrailingZeroBits") +private external fun countTrailingZeroBits(value: Long): Int + +/** + * Counts the number of consecutive least significant bits that are zero in the binary representation of this [Long] number. + */ +@SinceKotlin("1.4") +@WasExperimental(ExperimentalStdlibApi::class) +public actual fun Long.countTrailingZeroBits(): Int = + if (this == 0L) 64 else countTrailingZeroBits(this) + +/** + * Returns a number having a single bit set in the position of the most significant set bit of this [Long] number, + * or zero, if this number is zero. + */ +@SinceKotlin("1.4") +@WasExperimental(ExperimentalStdlibApi::class) +public actual fun Long.takeHighestOneBit(): Long = + if (this == 0L) 0L else 1L.shl(64 - 1 - countLeadingZeroBits(this)) + +/** + * Returns a number having a single bit set in the position of the least significant set bit of this [Long] number, + * or zero, if this number is zero. + */ +@SinceKotlin("1.4") +@WasExperimental(ExperimentalStdlibApi::class) +public actual fun Long.takeLowestOneBit(): Long = + this and -this + +/** + * Rotates the binary representation of this [Long] number left by the specified [bitCount] number of bits. + * The most significant bits pushed out from the left side reenter the number as the least significant bits on the right side. + * + * Rotating the number left by a negative bit count is the same as rotating it right by the negated bit count: + * `number.rotateLeft(-n) == number.rotateRight(n)` + * + * Rotating by a multiple of [Long.SIZE_BITS] (64) returns the same number, or more generally + * `number.rotateLeft(n) == number.rotateLeft(n % 64)` + */ +@SinceKotlin("1.3") +@ExperimentalStdlibApi +public actual fun Long.rotateLeft(bitCount: Int): Long = + shl(bitCount) or ushr(64 - bitCount) + +/** + * Rotates the binary representation of this [Long] number right by the specified [bitCount] number of bits. + * The least significant bits pushed out from the right side reenter the number as the most significant bits on the left side. + * + * Rotating the number right by a negative bit count is the same as rotating it left by the negated bit count: + * `number.rotateRight(-n) == number.rotateLeft(n)` + * + * Rotating by a multiple of [Long.SIZE_BITS] (64) returns the same number, or more generally + * `number.rotateRight(n) == number.rotateRight(n % 64)` + */ +@SinceKotlin("1.3") +@ExperimentalStdlibApi +@kotlin.internal.InlineOnly +public actual inline fun Long.rotateRight(bitCount: Int): Long = + shl(64 - bitCount) or ushr(bitCount) diff --git a/kotlin-native/runtime/src/main/kotlin/kotlin/Primitives.kt b/kotlin-native/runtime/src/main/kotlin/kotlin/Primitives.kt new file mode 100644 index 00000000000..ae1473f6da0 --- /dev/null +++ b/kotlin-native/runtime/src/main/kotlin/kotlin/Primitives.kt @@ -0,0 +1,1684 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ +@file:Suppress("OVERRIDE_BY_INLINE", "NOTHING_TO_INLINE") + + +package kotlin + +import kotlin.native.internal.CanBePrecreated +import kotlin.native.internal.IntrinsicType +import kotlin.native.internal.NumberConverter +import kotlin.native.internal.TypedIntrinsic + +/** + * Represents a 8-bit signed integer. + */ +public final class Byte private constructor() : Number(), Comparable { + @CanBePrecreated + companion object { + /** + * A constant holding the minimum value an instance of Byte can have. + */ + public const val MIN_VALUE: Byte = -128 + + /** + * A constant holding the maximum value an instance of Byte can have. + */ + public const val MAX_VALUE: Byte = 127 + + /** + * The number of bytes used to represent an instance of Byte in a binary form. + */ + @SinceKotlin("1.3") + public const val SIZE_BYTES: Int = 1 + + /** + * The number of bits used to represent an instance of Byte in a binary form. + */ + @SinceKotlin("1.3") + public const val SIZE_BITS: Int = 8 + } + + /** + * Compares this value with the specified value for order. + * Returns zero if this value is equal to the specified other value, a negative number if it's less than other, + * or a positive number if it's greater than other. + */ + @TypedIntrinsic(IntrinsicType.SIGNED_COMPARE_TO) + external public override operator fun compareTo(other: Byte): Int + /** + * Compares this value with the specified value for order. + * Returns zero if this value is equal to the specified other value, a negative number if it's less than other, + * or a positive number if it's greater than other. + */ + public inline operator fun compareTo(other: Short): Int = + this.toShort().compareTo(other) + /** + * Compares this value with the specified value for order. + * Returns zero if this value is equal to the specified other value, a negative number if it's less than other, + * or a positive number if it's greater than other. + */ + public inline operator fun compareTo(other: Int): Int = + this.toInt().compareTo(other) + /** + * Compares this value with the specified value for order. + * Returns zero if this value is equal to the specified other value, a negative number if it's less than other, + * or a positive number if it's greater than other. + */ + public inline operator fun compareTo(other: Long): Int = + this.toLong().compareTo(other) + /** + * Compares this value with the specified value for order. + * Returns zero if this value is equal to the specified other value, a negative number if it's less than other, + * or a positive number if it's greater than other. + */ + public inline operator fun compareTo(other: Float): Int = + this.toFloat().compareTo(other) + /** + * Compares this value with the specified value for order. + * Returns zero if this value is equal to the specified other value, a negative number if it's less than other, + * or a positive number if it's greater than other. + */ + public inline operator fun compareTo(other: Double): Int = + this.toDouble().compareTo(other) + + /** Adds the other value to this value. */ + public inline operator fun plus(other: Byte): Int = + this.toInt() + other.toInt() + /** Adds the other value to this value. */ + public inline operator fun plus(other: Short): Int = + this.toInt() + other.toInt() + /** Adds the other value to this value. */ + public inline operator fun plus(other: Int): Int = + this.toInt() + other + /** Adds the other value to this value. */ + public inline operator fun plus(other: Long): Long = + this.toLong() + other + /** Adds the other value to this value. */ + public inline operator fun plus(other: Float): Float = + this.toFloat() + other + /** Adds the other value to this value. */ + public inline operator fun plus(other: Double): Double = + this.toDouble() + other + + /** Subtracts the other value from this value. */ + public inline operator fun minus(other: Byte): Int = + this.toInt() - other.toInt() + /** Subtracts the other value from this value. */ + public inline operator fun minus(other: Short): Int = + this.toInt() - other.toInt() + /** Subtracts the other value from this value. */ + public inline operator fun minus(other: Int): Int = + this.toInt() - other + /** Subtracts the other value from this value. */ + public inline operator fun minus(other: Long): Long = + this.toLong() - other + /** Subtracts the other value from this value. */ + public inline operator fun minus(other: Float): Float = + this.toFloat() - other + /** Subtracts the other value from this value. */ + public inline operator fun minus(other: Double): Double = + this.toDouble() - other + + /** Multiplies this value by the other value. */ + public inline operator fun times(other: Byte): Int = + this.toInt() * other.toInt() + /** Multiplies this value by the other value. */ + public inline operator fun times(other: Short): Int = + this.toInt() * other.toInt() + /** Multiplies this value by the other value. */ + public inline operator fun times(other: Int): Int = + this.toInt() * other + /** Multiplies this value by the other value. */ + public inline operator fun times(other: Long): Long = + this.toLong() * other + /** Multiplies this value by the other value. */ + public inline operator fun times(other: Float): Float = + this.toFloat() * other + /** Multiplies this value by the other value. */ + public inline operator fun times(other: Double): Double = + this.toDouble() * other + + /** Divides this value by the other value. */ + public inline operator fun div(other: Byte): Int = + this.toInt() / other.toInt() + /** Divides this value by the other value. */ + public inline operator fun div(other: Short): Int = + this.toInt() / other.toInt() + /** Divides this value by the other value. */ + public inline operator fun div(other: Int): Int = + this.toInt() / other + /** Divides this value by the other value. */ + public inline operator fun div(other: Long): Long = + this.toLong() / other + /** Divides this value by the other value. */ + public inline operator fun div(other: Float): Float = + this.toFloat() / other + /** Divides this value by the other value. */ + public inline operator fun div(other: Double): Double = + this.toDouble() / other + + /** Calculates the remainder of dividing this value by the other value. */ + public inline operator fun rem(other: Byte): Int = + this.toInt() % other.toInt() + /** Calculates the remainder of dividing this value by the other value. */ + public inline operator fun rem(other: Short): Int = + this.toInt() % other.toInt() + /** Calculates the remainder of dividing this value by the other value. */ + public inline operator fun rem(other: Int): Int = + this.toInt() % other + /** Calculates the remainder of dividing this value by the other value. */ + public inline operator fun rem(other: Long): Long = + this.toLong() % other + /** Calculates the remainder of dividing this value by the other value. */ + public inline operator fun rem(other: Float): Float = + this.toFloat() % other + /** Calculates the remainder of dividing this value by the other value. */ + public inline operator fun rem(other: Double): Double = + this.toDouble() % other + + /** Increments this value. */ + @TypedIntrinsic(IntrinsicType.INC) + external public operator fun inc(): Byte + /** Decrements this value. */ + @TypedIntrinsic(IntrinsicType.DEC) + external public operator fun dec(): Byte + /** Returns this value. */ + public inline operator fun unaryPlus(): Int = + this.toInt() + /** Returns the negative of this value. */ + public inline operator fun unaryMinus(): Int = + -this.toInt() + + /** Returns this value. */ + public inline override fun toByte(): Byte = + this + /** + * Converts this [Byte] value to [Char]. + * + * If this value is non-negative, the resulting `Char` code is equal to this value. + * + * The least significant 8 bits of the resulting `Char` code are the same as the bits of this `Byte` value, + * whereas the most significant 8 bits are filled with the sign bit of this value. + */ + @TypedIntrinsic(IntrinsicType.SIGN_EXTEND) + external public override fun toChar(): Char + /** + * Converts this [Byte] value to [Short]. + * + * The resulting `Short` value represents the same numerical value as this `Byte`. + * + * The least significant 8 bits of the resulting `Short` value are the same as the bits of this `Byte` value, + * whereas the most significant 8 bits are filled with the sign bit of this value. + */ + @TypedIntrinsic(IntrinsicType.SIGN_EXTEND) + external public override fun toShort(): Short + /** + * Converts this [Byte] value to [Int]. + * + * The resulting `Int` value represents the same numerical value as this `Byte`. + * + * The least significant 8 bits of the resulting `Int` value are the same as the bits of this `Byte` value, + * whereas the most significant 24 bits are filled with the sign bit of this value. + */ + @TypedIntrinsic(IntrinsicType.SIGN_EXTEND) + external public override fun toInt(): Int + /** + * Converts this [Byte] value to [Long]. + * + * The resulting `Long` value represents the same numerical value as this `Byte`. + * + * The least significant 8 bits of the resulting `Long` value are the same as the bits of this `Byte` value, + * whereas the most significant 56 bits are filled with the sign bit of this value. + */ + @TypedIntrinsic(IntrinsicType.SIGN_EXTEND) + external public override fun toLong(): Long + /** + * Converts this [Byte] value to [Float]. + * + * The resulting `Float` value represents the same numerical value as this `Byte`. + */ + @TypedIntrinsic(IntrinsicType.SIGNED_TO_FLOAT) + external public override fun toFloat(): Float + /** + * Converts this [Byte] value to [Double]. + * + * The resulting `Double` value represents the same numerical value as this `Byte`. + */ + @TypedIntrinsic(IntrinsicType.SIGNED_TO_FLOAT) + external public override fun toDouble(): Double + + /** Creates a range from this value to the specified [other] value. */ + public operator fun rangeTo(other: Byte): IntRange { + return IntRange(this.toInt(), other.toInt()) + } + /** Creates a range from this value to the specified [other] value. */ + public operator fun rangeTo(other: Short): IntRange { + return IntRange(this.toInt(), other.toInt()) + } + /** Creates a range from this value to the specified [other] value. */ + public operator fun rangeTo(other: Int): IntRange { + return IntRange(this.toInt(), other.toInt()) + } + /** Creates a range from this value to the specified [other] value. */ + public operator fun rangeTo(other: Long): LongRange { + return LongRange(this.toLong(), other.toLong()) + } + + // Konan-specific. + public fun equals(other: Byte): Boolean = kotlin.native.internal.areEqualByValue(this, other) + + public override fun equals(other: Any?): Boolean = + other is Byte && kotlin.native.internal.areEqualByValue(this, other) + + @SymbolName("Kotlin_Byte_toString") + external public override fun toString(): String + + public override fun hashCode(): Int { + return this.toInt() + } +} + +/** + * Represents a 16-bit signed integer. + */ +public final class Short private constructor() : Number(), Comparable { + @CanBePrecreated + companion object { + /** + * A constant holding the minimum value an instance of Short can have. + */ + public const val MIN_VALUE: Short = -32768 + + /** + * A constant holding the maximum value an instance of Short can have. + */ + public const val MAX_VALUE: Short = 32767 + + /** + * The number of bytes used to represent an instance of Short in a binary form. + */ + @SinceKotlin("1.3") + public const val SIZE_BYTES: Int = 2 + + /** + * The number of bits used to represent an instance of Short in a binary form. + */ + @SinceKotlin("1.3") + public const val SIZE_BITS: Int = 16 + } + + /** + * Compares this value with the specified value for order. + * Returns zero if this value is equal to the specified other value, a negative number if it's less than other, + * or a positive number if it's greater than other. + */ + public inline operator fun compareTo(other: Byte): Int = + this.compareTo(other.toShort()) + /** + * Compares this value with the specified value for order. + * Returns zero if this value is equal to the specified other value, a negative number if it's less than other, + * or a positive number if it's greater than other. + */ + @TypedIntrinsic(IntrinsicType.SIGNED_COMPARE_TO) + external public override operator fun compareTo(other: Short): Int + /** + * Compares this value with the specified value for order. + * Returns zero if this value is equal to the specified other value, a negative number if it's less than other, + * or a positive number if it's greater than other. + */ + public inline operator fun compareTo(other: Int): Int = + this.toInt().compareTo(other) + /** + * Compares this value with the specified value for order. + * Returns zero if this value is equal to the specified other value, a negative number if it's less than other, + * or a positive number if it's greater than other. + */ + public inline operator fun compareTo(other: Long): Int = + this.toLong().compareTo(other) + /** + * Compares this value with the specified value for order. + * Returns zero if this value is equal to the specified other value, a negative number if it's less than other, + * or a positive number if it's greater than other. + */ + public inline operator fun compareTo(other: Float): Int = + this.toFloat().compareTo(other) + /** + * Compares this value with the specified value for order. + * Returns zero if this value is equal to the specified other value, a negative number if it's less than other, + * or a positive number if it's greater than other. + */ + public inline operator fun compareTo(other: Double): Int = + this.toDouble().compareTo(other) + + /** Adds the other value to this value. */ + public inline operator fun plus(other: Byte): Int = + this.toInt() + other.toInt() + /** Adds the other value to this value. */ + public inline operator fun plus(other: Short): Int = + this.toInt() + other.toInt() + /** Adds the other value to this value. */ + public inline operator fun plus(other: Int): Int = + this.toInt() + other + /** Adds the other value to this value. */ + public inline operator fun plus(other: Long): Long = + this.toLong() + other + /** Adds the other value to this value. */ + public inline operator fun plus(other: Float): Float = + this.toFloat() + other + /** Adds the other value to this value. */ + public inline operator fun plus(other: Double): Double = + this.toDouble() + other + + /** Subtracts the other value from this value. */ + public inline operator fun minus(other: Byte): Int = + this.toInt() - other.toInt() + /** Subtracts the other value from this value. */ + public inline operator fun minus(other: Short): Int = + this.toInt() - other.toInt() + /** Subtracts the other value from this value. */ + public inline operator fun minus(other: Int): Int = + this.toInt() - other + /** Subtracts the other value from this value. */ + public inline operator fun minus(other: Long): Long = + this.toLong() - other + /** Subtracts the other value from this value. */ + public inline operator fun minus(other: Float): Float = + this.toFloat() - other + /** Subtracts the other value from this value. */ + public inline operator fun minus(other: Double): Double = + this.toDouble() - other + + /** Multiplies this value by the other value. */ + public inline operator fun times(other: Byte): Int = + this.toInt() * other.toInt() + /** Multiplies this value by the other value. */ + public inline operator fun times(other: Short): Int = + this.toInt() * other.toInt() + /** Multiplies this value by the other value. */ + public inline operator fun times(other: Int): Int = + this.toInt() * other + /** Multiplies this value by the other value. */ + public inline operator fun times(other: Long): Long = + this.toLong() * other + /** Multiplies this value by the other value. */ + public inline operator fun times(other: Float): Float = + this.toFloat() * other + /** Multiplies this value by the other value. */ + public inline operator fun times(other: Double): Double = + this.toDouble() * other + + /** Divides this value by the other value. */ + public inline operator fun div(other: Byte): Int = + this.toInt() / other.toInt() + /** Divides this value by the other value. */ + public inline operator fun div(other: Short): Int = + this.toInt() / other.toInt() + /** Divides this value by the other value. */ + public inline operator fun div(other: Int): Int = + this.toInt() / other + /** Divides this value by the other value. */ + public inline operator fun div(other: Long): Long = + this.toLong() / other + /** Divides this value by the other value. */ + public inline operator fun div(other: Float): Float = + this.toFloat() / other + /** Divides this value by the other value. */ + public inline operator fun div(other: Double): Double = + this.toDouble() / other + + /** Calculates the remainder of dividing this value by the other value. */ + public inline operator fun rem(other: Byte): Int = + this.toInt() % other.toInt() + /** Calculates the remainder of dividing this value by the other value. */ + public inline operator fun rem(other: Short): Int = + this.toInt() % other.toInt() + /** Calculates the remainder of dividing this value by the other value. */ + public inline operator fun rem(other: Int): Int = + this.toInt() % other + /** Calculates the remainder of dividing this value by the other value. */ + public inline operator fun rem(other: Long): Long = + this.toLong() % other + /** Calculates the remainder of dividing this value by the other value. */ + public inline operator fun rem(other: Float): Float = + this.toFloat() % other + /** Calculates the remainder of dividing this value by the other value. */ + public inline operator fun rem(other: Double): Double = + this.toDouble() % other + + /** Increments this value. */ + @TypedIntrinsic(IntrinsicType.INC) + external public operator fun inc(): Short + /** Decrements this value. */ + @TypedIntrinsic(IntrinsicType.DEC) + external public operator fun dec(): Short + /** Returns this value. */ + public operator fun unaryPlus(): Int = + this.toInt() + /** Returns the negative of this value. */ + public inline operator fun unaryMinus(): Int = + -this.toInt() + + /** Creates a range from this value to the specified [other] value. */ + public operator fun rangeTo(other: Byte): IntRange { + return IntRange(this.toInt(), other.toInt()) + } + /** Creates a range from this value to the specified [other] value. */ + public operator fun rangeTo(other: Short): IntRange { + return IntRange(this.toInt(), other.toInt()) + } + /** Creates a range from this value to the specified [other] value. */ + public operator fun rangeTo(other: Int): IntRange { + return IntRange(this.toInt(), other.toInt()) + } + /** Creates a range from this value to the specified [other] value. */ + public operator fun rangeTo(other: Long): LongRange { + return LongRange(this.toLong(), other.toLong()) + } + + /** + * Converts this [Short] value to [Byte]. + * + * If this value is in [Byte.MIN_VALUE]..[Byte.MAX_VALUE], the resulting `Byte` value represents + * the same numerical value as this `Short`. + * + * The resulting `Byte` value is represented by the least significant 8 bits of this `Short` value. + */ + @TypedIntrinsic(IntrinsicType.INT_TRUNCATE) + external public override fun toByte(): Byte + /** + * Converts this [Short] value to [Char]. + * + * The resulting `Char` code is equal to this value reinterpreted as an unsigned number, + * i.e. it has the same binary representation as this `Short`. + */ + @TypedIntrinsic(IntrinsicType.ZERO_EXTEND) + external public override fun toChar(): Char + + /** Returns this value. */ + public inline override fun toShort(): Short = + this + /** + * Converts this [Short] value to [Int]. + * + * The resulting `Int` value represents the same numerical value as this `Short`. + * + * The least significant 16 bits of the resulting `Int` value are the same as the bits of this `Short` value, + * whereas the most significant 16 bits are filled with the sign bit of this value. + */ + @TypedIntrinsic(IntrinsicType.SIGN_EXTEND) + external public override fun toInt(): Int + /** + * Converts this [Short] value to [Long]. + * + * The resulting `Long` value represents the same numerical value as this `Short`. + * + * The least significant 16 bits of the resulting `Long` value are the same as the bits of this `Short` value, + * whereas the most significant 48 bits are filled with the sign bit of this value. + */ + @TypedIntrinsic(IntrinsicType.SIGN_EXTEND) + external public override fun toLong(): Long + /** + * Converts this [Short] value to [Float]. + * + * The resulting `Float` value represents the same numerical value as this `Short`. + */ + @TypedIntrinsic(IntrinsicType.SIGNED_TO_FLOAT) + external public override fun toFloat(): Float + /** + * Converts this [Short] value to [Double]. + * + * The resulting `Double` value represents the same numerical value as this `Short`. + */ + @TypedIntrinsic(IntrinsicType.SIGNED_TO_FLOAT) + external public override fun toDouble(): Double + + // Konan-specific. + public fun equals(other: Short): Boolean = kotlin.native.internal.areEqualByValue(this, other) + + public override fun equals(other: Any?): Boolean = + other is Short && kotlin.native.internal.areEqualByValue(this, other) + + @SymbolName("Kotlin_Short_toString") + external public override fun toString(): String + + public override fun hashCode(): Int { + return this.toInt() + } +} + +/** + * Represents a 32-bit signed integer. + */ +public final class Int private constructor() : Number(), Comparable { + @CanBePrecreated + companion object { + /** + * A constant holding the minimum value an instance of Int can have. + */ + public const val MIN_VALUE: Int = -2147483648 + + /** + * A constant holding the maximum value an instance of Int can have. + */ + public const val MAX_VALUE: Int = 2147483647 + + /** + * The number of bytes used to represent an instance of Int in a binary form. + */ + @SinceKotlin("1.3") + public const val SIZE_BYTES: Int = 4 + + /** + * The number of bits used to represent an instance of Int in a binary form. + */ + @SinceKotlin("1.3") + public const val SIZE_BITS: Int = 32 + } + + /** + * Compares this value with the specified value for order. + * Returns zero if this value is equal to the specified other value, a negative number if it's less than other, + * or a positive number if it's greater than other. + */ + public inline operator fun compareTo(other: Byte): Int = + this.compareTo(other.toInt()) + /** + * Compares this value with the specified value for order. + * Returns zero if this value is equal to the specified other value, a negative number if it's less than other, + * or a positive number if it's greater than other. + */ + public inline operator fun compareTo(other: Short): Int = + this.compareTo(other.toInt()) + /** + * Compares this value with the specified value for order. + * Returns zero if this value is equal to the specified other value, a negative number if it's less than other, + * or a positive number if it's greater than other. + */ + @TypedIntrinsic(IntrinsicType.SIGNED_COMPARE_TO) + external public override operator fun compareTo(other: Int): Int + /** + * Compares this value with the specified value for order. + * Returns zero if this value is equal to the specified other value, a negative number if it's less than other, + * or a positive number if it's greater than other. + */ + public inline operator fun compareTo(other: Long): Int = + this.toLong().compareTo(other) + /** + * Compares this value with the specified value for order. + * Returns zero if this value is equal to the specified other value, a negative number if it's less than other, + * or a positive number if it's greater than other. + */ + public inline operator fun compareTo(other: Float): Int = + this.toFloat().compareTo(other) + /** + * Compares this value with the specified value for order. + * Returns zero if this value is equal to the specified other value, a negative number if it's less than other, + * or a positive number if it's greater than other. + */ + public inline operator fun compareTo(other: Double): Int = + this.toDouble().compareTo(other) + + /** Adds the other value to this value. */ + public inline operator fun plus(other: Byte): Int = + this + other.toInt() + /** Adds the other value to this value. */ + public inline operator fun plus(other: Short): Int = + this + other.toInt() + /** Adds the other value to this value. */ + @TypedIntrinsic(IntrinsicType.PLUS) + external public operator fun plus(other: Int): Int + /** Adds the other value to this value. */ + public inline operator fun plus(other: Long): Long = + this.toLong() + other + /** Adds the other value to this value. */ + public inline operator fun plus(other: Float): Float = + this.toFloat() + other + /** Adds the other value to this value. */ + public inline operator fun plus(other: Double): Double = + this.toDouble() + other + + /** Subtracts the other value from this value. */ + public inline operator fun minus(other: Byte): Int = + this - other.toInt() + /** Subtracts the other value from this value. */ + public inline operator fun minus(other: Short): Int = + this - other.toInt() + /** Subtracts the other value from this value. */ + @TypedIntrinsic(IntrinsicType.MINUS) + external public operator fun minus(other: Int): Int + /** Subtracts the other value from this value. */ + public inline operator fun minus(other: Long): Long = + this.toLong() - other + /** Subtracts the other value from this value. */ + public inline operator fun minus(other: Float): Float = + this.toFloat() - other + /** Subtracts the other value from this value. */ + public inline operator fun minus(other: Double): Double = + this.toDouble() - other + + /** Multiplies this value by the other value. */ + public inline operator fun times(other: Byte): Int = + this * other.toInt() + /** Multiplies this value by the other value. */ + public inline operator fun times(other: Short): Int = + this * other.toInt() + /** Multiplies this value by the other value. */ + @TypedIntrinsic(IntrinsicType.TIMES) + external public operator fun times(other: Int): Int + /** Multiplies this value by the other value. */ + public inline operator fun times(other: Long): Long = + this.toLong() * other + /** Multiplies this value by the other value. */ + public inline operator fun times(other: Float): Float = + this.toFloat() * other + /** Multiplies this value by the other value. */ + public inline operator fun times(other: Double): Double = + this.toDouble() * other + + /** Divides this value by the other value. */ + public inline operator fun div(other: Byte): Int = + this / other.toInt() + /** Divides this value by the other value. */ + public inline operator fun div(other: Short): Int = + this / other.toInt() + /** Divides this value by the other value. */ + @TypedIntrinsic(IntrinsicType.SIGNED_DIV) + external public operator fun div(other: Int): Int + /** Divides this value by the other value. */ + public inline operator fun div(other: Long): Long = + this.toLong() / other + /** Divides this value by the other value. */ + public inline operator fun div(other: Float): Float = + this.toFloat() / other + /** Divides this value by the other value. */ + public inline operator fun div(other: Double): Double = + this.toDouble() / other + + /** Calculates the remainder of dividing this value by the other value. */ + public inline operator fun rem(other: Byte): Int = + this % other.toInt() + /** Calculates the remainder of dividing this value by the other value. */ + public inline operator fun rem(other: Short): Int = + this % other.toInt() + /** Calculates the remainder of dividing this value by the other value. */ + @TypedIntrinsic(IntrinsicType.SIGNED_REM) + external public operator fun rem(other: Int): Int + /** Calculates the remainder of dividing this value by the other value. */ + public inline operator fun rem(other: Long): Long = + this.toLong() % other + /** Calculates the remainder of dividing this value by the other value. */ + public inline operator fun rem(other: Float): Float = + this.toFloat() % other + /** Calculates the remainder of dividing this value by the other value. */ + public inline operator fun rem(other: Double): Double = + this.toDouble() % other + + /** Increments this value. */ + @TypedIntrinsic(IntrinsicType.INC) + external public operator fun inc(): Int + /** Decrements this value. */ + @TypedIntrinsic(IntrinsicType.DEC) + external public operator fun dec(): Int + /** Returns this value. */ + @TypedIntrinsic(IntrinsicType.UNARY_PLUS) + external public operator fun unaryPlus(): Int + /** Returns the negative of this value. */ + @TypedIntrinsic(IntrinsicType.UNARY_MINUS) + external public operator fun unaryMinus(): Int + + /** Shifts this value left by the [bitCount] number of bits. */ + @TypedIntrinsic(IntrinsicType.SHL) + external public infix fun shl(bitCount: Int): Int + /** Shifts this value right by the [bitCount] number of bits, filling the leftmost bits with copies of the sign bit. */ + @TypedIntrinsic(IntrinsicType.SHR) + external public infix fun shr(bitCount: Int): Int + /** Shifts this value right by the [bitCount] number of bits, filling the leftmost bits with zeros. */ + @TypedIntrinsic(IntrinsicType.USHR) + external public infix fun ushr(bitCount: Int): Int + /** Performs a bitwise AND operation between the two values. */ + @TypedIntrinsic(IntrinsicType.AND) + external public infix fun and(other: Int): Int + /** Performs a bitwise OR operation between the two values. */ + @TypedIntrinsic(IntrinsicType.OR) + external public infix fun or(other: Int): Int + /** Performs a bitwise XOR operation between the two values. */ + @TypedIntrinsic(IntrinsicType.XOR) + external public infix fun xor(other: Int): Int + /** Inverts the bits in this value. */ + @TypedIntrinsic(IntrinsicType.INV) + external public fun inv(): Int + + /** Creates a range from this value to the specified [other] value. */ + public operator fun rangeTo(other: Byte): IntRange { + return IntRange(this, other.toInt()) + } + /** Creates a range from this value to the specified [other] value. */ + public operator fun rangeTo(other: Short): IntRange { + return IntRange(this, other.toInt()) + } + /** Creates a range from this value to the specified [other] value. */ + public operator fun rangeTo(other: Int): IntRange { + return IntRange(this, other.toInt()) + } + /** Creates a range from this value to the specified [other] value. */ + public operator fun rangeTo(other: Long): LongRange { + return LongRange(this.toLong(), other.toLong()) + } + + /** + * Converts this [Int] value to [Byte]. + * + * If this value is in [Byte.MIN_VALUE]..[Byte.MAX_VALUE], the resulting `Byte` value represents + * the same numerical value as this `Int`. + * + * The resulting `Byte` value is represented by the least significant 8 bits of this `Int` value. + */ + @TypedIntrinsic(IntrinsicType.INT_TRUNCATE) + external public override fun toByte(): Byte + /** + * Converts this [Int] value to [Char]. + * + * If this value is in the range of `Char` codes `Char.MIN_VALUE..Char.MAX_VALUE`, + * the resulting `Char` code is equal to this value. + * + * The resulting `Char` code is represented by the least significant 16 bits of this `Int` value. + */ + @TypedIntrinsic(IntrinsicType.INT_TRUNCATE) + external public override fun toChar(): Char + /** + * Converts this [Int] value to [Short]. + * + * If this value is in [Short.MIN_VALUE]..[Short.MAX_VALUE], the resulting `Short` value represents + * the same numerical value as this `Int`. + * + * The resulting `Short` value is represented by the least significant 16 bits of this `Int` value. + */ + @TypedIntrinsic(IntrinsicType.INT_TRUNCATE) + external public override fun toShort(): Short + + /** Returns this value. */ + public inline override fun toInt(): Int = + this + /** + * Converts this [Int] value to [Long]. + * + * The resulting `Long` value represents the same numerical value as this `Int`. + * + * The least significant 32 bits of the resulting `Long` value are the same as the bits of this `Int` value, + * whereas the most significant 32 bits are filled with the sign bit of this value. + */ + @TypedIntrinsic(IntrinsicType.SIGN_EXTEND) + external public override fun toLong(): Long + /** + * Converts this [Int] value to [Float]. + * + * The resulting value is the closest `Float` to this `Int` value. + * In case when this `Int` value is exactly between two `Float`s, + * the one with zero at least significant bit of mantissa is selected. + */ + @TypedIntrinsic(IntrinsicType.SIGNED_TO_FLOAT) + external public override fun toFloat(): Float + /** + * Converts this [Int] value to [Double]. + * + * The resulting `Double` value represents the same numerical value as this `Int`. + */ + @TypedIntrinsic(IntrinsicType.SIGNED_TO_FLOAT) + external public override fun toDouble(): Double + + // Konan-specific. + public fun equals(other: Int): Boolean = kotlin.native.internal.areEqualByValue(this, other) + + public override fun equals(other: Any?): Boolean = + other is Int && kotlin.native.internal.areEqualByValue(this, other) + + @SymbolName("Kotlin_Int_toString") + external public override fun toString(): String + + public override fun hashCode(): Int { + return this + } +} + +/** + * Represents a 64-bit signed integer. + */ +public final class Long private constructor() : Number(), Comparable { + @CanBePrecreated + companion object { + /** + * A constant holding the minimum value an instance of Long can have. + */ + public const val MIN_VALUE: Long = -9223372036854775807L - 1L + + /** + * A constant holding the maximum value an instance of Long can have. + */ + public const val MAX_VALUE: Long = 9223372036854775807L + + /** + * The number of bytes used to represent an instance of Long in a binary form. + */ + @SinceKotlin("1.3") + public const val SIZE_BYTES: Int = 8 + + /** + * The number of bits used to represent an instance of Long in a binary form. + */ + @SinceKotlin("1.3") + public const val SIZE_BITS: Int = 64 + } + + /** + * Compares this value with the specified value for order. + * Returns zero if this value is equal to the specified other value, a negative number if it's less than other, + * or a positive number if it's greater than other. + */ + public inline operator fun compareTo(other: Byte): Int = + this.compareTo(other.toLong()) + /** + * Compares this value with the specified value for order. + * Returns zero if this value is equal to the specified other value, a negative number if it's less than other, + * or a positive number if it's greater than other. + */ + public inline operator fun compareTo(other: Short): Int = + this.compareTo(other.toLong()) + /** + * Compares this value with the specified value for order. + * Returns zero if this value is equal to the specified other value, a negative number if it's less than other, + * or a positive number if it's greater than other. + */ + public inline operator fun compareTo(other: Int): Int = + this.compareTo(other.toLong()) + /** + * Compares this value with the specified value for order. + * Returns zero if this value is equal to the specified other value, a negative number if it's less than other, + * or a positive number if it's greater than other. + */ + @TypedIntrinsic(IntrinsicType.SIGNED_COMPARE_TO) + external public override operator fun compareTo(other: Long): Int + /** + * Compares this value with the specified value for order. + * Returns zero if this value is equal to the specified other value, a negative number if it's less than other, + * or a positive number if it's greater than other. + */ + public inline operator fun compareTo(other: Float): Int = + this.toFloat().compareTo(other) + /** + * Compares this value with the specified value for order. + * Returns zero if this value is equal to the specified other value, a negative number if it's less than other, + * or a positive number if it's greater than other. + */ + public inline operator fun compareTo(other: Double): Int = + this.toDouble().compareTo(other) + + /** Adds the other value to this value. */ + public inline operator fun plus(other: Byte): Long = + this + other.toLong() + /** Adds the other value to this value. */ + public inline operator fun plus(other: Short): Long = + this + other.toLong() + /** Adds the other value to this value. */ + public inline operator fun plus(other: Int): Long = + this + other.toLong() + /** Adds the other value to this value. */ + @TypedIntrinsic(IntrinsicType.PLUS) + external public operator fun plus(other: Long): Long + /** Adds the other value to this value. */ + public inline operator fun plus(other: Float): Float = + this.toFloat() + other + /** Adds the other value to this value. */ + public inline operator fun plus(other: Double): Double = + this.toDouble() + other + + /** Subtracts the other value from this value. */ + public inline operator fun minus(other: Byte): Long = + this - other.toLong() + /** Subtracts the other value from this value. */ + public inline operator fun minus(other: Short): Long = + this - other.toLong() + /** Subtracts the other value from this value. */ + public inline operator fun minus(other: Int): Long = + this - other.toLong() + /** Subtracts the other value from this value. */ + @TypedIntrinsic(IntrinsicType.MINUS) + external public operator fun minus(other: Long): Long + /** Subtracts the other value from this value. */ + public inline operator fun minus(other: Float): Float = + this.toFloat() - other + /** Subtracts the other value from this value. */ + public inline operator fun minus(other: Double): Double = + this.toDouble() - other + + /** Multiplies this value by the other value. */ + public inline operator fun times(other: Byte): Long = + this * other.toLong() + /** Multiplies this value by the other value. */ + public inline operator fun times(other: Short): Long = + this * other.toLong() + /** Multiplies this value by the other value. */ + public inline operator fun times(other: Int): Long = + this * other.toLong() + /** Multiplies this value by the other value. */ + @TypedIntrinsic(IntrinsicType.TIMES) + external public operator fun times(other: Long): Long + /** Multiplies this value by the other value. */ + public inline operator fun times(other: Float): Float = + this.toFloat() * other + /** Multiplies this value by the other value. */ + public inline operator fun times(other: Double): Double = + this.toDouble() * other + + /** Divides this value by the other value. */ + public inline operator fun div(other: Byte): Long = + this / other.toLong() + /** Divides this value by the other value. */ + public inline operator fun div(other: Short): Long = + this / other.toLong() + /** Divides this value by the other value. */ + public inline operator fun div(other: Int): Long = + this / other.toLong() + /** Divides this value by the other value. */ + @TypedIntrinsic(IntrinsicType.SIGNED_DIV) + external public operator fun div(other: Long): Long + /** Divides this value by the other value. */ + public inline operator fun div(other: Float): Float = + this.toFloat() / other + /** Divides this value by the other value. */ + public inline operator fun div(other: Double): Double = + this.toDouble() / other + + /** Calculates the remainder of dividing this value by the other value. */ + public inline operator fun rem(other: Byte): Long = + this % other.toLong() + /** Calculates the remainder of dividing this value by the other value. */ + public inline operator fun rem(other: Short): Long = + this % other.toLong() + /** Calculates the remainder of dividing this value by the other value. */ + public inline operator fun rem(other: Int): Long = + this % other.toLong() + /** Calculates the remainder of dividing this value by the other value. */ + @TypedIntrinsic(IntrinsicType.SIGNED_REM) + external public operator fun rem(other: Long): Long + /** Calculates the remainder of dividing this value by the other value. */ + public inline operator fun rem(other: Float): Float = + this.toFloat() % other + /** Calculates the remainder of dividing this value by the other value. */ + public inline operator fun rem(other: Double): Double = + this.toDouble() % other + + /** Increments this value. */ + @TypedIntrinsic(IntrinsicType.INC) + external public operator fun inc(): Long + /** Decrements this value. */ + @TypedIntrinsic(IntrinsicType.DEC) + external public operator fun dec(): Long + /** Returns this value. */ + public inline operator fun unaryPlus(): Long = + this + /** Returns the negative of this value. */ + @TypedIntrinsic(IntrinsicType.UNARY_MINUS) + external public operator fun unaryMinus(): Long + + /** Creates a range from this value to the specified [other] value. */ + public operator fun rangeTo(other: Byte): LongRange { + return LongRange(this, other.toLong()) + } + /** Creates a range from this value to the specified [other] value. */ + public operator fun rangeTo(other: Short): LongRange { + return LongRange(this, other.toLong()) + } + /** Creates a range from this value to the specified [other] value. */ + public operator fun rangeTo(other: Int): LongRange { + return LongRange(this, other.toLong()) + } + /** Creates a range from this value to the specified [other] value. */ + public operator fun rangeTo(other: Long): LongRange { + return LongRange(this, other.toLong()) + } + + /** Shifts this value left by the [bitCount] number of bits. */ + @TypedIntrinsic(IntrinsicType.SHL) + external public infix fun shl(bitCount: Int): Long + /** Shifts this value right by the [bitCount] number of bits, filling the leftmost bits with copies of the sign bit. */ + @TypedIntrinsic(IntrinsicType.SHR) + external public infix fun shr(bitCount: Int): Long + /** Shifts this value right by the [bitCount] number of bits, filling the leftmost bits with zeros. */ + @TypedIntrinsic(IntrinsicType.USHR) + external public infix fun ushr(bitCount: Int): Long + /** Performs a bitwise AND operation between the two values. */ + @TypedIntrinsic(IntrinsicType.AND) + external public infix fun and(other: Long): Long + /** Performs a bitwise OR operation between the two values. */ + @TypedIntrinsic(IntrinsicType.OR) + external public infix fun or(other: Long): Long + /** Performs a bitwise XOR operation between the two values. */ + @TypedIntrinsic(IntrinsicType.XOR) + external public infix fun xor(other: Long): Long + /** Inverts the bits in this value. */ + @TypedIntrinsic(IntrinsicType.INV) + external public fun inv(): Long + + /** + * Converts this [Long] value to [Byte]. + * + * If this value is in [Byte.MIN_VALUE]..[Byte.MAX_VALUE], the resulting `Byte` value represents + * the same numerical value as this `Long`. + * + * The resulting `Byte` value is represented by the least significant 8 bits of this `Long` value. + */ + @TypedIntrinsic(IntrinsicType.INT_TRUNCATE) + external public override fun toByte(): Byte + /** + * Converts this [Long] value to [Char]. + * + * If this value is in the range of `Char` codes `Char.MIN_VALUE..Char.MAX_VALUE`, + * the resulting `Char` code is equal to this value. + * + * The resulting `Char` code is represented by the least significant 16 bits of this `Long` value. + */ + @TypedIntrinsic(IntrinsicType.INT_TRUNCATE) + external public override fun toChar(): Char + /** + * Converts this [Long] value to [Short]. + * + * If this value is in [Short.MIN_VALUE]..[Short.MAX_VALUE], the resulting `Short` value represents + * the same numerical value as this `Long`. + * + * The resulting `Short` value is represented by the least significant 16 bits of this `Long` value. + */ + @TypedIntrinsic(IntrinsicType.INT_TRUNCATE) + external public override fun toShort(): Short + /** + * Converts this [Long] value to [Int]. + * + * If this value is in [Int.MIN_VALUE]..[Int.MAX_VALUE], the resulting `Int` value represents + * the same numerical value as this `Long`. + * + * The resulting `Int` value is represented by the least significant 32 bits of this `Long` value. + */ + @TypedIntrinsic(IntrinsicType.INT_TRUNCATE) + external public override fun toInt(): Int + + /** Returns this value. */ + public inline override fun toLong(): Long = + this + /** + * Converts this [Long] value to [Float]. + * + * The resulting value is the closest `Float` to this `Long` value. + * In case when this `Long` value is exactly between two `Float`s, + * the one with zero at least significant bit of mantissa is selected. + */ + @TypedIntrinsic(IntrinsicType.SIGNED_TO_FLOAT) + external public override fun toFloat(): Float + /** + * Converts this [Long] value to [Double]. + * + * The resulting value is the closest `Double` to this `Long` value. + * In case when this `Long` value is exactly between two `Double`s, + * the one with zero at least significant bit of mantissa is selected. + */ + @TypedIntrinsic(IntrinsicType.SIGNED_TO_FLOAT) + external public override fun toDouble(): Double + + // Konan-specific. + public fun equals(other: Long): Boolean = kotlin.native.internal.areEqualByValue(this, other) + + public override fun equals(other: Any?): Boolean = + other is Long && kotlin.native.internal.areEqualByValue(this, other) + + @SymbolName("Kotlin_Long_toString") + external public override fun toString(): String + + public override fun hashCode(): Int { + return ((this ushr 32) xor this).toInt() + } +} + +/** + * Represents a single-precision 32-bit IEEE 754 floating point number. + */ +public final class Float private constructor() : Number(), Comparable { + companion object { + /** + * A constant holding the smallest *positive* nonzero value of Float. + */ + public const val MIN_VALUE: Float = 1.40129846432481707e-45f + + /** + * A constant holding the largest positive finite value of Float. + */ + public const val MAX_VALUE: Float = 3.40282346638528860e+38f + + /** + * A constant holding the positive infinity value of Float. + */ + @Suppress("DIVISION_BY_ZERO") + public const val POSITIVE_INFINITY: Float = 1.0f / 0.0f + + /** + * A constant holding the negative infinity value of Float. + */ + @Suppress("DIVISION_BY_ZERO") + public const val NEGATIVE_INFINITY: Float = -1.0f / 0.0f + + /** + * A constant holding the "not a number" value of Float. + */ + @Suppress("DIVISION_BY_ZERO") + public const val NaN: Float = -(0.0f / 0.0f) + + /** + * The number of bytes used to represent an instance of Float in a binary form. + */ + @SinceKotlin("1.4") + public const val SIZE_BYTES: Int = 4 + + /** + * The number of bits used to represent an instance of Float in a binary form. + */ + @SinceKotlin("1.4") + public const val SIZE_BITS: Int = 32 + } + + /** + * Compares this value with the specified value for order. + * Returns zero if this value is equal to the specified other value, a negative number if it's less than other, + * or a positive number if it's greater than other. + */ + public operator fun compareTo(other: Byte): Int = compareTo(other.toFloat()) + /** + * Compares this value with the specified value for order. + * Returns zero if this value is equal to the specified other value, a negative number if it's less than other, + * or a positive number if it's greater than other. + */ + public operator fun compareTo(other: Short): Int = compareTo(other.toFloat()) + /** + * Compares this value with the specified value for order. + * Returns zero if this value is equal to the specified other value, a negative number if it's less than other, + * or a positive number if it's greater than other. + */ + public operator fun compareTo(other: Int): Int = compareTo(other.toFloat()) + /** + * Compares this value with the specified value for order. + * Returns zero if this value is equal to the specified other value, a negative number if it's less than other, + * or a positive number if it's greater than other. + */ + public operator fun compareTo(other: Long): Int = compareTo(other.toFloat()) + /** + * Compares this value with the specified value for order. + * Returns zero if this value is equal to the specified other value, a negative number if it's less than other, + * or a positive number if it's greater than other. + */ + public override operator fun compareTo(other: Float): Int { + // if any of values in NaN both comparisons return false + if (this > other) return 1 + if (this < other) return -1 + + val thisBits = this.toBits() + val otherBits = other.toBits() + + // Canonical NaN bits representation higher than any other bit representvalue + return thisBits.compareTo(otherBits) + } + + /** + * Compares this value with the specified value for order. + * Returns zero if this value is equal to the specified other value, a negative number if it's less than other, + * or a positive number if it's greater than other. + */ + public operator fun compareTo(other: Double): Int = - other.compareTo(this) + + /** Adds the other value to this value. */ + public inline operator fun plus(other: Byte): Float = + this + other.toFloat() + /** Adds the other value to this value. */ + public inline operator fun plus(other: Short): Float = + this + other.toFloat() + /** Adds the other value to this value. */ + public inline operator fun plus(other: Int): Float = + this + other.toFloat() + /** Adds the other value to this value. */ + public inline operator fun plus(other: Long): Float = + this + other.toFloat() + /** Adds the other value to this value. */ + @TypedIntrinsic(IntrinsicType.PLUS) + external public operator fun plus(other: Float): Float + /** Adds the other value to this value. */ + public inline operator fun plus(other: Double): Double = + this.toDouble() + other + + /** Subtracts the other value from this value. */ + public inline operator fun minus(other: Byte): Float = + this - other.toFloat() + /** Subtracts the other value from this value. */ + public inline operator fun minus(other: Short): Float = + this - other.toFloat() + /** Subtracts the other value from this value. */ + public inline operator fun minus(other: Int): Float = + this - other.toFloat() + /** Subtracts the other value from this value. */ + public inline operator fun minus(other: Long): Float = + this - other.toFloat() + /** Subtracts the other value from this value. */ + @TypedIntrinsic(IntrinsicType.MINUS) + external public operator fun minus(other: Float): Float + /** Subtracts the other value from this value. */ + public inline operator fun minus(other: Double): Double = + this.toDouble() - other + + /** Multiplies this value by the other value. */ + public inline operator fun times(other: Byte): Float = + this * other.toFloat() + /** Multiplies this value by the other value. */ + public inline operator fun times(other: Short): Float = + this * other.toFloat() + /** Multiplies this value by the other value. */ + public inline operator fun times(other: Int): Float = + this * other.toFloat() + /** Multiplies this value by the other value. */ + public inline operator fun times(other: Long): Float = + this * other.toFloat() + /** Multiplies this value by the other value. */ + @TypedIntrinsic(IntrinsicType.TIMES) + external public operator fun times(other: Float): Float + /** Multiplies this value by the other value. */ + public inline operator fun times(other: Double): Double = + this.toDouble() * other + + /** Divides this value by the other value. */ + public inline operator fun div(other: Byte): Float = + this / other.toFloat() + /** Divides this value by the other value. */ + public inline operator fun div(other: Short): Float = + this / other.toFloat() + /** Divides this value by the other value. */ + public inline operator fun div(other: Int): Float = + this / other.toFloat() + /** Divides this value by the other value. */ + public inline operator fun div(other: Long): Float = + this / other.toFloat() + /** Divides this value by the other value. */ + @TypedIntrinsic(IntrinsicType.SIGNED_DIV) + external public operator fun div(other: Float): Float + /** Divides this value by the other value. */ + public inline operator fun div(other: Double): Double = + this.toDouble() / other + + /** Calculates the remainder of dividing this value by the other value. */ + public inline operator fun rem(other: Byte): Float = + this % other.toFloat() + /** Calculates the remainder of dividing this value by the other value. */ + public inline operator fun rem(other: Short): Float = + this % other.toFloat() + /** Calculates the remainder of dividing this value by the other value. */ + public inline operator fun rem(other: Int): Float = + this % other.toFloat() + /** Calculates the remainder of dividing this value by the other value. */ + public inline operator fun rem(other: Long): Float = + this % other.toFloat() + /** Calculates the remainder of dividing this value by the other value. */ + @TypedIntrinsic(IntrinsicType.SIGNED_REM) + external public operator fun rem(other: Float): Float + /** Calculates the remainder of dividing this value by the other value. */ + public inline operator fun rem(other: Double): Double = + this.toDouble() % other + + /** Increments this value. */ + @TypedIntrinsic(IntrinsicType.INC) + external public operator fun inc(): Float + /** Decrements this value. */ + @TypedIntrinsic(IntrinsicType.DEC) + external public operator fun dec(): Float + /** Returns this value. */ + @TypedIntrinsic(IntrinsicType.UNARY_PLUS) + external public operator fun unaryPlus(): Float + /** Returns the negative of this value. */ + @TypedIntrinsic(IntrinsicType.UNARY_MINUS) + external public operator fun unaryMinus(): Float + + /** + * Converts this [Float] value to [Byte]. + * + * The resulting `Byte` value is equal to `this.toInt().toByte()`. + */ + @Deprecated("Unclear conversion. To achieve the same result convert to Int explicitly and then to Byte.", ReplaceWith("toInt().toByte()")) + public override fun toByte(): Byte = this.toInt().toByte() + + /** + * Converts this [Float] value to [Char]. + * + * The resulting `Char` value is equal to `this.toInt().toChar()`. + */ + public override fun toChar(): Char = this.toInt().toChar() + + /** + * Converts this [Float] value to [Short]. + * + * The resulting `Short` value is equal to `this.toInt().toShort()`. + */ + @Deprecated("Unclear conversion. To achieve the same result convert to Int explicitly and then to Short.", ReplaceWith("toInt().toShort()")) + public override fun toShort(): Short = this.toInt().toShort() + + /** + * Converts this [Float] value to [Int]. + * + * The fractional part, if any, is rounded down. + * Returns zero if this `Float` value is `NaN`, [Int.MIN_VALUE] if it's less than `Int.MIN_VALUE`, + * [Int.MAX_VALUE] if it's bigger than `Int.MAX_VALUE`. + */ + @SymbolName("Kotlin_Float_toInt") + external public override fun toInt(): Int + /** + * Converts this [Float] value to [Long]. + * + * The fractional part, if any, is rounded down. + * Returns zero if this `Float` value is `NaN`, [Long.MIN_VALUE] if it's less than `Long.MIN_VALUE`, + * [Long.MAX_VALUE] if it's bigger than `Long.MAX_VALUE`. + */ + @SymbolName("Kotlin_Float_toLong") + external public override fun toLong(): Long + + /** Returns this value. */ + public inline override fun toFloat(): Float = + this + /** + * Converts this [Float] value to [Double]. + * + * The resulting `Double` value represents the same numerical value as this `Float`. + */ + @TypedIntrinsic(IntrinsicType.FLOAT_EXTEND) + external public override fun toDouble(): Double + + public fun equals(other: Float): Boolean = toBits() == other.toBits() + + public override fun equals(other: Any?): Boolean = other is Float && this.equals(other) + + public override fun toString() = NumberConverter.convert(this) + + public override fun hashCode(): Int { + return bits() + } + + @TypedIntrinsic(IntrinsicType.REINTERPRET) + @PublishedApi + external internal fun bits(): Int +} + +/** + * Represents a double-precision 64-bit IEEE 754 floating point number. + */ +public final class Double private constructor() : Number(), Comparable { + companion object { + /** + * A constant holding the smallest *positive* nonzero value of Double. + */ + public const val MIN_VALUE: Double = 4.9e-324 + + /** + * A constant holding the largest positive finite value of Double. + */ + public const val MAX_VALUE: Double = 1.7976931348623157e+308 + + /** + * A constant holding the positive infinity value of Double. + */ + @Suppress("DIVISION_BY_ZERO") + public const val POSITIVE_INFINITY: Double = 1.0 / 0.0 + + /** + * A constant holding the negative infinity value of Double. + */ + @Suppress("DIVISION_BY_ZERO") + public const val NEGATIVE_INFINITY: Double = -1.0 / 0.0 + + /** + * A constant holding the "not a number" value of Double. + */ + @Suppress("DIVISION_BY_ZERO") + public const val NaN: Double = -(0.0 / 0.0) + + /** + * The number of bytes used to represent an instance of Double in a binary form. + */ + @SinceKotlin("1.4") + public const val SIZE_BYTES: Int = 8 + + /** + * The number of bits used to represent an instance of Double in a binary form. + */ + @SinceKotlin("1.4") + public const val SIZE_BITS: Int = 64 + } + + /** + * Compares this value with the specified value for order. + * Returns zero if this value is equal to the specified other value, a negative number if it's less than other, + * or a positive number if it's greater than other. + */ + public operator fun compareTo(other: Byte): Int = compareTo(other.toDouble()) + + /** + * Compares this value with the specified value for order. + * Returns zero if this value is equal to the specified other value, a negative number if it's less than other, + * or a positive number if it's greater than other. + */ + public operator fun compareTo(other: Short): Int = compareTo(other.toDouble()) + + /** + * Compares this value with the specified value for order. + * Returns zero if this value is equal to the specified other value, a negative number if it's less than other, + * or a positive number if it's greater than other. + */ + public operator fun compareTo(other: Int): Int = compareTo(other.toDouble()) + + /** + * Compares this value with the specified value for order. + * Returns zero if this value is equal to the specified other value, a negative number if it's less than other, + * or a positive number if it's greater than other. + */ + public operator fun compareTo(other: Long): Int = compareTo(other.toDouble()) + + /** + * Compares this value with the specified value for order. + * Returns zero if this value is equal to the specified other value, a negative number if it's less than other, + * or a positive number if it's greater than other. + */ + public operator fun compareTo(other: Float): Int = compareTo(other.toDouble()) + + /** + * Compares this value with the specified value for order. + * Returns zero if this value is equal to the specified other value, a negative number if it's less than other, + * or a positive number if it's greater than other. + */ + public override operator fun compareTo(other: Double): Int { + // if any of values in NaN both comparisons return false + if (this > other) return 1 + if (this < other) return -1 + + val thisBits = this.toBits() + val otherBits = other.toBits() + + // Canonical NaN bits representation higher than any other bit representvalue + return thisBits.compareTo(otherBits) + } + + /** Adds the other value to this value. */ + public inline operator fun plus(other: Byte): Double = + this + other.toDouble() + /** Adds the other value to this value. */ + public inline operator fun plus(other: Short): Double = + this + other.toDouble() + /** Adds the other value to this value. */ + public inline operator fun plus(other: Int): Double = + this + other.toDouble() + /** Adds the other value to this value. */ + public inline operator fun plus(other: Long): Double = + this + other.toDouble() + /** Adds the other value to this value. */ + public inline operator fun plus(other: Float): Double = + this + other.toDouble() + /** Adds the other value to this value. */ + @TypedIntrinsic(IntrinsicType.PLUS) + external public operator fun plus(other: Double): Double + + /** Subtracts the other value from this value. */ + public inline operator fun minus(other: Byte): Double = + this - other.toDouble() + /** Subtracts the other value from this value. */ + public inline operator fun minus(other: Short): Double = + this - other.toDouble() + /** Subtracts the other value from this value. */ + public inline operator fun minus(other: Int): Double = + this - other.toDouble() + /** Subtracts the other value from this value. */ + public inline operator fun minus(other: Long): Double = + this - other.toDouble() + /** Subtracts the other value from this value. */ + public inline operator fun minus(other: Float): Double = + this - other.toDouble() + /** Subtracts the other value from this value. */ + @TypedIntrinsic(IntrinsicType.MINUS) + external public operator fun minus(other: Double): Double + + /** Multiplies this value by the other value. */ + public inline operator fun times(other: Byte): Double = + this * other.toDouble() + /** Multiplies this value by the other value. */ + public inline operator fun times(other: Short): Double = + this * other.toDouble() + /** Multiplies this value by the other value. */ + public inline operator fun times(other: Int): Double = + this * other.toDouble() + /** Multiplies this value by the other value. */ + public inline operator fun times(other: Long): Double = + this * other.toDouble() + /** Multiplies this value by the other value. */ + public inline operator fun times(other: Float): Double = + this * other.toDouble() + /** Multiplies this value by the other value. */ + @TypedIntrinsic(IntrinsicType.TIMES) + external public operator fun times(other: Double): Double + + /** Divides this value by the other value. */ + public inline operator fun div(other: Byte): Double = + this / other.toDouble() + /** Divides this value by the other value. */ + public inline operator fun div(other: Short): Double = + this / other.toDouble() + /** Divides this value by the other value. */ + public inline operator fun div(other: Int): Double = + this / other.toDouble() + /** Divides this value by the other value. */ + public inline operator fun div(other: Long): Double = + this / other.toDouble() + /** Divides this value by the other value. */ + public inline operator fun div(other: Float): Double = + this / other.toDouble() + /** Divides this value by the other value. */ + @TypedIntrinsic(IntrinsicType.SIGNED_DIV) + external public operator fun div(other: Double): Double + + /** Calculates the remainder of dividing this value by the other value. */ + public inline operator fun rem(other: Byte): Double = + this % other.toDouble() + /** Calculates the remainder of dividing this value by the other value. */ + public inline operator fun rem(other: Short): Double = + this % other.toDouble() + /** Calculates the remainder of dividing this value by the other value. */ + public inline operator fun rem(other: Int): Double = + this % other.toDouble() + /** Calculates the remainder of dividing this value by the other value. */ + public inline operator fun rem(other: Long): Double = + this % other.toDouble() + /** Calculates the remainder of dividing this value by the other value. */ + public inline operator fun rem(other: Float): Double = + this % other.toDouble() + /** Calculates the remainder of dividing this value by the other value. */ + @TypedIntrinsic(IntrinsicType.SIGNED_REM) + external public operator fun rem(other: Double): Double + + /** Increments this value. */ + @TypedIntrinsic(IntrinsicType.INC) + external public operator fun inc(): Double + /** Decrements this value. */ + @TypedIntrinsic(IntrinsicType.DEC) + external public operator fun dec(): Double + /** Returns this value. */ + @TypedIntrinsic(IntrinsicType.UNARY_PLUS) + external public operator fun unaryPlus(): Double + /** Returns the negative of this value. */ + @TypedIntrinsic(IntrinsicType.UNARY_MINUS) + external public operator fun unaryMinus(): Double + + /** + * Converts this [Double] value to [Byte]. + * + * The resulting `Byte` value is equal to `this.toInt().toByte()`. + */ + @Deprecated("Unclear conversion. To achieve the same result convert to Int explicitly and then to Byte.", ReplaceWith("toInt().toByte()")) + public override fun toByte(): Byte = this.toInt().toByte() + + /** + * Converts this [Double] value to [Char]. + * + * The resulting `Char` value is equal to `this.toInt().toChar()`. + */ + public override fun toChar(): Char = this.toInt().toChar() + + /** + * Converts this [Double] value to [Short]. + * + * The resulting `Short` value is equal to `this.toInt().toShort()`. + */ + @Deprecated("Unclear conversion. To achieve the same result convert to Int explicitly and then to Short.", ReplaceWith("toInt().toShort()")) + public override fun toShort(): Short = this.toInt().toShort() + + /** + * Converts this [Double] value to [Int]. + * + * The fractional part, if any, is rounded down. + * Returns zero if this `Double` value is `NaN`, [Int.MIN_VALUE] if it's less than `Int.MIN_VALUE`, + * [Int.MAX_VALUE] if it's bigger than `Int.MAX_VALUE`. + */ + @SymbolName("Kotlin_Double_toInt") + external public override fun toInt(): Int + /** + * Converts this [Double] value to [Long]. + * + * The fractional part, if any, is rounded down. + * Returns zero if this `Double` value is `NaN`, [Long.MIN_VALUE] if it's less than `Long.MIN_VALUE`, + * [Long.MAX_VALUE] if it's bigger than `Long.MAX_VALUE`. + */ + @SymbolName("Kotlin_Double_toLong") + external public override fun toLong(): Long + /** + * Converts this [Double] value to [Float]. + * + * The resulting value is the closest `Float` to this `Double` value. + * In case when this `Double` value is exactly between two `Float`s, + * the one with zero at least significant bit of mantissa is selected. + */ + @TypedIntrinsic(IntrinsicType.FLOAT_TRUNCATE) + external public override fun toFloat(): Float + + /** Returns this value. */ + public inline override fun toDouble(): Double = + this + + public fun equals(other: Double): Boolean = toBits() == other.toBits() + + public override fun equals(other: Any?): Boolean = other is Double && this.equals(other) + + public override fun toString(): String = NumberConverter.convert(this) + + public override fun hashCode(): Int = bits().hashCode() + + @TypedIntrinsic(IntrinsicType.REINTERPRET) + @PublishedApi + external internal fun bits(): Long +} diff --git a/kotlin-native/runtime/src/main/kotlin/kotlin/String.kt b/kotlin-native/runtime/src/main/kotlin/kotlin/String.kt new file mode 100644 index 00000000000..5e31807da15 --- /dev/null +++ b/kotlin-native/runtime/src/main/kotlin/kotlin/String.kt @@ -0,0 +1,59 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +package kotlin + +import kotlin.native.internal.ExportTypeInfo +import kotlin.native.internal.Frozen + +@ExportTypeInfo("theStringTypeInfo") +@Frozen +public final class String : Comparable, CharSequence { + public companion object { + } + + @SymbolName("Kotlin_String_hashCode") + external public override fun hashCode(): Int + + public operator fun plus(other: Any?): String { + return plusImpl(other.toString()) + } + + override public fun toString(): String { + return this + } + + public override val length: Int + get() = getStringLength() + + /** + * Returns the character of this string at the specified [index]. + * + * If the [index] is out of bounds of this string, throws an [IndexOutOfBoundsException]. + */ + @SymbolName("Kotlin_String_get") + external override public fun get(index: Int): Char + + @SymbolName("Kotlin_String_subSequence") + external override public fun subSequence(startIndex: Int, endIndex: Int): CharSequence + + @SymbolName("Kotlin_String_compareTo") + override external public fun compareTo(other: String): Int + + @SymbolName("Kotlin_String_getStringLength") + external private fun getStringLength(): Int + + @SymbolName("Kotlin_String_plusImpl") + external private fun plusImpl(other: String): String + + @SymbolName("Kotlin_String_equals") + external public override fun equals(other: Any?): Boolean +} + +public inline operator fun kotlin.String?.plus(other: kotlin.Any?): kotlin.String = + (this?.toString() ?: "null").plus(other?.toString() ?: "null") + + +public inline fun Any?.toString() = this?.toString() ?: "null" \ No newline at end of file diff --git a/kotlin-native/runtime/src/main/kotlin/kotlin/Throwable.kt b/kotlin-native/runtime/src/main/kotlin/kotlin/Throwable.kt new file mode 100644 index 00000000000..55dc6e660cb --- /dev/null +++ b/kotlin-native/runtime/src/main/kotlin/kotlin/Throwable.kt @@ -0,0 +1,192 @@ +/* + * Copyright 2010-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +package kotlin + +import kotlin.native.concurrent.freeze +import kotlin.native.concurrent.isFrozen +import kotlin.native.internal.ExportForCppRuntime +import kotlin.native.internal.ExportTypeInfo +import kotlin.native.internal.NativePtrArray + +/** + * The base class for all errors and exceptions. Only instances of this class can be thrown or caught. + * + * @param message the detail message string. + * @param cause the cause of this throwable. + */ +@ExportTypeInfo("theThrowableTypeInfo") +public open class Throwable(open val message: String?, open val cause: Throwable?) { + + constructor(message: String?) : this(message, null) + + constructor(cause: Throwable?) : this(cause?.toString(), cause) + + constructor() : this(null, null) + + @get:ExportForCppRuntime("Kotlin_Throwable_getStackTrace") + private val stackTrace: NativePtrArray = getCurrentStackTrace() + + private val stackTraceStrings: Array by lazy { + getStackTraceStrings(stackTrace).freeze() + } + + /** + * Returns an array of stack trace strings representing the stack trace + * pertaining to this throwable. + */ + public fun getStackTrace(): Array = stackTraceStrings + + internal fun getStackTraceAddressesInternal(): List = + (0 until stackTrace.size).map { index -> stackTrace[index].toLong() } + + /** + * Prints the [detailed description][Throwable.stackTraceToString] of this throwable to the standard output. + */ + public fun printStackTrace(): Unit = ExceptionTraceBuilder(this).print() + + internal fun dumpStackTrace(): String = ExceptionTraceBuilder(this).build() + + private class ExceptionTraceBuilder(private val top: Throwable) { + private val target = StringBuilder() + private var printOut = false + private val visited = mutableSetOf() + + fun build(): String { + top.dumpFullTrace("", "") + return target.toString() + } + + fun print() { + printOut = true + top.dumpFullTrace("", "") + } + + private fun StringBuilder.endln() { + if (printOut) { + println(this) + clear() + } else { + appendln() + } + } + + private fun Throwable.dumpFullTrace(indent: String, qualifier: String) { + this.dumpSelfTrace(indent, qualifier) || return + + var cause = this.cause + while (cause != null) { + cause.dumpSelfTrace(indent, "Caused by: ") + cause = cause.cause + } + } + + private fun Throwable.dumpSelfTrace(indent: String, qualifier: String): Boolean { + if (!visited.add(this)) { + target.append(indent).append(qualifier).append("[CIRCULAR REFERENCE, SEE ABOVE: ").append(this).append("]").endln() + return false + } + target.append(indent).append(qualifier).append(this).endln() + // leave 1 common frame to ease matching with the top exception stack + val commonFrames = (commonStackFrames() - 1).coerceAtLeast(0) + for (frameIndex in 0 until stackTraceStrings.size - commonFrames) { + val element = stackTraceStrings[frameIndex] + target.append(indent).append(" at ").append(element).endln() + } + if (commonFrames > 0) { + target.append(indent).append(" ... and ").append(commonFrames).append(" more common stack frames skipped").endln() + } + val suppressed = suppressedExceptionsList + if (!suppressed.isNullOrEmpty()) { + val suppressedIndent = indent + " " + for (s in suppressed) { + s.dumpFullTrace(suppressedIndent, "Suppressed: ") + } + } + return true + } + + private fun Throwable.commonStackFrames(): Int { + if (top === this) return 0 + val topStack = top.stackTrace + val topSize = topStack.size + val thisStack = this.stackTrace + val thisSize = thisStack.size + val maxSize = minOf(topSize, thisSize) + var frame = 0 + while (frame < maxSize) { + if (thisStack[thisSize - 1 - frame] != topStack[topSize - 1 - frame]) break + frame++ + } + return frame + } + } + + + /** + * Returns the short description of this throwable consisting of + * the exception class name (fully qualified if possible) + * followed by the exception message if it is not null. + */ + public override fun toString(): String { + val kClass = this::class + val s = kClass.qualifiedName ?: kClass.simpleName ?: "Throwable" + return if (message != null) s + ": " + message.toString() else s + } + + internal var suppressedExceptionsList: MutableList? = null +} + +@SymbolName("Kotlin_getCurrentStackTrace") +private external fun getCurrentStackTrace(): NativePtrArray + +@SymbolName("Kotlin_getStackTraceStrings") +private external fun getStackTraceStrings(stackTrace: NativePtrArray): Array + +/** + * Returns the detailed description of this throwable with its stack trace. + * + * The detailed description includes: + * - the short description (see [Throwable.toString]) of this throwable; + * - the complete stack trace; + * - detailed descriptions of the exceptions that were [suppressed][suppressedExceptions] in order to deliver this exception; + * - the detailed description of each throwable in the [Throwable.cause] chain. + */ +@SinceKotlin("1.4") +public actual fun Throwable.stackTraceToString(): String = dumpStackTrace() + +/** + * Prints the [detailed description][Throwable.stackTraceToString] of this throwable to the standard output. + */ +@SinceKotlin("1.4") +@Suppress("EXTENSION_SHADOWED_BY_MEMBER") +@kotlin.internal.InlineOnly +public actual inline fun Throwable.printStackTrace(): Unit = printStackTrace() + +/** + * Adds the specified exception to the list of exceptions that were + * suppressed in order to deliver this exception. + * + * Does nothing if this [Throwable] is frozen. + */ +@SinceKotlin("1.4") +public actual fun Throwable.addSuppressed(exception: Throwable) { + if (this !== exception && !this.isFrozen) { + val suppressed = suppressedExceptionsList + when { + suppressed == null -> suppressedExceptionsList = mutableListOf(exception) + suppressed.isFrozen -> suppressedExceptionsList = suppressed.toMutableList().apply { add(exception) } + else -> suppressed.add(exception) + } + } +} + +/** + * Returns a list of all exceptions that were suppressed in order to deliver this exception. + */ +@SinceKotlin("1.4") +public actual val Throwable.suppressedExceptions: List get() { + return this.suppressedExceptionsList ?: emptyList() +} diff --git a/kotlin-native/runtime/src/main/kotlin/kotlin/Unit.kt b/kotlin-native/runtime/src/main/kotlin/kotlin/Unit.kt new file mode 100644 index 00000000000..fca7a20e47c --- /dev/null +++ b/kotlin-native/runtime/src/main/kotlin/kotlin/Unit.kt @@ -0,0 +1,16 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +package kotlin + +import kotlin.native.internal.ExportTypeInfo + +/** + * The type with only one value: the `Unit` object. + */ +@ExportTypeInfo("theUnitTypeInfo") +public object Unit { + override fun toString() = "kotlin.Unit" +} \ No newline at end of file diff --git a/kotlin-native/runtime/src/main/kotlin/kotlin/annotation/Annotations.kt b/kotlin-native/runtime/src/main/kotlin/kotlin/annotation/Annotations.kt new file mode 100644 index 00000000000..4091a425c72 --- /dev/null +++ b/kotlin-native/runtime/src/main/kotlin/kotlin/annotation/Annotations.kt @@ -0,0 +1,92 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +package kotlin.annotation + +import kotlin.annotation.AnnotationTarget.* + +/** + * Contains the list of code elements which are the possible annotation targets + */ +public enum class AnnotationTarget { + /** Class, interface or object, annotation class is also included */ + CLASS, + /** Annotation class only */ + ANNOTATION_CLASS, + /** Generic type parameter (unsupported yet) */ + TYPE_PARAMETER, + /** Property */ + PROPERTY, + /** Field, including property's backing field */ + FIELD, + /** Local variable */ + LOCAL_VARIABLE, + /** Value parameter of a function or a constructor */ + VALUE_PARAMETER, + /** Constructor only (primary or secondary) */ + CONSTRUCTOR, + /** Function (constructors are not included) */ + FUNCTION, + /** Property getter only */ + PROPERTY_GETTER, + /** Property setter only */ + PROPERTY_SETTER, + /** Type usage */ + TYPE, + /** Any expression */ + EXPRESSION, + /** File */ + FILE, + /** Type alias */ + @SinceKotlin("1.1") + TYPEALIAS +} + +/** + * Contains the list of possible annotation's retentions. + * + * Determines how an annotation is stored in binary output. + */ +public enum class AnnotationRetention { + /** Annotation isn't stored in binary output */ + SOURCE, + /** Annotation is stored in binary output, but invisible for reflection */ + BINARY, + /** Annotation is stored in binary output and visible for reflection (default retention) */ + RUNTIME +} + +/** + * This meta-annotation indicates the kinds of code elements which are possible targets of an annotation. + * + * If the target meta-annotation is not present on an annotation declaration, the annotation is applicable to the following elements: + * [CLASS], [PROPERTY], [FIELD], [LOCAL_VARIABLE], [VALUE_PARAMETER], [CONSTRUCTOR], [FUNCTION], [PROPERTY_GETTER], [PROPERTY_SETTER]. + * + * @property allowedTargets list of allowed annotation targets + */ +@Target(AnnotationTarget.ANNOTATION_CLASS) +@MustBeDocumented +public annotation class Target(vararg val allowedTargets: AnnotationTarget) + +/** + * This meta-annotation determines whether an annotation is stored in binary output and visible for reflection. By default, both are true. + * + * @property value necessary annotation retention (RUNTIME, BINARY or SOURCE) + */ +@Target(AnnotationTarget.ANNOTATION_CLASS) +public annotation class Retention(val value: AnnotationRetention = AnnotationRetention.RUNTIME) + +/** + * This meta-annotation determines that an annotation is applicable twice or more on a single code element + */ +@Target(AnnotationTarget.ANNOTATION_CLASS) +public annotation class Repeatable + +/** + * This meta-annotation determines that an annotation is a part of public API and therefore should be included in the generated + * documentation for the element to which the annotation is applied. + */ +@Target(AnnotationTarget.ANNOTATION_CLASS) +public annotation class MustBeDocumented \ No newline at end of file diff --git a/kotlin-native/runtime/src/main/kotlin/kotlin/collections/AbstractMutableCollection.kt b/kotlin-native/runtime/src/main/kotlin/kotlin/collections/AbstractMutableCollection.kt new file mode 100644 index 00000000000..0bcba06c9ed --- /dev/null +++ b/kotlin-native/runtime/src/main/kotlin/kotlin/collections/AbstractMutableCollection.kt @@ -0,0 +1,70 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +package kotlin.collections + +/** + * Provides a skeletal implementation of the [MutableCollection] interface. + * + * @param E the type of elements contained in the collection. The collection is invariant in its element type. + */ +public actual abstract class AbstractMutableCollection protected actual constructor(): MutableCollection, AbstractCollection() { + + // Bulk Modification Operations + /** + * Adds all of the elements of the specified collection to this collection. + * + * @return `true` if any of the specified elements was added to the collection, `false` if the collection was not modified. + */ + actual override public fun addAll(elements: Collection): Boolean { + var changed = false + for (v in elements) { + if (add(v)) changed = true + } + return changed + } + + /** + * Removes a single instance of the specified element from this + * collection, if it is present. + * + * @return `true` if the element has been successfully removed; `false` if it was not present in the collection. + */ + actual override fun remove(element: E): Boolean { + val it = iterator() + while (it.hasNext()) { + if (it.next() == element) { + it.remove() + return true + } + } + return false + } + + /** + * Removes all of this collection's elements that are also contained in the specified collection. + * + * @return `true` if any of the specified elements was removed from the collection, `false` if the collection was not modified. + */ + actual override public fun removeAll(elements: Collection): Boolean = (this as MutableIterable).removeAll { it in elements } + + /** + * Retains only the elements in this collection that are contained in the specified collection. + * + * @return `true` if any element was removed from the collection, `false` if the collection was not modified. + */ + actual override public fun retainAll(elements: Collection): Boolean = (this as MutableIterable).retainAll { it in elements } + + /** + * Removes all elements from this collection. + */ + actual override fun clear(): Unit { + val it = iterator() + while (it.hasNext()) { + it.next() + it.remove() + } + } +} diff --git a/kotlin-native/runtime/src/main/kotlin/kotlin/collections/AbstractMutableList.kt b/kotlin-native/runtime/src/main/kotlin/kotlin/collections/AbstractMutableList.kt new file mode 100644 index 00000000000..1ac07d505a8 --- /dev/null +++ b/kotlin-native/runtime/src/main/kotlin/kotlin/collections/AbstractMutableList.kt @@ -0,0 +1,202 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ +package kotlin.collections + +/** + * AbstractMutableList implementation copied from JS backend + * (see js/js.libraries/src/core/collections/AbstractMutableList.kt). + * + * Based on GWT AbstractList + * Copyright 2007 Google Inc. + */ + +/** + * Provides a skeletal implementation of the [MutableList] interface. + * + * @param E the type of elements contained in the list. The list is invariant in its element type. + */ +public actual abstract class AbstractMutableList protected actual constructor() : AbstractMutableCollection(), MutableList { + protected var modCount: Int = 0 + + abstract override fun add(index: Int, element: E): Unit + abstract override fun removeAt(index: Int): E + abstract override fun set(index: Int, element: E): E + + /** + * Adds the specified element to the end of this list. + * + * @return `true` because the list is always modified as the result of this operation. + */ + override actual fun add(element: E): Boolean { + add(size, element) + return true + } + + override actual fun addAll(index: Int, elements: Collection): Boolean { + var i = index + var changed = false + for (e in elements) { + add(i++, e) + changed = true + } + return changed + } + + override actual fun clear() { + removeRange(0, size) + } + + override actual fun removeAll(elements: Collection): Boolean = removeAll { it in elements } + override actual fun retainAll(elements: Collection): Boolean = removeAll { it !in elements } + + + override actual fun iterator(): MutableIterator = IteratorImpl() + + override actual fun contains(element: E): Boolean = indexOf(element) >= 0 + + override actual fun indexOf(element: E): Int { + for (index in 0..lastIndex) { + if (get(index) == element) { + return index + } + } + return -1 + } + + override actual fun lastIndexOf(element: E): Int { + for (index in lastIndex downTo 0) { + if (get(index) == element) { + return index + } + } + return -1 + } + + override actual fun listIterator(): MutableListIterator = listIterator(0) + override actual fun listIterator(index: Int): MutableListIterator = ListIteratorImpl(index) + + + override actual fun subList(fromIndex: Int, toIndex: Int): MutableList = SubList(this, fromIndex, toIndex) + + /** + * Removes the range of elements from this list starting from [fromIndex] and ending with but not including [toIndex]. + */ + protected open fun removeRange(fromIndex: Int, toIndex: Int) { + val iterator = listIterator(fromIndex) + repeat(toIndex - fromIndex) { + iterator.next() + iterator.remove() + } + } + + override fun equals(other: Any?): Boolean { + if (other === this) return true + if (other !is List<*>) return false + + return AbstractList.orderedEquals(this, other) + } + + override fun hashCode(): Int = AbstractList.orderedHashCode(this) + + private open inner class IteratorImpl : MutableIterator { + /** the index of the item that will be returned on the next call to [next]`()` */ + protected var index = 0 + /** the index of the item that was returned on the previous call to [next]`()` + * or [ListIterator.previous]`()` (for `ListIterator`), + * -1 if no such item exists + */ + protected var last = -1 + + override fun hasNext(): Boolean = index < size + + override fun next(): E { + if (!hasNext()) throw NoSuchElementException() + last = index++ + return get(last) + } + + override fun remove() { + check(last != -1) { "Call next() or previous() before removing element from the iterator."} + + removeAt(last) + index = last + last = -1 + } + } + + /** + * Implementation of `MutableListIterator` for abstract lists. + */ + private inner class ListIteratorImpl(index: Int) : IteratorImpl(), MutableListIterator { + + init { + AbstractList.checkPositionIndex(index, this@AbstractMutableList.size) + this.index = index + } + + override fun hasPrevious(): Boolean = index > 0 + + override fun nextIndex(): Int = index + + override fun previous(): E { + if (!hasPrevious()) throw NoSuchElementException() + + last = --index + return get(last) + } + + override fun previousIndex(): Int = index - 1 + + override fun add(element: E) { + add(index, element) + index++ + last = -1 + } + + override fun set(element: E) { + check(last != -1) { "Call next() or previous() before updating element value with the iterator."} + this@AbstractMutableList[last] = element + } + } + + private class SubList(private val list: AbstractMutableList, private val fromIndex: Int, toIndex: Int) : AbstractMutableList() { + private var _size: Int = 0 + + init { + AbstractList.checkRangeIndexes(fromIndex, toIndex, list.size) + this._size = toIndex - fromIndex + } + + override fun add(index: Int, element: E) { + AbstractList.checkPositionIndex(index, _size) + + list.add(fromIndex + index, element) + _size++ + } + + override fun get(index: Int): E { + AbstractList.checkElementIndex(index, _size) + + return list[fromIndex + index] + } + + override fun removeAt(index: Int): E { + AbstractList.checkElementIndex(index, _size) + + val result = list.removeAt(fromIndex + index) + _size-- + return result + } + + override fun set(index: Int, element: E): E { + AbstractList.checkElementIndex(index, _size) + + return list.set(fromIndex + index, element) + } + + override val size: Int get() = _size + } + +} \ No newline at end of file diff --git a/kotlin-native/runtime/src/main/kotlin/kotlin/collections/AbstractMutableMap.kt b/kotlin-native/runtime/src/main/kotlin/kotlin/collections/AbstractMutableMap.kt new file mode 100644 index 00000000000..46f0a65f1f2 --- /dev/null +++ b/kotlin-native/runtime/src/main/kotlin/kotlin/collections/AbstractMutableMap.kt @@ -0,0 +1,135 @@ +package kotlin.collections + +/** + * Provides a skeletal implementation of the [MutableMap] interface. + * + * The implementor is required to implement [entries] property, which should return mutable set of map entries, and [put] function. + * + * @param K the type of map keys. The map is invariant in its key type. + * @param V the type of map values. The map is invariant in its value type. + */ +@SinceKotlin("1.1") +public actual abstract class AbstractMutableMap protected actual constructor() : AbstractMap(), MutableMap { + /** + * Associates the specified [value] with the specified [key] in the map. + * + * @return the previous value associated with the key, or `null` if the key was not present in the map. + */ + actual abstract override fun put(key: K, value: V): V? + + + /** + * A mutable [Map.Entry] shared by several [Map] implementations. + */ + internal open class SimpleEntry(override val key: K, value: V) : MutableMap.MutableEntry { + constructor(entry: Map.Entry) : this(entry.key, entry.value) + + private var _value = value + + override val value: V get() = _value + + override fun setValue(newValue: V): V { + val oldValue = this._value + this._value = newValue + return oldValue + } + + override fun hashCode(): Int = entryHashCode(this) + override fun toString(): String = entryToString(this) + override fun equals(other: Any?): Boolean = entryEquals(this, other) + } + + + actual override fun putAll(from: Map) { + for ((key, value) in from) { + put(key, value) + } + } + + actual override fun remove(key: K): V? { + val iter = entries.iterator() + while (iter.hasNext()) { + val entry = iter.next() + val k = entry.key + if (key == k) { + val value = entry.value + iter.remove() + return value + } + } + return null + } + + actual override fun clear() { + entries.clear() + } + + private var _keys: MutableSet? = null + actual override val keys: MutableSet + get() { + if (_keys == null) { + _keys = object : AbstractMutableSet() { + override fun add(element: K): Boolean = throw UnsupportedOperationException("Add is not supported on keys") + override fun clear() { + this@AbstractMutableMap.clear() + } + + override operator fun contains(element: K): Boolean = containsKey(element) + + override operator fun iterator(): MutableIterator { + val entryIterator = entries.iterator() + return object : MutableIterator { + override fun hasNext(): Boolean = entryIterator.hasNext() + override fun next(): K = entryIterator.next().key + override fun remove() = entryIterator.remove() + } + } + + override fun remove(element: K): Boolean { + if (containsKey(element)) { + this@AbstractMutableMap.remove(element) + return true + } + return false + } + + override val size: Int get() = this@AbstractMutableMap.size + } + } + return _keys!! + } + + private var _values: MutableCollection? = null + actual override val values: MutableCollection + get() { + if (_values == null) { + _values = object : AbstractMutableCollection() { + override fun add(element: V): Boolean = throw UnsupportedOperationException("Add is not supported on values") + override fun clear() = this@AbstractMutableMap.clear() + + override operator fun contains(element: V): Boolean = containsValue(element) + + override operator fun iterator(): MutableIterator { + val entryIterator = entries.iterator() + return object : MutableIterator { + override fun hasNext(): Boolean = entryIterator.hasNext() + override fun next(): V = entryIterator.next().value + override fun remove() = entryIterator.remove() + } + } + + override val size: Int get() = this@AbstractMutableMap.size + + // TODO: should we implement them this way? Currently it's unspecified in JVM + override fun equals(other: Any?): Boolean { + if (this === other) return true + if (other !is Collection<*>) return false + return AbstractList.orderedEquals(this, other) + } + + override fun hashCode(): Int = AbstractList.orderedHashCode(this) + } + } + return _values!! + } +} diff --git a/kotlin-native/runtime/src/main/kotlin/kotlin/collections/AbstractMutableSet.kt b/kotlin-native/runtime/src/main/kotlin/kotlin/collections/AbstractMutableSet.kt new file mode 100644 index 00000000000..47da186ccb6 --- /dev/null +++ b/kotlin-native/runtime/src/main/kotlin/kotlin/collections/AbstractMutableSet.kt @@ -0,0 +1,32 @@ +package kotlin.collections + +/** + * Provides a skeletal implementation of the [MutableSet] interface. + * + * @param E the type of elements contained in the set. The set is invariant in its element type. + */ +@SinceKotlin("1.1") +public actual abstract class AbstractMutableSet protected actual constructor() : AbstractMutableCollection(), MutableSet { + /** + * Adds the specified element to the set. + * + * @return `true` if the element has been added, `false` if the element is already contained in the set. + */ + actual abstract override fun add(element: E): Boolean + + /** + * Compares this set with another set instance with the unordered structural equality. + * + * @return `true`, if [other] instance is a [Set] of the same size, all elements of which are contained in this set. + */ + override fun equals(other: Any?): Boolean { + if (other === this) return true + if (other !is Set<*>) return false + return AbstractSet.setEquals(this, other) + } + + /** + * Returns the hash code value for this set. + */ + override fun hashCode(): Int = AbstractSet.unorderedHashCode(this) +} \ No newline at end of file diff --git a/kotlin-native/runtime/src/main/kotlin/kotlin/collections/ArrayList.kt b/kotlin-native/runtime/src/main/kotlin/kotlin/collections/ArrayList.kt new file mode 100644 index 00000000000..553fa452b73 --- /dev/null +++ b/kotlin-native/runtime/src/main/kotlin/kotlin/collections/ArrayList.kt @@ -0,0 +1,350 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +package kotlin.collections + +actual class ArrayList private constructor( + private var array: Array, + private var offset: Int, + private var length: Int, + private var isReadOnly: Boolean, + private val backing: ArrayList?, + private val root: ArrayList? +) : MutableList, RandomAccess, AbstractMutableList() { + + actual constructor() : this(10) + + actual constructor(initialCapacity: Int) : this( + arrayOfUninitializedElements(initialCapacity), 0, 0, false, null, null) + + actual constructor(elements: Collection) : this(elements.size) { + addAll(elements) + } + + @PublishedApi + internal fun build(): List { + if (backing != null) throw IllegalStateException() // just in case somebody casts subList to ArrayList + checkIsMutable() + isReadOnly = true + return this + } + + override actual val size: Int + get() = length + + override actual fun isEmpty(): Boolean = length == 0 + + override actual fun get(index: Int): E { + checkElementIndex(index) + return array[offset + index] + } + + override actual operator fun set(index: Int, element: E): E { + checkIsMutable() + checkElementIndex(index) + val old = array[offset + index] + array[offset + index] = element + return old + } + + override actual fun indexOf(element: E): Int { + var i = 0 + while (i < length) { + if (array[offset + i] == element) return i + i++ + } + return -1 + } + + override actual fun lastIndexOf(element: E): Int { + var i = length - 1 + while (i >= 0) { + if (array[offset + i] == element) return i + i-- + } + return -1 + } + + override actual fun iterator(): MutableIterator = Itr(this, 0) + override actual fun listIterator(): MutableListIterator = Itr(this, 0) + + override actual fun listIterator(index: Int): MutableListIterator { + checkPositionIndex(index) + return Itr(this, index) + } + + override actual fun add(element: E): Boolean { + checkIsMutable() + addAtInternal(offset + length, element) + return true + } + + override actual fun add(index: Int, element: E) { + checkIsMutable() + checkPositionIndex(index) + addAtInternal(offset + index, element) + } + + override actual fun addAll(elements: Collection): Boolean { + checkIsMutable() + val n = elements.size + addAllInternal(offset + length, elements, n) + return n > 0 + } + + override actual fun addAll(index: Int, elements: Collection): Boolean { + checkIsMutable() + checkPositionIndex(index) + val n = elements.size + addAllInternal(offset + index, elements, n) + return n > 0 + } + + override actual fun clear() { + checkIsMutable() + removeRangeInternal(offset, length) + } + + override actual fun removeAt(index: Int): E { + checkIsMutable() + checkElementIndex(index) + return removeAtInternal(offset + index) + } + + override actual fun remove(element: E): Boolean { + checkIsMutable() + val i = indexOf(element) + if (i >= 0) removeAt(i) + return i >= 0 + } + + override actual fun removeAll(elements: Collection): Boolean { + checkIsMutable() + return retainOrRemoveAllInternal(offset, length, elements, false) > 0 + } + + override actual fun retainAll(elements: Collection): Boolean { + checkIsMutable() + return retainOrRemoveAllInternal(offset, length, elements, true) > 0 + } + + override actual fun subList(fromIndex: Int, toIndex: Int): MutableList { + checkRangeIndexes(fromIndex, toIndex) + return ArrayList(array, offset + fromIndex, toIndex - fromIndex, isReadOnly, this, root ?: this) + } + + actual fun trimToSize() { + if (backing != null) throw IllegalStateException() // just in case somebody casts subList to ArrayList + if (length < array.size) + array = array.copyOfUninitializedElements(length) + } + + @OptIn(ExperimentalStdlibApi::class) + final actual fun ensureCapacity(minCapacity: Int) { + if (backing != null) throw IllegalStateException() // just in case somebody casts subList to ArrayList + if (minCapacity > array.size) { + val newSize = ArrayDeque.newCapacity(array.size, minCapacity) + array = array.copyOfUninitializedElements(newSize) + } + } + + override fun equals(other: Any?): Boolean { + return other === this || + (other is List<*>) && contentEquals(other) + } + + override fun hashCode(): Int { + return array.subarrayContentHashCode(offset, length) + } + + override fun toString(): String { + @Suppress("DEPRECATION") + return array.subarrayContentToString(offset, length) + } + + // ---------------------------- private ---------------------------- + + private fun checkElementIndex(index: Int) { + if (index < 0 || index >= length) { + throw IndexOutOfBoundsException("index: $index, size: $length") + } + } + + private fun checkPositionIndex(index: Int) { + if (index < 0 || index > length) { + throw IndexOutOfBoundsException("index: $index, size: $length") + } + } + + private fun checkRangeIndexes(fromIndex: Int, toIndex: Int) { + if (fromIndex < 0 || toIndex > length) { + throw IndexOutOfBoundsException("fromIndex: $fromIndex, toIndex: $toIndex, size: $length") + } + if (fromIndex > toIndex) { + throw IllegalArgumentException("fromIndex: $fromIndex > toIndex: $toIndex") + } + } + + private fun checkIsMutable() { + if (isReadOnly || root != null && root.isReadOnly) throw UnsupportedOperationException() + } + + private fun ensureExtraCapacity(n: Int) { + ensureCapacity(length + n) + } + + private fun contentEquals(other: List<*>): Boolean { + return array.subarrayContentEquals(offset, length, other) + } + + private fun insertAtInternal(i: Int, n: Int) { + ensureExtraCapacity(n) + array.copyInto(array, startIndex = i, endIndex = offset + length, destinationOffset = i + n) + length += n + } + + private fun addAtInternal(i: Int, element: E) { + if (backing != null) { + backing.addAtInternal(i, element) + array = backing.array + length++ + } else { + insertAtInternal(i, 1) + array[i] = element + } + } + + private fun addAllInternal(i: Int, elements: Collection, n: Int) { + if (backing != null) { + backing.addAllInternal(i, elements, n) + array = backing.array + length += n + } else { + insertAtInternal(i, n) + var j = 0 + val it = elements.iterator() + while (j < n) { + array[i + j] = it.next() + j++ + } + } + } + + private fun removeAtInternal(i: Int): E { + if (backing != null) { + val old = backing.removeAtInternal(i) + length-- + return old + } else { + val old = array[i] + array.copyInto(array, startIndex = i + 1, endIndex = offset + length, destinationOffset = i) + array.resetAt(offset + length - 1) + length-- + return old + } + } + + private fun removeRangeInternal(rangeOffset: Int, rangeLength: Int) { + if (backing != null) { + backing.removeRangeInternal(rangeOffset, rangeLength) + } else { + array.copyInto(array, startIndex = rangeOffset + rangeLength, endIndex = length, destinationOffset = rangeOffset) + array.resetRange(fromIndex = length - rangeLength, toIndex = length) + } + length -= rangeLength + } + + /** Retains elements if [retain] == true and removes them it [retain] == false. */ + private fun retainOrRemoveAllInternal(rangeOffset: Int, rangeLength: Int, elements: Collection, retain: Boolean): Int { + if (backing != null) { + val removed = backing.retainOrRemoveAllInternal(rangeOffset, rangeLength, elements, retain) + length -= removed + return removed + } else { + var i = 0 + var j = 0 + while (i < rangeLength) { + if (elements.contains(array[rangeOffset + i]) == retain) { + array[rangeOffset + j++] = array[rangeOffset + i++] + } else { + i++ + } + } + val removed = rangeLength - j + array.copyInto(array, startIndex = rangeOffset + rangeLength, endIndex = length, destinationOffset = rangeOffset + j) + array.resetRange(fromIndex = length - removed, toIndex = length) + length -= removed + return removed + } + } + + private class Itr : MutableListIterator { + private val list: ArrayList + private var index: Int + private var lastIndex: Int + + constructor(list: ArrayList, index: Int) { + this.list = list + this.index = index + this.lastIndex = -1 + } + + override fun hasPrevious(): Boolean = index > 0 + override fun hasNext(): Boolean = index < list.length + + override fun previousIndex(): Int = index - 1 + override fun nextIndex(): Int = index + + override fun previous(): E { + if (index <= 0) throw NoSuchElementException() + lastIndex = --index + return list.array[list.offset + lastIndex] + } + + override fun next(): E { + if (index >= list.length) throw NoSuchElementException() + lastIndex = index++ + return list.array[list.offset + lastIndex] + } + + override fun set(element: E) { + check(lastIndex != -1) { "Call next() or previous() before replacing element from the iterator." } + list.set(lastIndex, element) + } + + override fun add(element: E) { + list.add(index++, element) + lastIndex = -1 + } + + override fun remove() { + check(lastIndex != -1) { "Call next() or previous() before removing element from the iterator." } + list.removeAt(lastIndex) + index = lastIndex + lastIndex = -1 + } + } +} + +private fun Array.subarrayContentHashCode(offset: Int, length: Int): Int { + var result = 1 + var i = 0 + while (i < length) { + val nextElement = this[offset + i] + result = result * 31 + nextElement.hashCode() + i++ + } + return result +} + +private fun Array.subarrayContentEquals(offset: Int, length: Int, other: List<*>): Boolean { + if (length != other.size) return false + var i = 0 + while (i < length) { + if (this[offset + i] != other[i]) return false + i++ + } + return true +} diff --git a/kotlin-native/runtime/src/main/kotlin/kotlin/collections/ArraySorting.kt b/kotlin-native/runtime/src/main/kotlin/kotlin/collections/ArraySorting.kt new file mode 100644 index 00000000000..1646c0121d6 --- /dev/null +++ b/kotlin-native/runtime/src/main/kotlin/kotlin/collections/ArraySorting.kt @@ -0,0 +1,395 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +package kotlin.collections + + +private fun > mergeSort(array: Array, start: Int, endInclusive: Int) { + @Suppress("UNCHECKED_CAST") + val buffer = arrayOfNulls(array.size) as Array + val result = mergeSort(array, buffer, start, endInclusive) + if (result !== array) { + for (i in start..endInclusive) array[i] = result[i] + } +} + +// Both start and end are inclusive indices. +private fun > mergeSort(array: Array, buffer: Array, start: Int, end: Int): Array { + if (start == end) { + return array + } + + val median = (start + end) / 2 + val left = mergeSort(array, buffer, start, median) + val right = mergeSort(array, buffer, median + 1, end) + + val target = if (left === buffer) array else buffer + + // Merge. + var leftIndex = start + var rightIndex = median + 1 + for (i in start..end) { + when { + leftIndex <= median && rightIndex <= end -> { + val leftValue = left[leftIndex] + val rightValue = right[rightIndex] + + if (leftValue <= rightValue) { + target[i] = leftValue + leftIndex++ + } else { + target[i] = rightValue + rightIndex++ + } + } + leftIndex <= median -> { + target[i] = left[leftIndex] + leftIndex++ + } + else /* rightIndex <= end */ -> { + target[i] = right[rightIndex] + rightIndex++ + } + } + } + + return target +} + +// Sort with comparator. +private fun mergeSort(array: Array, start: Int, endInclusive: Int, comparator: Comparator) { + @Suppress("UNCHECKED_CAST") + val buffer = arrayOfNulls(array.size) as Array + val result = mergeSort(array, buffer, start, endInclusive, comparator) + if (result !== array) { + for (i in start..endInclusive) array[i] = result[i] + } +} + +// Both start and end are inclusive indices. +private fun mergeSort(array: Array, buffer: Array, start: Int, end: Int, comparator: Comparator): Array { + if (start == end) { + return array + } + + val median = (start + end) / 2 + val left = mergeSort(array, buffer, start, median, comparator) + val right = mergeSort(array, buffer, median + 1, end, comparator) + + val target = if (left === buffer) array else buffer + + // Merge. + var leftIndex = start + var rightIndex = median + 1 + for (i in start..end) { + when { + leftIndex <= median && rightIndex <= end -> { + val leftValue = left[leftIndex] + val rightValue = right[rightIndex] + + if (comparator.compare(leftValue, rightValue) <= 0) { + target[i] = leftValue + leftIndex++ + } else { + target[i] = rightValue + rightIndex++ + } + } + leftIndex <= median -> { + target[i] = left[leftIndex] + leftIndex++ + } + else /* rightIndex <= end */ -> { + target[i] = right[rightIndex] + rightIndex++ + } + } + } + + return target +} + +// ByteArray ============================================================================= +private fun partition( + array: ByteArray, left: Int, right: Int): Int { + var i = left + var j = right + val pivot = array[(left + right) / 2] + while (i <= j) { + while (array[i] < pivot) + i++ + while (array[j] > pivot) + j-- + if (i <= j) { + val tmp = array[i] + array[i] = array[j] + array[j] = tmp + i++ + j-- + } + } + return i +} + +private fun quickSort( + array: ByteArray, left: Int, right: Int) { + val index = partition(array, left, right) + if (left < index - 1) + quickSort(array, left, index - 1) + if (index < right) + quickSort(array, index, right) +} + +// ShortArray ============================================================================= +private fun partition( + array: ShortArray, left: Int, right: Int): Int { + var i = left + var j = right + val pivot = array[(left + right) / 2] + while (i <= j) { + while (array[i] < pivot) + i++ + while (array[j] > pivot) + j-- + if (i <= j) { + val tmp = array[i] + array[i] = array[j] + array[j] = tmp + i++ + j-- + } + } + return i +} + +private fun quickSort( + array: ShortArray, left: Int, right: Int) { + val index = partition(array, left, right) + if (left < index - 1) + quickSort(array, left, index - 1) + if (index < right) + quickSort(array, index, right) +} + +// IntArray ============================================================================= +private fun partition( + array: IntArray, left: Int, right: Int): Int { + var i = left + var j = right + val pivot = array[(left + right) / 2] + while (i <= j) { + while (array[i] < pivot) + i++ + while (array[j] > pivot) + j-- + if (i <= j) { + val tmp = array[i] + array[i] = array[j] + array[j] = tmp + i++ + j-- + } + } + return i +} + +private fun quickSort( + array: IntArray, left: Int, right: Int) { + val index = partition(array, left, right) + if (left < index - 1) + quickSort(array, left, index - 1) + if (index < right) + quickSort(array, index, right) +} + +// LongArray ============================================================================= +private fun partition( + array: LongArray, left: Int, right: Int): Int { + var i = left + var j = right + val pivot = array[(left + right) / 2] + while (i <= j) { + while (array[i] < pivot) + i++ + while (array[j] > pivot) + j-- + if (i <= j) { + val tmp = array[i] + array[i] = array[j] + array[j] = tmp + i++ + j-- + } + } + return i +} + +private fun quickSort( + array: LongArray, left: Int, right: Int) { + val index = partition(array, left, right) + if (left < index - 1) + quickSort(array, left, index - 1) + if (index < right) + quickSort(array, index, right) +} + +// CharArray ============================================================================= +private fun partition( + array: CharArray, left: Int, right: Int): Int { + var i = left + var j = right + val pivot = array[(left + right) / 2] + while (i <= j) { + while (array[i] < pivot) + i++ + while (array[j] > pivot) + j-- + if (i <= j) { + val tmp = array[i] + array[i] = array[j] + array[j] = tmp + i++ + j-- + } + } + return i +} + +private fun quickSort( + array: CharArray, left: Int, right: Int) { + val index = partition(array, left, right) + if (left < index - 1) + quickSort(array, left, index - 1) + if (index < right) + quickSort(array, index, right) +} + +// FloatArray ============================================================================= +private fun partition( + array: FloatArray, left: Int, right: Int): Int { + var i = left + var j = right + val pivot = array[(left + right) / 2] + while (i <= j) { + while (array[i].compareTo(pivot) < 0) + i++ + while (array[j].compareTo(pivot) > 0) + j-- + if (i <= j) { + val tmp = array[i] + array[i] = array[j] + array[j] = tmp + i++ + j-- + } + } + return i +} + +private fun quickSort( + array: FloatArray, left: Int, right: Int) { + val index = partition(array, left, right) + if (left < index - 1) + quickSort(array, left, index - 1) + if (index < right) + quickSort(array, index, right) +} + +// DoubleArray ============================================================================= +private fun partition( + array: DoubleArray, left: Int, right: Int): Int { + var i = left + var j = right + val pivot = array[(left + right) / 2] + while (i <= j) { + while (array[i].compareTo(pivot) < 0) + i++ + while (array[j].compareTo(pivot) > 0) + j-- + if (i <= j) { + val tmp = array[i] + array[i] = array[j] + array[j] = tmp + i++ + j-- + } + } + return i +} + +private fun quickSort( + array: DoubleArray, left: Int, right: Int) { + val index = partition(array, left, right) + if (left < index - 1) + quickSort(array, left, index - 1) + if (index < right) + quickSort(array, index, right) +} + +// BooleanArray ============================================================================= +private fun partition( + array: BooleanArray, left: Int, right: Int): Int { + var i = left + var j = right + val pivot = array[(left + right) / 2] + while (i <= j) { + while (array[i] < pivot) + i++ + while (array[j] > pivot) + j-- + if (i <= j) { + val tmp = array[i] + array[i] = array[j] + array[j] = tmp + i++ + j-- + } + } + return i +} + +private fun quickSort( + array: BooleanArray, left: Int, right: Int) { + val index = partition(array, left, right) + if (left < index - 1) + quickSort(array, left, index - 1) + if (index < right) + quickSort(array, index, right) +} + +// Interfaces ============================================================================= +/** + * Sorts the subarray specified by [fromIndex] (inclusive) and [toIndex] (exclusive) parameters + * using the merge sort algorithm with the given [comparator]. + */ +internal fun sortArrayWith(array: Array, fromIndex: Int, toIndex: Int, comparator: Comparator) { + if (fromIndex < toIndex - 1) { + @Suppress("UNCHECKED_CAST") + mergeSort(array as Array, fromIndex, toIndex - 1, comparator) + } +} + +/** + * Sorts a subarray of [Comparable] elements specified by [fromIndex] (inclusive) and + * [toIndex] (exclusive) parameters using the merge sort algorithm. + */ +internal fun > sortArray(array: Array, fromIndex: Int, toIndex: Int) { + if (fromIndex < toIndex - 1) { + @Suppress("UNCHECKED_CAST") + mergeSort(array as Array, fromIndex, toIndex - 1) + } +} + +/** + * Sorts the given array using qsort algorithm. + */ +internal fun sortArray(array: ByteArray, fromIndex: Int, toIndex: Int) = quickSort(array, fromIndex, toIndex - 1) +internal fun sortArray(array: ShortArray, fromIndex: Int, toIndex: Int) = quickSort(array, fromIndex, toIndex - 1) +internal fun sortArray(array: IntArray, fromIndex: Int, toIndex: Int) = quickSort(array, fromIndex, toIndex - 1) +internal fun sortArray(array: LongArray, fromIndex: Int, toIndex: Int) = quickSort(array, fromIndex, toIndex - 1) +internal fun sortArray(array: CharArray, fromIndex: Int, toIndex: Int) = quickSort(array, fromIndex, toIndex - 1) +internal fun sortArray(array: FloatArray, fromIndex: Int, toIndex: Int) = quickSort(array, fromIndex, toIndex - 1) +internal fun sortArray(array: DoubleArray, fromIndex: Int, toIndex: Int) = quickSort(array, fromIndex, toIndex - 1) +internal fun sortArray(array: BooleanArray, fromIndex: Int, toIndex: Int) = quickSort(array, fromIndex, toIndex - 1) \ No newline at end of file diff --git a/kotlin-native/runtime/src/main/kotlin/kotlin/collections/ArrayUtil.kt b/kotlin-native/runtime/src/main/kotlin/kotlin/collections/ArrayUtil.kt new file mode 100644 index 00000000000..ad19f96b15b --- /dev/null +++ b/kotlin-native/runtime/src/main/kotlin/kotlin/collections/ArrayUtil.kt @@ -0,0 +1,169 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +package kotlin.collections + +import kotlin.native.internal.PointsTo +import kotlin.native.internal.ExportForCppRuntime + +/** + * Returns an array of objects of the given type with the given [size], initialized with _uninitialized_ values. + * Attempts to read _uninitialized_ values from this array work in implementation-dependent manner, + * either throwing exception or returning some kind of implementation-specific default value. + */ +@PublishedApi +internal inline fun arrayOfUninitializedElements(size: Int): Array { + // TODO: special case for size == 0? + require(size >= 0) { "capacity must be non-negative." } + @Suppress("TYPE_PARAMETER_AS_REIFIED") + return Array(size) +} + + +/** + * Returns a new array which is a copy of the original array with new elements filled with null values. + */ +internal fun Array.copyOfNulls(newSize: Int): Array = copyOfNulls(0, newSize) + +internal fun Array.copyOfNulls(fromIndex: Int, toIndex: Int): Array { + val newSize = toIndex - fromIndex + if (newSize < 0) { + throw IllegalArgumentException("$fromIndex > $toIndex") + } + val result = @Suppress("TYPE_PARAMETER_AS_REIFIED") arrayOfNulls(newSize) + this.copyInto(result, 0, fromIndex, toIndex.coerceAtMost(size)) + return result +} + +/** + * Copies elements of the [collection] into the given [array]. + * If the array is too small, allocates a new one of collection.size size. + * @return [array] with the elements copied from the collection. + */ +internal fun collectionToArray(collection: Collection, array: Array): Array { + val toArray = if (collection.size > array.size) { + arrayOfUninitializedElements(collection.size) + } else { + array + } + var i = 0 + for (v in collection) { + @Suppress("UNCHECKED_CAST") + toArray[i] = v as T + i++ + } + return toArray +} + +/** + * Creates an array of collection.size size and copies elements of the [collection] into it. + * @return [array] with the elements copied from the collection. + */ +internal fun collectionToArray(collection: Collection): Array + = collectionToArray(collection, arrayOfUninitializedElements(collection.size)) + + +/** + * Resets an array element at a specified index to some implementation-specific _uninitialized_ value. + * In particular, references stored in this element are released and become available for garbage collection. + * Attempts to read _uninitialized_ value work in implementation-dependent manner, + * either throwing exception or returning some kind of implementation-specific default value. + */ +internal fun Array.resetAt(index: Int) { + (@Suppress("UNCHECKED_CAST")(this as Array))[index] = null +} + +@SymbolName("Kotlin_Array_fillImpl") +@PointsTo(0x3000, 0x0000, 0x0000, 0x0000) // array.intestines -> value +internal external fun arrayFill(array: Array, fromIndex: Int, toIndex: Int, value: T) + +@SymbolName("Kotlin_ByteArray_fillImpl") +internal external fun arrayFill(array: ByteArray, fromIndex: Int, toIndex: Int, value: Byte) + +@SymbolName("Kotlin_ShortArray_fillImpl") +internal external fun arrayFill(array: ShortArray, fromIndex: Int, toIndex: Int, value: Short) + +@SymbolName("Kotlin_CharArray_fillImpl") +internal external fun arrayFill(array: CharArray, fromIndex: Int, toIndex: Int, value: Char) + +@SymbolName("Kotlin_IntArray_fillImpl") +internal external fun arrayFill(array: IntArray, fromIndex: Int, toIndex: Int, value: Int) + +@SymbolName("Kotlin_LongArray_fillImpl") +internal external fun arrayFill(array: LongArray, fromIndex: Int, toIndex: Int, value: Long) + +@SymbolName("Kotlin_DoubleArray_fillImpl") +internal external fun arrayFill(array: DoubleArray, fromIndex: Int, toIndex: Int, value: Double) + +@SymbolName("Kotlin_FloatArray_fillImpl") +internal external fun arrayFill(array: FloatArray, fromIndex: Int, toIndex: Int, value: Float) + +@SymbolName("Kotlin_BooleanArray_fillImpl") +internal external fun arrayFill(array: BooleanArray, fromIndex: Int, toIndex: Int, value: Boolean) + +@ExportForCppRuntime +internal fun checkRangeIndexes(fromIndex: Int, toIndex: Int, size: Int) { + if (fromIndex < 0 || toIndex > size) { + throw IndexOutOfBoundsException("fromIndex: $fromIndex, toIndex: $toIndex, size: $size") + } + if (fromIndex > toIndex) { + throw IllegalArgumentException("fromIndex: $fromIndex > toIndex: $toIndex") + } +} + +/** + * Resets a range of array elements at a specified [fromIndex] (inclusive) to [toIndex] (exclusive) range of indices + * to some implementation-specific _uninitialized_ value. + * In particular, references stored in these elements are released and become available for garbage collection. + * Attempts to read _uninitialized_ values work in implementation-dependent manner, + * either throwing exception or returning some kind of implementation-specific default value. + */ +internal fun Array.resetRange(fromIndex: Int, toIndex: Int) { + arrayFill(@Suppress("UNCHECKED_CAST") (this as Array), fromIndex, toIndex, null) +} + +@SymbolName("Kotlin_Array_copyImpl") +@PointsTo(0x00000, 0x00000, 0x00004, 0x00000, 0x00000) // destination.intestines -> array.intestines +internal external fun arrayCopy(array: Array, fromIndex: Int, destination: Array, toIndex: Int, count: Int) + +@SymbolName("Kotlin_ByteArray_copyImpl") +internal external fun arrayCopy(array: ByteArray, fromIndex: Int, destination: ByteArray, toIndex: Int, count: Int) + +@SymbolName("Kotlin_ShortArray_copyImpl") +internal external fun arrayCopy(array: ShortArray, fromIndex: Int, destination: ShortArray, toIndex: Int, count: Int) + +@SymbolName("Kotlin_CharArray_copyImpl") +internal external fun arrayCopy(array: CharArray, fromIndex: Int, destination: CharArray, toIndex: Int, count: Int) + +@SymbolName("Kotlin_IntArray_copyImpl") +internal external fun arrayCopy(array: IntArray, fromIndex: Int, destination: IntArray, toIndex: Int, count: Int) + +@SymbolName("Kotlin_LongArray_copyImpl") +internal external fun arrayCopy(array: LongArray, fromIndex: Int, destination: LongArray, toIndex: Int, count: Int) + +@SymbolName("Kotlin_FloatArray_copyImpl") +internal external fun arrayCopy(array: FloatArray, fromIndex: Int, destination: FloatArray, toIndex: Int, count: Int) + +@SymbolName("Kotlin_DoubleArray_copyImpl") +internal external fun arrayCopy(array: DoubleArray, fromIndex: Int, destination: DoubleArray, toIndex: Int, count: Int) + +@SymbolName("Kotlin_BooleanArray_copyImpl") +internal external fun arrayCopy(array: BooleanArray, fromIndex: Int, destination: BooleanArray, toIndex: Int, count: Int) + + +internal fun Collection.collectionToString(): String { + val sb = StringBuilder(2 + size * 3) + sb.append("[") + var i = 0 + val it = iterator() + while (it.hasNext()) { + if (i > 0) sb.append(", ") + val next = it.next() + if (next == this) sb.append("(this Collection)") else sb.append(next) + i++ + } + sb.append("]") + return sb.toString() +} diff --git a/kotlin-native/runtime/src/main/kotlin/kotlin/collections/Arrays.kt b/kotlin-native/runtime/src/main/kotlin/kotlin/collections/Arrays.kt new file mode 100644 index 00000000000..1e89a90e823 --- /dev/null +++ b/kotlin-native/runtime/src/main/kotlin/kotlin/collections/Arrays.kt @@ -0,0 +1,120 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +package kotlin.collections + +import kotlin.internal.PureReifiable + +/** Returns the array if it's not `null`, or an empty array otherwise. */ +public actual inline fun Array?.orEmpty(): Array = this ?: emptyArray() + +internal fun checkCopyOfRangeArguments(fromIndex: Int, toIndex: Int, size: Int) { + if (toIndex > size) + throw IndexOutOfBoundsException("toIndex ($toIndex) is greater than size ($size).") + if (fromIndex > toIndex) + throw IllegalArgumentException("fromIndex ($fromIndex) is greater than toIndex ($toIndex).") +} + + +// TODO: internal +/** + * Returns a string representation of the contents of the subarray of the specified array as if it is [List]. + */ +@kotlin.internal.InlineOnly +@Deprecated("This function will become internal soon.", level = DeprecationLevel.WARNING) +public inline fun Array.subarrayContentToString(offset: Int, length: Int): String { + val sb = StringBuilder(2 + length * 3) + sb.append("[") + var i = 0 + while (i < length) { + if (i > 0) sb.append(", ") + sb.append(this[offset + i]) + i++ + } + sb.append("]") + return sb.toString() +} + + +/** + * Returns a hash code based on the contents of this array as if it is [List]. + * Nested arrays are treated as lists too. + * + * If any of arrays contains itself on any nesting level the behavior is undefined. + */ +@SinceKotlin("1.1") +@OptIn(ExperimentalUnsignedTypes::class) +internal fun Array?.contentDeepHashCodeImpl(): Int { + if (this == null) return 0 + var result = 1 + for (element in this) { + val elementHash = when (element) { + null -> 0 + + is Array<*> -> element.contentDeepHashCode() + + is ByteArray -> element.contentHashCode() + is ShortArray -> element.contentHashCode() + is IntArray -> element.contentHashCode() + is LongArray -> element.contentHashCode() + is FloatArray -> element.contentHashCode() + is DoubleArray -> element.contentHashCode() + is CharArray -> element.contentHashCode() + is BooleanArray -> element.contentHashCode() + + is UByteArray -> element.contentHashCode() + is UShortArray -> element.contentHashCode() + is UIntArray -> element.contentHashCode() + is ULongArray -> element.contentHashCode() + + else -> element.hashCode() + } + + result = 31 * result + elementHash + } + return result +} + +@Suppress("UNCHECKED_CAST") +internal actual fun arrayOfNulls(reference: Array, size: Int): Array = arrayOfNulls(size) as Array + +internal actual fun copyToArrayImpl(collection: Collection<*>): Array { + val array = arrayOfUninitializedElements(collection.size) + val iterator = collection.iterator() + var index = 0 + while (iterator.hasNext()) + array[index++] = iterator.next() + return array +} + +@Suppress("UNCHECKED_CAST") +internal actual fun copyToArrayImpl(collection: Collection<*>, array: Array): Array { + if (array.size < collection.size) + return copyToArrayImpl(collection) as Array + + val iterator = collection.iterator() + var index = 0 + while (iterator.hasNext()) { + array[index++] = iterator.next() as T + } + if (index < array.size) { + return array.copyOf(index) as Array + } + return array +} + +/** + * Returns a *typed* array containing all of the elements of this collection. + * + * Allocates an array of runtime type `T` having its size equal to the size of this collection + * and populates the array with the elements of this collection. + */ +public actual inline fun Collection.toTypedArray(): Array { + val result = arrayOfNulls(size) + var index = 0 + for (element in this) result[index++] = element + @Suppress("UNCHECKED_CAST") + return result as Array +} diff --git a/kotlin-native/runtime/src/main/kotlin/kotlin/collections/Collection.kt b/kotlin-native/runtime/src/main/kotlin/kotlin/collections/Collection.kt new file mode 100644 index 00000000000..c2935df785d --- /dev/null +++ b/kotlin-native/runtime/src/main/kotlin/kotlin/collections/Collection.kt @@ -0,0 +1,90 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +package kotlin.collections + +/** + * A generic collection of elements. Methods in this interface support only read-only access to the collection; + * read/write access is supported through the [MutableCollection] interface. + * @param E the type of elements contained in the collection. The collection is covariant in its element type. + */ +public interface Collection : Iterable { + // Query Operations + /** + * Returns the size of the collection. + */ + public val size: Int + + /** + * Returns `true` if the collection is empty (contains no elements), `false` otherwise. + */ + public fun isEmpty(): Boolean + + /** + * Checks if the specified element is contained in this collection. + */ + public operator fun contains(element: @UnsafeVariance E): Boolean + override fun iterator(): Iterator + + // Bulk Operations + /** + * Checks if all elements in the specified collection are contained in this collection. + */ + public fun containsAll(elements: Collection<@UnsafeVariance E>): Boolean +} + +/** + * A generic collection of elements that supports adding and removing elements. + * + * @param E the type of elements contained in the collection. The mutable collection is invariant in its element type. + */ +public interface MutableCollection : Collection, MutableIterable { + // Query Operations + override fun iterator(): MutableIterator + + // Modification Operations + /** + * Adds the specified element to the collection. + * + * @return `true` if the element has been added, `false` if the collection does not support duplicates + * and the element is already contained in the collection. + */ + public fun add(element: E): Boolean + + /** + * Removes a single instance of the specified element from this + * collection, if it is present. + * + * @return `true` if the element has been successfully removed; `false` if it was not present in the collection. + */ + public fun remove(element: E): Boolean + + // Bulk Modification Operations + /** + * Adds all of the elements of the specified collection to this collection. + * + * @return `true` if any of the specified elements was added to the collection, `false` if the collection was not modified. + */ + public fun addAll(elements: Collection): Boolean + + /** + * Removes all of this collection's elements that are also contained in the specified collection. + * + * @return `true` if any of the specified elements was removed from the collection, `false` if the collection was not modified. + */ + public fun removeAll(elements: Collection): Boolean + + /** + * Retains only the elements in this collection that are contained in the specified collection. + * + * @return `true` if any element was removed from the collection, `false` if the collection was not modified. + */ + public fun retainAll(elements: Collection): Boolean + + /** + * Removes all elements from this collection. + */ + public fun clear(): Unit +} diff --git a/kotlin-native/runtime/src/main/kotlin/kotlin/collections/Collections.kt b/kotlin-native/runtime/src/main/kotlin/kotlin/collections/Collections.kt new file mode 100644 index 00000000000..3eb094f28da --- /dev/null +++ b/kotlin-native/runtime/src/main/kotlin/kotlin/collections/Collections.kt @@ -0,0 +1,137 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +package kotlin.collections + +import kotlin.comparisons.* +import kotlin.internal.InlineOnly +import kotlin.random.* + +/** Copies typed varargs array to an array of objects */ +internal actual fun Array.copyToArrayOfAny(isVarargs: Boolean): Array = + // if the array came from varargs and already is array of Any, copying isn't required. + if (isVarargs) this + else this.copyOfUninitializedElements(this.size) + + +/** + * Classes that inherit from this interface can be represented as a sequence of elements that can + * be iterated over. + * @param T the type of element being iterated over. The iterator is covariant in its element type. + */ +public interface Iterable { + /** + * Returns an iterator over the elements of this object. + */ + public operator fun iterator(): Iterator +} + +/** + * Classes that inherit from this interface can be represented as a sequence of elements that can + * be iterated over and that supports removing elements during iteration. + * @param T the type of element being iterated over. The mutable iterator is invariant in its element type. + */ +public interface MutableIterable : Iterable { + /** + * Returns an iterator over the elements of this sequence that supports removing elements during iteration. + */ + override fun iterator(): MutableIterator +} + + +@PublishedApi +@SinceKotlin("1.3") +@ExperimentalStdlibApi +@kotlin.internal.InlineOnly +internal actual inline fun buildListInternal(builderAction: MutableList.() -> Unit): List { + return ArrayList().apply(builderAction).build() +} + +@PublishedApi +@SinceKotlin("1.3") +@ExperimentalStdlibApi +@kotlin.internal.InlineOnly +internal actual inline fun buildListInternal(capacity: Int, builderAction: MutableList.() -> Unit): List { + return ArrayList(capacity).apply(builderAction).build() +} + + +/** + * Replaces each element in the list with a result of a transformation specified. + */ +public fun MutableList.replaceAll(transformation: (T) -> T) { + val it = listIterator() + while (it.hasNext()) { + val element = it.next() + it.set(transformation(element)) + } +} + +/** + * Groups elements from the [Grouping] source by key and counts elements in each group. + * + * @return a [Map] associating the key of each group with the count of elements in the group. + * + * @sample samples.collections.Grouping.groupingByEachCount + */ +@SinceKotlin("1.1") +public actual fun Grouping.eachCount(): Map = eachCountTo(mutableMapOf()) + +// Copied from JS. + +/** + * Fills the list with the provided [value]. + * + * Each element in the list gets replaced with the [value]. + */ +@SinceKotlin("1.2") +public actual fun MutableList.fill(value: T): Unit { + for (index in 0..lastIndex) { + this[index] = value + } +} + +/** + * Randomly shuffles elements in this list. + * + * See: https://en.wikipedia.org/wiki/Fisher%E2%80%93Yates_shuffle#The_modern_algorithm + */ +@SinceKotlin("1.2") +public actual fun MutableList.shuffle(): Unit { + for (i in lastIndex downTo 1) { + val j = Random.nextInt(i + 1) + val copy = this[i] + this[i] = this[j] + this[j] = copy + } +} + +/** + * Returns a new list with the elements of this list randomly shuffled. + */ +@SinceKotlin("1.2") +public actual fun Iterable.shuffled(): List = toMutableList().apply { shuffle() } + +@PublishedApi +@SinceKotlin("1.3") +@InlineOnly +internal actual inline fun checkIndexOverflow(index: Int): Int { + if (index < 0) { + // TODO: api version check? + throwIndexOverflow() + } + return index +} + +@PublishedApi +@SinceKotlin("1.3") +@InlineOnly +internal actual inline fun checkCountOverflow(count: Int): Int { + if (count < 0) { + // TODO: api version check? + throwCountOverflow() + } + return count +} diff --git a/kotlin-native/runtime/src/main/kotlin/kotlin/collections/HashMap.kt b/kotlin-native/runtime/src/main/kotlin/kotlin/collections/HashMap.kt new file mode 100644 index 00000000000..22384f69b74 --- /dev/null +++ b/kotlin-native/runtime/src/main/kotlin/kotlin/collections/HashMap.kt @@ -0,0 +1,660 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +package kotlin.collections + +import kotlin.native.concurrent.isFrozen + +actual class HashMap private constructor( + private var keysArray: Array, + private var valuesArray: Array?, // allocated only when actually used, always null in pure HashSet + private var presenceArray: IntArray, + private var hashArray: IntArray, + private var maxProbeDistance: Int, + private var length: Int +) : MutableMap { + private var hashShift: Int = computeShift(hashSize) + + private var _size: Int = 0 + override actual val size: Int + get() = _size + + private var keysView: HashMapKeys? = null + private var valuesView: HashMapValues? = null + private var entriesView: HashMapEntrySet? = null + + private var isReadOnly: Boolean = false + + // ---------------------------- functions ---------------------------- + + actual constructor() : this(INITIAL_CAPACITY) + + actual constructor(initialCapacity: Int) : this( + arrayOfUninitializedElements(initialCapacity), + null, + IntArray(initialCapacity), + IntArray(computeHashSize(initialCapacity)), + INITIAL_MAX_PROBE_DISTANCE, + 0) + + actual constructor(original: Map) : this(original.size) { + putAll(original) + } + + // This implementation doesn't use a loadFactor, this constructor is used for compatibility with common stdlib + actual constructor(initialCapacity: Int, loadFactor: Float) : this(initialCapacity) + + @PublishedApi + internal fun build(): Map { + checkIsMutable() + isReadOnly = true + return this + } + + override actual fun isEmpty(): Boolean = _size == 0 + override actual fun containsKey(key: K): Boolean = findKey(key) >= 0 + override actual fun containsValue(value: V): Boolean = findValue(value) >= 0 + + override actual operator fun get(key: K): V? { + val index = findKey(key) + if (index < 0) return null + return valuesArray!![index] + } + + override actual fun put(key: K, value: V): V? { + checkIsMutable() + val index = addKey(key) + val valuesArray = allocateValuesArray() + if (index < 0) { + val oldValue = valuesArray[-index - 1] + valuesArray[-index - 1] = value + return oldValue + } else { + valuesArray[index] = value + return null + } + } + + override actual fun putAll(from: Map) { + checkIsMutable() + putAllEntries(from.entries) + } + + override actual fun remove(key: K): V? { + val index = removeKey(key) // mutability gets checked here + if (index < 0) return null + val valuesArray = valuesArray!! + val oldValue = valuesArray[index] + valuesArray.resetAt(index) + return oldValue + } + + override actual fun clear() { + checkIsMutable() + // O(length) implementation for hashArray cleanup + for (i in 0..length - 1) { + val hash = presenceArray[i] + if (hash >= 0) { + hashArray[hash] = 0 + presenceArray[i] = TOMBSTONE + } + } + keysArray.resetRange(0, length) + valuesArray?.resetRange(0, length) + _size = 0 + length = 0 + } + + override actual val keys: MutableSet get() { + val cur = keysView + return if (cur == null) { + val new = HashMapKeys(this) + if (!isFrozen) + keysView = new + new + } else cur + } + + override actual val values: MutableCollection get() { + val cur = valuesView + return if (cur == null) { + val new = HashMapValues(this) + if (!isFrozen) + valuesView = new + new + } else cur + } + + override actual val entries: MutableSet> get() { + val cur = entriesView + return if (cur == null) { + val new = HashMapEntrySet(this) + if (!isFrozen) + entriesView = new + return new + } else cur + } + + override fun equals(other: Any?): Boolean { + return other === this || + (other is Map<*, *>) && + contentEquals(other) + } + + override fun hashCode(): Int { + var result = 0 + val it = entriesIterator() + while (it.hasNext()) { + result += it.nextHashCode() + } + return result + } + + override fun toString(): String { + val sb = StringBuilder(2 + _size * 3) + sb.append("{") + var i = 0 + val it = entriesIterator() + while (it.hasNext()) { + if (i > 0) sb.append(", ") + it.nextAppendString(sb) + i++ + } + sb.append("}") + return sb.toString() + } + + // ---------------------------- private ---------------------------- + + private val capacity: Int get() = keysArray.size + private val hashSize: Int get() = hashArray.size + + internal fun checkIsMutable() { + if (isReadOnly) throw UnsupportedOperationException() + } + + private fun ensureExtraCapacity(n: Int) { + ensureCapacity(length + n) + } + + private fun ensureCapacity(capacity: Int) { + if (capacity > this.capacity) { + var newSize = this.capacity * 3 / 2 + if (capacity > newSize) newSize = capacity + keysArray = keysArray.copyOfUninitializedElements(newSize) + valuesArray = valuesArray?.copyOfUninitializedElements(newSize) + presenceArray = presenceArray.copyOf(newSize) + val newHashSize = computeHashSize(newSize) + if (newHashSize > hashSize) rehash(newHashSize) + } else if (length + capacity - _size > this.capacity) { + rehash(hashSize) + } + } + + private fun allocateValuesArray(): Array { + val curValuesArray = valuesArray + if (curValuesArray != null) return curValuesArray + val newValuesArray = arrayOfUninitializedElements(capacity) + valuesArray = newValuesArray + return newValuesArray + } + + // Null-check for escaping extra boxing for non-nullable keys. + private fun hash(key: K) = if (key == null) 0 else (key.hashCode() * MAGIC) ushr hashShift + + private fun compact() { + var i = 0 + var j = 0 + val valuesArray = valuesArray + while (i < length) { + if (presenceArray[i] >= 0) { + keysArray[j] = keysArray[i] + if (valuesArray != null) valuesArray[j] = valuesArray[i] + j++ + } + i++ + } + keysArray.resetRange(j, length) + valuesArray?.resetRange(j, length) + length = j + //check(length == size) { "Internal invariant violated during compact: length=$length != size=$size" } + } + + private fun rehash(newHashSize: Int) { + if (length > _size) compact() + if (newHashSize != hashSize) { + hashArray = IntArray(newHashSize) + hashShift = computeShift(newHashSize) + } else { + hashArray.fill(0, 0, hashSize) + } + var i = 0 + while (i < length) { + if (!putRehash(i++)) { + throw IllegalStateException("This cannot happen with fixed magic multiplier and grow-only hash array. " + + "Have object hashCodes changed?") + } + } + } + + private fun putRehash(i: Int): Boolean { + var hash = hash(keysArray[i]) + var probesLeft = maxProbeDistance + while (true) { + val index = hashArray[hash] + if (index == 0) { + hashArray[hash] = i + 1 + presenceArray[i] = hash + return true + } + if (--probesLeft < 0) return false + if (hash-- == 0) hash = hashSize - 1 + } + } + + private fun findKey(key: K): Int { + var hash = hash(key) + var probesLeft = maxProbeDistance + while (true) { + val index = hashArray[hash] + if (index == 0) return TOMBSTONE + if (index > 0 && keysArray[index - 1] == key) return index - 1 + if (--probesLeft < 0) return TOMBSTONE + if (hash-- == 0) hash = hashSize - 1 + } + } + + private fun findValue(value: V): Int { + var i = length + while (--i >= 0) { + if (presenceArray[i] >= 0 && valuesArray!![i] == value) + return i + } + return TOMBSTONE + } + + internal fun addKey(key: K): Int { + checkIsMutable() + retry@ while (true) { + var hash = hash(key) + // put is allowed to grow maxProbeDistance with some limits (resize hash on reaching limits) + val tentativeMaxProbeDistance = (maxProbeDistance * 2).coerceAtMost(hashSize / 2) + var probeDistance = 0 + while (true) { + val index = hashArray[hash] + if (index <= 0) { // claim or reuse hash slot + if (length >= capacity) { + ensureExtraCapacity(1) + continue@retry + } + val putIndex = length++ + keysArray[putIndex] = key + presenceArray[putIndex] = hash + hashArray[hash] = putIndex + 1 + _size++ + if (probeDistance > maxProbeDistance) maxProbeDistance = probeDistance + return putIndex + } + if (keysArray[index - 1] == key) { + return -index + } + if (++probeDistance > tentativeMaxProbeDistance) { + rehash(hashSize * 2) // cannot find room even with extra "tentativeMaxProbeDistance" -- grow hash + continue@retry + } + if (hash-- == 0) hash = hashSize - 1 + } + } + } + + internal fun removeKey(key: K): Int { + checkIsMutable() + val index = findKey(key) + if (index < 0) return TOMBSTONE + removeKeyAt(index) + return index + } + + private fun removeKeyAt(index: Int) { + keysArray.resetAt(index) + removeHashAt(presenceArray[index]) + presenceArray[index] = TOMBSTONE + _size-- + } + + private fun removeHashAt(removedHash: Int) { + var hash = removedHash + var hole = removedHash // will try to patch the hole in hash array + var probeDistance = 0 + var patchAttemptsLeft = (maxProbeDistance * 2).coerceAtMost(hashSize / 2) // don't spend too much effort + while (true) { + if (hash-- == 0) hash = hashSize - 1 + if (++probeDistance > maxProbeDistance) { + // too far away -- can release the hole, bad case will not happen + hashArray[hole] = 0 + return + } + val index = hashArray[hash] + if (index == 0) { + // end of chain -- can release the hole, bad case will not happen + hashArray[hole] = 0 + return + } + if (index < 0) { + // TOMBSTONE FOUND + // - <--- [ TS ] ------ [hole] ---> + + // \------------/ + // probeDistance + // move tombstone into the hole + hashArray[hole] = TOMBSTONE + hole = hash + probeDistance = 0 + } else { + val otherHash = hash(keysArray[index - 1]) + // Bad case: + // - <--- [hash] ------ [hole] ------ [otherHash] ---> + + // \------------/ + // probeDistance + if ((otherHash - hash) and (hashSize - 1) >= probeDistance) { + // move otherHash into the hole, move the hole + hashArray[hole] = index + presenceArray[index - 1] = hole + hole = hash + probeDistance = 0 + } + } + // check how long we're patching holes + if (--patchAttemptsLeft < 0) { + // just place tombstone into the hole + hashArray[hole] = TOMBSTONE + return + } + } + } + + internal fun containsEntry(entry: Map.Entry): Boolean { + val index = findKey(entry.key) + if (index < 0) return false + return valuesArray!![index] == entry.value + } + + internal fun getEntry(entry: Map.Entry): MutableMap.MutableEntry? { + val index = findKey(entry.key) + return if (index < 0 || valuesArray!![index] != entry.value) { + null + } else { + EntryRef(this, index) + } + } + + internal fun getKey(key: K): K? { + val index = findKey(key) + return if (index >= 0) { + keysArray[index]!! + } else { + null + } + } + + private fun contentEquals(other: Map<*, *>): Boolean = _size == other.size && containsAllEntries(other.entries) + + internal fun containsAllEntries(m: Collection<*>): Boolean { + val it = m.iterator() + while (it.hasNext()) { + val entry = it.next() + try { + @Suppress("UNCHECKED_CAST") // todo: get rid of unchecked cast here somehow + if (entry == null || !containsEntry(entry as Map.Entry)) + return false + } catch (e: ClassCastException) { + return false + } + } + return true + } + + private fun putEntry(entry: Map.Entry): Boolean { + val index = addKey(entry.key) + val valuesArray = allocateValuesArray() + if (index >= 0) { + valuesArray[index] = entry.value + return true + } + val oldValue = valuesArray[-index - 1] + if (entry.value != oldValue) { + valuesArray[-index - 1] = entry.value + return true + } + return false + } + + private fun putAllEntries(from: Collection>): Boolean { + if (from.isEmpty()) return false + ensureExtraCapacity(from.size) + val it = from.iterator() + var updated = false + while (it.hasNext()) { + if (putEntry(it.next())) + updated = true + } + return updated + } + + internal fun removeEntry(entry: Map.Entry): Boolean { + checkIsMutable() + val index = findKey(entry.key) + if (index < 0) return false + if (valuesArray!![index] != entry.value) return false + removeKeyAt(index) + return true + } + + internal fun removeValue(element: V): Boolean { + checkIsMutable() + val index = findValue(element) + if (index < 0) return false + removeKeyAt(index) + return true + } + + internal fun keysIterator() = KeysItr(this) + internal fun valuesIterator() = ValuesItr(this) + internal fun entriesIterator() = EntriesItr(this) + + @kotlin.native.internal.CanBePrecreated + private companion object { + private const val MAGIC = -1640531527 // 2654435769L.toInt(), golden ratio + private const val INITIAL_CAPACITY = 8 + private const val INITIAL_MAX_PROBE_DISTANCE = 2 + private const val TOMBSTONE = -1 + + @OptIn(ExperimentalStdlibApi::class) + private fun computeHashSize(capacity: Int): Int = (capacity.coerceAtLeast(1) * 3).takeHighestOneBit() + + @OptIn(ExperimentalStdlibApi::class) + private fun computeShift(hashSize: Int): Int = hashSize.countLeadingZeroBits() + 1 + } + + internal open class Itr( + internal val map: HashMap + ) { + internal var index = 0 + internal var lastIndex: Int = -1 + + init { + initNext() + } + + internal fun initNext() { + while (index < map.length && map.presenceArray[index] < 0) + index++ + } + + fun hasNext(): Boolean = index < map.length + + fun remove() { + map.checkIsMutable() + map.removeKeyAt(lastIndex) + lastIndex = -1 + } + } + + internal class KeysItr(map: HashMap) : Itr(map), MutableIterator { + override fun next(): K { + if (index >= map.length) throw NoSuchElementException() + lastIndex = index++ + val result = map.keysArray[lastIndex] + initNext() + return result + } + + } + + internal class ValuesItr(map: HashMap) : Itr(map), MutableIterator { + override fun next(): V { + if (index >= map.length) throw NoSuchElementException() + lastIndex = index++ + val result = map.valuesArray!![lastIndex] + initNext() + return result + } + } + + internal class EntriesItr(map: HashMap) : Itr(map), + MutableIterator> { + override fun next(): EntryRef { + if (index >= map.length) throw NoSuchElementException() + lastIndex = index++ + val result = EntryRef(map, lastIndex) + initNext() + return result + } + + internal fun nextHashCode(): Int { + if (index >= map.length) throw NoSuchElementException() + lastIndex = index++ + val result = map.keysArray[lastIndex].hashCode() xor map.valuesArray!![lastIndex].hashCode() + initNext() + return result + } + + fun nextAppendString(sb: StringBuilder) { + if (index >= map.length) throw NoSuchElementException() + lastIndex = index++ + val key = map.keysArray[lastIndex] + if (key == map) sb.append("(this Map)") else sb.append(key) + sb.append('=') + val value = map.valuesArray!![lastIndex] + if (value == map) sb.append("(this Map)") else sb.append(value) + initNext() + } + } + + internal class EntryRef( + private val map: HashMap, + private val index: Int + ) : MutableMap.MutableEntry { + override val key: K + get() = map.keysArray[index] + + override val value: V + get() = map.valuesArray!![index] + + override fun setValue(newValue: V): V { + map.checkIsMutable() + val valuesArray = map.allocateValuesArray() + val oldValue = valuesArray[index] + valuesArray[index] = newValue + return oldValue + } + + override fun equals(other: Any?): Boolean = + other is Map.Entry<*, *> && + other.key == key && + other.value == value + + override fun hashCode(): Int = key.hashCode() xor value.hashCode() + + override fun toString(): String = "$key=$value" + } +} + +internal class HashMapKeys internal constructor( + private val backing: HashMap +) : MutableSet, kotlin.native.internal.KonanSet, AbstractMutableSet() { + + override val size: Int get() = backing.size + override fun isEmpty(): Boolean = backing.isEmpty() + override fun contains(element: E): Boolean = backing.containsKey(element) + override fun getElement(element: E): E? = backing.getKey(element) + override fun clear() = backing.clear() + override fun add(element: E): Boolean = throw UnsupportedOperationException() + override fun addAll(elements: Collection): Boolean = throw UnsupportedOperationException() + override fun remove(element: E): Boolean = backing.removeKey(element) >= 0 + override fun iterator(): MutableIterator = backing.keysIterator() + + override fun removeAll(elements: Collection): Boolean { + backing.checkIsMutable() + return super.removeAll(elements) + } + + override fun retainAll(elements: Collection): Boolean { + backing.checkIsMutable() + return super.retainAll(elements) + } +} + +internal class HashMapValues internal constructor( + val backing: HashMap<*, V> +) : MutableCollection, AbstractMutableCollection() { + + override val size: Int get() = backing.size + override fun isEmpty(): Boolean = backing.isEmpty() + override fun contains(element: V): Boolean = backing.containsValue(element) + override fun add(element: V): Boolean = throw UnsupportedOperationException() + override fun addAll(elements: Collection): Boolean = throw UnsupportedOperationException() + override fun clear() = backing.clear() + override fun iterator(): MutableIterator = backing.valuesIterator() + override fun remove(element: V): Boolean = backing.removeValue(element) + + override fun removeAll(elements: Collection): Boolean { + backing.checkIsMutable() + return super.removeAll(elements) + } + + override fun retainAll(elements: Collection): Boolean { + backing.checkIsMutable() + return super.retainAll(elements) + } +} + +internal class HashMapEntrySet internal constructor( + val backing: HashMap +) : MutableSet>, kotlin.native.internal.KonanSet>, AbstractMutableSet>() { + + override val size: Int get() = backing.size + override fun isEmpty(): Boolean = backing.isEmpty() + override fun contains(element: MutableMap.MutableEntry): Boolean = backing.containsEntry(element) + override fun getElement(element: MutableMap.MutableEntry): MutableMap.MutableEntry? = backing.getEntry(element) + override fun clear() = backing.clear() + override fun add(element: MutableMap.MutableEntry): Boolean = throw UnsupportedOperationException() + override fun addAll(elements: Collection>): Boolean = throw UnsupportedOperationException() + override fun remove(element: MutableMap.MutableEntry): Boolean = backing.removeEntry(element) + override fun iterator(): MutableIterator> = backing.entriesIterator() + override fun containsAll(elements: Collection>): Boolean = backing.containsAllEntries(elements) + + override fun removeAll(elements: Collection>): Boolean { + backing.checkIsMutable() + return super.removeAll(elements) + } + + override fun retainAll(elements: Collection>): Boolean { + backing.checkIsMutable() + return super.retainAll(elements) + } +} + +// This hash map keeps insertion order. +actual typealias LinkedHashMap = HashMap \ No newline at end of file diff --git a/kotlin-native/runtime/src/main/kotlin/kotlin/collections/HashSet.kt b/kotlin-native/runtime/src/main/kotlin/kotlin/collections/HashSet.kt new file mode 100644 index 00000000000..004bf7675fe --- /dev/null +++ b/kotlin-native/runtime/src/main/kotlin/kotlin/collections/HashSet.kt @@ -0,0 +1,55 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +package kotlin.collections + +actual class HashSet internal constructor( + private val backing: HashMap +) : MutableSet, kotlin.native.internal.KonanSet, AbstractMutableSet() { + + actual constructor() : this(HashMap()) + + actual constructor(initialCapacity: Int) : this(HashMap(initialCapacity)) + + actual constructor(elements: Collection) : this(elements.size) { + addAll(elements) + } + + // This implementation doesn't use a loadFactor + actual constructor(initialCapacity: Int, loadFactor: Float) : this(initialCapacity) + + @PublishedApi + internal fun build(): Set { + backing.build() + return this + } + + override actual val size: Int get() = backing.size + override actual fun isEmpty(): Boolean = backing.isEmpty() + override actual fun contains(element: E): Boolean = backing.containsKey(element) + override fun getElement(element: E): E? = backing.getKey(element) + override actual fun clear() = backing.clear() + override actual fun add(element: E): Boolean = backing.addKey(element) >= 0 + override actual fun remove(element: E): Boolean = backing.removeKey(element) >= 0 + override actual fun iterator(): MutableIterator = backing.keysIterator() + + override actual fun addAll(elements: Collection): Boolean { + backing.checkIsMutable() + return super.addAll(elements) + } + + override actual fun removeAll(elements: Collection): Boolean { + backing.checkIsMutable() + return super.removeAll(elements) + } + + override actual fun retainAll(elements: Collection): Boolean { + backing.checkIsMutable() + return super.retainAll(elements) + } +} + +// This hash set keeps insertion order. +actual typealias LinkedHashSet = HashSet \ No newline at end of file diff --git a/kotlin-native/runtime/src/main/kotlin/kotlin/collections/Iterator.kt b/kotlin-native/runtime/src/main/kotlin/kotlin/collections/Iterator.kt new file mode 100644 index 00000000000..274a682945c --- /dev/null +++ b/kotlin-native/runtime/src/main/kotlin/kotlin/collections/Iterator.kt @@ -0,0 +1,91 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +package kotlin.collections + +/** + * An iterator over a collection or another entity that can be represented as a sequence of elements. + * Allows to sequentially access the elements. + */ +public interface Iterator { + /** + * Returns the next element in the iteration. + */ + public operator fun next(): T + + /** + * Returns `true` if the iteration has more elements. + */ + public operator fun hasNext(): Boolean +} + +/** + * An iterator over a mutable collection. Provides the ability to remove elements while iterating. + * @see MutableCollection.iterator + */ +public interface MutableIterator : Iterator { + /** + * Removes from the underlying collection the last element returned by this iterator. + */ + public fun remove(): Unit +} + +/** + * An iterator over a collection that supports indexed access. + * @see List.listIterator + */ +public interface ListIterator : Iterator { + // Query Operations + override fun next(): T + override fun hasNext(): Boolean + + /** + * Returns `true` if there are elements in the iteration before the current element. + */ + public fun hasPrevious(): Boolean + + /** + * Returns the previous element in the iteration and moves the cursor position backwards. + */ + public fun previous(): T + + /** + * Returns the index of the element that would be returned by a subsequent call to [next]. + */ + public fun nextIndex(): Int + + /** + * Returns the index of the element that would be returned by a subsequent call to [previous]. + */ + public fun previousIndex(): Int +} + +/** + * An iterator over a mutable collection that supports indexed access. Provides the ability + * to add, modify and remove elements while iterating. + */ +public interface MutableListIterator : ListIterator, MutableIterator { + // Query Operations + override fun next(): T + override fun hasNext(): Boolean + + // Modification Operations + override fun remove(): Unit + + /** + * Replaces the last element returned by [next] or [previous] with the specified element [element]. + */ + public fun set(element: T): Unit + + /** + * Adds the specified element [element] into the underlying collection immediately before the element that would be + * returned by [next], if any, and after the element that would be returned by [previous], if any. + * (If the collection contains no elements, the new element becomes the sole element in the collection.) + * The new element is inserted before the implicit cursor: a subsequent call to [next] would be unaffected, + * and a subsequent call to [previous] would return the new element. (This call increases by one the value \ + * that would be returned by a call to [nextIndex] or [previousIndex].) + */ + public fun add(element: T): Unit +} diff --git a/kotlin-native/runtime/src/main/kotlin/kotlin/collections/Iterators.kt b/kotlin-native/runtime/src/main/kotlin/kotlin/collections/Iterators.kt new file mode 100644 index 00000000000..08f4990bc45 --- /dev/null +++ b/kotlin-native/runtime/src/main/kotlin/kotlin/collections/Iterators.kt @@ -0,0 +1,70 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +package kotlin.collections + +/** An iterator over a sequence of values of type `Byte`. */ +public abstract class ByteIterator : Iterator { + override final fun next() = nextByte() + + /** Returns the next value in the sequence without boxing. */ + public abstract fun nextByte(): Byte +} + +/** An iterator over a sequence of values of type `Char`. */ +public abstract class CharIterator : Iterator { + override final fun next() = nextChar() + + /** Returns the next value in the sequence without boxing. */ + public abstract fun nextChar(): Char +} + +/** An iterator over a sequence of values of type `Short`. */ +public abstract class ShortIterator : Iterator { + override final fun next() = nextShort() + + /** Returns the next value in the sequence without boxing. */ + public abstract fun nextShort(): Short +} + +/** An iterator over a sequence of values of type `Int`. */ +public abstract class IntIterator : Iterator { + override final fun next() = nextInt() + + /** Returns the next value in the sequence without boxing. */ + public abstract fun nextInt(): Int +} + +/** An iterator over a sequence of values of type `Long`. */ +public abstract class LongIterator : Iterator { + override final fun next() = nextLong() + + /** Returns the next value in the sequence without boxing. */ + public abstract fun nextLong(): Long +} + +/** An iterator over a sequence of values of type `Float`. */ +public abstract class FloatIterator : Iterator { + override final fun next() = nextFloat() + + /** Returns the next value in the sequence without boxing. */ + public abstract fun nextFloat(): Float +} + +/** An iterator over a sequence of values of type `Double`. */ +public abstract class DoubleIterator : Iterator { + override final fun next() = nextDouble() + + /** Returns the next value in the sequence without boxing. */ + public abstract fun nextDouble(): Double +} + +/** An iterator over a sequence of values of type `Boolean`. */ +public abstract class BooleanIterator : Iterator { + override final fun next() = nextBoolean() + + /** Returns the next value in the sequence without boxing. */ + public abstract fun nextBoolean(): Boolean +} diff --git a/kotlin-native/runtime/src/main/kotlin/kotlin/collections/List.kt b/kotlin-native/runtime/src/main/kotlin/kotlin/collections/List.kt new file mode 100644 index 00000000000..ace36b768a7 --- /dev/null +++ b/kotlin-native/runtime/src/main/kotlin/kotlin/collections/List.kt @@ -0,0 +1,126 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +package kotlin.collections + +/** + * A generic ordered collection of elements. Methods in this interface support only read-only access to the list; + * read/write access is supported through the [MutableList] interface. + * @param E the type of elements contained in the list. The list is covariant in its element type. + */ +public interface List : Collection { + // Query Operations + override val size: Int + override fun isEmpty(): Boolean + override fun contains(element: @UnsafeVariance E): Boolean + override fun iterator(): Iterator + + // Bulk Operations + override fun containsAll(elements: Collection<@UnsafeVariance E>): Boolean + + // Positional Access Operations + /** + * Returns the element at the specified index in the list. + */ + public operator fun get(index: Int): E + + // Search Operations + /** + * Returns the index of the first occurrence of the specified element in the list, or -1 if the specified + * element is not contained in the list. + */ + public fun indexOf(element: @UnsafeVariance E): Int + + /** + * Returns the index of the last occurrence of the specified element in the list, or -1 if the specified + * element is not contained in the list. + */ + public fun lastIndexOf(element: @UnsafeVariance E): Int + + // List Iterators + /** + * Returns a list iterator over the elements in this list (in proper sequence). + */ + public fun listIterator(): ListIterator + + /** + * Returns a list iterator over the elements in this list (in proper sequence), starting at the specified [index]. + */ + public fun listIterator(index: Int): ListIterator + + // View + /** + * Returns a view of the portion of this list between the specified [fromIndex] (inclusive) and [toIndex] (exclusive). + * The returned list is backed by this list, so non-structural changes in the returned list are reflected in this list, and vice-versa. + * + * Structural changes in the base list make the behavior of the view undefined. + */ + public fun subList(fromIndex: Int, toIndex: Int): List +} + +/** + * A generic ordered collection of elements that supports adding and removing elements. + * @param E the type of elements contained in the list. The mutable list is invariant in its element type. + */ +public interface MutableList : List, MutableCollection { + // Modification Operations + /** + * Adds the specified element to the end of this list. + * + * @return `true` because the list is always modified as the result of this operation. + */ + override fun add(element: E): Boolean + + override fun remove(element: E): Boolean + + // Bulk Modification Operations + /** + * Adds all of the elements of the specified collection to the end of this list. + * + * The elements are appended in the order they appear in the [elements] collection. + * + * @return `true` if the list was changed as the result of the operation. + */ + override fun addAll(elements: Collection): Boolean + + /** + * Inserts all of the elements of the specified collection [elements] into this list at the specified [index]. + * + * @return `true` if the list was changed as the result of the operation. + */ + public fun addAll(index: Int, elements: Collection): Boolean + + override fun removeAll(elements: Collection): Boolean + override fun retainAll(elements: Collection): Boolean + override fun clear(): Unit + + // Positional Access Operations + /** + * Replaces the element at the specified position in this list with the specified element. + * + * @return the element previously at the specified position. + */ + public operator fun set(index: Int, element: E): E + + /** + * Inserts an element into the list at the specified [index]. + */ + public fun add(index: Int, element: E): Unit + + /** + * Removes an element at the specified [index] from the list. + * + * @return the element that has been removed. + */ + public fun removeAt(index: Int): E + + // List Iterators + override fun listIterator(): MutableListIterator + + override fun listIterator(index: Int): MutableListIterator + + // View + override fun subList(fromIndex: Int, toIndex: Int): MutableList +} \ No newline at end of file diff --git a/kotlin-native/runtime/src/main/kotlin/kotlin/collections/Map.kt b/kotlin-native/runtime/src/main/kotlin/kotlin/collections/Map.kt new file mode 100644 index 00000000000..076a179b3c5 --- /dev/null +++ b/kotlin-native/runtime/src/main/kotlin/kotlin/collections/Map.kt @@ -0,0 +1,136 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +package kotlin.collections + +/** + * A collection that holds pairs of objects (keys and values) and supports efficiently retrieving + * the value corresponding to each key. Map keys are unique; the map holds only one value for each key. + * Methods in this interface support only read-only access to the map; read-write access is supported through + * the [MutableMap] interface. + * @param K the type of map keys. The map is invariant in its key type, as it + * can accept key as a parameter (of [containsKey] for example) and return it in [keys] set. + * @param V the type of map values. The map is covariant in its value type. + */ +public interface Map { + // Query Operations + /** + * Returns the number of key/value pairs in the map. + */ + public val size: Int + + /** + * Returns `true` if the map is empty (contains no elements), `false` otherwise. + */ + public fun isEmpty(): Boolean + + /** + * Returns `true` if the map contains the specified [key]. + */ + public fun containsKey(key: K): Boolean + + /** + * Returns `true` if the map maps one or more keys to the specified [value]. + */ + public fun containsValue(value: @UnsafeVariance V): Boolean + + /** + * Returns the value corresponding to the given [key], or `null` if such a key is not present in the map. + */ + public operator fun get(key: K): V? + + // Views + /** + * Returns a read-only [Set] of all keys in this map. + */ + public val keys: Set + + /** + * Returns a read-only [Collection] of all values in this map. Note that this collection may contain duplicate values. + */ + public val values: Collection + + /** + * Returns a read-only [Set] of all key/value pairs in this map. + */ + public val entries: Set> + + /** + * Represents a key/value pair held by a [Map]. + */ + public interface Entry { + /** + * Returns the key of this key/value pair. + */ + public val key: K + + /** + * Returns the value of this key/value pair. + */ + public val value: V + } +} + +/** + * A modifiable collection that holds pairs of objects (keys and values) and supports efficiently retrieving + * the value corresponding to each key. Map keys are unique; the map holds only one value for each key. + * @param K the type of map keys. The map is invariant in its key type. + * @param V the type of map values. The mutable map is invariant in its value type. + */ +public interface MutableMap : Map { + // Modification Operations + /** + * Associates the specified [value] with the specified [key] in the map. + * + * @return the previous value associated with the key, or `null` if the key was not present in the map. + */ + public fun put(key: K, value: V): V? + + /** + * Removes the specified key and its corresponding value from this map. + * + * @return the previous value associated with the key, or `null` if the key was not present in the map. + */ + public fun remove(key: K): V? + + // Bulk Modification Operations + /** + * Updates this map with key/value pairs from the specified map [from]. + */ + public fun putAll(from: Map): Unit + + /** + * Removes all elements from this map. + */ + public fun clear(): Unit + + // Views + /** + * Returns a [MutableSet] of all keys in this map. + */ + override val keys: MutableSet + + /** + * Returns a [MutableCollection] of all values in this map. Note that this collection may contain duplicate values. + */ + override val values: MutableCollection + + /** + * Returns a [MutableSet] of all key/value pairs in this map. + */ + override val entries: MutableSet> + + /** + * Represents a key/value pair held by a [MutableMap]. + */ + public interface MutableEntry : Map.Entry { + /** + * Changes the value associated with the key of this entry. + * + * @return the previous value corresponding to the key. + */ + public fun setValue(newValue: V): V + } +} diff --git a/kotlin-native/runtime/src/main/kotlin/kotlin/collections/Maps.kt b/kotlin-native/runtime/src/main/kotlin/kotlin/collections/Maps.kt new file mode 100644 index 00000000000..c4255e69724 --- /dev/null +++ b/kotlin-native/runtime/src/main/kotlin/kotlin/collections/Maps.kt @@ -0,0 +1,38 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +package kotlin.collections + +@PublishedApi +@SinceKotlin("1.3") +@ExperimentalStdlibApi +@kotlin.internal.InlineOnly +internal actual inline fun buildMapInternal(builderAction: MutableMap.() -> Unit): Map { + return HashMap().apply(builderAction).build() +} + +@PublishedApi +@SinceKotlin("1.3") +@ExperimentalStdlibApi +@kotlin.internal.InlineOnly +internal actual inline fun buildMapInternal(capacity: Int, builderAction: MutableMap.() -> Unit): Map { + return HashMap(capacity).apply(builderAction).build() +} + + +// creates a singleton copy of map, if there is specialization available in target platform, otherwise returns itself +@Suppress("NOTHING_TO_INLINE") +internal inline actual fun Map.toSingletonMapOrSelf(): Map = toSingletonMap() + +// creates a singleton copy of map +internal actual fun Map.toSingletonMap(): Map + = with(entries.iterator().next()) { mutableMapOf(key to value) } + + +/** + * Native map and set implementations do not make use of capacities or load factors. + */ +@PublishedApi +internal actual fun mapCapacity(expectedSize: Int) = expectedSize diff --git a/kotlin-native/runtime/src/main/kotlin/kotlin/collections/MutableCollections.kt b/kotlin-native/runtime/src/main/kotlin/kotlin/collections/MutableCollections.kt new file mode 100644 index 00000000000..fd2d44393a5 --- /dev/null +++ b/kotlin-native/runtime/src/main/kotlin/kotlin/collections/MutableCollections.kt @@ -0,0 +1,29 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +package kotlin.collections + +/** + * Sorts elements in the list in-place according to their natural sort order. + * + * The sort is _stable_. It means that equal elements preserve their order relative to each other after sorting. + */ +public actual fun > MutableList.sort(): Unit = sortWith(naturalOrder()) + +/** + * Sorts elements in the list in-place according to the order specified with [comparator]. + * + * The sort is _stable_. It means that equal elements preserve their order relative to each other after sorting. + */ +public actual fun MutableList.sortWith(comparator: Comparator): Unit { + if (size > 1) { + val it = listIterator() + val sortedArray = @Suppress("UNCHECKED_CAST") (toTypedArray() as Array).apply { sortWith(comparator) } + for (v in sortedArray) { + it.next() + it.set(v) + } + } +} diff --git a/kotlin-native/runtime/src/main/kotlin/kotlin/collections/RandomAccess.kt b/kotlin-native/runtime/src/main/kotlin/kotlin/collections/RandomAccess.kt new file mode 100644 index 00000000000..f2af9906f1a --- /dev/null +++ b/kotlin-native/runtime/src/main/kotlin/kotlin/collections/RandomAccess.kt @@ -0,0 +1,11 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +package kotlin.collections + +/** + * Marker interface indicating that the [List] implementation supports fast indexed access. + */ +public actual interface RandomAccess diff --git a/kotlin-native/runtime/src/main/kotlin/kotlin/collections/Set.kt b/kotlin-native/runtime/src/main/kotlin/kotlin/collections/Set.kt new file mode 100644 index 00000000000..a7e1c76ad00 --- /dev/null +++ b/kotlin-native/runtime/src/main/kotlin/kotlin/collections/Set.kt @@ -0,0 +1,52 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +package kotlin.collections + +/** + * A generic unordered collection of elements that does not support duplicate elements. + * Methods in this interface support only read-only access to the set; + * read/write access is supported through the [MutableSet] interface. + * @param E the type of elements contained in the set. The set is covariant in its element type. + */ +public interface Set : Collection { + // Query Operations + override val size: Int + + override fun isEmpty(): Boolean + override fun contains(element: @UnsafeVariance E): Boolean + override fun iterator(): Iterator + + // Bulk Operations + override fun containsAll(elements: Collection<@UnsafeVariance E>): Boolean +} + +/** + * A generic unordered collection of elements that does not support duplicate elements, and supports + * adding and removing elements. + * @param E the type of elements contained in the set. The mutable set is invariant in its element type. + */ +public interface MutableSet : Set, MutableCollection { + // Query Operations + override fun iterator(): MutableIterator + + // Modification Operations + + /** + * Adds the specified element to the set. + * + * @return `true` if the element has been added, `false` if the element is already contained in the set. + */ + override fun add(element: E): Boolean + + override fun remove(element: E): Boolean + + // Bulk Modification Operations + override fun addAll(elements: Collection): Boolean + + override fun removeAll(elements: Collection): Boolean + override fun retainAll(elements: Collection): Boolean + override fun clear(): Unit +} diff --git a/kotlin-native/runtime/src/main/kotlin/kotlin/collections/Sets.kt b/kotlin-native/runtime/src/main/kotlin/kotlin/collections/Sets.kt new file mode 100644 index 00000000000..0757b4574f0 --- /dev/null +++ b/kotlin-native/runtime/src/main/kotlin/kotlin/collections/Sets.kt @@ -0,0 +1,28 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +package kotlin.collections + +// TODO: Add SingletonSet class +/** + * Returns an immutable set containing only the specified object [element]. + */ +public fun setOf(element: T): Set = hashSetOf(element) + +@PublishedApi +@SinceKotlin("1.3") +@ExperimentalStdlibApi +@kotlin.internal.InlineOnly +internal actual inline fun buildSetInternal(builderAction: MutableSet.() -> Unit): Set { + return HashSet().apply(builderAction).build() +} + +@PublishedApi +@SinceKotlin("1.3") +@ExperimentalStdlibApi +@kotlin.internal.InlineOnly +internal actual inline fun buildSetInternal(capacity: Int, builderAction: MutableSet.() -> Unit): Set { + return HashSet(capacity).apply(builderAction).build() +} diff --git a/kotlin-native/runtime/src/main/kotlin/kotlin/coroutines/ContinuationImpl.kt b/kotlin-native/runtime/src/main/kotlin/kotlin/coroutines/ContinuationImpl.kt new file mode 100644 index 00000000000..6bb090a2005 --- /dev/null +++ b/kotlin-native/runtime/src/main/kotlin/kotlin/coroutines/ContinuationImpl.kt @@ -0,0 +1,123 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +package kotlin.coroutines.native.internal + +import kotlin.coroutines.* +import kotlin.coroutines.intrinsics.CoroutineSingletons +import kotlin.coroutines.intrinsics.* + +@SinceKotlin("1.3") +internal abstract class BaseContinuationImpl( + // This is `public val` so that it is private on JVM and cannot be modified by untrusted code, yet + // it has a public getter (since even untrusted code is allowed to inspect its call stack). + public val completion: Continuation? +) : Continuation, Serializable { + // This implementation is final. This fact is used to unroll resumeWith recursion. + public final override fun resumeWith(result: Result) { + // Invoke "resume" debug probe only once, even if previous frames are "resumed" in the loop below, too + probeCoroutineResumed(this) + // This loop unrolls recursion in current.resumeWith(param) to make saner and shorter stack traces on resume + var current = this + var param = result + while (true) { + with(current) { + val completion = completion!! // fail fast when trying to resume continuation without completion + val outcome: Result = + try { + val outcome = invokeSuspend(param) + if (outcome === COROUTINE_SUSPENDED) return + Result.success(outcome) + } catch (exception: Throwable) { + Result.failure(exception) + } + releaseIntercepted() // this state machine instance is terminating + if (completion is BaseContinuationImpl) { + // unrolling recursion via loop + current = completion + param = outcome + } else { + // top-level completion reached -- invoke and return + completion.resumeWith(outcome) + return + } + } + } + } + + protected abstract fun invokeSuspend(result: Result): Any? + + protected open fun releaseIntercepted() { + // does nothing here, overridden in ContinuationImpl + } + + public open fun create(completion: Continuation<*>): Continuation { + throw UnsupportedOperationException("create(Continuation) has not been overridden") + } + + public open fun create(value: Any?, completion: Continuation<*>): Continuation { + throw UnsupportedOperationException("create(Any?;Continuation) has not been overridden") + } + + public override fun toString(): String { + // todo: how continuation shall be rendered? + return "Continuation @ ${this::class.simpleName}" + } +} + +@SinceKotlin("1.3") +// State machines for named restricted suspend functions extend from this class +internal abstract class RestrictedContinuationImpl( + completion: Continuation? +) : BaseContinuationImpl(completion) { + init { + completion?.let { + require(it.context === EmptyCoroutineContext) { + "Coroutines with restricted suspension must have EmptyCoroutineContext" + } + } + } + + public override val context: CoroutineContext + get() = EmptyCoroutineContext +} + +@SinceKotlin("1.3") +// State machines for named suspend functions extend from this class +internal abstract class ContinuationImpl( + completion: Continuation?, + private val _context: CoroutineContext? +) : BaseContinuationImpl(completion) { + constructor(completion: Continuation?) : this(completion, completion?.context) + + public override val context: CoroutineContext + get() = _context!! + + private var intercepted: Continuation? = null + + public fun intercepted(): Continuation = + intercepted + ?: (context[ContinuationInterceptor]?.interceptContinuation(this) ?: this) + .also { intercepted = it } + + protected override fun releaseIntercepted() { + val intercepted = intercepted + if (intercepted != null && intercepted !== this) { + context[ContinuationInterceptor]!!.releaseInterceptedContinuation(intercepted) + } + this.intercepted = CompletedContinuation // just in case + } +} + +internal object CompletedContinuation : Continuation { + override val context: CoroutineContext + get() = error("This continuation is already complete") + + override fun resumeWith(result: Result) { + error("This continuation is already complete") + } + + override fun toString(): String = "This continuation is already complete" +} diff --git a/kotlin-native/runtime/src/main/kotlin/kotlin/coroutines/DebugProbes.kt b/kotlin-native/runtime/src/main/kotlin/kotlin/coroutines/DebugProbes.kt new file mode 100644 index 00000000000..35e5be28297 --- /dev/null +++ b/kotlin-native/runtime/src/main/kotlin/kotlin/coroutines/DebugProbes.kt @@ -0,0 +1,76 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +package kotlin.coroutines.native.internal + +// TODO: support coroutines debugging in Kotlin/Native. + +import kotlin.coroutines.Continuation +import kotlin.coroutines.intrinsics.* + +/** + * This probe is invoked when coroutine is being created and it can replace completion + * with its own wrapped object to intercept completion of this coroutine. + * + * This probe is invoked from stdlib implementation of [createCoroutineUnintercepted] function. + * + * Once created, coroutine is repeatedly [resumed][probeCoroutineResumed] and [suspended][probeCoroutineSuspended], + * until it is complete. On completion, the object that was returned by this probe is invoked. + * + * ``` + * +-------+ probeCoroutineCreated +-----------+ + * | START | ---------------------->| SUSPENDED | + * +-------+ +-----------+ + * probeCoroutineResumed | ^ probeCoroutineSuspended + * V | + * +------------+ completion invoked +-----------+ + * | RUNNING | ------------------->| COMPLETED | + * +------------+ +-----------+ + * ``` + * + * While the coroutine is resumed and suspended, it is represented by the pointer to its `frame` + * which always extends [BaseContinuationImpl] and represents a pointer to the topmost frame of the + * coroutine. Each [BaseContinuationImpl] object has [completion][BaseContinuationImpl.completion] reference + * that points either to another frame (extending [BaseContinuationImpl]) or to the completion object + * that was returned by this `probeCoroutineCreated` function. + * + * When coroutine is [suspended][probeCoroutineSuspended], then it is later [resumed][probeCoroutineResumed] + * with a reference to the same frame. However, while coroutine is running it can unwind its frames and + * invoke other suspending functions, so its next suspension can happen with a different frame pointer. + */ +@SinceKotlin("1.3") +internal fun probeCoroutineCreated(completion: Continuation): Continuation { + return completion +} + +/** + * This probe is invoked when coroutine is resumed using [Continuation.resumeWith]. + * + * This probe is invoked from stdlib implementation of [BaseContinuationImpl.resumeWith] function. + * + * Coroutines machinery implementation guarantees that the actual [frame] instance extends + * [BaseContinuationImpl] class, despite the fact that the declared type of [frame] + * parameter in this function is `Continuation<*>`. See [probeCoroutineCreated] for details. + */ +@Suppress("UNUSED_PARAMETER") +@SinceKotlin("1.3") +internal fun probeCoroutineResumed(frame: Continuation<*>) { +} + +/** + * This probe is invoked when coroutine is suspended using [suspendCoroutineUninterceptedOrReturn], that is + * when the corresponding `block` returns [COROUTINE_SUSPENDED]. + * + * This probe is invoked from compiler-generated intrinsic for [suspendCoroutineUninterceptedOrReturn] function. + * + * Coroutines machinery implementation guarantees that the actual [frame] instance extends + * [BaseContinuationImpl] class, despite the fact that the declared type of [frame] + * parameter in this function is `Continuation<*>`. See [probeCoroutineCreated] for details. + */ +@Suppress("UNUSED_PARAMETER") +@SinceKotlin("1.3") +internal fun probeCoroutineSuspended(frame: Continuation<*>) { +} + diff --git a/kotlin-native/runtime/src/main/kotlin/kotlin/coroutines/SafeContinuationNative.kt b/kotlin-native/runtime/src/main/kotlin/kotlin/coroutines/SafeContinuationNative.kt new file mode 100644 index 00000000000..babe1ec2a94 --- /dev/null +++ b/kotlin-native/runtime/src/main/kotlin/kotlin/coroutines/SafeContinuationNative.kt @@ -0,0 +1,52 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +package kotlin.coroutines + +import kotlin.* +import kotlin.coroutines.intrinsics.CoroutineSingletons.* +import kotlin.coroutines.intrinsics.* + +@PublishedApi +@SinceKotlin("1.3") +internal actual class SafeContinuation +internal actual constructor( + private val delegate: Continuation, + initialResult: Any? +) : Continuation { + @PublishedApi + internal actual constructor(delegate: Continuation) : this(delegate, UNDECIDED) + + public actual override val context: CoroutineContext + get() = delegate.context + + private var result: Any? = initialResult + + public actual override fun resumeWith(result: Result) { + val cur = this.result + when { + cur === UNDECIDED -> this.result = result.value + cur === COROUTINE_SUSPENDED -> { + this.result = RESUMED + delegate.resumeWith(result) + } + else -> throw IllegalStateException("Already resumed") + } + } + + @PublishedApi + internal actual fun getOrThrow(): Any? { + val result = this.result + if (result === UNDECIDED) { + this.result = COROUTINE_SUSPENDED + return COROUTINE_SUSPENDED + } + return when { + result === RESUMED -> COROUTINE_SUSPENDED // already called continuation, indicate COROUTINE_SUSPENDED upstream + result is Result.Failure -> throw result.exception + else -> result // either COROUTINE_SUSPENDED or data + } + } +} \ No newline at end of file diff --git a/kotlin-native/runtime/src/main/kotlin/kotlin/coroutines/SuspendFunction.kt b/kotlin-native/runtime/src/main/kotlin/kotlin/coroutines/SuspendFunction.kt new file mode 100644 index 00000000000..eab05e728c7 --- /dev/null +++ b/kotlin-native/runtime/src/main/kotlin/kotlin/coroutines/SuspendFunction.kt @@ -0,0 +1,16 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +package kotlin.coroutines + +import kotlin.native.internal.FixmeReflection + +/** + * Represents a value of a functional type, such as a lambda, an anonymous function or a function reference. + * + * @param R return type of the function. + */ +@FixmeReflection +public interface SuspendFunction diff --git a/kotlin-native/runtime/src/main/kotlin/kotlin/coroutines/cancellation/CancellationException.kt b/kotlin-native/runtime/src/main/kotlin/kotlin/coroutines/cancellation/CancellationException.kt new file mode 100644 index 00000000000..445742edda1 --- /dev/null +++ b/kotlin-native/runtime/src/main/kotlin/kotlin/coroutines/cancellation/CancellationException.kt @@ -0,0 +1,15 @@ +/* + * Copyright 2010-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +package kotlin.coroutines.cancellation + +@ExperimentalStdlibApi +@SinceKotlin("1.4") +public actual open class CancellationException : IllegalStateException { + actual constructor() : super() + actual constructor(message: String?) : super(message) + constructor(message: String?, cause: Throwable?) : super(message, cause) + constructor(cause: Throwable?) : super(cause) +} diff --git a/kotlin-native/runtime/src/main/kotlin/kotlin/coroutines/intrinsics/IntrinsicsNative.kt b/kotlin-native/runtime/src/main/kotlin/kotlin/coroutines/intrinsics/IntrinsicsNative.kt new file mode 100644 index 00000000000..854a5e192e0 --- /dev/null +++ b/kotlin-native/runtime/src/main/kotlin/kotlin/coroutines/intrinsics/IntrinsicsNative.kt @@ -0,0 +1,235 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +package kotlin.coroutines.intrinsics + +import kotlin.coroutines.* +import kotlin.coroutines.native.internal.* +import kotlin.native.internal.* + +/** + * Starts an unintercepted coroutine without a receiver and with result type [T] and executes it until its first suspension. + * Returns the result of the coroutine or throws its exception if it does not suspend or [COROUTINE_SUSPENDED] if it suspends. + * In the latter case, the [completion] continuation is invoked when the coroutine completes with a result or an exception. + * + * The coroutine is started directly in the invoker's thread without going through the [ContinuationInterceptor] that might + * be present in the completion's [CoroutineContext]. It is the invoker's responsibility to ensure that a proper invocation + * context is established. + * + * This function is designed to be used from inside of [suspendCoroutineUninterceptedOrReturn] to resume the execution of the suspended + * coroutine using a reference to the suspending function. + */ +@Suppress("UNCHECKED_CAST") +@kotlin.internal.InlineOnly +public actual inline fun (suspend () -> T).startCoroutineUninterceptedOrReturn( + completion: Continuation +): Any? = (this as Function1, Any?>).invoke(completion) + +/** + * Starts an unintercepted coroutine with receiver type [R] and result type [T] and executes it until its first suspension. + * Returns the result of the coroutine or throws its exception if it does not suspend or [COROUTINE_SUSPENDED] if it suspends. + * In the latter case, the [completion] continuation is invoked when the coroutine completes with a result or an exception. + * + * The coroutine is started directly in the invoker's thread without going through the [ContinuationInterceptor] that might + * be present in the completion's [CoroutineContext]. It is the invoker's responsibility to ensure that a proper invocation + * context is established. + * + * This function is designed to be used from inside of [suspendCoroutineUninterceptedOrReturn] to resume the execution of the suspended + * coroutine using a reference to the suspending function. + */ +@Suppress("UNCHECKED_CAST") +@kotlin.internal.InlineOnly +public actual inline fun (suspend R.() -> T).startCoroutineUninterceptedOrReturn( + receiver: R, + completion: Continuation +): Any? = (this as Function2, Any?>).invoke(receiver, completion) + +@Suppress("UNCHECKED_CAST") +@kotlin.internal.InlineOnly +internal actual inline fun (suspend R.(P) -> T).startCoroutineUninterceptedOrReturn( + receiver: R, + param: P, + completion: Continuation +): Any? = (this as Function3, Any?>).invoke(receiver, param, completion) + +private object CoroutineSuspendedMarker + + +/** + * Creates unintercepted coroutine without receiver and with result type [T]. + * This function creates a new, fresh instance of suspendable computation every time it is invoked. + * + * To start executing the created coroutine, invoke `resume(Unit)` on the returned [Continuation] instance. + * The [completion] continuation is invoked when coroutine completes with result or exception. + * + * This function returns unintercepted continuation. + * Invocation of `resume(Unit)` starts coroutine immediately in the invoker's call stack without going through the + * [ContinuationInterceptor] that might be present in the completion's [CoroutineContext]. + * It is the invoker's responsibility to ensure that a proper invocation context is established. + * Note that [completion] of this function may get invoked in an arbitrary context. + * + * [Continuation.intercepted] can be used to acquire the intercepted continuation. + * Invocation of `resume(Unit)` on intercepted continuation guarantees that execution of + * both the coroutine and [completion] happens in the invocation context established by + * [ContinuationInterceptor]. + * + * Repeated invocation of any resume function on the resulting continuation corrupts the + * state machine of the coroutine and may result in arbitrary behaviour or exception. + */ +@SinceKotlin("1.3") +@Suppress("UNCHECKED_CAST") +public actual fun (suspend () -> T).createCoroutineUnintercepted( + completion: Continuation +): Continuation { + val probeCompletion = probeCoroutineCreated(completion) + return if (this is BaseContinuationImpl) + create(probeCompletion) + else + createCoroutineFromSuspendFunction(probeCompletion) { + (this as Function1, Any?>).invoke(it) + } +} + +/** + * Creates unintercepted coroutine with receiver type [R] and result type [T]. + * This function creates a new, fresh instance of suspendable computation every time it is invoked. + * + * To start executing the created coroutine, invoke `resume(Unit)` on the returned [Continuation] instance. + * The [completion] continuation is invoked when coroutine completes with result or exception. + * + * This function returns unintercepted continuation. + * Invocation of `resume(Unit)` starts coroutine immediately in the invoker's call stack without going through the + * [ContinuationInterceptor] that might be present in the completion's [CoroutineContext]. + * It is the invoker's responsibility to ensure that a proper invocation context is established. + * Note that [completion] of this function may get invoked in an arbitrary context. + * + * [Continuation.intercepted] can be used to acquire the intercepted continuation. + * Invocation of `resume(Unit)` on intercepted continuation guarantees that execution of + * both the coroutine and [completion] happens in the invocation context established by + * [ContinuationInterceptor]. + * + * Repeated invocation of any resume function on the resulting continuation corrupts the + * state machine of the coroutine and may result in arbitrary behaviour or exception. + */ +@SinceKotlin("1.3") +@Suppress("UNCHECKED_CAST") +public actual fun (suspend R.() -> T).createCoroutineUnintercepted( + receiver: R, + completion: Continuation +): Continuation { + val probeCompletion = probeCoroutineCreated(completion) + return if (this is BaseContinuationImpl) + create(receiver, probeCompletion) + else { + createCoroutineFromSuspendFunction(probeCompletion) { + (this as Function2, Any?>).invoke(receiver, it) + } + } +} + +/** + * Intercepts this continuation with [ContinuationInterceptor]. + * + * This function shall be used on the immediate result of [createCoroutineUnintercepted] or [suspendCoroutineUninterceptedOrReturn], + * in which case it checks for [ContinuationInterceptor] in the continuation's [context][Continuation.context], + * invokes [ContinuationInterceptor.interceptContinuation], caches and returns the result. + * + * If this function is invoked on other [Continuation] instances it returns `this` continuation unchanged. + */ +@SinceKotlin("1.3") +public actual fun Continuation.intercepted(): Continuation = + (this as? ContinuationImpl)?.intercepted() ?: this + +// INTERNAL DEFINITIONS + +/** + * This function is used when [createCoroutineUnintercepted] encounters suspending lambda that does not extend BaseContinuationImpl. + * + * It happens in two cases: + * 1. Callable reference to suspending function, + * 2. Suspending function reference implemented by Java code. + * + * We must wrap it into an instance that extends [BaseContinuationImpl], because that is an expectation of all coroutines machinery. + * As an optimization we use lighter-weight [RestrictedContinuationImpl] base class (it has less fields) if the context is + * [EmptyCoroutineContext], and a full-blown [ContinuationImpl] class otherwise. + * + * The instance of [BaseContinuationImpl] is passed to the [block] so that it can be passed to the corresponding invocation. + */ +@SinceKotlin("1.3") +@Suppress("UNCHECKED_CAST") +private inline fun createCoroutineFromSuspendFunction( + completion: Continuation, + crossinline block: (Continuation) -> Any? +): Continuation { + val context = completion.context + // label == 0 when coroutine is not started yet (initially) or label == 1 when it was + return if (context === EmptyCoroutineContext) + object : RestrictedContinuationImpl(completion as Continuation) { + private var label = 0 + + override fun invokeSuspend(result: Result): Any? = + when (label) { + 0 -> { + label = 1 + result.getOrThrow() // Rethrow exception if trying to start with exception (will be caught by BaseContinuationImpl.resumeWith + block(this) // run the block, may return or suspend + } + 1 -> { + label = 2 + result.getOrThrow() // this is the result if the block had suspended + } + else -> error("This coroutine had already completed") + } + } + else + object : ContinuationImpl(completion as Continuation, context) { + private var label = 0 + + override fun invokeSuspend(result: Result): Any? = + when (label) { + 0 -> { + label = 1 + result.getOrThrow() // Rethrow exception if trying to start with exception (will be caught by BaseContinuationImpl.resumeWith + block(this) // run the block, may return or suspend + } + 1 -> { + label = 2 + result.getOrThrow() // this is the result if the block had suspended + } + else -> error("This coroutine had already completed") + } + } +} + +/** + * This function creates continuation suitable for passing as implicit argument to suspend functions. + * The continuation calls [callback] and then delegates to [completion]. + * + * The result is [ContinuationImpl] because that is an expectation of all coroutines machinery. + * + * It can be thought as a state machine of + * ``` + * suspend fun foo() { + * val result = runCatching { } + * callback(result) + * } + * ``` + */ +@Suppress("UNCHECKED_CAST") +internal inline fun createContinuationArgumentFromCallback( + completion: Continuation, + crossinline callback: (Result) -> Unit +): Continuation = object : ContinuationImpl(completion as Continuation) { + private var invoked = false + + override fun invokeSuspend(result: Result): Any? { + if (invoked) error("This coroutine had already completed") + invoked = true + + callback(result) + + return Unit // Not suspended. + } +} \ No newline at end of file diff --git a/kotlin-native/runtime/src/main/kotlin/kotlin/internal/Annotations.kt b/kotlin-native/runtime/src/main/kotlin/kotlin/internal/Annotations.kt new file mode 100644 index 00000000000..2b777433cc8 --- /dev/null +++ b/kotlin-native/runtime/src/main/kotlin/kotlin/internal/Annotations.kt @@ -0,0 +1,14 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +package kotlin.internal + +/** + * Specifies that the corresponding type parameter is not used for unsafe operations such as casts or 'is' checks + * That means it's completely safe to use generic types as argument for such parameter. + */ +@Target(AnnotationTarget.TYPE_PARAMETER) +@Retention(AnnotationRetention.BINARY) +internal annotation class PureReifiable diff --git a/kotlin-native/runtime/src/main/kotlin/kotlin/internal/ProgressionUtil.kt b/kotlin-native/runtime/src/main/kotlin/kotlin/internal/ProgressionUtil.kt new file mode 100644 index 00000000000..04b54c62168 --- /dev/null +++ b/kotlin-native/runtime/src/main/kotlin/kotlin/internal/ProgressionUtil.kt @@ -0,0 +1,72 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +package kotlin.internal + +// a mod b (in arithmetical sense) +private fun mod(a: Int, b: Int): Int { + val mod = a % b + return if (mod >= 0) mod else mod + b +} + +private fun mod(a: Long, b: Long): Long { + val mod = a % b + return if (mod >= 0) mod else mod + b +} + +// (a - b) mod c +private fun differenceModulo(a: Int, b: Int, c: Int): Int { + return mod(mod(a, c) - mod(b, c), c) +} + +private fun differenceModulo(a: Long, b: Long, c: Long): Long { + return mod(mod(a, c) - mod(b, c), c) +} + +/** + * Calculates the final element of a bounded arithmetic progression, i.e. the last element of the progression which is in the range + * from [start] to [end] in case of a positive [step], or from [end] to [start] in case of a negative + * [step]. + * + * No validation on passed parameters is performed. The given parameters should satisfy the condition: + * + * - either `step > 0` and `start <= end`, + * - or `step < 0` and `start >= end`. + * + * @param start first element of the progression + * @param end ending bound for the progression + * @param step increment, or difference of successive elements in the progression + * @return the final element of the progression + * @suppress + */ +@PublishedApi +internal fun getProgressionLastElement(start: Int, end: Int, step: Int): Int = when { + step > 0 -> if (start >= end) end else end - differenceModulo(end, start, step) + step < 0 -> if (start <= end) end else end + differenceModulo(start, end, -step) + else -> throw kotlin.IllegalArgumentException("Step is zero.") +} + +/** + * Calculates the final element of a bounded arithmetic progression, i.e. the last element of the progression which is in the range + * from [start] to [end] in case of a positive [step], or from [end] to [start] in case of a negative + * [step]. + * + * No validation on passed parameters is performed. The given parameters should satisfy the condition: + * + * - either `step > 0` and `start <= end`, + * - or `step < 0` and `start >= end`. + * + * @param start first element of the progression + * @param end ending bound for the progression + * @param step increment, or difference of successive elements in the progression + * @return the final element of the progression + * @suppress + */ +@PublishedApi +internal fun getProgressionLastElement(start: Long, end: Long, step: Long): Long = when { + step > 0 -> if (start >= end) end else end - differenceModulo(end, start, step) + step < 0 -> if (start <= end) end else end + differenceModulo(start, end, -step) + else -> throw kotlin.IllegalArgumentException("Step is zero.") +} diff --git a/kotlin-native/runtime/src/main/kotlin/kotlin/io/Console.kt b/kotlin-native/runtime/src/main/kotlin/kotlin/io/Console.kt new file mode 100644 index 00000000000..a0b3bc11e1f --- /dev/null +++ b/kotlin-native/runtime/src/main/kotlin/kotlin/io/Console.kt @@ -0,0 +1,36 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +package kotlin.io + +/** Prints the given [message] to the standard output stream. */ +@SymbolName("Kotlin_io_Console_print") +external public fun print(message: String) + +/** Prints the given [message] to the standard output stream. */ +public actual fun print(message: Any?) { + print(message.toString()) +} + +/** Prints the given [message] and the line separator to the standard output stream. */ +@SymbolName("Kotlin_io_Console_println") +external public fun println(message: String) + +/** Prints the given [message] and the line separator to the standard output stream. */ +public actual fun println(message: Any?) { + println(message.toString()) +} + +/** Prints the line separator to the standard output stream. */ +@SymbolName("Kotlin_io_Console_println0") +external public actual fun println() + +/** + * Reads a line of input from the standard input stream. + * + * @return the line read or `null` if the input stream is redirected to a file and the end of file has been reached. + */ +@SymbolName("Kotlin_io_Console_readLine") +external public fun readLine(): String? diff --git a/kotlin-native/runtime/src/main/kotlin/kotlin/io/Serializable.kt b/kotlin-native/runtime/src/main/kotlin/kotlin/io/Serializable.kt new file mode 100644 index 00000000000..6efbb7a1d61 --- /dev/null +++ b/kotlin-native/runtime/src/main/kotlin/kotlin/io/Serializable.kt @@ -0,0 +1,9 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +package kotlin.io + +// TODO: This interface is a temporary solution for common collections and not used in Native. +internal actual interface Serializable \ No newline at end of file diff --git a/kotlin-native/runtime/src/main/kotlin/kotlin/math/math.kt b/kotlin-native/runtime/src/main/kotlin/kotlin/math/math.kt new file mode 100644 index 00000000000..b288cc64725 --- /dev/null +++ b/kotlin-native/runtime/src/main/kotlin/kotlin/math/math.kt @@ -0,0 +1,1199 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +package kotlin.math + +// region ================ Double Math ======================================== + +/** Computes the sine of the angle [x] given in radians. + * + * Special cases: + * - `sin(NaN|+Inf|-Inf)` is `NaN` + */ +@SinceKotlin("1.2") +@SymbolName("Kotlin_math_sin") +external public actual fun sin(x: Double): Double + +/** Computes the cosine of the angle [x] given in radians. + * + * Special cases: + * - `cos(NaN|+Inf|-Inf)` is `NaN` + */ +@SinceKotlin("1.2") +@SymbolName("Kotlin_math_cos") +external public actual fun cos(x: Double): Double + +/** Computes the tangent of the angle [x] given in radians. + * + * Special cases: + * - `tan(NaN|+Inf|-Inf)` is `NaN` + */ +@SinceKotlin("1.2") +@SymbolName("Kotlin_math_tan") +external public actual fun tan(x: Double): Double + +/** + * Computes the arc sine of the value [x]; + * the returned value is an angle in the range from `-PI/2` to `PI/2` radians. + * + * Special cases: + * - `asin(x)` is `NaN`, when `abs(x) > 1` or x is `NaN` + */ +@SinceKotlin("1.2") +@SymbolName("Kotlin_math_asin") +external public actual fun asin(x: Double): Double + +/** + * Computes the arc cosine of the value [x]; + * the returned value is an angle in the range from `0.0` to `PI` radians. + * + * Special cases: + * - `acos(x)` is `NaN`, when `abs(x) > 1` or x is `NaN` + */ +@SinceKotlin("1.2") +@SymbolName("Kotlin_math_acos") +external public actual fun acos(x: Double): Double + +/** + * Computes the arc tangent of the value [x]; + * the returned value is an angle in the range from `-PI/2` to `PI/2` radians. + * + * Special cases: + * - `atan(NaN)` is `NaN` + */ +@SinceKotlin("1.2") +@SymbolName("Kotlin_math_atan") +external public actual fun atan(x: Double): Double + +/** + * Returns the angle `theta` of the polar coordinates `(r, theta)` that correspond + * to the rectangular coordinates `(x, y)` by computing the arc tangent of the value [y] / [x]; + * the returned value is an angle in the range from `-PI` to `PI` radians. + * + * Special cases: + * - `atan2(0.0, 0.0)` is `0.0` + * - `atan2(0.0, x)` is `0.0` for `x > 0` and `PI` for `x < 0` + * - `atan2(-0.0, x)` is `-0.0` for 'x > 0` and `-PI` for `x < 0` + * - `atan2(y, +Inf)` is `0.0` for `0 < y < +Inf` and `-0.0` for '-Inf < y < 0` + * - `atan2(y, -Inf)` is `PI` for `0 < y < +Inf` and `-PI` for `-Inf < y < 0` + * - `atan2(y, 0.0)` is `PI/2` for `y > 0` and `-PI/2` for `y < 0` + * - `atan2(+Inf, x)` is `PI/2` for finite `x`y + * - `atan2(-Inf, x)` is `-PI/2` for finite `x` + * - `atan2(NaN, x)` and `atan2(y, NaN)` is `NaN` + */ +@SinceKotlin("1.2") +@SymbolName("Kotlin_math_atan2") +external public actual fun atan2(y: Double, x: Double): Double + +/** + * Computes the hyperbolic sine of the value [x]. + * + * Special cases: + * - `sinh(NaN)` is `NaN` + * - `sinh(+Inf)` is `+Inf` + * - `sinh(-Inf)` is `-Inf` + */ +@SinceKotlin("1.2") +@SymbolName("Kotlin_math_sinh") +external public actual fun sinh(x: Double): Double + +/** + * Computes the hyperbolic cosine of the value [x]. + * + * Special cases: + * - `cosh(NaN)` is `NaN` + * - `cosh(+Inf|-Inf)` is `+Inf` + */ +@SinceKotlin("1.2") +@SymbolName("Kotlin_math_cosh") +external public actual fun cosh(x: Double): Double + +/** + * Computes the hyperbolic tangent of the value [x]. + * + * Special cases: + * - `tanh(NaN)` is `NaN` + * - `tanh(+Inf)` is `1.0` + * - `tanh(-Inf)` is `-1.0` + */ +@SinceKotlin("1.2") +@SymbolName("Kotlin_math_tanh") +external public actual fun tanh(x: Double): Double + +/** + * Computes the inverse hyperbolic sine of the value [x]. + * + * The returned value is `y` such that `sinh(y) == x`. + * + * Special cases: + * - `asinh(NaN)` is `NaN` + * - `asinh(+Inf)` is `+Inf` + * - `asinh(-Inf)` is `-Inf` + */ +@SinceKotlin("1.2") +@SymbolName("Kotlin_math_asinh") +external public actual fun asinh(x: Double): Double + +/** + * Computes the inverse hyperbolic cosine of the value [x]. + * + * The returned value is positive `y` such that `cosh(y) == x`. + * + * Special cases: + * - `acosh(NaN)` is `NaN` + * - `acosh(x)` is `NaN` when `x < 1` + * - `acosh(+Inf)` is `+Inf` + */ +@SinceKotlin("1.2") +@SymbolName("Kotlin_math_acosh") +external public actual fun acosh(x: Double): Double + +/** + * Computes the inverse hyperbolic tangent of the value [x]. + * + * The returned value is `y` such that `tanh(y) == x`. + * + * Special cases: + * - `tanh(NaN)` is `NaN` + * - `tanh(x)` is `NaN` when `x > 1` or `x < -1` + * - `tanh(1.0)` is `+Inf` + * - `tanh(-1.0)` is `-Inf` + */ +@SinceKotlin("1.2") +@SymbolName("Kotlin_math_atanh") +external public actual fun atanh(x: Double): Double + +/** + * Computes `sqrt(x^2 + y^2)` without intermediate overflow or underflow. + * + * Special cases: + * - returns `+Inf` if any of arguments is infinite + * - returns `NaN` if any of arguments is `NaN` and the other is not infinite + */ +@SinceKotlin("1.2") +@SymbolName("Kotlin_math_hypot") +external public actual fun hypot(x: Double, y: Double): Double + +/** + * Computes the positive square root of the value [x]. + * + * Special cases: + * - `sqrt(x)` is `NaN` when `x < 0` or `x` is `NaN` + */ +@SinceKotlin("1.2") +@SymbolName("Kotlin_math_sqrt") +external public actual fun sqrt(x: Double): Double + +/** + * Computes Euler's number `e` raised to the power of the value [x]. + * + * Special cases: + * - `exp(NaN)` is `NaN` + * - `exp(+Inf)` is `+Inf` + * - `exp(-Inf)` is `0.0` + */ +@SinceKotlin("1.2") +@SymbolName("Kotlin_math_exp") +external public actual fun exp(x: Double): Double + +/** + * Computes `exp(x) - 1`. + * + * This function can be implemented to produce more precise result for [x] near zero. + * + * Special cases: + * - `expm1(NaN)` is `NaN` + * - `expm1(+Inf)` is `+Inf` + * - `expm1(-Inf)` is `-1.0` + * + * @see [exp] function. + */ +@SinceKotlin("1.2") +@SymbolName("Kotlin_math_expm1") +external public actual fun expm1(x: Double): Double + +/** + * Computes the logarithm of the value [x] to the given [base]. + * + * Special cases: + * - `log(x, b)` is `NaN` if either `x` or `b` are `NaN` + * - `log(x, b)` is `NaN` when `x < 0` or `b <= 0` or `b == 1.0` + * - `log(+Inf, +Inf)` is `NaN` + * - `log(+Inf, b)` is `+Inf` for `b > 1` and `-Inf` for `b < 1` + * - `log(0.0, b)` is `-Inf` for `b > 1` and `+Inf` for `b > 1` + * + * See also logarithm functions for common fixed bases: [ln], [log10] and [log2]. + */ +@SinceKotlin("1.2") +public actual fun log(x: Double, base: Double): Double { + if (base <= 0.0 || base == 1.0) return Double.NaN + return ln(x) / ln(base) +} + +/** + * Computes the natural logarithm (base `E`) of the value [x]. + * + * Special cases: + * - `ln(NaN)` is `NaN` + * - `ln(x)` is `NaN` when `x < 0.0` + * - `ln(+Inf)` is `+Inf` + * - `ln(0.0)` is `-Inf` + */ +@SinceKotlin("1.2") +@SymbolName("Kotlin_math_ln") +external public actual fun ln(x: Double): Double + +/** + * Computes the common logarithm (base 10) of the value [x]. + * + * @see [ln] actual function for special cases. + */ +@SinceKotlin("1.2") +@SymbolName("Kotlin_math_log10") +external public actual fun log10(x: Double): Double + +/** + * Computes the binary logarithm (base 2) of the value [x]. + * + * @see [ln] actual function for special cases. + */ +@SinceKotlin("1.2") +@SymbolName("Kotlin_math_log2") +external public actual fun log2(x: Double): Double + +/** + * Computes `ln(x + 1)`. + * + * This function can be implemented to produce more precise result for [x] near zero. + * + * Special cases: + * - `ln1p(NaN)` is `NaN` + * - `ln1p(x)` is `NaN` where `x < -1.0` + * - `ln1p(-1.0)` is `-Inf` + * - `ln1p(+Inf)` is `+Inf` + * + * @see [ln] function + * @see [expm1] function + */ +@SinceKotlin("1.2") +@SymbolName("Kotlin_math_ln1p") +external public actual fun ln1p(x: Double): Double + +/** + * Rounds the given value [x] to an integer towards positive infinity. + + * @return the smallest double value that is greater than or equal to the given value [x] and is a mathematical integer. + * + * Special cases: + * - `ceil(x)` is `x` where `x` is `NaN` or `+Inf` or `-Inf` or already a mathematical integer. + */ +@SinceKotlin("1.2") +@SymbolName("Kotlin_math_ceil") +external public actual fun ceil(x: Double): Double + +/** + * Rounds the given value [x] to an integer towards negative infinity. + + * @return the largest double value that is smaller than or equal to the given value [x] and is a mathematical integer. + * + * Special cases: + * - `floor(x)` is `x` where `x` is `NaN` or `+Inf` or `-Inf` or already a mathematical integer. + */ +@SinceKotlin("1.2") +@SymbolName("Kotlin_math_floor") +external public actual fun floor(x: Double): Double + +/** + * Rounds the given value [x] to an integer towards zero. + * + * @return the value [x] having its fractional part truncated. + * + * Special cases: + * - `truncate(x)` is `x` where `x` is `NaN` or `+Inf` or `-Inf` or already a mathematical integer. + */ +@SinceKotlin("1.2") +public actual fun truncate(x: Double): Double = when { + x.isNaN() || x.isInfinite() -> x + x > 0 -> floor(x) + else -> ceil(x) +} + +/** + * Rounds the given value [x] towards the closest integer with ties rounded towards even integer. + * + * Special cases: + * - `round(x)` is `x` where `x` is `NaN` or `+Inf` or `-Inf` or already a mathematical integer. + */ +@SinceKotlin("1.2") +@SymbolName("Kotlin_math_round") +external public actual fun round(x: Double): Double + +/** + * Returns the absolute value of the given value [x]. + * + * Special cases: + * - `abs(NaN)` is `NaN` + * + * @see absoluteValue extension property for [Double] + */ +@SinceKotlin("1.2") +@SymbolName("Kotlin_math_abs") +external public actual fun abs(x: Double): Double + +/** + * Returns the sign of the given value [x]: + * - `-1.0` if the value is negative, + * - zero if the value is zero, + * - `1.0` if the value is positive + * + * Special case: + * - `sign(NaN)` is `NaN` + */ +@SinceKotlin("1.2") +public actual fun sign(x: Double): Double = when { + x.isNaN() -> Double.NaN + x > 0 -> 1.0 + x < 0 -> -1.0 + else -> x +} + +/** + * Returns the smaller of two values. + * + * If either value is `NaN`, then the result is `NaN`. + */ +@SinceKotlin("1.2") +public actual fun min(a: Double, b: Double): Double = when { + a.isNaN() || b.isNaN() -> Double.NaN + a == 0.0 && b == 0.0 -> if (a.signBit()) a else b // -0.0 < +0.0 + else -> if (a < b) a else b +} +/** + * Returns the greater of two values. + * + * If either value is `NaN`, then the result is `NaN`. + */ +@SinceKotlin("1.2") +public actual fun max(a: Double, b: Double): Double = when { + a.isNaN() || b.isNaN() -> Double.NaN + a == 0.0 && b == 0.0 -> if (!a.signBit()) a else b // -0.0 < +0.0 + else -> if (a > b) a else b +} + +// extensions + +/** + * Raises this value to the power [x]. + * + * Special cases: + * - `b.pow(0.0)` is `1.0` + * - `b.pow(1.0) == b` + * - `b.pow(NaN)` is `NaN` + * - `NaN.pow(x)` is `NaN` for `x != 0.0` + * - `b.pow(Inf)` is `NaN` for `abs(b) == 1.0` + * - `b.pow(x)` is `NaN` for `b < 0` and `x` is finite and not an integer + */ +@SinceKotlin("1.2") +@SymbolName("Kotlin_math_Double_pow") +external public actual fun Double.pow(x: Double): Double + +/** + * Raises this value to the integer power [n]. + * + * See the other overload of [pow] for details. + */ +@SinceKotlin("1.2") +public actual fun Double.pow(n: Int): Double = pow(n.toDouble()) + +/** + * Computes the remainder of division of this value by the [divisor] value according to the IEEE 754 standard. + * + * The result is computed as `r = this - (q * divisor)` where `q` is the quotient of division rounded to the nearest integer, + * `q = round(this / other)`. + * + * Special cases: + * - `x.IEEErem(y)` is `NaN`, when `x` is `NaN` or `y` is `NaN` or `x` is `+Inf|-Inf` or `y` is zero. + * - `x.IEEErem(y) == x` when `x` is finite and `y` is infinite. + * + * @see round + */ +@SinceKotlin("1.2") +@SymbolName("Kotlin_math_Double_IEEErem") +external public fun Double.IEEErem(divisor: Double): Double + +/** + * Returns the absolute value of this value. + * + * Special cases: + * - `NaN.absoluteValue` is `NaN` + * + * @see abs actual function + */ +@SinceKotlin("1.2") +public actual val Double.absoluteValue: Double + get() = abs(this) + +/** + * Returns the sign of this value: + * - `-1.0` if the value is negative, + * - zero if the value is zero, + * - `1.0` if the value is positive + * + * Special case: + * - `NaN.sign` is `NaN` + */ +@SinceKotlin("1.2") +public actual val Double.sign: Double + get() = sign(this) + +/** + * Returns this value with the sign bit same as of the [sign] value. + * + * If [sign] is `NaN` the sign of the result is undefined. + */ +@SinceKotlin("1.2") +@SymbolName("Kotlin_math_Double_withSign") +external public actual fun Double.withSign(sign: Double): Double + +/** + * Returns this value with the sign bit same as of the [sign] value. + */ +@SinceKotlin("1.2") +public actual fun Double.withSign(sign: Int): Double = withSign(sign.toDouble()) + +/** + * Returns the ulp (unit in the last place) of this value. + * + * An ulp is a positive distance between this value and the next nearest [Double] value larger in magnitude. + * + * Special Cases: + * - `NaN.ulp` is `NaN` + * - `x.ulp` is `+Inf` when `x` is `+Inf` or `-Inf` + * - `0.0.ulp` is `Double.MIN_VALUE` + */ +@SinceKotlin("1.2") +public actual val Double.ulp: Double + get() = when { + isNaN() -> Double.NaN + isInfinite() -> Double.POSITIVE_INFINITY + this == Double.MAX_VALUE || this == -Double.MAX_VALUE -> 2.0.pow(971) + else -> { + val d = absoluteValue + d.nextUp() - d + } + } + +/** + * Returns the [Double] value nearest to this value in direction of positive infinity. + */ +@SinceKotlin("1.2") +@SymbolName("Kotlin_math_Double_nextUp") +external public actual fun Double.nextUp(): Double +/** + * Returns the [Double] value nearest to this value in direction of negative infinity. + */ +@SinceKotlin("1.2") +@SymbolName("Kotlin_math_Double_nextDown") +external public actual fun Double.nextDown(): Double + +/** + * Returns the [Double] value nearest to this value in direction from this value towards the value [to]. + * + * Special cases: + * - `x.nextTowards(y)` is `NaN` if either `x` or `y` are `NaN` + * - `x.nextTowards(x) == x` + * + */ +@SinceKotlin("1.2") +@SymbolName("Kotlin_math_Double_nextTowards") +external public actual fun Double.nextTowards(to: Double): Double + +/** + * Returns true if the sign of [this] value is negative and false otherwise + */ +@SymbolName("Kotlin_math_Double_signBit") +external private fun Double.signBit(): Boolean + +/** + * Rounds this [Double] value to the nearest integer and converts the result to [Int]. + * Ties are rounded towards positive infinity. + * + * Special cases: + * - `x.roundToInt() == Int.MAX_VALUE` when `x > Int.MAX_VALUE` + * - `x.roundToInt() == Int.MIN_VALUE` when `x < Int.MIN_VALUE` + * + * @throws IllegalArgumentException when this value is `NaN` + */ +@SinceKotlin("1.2") +public actual fun Double.roundToInt(): Int = when { + isNaN() -> throw IllegalArgumentException("Cannot round NaN value.") + this > Int.MAX_VALUE -> Int.MAX_VALUE + this < Int.MIN_VALUE -> Int.MIN_VALUE + else -> floor(this + 0.5).toInt() +} + +/** + * Rounds this [Double] value to the nearest integer and converts the result to [Long]. + * Ties are rounded towards positive infinity. + * + * Special cases: + * - `x.roundToLong() == Long.MAX_VALUE` when `x > Long.MAX_VALUE` + * - `x.roundToLong() == Long.MIN_VALUE` when `x < Long.MIN_VALUE` + * + * @throws IllegalArgumentException when this value is `NaN` + */ +@SinceKotlin("1.2") +public actual fun Double.roundToLong(): Long = when { + isNaN() -> throw IllegalArgumentException("Cannot round NaN value.") + this > Long.MAX_VALUE -> Long.MAX_VALUE + this < Long.MIN_VALUE -> Long.MIN_VALUE + else -> floor(this + 0.5).toLong() +} + +// endregion + +// region ================ Float Math ======================================== + +/** Computes the sine of the angle [x] given in radians. + * + * Special cases: + * - `sin(NaN|+Inf|-Inf)` is `NaN` + */ +@SinceKotlin("1.2") +@SymbolName("Kotlin_math_sinf") +external public actual fun sin(x: Float): Float + +/** Computes the cosine of the angle [x] given in radians. + * + * Special cases: + * - `cos(NaN|+Inf|-Inf)` is `NaN` + */ +@SinceKotlin("1.2") +@SymbolName("Kotlin_math_cosf") +external public actual fun cos(x: Float): Float + +/** Computes the tangent of the angle [x] given in radians. + * + * Special cases: + * - `tan(NaN|+Inf|-Inf)` is `NaN` + */ +@SinceKotlin("1.2") +@SymbolName("Kotlin_math_tanf") +external public actual fun tan(x: Float): Float + +/** + * Computes the arc sine of the value [x]; + * the returned value is an angle in the range from `-PI/2` to `PI/2` radians. + * + * Special cases: + * - `asin(x)` is `NaN`, when `abs(x) > 1` or x is `NaN` + */ +@SinceKotlin("1.2") +@SymbolName("Kotlin_math_asinf") +external public actual fun asin(x: Float): Float + +/** + * Computes the arc cosine of the value [x]; + * the returned value is an angle in the range from `0.0` to `PI` radians. + * + * Special cases: + * - `acos(x)` is `NaN`, when `abs(x) > 1` or x is `NaN` + */ +@SinceKotlin("1.2") +@SymbolName("Kotlin_math_acosf") +external public actual fun acos(x: Float): Float + +/** + * Computes the arc tangent of the value [x]; + * the returned value is an angle in the range from `-PI/2` to `PI/2` radians. + * + * Special cases: + * - `atan(NaN)` is `NaN` + */ +@SinceKotlin("1.2") +@SymbolName("Kotlin_math_atanf") +external public actual fun atan(x: Float): Float + +/** + * Returns the angle `theta` of the polar coordinates `(r, theta)` that correspond + * to the rectangular coordinates `(x, y)` by computing the arc tangent of the value [y] / [x]; + * the returned value is an angle in the range from `-PI` to `PI` radians. + * + * Special cases: + * - `atan2(0.0, 0.0)` is `0.0` + * - `atan2(0.0, x)` is `0.0` for `x > 0` and `PI` for `x < 0` + * - `atan2(-0.0, x)` is `-0.0` for 'x > 0` and `-PI` for `x < 0` + * - `atan2(y, +Inf)` is `0.0` for `0 < y < +Inf` and `-0.0` for '-Inf < y < 0` + * - `atan2(y, -Inf)` is `PI` for `0 < y < +Inf` and `-PI` for `-Inf < y < 0` + * - `atan2(y, 0.0)` is `PI/2` for `y > 0` and `-PI/2` for `y < 0` + * - `atan2(+Inf, x)` is `PI/2` for finite `x`y + * - `atan2(-Inf, x)` is `-PI/2` for finite `x` + * - `atan2(NaN, x)` and `atan2(y, NaN)` is `NaN` + */ +@SinceKotlin("1.2") +@SymbolName("Kotlin_math_atan2f") +external public actual fun atan2(y: Float, x: Float): Float + +/** + * Computes the hyperbolic sine of the value [x]. + * + * Special cases: + * - `sinh(NaN)` is `NaN` + * - `sinh(+Inf)` is `+Inf` + * - `sinh(-Inf)` is `-Inf` + */ +@SinceKotlin("1.2") +@SymbolName("Kotlin_math_sinhf") +external public actual fun sinh(x: Float): Float + +/** + * Computes the hyperbolic cosine of the value [x]. + * + * Special cases: + * - `cosh(NaN)` is `NaN` + * - `cosh(+Inf|-Inf)` is `+Inf` + */ +@SinceKotlin("1.2") +@SymbolName("Kotlin_math_coshf") +external public actual fun cosh(x: Float): Float + +/** + * Computes the hyperbolic tangent of the value [x]. + * + * Special cases: + * - `tanh(NaN)` is `NaN` + * - `tanh(+Inf)` is `1.0` + * - `tanh(-Inf)` is `-1.0` + */ +@SinceKotlin("1.2") +@SymbolName("Kotlin_math_tanhf") +external public actual fun tanh(x: Float): Float + +/** + * Computes the inverse hyperbolic sine of the value [x]. + * + * The returned value is `y` such that `sinh(y) == x`. + * + * Special cases: + * - `asinh(NaN)` is `NaN` + * - `asinh(+Inf)` is `+Inf` + * - `asinh(-Inf)` is `-Inf` + */ +@SinceKotlin("1.2") +@SymbolName("Kotlin_math_asinhf") +external public actual fun asinh(x: Float): Float + +/** + * Computes the inverse hyperbolic cosine of the value [x]. + * + * The returned value is positive `y` such that `cosh(y) == x`. + * + * Special cases: + * - `acosh(NaN)` is `NaN` + * - `acosh(x)` is `NaN` when `x < 1` + * - `acosh(+Inf)` is `+Inf` + */ +@SinceKotlin("1.2") +@SymbolName("Kotlin_math_acoshf") +external public actual fun acosh(x: Float): Float + +/** + * Computes the inverse hyperbolic tangent of the value [x]. + * + * The returned value is `y` such that `tanh(y) == x`. + * + * Special cases: + * - `tanh(NaN)` is `NaN` + * - `tanh(x)` is `NaN` when `x > 1` or `x < -1` + * - `tanh(1.0)` is `+Inf` + * - `tanh(-1.0)` is `-Inf` + */ +@SinceKotlin("1.2") +@SymbolName("Kotlin_math_atanhf") +external public actual fun atanh(x: Float): Float + +/** + * Computes `sqrt(x^2 + y^2)` without intermediate overflow or underflow. + * + * Special cases: + * - returns `+Inf` if any of arguments is infinite + * - returns `NaN` if any of arguments is `NaN` and the other is not infinite + */ +@SinceKotlin("1.2") +@SymbolName("Kotlin_math_hypotf") +external public actual fun hypot(x: Float, y: Float): Float + +/** + * Computes the positive square root of the value [x]. + * + * Special cases: + * - `sqrt(x)` is `NaN` when `x < 0` or `x` is `NaN` + */ +@SinceKotlin("1.2") +@SymbolName("Kotlin_math_sqrtf") +external public actual fun sqrt(x: Float): Float + +/** + * Computes Euler's number `e` raised to the power of the value [x]. + * + * Special cases: + * - `exp(NaN)` is `NaN` + * - `exp(+Inf)` is `+Inf` + * - `exp(-Inf)` is `0.0` + */ +@SinceKotlin("1.2") +@SymbolName("Kotlin_math_expf") +external public actual fun exp(x: Float): Float + +/** + * Computes `exp(x) - 1`. + * + * This function can be implemented to produce more precise result for [x] near zero. + * + * Special cases: + * - `expm1(NaN)` is `NaN` + * - `expm1(+Inf)` is `+Inf` + * - `expm1(-Inf)` is `-1.0` + * + * @see [exp] function. + */ +@SinceKotlin("1.2") +@SymbolName("Kotlin_math_expm1f") +external public actual fun expm1(x: Float): Float + +/** + * Computes the logarithm of the value [x] to the given [base]. + * + * Special cases: + * - `log(x, b)` is `NaN` if either `x` or `b` are `NaN` + * - `log(x, b)` is `NaN` when `x < 0` or `b <= 0` or `b == 1.0` + * - `log(+Inf, +Inf)` is `NaN` + * - `log(+Inf, b)` is `+Inf` for `b > 1` and `-Inf` for `b < 1` + * - `log(0.0, b)` is `-Inf` for `b > 1` and `+Inf` for `b > 1` + * + * See also logarithm functions for common fixed bases: [ln], [log10] and [log2]. + */ +@SinceKotlin("1.2") +public actual fun log(x: Float, base: Float): Float { + if (base <= 0.0F || base == 1.0F) return Float.NaN + return ln(x) / ln(base) +} + +/** + * Computes the natural logarithm (base `E`) of the value [x]. + * + * Special cases: + * - `ln(NaN)` is `NaN` + * - `ln(x)` is `NaN` when `x < 0.0` + * - `ln(+Inf)` is `+Inf` + * - `ln(0.0)` is `-Inf` + */ +@SinceKotlin("1.2") +@SymbolName("Kotlin_math_lnf") +external public actual fun ln(x: Float): Float + +/** + * Computes the common logarithm (base 10) of the value [x]. + * + * @see [ln] actual function for special cases. + */ +@SinceKotlin("1.2") +@SymbolName("Kotlin_math_log10f") +external public actual fun log10(x: Float): Float + +/** + * Computes the binary logarithm (base 2) of the value [x]. + * + * @see [ln] actual function for special cases. + */ +@SinceKotlin("1.2") +@SymbolName("Kotlin_math_log2f") +external public actual fun log2(x: Float): Float + +/** + * Computes `ln(a + 1)`. + * + * This function can be implemented to produce more precise result for [x] near zero. + * + * Special cases: + * - `ln1p(NaN)` is `NaN` + * - `ln1p(x)` is `NaN` where `x < -1.0` + * - `ln1p(-1.0)` is `-Inf` + * - `ln1p(+Inf)` is `+Inf` + * + * @see [ln] function + * @see [expm1] function + */ +@SinceKotlin("1.2") +@SymbolName("Kotlin_math_ln1pf") +external public actual fun ln1p(x: Float): Float + +/** + * Rounds the given value [x] to an integer towards positive infinity. + + * @return the smallest Float value that is greater than or equal to the given value [x] and is a mathematical integer. + * + * Special cases: + * - `ceil(x)` is `x` where `x` is `NaN` or `+Inf` or `-Inf` or already a mathematical integer. + */ +@SinceKotlin("1.2") +@SymbolName("Kotlin_math_ceilf") +external public actual fun ceil(x: Float): Float + +/** + * Rounds the given value [x] to an integer towards negative infinity. + + * @return the largest Float value that is smaller than or equal to the given value [x] and is a mathematical integer. + * + * Special cases: + * - `floor(x)` is `x` where `x` is `NaN` or `+Inf` or `-Inf` or already a mathematical integer. + */ +@SinceKotlin("1.2") +@SymbolName("Kotlin_math_floorf") +external public actual fun floor(x: Float): Float + +/** + * Rounds the given value [x] to an integer towards zero. + * + * @return the value [x] having its fractional part truncated. + * + * Special cases: + * - `truncate(x)` is `x` where `x` is `NaN` or `+Inf` or `-Inf` or already a mathematical integer. + */ +@SinceKotlin("1.2") +public actual fun truncate(x: Float): Float = when { + x.isNaN() || x.isInfinite() -> x + x > 0 -> floor(x) + else -> ceil(x) +} + +/** + * Rounds the given value [x] towards the closest integer with ties rounded towards even integer. + * + * Special cases: + * - `round(x)` is `x` where `x` is `NaN` or `+Inf` or `-Inf` or already a mathematical integer. + */ +@SinceKotlin("1.2") +@SymbolName("Kotlin_math_roundf") +external public actual fun round(x: Float): Float + + +/** + * Returns the absolute value of the given value [x]. + * + * Special cases: + * - `abs(NaN)` is `NaN` + * + * @see absoluteValue extension property for [Float] + */ +@SinceKotlin("1.2") +@SymbolName("Kotlin_math_absf") +external public actual fun abs(x: Float): Float + +/** + * Returns the sign of the given value [x]: + * - `-1.0` if the value is negative, + * - zero if the value is zero, + * - `1.0` if the value is positive + * + * Special case: + * - `sign(NaN)` is `NaN` + */ +@SinceKotlin("1.2") +public actual fun sign(x: Float): Float = when { + x.isNaN() -> Float.NaN + x > 0 -> 1.0f + x < 0 -> -1.0f + else -> x +} + +/** + * Returns the smaller of two values. + * + * If either value is `NaN`, then the result is `NaN`. + */ +@SinceKotlin("1.2") +public actual fun min(a: Float, b: Float): Float = when { + a.isNaN() || b.isNaN() -> Float.NaN + a == 0.0f && b == 0.0f -> if (a.signBit()) a else b // -0.0 < +0.0 + else -> if (a < b) a else b +} +/** + * Returns the greater of two values. + * + * If either value is `NaN`, then the result is `NaN`. + */ +@SinceKotlin("1.2") +public actual fun max(a: Float, b: Float): Float = when { + a.isNaN() || b.isNaN() -> Float.NaN + a == 0.0f && b == 0.0f -> if (!a.signBit()) a else b // -0.0 < +0.0 + else -> if (a > b) a else b +} + +// extensions + +/** + * Raises this value to the power [x]. + * + * Special cases: + * - `b.pow(0.0)` is `1.0` + * - `b.pow(1.0) == b` + * - `b.pow(NaN)` is `NaN` + * - `NaN.pow(x)` is `NaN` for `x != 0.0` + * - `b.pow(Inf)` is `NaN` for `abs(b) == 1.0` + * - `b.pow(x)` is `NaN` for `b < 0` and `x` is finite and not an integer + */ +@SinceKotlin("1.2") +@SymbolName("Kotlin_math_Float_pow") +external public actual fun Float.pow(x: Float): Float + +/** + * Raises this value to the integer power [n]. + * + * See the other overload of [pow] for details. + */ +@SinceKotlin("1.2") +public actual fun Float.pow(n: Int): Float = pow(n.toFloat()) + +/** + * Computes the remainder of division of this value by the [divisor] value according to the IEEE 754 standard. + * + * The result is computed as `r = this - (q * divisor)` where `q` is the quotient of division rounded to the nearest integer, + * `q = round(this / other)`. + * + * Special cases: + * - `x.IEEErem(y)` is `NaN`, when `x` is `NaN` or `y` is `NaN` or `x` is `+Inf|-Inf` or `y` is zero. + * - `x.IEEErem(y) == x` when `x` is finite and `y` is infinite. + * + * @see round + */ +@SinceKotlin("1.2") +@SymbolName("Kotlin_math_Float_IEEErem") +external public fun Float.IEEErem(divisor: Float): Float + +/** + * Returns the absolute value of this value. + * + * Special cases: + * - `NaN.absoluteValue` is `NaN` + * + * @see abs actual function + */ +@SinceKotlin("1.2") +public actual val Float.absoluteValue: Float + get() = abs(this) + +/** + * Returns the sign of this value: + * - `-1.0` if the value is negative, + * - zero if the value is zero, + * - `1.0` if the value is positive + * + * Special case: + * - `NaN.sign` is `NaN` + */ +@SinceKotlin("1.2") +public actual val Float.sign: Float + get() = sign(this) + +/** + * Returns this value with the sign bit same as of the [sign] value. + * + * If [sign] is `NaN` the sign of the result is undefined. + */ +@SinceKotlin("1.2") +@SymbolName("Kotlin_math_Float_withSign") +external public actual fun Float.withSign(sign: Float): Float +/** + * Returns this value with the sign bit same as of the [sign] value. + */ +@SinceKotlin("1.2") +public actual fun Float.withSign(sign: Int): Float = withSign(sign.toFloat()) + +@SinceKotlin("1.2") +public val Float.ulp: Float + get() = when { + isNaN() -> Float.NaN + isInfinite() -> Float.POSITIVE_INFINITY + this == Float.MAX_VALUE || this == -Float.MAX_VALUE -> 2.0f.pow(104) + else -> { + val d = absoluteValue + d.nextUp() - d + } + } + +/** + * Returns the [Float] value nearest to this value in direction of positive infinity. + */ +@SinceKotlin("1.2") +@SymbolName("Kotlin_math_Float_nextUp") +external public fun Float.nextUp(): Float +/** + * Returns the [Float] value nearest to this value in direction of negative infinity. + */ +@SinceKotlin("1.2") +@SymbolName("Kotlin_math_Float_nextDown") +external public fun Float.nextDown(): Float + +/** + * Returns the [Float] value nearest to this value in direction from this value towards the value [to]. + * + * Special cases: + * - `x.nextTowards(y)` is `NaN` if either `x` or `y` are `NaN` + * - `x.nextTowards(x) == x` + * + */ +@SinceKotlin("1.2") +@SymbolName("Kotlin_math_Float_nextTowards") +external public fun Float.nextTowards(to: Float): Float + +/** + * Returns true if the sign of [this] value is negative and false otherwise + */ +@SymbolName("Kotlin_math_Float_signBit") +external private fun Float.signBit(): Boolean + +/** + * Rounds this [Float] value to the nearest integer and converts the result to [Int]. + * Ties are rounded towards positive infinity. + * + * Special cases: + * - `x.roundToInt() == Int.MAX_VALUE` when `x > Int.MAX_VALUE` + * - `x.roundToInt() == Int.MIN_VALUE` when `x < Int.MIN_VALUE` + * + * @throws IllegalArgumentException when this value is `NaN` + */ +@SinceKotlin("1.2") +public actual fun Float.roundToInt(): Int = when { + isNaN() -> throw IllegalArgumentException("Cannot round NaN value.") + this > Int.MAX_VALUE -> Int.MAX_VALUE + this < Int.MIN_VALUE -> Int.MIN_VALUE + else -> floor(this + 0.5f).toInt() +} + +/** + * Rounds this [Float] value to the nearest integer and converts the result to [Long]. + * Ties are rounded towards positive infinity. + * + * Special cases: + * - `x.roundToLong() == Long.MAX_VALUE` when `x > Long.MAX_VALUE` + * - `x.roundToLong() == Long.MIN_VALUE` when `x < Long.MIN_VALUE` + * + * @throws IllegalArgumentException when this value is `NaN` + */ +@SinceKotlin("1.2") +public actual fun Float.roundToLong(): Long = when { + isNaN() -> throw IllegalArgumentException("Cannot round NaN value.") + this > Long.MAX_VALUE -> Long.MAX_VALUE + this < Long.MIN_VALUE -> Long.MIN_VALUE + else -> floor(this + 0.5f).toLong() +} + +// endregion + +// region ================ Integer Math ======================================== + +/** + * Returns the absolute value of the given value [n]. + * + * Special cases: + * - `abs(Int.MIN_VALUE)` is `Int.MIN_VALUE` due to an overflow + * + * @see absoluteValue extension property for [Int] + */ +@SinceKotlin("1.2") +@SymbolName("Kotlin_math_absi") +external public actual fun abs(n: Int): Int + +/** + * Returns the smaller of two values. + */ +@SinceKotlin("1.2") +public actual fun min(a: Int, b: Int): Int = if (a < b) a else b + +/** + * Returns the greater of two values. + */ +@SinceKotlin("1.2") +public actual fun max(a: Int, b: Int): Int = if (a > b) a else b + +/** + * Returns the absolute value of this value. + * + * Special cases: + * - `Int.MIN_VALUE.absoluteValue` is `Int.MIN_VALUE` due to an overflow + * + * @see abs actual function + */ +@SinceKotlin("1.2") +public actual val Int.absoluteValue: Int + get() = abs(this) + +/** + * Returns the sign of this value: + * - `-1` if the value is negative, + * - `0` if the value is zero, + * - `1` if the value is positive + */ +@SinceKotlin("1.2") +public actual val Int.sign: Int + get() = when { + this < 0 -> -1 + this > 0 -> 1 + else -> 0 + } + + +/** + * Returns the absolute value of the given value [n]. + * + * Special cases: + * - `abs(Long.MIN_VALUE)` is `Long.MIN_VALUE` due to an overflow + * + * @see absoluteValue extension property for [Long] + */ +@SinceKotlin("1.2") +@SymbolName("Kotlin_math_absl") +external public actual fun abs(n: Long): Long + +/** + * Returns the smaller of two values. + */ +@SinceKotlin("1.2") +public actual fun min(a: Long, b: Long): Long = if (a < b) a else b + +/** + * Returns the greater of two values. + */ +@SinceKotlin("1.2") +public actual fun max(a: Long, b: Long): Long = if (a > b) a else b + +/** + * Returns the absolute value of this value. + * + * Special cases: + * - `Long.MIN_VALUE.absoluteValue` is `Long.MIN_VALUE` due to an overflow + * + * @see abs actual function + */ +@SinceKotlin("1.2") +public actual val Long.absoluteValue: Long + get() = abs(this) + +/** + * Returns the sign of this value: + * - `-1` if the value is negative, + * - `0` if the value is zero, + * - `1` if the value is positive + */ +@SinceKotlin("1.2") +public actual val Long.sign: Int + get() = when { + this < 0 -> -1 + this > 0 -> 1 + else -> 0 + } + +// endregion \ No newline at end of file diff --git a/kotlin-native/runtime/src/main/kotlin/kotlin/native/Annotations.kt b/kotlin-native/runtime/src/main/kotlin/kotlin/native/Annotations.kt new file mode 100644 index 00000000000..a5dc4825526 --- /dev/null +++ b/kotlin-native/runtime/src/main/kotlin/kotlin/native/Annotations.kt @@ -0,0 +1,54 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +package kotlin.native + +import kotlin.reflect.KClass + +/** + * Forces the compiler to use specified symbol name for the target `external` function. + * + * TODO: changing symbol name breaks the binary compatibility, + * so it should probably be allowed on `internal` and `private` functions only. + */ +@Target(AnnotationTarget.FUNCTION) +@Retention(AnnotationRetention.BINARY) +public annotation class SymbolName(val name: String) + +/** + * Preserve the function entry point during global optimizations. + */ +@Target(AnnotationTarget.FUNCTION, AnnotationTarget.CLASS) +@Retention(AnnotationRetention.BINARY) +public annotation class Retain + +/** + * Preserve the function entry point during global optimizations, only for the given target. + */ +@Target(AnnotationTarget.FUNCTION, AnnotationTarget.CLASS) +@Retention(AnnotationRetention.BINARY) +public annotation class RetainForTarget(val target: String) + + +/** @suppress */ +@Deprecated("Use common kotlin.Throws annotation instead.", ReplaceWith("kotlin.Throws"), DeprecationLevel.WARNING) +public typealias Throws = kotlin.Throws + +/** @suppress */ +public typealias ThreadLocal = kotlin.native.concurrent.ThreadLocal + +/** @suppress */ +public typealias SharedImmutable = kotlin.native.concurrent.SharedImmutable + +/** + * Makes top level function available from C/C++ code with the given name. + * + * [externName] controls the name of top level function, [shortName] controls the short name. + * If [externName] is empty, no top level declaration is being created. + */ +@Target(AnnotationTarget.FUNCTION) +@Retention(AnnotationRetention.BINARY) +public annotation class CName(val externName: String = "", val shortName: String = "") + diff --git a/kotlin-native/runtime/src/main/kotlin/kotlin/native/BitSet.kt b/kotlin-native/runtime/src/main/kotlin/kotlin/native/BitSet.kt new file mode 100644 index 00000000000..090db434df6 --- /dev/null +++ b/kotlin-native/runtime/src/main/kotlin/kotlin/native/BitSet.kt @@ -0,0 +1,437 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +package kotlin.native + +/** + * A vector of bits growing if necessary and allowing one to set/clear/read bits from it by a bit index. + * + * @constructor creates an empty bit set with the specified [size] + * @param size the size of one element in the array used to store bits. + */ +public class BitSet(size: Int = ELEMENT_SIZE) { + + @kotlin.native.internal.CanBePrecreated + companion object { + // Default size of one element in the array used to store bits. + private const val ELEMENT_SIZE = 64 + private const val MAX_BIT_OFFSET = ELEMENT_SIZE - 1 + private const val ALL_TRUE = -1L // 0xFFFF_FFFF_FFFF_FFFF + private const val ALL_FALSE = 0L // 0x0000_0000_0000_0000 + } + + private var bits: LongArray = LongArray(bitToElementSize(size)) + + private val lastIndex: Int + get() = size - 1 + + /** Returns an index of the last bit that has `true` value. Returns -1 if the set is empty. */ + val lastTrueIndex: Int + get() = previousSetBit(size) + + /** True if this BitSet contains no bits set to true. */ + val isEmpty: Boolean + get() = bits.all { it == ALL_FALSE } + + /** Actual number of bits available in the set. All bits with indices >= size assumed to be 0 */ + var size: Int = size + private set + + /** + * Creates a bit set of given [length] filling elements using [initializer] + */ + constructor(length: Int, initializer: (Int) -> Boolean): this(length) { + for (i in 0 until length) { + set(i, initializer(i)) + } + } + + // Transforms a bit index into an element index in the `bits` array. + private val Int.elementIndex: Int + get() = this / ELEMENT_SIZE + + // Transforms a bit index in the set into a bit in the element of the `bits` array. + private val Int.bitOffset: Int + get() = this % ELEMENT_SIZE + + // Transforms a bit index in the set into pair of a `bits` element index and a bit index in the element. + private val Int.asBitCoordinates: Pair + get() = Pair(elementIndex, bitOffset) + + // Transforms a bit offset to the mask with only bit set corresponding to the offset. + private val Int.asMask: Long + get() = 0x1L shl this + + // Transforms a bit offset to the mask with only bits before the index (inclusive) set. + private val Int.asMaskBefore: Long + get() = getMaskBetween(0, this) + + // Transforms a bit offset to the mask with only bits after the index (inclusive) set. + private val Int.asMaskAfter: Long + get() = getMaskBetween(this, MAX_BIT_OFFSET) + + // Builds a masks with 1 between fromOffset and toOffset (both inclusive). + private fun getMaskBetween(fromOffset: Int, toOffset: Int): Long { + var res = 0L + val maskToAdd = fromOffset.asMask + for (i in fromOffset..toOffset) { + res = (res shl 1) or maskToAdd + } + return res + } + + // Transforms a size in bits to a size in elements of the `bits` array. + private fun bitToElementSize(bitSize: Int): Int = (bitSize + ELEMENT_SIZE - 1) / ELEMENT_SIZE + + // Transforms a pair of an element index and a bit offset to a bit index. + private fun bitIndex(elementIndex: Int, bitOffset: Int) = + elementIndex * ELEMENT_SIZE + bitOffset + + // Sets all bits after the last available bit (size - 1) to 0. + private fun clearUnusedTail() { + val (lastElementIndex, lastBitOffset) = lastIndex.asBitCoordinates + bits[bits.lastIndex] = bits[bits.lastIndex] and lastBitOffset.asMaskBefore + for (i in lastElementIndex + 1 until bits.size) { + bits[i] = ALL_FALSE + } + } + + // Internal function. Sets bits specified by the element index and the given mask to value. + private fun setBitsWithMask(elementIndex: Int, mask: Long, value: Boolean) { + val element = bits[elementIndex] + if (value) { + bits[elementIndex] = element or mask + } else { + bits[elementIndex] = element and mask.inv() + } + } + + // Internal function. Flips bits specified by the element index and the given mask. + private fun flipBitsWithMask(elementIndex: Int, mask: Long) { + val element = bits[elementIndex] + bits[elementIndex] = element xor mask + } + + /** + * Checks if index is valid and extends the `bits` array if the index exceeds its size. + * @throws [IndexOutOfBoundsException] if [index] < 0. + */ + private fun ensureCapacity(index: Int) { + if (index < 0) { + throw IndexOutOfBoundsException() + } + if (index >= size) { + size = index + 1 + if (index.elementIndex >= bits.size) { + // Create a new array containing the index-th bit. + bits = bits.copyOf(bitToElementSize(index + 1)) + } + // Set all bits after the index to 0. TODO: We can remove it. + clearUnusedTail() + } + } + + /** Set the bit specified to the specified value. */ + fun set(index: Int, value: Boolean = true) { + ensureCapacity(index) + val (elementIndex, offset) = index.asBitCoordinates + setBitsWithMask(elementIndex, offset.asMask, value) + } + + /** Sets the bits with indices between [from] (inclusive) and [to] (exclusive) to the specified value. */ + fun set(from : Int, to: Int, value: Boolean = true) = set(from until to, value) + + /** Sets the bits from the range specified to the specified value. */ + fun set(range: IntRange, value: Boolean = true) { + if (range.start < 0 || range.endInclusive < 0) { + throw IndexOutOfBoundsException() + } + if (range.start > range.endInclusive) { // Empty range. + return + } + ensureCapacity(range.endInclusive) + val (fromIndex, fromOffset) = range.start.asBitCoordinates + val (toIndex, toOffset) = range.endInclusive.asBitCoordinates + if (toIndex == fromIndex) { + val mask = getMaskBetween(fromOffset, toOffset) + setBitsWithMask(fromIndex, mask, value) + } else { + // Set bits in the first element. + setBitsWithMask(fromIndex, fromOffset.asMaskAfter, value) + // Set all bits of all elements (excluding border ones) to 0 or 1 depending. + for (index in fromIndex + 1 until toIndex) { + bits[index] = if (value) ALL_TRUE else ALL_FALSE + } + // Set bits in the last element + setBitsWithMask(toIndex, toOffset.asMaskBefore, value) + } + } + + + /** Clears the bit specified */ + fun clear(index: Int) = set(index, false) + /** Clears the bits with indices between [from] (inclusive) and [to] (exclusive) to the specified value. */ + fun clear(from : Int, to: Int) = set(from, to, false) + /** Clears the bit specified */ + fun clear(range: IntRange) = set(range, false) + + /** Sets all bits in the BitSet to `false`. */ + fun clear() { + for (i in bits.indices) { + bits[i] = ALL_FALSE + } + } + + /** Reverses the bit specified. */ + fun flip(index: Int) { + ensureCapacity(index) + val (elementIndex, offset) = index.asBitCoordinates + flipBitsWithMask(elementIndex, offset.asMask) + } + + /** Reverses the bits with indices between [from] (inclusive) and [to] (exclusive). */ + fun flip(from: Int, to: Int) = flip(from until to) + + /** Reverses the bits from the range specified. */ + fun flip(range: IntRange) { + if (range.start < 0 || range.endInclusive < 0) { + throw IndexOutOfBoundsException() + } + if (range.start > range.endInclusive) { // Empty range. + return + } + ensureCapacity(range.endInclusive) + val (fromIndex, fromOffset) = range.start.asBitCoordinates + val (toIndex, toOffset) = range.endInclusive.asBitCoordinates + if (toIndex == fromIndex) { + val mask = getMaskBetween(fromOffset, toOffset) + flipBitsWithMask(fromIndex, mask) + } else { + // Flip bits in the first element. + flipBitsWithMask(toIndex, toOffset.asMaskAfter) + // Flip bits between the first and the last elements. + for (index in fromIndex + 1 until toIndex) { + bits[index] = bits[index].inv() + } + // Flip bits in the last element. + flipBitsWithMask(toIndex, toOffset.asMaskBefore) + } + } + + /** + * Returns an index of a next set (if [lookFor] == true) or clear + * (if [lookFor] == false) bit after [startIndex] (inclusive). + * Returns -1 (for [lookFor] == true) or [size] (for lookFor == false) + * if there is no such bits between [startIndex] and [size] - 1. + * @throws IndexOutOfBoundException if [startIndex] < 0. + */ + private fun nextBit(startIndex: Int, lookFor: Boolean): Int { + if (startIndex < 0) { + throw IndexOutOfBoundsException() + } + if (startIndex >= size) { + return if (lookFor) -1 else startIndex + } + val (startElementIndex, startOffset) = startIndex.asBitCoordinates + // Look for the next set bit in the first element. + var element = bits[startElementIndex] + for (offset in startOffset..MAX_BIT_OFFSET) { + val bit = element and (0x1L shl offset) != 0L + if (bit == lookFor) { // Look for not 0 if we need a set bit and look for 0 otherwise. + return bitIndex(startElementIndex, offset) + } + } + // Look for in the remaining elements. + for (index in startElementIndex + 1..bits.lastIndex) { + element = bits[index] + for (offset in 0..MAX_BIT_OFFSET) { + val bit = element and (0x1L shl offset) != 0L + if (bit == lookFor) { // Look for not 0 if we need a set bit and look for 0 otherwise. + return bitIndex(index, offset) + } + } + } + return if (lookFor) -1 else size + } + + /** + * Returns an index of a next bit which value is `true` after [startIndex] (inclusive). + * Returns -1 if there is no such bits after [startIndex]. + * @throws IndexOutOfBoundException if [startIndex] < 0. + */ + fun nextSetBit(startIndex: Int = 0): Int = nextBit(startIndex, true) + + /** + * Returns an index of a next bit which value is `false` after [startIndex] (inclusive). + * Returns [size] if there is no such bits between [startIndex] and [size] - 1 assuming that the set has an infinite + * sequence of `false` bits after (size - 1)-th. + * @throws IndexOutOfBoundException if [startIndex] < 0. + */ + fun nextClearBit(startIndex: Int = 0): Int = nextBit(startIndex, false) + + /** + * Returns the biggest index of a bit which value is [lookFor] before [startIndex] (inclusive). + * Returns -1 if there is no such bits before [startIndex]. + * If [startIndex] >= [size] returns -1 + */ + fun previousBit(startIndex: Int, lookFor: Boolean): Int { + var correctStartIndex = startIndex + if (startIndex >= size) { + // We assume that all bits after `size - 1` are 0. So we can return the start index if we are looking for 0. + if (!lookFor) { + return startIndex + } else { + // If we are looking for 1 we can skip all these 0 after `size - 1`. + correctStartIndex = size - 1 + } + } + if (correctStartIndex < -1) { + throw IndexOutOfBoundsException() + } + if (correctStartIndex == -1) { + return -1 + } + + val (startElementIndex, startOffset) = correctStartIndex.asBitCoordinates + // Look for the next set bit in the first element. + var element = bits[startElementIndex] + for (offset in startOffset downTo 0) { + val bit = element and (0x1L shl offset) != 0L + if (bit == lookFor) { // Look for not 0 if we need a set bit and look for 0 otherwise. + return bitIndex(startElementIndex, offset) + } + } + // Look for in the remaining elements. + for (index in startElementIndex - 1 downTo 0) { + element = bits[index] + for (offset in MAX_BIT_OFFSET downTo 0) { + val bit = element and (0x1L shl offset) != 0L + if (bit == lookFor) { // Look for not 0 if we need a set bit and look for 0 otherwise. + return bitIndex(index, offset) + } + } + } + return -1 + } + + /** + * Returns the biggest index of a bit which value is `true` before [startIndex] (inclusive). + * Returns -1 if there is no such bits before [startIndex] or if [startIndex] == -1. + * If [startIndex] >= size will search from (size - 1)-th bit. + * @throws IndexOutOfBoundException if [startIndex] < -1. + */ + fun previousSetBit(startIndex: Int): Int = previousBit(startIndex, true) + + /** + * Returns the biggest index of a bit which value is `false` before [startIndex] (inclusive). + * Returns -1 if there is no such bits before [startIndex] or if [startIndex] == -1. + * If [startIndex] >= size will return [startIndex] assuming that the set has an infinite + * sequence of `false` bits after (size - 1)-th. + * @throws IndexOutOfBoundException if [startIndex] < -1. + */ + fun previousClearBit(startIndex: Int): Int = previousBit(startIndex, false) + + /** Returns a value of a bit with the [index] specified. */ + operator fun get(index: Int): Boolean { + if (index < 0) { + throw IndexOutOfBoundsException() + } + if (index >= size) { + return false + } + val (elementIndex, offset) = index.asBitCoordinates + return bits[elementIndex] and offset.asMask != 0L + } + + private inline fun doOperation(another: BitSet, operation: Long.(Long) -> Long) { + ensureCapacity(another.lastIndex) + var index = 0 + while (index < another.bits.size) { + bits[index] = operation(bits[index], another.bits[index]) + index++ + } + while (index < bits.size) { + bits[index] = operation(bits[index], ALL_FALSE) + index++ + } + } + + /** Performs a logical and operation over corresponding bits of this and [another] BitSets. The result is saved in this BitSet. */ + fun and(another: BitSet) = doOperation(another, Long::and) + + /** Performs a logical or operation over corresponding bits of this and [another] BitSets. The result is saved in this BitSet. */ + fun or(another: BitSet) = doOperation(another, Long::or) + + /** Performs a logical xor operation over corresponding bits of this and [another] BitSets. The result is saved in this BitSet. */ + fun xor(another: BitSet) = doOperation(another, Long::xor) + + /** Performs a logical and + not operations over corresponding bits of this and [another] BitSets. The result is saved in this BitSet. */ + fun andNot(another: BitSet) { + ensureCapacity(another.lastIndex) + var index = 0 + while (index < another.bits.size) { + bits[index] = bits[index] and another.bits[index].inv() + index++ + } + while (index < bits.size) { + bits[index] = bits[index] and ALL_TRUE + index++ + } + } + + /** Returns true if the specified BitSet has any bits set to true that are also set to true in this BitSet. */ + fun intersects(another: BitSet): Boolean = + (0 until minOf(bits.size, another.bits.size)).any { bits[it] and another.bits[it] != 0L } + + override fun toString(): String { + val sb = StringBuilder() + var first = true + sb.append('[') + var index = nextSetBit(0) + while (index != -1) { + if (!first) { + sb.append('|') + } else { + first = false + } + sb.append(index) + index = nextSetBit(index + 1) + } + sb.append(']') + return sb.toString() + } + + override fun hashCode(): Int { + var x: Long = 1234 + for (i in 0..bits.lastIndex) { + x = x xor bits[i] * (i + 1) + } + return (x shr 32 xor x).toInt() + } + + override fun equals(other: Any?): Boolean { + if (this === other) { + return true + } + if (other !is BitSet) { + return false + } + var index = 0 + while (index < minOf(bits.size, other.bits.size)) { + if (bits[index] != other.bits[index]) { + return false + } + index++ + } + val longestBits = if (bits.size > other.bits.size) bits else other.bits + while (index < longestBits.size) { + if (longestBits[index] != ALL_FALSE) { + return false + } + index++ + } + return true + } +} diff --git a/kotlin-native/runtime/src/main/kotlin/kotlin/native/Blob.kt b/kotlin-native/runtime/src/main/kotlin/kotlin/native/Blob.kt new file mode 100644 index 00000000000..d62ff3a9efe --- /dev/null +++ b/kotlin-native/runtime/src/main/kotlin/kotlin/native/Blob.kt @@ -0,0 +1,86 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ +package kotlin.native + +import kotlin.native.internal.* +import kotlinx.cinterop.* + +/** + * An immutable compile-time array of bytes. + */ +@ExportTypeInfo("theImmutableBlobTypeInfo") +public final class ImmutableBlob private constructor() { + public val size: Int + get() = getArrayLength() + + // Data layout is the same as for ByteArray, so we can share native functions. + @SymbolName("Kotlin_ByteArray_get") + public external operator fun get(index: Int): Byte + + @SymbolName("Kotlin_ByteArray_getArrayLength") + private external fun getArrayLength(): Int + + /** Creates an iterator over the elements of the array. */ + public operator fun iterator(): ByteIterator { + return ImmutableBlobIteratorImpl(this) + } +} + +private class ImmutableBlobIteratorImpl(val blob: ImmutableBlob) : ByteIterator() { + var index : Int = 0 + + public override fun nextByte(): Byte { + if (!hasNext()) throw NoSuchElementException("$index") + return blob[index++] + } + + public override operator fun hasNext(): Boolean { + return index < blob.size + } +} + +/** + * Copies the data from this blob into a new [ByteArray]. + * + * @param startIndex the beginning (inclusive) of the subrange to copy, 0 by default. + * @param endIndex the end (exclusive) of the subrange to copy, size of this blob by default. + */ +@SymbolName("Kotlin_ImmutableBlob_toByteArray") +public external fun ImmutableBlob.toByteArray(startIndex: Int = 0, endIndex: Int = size): ByteArray + +/** + * Copies the data from this blob into a new [UByteArray]. + * + * @param startIndex the beginning (inclusive) of the subrange to copy, 0 by default. + * @param endIndex the end (exclusive) of the subrange to copy, size of this blob by default. + */ +@ExperimentalUnsignedTypes +@SymbolName("Kotlin_ImmutableBlob_toByteArray") +public external fun ImmutableBlob.toUByteArray(startIndex: Int = 0, endIndex: Int = size): UByteArray + +/** + * Returns stable C pointer to data at certain [offset], useful as a way to pass resource + * to C APIs. + * @see kotlinx.cinterop.CPointer + */ +public fun ImmutableBlob.asCPointer(offset: Int = 0): CPointer = + interpretCPointer(asCPointerImpl(offset))!! + +public fun ImmutableBlob.asUCPointer(offset: Int = 0): CPointer = + interpretCPointer(asCPointerImpl(offset))!! + +@SymbolName("Kotlin_ImmutableBlob_asCPointerImpl") +private external fun ImmutableBlob.asCPointerImpl(offset: Int): kotlin.native.internal.NativePtr + +/** + * Creates [ImmutableBlob] out of compile-time constant data. + * + * This method accepts values of [Short] type in range `0x00..0xff`, other values are prohibited. + * + * One element still represent one byte in the output data. + * This is the only way to create ImmutableBlob for now. + */ +@TypedIntrinsic(IntrinsicType.IMMUTABLE_BLOB) +public external fun immutableBlobOf(vararg elements: Short): ImmutableBlob diff --git a/kotlin-native/runtime/src/main/kotlin/kotlin/native/Platform.kt b/kotlin-native/runtime/src/main/kotlin/kotlin/native/Platform.kt new file mode 100644 index 00000000000..6ca425e88fa --- /dev/null +++ b/kotlin-native/runtime/src/main/kotlin/kotlin/native/Platform.kt @@ -0,0 +1,129 @@ +/* + * Copyright 2010-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ +package kotlin.native + +/** + * Operating system family. + */ +public enum class OsFamily { + UNKNOWN, + MACOSX, + IOS, + LINUX, + WINDOWS, + ANDROID, + WASM, + TVOS, + WATCHOS +} + +/** + * Central Processor Unit architecture. + */ +public enum class CpuArchitecture(val bitness: Int) { + UNKNOWN(-1), + ARM32(32), + ARM64(64), + X86(32), + X64(64), + MIPS32(32), + MIPSEL32(32), + WASM32(32); +} + +/** + * Memory model. + */ +public enum class MemoryModel { + STRICT, + RELAXED +} + +/** + * Object describing the current platform program executes upon. + */ +public object Platform { + /** + * Check if current architecture allows unaligned access to wider than byte locations. + */ + public val canAccessUnaligned: Boolean + get() = Platform_canAccessUnaligned() != 0 + + /** + * Check if byte order of the current platform is least significant byte (LSB) first, aka little endian. + */ + public val isLittleEndian: Boolean + get() = Platform_isLittleEndian() != 0 + + /** + * Operating system family program executes upon. + */ + public val osFamily: OsFamily + get() = OsFamily.values()[Platform_getOsFamily()] + + /** + * Architechture of the CPU program executes upon. + */ + public val cpuArchitecture: CpuArchitecture + get() = CpuArchitecture.values()[Platform_getCpuArchitecture()] + + /** + * Memory model binary was compiled with. + */ + public val memoryModel: MemoryModel + get() = MemoryModel.values()[Platform_getMemoryModel()] + + /** + * If binary was compiled in debug mode. + */ + public val isDebugBinary: Boolean + get() = Platform_isDebugBinary() + + /** + * If the memory leak checker is activated, by default `true` in debug mode, `false` in release. + * When memory leak checker is activated, and leak is detected during last Kotlin context + * deinitialization process - error message with leak information is printed and application + * execution is aborted. + * + * @see isDebugBinary + */ + public var isMemoryLeakCheckerActive: Boolean + get() = Platform_getMemoryLeakChecker() + set(value) = Platform_setMemoryLeakChecker(value) + + public var isCleanersLeakCheckerActive: Boolean + get() = Platform_getCleanersLeakChecker() + set(value) = Platform_setCleanersLeakChecker(value) +} + +@SymbolName("Konan_Platform_canAccessUnaligned") +private external fun Platform_canAccessUnaligned(): Int + +@SymbolName("Konan_Platform_isLittleEndian") +private external fun Platform_isLittleEndian(): Int + +@SymbolName("Konan_Platform_getOsFamily") +private external fun Platform_getOsFamily(): Int + +@SymbolName("Konan_Platform_getCpuArchitecture") +private external fun Platform_getCpuArchitecture(): Int + +@SymbolName("Konan_Platform_getMemoryModel") +private external fun Platform_getMemoryModel(): Int + +@SymbolName("Konan_Platform_isDebugBinary") +private external fun Platform_isDebugBinary(): Boolean + +@SymbolName("Konan_Platform_getMemoryLeakChecker") +private external fun Platform_getMemoryLeakChecker(): Boolean + +@SymbolName("Konan_Platform_setMemoryLeakChecker") +private external fun Platform_setMemoryLeakChecker(value: Boolean): Unit + +@SymbolName("Konan_Platform_getCleanersLeakChecker") +private external fun Platform_getCleanersLeakChecker(): Boolean + +@SymbolName("Konan_Platform_setCleanersLeakChecker") +private external fun Platform_setCleanersLeakChecker(value: Boolean): Unit diff --git a/kotlin-native/runtime/src/main/kotlin/kotlin/native/Runtime.kt b/kotlin-native/runtime/src/main/kotlin/kotlin/native/Runtime.kt new file mode 100644 index 00000000000..4722db26c4f --- /dev/null +++ b/kotlin-native/runtime/src/main/kotlin/kotlin/native/Runtime.kt @@ -0,0 +1,63 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ +package kotlin.native + +import kotlin.native.concurrent.isFrozen +import kotlin.native.concurrent.InvalidMutabilityException +import kotlin.native.internal.Escapes + +/** + * Initializes Kotlin runtime for the current thread, if not inited already. + */ +@SymbolName("Kotlin_initRuntimeIfNeeded") +external public fun initRuntimeIfNeeded(): Unit + +/** + * Deinitializes Kotlin runtime for the current thread, if was inited. + * Cannot be called from Kotlin frames holding references, thus deprecated. + */ +@SymbolName("Kotlin_deinitRuntimeIfNeeded") +@Deprecated("Deinit runtime can not be called from Kotlin", level = DeprecationLevel.ERROR) +external public fun deinitRuntimeIfNeeded(): Unit + +/** + * Exception thrown when top level variable is accessed from incorrect execution context. + */ +public class IncorrectDereferenceException : RuntimeException { + constructor() : super() + + constructor(message: String) : super(message) +} + +/** + * Typealias describing custom exception reporting hook. + */ +public typealias ReportUnhandledExceptionHook = Function1 + +/** + * Install custom unhandled exception hook. Returns old hook, or null if it was not specified. + * Hook is invoked whenever there's uncaught exception reaching boundaries of the Kotlin world, + * i.e. top level main(), or when Objective-C to Kotlin call not marked with @Throws throws an exception. + * Hook must be a frozen lambda, so that it could be called from any thread/worker. + * Hook is invoked once, and is cleared afterwards, so that memory leak detection works as expected even + * with custom exception hooks. + */ +public fun setUnhandledExceptionHook(hook: ReportUnhandledExceptionHook): ReportUnhandledExceptionHook? { + if (!hook.isFrozen) { + throw InvalidMutabilityException("Unhandled exception hook must be frozen") + } + return setUnhandledExceptionHook0(hook) +} + +@SymbolName("Kotlin_setUnhandledExceptionHook") +@Escapes(0b01) // escapes +external private fun setUnhandledExceptionHook0(hook: ReportUnhandledExceptionHook): ReportUnhandledExceptionHook? + +/** + * Compute stable wrt potential object relocations by the memory manager identity hash code. + * @return 0 for `null` object, identity hash code otherwise. + */ +@SymbolName("Kotlin_Any_hashCode") +public external fun Any?.identityHashCode(): Int \ No newline at end of file diff --git a/kotlin-native/runtime/src/main/kotlin/kotlin/native/Text.kt b/kotlin-native/runtime/src/main/kotlin/kotlin/native/Text.kt new file mode 100644 index 00000000000..dca59618736 --- /dev/null +++ b/kotlin-native/runtime/src/main/kotlin/kotlin/native/Text.kt @@ -0,0 +1,157 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +package kotlin.native + +import kotlinx.cinterop.toKString + +/** + * Converts an UTF-8 array into a [String]. Replaces invalid input sequences with a default character. + */ +@Deprecated( + "Use toKString or decodeToString instead", + ReplaceWith("toKString()", "kotlinx.cinterop.toKString"), + DeprecationLevel.ERROR +) +public fun ByteArray.stringFromUtf8() : String { + @Suppress("DEPRECATION_ERROR") + return this.stringFromUtf8(0, this.size) +} + +/** + * Converts an UTF-8 array into a [String]. Replaces invalid input sequences with a default character. + */ +@Deprecated( + "Use toKString or decodeToString instead", + ReplaceWith("toKString(start, start + size)", "kotlinx.cinterop.toKString"), + DeprecationLevel.ERROR +) +public fun ByteArray.stringFromUtf8(start: Int = 0, size: Int = this.size) : String { + return toKString(start, start + size) +} + +/** + * Converts an UTF-8 array into a [String]. + * @throws [IllegalCharacterConversionException] if the input is invalid. + */ +@Deprecated( + "Use toKString or decodeToString instead", + ReplaceWith("toKString(throwOnInvalidSequence = true)", "kotlinx.cinterop.toKString"), + DeprecationLevel.ERROR +) +public fun ByteArray.stringFromUtf8OrThrow() : String { + @Suppress("DEPRECATION_ERROR") + return this.stringFromUtf8OrThrow(0, this.size) +} + +/** + * Converts an UTF-8 array into a [String]. + * @throws [IllegalCharacterConversionException] if the input is invalid. + */ +@Deprecated( + "Use toKString or decodeToString instead", + ReplaceWith("toKString(start, start + size, throwOnInvalidSequence = true)", "kotlinx.cinterop.toKString"), + DeprecationLevel.ERROR +) +public fun ByteArray.stringFromUtf8OrThrow(start: Int = 0, size: Int = this.size) : String { + try { + return toKString(start, start + size, throwOnInvalidSequence = true) + } catch (e: CharacterCodingException) { + @Suppress("DEPRECATION_ERROR") + throw IllegalCharacterConversionException() + } +} + +/** + * Converts a [String] into an UTF-8 array. Replaces invalid input sequences with a default character. + */ +@Deprecated( + "Use encodeToByteArray instead", + ReplaceWith("encodeToByteArray()"), + DeprecationLevel.ERROR +) +public fun String.toUtf8() : ByteArray { + @Suppress("DEPRECATION_ERROR") + return this.toUtf8(0, this.length) +} + +/** + * Converts a [String] into an UTF-8 array. Replaces invalid input sequences with a default character. + */ +@Deprecated( + "Use encodeToByteArray instead", + ReplaceWith("encodeToByteArray(start, start + size)"), + DeprecationLevel.ERROR +) +public fun String.toUtf8(start: Int = 0, size: Int = this.length) : ByteArray { + checkBoundsIndexes(start, start + size, this.length) + return unsafeStringToUtf8(start, size) +} + +/** + * Converts a [String] into an UTF-8 array. + * @throws [IllegalCharacterConversionException] if the input is invalid. + */ +@Deprecated( + "Use encodeToByteArray instead", + ReplaceWith("encodeToByteArray(throwOnInvalidSequence = true)"), + DeprecationLevel.ERROR +) +public fun String.toUtf8OrThrow() : ByteArray { + @Suppress("DEPRECATION_ERROR") + return this.toUtf8OrThrow(0, this.length) +} + +/** + * Converts a [String] into an UTF-8 array. + * @throws [IllegalCharacterConversionException] if the input is invalid. + */ +@Deprecated( + "Use encodeToByteArray instead", + ReplaceWith("encodeToByteArray(start, start + size, throwOnInvalidSequence = true)"), + DeprecationLevel.ERROR +) +public fun String.toUtf8OrThrow(start: Int = 0, size: Int = this.length) : ByteArray { + checkBoundsIndexes(start, start + size, this.length) + try { + return unsafeStringToUtf8OrThrow(start, size) + } catch (e: CharacterCodingException) { + @Suppress("DEPRECATION_ERROR") + throw IllegalCharacterConversionException() + } +} + +internal fun checkBoundsIndexes(startIndex: Int, endIndex: Int, size: Int) { + if (startIndex < 0 || endIndex > size) { + throw IndexOutOfBoundsException("startIndex: $startIndex, endIndex: $endIndex, size: $size") + } + if (startIndex > endIndex) { + throw IllegalArgumentException("startIndex: $startIndex > endIndex: $endIndex") + } +} + +internal fun insertString(array: CharArray, start: Int, value: String): Int = + insertString(array, start, value, 0, value.length) + +@SymbolName("Kotlin_ByteArray_unsafeStringFromUtf8") +internal external fun ByteArray.unsafeStringFromUtf8(start: Int, size: Int) : String + +@SymbolName("Kotlin_ByteArray_unsafeStringFromUtf8OrThrow") +internal external fun ByteArray.unsafeStringFromUtf8OrThrow(start: Int, size: Int) : String + +@SymbolName("Kotlin_String_unsafeStringToUtf8") +internal external fun String.unsafeStringToUtf8(start: Int, size: Int) : ByteArray + +@SymbolName("Kotlin_String_unsafeStringToUtf8OrThrow") +internal external fun String.unsafeStringToUtf8OrThrow(start: Int, size: Int) : ByteArray + +@SymbolName("Kotlin_String_unsafeStringFromCharArray") +internal external fun unsafeStringFromCharArray(array: CharArray, start: Int, size: Int) : String + +@SymbolName("Kotlin_StringBuilder_insertString") +internal external fun insertString(array: CharArray, distIndex: Int, value: String, sourceIndex: Int, count: Int): Int + +@SymbolName("Kotlin_StringBuilder_insertInt") +internal external fun insertInt(array: CharArray, start: Int, value: Int): Int \ No newline at end of file diff --git a/kotlin-native/runtime/src/main/kotlin/kotlin/native/ThrowableExtensions.kt b/kotlin-native/runtime/src/main/kotlin/kotlin/native/ThrowableExtensions.kt new file mode 100644 index 00000000000..57d4548effd --- /dev/null +++ b/kotlin-native/runtime/src/main/kotlin/kotlin/native/ThrowableExtensions.kt @@ -0,0 +1,12 @@ +/* + * Copyright 2010-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ +package kotlin.native + +/** + * Returns a list of stack trace addresses representing the stack trace + * pertaining to this throwable. + */ +public fun Throwable.getStackTraceAddresses(): List = + this.getStackTraceAddressesInternal() diff --git a/kotlin-native/runtime/src/main/kotlin/kotlin/native/TypedArrays.kt b/kotlin-native/runtime/src/main/kotlin/kotlin/native/TypedArrays.kt new file mode 100644 index 00000000000..e8f51a49631 --- /dev/null +++ b/kotlin-native/runtime/src/main/kotlin/kotlin/native/TypedArrays.kt @@ -0,0 +1,158 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ +package kotlin.native + +import kotlin.native.SymbolName + +/** + * Those operations allows to extract primitive values out of the [ByteArray] byte buffers. + * Data is treated as if it was in Least-Significant-Byte first (little-endian) byte order. + * If index is outside of array boundaries - [ArrayIndexOutOfBoundsException] is thrown. + */ + +/** + * Gets [UByte] out of the [ByteArray] byte buffer at specified index [index] + * @throws ArrayIndexOutOfBoundsException if [index] is outside of array boundaries. + */ +@ExperimentalUnsignedTypes +public fun ByteArray.getUByteAt(index: Int): UByte = UByte(get(index)) + +/** + * Gets [Char] out of the [ByteArray] byte buffer at specified index [index] + * @throws ArrayIndexOutOfBoundsException if [index] is outside of array boundaries. + */ +@SymbolName("Kotlin_ByteArray_getCharAt") +public external fun ByteArray.getCharAt(index: Int): Char + +/** + * Gets [Short] out of the [ByteArray] byte buffer at specified index [index] + * @throws ArrayIndexOutOfBoundsException if [index] is outside of array boundaries. + */ +@SymbolName("Kotlin_ByteArray_getShortAt") +public external fun ByteArray.getShortAt(index: Int): Short + +/** + * Gets [UShort] out of the [ByteArray] byte buffer at specified index [index] + * @throws ArrayIndexOutOfBoundsException if [index] is outside of array boundaries. + */ +@SymbolName("Kotlin_ByteArray_getShortAt") +@ExperimentalUnsignedTypes +public external fun ByteArray.getUShortAt(index: Int): UShort + +/** + * Gets [Int] out of the [ByteArray] byte buffer at specified index [index] + * @throws ArrayIndexOutOfBoundsException if [index] is outside of array boundaries. + */ +@SymbolName("Kotlin_ByteArray_getIntAt") +public external fun ByteArray.getIntAt(index: Int): Int + +/** + * Gets [UInt] out of the [ByteArray] byte buffer at specified index [index] + * @throws ArrayIndexOutOfBoundsException if [index] is outside of array boundaries. + */ +@SymbolName("Kotlin_ByteArray_getIntAt") +@ExperimentalUnsignedTypes +public external fun ByteArray.getUIntAt(index: Int): UInt + +/** + * Gets [Long] out of the [ByteArray] byte buffer at specified index [index] + * @throws ArrayIndexOutOfBoundsException if [index] is outside of array boundaries. + */ +@SymbolName("Kotlin_ByteArray_getLongAt") +public external fun ByteArray.getLongAt(index: Int): Long + +/** + * Gets [ULong] out of the [ByteArray] byte buffer at specified index [index] + * @throws ArrayIndexOutOfBoundsException if [index] is outside of array boundaries. + */ +@SymbolName("Kotlin_ByteArray_getLongAt") +@ExperimentalUnsignedTypes +public external fun ByteArray.getULongAt(index: Int): ULong + +/** + * Gets [Float] out of the [ByteArray] byte buffer at specified index [index] + * @throws ArrayIndexOutOfBoundsException if [index] is outside of array boundaries. + */ +@SymbolName("Kotlin_ByteArray_getFloatAt") +public external fun ByteArray.getFloatAt(index: Int): Float + +/** + * Gets [Double] out of the [ByteArray] byte buffer at specified index [index] + * @throws ArrayIndexOutOfBoundsException if [index] is outside of array boundaries. + */ +@SymbolName("Kotlin_ByteArray_getDoubleAt") +public external fun ByteArray.getDoubleAt(index: Int): Double + +/** + * Sets [UByte] out of the [ByteArray] byte buffer at specified index [index] + * @throws ArrayIndexOutOfBoundsException if [index] is outside of array boundaries. + */ +@SymbolName("Kotlin_ByteArray_set") +public external fun ByteArray.setUByteAt(index: Int, value: UByte) + +/** + * Sets [Char] out of the [ByteArray] byte buffer at specified index [index] + * @throws ArrayIndexOutOfBoundsException if [index] is outside of array boundaries. + */ +@SymbolName("Kotlin_ByteArray_setCharAt") +public external fun ByteArray.setCharAt(index: Int, value: Char) + +/** + * Sets [Short] out of the [ByteArray] byte buffer at specified index [index] + * @throws ArrayIndexOutOfBoundsException if [index] is outside of array boundaries. + */ +@SymbolName("Kotlin_ByteArray_setShortAt") +public external fun ByteArray.setShortAt(index: Int, value: Short) + +/** + * Sets [UShort] out of the [ByteArray] byte buffer at specified index [index] + * @throws ArrayIndexOutOfBoundsException if [index] is outside of array boundaries. + */ +@SymbolName("Kotlin_ByteArray_setShortAt") +@ExperimentalUnsignedTypes +public external fun ByteArray.setUShortAt(index: Int, value: UShort) + +/** + * Sets [Int] out of the [ByteArray] byte buffer at specified index [index] + * @throws ArrayIndexOutOfBoundsException if [index] is outside of array boundaries. + */ +@SymbolName("Kotlin_ByteArray_setIntAt") +public external fun ByteArray.setIntAt(index: Int, value: Int) + +/** + * Sets [UInt] out of the [ByteArray] byte buffer at specified index [index] + * @throws ArrayIndexOutOfBoundsException if [index] is outside of array boundaries. + */ +@SymbolName("Kotlin_ByteArray_setIntAt") +public external fun ByteArray.setUIntAt(index: Int, value: UInt) + +/** + * Sets [Long] out of the [ByteArray] byte buffer at specified index [index] + * @throws ArrayIndexOutOfBoundsException if [index] is outside of array boundaries. + */ +@SymbolName("Kotlin_ByteArray_setLongAt") +public external fun ByteArray.setLongAt(index: Int, value: Long) + +/** + * Sets [ULong] out of the [ByteArray] byte buffer at specified index [index] + * @throws ArrayIndexOutOfBoundsException if [index] is outside of array boundaries. + */ +@SymbolName("Kotlin_ByteArray_setLongAt") +@ExperimentalUnsignedTypes +public external fun ByteArray.setULongAt(index: Int, value: ULong) + +/** + * Sets [Float] out of the [ByteArray] byte buffer at specified index [index] + * @throws ArrayIndexOutOfBoundsException if [index] is outside of array boundaries. + */ +@SymbolName("Kotlin_ByteArray_setFloatAt") +public external fun ByteArray.setFloatAt(index: Int, value: Float) + +/** + * Sets [Double] out of the [ByteArray] byte buffer at specified index [index] + * @throws ArrayIndexOutOfBoundsException if [index] is outside of array boundaries. + */ +@SymbolName("Kotlin_ByteArray_setDoubleAt") +public external fun ByteArray.setDoubleAt(index: Int, value: Double) diff --git a/kotlin-native/runtime/src/main/kotlin/kotlin/native/concurrent/Annotations.kt b/kotlin-native/runtime/src/main/kotlin/kotlin/native/concurrent/Annotations.kt new file mode 100644 index 00000000000..e7db20f1110 --- /dev/null +++ b/kotlin-native/runtime/src/main/kotlin/kotlin/native/concurrent/Annotations.kt @@ -0,0 +1,33 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +package kotlin.native.concurrent + +/** + * Marks a top level property with a backing field or an object as thread local. + * The object remains mutable and it is possible to change its state, + * but every thread will have a distinct copy of this object, + * so changes in one thread are not reflected in another. + * + * The annotation has effect only in Kotlin/Native platform. + * + * PLEASE NOTE THAT THIS ANNOTATION MAY GO AWAY IN UPCOMING RELEASES. + */ +@Target(AnnotationTarget.PROPERTY, AnnotationTarget.CLASS) +@Retention(AnnotationRetention.BINARY) +public actual annotation class ThreadLocal + +/** + * Marks a top level property with a backing field as immutable. + * It is possible to share the value of such property between multiple threads, but it becomes deeply frozen, + * so no changes can be made to its state or the state of objects it refers to. + * + * The annotation has effect only in Kotlin/Native platform. + * + * PLEASE NOTE THAT THIS ANNOTATION MAY GO AWAY IN UPCOMING RELEASES. + */ +@Target(AnnotationTarget.PROPERTY) +@Retention(AnnotationRetention.BINARY) +public actual annotation class SharedImmutable \ No newline at end of file diff --git a/kotlin-native/runtime/src/main/kotlin/kotlin/native/concurrent/Atomics.kt b/kotlin-native/runtime/src/main/kotlin/kotlin/native/concurrent/Atomics.kt new file mode 100644 index 00000000000..ed6ff354af8 --- /dev/null +++ b/kotlin-native/runtime/src/main/kotlin/kotlin/native/concurrent/Atomics.kt @@ -0,0 +1,382 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +package kotlin.native.concurrent + +import kotlin.native.internal.ExportTypeInfo +import kotlin.native.internal.Frozen +import kotlin.native.internal.LeakDetectorCandidate +import kotlin.native.internal.NoReorderFields +import kotlin.native.SymbolName +import kotlinx.cinterop.NativePtr + +/** + * Atomic values and freezing: atomics [AtomicInt], [AtomicLong], [AtomicNativePtr] and [AtomicReference] + * are unique types with regard to freezing. Namely, they provide mutating operations, while can participate + * in frozen subgraphs. So shared frozen objects can have fields of atomic types. + */ +@Frozen +public class AtomicInt(private var value_: Int) { + /** + * The value being held by this class. + */ + public var value: Int + get() = getImpl() + set(new) = setImpl(new) + + /** + * Increments the value by [delta] and returns the new value. + * + * @param delta the value to add + * @return the new value + */ + @SymbolName("Kotlin_AtomicInt_addAndGet") + external public fun addAndGet(delta: Int): Int + + /** + * Compares value with [expected] and replaces it with [new] value if values matches. + * + * @param expected the expected value + * @param new the new value + * @return the old value + */ + @SymbolName("Kotlin_AtomicInt_compareAndSwap") + external public fun compareAndSwap(expected: Int, new: Int): Int + + /** + * Compares value with [expected] and replaces it with [new] value if values matches. + * + * @param expected the expected value + * @param new the new value + * @return true if successful + */ + @SymbolName("Kotlin_AtomicInt_compareAndSet") + external public fun compareAndSet(expected: Int, new: Int): Boolean + + /** + * Increments value by one. + */ + public fun increment(): Unit { + addAndGet(1) + } + + /** + * Decrements value by one. + */ + public fun decrement(): Unit { + addAndGet(-1) + } + + /** + * Returns the string representation of this object. + * + * @return the string representation + */ + public override fun toString(): String = value.toString() + + // Implementation details. + @SymbolName("Kotlin_AtomicInt_set") + private external fun setImpl(new: Int): Unit + + @SymbolName("Kotlin_AtomicInt_get") + private external fun getImpl(): Int +} + +@Frozen +public class AtomicLong(private var value_: Long = 0) { + /** + * The value being held by this class. + */ + public var value: Long + get() = getImpl() + set(new) = setImpl(new) + + /** + * Increments the value by [delta] and returns the new value. + * + * @param delta the value to add + * @return the new value + */ + @SymbolName("Kotlin_AtomicLong_addAndGet") + external public fun addAndGet(delta: Long): Long + + /** + * Increments the value by [delta] and returns the new value. + * + * @param delta the value to add + * @return the new value + */ + public fun addAndGet(delta: Int): Long = addAndGet(delta.toLong()) + + /** + * Compares value with [expected] and replaces it with [new] value if values matches. + * + * @param expected the expected value + * @param new the new value + * @return the old value + */ + @SymbolName("Kotlin_AtomicLong_compareAndSwap") + external public fun compareAndSwap(expected: Long, new: Long): Long + + /** + * Compares value with [expected] and replaces it with [new] value if values matches. + * + * @param expected the expected value + * @param new the new value + * @return true if successful, false if state is unchanged + */ + @SymbolName("Kotlin_AtomicLong_compareAndSet") + external public fun compareAndSet(expected: Long, new: Long): Boolean + + /** + * Increments value by one. + */ + public fun increment(): Unit { + addAndGet(1L) + } + + /** + * Decrements value by one. + */ + fun decrement(): Unit { + addAndGet(-1L) + } + + /** + * Returns the string representation of this object. + * + * @return the string representation of this object + */ + public override fun toString(): String = value.toString() + + // Implementation details. + @SymbolName("Kotlin_AtomicLong_set") + private external fun setImpl(new: Long): Unit + + @SymbolName("Kotlin_AtomicLong_get") + private external fun getImpl(): Long +} + +@Frozen +public class AtomicNativePtr(private var value_: NativePtr) { + /** + * The value being held by this class. + */ + public var value: NativePtr + get() = getImpl() + set(new) = setImpl(new) + + /** + * Compares value with [expected] and replaces it with [new] value if values matches. + * If [new] value is not null, it must be frozen or permanent object. + * + * @param expected the expected value + * @param new the new value + * @throws InvalidMutabilityException if [new] is not frozen or a permanent object + * @return the old value + */ + @SymbolName("Kotlin_AtomicNativePtr_compareAndSwap") + external public fun compareAndSwap(expected: NativePtr, new: NativePtr): NativePtr + + /** + * Compares value with [expected] and replaces it with [new] value if values matches. + * + * @param expected the expected value + * @param new the new value + * @return true if successful + */ + @SymbolName("Kotlin_AtomicNativePtr_compareAndSet") + external public fun compareAndSet(expected: NativePtr, new: NativePtr): Boolean + + /** + * Returns the string representation of this object. + * + * @return string representation of this object + */ + public override fun toString(): String = value.toString() + + // Implementation details. + @SymbolName("Kotlin_AtomicNativePtr_set") + private external fun setImpl(new: NativePtr): Unit + + @SymbolName("Kotlin_AtomicNativePtr_get") + private external fun getImpl(): NativePtr +} + + +private fun idString(value: Any) = "${value.hashCode().toUInt().toString(16)}" + +private fun debugString(value: Any?): String { + if (value == null) return "null" + return "${value::class.qualifiedName}: ${idString(value)}" +} + +/** + * An atomic reference to a frozen Kotlin object. Can be used in concurrent scenarious + * but frequently shall be of nullable type and be zeroed out once no longer needed. + * Otherwise memory leak could happen. To detect such leaks [kotlin.native.internal.GC.detectCycles] + * in debug mode could be helpful. + */ +@Frozen +@LeakDetectorCandidate +@NoReorderFields +public class AtomicReference { + private var value_: T + + // A spinlock to fix potential ARC race. + private var lock: Int = 0 + + // Optimization for speeding up access. + private var cookie: Int = 0 + + /** + * Creates a new atomic reference pointing to given [ref]. + * @throws InvalidMutabilityException if reference is not frozen. + */ + constructor(value: T) { + checkIfFrozen(value) + value_ = value + } + + /** + * The referenced value. + * Gets the value or sets the [new] value. If [new] value is not null, + * it must be frozen or permanent object. + * + * @throws InvalidMutabilityException if the value is not frozen or a permanent object + */ + public var value: T + get() = @Suppress("UNCHECKED_CAST")(getImpl() as T) + set(new) = setImpl(new) + + /** + * Compares value with [expected] and replaces it with [new] value if values matches. + * Note that comparison is identity-based, not value-based. + * If [new] value is not null, it must be frozen or permanent object. + * + * @param expected the expected value + * @param new the new value + * @throws InvalidMutabilityException if the value is not frozen or a permanent object + * @return the old value + */ + @SymbolName("Kotlin_AtomicReference_compareAndSwap") + external public fun compareAndSwap(expected: T, new: T): T + + /** + * Compares value with [expected] and replaces it with [new] value if values matches. + * Note that comparison is identity-based, not value-based. + * + * @param expected the expected value + * @param new the new value + * @return true if successful + */ + @SymbolName("Kotlin_AtomicReference_compareAndSet") + external public fun compareAndSet(expected: T, new: T): Boolean + + /** + * Returns the string representation of this object. + * + * @return string representation of this object + */ + public override fun toString(): String = + "${debugString(this)} -> ${debugString(value)}" + + // Implementation details. + @SymbolName("Kotlin_AtomicReference_set") + private external fun setImpl(new: Any?): Unit + + @SymbolName("Kotlin_AtomicReference_get") + private external fun getImpl(): Any? +} + +/** + * An atomic reference to a Kotlin object. Can be used in concurrent scenarious, but must be frozen first, + * otherwise behaves as regular box for the value. If frozen, shall be zeroed out once no longer needed. + * Otherwise memory leak could happen. To detect such leaks [kotlin.native.internal.GC.detectCycles] + * in debug mode could be helpful. + */ +@NoReorderFields +@LeakDetectorCandidate +@ExportTypeInfo("theFreezableAtomicReferenceTypeInfo") +public class FreezableAtomicReference(private var value_: T) { + // A spinlock to fix potential ARC race. + private var lock: Int = 0 + + // Optimization for speeding up access. + private var cookie: Int = 0 + + /** + * The referenced value. + * Gets the value or sets the [new] value. If [new] value is not null, + * and `this` is frozen - it must be frozen or permanent object. + * + * @throws InvalidMutabilityException if the value is not frozen or a permanent object + */ + public var value: T + get() = @Suppress("UNCHECKED_CAST")(getImpl() as T) + set(new) { + if (this.isFrozen) + setImpl(new) + else + value_ = new + } + + /** + * Compares value with [expected] and replaces it with [new] value if values matches. + * If [new] value is not null and object is frozen, it must be frozen or permanent object. + * + * @param expected the expected value + * @param new the new value + * @throws InvalidMutabilityException if the value is not frozen or a permanent object + * @return the old value + */ + public fun compareAndSwap(expected: T, new: T): T { + return if (this.isFrozen) @Suppress("UNCHECKED_CAST")(compareAndSwapImpl(expected, new) as T) else { + val old = value_ + if (old === expected) value_ = new + old + } + } + + /** + * Compares value with [expected] and replaces it with [new] value if values matches. + * Note that comparison is identity-based, not value-based. + * + * @param expected the expected value + * @param new the new value + * @return true if successful + */ + public fun compareAndSet(expected: T, new: T): Boolean { + if (this.isFrozen) return compareAndSetImpl(expected, new) + val old = value_ + if (old === expected) { + value_ = new + return true + } else { + return false + } + } + + /** + * Returns the string representation of this object. + * + * @return string representation of this object + */ + public override fun toString(): String = + "${debugString(this)} -> ${debugString(value)}" + + // Implementation details. + @SymbolName("Kotlin_AtomicReference_set") + private external fun setImpl(new: Any?): Unit + + @SymbolName("Kotlin_AtomicReference_get") + private external fun getImpl(): Any? + + @SymbolName("Kotlin_AtomicReference_compareAndSwap") + private external fun compareAndSwapImpl(expected: Any?, new: Any?): Any? + + @SymbolName("Kotlin_AtomicReference_compareAndSet") + private external fun compareAndSetImpl(expected: Any?, new: Any?): Boolean +} diff --git a/kotlin-native/runtime/src/main/kotlin/kotlin/native/concurrent/Continuation.kt b/kotlin-native/runtime/src/main/kotlin/kotlin/native/concurrent/Continuation.kt new file mode 100644 index 00000000000..44d671ed819 --- /dev/null +++ b/kotlin-native/runtime/src/main/kotlin/kotlin/native/concurrent/Continuation.kt @@ -0,0 +1,110 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +package kotlin.native.concurrent + +import kotlin.native.internal.* +import kotlinx.cinterop.* + +public class Continuation0(block: () -> Unit, + private val invoker: CPointer Unit>>, + private val singleShot: Boolean = false): Function0 { + + private val stable = StableRef.create(block) + + init { + freeze() + } + + public override operator fun invoke() { + invoker(stable.asCPointer()) + if (singleShot) { + stable.dispose() + } + } + + public fun dispose() { + assert(!singleShot) + stable.dispose() + } +} + +public class Continuation1( + block: (p1: T1) -> Unit, + private val invoker: CPointer Unit>>, + private val singleShot: Boolean = false) : Function1 { + + private val stable = StableRef.create(block) + + init { + freeze() + } + + public override operator fun invoke(p1: T1) { + require(p1.isFrozen) + + val args = StableRef.create(Pair(stable, p1).freeze()) + try { + invoker(args.asCPointer()) + } finally { + args.dispose() + } + if (singleShot) { + stable.dispose() + } + } + + public fun dispose() { + assert(!singleShot) + stable.dispose() + } +} + +public class Continuation2( + block: (p1: T1, p2: T2) -> Unit, + private val invoker: CPointer Unit>>, + private val singleShot: Boolean = false) : Function2 { + + private val stable = StableRef.create(block) + + init { + freeze() + } + + public override operator fun invoke(p1: T1, p2: T2) { + require(p1.isFrozen) + require(p2.isFrozen) + + val args = StableRef.create(Triple(stable, p1, p2).freeze()) + try { + invoker(args.asCPointer()) + } finally { + args.dispose() + } + if (singleShot) { + stable.dispose() + } + } + + fun dispose() { + assert(!singleShot) + stable.dispose() + } +} + +public fun COpaquePointer.callContinuation0() { + val single = this.asStableRef<() -> Unit>() + single.get()() +} + +public fun COpaquePointer.callContinuation1() { + val pair = this.asStableRef Unit>, T1>>().get() + pair.first.get()(pair.second) +} + +public fun COpaquePointer.callContinuation2() { + val triple = this.asStableRef Unit>, T1, T2>>().get() + triple.first.get()(triple.second, triple.third) +} diff --git a/kotlin-native/runtime/src/main/kotlin/kotlin/native/concurrent/Freezing.kt b/kotlin-native/runtime/src/main/kotlin/kotlin/native/concurrent/Freezing.kt new file mode 100644 index 00000000000..4b3f326358f --- /dev/null +++ b/kotlin-native/runtime/src/main/kotlin/kotlin/native/concurrent/Freezing.kt @@ -0,0 +1,53 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +package kotlin.native.concurrent + +/** + * Exception thrown whenever freezing is not possible. + * + * @param toFreeze an object intended to be frozen. + * @param blocker an object preventing freezing, usually one marked with [ensureNeverFrozen] earlier. + */ +public class FreezingException(toFreeze: Any, blocker: Any) : + RuntimeException("freezing of $toFreeze has failed, first blocker is $blocker") + +/** + * Exception thrown whenever we attempt to mutate frozen objects. + * + * @param where a frozen object that was attempted to mutate + */ +public class InvalidMutabilityException(message: String) : RuntimeException(message) + +/** + * Freezes object subgraph reachable from this object. Frozen objects can be freely + * shared between threads/workers. + * + * @throws FreezingException if freezing is not possible + * @return the object itself + * @see ensureNeverFrozen + */ +public fun T.freeze(): T { + freezeInternal(this) + return this +} + +/** + * Checks if given object is null or frozen or permanent (i.e. instantiated at compile-time). + * + * @return true if given object is null or frozen or permanent + */ +public val Any?.isFrozen + get() = isFrozenInternal(this) + +/** + * This function ensures that if we see such an object during freezing attempt - freeze fails and + * [FreezingException] is thrown. + * + * @throws FreezingException thrown immediately if this object is already frozen + * @see freeze + */ +@SymbolName("Kotlin_Worker_ensureNeverFrozen") +public external fun Any.ensureNeverFrozen() \ No newline at end of file diff --git a/kotlin-native/runtime/src/main/kotlin/kotlin/native/concurrent/Future.kt b/kotlin-native/runtime/src/main/kotlin/kotlin/native/concurrent/Future.kt new file mode 100644 index 00000000000..218c6730ff9 --- /dev/null +++ b/kotlin-native/runtime/src/main/kotlin/kotlin/native/concurrent/Future.kt @@ -0,0 +1,104 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +package kotlin.native.concurrent + +import kotlin.native.internal.Frozen + +/** + * State of the future object. + */ +enum class FutureState(val value: Int) { + INVALID(0), + /** Future is scheduled for execution. */ + SCHEDULED(1), + /** Future result is computed. */ + COMPUTED(2), + /** Future is cancelled. */ + CANCELLED(3), + /** Computation thrown an exception. */ + THROWN(4) +} + +/** + * Class representing abstract computation, whose result may become available in the future. + */ +@Suppress("NON_PUBLIC_PRIMARY_CONSTRUCTOR_OF_INLINE_CLASS") +public inline class Future @PublishedApi internal constructor(val id: Int) { + /** + * Blocks execution until the future is ready. + * + * @return the execution result of [code] consumed future's computaiton + * @throws IllegalStateException if future is in [FutureState.INVALID], [FutureState.CANCELLED] or + * [FutureState.THROWN] state + */ + public inline fun consume(code: (T) -> R): R = when (state) { + FutureState.SCHEDULED, FutureState.COMPUTED -> { + val value = @Suppress("UNCHECKED_CAST", "NON_PUBLIC_CALL_FROM_PUBLIC_INLINE") + (consumeFuture(id) as T) + code(value) + } + FutureState.INVALID -> + throw IllegalStateException("Future is in an invalid state") + FutureState.CANCELLED -> { + consumeFuture(id) + throw IllegalStateException("Future is cancelled") + } + FutureState.THROWN -> { + consumeFuture(id) + throw IllegalStateException("Job has thrown an exception") + } + } + + /** + * The result of the future computation. + * Blocks execution until the future is ready. Second attempt to get will result in an error. + */ + public val result: T + get() = consume { it -> it } + + /** + * A [FutureState] of this future + */ + public val state: FutureState + get() = FutureState.values()[stateOfFuture(id)] + + override public fun toString(): String = "future $id" +} + + +@Deprecated("Use 'waitForMultipleFutures' top-level function instead", ReplaceWith("waitForMultipleFutures(this, millis)"), DeprecationLevel.ERROR) +public fun Collection>.waitForMultipleFutures(millis: Int): Set> = waitForMultipleFutures(this, millis) + + +/** + * Wait for availability of futures in the collection. Returns set with all futures which have + * value available for the consumption, i.e. [FutureState.COMPUTED]. + * + * @param timeoutMillis the amount of time in milliseconds to wait for the computed future + */ +public fun waitForMultipleFutures(futures: Collection>, timeoutMillis: Int): Set> { + val result = mutableSetOf>() + + while (true) { + val versionToken = versionToken() + for (future in futures) { + if (future.state == FutureState.COMPUTED) { + result += future + } + } + if (result.isNotEmpty()) return result + + if (waitForAnyFuture(versionToken, timeoutMillis)) break + } + + for (future in futures) { + if (future.state == FutureState.COMPUTED) { + result += future + } + } + + return result +} \ No newline at end of file diff --git a/kotlin-native/runtime/src/main/kotlin/kotlin/native/concurrent/Internal.kt b/kotlin-native/runtime/src/main/kotlin/kotlin/native/concurrent/Internal.kt new file mode 100644 index 00000000000..0d13130f25b --- /dev/null +++ b/kotlin-native/runtime/src/main/kotlin/kotlin/native/concurrent/Internal.kt @@ -0,0 +1,107 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +package kotlin.native.concurrent + +import kotlin.native.internal.DescribeObjectForDebugging +import kotlin.native.internal.ExportForCppRuntime +import kotlin.native.internal.InternalForKotlinNative +import kotlin.native.internal.debugDescription +import kotlin.native.identityHashCode +import kotlin.reflect.KClass +import kotlinx.cinterop.* + +// Implementation details. + +@SymbolName("Kotlin_Worker_stateOfFuture") +external internal fun stateOfFuture(id: Int): Int + +@SymbolName("Kotlin_Worker_consumeFuture") +@PublishedApi +external internal fun consumeFuture(id: Int): Any? + +@SymbolName("Kotlin_Worker_waitForAnyFuture") +external internal fun waitForAnyFuture(versionToken: Int, millis: Int): Boolean + +@SymbolName("Kotlin_Worker_versionToken") +external internal fun versionToken(): Int + +@kotlin.native.internal.ExportForCompiler +internal fun executeImpl(worker: Worker, mode: TransferMode, producer: () -> Any?, + job: CPointer>): Future = + Future(executeInternal(worker.id, mode.value, producer, job)) + +@SymbolName("Kotlin_Worker_startInternal") +external internal fun startInternal(errorReporting: Boolean, name: String?): Int + +@SymbolName("Kotlin_Worker_currentInternal") +external internal fun currentInternal(): Int + +@SymbolName("Kotlin_Worker_requestTerminationWorkerInternal") +external internal fun requestTerminationInternal(id: Int, processScheduledJobs: Boolean): Int + +@SymbolName("Kotlin_Worker_executeInternal") +external internal fun executeInternal( + id: Int, mode: Int, producer: () -> Any?, job: CPointer>): Int + +@SymbolName("Kotlin_Worker_executeAfterInternal") +external internal fun executeAfterInternal(id: Int, operation: () -> Unit, afterMicroseconds: Long): Unit + +@SymbolName("Kotlin_Worker_processQueueInternal") +external internal fun processQueueInternal(id: Int): Boolean + +@SymbolName("Kotlin_Worker_parkInternal") +external internal fun parkInternal(id: Int, timeoutMicroseconds: Long, process: Boolean): Boolean + +@SymbolName("Kotlin_Worker_getNameInternal") +external internal fun getWorkerNameInternal(id: Int): String? + +@ExportForCppRuntime +internal fun ThrowWorkerUnsupported(): Unit = + throw UnsupportedOperationException("Workers are not supported") + +@ExportForCppRuntime +internal fun ThrowWorkerInvalidState(): Unit = + throw IllegalStateException("Illegal transfer state") + +@ExportForCppRuntime +internal fun WorkerLaunchpad(function: () -> Any?) = function() + +@PublishedApi +@SymbolName("Kotlin_Worker_detachObjectGraphInternal") +external internal fun detachObjectGraphInternal(mode: Int, producer: () -> Any?): NativePtr + +@PublishedApi +@SymbolName("Kotlin_Worker_attachObjectGraphInternal") +external internal fun attachObjectGraphInternal(stable: NativePtr): Any? + +@SymbolName("Kotlin_Worker_freezeInternal") +internal external fun freezeInternal(it: Any?) + +@SymbolName("Kotlin_Worker_isFrozenInternal") +internal external fun isFrozenInternal(it: Any?): Boolean + +@ExportForCppRuntime +internal fun ThrowFreezingException(toFreeze: Any, blocker: Any): Nothing = + throw FreezingException(toFreeze, blocker) + +@ExportForCppRuntime +internal fun ThrowInvalidMutabilityException(where: Any): Nothing { + val description = debugDescription(where::class, where.identityHashCode()) + throw InvalidMutabilityException("mutation attempt of frozen $description") +} + +@ExportForCppRuntime +internal fun ThrowIllegalObjectSharingException(typeInfo: NativePtr, address: NativePtr) { + val description = DescribeObjectForDebugging(typeInfo, address) + throw IncorrectDereferenceException("illegal attempt to access non-shared $description from other thread") +} + +@SymbolName("Kotlin_AtomicReference_checkIfFrozen") +external internal fun checkIfFrozen(ref: Any?) + +@InternalForKotlinNative +@SymbolName("Kotlin_Worker_waitTermination") +external public fun waitWorkerTermination(worker: Worker) diff --git a/kotlin-native/runtime/src/main/kotlin/kotlin/native/concurrent/Lazy.kt b/kotlin-native/runtime/src/main/kotlin/kotlin/native/concurrent/Lazy.kt new file mode 100644 index 00000000000..767d8d2f17c --- /dev/null +++ b/kotlin-native/runtime/src/main/kotlin/kotlin/native/concurrent/Lazy.kt @@ -0,0 +1,121 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +package kotlin.native.concurrent + +import kotlin.native.internal.Frozen + +internal class FreezeAwareLazyImpl(initializer: () -> T) : Lazy { + private val value_ = FreezableAtomicReference(UNINITIALIZED) + private var initializer_: (() -> T)? = initializer + private val lock_ = Lock() + + private fun getOrInit(doFreeze: Boolean): T { + var result = value_.value + if (result !== UNINITIALIZED) { + if (result === INITIALIZING) { + value_.value = UNINITIALIZED + throw IllegalStateException("Recursive lazy computation") + } + @Suppress("UNCHECKED_CAST") + return result as T + } + // Set value_ to INITIALIZING. + value_.value = INITIALIZING + try { + result = initializer_!!() + if (doFreeze) result.freeze() + } catch (throwable: Throwable) { + value_.value = UNINITIALIZED + throw throwable + } + if (!doFreeze) { + if (this.isFrozen) { + value_.value = UNINITIALIZED + throw InvalidMutabilityException("Frozen during lazy computation") + } + // Clear initializer. + initializer_ = null + } + // Set value_ to actual one. + value_.value = result + @Suppress("UNCHECKED_CAST") + return result as T + } + + override val value: T + get() { + return if (isFrozen) { + locked(lock_) { + getOrInit(true) + } + } else { + getOrInit(false) + } + } + + /** + * This operation on shared objects may return value which is no longer reflect the current state of lazy. + */ + override fun isInitialized(): Boolean = (value_.value !== UNINITIALIZED) && (value_.value !== INITIALIZING) + + override fun toString(): String = if (isInitialized()) + value.toString() else "Lazy value not initialized yet" +} + +internal object UNINITIALIZED { + // So that single-threaded configs can use those as well. + init { + freeze() + } +} + +internal object INITIALIZING { + // So that single-threaded configs can use those as well. + init { + freeze() + } +} + +@Frozen +internal class AtomicLazyImpl(initializer: () -> T) : Lazy { + private val initializer_ = AtomicReference?>(initializer.freeze()) + private val value_ = AtomicReference(UNINITIALIZED) + + override val value: T + get() { + if (value_.compareAndSwap(UNINITIALIZED, INITIALIZING) === UNINITIALIZED) { + // We execute exclusively here. + val ctor = initializer_.value + if (ctor != null && initializer_.compareAndSet(ctor, null)) { + value_.compareAndSet(INITIALIZING, ctor().freeze()) + } else { + // Something wrong. + assert(false) + } + } + var result: Any? + do { + result = value_.value + } while (result === INITIALIZING) + + assert(result !== UNINITIALIZED && result !== INITIALIZING) + @Suppress("UNCHECKED_CAST") + return result as T + } + + override fun isInitialized(): Boolean = value_.value !== UNINITIALIZED + + override fun toString(): String = if (isInitialized()) + value_.value.toString() else "Lazy value not initialized yet." +} + +/** + * Atomic lazy initializer, could be used in frozen objects, freezes initializing lambda, + * so use very carefully. Also, as with other uses of an [AtomicReference] may potentially + * leak memory, so it is recommended to use `atomicLazy` in cases of objects living forever, + * such as object signletons, or in cases where it's guaranteed not to have cyclical garbage. + */ +public fun atomicLazy(initializer: () -> T): Lazy = AtomicLazyImpl(initializer) \ No newline at end of file diff --git a/kotlin-native/runtime/src/main/kotlin/kotlin/native/concurrent/Lock.kt b/kotlin-native/runtime/src/main/kotlin/kotlin/native/concurrent/Lock.kt new file mode 100644 index 00000000000..84d2c5bf083 --- /dev/null +++ b/kotlin-native/runtime/src/main/kotlin/kotlin/native/concurrent/Lock.kt @@ -0,0 +1,58 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +package kotlin.native.concurrent + +import kotlin.native.internal.Frozen + +@ThreadLocal +private object CurrentThread { + val id = Any().freeze() +} + +@Frozen +internal class Lock { + private val locker_ = AtomicInt(0) + private val reenterCount_ = AtomicInt(0) + + // TODO: make it properly reschedule instead of spinning. + fun lock() { + val lockData = CurrentThread.id.hashCode() + loop@ do { + val old = locker_.compareAndSwap(0, lockData) + when (old) { + lockData -> { + // Was locked by us already. + reenterCount_.increment() + break@loop + } + 0 -> { + // We just got the lock. + assert(reenterCount_.value == 0) + break@loop + } + } + } while (true) + } + + fun unlock() { + if (reenterCount_.value > 0) { + reenterCount_.decrement() + } else { + val lockData = CurrentThread.id.hashCode() + val old = locker_.compareAndSwap(lockData, 0) + assert(old == lockData) + } + } +} + +internal inline fun locked(lock: Lock, block: () -> R): R { + lock.lock() + try { + return block() + } finally { + lock.unlock() + } +} \ No newline at end of file diff --git a/kotlin-native/runtime/src/main/kotlin/kotlin/native/concurrent/MutableData.kt b/kotlin-native/runtime/src/main/kotlin/kotlin/native/concurrent/MutableData.kt new file mode 100644 index 00000000000..5f17ff70695 --- /dev/null +++ b/kotlin-native/runtime/src/main/kotlin/kotlin/native/concurrent/MutableData.kt @@ -0,0 +1,133 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +package kotlin.native.concurrent + +import kotlin.native.internal.* +import kotlinx.cinterop.* + +@SymbolName("Kotlin_Any_share") +external private fun Any.share() + +@SymbolName("Kotlin_CPointer_CopyMemory") +external private fun CopyMemory(to: COpaquePointer?, from: COpaquePointer?, count: Int) + +@SymbolName("ReadHeapRefNoLock") +internal external fun readHeapRefNoLock(where: Any, index: Int): Any? + +/** + * Mutable concurrently accessible data buffer. Could be accessed from several workers simulteniously. + */ +@Frozen +@NoReorderFields +public class MutableData constructor(capacity: Int = 16) { + init { + if (capacity <= 0) throw IllegalArgumentException() + // Instance of MutableData is shared. + share() + } + + private var buffer_ = ByteArray(capacity).apply { share() } + private var buffer: ByteArray + get() = readHeapRefNoLock(this, 0) as ByteArray + set(value) { buffer_ = value} + private var size_ = 0 + private val lock = Lock() + + private fun resizeDataLocked(newSize: Int): Int { + assert(newSize >= size) + if (newSize > buffer.size) { + val actualSize = maxOf(buffer.size * 3 / 2 + 1, newSize) + val newBuffer = ByteArray(actualSize) + buffer.copyInto(newBuffer, startIndex = 0, endIndex = size) + newBuffer.share() + buffer = newBuffer + } + val position = size + size_ = newSize + return position + } + + /** + * Current data size, may concurrently change later on. + */ + public val size: Int + get() = size_ + + /** + * Reset the data buffer, makings its size 0. + */ + public fun reset() = locked(lock) { + size_ = 0 + } + + /** + * Appends data to the buffer. + */ + public fun append(data: MutableData) = locked(lock) { + val toCopy = data.size + val where = resizeDataLocked(size + toCopy) + data.copyInto(buffer, 0, toCopy, where) + } + + /** + * Appends byte array to the buffer. + */ + public fun append(data: ByteArray, fromIndex: Int = 0, toIndex: Int = data.size): Unit = locked(lock) { + if (fromIndex > toIndex) + throw IndexOutOfBoundsException("$fromIndex is bigger than $toIndex") + if (fromIndex == toIndex) return + val where = resizeDataLocked(this.size + (toIndex - fromIndex)) + data.copyInto(buffer, where, fromIndex, toIndex) + } + + /** + * Appends C data to the buffer, if `data` is null or `count` is non-positive - return. + */ + public fun append(data: COpaquePointer?, count: Int): Unit = locked(lock) { + if (data == null || count <= 0) return + val where = resizeDataLocked(this.size + count) + buffer.usePinned { + it -> CopyMemory(it.addressOf(where), data, count) + } + } + + /** + * Copies range of mutable data to the byte array. + */ + public fun copyInto(output: ByteArray, destinationIndex: Int, startIndex: Int, endIndex: Int): Unit = locked(lock) { + buffer.copyInto(output, destinationIndex, startIndex, endIndex) + } + + /** + * Get a byte from the mutable data. + * + * @Throws IndexOutOfBoundsException if index is beyond range. + */ + public operator fun get(index: Int): Byte = locked(lock) { + // index < 0 is checked below by array access. + if (index >= size) + throw IndexOutOfBoundsException("$index is not below $size") + buffer[index] + } + + /** + * Executes provided block under lock with raw pointer to the data stored in the buffer. + * Block is executed under the spinlock, and must be short. + */ + public fun withPointerLocked(block: (COpaquePointer, dataSize: Int) -> R) = locked(lock) { + buffer.usePinned { + it -> block(it.addressOf(0), size) + } + } + + /** + * Executes provided block under lock with the raw data buffer. + * Block is executed under the spinlock, and must be short. + */ + public fun withBufferLocked(block: (array: ByteArray, dataSize: Int) -> R) = locked(lock) { + block(buffer, size) + } +} \ No newline at end of file diff --git a/kotlin-native/runtime/src/main/kotlin/kotlin/native/concurrent/ObjectTransfer.kt b/kotlin-native/runtime/src/main/kotlin/kotlin/native/concurrent/ObjectTransfer.kt new file mode 100644 index 00000000000..146642298a1 --- /dev/null +++ b/kotlin-native/runtime/src/main/kotlin/kotlin/native/concurrent/ObjectTransfer.kt @@ -0,0 +1,88 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +package kotlin.native.concurrent + +import kotlinx.cinterop.* +import kotlin.native.internal.Frozen + +/** + * ## Object Transfer Basics. + * + * Objects can be passed between threads in one of two possible modes. + * + * - [SAFE] - object subgraph is checked to be not reachable by other globals or locals, and passed + * if so, otherwise an exception is thrown + * - [UNSAFE] - object is blindly passed to another worker, if there are references + * left in the passing worker - it may lead to crash or program malfunction + * + * Safe mode checks if object is no longer used in passing worker, using memory-management + * specific algorithm (ARC implementation relies on trial deletion on object graph rooted in + * passed object), and throws an [IllegalStateException] if object graph rooted in transferred object + * is reachable by some other means, + * + * Unsafe mode is intended for most performance critical operations, where object graph ownership + * is expected to be correct (such as application debugged earlier in [SAFE] mode), just transfers + * ownership without further checks. + * + * Note, that for some cases cycle collection need to be done to ensure that dead cycles do not affect + * reachability of passed object graph. + * + * @see [kotlin.native.internal.GC.collect]. + */ +public enum class TransferMode(val value: Int) { + /** + * Reachibility check is performed. + */ + SAFE(0), + /** + * Skip reachibility check, can lead to mysterious crashes in an application. + * USE UNSAFE MODE ONLY IF ABSOLUTELY SURE WHAT YOU'RE DOING!!! + */ + UNSAFE(1) +} + +/** + * Detached object graph encapsulates transferrable detached subgraph which cannot be accessed + * externally, until it is attached with the [attach] extension function. + */ +@Frozen +public class DetachedObjectGraph internal constructor(pointer: NativePtr) { + @PublishedApi + internal val stable = AtomicNativePtr(pointer) + + /** + * Creates stable pointer to object, ensuring associated object subgraph is disjoint in specified mode + * ([TransferMode.SAFE] by default). + * Raw value returned by [asCPointer] could be stored to a C variable or passed to another Kotlin machine. + */ + public constructor(mode: TransferMode = TransferMode.SAFE, producer: () -> T) + : this(detachObjectGraphInternal(mode.value, producer as () -> Any?)) + + /** + * Restores detached object graph from the value stored earlier in a C raw pointer. + */ + public constructor(pointer: COpaquePointer?) : this(pointer?.rawValue ?: NativePtr.NULL) + + /** + * Returns raw C pointer value, usable for interoperability with C scenarious. + */ + public fun asCPointer(): COpaquePointer? = interpretCPointer(stable.value) +} + +/** + * Attaches previously detached object subgraph created by [DetachedObjectGraph]. + * Please note, that once object graph is attached, the [DetachedObjectGraph.stable] pointer does not + * make sense anymore, and shall be discarded, so attach of one DetachedObjectGraph object can only + * happen once. + */ +public inline fun DetachedObjectGraph.attach(): T { + var rawStable: NativePtr + do { + rawStable = stable.value + } while (!stable.compareAndSet(rawStable, NativePtr.NULL)) + val result = attachObjectGraphInternal(rawStable) as T + return result +} diff --git a/kotlin-native/runtime/src/main/kotlin/kotlin/native/concurrent/Worker.kt b/kotlin-native/runtime/src/main/kotlin/kotlin/native/concurrent/Worker.kt new file mode 100644 index 00000000000..0ff76764566 --- /dev/null +++ b/kotlin-native/runtime/src/main/kotlin/kotlin/native/concurrent/Worker.kt @@ -0,0 +1,190 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +package kotlin.native.concurrent + +import kotlin.native.internal.ExportForCppRuntime +import kotlin.native.internal.Frozen +import kotlin.native.internal.VolatileLambda +import kotlin.native.internal.IntrinsicType +import kotlin.native.internal.TypedIntrinsic +import kotlinx.cinterop.* + +/** + * ## Workers: theory of operations. + * + * [Worker] represents asynchronous and concurrent computation, usually performed by other threads + * in the same process. Object passing between workers is performed using transfer operation, so that + * object graph belongs to one worker at the time, but can be disconnected and reconnected as needed. + * See 'Object Transfer Basics' and [TransferMode] for more details on how objects shall be transferred. + * This approach ensures that no concurrent access happens to same object, while data may flow between + * workers as needed. + */ + +/** + * Class representing worker. + */ +@Suppress("NON_PUBLIC_PRIMARY_CONSTRUCTOR_OF_INLINE_CLASS") +public inline class Worker @PublishedApi internal constructor(val id: Int) { + companion object { + /** + * Start new scheduling primitive, such as thread, to accept new tasks via `execute` interface. + * Typically new worker may be needed for computations offload to another core, for IO it may be + * better to use non-blocking IO combined with more lightweight coroutines. + * + * @param errorReporting controls if an uncaught exceptions in the worker will be printed out + * @param name defines the optional name of this worker, if none - default naming is used. + * @return worker object, usable across multiple concurrent contexts. + */ + public fun start(errorReporting: Boolean = true, name: String? = null): Worker + = Worker(startInternal(errorReporting, name)) + + /** + * Return the current worker. Worker context is accessible to any valid Kotlin context, + * but only actual active worker produced with [Worker.start] automatically processes execution requests. + * For other situations [processQueue] must be called explicitly to process request queue. + * @return current worker object, usable across multiple concurrent contexts. + */ + public val current: Worker get() = Worker(currentInternal()) + + /** + * Create worker object from a C pointer. + * + * This function is deprecated. See [Worker.asCPointer] for more details. + * + * @param pointer value returned earlier by [Worker.asCPointer] + */ + @Deprecated("Use kotlinx.cinterop.StableRef instead", level = DeprecationLevel.WARNING) + public fun fromCPointer(pointer: COpaquePointer?): Worker = + if (pointer != null) Worker(pointer.toLong().toInt()) else throw IllegalArgumentException() + } + + /** + * Requests termination of the worker. + * + * @param processScheduledJobs controls is we shall wait until all scheduled jobs processed, + * or terminate immediately. If there are jobs to be execucted with [executeAfter] their execution + * is awaited for. + */ + public fun requestTermination(processScheduledJobs: Boolean = true): Future = + Future(requestTerminationInternal(id, processScheduledJobs)) + + /** + * Plan job for further execution in the worker. Execute is a two-phase operation: + * - first [producer] function is executed, and resulting object and whatever it refers to + * is analyzed for being an isolated object subgraph, if in checked mode. + * - Afterwards, this disconnected object graph and [job] function pointer is being added to jobs queue + * of the selected worker. Note that [job] must not capture any state itself, so that whole state is + * explicitly stored in object produced by [producer]. Scheduled job is being executed by the worker, + * and result of such a execution is being disconnected from worker's object graph. Whoever will consume + * the future, can use result of worker's computations. + * Note, that some technically disjoint subgraphs may lead to `kotlin.IllegalStateException` + * so `kotlin.native.internal.GC.collect()` could be called in the end of `producer` and `job` + * if garbage cyclic structures or other uncollected objects refer to the value being transferred. + * + * @return the future with the computation result of [job]. + */ + @Suppress("UNUSED_PARAMETER") + @TypedIntrinsic(IntrinsicType.WORKER_EXECUTE) + public fun execute(mode: TransferMode, producer: () -> T1, @VolatileLambda job: (T1) -> T2): Future = + /* + * This function is a magical operation, handled by lowering in the compiler, and replaced with call to + * executeImpl(worker, mode, producer, job) + * but first ensuring that `job` parameter doesn't capture any state. + */ + throw RuntimeException("Shall not be called directly") + + /** + * Plan job for further execution in the worker. [operation] parameter must be either frozen, or execution to be + * planned on the current worker. Otherwise [IllegalStateException] will be thrown. + * + * @param afterMicroseconds defines after how many microseconds delay execution shall happen, 0 means immediately, + * @throws [IllegalArgumentException] on negative values of [afterMicroseconds]. + * @throws [IllegalStateException] if [operation] parameter is not frozen and worker is not current. + */ + public fun executeAfter(afterMicroseconds: Long = 0, operation: () -> Unit): Unit { + val current = currentInternal() + if (current != id && !operation.isFrozen) throw IllegalStateException("Job for another worker must be frozen") + if (afterMicroseconds < 0) throw IllegalArgumentException("Timeout parameter must be non-negative") + executeAfterInternal(id, operation, afterMicroseconds) + } + + /** + * Process pending job(s) on the queue of this worker. + * Note that jobs scheduled with [executeAfter] using non-zero timeout are + * not processed this way. If termination request arrives while processing the queue via this API, + * worker is marked as terminated and will exit once the current request is done with. + * + * @throws [IllegalStateException] if this request is executed on non-current [Worker]. + * @return `true` if request(s) was processed and `false` otherwise. + */ + public fun processQueue(): Boolean = processQueueInternal(id) + + /** + * Park execution of the current worker until a new request arrives or timeout specified in + * [timeoutMicroseconds] elapsed. If [process] is true, pending queue elements are processed, + * including delayed requests. Note that multiple requests could be processed this way. + * + * @param timeoutMicroseconds defines how long to park worker if no requests arrive, waits forever if -1. + * @param process defines if arrived request(s) shall be processed. + * @return if [process] is `true`: if request(s) was processed `true` and `false` otherwise. + * if [process] is `false`:` true` if request(s) has arrived and `false` if timeout happens. + * @throws [IllegalStateException] if this request is executed on non-current [Worker]. + * @throws [IllegalArgumentException] if timeout value is incorrect. + */ + public fun park(timeoutMicroseconds: Long, process: Boolean = false): Boolean { + if (timeoutMicroseconds < -1) throw IllegalArgumentException() + return parkInternal(id, timeoutMicroseconds, process) + } + + /** + * Name of the worker, as specified in [Worker.start] or "worker $id" by default, + * + * @throws [IllegalStateException] if this request is executed on an invalid worker. + */ + public val name: String + get() { + val customName = getWorkerNameInternal(id) + return if (customName == null) "worker $id" else customName + } + + /** + * String representation of the worker. + */ + override public fun toString(): String = "Worker $name" + + /** + * Convert worker to a COpaquePointer value that could be passed via native void* pointer. + * Can be used as an argument of [Worker.fromCPointer]. + * + * This function is deprecated. Use `kotlinx.cinterop.StableRef.create(worker).asCPointer()` instead. + * The result can be unwrapped with `pointer.asStableRef().get()`. + * [StableRef] should be eventually disposed manually with [StableRef.dispose]. + * + * @return worker identifier as C pointer. + */ + @Deprecated("Use kotlinx.cinterop.StableRef instead", level = DeprecationLevel.WARNING) + public fun asCPointer() : COpaquePointer? = id.toLong().toCPointer() +} + +/** + * Executes [block] with new [Worker] as resource, by starting the new worker, calling provided [block] + * (in current context) with newly started worker as [this] and terminating worker after the block completes. + * Note that this operation is pretty heavyweight, use preconfigured worker or worker pool if need to + * execute it frequently. + * + * @param name of the started worker. + * @param errorReporting controls if uncaught errors in worker to be reported. + * @param block to be executed. + * @return value returned by the block. + */ +public inline fun withWorker(name: String? = null, errorReporting: Boolean = true, block: Worker.() -> R): R { + val worker = Worker.start(errorReporting, name) + try { + return worker.block() + } finally { + worker.requestTermination().result + } +} \ No newline at end of file diff --git a/kotlin-native/runtime/src/main/kotlin/kotlin/native/concurrent/WorkerBoundReference.kt b/kotlin-native/runtime/src/main/kotlin/kotlin/native/concurrent/WorkerBoundReference.kt new file mode 100644 index 00000000000..16e6e23a982 --- /dev/null +++ b/kotlin-native/runtime/src/main/kotlin/kotlin/native/concurrent/WorkerBoundReference.kt @@ -0,0 +1,67 @@ +/* + * Copyright 2010-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +package kotlin.native.concurrent + +import kotlin.native.internal.* + +@SymbolName("Kotlin_WorkerBoundReference_create") +external private fun createWorkerBoundReference(value: Any): NativePtr + +@SymbolName("Kotlin_WorkerBoundReference_deref") +external private fun derefWorkerBoundReference(ref: NativePtr): Any? + +@SymbolName("Kotlin_WorkerBoundReference_describe") +external private fun describeWorkerBoundReference(ref: NativePtr): String + +/** + * A shared reference to a Kotlin object that doesn't freeze the referred object when it gets frozen itself. + * + * After freezing can be safely passed between workers, but [value] can only be accessed on + * the worker [WorkerBoundReference] was created on, unless the referred object is frozen too. + * + * Note: Garbage collector currently cannot free any reference cycles with frozen [WorkerBoundReference] in them. + * To resolve such cycles consider using [AtomicReference] which can be explicitly + * nulled out. + */ +@NoReorderFields +@ExportTypeInfo("theWorkerBoundReferenceTypeInfo") +@HasFinalizer +public class WorkerBoundReference(value: T) { + + private var ptr = NativePtr.NULL + private val ownerName = Worker.current.name + private var valueBeforeFreezing: T? = value + + private val valueDescription + get() = describeWorkerBoundReference(ptr) + + /** + * The referenced value. + * @throws IncorrectDereferenceException if referred object is not frozen and current worker is different from the one created [this]. + */ + val value: T + get() = valueOrNull ?: throw IncorrectDereferenceException("illegal attempt to access non-shared $valueDescription bound to `$ownerName` from `${Worker.current.name}`") + + /** + * The referenced value or null if referred object is not frozen and current worker is different from the one created [this]. + */ + val valueOrNull: T? + get() = valueBeforeFreezing ?: @Suppress("UNCHECKED_CAST") (derefWorkerBoundReference(ptr) as T?) + + /** + * Worker that [value] is bound to. + */ + val worker: Worker = Worker.current + + @ExportForCppRuntime("Kotlin_WorkerBoundReference_freezeHook") + private fun freezeHook() { + // If this hook was already run, do nothing. + if (valueBeforeFreezing == null) + return + ptr = createWorkerBoundReference(valueBeforeFreezing!!) + valueBeforeFreezing = null + } +} diff --git a/kotlin-native/runtime/src/main/kotlin/kotlin/native/internal/Annotations.kt b/kotlin-native/runtime/src/main/kotlin/kotlin/native/internal/Annotations.kt new file mode 100644 index 00000000000..90e60161a18 --- /dev/null +++ b/kotlin-native/runtime/src/main/kotlin/kotlin/native/internal/Annotations.kt @@ -0,0 +1,147 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +package kotlin.native.internal + +/** + * Makes this function to be possible to call by given name from C++ part of runtime using C ABI. + * The parameters are mapped in an implementation-dependent manner. + * + * The function to call from C++ can be a wrapper around the original function. + * + * If the name is not specified, the function to call will be available by its Kotlin unqualified name. + * + * This annotation is not intended for the general consumption and is public only for the launcher! + */ +@Target( + AnnotationTarget.FUNCTION, + AnnotationTarget.CONSTRUCTOR, + AnnotationTarget.PROPERTY_GETTER, + AnnotationTarget.PROPERTY_SETTER +) +@Retention(AnnotationRetention.BINARY) +public annotation class ExportForCppRuntime(val name: String = "") + +/** + * This annotation denotes that the element is intrinsic and its usages require special handling in compiler. + */ +@Target(AnnotationTarget.FUNCTION, AnnotationTarget.PROPERTY) +@Retention(AnnotationRetention.BINARY) +internal annotation class Intrinsic + +/** + * Exports symbol for compiler needs. + * + * This annotation is not intended for the general consumption and is public only for interop! + */ +@Target(AnnotationTarget.FUNCTION, AnnotationTarget.CONSTRUCTOR, AnnotationTarget.CLASS) +@Retention(AnnotationRetention.BINARY) +public annotation class ExportForCompiler + +/** + * Class is frozen by default. Also this annotation is (ab)used for marking objects + * where mutability checks are not needed, and they are shared, such as atomics. + */ +@Target(AnnotationTarget.CLASS) +@Retention(AnnotationRetention.BINARY) +internal annotation class Frozen + +/** + * Fields of annotated class won't be sorted. + */ +@Target(AnnotationTarget.CLASS) +@Retention(AnnotationRetention.BINARY) +internal annotation class NoReorderFields + +/** + * Exports the TypeInfo of this class by given name to use it from runtime. + */ +@Target(AnnotationTarget.CLASS) +@Retention(AnnotationRetention.BINARY) +public annotation class ExportTypeInfo(val name: String) + +/** + * If a lambda shall be carefully lowered by the compiler. + */ +@Target(AnnotationTarget.VALUE_PARAMETER) +@Retention(AnnotationRetention.BINARY) +internal annotation class VolatileLambda + +/** + * Need to be fixed because of reflection. + */ +@Target(AnnotationTarget.FUNCTION, AnnotationTarget.CLASS) +@Retention(AnnotationRetention.SOURCE) +internal annotation class FixmeReflection + +/** + * Need to be fixed because of concurrency. + */ +@Target(AnnotationTarget.FUNCTION, AnnotationTarget.CLASS) +@Retention(AnnotationRetention.SOURCE) +internal annotation class FixmeConcurrency + +/** + * Escape analysis annotations. + */ +@Target(AnnotationTarget.FUNCTION) +@Retention(AnnotationRetention.BINARY) +internal annotation class Escapes(val who: Int) + +// Decyphering of binary values can be found in EscapeAnalysis.kt +@Target(AnnotationTarget.FUNCTION) +@Retention(AnnotationRetention.BINARY) +internal annotation class PointsTo(vararg val onWhom: Int) + + +@Target(AnnotationTarget.FUNCTION) +@Retention(AnnotationRetention.BINARY) +internal annotation class TypedIntrinsic(val kind: String) + +/** + * Indicates that `@SymbolName external` function is implemented in library-stored bitcode + * and doesn't have native dependencies. + */ +@Target(AnnotationTarget.FUNCTION) +@Retention(AnnotationRetention.BINARY) +annotation class Independent + +/** + * Indicates that `@SymbolName external` function can throw foreign exception to be filtered on callsite. + * + * Note: this annotation describes rather behaviour of the (direct) call than that of the function. + * E.g. it doesn't have any effect when calling the function virtually. TODO: rework. + */ +@Target(AnnotationTarget.FUNCTION) +@Retention(AnnotationRetention.BINARY) +@PublishedApi internal annotation class FilterExceptions(val mode: String = "terminate") + +/** + * Marks a class whose instances to be added to the list of leak detector candidates. + */ +@Target(AnnotationTarget.CLASS) +@PublishedApi internal annotation class LeakDetectorCandidate + +/** + * Indicates that given top level signleton object can be created in compile time and thus + * members access doesn't need to use an init barrier and allow better optimizations for + * field access, such as constant folding. + */ +@Target(AnnotationTarget.CLASS) +@Retention(AnnotationRetention.SOURCE) +public annotation class CanBePrecreated + +/** + * Marks a class that has a finalizer. + */ +@Target(AnnotationTarget.CLASS) +internal annotation class HasFinalizer + +/** + * Marks a declaration that is internal for Kotlin/Native and shouldn't be used externally. + */ +@RequiresOptIn(level = RequiresOptIn.Level.ERROR) +@Retention(value = AnnotationRetention.BINARY) +internal annotation class InternalForKotlinNative diff --git a/kotlin-native/runtime/src/main/kotlin/kotlin/native/internal/Boxing.kt b/kotlin-native/runtime/src/main/kotlin/kotlin/native/internal/Boxing.kt new file mode 100644 index 00000000000..b9adfca5c55 --- /dev/null +++ b/kotlin-native/runtime/src/main/kotlin/kotlin/native/internal/Boxing.kt @@ -0,0 +1,76 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +package kotlin.native.internal + +@SymbolName("getCachedBooleanBox") +external fun getCachedBooleanBox(value: Boolean): Boolean? +@SymbolName("inBooleanBoxCache") +external fun inBooleanBoxCache(value: Boolean): Boolean +@SymbolName("getCachedByteBox") +external fun getCachedByteBox(value: Byte): Byte? +@SymbolName("inByteBoxCache") +external fun inByteBoxCache(value: Byte): Boolean +@SymbolName("getCachedCharBox") +external fun getCachedCharBox(value: Char): Char? +@SymbolName("inCharBoxCache") +external fun inCharBoxCache(value: Char): Boolean +@SymbolName("getCachedShortBox") +external fun getCachedShortBox(value: Short): Short? +@SymbolName("inShortBoxCache") +external fun inShortBoxCache(value: Short): Boolean +@SymbolName("getCachedIntBox") +external fun getCachedIntBox(idx: Int): Int? +@SymbolName("inIntBoxCache") +external fun inIntBoxCache(value: Int): Boolean +@SymbolName("getCachedLongBox") +external fun getCachedLongBox(value: Long): Long? +@SymbolName("inLongBoxCache") +external fun inLongBoxCache(value: Long): Boolean + +// TODO: functions below are used for ObjCExport, move and rename them correspondigly. + +@ExportForCppRuntime("Kotlin_boxBoolean") +fun boxBoolean(value: Boolean): Boolean? = value + +@ExportForCppRuntime("Kotlin_boxChar") +fun boxChar(value: Char): Char? = value + +@ExportForCppRuntime("Kotlin_boxByte") +fun boxByte(value: Byte): Byte? = value + +@ExportForCppRuntime("Kotlin_boxShort") +fun boxShort(value: Short): Short? = value + +@ExportForCppRuntime("Kotlin_boxInt") +fun boxInt(value: Int): Int? = value + +@ExportForCppRuntime("Kotlin_boxLong") +fun boxLong(value: Long): Long? = value + +@ExperimentalUnsignedTypes +@ExportForCppRuntime("Kotlin_boxUByte") +fun boxUByte(value: UByte): UByte? = value + +@ExperimentalUnsignedTypes +@ExportForCppRuntime("Kotlin_boxUShort") +fun boxUShort(value: UShort): UShort? = value + +@ExperimentalUnsignedTypes +@ExportForCppRuntime("Kotlin_boxUInt") +fun boxUInt(value: UInt): UInt? = value + +@ExperimentalUnsignedTypes +@ExportForCppRuntime("Kotlin_boxULong") +fun boxULong(value: ULong): ULong? = value + +@ExportForCppRuntime("Kotlin_boxFloat") +fun boxFloat(value: Float): Float? = value + +@ExportForCppRuntime("Kotlin_boxDouble") +fun boxDouble(value: Double): Double? = value + +@ExportForCppRuntime("Kotlin_boxUnit") +internal fun Kotlin_boxUnit(): Unit? = Unit \ No newline at end of file diff --git a/kotlin-native/runtime/src/main/kotlin/kotlin/native/internal/Cleaner.kt b/kotlin-native/runtime/src/main/kotlin/kotlin/native/internal/Cleaner.kt new file mode 100644 index 00000000000..382dd03d572 --- /dev/null +++ b/kotlin-native/runtime/src/main/kotlin/kotlin/native/internal/Cleaner.kt @@ -0,0 +1,132 @@ +/* + * Copyright 2010-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +package kotlin.native.internal + +import kotlin.native.concurrent.* +import kotlinx.cinterop.NativePtr + +public interface Cleaner + +/** + * Creates an object with a cleanup associated. + * + * After the resulting object ("cleaner") gets deallocated by memory manager, + * [block] is eventually called once with [argument]. + * + * Example of usage: + * ``` + * class ResourceWrapper { + * private val resource = Resource() + * + * private val cleaner = createCleaner(resource) { it.dispose() } + * } + * ``` + * + * When `ResourceWrapper` becomes unused and gets deallocated, its `cleaner` + * is also deallocated, and the resource is disposed later. + * + * It is not specified which thread runs [block], as well as whether two or more + * blocks from different cleaners can be run in parallel. + * + * Note: if [argument] refers (directly or indirectly) the cleaner, then both + * might leak, and the [block] will not be called in this case. + * For example, the code below has a leak: + * ``` + * class LeakingResourceWrapper { + * private val resource = Resource() + * private val cleaner = createCleaner(this) { it.resource.dispose() } + * } + * ``` + * In this case cleaner's argument (`LeakingResourceWrapper`) can't be deallocated + * until cleaner's block is executed, which can happen only strictly after + * the cleaner is deallocated, which can't happen until `LeakingResourceWrapper` + * is deallocated. So the requirements on object deallocations are contradictory + * in this case, which can't be handled gracefully. The cleaner's block + * is not executed then, and cleaner and its argument might leak + * (depending on the implementation). + * + * [block] should not use `@ThreadLocal` globals, because it may + * be executed on a different thread. + * + * If [block] throws an exception, the behavior is unspecified. + * + * Cleaners should not be kept in globals, because if cleaner is not deallocated + * before exiting main(), it'll never get executed. + * Use `Platform.isCleanersLeakCheckerActive` to warn about unexecuted cleaners. + * + * If cleaners are not GC'd before main() exits, then it's not guaranteed that + * they will be run. Moreover, it depends on `Platform.isCleanersLeakCheckerActive`. + * With the checker enabled, cleaners will be run (and therefore not reported as + * unexecuted cleaners); with the checker disabled - they might not get run. + * + * @param argument must be shareable + * @param block must not capture anything + */ +// TODO: Consider just annotating the lambda argument rather than hardcoding checking +// by function name in the compiler. +@ExperimentalStdlibApi +@ExportForCompiler +fun createCleaner(argument: T, block: (T) -> Unit): Cleaner { + if (!argument.isShareable()) + throw IllegalArgumentException("$argument must be shareable") + + val clean = { + // TODO: Maybe if this fails with exception, it should be (optionally) reported. + block(argument) + }.freeze() + + // Make sure there's an extra reference to clean, so it's definitely alive when CleanerImpl is destroyed. + val cleanPtr = createStablePointer(clean) + + // Make sure cleaner worker is initialized. + getCleanerWorker() + + return CleanerImpl(cleanPtr).freeze() +} + +/** + * Perform GC on a worker that executes Cleaner blocks. + */ +@InternalForKotlinNative +fun performGCOnCleanerWorker() = + getCleanerWorker().execute(TransferMode.SAFE, {}) { + GC.collect() + }.result + +/** + * Wait for a worker that executes Cleaner blocks to complete its scheduled tasks. + */ +@InternalForKotlinNative +fun waitCleanerWorker() = + getCleanerWorker().execute(TransferMode.SAFE, {}) { + Unit + }.result + +@SymbolName("Kotlin_CleanerImpl_getCleanerWorker") +external private fun getCleanerWorker(): Worker + +@ExportForCppRuntime("Kotlin_CleanerImpl_shutdownCleanerWorker") +private fun shutdownCleanerWorker(worker: Worker, executeScheduledCleaners: Boolean) { + worker.requestTermination(executeScheduledCleaners).result +} + +@ExportForCppRuntime("Kotlin_CleanerImpl_createCleanerWorker") +private fun createCleanerWorker(): Worker { + return Worker.start(errorReporting = false, name = "Cleaner worker") +} + +@NoReorderFields +@ExportTypeInfo("theCleanerImplTypeInfo") +@HasFinalizer +private class CleanerImpl( + private val cleanPtr: NativePtr, +): Cleaner {} + +@SymbolName("Kotlin_Any_isShareable") +external private fun Any?.isShareable(): Boolean + +@SymbolName("CreateStablePointer") +external private fun createStablePointer(obj: Any): NativePtr diff --git a/kotlin-native/runtime/src/main/kotlin/kotlin/native/internal/Coroutines.kt b/kotlin-native/runtime/src/main/kotlin/kotlin/native/internal/Coroutines.kt new file mode 100644 index 00000000000..4ac467ec2cd --- /dev/null +++ b/kotlin-native/runtime/src/main/kotlin/kotlin/native/internal/Coroutines.kt @@ -0,0 +1,30 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +package kotlin.native.internal + +import kotlin.coroutines.* +import kotlin.coroutines.intrinsics.* + +@kotlin.internal.InlineOnly +@PublishedApi +internal inline suspend fun suspendCoroutineUninterceptedOrReturn(crossinline block: (Continuation) -> Any?): T = + returnIfSuspended(block(getContinuation())) + +@TypedIntrinsic(IntrinsicType.GET_CONTINUATION) +@PublishedApi +internal external fun getContinuation(): Continuation + +@kotlin.internal.InlineOnly +@PublishedApi +internal inline suspend fun getCoroutineContext(): CoroutineContext = + getContinuation().context + +@TypedIntrinsic(IntrinsicType.RETURN_IF_SUSPENDED) +@PublishedApi +internal external suspend fun returnIfSuspended(@Suppress("UNUSED_PARAMETER") argument: Any?): T + +@TypedIntrinsic(IntrinsicType.COROUTINE_LAUNCHPAD) +internal external fun coroutineLaunchpad(suspendFunctionCall: Any?, continuation: Continuation<*>): Any? \ No newline at end of file diff --git a/kotlin-native/runtime/src/main/kotlin/kotlin/native/internal/DefaultConstructorMarker.kt b/kotlin-native/runtime/src/main/kotlin/kotlin/native/internal/DefaultConstructorMarker.kt new file mode 100644 index 00000000000..2a4be57a97b --- /dev/null +++ b/kotlin-native/runtime/src/main/kotlin/kotlin/native/internal/DefaultConstructorMarker.kt @@ -0,0 +1,9 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +package kotlin.native.internal + +@ExportForCompiler +internal object DefaultConstructorMarker; diff --git a/kotlin-native/runtime/src/main/kotlin/kotlin/native/internal/Enums.kt b/kotlin-native/runtime/src/main/kotlin/kotlin/native/internal/Enums.kt new file mode 100644 index 00000000000..050b312a2e3 --- /dev/null +++ b/kotlin-native/runtime/src/main/kotlin/kotlin/native/internal/Enums.kt @@ -0,0 +1,14 @@ +/* + * Copyright 2010-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +package kotlin.native.internal + +@TypedIntrinsic(IntrinsicType.ENUM_VALUES) +@PublishedApi +internal external fun > enumValuesIntrinsic(): Array + +@TypedIntrinsic(IntrinsicType.ENUM_VALUE_OF) +@PublishedApi +internal external fun > enumValueOfIntrinsic(name: String): T diff --git a/kotlin-native/runtime/src/main/kotlin/kotlin/native/internal/FloatingPointParser.kt b/kotlin-native/runtime/src/main/kotlin/kotlin/native/internal/FloatingPointParser.kt new file mode 100644 index 00000000000..cee7cd9e9f6 --- /dev/null +++ b/kotlin-native/runtime/src/main/kotlin/kotlin/native/internal/FloatingPointParser.kt @@ -0,0 +1,381 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package kotlin.native.internal + +import kotlin.comparisons.* + +/** + * Takes a String and an integer exponent. The String should hold a positive + * integer value (or zero). The exponent will be used to calculate the + * floating point number by taking the positive integer the String + * represents and multiplying by 10 raised to the power of the + * exponent. Returns the closest double value to the real number. + + * @param s the String that will be parsed to a floating point + * @param e an int represent the 10 to part + * @return the double closest to the real number + * @exception NumberFormatException if the String doesn't represent a positive integer value + */ +@SymbolName("Kotlin_native_FloatingPointParser_parseDoubleImpl") +private external fun parseDoubleImpl(s: String, e: Int): Double + +/** + * Takes a String and an integer exponent. The String should hold a positive + * integer value (or zero). The exponent will be used to calculate the + * floating point number by taking the positive integer the String + * represents and multiplying by 10 raised to the power of the + * exponent. Returns the closest float value to the real number. + + * @param s the String that will be parsed to a floating point + * @param e an int represent the 10 to part + * @return the float closest to the real number + * @exception NumberFormatException if the String doesn't represent a positive integer value + */ +@SymbolName("Kotlin_native_FloatingPointParser_parseFloatImpl") +private external fun parseFloatImpl(s: String, e: Int): Float + +/** + * Used to parse a string and return either a single or double precision + * floating point number. + */ +object FloatingPointParser { + /* + * All number with exponent larger than MAX_EXP can be treated as infinity. + * All number with exponent smaller than MIN_EXP can be treated as zero. + * Exponent is 10 based. + * Eg. double's min value is 5e-324, so double "1e-325" should be parsed as 0.0 + */ + private val FLOAT_MIN_EXP = -46 + private val FLOAT_MAX_EXP = 38 + private val DOUBLE_MIN_EXP = -324 + private val DOUBLE_MAX_EXP = 308 + + private class StringExponentPair(var s: String, var e: Int, var negative: Boolean) + + /** + * Takes a String and does some initial parsing. Should return a + * StringExponentPair containing a String with no leading or trailing white + * space and trailing zeroes eliminated. The exponent of the + * StringExponentPair will be used to calculate the floating point number by + * taking the positive integer the String represents and multiplying by 10 + * raised to the power of the exponent. + + * @param string the String that will be parsed to a floating point + * @return a StringExponentPair with necessary values + * @exception NumberFormatException if the String doesn't pass basic tests + */ + private fun initialParse(string: String): StringExponentPair { + var s = string + var length = s.length + var negative = false + var c: Char + var start: Int + var end: Int + val decimal: Int + var shift: Int + var e = 0 + + start = 0 + if (length == 0) + throw NumberFormatException(s) + + c = s[length - 1] + if (c == 'D' || c == 'd' || c == 'F' || c == 'f') { + length-- + if (length == 0) + throw NumberFormatException(s) + } + + end = maxOf(s.indexOf('E'), s.indexOf('e')) + if (end > -1) { + if (end + 1 == length) + throw NumberFormatException(s) + + var exponent_offset = end + 1 + if (s[exponent_offset] == '+') { + if (s[exponent_offset + 1] == '-') { + throw NumberFormatException(s) + } + exponent_offset++ // skip the plus sign + if (exponent_offset == length) + throw NumberFormatException(s) + } + val strExp = s.substring(exponent_offset, length) + try { + e = strExp.toInt() + } catch (ex: NumberFormatException) { + // strExp is not empty, so there are 2 situations the exception be thrown + // if the string is invalid we should throw exception, if the actual number + // is out of the range of Integer, we can still parse the original number to + // double or float. + var ch: Char + for (i in 0..strExp.length - 1) { + ch = strExp[i] + if (ch < '0' || ch > '9') { + if (i == 0 && ch == '-') + continue + // ex contains the exponent substring only so throw + // a new exception with the correct string. + throw NumberFormatException(s) + } + } + e = if (strExp[0] == '-') Int.MIN_VALUE else Int.MAX_VALUE + } + + } else { + end = length + } + if (length == 0) + throw NumberFormatException(s) + + c = s[start] + if (c == '-') { + ++start + --length + negative = true + } else if (c == '+') { + ++start + --length + } + if (length == 0) + throw NumberFormatException(s) + + decimal = s.indexOf('.') + if (decimal > -1) { + shift = end - decimal - 1 + // Prevent e overflow, shift >= 0. + if (e >= 0 || e - Int.MIN_VALUE > shift) { + e -= shift + } + s = s.substring(start, decimal) + s.substring(decimal + 1, end) + } else { + s = s.substring(start, end) + } + + length = s.length + if (length == 0) + throw NumberFormatException() + + end = length + while (end > 1 && s[end - 1] == '0') + --end + + start = 0 + while (start < end - 1 && s[start] == '0') + start++ + + if (end != length || start != 0) { + shift = length - end + if (e <= 0 || Int.MAX_VALUE - e > shift) { + e += shift + } + s = s.substring(start, end) + } + + // Trim the length of very small numbers, natives can only handle down to E-309. + val APPROX_MIN_MAGNITUDE = -359 + val MAX_DIGITS = 52 + length = s.length + if (length > MAX_DIGITS && e < APPROX_MIN_MAGNITUDE) { + val d = minOf(APPROX_MIN_MAGNITUDE - e, length - 1) + s = s.substring(0, length - d) + e += d + } + + return StringExponentPair(s, e, negative) + } + + /* + * Assumes the string is trimmed. + */ + private fun parseDoubleName(namedDouble: String, length: Int): Double { + // Valid strings are only +Nan, NaN, -Nan, +Infinity, Infinity, -Infinity. + if (length != 3 && length != 4 && length != 8 && length != 9) { + throw NumberFormatException() + } + + var negative = false + var cmpstart = 0 + when (namedDouble[0]) { + '-' -> { + negative = true + cmpstart = 1 + } + '+' -> cmpstart = 1 + } + + if (namedDouble.regionMatches(cmpstart, "Infinity", 0, 8, ignoreCase = false)) { + return if (negative) + Double.NEGATIVE_INFINITY + else + Double.POSITIVE_INFINITY + } + + if (namedDouble.regionMatches(cmpstart, "NaN", 0, 3, ignoreCase = false)) { + return Double.NaN + } + + throw NumberFormatException() + } + + /* + * Assumes the string is trimmed. + */ + private fun parseFloatName(namedFloat: String, length: Int): Float { + // Valid strings are only +Nan, NaN, -Nan, +Infinity, Infinity, -Infinity. + if (length != 3 && length != 4 && length != 8 && length != 9) { + throw NumberFormatException() + } + + var negative = false + var cmpstart = 0 + when (namedFloat[0]) { + '-' -> { + negative = true + cmpstart = 1 + } + '+' -> cmpstart = 1 + } + + if (namedFloat.regionMatches(cmpstart, "Infinity", 0, 8, ignoreCase = false)) { + return if (negative) Float.NEGATIVE_INFINITY else Float.POSITIVE_INFINITY + } + + if (namedFloat.regionMatches(cmpstart, "NaN", 0, 3, ignoreCase = false)) { + return Float.NaN + } + + throw NumberFormatException() + } + + /* + * Answers true if the string should be parsed as a hex encoding. + * Assumes the string is trimmed. + */ + private fun parseAsHex(s: String): Boolean { + val length = s.length + if (length < 2) { + return false + } + var first = s[0] + var second = s[1] + if (first == '+' || first == '-') { + // Move along. + if (length < 3) { + return false + } + first = second + second = s[2] + } + return first == '0' && (second == 'x' || second == 'X') + } + + /** + * Returns the closest double value to the real number in the string. + * + * @param string the String that will be parsed to a floating point + * @return the double closest to the real number + * @exception NumberFormatException if the String doesn't represent a double + */ + fun parseDouble(string: String): Double { + var s = string + s = s.trim { it <= ' ' } + val length = s.length + + if (length == 0) { + throw NumberFormatException(s) + } + + // See if this could be a named double. + val last = s[length - 1] + if (last == 'y' || last == 'N') { + return parseDoubleName(s, length) + } + + // See if it could be a hexadecimal representation. + if (parseAsHex(s)) { + return HexStringParser.parseDouble(s) + } + + val info = initialParse(s) + + // Two kinds of situation will directly return 0.0: + // 1. info.s is 0; + // 2. actual exponent is less than Double.MIN_EXPONENT. + if ("0" == info.s || info.e + info.s.length - 1 < DOUBLE_MIN_EXP) { + return if (info.negative) -0.0 else 0.0 + } + // If actual exponent is larger than Double.MAX_EXPONENT, return infinity. + // Prevent overflow, check twice. + if (info.e > DOUBLE_MAX_EXP || info.e + info.s.length - 1 > DOUBLE_MAX_EXP) { + return if (info.negative) Double.NEGATIVE_INFINITY else Double.POSITIVE_INFINITY + } + var result = parseDoubleImpl(info.s, info.e) + if (info.negative) + result = -result + + return result + } + + /** + * Returns the closest float value to the real number in the string. + * + * @param s the String that will be parsed to a floating point + * @return the float closest to the real number + * @exception NumberFormatException if the String doesn't represent a float + */ + fun parseFloat(string: String): Float { + var s = string + s = s.trim { it <= ' ' } + val length = s.length + + if (length == 0) { + throw NumberFormatException(s) + } + + // See if this could be a named float. + val last = s[length - 1] + if (last == 'y' || last == 'N') { + return parseFloatName(s, length) + } + + // See if it could be a hexadecimal representation. + if (parseAsHex(s)) { + return HexStringParser.parseFloat(s) + } + + val info = initialParse(s) + + // Two kinds of situation will directly return 0.0f. + // 1. info.s is 0; + // 2. actual exponent is less than Float.MIN_EXPONENT. + if ("0" == info.s || info.e + info.s.length - 1 < FLOAT_MIN_EXP) { + return if (info.negative) -0.0f else 0.0f + } + // If actual exponent is larger than Float.MAX_EXPONENT, return infinity. + // Prevent overflow, check twice. + if (info.e > FLOAT_MAX_EXP || info.e + info.s.length - 1 > FLOAT_MAX_EXP) { + return if (info.negative) Float.NEGATIVE_INFINITY else Float.POSITIVE_INFINITY + } + var result = parseFloatImpl(info.s, info.e) + if (info.negative) + result = -result + + return result + } +} \ No newline at end of file diff --git a/kotlin-native/runtime/src/main/kotlin/kotlin/native/internal/FunctionAdapter.kt b/kotlin-native/runtime/src/main/kotlin/kotlin/native/internal/FunctionAdapter.kt new file mode 100644 index 00000000000..66d48e693d8 --- /dev/null +++ b/kotlin-native/runtime/src/main/kotlin/kotlin/native/internal/FunctionAdapter.kt @@ -0,0 +1,12 @@ +/* + * Copyright 2010-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +package kotlin.native.internal + +import kotlin.Function + +internal interface FunctionAdapter { + fun getFunctionDelegate(): Function<*> +} \ No newline at end of file diff --git a/kotlin-native/runtime/src/main/kotlin/kotlin/native/internal/GC.kt b/kotlin-native/runtime/src/main/kotlin/kotlin/native/internal/GC.kt new file mode 100644 index 00000000000..fd52d6ceeee --- /dev/null +++ b/kotlin-native/runtime/src/main/kotlin/kotlin/native/internal/GC.kt @@ -0,0 +1,146 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +package kotlin.native.internal + +/** + * ## Cycle garbage collector interface. + * + * Konan relies upon reference counting for object management, however it could + * not collect cyclical garbage, so we perform periodic garbage collection. + * This may slow down application, so this interface provides control over how + * garbage collector activates and runs. + * Garbage collector can be in one of the following states: + * - running + * - suspended (so cycle candidates are collected, but GC is not performed until resume) + * - stopped (all cyclical garbage is hopelessly lost) + * Immediately after startup GC is in running state. + * Depending on application needs it may select to suspend GC for certain phases of + * its lifetime, and resume it later on, or just completely turn it off, if GC pauses + * are less desirable than cyclical garbage leaks. + */ +object GC { + /** + * To force garbage collection immediately, unless collector is stopped + * with [stop] operation. Even if GC is suspended, [collect] still triggers collection. + */ + @SymbolName("Kotlin_native_internal_GC_collect") + external fun collect() + + /** + * Request global cyclic collector, operation is async and just triggers the collection. + */ + @SymbolName("Kotlin_native_internal_GC_collectCyclic") + external fun collectCyclic() + + /** + * Suspend garbage collection. Release candidates are still collected, but + * GC algorithm is not executed. + */ + @SymbolName("Kotlin_native_internal_GC_suspend") + external fun suspend() + + /** + * Resume garbage collection. Can potentially lead to GC immediately. + */ + @SymbolName("Kotlin_native_internal_GC_resume") + external fun resume() + + /** + * Stop garbage collection. Cyclical garbage is no longer collected. + */ + @SymbolName("Kotlin_native_internal_GC_stop") + external fun stop() + + /** + * Start garbage collection. Cyclical garbage produced while GC was stopped + * cannot be reclaimed, but all new garbage is collected. + */ + @SymbolName("Kotlin_native_internal_GC_start") + external fun start() + + /** + * GC threshold, controlling how frequenly GC is activated, and how much time GC + * takes. Bigger values lead to longer GC pauses, but less GCs. + */ + var threshold: Int + get() = getThreshold() + set(value) = setThreshold(value) + + /** + * GC allocation threshold, controlling how frequenly GC collect cycles, and how much time + * this process takes. Bigger values lead to longer GC pauses, but less GCs. + */ + var collectCyclesThreshold: Long + get() = getCollectCyclesThreshold() + set(value) = setCollectCyclesThreshold(value) + + /** + * GC allocation threshold, controlling how many bytes allocated since last + * collection will trigger new GC. + */ + var thresholdAllocations: Long + get() = getThresholdAllocations() + set(value) = setThresholdAllocations(value) + + /** + * If GC shall auto-tune thresholds, depending on how much time is spent in collection. + */ + var autotune: Boolean + get() = getTuneThreshold() + set(value) = setTuneThreshold(value) + + + /** + * If cyclic collector for atomic references to be deployed. + */ + var cyclicCollectorEnabled: Boolean + get() = getCyclicCollectorEnabled() + set(value) = setCyclicCollectorEnabled(value) + + /** + * Detect cyclic references going via atomic references and return list of cycle-inducing objects + * or `null` if the leak detector is not available. Use [Platform.isMemoryLeakCheckerActive] to check + * leak detector availability. + */ + @SymbolName("Kotlin_native_internal_GC_detectCycles") + external fun detectCycles(): Array? + + /** + * Find a reference cycle including from the given object, `null` if no cycles detected. + */ + @SymbolName("Kotlin_native_internal_GC_findCycle") + external fun findCycle(root: Any): Array? + + @SymbolName("Kotlin_native_internal_GC_getThreshold") + private external fun getThreshold(): Int + + @SymbolName("Kotlin_native_internal_GC_setThreshold") + private external fun setThreshold(value: Int) + + @SymbolName("Kotlin_native_internal_GC_getCollectCyclesThreshold") + private external fun getCollectCyclesThreshold(): Long + + @SymbolName("Kotlin_native_internal_GC_setCollectCyclesThreshold") + private external fun setCollectCyclesThreshold(value: Long) + + @SymbolName("Kotlin_native_internal_GC_getThresholdAllocations") + private external fun getThresholdAllocations(): Long + + @SymbolName("Kotlin_native_internal_GC_setThresholdAllocations") + private external fun setThresholdAllocations(value: Long) + + @SymbolName("Kotlin_native_internal_GC_getTuneThreshold") + private external fun getTuneThreshold(): Boolean + + @SymbolName("Kotlin_native_internal_GC_setTuneThreshold") + private external fun setTuneThreshold(value: Boolean) + + @SymbolName("Kotlin_native_internal_GC_getCyclicCollector") + private external fun getCyclicCollectorEnabled(): Boolean + + @SymbolName("Kotlin_native_internal_GC_setCyclicCollector") + private external fun setCyclicCollectorEnabled(value: Boolean) +} diff --git a/kotlin-native/runtime/src/main/kotlin/kotlin/native/internal/HexStringParser.kt b/kotlin-native/runtime/src/main/kotlin/kotlin/native/internal/HexStringParser.kt new file mode 100644 index 00000000000..db106c7913d --- /dev/null +++ b/kotlin-native/runtime/src/main/kotlin/kotlin/native/internal/HexStringParser.kt @@ -0,0 +1,368 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package kotlin.native.internal + +import kotlin.text.regex.* + +@SymbolName("Kotlin_native_int_bits_to_float") +private external fun intBitsToFloat(x: Int): Float + +@SymbolName("Kotlin_native_long_bits_to_double") +private external fun longBitsToDouble(x: Long): Double + +/* + * Parses hex string to a single or double precision floating point number. + */ +internal class HexStringParser(private val EXPONENT_WIDTH: Int, private val MANTISSA_WIDTH: Int) { + + private val EXPONENT_BASE: Long + + private val MAX_EXPONENT: Long + + private val MIN_EXPONENT: Long + + private val MANTISSA_MASK: Long + + private var sign: Long = 0 + + private var exponent: Long = 0 + + private var mantissa: Long = 0 + + private var abandonedNumber = "" //$NON-NLS-1$ + + init { + this.EXPONENT_BASE = (-1L shl (EXPONENT_WIDTH - 1)).inv() + this.MAX_EXPONENT = (-1L shl EXPONENT_WIDTH).inv() + this.MIN_EXPONENT = (-(MANTISSA_WIDTH + 1)).toLong() + this.MANTISSA_MASK = (-1L shl MANTISSA_WIDTH).inv() + } + + private fun parse(hexString: String): Long { + val hexSegments = getSegmentsFromHexString(hexString) + val signStr = hexSegments[0] + val significantStr = hexSegments[1] + val exponentStr = hexSegments[2] + + parseHexSign(signStr) + parseExponent(exponentStr) + parseMantissa(significantStr) + + sign = sign shl (MANTISSA_WIDTH + EXPONENT_WIDTH) + exponent = exponent shl MANTISSA_WIDTH + return sign or exponent or mantissa + } + + /* + * Parses the sign field. + */ + private fun parseHexSign(signStr: String) { + this.sign = (if (signStr == "-") 1 else 0).toLong() //$NON-NLS-1$ + } + + /* + * Parses the exponent field. + */ + private fun parseExponent(exponentString: String) { + var exponentStr = exponentString + val leadingChar = exponentStr[0] + val expSign = if (leadingChar == '-') -1 else 1 + if (!leadingChar.isDigit()) { + exponentStr = exponentStr.substring(1) + } + + try { + exponent = expSign * exponentStr.toLong() + checkedAddExponent(EXPONENT_BASE) + } catch (e: NumberFormatException) { + exponent = expSign * Long.MAX_VALUE + } + + } + + /* + * Parses the mantissa field. + */ + private fun parseMantissa(significantStr: String) { + val strings = significantStr.split("\\.".toRegex()).dropLastWhile { it.isEmpty() }.toTypedArray() //$NON-NLS-1$ + val strIntegerPart = strings[0] + val strDecimalPart = if (strings.size > 1) strings[1] else "" //$NON-NLS-1$ + + var significand = getNormalizedSignificand(strIntegerPart, strDecimalPart) + if (significand == "0") { //$NON-NLS-1$ + setZero() + return + } + + val offset = getOffset(strIntegerPart, strDecimalPart) + checkedAddExponent(offset.toLong()) + + if (exponent >= MAX_EXPONENT) { + setInfinite() + return + } + + if (exponent <= MIN_EXPONENT) { + setZero() + return + } + + if (significand.length > MAX_SIGNIFICANT_LENGTH) { + abandonedNumber = significand.substring(MAX_SIGNIFICANT_LENGTH) + significand = significand.substring(0, MAX_SIGNIFICANT_LENGTH) + } + + mantissa = significand.toLong(HEX_RADIX) + + if (exponent >= 1) { + processNormalNumber() + } else { + processSubNormalNumber() + } + + } + + private fun setInfinite() { + exponent = MAX_EXPONENT + mantissa = 0 + } + + private fun setZero() { + exponent = 0 + mantissa = 0 + } + + private fun signum(x: Long) = when { + x == 0L -> 0 + x > 0L -> 1 + else -> -1 + } + + /* + * Sets the exponent variable to Long.MAX_VALUE or -Long.MAX_VALUE if + * overflow or underflow happens. + */ + private fun checkedAddExponent(offset: Long) { + val result = exponent + offset + val expSign = signum(exponent) + if (expSign * signum(offset) > 0 && expSign * signum(result) < 0) { + exponent = expSign * Long.MAX_VALUE + } else { + exponent = result + } + } + + private fun processNormalNumber() { + val desiredWidth = MANTISSA_WIDTH + 2 + fitMantissaInDesiredWidth(desiredWidth) + round() + mantissa = mantissa and MANTISSA_MASK + } + + private fun processSubNormalNumber() { + var desiredWidth = MANTISSA_WIDTH + 1 + desiredWidth += exponent.toInt()//lends bit from mantissa to exponent + exponent = 0 + fitMantissaInDesiredWidth(desiredWidth) + round() + mantissa = mantissa and MANTISSA_MASK + } + + /* + * Adjusts the mantissa to desired width for further analysis. + */ + private fun fitMantissaInDesiredWidth(desiredWidth: Int) { + val bitLength = countBitsLength(mantissa) + if (bitLength > desiredWidth) { + discardTrailingBits((bitLength - desiredWidth).toLong()) + } else { + mantissa = mantissa shl (desiredWidth - bitLength) + } + } + + /* + * Stores the discarded bits to abandonedNumber. + */ + private fun discardTrailingBits(num: Long) { + val mask = (-1L shl num.toInt()).inv() + abandonedNumber += mantissa and mask + mantissa = mantissa shr num.toInt() + } + + /* + * The value is rounded up or down to the nearest infinitely precise result. + * If the value is exactly halfway between two infinitely precise results, + * then it should be rounded up to the nearest infinitely precise even. + */ + private fun round() { + val result = abandonedNumber.replace("0+".toRegex(), "") //$NON-NLS-1$ //$NON-NLS-2$ + val moreThanZero = result.length > 0 + + val lastDiscardedBit = (mantissa and 1L).toInt() + mantissa = mantissa shr 1 + val tailBitInMantissa = (mantissa and 1L).toInt() + + if (lastDiscardedBit == 1 && (moreThanZero || tailBitInMantissa == 1)) { + val oldLength = countBitsLength(mantissa) + mantissa += 1L + val newLength = countBitsLength(mantissa) + + //Rounds up to exponent when whole bits of mantissa are one-bits. + if (oldLength >= MANTISSA_WIDTH && newLength > oldLength) { + checkedAddExponent(1) + } + } + } + + /* + * Returns the normalized significand after removing the leading zeros. + */ + private fun getNormalizedSignificand(strIntegerPart: String, strDecimalPart: String): String { + var significand = strIntegerPart + strDecimalPart + significand = significand.replaceFirst("^0+".toRegex(), "") //$NON-NLS-1$//$NON-NLS-2$ + if (significand.length == 0) { + significand = "0" //$NON-NLS-1$ + } + return significand + } + + /* + * Calculates the offset between the normalized number and unnormalized + * number. In a normalized representation, significand is represented by the + * characters "0x1." followed by a lowercase hexadecimal representation of + * the rest of the significand as a fraction. + */ + private fun getOffset(strIntegerPartParam: String, strDecimalPart: String): Int { + var strIntegerPart = strIntegerPartParam + strIntegerPart = strIntegerPart.replaceFirst("^0+".toRegex(), "") //$NON-NLS-1$ //$NON-NLS-2$ + + // If the Integer part is a nonzero number. + if (strIntegerPart.length != 0) { + val leadingNumber = strIntegerPart.substring(0, 1) + return (strIntegerPart.length - 1) * 4 + countBitsLength(leadingNumber.toLong(HEX_RADIX)) - 1 + } + + // If the Integer part is a zero number. + var i = 0 + while (i < strDecimalPart.length && strDecimalPart[i] == '0') { + i++ + } + if (i == strDecimalPart.length) { + return 0 + } + val leadingNumber = strDecimalPart.substring(i, i + 1) + return (-i - 1) * 4 + countBitsLength(leadingNumber.toLong(HEX_RADIX)) - 1 + } + + fun numberOfLeadingZeros(i: Long): Int { + // HD, Figure 5-6 + if (i == 0L) + return 64 + var n = 1 + var x = (i ushr 32).toInt() + if (x == 0) { + n += 32 + x = i.toInt() + } + if (x ushr 16 == 0) { + n += 16 + x = x shl 16 + } + if (x ushr 24 == 0) { + n += 8 + x = x shl 8 + } + if (x ushr 28 == 0) { + n += 4 + x = x shl 4 + } + if (x ushr 30 == 0) { + n += 2 + x = x shl 2 + } + n -= x ushr 31 + return n + } + + private fun countBitsLength(value: Long) = 64 - numberOfLeadingZeros(value) + + companion object { + + private val DOUBLE_EXPONENT_WIDTH = 11 + + private val DOUBLE_MANTISSA_WIDTH = 52 + + private val FLOAT_EXPONENT_WIDTH = 8 + + private val FLOAT_MANTISSA_WIDTH = 23 + + private val HEX_RADIX = 16 + + private val MAX_SIGNIFICANT_LENGTH = 15 + + private val HEX_SIGNIFICANT = "0[xX](\\p{XDigit}+\\.?|\\p{XDigit}*\\.\\p{XDigit}+)" //$NON-NLS-1$ + + private val BINARY_EXPONENT = "[pP]([+-]?\\d+)" //$NON-NLS-1$ + + private val FLOAT_TYPE_SUFFIX = "[fFdD]?" //$NON-NLS-1$ + + private val HEX_PATTERN = "[\\x00-\\x20]*([+-]?)$HEX_SIGNIFICANT" + //$NON-NLS-1$ + + BINARY_EXPONENT + FLOAT_TYPE_SUFFIX + "[\\x00-\\x20]*" //$NON-NLS-1$ + + private val PATTERN = Regex(HEX_PATTERN) + + /* + * Parses the hex string to a double number. + */ + fun parseDouble(hexString: String): Double { + val parser = HexStringParser(DOUBLE_EXPONENT_WIDTH, + DOUBLE_MANTISSA_WIDTH) + val result = parser.parse(hexString) + return longBitsToDouble(result) + } + + /* + * Parses the hex string to a float number. + */ + fun parseFloat(hexString: String): Float { + val parser = HexStringParser(FLOAT_EXPONENT_WIDTH, + FLOAT_MANTISSA_WIDTH) + val result = parser.parse(hexString).toInt() + return intBitsToFloat(result) + } + + /* + * Analyzes the hex string and extracts the sign and digit segments. + */ + private fun getSegmentsFromHexString(hexString: String): Array { + val matchResult = PATTERN.matchEntire(hexString) + if (matchResult == null) { + throw NumberFormatException() + } + + val hexSegments = arrayOf( + matchResult.groupValues[1], + matchResult.groupValues[2], + matchResult.groupValues[3] + ) + + return hexSegments + } + } +} \ No newline at end of file diff --git a/kotlin-native/runtime/src/main/kotlin/kotlin/native/internal/InteropBoxing.kt b/kotlin-native/runtime/src/main/kotlin/kotlin/native/internal/InteropBoxing.kt new file mode 100644 index 00000000000..7412210cc51 --- /dev/null +++ b/kotlin-native/runtime/src/main/kotlin/kotlin/native/internal/InteropBoxing.kt @@ -0,0 +1,66 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +package kotlin.native.internal + +import kotlinx.cinterop.* + +@Frozen +class NativePtrBox(val value: NativePtr) { + override fun equals(other: Any?): Boolean { + if (other !is NativePtrBox) { + return false + } + + return this.value == other.value + } + + override fun hashCode() = value.hashCode() + + override fun toString() = value.toString() +} + +fun boxNativePtr(value: NativePtr) = NativePtrBox(value) + +@Frozen +class NativePointedBox(val value: NativePointed) { + override fun equals(other: Any?): Boolean { + if (other !is NativePointedBox) { + return false + } + + return this.value == other.value + } + + // TODO: can't delegate the following methods to `this.value` + // because `NativePointed` doesn't provide them. + + override fun hashCode() = this.value.rawPtr.hashCode() + + override fun toString() = "NativePointed(raw=${this.value.rawPtr})" +} + +fun boxNativePointed(value: NativePointed?) = if (value != null) NativePointedBox(value) else null +fun unboxNativePointed(box: NativePointedBox?) = box?.value + +@Frozen +class CPointerBox(val value: CPointer) : CValuesRef() { + override fun equals(other: Any?): Boolean { + if (other !is CPointerBox) { + return false + } + + return this.value == other.value + } + + override fun hashCode() = value.hashCode() + + override fun toString() = value.toString() + + override fun getPointer(scope: AutofreeScope) = value.getPointer(scope) +} + +fun boxCPointer(value: CPointer?) = if (value != null) CPointerBox(value) else null +fun unboxCPointer(box: CPointerBox?) = box?.value \ No newline at end of file diff --git a/kotlin-native/runtime/src/main/kotlin/kotlin/native/internal/IntrinsicType.kt b/kotlin-native/runtime/src/main/kotlin/kotlin/native/internal/IntrinsicType.kt new file mode 100644 index 00000000000..25edf9928d0 --- /dev/null +++ b/kotlin-native/runtime/src/main/kotlin/kotlin/native/internal/IntrinsicType.kt @@ -0,0 +1,85 @@ +package kotlin.native.internal + +class IntrinsicType { + companion object { + // Arithmetic + const val PLUS = "PLUS" + const val MINUS = "MINUS" + const val TIMES = "TIMES" + const val SIGNED_DIV = "SIGNED_DIV" + const val SIGNED_REM = "SIGNED_REM" + const val UNSIGNED_DIV = "UNSIGNED_DIV" + const val UNSIGNED_REM = "UNSIGNED_REM" + const val INC = "INC" + const val DEC = "DEC" + const val UNARY_PLUS = "UNARY_PLUS" + const val UNARY_MINUS = "UNARY_MINUS" + const val SHL = "SHL" + const val SHR = "SHR" + const val USHR = "USHR" + const val AND = "AND" + const val OR = "OR" + const val XOR = "XOR" + const val INV = "INV" + const val SIGN_EXTEND = "SIGN_EXTEND" + const val ZERO_EXTEND = "ZERO_EXTEND" + const val INT_TRUNCATE = "INT_TRUNCATE" + const val FLOAT_TRUNCATE = "FLOAT_TRUNCATE" + const val FLOAT_EXTEND = "FLOAT_EXTEND" + const val SIGNED_TO_FLOAT = "SIGNED_TO_FLOAT" + const val UNSIGNED_TO_FLOAT = "UNSIGNED_TO_FLOAT" + const val FLOAT_TO_SIGNED = "FLOAT_TO_SIGNED" + const val SIGNED_COMPARE_TO = "SIGNED_COMPARE_TO" + const val UNSIGNED_COMPARE_TO = "UNSIGNED_COMPARE_TO" + const val NOT = "NOT" + const val REINTERPRET = "REINTERPRET" + const val EXTRACT_ELEMENT = "EXTRACT_ELEMENT" + const val ARE_EQUAL_BY_VALUE = "ARE_EQUAL_BY_VALUE" + const val IEEE_754_EQUALS = "IEEE_754_EQUALS" + + // ObjC related stuff + const val OBJC_GET_MESSENGER = "OBJC_GET_MESSENGER" + const val OBJC_GET_MESSENGER_STRET = "OBJC_GET_MESSENGER_STRET" + const val OBJC_GET_OBJC_CLASS = "OBJC_GET_OBJC_CLASS" + const val OBJC_CREATE_SUPER_STRUCT = "OBJC_CREATE_SUPER_STRUCT" + const val OBJC_INIT_BY = "OBJC_INIT_BY" + const val OBJC_GET_SELECTOR = "OBJC_GET_SELECTOR" + + // Other + const val GET_CLASS_TYPE_INFO = "GET_CLASS_TYPE_INFO" + const val INTEROP_READ_BITS = "INTEROP_READ_BITS" + const val INTEROP_WRITE_BITS = "INTEROP_WRITE_BITS" + const val CREATE_UNINITIALIZED_INSTANCE = "CREATE_UNINITIALIZED_INSTANCE" + const val LIST_OF_INTERNAL = "LIST_OF_INTERNAL" + const val IDENTITY = "IDENTITY" + const val IMMUTABLE_BLOB = "IMMUTABLE_BLOB" + const val INIT_INSTANCE = "INIT_INSTANCE" + + // Enums + const val ENUM_VALUES = "ENUM_VALUES" + const val ENUM_VALUE_OF = "ENUM_VALUE_OF" + + // Coroutines + const val GET_CONTINUATION = "GET_CONTINUATION" + const val RETURN_IF_SUSPENDED = "RETURN_IF_SUSPENDED" + const val COROUTINE_LAUNCHPAD = "COROUTINE_LAUNCHPAD" + + // Interop + const val INTEROP_READ_PRIMITIVE = "INTEROP_READ_PRIMITIVE" + const val INTEROP_WRITE_PRIMITIVE = "INTEROP_WRITE_PRIMITIVE" + const val INTEROP_GET_POINTER_SIZE = "INTEROP_GET_POINTER_SIZE" + const val INTEROP_NATIVE_PTR_TO_LONG = "INTEROP_NATIVE_PTR_TO_LONG" + const val INTEROP_NATIVE_PTR_PLUS_LONG = "INTEROP_NATIVE_PTR_PLUS_LONG" + const val INTEROP_GET_NATIVE_NULL_PTR = "INTEROP_GET_NATIVE_NULL_PTR" + const val INTEROP_CONVERT = "INTEROP_CONVERT" + const val INTEROP_BITS_TO_FLOAT = "INTEROP_BITS_TO_FLOAT" + const val INTEROP_BITS_TO_DOUBLE = "INTEROP_BITS_TO_DOUBLE" + const val INTEROP_SIGN_EXTEND = "INTEROP_SIGN_EXTEND" + const val INTEROP_NARROW = "INTEROP_NARROW" + const val INTEROP_STATIC_C_FUNCTION = "INTEROP_STATIC_C_FUNCTION" + const val INTEROP_FUNPTR_INVOKE = "INTEROP_FUNPTR_INVOKE" + + // Worker + const val WORKER_EXECUTE = "WORKER_EXECUTE" + } +} \ No newline at end of file diff --git a/kotlin-native/runtime/src/main/kotlin/kotlin/native/internal/Intrinsics.kt b/kotlin-native/runtime/src/main/kotlin/kotlin/native/internal/Intrinsics.kt new file mode 100644 index 00000000000..1120a5cd60a --- /dev/null +++ b/kotlin-native/runtime/src/main/kotlin/kotlin/native/internal/Intrinsics.kt @@ -0,0 +1,32 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +package kotlin.native.internal + +import kotlinx.cinterop.CPointer +import kotlinx.cinterop.NativePointed +import kotlinx.cinterop.NativePtr + +import kotlin.native.internal.TypedIntrinsic +import kotlin.native.internal.IntrinsicType + +@TypedIntrinsic(IntrinsicType.ARE_EQUAL_BY_VALUE) @PublishedApi external internal fun areEqualByValue(first: Boolean, second: Boolean): Boolean +@TypedIntrinsic(IntrinsicType.ARE_EQUAL_BY_VALUE) @PublishedApi external internal fun areEqualByValue(first: Byte, second: Byte): Boolean +@TypedIntrinsic(IntrinsicType.ARE_EQUAL_BY_VALUE) @PublishedApi external internal fun areEqualByValue(first: Short, second: Short): Boolean +@TypedIntrinsic(IntrinsicType.ARE_EQUAL_BY_VALUE) @PublishedApi external internal fun areEqualByValue(first: Int, second: Int): Boolean +@TypedIntrinsic(IntrinsicType.ARE_EQUAL_BY_VALUE) @PublishedApi external internal fun areEqualByValue(first: Long, second: Long): Boolean +@TypedIntrinsic(IntrinsicType.ARE_EQUAL_BY_VALUE) @PublishedApi external internal fun areEqualByValue(first: NativePtr, second: NativePtr): Boolean + +// Bitwise equality: +@TypedIntrinsic(IntrinsicType.ARE_EQUAL_BY_VALUE) @PublishedApi external internal fun areEqualByValue(first: Float, second: Float): Boolean +@TypedIntrinsic(IntrinsicType.ARE_EQUAL_BY_VALUE) @PublishedApi external internal fun areEqualByValue(first: Double, second: Double): Boolean +@TypedIntrinsic(IntrinsicType.ARE_EQUAL_BY_VALUE) @PublishedApi external internal fun areEqualByValue(first: Vector128, second: Vector128): Boolean + +// IEEE754 equality: +@TypedIntrinsic(IntrinsicType.IEEE_754_EQUALS) @PublishedApi external internal fun ieee754Equals(first: Float, second: Float): Boolean +@TypedIntrinsic(IntrinsicType.IEEE_754_EQUALS) @PublishedApi external internal fun ieee754Equals(first: Double, second: Double): Boolean + +// Reinterprets this value from T to R having the same binary representation (e.g. to unwrap inline class). +@TypedIntrinsic(IntrinsicType.IDENTITY) @PublishedApi external internal fun T.reinterpret(): R diff --git a/kotlin-native/runtime/src/main/kotlin/kotlin/native/internal/KClassImpl.kt b/kotlin-native/runtime/src/main/kotlin/kotlin/native/internal/KClassImpl.kt new file mode 100644 index 00000000000..a145346d09b --- /dev/null +++ b/kotlin-native/runtime/src/main/kotlin/kotlin/native/internal/KClassImpl.kt @@ -0,0 +1,89 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +package kotlin.native.internal + +import kotlin.reflect.KClass + +@ExportForCompiler +internal class KClassImpl(private val typeInfo: NativePtr) : KClass { + override val simpleName: String? + get() { + val relativeName = getRelativeName(typeInfo) + ?: return null + + return relativeName.substringAfterLast(".") + } + + override val qualifiedName: String? + get() { + val packageName = getPackageName(typeInfo) + ?: return null + + val relativeName = getRelativeName(typeInfo)!! + return if (packageName.isEmpty()) { + relativeName + } else { + "$packageName.$relativeName" + } + } + + override fun isInstance(value: Any?): Boolean = value != null && isInstance(value, this.typeInfo) + + override fun equals(other: Any?): Boolean = + other is KClassImpl<*> && this.typeInfo == other.typeInfo + + override fun hashCode(): Int = typeInfo.hashCode() + + override fun toString(): String { + return "class " + (qualifiedName ?: simpleName ?: "") + } + + internal fun findAssociatedObjectImpl(key: KClassImpl<*>): Any? = + findAssociatedObjectImpl(this.typeInfo, key.typeInfo) +} + +@PublishedApi +internal fun KClass<*>.findAssociatedObject(key: KClass<*>): Any? = + if (this is KClassImpl<*> && key is KClassImpl<*>) { + this.findAssociatedObjectImpl(key) + } else { + null + } + +@PublishedApi +internal class KClassUnsupportedImpl(private val message: String) : KClass { + override val simpleName: String? get() = error(message) + + override val qualifiedName: String? get() = error(message) + + override fun isInstance(value: Any?): Boolean = error(message) + + override fun equals(other: Any?): Boolean = error(message) + + override fun hashCode(): Int = error(message) + + override fun toString(): String = "unreflected class ($message)" +} + +@SymbolName("Kotlin_TypeInfo_findAssociatedObject") +private external fun findAssociatedObjectImpl(typeInfo: NativePtr, key: NativePtr): Any? + +@ExportForCompiler +@SymbolName("Kotlin_Any_getTypeInfo") +internal external fun getObjectTypeInfo(obj: Any): NativePtr + +@ExportForCompiler +@TypedIntrinsic(IntrinsicType.GET_CLASS_TYPE_INFO) +internal external inline fun getClassTypeInfo(): NativePtr + +@SymbolName("Kotlin_TypeInfo_getPackageName") +private external fun getPackageName(typeInfo: NativePtr): String? + +@SymbolName("Kotlin_TypeInfo_getRelativeName") +private external fun getRelativeName(typeInfo: NativePtr): String? + +@SymbolName("Kotlin_TypeInfo_isInstance") +private external fun isInstance(obj: Any, typeInfo: NativePtr): Boolean diff --git a/kotlin-native/runtime/src/main/kotlin/kotlin/native/internal/KFunctionImpl.kt b/kotlin-native/runtime/src/main/kotlin/kotlin/native/internal/KFunctionImpl.kt new file mode 100644 index 00000000000..bae3a016151 --- /dev/null +++ b/kotlin-native/runtime/src/main/kotlin/kotlin/native/internal/KFunctionImpl.kt @@ -0,0 +1,34 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +package kotlin.native.internal + +import kotlin.reflect.KFunction +import kotlin.reflect.KType + +@FixmeReflection +internal abstract class KFunctionImpl( + override val name: String, val fqName: String, val receiver: Any?, + val arity: Int, val flags: Int, override val returnType: KType +): KFunction { + override fun equals(other: Any?): Boolean { + if (other !is KFunctionImpl<*>) return false + return fqName == other.fqName && receiver == other.receiver + && arity == other.arity && flags == other.flags + } + + private fun evalutePolynom(x: Int, vararg coeffs: Int): Int { + var res = 0 + for (coeff in coeffs) + res = res * x + coeff + return res + } + + override fun hashCode() = evalutePolynom(31, fqName.hashCode(), receiver.hashCode(), arity, flags) + + override fun toString(): String { + return "${if (name == "") "constructor" else "function " + name}" + } +} \ No newline at end of file diff --git a/kotlin-native/runtime/src/main/kotlin/kotlin/native/internal/KPropertyImpl.kt b/kotlin-native/runtime/src/main/kotlin/kotlin/native/internal/KPropertyImpl.kt new file mode 100644 index 00000000000..d80b74cabb1 --- /dev/null +++ b/kotlin-native/runtime/src/main/kotlin/kotlin/native/internal/KPropertyImpl.kt @@ -0,0 +1,170 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +package kotlin.native.internal + +import kotlin.UnsupportedOperationException +import kotlin.reflect.* + +@FixmeReflection +open class KProperty0Impl(override val name: String, override val returnType: KType, val getter: () -> R): KProperty0 { + override fun get(): R { + return getter() + } + override fun invoke(): R { + return getter() + } + + override fun equals(other: Any?): Boolean { + val otherKProperty = other as? KProperty0Impl<*> + if (otherKProperty == null) return false + return name == otherKProperty.name && getter == otherKProperty.getter + } + + override fun hashCode(): Int { + return name.hashCode() * 31 + getter.hashCode() + } + + override fun toString(): String { + return "property $name (Kotlin reflection is not available)" + } +} + +@FixmeReflection +open class KProperty1Impl(override val name: String, override val returnType: KType, val getter: (T) -> R): KProperty1 { + override fun get(receiver: T): R { + return getter(receiver) + } + override fun invoke(p1: T): R { + return getter(p1) + } + + override fun equals(other: Any?): Boolean { + val otherKProperty = other as? KProperty1Impl<*, *> + if (otherKProperty == null) return false + return name == otherKProperty.name && getter == otherKProperty.getter + } + + override fun hashCode(): Int { + return name.hashCode() * 31 + getter.hashCode() + } + + override fun toString(): String { + return "property $name (Kotlin reflection is not available)" + } +} + +@FixmeReflection +open class KProperty2Impl(override val name: String, override val returnType: KType, val getter: (T1, T2) -> R): KProperty2 { + override fun get(receiver1: T1, receiver2: T2): R { + return getter(receiver1, receiver2) + } + override fun invoke(p1: T1, p2: T2): R { + return getter(p1, p2) + } + + override fun equals(other: Any?): Boolean { + val otherKProperty = other as? KProperty2Impl<*, *, *> + if (otherKProperty == null) return false + return name == otherKProperty.name && getter == otherKProperty.getter + } + + override fun hashCode(): Int { + return name.hashCode() * 31 + getter.hashCode() + } + + override fun toString(): String { + return "property $name (Kotlin reflection is not available)" + } +} + +@FixmeReflection +class KMutableProperty0Impl(name: String, returnType: KType, getter: () -> R, val setter: (R) -> Unit) + : KProperty0Impl(name, returnType, getter), KMutableProperty0 { + override fun set(value: R): Unit { + setter(value) + } + + override fun equals(other: Any?): Boolean { + val otherKProperty = other as? KMutableProperty0Impl<*> + if (otherKProperty == null) return false + return name == otherKProperty.name && getter == otherKProperty.getter && setter == otherKProperty.setter + } + + override fun hashCode(): Int { + return (name.hashCode() * 31 + getter.hashCode()) * 31 + setter.hashCode() + } + + override fun toString(): String { + return "property $name (Kotlin reflection is not available)" + } +} + +@FixmeReflection +class KMutableProperty1Impl(name: String, returnType: KType, getter: (T) -> R, val setter: (T, R) -> Unit) + : KProperty1Impl(name, returnType, getter), KMutableProperty1 { + override fun set(receiver: T, value: R): Unit { + setter(receiver, value) + } + + override fun equals(other: Any?): Boolean { + val otherKProperty = other as? KMutableProperty1Impl<*, *> + if (otherKProperty == null) return false + return name == otherKProperty.name && getter == otherKProperty.getter && setter == otherKProperty.setter + } + + override fun hashCode(): Int { + return (name.hashCode() * 31 + getter.hashCode()) * 31 + setter.hashCode() + } + + override fun toString(): String { + return "property $name (Kotlin reflection is not available)" + } +} + +@FixmeReflection +class KMutableProperty2Impl(name: String, returnType: KType, getter: (T1, T2) -> R, val setter: (T1, T2, R) -> Unit) + : KProperty2Impl(name, returnType, getter), KMutableProperty2 { + override fun set(receiver1: T1, receiver2: T2, value: R): Unit { + setter(receiver1, receiver2, value) + } + + override fun equals(other: Any?): Boolean { + val otherKProperty = other as? KMutableProperty2Impl<* ,*, *> + if (otherKProperty == null) return false + return name == otherKProperty.name && getter == otherKProperty.getter && setter == otherKProperty.setter + } + + override fun hashCode(): Int { + return (name.hashCode() * 31 + getter.hashCode()) * 31 + setter.hashCode() + } + + override fun toString(): String { + return "property $name (Kotlin reflection is not available)" + } +} + +open class KLocalDelegatedPropertyImpl(override val name: String, override val returnType: KType): KProperty0 { + override fun get(): R { + throw UnsupportedOperationException("Not supported for local property reference.") + } + override fun invoke(): R { + throw UnsupportedOperationException("Not supported for local property reference.") + } + + override fun toString(): String { + return "property $name (Kotlin reflection is not available)" + } +} + +class KLocalDelegatedMutablePropertyImpl(name: String, returnType: KType): KLocalDelegatedPropertyImpl(name, returnType), KMutableProperty0 { + override fun set(value: R): Unit { + throw UnsupportedOperationException("Not supported for local property reference.") + } + + override fun toString(): String { + return "property $name (Kotlin reflection is not available)" + } +} \ No newline at end of file diff --git a/kotlin-native/runtime/src/main/kotlin/kotlin/native/internal/KSuspendFunctionImpl.kt b/kotlin-native/runtime/src/main/kotlin/kotlin/native/internal/KSuspendFunctionImpl.kt new file mode 100644 index 00000000000..011311e7f05 --- /dev/null +++ b/kotlin-native/runtime/src/main/kotlin/kotlin/native/internal/KSuspendFunctionImpl.kt @@ -0,0 +1,18 @@ +/* + * Copyright 2010-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +package kotlin.native.internal + +import kotlin.reflect.KType +import kotlin.reflect.KFunction +import kotlin.reflect.KClass + +@FixmeReflection +internal abstract class KSuspendFunctionImpl( + name: String, fqName: String, receiver: Any?, + arity: Int, flags: Int, returnType: KType +): KFunctionImpl(name, fqName, receiver, arity, flags, returnType) { + override fun toString() = "suspend function $name" +} diff --git a/kotlin-native/runtime/src/main/kotlin/kotlin/native/internal/KTypeImpl.kt b/kotlin-native/runtime/src/main/kotlin/kotlin/native/internal/KTypeImpl.kt new file mode 100644 index 00000000000..cf3185cd44d --- /dev/null +++ b/kotlin-native/runtime/src/main/kotlin/kotlin/native/internal/KTypeImpl.kt @@ -0,0 +1,66 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +package kotlin.native.internal + +import kotlin.reflect.* + +internal class KTypeImpl( + override val classifier: KClassifier?, + override val arguments: List, + override val isMarkedNullable: Boolean +) : KType { + override fun equals(other: Any?) = + other is KTypeImpl && + this.classifier == other.classifier && + this.arguments == other.arguments && + this.isMarkedNullable == other.isMarkedNullable + + override fun hashCode(): Int { + return (classifier?.hashCode() ?: 0) * 31 * 31 + this.arguments.hashCode() * 31 + if (isMarkedNullable) 1 else 0 + } + + override fun toString(): String { + val classifierString = when (classifier) { + is KClass<*> -> classifier.qualifiedName ?: classifier.simpleName + is KTypeParameter -> classifier.name + else -> null + } ?: return "(non-denotable type)" + + return buildString { + append(classifierString) + + if (arguments.isNotEmpty()) { + append('<') + + arguments.forEachIndexed { index, argument -> + if (index > 0) append(", ") + + append(argument) + } + + append('>') + } + + if (isMarkedNullable) append('?') + } + } +} + +internal class KTypeImplForTypeParametersWithRecursiveBounds : KType { + override val classifier: KClassifier? + get() = error("Type parameters with recursive bounds are not yet supported in reflection") + + override val arguments: List get() = emptyList() + + override val isMarkedNullable: Boolean + get() = error("Type parameters with recursive bounds are not yet supported in reflection") + + override fun equals(other: Any?) = + error("Type parameters with recursive bounds are not yet supported in reflection") + + override fun hashCode(): Int = + error("Type parameters with recursive bounds are not yet supported in reflection") +} diff --git a/kotlin-native/runtime/src/main/kotlin/kotlin/native/internal/KTypeParameterImpl.kt b/kotlin-native/runtime/src/main/kotlin/kotlin/native/internal/KTypeParameterImpl.kt new file mode 100644 index 00000000000..f7fe3b74877 --- /dev/null +++ b/kotlin-native/runtime/src/main/kotlin/kotlin/native/internal/KTypeParameterImpl.kt @@ -0,0 +1,27 @@ +/* + * Copyright 2010-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +package kotlin.native.internal + +import kotlin.reflect.* + +internal class KTypeParameterImpl( + override val name: String, + private val containerFqName: String, + override val upperBounds: List, + override val variance: KVariance, + override val isReified: Boolean +) : KTypeParameter { + override fun toString(): String = when (variance) { + KVariance.INVARIANT -> "" + KVariance.IN -> "in " + KVariance.OUT -> "out " + } + name + + override fun equals(other: Any?) = + other is KTypeParameterImpl && name == other.name && containerFqName == other.containerFqName + + override fun hashCode() = containerFqName.hashCode() * 31 + name.hashCode() +} \ No newline at end of file diff --git a/kotlin-native/runtime/src/main/kotlin/kotlin/native/internal/KonanCollections.kt b/kotlin-native/runtime/src/main/kotlin/kotlin/native/internal/KonanCollections.kt new file mode 100644 index 00000000000..d98bdc71a34 --- /dev/null +++ b/kotlin-native/runtime/src/main/kotlin/kotlin/native/internal/KonanCollections.kt @@ -0,0 +1,15 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +package kotlin.native.internal + +internal interface KonanSet : Set { + /** + * Searches for the specified element in this set. + * + * @return the element from the set equal to [element], or `null` if no such element found. + */ + fun getElement(element: @UnsafeVariance E): E? +} diff --git a/kotlin-native/runtime/src/main/kotlin/kotlin/native/internal/KonanRuntimeTypes.kt b/kotlin-native/runtime/src/main/kotlin/kotlin/native/internal/KonanRuntimeTypes.kt new file mode 100644 index 00000000000..89e8c6d22d8 --- /dev/null +++ b/kotlin-native/runtime/src/main/kotlin/kotlin/native/internal/KonanRuntimeTypes.kt @@ -0,0 +1,9 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +package kotlin.native.internal + + +internal class FunctionReference \ No newline at end of file diff --git a/kotlin-native/runtime/src/main/kotlin/kotlin/native/internal/NativePtr.kt b/kotlin-native/runtime/src/main/kotlin/kotlin/native/internal/NativePtr.kt new file mode 100644 index 00000000000..64612ed3cd4 --- /dev/null +++ b/kotlin-native/runtime/src/main/kotlin/kotlin/native/internal/NativePtr.kt @@ -0,0 +1,61 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +@file:Suppress("RESERVED_MEMBER_INSIDE_INLINE_CLASS") + +package kotlin.native.internal + +@TypedIntrinsic(IntrinsicType.INTEROP_GET_NATIVE_NULL_PTR) +external fun getNativeNullPtr(): NativePtr + +class NativePtr @PublishedApi internal constructor(private val value: NonNullNativePtr?) { + companion object { + // TODO: make it properly precreated, maybe use an intrinsic for that. + val NULL = getNativeNullPtr() + } + + @TypedIntrinsic(IntrinsicType.INTEROP_NATIVE_PTR_PLUS_LONG) + external operator fun plus(offset: Long): NativePtr + + @TypedIntrinsic(IntrinsicType.INTEROP_NATIVE_PTR_TO_LONG) + external fun toLong(): Long + + override fun equals(other: Any?) = (other is NativePtr) && kotlin.native.internal.areEqualByValue(this, other) + + override fun hashCode() = this.toLong().hashCode() + + override fun toString() = "0x${this.toLong().toString(16)}" + + internal fun isNull(): Boolean = (value == null) +} + +@PublishedApi +internal class NonNullNativePtr private constructor() { // TODO: refactor to use this type widely. + @Suppress("NOTHING_TO_INLINE") + inline fun toNativePtr() = NativePtr(this) + + override fun toString() = toNativePtr().toString() + + override fun hashCode() = toNativePtr().hashCode() + + override fun equals(other: Any?) = other is NonNullNativePtr + && kotlin.native.internal.areEqualByValue(this.toNativePtr(), other.toNativePtr()) +} + +@ExportTypeInfo("theNativePtrArrayTypeInfo") +internal class NativePtrArray { + + @SymbolName("Kotlin_NativePtrArray_get") + external public operator fun get(index: Int): NativePtr + + @SymbolName("Kotlin_NativePtrArray_set") + external public operator fun set(index: Int, value: NativePtr): Unit + + val size: Int + get() = getArrayLength() + + @SymbolName("Kotlin_NativePtrArray_getArrayLength") + external private fun getArrayLength(): Int +} diff --git a/kotlin-native/runtime/src/main/kotlin/kotlin/native/internal/NumberConverter.kt b/kotlin-native/runtime/src/main/kotlin/kotlin/native/internal/NumberConverter.kt new file mode 100644 index 00000000000..cd53a538095 --- /dev/null +++ b/kotlin-native/runtime/src/main/kotlin/kotlin/native/internal/NumberConverter.kt @@ -0,0 +1,315 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package kotlin.native.internal + +@SymbolName("Kotlin_native_NumberConverter_bigIntDigitGeneratorInstImpl") +private external fun bigIntDigitGeneratorInstImpl(results: IntArray, uArray: IntArray, f: Long, e: Int, + isDenormalized: Boolean, mantissaIsZero: Boolean, p: Int) + +@SymbolName("Kotlin_native_NumberConverter_ceil") +private external fun ceil(x: Double): Double + +/** + * Converts [Float] or [Double] numbers to the [String] representation + */ +class NumberConverter { + + private var setCount: Int = 0 // Number of times u and k have been gotten. + + private var getCount: Int = 0 // Number of times u and k have been set. + + private val uArray = IntArray(64) + + private var firstK: Int = 0 + + private fun convertDouble(inputNumber: Double): String { + val p = 1023 + 52 // The power offset (precision). + @Suppress("INTEGER_OVERFLOW") + val signMask = 0x7FFFFFFFFFFFFFFFL + 1 // The mask to get the sign of. + // The number. + val eMask = 0x7FF0000000000000L // The mask to get the power bits. + val fMask = 0x000FFFFFFFFFFFFFL // The mask to get the significand. + + // Bits. + val inputNumberBits = inputNumber.bits() + // The value of the sign... 0 is positive, ~0 is negative. + val signString = if (inputNumberBits and signMask == 0L) "" else "-" + // The value of the 'power bits' of the inputNumber. + val e = (inputNumberBits and eMask shr 52).toInt() + // The value of the 'significand bits' of the inputNumber. + var f = inputNumberBits and fMask + val mantissaIsZero = f == 0L + var pow: Int + var numBits = 52 + + if (e == 2047) + return if (mantissaIsZero) signString + "Infinity" else "NaN" + if (e == 0) { + if (mantissaIsZero) + return signString + "0.0" + if (f == 1L) + // Special case to increase precision even though 2 * Double.MIN_VALUE is 1.0e-323. + return signString + "4.9E-324" + pow = 1 - p // A denormalized number. + var ff = f + while (ff and 0x0010000000000000L == 0L) { + ff = ff shl 1 + numBits-- + } + } else { + // 0 < e < 2047. + // A "normalized" number. + f = f or 0x0010000000000000L + pow = e - p + } + + if (-59 < pow && pow < 6 || pow == -59 && !mantissaIsZero) + longDigitGenerator(f, pow, e == 0, mantissaIsZero, numBits) + else + bigIntDigitGeneratorInstImpl(f, pow, e == 0, mantissaIsZero, numBits) + + if (inputNumber >= 1e7 || inputNumber <= -1e7 + || inputNumber > -1e-3 && inputNumber < 1e-3) + return signString + freeFormatExponential() + + return signString + freeFormat() + } + + private fun convertFloat(inputNumber: Float): String { + val p = 127 + 23 // The power offset (precision). + @Suppress("INTEGER_OVERFLOW") + val signMask = 0x7FFFFFFF + 1 // The mask to get the sign of the number. + val eMask = 0x7F800000 // The mask to get the power bits. + val fMask = 0x007FFFFF // The mask to get the significand bits. + + val inputNumberBits = inputNumber.bits() + // The value of the sign... 0 is positive, ~0 is negative. + val signString = if (inputNumberBits and signMask == 0) "" else "-" + // The value of the 'power bits' of the inputNumber. + val e = inputNumberBits and eMask shr 23 + // The value of the 'significand bits' of the inputNumber. + var f = inputNumberBits and fMask + val mantissaIsZero = f == 0 + var pow: Int + var numBits = 23 + + if (e == 255) + return if (mantissaIsZero) signString + "Infinity" else "NaN" + if (e == 0) { + if (mantissaIsZero) + return signString + "0.0" + pow = 1 - p // A denormalized number. + if (f < 8) { // Want more precision with smallest values. + f = f shl 2 + pow -= 2 + } + var ff = f + while (ff and 0x00800000 == 0) { + ff = ff shl 1 + numBits-- + } + } else { + // 0 < e < 255. + // A "normalized" number. + f = f or 0x00800000 + pow = e - p + } + + if (-59 < pow && pow < 35 || pow == -59 && !mantissaIsZero) + longDigitGenerator(f.toLong(), pow, e == 0, mantissaIsZero, numBits) + else + bigIntDigitGeneratorInstImpl(f.toLong(), pow, e == 0, mantissaIsZero, numBits) + if (inputNumber >= 1e7f || inputNumber <= -1e7f + || inputNumber > -1e-3f && inputNumber < 1e-3f) + return signString + freeFormatExponential() + + return signString + freeFormat() + } + + private fun freeFormatExponential(): String { + // Corresponds to process "Free-Format Exponential". + val formattedDecimal = CharArray(25) + formattedDecimal[0] = ('0' + uArray[getCount++]) + formattedDecimal[1] = '.' + // The position the next character is to be inserted into formattedDecimal. + var charPos = 2 + + var k = firstK + val expt = k + while (true) { + k-- + if (getCount >= setCount) + break + + formattedDecimal[charPos++] = ('0' + uArray[getCount++]) + } + + if (k == expt - 1) + formattedDecimal[charPos++] = '0' + formattedDecimal[charPos++] = 'E' + return unsafeStringFromCharArray(formattedDecimal, 0, charPos) + expt.toString() + } + + private fun freeFormat(): String { + // Corresponds to process "Free-Format". + val formattedDecimal = CharArray(25) + // The position the next character is to be inserted into formattedDecimal. + var charPos = 0 + var k = firstK + if (k < 0) { + formattedDecimal[0] = '0' + formattedDecimal[1] = '.' + charPos += 2 + for (i in k + 1 .. -1) + formattedDecimal[charPos++] = '0' + } + + var u = uArray[getCount++] + do { + if (u != -1) + formattedDecimal[charPos++] = ('0' + u) + else if (k >= -1) + formattedDecimal[charPos++] = '0' + + if (k == 0) + formattedDecimal[charPos++] = '.' + + k-- + u = if (getCount < setCount) uArray[getCount++] else -1 + } while (u != -1 || k >= -1) + return unsafeStringFromCharArray(formattedDecimal, 0, charPos) + } + + private fun bigIntDigitGeneratorInstImpl(f: Long, e: Int, + isDenormalized: Boolean, mantissaIsZero: Boolean, p: Int) { + val results = IntArray(3) + bigIntDigitGeneratorInstImpl(results, uArray, f, e, isDenormalized, mantissaIsZero, p) + setCount = results[0] + getCount = results[1] + firstK = results[2] + } + + private fun longDigitGenerator(f: Long, e: Int, isDenormalized: Boolean, + mantissaIsZero: Boolean, p: Int) { + var r: Long + var s: Long + var m: Long + if (e >= 0) { + m = 1L shl e + if (!mantissaIsZero) { + r = f shl e + 1 + s = 2 + } else { + r = f shl e + 2 + s = 4 + } + } else { + m = 1 + if (isDenormalized || !mantissaIsZero) { + r = f shl 1 + s = 1L shl 1 - e + } else { + r = f shl 2 + s = 1L shl 2 - e + } + } + + val k = ceil((e + p - 1) * invLogOfTenBaseTwo - 1e-10).toInt() + + if (k > 0) { + s *= TEN_TO_THE[k] + } else if (k < 0) { + val scale = TEN_TO_THE[-k] + r *= scale + m = if (m == 1L) scale else m * scale + } + + if (r + m > s) { // Was M_plus. + firstK = k + } else { + firstK = k - 1 + r *= 10 + m *= 10 + } + + setCount = 0 + getCount = setCount // Reset indices. + var low: Boolean + var high: Boolean + var u: Int + val si = longArrayOf(s, s shl 1, s shl 2, s shl 3) + while (true) { + // Set U to be floor (r / s) and r to be the remainder + // using a kind of "binary search" to find the answer. + // It's a lot quicker than actually dividing since we know + // the answer will be between 0 and 10. + u = 0 + var remainder: Long + for (i in 3 downTo 0) { + remainder = r - si[i] + if (remainder >= 0) { + r = remainder + u += 1 shl i + } + } + + low = r < m // Was M_minus. + high = r + m > s // Was M_plus. + + if (low || high) + break + + r *= 10 + m *= 10 + uArray[setCount++] = u + } + if (low && !high) + uArray[setCount++] = u + else if (high && !low) + uArray[setCount++] = u + 1 + else if (r shl 1 < s) + uArray[setCount++] = u + else + uArray[setCount++] = u + 1 + } + + companion object { + + private val invLogOfTenBaseTwo = 0.30102999566398114251 + + private val TEN_TO_THE = LongArray(20) + + init { + TEN_TO_THE[0] = 1L + for (i in 1 until TEN_TO_THE.size) { + TEN_TO_THE[i] = TEN_TO_THE[i - 1] * 10 + } + } + + private val converter: NumberConverter + get() = NumberConverter() + + fun convert(input: Double): String { + return converter.convertDouble(input) + } + + fun convert(input: Float): String { + return converter.convertFloat(input) + } + } +} \ No newline at end of file diff --git a/kotlin-native/runtime/src/main/kotlin/kotlin/native/internal/ObjCExportCoroutines.kt b/kotlin-native/runtime/src/main/kotlin/kotlin/native/internal/ObjCExportCoroutines.kt new file mode 100644 index 00000000000..c8a6188dc5f --- /dev/null +++ b/kotlin-native/runtime/src/main/kotlin/kotlin/native/internal/ObjCExportCoroutines.kt @@ -0,0 +1,66 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +package kotlin.native.internal + +import kotlin.coroutines.* +import kotlin.coroutines.intrinsics.* +import kotlin.coroutines.native.internal.* +import kotlin.native.concurrent.* + +@ExportForCppRuntime +private fun Kotlin_ObjCExport_createContinuationArgumentImpl( + completionHolder: Any, + exceptionTypes: NativePtr +): Continuation = createContinuationArgumentFromCallback(EmptyCompletion) { result -> + result.fold( + onSuccess = { value -> + runCompletionSuccess(completionHolder, value) + }, + onFailure = { exception -> + runCompletionFailure(completionHolder, exception, exceptionTypes) + } + ) +} + +private object EmptyCompletion : Continuation { + override val context: CoroutineContext + get() = EmptyCoroutineContext + + override fun resumeWith(result: Result) { + val exception = result.exceptionOrNull() ?: return + TerminateWithUnhandledException(exception) + // Throwing the exception from [resumeWith] is not generally expected. + // Also terminating is consistent with other pieces of ObjCExport machinery. + } +} + +@PublishedApi +@ExportForCppRuntime("Kotlin_ObjCExport_resumeContinuationSuccess") // Also makes it a data flow root. +internal fun resumeContinuation(continuation: Continuation, value: Any?) { + continuation.resume(value) +} + +@PublishedApi +@ExportForCppRuntime("Kotlin_ObjCExport_resumeContinuationFailure") // Also makes it a data flow root. +internal fun resumeContinuationWithException(continuation: Continuation, exception: Throwable) { + continuation.resumeWithException(exception) +} + +@PublishedApi +@ExportForCompiler // Mark as data flow root. +internal fun getCoroutineSuspended(): Any = COROUTINE_SUSPENDED + +@PublishedApi +@ExportForCompiler // Mark as data flow root. +internal fun interceptedContinuation(continuation: Continuation): Continuation = continuation.intercepted() + +@FilterExceptions +@SymbolName("Kotlin_ObjCExport_runCompletionSuccess") +private external fun runCompletionSuccess(completionHolder: Any, result: Any?) + +@FilterExceptions +@SymbolName("Kotlin_ObjCExport_runCompletionFailure") +private external fun runCompletionFailure(completionHolder: Any, exception: Throwable, exceptionTypes: NativePtr) \ No newline at end of file diff --git a/kotlin-native/runtime/src/main/kotlin/kotlin/native/internal/ObjCExportUtils.kt b/kotlin-native/runtime/src/main/kotlin/kotlin/native/internal/ObjCExportUtils.kt new file mode 100644 index 00000000000..1454a625c26 --- /dev/null +++ b/kotlin-native/runtime/src/main/kotlin/kotlin/native/internal/ObjCExportUtils.kt @@ -0,0 +1,295 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +package kotlin.native.internal + +import kotlin.native.internal.ExportForCppRuntime +import kotlin.native.internal.KonanSet +import kotlin.native.internal.ReportUnhandledException + +/** + * This interface denotes the object to be a wrapper for the Objective-C object, + * so the latter should be used to observe object lifetime. + */ +@ExportTypeInfo("theObjCObjectWrapperTypeInfo") +internal interface ObjCObjectWrapper + +internal class NSArrayAsKList : AbstractList(), ObjCObjectWrapper { + + override val size: Int get() = getSize() + + @SymbolName("Kotlin_NSArrayAsKList_getSize") + private external fun getSize(): Int + + @SymbolName("Kotlin_NSArrayAsKList_get") + external override fun get(index: Int): Any? +} + +internal class NSMutableArrayAsKMutableList : AbstractMutableList(), ObjCObjectWrapper { + + override val size: Int get() = getSize() + + @SymbolName("Kotlin_NSArrayAsKList_getSize") + private external fun getSize(): Int + + @SymbolName("Kotlin_NSArrayAsKList_get") + external override fun get(index: Int): Any? + + @SymbolName("Kotlin_NSMutableArrayAsKMutableList_add") + external override fun add(index: Int, element: Any?): Unit + + @SymbolName("Kotlin_NSMutableArrayAsKMutableList_removeAt") + external override fun removeAt(index: Int): Any? + + @SymbolName("Kotlin_NSMutableArrayAsKMutableList_set") + external override fun set(index: Int, element: Any?): Any? +} + +internal class NSSetAsKSet : AbstractSet(), KonanSet, ObjCObjectWrapper { + + override val size: Int get() = getSize() + + @SymbolName("Kotlin_NSSetAsKSet_getSize") + private external fun getSize(): Int + + @SymbolName("Kotlin_NSSetAsKSet_contains") + external override fun contains(element: Any?): Boolean + + @SymbolName("Kotlin_NSSetAsKSet_getElement") + external override fun getElement(element: Any?): Any? + + @SymbolName("Kotlin_NSSetAsKSet_iterator") + external override fun iterator(): Iterator +} + +internal class NSDictionaryAsKMap : Map, ObjCObjectWrapper { + + override fun equals(other: Any?): Boolean { + if (this === other) return true + if (other !is Map<*, *>) return false + if (this.size != other.size) return false + + return other.entries.all { this.containsEntry(it.key, it.value) } + } + + override fun hashCode(): Int { + var result = 0 + keyIterator().forEach { key -> + result += key.hashCode() xor this.getOrThrowConcurrentModification(key).hashCode() + } + return result + } + + override fun toString(): String = entries.joinToString(", ", "{", "}") { toString(it.key) + "=" + toString(it.value) } + + private fun toString(o: Any?): String = if (o === this) "(this Map)" else o.toString() + + override val size: Int get() = getSize() + + @SymbolName("Kotlin_NSDictionaryAsKMap_getSize") + private external fun getSize(): Int + + override fun isEmpty(): Boolean = (size == 0) + + @SymbolName("Kotlin_NSDictionaryAsKMap_containsKey") + override external fun containsKey(key: Any?): Boolean + + @SymbolName("Kotlin_NSDictionaryAsKMap_containsValue") + override external fun containsValue(value: Any?): Boolean + + @SymbolName("Kotlin_NSDictionaryAsKMap_get") + external override operator fun get(key: Any?): Any? + + @SymbolName("Kotlin_NSDictionaryAsKMap_getOrThrowConcurrentModification") + private external fun getOrThrowConcurrentModification(key: Any?): Any? + + @SymbolName("Kotlin_NSDictionaryAsKMap_containsEntry") + private external fun containsEntry(key: Any?, value: Any?): Boolean + + // Views + override val keys: Set get() = this.Keys() + + override val values: Collection get() = this.Values() + + override val entries: Set> get() = this.Entries() + + @SymbolName("Kotlin_NSDictionaryAsKMap_keyIterator") + private external fun keyIterator(): Iterator + + private inner class Keys : AbstractSet() { + + override val size: Int get() = this@NSDictionaryAsKMap.size + + override fun iterator(): Iterator = this@NSDictionaryAsKMap.keyIterator() + + override fun contains(element: Any?): Boolean = this@NSDictionaryAsKMap.containsKey(element) + } + + @SymbolName("Kotlin_NSDictionaryAsKMap_valueIterator") + private external fun valueIterator(): Iterator + + private inner class Values : AbstractCollection() { + // TODO: what about equals and hashCode? + + override val size: Int get() = this@NSDictionaryAsKMap.size + + override fun iterator(): Iterator = this@NSDictionaryAsKMap.valueIterator() + + override fun contains(element: Any?): Boolean = this@NSDictionaryAsKMap.containsValue(element) + } + + private inner class Entries : AbstractSet>() { + + override val size: Int get() = this@NSDictionaryAsKMap.size + + override fun iterator(): Iterator> = this@NSDictionaryAsKMap.EntryIterator() + + override fun contains(element: Map.Entry): Boolean { + return this@NSDictionaryAsKMap.containsEntry(element.key, element.value) + } + } + + private class Entry(override val key: Any?, override val value: Any?) : Map.Entry { + override fun equals(other: Any?): Boolean = + other is Map.Entry<*, *> && + other.key == key && + other.value == value + + override fun hashCode(): Int = key.hashCode() xor value.hashCode() + + override fun toString(): String = "$key=$value" + } + + private inner class EntryIterator : Iterator> { + val keyIterator = this@NSDictionaryAsKMap.keyIterator() + + override fun hasNext(): Boolean = keyIterator.hasNext() + + override fun next(): Map.Entry { + val nextKey = keyIterator.next() + val nextValue = this@NSDictionaryAsKMap.getOrThrowConcurrentModification(nextKey) + + return Entry(nextKey, nextValue) + } + } + +} + +internal class NSEnumeratorAsKIterator : AbstractIterator() { + + @SymbolName("Kotlin_NSEnumeratorAsKIterator_computeNext") + override external fun computeNext() + + @ExportForCppRuntime + private fun Kotlin_NSEnumeratorAsKIterator_done() = this.done() + + @ExportForCppRuntime + private fun Kotlin_NSEnumeratorAsKIterator_setNext(value: Any?) = this.setNext(value) +} + +@ExportForCppRuntime private fun Kotlin_Collection_getSize(collection: Collection<*>): Int = collection.size + +@ExportForCppRuntime private fun Kotlin_List_get(list: List<*>, index: Int): Any? = list.get(index) + +@ExportForCppRuntime private fun Kotlin_MutableList_addObjectAtIndex(list: MutableList, index: Int, obj: Any?) { + list.add(index, obj) +} + +@ExportForCppRuntime private fun Kotlin_MutableList_removeObjectAtIndex(list: MutableList, index: Int) { + list.removeAt(index) +} + +@ExportForCppRuntime private fun Kotlin_MutableCollection_addObject(list: MutableCollection, obj: Any?) { + list.add(obj) +} + +@ExportForCppRuntime private fun Kotlin_MutableList_removeLastObject(list: MutableList) { + list.removeAt(list.lastIndex) +} + +@ExportForCppRuntime private fun Kotlin_MutableList_setObject(list: MutableList, index: Int, obj: Any?) { + list.set(index, obj) +} + +@ExportForCppRuntime private fun Kotlin_MutableCollection_removeObject( + collection: MutableCollection, element: Any? +) { + collection.remove(element) +} + +@ExportForCppRuntime private fun Kotlin_Iterator_hasNext(iterator: Iterator): Boolean = iterator.hasNext() +@ExportForCppRuntime private fun Kotlin_Iterator_next(iterator: Iterator): Any? = iterator.next() + +@ExportForCppRuntime private fun Kotlin_Set_contains(set: Set, element: Any?): Boolean = set.contains(element) + +@ExportForCppRuntime private fun Kotlin_Set_getElement(set: Set, element: Any?): Any? = + if (set is KonanSet) { + set.getElement(element) + } else if (set.contains(element)) { + set.first { it == element } + } else { + null + } + +@ExportForCppRuntime private fun Kotlin_Set_iterator(set: Set): Iterator = set.iterator() +@ExportForCppRuntime private fun Kotlin_MutableSet_createWithCapacity(capacity: Int): MutableSet = + HashSet(capacity) + +@ExportForCppRuntime private fun Kotlin_Map_getSize(map: Map): Int = map.size +@ExportForCppRuntime private fun Kotlin_Map_containsKey(map: Map, key: Any?): Boolean = map.containsKey(key) +@ExportForCppRuntime private fun Kotlin_Map_get(map: Map, key: Any?): Any? = map.get(key) +@ExportForCppRuntime private fun Kotlin_Map_keyIterator(map: Map): Iterator = map.keys.iterator() + +@ExportForCppRuntime private fun Kotlin_MutableMap_createWithCapacity(capacity: Int): MutableMap = + HashMap(capacity) + +@ExportForCppRuntime private fun Kotlin_MutableMap_set(map: MutableMap, key: Any?, value: Any?) { + map.set(key, value) +} +@ExportForCppRuntime private fun Kotlin_MutableMap_remove(map: MutableMap, key: Any?) { + map.remove(key) +} + +@ExportForCppRuntime private fun Kotlin_ObjCExport_ThrowCollectionTooLarge() { + throw Error("an Objective-C collection is too large") +} + +@ExportForCppRuntime private fun Kotlin_ObjCExport_ThrowCollectionConcurrentModification() { + throw Error("an Objective-C collection was modified while iterating") +} + +@ExportForCppRuntime private fun Kotlin_NSArrayAsKList_create() = NSArrayAsKList() +@ExportForCppRuntime private fun Kotlin_NSMutableArrayAsKMutableList_create() = NSMutableArrayAsKMutableList() +@ExportForCppRuntime private fun Kotlin_NSEnumeratorAsKIterator_create() = NSEnumeratorAsKIterator() +@ExportForCppRuntime private fun Kotlin_NSSetAsKSet_create() = NSSetAsKSet() +@ExportForCppRuntime private fun Kotlin_NSDictionaryAsKMap_create() = NSDictionaryAsKMap() + +@ExportForCppRuntime private fun Kotlin_ObjCExport_NSErrorAsExceptionImpl( + message: String?, + error: Any +) = ObjCErrorException(message, error) + +class ObjCErrorException( + message: String?, + internal val error: Any +) : Exception(message) { + override fun toString(): String = "NSError-based exception: $message" +} + +@PublishedApi +@SymbolName("Kotlin_ObjCExport_trapOnUndeclaredException") +@ExportForCppRuntime +internal external fun trapOnUndeclaredException(exception: Throwable) + +@ExportForCppRuntime +private fun Kotlin_Throwable_getMessage(throwable: Throwable): String? = throwable.message + +@ExportForCppRuntime +private fun Kotlin_ObjCExport_getWrappedError(throwable: Throwable): Any? = + (throwable as? ObjCErrorException)?.error + +@ExportTypeInfo("theOpaqueFunctionTypeInfo") +@PublishedApi +internal class OpaqueFunction : Function diff --git a/kotlin-native/runtime/src/main/kotlin/kotlin/native/internal/Ref.kt b/kotlin-native/runtime/src/main/kotlin/kotlin/native/internal/Ref.kt new file mode 100644 index 00000000000..5d112420d5d --- /dev/null +++ b/kotlin-native/runtime/src/main/kotlin/kotlin/native/internal/Ref.kt @@ -0,0 +1,13 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +package kotlin.native.internal + +/** + * This class is used to allocate closure-captured variables in the heap. + */ +class Ref { + var element: T = undefined() +} \ No newline at end of file diff --git a/kotlin-native/runtime/src/main/kotlin/kotlin/native/internal/RuntimeUtils.kt b/kotlin-native/runtime/src/main/kotlin/kotlin/native/internal/RuntimeUtils.kt new file mode 100644 index 00000000000..f4cdde2d06d --- /dev/null +++ b/kotlin-native/runtime/src/main/kotlin/kotlin/native/internal/RuntimeUtils.kt @@ -0,0 +1,217 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +package kotlin.native.internal + +import kotlin.internal.getProgressionLastElement +import kotlin.reflect.KClass + +@ExportForCppRuntime +fun ThrowNullPointerException(): Nothing { + throw NullPointerException() +} + +@ExportForCppRuntime +internal fun ThrowIndexOutOfBoundsException(): Nothing { + throw IndexOutOfBoundsException() +} + +@ExportForCppRuntime +internal fun ThrowArrayIndexOutOfBoundsException(): Nothing { + throw ArrayIndexOutOfBoundsException() +} + +@ExportForCppRuntime +fun ThrowClassCastException(instance: Any, typeInfo: NativePtr): Nothing { + val clazz = KClassImpl(typeInfo) + throw ClassCastException("${instance::class.qualifiedName} cannot be cast to ${clazz.qualifiedName}") +} + +@ExportForCppRuntime +fun ThrowTypeCastException(): Nothing { + throw TypeCastException() +} + +@ExportForCppRuntime +fun ThrowKotlinNothingValueException(): Nothing { + throw KotlinNothingValueException() +} + +@ExportForCppRuntime +fun ThrowInvalidReceiverTypeException(klass: KClass<*>): Nothing { + throw RuntimeException("Unexpected receiver type: " + (klass.qualifiedName ?: "noname")) +} + +@ExportForCppRuntime +internal fun ThrowArithmeticException() : Nothing { + throw ArithmeticException() +} + +@ExportForCppRuntime +internal fun ThrowNumberFormatException() : Nothing { + throw NumberFormatException() +} + +@ExportForCppRuntime +internal fun ThrowOutOfMemoryError() : Nothing { + throw OutOfMemoryError() +} + +fun ThrowNoWhenBranchMatchedException(): Nothing { + throw NoWhenBranchMatchedException() +} + +fun ThrowUninitializedPropertyAccessException(propertyName: String): Nothing { + throw UninitializedPropertyAccessException("lateinit property $propertyName has not been initialized") +} + +@ExportForCppRuntime +internal fun ThrowIllegalArgumentException() : Nothing { + throw IllegalArgumentException() +} + +@ExportForCppRuntime +internal fun ThrowIllegalArgumentExceptionWithMessage(message: String) : Nothing { + throw IllegalArgumentException(message) +} + +@ExportForCppRuntime +internal fun ThrowIllegalStateException() : Nothing { + throw IllegalStateException() +} + +@ExportForCppRuntime +internal fun ThrowIllegalStateExceptionWithMessage(message:String) : Nothing { + throw IllegalStateException(message) +} + + +@ExportForCppRuntime +internal fun ThrowNotImplementedError(): Nothing { + throw NotImplementedError("An operation is not implemented.") +} + +@ExportForCppRuntime +internal fun ThrowCharacterCodingException(): Nothing { + throw CharacterCodingException() +} + +@ExportForCppRuntime +internal fun ThrowIncorrectDereferenceException() { + throw IncorrectDereferenceException( + "Trying to access top level value not marked as @ThreadLocal or @SharedImmutable from non-main thread") +} + +@ExportForCppRuntime +internal fun PrintThrowable(throwable: Throwable) { + println(throwable) +} + +@ExportForCppRuntime +internal fun ReportUnhandledException(throwable: Throwable) { + print("Uncaught Kotlin exception: ") + throwable.printStackTrace() +} + +@SymbolName("TerminateWithUnhandledException") +internal external fun TerminateWithUnhandledException(throwable: Throwable) + +@ExportForCppRuntime +internal fun ExceptionReporterLaunchpad(reporter: (Throwable) -> Unit, throwable: Throwable) { + try { + reporter(throwable) + } catch (t: Throwable) { + ReportUnhandledException(t) + } +} + +@ExportForCppRuntime +internal fun TheEmptyString() = "" + +public fun > valueOfForEnum(name: String, values: Array) : T { + var left = 0 + var right = values.size - 1 + while (left <= right) { + val middle = (left + right) / 2 + val x = values[middle].name.compareTo(name) + when { + x < 0 -> left = middle + 1 + x > 0 -> right = middle - 1 + else -> return values[middle] + } + } + throw Exception("Invalid enum value name: $name") +} + +public fun > valuesForEnum(values: Array): Array { + val result = @Suppress("TYPE_PARAMETER_AS_REIFIED") Array(values.size) + for (value in values) + result[value.ordinal] = value + @Suppress("UNCHECKED_CAST") + return result as Array +} + +@PublishedApi +@TypedIntrinsic(IntrinsicType.CREATE_UNINITIALIZED_INSTANCE) +internal external fun createUninitializedInstance(): T + +@PublishedApi +@TypedIntrinsic(IntrinsicType.INIT_INSTANCE) +internal external fun initInstance(thiz: Any, constructorCall: Any): Unit + +@PublishedApi +internal fun checkProgressionStep(step: Int) = + if (step > 0) step else throw IllegalArgumentException("Step must be positive, was: $step.") +@PublishedApi +internal fun checkProgressionStep(step: Long) = + if (step > 0) step else throw IllegalArgumentException("Step must be positive, was: $step.") + +@PublishedApi +internal fun getProgressionLast(start: Char, end: Char, step: Int): Char = + getProgressionLast(start.toInt(), end.toInt(), step).toChar() + +@PublishedApi +internal fun getProgressionLast(start: Int, end: Int, step: Int): Int = + getProgressionLastElement(start, end, step) +@PublishedApi +internal fun getProgressionLast(start: Long, end: Long, step: Long): Long = + getProgressionLastElement(start, end, step) + +@PublishedApi +// Called by the debugger. +@ExportForCppRuntime +internal fun KonanObjectToUtf8Array(value: Any?): ByteArray { + val string = try { + when (value) { + is Array<*> -> value.contentToString() + is CharArray -> value.contentToString() + is BooleanArray -> value.contentToString() + is ByteArray -> value.contentToString() + is ShortArray -> value.contentToString() + is IntArray -> value.contentToString() + is LongArray -> value.contentToString() + is FloatArray -> value.contentToString() + is DoubleArray -> value.contentToString() + else -> value.toString() + } + } catch (error: Throwable) { + "" + } + return string.encodeToByteArray() +} + +@TypedIntrinsic(IntrinsicType.LIST_OF_INTERNAL) +@PublishedApi +internal fun listOfInternal(vararg elements: T): List { + val result = ArrayList(elements.size) + for (i in 0 until elements.size) + result.add(elements[i]) + return result +} + + +@PublishedApi +@SymbolName("OnUnhandledException") +external internal fun OnUnhandledException(throwable: Throwable) diff --git a/kotlin-native/runtime/src/main/kotlin/kotlin/native/internal/Undefined.kt b/kotlin-native/runtime/src/main/kotlin/kotlin/native/internal/Undefined.kt new file mode 100644 index 00000000000..2a3723cbddf --- /dev/null +++ b/kotlin-native/runtime/src/main/kotlin/kotlin/native/internal/Undefined.kt @@ -0,0 +1,13 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +package kotlin.native.internal + +/** + * Returns undefined value of type `T`. + * This method is unsafe and should be used with care. + */ +@SymbolName("Kotlin_native_internal_undefined") +internal external fun undefined(): T \ No newline at end of file diff --git a/kotlin-native/runtime/src/main/kotlin/kotlin/native/internal/Utils.kt b/kotlin-native/runtime/src/main/kotlin/kotlin/native/internal/Utils.kt new file mode 100644 index 00000000000..d1d4435bc53 --- /dev/null +++ b/kotlin-native/runtime/src/main/kotlin/kotlin/native/internal/Utils.kt @@ -0,0 +1,21 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +package kotlin.native.internal + +import kotlin.reflect.KClass + +@ExportForCppRuntime +internal fun DescribeObjectForDebugging(typeInfo: NativePtr, address: NativePtr): String { + val kClass = kotlin.native.internal.KClassImpl(typeInfo) + return debugDescription(kClass, address.toLong().toInt()) +} + +internal fun debugDescription(kClass: KClass<*>, identity: Int): String { + val className = kClass.qualifiedName ?: kClass.simpleName ?: "" + val unsignedIdentity = identity.toLong() and 0xffffffffL + val identityStr = unsignedIdentity.toString(16) + return "$className@$identityStr" +} diff --git a/kotlin-native/runtime/src/main/kotlin/kotlin/native/internal/test/GTestLogger.kt b/kotlin-native/runtime/src/main/kotlin/kotlin/native/internal/test/GTestLogger.kt new file mode 100644 index 00000000000..432a7c7ed01 --- /dev/null +++ b/kotlin-native/runtime/src/main/kotlin/kotlin/native/internal/test/GTestLogger.kt @@ -0,0 +1,63 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +package kotlin.native.internal.test + +internal class GTestLogger : TestLoggerWithStatistics() { + + private val Collection.totalTestsNotIgnored: Int + get() = asSequence().filter { !it.ignored }.sumBy { it.testCases.values.count { !it.ignored } } + + private val Collection.totalNotIgnored: Int + get() = filter { !it.ignored }.size + + override fun startIteration(runner: TestRunner, iteration: Int, suites: Collection) { + if (runner.iterations != 1) { + println("\nRepeating all tests (iteration $iteration) . . .\n") + } + super.startIteration(runner, iteration, suites) + println("[==========] Running ${suites.totalTestsNotIgnored} tests from ${suites.totalNotIgnored} test cases.") + // Just hack to deal with GTest output parsers. + println("[----------] Global test environment set-up.") + } + + private fun printResults(timeMillis: Long) = with (statistics) { + println("[----------] Global test environment tear-down") // Just hack to deal with GTest output parsers. + println("[==========] $total tests from $totalSuites test cases ran. ($timeMillis ms total)") + println("[ PASSED ] $passed tests.") + if (hasFailedTests) { + println("[ FAILED ] $failed tests, listed below:") + failedTests.forEach { + println("[ FAILED ] ${it.prettyName}") + } + println("\n$failed FAILED TESTS") + } + if (ignored != 0) { + println("YOU HAVE $ignored DISABLED TEST(S)") + } + } + + override fun finishIteration(runner: TestRunner, iteration: Int, timeMillis: Long) = printResults(timeMillis) + + override fun startSuite(suite: TestSuite) = println("[----------] ${suite.size} tests from ${suite.name}") + + override fun finishSuite(suite: TestSuite, timeMillis: Long) { + super.finishSuite(suite, timeMillis) + println("[----------] ${suite.size} tests from ${suite.name} ($timeMillis ms total)\n") + } + + override fun start(testCase: TestCase) = println("[ RUN ] ${testCase.prettyName}") + + override fun pass(testCase: TestCase, timeMillis: Long) { + super.pass(testCase, timeMillis) + println("[ OK ] ${testCase.prettyName} ($timeMillis ms)") + } + + override fun fail(testCase: TestCase, e: Throwable, timeMillis: Long) { + super.fail(testCase, e, timeMillis) + e.printStackTrace() + println("[ FAILED ] ${testCase.prettyName} ($timeMillis ms)") + } +} diff --git a/kotlin-native/runtime/src/main/kotlin/kotlin/native/internal/test/Launcher.kt b/kotlin-native/runtime/src/main/kotlin/kotlin/native/internal/test/Launcher.kt new file mode 100644 index 00000000000..5f11161fff1 --- /dev/null +++ b/kotlin-native/runtime/src/main/kotlin/kotlin/native/internal/test/Launcher.kt @@ -0,0 +1,40 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +package kotlin.native.internal.test + +import kotlin.system.exitProcess +import kotlin.native.concurrent.* + +@ThreadLocal +private object GeneratedSuites { + val suites = mutableListOf() + fun add(suite: TestSuite) = suites.add(suite) +} + +public fun registerSuite(suite: TestSuite): Unit { + GeneratedSuites.add(suite) +} + +fun testLauncherEntryPoint(args: Array): Int { + return TestRunner(GeneratedSuites.suites, args).run() +} + +fun main(args: Array) { + exitProcess(testLauncherEntryPoint(args)) +} + +fun worker(args: Array) { + val worker = Worker.start() + val result = worker.execute(TransferMode.SAFE, { args.freeze() }) { + it -> testLauncherEntryPoint(it) + }.result + worker.requestTermination().result + exitProcess(result) +} + +fun mainNoExit(args: Array) { + testLauncherEntryPoint(args) +} diff --git a/kotlin-native/runtime/src/main/kotlin/kotlin/native/internal/test/TeamCityLogger.kt b/kotlin-native/runtime/src/main/kotlin/kotlin/native/internal/test/TeamCityLogger.kt new file mode 100644 index 00000000000..984a0eca6f2 --- /dev/null +++ b/kotlin-native/runtime/src/main/kotlin/kotlin/native/internal/test/TeamCityLogger.kt @@ -0,0 +1,61 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +package kotlin.native.internal.test + +import kotlin.text.StringBuilder + +internal class TeamCityLogger : BaseTestLogger() { + + private fun String.escapeForTC(): String = StringBuilder(length).apply { + for(char in this@escapeForTC) { + append(when(char) { + '|' -> "||" + '\'' -> "|'" + '\n' -> "|n" + '\r' -> "|r" + '[' -> "|[" + ']' -> "|]" + else -> char + }) + } + }.toString() + + private val TestCase.tcName + get() = name.escapeForTC() + + private val TestSuite.tcName + get() = name.escapeForTC() + + private fun finish(testCase: TestCase, durationMs: Long) = + report("testFinished name='${testCase.tcName}' duration='$durationMs'") + + private fun report(msg: String) = println("##teamcity[$msg]") + + override fun start(testCase: TestCase) = report("testStarted" + + " name='${testCase.tcName}'" + + " locationHint='ktest:test://${testCase.suite.tcName}.${testCase.tcName}'") + override fun startSuite(suite: TestSuite) = report("testSuiteStarted" + + " name='${suite.tcName}'" + + " locationHint='ktest:suite://${suite.tcName}'") + + override fun ignoreSuite(suite: TestSuite) { + startSuite(suite) + suite.testCases.values.forEach { ignore(it) } + finishSuite(suite, 0L) + } + + override fun finishSuite(suite: TestSuite, timeMillis: Long) = report("testSuiteFinished name='${suite.tcName}'") + + override fun pass(testCase: TestCase, timeMillis: Long) = finish(testCase, timeMillis) + override fun fail(testCase: TestCase, e: Throwable, timeMillis: Long) { + val stackTrace = e.dumpStackTrace().escapeForTC() + val message = e.message?.escapeForTC() + report("testFailed name='${testCase.tcName}' message='$message' details='$stackTrace'") + finish(testCase, timeMillis) + } + + override fun ignore(testCase: TestCase) = report("testIgnored name='${testCase.tcName}'") +} \ No newline at end of file diff --git a/kotlin-native/runtime/src/main/kotlin/kotlin/native/internal/test/TestListener.kt b/kotlin-native/runtime/src/main/kotlin/kotlin/native/internal/test/TestListener.kt new file mode 100644 index 00000000000..19eb544a61f --- /dev/null +++ b/kotlin-native/runtime/src/main/kotlin/kotlin/native/internal/test/TestListener.kt @@ -0,0 +1,37 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +package kotlin.native.internal.test + +internal interface TestListener { + fun startTesting(runner: TestRunner) + fun finishTesting(runner: TestRunner, timeMillis: Long) + + fun startIteration(runner: TestRunner, iteration: Int, suites: Collection) + fun finishIteration(runner: TestRunner, iteration: Int, timeMillis: Long) + + fun startSuite(suite: TestSuite) + fun finishSuite(suite: TestSuite, timeMillis: Long) + fun ignoreSuite(suite: TestSuite) + + fun start(testCase: TestCase) + fun pass(testCase: TestCase, timeMillis: Long) + fun fail(testCase: TestCase, e: Throwable, timeMillis: Long) + fun ignore(testCase: TestCase) +} + +internal open class BaseTestListener: TestListener { + override fun startTesting(runner: TestRunner) {} + override fun finishTesting(runner: TestRunner, timeMillis: Long) {} + override fun startIteration(runner: TestRunner, iteration: Int, suites: Collection) {} + override fun finishIteration(runner: TestRunner, iteration: Int, timeMillis: Long) {} + override fun startSuite(suite: TestSuite) {} + override fun finishSuite(suite: TestSuite, timeMillis: Long) {} + override fun ignoreSuite(suite: TestSuite) {} + override fun start(testCase: TestCase) {} + override fun pass(testCase: TestCase, timeMillis: Long) {} + override fun fail(testCase: TestCase, e: Throwable, timeMillis: Long) {} + override fun ignore(testCase: TestCase) {} +} diff --git a/kotlin-native/runtime/src/main/kotlin/kotlin/native/internal/test/TestLogger.kt b/kotlin-native/runtime/src/main/kotlin/kotlin/native/internal/test/TestLogger.kt new file mode 100644 index 00000000000..46ea69c791f --- /dev/null +++ b/kotlin-native/runtime/src/main/kotlin/kotlin/native/internal/test/TestLogger.kt @@ -0,0 +1,65 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +package kotlin.native.internal.test + +internal interface TestLogger: TestListener { + fun logTestList(runner: TestRunner, suites: Collection) + fun log(message: String) +} + +internal open class BaseTestLogger: BaseTestListener(), TestLogger { + override fun log(message: String) = println(message) + override fun logTestList(runner: TestRunner, suites: Collection) { + suites.forEach { suite -> + println("${suite.name}.") + suite.testCases.values.forEach { + println(" ${it.name}") + } + } + } +} + +internal open class TestLoggerWithStatistics: BaseTestLogger() { + + protected val statistics = MutableTestStatistics() + + override fun startTesting(runner: TestRunner) = statistics.reset() + override fun startIteration(runner: TestRunner, iteration: Int, suites: Collection) = statistics.reset() + + override fun finishSuite(suite: TestSuite, timeMillis: Long) = statistics.registerSuite() + override fun ignoreSuite(suite: TestSuite) = statistics.registerIgnore(suite.size) + override fun pass(testCase: TestCase, timeMillis: Long) = statistics.registerPass() + override fun fail(testCase: TestCase, e: Throwable, timeMillis: Long) = statistics.registerFail(testCase) + override fun ignore(testCase: TestCase) = statistics.registerIgnore() +} + +internal class SilentTestLogger: BaseTestLogger() { + override fun logTestList(runner: TestRunner, suites: Collection) {} + override fun log(message: String) {} + override fun fail(testCase: TestCase, e: Throwable, timeMillis: Long) = e.printStackTrace() +} + +internal class SimpleTestLogger: BaseTestLogger() { + override fun startTesting(runner: TestRunner) = println("Starting testing") + override fun finishTesting(runner: TestRunner, timeMillis: Long) = println("Testing finished") + + override fun startIteration(runner: TestRunner, iteration: Int, suites: Collection) = + println("Starting iteration: $iteration") + override fun finishIteration(runner: TestRunner, iteration: Int, timeMillis: Long) = + println("Iteration finished: $iteration") + + override fun startSuite(suite: TestSuite) = println("Starting test suite: $suite") + override fun finishSuite(suite: TestSuite, timeMillis: Long) = println("Test suite finished: $suite") + override fun ignoreSuite(suite: TestSuite) = println("Test suite ignored: $suite") + + override fun start(testCase: TestCase) = println("Starting test case: $testCase") + override fun pass(testCase: TestCase, timeMillis: Long) = println("Passed: $testCase") + override fun fail(testCase: TestCase, e: Throwable, timeMillis: Long) { + println("Failed: $testCase. Exception:") + e.printStackTrace() + } + override fun ignore(testCase: TestCase) = println("Ignore: $testCase") +} diff --git a/kotlin-native/runtime/src/main/kotlin/kotlin/native/internal/test/TestRunner.kt b/kotlin-native/runtime/src/main/kotlin/kotlin/native/internal/test/TestRunner.kt new file mode 100644 index 00000000000..6ca30decc49 --- /dev/null +++ b/kotlin-native/runtime/src/main/kotlin/kotlin/native/internal/test/TestRunner.kt @@ -0,0 +1,280 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +package kotlin.native.internal.test + +import kotlin.IllegalArgumentException +import kotlin.system.getTimeMillis +import kotlin.system.measureTimeMillis +import kotlin.text.StringBuilder + +internal class TestRunner(val suites: List, args: Array) { + private val filters = mutableListOf<(TestCase) -> Boolean>() + private val listeners = mutableSetOf() + private var logger: TestLogger = GTestLogger() + private var runTests = true + private var useExitCode = true + var iterations = 1 + private set + var exitCode = 0 + private set + + init { + args.filter { + it.startsWith("--gtest_") || it.startsWith("--ktest_") || it == "--help" || it == "-h" + }.forEach { + val arg = it.split('=') + when (arg.size) { + 1 -> when (arg[0]) { + "--gtest_list_tests", + "--ktest_list_tests" -> { + logger.logTestList(this, filterSuites()); runTests = false + } + "-h", + "--help" -> { + logger.log(help); runTests = false + } + "--ktest_no_exit_code" -> useExitCode = false + else -> throw IllegalArgumentException("Unknown option: $it\n$help") + } + 2 -> { + val key = arg[0] + val value = arg[1] + when (key) { + "--ktest_logger" -> setLoggerFromArg(value) + "--gtest_filter", + "--ktest_filter" -> setGTestFilterFromArg(value) + "--ktest_regex_filter" -> setRegexFilterFromArg(value, true) + "--ktest_negative_regex_filter" -> setRegexFilterFromArg(value, false) + "--ktest_gradle_filter" -> setGradleFilterFromArg(value, true) + "--ktest_negative_gradle_filter" -> setGradleFilterFromArg(value, false) + "--ktest_repeat", + "--gtest_repeat" -> iterations = value.toIntOrNull() ?: throw IllegalArgumentException("Cannot parse number: $value") + else -> throw IllegalArgumentException("Unknown option: $it\n$help") + } + } + else -> throw IllegalArgumentException("Unknown option: $it\n$help") + } + } + } + + inner class FilteredSuite(val innerSuite: TestSuite) : TestSuite by innerSuite { + + private val TestCase.matchFilters: Boolean + get() = filters.all { it(this) } + + override val size: Int + get() = testCases.size + + override val testCases: Map = innerSuite.testCases.filter { it.value.matchFilters } + override fun toString() = innerSuite.toString() + } + + private fun filterSuites(): Collection = suites.map { FilteredSuite(it) } + + // TODO: Support short aliases. + // TODO: Support several test iterations. + /** + * Initialize the TestRunner using the command line options passed in [args]. + * Returns: true if tests may be ran, false otherwise (there are unrecognized options or just help). + * The following options are available: + * + * --gtest_list_tests + * --ktest_list_tests - Show all available tests. + * + * --gtest_filter=POSITIVE_PATTERNS[-NEGATIVE_PATTERNS] + * --ktest_filter=POSITIVE_PATTERNS[-NEGATIVE_PATTERNS] - Run only the tests whose name matches one of the + * positive patterns but none of the negative patterns. + * '?' matches any single character; '*' matches any + * substring; ':' separates two patterns. + * + * --ktest_regex_filter=PATTERN - Run only the tests whose name matches the pattern. + * The pattern is a Kotlin regular expression. + * + * --ktest_negative_regex_filter=PATTERN - Run only the tests whose name doesn't match the pattern. + * The pattern is a Kotlin regular expression. + * + * --gtest_repeat=COUNT + * --ktest_repeat=COUNT - Run the tests repeatedly. + * Use a negative count to repeat forever. + * + * --ktest_logger=GTEST|TEAMCITY|SIMPLE|SILENT - Use the specified output format. The default one is GTEST. + * + * --ktest_no_exit_code - Don't return a non-zero exit code if there are failing tests. + */ + + private fun String.substringEscaped(range: IntRange) = + this.substring(range).let { if (it.isNotEmpty()) Regex.escape(it) else "" } + + private fun String.toGTestPatterns() = splitToSequence(':').map { pattern -> + val result = StringBuilder() + var prevIndex = 0 + pattern.forEachIndexed { index, c -> + if (c == '*' || c == '?') { + result.append(pattern.substringEscaped(prevIndex until index)) + prevIndex = index + 1 + result.append(if (c == '*') ".*" else ".") + } + } + result.append(pattern.substringEscaped(prevIndex until pattern.length)) + return@map result.toString().toRegex() + }.toList() + + private fun setGTestFilterFromArg(filter: String) { + if (filter.isEmpty()) { + throw IllegalArgumentException("Empty filter") + } + val filters = filter.split('-') + if (filters.size > 2) { + throw IllegalArgumentException("Wrong pattern syntax: $filter.") + } + + val positivePatterns = filters[0].toGTestPatterns() + val negativePatterns = filters.getOrNull(1)?.toGTestPatterns() ?: emptyList() + + this.filters.add { testCase -> + positivePatterns.any { testCase.prettyName.matches(it) } && + negativePatterns.none { testCase.prettyName.matches(it) } + } + } + + private fun setRegexFilterFromArg(filter: String, positive: Boolean = true) { + if (filter.isEmpty()) { + throw IllegalArgumentException("Empty filter") + } + val pattern = filter.toRegex() + filters.add { testCase -> + testCase.prettyName.matches(pattern) == positive + } + } + + private fun setGradleFilterFromArg(filter: String, positive: Boolean = true) { + if (filter.isEmpty()) { + throw IllegalArgumentException("Empty filter") + } + + val patterns = filter.split(',').map { pattern -> + pattern.split('*').joinToString(separator = ".*") { Regex.escape(it) }.toRegex() + } + + fun TestCase.matches(pattern: Regex) = + prettyName.matches(pattern) || suite.name.matches(pattern) + + if (positive) { + filters.add { testCase -> + patterns.any { testCase.matches(it) } + } + } else { + filters.add { testCase -> + patterns.none { testCase.matches(it) } + } + } + } + + private fun setLoggerFromArg(logger: String) { + when (logger.toUpperCase()) { + "GTEST" -> this.logger = GTestLogger() + "TEAMCITY" -> this.logger = TeamCityLogger() + "SIMPLE" -> this.logger = SimpleTestLogger() + "SILENT" -> this.logger = SilentTestLogger() + else -> throw IllegalArgumentException("Unknown logger type. Available types: GTEST, TEAMCITY, SIMPLE") + } + } + + private val help: String + get() = """ + |Available options: + |--gtest_list_tests + |--ktest_list_tests - Show all available tests. + | + |--gtest_filter=POSTIVE_PATTERNS[-NEGATIVE_PATTERNS] + |--ktest_filter=POSTIVE_PATTERNS[-NEGATIVE_PATTERNS] - Run only the tests whose name matches one of the + | positive patterns but none of the negative patterns. + | '?' matches any single character; '*' matches any + | substring; ':' separates two patterns. + | + |--ktest_regex_filter=PATTERN - Run only the tests whose name matches the pattern. + | The pattern is a Kotlin regular expression. + | + |--ktest_negative_regex_filter=PATTERN - Run only the tests whose name doesn't match the pattern. + | The pattern is a Kotlin regular expression. + | + |--ktest_gradle_filter=PATTERNS - Run only the tests which matches the at least one of the patterns. + | '*' matches any number of characters, ',' separates patterns. + | A test matches a pattern if: + | - its name matches the pattern or + | - its class name matches the pattern. + | + |--ktest_negative_gradle_filter=PATTERNS - Don't run tests if they match at least one of the patterns. + | The pattern is the same as for the ktest_gradle_filter option. + | + |--gtest_repeat=COUNT + |--ktest_repeat=COUNT - Run the tests repeatedly. + | Use a negative count to repeat forever. + | + |--ktest_logger=GTEST|TEAMCITY|SIMPLE|SILENT - Use the specified output format. The default one is GTEST. + | + |--ktest_no_exit_code - Don't return a non-zero exit code if there are failing tests. + """.trimMargin() + + private inline fun sendToListeners(event: TestListener.() -> Unit) { + logger.event() + listeners.forEach(event) + } + + private fun TestSuite.run() { + doBeforeClass() + testCases.values.forEach { testCase -> + if (testCase.ignored) { + sendToListeners { ignore(testCase) } + } else { + val startTime = getTimeMillis() + try { + sendToListeners { start(testCase) } + testCase.run() + sendToListeners { pass(testCase, getTimeMillis() - startTime) } + } catch (e: Throwable) { + sendToListeners { fail(testCase, e, getTimeMillis() - startTime) } + if (useExitCode) { + exitCode = 1 + } + } + } + } + doAfterClass() + } + + private fun runIteration(iteration: Int) { + val suitesFiltered = filterSuites() + sendToListeners { startIteration(this@TestRunner, iteration, suitesFiltered) } + val iterationTime = measureTimeMillis { + suitesFiltered.forEach { + if (it.ignored) { + sendToListeners { ignoreSuite(it) } + } else { + sendToListeners { startSuite(it) } + val time = measureTimeMillis { it.run() } + sendToListeners { finishSuite(it, time) } + } + } + } + sendToListeners { finishIteration(this@TestRunner, iteration, iterationTime) } + } + + fun run(): Int { + if (!runTests) + return 0 + sendToListeners { startTesting(this@TestRunner) } + val totalTime = measureTimeMillis { + var i = 1 + while (i <= iterations || iterations < 0) { + runIteration(i) + i++ + } + } + sendToListeners { finishTesting(this@TestRunner, totalTime) } + return exitCode + } +} diff --git a/kotlin-native/runtime/src/main/kotlin/kotlin/native/internal/test/TestStatistics.kt b/kotlin-native/runtime/src/main/kotlin/kotlin/native/internal/test/TestStatistics.kt new file mode 100644 index 00000000000..c4aad26afe3 --- /dev/null +++ b/kotlin-native/runtime/src/main/kotlin/kotlin/native/internal/test/TestStatistics.kt @@ -0,0 +1,69 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +package kotlin.native.internal.test + +internal interface TestStatistics { + val total: Int + val passed: Int + val failed: Int + val ignored: Int + + val totalSuites: Int + + val failedTests: Collection + val hasFailedTests: Boolean +} + +internal class MutableTestStatistics: TestStatistics { + + override var total: Int = 0; private set + override var passed: Int = 0; private set + override var ignored: Int = 0; private set + + override var totalSuites: Int = 0; private set + + override val failed: Int + get() = _failedTests.size + + override val hasFailedTests: Boolean + get() = _failedTests.isNotEmpty() + + private val _failedTests = mutableListOf() + override val failedTests: Collection + get() = _failedTests + + fun registerSuite(count: Int = 1) { + require(count >= 0) + totalSuites += count + } + + fun registerPass(count: Int = 1) { + require(count >= 0) + total += count + passed += count + } + + fun registerFail(testCases: Collection) { + total += testCases.size + _failedTests.addAll(testCases) + } + + fun registerFail(testCase: TestCase) = registerFail(listOf(testCase)) + + fun registerIgnore(count: Int = 1) { + require(count >= 0) + total += count + ignored += count + } + + fun reset() { + total = 0 + passed = 0 + ignored = 0 + totalSuites = 0 + _failedTests.clear() + } +} diff --git a/kotlin-native/runtime/src/main/kotlin/kotlin/native/internal/test/TestSuite.kt b/kotlin-native/runtime/src/main/kotlin/kotlin/native/internal/test/TestSuite.kt new file mode 100644 index 00000000000..5a9fe5dfc85 --- /dev/null +++ b/kotlin-native/runtime/src/main/kotlin/kotlin/native/internal/test/TestSuite.kt @@ -0,0 +1,167 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +package kotlin.native.internal.test + +import kotlin.IllegalArgumentException +import kotlin.system.getTimeMillis +import kotlin.system.measureTimeMillis + +public interface TestCase { + val name: String + val ignored: Boolean + val suite: TestSuite + + fun run() +} + +internal val TestCase.prettyName get() = "${suite.name}.$name" + +public interface TestSuite { + val name: String + val ignored: Boolean + val testCases: Map + val size : Int + + fun doBeforeClass() + fun doAfterClass() +} + +public enum class TestFunctionKind { + BEFORE_TEST, + AFTER_TEST, + BEFORE_CLASS, + AFTER_CLASS +} + +public abstract class AbstractTestSuite>(override val name: String, override val ignored: Boolean) + : TestSuite { + override fun toString(): String = name + + // TODO: Make inner and remove the type param when the bug is fixed. + abstract class BasicTestCase>( + override val name: String, + override val suite: AbstractTestSuite, + val testFunction: F, + override val ignored: Boolean + ) : TestCase { + override fun toString(): String = "$name ($suite)" + } + + private val _testCases = mutableMapOf>() + override val testCases: Map> + get() = _testCases + + private fun registerTestCase(testCase: BasicTestCase) = _testCases.put(testCase.name, testCase) + + fun registerTestCase(name: String, testFunction: F, ignored: Boolean) = + registerTestCase(createTestCase(name, testFunction, ignored)) + + abstract fun createTestCase(name: String, testFunction: F, ignored: Boolean): BasicTestCase + + init { + registerSuite(this) + } + + override val size: Int + get() = testCases.size +} + +public abstract class BaseClassSuite(name: String, ignored: Boolean) + : AbstractTestSuite Unit>(name, ignored) { + + class TestCase(name: String, + override val suite: BaseClassSuite, + testFunction: INSTANCE.() -> Unit, + ignored: Boolean) + : BasicTestCase Unit>(name, suite, testFunction, ignored) { + + override fun run() { + val instance = suite.createInstance() + try { + suite.before.forEach { instance.it() } + instance.testFunction() + } finally { + suite.after.forEach { instance.it() } + } + } + } + + // These two methods are overridden in test suite classes generated by the compiler. + abstract fun createInstance(): INSTANCE + open fun getCompanion(): COMPANION = throw NotImplementedError("Test class has no companion object") + + companion object { + val INSTANCE_KINDS = listOf(TestFunctionKind.BEFORE_TEST, TestFunctionKind.AFTER_TEST) + val COMPANION_KINDS = listOf(TestFunctionKind.BEFORE_CLASS, TestFunctionKind.AFTER_CLASS) + } + + private val instanceFunctions = mutableMapOf Unit>>() + private fun getInstanceFunctions(kind: TestFunctionKind): MutableCollection Unit> { + check(kind in INSTANCE_KINDS) + return instanceFunctions.getOrPut(kind) { mutableSetOf() } + } + + private val companionFunction = mutableMapOf Unit>>() + private fun getCompanionFunctions(kind: TestFunctionKind): MutableCollection Unit> { + check(kind in COMPANION_KINDS) + return companionFunction.getOrPut(kind) { mutableSetOf() } + } + + val before: Collection Unit> get() = getInstanceFunctions(TestFunctionKind.BEFORE_TEST) + val after: Collection Unit> get() = getInstanceFunctions(TestFunctionKind.AFTER_TEST) + + val beforeClass: Collection Unit> get() = getCompanionFunctions(TestFunctionKind.BEFORE_CLASS) + val afterClass: Collection Unit> get() = getCompanionFunctions(TestFunctionKind.AFTER_CLASS) + + @Suppress("UNCHECKED_CAST") + fun registerFunction(kind: TestFunctionKind, function: Function1<*, Unit>) = + when (kind) { + in INSTANCE_KINDS -> getInstanceFunctions(kind).add(function as INSTANCE.() -> Unit) + in COMPANION_KINDS -> getCompanionFunctions(kind).add(function as COMPANION.() -> Unit) + else -> throw IllegalArgumentException("Unknown function kind: $kind") + } + + override fun doBeforeClass() = beforeClass.forEach { getCompanion().it() } + override fun doAfterClass() = afterClass.forEach { getCompanion().it() } + + override fun createTestCase(name: String, testFunction: INSTANCE.() -> Unit, ignored: Boolean) + : BasicTestCase Unit> = + TestCase(name, this, testFunction, ignored) +} + +private typealias TopLevelFun = () -> Unit + +public class TopLevelSuite(name: String): AbstractTestSuite(name, false) { + + class TestCase(name: String, override val suite: TopLevelSuite, testFunction: TopLevelFun, ignored: Boolean) + : BasicTestCase(name, suite, testFunction, ignored) { + + override fun run() { + try { + suite.before.forEach { it() } + testFunction() + } finally { + suite.after.forEach { it() } + } + } + } + + private val specialFunctions = mutableMapOf>() + private fun getFunctions(type: TestFunctionKind) = specialFunctions.getOrPut(type) { mutableSetOf() } + + val before: Collection get() = getFunctions(TestFunctionKind.BEFORE_TEST) + val after: Collection get() = getFunctions(TestFunctionKind.AFTER_TEST) + val beforeClass: Collection get() = getFunctions(TestFunctionKind.BEFORE_CLASS) + val afterClass: Collection get() = getFunctions(TestFunctionKind.AFTER_CLASS) + + fun registerFunction(kind: TestFunctionKind, function: TopLevelFun) = getFunctions(kind).add(function) + + override fun doBeforeClass() = beforeClass.forEach { it() } + override fun doAfterClass() = afterClass.forEach { it() } + + override fun createTestCase(name: String, testFunction: TopLevelFun, ignored: Boolean) + : BasicTestCase = TestCase(name, this, testFunction, ignored) +} \ No newline at end of file diff --git a/kotlin-native/runtime/src/main/kotlin/kotlin/native/ref/Weak.kt b/kotlin-native/runtime/src/main/kotlin/kotlin/native/ref/Weak.kt new file mode 100644 index 00000000000..3192c5022d4 --- /dev/null +++ b/kotlin-native/runtime/src/main/kotlin/kotlin/native/ref/Weak.kt @@ -0,0 +1,47 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +package kotlin.native.ref + +/** + * Class WeakReference encapsulates weak reference to an object, which could be used to either + * retrieve a strong reference to an object, or return null, if object was already destroyed by + * the memory manager. + */ +public class WeakReference { + /** + * Creates a weak reference object pointing to an object. Weak reference doesn't prevent + * removing object, and is nullified once object is collected. + */ + constructor(referred: T) { + pointer = getWeakReferenceImpl(referred) + } + + /** + * Backing store for the object pointer, inaccessible directly. + */ + @PublishedApi + internal var pointer: WeakReferenceImpl? + + /** + * Clears reference to an object. + */ + public fun clear() { + pointer = null + } + + /** + * Returns either reference to an object or null, if it was collected. + */ + @Suppress("UNCHECKED_CAST") + public fun get(): T? = pointer?.get() as T? + + /** + * Returns either reference to an object or null, if it was collected. + */ + public val value: T? + get() = this.get() +} + diff --git a/kotlin-native/runtime/src/main/kotlin/kotlin/native/ref/WeakPrivate.kt b/kotlin-native/runtime/src/main/kotlin/kotlin/native/ref/WeakPrivate.kt new file mode 100644 index 00000000000..b5c3fb32319 --- /dev/null +++ b/kotlin-native/runtime/src/main/kotlin/kotlin/native/ref/WeakPrivate.kt @@ -0,0 +1,70 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +package kotlin.native.ref + +import kotlinx.cinterop.COpaquePointer +import kotlin.native.internal.ExportForCppRuntime +import kotlin.native.internal.Frozen +import kotlin.native.internal.NoReorderFields +import kotlin.native.internal.Escapes + +/** + * Theory of operations: + * + * Weak references in Kotlin/Native are implemented in the following way. Whenever weak reference to an + * object is created, we atomically modify type info pointer in the object to point into a metaobject. + * This metaobject contains a strong reference to the counter object (instance of WeakReferenceCounter class). + * Every other weak reference contains a strong reference to the counter object. + * + * [weak1] [weak2] + * \ / + * V V + * .......[Counter] <---- + * . | + * . | + * ->[Object] -> [Meta]- + * + * References from weak reference objects to the counter and from the metaobject to the counter are strong, + * and from the counter to the object is nullably weak. So whenever an object dies, if it has a metaobject, + * it is traversed to find a counter object, and atomically nullify reference to the object. Afterward, all attempts + * to get the object would yield null. + */ + +// Clear holding the counter object, which refers to the actual object. +@NoReorderFields +@Frozen +internal class WeakReferenceCounter(var referred: COpaquePointer?) : WeakReferenceImpl() { + // Spinlock, potentially taken when materializing or removing 'referred' object. + var lock: Int = 0 + + // Optimization for concurrent access. + var cookie: Int = 0 + + @SymbolName("Konan_WeakReferenceCounter_get") + external override fun get(): Any? +} + +@PublishedApi +internal abstract class WeakReferenceImpl { + abstract fun get(): Any? +} + +// Get a counter from non-null object. +@SymbolName("Konan_getWeakReferenceImpl") +@Escapes(0b01) // referent escapes. +external internal fun getWeakReferenceImpl(referent: Any): WeakReferenceImpl + +// Create a counter object. +@ExportForCppRuntime +internal fun makeWeakReferenceCounter(referred: COpaquePointer) = WeakReferenceCounter(referred) + +internal class PermanentWeakReferenceImpl(val referred: Any): kotlin.native.ref.WeakReferenceImpl() { + override fun get(): Any? = referred +} + +// Create a reference to the permanent object. +@ExportForCppRuntime +internal fun makePermanentWeakReferenceImpl(referred: Any) = PermanentWeakReferenceImpl(referred) diff --git a/kotlin-native/runtime/src/main/kotlin/kotlin/native/simd.kt b/kotlin-native/runtime/src/main/kotlin/kotlin/native/simd.kt new file mode 100644 index 00000000000..85d4e9de5ec --- /dev/null +++ b/kotlin-native/runtime/src/main/kotlin/kotlin/native/simd.kt @@ -0,0 +1,57 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ +package kotlin.native + +import kotlin.native.internal.TypedIntrinsic +import kotlin.native.internal.IntrinsicType + + +public final class Vector128 private constructor() { + @TypedIntrinsic(IntrinsicType.EXTRACT_ELEMENT) + external fun getByteAt(index: Int): Byte + + @TypedIntrinsic(IntrinsicType.EXTRACT_ELEMENT) + external fun getIntAt(index: Int): Int + + @TypedIntrinsic(IntrinsicType.EXTRACT_ELEMENT) + external fun getLongAt(index: Int): Long + + @TypedIntrinsic(IntrinsicType.EXTRACT_ELEMENT) + external fun getFloatAt(index: Int): Float + + @TypedIntrinsic(IntrinsicType.EXTRACT_ELEMENT) + external fun getDoubleAt(index: Int): Double + + @TypedIntrinsic(IntrinsicType.EXTRACT_ELEMENT) + external fun getUByteAt(index: Int): UByte + + @TypedIntrinsic(IntrinsicType.EXTRACT_ELEMENT) + external fun getUIntAt(index: Int): UInt + + @TypedIntrinsic(IntrinsicType.EXTRACT_ELEMENT) + external fun getULongAt(index: Int): ULong + + public override fun toString() = + "(0x${getUIntAt(0).toString(16)}, 0x${getUIntAt(1).toString(16)}, 0x${getUIntAt(2).toString(16)}, 0x${getUIntAt(3).toString(16)})" + + // Not as good for floating types + public fun equals(other: Vector128): Boolean = + getLongAt(0) == other.getLongAt(0) && getLongAt(1) == other.getLongAt(1) + + public override fun equals(other: Any?): Boolean = + other is Vector128 && this.equals(other) + + override fun hashCode(): Int { + val x0 = getLongAt(0) + val x1 = getLongAt(1) + return 31 * (x0 xor (x0 shr 32)).toInt() + (x1 xor (x1 shr 32)).toInt() + } +} + +@SymbolName("Kotlin_Vector4f_of") +external fun vectorOf(f0: Float, f1: Float, f2: Float, f3: Float): Vector128 + +@SymbolName("Kotlin_Vector4i32_of") +external fun vectorOf(f0: Int, f1: Int, f2: Int, f3: Int): Vector128 diff --git a/kotlin-native/runtime/src/main/kotlin/kotlin/random/Random.kt b/kotlin-native/runtime/src/main/kotlin/kotlin/random/Random.kt new file mode 100644 index 00000000000..9d1942152f1 --- /dev/null +++ b/kotlin-native/runtime/src/main/kotlin/kotlin/random/Random.kt @@ -0,0 +1,40 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ +package kotlin.random + +import kotlin.native.concurrent.AtomicLong +import kotlin.system.getTimeNanos + +/** + * The default implementation of pseudo-random generator using the linear congruential generator. + */ +internal object NativeRandom : Random() { + private const val MULTIPLIER = 0x5deece66dL + private val _seed = AtomicLong(mult(getTimeNanos())) + + /** + * Random generator seed value. + */ + private val seed: Long + get() = _seed.value + + private fun mult(value: Long) = (value xor MULTIPLIER) and ((1L shl 48) - 1) + + private fun update(seed: Long): Unit { + _seed.value = seed + } + + override fun nextBits(bitCount: Int): Int { + update((seed * MULTIPLIER + 0xbL) and ((1L shl 48) - 1)) + return (seed ushr (48 - bitCount)).toInt() + } + + override fun nextInt(): Int = nextBits(32) +} + +internal actual fun defaultPlatformRandom(): Random = NativeRandom + +internal actual fun doubleFromParts(hi26: Int, low27: Int): Double = + (hi26.toLong().shl(27) + low27) / (1L shl 53).toDouble() diff --git a/kotlin-native/runtime/src/main/kotlin/kotlin/ranges/ProgressionIterators.kt b/kotlin-native/runtime/src/main/kotlin/kotlin/ranges/ProgressionIterators.kt new file mode 100644 index 00000000000..8c8441a6800 --- /dev/null +++ b/kotlin-native/runtime/src/main/kotlin/kotlin/ranges/ProgressionIterators.kt @@ -0,0 +1,78 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +package kotlin.ranges + +/** + * An iterator over a progression of values of type `Char`. + * @property step the number by which the value is incremented on each step. + */ +internal class CharProgressionIterator(first: Char, last: Char, val step: Int) : CharIterator() { + private val finalElement = last.toInt() + private var hasNext: Boolean = if (step > 0) first <= last else first >= last + private var next = if (hasNext) first.toInt() else finalElement + + override fun hasNext(): Boolean = hasNext + + override fun nextChar(): Char { + val value = next + if (value == finalElement) { + if (!hasNext) throw kotlin.NoSuchElementException() + hasNext = false + } + else { + next += step + } + return value.toChar() + } +} + +/** + * An iterator over a progression of values of type `Int`. + * @property step the number by which the value is incremented on each step. + */ +internal class IntProgressionIterator(first: Int, last: Int, val step: Int) : IntIterator() { + private val finalElement = last + private var hasNext: Boolean = if (step > 0) first <= last else first >= last + private var next = if (hasNext) first else finalElement + + override fun hasNext(): Boolean = hasNext + + override fun nextInt(): Int { + val value = next + if (value == finalElement) { + if (!hasNext) throw kotlin.NoSuchElementException() + hasNext = false + } + else { + next += step + } + return value + } +} + +/** + * An iterator over a progression of values of type `Long`. + * @property step the number by which the value is incremented on each step. + */ +internal class LongProgressionIterator(first: Long, last: Long, val step: Long) : LongIterator() { + private val finalElement = last + private var hasNext: Boolean = if (step > 0) first <= last else first >= last + private var next = if (hasNext) first else finalElement + + override fun hasNext(): Boolean = hasNext + + override fun nextLong(): Long { + val value = next + if (value == finalElement) { + if (!hasNext) throw kotlin.NoSuchElementException() + hasNext = false + } + else { + next += step + } + return value + } +} \ No newline at end of file diff --git a/kotlin-native/runtime/src/main/kotlin/kotlin/ranges/Progressions.kt b/kotlin-native/runtime/src/main/kotlin/kotlin/ranges/Progressions.kt new file mode 100644 index 00000000000..ff97fc4d1e4 --- /dev/null +++ b/kotlin-native/runtime/src/main/kotlin/kotlin/ranges/Progressions.kt @@ -0,0 +1,181 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +// A copy-paste from kotlin/core/builtins/src/kotlin/Progressions.kt + +package kotlin.ranges + +import kotlin.internal.getProgressionLastElement + +/** + * A progression of values of type `Char`. + */ +public open class CharProgression +internal constructor +( + start: Char, + endInclusive: Char, + step: Int +) : Iterable { + init { + if (step == 0) throw kotlin.IllegalArgumentException("Step must be non-zero.") + if (step == Int.MIN_VALUE) throw kotlin.IllegalArgumentException("Step must be greater than Int.MIN_VALUE to avoid overflow on negation.") + } + + /** + * The first element in the progression. + */ + public val first: Char = start + + /** + * The last element in the progression. + */ + public val last: Char = getProgressionLastElement(start.toInt(), endInclusive.toInt(), step).toChar() + + /** + * The step of the progression. + */ + public val step: Int = step + + override fun iterator(): CharIterator = CharProgressionIterator(first, last, step) + + /** Checks if the progression is empty. */ + public open fun isEmpty(): Boolean = if (step > 0) first > last else first < last + + override fun equals(other: Any?): Boolean = + other is CharProgression && (isEmpty() && other.isEmpty() || + first == other.first && last == other.last && step == other.step) + + override fun hashCode(): Int = + if (isEmpty()) -1 else (31 * (31 * first.toInt() + last.toInt()) + step) + + override fun toString(): String = if (step > 0) "$first..$last step $step" else "$first downTo $last step ${-step}" + + companion object { + /** + * Creates CharProgression within the specified bounds of a closed range. + + * The progression starts with the [rangeStart] value and goes toward the [rangeEnd] value not excluding it, with the specified [step]. + * In order to go backwards the [step] must be negative. + * + * [step] must be greater than `Int.MIN_VALUE` and not equal to zero. + */ + public fun fromClosedRange(rangeStart: Char, rangeEnd: Char, step: Int): CharProgression = CharProgression(rangeStart, rangeEnd, step) + } +} + +/** + * A progression of values of type `Int`. + */ +public open class IntProgression +internal constructor +( + start: Int, + endInclusive: Int, + step: Int +) : Iterable { + init { + if (step == 0) throw kotlin.IllegalArgumentException("Step must be non-zero.") + if (step == Int.MIN_VALUE) throw kotlin.IllegalArgumentException("Step must be greater than Int.MIN_VALUE to avoid overflow on negation.") + } + + /** + * The first element in the progression. + */ + public val first: Int = start + + /** + * The last element in the progression. + */ + public val last: Int = getProgressionLastElement(start.toInt(), endInclusive.toInt(), step).toInt() + + /** + * The step of the progression. + */ + public val step: Int = step + + override fun iterator(): IntIterator = IntProgressionIterator(first, last, step) + + /** Checks if the progression is empty. */ + public open fun isEmpty(): Boolean = if (step > 0) first > last else first < last + + override fun equals(other: Any?): Boolean = + other is IntProgression && (isEmpty() && other.isEmpty() || + first == other.first && last == other.last && step == other.step) + + override fun hashCode(): Int = + if (isEmpty()) -1 else (31 * (31 * first + last) + step) + + override fun toString(): String = if (step > 0) "$first..$last step $step" else "$first downTo $last step ${-step}" + + companion object { + /** + * Creates IntProgression within the specified bounds of a closed range. + + * The progression starts with the [rangeStart] value and goes toward the [rangeEnd] value not excluding it, with the specified [step]. + * In order to go backwards the [step] must be negative. + * + * [step] must be greater than `Int.MIN_VALUE` and not equal to zero. + */ + public fun fromClosedRange(rangeStart: Int, rangeEnd: Int, step: Int): IntProgression = IntProgression(rangeStart, rangeEnd, step) + } +} + +/** + * A progression of values of type `Long`. + */ +public open class LongProgression +internal constructor +( + start: Long, + endInclusive: Long, + step: Long +) : Iterable { + init { + if (step == 0L) throw kotlin.IllegalArgumentException("Step must be non-zero.") + if (step == Long.MIN_VALUE) throw kotlin.IllegalArgumentException("Step must be greater than Long.MIN_VALUE to avoid overflow on negation.") + } + + /** + * The first element in the progression. + */ + public val first: Long = start + + /** + * The last element in the progression. + */ + public val last: Long = getProgressionLastElement(start.toLong(), endInclusive.toLong(), step).toLong() + + /** + * The step of the progression. + */ + public val step: Long = step + + override fun iterator(): LongIterator = LongProgressionIterator(first, last, step) + + /** Checks if the progression is empty. */ + public open fun isEmpty(): Boolean = if (step > 0) first > last else first < last + + override fun equals(other: Any?): Boolean = + other is LongProgression && (isEmpty() && other.isEmpty() || + first == other.first && last == other.last && step == other.step) + + override fun hashCode(): Int = + if (isEmpty()) -1 else (31 * (31 * (first xor (first ushr 32)) + (last xor (last ushr 32))) + (step xor (step ushr 32))).toInt() + + override fun toString(): String = if (step > 0) "$first..$last step $step" else "$first downTo $last step ${-step}" + + companion object { + /** + * Creates LongProgression within the specified bounds of a closed range. + + * The progression starts with the [rangeStart] value and goes toward the [rangeEnd] value not excluding it, with the specified [step]. + * In order to go backwards the [step] must be negative. + * + * [step] must be greater than `Long.MIN_VALUE` and not equal to zero. + */ + public fun fromClosedRange(rangeStart: Long, rangeEnd: Long, step: Long): LongProgression = LongProgression(rangeStart, rangeEnd, step) + } +} \ No newline at end of file diff --git a/kotlin-native/runtime/src/main/kotlin/kotlin/ranges/Range.kt b/kotlin-native/runtime/src/main/kotlin/kotlin/ranges/Range.kt new file mode 100644 index 00000000000..3003d0f1176 --- /dev/null +++ b/kotlin-native/runtime/src/main/kotlin/kotlin/ranges/Range.kt @@ -0,0 +1,32 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +package kotlin.ranges + +/** + * Represents a range of values (for example, numbers or characters). + * See the [Kotlin language documentation](https://kotlinlang.org/docs/reference/ranges.html) for more information. + */ +public interface ClosedRange> { + /** + * The minimum value in the range. + */ + public val start: T + + /** + * The maximum value in the range (inclusive). + */ + public val endInclusive: T + + /** + * Checks whether the specified [value] belongs to the range. + */ + public operator fun contains(value: T): Boolean = value >= start && value <= endInclusive + + /** + * Checks whether the range is empty. + */ + public fun isEmpty(): Boolean = start > endInclusive +} diff --git a/kotlin-native/runtime/src/main/kotlin/kotlin/ranges/Ranges.kt b/kotlin-native/runtime/src/main/kotlin/kotlin/ranges/Ranges.kt new file mode 100644 index 00000000000..0243ad46b94 --- /dev/null +++ b/kotlin-native/runtime/src/main/kotlin/kotlin/ranges/Ranges.kt @@ -0,0 +1,84 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +package kotlin.ranges + +/** + * A range of values of type `Char`. + */ +public class CharRange(start: Char, endInclusive: Char) : CharProgression(start, endInclusive, 1), ClosedRange { + override val start: Char get() = first + override val endInclusive: Char get() = last + + override fun contains(value: Char): Boolean = first <= value && value <= last + + override fun isEmpty(): Boolean = first > last + + override fun equals(other: Any?): Boolean = + other is CharRange && (isEmpty() && other.isEmpty() || + first == other.first && last == other.last) + + override fun hashCode(): Int = + if (isEmpty()) -1 else (31 * first.toInt() + last.toInt()) + + override fun toString(): String = "$first..$last" + + companion object { + /** An empty range of values of type Char. */ + public val EMPTY: CharRange = CharRange(1.toChar(), 0.toChar()) + } +} + +/** + * A range of values of type `Int`. + */ +public class IntRange(start: Int, endInclusive: Int) : IntProgression(start, endInclusive, 1), ClosedRange { + override val start: Int get() = first + override val endInclusive: Int get() = last + + override fun contains(value: Int): Boolean = first <= value && value <= last + + override fun isEmpty(): Boolean = first > last + + override fun equals(other: Any?): Boolean = + other is IntRange && (isEmpty() && other.isEmpty() || + first == other.first && last == other.last) + + override fun hashCode(): Int = + if (isEmpty()) -1 else (31 * first + last) + + override fun toString(): String = "$first..$last" + + companion object { + /** An empty range of values of type Int. */ + public val EMPTY: IntRange = IntRange(1, 0) + } +} + +/** + * A range of values of type `Long`. + */ +public class LongRange(start: Long, endInclusive: Long) : LongProgression(start, endInclusive, 1), ClosedRange { + override val start: Long get() = first + override val endInclusive: Long get() = last + + override fun contains(value: Long): Boolean = first <= value && value <= last + + override fun isEmpty(): Boolean = first > last + + override fun equals(other: Any?): Boolean = + other is LongRange && (isEmpty() && other.isEmpty() || + first == other.first && last == other.last) + + override fun hashCode(): Int = + if (isEmpty()) -1 else (31 * (first xor (first ushr 32)) + (last xor (last ushr 32))).toInt() + + override fun toString(): String = "$first..$last" + + companion object { + /** An empty range of values of type Long. */ + public val EMPTY: LongRange = LongRange(1, 0) + } +} diff --git a/kotlin-native/runtime/src/main/kotlin/kotlin/reflect/AssociatedObjects.kt b/kotlin-native/runtime/src/main/kotlin/kotlin/reflect/AssociatedObjects.kt new file mode 100644 index 00000000000..7a2af7efd65 --- /dev/null +++ b/kotlin-native/runtime/src/main/kotlin/kotlin/reflect/AssociatedObjects.kt @@ -0,0 +1,41 @@ +/* + * Copyright 2010-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +package kotlin.reflect + +import kotlin.native.internal.* + +/** + * The experimental marker for associated objects API. + * + * Any usage of a declaration annotated with `@ExperimentalAssociatedObjects` must be accepted either by + * annotating that usage with the [OptIn] annotation, e.g. `@OptIn(ExperimentalAssociatedObjects::class)`, + * or by using the compiler argument `-Xopt-in=kotlin.reflect.ExperimentalAssociatedObjects`. + */ +@RequiresOptIn(level = RequiresOptIn.Level.ERROR) +@Retention(value = AnnotationRetention.BINARY) +public annotation class ExperimentalAssociatedObjects + +/** + * Makes the annotated annotation class an associated object key. + * + * An associated object key annotation should have single [KClass] parameter. + * When applied to a class with reference to an object declaration as an argument, it binds + * the object to the class, making this binding discoverable at runtime using [findAssociatedObject]. + */ +@ExperimentalAssociatedObjects +@Retention(AnnotationRetention.BINARY) +@Target(AnnotationTarget.ANNOTATION_CLASS) +public annotation class AssociatedObjectKey + +/** + * If [T] is an @[AssociatedObjectKey]-annotated annotation class and [this] class is annotated with @[T] (`S::class`), + * returns object `S`. + * + * Otherwise returns `null`. + */ +@ExperimentalAssociatedObjects +public inline fun KClass<*>.findAssociatedObject(): Any? = + this.findAssociatedObject(T::class) diff --git a/kotlin-native/runtime/src/main/kotlin/kotlin/reflect/KAnnotatedElement.kt b/kotlin-native/runtime/src/main/kotlin/kotlin/reflect/KAnnotatedElement.kt new file mode 100644 index 00000000000..fee9cd66ecf --- /dev/null +++ b/kotlin-native/runtime/src/main/kotlin/kotlin/reflect/KAnnotatedElement.kt @@ -0,0 +1,16 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +package kotlin.reflect + +import kotlin.native.internal.FixmeReflection + +/** + * Represents an annotated element and allows to obtain its annotations. + * See the [Kotlin language documentation](https://kotlinlang.org/docs/reference/annotations.html) + * for more information. + */ +@FixmeReflection +public interface KAnnotatedElement \ No newline at end of file diff --git a/kotlin-native/runtime/src/main/kotlin/kotlin/reflect/KCallable.kt b/kotlin-native/runtime/src/main/kotlin/kotlin/reflect/KCallable.kt new file mode 100644 index 00000000000..a3ca665e6d4 --- /dev/null +++ b/kotlin-native/runtime/src/main/kotlin/kotlin/reflect/KCallable.kt @@ -0,0 +1,30 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +package kotlin.reflect + +import kotlin.native.internal.FixmeReflection + +/** + * Represents a callable entity, such as a function or a property. + * + * @param R return type of the callable. + */ +public actual interface KCallable : KAnnotatedElement { + /** + * The name of this callable as it was declared in the source code. + * If the callable has no name, a special invented name is created. + * Nameless callables include: + * - constructors have the name "", + * - property accessors: the getter for a property named "foo" will have the name "", + * the setter, similarly, will have the name "". + */ + public actual val name: String + + /** + * The type of values returned by this callable. + */ + public val returnType: KType +} diff --git a/kotlin-native/runtime/src/main/kotlin/kotlin/reflect/KClass.kt b/kotlin-native/runtime/src/main/kotlin/kotlin/reflect/KClass.kt new file mode 100644 index 00000000000..d6906cc0903 --- /dev/null +++ b/kotlin-native/runtime/src/main/kotlin/kotlin/reflect/KClass.kt @@ -0,0 +1,49 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +package kotlin.reflect + +/** + * Represents a class and provides introspection capabilities. + * Instances of this class are obtainable by the `::class` syntax. + * See the [Kotlin language documentation](https://kotlinlang.org/docs/reference/reflection.html#class-references) + * for more information. + * + * @param T the type of the class. + */ +public actual interface KClass : KDeclarationContainer, KAnnotatedElement, KClassifier { + /** + * The simple name of the class as it was declared in the source code, + * or `null` if the class has no name (if, for example, it is a class of an anonymous object). + */ + public actual val simpleName: String? + + /** + * The fully qualified dot-separated name of the class, + * or `null` if the class is local or a class of an anonymous object. + */ + public actual val qualifiedName: String? + + /** + * Returns `true` if [value] is an instance of this class on a given platform. + */ + @SinceKotlin("1.1") + public actual fun isInstance(value: Any?): Boolean + + /** + * Returns `true` if this [KClass] instance represents the same Kotlin class as the class represented by [other]. + * On JVM this means that all of the following conditions are satisfied: + * + * 1. [other] has the same (fully qualified) Kotlin class name as this instance. + * 2. [other]'s backing [Class] object is loaded with the same class loader as the [Class] object of this instance. + * 3. If the classes represent [Array], then [Class] objects of their element types are equal. + * + * For example, on JVM, [KClass] instances for a primitive type (`int`) and the corresponding wrapper type (`java.lang.Integer`) + * are considered equal, because they have the same fully qualified name "kotlin.Int". + */ + override fun equals(other: Any?): Boolean + + override fun hashCode(): Int +} diff --git a/kotlin-native/runtime/src/main/kotlin/kotlin/reflect/KClassesImpl.kt b/kotlin-native/runtime/src/main/kotlin/kotlin/reflect/KClassesImpl.kt new file mode 100644 index 00000000000..17baee448c4 --- /dev/null +++ b/kotlin-native/runtime/src/main/kotlin/kotlin/reflect/KClassesImpl.kt @@ -0,0 +1,9 @@ +/* + * Copyright 2010-2019 JetBrains s.r.o. and Kotlin Programming Language contributors. + * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. + */ + +package kotlin.reflect + +internal actual inline val KClass<*>.qualifiedOrSimpleName: String? + get() = qualifiedName \ No newline at end of file diff --git a/kotlin-native/runtime/src/main/kotlin/kotlin/reflect/KDeclarationContainer.kt b/kotlin-native/runtime/src/main/kotlin/kotlin/reflect/KDeclarationContainer.kt new file mode 100644 index 00000000000..1289bb63887 --- /dev/null +++ b/kotlin-native/runtime/src/main/kotlin/kotlin/reflect/KDeclarationContainer.kt @@ -0,0 +1,12 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +package kotlin.reflect + +/** + * Represents an entity which may contain declarations of any other entities, + * such as a class or a package. + */ +public interface KDeclarationContainer \ No newline at end of file diff --git a/kotlin-native/runtime/src/main/kotlin/kotlin/reflect/KFunction.kt b/kotlin-native/runtime/src/main/kotlin/kotlin/reflect/KFunction.kt new file mode 100644 index 00000000000..3197c00cf7d --- /dev/null +++ b/kotlin-native/runtime/src/main/kotlin/kotlin/reflect/KFunction.kt @@ -0,0 +1,8 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +package kotlin.reflect + +public actual interface KFunction : KCallable, Function diff --git a/kotlin-native/runtime/src/main/kotlin/kotlin/reflect/KProperty.kt b/kotlin-native/runtime/src/main/kotlin/kotlin/reflect/KProperty.kt new file mode 100644 index 00000000000..021f454a6db --- /dev/null +++ b/kotlin-native/runtime/src/main/kotlin/kotlin/reflect/KProperty.kt @@ -0,0 +1,55 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +package kotlin.reflect + +import kotlin.native.internal.FixmeReflection + +/** + * Represents a property, such as a named `val` or `var` declaration. + * Instances of this class are obtainable by the `::` operator. + * + * See the [Kotlin language documentation](https://kotlinlang.org/docs/reference/reflection.html) + * for more information. + * + * @param V the type of the property value. + */ +public actual interface KProperty : KCallable + +public actual interface KProperty0 : kotlin.reflect.KProperty, () -> V { + + public actual fun get(): V + + public override abstract operator fun invoke(): V +} + +public actual interface KProperty1 : kotlin.reflect.KProperty, (T) -> V { + public actual fun get(receiver: T): V + + public override operator fun invoke(p1: T): V +} + +public actual interface KProperty2 : kotlin.reflect.KProperty, (D, E) -> V { + public actual fun get(receiver1: D, receiver2: E): V + + public override operator fun invoke(p1: D, p2: E): V +} + +/** + * Represents a property declared as a `var`. + */ +public actual interface KMutableProperty : KProperty + +public actual interface KMutableProperty0 : KProperty0, KMutableProperty { + public actual fun set(value: V) +} + +public actual interface KMutableProperty1 : KProperty1, KMutableProperty { + public actual fun set(receiver: T, value: V) +} + +public actual interface KMutableProperty2 : KProperty2, KMutableProperty { + public actual fun set(receiver1: D, receiver2: E, value: V) +} \ No newline at end of file diff --git a/kotlin-native/runtime/src/main/kotlin/kotlin/reflect/KType.kt b/kotlin-native/runtime/src/main/kotlin/kotlin/reflect/KType.kt new file mode 100644 index 00000000000..8bdc56c3288 --- /dev/null +++ b/kotlin-native/runtime/src/main/kotlin/kotlin/reflect/KType.kt @@ -0,0 +1,51 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +package kotlin.reflect + +/** + * Represents a type. Type is usually either a class with optional type arguments, + * or a type parameter of some declaration, plus nullability. + */ +public actual interface KType { + /** + * The declaration of the classifier used in this type. + * For example, in the type `List` the classifier would be the [KClass] instance for [List]. + * + * Returns `null` if this type is not denotable in Kotlin, for example if it is an intersection type. + */ + @SinceKotlin("1.1") + public actual val classifier: KClassifier? + + /** + * Type arguments passed for the parameters of the classifier in this type. + * For example, in the type `Array` the only type argument is `out Number`. + * + * In case this type is based on an inner class, the returned list contains the type arguments provided for the innermost class first, + * then its outer class, and so on. + * For example, in the type `Outer.Inner` the returned list is `[C, D, A, B]`. + */ + @SinceKotlin("1.1") + public actual val arguments: List + + /** + * `true` if this type was marked nullable in the source code. + * + * For Kotlin types, it means that `null` value is allowed to be represented by this type. + * In practice it means that the type was declared with a question mark at the end. + * For non-Kotlin types, it means the type or the symbol which was declared with this type + * is annotated with a runtime-retained nullability annotation such as [javax.annotation.Nullable]. + * + * Note that even if [isMarkedNullable] is false, values of the type can still be `null`. + * This may happen if it is a type of the type parameter with a nullable upper bound: + * + * ``` + * fun foo(t: T) { + * // isMarkedNullable == false for t's type, but t can be null here when T = "Any?" + * } + * ``` + */ + public actual val isMarkedNullable: Boolean +} diff --git a/kotlin-native/runtime/src/main/kotlin/kotlin/sequences/Sequences.kt b/kotlin-native/runtime/src/main/kotlin/kotlin/sequences/Sequences.kt new file mode 100644 index 00000000000..24c1fbd87b0 --- /dev/null +++ b/kotlin-native/runtime/src/main/kotlin/kotlin/sequences/Sequences.kt @@ -0,0 +1,22 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +package kotlin.sequences + +import kotlin.comparisons.* +import kotlin.native.internal.FixmeConcurrency + +@FixmeConcurrency +internal actual class ConstrainedOnceSequence actual constructor(sequence: Sequence) : Sequence { + // TODO: not MT friendly. + private var sequenceRef : Sequence? = sequence + + override actual fun iterator(): Iterator { + val sequence = sequenceRef + if (sequence == null) throw IllegalStateException("This sequence can be consumed only once.") + sequenceRef = null + return sequence.iterator() + } +} diff --git a/kotlin-native/runtime/src/main/kotlin/kotlin/system/Process.kt b/kotlin-native/runtime/src/main/kotlin/kotlin/system/Process.kt new file mode 100644 index 00000000000..c4b892fc172 --- /dev/null +++ b/kotlin-native/runtime/src/main/kotlin/kotlin/system/Process.kt @@ -0,0 +1,17 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +package kotlin.system + +/** + * Terminates the currently running process. + * + * @param status serves as a status code; by convention, + * a nonzero status code indicates abnormal termination. + * + * @return This method never returns normally. + */ +@SymbolName("Kotlin_system_exitProcess") +public external fun exitProcess(status: Int): Nothing \ No newline at end of file diff --git a/kotlin-native/runtime/src/main/kotlin/kotlin/system/Timing.kt b/kotlin-native/runtime/src/main/kotlin/kotlin/system/Timing.kt new file mode 100644 index 00000000000..9d205f3b621 --- /dev/null +++ b/kotlin-native/runtime/src/main/kotlin/kotlin/system/Timing.kt @@ -0,0 +1,48 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +package kotlin.system + +/** + * Gets current system time in milliseconds since certain moment in the past, + * only delta between two subsequent calls makes sense. + */ +@SymbolName("Kotlin_system_getTimeMillis") +public external fun getTimeMillis() : Long + +/** + * Gets current system time in nanoseconds since certain moment in the past, + * only delta between two subsequent calls makes sense. + */ +@SymbolName("Kotlin_system_getTimeNanos") +public external fun getTimeNanos() : Long + +/** + * Gets current system time in microseconds since certain moment in the past, + * only delta between two subsequent calls makes sense. + */ +@SymbolName("Kotlin_system_getTimeMicros") +public external fun getTimeMicros() : Long + +/** Executes the given [block] and returns elapsed time in milliseconds. */ +public inline fun measureTimeMillis(block: () -> Unit) : Long { + val start = getTimeMillis() + block() + return getTimeMillis() - start +} + +/** Executes the given [block] and returns elapsed time in microseconds (Kotlin/Native only). */ +public inline fun measureTimeMicros(block: () -> Unit) : Long { + val start = getTimeMicros() + block() + return getTimeMicros() - start +} + +/** Executes the given [block] and returns elapsed time in nanoseconds. */ +public inline fun measureNanoTime(block: () -> Unit) : Long { + val start = getTimeNanos() + block() + return getTimeNanos() - start +} diff --git a/kotlin-native/runtime/src/main/kotlin/kotlin/test/Annotation.kt b/kotlin-native/runtime/src/main/kotlin/kotlin/test/Annotation.kt new file mode 100644 index 00000000000..0dc98487596 --- /dev/null +++ b/kotlin-native/runtime/src/main/kotlin/kotlin/test/Annotation.kt @@ -0,0 +1,47 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +package kotlin.test + +/** + * Marks a function as a test. + */ +@Target(AnnotationTarget.FUNCTION) +public actual annotation class Test + +/** + * Marks a function to be executed before a suite. Not supported in Kotlin/Common. + */ +@Target(AnnotationTarget.FUNCTION) +public annotation class BeforeClass + +/** + * Marks a function to be executed after a suite. Not supported in Kotlin/Common. + */ +@Target(AnnotationTarget.FUNCTION) +public annotation class AfterClass + +/** + * Marks a function to be invoked before each test. + */ +@Target(AnnotationTarget.FUNCTION) +public actual annotation class BeforeTest + +/** + * Marks a function to be invoked after each test. + */ +@Target(AnnotationTarget.FUNCTION) +public actual annotation class AfterTest + +/** + * Marks a test or a suite as ignored. + */ +@Target(AnnotationTarget.CLASS, AnnotationTarget.FUNCTION) +public actual annotation class Ignore + +@Deprecated("AfterEach should be replaced with AfterTest to unify usage of kotlin.test", level = DeprecationLevel.ERROR) +public typealias AfterEach = AfterTest +@Deprecated("BeforeEach should be replaced with BeforeTest to unify usage of kotlin.test", level = DeprecationLevel.ERROR) +public typealias BeforeEach = BeforeTest diff --git a/kotlin-native/runtime/src/main/kotlin/kotlin/test/Assertions.kt b/kotlin-native/runtime/src/main/kotlin/kotlin/test/Assertions.kt new file mode 100644 index 00000000000..87660c4595c --- /dev/null +++ b/kotlin-native/runtime/src/main/kotlin/kotlin/test/Assertions.kt @@ -0,0 +1,47 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +/** + * A number of common helper methods for writing unit tests. + */ +@file:Suppress("INVISIBLE_MEMBER", "INVISIBLE_REFERENCE") + +package kotlin.test + +import kotlin.reflect.KClass + +/** + * Takes the given [block] of test code and _doesn't_ execute it. + * + * This keeps the code under test referenced, but doesn't actually test it until it is implemented. + */ +@Suppress("UNUSED_PARAMETER") +public actual inline fun todo(block: () -> Unit) { + println("TODO") +} + +@PublishedApi +internal actual fun checkResultIsFailure(exceptionClass: KClass, message: String?, blockResult: Result): T { + blockResult.fold( + onSuccess = { + asserter.fail(messagePrefix(message) + "Expected an exception of ${exceptionClass.qualifiedName} to be thrown, but was completed successfully.") + }, + onFailure = { e -> + if (exceptionClass.isInstance(e)) { + @Suppress("UNCHECKED_CAST") + return e as T + } + asserter.fail(messagePrefix(message) + "Expected an exception of ${exceptionClass.qualifiedName} to be thrown, but was $e", e) + } + ) +} + +/** Platform-specific construction of AssertionError with cause */ +@Suppress("NOTHING_TO_INLINE") +internal actual inline fun AssertionErrorWithCause(message: String?, cause: Throwable?): AssertionError = + AssertionError(message, cause) + + +internal actual fun lookupAsserter(): Asserter = DefaultAsserter \ No newline at end of file diff --git a/kotlin-native/runtime/src/main/kotlin/kotlin/text/Appendable.kt b/kotlin-native/runtime/src/main/kotlin/kotlin/text/Appendable.kt new file mode 100644 index 00000000000..74f572e022b --- /dev/null +++ b/kotlin-native/runtime/src/main/kotlin/kotlin/text/Appendable.kt @@ -0,0 +1,37 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +package kotlin.text + +/** + * An object to which char sequences and values can be appended. + */ +public actual interface Appendable { + /** + * Appends the specified character [value] to this Appendable and returns this instance. + * + * @param value the character to append. + */ + actual fun append(value: Char): Appendable + + /** + * Appends the specified character sequence [value] to this Appendable and returns this instance. + * + * @param value the character sequence to append. If [value] is `null`, then the four characters `"null"` are appended to this Appendable. + */ + actual fun append(value: CharSequence?): Appendable + + /** + * Appends a subsequence of the specified character sequence [value] to this Appendable and returns this instance. + * + * @param value the character sequence from which a subsequence is appended. If [value] is `null`, + * then characters are appended as if [value] contained the four characters `"null"`. + * @param startIndex the beginning (inclusive) of the subsequence to append. + * @param endIndex the end (exclusive) of the subsequence to append. + * + * @throws IndexOutOfBoundsException or [IllegalArgumentException] when [startIndex] or [endIndex] is out of range of the [value] character sequence indices or when `startIndex > endIndex`. + */ + actual fun append(value: CharSequence?, startIndex: Int, endIndex: Int): Appendable +} diff --git a/kotlin-native/runtime/src/main/kotlin/kotlin/text/Char.kt b/kotlin-native/runtime/src/main/kotlin/kotlin/text/Char.kt new file mode 100644 index 00000000000..3298d7d48de --- /dev/null +++ b/kotlin-native/runtime/src/main/kotlin/kotlin/text/Char.kt @@ -0,0 +1,159 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +package kotlin.text + +import kotlin.IllegalArgumentException + +/** + * Returns `true` if this character (Unicode code point) is defined in Unicode. + */ +@SymbolName("Kotlin_Char_isDefined") +external public fun Char.isDefined(): Boolean + +/** + * Returns `true` if this character is a letter. + */ +@SymbolName("Kotlin_Char_isLetter") +external public fun Char.isLetter(): Boolean + +/** + * Returns `true` if this character is a letter or digit. + */ +@SymbolName("Kotlin_Char_isLetterOrDigit") +external public fun Char.isLetterOrDigit(): Boolean + +/** + * Returns `true` if this character (Unicode code point) is a digit. + */ +@SymbolName("Kotlin_Char_isDigit") +external public fun Char.isDigit(): Boolean + +/** + * Returns `true` if this character (Unicode code point) should be regarded as an ignorable + * character in a Java identifier or a Unicode identifier. + */ +@SymbolName("Kotlin_Char_isIdentifierIgnorable") +external public fun Char.isIdentifierIgnorable(): Boolean + +/** + * Returns `true` if this character is an ISO control character. + */ +@SymbolName("Kotlin_Char_isISOControl") +external public fun Char.isISOControl(): Boolean + +/** + * Determines whether a character is whitespace according to the Unicode standard. + * Returns `true` if the character is whitespace. + */ +@SymbolName("Kotlin_Char_isWhitespace") +external public actual fun Char.isWhitespace(): Boolean + +/** + * Returns `true` if this character is upper case. + */ +@SymbolName("Kotlin_Char_isUpperCase") +external public fun Char.isUpperCase(): Boolean + +/** + * Returns `true` if this character is lower case. + */ +@SymbolName("Kotlin_Char_isLowerCase") +external public fun Char.isLowerCase(): Boolean + +/** + * Converts this character to uppercase. + */ +@SymbolName("Kotlin_Char_toUpperCase") +external public actual fun Char.toUpperCase(): Char + +/** + * Converts this character to lowercase. + */ +@SymbolName("Kotlin_Char_toLowerCase") +external public actual fun Char.toLowerCase(): Char + +/** + * Returns `true` if this character is a Unicode high-surrogate code unit (also known as leading-surrogate code unit). + */ +@SymbolName("Kotlin_Char_isHighSurrogate") +external public actual fun Char.isHighSurrogate(): Boolean + +/** + * Returns `true` if this character is a Unicode low-surrogate code unit (also known as trailing-surrogate code unit). + */ +@SymbolName("Kotlin_Char_isLowSurrogate") +external public actual fun Char.isLowSurrogate(): Boolean + + +internal actual fun digitOf(char: Char, radix: Int): Int = digitOfChecked(char, checkRadix(radix)) + +@SymbolName("Kotlin_Char_digitOfChecked") +external internal fun digitOfChecked(char: Char, radix: Int): Int + +/** + * Returns a value indicating a character's general category. + */ +public val Char.category: CharCategory get() = CharCategory.valueOf(getType()) + +/** Retrun a Unicode category of the character as an Int. */ +@SymbolName("Kotlin_Char_getType") +external internal fun Char.getType(): Int + +/** + * Checks whether the given [radix] is valid radix for string to number and number to string conversion. + */ +@PublishedApi +internal actual fun checkRadix(radix: Int): Int { + if(radix !in Char.MIN_RADIX..Char.MAX_RADIX) { + throw IllegalArgumentException("radix $radix was not in valid range ${Char.MIN_RADIX..Char.MAX_RADIX}") + } + return radix +} + +// Char.Compaion methods. Konan specific. + +// TODO: Make public when supplementary codepoints are supported. +/** Converts a unicode code point to lower case. */ +internal fun Char.Companion.toLowerCase(codePoint: Int): Int = + if (codePoint < MIN_SUPPLEMENTARY_CODE_POINT) { + codePoint.toChar().toLowerCase().toInt() + } else { + codePoint // TODO: Implement this transformation for supplementary codepoints. + } + +/** Converts a unicode code point to upper case. */ +internal fun Char.Companion.toUpperCase(codePoint: Int): Int = + if (codePoint < MIN_SUPPLEMENTARY_CODE_POINT) { + codePoint.toChar().toUpperCase().toInt() + } else { + codePoint // TODO: Implement this transformation for supplementary codepoints. + } + +/** Converts a surrogate pair to a unicode code point. Doesn't validate that the characters are a valid surrogate pair. */ +public fun Char.Companion.toCodePoint(high: Char, low: Char): Int = + (((high - MIN_HIGH_SURROGATE) shl 10) or (low - MIN_LOW_SURROGATE)) + 0x10000 + +/** Checks if the codepoint specified is a supplementary codepoint or not. */ +public fun Char.Companion.isSupplementaryCodePoint(codepoint: Int): Boolean = + codepoint in MIN_SUPPLEMENTARY_CODE_POINT..MAX_CODE_POINT + +public fun Char.Companion.isSurrogatePair(high: Char, low: Char): Boolean = high.isHighSurrogate() && low.isLowSurrogate() + +/** + * Converts the codepoint specified to a char array. If the codepoint is not supplementary, the method will + * return an array with one element otherwise it will return an array A with a high surrogate in A[0] and + * a low surrogate in A[1]. + */ +public fun Char.Companion.toChars(codePoint: Int): CharArray = + when { + codePoint in 0 until MIN_SUPPLEMENTARY_CODE_POINT -> charArrayOf(codePoint.toChar()) + codePoint in MIN_SUPPLEMENTARY_CODE_POINT..MAX_CODE_POINT -> { + val low = ((codePoint - 0x10000) and 0x3FF) + MIN_LOW_SURROGATE.toInt() + val high = (((codePoint - 0x10000) ushr 10) and 0x3FF) + MIN_HIGH_SURROGATE.toInt() + charArrayOf(high.toChar(), low.toChar()) + } + else -> throw IllegalArgumentException() + } diff --git a/kotlin-native/runtime/src/main/kotlin/kotlin/text/CharCategory.kt b/kotlin-native/runtime/src/main/kotlin/kotlin/text/CharCategory.kt new file mode 100644 index 00000000000..3bdd766f5df --- /dev/null +++ b/kotlin-native/runtime/src/main/kotlin/kotlin/text/CharCategory.kt @@ -0,0 +1,174 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ +package kotlin.text + +/** + * Represents the character general category in the Unicode specification. + */ +public enum class CharCategory(public val value: Int, public val code: String) { + /** + * General category "Cn" in the Unicode specification. + */ + UNASSIGNED(0, "Cn"), + + /** + * General category "Lu" in the Unicode specification. + */ + UPPERCASE_LETTER(1, "Lu"), + + /** + * General category "Ll" in the Unicode specification. + */ + LOWERCASE_LETTER(2, "Ll"), + + /** + * General category "Lt" in the Unicode specification. + */ + TITLECASE_LETTER(3, "Lt"), + + /** + * General category "Lm" in the Unicode specification. + */ + MODIFIER_LETTER(4, "Lm"), + + /** + * General category "Lo" in the Unicode specification. + */ + OTHER_LETTER(5, "Lo"), + + /** + * General category "Mn" in the Unicode specification. + */ + NON_SPACING_MARK(6, "Mn"), + + /** + * General category "Me" in the Unicode specification. + */ + ENCLOSING_MARK(7, "Me"), + + /** + * General category "Mc" in the Unicode specification. + */ + COMBINING_SPACING_MARK(8, "Mc"), + + /** + * General category "Nd" in the Unicode specification. + */ + DECIMAL_DIGIT_NUMBER(9, "Nd"), + + /** + * General category "Nl" in the Unicode specification. + */ + LETTER_NUMBER(10, "Nl"), + + /** + * General category "No" in the Unicode specification. + */ + OTHER_NUMBER(11, "No"), + + /** + * General category "Zs" in the Unicode specification. + */ + SPACE_SEPARATOR(12, "Zs"), + + /** + * General category "Zl" in the Unicode specification. + */ + LINE_SEPARATOR(13, "Zl"), + + /** + * General category "Zp" in the Unicode specification. + */ + PARAGRAPH_SEPARATOR(14, "Zp"), + + /** + * General category "Cc" in the Unicode specification. + */ + CONTROL(15, "Cc"), + + /** + * General category "Cf" in the Unicode specification. + */ + FORMAT(16, "Cf"), + + /** + * General category "Co" in the Unicode specification. + */ + PRIVATE_USE(18, "Co"), + + /** + * General category "Cs" in the Unicode specification. + */ + SURROGATE(19, "Cs"), + + /** + * General category "Pd" in the Unicode specification. + */ + DASH_PUNCTUATION(20, "Pd"), + + /** + * General category "Ps" in the Unicode specification. + */ + START_PUNCTUATION(21, "Ps"), + + /** + * General category "Pe" in the Unicode specification. + */ + END_PUNCTUATION(22, "Pe"), + + /** + * General category "Pc" in the Unicode specification. + */ + CONNECTOR_PUNCTUATION(23, "Pc"), + + /** + * General category "Po" in the Unicode specification. + */ + OTHER_PUNCTUATION(24, "Po"), + + /** + * General category "Sm" in the Unicode specification. + */ + MATH_SYMBOL(25, "Sm"), + + /** + * General category "Sc" in the Unicode specification. + */ + CURRENCY_SYMBOL(26, "Sc"), + + /** + * General category "Sk" in the Unicode specification. + */ + MODIFIER_SYMBOL(27, "Sk"), + + /** + * General category "So" in the Unicode specification. + */ + OTHER_SYMBOL(28, "So"), + + /** + * General category "Pi" in the Unicode specification. + */ + INITIAL_QUOTE_PUNCTUATION(29, "Pi"), + + /** + * General category "Pf" in the Unicode specification. + */ + FINAL_QUOTE_PUNCTUATION(30, "Pf"); + + /** + * Returns `true` if [char] character belongs to this category. + */ + public operator fun contains(char: Char): Boolean = char.getType() == this.value + + public companion object { + public fun valueOf(category: Int): CharCategory = + when { + category >=0 && category <= 16 -> values()[category] + category >= 18 && category <= 30 -> values()[category - 1] + else -> throw IllegalArgumentException("Category #$category is not defined.") + } + } +} \ No newline at end of file diff --git a/kotlin-native/runtime/src/main/kotlin/kotlin/text/CharacterCodingException.kt b/kotlin-native/runtime/src/main/kotlin/kotlin/text/CharacterCodingException.kt new file mode 100644 index 00000000000..b17aa0164ca --- /dev/null +++ b/kotlin-native/runtime/src/main/kotlin/kotlin/text/CharacterCodingException.kt @@ -0,0 +1,14 @@ +/* + * Copyright 2010-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +package kotlin.text + +/** + * The exception thrown when a character encoding or decoding error occurs. + */ +@SinceKotlin("1.3") +public actual open class CharacterCodingException(message: String?) : Exception(message) { + actual constructor() : this(null) +} diff --git a/kotlin-native/runtime/src/main/kotlin/kotlin/text/PatternSyntaxException.kt b/kotlin-native/runtime/src/main/kotlin/kotlin/text/PatternSyntaxException.kt new file mode 100644 index 00000000000..8dd59bd287e --- /dev/null +++ b/kotlin-native/runtime/src/main/kotlin/kotlin/text/PatternSyntaxException.kt @@ -0,0 +1,32 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +package kotlin.text + +/** + * Encapsulates a syntax error that occurred during the compilation of a + * [Pattern]. Might include a detailed description, the original regular + * expression, and the index at which the error occurred. + */ +internal class PatternSyntaxException( + val description: String = "", + val pattern: String = "", + val index: Int = -1 +) : IllegalArgumentException(formatMessage(description, pattern, index)) { + companion object { + fun formatMessage(description: String, pattern: String, index: Int): String { + if (index < 0 || pattern == "") { + return description + } + + val filler = if (index >= 1) " ".repeat(index) else "" + return """ + $description near index: $index + $pattern + $filler^ + """.trimIndent() + } + } +} diff --git a/kotlin-native/runtime/src/main/kotlin/kotlin/text/Regex.kt b/kotlin-native/runtime/src/main/kotlin/kotlin/text/Regex.kt new file mode 100644 index 00000000000..423a3b33191 --- /dev/null +++ b/kotlin-native/runtime/src/main/kotlin/kotlin/text/Regex.kt @@ -0,0 +1,315 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +package kotlin.text + +import kotlin.text.regex.* + +@PublishedApi +internal interface FlagEnum { + val value: Int + val mask: Int +} + +private fun Iterable.toInt(): Int = this.fold(0, { value, option -> value or option.value }) + +private fun fromInt(value: Int): Set = + RegexOption.values().filterTo(mutableSetOf()) { value and it.mask == it.value } + +/** + * Provides enumeration values to use to set regular expression options. + */ +public actual enum class RegexOption(override val value: Int, override val mask: Int = value) : FlagEnum { + // common + + /** Enables case-insensitive matching. Case comparison is Unicode-aware. */ + IGNORE_CASE(Pattern.CASE_INSENSITIVE), + + /** + * Enables multiline mode. + * + * In multiline mode the expressions `^` and `$` match just after or just before, + * respectively, a line terminator or the end of the input sequence. + */ + MULTILINE(Pattern.MULTILINE), + + /** + * Enables literal parsing of the pattern. + * + * Metacharacters or escape sequences in the input sequence will be given no special meaning. + */ + LITERAL(Pattern.LITERAL), + + /** Enables Unix lines mode. In this mode, only the `'\n'` is recognized as a line terminator. */ + UNIX_LINES(Pattern.UNIX_LINES), + + /** Permits whitespace and comments in pattern. */ + COMMENTS(Pattern.COMMENTS), + + /** Enables the mode, when the expression `.` matches any character, including a line terminator. */ + DOT_MATCHES_ALL(Pattern.DOTALL), + + /** Enables equivalence by canonical decomposition. */ + CANON_EQ(Pattern.CANON_EQ) +} + + +/** + * Represents the results from a single capturing group within a [MatchResult] of [Regex]. + * + * @param value The value of captured group. + * @param range The range of indices in the input string where group was captured. + * + * The [range] property is available on JVM only. + */ +public actual data class MatchGroup(actual val value: String, val range: IntRange) + +/** + * Represents a compiled regular expression. + * Provides functions to match strings in text with a pattern, replace the found occurrences and split text around matches. + */ +public actual class Regex internal constructor(internal val nativePattern: Pattern) { + + internal enum class Mode { + FIND, MATCH + } + + /** Creates a regular expression from the specified [pattern] string and the default options. */ + actual constructor(pattern: String): this(Pattern(pattern)) + + /** Creates a regular expression from the specified [pattern] string and the specified single [option]. */ + actual constructor(pattern: String, option: RegexOption): this(Pattern(pattern, ensureUnicodeCase(option.value))) + + /** Creates a regular expression from the specified [pattern] string and the specified set of [options]. */ + actual constructor(pattern: String, options: Set): this(Pattern(pattern, ensureUnicodeCase(options.toInt()))) + + + /** The pattern string of this regular expression. */ + actual val pattern: String + get() = nativePattern.pattern + + private val startNode = nativePattern.startNode + + /** The set of options that were used to create this regular expression. */ + actual val options: Set = fromInt(nativePattern.flags) + + actual companion object { + /** + * Returns a regular expression that matches the specified [literal] string literally. + * No characters of that string will have special meaning when searching for an occurrence of the regular expression. + */ + actual fun fromLiteral(literal: String): Regex = Regex(literal, RegexOption.LITERAL) + + /** + * Returns a regular expression pattern string that matches the specified [literal] string literally. + * No characters of that string will have special meaning when searching for an occurrence of the regular expression. + */ + actual fun escape(literal: String): String = Pattern.quote(literal) + + /** + * Returns a literal replacement expression for the specified [literal] string. + * No characters of that string will have special meaning when it is used as a replacement string in [Regex.replace] function. + */ + actual fun escapeReplacement(literal: String): String { + if (!literal.contains('\\') && !literal.contains('$')) + return literal + + val result = StringBuilder(literal.length * 2) + literal.forEach { + if (it == '\\' || it == '$') { + result.append('\\') + } + result.append(it) + } + + return result.toString() + } + + // TODO: Remove + private fun ensureUnicodeCase(flags: Int) = flags + } + + private fun doMatch(input: CharSequence, mode: Mode): MatchResult? { + // TODO: Harmony has a default constructor for MatchResult. Do we need it? + // TODO: Reuse the matchResult. + val matchResult = MatchResultImpl(input, this) + matchResult.mode = mode + val matches = startNode.matches(0, input, matchResult) >= 0 + if (!matches) { + return null + } + matchResult.finalizeMatch() + return matchResult + } + + /** Indicates whether the regular expression matches the entire [input]. */ + actual infix fun matches(input: CharSequence): Boolean = doMatch(input, Mode.MATCH) != null + + /** Indicates whether the regular expression can find at least one match in the specified [input]. */ + actual fun containsMatchIn(input: CharSequence): Boolean = find(input) != null + + /** + * Returns the first match of a regular expression in the [input], beginning at the specified [startIndex]. + * + * @param startIndex An index to start search with, by default 0. Must be not less than zero and not greater than `input.length()` + * @return An instance of [MatchResult] if match was found or `null` otherwise. + * @throws IndexOutOfBoundsException if [startIndex] is less than zero or greater than the length of the [input] char sequence. + */ + actual fun find(input: CharSequence, startIndex: Int): MatchResult? { + if (startIndex < 0 || startIndex > input.length) { + throw IndexOutOfBoundsException("Start index is out of bounds: $startIndex, input length: ${input.length}") + } + val matchResult = MatchResultImpl(input, this) + matchResult.mode = Mode.FIND + matchResult.startIndex = startIndex + val foundIndex = startNode.find(startIndex, input, matchResult) + if (foundIndex >= 0) { + matchResult.finalizeMatch() + return matchResult + } else { + return null + } + } + + /** + * Returns a sequence of all occurrences of a regular expression within the [input] string, beginning at the specified [startIndex]. + * + * @throws IndexOutOfBoundsException if [startIndex] is less than zero or greater than the length of the [input] char sequence. + */ + actual fun findAll(input: CharSequence, startIndex: Int): Sequence { + if (startIndex < 0 || startIndex > input.length) { + throw IndexOutOfBoundsException("Start index is out of bounds: $startIndex, input length: ${input.length}") + } + return generateSequence({ find(input, startIndex) }, MatchResult::next) + } + + /** + * Attempts to match the entire [input] CharSequence against the pattern. + * + * @return An instance of [MatchResult] if the entire input matches or `null` otherwise. + */ + actual fun matchEntire(input: CharSequence): MatchResult?= doMatch(input, Mode.MATCH) + + private fun processReplacement(match: MatchResult, replacement: String): String { + val result = StringBuilder(replacement.length) + var escaped = false + var backReference = false + for (ch in replacement) { + when { + escaped -> { + result.append(ch) + escaped = false + } + backReference -> { + if (ch !in '0'..'9') { + throw IllegalArgumentException("Incorrect back reference: $ch.") + } + val group = ch - '0' + result.append(match.groupValues[group]) + // We don't catch IndexOutOfBoundException here because + // it's a correct exception in case of a wrong group number. + // TODO: But we can rethrow it with more informative message. + backReference = false + } + ch == '\\' -> escaped = true + ch == '$' -> backReference = true + else -> result.append(ch) + } + } + if (backReference || escaped) { + throw IllegalArgumentException("Unexpected end of replacement.") + } + return result.toString() + } + + /** + * Replaces all occurrences of this regular expression in the specified [input] string with + * specified [replacement] expression. + * + * @param replacement A replacement expression that can include substitutions. + */ + actual fun replace(input: CharSequence, replacement: String): String + = replace(input) { match -> processReplacement(match, replacement) } + + /** + * Replaces all occurrences of this regular expression in the specified [input] string with the result of + * the given function [transform] that takes [MatchResult] and returns a string to be used as a + * replacement for that match. + */ + actual fun replace(input: CharSequence, transform: (MatchResult) -> CharSequence): String { + var match: MatchResult? = find(input) ?: return input.toString() + + var lastStart = 0 + val length = input.length + val sb = StringBuilder(length) + do { + val foundMatch = match!! + sb.append(input, lastStart, foundMatch.range.start) + sb.append(transform(foundMatch)) + lastStart = foundMatch.range.endInclusive + 1 + match = foundMatch.next() + } while (lastStart < length && match != null) + + if (lastStart < length) { + sb.append(input, lastStart, length) + } + + return sb.toString() + } + + /** + * Replaces the first occurrence of this regular expression in the specified [input] string with specified [replacement] expression. + * + * @param replacement A replacement expression that can include substitutions. + */ + actual fun replaceFirst(input: CharSequence, replacement: String): String { + val match = find(input) ?: return input.toString() + val length = input.length + val result = StringBuilder(length) + result.append(input, 0, match.range.start) + result.append(processReplacement(match, replacement)) + if (match.range.endInclusive + 1 < length) { + result.append(input, match.range.endInclusive + 1, length) + } + return result.toString() + } + + /** + * Splits the [input] CharSequence around matches of this regular expression. + * + * @param limit Non-negative value specifying the maximum number of substrings the string can be split to. + * Zero by default means no limit is set. + */ + actual fun split(input: CharSequence, limit: Int): List { + require(limit >= 0, { "Limit must be non-negative, but was $limit." } ) + + var match: MatchResult? = find(input) + + if (match == null || limit == 1) return listOf(input.toString()) + + val result = ArrayList(if (limit > 0) limit.coerceAtMost(10) else 10) + var lastStart = 0 + val lastSplit = limit - 1 // negative if there's no limit + + do { + result.add(input.substring(lastStart, match!!.range.start)) + lastStart = match.range.endInclusive + 1 + if (lastSplit >= 0 && result.size == lastSplit) break + match = match.next() + } while (match != null) + + result.add(input.substring(lastStart, input.length)) + + return result + } + + /** + * Returns the string representation of this regular expression, namely the [pattern] of this regular expression. + * + * Note that another regular expression constructed from the same pattern string may have different [options] + * and may match strings differently. + */ + override fun toString(): String = nativePattern.toString() +} diff --git a/kotlin-native/runtime/src/main/kotlin/kotlin/text/StringBuilder.kt b/kotlin-native/runtime/src/main/kotlin/kotlin/text/StringBuilder.kt new file mode 100644 index 00000000000..c85f4f7b237 --- /dev/null +++ b/kotlin-native/runtime/src/main/kotlin/kotlin/text/StringBuilder.kt @@ -0,0 +1,917 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +package kotlin.text + +/** + * A mutable sequence of characters. + * + * String builder can be used to efficiently perform multiple string manipulation operations. + */ +actual class StringBuilder private constructor ( + private var array: CharArray) : CharSequence, Appendable { + + /** Constructs an empty string builder. */ + actual constructor() : this(10) + + /** Constructs an empty string builder with the specified initial [capacity]. */ + actual constructor(capacity: Int) : this(CharArray(capacity)) + + /** Constructs a string builder that contains the same characters as the specified [content] string. */ + actual constructor(content: String) : this(content.toCharArray()) { + _length = array.size + } + + /** Constructs a string builder that contains the same characters as the specified [content] char sequence. */ + actual constructor(content: CharSequence): this(content.length) { + append(content) + } + + // Of CharSequence. + private var _length: Int = 0 + set(capacity) { + ensureCapacity(capacity) + field = capacity + } + actual override val length: Int + get() = _length + + actual override fun get(index: Int): Char { + checkIndex(index) + return array[index] + } + + actual override fun subSequence(startIndex: Int, endIndex: Int): CharSequence = substring(startIndex, endIndex) + + // Of Appenable. + actual override fun append(value: Char) : StringBuilder { + ensureExtraCapacity(1) + array[_length++] = value + return this + } + + actual override fun append(value: CharSequence?): StringBuilder { + // Kotlin/JVM processes null as if the argument was "null" char sequence. + val toAppend = value ?: "null" + return append(toAppend, 0, toAppend.length) + } + + actual override fun append(value: CharSequence?, startIndex: Int, endIndex: Int): StringBuilder = + this.appendRange(value ?: "null", startIndex, endIndex) + + /** + * Reverses the contents of this string builder and returns this instance. + * + * Surrogate pairs included in this string builder are treated as single characters. + * Therefore, the order of the high-low surrogates is never reversed. + * + * Note that the reverse operation may produce new surrogate pairs that were unpaired low-surrogates and high-surrogates before the operation. + * For example, reversing `"\uDC00\uD800"` produces `"\uD800\uDC00"` which is a valid surrogate pair. + */ + // Based on Apache Harmony implementation. + actual fun reverse(): StringBuilder { + if (this.length < 2) { + return this + } + var end = _length - 1 + var front = 0 + var frontLeadingChar = array[0] + var endTrailingChar = array[end] + var allowFrontSurrogate = true + var allowEndSurrogate = true + while (front < _length / 2) { + + var frontTrailingChar = array[front + 1] + var endLeadingChar = array[end - 1] + var surrogateAtFront = allowFrontSurrogate && frontTrailingChar.isLowSurrogate() && frontLeadingChar.isHighSurrogate() + if (surrogateAtFront && _length < 3) { + return this + } + var surrogateAtEnd = allowEndSurrogate && endTrailingChar.isLowSurrogate() && endLeadingChar.isHighSurrogate() + allowFrontSurrogate = true + allowEndSurrogate = true + when { + surrogateAtFront && surrogateAtEnd -> { + // Both surrogates - just exchange them. + array[end] = frontTrailingChar + array[end - 1] = frontLeadingChar + array[front] = endLeadingChar + array[front + 1] = endTrailingChar + frontLeadingChar = array[front + 2] + endTrailingChar = array[end - 2] + front++ + end-- + } + !surrogateAtFront && !surrogateAtEnd -> { + // Neither surrogates - exchange only front/end. + array[end] = frontLeadingChar + array[front] = endTrailingChar + frontLeadingChar = frontTrailingChar + endTrailingChar = endLeadingChar + } + surrogateAtFront && !surrogateAtEnd -> { + // Surrogate only at the front - + // move the low part, the high part will be moved as a usual character on the next iteration. + array[end] = frontTrailingChar + array[front] = endTrailingChar + endTrailingChar = endLeadingChar + allowFrontSurrogate = false + } + !surrogateAtFront && surrogateAtEnd -> { + // Surrogate only at the end - + // move the high part, the low part will be moved as a usual character on the next iteration. + array[end] = frontLeadingChar + array[front] = endLeadingChar + frontLeadingChar = frontTrailingChar + allowEndSurrogate = false + } + } + front++ + end-- + } + if (_length % 2 == 1 && (!allowEndSurrogate || !allowFrontSurrogate)) { + array[end] = if (allowFrontSurrogate) endTrailingChar else frontLeadingChar + } + return this + } + + /** + * Appends the string representation of the specified object [value] to this string builder and returns this instance. + * + * The overall effect is exactly as if the [value] were converted to a string by the `value.toString()` method, + * and then that string was appended to this string builder. + */ + actual fun append(value: Any?): StringBuilder = append(value.toString()) + + /** + * Appends the string representation of the specified boolean [value] to this string builder and returns this instance. + * + * The overall effect is exactly as if the [value] were converted to a string by the `value.toString()` method, + * and then that string was appended to this string builder. + */ + // TODO: optimize those! + actual fun append(value: Boolean): StringBuilder = append(value.toString()) + fun append(value: Byte): StringBuilder = append(value.toString()) + fun append(value: Short): StringBuilder = append(value.toString()) + fun append(value: Int): StringBuilder { + ensureExtraCapacity(11) + _length += insertInt(array, _length, value) + return this + } + fun append(value: Long): StringBuilder = append(value.toString()) + fun append(value: Float): StringBuilder = append(value.toString()) + fun append(value: Double): StringBuilder = append(value.toString()) + + /** + * Appends characters in the specified character array [value] to this string builder and returns this instance. + * + * Characters are appended in order, starting at the index 0. + */ + actual fun append(value: CharArray): StringBuilder { + ensureExtraCapacity(value.size) + value.copyInto(array, _length) + _length += value.size + return this + } + + @Deprecated("Provided for binary compatibility.", level = DeprecationLevel.HIDDEN) + fun append(value: String): StringBuilder = append(value) + + /** + * Appends the specified string [value] to this string builder and returns this instance. + * + * If [value] is `null`, then the four characters `"null"` are appended. + */ + actual fun append(value: String?): StringBuilder { + val toAppend = value ?: "null" + ensureExtraCapacity(toAppend.length) + _length += insertString(array, _length, toAppend) + return this + } + + /** + * Returns the current capacity of this string builder. + * + * The capacity is the maximum length this string builder can have before an allocation occurs. + */ + actual fun capacity(): Int = array.size + + /** + * Ensures that the capacity of this string builder is at least equal to the specified [minimumCapacity]. + * + * If the current capacity is less than the [minimumCapacity], a new backing storage is allocated with greater capacity. + * Otherwise, this method takes no action and simply returns. + */ + actual fun ensureCapacity(minimumCapacity: Int) { + if (minimumCapacity > array.size) { + var newSize = array.size * 2 + 2 + if (minimumCapacity > newSize) + newSize = minimumCapacity + array = array.copyOf(newSize) + } + } + + /** + * Returns the index within this string builder of the first occurrence of the specified [string]. + * + * Returns `-1` if the specified [string] does not occur in this string builder. + */ + @SinceKotlin("1.4") + @WasExperimental(ExperimentalStdlibApi::class) + actual fun indexOf(string: String): Int { + return (this as CharSequence).indexOf(string, startIndex = 0, ignoreCase = false) + } + + /** + * Returns the index within this string builder of the first occurrence of the specified [string], + * starting at the specified [startIndex]. + * + * Returns `-1` if the specified [string] does not occur in this string builder starting at the specified [startIndex]. + */ + @SinceKotlin("1.4") + @WasExperimental(ExperimentalStdlibApi::class) + actual fun indexOf(string: String, startIndex: Int): Int { + if (string.isEmpty() && startIndex >= _length) return _length + return (this as CharSequence).indexOf(string, startIndex, ignoreCase = false) + } + + /** + * Returns the index within this string builder of the last occurrence of the specified [string]. + * The last occurrence of empty string `""` is considered to be at the index equal to `this.length`. + * + * Returns `-1` if the specified [string] does not occur in this string builder. + */ + @SinceKotlin("1.4") + @WasExperimental(ExperimentalStdlibApi::class) + actual fun lastIndexOf(string: String): Int { + if (string.isEmpty()) return _length + return (this as CharSequence).lastIndexOf(string, startIndex = lastIndex, ignoreCase = false) + } + + /** + * Returns the index within this string builder of the last occurrence of the specified [string], + * starting from the specified [startIndex] toward the beginning. + * + * Returns `-1` if the specified [string] does not occur in this string builder starting at the specified [startIndex]. + */ + @SinceKotlin("1.4") + @WasExperimental(ExperimentalStdlibApi::class) + actual fun lastIndexOf(string: String, startIndex: Int): Int { + if (string.isEmpty() && startIndex >= _length) return _length + return (this as CharSequence).lastIndexOf(string, startIndex, ignoreCase = false) + } + + /** + * Inserts the string representation of the specified boolean [value] into this string builder at the specified [index] and returns this instance. + * + * The overall effect is exactly as if the [value] were converted to a string by the `value.toString()` method, + * and then that string was inserted into this string builder at the specified [index]. + * + * @throws IndexOutOfBoundsException if [index] is less than zero or greater than the length of this string builder. + */ + // TODO: optimize those! + actual fun insert(index: Int, value: Boolean): StringBuilder = insert(index, value.toString()) + fun insert(index: Int, value: Byte) = insert(index, value.toString()) + fun insert(index: Int, value: Short) = insert(index, value.toString()) + fun insert(index: Int, value: Int) = insert(index, value.toString()) + fun insert(index: Int, value: Long) = insert(index, value.toString()) + fun insert(index: Int, value: Float) = insert(index, value.toString()) + fun insert(index: Int, value: Double) = insert(index, value.toString()) + + /** + * Inserts the specified character [value] into this string builder at the specified [index] and returns this instance. + * + * @throws IndexOutOfBoundsException if [index] is less than zero or greater than the length of this string builder. + */ + actual fun insert(index: Int, value: Char): StringBuilder { + checkInsertIndex(index) + ensureExtraCapacity(1) + val newLastIndex = lastIndex + 1 + for (i in newLastIndex downTo index + 1) { + array[i] = array[i - 1] + } + array[index] = value + _length++ + return this + } + + /** + * Inserts characters in the specified character array [value] into this string builder at the specified [index] and returns this instance. + * + * The inserted characters go in same order as in the [value] character array, starting at [index]. + * + * @throws IndexOutOfBoundsException if [index] is less than zero or greater than the length of this string builder. + */ + actual fun insert(index: Int, value: CharArray): StringBuilder { + checkInsertIndex(index) + ensureExtraCapacity(value.size) + + array.copyInto(array, startIndex = index, endIndex = _length, destinationOffset = index + value.size) + value.copyInto(array, destinationOffset = index) + + _length += value.size + return this + } + + /** + * Inserts characters in the specified character sequence [value] into this string builder at the specified [index] and returns this instance. + * + * The inserted characters go in the same order as in the [value] character sequence, starting at [index]. + * + * @param index the position in this string builder to insert at. + * @param value the character sequence from which characters are inserted. If [value] is `null`, then the four characters `"null"` are inserted. + * + * @throws IndexOutOfBoundsException if [index] is less than zero or greater than the length of this string builder. + */ + actual fun insert(index: Int, value: CharSequence?): StringBuilder { + // Kotlin/JVM inserts the "null" string if the argument is null. + val toInsert = value ?: "null" + return insertRange(index, toInsert, 0, toInsert.length) + } + + /** + * Inserts the string representation of the specified object [value] into this string builder at the specified [index] and returns this instance. + * + * The overall effect is exactly as if the [value] were converted to a string by the `value.toString()` method, + * and then that string was inserted into this string builder at the specified [index]. + * + * @throws IndexOutOfBoundsException if [index] is less than zero or greater than the length of this string builder. + */ + actual fun insert(index: Int, value: Any?): StringBuilder = insert(index, value.toString()) + + @Deprecated("Provided for binary compatibility.", level = DeprecationLevel.HIDDEN) + fun insert(index: Int, value: String): StringBuilder = insert(index, value) + + /** + * Inserts the string [value] into this string builder at the specified [index] and returns this instance. + * + * If [value] is `null`, then the four characters `"null"` are inserted. + * + * @throws IndexOutOfBoundsException if [index] is less than zero or greater than the length of this string builder. + */ + actual fun insert(index: Int, value: String?): StringBuilder { + val toInsert = value ?: "null" + checkInsertIndex(index) + ensureExtraCapacity(toInsert.length) + array.copyInto(array, startIndex = index, endIndex = _length, destinationOffset = index + toInsert.length) + _length += insertString(array, index, toInsert) + return this + } + + /** + * Sets the length of this string builder to the specified [newLength]. + * + * If the [newLength] is less than the current length, it is changed to the specified [newLength]. + * Otherwise, null characters '\u0000' are appended to this string builder until its length is less than the [newLength]. + * + * Note that in Kotlin/JS [set] operator function has non-constant execution time complexity. + * Therefore, increasing length of this string builder and then updating each character by index may slow down your program. + * + * @throws IndexOutOfBoundsException or [IllegalArgumentException] if [newLength] is less than zero. + */ + actual fun setLength(newLength: Int) { + if (newLength < 0) { + throw IllegalArgumentException("Negative new length: $newLength.") + } + + if (newLength > _length) { + array.fill('\u0000', _length, newLength.coerceAtMost(array.size)) + } + _length = newLength + } + + /** + * Returns a new [String] that contains characters in this string builder at [startIndex] (inclusive) and up to the [endIndex] (exclusive). + * + * @throws IndexOutOfBoundsException or [IllegalArgumentException] when [startIndex] or [endIndex] is out of range of this string builder indices or when `startIndex > endIndex`. + */ + actual fun substring(startIndex: Int, endIndex: Int): String { + checkBoundsIndexes(startIndex, endIndex, _length) + return unsafeStringFromCharArray(array, startIndex, endIndex - startIndex) + } + + /** + * Returns a new [String] that contains characters in this string builder at [startIndex] (inclusive) and up to the [length] (exclusive). + * + * @throws IndexOutOfBoundsException if [startIndex] is less than zero or greater than the length of this string builder. + */ + @SinceKotlin("1.4") + @WasExperimental(ExperimentalStdlibApi::class) + actual fun substring(startIndex: Int): String { + return substring(startIndex, _length) + } + + /** + * Attempts to reduce storage used for this string builder. + * + * If the backing storage of this string builder is larger than necessary to hold its current contents, + * then it may be resized to become more space efficient. + * Calling this method may, but is not required to, affect the value of the [capacity] property. + */ + actual fun trimToSize() { + if (_length < array.size) + array = array.copyOf(_length) + } + + override fun toString(): String = unsafeStringFromCharArray(array, 0, _length) + + /** + * Sets the character at the specified [index] to the specified [value]. + * + * @throws IndexOutOfBoundsException if [index] is out of bounds of this string builder. + */ + operator fun set(index: Int, value: Char) { + checkIndex(index) + array[index] = value + } + + /** + * Replaces characters in the specified range of this string builder with characters in the specified string [value] and returns this instance. + * + * @param startIndex the beginning (inclusive) of the range to replace. + * @param endIndex the end (exclusive) of the range to replace. + * @param value the string to replace with. + * + * @throws IndexOutOfBoundsException or [IllegalArgumentException] if [startIndex] is less than zero, greater than the length of this string builder, or `startIndex > endIndex`. + */ + @SinceKotlin("1.4") + @WasExperimental(ExperimentalStdlibApi::class) + fun setRange(startIndex: Int, endIndex: Int, value: String): StringBuilder { + checkReplaceRange(startIndex, endIndex, _length) + + val coercedEndIndex = endIndex.coerceAtMost(_length) + val lengthDiff = value.length - (coercedEndIndex - startIndex) + ensureExtraCapacity(_length + lengthDiff) + array.copyInto(array, startIndex = coercedEndIndex, endIndex = _length, destinationOffset = startIndex + value.length) + var replaceIndex = startIndex + for (index in 0 until value.length) array[replaceIndex++] = value[index] // optimize + _length += lengthDiff + + return this + } + + /** + * Removes the character at the specified [index] from this string builder and returns this instance. + * + * If the `Char` at the specified [index] is part of a supplementary code point, this method does not remove the entire supplementary character. + * + * @param index the index of `Char` to remove. + * + * @throws IndexOutOfBoundsException if [index] is out of bounds of this string builder. + */ + @SinceKotlin("1.4") + @WasExperimental(ExperimentalStdlibApi::class) + fun deleteAt(index: Int): StringBuilder { + checkIndex(index) + array.copyInto(array, startIndex = index + 1, endIndex = _length, destinationOffset = index) + --_length + return this + } + + /** + * Removes characters in the specified range from this string builder and returns this instance. + * + * @param startIndex the beginning (inclusive) of the range to remove. + * @param endIndex the end (exclusive) of the range to remove. + * + * @throws IndexOutOfBoundsException or [IllegalArgumentException] when [startIndex] is out of range of this string builder indices or when `startIndex > endIndex`. + */ + @SinceKotlin("1.4") + @WasExperimental(ExperimentalStdlibApi::class) + fun deleteRange(startIndex: Int, endIndex: Int): StringBuilder { + checkReplaceRange(startIndex, endIndex, _length) + + val coercedEndIndex = endIndex.coerceAtMost(_length) + array.copyInto(array, startIndex = coercedEndIndex, endIndex = _length, destinationOffset = startIndex) + _length -= coercedEndIndex - startIndex + return this + } + + /** + * Copies characters from this string builder into the [destination] character array. + * + * @param destination the array to copy to. + * @param destinationOffset the position in the array to copy to, 0 by default. + * @param startIndex the beginning (inclusive) of the range to copy, 0 by default. + * @param endIndex the end (exclusive) of the range to copy, length of this string builder by default. + * + * @throws IndexOutOfBoundsException or [IllegalArgumentException] when [startIndex] or [endIndex] is out of range of this string builder indices or when `startIndex > endIndex`. + * @throws IndexOutOfBoundsException when the subrange doesn't fit into the [destination] array starting at the specified [destinationOffset], + * or when that index is out of the [destination] array indices range. + */ + @SinceKotlin("1.4") + @WasExperimental(ExperimentalStdlibApi::class) + fun toCharArray(destination: CharArray, destinationOffset: Int = 0, startIndex: Int = 0, endIndex: Int = this.length) { + checkBoundsIndexes(startIndex, endIndex, _length) + checkBoundsIndexes(destinationOffset, destinationOffset + endIndex - startIndex, destination.size) + + array.copyInto(destination, destinationOffset, startIndex, endIndex) + } + + /** + * Appends characters in a subarray of the specified character array [value] to this string builder and returns this instance. + * + * Characters are appended in order, starting at specified [startIndex]. + * + * @param value the array from which characters are appended. + * @param startIndex the beginning (inclusive) of the subarray to append. + * @param endIndex the end (exclusive) of the subarray to append. + * + * @throws IndexOutOfBoundsException or [IllegalArgumentException] when [startIndex] or [endIndex] is out of range of the [value] array indices or when `startIndex > endIndex`. + */ + @SinceKotlin("1.4") + @WasExperimental(ExperimentalStdlibApi::class) + fun appendRange(value: CharArray, startIndex: Int, endIndex: Int): StringBuilder { + checkBoundsIndexes(startIndex, endIndex, value.size) + val extraLength = endIndex - startIndex + ensureExtraCapacity(extraLength) + value.copyInto(array, _length, startIndex, endIndex) + _length += extraLength + return this + } + + /** + * Appends a subsequence of the specified character sequence [value] to this string builder and returns this instance. + * + * @param value the character sequence from which a subsequence is appended. + * @param startIndex the beginning (inclusive) of the subsequence to append. + * @param endIndex the end (exclusive) of the subsequence to append. + * + * @throws IndexOutOfBoundsException or [IllegalArgumentException] when [startIndex] or [endIndex] is out of range of the [value] character sequence indices or when `startIndex > endIndex`. + */ + @SinceKotlin("1.4") + @WasExperimental(ExperimentalStdlibApi::class) + fun appendRange(value: CharSequence, startIndex: Int, endIndex: Int): StringBuilder { + checkBoundsIndexes(startIndex, endIndex, value.length) + val extraLength = endIndex - startIndex + ensureExtraCapacity(extraLength) + (value as? String)?.let { + _length += insertString(array, _length, it, startIndex, extraLength) + return this + } + var index = startIndex + while (index < endIndex) + array[_length++] = value[index++] + return this + } + + /** + * Inserts characters in a subsequence of the specified character sequence [value] into this string builder at the specified [index] and returns this instance. + * + * The inserted characters go in the same order as in the [value] character sequence, starting at [index]. + * + * @param index the position in this string builder to insert at. + * @param value the character sequence from which a subsequence is inserted. + * @param startIndex the beginning (inclusive) of the subsequence to insert. + * @param endIndex the end (exclusive) of the subsequence to insert. + * + * @throws IndexOutOfBoundsException or [IllegalArgumentException] when [startIndex] or [endIndex] is out of range of the [value] character sequence indices or when `startIndex > endIndex`. + * @throws IndexOutOfBoundsException if [index] is less than zero or greater than the length of this string builder. + */ + @SinceKotlin("1.4") + @WasExperimental(ExperimentalStdlibApi::class) + fun insertRange(index: Int, value: CharSequence, startIndex: Int, endIndex: Int): StringBuilder { + checkBoundsIndexes(startIndex, endIndex, value.length) + checkInsertIndex(index) + val extraLength = endIndex - startIndex + ensureExtraCapacity(extraLength) + + array.copyInto(array, startIndex = index, endIndex = _length, destinationOffset = index + extraLength) + var from = startIndex + var to = index + while (from < endIndex) { + array[to++] = value[from++] + } + + _length += extraLength + return this + } + + /** + * Inserts characters in a subarray of the specified character array [value] into this string builder at the specified [index] and returns this instance. + * + * The inserted characters go in same order as in the [value] array, starting at [index]. + * + * @param index the position in this string builder to insert at. + * @param value the array from which characters are inserted. + * @param startIndex the beginning (inclusive) of the subarray to insert. + * @param endIndex the end (exclusive) of the subarray to insert. + * + * @throws IndexOutOfBoundsException or [IllegalArgumentException] when [startIndex] or [endIndex] is out of range of the [value] array indices or when `startIndex > endIndex`. + * @throws IndexOutOfBoundsException if [index] is less than zero or greater than the length of this string builder. + */ + @SinceKotlin("1.4") + @WasExperimental(ExperimentalStdlibApi::class) + fun insertRange(index: Int, value: CharArray, startIndex: Int, endIndex: Int): StringBuilder { + checkInsertIndex(index) + checkBoundsIndexes(startIndex, endIndex, value.size) + + val extraLength = endIndex - startIndex + array.copyInto(array, startIndex = index, endIndex = _length, destinationOffset = index + extraLength) + value.copyInto(array, startIndex = startIndex, endIndex = endIndex, destinationOffset = index) + + _length += extraLength + return this + } + + // ---------------------------- private ---------------------------- + + private fun ensureExtraCapacity(n: Int) { + ensureCapacity(_length + n) + } + + private fun checkIndex(index: Int) { + if (index < 0 || index >= _length) throw IndexOutOfBoundsException() + } + + private fun checkInsertIndex(index: Int) { + if (index < 0 || index > _length) throw IndexOutOfBoundsException() + } + + private fun checkInsertIndexFrom(index: Int, fromIndex: Int) { + if (index < fromIndex || index > _length) throw IndexOutOfBoundsException() + } + + private fun checkReplaceRange(startIndex: Int, endIndex: Int, length: Int) { + if (startIndex < 0 || startIndex > length) { + throw IndexOutOfBoundsException("startIndex: $startIndex, length: $length") + } + if (startIndex > endIndex) { + throw IllegalArgumentException("startIndex($startIndex) > endIndex($endIndex)") + } + } +} + +/** + * Clears the content of this string builder making it empty. + * + * @sample samples.text.Strings.clearStringBuilder + */ +@SinceKotlin("1.3") +public actual fun StringBuilder.clear(): StringBuilder = apply { setLength(0) } + +/** + * Sets the character at the specified [index] to the specified [value]. + * + * @throws IndexOutOfBoundsException if [index] is out of bounds of this string builder. + */ +@Suppress("EXTENSION_SHADOWED_BY_MEMBER") +@kotlin.internal.InlineOnly +public actual inline operator fun StringBuilder.set(index: Int, value: Char): Unit = this.set(index, value) + +/** + * Replaces characters in the specified range of this string builder with characters in the specified string [value] and returns this instance. + * + * @param startIndex the beginning (inclusive) of the range to replace. + * @param endIndex the end (exclusive) of the range to replace. + * @param value the string to replace with. + * + * @throws IndexOutOfBoundsException or [IllegalArgumentException] if [startIndex] is less than zero, greater than the length of this string builder, or `startIndex > endIndex`. + */ +@SinceKotlin("1.4") +@WasExperimental(ExperimentalStdlibApi::class) +@Suppress("EXTENSION_SHADOWED_BY_MEMBER") +@kotlin.internal.InlineOnly +public actual inline fun StringBuilder.setRange(startIndex: Int, endIndex: Int, value: String): StringBuilder = + this.setRange(startIndex, endIndex, value) + +/** + * Removes the character at the specified [index] from this string builder and returns this instance. + * + * If the `Char` at the specified [index] is part of a supplementary code point, this method does not remove the entire supplementary character. + * + * @param index the index of `Char` to remove. + * + * @throws IndexOutOfBoundsException if [index] is out of bounds of this string builder. + */ +@SinceKotlin("1.4") +@WasExperimental(ExperimentalStdlibApi::class) +@Suppress("EXTENSION_SHADOWED_BY_MEMBER") +@kotlin.internal.InlineOnly +public actual inline fun StringBuilder.deleteAt(index: Int): StringBuilder = this.deleteAt(index) + +/** + * Removes characters in the specified range from this string builder and returns this instance. + * + * @param startIndex the beginning (inclusive) of the range to remove. + * @param endIndex the end (exclusive) of the range to remove. + * + * @throws IndexOutOfBoundsException or [IllegalArgumentException] when [startIndex] or [endIndex] is out of range of this string builder indices or when `startIndex > endIndex`. + */ +@SinceKotlin("1.4") +@WasExperimental(ExperimentalStdlibApi::class) +@Suppress("EXTENSION_SHADOWED_BY_MEMBER") +@kotlin.internal.InlineOnly +public actual inline fun StringBuilder.deleteRange(startIndex: Int, endIndex: Int): StringBuilder = this.deleteRange(startIndex, endIndex) + +/** + * Copies characters from this string builder into the [destination] character array. + * + * @param destination the array to copy to. + * @param destinationOffset the position in the array to copy to, 0 by default. + * @param startIndex the beginning (inclusive) of the range to copy, 0 by default. + * @param endIndex the end (exclusive) of the range to copy, length of this string builder by default. + * + * @throws IndexOutOfBoundsException or [IllegalArgumentException] when [startIndex] or [endIndex] is out of range of this string builder indices or when `startIndex > endIndex`. + * @throws IndexOutOfBoundsException when the subrange doesn't fit into the [destination] array starting at the specified [destinationOffset], + * or when that index is out of the [destination] array indices range. + */ +@SinceKotlin("1.4") +@WasExperimental(ExperimentalStdlibApi::class) +@Suppress("EXTENSION_SHADOWED_BY_MEMBER", "ACTUAL_FUNCTION_WITH_DEFAULT_ARGUMENTS") +@kotlin.internal.InlineOnly +public actual inline fun StringBuilder.toCharArray(destination: CharArray, destinationOffset: Int = 0, startIndex: Int = 0, endIndex: Int = this.length) = + this.toCharArray(destination, destinationOffset, startIndex, endIndex) + +/** + * Appends characters in a subarray of the specified character array [value] to this string builder and returns this instance. + * + * Characters are appended in order, starting at specified [startIndex]. + * + * @param value the array from which characters are appended. + * @param startIndex the beginning (inclusive) of the subarray to append. + * @param endIndex the end (exclusive) of the subarray to append. + * + * @throws IndexOutOfBoundsException or [IllegalArgumentException] when [startIndex] or [endIndex] is out of range of the [value] array indices or when `startIndex > endIndex`. + */ +@SinceKotlin("1.4") +@WasExperimental(ExperimentalStdlibApi::class) +@Suppress("EXTENSION_SHADOWED_BY_MEMBER") +@kotlin.internal.InlineOnly +public actual inline fun StringBuilder.appendRange(value: CharArray, startIndex: Int, endIndex: Int): StringBuilder = + this.appendRange(value, startIndex, endIndex) + +/** + * Appends a subsequence of the specified character sequence [value] to this string builder and returns this instance. + * + * @param value the character sequence from which a subsequence is appended. + * @param startIndex the beginning (inclusive) of the subsequence to append. + * @param endIndex the end (exclusive) of the subsequence to append. + * + * @throws IndexOutOfBoundsException or [IllegalArgumentException] when [startIndex] or [endIndex] is out of range of the [value] character sequence indices or when `startIndex > endIndex`. + */ +@SinceKotlin("1.4") +@WasExperimental(ExperimentalStdlibApi::class) +@Suppress("EXTENSION_SHADOWED_BY_MEMBER") +@kotlin.internal.InlineOnly +public actual inline fun StringBuilder.appendRange(value: CharSequence, startIndex: Int, endIndex: Int): StringBuilder = + this.appendRange(value, startIndex, endIndex) + +/** + * Inserts characters in a subarray of the specified character array [value] into this string builder at the specified [index] and returns this instance. + * + * The inserted characters go in same order as in the [value] array, starting at [index]. + * + * @param index the position in this string builder to insert at. + * @param value the array from which characters are inserted. + * @param startIndex the beginning (inclusive) of the subarray to insert. + * @param endIndex the end (exclusive) of the subarray to insert. + * + * @throws IndexOutOfBoundsException or [IllegalArgumentException] when [startIndex] or [endIndex] is out of range of the [value] array indices or when `startIndex > endIndex`. + * @throws IndexOutOfBoundsException if [index] is less than zero or greater than the length of this string builder. + */ +@SinceKotlin("1.4") +@WasExperimental(ExperimentalStdlibApi::class) +@Suppress("EXTENSION_SHADOWED_BY_MEMBER") +@kotlin.internal.InlineOnly +public actual inline fun StringBuilder.insertRange(index: Int, value: CharArray, startIndex: Int, endIndex: Int): StringBuilder = + this.insertRange(index, value, startIndex, endIndex) + +/** + * Inserts characters in a subsequence of the specified character sequence [value] into this string builder at the specified [index] and returns this instance. + * + * The inserted characters go in the same order as in the [value] character sequence, starting at [index]. + * + * @param index the position in this string builder to insert at. + * @param value the character sequence from which a subsequence is inserted. + * @param startIndex the beginning (inclusive) of the subsequence to insert. + * @param endIndex the end (exclusive) of the subsequence to insert. + * + * @throws IndexOutOfBoundsException or [IllegalArgumentException] when [startIndex] or [endIndex] is out of range of the [value] character sequence indices or when `startIndex > endIndex`. + * @throws IndexOutOfBoundsException if [index] is less than zero or greater than the length of this string builder. + */ +@SinceKotlin("1.4") +@WasExperimental(ExperimentalStdlibApi::class) +@Suppress("EXTENSION_SHADOWED_BY_MEMBER") +@kotlin.internal.InlineOnly +public actual inline fun StringBuilder.insertRange(index: Int, value: CharSequence, startIndex: Int, endIndex: Int): StringBuilder = + this.insertRange(index, value, startIndex, endIndex) + +// Method parameters renamings +@Suppress("EXTENSION_SHADOWED_BY_MEMBER") +@Deprecated("Use append(value: Boolean) instead", ReplaceWith("append(value = it)"), DeprecationLevel.WARNING) +@kotlin.internal.InlineOnly +public inline fun StringBuilder.append(it: Boolean): StringBuilder = this.append(value = it) + +@Suppress("EXTENSION_SHADOWED_BY_MEMBER") +@Deprecated("Use append(value: Byte) instead", ReplaceWith("append(value = it)"), DeprecationLevel.WARNING) +@kotlin.internal.InlineOnly +public inline fun StringBuilder.append(it: Byte): StringBuilder = this.append(value = it) + +@Suppress("EXTENSION_SHADOWED_BY_MEMBER") +@Deprecated("Use append(value: Short) instead", ReplaceWith("append(value = it)"), DeprecationLevel.WARNING) +@kotlin.internal.InlineOnly +public inline fun StringBuilder.append(it: Short): StringBuilder = this.append(value = it) + +@Suppress("EXTENSION_SHADOWED_BY_MEMBER") +@Deprecated("Use append(value: Int) instead", ReplaceWith("append(value = it)"), DeprecationLevel.WARNING) +@kotlin.internal.InlineOnly +public inline fun StringBuilder.append(it: Int): StringBuilder = this.append(value = it) + +@Suppress("EXTENSION_SHADOWED_BY_MEMBER") +@Deprecated("Use append(value: Long) instead", ReplaceWith("append(value = it)"), DeprecationLevel.WARNING) +@kotlin.internal.InlineOnly +public inline fun StringBuilder.append(it: Long): StringBuilder = this.append(value = it) + +@Suppress("EXTENSION_SHADOWED_BY_MEMBER") +@Deprecated("Use append(value: Float) instead", ReplaceWith("append(value = it)"), DeprecationLevel.WARNING) +@kotlin.internal.InlineOnly +public inline fun StringBuilder.append(it: Float): StringBuilder = this.append(value = it) + +@Suppress("EXTENSION_SHADOWED_BY_MEMBER") +@Deprecated("Use append(value: Double) instead", ReplaceWith("append(value = it)"), DeprecationLevel.WARNING) +@kotlin.internal.InlineOnly +public inline fun StringBuilder.append(it: Double): StringBuilder = this.append(value = it) + +@Suppress("EXTENSION_SHADOWED_BY_MEMBER") +@Deprecated("Use append(value: String) instead", ReplaceWith("append(value = it)"), DeprecationLevel.WARNING) +@kotlin.internal.InlineOnly +public inline fun StringBuilder.append(it: String): StringBuilder = this.append(value = it) + +@Suppress("EXTENSION_SHADOWED_BY_MEMBER") +@Deprecated("Use append(value: CharArray) instead", ReplaceWith("append(value = it)"), DeprecationLevel.WARNING) +@kotlin.internal.InlineOnly +public inline fun StringBuilder.append(it: CharArray): StringBuilder = this.append(value = it) + +@Suppress("EXTENSION_SHADOWED_BY_MEMBER") +@Deprecated("Use ensureCapacity(minimumCapacity: Int) instead", ReplaceWith("ensureCapacity(minimumCapacity = capacity)"), DeprecationLevel.WARNING) +@kotlin.internal.InlineOnly +public inline fun StringBuilder.ensureCapacity(capacity: Int): Unit = this.ensureCapacity(minimumCapacity = capacity) + +@Suppress("EXTENSION_SHADOWED_BY_MEMBER") +@Deprecated("Use insert(index: Int, value: Char) instead", ReplaceWith("insert(index, value = c)"), DeprecationLevel.WARNING) +@kotlin.internal.InlineOnly +public inline fun StringBuilder.insert(index: Int, c: Char): StringBuilder = this.insert(index, value = c) + +@Suppress("EXTENSION_SHADOWED_BY_MEMBER") +@Deprecated("Use insert(index: Int, value: CharArray) instead", ReplaceWith("insert(index, value = chars)"), DeprecationLevel.WARNING) +@kotlin.internal.InlineOnly +public inline fun StringBuilder.insert(index: Int, chars: CharArray): StringBuilder = this.insert(index, value = chars) + +@Suppress("EXTENSION_SHADOWED_BY_MEMBER") +@Deprecated("Use insert(index: Int, value: CharSequence?) instead", ReplaceWith("insert(index, value = csq)"), DeprecationLevel.WARNING) +@kotlin.internal.InlineOnly +public inline fun StringBuilder.insert(index: Int, csq: CharSequence?): StringBuilder = this.insert(index, value = csq) + +@Suppress("EXTENSION_SHADOWED_BY_MEMBER") +@Deprecated("Use insert(index: Int, value: String) instead", ReplaceWith("insert(index, value = string)"), DeprecationLevel.WARNING) +@kotlin.internal.InlineOnly +public inline fun StringBuilder.insert(index: Int, string: String): StringBuilder = this.insert(index, value = string) + +@Suppress("EXTENSION_SHADOWED_BY_MEMBER") +@Deprecated("Use setLength(newLength: Int) instead", ReplaceWith("setLength(newLength = l)"), DeprecationLevel.WARNING) +@kotlin.internal.InlineOnly +public inline fun StringBuilder.setLength(l: Int) = this.setLength(newLength = l) + +// Method renamings +/** + * Inserts characters in a subsequence of the specified character sequence [csq] into this string builder at the specified [index] and returns this instance. + * + * The inserted characters go in the same order as in the [csq] character sequence, starting at [index]. + * + * @param index the position in this string builder to insert at. + * @param csq the character sequence from which a subsequence is inserted. If [csq] is `null`, + * then characters will be inserted as if [csq] contained the four characters `"null"`. + * @param start the beginning (inclusive) of the subsequence to insert. + * @param end the end (exclusive) of the subsequence to insert. + * + * @throws IndexOutOfBoundsException or [IllegalArgumentException] when [start] or [end] is out of range of the [csq] character sequence indices or when `start > end`. + * @throws IndexOutOfBoundsException if [index] is less than zero or greater than the length of this string builder. + */ +@Deprecated( + "Use insertRange(index: Int, csq: CharSequence, start: Int, end: Int) instead", + ReplaceWith("insertRange(index, csq ?: \"null\", start, end)"), + DeprecationLevel.WARNING +) +@kotlin.internal.InlineOnly +public inline fun StringBuilder.insert(index: Int, csq: CharSequence?, start: Int, end: Int): StringBuilder = + this.insertRange(index, csq ?: "null", start, end) + +@Deprecated("Use set(index: Int, value: Char) instead", ReplaceWith("set(index, value)"), DeprecationLevel.WARNING) +@kotlin.internal.InlineOnly +public inline fun StringBuilder.setCharAt(index: Int, value: Char) = this.set(index, value) + +/** + * Removes the character at the specified [index] from this string builder and returns this instance. + * + * If the `Char` at the specified [index] is part of a supplementary code point, this method does not remove the entire supplementary character. + * + * @param index the index of `Char` to remove. + * + * @throws IndexOutOfBoundsException if [index] is out of bounds of this string builder. + */ +@Deprecated("Use deleteAt(index: Int) instead", ReplaceWith("deleteAt(index)"), DeprecationLevel.WARNING) +@kotlin.internal.InlineOnly +public inline fun StringBuilder.deleteCharAt(index: Int) = this.deleteAt(index) diff --git a/kotlin-native/runtime/src/main/kotlin/kotlin/text/StringBuilderNative.kt b/kotlin-native/runtime/src/main/kotlin/kotlin/text/StringBuilderNative.kt new file mode 100644 index 00000000000..f73b1c2f7f9 --- /dev/null +++ b/kotlin-native/runtime/src/main/kotlin/kotlin/text/StringBuilderNative.kt @@ -0,0 +1,67 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +package kotlin.text + +/** Appends [value] to this [StringBuilder], followed by a line feed character (`\n`). */ +@SinceKotlin("1.4") +@kotlin.internal.InlineOnly +public inline fun StringBuilder.appendLine(value: Byte): StringBuilder = append(value).appendLine() + +/** Appends [value] to this [StringBuilder], followed by a line feed character (`\n`). */ +@SinceKotlin("1.4") +@kotlin.internal.InlineOnly +public inline fun StringBuilder.appendLine(value: Short): StringBuilder = append(value).appendLine() + +/** Appends [value] to this [StringBuilder], followed by a line feed character (`\n`). */ +@SinceKotlin("1.4") +@kotlin.internal.InlineOnly +public inline fun StringBuilder.appendLine(value: Int): StringBuilder = append(value).appendLine() + +/** Appends [value] to this [StringBuilder], followed by a line feed character (`\n`). */ +@SinceKotlin("1.4") +@kotlin.internal.InlineOnly +public inline fun StringBuilder.appendLine(value: Long): StringBuilder = append(value).appendLine() + +/** Appends [value] to this [StringBuilder], followed by a line feed character (`\n`). */ +@SinceKotlin("1.4") +@kotlin.internal.InlineOnly +public inline fun StringBuilder.appendLine(value: Float): StringBuilder = append(value).appendLine() + +/** Appends [value] to this [StringBuilder], followed by a line feed character (`\n`). */ +@SinceKotlin("1.4") +@kotlin.internal.InlineOnly +public inline fun StringBuilder.appendLine(value: Double): StringBuilder = append(value).appendLine() + + +@Deprecated("Use appendLine instead", ReplaceWith("appendLine(it)"), level = DeprecationLevel.WARNING) +public fun StringBuilder.appendln(it: String): StringBuilder = appendLine(it) + +@Deprecated("Use appendLine instead", ReplaceWith("appendLine(it)"), level = DeprecationLevel.WARNING) +public fun StringBuilder.appendln(it: Boolean): StringBuilder = appendLine(it) + +@Deprecated("Use appendLine instead", ReplaceWith("appendLine(it)"), level = DeprecationLevel.WARNING) +public fun StringBuilder.appendln(it: Byte): StringBuilder = appendLine(it) + +@Deprecated("Use appendLine instead", ReplaceWith("appendLine(it)"), level = DeprecationLevel.WARNING) +public fun StringBuilder.appendln(it: Short): StringBuilder = appendLine(it) + +@Deprecated("Use appendLine instead", ReplaceWith("appendLine(it)"), level = DeprecationLevel.WARNING) +public fun StringBuilder.appendln(it: Int): StringBuilder = appendLine(it) + +@Deprecated("Use appendLine instead", ReplaceWith("appendLine(it)"), level = DeprecationLevel.WARNING) +public fun StringBuilder.appendln(it: Long): StringBuilder = appendLine(it) + +@Deprecated("Use appendLine instead", ReplaceWith("appendLine(it)"), level = DeprecationLevel.WARNING) +public fun StringBuilder.appendln(it: Float): StringBuilder = appendLine(it) + +@Deprecated("Use appendLine instead", ReplaceWith("appendLine(it)"), level = DeprecationLevel.WARNING) +public fun StringBuilder.appendln(it: Double): StringBuilder = appendLine(it) + +@Deprecated("Use appendLine instead", ReplaceWith("appendLine(it)"), level = DeprecationLevel.WARNING) +public fun StringBuilder.appendln(it: Any?): StringBuilder = appendLine(it) + +@Deprecated("Use appendLine instead", ReplaceWith("appendLine()"), level = DeprecationLevel.WARNING) +public fun StringBuilder.appendln(): StringBuilder = appendLine() \ No newline at end of file diff --git a/kotlin-native/runtime/src/main/kotlin/kotlin/text/StringNumberConversions.kt b/kotlin-native/runtime/src/main/kotlin/kotlin/text/StringNumberConversions.kt new file mode 100644 index 00000000000..993092b5133 --- /dev/null +++ b/kotlin-native/runtime/src/main/kotlin/kotlin/text/StringNumberConversions.kt @@ -0,0 +1,172 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +package kotlin.text + +import kotlin.native.internal.FloatingPointParser + +/** + * Returns a string representation of this [Byte] value in the specified [radix]. + * + * @throws IllegalArgumentException when [radix] is not a valid radix for number to string conversion. + */ +@SinceKotlin("1.1") +@kotlin.internal.InlineOnly +public actual inline fun Byte.toString(radix: Int): String = this.toInt().toString(checkRadix(radix)) + +/** + * Returns a string representation of this [Short] value in the specified [radix]. + * + * @throws IllegalArgumentException when [radix] is not a valid radix for number to string conversion. + */ +@SinceKotlin("1.1") +@kotlin.internal.InlineOnly +public actual inline fun Short.toString(radix: Int): String = this.toInt().toString(checkRadix(radix)) + +@SymbolName("Kotlin_Int_toStringRadix") +@PublishedApi +external internal fun intToString(value: Int, radix: Int): String + +/** + * Returns a string representation of this [Int] value in the specified [radix]. + * + * @throws IllegalArgumentException when [radix] is not a valid radix for number to string conversion. + */ +@SinceKotlin("1.1") +@kotlin.internal.InlineOnly +public actual inline fun Int.toString(radix: Int): String = intToString(this, checkRadix(radix)) + +@SymbolName("Kotlin_Long_toStringRadix") +@PublishedApi +external internal fun longToString(value: Long, radix: Int): String + +/** + * Returns a string representation of this [Long] value in the specified [radix]. + * + * @throws IllegalArgumentException when [radix] is not a valid radix for number to string conversion. + */ +@SinceKotlin("1.1") +@kotlin.internal.InlineOnly +public actual inline fun Long.toString(radix: Int): String = longToString(this, checkRadix(radix)) + +/** + * Returns `true` if the content of this string is equal to the word "true", ignoring case, and `false` otherwise. + */ +@Deprecated("Use Kotlin compiler 1.4 to avoid deprecation warning.") +@DeprecatedSinceKotlin(hiddenSince = "1.4") +@kotlin.internal.InlineOnly +public actual inline fun String.toBoolean(): Boolean = this.toBoolean() + +/** + * Returns `true` if this string is not `null` and its content is equal to the word "true", ignoring case, and `false` otherwise. + */ +@SinceKotlin("1.4") +@kotlin.internal.InlineOnly +public actual inline fun String?.toBoolean(): Boolean = this.equals("true", ignoreCase = true) + +/** + * Parses the string as a signed [Byte] number and returns the result. + * @throws NumberFormatException if the string is not a valid representation of a number. + */ +@kotlin.internal.InlineOnly +public actual inline fun String.toByte(): Byte = toByteOrNull() ?: throw NumberFormatException() + +/** + * Parses the string as a signed [Byte] number and returns the result. + * @throws NumberFormatException if the string is not a valid representation of a number. + * @throws IllegalArgumentException when [radix] is not a valid radix for string to number conversion. + */ +@SinceKotlin("1.1") +@kotlin.internal.InlineOnly +public actual inline fun String.toByte(radix: Int): Byte = toByteOrNull(radix) ?: throw NumberFormatException() + +/** + * Parses the string as a [Short] number and returns the result. + * @throws NumberFormatException if the string is not a valid representation of a number. + */ +@kotlin.internal.InlineOnly +public actual inline fun String.toShort(): Short = toShortOrNull() ?: throw NumberFormatException() + +/** + * Parses the string as a [Short] number and returns the result. + * @throws NumberFormatException if the string is not a valid representation of a number. + * @throws IllegalArgumentException when [radix] is not a valid radix for string to number conversion. + */ +@SinceKotlin("1.1") +@kotlin.internal.InlineOnly +public actual inline fun String.toShort(radix: Int): Short = toShortOrNull(radix) ?: throw NumberFormatException() + +/** + * Parses the string as an [Int] number and returns the result. + * @throws NumberFormatException if the string is not a valid representation of a number. + */ +@kotlin.internal.InlineOnly +public actual inline fun String.toInt(): Int = toIntOrNull() ?: throw NumberFormatException() + +/** + * Parses the string as an [Int] number and returns the result. + * @throws NumberFormatException if the string is not a valid representation of a number. + * @throws IllegalArgumentException when [radix] is not a valid radix for string to number conversion. + */ +@SinceKotlin("1.1") +@kotlin.internal.InlineOnly +public actual inline fun String.toInt(radix: Int): Int = toIntOrNull(radix) ?: throw NumberFormatException() + +/** + * Parses the string as a [Long] number and returns the result. + * @throws NumberFormatException if the string is not a valid representation of a number. + */ +@kotlin.internal.InlineOnly +public actual inline fun String.toLong(): Long = toLongOrNull() ?: throw NumberFormatException() + +/** + * Parses the string as a [Long] number and returns the result. + * @throws NumberFormatException if the string is not a valid representation of a number. + * @throws IllegalArgumentException when [radix] is not a valid radix for string to number conversion. + */ +@SinceKotlin("1.1") +@kotlin.internal.InlineOnly +public actual inline fun String.toLong(radix: Int): Long = toLongOrNull(radix) ?: throw NumberFormatException() + +/** + * Parses the string as a [Float] number and returns the result. + * @throws NumberFormatException if the string is not a valid representation of a number. + */ +@kotlin.internal.InlineOnly +public actual inline fun String.toFloat(): Float = FloatingPointParser.parseFloat(this) + + +/** + * Parses the string as a [Double] number and returns the result. + * @throws NumberFormatException if the string is not a valid representation of a number. + */ +@kotlin.internal.InlineOnly +public actual inline fun String.toDouble(): Double = FloatingPointParser.parseDouble(this) + +/** + * Parses the string as a [Float] number and returns the result + * or `null` if the string is not a valid representation of a number. + */ +@SinceKotlin("1.1") +public actual fun String.toFloatOrNull(): Float? { + try { + return toFloat() + } catch (e: NumberFormatException) { + return null + } +} + +/** + * Parses the string as a [Double] number and returns the result + * or `null` if the string is not a valid representation of a number. + */ +@SinceKotlin("1.1") +public actual fun String.toDoubleOrNull(): Double? { + try { + return toDouble() + } catch (e: NumberFormatException) { + return null + } +} diff --git a/kotlin-native/runtime/src/main/kotlin/kotlin/text/Strings.kt b/kotlin-native/runtime/src/main/kotlin/kotlin/text/Strings.kt new file mode 100644 index 00000000000..744d5e35326 --- /dev/null +++ b/kotlin-native/runtime/src/main/kotlin/kotlin/text/Strings.kt @@ -0,0 +1,350 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +package kotlin.text + +import kotlin.native.concurrent.SharedImmutable + +/** + * Returns the index within this string of the first occurrence of the specified character, starting from the specified offset. + */ +@SymbolName("Kotlin_String_indexOfChar") +internal actual external fun String.nativeIndexOf(ch: Char, fromIndex: Int): Int + +/** + * Returns the index within this string of the first occurrence of the specified substring, starting from the specified offset. + */ +@SymbolName("Kotlin_String_indexOfString") +internal actual external fun String.nativeIndexOf(str: String, fromIndex: Int): Int + +/** + * Returns the index within this string of the last occurrence of the specified character. + */ +@SymbolName("Kotlin_String_lastIndexOfChar") +internal actual external fun String.nativeLastIndexOf(ch: Char, fromIndex: Int): Int + +/** + * Returns the index within this string of the last occurrence of the specified character, starting from the specified offset. + */ +@SymbolName("Kotlin_String_lastIndexOfString") +internal actual external fun String.nativeLastIndexOf(str: String, fromIndex: Int): Int + +/** + * Returns `true` if this string is equal to [other], optionally ignoring character case. + * + * @param ignoreCase `true` to ignore character case when comparing strings. By default `false`. + */ +public actual fun String?.equals(other: String?, ignoreCase: Boolean): Boolean { + if (this === null) + return other === null + if (other === null) + return false + return if (!ignoreCase) + this.equals(other) + else + stringEqualsIgnoreCase(this, other) +} + +@SymbolName("Kotlin_String_equalsIgnoreCase") +internal external fun stringEqualsIgnoreCase(thiz: String, other: String): Boolean + +/** + * Returns a new string with all occurrences of [oldChar] replaced with [newChar]. + */ +@SymbolName("Kotlin_String_replace") +public actual external fun String.replace( + oldChar: Char, newChar: Char, ignoreCase: Boolean): String + +/** + * Returns a new string obtained by replacing all occurrences of the [oldValue] substring in this string + * with the specified [newValue] string. + */ +public actual fun String.replace(oldValue: String, newValue: String, ignoreCase: Boolean): String = + splitToSequence(oldValue, ignoreCase = ignoreCase).joinToString(separator = newValue) + +/** + * Returns a new string with the first occurrence of [oldChar] replaced with [newChar]. + */ +public actual fun String.replaceFirst(oldChar: Char, newChar: Char, ignoreCase: Boolean): String { + val index = indexOf(oldChar, ignoreCase = ignoreCase) + return if (index < 0) this else this.replaceRange(index, index + 1, newChar.toString()) +} + +/** + * Returns a new string obtained by replacing the first occurrence of the [oldValue] substring in this string + * with the specified [newValue] string. + */ +public actual fun String.replaceFirst(oldValue: String, newValue: String, ignoreCase: Boolean): String { + val index = indexOf(oldValue, ignoreCase = ignoreCase) + return if (index < 0) this else this.replaceRange(index, index + oldValue.length, newValue) +} + +/** + * Returns `true` if this string is empty or consists solely of whitespace characters. + * + * @sample samples.text.Strings.stringIsBlank + */ +public actual fun CharSequence.isBlank(): Boolean = length == 0 || indices.all { this[it].isWhitespace() } + +/** + * Returns the substring of this string starting at the [startIndex] and ending right before the [endIndex]. + * + * @param startIndex the start index (inclusive). + * @param endIndex the end index (exclusive). + */ +@kotlin.internal.InlineOnly +public actual inline fun String.substring(startIndex: Int, endIndex: Int): String = + subSequence(startIndex, endIndex) as String + +/** + * Returns a substring of this string that starts at the specified [startIndex] and continues to the end of the string. + */ +@kotlin.internal.InlineOnly +public actual inline fun String.substring(startIndex: Int): String = + subSequence(startIndex, this.length) as String + +/** + * Returns `true` if this string starts with the specified prefix. + */ +public actual fun String.startsWith(prefix: String, ignoreCase: Boolean): Boolean = + regionMatches(0, prefix, 0, prefix.length, ignoreCase) + +/** + * Returns `true` if a substring of this string starting at the specified offset [startIndex] starts with the specified prefix. + */ +public actual fun String.startsWith(prefix: String, startIndex: Int, ignoreCase: Boolean): Boolean = + regionMatches(startIndex, prefix, 0, prefix.length, ignoreCase) + +/** + * Returns `true` if this string ends with the specified suffix. + */ +public actual fun String.endsWith(suffix: String, ignoreCase: Boolean): Boolean = + regionMatches(length - suffix.length, suffix, 0, suffix.length, ignoreCase) + +/** + * Returns `true` if the specified range in this char sequence is equal to the specified range in another char sequence. + * @param thisOffset the start offset in this char sequence of the substring to compare. + * @param other the string against a substring of which the comparison is performed. + * @param otherOffset the start offset in the other char sequence of the substring to compare. + * @param length the length of the substring to compare. + */ +public actual fun CharSequence.regionMatches( + thisOffset: Int, other: CharSequence, otherOffset: Int, length: Int, + ignoreCase: Boolean): Boolean { + return if (this is String && other is String) { + this.regionMatches(thisOffset, other, otherOffset, length, ignoreCase) + } else { + regionMatchesImpl(thisOffset, other, otherOffset, length, ignoreCase) + } +} + +/** + * Returns `true` if the specified range in this string is equal to the specified range in another string. + * @param thisOffset the start offset in this string of the substring to compare. + * @param other the string against a substring of which the comparison is performed. + * @param otherOffset the start offset in the other string of the substring to compare. + * @param length the length of the substring to compare. + */ +@SymbolName("Kotlin_String_regionMatches") +public external fun String.regionMatches( + thisOffset: Int, other: String, otherOffset: Int, length: Int, + ignoreCase: Boolean = false): Boolean + +/** + * Returns a copy of this string converted to upper case using the rules of the default locale. + */ +@SymbolName("Kotlin_String_toUpperCase") +public actual external fun String.toUpperCase(): String + +/** + * Returns a copy of this string converted to lower case using the rules of the default locale. + */ +@SymbolName("Kotlin_String_toLowerCase") +@Suppress("NOTHING_TO_INLINE") +public actual external fun String.toLowerCase(): String + +/** + * Returns a [CharArray] containing characters of this string. + */ +public actual fun String.toCharArray(): CharArray = toCharArray(this, 0, length) + +@SymbolName("Kotlin_String_toCharArray") +private external fun toCharArray(string: String, start: Int, size: Int): CharArray + +/** + * Returns a copy of this string having its first letter titlecased using the rules of the default locale, + * or the original string if it's empty or already starts with a title case letter. + * + * The title case of a character is usually the same as its upper case with several exceptions. + * The particular list of characters with the special title case form depends on the underlying platform. + * + * @sample samples.text.Strings.capitalize + */ +public actual fun String.capitalize(): String { + return if (isNotEmpty() && this[0].isLowerCase()) substring(0, 1).toUpperCase() + substring(1) else this +} + +/** + * Returns a copy of this string having its first letter lowercased using the rules of the default locale, + * or the original string if it's empty or already starts with a lower case letter. + * + * @sample samples.text.Strings.decapitalize + */ +public actual fun String.decapitalize(): String { + return if (isNotEmpty() && !this[0].isLowerCase()) substring(0, 1).toLowerCase() + substring(1) else this +} + +/** + * Returns a string containing this char sequence repeated [n] times. + * @throws [IllegalArgumentException] when n < 0. + * @sample samples.text.Strings.repeat + */ +public actual fun CharSequence.repeat(n: Int): String { + require(n >= 0) { "Count 'n' must be non-negative, but was $n." } + + return when (n) { + 0 -> "" + 1 -> this.toString() + else -> { + when (length) { + 0 -> "" + 1 -> this[0].let { char -> CharArray(n) { char }.concatToString() } + else -> { + val sb = StringBuilder(n * length) + for (i in 1..n) { + sb.append(this) + } + sb.toString() + } + } + } + } +} + +/** + * Converts the characters in the specified array to a string. + */ +@Deprecated("Use CharArray.concatToString() instead", ReplaceWith("chars.concatToString()")) +public actual fun String(chars: CharArray): String = chars.concatToString() + +/** + * Converts the characters from a portion of the specified array to a string. + * + * @throws IndexOutOfBoundsException if either [offset] or [length] are less than zero + * or `offset + length` is out of [chars] array bounds. + */ +@Deprecated("Use CharArray.concatToString(startIndex, endIndex) instead", ReplaceWith("chars.concatToString(offset, offset + length)")) +public actual fun String(chars: CharArray, offset: Int, length: Int): String { + if (offset < 0 || length < 0 || offset + length > chars.size) + throw ArrayIndexOutOfBoundsException() + + return unsafeStringFromCharArray(chars, offset, length) +} + +/** + * Concatenates characters in this [CharArray] into a String. + */ +@SinceKotlin("1.3") +public actual fun CharArray.concatToString(): String = unsafeStringFromCharArray(this, 0, size) + +/** + * Concatenates characters in this [CharArray] or its subrange into a String. + * + * @param startIndex the beginning (inclusive) of the subrange of characters, 0 by default. + * @param endIndex the end (exclusive) of the subrange of characters, size of this array by default. + * + * @throws IndexOutOfBoundsException if [startIndex] is less than zero or [endIndex] is greater than the size of this array. + * @throws IllegalArgumentException if [startIndex] is greater than [endIndex]. + */ +@SinceKotlin("1.3") +public actual fun CharArray.concatToString(startIndex: Int, endIndex: Int): String { + checkBoundsIndexes(startIndex, endIndex, size) + return unsafeStringFromCharArray(this, startIndex, endIndex - startIndex) +} + +/** + * Returns a [CharArray] containing characters of this string or its substring. + * + * @param startIndex the beginning (inclusive) of the substring, 0 by default. + * @param endIndex the end (exclusive) of the substring, length of this string by default. + * + * @throws IndexOutOfBoundsException if [startIndex] is less than zero or [endIndex] is greater than the length of this string. + * @throws IllegalArgumentException if [startIndex] is greater than [endIndex]. + */ +@SinceKotlin("1.3") +public actual fun String.toCharArray(startIndex: Int, endIndex: Int): CharArray { + checkBoundsIndexes(startIndex, endIndex, length) + return toCharArray(this, startIndex, endIndex - startIndex) +} + +/** + * Decodes a string from the bytes in UTF-8 encoding in this array. + * + * Malformed byte sequences are replaced by the replacement char `\uFFFD`. + */ +@SinceKotlin("1.3") +public actual fun ByteArray.decodeToString(): String = unsafeStringFromUtf8(0, size) + +/** + * Decodes a string from the bytes in UTF-8 encoding in this array or its subrange. + * + * @param startIndex the beginning (inclusive) of the subrange to decode, 0 by default. + * @param endIndex the end (exclusive) of the subrange to decode, size of this array by default. + * @param throwOnInvalidSequence specifies whether to throw an exception on malformed byte sequence or replace it by the replacement char `\uFFFD`. + * + * @throws IndexOutOfBoundsException if [startIndex] is less than zero or [endIndex] is greater than the size of this array. + * @throws IllegalArgumentException if [startIndex] is greater than [endIndex]. + * @throws CharacterCodingException if the byte array contains malformed UTF-8 byte sequence and [throwOnInvalidSequence] is true. + */ +@SinceKotlin("1.3") +public actual fun ByteArray.decodeToString(startIndex: Int, endIndex: Int, throwOnInvalidSequence: Boolean): String { + checkBoundsIndexes(startIndex, endIndex, size) + return if (throwOnInvalidSequence) + unsafeStringFromUtf8OrThrow(startIndex, endIndex - startIndex) + else + unsafeStringFromUtf8(startIndex, endIndex - startIndex) +} + +/** + * Encodes this string to an array of bytes in UTF-8 encoding. + * + * Any malformed char sequence is replaced by the replacement byte sequence. + */ +@SinceKotlin("1.3") +public actual fun String.encodeToByteArray(): ByteArray = unsafeStringToUtf8(0, length) + +/** + * Encodes this string or its substring to an array of bytes in UTF-8 encoding. + * + * @param startIndex the beginning (inclusive) of the substring to encode, 0 by default. + * @param endIndex the end (exclusive) of the substring to encode, length of this string by default. + * @param throwOnInvalidSequence specifies whether to throw an exception on malformed char sequence or replace. + * + * @throws IndexOutOfBoundsException if [startIndex] is less than zero or [endIndex] is greater than the length of this string. + * @throws IllegalArgumentException if [startIndex] is greater than [endIndex]. + * @throws CharacterCodingException if this string contains malformed char sequence and [throwOnInvalidSequence] is true. + */ +@SinceKotlin("1.3") +public actual fun String.encodeToByteArray(startIndex: Int, endIndex: Int, throwOnInvalidSequence: Boolean): ByteArray { + checkBoundsIndexes(startIndex, endIndex, length) + return if (throwOnInvalidSequence) + unsafeStringToUtf8OrThrow(startIndex, endIndex - startIndex) + else + unsafeStringToUtf8(startIndex, endIndex - startIndex) +} + +@SymbolName("Kotlin_String_compareToIgnoreCase") +internal external fun compareToIgnoreCase(thiz: String, other: String): Int + +public actual fun String.compareTo(other: String, ignoreCase: Boolean): Int { + return if (!ignoreCase) this.compareTo(other) + else compareToIgnoreCase(this, other) +} + +@SharedImmutable +private val STRING_CASE_INSENSITIVE_ORDER = Comparator { a, b -> a.compareTo(b, ignoreCase = true) } + +public actual val String.Companion.CASE_INSENSITIVE_ORDER: Comparator + get() = STRING_CASE_INSENSITIVE_ORDER diff --git a/kotlin-native/runtime/src/main/kotlin/kotlin/text/regex/AbstractCharClass.kt b/kotlin-native/runtime/src/main/kotlin/kotlin/text/regex/AbstractCharClass.kt new file mode 100644 index 00000000000..0b120951773 --- /dev/null +++ b/kotlin-native/runtime/src/main/kotlin/kotlin/text/regex/AbstractCharClass.kt @@ -0,0 +1,584 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package kotlin.text.regex + +import kotlin.collections.associate +import kotlin.native.concurrent.AtomicReference +import kotlin.native.concurrent.freeze + +/** + * Unicode category (i.e. Ll, Lu). + */ +internal open class UnicodeCategory(protected val category: Int) : AbstractCharClass() { + override fun contains(ch: Int): Boolean = alt xor (ch.toChar().category.value == category) +} + +/** + * Unicode category scope (i.e IsL, IsM, ...) + */ +internal class UnicodeCategoryScope(category: Int) : UnicodeCategory(category) { + override fun contains(ch: Int): Boolean { + return alt xor (((category shr ch.toChar().category.value) and 1) != 0) + } +} + +/** + * This class represents character classes, i.e. sets of character either predefined or user defined. + * Note: this class represent a token, not node, so being constructed by lexer. + */ +internal abstract class AbstractCharClass : SpecialToken() { + /** + * Show if the class has alternative meaning: + * if the class contains character 'a' and alt == true then the class will contains all characters except 'a'. + */ + internal var alt: Boolean = false + internal var altSurrogates: Boolean = false + + internal val lowHighSurrogates = BitSet(SURROGATE_CARDINALITY) // Bit set for surrogates? + + /* + * Indicates if this class may contain supplementary Unicode codepoints. + * If this flag is specified it doesn't mean that this class contains supplementary characters but may contain. + */ + var mayContainSupplCodepoints = false + protected set + + /** Returns true if this char class contains character specified. */ + abstract operator fun contains(ch: Int): Boolean + open fun contains(ch: Char): Boolean = contains(ch.toInt()) + + /** + * Returns BitSet representing this character class or `null` + * if this character class does not have character representation; + */ + open internal val bits: BitSet? + get() = null + + fun hasLowHighSurrogates(): Boolean { + return if (altSurrogates) + lowHighSurrogates.nextClearBit(0) != -1 + else + lowHighSurrogates.nextSetBit(0) != -1 + } + + override val type: Type = Type.CHARCLASS + + open val instance: AbstractCharClass + get() = this + + + private val surrogates_ = AtomicReference(null) + fun classWithSurrogates(): AbstractCharClass { + surrogates_.value?.let { + return it + } + val surrogates = lowHighSurrogates + val result = object : AbstractCharClass() { + override fun contains(ch: Int): Boolean { + val index = ch - Char.MIN_SURROGATE.toInt() + + return if (index >= 0 && index < AbstractCharClass.SURROGATE_CARDINALITY) { + this.altSurrogates xor surrogates[index] + } else { + false + } + } + } + result.setNegative(this.altSurrogates) + surrogates_.compareAndSet(null, result.freeze()) + return surrogates_.value!! + } + + + // We cannot cache this class as we've done with surrogates above because + // here is a circular reference between it and AbstractCharClass. + fun classWithoutSurrogates(): AbstractCharClass { + val result = object : AbstractCharClass() { + override fun contains(ch: Int): Boolean { + val index = ch - Char.MIN_SURROGATE.toInt() + + val containslHS = if (index >= 0 && index < AbstractCharClass.SURROGATE_CARDINALITY) + this.altSurrogates xor this@AbstractCharClass.lowHighSurrogates.get(index) + else + false + + return this@AbstractCharClass.contains(ch) && !containslHS + } + } + result.setNegative(isNegative()) + result.mayContainSupplCodepoints = mayContainSupplCodepoints + return result + } + + /** + * Sets this CharClass to negative form, i.e. if they will add some characters and after that set this + * class to negative it will accept all the characters except previously set ones. + * + * Although this method will not alternate all the already set characters, + * just overall meaning of the class. + */ + fun setNegative(value: Boolean): AbstractCharClass { + if (alt xor value) { + alt = !alt + altSurrogates = !altSurrogates + } + if (!mayContainSupplCodepoints) { + mayContainSupplCodepoints = true + } + return this + } + + fun isNegative(): Boolean { + return alt + } + + internal abstract class CachedCharClass { + lateinit private var posValue: AbstractCharClass + + lateinit private var negValue: AbstractCharClass + + // Somewhat ugly init sequence, as computeValue() may depend on fields, initialized in subclass ctor. + protected fun initValues() { + posValue = computeValue() + negValue = computeValue().setNegative(true) + } + + fun getValue(negative: Boolean): AbstractCharClass = if (!negative) posValue else negValue + protected abstract fun computeValue(): AbstractCharClass + } + + internal class CachedDigit : CachedCharClass() { + init { + initValues() + } + override fun computeValue(): AbstractCharClass = CharClass().add('0', '9') + } + + internal class CachedNonDigit : CachedCharClass() { + init { + initValues() + } + override fun computeValue(): AbstractCharClass = + CharClass().add('0', '9').setNegative(true).apply { mayContainSupplCodepoints = true } + } + + internal class CachedSpace : CachedCharClass() { + init { + initValues() + } + /* 9-13 - \t\n\x0B\f\r; 32 - ' ' */ + override fun computeValue(): AbstractCharClass = CharClass().add(9, 13).add(32) + } + + internal class CachedNonSpace : CachedCharClass() { + init { + initValues() + } + override fun computeValue(): AbstractCharClass = + CachedSpace().getValue(negative = true).apply { mayContainSupplCodepoints = true } + } + + internal class CachedWord : CachedCharClass() { + init { + initValues() + } + override fun computeValue(): AbstractCharClass = CharClass().add('a', 'z').add('A', 'Z').add('0', '9').add('_') + } + + internal class CachedNonWord : CachedCharClass() { + init { + initValues() + } + override fun computeValue(): AbstractCharClass = + CachedWord().getValue(negative = true).apply { mayContainSupplCodepoints = true } + } + + internal class CachedLower : CachedCharClass() { + init { + initValues() + } + override fun computeValue(): AbstractCharClass = CharClass().add('a', 'z') + } + + internal class CachedUpper : CachedCharClass() { + init { + initValues() + } + override fun computeValue(): AbstractCharClass = CharClass().add('A', 'Z') + } + + internal class CachedASCII : CachedCharClass() { + init { + initValues() + } + override fun computeValue(): AbstractCharClass = CharClass().add(0x00, 0x7F) + } + + internal class CachedAlpha : CachedCharClass() { + init { + initValues() + } + override fun computeValue(): AbstractCharClass = CharClass().add('a', 'z').add('A', 'Z') + } + + internal class CachedAlnum : CachedCharClass() { + init { + initValues() + } + override fun computeValue(): AbstractCharClass = + (CachedAlpha().getValue(negative = false) as CharClass).add('0', '9') + } + + internal class CachedPunct : CachedCharClass() { + init { + initValues() + } + /* Punctuation !"#$%&'()*+,-./:;<=>?@ [\]^_` {|}~ */ + override fun computeValue(): AbstractCharClass = CharClass().add(0x21, 0x40).add(0x5B, 0x60).add(0x7B, 0x7E) + } + + internal class CachedGraph : CachedCharClass() { + init { + initValues() + } + /* plus punctuation */ + override fun computeValue(): AbstractCharClass = + (CachedAlnum().getValue(negative = false) as CharClass) + .add(0x21, 0x40) + .add(0x5B, 0x60) + .add(0x7B, 0x7E) + } + + internal class CachedPrint : CachedCharClass() { + init { + initValues() + } + override fun computeValue(): AbstractCharClass = + (CachedGraph().getValue(negative = true) as CharClass).add(0x20) + } + + internal class CachedBlank : CachedCharClass() { + init { + initValues() + } + override fun computeValue(): AbstractCharClass = CharClass().add(' ').add('\t') + } + + internal class CachedCntrl : CachedCharClass() { + init { + initValues() + } + override fun computeValue(): AbstractCharClass = CharClass().add(0x00, 0x1F).add(0x7F) + } + + internal class CachedXDigit : CachedCharClass() { + init { + initValues() + } + override fun computeValue(): AbstractCharClass = CharClass().add('0', '9').add('a', 'f').add('A', 'F') + } + + internal class CachedRange(var start: Int, var end: Int) : CachedCharClass() { + init { + initValues() + } + override fun computeValue(): AbstractCharClass = + object: AbstractCharClass() { + override fun contains(ch: Int): Boolean = alt xor (ch in start..end) + }.apply { + if (end >= Char.MIN_SUPPLEMENTARY_CODE_POINT) { + mayContainSupplCodepoints = true + } + val minSurrogate = Char.MIN_SURROGATE.toInt() + val maxSurrogate = Char.MAX_SURROGATE.toInt() + // There is an intersection with surrogate characters. + if (end >= minSurrogate && start <= maxSurrogate && start <= end) { + val surrogatesStart = maxOf(start, minSurrogate) - minSurrogate + val surrogatesEnd = minOf(end, maxSurrogate) - minSurrogate + lowHighSurrogates.set(surrogatesStart..surrogatesEnd) + } + } + } + + internal class CachedSpecialsBlock : CachedCharClass() { + init { + initValues() + } + public override fun computeValue(): AbstractCharClass = CharClass().add(0xFEFF, 0xFEFF).add(0xFFF0, 0xFFFD) + } + + internal class CachedCategoryScope( + val category: Int, + val mayContainSupplCodepoints: Boolean, + val containsAllSurrogates: Boolean = false) : CachedCharClass() { + init { + initValues() + } + override fun computeValue(): AbstractCharClass { + val result = UnicodeCategoryScope(category) + if (containsAllSurrogates) { + result.lowHighSurrogates.set(0, SURROGATE_CARDINALITY) + } + + result.mayContainSupplCodepoints = mayContainSupplCodepoints + return result + } + } + + internal class CachedCategory( + val category: Int, + val mayContainSupplCodepoints: Boolean, + val containsAllSurrogates: Boolean = false) : CachedCharClass() { + init { + initValues() + } + override fun computeValue(): AbstractCharClass { + val result = UnicodeCategory(category) + if (containsAllSurrogates) { + result.lowHighSurrogates.set(0, SURROGATE_CARDINALITY) + } + result.mayContainSupplCodepoints = mayContainSupplCodepoints + return result + } + } + + companion object { + //Char.MAX_SURROGATE - Char.MIN_SURROGATE + 1 + const val SURROGATE_CARDINALITY = 2048 + + /** + * Character classes. + * See http://www.unicode.org/reports/tr18/, http://www.unicode.org/Public/4.1.0/ucd/Blocks.txt + */ + enum class CharClasses(val regexName : String, val factory: () -> CachedCharClass) { + LOWER("Lower", ::CachedLower), + UPPER("Upper", ::CachedUpper), + ASCII("ASCII", ::CachedASCII), + ALPHA("Alpha", ::CachedAlpha), + DIGIT("Digit", ::CachedDigit), + ALNUM("Alnum", :: CachedAlnum), + PUNCT("Punct", ::CachedPunct), + GRAPH("Graph", ::CachedGraph), + PRINT("Print", ::CachedPrint), + BLANK("Blank", ::CachedBlank), + CNTRL("Cntrl", ::CachedCntrl), + XDIGIT("XDigit", ::CachedXDigit), + SPACE("Space", ::CachedSpace), + WORD("w", ::CachedWord), + NON_WORD("W", ::CachedNonWord), + SPACE_SHORT("s", ::CachedSpace), + NON_SPACE("S", ::CachedNonSpace), + DIGIT_SHORT("d", ::CachedDigit), + NON_DIGIT("D", ::CachedNonDigit), + BASIC_LATIN("BasicLatin", { CachedRange(0x0000, 0x007F) }), + LATIN1_SUPPLEMENT("Latin-1Supplement", { CachedRange(0x0080, 0x00FF) }), + LATIN_EXTENDED_A("LatinExtended-A", { CachedRange(0x0100, 0x017F) }), + LATIN_EXTENDED_B("LatinExtended-B", { CachedRange(0x0180, 0x024F) }), + IPA_EXTENSIONS("IPAExtensions", { CachedRange(0x0250, 0x02AF) }), + SPACING_MODIFIER_LETTERS("SpacingModifierLetters", { CachedRange(0x02B0, 0x02FF) }), + COMBINING_DIACRITICAL_MARKS("CombiningDiacriticalMarks", { CachedRange(0x0300, 0x036F) }), + GREEK("Greek", { CachedRange(0x0370, 0x03FF) }), + CYRILLIC("Cyrillic", { CachedRange(0x0400, 0x04FF) }), + CYRILLIC_SUPPLEMENT("CyrillicSupplement", { CachedRange(0x0500, 0x052F) }), + ARMENIAN("Armenian", { CachedRange(0x0530, 0x058F) }), + HEBREW("Hebrew", { CachedRange(0x0590, 0x05FF) }), + ARABIC("Arabic", { CachedRange(0x0600, 0x06FF) }), + SYRIAC("Syriac", { CachedRange(0x0700, 0x074F) }), + ARABICSUPPLEMENT("ArabicSupplement", { CachedRange(0x0750, 0x077F) }), + THAANA("Thaana", { CachedRange(0x0780, 0x07BF) }), + DEVANAGARI("Devanagari", { CachedRange(0x0900, 0x097F) }), + BENGALI("Bengali", { CachedRange(0x0980, 0x09FF) }), + GURMUKHI("Gurmukhi", { CachedRange(0x0A00, 0x0A7F) }), + GUJARATI("Gujarati", { CachedRange(0x0A80, 0x0AFF) }), + ORIYA("Oriya", { CachedRange(0x0B00, 0x0B7F) }), + TAMIL("Tamil", { CachedRange(0x0B80, 0x0BFF) }), + TELUGU("Telugu", { CachedRange(0x0C00, 0x0C7F) }), + KANNADA("Kannada", { CachedRange(0x0C80, 0x0CFF) }), + MALAYALAM("Malayalam", { CachedRange(0x0D00, 0x0D7F) }), + SINHALA("Sinhala", { CachedRange(0x0D80, 0x0DFF) }), + THAI("Thai", { CachedRange(0x0E00, 0x0E7F) }), + LAO("Lao", { CachedRange(0x0E80, 0x0EFF) }), + TIBETAN("Tibetan", { CachedRange(0x0F00, 0x0FFF) }), + MYANMAR("Myanmar", { CachedRange(0x1000, 0x109F) }), + GEORGIAN("Georgian", { CachedRange(0x10A0, 0x10FF) }), + HANGULJAMO("HangulJamo", { CachedRange(0x1100, 0x11FF) }), + ETHIOPIC("Ethiopic", { CachedRange(0x1200, 0x137F) }), + ETHIOPICSUPPLEMENT("EthiopicSupplement", { CachedRange(0x1380, 0x139F) }), + CHEROKEE("Cherokee", { CachedRange(0x13A0, 0x13FF) }), + UNIFIEDCANADIANABORIGINALSYLLABICS("UnifiedCanadianAboriginalSyllabics", { CachedRange(0x1400, 0x167F) }), + OGHAM("Ogham", { CachedRange(0x1680, 0x169F) }), + RUNIC("Runic", { CachedRange(0x16A0, 0x16FF) }), + TAGALOG("Tagalog", { CachedRange(0x1700, 0x171F) }), + HANUNOO("Hanunoo", { CachedRange(0x1720, 0x173F) }), + BUHID("Buhid", { CachedRange(0x1740, 0x175F) }), + TAGBANWA("Tagbanwa", { CachedRange(0x1760, 0x177F) }), + KHMER("Khmer", { CachedRange(0x1780, 0x17FF) }), + MONGOLIAN("Mongolian", { CachedRange(0x1800, 0x18AF) }), + LIMBU("Limbu", { CachedRange(0x1900, 0x194F) }), + TAILE("TaiLe", { CachedRange(0x1950, 0x197F) }), + NEWTAILUE("NewTaiLue", { CachedRange(0x1980, 0x19DF) }), + KHMERSYMBOLS("KhmerSymbols", { CachedRange(0x19E0, 0x19FF) }), + BUGINESE("Buginese", { CachedRange(0x1A00, 0x1A1F) }), + PHONETICEXTENSIONS("PhoneticExtensions", { CachedRange(0x1D00, 0x1D7F) }), + PHONETICEXTENSIONSSUPPLEMENT("PhoneticExtensionsSupplement", { CachedRange(0x1D80, 0x1DBF) }), + COMBININGDIACRITICALMARKSSUPPLEMENT("CombiningDiacriticalMarksSupplement", { CachedRange(0x1DC0, 0x1DFF) }), + LATINEXTENDEDADDITIONAL("LatinExtendedAdditional", { CachedRange(0x1E00, 0x1EFF) }), + GREEKEXTENDED("GreekExtended", { CachedRange(0x1F00, 0x1FFF) }), + GENERALPUNCTUATION("GeneralPunctuation", { CachedRange(0x2000, 0x206F) }), + SUPERSCRIPTSANDSUBSCRIPTS("SuperscriptsandSubscripts", { CachedRange(0x2070, 0x209F) }), + CURRENCYSYMBOLS("CurrencySymbols", { CachedRange(0x20A0, 0x20CF) }), + COMBININGMARKSFORSYMBOLS("CombiningMarksforSymbols", { CachedRange(0x20D0, 0x20FF) }), + LETTERLIKESYMBOLS("LetterlikeSymbols", { CachedRange(0x2100, 0x214F) }), + NUMBERFORMS("NumberForms", { CachedRange(0x2150, 0x218F) }), + ARROWS("Arrows", { CachedRange(0x2190, 0x21FF) }), + MATHEMATICALOPERATORS("MathematicalOperators", { CachedRange(0x2200, 0x22FF) }), + MISCELLANEOUSTECHNICAL("MiscellaneousTechnical", { CachedRange(0x2300, 0x23FF) }), + CONTROLPICTURES("ControlPictures", { CachedRange(0x2400, 0x243F) }), + OPTICALCHARACTERRECOGNITION("OpticalCharacterRecognition", { CachedRange(0x2440, 0x245F) }), + ENCLOSEDALPHANUMERICS("EnclosedAlphanumerics", { CachedRange(0x2460, 0x24FF) }), + BOXDRAWING("BoxDrawing", { CachedRange(0x2500, 0x257F) }), + BLOCKELEMENTS("BlockElements", { CachedRange(0x2580, 0x259F) }), + GEOMETRICSHAPES("GeometricShapes", { CachedRange(0x25A0, 0x25FF) }), + MISCELLANEOUSSYMBOLS("MiscellaneousSymbols", { CachedRange(0x2600, 0x26FF) }), + DINGBATS("Dingbats", { CachedRange(0x2700, 0x27BF) }), + MISCELLANEOUSMATHEMATICALSYMBOLS_A("MiscellaneousMathematicalSymbols-A", { CachedRange(0x27C0, 0x27EF) }), + SUPPLEMENTALARROWS_A("SupplementalArrows-A", { CachedRange(0x27F0, 0x27FF) }), + BRAILLEPATTERNS("BraillePatterns", { CachedRange(0x2800, 0x28FF) }), + SUPPLEMENTALARROWS_B("SupplementalArrows-B", { CachedRange(0x2900, 0x297F) }), + MISCELLANEOUSMATHEMATICALSYMBOLS_B("MiscellaneousMathematicalSymbols-B", { CachedRange(0x2980, 0x29FF) }), + SUPPLEMENTALMATHEMATICALOPERATORS("SupplementalMathematicalOperators", { CachedRange(0x2A00, 0x2AFF) }), + MISCELLANEOUSSYMBOLSANDARROWS("MiscellaneousSymbolsandArrows", { CachedRange(0x2B00, 0x2BFF) }), + GLAGOLITIC("Glagolitic", { CachedRange(0x2C00, 0x2C5F) }), + COPTIC("Coptic", { CachedRange(0x2C80, 0x2CFF) }), + GEORGIANSUPPLEMENT("GeorgianSupplement", { CachedRange(0x2D00, 0x2D2F) }), + TIFINAGH("Tifinagh", { CachedRange(0x2D30, 0x2D7F) }), + ETHIOPICEXTENDED("EthiopicExtended", { CachedRange(0x2D80, 0x2DDF) }), + SUPPLEMENTALPUNCTUATION("SupplementalPunctuation", { CachedRange(0x2E00, 0x2E7F) }), + CJKRADICALSSUPPLEMENT("CJKRadicalsSupplement", { CachedRange(0x2E80, 0x2EFF) }), + KANGXIRADICALS("KangxiRadicals", { CachedRange(0x2F00, 0x2FDF) }), + IDEOGRAPHICDESCRIPTIONCHARACTERS("IdeographicDescriptionCharacters", { CachedRange(0x2FF0, 0x2FFF) }), + CJKSYMBOLSANDPUNCTUATION("CJKSymbolsandPunctuation", { CachedRange(0x3000, 0x303F) }), + HIRAGANA("Hiragana", { CachedRange(0x3040, 0x309F) }), + KATAKANA("Katakana", { CachedRange(0x30A0, 0x30FF) }), + BOPOMOFO("Bopomofo", { CachedRange(0x3100, 0x312F) }), + HANGULCOMPATIBILITYJAMO("HangulCompatibilityJamo", { CachedRange(0x3130, 0x318F) }), + KANBUN("Kanbun", { CachedRange(0x3190, 0x319F) }), + BOPOMOFOEXTENDED("BopomofoExtended", { CachedRange(0x31A0, 0x31BF) }), + CJKSTROKES("CJKStrokes", { CachedRange(0x31C0, 0x31EF) }), + KATAKANAPHONETICEXTENSIONS("KatakanaPhoneticExtensions", { CachedRange(0x31F0, 0x31FF) }), + ENCLOSEDCJKLETTERSANDMONTHS("EnclosedCJKLettersandMonths", { CachedRange(0x3200, 0x32FF) }), + CJKCOMPATIBILITY("CJKCompatibility", { CachedRange(0x3300, 0x33FF) }), + CJKUNIFIEDIDEOGRAPHSEXTENSIONA("CJKUnifiedIdeographsExtensionA", { CachedRange(0x3400, 0x4DB5) }), + YIJINGHEXAGRAMSYMBOLS("YijingHexagramSymbols", { CachedRange(0x4DC0, 0x4DFF) }), + CJKUNIFIEDIDEOGRAPHS("CJKUnifiedIdeographs", { CachedRange(0x4E00, 0x9FFF) }), + YISYLLABLES("YiSyllables", { CachedRange(0xA000, 0xA48F) }), + YIRADICALS("YiRadicals", { CachedRange(0xA490, 0xA4CF) }), + MODIFIERTONELETTERS("ModifierToneLetters", { CachedRange(0xA700, 0xA71F) }), + SYLOTINAGRI("SylotiNagri", { CachedRange(0xA800, 0xA82F) }), + HANGULSYLLABLES("HangulSyllables", { CachedRange(0xAC00, 0xD7A3) }), + HIGHSURROGATES("HighSurrogates", { CachedRange(0xD800, 0xDB7F) }), + HIGHPRIVATEUSESURROGATES("HighPrivateUseSurrogates", { CachedRange(0xDB80, 0xDBFF) }), + LOWSURROGATES("LowSurrogates", { CachedRange(0xDC00, 0xDFFF) }), + PRIVATEUSEAREA("PrivateUseArea", { CachedRange(0xE000, 0xF8FF) }), + CJKCOMPATIBILITYIDEOGRAPHS("CJKCompatibilityIdeographs", { CachedRange(0xF900, 0xFAFF) }), + ALPHABETICPRESENTATIONFORMS("AlphabeticPresentationForms", { CachedRange(0xFB00, 0xFB4F) }), + ARABICPRESENTATIONFORMS_A("ArabicPresentationForms-A", { CachedRange(0xFB50, 0xFDFF) }), + VARIATIONSELECTORS("VariationSelectors", { CachedRange(0xFE00, 0xFE0F) }), + VERTICALFORMS("VerticalForms", { CachedRange(0xFE10, 0xFE1F) }), + COMBININGHALFMARKS("CombiningHalfMarks", { CachedRange(0xFE20, 0xFE2F) }), + CJKCOMPATIBILITYFORMS("CJKCompatibilityForms", { CachedRange(0xFE30, 0xFE4F) }), + SMALLFORMVARIANTS("SmallFormVariants", { CachedRange(0xFE50, 0xFE6F) }), + ARABICPRESENTATIONFORMS_B("ArabicPresentationForms-B", { CachedRange(0xFE70, 0xFEFF) }), + HALFWIDTHANDFULLWIDTHFORMS("HalfwidthandFullwidthForms", { CachedRange(0xFF00, 0xFFEF) }), + ALL("all", { CachedRange(0x00, 0x10FFFF) }), + SPECIALS("Specials", ::CachedSpecialsBlock), + CN("Cn", { CachedCategory(CharCategory.UNASSIGNED.value, true) }), + ISL("IsL", { CachedCategoryScope(0x3E, true) }), + LU("Lu", { CachedCategory(CharCategory.UPPERCASE_LETTER.value, true) }), + LL("Ll", { CachedCategory(CharCategory.LOWERCASE_LETTER.value, true) }), + LT("Lt", { CachedCategory(CharCategory.TITLECASE_LETTER.value, false) }), + LM("Lm", { CachedCategory(CharCategory.MODIFIER_LETTER.value, false) }), + LO("Lo", { CachedCategory(CharCategory.OTHER_LETTER.value, true) }), + ISM("IsM", { CachedCategoryScope(0x1C0, true) }), + MN("Mn", { CachedCategory(CharCategory.NON_SPACING_MARK.value, true) }), + ME("Me", { CachedCategory(CharCategory.ENCLOSING_MARK.value, false) }), + MC("Mc", { CachedCategory(CharCategory.COMBINING_SPACING_MARK.value, true) }), + N("N", { CachedCategoryScope(0xE00, true) }), + ND("Nd", { CachedCategory(CharCategory.DECIMAL_DIGIT_NUMBER.value, true) }), + NL("Nl", { CachedCategory(CharCategory.LETTER_NUMBER.value, true) }), + NO("No", { CachedCategory(CharCategory.OTHER_NUMBER.value, true) }), + ISZ("IsZ", { CachedCategoryScope(0x7000, false) }), + ZS("Zs", { CachedCategory(CharCategory.SPACE_SEPARATOR.value, false) }), + ZL("Zl", { CachedCategory(CharCategory.LINE_SEPARATOR.value, false) }), + ZP("Zp", { CachedCategory(CharCategory.PARAGRAPH_SEPARATOR.value, false) }), + ISC("IsC", { CachedCategoryScope(0xF0000, true, true) }), + CC("Cc", { CachedCategory(CharCategory.CONTROL.value, false) }), + CF("Cf", { CachedCategory(CharCategory.FORMAT.value, true) }), + CO("Co", { CachedCategory(CharCategory.PRIVATE_USE.value, true) }), + CS("Cs", { CachedCategory(CharCategory.SURROGATE.value, false, true) }), + ISP("IsP", { CachedCategoryScope((1 shl CharCategory.DASH_PUNCTUATION.value) + or (1 shl CharCategory.START_PUNCTUATION.value) + or (1 shl CharCategory.END_PUNCTUATION.value) + or (1 shl CharCategory.CONNECTOR_PUNCTUATION.value) + or (1 shl CharCategory.OTHER_PUNCTUATION.value) + or (1 shl CharCategory.INITIAL_QUOTE_PUNCTUATION.value) + or (1 shl CharCategory.FINAL_QUOTE_PUNCTUATION.value), true) }), + PD("Pd", { CachedCategory(CharCategory.DASH_PUNCTUATION.value, false) }), + PS("Ps", { CachedCategory(CharCategory.START_PUNCTUATION.value, false) }), + PE("Pe", { CachedCategory(CharCategory.END_PUNCTUATION.value, false) }), + PC("Pc", { CachedCategory(CharCategory.CONNECTOR_PUNCTUATION.value, false) }), + PO("Po", { CachedCategory(CharCategory.OTHER_PUNCTUATION.value, true) }), + ISS("IsS", { CachedCategoryScope(0x7E000000, true) }), + SM("Sm", { CachedCategory(CharCategory.MATH_SYMBOL.value, true) }), + SC("Sc", { CachedCategory(CharCategory.CURRENCY_SYMBOL.value, false) }), + SK("Sk", { CachedCategory(CharCategory.MODIFIER_SYMBOL.value, false) }), + SO("So", { CachedCategory(CharCategory.OTHER_SYMBOL.value, true) }), + PI("Pi", { CachedCategory(CharCategory.INITIAL_QUOTE_PUNCTUATION.value, false) }), + PF("Pf", { CachedCategory(CharCategory.FINAL_QUOTE_PUNCTUATION.value, false) }) + } + + private val classCache = Array>(CharClasses.values().size, { + AtomicReference(null) + }) + private val classCacheMap = CharClasses.values().associate { it -> it.regexName to it } + + fun intersects(ch1: Int, ch2: Int): Boolean = ch1 == ch2 + fun intersects(cc: AbstractCharClass, ch: Int): Boolean = cc.contains(ch) + + fun intersects(cc1: AbstractCharClass, cc2: AbstractCharClass): Boolean { + if (cc1.bits == null || cc2.bits == null) { + return true + } + return cc1.bits!!.intersects(cc2.bits!!) + } + + fun getPredefinedClass(name: String, negative: Boolean): AbstractCharClass { + val charClass = classCacheMap[name] ?: throw PatternSyntaxException("No such character class") + val cachedClass = classCache[charClass.ordinal].value ?: run { + classCache[charClass.ordinal].compareAndSwap(null, charClass.factory().freeze()) + classCache[charClass.ordinal].value!! + } + return cachedClass.getValue(negative) + } + } +} diff --git a/kotlin-native/runtime/src/main/kotlin/kotlin/text/regex/AbstractLineTerminator.kt b/kotlin-native/runtime/src/main/kotlin/kotlin/text/regex/AbstractLineTerminator.kt new file mode 100644 index 00000000000..fc145cc4be5 --- /dev/null +++ b/kotlin-native/runtime/src/main/kotlin/kotlin/text/regex/AbstractLineTerminator.kt @@ -0,0 +1,75 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package kotlin.text.regex + +private object unixLT : AbstractLineTerminator() { + override fun isLineTerminator(codepoint: Int): Boolean = (codepoint == '\n'.toInt()) + override fun isLineTerminatorPair(char1: Char, char2: Char): Boolean = false + override fun isAfterLineTerminator(previous: Char, checked: Char): Boolean = (previous == '\n') +} + +private object unicodeLT : AbstractLineTerminator() { + override fun isLineTerminatorPair(char1: Char, char2: Char): Boolean { + return char1 == '\r' && char2 == '\n' + } + + override fun isLineTerminator(codepoint: Int): Boolean { + return codepoint == '\n'.toInt() + || codepoint == '\r'.toInt() + || codepoint == '\u0085'.toInt() + || codepoint or 1 == '\u2029'.toInt() + } + + override fun isAfterLineTerminator(previous: Char, checked: Char): Boolean { + return previous == '\n' || previous == '\u0085' || previous.toInt() or 1 == '\u2029'.toInt() + || previous == '\r' && checked != '\n' + } +} + +/** + * Line terminator factory + */ +internal abstract class AbstractLineTerminator { + + /** Checks if the single character is a line terminator or not. */ + open fun isLineTerminator(char: Char): Boolean = isLineTerminator(char.toInt()) + + /** Checks if the codepoint is a line terminator or not */ + abstract fun isLineTerminator(codepoint: Int): Boolean + + /** Checks if the pair of symbols is a line terminator (e.g. for \r\n case) */ + abstract fun isLineTerminatorPair(char1: Char, char2: Char): Boolean + + /** Checks if a [checked] character is after a line terminator using the [previous] character.*/ + abstract fun isAfterLineTerminator(previous: Char, checked: Char): Boolean + + companion object { + fun getInstance(flag: Int): AbstractLineTerminator { + if (flag and Pattern.UNIX_LINES != 0) { + return unixLT + } else { + return unicodeLT + } + } + } +} diff --git a/kotlin-native/runtime/src/main/kotlin/kotlin/text/regex/CharClass.kt b/kotlin-native/runtime/src/main/kotlin/kotlin/text/regex/CharClass.kt new file mode 100644 index 00000000000..0915c5cf8a6 --- /dev/null +++ b/kotlin-native/runtime/src/main/kotlin/kotlin/text/regex/CharClass.kt @@ -0,0 +1,539 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package kotlin.text.regex + +/** + * User defined character classes (e.g. [abef]). + */ +// TODO: replace the implementation with one using BitSet for first 256 symbols and a hash table / tree for the rest of UTF. +internal class CharClass(val ignoreCase: Boolean = false, negative: Boolean = false) : AbstractCharClass() { + + var invertedSurrogates = false + + /** + * Shows if the alt flags was inverted during the range construction process. + * E.g. consider the following range: [\D3]. Here we firstly add the \D char class (which has the alt flag set) into a + * resulting char set. After that the resulting char also has the alt flag set. But then we need to add the '3' character + * into this class with positive sense. So we set the inverted flag to show that the range is not negative ([^..]) + * by itself but was inverted during some transformations. + */ + var inverted = false + + var hideBits = false + + internal var bits_ = BitSet() + override val bits: BitSet? + get() { + if (hideBits) + return null + return bits_ + } + + var nonBitSet: AbstractCharClass? = null + + private val Int.asciiSupplement: Int + get() = when { + this in 'a'.toInt()..'z'.toInt() -> this - 32 + this in 'A'.toInt()..'Z'.toInt() -> this + 32 + else -> this + } + private val Int.isSurrogate: Boolean + get() = this in Char.MIN_SURROGATE.toInt()..Char.MAX_SURROGATE.toInt() + + init { + setNegative(negative) + } + + /* + * We can use this method safely even if nonBitSet != null + * due to specific of range constructions in regular expressions. + */ + fun add(ch: Int): CharClass { + var character = ch + if (ignoreCase) { + if (character.toChar() in 'a'..'z' || character.toChar() in 'A'..'Z') { + bits_.set(character.asciiSupplement, !inverted) + } else if (character > 128) { + character = Char.toLowerCase(Char.toUpperCase(character)) + } + } + if (character.toChar().isSurrogate()) { + lowHighSurrogates.set(character - Char.MIN_SURROGATE.toInt(), !invertedSurrogates) + } + bits_.set(character, !inverted) + if (!mayContainSupplCodepoints && Char.isSupplementaryCodePoint(ch)) { + mayContainSupplCodepoints = true + } + return this + } + + fun add(ch: Char): CharClass = add(ch.toInt()) + + /* + * The difference between add(AbstractCharClass) and union(AbstractCharClass) + * is that add() is used for constructions like "[^abc\\d]" + * (this pattern doesn't match "1") + * while union is used for constructions like "[^abc[\\d]]" + * (this pattern matches "1"). + */ + fun add(another: AbstractCharClass): CharClass { + + if (!mayContainSupplCodepoints && another.mayContainSupplCodepoints) { + mayContainSupplCodepoints = true + } + + // Process surrogates. + if (!invertedSurrogates) { + + //A | !B = ! ((A ^ B) & B) + if (another.altSurrogates) { + lowHighSurrogates.xor(another.lowHighSurrogates) + lowHighSurrogates.and(another.lowHighSurrogates) + altSurrogates = !altSurrogates + invertedSurrogates = true + + //A | B + } else { + lowHighSurrogates.or(another.lowHighSurrogates) + } + } else { + + //!A | !B = !(A & B) + if (another.altSurrogates) { + lowHighSurrogates.and(another.lowHighSurrogates) + + //!A | B = !(A & !B) + } else { + lowHighSurrogates.andNot(another.lowHighSurrogates) + } + } + + val anotherBits = another.bits + if (!hideBits && anotherBits != null) { + if (!inverted) { + + //A | !B = ! ((A ^ B) & B) + if (another.isNegative()) { + bits_.xor(anotherBits) + bits_.and(anotherBits) + alt = !alt + inverted = true + + //A | B + } else { + bits_.or(anotherBits) + } + } else { + + //!A | !B = !(A & B) + if (another.isNegative()) { + bits_.and(anotherBits) + + //!A | B = !(A & !B) + } else { + bits_.andNot(anotherBits) + } + } + // Some of charclasses hides its bits + } else { + val curAlt = alt + + if (nonBitSet == null) { + + if (curAlt && !inverted && bits_.isEmpty) { + nonBitSet = object : AbstractCharClass() { + override operator fun contains(ch: Int): Boolean { + return another.contains(ch) + } + } + } else { + + /* + * We keep the value of alt unchanged for + * constructions like [^[abc]fgb] by using + * the formula a ^ b == !a ^ !b. + */ + if (curAlt) { + nonBitSet = object : AbstractCharClass() { + override operator fun contains(ch: Int): Boolean { + return !(curAlt xor bits_.get(ch) || curAlt xor inverted xor another.contains(ch)) + } + } + } else { + nonBitSet = object : AbstractCharClass() { + override operator fun contains(ch: Int): Boolean { + return curAlt xor bits_.get(ch) || curAlt xor inverted xor another.contains(ch) + } + } + } + } + + hideBits = true + } else { + val nb = nonBitSet + + if (curAlt) { + nonBitSet = object : AbstractCharClass() { + override operator fun contains(ch: Int): Boolean { + return !(curAlt xor (nb!!.contains(ch) || another.contains(ch))) + } + } + } else { + nonBitSet = object : AbstractCharClass() { + override operator fun contains(ch: Int): Boolean { + return curAlt xor (nb!!.contains(ch) || another.contains(ch)) + } + } + } + } + } + + return this + } + + fun add(start: Int, end: Int): CharClass { + if (start > end) + throw IllegalArgumentException("Incorrect range of symbols (start > end)") + val minSurrogate = Char.MIN_SURROGATE.toInt() + val maxSurrogate = Char.MAX_SURROGATE.toInt() + if (ignoreCase) { + // TODO: Make a faster implementation. + for (i in start..end) { + add(i) + } + } else { + // No intersection with surrogate characters. + if (end < minSurrogate || start > maxSurrogate) { + bits_.set(start, end + 1, !inverted) + } else { + val surrogatesStart = maxOf(start, minSurrogate) + val surrogatesEnd = minOf(end, maxSurrogate) + bits_.set(start, end + 1, !inverted) + lowHighSurrogates.set(surrogatesStart - minSurrogate, + surrogatesEnd - minSurrogate + 1, + !invertedSurrogates) + if (!mayContainSupplCodepoints && end >= Char.MIN_SUPPLEMENTARY_CODE_POINT) { + mayContainSupplCodepoints = true + } + } + } + return this + } + + fun add(start: Char, end: Char): CharClass = add(start.toInt(), end.toInt()) + + // OR operation + fun union(another: AbstractCharClass) { + if (!mayContainSupplCodepoints && another.mayContainSupplCodepoints) { + mayContainSupplCodepoints = true + } + + + if (altSurrogates xor another.altSurrogates) { + + //!A | B = !(A & !B) + if (altSurrogates) { + lowHighSurrogates.andNot(another.lowHighSurrogates) + + //A | !B = !((A ^ B) & B) + } else { + lowHighSurrogates.xor(another.lowHighSurrogates) + lowHighSurrogates.and(another.lowHighSurrogates) + altSurrogates = true + } + + } else { + + //!A | !B = !(A & B) + if (altSurrogates) { + lowHighSurrogates.and(another.lowHighSurrogates) + + //A | B + } else { + lowHighSurrogates.or(another.lowHighSurrogates) + } + } + + val anotherBits = another.bits + if (!hideBits && anotherBits != null) { + if (alt xor another.isNegative()) { + + //!A | B = !(A & !B) + if (alt) { + bits_.andNot(anotherBits) + + //A | !B = !((A ^ B) & B) + } else { + bits_.xor(anotherBits) + bits_.and(anotherBits) + alt = true + } + + } else { + + //!A | !B = !(A & B) + if (alt) { + bits_.and(anotherBits) + + //A | B + } else { + bits_.or(anotherBits) + } + } + } else { + val curAlt = alt + + if (nonBitSet == null) { + + if (!inverted && bits_.isEmpty) { + if (curAlt) { + nonBitSet = object : AbstractCharClass() { + override operator fun contains(ch: Int): Boolean { + return !another.contains(ch) + } + } + } else { + nonBitSet = object : AbstractCharClass() { + override operator fun contains(ch: Int): Boolean { + return another.contains(ch) + } + } + } + } else { + + if (curAlt) { + nonBitSet = object : AbstractCharClass() { + override operator fun contains(ch: Int): Boolean { + return !(another.contains(ch) || curAlt xor bits_.get(ch)) + } + } + } else { + nonBitSet = object : AbstractCharClass() { + override operator fun contains(ch: Int): Boolean { + return another.contains(ch) || curAlt xor bits_.get(ch) + } + } + } + } + hideBits = true + } else { + val nb = nonBitSet + + if (curAlt) { + nonBitSet = object : AbstractCharClass() { + override operator fun contains(ch: Int): Boolean { + return !(curAlt xor nb!!.contains(ch) || another.contains(ch)) + } + } + } else { + nonBitSet = object : AbstractCharClass() { + override operator fun contains(ch: Int): Boolean { + return curAlt xor nb!!.contains(ch) || another.contains(ch) + } + } + } + } + } + } + + // AND operation + fun intersection(another: AbstractCharClass) { + if (!mayContainSupplCodepoints && another.mayContainSupplCodepoints) { + mayContainSupplCodepoints = true + } + + if (altSurrogates xor another.altSurrogates) { + + //!A & B = ((A ^ B) & B) + if (altSurrogates) { + lowHighSurrogates.xor(another.lowHighSurrogates) + lowHighSurrogates.and(another.lowHighSurrogates) + altSurrogates = false + + //A & !B + } else { + lowHighSurrogates.andNot(another.lowHighSurrogates) + } + } else { + + //!A & !B = !(A | B) + if (altSurrogates) { + lowHighSurrogates.or(another.lowHighSurrogates) + + //A & B + } else { + lowHighSurrogates.and(another.lowHighSurrogates) + } + } + + val anotherBits = another.bits + if (!hideBits && anotherBits != null) { + + if (alt xor another.isNegative()) { + + //!A & B = ((A ^ B) & B) + if (alt) { + bits_.xor(anotherBits) + bits_.and(anotherBits) + alt = false + + //A & !B + } else { + bits_.andNot(anotherBits) + } + } else { + + //!A & !B = !(A | B) + if (alt) { + bits_.or(anotherBits) + + //A & B + } else { + bits_.and(anotherBits) + } + } + } else { + val curAlt = alt + + if (nonBitSet == null) { + + if (!inverted && bits_.isEmpty) { + if (curAlt) { + nonBitSet = object : AbstractCharClass() { + override operator fun contains(ch: Int): Boolean { + return !another.contains(ch) + } + } + } else { + nonBitSet = object : AbstractCharClass() { + override operator fun contains(ch: Int): Boolean { + return another.contains(ch) + } + } + } + } else { + + if (curAlt) { + nonBitSet = object : AbstractCharClass() { + override operator fun contains(ch: Int): Boolean { + return !(another.contains(ch) && curAlt xor bits_.get(ch)) + } + } + } else { + nonBitSet = object : AbstractCharClass() { + override operator fun contains(ch: Int): Boolean { + return another.contains(ch) && curAlt xor bits_.get(ch) + } + } + } + } + hideBits = true + } else { + val nb = nonBitSet + + if (curAlt) { + nonBitSet = object : AbstractCharClass() { + override operator fun contains(ch: Int): Boolean { + return !(curAlt xor nb!!.contains(ch) && another.contains(ch)) + } + } + } else { + nonBitSet = object : AbstractCharClass() { + override operator fun contains(ch: Int): Boolean { + return curAlt xor nb!!.contains(ch) && another.contains(ch) + } + } + } + } + } + } + + /** + * Returns `true` if character class contains symbol specified, + * `false` otherwise. Note: #setNegative() method changes the + * meaning of contains method; + + * @param ch + * * + * @return `true` if character class contains symbol specified; + * */ + override operator fun contains(ch: Int): Boolean { + if (nonBitSet == null) { + return alt xor bits_.get(ch) + } else { + return alt xor nonBitSet!!.contains(ch) + } + } + + @OptIn(ExperimentalStdlibApi::class) + override val instance: AbstractCharClass + get() { + + if (nonBitSet == null) { + val bs = bits + + val res = object : AbstractCharClass() { + override operator fun contains(ch: Int): Boolean { + return this.alt xor bs!!.get(ch) + } + + override fun toString(): String { + val temp = StringBuilder() + var i = bs!!.nextSetBit(0) + while (i >= 0) { + temp.append(Char.toChars(i)) + temp.append('|') + i = bs.nextSetBit(i + 1) + } + + if (temp.length > 0) + temp.deleteAt(temp.length - 1) + + return temp.toString() + } + + } + return res.setNegative(isNegative()) + } else { + return this + } + } + + @OptIn(ExperimentalStdlibApi::class) + //for debugging purposes only + override fun toString(): String { + val temp = StringBuilder() + var i = bits_.nextSetBit(0) + while (i >= 0) { + temp.append(Char.toChars(i)) + temp.append('|') + i = bits_.nextSetBit(i + 1) + } + + if (temp.length > 0) + temp.deleteAt(temp.length - 1) + + return temp.toString() + } +} + diff --git a/kotlin-native/runtime/src/main/kotlin/kotlin/text/regex/Lexer.kt b/kotlin-native/runtime/src/main/kotlin/kotlin/text/regex/Lexer.kt new file mode 100644 index 00000000000..fe7ccd23f08 --- /dev/null +++ b/kotlin-native/runtime/src/main/kotlin/kotlin/text/regex/Lexer.kt @@ -0,0 +1,942 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +// TODO: Licenses. + +package kotlin.text.regex + +// Access to the decomposition tables. ========================================================================= +/** Gets canonical class for given codepoint from decomposition mappings table. */ +@SymbolName("Kotlin_text_regex_getCanonicalClassInternal") +external private fun getCanonicalClassInternal(ch: Int): Int + +/** Check if the given character is in table of single decompositions. */ +@SymbolName("Kotlin_text_regex_hasSingleCodepointDecompositionInternal") +external private fun hasSingleCodepointDecompositionInternal(ch: Int): Boolean + +/** Returns a decomposition for a given codepoint. */ +@SymbolName("Kotlin_text_regex_getDecompositionInternal") +external private fun getDecompositionInternal(ch: Int): IntArray? + +/** + * Decomposes the given string represented as an array of codepoints. Saves the decomposition into [outputCodepoints] array. + * Returns the length of the decomposition. + */ +@SymbolName("Kotlin_text_regex_decomposeString") +external private fun decomposeString(inputCodePoints: IntArray, inputLength: Int, outputCodePoints: IntArray): Int +// ============================================================================================================= + +/** + * This is base class for special tokens like character classes and quantifiers. + */ +internal abstract class SpecialToken { + + /** + * Returns the type of the token, may return following values: + * TOK_CHARCLASS - token representing character class; + * TOK_QUANTIFIER - token representing quantifier; + */ + abstract val type: Type + + enum class Type { + CHARCLASS, + QUANTIFIER + } +} + +internal class Lexer(val patternString: String, flags: Int) { + + // The property is set in the init block after some transformations over the pattern string. + private val pattern: CharArray + + var flags = flags + private set + + // Modes =========================================================================================================== + enum class Mode { + PATTERN, + RANGE, + ESCAPE + } + + /** + * Mode: whether the lexer processes character range ([Mode.RANGE]), escaped sequence ([Mode.RANGE]) + * or any other part of a regex ([PATTERN]). + */ + var mode = Mode.PATTERN + private set + + /** When in [Mode.ESCAPE] mode, this field will save the previous one */ + private var savedMode = Mode.PATTERN + + fun setModeWithReread(value: Mode) { + if(value == Mode.PATTERN || value == Mode.RANGE) { + mode = value + } + if (mode == Mode.PATTERN) { + reread() + } + } + + // Tokens ========================================================================================================== + internal var lookBack: Int = 0 // Previous char read. + private set + internal var currentChar: Int = 0 // Current character read. Returns 0 if there is no more characters. + private set + internal var lookAhead: Int = 0 // Next character. + private set + + internal var curSpecialToken: SpecialToken? = null // Current special token (e.g. quantifier) + private set + internal var lookAheadSpecialToken: SpecialToken? = null // Next special token + private set + + // Indices in the pattern. + var index = 0 // Current char being processed index. + private set + var prevNonWhitespaceIndex = 0 // Previous non-whitespace character index. + private set + var curTokenIndex = 0 // Current token start index. + private set + var lookAheadTokenIndex = 0 // Next token index. + private set + + init { + var processedPattern = patternString + if (flags and Pattern.LITERAL > 0) { + processedPattern = Pattern.quote(patternString) + } else if (flags and Pattern.CANON_EQ > 0) { + processedPattern = Lexer.normalize(patternString) + } + + this.pattern = processedPattern.toCharArray().copyOf(processedPattern.length + 2) + this.pattern[this.pattern.size - 1] = 0.toChar() + this.pattern[this.pattern.size - 2] = 0.toChar() + + // Read first two tokens. + movePointer() + movePointer() + } + + // Character checks ================================================================================================ + /** Returns true, if current token is special, i.e. quantifier, or other compound token. */ + val isSpecial: Boolean get() = curSpecialToken != null + val isQuantifier: Boolean get() = isSpecial && curSpecialToken!!.type == SpecialToken.Type.QUANTIFIER + val isNextSpecial: Boolean get() = lookAheadSpecialToken != null + + private fun Int.isSurrogatePair() : Boolean { + val high = (this ushr 16).toChar() + val low = this.toChar() + return high.isHighSurrogate() && low.isLowSurrogate() + } + + private fun Char.isLineSeparator(): Boolean = + this == '\n' || this == '\r' || this == '\u0085' || this.toInt() or 1 == '\u2029'.toInt() + + /** Checks if there are any characters in the pattern. */ + fun isEmpty(): Boolean = + currentChar == 0 && lookAhead == 0 && index >= pattern.size && !isSpecial + + /** Return true if the current character is letter, false otherwise .*/ + fun isLetter(): Boolean = + !isEmpty() && !isSpecial && isLetter(currentChar) + + /** Check if the current char is high/low surrogate. */ + fun isHighSurrogate(): Boolean = currentChar in 0xDBFF..0xD800 + fun isLowSurrogate(): Boolean = currentChar in 0xDFFF..0xDC00 + fun isSurrogate(): Boolean = isHighSurrogate() || isLowSurrogate() + + /** + * Restores flags for Lexer + * @param flags + */ + fun restoreFlags(flags: Int) { + this.flags = flags + lookAhead = currentChar + lookAheadSpecialToken = curSpecialToken + + // curTokenIndex is an index of closing bracket ')' + index = curTokenIndex + 1 + lookAheadTokenIndex = curTokenIndex + movePointer() + } + + override fun toString(): String { + return patternString + } + + // Processing index moving ========================================================================================= + /** Returns current character and moves string index to the next one. */ + operator fun next(): Int { + movePointer() + return lookBack + } + + /** Returns current special token and moves string index to the next one */ + fun nextSpecial(): SpecialToken? { + val res = curSpecialToken + movePointer() + return res + } + + /** + * Reread current character. May be required if a previous token changes mode + * to one with different character interpretation. + */ + private fun reread() { + lookAhead = currentChar + lookAheadSpecialToken = curSpecialToken + index = lookAheadTokenIndex + lookAheadTokenIndex = curTokenIndex + movePointer() + } + + /** + * Returns the next character index to read and moves pointer to the next one. + * If comments flag is on this method will skip comments and whitespaces. + * + * The following actions are equivalent if comments flag is off: + * currentChar = pattern[index++] == currentChar = pattern[nextIndex] + */ + private fun nextIndex(): Int { + prevNonWhitespaceIndex = index + if (flags and Pattern.COMMENTS != 0) { + skipComments() + } else { + index++ + } + return prevNonWhitespaceIndex + } + + /** Skips comments and whitespaces */ + private fun skipComments(): Int { + val length = pattern.size - 2 + index++ + do { + while (index < length && pattern[index].isWhitespace()) { + index++ + } + if (index < length && pattern[index] == '#') { + index++ + while (index < length && !pattern[index].isLineSeparator()) { + index++ + } + } else { + return index + } + } while (true) + } + + /** + * Returns the next code point in the pattern string. + */ + private fun nextCodePoint(): Int { + val high = pattern[nextIndex()] // nextIndex skips comments and whitespaces if comments flag is on. + if (high.isHighSurrogate()) { + // Low and high chars may be delimited by spaces. + val lowExpectedIndex = prevNonWhitespaceIndex + 1 + if (lowExpectedIndex < pattern.size) { + val low = pattern[lowExpectedIndex] + if (low.isLowSurrogate()) { + nextIndex() + return Char.toCodePoint(high, low) + } + } + } + return high.toInt() + } + + /** + * Moves pointer one position right. Saves the current character to [lookBack], + * [lookAhead] to the current one and finally read one more to [lookAhead]. + */ + private fun movePointer() { + // swap pointers + lookBack = currentChar + currentChar = lookAhead + curSpecialToken = lookAheadSpecialToken + curTokenIndex = lookAheadTokenIndex + lookAheadTokenIndex = index + var reread: Boolean + do { + // Read the next character, analyze it and construct a token. + lookAhead = if (index < pattern.size) nextCodePoint() else 0 + lookAheadSpecialToken = null + + if (mode == Mode.ESCAPE) { + processInEscapeMode() + } + + reread = when (mode) { + Mode.PATTERN -> processInPatternMode() + Mode.RANGE -> processInRangeMode() + else -> false + } + } while (reread) + } + + // Special functions called from [movePointer] function to process chars in different modes ======================== + /** + * Processing an escaped sequence like "\Q foo \E". Just skip a character if it is not \E. + * Returns whether we need to reread the character or not + */ + private fun processInEscapeMode(): Boolean { + if (lookAhead == '\\'.toInt()) { + // Need not care about supplementary code points here. + val lookAheadChar: Char = if (index < pattern.size) pattern[nextIndex()] else '\u0000' + lookAhead = lookAheadChar.toInt() + + if (lookAheadChar == 'E') { + // If \E found - change the mode to the previous one and shift to the next char. + mode = savedMode + lookAhead = if (index <= pattern.size - 2) nextCodePoint() else 0 + } else { + // If \ have no E - make a step back and return. + lookAhead = '\\'.toInt() + index = prevNonWhitespaceIndex + } + } + return false + } + + /** Processes a next character in [Mode.PATTERN] mode. Returns whether we need to reread the character or not */ + private fun processInPatternMode(): Boolean { + if (lookAhead.isSurrogatePair()) { + return false + } + val lookAheadChar = lookAhead.toChar() + + if (lookAheadChar == '\\') { + return processEscapedChar() + } + + // TODO: Look like we can create a quantifier here. + when (lookAheadChar) { + // Quantifier (*, +, ?). + '+', '*', '?' -> { + val mode = if (index < pattern.size) pattern[index] else '*' + // look at the next character to determine if the mode is greedy, reluctant or possessive. + when (mode) { + '+' -> { lookAhead = lookAhead or Lexer.QMOD_POSSESSIVE; nextIndex() } + '?' -> { lookAhead = lookAhead or Lexer.QMOD_RELUCTANT; nextIndex() } + else -> lookAhead = lookAhead or Lexer.QMOD_GREEDY + } + } + + // Quantifier ({x,y}). + '{' -> lookAheadSpecialToken = processQuantifier() + + // $. + '$' -> lookAhead = CHAR_DOLLAR + + // A group or a special construction. + '(' -> { + if (pattern[index] != '?') { + // Group + lookAhead = CHAR_LEFT_PARENTHESIS + } else { + // Special constructs (non-capturing groups, look ahead/look behind etc). + nextIndex() + var char = pattern[index] + var isLookBehind = false + do { + if (!isLookBehind) { + when (char) { + // Look ahead or an atomic group. + '!' -> { lookAhead = CHAR_NEG_LOOKAHEAD; nextIndex() } + '=' -> { lookAhead = CHAR_POS_LOOKAHEAD; nextIndex() } + '>' -> { lookAhead = CHAR_ATOMIC_GROUP; nextIndex() } + // Positive / negaitve look behind - need to check the next char. + '<' -> { + nextIndex() + char = pattern[index] + isLookBehind = true + } + // Flags. + else -> { + lookAhead = readFlags() + + // We return `res = res or 1 shl 8` from readFlags() if we read (?idmsux-idmsux) + if (lookAhead >= 256) { + // Just flags (no non-capturing group with them). Erase auxiliary bit. + lookAhead = lookAhead and 0xff + flags = lookAhead + lookAhead = lookAhead shl 16 + lookAhead = CHAR_FLAGS or lookAhead + } else { + // A non-capturing group with flags: (?:Foo) + flags = lookAhead + lookAhead = lookAhead shl 16 + lookAhead = CHAR_NONCAP_GROUP or lookAhead + } + } + } + } else { + // Process the second char for look behind construction. + isLookBehind = false + when (char) { + '!' -> { lookAhead = CHAR_NEG_LOOKBEHIND; nextIndex() } + '=' -> { lookAhead = CHAR_POS_LOOKBEHIND; nextIndex() } + else -> throw PatternSyntaxException("Unknown look behind", patternString, curTokenIndex) + } + } + } while (isLookBehind) + } + } + + ')' -> lookAhead = CHAR_RIGHT_PARENTHESIS + '[' -> { lookAhead = CHAR_LEFT_SQUARE_BRACKET; mode = Mode.RANGE } + '^' -> lookAhead = CHAR_CARET + '|' -> lookAhead = CHAR_VERTICAL_BAR + '.' -> lookAhead = CHAR_DOT + } + return false + } + + /** Processes a character inside a range. Returns whether we need to reread the character or not */ + private fun processInRangeMode(): Boolean { + if (lookAhead.isSurrogatePair()) { + return false + } + val lookAheadChar = lookAhead.toChar() + + when (lookAheadChar) { + '\\' -> return processEscapedChar() + '[' -> lookAhead = CHAR_LEFT_SQUARE_BRACKET + ']' -> lookAhead = CHAR_RIGHT_SQUARE_BRACKET + '^' -> lookAhead = CHAR_CARET + '&' -> lookAhead = CHAR_AMPERSAND + '-' -> lookAhead = CHAR_HYPHEN + } + return false + } + + /** Processes an escaped (\x) character in any mode. Returns whether we need to reread the character or not */ + private fun processEscapedChar() : Boolean { + lookAhead = if (index < pattern.size - 2) { + nextCodePoint() + } else { + throw PatternSyntaxException("Trailing \\", patternString, curTokenIndex) + } + + // The current code point cannot be a surrogate pair because it is an escaped special one. + // Cast it to char or just skip it as if we pass through the else branch of the when below. + if (lookAhead.isSurrogatePair()) { + return false + } + val lookAheadChar = lookAhead.toChar() + + when (lookAheadChar) { + // Character class. + 'P', 'p' -> { + val cs = parseCharClassName() + val negative = lookAheadChar == 'P' + + lookAheadSpecialToken = AbstractCharClass.getPredefinedClass(cs, negative) + lookAhead = 0 + } + + // Word/whitespace/digit. + 'w', 's', 'd', 'W', 'S', 'D' -> { + lookAheadSpecialToken = AbstractCharClass.getPredefinedClass( + String(pattern, prevNonWhitespaceIndex, 1), + false + ) + lookAhead = 0 + } + + // Enter in ESCAPE mode. Skip this \Q symbol. + 'Q' -> { + savedMode = mode + mode = Mode.ESCAPE + return true + } + + // Special characters like tab, new line etc. + 't' -> lookAhead = '\t'.toInt() + 'n' -> lookAhead = '\n'.toInt() + 'r' -> lookAhead = '\r'.toInt() + 'f' -> lookAhead = '\u000C'.toInt() + 'a' -> lookAhead = '\u0007'.toInt() + 'e' -> lookAhead = '\u001B'.toInt() + + // Back references to capturing groups. + '1', '2', '3', '4', '5', '6', '7', '8', '9' -> { + if (mode == Mode.PATTERN) { + lookAhead = 0x80000000.toInt() or lookAhead // Captured group reference is 0x80... + } + } + + // A literal: octal, hex, or hex unicode. + '0' -> lookAhead = readOctals() + 'x' -> lookAhead = readHex("hexadecimal", 2) + 'u' -> lookAhead = readHex("Unicode", 4) + + // Special characters like EOL, EOI etc + 'b' -> lookAhead = CHAR_WORD_BOUND + 'B' -> lookAhead = CHAR_NONWORD_BOUND + 'A' -> lookAhead = CHAR_START_OF_INPUT + 'G' -> lookAhead = CHAR_PREVIOUS_MATCH + 'Z' -> lookAhead = CHAR_END_OF_LINE + 'z' -> lookAhead = CHAR_END_OF_INPUT + + // \cx - A control character corresponding to x. + 'c' -> { + if (index < pattern.size - 2) { + // Need not care about supplementary codepoints here. + lookAhead = pattern[nextIndex()].toInt() and 0x1f + } else { + throw PatternSyntaxException("Illegal control sequence", patternString, curTokenIndex) + } + } + + 'C', 'E', 'F', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'R', 'T', 'U', 'V', 'X', 'Y', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'o', 'q', 'y' -> + throw PatternSyntaxException("Illegal escape sequence", patternString, curTokenIndex) + } + return false + } + + /** Process [lookAhead] in assumption that it's quantifier. */ + private fun processQuantifier(): Quantifier { + assert(lookAhead == '{'.toInt()) + val sb = StringBuilder(4) + var min = -1 + var max = -1 + + // Obtain a min value. + var char: Char = if (index < pattern.size) { + pattern[nextIndex()] + } else { + throw PatternSyntaxException("Incorrect Quantifier Syntax", patternString, curTokenIndex) + } + while (char != '}') { + + if (char == ',' && min < 0) { + try { + val minParsed = sb.toString().toInt() + min = if (minParsed >= 0) minParsed else throw PatternSyntaxException("Incorrect Quantifier Syntax", patternString, curTokenIndex) + sb.setLength(0) + } catch (nfe: NumberFormatException) { + throw PatternSyntaxException("Incorrect Quantifier Syntax", patternString, curTokenIndex) + } + } else { + sb.append(char) + } + char = if (index < pattern.size) pattern[nextIndex()] else break + } + + if (char != '}') { + throw PatternSyntaxException("Incorrect Quantifier Syntax", patternString, curTokenIndex) + } + + // Obtain a max value, if it exists + if (sb.isNotEmpty()) { + try { + val maxParsed = sb.toString().toInt() + max = if (maxParsed >= 0) maxParsed else throw PatternSyntaxException("Incorrect Quantifier Syntax", patternString, curTokenIndex) + if (min < 0) { + min = max + } + } catch (nfe: NumberFormatException) { + throw PatternSyntaxException("Incorrect Quantifier Syntax", patternString, curTokenIndex) + } + } + + if (min < 0 || max >=0 && max < min) { + throw PatternSyntaxException("Incorrect Quantifier Syntax", patternString, curTokenIndex) + } + + val mod = if (index < pattern.size) pattern[index] else '*' + when (mod) { + '+' -> { lookAhead = Lexer.QUANT_COMP_P; nextIndex() } + '?' -> { lookAhead = Lexer.QUANT_COMP_R; nextIndex() } + else -> lookAhead = Lexer.QUANT_COMP + } + return Quantifier(min, max) + } + + // Reading methods for specific tokens ============================================================================= + /** Process expression flags given with (?idmsux-idmsux). Returns the flags processed. */ + private fun readFlags(): Int { + var positive = true + var result = flags + + while (index < pattern.size) { + val char = pattern[index] + when (char) { + '-' -> { + if (!positive) { + throw PatternSyntaxException("Illegal inline construct", patternString, curTokenIndex) + } + positive = false + } + + 'i' -> result = if (positive) + result or Pattern.CASE_INSENSITIVE + else + result xor Pattern.CASE_INSENSITIVE and result + + 'd' -> result = if (positive) + result or Pattern.UNIX_LINES + else + result xor Pattern.UNIX_LINES and result + + 'm' -> result = if (positive) + result or Pattern.MULTILINE + else + result xor Pattern.MULTILINE and result + + 's' -> result = if (positive) + result or Pattern.DOTALL + else + result xor Pattern.DOTALL and result + + // We don't support UNICODE_CASE. + /*'u' -> result = if (positive) + result or Pattern.UNICODE_CASE + else + result xor Pattern.UNICODE_CASE and result*/ + + 'x' -> result = if (positive) + result or Pattern.COMMENTS + else + result xor Pattern.COMMENTS and result + + ':' -> { + nextIndex() + return result + } + + ')' -> { + nextIndex() + return result or (1 shl 8) + } + } + nextIndex() + } + throw PatternSyntaxException("Illegal inline construct", patternString, curTokenIndex) + } + + /** Parse character classes names and verifies correction of the syntax */ + private fun parseCharClassName(): String { + val sb = StringBuilder(10) + if (index < pattern.size - 2) { + // one symbol family + if (pattern[index] != '{') { + return "Is${pattern[nextIndex()]}" + } + + nextIndex() // Skip '{' + var char = pattern[nextIndex()] + while (index < pattern.size - 2 && char != '}') { + sb.append(char) + char = pattern[nextIndex()] + } + if (char != '}') throw PatternSyntaxException("Unclosed character family", patternString, curTokenIndex) + } + if (sb.isEmpty()) throw PatternSyntaxException("Empty character family", patternString, curTokenIndex) + + val res = sb.toString() + return when { + res.length == 1 -> "Is$res" + res.length > 3 && (res.startsWith("Is") || res.startsWith("In")) -> res.substring(2) + else -> res + } + } + + /** Process hexadecimal integer. */ + private fun readHex(radixName: String, max: Int): Int { + val builder = StringBuilder(max) + val length = pattern.size - 2 + var i = 0 + while (i < max && index < length) { + builder.append(pattern[nextIndex()]) + i++ + } + if (i == max) { + try { + return builder.toString().toInt(16) + } catch (e: NumberFormatException) {} + } + throw PatternSyntaxException("Invalid $radixName escape sequence", patternString, curTokenIndex) + } + + /** Process octal integer. */ + private fun readOctals(): Int { + val length = pattern.size - 2 + var result = 0 + var digit = digitOf(pattern[index], 8) + if (digit == -1) { + throw PatternSyntaxException("Invalid octal escape sequence", patternString, curTokenIndex) + } + val max = if (digit > 3) 2 else 3 + var i = 0 + while (i < max && index < length && digit != -1) { + result *= 8 + result += digit + nextIndex() + digit = digitOf(pattern[index], 8) + i++ + } + return result + } + + companion object { + // Special characters. + val CHAR_DOLLAR = 0xe0000000.toInt() or '$'.toInt() + val CHAR_RIGHT_PARENTHESIS = 0xe0000000.toInt() or ')'.toInt() + val CHAR_LEFT_SQUARE_BRACKET = 0xe0000000.toInt() or '['.toInt() + val CHAR_RIGHT_SQUARE_BRACKET = 0xe0000000.toInt() or ']'.toInt() + val CHAR_CARET = 0xe0000000.toInt() or '^'.toInt() + val CHAR_VERTICAL_BAR = 0xe0000000.toInt() or '|'.toInt() + val CHAR_AMPERSAND = 0xe0000000.toInt() or '&'.toInt() + val CHAR_HYPHEN = 0xe0000000.toInt() or '-'.toInt() + val CHAR_DOT = 0xe0000000.toInt() or '.'.toInt() + val CHAR_LEFT_PARENTHESIS = 0x80000000.toInt() or '('.toInt() + val CHAR_NONCAP_GROUP = 0xc0000000.toInt() or '('.toInt() + val CHAR_POS_LOOKAHEAD = 0xe0000000.toInt() or '('.toInt() + val CHAR_NEG_LOOKAHEAD = 0xf0000000.toInt() or '('.toInt() + val CHAR_POS_LOOKBEHIND = 0xf8000000.toInt() or '('.toInt() + val CHAR_NEG_LOOKBEHIND = 0xfc000000.toInt() or '('.toInt() + val CHAR_ATOMIC_GROUP = 0xfe000000.toInt() or '('.toInt() + val CHAR_FLAGS = 0xff000000.toInt() or '('.toInt() + val CHAR_START_OF_INPUT = 0x80000000.toInt() or 'A'.toInt() + val CHAR_WORD_BOUND = 0x80000000.toInt() or 'b'.toInt() + val CHAR_NONWORD_BOUND = 0x80000000.toInt() or 'B'.toInt() + val CHAR_PREVIOUS_MATCH = 0x80000000.toInt() or 'G'.toInt() + val CHAR_END_OF_INPUT = 0x80000000.toInt() or 'z'.toInt() + val CHAR_END_OF_LINE = 0x80000000.toInt() or 'Z'.toInt() + + // Quantifier modes. + val QMOD_GREEDY = 0xe0000000.toInt() + val QMOD_RELUCTANT = 0xc0000000.toInt() + val QMOD_POSSESSIVE = 0x80000000.toInt() + + // Quantifiers. + val QUANT_STAR = QMOD_GREEDY or '*'.toInt() + val QUANT_STAR_P = QMOD_POSSESSIVE or '*'.toInt() + val QUANT_STAR_R = QMOD_RELUCTANT or '*'.toInt() + val QUANT_PLUS = QMOD_GREEDY or '+'.toInt() + val QUANT_PLUS_P = QMOD_POSSESSIVE or '+'.toInt() + val QUANT_PLUS_R = QMOD_RELUCTANT or '+'.toInt() + val QUANT_ALT = QMOD_GREEDY or '?'.toInt() + val QUANT_ALT_P = QMOD_POSSESSIVE or '?'.toInt() + val QUANT_ALT_R = QMOD_RELUCTANT or '?'.toInt() + val QUANT_COMP = QMOD_GREEDY or '{'.toInt() + val QUANT_COMP_P = QMOD_POSSESSIVE or '{'.toInt() + val QUANT_COMP_R = QMOD_RELUCTANT or '{'.toInt() + + /** Returns true if [ch] is a plain token. */ + fun isLetter(ch: Int): Boolean { + // All supplementary codepoints have integer value that is >= 0. + return ch >= 0 + } + + private fun String.codePointAt(index: Int): Int { + val high = this[index] + if (high.isHighSurrogate() && index + 1 < this.length) { + val low = this[index + 1] + if (low.isLowSurrogate()) { + return Char.toCodePoint(high, low) + } + } + return high.toInt() + } + + // Decomposition =============================================================================================== + // Maximum length of decomposition. + val MAX_DECOMPOSITION_LENGTH = 4 + // Maximum length of Hangul decomposition. Note that MAX_HANGUL_DECOMPOSITION_LENGTH <= MAX_DECOMPOSITION_LENGTH. + val MAX_HANGUL_DECOMPOSITION_LENGTH = 3 + + /* + * Following constants are needed for Hangul canonical decomposition. + * Hangul decomposition algorithm and constants are taken according + * to description at http://www.unicode.org/versions/Unicode4.0.0/ch03.pdf + * "3.12 Conjoining Jamo Behavior" + */ + const val SBase = 0xAC00 + const val LBase = 0x1100 + const val VBase = 0x1161 + const val TBase = 0x11A7 + const val SCount = 11172 + const val LCount = 19 + const val VCount = 21 + const val TCount = 28 + const val NCount = 588 + + // Access to the decomposition tables. ========================================================================= + /** Gets canonical class for given codepoint from decomposition mappings table. */ + fun getCanonicalClass(ch: Int): Int = getCanonicalClassInternal(ch) + + /** Tests Unicode codepoint if it is a boundary of decomposed Unicode codepoint. */ + fun isDecomposedCharBoundary(ch: Int): Boolean = getCanonicalClass(ch) == 0 + + /** Tests if given codepoint is a canonical decomposition of another codepoint. */ + fun hasSingleCodepointDecomposition(ch: Int): Boolean = hasSingleCodepointDecompositionInternal(ch) + + /** Tests if given codepoint has canonical decomposition and given codepoint's canonical class is not 0. */ + fun hasDecompositionNonNullCanClass(ch: Int): Boolean = + (ch == 0x0340) or (ch == 0x0341) or (ch == 0x0343) or (ch == 0x0344) + + /** Gets decomposition for given codepoint from decomposition mappings table. */ + fun getDecomposition(ch: Int): IntArray? = getDecompositionInternal(ch) + + // ============================================================================================================= + + /** + * Normalize given string. + */ + fun normalize(input: String): String { + val inputChars = input.toCharArray() + val inputLength = inputChars.size + var inputCodePointsIndex = 0 + var decompHangulIndex = 0 + + //codePoints of input + val inputCodePoints = IntArray(inputLength) + + //result of canonical decomposition of input + var resCodePoints = IntArray(inputLength * MAX_DECOMPOSITION_LENGTH) + + //current symbol's codepoint + var ch: Int + + //current symbol's decomposition + var decomp: IntArray? + + //result of canonical and Hangul decomposition of input + val decompHangul: IntArray + + //result of canonical decomposition of input in UTF-16 encoding + val result = StringBuilder() + + var i = 0 + while (i < inputLength) { + ch = input.codePointAt(i) + inputCodePoints[inputCodePointsIndex++] = ch + i += if (Char.isSupplementaryCodePoint(ch)) 2 else 1 + } + + // Canonical decomposition based on mappings in decomposition table. + var resCodePointsIndex = decomposeString(inputCodePoints, inputCodePointsIndex, resCodePoints) + + // Canonical ordering. + // See http://www.unicode.org/reports/tr15/#Decomposition for details + resCodePoints = Lexer.getCanonicalOrder(resCodePoints, resCodePointsIndex) + + // Decomposition for Hangul syllables. + // See http://www.unicode.org/reports/tr15/#Hangul for details + decompHangul = IntArray(resCodePoints.size) + @Suppress("NAME_SHADOWING") + for (i in 0..resCodePointsIndex - 1) { + val curSymb = resCodePoints[i] + + decomp = getHangulDecomposition(curSymb) + if (decomp == null) { + decompHangul[decompHangulIndex++] = curSymb + } else { + // Note that Hangul decompositions have length that is equal 2 or 3. + decompHangul[decompHangulIndex++] = decomp[0] + decompHangul[decompHangulIndex++] = decomp[1] + if (decomp.size == 3) { + decompHangul[decompHangulIndex++] = decomp[2] + } + } + } + + // Translating into UTF-16 encoding + @Suppress("NAME_SHADOWING") + for (i in 0..decompHangulIndex - 1) { + result.append(Char.toChars(decompHangul[i])) + } + + return result.toString() + } + + /** + * Rearrange codepoints in [inputInts] according to canonical order. Return an array with rearranged codepoints. + */ + fun getCanonicalOrder(inputInts: IntArray, length: Int): IntArray { + val inputLength = if (length < inputInts.size) + length + else + inputInts.size + + /* + * Simple bubble-sort algorithm. Note that many codepoints have 0 canonical class, so this algorithm works + * almost lineary in overwhelming majority of cases. This is due to specific of Unicode combining + * classes and codepoints. + */ + for (i in 1..inputLength - 1) { + var j = i - 1 + val iCanonicalClass = getCanonicalClass(inputInts[i]) + val ch: Int + + if (iCanonicalClass == 0) { + continue + } + + while (j > -1) { + if (getCanonicalClass(inputInts[j]) > iCanonicalClass) { + j = j - 1 + } else { + break + } + } + + ch = inputInts[i] + for (k in i downTo j + 1 + 1) { + inputInts[k] = inputInts[k - 1] + } + inputInts[j + 1] = ch + } + + return inputInts + } + + /** + * Gets decomposition for given Hangul syllable. + * This is an implementation of Hangul decomposition algorithm + * according to http://www.unicode.org/versions/Unicode4.0.0/ch03.pdf "3.12 Conjoining Jamo Behavior". + */ + fun getHangulDecomposition(ch: Int): IntArray? { + val SIndex = ch - SBase + + if (SIndex < 0 || SIndex >= SCount) { + return null + } else { + val L = LBase + SIndex / NCount + val V = VBase + SIndex % NCount / TCount + var T = SIndex % TCount + val decomp: IntArray + + if (T == 0) { + decomp = intArrayOf(L, V) + } else { + T = TBase + T + decomp = intArrayOf(L, V, T) + } + return decomp + } + } + } +} diff --git a/kotlin-native/runtime/src/main/kotlin/kotlin/text/regex/MatchResultImpl.kt b/kotlin-native/runtime/src/main/kotlin/kotlin/text/regex/MatchResultImpl.kt new file mode 100644 index 00000000000..91d29ec75e3 --- /dev/null +++ b/kotlin-native/runtime/src/main/kotlin/kotlin/text/regex/MatchResultImpl.kt @@ -0,0 +1,231 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package kotlin.text.regex + +/** + * Match result implementation + */ + +internal class MatchResultImpl +/** + * @param input an input sequence for matching/searching. + * @param regex a [Regex] instance used for matching/searching. + * @param rightBound index in the [input] used as a right bound for matching/searching. Exclusive. + */ +constructor (internal val input: CharSequence, + internal val regex: Regex) : MatchResult { + + // Harmony's implementation ======================================================================================== + private val nativePattern = regex.nativePattern + private val groupCount = nativePattern.capturingGroupCount + private val groupBounds = IntArray(groupCount * 2) { -1 } + + private val consumers = IntArray(nativePattern.consumersCount + 1) { -1 } + + // Used by quantifiers to store a count of a quantified expression occurrences. + val enterCounters: IntArray = IntArray( maxOf(nativePattern.groupQuantifierCount, 0) ) + + var startIndex: Int = 0 + set (startIndex: Int) { + field = startIndex + if (previousMatch < 0) { + previousMatch = startIndex + } + } + + var previousMatch = -1 + var mode = Regex.Mode.MATCH + + // MatchResult interface =========================================================================================== + /** The range of indices in the original string where match was captured. */ + override val range: IntRange + get() = getStart(0) until getEnd(0) + + /** The substring from the input string captured by this match. */ + override val value: String + get() = group(0) ?: throw AssertionError("No groupIndex #0 in the match result.") + + /** + * A collection of groups matched by the regular expression. + * + * This collection has size of `groupCount + 1` where `groupCount` is the count of groups in the regular expression. + * Groups are indexed from 1 to `groupCount` and group with the index 0 corresponds to the entire match. + */ + // Create one object or several ones? + override val groups: MatchGroupCollection = object: MatchGroupCollection, AbstractCollection() { + override val size: Int + get() = this@MatchResultImpl.groupCount + + + override fun iterator(): Iterator { + return object: Iterator { + var nextIndex: Int = 0 + + override fun hasNext(): Boolean { + return nextIndex < size + } + + override fun next(): MatchGroup? { + if (!hasNext()) { + throw NoSuchElementException() + } + return get(nextIndex++) + } + } + } + + override fun get(index: Int): MatchGroup? { + val value = group(index) ?: return null + return MatchGroup(value, getStart(index) until getEnd(index)) + } + } + + /** + * A list of matched indexed group values. + * + * This list has size of `groupCount + 1` where `groupCount` is the count of groups in the regular expression. + * Groups are indexed from 1 to `groupCount` and group with the index 0 corresponds to the entire match. + * + * If the group in the regular expression is optional and there were no match captured by that group, + * corresponding item in [groupValues] is an empty string. + * + * @sample: samples.text.Regexps.matchDestructuringToGroupValues + */ + override val groupValues: List + get() = mutableListOf().apply { + for (i in 0 until groupCount) { + this.add(group(i) ?: "") + } + } + + override fun next(): MatchResult? { + var nextStart = range.endInclusive + 1 + // If the current match is empty - shift by 1. + if (nextStart == range.start) { + nextStart++ + } + if (nextStart > input.length) { + return null + } + return regex.find(input, nextStart) + } + // ================================================================================================================= + + + // Harmony's implementation ======================================================================================== + fun setConsumed(counter: Int, value: Int) { + this.consumers[counter] = value + } + + fun getConsumed(counter: Int): Int { + return this.consumers[counter] + } + + fun isCaptured(group: Int): Boolean = getStart(group) >= 0 + + // Setters and getters for starts and ends of groups =============================================================== + internal fun setStart(group: Int, offset: Int) { + checkGroup(group) + groupBounds[group * 2] = offset + } + + internal fun setEnd(group: Int, offset: Int) { + checkGroup(group) + groupBounds[group * 2 + 1] = offset + } + + /** + * Returns the index of the first character of the text that matched a given group. + * + * @param group the group, ranging from 0 to groupCount() - 1, with 0 representing the whole pattern. + * @return the character index. + */ + fun getStart(group: Int = 0): Int { + checkGroup(group) + return groupBounds[group * 2] + } + + /** + * Returns the index of the first character following the text that matched a given group. + * + * @param group the group, ranging from 0 to groupCount() - 1, with 0 representing the whole pattern. + * @return the character index. + */ + fun getEnd(group: Int = 0): Int { + checkGroup(group) + return groupBounds[group * 2 + 1] + } + + // ================================================================================================== + + /** + * Returns the text that matched a given group of the regular expression. + * + * @param group the group, ranging from 0 to groupCount() - 1, with 0 representing the whole pattern. + * @return the text that matched the group. + */ + fun group(group: Int = 0): String? { + val start = getStart(group) + val end = getEnd(group) + if (start < 0 || end < 0) { + return null + } + return input.subSequence(getStart(group), getEnd(group)).toString() + } + + /** + * Returns the number of groups in the result, which is always equal to + * the number of groups in the original regular expression. + * + * @return the number of groups. + */ + fun groupCount(): Int { + return groupCount - 1 + } + + /* + * This method being called after any successful match; For now it's being + * used to check zero group for empty match; + */ + fun finalizeMatch() { + if (this.groupBounds[0] == -1) { + this.groupBounds[0] = this.startIndex + this.groupBounds[1] = this.startIndex + } + + previousMatch = getEnd() + } + + private fun checkGroup(group: Int) { + if (group < 0 || group > groupCount) { + throw IndexOutOfBoundsException("Group index out of bounds: $group") + } + } + + fun updateGroup(index: Int, srtOffset: Int, endOffset: Int) { + checkGroup(index) + groupBounds[index * 2] = srtOffset + groupBounds[index * 2 + 1] = endOffset + } +} + diff --git a/kotlin-native/runtime/src/main/kotlin/kotlin/text/regex/Pattern.kt b/kotlin-native/runtime/src/main/kotlin/kotlin/text/regex/Pattern.kt new file mode 100644 index 00000000000..e114670218d --- /dev/null +++ b/kotlin-native/runtime/src/main/kotlin/kotlin/text/regex/Pattern.kt @@ -0,0 +1,878 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package kotlin.text.regex + +/** Represents a compiled pattern used by [Regex] for matching, searching, or replacing strings. */ +internal class Pattern(val pattern: String, flags: Int = 0) { + + var flags = flags + private set + + /** A lexer instance used to get tokens from the pattern. */ + private val lexemes = Lexer(pattern, flags) + + /* All back references that may be used in pattern. */ + private val backRefs = arrayOfNulls(BACK_REF_NUMBER) + + /** Is true if back referenced sets replacement by second compilation pass is needed.*/ + private var needsBackRefReplacement = false + + /** Global count of found capturing groups. */ + var capturingGroupCount = 0 + private set + + /** A number of group quantifiers in the pattern */ + var groupQuantifierCount = 0 + private set + + /** + * A number of consumers found in the pattern. + * Consumer is any expression ending with an FSet except capturing groups (they are counted by [capturingGroupCount]) + */ + var consumersCount = 0 + private set + + /** A node to start a matching/searching process by call startNode.matches/startNode.find. */ + internal val startNode: AbstractSet + + /** Compiles the given pattern */ + init { + if (flags != 0 && flags or flagsBitMask != flagsBitMask) { + throw IllegalArgumentException("Invalid match flags value") + } + startNode = processExpression(-1, this.flags, null) + + if (!lexemes.isEmpty()) { + throw PatternSyntaxException("Trailing characters", pattern, lexemes.curTokenIndex) + } + + // Finalize compilation + if (needsBackRefReplacement) { + startNode.processSecondPass() + } + } + + override fun toString(): String = pattern + + /** Return true if the pattern has the specified flag */ + private fun hasFlag(flag: Int): Boolean = flags and flag == flag + + // Compilation methods. ============================================================================================ + /** A->(a|)+ */ + private fun processAlternations(last: AbstractSet): AbstractSet { + val auxRange = CharClass(hasFlag(Pattern.CASE_INSENSITIVE)) + while (!lexemes.isEmpty() && lexemes.isLetter() + && (lexemes.lookAhead == 0 + || lexemes.lookAhead == Lexer.CHAR_VERTICAL_BAR + || lexemes.lookAhead == Lexer.CHAR_RIGHT_PARENTHESIS)) { + auxRange.add(lexemes.next()) + if (lexemes.currentChar == Lexer.CHAR_VERTICAL_BAR) { + lexemes.next() + } + } + val rangeSet = processRangeSet(auxRange) + rangeSet.next = last + + return rangeSet + } + + /** E->AE; E->S|E; E->S; A->(a|)+ E->S(|S)* */ + private fun processExpression(ch: Int, newFlags: Int, last: AbstractSet?): AbstractSet { + val children = ArrayList() + val savedFlags = flags + var saveChangedFlags = false + + if (newFlags != flags) { + flags = newFlags + } + + // Create a right finalizing set. + val fSet: FSet + when (ch) { + // Special groups: non-capturing, look ahead/behind etc. + Lexer.CHAR_NONCAP_GROUP -> fSet = NonCapFSet(consumersCount++) + Lexer.CHAR_POS_LOOKAHEAD, + Lexer.CHAR_NEG_LOOKAHEAD -> fSet = AheadFSet() + Lexer.CHAR_POS_LOOKBEHIND, + Lexer.CHAR_NEG_LOOKBEHIND -> fSet = BehindFSet(consumersCount++) + Lexer.CHAR_ATOMIC_GROUP -> fSet = AtomicFSet(consumersCount++) + // A Capturing group. + else -> { + if (last == null) { + // Whole pattern - group #0. + fSet = FinalSet() + saveChangedFlags = true + } else { + fSet = FSet(capturingGroupCount) + } + if (capturingGroupCount < BACK_REF_NUMBER) { + backRefs[capturingGroupCount] = fSet + } + capturingGroupCount++ + } + } + + //Process to EOF or ')' + do { + val child: AbstractSet + when { + // a|... + lexemes.isLetter() && lexemes.lookAhead == Lexer.CHAR_VERTICAL_BAR -> child = processAlternations(fSet) + // ..|.., e.g. in "a||||b" + lexemes.currentChar == Lexer.CHAR_VERTICAL_BAR -> { + child = EmptySet(fSet) + lexemes.next() + } + else -> { + child = processSubExpression(fSet) + if (lexemes.currentChar == Lexer.CHAR_VERTICAL_BAR) { + lexemes.next() + } + } + } + children.add(child) + } while (!(lexemes.isEmpty() || lexemes.currentChar == Lexer.CHAR_RIGHT_PARENTHESIS)) + + // |) or | - add an empty node. + if (lexemes.lookBack == Lexer.CHAR_VERTICAL_BAR) { + children.add(EmptySet(fSet)) + } + + // Restore flags. + if (flags != savedFlags && !saveChangedFlags) { + flags = savedFlags + lexemes.restoreFlags(flags) + } + + when (ch) { + Lexer.CHAR_NONCAP_GROUP -> return NonCapturingJointSet(children, fSet) + Lexer.CHAR_POS_LOOKAHEAD -> return PositiveLookAheadSet(children, fSet) + Lexer.CHAR_NEG_LOOKAHEAD -> return NegativeLookAheadSet(children, fSet) + Lexer.CHAR_POS_LOOKBEHIND -> return PositiveLookBehindSet(children, fSet) + Lexer.CHAR_NEG_LOOKBEHIND -> return NegativeLookBehindSet(children, fSet) + Lexer.CHAR_ATOMIC_GROUP -> return AtomicJointSet(children, fSet) + + else -> when (children.size) { + 0 -> return EmptySet(fSet) + 1 -> return SingleSet(children[0], fSet) + else -> return JointSet(children, fSet) + } + } + } + + + /** + * T->aaa + */ + private fun processSequence(): AbstractSet { + val substring = StringBuilder() + while (!lexemes.isEmpty() + && lexemes.isLetter() + && !lexemes.isSurrogate() + && (!lexemes.isNextSpecial && lexemes.lookAhead == 0 // End of a pattern. + || !lexemes.isNextSpecial && Lexer.isLetter(lexemes.lookAhead) + || lexemes.lookAhead == Lexer.CHAR_RIGHT_PARENTHESIS + || lexemes.lookAhead and 0x8000ffff.toInt() == Lexer.CHAR_LEFT_PARENTHESIS + || lexemes.lookAhead == Lexer.CHAR_VERTICAL_BAR + || lexemes.lookAhead == Lexer.CHAR_DOLLAR)) { + val ch = lexemes.next() + + if (Char.isSupplementaryCodePoint(ch)) { + substring.append(Char.toChars(ch)) + } else { + substring.append(ch.toChar()) + } + } + return SequenceSet(substring, hasFlag(CASE_INSENSITIVE)) + } + + /** + * D->a + */ + private fun processDecomposedChar(): AbstractSet { + val codePoints = IntArray(Lexer.MAX_DECOMPOSITION_LENGTH) + val codePointsHangul: CharArray + var readCodePoints = 0 + var curSymb = -1 + var curSymbIndex = -1 + + if (!lexemes.isEmpty() && lexemes.isLetter()) { + curSymb = lexemes.next() + codePoints[readCodePoints] = curSymb + curSymbIndex = curSymb - Lexer.LBase + } + + /* + * We process decomposed Hangul syllable LV or LVT or process jamo L. + * See http://www.unicode.org/versions/Unicode4.0.0/ch03.pdf + * "3.12 Conjoining Jamo Behavior" + */ + if (curSymbIndex >= 0 && curSymbIndex < Lexer.LCount) { + codePointsHangul = CharArray(Lexer.MAX_HANGUL_DECOMPOSITION_LENGTH) + codePointsHangul[readCodePoints++] = curSymb.toChar() + + curSymb = lexemes.currentChar + curSymbIndex = curSymb - Lexer.VBase + if (curSymbIndex >= 0 && curSymbIndex < Lexer.VCount) { + codePointsHangul[readCodePoints++] = curSymb.toChar() + lexemes.next() + curSymb = lexemes.currentChar + curSymbIndex = curSymb - Lexer.TBase + if (curSymbIndex >= 0 && curSymbIndex < Lexer.TCount) { + codePointsHangul[@Suppress("UNUSED_CHANGED_VALUE")readCodePoints++] = curSymb.toChar() + lexemes.next() + + //LVT syllable + return HangulDecomposedCharSet(codePointsHangul, 3) + } else { + + //LV syllable + return HangulDecomposedCharSet(codePointsHangul, 2) + } + } else { + + //L jamo + return CharSet(codePointsHangul[0], hasFlag(CASE_INSENSITIVE)) + } + + /* + * We process single codepoint or decomposed codepoint. + * We collect decomposed codepoint and obtain + * one DecomposedCharSet. + */ + } else { + readCodePoints++ + + while (readCodePoints < Lexer.MAX_DECOMPOSITION_LENGTH + && !lexemes.isEmpty() && lexemes.isLetter() + && !Lexer.isDecomposedCharBoundary(lexemes.currentChar)) { + codePoints[readCodePoints++] = lexemes.next() + } + + /* + * We have read an ordinary symbol. + */ + if (readCodePoints == 1 && !Lexer.hasSingleCodepointDecomposition(codePoints[0])) { + return processCharSet(codePoints[0]) + } else { + return DecomposedCharSet(codePoints, readCodePoints) + } + } + } + + /** + * S->BS; S->QS; S->Q; B->a+ + */ + private fun processSubExpression(last: AbstractSet): AbstractSet { + var cur: AbstractSet + when { + lexemes.isLetter() && !lexemes.isNextSpecial && Lexer.isLetter(lexemes.lookAhead) -> { + when { + hasFlag(Pattern.CANON_EQ) -> { + cur = processDecomposedChar() + if (!lexemes.isEmpty() + && (lexemes.currentChar != Lexer.CHAR_RIGHT_PARENTHESIS || last is FinalSet) + && lexemes.currentChar != Lexer.CHAR_VERTICAL_BAR + && !lexemes.isLetter()) { + + cur = processQuantifier(last, cur) + } + } + lexemes.isHighSurrogate() || lexemes.isLowSurrogate() -> { + val term = processTerminal(last) + cur = processQuantifier(last, term) + } + else -> { + cur = processSequence() + } + } + } + lexemes.currentChar == Lexer.CHAR_RIGHT_PARENTHESIS -> { + if (last is FinalSet) { + throw PatternSyntaxException("unmatched )", pattern, lexemes.curTokenIndex) + } + cur = EmptySet(last) + } + else -> { + val term = processTerminal(last) + cur = processQuantifier(last, term) + } + } + + if (!lexemes.isEmpty() + && (lexemes.currentChar != Lexer.CHAR_RIGHT_PARENTHESIS || last is FinalSet) + && lexemes.currentChar != Lexer.CHAR_VERTICAL_BAR) { + + val next = processSubExpression(last) + if (cur is LeafQuantifierSet + // '*' or '{0,}' quantifier + && cur.max == Quantifier.INF + && cur.min == 0 + && !next.first(cur.innerSet)) { + // An Optimizer node for the case where there is no intersection with the next node + cur = UnifiedQuantifierSet(cur) + } + cur.next = next + } else { + cur.next = last + } + return cur + } + + /** + * Q->T(*|+|?...) also do some optimizations. + */ + private fun processQuantifier(last: AbstractSet, term: AbstractSet): AbstractSet { + val quant = lexemes.currentChar + + if (term !is LeafSet) { + return when (quant) { + Lexer.QUANT_STAR, Lexer.QUANT_PLUS -> { + val q: QuantifierSet + + lexemes.next() + if (term.type == AbstractSet.TYPE_DOTSET) { + q = DotQuantifierSet(term, last, quant, AbstractLineTerminator.getInstance(flags), hasFlag(Pattern.DOTALL)) + } else { + q = GroupQuantifierSet(Quantifier.fromLexerToken(quant), term, last, quant, groupQuantifierCount++) + } + term.next = q + q + } + + Lexer.QUANT_ALT -> { + lexemes.next() + val q = GroupQuantifierSet(Quantifier.fromLexerToken(quant), term, last, quant, groupQuantifierCount++) + term.next = q + q + } + + Lexer.QUANT_STAR_R, Lexer.QUANT_PLUS_R, Lexer.QUANT_ALT_R -> { + lexemes.next() + val q = ReluctantGroupQuantifierSet(Quantifier.fromLexerToken(quant), term, last, quant, groupQuantifierCount++) + term.next = q + q + } + + Lexer.QUANT_PLUS_P, Lexer.QUANT_STAR_P, Lexer.QUANT_ALT_P -> { + lexemes.next() + PossessiveGroupQuantifierSet(Quantifier.fromLexerToken(quant), term, last, quant, groupQuantifierCount++) + } + + Lexer.QUANT_COMP -> { + val q = GroupQuantifierSet(lexemes.nextSpecial() as Quantifier, term, last, Lexer.QUANT_ALT, groupQuantifierCount++) + term.next = q + q + } + + Lexer.QUANT_COMP_R -> { + val q = ReluctantGroupQuantifierSet(lexemes.nextSpecial() as Quantifier, term, last, Lexer.QUANT_ALT, groupQuantifierCount++) + term.next = q + q + } + + Lexer.QUANT_COMP_P -> { + return PossessiveGroupQuantifierSet(lexemes.nextSpecial() as Quantifier, term, last, Lexer.QUANT_ALT, groupQuantifierCount++) + } + + else -> term + } + } else { + val leaf: LeafSet = term + return when (quant) { + Lexer.QUANT_STAR, Lexer.QUANT_PLUS -> { + lexemes.next() + val q = LeafQuantifierSet(Quantifier.fromLexerToken(quant), leaf, last, quant) + leaf.next = q + q + } + + Lexer.QUANT_STAR_R, Lexer.QUANT_PLUS_R -> { + lexemes.next() + val q = ReluctantLeafQuantifierSet(Quantifier.fromLexerToken(quant), leaf, last, quant) + leaf.next = q + q + } + + Lexer.QUANT_PLUS_P, Lexer.QUANT_STAR_P -> { + lexemes.next() + val q = PossessiveLeafQuantifierSet(Quantifier.fromLexerToken(quant), leaf, last, quant) + leaf.next = q + q + } + + Lexer.QUANT_ALT -> { + lexemes.next() + LeafQuantifierSet(Quantifier.altQuantifier, leaf, last, Lexer.QUANT_ALT) + } + + Lexer.QUANT_ALT_R -> { + lexemes.next() + ReluctantLeafQuantifierSet(Quantifier.altQuantifier, leaf, last, Lexer.QUANT_ALT_R) + } + + Lexer.QUANT_ALT_P -> { + lexemes.next() + PossessiveLeafQuantifierSet(Quantifier.altQuantifier, leaf, last, Lexer.QUANT_ALT_P) + } + + Lexer.QUANT_COMP -> { + LeafQuantifierSet(lexemes.nextSpecial() as Quantifier, leaf, last, Lexer.QUANT_COMP) + } + Lexer.QUANT_COMP_R -> { + ReluctantLeafQuantifierSet(lexemes.nextSpecial() as Quantifier, leaf, last, Lexer.QUANT_COMP_R) + } + Lexer.QUANT_COMP_P -> { + ReluctantLeafQuantifierSet(lexemes.nextSpecial() as Quantifier, leaf, last, Lexer.QUANT_COMP_P) + } + + else -> term + } + } + } + + /** + * T-> letter|[range]|{char-class}|(E) + */ + private fun processTerminal(last: AbstractSet): AbstractSet { + val term: AbstractSet + var char = lexemes.currentChar + // Process flags: (?...)(?...)... + while (char and 0xff00ffff.toInt() == Lexer.CHAR_FLAGS) { + lexemes.next() + flags = (char shr 16) and flagsBitMask + char = lexemes.currentChar + } + // The terminal is some kind of group: (E). Call processExpression for it. + if (char and 0x8000ffff.toInt() == Lexer.CHAR_LEFT_PARENTHESIS) { + lexemes.next() + var newFlags = flags + if (char and 0xff00ffff.toInt() == Lexer.CHAR_NONCAP_GROUP) { + newFlags = (char shr 16) and flagsBitMask + } + term = processExpression(char and 0xff00ffff.toInt(), newFlags, last) // Remove flags from the token. + if (lexemes.currentChar != Lexer.CHAR_RIGHT_PARENTHESIS) { + throw PatternSyntaxException("unmatched (", pattern, lexemes.curTokenIndex) + } + lexemes.next() + } else { + // Other terminals. + when (char) { + Lexer.CHAR_LEFT_SQUARE_BRACKET -> { // Range: [...] + lexemes.next() + var negative = false + if (lexemes.currentChar == Lexer.CHAR_CARET) { + negative = true + lexemes.next() + } + + term = processRange(negative, last) + if (lexemes.currentChar != Lexer.CHAR_RIGHT_SQUARE_BRACKET) { + throw PatternSyntaxException("unmatched [", pattern, lexemes.curTokenIndex) + } + lexemes.setModeWithReread(Lexer.Mode.PATTERN) + lexemes.next() + } + + Lexer.CHAR_DOT -> { // Dot: . + lexemes.next() + term = DotSet(AbstractLineTerminator.getInstance(flags), hasFlag(DOTALL)) + } + + Lexer.CHAR_CARET -> { // Beginning of the string: ^ + lexemes.next() + term = SOLSet(AbstractLineTerminator.getInstance(flags), hasFlag(MULTILINE)) + consumersCount++ + } + + Lexer.CHAR_DOLLAR -> { // End of the string: $ + lexemes.next() + term = EOLSet(consumersCount++, AbstractLineTerminator.getInstance(flags), hasFlag(MULTILINE)) + + } + + // Word / non-word boundary. + Lexer.CHAR_WORD_BOUND -> { + lexemes.next() + term = WordBoundarySet(true) + } + + Lexer.CHAR_NONWORD_BOUND -> { + lexemes.next() + term = WordBoundarySet(false) + } + + Lexer.CHAR_END_OF_INPUT -> { // End of an input: \z + lexemes.next() + term = EOISet() + } + + Lexer.CHAR_END_OF_LINE -> { // End of a line: \Z + lexemes.next() + term = EOLSet(consumersCount++, AbstractLineTerminator.getInstance(flags)) + } + + Lexer.CHAR_START_OF_INPUT -> { // Start if an input: \A + lexemes.next() + term = SOLSet(AbstractLineTerminator.getInstance(flags)) + } + + Lexer.CHAR_PREVIOUS_MATCH -> { // A previous match: \G + lexemes.next() + term = PreviousMatchSet() + } + + // Back references: \1, \2 etc. + 0x80000000.toInt() or '1'.toInt(), + 0x80000000.toInt() or '2'.toInt(), + 0x80000000.toInt() or '3'.toInt(), + 0x80000000.toInt() or '4'.toInt(), + 0x80000000.toInt() or '5'.toInt(), + 0x80000000.toInt() or '6'.toInt(), + 0x80000000.toInt() or '7'.toInt(), + 0x80000000.toInt() or '8'.toInt(), + 0x80000000.toInt() or '9'.toInt() -> { + val number = (char and 0x7FFFFFFF) - '0'.toInt() + if (number < capturingGroupCount) { // All is ok - the group exists. + lexemes.next() + term = BackReferenceSet(number, consumersCount++, hasFlag(CASE_INSENSITIVE)) + // backRefs[number] is proved to be not null because the group is already created (number < capturingGroupCount) + backRefs[number]!!.isBackReferenced = true + needsBackRefReplacement = true // And process back references in the second pass. + } else { + throw PatternSyntaxException("No such group yet exists at this point in the pattern", pattern, lexemes.curTokenIndex) + } + } + + // A special token (\D, \w etc), 'u0000' or the end of the pattern. + 0 -> { + val cc: AbstractCharClass? = lexemes.curSpecialToken as AbstractCharClass? + when { + cc != null -> { + term = processRangeSet(cc) + lexemes.next() + } + !lexemes.isEmpty() -> { + term = CharSet(char.toChar()) + lexemes.next() + } + else -> term = EmptySet(last) + } + } + + else -> { + when { + // A regular character. + char >= 0 && !lexemes.isSpecial -> { + term = processCharSet(char) + lexemes.next() + } + char == Lexer.CHAR_VERTICAL_BAR -> { + term = EmptySet(last) + } + char == Lexer.CHAR_RIGHT_PARENTHESIS -> { + if (last is FinalSet) { + throw PatternSyntaxException("unmatched )", pattern, lexemes.curTokenIndex) + } + term = EmptySet(last) + } + else -> { + val current = if (lexemes.isSpecial) lexemes.curSpecialToken.toString() else char.toString() + throw PatternSyntaxException("Dangling meta construction: $current", pattern, lexemes.curTokenIndex) + } + } + } + } + } + return term + } + + + /** + * Process [...] ranges + */ + private fun processRange(negative: Boolean, last: AbstractSet): AbstractSet { + val res = processRangeExpression(negative) + val rangeSet = processRangeSet(res) + rangeSet.next = last + + return rangeSet + } + + private fun processRangeExpression(alt: Boolean): CharClass { + var result = CharClass(hasFlag(Pattern.CASE_INSENSITIVE), alt) + var buffer = -1 + var intersection = false + var firstInClass = true + + var notClosed = lexemes.currentChar != Lexer.CHAR_RIGHT_SQUARE_BRACKET + while (!lexemes.isEmpty() && (notClosed || firstInClass)) { + when (lexemes.currentChar) { + + Lexer.CHAR_RIGHT_SQUARE_BRACKET -> { + if (buffer >= 0) { + result.add(buffer) + } + buffer = ']'.toInt() + lexemes.next() + } + + Lexer.CHAR_LEFT_SQUARE_BRACKET -> { + if (buffer >= 0) { + result.add(buffer) + buffer = -1 + } + lexemes.next() + var negative = false + if (lexemes.currentChar == Lexer.CHAR_CARET) { + lexemes.next() + negative = true + } + + if (intersection) + result.intersection(processRangeExpression(negative)) + else + result.union(processRangeExpression(negative)) + intersection = false + lexemes.next() + } + + Lexer.CHAR_AMPERSAND -> { + if (buffer >= 0) { + result.add(buffer) + } + buffer = lexemes.next() // buffer == Lexer.CHAR_AMPERSAND since next() returns currentChar. + + /* + * If there is a start for subrange we will do an intersection + * otherwise treat '&' as a normal character + */ + if (lexemes.currentChar == Lexer.CHAR_AMPERSAND) { + if (lexemes.lookAhead == Lexer.CHAR_LEFT_SQUARE_BRACKET) { + lexemes.next() + intersection = true + buffer = -1 + } else { + lexemes.next() + if (firstInClass) { + // Skip "&&" at "[&&...]" or "[^&&...]" + result = processRangeExpression(false) + } else { + // Ignore "&&" at "[X&&]" ending where X != empty string + if (lexemes.currentChar != Lexer.CHAR_RIGHT_SQUARE_BRACKET) { + result.intersection(processRangeExpression(false)) + } + } + } + } else { + //treat '&' as a normal character + buffer = '&'.toInt() + } + } + + Lexer.CHAR_HYPHEN -> { + if (firstInClass + || lexemes.lookAhead == Lexer.CHAR_RIGHT_SQUARE_BRACKET + || lexemes.lookAhead == Lexer.CHAR_LEFT_SQUARE_BRACKET + || buffer < 0) { + // Treat the hypen as a normal character. + if (buffer >= 0) { + result.add(buffer) + } + buffer = '-'.toInt() + lexemes.next() + } else { + // A range. + lexemes.next() + var cur = lexemes.currentChar + + if (!lexemes.isSpecial + && (cur >= 0 + || lexemes.lookAhead == Lexer.CHAR_RIGHT_SQUARE_BRACKET + || lexemes.lookAhead == Lexer.CHAR_LEFT_SQUARE_BRACKET + || buffer < 0)) { + + try { + if (!Lexer.isLetter(cur)) { + cur = cur and 0xFFFF + } + result.add(buffer, cur) + } catch (e: Exception) { + throw PatternSyntaxException("Illegal character range", pattern, lexemes.curTokenIndex) + } + + lexemes.next() + buffer = -1 + } else { + throw PatternSyntaxException("Illegal character range", pattern, lexemes.curTokenIndex) + } + } + } + + Lexer.CHAR_CARET -> { + if (buffer >= 0) { + result.add(buffer) + } + buffer = '^'.toInt() + lexemes.next() + } + + 0 -> { + if (buffer >= 0) { + result.add(buffer) + } + val cs = lexemes.curSpecialToken as AbstractCharClass? + if (cs != null) { + result.add(cs) + buffer = -1 + } else { + buffer = 0 + } + + lexemes.next() + } + + else -> { + if (buffer >= 0) { + result.add(buffer) + } + buffer = lexemes.next() + } + } + + firstInClass = false + notClosed = lexemes.currentChar != Lexer.CHAR_RIGHT_SQUARE_BRACKET + } + if (notClosed) { + throw PatternSyntaxException("Missing ']'", pattern, lexemes.curTokenIndex) + } + if (buffer >= 0) { + result.add(buffer) + } + return result + } + + private fun processRangeSet(charClass: AbstractCharClass): AbstractSet { + if (charClass.hasLowHighSurrogates()) { + val lowHighSurrRangeSet = SurrogateRangeSet(charClass.classWithSurrogates()) + + if (charClass.mayContainSupplCodepoints) { + return CompositeRangeSet(SupplementaryRangeSet(charClass.classWithoutSurrogates(), hasFlag(CASE_INSENSITIVE)), lowHighSurrRangeSet) + } + + return CompositeRangeSet(RangeSet(charClass.classWithoutSurrogates(), hasFlag(CASE_INSENSITIVE)), lowHighSurrRangeSet) + } + + if (charClass.mayContainSupplCodepoints) { + return SupplementaryRangeSet(charClass, hasFlag(CASE_INSENSITIVE)) + } + + return RangeSet(charClass, hasFlag(CASE_INSENSITIVE)) + } + + private fun processCharSet(ch: Int): AbstractSet { + val isSupplCodePoint = Char.isSupplementaryCodePoint(ch) + + return when { + isSupplCodePoint -> SequenceSet(String(Char.toChars(ch), 0, 2), hasFlag(CASE_INSENSITIVE)) + ch.toChar().isLowSurrogate() -> LowSurrogateCharSet(ch.toChar()) + ch.toChar().isHighSurrogate() -> HighSurrogateCharSet(ch.toChar()) + else -> CharSet(ch.toChar(), hasFlag(CASE_INSENSITIVE)) + } + } + + companion object { + //TODO: Use RegexOption enum here. + // Flags. + /** + * This constant specifies that a pattern matches Unix line endings ('\n') + * only against the '.', '^', and '$' meta characters. + */ + val UNIX_LINES = 1 shl 0 + + /** + * This constant specifies that a `Pattern` is matched + * case-insensitively. That is, the patterns "a+" and "A+" would both match + * the string "aAaAaA". + */ + val CASE_INSENSITIVE = 1 shl 1 + + /** + * This constant specifies that a `Pattern` may contain whitespace or + * comments. Otherwise comments and whitespace are taken as literal + * characters. + */ + val COMMENTS = 1 shl 2 + + /** + * This constant specifies that the meta characters '^' and '$' match only + * the beginning and end end of an input line, respectively. Normally, they + * match the beginning and the end of the complete input. + */ + val MULTILINE = 1 shl 3 + + /** + * This constant specifies that the whole `Pattern` is to be taken + * literally, that is, all meta characters lose their meanings. + */ + val LITERAL = 1 shl 4 + + /** + * This constant specifies that the '.' meta character matches arbitrary + * characters, including line endings, which is normally not the case. + */ + val DOTALL = 1 shl 5 + + /** + * This constant specifies that a character in a `Pattern` and a + * character in the input string only match if they are canonically + * equivalent. + */ + val CANON_EQ = 1 shl 6 + + /** Max number of back references supported. */ + internal val BACK_REF_NUMBER = 10 + + /** A bit mask that includes all defined match flags */ + internal val flagsBitMask = Pattern.UNIX_LINES or + Pattern.CASE_INSENSITIVE or + Pattern.COMMENTS or + Pattern.MULTILINE or + Pattern.LITERAL or + Pattern.DOTALL or + Pattern.CANON_EQ + + + /** + * Quotes a given string using "\Q" and "\E", so that all other meta-characters lose their special meaning. + * If the string is used for a `Pattern` afterwards, it can only be matched literally. + */ + fun quote(s: String): String { + return StringBuilder() + .append("\\Q") + .append(s.replace("\\E", "\\E\\\\E\\Q")) + .append("\\E").toString() + } + } +} + diff --git a/kotlin-native/runtime/src/main/kotlin/kotlin/text/regex/Quantifier.kt b/kotlin-native/runtime/src/main/kotlin/kotlin/text/regex/Quantifier.kt new file mode 100644 index 00000000000..8532dcd51ba --- /dev/null +++ b/kotlin-native/runtime/src/main/kotlin/kotlin/text/regex/Quantifier.kt @@ -0,0 +1,58 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package kotlin.text.regex + +import kotlin.IllegalArgumentException + +/** + * Represents RE quantifier; contains two fields responsible for min and max number of repetitions. + * -1 as a maximum number of repetition represents infinity(i.e. +,*). + */ +internal class Quantifier(val min: Int, val max: Int = min) : SpecialToken() { + + init { + if (min < 0 || max < -1) { + throw IllegalArgumentException("Incorrect quantifier value: $this") + } + } + + override fun toString() = "{$min, ${if (max == INF) "" else max}}" + + override val type: Type = SpecialToken.Type.QUANTIFIER + + companion object { + val starQuantifier = Quantifier(0, -1) + val plusQuantifier = Quantifier(1, -1) + val altQuantifier = Quantifier(0, 1) + + val INF = -1 + + fun fromLexerToken(token: Int) = when(token) { + Lexer.QUANT_STAR, Lexer.QUANT_STAR_P, Lexer.QUANT_STAR_R -> starQuantifier + Lexer.QUANT_ALT, Lexer.QUANT_ALT_P, Lexer.QUANT_ALT_R -> altQuantifier + Lexer.QUANT_PLUS, Lexer.QUANT_PLUS_P, Lexer.QUANT_PLUS_R -> plusQuantifier + else -> throw IllegalArgumentException("Unknown quantifier token: $token") + } + } +} + diff --git a/kotlin-native/runtime/src/main/kotlin/kotlin/text/regex/sets/AbstractSet.kt b/kotlin-native/runtime/src/main/kotlin/kotlin/text/regex/sets/AbstractSet.kt new file mode 100644 index 00000000000..897b4d61f9b --- /dev/null +++ b/kotlin-native/runtime/src/main/kotlin/kotlin/text/regex/sets/AbstractSet.kt @@ -0,0 +1,159 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package kotlin.text.regex + +import kotlin.AssertionError + +/** Basic class for sets which have no complex next node handling. */ +internal abstract class SimpleSet : AbstractSet { + override var next: AbstractSet = dummyNext + constructor() + constructor(type : Int): super(type) +} + +/** + * Basic class for nodes, representing given regular expression. + * Note: (Almost) All the classes representing nodes has 'set' suffix. + */ +internal abstract class AbstractSet(val type: Int = 0) { + + companion object { + const val TYPE_LEAF = 1 shl 0 + const val TYPE_FSET = 1 shl 1 + const val TYPE_QUANT = 1 shl 3 + const val TYPE_DOTSET = 0x80000000.toInt() or '.'.toInt() + + val dummyNext = object : AbstractSet() { + override var next: AbstractSet + get() = throw AssertionError("This method is not expected to be called.") + @Suppress("UNUSED_PARAMETER") + set(value) {} + override fun matches(startIndex: Int, testString: CharSequence, matchResult: MatchResultImpl) = + throw AssertionError("This method is not expected to be called.") + override fun hasConsumed(matchResult: MatchResultImpl): Boolean = + throw AssertionError("This method is not expected to be called.") + override fun processSecondPassInternal(): AbstractSet = this + override fun processSecondPass(): AbstractSet = this + } + } + + var secondPassVisited = false + abstract var next: AbstractSet + + protected open val name: String + get() = "" + + /** + * Checks if this node matches in given position and recursively call + * next node matches on positive self match. Returns positive integer if + * entire match succeed, negative otherwise. + * @param startIndex - string index to start from. + * @param testString - input string. + * @param matchResult - MatchResult to sore result into. + * @return -1 if match fails or n > 0; + */ + abstract fun matches(startIndex: Int, testString: CharSequence, matchResult: MatchResultImpl): Int + + /** + * Attempts to apply pattern starting from this set/startIndex; returns + * index this search was started from, if value is negative, this means that + * this search didn't succeed, additional information could be obtained via + * matchResult. + * + * Note: this is default implementation for find method, it's based on + * matches, subclasses do not have to override find method unless + * more effective find method exists for a particular node type + * (sequence, i.e. substring, for example). Same applies for find back + * method. + * + * @param startIndex - starting index. + * @param testString - string to search in. + * @param matchResult - result of the match. + * @return last searched index. + */ + open fun find(startIndex: Int, testString: CharSequence, matchResult: MatchResultImpl): Int + = (startIndex..testString.length).firstOrNull { index -> matches(index, testString, matchResult) >= 0 } + ?: -1 + + /** + * @param leftLimit - an index, to finish search back (left limit, inclusive). + * @param rightLimit - an index to start search from (right limit, exclusive). + * @param testString - test string. + * @param matchResult - match result. + * @return an index to start back search next time if this search fails(new left bound); + * if this search fails the value is negative. + */ + open fun findBack(leftLimit: Int, rightLimit: Int, testString: CharSequence, matchResult: MatchResultImpl): Int + = (rightLimit downTo leftLimit).firstOrNull { index -> matches(index, testString, matchResult) >= 0 } + ?: -1 + + /** + * Returns true, if this node has consumed any characters during + * positive match attempt, for example node representing character always + * consumes one character if it matches. If particular node matches + * empty sting this method will return false. + * + * @param matchResult - match result; + * @return true if the node consumes any character and false otherwise. + */ + abstract fun hasConsumed(matchResult: MatchResultImpl): Boolean + + /** + * Returns true if the given node intersects with this one, false otherwise. + * This method is being used for quantifiers construction, lets consider the + * following regular expression (a|b)*ccc. (a|b) does not intersects with "ccc" + * and thus can be quantified greedily (w/o kickbacks), like *+ instead of *. + + * @param set - A node the intersection is checked for. Usually a previous node. + * @return true if the given node intersects with this one, false otherwise. + */ + open fun first(set: AbstractSet): Boolean = true + + /** + * This method is used for replacement backreferenced sets. + * + * @return null if current node need not to be replaced, + * [JointSet] which is replacement of current node otherwise. + */ + open fun processBackRefReplacement(): JointSet? { + return null + } + + /** + * This method performs the second pass without checking if it's already performed or not. + */ + protected open fun processSecondPassInternal(): AbstractSet { + if (!next.secondPassVisited) { + this.next = next.processSecondPass() + } + return processBackRefReplacement() ?: this + } + + /** + * This method is used for traversing nodes after the first stage of compilation. + */ + open fun processSecondPass(): AbstractSet { + secondPassVisited = true + return processSecondPassInternal() + } +} \ No newline at end of file diff --git a/kotlin-native/runtime/src/main/kotlin/kotlin/text/regex/sets/AtomicJointSet.kt b/kotlin-native/runtime/src/main/kotlin/kotlin/text/regex/sets/AtomicJointSet.kt new file mode 100644 index 00000000000..a3fcbaa19eb --- /dev/null +++ b/kotlin-native/runtime/src/main/kotlin/kotlin/text/regex/sets/AtomicJointSet.kt @@ -0,0 +1,50 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package kotlin.text.regex + +/** + * This class represent atomic group (?>X), once X matches, this match become unchangeable till the end of the match. + */ +open internal class AtomicJointSet(children: List, fSet: FSet) : NonCapturingJointSet(children, fSet) { + + /** Returns startIndex+shift, the next position to match */ + override fun matches(startIndex: Int, testString: CharSequence, matchResult: MatchResultImpl): Int { + val start = matchResult.getConsumed(groupIndex) + matchResult.setConsumed(groupIndex, startIndex) + children.forEach { + val shift = it.matches(startIndex, testString, matchResult) + if (shift >= 0) { + // AtomicFset always returns true, but saves the index to run this next.match() from; + return next.matches((fSet as AtomicFSet).index, testString, matchResult) + } + } + + matchResult.setConsumed(groupIndex, start) + return -1 + } + + override val name: String + get() = "AtomicJointSet" + + override var next: AbstractSet = dummyNext +} diff --git a/kotlin-native/runtime/src/main/kotlin/kotlin/text/regex/sets/BackReferenceSet.kt b/kotlin-native/runtime/src/main/kotlin/kotlin/text/regex/sets/BackReferenceSet.kt new file mode 100644 index 00000000000..8a94fb45aac --- /dev/null +++ b/kotlin-native/runtime/src/main/kotlin/kotlin/text/regex/sets/BackReferenceSet.kt @@ -0,0 +1,97 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package kotlin.text.regex + +/** + * Back reference node; + */ +open internal class BackReferenceSet(val referencedGroup: Int, val consCounter: Int, val ignoreCase: Boolean = false) + : SimpleSet() { + + + override fun matches(startIndex: Int, testString: CharSequence, matchResult: MatchResultImpl): Int { + val groupValue = getReferencedGroupValue(matchResult) + + if (groupValue == null || startIndex + groupValue.length > testString.length) { + return -1 + } + + if (testString.startsWith(groupValue, startIndex, ignoreCase)) { + matchResult.setConsumed(consCounter, groupValue.length) + return next.matches(startIndex + groupValue.length, testString, matchResult) + } + return -1 + } + + override fun find(startIndex: Int, testString: CharSequence, matchResult: MatchResultImpl): Int { + val groupValue = getReferencedGroupValue(matchResult) + if (groupValue == null || startIndex + groupValue.length > testString.length) { + return -1 + } + + var index = startIndex + while (index <= testString.length) { + index = testString.indexOf(groupValue, index, ignoreCase) + if (index < 0) { + return -1 + } + if (index < testString.length + && next.matches(index + groupValue.length, testString, matchResult) >=0) { + return index + } + index++ + } + return -1 + } + + override fun findBack(leftLimit: Int, rightLimit: Int, testString: CharSequence, matchResult: MatchResultImpl): Int { + val groupValue = getReferencedGroupValue(matchResult) + if (groupValue == null || leftLimit + groupValue.length > rightLimit) { + return -1 + } + + var index = rightLimit + while (index >= leftLimit) { + index = testString.lastIndexOf(groupValue, index, ignoreCase) + if (index < 0) { + return -1 + } + if (index >= 0 && next.matches(index + groupValue.length, testString, matchResult) >= 0) { + return index + } + index-- + } + return -1 + } + + + protected fun getReferencedGroupValue(matchResult: MatchResultImpl) = matchResult.group(referencedGroup) + override val name: String + get() = "back reference: $referencedGroup" + + override fun hasConsumed(matchResult: MatchResultImpl): Boolean { + val result = matchResult.getConsumed(consCounter) != 0 + matchResult.setConsumed(consCounter, -1) + return result + } +} diff --git a/kotlin-native/runtime/src/main/kotlin/kotlin/text/regex/sets/CharSet.kt b/kotlin-native/runtime/src/main/kotlin/kotlin/text/regex/sets/CharSet.kt new file mode 100644 index 00000000000..76dce2f6e6e --- /dev/null +++ b/kotlin-native/runtime/src/main/kotlin/kotlin/text/regex/sets/CharSet.kt @@ -0,0 +1,88 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package kotlin.text.regex + +/** + * Represents node accepting single character. + */ +open internal class CharSet(char: Char, val ignoreCase: Boolean = false) : LeafSet() { + + // We use only low case characters when working in case insensitive mode. + val char: Char = if (ignoreCase) char.toLowerCase() else char + + // Overrides ======================================================================================================= + + override fun accepts(startIndex: Int, testString: CharSequence): Int { + if (ignoreCase) { + return if (this.char == testString[startIndex].toLowerCase()) 1 else -1 + } else { + return if (this.char == testString[startIndex]) 1 else -1 + } + } + + override fun find(startIndex: Int, testString: CharSequence, matchResult: MatchResultImpl): Int { + var index = startIndex + while (index < testString.length) { + index = testString.indexOf(char, index, ignoreCase) + if (index < 0) { + return -1 + } + if (next.matches(index + charCount, testString, matchResult) >= 0) { + return index + } + index++ + } + return -1 + } + + override fun findBack(leftLimit: Int, rightLimit: Int, testString: CharSequence, matchResult: MatchResultImpl): Int { + var index = rightLimit + while (index >= leftLimit) { + index = testString.lastIndexOf(char, index, ignoreCase) + if (index < 0) { + return -1 + } + if (next.matches(index + charCount, testString, matchResult) >= 0) { + return index + } + index-- + } + return -1 + } + + override val name: String + get()= char.toString() + + override fun first(set: AbstractSet): Boolean { + if (ignoreCase) { + return super.first(set) + } + return when (set) { + is CharSet -> set.char == char + is RangeSet -> set.accepts(0, char.toString()) > 0 + is SupplementaryCharSet -> false + is SupplementaryRangeSet -> set.contains(char) + else -> true + } + } +} \ No newline at end of file diff --git a/kotlin-native/runtime/src/main/kotlin/kotlin/text/regex/sets/CompositeRangeSet.kt b/kotlin-native/runtime/src/main/kotlin/kotlin/text/regex/sets/CompositeRangeSet.kt new file mode 100644 index 00000000000..c6b4b57a168 --- /dev/null +++ b/kotlin-native/runtime/src/main/kotlin/kotlin/text/regex/sets/CompositeRangeSet.kt @@ -0,0 +1,122 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* + * + * Portions, Copyright © 1991-2005 Unicode, Inc. The following applies to Unicode. + * + * COPYRIGHT AND PERMISSION NOTICE + * + * Copyright © 1991-2005 Unicode, Inc. All rights reserved. Distributed under + * the Terms of Use in http://www.unicode.org/copyright.html. Permission is + * hereby granted, free of charge, to any person obtaining a copy of the + * Unicode data files and any associated documentation (the "Data Files") + * or Unicode software and any associated documentation (the "Software") + * to deal in the Data Files or Software without restriction, including without + * limitation the rights to use, copy, modify, merge, publish, distribute, + * and/or sell copies of the Data Files or Software, and to permit persons + * to whom the Data Files or Software are furnished to do so, provided that + * (a) the above copyright notice(s) and this permission notice appear with + * all copies of the Data Files or Software, (b) both the above copyright + * notice(s) and this permission notice appear in associated documentation, + * and (c) there is clear notice in each modified Data File or in the Software + * as well as in the documentation associated with the Data File(s) or Software + * that the data or software has been modified. + + * THE DATA FILES AND SOFTWARE ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY + * KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT + * OF THIRD PARTY RIGHTS. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR HOLDERS + * INCLUDED IN THIS NOTICE BE LIABLE FOR ANY CLAIM, OR ANY SPECIAL INDIRECT + * OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS + * OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR + * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THE DATA FILES OR SOFTWARE. + * + * Except as contained in this notice, the name of a copyright holder shall + * not be used in advertising or otherwise to promote the sale, use or other + * dealings in these Data Files or Software without prior written + * authorization of the copyright holder. + * + * 2. Additional terms from the Database: + * + * Copyright © 1995-1999 Unicode, Inc. All Rights reserved. + * + * Disclaimer + * + * The Unicode Character Database is provided as is by Unicode, Inc. + * No claims are made as to fitness for any particular purpose. No warranties + * of any kind are expressed or implied. The recipient agrees to determine + * applicability of information provided. If this file has been purchased + * on magnetic or optical media from Unicode, Inc., the sole remedy for any claim + * will be exchange of defective media within 90 days of receipt. This disclaimer + * is applicable for all other data files accompanying the Unicode Character Database, + * some of which have been compiled by the Unicode Consortium, and some of which + * have been supplied by other sources. + * + * Limitations on Rights to Redistribute This Data + * + * Recipient is granted the right to make copies in any form for internal + * distribution and to freely use the information supplied in the creation of + * products supporting the UnicodeTM Standard. The files in + * the Unicode Character Database can be redistributed to third parties or other + * organizations (whether for profit or not) as long as this notice and the disclaimer + * notice are retained. Information can be extracted from these files and used + * in documentation or programs, as long as there is an accompanying notice + * indicating the source. + */ + +package kotlin.text.regex + +/** + * This class is used to split the range that contains surrogate characters into two ranges: + * the first consisting of these surrogate characters and the second consisting of all others characters + * from the parent range. This class represents the parent range split in such a manner. + */ +internal class CompositeRangeSet(/* range without surrogates */ val withoutSurrogates: AbstractSet, + /* range containing surrogates only */ val surrogates: AbstractSet) : SimpleSet() { + + override var next: AbstractSet = dummyNext + get() = field + set(next) { + field = next + surrogates.next = next + withoutSurrogates.next = next + } + + override fun matches(startIndex: Int, testString: CharSequence, matchResult: MatchResultImpl): Int { + var result = withoutSurrogates.matches(startIndex, testString, matchResult) + if (result < 0) { + result = surrogates.matches(startIndex, testString, matchResult) + } + return result + } + + override val name: String + get() = "CompositeRangeSet: " + " " + withoutSurrogates + " " + surrogates + + override fun hasConsumed(matchResult: MatchResultImpl): Boolean = true + + override fun first(set: AbstractSet): Boolean { + return true + } +} diff --git a/kotlin-native/runtime/src/main/kotlin/kotlin/text/regex/sets/DecomposedCharSet.kt b/kotlin-native/runtime/src/main/kotlin/kotlin/text/regex/sets/DecomposedCharSet.kt new file mode 100644 index 00000000000..ec0e70a9221 --- /dev/null +++ b/kotlin-native/runtime/src/main/kotlin/kotlin/text/regex/sets/DecomposedCharSet.kt @@ -0,0 +1,160 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package kotlin.text.regex + +/** + * Decomposes the given codepoint. Saves the decomposition into [outputCodepoints] array starting with [fromIndex]. + * Returns the length of the decomposition. + */ +@SymbolName("Kotlin_text_regex_decomposeCodePoint") +external private fun decomposeCodePoint(codePoint: Int, outputCodePoints: IntArray, fromIndex: Int): Int + +/** Represents canonical decomposition of Unicode character. Is used when CANON_EQ flag of Pattern class is specified. */ +open internal class DecomposedCharSet( + /** Decomposition of the Unicode codepoint */ + private val decomposedChar: IntArray, + /** Length of useful part of decomposedChar decomposedCharLength <= decomposedChar.length */ + private val decomposedCharLength: Int) : SimpleSet() { + + /** Contains information about number of chars that were read for a codepoint last time */ + private var readCharsForCodePoint = 1 + + /** UTF-16 encoding of decomposedChar */ + private val decomposedCharUTF16: String by lazy { + val strBuff = StringBuilder() + + for (i in 0..decomposedCharLength - 1) { + strBuff.append(Char.toChars(decomposedChar[i])) + } + return@lazy strBuff.toString() + } + + override fun matches(startIndex: Int, testString: CharSequence, matchResult: MatchResultImpl): Int { + var strIndex = startIndex + val rightBound = testString.length + + if (strIndex >= rightBound) { + return -1 + } + + // We read testString and decompose it gradually to compare with this decomposedChar at position strIndex + var curChar = codePointAt(strIndex, testString, rightBound) + strIndex += readCharsForCodePoint + var readCodePoints = 0 + var i = 0 + // All decompositions have length that is less or equal Lexer.MAX_DECOMPOSITION_LENGTH + var decomposedCodePoint: IntArray = IntArray(Lexer.MAX_DECOMPOSITION_LENGTH) + readCodePoints += decomposeCodePoint(curChar, decomposedCodePoint, readCodePoints) + + if (strIndex < rightBound) { + curChar = codePointAt(strIndex, testString, rightBound) + + // Read testString until we met a decomposed char boundary and decompose obtained portion of testString. + while (readCodePoints < Lexer.MAX_DECOMPOSITION_LENGTH && !Lexer.isDecomposedCharBoundary(curChar)) { + + if (!Lexer.hasDecompositionNonNullCanClass(curChar)) { + decomposedCodePoint[readCodePoints++] = curChar + } else { + /* + * A few codepoints have decompositions and non null canonical classes, we have to take them into + * consideration, but general rule is: if canonical class != 0 then no decomposition + */ + readCodePoints += decomposeCodePoint(curChar, decomposedCodePoint, readCodePoints) + } + + strIndex += readCharsForCodePoint + + if (strIndex < rightBound) { + curChar = codePointAt(strIndex, testString, rightBound) + } else { + break + } + } + } + + // Some optimization since length of decomposed char is <= 3 usually + when (readCodePoints) { + 0, 1, 2 -> {} + + 3 -> { + var i1 = Lexer.getCanonicalClass(decomposedCodePoint[1]) + val i2 = Lexer.getCanonicalClass(decomposedCodePoint[2]) + + if (i2 != 0 && i1 > i2) { + i1 = decomposedCodePoint[1] + decomposedCodePoint[1] = decomposedCodePoint[2] + decomposedCodePoint[2] = i1 + } + } + + else -> decomposedCodePoint = Lexer.getCanonicalOrder(decomposedCodePoint, readCodePoints) + } + + // Compare decomposedChar with decomposed char that was just read from testString + if (readCodePoints != decomposedCharLength) { + return -1 + } + + if ((0 until readCodePoints).firstOrNull { decomposedCodePoint[i] != decomposedChar[i] } != null) { + return -1 + } + return next.matches(strIndex, testString, matchResult) + } + + override val name: String + get() = "decomposed char: $decomposedChar" + + /** Reads Unicode codepoint from [testString] starting from [strIndex] until [rightBound]. */ + fun codePointAt(strIndex: Int, testString: CharSequence, rightBound: Int): Int { + var index = strIndex + + // We store information about number of codepoints we read at variable readCharsForCodePoint. + val curChar: Int + readCharsForCodePoint = 1 + if (index < rightBound - 1) { + val high = testString[index++] + val low = testString[index] + + if (Char.isSurrogatePair(high, low)) { + curChar = Char.toCodePoint(high, low) + readCharsForCodePoint = 2 + } else { + curChar = high.toInt() + } + } else { + curChar = testString[index].toInt() + } + + return curChar + } + + override fun first(set: AbstractSet): Boolean { + return if (set is DecomposedCharSet) + set.decomposedChar.contentEquals(decomposedChar) + else + true + } + + override fun hasConsumed(matchResult: MatchResultImpl): Boolean = true +} + diff --git a/kotlin-native/runtime/src/main/kotlin/kotlin/text/regex/sets/DotQuantifierSet.kt b/kotlin-native/runtime/src/main/kotlin/kotlin/text/regex/sets/DotQuantifierSet.kt new file mode 100644 index 00000000000..8133f440cb4 --- /dev/null +++ b/kotlin-native/runtime/src/main/kotlin/kotlin/text/regex/sets/DotQuantifierSet.kt @@ -0,0 +1,103 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package kotlin.text.regex + +/** + * Special node for ".*" construction. + * The main idea here is to find line terminator and try to find the rest of the construction from this point. + */ +// TODO: Add optimized implementation for '.+' case +internal class DotQuantifierSet( + innerSet: AbstractSet, + next: AbstractSet, + type: Int, + val lineTerminator: AbstractLineTerminator, + val matchLineTerminator: Boolean = false +) : QuantifierSet(innerSet, next, type) { + + override fun matches(startIndex: Int, testString: CharSequence, matchResult: MatchResultImpl): Int { + val rightBound = testString.length + val startSearch = if (matchLineTerminator) rightBound else testString.findLineTerminator(startIndex, rightBound) + + if (startSearch <= startIndex) { + return if (type.toChar() == '+') { + -1 + } else { + next.matches(startIndex, testString, matchResult) + } + } + val result = next.findBack(startIndex, startSearch, testString, matchResult) + if (type.toChar() == '+' && result == startIndex) { + return -1 + } + return result + } + + override fun find(startIndex: Int, testString: CharSequence, matchResult: MatchResultImpl): Int { + val rightBound = testString.length + if (matchLineTerminator) { + val foundIndex = next.findBack(startIndex, rightBound, testString, matchResult) + if (foundIndex >= 0 && !(type.toChar() == '+' && foundIndex == startIndex)) { + return startIndex + } else { + return -1 + } + } else { + // 1. find first occurrence of the searched pattern. + var nextFound = next.find(startIndex, testString, matchResult) + if (nextFound < 0) { + return -1 + } + + // 2. Check if we have other occurrences till the end of line (because .* is greedy and we need the last one). + val nextFoundLast = next.findBack(nextFound, + testString.findLineTerminator(nextFound, rightBound), + testString, matchResult) + nextFound = maxOf(nextFound, nextFoundLast) + + // 3. Find the left boundary of this search. + val leftBound = findBackLineTerminator(startIndex, nextFound, testString) + if (type.toChar() == '+' && leftBound + 1 == nextFound) { + return -1 + } + return leftBound + 1 + } + } + + /** + * Find the first line terminator between [from] (inclusive) and [to] (exclusive) indices. + * Returns [to] if no terminator found. + */ + private fun CharSequence.findLineTerminator(from: Int, to: Int): Int = + (from until to).firstOrNull { lineTerminator.isLineTerminator(this[it]) } ?: to + + /** + * Find the first line terminator between [from] (inclusive) and [to] (exclusive) indices. + * Returns [from - 1] if no terminator found. + */ + private fun findBackLineTerminator(from: Int, to: Int, testString: CharSequence): Int = + (from until to).lastOrNull { lineTerminator.isLineTerminator(testString[it]) } ?: from - 1 + + override val name: String + get() = ".*" +} diff --git a/kotlin-native/runtime/src/main/kotlin/kotlin/text/regex/sets/DotSet.kt b/kotlin-native/runtime/src/main/kotlin/kotlin/text/regex/sets/DotSet.kt new file mode 100644 index 00000000000..ec5174194e2 --- /dev/null +++ b/kotlin-native/runtime/src/main/kotlin/kotlin/text/regex/sets/DotSet.kt @@ -0,0 +1,58 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package kotlin.text.regex + +/** + * Node accepting any character except line terminators. + */ +internal class DotSet(val lt: AbstractLineTerminator, val matchLineTerminator: Boolean) + : SimpleSet(AbstractSet.TYPE_DOTSET) { + + override fun matches(startIndex: Int, testString: CharSequence, matchResult: MatchResultImpl): Int { + val rightBound = testString.length + if (startIndex >= rightBound) { + return -1 + } + + val high = testString[startIndex] + if (high.isHighSurrogate() && startIndex + 2 <= rightBound) { + val low = testString[startIndex + 1] + if (Char.isSurrogatePair(high, low)) { + if (!matchLineTerminator && lt.isLineTerminator(Char.toCodePoint(high, low))) { + return -1 + } else { + return next.matches(startIndex + 2, testString, matchResult) + } + } + } + if (!matchLineTerminator && lt.isLineTerminator(high)) { + return -1 + } else { + return next.matches(startIndex + 1, testString, matchResult) + } + } + + override fun hasConsumed(matchResult: MatchResultImpl): Boolean = true + override val name: String + get() = "." +} diff --git a/kotlin-native/runtime/src/main/kotlin/kotlin/text/regex/sets/EOISet.kt b/kotlin-native/runtime/src/main/kotlin/kotlin/text/regex/sets/EOISet.kt new file mode 100644 index 00000000000..d37e1bba694 --- /dev/null +++ b/kotlin-native/runtime/src/main/kotlin/kotlin/text/regex/sets/EOISet.kt @@ -0,0 +1,40 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package kotlin.text.regex + +/** + * Represents end of input '\z', i.e. matches only character after the last one; + */ +internal class EOISet : SimpleSet() { + + override fun matches(startIndex: Int, testString: CharSequence, matchResult: MatchResultImpl): Int { + if (startIndex < testString.length) { + return -1 + } + return next.matches(startIndex, testString, matchResult) + } + + override fun hasConsumed(matchResult: MatchResultImpl): Boolean = false + override val name: String + get() = "EOI" +} diff --git a/kotlin-native/runtime/src/main/kotlin/kotlin/text/regex/sets/EOLSet.kt b/kotlin-native/runtime/src/main/kotlin/kotlin/text/regex/sets/EOLSet.kt new file mode 100644 index 00000000000..3be25f4a10e --- /dev/null +++ b/kotlin-native/runtime/src/main/kotlin/kotlin/text/regex/sets/EOLSet.kt @@ -0,0 +1,56 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package kotlin.text.regex + +/** + * Represents a node for a '$' sign. + * Note: In Kotlin we use only the "anchoring bounds" mode when "$" matches the end of a match region. + * See: http://docs.oracle.com/javase/8/docs/api/java/util/regex/Matcher.html#useAnchoringBounds-boolean- + */ +internal class EOLSet(val consCounter: Int, val lt: AbstractLineTerminator, val multiline: Boolean = false) : SimpleSet() { + + override fun matches(startIndex: Int, testString: CharSequence, matchResult: MatchResultImpl): Int { + val rightBound = testString.length + val remainingChars = rightBound - startIndex + + when { + startIndex >= rightBound || + remainingChars == 1 && lt.isLineTerminator(testString[startIndex]) || + remainingChars == 2 && lt.isLineTerminatorPair(testString[startIndex], testString[startIndex+1]) || + multiline && lt.isLineTerminator(testString[startIndex]) -> { + matchResult.setConsumed(consCounter, 0) + return next.matches(startIndex, testString, matchResult) + } + } + return -1 + } + + override fun hasConsumed(matchResult: MatchResultImpl): Boolean { + val result = matchResult.getConsumed(consCounter) != 0 + matchResult.setConsumed(consCounter, -1) + return result + } + + override val name: String + get()= "" +} diff --git a/kotlin-native/runtime/src/main/kotlin/kotlin/text/regex/sets/EmptySet.kt b/kotlin-native/runtime/src/main/kotlin/kotlin/text/regex/sets/EmptySet.kt new file mode 100644 index 00000000000..2e507eee5a3 --- /dev/null +++ b/kotlin-native/runtime/src/main/kotlin/kotlin/text/regex/sets/EmptySet.kt @@ -0,0 +1,72 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package kotlin.text.regex + +/** + * Valid constant zero character match. + */ +internal class EmptySet(override var next: AbstractSet) : LeafSet() { + + override val charCount = 0 + + override fun accepts(startIndex: Int, testString: CharSequence): Int = 0 + + override fun find(startIndex: Int, testString: CharSequence, matchResult: MatchResultImpl): Int { + for (index in startIndex..testString.length) { + if (index < testString.length) { + if (testString[index].isLowSurrogate() && + index > 0 && testString[index - 1].isHighSurrogate()) { + continue + } + } + if (next.matches(index, testString, matchResult) >= 0) { + return index + } + } + return -1 + } + + override fun findBack(leftLimit: Int, rightLimit: Int, testString: CharSequence, matchResult: MatchResultImpl): Int { + for (index in rightLimit downTo leftLimit) { + if (index < testString.length) { + if (testString[index].isLowSurrogate() && + index > 0 && testString[index - 1].isHighSurrogate()) { + continue + } + } + if (next.matches(index, testString, matchResult) >= 0) { + return index + } + } + return -1 + } + + + override val name: String + get()= "" + + override fun hasConsumed(matchResult: MatchResultImpl): Boolean { + return false + } + +} diff --git a/kotlin-native/runtime/src/main/kotlin/kotlin/text/regex/sets/FSets.kt b/kotlin-native/runtime/src/main/kotlin/kotlin/text/regex/sets/FSets.kt new file mode 100644 index 00000000000..701b70f65ca --- /dev/null +++ b/kotlin-native/runtime/src/main/kotlin/kotlin/text/regex/sets/FSets.kt @@ -0,0 +1,159 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package kotlin.text.regex + +/** + * The node which marks end of the particular group. + */ +open internal class FSet(val groupIndex: Int) : SimpleSet() { + + var isBackReferenced = false + + override fun matches(startIndex: Int, testString: CharSequence, matchResult: MatchResultImpl): Int { + val oldEnd = matchResult.getEnd(groupIndex) + matchResult.setEnd(groupIndex, startIndex) + val shift = next.matches(startIndex, testString, matchResult) + if (shift < 0) { + matchResult.setEnd(groupIndex, oldEnd) + } + return shift + } + + override fun hasConsumed(matchResult: MatchResultImpl): Boolean = false + override val name: String + get() = "fSet" + + override fun processSecondPass(): FSet { + val result = super.processSecondPass() + assert(result == this) + return this + } + + /** + * Marks the end of the particular group and not take into account possible + * kickbacks (required for atomic groups, for instance) + */ + internal class PossessiveFSet : SimpleSet() { + override fun matches(startIndex: Int, testString: CharSequence, matchResult: MatchResultImpl): Int { + return startIndex + } + + override fun hasConsumed(matchResult: MatchResultImpl): Boolean { + return false + } + + override val name: String + get() = "possessiveFSet" + } + + companion object { + var possessiveFSet = PossessiveFSet() + } +} + +/** + * Special construction which marks end of pattern. + */ +internal class FinalSet : FSet(0) { + + override fun matches(startIndex: Int, testString: CharSequence, + matchResult: MatchResultImpl): Int { + if (matchResult.mode == Regex.Mode.FIND || startIndex == testString.length) { + matchResult.setEnd(0, startIndex) + return startIndex + } + return -1 + } + + override val name: String + get() = "FinalSet" +} + +/** + * Non-capturing group closing node. + */ +internal class NonCapFSet(groupIndex: Int) : FSet(groupIndex) { + + override fun matches(startIndex: Int, testString: CharSequence, matchResult: MatchResultImpl): Int { + matchResult.setConsumed(groupIndex, startIndex - matchResult.getConsumed(groupIndex)) + return next.matches(startIndex, testString, matchResult) + } + + override val name: String + get() = "NonCapFSet" + + override fun hasConsumed(matchResult: MatchResultImpl): Boolean { + return false + } +} + +/** + * LookAhead FSet, always returns true + */ +internal class AheadFSet : FSet(-1) { + + override fun matches(startIndex: Int, testString: CharSequence, matchResult: MatchResultImpl): Int { + return startIndex + } + + override val name: String + get() = "AheadFSet" +} + +/** + * FSet for lookbehind constructs. Checks if string index saved by corresponding + * jointSet in "consumers" equals to current index and return current string + * index, return -1 otherwise. + + */ +internal class BehindFSet(groupIndex: Int) : FSet(groupIndex) { + + override fun matches(startIndex: Int, testString: CharSequence, matchResult: MatchResultImpl): Int { + val rightBound = matchResult.getConsumed(groupIndex) + return if (rightBound == startIndex) startIndex else -1 + } + + override val name: String + get() = "BehindFSet" +} + +/** + * Represents an end of an atomic group. + */ +internal class AtomicFSet(groupIndex: Int) : FSet(groupIndex) { + + var index: Int = 0 + + override fun matches(startIndex: Int, testString: CharSequence, matchResult: MatchResultImpl): Int { + matchResult.setConsumed(groupIndex, startIndex - matchResult.getConsumed(groupIndex)) + index = startIndex + return startIndex + } + + override val name: String + get() = "AtomicFSet" + + override fun hasConsumed(matchResult: MatchResultImpl): Boolean { + return false + } +} \ No newline at end of file diff --git a/kotlin-native/runtime/src/main/kotlin/kotlin/text/regex/sets/GroupQuantifierSet.kt b/kotlin-native/runtime/src/main/kotlin/kotlin/text/regex/sets/GroupQuantifierSet.kt new file mode 100644 index 00000000000..95fecf1149c --- /dev/null +++ b/kotlin-native/runtime/src/main/kotlin/kotlin/text/regex/sets/GroupQuantifierSet.kt @@ -0,0 +1,92 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package kotlin.text.regex + +/** + * Default quantifier over groups, in fact this type of quantifier is + * generally used for constructions we cant identify number of characters they + * consume. + + */ +open internal class GroupQuantifierSet( + val quantifier: Quantifier, + innerSet: AbstractSet, + next: AbstractSet, + type: Int, + val groupQuantifierIndex: Int // It's used to remember a number of the innerSet occurrences during the recursive search. +) : QuantifierSet(innerSet, next, type) { + + val max: Int get() = quantifier.max + val min: Int get() = quantifier.min + + // We call innerSet.matches here, if it succeeds it call next.matches where next is this QuantifierSet. + // So we have a recursive searching procedure. + override fun matches(startIndex: Int, testString: CharSequence, matchResult: MatchResultImpl): Int { + var enterCount = matchResult.enterCounters[groupQuantifierIndex] + + fun matchNext(): Int { + matchResult.enterCounters[groupQuantifierIndex] = 0 + val result = next.matches(startIndex, testString, matchResult) + matchResult.enterCounters[groupQuantifierIndex] = enterCount + return result + } + + if (!innerSet.hasConsumed(matchResult)) { + return matchNext() + } + + // Fast case: '*' or {0, } - no need to count occurrences. + if (min == 0 && max == Quantifier.INF) { + val nextIndex = innerSet.matches(startIndex, testString, matchResult) + return if (nextIndex < 0) { + matchNext() + } else { + nextIndex + } + } + + // can't go inner set; + if (max != Quantifier.INF && enterCount >= max) { + return matchNext() + } + + // go inner set; + matchResult.enterCounters[groupQuantifierIndex] = ++enterCount + val nextIndex = innerSet.matches(startIndex, testString, matchResult) + + return if (nextIndex < 0) { + matchResult.enterCounters[groupQuantifierIndex] = --enterCount + if (enterCount >= min) { + matchNext() + } else { + -1 + } + } else { + nextIndex + } + + } + + override val name: String + get() = quantifier.toString() +} diff --git a/kotlin-native/runtime/src/main/kotlin/kotlin/text/regex/sets/HangulDecomposedCharSet.kt b/kotlin-native/runtime/src/main/kotlin/kotlin/text/regex/sets/HangulDecomposedCharSet.kt new file mode 100644 index 00000000000..39a6101ceb5 --- /dev/null +++ b/kotlin-native/runtime/src/main/kotlin/kotlin/text/regex/sets/HangulDecomposedCharSet.kt @@ -0,0 +1,179 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package kotlin.text.regex + +import kotlin.text.* + +/** + * Represents canonical decomposition of Hangul syllable. Is used when + * CANON_EQ flag of Pattern class is specified. + */ +internal class HangulDecomposedCharSet( + /** + * Decomposed Hangul syllable. + */ + private val decomposedChar: CharArray, + /** + * Length of useful part of decomposedChar + * decomposedCharLength <= decomposedChar.length + */ + private val decomposedCharLength: Int) : SimpleSet() { + + /** + * String representing syllable + */ + private val decomposedCharUTF16: String by lazy { + String(decomposedChar, 0, decomposedChar.size) + } + + override val name: String + get() = "decomposed Hangul syllable: $decomposedCharUTF16" + + override fun matches(startIndex: Int, testString: CharSequence, matchResult: MatchResultImpl): Int { + var index = startIndex + + /* + * All decompositions for Hangul syllables have length that + * is less or equal Lexer.MAX_DECOMPOSITION_LENGTH + */ + val rightBound = testString.length + var SyllIndex = 0 + val decompSyllable = IntArray(Lexer + .MAX_HANGUL_DECOMPOSITION_LENGTH) + val decompCurSymb: IntArray? + var curSymb: Char + + /* + * For details about Hangul composition and decomposition see + * http://www.unicode.org/versions/Unicode4.0.0/ch03.pdf + * "3.12 Conjoining Jamo Behavior" + */ + var LIndex: Int + var VIndex = -1 + var TIndex = -1 + + if (index >= rightBound) { + return -1 + } + curSymb = testString[index++] + decompCurSymb = Lexer.getHangulDecomposition(curSymb.toInt()) + + if (decompCurSymb == null) { + + /* + * We deal with ordinary letter or sequence of jamos + * at index at testString. + */ + decompSyllable[SyllIndex++] = curSymb.toInt() + LIndex = curSymb.toInt() - Lexer.LBase + + if (LIndex < 0 || LIndex >= Lexer.LCount) { + + /* + * Ordinary letter, that doesn't match this + */ + return -1 + } + + if (index < rightBound) { + curSymb = testString[index] + VIndex = curSymb.toInt() - Lexer.VBase + } + + if (VIndex < 0 || VIndex >= Lexer.VCount) { + + /* + * Single L jamo doesn't compose Hangul syllable, + * so doesn't match + */ + return -1 + } + index++ + decompSyllable[SyllIndex++] = curSymb.toInt() + + if (index < rightBound) { + curSymb = testString[index] + TIndex = curSymb.toInt() - Lexer.TBase + } + + if (TIndex < 0 || TIndex >= Lexer.TCount) { + + /* + * We deal with LV syllable at testString, so + * compare it to this + */ + return if (decomposedCharLength == 2 + && decompSyllable[0] == decomposedChar[0].toInt() + && decompSyllable[1] == decomposedChar[1].toInt()) + next.matches(index, testString, matchResult) + else + -1 + } + index++ + decompSyllable[@Suppress("UNUSED_CHANGED_VALUE")SyllIndex++] = curSymb.toInt() + + /* + * We deal with LVT syllable at testString, so + * compare it to this + */ + return if (decomposedCharLength == 3 + && decompSyllable[0] == decomposedChar[0].toInt() + && decompSyllable[1] == decomposedChar[1].toInt() + && decompSyllable[2] == decomposedChar[2].toInt()) + next.matches(index, testString, matchResult) + else + -1 + } else { + + /* + * We deal with Hangul syllable at index at testString. + * So we decomposed it to compare with this. + */ + var i = 0 + + if (decompCurSymb.size != decomposedCharLength) { + return -1 + } + + while (i < decomposedCharLength) { + if (decompCurSymb[i] != decomposedChar[i].toInt()) { + return -1 + } + i++ + } + return next.matches(index, testString, matchResult) + } + } + + override fun first(set: AbstractSet): Boolean { + return if (set is HangulDecomposedCharSet) + set.decomposedCharUTF16 == decomposedCharUTF16 + else + true + } + + override fun hasConsumed(matchResult: MatchResultImpl): Boolean { + return true + } +} + diff --git a/kotlin-native/runtime/src/main/kotlin/kotlin/text/regex/sets/JointSet.kt b/kotlin-native/runtime/src/main/kotlin/kotlin/text/regex/sets/JointSet.kt new file mode 100644 index 00000000000..c1f09fd4d37 --- /dev/null +++ b/kotlin-native/runtime/src/main/kotlin/kotlin/text/regex/sets/JointSet.kt @@ -0,0 +1,82 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package kotlin.text.regex + +/** + * Represents group, which is alternation of other subexpression. + * One should think about "group" in this model as JointSet opening group and corresponding FSet closing group. + */ +open internal class JointSet(children: List, fSet: FSet) : AbstractSet() { + + protected var children: MutableList = mutableListOf().apply { addAll(children) } + + var fSet: FSet = fSet + protected set + + var groupIndex: Int = fSet.groupIndex + protected set + + /** + * Returns startIndex+shift, the next position to match + */ + override fun matches(startIndex: Int, testString: CharSequence, matchResult: MatchResultImpl): Int { + if (children.isEmpty()) { + return -1 + } + val oldStart = matchResult.getStart(groupIndex) + matchResult.setStart(groupIndex, startIndex) + children.forEach { + val shift = it.matches(startIndex, testString, matchResult) + if (shift >= 0) { + return shift + } + } + matchResult.setStart(groupIndex, oldStart) + return -1 + } + + override var next: AbstractSet + get() = fSet.next + set(next) { + fSet.next = next + } + + override val name: String + get() = "JointSet" + override fun first(set: AbstractSet): Boolean = children.any { it.first(set) } + + override fun hasConsumed(matchResult: MatchResultImpl): Boolean { + return !(matchResult.getEnd(groupIndex) >= 0 && matchResult.getStart(groupIndex) == matchResult.getEnd(groupIndex)) + } + + override fun processSecondPassInternal(): AbstractSet { + val fSet = this.fSet + if (!fSet.secondPassVisited) { + val newFSet = fSet.processSecondPass() + assert(newFSet == fSet) + } + + children.replaceAll { child -> if (!child.secondPassVisited) child.processSecondPass() else child } + return super.processSecondPassInternal() + } +} diff --git a/kotlin-native/runtime/src/main/kotlin/kotlin/text/regex/sets/LeafQuantifierSet.kt b/kotlin-native/runtime/src/main/kotlin/kotlin/text/regex/sets/LeafQuantifierSet.kt new file mode 100644 index 00000000000..2aa103bc235 --- /dev/null +++ b/kotlin-native/runtime/src/main/kotlin/kotlin/text/regex/sets/LeafQuantifierSet.kt @@ -0,0 +1,94 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package kotlin.text.regex + +import kotlin.RuntimeException + +/** + * Generalized greedy quantifier node over the leaf nodes. + * - a{n,m}; + * - a* == a{0, }; + * - a? == a{0, 1}; + * - a+ == a{1, }; + */ +open internal class LeafQuantifierSet(var quantifier: Quantifier, + innerSet: LeafSet, + next: AbstractSet, + type: Int +) : QuantifierSet(innerSet, next, type) { + + val leaf: LeafSet get() = super.innerSet as LeafSet + val min: Int get() = quantifier.min + val max: Int get() = quantifier.max + + override fun matches(startIndex: Int, testString: CharSequence, matchResult: MatchResultImpl): Int { + var index = startIndex + var occurrences = 0 + + // Process first occurrences of the sequence being looked for. + while (occurrences < min) { + if (index + leaf.charCount > testString.length) { + return -1 + } + + val shift = leaf.accepts(index, testString) + if (shift < 1) { + return -1 + } + index += shift + occurrences++ + } + + // Process occurrences between min and max. + while ((max == Quantifier.INF || occurrences < max) && index + leaf.charCount <= testString.length) { + val shift = leaf.accepts(index, testString) + if (shift < 1) { + break + } + index += shift + occurrences++ + } + + // Roll back if the next node does't match the remaining string. + while (occurrences >= min) { + val shift = next.matches(index, testString, matchResult) + if (shift >= 0) { + return shift + } + index -= leaf.charCount + occurrences-- + } + return -1 + } + + override val name: String + get() = quantifier.toString() + + override var innerSet: AbstractSet + get() = super.innerSet + set(innerSet) { + if (innerSet !is LeafSet) + throw RuntimeException("Internal Error") + super.innerSet = innerSet + } +} diff --git a/kotlin-native/runtime/src/main/kotlin/kotlin/text/regex/sets/LeafSet.kt b/kotlin-native/runtime/src/main/kotlin/kotlin/text/regex/sets/LeafSet.kt new file mode 100644 index 00000000000..26837e22ead --- /dev/null +++ b/kotlin-native/runtime/src/main/kotlin/kotlin/text/regex/sets/LeafSet.kt @@ -0,0 +1,55 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package kotlin.text.regex + +/** + * Base class for nodes representing leaf tokens of the RE, those who consumes fixed number of characters. + */ +internal abstract class LeafSet : SimpleSet(AbstractSet.TYPE_LEAF) { + + open val charCount = 1 + + /** Returns "shift", the number of accepted chars. Commonly internal function, but called by quantifiers. */ + abstract fun accepts(startIndex: Int, testString: CharSequence): Int + + /** + * Checks if we can enter this state and pass the control to the next one. + * Return positive value if match succeeds, negative otherwise. + */ + override fun matches(startIndex: Int, testString: CharSequence, matchResult: MatchResultImpl): Int { + if (startIndex + charCount > testString.length) { + return -1 + } + + val shift = accepts(startIndex, testString) // TODO: may be move the check above in accept function. + if (shift < 0) { + return -1 + } + + return next.matches(startIndex + shift, testString, matchResult) + } + + override fun hasConsumed(matchResult: MatchResultImpl): Boolean { + return true + } +} diff --git a/kotlin-native/runtime/src/main/kotlin/kotlin/text/regex/sets/LookAheadSets.kt b/kotlin-native/runtime/src/main/kotlin/kotlin/text/regex/sets/LookAheadSets.kt new file mode 100644 index 00000000000..4b26a0bb0b3 --- /dev/null +++ b/kotlin-native/runtime/src/main/kotlin/kotlin/text/regex/sets/LookAheadSets.kt @@ -0,0 +1,66 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package kotlin.text.regex + +/** + * Positive lookahead node. + */ +internal class PositiveLookAheadSet(children: List, fSet: FSet) : AtomicJointSet(children, fSet) { + + /** Returns startIndex+shift, the next position to match */ + override fun matches(startIndex: Int, testString: CharSequence, matchResult: MatchResultImpl): Int { + children.forEach { + val shift = it.matches(startIndex, testString, matchResult) + if (shift >= 0) { + // PosLookaheadFset always returns true, position remains the same next.match() from; + return next.matches(startIndex, testString, matchResult) + } + } + return -1 + } + + override fun hasConsumed(matchResult: MatchResultImpl): Boolean = true + override val name: String + get() = "PositiveLookaheadJointSet" +} + +/** + * Negative look ahead node. + */ +internal class NegativeLookAheadSet(children: List, fSet: FSet) : AtomicJointSet(children, fSet) { + + /** Returns startIndex+shift, the next position to match */ + override fun matches(startIndex: Int, testString: CharSequence, matchResult: MatchResultImpl): Int { + children.forEach { + if (it.matches(startIndex, testString, matchResult) >= 0) { + return -1 + } + } + + return next.matches(startIndex, testString, matchResult) + } + + override fun hasConsumed(matchResult: MatchResultImpl): Boolean = true + override val name: String + get() = "NegativeLookaheadJointSet" +} diff --git a/kotlin-native/runtime/src/main/kotlin/kotlin/text/regex/sets/LookBehindSets.kt b/kotlin-native/runtime/src/main/kotlin/kotlin/text/regex/sets/LookBehindSets.kt new file mode 100644 index 00000000000..47da005ecb5 --- /dev/null +++ b/kotlin-native/runtime/src/main/kotlin/kotlin/text/regex/sets/LookBehindSets.kt @@ -0,0 +1,71 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package kotlin.text.regex + +/** + * Positive lookbehind node. + */ +internal class PositiveLookBehindSet(children: List, fSet: FSet) : AtomicJointSet(children, fSet) { + + /** Returns startIndex+shift, the next position to match */ + override fun matches(startIndex: Int, testString: CharSequence, matchResult: MatchResultImpl): Int { + + matchResult.setConsumed(groupIndex, startIndex) + children.forEach { + if (it.findBack(0, startIndex, testString, matchResult) >= 0) { + matchResult.setConsumed(groupIndex, -1) + return next.matches(startIndex, testString, matchResult) + } + } + + return -1 + } + + override fun hasConsumed(matchResult: MatchResultImpl): Boolean = true + override val name: String + get() = "PositiveBehindJointSet" +} + +/** + * Negative look behind node. + */ +internal class NegativeLookBehindSet(children: List, fSet: FSet) : AtomicJointSet(children, fSet) { + + /** Returns startIndex+shift, the next position to match */ + override fun matches(startIndex: Int, testString: CharSequence, matchResult: MatchResultImpl): Int { + matchResult.setConsumed(groupIndex, startIndex) + + children.forEach { + val shift = it.findBack(0, startIndex, testString, matchResult) + if (shift >= 0) { + return -1 + } + } + + return next.matches(startIndex, testString, matchResult) + } + + override fun hasConsumed(matchResult: MatchResultImpl): Boolean = true + override val name: String + get() = "NegativeBehindJointSet" +} diff --git a/kotlin-native/runtime/src/main/kotlin/kotlin/text/regex/sets/NonCapturingJointSet.kt b/kotlin-native/runtime/src/main/kotlin/kotlin/text/regex/sets/NonCapturingJointSet.kt new file mode 100644 index 00000000000..07f7ec45c22 --- /dev/null +++ b/kotlin-native/runtime/src/main/kotlin/kotlin/text/regex/sets/NonCapturingJointSet.kt @@ -0,0 +1,54 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package kotlin.text.regex + +/** + * Node representing non-capturing group + */ +open internal class NonCapturingJointSet(children: List, fSet: FSet) : JointSet(children, fSet) { + + /** + * Returns startIndex+shift, the next position to match + */ + override fun matches(startIndex: Int, testString: CharSequence, matchResult: MatchResultImpl): Int { + val start = matchResult.getConsumed(groupIndex) + matchResult.setConsumed(groupIndex, startIndex) + + children.forEach { + val shift = it.matches(startIndex, testString, matchResult) + if (shift >= 0) { + return shift + } + } + + matchResult.setConsumed(groupIndex, start) + return -1 + } + + override val name: String + get() = "NonCapturingJointSet" + + override fun hasConsumed(matchResult: MatchResultImpl): Boolean { + return matchResult.getConsumed(groupIndex) != 0 + } +} diff --git a/kotlin-native/runtime/src/main/kotlin/kotlin/text/regex/sets/PossessiveGroupQuantifierSet.kt b/kotlin-native/runtime/src/main/kotlin/kotlin/text/regex/sets/PossessiveGroupQuantifierSet.kt new file mode 100644 index 00000000000..090c9fa82b7 --- /dev/null +++ b/kotlin-native/runtime/src/main/kotlin/kotlin/text/regex/sets/PossessiveGroupQuantifierSet.kt @@ -0,0 +1,57 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package kotlin.text.regex + +/** + * Possessive quantifier set over groups. + */ +internal class PossessiveGroupQuantifierSet( + quantifier: Quantifier, + innerSet: AbstractSet, + next: AbstractSet, + type: Int, + setCounter: Int +): GroupQuantifierSet(quantifier, innerSet, next, type, setCounter) { + + init { + innerSet.next = FSet.possessiveFSet + } + + override fun matches(startIndex: Int, testString: CharSequence, matchResult: MatchResultImpl): Int { + + var index = startIndex + var nextIndex: Int = innerSet.matches(index, testString, matchResult) + var occurrences = 0 + while (nextIndex > index && (max == Quantifier.INF || occurrences < max)) { + occurrences++ + index = nextIndex + nextIndex = innerSet.matches(index, testString, matchResult) + } + + if (occurrences < quantifier.min) { + return -1 + } else { + return next.matches(index, testString, matchResult) + } + } +} diff --git a/kotlin-native/runtime/src/main/kotlin/kotlin/text/regex/sets/PossessiveLeafQuantifierSet.kt b/kotlin-native/runtime/src/main/kotlin/kotlin/text/regex/sets/PossessiveLeafQuantifierSet.kt new file mode 100644 index 00000000000..f8f5169bfed --- /dev/null +++ b/kotlin-native/runtime/src/main/kotlin/kotlin/text/regex/sets/PossessiveLeafQuantifierSet.kt @@ -0,0 +1,66 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package kotlin.text.regex + +/** + * Possessive quantifier node over a leaf node. + * - a{n,m}+; + * - a*+ == a{0, }+; + * - a?+ == a{0, 1}+; + * - a++ == a{1, }+; + */ +internal class PossessiveLeafQuantifierSet( + quant: Quantifier, + innerSet: LeafSet, + next: AbstractSet, type: Int +) : LeafQuantifierSet(quant, innerSet, next, type) { + + override fun matches(startIndex: Int, testString: CharSequence, matchResult: MatchResultImpl): Int { + var index = startIndex + var occurrences = 0 + + while (occurrences < min) { + if (index + leaf.charCount > testString.length) { + return -1 + } + + val shift = leaf.accepts(index, testString) + if (shift < 1) { + return -1 + } + index += shift + occurrences++ + } + + while ((max == Quantifier.INF || occurrences < max) && index + leaf.charCount <= testString.length) { + val shift = leaf.accepts(index, testString) + if (shift < 1) { + break + } + index += shift + occurrences++ + } + + return next.matches(index, testString, matchResult) + } +} diff --git a/kotlin-native/runtime/src/main/kotlin/kotlin/text/regex/sets/PreviousMatchSet.kt b/kotlin-native/runtime/src/main/kotlin/kotlin/text/regex/sets/PreviousMatchSet.kt new file mode 100644 index 00000000000..25688fda7ff --- /dev/null +++ b/kotlin-native/runtime/src/main/kotlin/kotlin/text/regex/sets/PreviousMatchSet.kt @@ -0,0 +1,43 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package kotlin.text.regex + +/** + * Node representing previous match (\G). + */ +internal class PreviousMatchSet : SimpleSet() { + + override fun matches(startIndex: Int, testString: CharSequence, matchResult: MatchResultImpl): Int { + if (startIndex == matchResult.previousMatch) { + return next.matches(startIndex, testString, matchResult) + } + return -1 + } + + override fun hasConsumed(matchResult: MatchResultImpl): Boolean = false + override val name: String + get() = "PreviousMatchSet" +} + + + diff --git a/kotlin-native/runtime/src/main/kotlin/kotlin/text/regex/sets/QuantifierSet.kt b/kotlin-native/runtime/src/main/kotlin/kotlin/text/regex/sets/QuantifierSet.kt new file mode 100644 index 00000000000..ac965b81da9 --- /dev/null +++ b/kotlin-native/runtime/src/main/kotlin/kotlin/text/regex/sets/QuantifierSet.kt @@ -0,0 +1,44 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package kotlin.text.regex + +/** + * Base class for quantifiers. + */ +internal abstract class QuantifierSet(open var innerSet: AbstractSet, override var next: AbstractSet, type: Int) + : SimpleSet(type) { + + override fun first(set: AbstractSet): Boolean = + innerSet.first(set) || next.first(set) + + override fun hasConsumed(matchResult: MatchResultImpl): Boolean = true + + override fun processSecondPassInternal(): AbstractSet { + val innerSet = this.innerSet + if (innerSet.secondPassVisited) { + this.innerSet = innerSet.processSecondPass() + } + + return super.processSecondPassInternal() + } +} diff --git a/kotlin-native/runtime/src/main/kotlin/kotlin/text/regex/sets/RangeSet.kt b/kotlin-native/runtime/src/main/kotlin/kotlin/text/regex/sets/RangeSet.kt new file mode 100644 index 00000000000..3205c35bfc2 --- /dev/null +++ b/kotlin-native/runtime/src/main/kotlin/kotlin/text/regex/sets/RangeSet.kt @@ -0,0 +1,53 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package kotlin.text.regex + +/** + * Represents node accepting single character from the given char class. + */ +open internal class RangeSet(charClass: AbstractCharClass, val ignoreCase: Boolean = false) : LeafSet() { + + val chars: AbstractCharClass = charClass.instance + + override fun accepts(startIndex: Int, testString: CharSequence): Int { + if (ignoreCase) { + val char = testString[startIndex] + return if (chars.contains(char.toUpperCase()) || chars.contains(char.toLowerCase())) 1 else -1 + } else { + return if (chars.contains(testString[startIndex])) 1 else -1 + } + } + + override val name: String + get() = "range:" + (if (chars.alt) "^ " else " ") + chars.toString() + + override fun first(set: AbstractSet): Boolean { + return when (set) { + is CharSet -> AbstractCharClass.intersects(chars, set.char.toInt()) + is RangeSet -> AbstractCharClass.intersects(chars, set.chars) + is SupplementaryCharSet -> false + is SupplementaryRangeSet -> AbstractCharClass.intersects(chars, set.chars) + else -> true + } + } +} diff --git a/kotlin-native/runtime/src/main/kotlin/kotlin/text/regex/sets/ReluctantGroupQuantifierSet.kt b/kotlin-native/runtime/src/main/kotlin/kotlin/text/regex/sets/ReluctantGroupQuantifierSet.kt new file mode 100644 index 00000000000..a6da1602cd2 --- /dev/null +++ b/kotlin-native/runtime/src/main/kotlin/kotlin/text/regex/sets/ReluctantGroupQuantifierSet.kt @@ -0,0 +1,78 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package kotlin.text.regex + +/** + * Reluctant version of the group quantifier set. + */ +internal class ReluctantGroupQuantifierSet( + quantifier: Quantifier, + innerSet: AbstractSet, + next: AbstractSet, + type: Int, + setCounter: Int +) : GroupQuantifierSet(quantifier, innerSet, next, type, setCounter) { + + override fun matches(startIndex: Int, testString: CharSequence, matchResult: MatchResultImpl): Int { + var enterCount = matchResult.enterCounters[groupQuantifierIndex] + + fun matchNext(): Int { + matchResult.enterCounters[groupQuantifierIndex] = 0 + val result = next.matches(startIndex, testString, matchResult) + matchResult.enterCounters[groupQuantifierIndex] = enterCount + return result + } + + if (!innerSet.hasConsumed(matchResult)) { + return matchNext() + } + + // Fast case: '*' or {0, } - no need to count occurrences. + if (min == 0 && max == Quantifier.INF) { + val res = next.matches(startIndex, testString, matchResult) + return if (res < 0) { + innerSet.matches(startIndex, testString, matchResult) + } else { + res + } + } + + // can't go inner set; + if (max != Quantifier.INF && enterCount >= max) { + return matchNext() + } + + return if (enterCount >= min) { + val nextIndex = matchNext() + if (nextIndex < 0) { + matchResult.enterCounters[groupQuantifierIndex] = ++enterCount + innerSet.matches(startIndex, testString, matchResult) + } else { + nextIndex + } + } else { + matchResult.enterCounters[groupQuantifierIndex] = ++enterCount + innerSet.matches(startIndex, testString, matchResult) + } + } +} diff --git a/kotlin-native/runtime/src/main/kotlin/kotlin/text/regex/sets/ReluctantLeafQuantifierSet.kt b/kotlin-native/runtime/src/main/kotlin/kotlin/text/regex/sets/ReluctantLeafQuantifierSet.kt new file mode 100644 index 00000000000..33ce43b13a6 --- /dev/null +++ b/kotlin-native/runtime/src/main/kotlin/kotlin/text/regex/sets/ReluctantLeafQuantifierSet.kt @@ -0,0 +1,72 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package kotlin.text.regex + +/** + * Reluctant quantifier node over a leaf node. + * - a{n,m}?; + * - a*? == a{0, }?; + * - a?? == a{0, 1}?; + * - a+? == a{1, }?; + */ +internal class ReluctantLeafQuantifierSet( + quant: Quantifier, + innerSet: LeafSet, + next: AbstractSet, + type: Int +) : LeafQuantifierSet(quant, innerSet, next, type) { + + override fun matches(startIndex: Int, testString: CharSequence, matchResult: MatchResultImpl): Int { + var index = startIndex + var occurrences = 0 + + while (occurrences < min) { + if (index + leaf.charCount > testString.length) { + return -1 + } + + val shift = leaf.accepts(index, testString) + if (shift < 1) { + return -1 + } + index += shift + occurrences++ + } + + do { + var shift = next.matches(index, testString, matchResult) + if (shift >= 0) { + return shift + } + + if (index + leaf.charCount <= testString.length) { + shift = leaf.accepts(index, testString) + index += shift + occurrences++ + } + + } while (shift >= 1 && (max == Quantifier.INF || occurrences <= max)) + + return -1 + } +} diff --git a/kotlin-native/runtime/src/main/kotlin/kotlin/text/regex/sets/SOLSet.kt b/kotlin-native/runtime/src/main/kotlin/kotlin/text/regex/sets/SOLSet.kt new file mode 100644 index 00000000000..774dac1410d --- /dev/null +++ b/kotlin-native/runtime/src/main/kotlin/kotlin/text/regex/sets/SOLSet.kt @@ -0,0 +1,50 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package kotlin.text.regex + +/** + * A node representing a '^' sign. + * Note: In Kotlin we use only the "anchoring bounds" mode when "^" matches beginning of a match region. + * See: http://docs.oracle.com/javase/8/docs/api/java/util/regex/Matcher.html#useAnchoringBounds-boolean- + */ +internal class SOLSet(val lt: AbstractLineTerminator, val multiline: Boolean = false) : SimpleSet() { + + override fun matches(startIndex: Int, testString: CharSequence, matchResult: MatchResultImpl): Int { + if (!multiline) { + if (startIndex == 0) { + return next.matches(startIndex, testString, matchResult) + } + } else { + if (startIndex != testString.length + && (startIndex == 0 + || lt.isAfterLineTerminator(testString[startIndex - 1], testString[startIndex]))) { + return next.matches(startIndex, testString, matchResult) + } + } + return -1 + } + + override fun hasConsumed(matchResult: MatchResultImpl): Boolean = false + override val name: String + get() = "^" +} \ No newline at end of file diff --git a/kotlin-native/runtime/src/main/kotlin/kotlin/text/regex/sets/SequenceSet.kt b/kotlin-native/runtime/src/main/kotlin/kotlin/text/regex/sets/SequenceSet.kt new file mode 100644 index 00000000000..d3613805fb0 --- /dev/null +++ b/kotlin-native/runtime/src/main/kotlin/kotlin/text/regex/sets/SequenceSet.kt @@ -0,0 +1,105 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package kotlin.text.regex + +/** + * This class represents nodes constructed with character sequences. For + * example, lets consider regular expression: ".*word.*". During regular + * expression compilation phase character sequence w-o-r-d, will be represented + * with single node for the entire word. + */ +open internal class SequenceSet(substring: CharSequence, val ignoreCase: Boolean = false) : LeafSet() { + + /** Represents a character sequence used for matching/searching. */ + protected val patternString: String = substring.toString() + + override val name: String= "sequence: " + patternString + + override val charCount = substring.length + + // Overrides ======================================================================================================= + + /** Returns true if [index] points to a low surrogate following a high surrogate */ + private fun isLowSurrogateOfSupplement(string: CharSequence, index: Int): Boolean = + index < string.length && string[index].isLowSurrogate() && index > 0 && string[index - 1].isHighSurrogate() + + override fun accepts(startIndex: Int, testString: CharSequence): Int { + return if (testString.startsWith(patternString, startIndex, ignoreCase) + && !isLowSurrogateOfSupplement(testString, startIndex) + && !isLowSurrogateOfSupplement(testString, startIndex + patternString.length)) { + charCount + } else { + -1 + } + } + + override fun find(startIndex: Int, testString: CharSequence, matchResult: MatchResultImpl): Int { + var index = startIndex + while (index < testString.length) { + index = testString.indexOf(patternString, index, ignoreCase) + if (index < 0) { + return -1 + } + // Check if we have a supplementary code point at the beginning or at the end of the string. + if (!isLowSurrogateOfSupplement(testString, index) + && !isLowSurrogateOfSupplement(testString, index + patternString.length) + && next.matches(index + charCount, testString, matchResult) >= 0) { + return index + } + index++ + } + return -1 + } + + override fun findBack(leftLimit: Int, rightLimit: Int, testString: CharSequence, matchResult: MatchResultImpl): Int { + var index = rightLimit + while (index >= leftLimit) { + index = testString.lastIndexOf(patternString, index, ignoreCase) + if (index < 0) { + return -1 + } + // Check if we have a supplementary code point at the beginning or at the end of the string. + if (!isLowSurrogateOfSupplement(testString, index) + && !isLowSurrogateOfSupplement(testString, index + patternString.length) + && next.matches(index + charCount, testString, matchResult) >= 0) { + return index + } + index-- + } + return -1 + } + + override fun first(set: AbstractSet): Boolean { + if (ignoreCase) { + return super.first(set) + } + return when (set) { + is CharSet -> set.char == patternString[0] + is RangeSet -> set.accepts(0, patternString.substring(0, 1)) > 0 + is SupplementaryRangeSet -> set.contains(patternString[0]) || patternString.length > 1 && set.contains(Char.toCodePoint(patternString[0], patternString[1])) + is SupplementaryCharSet -> if (patternString.length > 1) set.codePoint == Char.toCodePoint(patternString[0], patternString[1]) + else false + else -> true + } + } +} diff --git a/kotlin-native/runtime/src/main/kotlin/kotlin/text/regex/sets/SingleSet.kt b/kotlin-native/runtime/src/main/kotlin/kotlin/text/regex/sets/SingleSet.kt new file mode 100644 index 00000000000..cd315c196f0 --- /dev/null +++ b/kotlin-native/runtime/src/main/kotlin/kotlin/text/regex/sets/SingleSet.kt @@ -0,0 +1,151 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package kotlin.text.regex + +/** + * Group node over subexpression without alternations. + */ +open internal class SingleSet(var kid: AbstractSet, fSet: FSet) : JointSet(listOf(), fSet) { + + var backReferencedSet: BackReferencedSingleSet? = null + + // Overrides (API) ================================================================================================= + + override fun matches(startIndex: Int, testString: CharSequence, matchResult: MatchResultImpl): Int { + val start = matchResult.getStart(groupIndex) + matchResult.setStart(groupIndex, startIndex) + val shift = kid.matches(startIndex, testString, matchResult) + if (shift >= 0) { + return shift + } + matchResult.setStart(groupIndex, start) + return -1 + } + + override fun find(startIndex: Int, testString: CharSequence, matchResult: MatchResultImpl): Int { + val res = kid.find(startIndex, testString, matchResult) + if (res >= 0) + matchResult.setStart(groupIndex, res) + return res + } + + override fun findBack(leftLimit: Int, rightLimit: Int, testString: CharSequence, matchResult: MatchResultImpl): Int { + val res = kid.findBack(leftLimit, rightLimit, testString, matchResult) + if (res >= 0) + matchResult.setStart(groupIndex, res) + return res + } + + override fun first(set: AbstractSet): Boolean = kid.first(set) + + // Second pass processing ========================================================================================== + + override fun processBackRefReplacement(): JointSet? { + /** + * We will store a reference to created BackReferencedSingleSet + * in [backReferencedSet] field. This is needed to process replacement + * of sets correctly since sometimes we cannot renew all references to + * detachable set in the current point of traverse. See + * QuantifierSet and AbstractSet processSecondPass() methods for + * more details. + */ + val result = BackReferencedSingleSet(this) + backReferencedSet = result + return result + } + + override fun processSecondPassInternal(): AbstractSet { + fSet = fSet.processSecondPass() + kid = kid.processSecondPass() + return processBackRefReplacement() ?: this + } + + /** + * This method is used for traversing nodes after the first stage of compilation. + */ + override fun processSecondPass(): AbstractSet { + if (secondPassVisited) { + if (fSet.isBackReferenced) { + assert(backReferencedSet != null) // secondPassVisited + return backReferencedSet!! + } + } + secondPassVisited = true + return processSecondPassInternal() + } + + // Backreferenced version of the class ============================================================================= + + /** + * Group node over subexpression without alternations. + * This node is used if current group is referenced via a backreference. + */ + internal class BackReferencedSingleSet(node: SingleSet) : SingleSet(node.kid, node.fSet) { + + /* + * This class is needed only for overwriting find() and findBack() methods of SingleSet class, which is being + * back referenced. The following example explains the need for such substitution: + * + * Let's consider the pattern ".*(.)\\1". + * Leading .* works as follows: finds line terminator and runs findBack from that point. + * `findBack` method in its turn (in contrast to matches) sets group boundaries on the back trace. + * Thus at the point we try to match back reference(\\1) groups are not yet set. + * + * To fix this problem we replace backreferenced groups with instances of this class, + * which will use matches instead of find; this will affect performance, but ensure correctness of the match. + */ + override fun find(startIndex: Int, testString: CharSequence, matchResult: MatchResultImpl): Int { + for (index in startIndex..testString.length) { + val oldStart = matchResult.getStart(groupIndex) + matchResult.setStart(groupIndex, index) + + val res = kid.matches(index, testString, matchResult) + if (res >= 0) { + return index + } else { + matchResult.setStart(groupIndex, oldStart) + } + } + return -1 + } + + override fun findBack(leftLimit: Int, rightLimit: Int, + testString: CharSequence, matchResult: MatchResultImpl): Int { + for (index in rightLimit downTo leftLimit) { + val oldStart = matchResult.getStart(groupIndex) + matchResult.setStart(groupIndex, index) + + val res = kid.matches(index, testString, matchResult) + if (res >= 0) { + return index + } else { + matchResult.setStart(groupIndex, oldStart) + } + } + return -1 + } + + override fun processBackRefReplacement(): JointSet? = null + } +} + diff --git a/kotlin-native/runtime/src/main/kotlin/kotlin/text/regex/sets/SupplementaryCharSet.kt b/kotlin-native/runtime/src/main/kotlin/kotlin/text/regex/sets/SupplementaryCharSet.kt new file mode 100644 index 00000000000..089baf9d571 --- /dev/null +++ b/kotlin-native/runtime/src/main/kotlin/kotlin/text/regex/sets/SupplementaryCharSet.kt @@ -0,0 +1,108 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* + * + * Portions, Copyright © 1991-2005 Unicode, Inc. The following applies to Unicode. + * + * COPYRIGHT AND PERMISSION NOTICE + * + * Copyright © 1991-2005 Unicode, Inc. All rights reserved. Distributed under + * the Terms of Use in http://www.unicode.org/copyright.html. Permission is + * hereby granted, free of charge, to any person obtaining a copy of the + * Unicode data files and any associated documentation (the "Data Files") + * or Unicode software and any associated documentation (the "Software") + * to deal in the Data Files or Software without restriction, including without + * limitation the rights to use, copy, modify, merge, publish, distribute, + * and/or sell copies of the Data Files or Software, and to permit persons + * to whom the Data Files or Software are furnished to do so, provided that + * (a) the above copyright notice(s) and this permission notice appear with + * all copies of the Data Files or Software, (b) both the above copyright + * notice(s) and this permission notice appear in associated documentation, + * and (c) there is clear notice in each modified Data File or in the Software + * as well as in the documentation associated with the Data File(s) or Software + * that the data or software has been modified. + + * THE DATA FILES AND SOFTWARE ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY + * KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT + * OF THIRD PARTY RIGHTS. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR HOLDERS + * INCLUDED IN THIS NOTICE BE LIABLE FOR ANY CLAIM, OR ANY SPECIAL INDIRECT + * OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS + * OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR + * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THE DATA FILES OR SOFTWARE. + * + * Except as contained in this notice, the name of a copyright holder shall + * not be used in advertising or otherwise to promote the sale, use or other + * dealings in these Data Files or Software without prior written + * authorization of the copyright holder. + * + * 2. Additional terms from the Database: + * + * Copyright © 1995-1999 Unicode, Inc. All Rights reserved. + * + * Disclaimer + * + * The Unicode Character Database is provided as is by Unicode, Inc. + * No claims are made as to fitness for any particular purpose. No warranties + * of any kind are expressed or implied. The recipient agrees to determine + * applicability of information provided. If this file has been purchased + * on magnetic or optical media from Unicode, Inc., the sole remedy for any claim + * will be exchange of defective media within 90 days of receipt. This disclaimer + * is applicable for all other data files accompanying the Unicode Character Database, + * some of which have been compiled by the Unicode Consortium, and some of which + * have been supplied by other sources. + * + * Limitations on Rights to Redistribute This Data + * + * Recipient is granted the right to make copies in any form for internal + * distribution and to freely use the information supplied in the creation of + * products supporting the UnicodeTM Standard. The files in + * the Unicode Character Database can be redistributed to third parties or other + * organizations (whether for profit or not) as long as this notice and the disclaimer + * notice are retained. Information can be extracted from these files and used + * in documentation or programs, as long as there is an accompanying notice + * indicating the source. + */ + +package kotlin.text.regex + +/** + * Represents node accepting single supplementary codepoint. + */ +internal class SupplementaryCharSet(val codePoint: Int, ignoreCase: Boolean) + : SequenceSet(String(Char.toChars(codePoint), 0, 2), ignoreCase) { + + override val name: String + get() = patternString + + override fun first(set: AbstractSet): Boolean { + return when (set) { + is SupplementaryCharSet -> set.codePoint == codePoint + is SupplementaryRangeSet -> set.contains(codePoint) + is CharSet, + is RangeSet -> false + else -> true + } + } +} diff --git a/kotlin-native/runtime/src/main/kotlin/kotlin/text/regex/sets/SupplementaryRangeSet.kt b/kotlin-native/runtime/src/main/kotlin/kotlin/text/regex/sets/SupplementaryRangeSet.kt new file mode 100644 index 00000000000..c73a7db2633 --- /dev/null +++ b/kotlin-native/runtime/src/main/kotlin/kotlin/text/regex/sets/SupplementaryRangeSet.kt @@ -0,0 +1,150 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* + * + * Portions, Copyright © 1991-2005 Unicode, Inc. The following applies to Unicode. + * + * COPYRIGHT AND PERMISSION NOTICE + * + * Copyright © 1991-2005 Unicode, Inc. All rights reserved. Distributed under + * the Terms of Use in http://www.unicode.org/copyright.html. Permission is + * hereby granted, free of charge, to any person obtaining a copy of the + * Unicode data files and any associated documentation (the "Data Files") + * or Unicode software and any associated documentation (the "Software") + * to deal in the Data Files or Software without restriction, including without + * limitation the rights to use, copy, modify, merge, publish, distribute, + * and/or sell copies of the Data Files or Software, and to permit persons + * to whom the Data Files or Software are furnished to do so, provided that + * (a) the above copyright notice(s) and this permission notice appear with + * all copies of the Data Files or Software, (b) both the above copyright + * notice(s) and this permission notice appear in associated documentation, + * and (c) there is clear notice in each modified Data File or in the Software + * as well as in the documentation associated with the Data File(s) or Software + * that the data or software has been modified. + + * THE DATA FILES AND SOFTWARE ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY + * KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT + * OF THIRD PARTY RIGHTS. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR HOLDERS + * INCLUDED IN THIS NOTICE BE LIABLE FOR ANY CLAIM, OR ANY SPECIAL INDIRECT + * OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS + * OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR + * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THE DATA FILES OR SOFTWARE. + * + * Except as contained in this notice, the name of a copyright holder shall + * not be used in advertising or otherwise to promote the sale, use or other + * dealings in these Data Files or Software without prior written + * authorization of the copyright holder. + * + * 2. Additional terms from the Database: + * + * Copyright © 1995-1999 Unicode, Inc. All Rights reserved. + * + * Disclaimer + * + * The Unicode Character Database is provided as is by Unicode, Inc. + * No claims are made as to fitness for any particular purpose. No warranties + * of any kind are expressed or implied. The recipient agrees to determine + * applicability of information provided. If this file has been purchased + * on magnetic or optical media from Unicode, Inc., the sole remedy for any claim + * will be exchange of defective media within 90 days of receipt. This disclaimer + * is applicable for all other data files accompanying the Unicode Character Database, + * some of which have been compiled by the Unicode Consortium, and some of which + * have been supplied by other sources. + * + * Limitations on Rights to Redistribute This Data + * + * Recipient is granted the right to make copies in any form for internal + * distribution and to freely use the information supplied in the creation of + * products supporting the UnicodeTM Standard. The files in + * the Unicode Character Database can be redistributed to third parties or other + * organizations (whether for profit or not) as long as this notice and the disclaimer + * notice are retained. Information can be extracted from these files and used + * in documentation or programs, as long as there is an accompanying notice + * indicating the source. + */ + +package kotlin.text.regex + +/** + * Represents node accepting single character from the given char class. + * This character can be supplementary (2 chars needed to represent) or from + * basic multilingual pane (1 needed char to represent it). + */ +open internal class SupplementaryRangeSet(charClass: AbstractCharClass, val ignoreCase: Boolean = false): SimpleSet() { + + val chars = charClass.instance + + override fun matches(startIndex: Int, testString: CharSequence, matchResult: MatchResultImpl): Int { + val rightBound = testString.length + if (startIndex >= rightBound) { + return -1 + } + + var index = startIndex + + val high = testString[index++] + if (contains(high)) { + val result = next.matches(index, testString, matchResult) + if (result >= 0) return result + } + + if (index < rightBound) { + val low = testString[index++] + if (Char.isSurrogatePair(high, low) && contains(Char.toCodePoint(high, low))) { + return next.matches(index, testString, matchResult) + } + } + + return -1 + } + + fun contains(char: Char): Boolean { + if (ignoreCase) { + return chars.contains(char.toUpperCase()) || chars.contains(char.toLowerCase()) + } else { + return chars.contains(char) + } + } + + fun contains(char: Int): Boolean { + return chars.contains(char) + } + + override val name: String + get() = "range:" + (if (chars.alt) "^ " else " ") + chars.toString() + + + override fun first(set: AbstractSet): Boolean { + return when(set) { + is SupplementaryCharSet -> AbstractCharClass.intersects(chars, set.codePoint) + is CharSet -> AbstractCharClass.intersects(chars, set.char.toInt()) + is SupplementaryRangeSet -> AbstractCharClass.intersects(chars, set.chars) + is RangeSet -> AbstractCharClass.intersects(chars, set.chars) + else -> true + } + } + + override fun hasConsumed(matchResult: MatchResultImpl): Boolean = true +} diff --git a/kotlin-native/runtime/src/main/kotlin/kotlin/text/regex/sets/SurrogateCharSets.kt b/kotlin-native/runtime/src/main/kotlin/kotlin/text/regex/sets/SurrogateCharSets.kt new file mode 100644 index 00000000000..9f975af9b78 --- /dev/null +++ b/kotlin-native/runtime/src/main/kotlin/kotlin/text/regex/sets/SurrogateCharSets.kt @@ -0,0 +1,219 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* + * + * Portions, Copyright © 1991-2005 Unicode, Inc. The following applies to Unicode. + * + * COPYRIGHT AND PERMISSION NOTICE + * + * Copyright © 1991-2005 Unicode, Inc. All rights reserved. Distributed under + * the Terms of Use in http://www.unicode.org/copyright.html. Permission is + * hereby granted, free of charge, to any person obtaining a copy of the + * Unicode data files and any associated documentation (the "Data Files") + * or Unicode software and any associated documentation (the "Software") + * to deal in the Data Files or Software without restriction, including without + * limitation the rights to use, copy, modify, merge, publish, distribute, + * and/or sell copies of the Data Files or Software, and to permit persons + * to whom the Data Files or Software are furnished to do so, provided that + * (a) the above copyright notice(s) and this permission notice appear with + * all copies of the Data Files or Software, (b) both the above copyright + * notice(s) and this permission notice appear in associated documentation, + * and (c) there is clear notice in each modified Data File or in the Software + * as well as in the documentation associated with the Data File(s) or Software + * that the data or software has been modified. + + * THE DATA FILES AND SOFTWARE ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY + * KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT + * OF THIRD PARTY RIGHTS. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR HOLDERS + * INCLUDED IN THIS NOTICE BE LIABLE FOR ANY CLAIM, OR ANY SPECIAL INDIRECT + * OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS + * OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR + * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THE DATA FILES OR SOFTWARE. + * + * Except as contained in this notice, the name of a copyright holder shall + * not be used in advertising or otherwise to promote the sale, use or other + * dealings in these Data Files or Software without prior written + * authorization of the copyright holder. + * + * 2. Additional terms from the Database: + * + * Copyright © 1995-1999 Unicode, Inc. All Rights reserved. + * + * Disclaimer + * + * The Unicode Character Database is provided as is by Unicode, Inc. + * No claims are made as to fitness for any particular purpose. No warranties + * of any kind are expressed or implied. The recipient agrees to determine + * applicability of information provided. If this file has been purchased + * on magnetic or optical media from Unicode, Inc., the sole remedy for any claim + * will be exchange of defective media within 90 days of receipt. This disclaimer + * is applicable for all other data files accompanying the Unicode Character Database, + * some of which have been compiled by the Unicode Consortium, and some of which + * have been supplied by other sources. + * + * Limitations on Rights to Redistribute This Data + * + * Recipient is granted the right to make copies in any form for internal + * distribution and to freely use the information supplied in the creation of + * products supporting the UnicodeTM Standard. The files in + * the Unicode Character Database can be redistributed to third parties or other + * organizations (whether for profit or not) as long as this notice and the disclaimer + * notice are retained. Information can be extracted from these files and used + * in documentation or programs, as long as there is an accompanying notice + * indicating the source. + */ + +package kotlin.text.regex + +/** + * This class represents low surrogate character. + * + * Note that we can use high and low surrogate characters + * that don't combine into supplementary code point. + * See http://www.unicode.org/reports/tr18/#Supplementary_Characters + */ +internal class LowSurrogateCharSet(low: Char) : CharSet(low) { + + override fun accepts(startIndex: Int, testString: CharSequence): Int { + val result = super.accepts(startIndex, testString) + if (result < 0 || testString.isHighSurrogate(startIndex - 1)) { + return -1 + } + return result + } + + private fun CharSequence.isHighSurrogate(index: Int, leftBound: Int = 0, rightBound: Int = length) + = (index in leftBound until rightBound && this[index].isHighSurrogate()) + + override fun find(startIndex: Int, testString: CharSequence, matchResult: MatchResultImpl): Int { + var index = startIndex + while (index < testString.length) { + index = testString.indexOf(char, index, ignoreCase) + if (index < 0) { + return -1 + } + if (!testString.isHighSurrogate(index - 1) + && next.matches(index + charCount, testString, matchResult) >= 0) { + return index + } + index++ + } + return -1 + } + + override fun findBack(leftLimit: Int, rightLimit: Int, testString: CharSequence, matchResult: MatchResultImpl): Int { + var index = rightLimit + while (index >= leftLimit) { + index = testString.lastIndexOf(char, index, ignoreCase) + if (index < 0) { + return -1 + } + if (!testString.isHighSurrogate(index - 1, leftLimit, rightLimit) + && next.matches(index + charCount, testString, matchResult) >= 0) { + return index + } + index-- + } + return -1 + } + + override fun first(set: AbstractSet): Boolean { + return when(set) { + is LowSurrogateCharSet -> set.char == this.char + is CharSet, + is RangeSet, + is SupplementaryCharSet, + is SupplementaryRangeSet -> false + else -> true + } + } + + override fun hasConsumed(matchResult: MatchResultImpl): Boolean = true +} + +/** + * This class represents high surrogate character. + */ +internal class HighSurrogateCharSet(high: Char) : CharSet(high) { + + override fun accepts(startIndex: Int, testString: CharSequence): Int { + val result = super.accepts(startIndex, testString) + if (result < 0 || testString.isLowSurrogate(startIndex + 1)) { + return -1 + } + return result + } + + private fun CharSequence.isLowSurrogate(index: Int, leftBound: Int = 0, rightBound: Int = length) + = (index in leftBound until rightBound && this[index].isLowSurrogate()) + + // TODO: We have a similar code here, in LowSurrogateCharSet and in CharSet. Reuse it somehow. + override fun find(startIndex: Int, testString: CharSequence, matchResult: MatchResultImpl): Int { + var index = startIndex + while (index < testString.length) { + index = testString.indexOf(char, index, ignoreCase) + if (index < 0) { + return -1 + } + // Remove params. + if (!testString.isLowSurrogate(index + 1) + && next.matches(index + charCount, testString, matchResult) >= 0) { + return index + } + index++ + } + return -1 + } + + override fun findBack(leftLimit: Int, rightLimit: Int, testString: CharSequence, matchResult: MatchResultImpl): Int { + var index = rightLimit + while (index >= leftLimit) { + index = testString.lastIndexOf(char, index, ignoreCase) + if (index < 0) { + return -1 + } + if (!testString.isLowSurrogate(index + 1, leftLimit, rightLimit) + && next.matches(index + charCount, testString, matchResult) >= 0) { + return index + } + index-- + } + return -1 + } + + override fun first(set: AbstractSet): Boolean { + return when (set) { + is HighSurrogateCharSet -> set.char == this.char + is CharSet, + is RangeSet, + is SupplementaryCharSet, + is SupplementaryRangeSet -> false + else -> true + } + } + + override fun hasConsumed(matchResult: MatchResultImpl): Boolean = true +} + diff --git a/kotlin-native/runtime/src/main/kotlin/kotlin/text/regex/sets/SurrogateRangeSet.kt b/kotlin-native/runtime/src/main/kotlin/kotlin/text/regex/sets/SurrogateRangeSet.kt new file mode 100644 index 00000000000..14534cfcb17 --- /dev/null +++ b/kotlin-native/runtime/src/main/kotlin/kotlin/text/regex/sets/SurrogateRangeSet.kt @@ -0,0 +1,124 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* + * + * Portions, Copyright © 1991-2005 Unicode, Inc. The following applies to Unicode. + * + * COPYRIGHT AND PERMISSION NOTICE + * + * Copyright © 1991-2005 Unicode, Inc. All rights reserved. Distributed under + * the Terms of Use in http://www.unicode.org/copyright.html. Permission is + * hereby granted, free of charge, to any person obtaining a copy of the + * Unicode data files and any associated documentation (the "Data Files") + * or Unicode software and any associated documentation (the "Software") + * to deal in the Data Files or Software without restriction, including without + * limitation the rights to use, copy, modify, merge, publish, distribute, + * and/or sell copies of the Data Files or Software, and to permit persons + * to whom the Data Files or Software are furnished to do so, provided that + * (a) the above copyright notice(s) and this permission notice appear with + * all copies of the Data Files or Software, (b) both the above copyright + * notice(s) and this permission notice appear in associated documentation, + * and (c) there is clear notice in each modified Data File or in the Software + * as well as in the documentation associated with the Data File(s) or Software + * that the data or software has been modified. + + * THE DATA FILES AND SOFTWARE ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY + * KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT + * OF THIRD PARTY RIGHTS. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR HOLDERS + * INCLUDED IN THIS NOTICE BE LIABLE FOR ANY CLAIM, OR ANY SPECIAL INDIRECT + * OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS + * OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR + * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THE DATA FILES OR SOFTWARE. + * + * Except as contained in this notice, the name of a copyright holder shall + * not be used in advertising or otherwise to promote the sale, use or other + * dealings in these Data Files or Software without prior written + * authorization of the copyright holder. + * + * 2. Additional terms from the Database: + * + * Copyright © 1995-1999 Unicode, Inc. All Rights reserved. + * + * Disclaimer + * + * The Unicode Character Database is provided as is by Unicode, Inc. + * No claims are made as to fitness for any particular purpose. No warranties + * of any kind are expressed or implied. The recipient agrees to determine + * applicability of information provided. If this file has been purchased + * on magnetic or optical media from Unicode, Inc., the sole remedy for any claim + * will be exchange of defective media within 90 days of receipt. This disclaimer + * is applicable for all other data files accompanying the Unicode Character Database, + * some of which have been compiled by the Unicode Consortium, and some of which + * have been supplied by other sources. + * + * Limitations on Rights to Redistribute This Data + * + * Recipient is granted the right to make copies in any form for internal + * distribution and to freely use the information supplied in the creation of + * products supporting the UnicodeTM Standard. The files in + * the Unicode Character Database can be redistributed to third parties or other + * organizations (whether for profit or not) as long as this notice and the disclaimer + * notice are retained. Information can be extracted from these files and used + * in documentation or programs, as long as there is an accompanying notice + * indicating the source. + */ + +package kotlin.text.regex + +/* + * This class is a range that contains only surrogate characters. + */ +internal class SurrogateRangeSet(surrChars: AbstractCharClass) : RangeSet(surrChars) { + + override fun accepts(startIndex: Int, testString: CharSequence): Int { + val result = super.accepts(startIndex, testString) + when { + result < 0 || + testString.isHighSurrogate(startIndex - 1) && testString.isLowSurrogate(startIndex) || + testString.isHighSurrogate(startIndex) && testString.isLowSurrogate(startIndex + 1) -> + return -1 + } + return result + } + + private fun CharSequence.isHighSurrogate(index: Int, leftBound: Int = 0, rightBound: Int = length) + = (index in leftBound until rightBound && this[index].isHighSurrogate()) + + private fun CharSequence.isLowSurrogate(index: Int, leftBound: Int = 0, rightBound: Int = length) + = (index in leftBound until rightBound && this[index].isLowSurrogate()) + + override fun first(set: AbstractSet): Boolean { + return when (set) { + is SurrogateRangeSet -> true + is CharSet, + is RangeSet, + is SupplementaryCharSet, + is SupplementaryRangeSet -> false + else -> true + } + } + + override fun hasConsumed(matchResult: MatchResultImpl): Boolean = true +} diff --git a/kotlin-native/runtime/src/main/kotlin/kotlin/text/regex/sets/UnifiedQuantifierSet.kt b/kotlin-native/runtime/src/main/kotlin/kotlin/text/regex/sets/UnifiedQuantifierSet.kt new file mode 100644 index 00000000000..4b0833a6f12 --- /dev/null +++ b/kotlin-native/runtime/src/main/kotlin/kotlin/text/regex/sets/UnifiedQuantifierSet.kt @@ -0,0 +1,57 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package kotlin.text.regex + +/** + * Optimized greedy quantifier node ('*') for the case where there is no intersection with + * next node and normal quantifiers could be treated as greedy and possessive. + */ +internal class UnifiedQuantifierSet(quant: LeafQuantifierSet) : LeafQuantifierSet(Quantifier.starQuantifier, quant.leaf, quant.next, quant.type) { + + override fun matches(startIndex: Int, testString: CharSequence, matchResult: MatchResultImpl): Int { + var index = startIndex + while (index + leaf.charCount <= testString.length && leaf.accepts(index, testString) > 0) { + index += leaf.charCount + } + + return next.matches(index, testString, matchResult) + } + + override fun find(startIndex: Int, testString: CharSequence, matchResult: MatchResultImpl): Int { + var startSearch = next.find(startIndex, testString, matchResult) + if (startSearch < 0) + return -1 + + var result = startSearch + var index = startSearch - leaf.charCount + while (index >= startIndex && leaf.accepts(index, testString) > 0) { + result = index + index -= leaf.charCount + } + return result + } + + init { + innerSet.next = this + } +} diff --git a/kotlin-native/runtime/src/main/kotlin/kotlin/text/regex/sets/WordBoundarySet.kt b/kotlin-native/runtime/src/main/kotlin/kotlin/text/regex/sets/WordBoundarySet.kt new file mode 100644 index 00000000000..c6848035d58 --- /dev/null +++ b/kotlin-native/runtime/src/main/kotlin/kotlin/text/regex/sets/WordBoundarySet.kt @@ -0,0 +1,67 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package kotlin.text.regex + +/** + * Represents word boundary, checks current character and previous one. If they have different types returns true; + */ +internal class WordBoundarySet(var positive: Boolean) : SimpleSet() { + + override fun matches(startIndex: Int, testString: CharSequence, matchResult: MatchResultImpl): Int { + val curChar = if (startIndex >= testString.length) ' ' else testString[startIndex] + val prevChar = if (startIndex == 0) ' ' else testString[startIndex - 1] + + val right = curChar == ' ' || isSpace(curChar, startIndex, testString) + val left = prevChar == ' ' || isSpace(prevChar, startIndex - 1, testString) + + return if (left xor right xor positive) + -1 + else + next.matches(startIndex, testString, matchResult) + } + + /** Returns false, because word boundary does not consumes any characters and do not move string index. */ + override fun hasConsumed(matchResult: MatchResultImpl): Boolean = false + override val name: String + get() = "WordBoundarySet" + + private fun isSpace(char: Char, startIndex: Int, testString: CharSequence): Boolean { + if (char.isLetterOrDigit() || char == '_') { + return false + } + if (char.category == CharCategory.NON_SPACING_MARK) { + var index = startIndex + while (--index >= 0) { + val ch = testString[index] + when { + ch.isLetterOrDigit() -> return false + char.category != CharCategory.NON_SPACING_MARK -> return true + } + } + } + return true + } +} + + + diff --git a/kotlin-native/runtime/src/main/kotlin/kotlin/time/DurationUnit.kt b/kotlin-native/runtime/src/main/kotlin/kotlin/time/DurationUnit.kt new file mode 100644 index 00000000000..c6c09c967a4 --- /dev/null +++ b/kotlin-native/runtime/src/main/kotlin/kotlin/time/DurationUnit.kt @@ -0,0 +1,51 @@ +/* + * Copyright 2010-2019 JetBrains s.r.o. and Kotlin Programming Language contributors. + * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. + */ + +package kotlin.time + + +@SinceKotlin("1.3") +@ExperimentalTime +public actual enum class DurationUnit(internal val scale: Double) { + /** + * Time unit representing one nanosecond, which is 1/1000 of a microsecond. + */ + NANOSECONDS(1e0), + /** + * Time unit representing one microsecond, which is 1/1000 of a millisecond. + */ + MICROSECONDS(1e3), + /** + * Time unit representing one millisecond, which is 1/1000 of a second. + */ + MILLISECONDS(1e6), + /** + * Time unit representing one second. + */ + SECONDS(1e9), + /** + * Time unit representing one minute. + */ + MINUTES(60e9), + /** + * Time unit representing one hour. + */ + HOURS(3600e9), + /** + * Time unit representing one day, which is always equal to 24 hours. + */ + DAYS(86400e9); +} + +@SinceKotlin("1.3") +@ExperimentalTime +internal actual fun convertDurationUnit(value: Double, sourceUnit: DurationUnit, targetUnit: DurationUnit): Double { + val sourceCompareTarget = sourceUnit.scale.compareTo(targetUnit.scale) + return when { + sourceCompareTarget > 0 -> value * (sourceUnit.scale / targetUnit.scale) + sourceCompareTarget < 0 -> value / (targetUnit.scale / sourceUnit.scale) + else -> value + } +} diff --git a/kotlin-native/runtime/src/main/kotlin/kotlin/time/MonotonicTimeSource.kt b/kotlin-native/runtime/src/main/kotlin/kotlin/time/MonotonicTimeSource.kt new file mode 100644 index 00000000000..ba372cefad8 --- /dev/null +++ b/kotlin-native/runtime/src/main/kotlin/kotlin/time/MonotonicTimeSource.kt @@ -0,0 +1,15 @@ +/* + * Copyright 2010-2019 JetBrains s.r.o. and Kotlin Programming Language contributors. + * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. + */ + +package kotlin.time + +import kotlin.system.* + +@SinceKotlin("1.3") +@ExperimentalTime +internal actual object MonotonicTimeSource : AbstractLongTimeSource(unit = DurationUnit.NANOSECONDS), TimeSource { // TODO: interface should not be required here + override fun read(): Long = getTimeNanos() + override fun toString(): String = "TimeSource(nanoTime())" +} \ No newline at end of file diff --git a/kotlin-native/runtime/src/main/kotlin/kotlin/time/formatToDecimals.kt b/kotlin-native/runtime/src/main/kotlin/kotlin/time/formatToDecimals.kt new file mode 100644 index 00000000000..eef7e12b957 --- /dev/null +++ b/kotlin-native/runtime/src/main/kotlin/kotlin/time/formatToDecimals.kt @@ -0,0 +1,23 @@ +/* + * Copyright 2010-2019 JetBrains s.r.o. and Kotlin Programming Language contributors. + * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. + */ + +package kotlin.time + + +@SymbolName("Kotlin_DurationValue_formatToExactDecimals") +internal actual external fun formatToExactDecimals(value: Double, decimals: Int): String + +internal actual fun formatUpToDecimals(value: Double, decimals: Int): String { + return formatToExactDecimals(value, decimals).trimEnd('0') +} + +@SymbolName("Kotlin_DurationValue_formatScientificImpl") +internal external fun formatScientificImpl(value: Double): String + +internal actual fun formatScientific(value: Double): String { + val result = formatScientificImpl(value) + val expIndex = result.indexOf("e+0") + return if (expIndex < 0) result else result.removeRange(expIndex + 2, expIndex + 3) +} \ No newline at end of file diff --git a/kotlin-native/runtime/src/mimalloc/README.md b/kotlin-native/runtime/src/mimalloc/README.md new file mode 100644 index 00000000000..2a827b7b92e --- /dev/null +++ b/kotlin-native/runtime/src/mimalloc/README.md @@ -0,0 +1,39 @@ +#mimalloc + +mimalloc is a general purpose allocator with excellent performance characteristics. +Initially developed by Daan Leijen for the run-time systems of the Koka and Lean languages. + +Source code: https://github.com/microsoft/mimalloc +Used version: 1.6.7 (https://github.com/microsoft/mimalloc/releases/tag/v1.6.7) + +The constant KONAN_MI_MALLOC is used to integrate mimalloc code in K/N runtime. +All changes that are done should be under directives `#if defined(KONAN_MI_MALLOC)` + +To add code, do: + + #if defined(KONAN_MI_MALLOC) + + #endif // KONAN_MI_MALLOC + +To delete code, do: + + #if !defined(KONAN_MI_MALLOC) + + #endif // KONAN_MI_MALLOC + +To modify code, do: + + #if !defined(KONAN_MI_MALLOC) + + #else // KONAN_MI_MALLOC + + #endif // KONAN_MI_MALLOC + +or + + #if defined(KONAN_MI_MALLOC) + + #else // KONAN_MI_MALLOC + + #endif // KONAN_MI_MALLOC + diff --git a/kotlin-native/runtime/src/mimalloc/c/alloc-aligned.c b/kotlin-native/runtime/src/mimalloc/c/alloc-aligned.c new file mode 100644 index 00000000000..4cbe58a5c05 --- /dev/null +++ b/kotlin-native/runtime/src/mimalloc/c/alloc-aligned.c @@ -0,0 +1,205 @@ +/* ---------------------------------------------------------------------------- +Copyright (c) 2018, Microsoft Research, Daan Leijen +This is free software; you can redistribute it and/or modify it under the +terms of the MIT license. A copy of the license can be found in the file +"licenses/third_party/mimalloc_LICENSE.txt" at the root of this distribution. +-----------------------------------------------------------------------------*/ + +#include "mimalloc.h" +#include "mimalloc-internal.h" + +#include // memset, memcpy + +// ------------------------------------------------------ +// Aligned Allocation +// ------------------------------------------------------ + +static void* mi_heap_malloc_zero_aligned_at(mi_heap_t* const heap, const size_t size, const size_t alignment, const size_t offset, const bool zero) mi_attr_noexcept { + // note: we don't require `size > offset`, we just guarantee that + // the address at offset is aligned regardless of the allocated size. + mi_assert(alignment > 0); + if (mi_unlikely(size > PTRDIFF_MAX)) return NULL; // we don't allocate more than PTRDIFF_MAX (see ) + if (mi_unlikely(alignment==0 || !_mi_is_power_of_two(alignment))) return NULL; // require power-of-two (see ) + const uintptr_t align_mask = alignment-1; // for any x, `(x & align_mask) == (x % alignment)` + + // try if there is a small block available with just the right alignment + const size_t padsize = size + MI_PADDING_SIZE; + if (mi_likely(padsize <= MI_SMALL_SIZE_MAX)) { + mi_page_t* page = _mi_heap_get_free_small_page(heap,padsize); + const bool is_aligned = (((uintptr_t)page->free+offset) & align_mask)==0; + if (mi_likely(page->free != NULL && is_aligned)) + { + #if MI_STAT>1 + mi_heap_stat_increase( heap, malloc, size); + #endif + void* p = _mi_page_malloc(heap,page,padsize); // TODO: inline _mi_page_malloc + mi_assert_internal(p != NULL); + mi_assert_internal(((uintptr_t)p + offset) % alignment == 0); + if (zero) _mi_block_zero_init(page,p,size); + return p; + } + } + + // use regular allocation if it is guaranteed to fit the alignment constraints + if (offset==0 && alignment<=padsize && padsize<=MI_MEDIUM_OBJ_SIZE_MAX && (padsize&align_mask)==0) { + void* p = _mi_heap_malloc_zero(heap, size, zero); + mi_assert_internal(p == NULL || ((uintptr_t)p % alignment) == 0); + return p; + } + + // otherwise over-allocate + void* p = _mi_heap_malloc_zero(heap, size + alignment - 1, zero); + if (p == NULL) return NULL; + + // .. and align within the allocation + uintptr_t adjust = alignment - (((uintptr_t)p + offset) & align_mask); + mi_assert_internal(adjust <= alignment); + void* aligned_p = (adjust == alignment ? p : (void*)((uintptr_t)p + adjust)); + if (aligned_p != p) mi_page_set_has_aligned(_mi_ptr_page(p), true); + mi_assert_internal(((uintptr_t)aligned_p + offset) % alignment == 0); + mi_assert_internal( p == _mi_page_ptr_unalign(_mi_ptr_segment(aligned_p),_mi_ptr_page(aligned_p),aligned_p) ); + return aligned_p; +} + + +mi_decl_restrict void* mi_heap_malloc_aligned_at(mi_heap_t* heap, size_t size, size_t alignment, size_t offset) mi_attr_noexcept { + return mi_heap_malloc_zero_aligned_at(heap, size, alignment, offset, false); +} + +mi_decl_restrict void* mi_heap_malloc_aligned(mi_heap_t* heap, size_t size, size_t alignment) mi_attr_noexcept { + return mi_heap_malloc_aligned_at(heap, size, alignment, 0); +} + +mi_decl_restrict void* mi_heap_zalloc_aligned_at(mi_heap_t* heap, size_t size, size_t alignment, size_t offset) mi_attr_noexcept { + return mi_heap_malloc_zero_aligned_at(heap, size, alignment, offset, true); +} + +mi_decl_restrict void* mi_heap_zalloc_aligned(mi_heap_t* heap, size_t size, size_t alignment) mi_attr_noexcept { + return mi_heap_zalloc_aligned_at(heap, size, alignment, 0); +} + +mi_decl_restrict void* mi_heap_calloc_aligned_at(mi_heap_t* heap, size_t count, size_t size, size_t alignment, size_t offset) mi_attr_noexcept { + size_t total; + if (mi_count_size_overflow(count, size, &total)) return NULL; + return mi_heap_zalloc_aligned_at(heap, total, alignment, offset); +} + +mi_decl_restrict void* mi_heap_calloc_aligned(mi_heap_t* heap, size_t count, size_t size, size_t alignment) mi_attr_noexcept { + return mi_heap_calloc_aligned_at(heap,count,size,alignment,0); +} + +mi_decl_restrict void* mi_malloc_aligned_at(size_t size, size_t alignment, size_t offset) mi_attr_noexcept { + return mi_heap_malloc_aligned_at(mi_get_default_heap(), size, alignment, offset); +} + +mi_decl_restrict void* mi_malloc_aligned(size_t size, size_t alignment) mi_attr_noexcept { + return mi_heap_malloc_aligned(mi_get_default_heap(), size, alignment); +} + +mi_decl_restrict void* mi_zalloc_aligned_at(size_t size, size_t alignment, size_t offset) mi_attr_noexcept { + return mi_heap_zalloc_aligned_at(mi_get_default_heap(), size, alignment, offset); +} + +mi_decl_restrict void* mi_zalloc_aligned(size_t size, size_t alignment) mi_attr_noexcept { + return mi_heap_zalloc_aligned(mi_get_default_heap(), size, alignment); +} + +mi_decl_restrict void* mi_calloc_aligned_at(size_t count, size_t size, size_t alignment, size_t offset) mi_attr_noexcept { + return mi_heap_calloc_aligned_at(mi_get_default_heap(), count, size, alignment, offset); +} + +mi_decl_restrict void* mi_calloc_aligned(size_t count, size_t size, size_t alignment) mi_attr_noexcept { + return mi_heap_calloc_aligned(mi_get_default_heap(), count, size, alignment); +} + + +static void* mi_heap_realloc_zero_aligned_at(mi_heap_t* heap, void* p, size_t newsize, size_t alignment, size_t offset, bool zero) mi_attr_noexcept { + mi_assert(alignment > 0); + if (alignment <= sizeof(uintptr_t)) return _mi_heap_realloc_zero(heap,p,newsize,zero); + if (p == NULL) return mi_heap_malloc_zero_aligned_at(heap,newsize,alignment,offset,zero); + size_t size = mi_usable_size(p); + if (newsize <= size && newsize >= (size - (size / 2)) + && (((uintptr_t)p + offset) % alignment) == 0) { + return p; // reallocation still fits, is aligned and not more than 50% waste + } + else { + void* newp = mi_heap_malloc_aligned_at(heap,newsize,alignment,offset); + if (newp != NULL) { + if (zero && newsize > size) { + const mi_page_t* page = _mi_ptr_page(newp); + if (page->is_zero) { + // already zero initialized + mi_assert_expensive(mi_mem_is_zero(newp,newsize)); + } + else { + // also set last word in the previous allocation to zero to ensure any padding is zero-initialized + size_t start = (size >= sizeof(intptr_t) ? size - sizeof(intptr_t) : 0); + memset((uint8_t*)newp + start, 0, newsize - start); + } + } + memcpy(newp, p, (newsize > size ? size : newsize)); + mi_free(p); // only free if successful + } + return newp; + } +} + +static void* mi_heap_realloc_zero_aligned(mi_heap_t* heap, void* p, size_t newsize, size_t alignment, bool zero) mi_attr_noexcept { + mi_assert(alignment > 0); + if (alignment <= sizeof(uintptr_t)) return _mi_heap_realloc_zero(heap,p,newsize,zero); + size_t offset = ((uintptr_t)p % alignment); // use offset of previous allocation (p can be NULL) + return mi_heap_realloc_zero_aligned_at(heap,p,newsize,alignment,offset,zero); +} + +void* mi_heap_realloc_aligned_at(mi_heap_t* heap, void* p, size_t newsize, size_t alignment, size_t offset) mi_attr_noexcept { + return mi_heap_realloc_zero_aligned_at(heap,p,newsize,alignment,offset,false); +} + +void* mi_heap_realloc_aligned(mi_heap_t* heap, void* p, size_t newsize, size_t alignment) mi_attr_noexcept { + return mi_heap_realloc_zero_aligned(heap,p,newsize,alignment,false); +} + +void* mi_heap_rezalloc_aligned_at(mi_heap_t* heap, void* p, size_t newsize, size_t alignment, size_t offset) mi_attr_noexcept { + return mi_heap_realloc_zero_aligned_at(heap, p, newsize, alignment, offset, true); +} + +void* mi_heap_rezalloc_aligned(mi_heap_t* heap, void* p, size_t newsize, size_t alignment) mi_attr_noexcept { + return mi_heap_realloc_zero_aligned(heap, p, newsize, alignment, true); +} + +void* mi_heap_recalloc_aligned_at(mi_heap_t* heap, void* p, size_t newcount, size_t size, size_t alignment, size_t offset) mi_attr_noexcept { + size_t total; + if (mi_count_size_overflow(newcount, size, &total)) return NULL; + return mi_heap_rezalloc_aligned_at(heap, p, total, alignment, offset); +} + +void* mi_heap_recalloc_aligned(mi_heap_t* heap, void* p, size_t newcount, size_t size, size_t alignment) mi_attr_noexcept { + size_t total; + if (mi_count_size_overflow(newcount, size, &total)) return NULL; + return mi_heap_rezalloc_aligned(heap, p, total, alignment); +} + +void* mi_realloc_aligned_at(void* p, size_t newsize, size_t alignment, size_t offset) mi_attr_noexcept { + return mi_heap_realloc_aligned_at(mi_get_default_heap(), p, newsize, alignment, offset); +} + +void* mi_realloc_aligned(void* p, size_t newsize, size_t alignment) mi_attr_noexcept { + return mi_heap_realloc_aligned(mi_get_default_heap(), p, newsize, alignment); +} + +void* mi_rezalloc_aligned_at(void* p, size_t newsize, size_t alignment, size_t offset) mi_attr_noexcept { + return mi_heap_rezalloc_aligned_at(mi_get_default_heap(), p, newsize, alignment, offset); +} + +void* mi_rezalloc_aligned(void* p, size_t newsize, size_t alignment) mi_attr_noexcept { + return mi_heap_rezalloc_aligned(mi_get_default_heap(), p, newsize, alignment); +} + +void* mi_recalloc_aligned_at(void* p, size_t newcount, size_t size, size_t alignment, size_t offset) mi_attr_noexcept { + return mi_heap_recalloc_aligned_at(mi_get_default_heap(), p, newcount, size, alignment, offset); +} + +void* mi_recalloc_aligned(void* p, size_t newcount, size_t size, size_t alignment) mi_attr_noexcept { + return mi_heap_recalloc_aligned(mi_get_default_heap(), p, newcount, size, alignment); +} + diff --git a/kotlin-native/runtime/src/mimalloc/c/alloc-override-osx.c b/kotlin-native/runtime/src/mimalloc/c/alloc-override-osx.c new file mode 100644 index 00000000000..25a6cd4c301 --- /dev/null +++ b/kotlin-native/runtime/src/mimalloc/c/alloc-override-osx.c @@ -0,0 +1,262 @@ +/* ---------------------------------------------------------------------------- +Copyright (c) 2018, Microsoft Research, Daan Leijen +This is free software; you can redistribute it and/or modify it under the +terms of the MIT license. A copy of the license can be found in the file +"licenses/third_party/mimalloc_LICENSE.txt" at the root of this distribution. +-----------------------------------------------------------------------------*/ +// Copyright 2019-2020 JetBrains s.r.o. + +#if !KONAN_MI_MALLOC +#include "mimalloc.h" +#include "mimalloc-internal.h" + +#if defined(MI_MALLOC_OVERRIDE) + +#if !defined(__APPLE__) +#error "this file should only be included on macOS" +#endif + +/* ------------------------------------------------------ + Override system malloc on macOS + This is done through the malloc zone interface. + It seems we also need to interpose (see `alloc-override.c`) + or otherwise we get zone errors as there are usually + already allocations done by the time we take over the + zone. Unfortunately, that means we need to replace + the `free` with a checked free (`cfree`) impacting + performance. +------------------------------------------------------ */ + +#include +#include +#include // memset + +#if defined(MAC_OS_X_VERSION_10_6) && \ + MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_6 +// only available from OSX 10.6 +extern malloc_zone_t* malloc_default_purgeable_zone(void) __attribute__((weak_import)); +#endif + + +/* ------------------------------------------------------ + malloc zone members +------------------------------------------------------ */ + +static size_t zone_size(malloc_zone_t* zone, const void* p) { + UNUSED(zone); + if (!mi_is_in_heap_region(p)) + return 0; // not our pointer, bail out + + return mi_usable_size(p); +} + +static void* zone_malloc(malloc_zone_t* zone, size_t size) { + UNUSED(zone); + return mi_malloc(size); +} + +static void* zone_calloc(malloc_zone_t* zone, size_t count, size_t size) { + UNUSED(zone); + return mi_calloc(count, size); +} + +static void* zone_valloc(malloc_zone_t* zone, size_t size) { + UNUSED(zone); + return mi_malloc_aligned(size, _mi_os_page_size()); +} + +static void zone_free(malloc_zone_t* zone, void* p) { + UNUSED(zone); + return mi_free(p); +} + +static void* zone_realloc(malloc_zone_t* zone, void* p, size_t newsize) { + UNUSED(zone); + return mi_realloc(p, newsize); +} + +static void* zone_memalign(malloc_zone_t* zone, size_t alignment, size_t size) { + UNUSED(zone); + return mi_malloc_aligned(size,alignment); +} + +static void zone_destroy(malloc_zone_t* zone) { + UNUSED(zone); + // todo: ignore for now? +} + +static unsigned zone_batch_malloc(malloc_zone_t* zone, size_t size, void** ps, unsigned count) { + size_t i; + for (i = 0; i < count; i++) { + ps[i] = zone_malloc(zone, size); + if (ps[i] == NULL) break; + } + return i; +} + +static void zone_batch_free(malloc_zone_t* zone, void** ps, unsigned count) { + for(size_t i = 0; i < count; i++) { + zone_free(zone, ps[i]); + ps[i] = NULL; + } +} + +static size_t zone_pressure_relief(malloc_zone_t* zone, size_t size) { + UNUSED(zone); UNUSED(size); + mi_collect(false); + return 0; +} + +static void zone_free_definite_size(malloc_zone_t* zone, void* p, size_t size) { + UNUSED(size); + zone_free(zone,p); +} + + +/* ------------------------------------------------------ + Introspection members +------------------------------------------------------ */ + +static kern_return_t intro_enumerator(task_t task, void* p, + unsigned type_mask, vm_address_t zone_address, + memory_reader_t reader, + vm_range_recorder_t recorder) +{ + // todo: enumerate all memory + UNUSED(task); UNUSED(p); UNUSED(type_mask); UNUSED(zone_address); + UNUSED(reader); UNUSED(recorder); + return KERN_SUCCESS; +} + +static size_t intro_good_size(malloc_zone_t* zone, size_t size) { + UNUSED(zone); + return mi_good_size(size); +} + +static boolean_t intro_check(malloc_zone_t* zone) { + UNUSED(zone); + return true; +} + +static void intro_print(malloc_zone_t* zone, boolean_t verbose) { + UNUSED(zone); UNUSED(verbose); + mi_stats_print(NULL); +} + +static void intro_log(malloc_zone_t* zone, void* p) { + UNUSED(zone); UNUSED(p); + // todo? +} + +static void intro_force_lock(malloc_zone_t* zone) { + UNUSED(zone); + // todo? +} + +static void intro_force_unlock(malloc_zone_t* zone) { + UNUSED(zone); + // todo? +} + +static void intro_statistics(malloc_zone_t* zone, malloc_statistics_t* stats) { + UNUSED(zone); + // todo... + stats->blocks_in_use = 0; + stats->size_in_use = 0; + stats->max_size_in_use = 0; + stats->size_allocated = 0; +} + +static boolean_t intro_zone_locked(malloc_zone_t* zone) { + UNUSED(zone); + return false; +} + + +/* ------------------------------------------------------ + At process start, override the default allocator +------------------------------------------------------ */ + +static malloc_zone_t* mi_get_default_zone() +{ + // The first returned zone is the real default + malloc_zone_t** zones = NULL; + unsigned count = 0; + kern_return_t ret = malloc_get_all_zones(0, NULL, (vm_address_t**)&zones, &count); + if (ret == KERN_SUCCESS && count > 0) { + return zones[0]; + } + else { + // fallback + return malloc_default_zone(); + } +} + +static void __attribute__((constructor)) _mi_macos_override_malloc() +{ + static malloc_introspection_t intro; + memset(&intro, 0, sizeof(intro)); + + intro.enumerator = &intro_enumerator; + intro.good_size = &intro_good_size; + intro.check = &intro_check; + intro.print = &intro_print; + intro.log = &intro_log; + intro.force_lock = &intro_force_lock; + intro.force_unlock = &intro_force_unlock; + + static malloc_zone_t zone; + memset(&zone, 0, sizeof(zone)); + + zone.version = 4; + zone.zone_name = "mimalloc"; + zone.size = &zone_size; + zone.introspect = &intro; + zone.malloc = &zone_malloc; + zone.calloc = &zone_calloc; + zone.valloc = &zone_valloc; + zone.free = &zone_free; + zone.realloc = &zone_realloc; + zone.destroy = &zone_destroy; + zone.batch_malloc = &zone_batch_malloc; + zone.batch_free = &zone_batch_free; + + malloc_zone_t* purgeable_zone = NULL; + +#if defined(MAC_OS_X_VERSION_10_6) && \ + MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_6 + // switch to version 9 on OSX 10.6 to support memalign. + zone.version = 9; + zone.memalign = &zone_memalign; + zone.free_definite_size = &zone_free_definite_size; + zone.pressure_relief = &zone_pressure_relief; + intro.zone_locked = &intro_zone_locked; + intro.statistics = &intro_statistics; + + // force the purgeable zone to exist to avoid strange bugs + if (malloc_default_purgeable_zone) { + purgeable_zone = malloc_default_purgeable_zone(); + } +#endif + + // Register our zone + malloc_zone_register(&zone); + + // Unregister the default zone, this makes our zone the new default + // as that was the last registered. + malloc_zone_t *default_zone = mi_get_default_zone(); + malloc_zone_unregister(default_zone); + + // Reregister the default zone so free and realloc in that zone keep working. + malloc_zone_register(default_zone); + + // Unregister, and re-register the purgeable_zone to avoid bugs if it occurs + // earlier than the default zone. + if (purgeable_zone != NULL) { + malloc_zone_unregister(purgeable_zone); + malloc_zone_register(purgeable_zone); + } +} + +#endif // MI_MALLOC_OVERRIDE +#endif \ No newline at end of file diff --git a/kotlin-native/runtime/src/mimalloc/c/alloc-override.c b/kotlin-native/runtime/src/mimalloc/c/alloc-override.c new file mode 100644 index 00000000000..59f06c0efd0 --- /dev/null +++ b/kotlin-native/runtime/src/mimalloc/c/alloc-override.c @@ -0,0 +1,218 @@ +/* ---------------------------------------------------------------------------- +Copyright (c) 2018, Microsoft Research, Daan Leijen +This is free software; you can redistribute it and/or modify it under the +terms of the MIT license. A copy of the license can be found in the file +"licenses/third_party/mimalloc_LICENSE.txt" at the root of this distribution. +-----------------------------------------------------------------------------*/ +// Copyright 2019-2020 JetBrains s.r.o. + +#if !KONAN_MI_MALLOC +#if !defined(MI_IN_ALLOC_C) +#error "this file should be included from 'alloc.c' (so aliases can work)" +#endif + +#if defined(MI_MALLOC_OVERRIDE) && defined(_WIN32) && !(defined(MI_SHARED_LIB) && defined(_DLL)) +#error "It is only possible to override "malloc" on Windows when building as a DLL (and linking the C runtime as a DLL)" +#endif + +#if defined(MI_MALLOC_OVERRIDE) && !(defined(_WIN32)) // || (defined(__MACH__) && !defined(MI_INTERPOSE))) + +// ------------------------------------------------------ +// Override system malloc +// ------------------------------------------------------ + +#if (defined(__GNUC__) || defined(__clang__)) && !defined(__MACH__) + // use aliasing to alias the exported function to one of our `mi_` functions + #if (defined(__GNUC__) && __GNUC__ >= 9) + #define MI_FORWARD(fun) __attribute__((alias(#fun), used, visibility("default"), copy(fun))) + #else + #define MI_FORWARD(fun) __attribute__((alias(#fun), used, visibility("default"))) + #endif + #define MI_FORWARD1(fun,x) MI_FORWARD(fun) + #define MI_FORWARD2(fun,x,y) MI_FORWARD(fun) + #define MI_FORWARD3(fun,x,y,z) MI_FORWARD(fun) + #define MI_FORWARD0(fun,x) MI_FORWARD(fun) + #define MI_FORWARD02(fun,x,y) MI_FORWARD(fun) +#else + // use forwarding by calling our `mi_` function + #define MI_FORWARD1(fun,x) { return fun(x); } + #define MI_FORWARD2(fun,x,y) { return fun(x,y); } + #define MI_FORWARD3(fun,x,y,z) { return fun(x,y,z); } + #define MI_FORWARD0(fun,x) { fun(x); } + #define MI_FORWARD02(fun,x,y) { fun(x,y); } +#endif + +#if defined(__APPLE__) && defined(MI_SHARED_LIB_EXPORT) && defined(MI_INTERPOSE) + // use interposing so `DYLD_INSERT_LIBRARIES` works without `DYLD_FORCE_FLAT_NAMESPACE=1` + // See: + struct mi_interpose_s { + const void* replacement; + const void* target; + }; + #define MI_INTERPOSE_FUN(oldfun,newfun) { (const void*)&newfun, (const void*)&oldfun } + #define MI_INTERPOSE_MI(fun) MI_INTERPOSE_FUN(fun,mi_##fun) + __attribute__((used)) static struct mi_interpose_s _mi_interposes[] __attribute__((section("__DATA, __interpose"))) = + { + MI_INTERPOSE_MI(malloc), + MI_INTERPOSE_MI(calloc), + MI_INTERPOSE_MI(realloc), + MI_INTERPOSE_MI(strdup), + MI_INTERPOSE_MI(strndup), + MI_INTERPOSE_MI(realpath), + MI_INTERPOSE_MI(posix_memalign), + MI_INTERPOSE_MI(reallocf), + MI_INTERPOSE_MI(valloc), + // some code allocates from a zone but deallocates using plain free :-( (like NxHashResizeToCapacity ) + MI_INTERPOSE_FUN(free,mi_cfree), // use safe free that checks if pointers are from us + }; +#elif defined(_MSC_VER) + // cannot override malloc unless using a dll. + // we just override new/delete which does work in a static library. +#else + // On all other systems forward to our API + void* malloc(size_t size) MI_FORWARD1(mi_malloc, size); + void* calloc(size_t size, size_t n) MI_FORWARD2(mi_calloc, size, n); + void* realloc(void* p, size_t newsize) MI_FORWARD2(mi_realloc, p, newsize); + void free(void* p) MI_FORWARD0(mi_free, p); +#endif + +#if (defined(__GNUC__) || defined(__clang__)) && !defined(__MACH__) +#pragma GCC visibility push(default) +#endif + +// ------------------------------------------------------ +// Override new/delete +// This is not really necessary as they usually call +// malloc/free anyway, but it improves performance. +// ------------------------------------------------------ +#ifdef __cplusplus + // ------------------------------------------------------ + // With a C++ compiler we override the new/delete operators. + // see + // ------------------------------------------------------ + #include + void operator delete(void* p) noexcept MI_FORWARD0(mi_free,p); + void operator delete[](void* p) noexcept MI_FORWARD0(mi_free,p); + + void* operator new(std::size_t n) noexcept(false) MI_FORWARD1(mi_new,n); + void* operator new[](std::size_t n) noexcept(false) MI_FORWARD1(mi_new,n); + + void* operator new (std::size_t n, const std::nothrow_t& tag) noexcept { UNUSED(tag); return mi_new_nothrow(n); } + void* operator new[](std::size_t n, const std::nothrow_t& tag) noexcept { UNUSED(tag); return mi_new_nothrow(n); } + + #if (__cplusplus >= 201402L || _MSC_VER >= 1916) + void operator delete (void* p, std::size_t n) noexcept MI_FORWARD02(mi_free_size,p,n); + void operator delete[](void* p, std::size_t n) noexcept MI_FORWARD02(mi_free_size,p,n); + #endif + + #if (__cplusplus > 201402L && defined(__cpp_aligned_new)) && (!defined(__GNUC__) || (__GNUC__ > 5)) + void operator delete (void* p, std::align_val_t al) noexcept { mi_free_aligned(p, static_cast(al)); } + void operator delete[](void* p, std::align_val_t al) noexcept { mi_free_aligned(p, static_cast(al)); } + void operator delete (void* p, std::size_t n, std::align_val_t al) noexcept { mi_free_size_aligned(p, n, static_cast(al)); }; + void operator delete[](void* p, std::size_t n, std::align_val_t al) noexcept { mi_free_size_aligned(p, n, static_cast(al)); }; + + void* operator new( std::size_t n, std::align_val_t al) noexcept(false) { return mi_new_aligned(n, static_cast(al)); } + void* operator new[]( std::size_t n, std::align_val_t al) noexcept(false) { return mi_new_aligned(n, static_cast(al)); } + void* operator new (std::size_t n, std::align_val_t al, const std::nothrow_t&) noexcept { return mi_new_aligned_nothrow(n, static_cast(al)); } + void* operator new[](std::size_t n, std::align_val_t al, const std::nothrow_t&) noexcept { return mi_new_aligned_nothrow(n, static_cast(al)); } + #endif + +#elif (defined(__GNUC__) || defined(__clang__)) + // ------------------------------------------------------ + // Override by defining the mangled C++ names of the operators (as + // used by GCC and CLang). + // See + // ------------------------------------------------------ + void _ZdlPv(void* p) MI_FORWARD0(mi_free,p); // delete + void _ZdaPv(void* p) MI_FORWARD0(mi_free,p); // delete[] + void _ZdlPvm(void* p, size_t n) MI_FORWARD02(mi_free_size,p,n); + void _ZdaPvm(void* p, size_t n) MI_FORWARD02(mi_free_size,p,n); + void _ZdlPvSt11align_val_t(void* p, size_t al) { mi_free_aligned(p,al); } + void _ZdaPvSt11align_val_t(void* p, size_t al) { mi_free_aligned(p,al); } + void _ZdlPvmSt11align_val_t(void* p, size_t n, size_t al) { mi_free_size_aligned(p,n,al); } + void _ZdaPvmSt11align_val_t(void* p, size_t n, size_t al) { mi_free_size_aligned(p,n,al); } + + typedef struct mi_nothrow_s { } mi_nothrow_t; + #if (MI_INTPTR_SIZE==8) + void* _Znwm(size_t n) MI_FORWARD1(mi_new,n); // new 64-bit + void* _Znam(size_t n) MI_FORWARD1(mi_new,n); // new[] 64-bit + void* _ZnwmSt11align_val_t(size_t n, size_t al) MI_FORWARD2(mi_new_aligned, n, al); + void* _ZnamSt11align_val_t(size_t n, size_t al) MI_FORWARD2(mi_new_aligned, n, al); + void* _ZnwmRKSt9nothrow_t(size_t n, mi_nothrow_t tag) { UNUSED(tag); return mi_new_nothrow(n); } + void* _ZnamRKSt9nothrow_t(size_t n, mi_nothrow_t tag) { UNUSED(tag); return mi_new_nothrow(n); } + void* _ZnwmSt11align_val_tRKSt9nothrow_t(size_t n, size_t al, mi_nothrow_t tag) { UNUSED(tag); return mi_new_aligned_nothrow(n,al); } + void* _ZnamSt11align_val_tRKSt9nothrow_t(size_t n, size_t al, mi_nothrow_t tag) { UNUSED(tag); return mi_new_aligned_nothrow(n,al); } + #elif (MI_INTPTR_SIZE==4) + void* _Znwj(size_t n) MI_FORWARD1(mi_new,n); // new 64-bit + void* _Znaj(size_t n) MI_FORWARD1(mi_new,n); // new[] 64-bit + void* _ZnwjSt11align_val_t(size_t n, size_t al) MI_FORWARD2(mi_new_aligned, n, al); + void* _ZnajSt11align_val_t(size_t n, size_t al) MI_FORWARD2(mi_new_aligned, n, al); + void* _ZnwjRKSt9nothrow_t(size_t n, mi_nothrow_t tag) { UNUSED(tag); return mi_new_nothrow(n); } + void* _ZnajRKSt9nothrow_t(size_t n, mi_nothrow_t tag) { UNUSED(tag); return mi_new_nothrow(n); } + void* _ZnwjSt11align_val_tRKSt9nothrow_t(size_t n, size_t al, mi_nothrow_t tag) { UNUSED(tag); return mi_new_aligned_nothrow(n,al); } + void* _ZnajSt11align_val_tRKSt9nothrow_t(size_t n, size_t al, mi_nothrow_t tag) { UNUSED(tag); return mi_new_aligned_nothrow(n,al); } + #else + #error "define overloads for new/delete for this platform (just for performance, can be skipped)" + #endif +#endif // __cplusplus + + +#ifdef __cplusplus +extern "C" { +#endif + +// ------------------------------------------------------ +// Posix & Unix functions definitions +// ------------------------------------------------------ + +void cfree(void* p) MI_FORWARD0(mi_free, p); +void* reallocf(void* p, size_t newsize) MI_FORWARD2(mi_reallocf,p,newsize); +size_t malloc_size(const void* p) MI_FORWARD1(mi_usable_size,p); +#if !defined(__ANDROID__) +size_t malloc_usable_size(void *p) MI_FORWARD1(mi_usable_size,p); +#else +size_t malloc_usable_size(const void *p) MI_FORWARD1(mi_usable_size,p); +#endif + +// no forwarding here due to aliasing/name mangling issues +void* valloc(size_t size) { return mi_valloc(size); } +void* pvalloc(size_t size) { return mi_pvalloc(size); } +void* reallocarray(void* p, size_t count, size_t size) { return mi_reallocarray(p, count, size); } +void* memalign(size_t alignment, size_t size) { return mi_memalign(alignment, size); } +int posix_memalign(void** p, size_t alignment, size_t size) { return mi_posix_memalign(p, alignment, size); } +void* _aligned_malloc(size_t alignment, size_t size) { return mi_aligned_alloc(alignment, size); } + +// on some glibc `aligned_alloc` is declared `static inline` so we cannot override it (e.g. Conda). This happens +// when _GLIBCXX_HAVE_ALIGNED_ALLOC is not defined. However, in those cases it will use `memalign`, `posix_memalign`, +// or `_aligned_malloc` and we can avoid overriding it ourselves. +// We should always override if using C compilation. (issue #276) +#if _GLIBCXX_HAVE_ALIGNED_ALLOC || !defined(__cplusplus) +void* aligned_alloc(size_t alignment, size_t size) { return mi_aligned_alloc(alignment, size); } +#endif + + +#if defined(__GLIBC__) && defined(__linux__) + // forward __libc interface (needed for glibc-based Linux distributions) + void* __libc_malloc(size_t size) MI_FORWARD1(mi_malloc,size); + void* __libc_calloc(size_t count, size_t size) MI_FORWARD2(mi_calloc,count,size); + void* __libc_realloc(void* p, size_t size) MI_FORWARD2(mi_realloc,p,size); + void __libc_free(void* p) MI_FORWARD0(mi_free,p); + void __libc_cfree(void* p) MI_FORWARD0(mi_free,p); + + void* __libc_valloc(size_t size) { return mi_valloc(size); } + void* __libc_pvalloc(size_t size) { return mi_pvalloc(size); } + void* __libc_memalign(size_t alignment, size_t size) { return mi_memalign(alignment,size); } + int __posix_memalign(void** p, size_t alignment, size_t size) { return mi_posix_memalign(p,alignment,size); } +#endif + +#ifdef __cplusplus +} +#endif + +#if (defined(__GNUC__) || defined(__clang__)) && !defined(__MACH__) +#pragma GCC visibility pop +#endif + +#endif // MI_MALLOC_OVERRIDE && !_WIN32 + +#endif // KONAN_MI_MALLOC diff --git a/kotlin-native/runtime/src/mimalloc/c/alloc-posix.c b/kotlin-native/runtime/src/mimalloc/c/alloc-posix.c new file mode 100644 index 00000000000..193fe1dfc1a --- /dev/null +++ b/kotlin-native/runtime/src/mimalloc/c/alloc-posix.c @@ -0,0 +1,157 @@ +/* ---------------------------------------------------------------------------- +Copyright (c) 2018,2019, Microsoft Research, Daan Leijen +This is free software; you can redistribute it and/or modify it under the +terms of the MIT license. A copy of the license can be found in the file +"licenses/third_party/mimalloc_LICENSE.txt" at the root of this distribution. +-----------------------------------------------------------------------------*/ + +// ------------------------------------------------------------------------ +// mi prefixed publi definitions of various Posix, Unix, and C++ functions +// for convenience and used when overriding these functions. +// ------------------------------------------------------------------------ +#include "mimalloc.h" +#include "mimalloc-internal.h" + +// ------------------------------------------------------ +// Posix & Unix functions definitions +// ------------------------------------------------------ + +#include +#include // memcpy +#include // getenv + +#ifdef _MSC_VER +#pragma warning(disable:4996) // getenv _wgetenv +#endif + +#ifndef EINVAL +#define EINVAL 22 +#endif +#ifndef ENOMEM +#define ENOMEM 12 +#endif + + +size_t mi_malloc_size(const void* p) mi_attr_noexcept { + return mi_usable_size(p); +} + +size_t mi_malloc_usable_size(const void *p) mi_attr_noexcept { + return mi_usable_size(p); +} + +void mi_cfree(void* p) mi_attr_noexcept { + if (mi_is_in_heap_region(p)) { + mi_free(p); + } +} + +int mi_posix_memalign(void** p, size_t alignment, size_t size) mi_attr_noexcept { + // Note: The spec dictates we should not modify `*p` on an error. (issue#27) + // + if (p == NULL) return EINVAL; + if (alignment % sizeof(void*) != 0) return EINVAL; // natural alignment + if (!_mi_is_power_of_two(alignment)) return EINVAL; // not a power of 2 + void* q = (mi_malloc_satisfies_alignment(alignment, size) ? mi_malloc(size) : mi_malloc_aligned(size, alignment)); + if (q==NULL && size != 0) return ENOMEM; + mi_assert_internal(((uintptr_t)q % alignment) == 0); + *p = q; + return 0; +} + +mi_decl_restrict void* mi_memalign(size_t alignment, size_t size) mi_attr_noexcept { + void* p = (mi_malloc_satisfies_alignment(alignment,size) ? mi_malloc(size) : mi_malloc_aligned(size, alignment)); + mi_assert_internal(((uintptr_t)p % alignment) == 0); + return p; +} + +mi_decl_restrict void* mi_valloc(size_t size) mi_attr_noexcept { + return mi_memalign( _mi_os_page_size(), size ); +} + +mi_decl_restrict void* mi_pvalloc(size_t size) mi_attr_noexcept { + size_t psize = _mi_os_page_size(); + if (size >= SIZE_MAX - psize) return NULL; // overflow + size_t asize = _mi_align_up(size, psize); + return mi_malloc_aligned(asize, psize); +} + +mi_decl_restrict void* mi_aligned_alloc(size_t alignment, size_t size) mi_attr_noexcept { + if (alignment==0 || !_mi_is_power_of_two(alignment)) return NULL; + if ((size&(alignment-1)) != 0) return NULL; // C11 requires integral multiple, see + void* p = (mi_malloc_satisfies_alignment(alignment, size) ? mi_malloc(size) : mi_malloc_aligned(size, alignment)); + mi_assert_internal(((uintptr_t)p % alignment) == 0); + return p; +} + +void* mi_reallocarray( void* p, size_t count, size_t size ) mi_attr_noexcept { // BSD + void* newp = mi_reallocn(p,count,size); + if (newp==NULL) errno = ENOMEM; + return newp; +} + +void* mi__expand(void* p, size_t newsize) mi_attr_noexcept { // Microsoft + void* res = mi_expand(p, newsize); + if (res == NULL) errno = ENOMEM; + return res; +} + +mi_decl_restrict unsigned short* mi_wcsdup(const unsigned short* s) mi_attr_noexcept { + if (s==NULL) return NULL; + size_t len; + for(len = 0; s[len] != 0; len++) { } + size_t size = (len+1)*sizeof(unsigned short); + unsigned short* p = (unsigned short*)mi_malloc(size); + if (p != NULL) { + memcpy(p,s,size); + } + return p; +} + +mi_decl_restrict unsigned char* mi_mbsdup(const unsigned char* s) mi_attr_noexcept { + return (unsigned char*)mi_strdup((const char*)s); +} + +int mi_dupenv_s(char** buf, size_t* size, const char* name) mi_attr_noexcept { + if (buf==NULL || name==NULL) return EINVAL; + if (size != NULL) *size = 0; + char* p = getenv(name); // mscver warning 4996 + if (p==NULL) { + *buf = NULL; + } + else { + *buf = mi_strdup(p); + if (*buf==NULL) return ENOMEM; + if (size != NULL) *size = strlen(p); + } + return 0; +} + +int mi_wdupenv_s(unsigned short** buf, size_t* size, const unsigned short* name) mi_attr_noexcept { + if (buf==NULL || name==NULL) return EINVAL; + if (size != NULL) *size = 0; +#if !defined(_WIN32) || (defined(WINAPI_FAMILY) && (WINAPI_FAMILY != WINAPI_FAMILY_DESKTOP_APP)) + // not supported + *buf = NULL; + return EINVAL; +#else + unsigned short* p = (unsigned short*)_wgetenv((const wchar_t*)name); // msvc warning 4996 + if (p==NULL) { + *buf = NULL; + } + else { + *buf = mi_wcsdup(p); + if (*buf==NULL) return ENOMEM; + if (size != NULL) *size = wcslen((const wchar_t*)p); + } + return 0; +#endif +} + +void* mi_aligned_offset_recalloc(void* p, size_t newcount, size_t size, size_t alignment, size_t offset) mi_attr_noexcept { // Microsoft + return mi_recalloc_aligned_at(p, newcount, size, alignment, offset); +} + +void* mi_aligned_recalloc(void* p, size_t newcount, size_t size, size_t alignment) mi_attr_noexcept { // Microsoft + return mi_recalloc_aligned(p, newcount, size, alignment); +} diff --git a/kotlin-native/runtime/src/mimalloc/c/alloc.c b/kotlin-native/runtime/src/mimalloc/c/alloc.c new file mode 100644 index 00000000000..3508fb30fdd --- /dev/null +++ b/kotlin-native/runtime/src/mimalloc/c/alloc.c @@ -0,0 +1,855 @@ +/* ---------------------------------------------------------------------------- +Copyright (c) 2018, Microsoft Research, Daan Leijen +This is free software; you can redistribute it and/or modify it under the +terms of the MIT license. A copy of the license can be found in the file +"licenses/third_party/mimalloc_LICENSE.txt" at the root of this distribution. +-----------------------------------------------------------------------------*/ +#include "mimalloc.h" +#include "mimalloc-internal.h" +#include "mimalloc-atomic.h" + +#include // memset, memcpy, strlen +#include // malloc, exit + +#define MI_IN_ALLOC_C +#include "alloc-override.c" +#undef MI_IN_ALLOC_C + +// ------------------------------------------------------ +// Allocation +// ------------------------------------------------------ + +// Fast allocation in a page: just pop from the free list. +// Fall back to generic allocation only if the list is empty. +extern inline void* _mi_page_malloc(mi_heap_t* heap, mi_page_t* page, size_t size) mi_attr_noexcept { + mi_assert_internal(page->xblock_size==0||mi_page_block_size(page) >= size); + mi_block_t* block = page->free; + if (mi_unlikely(block == NULL)) { + return _mi_malloc_generic(heap, size); + } + mi_assert_internal(block != NULL && _mi_ptr_page(block) == page); + // pop from the free list + page->free = mi_block_next(page, block); + page->used++; + mi_assert_internal(page->free == NULL || _mi_ptr_page(page->free) == page); +#if (MI_DEBUG>0) + if (!page->is_zero) { memset(block, MI_DEBUG_UNINIT, size); } +#elif (MI_SECURE!=0) + block->next = 0; // don't leak internal data +#endif +#if (MI_STAT>1) + const size_t bsize = mi_page_usable_block_size(page); + if (bsize <= MI_LARGE_OBJ_SIZE_MAX) { + const size_t bin = _mi_bin(bsize); + mi_heap_stat_increase(heap, normal[bin], 1); + } +#endif +#if (MI_PADDING > 0) && defined(MI_ENCODE_FREELIST) + mi_padding_t* const padding = (mi_padding_t*)((uint8_t*)block + mi_page_usable_block_size(page)); + ptrdiff_t delta = ((uint8_t*)padding - (uint8_t*)block - (size - MI_PADDING_SIZE)); + mi_assert_internal(delta >= 0 && mi_page_usable_block_size(page) >= (size - MI_PADDING_SIZE + delta)); + padding->canary = (uint32_t)(mi_ptr_encode(page,block,page->keys)); + padding->delta = (uint32_t)(delta); + uint8_t* fill = (uint8_t*)padding - delta; + const size_t maxpad = (delta > MI_MAX_ALIGN_SIZE ? MI_MAX_ALIGN_SIZE : delta); // set at most N initial padding bytes + for (size_t i = 0; i < maxpad; i++) { fill[i] = MI_DEBUG_PADDING; } +#endif + return block; +} + +// allocate a small block +extern inline mi_decl_restrict void* mi_heap_malloc_small(mi_heap_t* heap, size_t size) mi_attr_noexcept { + mi_assert(heap!=NULL); + mi_assert(heap->thread_id == 0 || heap->thread_id == _mi_thread_id()); // heaps are thread local + mi_assert(size <= MI_SMALL_SIZE_MAX); + #if (MI_PADDING) + if (size == 0) { + size = sizeof(void*); + } + #endif + mi_page_t* page = _mi_heap_get_free_small_page(heap,size + MI_PADDING_SIZE); + void* p = _mi_page_malloc(heap, page, size + MI_PADDING_SIZE); + mi_assert_internal(p==NULL || mi_usable_size(p) >= size); + #if MI_STAT>1 + if (p != NULL) { + if (!mi_heap_is_initialized(heap)) { heap = mi_get_default_heap(); } + mi_heap_stat_increase(heap, malloc, mi_usable_size(p)); + } + #endif + return p; +} + +extern inline mi_decl_restrict void* mi_malloc_small(size_t size) mi_attr_noexcept { + return mi_heap_malloc_small(mi_get_default_heap(), size); +} + +// The main allocation function +extern inline mi_decl_restrict void* mi_heap_malloc(mi_heap_t* heap, size_t size) mi_attr_noexcept { + if (mi_likely(size <= MI_SMALL_SIZE_MAX)) { + return mi_heap_malloc_small(heap, size); + } + else { + mi_assert(heap!=NULL); + mi_assert(heap->thread_id == 0 || heap->thread_id == _mi_thread_id()); // heaps are thread local + void* const p = _mi_malloc_generic(heap, size + MI_PADDING_SIZE); // note: size can overflow but it is detected in malloc_generic + mi_assert_internal(p == NULL || mi_usable_size(p) >= size); + #if MI_STAT>1 + if (p != NULL) { + if (!mi_heap_is_initialized(heap)) { heap = mi_get_default_heap(); } + mi_heap_stat_increase(heap, malloc, mi_usable_size(p)); + } + #endif + return p; + } +} + +extern inline mi_decl_restrict void* mi_malloc(size_t size) mi_attr_noexcept { + return mi_heap_malloc(mi_get_default_heap(), size); +} + + +void _mi_block_zero_init(const mi_page_t* page, void* p, size_t size) { + // note: we need to initialize the whole usable block size to zero, not just the requested size, + // or the recalloc/rezalloc functions cannot safely expand in place (see issue #63) + UNUSED(size); + mi_assert_internal(p != NULL); + mi_assert_internal(mi_usable_size(p) >= size); // size can be zero + mi_assert_internal(_mi_ptr_page(p)==page); + if (page->is_zero && size > sizeof(mi_block_t)) { + // already zero initialized memory + ((mi_block_t*)p)->next = 0; // clear the free list pointer + mi_assert_expensive(mi_mem_is_zero(p, mi_usable_size(p))); + } + else { + // otherwise memset + memset(p, 0, mi_usable_size(p)); + } +} + +// zero initialized small block +mi_decl_restrict void* mi_zalloc_small(size_t size) mi_attr_noexcept { + void* p = mi_malloc_small(size); + if (p != NULL) { + _mi_block_zero_init(_mi_ptr_page(p), p, size); // todo: can we avoid getting the page again? + } + return p; +} + +void* _mi_heap_malloc_zero(mi_heap_t* heap, size_t size, bool zero) { + void* p = mi_heap_malloc(heap,size); + if (zero && p != NULL) { + _mi_block_zero_init(_mi_ptr_page(p),p,size); // todo: can we avoid getting the page again? + } + return p; +} + +extern inline mi_decl_restrict void* mi_heap_zalloc(mi_heap_t* heap, size_t size) mi_attr_noexcept { + return _mi_heap_malloc_zero(heap, size, true); +} + +mi_decl_restrict void* mi_zalloc(size_t size) mi_attr_noexcept { + return mi_heap_zalloc(mi_get_default_heap(),size); +} + + +// ------------------------------------------------------ +// Check for double free in secure and debug mode +// This is somewhat expensive so only enabled for secure mode 4 +// ------------------------------------------------------ + +#if (MI_ENCODE_FREELIST && (MI_SECURE>=4 || MI_DEBUG!=0)) +// linear check if the free list contains a specific element +static bool mi_list_contains(const mi_page_t* page, const mi_block_t* list, const mi_block_t* elem) { + while (list != NULL) { + if (elem==list) return true; + list = mi_block_next(page, list); + } + return false; +} + +static mi_decl_noinline bool mi_check_is_double_freex(const mi_page_t* page, const mi_block_t* block) { + // The decoded value is in the same page (or NULL). + // Walk the free lists to verify positively if it is already freed + if (mi_list_contains(page, page->free, block) || + mi_list_contains(page, page->local_free, block) || + mi_list_contains(page, mi_page_thread_free(page), block)) + { + _mi_error_message(EAGAIN, "double free detected of block %p with size %zu\n", block, mi_page_block_size(page)); + return true; + } + return false; +} + +static inline bool mi_check_is_double_free(const mi_page_t* page, const mi_block_t* block) { + mi_block_t* n = mi_block_nextx(page, block, page->keys); // pretend it is freed, and get the decoded first field + if (((uintptr_t)n & (MI_INTPTR_SIZE-1))==0 && // quick check: aligned pointer? + (n==NULL || mi_is_in_same_page(block, n))) // quick check: in same page or NULL? + { + // Suspicous: decoded value a in block is in the same page (or NULL) -- maybe a double free? + // (continue in separate function to improve code generation) + return mi_check_is_double_freex(page, block); + } + return false; +} +#else +static inline bool mi_check_is_double_free(const mi_page_t* page, const mi_block_t* block) { + UNUSED(page); + UNUSED(block); + return false; +} +#endif + +// --------------------------------------------------------------------------- +// Check for heap block overflow by setting up padding at the end of the block +// --------------------------------------------------------------------------- + +#if (MI_PADDING>0) && defined(MI_ENCODE_FREELIST) +static bool mi_page_decode_padding(const mi_page_t* page, const mi_block_t* block, size_t* delta, size_t* bsize) { + *bsize = mi_page_usable_block_size(page); + const mi_padding_t* const padding = (mi_padding_t*)((uint8_t*)block + *bsize); + *delta = padding->delta; + return ((uint32_t)mi_ptr_encode(page,block,page->keys) == padding->canary && *delta <= *bsize); +} + +// Return the exact usable size of a block. +static size_t mi_page_usable_size_of(const mi_page_t* page, const mi_block_t* block) { + size_t bsize; + size_t delta; + bool ok = mi_page_decode_padding(page, block, &delta, &bsize); + mi_assert_internal(ok); mi_assert_internal(delta <= bsize); + return (ok ? bsize - delta : 0); +} + +static bool mi_verify_padding(const mi_page_t* page, const mi_block_t* block, size_t* size, size_t* wrong) { + size_t bsize; + size_t delta; + bool ok = mi_page_decode_padding(page, block, &delta, &bsize); + *size = *wrong = bsize; + if (!ok) return false; + mi_assert_internal(bsize >= delta); + *size = bsize - delta; + uint8_t* fill = (uint8_t*)block + bsize - delta; + const size_t maxpad = (delta > MI_MAX_ALIGN_SIZE ? MI_MAX_ALIGN_SIZE : delta); // check at most the first N padding bytes + for (size_t i = 0; i < maxpad; i++) { + if (fill[i] != MI_DEBUG_PADDING) { + *wrong = bsize - delta + i; + return false; + } + } + return true; +} + +static void mi_check_padding(const mi_page_t* page, const mi_block_t* block) { + size_t size; + size_t wrong; + if (!mi_verify_padding(page,block,&size,&wrong)) { + _mi_error_message(EFAULT, "buffer overflow in heap block %p of size %zu: write after %zu bytes\n", block, size, wrong ); + } +} + +// When a non-thread-local block is freed, it becomes part of the thread delayed free +// list that is freed later by the owning heap. If the exact usable size is too small to +// contain the pointer for the delayed list, then shrink the padding (by decreasing delta) +// so it will later not trigger an overflow error in `mi_free_block`. +static void mi_padding_shrink(const mi_page_t* page, const mi_block_t* block, const size_t min_size) { + size_t bsize; + size_t delta; + bool ok = mi_page_decode_padding(page, block, &delta, &bsize); + mi_assert_internal(ok); + if (!ok || (bsize - delta) >= min_size) return; // usually already enough space + mi_assert_internal(bsize >= min_size); + if (bsize < min_size) return; // should never happen + size_t new_delta = (bsize - min_size); + mi_assert_internal(new_delta < bsize); + mi_padding_t* padding = (mi_padding_t*)((uint8_t*)block + bsize); + padding->delta = (uint32_t)new_delta; +} +#else +static void mi_check_padding(const mi_page_t* page, const mi_block_t* block) { + UNUSED(page); + UNUSED(block); +} + +static size_t mi_page_usable_size_of(const mi_page_t* page, const mi_block_t* block) { + UNUSED(block); + return mi_page_usable_block_size(page); +} + +static void mi_padding_shrink(const mi_page_t* page, const mi_block_t* block, const size_t min_size) { + UNUSED(page); + UNUSED(block); + UNUSED(min_size); +} +#endif + +// ------------------------------------------------------ +// Free +// ------------------------------------------------------ + +// multi-threaded free +static mi_decl_noinline void _mi_free_block_mt(mi_page_t* page, mi_block_t* block) +{ + // The padding check may access the non-thread-owned page for the key values. + // that is safe as these are constant and the page won't be freed (as the block is not freed yet). + mi_check_padding(page, block); + mi_padding_shrink(page, block, sizeof(mi_block_t)); // for small size, ensure we can fit the delayed thread pointers without triggering overflow detection + #if (MI_DEBUG!=0) + memset(block, MI_DEBUG_FREED, mi_usable_size(block)); + #endif + + // huge page segments are always abandoned and can be freed immediately + mi_segment_t* const segment = _mi_page_segment(page); + if (segment->page_kind==MI_PAGE_HUGE) { + _mi_segment_huge_page_free(segment, page, block); + return; + } + + // Try to put the block on either the page-local thread free list, or the heap delayed free list. + mi_thread_free_t tfreex; + bool use_delayed; + mi_thread_free_t tfree = mi_atomic_load_relaxed(&page->xthread_free); + do { + use_delayed = (mi_tf_delayed(tfree) == MI_USE_DELAYED_FREE); + if (mi_unlikely(use_delayed)) { + // unlikely: this only happens on the first concurrent free in a page that is in the full list + tfreex = mi_tf_set_delayed(tfree,MI_DELAYED_FREEING); + } + else { + // usual: directly add to page thread_free list + mi_block_set_next(page, block, mi_tf_block(tfree)); + tfreex = mi_tf_set_block(tfree,block); + } + } while (!mi_atomic_cas_weak_release(&page->xthread_free, &tfree, tfreex)); + + if (mi_unlikely(use_delayed)) { + // racy read on `heap`, but ok because MI_DELAYED_FREEING is set (see `mi_heap_delete` and `mi_heap_collect_abandon`) + mi_heap_t* const heap = (mi_heap_t*)(mi_atomic_load_acquire(&page->xheap)); //mi_page_heap(page); + mi_assert_internal(heap != NULL); + if (heap != NULL) { + // add to the delayed free list of this heap. (do this atomically as the lock only protects heap memory validity) + mi_block_t* dfree = mi_atomic_load_ptr_relaxed(mi_block_t, &heap->thread_delayed_free); + do { + mi_block_set_nextx(heap,block,dfree, heap->keys); + } while (!mi_atomic_cas_ptr_weak_release(mi_block_t,&heap->thread_delayed_free, &dfree, block)); + } + + // and reset the MI_DELAYED_FREEING flag + tfree = mi_atomic_load_relaxed(&page->xthread_free); + do { + tfreex = tfree; + mi_assert_internal(mi_tf_delayed(tfree) == MI_DELAYED_FREEING); + tfreex = mi_tf_set_delayed(tfree,MI_NO_DELAYED_FREE); + } while (!mi_atomic_cas_weak_release(&page->xthread_free, &tfree, tfreex)); + } +} + + +// regular free +static inline void _mi_free_block(mi_page_t* page, bool local, mi_block_t* block) +{ + // and push it on the free list + if (mi_likely(local)) { + // owning thread can free a block directly + if (mi_unlikely(mi_check_is_double_free(page, block))) return; + mi_check_padding(page, block); + #if (MI_DEBUG!=0) + memset(block, MI_DEBUG_FREED, mi_page_block_size(page)); + #endif + mi_block_set_next(page, block, page->local_free); + page->local_free = block; + page->used--; + if (mi_unlikely(mi_page_all_free(page))) { + _mi_page_retire(page); + } + else if (mi_unlikely(mi_page_is_in_full(page))) { + _mi_page_unfull(page); + } + } + else { + _mi_free_block_mt(page,block); + } +} + + +// Adjust a block that was allocated aligned, to the actual start of the block in the page. +mi_block_t* _mi_page_ptr_unalign(const mi_segment_t* segment, const mi_page_t* page, const void* p) { + mi_assert_internal(page!=NULL && p!=NULL); + const size_t diff = (uint8_t*)p - _mi_page_start(segment, page, NULL); + const size_t adjust = (diff % mi_page_block_size(page)); + return (mi_block_t*)((uintptr_t)p - adjust); +} + + +static void mi_decl_noinline mi_free_generic(const mi_segment_t* segment, bool local, void* p) { + mi_page_t* const page = _mi_segment_page_of(segment, p); + mi_block_t* const block = (mi_page_has_aligned(page) ? _mi_page_ptr_unalign(segment, page, p) : (mi_block_t*)p); + _mi_free_block(page, local, block); +} + +// Get the segment data belonging to a pointer +// This is just a single `and` in assembly but does further checks in debug mode +// (and secure mode) if this was a valid pointer. +static inline mi_segment_t* mi_checked_ptr_segment(const void* p, const char* msg) +{ + UNUSED(msg); +#if (MI_DEBUG>0) + if (mi_unlikely(((uintptr_t)p & (MI_INTPTR_SIZE - 1)) != 0)) { + _mi_error_message(EINVAL, "%s: invalid (unaligned) pointer: %p\n", msg, p); + return NULL; + } +#endif + + mi_segment_t* const segment = _mi_ptr_segment(p); + if (mi_unlikely(segment == NULL)) return NULL; // checks also for (p==NULL) + +#if (MI_DEBUG>0) + if (mi_unlikely(!mi_is_in_heap_region(p))) { + _mi_warning_message("%s: pointer might not point to a valid heap region: %p\n" + "(this may still be a valid very large allocation (over 64MiB))\n", msg, p); + if (mi_likely(_mi_ptr_cookie(segment) == segment->cookie)) { + _mi_warning_message("(yes, the previous pointer %p was valid after all)\n", p); + } + } +#endif +#if (MI_DEBUG>0 || MI_SECURE>=4) + if (mi_unlikely(_mi_ptr_cookie(segment) != segment->cookie)) { + _mi_error_message(EINVAL, "%s: pointer does not point to a valid heap space: %p\n", p); + } +#endif + return segment; +} + + +// Free a block +void mi_free(void* p) mi_attr_noexcept +{ + const mi_segment_t* const segment = mi_checked_ptr_segment(p,"mi_free"); + if (mi_unlikely(segment == NULL)) return; + + const uintptr_t tid = _mi_thread_id(); + mi_page_t* const page = _mi_segment_page_of(segment, p); + mi_block_t* const block = (mi_block_t*)p; + +#if (MI_STAT>1) + mi_heap_t* const heap = mi_heap_get_default(); + const size_t bsize = mi_page_usable_block_size(page); + mi_heap_stat_decrease(heap, malloc, bsize); + if (bsize <= MI_LARGE_OBJ_SIZE_MAX) { // huge page stats are accounted for in `_mi_page_retire` + mi_heap_stat_decrease(heap, normal[_mi_bin(bsize)], 1); + } +#endif + + if (mi_likely(tid == segment->thread_id && page->flags.full_aligned == 0)) { // the thread id matches and it is not a full page, nor has aligned blocks + // local, and not full or aligned + if (mi_unlikely(mi_check_is_double_free(page,block))) return; + mi_check_padding(page, block); + #if (MI_DEBUG!=0) + memset(block, MI_DEBUG_FREED, mi_page_block_size(page)); + #endif + mi_block_set_next(page, block, page->local_free); + page->local_free = block; + if (mi_unlikely(--page->used == 0)) { // using this expression generates better code than: page->used--; if (mi_page_all_free(page)) + _mi_page_retire(page); + } + } + else { + // non-local, aligned blocks, or a full page; use the more generic path + // note: recalc page in generic to improve code generation + mi_free_generic(segment, tid == segment->thread_id, p); + } +} + +bool _mi_free_delayed_block(mi_block_t* block) { + // get segment and page + const mi_segment_t* const segment = _mi_ptr_segment(block); + mi_assert_internal(_mi_ptr_cookie(segment) == segment->cookie); + mi_assert_internal(_mi_thread_id() == segment->thread_id); + mi_page_t* const page = _mi_segment_page_of(segment, block); + + // Clear the no-delayed flag so delayed freeing is used again for this page. + // This must be done before collecting the free lists on this page -- otherwise + // some blocks may end up in the page `thread_free` list with no blocks in the + // heap `thread_delayed_free` list which may cause the page to be never freed! + // (it would only be freed if we happen to scan it in `mi_page_queue_find_free_ex`) + _mi_page_use_delayed_free(page, MI_USE_DELAYED_FREE, false /* dont overwrite never delayed */); + + // collect all other non-local frees to ensure up-to-date `used` count + _mi_page_free_collect(page, false); + + // and free the block (possibly freeing the page as well since used is updated) + _mi_free_block(page, true, block); + return true; +} + +// Bytes available in a block +static size_t _mi_usable_size(const void* p, const char* msg) mi_attr_noexcept { + const mi_segment_t* const segment = mi_checked_ptr_segment(p,msg); + if (segment==NULL) return 0; + const mi_page_t* const page = _mi_segment_page_of(segment, p); + const mi_block_t* block = (const mi_block_t*)p; + if (mi_unlikely(mi_page_has_aligned(page))) { + block = _mi_page_ptr_unalign(segment, page, p); + size_t size = mi_page_usable_size_of(page, block); + ptrdiff_t const adjust = (uint8_t*)p - (uint8_t*)block; + mi_assert_internal(adjust >= 0 && (size_t)adjust <= size); + return (size - adjust); + } + else { + return mi_page_usable_size_of(page, block); + } +} + +size_t mi_usable_size(const void* p) mi_attr_noexcept { + return _mi_usable_size(p, "mi_usable_size"); +} + + +// ------------------------------------------------------ +// ensure explicit external inline definitions are emitted! +// ------------------------------------------------------ + +#ifdef __cplusplus +void* _mi_externs[] = { + (void*)&_mi_page_malloc, + (void*)&mi_malloc, + (void*)&mi_malloc_small, + (void*)&mi_heap_malloc, + (void*)&mi_heap_zalloc, + (void*)&mi_heap_malloc_small +}; +#endif + + +// ------------------------------------------------------ +// Allocation extensions +// ------------------------------------------------------ + +void mi_free_size(void* p, size_t size) mi_attr_noexcept { + UNUSED_RELEASE(size); + mi_assert(p == NULL || size <= _mi_usable_size(p,"mi_free_size")); + mi_free(p); +} + +void mi_free_size_aligned(void* p, size_t size, size_t alignment) mi_attr_noexcept { + UNUSED_RELEASE(alignment); + mi_assert(((uintptr_t)p % alignment) == 0); + mi_free_size(p,size); +} + +void mi_free_aligned(void* p, size_t alignment) mi_attr_noexcept { + UNUSED_RELEASE(alignment); + mi_assert(((uintptr_t)p % alignment) == 0); + mi_free(p); +} + +extern inline mi_decl_restrict void* mi_heap_calloc(mi_heap_t* heap, size_t count, size_t size) mi_attr_noexcept { + size_t total; + if (mi_count_size_overflow(count,size,&total)) return NULL; + return mi_heap_zalloc(heap,total); +} + +mi_decl_restrict void* mi_calloc(size_t count, size_t size) mi_attr_noexcept { + return mi_heap_calloc(mi_get_default_heap(),count,size); +} + +// Uninitialized `calloc` +extern mi_decl_restrict void* mi_heap_mallocn(mi_heap_t* heap, size_t count, size_t size) mi_attr_noexcept { + size_t total; + if (mi_count_size_overflow(count, size, &total)) return NULL; + return mi_heap_malloc(heap, total); +} + +mi_decl_restrict void* mi_mallocn(size_t count, size_t size) mi_attr_noexcept { + return mi_heap_mallocn(mi_get_default_heap(),count,size); +} + +// Expand in place or fail +void* mi_expand(void* p, size_t newsize) mi_attr_noexcept { + if (p == NULL) return NULL; + size_t size = _mi_usable_size(p,"mi_expand"); + if (newsize > size) return NULL; + return p; // it fits +} + +void* _mi_heap_realloc_zero(mi_heap_t* heap, void* p, size_t newsize, bool zero) { + if (p == NULL) return _mi_heap_malloc_zero(heap,newsize,zero); + size_t size = _mi_usable_size(p,"mi_realloc"); + if (newsize <= size && newsize >= (size / 2)) { + return p; // reallocation still fits and not more than 50% waste + } + void* newp = mi_heap_malloc(heap,newsize); + if (mi_likely(newp != NULL)) { + if (zero && newsize > size) { + // also set last word in the previous allocation to zero to ensure any padding is zero-initialized + size_t start = (size >= sizeof(intptr_t) ? size - sizeof(intptr_t) : 0); + memset((uint8_t*)newp + start, 0, newsize - start); + } + memcpy(newp, p, (newsize > size ? size : newsize)); + mi_free(p); // only free if successful + } + return newp; +} + +void* mi_heap_realloc(mi_heap_t* heap, void* p, size_t newsize) mi_attr_noexcept { + return _mi_heap_realloc_zero(heap, p, newsize, false); +} + +void* mi_heap_reallocn(mi_heap_t* heap, void* p, size_t count, size_t size) mi_attr_noexcept { + size_t total; + if (mi_count_size_overflow(count, size, &total)) return NULL; + return mi_heap_realloc(heap, p, total); +} + + +// Reallocate but free `p` on errors +void* mi_heap_reallocf(mi_heap_t* heap, void* p, size_t newsize) mi_attr_noexcept { + void* newp = mi_heap_realloc(heap, p, newsize); + if (newp==NULL && p!=NULL) mi_free(p); + return newp; +} + +void* mi_heap_rezalloc(mi_heap_t* heap, void* p, size_t newsize) mi_attr_noexcept { + return _mi_heap_realloc_zero(heap, p, newsize, true); +} + +void* mi_heap_recalloc(mi_heap_t* heap, void* p, size_t count, size_t size) mi_attr_noexcept { + size_t total; + if (mi_count_size_overflow(count, size, &total)) return NULL; + return mi_heap_rezalloc(heap, p, total); +} + + +void* mi_realloc(void* p, size_t newsize) mi_attr_noexcept { + return mi_heap_realloc(mi_get_default_heap(),p,newsize); +} + +void* mi_reallocn(void* p, size_t count, size_t size) mi_attr_noexcept { + return mi_heap_reallocn(mi_get_default_heap(),p,count,size); +} + +// Reallocate but free `p` on errors +void* mi_reallocf(void* p, size_t newsize) mi_attr_noexcept { + return mi_heap_reallocf(mi_get_default_heap(),p,newsize); +} + +void* mi_rezalloc(void* p, size_t newsize) mi_attr_noexcept { + return mi_heap_rezalloc(mi_get_default_heap(), p, newsize); +} + +void* mi_recalloc(void* p, size_t count, size_t size) mi_attr_noexcept { + return mi_heap_recalloc(mi_get_default_heap(), p, count, size); +} + + + +// ------------------------------------------------------ +// strdup, strndup, and realpath +// ------------------------------------------------------ + +// `strdup` using mi_malloc +mi_decl_restrict char* mi_heap_strdup(mi_heap_t* heap, const char* s) mi_attr_noexcept { + if (s == NULL) return NULL; + size_t n = strlen(s); + char* t = (char*)mi_heap_malloc(heap,n+1); + if (t != NULL) memcpy(t, s, n + 1); + return t; +} + +mi_decl_restrict char* mi_strdup(const char* s) mi_attr_noexcept { + return mi_heap_strdup(mi_get_default_heap(), s); +} + +// `strndup` using mi_malloc +mi_decl_restrict char* mi_heap_strndup(mi_heap_t* heap, const char* s, size_t n) mi_attr_noexcept { + if (s == NULL) return NULL; + const char* end = (const char*)memchr(s, 0, n); // find end of string in the first `n` characters (returns NULL if not found) + const size_t m = (end != NULL ? (size_t)(end - s) : n); // `m` is the minimum of `n` or the end-of-string + mi_assert_internal(m <= n); + char* t = (char*)mi_heap_malloc(heap, m+1); + if (t == NULL) return NULL; + memcpy(t, s, m); + t[m] = 0; + return t; +} + +mi_decl_restrict char* mi_strndup(const char* s, size_t n) mi_attr_noexcept { + return mi_heap_strndup(mi_get_default_heap(),s,n); +} + +#ifndef __wasi__ +// `realpath` using mi_malloc +#ifdef _WIN32 +#ifndef PATH_MAX +#define PATH_MAX MAX_PATH +#endif +#include +mi_decl_restrict char* mi_heap_realpath(mi_heap_t* heap, const char* fname, char* resolved_name) mi_attr_noexcept { + // todo: use GetFullPathNameW to allow longer file names + char buf[PATH_MAX]; + DWORD res = GetFullPathNameA(fname, PATH_MAX, (resolved_name == NULL ? buf : resolved_name), NULL); + if (res == 0) { + errno = GetLastError(); return NULL; + } + else if (res > PATH_MAX) { + errno = EINVAL; return NULL; + } + else if (resolved_name != NULL) { + return resolved_name; + } + else { + return mi_heap_strndup(heap, buf, PATH_MAX); + } +} +#else +#include // pathconf +static size_t mi_path_max() { + static size_t path_max = 0; + if (path_max <= 0) { + long m = pathconf("/",_PC_PATH_MAX); + if (m <= 0) path_max = 4096; // guess + else if (m < 256) path_max = 256; // at least 256 + else path_max = m; + } + return path_max; +} + +char* mi_heap_realpath(mi_heap_t* heap, const char* fname, char* resolved_name) mi_attr_noexcept { + if (resolved_name != NULL) { + return realpath(fname,resolved_name); + } + else { + size_t n = mi_path_max(); + char* buf = (char*)mi_malloc(n+1); + if (buf==NULL) return NULL; + char* rname = realpath(fname,buf); + char* result = mi_heap_strndup(heap,rname,n); // ok if `rname==NULL` + mi_free(buf); + return result; + } +} +#endif + +mi_decl_restrict char* mi_realpath(const char* fname, char* resolved_name) mi_attr_noexcept { + return mi_heap_realpath(mi_get_default_heap(),fname,resolved_name); +} +#endif + +/*------------------------------------------------------- +C++ new and new_aligned +The standard requires calling into `get_new_handler` and +throwing the bad_alloc exception on failure. If we compile +with a C++ compiler we can implement this precisely. If we +use a C compiler we cannot throw a `bad_alloc` exception +but we call `exit` instead (i.e. not returning). +-------------------------------------------------------*/ + +#ifdef __cplusplus +#include +static bool mi_try_new_handler(bool nothrow) { + std::new_handler h = std::get_new_handler(); + if (h==NULL) { + if (!nothrow) throw std::bad_alloc(); + return false; + } + else { + h(); + return true; + } +} +#else +typedef void (*std_new_handler_t)(); + +#if (defined(__GNUC__) || defined(__clang__)) +std_new_handler_t __attribute((weak)) _ZSt15get_new_handlerv() { + return NULL; +} +static std_new_handler_t mi_get_new_handler() { + return _ZSt15get_new_handlerv(); +} +#else +// note: on windows we could dynamically link to `?get_new_handler@std@@YAP6AXXZXZ`. +static std_new_handler_t mi_get_new_handler() { + return NULL; +} +#endif + +static bool mi_try_new_handler(bool nothrow) { + std_new_handler_t h = mi_get_new_handler(); + if (h==NULL) { + if (!nothrow) exit(ENOMEM); // cannot throw in plain C, use exit as we are out of memory anyway. + return false; + } + else { + h(); + return true; + } +} +#endif + +static mi_decl_noinline void* mi_try_new(size_t size, bool nothrow ) { + void* p = NULL; + while(p == NULL && mi_try_new_handler(nothrow)) { + p = mi_malloc(size); + } + return p; +} + +mi_decl_restrict void* mi_new(size_t size) { + void* p = mi_malloc(size); + if (mi_unlikely(p == NULL)) return mi_try_new(size,false); + return p; +} + +mi_decl_restrict void* mi_new_nothrow(size_t size) mi_attr_noexcept { + void* p = mi_malloc(size); + if (mi_unlikely(p == NULL)) return mi_try_new(size, true); + return p; +} + +mi_decl_restrict void* mi_new_aligned(size_t size, size_t alignment) { + void* p; + do { + p = mi_malloc_aligned(size, alignment); + } + while(p == NULL && mi_try_new_handler(false)); + return p; +} + +mi_decl_restrict void* mi_new_aligned_nothrow(size_t size, size_t alignment) mi_attr_noexcept { + void* p; + do { + p = mi_malloc_aligned(size, alignment); + } + while(p == NULL && mi_try_new_handler(true)); + return p; +} + +mi_decl_restrict void* mi_new_n(size_t count, size_t size) { + size_t total; + if (mi_unlikely(mi_count_size_overflow(count, size, &total))) { + mi_try_new_handler(false); // on overflow we invoke the try_new_handler once to potentially throw std::bad_alloc + return NULL; + } + else { + return mi_new(total); + } +} + +void* mi_new_realloc(void* p, size_t newsize) { + void* q; + do { + q = mi_realloc(p, newsize); + } while (q == NULL && mi_try_new_handler(false)); + return q; +} + +void* mi_new_reallocn(void* p, size_t newcount, size_t size) { + size_t total; + if (mi_unlikely(mi_count_size_overflow(newcount, size, &total))) { + mi_try_new_handler(false); // on overflow we invoke the try_new_handler once to potentially throw std::bad_alloc + return NULL; + } + else { + return mi_new_realloc(p, total); + } +} diff --git a/kotlin-native/runtime/src/mimalloc/c/arena.c b/kotlin-native/runtime/src/mimalloc/c/arena.c new file mode 100644 index 00000000000..73a7e70432f --- /dev/null +++ b/kotlin-native/runtime/src/mimalloc/c/arena.c @@ -0,0 +1,357 @@ +/* ---------------------------------------------------------------------------- +Copyright (c) 2019, Microsoft Research, Daan Leijen +This is free software; you can redistribute it and/or modify it under the +terms of the MIT license. A copy of the license can be found in the file +"LICENSE" at the root of this distribution. +-----------------------------------------------------------------------------*/ + +/* ---------------------------------------------------------------------------- +"Arenas" are fixed area's of OS memory from which we can allocate +large blocks (>= MI_ARENA_BLOCK_SIZE, 32MiB). +In contrast to the rest of mimalloc, the arenas are shared between +threads and need to be accessed using atomic operations. + +Currently arenas are only used to for huge OS page (1GiB) reservations, +otherwise it delegates to direct allocation from the OS. +In the future, we can expose an API to manually add more kinds of arenas +which is sometimes needed for embedded devices or shared memory for example. +(We can also employ this with WASI or `sbrk` systems to reserve large arenas + on demand and be able to reuse them efficiently). + +The arena allocation needs to be thread safe and we use an atomic +bitmap to allocate. The current implementation of the bitmap can +only do this within a field (`uintptr_t`) so we can allocate at most +blocks of 2GiB (64*32MiB) and no object can cross the boundary. This +can lead to fragmentation but fortunately most objects will be regions +of 256MiB in practice. +-----------------------------------------------------------------------------*/ +#include "mimalloc.h" +#include "mimalloc-internal.h" +#include "mimalloc-atomic.h" + +#include // memset + +#include "bitmap.inc.c" // atomic bitmap + + +// os.c +void* _mi_os_alloc_aligned(size_t size, size_t alignment, bool commit, bool* large, mi_os_tld_t* tld); +void _mi_os_free_ex(void* p, size_t size, bool was_committed, mi_stats_t* stats); +void _mi_os_free(void* p, size_t size, mi_stats_t* stats); + +void* _mi_os_alloc_huge_os_pages(size_t pages, int numa_node, mi_msecs_t max_secs, size_t* pages_reserved, size_t* psize); +void _mi_os_free_huge_pages(void* p, size_t size, mi_stats_t* stats); + +bool _mi_os_commit(void* p, size_t size, bool* is_zero, mi_stats_t* stats); + +/* ----------------------------------------------------------- + Arena allocation +----------------------------------------------------------- */ + +#define MI_SEGMENT_ALIGN MI_SEGMENT_SIZE +#define MI_ARENA_BLOCK_SIZE (8*MI_SEGMENT_ALIGN) // 32MiB +#define MI_ARENA_MAX_OBJ_SIZE (MI_BITMAP_FIELD_BITS * MI_ARENA_BLOCK_SIZE) // 2GiB +#define MI_ARENA_MIN_OBJ_SIZE (MI_ARENA_BLOCK_SIZE/2) // 16MiB +#define MI_MAX_ARENAS (64) // not more than 256 (since we use 8 bits in the memid) + +// A memory arena descriptor +typedef struct mi_arena_s { + _Atomic(uint8_t*) start; // the start of the memory area + size_t block_count; // size of the area in arena blocks (of `MI_ARENA_BLOCK_SIZE`) + size_t field_count; // number of bitmap fields (where `field_count * MI_BITMAP_FIELD_BITS >= block_count`) + int numa_node; // associated NUMA node + bool is_zero_init; // is the arena zero initialized? + bool is_committed; // is the memory committed + bool is_large; // large OS page allocated + _Atomic(uintptr_t) search_idx; // optimization to start the search for free blocks + mi_bitmap_field_t* blocks_dirty; // are the blocks potentially non-zero? + mi_bitmap_field_t* blocks_committed; // if `!is_committed`, are the blocks committed? + mi_bitmap_field_t blocks_inuse[1]; // in-place bitmap of in-use blocks (of size `field_count`) +} mi_arena_t; + + +// The available arenas +static mi_decl_cache_align _Atomic(mi_arena_t*) mi_arenas[MI_MAX_ARENAS]; +static mi_decl_cache_align _Atomic(uintptr_t) mi_arena_count; // = 0 + + +/* ----------------------------------------------------------- + Arena allocations get a memory id where the lower 8 bits are + the arena index +1, and the upper bits the block index. +----------------------------------------------------------- */ + +// Use `0` as a special id for direct OS allocated memory. +#define MI_MEMID_OS 0 + +static size_t mi_arena_id_create(size_t arena_index, mi_bitmap_index_t bitmap_index) { + mi_assert_internal(arena_index < 0xFE); + mi_assert_internal(((bitmap_index << 8) >> 8) == bitmap_index); // no overflow? + return ((bitmap_index << 8) | ((arena_index+1) & 0xFF)); +} + +static void mi_arena_id_indices(size_t memid, size_t* arena_index, mi_bitmap_index_t* bitmap_index) { + mi_assert_internal(memid != MI_MEMID_OS); + *arena_index = (memid & 0xFF) - 1; + *bitmap_index = (memid >> 8); +} + +static size_t mi_block_count_of_size(size_t size) { + return _mi_divide_up(size, MI_ARENA_BLOCK_SIZE); +} + +/* ----------------------------------------------------------- + Thread safe allocation in an arena +----------------------------------------------------------- */ +static bool mi_arena_alloc(mi_arena_t* arena, size_t blocks, mi_bitmap_index_t* bitmap_idx) +{ + const size_t fcount = arena->field_count; + size_t idx = mi_atomic_load_acquire(&arena->search_idx); // start from last search + for (size_t visited = 0; visited < fcount; visited++, idx++) { + if (idx >= fcount) idx = 0; // wrap around + // try to atomically claim a range of bits + if (mi_bitmap_try_find_claim_field(arena->blocks_inuse, idx, blocks, bitmap_idx)) { + mi_atomic_store_release(&arena->search_idx, idx); // start search from here next time + return true; + } + } + return false; +} + + +/* ----------------------------------------------------------- + Arena Allocation +----------------------------------------------------------- */ + +static void* mi_arena_alloc_from(mi_arena_t* arena, size_t arena_index, size_t needed_bcount, + bool* commit, bool* large, bool* is_zero, size_t* memid, mi_os_tld_t* tld) +{ + mi_bitmap_index_t bitmap_index; + if (!mi_arena_alloc(arena, needed_bcount, &bitmap_index)) return NULL; + + // claimed it! set the dirty bits (todo: no need for an atomic op here?) + void* p = arena->start + (mi_bitmap_index_bit(bitmap_index)*MI_ARENA_BLOCK_SIZE); + *memid = mi_arena_id_create(arena_index, bitmap_index); + *is_zero = mi_bitmap_claim(arena->blocks_dirty, arena->field_count, needed_bcount, bitmap_index, NULL); + *large = arena->is_large; + if (arena->is_committed) { + // always committed + *commit = true; + } + else if (*commit) { + // arena not committed as a whole, but commit requested: ensure commit now + bool any_uncommitted; + mi_bitmap_claim(arena->blocks_committed, arena->field_count, needed_bcount, bitmap_index, &any_uncommitted); + if (any_uncommitted) { + bool commit_zero; + _mi_os_commit(p, needed_bcount * MI_ARENA_BLOCK_SIZE, &commit_zero, tld->stats); + if (commit_zero) *is_zero = true; + } + } + else { + // no need to commit, but check if already fully committed + *commit = mi_bitmap_is_claimed(arena->blocks_committed, arena->field_count, needed_bcount, bitmap_index); + } + return p; +} + +void* _mi_arena_alloc_aligned(size_t size, size_t alignment, + bool* commit, bool* large, bool* is_zero, + size_t* memid, mi_os_tld_t* tld) +{ + mi_assert_internal(commit != NULL && large != NULL && is_zero != NULL && memid != NULL && tld != NULL); + mi_assert_internal(size > 0); + *memid = MI_MEMID_OS; + *is_zero = false; + + // try to allocate in an arena if the alignment is small enough + // and the object is not too large or too small. + if (alignment <= MI_SEGMENT_ALIGN && + size <= MI_ARENA_MAX_OBJ_SIZE && + size >= MI_ARENA_MIN_OBJ_SIZE) + { + const size_t bcount = mi_block_count_of_size(size); + const int numa_node = _mi_os_numa_node(tld); // current numa node + + mi_assert_internal(size <= bcount*MI_ARENA_BLOCK_SIZE); + // try numa affine allocation + for (size_t i = 0; i < MI_MAX_ARENAS; i++) { + mi_arena_t* arena = mi_atomic_load_ptr_relaxed(mi_arena_t, &mi_arenas[i]); + if (arena==NULL) break; // end reached + if ((arena->numa_node<0 || arena->numa_node==numa_node) && // numa local? + (*large || !arena->is_large)) // large OS pages allowed, or arena is not large OS pages + { + void* p = mi_arena_alloc_from(arena, i, bcount, commit, large, is_zero, memid, tld); + mi_assert_internal((uintptr_t)p % alignment == 0); + if (p != NULL) return p; + } + } + // try from another numa node instead.. + for (size_t i = 0; i < MI_MAX_ARENAS; i++) { + mi_arena_t* arena = mi_atomic_load_ptr_relaxed(mi_arena_t, &mi_arenas[i]); + if (arena==NULL) break; // end reached + if ((arena->numa_node>=0 && arena->numa_node!=numa_node) && // not numa local! + (*large || !arena->is_large)) // large OS pages allowed, or arena is not large OS pages + { + void* p = mi_arena_alloc_from(arena, i, bcount, commit, large, is_zero, memid, tld); + mi_assert_internal((uintptr_t)p % alignment == 0); + if (p != NULL) return p; + } + } + } + + // finally, fall back to the OS + *is_zero = true; + *memid = MI_MEMID_OS; + return _mi_os_alloc_aligned(size, alignment, *commit, large, tld); +} + +void* _mi_arena_alloc(size_t size, bool* commit, bool* large, bool* is_zero, size_t* memid, mi_os_tld_t* tld) +{ + return _mi_arena_alloc_aligned(size, MI_ARENA_BLOCK_SIZE, commit, large, is_zero, memid, tld); +} + +/* ----------------------------------------------------------- + Arena free +----------------------------------------------------------- */ + +void _mi_arena_free(void* p, size_t size, size_t memid, bool all_committed, mi_stats_t* stats) { + mi_assert_internal(size > 0 && stats != NULL); + if (p==NULL) return; + if (size==0) return; + if (memid == MI_MEMID_OS) { + // was a direct OS allocation, pass through + _mi_os_free_ex(p, size, all_committed, stats); + } + else { + // allocated in an arena + size_t arena_idx; + size_t bitmap_idx; + mi_arena_id_indices(memid, &arena_idx, &bitmap_idx); + mi_assert_internal(arena_idx < MI_MAX_ARENAS); + mi_arena_t* arena = mi_atomic_load_ptr_relaxed(mi_arena_t,&mi_arenas[arena_idx]); + mi_assert_internal(arena != NULL); + if (arena == NULL) { + _mi_error_message(EINVAL, "trying to free from non-existent arena: %p, size %zu, memid: 0x%zx\n", p, size, memid); + return; + } + mi_assert_internal(arena->field_count > mi_bitmap_index_field(bitmap_idx)); + if (arena->field_count <= mi_bitmap_index_field(bitmap_idx)) { + _mi_error_message(EINVAL, "trying to free from non-existent arena block: %p, size %zu, memid: 0x%zx\n", p, size, memid); + return; + } + const size_t blocks = mi_block_count_of_size(size); + bool ones = mi_bitmap_unclaim(arena->blocks_inuse, arena->field_count, blocks, bitmap_idx); + if (!ones) { + _mi_error_message(EAGAIN, "trying to free an already freed block: %p, size %zu\n", p, size); + return; + }; + } +} + +/* ----------------------------------------------------------- + Add an arena. +----------------------------------------------------------- */ + +static bool mi_arena_add(mi_arena_t* arena) { + mi_assert_internal(arena != NULL); + mi_assert_internal((uintptr_t)mi_atomic_load_ptr_relaxed(uint8_t,&arena->start) % MI_SEGMENT_ALIGN == 0); + mi_assert_internal(arena->block_count > 0); + + uintptr_t i = mi_atomic_increment_acq_rel(&mi_arena_count); + if (i >= MI_MAX_ARENAS) { + mi_atomic_decrement_acq_rel(&mi_arena_count); + return false; + } + mi_atomic_store_ptr_release(mi_arena_t,&mi_arenas[i], arena); + return true; +} + + +/* ----------------------------------------------------------- + Reserve a huge page arena. +----------------------------------------------------------- */ +#include // ENOMEM + +// reserve at a specific numa node +int mi_reserve_huge_os_pages_at(size_t pages, int numa_node, size_t timeout_msecs) mi_attr_noexcept { + if (pages==0) return 0; + if (numa_node < -1) numa_node = -1; + if (numa_node >= 0) numa_node = numa_node % _mi_os_numa_node_count(); + size_t hsize = 0; + size_t pages_reserved = 0; + void* p = _mi_os_alloc_huge_os_pages(pages, numa_node, timeout_msecs, &pages_reserved, &hsize); + if (p==NULL || pages_reserved==0) { + _mi_warning_message("failed to reserve %zu gb huge pages\n", pages); + return ENOMEM; + } + _mi_verbose_message("numa node %i: reserved %zu gb huge pages (of the %zu gb requested)\n", numa_node, pages_reserved, pages); + + size_t bcount = mi_block_count_of_size(hsize); + size_t fields = _mi_divide_up(bcount, MI_BITMAP_FIELD_BITS); + size_t asize = sizeof(mi_arena_t) + (2*fields*sizeof(mi_bitmap_field_t)); + mi_arena_t* arena = (mi_arena_t*)_mi_os_alloc(asize, &_mi_stats_main); // TODO: can we avoid allocating from the OS? + if (arena == NULL) { + _mi_os_free_huge_pages(p, hsize, &_mi_stats_main); + return ENOMEM; + } + arena->block_count = bcount; + arena->field_count = fields; + arena->start = (uint8_t*)p; + arena->numa_node = numa_node; // TODO: or get the current numa node if -1? (now it allows anyone to allocate on -1) + arena->is_large = true; + arena->is_zero_init = true; + arena->is_committed = true; + arena->search_idx = 0; + arena->blocks_dirty = &arena->blocks_inuse[fields]; // just after inuse bitmap + arena->blocks_committed = NULL; + // the bitmaps are already zero initialized due to os_alloc + // just claim leftover blocks if needed + ptrdiff_t post = (fields * MI_BITMAP_FIELD_BITS) - bcount; + mi_assert_internal(post >= 0); + if (post > 0) { + // don't use leftover bits at the end + mi_bitmap_index_t postidx = mi_bitmap_index_create(fields - 1, MI_BITMAP_FIELD_BITS - post); + mi_bitmap_claim(arena->blocks_inuse, fields, post, postidx, NULL); + } + + mi_arena_add(arena); + return 0; +} + + +// reserve huge pages evenly among the given number of numa nodes (or use the available ones as detected) +int mi_reserve_huge_os_pages_interleave(size_t pages, size_t numa_nodes, size_t timeout_msecs) mi_attr_noexcept { + if (pages == 0) return 0; + + // pages per numa node + size_t numa_count = (numa_nodes > 0 ? numa_nodes : _mi_os_numa_node_count()); + if (numa_count <= 0) numa_count = 1; + const size_t pages_per = pages / numa_count; + const size_t pages_mod = pages % numa_count; + const size_t timeout_per = (timeout_msecs==0 ? 0 : (timeout_msecs / numa_count) + 50); + + // reserve evenly among numa nodes + for (size_t numa_node = 0; numa_node < numa_count && pages > 0; numa_node++) { + size_t node_pages = pages_per; // can be 0 + if (numa_node < pages_mod) node_pages++; + int err = mi_reserve_huge_os_pages_at(node_pages, (int)numa_node, timeout_per); + if (err) return err; + if (pages < node_pages) { + pages = 0; + } + else { + pages -= node_pages; + } + } + + return 0; +} + +int mi_reserve_huge_os_pages(size_t pages, double max_secs, size_t* pages_reserved) mi_attr_noexcept { + UNUSED(max_secs); + _mi_warning_message("mi_reserve_huge_os_pages is deprecated: use mi_reserve_huge_os_pages_interleave/at instead\n"); + if (pages_reserved != NULL) *pages_reserved = 0; + int err = mi_reserve_huge_os_pages_interleave(pages, 0, (size_t)(max_secs * 1000.0)); + if (err==0 && pages_reserved!=NULL) *pages_reserved = pages; + return err; +} diff --git a/kotlin-native/runtime/src/mimalloc/c/bitmap.inc.c b/kotlin-native/runtime/src/mimalloc/c/bitmap.inc.c new file mode 100644 index 00000000000..2d6df46e84d --- /dev/null +++ b/kotlin-native/runtime/src/mimalloc/c/bitmap.inc.c @@ -0,0 +1,247 @@ +/* ---------------------------------------------------------------------------- +Copyright (c) 2019, Microsoft Research, Daan Leijen +This is free software; you can redistribute it and/or modify it under the +terms of the MIT license. A copy of the license can be found in the file +"LICENSE" at the root of this distribution. +-----------------------------------------------------------------------------*/ + +/* ---------------------------------------------------------------------------- +This file is meant to be included in other files for efficiency. +It implements a bitmap that can set/reset sequences of bits atomically +and is used to concurrently claim memory ranges. + +A bitmap is an array of fields where each field is a machine word (`uintptr_t`) + +A current limitation is that the bit sequences cannot cross fields +and that the sequence must be smaller or equal to the bits in a field. +---------------------------------------------------------------------------- */ +#pragma once +#ifndef MI_BITMAP_C +#define MI_BITMAP_C + +#include "mimalloc.h" +#include "mimalloc-internal.h" + +/* ----------------------------------------------------------- + Bitmap definition +----------------------------------------------------------- */ + +#define MI_BITMAP_FIELD_BITS (8*MI_INTPTR_SIZE) +#define MI_BITMAP_FIELD_FULL (~((uintptr_t)0)) // all bits set + +// An atomic bitmap of `uintptr_t` fields +typedef _Atomic(uintptr_t) mi_bitmap_field_t; +typedef mi_bitmap_field_t* mi_bitmap_t; + +// A bitmap index is the index of the bit in a bitmap. +typedef size_t mi_bitmap_index_t; + +// Create a bit index. +static inline mi_bitmap_index_t mi_bitmap_index_create(size_t idx, size_t bitidx) { + mi_assert_internal(bitidx < MI_BITMAP_FIELD_BITS); + return (idx*MI_BITMAP_FIELD_BITS) + bitidx; +} + +// Get the field index from a bit index. +static inline size_t mi_bitmap_index_field(mi_bitmap_index_t bitmap_idx) { + return (bitmap_idx / MI_BITMAP_FIELD_BITS); +} + +// Get the bit index in a bitmap field +static inline size_t mi_bitmap_index_bit_in_field(mi_bitmap_index_t bitmap_idx) { + return (bitmap_idx % MI_BITMAP_FIELD_BITS); +} + +// Get the full bit index +static inline size_t mi_bitmap_index_bit(mi_bitmap_index_t bitmap_idx) { + return bitmap_idx; +} + + +// The bit mask for a given number of blocks at a specified bit index. +static inline uintptr_t mi_bitmap_mask_(size_t count, size_t bitidx) { + mi_assert_internal(count + bitidx <= MI_BITMAP_FIELD_BITS); + if (count == MI_BITMAP_FIELD_BITS) return MI_BITMAP_FIELD_FULL; + return ((((uintptr_t)1 << count) - 1) << bitidx); +} + + +/* ----------------------------------------------------------- + Use bit scan forward/reverse to quickly find the first zero bit if it is available +----------------------------------------------------------- */ +#if defined(_MSC_VER) +#define MI_HAVE_BITSCAN +#include +#ifndef MI_64 +#if MI_INTPTR_SIZE==8 +#define MI_64(f) f##64 +#else +#define MI_64(f) f +#endif +#endif + +static inline size_t mi_bsf(uintptr_t x) { + if (x==0) return 8*MI_INTPTR_SIZE; + DWORD idx; + MI_64(_BitScanForward)(&idx, x); + return idx; +} +static inline size_t mi_bsr(uintptr_t x) { + if (x==0) return 8*MI_INTPTR_SIZE; + DWORD idx; + MI_64(_BitScanReverse)(&idx, x); + return idx; +} +#elif defined(__GNUC__) || defined(__clang__) +#include // LONG_MAX +#define MI_HAVE_BITSCAN +#if (INTPTR_MAX == LONG_MAX) +# define MI_L(x) x##l +#else +# define MI_L(x) x##ll +#endif +static inline size_t mi_bsf(uintptr_t x) { + return (x==0 ? 8*MI_INTPTR_SIZE : MI_L(__builtin_ctz)(x)); +} +static inline size_t mi_bsr(uintptr_t x) { + return (x==0 ? 8*MI_INTPTR_SIZE : (8*MI_INTPTR_SIZE - 1) - MI_L(__builtin_clz)(x)); +} +#endif + +/* ----------------------------------------------------------- + Claim a bit sequence atomically +----------------------------------------------------------- */ + +// Try to atomically claim a sequence of `count` bits at in `idx` +// in the bitmap field. Returns `true` on success. +static inline bool mi_bitmap_try_claim_field(mi_bitmap_t bitmap, size_t bitmap_fields, const size_t count, mi_bitmap_index_t bitmap_idx) { + const size_t idx = mi_bitmap_index_field(bitmap_idx); + const size_t bitidx = mi_bitmap_index_bit_in_field(bitmap_idx); + const uintptr_t mask = mi_bitmap_mask_(count, bitidx); + mi_assert_internal(bitmap_fields > idx); UNUSED(bitmap_fields); + mi_assert_internal(bitidx + count <= MI_BITMAP_FIELD_BITS); + + uintptr_t field = mi_atomic_load_relaxed(&bitmap[idx]); + if ((field & mask) == 0) { // free? + if (mi_atomic_cas_strong_acq_rel(&bitmap[idx], &field, (field|mask))) { + // claimed! + return true; + } + } + return false; +} + + +// Try to atomically claim a sequence of `count` bits in a single +// field at `idx` in `bitmap`. Returns `true` on success. +static inline bool mi_bitmap_try_find_claim_field(mi_bitmap_t bitmap, size_t idx, const size_t count, mi_bitmap_index_t* bitmap_idx) +{ + mi_assert_internal(bitmap_idx != NULL); + _Atomic(uintptr_t)* field = &bitmap[idx]; + uintptr_t map = mi_atomic_load_relaxed(field); + if (map==MI_BITMAP_FIELD_FULL) return false; // short cut + + // search for 0-bit sequence of length count + const uintptr_t mask = mi_bitmap_mask_(count, 0); + const size_t bitidx_max = MI_BITMAP_FIELD_BITS - count; + +#ifdef MI_HAVE_BITSCAN + size_t bitidx = mi_bsf(~map); // quickly find the first zero bit if possible +#else + size_t bitidx = 0; // otherwise start at 0 +#endif + uintptr_t m = (mask << bitidx); // invariant: m == mask shifted by bitidx + + // scan linearly for a free range of zero bits + while (bitidx <= bitidx_max) { + if ((map & m) == 0) { // are the mask bits free at bitidx? + mi_assert_internal((m >> bitidx) == mask); // no overflow? + const uintptr_t newmap = map | m; + mi_assert_internal((newmap^map) >> bitidx == mask); + if (!mi_atomic_cas_weak_acq_rel(field, &map, newmap)) { // TODO: use strong cas here? + // no success, another thread claimed concurrently.. keep going (with updated `map`) + continue; + } + else { + // success, we claimed the bits! + *bitmap_idx = mi_bitmap_index_create(idx, bitidx); + return true; + } + } + else { + // on to the next bit range +#ifdef MI_HAVE_BITSCAN + const size_t shift = (count == 1 ? 1 : mi_bsr(map & m) - bitidx + 1); + mi_assert_internal(shift > 0 && shift <= count); +#else + const size_t shift = 1; +#endif + bitidx += shift; + m <<= shift; + } + } + // no bits found + return false; +} + + +// Find `count` bits of 0 and set them to 1 atomically; returns `true` on success. +// For now, `count` can be at most MI_BITMAP_FIELD_BITS and will never span fields. +static inline bool mi_bitmap_try_find_claim(mi_bitmap_t bitmap, size_t bitmap_fields, size_t count, mi_bitmap_index_t* bitmap_idx) { + for (size_t idx = 0; idx < bitmap_fields; idx++) { + if (mi_bitmap_try_find_claim_field(bitmap, idx, count, bitmap_idx)) { + return true; + } + } + return false; +} + +// Set `count` bits at `bitmap_idx` to 0 atomically +// Returns `true` if all `count` bits were 1 previously. +static inline bool mi_bitmap_unclaim(mi_bitmap_t bitmap, size_t bitmap_fields, size_t count, mi_bitmap_index_t bitmap_idx) { + const size_t idx = mi_bitmap_index_field(bitmap_idx); + const size_t bitidx = mi_bitmap_index_bit_in_field(bitmap_idx); + const uintptr_t mask = mi_bitmap_mask_(count, bitidx); + mi_assert_internal(bitmap_fields > idx); UNUSED(bitmap_fields); + // mi_assert_internal((bitmap[idx] & mask) == mask); + uintptr_t prev = mi_atomic_and_acq_rel(&bitmap[idx], ~mask); + return ((prev & mask) == mask); +} + + +// Set `count` bits at `bitmap_idx` to 1 atomically +// Returns `true` if all `count` bits were 0 previously. `any_zero` is `true` if there was at least one zero bit. +static inline bool mi_bitmap_claim(mi_bitmap_t bitmap, size_t bitmap_fields, size_t count, mi_bitmap_index_t bitmap_idx, bool* any_zero) { + const size_t idx = mi_bitmap_index_field(bitmap_idx); + const size_t bitidx = mi_bitmap_index_bit_in_field(bitmap_idx); + const uintptr_t mask = mi_bitmap_mask_(count, bitidx); + mi_assert_internal(bitmap_fields > idx); UNUSED(bitmap_fields); + //mi_assert_internal(any_zero != NULL || (bitmap[idx] & mask) == 0); + uintptr_t prev = mi_atomic_or_acq_rel(&bitmap[idx], mask); + if (any_zero != NULL) *any_zero = ((prev & mask) != mask); + return ((prev & mask) == 0); +} + +// Returns `true` if all `count` bits were 1. `any_ones` is `true` if there was at least one bit set to one. +static inline bool mi_bitmap_is_claimedx(mi_bitmap_t bitmap, size_t bitmap_fields, size_t count, mi_bitmap_index_t bitmap_idx, bool* any_ones) { + const size_t idx = mi_bitmap_index_field(bitmap_idx); + const size_t bitidx = mi_bitmap_index_bit_in_field(bitmap_idx); + const uintptr_t mask = mi_bitmap_mask_(count, bitidx); + mi_assert_internal(bitmap_fields > idx); UNUSED(bitmap_fields); + uintptr_t field = mi_atomic_load_relaxed(&bitmap[idx]); + if (any_ones != NULL) *any_ones = ((field & mask) != 0); + return ((field & mask) == mask); +} + +static inline bool mi_bitmap_is_claimed(mi_bitmap_t bitmap, size_t bitmap_fields, size_t count, mi_bitmap_index_t bitmap_idx) { + return mi_bitmap_is_claimedx(bitmap, bitmap_fields, count, bitmap_idx, NULL); +} + +static inline bool mi_bitmap_is_any_claimed(mi_bitmap_t bitmap, size_t bitmap_fields, size_t count, mi_bitmap_index_t bitmap_idx) { + bool any_ones; + mi_bitmap_is_claimedx(bitmap, bitmap_fields, count, bitmap_idx, &any_ones); + return any_ones; +} + + +#endif diff --git a/kotlin-native/runtime/src/mimalloc/c/heap.c b/kotlin-native/runtime/src/mimalloc/c/heap.c new file mode 100644 index 00000000000..bc7b07a8a92 --- /dev/null +++ b/kotlin-native/runtime/src/mimalloc/c/heap.c @@ -0,0 +1,558 @@ +/*---------------------------------------------------------------------------- +Copyright (c) 2018, Microsoft Research, Daan Leijen +This is free software; you can redistribute it and/or modify it under the +terms of the MIT license. A copy of the license can be found in the file +"licenses/third_party/mimalloc_LICENSE.txt" at the root of this distribution. +-----------------------------------------------------------------------------*/ + +#include "mimalloc.h" +#include "mimalloc-internal.h" +#include "mimalloc-atomic.h" + +#include // memset, memcpy + +#if defined(_MSC_VER) && (_MSC_VER < 1920) +#pragma warning(disable:4204) // non-constant aggregate initializer +#endif + +/* ----------------------------------------------------------- + Helpers +----------------------------------------------------------- */ + +// return `true` if ok, `false` to break +typedef bool (heap_page_visitor_fun)(mi_heap_t* heap, mi_page_queue_t* pq, mi_page_t* page, void* arg1, void* arg2); + +// Visit all pages in a heap; returns `false` if break was called. +static bool mi_heap_visit_pages(mi_heap_t* heap, heap_page_visitor_fun* fn, void* arg1, void* arg2) +{ + if (heap==NULL || heap->page_count==0) return 0; + + // visit all pages + #if MI_DEBUG>1 + size_t total = heap->page_count; + #endif + size_t count = 0; + for (size_t i = 0; i <= MI_BIN_FULL; i++) { + mi_page_queue_t* pq = &heap->pages[i]; + mi_page_t* page = pq->first; + while(page != NULL) { + mi_page_t* next = page->next; // save next in case the page gets removed from the queue + mi_assert_internal(mi_page_heap(page) == heap); + count++; + if (!fn(heap, pq, page, arg1, arg2)) return false; + page = next; // and continue + } + } + mi_assert_internal(count == total); + return true; +} + + +#if MI_DEBUG>=2 +static bool mi_heap_page_is_valid(mi_heap_t* heap, mi_page_queue_t* pq, mi_page_t* page, void* arg1, void* arg2) { + UNUSED(arg1); + UNUSED(arg2); + UNUSED(pq); + mi_assert_internal(mi_page_heap(page) == heap); + mi_segment_t* segment = _mi_page_segment(page); + mi_assert_internal(segment->thread_id == heap->thread_id); + mi_assert_expensive(_mi_page_is_valid(page)); + return true; +} +#endif +#if MI_DEBUG>=3 +static bool mi_heap_is_valid(mi_heap_t* heap) { + mi_assert_internal(heap!=NULL); + mi_heap_visit_pages(heap, &mi_heap_page_is_valid, NULL, NULL); + return true; +} +#endif + + + + +/* ----------------------------------------------------------- + "Collect" pages by migrating `local_free` and `thread_free` + lists and freeing empty pages. This is done when a thread + stops (and in that case abandons pages if there are still + blocks alive) +----------------------------------------------------------- */ + +typedef enum mi_collect_e { + MI_NORMAL, + MI_FORCE, + MI_ABANDON +} mi_collect_t; + + +static bool mi_heap_page_collect(mi_heap_t* heap, mi_page_queue_t* pq, mi_page_t* page, void* arg_collect, void* arg2 ) { + UNUSED(arg2); + UNUSED(heap); + mi_assert_internal(mi_heap_page_is_valid(heap, pq, page, NULL, NULL)); + mi_collect_t collect = *((mi_collect_t*)arg_collect); + _mi_page_free_collect(page, collect >= MI_FORCE); + if (mi_page_all_free(page)) { + // no more used blocks, free the page. + // note: this will free retired pages as well. + _mi_page_free(page, pq, collect >= MI_FORCE); + } + else if (collect == MI_ABANDON) { + // still used blocks but the thread is done; abandon the page + _mi_page_abandon(page, pq); + } + return true; // don't break +} + +static bool mi_heap_page_never_delayed_free(mi_heap_t* heap, mi_page_queue_t* pq, mi_page_t* page, void* arg1, void* arg2) { + UNUSED(arg1); + UNUSED(arg2); + UNUSED(heap); + UNUSED(pq); + _mi_page_use_delayed_free(page, MI_NEVER_DELAYED_FREE, false); + return true; // don't break +} + +static void mi_heap_collect_ex(mi_heap_t* heap, mi_collect_t collect) +{ + if (!mi_heap_is_initialized(heap)) return; + _mi_deferred_free(heap, collect >= MI_FORCE); + + // note: never reclaim on collect but leave it to threads that need storage to reclaim + if ( + #ifdef NDEBUG + collect == MI_FORCE + #else + collect >= MI_FORCE + #endif + && _mi_is_main_thread() && mi_heap_is_backing(heap) && !heap->no_reclaim) + { + // the main thread is abandoned (end-of-program), try to reclaim all abandoned segments. + // if all memory is freed by now, all segments should be freed. + _mi_abandoned_reclaim_all(heap, &heap->tld->segments); + } + + // if abandoning, mark all pages to no longer add to delayed_free + if (collect == MI_ABANDON) { + mi_heap_visit_pages(heap, &mi_heap_page_never_delayed_free, NULL, NULL); + } + + // free thread delayed blocks. + // (if abandoning, after this there are no more thread-delayed references into the pages.) + _mi_heap_delayed_free(heap); + + // collect retired pages + _mi_heap_collect_retired(heap, collect >= MI_FORCE); + + // collect all pages owned by this thread + mi_heap_visit_pages(heap, &mi_heap_page_collect, &collect, NULL); + mi_assert_internal( collect != MI_ABANDON || mi_atomic_load_ptr_acquire(mi_block_t,&heap->thread_delayed_free) == NULL ); + + // collect segment caches + if (collect >= MI_FORCE) { + _mi_segment_thread_collect(&heap->tld->segments); + } + + // collect regions on program-exit (or shared library unload) + if (collect >= MI_FORCE && _mi_is_main_thread() && mi_heap_is_backing(heap)) { + _mi_mem_collect(&heap->tld->os); + } +} + +void _mi_heap_collect_abandon(mi_heap_t* heap) { + mi_heap_collect_ex(heap, MI_ABANDON); +} + +void mi_heap_collect(mi_heap_t* heap, bool force) mi_attr_noexcept { + mi_heap_collect_ex(heap, (force ? MI_FORCE : MI_NORMAL)); +} + +void mi_collect(bool force) mi_attr_noexcept { + mi_heap_collect(mi_get_default_heap(), force); +} + + +/* ----------------------------------------------------------- + Heap new +----------------------------------------------------------- */ + +mi_heap_t* mi_heap_get_default(void) { + mi_thread_init(); + return mi_get_default_heap(); +} + +mi_heap_t* mi_heap_get_backing(void) { + mi_heap_t* heap = mi_heap_get_default(); + mi_assert_internal(heap!=NULL); + mi_heap_t* bheap = heap->tld->heap_backing; + mi_assert_internal(bheap!=NULL); + mi_assert_internal(bheap->thread_id == _mi_thread_id()); + return bheap; +} + +mi_heap_t* mi_heap_new(void) { + mi_heap_t* bheap = mi_heap_get_backing(); + mi_heap_t* heap = mi_heap_malloc_tp(bheap, mi_heap_t); // todo: OS allocate in secure mode? + if (heap==NULL) return NULL; + memcpy(heap, &_mi_heap_empty, sizeof(mi_heap_t)); + heap->tld = bheap->tld; + heap->thread_id = _mi_thread_id(); + _mi_random_split(&bheap->random, &heap->random); + heap->cookie = _mi_heap_random_next(heap) | 1; + heap->keys[0] = _mi_heap_random_next(heap); + heap->keys[1] = _mi_heap_random_next(heap); + heap->no_reclaim = true; // don't reclaim abandoned pages or otherwise destroy is unsafe + // push on the thread local heaps list + heap->next = heap->tld->heaps; + heap->tld->heaps = heap; + return heap; +} + +uintptr_t _mi_heap_random_next(mi_heap_t* heap) { + return _mi_random_next(&heap->random); +} + +// zero out the page queues +static void mi_heap_reset_pages(mi_heap_t* heap) { + mi_assert_internal(mi_heap_is_initialized(heap)); + // TODO: copy full empty heap instead? + memset(&heap->pages_free_direct, 0, sizeof(heap->pages_free_direct)); +#ifdef MI_MEDIUM_DIRECT + memset(&heap->pages_free_medium, 0, sizeof(heap->pages_free_medium)); +#endif + memcpy(&heap->pages, &_mi_heap_empty.pages, sizeof(heap->pages)); + heap->thread_delayed_free = NULL; + heap->page_count = 0; +} + +// called from `mi_heap_destroy` and `mi_heap_delete` to free the internal heap resources. +static void mi_heap_free(mi_heap_t* heap) { + mi_assert(heap != NULL); + mi_assert_internal(mi_heap_is_initialized(heap)); + if (mi_heap_is_backing(heap)) return; // dont free the backing heap + + // reset default + if (mi_heap_is_default(heap)) { + _mi_heap_set_default_direct(heap->tld->heap_backing); + } + + // remove ourselves from the thread local heaps list + // linear search but we expect the number of heaps to be relatively small + mi_heap_t* prev = NULL; + mi_heap_t* curr = heap->tld->heaps; + while (curr != heap && curr != NULL) { + prev = curr; + curr = curr->next; + } + mi_assert_internal(curr == heap); + if (curr == heap) { + if (prev != NULL) { prev->next = heap->next; } + else { heap->tld->heaps = heap->next; } + } + mi_assert_internal(heap->tld->heaps != NULL); + + // and free the used memory + mi_free(heap); +} + + +/* ----------------------------------------------------------- + Heap destroy +----------------------------------------------------------- */ + +static bool _mi_heap_page_destroy(mi_heap_t* heap, mi_page_queue_t* pq, mi_page_t* page, void* arg1, void* arg2) { + UNUSED(arg1); + UNUSED(arg2); + UNUSED(heap); + UNUSED(pq); + + // ensure no more thread_delayed_free will be added + _mi_page_use_delayed_free(page, MI_NEVER_DELAYED_FREE, false); + + // stats + const size_t bsize = mi_page_block_size(page); + if (bsize > MI_LARGE_OBJ_SIZE_MAX) { + if (bsize > MI_HUGE_OBJ_SIZE_MAX) { + _mi_stat_decrease(&heap->tld->stats.giant, bsize); + } + else { + _mi_stat_decrease(&heap->tld->stats.huge, bsize); + } + } +#if (MI_STAT>1) + _mi_page_free_collect(page, false); // update used count + const size_t inuse = page->used; + if (bsize <= MI_LARGE_OBJ_SIZE_MAX) { + mi_heap_stat_decrease(heap, normal[_mi_bin(bsize)], inuse); + } + mi_heap_stat_decrease(heap, malloc, bsize * inuse); // todo: off for aligned blocks... +#endif + + /// pretend it is all free now + mi_assert_internal(mi_page_thread_free(page) == NULL); + page->used = 0; + + // and free the page + // mi_page_free(page,false); + page->next = NULL; + page->prev = NULL; + _mi_segment_page_free(page,false /* no force? */, &heap->tld->segments); + + return true; // keep going +} + +void _mi_heap_destroy_pages(mi_heap_t* heap) { + mi_heap_visit_pages(heap, &_mi_heap_page_destroy, NULL, NULL); + mi_heap_reset_pages(heap); +} + +void mi_heap_destroy(mi_heap_t* heap) { + mi_assert(heap != NULL); + mi_assert(mi_heap_is_initialized(heap)); + mi_assert(heap->no_reclaim); + mi_assert_expensive(mi_heap_is_valid(heap)); + if (!mi_heap_is_initialized(heap)) return; + if (!heap->no_reclaim) { + // don't free in case it may contain reclaimed pages + mi_heap_delete(heap); + } + else { + // free all pages + _mi_heap_destroy_pages(heap); + mi_heap_free(heap); + } +} + + + +/* ----------------------------------------------------------- + Safe Heap delete +----------------------------------------------------------- */ + +// Tranfer the pages from one heap to the other +static void mi_heap_absorb(mi_heap_t* heap, mi_heap_t* from) { + mi_assert_internal(heap!=NULL); + if (from==NULL || from->page_count == 0) return; + + // reduce the size of the delayed frees + _mi_heap_delayed_free(from); + + // transfer all pages by appending the queues; this will set a new heap field + // so threads may do delayed frees in either heap for a while. + // note: appending waits for each page to not be in the `MI_DELAYED_FREEING` state + // so after this only the new heap will get delayed frees + for (size_t i = 0; i <= MI_BIN_FULL; i++) { + mi_page_queue_t* pq = &heap->pages[i]; + mi_page_queue_t* append = &from->pages[i]; + size_t pcount = _mi_page_queue_append(heap, pq, append); + heap->page_count += pcount; + from->page_count -= pcount; + } + mi_assert_internal(from->page_count == 0); + + // and do outstanding delayed frees in the `from` heap + // note: be careful here as the `heap` field in all those pages no longer point to `from`, + // turns out to be ok as `_mi_heap_delayed_free` only visits the list and calls a + // the regular `_mi_free_delayed_block` which is safe. + _mi_heap_delayed_free(from); + mi_assert_internal(from->thread_delayed_free == NULL); + + // and reset the `from` heap + mi_heap_reset_pages(from); +} + +// Safe delete a heap without freeing any still allocated blocks in that heap. +void mi_heap_delete(mi_heap_t* heap) +{ + mi_assert(heap != NULL); + mi_assert(mi_heap_is_initialized(heap)); + mi_assert_expensive(mi_heap_is_valid(heap)); + if (!mi_heap_is_initialized(heap)) return; + + if (!mi_heap_is_backing(heap)) { + // tranfer still used pages to the backing heap + mi_heap_absorb(heap->tld->heap_backing, heap); + } + else { + // the backing heap abandons its pages + _mi_heap_collect_abandon(heap); + } + mi_assert_internal(heap->page_count==0); + mi_heap_free(heap); +} + +mi_heap_t* mi_heap_set_default(mi_heap_t* heap) { + mi_assert(mi_heap_is_initialized(heap)); + if (!mi_heap_is_initialized(heap)) return NULL; + mi_assert_expensive(mi_heap_is_valid(heap)); + mi_heap_t* old = mi_get_default_heap(); + _mi_heap_set_default_direct(heap); + return old; +} + + + + +/* ----------------------------------------------------------- + Analysis +----------------------------------------------------------- */ + +// static since it is not thread safe to access heaps from other threads. +static mi_heap_t* mi_heap_of_block(const void* p) { + if (p == NULL) return NULL; + mi_segment_t* segment = _mi_ptr_segment(p); + bool valid = (_mi_ptr_cookie(segment) == segment->cookie); + mi_assert_internal(valid); + if (mi_unlikely(!valid)) return NULL; + return mi_page_heap(_mi_segment_page_of(segment,p)); +} + +bool mi_heap_contains_block(mi_heap_t* heap, const void* p) { + mi_assert(heap != NULL); + if (!mi_heap_is_initialized(heap)) return false; + return (heap == mi_heap_of_block(p)); +} + + +static bool mi_heap_page_check_owned(mi_heap_t* heap, mi_page_queue_t* pq, mi_page_t* page, void* p, void* vfound) { + UNUSED(heap); + UNUSED(pq); + bool* found = (bool*)vfound; + mi_segment_t* segment = _mi_page_segment(page); + void* start = _mi_page_start(segment, page, NULL); + void* end = (uint8_t*)start + (page->capacity * mi_page_block_size(page)); + *found = (p >= start && p < end); + return (!*found); // continue if not found +} + +bool mi_heap_check_owned(mi_heap_t* heap, const void* p) { + mi_assert(heap != NULL); + if (!mi_heap_is_initialized(heap)) return false; + if (((uintptr_t)p & (MI_INTPTR_SIZE - 1)) != 0) return false; // only aligned pointers + bool found = false; + mi_heap_visit_pages(heap, &mi_heap_page_check_owned, (void*)p, &found); + return found; +} + +bool mi_check_owned(const void* p) { + return mi_heap_check_owned(mi_get_default_heap(), p); +} + +/* ----------------------------------------------------------- + Visit all heap blocks and areas + Todo: enable visiting abandoned pages, and + enable visiting all blocks of all heaps across threads +----------------------------------------------------------- */ + +// Separate struct to keep `mi_page_t` out of the public interface +typedef struct mi_heap_area_ex_s { + mi_heap_area_t area; + mi_page_t* page; +} mi_heap_area_ex_t; + +static bool mi_heap_area_visit_blocks(const mi_heap_area_ex_t* xarea, mi_block_visit_fun* visitor, void* arg) { + mi_assert(xarea != NULL); + if (xarea==NULL) return true; + const mi_heap_area_t* area = &xarea->area; + mi_page_t* page = xarea->page; + mi_assert(page != NULL); + if (page == NULL) return true; + + _mi_page_free_collect(page,true); + mi_assert_internal(page->local_free == NULL); + if (page->used == 0) return true; + + const size_t bsize = mi_page_block_size(page); + size_t psize; + uint8_t* pstart = _mi_page_start(_mi_page_segment(page), page, &psize); + + if (page->capacity == 1) { + // optimize page with one block + mi_assert_internal(page->used == 1 && page->free == NULL); + return visitor(mi_page_heap(page), area, pstart, bsize, arg); + } + + // create a bitmap of free blocks. + #define MI_MAX_BLOCKS (MI_SMALL_PAGE_SIZE / sizeof(void*)) + uintptr_t free_map[MI_MAX_BLOCKS / sizeof(uintptr_t)]; + memset(free_map, 0, sizeof(free_map)); + + size_t free_count = 0; + for (mi_block_t* block = page->free; block != NULL; block = mi_block_next(page,block)) { + free_count++; + mi_assert_internal((uint8_t*)block >= pstart && (uint8_t*)block < (pstart + psize)); + size_t offset = (uint8_t*)block - pstart; + mi_assert_internal(offset % bsize == 0); + size_t blockidx = offset / bsize; // Todo: avoid division? + mi_assert_internal( blockidx < MI_MAX_BLOCKS); + size_t bitidx = (blockidx / sizeof(uintptr_t)); + size_t bit = blockidx - (bitidx * sizeof(uintptr_t)); + free_map[bitidx] |= ((uintptr_t)1 << bit); + } + mi_assert_internal(page->capacity == (free_count + page->used)); + + // walk through all blocks skipping the free ones + size_t used_count = 0; + for (size_t i = 0; i < page->capacity; i++) { + size_t bitidx = (i / sizeof(uintptr_t)); + size_t bit = i - (bitidx * sizeof(uintptr_t)); + uintptr_t m = free_map[bitidx]; + if (bit == 0 && m == UINTPTR_MAX) { + i += (sizeof(uintptr_t) - 1); // skip a run of free blocks + } + else if ((m & ((uintptr_t)1 << bit)) == 0) { + used_count++; + uint8_t* block = pstart + (i * bsize); + if (!visitor(mi_page_heap(page), area, block, bsize, arg)) return false; + } + } + mi_assert_internal(page->used == used_count); + return true; +} + +typedef bool (mi_heap_area_visit_fun)(const mi_heap_t* heap, const mi_heap_area_ex_t* area, void* arg); + + +static bool mi_heap_visit_areas_page(mi_heap_t* heap, mi_page_queue_t* pq, mi_page_t* page, void* vfun, void* arg) { + UNUSED(heap); + UNUSED(pq); + mi_heap_area_visit_fun* fun = (mi_heap_area_visit_fun*)vfun; + mi_heap_area_ex_t xarea; + const size_t bsize = mi_page_block_size(page); + xarea.page = page; + xarea.area.reserved = page->reserved * bsize; + xarea.area.committed = page->capacity * bsize; + xarea.area.blocks = _mi_page_start(_mi_page_segment(page), page, NULL); + xarea.area.used = page->used; + xarea.area.block_size = bsize; + return fun(heap, &xarea, arg); +} + +// Visit all heap pages as areas +static bool mi_heap_visit_areas(const mi_heap_t* heap, mi_heap_area_visit_fun* visitor, void* arg) { + if (visitor == NULL) return false; + return mi_heap_visit_pages((mi_heap_t*)heap, &mi_heap_visit_areas_page, (void*)(visitor), arg); // note: function pointer to void* :-{ +} + +// Just to pass arguments +typedef struct mi_visit_blocks_args_s { + bool visit_blocks; + mi_block_visit_fun* visitor; + void* arg; +} mi_visit_blocks_args_t; + +static bool mi_heap_area_visitor(const mi_heap_t* heap, const mi_heap_area_ex_t* xarea, void* arg) { + mi_visit_blocks_args_t* args = (mi_visit_blocks_args_t*)arg; + if (!args->visitor(heap, &xarea->area, NULL, xarea->area.block_size, args->arg)) return false; + if (args->visit_blocks) { + return mi_heap_area_visit_blocks(xarea, args->visitor, args->arg); + } + else { + return true; + } +} + +// Visit all blocks in a heap +bool mi_heap_visit_blocks(const mi_heap_t* heap, bool visit_blocks, mi_block_visit_fun* visitor, void* arg) { + mi_visit_blocks_args_t args = { visit_blocks, visitor, arg }; + return mi_heap_visit_areas(heap, &mi_heap_area_visitor, &args); +} diff --git a/kotlin-native/runtime/src/mimalloc/c/include/mimalloc-atomic.h b/kotlin-native/runtime/src/mimalloc/c/include/mimalloc-atomic.h new file mode 100644 index 00000000000..3e9d7d5a99a --- /dev/null +++ b/kotlin-native/runtime/src/mimalloc/c/include/mimalloc-atomic.h @@ -0,0 +1,326 @@ +/* ---------------------------------------------------------------------------- +Copyright (c) 2018,2020 Microsoft Research, Daan Leijen +This is free software; you can redistribute it and/or modify it under the +terms of the MIT license. A copy of the license can be found in the file +"licenses/third_party/mimalloc_LICENSE.txt" at the root of this distribution. +-----------------------------------------------------------------------------*/ +// Copyright 2019-2020 JetBrains s.r.o. + +#pragma once +#ifndef MIMALLOC_ATOMIC_H +#define MIMALLOC_ATOMIC_H + +// -------------------------------------------------------------------------------------------- +// Atomics +// We need to be portable between C, C++, and MSVC. +// We base the primitives on the C/C++ atomics and create a mimimal wrapper for MSVC in C compilation mode. +// This is why we try to use only `uintptr_t` and `*` as atomic types. +// To gain better insight in the range of used atomics, we use explicitly named memory order operations +// instead of passing the memory order as a parameter. +// ----------------------------------------------------------------------------------------------- + +#if defined(__cplusplus) +// Use C++ atomics +#include +#define _Atomic(tp) std::atomic +#define mi_atomic(name) std::atomic_##name +#define mi_memory_order(name) std::memory_order_##name +#elif defined(_MSC_VER) +// Use MSVC C wrapper for C11 atomics +#define _Atomic(tp) tp +#define ATOMIC_VAR_INIT(x) x +#define mi_atomic(name) mi_atomic_##name +#define mi_memory_order(name) mi_memory_order_##name +#else +// Use C11 atomics +#include +#define mi_atomic(name) atomic_##name +#define mi_memory_order(name) memory_order_##name +#endif + +// Various defines for all used memory orders in mimalloc +#define mi_atomic_cas_weak(p,expected,desired,mem_success,mem_fail) \ + mi_atomic(compare_exchange_weak_explicit)(p,expected,desired,mem_success,mem_fail) + +#define mi_atomic_cas_strong(p,expected,desired,mem_success,mem_fail) \ + mi_atomic(compare_exchange_strong_explicit)(p,expected,desired,mem_success,mem_fail) + +#define mi_atomic_load_acquire(p) mi_atomic(load_explicit)(p,mi_memory_order(acquire)) +#define mi_atomic_load_relaxed(p) mi_atomic(load_explicit)(p,mi_memory_order(relaxed)) +#define mi_atomic_store_release(p,x) mi_atomic(store_explicit)(p,x,mi_memory_order(release)) +#define mi_atomic_store_relaxed(p,x) mi_atomic(store_explicit)(p,x,mi_memory_order(relaxed)) +#define mi_atomic_exchange_release(p,x) mi_atomic(exchange_explicit)(p,x,mi_memory_order(release)) +#define mi_atomic_exchange_acq_rel(p,x) mi_atomic(exchange_explicit)(p,x,mi_memory_order(acq_rel)) +#define mi_atomic_cas_weak_release(p,exp,des) mi_atomic_cas_weak(p,exp,des,mi_memory_order(release),mi_memory_order(relaxed)) +#define mi_atomic_cas_weak_acq_rel(p,exp,des) mi_atomic_cas_weak(p,exp,des,mi_memory_order(acq_rel),mi_memory_order(acquire)) +#define mi_atomic_cas_strong_release(p,exp,des) mi_atomic_cas_strong(p,exp,des,mi_memory_order(release),mi_memory_order(relaxed)) +#define mi_atomic_cas_strong_acq_rel(p,exp,des) mi_atomic_cas_strong(p,exp,des,mi_memory_order(acq_rel),mi_memory_order(acquire)) + +#define mi_atomic_add_relaxed(p,x) mi_atomic(fetch_add_explicit)(p,x,mi_memory_order(relaxed)) +#define mi_atomic_sub_relaxed(p,x) mi_atomic(fetch_sub_explicit)(p,x,mi_memory_order(relaxed)) +#define mi_atomic_add_acq_rel(p,x) mi_atomic(fetch_add_explicit)(p,x,mi_memory_order(acq_rel)) +#define mi_atomic_sub_acq_rel(p,x) mi_atomic(fetch_sub_explicit)(p,x,mi_memory_order(acq_rel)) +#define mi_atomic_and_acq_rel(p,x) mi_atomic(fetch_and_explicit)(p,x,mi_memory_order(acq_rel)) +#define mi_atomic_or_acq_rel(p,x) mi_atomic(fetch_or_explicit)(p,x,mi_memory_order(acq_rel)) + +#define mi_atomic_increment_relaxed(p) mi_atomic_add_relaxed(p,(uintptr_t)1) +#define mi_atomic_decrement_relaxed(p) mi_atomic_sub_relaxed(p,(uintptr_t)1) +#define mi_atomic_increment_acq_rel(p) mi_atomic_add_acq_rel(p,(uintptr_t)1) +#define mi_atomic_decrement_acq_rel(p) mi_atomic_sub_acq_rel(p,(uintptr_t)1) + +static inline void mi_atomic_yield(void); +static inline intptr_t mi_atomic_addi(_Atomic(intptr_t)*p, intptr_t add); +static inline intptr_t mi_atomic_subi(_Atomic(intptr_t)*p, intptr_t sub); + + +#if defined(__cplusplus) || !defined(_MSC_VER) + +// In C++/C11 atomics we have polymorphic atomics so can use the typed `ptr` variants (where `tp` is the type of atomic value) +// We use these macros so we can provide a typed wrapper in MSVC in C compilation mode as well +#define mi_atomic_load_ptr_acquire(tp,p) mi_atomic_load_acquire(p) +#define mi_atomic_load_ptr_relaxed(tp,p) mi_atomic_load_relaxed(p) + +// In C++ we need to add casts to help resolve templates if NULL is passed +#if defined(__cplusplus) +#define mi_atomic_store_ptr_release(tp,p,x) mi_atomic_store_release(p,(tp*)x) +#define mi_atomic_store_ptr_relaxed(tp,p,x) mi_atomic_store_relaxed(p,(tp*)x) +#define mi_atomic_cas_ptr_weak_release(tp,p,exp,des) mi_atomic_cas_weak_release(p,exp,(tp*)des) +#define mi_atomic_cas_ptr_weak_acq_rel(tp,p,exp,des) mi_atomic_cas_weak_acq_rel(p,exp,(tp*)des) +#define mi_atomic_cas_ptr_strong_release(tp,p,exp,des) mi_atomic_cas_strong_release(p,exp,(tp*)des) +#define mi_atomic_exchange_ptr_release(tp,p,x) mi_atomic_exchange_release(p,(tp*)x) +#define mi_atomic_exchange_ptr_acq_rel(tp,p,x) mi_atomic_exchange_acq_rel(p,(tp*)x) +#else +#define mi_atomic_store_ptr_release(tp,p,x) mi_atomic_store_release(p,x) +#define mi_atomic_store_ptr_relaxed(tp,p,x) mi_atomic_store_relaxed(p,x) +#define mi_atomic_cas_ptr_weak_release(tp,p,exp,des) mi_atomic_cas_weak_release(p,exp,des) +#define mi_atomic_cas_ptr_weak_acq_rel(tp,p,exp,des) mi_atomic_cas_weak_acq_rel(p,exp,des) +#define mi_atomic_cas_ptr_strong_release(tp,p,exp,des) mi_atomic_cas_strong_release(p,exp,des) +#define mi_atomic_exchange_ptr_release(tp,p,x) mi_atomic_exchange_release(p,x) +#define mi_atomic_exchange_ptr_acq_rel(tp,p,x) mi_atomic_exchange_acq_rel(p,x) +#endif + +// These are used by the statistics +static inline int64_t mi_atomic_addi64_relaxed(volatile int64_t* p, int64_t add) { + return mi_atomic(fetch_add_explicit)((_Atomic(int64_t)*)p, add, mi_memory_order(relaxed)); +} +static inline void mi_atomic_maxi64_relaxed(volatile int64_t* p, int64_t x) { + int64_t current = mi_atomic_load_relaxed((_Atomic(int64_t)*)p); + while (current < x && !mi_atomic_cas_weak_release((_Atomic(int64_t)*)p, ¤t, x)) { /* nothing */ }; +} + +// Used by timers +#define mi_atomic_loadi64_acquire(p) mi_atomic(load_explicit)(p,mi_memory_order(acquire)) +#define mi_atomic_loadi64_relaxed(p) mi_atomic(load_explicit)(p,mi_memory_order(relaxed)) +#define mi_atomic_storei64_release(p,x) mi_atomic(store_explicit)(p,x,mi_memory_order(release)) +#define mi_atomic_storei64_relaxed(p,x) mi_atomic(store_explicit)(p,x,mi_memory_order(relaxed)) + + + +#elif defined(_MSC_VER) + +// MSVC C compilation wrapper that uses Interlocked operations to model C11 atomics. +#define WIN32_LEAN_AND_MEAN +#include +#include +#ifdef _WIN64 +typedef LONG64 msc_intptr_t; +#define MI_64(f) f##64 +#else +typedef LONG msc_intptr_t; +#define MI_64(f) f +#endif + +typedef enum mi_memory_order_e { + mi_memory_order_relaxed, + mi_memory_order_consume, + mi_memory_order_acquire, + mi_memory_order_release, + mi_memory_order_acq_rel, + mi_memory_order_seq_cst +} mi_memory_order; + +static inline uintptr_t mi_atomic_fetch_add_explicit(_Atomic(uintptr_t)*p, uintptr_t add, mi_memory_order mo) { + (void)(mo); + return (uintptr_t)MI_64(_InterlockedExchangeAdd)((volatile msc_intptr_t*)p, (msc_intptr_t)add); +} +static inline uintptr_t mi_atomic_fetch_sub_explicit(_Atomic(uintptr_t)*p, uintptr_t sub, mi_memory_order mo) { + (void)(mo); + return (uintptr_t)MI_64(_InterlockedExchangeAdd)((volatile msc_intptr_t*)p, -((msc_intptr_t)sub)); +} +static inline uintptr_t mi_atomic_fetch_and_explicit(_Atomic(uintptr_t)*p, uintptr_t x, mi_memory_order mo) { + (void)(mo); + return (uintptr_t)MI_64(_InterlockedAnd)((volatile msc_intptr_t*)p, (msc_intptr_t)x); +} +static inline uintptr_t mi_atomic_fetch_or_explicit(_Atomic(uintptr_t)*p, uintptr_t x, mi_memory_order mo) { + (void)(mo); + return (uintptr_t)MI_64(_InterlockedOr)((volatile msc_intptr_t*)p, (msc_intptr_t)x); +} +static inline bool mi_atomic_compare_exchange_strong_explicit(_Atomic(uintptr_t)*p, uintptr_t* expected, uintptr_t desired, mi_memory_order mo1, mi_memory_order mo2) { + (void)(mo1); (void)(mo2); + uintptr_t read = (uintptr_t)MI_64(_InterlockedCompareExchange)((volatile msc_intptr_t*)p, (msc_intptr_t)desired, (msc_intptr_t)(*expected)); + if (read == *expected) { + return true; + } + else { + *expected = read; + return false; + } +} +static inline bool mi_atomic_compare_exchange_weak_explicit(_Atomic(uintptr_t)*p, uintptr_t* expected, uintptr_t desired, mi_memory_order mo1, mi_memory_order mo2) { + return mi_atomic_compare_exchange_strong_explicit(p, expected, desired, mo1, mo2); +} +static inline uintptr_t mi_atomic_exchange_explicit(_Atomic(uintptr_t)*p, uintptr_t exchange, mi_memory_order mo) { + (void)(mo); + return (uintptr_t)MI_64(_InterlockedExchange)((volatile msc_intptr_t*)p, (msc_intptr_t)exchange); +} +static inline void mi_atomic_thread_fence(mi_memory_order mo) { + (void)(mo); + _Atomic(uintptr_t)x = 0; + mi_atomic_exchange_explicit(&x, 1, mo); +} +static inline uintptr_t mi_atomic_load_explicit(_Atomic(uintptr_t) const* p, mi_memory_order mo) { + (void)(mo); +#if defined(_M_IX86) || defined(_M_X64) + return *p; +#else + uintptr_t x = *p; + if (mo > mi_memory_order_relaxed) { + while (!mi_atomic_compare_exchange_weak_explicit(p, &x, x, mo, mi_memory_order_relaxed)) { /* nothing */ }; + } + return x; +#endif +} +static inline void mi_atomic_store_explicit(_Atomic(uintptr_t)*p, uintptr_t x, mi_memory_order mo) { + (void)(mo); +#if defined(_M_IX86) || defined(_M_X64) + *p = x; +#else + mi_atomic_exchange_explicit(p, x, mo); +#endif +} +static inline int64_t mi_atomic_loadi64_explicit(_Atomic(int64_t)*p, mi_memory_order mo) { + (void)(mo); +#if defined(_M_X64) + return *p; +#else + int64_t old = *p; + int64_t x = old; + while ((old = InterlockedCompareExchange64(p, x, old)) != x) { + x = old; + } + return x; +#endif +} +static inline void mi_atomic_storei64_explicit(_Atomic(int64_t)*p, int64_t x, mi_memory_order mo) { + (void)(mo); +#if defined(x_M_IX86) || defined(_M_X64) + *p = x; +#else + InterlockedExchange64(p, x); +#endif +} + +// These are used by the statistics +static inline int64_t mi_atomic_addi64_relaxed(volatile _Atomic(int64_t)*p, int64_t add) { +#ifdef _WIN64 + return (int64_t)mi_atomic_addi((int64_t*)p, add); +#else + int64_t current; + int64_t sum; + do { + current = *p; + sum = current + add; + } while (_InterlockedCompareExchange64(p, sum, current) != current); + return current; +#endif +} +static inline void mi_atomic_maxi64_relaxed(volatile _Atomic(int64_t)*p, int64_t x) { + int64_t current; + do { + current = *p; + } while (current < x && _InterlockedCompareExchange64(p, x, current) != current); +} + +// The pointer macros cast to `uintptr_t`. +#define mi_atomic_load_ptr_acquire(tp,p) (tp*)mi_atomic_load_acquire((_Atomic(uintptr_t)*)(p)) +#define mi_atomic_load_ptr_relaxed(tp,p) (tp*)mi_atomic_load_relaxed((_Atomic(uintptr_t)*)(p)) +#define mi_atomic_store_ptr_release(tp,p,x) mi_atomic_store_release((_Atomic(uintptr_t)*)(p),(uintptr_t)(x)) +#define mi_atomic_store_ptr_relaxed(tp,p,x) mi_atomic_store_relaxed((_Atomic(uintptr_t)*)(p),(uintptr_t)(x)) +#define mi_atomic_cas_ptr_weak_release(tp,p,exp,des) mi_atomic_cas_weak_release((_Atomic(uintptr_t)*)(p),(uintptr_t*)exp,(uintptr_t)des) +#define mi_atomic_cas_ptr_weak_acq_rel(tp,p,exp,des) mi_atomic_cas_weak_acq_rel((_Atomic(uintptr_t)*)(p),(uintptr_t*)exp,(uintptr_t)des) +#define mi_atomic_cas_ptr_strong_release(tp,p,exp,des) mi_atomic_cas_strong_release((_Atomic(uintptr_t)*)(p),(uintptr_t*)exp,(uintptr_t)des) +#define mi_atomic_exchange_ptr_release(tp,p,x) (tp*)mi_atomic_exchange_release((_Atomic(uintptr_t)*)(p),(uintptr_t)x) +#define mi_atomic_exchange_ptr_acq_rel(tp,p,x) (tp*)mi_atomic_exchange_acq_rel((_Atomic(uintptr_t)*)(p),(uintptr_t)x) + +#define mi_atomic_loadi64_acquire(p) mi_atomic(loadi64_explicit)(p,mi_memory_order(acquire)) +#define mi_atomic_loadi64_relaxed(p) mi_atomic(loadi64_explicit)(p,mi_memory_order(relaxed)) +#define mi_atomic_storei64_release(p,x) mi_atomic(storei64_explicit)(p,x,mi_memory_order(release)) +#define mi_atomic_storei64_relaxed(p,x) mi_atomic(storei64_explicit)(p,x,mi_memory_order(relaxed)) + + +#endif + + +// Atomically add a signed value; returns the previous value. +static inline intptr_t mi_atomic_addi(_Atomic(intptr_t)*p, intptr_t add) { + return (intptr_t)mi_atomic_add_acq_rel((_Atomic(uintptr_t)*)p, (uintptr_t)add); +} + +// Atomically subtract a signed value; returns the previous value. +static inline intptr_t mi_atomic_subi(_Atomic(intptr_t)*p, intptr_t sub) { + return (intptr_t)mi_atomic_addi(p, -sub); +} + +// Yield +#if defined(__cplusplus) +#include +static inline void mi_atomic_yield(void) { + std::this_thread::yield(); +} +#elif defined(_WIN32) +#define WIN32_LEAN_AND_MEAN +#include +static inline void mi_atomic_yield(void) { + YieldProcessor(); +} +#elif (defined(__GNUC__) || defined(__clang__)) && \ + (defined(__x86_64__) || defined(__i386__) || defined(__arm__) || defined(__aarch64__)) +#if defined(__x86_64__) || defined(__i386__) +static inline void mi_atomic_yield(void) { + __asm__ volatile ("pause" ::: "memory"); +} +#elif defined(__arm__) || defined(__aarch64__) + #if KONAN_MI_MALLOC + #if defined(__arm__) + #include + static inline void mi_atomic_yield(void) { + sched_yield(); + } + #else + static inline void mi_atomic_yield(void) { + asm volatile("yield"); + } + #endif + #else // KONAN_MI_MALLOC + static inline void mi_atomic_yield(void) { + asm volatile("yield"); + } + #endif // KONAN_MI_MALLOC +#endif +#elif defined(__wasi__) + #include + static inline void mi_atomic_yield(void) { + sched_yield(); + } +#else + #include + static inline void mi_atomic_yield(void) { + sleep(0); + } +#endif + +#endif // __MIMALLOC_ATOMIC_H + + + + diff --git a/kotlin-native/runtime/src/mimalloc/c/include/mimalloc-internal.h b/kotlin-native/runtime/src/mimalloc/c/include/mimalloc-internal.h new file mode 100644 index 00000000000..67fd2b5925e --- /dev/null +++ b/kotlin-native/runtime/src/mimalloc/c/include/mimalloc-internal.h @@ -0,0 +1,777 @@ +/* ---------------------------------------------------------------------------- +Copyright (c) 2018, Microsoft Research, Daan Leijen +This is free software; you can redistribute it and/or modify it under the +terms of the MIT license. A copy of the license can be found in the file +"licenses/third_party/mimalloc_LICENSE.txt" at the root of this distribution. +-----------------------------------------------------------------------------*/ +// Copyright 2019-2020 JetBrains s.r.o. + +#pragma once +#ifndef MIMALLOC_INTERNAL_H +#define MIMALLOC_INTERNAL_H + +#include "mimalloc-types.h" + +#if (MI_DEBUG>0) +#define mi_trace_message(...) _mi_trace_message(__VA_ARGS__) +#else +#define mi_trace_message(...) +#endif + +#define MI_CACHE_LINE 64 +#if defined(_MSC_VER) +#pragma warning(disable:4127) // suppress constant conditional warning (due to MI_SECURE paths) +#define mi_decl_noinline __declspec(noinline) +#define mi_decl_thread __declspec(thread) +#define mi_decl_cache_align __declspec(align(MI_CACHE_LINE)) +#elif (defined(__GNUC__) && (__GNUC__>=3)) // includes clang and icc +#define mi_decl_noinline __attribute__((noinline)) +#define mi_decl_thread __thread +#define mi_decl_cache_align __attribute__((aligned(MI_CACHE_LINE))) +#else +#define mi_decl_noinline +#define mi_decl_thread __thread // hope for the best :-) +#define mi_decl_cache_align +#endif + + +// "options.c" +void _mi_fputs(mi_output_fun* out, void* arg, const char* prefix, const char* message); +void _mi_fprintf(mi_output_fun* out, void* arg, const char* fmt, ...); +void _mi_warning_message(const char* fmt, ...); +void _mi_verbose_message(const char* fmt, ...); +void _mi_trace_message(const char* fmt, ...); +void _mi_options_init(void); +void _mi_error_message(int err, const char* fmt, ...); + +// random.c +void _mi_random_init(mi_random_ctx_t* ctx); +void _mi_random_split(mi_random_ctx_t* ctx, mi_random_ctx_t* new_ctx); +uintptr_t _mi_random_next(mi_random_ctx_t* ctx); +uintptr_t _mi_heap_random_next(mi_heap_t* heap); +uintptr_t _os_random_weak(uintptr_t extra_seed); +static inline uintptr_t _mi_random_shuffle(uintptr_t x); + +// init.c +extern mi_stats_t _mi_stats_main; +extern const mi_page_t _mi_page_empty; +bool _mi_is_main_thread(void); +bool _mi_preloading(); // true while the C runtime is not ready + +// os.c +size_t _mi_os_page_size(void); +void _mi_os_init(void); // called from process init +void* _mi_os_alloc(size_t size, mi_stats_t* stats); // to allocate thread local data +void _mi_os_free(void* p, size_t size, mi_stats_t* stats); // to free thread local data +size_t _mi_os_good_alloc_size(size_t size); + +// memory.c +void* _mi_mem_alloc_aligned(size_t size, size_t alignment, bool* commit, bool* large, bool* is_zero, size_t* id, mi_os_tld_t* tld); +void _mi_mem_free(void* p, size_t size, size_t id, bool fully_committed, bool any_reset, mi_os_tld_t* tld); + +bool _mi_mem_reset(void* p, size_t size, mi_os_tld_t* tld); +bool _mi_mem_unreset(void* p, size_t size, bool* is_zero, mi_os_tld_t* tld); +bool _mi_mem_commit(void* p, size_t size, bool* is_zero, mi_os_tld_t* tld); +bool _mi_mem_protect(void* addr, size_t size); +bool _mi_mem_unprotect(void* addr, size_t size); + +void _mi_mem_collect(mi_os_tld_t* tld); + +// "segment.c" +mi_page_t* _mi_segment_page_alloc(mi_heap_t* heap, size_t block_wsize, mi_segments_tld_t* tld, mi_os_tld_t* os_tld); +void _mi_segment_page_free(mi_page_t* page, bool force, mi_segments_tld_t* tld); +void _mi_segment_page_abandon(mi_page_t* page, mi_segments_tld_t* tld); +uint8_t* _mi_segment_page_start(const mi_segment_t* segment, const mi_page_t* page, size_t block_size, size_t* page_size, size_t* pre_size); // page start for any page +void _mi_segment_huge_page_free(mi_segment_t* segment, mi_page_t* page, mi_block_t* block); + +void _mi_segment_thread_collect(mi_segments_tld_t* tld); +void _mi_abandoned_reclaim_all(mi_heap_t* heap, mi_segments_tld_t* tld); +void _mi_abandoned_await_readers(void); + + + +// "page.c" +void* _mi_malloc_generic(mi_heap_t* heap, size_t size) mi_attr_noexcept mi_attr_malloc; + +void _mi_page_retire(mi_page_t* page); // free the page if there are no other pages with many free blocks +void _mi_page_unfull(mi_page_t* page); +void _mi_page_free(mi_page_t* page, mi_page_queue_t* pq, bool force); // free the page +void _mi_page_abandon(mi_page_t* page, mi_page_queue_t* pq); // abandon the page, to be picked up by another thread... +void _mi_heap_delayed_free(mi_heap_t* heap); +void _mi_heap_collect_retired(mi_heap_t* heap, bool force); + +void _mi_page_use_delayed_free(mi_page_t* page, mi_delayed_t delay, bool override_never); +size_t _mi_page_queue_append(mi_heap_t* heap, mi_page_queue_t* pq, mi_page_queue_t* append); +void _mi_deferred_free(mi_heap_t* heap, bool force); + +void _mi_page_free_collect(mi_page_t* page,bool force); +void _mi_page_reclaim(mi_heap_t* heap, mi_page_t* page); // callback from segments + +size_t _mi_bin_size(uint8_t bin); // for stats +uint8_t _mi_bin(size_t size); // for stats +uint8_t _mi_bsr(uintptr_t x); // bit-scan-right, used on BSD in "os.c" + +// "heap.c" +void _mi_heap_destroy_pages(mi_heap_t* heap); +void _mi_heap_collect_abandon(mi_heap_t* heap); +void _mi_heap_set_default_direct(mi_heap_t* heap); + +// "stats.c" +void _mi_stats_done(mi_stats_t* stats); + +mi_msecs_t _mi_clock_now(void); +mi_msecs_t _mi_clock_end(mi_msecs_t start); +mi_msecs_t _mi_clock_start(void); + +// "alloc.c" +void* _mi_page_malloc(mi_heap_t* heap, mi_page_t* page, size_t size) mi_attr_noexcept; // called from `_mi_malloc_generic` +void* _mi_heap_malloc_zero(mi_heap_t* heap, size_t size, bool zero); +void* _mi_heap_realloc_zero(mi_heap_t* heap, void* p, size_t newsize, bool zero); +mi_block_t* _mi_page_ptr_unalign(const mi_segment_t* segment, const mi_page_t* page, const void* p); +bool _mi_free_delayed_block(mi_block_t* block); +void _mi_block_zero_init(const mi_page_t* page, void* p, size_t size); + +#if MI_DEBUG>1 +bool _mi_page_is_valid(mi_page_t* page); +#endif + + +// ------------------------------------------------------ +// Branches +// ------------------------------------------------------ + +#if defined(__GNUC__) || defined(__clang__) +#define mi_unlikely(x) __builtin_expect((x),0) +#define mi_likely(x) __builtin_expect((x),1) +#else +#define mi_unlikely(x) (x) +#define mi_likely(x) (x) +#endif + +#ifndef __has_builtin +#define __has_builtin(x) 0 +#endif + + +/* ----------------------------------------------------------- + Error codes passed to `_mi_fatal_error` + All are recoverable but EFAULT is a serious error and aborts by default in secure mode. + For portability define undefined error codes using common Unix codes: + +----------------------------------------------------------- */ +#include +#ifndef EAGAIN // double free +#define EAGAIN (11) +#endif +#ifndef ENOMEM // out of memory +#define ENOMEM (12) +#endif +#ifndef EFAULT // corrupted free-list or meta-data +#define EFAULT (14) +#endif +#ifndef EINVAL // trying to free an invalid pointer +#define EINVAL (22) +#endif +#ifndef EOVERFLOW // count*size overflow +#define EOVERFLOW (75) +#endif + + +/* ----------------------------------------------------------- + Inlined definitions +----------------------------------------------------------- */ +#define UNUSED(x) (void)(x) +#if (MI_DEBUG>0) +#define UNUSED_RELEASE(x) +#else +#define UNUSED_RELEASE(x) UNUSED(x) +#endif + +#define MI_INIT4(x) x(),x(),x(),x() +#define MI_INIT8(x) MI_INIT4(x),MI_INIT4(x) +#define MI_INIT16(x) MI_INIT8(x),MI_INIT8(x) +#define MI_INIT32(x) MI_INIT16(x),MI_INIT16(x) +#define MI_INIT64(x) MI_INIT32(x),MI_INIT32(x) +#define MI_INIT128(x) MI_INIT64(x),MI_INIT64(x) +#define MI_INIT256(x) MI_INIT128(x),MI_INIT128(x) + + +// Is `x` a power of two? (0 is considered a power of two) +static inline bool _mi_is_power_of_two(uintptr_t x) { + return ((x & (x - 1)) == 0); +} + +// Align upwards +static inline uintptr_t _mi_align_up(uintptr_t sz, size_t alignment) { + mi_assert_internal(alignment != 0); + uintptr_t mask = alignment - 1; + if ((alignment & mask) == 0) { // power of two? + return ((sz + mask) & ~mask); + } + else { + return (((sz + mask)/alignment)*alignment); + } +} + +// Divide upwards: `s <= _mi_divide_up(s,d)*d < s+d`. +static inline uintptr_t _mi_divide_up(uintptr_t size, size_t divider) { + mi_assert_internal(divider != 0); + return (divider == 0 ? size : ((size + divider - 1) / divider)); +} + +// Is memory zero initialized? +static inline bool mi_mem_is_zero(void* p, size_t size) { + for (size_t i = 0; i < size; i++) { + if (((uint8_t*)p)[i] != 0) return false; + } + return true; +} + +// Align a byte size to a size in _machine words_, +// i.e. byte size == `wsize*sizeof(void*)`. +static inline size_t _mi_wsize_from_size(size_t size) { + mi_assert_internal(size <= SIZE_MAX - sizeof(uintptr_t)); + return (size + sizeof(uintptr_t) - 1) / sizeof(uintptr_t); +} + +// Does malloc satisfy the alignment constraints already? +static inline bool mi_malloc_satisfies_alignment(size_t alignment, size_t size) { + return (alignment == sizeof(void*) || (alignment == MI_MAX_ALIGN_SIZE && size > (MI_MAX_ALIGN_SIZE/2))); +} + +// Overflow detecting multiply +#if __has_builtin(__builtin_umul_overflow) || __GNUC__ >= 5 +#include // UINT_MAX, ULONG_MAX +#if defined(_CLOCK_T) // for Illumos +#undef _CLOCK_T +#endif + +static inline bool mi_mul_overflow(size_t count, size_t size, size_t* total) { +// Changed order for armv7 (ULONG_MAX == UINT_MAX, but size_t = unsigned long) +#if defined(__MACH__) && KONAN_MI_MALLOC + #if (SIZE_MAX == ULONG_MAX) + return __builtin_umull_overflow(count, size, total); + #elif (SIZE_MAX == UINT_MAX) + return __builtin_umul_overflow(count, size, total); + #else + return __builtin_umulll_overflow(count, size, total); + #endif +#else // KONAN_MI_MALLOC + #if (SIZE_MAX == UINT_MAX) + return __builtin_umul_overflow(count, size, total); + #elif (SIZE_MAX == ULONG_MAX) + return __builtin_umull_overflow(count, size, total); + #else + return __builtin_umulll_overflow(count, size, total); + #endif +#endif // KONAN_MI_MALLOC +} +#else /* __builtin_umul_overflow is unavailable */ +static inline bool mi_mul_overflow(size_t count, size_t size, size_t* total) { + #define MI_MUL_NO_OVERFLOW ((size_t)1 << (4*sizeof(size_t))) // sqrt(SIZE_MAX) + *total = count * size; + return ((size >= MI_MUL_NO_OVERFLOW || count >= MI_MUL_NO_OVERFLOW) + && size > 0 && (SIZE_MAX / size) < count); +} +#endif + +// Safe multiply `count*size` into `total`; return `true` on overflow. +static inline bool mi_count_size_overflow(size_t count, size_t size, size_t* total) { + if (count==1) { // quick check for the case where count is one (common for C++ allocators) + *total = size; + return false; + } + else if (mi_unlikely(mi_mul_overflow(count, size, total))) { + _mi_error_message(EOVERFLOW, "allocation request is too large (%zu * %zu bytes)\n", count, size); + *total = SIZE_MAX; + return true; + } + else return false; +} + + +/* ---------------------------------------------------------------------------------------- +The thread local default heap: `_mi_get_default_heap` returns the thread local heap. +On most platforms (Windows, Linux, FreeBSD, NetBSD, etc), this just returns a +__thread local variable (`_mi_heap_default`). With the initial-exec TLS model this ensures +that the storage will always be available (allocated on the thread stacks). +On some platforms though we cannot use that when overriding `malloc` since the underlying +TLS implementation (or the loader) will call itself `malloc` on a first access and recurse. +We try to circumvent this in an efficient way: +- macOSX : we use an unused TLS slot from the OS allocated slots (MI_TLS_SLOT). On OSX, the + loader itself calls `malloc` even before the modules are initialized. +- OpenBSD: we use an unused slot from the pthread block (MI_TLS_PTHREAD_SLOT_OFS). +- DragonFly: not yet working. +------------------------------------------------------------------------------------------- */ + +extern const mi_heap_t _mi_heap_empty; // read-only empty heap, initial value of the thread local default heap +extern bool _mi_process_is_initialized; +mi_heap_t* _mi_heap_main_get(void); // statically allocated main backing heap + +#if defined(MI_MALLOC_OVERRIDE) +#if defined(__MACH__) // OSX +#define MI_TLS_SLOT 89 // seems unused? +// other possible unused ones are 9, 29, __PTK_FRAMEWORK_JAVASCRIPTCORE_KEY4 (94), __PTK_FRAMEWORK_GC_KEY9 (112) and __PTK_FRAMEWORK_OLDGC_KEY9 (89) +// see +#elif defined(__OpenBSD__) +// use end bytes of a name; goes wrong if anyone uses names > 23 characters (ptrhread specifies 16) +// see +#define MI_TLS_PTHREAD_SLOT_OFS (6*sizeof(int) + 4*sizeof(void*) + 24) +#elif defined(__DragonFly__) +#warning "mimalloc is not working correctly on DragonFly yet." +#define MI_TLS_PTHREAD_SLOT_OFS (4 + 1*sizeof(void*)) // offset `uniqueid` (also used by gdb?) +#endif +#endif + +#if defined(MI_TLS_SLOT) +static inline void* mi_tls_slot(size_t slot) mi_attr_noexcept; // forward declaration +#elif defined(MI_TLS_PTHREAD_SLOT_OFS) +#include +static inline mi_heap_t** mi_tls_pthread_heap_slot(void) { + pthread_t self = pthread_self(); + #if defined(__DragonFly__) + if (self==NULL) { + static mi_heap_t* pheap_main = _mi_heap_main_get(); + return &pheap_main; + } + #endif + return (mi_heap_t**)((uint8_t*)self + MI_TLS_PTHREAD_SLOT_OFS); +} +#elif defined(MI_TLS_PTHREAD) +#include +extern pthread_key_t _mi_heap_default_key; +#else +extern mi_decl_thread mi_heap_t* _mi_heap_default; // default heap to allocate from +#endif + +static inline mi_heap_t* mi_get_default_heap(void) { +#if defined(MI_TLS_SLOT) + mi_heap_t* heap = (mi_heap_t*)mi_tls_slot(MI_TLS_SLOT); + return (mi_unlikely(heap == NULL) ? (mi_heap_t*)&_mi_heap_empty : heap); +#elif defined(MI_TLS_PTHREAD_SLOT_OFS) + mi_heap_t* heap = *mi_tls_pthread_heap_slot(); + return (mi_unlikely(heap == NULL) ? (mi_heap_t*)&_mi_heap_empty : heap); +#elif defined(MI_TLS_PTHREAD) + mi_heap_t* heap = (mi_unlikely(_mi_heap_default_key == (pthread_key_t)(-1)) ? _mi_heap_main_get() : (mi_heap_t*)pthread_getspecific(_mi_heap_default_key)); + return (mi_unlikely(heap == NULL) ? (mi_heap_t*)&_mi_heap_empty : heap); +#else + #if defined(MI_TLS_RECURSE_GUARD) + if (mi_unlikely(!_mi_process_is_initialized)) return _mi_heap_main_get(); + #endif + return _mi_heap_default; +#endif +} + +static inline bool mi_heap_is_default(const mi_heap_t* heap) { + return (heap == mi_get_default_heap()); +} + +static inline bool mi_heap_is_backing(const mi_heap_t* heap) { + return (heap->tld->heap_backing == heap); +} + +static inline bool mi_heap_is_initialized(mi_heap_t* heap) { + mi_assert_internal(heap != NULL); + return (heap != &_mi_heap_empty); +} + +static inline uintptr_t _mi_ptr_cookie(const void* p) { + extern mi_heap_t _mi_heap_main; + mi_assert_internal(_mi_heap_main.cookie != 0); + return ((uintptr_t)p ^ _mi_heap_main.cookie); +} + +/* ----------------------------------------------------------- + Pages +----------------------------------------------------------- */ + +static inline mi_page_t* _mi_heap_get_free_small_page(mi_heap_t* heap, size_t size) { + mi_assert_internal(size <= (MI_SMALL_SIZE_MAX + MI_PADDING_SIZE)); + const size_t idx = _mi_wsize_from_size(size); + mi_assert_internal(idx < MI_PAGES_DIRECT); + return heap->pages_free_direct[idx]; +} + +// Get the page belonging to a certain size class +static inline mi_page_t* _mi_get_free_small_page(size_t size) { + return _mi_heap_get_free_small_page(mi_get_default_heap(), size); +} + +// Segment that contains the pointer +static inline mi_segment_t* _mi_ptr_segment(const void* p) { + // mi_assert_internal(p != NULL); + return (mi_segment_t*)((uintptr_t)p & ~MI_SEGMENT_MASK); +} + +// Segment belonging to a page +static inline mi_segment_t* _mi_page_segment(const mi_page_t* page) { + mi_segment_t* segment = _mi_ptr_segment(page); + mi_assert_internal(segment == NULL || page == &segment->pages[page->segment_idx]); + return segment; +} + +// used internally +static inline uintptr_t _mi_segment_page_idx_of(const mi_segment_t* segment, const void* p) { + // if (segment->page_size > MI_SEGMENT_SIZE) return &segment->pages[0]; // huge pages + ptrdiff_t diff = (uint8_t*)p - (uint8_t*)segment; + mi_assert_internal(diff >= 0 && (size_t)diff < MI_SEGMENT_SIZE); + uintptr_t idx = (uintptr_t)diff >> segment->page_shift; + mi_assert_internal(idx < segment->capacity); + mi_assert_internal(segment->page_kind <= MI_PAGE_MEDIUM || idx == 0); + return idx; +} + +// Get the page containing the pointer +static inline mi_page_t* _mi_segment_page_of(const mi_segment_t* segment, const void* p) { + uintptr_t idx = _mi_segment_page_idx_of(segment, p); + return &((mi_segment_t*)segment)->pages[idx]; +} + +// Quick page start for initialized pages +static inline uint8_t* _mi_page_start(const mi_segment_t* segment, const mi_page_t* page, size_t* page_size) { + const size_t bsize = page->xblock_size; + mi_assert_internal(bsize > 0 && (bsize%sizeof(void*)) == 0); + return _mi_segment_page_start(segment, page, bsize, page_size, NULL); +} + +// Get the page containing the pointer +static inline mi_page_t* _mi_ptr_page(void* p) { + return _mi_segment_page_of(_mi_ptr_segment(p), p); +} + +// Get the block size of a page (special cased for huge objects) +static inline size_t mi_page_block_size(const mi_page_t* page) { + const size_t bsize = page->xblock_size; + mi_assert_internal(bsize > 0); + if (mi_likely(bsize < MI_HUGE_BLOCK_SIZE)) { + return bsize; + } + else { + size_t psize; + _mi_segment_page_start(_mi_page_segment(page), page, bsize, &psize, NULL); + return psize; + } +} + +// Get the usable block size of a page without fixed padding. +// This may still include internal padding due to alignment and rounding up size classes. +static inline size_t mi_page_usable_block_size(const mi_page_t* page) { + return mi_page_block_size(page) - MI_PADDING_SIZE; +} + + +// Thread free access +static inline mi_block_t* mi_page_thread_free(const mi_page_t* page) { + return (mi_block_t*)(mi_atomic_load_relaxed(&((mi_page_t*)page)->xthread_free) & ~3); +} + +static inline mi_delayed_t mi_page_thread_free_flag(const mi_page_t* page) { + return (mi_delayed_t)(mi_atomic_load_relaxed(&((mi_page_t*)page)->xthread_free) & 3); +} + +// Heap access +static inline mi_heap_t* mi_page_heap(const mi_page_t* page) { + return (mi_heap_t*)(mi_atomic_load_relaxed(&((mi_page_t*)page)->xheap)); +} + +static inline void mi_page_set_heap(mi_page_t* page, mi_heap_t* heap) { + mi_assert_internal(mi_page_thread_free_flag(page) != MI_DELAYED_FREEING); + mi_atomic_store_release(&page->xheap,(uintptr_t)heap); +} + +// Thread free flag helpers +static inline mi_block_t* mi_tf_block(mi_thread_free_t tf) { + return (mi_block_t*)(tf & ~0x03); +} +static inline mi_delayed_t mi_tf_delayed(mi_thread_free_t tf) { + return (mi_delayed_t)(tf & 0x03); +} +static inline mi_thread_free_t mi_tf_make(mi_block_t* block, mi_delayed_t delayed) { + return (mi_thread_free_t)((uintptr_t)block | (uintptr_t)delayed); +} +static inline mi_thread_free_t mi_tf_set_delayed(mi_thread_free_t tf, mi_delayed_t delayed) { + return mi_tf_make(mi_tf_block(tf),delayed); +} +static inline mi_thread_free_t mi_tf_set_block(mi_thread_free_t tf, mi_block_t* block) { + return mi_tf_make(block, mi_tf_delayed(tf)); +} + +// are all blocks in a page freed? +// note: needs up-to-date used count, (as the `xthread_free` list may not be empty). see `_mi_page_collect_free`. +static inline bool mi_page_all_free(const mi_page_t* page) { + mi_assert_internal(page != NULL); + return (page->used == 0); +} + +// are there any available blocks? +static inline bool mi_page_has_any_available(const mi_page_t* page) { + mi_assert_internal(page != NULL && page->reserved > 0); + return (page->used < page->reserved || (mi_page_thread_free(page) != NULL)); +} + +// are there immediately available blocks, i.e. blocks available on the free list. +static inline bool mi_page_immediate_available(const mi_page_t* page) { + mi_assert_internal(page != NULL); + return (page->free != NULL); +} + +// is more than 7/8th of a page in use? +static inline bool mi_page_mostly_used(const mi_page_t* page) { + if (page==NULL) return true; + uint16_t frac = page->reserved / 8U; + return (page->reserved - page->used <= frac); +} + +static inline mi_page_queue_t* mi_page_queue(const mi_heap_t* heap, size_t size) { + return &((mi_heap_t*)heap)->pages[_mi_bin(size)]; +} + + + +//----------------------------------------------------------- +// Page flags +//----------------------------------------------------------- +static inline bool mi_page_is_in_full(const mi_page_t* page) { + return page->flags.x.in_full; +} + +static inline void mi_page_set_in_full(mi_page_t* page, bool in_full) { + page->flags.x.in_full = in_full; +} + +static inline bool mi_page_has_aligned(const mi_page_t* page) { + return page->flags.x.has_aligned; +} + +static inline void mi_page_set_has_aligned(mi_page_t* page, bool has_aligned) { + page->flags.x.has_aligned = has_aligned; +} + + +/* ------------------------------------------------------------------- +Encoding/Decoding the free list next pointers + +This is to protect against buffer overflow exploits where the +free list is mutated. Many hardened allocators xor the next pointer `p` +with a secret key `k1`, as `p^k1`. This prevents overwriting with known +values but might be still too weak: if the attacker can guess +the pointer `p` this can reveal `k1` (since `p^k1^p == k1`). +Moreover, if multiple blocks can be read as well, the attacker can +xor both as `(p1^k1) ^ (p2^k1) == p1^p2` which may reveal a lot +about the pointers (and subsequently `k1`). + +Instead mimalloc uses an extra key `k2` and encodes as `((p^k2)<<> (MI_INTPTR_BITS - shift)))); +} +static inline uintptr_t mi_rotr(uintptr_t x, uintptr_t shift) { + shift %= MI_INTPTR_BITS; + return (shift==0 ? x : ((x >> shift) | (x << (MI_INTPTR_BITS - shift)))); +} + +static inline void* mi_ptr_decode(const void* null, const mi_encoded_t x, const uintptr_t* keys) { + void* p = (void*)(mi_rotr(x - keys[0], keys[0]) ^ keys[1]); + return (mi_unlikely(p==null) ? NULL : p); +} + +static inline mi_encoded_t mi_ptr_encode(const void* null, const void* p, const uintptr_t* keys) { + uintptr_t x = (uintptr_t)(mi_unlikely(p==NULL) ? null : p); + return mi_rotl(x ^ keys[1], keys[0]) + keys[0]; +} + +static inline mi_block_t* mi_block_nextx( const void* null, const mi_block_t* block, const uintptr_t* keys ) { + #ifdef MI_ENCODE_FREELIST + return (mi_block_t*)mi_ptr_decode(null, block->next, keys); + #else + UNUSED(keys); UNUSED(null); + return (mi_block_t*)block->next; + #endif +} + +static inline void mi_block_set_nextx(const void* null, mi_block_t* block, const mi_block_t* next, const uintptr_t* keys) { + #ifdef MI_ENCODE_FREELIST + block->next = mi_ptr_encode(null, next, keys); + #else + UNUSED(keys); UNUSED(null); + block->next = (mi_encoded_t)next; + #endif +} + +static inline mi_block_t* mi_block_next(const mi_page_t* page, const mi_block_t* block) { + #ifdef MI_ENCODE_FREELIST + mi_block_t* next = mi_block_nextx(page,block,page->keys); + // check for free list corruption: is `next` at least in the same page? + // TODO: check if `next` is `page->block_size` aligned? + if (mi_unlikely(next!=NULL && !mi_is_in_same_page(block, next))) { + _mi_error_message(EFAULT, "corrupted free list entry of size %zub at %p: value 0x%zx\n", mi_page_block_size(page), block, (uintptr_t)next); + next = NULL; + } + return next; + #else + UNUSED(page); + return mi_block_nextx(page,block,NULL); + #endif +} + +static inline void mi_block_set_next(const mi_page_t* page, mi_block_t* block, const mi_block_t* next) { + #ifdef MI_ENCODE_FREELIST + mi_block_set_nextx(page,block,next, page->keys); + #else + UNUSED(page); + mi_block_set_nextx(page,block,next,NULL); + #endif +} + +// ------------------------------------------------------------------- +// Fast "random" shuffle +// ------------------------------------------------------------------- + +static inline uintptr_t _mi_random_shuffle(uintptr_t x) { + if (x==0) { x = 17; } // ensure we don't get stuck in generating zeros +#if (MI_INTPTR_SIZE==8) + // by Sebastiano Vigna, see: + x ^= x >> 30; + x *= 0xbf58476d1ce4e5b9UL; + x ^= x >> 27; + x *= 0x94d049bb133111ebUL; + x ^= x >> 31; +#elif (MI_INTPTR_SIZE==4) + // by Chris Wellons, see: + x ^= x >> 16; + x *= 0x7feb352dUL; + x ^= x >> 15; + x *= 0x846ca68bUL; + x ^= x >> 16; +#endif + return x; +} + +// ------------------------------------------------------------------- +// Optimize numa node access for the common case (= one node) +// ------------------------------------------------------------------- + +int _mi_os_numa_node_get(mi_os_tld_t* tld); +size_t _mi_os_numa_node_count_get(void); + +extern size_t _mi_numa_node_count; +static inline int _mi_os_numa_node(mi_os_tld_t* tld) { + if (mi_likely(_mi_numa_node_count == 1)) return 0; + else return _mi_os_numa_node_get(tld); +} +static inline size_t _mi_os_numa_node_count(void) { + if (mi_likely(_mi_numa_node_count>0)) return _mi_numa_node_count; + else return _mi_os_numa_node_count_get(); +} + + +// ------------------------------------------------------------------- +// Getting the thread id should be performant as it is called in the +// fast path of `_mi_free` and we specialize for various platforms. +// ------------------------------------------------------------------- +#if defined(_WIN32) +#define WIN32_LEAN_AND_MEAN +#include +static inline uintptr_t _mi_thread_id(void) mi_attr_noexcept { + // Windows: works on Intel and ARM in both 32- and 64-bit + return (uintptr_t)NtCurrentTeb(); +} + +#elif defined(__GNUC__) && \ + (defined(__x86_64__) || defined(__i386__) || defined(__arm__) || defined(__aarch64__)) + +#if KONAN_MI_MALLOC + #include + pthread_t pthread_self(void); +#endif // KONAN_MI_MALLOC + +// TLS register on x86 is in the FS or GS register, see: https://akkadia.org/drepper/tls.pdf +static inline void* mi_tls_slot(size_t slot) mi_attr_noexcept { + void* res; + const size_t ofs = (slot*sizeof(void*)); +#if defined(__i386__) + __asm__("movl %%gs:%1, %0" : "=r" (res) : "m" (*((void**)ofs)) : ); // 32-bit always uses GS +#elif defined(__MACH__) && defined(__x86_64__) + __asm__("movq %%gs:%1, %0" : "=r" (res) : "m" (*((void**)ofs)) : ); // x86_64 macOSX uses GS +#elif defined(__x86_64__) + __asm__("movq %%fs:%1, %0" : "=r" (res) : "m" (*((void**)ofs)) : ); // x86_64 Linux, BSD uses FS +#elif defined(__arm__) + void** tcb; UNUSED(ofs); + __asm__ volatile ("mrc p15, 0, %0, c13, c0, 3\nbic %0, %0, #3" : "=r" (tcb)); + res = tcb[slot]; +#elif defined(__aarch64__) + void** tcb; UNUSED(ofs); + __asm__ volatile ("mrs %0, tpidr_el0" : "=r" (tcb)); + res = tcb[slot]; +#endif + return res; +} + +// setting is only used on macOSX for now +static inline void mi_tls_slot_set(size_t slot, void* value) mi_attr_noexcept { + const size_t ofs = (slot*sizeof(void*)); +#if defined(__i386__) + __asm__("movl %1,%%gs:%0" : "=m" (*((void**)ofs)) : "rn" (value) : ); // 32-bit always uses GS +#elif defined(__MACH__) && defined(__x86_64__) + __asm__("movq %1,%%gs:%0" : "=m" (*((void**)ofs)) : "rn" (value) : ); // x86_64 macOSX uses GS +#elif defined(__x86_64__) + __asm__("movq %1,%%fs:%1" : "=m" (*((void**)ofs)) : "rn" (value) : ); // x86_64 Linux, BSD uses FS +#elif defined(__arm__) + void** tcb; UNUSED(ofs); + __asm__ volatile ("mrc p15, 0, %0, c13, c0, 3\nbic %0, %0, #3" : "=r" (tcb)); + tcb[slot] = value; +#elif defined(__aarch64__) + void** tcb; UNUSED(ofs); + __asm__ volatile ("mrs %0, tpidr_el0" : "=r" (tcb)); + tcb[slot] = value; +#endif +} + +static inline uintptr_t _mi_thread_id(void) mi_attr_noexcept { + #if defined(__MACH__) && KONAN_MI_MALLOC + #include + #if TARGET_OS_EMBEDDED // iOS/tvOS/watchOS devices. + return pthread_mach_thread_np(pthread_self()); + #else + // in all our targets, slot 0 is the pointer to the thread control block + return (uintptr_t)mi_tls_slot(0); + #endif + #else // KONAN_MI_MALLOC + // in all our targets, slot 0 is the pointer to the thread control block + return (uintptr_t)mi_tls_slot(0); + #endif // KONAN_MI_MALLOC +} +#else +// otherwise use standard C +static inline uintptr_t _mi_thread_id(void) mi_attr_noexcept { + return (uintptr_t)&_mi_heap_default; +} +#endif + + +#endif diff --git a/kotlin-native/runtime/src/mimalloc/c/include/mimalloc-new-delete.h b/kotlin-native/runtime/src/mimalloc/c/include/mimalloc-new-delete.h new file mode 100644 index 00000000000..e9d12fcabca --- /dev/null +++ b/kotlin-native/runtime/src/mimalloc/c/include/mimalloc-new-delete.h @@ -0,0 +1,52 @@ +/* ---------------------------------------------------------------------------- +Copyright (c) 2018,2019 Microsoft Research, Daan Leijen +This is free software; you can redistribute it and/or modify it under the +terms of the MIT license. A copy of the license can be found in the file +"licenses/third_party/mimalloc_LICENSE.txt" at the root of this distribution. +-----------------------------------------------------------------------------*/ +#pragma once +#ifndef MIMALLOC_NEW_DELETE_H +#define MIMALLOC_NEW_DELETE_H + +// ---------------------------------------------------------------------------- +// This header provides convenient overrides for the new and +// delete operations in C++. +// +// This header should be included in only one source file! +// +// On Windows, or when linking dynamically with mimalloc, these +// can be more performant than the standard new-delete operations. +// See +// --------------------------------------------------------------------------- +#if defined(__cplusplus) + #include + #include + + void operator delete(void* p) noexcept { mi_free(p); }; + void operator delete[](void* p) noexcept { mi_free(p); }; + + void* operator new(std::size_t n) noexcept(false) { return mi_new(n); } + void* operator new[](std::size_t n) noexcept(false) { return mi_new(n); } + + void* operator new (std::size_t n, const std::nothrow_t& tag) noexcept { (void)(tag); return mi_new_nothrow(n); } + void* operator new[](std::size_t n, const std::nothrow_t& tag) noexcept { (void)(tag); return mi_new_nothrow(n); } + + #if (__cplusplus >= 201402L || _MSC_VER >= 1916) + void operator delete (void* p, std::size_t n) noexcept { mi_free_size(p,n); }; + void operator delete[](void* p, std::size_t n) noexcept { mi_free_size(p,n); }; + #endif + + #if (__cplusplus > 201402L || defined(__cpp_aligned_new)) + void operator delete (void* p, std::align_val_t al) noexcept { mi_free_aligned(p, static_cast(al)); } + void operator delete[](void* p, std::align_val_t al) noexcept { mi_free_aligned(p, static_cast(al)); } + void operator delete (void* p, std::size_t n, std::align_val_t al) noexcept { mi_free_size_aligned(p, n, static_cast(al)); }; + void operator delete[](void* p, std::size_t n, std::align_val_t al) noexcept { mi_free_size_aligned(p, n, static_cast(al)); }; + + void* operator new( std::size_t n, std::align_val_t al) noexcept(false) { return mi_new_aligned(n, static_cast(al)); } + void* operator new[]( std::size_t n, std::align_val_t al) noexcept(false) { return mi_new_aligned(n, static_cast(al)); } + void* operator new (std::size_t n, std::align_val_t al, const std::nothrow_t&) noexcept { return mi_new_aligned_nothrow(n, static_cast(al)); } + void* operator new[](std::size_t n, std::align_val_t al, const std::nothrow_t&) noexcept { return mi_new_aligned_nothrow(n, static_cast(al)); } + #endif +#endif + +#endif // MIMALLOC_NEW_DELETE_H diff --git a/kotlin-native/runtime/src/mimalloc/c/include/mimalloc-override.h b/kotlin-native/runtime/src/mimalloc/c/include/mimalloc-override.h new file mode 100644 index 00000000000..43a33ed1223 --- /dev/null +++ b/kotlin-native/runtime/src/mimalloc/c/include/mimalloc-override.h @@ -0,0 +1,66 @@ +/* ---------------------------------------------------------------------------- +Copyright (c) 2018,2019 Microsoft Research, Daan Leijen +This is free software; you can redistribute it and/or modify it under the +terms of the MIT license. A copy of the license can be found in the file +"licenses/third_party/mimalloc_LICENSE.txt" at the root of this distribution. +-----------------------------------------------------------------------------*/ +#pragma once +#ifndef MIMALLOC_OVERRIDE_H +#define MIMALLOC_OVERRIDE_H + +/* ---------------------------------------------------------------------------- +This header can be used to statically redirect malloc/free and new/delete +to the mimalloc variants. This can be useful if one can include this file on +each source file in a project (but be careful when using external code to +not accidentally mix pointers from different allocators). +-----------------------------------------------------------------------------*/ + +#include + +// Standard C allocation +#define malloc(n) mi_malloc(n) +#define calloc(n,c) mi_calloc(n,c) +#define realloc(p,n) mi_realloc(p,n) +#define free(p) mi_free(p) + +#define strdup(s) mi_strdup(s) +#define strndup(s) mi_strndup(s) +#define realpath(f,n) mi_realpath(f,n) + +// Microsoft extensions +#define _expand(p,n) mi_expand(p,n) +#define _msize(p) mi_usable_size(p) +#define _recalloc(p,n,c) mi_recalloc(p,n,c) + +#define _strdup(s) mi_strdup(s) +#define _strndup(s) mi_strndup(s) +#define _wcsdup(s) (wchar_t*)mi_wcsdup((const unsigned short*)(s)) +#define _mbsdup(s) mi_mbsdup(s) +#define _dupenv_s(b,n,v) mi_dupenv_s(b,n,v) +#define _wdupenv_s(b,n,v) mi_wdupenv_s((unsigned short*)(b),n,(const unsigned short*)(v)) + +// Various Posix and Unix variants +#define reallocf(p,n) mi_reallocf(p,n) +#define malloc_size(p) mi_usable_size(p) +#define malloc_usable_size(p) mi_usable_size(p) +#define cfree(p) mi_free(p) + +#define valloc(n) mi_valloc(n) +#define pvalloc(n) mi_pvalloc(n) +#define reallocarray(p,s,n) mi_reallocarray(p,s,n) +#define memalign(a,n) mi_memalign(a,n) +#define aligned_alloc(a,n) mi_aligned_alloc(a,n) +#define posix_memalign(p,a,n) mi_posix_memalign(p,a,n) +#define _posix_memalign(p,a,n) mi_posix_memalign(p,a,n) + +// Microsoft aligned variants +#define _aligned_malloc(n,a) mi_malloc_aligned(n,a) +#define _aligned_realloc(p,n,a) mi_realloc_aligned(p,n,a) +#define _aligned_recalloc(p,s,n,a) mi_aligned_recalloc(p,s,n,a) +#define _aligned_msize(p,a,o) mi_usable_size(p) +#define _aligned_free(p) mi_free(p) +#define _aligned_offset_malloc(n,a,o) mi_malloc_aligned_at(n,a,o) +#define _aligned_offset_realloc(p,n,a,o) mi_realloc_aligned_at(p,n,a,o) +#define _aligned_offset_recalloc(p,s,n,a,o) mi_recalloc_aligned_at(p,s,n,a,o) + +#endif // MIMALLOC_OVERRIDE_H diff --git a/kotlin-native/runtime/src/mimalloc/c/include/mimalloc-types.h b/kotlin-native/runtime/src/mimalloc/c/include/mimalloc-types.h new file mode 100644 index 00000000000..511271c56e8 --- /dev/null +++ b/kotlin-native/runtime/src/mimalloc/c/include/mimalloc-types.h @@ -0,0 +1,502 @@ +/* ---------------------------------------------------------------------------- +Copyright (c) 2018, Microsoft Research, Daan Leijen +This is free software; you can redistribute it and/or modify it under the +terms of the MIT license. A copy of the license can be found in the file +"licenses/third_party/mimalloc_LICENSE.txt" at the root of this distribution. +-----------------------------------------------------------------------------*/ +// Copyright 2019-2020 JetBrains s.r.o. + +#pragma once +#ifndef MIMALLOC_TYPES_H +#define MIMALLOC_TYPES_H + +#include // ptrdiff_t +#include // uintptr_t, uint16_t, etc +#include // _Atomic + +#ifdef _MSC_VER +#pragma warning(disable:4214) // bitfield is not int +#endif + +// Minimal alignment necessary. On most platforms 16 bytes are needed +// due to SSE registers for example. This must be at least `MI_INTPTR_SIZE` +#ifndef MI_MAX_ALIGN_SIZE +#define MI_MAX_ALIGN_SIZE 16 // sizeof(max_align_t) +#endif + +// ------------------------------------------------------ +// Variants +// ------------------------------------------------------ + +// Define NDEBUG in the release version to disable assertions. +#if KONAN_MI_MALLOC + #define NDEBUG +#endif // KONAN_MI_MALLOC + +// Define MI_STAT as 1 to maintain statistics; set it to 2 to have detailed statistics (but costs some performance). +// #define MI_STAT 1 + +// Define MI_SECURE to enable security mitigations +// #define MI_SECURE 1 // guard page around metadata +// #define MI_SECURE 2 // guard page around each mimalloc page +// #define MI_SECURE 3 // encode free lists (detect corrupted free list (buffer overflow), and invalid pointer free) +// #define MI_SECURE 4 // checks for double free. (may be more expensive) + +#if !defined(MI_SECURE) +#define MI_SECURE 0 +#endif + +// Define MI_DEBUG for debug mode +// #define MI_DEBUG 1 // basic assertion checks and statistics, check double free, corrupted free list, and invalid pointer free. +// #define MI_DEBUG 2 // + internal assertion checks +// #define MI_DEBUG 3 // + extensive internal invariant checking (cmake -DMI_DEBUG_FULL=ON) +#if !defined(MI_DEBUG) +#if !defined(NDEBUG) || defined(_DEBUG) +#define MI_DEBUG 2 +#else +#define MI_DEBUG 0 +#endif +#endif + +// Reserve extra padding at the end of each block to be more resilient against heap block overflows. +// The padding can detect byte-precise buffer overflow on free. +#if !defined(MI_PADDING) && (MI_DEBUG>=1) +#define MI_PADDING 1 +#endif + + +// Encoded free lists allow detection of corrupted free lists +// and can detect buffer overflows, modify after free, and double `free`s. +#if (MI_SECURE>=3 || MI_DEBUG>=1 || MI_PADDING > 0) +#define MI_ENCODE_FREELIST 1 +#endif + +// ------------------------------------------------------ +// Platform specific values +// ------------------------------------------------------ + +// ------------------------------------------------------ +// Size of a pointer. +// We assume that `sizeof(void*)==sizeof(intptr_t)` +// and it holds for all platforms we know of. +// +// However, the C standard only requires that: +// p == (void*)((intptr_t)p)) +// but we also need: +// i == (intptr_t)((void*)i) +// or otherwise one might define an intptr_t type that is larger than a pointer... +// ------------------------------------------------------ + +#if INTPTR_MAX == 9223372036854775807LL +# define MI_INTPTR_SHIFT (3) +#elif INTPTR_MAX == 2147483647LL +# define MI_INTPTR_SHIFT (2) +#else +#error platform must be 32 or 64 bits +#endif + +#define MI_INTPTR_SIZE (1<= 655360) +#error "define more bins" +#endif + +// Used as a special value to encode block sizes in 32 bits. +#define MI_HUGE_BLOCK_SIZE ((uint32_t)MI_HUGE_OBJ_SIZE_MAX) + +// The free lists use encoded next fields +// (Only actually encodes when MI_ENCODED_FREELIST is defined.) +typedef uintptr_t mi_encoded_t; + +// free lists contain blocks +typedef struct mi_block_s { + mi_encoded_t next; +} mi_block_t; + + +// The delayed flags are used for efficient multi-threaded free-ing +typedef enum mi_delayed_e { + MI_USE_DELAYED_FREE = 0, // push on the owning heap thread delayed list + MI_DELAYED_FREEING = 1, // temporary: another thread is accessing the owning heap + MI_NO_DELAYED_FREE = 2, // optimize: push on page local thread free queue if another block is already in the heap thread delayed free list + MI_NEVER_DELAYED_FREE = 3 // sticky, only resets on page reclaim +} mi_delayed_t; + + +// The `in_full` and `has_aligned` page flags are put in a union to efficiently +// test if both are false (`full_aligned == 0`) in the `mi_free` routine. +#if !MI_TSAN +typedef union mi_page_flags_s { + uint8_t full_aligned; + struct { + uint8_t in_full : 1; + uint8_t has_aligned : 1; + } x; +} mi_page_flags_t; +#else +// under thread sanitizer, use a byte for each flag to suppress warning, issue #130 +typedef union mi_page_flags_s { + uint16_t full_aligned; + struct { + uint8_t in_full; + uint8_t has_aligned; + } x; +} mi_page_flags_t; +#endif + +// Thread free list. +// We use the bottom 2 bits of the pointer for mi_delayed_t flags +typedef uintptr_t mi_thread_free_t; + +// A page contains blocks of one specific size (`block_size`). +// Each page has three list of free blocks: +// `free` for blocks that can be allocated, +// `local_free` for freed blocks that are not yet available to `mi_malloc` +// `thread_free` for freed blocks by other threads +// The `local_free` and `thread_free` lists are migrated to the `free` list +// when it is exhausted. The separate `local_free` list is necessary to +// implement a monotonic heartbeat. The `thread_free` list is needed for +// avoiding atomic operations in the common case. +// +// +// `used - |thread_free|` == actual blocks that are in use (alive) +// `used - |thread_free| + |free| + |local_free| == capacity` +// +// We don't count `freed` (as |free|) but use `used` to reduce +// the number of memory accesses in the `mi_page_all_free` function(s). +// +// Notes: +// - Access is optimized for `mi_free` and `mi_page_alloc` (in `alloc.c`) +// - Using `uint16_t` does not seem to slow things down +// - The size is 8 words on 64-bit which helps the page index calculations +// (and 10 words on 32-bit, and encoded free lists add 2 words. Sizes 10 +// and 12 are still good for address calculation) +// - To limit the structure size, the `xblock_size` is 32-bits only; for +// blocks > MI_HUGE_BLOCK_SIZE the size is determined from the segment page size +// - `thread_free` uses the bottom bits as a delayed-free flags to optimize +// concurrent frees where only the first concurrent free adds to the owning +// heap `thread_delayed_free` list (see `alloc.c:mi_free_block_mt`). +// The invariant is that no-delayed-free is only set if there is +// at least one block that will be added, or as already been added, to +// the owning heap `thread_delayed_free` list. This guarantees that pages +// will be freed correctly even if only other threads free blocks. +typedef struct mi_page_s { + // "owned" by the segment + uint8_t segment_idx; // index in the segment `pages` array, `page == &segment->pages[page->segment_idx]` + uint8_t segment_in_use:1; // `true` if the segment allocated this page + uint8_t is_reset:1; // `true` if the page memory was reset + uint8_t is_committed:1; // `true` if the page virtual memory is committed + uint8_t is_zero_init:1; // `true` if the page was zero initialized + + // layout like this to optimize access in `mi_malloc` and `mi_free` + uint16_t capacity; // number of blocks committed, must be the first field, see `segment.c:page_clear` + uint16_t reserved; // number of blocks reserved in memory + mi_page_flags_t flags; // `in_full` and `has_aligned` flags (8 bits) + uint8_t is_zero:1; // `true` if the blocks in the free list are zero initialized + uint8_t retire_expire:7; // expiration count for retired blocks + + mi_block_t* free; // list of available free blocks (`malloc` allocates from this list) + #ifdef MI_ENCODE_FREELIST + uintptr_t keys[2]; // two random keys to encode the free lists (see `_mi_block_next`) + #endif + uint32_t used; // number of blocks in use (including blocks in `local_free` and `thread_free`) + uint32_t xblock_size; // size available in each block (always `>0`) + + mi_block_t* local_free; // list of deferred free blocks by this thread (migrates to `free`) + _Atomic(mi_thread_free_t) xthread_free; // list of deferred free blocks freed by other threads + _Atomic(uintptr_t) xheap; + + struct mi_page_s* next; // next page owned by this thread with the same `block_size` + struct mi_page_s* prev; // previous page owned by this thread with the same `block_size` +} mi_page_t; + + + +typedef enum mi_page_kind_e { + MI_PAGE_SMALL, // small blocks go into 64kb pages inside a segment + MI_PAGE_MEDIUM, // medium blocks go into 512kb pages inside a segment + MI_PAGE_LARGE, // larger blocks go into a single page spanning a whole segment + MI_PAGE_HUGE // huge blocks (>512kb) are put into a single page in a segment of the exact size (but still 2mb aligned) +} mi_page_kind_t; + +// Segments are large allocated memory blocks (2mb on 64 bit) from +// the OS. Inside segments we allocated fixed size _pages_ that +// contain blocks. +typedef struct mi_segment_s { + // memory fields + size_t memid; // id for the os-level memory manager + bool mem_is_fixed; // `true` if we cannot decommit/reset/protect in this memory (i.e. when allocated using large OS pages) + bool mem_is_committed; // `true` if the whole segment is eagerly committed + + // segment fields + _Atomic(struct mi_segment_s*) abandoned_next; + struct mi_segment_s* next; // must be the first segment field after abandoned_next -- see `segment.c:segment_init` + struct mi_segment_s* prev; + + size_t abandoned; // abandoned pages (i.e. the original owning thread stopped) (`abandoned <= used`) + size_t abandoned_visits; // count how often this segment is visited in the abandoned list (to force reclaim it it is too long) + + size_t used; // count of pages in use (`used <= capacity`) + size_t capacity; // count of available pages (`#free + used`) + size_t segment_size; // for huge pages this may be different from `MI_SEGMENT_SIZE` + size_t segment_info_size;// space we are using from the first page for segment meta-data and possible guard pages. + uintptr_t cookie; // verify addresses in secure mode: `_mi_ptr_cookie(segment) == segment->cookie` + + // layout like this to optimize access in `mi_free` + size_t page_shift; // `1 << page_shift` == the page sizes == `page->block_size * page->reserved` (unless the first page, then `-segment_info_size`). + _Atomic(uintptr_t) thread_id; // unique id of the thread owning this segment + mi_page_kind_t page_kind; // kind of pages: small, large, or huge + mi_page_t pages[1]; // up to `MI_SMALL_PAGES_PER_SEGMENT` pages +} mi_segment_t; + + +// ------------------------------------------------------ +// Heaps +// Provide first-class heaps to allocate from. +// A heap just owns a set of pages for allocation and +// can only be allocate/reallocate from the thread that created it. +// Freeing blocks can be done from any thread though. +// Per thread, the segments are shared among its heaps. +// Per thread, there is always a default heap that is +// used for allocation; it is initialized to statically +// point to an empty heap to avoid initialization checks +// in the fast path. +// ------------------------------------------------------ + +// Thread local data +typedef struct mi_tld_s mi_tld_t; + +// Pages of a certain block size are held in a queue. +typedef struct mi_page_queue_s { + mi_page_t* first; + mi_page_t* last; + size_t block_size; +} mi_page_queue_t; + +#define MI_BIN_FULL (MI_BIN_HUGE+1) + +// Random context +typedef struct mi_random_cxt_s { + uint32_t input[16]; + uint32_t output[16]; + int output_available; +} mi_random_ctx_t; + + +// In debug mode there is a padding stucture at the end of the blocks to check for buffer overflows +#if (MI_PADDING) +typedef struct mi_padding_s { + uint32_t canary; // encoded block value to check validity of the padding (in case of overflow) + uint32_t delta; // padding bytes before the block. (mi_usable_size(p) - delta == exact allocated bytes) +} mi_padding_t; +#define MI_PADDING_SIZE (sizeof(mi_padding_t)) +#define MI_PADDING_WSIZE ((MI_PADDING_SIZE + MI_INTPTR_SIZE - 1) / MI_INTPTR_SIZE) +#else +#define MI_PADDING_SIZE 0 +#define MI_PADDING_WSIZE 0 +#endif + +#define MI_PAGES_DIRECT (MI_SMALL_WSIZE_MAX + MI_PADDING_WSIZE + 1) + + +// A heap owns a set of pages. +struct mi_heap_s { + mi_tld_t* tld; + mi_page_t* pages_free_direct[MI_PAGES_DIRECT]; // optimize: array where every entry points a page with possibly free blocks in the corresponding queue for that size. + mi_page_queue_t pages[MI_BIN_FULL + 1]; // queue of pages for each size class (or "bin") + _Atomic(mi_block_t*) thread_delayed_free; + uintptr_t thread_id; // thread this heap belongs too + uintptr_t cookie; // random cookie to verify pointers (see `_mi_ptr_cookie`) + uintptr_t keys[2]; // two random keys used to encode the `thread_delayed_free` list + mi_random_ctx_t random; // random number context used for secure allocation + size_t page_count; // total number of pages in the `pages` queues. + size_t page_retired_min; // smallest retired index (retired pages are fully free, but still in the page queues) + size_t page_retired_max; // largest retired index into the `pages` array. + mi_heap_t* next; // list of heaps per thread + bool no_reclaim; // `true` if this heap should not reclaim abandoned pages +}; + + + +// ------------------------------------------------------ +// Debug +// ------------------------------------------------------ + +#define MI_DEBUG_UNINIT (0xD0) +#define MI_DEBUG_FREED (0xDF) +#define MI_DEBUG_PADDING (0xDE) + +#if (MI_DEBUG) +// use our own assertion to print without memory allocation +void _mi_assert_fail(const char* assertion, const char* fname, unsigned int line, const char* func ); +#define mi_assert(expr) ((expr) ? (void)0 : _mi_assert_fail(#expr,__FILE__,__LINE__,__func__)) +#else +#define mi_assert(x) +#endif + +#if (MI_DEBUG>1) +#define mi_assert_internal mi_assert +#else +#define mi_assert_internal(x) +#endif + +#if (MI_DEBUG>2) +#define mi_assert_expensive mi_assert +#else +#define mi_assert_expensive(x) +#endif + +// ------------------------------------------------------ +// Statistics +// ------------------------------------------------------ + +#ifndef MI_STAT +#if (MI_DEBUG>0) +#define MI_STAT 2 +#else +#define MI_STAT 0 +#endif +#endif + +typedef struct mi_stat_count_s { + int64_t allocated; + int64_t freed; + int64_t peak; + int64_t current; +} mi_stat_count_t; + +typedef struct mi_stat_counter_s { + int64_t total; + int64_t count; +} mi_stat_counter_t; + +typedef struct mi_stats_s { + mi_stat_count_t segments; + mi_stat_count_t pages; + mi_stat_count_t reserved; + mi_stat_count_t committed; + mi_stat_count_t reset; + mi_stat_count_t page_committed; + mi_stat_count_t segments_abandoned; + mi_stat_count_t pages_abandoned; + mi_stat_count_t threads; + mi_stat_count_t huge; + mi_stat_count_t giant; + mi_stat_count_t malloc; + mi_stat_count_t segments_cache; + mi_stat_counter_t pages_extended; + mi_stat_counter_t mmap_calls; + mi_stat_counter_t commit_calls; + mi_stat_counter_t page_no_retire; + mi_stat_counter_t searches; + mi_stat_counter_t huge_count; + mi_stat_counter_t giant_count; +#if MI_STAT>1 + mi_stat_count_t normal[MI_BIN_HUGE+1]; +#endif +} mi_stats_t; + + +void _mi_stat_increase(mi_stat_count_t* stat, size_t amount); +void _mi_stat_decrease(mi_stat_count_t* stat, size_t amount); +void _mi_stat_counter_increase(mi_stat_counter_t* stat, size_t amount); + +#if (MI_STAT) +#define mi_stat_increase(stat,amount) _mi_stat_increase( &(stat), amount) +#define mi_stat_decrease(stat,amount) _mi_stat_decrease( &(stat), amount) +#define mi_stat_counter_increase(stat,amount) _mi_stat_counter_increase( &(stat), amount) +#else +#define mi_stat_increase(stat,amount) (void)0 +#define mi_stat_decrease(stat,amount) (void)0 +#define mi_stat_counter_increase(stat,amount) (void)0 +#endif + +#define mi_heap_stat_increase(heap,stat,amount) mi_stat_increase( (heap)->tld->stats.stat, amount) +#define mi_heap_stat_decrease(heap,stat,amount) mi_stat_decrease( (heap)->tld->stats.stat, amount) + +// ------------------------------------------------------ +// Thread Local data +// ------------------------------------------------------ + +typedef int64_t mi_msecs_t; + +// Queue of segments +typedef struct mi_segment_queue_s { + mi_segment_t* first; + mi_segment_t* last; +} mi_segment_queue_t; + +// OS thread local data +typedef struct mi_os_tld_s { + size_t region_idx; // start point for next allocation + mi_stats_t* stats; // points to tld stats +} mi_os_tld_t; + +// Segments thread local data +typedef struct mi_segments_tld_s { + mi_segment_queue_t small_free; // queue of segments with free small pages + mi_segment_queue_t medium_free; // queue of segments with free medium pages + mi_page_queue_t pages_reset; // queue of freed pages that can be reset + size_t count; // current number of segments; + size_t peak_count; // peak number of segments + size_t current_size; // current size of all segments + size_t peak_size; // peak size of all segments + size_t cache_count; // number of segments in the cache + size_t cache_size; // total size of all segments in the cache + mi_segment_t* cache; // (small) cache of segments + mi_stats_t* stats; // points to tld stats + mi_os_tld_t* os; // points to os stats +} mi_segments_tld_t; + +// Thread local data +struct mi_tld_s { + unsigned long long heartbeat; // monotonic heartbeat count + bool recurse; // true if deferred was called; used to prevent infinite recursion. + mi_heap_t* heap_backing; // backing heap of this thread (cannot be deleted) + mi_heap_t* heaps; // list of heaps in this thread (so we can abandon all when the thread terminates) + mi_segments_tld_t segments; // segment tld + mi_os_tld_t os; // os tld + mi_stats_t stats; // statistics +}; + +#endif diff --git a/kotlin-native/runtime/src/mimalloc/c/include/mimalloc.h b/kotlin-native/runtime/src/mimalloc/c/include/mimalloc.h new file mode 100644 index 00000000000..63c338a8e40 --- /dev/null +++ b/kotlin-native/runtime/src/mimalloc/c/include/mimalloc.h @@ -0,0 +1,429 @@ +/* ---------------------------------------------------------------------------- +Copyright (c) 2018-2020, Microsoft Research, Daan Leijen +This is free software; you can redistribute it and/or modify it under the +terms of the MIT license. A copy of the license can be found in the file +"licenses/third_party/mimalloc_LICENSE.txt" at the root of this distribution. +-----------------------------------------------------------------------------*/ +#pragma once +#ifndef MIMALLOC_H +#define MIMALLOC_H + +#define MI_MALLOC_VERSION 167 // major + 2 digits minor + +// ------------------------------------------------------ +// Compiler specific attributes +// ------------------------------------------------------ + +#ifdef __cplusplus + #if (__cplusplus >= 201103L) || (_MSC_VER > 1900) // C++11 + #define mi_attr_noexcept noexcept + #else + #define mi_attr_noexcept throw() + #endif +#else + #define mi_attr_noexcept +#endif + +#if defined(__cplusplus) && (__cplusplus >= 201703) + #define mi_decl_nodiscard [[nodiscard]] +#elif (__GNUC__ >= 4) || defined(__clang__) // includes clang, icc, and clang-cl + #define mi_decl_nodiscard __attribute__((warn_unused_result)) +#elif (_MSC_VER >= 1700) + #define mi_decl_nodiscard _Check_return_ +#else + #define mi_decl_nodiscard +#endif + +#if defined(_MSC_VER) || defined(__MINGW32__) + #if !defined(MI_SHARED_LIB) + #define mi_decl_export + #elif defined(MI_SHARED_LIB_EXPORT) + #define mi_decl_export __declspec(dllexport) + #else + #define mi_decl_export __declspec(dllimport) + #endif + #if defined(__MINGW32__) + #define mi_decl_restrict + #define mi_attr_malloc __attribute__((malloc)) + #else + #if (_MSC_VER >= 1900) && !defined(__EDG__) + #define mi_decl_restrict __declspec(allocator) __declspec(restrict) + #else + #define mi_decl_restrict __declspec(restrict) + #endif + #define mi_attr_malloc + #endif + #define mi_cdecl __cdecl + #define mi_attr_alloc_size(s) + #define mi_attr_alloc_size2(s1,s2) + #define mi_attr_alloc_align(p) +#elif defined(__GNUC__) // includes clang and icc + #define mi_cdecl // leads to warnings... __attribute__((cdecl)) + #define mi_decl_export __attribute__((visibility("default"))) + #define mi_decl_restrict + #define mi_attr_malloc __attribute__((malloc)) + #if (defined(__clang_major__) && (__clang_major__ < 4)) || (__GNUC__ < 5) + #define mi_attr_alloc_size(s) + #define mi_attr_alloc_size2(s1,s2) + #define mi_attr_alloc_align(p) + #elif defined(__INTEL_COMPILER) + #define mi_attr_alloc_size(s) __attribute__((alloc_size(s))) + #define mi_attr_alloc_size2(s1,s2) __attribute__((alloc_size(s1,s2))) + #define mi_attr_alloc_align(p) + #else + #define mi_attr_alloc_size(s) __attribute__((alloc_size(s))) + #define mi_attr_alloc_size2(s1,s2) __attribute__((alloc_size(s1,s2))) + #define mi_attr_alloc_align(p) __attribute__((alloc_align(p))) + #endif +#else + #define mi_cdecl + #define mi_decl_export + #define mi_decl_restrict + #define mi_attr_malloc + #define mi_attr_alloc_size(s) + #define mi_attr_alloc_size2(s1,s2) + #define mi_attr_alloc_align(p) +#endif + +// ------------------------------------------------------ +// Includes +// ------------------------------------------------------ + +#include // size_t +#include // bool + +#ifdef __cplusplus +extern "C" { +#endif + +// ------------------------------------------------------ +// Standard malloc interface +// ------------------------------------------------------ + +mi_decl_nodiscard mi_decl_export mi_decl_restrict void* mi_malloc(size_t size) mi_attr_noexcept mi_attr_malloc mi_attr_alloc_size(1); +mi_decl_nodiscard mi_decl_export mi_decl_restrict void* mi_calloc(size_t count, size_t size) mi_attr_noexcept mi_attr_malloc mi_attr_alloc_size2(1,2); +mi_decl_nodiscard mi_decl_export void* mi_realloc(void* p, size_t newsize) mi_attr_noexcept mi_attr_alloc_size(2); +mi_decl_export void* mi_expand(void* p, size_t newsize) mi_attr_noexcept mi_attr_alloc_size(2); + +mi_decl_export void mi_free(void* p) mi_attr_noexcept; +mi_decl_nodiscard mi_decl_export mi_decl_restrict char* mi_strdup(const char* s) mi_attr_noexcept mi_attr_malloc; +mi_decl_nodiscard mi_decl_export mi_decl_restrict char* mi_strndup(const char* s, size_t n) mi_attr_noexcept mi_attr_malloc; +mi_decl_nodiscard mi_decl_export mi_decl_restrict char* mi_realpath(const char* fname, char* resolved_name) mi_attr_noexcept mi_attr_malloc; + +// ------------------------------------------------------ +// Extended functionality +// ------------------------------------------------------ +#define MI_SMALL_WSIZE_MAX (128) +#define MI_SMALL_SIZE_MAX (MI_SMALL_WSIZE_MAX*sizeof(void*)) + +mi_decl_nodiscard mi_decl_export mi_decl_restrict void* mi_malloc_small(size_t size) mi_attr_noexcept mi_attr_malloc mi_attr_alloc_size(1); +mi_decl_nodiscard mi_decl_export mi_decl_restrict void* mi_zalloc_small(size_t size) mi_attr_noexcept mi_attr_malloc mi_attr_alloc_size(1); +mi_decl_nodiscard mi_decl_export mi_decl_restrict void* mi_zalloc(size_t size) mi_attr_noexcept mi_attr_malloc mi_attr_alloc_size(1); + +mi_decl_nodiscard mi_decl_export mi_decl_restrict void* mi_mallocn(size_t count, size_t size) mi_attr_noexcept mi_attr_malloc mi_attr_alloc_size2(1,2); +mi_decl_nodiscard mi_decl_export void* mi_reallocn(void* p, size_t count, size_t size) mi_attr_noexcept mi_attr_alloc_size2(2,3); +mi_decl_nodiscard mi_decl_export void* mi_reallocf(void* p, size_t newsize) mi_attr_noexcept mi_attr_alloc_size(2); + +mi_decl_nodiscard mi_decl_export size_t mi_usable_size(const void* p) mi_attr_noexcept; +mi_decl_nodiscard mi_decl_export size_t mi_good_size(size_t size) mi_attr_noexcept; + + +// ------------------------------------------------------ +// Internals +// ------------------------------------------------------ + +typedef void (mi_cdecl mi_deferred_free_fun)(bool force, unsigned long long heartbeat, void* arg); +mi_decl_export void mi_register_deferred_free(mi_deferred_free_fun* deferred_free, void* arg) mi_attr_noexcept; + +typedef void (mi_cdecl mi_output_fun)(const char* msg, void* arg); +mi_decl_export void mi_register_output(mi_output_fun* out, void* arg) mi_attr_noexcept; + +typedef void (mi_cdecl mi_error_fun)(int err, void* arg); +mi_decl_export void mi_register_error(mi_error_fun* fun, void* arg); + +mi_decl_export void mi_collect(bool force) mi_attr_noexcept; +mi_decl_export int mi_version(void) mi_attr_noexcept; +mi_decl_export void mi_stats_reset(void) mi_attr_noexcept; +mi_decl_export void mi_stats_merge(void) mi_attr_noexcept; +mi_decl_export void mi_stats_print(void* out) mi_attr_noexcept; // backward compatibility: `out` is ignored and should be NULL +mi_decl_export void mi_stats_print_out(mi_output_fun* out, void* arg) mi_attr_noexcept; + +mi_decl_export void mi_process_init(void) mi_attr_noexcept; +mi_decl_export void mi_thread_init(void) mi_attr_noexcept; +mi_decl_export void mi_thread_done(void) mi_attr_noexcept; +mi_decl_export void mi_thread_stats_print_out(mi_output_fun* out, void* arg) mi_attr_noexcept; + +mi_decl_export void mi_process_info(size_t* elapsed_msecs, size_t* user_msecs, size_t* system_msecs, + size_t* current_rss, size_t* peak_rss, + size_t* current_commit, size_t* peak_commit, size_t* page_faults) mi_attr_noexcept; + +// ------------------------------------------------------------------------------------- +// Aligned allocation +// Note that `alignment` always follows `size` for consistency with unaligned +// allocation, but unfortunately this differs from `posix_memalign` and `aligned_alloc`. +// ------------------------------------------------------------------------------------- + +mi_decl_nodiscard mi_decl_export mi_decl_restrict void* mi_malloc_aligned(size_t size, size_t alignment) mi_attr_noexcept mi_attr_malloc mi_attr_alloc_size(1) mi_attr_alloc_align(2); +mi_decl_nodiscard mi_decl_export mi_decl_restrict void* mi_malloc_aligned_at(size_t size, size_t alignment, size_t offset) mi_attr_noexcept mi_attr_malloc mi_attr_alloc_size(1); +mi_decl_nodiscard mi_decl_export mi_decl_restrict void* mi_zalloc_aligned(size_t size, size_t alignment) mi_attr_noexcept mi_attr_malloc mi_attr_alloc_size(1) mi_attr_alloc_align(2); +mi_decl_nodiscard mi_decl_export mi_decl_restrict void* mi_zalloc_aligned_at(size_t size, size_t alignment, size_t offset) mi_attr_noexcept mi_attr_malloc mi_attr_alloc_size(1); +mi_decl_nodiscard mi_decl_export mi_decl_restrict void* mi_calloc_aligned(size_t count, size_t size, size_t alignment) mi_attr_noexcept mi_attr_malloc mi_attr_alloc_size2(1,2) mi_attr_alloc_align(3); +mi_decl_nodiscard mi_decl_export mi_decl_restrict void* mi_calloc_aligned_at(size_t count, size_t size, size_t alignment, size_t offset) mi_attr_noexcept mi_attr_malloc mi_attr_alloc_size2(1,2); +mi_decl_nodiscard mi_decl_export void* mi_realloc_aligned(void* p, size_t newsize, size_t alignment) mi_attr_noexcept mi_attr_alloc_size(2) mi_attr_alloc_align(3); +mi_decl_nodiscard mi_decl_export void* mi_realloc_aligned_at(void* p, size_t newsize, size_t alignment, size_t offset) mi_attr_noexcept mi_attr_alloc_size(2); + + +// ------------------------------------------------------------------------------------- +// Heaps: first-class, but can only allocate from the same thread that created it. +// ------------------------------------------------------------------------------------- + +struct mi_heap_s; +typedef struct mi_heap_s mi_heap_t; + +mi_decl_nodiscard mi_decl_export mi_heap_t* mi_heap_new(void); +mi_decl_export void mi_heap_delete(mi_heap_t* heap); +mi_decl_export void mi_heap_destroy(mi_heap_t* heap); +mi_decl_export mi_heap_t* mi_heap_set_default(mi_heap_t* heap); +mi_decl_export mi_heap_t* mi_heap_get_default(void); +mi_decl_export mi_heap_t* mi_heap_get_backing(void); +mi_decl_export void mi_heap_collect(mi_heap_t* heap, bool force) mi_attr_noexcept; + +mi_decl_nodiscard mi_decl_export mi_decl_restrict void* mi_heap_malloc(mi_heap_t* heap, size_t size) mi_attr_noexcept mi_attr_malloc mi_attr_alloc_size(2); +mi_decl_nodiscard mi_decl_export mi_decl_restrict void* mi_heap_zalloc(mi_heap_t* heap, size_t size) mi_attr_noexcept mi_attr_malloc mi_attr_alloc_size(2); +mi_decl_nodiscard mi_decl_export mi_decl_restrict void* mi_heap_calloc(mi_heap_t* heap, size_t count, size_t size) mi_attr_noexcept mi_attr_malloc mi_attr_alloc_size2(2, 3); +mi_decl_nodiscard mi_decl_export mi_decl_restrict void* mi_heap_mallocn(mi_heap_t* heap, size_t count, size_t size) mi_attr_noexcept mi_attr_malloc mi_attr_alloc_size2(2, 3); +mi_decl_nodiscard mi_decl_export mi_decl_restrict void* mi_heap_malloc_small(mi_heap_t* heap, size_t size) mi_attr_noexcept mi_attr_malloc mi_attr_alloc_size(2); + +mi_decl_nodiscard mi_decl_export void* mi_heap_realloc(mi_heap_t* heap, void* p, size_t newsize) mi_attr_noexcept mi_attr_alloc_size(3); +mi_decl_nodiscard mi_decl_export void* mi_heap_reallocn(mi_heap_t* heap, void* p, size_t count, size_t size) mi_attr_noexcept mi_attr_alloc_size2(3,4); +mi_decl_nodiscard mi_decl_export void* mi_heap_reallocf(mi_heap_t* heap, void* p, size_t newsize) mi_attr_noexcept mi_attr_alloc_size(3); + +mi_decl_nodiscard mi_decl_export mi_decl_restrict char* mi_heap_strdup(mi_heap_t* heap, const char* s) mi_attr_noexcept mi_attr_malloc; +mi_decl_nodiscard mi_decl_export mi_decl_restrict char* mi_heap_strndup(mi_heap_t* heap, const char* s, size_t n) mi_attr_noexcept mi_attr_malloc; +mi_decl_nodiscard mi_decl_export mi_decl_restrict char* mi_heap_realpath(mi_heap_t* heap, const char* fname, char* resolved_name) mi_attr_noexcept mi_attr_malloc; + +mi_decl_nodiscard mi_decl_export mi_decl_restrict void* mi_heap_malloc_aligned(mi_heap_t* heap, size_t size, size_t alignment) mi_attr_noexcept mi_attr_malloc mi_attr_alloc_size(2) mi_attr_alloc_align(3); +mi_decl_nodiscard mi_decl_export mi_decl_restrict void* mi_heap_malloc_aligned_at(mi_heap_t* heap, size_t size, size_t alignment, size_t offset) mi_attr_noexcept mi_attr_malloc mi_attr_alloc_size(2); +mi_decl_nodiscard mi_decl_export mi_decl_restrict void* mi_heap_zalloc_aligned(mi_heap_t* heap, size_t size, size_t alignment) mi_attr_noexcept mi_attr_malloc mi_attr_alloc_size(2) mi_attr_alloc_align(3); +mi_decl_nodiscard mi_decl_export mi_decl_restrict void* mi_heap_zalloc_aligned_at(mi_heap_t* heap, size_t size, size_t alignment, size_t offset) mi_attr_noexcept mi_attr_malloc mi_attr_alloc_size(2); +mi_decl_nodiscard mi_decl_export mi_decl_restrict void* mi_heap_calloc_aligned(mi_heap_t* heap, size_t count, size_t size, size_t alignment) mi_attr_noexcept mi_attr_malloc mi_attr_alloc_size2(2, 3) mi_attr_alloc_align(4); +mi_decl_nodiscard mi_decl_export mi_decl_restrict void* mi_heap_calloc_aligned_at(mi_heap_t* heap, size_t count, size_t size, size_t alignment, size_t offset) mi_attr_noexcept mi_attr_malloc mi_attr_alloc_size2(2, 3); +mi_decl_nodiscard mi_decl_export void* mi_heap_realloc_aligned(mi_heap_t* heap, void* p, size_t newsize, size_t alignment) mi_attr_noexcept mi_attr_alloc_size(3) mi_attr_alloc_align(4); +mi_decl_nodiscard mi_decl_export void* mi_heap_realloc_aligned_at(mi_heap_t* heap, void* p, size_t newsize, size_t alignment, size_t offset) mi_attr_noexcept mi_attr_alloc_size(3); + + +// -------------------------------------------------------------------------------- +// Zero initialized re-allocation. +// Only valid on memory that was originally allocated with zero initialization too. +// e.g. `mi_calloc`, `mi_zalloc`, `mi_zalloc_aligned` etc. +// see +// -------------------------------------------------------------------------------- + +mi_decl_nodiscard mi_decl_export void* mi_rezalloc(void* p, size_t newsize) mi_attr_noexcept mi_attr_alloc_size(2); +mi_decl_nodiscard mi_decl_export void* mi_recalloc(void* p, size_t newcount, size_t size) mi_attr_noexcept mi_attr_alloc_size2(2,3); + +mi_decl_nodiscard mi_decl_export void* mi_rezalloc_aligned(void* p, size_t newsize, size_t alignment) mi_attr_noexcept mi_attr_alloc_size(2) mi_attr_alloc_align(3); +mi_decl_nodiscard mi_decl_export void* mi_rezalloc_aligned_at(void* p, size_t newsize, size_t alignment, size_t offset) mi_attr_noexcept mi_attr_alloc_size(2); +mi_decl_nodiscard mi_decl_export void* mi_recalloc_aligned(void* p, size_t newcount, size_t size, size_t alignment) mi_attr_noexcept mi_attr_alloc_size2(2,3) mi_attr_alloc_align(4); +mi_decl_nodiscard mi_decl_export void* mi_recalloc_aligned_at(void* p, size_t newcount, size_t size, size_t alignment, size_t offset) mi_attr_noexcept mi_attr_alloc_size2(2,3); + +mi_decl_nodiscard mi_decl_export void* mi_heap_rezalloc(mi_heap_t* heap, void* p, size_t newsize) mi_attr_noexcept mi_attr_alloc_size(3); +mi_decl_nodiscard mi_decl_export void* mi_heap_recalloc(mi_heap_t* heap, void* p, size_t newcount, size_t size) mi_attr_noexcept mi_attr_alloc_size2(3,4); + +mi_decl_nodiscard mi_decl_export void* mi_heap_rezalloc_aligned(mi_heap_t* heap, void* p, size_t newsize, size_t alignment) mi_attr_noexcept mi_attr_alloc_size(3) mi_attr_alloc_align(4); +mi_decl_nodiscard mi_decl_export void* mi_heap_rezalloc_aligned_at(mi_heap_t* heap, void* p, size_t newsize, size_t alignment, size_t offset) mi_attr_noexcept mi_attr_alloc_size(3); +mi_decl_nodiscard mi_decl_export void* mi_heap_recalloc_aligned(mi_heap_t* heap, void* p, size_t newcount, size_t size, size_t alignment) mi_attr_noexcept mi_attr_alloc_size2(3,4) mi_attr_alloc_align(5); +mi_decl_nodiscard mi_decl_export void* mi_heap_recalloc_aligned_at(mi_heap_t* heap, void* p, size_t newcount, size_t size, size_t alignment, size_t offset) mi_attr_noexcept mi_attr_alloc_size2(3,4); + + +// ------------------------------------------------------ +// Analysis +// ------------------------------------------------------ + +mi_decl_export bool mi_heap_contains_block(mi_heap_t* heap, const void* p); +mi_decl_export bool mi_heap_check_owned(mi_heap_t* heap, const void* p); +mi_decl_export bool mi_check_owned(const void* p); + +// An area of heap space contains blocks of a single size. +typedef struct mi_heap_area_s { + void* blocks; // start of the area containing heap blocks + size_t reserved; // bytes reserved for this area (virtual) + size_t committed; // current available bytes for this area + size_t used; // bytes in use by allocated blocks + size_t block_size; // size in bytes of each block +} mi_heap_area_t; + +typedef bool (mi_cdecl mi_block_visit_fun)(const mi_heap_t* heap, const mi_heap_area_t* area, void* block, size_t block_size, void* arg); + +mi_decl_export bool mi_heap_visit_blocks(const mi_heap_t* heap, bool visit_all_blocks, mi_block_visit_fun* visitor, void* arg); + +// Experimental +mi_decl_nodiscard mi_decl_export bool mi_is_in_heap_region(const void* p) mi_attr_noexcept; +mi_decl_nodiscard mi_decl_export bool mi_is_redirected(void) mi_attr_noexcept; + +mi_decl_export int mi_reserve_huge_os_pages_interleave(size_t pages, size_t numa_nodes, size_t timeout_msecs) mi_attr_noexcept; +mi_decl_export int mi_reserve_huge_os_pages_at(size_t pages, int numa_node, size_t timeout_msecs) mi_attr_noexcept; + +// deprecated +mi_decl_export int mi_reserve_huge_os_pages(size_t pages, double max_secs, size_t* pages_reserved) mi_attr_noexcept; + + +// ------------------------------------------------------ +// Convenience +// ------------------------------------------------------ + +#define mi_malloc_tp(tp) ((tp*)mi_malloc(sizeof(tp))) +#define mi_zalloc_tp(tp) ((tp*)mi_zalloc(sizeof(tp))) +#define mi_calloc_tp(tp,n) ((tp*)mi_calloc(n,sizeof(tp))) +#define mi_mallocn_tp(tp,n) ((tp*)mi_mallocn(n,sizeof(tp))) +#define mi_reallocn_tp(p,tp,n) ((tp*)mi_reallocn(p,n,sizeof(tp))) +#define mi_recalloc_tp(p,tp,n) ((tp*)mi_recalloc(p,n,sizeof(tp))) + +#define mi_heap_malloc_tp(hp,tp) ((tp*)mi_heap_malloc(hp,sizeof(tp))) +#define mi_heap_zalloc_tp(hp,tp) ((tp*)mi_heap_zalloc(hp,sizeof(tp))) +#define mi_heap_calloc_tp(hp,tp,n) ((tp*)mi_heap_calloc(hp,n,sizeof(tp))) +#define mi_heap_mallocn_tp(hp,tp,n) ((tp*)mi_heap_mallocn(hp,n,sizeof(tp))) +#define mi_heap_reallocn_tp(hp,p,tp,n) ((tp*)mi_heap_reallocn(hp,p,n,sizeof(tp))) +#define mi_heap_recalloc_tp(hp,p,tp,n) ((tp*)mi_heap_recalloc(hp,p,n,sizeof(tp))) + + +// ------------------------------------------------------ +// Options, all `false` by default +// ------------------------------------------------------ + +typedef enum mi_option_e { + // stable options + mi_option_show_errors, + mi_option_show_stats, + mi_option_verbose, + // the following options are experimental + mi_option_eager_commit, + mi_option_eager_region_commit, + mi_option_reset_decommits, + mi_option_large_os_pages, // implies eager commit + mi_option_reserve_huge_os_pages, + mi_option_segment_cache, + mi_option_page_reset, + mi_option_abandoned_page_reset, + mi_option_segment_reset, + mi_option_eager_commit_delay, + mi_option_reset_delay, + mi_option_use_numa_nodes, + mi_option_os_tag, + mi_option_max_errors, + _mi_option_last +} mi_option_t; + + +mi_decl_nodiscard mi_decl_export bool mi_option_is_enabled(mi_option_t option); +mi_decl_export void mi_option_enable(mi_option_t option); +mi_decl_export void mi_option_disable(mi_option_t option); +mi_decl_export void mi_option_set_enabled(mi_option_t option, bool enable); +mi_decl_export void mi_option_set_enabled_default(mi_option_t option, bool enable); + +mi_decl_nodiscard mi_decl_export long mi_option_get(mi_option_t option); +mi_decl_export void mi_option_set(mi_option_t option, long value); +mi_decl_export void mi_option_set_default(mi_option_t option, long value); + + +// ------------------------------------------------------------------------------------------------------- +// "mi" prefixed implementations of various posix, Unix, Windows, and C++ allocation functions. +// (This can be convenient when providing overrides of these functions as done in `mimalloc-override.h`.) +// note: we use `mi_cfree` as "checked free" and it checks if the pointer is in our heap before free-ing. +// ------------------------------------------------------------------------------------------------------- + +mi_decl_export void mi_cfree(void* p) mi_attr_noexcept; +mi_decl_export void* mi__expand(void* p, size_t newsize) mi_attr_noexcept; +mi_decl_nodiscard mi_decl_export size_t mi_malloc_size(const void* p) mi_attr_noexcept; +mi_decl_nodiscard mi_decl_export size_t mi_malloc_usable_size(const void *p) mi_attr_noexcept; + +mi_decl_export int mi_posix_memalign(void** p, size_t alignment, size_t size) mi_attr_noexcept; +mi_decl_nodiscard mi_decl_export mi_decl_restrict void* mi_memalign(size_t alignment, size_t size) mi_attr_noexcept mi_attr_malloc mi_attr_alloc_size(2) mi_attr_alloc_align(1); +mi_decl_nodiscard mi_decl_export mi_decl_restrict void* mi_valloc(size_t size) mi_attr_noexcept mi_attr_malloc mi_attr_alloc_size(1); +mi_decl_nodiscard mi_decl_export mi_decl_restrict void* mi_pvalloc(size_t size) mi_attr_noexcept mi_attr_malloc mi_attr_alloc_size(1); +mi_decl_nodiscard mi_decl_export mi_decl_restrict void* mi_aligned_alloc(size_t alignment, size_t size) mi_attr_noexcept mi_attr_malloc mi_attr_alloc_size(2) mi_attr_alloc_align(1); + +mi_decl_nodiscard mi_decl_export void* mi_reallocarray(void* p, size_t count, size_t size) mi_attr_noexcept mi_attr_alloc_size2(2,3); +mi_decl_nodiscard mi_decl_export void* mi_aligned_recalloc(void* p, size_t newcount, size_t size, size_t alignment) mi_attr_noexcept; +mi_decl_nodiscard mi_decl_export void* mi_aligned_offset_recalloc(void* p, size_t newcount, size_t size, size_t alignment, size_t offset) mi_attr_noexcept; + +mi_decl_nodiscard mi_decl_export mi_decl_restrict unsigned short* mi_wcsdup(const unsigned short* s) mi_attr_noexcept mi_attr_malloc; +mi_decl_nodiscard mi_decl_export mi_decl_restrict unsigned char* mi_mbsdup(const unsigned char* s) mi_attr_noexcept mi_attr_malloc; +mi_decl_export int mi_dupenv_s(char** buf, size_t* size, const char* name) mi_attr_noexcept; +mi_decl_export int mi_wdupenv_s(unsigned short** buf, size_t* size, const unsigned short* name) mi_attr_noexcept; + +mi_decl_export void mi_free_size(void* p, size_t size) mi_attr_noexcept; +mi_decl_export void mi_free_size_aligned(void* p, size_t size, size_t alignment) mi_attr_noexcept; +mi_decl_export void mi_free_aligned(void* p, size_t alignment) mi_attr_noexcept; + +// The `mi_new` wrappers implement C++ semantics on out-of-memory instead of directly returning `NULL`. +// (and call `std::get_new_handler` and potentially raise a `std::bad_alloc` exception). +mi_decl_nodiscard mi_decl_export mi_decl_restrict void* mi_new(size_t size) mi_attr_malloc mi_attr_alloc_size(1); +mi_decl_nodiscard mi_decl_export mi_decl_restrict void* mi_new_aligned(size_t size, size_t alignment) mi_attr_malloc mi_attr_alloc_size(1) mi_attr_alloc_align(2); +mi_decl_nodiscard mi_decl_export mi_decl_restrict void* mi_new_nothrow(size_t size) mi_attr_noexcept mi_attr_malloc mi_attr_alloc_size(1); +mi_decl_nodiscard mi_decl_export mi_decl_restrict void* mi_new_aligned_nothrow(size_t size, size_t alignment) mi_attr_noexcept mi_attr_malloc mi_attr_alloc_size(1) mi_attr_alloc_align(2); +mi_decl_nodiscard mi_decl_export mi_decl_restrict void* mi_new_n(size_t count, size_t size) mi_attr_malloc mi_attr_alloc_size2(1, 2); +mi_decl_nodiscard mi_decl_export void* mi_new_realloc(void* p, size_t newsize) mi_attr_alloc_size(2); +mi_decl_nodiscard mi_decl_export void* mi_new_reallocn(void* p, size_t newcount, size_t size) mi_attr_alloc_size2(2, 3); + +#ifdef __cplusplus +} +#endif + +// --------------------------------------------------------------------------------------------- +// Implement the C++ std::allocator interface for use in STL containers. +// (note: see `mimalloc-new-delete.h` for overriding the new/delete operators globally) +// --------------------------------------------------------------------------------------------- +#ifdef __cplusplus + +#include // PTRDIFF_MAX +#if (__cplusplus >= 201103L) || (_MSC_VER > 1900) // C++11 +#include // std::true_type +#include // std::forward +#endif + +template struct mi_stl_allocator { + typedef T value_type; + typedef std::size_t size_type; + typedef std::ptrdiff_t difference_type; + typedef value_type& reference; + typedef value_type const& const_reference; + typedef value_type* pointer; + typedef value_type const* const_pointer; + template struct rebind { typedef mi_stl_allocator other; }; + + mi_stl_allocator() mi_attr_noexcept = default; + mi_stl_allocator(const mi_stl_allocator&) mi_attr_noexcept = default; + template mi_stl_allocator(const mi_stl_allocator&) mi_attr_noexcept { } + mi_stl_allocator select_on_container_copy_construction() const { return *this; } + void deallocate(T* p, size_type) { mi_free(p); } + + #if (__cplusplus >= 201703L) // C++17 + mi_decl_nodiscard T* allocate(size_type count) { return static_cast(mi_new_n(count, sizeof(T))); } + mi_decl_nodiscard T* allocate(size_type count, const void*) { return allocate(count); } + #else + mi_decl_nodiscard pointer allocate(size_type count, const void* = 0) { return static_cast(mi_new_n(count, sizeof(value_type))); } + #endif + + #if ((__cplusplus >= 201103L) || (_MSC_VER > 1900)) // C++11 + using propagate_on_container_copy_assignment = std::true_type; + using propagate_on_container_move_assignment = std::true_type; + using propagate_on_container_swap = std::true_type; + using is_always_equal = std::true_type; + template void construct(U* p, Args&& ...args) { ::new(p) U(std::forward(args)...); } + template void destroy(U* p) mi_attr_noexcept { p->~U(); } + #else + void construct(pointer p, value_type const& val) { ::new(p) value_type(val); } + void destroy(pointer p) { p->~value_type(); } + #endif + + size_type max_size() const mi_attr_noexcept { return (PTRDIFF_MAX/sizeof(value_type)); } + pointer address(reference x) const { return &x; } + const_pointer address(const_reference x) const { return &x; } +}; + +template bool operator==(const mi_stl_allocator& , const mi_stl_allocator& ) mi_attr_noexcept { return true; } +template bool operator!=(const mi_stl_allocator& , const mi_stl_allocator& ) mi_attr_noexcept { return false; } +#endif // __cplusplus + +#endif diff --git a/kotlin-native/runtime/src/mimalloc/c/init.c b/kotlin-native/runtime/src/mimalloc/c/init.c new file mode 100644 index 00000000000..176cd722e26 --- /dev/null +++ b/kotlin-native/runtime/src/mimalloc/c/init.c @@ -0,0 +1,563 @@ +/* ---------------------------------------------------------------------------- +Copyright (c) 2018, Microsoft Research, Daan Leijen +This is free software; you can redistribute it and/or modify it under the +terms of the MIT license. A copy of the license can be found in the file +"licenses/third_party/mimalloc_LICENSE.txt" at the root of this distribution. +-----------------------------------------------------------------------------*/ +#include "mimalloc.h" +#include "mimalloc-internal.h" + +#include // memcpy, memset +#include // atexit + +// Empty page used to initialize the small free pages array +const mi_page_t _mi_page_empty = { + 0, false, false, false, false, + 0, // capacity + 0, // reserved capacity + { 0 }, // flags + false, // is_zero + 0, // retire_expire + NULL, // free + #if MI_ENCODE_FREELIST + { 0, 0 }, + #endif + 0, // used + 0, // xblock_size + NULL, // local_free + ATOMIC_VAR_INIT(0), // xthread_free + ATOMIC_VAR_INIT(0), // xheap + NULL, NULL +}; + +#define MI_PAGE_EMPTY() ((mi_page_t*)&_mi_page_empty) + +#if (MI_PADDING>0) && (MI_INTPTR_SIZE >= 8) +#define MI_SMALL_PAGES_EMPTY { MI_INIT128(MI_PAGE_EMPTY), MI_PAGE_EMPTY(), MI_PAGE_EMPTY() } +#elif (MI_PADDING>0) +#define MI_SMALL_PAGES_EMPTY { MI_INIT128(MI_PAGE_EMPTY), MI_PAGE_EMPTY(), MI_PAGE_EMPTY(), MI_PAGE_EMPTY() } +#else +#define MI_SMALL_PAGES_EMPTY { MI_INIT128(MI_PAGE_EMPTY), MI_PAGE_EMPTY() } +#endif + + +// Empty page queues for every bin +#define QNULL(sz) { NULL, NULL, (sz)*sizeof(uintptr_t) } +#define MI_PAGE_QUEUES_EMPTY \ + { QNULL(1), \ + QNULL( 1), QNULL( 2), QNULL( 3), QNULL( 4), QNULL( 5), QNULL( 6), QNULL( 7), QNULL( 8), /* 8 */ \ + QNULL( 10), QNULL( 12), QNULL( 14), QNULL( 16), QNULL( 20), QNULL( 24), QNULL( 28), QNULL( 32), /* 16 */ \ + QNULL( 40), QNULL( 48), QNULL( 56), QNULL( 64), QNULL( 80), QNULL( 96), QNULL( 112), QNULL( 128), /* 24 */ \ + QNULL( 160), QNULL( 192), QNULL( 224), QNULL( 256), QNULL( 320), QNULL( 384), QNULL( 448), QNULL( 512), /* 32 */ \ + QNULL( 640), QNULL( 768), QNULL( 896), QNULL( 1024), QNULL( 1280), QNULL( 1536), QNULL( 1792), QNULL( 2048), /* 40 */ \ + QNULL( 2560), QNULL( 3072), QNULL( 3584), QNULL( 4096), QNULL( 5120), QNULL( 6144), QNULL( 7168), QNULL( 8192), /* 48 */ \ + QNULL( 10240), QNULL( 12288), QNULL( 14336), QNULL( 16384), QNULL( 20480), QNULL( 24576), QNULL( 28672), QNULL( 32768), /* 56 */ \ + QNULL( 40960), QNULL( 49152), QNULL( 57344), QNULL( 65536), QNULL( 81920), QNULL( 98304), QNULL(114688), QNULL(131072), /* 64 */ \ + QNULL(163840), QNULL(196608), QNULL(229376), QNULL(262144), QNULL(327680), QNULL(393216), QNULL(458752), QNULL(524288), /* 72 */ \ + QNULL(MI_LARGE_OBJ_WSIZE_MAX + 1 /* 655360, Huge queue */), \ + QNULL(MI_LARGE_OBJ_WSIZE_MAX + 2) /* Full queue */ } + +#define MI_STAT_COUNT_NULL() {0,0,0,0} + +// Empty statistics +#if MI_STAT>1 +#define MI_STAT_COUNT_END_NULL() , { MI_STAT_COUNT_NULL(), MI_INIT32(MI_STAT_COUNT_NULL) } +#else +#define MI_STAT_COUNT_END_NULL() +#endif + +#define MI_STATS_NULL \ + MI_STAT_COUNT_NULL(), MI_STAT_COUNT_NULL(), \ + MI_STAT_COUNT_NULL(), MI_STAT_COUNT_NULL(), \ + MI_STAT_COUNT_NULL(), MI_STAT_COUNT_NULL(), \ + MI_STAT_COUNT_NULL(), MI_STAT_COUNT_NULL(), \ + MI_STAT_COUNT_NULL(), MI_STAT_COUNT_NULL(), \ + MI_STAT_COUNT_NULL(), MI_STAT_COUNT_NULL(), \ + MI_STAT_COUNT_NULL(), \ + { 0, 0 }, { 0, 0 }, { 0, 0 }, \ + { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 } \ + MI_STAT_COUNT_END_NULL() + +// -------------------------------------------------------- +// Statically allocate an empty heap as the initial +// thread local value for the default heap, +// and statically allocate the backing heap for the main +// thread so it can function without doing any allocation +// itself (as accessing a thread local for the first time +// may lead to allocation itself on some platforms) +// -------------------------------------------------------- + +const mi_heap_t _mi_heap_empty = { + NULL, + MI_SMALL_PAGES_EMPTY, + MI_PAGE_QUEUES_EMPTY, + ATOMIC_VAR_INIT(NULL), + 0, // tid + 0, // cookie + { 0, 0 }, // keys + { {0}, {0}, 0 }, + 0, // page count + MI_BIN_FULL, 0, // page retired min/max + NULL, // next + false +}; + +// the thread-local default heap for allocation +mi_decl_thread mi_heap_t* _mi_heap_default = (mi_heap_t*)&_mi_heap_empty; + +extern mi_heap_t _mi_heap_main; + +static mi_tld_t tld_main = { + 0, false, + &_mi_heap_main, &_mi_heap_main, + { { NULL, NULL }, {NULL ,NULL}, {NULL ,NULL, 0}, + 0, 0, 0, 0, 0, 0, NULL, + &tld_main.stats, &tld_main.os + }, // segments + { 0, &tld_main.stats }, // os + { MI_STATS_NULL } // stats +}; + +mi_heap_t _mi_heap_main = { + &tld_main, + MI_SMALL_PAGES_EMPTY, + MI_PAGE_QUEUES_EMPTY, + ATOMIC_VAR_INIT(NULL), + 0, // thread id + 0, // initial cookie + { 0, 0 }, // the key of the main heap can be fixed (unlike page keys that need to be secure!) + { {0x846ca68b}, {0}, 0 }, // random + 0, // page count + MI_BIN_FULL, 0, // page retired min/max + NULL, // next heap + false // can reclaim +}; + +bool _mi_process_is_initialized = false; // set to `true` in `mi_process_init`. + +mi_stats_t _mi_stats_main = { MI_STATS_NULL }; + + +static void mi_heap_main_init(void) { + if (_mi_heap_main.cookie == 0) { + _mi_heap_main.thread_id = _mi_thread_id(); + _mi_heap_main.cookie = _os_random_weak((uintptr_t)&mi_heap_main_init); + _mi_random_init(&_mi_heap_main.random); + _mi_heap_main.keys[0] = _mi_heap_random_next(&_mi_heap_main); + _mi_heap_main.keys[1] = _mi_heap_random_next(&_mi_heap_main); + } +} + +mi_heap_t* _mi_heap_main_get(void) { + mi_heap_main_init(); + return &_mi_heap_main; +} + + +/* ----------------------------------------------------------- + Initialization and freeing of the thread local heaps +----------------------------------------------------------- */ + +// note: in x64 in release build `sizeof(mi_thread_data_t)` is under 4KiB (= OS page size). +typedef struct mi_thread_data_s { + mi_heap_t heap; // must come first due to cast in `_mi_heap_done` + mi_tld_t tld; +} mi_thread_data_t; + +// Initialize the thread local default heap, called from `mi_thread_init` +static bool _mi_heap_init(void) { + if (mi_heap_is_initialized(mi_get_default_heap())) return true; + if (_mi_is_main_thread()) { + // mi_assert_internal(_mi_heap_main.thread_id != 0); // can happen on freeBSD where alloc is called before any initialization + // the main heap is statically allocated + mi_heap_main_init(); + _mi_heap_set_default_direct(&_mi_heap_main); + //mi_assert_internal(_mi_heap_default->tld->heap_backing == mi_get_default_heap()); + } + else { + // use `_mi_os_alloc` to allocate directly from the OS + mi_thread_data_t* td = (mi_thread_data_t*)_mi_os_alloc(sizeof(mi_thread_data_t), &_mi_stats_main); // Todo: more efficient allocation? + if (td == NULL) { + // if this fails, try once more. (issue #257) + td = (mi_thread_data_t*)_mi_os_alloc(sizeof(mi_thread_data_t), &_mi_stats_main); + if (td == NULL) { + // really out of memory + _mi_error_message(ENOMEM, "unable to allocate thread local heap metadata (%zu bytes)\n", sizeof(mi_thread_data_t)); + return false; + } + } + // OS allocated so already zero initialized + mi_tld_t* tld = &td->tld; + mi_heap_t* heap = &td->heap; + memcpy(heap, &_mi_heap_empty, sizeof(*heap)); + heap->thread_id = _mi_thread_id(); + _mi_random_init(&heap->random); + heap->cookie = _mi_heap_random_next(heap) | 1; + heap->keys[0] = _mi_heap_random_next(heap); + heap->keys[1] = _mi_heap_random_next(heap); + heap->tld = tld; + tld->heap_backing = heap; + tld->heaps = heap; + tld->segments.stats = &tld->stats; + tld->segments.os = &tld->os; + tld->os.stats = &tld->stats; + _mi_heap_set_default_direct(heap); + } + return false; +} + +// Free the thread local default heap (called from `mi_thread_done`) +static bool _mi_heap_done(mi_heap_t* heap) { + if (!mi_heap_is_initialized(heap)) return true; + + // reset default heap + _mi_heap_set_default_direct(_mi_is_main_thread() ? &_mi_heap_main : (mi_heap_t*)&_mi_heap_empty); + + // switch to backing heap + heap = heap->tld->heap_backing; + if (!mi_heap_is_initialized(heap)) return false; + + // delete all non-backing heaps in this thread + mi_heap_t* curr = heap->tld->heaps; + while (curr != NULL) { + mi_heap_t* next = curr->next; // save `next` as `curr` will be freed + if (curr != heap) { + mi_assert_internal(!mi_heap_is_backing(curr)); + mi_heap_delete(curr); + } + curr = next; + } + mi_assert_internal(heap->tld->heaps == heap && heap->next == NULL); + mi_assert_internal(mi_heap_is_backing(heap)); + + // collect if not the main thread + if (heap != &_mi_heap_main) { + _mi_heap_collect_abandon(heap); + } + + // merge stats + _mi_stats_done(&heap->tld->stats); + + // free if not the main thread + if (heap != &_mi_heap_main) { + mi_assert_internal(heap->tld->segments.count == 0 || heap->thread_id != _mi_thread_id()); + _mi_os_free(heap, sizeof(mi_thread_data_t), &_mi_stats_main); + } +#if 0 + // never free the main thread even in debug mode; if a dll is linked statically with mimalloc, + // there may still be delete/free calls after the mi_fls_done is called. Issue #207 + else { + _mi_heap_destroy_pages(heap); + mi_assert_internal(heap->tld->heap_backing == &_mi_heap_main); + } +#endif + return false; +} + + + +// -------------------------------------------------------- +// Try to run `mi_thread_done()` automatically so any memory +// owned by the thread but not yet released can be abandoned +// and re-owned by another thread. +// +// 1. windows dynamic library: +// call from DllMain on DLL_THREAD_DETACH +// 2. windows static library: +// use `FlsAlloc` to call a destructor when the thread is done +// 3. unix, pthreads: +// use a pthread key to call a destructor when a pthread is done +// +// In the last two cases we also need to call `mi_process_init` +// to set up the thread local keys. +// -------------------------------------------------------- + +static void _mi_thread_done(mi_heap_t* default_heap); + +#ifdef __wasi__ +// no pthreads in the WebAssembly Standard Interface +#elif !defined(_WIN32) +#define MI_USE_PTHREADS +#endif + +#if defined(_WIN32) && defined(MI_SHARED_LIB) + // nothing to do as it is done in DllMain +#elif defined(_WIN32) && !defined(MI_SHARED_LIB) + // use thread local storage keys to detect thread ending + #include + #include + #if (_WIN32_WINNT < 0x600) // before Windows Vista + WINBASEAPI DWORD WINAPI FlsAlloc( _In_opt_ PFLS_CALLBACK_FUNCTION lpCallback ); + WINBASEAPI PVOID WINAPI FlsGetValue( _In_ DWORD dwFlsIndex ); + WINBASEAPI BOOL WINAPI FlsSetValue( _In_ DWORD dwFlsIndex, _In_opt_ PVOID lpFlsData ); + WINBASEAPI BOOL WINAPI FlsFree(_In_ DWORD dwFlsIndex); + #endif + static DWORD mi_fls_key = (DWORD)(-1); + static void NTAPI mi_fls_done(PVOID value) { + if (value!=NULL) _mi_thread_done((mi_heap_t*)value); + } +#elif defined(MI_USE_PTHREADS) + // use pthread local storage keys to detect thread ending + // (and used with MI_TLS_PTHREADS for the default heap) + #include + pthread_key_t _mi_heap_default_key = (pthread_key_t)(-1); + static void mi_pthread_done(void* value) { + if (value!=NULL) _mi_thread_done((mi_heap_t*)value); + } +#elif defined(__wasi__) +// no pthreads in the WebAssembly Standard Interface +#else + #pragma message("define a way to call mi_thread_done when a thread is done") +#endif + +// Set up handlers so `mi_thread_done` is called automatically +static void mi_process_setup_auto_thread_done(void) { + static bool tls_initialized = false; // fine if it races + if (tls_initialized) return; + tls_initialized = true; + #if defined(_WIN32) && defined(MI_SHARED_LIB) + // nothing to do as it is done in DllMain + #elif defined(_WIN32) && !defined(MI_SHARED_LIB) + mi_fls_key = FlsAlloc(&mi_fls_done); + #elif defined(MI_USE_PTHREADS) + mi_assert_internal(_mi_heap_default_key == (pthread_key_t)(-1)); + pthread_key_create(&_mi_heap_default_key, &mi_pthread_done); + #endif + _mi_heap_set_default_direct(&_mi_heap_main); +} + + +bool _mi_is_main_thread(void) { + return (_mi_heap_main.thread_id==0 || _mi_heap_main.thread_id == _mi_thread_id()); +} + +// This is called from the `mi_malloc_generic` +void mi_thread_init(void) mi_attr_noexcept +{ + // ensure our process has started already + mi_process_init(); + + // initialize the thread local default heap + // (this will call `_mi_heap_set_default_direct` and thus set the + // fiber/pthread key to a non-zero value, ensuring `_mi_thread_done` is called) + if (_mi_heap_init()) return; // returns true if already initialized + + _mi_stat_increase(&_mi_stats_main.threads, 1); + //_mi_verbose_message("thread init: 0x%zx\n", _mi_thread_id()); +} + +void mi_thread_done(void) mi_attr_noexcept { + _mi_thread_done(mi_get_default_heap()); +} + +static void _mi_thread_done(mi_heap_t* heap) { + _mi_stat_decrease(&_mi_stats_main.threads, 1); + + // check thread-id as on Windows shutdown with FLS the main (exit) thread may call this on thread-local heaps... + if (heap->thread_id != _mi_thread_id()) return; + + // abandon the thread local heap + if (_mi_heap_done(heap)) return; // returns true if already ran +} + +void _mi_heap_set_default_direct(mi_heap_t* heap) { + mi_assert_internal(heap != NULL); + #if defined(MI_TLS_SLOT) + mi_tls_slot_set(MI_TLS_SLOT,heap); + #elif defined(MI_TLS_PTHREAD_SLOT_OFS) + *mi_tls_pthread_heap_slot() = heap; + #elif defined(MI_TLS_PTHREAD) + // we use _mi_heap_default_key + #else + _mi_heap_default = heap; + #endif + + // ensure the default heap is passed to `_mi_thread_done` + // setting to a non-NULL value also ensures `mi_thread_done` is called. + #if defined(_WIN32) && defined(MI_SHARED_LIB) + // nothing to do as it is done in DllMain + #elif defined(_WIN32) && !defined(MI_SHARED_LIB) + mi_assert_internal(mi_fls_key != 0); + FlsSetValue(mi_fls_key, heap); + #elif defined(MI_USE_PTHREADS) + if (_mi_heap_default_key != (pthread_key_t)(-1)) { // can happen during recursive invocation on freeBSD + pthread_setspecific(_mi_heap_default_key, heap); + } + #endif +} + + +// -------------------------------------------------------- +// Run functions on process init/done, and thread init/done +// -------------------------------------------------------- +static void mi_process_done(void); + +static bool os_preloading = true; // true until this module is initialized +static bool mi_redirected = false; // true if malloc redirects to mi_malloc + +// Returns true if this module has not been initialized; Don't use C runtime routines until it returns false. +bool _mi_preloading(void) { + return os_preloading; +} + +bool mi_is_redirected(void) mi_attr_noexcept { + return mi_redirected; +} + +// Communicate with the redirection module on Windows +#if defined(_WIN32) && defined(MI_SHARED_LIB) +#ifdef __cplusplus +extern "C" { +#endif +mi_decl_export void _mi_redirect_entry(DWORD reason) { + // called on redirection; careful as this may be called before DllMain + if (reason == DLL_PROCESS_ATTACH) { + mi_redirected = true; + } + else if (reason == DLL_PROCESS_DETACH) { + mi_redirected = false; + } + else if (reason == DLL_THREAD_DETACH) { + mi_thread_done(); + } +} +__declspec(dllimport) bool mi_allocator_init(const char** message); +__declspec(dllimport) void mi_allocator_done(void); +#ifdef __cplusplus +} +#endif +#else +static bool mi_allocator_init(const char** message) { + if (message != NULL) *message = NULL; + return true; +} +static void mi_allocator_done(void) { + // nothing to do +} +#endif + +// Called once by the process loader +static void mi_process_load(void) { + mi_heap_main_init(); + #if defined(MI_TLS_RECURSE_GUARD) + volatile mi_heap_t* dummy = _mi_heap_default; // access TLS to allocate it before setting tls_initialized to true; + UNUSED(dummy); + #endif + os_preloading = false; + atexit(&mi_process_done); + _mi_options_init(); + mi_process_init(); + //mi_stats_reset();- + if (mi_redirected) _mi_verbose_message("malloc is redirected.\n"); + + // show message from the redirector (if present) + const char* msg = NULL; + mi_allocator_init(&msg); + if (msg != NULL && (mi_option_is_enabled(mi_option_verbose) || mi_option_is_enabled(mi_option_show_errors))) { + _mi_fputs(NULL,NULL,NULL,msg); + } +} + +// Initialize the process; called by thread_init or the process loader +void mi_process_init(void) mi_attr_noexcept { + // ensure we are called once + if (_mi_process_is_initialized) return; + _mi_process_is_initialized = true; + mi_process_setup_auto_thread_done(); + + _mi_verbose_message("process init: 0x%zx\n", _mi_thread_id()); + _mi_os_init(); + mi_heap_main_init(); + #if (MI_DEBUG) + _mi_verbose_message("debug level : %d\n", MI_DEBUG); + #endif + _mi_verbose_message("secure level: %d\n", MI_SECURE); + mi_thread_init(); + mi_stats_reset(); // only call stat reset *after* thread init (or the heap tld == NULL) + + if (mi_option_is_enabled(mi_option_reserve_huge_os_pages)) { + size_t pages = mi_option_get(mi_option_reserve_huge_os_pages); + mi_reserve_huge_os_pages_interleave(pages, 0, pages*500); + } +} + +// Called when the process is done (through `at_exit`) +static void mi_process_done(void) { + // only shutdown if we were initialized + if (!_mi_process_is_initialized) return; + // ensure we are called once + static bool process_done = false; + if (process_done) return; + process_done = true; + + #if defined(_WIN32) && !defined(MI_SHARED_LIB) + FlsSetValue(mi_fls_key, NULL); // don't call main-thread callback + FlsFree(mi_fls_key); // call thread-done on all threads to prevent dangling callback pointer if statically linked with a DLL; Issue #208 + #endif + + #if (MI_DEBUG != 0) || !defined(MI_SHARED_LIB) + // free all memory if possible on process exit. This is not needed for a stand-alone process + // but should be done if mimalloc is statically linked into another shared library which + // is repeatedly loaded/unloaded, see issue #281. + mi_collect(true /* force */ ); + #endif + + if (mi_option_is_enabled(mi_option_show_stats) || mi_option_is_enabled(mi_option_verbose)) { + mi_stats_print(NULL); + } + mi_allocator_done(); + _mi_verbose_message("process done: 0x%zx\n", _mi_heap_main.thread_id); + os_preloading = true; // don't call the C runtime anymore +} + + + +#if defined(_WIN32) && defined(MI_SHARED_LIB) + // Windows DLL: easy to hook into process_init and thread_done + __declspec(dllexport) BOOL WINAPI DllMain(HINSTANCE inst, DWORD reason, LPVOID reserved) { + UNUSED(reserved); + UNUSED(inst); + if (reason==DLL_PROCESS_ATTACH) { + mi_process_load(); + } + else if (reason==DLL_THREAD_DETACH) { + if (!mi_is_redirected()) mi_thread_done(); + } + return TRUE; + } + +#elif defined(__cplusplus) + // C++: use static initialization to detect process start + static bool _mi_process_init(void) { + mi_process_load(); + return (_mi_heap_main.thread_id != 0); + } + static bool mi_initialized = _mi_process_init(); + +#elif defined(__GNUC__) || defined(__clang__) + // GCC,Clang: use the constructor attribute + static void __attribute__((constructor)) _mi_process_init(void) { + mi_process_load(); + } + +#elif defined(_MSC_VER) + // MSVC: use data section magic for static libraries + // See + static int _mi_process_init(void) { + mi_process_load(); + return 0; + } + typedef int(*_crt_cb)(void); + #ifdef _M_X64 + __pragma(comment(linker, "/include:" "_mi_msvc_initu")) + #pragma section(".CRT$XIU", long, read) + #else + __pragma(comment(linker, "/include:" "__mi_msvc_initu")) + #endif + #pragma data_seg(".CRT$XIU") + _crt_cb _mi_msvc_initu[] = { &_mi_process_init }; + #pragma data_seg() + +#else +#pragma message("define a way to call mi_process_load on your platform") +#endif diff --git a/kotlin-native/runtime/src/mimalloc/c/options.c b/kotlin-native/runtime/src/mimalloc/c/options.c new file mode 100644 index 00000000000..b5c50d1b0ad --- /dev/null +++ b/kotlin-native/runtime/src/mimalloc/c/options.c @@ -0,0 +1,520 @@ +/* ---------------------------------------------------------------------------- +Copyright (c) 2018, Microsoft Research, Daan Leijen +This is free software; you can redistribute it and/or modify it under the +terms of the MIT license. A copy of the license can be found in the file +"licenses/third_party/mimalloc_LICENSE.txt" at the root of this distribution. +-----------------------------------------------------------------------------*/ +#include "mimalloc.h" +#include "mimalloc-internal.h" +#include "mimalloc-atomic.h" + +#include +#include // strtol +#include // strncpy, strncat, strlen, strstr +#include // toupper +#include + +#ifdef _MSC_VER +#pragma warning(disable:4996) // strncpy, strncat +#endif + + +static uintptr_t mi_max_error_count = 16; // stop outputting errors after this + +static void mi_add_stderr_output(); + +int mi_version(void) mi_attr_noexcept { + return MI_MALLOC_VERSION; +} + +#ifdef _WIN32 +#include +#endif + +// -------------------------------------------------------- +// Options +// These can be accessed by multiple threads and may be +// concurrently initialized, but an initializing data race +// is ok since they resolve to the same value. +// -------------------------------------------------------- +typedef enum mi_init_e { + UNINIT, // not yet initialized + DEFAULTED, // not found in the environment, use default value + INITIALIZED // found in environment or set explicitly +} mi_init_t; + +typedef struct mi_option_desc_s { + long value; // the value + mi_init_t init; // is it initialized yet? (from the environment) + mi_option_t option; // for debugging: the option index should match the option + const char* name; // option name without `mimalloc_` prefix +} mi_option_desc_t; + +#define MI_OPTION(opt) mi_option_##opt, #opt +#define MI_OPTION_DESC(opt) {0, UNINIT, MI_OPTION(opt) } + +static mi_option_desc_t options[_mi_option_last] = +{ + // stable options +#if MI_DEBUG || defined(MI_SHOW_ERRORS) + { 1, UNINIT, MI_OPTION(show_errors) }, +#else + { 0, UNINIT, MI_OPTION(show_errors) }, +#endif + { 0, UNINIT, MI_OPTION(show_stats) }, + { 0, UNINIT, MI_OPTION(verbose) }, + + // the following options are experimental and not all combinations make sense. + { 1, UNINIT, MI_OPTION(eager_commit) }, // commit per segment directly (4MiB) (but see also `eager_commit_delay`) + #if defined(_WIN32) || (MI_INTPTR_SIZE <= 4) // and other OS's without overcommit? + { 0, UNINIT, MI_OPTION(eager_region_commit) }, + { 1, UNINIT, MI_OPTION(reset_decommits) }, // reset decommits memory + #else + { 1, UNINIT, MI_OPTION(eager_region_commit) }, + { 0, UNINIT, MI_OPTION(reset_decommits) }, // reset uses MADV_FREE/MADV_DONTNEED + #endif + { 0, UNINIT, MI_OPTION(large_os_pages) }, // use large OS pages, use only with eager commit to prevent fragmentation of VMA's + { 0, UNINIT, MI_OPTION(reserve_huge_os_pages) }, + { 0, UNINIT, MI_OPTION(segment_cache) }, // cache N segments per thread + { 1, UNINIT, MI_OPTION(page_reset) }, // reset page memory on free + { 0, UNINIT, MI_OPTION(abandoned_page_reset) },// reset free page memory when a thread terminates + { 0, UNINIT, MI_OPTION(segment_reset) }, // reset segment memory on free (needs eager commit) +#if defined(__NetBSD__) + { 0, UNINIT, MI_OPTION(eager_commit_delay) }, // the first N segments per thread are not eagerly committed +#else + { 1, UNINIT, MI_OPTION(eager_commit_delay) }, // the first N segments per thread are not eagerly committed (but per page in the segment on demand) +#endif + { 100, UNINIT, MI_OPTION(reset_delay) }, // reset delay in milli-seconds + { 0, UNINIT, MI_OPTION(use_numa_nodes) }, // 0 = use available numa nodes, otherwise use at most N nodes. + { 100, UNINIT, MI_OPTION(os_tag) }, // only apple specific for now but might serve more or less related purpose + { 16, UNINIT, MI_OPTION(max_errors) } // maximum errors that are output +}; + +static void mi_option_init(mi_option_desc_t* desc); + +void _mi_options_init(void) { + // called on process load; should not be called before the CRT is initialized! + // (e.g. do not call this from process_init as that may run before CRT initialization) + mi_add_stderr_output(); // now it safe to use stderr for output + for(int i = 0; i < _mi_option_last; i++ ) { + mi_option_t option = (mi_option_t)i; + long l = mi_option_get(option); UNUSED(l); // initialize + if (option != mi_option_verbose) { + mi_option_desc_t* desc = &options[option]; + _mi_verbose_message("option '%s': %ld\n", desc->name, desc->value); + } + } + mi_max_error_count = mi_option_get(mi_option_max_errors); +} + +long mi_option_get(mi_option_t option) { + mi_assert(option >= 0 && option < _mi_option_last); + mi_option_desc_t* desc = &options[option]; + mi_assert(desc->option == option); // index should match the option + if (mi_unlikely(desc->init == UNINIT)) { + mi_option_init(desc); + } + return desc->value; +} + +void mi_option_set(mi_option_t option, long value) { + mi_assert(option >= 0 && option < _mi_option_last); + mi_option_desc_t* desc = &options[option]; + mi_assert(desc->option == option); // index should match the option + desc->value = value; + desc->init = INITIALIZED; +} + +void mi_option_set_default(mi_option_t option, long value) { + mi_assert(option >= 0 && option < _mi_option_last); + mi_option_desc_t* desc = &options[option]; + if (desc->init != INITIALIZED) { + desc->value = value; + } +} + +bool mi_option_is_enabled(mi_option_t option) { + return (mi_option_get(option) != 0); +} + +void mi_option_set_enabled(mi_option_t option, bool enable) { + mi_option_set(option, (enable ? 1 : 0)); +} + +void mi_option_set_enabled_default(mi_option_t option, bool enable) { + mi_option_set_default(option, (enable ? 1 : 0)); +} + +void mi_option_enable(mi_option_t option) { + mi_option_set_enabled(option,true); +} + +void mi_option_disable(mi_option_t option) { + mi_option_set_enabled(option,false); +} + + +static void mi_out_stderr(const char* msg, void* arg) { + UNUSED(arg); + #ifdef _WIN32 + // on windows with redirection, the C runtime cannot handle locale dependent output + // after the main thread closes so we use direct console output. + if (!_mi_preloading()) { _cputs(msg); } + #else + fputs(msg, stderr); + #endif +} + +// Since an output function can be registered earliest in the `main` +// function we also buffer output that happens earlier. When +// an output function is registered it is called immediately with +// the output up to that point. +#ifndef MI_MAX_DELAY_OUTPUT +#define MI_MAX_DELAY_OUTPUT ((uintptr_t)(32*1024)) +#endif +static char out_buf[MI_MAX_DELAY_OUTPUT+1]; +static _Atomic(uintptr_t) out_len; + +static void mi_out_buf(const char* msg, void* arg) { + UNUSED(arg); + if (msg==NULL) return; + if (mi_atomic_load_relaxed(&out_len)>=MI_MAX_DELAY_OUTPUT) return; + size_t n = strlen(msg); + if (n==0) return; + // claim space + uintptr_t start = mi_atomic_add_acq_rel(&out_len, n); + if (start >= MI_MAX_DELAY_OUTPUT) return; + // check bound + if (start+n >= MI_MAX_DELAY_OUTPUT) { + n = MI_MAX_DELAY_OUTPUT-start-1; + } + memcpy(&out_buf[start], msg, n); +} + +static void mi_out_buf_flush(mi_output_fun* out, bool no_more_buf, void* arg) { + if (out==NULL) return; + // claim (if `no_more_buf == true`, no more output will be added after this point) + size_t count = mi_atomic_add_acq_rel(&out_len, (no_more_buf ? MI_MAX_DELAY_OUTPUT : 1)); + // and output the current contents + if (count>MI_MAX_DELAY_OUTPUT) count = MI_MAX_DELAY_OUTPUT; + out_buf[count] = 0; + out(out_buf,arg); + if (!no_more_buf) { + out_buf[count] = '\n'; // if continue with the buffer, insert a newline + } +} + + +// Once this module is loaded, switch to this routine +// which outputs to stderr and the delayed output buffer. +static void mi_out_buf_stderr(const char* msg, void* arg) { + mi_out_stderr(msg,arg); + mi_out_buf(msg,arg); +} + + + +// -------------------------------------------------------- +// Default output handler +// -------------------------------------------------------- + +// Should be atomic but gives errors on many platforms as generally we cannot cast a function pointer to a uintptr_t. +// For now, don't register output from multiple threads. +static mi_output_fun* volatile mi_out_default; // = NULL +static _Atomic(void*) mi_out_arg; // = NULL + +static mi_output_fun* mi_out_get_default(void** parg) { + if (parg != NULL) { *parg = mi_atomic_load_ptr_acquire(void,&mi_out_arg); } + mi_output_fun* out = mi_out_default; + return (out == NULL ? &mi_out_buf : out); +} + +void mi_register_output(mi_output_fun* out, void* arg) mi_attr_noexcept { + mi_out_default = (out == NULL ? &mi_out_stderr : out); // stop using the delayed output buffer + mi_atomic_store_ptr_release(void,&mi_out_arg, arg); + if (out!=NULL) mi_out_buf_flush(out,true,arg); // output all the delayed output now +} + +// add stderr to the delayed output after the module is loaded +static void mi_add_stderr_output() { + mi_assert_internal(mi_out_default == NULL); + mi_out_buf_flush(&mi_out_stderr, false, NULL); // flush current contents to stderr + mi_out_default = &mi_out_buf_stderr; // and add stderr to the delayed output +} + +// -------------------------------------------------------- +// Messages, all end up calling `_mi_fputs`. +// -------------------------------------------------------- +static _Atomic(uintptr_t) error_count; // = 0; // when MAX_ERROR_COUNT stop emitting errors and warnings + +// When overriding malloc, we may recurse into mi_vfprintf if an allocation +// inside the C runtime causes another message. +static mi_decl_thread bool recurse = false; + +static bool mi_recurse_enter(void) { + #ifdef MI_TLS_RECURSE_GUARD + if (_mi_preloading()) return true; + #endif + if (recurse) return false; + recurse = true; + return true; +} + +static void mi_recurse_exit(void) { + #ifdef MI_TLS_RECURSE_GUARD + if (_mi_preloading()) return; + #endif + recurse = false; +} + +void _mi_fputs(mi_output_fun* out, void* arg, const char* prefix, const char* message) { + if (out==NULL || (FILE*)out==stdout || (FILE*)out==stderr) { // TODO: use mi_out_stderr for stderr? + if (!mi_recurse_enter()) return; + out = mi_out_get_default(&arg); + if (prefix != NULL) out(prefix, arg); + out(message, arg); + mi_recurse_exit(); + } + else { + if (prefix != NULL) out(prefix, arg); + out(message, arg); + } +} + +// Define our own limited `fprintf` that avoids memory allocation. +// We do this using `snprintf` with a limited buffer. +static void mi_vfprintf( mi_output_fun* out, void* arg, const char* prefix, const char* fmt, va_list args ) { + char buf[512]; + if (fmt==NULL) return; + if (!mi_recurse_enter()) return; + vsnprintf(buf,sizeof(buf)-1,fmt,args); + mi_recurse_exit(); + _mi_fputs(out,arg,prefix,buf); +} + +void _mi_fprintf( mi_output_fun* out, void* arg, const char* fmt, ... ) { + va_list args; + va_start(args,fmt); + mi_vfprintf(out,arg,NULL,fmt,args); + va_end(args); +} + +void _mi_trace_message(const char* fmt, ...) { + if (mi_option_get(mi_option_verbose) <= 1) return; // only with verbose level 2 or higher + va_list args; + va_start(args, fmt); + mi_vfprintf(NULL, NULL, "mimalloc: ", fmt, args); + va_end(args); +} + +void _mi_verbose_message(const char* fmt, ...) { + if (!mi_option_is_enabled(mi_option_verbose)) return; + va_list args; + va_start(args,fmt); + mi_vfprintf(NULL, NULL, "mimalloc: ", fmt, args); + va_end(args); +} + +static void mi_show_error_message(const char* fmt, va_list args) { + if (!mi_option_is_enabled(mi_option_show_errors) && !mi_option_is_enabled(mi_option_verbose)) return; + if (mi_atomic_increment_acq_rel(&error_count) > mi_max_error_count) return; + mi_vfprintf(NULL, NULL, "mimalloc: error: ", fmt, args); +} + +void _mi_warning_message(const char* fmt, ...) { + if (!mi_option_is_enabled(mi_option_show_errors) && !mi_option_is_enabled(mi_option_verbose)) return; + if (mi_atomic_increment_acq_rel(&error_count) > mi_max_error_count) return; + va_list args; + va_start(args,fmt); + mi_vfprintf(NULL, NULL, "mimalloc: warning: ", fmt, args); + va_end(args); +} + + +#if MI_DEBUG +void _mi_assert_fail(const char* assertion, const char* fname, unsigned line, const char* func ) { + _mi_fprintf(NULL, NULL, "mimalloc: assertion failed: at \"%s\":%u, %s\n assertion: \"%s\"\n", fname, line, (func==NULL?"":func), assertion); + abort(); +} +#endif + +// -------------------------------------------------------- +// Errors +// -------------------------------------------------------- + +static mi_error_fun* volatile mi_error_handler; // = NULL +static _Atomic(void*) mi_error_arg; // = NULL + +static void mi_error_default(int err) { + UNUSED(err); +#if (MI_DEBUG>0) + if (err==EFAULT) { + #ifdef _MSC_VER + __debugbreak(); + #endif + abort(); + } +#endif +#if (MI_SECURE>0) + if (err==EFAULT) { // abort on serious errors in secure mode (corrupted meta-data) + abort(); + } +#endif +#if defined(MI_XMALLOC) + if (err==ENOMEM || err==EOVERFLOW) { // abort on memory allocation fails in xmalloc mode + abort(); + } +#endif +} + +void mi_register_error(mi_error_fun* fun, void* arg) { + mi_error_handler = fun; // can be NULL + mi_atomic_store_ptr_release(void,&mi_error_arg, arg); +} + +void _mi_error_message(int err, const char* fmt, ...) { + // show detailed error message + va_list args; + va_start(args, fmt); + mi_show_error_message(fmt, args); + va_end(args); + // and call the error handler which may abort (or return normally) + if (mi_error_handler != NULL) { + mi_error_handler(err, mi_atomic_load_ptr_acquire(void,&mi_error_arg)); + } + else { + mi_error_default(err); + } +} + +// -------------------------------------------------------- +// Initialize options by checking the environment +// -------------------------------------------------------- + +static void mi_strlcpy(char* dest, const char* src, size_t dest_size) { + dest[0] = 0; + strncpy(dest, src, dest_size - 1); + dest[dest_size - 1] = 0; +} + +static void mi_strlcat(char* dest, const char* src, size_t dest_size) { + strncat(dest, src, dest_size - 1); + dest[dest_size - 1] = 0; +} + +static inline int mi_strnicmp(const char* s, const char* t, size_t n) { + if (n==0) return 0; + for (; *s != 0 && *t != 0 && n > 0; s++, t++, n--) { + if (toupper(*s) != toupper(*t)) break; + } + return (n==0 ? 0 : *s - *t); +} + +#if defined _WIN32 +// On Windows use GetEnvironmentVariable instead of getenv to work +// reliably even when this is invoked before the C runtime is initialized. +// i.e. when `_mi_preloading() == true`. +// Note: on windows, environment names are not case sensitive. +#include +static bool mi_getenv(const char* name, char* result, size_t result_size) { + result[0] = 0; + size_t len = GetEnvironmentVariableA(name, result, (DWORD)result_size); + return (len > 0 && len < result_size); +} +#elif !defined(MI_USE_ENVIRON) || (MI_USE_ENVIRON!=0) +// On Posix systemsr use `environ` to acces environment variables +// even before the C runtime is initialized. +#if defined(__APPLE__) && defined(__has_include) && __has_include() +#include +static char** mi_get_environ(void) { + return (*_NSGetEnviron()); +} +#else +extern char** environ; +static char** mi_get_environ(void) { + return environ; +} +#endif +static bool mi_getenv(const char* name, char* result, size_t result_size) { + if (name==NULL) return false; + const size_t len = strlen(name); + if (len == 0) return false; + char** env = mi_get_environ(); + if (env == NULL) return false; + // compare up to 256 entries + for (int i = 0; i < 256 && env[i] != NULL; i++) { + const char* s = env[i]; + if (mi_strnicmp(name, s, len) == 0 && s[len] == '=') { // case insensitive + // found it + mi_strlcpy(result, s + len + 1, result_size); + return true; + } + } + return false; +} +#else +// fallback: use standard C `getenv` but this cannot be used while initializing the C runtime +static bool mi_getenv(const char* name, char* result, size_t result_size) { + // cannot call getenv() when still initializing the C runtime. + if (_mi_preloading()) return false; + const char* s = getenv(name); + if (s == NULL) { + // we check the upper case name too. + char buf[64+1]; + size_t len = strlen(name); + if (len >= sizeof(buf)) len = sizeof(buf) - 1; + for (size_t i = 0; i < len; i++) { + buf[i] = toupper(name[i]); + } + buf[len] = 0; + s = getenv(buf); + } + if (s != NULL && strlen(s) < result_size) { + mi_strlcpy(result, s, result_size); + return true; + } + else { + return false; + } +} +#endif + +static void mi_option_init(mi_option_desc_t* desc) { + // Read option value from the environment + char buf[64+1]; + mi_strlcpy(buf, "mimalloc_", sizeof(buf)); + mi_strlcat(buf, desc->name, sizeof(buf)); + char s[64+1]; + if (mi_getenv(buf, s, sizeof(s))) { + size_t len = strlen(s); + if (len >= sizeof(buf)) len = sizeof(buf) - 1; + for (size_t i = 0; i < len; i++) { + buf[i] = (char)toupper(s[i]); + } + buf[len] = 0; + if (buf[0]==0 || strstr("1;TRUE;YES;ON", buf) != NULL) { + desc->value = 1; + desc->init = INITIALIZED; + } + else if (strstr("0;FALSE;NO;OFF", buf) != NULL) { + desc->value = 0; + desc->init = INITIALIZED; + } + else { + char* end = buf; + long value = strtol(buf, &end, 10); + if (*end == 0) { + desc->value = value; + desc->init = INITIALIZED; + } + else { + _mi_warning_message("environment option mimalloc_%s has an invalid value: %s\n", desc->name, buf); + desc->init = DEFAULTED; + } + } + mi_assert_internal(desc->init != UNINIT); + } + else if (!_mi_preloading()) { + desc->init = DEFAULTED; + } +} diff --git a/kotlin-native/runtime/src/mimalloc/c/os.c b/kotlin-native/runtime/src/mimalloc/c/os.c new file mode 100644 index 00000000000..fb47147e708 --- /dev/null +++ b/kotlin-native/runtime/src/mimalloc/c/os.c @@ -0,0 +1,1193 @@ +/* ---------------------------------------------------------------------------- +Copyright (c) 2018, Microsoft Research, Daan Leijen +This is free software; you can redistribute it and/or modify it under the +terms of the MIT license. A copy of the license can be found in the file +"licenses/third_party/mimalloc_LICENSE.txt" at the root of this distribution. +-----------------------------------------------------------------------------*/ +#ifndef _DEFAULT_SOURCE +#define _DEFAULT_SOURCE // ensure mmap flags are defined +#endif + +#if defined(__sun) +// illumos provides new mman.h api when any of these are defined +// otherwise the old api based on caddr_t which predates the void pointers one. +// stock solaris provides only the former, chose to atomically to discard those +// flags only here rather than project wide tough. +#undef _XOPEN_SOURCE +#undef _POSIX_C_SOURCE +#endif +#include "mimalloc.h" +#include "mimalloc-internal.h" +#include "mimalloc-atomic.h" + +#include // strerror + +#ifdef _MSC_VER +#pragma warning(disable:4996) // strerror +#endif + + +#if defined(_WIN32) +#include +#elif defined(__wasi__) +// stdlib.h is all we need, and has already been included in mimalloc.h +#else +#include // mmap +#include // sysconf +#if defined(__linux__) +#include +#if defined(__GLIBC__) +#include // linux mmap flags +#else +#include +#endif +#endif +#if defined(__APPLE__) +#include +#if !TARGET_IOS_IPHONE && !TARGET_IOS_SIMULATOR +#include +#endif +#endif +#if defined(__HAIKU__) +#define madvise posix_madvise +#define MADV_DONTNEED POSIX_MADV_DONTNEED +#endif +#endif + +/* ----------------------------------------------------------- + Initialization. + On windows initializes support for aligned allocation and + large OS pages (if MIMALLOC_LARGE_OS_PAGES is true). +----------------------------------------------------------- */ +bool _mi_os_decommit(void* addr, size_t size, mi_stats_t* stats); + +static void* mi_align_up_ptr(void* p, size_t alignment) { + return (void*)_mi_align_up((uintptr_t)p, alignment); +} + +static uintptr_t _mi_align_down(uintptr_t sz, size_t alignment) { + return (sz / alignment) * alignment; +} + +static void* mi_align_down_ptr(void* p, size_t alignment) { + return (void*)_mi_align_down((uintptr_t)p, alignment); +} + +// page size (initialized properly in `os_init`) +static size_t os_page_size = 4096; + +// minimal allocation granularity +static size_t os_alloc_granularity = 4096; + +// if non-zero, use large page allocation +static size_t large_os_page_size = 0; + +// OS (small) page size +size_t _mi_os_page_size() { + return os_page_size; +} + +// if large OS pages are supported (2 or 4MiB), then return the size, otherwise return the small page size (4KiB) +size_t _mi_os_large_page_size() { + return (large_os_page_size != 0 ? large_os_page_size : _mi_os_page_size()); +} + +static bool use_large_os_page(size_t size, size_t alignment) { + // if we have access, check the size and alignment requirements + if (large_os_page_size == 0 || !mi_option_is_enabled(mi_option_large_os_pages)) return false; + return ((size % large_os_page_size) == 0 && (alignment % large_os_page_size) == 0); +} + +// round to a good OS allocation size (bounded by max 12.5% waste) +size_t _mi_os_good_alloc_size(size_t size) { + size_t align_size; + if (size < 512*KiB) align_size = _mi_os_page_size(); + else if (size < 2*MiB) align_size = 64*KiB; + else if (size < 8*MiB) align_size = 256*KiB; + else if (size < 32*MiB) align_size = 1*MiB; + else align_size = 4*MiB; + if (size >= (SIZE_MAX - align_size)) return size; // possible overflow? + return _mi_align_up(size, align_size); +} + +#if defined(_WIN32) +// We use VirtualAlloc2 for aligned allocation, but it is only supported on Windows 10 and Windows Server 2016. +// So, we need to look it up dynamically to run on older systems. (use __stdcall for 32-bit compatibility) +// NtAllocateVirtualAllocEx is used for huge OS page allocation (1GiB) +// +// We hide MEM_EXTENDED_PARAMETER to compile with older SDK's. +#include +typedef PVOID (__stdcall *PVirtualAlloc2)(HANDLE, PVOID, SIZE_T, ULONG, ULONG, /* MEM_EXTENDED_PARAMETER* */ void*, ULONG); +typedef NTSTATUS (__stdcall *PNtAllocateVirtualMemoryEx)(HANDLE, PVOID*, SIZE_T*, ULONG, ULONG, /* MEM_EXTENDED_PARAMETER* */ PVOID, ULONG); +static PVirtualAlloc2 pVirtualAlloc2 = NULL; +static PNtAllocateVirtualMemoryEx pNtAllocateVirtualMemoryEx = NULL; + +// Similarly, GetNumaProcesorNodeEx is only supported since Windows 7 +#if (_WIN32_WINNT < 0x601) // before Win7 +typedef struct _PROCESSOR_NUMBER { WORD Group; BYTE Number; BYTE Reserved; } PROCESSOR_NUMBER, *PPROCESSOR_NUMBER; +#endif +typedef VOID (__stdcall *PGetCurrentProcessorNumberEx)(PPROCESSOR_NUMBER ProcNumber); +typedef BOOL (__stdcall *PGetNumaProcessorNodeEx)(PPROCESSOR_NUMBER Processor, PUSHORT NodeNumber); +typedef BOOL (__stdcall* PGetNumaNodeProcessorMaskEx)(USHORT Node, PGROUP_AFFINITY ProcessorMask); +static PGetCurrentProcessorNumberEx pGetCurrentProcessorNumberEx = NULL; +static PGetNumaProcessorNodeEx pGetNumaProcessorNodeEx = NULL; +static PGetNumaNodeProcessorMaskEx pGetNumaNodeProcessorMaskEx = NULL; + +static bool mi_win_enable_large_os_pages() +{ + if (large_os_page_size > 0) return true; + + // Try to see if large OS pages are supported + // To use large pages on Windows, we first need access permission + // Set "Lock pages in memory" permission in the group policy editor + // + unsigned long err = 0; + HANDLE token = NULL; + BOOL ok = OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &token); + if (ok) { + TOKEN_PRIVILEGES tp; + ok = LookupPrivilegeValue(NULL, TEXT("SeLockMemoryPrivilege"), &tp.Privileges[0].Luid); + if (ok) { + tp.PrivilegeCount = 1; + tp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED; + ok = AdjustTokenPrivileges(token, FALSE, &tp, 0, (PTOKEN_PRIVILEGES)NULL, 0); + if (ok) { + err = GetLastError(); + ok = (err == ERROR_SUCCESS); + if (ok) { + large_os_page_size = GetLargePageMinimum(); + } + } + } + CloseHandle(token); + } + if (!ok) { + if (err == 0) err = GetLastError(); + _mi_warning_message("cannot enable large OS page support, error %lu\n", err); + } + return (ok!=0); +} + +void _mi_os_init(void) { + // get the page size + SYSTEM_INFO si; + GetSystemInfo(&si); + if (si.dwPageSize > 0) os_page_size = si.dwPageSize; + if (si.dwAllocationGranularity > 0) os_alloc_granularity = si.dwAllocationGranularity; + // get the VirtualAlloc2 function + HINSTANCE hDll; + hDll = LoadLibrary(TEXT("kernelbase.dll")); + if (hDll != NULL) { + // use VirtualAlloc2FromApp if possible as it is available to Windows store apps + pVirtualAlloc2 = (PVirtualAlloc2)(void (*)(void))GetProcAddress(hDll, "VirtualAlloc2FromApp"); + if (pVirtualAlloc2==NULL) pVirtualAlloc2 = (PVirtualAlloc2)(void (*)(void))GetProcAddress(hDll, "VirtualAlloc2"); + FreeLibrary(hDll); + } + // NtAllocateVirtualMemoryEx is used for huge page allocation + hDll = LoadLibrary(TEXT("ntdll.dll")); + if (hDll != NULL) { + pNtAllocateVirtualMemoryEx = (PNtAllocateVirtualMemoryEx)(void (*)(void))GetProcAddress(hDll, "NtAllocateVirtualMemoryEx"); + FreeLibrary(hDll); + } + // Try to use Win7+ numa API + hDll = LoadLibrary(TEXT("kernel32.dll")); + if (hDll != NULL) { + pGetCurrentProcessorNumberEx = (PGetCurrentProcessorNumberEx)(void (*)(void))GetProcAddress(hDll, "GetCurrentProcessorNumberEx"); + pGetNumaProcessorNodeEx = (PGetNumaProcessorNodeEx)(void (*)(void))GetProcAddress(hDll, "GetNumaProcessorNodeEx"); + pGetNumaNodeProcessorMaskEx = (PGetNumaNodeProcessorMaskEx)(void (*)(void))GetProcAddress(hDll, "GetNumaNodeProcessorMaskEx"); + FreeLibrary(hDll); + } + if (mi_option_is_enabled(mi_option_large_os_pages) || mi_option_is_enabled(mi_option_reserve_huge_os_pages)) { + mi_win_enable_large_os_pages(); + } +} +#elif defined(__wasi__) +void _mi_os_init() { + os_page_size = 0x10000; // WebAssembly has a fixed page size: 64KB + os_alloc_granularity = 16; +} +#else +void _mi_os_init() { + // get the page size + long result = sysconf(_SC_PAGESIZE); + if (result > 0) { + os_page_size = (size_t)result; + os_alloc_granularity = os_page_size; + } + large_os_page_size = 2*MiB; // TODO: can we query the OS for this? +} +#endif + + +/* ----------------------------------------------------------- + Raw allocation on Windows (VirtualAlloc) and Unix's (mmap). +----------------------------------------------------------- */ + +static bool mi_os_mem_free(void* addr, size_t size, bool was_committed, mi_stats_t* stats) +{ + if (addr == NULL || size == 0) return true; // || _mi_os_is_huge_reserved(addr) + bool err = false; +#if defined(_WIN32) + err = (VirtualFree(addr, 0, MEM_RELEASE) == 0); +#elif defined(__wasi__) + err = 0; // WebAssembly's heap cannot be shrunk +#else + err = (munmap(addr, size) == -1); +#endif + if (was_committed) _mi_stat_decrease(&stats->committed, size); + _mi_stat_decrease(&stats->reserved, size); + if (err) { + _mi_warning_message("munmap failed: %s, addr 0x%8li, size %lu\n", strerror(errno), (size_t)addr, size); + return false; + } + else { + return true; + } +} + +static void* mi_os_get_aligned_hint(size_t try_alignment, size_t size); + +#ifdef _WIN32 +static void* mi_win_virtual_allocx(void* addr, size_t size, size_t try_alignment, DWORD flags) { +#if (MI_INTPTR_SIZE >= 8) + // on 64-bit systems, try to use the virtual address area after 4TiB for 4MiB aligned allocations + void* hint; + if (addr == NULL && (hint = mi_os_get_aligned_hint(try_alignment,size)) != NULL) { + void* p = VirtualAlloc(hint, size, flags, PAGE_READWRITE); + if (p != NULL) return p; + DWORD err = GetLastError(); + if (err != ERROR_INVALID_ADDRESS && // If linked with multiple instances, we may have tried to allocate at an already allocated area (#210) + err != ERROR_INVALID_PARAMETER) { // Windows7 instability (#230) + return NULL; + } + // fall through + } +#endif +#if defined(MEM_EXTENDED_PARAMETER_TYPE_BITS) + // on modern Windows try use VirtualAlloc2 for aligned allocation + if (try_alignment > 0 && (try_alignment % _mi_os_page_size()) == 0 && pVirtualAlloc2 != NULL) { + MEM_ADDRESS_REQUIREMENTS reqs = { 0, 0, 0 }; + reqs.Alignment = try_alignment; + MEM_EXTENDED_PARAMETER param = { {0, 0}, {0} }; + param.Type = MemExtendedParameterAddressRequirements; + param.Pointer = &reqs; + return (*pVirtualAlloc2)(GetCurrentProcess(), addr, size, flags, PAGE_READWRITE, ¶m, 1); + } +#endif + // last resort + return VirtualAlloc(addr, size, flags, PAGE_READWRITE); +} + +static void* mi_win_virtual_alloc(void* addr, size_t size, size_t try_alignment, DWORD flags, bool large_only, bool allow_large, bool* is_large) { + mi_assert_internal(!(large_only && !allow_large)); + static _Atomic(uintptr_t) large_page_try_ok; // = 0; + void* p = NULL; + if ((large_only || use_large_os_page(size, try_alignment)) + && allow_large && (flags&MEM_COMMIT)!=0 && (flags&MEM_RESERVE)!=0) { + uintptr_t try_ok = mi_atomic_load_acquire(&large_page_try_ok); + if (!large_only && try_ok > 0) { + // if a large page allocation fails, it seems the calls to VirtualAlloc get very expensive. + // therefore, once a large page allocation failed, we don't try again for `large_page_try_ok` times. + mi_atomic_cas_strong_acq_rel(&large_page_try_ok, &try_ok, try_ok - 1); + } + else { + // large OS pages must always reserve and commit. + *is_large = true; + p = mi_win_virtual_allocx(addr, size, try_alignment, flags | MEM_LARGE_PAGES); + if (large_only) return p; + // fall back to non-large page allocation on error (`p == NULL`). + if (p == NULL) { + mi_atomic_store_release(&large_page_try_ok,10UL); // on error, don't try again for the next N allocations + } + } + } + if (p == NULL) { + *is_large = ((flags&MEM_LARGE_PAGES) != 0); + p = mi_win_virtual_allocx(addr, size, try_alignment, flags); + } + if (p == NULL) { + _mi_warning_message("unable to allocate OS memory (%zu bytes, error code: %i, address: %p, large only: %d, allow large: %d)\n", size, GetLastError(), addr, large_only, allow_large); + } + return p; +} + +#elif defined(__wasi__) +static void* mi_wasm_heap_grow(size_t size, size_t try_alignment) { + uintptr_t base = __builtin_wasm_memory_size(0) * _mi_os_page_size(); + uintptr_t aligned_base = _mi_align_up(base, (uintptr_t) try_alignment); + size_t alloc_size = _mi_align_up( aligned_base - base + size, _mi_os_page_size()); + mi_assert(alloc_size >= size && (alloc_size % _mi_os_page_size()) == 0); + if (alloc_size < size) return NULL; + if (__builtin_wasm_memory_grow(0, alloc_size / _mi_os_page_size()) == SIZE_MAX) { + errno = ENOMEM; + return NULL; + } + return (void*)aligned_base; +} +#else +#define MI_OS_USE_MMAP +static void* mi_unix_mmapx(void* addr, size_t size, size_t try_alignment, int protect_flags, int flags, int fd) { + void* p = NULL; + #if (MI_INTPTR_SIZE >= 8) && !defined(MAP_ALIGNED) + // on 64-bit systems, use the virtual address area after 4TiB for 4MiB aligned allocations + void* hint; + if (addr == NULL && (hint = mi_os_get_aligned_hint(try_alignment, size)) != NULL) { + p = mmap(hint,size,protect_flags,flags,fd,0); + if (p==MAP_FAILED) p = NULL; // fall back to regular mmap + } + #else + UNUSED(try_alignment); + UNUSED(mi_os_get_aligned_hint); + #endif + if (p==NULL) { + p = mmap(addr,size,protect_flags,flags,fd,0); + if (p==MAP_FAILED) p = NULL; + } + return p; +} + +static void* mi_unix_mmap(void* addr, size_t size, size_t try_alignment, int protect_flags, bool large_only, bool allow_large, bool* is_large) { + void* p = NULL; + #if !defined(MAP_ANONYMOUS) + #define MAP_ANONYMOUS MAP_ANON + #endif + #if !defined(MAP_NORESERVE) + #define MAP_NORESERVE 0 + #endif + int flags = MAP_PRIVATE | MAP_ANONYMOUS | MAP_NORESERVE; + int fd = -1; + #if defined(MAP_ALIGNED) // BSD + if (try_alignment > 0) { + size_t n = _mi_bsr(try_alignment); + if (((size_t)1 << n) == try_alignment && n >= 12 && n <= 30) { // alignment is a power of 2 and 4096 <= alignment <= 1GiB + flags |= MAP_ALIGNED(n); + } + } + #endif + #if defined(PROT_MAX) + protect_flags |= PROT_MAX(PROT_READ | PROT_WRITE); // BSD + #endif + #if defined(VM_MAKE_TAG) + // macOS: tracking anonymous page with a specific ID. (All up to 98 are taken officially but LLVM sanitizers had taken 99) + int os_tag = (int)mi_option_get(mi_option_os_tag); + if (os_tag < 100 || os_tag > 255) os_tag = 100; + fd = VM_MAKE_TAG(os_tag); + #endif + if ((large_only || use_large_os_page(size, try_alignment)) && allow_large) { + static _Atomic(uintptr_t) large_page_try_ok; // = 0; + uintptr_t try_ok = mi_atomic_load_acquire(&large_page_try_ok); + if (!large_only && try_ok > 0) { + // If the OS is not configured for large OS pages, or the user does not have + // enough permission, the `mmap` will always fail (but it might also fail for other reasons). + // Therefore, once a large page allocation failed, we don't try again for `large_page_try_ok` times + // to avoid too many failing calls to mmap. + mi_atomic_cas_strong_acq_rel(&large_page_try_ok, &try_ok, try_ok - 1); + } + else { + int lflags = flags & ~MAP_NORESERVE; // using NORESERVE on huge pages seems to fail on Linux + int lfd = fd; + #ifdef MAP_ALIGNED_SUPER + lflags |= MAP_ALIGNED_SUPER; + #endif + #ifdef MAP_HUGETLB + lflags |= MAP_HUGETLB; + #endif + #ifdef MAP_HUGE_1GB + static bool mi_huge_pages_available = true; + if ((size % GiB) == 0 && mi_huge_pages_available) { + lflags |= MAP_HUGE_1GB; + } + else + #endif + { + #ifdef MAP_HUGE_2MB + lflags |= MAP_HUGE_2MB; + #endif + } + #ifdef VM_FLAGS_SUPERPAGE_SIZE_2MB + lfd |= VM_FLAGS_SUPERPAGE_SIZE_2MB; + #endif + if (large_only || lflags != flags) { + // try large OS page allocation + *is_large = true; + p = mi_unix_mmapx(addr, size, try_alignment, protect_flags, lflags, lfd); + #ifdef MAP_HUGE_1GB + if (p == NULL && (lflags & MAP_HUGE_1GB) != 0) { + mi_huge_pages_available = false; // don't try huge 1GiB pages again + _mi_warning_message("unable to allocate huge (1GiB) page, trying large (2MiB) pages instead (error %i)\n", errno); + lflags = ((lflags & ~MAP_HUGE_1GB) | MAP_HUGE_2MB); + p = mi_unix_mmapx(addr, size, try_alignment, protect_flags, lflags, lfd); + } + #endif + if (large_only) return p; + if (p == NULL) { + mi_atomic_store_release(&large_page_try_ok, 10UL); // on error, don't try again for the next N allocations + } + } + } + } + if (p == NULL) { + *is_large = false; + p = mi_unix_mmapx(addr, size, try_alignment, protect_flags, flags, fd); + #if defined(MADV_HUGEPAGE) + // Many Linux systems don't allow MAP_HUGETLB but they support instead + // transparent huge pages (THP). It is not required to call `madvise` with MADV_HUGE + // though since properly aligned allocations will already use large pages if available + // in that case -- in particular for our large regions (in `memory.c`). + // However, some systems only allow THP if called with explicit `madvise`, so + // when large OS pages are enabled for mimalloc, we call `madvice` anyways. + if (allow_large && use_large_os_page(size, try_alignment)) { + if (madvise(p, size, MADV_HUGEPAGE) == 0) { + *is_large = true; // possibly + }; + } + #endif + #if defined(__sun) + if (allow_large && use_large_os_page(size, try_alignment)) { + struct memcntl_mha cmd = {0}; + cmd.mha_pagesize = large_os_page_size; + cmd.mha_cmd = MHA_MAPSIZE_VA; + if (memcntl(p, size, MC_HAT_ADVISE, (caddr_t)&cmd, 0, 0) == 0) { + *is_large = true; + } + } + #endif + } + if (p == NULL) { + _mi_warning_message("unable to allocate OS memory (%zu bytes, error code: %i, address: %p, large only: %d, allow large: %d)\n", size, errno, addr, large_only, allow_large); + } + return p; +} +#endif + +// On 64-bit systems, we can do efficient aligned allocation by using +// the 4TiB to 30TiB area to allocate them. +#if (MI_INTPTR_SIZE >= 8) && (defined(_WIN32) || (defined(MI_OS_USE_MMAP) && !defined(MAP_ALIGNED))) +static mi_decl_cache_align _Atomic(uintptr_t) aligned_base; + +// Return a 4MiB aligned address that is probably available +static void* mi_os_get_aligned_hint(size_t try_alignment, size_t size) { + if (try_alignment == 0 || try_alignment > MI_SEGMENT_SIZE) return NULL; + if ((size%MI_SEGMENT_SIZE) != 0) return NULL; + uintptr_t hint = mi_atomic_add_acq_rel(&aligned_base, size); + if (hint == 0 || hint > ((intptr_t)30<<40)) { // try to wrap around after 30TiB (area after 32TiB is used for huge OS pages) + uintptr_t init = ((uintptr_t)4 << 40); // start at 4TiB area + #if (MI_SECURE>0 || MI_DEBUG==0) // security: randomize start of aligned allocations unless in debug mode + uintptr_t r = _mi_heap_random_next(mi_get_default_heap()); + init = init + (MI_SEGMENT_SIZE * ((r>>17) & 0xFFFFF)); // (randomly 20 bits)*4MiB == 0 to 4TiB + #endif + uintptr_t expected = hint + size; + mi_atomic_cas_strong_acq_rel(&aligned_base, &expected, init); + hint = mi_atomic_add_acq_rel(&aligned_base, size); // this may still give 0 or > 30TiB but that is ok, it is a hint after all + } + if (hint%try_alignment != 0) return NULL; + return (void*)hint; +} +#else +static void* mi_os_get_aligned_hint(size_t try_alignment, size_t size) { + UNUSED(try_alignment); UNUSED(size); + return NULL; +} +#endif + + +// Primitive allocation from the OS. +// Note: the `try_alignment` is just a hint and the returned pointer is not guaranteed to be aligned. +static void* mi_os_mem_alloc(size_t size, size_t try_alignment, bool commit, bool allow_large, bool* is_large, mi_stats_t* stats) { + mi_assert_internal(size > 0 && (size % _mi_os_page_size()) == 0); + if (size == 0) return NULL; + if (!commit) allow_large = false; + + void* p = NULL; + /* + if (commit && allow_large) { + p = _mi_os_try_alloc_from_huge_reserved(size, try_alignment); + if (p != NULL) { + *is_large = true; + return p; + } + } + */ + + #if defined(_WIN32) + int flags = MEM_RESERVE; + if (commit) flags |= MEM_COMMIT; + p = mi_win_virtual_alloc(NULL, size, try_alignment, flags, false, allow_large, is_large); + #elif defined(__wasi__) + *is_large = false; + p = mi_wasm_heap_grow(size, try_alignment); + #else + int protect_flags = (commit ? (PROT_WRITE | PROT_READ) : PROT_NONE); + p = mi_unix_mmap(NULL, size, try_alignment, protect_flags, false, allow_large, is_large); + #endif + mi_stat_counter_increase(stats->mmap_calls, 1); + if (p != NULL) { + _mi_stat_increase(&stats->reserved, size); + if (commit) { _mi_stat_increase(&stats->committed, size); } + } + return p; +} + + +// Primitive aligned allocation from the OS. +// This function guarantees the allocated memory is aligned. +static void* mi_os_mem_alloc_aligned(size_t size, size_t alignment, bool commit, bool allow_large, bool* is_large, mi_stats_t* stats) { + mi_assert_internal(alignment >= _mi_os_page_size() && ((alignment & (alignment - 1)) == 0)); + mi_assert_internal(size > 0 && (size % _mi_os_page_size()) == 0); + if (!commit) allow_large = false; + if (!(alignment >= _mi_os_page_size() && ((alignment & (alignment - 1)) == 0))) return NULL; + size = _mi_align_up(size, _mi_os_page_size()); + + // try first with a hint (this will be aligned directly on Win 10+ or BSD) + void* p = mi_os_mem_alloc(size, alignment, commit, allow_large, is_large, stats); + if (p == NULL) return NULL; + + // if not aligned, free it, overallocate, and unmap around it + if (((uintptr_t)p % alignment != 0)) { + mi_os_mem_free(p, size, commit, stats); + if (size >= (SIZE_MAX - alignment)) return NULL; // overflow + size_t over_size = size + alignment; + +#if _WIN32 + // over-allocate and than re-allocate exactly at an aligned address in there. + // this may fail due to threads allocating at the same time so we + // retry this at most 3 times before giving up. + // (we can not decommit around the overallocation on Windows, because we can only + // free the original pointer, not one pointing inside the area) + int flags = MEM_RESERVE; + if (commit) flags |= MEM_COMMIT; + for (int tries = 0; tries < 3; tries++) { + // over-allocate to determine a virtual memory range + p = mi_os_mem_alloc(over_size, alignment, commit, false, is_large, stats); + if (p == NULL) return NULL; // error + if (((uintptr_t)p % alignment) == 0) { + // if p happens to be aligned, just decommit the left-over area + _mi_os_decommit((uint8_t*)p + size, over_size - size, stats); + break; + } + else { + // otherwise free and allocate at an aligned address in there + mi_os_mem_free(p, over_size, commit, stats); + void* aligned_p = mi_align_up_ptr(p, alignment); + p = mi_win_virtual_alloc(aligned_p, size, alignment, flags, false, allow_large, is_large); + if (p == aligned_p) break; // success! + if (p != NULL) { // should not happen? + mi_os_mem_free(p, size, commit, stats); + p = NULL; + } + } + } +#else + // overallocate... + p = mi_os_mem_alloc(over_size, alignment, commit, false, is_large, stats); + if (p == NULL) return NULL; + // and selectively unmap parts around the over-allocated area. + void* aligned_p = mi_align_up_ptr(p, alignment); + size_t pre_size = (uint8_t*)aligned_p - (uint8_t*)p; + size_t mid_size = _mi_align_up(size, _mi_os_page_size()); + size_t post_size = over_size - pre_size - mid_size; + mi_assert_internal(pre_size < over_size && post_size < over_size && mid_size >= size); + if (pre_size > 0) mi_os_mem_free(p, pre_size, commit, stats); + if (post_size > 0) mi_os_mem_free((uint8_t*)aligned_p + mid_size, post_size, commit, stats); + // we can return the aligned pointer on `mmap` systems + p = aligned_p; +#endif + } + + mi_assert_internal(p == NULL || (p != NULL && ((uintptr_t)p % alignment) == 0)); + return p; +} + +/* ----------------------------------------------------------- + OS API: alloc, free, alloc_aligned +----------------------------------------------------------- */ + +void* _mi_os_alloc(size_t size, mi_stats_t* tld_stats) { + UNUSED(tld_stats); + mi_stats_t* stats = &_mi_stats_main; + if (size == 0) return NULL; + size = _mi_os_good_alloc_size(size); + bool is_large = false; + return mi_os_mem_alloc(size, 0, true, false, &is_large, stats); +} + +void _mi_os_free_ex(void* p, size_t size, bool was_committed, mi_stats_t* tld_stats) { + UNUSED(tld_stats); + mi_stats_t* stats = &_mi_stats_main; + if (size == 0 || p == NULL) return; + size = _mi_os_good_alloc_size(size); + mi_os_mem_free(p, size, was_committed, stats); +} + +void _mi_os_free(void* p, size_t size, mi_stats_t* stats) { + _mi_os_free_ex(p, size, true, stats); +} + +void* _mi_os_alloc_aligned(size_t size, size_t alignment, bool commit, bool* large, mi_os_tld_t* tld) +{ + UNUSED(tld); + if (size == 0) return NULL; + size = _mi_os_good_alloc_size(size); + alignment = _mi_align_up(alignment, _mi_os_page_size()); + bool allow_large = false; + if (large != NULL) { + allow_large = *large; + *large = false; + } + return mi_os_mem_alloc_aligned(size, alignment, commit, allow_large, (large!=NULL?large:&allow_large), &_mi_stats_main /*tld->stats*/ ); +} + + + +/* ----------------------------------------------------------- + OS memory API: reset, commit, decommit, protect, unprotect. +----------------------------------------------------------- */ + + +// OS page align within a given area, either conservative (pages inside the area only), +// or not (straddling pages outside the area is possible) +static void* mi_os_page_align_areax(bool conservative, void* addr, size_t size, size_t* newsize) { + mi_assert(addr != NULL && size > 0); + if (newsize != NULL) *newsize = 0; + if (size == 0 || addr == NULL) return NULL; + + // page align conservatively within the range + void* start = (conservative ? mi_align_up_ptr(addr, _mi_os_page_size()) + : mi_align_down_ptr(addr, _mi_os_page_size())); + void* end = (conservative ? mi_align_down_ptr((uint8_t*)addr + size, _mi_os_page_size()) + : mi_align_up_ptr((uint8_t*)addr + size, _mi_os_page_size())); + ptrdiff_t diff = (uint8_t*)end - (uint8_t*)start; + if (diff <= 0) return NULL; + + mi_assert_internal((conservative && (size_t)diff <= size) || (!conservative && (size_t)diff >= size)); + if (newsize != NULL) *newsize = (size_t)diff; + return start; +} + +static void* mi_os_page_align_area_conservative(void* addr, size_t size, size_t* newsize) { + return mi_os_page_align_areax(true, addr, size, newsize); +} + +static void mi_mprotect_hint(int err) { +#if defined(MI_OS_USE_MMAP) && (MI_SECURE>=2) // guard page around every mimalloc page + if (err == ENOMEM) { + _mi_warning_message("the previous warning may have been caused by a low memory map limit.\n" + " On Linux this is controlled by the vm.max_map_count. For example:\n" + " > sudo sysctl -w vm.max_map_count=262144\n"); + } +#else + UNUSED(err); +#endif +} + +// Commit/Decommit memory. +// Usually commit is aligned liberal, while decommit is aligned conservative. +// (but not for the reset version where we want commit to be conservative as well) +static bool mi_os_commitx(void* addr, size_t size, bool commit, bool conservative, bool* is_zero, mi_stats_t* stats) { + // page align in the range, commit liberally, decommit conservative + if (is_zero != NULL) { *is_zero = false; } + size_t csize; + void* start = mi_os_page_align_areax(conservative, addr, size, &csize); + if (csize == 0) return true; // || _mi_os_is_huge_reserved(addr)) + int err = 0; + if (commit) { + _mi_stat_increase(&stats->committed, size); // use size for precise commit vs. decommit + _mi_stat_counter_increase(&stats->commit_calls, 1); + } + else { + _mi_stat_decrease(&stats->committed, size); + } + + #if defined(_WIN32) + if (commit) { + // if the memory was already committed, the call succeeds but it is not zero'd + // *is_zero = true; + void* p = VirtualAlloc(start, csize, MEM_COMMIT, PAGE_READWRITE); + err = (p == start ? 0 : GetLastError()); + } + else { + BOOL ok = VirtualFree(start, csize, MEM_DECOMMIT); + err = (ok ? 0 : GetLastError()); + } + #elif defined(__wasi__) + // WebAssembly guests can't control memory protection + #elif defined(MAP_FIXED) + if (!commit) { + // use mmap with MAP_FIXED to discard the existing memory (and reduce commit charge) + void* p = mmap(start, csize, PROT_NONE, (MAP_FIXED | MAP_PRIVATE | MAP_ANONYMOUS | MAP_NORESERVE), -1, 0); + if (p != start) { err = errno; } + } + else { + // for commit, just change the protection + err = mprotect(start, csize, (PROT_READ | PROT_WRITE)); + if (err != 0) { err = errno; } + } + #else + err = mprotect(start, csize, (commit ? (PROT_READ | PROT_WRITE) : PROT_NONE)); + if (err != 0) { err = errno; } + #endif + if (err != 0) { + _mi_warning_message("%s error: start: %p, csize: 0x%x, err: %i\n", commit ? "commit" : "decommit", start, csize, err); + mi_mprotect_hint(err); + } + mi_assert_internal(err == 0); + return (err == 0); +} + +bool _mi_os_commit(void* addr, size_t size, bool* is_zero, mi_stats_t* tld_stats) { + UNUSED(tld_stats); + mi_stats_t* stats = &_mi_stats_main; + return mi_os_commitx(addr, size, true, false /* liberal */, is_zero, stats); +} + +bool _mi_os_decommit(void* addr, size_t size, mi_stats_t* tld_stats) { + UNUSED(tld_stats); + mi_stats_t* stats = &_mi_stats_main; + bool is_zero; + return mi_os_commitx(addr, size, false, true /* conservative */, &is_zero, stats); +} + +static bool mi_os_commit_unreset(void* addr, size_t size, bool* is_zero, mi_stats_t* stats) { + return mi_os_commitx(addr, size, true, true /* conservative */, is_zero, stats); +} + +// Signal to the OS that the address range is no longer in use +// but may be used later again. This will release physical memory +// pages and reduce swapping while keeping the memory committed. +// We page align to a conservative area inside the range to reset. +static bool mi_os_resetx(void* addr, size_t size, bool reset, mi_stats_t* stats) { + // page align conservatively within the range + size_t csize; + void* start = mi_os_page_align_area_conservative(addr, size, &csize); + if (csize == 0) return true; // || _mi_os_is_huge_reserved(addr) + if (reset) _mi_stat_increase(&stats->reset, csize); + else _mi_stat_decrease(&stats->reset, csize); + if (!reset) return true; // nothing to do on unreset! + + #if (MI_DEBUG>1) + if (MI_SECURE==0) { + memset(start, 0, csize); // pretend it is eagerly reset + } + #endif + +#if defined(_WIN32) + // Testing shows that for us (on `malloc-large`) MEM_RESET is 2x faster than DiscardVirtualMemory + void* p = VirtualAlloc(start, csize, MEM_RESET, PAGE_READWRITE); + mi_assert_internal(p == start); + #if 1 + if (p == start && start != NULL) { + VirtualUnlock(start,csize); // VirtualUnlock after MEM_RESET removes the memory from the working set + } + #endif + if (p != start) return false; +#else +#if defined(MADV_FREE) + static _Atomic(uintptr_t) advice = ATOMIC_VAR_INIT(MADV_FREE); + int err = madvise(start, csize, (int)mi_atomic_load_relaxed(&advice)); + if (err != 0 && errno == EINVAL && advice == MADV_FREE) { + // if MADV_FREE is not supported, fall back to MADV_DONTNEED from now on + mi_atomic_store_release(&advice, (uintptr_t)MADV_DONTNEED); + err = madvise(start, csize, MADV_DONTNEED); + } +#elif defined(__wasi__) + int err = 0; +#else + int err = madvise(start, csize, MADV_DONTNEED); +#endif + if (err != 0) { + _mi_warning_message("madvise reset error: start: %p, csize: 0x%x, errno: %i\n", start, csize, errno); + } + //mi_assert(err == 0); + if (err != 0) return false; +#endif + return true; +} + +// Signal to the OS that the address range is no longer in use +// but may be used later again. This will release physical memory +// pages and reduce swapping while keeping the memory committed. +// We page align to a conservative area inside the range to reset. +bool _mi_os_reset(void* addr, size_t size, mi_stats_t* tld_stats) { + UNUSED(tld_stats); + mi_stats_t* stats = &_mi_stats_main; + if (mi_option_is_enabled(mi_option_reset_decommits)) { + return _mi_os_decommit(addr, size, stats); + } + else { + return mi_os_resetx(addr, size, true, stats); + } +} + +bool _mi_os_unreset(void* addr, size_t size, bool* is_zero, mi_stats_t* tld_stats) { + UNUSED(tld_stats); + mi_stats_t* stats = &_mi_stats_main; + if (mi_option_is_enabled(mi_option_reset_decommits)) { + return mi_os_commit_unreset(addr, size, is_zero, stats); // re-commit it (conservatively!) + } + else { + *is_zero = false; + return mi_os_resetx(addr, size, false, stats); + } +} + + +// Protect a region in memory to be not accessible. +static bool mi_os_protectx(void* addr, size_t size, bool protect) { + // page align conservatively within the range + size_t csize = 0; + void* start = mi_os_page_align_area_conservative(addr, size, &csize); + if (csize == 0) return false; + /* + if (_mi_os_is_huge_reserved(addr)) { + _mi_warning_message("cannot mprotect memory allocated in huge OS pages\n"); + } + */ + int err = 0; +#ifdef _WIN32 + DWORD oldprotect = 0; + BOOL ok = VirtualProtect(start, csize, protect ? PAGE_NOACCESS : PAGE_READWRITE, &oldprotect); + err = (ok ? 0 : GetLastError()); +#elif defined(__wasi__) + err = 0; +#else + err = mprotect(start, csize, protect ? PROT_NONE : (PROT_READ | PROT_WRITE)); + if (err != 0) { err = errno; } +#endif + if (err != 0) { + _mi_warning_message("mprotect error: start: %p, csize: 0x%x, err: %i\n", start, csize, err); + mi_mprotect_hint(err); + } + return (err == 0); +} + +bool _mi_os_protect(void* addr, size_t size) { + return mi_os_protectx(addr, size, true); +} + +bool _mi_os_unprotect(void* addr, size_t size) { + return mi_os_protectx(addr, size, false); +} + + + +bool _mi_os_shrink(void* p, size_t oldsize, size_t newsize, mi_stats_t* stats) { + // page align conservatively within the range + mi_assert_internal(oldsize > newsize && p != NULL); + if (oldsize < newsize || p == NULL) return false; + if (oldsize == newsize) return true; + + // oldsize and newsize should be page aligned or we cannot shrink precisely + void* addr = (uint8_t*)p + newsize; + size_t size = 0; + void* start = mi_os_page_align_area_conservative(addr, oldsize - newsize, &size); + if (size == 0 || start != addr) return false; + +#ifdef _WIN32 + // we cannot shrink on windows, but we can decommit + return _mi_os_decommit(start, size, stats); +#else + return mi_os_mem_free(start, size, true, stats); +#endif +} + + +/* ---------------------------------------------------------------------------- +Support for allocating huge OS pages (1Gib) that are reserved up-front +and possibly associated with a specific NUMA node. (use `numa_node>=0`) +-----------------------------------------------------------------------------*/ +#define MI_HUGE_OS_PAGE_SIZE (GiB) + +#if defined(_WIN32) && (MI_INTPTR_SIZE >= 8) +static void* mi_os_alloc_huge_os_pagesx(void* addr, size_t size, int numa_node) +{ + mi_assert_internal(size%GiB == 0); + mi_assert_internal(addr != NULL); + const DWORD flags = MEM_LARGE_PAGES | MEM_COMMIT | MEM_RESERVE; + + mi_win_enable_large_os_pages(); + + #if defined(MEM_EXTENDED_PARAMETER_TYPE_BITS) + MEM_EXTENDED_PARAMETER params[3] = { {{0,0},{0}},{{0,0},{0}},{{0,0},{0}} }; + // on modern Windows try use NtAllocateVirtualMemoryEx for 1GiB huge pages + static bool mi_huge_pages_available = true; + if (pNtAllocateVirtualMemoryEx != NULL && mi_huge_pages_available) { + #ifndef MEM_EXTENDED_PARAMETER_NONPAGED_HUGE + #define MEM_EXTENDED_PARAMETER_NONPAGED_HUGE (0x10) + #endif + params[0].Type = 5; // == MemExtendedParameterAttributeFlags; + params[0].ULong64 = MEM_EXTENDED_PARAMETER_NONPAGED_HUGE; + ULONG param_count = 1; + if (numa_node >= 0) { + param_count++; + params[1].Type = MemExtendedParameterNumaNode; + params[1].ULong = (unsigned)numa_node; + } + SIZE_T psize = size; + void* base = addr; + NTSTATUS err = (*pNtAllocateVirtualMemoryEx)(GetCurrentProcess(), &base, &psize, flags, PAGE_READWRITE, params, param_count); + if (err == 0 && base != NULL) { + return base; + } + else { + // fall back to regular large pages + mi_huge_pages_available = false; // don't try further huge pages + _mi_warning_message("unable to allocate using huge (1gb) pages, trying large (2mb) pages instead (status 0x%lx)\n", err); + } + } + // on modern Windows try use VirtualAlloc2 for numa aware large OS page allocation + if (pVirtualAlloc2 != NULL && numa_node >= 0) { + params[0].Type = MemExtendedParameterNumaNode; + params[0].ULong = (unsigned)numa_node; + return (*pVirtualAlloc2)(GetCurrentProcess(), addr, size, flags, PAGE_READWRITE, params, 1); + } + #else + UNUSED(numa_node); + #endif + // otherwise use regular virtual alloc on older windows + return VirtualAlloc(addr, size, flags, PAGE_READWRITE); +} + +#elif defined(MI_OS_USE_MMAP) && (MI_INTPTR_SIZE >= 8) && !defined(__HAIKU__) +#include +#ifndef MPOL_PREFERRED +#define MPOL_PREFERRED 1 +#endif +#if defined(SYS_mbind) +static long mi_os_mbind(void* start, unsigned long len, unsigned long mode, const unsigned long* nmask, unsigned long maxnode, unsigned flags) { + return syscall(SYS_mbind, start, len, mode, nmask, maxnode, flags); +} +#else +static long mi_os_mbind(void* start, unsigned long len, unsigned long mode, const unsigned long* nmask, unsigned long maxnode, unsigned flags) { + UNUSED(start); UNUSED(len); UNUSED(mode); UNUSED(nmask); UNUSED(maxnode); UNUSED(flags); + return 0; +} +#endif +static void* mi_os_alloc_huge_os_pagesx(void* addr, size_t size, int numa_node) { + mi_assert_internal(size%GiB == 0); + bool is_large = true; + void* p = mi_unix_mmap(addr, size, MI_SEGMENT_SIZE, PROT_READ | PROT_WRITE, true, true, &is_large); + if (p == NULL) return NULL; + if (numa_node >= 0 && numa_node < 8*MI_INTPTR_SIZE) { // at most 64 nodes + uintptr_t numa_mask = (1UL << numa_node); + // TODO: does `mbind` work correctly for huge OS pages? should we + // use `set_mempolicy` before calling mmap instead? + // see: + long err = mi_os_mbind(p, size, MPOL_PREFERRED, &numa_mask, 8*MI_INTPTR_SIZE, 0); + if (err != 0) { + _mi_warning_message("failed to bind huge (1gb) pages to numa node %d: %s\n", numa_node, strerror(errno)); + } + } + return p; +} +#else +static void* mi_os_alloc_huge_os_pagesx(void* addr, size_t size, int numa_node) { + UNUSED(addr); UNUSED(size); UNUSED(numa_node); + return NULL; +} +#endif + +#if (MI_INTPTR_SIZE >= 8) +// To ensure proper alignment, use our own area for huge OS pages +static mi_decl_cache_align _Atomic(uintptr_t) mi_huge_start; // = 0 + +// Claim an aligned address range for huge pages +static uint8_t* mi_os_claim_huge_pages(size_t pages, size_t* total_size) { + if (total_size != NULL) *total_size = 0; + const size_t size = pages * MI_HUGE_OS_PAGE_SIZE; + + uintptr_t start = 0; + uintptr_t end = 0; + uintptr_t huge_start = mi_atomic_load_relaxed(&mi_huge_start); + do { + start = huge_start; + if (start == 0) { + // Initialize the start address after the 32TiB area + start = ((uintptr_t)32 << 40); // 32TiB virtual start address +#if (MI_SECURE>0 || MI_DEBUG==0) // security: randomize start of huge pages unless in debug mode + uintptr_t r = _mi_heap_random_next(mi_get_default_heap()); + start = start + ((uintptr_t)MI_HUGE_OS_PAGE_SIZE * ((r>>17) & 0x0FFF)); // (randomly 12bits)*1GiB == between 0 to 4TiB +#endif + } + end = start + size; + mi_assert_internal(end % MI_SEGMENT_SIZE == 0); + } while (!mi_atomic_cas_strong_acq_rel(&mi_huge_start, &huge_start, end)); + + if (total_size != NULL) *total_size = size; + return (uint8_t*)start; +} +#else +static uint8_t* mi_os_claim_huge_pages(size_t pages, size_t* total_size) { + UNUSED(pages); + if (total_size != NULL) *total_size = 0; + return NULL; +} +#endif + +// Allocate MI_SEGMENT_SIZE aligned huge pages +void* _mi_os_alloc_huge_os_pages(size_t pages, int numa_node, mi_msecs_t max_msecs, size_t* pages_reserved, size_t* psize) { + if (psize != NULL) *psize = 0; + if (pages_reserved != NULL) *pages_reserved = 0; + size_t size = 0; + uint8_t* start = mi_os_claim_huge_pages(pages, &size); + if (start == NULL) return NULL; // or 32-bit systems + + // Allocate one page at the time but try to place them contiguously + // We allocate one page at the time to be able to abort if it takes too long + // or to at least allocate as many as available on the system. + mi_msecs_t start_t = _mi_clock_start(); + size_t page; + for (page = 0; page < pages; page++) { + // allocate a page + void* addr = start + (page * MI_HUGE_OS_PAGE_SIZE); + void* p = mi_os_alloc_huge_os_pagesx(addr, MI_HUGE_OS_PAGE_SIZE, numa_node); + + // Did we succeed at a contiguous address? + if (p != addr) { + // no success, issue a warning and break + if (p != NULL) { + _mi_warning_message("could not allocate contiguous huge page %zu at %p\n", page, addr); + _mi_os_free(p, MI_HUGE_OS_PAGE_SIZE, &_mi_stats_main); + } + break; + } + + // success, record it + _mi_stat_increase(&_mi_stats_main.committed, MI_HUGE_OS_PAGE_SIZE); + _mi_stat_increase(&_mi_stats_main.reserved, MI_HUGE_OS_PAGE_SIZE); + + // check for timeout + if (max_msecs > 0) { + mi_msecs_t elapsed = _mi_clock_end(start_t); + if (page >= 1) { + mi_msecs_t estimate = ((elapsed / (page+1)) * pages); + if (estimate > 2*max_msecs) { // seems like we are going to timeout, break + elapsed = max_msecs + 1; + } + } + if (elapsed > max_msecs) { + _mi_warning_message("huge page allocation timed out\n"); + break; + } + } + } + mi_assert_internal(page*MI_HUGE_OS_PAGE_SIZE <= size); + if (pages_reserved != NULL) *pages_reserved = page; + if (psize != NULL) *psize = page * MI_HUGE_OS_PAGE_SIZE; + return (page == 0 ? NULL : start); +} + +// free every huge page in a range individually (as we allocated per page) +// note: needed with VirtualAlloc but could potentially be done in one go on mmap'd systems. +void _mi_os_free_huge_pages(void* p, size_t size, mi_stats_t* stats) { + if (p==NULL || size==0) return; + uint8_t* base = (uint8_t*)p; + while (size >= MI_HUGE_OS_PAGE_SIZE) { + _mi_os_free(base, MI_HUGE_OS_PAGE_SIZE, stats); + size -= MI_HUGE_OS_PAGE_SIZE; + } +} + +/* ---------------------------------------------------------------------------- +Support NUMA aware allocation +-----------------------------------------------------------------------------*/ +#ifdef _WIN32 +static size_t mi_os_numa_nodex() { + USHORT numa_node = 0; + if (pGetCurrentProcessorNumberEx != NULL && pGetNumaProcessorNodeEx != NULL) { + // Extended API is supported + PROCESSOR_NUMBER pnum; + (*pGetCurrentProcessorNumberEx)(&pnum); + USHORT nnode = 0; + BOOL ok = (*pGetNumaProcessorNodeEx)(&pnum, &nnode); + if (ok) numa_node = nnode; + } + else { + // Vista or earlier, use older API that is limited to 64 processors. Issue #277 + DWORD pnum = GetCurrentProcessorNumber(); + UCHAR nnode = 0; + BOOL ok = GetNumaProcessorNode((UCHAR)pnum, &nnode); + if (ok) numa_node = nnode; + } + return numa_node; +} + +static size_t mi_os_numa_node_countx(void) { + ULONG numa_max = 0; + GetNumaHighestNodeNumber(&numa_max); + // find the highest node number that has actual processors assigned to it. Issue #282 + while(numa_max > 0) { + if (pGetNumaNodeProcessorMaskEx != NULL) { + // Extended API is supported + GROUP_AFFINITY affinity; + if ((*pGetNumaNodeProcessorMaskEx)((USHORT)numa_max, &affinity)) { + if (affinity.Mask != 0) break; // found the maximum non-empty node + } + } + else { + // Vista or earlier, use older API that is limited to 64 processors. + ULONGLONG mask; + if (GetNumaNodeProcessorMask((UCHAR)numa_max, &mask)) { + if (mask != 0) break; // found the maximum non-empty node + }; + } + // max node was invalid or had no processor assigned, try again + numa_max--; + } + return ((size_t)numa_max + 1); +} +#elif defined(__linux__) +#include // getcpu +#include // access + +static size_t mi_os_numa_nodex(void) { +#ifdef SYS_getcpu + unsigned long node = 0; + unsigned long ncpu = 0; + long err = syscall(SYS_getcpu, &ncpu, &node, NULL); + if (err != 0) return 0; + return node; +#else + return 0; +#endif +} +static size_t mi_os_numa_node_countx(void) { + char buf[128]; + unsigned node = 0; + for(node = 0; node < 256; node++) { + // enumerate node entries -- todo: it there a more efficient way to do this? (but ensure there is no allocation) + snprintf(buf, 127, "/sys/devices/system/node/node%u", node + 1); + if (access(buf,R_OK) != 0) break; + } + return (node+1); +} +#else +static size_t mi_os_numa_nodex(void) { + return 0; +} +static size_t mi_os_numa_node_countx(void) { + return 1; +} +#endif + +size_t _mi_numa_node_count = 0; // cache the node count + +size_t _mi_os_numa_node_count_get(void) { + if (mi_unlikely(_mi_numa_node_count <= 0)) { + long ncount = mi_option_get(mi_option_use_numa_nodes); // given explicitly? + if (ncount <= 0) ncount = (long)mi_os_numa_node_countx(); // or detect dynamically + _mi_numa_node_count = (size_t)(ncount <= 0 ? 1 : ncount); + _mi_verbose_message("using %zd numa regions\n", _mi_numa_node_count); + } + mi_assert_internal(_mi_numa_node_count >= 1); + return _mi_numa_node_count; +} + +int _mi_os_numa_node_get(mi_os_tld_t* tld) { + UNUSED(tld); + size_t numa_count = _mi_os_numa_node_count(); + if (numa_count<=1) return 0; // optimize on single numa node systems: always node 0 + // never more than the node count and >= 0 + size_t numa_node = mi_os_numa_nodex(); + if (numa_node >= numa_count) { numa_node = numa_node % numa_count; } + return (int)numa_node; +} diff --git a/kotlin-native/runtime/src/mimalloc/c/page-queue.c b/kotlin-native/runtime/src/mimalloc/c/page-queue.c new file mode 100644 index 00000000000..fc1522a078b --- /dev/null +++ b/kotlin-native/runtime/src/mimalloc/c/page-queue.c @@ -0,0 +1,368 @@ +/*---------------------------------------------------------------------------- +Copyright (c) 2018, Microsoft Research, Daan Leijen +This is free software; you can redistribute it and/or modify it under the +terms of the MIT license. A copy of the license can be found in the file +"licenses/third_party/mimalloc_LICENSE.txt" at the root of this distribution. +-----------------------------------------------------------------------------*/ + +/* ----------------------------------------------------------- + Definition of page queues for each block size +----------------------------------------------------------- */ + +#ifndef MI_IN_PAGE_C +#error "this file should be included from 'page.c'" +#endif + +/* ----------------------------------------------------------- + Minimal alignment in machine words (i.e. `sizeof(void*)`) +----------------------------------------------------------- */ + +#if (MI_MAX_ALIGN_SIZE > 4*MI_INTPTR_SIZE) + #error "define alignment for more than 4x word size for this platform" +#elif (MI_MAX_ALIGN_SIZE > 2*MI_INTPTR_SIZE) + #define MI_ALIGN4W // 4 machine words minimal alignment +#elif (MI_MAX_ALIGN_SIZE > MI_INTPTR_SIZE) + #define MI_ALIGN2W // 2 machine words minimal alignment +#else + // ok, default alignment is 1 word +#endif + + +/* ----------------------------------------------------------- + Queue query +----------------------------------------------------------- */ + + +static inline bool mi_page_queue_is_huge(const mi_page_queue_t* pq) { + return (pq->block_size == (MI_LARGE_OBJ_SIZE_MAX+sizeof(uintptr_t))); +} + +static inline bool mi_page_queue_is_full(const mi_page_queue_t* pq) { + return (pq->block_size == (MI_LARGE_OBJ_SIZE_MAX+(2*sizeof(uintptr_t)))); +} + +static inline bool mi_page_queue_is_special(const mi_page_queue_t* pq) { + return (pq->block_size > MI_LARGE_OBJ_SIZE_MAX); +} + +/* ----------------------------------------------------------- + Bins +----------------------------------------------------------- */ + +// Bit scan reverse: return the index of the highest bit. +static inline uint8_t mi_bsr32(uint32_t x); + +#if defined(_MSC_VER) +#include +static inline uint8_t mi_bsr32(uint32_t x) { + uint32_t idx; + _BitScanReverse((DWORD*)&idx, x); + return (uint8_t)idx; +} +#elif defined(__GNUC__) || defined(__clang__) +static inline uint8_t mi_bsr32(uint32_t x) { + return (31 - __builtin_clz(x)); +} +#else +static inline uint8_t mi_bsr32(uint32_t x) { + // de Bruijn multiplication, see + static const uint8_t debruijn[32] = { + 31, 0, 22, 1, 28, 23, 18, 2, 29, 26, 24, 10, 19, 7, 3, 12, + 30, 21, 27, 17, 25, 9, 6, 11, 20, 16, 8, 5, 15, 4, 14, 13, + }; + x |= x >> 1; + x |= x >> 2; + x |= x >> 4; + x |= x >> 8; + x |= x >> 16; + x++; + return debruijn[(x*0x076be629) >> 27]; +} +#endif + +// Bit scan reverse: return the index of the highest bit. +uint8_t _mi_bsr(uintptr_t x) { + if (x == 0) return 0; +#if MI_INTPTR_SIZE==8 + uint32_t hi = (x >> 32); + return (hi == 0 ? mi_bsr32((uint32_t)x) : 32 + mi_bsr32(hi)); +#elif MI_INTPTR_SIZE==4 + return mi_bsr32(x); +#else +# error "define bsr for non-32 or 64-bit platforms" +#endif +} + +// Return the bin for a given field size. +// Returns MI_BIN_HUGE if the size is too large. +// We use `wsize` for the size in "machine word sizes", +// i.e. byte size == `wsize*sizeof(void*)`. +extern inline uint8_t _mi_bin(size_t size) { + size_t wsize = _mi_wsize_from_size(size); + uint8_t bin; + if (wsize <= 1) { + bin = 1; + } + #if defined(MI_ALIGN4W) + else if (wsize <= 4) { + bin = (uint8_t)((wsize+1)&~1); // round to double word sizes + } + #elif defined(MI_ALIGN2W) + else if (wsize <= 8) { + bin = (uint8_t)((wsize+1)&~1); // round to double word sizes + } + #else + else if (wsize <= 8) { + bin = (uint8_t)wsize; + } + #endif + else if (wsize > MI_LARGE_OBJ_WSIZE_MAX) { + bin = MI_BIN_HUGE; + } + else { + #if defined(MI_ALIGN4W) + if (wsize <= 16) { wsize = (wsize+3)&~3; } // round to 4x word sizes + #endif + wsize--; + // find the highest bit + uint8_t b = mi_bsr32((uint32_t)wsize); + // and use the top 3 bits to determine the bin (~12.5% worst internal fragmentation). + // - adjust with 3 because we use do not round the first 8 sizes + // which each get an exact bin + bin = ((b << 2) + (uint8_t)((wsize >> (b - 2)) & 0x03)) - 3; + mi_assert_internal(bin < MI_BIN_HUGE); + } + mi_assert_internal(bin > 0 && bin <= MI_BIN_HUGE); + return bin; +} + + + +/* ----------------------------------------------------------- + Queue of pages with free blocks +----------------------------------------------------------- */ + +size_t _mi_bin_size(uint8_t bin) { + return _mi_heap_empty.pages[bin].block_size; +} + +// Good size for allocation +size_t mi_good_size(size_t size) mi_attr_noexcept { + if (size <= MI_LARGE_OBJ_SIZE_MAX) { + return _mi_bin_size(_mi_bin(size)); + } + else { + return _mi_align_up(size,_mi_os_page_size()); + } +} + +#if (MI_DEBUG>1) +static bool mi_page_queue_contains(mi_page_queue_t* queue, const mi_page_t* page) { + mi_assert_internal(page != NULL); + mi_page_t* list = queue->first; + while (list != NULL) { + mi_assert_internal(list->next == NULL || list->next->prev == list); + mi_assert_internal(list->prev == NULL || list->prev->next == list); + if (list == page) break; + list = list->next; + } + return (list == page); +} + +#endif + +#if (MI_DEBUG>1) +static bool mi_heap_contains_queue(const mi_heap_t* heap, const mi_page_queue_t* pq) { + return (pq >= &heap->pages[0] && pq <= &heap->pages[MI_BIN_FULL]); +} +#endif + +static mi_page_queue_t* mi_page_queue_of(const mi_page_t* page) { + uint8_t bin = (mi_page_is_in_full(page) ? MI_BIN_FULL : _mi_bin(page->xblock_size)); + mi_heap_t* heap = mi_page_heap(page); + mi_assert_internal(heap != NULL && bin <= MI_BIN_FULL); + mi_page_queue_t* pq = &heap->pages[bin]; + mi_assert_internal(bin >= MI_BIN_HUGE || page->xblock_size == pq->block_size); + mi_assert_expensive(mi_page_queue_contains(pq, page)); + return pq; +} + +static mi_page_queue_t* mi_heap_page_queue_of(mi_heap_t* heap, const mi_page_t* page) { + uint8_t bin = (mi_page_is_in_full(page) ? MI_BIN_FULL : _mi_bin(page->xblock_size)); + mi_assert_internal(bin <= MI_BIN_FULL); + mi_page_queue_t* pq = &heap->pages[bin]; + mi_assert_internal(mi_page_is_in_full(page) || page->xblock_size == pq->block_size); + return pq; +} + +// The current small page array is for efficiency and for each +// small size (up to 256) it points directly to the page for that +// size without having to compute the bin. This means when the +// current free page queue is updated for a small bin, we need to update a +// range of entries in `_mi_page_small_free`. +static inline void mi_heap_queue_first_update(mi_heap_t* heap, const mi_page_queue_t* pq) { + mi_assert_internal(mi_heap_contains_queue(heap,pq)); + size_t size = pq->block_size; + if (size > MI_SMALL_SIZE_MAX) return; + + mi_page_t* page = pq->first; + if (pq->first == NULL) page = (mi_page_t*)&_mi_page_empty; + + // find index in the right direct page array + size_t start; + size_t idx = _mi_wsize_from_size(size); + mi_page_t** pages_free = heap->pages_free_direct; + + if (pages_free[idx] == page) return; // already set + + // find start slot + if (idx<=1) { + start = 0; + } + else { + // find previous size; due to minimal alignment upto 3 previous bins may need to be skipped + uint8_t bin = _mi_bin(size); + const mi_page_queue_t* prev = pq - 1; + while( bin == _mi_bin(prev->block_size) && prev > &heap->pages[0]) { + prev--; + } + start = 1 + _mi_wsize_from_size(prev->block_size); + if (start > idx) start = idx; + } + + // set size range to the right page + mi_assert(start <= idx); + for (size_t sz = start; sz <= idx; sz++) { + pages_free[sz] = page; + } +} + +/* +static bool mi_page_queue_is_empty(mi_page_queue_t* queue) { + return (queue->first == NULL); +} +*/ + +static void mi_page_queue_remove(mi_page_queue_t* queue, mi_page_t* page) { + mi_assert_internal(page != NULL); + mi_assert_expensive(mi_page_queue_contains(queue, page)); + mi_assert_internal(page->xblock_size == queue->block_size || (page->xblock_size > MI_LARGE_OBJ_SIZE_MAX && mi_page_queue_is_huge(queue)) || (mi_page_is_in_full(page) && mi_page_queue_is_full(queue))); + mi_heap_t* heap = mi_page_heap(page); + if (page->prev != NULL) page->prev->next = page->next; + if (page->next != NULL) page->next->prev = page->prev; + if (page == queue->last) queue->last = page->prev; + if (page == queue->first) { + queue->first = page->next; + // update first + mi_assert_internal(mi_heap_contains_queue(heap, queue)); + mi_heap_queue_first_update(heap,queue); + } + heap->page_count--; + page->next = NULL; + page->prev = NULL; + // mi_atomic_store_ptr_release(mi_atomic_cast(void*, &page->heap), NULL); + mi_page_set_in_full(page,false); +} + + +static void mi_page_queue_push(mi_heap_t* heap, mi_page_queue_t* queue, mi_page_t* page) { + mi_assert_internal(mi_page_heap(page) == heap); + mi_assert_internal(!mi_page_queue_contains(queue, page)); + mi_assert_internal(_mi_page_segment(page)->page_kind != MI_PAGE_HUGE); + mi_assert_internal(page->xblock_size == queue->block_size || + (page->xblock_size > MI_LARGE_OBJ_SIZE_MAX && mi_page_queue_is_huge(queue)) || + (mi_page_is_in_full(page) && mi_page_queue_is_full(queue))); + + mi_page_set_in_full(page, mi_page_queue_is_full(queue)); + // mi_atomic_store_ptr_release(mi_atomic_cast(void*, &page->heap), heap); + page->next = queue->first; + page->prev = NULL; + if (queue->first != NULL) { + mi_assert_internal(queue->first->prev == NULL); + queue->first->prev = page; + queue->first = page; + } + else { + queue->first = queue->last = page; + } + + // update direct + mi_heap_queue_first_update(heap, queue); + heap->page_count++; +} + + +static void mi_page_queue_enqueue_from(mi_page_queue_t* to, mi_page_queue_t* from, mi_page_t* page) { + mi_assert_internal(page != NULL); + mi_assert_expensive(mi_page_queue_contains(from, page)); + mi_assert_expensive(!mi_page_queue_contains(to, page)); + mi_assert_internal((page->xblock_size == to->block_size && page->xblock_size == from->block_size) || + (page->xblock_size == to->block_size && mi_page_queue_is_full(from)) || + (page->xblock_size == from->block_size && mi_page_queue_is_full(to)) || + (page->xblock_size > MI_LARGE_OBJ_SIZE_MAX && mi_page_queue_is_huge(to)) || + (page->xblock_size > MI_LARGE_OBJ_SIZE_MAX && mi_page_queue_is_full(to))); + + mi_heap_t* heap = mi_page_heap(page); + if (page->prev != NULL) page->prev->next = page->next; + if (page->next != NULL) page->next->prev = page->prev; + if (page == from->last) from->last = page->prev; + if (page == from->first) { + from->first = page->next; + // update first + mi_assert_internal(mi_heap_contains_queue(heap, from)); + mi_heap_queue_first_update(heap, from); + } + + page->prev = to->last; + page->next = NULL; + if (to->last != NULL) { + mi_assert_internal(heap == mi_page_heap(to->last)); + to->last->next = page; + to->last = page; + } + else { + to->first = page; + to->last = page; + mi_heap_queue_first_update(heap, to); + } + + mi_page_set_in_full(page, mi_page_queue_is_full(to)); +} + +// Only called from `mi_heap_absorb`. +size_t _mi_page_queue_append(mi_heap_t* heap, mi_page_queue_t* pq, mi_page_queue_t* append) { + mi_assert_internal(mi_heap_contains_queue(heap,pq)); + mi_assert_internal(pq->block_size == append->block_size); + + if (append->first==NULL) return 0; + + // set append pages to new heap and count + size_t count = 0; + for (mi_page_t* page = append->first; page != NULL; page = page->next) { + // inline `mi_page_set_heap` to avoid wrong assertion during absorption; + // in this case it is ok to be delayed freeing since both "to" and "from" heap are still alive. + mi_atomic_store_release(&page->xheap, (uintptr_t)heap); + // set the flag to delayed free (not overriding NEVER_DELAYED_FREE) which has as a + // side effect that it spins until any DELAYED_FREEING is finished. This ensures + // that after appending only the new heap will be used for delayed free operations. + _mi_page_use_delayed_free(page, MI_USE_DELAYED_FREE, false); + count++; + } + + if (pq->last==NULL) { + // take over afresh + mi_assert_internal(pq->first==NULL); + pq->first = append->first; + pq->last = append->last; + mi_heap_queue_first_update(heap, pq); + } + else { + // append to end + mi_assert_internal(pq->last!=NULL); + mi_assert_internal(append->first!=NULL); + pq->last->next = append->first; + append->first->prev = pq->last; + pq->last = append->last; + } + return count; +} diff --git a/kotlin-native/runtime/src/mimalloc/c/page.c b/kotlin-native/runtime/src/mimalloc/c/page.c new file mode 100644 index 00000000000..d0cabfa4214 --- /dev/null +++ b/kotlin-native/runtime/src/mimalloc/c/page.c @@ -0,0 +1,843 @@ +/*---------------------------------------------------------------------------- +Copyright (c) 2018, Microsoft Research, Daan Leijen +This is free software; you can redistribute it and/or modify it under the +terms of the MIT license. A copy of the license can be found in the file +"licenses/third_party/mimalloc_LICENSE.txt" at the root of this distribution. +-----------------------------------------------------------------------------*/ + +/* ----------------------------------------------------------- + The core of the allocator. Every segment contains + pages of a {certain block size. The main function + exported is `mi_malloc_generic`. +----------------------------------------------------------- */ + +#include "mimalloc.h" +#include "mimalloc-internal.h" +#include "mimalloc-atomic.h" + +/* ----------------------------------------------------------- + Definition of page queues for each block size +----------------------------------------------------------- */ + +#define MI_IN_PAGE_C +#include "page-queue.c" +#undef MI_IN_PAGE_C + + +/* ----------------------------------------------------------- + Page helpers +----------------------------------------------------------- */ + +// Index a block in a page +static inline mi_block_t* mi_page_block_at(const mi_page_t* page, void* page_start, size_t block_size, size_t i) { + UNUSED(page); + mi_assert_internal(page != NULL); + mi_assert_internal(i <= page->reserved); + return (mi_block_t*)((uint8_t*)page_start + (i * block_size)); +} + +static void mi_page_init(mi_heap_t* heap, mi_page_t* page, size_t size, mi_tld_t* tld); +static void mi_page_extend_free(mi_heap_t* heap, mi_page_t* page, mi_tld_t* tld); + +#if (MI_DEBUG>=3) +static size_t mi_page_list_count(mi_page_t* page, mi_block_t* head) { + size_t count = 0; + while (head != NULL) { + mi_assert_internal(page == _mi_ptr_page(head)); + count++; + head = mi_block_next(page, head); + } + return count; +} + +/* +// Start of the page available memory +static inline uint8_t* mi_page_area(const mi_page_t* page) { + return _mi_page_start(_mi_page_segment(page), page, NULL); +} +*/ + +static bool mi_page_list_is_valid(mi_page_t* page, mi_block_t* p) { + size_t psize; + uint8_t* page_area = _mi_page_start(_mi_page_segment(page), page, &psize); + mi_block_t* start = (mi_block_t*)page_area; + mi_block_t* end = (mi_block_t*)(page_area + psize); + while(p != NULL) { + if (p < start || p >= end) return false; + p = mi_block_next(page, p); + } + return true; +} + +static bool mi_page_is_valid_init(mi_page_t* page) { + mi_assert_internal(page->xblock_size > 0); + mi_assert_internal(page->used <= page->capacity); + mi_assert_internal(page->capacity <= page->reserved); + + const size_t bsize = mi_page_block_size(page); + mi_segment_t* segment = _mi_page_segment(page); + uint8_t* start = _mi_page_start(segment,page,NULL); + mi_assert_internal(start == _mi_segment_page_start(segment,page,bsize,NULL,NULL)); + //mi_assert_internal(start + page->capacity*page->block_size == page->top); + + mi_assert_internal(mi_page_list_is_valid(page,page->free)); + mi_assert_internal(mi_page_list_is_valid(page,page->local_free)); + + #if MI_DEBUG>3 // generally too expensive to check this + if (page->flags.is_zero) { + for(mi_block_t* block = page->free; block != NULL; mi_block_next(page,block)) { + mi_assert_expensive(mi_mem_is_zero(block + 1, page->block_size - sizeof(mi_block_t))); + } + } + #endif + + mi_block_t* tfree = mi_page_thread_free(page); + mi_assert_internal(mi_page_list_is_valid(page, tfree)); + //size_t tfree_count = mi_page_list_count(page, tfree); + //mi_assert_internal(tfree_count <= page->thread_freed + 1); + + size_t free_count = mi_page_list_count(page, page->free) + mi_page_list_count(page, page->local_free); + mi_assert_internal(page->used + free_count == page->capacity); + + return true; +} + +bool _mi_page_is_valid(mi_page_t* page) { + mi_assert_internal(mi_page_is_valid_init(page)); + #if MI_SECURE + mi_assert_internal(page->keys[0] != 0); + #endif + if (mi_page_heap(page)!=NULL) { + mi_segment_t* segment = _mi_page_segment(page); + mi_assert_internal(!_mi_process_is_initialized || segment->thread_id == mi_page_heap(page)->thread_id || segment->thread_id==0); + if (segment->page_kind != MI_PAGE_HUGE) { + mi_page_queue_t* pq = mi_page_queue_of(page); + mi_assert_internal(mi_page_queue_contains(pq, page)); + mi_assert_internal(pq->block_size==mi_page_block_size(page) || mi_page_block_size(page) > MI_LARGE_OBJ_SIZE_MAX || mi_page_is_in_full(page)); + mi_assert_internal(mi_heap_contains_queue(mi_page_heap(page),pq)); + } + } + return true; +} +#endif + +void _mi_page_use_delayed_free(mi_page_t* page, mi_delayed_t delay, bool override_never) { + mi_thread_free_t tfreex; + mi_delayed_t old_delay; + mi_thread_free_t tfree; + do { + tfree = mi_atomic_load_acquire(&page->xthread_free); // note: must acquire as we can break/repeat this loop and not do a CAS; + tfreex = mi_tf_set_delayed(tfree, delay); + old_delay = mi_tf_delayed(tfree); + if (mi_unlikely(old_delay == MI_DELAYED_FREEING)) { + mi_atomic_yield(); // delay until outstanding MI_DELAYED_FREEING are done. + // tfree = mi_tf_set_delayed(tfree, MI_NO_DELAYED_FREE); // will cause CAS to busy fail + } + else if (delay == old_delay) { + break; // avoid atomic operation if already equal + } + else if (!override_never && old_delay == MI_NEVER_DELAYED_FREE) { + break; // leave never-delayed flag set + } + } while ((old_delay == MI_DELAYED_FREEING) || + !mi_atomic_cas_weak_release(&page->xthread_free, &tfree, tfreex)); +} + +/* ----------------------------------------------------------- + Page collect the `local_free` and `thread_free` lists +----------------------------------------------------------- */ + +// Collect the local `thread_free` list using an atomic exchange. +// Note: The exchange must be done atomically as this is used right after +// moving to the full list in `mi_page_collect_ex` and we need to +// ensure that there was no race where the page became unfull just before the move. +static void _mi_page_thread_free_collect(mi_page_t* page) +{ + mi_block_t* head; + mi_thread_free_t tfreex; + mi_thread_free_t tfree = mi_atomic_load_relaxed(&page->xthread_free); + do { + head = mi_tf_block(tfree); + tfreex = mi_tf_set_block(tfree,NULL); + } while (!mi_atomic_cas_weak_acq_rel(&page->xthread_free, &tfree, tfreex)); + + // return if the list is empty + if (head == NULL) return; + + // find the tail -- also to get a proper count (without data races) + uint32_t max_count = page->capacity; // cannot collect more than capacity + uint32_t count = 1; + mi_block_t* tail = head; + mi_block_t* next; + while ((next = mi_block_next(page,tail)) != NULL && count <= max_count) { + count++; + tail = next; + } + // if `count > max_count` there was a memory corruption (possibly infinite list due to double multi-threaded free) + if (count > max_count) { + _mi_error_message(EFAULT, "corrupted thread-free list\n"); + return; // the thread-free items cannot be freed + } + + // and append the current local free list + mi_block_set_next(page,tail, page->local_free); + page->local_free = head; + + // update counts now + page->used -= count; +} + +void _mi_page_free_collect(mi_page_t* page, bool force) { + mi_assert_internal(page!=NULL); + + // collect the thread free list + if (force || mi_page_thread_free(page) != NULL) { // quick test to avoid an atomic operation + _mi_page_thread_free_collect(page); + } + + // and the local free list + if (page->local_free != NULL) { + if (mi_likely(page->free == NULL)) { + // usual case + page->free = page->local_free; + page->local_free = NULL; + page->is_zero = false; + } + else if (force) { + // append -- only on shutdown (force) as this is a linear operation + mi_block_t* tail = page->local_free; + mi_block_t* next; + while ((next = mi_block_next(page, tail)) != NULL) { + tail = next; + } + mi_block_set_next(page, tail, page->free); + page->free = page->local_free; + page->local_free = NULL; + page->is_zero = false; + } + } + + mi_assert_internal(!force || page->local_free == NULL); +} + + + +/* ----------------------------------------------------------- + Page fresh and retire +----------------------------------------------------------- */ + +// called from segments when reclaiming abandoned pages +void _mi_page_reclaim(mi_heap_t* heap, mi_page_t* page) { + mi_assert_expensive(mi_page_is_valid_init(page)); + mi_assert_internal(mi_page_heap(page) == heap); + mi_assert_internal(mi_page_thread_free_flag(page) != MI_NEVER_DELAYED_FREE); + mi_assert_internal(_mi_page_segment(page)->page_kind != MI_PAGE_HUGE); + mi_assert_internal(!page->is_reset); + // TODO: push on full queue immediately if it is full? + mi_page_queue_t* pq = mi_page_queue(heap, mi_page_block_size(page)); + mi_page_queue_push(heap, pq, page); + mi_assert_expensive(_mi_page_is_valid(page)); +} + +// allocate a fresh page from a segment +static mi_page_t* mi_page_fresh_alloc(mi_heap_t* heap, mi_page_queue_t* pq, size_t block_size) { + mi_assert_internal(pq==NULL||mi_heap_contains_queue(heap, pq)); + mi_assert_internal(pq==NULL||block_size == pq->block_size); + mi_page_t* page = _mi_segment_page_alloc(heap, block_size, &heap->tld->segments, &heap->tld->os); + if (page == NULL) { + // this may be out-of-memory, or an abandoned page was reclaimed (and in our queue) + return NULL; + } + // a fresh page was found, initialize it + mi_assert_internal(pq==NULL || _mi_page_segment(page)->page_kind != MI_PAGE_HUGE); + mi_page_init(heap, page, block_size, heap->tld); + _mi_stat_increase(&heap->tld->stats.pages, 1); + if (pq!=NULL) mi_page_queue_push(heap, pq, page); // huge pages use pq==NULL + mi_assert_expensive(_mi_page_is_valid(page)); + return page; +} + +// Get a fresh page to use +static mi_page_t* mi_page_fresh(mi_heap_t* heap, mi_page_queue_t* pq) { + mi_assert_internal(mi_heap_contains_queue(heap, pq)); + mi_page_t* page = mi_page_fresh_alloc(heap, pq, pq->block_size); + if (page==NULL) return NULL; + mi_assert_internal(pq->block_size==mi_page_block_size(page)); + mi_assert_internal(pq==mi_page_queue(heap, mi_page_block_size(page))); + return page; +} + +/* ----------------------------------------------------------- + Do any delayed frees + (put there by other threads if they deallocated in a full page) +----------------------------------------------------------- */ +void _mi_heap_delayed_free(mi_heap_t* heap) { + // take over the list (note: no atomic exchange since it is often NULL) + mi_block_t* block = mi_atomic_load_ptr_relaxed(mi_block_t, &heap->thread_delayed_free); + while (block != NULL && !mi_atomic_cas_ptr_weak_acq_rel(mi_block_t, &heap->thread_delayed_free, &block, NULL)) { /* nothing */ }; + + // and free them all + while(block != NULL) { + mi_block_t* next = mi_block_nextx(heap,block, heap->keys); + // use internal free instead of regular one to keep stats etc correct + if (!_mi_free_delayed_block(block)) { + // we might already start delayed freeing while another thread has not yet + // reset the delayed_freeing flag; in that case delay it further by reinserting. + mi_block_t* dfree = mi_atomic_load_ptr_relaxed(mi_block_t, &heap->thread_delayed_free); + do { + mi_block_set_nextx(heap, block, dfree, heap->keys); + } while (!mi_atomic_cas_ptr_weak_release(mi_block_t,&heap->thread_delayed_free, &dfree, block)); + } + block = next; + } +} + +/* ----------------------------------------------------------- + Unfull, abandon, free and retire +----------------------------------------------------------- */ + +// Move a page from the full list back to a regular list +void _mi_page_unfull(mi_page_t* page) { + mi_assert_internal(page != NULL); + mi_assert_expensive(_mi_page_is_valid(page)); + mi_assert_internal(mi_page_is_in_full(page)); + if (!mi_page_is_in_full(page)) return; + + mi_heap_t* heap = mi_page_heap(page); + mi_page_queue_t* pqfull = &heap->pages[MI_BIN_FULL]; + mi_page_set_in_full(page, false); // to get the right queue + mi_page_queue_t* pq = mi_heap_page_queue_of(heap, page); + mi_page_set_in_full(page, true); + mi_page_queue_enqueue_from(pq, pqfull, page); +} + +static void mi_page_to_full(mi_page_t* page, mi_page_queue_t* pq) { + mi_assert_internal(pq == mi_page_queue_of(page)); + mi_assert_internal(!mi_page_immediate_available(page)); + mi_assert_internal(!mi_page_is_in_full(page)); + + if (mi_page_is_in_full(page)) return; + mi_page_queue_enqueue_from(&mi_page_heap(page)->pages[MI_BIN_FULL], pq, page); + _mi_page_free_collect(page,false); // try to collect right away in case another thread freed just before MI_USE_DELAYED_FREE was set +} + + +// Abandon a page with used blocks at the end of a thread. +// Note: only call if it is ensured that no references exist from +// the `page->heap->thread_delayed_free` into this page. +// Currently only called through `mi_heap_collect_ex` which ensures this. +void _mi_page_abandon(mi_page_t* page, mi_page_queue_t* pq) { + mi_assert_internal(page != NULL); + mi_assert_expensive(_mi_page_is_valid(page)); + mi_assert_internal(pq == mi_page_queue_of(page)); + mi_assert_internal(mi_page_heap(page) != NULL); + + mi_heap_t* pheap = mi_page_heap(page); + + // remove from our page list + mi_segments_tld_t* segments_tld = &pheap->tld->segments; + mi_page_queue_remove(pq, page); + + // page is no longer associated with our heap + mi_assert_internal(mi_page_thread_free_flag(page)==MI_NEVER_DELAYED_FREE); + mi_page_set_heap(page, NULL); + +#if MI_DEBUG>1 + // check there are no references left.. + for (mi_block_t* block = (mi_block_t*)pheap->thread_delayed_free; block != NULL; block = mi_block_nextx(pheap, block, pheap->keys)) { + mi_assert_internal(_mi_ptr_page(block) != page); + } +#endif + + // and abandon it + mi_assert_internal(mi_page_heap(page) == NULL); + _mi_segment_page_abandon(page,segments_tld); +} + + +// Free a page with no more free blocks +void _mi_page_free(mi_page_t* page, mi_page_queue_t* pq, bool force) { + mi_assert_internal(page != NULL); + mi_assert_expensive(_mi_page_is_valid(page)); + mi_assert_internal(pq == mi_page_queue_of(page)); + mi_assert_internal(mi_page_all_free(page)); + mi_assert_internal(mi_page_thread_free_flag(page)!=MI_DELAYED_FREEING); + + // no more aligned blocks in here + mi_page_set_has_aligned(page, false); + + // remove from the page list + // (no need to do _mi_heap_delayed_free first as all blocks are already free) + mi_segments_tld_t* segments_tld = &mi_page_heap(page)->tld->segments; + mi_page_queue_remove(pq, page); + + // and free it + mi_page_set_heap(page,NULL); + _mi_segment_page_free(page, force, segments_tld); +} + +#define MI_MAX_RETIRE_SIZE MI_LARGE_OBJ_SIZE_MAX +#define MI_RETIRE_CYCLES (8) + +// Retire a page with no more used blocks +// Important to not retire too quickly though as new +// allocations might coming. +// Note: called from `mi_free` and benchmarks often +// trigger this due to freeing everything and then +// allocating again so careful when changing this. +void _mi_page_retire(mi_page_t* page) { + mi_assert_internal(page != NULL); + mi_assert_expensive(_mi_page_is_valid(page)); + mi_assert_internal(mi_page_all_free(page)); + + mi_page_set_has_aligned(page, false); + + // don't retire too often.. + // (or we end up retiring and re-allocating most of the time) + // NOTE: refine this more: we should not retire if this + // is the only page left with free blocks. It is not clear + // how to check this efficiently though... + // for now, we don't retire if it is the only page left of this size class. + mi_page_queue_t* pq = mi_page_queue_of(page); + if (mi_likely(page->xblock_size <= MI_MAX_RETIRE_SIZE && !mi_page_is_in_full(page))) { + if (pq->last==page && pq->first==page) { // the only page in the queue? + mi_stat_counter_increase(_mi_stats_main.page_no_retire,1); + page->retire_expire = (page->xblock_size <= MI_SMALL_OBJ_SIZE_MAX ? MI_RETIRE_CYCLES : MI_RETIRE_CYCLES/4); + mi_heap_t* heap = mi_page_heap(page); + mi_assert_internal(pq >= heap->pages); + const size_t index = pq - heap->pages; + mi_assert_internal(index < MI_BIN_FULL && index < MI_BIN_HUGE); + if (index < heap->page_retired_min) heap->page_retired_min = index; + if (index > heap->page_retired_max) heap->page_retired_max = index; + mi_assert_internal(mi_page_all_free(page)); + return; // dont't free after all + } + } + + _mi_page_free(page, pq, false); +} + +// free retired pages: we don't need to look at the entire queues +// since we only retire pages that are at the head position in a queue. +void _mi_heap_collect_retired(mi_heap_t* heap, bool force) { + size_t min = MI_BIN_FULL; + size_t max = 0; + for(size_t bin = heap->page_retired_min; bin <= heap->page_retired_max; bin++) { + mi_page_queue_t* pq = &heap->pages[bin]; + mi_page_t* page = pq->first; + if (page != NULL && page->retire_expire != 0) { + if (mi_page_all_free(page)) { + page->retire_expire--; + if (force || page->retire_expire == 0) { + _mi_page_free(pq->first, pq, force); + } + else { + // keep retired, update min/max + if (bin < min) min = bin; + if (bin > max) max = bin; + } + } + else { + page->retire_expire = 0; + } + } + } + heap->page_retired_min = min; + heap->page_retired_max = max; +} + + +/* ----------------------------------------------------------- + Initialize the initial free list in a page. + In secure mode we initialize a randomized list by + alternating between slices. +----------------------------------------------------------- */ + +#define MI_MAX_SLICE_SHIFT (6) // at most 64 slices +#define MI_MAX_SLICES (1UL << MI_MAX_SLICE_SHIFT) +#define MI_MIN_SLICES (2) + +static void mi_page_free_list_extend_secure(mi_heap_t* const heap, mi_page_t* const page, const size_t bsize, const size_t extend, mi_stats_t* const stats) { + UNUSED(stats); + #if (MI_SECURE<=2) + mi_assert_internal(page->free == NULL); + mi_assert_internal(page->local_free == NULL); + #endif + mi_assert_internal(page->capacity + extend <= page->reserved); + mi_assert_internal(bsize == mi_page_block_size(page)); + void* const page_area = _mi_page_start(_mi_page_segment(page), page, NULL); + + // initialize a randomized free list + // set up `slice_count` slices to alternate between + size_t shift = MI_MAX_SLICE_SHIFT; + while ((extend >> shift) == 0) { + shift--; + } + const size_t slice_count = (size_t)1U << shift; + const size_t slice_extend = extend / slice_count; + mi_assert_internal(slice_extend >= 1); + mi_block_t* blocks[MI_MAX_SLICES]; // current start of the slice + size_t counts[MI_MAX_SLICES]; // available objects in the slice + for (size_t i = 0; i < slice_count; i++) { + blocks[i] = mi_page_block_at(page, page_area, bsize, page->capacity + i*slice_extend); + counts[i] = slice_extend; + } + counts[slice_count-1] += (extend % slice_count); // final slice holds the modulus too (todo: distribute evenly?) + + // and initialize the free list by randomly threading through them + // set up first element + const uintptr_t r = _mi_heap_random_next(heap); + size_t current = r % slice_count; + counts[current]--; + mi_block_t* const free_start = blocks[current]; + // and iterate through the rest; use `random_shuffle` for performance + uintptr_t rnd = _mi_random_shuffle(r|1); // ensure not 0 + for (size_t i = 1; i < extend; i++) { + // call random_shuffle only every INTPTR_SIZE rounds + const size_t round = i%MI_INTPTR_SIZE; + if (round == 0) rnd = _mi_random_shuffle(rnd); + // select a random next slice index + size_t next = ((rnd >> 8*round) & (slice_count-1)); + while (counts[next]==0) { // ensure it still has space + next++; + if (next==slice_count) next = 0; + } + // and link the current block to it + counts[next]--; + mi_block_t* const block = blocks[current]; + blocks[current] = (mi_block_t*)((uint8_t*)block + bsize); // bump to the following block + mi_block_set_next(page, block, blocks[next]); // and set next; note: we may have `current == next` + current = next; + } + // prepend to the free list (usually NULL) + mi_block_set_next(page, blocks[current], page->free); // end of the list + page->free = free_start; +} + +static mi_decl_noinline void mi_page_free_list_extend( mi_page_t* const page, const size_t bsize, const size_t extend, mi_stats_t* const stats) +{ + UNUSED(stats); + #if (MI_SECURE <= 2) + mi_assert_internal(page->free == NULL); + mi_assert_internal(page->local_free == NULL); + #endif + mi_assert_internal(page->capacity + extend <= page->reserved); + mi_assert_internal(bsize == mi_page_block_size(page)); + void* const page_area = _mi_page_start(_mi_page_segment(page), page, NULL ); + + mi_block_t* const start = mi_page_block_at(page, page_area, bsize, page->capacity); + + // initialize a sequential free list + mi_block_t* const last = mi_page_block_at(page, page_area, bsize, page->capacity + extend - 1); + mi_block_t* block = start; + while(block <= last) { + mi_block_t* next = (mi_block_t*)((uint8_t*)block + bsize); + mi_block_set_next(page,block,next); + block = next; + } + // prepend to free list (usually `NULL`) + mi_block_set_next(page, last, page->free); + page->free = start; +} + +/* ----------------------------------------------------------- + Page initialize and extend the capacity +----------------------------------------------------------- */ + +#define MI_MAX_EXTEND_SIZE (4*1024) // heuristic, one OS page seems to work well. +#if (MI_SECURE>0) +#define MI_MIN_EXTEND (8*MI_SECURE) // extend at least by this many +#else +#define MI_MIN_EXTEND (1) +#endif + +// Extend the capacity (up to reserved) by initializing a free list +// We do at most `MI_MAX_EXTEND` to avoid touching too much memory +// Note: we also experimented with "bump" allocation on the first +// allocations but this did not speed up any benchmark (due to an +// extra test in malloc? or cache effects?) +static void mi_page_extend_free(mi_heap_t* heap, mi_page_t* page, mi_tld_t* tld) { + mi_assert_expensive(mi_page_is_valid_init(page)); + #if (MI_SECURE<=2) + mi_assert(page->free == NULL); + mi_assert(page->local_free == NULL); + if (page->free != NULL) return; + #endif + if (page->capacity >= page->reserved) return; + + size_t page_size; + //uint8_t* page_start = + _mi_page_start(_mi_page_segment(page), page, &page_size); + mi_stat_counter_increase(tld->stats.pages_extended, 1); + + // calculate the extend count + const size_t bsize = (page->xblock_size < MI_HUGE_BLOCK_SIZE ? page->xblock_size : page_size); + size_t extend = page->reserved - page->capacity; + size_t max_extend = (bsize >= MI_MAX_EXTEND_SIZE ? MI_MIN_EXTEND : MI_MAX_EXTEND_SIZE/(uint32_t)bsize); + if (max_extend < MI_MIN_EXTEND) max_extend = MI_MIN_EXTEND; + + if (extend > max_extend) { + // ensure we don't touch memory beyond the page to reduce page commit. + // the `lean` benchmark tests this. Going from 1 to 8 increases rss by 50%. + extend = (max_extend==0 ? 1 : max_extend); + } + + mi_assert_internal(extend > 0 && extend + page->capacity <= page->reserved); + mi_assert_internal(extend < (1UL<<16)); + + // and append the extend the free list + if (extend < MI_MIN_SLICES || MI_SECURE==0) { //!mi_option_is_enabled(mi_option_secure)) { + mi_page_free_list_extend(page, bsize, extend, &tld->stats ); + } + else { + mi_page_free_list_extend_secure(heap, page, bsize, extend, &tld->stats); + } + // enable the new free list + page->capacity += (uint16_t)extend; + mi_stat_increase(tld->stats.page_committed, extend * bsize); + + // extension into zero initialized memory preserves the zero'd free list + if (!page->is_zero_init) { + page->is_zero = false; + } + mi_assert_expensive(mi_page_is_valid_init(page)); +} + +// Initialize a fresh page +static void mi_page_init(mi_heap_t* heap, mi_page_t* page, size_t block_size, mi_tld_t* tld) { + mi_assert(page != NULL); + mi_segment_t* segment = _mi_page_segment(page); + mi_assert(segment != NULL); + mi_assert_internal(block_size > 0); + // set fields + mi_page_set_heap(page, heap); + size_t page_size; + _mi_segment_page_start(segment, page, block_size, &page_size, NULL); + page->xblock_size = (block_size < MI_HUGE_BLOCK_SIZE ? (uint32_t)block_size : MI_HUGE_BLOCK_SIZE); + mi_assert_internal(page_size / block_size < (1L<<16)); + page->reserved = (uint16_t)(page_size / block_size); + #ifdef MI_ENCODE_FREELIST + page->keys[0] = _mi_heap_random_next(heap); + page->keys[1] = _mi_heap_random_next(heap); + #endif + page->is_zero = page->is_zero_init; + + mi_assert_internal(page->capacity == 0); + mi_assert_internal(page->free == NULL); + mi_assert_internal(page->used == 0); + mi_assert_internal(page->xthread_free == 0); + mi_assert_internal(page->next == NULL); + mi_assert_internal(page->prev == NULL); + mi_assert_internal(page->retire_expire == 0); + mi_assert_internal(!mi_page_has_aligned(page)); + #if (MI_ENCODE_FREELIST) + mi_assert_internal(page->keys[0] != 0); + mi_assert_internal(page->keys[1] != 0); + #endif + mi_assert_expensive(mi_page_is_valid_init(page)); + + // initialize an initial free list + mi_page_extend_free(heap,page,tld); + mi_assert(mi_page_immediate_available(page)); +} + + +/* ----------------------------------------------------------- + Find pages with free blocks +-------------------------------------------------------------*/ + +// Find a page with free blocks of `page->block_size`. +static mi_page_t* mi_page_queue_find_free_ex(mi_heap_t* heap, mi_page_queue_t* pq, bool first_try) +{ + // search through the pages in "next fit" order + size_t count = 0; + mi_page_t* page = pq->first; + while (page != NULL) + { + mi_page_t* next = page->next; // remember next + count++; + + // 0. collect freed blocks by us and other threads + _mi_page_free_collect(page, false); + + // 1. if the page contains free blocks, we are done + if (mi_page_immediate_available(page)) { + break; // pick this one + } + + // 2. Try to extend + if (page->capacity < page->reserved) { + mi_page_extend_free(heap, page, heap->tld); + mi_assert_internal(mi_page_immediate_available(page)); + break; + } + + // 3. If the page is completely full, move it to the `mi_pages_full` + // queue so we don't visit long-lived pages too often. + mi_assert_internal(!mi_page_is_in_full(page) && !mi_page_immediate_available(page)); + mi_page_to_full(page, pq); + + page = next; + } // for each page + + mi_stat_counter_increase(heap->tld->stats.searches, count); + + if (page == NULL) { + _mi_heap_collect_retired(heap, false); // perhaps make a page available + page = mi_page_fresh(heap, pq); + if (page == NULL && first_try) { + // out-of-memory _or_ an abandoned page with free blocks was reclaimed, try once again + page = mi_page_queue_find_free_ex(heap, pq, false); + } + } + else { + mi_assert(pq->first == page); + page->retire_expire = 0; + } + mi_assert_internal(page == NULL || mi_page_immediate_available(page)); + return page; +} + + + +// Find a page with free blocks of `size`. +static inline mi_page_t* mi_find_free_page(mi_heap_t* heap, size_t size) { + mi_page_queue_t* pq = mi_page_queue(heap,size); + mi_page_t* page = pq->first; + if (page != NULL) { + if ((MI_SECURE >= 3) && page->capacity < page->reserved && ((_mi_heap_random_next(heap) & 1) == 1)) { + // in secure mode, we extend half the time to increase randomness + mi_page_extend_free(heap, page, heap->tld); + mi_assert_internal(mi_page_immediate_available(page)); + } + else { + _mi_page_free_collect(page,false); + } + if (mi_page_immediate_available(page)) { + page->retire_expire = 0; + return page; // fast path + } + } + return mi_page_queue_find_free_ex(heap, pq, true); +} + + +/* ----------------------------------------------------------- + Users can register a deferred free function called + when the `free` list is empty. Since the `local_free` + is separate this is deterministically called after + a certain number of allocations. +----------------------------------------------------------- */ + +static mi_deferred_free_fun* volatile deferred_free = NULL; +static _Atomic(void*) deferred_arg; // = NULL + +void _mi_deferred_free(mi_heap_t* heap, bool force) { + heap->tld->heartbeat++; + if (deferred_free != NULL && !heap->tld->recurse) { + heap->tld->recurse = true; + deferred_free(force, heap->tld->heartbeat, mi_atomic_load_ptr_relaxed(void,&deferred_arg)); + heap->tld->recurse = false; + } +} + +void mi_register_deferred_free(mi_deferred_free_fun* fn, void* arg) mi_attr_noexcept { + deferred_free = fn; + mi_atomic_store_ptr_release(void,&deferred_arg, arg); +} + + +/* ----------------------------------------------------------- + General allocation +----------------------------------------------------------- */ + +// A huge page is allocated directly without being in a queue. +// Because huge pages contain just one block, and the segment contains +// just that page, we always treat them as abandoned and any thread +// that frees the block can free the whole page and segment directly. +static mi_page_t* mi_huge_page_alloc(mi_heap_t* heap, size_t size) { + size_t block_size = _mi_os_good_alloc_size(size); + mi_assert_internal(_mi_bin(block_size) == MI_BIN_HUGE); + mi_page_t* page = mi_page_fresh_alloc(heap,NULL,block_size); + if (page != NULL) { + const size_t bsize = mi_page_block_size(page); // note: not `mi_page_usable_block_size` as `size` includes padding already + mi_assert_internal(bsize >= size); + mi_assert_internal(mi_page_immediate_available(page)); + mi_assert_internal(_mi_page_segment(page)->page_kind==MI_PAGE_HUGE); + mi_assert_internal(_mi_page_segment(page)->used==1); + mi_assert_internal(_mi_page_segment(page)->thread_id==0); // abandoned, not in the huge queue + mi_page_set_heap(page, NULL); + + if (bsize > MI_HUGE_OBJ_SIZE_MAX) { + _mi_stat_increase(&heap->tld->stats.giant, bsize); + _mi_stat_counter_increase(&heap->tld->stats.giant_count, 1); + } + else { + _mi_stat_increase(&heap->tld->stats.huge, bsize); + _mi_stat_counter_increase(&heap->tld->stats.huge_count, 1); + } + } + return page; +} + + +// Allocate a page +// Note: in debug mode the size includes MI_PADDING_SIZE and might have overflowed. +static mi_page_t* mi_find_page(mi_heap_t* heap, size_t size) mi_attr_noexcept { + // huge allocation? + const size_t req_size = size - MI_PADDING_SIZE; // correct for padding_size in case of an overflow on `size` + if (mi_unlikely(req_size > (MI_LARGE_OBJ_SIZE_MAX - MI_PADDING_SIZE) )) { + if (mi_unlikely(req_size > PTRDIFF_MAX)) { // we don't allocate more than PTRDIFF_MAX (see ) + _mi_error_message(EOVERFLOW, "allocation request is too large (%zu bytes)\n", req_size); + return NULL; + } + else { + return mi_huge_page_alloc(heap,size); + } + } + else { + // otherwise find a page with free blocks in our size segregated queues + mi_assert_internal(size >= MI_PADDING_SIZE); + return mi_find_free_page(heap, size); + } +} + +// Generic allocation routine if the fast path (`alloc.c:mi_page_malloc`) does not succeed. +// Note: in debug mode the size includes MI_PADDING_SIZE and might have overflowed. +void* _mi_malloc_generic(mi_heap_t* heap, size_t size) mi_attr_noexcept +{ + mi_assert_internal(heap != NULL); + + // initialize if necessary + if (mi_unlikely(!mi_heap_is_initialized(heap))) { + mi_thread_init(); // calls `_mi_heap_init` in turn + heap = mi_get_default_heap(); + if (mi_unlikely(!mi_heap_is_initialized(heap))) { return NULL; } + } + mi_assert_internal(mi_heap_is_initialized(heap)); + + // call potential deferred free routines + _mi_deferred_free(heap, false); + + // free delayed frees from other threads + _mi_heap_delayed_free(heap); + + // find (or allocate) a page of the right size + mi_page_t* page = mi_find_page(heap, size); + if (mi_unlikely(page == NULL)) { // first time out of memory, try to collect and retry the allocation once more + mi_heap_collect(heap, true /* force */); + page = mi_find_page(heap, size); + } + + if (mi_unlikely(page == NULL)) { // out of memory + const size_t req_size = size - MI_PADDING_SIZE; // correct for padding_size in case of an overflow on `size` + _mi_error_message(ENOMEM, "unable to allocate memory (%zu bytes)\n", req_size); + return NULL; + } + + mi_assert_internal(mi_page_immediate_available(page)); + mi_assert_internal(mi_page_block_size(page) >= size); + + // and try again, this time succeeding! (i.e. this should never recurse) + return _mi_page_malloc(heap, page, size); +} diff --git a/kotlin-native/runtime/src/mimalloc/c/random.c b/kotlin-native/runtime/src/mimalloc/c/random.c new file mode 100644 index 00000000000..b9485ea094f --- /dev/null +++ b/kotlin-native/runtime/src/mimalloc/c/random.c @@ -0,0 +1,339 @@ +/* ---------------------------------------------------------------------------- +Copyright (c) 2019, Microsoft Research, Daan Leijen +This is free software; you can redistribute it and/or modify it under the +terms of the MIT license. A copy of the license can be found in the file +"LICENSE" at the root of this distribution. +-----------------------------------------------------------------------------*/ +#include "mimalloc.h" +#include "mimalloc-internal.h" + +#include // memset + +/* ---------------------------------------------------------------------------- +We use our own PRNG to keep predictable performance of random number generation +and to avoid implementations that use a lock. We only use the OS provided +random source to initialize the initial seeds. Since we do not need ultimate +performance but we do rely on the security (for secret cookies in secure mode) +we use a cryptographically secure generator (chacha20). +-----------------------------------------------------------------------------*/ + +#define MI_CHACHA_ROUNDS (20) // perhaps use 12 for better performance? + + +/* ---------------------------------------------------------------------------- +Chacha20 implementation as the original algorithm with a 64-bit nonce +and counter: https://en.wikipedia.org/wiki/Salsa20 +The input matrix has sixteen 32-bit values: +Position 0 to 3: constant key +Position 4 to 11: the key +Position 12 to 13: the counter. +Position 14 to 15: the nonce. + +The implementation uses regular C code which compiles very well on modern compilers. +(gcc x64 has no register spills, and clang 6+ uses SSE instructions) +-----------------------------------------------------------------------------*/ + +static inline uint32_t rotl(uint32_t x, uint32_t shift) { + return (x << shift) | (x >> (32 - shift)); +} + +static inline void qround(uint32_t x[16], size_t a, size_t b, size_t c, size_t d) { + x[a] += x[b]; x[d] = rotl(x[d] ^ x[a], 16); + x[c] += x[d]; x[b] = rotl(x[b] ^ x[c], 12); + x[a] += x[b]; x[d] = rotl(x[d] ^ x[a], 8); + x[c] += x[d]; x[b] = rotl(x[b] ^ x[c], 7); +} + +static void chacha_block(mi_random_ctx_t* ctx) +{ + // scramble into `x` + uint32_t x[16]; + for (size_t i = 0; i < 16; i++) { + x[i] = ctx->input[i]; + } + for (size_t i = 0; i < MI_CHACHA_ROUNDS; i += 2) { + qround(x, 0, 4, 8, 12); + qround(x, 1, 5, 9, 13); + qround(x, 2, 6, 10, 14); + qround(x, 3, 7, 11, 15); + qround(x, 0, 5, 10, 15); + qround(x, 1, 6, 11, 12); + qround(x, 2, 7, 8, 13); + qround(x, 3, 4, 9, 14); + } + + // add scrambled data to the initial state + for (size_t i = 0; i < 16; i++) { + ctx->output[i] = x[i] + ctx->input[i]; + } + ctx->output_available = 16; + + // increment the counter for the next round + ctx->input[12] += 1; + if (ctx->input[12] == 0) { + ctx->input[13] += 1; + if (ctx->input[13] == 0) { // and keep increasing into the nonce + ctx->input[14] += 1; + } + } +} + +static uint32_t chacha_next32(mi_random_ctx_t* ctx) { + if (ctx->output_available <= 0) { + chacha_block(ctx); + ctx->output_available = 16; // (assign again to suppress static analysis warning) + } + const uint32_t x = ctx->output[16 - ctx->output_available]; + ctx->output[16 - ctx->output_available] = 0; // reset once the data is handed out + ctx->output_available--; + return x; +} + +static inline uint32_t read32(const uint8_t* p, size_t idx32) { + const size_t i = 4*idx32; + return ((uint32_t)p[i+0] | (uint32_t)p[i+1] << 8 | (uint32_t)p[i+2] << 16 | (uint32_t)p[i+3] << 24); +} + +static void chacha_init(mi_random_ctx_t* ctx, const uint8_t key[32], uint64_t nonce) +{ + // since we only use chacha for randomness (and not encryption) we + // do not _need_ to read 32-bit values as little endian but we do anyways + // just for being compatible :-) + memset(ctx, 0, sizeof(*ctx)); + for (size_t i = 0; i < 4; i++) { + const uint8_t* sigma = (uint8_t*)"expand 32-byte k"; + ctx->input[i] = read32(sigma,i); + } + for (size_t i = 0; i < 8; i++) { + ctx->input[i + 4] = read32(key,i); + } + ctx->input[12] = 0; + ctx->input[13] = 0; + ctx->input[14] = (uint32_t)nonce; + ctx->input[15] = (uint32_t)(nonce >> 32); +} + +static void chacha_split(mi_random_ctx_t* ctx, uint64_t nonce, mi_random_ctx_t* ctx_new) { + memset(ctx_new, 0, sizeof(*ctx_new)); + memcpy(ctx_new->input, ctx->input, sizeof(ctx_new->input)); + ctx_new->input[12] = 0; + ctx_new->input[13] = 0; + ctx_new->input[14] = (uint32_t)nonce; + ctx_new->input[15] = (uint32_t)(nonce >> 32); + mi_assert_internal(ctx->input[14] != ctx_new->input[14] || ctx->input[15] != ctx_new->input[15]); // do not reuse nonces! + chacha_block(ctx_new); +} + + +/* ---------------------------------------------------------------------------- +Random interface +-----------------------------------------------------------------------------*/ + +#if MI_DEBUG>1 +static bool mi_random_is_initialized(mi_random_ctx_t* ctx) { + return (ctx != NULL && ctx->input[0] != 0); +} +#endif + +void _mi_random_split(mi_random_ctx_t* ctx, mi_random_ctx_t* ctx_new) { + mi_assert_internal(mi_random_is_initialized(ctx)); + mi_assert_internal(ctx != ctx_new); + chacha_split(ctx, (uintptr_t)ctx_new /*nonce*/, ctx_new); +} + +uintptr_t _mi_random_next(mi_random_ctx_t* ctx) { + mi_assert_internal(mi_random_is_initialized(ctx)); + #if MI_INTPTR_SIZE <= 4 + return chacha_next32(ctx); + #elif MI_INTPTR_SIZE == 8 + return (((uintptr_t)chacha_next32(ctx) << 32) | chacha_next32(ctx)); + #else + # error "define mi_random_next for this platform" + #endif +} + + +/* ---------------------------------------------------------------------------- +To initialize a fresh random context we rely on the OS: +- Windows : BCryptGenRandom (or RtlGenRandom) +- osX,bsd,wasi: arc4random_buf +- Linux : getrandom,/dev/urandom +If we cannot get good randomness, we fall back to weak randomness based on a timer and ASLR. +-----------------------------------------------------------------------------*/ + +#if defined(_WIN32) + +#if !defined(MI_USE_RTLGENRANDOM) +// We prefer BCryptGenRandom over RtlGenRandom +#pragma comment (lib,"bcrypt.lib") +#include +static bool os_random_buf(void* buf, size_t buf_len) { + return (BCryptGenRandom(NULL, (PUCHAR)buf, (ULONG)buf_len, BCRYPT_USE_SYSTEM_PREFERRED_RNG) >= 0); +} +#else +// Use (unofficial) RtlGenRandom +#pragma comment (lib,"advapi32.lib") +#define RtlGenRandom SystemFunction036 +#ifdef __cplusplus +extern "C" { +#endif +BOOLEAN NTAPI RtlGenRandom(PVOID RandomBuffer, ULONG RandomBufferLength); +#ifdef __cplusplus +} +#endif +static bool os_random_buf(void* buf, size_t buf_len) { + return (RtlGenRandom(buf, (ULONG)buf_len) != 0); +} +#endif + +#elif defined(ANDROID) || defined(XP_DARWIN) || defined(__APPLE__) || defined(__DragonFly__) || \ + defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__) || \ + defined(__sun) || defined(__wasi__) +#include +static bool os_random_buf(void* buf, size_t buf_len) { + arc4random_buf(buf, buf_len); + return true; +} +#elif defined(__linux__) +#include +#include +#include +#include +#include +#include +static bool os_random_buf(void* buf, size_t buf_len) { + // Modern Linux provides `getrandom` but different distributions either use `sys/random.h` or `linux/random.h` + // and for the latter the actual `getrandom` call is not always defined. + // (see ) + // We therefore use a syscall directly and fall back dynamically to /dev/urandom when needed. +#ifdef SYS_getrandom + #ifndef GRND_NONBLOCK + #define GRND_NONBLOCK (1) + #endif + static _Atomic(uintptr_t) no_getrandom; // = 0 + if (mi_atomic_load_acquire(&no_getrandom)==0) { + ssize_t ret = syscall(SYS_getrandom, buf, buf_len, GRND_NONBLOCK); + if (ret >= 0) return (buf_len == (size_t)ret); + if (ret != ENOSYS) return false; + mi_atomic_store_release(&no_getrandom, 1UL); // don't call again, and fall back to /dev/urandom + } +#endif + int flags = O_RDONLY; + #if defined(O_CLOEXEC) + flags |= O_CLOEXEC; + #endif + int fd = open("/dev/urandom", flags, 0); + if (fd < 0) return false; + size_t count = 0; + while(count < buf_len) { + ssize_t ret = read(fd, (char*)buf + count, buf_len - count); + if (ret<=0) { + if (errno!=EAGAIN && errno!=EINTR) break; + } + else { + count += ret; + } + } + close(fd); + return (count==buf_len); +} +#else +static bool os_random_buf(void* buf, size_t buf_len) { + return false; +} +#endif + +#if defined(_WIN32) +#include +#elif defined(__APPLE__) +#include +#else +#include +#endif + +uintptr_t _os_random_weak(uintptr_t extra_seed) { + uintptr_t x = (uintptr_t)&_os_random_weak ^ extra_seed; // ASLR makes the address random + + #if defined(_WIN32) + LARGE_INTEGER pcount; + QueryPerformanceCounter(&pcount); + x ^= (uintptr_t)(pcount.QuadPart); + #elif defined(__APPLE__) + x ^= (uintptr_t)mach_absolute_time(); + #else + struct timespec time; + clock_gettime(CLOCK_MONOTONIC, &time); + x ^= (uintptr_t)time.tv_sec; + x ^= (uintptr_t)time.tv_nsec; + #endif + // and do a few randomization steps + uintptr_t max = ((x ^ (x >> 17)) & 0x0F) + 1; + for (uintptr_t i = 0; i < max; i++) { + x = _mi_random_shuffle(x); + } + mi_assert_internal(x != 0); + return x; +} + +void _mi_random_init(mi_random_ctx_t* ctx) { + uint8_t key[32]; + if (!os_random_buf(key, sizeof(key))) { + // if we fail to get random data from the OS, we fall back to a + // weak random source based on the current time + _mi_warning_message("unable to use secure randomness\n"); + uintptr_t x = _os_random_weak(0); + for (size_t i = 0; i < 8; i++) { // key is eight 32-bit words. + x = _mi_random_shuffle(x); + ((uint32_t*)key)[i] = (uint32_t)x; + } + } + chacha_init(ctx, key, (uintptr_t)ctx /*nonce*/ ); +} + +/* -------------------------------------------------------- +test vectors from +----------------------------------------------------------- */ +/* +static bool array_equals(uint32_t* x, uint32_t* y, size_t n) { + for (size_t i = 0; i < n; i++) { + if (x[i] != y[i]) return false; + } + return true; +} +static void chacha_test(void) +{ + uint32_t x[4] = { 0x11111111, 0x01020304, 0x9b8d6f43, 0x01234567 }; + uint32_t x_out[4] = { 0xea2a92f4, 0xcb1cf8ce, 0x4581472e, 0x5881c4bb }; + qround(x, 0, 1, 2, 3); + mi_assert_internal(array_equals(x, x_out, 4)); + + uint32_t y[16] = { + 0x879531e0, 0xc5ecf37d, 0x516461b1, 0xc9a62f8a, + 0x44c20ef3, 0x3390af7f, 0xd9fc690b, 0x2a5f714c, + 0x53372767, 0xb00a5631, 0x974c541a, 0x359e9963, + 0x5c971061, 0x3d631689, 0x2098d9d6, 0x91dbd320 }; + uint32_t y_out[16] = { + 0x879531e0, 0xc5ecf37d, 0xbdb886dc, 0xc9a62f8a, + 0x44c20ef3, 0x3390af7f, 0xd9fc690b, 0xcfacafd2, + 0xe46bea80, 0xb00a5631, 0x974c541a, 0x359e9963, + 0x5c971061, 0xccc07c79, 0x2098d9d6, 0x91dbd320 }; + qround(y, 2, 7, 8, 13); + mi_assert_internal(array_equals(y, y_out, 16)); + + mi_random_ctx_t r = { + { 0x61707865, 0x3320646e, 0x79622d32, 0x6b206574, + 0x03020100, 0x07060504, 0x0b0a0908, 0x0f0e0d0c, + 0x13121110, 0x17161514, 0x1b1a1918, 0x1f1e1d1c, + 0x00000001, 0x09000000, 0x4a000000, 0x00000000 }, + {0}, + 0 + }; + uint32_t r_out[16] = { + 0xe4e7f110, 0x15593bd1, 0x1fdd0f50, 0xc47120a3, + 0xc7f4d1c7, 0x0368c033, 0x9aaa2204, 0x4e6cd4c3, + 0x466482d2, 0x09aa9f07, 0x05d7c214, 0xa2028bd9, + 0xd19c12b5, 0xb94e16de, 0xe883d0cb, 0x4e3c50a2 }; + chacha_block(&r); + mi_assert_internal(array_equals(r.output, r_out, 16)); +} +*/ diff --git a/kotlin-native/runtime/src/mimalloc/c/region.c b/kotlin-native/runtime/src/mimalloc/c/region.c new file mode 100644 index 00000000000..b6d0da31508 --- /dev/null +++ b/kotlin-native/runtime/src/mimalloc/c/region.c @@ -0,0 +1,500 @@ +/* ---------------------------------------------------------------------------- +Copyright (c) 2019, Microsoft Research, Daan Leijen +This is free software; you can redistribute it and/or modify it under the +terms of the MIT license. A copy of the license can be found in the file +"LICENSE" at the root of this distribution. +-----------------------------------------------------------------------------*/ + +/* ---------------------------------------------------------------------------- +This implements a layer between the raw OS memory (VirtualAlloc/mmap/sbrk/..) +and the segment and huge object allocation by mimalloc. There may be multiple +implementations of this (one could be the identity going directly to the OS, +another could be a simple cache etc), but the current one uses large "regions". +In contrast to the rest of mimalloc, the "regions" are shared between threads and +need to be accessed using atomic operations. +We need this memory layer between the raw OS calls because of: +1. on `sbrk` like systems (like WebAssembly) we need our own memory maps in order + to reuse memory effectively. +2. It turns out that for large objects, between 1MiB and 32MiB (?), the cost of + an OS allocation/free is still (much) too expensive relative to the accesses + in that object :-( (`malloc-large` tests this). This means we need a cheaper + way to reuse memory. +3. This layer allows for NUMA aware allocation. + +Possible issues: +- (2) can potentially be addressed too with a small cache per thread which is much + simpler. Generally though that requires shrinking of huge pages, and may overuse + memory per thread. (and is not compatible with `sbrk`). +- Since the current regions are per-process, we need atomic operations to + claim blocks which may be contended +- In the worst case, we need to search the whole region map (16KiB for 256GiB) + linearly. At what point will direct OS calls be faster? Is there a way to + do this better without adding too much complexity? +-----------------------------------------------------------------------------*/ +#include "mimalloc.h" +#include "mimalloc-internal.h" +#include "mimalloc-atomic.h" + +#include // memset + +#include "bitmap.inc.c" + +// Internal raw OS interface +size_t _mi_os_large_page_size(); +bool _mi_os_protect(void* addr, size_t size); +bool _mi_os_unprotect(void* addr, size_t size); +bool _mi_os_commit(void* p, size_t size, bool* is_zero, mi_stats_t* stats); +bool _mi_os_decommit(void* p, size_t size, mi_stats_t* stats); +bool _mi_os_reset(void* p, size_t size, mi_stats_t* stats); +bool _mi_os_unreset(void* p, size_t size, bool* is_zero, mi_stats_t* stats); + +// arena.c +void _mi_arena_free(void* p, size_t size, size_t memid, bool all_committed, mi_stats_t* stats); +void* _mi_arena_alloc(size_t size, bool* commit, bool* large, bool* is_zero, size_t* memid, mi_os_tld_t* tld); +void* _mi_arena_alloc_aligned(size_t size, size_t alignment, bool* commit, bool* large, bool* is_zero, size_t* memid, mi_os_tld_t* tld); + + + +// Constants +#if (MI_INTPTR_SIZE==8) +#define MI_HEAP_REGION_MAX_SIZE (256 * GiB) // 64KiB for the region map +#elif (MI_INTPTR_SIZE==4) +#define MI_HEAP_REGION_MAX_SIZE (3 * GiB) // ~ KiB for the region map +#else +#error "define the maximum heap space allowed for regions on this platform" +#endif + +#define MI_SEGMENT_ALIGN MI_SEGMENT_SIZE + +#define MI_REGION_MAX_BLOCKS MI_BITMAP_FIELD_BITS +#define MI_REGION_SIZE (MI_SEGMENT_SIZE * MI_BITMAP_FIELD_BITS) // 256MiB (64MiB on 32 bits) +#define MI_REGION_MAX (MI_HEAP_REGION_MAX_SIZE / MI_REGION_SIZE) // 1024 (48 on 32 bits) +#define MI_REGION_MAX_OBJ_BLOCKS (MI_REGION_MAX_BLOCKS/4) // 64MiB +#define MI_REGION_MAX_OBJ_SIZE (MI_REGION_MAX_OBJ_BLOCKS*MI_SEGMENT_SIZE) + +// Region info +typedef union mi_region_info_u { + uintptr_t value; + struct { + bool valid; // initialized? + bool is_large; // allocated in fixed large/huge OS pages + short numa_node; // the associated NUMA node (where -1 means no associated node) + } x; +} mi_region_info_t; + + +// A region owns a chunk of REGION_SIZE (256MiB) (virtual) memory with +// a bit map with one bit per MI_SEGMENT_SIZE (4MiB) block. +typedef struct mem_region_s { + _Atomic(uintptr_t) info; // mi_region_info_t.value + _Atomic(void*) start; // start of the memory area + mi_bitmap_field_t in_use; // bit per in-use block + mi_bitmap_field_t dirty; // track if non-zero per block + mi_bitmap_field_t commit; // track if committed per block + mi_bitmap_field_t reset; // track if reset per block + _Atomic(uintptr_t) arena_memid; // if allocated from a (huge page) arena + uintptr_t padding; // round to 8 fields +} mem_region_t; + +// The region map +static mem_region_t regions[MI_REGION_MAX]; + +// Allocated regions +static _Atomic(uintptr_t) regions_count; // = 0; + + +/* ---------------------------------------------------------------------------- +Utility functions +-----------------------------------------------------------------------------*/ + +// Blocks (of 4MiB) needed for the given size. +static size_t mi_region_block_count(size_t size) { + return _mi_divide_up(size, MI_SEGMENT_SIZE); +} + +/* +// Return a rounded commit/reset size such that we don't fragment large OS pages into small ones. +static size_t mi_good_commit_size(size_t size) { + if (size > (SIZE_MAX - _mi_os_large_page_size())) return size; + return _mi_align_up(size, _mi_os_large_page_size()); +} +*/ + +// Return if a pointer points into a region reserved by us. +bool mi_is_in_heap_region(const void* p) mi_attr_noexcept { + if (p==NULL) return false; + size_t count = mi_atomic_load_relaxed(®ions_count); + for (size_t i = 0; i < count; i++) { + uint8_t* start = (uint8_t*)mi_atomic_load_ptr_relaxed(uint8_t, ®ions[i].start); + if (start != NULL && (uint8_t*)p >= start && (uint8_t*)p < start + MI_REGION_SIZE) return true; + } + return false; +} + + +static void* mi_region_blocks_start(const mem_region_t* region, mi_bitmap_index_t bit_idx) { + uint8_t* start = (uint8_t*)mi_atomic_load_ptr_acquire(uint8_t, &((mem_region_t*)region)->start); + mi_assert_internal(start != NULL); + return (start + (bit_idx * MI_SEGMENT_SIZE)); +} + +static size_t mi_memid_create(mem_region_t* region, mi_bitmap_index_t bit_idx) { + mi_assert_internal(bit_idx < MI_BITMAP_FIELD_BITS); + size_t idx = region - regions; + mi_assert_internal(®ions[idx] == region); + return (idx*MI_BITMAP_FIELD_BITS + bit_idx)<<1; +} + +static size_t mi_memid_create_from_arena(size_t arena_memid) { + return (arena_memid << 1) | 1; +} + + +static bool mi_memid_is_arena(size_t id, mem_region_t** region, mi_bitmap_index_t* bit_idx, size_t* arena_memid) { + if ((id&1)==1) { + if (arena_memid != NULL) *arena_memid = (id>>1); + return true; + } + else { + size_t idx = (id >> 1) / MI_BITMAP_FIELD_BITS; + *bit_idx = (mi_bitmap_index_t)(id>>1) % MI_BITMAP_FIELD_BITS; + *region = ®ions[idx]; + return false; + } +} + + +/* ---------------------------------------------------------------------------- + Allocate a region is allocated from the OS (or an arena) +-----------------------------------------------------------------------------*/ + +static bool mi_region_try_alloc_os(size_t blocks, bool commit, bool allow_large, mem_region_t** region, mi_bitmap_index_t* bit_idx, mi_os_tld_t* tld) +{ + // not out of regions yet? + if (mi_atomic_load_relaxed(®ions_count) >= MI_REGION_MAX - 1) return false; + + // try to allocate a fresh region from the OS + bool region_commit = (commit && mi_option_is_enabled(mi_option_eager_region_commit)); + bool region_large = (commit && allow_large); + bool is_zero = false; + size_t arena_memid = 0; + void* const start = _mi_arena_alloc_aligned(MI_REGION_SIZE, MI_SEGMENT_ALIGN, ®ion_commit, ®ion_large, &is_zero, &arena_memid, tld); + if (start == NULL) return false; + mi_assert_internal(!(region_large && !allow_large)); + mi_assert_internal(!region_large || region_commit); + + // claim a fresh slot + const uintptr_t idx = mi_atomic_increment_acq_rel(®ions_count); + if (idx >= MI_REGION_MAX) { + mi_atomic_decrement_acq_rel(®ions_count); + _mi_arena_free(start, MI_REGION_SIZE, arena_memid, region_commit, tld->stats); + _mi_warning_message("maximum regions used: %zu GiB (perhaps recompile with a larger setting for MI_HEAP_REGION_MAX_SIZE)", _mi_divide_up(MI_HEAP_REGION_MAX_SIZE, GiB)); + return false; + } + + // allocated, initialize and claim the initial blocks + mem_region_t* r = ®ions[idx]; + r->arena_memid = arena_memid; + mi_atomic_store_release(&r->in_use, (uintptr_t)0); + mi_atomic_store_release(&r->dirty, (is_zero ? 0 : MI_BITMAP_FIELD_FULL)); + mi_atomic_store_release(&r->commit, (region_commit ? MI_BITMAP_FIELD_FULL : 0)); + mi_atomic_store_release(&r->reset, (uintptr_t)0); + *bit_idx = 0; + mi_bitmap_claim(&r->in_use, 1, blocks, *bit_idx, NULL); + mi_atomic_store_ptr_release(void,&r->start, start); + + // and share it + mi_region_info_t info; + info.value = 0; // initialize the full union to zero + info.x.valid = true; + info.x.is_large = region_large; + info.x.numa_node = (short)_mi_os_numa_node(tld); + mi_atomic_store_release(&r->info, info.value); // now make it available to others + *region = r; + return true; +} + +/* ---------------------------------------------------------------------------- + Try to claim blocks in suitable regions +-----------------------------------------------------------------------------*/ + +static bool mi_region_is_suitable(const mem_region_t* region, int numa_node, bool allow_large ) { + // initialized at all? + mi_region_info_t info; + info.value = mi_atomic_load_relaxed(&((mem_region_t*)region)->info); + if (info.value==0) return false; + + // numa correct + if (numa_node >= 0) { // use negative numa node to always succeed + int rnode = info.x.numa_node; + if (rnode >= 0 && rnode != numa_node) return false; + } + + // check allow-large + if (!allow_large && info.x.is_large) return false; + + return true; +} + + +static bool mi_region_try_claim(int numa_node, size_t blocks, bool allow_large, mem_region_t** region, mi_bitmap_index_t* bit_idx, mi_os_tld_t* tld) +{ + // try all regions for a free slot + const size_t count = mi_atomic_load_relaxed(®ions_count); // monotonic, so ok to be relaxed + size_t idx = tld->region_idx; // Or start at 0 to reuse low addresses? Starting at 0 seems to increase latency though + for (size_t visited = 0; visited < count; visited++, idx++) { + if (idx >= count) idx = 0; // wrap around + mem_region_t* r = ®ions[idx]; + // if this region suits our demand (numa node matches, large OS page matches) + if (mi_region_is_suitable(r, numa_node, allow_large)) { + // then try to atomically claim a segment(s) in this region + if (mi_bitmap_try_find_claim_field(&r->in_use, 0, blocks, bit_idx)) { + tld->region_idx = idx; // remember the last found position + *region = r; + return true; + } + } + } + return false; +} + + +static void* mi_region_try_alloc(size_t blocks, bool* commit, bool* is_large, bool* is_zero, size_t* memid, mi_os_tld_t* tld) +{ + mi_assert_internal(blocks <= MI_BITMAP_FIELD_BITS); + mem_region_t* region; + mi_bitmap_index_t bit_idx; + const int numa_node = (_mi_os_numa_node_count() <= 1 ? -1 : _mi_os_numa_node(tld)); + // try to claim in existing regions + if (!mi_region_try_claim(numa_node, blocks, *is_large, ®ion, &bit_idx, tld)) { + // otherwise try to allocate a fresh region and claim in there + if (!mi_region_try_alloc_os(blocks, *commit, *is_large, ®ion, &bit_idx, tld)) { + // out of regions or memory + return NULL; + } + } + + // ------------------------------------------------ + // found a region and claimed `blocks` at `bit_idx`, initialize them now + mi_assert_internal(region != NULL); + mi_assert_internal(mi_bitmap_is_claimed(®ion->in_use, 1, blocks, bit_idx)); + + mi_region_info_t info; + info.value = mi_atomic_load_acquire(®ion->info); + uint8_t* start = (uint8_t*)mi_atomic_load_ptr_acquire(uint8_t,®ion->start); + mi_assert_internal(!(info.x.is_large && !*is_large)); + mi_assert_internal(start != NULL); + + *is_zero = mi_bitmap_claim(®ion->dirty, 1, blocks, bit_idx, NULL); + *is_large = info.x.is_large; + *memid = mi_memid_create(region, bit_idx); + void* p = start + (mi_bitmap_index_bit_in_field(bit_idx) * MI_SEGMENT_SIZE); + + // commit + if (*commit) { + // ensure commit + bool any_uncommitted; + mi_bitmap_claim(®ion->commit, 1, blocks, bit_idx, &any_uncommitted); + if (any_uncommitted) { + mi_assert_internal(!info.x.is_large); + bool commit_zero = false; + if (!_mi_mem_commit(p, blocks * MI_SEGMENT_SIZE, &commit_zero, tld)) { + // failed to commit! unclaim and return + mi_bitmap_unclaim(®ion->in_use, 1, blocks, bit_idx); + return NULL; + } + if (commit_zero) *is_zero = true; + } + } + else { + // no need to commit, but check if already fully committed + *commit = mi_bitmap_is_claimed(®ion->commit, 1, blocks, bit_idx); + } + mi_assert_internal(!*commit || mi_bitmap_is_claimed(®ion->commit, 1, blocks, bit_idx)); + + // unreset reset blocks + if (mi_bitmap_is_any_claimed(®ion->reset, 1, blocks, bit_idx)) { + // some blocks are still reset + mi_assert_internal(!info.x.is_large); + mi_assert_internal(!mi_option_is_enabled(mi_option_eager_commit) || *commit || mi_option_get(mi_option_eager_commit_delay) > 0); + mi_bitmap_unclaim(®ion->reset, 1, blocks, bit_idx); + if (*commit || !mi_option_is_enabled(mi_option_reset_decommits)) { // only if needed + bool reset_zero = false; + _mi_mem_unreset(p, blocks * MI_SEGMENT_SIZE, &reset_zero, tld); + if (reset_zero) *is_zero = true; + } + } + mi_assert_internal(!mi_bitmap_is_any_claimed(®ion->reset, 1, blocks, bit_idx)); + + #if (MI_DEBUG>=2) + if (*commit) { ((uint8_t*)p)[0] = 0; } + #endif + + // and return the allocation + mi_assert_internal(p != NULL); + return p; +} + + +/* ---------------------------------------------------------------------------- + Allocation +-----------------------------------------------------------------------------*/ + +// Allocate `size` memory aligned at `alignment`. Return non NULL on success, with a given memory `id`. +// (`id` is abstract, but `id = idx*MI_REGION_MAP_BITS + bitidx`) +void* _mi_mem_alloc_aligned(size_t size, size_t alignment, bool* commit, bool* large, bool* is_zero, size_t* memid, mi_os_tld_t* tld) +{ + mi_assert_internal(memid != NULL && tld != NULL); + mi_assert_internal(size > 0); + *memid = 0; + *is_zero = false; + bool default_large = false; + if (large==NULL) large = &default_large; // ensure `large != NULL` + if (size == 0) return NULL; + size = _mi_align_up(size, _mi_os_page_size()); + + // allocate from regions if possible + void* p = NULL; + size_t arena_memid; + const size_t blocks = mi_region_block_count(size); + if (blocks <= MI_REGION_MAX_OBJ_BLOCKS && alignment <= MI_SEGMENT_ALIGN) { + p = mi_region_try_alloc(blocks, commit, large, is_zero, memid, tld); + if (p == NULL) { + _mi_warning_message("unable to allocate from region: size %zu\n", size); + } + } + if (p == NULL) { + // and otherwise fall back to the OS + p = _mi_arena_alloc_aligned(size, alignment, commit, large, is_zero, &arena_memid, tld); + *memid = mi_memid_create_from_arena(arena_memid); + } + + if (p != NULL) { + mi_assert_internal((uintptr_t)p % alignment == 0); +#if (MI_DEBUG>=2) + if (*commit) { ((uint8_t*)p)[0] = 0; } // ensure the memory is committed +#endif + } + return p; +} + + + +/* ---------------------------------------------------------------------------- +Free +-----------------------------------------------------------------------------*/ + +// Free previously allocated memory with a given id. +void _mi_mem_free(void* p, size_t size, size_t id, bool full_commit, bool any_reset, mi_os_tld_t* tld) { + mi_assert_internal(size > 0 && tld != NULL); + if (p==NULL) return; + if (size==0) return; + size = _mi_align_up(size, _mi_os_page_size()); + + size_t arena_memid = 0; + mi_bitmap_index_t bit_idx; + mem_region_t* region; + if (mi_memid_is_arena(id,®ion,&bit_idx,&arena_memid)) { + // was a direct arena allocation, pass through + _mi_arena_free(p, size, arena_memid, full_commit, tld->stats); + } + else { + // allocated in a region + mi_assert_internal(size <= MI_REGION_MAX_OBJ_SIZE); if (size > MI_REGION_MAX_OBJ_SIZE) return; + const size_t blocks = mi_region_block_count(size); + mi_assert_internal(blocks + bit_idx <= MI_BITMAP_FIELD_BITS); + mi_region_info_t info; + info.value = mi_atomic_load_acquire(®ion->info); + mi_assert_internal(info.value != 0); + void* blocks_start = mi_region_blocks_start(region, bit_idx); + mi_assert_internal(blocks_start == p); // not a pointer in our area? + mi_assert_internal(bit_idx + blocks <= MI_BITMAP_FIELD_BITS); + if (blocks_start != p || bit_idx + blocks > MI_BITMAP_FIELD_BITS) return; // or `abort`? + + // committed? + if (full_commit && (size % MI_SEGMENT_SIZE) == 0) { + mi_bitmap_claim(®ion->commit, 1, blocks, bit_idx, NULL); + } + + if (any_reset) { + // set the is_reset bits if any pages were reset + mi_bitmap_claim(®ion->reset, 1, blocks, bit_idx, NULL); + } + + // reset the blocks to reduce the working set. + if (!info.x.is_large && mi_option_is_enabled(mi_option_segment_reset) + && (mi_option_is_enabled(mi_option_eager_commit) || + mi_option_is_enabled(mi_option_reset_decommits))) // cannot reset halfway committed segments, use only `option_page_reset` instead + { + bool any_unreset; + mi_bitmap_claim(®ion->reset, 1, blocks, bit_idx, &any_unreset); + if (any_unreset) { + _mi_abandoned_await_readers(); // ensure no more pending write (in case reset = decommit) + _mi_mem_reset(p, blocks * MI_SEGMENT_SIZE, tld); + } + } + + // and unclaim + bool all_unclaimed = mi_bitmap_unclaim(®ion->in_use, 1, blocks, bit_idx); + mi_assert_internal(all_unclaimed); UNUSED(all_unclaimed); + } +} + + +/* ---------------------------------------------------------------------------- + collection +-----------------------------------------------------------------------------*/ +void _mi_mem_collect(mi_os_tld_t* tld) { + // free every region that has no segments in use. + uintptr_t rcount = mi_atomic_load_relaxed(®ions_count); + for (size_t i = 0; i < rcount; i++) { + mem_region_t* region = ®ions[i]; + if (mi_atomic_load_relaxed(®ion->info) != 0) { + // if no segments used, try to claim the whole region + uintptr_t m = mi_atomic_load_relaxed(®ion->in_use); + while (m == 0 && !mi_atomic_cas_weak_release(®ion->in_use, &m, MI_BITMAP_FIELD_FULL)) { /* nothing */ }; + if (m == 0) { + // on success, free the whole region + uint8_t* start = (uint8_t*)mi_atomic_load_ptr_acquire(uint8_t,®ions[i].start); + size_t arena_memid = mi_atomic_load_relaxed(®ions[i].arena_memid); + uintptr_t commit = mi_atomic_load_relaxed(®ions[i].commit); + memset(®ions[i], 0, sizeof(mem_region_t)); + // and release the whole region + mi_atomic_store_release(®ion->info, (uintptr_t)0); + if (start != NULL) { // && !_mi_os_is_huge_reserved(start)) { + _mi_abandoned_await_readers(); // ensure no pending reads + _mi_arena_free(start, MI_REGION_SIZE, arena_memid, (~commit == 0), tld->stats); + } + } + } + } +} + + +/* ---------------------------------------------------------------------------- + Other +-----------------------------------------------------------------------------*/ + +bool _mi_mem_reset(void* p, size_t size, mi_os_tld_t* tld) { + return _mi_os_reset(p, size, tld->stats); +} + +bool _mi_mem_unreset(void* p, size_t size, bool* is_zero, mi_os_tld_t* tld) { + return _mi_os_unreset(p, size, is_zero, tld->stats); +} + +bool _mi_mem_commit(void* p, size_t size, bool* is_zero, mi_os_tld_t* tld) { + return _mi_os_commit(p, size, is_zero, tld->stats); +} + +bool _mi_mem_decommit(void* p, size_t size, mi_os_tld_t* tld) { + return _mi_os_decommit(p, size, tld->stats); +} + +bool _mi_mem_protect(void* p, size_t size) { + return _mi_os_protect(p, size); +} + +bool _mi_mem_unprotect(void* p, size_t size) { + return _mi_os_unprotect(p, size); +} diff --git a/kotlin-native/runtime/src/mimalloc/c/segment.c b/kotlin-native/runtime/src/mimalloc/c/segment.c new file mode 100644 index 00000000000..b3585443fc0 --- /dev/null +++ b/kotlin-native/runtime/src/mimalloc/c/segment.c @@ -0,0 +1,1373 @@ +/* ---------------------------------------------------------------------------- +Copyright (c) 2018, Microsoft Research, Daan Leijen +This is free software; you can redistribute it and/or modify it under the +terms of the MIT license. A copy of the license can be found in the file +"licenses/third_party/mimalloc_LICENSE.txt" at the root of this distribution. +-----------------------------------------------------------------------------*/ +#include "mimalloc.h" +#include "mimalloc-internal.h" +#include "mimalloc-atomic.h" + +#include // memset +#include + +#define MI_PAGE_HUGE_ALIGN (256*1024) + +static uint8_t* mi_segment_raw_page_start(const mi_segment_t* segment, const mi_page_t* page, size_t* page_size); + +/* -------------------------------------------------------------------------------- + Segment allocation + We allocate pages inside bigger "segments" (4mb on 64-bit). This is to avoid + splitting VMA's on Linux and reduce fragmentation on other OS's. + Each thread owns its own segments. + + Currently we have: + - small pages (64kb), 64 in one segment + - medium pages (512kb), 8 in one segment + - large pages (4mb), 1 in one segment + - huge blocks > MI_LARGE_OBJ_SIZE_MAX become large segment with 1 page + + In any case the memory for a segment is virtual and usually committed on demand. + (i.e. we are careful to not touch the memory until we actually allocate a block there) + + If a thread ends, it "abandons" pages with used blocks + and there is an abandoned segment list whose segments can + be reclaimed by still running threads, much like work-stealing. +-------------------------------------------------------------------------------- */ + + +/* ----------------------------------------------------------- + Queue of segments containing free pages +----------------------------------------------------------- */ + +#if (MI_DEBUG>=3) +static bool mi_segment_queue_contains(const mi_segment_queue_t* queue, const mi_segment_t* segment) { + mi_assert_internal(segment != NULL); + mi_segment_t* list = queue->first; + while (list != NULL) { + if (list == segment) break; + mi_assert_internal(list->next==NULL || list->next->prev == list); + mi_assert_internal(list->prev==NULL || list->prev->next == list); + list = list->next; + } + return (list == segment); +} +#endif + +static bool mi_segment_queue_is_empty(const mi_segment_queue_t* queue) { + return (queue->first == NULL); +} + +static void mi_segment_queue_remove(mi_segment_queue_t* queue, mi_segment_t* segment) { + mi_assert_expensive(mi_segment_queue_contains(queue, segment)); + if (segment->prev != NULL) segment->prev->next = segment->next; + if (segment->next != NULL) segment->next->prev = segment->prev; + if (segment == queue->first) queue->first = segment->next; + if (segment == queue->last) queue->last = segment->prev; + segment->next = NULL; + segment->prev = NULL; +} + +static void mi_segment_enqueue(mi_segment_queue_t* queue, mi_segment_t* segment) { + mi_assert_expensive(!mi_segment_queue_contains(queue, segment)); + segment->next = NULL; + segment->prev = queue->last; + if (queue->last != NULL) { + mi_assert_internal(queue->last->next == NULL); + queue->last->next = segment; + queue->last = segment; + } + else { + queue->last = queue->first = segment; + } +} + +static mi_segment_queue_t* mi_segment_free_queue_of_kind(mi_page_kind_t kind, mi_segments_tld_t* tld) { + if (kind == MI_PAGE_SMALL) return &tld->small_free; + else if (kind == MI_PAGE_MEDIUM) return &tld->medium_free; + else return NULL; +} + +static mi_segment_queue_t* mi_segment_free_queue(const mi_segment_t* segment, mi_segments_tld_t* tld) { + return mi_segment_free_queue_of_kind(segment->page_kind, tld); +} + +// remove from free queue if it is in one +static void mi_segment_remove_from_free_queue(mi_segment_t* segment, mi_segments_tld_t* tld) { + mi_segment_queue_t* queue = mi_segment_free_queue(segment, tld); // may be NULL + bool in_queue = (queue!=NULL && (segment->next != NULL || segment->prev != NULL || queue->first == segment)); + if (in_queue) { + mi_segment_queue_remove(queue, segment); + } +} + +static void mi_segment_insert_in_free_queue(mi_segment_t* segment, mi_segments_tld_t* tld) { + mi_segment_enqueue(mi_segment_free_queue(segment, tld), segment); +} + + +/* ----------------------------------------------------------- + Invariant checking +----------------------------------------------------------- */ + +#if (MI_DEBUG>=2) +static bool mi_segment_is_in_free_queue(const mi_segment_t* segment, mi_segments_tld_t* tld) { + mi_segment_queue_t* queue = mi_segment_free_queue(segment, tld); + bool in_queue = (queue!=NULL && (segment->next != NULL || segment->prev != NULL || queue->first == segment)); + if (in_queue) { + mi_assert_expensive(mi_segment_queue_contains(queue, segment)); + } + return in_queue; +} +#endif + +static size_t mi_segment_page_size(const mi_segment_t* segment) { + if (segment->capacity > 1) { + mi_assert_internal(segment->page_kind <= MI_PAGE_MEDIUM); + return ((size_t)1 << segment->page_shift); + } + else { + mi_assert_internal(segment->page_kind >= MI_PAGE_LARGE); + return segment->segment_size; + } +} + + +#if (MI_DEBUG>=2) +static bool mi_pages_reset_contains(const mi_page_t* page, mi_segments_tld_t* tld) { + mi_page_t* p = tld->pages_reset.first; + while (p != NULL) { + if (p == page) return true; + p = p->next; + } + return false; +} +#endif + +#if (MI_DEBUG>=3) +static bool mi_segment_is_valid(const mi_segment_t* segment, mi_segments_tld_t* tld) { + mi_assert_internal(segment != NULL); + mi_assert_internal(_mi_ptr_cookie(segment) == segment->cookie); + mi_assert_internal(segment->used <= segment->capacity); + mi_assert_internal(segment->abandoned <= segment->used); + size_t nfree = 0; + for (size_t i = 0; i < segment->capacity; i++) { + const mi_page_t* const page = &segment->pages[i]; + if (!page->segment_in_use) { + nfree++; + } + if (page->segment_in_use || page->is_reset) { + mi_assert_expensive(!mi_pages_reset_contains(page, tld)); + } + } + mi_assert_internal(nfree + segment->used == segment->capacity); + // mi_assert_internal(segment->thread_id == _mi_thread_id() || (segment->thread_id==0)); // or 0 + mi_assert_internal(segment->page_kind == MI_PAGE_HUGE || + (mi_segment_page_size(segment) * segment->capacity == segment->segment_size)); + return true; +} +#endif + +static bool mi_page_not_in_queue(const mi_page_t* page, mi_segments_tld_t* tld) { + mi_assert_internal(page != NULL); + if (page->next != NULL || page->prev != NULL) { + mi_assert_internal(mi_pages_reset_contains(page, tld)); + return false; + } + else { + // both next and prev are NULL, check for singleton list + return (tld->pages_reset.first != page && tld->pages_reset.last != page); + } +} + + +/* ----------------------------------------------------------- + Guard pages +----------------------------------------------------------- */ + +static void mi_segment_protect_range(void* p, size_t size, bool protect) { + if (protect) { + _mi_mem_protect(p, size); + } + else { + _mi_mem_unprotect(p, size); + } +} + +static void mi_segment_protect(mi_segment_t* segment, bool protect, mi_os_tld_t* tld) { + // add/remove guard pages + if (MI_SECURE != 0) { + // in secure mode, we set up a protected page in between the segment info and the page data + const size_t os_psize = _mi_os_page_size(); + mi_assert_internal((segment->segment_info_size - os_psize) >= (sizeof(mi_segment_t) + ((segment->capacity - 1) * sizeof(mi_page_t)))); + mi_assert_internal(((uintptr_t)segment + segment->segment_info_size) % os_psize == 0); + mi_segment_protect_range((uint8_t*)segment + segment->segment_info_size - os_psize, os_psize, protect); + if (MI_SECURE <= 1 || segment->capacity == 1) { + // and protect the last (or only) page too + mi_assert_internal(MI_SECURE <= 1 || segment->page_kind >= MI_PAGE_LARGE); + uint8_t* start = (uint8_t*)segment + segment->segment_size - os_psize; + if (protect && !segment->mem_is_committed) { + if (protect) { + // ensure secure page is committed + if (_mi_mem_commit(start, os_psize, NULL, tld)) { // if this fails that is ok (as it is an unaccessible page) + mi_segment_protect_range(start, os_psize, protect); + } + } + } + else { + mi_segment_protect_range(start, os_psize, protect); + } + } + else { + // or protect every page + const size_t page_size = mi_segment_page_size(segment); + for (size_t i = 0; i < segment->capacity; i++) { + if (segment->pages[i].is_committed) { + mi_segment_protect_range((uint8_t*)segment + (i+1)*page_size - os_psize, os_psize, protect); + } + } + } + } +} + +/* ----------------------------------------------------------- + Page reset +----------------------------------------------------------- */ + +static void mi_page_reset(mi_segment_t* segment, mi_page_t* page, size_t size, mi_segments_tld_t* tld) { + mi_assert_internal(page->is_committed); + if (!mi_option_is_enabled(mi_option_page_reset)) return; + if (segment->mem_is_fixed || page->segment_in_use || !page->is_committed || page->is_reset) return; + size_t psize; + void* start = mi_segment_raw_page_start(segment, page, &psize); + page->is_reset = true; + mi_assert_internal(size <= psize); + size_t reset_size = ((size == 0 || size > psize) ? psize : size); + if (reset_size > 0) _mi_mem_reset(start, reset_size, tld->os); +} + +static bool mi_page_unreset(mi_segment_t* segment, mi_page_t* page, size_t size, mi_segments_tld_t* tld) +{ + mi_assert_internal(page->is_reset); + mi_assert_internal(page->is_committed); + mi_assert_internal(!segment->mem_is_fixed); + if (segment->mem_is_fixed || !page->is_committed || !page->is_reset) return true; + page->is_reset = false; + size_t psize; + uint8_t* start = mi_segment_raw_page_start(segment, page, &psize); + size_t unreset_size = (size == 0 || size > psize ? psize : size); + bool is_zero = false; + bool ok = true; + if (unreset_size > 0) { + ok = _mi_mem_unreset(start, unreset_size, &is_zero, tld->os); + } + if (is_zero) page->is_zero_init = true; + return ok; +} + + +/* ----------------------------------------------------------- + The free page queue +----------------------------------------------------------- */ + +// we re-use the `used` field for the expiration counter. Since this is a +// a 32-bit field while the clock is always 64-bit we need to guard +// against overflow, we use substraction to check for expiry which work +// as long as the reset delay is under (2^30 - 1) milliseconds (~12 days) +static void mi_page_reset_set_expire(mi_page_t* page) { + uint32_t expire = (uint32_t)_mi_clock_now() + mi_option_get(mi_option_reset_delay); + page->used = expire; +} + +static bool mi_page_reset_is_expired(mi_page_t* page, mi_msecs_t now) { + int32_t expire = (int32_t)(page->used); + return (((int32_t)now - expire) >= 0); +} + +static void mi_pages_reset_add(mi_segment_t* segment, mi_page_t* page, mi_segments_tld_t* tld) { + mi_assert_internal(!page->segment_in_use || !page->is_committed); + mi_assert_internal(mi_page_not_in_queue(page,tld)); + mi_assert_expensive(!mi_pages_reset_contains(page, tld)); + mi_assert_internal(_mi_page_segment(page)==segment); + if (!mi_option_is_enabled(mi_option_page_reset)) return; + if (segment->mem_is_fixed || page->segment_in_use || !page->is_committed || page->is_reset) return; + + if (mi_option_get(mi_option_reset_delay) == 0) { + // reset immediately? + mi_page_reset(segment, page, 0, tld); + } + else { + // otherwise push on the delayed page reset queue + mi_page_queue_t* pq = &tld->pages_reset; + // push on top + mi_page_reset_set_expire(page); + page->next = pq->first; + page->prev = NULL; + if (pq->first == NULL) { + mi_assert_internal(pq->last == NULL); + pq->first = pq->last = page; + } + else { + pq->first->prev = page; + pq->first = page; + } + } +} + +static void mi_pages_reset_remove(mi_page_t* page, mi_segments_tld_t* tld) { + if (mi_page_not_in_queue(page,tld)) return; + + mi_page_queue_t* pq = &tld->pages_reset; + mi_assert_internal(pq!=NULL); + mi_assert_internal(!page->segment_in_use); + mi_assert_internal(mi_pages_reset_contains(page, tld)); + if (page->prev != NULL) page->prev->next = page->next; + if (page->next != NULL) page->next->prev = page->prev; + if (page == pq->last) pq->last = page->prev; + if (page == pq->first) pq->first = page->next; + page->next = page->prev = NULL; + page->used = 0; +} + +static void mi_pages_reset_remove_all_in_segment(mi_segment_t* segment, bool force_reset, mi_segments_tld_t* tld) { + if (segment->mem_is_fixed) return; // never reset in huge OS pages + for (size_t i = 0; i < segment->capacity; i++) { + mi_page_t* page = &segment->pages[i]; + if (!page->segment_in_use && page->is_committed && !page->is_reset) { + mi_pages_reset_remove(page, tld); + if (force_reset) { + mi_page_reset(segment, page, 0, tld); + } + } + else { + mi_assert_internal(mi_page_not_in_queue(page,tld)); + } + } +} + +static void mi_reset_delayed(mi_segments_tld_t* tld) { + if (!mi_option_is_enabled(mi_option_page_reset)) return; + mi_msecs_t now = _mi_clock_now(); + mi_page_queue_t* pq = &tld->pages_reset; + // from oldest up to the first that has not expired yet + mi_page_t* page = pq->last; + while (page != NULL && mi_page_reset_is_expired(page,now)) { + mi_page_t* const prev = page->prev; // save previous field + mi_page_reset(_mi_page_segment(page), page, 0, tld); + page->used = 0; + page->prev = page->next = NULL; + page = prev; + } + // discard the reset pages from the queue + pq->last = page; + if (page != NULL){ + page->next = NULL; + } + else { + pq->first = NULL; + } +} + + +/* ----------------------------------------------------------- + Segment size calculations +----------------------------------------------------------- */ + +// Raw start of the page available memory; can be used on uninitialized pages (only `segment_idx` must be set) +// The raw start is not taking aligned block allocation into consideration. +static uint8_t* mi_segment_raw_page_start(const mi_segment_t* segment, const mi_page_t* page, size_t* page_size) { + size_t psize = (segment->page_kind == MI_PAGE_HUGE ? segment->segment_size : (size_t)1 << segment->page_shift); + uint8_t* p = (uint8_t*)segment + page->segment_idx * psize; + + if (page->segment_idx == 0) { + // the first page starts after the segment info (and possible guard page) + p += segment->segment_info_size; + psize -= segment->segment_info_size; + } + + if (MI_SECURE > 1 || (MI_SECURE == 1 && page->segment_idx == segment->capacity - 1)) { + // secure == 1: the last page has an os guard page at the end + // secure > 1: every page has an os guard page + psize -= _mi_os_page_size(); + } + + if (page_size != NULL) *page_size = psize; + mi_assert_internal(page->xblock_size == 0 || _mi_ptr_page(p) == page); + mi_assert_internal(_mi_ptr_segment(p) == segment); + return p; +} + +// Start of the page available memory; can be used on uninitialized pages (only `segment_idx` must be set) +uint8_t* _mi_segment_page_start(const mi_segment_t* segment, const mi_page_t* page, size_t block_size, size_t* page_size, size_t* pre_size) +{ + size_t psize; + uint8_t* p = mi_segment_raw_page_start(segment, page, &psize); + if (pre_size != NULL) *pre_size = 0; + if (page->segment_idx == 0 && block_size > 0 && segment->page_kind <= MI_PAGE_MEDIUM) { + // for small and medium objects, ensure the page start is aligned with the block size (PR#66 by kickunderscore) + size_t adjust = block_size - ((uintptr_t)p % block_size); + if (adjust < block_size) { + p += adjust; + psize -= adjust; + if (pre_size != NULL) *pre_size = adjust; + } + mi_assert_internal((uintptr_t)p % block_size == 0); + } + + if (page_size != NULL) *page_size = psize; + mi_assert_internal(page->xblock_size==0 || _mi_ptr_page(p) == page); + mi_assert_internal(_mi_ptr_segment(p) == segment); + return p; +} + +static size_t mi_segment_size(size_t capacity, size_t required, size_t* pre_size, size_t* info_size) +{ + const size_t minsize = sizeof(mi_segment_t) + ((capacity - 1) * sizeof(mi_page_t)) + 16 /* padding */; + size_t guardsize = 0; + size_t isize = 0; + + if (MI_SECURE == 0) { + // normally no guard pages + isize = _mi_align_up(minsize, 16 * MI_MAX_ALIGN_SIZE); + } + else { + // in secure mode, we set up a protected page in between the segment info + // and the page data (and one at the end of the segment) + const size_t page_size = _mi_os_page_size(); + isize = _mi_align_up(minsize, page_size); + guardsize = page_size; + required = _mi_align_up(required, page_size); + } + + if (info_size != NULL) *info_size = isize; + if (pre_size != NULL) *pre_size = isize + guardsize; + return (required==0 ? MI_SEGMENT_SIZE : _mi_align_up( required + isize + 2*guardsize, MI_PAGE_HUGE_ALIGN) ); +} + + +/* ---------------------------------------------------------------------------- +Segment caches +We keep a small segment cache per thread to increase local +reuse and avoid setting/clearing guard pages in secure mode. +------------------------------------------------------------------------------- */ + +static void mi_segments_track_size(long segment_size, mi_segments_tld_t* tld) { + if (segment_size>=0) _mi_stat_increase(&tld->stats->segments,1); + else _mi_stat_decrease(&tld->stats->segments,1); + tld->count += (segment_size >= 0 ? 1 : -1); + if (tld->count > tld->peak_count) tld->peak_count = tld->count; + tld->current_size += segment_size; + if (tld->current_size > tld->peak_size) tld->peak_size = tld->current_size; +} + +static void mi_segment_os_free(mi_segment_t* segment, size_t segment_size, mi_segments_tld_t* tld) { + segment->thread_id = 0; + mi_segments_track_size(-((long)segment_size),tld); + if (MI_SECURE != 0) { + mi_assert_internal(!segment->mem_is_fixed); + mi_segment_protect(segment, false, tld->os); // ensure no more guard pages are set + } + + bool any_reset = false; + bool fully_committed = true; + for (size_t i = 0; i < segment->capacity; i++) { + mi_page_t* page = &segment->pages[i]; + if (!page->is_committed) { fully_committed = false; } + if (page->is_reset) { any_reset = true; } + } + if (any_reset && mi_option_is_enabled(mi_option_reset_decommits)) { + fully_committed = false; + } + _mi_mem_free(segment, segment_size, segment->memid, fully_committed, any_reset, tld->os); +} + + +// The thread local segment cache is limited to be at most 1/8 of the peak size of segments in use, +#define MI_SEGMENT_CACHE_FRACTION (8) + +// note: returned segment may be partially reset +static mi_segment_t* mi_segment_cache_pop(size_t segment_size, mi_segments_tld_t* tld) { + if (segment_size != 0 && segment_size != MI_SEGMENT_SIZE) return NULL; + mi_segment_t* segment = tld->cache; + if (segment == NULL) return NULL; + tld->cache_count--; + tld->cache = segment->next; + segment->next = NULL; + mi_assert_internal(segment->segment_size == MI_SEGMENT_SIZE); + _mi_stat_decrease(&tld->stats->segments_cache, 1); + return segment; +} + +static bool mi_segment_cache_full(mi_segments_tld_t* tld) +{ + // if (tld->count == 1 && tld->cache_count==0) return false; // always cache at least the final segment of a thread + size_t max_cache = mi_option_get(mi_option_segment_cache); + if (tld->cache_count < max_cache + && tld->cache_count < (1 + (tld->peak_count / MI_SEGMENT_CACHE_FRACTION)) // at least allow a 1 element cache + ) { + return false; + } + // take the opportunity to reduce the segment cache if it is too large (now) + // TODO: this never happens as we check against peak usage, should we use current usage instead? + while (tld->cache_count > max_cache) { //(1 + (tld->peak_count / MI_SEGMENT_CACHE_FRACTION))) { + mi_segment_t* segment = mi_segment_cache_pop(0,tld); + mi_assert_internal(segment != NULL); + if (segment != NULL) mi_segment_os_free(segment, segment->segment_size, tld); + } + return true; +} + +static bool mi_segment_cache_push(mi_segment_t* segment, mi_segments_tld_t* tld) { + mi_assert_internal(!mi_segment_is_in_free_queue(segment, tld)); + mi_assert_internal(segment->next == NULL); + if (segment->segment_size != MI_SEGMENT_SIZE || mi_segment_cache_full(tld)) { + return false; + } + mi_assert_internal(segment->segment_size == MI_SEGMENT_SIZE); + segment->next = tld->cache; + tld->cache = segment; + tld->cache_count++; + _mi_stat_increase(&tld->stats->segments_cache,1); + return true; +} + +// called by threads that are terminating to free cached segments +void _mi_segment_thread_collect(mi_segments_tld_t* tld) { + mi_segment_t* segment; + while ((segment = mi_segment_cache_pop(0,tld)) != NULL) { + mi_segment_os_free(segment, segment->segment_size, tld); + } + mi_assert_internal(tld->cache_count == 0); + mi_assert_internal(tld->cache == NULL); +#if MI_DEBUG>=2 + if (!_mi_is_main_thread()) { + mi_assert_internal(tld->pages_reset.first == NULL); + mi_assert_internal(tld->pages_reset.last == NULL); + } +#endif +} + + +/* ----------------------------------------------------------- + Segment allocation +----------------------------------------------------------- */ + +// Allocate a segment from the OS aligned to `MI_SEGMENT_SIZE` . +static mi_segment_t* mi_segment_init(mi_segment_t* segment, size_t required, mi_page_kind_t page_kind, size_t page_shift, mi_segments_tld_t* tld, mi_os_tld_t* os_tld) +{ + // the segment parameter is non-null if it came from our cache + mi_assert_internal(segment==NULL || (required==0 && page_kind <= MI_PAGE_LARGE)); + + // calculate needed sizes first + size_t capacity; + if (page_kind == MI_PAGE_HUGE) { + mi_assert_internal(page_shift == MI_SEGMENT_SHIFT && required > 0); + capacity = 1; + } + else { + mi_assert_internal(required == 0); + size_t page_size = (size_t)1 << page_shift; + capacity = MI_SEGMENT_SIZE / page_size; + mi_assert_internal(MI_SEGMENT_SIZE % page_size == 0); + mi_assert_internal(capacity >= 1 && capacity <= MI_SMALL_PAGES_PER_SEGMENT); + } + size_t info_size; + size_t pre_size; + size_t segment_size = mi_segment_size(capacity, required, &pre_size, &info_size); + mi_assert_internal(segment_size >= required); + + // Initialize parameters + const bool eager_delayed = (page_kind <= MI_PAGE_MEDIUM && tld->count < (size_t)mi_option_get(mi_option_eager_commit_delay)); + const bool eager = !eager_delayed && mi_option_is_enabled(mi_option_eager_commit); + bool commit = eager; // || (page_kind >= MI_PAGE_LARGE); + bool pages_still_good = false; + bool is_zero = false; + + // Try to get it from our thread local cache first + if (segment != NULL) { + // came from cache + mi_assert_internal(segment->segment_size == segment_size); + if (page_kind <= MI_PAGE_MEDIUM && segment->page_kind == page_kind && segment->segment_size == segment_size) { + pages_still_good = true; + } + else + { + if (MI_SECURE!=0) { + mi_assert_internal(!segment->mem_is_fixed); + mi_segment_protect(segment, false, tld->os); // reset protection if the page kind differs + } + // different page kinds; unreset any reset pages, and unprotect + // TODO: optimize cache pop to return fitting pages if possible? + for (size_t i = 0; i < segment->capacity; i++) { + mi_page_t* page = &segment->pages[i]; + if (page->is_reset) { + if (!commit && mi_option_is_enabled(mi_option_reset_decommits)) { + page->is_reset = false; + } + else { + mi_page_unreset(segment, page, 0, tld); // todo: only unreset the part that was reset? (instead of the full page) + } + } + } + // ensure the initial info is committed + if (segment->capacity < capacity) { + bool commit_zero = false; + bool ok = _mi_mem_commit(segment, pre_size, &commit_zero, tld->os); + if (commit_zero) is_zero = true; + if (!ok) { + return NULL; + } + } + } + } + else { + // Allocate the segment from the OS + size_t memid; + bool mem_large = (!eager_delayed && (MI_SECURE==0)); // only allow large OS pages once we are no longer lazy + segment = (mi_segment_t*)_mi_mem_alloc_aligned(segment_size, MI_SEGMENT_SIZE, &commit, &mem_large, &is_zero, &memid, os_tld); + if (segment == NULL) return NULL; // failed to allocate + if (!commit) { + // ensure the initial info is committed + bool commit_zero = false; + bool ok = _mi_mem_commit(segment, pre_size, &commit_zero, tld->os); + if (commit_zero) is_zero = true; + if (!ok) { + // commit failed; we cannot touch the memory: free the segment directly and return `NULL` + _mi_mem_free(segment, MI_SEGMENT_SIZE, memid, false, false, os_tld); + return NULL; + } + } + segment->memid = memid; + segment->mem_is_fixed = mem_large; + segment->mem_is_committed = commit; + mi_segments_track_size((long)segment_size, tld); + } + mi_assert_internal(segment != NULL && (uintptr_t)segment % MI_SEGMENT_SIZE == 0); + mi_assert_internal(segment->mem_is_fixed ? segment->mem_is_committed : true); + mi_atomic_store_ptr_release(mi_segment_t, &segment->abandoned_next, NULL); // tsan + if (!pages_still_good) { + // zero the segment info (but not the `mem` fields) + ptrdiff_t ofs = offsetof(mi_segment_t, next); + memset((uint8_t*)segment + ofs, 0, info_size - ofs); + + // initialize pages info + for (uint8_t i = 0; i < capacity; i++) { + segment->pages[i].segment_idx = i; + segment->pages[i].is_reset = false; + segment->pages[i].is_committed = commit; + segment->pages[i].is_zero_init = is_zero; + } + } + else { + // zero the segment info but not the pages info (and mem fields) + ptrdiff_t ofs = offsetof(mi_segment_t, next); + memset((uint8_t*)segment + ofs, 0, offsetof(mi_segment_t,pages) - ofs); + } + + // initialize + segment->page_kind = page_kind; + segment->capacity = capacity; + segment->page_shift = page_shift; + segment->segment_size = segment_size; + segment->segment_info_size = pre_size; + segment->thread_id = _mi_thread_id(); + segment->cookie = _mi_ptr_cookie(segment); + // _mi_stat_increase(&tld->stats->page_committed, segment->segment_info_size); + + // set protection + mi_segment_protect(segment, true, tld->os); + + // insert in free lists for small and medium pages + if (page_kind <= MI_PAGE_MEDIUM) { + mi_segment_insert_in_free_queue(segment, tld); + } + + //fprintf(stderr,"mimalloc: alloc segment at %p\n", (void*)segment); + return segment; +} + +static mi_segment_t* mi_segment_alloc(size_t required, mi_page_kind_t page_kind, size_t page_shift, mi_segments_tld_t* tld, mi_os_tld_t* os_tld) { + return mi_segment_init(NULL, required, page_kind, page_shift, tld, os_tld); +} + +static void mi_segment_free(mi_segment_t* segment, bool force, mi_segments_tld_t* tld) { + UNUSED(force); + mi_assert(segment != NULL); + // note: don't reset pages even on abandon as the whole segment is freed? (and ready for reuse) + bool force_reset = (force && mi_option_is_enabled(mi_option_abandoned_page_reset)); + mi_pages_reset_remove_all_in_segment(segment, force_reset, tld); + mi_segment_remove_from_free_queue(segment,tld); + + mi_assert_expensive(!mi_segment_queue_contains(&tld->small_free, segment)); + mi_assert_expensive(!mi_segment_queue_contains(&tld->medium_free, segment)); + mi_assert(segment->next == NULL); + mi_assert(segment->prev == NULL); + _mi_stat_decrease(&tld->stats->page_committed, segment->segment_info_size); + + if (!force && mi_segment_cache_push(segment, tld)) { + // it is put in our cache + } + else { + // otherwise return it to the OS + mi_segment_os_free(segment, segment->segment_size, tld); + } +} + +/* ----------------------------------------------------------- + Free page management inside a segment +----------------------------------------------------------- */ + + +static bool mi_segment_has_free(const mi_segment_t* segment) { + return (segment->used < segment->capacity); +} + +static bool mi_segment_page_claim(mi_segment_t* segment, mi_page_t* page, mi_segments_tld_t* tld) { + mi_assert_internal(_mi_page_segment(page) == segment); + mi_assert_internal(!page->segment_in_use); + mi_pages_reset_remove(page, tld); + // check commit + if (!page->is_committed) { + mi_assert_internal(!segment->mem_is_fixed); + mi_assert_internal(!page->is_reset); + size_t psize; + uint8_t* start = mi_segment_raw_page_start(segment, page, &psize); + bool is_zero = false; + const size_t gsize = (MI_SECURE >= 2 ? _mi_os_page_size() : 0); + bool ok = _mi_mem_commit(start, psize + gsize, &is_zero, tld->os); + if (!ok) return false; // failed to commit! + if (gsize > 0) { mi_segment_protect_range(start + psize, gsize, true); } + if (is_zero) { page->is_zero_init = true; } + page->is_committed = true; + } + // set in-use before doing unreset to prevent delayed reset + page->segment_in_use = true; + segment->used++; + // check reset + if (page->is_reset) { + mi_assert_internal(!segment->mem_is_fixed); + bool ok = mi_page_unreset(segment, page, 0, tld); + if (!ok) { + page->segment_in_use = false; + segment->used--; + return false; + } + } + mi_assert_internal(page->segment_in_use); + mi_assert_internal(segment->used <= segment->capacity); + if (segment->used == segment->capacity && segment->page_kind <= MI_PAGE_MEDIUM) { + // if no more free pages, remove from the queue + mi_assert_internal(!mi_segment_has_free(segment)); + mi_segment_remove_from_free_queue(segment, tld); + } + return true; +} + + +/* ----------------------------------------------------------- + Free +----------------------------------------------------------- */ + +static void mi_segment_abandon(mi_segment_t* segment, mi_segments_tld_t* tld); + +// clear page data; can be called on abandoned segments +static void mi_segment_page_clear(mi_segment_t* segment, mi_page_t* page, bool allow_reset, mi_segments_tld_t* tld) +{ + mi_assert_internal(page->segment_in_use); + mi_assert_internal(mi_page_all_free(page)); + mi_assert_internal(page->is_committed); + mi_assert_internal(mi_page_not_in_queue(page, tld)); + + size_t inuse = page->capacity * mi_page_block_size(page); + _mi_stat_decrease(&tld->stats->page_committed, inuse); + _mi_stat_decrease(&tld->stats->pages, 1); + + // calculate the used size from the raw (non-aligned) start of the page + //size_t pre_size; + //_mi_segment_page_start(segment, page, page->block_size, NULL, &pre_size); + //size_t used_size = pre_size + (page->capacity * page->block_size); + + page->is_zero_init = false; + page->segment_in_use = false; + + // reset the page memory to reduce memory pressure? + // note: must come after setting `segment_in_use` to false but before block_size becomes 0 + //mi_page_reset(segment, page, 0 /*used_size*/, tld); + + // zero the page data, but not the segment fields and capacity, and block_size (for page size calculations) + uint32_t block_size = page->xblock_size; + uint16_t capacity = page->capacity; + uint16_t reserved = page->reserved; + ptrdiff_t ofs = offsetof(mi_page_t,capacity); + memset((uint8_t*)page + ofs, 0, sizeof(*page) - ofs); + page->capacity = capacity; + page->reserved = reserved; + page->xblock_size = block_size; + segment->used--; + + // add to the free page list for reuse/reset + if (allow_reset) { + mi_pages_reset_add(segment, page, tld); + } + + page->capacity = 0; // after reset these can be zero'd now + page->reserved = 0; +} + +void _mi_segment_page_free(mi_page_t* page, bool force, mi_segments_tld_t* tld) +{ + mi_assert(page != NULL); + mi_segment_t* segment = _mi_page_segment(page); + mi_assert_expensive(mi_segment_is_valid(segment,tld)); + mi_reset_delayed(tld); + + // mark it as free now + mi_segment_page_clear(segment, page, true, tld); + + if (segment->used == 0) { + // no more used pages; remove from the free list and free the segment + mi_segment_free(segment, force, tld); + } + else { + if (segment->used == segment->abandoned) { + // only abandoned pages; remove from free list and abandon + mi_segment_abandon(segment,tld); + } + else if (segment->used + 1 == segment->capacity) { + mi_assert_internal(segment->page_kind <= MI_PAGE_MEDIUM); // for now we only support small and medium pages + // move back to segments free list + mi_segment_insert_in_free_queue(segment,tld); + } + } +} + + +/* ----------------------------------------------------------- +Abandonment + +When threads terminate, they can leave segments with +live blocks (reached through other threads). Such segments +are "abandoned" and will be reclaimed by other threads to +reuse their pages and/or free them eventually + +We maintain a global list of abandoned segments that are +reclaimed on demand. Since this is shared among threads +the implementation needs to avoid the A-B-A problem on +popping abandoned segments: +We use tagged pointers to avoid accidentially identifying +reused segments, much like stamped references in Java. +Secondly, we maintain a reader counter to avoid resetting +or decommitting segments that have a pending read operation. + +Note: the current implementation is one possible design; +another way might be to keep track of abandoned segments +in the regions. This would have the advantage of keeping +all concurrent code in one place and not needing to deal +with ABA issues. The drawback is that it is unclear how to +scan abandoned segments efficiently in that case as they +would be spread among all other segments in the regions. +----------------------------------------------------------- */ + +// Use the bottom 20-bits (on 64-bit) of the aligned segment pointers +// to put in a tag that increments on update to avoid the A-B-A problem. +#define MI_TAGGED_MASK MI_SEGMENT_MASK +typedef uintptr_t mi_tagged_segment_t; + +static mi_segment_t* mi_tagged_segment_ptr(mi_tagged_segment_t ts) { + return (mi_segment_t*)(ts & ~MI_TAGGED_MASK); +} + +static mi_tagged_segment_t mi_tagged_segment(mi_segment_t* segment, mi_tagged_segment_t ts) { + mi_assert_internal(((uintptr_t)segment & MI_TAGGED_MASK) == 0); + uintptr_t tag = ((ts & MI_TAGGED_MASK) + 1) & MI_TAGGED_MASK; + return ((uintptr_t)segment | tag); +} + +// This is a list of visited abandoned pages that were full at the time. +// this list migrates to `abandoned` when that becomes NULL. The use of +// this list reduces contention and the rate at which segments are visited. +static mi_decl_cache_align _Atomic(mi_segment_t*) abandoned_visited; // = NULL + +// The abandoned page list (tagged as it supports pop) +static mi_decl_cache_align _Atomic(mi_tagged_segment_t) abandoned; // = NULL + +// Maintain these for debug purposes (these counts may be a bit off) +static mi_decl_cache_align _Atomic(uintptr_t) abandoned_count; +static mi_decl_cache_align _Atomic(uintptr_t) abandoned_visited_count; + +// We also maintain a count of current readers of the abandoned list +// in order to prevent resetting/decommitting segment memory if it might +// still be read. +static mi_decl_cache_align _Atomic(uintptr_t) abandoned_readers; // = 0 + +// Push on the visited list +static void mi_abandoned_visited_push(mi_segment_t* segment) { + mi_assert_internal(segment->thread_id == 0); + mi_assert_internal(mi_atomic_load_ptr_relaxed(mi_segment_t,&segment->abandoned_next) == NULL); + mi_assert_internal(segment->next == NULL && segment->prev == NULL); + mi_assert_internal(segment->used > 0); + mi_segment_t* anext = mi_atomic_load_ptr_relaxed(mi_segment_t, &abandoned_visited); + do { + mi_atomic_store_ptr_release(mi_segment_t, &segment->abandoned_next, anext); + } while (!mi_atomic_cas_ptr_weak_release(mi_segment_t, &abandoned_visited, &anext, segment)); + mi_atomic_increment_relaxed(&abandoned_visited_count); +} + +// Move the visited list to the abandoned list. +static bool mi_abandoned_visited_revisit(void) +{ + // quick check if the visited list is empty + if (mi_atomic_load_ptr_relaxed(mi_segment_t, &abandoned_visited) == NULL) return false; + + // grab the whole visited list + mi_segment_t* first = mi_atomic_exchange_ptr_acq_rel(mi_segment_t, &abandoned_visited, NULL); + if (first == NULL) return false; + + // first try to swap directly if the abandoned list happens to be NULL + mi_tagged_segment_t afirst; + mi_tagged_segment_t ts = mi_atomic_load_relaxed(&abandoned); + if (mi_tagged_segment_ptr(ts)==NULL) { + uintptr_t count = mi_atomic_load_relaxed(&abandoned_visited_count); + afirst = mi_tagged_segment(first, ts); + if (mi_atomic_cas_strong_acq_rel(&abandoned, &ts, afirst)) { + mi_atomic_add_relaxed(&abandoned_count, count); + mi_atomic_sub_relaxed(&abandoned_visited_count, count); + return true; + } + } + + // find the last element of the visited list: O(n) + mi_segment_t* last = first; + mi_segment_t* next; + while ((next = mi_atomic_load_ptr_relaxed(mi_segment_t, &last->abandoned_next)) != NULL) { + last = next; + } + + // and atomically prepend to the abandoned list + // (no need to increase the readers as we don't access the abandoned segments) + mi_tagged_segment_t anext = mi_atomic_load_relaxed(&abandoned); + uintptr_t count; + do { + count = mi_atomic_load_relaxed(&abandoned_visited_count); + mi_atomic_store_ptr_release(mi_segment_t, &last->abandoned_next, mi_tagged_segment_ptr(anext)); + afirst = mi_tagged_segment(first, anext); + } while (!mi_atomic_cas_weak_release(&abandoned, &anext, afirst)); + mi_atomic_add_relaxed(&abandoned_count, count); + mi_atomic_sub_relaxed(&abandoned_visited_count, count); + return true; +} + +// Push on the abandoned list. +static void mi_abandoned_push(mi_segment_t* segment) { + mi_assert_internal(segment->thread_id == 0); + mi_assert_internal(mi_atomic_load_ptr_relaxed(mi_segment_t, &segment->abandoned_next) == NULL); + mi_assert_internal(segment->next == NULL && segment->prev == NULL); + mi_assert_internal(segment->used > 0); + mi_tagged_segment_t next; + mi_tagged_segment_t ts = mi_atomic_load_relaxed(&abandoned); + do { + mi_atomic_store_ptr_release(mi_segment_t, &segment->abandoned_next, mi_tagged_segment_ptr(ts)); + next = mi_tagged_segment(segment, ts); + } while (!mi_atomic_cas_weak_release(&abandoned, &ts, next)); + mi_atomic_increment_relaxed(&abandoned_count); +} + +// Wait until there are no more pending reads on segments that used to be in the abandoned list +void _mi_abandoned_await_readers(void) { + uintptr_t n; + do { + n = mi_atomic_load_acquire(&abandoned_readers); + if (n != 0) mi_atomic_yield(); + } while (n != 0); +} + +// Pop from the abandoned list +static mi_segment_t* mi_abandoned_pop(void) { + mi_segment_t* segment; + // Check efficiently if it is empty (or if the visited list needs to be moved) + mi_tagged_segment_t ts = mi_atomic_load_relaxed(&abandoned); + segment = mi_tagged_segment_ptr(ts); + if (mi_likely(segment == NULL)) { + if (mi_likely(!mi_abandoned_visited_revisit())) { // try to swap in the visited list on NULL + return NULL; + } + } + + // Do a pop. We use a reader count to prevent + // a segment to be decommitted while a read is still pending, + // and a tagged pointer to prevent A-B-A link corruption. + // (this is called from `region.c:_mi_mem_free` for example) + mi_atomic_increment_relaxed(&abandoned_readers); // ensure no segment gets decommitted + mi_tagged_segment_t next = 0; + ts = mi_atomic_load_acquire(&abandoned); + do { + segment = mi_tagged_segment_ptr(ts); + if (segment != NULL) { + mi_segment_t* anext = mi_atomic_load_ptr_relaxed(mi_segment_t, &segment->abandoned_next); + next = mi_tagged_segment(anext, ts); // note: reads the segment's `abandoned_next` field so should not be decommitted + } + } while (segment != NULL && !mi_atomic_cas_weak_acq_rel(&abandoned, &ts, next)); + mi_atomic_decrement_relaxed(&abandoned_readers); // release reader lock + if (segment != NULL) { + mi_atomic_store_ptr_release(mi_segment_t, &segment->abandoned_next, NULL); + mi_atomic_decrement_relaxed(&abandoned_count); + } + return segment; +} + +/* ----------------------------------------------------------- + Abandon segment/page +----------------------------------------------------------- */ + +static void mi_segment_abandon(mi_segment_t* segment, mi_segments_tld_t* tld) { + mi_assert_internal(segment->used == segment->abandoned); + mi_assert_internal(segment->used > 0); + mi_assert_internal(mi_atomic_load_ptr_relaxed(mi_segment_t, &segment->abandoned_next) == NULL); + mi_assert_expensive(mi_segment_is_valid(segment, tld)); + + // remove the segment from the free page queue if needed + mi_reset_delayed(tld); + mi_pages_reset_remove_all_in_segment(segment, mi_option_is_enabled(mi_option_abandoned_page_reset), tld); + mi_segment_remove_from_free_queue(segment, tld); + mi_assert_internal(segment->next == NULL && segment->prev == NULL); + + // all pages in the segment are abandoned; add it to the abandoned list + _mi_stat_increase(&tld->stats->segments_abandoned, 1); + mi_segments_track_size(-((long)segment->segment_size), tld); + segment->thread_id = 0; + segment->abandoned_visits = 0; + mi_atomic_store_ptr_release(mi_segment_t, &segment->abandoned_next, NULL); + mi_abandoned_push(segment); +} + +void _mi_segment_page_abandon(mi_page_t* page, mi_segments_tld_t* tld) { + mi_assert(page != NULL); + mi_assert_internal(mi_page_thread_free_flag(page)==MI_NEVER_DELAYED_FREE); + mi_assert_internal(mi_page_heap(page) == NULL); + mi_segment_t* segment = _mi_page_segment(page); + mi_assert_expensive(!mi_pages_reset_contains(page, tld)); + mi_assert_expensive(mi_segment_is_valid(segment, tld)); + segment->abandoned++; + _mi_stat_increase(&tld->stats->pages_abandoned, 1); + mi_assert_internal(segment->abandoned <= segment->used); + if (segment->used == segment->abandoned) { + // all pages are abandoned, abandon the entire segment + mi_segment_abandon(segment, tld); + } +} + +/* ----------------------------------------------------------- + Reclaim abandoned pages +----------------------------------------------------------- */ + +// Possibly clear pages and check if free space is available +static bool mi_segment_check_free(mi_segment_t* segment, size_t block_size, bool* all_pages_free) +{ + mi_assert_internal(block_size < MI_HUGE_BLOCK_SIZE); + bool has_page = false; + size_t pages_used = 0; + size_t pages_used_empty = 0; + for (size_t i = 0; i < segment->capacity; i++) { + mi_page_t* page = &segment->pages[i]; + if (page->segment_in_use) { + pages_used++; + // ensure used count is up to date and collect potential concurrent frees + _mi_page_free_collect(page, false); + if (mi_page_all_free(page)) { + // if everything free already, page can be reused for some block size + // note: don't clear the page yet as we can only OS reset it once it is reclaimed + pages_used_empty++; + has_page = true; + } + else if (page->xblock_size == block_size && mi_page_has_any_available(page)) { + // a page has available free blocks of the right size + has_page = true; + } + } + else { + // whole empty page + has_page = true; + } + } + mi_assert_internal(pages_used == segment->used && pages_used >= pages_used_empty); + if (all_pages_free != NULL) { + *all_pages_free = ((pages_used - pages_used_empty) == 0); + } + return has_page; +} + + +// Reclaim a segment; returns NULL if the segment was freed +// set `right_page_reclaimed` to `true` if it reclaimed a page of the right `block_size` that was not full. +static mi_segment_t* mi_segment_reclaim(mi_segment_t* segment, mi_heap_t* heap, size_t requested_block_size, bool* right_page_reclaimed, mi_segments_tld_t* tld) { + mi_assert_internal(mi_atomic_load_ptr_relaxed(mi_segment_t, &segment->abandoned_next) == NULL); + if (right_page_reclaimed != NULL) { *right_page_reclaimed = false; } + + segment->thread_id = _mi_thread_id(); + segment->abandoned_visits = 0; + mi_segments_track_size((long)segment->segment_size, tld); + mi_assert_internal(segment->next == NULL && segment->prev == NULL); + mi_assert_expensive(mi_segment_is_valid(segment, tld)); + _mi_stat_decrease(&tld->stats->segments_abandoned, 1); + + for (size_t i = 0; i < segment->capacity; i++) { + mi_page_t* page = &segment->pages[i]; + if (page->segment_in_use) { + mi_assert_internal(!page->is_reset); + mi_assert_internal(page->is_committed); + mi_assert_internal(mi_page_not_in_queue(page, tld)); + mi_assert_internal(mi_page_thread_free_flag(page)==MI_NEVER_DELAYED_FREE); + mi_assert_internal(mi_page_heap(page) == NULL); + segment->abandoned--; + mi_assert(page->next == NULL); + _mi_stat_decrease(&tld->stats->pages_abandoned, 1); + // set the heap again and allow heap thread delayed free again. + mi_page_set_heap(page, heap); + _mi_page_use_delayed_free(page, MI_USE_DELAYED_FREE, true); // override never (after heap is set) + // TODO: should we not collect again given that we just collected in `check_free`? + _mi_page_free_collect(page, false); // ensure used count is up to date + if (mi_page_all_free(page)) { + // if everything free already, clear the page directly + mi_segment_page_clear(segment, page, true, tld); // reset is ok now + } + else { + // otherwise reclaim it into the heap + _mi_page_reclaim(heap, page); + if (requested_block_size == page->xblock_size && mi_page_has_any_available(page)) { + if (right_page_reclaimed != NULL) { *right_page_reclaimed = true; } + } + } + } + else if (page->is_committed && !page->is_reset) { // not in-use, and not reset yet + // note: do not reset as this includes pages that were not touched before + // mi_pages_reset_add(segment, page, tld); + } + } + mi_assert_internal(segment->abandoned == 0); + if (segment->used == 0) { + mi_assert_internal(right_page_reclaimed == NULL || !(*right_page_reclaimed)); + mi_segment_free(segment, false, tld); + return NULL; + } + else { + if (segment->page_kind <= MI_PAGE_MEDIUM && mi_segment_has_free(segment)) { + mi_segment_insert_in_free_queue(segment, tld); + } + return segment; + } +} + + +void _mi_abandoned_reclaim_all(mi_heap_t* heap, mi_segments_tld_t* tld) { + mi_segment_t* segment; + while ((segment = mi_abandoned_pop()) != NULL) { + mi_segment_reclaim(segment, heap, 0, NULL, tld); + } +} + +static mi_segment_t* mi_segment_try_reclaim(mi_heap_t* heap, size_t block_size, mi_page_kind_t page_kind, bool* reclaimed, mi_segments_tld_t* tld) +{ + *reclaimed = false; + mi_segment_t* segment; + int max_tries = 8; // limit the work to bound allocation times + while ((max_tries-- > 0) && ((segment = mi_abandoned_pop()) != NULL)) { + segment->abandoned_visits++; + bool all_pages_free; + bool has_page = mi_segment_check_free(segment,block_size,&all_pages_free); // try to free up pages (due to concurrent frees) + if (all_pages_free) { + // free the segment (by forced reclaim) to make it available to other threads. + // note1: we prefer to free a segment as that might lead to reclaiming another + // segment that is still partially used. + // note2: we could in principle optimize this by skipping reclaim and directly + // freeing but that would violate some invariants temporarily) + mi_segment_reclaim(segment, heap, 0, NULL, tld); + } + else if (has_page && segment->page_kind == page_kind) { + // found a free page of the right kind, or page of the right block_size with free space + // we return the result of reclaim (which is usually `segment`) as it might free + // the segment due to concurrent frees (in which case `NULL` is returned). + return mi_segment_reclaim(segment, heap, block_size, reclaimed, tld); + } + else if (segment->abandoned_visits >= 3) { + // always reclaim on 3rd visit to limit the list length. + mi_segment_reclaim(segment, heap, 0, NULL, tld); + } + else { + // otherwise, push on the visited list so it gets not looked at too quickly again + mi_abandoned_visited_push(segment); + } + } + return NULL; +} + + +/* ----------------------------------------------------------- + Reclaim or allocate +----------------------------------------------------------- */ + +static mi_segment_t* mi_segment_reclaim_or_alloc(mi_heap_t* heap, size_t block_size, mi_page_kind_t page_kind, size_t page_shift, mi_segments_tld_t* tld, mi_os_tld_t* os_tld) +{ + mi_assert_internal(page_kind <= MI_PAGE_LARGE); + mi_assert_internal(block_size < MI_HUGE_BLOCK_SIZE); + // 1. try to get a segment from our cache + mi_segment_t* segment = mi_segment_cache_pop(MI_SEGMENT_SIZE, tld); + if (segment != NULL) { + mi_segment_init(segment, 0, page_kind, page_shift, tld, os_tld); + return segment; + } + // 2. try to reclaim an abandoned segment + bool reclaimed; + segment = mi_segment_try_reclaim(heap, block_size, page_kind, &reclaimed, tld); + if (reclaimed) { + // reclaimed the right page right into the heap + mi_assert_internal(segment != NULL && segment->page_kind == page_kind && page_kind <= MI_PAGE_LARGE); + return NULL; // pretend out-of-memory as the page will be in the page queue of the heap with available blocks + } + else if (segment != NULL) { + // reclaimed a segment with empty pages (of `page_kind`) in it + return segment; + } + // 3. otherwise allocate a fresh segment + return mi_segment_alloc(0, page_kind, page_shift, tld, os_tld); +} + + +/* ----------------------------------------------------------- + Small page allocation +----------------------------------------------------------- */ + +static mi_page_t* mi_segment_find_free(mi_segment_t* segment, mi_segments_tld_t* tld) { + mi_assert_internal(mi_segment_has_free(segment)); + mi_assert_expensive(mi_segment_is_valid(segment, tld)); + for (size_t i = 0; i < segment->capacity; i++) { // TODO: use a bitmap instead of search? + mi_page_t* page = &segment->pages[i]; + if (!page->segment_in_use) { + bool ok = mi_segment_page_claim(segment, page, tld); + if (ok) return page; + } + } + mi_assert(false); + return NULL; +} + +// Allocate a page inside a segment. Requires that the page has free pages +static mi_page_t* mi_segment_page_alloc_in(mi_segment_t* segment, mi_segments_tld_t* tld) { + mi_assert_internal(mi_segment_has_free(segment)); + return mi_segment_find_free(segment, tld); +} + +static mi_page_t* mi_segment_page_alloc(mi_heap_t* heap, size_t block_size, mi_page_kind_t kind, size_t page_shift, mi_segments_tld_t* tld, mi_os_tld_t* os_tld) { + // find an available segment the segment free queue + mi_segment_queue_t* const free_queue = mi_segment_free_queue_of_kind(kind, tld); + if (mi_segment_queue_is_empty(free_queue)) { + // possibly allocate or reclaim a fresh segment + mi_segment_t* const segment = mi_segment_reclaim_or_alloc(heap, block_size, kind, page_shift, tld, os_tld); + if (segment == NULL) return NULL; // return NULL if out-of-memory (or reclaimed) + mi_assert_internal(free_queue->first == segment); + mi_assert_internal(segment->page_kind==kind); + mi_assert_internal(segment->used < segment->capacity); + } + mi_assert_internal(free_queue->first != NULL); + mi_page_t* const page = mi_segment_page_alloc_in(free_queue->first, tld); + mi_assert_internal(page != NULL); +#if MI_DEBUG>=2 + // verify it is committed + _mi_segment_page_start(_mi_page_segment(page), page, sizeof(void*), NULL, NULL)[0] = 0; +#endif + return page; +} + +static mi_page_t* mi_segment_small_page_alloc(mi_heap_t* heap, size_t block_size, mi_segments_tld_t* tld, mi_os_tld_t* os_tld) { + return mi_segment_page_alloc(heap, block_size, MI_PAGE_SMALL,MI_SMALL_PAGE_SHIFT,tld,os_tld); +} + +static mi_page_t* mi_segment_medium_page_alloc(mi_heap_t* heap, size_t block_size, mi_segments_tld_t* tld, mi_os_tld_t* os_tld) { + return mi_segment_page_alloc(heap, block_size, MI_PAGE_MEDIUM, MI_MEDIUM_PAGE_SHIFT, tld, os_tld); +} + +/* ----------------------------------------------------------- + large page allocation +----------------------------------------------------------- */ + +static mi_page_t* mi_segment_large_page_alloc(mi_heap_t* heap, size_t block_size, mi_segments_tld_t* tld, mi_os_tld_t* os_tld) { + mi_segment_t* segment = mi_segment_reclaim_or_alloc(heap,block_size,MI_PAGE_LARGE,MI_LARGE_PAGE_SHIFT,tld,os_tld); + if (segment == NULL) return NULL; + mi_page_t* page = mi_segment_find_free(segment, tld); + mi_assert_internal(page != NULL); +#if MI_DEBUG>=2 + _mi_segment_page_start(segment, page, sizeof(void*), NULL, NULL)[0] = 0; +#endif + return page; +} + +static mi_page_t* mi_segment_huge_page_alloc(size_t size, mi_segments_tld_t* tld, mi_os_tld_t* os_tld) +{ + mi_segment_t* segment = mi_segment_alloc(size, MI_PAGE_HUGE, MI_SEGMENT_SHIFT,tld,os_tld); + if (segment == NULL) return NULL; + mi_assert_internal(mi_segment_page_size(segment) - segment->segment_info_size - (2*(MI_SECURE == 0 ? 0 : _mi_os_page_size())) >= size); + segment->thread_id = 0; // huge pages are immediately abandoned + mi_segments_track_size(-(long)segment->segment_size, tld); + mi_page_t* page = mi_segment_find_free(segment, tld); + mi_assert_internal(page != NULL); + return page; +} + +// free huge block from another thread +void _mi_segment_huge_page_free(mi_segment_t* segment, mi_page_t* page, mi_block_t* block) { + // huge page segments are always abandoned and can be freed immediately by any thread + mi_assert_internal(segment->page_kind==MI_PAGE_HUGE); + mi_assert_internal(segment == _mi_page_segment(page)); + mi_assert_internal(mi_atomic_load_relaxed(&segment->thread_id)==0); + + // claim it and free + mi_heap_t* heap = mi_heap_get_default(); // issue #221; don't use the internal get_default_heap as we need to ensure the thread is initialized. + // paranoia: if this it the last reference, the cas should always succeed + uintptr_t expected_tid = 0; + if (mi_atomic_cas_strong_acq_rel(&segment->thread_id, &expected_tid, heap->thread_id)) { + mi_block_set_next(page, block, page->free); + page->free = block; + page->used--; + page->is_zero = false; + mi_assert(page->used == 0); + mi_tld_t* tld = heap->tld; + const size_t bsize = mi_page_usable_block_size(page); + if (bsize > MI_HUGE_OBJ_SIZE_MAX) { + _mi_stat_decrease(&tld->stats.giant, bsize); + } + else { + _mi_stat_decrease(&tld->stats.huge, bsize); + } + mi_segments_track_size((long)segment->segment_size, &tld->segments); + _mi_segment_page_free(page, true, &tld->segments); + } +#if (MI_DEBUG!=0) + else { + mi_assert_internal(false); + } +#endif +} + +/* ----------------------------------------------------------- + Page allocation +----------------------------------------------------------- */ + +mi_page_t* _mi_segment_page_alloc(mi_heap_t* heap, size_t block_size, mi_segments_tld_t* tld, mi_os_tld_t* os_tld) { + mi_page_t* page; + if (block_size <= MI_SMALL_OBJ_SIZE_MAX) { + page = mi_segment_small_page_alloc(heap, block_size, tld, os_tld); + } + else if (block_size <= MI_MEDIUM_OBJ_SIZE_MAX) { + page = mi_segment_medium_page_alloc(heap, block_size, tld, os_tld); + } + else if (block_size <= MI_LARGE_OBJ_SIZE_MAX) { + page = mi_segment_large_page_alloc(heap, block_size, tld, os_tld); + } + else { + page = mi_segment_huge_page_alloc(block_size,tld,os_tld); + } + mi_assert_expensive(page == NULL || mi_segment_is_valid(_mi_page_segment(page),tld)); + mi_assert_internal(page == NULL || (mi_segment_page_size(_mi_page_segment(page)) - (MI_SECURE == 0 ? 0 : _mi_os_page_size())) >= block_size); + mi_reset_delayed(tld); + mi_assert_internal(page == NULL || mi_page_not_in_queue(page, tld)); + return page; +} diff --git a/kotlin-native/runtime/src/mimalloc/c/static.c b/kotlin-native/runtime/src/mimalloc/c/static.c new file mode 100644 index 00000000000..39b417ad5ea --- /dev/null +++ b/kotlin-native/runtime/src/mimalloc/c/static.c @@ -0,0 +1,38 @@ +/* ---------------------------------------------------------------------------- +Copyright (c) 2018, Microsoft Research, Daan Leijen +This is free software; you can redistribute it and/or modify it under the +terms of the MIT license. A copy of the license can be found in the file +"licenses/third_party/mimalloc_LICENSE.txt" at the root of this distribution. +-----------------------------------------------------------------------------*/ +#ifndef _DEFAULT_SOURCE +#define _DEFAULT_SOURCE +#endif +#if defined(__sun) +// same remarks as os.c for the static's context. +#undef _XOPEN_SOURCE +#undef _POSIX_C_SOURCE +#endif + +#include "mimalloc.h" +#include "mimalloc-internal.h" + +// For a static override we create a single object file +// containing the whole library. If it is linked first +// it will override all the standard library allocation +// functions (on Unix's). +#include "stats.c" +#include "random.c" +#include "os.c" +#include "arena.c" +#include "region.c" +#include "segment.c" +#include "page.c" +#include "heap.c" +#include "alloc.c" +#include "alloc-aligned.c" +#include "alloc-posix.c" +#if MI_OSX_ZONE +#include "alloc-override-osx.c" +#endif +#include "init.c" +#include "options.c" diff --git a/kotlin-native/runtime/src/mimalloc/c/stats.c b/kotlin-native/runtime/src/mimalloc/c/stats.c new file mode 100644 index 00000000000..9280917b3e4 --- /dev/null +++ b/kotlin-native/runtime/src/mimalloc/c/stats.c @@ -0,0 +1,570 @@ +/* ---------------------------------------------------------------------------- +Copyright (c) 2018, Microsoft Research, Daan Leijen +This is free software; you can redistribute it and/or modify it under the +terms of the MIT license. A copy of the license can be found in the file +"licenses/third_party/mimalloc_LICENSE.txt" at the root of this distribution. +-----------------------------------------------------------------------------*/ +#include "mimalloc.h" +#include "mimalloc-internal.h" +#include "mimalloc-atomic.h" + +#include // fputs, stderr +#include // memset + +#if defined(_MSC_VER) && (_MSC_VER < 1920) +#pragma warning(disable:4204) // non-constant aggregate initializer +#endif + +/* ----------------------------------------------------------- + Statistics operations +----------------------------------------------------------- */ + +static bool mi_is_in_main(void* stat) { + return ((uint8_t*)stat >= (uint8_t*)&_mi_stats_main + && (uint8_t*)stat < ((uint8_t*)&_mi_stats_main + sizeof(mi_stats_t))); +} + +static void mi_stat_update(mi_stat_count_t* stat, int64_t amount) { + if (amount == 0) return; + if (mi_is_in_main(stat)) + { + // add atomically (for abandoned pages) + int64_t current = mi_atomic_addi64_relaxed(&stat->current, amount); + mi_atomic_maxi64_relaxed(&stat->peak, current + amount); + if (amount > 0) { + mi_atomic_addi64_relaxed(&stat->allocated,amount); + } + else { + mi_atomic_addi64_relaxed(&stat->freed, -amount); + } + } + else { + // add thread local + stat->current += amount; + if (stat->current > stat->peak) stat->peak = stat->current; + if (amount > 0) { + stat->allocated += amount; + } + else { + stat->freed += -amount; + } + } +} + +void _mi_stat_counter_increase(mi_stat_counter_t* stat, size_t amount) { + if (mi_is_in_main(stat)) { + mi_atomic_addi64_relaxed( &stat->count, 1 ); + mi_atomic_addi64_relaxed( &stat->total, (int64_t)amount ); + } + else { + stat->count++; + stat->total += amount; + } +} + +void _mi_stat_increase(mi_stat_count_t* stat, size_t amount) { + mi_stat_update(stat, (int64_t)amount); +} + +void _mi_stat_decrease(mi_stat_count_t* stat, size_t amount) { + mi_stat_update(stat, -((int64_t)amount)); +} + +// must be thread safe as it is called from stats_merge +static void mi_stat_add(mi_stat_count_t* stat, const mi_stat_count_t* src, int64_t unit) { + if (stat==src) return; + if (src->allocated==0 && src->freed==0) return; + mi_atomic_addi64_relaxed( &stat->allocated, src->allocated * unit); + mi_atomic_addi64_relaxed( &stat->current, src->current * unit); + mi_atomic_addi64_relaxed( &stat->freed, src->freed * unit); + // peak scores do not work across threads.. + mi_atomic_addi64_relaxed( &stat->peak, src->peak * unit); +} + +static void mi_stat_counter_add(mi_stat_counter_t* stat, const mi_stat_counter_t* src, int64_t unit) { + if (stat==src) return; + mi_atomic_addi64_relaxed( &stat->total, src->total * unit); + mi_atomic_addi64_relaxed( &stat->count, src->count * unit); +} + +// must be thread safe as it is called from stats_merge +static void mi_stats_add(mi_stats_t* stats, const mi_stats_t* src) { + if (stats==src) return; + mi_stat_add(&stats->segments, &src->segments,1); + mi_stat_add(&stats->pages, &src->pages,1); + mi_stat_add(&stats->reserved, &src->reserved, 1); + mi_stat_add(&stats->committed, &src->committed, 1); + mi_stat_add(&stats->reset, &src->reset, 1); + mi_stat_add(&stats->page_committed, &src->page_committed, 1); + + mi_stat_add(&stats->pages_abandoned, &src->pages_abandoned, 1); + mi_stat_add(&stats->segments_abandoned, &src->segments_abandoned, 1); + mi_stat_add(&stats->threads, &src->threads, 1); + + mi_stat_add(&stats->malloc, &src->malloc, 1); + mi_stat_add(&stats->segments_cache, &src->segments_cache, 1); + mi_stat_add(&stats->huge, &src->huge, 1); + mi_stat_add(&stats->giant, &src->giant, 1); + + mi_stat_counter_add(&stats->pages_extended, &src->pages_extended, 1); + mi_stat_counter_add(&stats->mmap_calls, &src->mmap_calls, 1); + mi_stat_counter_add(&stats->commit_calls, &src->commit_calls, 1); + + mi_stat_counter_add(&stats->page_no_retire, &src->page_no_retire, 1); + mi_stat_counter_add(&stats->searches, &src->searches, 1); + mi_stat_counter_add(&stats->huge_count, &src->huge_count, 1); + mi_stat_counter_add(&stats->giant_count, &src->giant_count, 1); +#if MI_STAT>1 + for (size_t i = 0; i <= MI_BIN_HUGE; i++) { + if (src->normal[i].allocated > 0 || src->normal[i].freed > 0) { + mi_stat_add(&stats->normal[i], &src->normal[i], 1); + } + } +#endif +} + +/* ----------------------------------------------------------- + Display statistics +----------------------------------------------------------- */ + +// unit > 0 : size in binary bytes +// unit == 0: count as decimal +// unit < 0 : count in binary +static void mi_printf_amount(int64_t n, int64_t unit, mi_output_fun* out, void* arg, const char* fmt) { + char buf[32]; + int len = 32; + const char* suffix = (unit <= 0 ? " " : "b"); + const int64_t base = (unit == 0 ? 1000 : 1024); + if (unit>0) n *= unit; + + const int64_t pos = (n < 0 ? -n : n); + if (pos < base) { + snprintf(buf, len, "%d %s ", (int)n, suffix); + } + else { + int64_t divider = base; + const char* magnitude = "k"; + if (pos >= divider*base) { divider *= base; magnitude = "m"; } + if (pos >= divider*base) { divider *= base; magnitude = "g"; } + const int64_t tens = (n / (divider/10)); + const long whole = (long)(tens/10); + const long frac1 = (long)(tens%10); + snprintf(buf, len, "%ld.%ld %s%s", whole, frac1, magnitude, suffix); + } + _mi_fprintf(out, arg, (fmt==NULL ? "%11s" : fmt), buf); +} + + +static void mi_print_amount(int64_t n, int64_t unit, mi_output_fun* out, void* arg) { + mi_printf_amount(n,unit,out,arg,NULL); +} + +static void mi_print_count(int64_t n, int64_t unit, mi_output_fun* out, void* arg) { + if (unit==1) _mi_fprintf(out, arg, "%11s"," "); + else mi_print_amount(n,0,out,arg); +} + +static void mi_stat_print(const mi_stat_count_t* stat, const char* msg, int64_t unit, mi_output_fun* out, void* arg ) { + _mi_fprintf(out, arg,"%10s:", msg); + if (unit>0) { + mi_print_amount(stat->peak, unit, out, arg); + mi_print_amount(stat->allocated, unit, out, arg); + mi_print_amount(stat->freed, unit, out, arg); + mi_print_amount(unit, 1, out, arg); + mi_print_count(stat->allocated, unit, out, arg); + if (stat->allocated > stat->freed) + _mi_fprintf(out, arg, " not all freed!\n"); + else + _mi_fprintf(out, arg, " ok\n"); + } + else if (unit<0) { + mi_print_amount(stat->peak, -1, out, arg); + mi_print_amount(stat->allocated, -1, out, arg); + mi_print_amount(stat->freed, -1, out, arg); + if (unit==-1) { + _mi_fprintf(out, arg, "%22s", ""); + } + else { + mi_print_amount(-unit, 1, out, arg); + mi_print_count((stat->allocated / -unit), 0, out, arg); + } + if (stat->allocated > stat->freed) + _mi_fprintf(out, arg, " not all freed!\n"); + else + _mi_fprintf(out, arg, " ok\n"); + } + else { + mi_print_amount(stat->peak, 1, out, arg); + mi_print_amount(stat->allocated, 1, out, arg); + _mi_fprintf(out, arg, "\n"); + } +} + +static void mi_stat_counter_print(const mi_stat_counter_t* stat, const char* msg, mi_output_fun* out, void* arg ) { + _mi_fprintf(out, arg, "%10s:", msg); + mi_print_amount(stat->total, -1, out, arg); + _mi_fprintf(out, arg, "\n"); +} + +static void mi_stat_counter_print_avg(const mi_stat_counter_t* stat, const char* msg, mi_output_fun* out, void* arg) { + const int64_t avg_tens = (stat->count == 0 ? 0 : (stat->total*10 / stat->count)); + const long avg_whole = (long)(avg_tens/10); + const long avg_frac1 = (long)(avg_tens%10); + _mi_fprintf(out, arg, "%10s: %5ld.%ld avg\n", msg, avg_whole, avg_frac1); +} + + +static void mi_print_header(mi_output_fun* out, void* arg ) { + _mi_fprintf(out, arg, "%10s: %10s %10s %10s %10s %10s\n", "heap stats", "peak ", "total ", "freed ", "unit ", "count "); +} + +#if MI_STAT>1 +static void mi_stats_print_bins(mi_stat_count_t* all, const mi_stat_count_t* bins, size_t max, const char* fmt, mi_output_fun* out, void* arg) { + bool found = false; + char buf[64]; + for (size_t i = 0; i <= max; i++) { + if (bins[i].allocated > 0) { + found = true; + int64_t unit = _mi_bin_size((uint8_t)i); + snprintf(buf, 64, "%s %3lu", fmt, (long)i); + mi_stat_add(all, &bins[i], unit); + mi_stat_print(&bins[i], buf, unit, out, arg); + } + } + //snprintf(buf, 64, "%s all", fmt); + //mi_stat_print(all, buf, 1); + if (found) { + _mi_fprintf(out, arg, "\n"); + mi_print_header(out, arg); + } +} +#endif + + + +//------------------------------------------------------------ +// Use an output wrapper for line-buffered output +// (which is nice when using loggers etc.) +//------------------------------------------------------------ +typedef struct buffered_s { + mi_output_fun* out; // original output function + void* arg; // and state + char* buf; // local buffer of at least size `count+1` + size_t used; // currently used chars `used <= count` + size_t count; // total chars available for output +} buffered_t; + +static void mi_buffered_flush(buffered_t* buf) { + buf->buf[buf->used] = 0; + _mi_fputs(buf->out, buf->arg, NULL, buf->buf); + buf->used = 0; +} + +static void mi_buffered_out(const char* msg, void* arg) { + buffered_t* buf = (buffered_t*)arg; + if (msg==NULL || buf==NULL) return; + for (const char* src = msg; *src != 0; src++) { + char c = *src; + if (buf->used >= buf->count) mi_buffered_flush(buf); + mi_assert_internal(buf->used < buf->count); + buf->buf[buf->used++] = c; + if (c == '\n') mi_buffered_flush(buf); + } +} + +//------------------------------------------------------------ +// Print statistics +//------------------------------------------------------------ + +static void mi_stat_process_info(mi_msecs_t* elapsed, mi_msecs_t* utime, mi_msecs_t* stime, size_t* current_rss, size_t* peak_rss, size_t* current_commit, size_t* peak_commit, size_t* page_faults); + +static void _mi_stats_print(mi_stats_t* stats, mi_output_fun* out0, void* arg0) mi_attr_noexcept { + // wrap the output function to be line buffered + char buf[256]; + buffered_t buffer = { out0, arg0, NULL, 0, 255 }; + buffer.buf = buf; + mi_output_fun* out = &mi_buffered_out; + void* arg = &buffer; + + // and print using that + mi_print_header(out,arg); + #if MI_STAT>1 + mi_stat_count_t normal = { 0,0,0,0 }; + mi_stats_print_bins(&normal, stats->normal, MI_BIN_HUGE, "normal",out,arg); + mi_stat_print(&normal, "normal", 1, out, arg); + mi_stat_print(&stats->huge, "huge", (stats->huge_count.count == 0 ? 1 : -(stats->huge.allocated / stats->huge_count.count)), out, arg); + mi_stat_print(&stats->giant, "giant", (stats->giant_count.count == 0 ? 1 : -(stats->giant.allocated / stats->giant_count.count)), out, arg); + mi_stat_count_t total = { 0,0,0,0 }; + mi_stat_add(&total, &normal, 1); + mi_stat_add(&total, &stats->huge, 1); + mi_stat_add(&total, &stats->giant, 1); + mi_stat_print(&total, "total", 1, out, arg); + _mi_fprintf(out, arg, "malloc requested: "); + mi_print_amount(stats->malloc.allocated, 1, out, arg); + _mi_fprintf(out, arg, "\n\n"); + #endif + mi_stat_print(&stats->reserved, "reserved", 1, out, arg); + mi_stat_print(&stats->committed, "committed", 1, out, arg); + mi_stat_print(&stats->reset, "reset", 1, out, arg); + mi_stat_print(&stats->page_committed, "touched", 1, out, arg); + mi_stat_print(&stats->segments, "segments", -1, out, arg); + mi_stat_print(&stats->segments_abandoned, "-abandoned", -1, out, arg); + mi_stat_print(&stats->segments_cache, "-cached", -1, out, arg); + mi_stat_print(&stats->pages, "pages", -1, out, arg); + mi_stat_print(&stats->pages_abandoned, "-abandoned", -1, out, arg); + mi_stat_counter_print(&stats->pages_extended, "-extended", out, arg); + mi_stat_counter_print(&stats->page_no_retire, "-noretire", out, arg); + mi_stat_counter_print(&stats->mmap_calls, "mmaps", out, arg); + mi_stat_counter_print(&stats->commit_calls, "commits", out, arg); + mi_stat_print(&stats->threads, "threads", -1, out, arg); + mi_stat_counter_print_avg(&stats->searches, "searches", out, arg); + _mi_fprintf(out, arg, "%10s: %7i\n", "numa nodes", _mi_os_numa_node_count()); + + mi_msecs_t elapsed; + mi_msecs_t user_time; + mi_msecs_t sys_time; + size_t current_rss; + size_t peak_rss; + size_t current_commit; + size_t peak_commit; + size_t page_faults; + mi_stat_process_info(&elapsed, &user_time, &sys_time, ¤t_rss, &peak_rss, ¤t_commit, &peak_commit, &page_faults); + _mi_fprintf(out, arg, "%10s: %7ld.%03ld s\n", "elapsed", elapsed/1000, elapsed%1000); + _mi_fprintf(out, arg, "%10s: user: %ld.%03ld s, system: %ld.%03ld s, faults: %lu, rss: ", "process", + user_time/1000, user_time%1000, sys_time/1000, sys_time%1000, (unsigned long)page_faults ); + mi_printf_amount((int64_t)peak_rss, 1, out, arg, "%s"); + if (peak_commit > 0) { + _mi_fprintf(out, arg, ", commit: "); + mi_printf_amount((int64_t)peak_commit, 1, out, arg, "%s"); + } + _mi_fprintf(out, arg, "\n"); +} + +static mi_msecs_t mi_process_start; // = 0 + +static mi_stats_t* mi_stats_get_default(void) { + mi_heap_t* heap = mi_heap_get_default(); + return &heap->tld->stats; +} + +static void mi_stats_merge_from(mi_stats_t* stats) { + if (stats != &_mi_stats_main) { + mi_stats_add(&_mi_stats_main, stats); + memset(stats, 0, sizeof(mi_stats_t)); + } +} + +void mi_stats_reset(void) mi_attr_noexcept { + mi_stats_t* stats = mi_stats_get_default(); + if (stats != &_mi_stats_main) { memset(stats, 0, sizeof(mi_stats_t)); } + memset(&_mi_stats_main, 0, sizeof(mi_stats_t)); + if (mi_process_start == 0) { mi_process_start = _mi_clock_start(); }; +} + +void mi_stats_merge(void) mi_attr_noexcept { + mi_stats_merge_from( mi_stats_get_default() ); +} + +void _mi_stats_done(mi_stats_t* stats) { // called from `mi_thread_done` + mi_stats_merge_from(stats); +} + +void mi_stats_print_out(mi_output_fun* out, void* arg) mi_attr_noexcept { + mi_stats_merge_from(mi_stats_get_default()); + _mi_stats_print(&_mi_stats_main, out, arg); +} + +void mi_stats_print(void* out) mi_attr_noexcept { + // for compatibility there is an `out` parameter (which can be `stdout` or `stderr`) + mi_stats_print_out((mi_output_fun*)out, NULL); +} + +void mi_thread_stats_print_out(mi_output_fun* out, void* arg) mi_attr_noexcept { + _mi_stats_print(mi_stats_get_default(), out, arg); +} + + +// ---------------------------------------------------------------- +// Basic timer for convenience; use milli-seconds to avoid doubles +// ---------------------------------------------------------------- +#ifdef _WIN32 +#include +static mi_msecs_t mi_to_msecs(LARGE_INTEGER t) { + static LARGE_INTEGER mfreq; // = 0 + if (mfreq.QuadPart == 0LL) { + LARGE_INTEGER f; + QueryPerformanceFrequency(&f); + mfreq.QuadPart = f.QuadPart/1000LL; + if (mfreq.QuadPart == 0) mfreq.QuadPart = 1; + } + return (mi_msecs_t)(t.QuadPart / mfreq.QuadPart); +} + +mi_msecs_t _mi_clock_now(void) { + LARGE_INTEGER t; + QueryPerformanceCounter(&t); + return mi_to_msecs(t); +} +#else +#include +#ifdef CLOCK_REALTIME +mi_msecs_t _mi_clock_now(void) { + struct timespec t; + clock_gettime(CLOCK_REALTIME, &t); + return ((mi_msecs_t)t.tv_sec * 1000) + ((mi_msecs_t)t.tv_nsec / 1000000); +} +#else +// low resolution timer +mi_msecs_t _mi_clock_now(void) { + return ((mi_msecs_t)clock() / ((mi_msecs_t)CLOCKS_PER_SEC / 1000)); +} +#endif +#endif + + +static mi_msecs_t mi_clock_diff; + +mi_msecs_t _mi_clock_start(void) { + if (mi_clock_diff == 0.0) { + mi_msecs_t t0 = _mi_clock_now(); + mi_clock_diff = _mi_clock_now() - t0; + } + return _mi_clock_now(); +} + +mi_msecs_t _mi_clock_end(mi_msecs_t start) { + mi_msecs_t end = _mi_clock_now(); + return (end - start - mi_clock_diff); +} + + +// -------------------------------------------------------- +// Basic process statistics +// -------------------------------------------------------- + +#if defined(_WIN32) +#include +#include +#pragma comment(lib,"psapi.lib") + +static mi_msecs_t filetime_msecs(const FILETIME* ftime) { + ULARGE_INTEGER i; + i.LowPart = ftime->dwLowDateTime; + i.HighPart = ftime->dwHighDateTime; + mi_msecs_t msecs = (i.QuadPart / 10000); // FILETIME is in 100 nano seconds + return msecs; +} + +static void mi_stat_process_info(mi_msecs_t* elapsed, mi_msecs_t* utime, mi_msecs_t* stime, size_t* current_rss, size_t* peak_rss, size_t* current_commit, size_t* peak_commit, size_t* page_faults) +{ + *elapsed = _mi_clock_end(mi_process_start); + FILETIME ct; + FILETIME ut; + FILETIME st; + FILETIME et; + GetProcessTimes(GetCurrentProcess(), &ct, &et, &st, &ut); + *utime = filetime_msecs(&ut); + *stime = filetime_msecs(&st); + PROCESS_MEMORY_COUNTERS info; + GetProcessMemoryInfo(GetCurrentProcess(), &info, sizeof(info)); + *current_rss = (size_t)info.WorkingSetSize; + *peak_rss = (size_t)info.PeakWorkingSetSize; + *current_commit = (size_t)info.PagefileUsage; + *peak_commit = (size_t)info.PeakPagefileUsage; + *page_faults = (size_t)info.PageFaultCount; +} + +#elif defined(__unix__) || defined(__unix) || defined(unix) || (defined(__APPLE__) && defined(__MACH__)) || defined(__HAIKU__) +#include +#include +#include + +#if defined(__APPLE__) && defined(__MACH__) +#include +#endif + +#if defined(__HAIKU__) +#include +#endif + +static mi_msecs_t timeval_secs(const struct timeval* tv) { + return ((mi_msecs_t)tv->tv_sec * 1000L) + ((mi_msecs_t)tv->tv_usec / 1000L); +} + +static void mi_stat_process_info(mi_msecs_t* elapsed, mi_msecs_t* utime, mi_msecs_t* stime, size_t* current_rss, size_t* peak_rss, size_t* current_commit, size_t* peak_commit, size_t* page_faults) +{ + *elapsed = _mi_clock_end(mi_process_start); + struct rusage rusage; + getrusage(RUSAGE_SELF, &rusage); + *utime = timeval_secs(&rusage.ru_utime); + *stime = timeval_secs(&rusage.ru_stime); +#if !defined(__HAIKU__) + *page_faults = rusage.ru_majflt; +#endif + // estimate commit using our stats + *peak_commit = (size_t)(mi_atomic_loadi64_relaxed((_Atomic(int64_t)*)&_mi_stats_main.committed.peak)); + *current_commit = (size_t)(mi_atomic_loadi64_relaxed((_Atomic(int64_t)*)&_mi_stats_main.committed.current)); + *current_rss = *current_commit; // estimate +#if defined(__HAIKU__) + // Haiku does not have (yet?) a way to + // get these stats per process + thread_info tid; + area_info mem; + ssize_t c; + get_thread_info(find_thread(0), &tid); + while (get_next_area_info(tid.team, &c, &mem) == B_OK) { + *peak_rss += mem.ram_size; + } +#elif defined(__APPLE__) && defined(__MACH__) + *peak_rss = rusage.ru_maxrss; // BSD reports in bytes + struct mach_task_basic_info info; + mach_msg_type_number_t infoCount = MACH_TASK_BASIC_INFO_COUNT; + if (task_info(mach_task_self(), MACH_TASK_BASIC_INFO, (task_info_t)&info, &infoCount) == KERN_SUCCESS) { + *current_rss = (size_t)info.resident_size; + } +#else + *peak_rss = rusage.ru_maxrss * 1024; // Linux reports in KiB +#endif +} + +#else +#ifndef __wasi__ +// WebAssembly instances are not processes +#pragma message("define a way to get process info") +#endif + +static void mi_stat_process_info(mi_msecs_t* elapsed, mi_msecs_t* utime, mi_msecs_t* stime, size_t* current_rss, size_t* peak_rss, size_t* current_commit, size_t* peak_commit, size_t* page_faults) +{ + *elapsed = _mi_clock_end(mi_process_start); + *peak_commit = (size_t)(mi_atomic_loadi64_relaxed((_Atomic(int64_t)*)&_mi_stats_main.committed.peak)); + *current_commit = (size_t)(mi_atomic_loadi64_relaxed((_Atomic(int64_t)*)&_mi_stats_main.committed.current)); + *peak_rss = *peak_commit; + *current_rss = *current_commit; + *page_faults = 0; + *utime = 0; + *stime = 0; +} +#endif + + +mi_decl_export void mi_process_info(size_t* elapsed_msecs, size_t* user_msecs, size_t* system_msecs, size_t* current_rss, size_t* peak_rss, size_t* current_commit, size_t* peak_commit, size_t* page_faults) mi_attr_noexcept +{ + mi_msecs_t elapsed = 0; + mi_msecs_t utime = 0; + mi_msecs_t stime = 0; + size_t current_rss0 = 0; + size_t peak_rss0 = 0; + size_t current_commit0 = 0; + size_t peak_commit0 = 0; + size_t page_faults0 = 0; + mi_stat_process_info(&elapsed,&utime, &stime, ¤t_rss0, &peak_rss0, ¤t_commit0, &peak_commit0, &page_faults0); + if (elapsed_msecs!=NULL) *elapsed_msecs = (elapsed < 0 ? 0 : (elapsed < (mi_msecs_t)PTRDIFF_MAX ? (size_t)elapsed : PTRDIFF_MAX)); + if (user_msecs!=NULL) *user_msecs = (utime < 0 ? 0 : (utime < (mi_msecs_t)PTRDIFF_MAX ? (size_t)utime : PTRDIFF_MAX)); + if (system_msecs!=NULL) *system_msecs = (stime < 0 ? 0 : (stime < (mi_msecs_t)PTRDIFF_MAX ? (size_t)stime : PTRDIFF_MAX)); + if (current_rss!=NULL) *current_rss = current_rss0; + if (peak_rss!=NULL) *peak_rss = peak_rss0; + if (current_commit!=NULL) *current_commit = current_commit0; + if (peak_commit!=NULL) *peak_commit = peak_commit0; + if (page_faults!=NULL) *page_faults = page_faults0; +} + diff --git a/kotlin-native/runtime/src/mm/cpp/Stubs.cpp b/kotlin-native/runtime/src/mm/cpp/Stubs.cpp new file mode 100644 index 00000000000..9f13af5ede2 --- /dev/null +++ b/kotlin-native/runtime/src/mm/cpp/Stubs.cpp @@ -0,0 +1,237 @@ +/* + * Copyright 2010-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +#include "Memory.h" + +ALWAYS_INLINE bool isFrozen(const ObjHeader* obj) { + RuntimeCheck(false, "Unimplemented"); +} + +ALWAYS_INLINE bool isPermanentOrFrozen(const ObjHeader* obj) { + RuntimeCheck(false, "Unimplemented"); +} + +ALWAYS_INLINE bool isShareable(const ObjHeader* obj) { + RuntimeCheck(false, "Unimplemented"); +} + +ObjHeader** ObjHeader::GetWeakCounterLocation() { + RuntimeCheck(false, "Unimplemented"); +} + +#ifdef KONAN_OBJC_INTEROP + +void* ObjHeader::GetAssociatedObject() { + RuntimeCheck(false, "Unimplemented"); +} + +void** ObjHeader::GetAssociatedObjectLocation() { + RuntimeCheck(false, "Unimplemented"); +} + +void ObjHeader::SetAssociatedObject(void* obj) { + RuntimeCheck(false, "Unimplemented"); +} + +#endif // KONAN_OBJC_INTEROP + +static MetaObjHeader* createMetaObject(TypeInfo** location) { + RuntimeCheck(false, "Unimplemented"); +} + +static void destroyMetaObject(TypeInfo** location) { + RuntimeCheck(false, "Unimplemented"); +} + +extern "C" { + +MemoryState* InitMemory() { + RuntimeCheck(false, "Unimplemented"); +} + +void DeinitMemory(MemoryState*) { + RuntimeCheck(false, "Unimplemented"); +} + +void RestoreMemory(MemoryState* memoryState) { + RuntimeCheck(false, "Unimplemented"); +} + +RUNTIME_NOTHROW OBJ_GETTER(AllocInstance, const TypeInfo* type_info) { + RuntimeCheck(false, "Unimplemented"); +} + +OBJ_GETTER(AllocArrayInstance, const TypeInfo* type_info, int32_t elements) { + RuntimeCheck(false, "Unimplemented"); +} + +OBJ_GETTER(InitInstance, ObjHeader** location, const TypeInfo* typeInfo, void (*ctor)(ObjHeader*)) { + RuntimeCheck(false, "Unimplemented"); +} + +OBJ_GETTER(InitSharedInstance, ObjHeader** location, const TypeInfo* typeInfo, void (*ctor)(ObjHeader*)) { + RuntimeCheck(false, "Unimplemented"); +} + +extern const bool IsStrictMemoryModel = true; + +RUNTIME_NOTHROW void SetStackRef(ObjHeader** location, const ObjHeader* object) { + RuntimeCheck(false, "Unimplemented"); +} + +RUNTIME_NOTHROW void SetHeapRef(ObjHeader** location, const ObjHeader* object) { + RuntimeCheck(false, "Unimplemented"); +} + +RUNTIME_NOTHROW void ZeroHeapRef(ObjHeader** location) { + RuntimeCheck(false, "Unimplemented"); +} + +RUNTIME_NOTHROW void ZeroArrayRefs(ArrayHeader* array) { + RuntimeCheck(false, "Unimplemented"); +} + +RUNTIME_NOTHROW void ZeroStackRef(ObjHeader** location) { + RuntimeCheck(false, "Unimplemented"); +} + +RUNTIME_NOTHROW void UpdateStackRef(ObjHeader** location, const ObjHeader* object) { + RuntimeCheck(false, "Unimplemented"); +} + +RUNTIME_NOTHROW void UpdateHeapRef(ObjHeader** location, const ObjHeader* object) { + RuntimeCheck(false, "Unimplemented"); +} + +RUNTIME_NOTHROW void UpdateHeapRefIfNull(ObjHeader** location, const ObjHeader* object) { + RuntimeCheck(false, "Unimplemented"); +} + +RUNTIME_NOTHROW void UpdateReturnRef(ObjHeader** returnSlot, const ObjHeader* object) { + RuntimeCheck(false, "Unimplemented"); +} + +RUNTIME_NOTHROW OBJ_GETTER( + SwapHeapRefLocked, ObjHeader** location, ObjHeader* expectedValue, ObjHeader* newValue, int32_t* spinlock, int32_t* cookie) { + RuntimeCheck(false, "Unimplemented"); +} + +RUNTIME_NOTHROW void SetHeapRefLocked(ObjHeader** location, ObjHeader* newValue, int32_t* spinlock, int32_t* cookie) { + RuntimeCheck(false, "Unimplemented"); +} + +RUNTIME_NOTHROW OBJ_GETTER(ReadHeapRefLocked, ObjHeader** location, int32_t* spinlock, int32_t* cookie) { + RuntimeCheck(false, "Unimplemented"); +} + +RUNTIME_NOTHROW void EnterFrame(ObjHeader** start, int parameters, int count) { + RuntimeCheck(false, "Unimplemented"); +} + +RUNTIME_NOTHROW void LeaveFrame(ObjHeader** start, int parameters, int count) { + RuntimeCheck(false, "Unimplemented"); +} + +RUNTIME_NOTHROW bool ClearSubgraphReferences(ObjHeader* root, bool checked) { + RuntimeCheck(false, "Unimplemented"); +} + +RUNTIME_NOTHROW void* CreateStablePointer(ObjHeader* obj) { + RuntimeCheck(false, "Unimplemented"); +} + +RUNTIME_NOTHROW void DisposeStablePointer(void* pointer) { + RuntimeCheck(false, "Unimplemented"); +} + +RUNTIME_NOTHROW OBJ_GETTER(DerefStablePointer, void*) { + RuntimeCheck(false, "Unimplemented"); +} + +RUNTIME_NOTHROW OBJ_GETTER(AdoptStablePointer, void*) { + RuntimeCheck(false, "Unimplemented"); +} + +void MutationCheck(ObjHeader* obj) { + RuntimeCheck(false, "Unimplemented"); +} + +RUNTIME_NOTHROW void CheckLifetimesConstraint(ObjHeader* obj, ObjHeader* pointee) { + RuntimeCheck(false, "Unimplemented"); +} + +void FreezeSubgraph(ObjHeader* obj) { + RuntimeCheck(false, "Unimplemented"); +} + +void EnsureNeverFrozen(ObjHeader* obj) { + RuntimeCheck(false, "Unimplemented"); +} + +RUNTIME_NOTHROW void AddTLSRecord(MemoryState* memory, void** key, int size) { + RuntimeCheck(false, "Unimplemented"); +} + +RUNTIME_NOTHROW void ClearTLSRecord(MemoryState* memory, void** key) { + RuntimeCheck(false, "Unimplemented"); +} + +RUNTIME_NOTHROW ObjHeader** LookupTLS(void** key, int index) { + RuntimeCheck(false, "Unimplemented"); +} + +RUNTIME_NOTHROW void GC_RegisterWorker(void* worker) { + RuntimeCheck(false, "Unimplemented"); +} + +RUNTIME_NOTHROW void GC_UnregisterWorker(void* worker) { + RuntimeCheck(false, "Unimplemented"); +} + +RUNTIME_NOTHROW void GC_CollectorCallback(void* worker) { + RuntimeCheck(false, "Unimplemented"); +} + +bool Kotlin_Any_isShareable(ObjHeader* thiz) { + RuntimeCheck(false, "Unimplemented"); +} + +RUNTIME_NOTHROW void PerformFullGC() { + RuntimeCheck(false, "Unimplemented"); +} + +bool TryAddHeapRef(const ObjHeader* object) { + RuntimeCheck(false, "Unimplemented"); +} + +RUNTIME_NOTHROW void ReleaseHeapRef(const ObjHeader* object) { + RuntimeCheck(false, "Unimplemented"); +} + +RUNTIME_NOTHROW void ReleaseHeapRefNoCollect(const ObjHeader* object) { + RuntimeCheck(false, "Unimplemented"); +} + +ForeignRefContext InitLocalForeignRef(ObjHeader* object) { + RuntimeCheck(false, "Unimplemented"); +} + +ForeignRefContext InitForeignRef(ObjHeader* object) { + RuntimeCheck(false, "Unimplemented"); +} + +void DeinitForeignRef(ObjHeader* object, ForeignRefContext context) { + RuntimeCheck(false, "Unimplemented"); +} + +bool IsForeignRefAccessible(ObjHeader* object, ForeignRefContext context) { + RuntimeCheck(false, "Unimplemented"); +} + +void AdoptReferenceFromSharedVariable(ObjHeader* object) { + RuntimeCheck(false, "Unimplemented"); +} + +} // extern "C" diff --git a/kotlin-native/runtime/src/objc/cpp/ObjCExportClasses.mm b/kotlin-native/runtime/src/objc/cpp/ObjCExportClasses.mm new file mode 100644 index 00000000000..bbe2641770a --- /dev/null +++ b/kotlin-native/runtime/src/objc/cpp/ObjCExportClasses.mm @@ -0,0 +1,242 @@ +/* + * Copyright 2010-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +#import "Types.h" +#import "Memory.h" +#import "MemorySharedRefs.hpp" + +#if KONAN_OBJC_INTEROP + +#import +#import +#import +#import +#import +#import +#import +#import + +#import "ObjCExport.h" +#import "ObjCExportInit.h" +#import "ObjCExportPrivate.h" +#import "Runtime.h" +#import "Utils.h" +#import "Exceptions.h" + +extern "C" id objc_retainAutoreleaseReturnValue(id self); +extern "C" id objc_autoreleaseReturnValue(id self); + +@interface NSObject (NSObjectPrivateMethods) +// Implemented for NSObject in libobjc/NSObject.mm +-(BOOL)_tryRetain; +@end; + +static void injectToRuntime(); + +// Note: `KotlinBase`'s `toKotlin` and `_tryRetain` methods will terminate if +// called with non-frozen object on a wrong worker. `retain` will also terminate +// in these conditions if backref's refCount is zero. + +@implementation KotlinBase { + BackRefFromAssociatedObject refHolder; + bool permanent; +} + +-(KRef)toKotlin:(KRef*)OBJ_RESULT { + RETURN_OBJ(refHolder.ref()); +} + ++(void)load { + injectToRuntime(); +} + ++(void)initialize { + if (self == [KotlinBase class]) { + Kotlin_ObjCExport_initialize(); + } + Kotlin_ObjCExport_initializeClass(self); +} + ++(instancetype)allocWithZone:(NSZone*)zone { + Kotlin_initRuntimeIfNeeded(); + + KotlinBase* result = [super allocWithZone:zone]; + + const TypeInfo* typeInfo = Kotlin_ObjCExport_getAssociatedTypeInfo(self); + if (typeInfo == nullptr) { + [NSException raise:NSGenericException + format:@"%s is not allocatable or +[KotlinBase initialize] method wasn't called on it", + class_getName(object_getClass(self))]; + } + + if (typeInfo->instanceSize_ < 0) { + [NSException raise:NSGenericException + format:@"%s must be allocated and initialized with a factory method", + class_getName(object_getClass(self))]; + } + ObjHolder holder; + AllocInstanceWithAssociatedObject(typeInfo, result, holder.slot()); + result->refHolder.initAndAddRef(holder.obj()); + RuntimeAssert(!holder.obj()->permanent(), "dynamically allocated object is permanent"); + result->permanent = false; + return result; +} + ++(instancetype)createWrapper:(ObjHeader*)obj { + KotlinBase* candidate = [super allocWithZone:nil]; + // TODO: should we call NSObject.init ? + candidate->refHolder.initAndAddRef(obj); + candidate->permanent = obj->permanent(); + + if (!obj->permanent()) { // TODO: permanent objects should probably be supported as custom types. + if (!isShareable(obj)) { + SetAssociatedObject(obj, candidate); + } else { + id old = AtomicCompareAndSwapAssociatedObject(obj, nullptr, candidate); + if (old != nullptr) { + candidate->refHolder.releaseRef(); + [candidate releaseAsAssociatedObject]; + return objc_retainAutoreleaseReturnValue(old); + } + } + } + + return objc_autoreleaseReturnValue(candidate); +} + +-(instancetype)retain { + if (permanent) { + [super retain]; + } else { + refHolder.addRef(); + } + return self; +} + +-(BOOL)_tryRetain { + if (permanent) { + return [super _tryRetain]; + } else { + return refHolder.tryAddRef(); + } +} + +-(oneway void)release { + if (permanent) { + [super release]; + } else { + refHolder.releaseRef(); + } +} + +-(void)releaseAsAssociatedObject { + // This function is called by the GC. It made a decision to reclaim Kotlin object, and runs + // deallocation hooks at the moment, including deallocation of the "associated object" ([self]) + // using the [super release] call below. + + // The deallocation involves running [self dealloc] which can contain arbitrary code. + // In particular, this code can retain and release [self]. Obj-C and Swift runtimes handle this + // gracefully (unless the object gets accessed after the deallocation of course), but Kotlin doesn't. + // Generally retaining and releasing Kotlin object that is being deallocated would lead to + // use-after-dispose and double-dispose problems (with unpredictable consequences) or to an assertion failure. + // To workaround this, detach the back ref from the Kotlin object: + refHolder.detach(); + // So retain/release/etc. on [self] won't affect the Kotlin object, and an attempt to get + // the reference to it (e.g. when calling Kotlin method on [self]) would crash. + // The latter is generally ok because can be triggered only by user-defined Swift/Obj-C + // subclasses of Kotlin classes. + + [super release]; +} + +- (instancetype)copyWithZone:(NSZone *)zone { + // TODO: write documentation. + return [self retain]; +} + +@end; + +@interface NSObject (NSObjectToKotlin) +@end; + +@implementation NSObject (NSObjectToKotlin) +-(ObjHeader*)toKotlin:(ObjHeader**)OBJ_RESULT { + RETURN_RESULT_OF(Kotlin_ObjCExport_convertUnmappedObjCObject, self); +} + +-(void)releaseAsAssociatedObject { + objc_release(self); +} +@end; + +@interface NSString (NSStringToKotlin) +@end; + +@implementation NSString (NSStringToKotlin) +-(ObjHeader*)toKotlin:(ObjHeader**)OBJ_RESULT { + RETURN_RESULT_OF(Kotlin_Interop_CreateKStringFromNSString, self); +} +@end; + +extern "C" { + +OBJ_GETTER(Kotlin_boxByte, KByte value); +OBJ_GETTER(Kotlin_boxShort, KShort value); +OBJ_GETTER(Kotlin_boxInt, KInt value); +OBJ_GETTER(Kotlin_boxLong, KLong value); +OBJ_GETTER(Kotlin_boxUByte, KUByte value); +OBJ_GETTER(Kotlin_boxUShort, KUShort value); +OBJ_GETTER(Kotlin_boxUInt, KUInt value); +OBJ_GETTER(Kotlin_boxULong, KULong value); +OBJ_GETTER(Kotlin_boxFloat, KFloat value); +OBJ_GETTER(Kotlin_boxDouble, KDouble value); + +} + +@interface NSNumber (NSNumberToKotlin) +@end; + +@implementation NSNumber (NSNumberToKotlin) +-(ObjHeader*)toKotlin:(ObjHeader**)OBJ_RESULT { + const char* type = self.objCType; + + // TODO: the code below makes some assumption on char, short, int and long sizes. + + switch (type[0]) { + case 'c': RETURN_RESULT_OF(Kotlin_boxByte, self.charValue); + case 's': RETURN_RESULT_OF(Kotlin_boxShort, self.shortValue); + case 'i': RETURN_RESULT_OF(Kotlin_boxInt, self.intValue); + case 'q': RETURN_RESULT_OF(Kotlin_boxLong, self.longLongValue); + case 'C': RETURN_RESULT_OF(Kotlin_boxUByte, self.unsignedCharValue); + case 'S': RETURN_RESULT_OF(Kotlin_boxUShort, self.unsignedShortValue); + case 'I': RETURN_RESULT_OF(Kotlin_boxUInt, self.unsignedIntValue); + case 'Q': RETURN_RESULT_OF(Kotlin_boxULong, self.unsignedLongLongValue); + case 'f': RETURN_RESULT_OF(Kotlin_boxFloat, self.floatValue); + case 'd': RETURN_RESULT_OF(Kotlin_boxDouble, self.doubleValue); + + default: RETURN_RESULT_OF(Kotlin_ObjCExport_convertUnmappedObjCObject, self); + } +} +@end; + +@interface NSDecimalNumber (NSDecimalNumberToKotlin) +@end; + +@implementation NSDecimalNumber (NSDecimalNumberToKotlin) +// Overrides [NSNumber toKotlin:] implementation. +-(ObjHeader*)toKotlin:(ObjHeader**)OBJ_RESULT { + RETURN_RESULT_OF(Kotlin_ObjCExport_convertUnmappedObjCObject, self); +} +@end; + +static void injectToRuntime() { + RuntimeCheck(Kotlin_ObjCExport_toKotlinSelector == nullptr, "runtime injected twice"); + Kotlin_ObjCExport_toKotlinSelector = @selector(toKotlin:); + + RuntimeCheck(Kotlin_ObjCExport_releaseAsAssociatedObjectSelector == nullptr, "runtime injected twice"); + Kotlin_ObjCExport_releaseAsAssociatedObjectSelector = @selector(releaseAsAssociatedObject); +} + +#endif // KONAN_OBJC_INTEROP diff --git a/kotlin-native/runtime/src/objc/cpp/ObjCExportCollections.mm b/kotlin-native/runtime/src/objc/cpp/ObjCExportCollections.mm new file mode 100644 index 00000000000..6e01c23eab4 --- /dev/null +++ b/kotlin-native/runtime/src/objc/cpp/ObjCExportCollections.mm @@ -0,0 +1,590 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "Memory.h" +#import "MemorySharedRefs.hpp" +#import "Types.h" + +#if KONAN_OBJC_INTEROP + +#import + +#import +#import +#import +#import +#import + +#import "Exceptions.h" +#import "Runtime.h" +#import "ObjCExport.h" +#import "ObjCExportCollections.h" + +extern "C" { + +// Imports from ObjCExportUtils.kt: + +OBJ_GETTER0(Kotlin_NSArrayAsKList_create); +OBJ_GETTER0(Kotlin_NSMutableArrayAsKMutableList_create); +OBJ_GETTER0(Kotlin_NSSetAsKSet_create); +OBJ_GETTER0(Kotlin_NSDictionaryAsKMap_create); + +KBoolean Kotlin_Iterator_hasNext(KRef iterator); +OBJ_GETTER(Kotlin_Iterator_next, KRef iterator); +KInt Kotlin_Collection_getSize(KRef collection); +KBoolean Kotlin_Set_contains(KRef set, KRef element); +OBJ_GETTER(Kotlin_Set_getElement, KRef set, KRef element); +OBJ_GETTER(Kotlin_Set_iterator, KRef set); +void Kotlin_MutableCollection_removeObject(KRef collection, KRef element); +void Kotlin_MutableCollection_addObject(KRef list, KRef obj); +OBJ_GETTER(Kotlin_MutableSet_createWithCapacity, KInt capacity); + +KInt Kotlin_Map_getSize(KRef map); +KBoolean Kotlin_Map_containsKey(KRef map, KRef key); +OBJ_GETTER(Kotlin_Map_get, KRef map, KRef key); +OBJ_GETTER(Kotlin_Map_keyIterator, KRef map); +OBJ_GETTER(Kotlin_List_get, KRef list, KInt index); + +OBJ_GETTER(Kotlin_MutableMap_createWithCapacity, KInt capacity); +void Kotlin_MutableMap_set(KRef map, KRef key, KRef value); +void Kotlin_MutableMap_remove(KRef map, KRef key); +void Kotlin_MutableList_addObjectAtIndex(KRef list, KInt index, KRef obj); +void Kotlin_MutableList_removeObjectAtIndex(KRef list, KInt index); +void Kotlin_MutableList_removeLastObject(KRef list); +void Kotlin_MutableList_setObject(KRef list, KInt index, KRef obj); + +} // extern "C" + +static inline KInt objCCapacityToKotlin(NSUInteger capacity) { + NSUInteger max = std::numeric_limits::max(); + return capacity > max ? max : capacity; +} + +static inline KInt objCIndexToKotlinOrThrow(NSUInteger index) { + if (index > std::numeric_limits::max()) { + ThrowArrayIndexOutOfBoundsException(); + } + + return index; +} + +// Note: collections can only be iterated on and converted to Kotlin representation +// when they are either frozen or if they are called on the worker that created them. + +@interface NSArray (NSArrayToKotlin) +@end; + +@implementation NSArray (NSArrayToKotlin) +-(KRef)toKotlin:(KRef*)OBJ_RESULT { + RETURN_RESULT_OF(invokeAndAssociate, Kotlin_NSArrayAsKList_create, objc_retain(self)); +} + +-(void)releaseAsAssociatedObject { + objc_release(self); +} +@end; + +@interface NSMutableArray (NSMutableArrayToKotlin) +@end; + +@implementation NSMutableArray (NSArrayToKotlin) +-(KRef)toKotlin:(KRef*)OBJ_RESULT { + RETURN_RESULT_OF(invokeAndAssociate, Kotlin_NSMutableArrayAsKMutableList_create, objc_retain(self)); +} + +-(void)releaseAsAssociatedObject { + objc_release(self); +} +@end; + + +@interface NSSet (NSSetToKotlin) +@end; + +@implementation NSSet (NSSetToKotlin) +-(KRef)toKotlin:(KRef*)OBJ_RESULT { + RETURN_RESULT_OF(invokeAndAssociate, Kotlin_NSSetAsKSet_create, objc_retain(self)); +} + +-(void)releaseAsAssociatedObject { + objc_release(self); +} + +@end; + +@interface NSDictionary (NSDictionaryToKotlin) +@end; + +@implementation NSDictionary (NSDictionaryToKotlin) +-(KRef)toKotlin:(KRef*)OBJ_RESULT { + RETURN_RESULT_OF(invokeAndAssociate, Kotlin_NSDictionaryAsKMap_create, objc_retain(self)); +} + +-(void)releaseAsAssociatedObject { + objc_release(self); +} + +@end; + +@interface KIteratorAsNSEnumerator : NSEnumerator +@end; + +@implementation KIteratorAsNSEnumerator { + KRefSharedHolder iteratorHolder; +} + +-(void)dealloc { + iteratorHolder.dispose(); + [super dealloc]; +} + ++(id)createWithKIterator:(KRef)iterator { + KIteratorAsNSEnumerator* result = [[[KIteratorAsNSEnumerator alloc] init] autorelease]; + result->iteratorHolder.init(iterator); + return result; +} + +- (id)nextObject { + KRef iterator = iteratorHolder.ref(); + if (Kotlin_Iterator_hasNext(iterator)) { + ObjHolder holder; + return refToObjCOrNSNull(Kotlin_Iterator_next(iterator, holder.slot())); + } else { + return nullptr; + } +} +@end; + +@interface KListAsNSArray : NSArray +@end; + +@implementation KListAsNSArray { + KRefSharedHolder listHolder; +} + +-(void)dealloc { + listHolder.dispose(); + [super dealloc]; +} + ++(id)createWithKList:(KRef)list { + KListAsNSArray* result = [[[KListAsNSArray alloc] init] autorelease]; + result->listHolder.init(list); + return result; +} + +-(KRef)toKotlin:(KRef*)OBJ_RESULT { + RETURN_OBJ(listHolder.ref()); +} + +-(id)objectAtIndex:(NSUInteger)index { + ObjHolder kotlinValueHolder; + KRef kotlinValue = Kotlin_List_get(listHolder.ref(), index, kotlinValueHolder.slot()); + return refToObjCOrNSNull(kotlinValue); +} + +-(NSUInteger)count { + return Kotlin_Collection_getSize(listHolder.ref()); +} + +@end; + +@interface KMutableListAsNSMutableArray : NSMutableArray +@end; + +@implementation KMutableListAsNSMutableArray { + KRefSharedHolder listHolder; +} + +-(void)dealloc { + listHolder.dispose(); + [super dealloc]; +} + ++(id)createWithKList:(KRef)list { + KMutableListAsNSMutableArray* result = [[[KMutableListAsNSMutableArray alloc] init] autorelease]; + result->listHolder.init(list); + return result; +} + +-(KRef)toKotlin:(KRef*)OBJ_RESULT { + RETURN_OBJ(listHolder.ref()); +} + +-(id)objectAtIndex:(NSUInteger)index { + ObjHolder kotlinValueHolder; + KRef kotlinValue = Kotlin_List_get(listHolder.ref(), index, kotlinValueHolder.slot()); + return refToObjCOrNSNull(kotlinValue); +} + +-(NSUInteger)count { + return Kotlin_Collection_getSize(listHolder.ref()); +} + +- (void)insertObject:(id)anObject atIndex:(NSUInteger)index { + ObjHolder holder; + KRef kotlinObject = refFromObjCOrNSNull(anObject, holder.slot()); + Kotlin_MutableList_addObjectAtIndex(listHolder.ref(), objCIndexToKotlinOrThrow(index), kotlinObject); +} + +- (void)removeObjectAtIndex:(NSUInteger)index { + Kotlin_MutableList_removeObjectAtIndex(listHolder.ref(), objCIndexToKotlinOrThrow(index)); +} + +- (void)addObject:(id)anObject { + ObjHolder holder; + Kotlin_MutableCollection_addObject(listHolder.ref(), refFromObjCOrNSNull(anObject, holder.slot())); +} + +- (void)removeLastObject { + Kotlin_MutableList_removeLastObject(listHolder.ref()); +} + +- (void)replaceObjectAtIndex:(NSUInteger)index withObject:(id)anObject { + ObjHolder holder; + KRef kotlinObject = refFromObjCOrNSNull(anObject, holder.slot()); + Kotlin_MutableList_setObject(listHolder.ref(), objCIndexToKotlinOrThrow(index), kotlinObject); +} + +@end; + +@interface KSetAsNSSet : NSSet +@end; + +static inline id KSet_getElement(KRef set, id object) { + if (object == NSNull.null) { + return Kotlin_Set_contains(set, nullptr) ? object : nullptr; + } else { + ObjHolder requestHolder, resultHolder; + KRef request = Kotlin_ObjCExport_refFromObjC(object, requestHolder.slot()); + KRef result = Kotlin_Set_getElement(set, request, resultHolder.slot()); + + // Note: if result is nullptr, then it can't be a null element of the set, because request != nullptr; + // so map nullptr to nullptr: + return Kotlin_ObjCExport_refToObjC(result); + } +} + +@implementation KSetAsNSSet { + KRefSharedHolder setHolder; +} + +-(void)dealloc { + setHolder.dispose(); + [super dealloc]; +} + ++(id)createWithKSet:(KRef)set { + KSetAsNSSet* result = [[[KSetAsNSSet alloc] init] autorelease]; + result->setHolder.init(set); + return result; +} + +-(KRef)toKotlin:(KRef*)OBJ_RESULT { + RETURN_OBJ(setHolder.ref()); +} + +-(NSUInteger) count { + return Kotlin_Collection_getSize(setHolder.ref()); +} + +- (id)member:(id)object { + return KSet_getElement(setHolder.ref(), object); +} + +// Not mandatory, just an optimization: +- (BOOL)containsObject:(id)anObject { + ObjHolder holder; + return Kotlin_Set_contains(setHolder.ref(), refFromObjCOrNSNull(anObject, holder.slot())); +} + +- (NSEnumerator*)objectEnumerator { + ObjHolder holder; + return [KIteratorAsNSEnumerator createWithKIterator:Kotlin_Set_iterator(setHolder.ref(), holder.slot())]; +} +@end; + +@interface KotlinMutableSet : NSMutableSet +@end; + +@implementation KotlinMutableSet { + KRefSharedHolder setHolder; +} + +-(instancetype)init { + if (self = [super init]) { + Kotlin_initRuntimeIfNeeded(); + ObjHolder holder; + KRef set = Kotlin_MutableSet_createWithCapacity(8, holder.slot()); + self->setHolder.init(set); + } + + return self; +} + +- (instancetype)initWithCapacity:(NSUInteger)numItems { + if (self = [super init]) { + Kotlin_initRuntimeIfNeeded(); + ObjHolder holder; + KRef set = Kotlin_MutableSet_createWithCapacity(objCCapacityToKotlin(numItems), holder.slot()); + self->setHolder.init(set); + } + + return self; +} + +// TODO: super class implementation appears to be good enough. +- (instancetype)initWithObjects:(const id _Nonnull [_Nullable])objects count:(NSUInteger)cnt { + if (self = [self initWithCapacity:cnt]) { + for (NSUInteger i = 0; i < cnt; ++i) { + [self addObject:objects[i]]; + } + } + + return self; +} + +// TODO: what about +// - (nullable instancetype)initWithCoder:(NSCoder *)aDecoder +// ? + +-(void)dealloc { + // Note: since setHolder initialization is not performed directly with alloc, + // it is possible that it wasn't initialized properly. + // Fortunately setHolder.dispose() handles the zero-initialized case too. + setHolder.dispose(); + [super dealloc]; +} + +-(instancetype)initWithKSet:(KRef)set { + if (self = [super init]) { + setHolder.init(set); + } + + return self; +} + +-(KRef)toKotlin:(KRef*)OBJ_RESULT { + RETURN_OBJ(setHolder.ref()); +} + +-(NSUInteger) count { + return Kotlin_Collection_getSize(setHolder.ref()); +} + +- (id)member:(id)object { + return KSet_getElement(setHolder.ref(), object); +} + +// Not mandatory, just an optimization: +- (BOOL)containsObject:(id)anObject { + ObjHolder holder; + return Kotlin_Set_contains(setHolder.ref(), refFromObjCOrNSNull(anObject, holder.slot())); +} + +- (NSEnumerator*)objectEnumerator { + ObjHolder holder; + return [KIteratorAsNSEnumerator createWithKIterator:Kotlin_Set_iterator(setHolder.ref(), holder.slot())]; +} + +- (void)addObject:(id)object { + ObjHolder holder; + Kotlin_MutableCollection_addObject(setHolder.ref(), refFromObjCOrNSNull(object, holder.slot())); +} + +- (void)removeObject:(id)object { + ObjHolder holder; + Kotlin_MutableCollection_removeObject(setHolder.ref(), refFromObjCOrNSNull(object, holder.slot())); +} +@end; + +@interface KMapAsNSDictionary : NSDictionary +@end; + +static inline id KMap_get(KRef map, id aKey) { + ObjHolder keyHolder, valueHolder; + + KRef kotlinKey = refFromObjCOrNSNull(aKey, keyHolder.slot()); + KRef kotlinValue = Kotlin_Map_get(map, kotlinKey, valueHolder.slot()); + + if (kotlinValue == nullptr) { + // Either null or not found. + return Kotlin_Map_containsKey(map, kotlinKey) ? NSNull.null : nullptr; + } else { + return refToObjCOrNSNull(kotlinValue); + } +} + +@implementation KMapAsNSDictionary { + KRefSharedHolder mapHolder; +} + +-(void)dealloc { + mapHolder.dispose(); + [super dealloc]; +} + ++(id)createWithKMap:(KRef)map { + KMapAsNSDictionary* result = [[[KMapAsNSDictionary alloc] init] autorelease]; + result->mapHolder.init(map); + return result; +} + +-(KRef)toKotlin:(KRef*)OBJ_RESULT { + RETURN_OBJ(mapHolder.ref()); +} + +// According to documentation, initWithObjects:forKeys:count: is required to be overridden when subclassing. +// But that doesn't make any sense, since this class can't be arbitrary initialized. + +-(NSUInteger) count { + return Kotlin_Map_getSize(mapHolder.ref()); +} + +- (id)objectForKey:(id)aKey { + return KMap_get(mapHolder.ref(), aKey); +} + +- (NSEnumerator *)keyEnumerator { + ObjHolder holder; + return [KIteratorAsNSEnumerator createWithKIterator:Kotlin_Map_keyIterator(mapHolder.ref(), holder.slot())]; +} + +@end; + +@interface KotlinMutableDictionary : NSMutableDictionary +@end; + +@implementation KotlinMutableDictionary { + KRefSharedHolder mapHolder; +} + +-(void)dealloc { + // Note: since mapHolder initialization is not performed directly with alloc, + // it is possible that it wasn't initialized properly. + // Fortunately mapHolder.dispose() handles the zero-initialized case too. + mapHolder.dispose(); + [super dealloc]; +} + +-(instancetype)init { + if (self = [super init]) { + Kotlin_initRuntimeIfNeeded(); + ObjHolder holder; + KRef map = Kotlin_MutableMap_createWithCapacity(8, holder.slot()); + self->mapHolder.init(map); + } + return self; +} + +// 'initWithObjects:forKeys:count:' seems to be implemented in base class. + +// TODO: what about +// - (nullable instancetype)initWithCoder:(NSCoder *)aDecoder +// ? + +- (instancetype)initWithCapacity:(NSUInteger)numItems { + if (self = [super init]) { + Kotlin_initRuntimeIfNeeded(); + ObjHolder holder; + KRef map = Kotlin_MutableMap_createWithCapacity(objCCapacityToKotlin(numItems), holder.slot()); + self->mapHolder.init(map); + } + return self; +} + +-(instancetype)initWithKMap:(KRef)map { + if (self = [super init]) { + mapHolder.init(map); + } + + return self; +} + +-(KRef)toKotlin:(KRef*)OBJ_RESULT { + RETURN_OBJ(mapHolder.ref()); +} + +-(NSUInteger) count { + return Kotlin_Map_getSize(mapHolder.ref()); +} + +- (id)objectForKey:(id)aKey { + return KMap_get(mapHolder.ref(), aKey); +} + +- (NSEnumerator *)keyEnumerator { + ObjHolder holder; + return [KIteratorAsNSEnumerator createWithKIterator:Kotlin_Map_keyIterator(mapHolder.ref(), holder.slot())]; +} + +- (void)setObject:(id)anObject forKey:(id)aKey { + ObjHolder keyHolder, valueHolder; + + id keyCopy = [aKey copyWithZone:nullptr]; // Correspond to the expected NSMutableDictionary behaviour. + KRef kotlinKey = refFromObjCOrNSNull(keyCopy, keyHolder.slot()); + objc_release(keyCopy); + + KRef kotlinValue = refFromObjCOrNSNull(anObject, valueHolder.slot()); + + Kotlin_MutableMap_set(mapHolder.ref(), kotlinKey, kotlinValue); +} + +- (void)removeObjectForKey:(id)aKey { + ObjHolder holder; + KRef kotlinKey = refFromObjCOrNSNull(aKey, holder.slot()); + + Kotlin_MutableMap_remove(mapHolder.ref(), kotlinKey); +} + +@end; + +@interface NSEnumerator (NSEnumeratorAsAssociatedObject) +@end; + +@implementation NSEnumerator (NSEnumeratorAsAssociatedObject) +-(void)releaseAsAssociatedObject { + objc_release(self); +} +@end; + +// Referenced from the generated code: + +extern "C" id Kotlin_Interop_CreateNSArrayFromKList(KRef obj) { + return [KListAsNSArray createWithKList:obj]; +} + +extern "C" id Kotlin_Interop_CreateNSMutableArrayFromKList(KRef obj) { + return [KMutableListAsNSMutableArray createWithKList:obj]; +} + +extern "C" id Kotlin_Interop_CreateNSSetFromKSet(KRef obj) { + return [KSetAsNSSet createWithKSet:obj]; +} + +extern "C" id Kotlin_Interop_CreateKotlinMutableSetFromKSet(KRef obj) { + return [[[KotlinMutableSet alloc] initWithKSet:obj] autorelease]; +} + +extern "C" id Kotlin_Interop_CreateNSDictionaryFromKMap(KRef obj) { + return [KMapAsNSDictionary createWithKMap:obj]; +} + +extern "C" id Kotlin_Interop_CreateKotlinMutableDictonaryFromKMap(KRef obj) { + return [[[KotlinMutableDictionary alloc] initWithKMap:obj] autorelease]; +} + +#endif // KONAN_OBJC_INTEROP diff --git a/kotlin-native/runtime/src/objc/cpp/ObjCExportNumbers.mm b/kotlin-native/runtime/src/objc/cpp/ObjCExportNumbers.mm new file mode 100644 index 00000000000..e721dab6991 --- /dev/null +++ b/kotlin-native/runtime/src/objc/cpp/ObjCExportNumbers.mm @@ -0,0 +1,766 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#if KONAN_OBJC_INTEROP + +#import +#import +#import +#import + +#import "ObjCExport.h" +#import "Runtime.h" +#import "Utils.h" + +extern "C" { + +OBJ_GETTER(Kotlin_boxBoolean, KBoolean value); +OBJ_GETTER(Kotlin_boxByte, KByte value); +OBJ_GETTER(Kotlin_boxShort, KShort value); +OBJ_GETTER(Kotlin_boxInt, KInt value); +OBJ_GETTER(Kotlin_boxLong, KLong value); +OBJ_GETTER(Kotlin_boxUByte, KUByte value); +OBJ_GETTER(Kotlin_boxUShort, KUShort value); +OBJ_GETTER(Kotlin_boxUInt, KUInt value); +OBJ_GETTER(Kotlin_boxULong, KULong value); +OBJ_GETTER(Kotlin_boxFloat, KFloat value); +OBJ_GETTER(Kotlin_boxDouble, KDouble value); + +} + +#pragma clang diagnostic ignored "-Wobjc-designated-initializers" + +@interface KotlinNumber : NSNumber +@end; + +[[ noreturn ]] static void incorrectNumberInitialization(KotlinNumber* self, SEL _cmd) { + [NSException raise:NSGenericException format:@"%@ can't be initialized with %s, use properly typed initialized", + NSStringFromClass([self class]), sel_getName(_cmd)]; + + abort(); +} + +[[ noreturn ]] static void incorrectNumberFactory(Class self, SEL _cmd) { + [NSException raise:NSGenericException format:@"%@ can't be created with %s, use properly typed factory", + NSStringFromClass(self), sel_getName(_cmd)]; + + abort(); +} + +@implementation KotlinNumber : NSNumber + +- (NSNumber *)initWithBool:(BOOL)value { incorrectNumberInitialization(self, _cmd); } +- (NSNumber *)initWithChar:(char)value { incorrectNumberInitialization(self, _cmd); } +- (NSNumber *)initWithShort:(short)value { incorrectNumberInitialization(self, _cmd); } +- (NSNumber *)initWithInt:(int)value { incorrectNumberInitialization(self, _cmd); } +- (NSNumber *)initWithInteger:(NSInteger)value { incorrectNumberInitialization(self, _cmd); } +- (NSNumber *)initWithLong:(long)value { incorrectNumberInitialization(self, _cmd); } +- (NSNumber *)initWithLongLong:(long long)value { incorrectNumberInitialization(self, _cmd); } +- (NSNumber *)initWithUnsignedChar:(unsigned char)value { incorrectNumberInitialization(self, _cmd); } +- (NSNumber *)initWithUnsignedShort:(unsigned short)value { incorrectNumberInitialization(self, _cmd); } +- (NSNumber *)initWithUnsignedInt:(unsigned int)value { incorrectNumberInitialization(self, _cmd); } +- (NSNumber *)initWithUnsignedInteger:(NSUInteger)value { incorrectNumberInitialization(self, _cmd); } +- (NSNumber *)initWithUnsignedLong:(unsigned long)value { incorrectNumberInitialization(self, _cmd); } +- (NSNumber *)initWithUnsignedLongLong:(unsigned long long)value { incorrectNumberInitialization(self, _cmd); } +- (NSNumber *)initWithFloat:(float)value { incorrectNumberInitialization(self, _cmd); } +- (NSNumber *)initWithDouble:(double)value { incorrectNumberInitialization(self, _cmd); } + ++ (NSNumber *)numberWithBool:(BOOL)value { incorrectNumberFactory(self, _cmd); } ++ (NSNumber *)numberWithChar:(char)value { incorrectNumberFactory(self, _cmd); } ++ (NSNumber *)numberWithShort:(short)value { incorrectNumberFactory(self, _cmd); } ++ (NSNumber *)numberWithInt:(int)value { incorrectNumberFactory(self, _cmd); } ++ (NSNumber *)numberWithInteger:(NSInteger)value { incorrectNumberFactory(self, _cmd); } ++ (NSNumber *)numberWithLong:(long)value { incorrectNumberFactory(self, _cmd); } ++ (NSNumber *)numberWithLongLong:(long long)value { incorrectNumberFactory(self, _cmd); } ++ (NSNumber *)numberWithUnsignedChar:(unsigned char)value { incorrectNumberFactory(self, _cmd); } ++ (NSNumber *)numberWithUnsignedShort:(unsigned short)value { incorrectNumberFactory(self, _cmd); } ++ (NSNumber *)numberWithUnsignedInt:(unsigned int)value { incorrectNumberFactory(self, _cmd); } ++ (NSNumber *)numberWithUnsignedLong:(unsigned long)value { incorrectNumberFactory(self, _cmd); } ++ (NSNumber *)numberWithUnsignedInteger:(NSUInteger)value { incorrectNumberFactory(self, _cmd); } ++ (NSNumber *)numberWithUnsignedLongLong:(unsigned long long)value { incorrectNumberFactory(self, _cmd); } ++ (NSNumber *)numberWithFloat:(float)value { incorrectNumberFactory(self, _cmd); } ++ (NSNumber *)numberWithDouble:(double)value { incorrectNumberFactory(self, _cmd); } + +@end; + +/* +The code below is generated by: + + +fun main(args: Array) { + println(genBoolean()) + println(genInteger("Byte", "c", "char")) + println(genInteger("Short", "s", "short")) + println(genInteger("Int", "i", "int")) + println(genInteger("Long", "q", "long long")) + println(genInteger("UByte", "C", "unsigned char")) + println(genInteger("UShort", "S", "unsigned short")) + println(genInteger("UInt", "I", "unsigned int")) + println(genInteger("ULong", "Q", "unsigned long long")) + println(genFloating("Float", "f", "float")) + println(genFloating("Double", "d", "double")) +} + +private fun genBoolean(): String = """ +@interface KotlinBoolean : KotlinNumber +@end; + +@implementation KotlinBoolean { + BOOL value_; +} + +- (void)getValue:(void *)value { + *(BOOL*)value = value_; +} + +- (instancetype)initWithBool:(BOOL)value { + self = [super init]; + value_ = value; + return self; +} + ++ (instancetype)numberWithBool:(BOOL)value { + KotlinBoolean* result = [[self new] autorelease]; + result->value_ = value; + return result; +} + +- (BOOL)boolValue { + return value_; +} + +- (char)charValue { + return value_; +} + +- (const char *)objCType { + return "c"; +} + +-(ObjHeader*)toKotlin:(ObjHeader**)OBJ_RESULT { + RETURN_RESULT_OF(Kotlin_boxBoolean, value_); +} + +@end; + +""".trimIndent() + +private fun genInteger( + name: String, + encoding: String, + cType: String, + kind: String = getNSNumberKind(cType) +) = """ +@interface Kotlin$name : KotlinNumber +@end; + +@implementation Kotlin$name { + $cType value_; +} + +- (void)getValue:(void *)value { + *($cType*)value = value_; +} + +- (instancetype)initWith${kind.capitalize()}:($cType)value { + self = [super init]; + value_ = value; + return self; +} + ++ (instancetype)numberWith${kind.capitalize()}:($cType)value { + Kotlin$name* result = [[self new] autorelease]; + result->value_ = value; + return result; +} + +// Required to convert Swift integer literals. +- (instancetype)initWithInteger:(NSInteger)value { + self = [super init]; + value_ = value; // TODO: check fits. + return self; +} + +- ($cType)${kind}Value { + return value_; +} + +- (const char *)objCType { + return "$encoding"; +} + +-(ObjHeader*)toKotlin:(ObjHeader**)OBJ_RESULT { + RETURN_RESULT_OF(Kotlin_box$name, value_); +} + +@end; + +""".trimIndent() + +private fun getNSNumberKind(cType: String) = + cType.split(' ').joinToString("") { it.capitalize() }.decapitalize() + +private fun genFloating( + name: String, + encoding: String, + cType: String, + kind: String = getNSNumberKind(cType) +): String = """ +@interface Kotlin$name : KotlinNumber +@end; + +@implementation Kotlin$name { + $cType value_; +} + +- (void)getValue:(void *)value { + *($cType*)value = value_; +} + +- (instancetype)initWith${kind.capitalize()}:($cType)value { + self = [super init]; + value_ = value; + return self; +} + ++ (instancetype)numberWith${kind.capitalize()}:($cType)value { + Kotlin$name* result = [[self new] autorelease]; + result->value_ = value; + return result; +} + +// Required to convert Swift integer literals. +- (instancetype)initWithInteger:(NSInteger)value { + self = [super init]; + value_ = value; // TODO: check fits. + return self; +} +${if (cType != "double") """ +// Required to convert Swift floating literals. +- (instancetype)initWithDouble:(double)value { + self = [super init]; + value_ = value; // TODO: check fits. + return self; +} +""" else ""} +- ($cType)${kind}Value { + return value_; +} + +- (const char *)objCType { + return "$encoding"; +} + +-(ObjHeader*)toKotlin:(ObjHeader**)OBJ_RESULT { + RETURN_RESULT_OF(Kotlin_box$name, value_); +} + +@end; + +""".trimIndent() +*/ + +// TODO: consider generating it by compiler. + +@interface KotlinBoolean : KotlinNumber +@end; + +@implementation KotlinBoolean { + BOOL value_; +} + +- (void)getValue:(void *)value { + *(BOOL*)value = value_; +} + +- (instancetype)initWithBool:(BOOL)value { + self = [super init]; + value_ = value; + return self; +} + ++ (instancetype)numberWithBool:(BOOL)value { + KotlinBoolean* result = [[self new] autorelease]; + result->value_ = value; + return result; +} + +- (BOOL)boolValue { + return value_; +} + +- (char)charValue { + return value_; +} + +- (const char *)objCType { + return "c"; +} + +-(ObjHeader*)toKotlin:(ObjHeader**)OBJ_RESULT { + RETURN_RESULT_OF(Kotlin_boxBoolean, value_); +} + +@end; + +@interface KotlinByte : KotlinNumber +@end; + +@implementation KotlinByte { + char value_; +} + +- (void)getValue:(void *)value { + *(char*)value = value_; +} + +- (instancetype)initWithChar:(char)value { + self = [super init]; + value_ = value; + return self; +} + ++ (instancetype)numberWithChar:(char)value { + KotlinByte* result = [[self new] autorelease]; + result->value_ = value; + return result; +} + +// Required to convert Swift integer literals. +- (instancetype)initWithInteger:(NSInteger)value { + self = [super init]; + value_ = value; // TODO: check fits. + return self; +} + +- (char)charValue { + return value_; +} + +- (const char *)objCType { + return "c"; +} + +-(ObjHeader*)toKotlin:(ObjHeader**)OBJ_RESULT { + RETURN_RESULT_OF(Kotlin_boxByte, value_); +} + +@end; + +@interface KotlinShort : KotlinNumber +@end; + +@implementation KotlinShort { + short value_; +} + +- (void)getValue:(void *)value { + *(short*)value = value_; +} + +- (instancetype)initWithShort:(short)value { + self = [super init]; + value_ = value; + return self; +} + ++ (instancetype)numberWithShort:(short)value { + KotlinShort* result = [[self new] autorelease]; + result->value_ = value; + return result; +} + +// Required to convert Swift integer literals. +- (instancetype)initWithInteger:(NSInteger)value { + self = [super init]; + value_ = value; // TODO: check fits. + return self; +} + +- (short)shortValue { + return value_; +} + +- (const char *)objCType { + return "s"; +} + +-(ObjHeader*)toKotlin:(ObjHeader**)OBJ_RESULT { + RETURN_RESULT_OF(Kotlin_boxShort, value_); +} + +@end; + +@interface KotlinInt : KotlinNumber +@end; + +@implementation KotlinInt { + int value_; +} + +- (void)getValue:(void *)value { + *(int*)value = value_; +} + +- (instancetype)initWithInt:(int)value { + self = [super init]; + value_ = value; + return self; +} + ++ (instancetype)numberWithInt:(int)value { + KotlinInt* result = [[self new] autorelease]; + result->value_ = value; + return result; +} + +// Required to convert Swift integer literals. +- (instancetype)initWithInteger:(NSInteger)value { + self = [super init]; + value_ = value; // TODO: check fits. + return self; +} + +- (int)intValue { + return value_; +} + +- (const char *)objCType { + return "i"; +} + +-(ObjHeader*)toKotlin:(ObjHeader**)OBJ_RESULT { + RETURN_RESULT_OF(Kotlin_boxInt, value_); +} + +@end; + +@interface KotlinLong : KotlinNumber +@end; + +@implementation KotlinLong { + long long value_; +} + +- (void)getValue:(void *)value { + *(long long*)value = value_; +} + +- (instancetype)initWithLongLong:(long long)value { + self = [super init]; + value_ = value; + return self; +} + ++ (instancetype)numberWithLongLong:(long long)value { + KotlinLong* result = [[self new] autorelease]; + result->value_ = value; + return result; +} + +// Required to convert Swift integer literals. +- (instancetype)initWithInteger:(NSInteger)value { + self = [super init]; + value_ = value; // TODO: check fits. + return self; +} + +- (long long)longLongValue { + return value_; +} + +- (const char *)objCType { + return "q"; +} + +-(ObjHeader*)toKotlin:(ObjHeader**)OBJ_RESULT { + RETURN_RESULT_OF(Kotlin_boxLong, value_); +} + +@end; + +@interface KotlinUByte : KotlinNumber +@end; + +@implementation KotlinUByte { + unsigned char value_; +} + +- (void)getValue:(void *)value { + *(unsigned char*)value = value_; +} + +- (instancetype)initWithUnsignedChar:(unsigned char)value { + self = [super init]; + value_ = value; + return self; +} + ++ (instancetype)numberWithUnsignedChar:(unsigned char)value { + KotlinUByte* result = [[self new] autorelease]; + result->value_ = value; + return result; +} + +// Required to convert Swift integer literals. +- (instancetype)initWithInteger:(NSInteger)value { + self = [super init]; + value_ = value; // TODO: check fits. + return self; +} + +- (unsigned char)unsignedCharValue { + return value_; +} + +- (const char *)objCType { + return "C"; +} + +-(ObjHeader*)toKotlin:(ObjHeader**)OBJ_RESULT { + RETURN_RESULT_OF(Kotlin_boxUByte, value_); +} + +@end; + +@interface KotlinUShort : KotlinNumber +@end; + +@implementation KotlinUShort { + unsigned short value_; +} + +- (void)getValue:(void *)value { + *(unsigned short*)value = value_; +} + +- (instancetype)initWithUnsignedShort:(unsigned short)value { + self = [super init]; + value_ = value; + return self; +} + ++ (instancetype)numberWithUnsignedShort:(unsigned short)value { + KotlinUShort* result = [[self new] autorelease]; + result->value_ = value; + return result; +} + +// Required to convert Swift integer literals. +- (instancetype)initWithInteger:(NSInteger)value { + self = [super init]; + value_ = value; // TODO: check fits. + return self; +} + +- (unsigned short)unsignedShortValue { + return value_; +} + +- (const char *)objCType { + return "S"; +} + +-(ObjHeader*)toKotlin:(ObjHeader**)OBJ_RESULT { + RETURN_RESULT_OF(Kotlin_boxUShort, value_); +} + +@end; + +@interface KotlinUInt : KotlinNumber +@end; + +@implementation KotlinUInt { + unsigned int value_; +} + +- (void)getValue:(void *)value { + *(unsigned int*)value = value_; +} + +- (instancetype)initWithUnsignedInt:(unsigned int)value { + self = [super init]; + value_ = value; + return self; +} + ++ (instancetype)numberWithUnsignedInt:(unsigned int)value { + KotlinUInt* result = [[self new] autorelease]; + result->value_ = value; + return result; +} + +// Required to convert Swift integer literals. +- (instancetype)initWithInteger:(NSInteger)value { + self = [super init]; + value_ = value; // TODO: check fits. + return self; +} + +- (unsigned int)unsignedIntValue { + return value_; +} + +- (const char *)objCType { + return "I"; +} + +-(ObjHeader*)toKotlin:(ObjHeader**)OBJ_RESULT { + RETURN_RESULT_OF(Kotlin_boxUInt, value_); +} + +@end; + +@interface KotlinULong : KotlinNumber +@end; + +@implementation KotlinULong { + unsigned long long value_; +} + +- (void)getValue:(void *)value { + *(unsigned long long*)value = value_; +} + +- (instancetype)initWithUnsignedLongLong:(unsigned long long)value { + self = [super init]; + value_ = value; + return self; +} + ++ (instancetype)numberWithUnsignedLongLong:(unsigned long long)value { + KotlinULong* result = [[self new] autorelease]; + result->value_ = value; + return result; +} + +// Required to convert Swift integer literals. +- (instancetype)initWithInteger:(NSInteger)value { + self = [super init]; + value_ = value; // TODO: check fits. + return self; +} + +- (unsigned long long)unsignedLongLongValue { + return value_; +} + +- (const char *)objCType { + return "Q"; +} + +-(ObjHeader*)toKotlin:(ObjHeader**)OBJ_RESULT { + RETURN_RESULT_OF(Kotlin_boxULong, value_); +} + +@end; + +@interface KotlinFloat : KotlinNumber +@end; + +@implementation KotlinFloat { + float value_; +} + +- (void)getValue:(void *)value { + *(float*)value = value_; +} + +- (instancetype)initWithFloat:(float)value { + self = [super init]; + value_ = value; + return self; +} + ++ (instancetype)numberWithFloat:(float)value { + KotlinFloat* result = [[self new] autorelease]; + result->value_ = value; + return result; +} + +// Required to convert Swift integer literals. +- (instancetype)initWithInteger:(NSInteger)value { + self = [super init]; + value_ = value; // TODO: check fits. + return self; +} + +// Required to convert Swift floating literals. +- (instancetype)initWithDouble:(double)value { + self = [super init]; + value_ = value; // TODO: check fits. + return self; +} + +- (float)floatValue { + return value_; +} + +- (const char *)objCType { + return "f"; +} + +-(ObjHeader*)toKotlin:(ObjHeader**)OBJ_RESULT { + RETURN_RESULT_OF(Kotlin_boxFloat, value_); +} + +@end; + +@interface KotlinDouble : KotlinNumber +@end; + +@implementation KotlinDouble { + double value_; +} + +- (void)getValue:(void *)value { + *(double*)value = value_; +} + +- (instancetype)initWithDouble:(double)value { + self = [super init]; + value_ = value; + return self; +} + ++ (instancetype)numberWithDouble:(double)value { + KotlinDouble* result = [[self new] autorelease]; + result->value_ = value; + return result; +} + +// Required to convert Swift integer literals. +- (instancetype)initWithInteger:(NSInteger)value { + self = [super init]; + value_ = value; // TODO: check fits. + return self; +} + +- (double)doubleValue { + return value_; +} + +- (const char *)objCType { + return "d"; +} + +-(ObjHeader*)toKotlin:(ObjHeader**)OBJ_RESULT { + RETURN_RESULT_OF(Kotlin_boxDouble, value_); +} + +@end; + +#endif // KONAN_OBJC_INTEROP diff --git a/kotlin-native/runtime/src/objc/cpp/ObjCInteropUtilsClasses.mm b/kotlin-native/runtime/src/objc/cpp/ObjCInteropUtilsClasses.mm new file mode 100644 index 00000000000..182c730e713 --- /dev/null +++ b/kotlin-native/runtime/src/objc/cpp/ObjCInteropUtilsClasses.mm @@ -0,0 +1,116 @@ +/* + * Copyright 2010-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +#if KONAN_OBJC_INTEROP + +#import +#import +#import "Memory.h" +#import "MemorySharedRefs.hpp" +#import "ObjCInteropUtilsPrivate.h" + +// TODO: rework the interface to reduce the number of virtual calls +// in Kotlin_Interop_createKotlinObjectHolder and Kotlin_Interop_unwrapKotlinObjectHolder +@interface KotlinObjectHolder : NSObject +-(id)initWithRef:(KRef)ref; +-(KRef)ref; +@end; + +@implementation KotlinObjectHolder { + KRefSharedHolder refHolder; +}; + +-(id)initWithRef:(KRef)ref { + if (self = [super init]) { + refHolder.init(ref); + } + return self; +} + +-(KRef)ref { + return refHolder.ref(); +} + +-(void)dealloc { + refHolder.dispose(); + [super dealloc]; +} + +@end; + +static id Kotlin_Interop_createKotlinObjectHolder(KRef any) { + if (any == nullptr) { + return nullptr; + } + + return [[[KotlinObjectHolder alloc] initWithRef:any] autorelease]; +} + +static KRef Kotlin_Interop_unwrapKotlinObjectHolder(id holder) { + if (holder == nullptr) { + return nullptr; + } + + return [((KotlinObjectHolder*)holder) ref]; +} + +// Used as an associated object for ObjCWeakReferenceImpl. +@interface KotlinObjCWeakReference : NSObject +@end; + +// libobjc: +extern "C" { +id objc_loadWeakRetained(id *location); +id objc_storeWeak(id *location, id newObj); +void objc_destroyWeak(id *location); +void objc_release(id obj); +} + +@implementation KotlinObjCWeakReference { + @public id referred; +} + +// Called when removing Kotlin object. +-(void)releaseAsAssociatedObject { + objc_destroyWeak(&referred); + objc_release(self); +} + +@end; + +extern "C" OBJ_GETTER(Kotlin_Interop_refFromObjC, id obj); + +static OBJ_GETTER(Konan_ObjCInterop_getWeakReference, KRef ref) { + KotlinObjCWeakReference* objcRef = (KotlinObjCWeakReference*)ref->GetAssociatedObject(); + + id objcReferred = objc_loadWeakRetained(&objcRef->referred); + KRef result = Kotlin_Interop_refFromObjC(objcReferred, OBJ_RESULT); + objc_release(objcReferred); + + return result; +} + +static void Konan_ObjCInterop_initWeakReference(KRef ref, id objcPtr) { + KotlinObjCWeakReference* objcRef = [KotlinObjCWeakReference new]; + objc_storeWeak(&objcRef->referred, objcPtr); + ref->SetAssociatedObject(objcRef); +} + +__attribute__((constructor)) +static void injectToRuntime() { + RuntimeCheck(Kotlin_Interop_createKotlinObjectHolder_ptr == nullptr, "runtime injected twice"); + Kotlin_Interop_createKotlinObjectHolder_ptr = &Kotlin_Interop_createKotlinObjectHolder; + + RuntimeCheck(Kotlin_Interop_unwrapKotlinObjectHolder_ptr == nullptr, "runtime injected twice"); + Kotlin_Interop_unwrapKotlinObjectHolder_ptr = &Kotlin_Interop_unwrapKotlinObjectHolder; + + RuntimeCheck(Konan_ObjCInterop_getWeakReference_ptr == nullptr, "runtime injected twice"); + Konan_ObjCInterop_getWeakReference_ptr = &Konan_ObjCInterop_getWeakReference; + + RuntimeCheck(Konan_ObjCInterop_initWeakReference_ptr == nullptr, "runtime injected twice"); + Konan_ObjCInterop_initWeakReference_ptr = &Konan_ObjCInterop_initWeakReference; +} + +#endif // KONAN_OBJC_INTEROP diff --git a/kotlin-native/runtime/src/opt_alloc/cpp/AllocImpl.cpp b/kotlin-native/runtime/src/opt_alloc/cpp/AllocImpl.cpp new file mode 100644 index 00000000000..c44d7a52fb7 --- /dev/null +++ b/kotlin-native/runtime/src/opt_alloc/cpp/AllocImpl.cpp @@ -0,0 +1,24 @@ +/* + * Copyright 2010-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ +#include +#include + +extern "C" { +void* mi_calloc(size_t, size_t); +void mi_free(void*); +void* mi_calloc_aligned(size_t count, size_t size, size_t alignment); + +void* konan_calloc_impl(size_t n_elements, size_t elem_size) { + return mi_calloc(n_elements, elem_size); +} + +void* konan_calloc_aligned_impl(size_t count, size_t size, size_t alignment) { + return mi_calloc_aligned(count, size, alignment); +} + +void konan_free_impl (void* mem) { + mi_free(mem); +} +} // extern "C" diff --git a/kotlin-native/runtime/src/profile_runtime/cpp/ProfileRuntime.cpp b/kotlin-native/runtime/src/profile_runtime/cpp/ProfileRuntime.cpp new file mode 100644 index 00000000000..46e9c43b45b --- /dev/null +++ b/kotlin-native/runtime/src/profile_runtime/cpp/ProfileRuntime.cpp @@ -0,0 +1,28 @@ +// Define symbols that are required for code coverage but missing in compiler-RT for MinGW.
 +// See https://reviews.llvm.org/D58106/ for details. +#ifdef KONAN_WINDOWS + +#include + +extern "C" { + +__attribute__((used)) +int lprofGetHostName(char *hostName, int length) { + const int maxHostNameLength = 128; + WCHAR buffer[maxHostNameLength]; + DWORD bufferSize = sizeof(buffer); + COMPUTER_NAME_FORMAT nameType = ComputerNameDnsFullyQualified; + if (!GetComputerNameExW(nameType, buffer, &bufferSize)) { + return -1; + } + int bytesWritten = WideCharToMultiByte(CP_UTF8, 0, buffer, -1, hostName, length, nullptr, nullptr); + if (bytesWritten == 0) { + return -1; + } else { + return 0; + } +} + +} + +#endif diff --git a/kotlin-native/runtime/src/relaxed/cpp/MemoryImpl.cpp b/kotlin-native/runtime/src/relaxed/cpp/MemoryImpl.cpp new file mode 100644 index 00000000000..09993333d4e --- /dev/null +++ b/kotlin-native/runtime/src/relaxed/cpp/MemoryImpl.cpp @@ -0,0 +1,72 @@ +/* + * Copyright 2010-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ +#include "Memory.h" +#include "../../legacymm/cpp/MemoryPrivate.hpp" // Fine, because this module is a part of legacy MM. + +// Note that only C++ part of the runtime goes via those functions, Kotlin uses specialized versions. + +extern "C" { + +const bool IsStrictMemoryModel = false; + +OBJ_GETTER(AllocInstance, const TypeInfo* typeInfo) { + RETURN_RESULT_OF(AllocInstanceRelaxed, typeInfo); +} + +OBJ_GETTER(AllocArrayInstance, const TypeInfo* typeInfo, int32_t elements) { + RETURN_RESULT_OF(AllocArrayInstanceRelaxed, typeInfo, elements); +} + +OBJ_GETTER(InitInstance, + ObjHeader** location, const TypeInfo* typeInfo, void (*ctor)(ObjHeader*)) { + RETURN_RESULT_OF(InitInstanceRelaxed, location, typeInfo, ctor); +} + +OBJ_GETTER(InitSharedInstance, + ObjHeader** location, const TypeInfo* typeInfo, void (*ctor)(ObjHeader*)) { + RETURN_RESULT_OF(InitSharedInstanceRelaxed, location, typeInfo, ctor); +} + +void ReleaseHeapRef(const ObjHeader* object) { + ReleaseHeapRefRelaxed(object); +} + +void ReleaseHeapRefNoCollect(const ObjHeader* object) { + ReleaseHeapRefNoCollectRelaxed(object); +} + +void ZeroStackRef(ObjHeader** location) { + ZeroStackRefRelaxed(location); +} + +void SetStackRef(ObjHeader** location, const ObjHeader* object) { + SetStackRefRelaxed(location, object); +} + +void SetHeapRef(ObjHeader** location, const ObjHeader* object) { + SetHeapRefRelaxed(location, object); +} + +void UpdateHeapRef(ObjHeader** location, const ObjHeader* object) { + UpdateHeapRefRelaxed(location, object); +} + +void UpdateReturnRef(ObjHeader** returnSlot, const ObjHeader* object) { + UpdateReturnRefRelaxed(returnSlot, object); +} + +void EnterFrame(ObjHeader** start, int parameters, int count) { + EnterFrameRelaxed(start, parameters, count); +} + +void LeaveFrame(ObjHeader** start, int parameters, int count) { + LeaveFrameRelaxed(start, parameters, count); +} + +void UpdateStackRef(ObjHeader** location, const ObjHeader* object) { + UpdateStackRefRelaxed(location, object); +} + +} // extern "C" diff --git a/kotlin-native/runtime/src/release/cpp/SourceInfo.cpp b/kotlin-native/runtime/src/release/cpp/SourceInfo.cpp new file mode 100644 index 00000000000..653cea5050f --- /dev/null +++ b/kotlin-native/runtime/src/release/cpp/SourceInfo.cpp @@ -0,0 +1,21 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "SourceInfo.h" + +struct SourceInfo Kotlin_getSourceInfo(void* addr) { + return (SourceInfo) { .fileName = nullptr, .lineNumber = -1, .column = -1 }; +} \ No newline at end of file diff --git a/kotlin-native/runtime/src/std_alloc/cpp/AllocImpl.cpp b/kotlin-native/runtime/src/std_alloc/cpp/AllocImpl.cpp new file mode 100644 index 00000000000..c3a165e44d6 --- /dev/null +++ b/kotlin-native/runtime/src/std_alloc/cpp/AllocImpl.cpp @@ -0,0 +1,23 @@ +/* + * Copyright 2010-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ +#include +#include + +extern "C" { +// Memory operations. +void* konan_calloc_impl(size_t n_elements, size_t elem_size) { + return calloc(n_elements, elem_size); +} + +void* konan_calloc_aligned_impl(size_t count, size_t size, size_t alignment) { + // alignment is not supported by std alloc - use mimalloc + return calloc(count, size); +} + +void konan_free_impl (void* mem) { + free(mem); +} +} + diff --git a/kotlin-native/runtime/src/strict/cpp/MemoryImpl.cpp b/kotlin-native/runtime/src/strict/cpp/MemoryImpl.cpp new file mode 100644 index 00000000000..ce7af356dc1 --- /dev/null +++ b/kotlin-native/runtime/src/strict/cpp/MemoryImpl.cpp @@ -0,0 +1,72 @@ +/* + * Copyright 2010-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ +#include "Memory.h" +#include "../../legacymm/cpp/MemoryPrivate.hpp" // Fine, because this module is a part of legacy MM. + +// Note that only C++ part of the runtime goes via those functions, Kotlin uses specialized versions. + +extern "C" { + +const bool IsStrictMemoryModel = true; + +OBJ_GETTER(AllocInstance, const TypeInfo* typeInfo) { + RETURN_RESULT_OF(AllocInstanceStrict, typeInfo); +} + +OBJ_GETTER(AllocArrayInstance, const TypeInfo* typeInfo, int32_t elements) { + RETURN_RESULT_OF(AllocArrayInstanceStrict, typeInfo, elements); +} + +OBJ_GETTER(InitInstance, + ObjHeader** location, const TypeInfo* typeInfo, void (*ctor)(ObjHeader*)) { + RETURN_RESULT_OF(InitInstanceStrict, location, typeInfo, ctor); +} + +OBJ_GETTER(InitSharedInstance, + ObjHeader** location, const TypeInfo* typeInfo, void (*ctor)(ObjHeader*)) { + RETURN_RESULT_OF(InitSharedInstanceStrict, location, typeInfo, ctor); +} + +void ReleaseHeapRef(const ObjHeader* object) { + ReleaseHeapRefStrict(object); +} + +void ReleaseHeapRefNoCollect(const ObjHeader* object) { + ReleaseHeapRefNoCollectStrict(object); +} + +void SetStackRef(ObjHeader** location, const ObjHeader* object) { + SetStackRefStrict(location, object); +} + +void SetHeapRef(ObjHeader** location, const ObjHeader* object) { + SetHeapRefStrict(location, object); +} + +void ZeroStackRef(ObjHeader** location) { + ZeroStackRefStrict(location); +} + +void UpdateHeapRef(ObjHeader** location, const ObjHeader* object) { + UpdateHeapRefStrict(location, object); +} + +void UpdateReturnRef(ObjHeader** returnSlot, const ObjHeader* object) { + UpdateReturnRefStrict(returnSlot, object); +} + +void EnterFrame(ObjHeader** start, int parameters, int count) { + EnterFrameStrict(start, parameters, count); +} + +void LeaveFrame(ObjHeader** start, int parameters, int count) { + LeaveFrameStrict(start, parameters, count); +} + +void UpdateStackRef(ObjHeader** location, const ObjHeader* object) { + UpdateStackRefStrict(location, object); +} + +} // extern "C" diff --git a/kotlin-native/runtime/src/test_support/cpp/CompilerGenerated.cpp b/kotlin-native/runtime/src/test_support/cpp/CompilerGenerated.cpp new file mode 100644 index 00000000000..16d087cf208 --- /dev/null +++ b/kotlin-native/runtime/src/test_support/cpp/CompilerGenerated.cpp @@ -0,0 +1,260 @@ +/* + * Copyright 2010-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +#include "TestSupportCompilerGenerated.hpp" + +#include "Types.h" + +namespace { + +TypeInfo theAnyTypeInfoImpl = {}; +TypeInfo theArrayTypeInfoImpl = {}; +TypeInfo theBooleanArrayTypeInfoImpl = {}; +TypeInfo theByteArrayTypeInfoImpl = {}; +TypeInfo theCharArrayTypeInfoImpl = {}; +TypeInfo theDoubleArrayTypeInfoImpl = {}; +TypeInfo theFloatArrayTypeInfoImpl = {}; +TypeInfo theForeignObjCObjectTypeInfoImpl = {}; +TypeInfo theFreezableAtomicReferenceTypeInfoImpl = {}; +TypeInfo theIntArrayTypeInfoImpl = {}; +TypeInfo theLongArrayTypeInfoImpl = {}; +TypeInfo theNativePtrArrayTypeInfoImpl = {}; +TypeInfo theObjCObjectWrapperTypeInfoImpl = {}; +TypeInfo theOpaqueFunctionTypeInfoImpl = {}; +TypeInfo theShortArrayTypeInfoImpl = {}; +TypeInfo theStringTypeInfoImpl = {}; +TypeInfo theThrowableTypeInfoImpl = {}; +TypeInfo theUnitTypeInfoImpl = {}; +TypeInfo theWorkerBoundReferenceTypeInfoImpl = {}; +TypeInfo theCleanerImplTypeInfoImpl = {}; + +ArrayHeader theEmptyStringImpl = { &theStringTypeInfoImpl, /* element count */ 0 }; + +template +struct KBox { + ObjHeader header; + const T value; +}; + +testing::StrictMock>* createCleanerWorkerMock = nullptr; +testing::StrictMock>* shutdownCleanerWorkerMock = nullptr; + +} // namespace + +extern "C" { + +// Set to 1 to enable runtime assertions. +extern const int KonanNeedDebugInfo = 1; + +extern const TypeInfo* theAnyTypeInfo = &theAnyTypeInfoImpl; +extern const TypeInfo* theArrayTypeInfo = &theArrayTypeInfoImpl; +extern const TypeInfo* theBooleanArrayTypeInfo = &theBooleanArrayTypeInfoImpl; +extern const TypeInfo* theByteArrayTypeInfo = &theByteArrayTypeInfoImpl; +extern const TypeInfo* theCharArrayTypeInfo = &theCharArrayTypeInfoImpl; +extern const TypeInfo* theDoubleArrayTypeInfo = &theDoubleArrayTypeInfoImpl; +extern const TypeInfo* theFloatArrayTypeInfo = &theFloatArrayTypeInfoImpl; +extern const TypeInfo* theForeignObjCObjectTypeInfo = &theForeignObjCObjectTypeInfoImpl; +extern const TypeInfo* theFreezableAtomicReferenceTypeInfo = &theFreezableAtomicReferenceTypeInfoImpl; +extern const TypeInfo* theIntArrayTypeInfo = &theIntArrayTypeInfoImpl; +extern const TypeInfo* theLongArrayTypeInfo = &theLongArrayTypeInfoImpl; +extern const TypeInfo* theNativePtrArrayTypeInfo = &theNativePtrArrayTypeInfoImpl; +extern const TypeInfo* theObjCObjectWrapperTypeInfo = &theObjCObjectWrapperTypeInfoImpl; +extern const TypeInfo* theOpaqueFunctionTypeInfo = &theOpaqueFunctionTypeInfoImpl; +extern const TypeInfo* theShortArrayTypeInfo = &theShortArrayTypeInfoImpl; +extern const TypeInfo* theStringTypeInfo = &theStringTypeInfoImpl; +extern const TypeInfo* theThrowableTypeInfo = &theThrowableTypeInfoImpl; +extern const TypeInfo* theUnitTypeInfo = &theUnitTypeInfoImpl; +extern const TypeInfo* theWorkerBoundReferenceTypeInfo = &theWorkerBoundReferenceTypeInfoImpl; +extern const TypeInfo* theCleanerImplTypeInfo = &theCleanerImplTypeInfoImpl; + +extern const ArrayHeader theEmptyArray = { &theArrayTypeInfoImpl, /* element count */0 }; + +OBJ_GETTER0(TheEmptyString) { + RETURN_OBJ(theEmptyStringImpl.obj()); +} + +RUNTIME_NORETURN OBJ_GETTER(makeWeakReferenceCounter, void*) { + throw std::runtime_error("Not implemented for tests"); +} + +RUNTIME_NORETURN OBJ_GETTER(makePermanentWeakReferenceImpl, void*) { + throw std::runtime_error("Not implemented for tests"); +} + +RUNTIME_NORETURN OBJ_GETTER(makeObjCWeakReferenceImpl, void*) { + throw std::runtime_error("Not implemented for tests"); +} + +void checkRangeIndexes(KInt from, KInt to, KInt size) { + if (from < 0 || to > size) { + throw std::out_of_range("Index out of bounds: from=" + std::to_string(from) + + ", to=" + std::to_string(to) + + ", size=" + std::to_string(size)); + } + if (from > to) { + throw std::invalid_argument("Illegal argument: from > to, from=" + std::to_string(from) + ", to=" + std::to_string(to)); + } +} + +RUNTIME_NORETURN OBJ_GETTER(WorkerLaunchpad, KRef) { + throw std::runtime_error("Not implemented for tests"); +} + +void RUNTIME_NORETURN ThrowWorkerInvalidState() { + throw std::runtime_error("Not implemented for tests"); +} + +void RUNTIME_NORETURN ThrowNullPointerException() { + throw std::runtime_error("Not implemented for tests"); +} + +void RUNTIME_NORETURN ThrowArrayIndexOutOfBoundsException() { + throw std::runtime_error("Not implemented for tests"); +} + +void RUNTIME_NORETURN ThrowClassCastException(const ObjHeader* instance, const TypeInfo* type_info) { + throw std::runtime_error("Not implemented for tests"); +} + +void RUNTIME_NORETURN ThrowArithmeticException() { + throw std::runtime_error("Not implemented for tests"); +} + +void RUNTIME_NORETURN ThrowNumberFormatException() { + throw std::runtime_error("Not implemented for tests"); +} + +void RUNTIME_NORETURN ThrowOutOfMemoryError() { + throw std::runtime_error("Not implemented for tests"); +} + +void RUNTIME_NORETURN ThrowNotImplementedError() { + throw std::runtime_error("Not implemented for tests"); +} + +void RUNTIME_NORETURN ThrowCharacterCodingException() { + throw std::runtime_error("Not implemented for tests"); +} + +void RUNTIME_NORETURN ThrowIllegalArgumentException() { + throw std::runtime_error("Not implemented for tests"); +} + +void RUNTIME_NORETURN ThrowIllegalStateException() { + throw std::runtime_error("Not implemented for tests"); +} + +void RUNTIME_NORETURN ThrowInvalidMutabilityException(KConstRef where) { + throw std::runtime_error("Not implemented for tests"); +} + +void RUNTIME_NORETURN ThrowIncorrectDereferenceException() { + throw std::runtime_error("Not implemented for tests"); +} + +void RUNTIME_NORETURN ThrowIllegalObjectSharingException(KConstNativePtr typeInfo, KConstNativePtr address) { + throw std::runtime_error("Not implemented for tests"); +} + +void RUNTIME_NORETURN ThrowFreezingException(KRef toFreeze, KRef blocker) { + throw std::runtime_error("Not implemented for tests"); +} + +void ReportUnhandledException(KRef throwable) { + konan::consolePrintf("Uncaught Kotlin exception."); +} + +RUNTIME_NORETURN OBJ_GETTER(DescribeObjectForDebugging, KConstNativePtr typeInfo, KConstNativePtr address) { + throw std::runtime_error("Not implemented for tests"); +} + +void ExceptionReporterLaunchpad(KRef reporter, KRef throwable) { + throw std::runtime_error("Not implemented for tests"); +} + +void Kotlin_WorkerBoundReference_freezeHook(KRef thiz) { + throw std::runtime_error("Not implemented for tests"); +} + +extern const KBoolean BOOLEAN_RANGE_FROM = false; +extern const KBoolean BOOLEAN_RANGE_TO = true; +extern KBox BOOLEAN_CACHE[] = { + {{}, false}, + {{}, true}, +}; + +OBJ_GETTER(Kotlin_boxBoolean, KBoolean value) { + if (value) { + RETURN_OBJ(&BOOLEAN_CACHE[1].header); + } else { + RETURN_OBJ(&BOOLEAN_CACHE[0].header); + } +} + +extern const KByte BYTE_RANGE_FROM = -1; +extern const KByte BYTE_RANGE_TO = 1; +extern KBox BYTE_CACHE[] = { + {{}, -1}, + {{}, 0}, + {{}, 1}, +}; + +extern const KChar CHAR_RANGE_FROM = 0; +extern const KChar CHAR_RANGE_TO = 2; +extern KBox CHAR_CACHE[] = { + {{}, 0}, + {{}, 1}, + {{}, 2}, +}; + +extern const KShort SHORT_RANGE_FROM = -1; +extern const KShort SHORT_RANGE_TO = 1; +extern KBox SHORT_CACHE[] = { + {{}, -1}, + {{}, 0}, + {{}, 1}, +}; + +extern const KInt INT_RANGE_FROM = -1; +extern const KInt INT_RANGE_TO = 1; +extern KBox INT_CACHE[] = { + {{}, -1}, + {{}, 0}, + {{}, 1}, +}; + +extern const KLong LONG_RANGE_FROM = -1; +extern const KLong LONG_RANGE_TO = 1; +extern KBox LONG_CACHE[] = { + {{}, -1}, + {{}, 0}, + {{}, 1}, +}; + +RUNTIME_NORETURN OBJ_GETTER(Kotlin_Throwable_getMessage, KRef throwable) { + throw std::runtime_error("Not implemented for tests"); +} + +void Kotlin_CleanerImpl_shutdownCleanerWorker(KInt worker, bool executeScheduledCleaners) { + if (!shutdownCleanerWorkerMock) throw std::runtime_error("Not implemented for tests"); + + return shutdownCleanerWorkerMock->Call(worker, executeScheduledCleaners); +} + +KInt Kotlin_CleanerImpl_createCleanerWorker() { + if (!createCleanerWorkerMock) throw std::runtime_error("Not implemented for tests"); + + return createCleanerWorkerMock->Call(); +} + +} // extern "C" + +ScopedStrictMockFunction ScopedCreateCleanerWorkerMock() { + return ScopedStrictMockFunction(&createCleanerWorkerMock); +} + +ScopedStrictMockFunction ScopedShutdownCleanerWorkerMock() { + return ScopedStrictMockFunction(&shutdownCleanerWorkerMock); +} diff --git a/kotlin-native/runtime/src/test_support/cpp/CompilerGeneratedObjC.mm b/kotlin-native/runtime/src/test_support/cpp/CompilerGeneratedObjC.mm new file mode 100644 index 00000000000..6400daf30d7 --- /dev/null +++ b/kotlin-native/runtime/src/test_support/cpp/CompilerGeneratedObjC.mm @@ -0,0 +1,72 @@ +/* + * Copyright 2010-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +#if KONAN_OBJC_INTEROP + +#include "TestSupportCompilerGenerated.hpp" + +#include +#include + +#include "Types.h" + +extern "C" { + +Class Kotlin_Interop_getObjCClass(const char* name) { + Class result = objc_lookUpClass(name); + if (result == nil) { + // GTest can display error messages of C++ exceptions so we use them instead of ObjC ones. + throw std::invalid_argument("Incorrect class name"); + } + return result; +} + +RUNTIME_NORETURN OBJ_GETTER0(Kotlin_NSEnumeratorAsKIterator_create) { + throw std::runtime_error("Not implemented for tests"); +} + +void Kotlin_NSEnumeratorAsKIterator_done(KRef thiz) { + throw std::runtime_error("Not implemented for tests"); +} + +void Kotlin_NSEnumeratorAsKIterator_setNext(KRef thiz, KRef value) { + throw std::runtime_error("Not implemented for tests"); +} + +RUNTIME_NORETURN OBJ_GETTER(Kotlin_ObjCExport_NSErrorAsExceptionImpl, KRef message, KRef error) { + throw std::runtime_error("Not implemented for tests"); +} + +void Kotlin_ObjCExport_ThrowCollectionConcurrentModification() { + throw std::runtime_error("Not implemented for tests"); +} + +void Kotlin_ObjCExport_ThrowCollectionTooLarge() { + throw std::runtime_error("Not implemented for tests"); +} + +typedef OBJ_GETTER((*convertReferenceFromObjC), id obj); +extern convertReferenceFromObjC Kotlin_ObjCExport_blockToFunctionConverters[] = {}; +extern int Kotlin_ObjCExport_blockToFunctionConverters_size = 0; + +RUNTIME_NORETURN OBJ_GETTER(Kotlin_ObjCExport_createContinuationArgumentImpl, KRef completionHolder, const TypeInfo** exceptionTypes) { + throw std::runtime_error("Not implemented for tests"); +} + +RUNTIME_NORETURN OBJ_GETTER(Kotlin_ObjCExport_getWrappedError, KRef throwable) { + throw std::runtime_error("Not implemented for tests"); +} + +void Kotlin_ObjCExport_resumeContinuationFailure(KRef continuation, KRef exception) { + throw std::runtime_error("Not implemented for tests"); +} + +void Kotlin_ObjCExport_resumeContinuationSuccess(KRef continuation, KRef result) { + throw std::runtime_error("Not implemented for tests"); +} + +} // extern "C" + +#endif // KONAN_OBJC_INTEROP diff --git a/kotlin-native/runtime/src/test_support/cpp/TestLauncher.cpp b/kotlin-native/runtime/src/test_support/cpp/TestLauncher.cpp new file mode 100644 index 00000000000..fa2c38e9536 --- /dev/null +++ b/kotlin-native/runtime/src/test_support/cpp/TestLauncher.cpp @@ -0,0 +1,12 @@ +/* + * Copyright 2010-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +#include "gmock/gmock.h" +#include "gtest/gtest.h" + +int main(int argc, char** argv) { + testing::InitGoogleMock(&argc, argv); + return RUN_ALL_TESTS(); +} diff --git a/kotlin-native/samples/README.md b/kotlin-native/samples/README.md new file mode 100644 index 00000000000..9e2a53a1da4 --- /dev/null +++ b/kotlin-native/samples/README.md @@ -0,0 +1,38 @@ +# Samples + +This directory contains a set of samples demonstrating how one can work with Kotlin/Native. The samples can be +built using Gradle build tool. See `README.md` in sample directories to learn more about specific samples and +the building process. + + * `androidNativeActivity` - Android Native Activity rendering 3D graphics using OpenGLES + * `calculator` - iOS Swift application, using Kotlin/Native code compiled into the framework + * `cocoapods` - A Kotlin/Native application using the `AFNetworking` library from CocoaPods. + * `csvparser` - simple CSV file parser and analyzer + * `echoServer` - TCP/IP echo server + * `gitchurn` - program interoperating with `libgit2` for GIT repository analysis + * `gtk` - GTK3 interoperability example + * `html5Canvas` - WebAssembly example + * `libcurl` - using of FTP/HTTP/HTTPS client library `libcurl` + * `nonBlockingEchoServer` - multi-client TCP/IP echo server using co-routines + * `objc` - AppKit Objective-C interoperability example for macOS + * `opengl` - OpenGL/GLUT teapot example + * `python_extension` - Python extension written in Kotlin/Native + * `tensorflow` - simple client for TensorFlow Machine Intelligence library + * `tetris` - Tetris game implementation (using SDL2 for rendering) + * `uikit` - UIKit Objective-C interoperability example for iOS + * `videoplayer` - SDL and FFMPEG-based video and audio player + * `win32` - trivial Win32 GUI application + * `workers` - example of using workers API + + +**Note**: If the samples are built from a source tree (not from a distribution archive) the compiler built from +the sources is used. So you must build the compiler and the necessary platform libraries by running +`./gradlew bundle` from the Kotlin/Native root directory before building samples (see +[README.md](https://github.com/JetBrains/kotlin-native/blob/master/README.md) for details). + +Alternatively you may remove a line `kotlin.native.home=<...>` from all `gradle.properties` files. +In this case the Gradle plugin downloads and uses a default compiler for this plugin version. + +One may also build all the samples with one command. To build them using Gradle run: + + ./gradlew buildAllSamples diff --git a/kotlin-native/samples/androidNativeActivity/README.md b/kotlin-native/samples/androidNativeActivity/README.md new file mode 100644 index 00000000000..8ac2551781c --- /dev/null +++ b/kotlin-native/samples/androidNativeActivity/README.md @@ -0,0 +1,22 @@ +# Android Native Activity + +This example shows how to build an Android Native Activity. Also, we provide an example +bridging mechanism for the Java APIs, callable from Native side. + +The example will render a textured dodecahedron using OpenGL ES library. It can be rotated with fingers. +Please make sure that Android SDK version 28 is installed, using Android SDK manager in Android Studio. +See https://developer.android.com/studio/index.html for more details on Android Studio or +`$ANDROID_HOME/tools/bin/sdkmanager "platforms;android-28" "build-tools;28.0.3"` from command line. +We use JniBridge to call vibration service on the Java side for short tremble on startup. + +To build use `ANDROID_HOME= ../gradlew assemble`. + +Run `$ANDROID_HOME/platform-tools/adb install -r build/outputs/apk/debug/androidNativeActivity-debug.apk` +to deploy the apk on the Android device or emulator. + +Note that "Emulated Performance - Graphics" in AVD manager must be set to "Software - GLES 2.0". + +Note: If you are importing project to IDEA for the first time, you might need to put `local.properties` file +with the following content: + + sdk.dir= diff --git a/kotlin-native/samples/androidNativeActivity/build.gradle.kts b/kotlin-native/samples/androidNativeActivity/build.gradle.kts new file mode 100644 index 00000000000..0c86de85e9a --- /dev/null +++ b/kotlin-native/samples/androidNativeActivity/build.gradle.kts @@ -0,0 +1,108 @@ +import org.jetbrains.kotlin.gradle.plugin.mpp.KotlinNativeTarget +import org.jetbrains.kotlin.gradle.plugin.mpp.KotlinNativeTargetPreset +import org.jetbrains.kotlin.gradle.plugin.mpp.NativeBuildType + +repositories { + google() + jcenter() + mavenCentral() + maven("https://dl.bintray.com/kotlin/kotlin-dev") + maven("https://dl.bintray.com/kotlin/kotlin-eap") +} + +plugins { + kotlin("multiplatform") + id("com.android.application") version("3.6.0") +} + +val appDir = buildDir.resolve("Polyhedron") +val libsDir = appDir.resolve("libs") +// Set to true to build only for the simulator. +val simulatorOnly = true + +val androidPresets = mapOf( + "arm32" to ("androidNativeArm32" to "$libsDir/armeabi-v7a"), + "arm64" to ("androidNativeArm64" to "$libsDir/arm64-v8a"), + "x86" to ("androidNativeX86" to "$libsDir/x86"), + "x64" to ("androidNativeX64" to "$libsDir/x86_64") +) + +android { + compileSdkVersion(28) + + defaultConfig { + applicationId = "com.jetbrains.konan_activity2" + minSdkVersion(9) + targetSdkVersion(28) + + ndk { + abiFilters("armeabi-v7a", "arm64-v8a", "x86", "x86_64") + } + } + + sourceSets { + val main by getting { + setRoot("src/x86Main") + jniLibs.srcDir(libsDir) + } + } +} + +kotlin { + androidPresets.forEach { (targetName, presetInfo) -> + val (presetName, _) = presetInfo + val preset = kotlin.presets[presetName] as KotlinNativeTargetPreset + targetFromPreset(preset, targetName) { + binaries { + executable { + entryPoint = "sample.androidnative.main" + } + } + compilations["main"].cinterops { + val bmpformat by creating + } + } + } + + sourceSets { + val x86Main by getting + if (!simulatorOnly) { + val x64Main by getting + val arm32Main by getting + val arm64Main by getting + arm32Main.dependsOn(x86Main) + arm64Main.dependsOn(x86Main) + x64Main.dependsOn(x86Main) + } + } +} + +// Disable generating Kotlin metadata. +tasks.compileKotlinMetadata { + enabled = false +} + +afterEvaluate { + androidPresets.forEach { (targetName, presetInfo) -> + val target = kotlin.targets[targetName] as KotlinNativeTarget + val (_, libDir) = presetInfo + + NativeBuildType.values().forEach { + val executable = target.binaries.getExecutable(it) + val linkTask = executable.linkTask + val binaryFile = executable.outputFile + + linkTask.doLast { + copy { + from(binaryFile) + into(libDir) + rename { "libpoly.so" } + } + } + + tasks.preBuild { + dependsOn(linkTask) + } + } + } +} diff --git a/kotlin-native/samples/androidNativeActivity/build.sh b/kotlin-native/samples/androidNativeActivity/build.sh new file mode 100755 index 00000000000..a26f890f026 --- /dev/null +++ b/kotlin-native/samples/androidNativeActivity/build.sh @@ -0,0 +1,5 @@ +#!/usr/bin/env bash + +DIR=$(cd "$(dirname "${BASH_SOURCE[0]}" )" && pwd ) + +$DIR/../gradlew -p $DIR assemble diff --git a/kotlin-native/samples/androidNativeActivity/gradle.properties b/kotlin-native/samples/androidNativeActivity/gradle.properties new file mode 100644 index 00000000000..876108389f6 --- /dev/null +++ b/kotlin-native/samples/androidNativeActivity/gradle.properties @@ -0,0 +1,15 @@ +kotlin.code.style=official + +# Run parallel builds in Gradle: +org.gradle.parallel=true +org.gradle.workers.max=4 + +# Pin Kotlin version: +# CHANGE_VERSION_WITH_RELEASE +kotlin_version=1.4.10 + +# Use custom Kotlin/Native home: +kotlin.native.home=../../dist + +# Increase memory for in-process compiler execution. +org.gradle.jvmargs=-Xmx3g diff --git a/kotlin-native/samples/androidNativeActivity/gradle/wrapper/gradle-wrapper.jar b/kotlin-native/samples/androidNativeActivity/gradle/wrapper/gradle-wrapper.jar new file mode 100644 index 00000000000..e708b1c023e Binary files /dev/null and b/kotlin-native/samples/androidNativeActivity/gradle/wrapper/gradle-wrapper.jar differ diff --git a/kotlin-native/samples/androidNativeActivity/gradle/wrapper/gradle-wrapper.properties b/kotlin-native/samples/androidNativeActivity/gradle/wrapper/gradle-wrapper.properties new file mode 100644 index 00000000000..12d38de6a48 --- /dev/null +++ b/kotlin-native/samples/androidNativeActivity/gradle/wrapper/gradle-wrapper.properties @@ -0,0 +1,5 @@ +distributionBase=GRADLE_USER_HOME +distributionPath=wrapper/dists +distributionUrl=https\://services.gradle.org/distributions/gradle-6.6.1-bin.zip +zipStoreBase=GRADLE_USER_HOME +zipStorePath=wrapper/dists diff --git a/kotlin-native/samples/androidNativeActivity/gradlew b/kotlin-native/samples/androidNativeActivity/gradlew new file mode 100755 index 00000000000..4f906e0c811 --- /dev/null +++ b/kotlin-native/samples/androidNativeActivity/gradlew @@ -0,0 +1,185 @@ +#!/usr/bin/env sh + +# +# Copyright 2015 the original author or authors. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# https://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +############################################################################## +## +## Gradle start up script for UN*X +## +############################################################################## + +# Attempt to set APP_HOME +# Resolve links: $0 may be a link +PRG="$0" +# Need this for relative symlinks. +while [ -h "$PRG" ] ; do + ls=`ls -ld "$PRG"` + link=`expr "$ls" : '.*-> \(.*\)$'` + if expr "$link" : '/.*' > /dev/null; then + PRG="$link" + else + PRG=`dirname "$PRG"`"/$link" + fi +done +SAVED="`pwd`" +cd "`dirname \"$PRG\"`/" >/dev/null +APP_HOME="`pwd -P`" +cd "$SAVED" >/dev/null + +APP_NAME="Gradle" +APP_BASE_NAME=`basename "$0"` + +# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"' + +# Use the maximum available, or set MAX_FD != -1 to use that value. +MAX_FD="maximum" + +warn () { + echo "$*" +} + +die () { + echo + echo "$*" + echo + exit 1 +} + +# OS specific support (must be 'true' or 'false'). +cygwin=false +msys=false +darwin=false +nonstop=false +case "`uname`" in + CYGWIN* ) + cygwin=true + ;; + Darwin* ) + darwin=true + ;; + MINGW* ) + msys=true + ;; + NONSTOP* ) + nonstop=true + ;; +esac + +CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar + + +# Determine the Java command to use to start the JVM. +if [ -n "$JAVA_HOME" ] ; then + if [ -x "$JAVA_HOME/jre/sh/java" ] ; then + # IBM's JDK on AIX uses strange locations for the executables + JAVACMD="$JAVA_HOME/jre/sh/java" + else + JAVACMD="$JAVA_HOME/bin/java" + fi + if [ ! -x "$JAVACMD" ] ; then + die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME + +Please set the JAVA_HOME variable in your environment to match the +location of your Java installation." + fi +else + JAVACMD="java" + which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. + +Please set the JAVA_HOME variable in your environment to match the +location of your Java installation." +fi + +# Increase the maximum file descriptors if we can. +if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then + MAX_FD_LIMIT=`ulimit -H -n` + if [ $? -eq 0 ] ; then + if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then + MAX_FD="$MAX_FD_LIMIT" + fi + ulimit -n $MAX_FD + if [ $? -ne 0 ] ; then + warn "Could not set maximum file descriptor limit: $MAX_FD" + fi + else + warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT" + fi +fi + +# For Darwin, add options to specify how the application appears in the dock +if $darwin; then + GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\"" +fi + +# For Cygwin or MSYS, switch paths to Windows format before running java +if [ "$cygwin" = "true" -o "$msys" = "true" ] ; then + APP_HOME=`cygpath --path --mixed "$APP_HOME"` + CLASSPATH=`cygpath --path --mixed "$CLASSPATH"` + + JAVACMD=`cygpath --unix "$JAVACMD"` + + # We build the pattern for arguments to be converted via cygpath + ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null` + SEP="" + for dir in $ROOTDIRSRAW ; do + ROOTDIRS="$ROOTDIRS$SEP$dir" + SEP="|" + done + OURCYGPATTERN="(^($ROOTDIRS))" + # Add a user-defined pattern to the cygpath arguments + if [ "$GRADLE_CYGPATTERN" != "" ] ; then + OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)" + fi + # Now convert the arguments - kludge to limit ourselves to /bin/sh + i=0 + for arg in "$@" ; do + CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -` + CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option + + if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition + eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"` + else + eval `echo args$i`="\"$arg\"" + fi + i=`expr $i + 1` + done + case $i in + 0) set -- ;; + 1) set -- "$args0" ;; + 2) set -- "$args0" "$args1" ;; + 3) set -- "$args0" "$args1" "$args2" ;; + 4) set -- "$args0" "$args1" "$args2" "$args3" ;; + 5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;; + 6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;; + 7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;; + 8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;; + 9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;; + esac +fi + +# Escape application args +save () { + for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done + echo " " +} +APP_ARGS=`save "$@"` + +# Collect all arguments for the java command, following the shell quoting and substitution rules +eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS" + +exec "$JAVACMD" "$@" diff --git a/kotlin-native/samples/androidNativeActivity/gradlew.bat b/kotlin-native/samples/androidNativeActivity/gradlew.bat new file mode 100644 index 00000000000..ac1b06f9382 --- /dev/null +++ b/kotlin-native/samples/androidNativeActivity/gradlew.bat @@ -0,0 +1,89 @@ +@rem +@rem Copyright 2015 the original author or authors. +@rem +@rem Licensed under the Apache License, Version 2.0 (the "License"); +@rem you may not use this file except in compliance with the License. +@rem You may obtain a copy of the License at +@rem +@rem https://www.apache.org/licenses/LICENSE-2.0 +@rem +@rem Unless required by applicable law or agreed to in writing, software +@rem distributed under the License is distributed on an "AS IS" BASIS, +@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +@rem See the License for the specific language governing permissions and +@rem limitations under the License. +@rem + +@if "%DEBUG%" == "" @echo off +@rem ########################################################################## +@rem +@rem Gradle startup script for Windows +@rem +@rem ########################################################################## + +@rem Set local scope for the variables with windows NT shell +if "%OS%"=="Windows_NT" setlocal + +set DIRNAME=%~dp0 +if "%DIRNAME%" == "" set DIRNAME=. +set APP_BASE_NAME=%~n0 +set APP_HOME=%DIRNAME% + +@rem Resolve any "." and ".." in APP_HOME to make it shorter. +for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi + +@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m" + +@rem Find java.exe +if defined JAVA_HOME goto findJavaFromJavaHome + +set JAVA_EXE=java.exe +%JAVA_EXE% -version >NUL 2>&1 +if "%ERRORLEVEL%" == "0" goto execute + +echo. +echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. +echo. +echo Please set the JAVA_HOME variable in your environment to match the +echo location of your Java installation. + +goto fail + +:findJavaFromJavaHome +set JAVA_HOME=%JAVA_HOME:"=% +set JAVA_EXE=%JAVA_HOME%/bin/java.exe + +if exist "%JAVA_EXE%" goto execute + +echo. +echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% +echo. +echo Please set the JAVA_HOME variable in your environment to match the +echo location of your Java installation. + +goto fail + +:execute +@rem Setup the command line + +set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar + + +@rem Execute Gradle +"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %* + +:end +@rem End local scope for the variables with windows NT shell +if "%ERRORLEVEL%"=="0" goto mainEnd + +:fail +rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of +rem the _cmd.exe /c_ return code! +if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 +exit /b 1 + +:mainEnd +if "%OS%"=="Windows_NT" endlocal + +:omega diff --git a/kotlin-native/samples/androidNativeActivity/settings.gradle.kts b/kotlin-native/samples/androidNativeActivity/settings.gradle.kts new file mode 100644 index 00000000000..1e84ed7b3ec --- /dev/null +++ b/kotlin-native/samples/androidNativeActivity/settings.gradle.kts @@ -0,0 +1,22 @@ +pluginManagement { + val kotlin_version: String by settings + resolutionStrategy { + eachPlugin { + if (requested.id.id == "org.jetbrains.kotlin.multiplatform") { + useModule("org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version") + } + if (requested.id.id == "com.android.application") { + useModule("com.android.tools.build:gradle:${requested.version}") + } + } + } + + repositories { + gradlePluginPortal() + google() + jcenter() + mavenCentral() + maven("https://dl.bintray.com/kotlin/kotlin-dev") + maven("https://dl.bintray.com/kotlin/kotlin-eap") + } +} diff --git a/kotlin-native/samples/androidNativeActivity/src/nativeInterop/cinterop/bmpformat.def b/kotlin-native/samples/androidNativeActivity/src/nativeInterop/cinterop/bmpformat.def new file mode 100644 index 00000000000..2d661b1bcf4 --- /dev/null +++ b/kotlin-native/samples/androidNativeActivity/src/nativeInterop/cinterop/bmpformat.def @@ -0,0 +1,16 @@ +package = sample.androidnative.bmpformat + +--- +#include + +typedef struct __attribute__((packed)) { + uint16_t magic; + uint32_t size; + uint32_t zero; + uint8_t padding1[8]; + int32_t width; + int32_t height; + uint8_t padding2[2]; + uint16_t bits; + uint8_t padding3[24]; +} BMPHeader; diff --git a/kotlin-native/samples/androidNativeActivity/src/x86Main/AndroidManifest.xml b/kotlin-native/samples/androidNativeActivity/src/x86Main/AndroidManifest.xml new file mode 100644 index 00000000000..2b7d60ee29b --- /dev/null +++ b/kotlin-native/samples/androidNativeActivity/src/x86Main/AndroidManifest.xml @@ -0,0 +1,38 @@ + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/kotlin-native/samples/androidNativeActivity/src/x86Main/assets/kotlin_logo.bmp b/kotlin-native/samples/androidNativeActivity/src/x86Main/assets/kotlin_logo.bmp new file mode 100644 index 00000000000..3311764c70d Binary files /dev/null and b/kotlin-native/samples/androidNativeActivity/src/x86Main/assets/kotlin_logo.bmp differ diff --git a/kotlin-native/samples/androidNativeActivity/src/x86Main/kotlin/BMPHeader.kt b/kotlin-native/samples/androidNativeActivity/src/x86Main/kotlin/BMPHeader.kt new file mode 100644 index 00000000000..34ae36f3e24 --- /dev/null +++ b/kotlin-native/samples/androidNativeActivity/src/x86Main/kotlin/BMPHeader.kt @@ -0,0 +1,7 @@ +package sample.androidnative + +import kotlinx.cinterop.* +import sample.androidnative.bmpformat.BMPHeader + +val BMPHeader.data + get() = (ptr.reinterpret() + sizeOf()) as CArrayPointer diff --git a/kotlin-native/samples/androidNativeActivity/src/x86Main/kotlin/Disposable.kt b/kotlin-native/samples/androidNativeActivity/src/x86Main/kotlin/Disposable.kt new file mode 100644 index 00000000000..b1076bde043 --- /dev/null +++ b/kotlin-native/samples/androidNativeActivity/src/x86Main/kotlin/Disposable.kt @@ -0,0 +1,62 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the license/LICENSE.txt file. + */ + +package sample.androidnative + +import kotlinx.cinterop.* + +/** + * Disposable class manages and owns all its native resources. It allocates some resources + * during construction and may allocate some additional resources during operation. + * It must free all its resource once [dispose] is invoked. "Disposed" is a final state of the disposable + * class. It is not supposed to be used after being disposed. + */ +interface Disposable { + /** + * Disposes all native resources owned by this class. This function must be invoked + * exactly once as the last operation on the corresponding class. + */ + fun dispose() +} + +/** + * Helper class to implement [Disposable] interface. It contains an [arena] for native + * memory allocations and a number of helper methods to simplify management of other + * kinds of native resources. + * + * It is important to wrap all potentially exception-throwing code in the class constructor + * into [tryConstruct] invocation, because, when object construction fails with exception, + * it ensures that all the resource that were allocated so far will get freed. + */ +abstract class DisposableContainer : Disposable { + val arena = Arena() + + override fun dispose() { + arena.clear() + } + + inline fun tryConstruct(init: () -> T): T = + try { init() } + catch (e: Throwable) { + dispose() + throw e + } + + inline fun disposable( + message: String = "disposable", + create: () -> T?, + crossinline dispose: (T) -> Unit + ): T = + tryConstruct { + create()?.also { + arena.defer { dispose(it) } + } ?: throw Error(message) + } + + inline fun disposable(create: () -> T): T = + disposable( + create = create, + dispose = { it.dispose() }) +} diff --git a/kotlin-native/samples/androidNativeActivity/src/x86Main/kotlin/Engine.kt b/kotlin-native/samples/androidNativeActivity/src/x86Main/kotlin/Engine.kt new file mode 100644 index 00000000000..e082bb980d7 --- /dev/null +++ b/kotlin-native/samples/androidNativeActivity/src/x86Main/kotlin/Engine.kt @@ -0,0 +1,226 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the license/LICENSE.txt file. + */ + +package sample.androidnative + +import kotlinx.cinterop.* +import platform.android.* +import platform.posix.* +import platform.gles3.* +import platform.linux.* + +fun logError(message: String) { + __android_log_write(ANDROID_LOG_ERROR.convert(), "KonanActivity", message) +} + +fun logInfo(message: String) { + __android_log_write(ANDROID_LOG_INFO.convert(), "KonanActivity", message) +} + +private fun getUnixError() = strerror(posix_errno())!!.toKString() + +const val LOOPER_ID_INPUT = 2 + +inline fun CPointer<*>?.dereferenceAs(): T = this!!.reinterpret().pointed + +class Engine(val state: NativeActivityState) : DisposableContainer() { + private val renderer = Renderer(this, state.activity!!.pointed, state.savedState) + private var queue: CPointer? = null + private var rendererState: COpaquePointer? = null + + private var currentPoint = Vector2.Zero + private var startPoint = Vector2.Zero + private var startTime = 0.0f + private var animationEndTime = 0.0f + private var velocity = Vector2.Zero + private var acceleration = Vector2.Zero + + private var needRedraw = true + private var animating = false + private val pointerSize = CPointerVar.size + + private val now = arena.alloc() + private val eventPointer = arena.alloc() + private val inputEvent = arena.alloc>() + + fun mainLoop() { + callToManagedAPI() + + val fd = arena.alloc() + while (true) { + // Process events. + eventLoop@ while (true) { + val id = ALooper_pollAll(if (needRedraw || animating) 0 else -1, fd.ptr, null, null) + if (id < 0) break@eventLoop + when (id) { + LOOPER_ID_SYS -> if (!processSysEvent(fd)) return // An error occured. + LOOPER_ID_INPUT -> processUserInput() + else -> logError("Unprocessed event: $id") + } + } + when { + animating -> { + val elapsed = getTime() - startTime + if (elapsed >= animationEndTime) { + animating = false + } else { + move(startPoint + velocity * elapsed + acceleration * (elapsed * elapsed * 0.5f)) + renderer.draw() + } + } + + needRedraw -> renderer.draw() + } + } + } + + override fun dispose() { + renderer.destroy() + super.dispose() + } + + private val jniBrigde = JniBridge(state.activity!!.pointed.vm!!) + + private fun callToManagedAPI() = jniBrigde.withLocalFrame { + // Actually, this is a context pointer. + val context = JniObject(state.activity!!.pointed.clazz!!) + + val contextClass = FindClass("android/content/Context") + val getSystemServiceMethod = GetMethodID( + contextClass, "getSystemService", "(Ljava/lang/String;)Ljava/lang/Object;")!! + val vibrator = CallObjectMethod(context, getSystemServiceMethod, "vibrator") + if (vibrator != null) { + val vibratorClass = FindClass("android/os/Vibrator") + val vibrateMethod = GetMethodID(vibratorClass, "vibrate", "(J)V")!! + CallVoidMethod(vibrator, vibrateMethod, 500L) + } + } + + private fun processSysEvent(fd: IntVar): Boolean { + val readBytes = read(fd.value, eventPointer.ptr, pointerSize.convert()).toLong() + if (readBytes != pointerSize.toLong()) { + logError("Failure reading event, $readBytes read: ${getUnixError()}") + return true + } + try { + val event = eventPointer.value.dereferenceAs() + println("got ${event.eventKind}") + when (event.eventKind) { + NativeActivityEventKind.START -> { + logInfo("Activity started") + renderer.start() + } + + NativeActivityEventKind.STOP -> { + renderer.stop() + } + + NativeActivityEventKind.DESTROY -> { + rendererState?.let { + free(it) + rendererState = null + } + return false + } + + NativeActivityEventKind.NATIVE_WINDOW_CREATED -> { + val windowEvent = eventPointer.value.dereferenceAs() + if (!renderer.initialize(windowEvent.window!!)) + return false + logInfo("Renderer initialized") + renderer.draw() + } + + NativeActivityEventKind.INPUT_QUEUE_CREATED -> { + val queueEvent = eventPointer.value.dereferenceAs() + if (queue != null) + AInputQueue_detachLooper(queue) + queue = queueEvent.queue + AInputQueue_attachLooper(queue, state.looper, LOOPER_ID_INPUT, null, null) + } + + NativeActivityEventKind.INPUT_QUEUE_DESTROYED -> { + val queueEvent = eventPointer.value.dereferenceAs() + AInputQueue_detachLooper(queueEvent.queue) + } + + NativeActivityEventKind.NATIVE_WINDOW_DESTROYED -> { + renderer.destroy() + } + + NativeActivityEventKind.SAVE_INSTANCE_STATE -> { + val saveStateEvent = eventPointer.value.dereferenceAs() + val state = renderer.getState() + val dataSize = state.second + rendererState = realloc(rendererState, dataSize.convert()) + memcpy(rendererState, state.first, dataSize.convert()) + logInfo("Saving instance state to $rendererState: $dataSize bytes") + saveStateEvent.savedState = rendererState + saveStateEvent.savedStateSize = dataSize.convert() + } + } + } finally { + notifySysEventProcessed() + } + return true + } + + private fun getTime(): Float { + clock_gettime(CLOCK_MONOTONIC, now.ptr) + return now.tv_sec + now.tv_nsec / 1_000_000_000.0f + } + + private fun getEventPoint(event: CPointer?, i: Int) = + Vector2(AMotionEvent_getRawX(event, i.convert()), AMotionEvent_getRawY(event, i.convert())) + + private fun getEventTime(event: CPointer?) = + AMotionEvent_getEventTime(event) / 1_000_000_000.0f + + private fun processUserInput(): Unit { + if (AInputQueue_getEvent(queue, inputEvent.ptr) < 0) { + logError("Failure reading input event") + return + } + val event = inputEvent.value + val eventType = AInputEvent_getType(event) + if (eventType.toUInt() == AINPUT_EVENT_TYPE_MOTION) { + val action = AKeyEvent_getAction(event).toUInt() and AMOTION_EVENT_ACTION_MASK + when (action) { + AMOTION_EVENT_ACTION_DOWN -> { + animating = false + currentPoint = getEventPoint(event, 0) + startTime = getEventTime(event) + startPoint = currentPoint + } + + AMOTION_EVENT_ACTION_UP -> { + val endPoint = getEventPoint(event, 0) + val endTime = getEventTime(event) + animating = true + velocity = (endPoint - startPoint) / (endTime - startTime + 1e-9f) + if (velocity.length > renderer.screen.length) + velocity = velocity * (renderer.screen.length / velocity.length) + acceleration = velocity.normalized() * (-renderer.screen.length * 0.5f) + animationEndTime = velocity.length / acceleration.length + startPoint = endPoint + startTime = endTime + move(endPoint) + } + + AMOTION_EVENT_ACTION_MOVE -> { + val numberOfPointers = AMotionEvent_getPointerCount(event).toInt() + for (i in 0 until numberOfPointers) + move(getEventPoint(event, i)) + } + } + } + AInputQueue_finishEvent(queue, event, 1) + } + + private fun move(newPoint: Vector2) { + renderer.rotateBy(newPoint - currentPoint) + currentPoint = newPoint + } +} diff --git a/kotlin-native/samples/androidNativeActivity/src/x86Main/kotlin/JniBridge.kt b/kotlin-native/samples/androidNativeActivity/src/x86Main/kotlin/JniBridge.kt new file mode 100644 index 00000000000..b8cc8d1b243 --- /dev/null +++ b/kotlin-native/samples/androidNativeActivity/src/x86Main/kotlin/JniBridge.kt @@ -0,0 +1,110 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the license/LICENSE.txt file. + */ + +package sample.androidnative + +import kotlinx.cinterop.* +import platform.android.* + +data class JniClass(val jclass: jclass) +data class JniObject(val jobject: jobject) +data class JniMethod(val jmethod: jmethodID) + +fun asJniClass(jclass: jclass?) = + if (jclass != null) JniClass(jclass) else null + +fun asJniObject(jobject: jobject?) = + if (jobject != null) JniObject(jobject) else null + +fun asJniMethod(jmethodID: jmethodID?) = + if (jmethodID != null) JniMethod(jmethodID) else null + +class JniBridge(val vm: CPointer) { + private val vmFunctions: JNIInvokeInterface = vm.pointed.pointed!! + val jniEnv = memScoped { + val envStorage = alloc>() + if (vmFunctions.AttachCurrentThreadAsDaemon!!(vm, envStorage.ptr, null) != 0) + throw Error("Cannot attach thread to the VM") + envStorage.value!! + } + private val envFunctions: JNINativeInterface = jniEnv.pointed.pointed!! + + // JNI operations. + private val fNewStringUTF = envFunctions.NewStringUTF!! + private val fFindClass = envFunctions.FindClass!! + private val fGetMethodID = envFunctions.GetMethodID!! + private val fCallVoidMethodA = envFunctions.CallVoidMethodA!! + private val fCallObjectMethodA = envFunctions.CallObjectMethodA!! + private val fExceptionCheck = envFunctions.ExceptionCheck!! + private val fExceptionDescribe = envFunctions.ExceptionDescribe!! + private val fExceptionClear = envFunctions.ExceptionClear!! + val fPushLocalFrame = envFunctions.PushLocalFrame!! + val fPopLocalFrame = envFunctions.PopLocalFrame!! + + private fun check() { + if (fExceptionCheck(jniEnv) != 0.toUByte()) { + fExceptionDescribe(jniEnv) + fExceptionClear(jniEnv) + throw Error("JVM exception thrown") + } + } + + fun toJString(string: String) = memScoped { + val result = asJniObject(fNewStringUTF(jniEnv, string.cstr.ptr)) + check() + result + } + + fun toJValues(arguments: Array, scope: MemScope): CPointer? { + val result = scope.allocArray(arguments.size) + arguments.mapIndexed { index, it -> + when (it) { + null -> result[index].l = null + is JniObject -> result[index].l = it.jobject + is String -> result[index].l = toJString(it)?.jobject + is Int -> result[index].i = it + is Long -> result[index].j = it + else -> throw Error("Unsupported conversion for ${it::class.simpleName}") + } + } + return result + } + + fun FindClass(name: String) = memScoped { + val result = asJniClass(fFindClass(jniEnv, name.cstr.ptr)) + check() + result + } + + fun GetMethodID(clazz: JniClass?, name: String, signature: String) = memScoped { + val result = asJniMethod(fGetMethodID(jniEnv, clazz?.jclass, name.cstr.ptr, signature.cstr.ptr)) + check() + result + } + + fun CallVoidMethod(receiver: JniObject?, method: JniMethod, vararg arguments: Any?) = memScoped { + fCallVoidMethodA(jniEnv, receiver?.jobject, method.jmethod, + toJValues(arguments, this@memScoped)) + check() + } + + fun CallObjectMethod(receiver: JniObject?, method: JniMethod, vararg arguments: Any?) = memScoped { + val result = asJniObject(fCallObjectMethodA(jniEnv, receiver?.jobject, method.jmethod, + toJValues(arguments, this@memScoped))) + check() + result + } + + // Usually, use this + inline fun withLocalFrame(block: JniBridge.() -> T): T { + if (fPushLocalFrame(jniEnv, 0) < 0) + throw Error("Cannot push new local frame") + try { + return block() + } finally { + fPopLocalFrame(jniEnv, null) + } + } +} diff --git a/kotlin-native/samples/androidNativeActivity/src/x86Main/kotlin/Polyhedra.kt b/kotlin-native/samples/androidNativeActivity/src/x86Main/kotlin/Polyhedra.kt new file mode 100644 index 00000000000..1a16c1cea46 --- /dev/null +++ b/kotlin-native/samples/androidNativeActivity/src/x86Main/kotlin/Polyhedra.kt @@ -0,0 +1,49 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the license/LICENSE.txt file. + */ + +package sample.androidnative + +const val Zero = 0.0f +const val DodeA = 0.93417235896f // (Sqrt(5) + 1) / (2 * Sqrt(3)) +const val DodeB = 0.35682208977f // (Sqrt(5) - 1) / (2 * Sqrt(3)) +const val DodeC = 0.57735026919f // 1 / Sqrt(3) +const val IcosA = 0.52573111212f // Sqrt(5 - Sqrt(5)) / Sqrt(10) +const val IcosB = 0.85065080835f // Sqrt(5 + Sqrt(5)) / Sqrt(10) + +enum class RegularPolyhedra(val vertices: Array, val faces: Array) { + Dodecahedron( + arrayOf( + Vector3(-DodeA, Zero, DodeB), Vector3(-DodeA, Zero, -DodeB), Vector3(DodeA, Zero, -DodeB), + Vector3(DodeA, Zero, DodeB), Vector3(DodeB, -DodeA, Zero), Vector3(-DodeB, -DodeA, Zero), + Vector3(-DodeB, DodeA, Zero), Vector3(DodeB, DodeA, Zero), Vector3(Zero, DodeB, -DodeA), + Vector3(Zero, -DodeB, -DodeA), Vector3(Zero, -DodeB, DodeA), Vector3(Zero, DodeB, DodeA), + Vector3(-DodeC, -DodeC, DodeC), Vector3(-DodeC, -DodeC, -DodeC), Vector3(DodeC, -DodeC, -DodeC), + Vector3(DodeC, -DodeC, DodeC), Vector3(-DodeC, DodeC, DodeC), Vector3(-DodeC, DodeC, -DodeC), + Vector3(DodeC, DodeC, -DodeC), Vector3(DodeC, DodeC, DodeC) + ), + arrayOf( + byteArrayOf(0, 12, 10, 11, 16), byteArrayOf(1, 17, 8, 9, 13), byteArrayOf(2, 14, 9, 8, 18), + byteArrayOf(3, 19, 11, 10, 15), byteArrayOf(4, 14, 2, 3, 15), byteArrayOf(5, 12, 0, 1, 13), + byteArrayOf(6, 17, 1, 0, 16), byteArrayOf(7, 19, 3, 2, 18), byteArrayOf(8, 17, 6, 7, 18), + byteArrayOf(9, 14, 4, 5, 13), byteArrayOf(10, 12, 5, 4, 15), byteArrayOf(11, 19, 7, 6, 16) + )), + Icosahedron( + arrayOf( + Vector3(-IcosA, Zero, IcosB), Vector3(IcosA, Zero, IcosB), Vector3(-IcosA, Zero, -IcosB), + Vector3(IcosA, Zero, -IcosB), Vector3(Zero, IcosB, IcosA), Vector3(Zero, IcosB, -IcosA), + Vector3(Zero, -IcosB, IcosA), Vector3(Zero, -IcosB, -IcosA), Vector3(IcosB, IcosA, Zero), + Vector3(-IcosB, IcosA, Zero), Vector3(IcosB, -IcosA, Zero), Vector3(-IcosB, -IcosA, Zero) + ), + arrayOf( + byteArrayOf(1, 4, 0), byteArrayOf(4, 9, 0), byteArrayOf(4, 5, 9), byteArrayOf(8, 5, 4), + byteArrayOf(1, 8, 4), byteArrayOf(1, 10, 8), byteArrayOf(10, 3, 8), byteArrayOf(8, 3, 5), + byteArrayOf(3, 2, 5), byteArrayOf(3, 7, 2), byteArrayOf(3, 10, 7), byteArrayOf(10, 6, 7), + byteArrayOf(6, 11, 7), byteArrayOf(6, 0, 11), byteArrayOf(6, 1, 0), byteArrayOf(10, 1, 6), + byteArrayOf(11, 0, 9), byteArrayOf(2, 11, 9), byteArrayOf(5, 2, 9), byteArrayOf(11, 2, 7) + ) + ); + + val verticesPerFace get() = faces[0].size +} \ No newline at end of file diff --git a/kotlin-native/samples/androidNativeActivity/src/x86Main/kotlin/Renderer.kt b/kotlin-native/samples/androidNativeActivity/src/x86Main/kotlin/Renderer.kt new file mode 100644 index 00000000000..cbc485783bf --- /dev/null +++ b/kotlin-native/samples/androidNativeActivity/src/x86Main/kotlin/Renderer.kt @@ -0,0 +1,302 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the license/LICENSE.txt file. + */ + +package sample.androidnative + +import kotlinx.cinterop.* +import platform.android.* +import platform.egl.* +import platform.posix.* +import platform.gles.* +import sample.androidnative.bmpformat.BMPHeader + +class Renderer(val container: DisposableContainer, + val nativeActivity: ANativeActivity, + val savedMatrix: COpaquePointer?) { + private var display: EGLDisplay? = null + private var surface: EGLSurface? = null + private var context: EGLContext? = null + private var initialized = false + + var screen = Vector2.Zero + + private val matrix = container.arena.allocArray(16) + + init { + if (savedMatrix != null) { + memcpy(matrix, savedMatrix, 16 * 4) + } else { + for (i in 0..3) + for (j in 0..3) + matrix[i * 4 + j] = if (i == j) 1.0f else 0.0f + } + } + + fun initialize(window: CPointer): Boolean { + with(container.arena) { + logInfo("Initializing context..") + display = eglGetDisplay(null) + if (display == null) { + logError("eglGetDisplay() returned error ${eglGetError()}") + return false + } + if (eglInitialize(display, null, null) == 0u) { + logError("eglInitialize() returned error ${eglGetError()}") + return false + } + + val attribs = cValuesOf( + EGL_SURFACE_TYPE, EGL_WINDOW_BIT, + EGL_BLUE_SIZE, 8, + EGL_GREEN_SIZE, 8, + EGL_RED_SIZE, 8, + EGL_NONE + ) + val numConfigs = alloc() + if (eglChooseConfig(display, attribs, null, 0, numConfigs.ptr) == 0u) { + throw Error("eglChooseConfig()#1 returned error ${eglGetError()}") + } + val supportedConfigs = allocArray(numConfigs.value) + if (eglChooseConfig(display, attribs, supportedConfigs, numConfigs.value, numConfigs.ptr) == 0u) { + throw Error("eglChooseConfig()#2 returned error ${eglGetError()}") + } + var configIndex = 0 + while (configIndex < numConfigs.value) { + val r = alloc() + val g = alloc() + val b = alloc() + val d = alloc() + if (eglGetConfigAttrib(display, supportedConfigs[configIndex], EGL_RED_SIZE, r.ptr) != 0u && + eglGetConfigAttrib (display, supportedConfigs[configIndex], EGL_GREEN_SIZE, g.ptr) != 0u && + eglGetConfigAttrib(display, supportedConfigs[configIndex], EGL_BLUE_SIZE, b.ptr) != 0u && + eglGetConfigAttrib(display, supportedConfigs[configIndex], EGL_DEPTH_SIZE, d.ptr) != 0u && + r.value == 8 && g.value == 8 && b.value == 8 && d.value == 0) break + ++configIndex + } + if (configIndex >= numConfigs.value) + configIndex = 0 + + surface = eglCreateWindowSurface(display, supportedConfigs[configIndex], window, null) + if (surface == null) { + throw Error("eglCreateWindowSurface() returned error ${eglGetError()}") + } + + context = eglCreateContext(display, supportedConfigs[configIndex], null, null) + if (context == null) { + throw Error("eglCreateContext() returned error ${eglGetError()}") + } + + if (eglMakeCurrent(display, surface, surface, context) == 0u) { + throw Error("eglMakeCurrent() returned error ${eglGetError()}") + } + + val width = alloc() + val height = alloc() + if (eglQuerySurface(display, surface, EGL_WIDTH, width.ptr) == 0u + || eglQuerySurface (display, surface, EGL_HEIGHT, height.ptr) == 0u) { + throw Error("eglQuerySurface() returned error ${eglGetError()}") + } + + this@Renderer.screen = Vector2(width.value.toFloat(), height.value.toFloat()) + + glDisable(GL_DITHER) + glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_FASTEST) + glClearColor(0.0f, 0.0f, 0.0f, 0.0f) + glEnable(GL_CULL_FACE) + glShadeModel(GL_SMOOTH) + glEnable(GL_DEPTH_TEST) + + glViewport(0, 0, width.value, height.value) + + val ratio = width.value.toFloat() / height.value + glMatrixMode(GL_PROJECTION) + checkErrors() + glLoadIdentity() + glFrustumf(-ratio, ratio, -1.0f, 1.0f, 1.0f, 10.0f) + + glMatrixMode(GL_MODELVIEW) + checkErrors() + glTranslatef(0.0f, 0.0f, -2.0f) + glLightfv(GL_LIGHT0, GL_POSITION, cValuesOf(1.25f, 1.25f, -2.0f, 0.0f)) + glEnable(GL_LIGHTING) + glEnable(GL_LIGHT0) + glEnable(GL_TEXTURE_2D) + glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, cValuesOf(0.0f, 1.0f, 1.0f, 1.0f)) + glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, cValuesOf(0.3f, 0.3f, 0.3f, 1.0f)) + glMaterialf(GL_FRONT_AND_BACK, GL_SHININESS, 30.0f) + + loadTexture("kotlin_logo.bmp") + + initialized = true + return true + } + } + + fun checkErrors() { + val error = glGetError() + if (error.toInt() != GL_NO_ERROR) + throw Error("OpenGL error 0x${error.toInt().toString(16)}") + } + + fun getState() = matrix to 16 * 4 + + fun rotateBy(vector: Vector2) { + if (!initialized) return + + val length = vector.length + if (length < 1e-9f) return + val angle = 180 * length / screen.length + val x = -vector.y / length + val y = -vector.x / length + + glPushMatrix() + glMatrixMode(GL_MODELVIEW) + checkErrors() + glLoadIdentity() + glRotatef(angle, x, y, 0.0f) + glMultMatrixf(matrix) + glGetFloatv(GL_MODELVIEW_MATRIX, matrix) + glPopMatrix() + } + + + private fun loadTexture(assetName: String): Unit = memScoped { + val asset = AAssetManager_open(nativeActivity.assetManager, assetName, AASSET_MODE_BUFFER.convert()) + ?: throw Error("Error opening asset $assetName") + println("loading texture $assetName") + try { + val length = AAsset_getLength(asset) + val buffer = allocArray(length) + if (AAsset_read(asset, buffer, length.convert()) != length.toInt()) { + throw Error("Error reading asset") + } + + with(buffer.reinterpret().pointed) { + if (magic != 0x4d42.toUShort() || zero != 0u || size != length.toUInt() || bits != 24.toUShort()) { + throw Error("Error parsing texture file") + } + val numberOfBytes = width * height * 3 + // Swap BGR in bitmap to RGB. + for (i in 0 until numberOfBytes step 3) { + val t = data[i] + data[i] = data[i + 2] + data[i + 2] = t + } + println("loaded texture ${width}x${height}") + glBindTexture(GL_TEXTURE_2D, 1) + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR) + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR) + glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_BLEND.toFloat()) + glTexEnvfv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, cValuesOf(1.0f, 1.0f, 1.0f, 1.0f)) + glPixelStorei(GL_UNPACK_ALIGNMENT, 1) + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, width, height, 0, GL_RGB, GL_UNSIGNED_BYTE, data) + + } + } finally { + AAsset_close(asset) + } + } + + private val texturePoints = arrayOf( + Vector2(0.0f, 0.2f), Vector2(0.0f, 0.8f), Vector2(0.6f, 1.0f), Vector2(1.0f, 0.5f), Vector2(0.8f, 0.0f) + ) + + private val scale = 1.25f + + fun draw(): Unit { + if (!initialized) return + + glPushMatrix() + glMatrixMode(GL_MODELVIEW) + checkErrors() + + glMultMatrixf(matrix) + + glClear((GL_COLOR_BUFFER_BIT or GL_DEPTH_BUFFER_BIT).toUInt()) + + glEnableClientState(GL_VERTEX_ARRAY) + glEnableClientState(GL_NORMAL_ARRAY) + glEnableClientState(GL_TEXTURE_COORD_ARRAY) + + val polygon = RegularPolyhedra.Dodecahedron + val vertices = mutableListOf() + val texCoords = mutableListOf() + val triangles = mutableListOf() + val normals = mutableListOf() + for (face in polygon.faces) { + val u = polygon.vertices[face[2].toInt()] - polygon.vertices[face[1].toInt()] + val v = polygon.vertices[face[0].toInt()] - polygon.vertices[face[1].toInt()] + val normal = u.crossProduct(v).normalized() + + val copiedFace = ByteArray(face.size) + for (j in face.indices) { + copiedFace[j] = (vertices.size / 4).toByte() + polygon.vertices[face[j].toInt()].copyCoordinatesTo(vertices) + vertices.add(scale) + normal.copyCoordinatesTo(normals) + texturePoints[j].copyCoordinatesTo(texCoords) + } + + for (j in 1..face.size - 2) { + triangles.add(copiedFace[0]) + triangles.add(copiedFace[j]) + triangles.add(copiedFace[j + 1]) + } + } + + memScoped { + glFrontFace(GL_CW) + glVertexPointer(4, GL_FLOAT, 0, vertices.toFloatArray().toCValues().ptr) + glTexCoordPointer(2, GL_FLOAT, 0, texCoords.toFloatArray().toCValues().ptr) + glNormalPointer(GL_FLOAT, 0, normals.toFloatArray().toCValues().ptr) + glDrawElements(GL_TRIANGLES, triangles.size, GL_UNSIGNED_BYTE, triangles.toByteArray().toCValues().ptr) + } + + glPopMatrix() + + if (eglSwapBuffers(display, surface) == 0u) { + val error = eglGetError() + if (error != EGL_BAD_SURFACE) + throw Error("eglSwapBuffers() returned error $error") + else { + if (eglMakeCurrent(display, surface, surface, context) == 0u) { + throw Error("Reinit eglMakeCurrent() returned error ${eglGetError()}") + } + if (eglSwapBuffers(display, surface) == 0u) + throw Error("Bad eglSwapBuffers() after surface reinit: ${eglGetError()}") + } + } + } + + fun start() { + logInfo("Starting renderer.") + if (initialized) { + if (eglMakeCurrent(display, surface, surface, context) == 0u) { + throw Error("eglMakeCurrent() returned error ${eglGetError()}") + } + } + } + + fun stop() { + logInfo("Stopping renderer..") + eglMakeCurrent(display, null, null, null) + } + + fun destroy() { + if (!initialized) return + + logInfo("Destroying renderer..") + eglMakeCurrent(display, null, null, null) + + context?.let { eglDestroyContext(display, it) } + surface?.let { eglDestroySurface(display, it) } + display?.let { eglTerminate(display) } + + display = null + surface = null + context = null + initialized = false + } +} diff --git a/kotlin-native/samples/androidNativeActivity/src/x86Main/kotlin/Vectors.kt b/kotlin-native/samples/androidNativeActivity/src/x86Main/kotlin/Vectors.kt new file mode 100644 index 00000000000..f86c077362c --- /dev/null +++ b/kotlin-native/samples/androidNativeActivity/src/x86Main/kotlin/Vectors.kt @@ -0,0 +1,55 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the license/LICENSE.txt file. + */ + +package sample.androidnative + +import kotlinx.cinterop.* +import platform.android.* +import platform.posix.* + +class Vector2(val x: Float, val y: Float) { + val length by lazy { sqrtf(x * x + y * y) } + + fun normalized(): Vector2 { + val len = length + return Vector2(x / len, y / len) + } + + fun copyCoordinatesTo(arr: MutableList) { + arr.add(x) + arr.add(y) + } + + operator fun minus(other: Vector2) = Vector2(x - other.x, y - other.y) + operator fun plus(other: Vector2) = Vector2(x + other.x, y + other.y) + operator fun times(other: Float) = Vector2(x * other, y * other) + operator fun div(other: Float) = Vector2(x / other, y / other) + + companion object { + val Zero = Vector2(0.0f, 0.0f) + } +} + +class Vector3(val x: Float, val y: Float, val z: Float) { + val length by lazy { sqrtf(x * x + y * y + z * z) } + + fun crossProduct(other: Vector3): Vector3 = + Vector3(y * other.z - z * other.y, z * other.x - x * other.z, x * other.y - y * other.x) + + fun normalized(): Vector3 { + val len = length + return Vector3(x / len, y / len, z / len) + } + + fun copyCoordinatesTo(arr: MutableList) { + arr.add(x) + arr.add(y) + arr.add(z) + } + + operator fun minus(other: Vector3) = Vector3(x - other.x, y - other.y, z - other.z) + operator fun plus(other: Vector3) = Vector3(x + other.x, y + other.y, z + other.z) +} + diff --git a/kotlin-native/samples/androidNativeActivity/src/x86Main/kotlin/main.kt b/kotlin-native/samples/androidNativeActivity/src/x86Main/kotlin/main.kt new file mode 100644 index 00000000000..dc558f08937 --- /dev/null +++ b/kotlin-native/samples/androidNativeActivity/src/x86Main/kotlin/main.kt @@ -0,0 +1,24 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the license/LICENSE.txt file. + */ + +package sample.androidnative + +import kotlinx.cinterop.* +import platform.android.* + +fun main() { + logInfo("Entering main().") + memScoped { + val state = alloc() + getNativeActivityState(state.ptr) + val engine = Engine(state) + try { + engine.mainLoop() + } finally { + engine.dispose() + } + } + kotlin.system.exitProcess(0) +} diff --git a/kotlin-native/samples/androidNativeActivity/src/x86Main/res/mipmap-hdpi/konan_activity.png b/kotlin-native/samples/androidNativeActivity/src/x86Main/res/mipmap-hdpi/konan_activity.png new file mode 100755 index 00000000000..deb3f79d059 Binary files /dev/null and b/kotlin-native/samples/androidNativeActivity/src/x86Main/res/mipmap-hdpi/konan_activity.png differ diff --git a/kotlin-native/samples/androidNativeActivity/src/x86Main/res/mipmap-mdpi/konan_activity.png b/kotlin-native/samples/androidNativeActivity/src/x86Main/res/mipmap-mdpi/konan_activity.png new file mode 100755 index 00000000000..63a53c0b2f8 Binary files /dev/null and b/kotlin-native/samples/androidNativeActivity/src/x86Main/res/mipmap-mdpi/konan_activity.png differ diff --git a/kotlin-native/samples/androidNativeActivity/src/x86Main/res/mipmap-xhdpi/konan_activity.png b/kotlin-native/samples/androidNativeActivity/src/x86Main/res/mipmap-xhdpi/konan_activity.png new file mode 100755 index 00000000000..cb7cfc14d03 Binary files /dev/null and b/kotlin-native/samples/androidNativeActivity/src/x86Main/res/mipmap-xhdpi/konan_activity.png differ diff --git a/kotlin-native/samples/androidNativeActivity/src/x86Main/res/mipmap-xxhdpi/konan_activity.png b/kotlin-native/samples/androidNativeActivity/src/x86Main/res/mipmap-xxhdpi/konan_activity.png new file mode 100755 index 00000000000..8d427824430 Binary files /dev/null and b/kotlin-native/samples/androidNativeActivity/src/x86Main/res/mipmap-xxhdpi/konan_activity.png differ diff --git a/kotlin-native/samples/androidNativeActivity/src/x86Main/res/values/strings.xml b/kotlin-native/samples/androidNativeActivity/src/x86Main/res/values/strings.xml new file mode 100644 index 00000000000..e1033450618 --- /dev/null +++ b/kotlin-native/samples/androidNativeActivity/src/x86Main/res/values/strings.xml @@ -0,0 +1,4 @@ + + + KonanActivity + diff --git a/kotlin-native/samples/build.gradle.kts b/kotlin-native/samples/build.gradle.kts new file mode 100644 index 00000000000..5dd47dbed61 --- /dev/null +++ b/kotlin-native/samples/build.gradle.kts @@ -0,0 +1,74 @@ +buildscript { + repositories { + mavenCentral() + maven("https://dl.bintray.com/kotlin/kotlin-dev") + maven("https://dl.bintray.com/kotlin/kotlin-eap") + } + + val kotlin_version: String by rootProject + dependencies { + classpath("org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version") + } +} + +allprojects { + repositories { + mavenCentral() + maven("https://dl.bintray.com/kotlin/kotlin-dev") + maven("https://dl.bintray.com/kotlin/kotlin-eap") + } +} + +val hostOs = System.getProperty("os.name") +val isMacos = hostOs == "Mac OS X" +val isLinux = hostOs == "Linux" +val isWindows = hostOs.startsWith("Windows") + +val localRepo = rootProject.file("build/.m2-local") + +val clean by tasks.creating(Delete::class) { + delete(localRepo) +} + +val buildSh by tasks.creating(Exec::class) { + errorOutput = System.out + isIgnoreExitValue = true + workingDir = projectDir + enabled = !isWindows + if (isLinux || isMacos) { + commandLine = listOf(projectDir.resolve("build.sh").toString()) + } +} + +val buildSamplesWithPlatformLibs by tasks.creating { + dependsOn(":csvparser:assemble") + dependsOn(":curl:assemble") + dependsOn(":echoServer:assemble") + dependsOn(":globalState:assemble") + dependsOn(":html5Canvas:assemble") + dependsOn(":workers:assemble") + + if (isMacos || isLinux) { + dependsOn(":nonBlockingEchoServer:assemble") + dependsOn(":tensorflow:assemble") + } + + if (isMacos) { + dependsOn(":objc:assemble") + dependsOn(":opengl:assemble") + dependsOn(":uikit:assemble") + dependsOn(":coverage:assemble") + dependsOn(":watchos:assemble") + } + + if (isWindows) { + dependsOn(":win32:assemble") + } +} + +val buildAllSamples by tasks.creating { + subprojects.forEach { + dependsOn("${it.path}:assemble") + } + finalizedBy(buildSh) +} diff --git a/kotlin-native/samples/build.sh b/kotlin-native/samples/build.sh new file mode 100755 index 00000000000..68e23e48676 --- /dev/null +++ b/kotlin-native/samples/build.sh @@ -0,0 +1,27 @@ +#!/usr/bin/env bash +EXCLUDE=() +BUILD_SCRIPT="build.sh" + +function isExcluded() { + CHECKED="${1}" + for VALUE in $EXCLUDE; do + if [ "x$CHECKED" == "x$VALUE" ]; then + return 0 + fi + done + return -1 +} + +for SAMPLE_DIR in *; do + if [ -d "$SAMPLE_DIR" ] && [ -e "$SAMPLE_DIR/$BUILD_SCRIPT" ]; then + echo + echo "======================================================" + date + echo "Building a sample: $SAMPLE_DIR." + if ! isExcluded "$SAMPLE_DIR"; then + bash "$SAMPLE_DIR/$BUILD_SCRIPT" || (echo "Cannot build a sample: $SAMPLE_DIR. See log for details." && exit 1) + else + echo "The sample excluded." + fi + fi +done diff --git a/kotlin-native/samples/calculator/.gitignore b/kotlin-native/samples/calculator/.gitignore new file mode 100644 index 00000000000..9bce6af399b --- /dev/null +++ b/kotlin-native/samples/calculator/.gitignore @@ -0,0 +1 @@ +xcuserdata diff --git a/kotlin-native/samples/calculator/README.md b/kotlin-native/samples/calculator/README.md new file mode 100644 index 00000000000..6b14b91f4cf --- /dev/null +++ b/kotlin-native/samples/calculator/README.md @@ -0,0 +1,55 @@ +# Calculator sample + +This example shows how to use Kotlin common module (located in [arithmeticParser](arithmeticParser/)) in different environments. +Currently for +* Android (see [androidApp](androidApp/)) +* iOS (see [iosApp](iosApp/)) +* plain JVM (cli) (see [cliApp](cliApp/)) + +## Common + +Common Kotlin module contains arithmetic expressions parser. + +## Android App +The common module may be used in an Android application. + +Please make sure that Android SDK version 28 is installed, using Android SDK manager in Android Studio. +See https://developer.android.com/studio/index.html for more details on Android Studio or +`$ANDROID_HOME/tools/bin/sdkmanager "platforms;android-28" "build-tools;28.0.3"` from command line. + +To build use `ANDROID_HOME= ../gradlew assemble`. + +Run `$ANDROID_HOME/platform-tools/adb install -r androidApp/build/outputs/apk/debug/androidApp-debug.apk` +to deploy the apk on the Android device or emulator. + +Note: If you are importing project to IDEA for the first time, you might need to put `local.properties` file +with the following content: + + sdk.dir= + +## iOS +The iOS project compiles Kotlin module to a framework (see [iosApp](iosApp/)). The framework can be easily included in an existing iOS project (e.g. written in Swift or Objective-C) + +To build and run the iOS sample do the following: + +1. Open `iosApp/calculator.xcodeproj` with Xcode. +2. Open the project's target through project navigator, go to tab 'General'. + In 'Identity' section change the bundle ID to the unique string in + reverse-DNS format. Then select the team in 'Signing' section. + + See the + [Xcode documentation](https://developer.apple.com/library/content/documentation/IDEs/Conceptual/AppDistributionGuide/ConfiguringYourApp/ConfiguringYourApp.html#//apple_ref/doc/uid/TP40012582-CH28-SW2) + for more info. +3. Now build and run the application with Xcode. + +The iOS application is written in Swift. It uses Kotlin module as a library. +Kotlin module is built into Objective-C framework by invoking Gradle +from custom "Run Script" build phase, and this framework is imported into +the Xcode project. + +## Plain JVM +The common module can also be used in JVM application built by Kotlin/JVM compiler with Gradle. +To build and run it, go to [cliApp](cliApp/) directory and use +``` +../gradlew runProgram +``` diff --git a/kotlin-native/samples/calculator/androidApp/build.gradle b/kotlin-native/samples/calculator/androidApp/build.gradle new file mode 100644 index 00000000000..211a555cb9a --- /dev/null +++ b/kotlin-native/samples/calculator/androidApp/build.gradle @@ -0,0 +1,24 @@ +apply plugin: 'org.jetbrains.kotlin.multiplatform' +apply plugin: 'com.android.application' +apply plugin: 'kotlin-android-extensions' + +android { + compileSdkVersion 28 + + defaultConfig { + applicationId 'org.konan.calculator' + minSdkVersion 21 + targetSdkVersion 28 + } +} + +dependencies { + api 'com.android.support:appcompat-v7:28.0.0' + api 'com.android.support.constraint:constraint-layout:1.1.3' + implementation fileTree(dir: 'libs', include: ['*.jar']) + implementation project(':arithmeticParser') +} + +kotlin { + android() +} diff --git a/kotlin-native/samples/calculator/androidApp/gradle.properties b/kotlin-native/samples/calculator/androidApp/gradle.properties new file mode 100644 index 00000000000..790a07d5124 --- /dev/null +++ b/kotlin-native/samples/calculator/androidApp/gradle.properties @@ -0,0 +1,2 @@ +kotlin.code.style=official +kotlin.import.noCommonSourceSets=true diff --git a/kotlin-native/samples/calculator/androidApp/src/main/AndroidManifest.xml b/kotlin-native/samples/calculator/androidApp/src/main/AndroidManifest.xml new file mode 100644 index 00000000000..a224235bfd7 --- /dev/null +++ b/kotlin-native/samples/calculator/androidApp/src/main/AndroidManifest.xml @@ -0,0 +1,26 @@ + + + + + + + + + + + + + + + diff --git a/kotlin-native/samples/calculator/androidApp/src/main/kotlin/MainActivity.kt b/kotlin-native/samples/calculator/androidApp/src/main/kotlin/MainActivity.kt new file mode 100644 index 00000000000..b21f0de3060 --- /dev/null +++ b/kotlin-native/samples/calculator/androidApp/src/main/kotlin/MainActivity.kt @@ -0,0 +1,33 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the license/LICENSE.txt file. + */ + +package sample.calculator.android + +import android.os.Bundle +import android.support.v7.app.AppCompatActivity +import android.widget.EditText +import android.widget.TextView +import sample.calculator.arithmeticparser.parseAndCompute + +class MainActivity : AppCompatActivity() { + + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + setContentView(R.layout.activity_main) + + val resultView = findViewById(R.id.computed_result) + + val input = findViewById(R.id.input) + input.setOnEditorActionListener { input, _, _ -> + val inputText = input.text.toString() + val result = parseAndCompute(inputText).expression + with(resultView) { + text = if (result != null) inputText + " = " + result.toString() else "Unable to parse $inputText" + } + true + } + } + +} \ No newline at end of file diff --git a/kotlin-native/samples/calculator/androidApp/src/main/res/drawable-v24/ic_launcher_foreground.xml b/kotlin-native/samples/calculator/androidApp/src/main/res/drawable-v24/ic_launcher_foreground.xml new file mode 100644 index 00000000000..c7bd21dbd86 --- /dev/null +++ b/kotlin-native/samples/calculator/androidApp/src/main/res/drawable-v24/ic_launcher_foreground.xml @@ -0,0 +1,34 @@ + + + + + + + + + + + diff --git a/kotlin-native/samples/calculator/androidApp/src/main/res/drawable/ic_launcher_background.xml b/kotlin-native/samples/calculator/androidApp/src/main/res/drawable/ic_launcher_background.xml new file mode 100644 index 00000000000..d5fccc538c1 --- /dev/null +++ b/kotlin-native/samples/calculator/androidApp/src/main/res/drawable/ic_launcher_background.xml @@ -0,0 +1,170 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/kotlin-native/samples/calculator/androidApp/src/main/res/layout/activity_main.xml b/kotlin-native/samples/calculator/androidApp/src/main/res/layout/activity_main.xml new file mode 100644 index 00000000000..73b2810335c --- /dev/null +++ b/kotlin-native/samples/calculator/androidApp/src/main/res/layout/activity_main.xml @@ -0,0 +1,26 @@ + + + + + + + + + + diff --git a/kotlin-native/samples/calculator/androidApp/src/main/res/mipmap-anydpi-v26/ic_launcher.xml b/kotlin-native/samples/calculator/androidApp/src/main/res/mipmap-anydpi-v26/ic_launcher.xml new file mode 100644 index 00000000000..eca70cfe52e --- /dev/null +++ b/kotlin-native/samples/calculator/androidApp/src/main/res/mipmap-anydpi-v26/ic_launcher.xml @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/kotlin-native/samples/calculator/androidApp/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml b/kotlin-native/samples/calculator/androidApp/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml new file mode 100644 index 00000000000..eca70cfe52e --- /dev/null +++ b/kotlin-native/samples/calculator/androidApp/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/kotlin-native/samples/calculator/androidApp/src/main/res/mipmap-hdpi/ic_launcher.png b/kotlin-native/samples/calculator/androidApp/src/main/res/mipmap-hdpi/ic_launcher.png new file mode 100644 index 00000000000..a2f5908281d Binary files /dev/null and b/kotlin-native/samples/calculator/androidApp/src/main/res/mipmap-hdpi/ic_launcher.png differ diff --git a/kotlin-native/samples/calculator/androidApp/src/main/res/mipmap-hdpi/ic_launcher_round.png b/kotlin-native/samples/calculator/androidApp/src/main/res/mipmap-hdpi/ic_launcher_round.png new file mode 100644 index 00000000000..1b523998081 Binary files /dev/null and b/kotlin-native/samples/calculator/androidApp/src/main/res/mipmap-hdpi/ic_launcher_round.png differ diff --git a/kotlin-native/samples/calculator/androidApp/src/main/res/mipmap-mdpi/ic_launcher.png b/kotlin-native/samples/calculator/androidApp/src/main/res/mipmap-mdpi/ic_launcher.png new file mode 100644 index 00000000000..ff10afd6e18 Binary files /dev/null and b/kotlin-native/samples/calculator/androidApp/src/main/res/mipmap-mdpi/ic_launcher.png differ diff --git a/kotlin-native/samples/calculator/androidApp/src/main/res/mipmap-mdpi/ic_launcher_round.png b/kotlin-native/samples/calculator/androidApp/src/main/res/mipmap-mdpi/ic_launcher_round.png new file mode 100644 index 00000000000..115a4c768a2 Binary files /dev/null and b/kotlin-native/samples/calculator/androidApp/src/main/res/mipmap-mdpi/ic_launcher_round.png differ diff --git a/kotlin-native/samples/calculator/androidApp/src/main/res/mipmap-xhdpi/ic_launcher.png b/kotlin-native/samples/calculator/androidApp/src/main/res/mipmap-xhdpi/ic_launcher.png new file mode 100644 index 00000000000..dcd3cd80833 Binary files /dev/null and b/kotlin-native/samples/calculator/androidApp/src/main/res/mipmap-xhdpi/ic_launcher.png differ diff --git a/kotlin-native/samples/calculator/androidApp/src/main/res/mipmap-xhdpi/ic_launcher_round.png b/kotlin-native/samples/calculator/androidApp/src/main/res/mipmap-xhdpi/ic_launcher_round.png new file mode 100644 index 00000000000..459ca609d3a Binary files /dev/null and b/kotlin-native/samples/calculator/androidApp/src/main/res/mipmap-xhdpi/ic_launcher_round.png differ diff --git a/kotlin-native/samples/calculator/androidApp/src/main/res/mipmap-xxhdpi/ic_launcher.png b/kotlin-native/samples/calculator/androidApp/src/main/res/mipmap-xxhdpi/ic_launcher.png new file mode 100644 index 00000000000..8ca12fe024b Binary files /dev/null and b/kotlin-native/samples/calculator/androidApp/src/main/res/mipmap-xxhdpi/ic_launcher.png differ diff --git a/kotlin-native/samples/calculator/androidApp/src/main/res/mipmap-xxhdpi/ic_launcher_round.png b/kotlin-native/samples/calculator/androidApp/src/main/res/mipmap-xxhdpi/ic_launcher_round.png new file mode 100644 index 00000000000..8e19b410a1b Binary files /dev/null and b/kotlin-native/samples/calculator/androidApp/src/main/res/mipmap-xxhdpi/ic_launcher_round.png differ diff --git a/kotlin-native/samples/calculator/androidApp/src/main/res/mipmap-xxxhdpi/ic_launcher.png b/kotlin-native/samples/calculator/androidApp/src/main/res/mipmap-xxxhdpi/ic_launcher.png new file mode 100644 index 00000000000..b824ebdd48d Binary files /dev/null and b/kotlin-native/samples/calculator/androidApp/src/main/res/mipmap-xxxhdpi/ic_launcher.png differ diff --git a/kotlin-native/samples/calculator/androidApp/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png b/kotlin-native/samples/calculator/androidApp/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png new file mode 100644 index 00000000000..4c19a13c239 Binary files /dev/null and b/kotlin-native/samples/calculator/androidApp/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png differ diff --git a/kotlin-native/samples/calculator/androidApp/src/main/res/values/colors.xml b/kotlin-native/samples/calculator/androidApp/src/main/res/values/colors.xml new file mode 100644 index 00000000000..3ab3e9cbce0 --- /dev/null +++ b/kotlin-native/samples/calculator/androidApp/src/main/res/values/colors.xml @@ -0,0 +1,6 @@ + + + #3F51B5 + #303F9F + #FF4081 + diff --git a/kotlin-native/samples/calculator/androidApp/src/main/res/values/strings.xml b/kotlin-native/samples/calculator/androidApp/src/main/res/values/strings.xml new file mode 100644 index 00000000000..add2d6a43d2 --- /dev/null +++ b/kotlin-native/samples/calculator/androidApp/src/main/res/values/strings.xml @@ -0,0 +1,4 @@ + + Konan Calculator + Enter mathematical expression: + diff --git a/kotlin-native/samples/calculator/androidApp/src/main/res/values/styles.xml b/kotlin-native/samples/calculator/androidApp/src/main/res/values/styles.xml new file mode 100644 index 00000000000..0eb88fe3350 --- /dev/null +++ b/kotlin-native/samples/calculator/androidApp/src/main/res/values/styles.xml @@ -0,0 +1,11 @@ + + + + + + diff --git a/kotlin-native/samples/calculator/arithmeticParser/Info.plist b/kotlin-native/samples/calculator/arithmeticParser/Info.plist new file mode 100644 index 00000000000..b5dc715d4fe --- /dev/null +++ b/kotlin-native/samples/calculator/arithmeticParser/Info.plist @@ -0,0 +1,22 @@ + + + + + CFBundleDevelopmentRegion + $(DEVELOPMENT_LANGUAGE) + CFBundleExecutable + $(EXECUTABLE_NAME) + CFBundleIdentifier + $(PRODUCT_BUNDLE_IDENTIFIER) + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + $(PRODUCT_NAME) + CFBundlePackageType + FMWK + CFBundleShortVersionString + 1.0 + CFBundleVersion + $(CURRENT_PROJECT_VERSION) + + diff --git a/kotlin-native/samples/calculator/arithmeticParser/build.gradle b/kotlin-native/samples/calculator/arithmeticParser/build.gradle new file mode 100644 index 00000000000..8a14ecff1c5 --- /dev/null +++ b/kotlin-native/samples/calculator/arithmeticParser/build.gradle @@ -0,0 +1,81 @@ +apply plugin: 'org.jetbrains.kotlin.multiplatform' + +kotlin { + targets { + fromPreset(determineIosPreset(), 'ios') { + binaries { + framework() + } + } + + fromPreset(presets.jvm, 'jvm') + } + + sourceSets { + commonMain { + dependencies { + api 'org.jetbrains.kotlin:kotlin-stdlib-common' + } + } + jvmMain { + dependencies { + api 'org.jetbrains.kotlin:kotlin-stdlib-jdk8' + } + } + } +} + +// Workaround for https://youtrack.jetbrains.com/issue/KT-27170 +configurations { + compileClasspath +} + +// If custom preset specified in 'calculator.preset.name' property, then use it for building. +// Otherwise build for iPhone simulator (by default). +def determineIosPreset() { + String presetName = project.hasProperty('calculator.preset.name') ? project.properties['calculator.preset.name'] : 'iosX64' + def preset = project.kotlin.presets[presetName] + println("$project has been configured for $presetName platform.") + preset +} + +// Special Gradle task that is called from Xcode. +// Two Gradle properties must be specified for this task: +// - calculator.configuration.name=[Release|Debug] +// - calculator.framework.location +task buildFrameworkForXcode { + + if (isCalledFromXcode()) { + dependsOn kotlin.targets.ios.binaries.getFramework(getBuildTypeForXcode()).linkTask + } + + doLast { + if (!isCalledFromXcode()) { + throw new Exception("Please run 'buildFrameworkForXcode' task with all necessary properties!") + } + + def frameworkDir = kotlin.targets.ios.binaries.getFramework(getBuildTypeForXcode()).outputFile + + println("from: ${frameworkDir.parentFile}") + println("into: ${getXcodeConfigurationBuildDir()}") + + copy { + from frameworkDir.parentFile + into getXcodeConfigurationBuildDir() + include "${frameworkDir.name}/**" + include "${frameworkDir.name}.dSYM/**" + } + } +} + +private boolean isCalledFromXcode() { + project.hasProperty('calculator.configuration.name') && project.hasProperty('calculator.framework.location') +} + +private String getBuildTypeForXcode() { + project.properties['calculator.configuration.name'] as String +} + +private String getXcodeConfigurationBuildDir() { + project.properties['calculator.framework.location'] as String +} diff --git a/kotlin-native/samples/calculator/arithmeticParser/gradle.properties b/kotlin-native/samples/calculator/arithmeticParser/gradle.properties new file mode 100644 index 00000000000..7fc6f1ff272 --- /dev/null +++ b/kotlin-native/samples/calculator/arithmeticParser/gradle.properties @@ -0,0 +1 @@ +kotlin.code.style=official diff --git a/kotlin-native/samples/calculator/arithmeticParser/src/commonMain/kotlin/Parser.kt b/kotlin-native/samples/calculator/arithmeticParser/src/commonMain/kotlin/Parser.kt new file mode 100644 index 00000000000..b44bb7182c8 --- /dev/null +++ b/kotlin-native/samples/calculator/arithmeticParser/src/commonMain/kotlin/Parser.kt @@ -0,0 +1,284 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the license/LICENSE.txt file. + */ + +package sample.calculator.arithmeticparser + +fun parseAndCompute(expression: String): PartialParser.Result = + PartialParser(Calculator(), PartialRenderer()).parseWithPartial(expression) + +class Calculator : ExpressionComposer { + override fun number(value: Double) = value + override fun plus(left: Double, right: Double) = left + right + override fun minus(left: Double, right: Double) = left - right + override fun mult(left: Double, right: Double) = left * right + override fun div(left: Double, right: Double) = left / right +} + +class PartialRenderer : PartialExpressionComposer { + override fun missing() = "..." + + override fun ending(expression: Double) = "$expression ..." + + override fun plus(left: Double, partialRight: String) = "$left + $partialRight" + override fun minus(left: Double, partialRight: String) = "$left - $partialRight" + override fun mult(left: Double, partialRight: String) = "$left * $partialRight" + override fun div(left: Double, partialRight: String) = "$left / $partialRight" + override fun leftParenthesized(partialExpression: String) = "($partialExpression" +} + +interface ExpressionComposer { + fun number(value: Double): E + fun plus(left: E, right: E): E + fun minus(left: E, right: E): E + fun mult(left: E, right: E): E + fun div(left: E, right: E): E +} + +open class Parser(private val composer: ExpressionComposer) { + fun parse(expression: String): E? { + val tokenizer = Tokenizer(expression) + val prefix = parseAsPrefix(tokenizer) + + if (prefix is EndedWithExpression && !tokenizer.hasNext()) { + val reduced = prefix.reduced() + if (reduced.prefix is Empty) { + return reduced.expression + } + } + + return null + } + + internal fun parseAsPrefix(tokenizer: Tokenizer): ExpressionPrefix = + generateSequence>(Empty) { + it.tryExtend(tokenizer) + }.last() + + private fun ExpressionPrefix.tryExtend(tokenizer: Tokenizer): ExpressionPrefix? = when (this) { + is ContinuableWithExpression -> { + val number = tokenizer.tryReadNumber() + when { + number != null -> this.with(composer.number(number)) + tokenizer.tryReadLeftParenthesis() -> this.withLeftParenthesis() + else -> null + } + } + + is EndedWithExpression -> { + val operator = tokenizer.tryReadBinaryOperator() + if (operator != null) { + this.extendedWithOperator(operator) + } else { + val reduced = this.reduced() + if (reduced.prefix is EndedWithLeftParenthesis && tokenizer.tryReadRightParenthesis()) { + // Drop parens: + reduced.prefix.prefix.with(reduced.expression) + } else { + null + } + } + } + } + + private tailrec fun EndedWithExpression.extendedWithOperator(operator: BinaryOperator): EndedWithOperator = + if (this.prefix is EndedWithOperator && this.prefix.operator.precedence >= operator.precedence) { + // Apply the operator + this.prefix + .withOperatorApplied(this.expression) + .extendedWithOperator(operator) + } else { + EndedWithOperator(this.prefix, this.expression, operator) + } + + internal tailrec fun EndedWithExpression.reduced(): EndedWithExpression = when (this.prefix) { + Empty, is EndedWithLeftParenthesis -> this + + is EndedWithOperator -> + this.prefix + .withOperatorApplied(this.expression) + .reduced() + } + + private fun EndedWithOperator.withOperatorApplied(rightOperand: E) = + this.prefix.with(composer.compose(this.operator, this.leftOperand, rightOperand)) + + private fun ExpressionComposer.compose( + binaryOperator: BinaryOperator, left: E, right: E + ): E = when (binaryOperator) { + BinaryOperator.PLUS -> plus(left, right) + BinaryOperator.MINUS -> minus(left, right) + BinaryOperator.MULT -> mult(left, right) + BinaryOperator.DIV -> div(left, right) + } + +} + +interface PartialExpressionComposer { + fun missing(): PE + fun ending(expression: E): PE + + fun plus(left: E, partialRight: PE): PE + fun minus(left: E, partialRight: PE): PE + fun mult(left: E, partialRight: PE): PE + fun div(left: E, partialRight: PE): PE + + fun leftParenthesized(partialExpression: PE): PE +} + +class PartialParser( + composer: ExpressionComposer, + private val partialComposer: PartialExpressionComposer +) : Parser(composer) { + + data class Result(val expression: E?, val partialExpression: PE, val remainder: String?) + + fun parseWithPartial(expression: String): Result { + val tokenizer = Tokenizer(expression) + val prefix = parseAsPrefix(tokenizer) + + val remainder = tokenizer.getRemainder() + + return Result( + if (remainder != null) null else tryReduce(prefix), + prefix.toPartialExpression(), + remainder + ) + } + + private fun tryReduce(prefix: ExpressionPrefix): E? { + if (prefix is EndedWithExpression) { + val reduced = prefix.reduced() + if (reduced.prefix is Empty) { + return reduced.expression + } + } + + return null + } + + private fun ExpressionPrefix.toPartialExpression(): PE = when (this) { + is EndedWithExpression -> this.prefix.toPartialExpressionWith( + ending = partialComposer.ending(this.expression) + ) + is ContinuableWithExpression -> this.toPartialExpressionWith(ending = partialComposer.missing()) + } + + private tailrec fun ContinuableWithExpression.toPartialExpressionWith( + ending: PE + ): PE = when (this) { + Empty -> ending + + is EndedWithLeftParenthesis -> this.prefix.toPartialExpressionWith( + ending = partialComposer.leftParenthesized(ending) + ) + + is EndedWithOperator -> this.prefix.toPartialExpressionWith( + ending = partialComposer.compose(this.operator, this.leftOperand, ending) + ) + } + + private fun PartialExpressionComposer.compose( + binaryOperator: BinaryOperator, + left: E, + right: PE + ): PE = when (binaryOperator) { + BinaryOperator.PLUS -> plus(left, right) + BinaryOperator.MINUS -> minus(left, right) + BinaryOperator.MULT -> mult(left, right) + BinaryOperator.DIV -> div(left, right) + } +} + +/** + * Immutable prefix of expression partially parsed to combination of abstractly represented expressions. + * The prefix representation can be thought as "almost AST", i.e. AST with unfinished rightmost leaf + * (referenced by this object), and its nodes contain links to parent and (if needed) left child. + * + * @param E abstract representation of expression, e.g. its value, AST etc. + */ +internal sealed class ExpressionPrefix + +internal data class EndedWithExpression( + val prefix: ContinuableWithExpression, + val expression: E +) : ExpressionPrefix() + +internal sealed class ContinuableWithExpression : ExpressionPrefix() + +private fun ContinuableWithExpression.with(expression: E) = + EndedWithExpression(this, expression) + +private object Empty : ContinuableWithExpression() + +private data class EndedWithLeftParenthesis( + val prefix: ContinuableWithExpression +) : ContinuableWithExpression() + +private fun ContinuableWithExpression.withLeftParenthesis() = + EndedWithLeftParenthesis(this) + +private data class EndedWithOperator( + val prefix: ContinuableWithExpression, + val leftOperand: E, + val operator: BinaryOperator +) : ContinuableWithExpression() + +internal enum class BinaryOperator(val sign: Char, val precedence: Int) { + PLUS('+', 2), + MINUS('-', 2), + MULT('*', 3), + DIV('/', 3) +} + +internal class Tokenizer(private val expression: String) { + private var index = 0 + + init { + skipSpaces() + } + + fun hasNext(): Boolean = (index < expression.length) + + fun getRemainder(): String? = if (this.hasNext()) { + expression.substring(index) + } else { + null + } + + fun tryReadNumber(): Double? { + var endIndex = index + while (expression.getOrNull(endIndex)?.isNumberChar() == true) { + ++endIndex + } + + return expression.substring(index, endIndex).toDoubleOrNull()?.also { + index = endIndex + skipSpaces() + } + } + + private fun Char.isNumberChar(): Boolean = this in '0'..'9' || this == '.' + + fun tryReadBinaryOperator(): BinaryOperator? = BinaryOperator.values().firstOrNull { tryRead(it.sign) } + + fun tryReadLeftParenthesis(): Boolean = tryRead('(') + + fun tryReadRightParenthesis(): Boolean = tryRead(')') + + + private fun tryRead(char: Char): Boolean = if (hasNext() && expression[index] == char) { + ++index + skipSpaces() + true + } else { + false + } + + private fun skipSpaces() { + while (expression.getOrNull(index)?.isWhitespace() == true) { + ++index + } + } +} diff --git a/kotlin-native/samples/calculator/build.gradle b/kotlin-native/samples/calculator/build.gradle new file mode 100644 index 00000000000..9b4f0c9f682 --- /dev/null +++ b/kotlin-native/samples/calculator/build.gradle @@ -0,0 +1,24 @@ +buildscript { + repositories { + google() + jcenter() + mavenCentral() + maven { url 'https://dl.bintray.com/kotlin/kotlin-dev' } + maven { url 'https://dl.bintray.com/kotlin/kotlin-eap' } + } + + dependencies { + classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version" + classpath 'com.android.tools.build:gradle:3.5.0' + } +} + +allprojects { + repositories { + google() + jcenter() + mavenCentral() + maven { url 'https://dl.bintray.com/kotlin/kotlin-dev' } + maven { url 'https://dl.bintray.com/kotlin/kotlin-eap' } + } +} diff --git a/kotlin-native/samples/calculator/build.sh b/kotlin-native/samples/calculator/build.sh new file mode 100755 index 00000000000..a26f890f026 --- /dev/null +++ b/kotlin-native/samples/calculator/build.sh @@ -0,0 +1,5 @@ +#!/usr/bin/env bash + +DIR=$(cd "$(dirname "${BASH_SOURCE[0]}" )" && pwd ) + +$DIR/../gradlew -p $DIR assemble diff --git a/kotlin-native/samples/calculator/cliApp/build.gradle b/kotlin-native/samples/calculator/cliApp/build.gradle new file mode 100644 index 00000000000..cbd2cd14391 --- /dev/null +++ b/kotlin-native/samples/calculator/cliApp/build.gradle @@ -0,0 +1,22 @@ +apply plugin: 'org.jetbrains.kotlin.multiplatform' + +kotlin { + targets { + jvm() + } + + sourceSets { + jvmMain { + dependencies { + implementation project(':arithmeticParser') + } + } + } +} + +task runProgram(type: JavaExec) { + dependsOn assemble + main = 'sample.calculator.jvm.JvmCli' + classpath = files(kotlin.targets.jvm.compilations.main.output) + kotlin.targets.jvm.compilations.main.runtimeDependencyFiles + args '2 + 3' +} diff --git a/kotlin-native/samples/calculator/cliApp/gradle.properties b/kotlin-native/samples/calculator/cliApp/gradle.properties new file mode 100644 index 00000000000..790a07d5124 --- /dev/null +++ b/kotlin-native/samples/calculator/cliApp/gradle.properties @@ -0,0 +1,2 @@ +kotlin.code.style=official +kotlin.import.noCommonSourceSets=true diff --git a/kotlin-native/samples/calculator/cliApp/src/jvmMain/kotlin/JvmCli.kt b/kotlin-native/samples/calculator/cliApp/src/jvmMain/kotlin/JvmCli.kt new file mode 100644 index 00000000000..f3554b27666 --- /dev/null +++ b/kotlin-native/samples/calculator/cliApp/src/jvmMain/kotlin/JvmCli.kt @@ -0,0 +1,31 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the license/LICENSE.txt file. + */ +@file:JvmName("JvmCli") + +package sample.calculator.jvm + +import sample.calculator.arithmeticparser.parseAndCompute + +fun main(args: Array) { + val expression = if (args.isNotEmpty()) { + args.first().also { + print(it) + } + } else { + println("Enter an expression:") + readLine()!! + } + + val result = parseAndCompute(expression) + val computed = result.expression + if (computed != null) { + println(" = $computed") + } else { + println(" = ${result.partialExpression}") + result.remainder?.let { + println("Unable to parse suffix: $it") + } + } +} diff --git a/kotlin-native/samples/calculator/gradle.properties b/kotlin-native/samples/calculator/gradle.properties new file mode 100644 index 00000000000..146d025d3e9 --- /dev/null +++ b/kotlin-native/samples/calculator/gradle.properties @@ -0,0 +1,15 @@ +kotlin.code.style=official + +# Run parallel builds in Gradle: +org.gradle.parallel=true +org.gradle.workers.max=4 + +# Pin Kotlin version: +# CHANGE_VERSION_WITH_RELEASE +kotlin_version=1.4.10 + +# Use custom Kotlin/Native home: +kotlin.native.home=../../../dist + +# Increase memory for in-process compiler execution. +org.gradle.jvmargs=-Xmx3g diff --git a/kotlin-native/samples/calculator/gradle/wrapper/gradle-wrapper.jar b/kotlin-native/samples/calculator/gradle/wrapper/gradle-wrapper.jar new file mode 100644 index 00000000000..e708b1c023e Binary files /dev/null and b/kotlin-native/samples/calculator/gradle/wrapper/gradle-wrapper.jar differ diff --git a/kotlin-native/samples/calculator/gradle/wrapper/gradle-wrapper.properties b/kotlin-native/samples/calculator/gradle/wrapper/gradle-wrapper.properties new file mode 100644 index 00000000000..12d38de6a48 --- /dev/null +++ b/kotlin-native/samples/calculator/gradle/wrapper/gradle-wrapper.properties @@ -0,0 +1,5 @@ +distributionBase=GRADLE_USER_HOME +distributionPath=wrapper/dists +distributionUrl=https\://services.gradle.org/distributions/gradle-6.6.1-bin.zip +zipStoreBase=GRADLE_USER_HOME +zipStorePath=wrapper/dists diff --git a/kotlin-native/samples/calculator/gradlew b/kotlin-native/samples/calculator/gradlew new file mode 100755 index 00000000000..4f906e0c811 --- /dev/null +++ b/kotlin-native/samples/calculator/gradlew @@ -0,0 +1,185 @@ +#!/usr/bin/env sh + +# +# Copyright 2015 the original author or authors. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# https://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +############################################################################## +## +## Gradle start up script for UN*X +## +############################################################################## + +# Attempt to set APP_HOME +# Resolve links: $0 may be a link +PRG="$0" +# Need this for relative symlinks. +while [ -h "$PRG" ] ; do + ls=`ls -ld "$PRG"` + link=`expr "$ls" : '.*-> \(.*\)$'` + if expr "$link" : '/.*' > /dev/null; then + PRG="$link" + else + PRG=`dirname "$PRG"`"/$link" + fi +done +SAVED="`pwd`" +cd "`dirname \"$PRG\"`/" >/dev/null +APP_HOME="`pwd -P`" +cd "$SAVED" >/dev/null + +APP_NAME="Gradle" +APP_BASE_NAME=`basename "$0"` + +# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"' + +# Use the maximum available, or set MAX_FD != -1 to use that value. +MAX_FD="maximum" + +warn () { + echo "$*" +} + +die () { + echo + echo "$*" + echo + exit 1 +} + +# OS specific support (must be 'true' or 'false'). +cygwin=false +msys=false +darwin=false +nonstop=false +case "`uname`" in + CYGWIN* ) + cygwin=true + ;; + Darwin* ) + darwin=true + ;; + MINGW* ) + msys=true + ;; + NONSTOP* ) + nonstop=true + ;; +esac + +CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar + + +# Determine the Java command to use to start the JVM. +if [ -n "$JAVA_HOME" ] ; then + if [ -x "$JAVA_HOME/jre/sh/java" ] ; then + # IBM's JDK on AIX uses strange locations for the executables + JAVACMD="$JAVA_HOME/jre/sh/java" + else + JAVACMD="$JAVA_HOME/bin/java" + fi + if [ ! -x "$JAVACMD" ] ; then + die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME + +Please set the JAVA_HOME variable in your environment to match the +location of your Java installation." + fi +else + JAVACMD="java" + which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. + +Please set the JAVA_HOME variable in your environment to match the +location of your Java installation." +fi + +# Increase the maximum file descriptors if we can. +if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then + MAX_FD_LIMIT=`ulimit -H -n` + if [ $? -eq 0 ] ; then + if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then + MAX_FD="$MAX_FD_LIMIT" + fi + ulimit -n $MAX_FD + if [ $? -ne 0 ] ; then + warn "Could not set maximum file descriptor limit: $MAX_FD" + fi + else + warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT" + fi +fi + +# For Darwin, add options to specify how the application appears in the dock +if $darwin; then + GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\"" +fi + +# For Cygwin or MSYS, switch paths to Windows format before running java +if [ "$cygwin" = "true" -o "$msys" = "true" ] ; then + APP_HOME=`cygpath --path --mixed "$APP_HOME"` + CLASSPATH=`cygpath --path --mixed "$CLASSPATH"` + + JAVACMD=`cygpath --unix "$JAVACMD"` + + # We build the pattern for arguments to be converted via cygpath + ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null` + SEP="" + for dir in $ROOTDIRSRAW ; do + ROOTDIRS="$ROOTDIRS$SEP$dir" + SEP="|" + done + OURCYGPATTERN="(^($ROOTDIRS))" + # Add a user-defined pattern to the cygpath arguments + if [ "$GRADLE_CYGPATTERN" != "" ] ; then + OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)" + fi + # Now convert the arguments - kludge to limit ourselves to /bin/sh + i=0 + for arg in "$@" ; do + CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -` + CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option + + if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition + eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"` + else + eval `echo args$i`="\"$arg\"" + fi + i=`expr $i + 1` + done + case $i in + 0) set -- ;; + 1) set -- "$args0" ;; + 2) set -- "$args0" "$args1" ;; + 3) set -- "$args0" "$args1" "$args2" ;; + 4) set -- "$args0" "$args1" "$args2" "$args3" ;; + 5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;; + 6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;; + 7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;; + 8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;; + 9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;; + esac +fi + +# Escape application args +save () { + for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done + echo " " +} +APP_ARGS=`save "$@"` + +# Collect all arguments for the java command, following the shell quoting and substitution rules +eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS" + +exec "$JAVACMD" "$@" diff --git a/kotlin-native/samples/calculator/gradlew.bat b/kotlin-native/samples/calculator/gradlew.bat new file mode 100644 index 00000000000..ac1b06f9382 --- /dev/null +++ b/kotlin-native/samples/calculator/gradlew.bat @@ -0,0 +1,89 @@ +@rem +@rem Copyright 2015 the original author or authors. +@rem +@rem Licensed under the Apache License, Version 2.0 (the "License"); +@rem you may not use this file except in compliance with the License. +@rem You may obtain a copy of the License at +@rem +@rem https://www.apache.org/licenses/LICENSE-2.0 +@rem +@rem Unless required by applicable law or agreed to in writing, software +@rem distributed under the License is distributed on an "AS IS" BASIS, +@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +@rem See the License for the specific language governing permissions and +@rem limitations under the License. +@rem + +@if "%DEBUG%" == "" @echo off +@rem ########################################################################## +@rem +@rem Gradle startup script for Windows +@rem +@rem ########################################################################## + +@rem Set local scope for the variables with windows NT shell +if "%OS%"=="Windows_NT" setlocal + +set DIRNAME=%~dp0 +if "%DIRNAME%" == "" set DIRNAME=. +set APP_BASE_NAME=%~n0 +set APP_HOME=%DIRNAME% + +@rem Resolve any "." and ".." in APP_HOME to make it shorter. +for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi + +@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m" + +@rem Find java.exe +if defined JAVA_HOME goto findJavaFromJavaHome + +set JAVA_EXE=java.exe +%JAVA_EXE% -version >NUL 2>&1 +if "%ERRORLEVEL%" == "0" goto execute + +echo. +echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. +echo. +echo Please set the JAVA_HOME variable in your environment to match the +echo location of your Java installation. + +goto fail + +:findJavaFromJavaHome +set JAVA_HOME=%JAVA_HOME:"=% +set JAVA_EXE=%JAVA_HOME%/bin/java.exe + +if exist "%JAVA_EXE%" goto execute + +echo. +echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% +echo. +echo Please set the JAVA_HOME variable in your environment to match the +echo location of your Java installation. + +goto fail + +:execute +@rem Setup the command line + +set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar + + +@rem Execute Gradle +"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %* + +:end +@rem End local scope for the variables with windows NT shell +if "%ERRORLEVEL%"=="0" goto mainEnd + +:fail +rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of +rem the _cmd.exe /c_ return code! +if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 +exit /b 1 + +:mainEnd +if "%OS%"=="Windows_NT" endlocal + +:omega diff --git a/kotlin-native/samples/calculator/iosApp/calculator.xcodeproj/project.pbxproj b/kotlin-native/samples/calculator/iosApp/calculator.xcodeproj/project.pbxproj new file mode 100644 index 00000000000..7f85ccaa88e --- /dev/null +++ b/kotlin-native/samples/calculator/iosApp/calculator.xcodeproj/project.pbxproj @@ -0,0 +1,519 @@ +// !$*UTF8*$! +{ + archiveVersion = 1; + classes = { + }; + objectVersion = 48; + objects = { + +/* Begin PBXBuildFile section */ + 2C3F38451FD1738300151601 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2C3F38441FD1738300151601 /* AppDelegate.swift */; }; + 2C3F38471FD1738300151601 /* ViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2C3F38461FD1738300151601 /* ViewController.swift */; }; + 2C3F384A1FD1738300151601 /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 2C3F38481FD1738300151601 /* Main.storyboard */; }; + 2C3F384C1FD1738300151601 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 2C3F384B1FD1738300151601 /* Assets.xcassets */; }; + 2C3F384F1FD1738300151601 /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 2C3F384D1FD1738300151601 /* LaunchScreen.storyboard */; }; + 7FE128BF205854BA0064CE74 /* arithmeticParser.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 7FF94AD92058464C00590D0D /* arithmeticParser.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; }; + 7FF94AE32058483900590D0D /* arithmeticParser.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 7FF94AD92058464C00590D0D /* arithmeticParser.framework */; }; +/* End PBXBuildFile section */ + +/* Begin PBXContainerItemProxy section */ + 2C10D2172521E5AA001EB717 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 2C3F38391FD1738300151601 /* Project object */; + proxyType = 1; + remoteGlobalIDString = 7FF94AD82058464C00590D0D; + remoteInfo = arithmeticParser; + }; +/* End PBXContainerItemProxy section */ + +/* Begin PBXCopyFilesBuildPhase section */ + 7FE128BE2058549E0064CE74 /* Embed Frameworks */ = { + isa = PBXCopyFilesBuildPhase; + buildActionMask = 2147483647; + dstPath = ""; + dstSubfolderSpec = 10; + files = ( + 7FE128BF205854BA0064CE74 /* arithmeticParser.framework in Embed Frameworks */, + ); + name = "Embed Frameworks"; + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXCopyFilesBuildPhase section */ + +/* Begin PBXFileReference section */ + 2C3F38411FD1738300151601 /* KotlinCalculator.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = KotlinCalculator.app; sourceTree = BUILT_PRODUCTS_DIR; }; + 2C3F38441FD1738300151601 /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; }; + 2C3F38461FD1738300151601 /* ViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ViewController.swift; sourceTree = ""; }; + 2C3F38491FD1738300151601 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = ""; }; + 2C3F384B1FD1738300151601 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; + 2C3F384E1FD1738300151601 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = ""; }; + 2C3F38501FD1738300151601 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; + 7FF94AD92058464C00590D0D /* arithmeticParser.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = arithmeticParser.framework; sourceTree = BUILT_PRODUCTS_DIR; }; + 7FF94AEA2058485300590D0D /* Parser.kt */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = Parser.kt; sourceTree = ""; }; +/* End PBXFileReference section */ + +/* Begin PBXFrameworksBuildPhase section */ + 2C3F383E1FD1738300151601 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + 7FF94AE32058483900590D0D /* arithmeticParser.framework in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXFrameworksBuildPhase section */ + +/* Begin PBXGroup section */ + 2C3F38381FD1738300151601 = { + isa = PBXGroup; + children = ( + 2C3F38431FD1738300151601 /* calculator */, + 7FF94ADA2058464C00590D0D /* arithmeticParser */, + 2C3F38421FD1738300151601 /* Products */, + 7FF94AE22058483900590D0D /* Frameworks */, + ); + sourceTree = ""; + }; + 2C3F38421FD1738300151601 /* Products */ = { + isa = PBXGroup; + children = ( + 2C3F38411FD1738300151601 /* KotlinCalculator.app */, + 7FF94AD92058464C00590D0D /* arithmeticParser.framework */, + ); + name = Products; + sourceTree = ""; + }; + 2C3F38431FD1738300151601 /* calculator */ = { + isa = PBXGroup; + children = ( + 2C3F38441FD1738300151601 /* AppDelegate.swift */, + 2C3F38461FD1738300151601 /* ViewController.swift */, + 2C3F38481FD1738300151601 /* Main.storyboard */, + 2C3F384B1FD1738300151601 /* Assets.xcassets */, + 2C3F384D1FD1738300151601 /* LaunchScreen.storyboard */, + 2C3F38501FD1738300151601 /* Info.plist */, + ); + path = calculator; + sourceTree = ""; + }; + 7FF94ADA2058464C00590D0D /* arithmeticParser */ = { + isa = PBXGroup; + children = ( + 7FF94AE42058485300590D0D /* src */, + ); + name = arithmeticParser; + sourceTree = ""; + }; + 7FF94AE22058483900590D0D /* Frameworks */ = { + isa = PBXGroup; + children = ( + ); + name = Frameworks; + sourceTree = ""; + }; + 7FF94AE42058485300590D0D /* src */ = { + isa = PBXGroup; + children = ( + 7FF94AE52058485300590D0D /* commonMain */, + ); + name = src; + path = ../arithmeticParser/src; + sourceTree = SOURCE_ROOT; + }; + 7FF94AE52058485300590D0D /* commonMain */ = { + isa = PBXGroup; + children = ( + 7FF94AE62058485300590D0D /* kotlin */, + ); + path = commonMain; + sourceTree = ""; + }; + 7FF94AE62058485300590D0D /* kotlin */ = { + isa = PBXGroup; + children = ( + 7FF94AEA2058485300590D0D /* Parser.kt */, + ); + path = kotlin; + sourceTree = ""; + }; +/* End PBXGroup section */ + +/* Begin PBXNativeTarget section */ + 2C3F38401FD1738300151601 /* KotlinCalculator */ = { + isa = PBXNativeTarget; + buildConfigurationList = 2C3F38531FD1738300151601 /* Build configuration list for PBXNativeTarget "KotlinCalculator" */; + buildPhases = ( + 2C3F383D1FD1738300151601 /* Sources */, + 2C3F383E1FD1738300151601 /* Frameworks */, + 2C3F383F1FD1738300151601 /* Resources */, + 7FE128BE2058549E0064CE74 /* Embed Frameworks */, + ); + buildRules = ( + ); + dependencies = ( + 2C10D2182521E5AA001EB717 /* PBXTargetDependency */, + ); + name = KotlinCalculator; + productName = calculator; + productReference = 2C3F38411FD1738300151601 /* KotlinCalculator.app */; + productType = "com.apple.product-type.application"; + }; + 7FF94AD82058464C00590D0D /* arithmeticParser */ = { + isa = PBXNativeTarget; + buildConfigurationList = 7FF94ADE2058464C00590D0D /* Build configuration list for PBXNativeTarget "arithmeticParser" */; + buildPhases = ( + 7FF94AE12058466D00590D0D /* Compile Kotlin/Native */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = arithmeticParser; + productName = arithmeticParser; + productReference = 7FF94AD92058464C00590D0D /* arithmeticParser.framework */; + productType = "com.apple.product-type.framework"; + }; +/* End PBXNativeTarget section */ + +/* Begin PBXProject section */ + 2C3F38391FD1738300151601 /* Project object */ = { + isa = PBXProject; + attributes = { + LastSwiftUpdateCheck = 0900; + LastUpgradeCheck = 0900; + ORGANIZATIONNAME = JetBrains; + TargetAttributes = { + 2C3F38401FD1738300151601 = { + CreatedOnToolsVersion = 9.0; + ProvisioningStyle = Automatic; + }; + 7FF94AD82058464C00590D0D = { + CreatedOnToolsVersion = 9.2; + ProvisioningStyle = Automatic; + }; + }; + }; + buildConfigurationList = 2C3F383C1FD1738300151601 /* Build configuration list for PBXProject "calculator" */; + compatibilityVersion = "Xcode 8.0"; + developmentRegion = en; + hasScannedForEncodings = 0; + knownRegions = ( + en, + Base, + ); + mainGroup = 2C3F38381FD1738300151601; + productRefGroup = 2C3F38421FD1738300151601 /* Products */; + projectDirPath = ""; + projectRoot = ""; + targets = ( + 2C3F38401FD1738300151601 /* KotlinCalculator */, + 7FF94AD82058464C00590D0D /* arithmeticParser */, + ); + }; +/* End PBXProject section */ + +/* Begin PBXResourcesBuildPhase section */ + 2C3F383F1FD1738300151601 /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 2C3F384F1FD1738300151601 /* LaunchScreen.storyboard in Resources */, + 2C3F384C1FD1738300151601 /* Assets.xcassets in Resources */, + 2C3F384A1FD1738300151601 /* Main.storyboard in Resources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXResourcesBuildPhase section */ + +/* Begin PBXShellScriptBuildPhase section */ + 7FF94AE12058466D00590D0D /* Compile Kotlin/Native */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputPaths = ( + ); + name = "Compile Kotlin/Native"; + outputPaths = ( + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "\"$SRCROOT/../gradlew\" -p \"$SRCROOT/..\" buildFrameworkForXcode \\\n-Pcalculator.preset.name=\"$KOTLIN_NATIVE_PRESET\" \\\n-Pcalculator.configuration.name=\"$CONFIGURATION\" \\\n-Pcalculator.framework.location=\"$CONFIGURATION_BUILD_DIR\"\n"; + }; +/* End PBXShellScriptBuildPhase section */ + +/* Begin PBXSourcesBuildPhase section */ + 2C3F383D1FD1738300151601 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 2C3F38471FD1738300151601 /* ViewController.swift in Sources */, + 2C3F38451FD1738300151601 /* AppDelegate.swift in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXSourcesBuildPhase section */ + +/* Begin PBXTargetDependency section */ + 2C10D2182521E5AA001EB717 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = 7FF94AD82058464C00590D0D /* arithmeticParser */; + targetProxy = 2C10D2172521E5AA001EB717 /* PBXContainerItemProxy */; + }; +/* End PBXTargetDependency section */ + +/* Begin PBXVariantGroup section */ + 2C3F38481FD1738300151601 /* Main.storyboard */ = { + isa = PBXVariantGroup; + children = ( + 2C3F38491FD1738300151601 /* Base */, + ); + name = Main.storyboard; + sourceTree = ""; + }; + 2C3F384D1FD1738300151601 /* LaunchScreen.storyboard */ = { + isa = PBXVariantGroup; + children = ( + 2C3F384E1FD1738300151601 /* Base */, + ); + name = LaunchScreen.storyboard; + sourceTree = ""; + }; +/* End PBXVariantGroup section */ + +/* Begin XCBuildConfiguration section */ + 2C3F38511FD1738300151601 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ANALYZER_NONNULL = YES; + CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_DOCUMENTATION_COMMENTS = YES; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + CODE_SIGN_IDENTITY = "iPhone Developer"; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = dwarf; + ENABLE_STRICT_OBJC_MSGSEND = YES; + ENABLE_TESTABILITY = YES; + GCC_C_LANGUAGE_STANDARD = gnu11; + GCC_DYNAMIC_NO_PIC = NO; + GCC_NO_COMMON_BLOCKS = YES; + GCC_OPTIMIZATION_LEVEL = 0; + GCC_PREPROCESSOR_DEFINITIONS = ( + "DEBUG=1", + "$(inherited)", + ); + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + IPHONEOS_DEPLOYMENT_TARGET = 11.0; + MTL_ENABLE_DEBUG_INFO = YES; + ONLY_ACTIVE_ARCH = YES; + SDKROOT = iphoneos; + SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG; + SWIFT_OPTIMIZATION_LEVEL = "-Onone"; + }; + name = Debug; + }; + 2C3F38521FD1738300151601 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ANALYZER_NONNULL = YES; + CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_DOCUMENTATION_COMMENTS = YES; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + CODE_SIGN_IDENTITY = "iPhone Developer"; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + ENABLE_NS_ASSERTIONS = NO; + ENABLE_STRICT_OBJC_MSGSEND = YES; + GCC_C_LANGUAGE_STANDARD = gnu11; + GCC_NO_COMMON_BLOCKS = YES; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + IPHONEOS_DEPLOYMENT_TARGET = 11.0; + MTL_ENABLE_DEBUG_INFO = NO; + SDKROOT = iphoneos; + SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule"; + VALIDATE_PRODUCT = YES; + }; + name = Release; + }; + 2C3F38541FD1738300151601 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CODE_SIGN_STYLE = Automatic; + DEVELOPMENT_TEAM = ""; + ENABLE_BITCODE = NO; + FRAMEWORK_SEARCH_PATHS = $BUILT_PRODUCTS_DIR; + INFOPLIST_FILE = calculator/Info.plist; + IPHONEOS_DEPLOYMENT_TARGET = 11.0; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; + PRODUCT_BUNDLE_IDENTIFIER = org.jetbrains.konan.calculator; + PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_VERSION = 4.0; + TARGETED_DEVICE_FAMILY = "1,2"; + }; + name = Debug; + }; + 2C3F38551FD1738300151601 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CODE_SIGN_STYLE = Automatic; + DEVELOPMENT_TEAM = ""; + ENABLE_BITCODE = NO; + FRAMEWORK_SEARCH_PATHS = $BUILT_PRODUCTS_DIR; + INFOPLIST_FILE = calculator/Info.plist; + IPHONEOS_DEPLOYMENT_TARGET = 11.0; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; + PRODUCT_BUNDLE_IDENTIFIER = org.jetbrains.konan.calculator; + PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_VERSION = 4.0; + TARGETED_DEVICE_FAMILY = "1,2"; + }; + name = Release; + }; + 7FF94ADF2058464C00590D0D /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + CODE_SIGN_IDENTITY = ""; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; + CODE_SIGN_STYLE = Automatic; + CURRENT_PROJECT_VERSION = 1; + DEVELOPMENT_TEAM = ""; + DYLIB_COMPATIBILITY_VERSION = 1; + DYLIB_CURRENT_VERSION = 1; + DYLIB_INSTALL_NAME_BASE = "@rpath"; + INFOPLIST_FILE = "$(SRCROOT)/../arithmeticParser/Info.plist"; + INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; + IPHONEOS_DEPLOYMENT_TARGET = 11.2; + "KOTLIN_NATIVE_PRESET[sdk=iphoneos*]" = iosArm64; + "KOTLIN_NATIVE_PRESET[sdk=iphonesimulator*]" = iosX64; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; + PRODUCT_BUNDLE_IDENTIFIER = JetBrains.arithmeticParser; + PRODUCT_MODULE_NAME = "_$(PRODUCT_NAME:c99extidentifier)"; + PRODUCT_NAME = "$(TARGET_NAME:c99extidentifier)"; + PROVISIONING_PROFILE_SPECIFIER = ""; + SKIP_INSTALL = YES; + TARGETED_DEVICE_FAMILY = "1,2"; + VALID_ARCHS = arm64; + VERSIONING_SYSTEM = "apple-generic"; + VERSION_INFO_PREFIX = ""; + }; + name = Debug; + }; + 7FF94AE02058464C00590D0D /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + CODE_SIGN_IDENTITY = ""; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; + CODE_SIGN_STYLE = Automatic; + CURRENT_PROJECT_VERSION = 1; + DEVELOPMENT_TEAM = ""; + DYLIB_COMPATIBILITY_VERSION = 1; + DYLIB_CURRENT_VERSION = 1; + DYLIB_INSTALL_NAME_BASE = "@rpath"; + INFOPLIST_FILE = "$(SRCROOT)/../arithmeticParser/Info.plist"; + INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; + IPHONEOS_DEPLOYMENT_TARGET = 11.2; + "KOTLIN_NATIVE_PRESET[sdk=iphoneos*]" = iosArm64; + "KOTLIN_NATIVE_PRESET[sdk=iphonesimulator*]" = iosX64; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; + PRODUCT_BUNDLE_IDENTIFIER = JetBrains.arithmeticParser; + PRODUCT_MODULE_NAME = "_$(PRODUCT_NAME:c99extidentifier)"; + PRODUCT_NAME = "$(TARGET_NAME:c99extidentifier)"; + PROVISIONING_PROFILE_SPECIFIER = ""; + SKIP_INSTALL = YES; + TARGETED_DEVICE_FAMILY = "1,2"; + VALID_ARCHS = arm64; + VERSIONING_SYSTEM = "apple-generic"; + VERSION_INFO_PREFIX = ""; + }; + name = Release; + }; +/* End XCBuildConfiguration section */ + +/* Begin XCConfigurationList section */ + 2C3F383C1FD1738300151601 /* Build configuration list for PBXProject "calculator" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 2C3F38511FD1738300151601 /* Debug */, + 2C3F38521FD1738300151601 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 2C3F38531FD1738300151601 /* Build configuration list for PBXNativeTarget "KotlinCalculator" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 2C3F38541FD1738300151601 /* Debug */, + 2C3F38551FD1738300151601 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 7FF94ADE2058464C00590D0D /* Build configuration list for PBXNativeTarget "arithmeticParser" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 7FF94ADF2058464C00590D0D /* Debug */, + 7FF94AE02058464C00590D0D /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; +/* End XCConfigurationList section */ + }; + rootObject = 2C3F38391FD1738300151601 /* Project object */; +} diff --git a/kotlin-native/samples/calculator/iosApp/calculator.xcodeproj/project.xcworkspace/contents.xcworkspacedata b/kotlin-native/samples/calculator/iosApp/calculator.xcodeproj/project.xcworkspace/contents.xcworkspacedata new file mode 100644 index 00000000000..7527b6e65d4 --- /dev/null +++ b/kotlin-native/samples/calculator/iosApp/calculator.xcodeproj/project.xcworkspace/contents.xcworkspacedata @@ -0,0 +1,7 @@ + + + + + diff --git a/kotlin-native/samples/calculator/iosApp/calculator.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist b/kotlin-native/samples/calculator/iosApp/calculator.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist new file mode 100644 index 00000000000..18d981003d6 --- /dev/null +++ b/kotlin-native/samples/calculator/iosApp/calculator.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist @@ -0,0 +1,8 @@ + + + + + IDEDidComputeMac32BitWarning + + + diff --git a/kotlin-native/samples/calculator/iosApp/calculator/AppDelegate.swift b/kotlin-native/samples/calculator/iosApp/calculator/AppDelegate.swift new file mode 100644 index 00000000000..b813994f762 --- /dev/null +++ b/kotlin-native/samples/calculator/iosApp/calculator/AppDelegate.swift @@ -0,0 +1,43 @@ +// +// Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license +// that can be found in the license/LICENSE.txt file. +// + +import UIKit + +@UIApplicationMain +class AppDelegate: UIResponder, UIApplicationDelegate { + + var window: UIWindow? + + + func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool { + // Override point for customization after application launch. + return true + } + + func applicationWillResignActive(_ application: UIApplication) { + // Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state. + // Use this method to pause ongoing tasks, disable timers, and invalidate graphics rendering callbacks. Games should use this method to pause the game. + } + + func applicationDidEnterBackground(_ application: UIApplication) { + // Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later. + // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits. + } + + func applicationWillEnterForeground(_ application: UIApplication) { + // Called as part of the transition from the background to the active state; here you can undo many of the changes made on entering the background. + } + + func applicationDidBecomeActive(_ application: UIApplication) { + // Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface. + } + + func applicationWillTerminate(_ application: UIApplication) { + // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:. + } + + +} + diff --git a/kotlin-native/samples/calculator/iosApp/calculator/Assets.xcassets/AppIcon.appiconset/Contents.json b/kotlin-native/samples/calculator/iosApp/calculator/Assets.xcassets/AppIcon.appiconset/Contents.json new file mode 100644 index 00000000000..d8db8d65fd7 --- /dev/null +++ b/kotlin-native/samples/calculator/iosApp/calculator/Assets.xcassets/AppIcon.appiconset/Contents.json @@ -0,0 +1,98 @@ +{ + "images" : [ + { + "idiom" : "iphone", + "size" : "20x20", + "scale" : "2x" + }, + { + "idiom" : "iphone", + "size" : "20x20", + "scale" : "3x" + }, + { + "idiom" : "iphone", + "size" : "29x29", + "scale" : "2x" + }, + { + "idiom" : "iphone", + "size" : "29x29", + "scale" : "3x" + }, + { + "idiom" : "iphone", + "size" : "40x40", + "scale" : "2x" + }, + { + "idiom" : "iphone", + "size" : "40x40", + "scale" : "3x" + }, + { + "idiom" : "iphone", + "size" : "60x60", + "scale" : "2x" + }, + { + "idiom" : "iphone", + "size" : "60x60", + "scale" : "3x" + }, + { + "idiom" : "ipad", + "size" : "20x20", + "scale" : "1x" + }, + { + "idiom" : "ipad", + "size" : "20x20", + "scale" : "2x" + }, + { + "idiom" : "ipad", + "size" : "29x29", + "scale" : "1x" + }, + { + "idiom" : "ipad", + "size" : "29x29", + "scale" : "2x" + }, + { + "idiom" : "ipad", + "size" : "40x40", + "scale" : "1x" + }, + { + "idiom" : "ipad", + "size" : "40x40", + "scale" : "2x" + }, + { + "idiom" : "ipad", + "size" : "76x76", + "scale" : "1x" + }, + { + "idiom" : "ipad", + "size" : "76x76", + "scale" : "2x" + }, + { + "idiom" : "ipad", + "size" : "83.5x83.5", + "scale" : "2x" + }, + { + "idiom" : "ios-marketing", + "size" : "1024x1024", + "scale" : "1x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/kotlin-native/samples/calculator/iosApp/calculator/Base.lproj/LaunchScreen.storyboard b/kotlin-native/samples/calculator/iosApp/calculator/Base.lproj/LaunchScreen.storyboard new file mode 100644 index 00000000000..f83f6fd5810 --- /dev/null +++ b/kotlin-native/samples/calculator/iosApp/calculator/Base.lproj/LaunchScreen.storyboard @@ -0,0 +1,25 @@ + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/kotlin-native/samples/calculator/iosApp/calculator/Base.lproj/Main.storyboard b/kotlin-native/samples/calculator/iosApp/calculator/Base.lproj/Main.storyboard new file mode 100644 index 00000000000..72546e9149b --- /dev/null +++ b/kotlin-native/samples/calculator/iosApp/calculator/Base.lproj/Main.storyboard @@ -0,0 +1,100 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/kotlin-native/samples/calculator/iosApp/calculator/Info.plist b/kotlin-native/samples/calculator/iosApp/calculator/Info.plist new file mode 100644 index 00000000000..88282c39cb6 --- /dev/null +++ b/kotlin-native/samples/calculator/iosApp/calculator/Info.plist @@ -0,0 +1,45 @@ + + + + + CFBundleDevelopmentRegion + $(DEVELOPMENT_LANGUAGE) + CFBundleDisplayName + KotlinCalc + CFBundleExecutable + $(EXECUTABLE_NAME) + CFBundleIdentifier + $(PRODUCT_BUNDLE_IDENTIFIER) + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + $(PRODUCT_NAME) + CFBundlePackageType + APPL + CFBundleShortVersionString + 1.0 + CFBundleVersion + 1 + LSRequiresIPhoneOS + + UILaunchStoryboardName + LaunchScreen + UIMainStoryboardFile + Main + UIRequiredDeviceCapabilities + + armv7 + + UISupportedInterfaceOrientations + + UIInterfaceOrientationPortrait + + UISupportedInterfaceOrientations~ipad + + UIInterfaceOrientationPortrait + UIInterfaceOrientationPortraitUpsideDown + UIInterfaceOrientationLandscapeLeft + UIInterfaceOrientationLandscapeRight + + + diff --git a/kotlin-native/samples/calculator/iosApp/calculator/ViewController.swift b/kotlin-native/samples/calculator/iosApp/calculator/ViewController.swift new file mode 100644 index 00000000000..8e15fbfc2cf --- /dev/null +++ b/kotlin-native/samples/calculator/iosApp/calculator/ViewController.swift @@ -0,0 +1,154 @@ +// +// Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license +// that can be found in the license/LICENSE.txt file. +// + +import UIKit +import arithmeticParser + +class ViewController: UIViewController, UITextViewDelegate, UICollectionViewDataSource { + + override func viewDidLoad() { + super.viewDidLoad() + // Do any additional setup after loading the view, typically from a nib. + numpad.dataSource = self + self.input.delegate = self + inputDidChange() + } + + override func didReceiveMemoryWarning() { + super.didReceiveMemoryWarning() + // Dispose of any resources that can be recreated. + } + + @IBOutlet var partialResult: UILabel! + @IBOutlet var result: UILabel! + @IBOutlet var input: UITextView! + @IBOutlet var numpad: UICollectionView! + + private let parser = PartialParser( + composer: Calculator(), + partialComposer: PartialRenderer() + ) + + @IBAction func numpadButtonPressed(_ sender: UIButton) { + let title = sender.currentTitle! + if title == "" { + return + } + + if title == "⌫" { + if !input.text.isEmpty { + input.text.removeLast() + } + } else { + input.text.append(title) + } + + inputDidChange() + } + + func textViewDidChange(_ textView: UITextView) { + if textView === input { + inputDidChange() + } + } + + override func touchesBegan(_ touches: Set, with event: UIEvent?) { + self.input.endEditing(true) + } + + private func inputDidChange() { + let parsed = parser.parseWithPartial(expression: input.text) + if let resultValue = parsed.expression { + result.text = "= \(resultValue)" + } else { + result.text = "" + } + + let attributedText = parsed.partialExpression + + if let remainder = parsed.remainder { + partialResult.attributedText = attributedText + + NSAttributedString(string: " ") + + NSAttributedString(string: remainder, attributes: + [.foregroundColor: UIColor.red, + .font: UIFont.boldSystemFont(ofSize: partialResult.font.pointSize)]) + } else { + partialResult.attributedText = attributedText + } + } + + private let buttons = [ + "7", "8", "9", "/", + "4", "5", "6", "*", + "1", "2", "3", "-", + ".", "0", "", "+", + "(", ")", "", "⌫" + ] + + func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int { + return buttons.count + } + + func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell { + let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "buttonCell", for: indexPath) + + (cell.viewWithTag(1) as! UIButton).setTitle(buttons[indexPath.item],for: .normal) + + return cell + } +} + +private func +(left: NSAttributedString, right: NSAttributedString) -> NSAttributedString { + let result = NSMutableAttributedString(attributedString: left) + result.append(right) + return result +} + +private extension String { + func toAttributed() -> NSAttributedString { + return NSAttributedString(string: self) + } +} + +private class PartialRenderer: NSObject, PartialExpressionComposer { + func missing() -> Any { + return "... ".toAttributed() + } + + func ending(expression: Any) -> Any { + return "\(formatDouble(expression))... ".toAttributed() + } + + func plus(left: Any, partialRight: Any) -> Any { + return compose("+", left, partialRight) + } + + func minus(left: Any, partialRight: Any) -> Any { + return compose("-", left, partialRight) + } + + func mult(left: Any, partialRight: Any) -> Any { + return compose("*", left, partialRight) + } + + func div(left: Any, partialRight: Any) -> Any { + return compose("/", left, partialRight) + } + + func leftParenthesized(partialExpression: Any) -> Any { + let suffix = NSAttributedString(string: ")", attributes: [.foregroundColor: UIColor.lightGray]) + return "(".toAttributed() + (partialExpression as! NSAttributedString) + suffix + } + + private func formatDouble(_ value: Any) -> String { + let rounded = round(1000 * (value as! Double)) / 1000 + return "\(rounded as NSNumber)" + } + + private func compose(_ op: String, _ left: Any, _ partialRight: Any) -> Any { + return "\(formatDouble(left)) \(op) ".toAttributed() + (partialRight as! NSAttributedString) + } + +} diff --git a/kotlin-native/samples/calculator/settings.gradle b/kotlin-native/samples/calculator/settings.gradle new file mode 100644 index 00000000000..fe07c42cef4 --- /dev/null +++ b/kotlin-native/samples/calculator/settings.gradle @@ -0,0 +1,16 @@ +include ':arithmeticParser' +include ':cliApp' + +boolean sdkDirPropertySpecified = false +File localPropertiesFile = file("${rootProject.projectDir}/local.properties") +if (localPropertiesFile.isFile()) { + Properties properties = new Properties() + localPropertiesFile.withInputStream { inputStream -> properties.load(inputStream) } + sdkDirPropertySpecified = properties.containsKey('sdk.dir') +} + + +// Don't create Android tasks if a user has no Android SDK. +if (sdkDirPropertySpecified || System.getenv('ANDROID_HOME') != null) { + include ':androidApp' +} diff --git a/kotlin-native/samples/cocoapods/.gitignore b/kotlin-native/samples/cocoapods/.gitignore new file mode 100644 index 00000000000..6492779ad8b --- /dev/null +++ b/kotlin-native/samples/cocoapods/.gitignore @@ -0,0 +1,8 @@ +ios-app/Pods +Podfile.lock +kotlin-library/kotlin_library.podspec +ios-app/ios-app.xcodeproj/xcuserdata +ios-app/ios-app.xcworkspace/xcuserdata +ios-app/ios-app.xcodeproj/project.xcworkspace/xcuserdata +ios-app/ios-app.xcworkspace/contents.xcworkspacedata +ios-app/ios-app.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist \ No newline at end of file diff --git a/kotlin-native/samples/cocoapods/README.md b/kotlin-native/samples/cocoapods/README.md new file mode 100644 index 00000000000..f69aa1c894f --- /dev/null +++ b/kotlin-native/samples/cocoapods/README.md @@ -0,0 +1,24 @@ +# Using CocoaPods + +This sample demonstrates how to use a CocoaPods library from Kotlin/Native. It uses the the +[AFNetworking](https://cocoapods.org/pods/AFNetworking) library to retrieve a web-page by a +given URL. + +## Configuring the project +1. [Install](https://guides.cocoapods.org/using/getting-started.html#installation) CocoaPods. + It's recommended to use CocoaPods 1.6.1 or higher. + +2. Navigate to the [kotlin-library](kotlin-library) directory and run + ``` + ./gradlew podspec + ``` + A [podspec](https://guides.cocoapods.org/syntax/podspec.html#specification) file for the + Kotlin/Native library will be generated. + +3. Navigate to the [ios-app](ios-app) directory and install the dependencies. The generated + podspec is already added to the Podfile, so just run + ``` + pod install + ``` + +4. Open [ios-app.xcworkspace](ios-app/ios-app.xcworkspace) in Xcode and run the build. \ No newline at end of file diff --git a/kotlin-native/samples/cocoapods/build.sh b/kotlin-native/samples/cocoapods/build.sh new file mode 100755 index 00000000000..322e9cf4ba3 --- /dev/null +++ b/kotlin-native/samples/cocoapods/build.sh @@ -0,0 +1,26 @@ +#!/usr/bin/env bash + +DIR=$(cd "$(dirname "${BASH_SOURCE[0]}" )" && pwd ) + +KOTLIN_DIR="$DIR/kotlin-library" +IOS_DIR="$DIR/ios-app" + +#Check CocoaPods version. +REQUIRED_POD_VERSION="1.6.1" +POD_VERSION=`pod --version` +EARLIER_VERSION=`echo "$POD_VERSION $REQUIRED_POD_VERSION" | tr " " "\n" | sort -V | head -1` + +if [ "$EARLIER_VERSION" != "$REQUIRED_POD_VERSION" ]; then + echo "ERROR: This version of CocoaPods is unsupported. Current version is $POD_VERSION. Minimal required version is $REQUIRED_POD_VERSION." + echo "See update instructions at https://guides.cocoapods.org/using/getting-started.html#updating-cocoapods" + exit 1 +fi + +# Prepare Kotlin/Native project to be consumed by CocoaPods. +"$KOTLIN_DIR/gradlew" -p "$KOTLIN_DIR" podspec + +# Run CocoaPods to configure the Xcode project. +pod --project-directory="$IOS_DIR" install + +# Run Xcode to build the app. +xcodebuild -sdk iphonesimulator -arch arm64 -configuration Release -workspace "$IOS_DIR/ios-app.xcworkspace" -scheme ios-app diff --git a/kotlin-native/samples/cocoapods/ios-app/Podfile b/kotlin-native/samples/cocoapods/ios-app/Podfile new file mode 100644 index 00000000000..5e3e6081186 --- /dev/null +++ b/kotlin-native/samples/cocoapods/ios-app/Podfile @@ -0,0 +1,8 @@ +# Either use_frameworks! or use_modular_headers! must be specified. +use_frameworks! + +platform :ios, '9.0' + +target 'ios-app' do + pod 'kotlin_library', :path => '../kotlin-library' +end \ No newline at end of file diff --git a/kotlin-native/samples/cocoapods/ios-app/ios-app.xcodeproj/project.pbxproj b/kotlin-native/samples/cocoapods/ios-app/ios-app.xcodeproj/project.pbxproj new file mode 100644 index 00000000000..fb3aa55d900 --- /dev/null +++ b/kotlin-native/samples/cocoapods/ios-app/ios-app.xcodeproj/project.pbxproj @@ -0,0 +1,419 @@ +// !$*UTF8*$! +{ + archiveVersion = 1; + classes = { + }; + objectVersion = 50; + objects = { + +/* Begin PBXBuildFile section */ + 2C11BACF224B4DCB00D1CC3C /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2C11BACE224B4DCB00D1CC3C /* AppDelegate.swift */; }; + 2C11BAD1224B4DCB00D1CC3C /* ViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2C11BAD0224B4DCB00D1CC3C /* ViewController.swift */; }; + 2C11BAD4224B4DCB00D1CC3C /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 2C11BAD2224B4DCB00D1CC3C /* Main.storyboard */; }; + 2C11BAD6224B4DCD00D1CC3C /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 2C11BAD5224B4DCD00D1CC3C /* Assets.xcassets */; }; + 2C11BAD9224B4DCD00D1CC3C /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 2C11BAD7224B4DCD00D1CC3C /* LaunchScreen.storyboard */; }; + 7AEB35573DF5ECC0B96C877C /* Pods_ios_app.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 06FDB564DA981DADB5693C07 /* Pods_ios_app.framework */; }; +/* End PBXBuildFile section */ + +/* Begin PBXFileReference section */ + 06FDB564DA981DADB5693C07 /* Pods_ios_app.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_ios_app.framework; sourceTree = BUILT_PRODUCTS_DIR; }; + 2C11BACB224B4DCB00D1CC3C /* ios-app.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = "ios-app.app"; sourceTree = BUILT_PRODUCTS_DIR; }; + 2C11BACE224B4DCB00D1CC3C /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; }; + 2C11BAD0224B4DCB00D1CC3C /* ViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ViewController.swift; sourceTree = ""; }; + 2C11BAD3224B4DCB00D1CC3C /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = ""; }; + 2C11BAD5224B4DCD00D1CC3C /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; + 2C11BAD8224B4DCD00D1CC3C /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = ""; }; + 2C11BADA224B4DCD00D1CC3C /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; + 2C11BAE0224B65DE00D1CC3C /* WebKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = WebKit.framework; path = System/Library/Frameworks/WebKit.framework; sourceTree = SDKROOT; }; + 44888DA7148EA4EB17DF765D /* Pods-ios-app.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-ios-app.debug.xcconfig"; path = "Target Support Files/Pods-ios-app/Pods-ios-app.debug.xcconfig"; sourceTree = ""; }; + A063F818143EBBCD07EA19D4 /* Pods-ios-app.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-ios-app.release.xcconfig"; path = "Target Support Files/Pods-ios-app/Pods-ios-app.release.xcconfig"; sourceTree = ""; }; +/* End PBXFileReference section */ + +/* Begin PBXFrameworksBuildPhase section */ + 2C11BAC8224B4DCB00D1CC3C /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + 7AEB35573DF5ECC0B96C877C /* Pods_ios_app.framework in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXFrameworksBuildPhase section */ + +/* Begin PBXGroup section */ + 2C11BAC2224B4DCB00D1CC3C = { + isa = PBXGroup; + children = ( + 2C11BACD224B4DCB00D1CC3C /* ios-app */, + 2C11BACC224B4DCB00D1CC3C /* Products */, + 9C1A5E5C1B80F794B7154EE0 /* Pods */, + B404E0DEAC80D8DB556F0E49 /* Frameworks */, + ); + sourceTree = ""; + }; + 2C11BACC224B4DCB00D1CC3C /* Products */ = { + isa = PBXGroup; + children = ( + 2C11BACB224B4DCB00D1CC3C /* ios-app.app */, + ); + name = Products; + sourceTree = ""; + }; + 2C11BACD224B4DCB00D1CC3C /* ios-app */ = { + isa = PBXGroup; + children = ( + 2C11BACE224B4DCB00D1CC3C /* AppDelegate.swift */, + 2C11BAD0224B4DCB00D1CC3C /* ViewController.swift */, + 2C11BAD2224B4DCB00D1CC3C /* Main.storyboard */, + 2C11BAD5224B4DCD00D1CC3C /* Assets.xcassets */, + 2C11BAD7224B4DCD00D1CC3C /* LaunchScreen.storyboard */, + 2C11BADA224B4DCD00D1CC3C /* Info.plist */, + ); + path = "ios-app"; + sourceTree = ""; + }; + 9C1A5E5C1B80F794B7154EE0 /* Pods */ = { + isa = PBXGroup; + children = ( + 44888DA7148EA4EB17DF765D /* Pods-ios-app.debug.xcconfig */, + A063F818143EBBCD07EA19D4 /* Pods-ios-app.release.xcconfig */, + ); + path = Pods; + sourceTree = ""; + }; + B404E0DEAC80D8DB556F0E49 /* Frameworks */ = { + isa = PBXGroup; + children = ( + 2C11BAE0224B65DE00D1CC3C /* WebKit.framework */, + 06FDB564DA981DADB5693C07 /* Pods_ios_app.framework */, + ); + name = Frameworks; + sourceTree = ""; + }; +/* End PBXGroup section */ + +/* Begin PBXNativeTarget section */ + 2C11BACA224B4DCB00D1CC3C /* ios-app */ = { + isa = PBXNativeTarget; + buildConfigurationList = 2C11BADD224B4DCD00D1CC3C /* Build configuration list for PBXNativeTarget "ios-app" */; + buildPhases = ( + F305A4DC70C8B21755898707 /* [CP] Check Pods Manifest.lock */, + 2C11BAC7224B4DCB00D1CC3C /* Sources */, + 2C11BAC8224B4DCB00D1CC3C /* Frameworks */, + 2C11BAC9224B4DCB00D1CC3C /* Resources */, + 042B85E17AFECF20FF11D591 /* [CP] Embed Pods Frameworks */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = "ios-app"; + productName = "ios-app"; + productReference = 2C11BACB224B4DCB00D1CC3C /* ios-app.app */; + productType = "com.apple.product-type.application"; + }; +/* End PBXNativeTarget section */ + +/* Begin PBXProject section */ + 2C11BAC3224B4DCB00D1CC3C /* Project object */ = { + isa = PBXProject; + attributes = { + LastSwiftUpdateCheck = 1010; + LastUpgradeCheck = 1010; + TargetAttributes = { + 2C11BACA224B4DCB00D1CC3C = { + CreatedOnToolsVersion = 10.1; + }; + }; + }; + buildConfigurationList = 2C11BAC6224B4DCB00D1CC3C /* Build configuration list for PBXProject "ios-app" */; + compatibilityVersion = "Xcode 9.3"; + developmentRegion = en; + hasScannedForEncodings = 0; + knownRegions = ( + en, + Base, + ); + mainGroup = 2C11BAC2224B4DCB00D1CC3C; + productRefGroup = 2C11BACC224B4DCB00D1CC3C /* Products */; + projectDirPath = ""; + projectRoot = ""; + targets = ( + 2C11BACA224B4DCB00D1CC3C /* ios-app */, + ); + }; +/* End PBXProject section */ + +/* Begin PBXResourcesBuildPhase section */ + 2C11BAC9224B4DCB00D1CC3C /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 2C11BAD9224B4DCD00D1CC3C /* LaunchScreen.storyboard in Resources */, + 2C11BAD6224B4DCD00D1CC3C /* Assets.xcassets in Resources */, + 2C11BAD4224B4DCB00D1CC3C /* Main.storyboard in Resources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXResourcesBuildPhase section */ + +/* Begin PBXShellScriptBuildPhase section */ + 042B85E17AFECF20FF11D591 /* [CP] Embed Pods Frameworks */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputFileListPaths = ( + ); + inputPaths = ( + "${PODS_ROOT}/Target Support Files/Pods-ios-app/Pods-ios-app-frameworks.sh", + "${BUILT_PRODUCTS_DIR}/AFNetworking/AFNetworking.framework", + ); + name = "[CP] Embed Pods Frameworks"; + outputFileListPaths = ( + ); + outputPaths = ( + "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/AFNetworking.framework", + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-ios-app/Pods-ios-app-frameworks.sh\"\n"; + showEnvVarsInLog = 0; + }; + F305A4DC70C8B21755898707 /* [CP] Check Pods Manifest.lock */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputFileListPaths = ( + ); + inputPaths = ( + "${PODS_PODFILE_DIR_PATH}/Podfile.lock", + "${PODS_ROOT}/Manifest.lock", + ); + name = "[CP] Check Pods Manifest.lock"; + outputFileListPaths = ( + ); + outputPaths = ( + "$(DERIVED_FILE_DIR)/Pods-ios-app-checkManifestLockResult.txt", + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n"; + showEnvVarsInLog = 0; + }; +/* End PBXShellScriptBuildPhase section */ + +/* Begin PBXSourcesBuildPhase section */ + 2C11BAC7224B4DCB00D1CC3C /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 2C11BAD1224B4DCB00D1CC3C /* ViewController.swift in Sources */, + 2C11BACF224B4DCB00D1CC3C /* AppDelegate.swift in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXSourcesBuildPhase section */ + +/* Begin PBXVariantGroup section */ + 2C11BAD2224B4DCB00D1CC3C /* Main.storyboard */ = { + isa = PBXVariantGroup; + children = ( + 2C11BAD3224B4DCB00D1CC3C /* Base */, + ); + name = Main.storyboard; + sourceTree = ""; + }; + 2C11BAD7224B4DCD00D1CC3C /* LaunchScreen.storyboard */ = { + isa = PBXVariantGroup; + children = ( + 2C11BAD8224B4DCD00D1CC3C /* Base */, + ); + name = LaunchScreen.storyboard; + sourceTree = ""; + }; +/* End PBXVariantGroup section */ + +/* Begin XCBuildConfiguration section */ + 2C11BADB224B4DCD00D1CC3C /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ANALYZER_NONNULL = YES; + CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_ENABLE_OBJC_WEAK = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_DOCUMENTATION_COMMENTS = YES; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + CODE_SIGN_IDENTITY = "iPhone Developer"; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = dwarf; + ENABLE_STRICT_OBJC_MSGSEND = YES; + ENABLE_TESTABILITY = YES; + GCC_C_LANGUAGE_STANDARD = gnu11; + GCC_DYNAMIC_NO_PIC = NO; + GCC_NO_COMMON_BLOCKS = YES; + GCC_OPTIMIZATION_LEVEL = 0; + GCC_PREPROCESSOR_DEFINITIONS = ( + "DEBUG=1", + "$(inherited)", + ); + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + IPHONEOS_DEPLOYMENT_TARGET = 9.0; + MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE; + MTL_FAST_MATH = YES; + ONLY_ACTIVE_ARCH = YES; + SDKROOT = iphoneos; + SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG; + SWIFT_OPTIMIZATION_LEVEL = "-Onone"; + }; + name = Debug; + }; + 2C11BADC224B4DCD00D1CC3C /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ANALYZER_NONNULL = YES; + CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_ENABLE_OBJC_WEAK = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_DOCUMENTATION_COMMENTS = YES; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + CODE_SIGN_IDENTITY = "iPhone Developer"; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + ENABLE_NS_ASSERTIONS = NO; + ENABLE_STRICT_OBJC_MSGSEND = YES; + GCC_C_LANGUAGE_STANDARD = gnu11; + GCC_NO_COMMON_BLOCKS = YES; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + IPHONEOS_DEPLOYMENT_TARGET = 9.0; + MTL_ENABLE_DEBUG_INFO = NO; + MTL_FAST_MATH = YES; + SDKROOT = iphoneos; + SWIFT_COMPILATION_MODE = wholemodule; + SWIFT_OPTIMIZATION_LEVEL = "-O"; + VALIDATE_PRODUCT = YES; + }; + name = Release; + }; + 2C11BADE224B4DCD00D1CC3C /* Debug */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 44888DA7148EA4EB17DF765D /* Pods-ios-app.debug.xcconfig */; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CODE_SIGN_STYLE = Automatic; + DEVELOPMENT_TEAM = ""; + INFOPLIST_FILE = "ios-app/Info.plist"; + IPHONEOS_DEPLOYMENT_TARGET = 9.0; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + ); + PRODUCT_BUNDLE_IDENTIFIER = "org.jetbrains.konan.ios-app"; + PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_VERSION = 4.2; + TARGETED_DEVICE_FAMILY = "1,2"; + }; + name = Debug; + }; + 2C11BADF224B4DCD00D1CC3C /* Release */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = A063F818143EBBCD07EA19D4 /* Pods-ios-app.release.xcconfig */; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CODE_SIGN_STYLE = Automatic; + DEVELOPMENT_TEAM = ""; + INFOPLIST_FILE = "ios-app/Info.plist"; + IPHONEOS_DEPLOYMENT_TARGET = 9.0; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + ); + PRODUCT_BUNDLE_IDENTIFIER = "org.jetbrains.konan.ios-app"; + PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_VERSION = 4.2; + TARGETED_DEVICE_FAMILY = "1,2"; + }; + name = Release; + }; +/* End XCBuildConfiguration section */ + +/* Begin XCConfigurationList section */ + 2C11BAC6224B4DCB00D1CC3C /* Build configuration list for PBXProject "ios-app" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 2C11BADB224B4DCD00D1CC3C /* Debug */, + 2C11BADC224B4DCD00D1CC3C /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 2C11BADD224B4DCD00D1CC3C /* Build configuration list for PBXNativeTarget "ios-app" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 2C11BADE224B4DCD00D1CC3C /* Debug */, + 2C11BADF224B4DCD00D1CC3C /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; +/* End XCConfigurationList section */ + }; + rootObject = 2C11BAC3224B4DCB00D1CC3C /* Project object */; +} diff --git a/kotlin-native/samples/cocoapods/ios-app/ios-app.xcodeproj/project.xcworkspace/contents.xcworkspacedata b/kotlin-native/samples/cocoapods/ios-app/ios-app.xcodeproj/project.xcworkspace/contents.xcworkspacedata new file mode 100644 index 00000000000..136ada05267 --- /dev/null +++ b/kotlin-native/samples/cocoapods/ios-app/ios-app.xcodeproj/project.xcworkspace/contents.xcworkspacedata @@ -0,0 +1,7 @@ + + + + + diff --git a/kotlin-native/samples/cocoapods/ios-app/ios-app.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist b/kotlin-native/samples/cocoapods/ios-app/ios-app.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist new file mode 100644 index 00000000000..18d981003d6 --- /dev/null +++ b/kotlin-native/samples/cocoapods/ios-app/ios-app.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist @@ -0,0 +1,8 @@ + + + + + IDEDidComputeMac32BitWarning + + + diff --git a/kotlin-native/samples/cocoapods/ios-app/ios-app/AppDelegate.swift b/kotlin-native/samples/cocoapods/ios-app/ios-app/AppDelegate.swift new file mode 100644 index 00000000000..849f883d23e --- /dev/null +++ b/kotlin-native/samples/cocoapods/ios-app/ios-app/AppDelegate.swift @@ -0,0 +1,38 @@ +import UIKit + +@UIApplicationMain +class AppDelegate: UIResponder, UIApplicationDelegate { + + var window: UIWindow? + + + func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool { + // Override point for customization after application launch. + return true + } + + func applicationWillResignActive(_ application: UIApplication) { + // Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state. + // Use this method to pause ongoing tasks, disable timers, and invalidate graphics rendering callbacks. Games should use this method to pause the game. + } + + func applicationDidEnterBackground(_ application: UIApplication) { + // Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later. + // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits. + } + + func applicationWillEnterForeground(_ application: UIApplication) { + // Called as part of the transition from the background to the active state; here you can undo many of the changes made on entering the background. + } + + func applicationDidBecomeActive(_ application: UIApplication) { + // Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface. + } + + func applicationWillTerminate(_ application: UIApplication) { + // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:. + } + + +} + diff --git a/kotlin-native/samples/cocoapods/ios-app/ios-app/Assets.xcassets/AppIcon.appiconset/Contents.json b/kotlin-native/samples/cocoapods/ios-app/ios-app/Assets.xcassets/AppIcon.appiconset/Contents.json new file mode 100644 index 00000000000..d8db8d65fd7 --- /dev/null +++ b/kotlin-native/samples/cocoapods/ios-app/ios-app/Assets.xcassets/AppIcon.appiconset/Contents.json @@ -0,0 +1,98 @@ +{ + "images" : [ + { + "idiom" : "iphone", + "size" : "20x20", + "scale" : "2x" + }, + { + "idiom" : "iphone", + "size" : "20x20", + "scale" : "3x" + }, + { + "idiom" : "iphone", + "size" : "29x29", + "scale" : "2x" + }, + { + "idiom" : "iphone", + "size" : "29x29", + "scale" : "3x" + }, + { + "idiom" : "iphone", + "size" : "40x40", + "scale" : "2x" + }, + { + "idiom" : "iphone", + "size" : "40x40", + "scale" : "3x" + }, + { + "idiom" : "iphone", + "size" : "60x60", + "scale" : "2x" + }, + { + "idiom" : "iphone", + "size" : "60x60", + "scale" : "3x" + }, + { + "idiom" : "ipad", + "size" : "20x20", + "scale" : "1x" + }, + { + "idiom" : "ipad", + "size" : "20x20", + "scale" : "2x" + }, + { + "idiom" : "ipad", + "size" : "29x29", + "scale" : "1x" + }, + { + "idiom" : "ipad", + "size" : "29x29", + "scale" : "2x" + }, + { + "idiom" : "ipad", + "size" : "40x40", + "scale" : "1x" + }, + { + "idiom" : "ipad", + "size" : "40x40", + "scale" : "2x" + }, + { + "idiom" : "ipad", + "size" : "76x76", + "scale" : "1x" + }, + { + "idiom" : "ipad", + "size" : "76x76", + "scale" : "2x" + }, + { + "idiom" : "ipad", + "size" : "83.5x83.5", + "scale" : "2x" + }, + { + "idiom" : "ios-marketing", + "size" : "1024x1024", + "scale" : "1x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/kotlin-native/samples/cocoapods/ios-app/ios-app/Assets.xcassets/Contents.json b/kotlin-native/samples/cocoapods/ios-app/ios-app/Assets.xcassets/Contents.json new file mode 100644 index 00000000000..da4a164c918 --- /dev/null +++ b/kotlin-native/samples/cocoapods/ios-app/ios-app/Assets.xcassets/Contents.json @@ -0,0 +1,6 @@ +{ + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/kotlin-native/samples/cocoapods/ios-app/ios-app/Base.lproj/LaunchScreen.storyboard b/kotlin-native/samples/cocoapods/ios-app/ios-app/Base.lproj/LaunchScreen.storyboard new file mode 100644 index 00000000000..bfa36129419 --- /dev/null +++ b/kotlin-native/samples/cocoapods/ios-app/ios-app/Base.lproj/LaunchScreen.storyboard @@ -0,0 +1,25 @@ + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/kotlin-native/samples/cocoapods/ios-app/ios-app/Base.lproj/Main.storyboard b/kotlin-native/samples/cocoapods/ios-app/ios-app/Base.lproj/Main.storyboard new file mode 100644 index 00000000000..29d14b9fb3a --- /dev/null +++ b/kotlin-native/samples/cocoapods/ios-app/ios-app/Base.lproj/Main.storyboard @@ -0,0 +1,69 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/kotlin-native/samples/cocoapods/ios-app/ios-app/Info.plist b/kotlin-native/samples/cocoapods/ios-app/ios-app/Info.plist new file mode 100644 index 00000000000..16be3b68112 --- /dev/null +++ b/kotlin-native/samples/cocoapods/ios-app/ios-app/Info.plist @@ -0,0 +1,45 @@ + + + + + CFBundleDevelopmentRegion + $(DEVELOPMENT_LANGUAGE) + CFBundleExecutable + $(EXECUTABLE_NAME) + CFBundleIdentifier + $(PRODUCT_BUNDLE_IDENTIFIER) + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + $(PRODUCT_NAME) + CFBundlePackageType + APPL + CFBundleShortVersionString + 1.0 + CFBundleVersion + 1 + LSRequiresIPhoneOS + + UILaunchStoryboardName + LaunchScreen + UIMainStoryboardFile + Main + UIRequiredDeviceCapabilities + + armv7 + + UISupportedInterfaceOrientations + + UIInterfaceOrientationPortrait + UIInterfaceOrientationLandscapeLeft + UIInterfaceOrientationLandscapeRight + + UISupportedInterfaceOrientations~ipad + + UIInterfaceOrientationPortrait + UIInterfaceOrientationPortraitUpsideDown + UIInterfaceOrientationLandscapeLeft + UIInterfaceOrientationLandscapeRight + + + diff --git a/kotlin-native/samples/cocoapods/ios-app/ios-app/ViewController.swift b/kotlin-native/samples/cocoapods/ios-app/ios-app/ViewController.swift new file mode 100644 index 00000000000..7325dd25b40 --- /dev/null +++ b/kotlin-native/samples/cocoapods/ios-app/ios-app/ViewController.swift @@ -0,0 +1,21 @@ +import UIKit +import kotlin_library + +class ViewController: UIViewController { + + @IBOutlet weak var goButton: UIButton! + @IBOutlet weak var urlField: UITextField! + @IBOutlet weak var contentTextView: UITextView! + + + override func viewDidLoad() { + super.viewDidLoad() + // Do any additional setup after loading the view, typically from a nib. + } + + @IBAction func onGoTouch(_ sender: Any) { + let url = urlField.text! + KotlinLibKt.getAndShow(url: url, contentView: contentTextView) + } +} + diff --git a/kotlin-native/samples/cocoapods/kotlin-library/build.gradle.kts b/kotlin-native/samples/cocoapods/kotlin-library/build.gradle.kts new file mode 100644 index 00000000000..291c2faba00 --- /dev/null +++ b/kotlin-native/samples/cocoapods/kotlin-library/build.gradle.kts @@ -0,0 +1,37 @@ +plugins { + id("org.jetbrains.kotlin.multiplatform") + id("org.jetbrains.kotlin.native.cocoapods") +} + +repositories { + jcenter() + maven { setUrl("https://dl.bintray.com/kotlin/kotlin-dev") } + maven { setUrl("https://dl.bintray.com/kotlin/kotlin-eap") } +} + +group = "org.jetbrains.kotlin.sample.native" +version = "1.0" + +kotlin { + // Add a platform switching to have an IDE support. + val buildForDevice = project.findProperty("kotlin.native.cocoapods.target") == "ios_arm" + if (buildForDevice) { + iosArm64("iOS64") + iosArm32("iOS32") + + val iOSMain by sourceSets.creating + sourceSets["iOS64Main"].dependsOn(iOSMain) + sourceSets["iOS32Main"].dependsOn(iOSMain) + } else { + iosX64("iOS") + } + + cocoapods { + // Configure fields required by CocoaPods. + summary = "Working with AFNetworking from Kotlin/Native using CocoaPods" + homepage = "https://github.com/JetBrains/kotlin-native" + + // Configure a dependency on AFNetworking. It will be added in all macOS and iOS targets. + pod("AFNetworking", "~> 3.2.0") + } +} diff --git a/kotlin-native/samples/cocoapods/kotlin-library/gradle.properties b/kotlin-native/samples/cocoapods/kotlin-library/gradle.properties new file mode 100644 index 00000000000..146d025d3e9 --- /dev/null +++ b/kotlin-native/samples/cocoapods/kotlin-library/gradle.properties @@ -0,0 +1,15 @@ +kotlin.code.style=official + +# Run parallel builds in Gradle: +org.gradle.parallel=true +org.gradle.workers.max=4 + +# Pin Kotlin version: +# CHANGE_VERSION_WITH_RELEASE +kotlin_version=1.4.10 + +# Use custom Kotlin/Native home: +kotlin.native.home=../../../dist + +# Increase memory for in-process compiler execution. +org.gradle.jvmargs=-Xmx3g diff --git a/kotlin-native/samples/cocoapods/kotlin-library/gradle/wrapper/gradle-wrapper.jar b/kotlin-native/samples/cocoapods/kotlin-library/gradle/wrapper/gradle-wrapper.jar new file mode 100644 index 00000000000..e708b1c023e Binary files /dev/null and b/kotlin-native/samples/cocoapods/kotlin-library/gradle/wrapper/gradle-wrapper.jar differ diff --git a/kotlin-native/samples/cocoapods/kotlin-library/gradle/wrapper/gradle-wrapper.properties b/kotlin-native/samples/cocoapods/kotlin-library/gradle/wrapper/gradle-wrapper.properties new file mode 100644 index 00000000000..12d38de6a48 --- /dev/null +++ b/kotlin-native/samples/cocoapods/kotlin-library/gradle/wrapper/gradle-wrapper.properties @@ -0,0 +1,5 @@ +distributionBase=GRADLE_USER_HOME +distributionPath=wrapper/dists +distributionUrl=https\://services.gradle.org/distributions/gradle-6.6.1-bin.zip +zipStoreBase=GRADLE_USER_HOME +zipStorePath=wrapper/dists diff --git a/kotlin-native/samples/cocoapods/kotlin-library/gradlew b/kotlin-native/samples/cocoapods/kotlin-library/gradlew new file mode 100755 index 00000000000..4f906e0c811 --- /dev/null +++ b/kotlin-native/samples/cocoapods/kotlin-library/gradlew @@ -0,0 +1,185 @@ +#!/usr/bin/env sh + +# +# Copyright 2015 the original author or authors. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# https://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +############################################################################## +## +## Gradle start up script for UN*X +## +############################################################################## + +# Attempt to set APP_HOME +# Resolve links: $0 may be a link +PRG="$0" +# Need this for relative symlinks. +while [ -h "$PRG" ] ; do + ls=`ls -ld "$PRG"` + link=`expr "$ls" : '.*-> \(.*\)$'` + if expr "$link" : '/.*' > /dev/null; then + PRG="$link" + else + PRG=`dirname "$PRG"`"/$link" + fi +done +SAVED="`pwd`" +cd "`dirname \"$PRG\"`/" >/dev/null +APP_HOME="`pwd -P`" +cd "$SAVED" >/dev/null + +APP_NAME="Gradle" +APP_BASE_NAME=`basename "$0"` + +# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"' + +# Use the maximum available, or set MAX_FD != -1 to use that value. +MAX_FD="maximum" + +warn () { + echo "$*" +} + +die () { + echo + echo "$*" + echo + exit 1 +} + +# OS specific support (must be 'true' or 'false'). +cygwin=false +msys=false +darwin=false +nonstop=false +case "`uname`" in + CYGWIN* ) + cygwin=true + ;; + Darwin* ) + darwin=true + ;; + MINGW* ) + msys=true + ;; + NONSTOP* ) + nonstop=true + ;; +esac + +CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar + + +# Determine the Java command to use to start the JVM. +if [ -n "$JAVA_HOME" ] ; then + if [ -x "$JAVA_HOME/jre/sh/java" ] ; then + # IBM's JDK on AIX uses strange locations for the executables + JAVACMD="$JAVA_HOME/jre/sh/java" + else + JAVACMD="$JAVA_HOME/bin/java" + fi + if [ ! -x "$JAVACMD" ] ; then + die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME + +Please set the JAVA_HOME variable in your environment to match the +location of your Java installation." + fi +else + JAVACMD="java" + which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. + +Please set the JAVA_HOME variable in your environment to match the +location of your Java installation." +fi + +# Increase the maximum file descriptors if we can. +if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then + MAX_FD_LIMIT=`ulimit -H -n` + if [ $? -eq 0 ] ; then + if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then + MAX_FD="$MAX_FD_LIMIT" + fi + ulimit -n $MAX_FD + if [ $? -ne 0 ] ; then + warn "Could not set maximum file descriptor limit: $MAX_FD" + fi + else + warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT" + fi +fi + +# For Darwin, add options to specify how the application appears in the dock +if $darwin; then + GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\"" +fi + +# For Cygwin or MSYS, switch paths to Windows format before running java +if [ "$cygwin" = "true" -o "$msys" = "true" ] ; then + APP_HOME=`cygpath --path --mixed "$APP_HOME"` + CLASSPATH=`cygpath --path --mixed "$CLASSPATH"` + + JAVACMD=`cygpath --unix "$JAVACMD"` + + # We build the pattern for arguments to be converted via cygpath + ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null` + SEP="" + for dir in $ROOTDIRSRAW ; do + ROOTDIRS="$ROOTDIRS$SEP$dir" + SEP="|" + done + OURCYGPATTERN="(^($ROOTDIRS))" + # Add a user-defined pattern to the cygpath arguments + if [ "$GRADLE_CYGPATTERN" != "" ] ; then + OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)" + fi + # Now convert the arguments - kludge to limit ourselves to /bin/sh + i=0 + for arg in "$@" ; do + CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -` + CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option + + if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition + eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"` + else + eval `echo args$i`="\"$arg\"" + fi + i=`expr $i + 1` + done + case $i in + 0) set -- ;; + 1) set -- "$args0" ;; + 2) set -- "$args0" "$args1" ;; + 3) set -- "$args0" "$args1" "$args2" ;; + 4) set -- "$args0" "$args1" "$args2" "$args3" ;; + 5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;; + 6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;; + 7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;; + 8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;; + 9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;; + esac +fi + +# Escape application args +save () { + for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done + echo " " +} +APP_ARGS=`save "$@"` + +# Collect all arguments for the java command, following the shell quoting and substitution rules +eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS" + +exec "$JAVACMD" "$@" diff --git a/kotlin-native/samples/cocoapods/kotlin-library/gradlew.bat b/kotlin-native/samples/cocoapods/kotlin-library/gradlew.bat new file mode 100644 index 00000000000..ac1b06f9382 --- /dev/null +++ b/kotlin-native/samples/cocoapods/kotlin-library/gradlew.bat @@ -0,0 +1,89 @@ +@rem +@rem Copyright 2015 the original author or authors. +@rem +@rem Licensed under the Apache License, Version 2.0 (the "License"); +@rem you may not use this file except in compliance with the License. +@rem You may obtain a copy of the License at +@rem +@rem https://www.apache.org/licenses/LICENSE-2.0 +@rem +@rem Unless required by applicable law or agreed to in writing, software +@rem distributed under the License is distributed on an "AS IS" BASIS, +@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +@rem See the License for the specific language governing permissions and +@rem limitations under the License. +@rem + +@if "%DEBUG%" == "" @echo off +@rem ########################################################################## +@rem +@rem Gradle startup script for Windows +@rem +@rem ########################################################################## + +@rem Set local scope for the variables with windows NT shell +if "%OS%"=="Windows_NT" setlocal + +set DIRNAME=%~dp0 +if "%DIRNAME%" == "" set DIRNAME=. +set APP_BASE_NAME=%~n0 +set APP_HOME=%DIRNAME% + +@rem Resolve any "." and ".." in APP_HOME to make it shorter. +for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi + +@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m" + +@rem Find java.exe +if defined JAVA_HOME goto findJavaFromJavaHome + +set JAVA_EXE=java.exe +%JAVA_EXE% -version >NUL 2>&1 +if "%ERRORLEVEL%" == "0" goto execute + +echo. +echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. +echo. +echo Please set the JAVA_HOME variable in your environment to match the +echo location of your Java installation. + +goto fail + +:findJavaFromJavaHome +set JAVA_HOME=%JAVA_HOME:"=% +set JAVA_EXE=%JAVA_HOME%/bin/java.exe + +if exist "%JAVA_EXE%" goto execute + +echo. +echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% +echo. +echo Please set the JAVA_HOME variable in your environment to match the +echo location of your Java installation. + +goto fail + +:execute +@rem Setup the command line + +set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar + + +@rem Execute Gradle +"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %* + +:end +@rem End local scope for the variables with windows NT shell +if "%ERRORLEVEL%"=="0" goto mainEnd + +:fail +rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of +rem the _cmd.exe /c_ return code! +if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 +exit /b 1 + +:mainEnd +if "%OS%"=="Windows_NT" endlocal + +:omega diff --git a/kotlin-native/samples/cocoapods/kotlin-library/settings.gradle.kts b/kotlin-native/samples/cocoapods/kotlin-library/settings.gradle.kts new file mode 100644 index 00000000000..7e3308930c6 --- /dev/null +++ b/kotlin-native/samples/cocoapods/kotlin-library/settings.gradle.kts @@ -0,0 +1,20 @@ +pluginManagement { + repositories { + jcenter() + maven { setUrl("https://dl.bintray.com/kotlin/kotlin-dev") } + maven { setUrl("https://dl.bintray.com/kotlin/kotlin-eap") } + } + + resolutionStrategy { + val kotlin_version: String by settings + eachPlugin { + when { + requested.id.id == "org.jetbrains.kotlin.native.cocoapods" || + requested.id.id == "kotlin-native-cocoapods" -> + useModule("org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version") + requested.id.id.startsWith("org.jetbrains.kotlin") -> + useVersion(kotlin_version) + } + } + } +} \ No newline at end of file diff --git a/kotlin-native/samples/cocoapods/kotlin-library/src/iosMain/kotlin/KotlinLib.kt b/kotlin-native/samples/cocoapods/kotlin-library/src/iosMain/kotlin/KotlinLib.kt new file mode 100644 index 00000000000..3c35250e9b9 --- /dev/null +++ b/kotlin-native/samples/cocoapods/kotlin-library/src/iosMain/kotlin/KotlinLib.kt @@ -0,0 +1,34 @@ +import cocoapods.AFNetworking.AFHTTPResponseSerializer +import cocoapods.AFNetworking.AFHTTPSessionManager +import platform.Foundation.* +import platform.UIKit.NSDocumentTypeDocumentAttribute +import platform.UIKit.NSHTMLTextDocumentType +import platform.UIKit.UITextView +import platform.UIKit.create +import kotlin.Any +import kotlin.String +import kotlin.to +import kotlin.toString + +/** + * Retrieves the content by the given URL and shows it at the given WebKitView + */ +fun getAndShow(url: String, contentView: UITextView) { + val manager = AFHTTPSessionManager() + manager.responseSerializer = AFHTTPResponseSerializer() + val onSuccess = { _: NSURLSessionDataTask?, response: Any? -> + val html = NSAttributedString.create( + data = response as NSData, + options = mapOf(NSDocumentTypeDocumentAttribute as Any? to NSHTMLTextDocumentType), + documentAttributes = null, + error = null + )!! + contentView.attributedText = html + } + val onError = { _: NSURLSessionDataTask?, error: NSError? -> + NSLog("Cannot get ${url}.") + NSLog(error.toString()) + } + + manager.GET(url, null, onSuccess, onError) +} \ No newline at end of file diff --git a/kotlin-native/samples/coverage/README.md b/kotlin-native/samples/coverage/README.md new file mode 100644 index 00000000000..25155d97f49 --- /dev/null +++ b/kotlin-native/samples/coverage/README.md @@ -0,0 +1,12 @@ +# Code Coverage usage sample + +This example shows how to collect coverage information during execution of the test suite. +Please note that this functionality will be incorporated into Gradle plugin so you won't need to do it by hand in the nearest future. + +### Prerequisites +`createCoverageReport` task requires `llvm-profdata` and `llvm-cov` to be added to the `$PATH`. +They can be found in the Kotlin/Native dependencies dir. By default it should look like +`$HOME/.konan/dependencies/clang-llvm-6.0.1-darwin-macos/bin` + +### Usage +Just run `createCoverageReport` task. diff --git a/kotlin-native/samples/coverage/build.gradle.kts b/kotlin-native/samples/coverage/build.gradle.kts new file mode 100644 index 00000000000..8ce4b4da2db --- /dev/null +++ b/kotlin-native/samples/coverage/build.gradle.kts @@ -0,0 +1,49 @@ +import org.jetbrains.kotlin.gradle.plugin.mpp.KotlinNativeTarget + +plugins { + kotlin("multiplatform") +} + +kotlin { + // Determine host preset. + val hostOs = System.getProperty("os.name") + val isMingwX64 = hostOs.startsWith("Windows") + + // Create a target for the host platform. + val hostTarget = when { + hostOs == "Mac OS X" -> macosX64("coverage") + hostOs == "Linux" -> linuxX64("coverage") + isMingwX64 -> mingwX64("coverage") + else -> throw GradleException("Host OS '$hostOs' is not supported in Kotlin/Native $project.") + } + + hostTarget.apply { + binaries { + executable(listOf(DEBUG)) + } + binaries.getTest("DEBUG").apply { + freeCompilerArgs += listOf("-Xlibrary-to-cover=${compilations["main"].output.classesDirs.singleFile.absolutePath}") + } + } + + sourceSets { + val coverageMain by getting + val coverageTest by getting + } +} + +tasks.create("createCoverageReport") { + dependsOn("coverageTest") + + description = "Create coverage report" + + doLast { + val testDebugBinary = kotlin.targets["coverage"].let { it as KotlinNativeTarget }.binaries.getTest("DEBUG").outputFile + exec { + commandLine("llvm-profdata", "merge", "$testDebugBinary.profraw", "-o", "$testDebugBinary.profdata") + } + exec { + commandLine("llvm-cov", "show", "$testDebugBinary", "-instr-profile", "$testDebugBinary.profdata") + } + } +} \ No newline at end of file diff --git a/kotlin-native/samples/coverage/gradle.properties b/kotlin-native/samples/coverage/gradle.properties new file mode 100644 index 00000000000..29e08e8ca88 --- /dev/null +++ b/kotlin-native/samples/coverage/gradle.properties @@ -0,0 +1 @@ +kotlin.code.style=official \ No newline at end of file diff --git a/kotlin-native/samples/coverage/src/coverageMain/kotlin/bar.kt b/kotlin-native/samples/coverage/src/coverageMain/kotlin/bar.kt new file mode 100644 index 00000000000..c15d0ce71bc --- /dev/null +++ b/kotlin-native/samples/coverage/src/coverageMain/kotlin/bar.kt @@ -0,0 +1,17 @@ +fun baz(args: Array) { + if (args.size > 4) { + println("Too many") + } else { + println("Fine") + } +} + +class A { + init { + println("A::init") + } + + fun f() { + println("A::f") + } +} \ No newline at end of file diff --git a/kotlin-native/samples/coverage/src/coverageMain/kotlin/main.kt b/kotlin-native/samples/coverage/src/coverageMain/kotlin/main.kt new file mode 100644 index 00000000000..546840df5bc --- /dev/null +++ b/kotlin-native/samples/coverage/src/coverageMain/kotlin/main.kt @@ -0,0 +1,3 @@ +fun main() { + baz(arrayOf("abc")) +} \ No newline at end of file diff --git a/kotlin-native/samples/coverage/src/coverageTest/kotlin/Tests.kt b/kotlin-native/samples/coverage/src/coverageTest/kotlin/Tests.kt new file mode 100644 index 00000000000..fd7d78c0bdb --- /dev/null +++ b/kotlin-native/samples/coverage/src/coverageTest/kotlin/Tests.kt @@ -0,0 +1,15 @@ +import kotlin.test.Test +import kotlin.test.assertTrue + +class CoverageTests { + @Test + fun testHello() { + main() + } + + @Test + fun testA() { + val a = A() + a.f() + } +} \ No newline at end of file diff --git a/kotlin-native/samples/csvparser/European_Mammals_Red_List_Nov_2009.csv b/kotlin-native/samples/csvparser/European_Mammals_Red_List_Nov_2009.csv new file mode 100644 index 00000000000..bea206c0eb7 --- /dev/null +++ b/kotlin-native/samples/csvparser/European_Mammals_Red_List_Nov_2009.csv @@ -0,0 +1,262 @@ +Kingdom,Phylum,Class,Order,Family,Scientific Name,Taxonomic Notes,Endemic to Europe,Endemic to EU25,European regional Red List Category,European regional Red List Criteria,EU25 regional Red List Category,EU25 regional Red List Criteria,Rationale of the Red List Category,Conservation status analysis,Range,Population,Habitat,Threats,Conservation Actions,Red List Assessors +ANIMALIA,CHORDATA,MAMMALIA,CARNIVORA,CANIDAE,Alopex lagopus,"""The Arctic fox is sometimes placed in a subgenus of Vulpes and sometimes in Canis. However, the species is still most often placed in Alopex. The most closely related species are swift fox (Vulpes velox) and kit fox (V. macrotis), neither of which occurs in the tundra."" (Sillero-Zubiri et al. 2004).",No,No,LC,,CR,"D1, C2a(i)","European regional assessment: Least Concern (LC)EU 25 regional assessment: Critically Endangered (CR)At the regional level, the species is Least Concern (there are large populations of >10,000 mature individuals, occupying a large area, and populations are generally stable). However, there may nevertheless be cause for concern in north-western mainland Russia, where population densities apparently are low and have failed to recover despite a decrease in hunting pressure. Little is known about the arctic fox in this region, and more information (and action) is urgently needed.Within the EU, the arctic fox is found only in Sweden and Finland, where its total population numbers at most 50-70 animals. In Sweden the population is very small but appears to have stabilized, whereas in Finland no breeding has been recorded since 2000 and the population can be assumed to be decreasing. Fennoscandian populations are all tiny and highly fragmented, so no rescue effect should be expected from outside the EU. Consequently the species qualifies as Critically Endangered (D1, C2a(i)).Arctic foxes in Fennoscandia are isolated from other populations, and thus can be described as a subpopulation (according to global Red List guidelines). Within that subpopulation there are a number of further isolated subpopulations, each numbering less than 50 individuals. The Fennoscandian subpopulation is assessed as Critically Endangered under Criterion C2a(i), as it numbers <250 mature individuals, and there are ongoing declines (although populations in Norway and Sweden are relatively stable, the Finnish population is declining).",Unfavourable,"Arctic foxes have a circumpolar distribution (Corbet 1978, Hall 1981, Ginsberg and Macdonald 1990, Pulliainen 1999, Wilson and Ruff 1999), occurring in three distinct ecological situations. Arctic foxes are found throughout the area of continental tundra that covers the northern coasts of Alaska, Canada and Siberia. They occur on most of the arctic islands including all islands of the Canadian high arctic, Greenland, Iceland, Svalbard, Jan Mayen, Bjørnøya, Novaya Zemlja, Wrangel Island, and the Komandor Islands (in addition, they have been introduced to some of the Aleutian Islands: Bailey 1992). Thirdly, they occur on the alpine tundra that occurs on the mountain ranges found along the spine of the Scandinavian peninsula (including the Kola region). Arctic foxes are also observed in the open drift ice. In a pan-European context arctic foxes occur in four geographic areas that represent all three ecological situations – continental tundra in western Siberia (Russia), arctic islands in Svalbard (Norway) and Iceland, and alpine tundra in Fennoscandia (Norway, Sweden, Finland and the Kola peninsula of Russia). Southern and altitudinal limitations on its global distribution is most probably set by intraguild competition with the larger red fox (Hersteinsson and Macdonald 1992). In Europe Arctic foxes occur from sea level to 1,500 m (N.E. Eide pers. comm. 2007).","The world population of arctic foxes is in the order of several hundred thousand animals (see Sillero-Zubiri et al. 2004 for specific details). Most populations fluctuate widely in numbers between years in response to varying lemming numbers. The species is common in the tundra areas of Russia, Canada, coastal Alaska, Greenland and Iceland. Exceptions are Fennoscandia, Mednyi Island (Komandor Islands, Russia) and the Pribilof Islands, where populations are at critically low levels (Sillero-Zubiri et al. 2004). The situation in Europe varies between areas. It is most realistic to consider the four geographic areas of occurrence separately:Western Siberia (from the White Sea to Novaya Zemlya). There are no reliable data about arctic fox numbers from this region, although Sillero-Zubiri et al. (2004) estimate that the total Russian population (including eastern Siberia) could potentially be in the order of 200,000-800,000 animals. In general in Western Russia, the species is sparse on the mainland but common on the Novaya Zemlya archipelago, where some thousands of animals can be estimated on the each island (A. Tikhonov pers. comm. 2006). Although the hunting pressure on this species is now very low all over Russia, mainland populations may not have recovered from historical overhunting (A. Tikhonov pers. comm. 2006).Svalbard. There has been no total census of arctic foxes on this archipelago, but the population is known to be numerous and stable. The arctic fox went extinct on the island Bjørnøya (part of the Svalbard archipelago) and on Jan Mayen (an isolated island further south between Svalbard and Iceland). The two populations were severely depleted following early 20th century extermination efforts (Fuglei et al. 1998). On Bjørnøya the arctic fox population has re-established by immigration over sea ice in recent years, and breeding is again documented, while no foxes have been observed on Jan Mayen since before 1998 (E. Fuglei pers. comm. 2007). Iceland. Numbers of arctic foxes on Iceland have fluctuated as a result of differing management practices. From a low point in the 1970s of around 1,300 individuals, the population reached 8,000 individuals in 2003 and is still increasing (Hersteinsson 2006).Fennoscandia. Arctic foxes were once very abundant throughout the alpine tundra habitats of Fennoscandia, but were greatly reduced due to over-harvesting in the late 19th and early 20th centuries. They have basically never recovered, despite having been protected for over 75 years (Østbye et al. 1978, Hersteinsson et al. 1989, Linnell et al. 1999, Kaikusalo et al. 2000). The most recent estimate is 120 adults in Norway, Sweden and Finland, around 50 of which are found in Sweden (Angerbjörn et al. 1995, Sillero-Zubiri et al. 2004, Angerbjörn et al. 2005), 50 in Norway (Frafjord and Rofstad 1998, Linnell et al. 1999), and 5-15 in Finland (Kaikusalo et al. 2000, Angerbjörn et al. 2005). The population on the Kola peninsula has not been accurately censused. Estimates range from c.40 individuals (Angerbjörn et al. 2005), and less than 100 individuals (A. Tikhonov pers. comm. 2006), to 1,000-2,000 animals (Potansky 1993). The latter figure is considered likely to be an overestimate (Sillero-Zubiri et al. 2004). Genetic research showed that the Arctic fox in Scandinavia presently is subdivided into four subpopulations, and that the Kola Peninsula and northwest Russia together form a large fifth subpopulation. Current dispersal between the subpopulations seems to be very low (Dalén et al. 2006). The population trend in Norway and Sweden is stable, but in Finland the population can be assumed to be decreasing as there has been no breeding documented since 2000 (H. Henttonen pers. comm. 2006).","The species is confined to arctic and alpine tundra, above or north of the treeline. The arctic fox is an opportunistic predator and scavenger, but in most inland areas the species is heavily dependent on fluctuating rodent populations. In Fennoscandia, the Norwegian lemming Lemmus lemmus was the main prey in summer (85% frequency of occurrence in faeces) followed by birds and reindeer (Rangifer tarandus) (Frafjord 1995, Elmhagen et al. 2000). Changes in fox populations have been observed to follow those of their main prey in three- to five-year cycles (Angerbjörn et al. 1995, Angerbjörn et al. 1999). The typical response to lemming peak-years is an increase in both the number of litters and litter size (Tannerfeldt and Angerbjörn 1996). Foxes living near ice-free coasts have access to both inland prey and sea birds, seal carcasses, fish and invertebrates connected to the marine environment, leading to relatively stable food availability and a more generalist strategy especially in areas without cyclic rodent populations (Hersteinsson and Macdonald 1996, Dalerum and Angerbjörn 2000, Eide et al. 2005). In Iceland, lamb carcasses frequently are found among prey remains at dens resulting in the species being considered a pest. Although individual foxes may indeed prey on lambs, it is more likely that a large proportion of the lambs have been scavenged (Hersteinsson 1996). Arctic foxes are known to prey on wildfowl (Eide et al. 2005) and occasionally kill reindeer calves (Prestrud 1992a). Foxes reach sexual maturity at 10 months, and the average lifespan for animals that reach adulthood is approximately three years (Angerbjörn et al. 2004). In more stable coastal environments the average age is probably higher (Prestrud 1992a). Arctic fox life history traits reflect adaptations to differing constraints in resource availability. Arctic foxes in unstable environments (e.g., habitats dominated by cyclic prey) have higher litter size but do not reproduce every year, whereas arctic foxes in stable environments (e.g., coastal habitats with bird cliffs), have a smaller litter size but reproduce every year (Tannerfeldt and Angerbjörn 1996, Angerbjörn et al. 2004). Social organization (home range size and territoriality) and hence local density of arctic fox is also highly influenced by resource availability; home range sizes range from 10 km2 in stable coastal habitats up to 52 km2 in more fluctuating environments (Angerbjörn et al. 1997, Strand et al. 2000, Eide et al. 2004). Hence predictable coastal habitats support a denser population of foxes compared to more unpredictable habitats. Arctic foxes tend to be territorial, with a mated pair occupying a common territory (Hersteinsson and Macdonald 1986, Prestrud 1992b, Landa et al. 1998, Tannerfeldt and Angerbjörn 1996, Eide et al. 2004). Additional, but non-reproductive adults may also be present within the territory even though their function as “helpers” may be somewhat limited. In some rare cases it has been observed that two adult females will reproduce within the same territory (Strand et al. 2000, Angerbjörn et al. 2004, Bodil Elmhagen pers. comm.). As a result of these home range sizes and territorial social organisation typical densities can vary from 20 adults per 100 km2 to 2-4 per 100 km2. A noticeable feature of arctic fox ecology is dependence on and year round use of dens. These dens are normally excavated in sandy soil and can reach a considerable size (Østbye et al. 1978, Dalerum et al. 2002, Frafjord 2003). After several decades, or even centuries, of use they can acquire many tens of openings. In areas without sandy deposits foxes use crevices in cliffs or moraines as dens (Prestrud 1992b).","Globally the large populations on the continental tundra of Alaska, Canada and Siberia (except Kola) and the island of Greenland are all harvested by trapping or shooting. The main motivation is for fur, although they are killed around settlements in parts of Greenland to reduce the risk of rabies being spread to sled dogs and humans. There is nothing that indicates that these populations are currently threatened by overharvest. The small population on the Komandor islands is threatened by a form of mange (Otodectes cynotis: Goltsman et al. 1996).In Europe the threats vary between regions.The animals occupying western Siberia are exposed to trapping, but nothing indicates that this is representing an immediate threat. There is no other information available about threats to this population.On Svalbard arctic foxes are trapped, but the extent of this trapping is limited to areas close to settlements, and it is therefore not regarded as a threat (Fuglei et al. 1998). Possible threats include accumulation of long distance transported pollutants and climate change, which may influence sea ice conditions in the future. The arctic fox on Svalbard (Norway) has higher levels of persistent organic pollutants (POPs) than foxes in other parts of the arctic (Norheim 1978, Wang-Andersen et al. 1993, Fuglei et al. 2007). The levels are similar to those found in polar bears from Svalbard and Greenland (Verreault et al. 2005). Such high concentrations of contaminants may have possible toxic health effects. The island Bjørnøya holds a small, recently re-established population of arctic foxes, while no foxes have been reported on Jan Mayen since before 1998 (E. Fuglei pers comm. 2007). Arctic foxes on these islands are protected and the main threat appears to be lack of influx of new animals and the extremely small population size. These islands were part of the Svalbard metapopulation, as sea ice allowed connectivity. Climate change through reduction in the extent of the sea ice might in fact explain why the arctic fox has not re-established on Jan Mayen (E. Fuglei pers comm. 2007).On Iceland the status of arctic fox has changed. Historically they were heavily persecuted because of the belief that they were involved in depredation on livestock. Recent legislation has restricted harvest and the population is increasing (Hersteinsson 2006), although in many areas they are still hunted year round.In Fennoscandia arctic foxes are scattered along the peninsula in very small populations that are relatively isolated from each other. The alpine tundra habitat is naturally fragmented, but the degree of population fragmentation has increased due to the extinction of local populations. The populations have not increased despite over 75 years of protection. Overexploitation due to hunting and trapping was most probably the originate threat and the reason behind the dramatic decline of arctic foxes in Fennoscandia (Østbye et al. 1978, Hersteinsson et al. 1989, Angerbjörn et al. 1995, Linnell et al. 1999, Kaikusalo et al. 2000). The value of arctic fox fur together with high grants for killing foxes gave motivation for this strong persecution. In 1924 Norwegian trappers could get 25% more than an average year's salary for a peasant for only one skin (Østbye and Pedersen 1990). Establishment of the fox farm industry at the beginning of 1900 probably also forced the decline further. Live trapping of foxes also continued also after protection. Arctic fox den sites are easy to spot and several dens were dug out during the sixties to catch cubs to bring in to fur farms (Østbye et al. 1978). The exact reason why the population in not responding to protection is not understood, but a range of factors are believed to be involved, including:Intraguild competition with red foxes. Red fox populations have increased and expanded in range throughout the 20th century, both in the boreal region and above the treeline to alpine tundra habitat (Selås and Vik 2006, Elmhagen et al. 2007). It is known that they have occupied former arctic fox dens in the most productive, low lying areas (Østbye et al. 1978, Linnell et al. 1999, Frafjord 2003, Tannerfeldt et al. 2002, Kaikusalo et al. 2000). Red foxes occupy the same niche and eat the same prey as arctic foxes (Elmhagen et al. 2002), they can kill arctic fox pups and adults (Frafjord et al. 1989, Tannerfeldt et al. 2002), and arctic foxes avoid breeding close to red foxes (Tannerfeldt et al. 2002). Therefore the potential for a negative effect is clearly present.Genetics. The remaining arctic fox populations are all very small and relatively isolated from each other. Today the population consists of four genetically distinct subpopulations with very little exchange of dispersing animals (Dalén et al. 2002, Dalén et al. 2006). Therefore the potential for inbreeding is high. So far there are no obvious signs of inbreeding depression but individual genetic variation was negatively associated with fitness (Dalén et al. unpublished). Although there is still a surprisingly high degree of variation, by comparison with historical samples it is clear that 25% of the variation has been lost (Nyström et al. 2006). Hybridization with arctic foxes that have escaped from fur farms has also been documented. Genetic mapping revealed hybridization of genotypes originating from escaped farm foxes (Norén et al. 2005), mixing in haplotypes not found in the wild Fennoscandian arctic fox (Dalén et al. 2005). The amount of reported escapes of farm foxes has increased in recent years and even breeding has been observed (N.E. Eide pers. comm. 2006). However at present demographic stochasticity probably remains a greater threat than inbreeding.Small population size. The small size of populations directly increases their individual risks of extinction, especially when they occupy a fluctuating environment with strong year to year variation in the probability of reproducing (Linnell et al. 1999, Loison et al. 2001). Extinction risk is further increased by fragmentation, which reduces the chance of rescue effects occurring (Dalén et al. 2006).Climate change. Projected climate change would intensify fragmentation of the Fennoscandian mountain plateau even further, and may exclude the arctic fox from lower lying alpine tundra areas. For a review of the potential impacts of climate change on arctic foxes see Ims and Fuglei (2005).","Occurrence in protected areasGood information is available for Norway, Sweden and Finland. For Iceland, Arctic foxes could potentially appear in most protected areas (Sillero-Zubiri et al. 2004). Norway: The National Parks Blåfjell-Skjækerfjella, Børgefjell, Saltfjellet, Øvre Dividal, Reisa. On Svalbard Arctic foxes are found in most protected areas.Sweden: The National Parks Sarek, Padjelanta, and Stora Sjöfallet, in the county of Norrbotten; the Nature Reserves Vindelfjällen, Marsfjället, and Gitsfjället, in the county of Västerbotten; the Nature Reserves Hamrafjället, Henvålen-Aloppan, Vålådalen, Gråberget-Hotagsfjällen, Frostvikenfjällen, Sösjöfjällen and Skäckerfjällen, in the county of Jämtland.Finland: Malla, Käsivarren erämaa, Iiton palsasuot, Saanan luonnonsuojelualue, Muotkatunturin erämaa, Hanhijänkä Pierkivaaran jänka, Pieran Marin jänkä, Kevo, Kaldoaivin erämaa, Paistunturin erämaa, Pulmankijärvi.There appear to be no significant protected areas in the the Kola peninsula that contain arctic foxes.LegislationIt is strictly protected under the Bern Convention (Appendix II), and is listed on Annex II* and Annes IV of the EU Habitats & Species Directive. In most of its range, the arctic fox is not protected under national legislation. However, the species and its dens have had total legal protection in Sweden since 1928, in Norway since 1930, and in Finland since 1940. In Europe, the arctic fox is a priority species under the Actions by the Community relating to the Environment (ACE). Conservation measures takenAction plans based on status reports have been developed for arctic foxes in Sweden (Löfgren and Angerbjörn 1998) and Norway (Direktoratet for Naturforvaltning 2003), and a status report has also been published for Finland (Kaikusalo et al. 2000). In Sweden and Finland, a species-specific conservation project has been completed (SEFALO), and a second is under way (SEFALO+), the latter also involving work in Norway (Angerbjörn et al. 2005). Measures taken include den monitoring (and protection of den sites by excluding ptarmigan hunting in Sweden only), supplementary feeding, red fox control, disease research, as well as building public awareness and education work (Angerbjörn et al. 2005). In Norway a captive breeding programme on arctic foxes was started in 2000 and extended in 2007. The first successful captive reproduction and release of foxes happened in 2006 (A. Landa pers. comm. 2006). A research programme on red fox control was started in northern Norway in 2004. Programmes to build public awareness have also been started in Norway by non-governmental organizations (www.fjellrev.no). A number of research projects on the arctic fox are underway, of which further details can be found in Sillero-Zubiri et al. (2004).","P. Hersteinsson, A. Landa, N.E. Eide, J.D.C. Linnell, H. Henttonnen, A. Tikhonov, A. Angerbjörn." +ANIMALIA,CHORDATA,MAMMALIA,CARNIVORA,CANIDAE,Canis aureus,,No,No,LC,,NT,,"European regional assessment: Least Concern (LC)EU 25 regional assessment: Near Threatened (NT)In Europe as a whole, the population trend is stable to increasing. The golden jackal is patchily distributed over a wide area, locally common, and faces no major threats. Hence it is listed as Least Concern.Within the EU 25 it is only found in Greece and Hungary, with vagrants in Italy, Austria, Slovenia and Slovakia. The distribution is patchy and fragmented, and each subpopulation consists of fewer than 1,000 mature adults. There has been more than a 50% population reduction in the past 20 years in Greece, but its population has expanded rapidly in Hungary during that same period. Overall, there is believed to have been a small population decline in the EU 25 over the last 18 years (3 generations), and the net population trend is believed to be slightly decreasing at present. Therefore it qualifies as Vulnerable under Criterion C2a(i). However, as it is a mobile species that readily colonises new areas, there is likely to be a rescue effect from expanding jackal populations in parts of Europe outside the EU 25. Consequently the assessment is downgraded by one category to Near Threatened.",Unfavourable,"The golden jackal has a large global distribution extending from north and east Africa and south-eastern and central Europe eastwards through the Middle East, the Caucasus and central and and southern Asia to Burma and Thailand (Sillero-Zubiri et al. 2004). It is the only jackal species that occurs outside subsaharan Africa. In Europe, it is resident in the Balkans and, since recent times, in Hungary and southwestern Ukraine. It has a very patchy distribution in Europe. It is regularly found as a vagrant in Austria, Slovakia, Slovenia and northeastern Italy (Kryštufek 1999). It is generally found between sea level and 600 m, and occasionally up to 1,000 m in the Peloponnese (Greece) (G. Giannatos pers. comm. 2006).","In Europe, the jackal occurs in small and scattered populations, mainly along the Mediterranean and Black Sea coast of the Balkan Peninsula and in southern parts of Hungary. Over the last century, its distributional border has fluctuated, and there have been both local colonisations and extinctions (Kryštufek 1999). In Greece, one of its European strongholds, its range and population have declined over the last 25 years, and it is by far the most rare canid species (Giannatos 2004, Giannatos et al. 2005). It is now stable in northeastern Greece (and may even be increasing) but in parts of southern Greece is still declining. The largest population in Europe is found in Bulgaria where the species has increased 33-fold in the last 20-30 years (Kryštufek and Tvrtkovic 1990). In Hungary, the jackal went extinct in 1942, but it has naturally recolonised over the last few decades, and now has a rapidly expanding population of c.1,000 individuals (Heltai et al. 2000, Heltai et al. 2004). Other population estimates for the jackal include 5,000 individuals (Bulgaria), >1,000 adults and sub-adults (Greece), and 40-50 animals in 7-8 groups (Ukraine) (Giannatos 2004, Giannatos et al. 2005). The global population is large, with a minimum of 80,000 individuals estimated for the Indian sub-continent (population estimates for Africa are not available), but it may be declining as a result of agricultural intensification and urbanisation (Sillero-Zubiri et al. 2004).","Globally, it occupies a wide range of habitats, from the Sahel desert to the evergreen forests of south-east Asia (Sillero-Zubiri et al. 2004). In Europe, it prefers cultivated areas and wetlands in lower elevations, with adequate cover to be used for hiding and breeding. Dense continuous forests and large intensively cultivated areas without cover are not suitable. Moderate human activity may benefit the jackal, as it tends to increase availability of food (carrion, refuse, and animal dung) (Giannatos 2004). In Central Europe (Hungary) the dominant food of golden jackal is small mammals, and the trophic niche overlap with red foxes is usually high, although the jackal seems to be more carnivorous and more specialist than the fox (Lanski and Heltai 2002, Lanski et al. 2006).","In Greece, population declines have been linked to loss of suitable habitat caused by changes in agricultural practices (intensification), specifically the loss of scrubby patches used as cover (Giannatos 2004). Changes in animal husbandry may have reduced the food base. Throughout its range, the species is widely persecuted as a pest.","The jackal is not considered a priority species for the European Union (it is included in the Annex V of the Habitats Directive, 92/43 EC). In Bulgaria, Croatia and Hungary it is a game species, and in Greece it is not classified. An Action Plan has recently been produced for jackals in Greece (Giannatos 2004), which suggested the following conservation measures: preservation and restoration of safe and good quality habitat; scientific research and monitoring to develop a database in order to improve management decisions for jackal conservation and promote co-operation of the jackal hosting countries in the region; legislation improvement; and public awareness, education and information to improve the animal's public image.","Giorgos Giannatos, Boris Kryštufek" +ANIMALIA,CHORDATA,MAMMALIA,CARNIVORA,CANIDAE,Canis lupus,"All European wolves are Canis lupus. Only two subspecies are recognized: C. l. signatus (Iberia) and C. l. italicus (Italy, France and Switzerland)",No,No,LC,,LC,,"European regional assessment: Least Concern (LC)EU 25 regional assessment: Least Concern (LC)Following the bottleneck of the 1960s and 1970s, the European wolf population is generally increasing in number and expanding the distribution range. The total number of wolves in the EU 25 is likely to be in the order of 4-5,000, and the number of wolves in geographic Europe is likely to exceed 10,000. Consequently the species qualifies as Least Concern at the European and EU 25 level. 1. IberiaNear Threatened. The Iberian population is large (about 2,500 wolves) and expanding toward south and east. It does not qualify for the category Vulnerable and it is maintained in category Near Threatened because of the fragmentation in management regimes, the lack of a population level management plan, the occurrence of largely unpredictable events of human reaction against wolves (poison, shooting, etc.) that may threaten the population at local level. The small population of Sierra Morena is far from the main population in the North and should be classified as Critically Endangered (D). 2. Western-Central AlpsEndangered (D). The Alpine population is the recent outgrowth of the Italian wolf population and it is still numerically small. Though it is increasing fast, it is currently estimated to be 100-120 animals, and it has limited genetic and demographic contacts with the adjacent population of the Apennines (less than one successful migrant per year, meaning that it qualifies as a subpopulation under IUCN Red List guidelines). Its small size justifies the assessment in category Endangered.3. Italian peninsulaVulnerable (D1). The Italian wolf population is estimated to be 500-800 individuals distributed along the Apennines. The shape of the range is narrow and elongated, restricted to the Apennines. The population has limited exchanges with the population of the Western Alps and recent genetic evidence indicates a flux of genes only in the direction toward the Alps. In spite of the recent increase in numbers and range, the Italian wolf population is still highly vulnerable to local extermination from human pressures (poison, shooting, car accidents) and the stochastic nature of these events suggest to maintain a cautionary assessment. The population does not qualify for the category Endangered, but it may easily reverse its current favourable status. 4. Dinaric-BalkanLeast Concern. This large wolf population (c.5,000 animals) appears to be in favourable conservation status mainly due to the limited management caused by the recent political instability of large areas of the region. However, the more marginal parts of the range may be subject to excessive pressure from human disturbance (Slovenia, southern Greece) and ad-hoc management actions should be implemented. 5. CarpathianLeast Concern. This large wolf population (c.5,000 animals) appears to be in favourable conservation status mainly due to the conservation implemented in Romania. However, some of the marginal areas of the range may be subject to excessive pressure (southern Poland, Slovakia) and may require ad-hoc conservation measures. Those marginal areas are also critical because of completely different management regimes implemented in neighboring countries (Ukraine, Poland and Slovakia). To ensure viability of those marginal parts of the Carpathian population international common decisions are important. 6. BalticLeast Concern. The relatively large number of wolves and the continuity of the range into Russia support its assessment in the category of Least Concern. However, the small portions of the population in Poland and some of the Baltic States may require conservation measures to ensure their long term persistence. 7. KareliaNear Threatened. The total population in Finland and Russian Karelia is not known, but is considered likely to number less than 10,000, and it may be declining as a result of persecution. The degree of fragmentation is not known. Consequently it is assessed precautionarily as Vulnerable (C2a(i)). The Karelian population is generally considered to be in contact with the large Russian population, and there would potentially be a rescue effect, so the assessment is downgraded by one step to Near Threatened. Very little information is currently available on the status of the wolf in Russian Karelia, and this population should be reassessed if any new relevant data becomes available.8. ScandinaviaEndangered (D). The number of mature individuals is estimated to be less than 250. The population has low genetic variability and has had no genetic exchange with the Finnish population since 1991.9. Germany/western PolandCritically Endangered (D). The population is tiny, fragmented and isolated.",Possibly Favourable,"Originally, the wolf was the world's most widely distributed mammal, living throughout the northern hemisphere north of 15°N latitude in North America and 12°N in India. It is distributed worldwide under domestication (as the domestic dog Canis familiaris). It has become extinct in much of Western Europe (Boitani 1995), in Mexico and much of the USA (Mech 1970). Present distribution is more restricted; wolves occur primarily in wilderness and remote areas, especially in Canada, Alaska and northern USA, Europe, and Asia from about 75°N to 12°N (Sillero-Zubiri et al. 2004). In Europe wolves are found from sea level to 2,400 m, although in central and southern areas they tend to occur in mountainous areas above 600 m, as a result of persecution (Sulkava and Pulliainen 1999). The European wolf population is a large metapopulation with several distinct fragments, which can be described as follows (LCIE 2007):1. Iberia Wolves are found in the north-western quadrant of Iberia including the western Basque country. Not in the Pyrenees, but south as far as Ávila. A very small number of wolves is isolated in the Sierra Morena mountains in southern Spain (Blanco and Cortés 2002, Álvares 2005).2. Western-Central AlpsThe population occupies an area that includes most of the Western Alps in France and Italy, many wolf packs territories being transboundary along the French-Italian border south of Valle d’Aosta. Isolated animals are dispersing regularly into Switzerland as far as Grisons but failed, until now, to establish a permanent pack (Boitani 2003, Marucco et al. 2005, Tropini et al. 2005). 3. Italian peninsulaWolves occur in the whole Apennines range from Liguria to Calabria (Aspromonte) and extending into northern Lazio and central western Tuscany (provinces of Siena, Grosseto and Pisa) (Ciucci and Boitani 1998, Corsi et al. 1999, Boitani 2003).4. Dinaric-BalkanThe population cover a vast area from Slovenia to north-central Greece and it includes the whole Dinaric mountain range through Croatia, Bosnia-Herzegovina, western Serbia and Kosovo, Montenegro, F.Y.R.O. Macedonia, Albania, western and southern Bulgaria. 5. CarpathianThe central Carpathian mountains in Romania are home of one of the healthiest and more numerous wolf population in Europe. This population extends across several countries, from Northern Bulgaria to Eastern Serbia, Romania, south-western Ukraine, Slovakia and southern Poland. Wolves are rarely reported in the Czech Republic.6. BalticThis population covers eastern Poland, Lithuania, Latvia, Estonia, Belarus, northern Ukraine and the Russian oblasts of Kaliningrad, Lenningrad, Novgorod, Pskov, Tver, Smolensk, Bryansk, Moscow, Kursk, Belgorod and Orel.7. KareliaWolves occur in Finland (mainly in the south) and Russian Karelia. The Finnish wolf population is a fringe population of a large Russian population.8. ScandinaviaThe distribution range of the population is in central Sweden and, to a lesser extent, in south-eastern Norway. It is spreading slowly toward southern and northern Sweden and into southern Norway.9. Germany/western PolandThis population consists of scattered packs living in eastern Germany (Saxony) and western Poland.","Because of the diversity in climate, topography, vegetation, human settlement and development of wolf range, wolf populations in various parts of the original range vary from extinct to relatively pristine. Wolf densities vary from about one per 12 km² to one per 120 km². Sillero et al. (2004) provide details, for each range country in the world, on subspecies present, population status, approximate numbers, the percentage of former range occupied at present, main prey (where known), legal status, and cause of decline. The European wolf population is a large metapopulation with several distinct fragments, although dispersal could theoretically connect almost all fragments. Following the bottleneck of the 1960s and 1970s, the European wolf population is generally increasing in number and expanding the distribution range. However, most European populations are still small and only a few have more than 1,000 animals (see below for specific details). Dispersing animals can be found anywhere in Europe. The total number of wolves in the EU 25 is likely to be in the order of 4-5,000; some of the populations are in continuity with wolf populations living in countries not yet part of the EU. The number of wolves in geographic Europe is likely to exceed 10,000.1. IberiaPopulation size: 2,500 wolves (including c.50 in the Sierra Morena). The Iberian wolf (Canis lupus signatus) may be a distinct subspecies. After the population reduction up to the 1960s, it is currently increasing in numbers and expanding its range across central Spain. The northwestern population is expanding, having recently crossed the Duero river in Spain. There are three distinct population segments within this population. The largest is that north of the river Duero in both countries. South of the Duero in Portugal there is a small segment of around 50 wolves which has only limited exchange of animals with the segments north of the Duero in Portugal and east to the Spanish segment south of the Duero. The isolated population in the Sierra Morena numbers c.50 individuals and appears to be stable. The nearest wolf population is in the Western Alps and connections between the two are nonexistent or limited to exceptional cases. In Cataluña, there are currently 2-3 wolves that have been genetically identified as members of the Alpine population from where they are assumed to have dispersed naturally (Blanco and Cortés 2002, Álvares 2005). 2. Western-Central AlpsPopulation size: 100-120 wolves. This population is of Italian origin and all wolves share the same Italian genetic haplotype. Individual wolves dispersing from the Apennines first colonized the Alps in 1992 and succeeded in establishing a permanent and expanding population which shows a highly dynamic spatial pattern spreading towards the west and north. The total number is estimated to be 100-120 wolves, increasing on average by 10% per year. The genetic continuity with the Apennines population has been recently assessed at 2.5 individuals per generation, all of them moving from the Apennines to the Alpine population. In 2005, a young radio-marked wolf dispersed more than 1000 km from Parma to Nice, providing evidence of the natural dispersal along the northern Apennines range. In spite of the continuity between the two populations, their ecological and socio-economic contexts are sufficiently different to justify a separation for management purposes (Boitani 2003, Marucco et al. 2005, Tropini et al. 2005, LCIE 2007).3. Italian peninsulaPopulation size: 500-800 wolves. The population has been described in 1921 (Altobello 1921) and confirmed in 1999 (Nowak 1999) as a distinct subspecies (Canis lupus italicus). It is genetically recognized by the presence of a unique mtDNA haplotype. After the population bottleneck of the 1960s, when total numbers were estimated to be about 100 animals, the population has steadily recovered and expanded into the western Alps. In 2006, the population was estimated to be 500-800 wolves. The nearest population (apart that in the Western Alps, see above) is in Slovenia (Dinaric-Balkan population). However, a large portion of the central Alps and the agricultural Po river valley effectively separate the Italian and the Dinaric populations (Ciucci and Boitani 1998, Corsi et al. 1999, Boitani 2003).4. Dinaric-BalkanPopulation size: 5,000 wolves.There is continuity of the population and suitable habitats throughout the range although the population might be significantly structured within the elongated range. The population is estimated to number c.5,000 individuals, although locally the densities may vary greatly and its overall demographic trend is unknown. In Croatia and Slovenia, the population has recovered significantly following active management started in the 1990s. To the north, the population has no contact with the nearest population in Italy, although dispersing animals are reported in Austria and eastern Italy. To the east, the population may exchange individuals with the large wolf population of the Carpathians which extends into northern Bulgaria (Iliopoulos 1999, Kusak et al. 2005, Štrbenac et al. 2005).5. CarpathianThis population is estimated to number c.5,000 animals, the majority of them living in Romania and Ukraine. Slovakia hosts about 400-500 wolves and southern Poland contributes with good wolf habitat in the areas along the south-eastern borders (wolf population in Polish Carpathians is about 180-220 individuals). In the past, there was natural continuity with wolves living in northern Poland and Belarus but the link is now constrained by large areas where wolves have been exterminated. Nevertheless, it is likely that some level of genetic exchange still occurs with the Dinaric-Balkan population in western Bulgaria and with the Belarusian population in eastern-central Poland (Okarma 1993, CLCP 1997-98, 2000, 2001, 2002; Smietana and Wajda 1997, Okarma et al. 2000). 6. BalticPopulation size: 3,600 wolves. The trend throughout the region appears to have been very consistent. At the start of the 20th century populations were reduced, but still widely present, these increased during and after World War 1. In the period between the wars, populations were greatly reduced again, but recovered to peak levels during and after Word War 2, only to be heavily persecuted in the 1950s such that they again reached very low levels in the 1960s and early 1970s. The populations appear to have then increased, peaking in the early 1990s – before being shot down again in the late 1990s. There are about 1,000 wolves in Poland and the Baltic States, about 1,000 in Belarus and 1,600 in the neighbouring Russian oblasts. This population is the westernmost portion of the large Russian population and it connects with the wolf range of Russian Karelia. In Poland, although the distribution is not continuous, it is highly likely that dispersal is still possible between the northern and southern populations (Carpathian), and dispersal towards west (Germany) is still observed (Bluzma 2000, Ozolins and Andersone 2001, Valdmann 2001, Sidorovich et al. 2003, Linnell et al. 2006). 7. KareliaPopulation size: 750 wolves. Following widespread control of the population in the first part of 20th century, the population recovered after the 1980s and 1990s. The current estimates are based on counts of family groups in Finland (about 200 wolves in Finland) and the population is expanding. In Karelia wolf numbers appear to be stable.8. ScandinaviaPopulation size: 130-150 wolves. The population derives from a pair that immigrated from Finland and first reproduced in Sweden in 1983. A third immigrant in 1991 boosted the reproduction and the population is now estimated to be 130-150 wolves (about 20% in Norway), with as many as 15 litters produced in 2006. The population has been steadily increasing from 1983-2001, then slightly decreased in 2002-3, and is currently increasing again. There is evidence of no genetic exchanges with the Finnish/Russian wolf population after 1991. Immigration from Finland is the only possible mechanism to increase the genetic variability of the population.9. Germany/western PolandPopulation size: <50 wolves. Wolves were exterminated in Germany during the 19th century, but individuals that were dispersing from Poland were shot occasionally throughout the 20th century. In the mid 1990s a pack began breeding in Saxony, and there are currently two packs breeding regularly. Wolves in western Poland have had a dynamic history, but presently there are only a few widely scattered packs throughout the region. This population is extremely fragmented internally. Potential connections exist to both the Baltic and Carpathian populations, but the distances are in the order of several hundred kilometers.","Wolves live in diverse habitat types and their broad distribution ranges show the species' adaptability to the most extreme habitat conditions. The wolf's habitat has been described as everywhere where humans do not kill it and where there is something to eat. Where wolves depend on wild ungulate prey, their habitat is that of their prey. Habitat quality should thus be interpreted in terms of human disturbance, prey densities and range size. In general, large forest areas are particularly suitable for wolves in Europe, although wolves are not primarily a forest species. The wolf has a very diversified diet and is a true generalist that feeds opportunistically on what is most available in its habitat. The wolf diet may include large prey, such as moose, deer and wild boar, or small vertebrates, invertebrates, vegetables and carcasses. Diet composition throughout the geographic range and seasonal variations depends on the relative abundance of potential prey, as well as accessibility and availability. A wolf typically requires 3-5 kg of meat per day, although it can fast for several days when food is not readily available.","Human intolerance is perhaps the greatest threat facing wolves in Europe today. Fear, misunderstanding and the fact that wolves do kill livestock have prompted an uneasy relationship with people in many areas, leading to direct conflict and persecution. In some countries unrestricted hunting of wolves poses a threat, while in others, licenses for killing wolves are issued irrespective of biological understanding. Poaching is widespread and probably represents the most important mortality factor for the wolf in Europe. Wolves preying on domestic animals have been a problem since man progressed from hunter/gatherer to farmer, and although the numbers of sheep or cattle taken are, as a percentage very low, livestock depredation remains the primary reason for exterminating wolves. Human encroachment is the most significant threat to wolf habitat. Wolves can live close to humans but they require safe areas in which to retreat. This is not considered in land planning in wolf areas and the small, fragmented populations in Western Europe can result in animals moving into unsuitable habitat. Specific threats to different European wolf populations are as follows:1. IberiaIllegal killing is still common (estimated to account for 50% of the total mortality) and poison baits are used (Blanco and Cortés 2002, Álvares 2005). 2. Western-Central AlpsDocumented causes of mortality include primarily car or train accidents and poaching events. Several cases of illegal killings have been reported in France and Italy, and conflicts with hunters and farmers are constantly reported. Both France and the Regional Government of Piemonte have been carrying out extensive and continuous research and monitoring of the wolf population and the damages to livestock and excellent data is available for management purposes. The number of livestock depredations in the Italian Alps is decreasing, despite the increase in wolf numbers, due to the high efforts in the implementation of preventive practices promoted by the Regional Government of Piemonte. Also if the wolf presence is still far from being accepted by local farmers and livestock breeders, the general attitude is improving (Boitani 2003, Marucco et al. 2005, Tropini et al. 2005).3. Italian peninsulaThe population is protected on paper but the law is poorly enforced and unpersecuted illegal killing is very common throughout the range. Poison baits are increasingly used against dogs, foxes and wolves. Hybridization with dogs has been found and it appears to account for at least 5% of the total wolf population (Ciucci and Boitani 1998, Corsi et al. 1999, Boitani 2003, Verardi et al. 2006). 4. Dinaric-BalkanLegal hunting and illegal killing are taking an unknown number of wolves throughout most of the range. Other pressures are commonly reported: widespread use of poisons, habitat fragmentation due to construction of fenced highways and shortage of wild preys (Huber et al. 2002, Iliopoulos 2005).5. CarpathianPoison baits and illegal killing are widespread throughout the range. In Ukraine, wolves are often treated as a pest species.6. BalticThe Latvian population appears to be on the way to being divided into two, with the area south of Riga starting to appears as a carnivore free area. This development will greatly increase the vulnerability of carnivore populations in western Latvia. 7. KareliaThe main threat to wolves in this region is killing by humans. In Finland, wolves cause very limited damage to livestock; predation on domestic dogs is the most frequent damage that cause strong resentment from the public. 8. ScandinaviaThe inbreeding coefficient is very high, on average higher than for full siblings mating (Liberg et al. 2005). Predation on domestic dogs, sheep and reindeer are the most frequent damages that cause continuing debate on wolf conservation.9. Germany/western PolandThe main risk for this population is its very small size, highly fragmented internal structure, and long distance from any other source. Coordination between Germany and western Poland is crucial. A single litter of wolf-dog hybrid pups was born in 2003.","The species is strictly protected by the Bern Convention (Appendix II) and is in Appendix II of CITES. In the European Union the species is protected by the Habitats Directive but there are several exceptions:1) in Spain, wolves north of the Duero river are not protected2) in Greece, wolves north of 39°N are not protected3) in Finland, wolves occurring in the reindeer herding area in northern Finland fall under Annex V of the Habitats Directive; wolves outside the reindeer herding area fall under Annex IV4) in the Baltic States (Estonia, Latvia and Lithuania) wolves are harvested (HD Appendix V)In general, habitat restoration is required in key areas to increase a healthy prey base and encourage wolves to move back into their former territory where appropriate. Corridors of land between small populations need to be established to allow movement of animals and prevent local extinctions. Conflict with humans needs to be addressed by involving local people in wolf management plans and through education programmes to increase people' s understanding of wolf biology and behaviour. Problems resulting from wolves preying on domestic animals need to be tackled by livestock protection schemes and compensation systems. Details of specific conservation measures for European wolf populations are given below: 1. IberiaWolves are fully protected in Portugal and south of the Duero river in Spain. North of the Duero, wolves are game species under various management regimes depending on legislation of 8 autonomous regional governments. Asturias has a wolf management plan and Galicia and Castilla y León are about to approve their plans. The autonomous regions are gradually approving their action plans. However, management coordination among the regional governments and between Spain and Portugal is very limited. The sub-population of Sierra Morena require ad-hoc management to ensure its viability (Blanco and Cortés 2002, Álvares 2005).2. Western-Central AlpsThe population is fully protected under the French, Italian and Swiss law. In France and Switzerland the national Action Plans include provisions for legal take of few wolves under strict conditions of damages on livestock. The three countries have recently (2006) signed a formal agreement of cooperation for the management of the entire population, marking an innovative procedure based on the recognition that the biological population needs to be managed through a common and accepted approach. 3. Italian peninsulaFully protected by a national law, while damage compensation is provided by 14 different regional laws. Compensation paid per wolf has been estimated to be the highest among European countries, but the effectiveness of compensation programs has never been assessed and it is increasingly questioned. Apart from formal protection the population is not actively managed. The species occur in several protected areas throughout its range but the size of these areas is far too small to protect a viable population. In spite of formal protection, illegal killings are estimated to take a substantial portion of the population every year (up to 15-20%). A national Action Plan sets the broad strategic ground for management but is not being implemented by the national and regional governments (Ciucci and Boitani 1998, Corsi et al. 1999, Boitani 2003). 4. Dinaric-BalkanManagement is fragmented by several national laws. It is a game species in almost all countries, except for Slovenia, Croatia and Greece south of 39° latitude where wolves are fully protected. In Croatia, an effective Action Plan is in place and implemented (Štrbenac et al. 2005). In general, law enforcement is weak or totally absent even in protected populations.5. CarpathianIn Slovakia wolves are game species with hunting season 1.11-15.1 and no quotas per season; in the Czech Republic they are protected game species, but hunting is prohibited; in Poland they are protected and in Romania they are protected game species with hunting quotas decided yearly; in Ukraine wolves are not game species nor protected (often treated as “pest” species, with bounties of c.20 Euro per individual) (Salvatori et al. 2002). 6. BalticThe standard management practice for most of the 20th century was open harvest, often with bounty incentives, all with the view of exterminating wolves, or at least seriously reducing their numbers. This situation persisted until the 1990s, when restrictions on their harvest gradually came into place in all countries They are currently protected in Poland, but harvested in the three Baltic States (EU Habitats & Species Directive Appendix V) and in Belorussia and Ukraine. The sub-population of western Poland and Germany requires ad-hoc management to ensure its viability. There is an action plan for the conservation of the wolf in Latvia (Ozolins and Andersone 2001).7. KareliaIn Finland, wolves occurring in the reindeer herding area fall under Annex V of the Habitats Directive; those outside the reindeer herding area fall under Annex IV. Finland has recently approved a National Management Plan that include removal of some wolves under controlled circumstances. In Russian Karelia, wolves are killed throughout the range and at any time. In spite of the small number of wolves, Finland has approved a plan to maintain the population within the current size (Ministry of Agriculture and Forestry 2006). Discontinuous flow of dispersing wolves from Russia allow a reasonable but cautiously positive forecast on the conservation of this population.8. Scandinaviait is fully protected in Sweden and Norway; however, Norway applies a zoning system that includes culling of wolf numbers in the areas where damages are considered unacceptable. Both Norway and Sweden provide full compensation of damages; Sweden applies a preventive compensation system to reindeer breeders that operate in areas where wolves live.9. Germany/western PolandWolves are protected in both countries, but the extent to which protection is enforced in western Poland is questionable.",Large Carnivore Initiative for Europe +ANIMALIA,CHORDATA,MAMMALIA,CARNIVORA,CANIDAE,Vulpes corsac,"Canis corsac Linnaeus, 1768:223. Type locality: “in campismagi deserti ab Jaco fluvio verus Irtim”; restricted by Ognev (1935) as “USSR, N. Kazakhstan, steppes between Ural and Irtysh rivers, near Petropavlovsk” (in Honacki et al. 1982). It has been suggested that Canis eckloni described by Przhevalski (1883) from Northern Tibet is a subspecies of the corsac (Ellerman and Morrison-Scott 1951). However, Canis eckloni is in fact a junior synonym for Vulpes ferrilata (Geptner et al. 1967). This confusion probably originated from earlier work by Przhevalski referring to the latter as “corsac”. Chromosome number: 2n=36, FN=72 (Aristov and Baryshnikov 2001).",No,No,LC,,NE,,"European regional assessment: Least Concern (LC)EU 25 regional assessment: Not Evaluated (NE)The corsac is found in central Asia, ranging into Mongolia and northeastern China. Populations fluctuate significantly. Population decreases are dramatic, caused by catastrophic climatic events, and numbers can drop tenfold within the space of a single year. Corsac foxes have the ability to forego water and food for extended periods of time. They are well adapted to a hot and dry climate. Current population status, and the nature of major threats, is unknown in most regions. However, the species is not considered threatened at present.",-,"Narrower than the historical range and includes two parts. The first covers the Middle Asian republics of Turkmenistan, Uzbekistan, Tajikistan and Kazakhstan, as well as steppe and forest-steppe areas of Russia, including the southern region of Western Siberia. In Europe its range reaches the Samara Region, Tatarstan to the North and northern Caucasia to the South. The second, much smaller area lies in southern Transbaikalye representing the northern periphery of the Mongolian and Manchurian section of the species area. Outside Russia the species area includes the steppe part of north-eastern China, including Manchuria, Inner Mongolia, and the region between Argun and Big Khingan, the entire Mongolian republic except for its forested and mountain regions, Dgungaria, Kashgaria, Afghanistan (probably only northern) and north-eastern Iran. Southern limit of distribution is unknown, but possibly it reaches to the mountain ridges separating the Tibet Highland from the North. Thus, the two ranges (western and eastern) are connected by a relatively narrow neck in the Dgungar Gate and Zaisan Basin region. In recent years a westward area expansion has been recorded, particularly into the Voronezh region following active recovery of baibak (Marmota bobak) populations. Occasionally, the species is recorded from the Ukrainian steppe (as far as Pavlodar to the West), eastern Transcaucasia (Azerbaijan) and, probably, western Kyrgyzstan.","Corsac populations fluctuate significantly. Population decreases are dramatic, caused by catastrophic climatic events, and numbers can drop tenfold within the space of a single year. On the other hand, in favourable years numbers can increase by the same margin and more within a three to four year period. Corsac foxes have the ability to forego water and food for extended periods of time. They are well adapted to a hot and dry climate. Current population status is unknown in most regions. Dramatic population changes were reported during the last century in PredKavkazie, between Kuma and Terek rivers and in Kuma-Manich Channel region. A drastic population decline was reported at the beginning of the last century (Dinnik 1914). Numbers had recovered by 1924 to 1925; one hunter during that time could take up to 15–30 corsac foxes in one season (Ognev 1931). By 1931 numbers decreased again with a subsequent increase in 1951 (Verezhagin 1959). In the Ural region during particular years up to 5,500 animals were taken by trappers, and up to 1,700 in the Gurievskaya region. To the south, in Mangishlak and Ustyurt, the corsac is widespread and in some years abundant. In Russia the corsac is rare in most regions, but common in West Siberia and Transbaikalie. It sometimes occurs in northern parts of West Siberia's forested steppes, but in low numbers. The species is common everywhere between the Volga and Ural rivers. In Turkmenistan, Kazakhstan, Mongolia and northern China, the corsac is common or abundant, although in Tajikistan and Uzbekistan the species is usually rare. Population status in Afghanistan and Iran is unknown.","The corsac typically inhabits steppes, semi-deserts and deserts, avoiding mountains, forested areas and dense bush. In the western part of the range they occur in low-grass steppe, avoiding dense and tall grass steppes. In Kaspyi Sea region the steppes and tarragon-cereal semi-deserts are favoured. It also occurs in fixed-sand habitats (Nogaiskaya Steppe). In Volgo-Ural watershed the corsac inhabits most usual habitats, but prefers semi-deserts. To the east of the Ural Mountains, the species inhabits steppes and in favourable years occurs even in forested steppes. In Kazakhstan typical habitats are low grass steppes and semi-deserts, often inhabiting low hills, but avoiding low mountains. In Middle-Asia it inhabits semi-deserts and ephemeral-deserts, avoiding drifting sands. One limiting factor is snow height in winter, and this species avoids areas where the depth of snow exceeds 150 mm, preferring areas where the snow is either shallower or highly compressed.Corsac foxes appear to depend on distribution of ground squirrels and marmots for food and shelter (the burrows being enlarged and used for refuge).","Development in Kazakhstan in the mid-1850s caused a significant reduction of corsac numbers in previously undisturbed habitats. In the 20th century several catastrophic population declines were recorded. During such crashes hunting on corsac foxes in the former Soviet Union was banned. For example, hunting of corsac foxes was stopped within the entire Kazakhstan territory from 1928 to 1938. Current population status, and the nature of major threats, is unknown in most regions. The western part of the range populations are recovering and their range expanding. In Kalmikiya large desert areas are changing into grass steppes, less suitable for corsac foxes. In Middle Asia and Kazakhstan a dramatic decrease of livestock during the last decade influenced many ecosystems and wildlife populations. However, the exact influence of this process on corsac populations remains unknown.Corsac pelts have been intensively traded. In general, over much of Russia during the 19th century, as many as 40,000–50,000 corsac pelts were traded in some years. For the time being, corsac pelts are not as highly appreciated as red fox pelts, and corsac foxes are usually trapped only incidentally.","Corsac foxes are protected in strict nature reserves (the highest protection status for the territory) and in national parks in China, Russia, Turkmenistan, Uzbekistan and Mongolia.Not listed on CITES Appendices.Listed in some regional Red books in Russia: Bashkir (Volga tribute) and Buryat (Transbaikalia region) with category III status (species with declining populations).Hunting of corsac foxes is regulated by special national legislation, in which the species is considered a fur-bearer species (Russia, Kazakhstan, Turkmenistan, Uzbekistan, Mongolia). Trapping/hunting is allowed only from November through March in Russia, Kazakhstan, and Turkmenistan. Certain methods of hunting are prohibited, such as digging or smoking animals out of dens, den flooding, and poisoning.No special conservation programmes have been carried out. Outside of protected areas, the corsac has the status of game species.Corsac foxes breed well in captivity, and there are some 29 animals currently listed in ISIS. In Moscow Zoo during 1960s one pair of corsac foxes produced six litters during the time that they remained together. Corsac foxes are easily habituated to humans.There are several aspects of this species' biology that require investigation, including social organization and behaviour, population structure, current distribution and population status in different regions, current levels of trapping/hunting impact, and other threats to the species.","Global assessment by A. Poyarkov and N. Ovsyanikov, regional assessment by European Mammal Assessment team" +ANIMALIA,CHORDATA,MAMMALIA,CARNIVORA,CANIDAE,Vulpes vulpes,,No,No,LC,,LC,,European regional assessment: Least Concern (LC)EU 25 regional assessment: Least Concern (LC)A very widespread and extremely abundant species that is highly adaptable to man-made habitats. It faces no major threats. It thus qualifies as Least Concern.,Possibly Favourable,"The red fox has an extremely large range. It is distributed throughout the northern hemisphere, from the Arctic Circle to North Africa, Central America, and the Asiatic steppes. It is absent from Iceland, the Arctic islands, some parts of Siberia, and it avoids desert areas. It occurs throughout the whole of Europe, with the exception of Iceland, Svalbard, Crete, and some of the smaller Mediterranean and North Sea islands (Hall 1981, Ginsberg and Macdonald 1990, Abe 1994, Stubbe 1999, Wilson and Ruff 1999, Abe et al. 2005). European subspecies were introduced to the eastern states of the US (e.g. Virginia) in the 17th Century, mixed with local subspecies, and then moved southwards with forest clearance. The species was also introduced to Australia in 1800s. Elsewhere introduced to the Falkland Islands (Malvinas) and to the Isle of Man (UK), although it may subsequently have disappeared there (Sillero-Zubiri et al. 2004). It occurs from sea level to 3,000 m (Stubbe 1999).","It is the most widespread and abundant wild carnivore in the world (Larivière and Pasitschniak-Arts 1996) and there are stable populations throughout Europe. In central Europe, populations are increasing owing to the oral immunisation of foxes against rabies (Stubbe 1999). In Germany 500,000 are killed every year by hunting (M. Stubbe pers. comm. 2006). In the UK the population was recently estimated to number approximately a quarter of a million animals (Battersby 2005).","In Europe it is found in a very wide variety of habitats including all types of forest and open landscapes. It is well adapted to many anthropogenic habitats including farmland and suburban and urban areas (Larivière and Pasitschniak-Arts 1996, Stubbe 1999). Red foxes are adaptable and opportunistic omnivores, with a diet ranging from invertebrates (e.g. earthworms and beetles) to mammals and birds (including game birds), and fruit. They also scavenge in rural areas (e.g. in Europe and Canada on deer and sheep carcasses which may be the major food source in upland areas inwinter), and in urban areas (on bird tables, compost heaps and refuse) (Sillero-Zubiri et al. 2004).","It is hunted for sport, and is persecuted as a pest (Stubbe 1999). However, this is not a threat to the survival of the species.","It is present in most protected areas in temperate and subarctic regions, with the exception of some inaccessible islands. It is widely regarded as a pest and is not protected, although most range states where trapping or hunting occurs have regulated closed versus open seasons and restrictions on methods of capture. In the European Union, trapping methods are regulated under an agreement on international trapping standards that was signed in 1997 (Sillero-Zubiri et al. 2004). Controlling red foxes may be necessary where rare species, or threatened populations, are at risk from red fox predation (Sillero-Zubiri et al. 2004). For example, nest predation by foxes has completely prevented recruitment to an internationally important sandwich tern colony in a number of consecutive years (Musgrave 1993).","Andreas Kranz, Alexei Tikhonov, Jim Conroy, Paulo Cavallini, Juan Herrero, Michael Stubbe, Tiit Maran, Margarida Fernandes" +ANIMALIA,CHORDATA,MAMMALIA,CARNIVORA,FELIDAE,Felis chaus,"Includes six subspecies, only the nominate occurs in Europe.",No,No,NA,,NE,,"European regional assessment: Not Applicable (NA)EU 25 regional assessment: Not Evaluated (NE)In Europe and the Caucasus Felis chaus is declining rapidly and only a small number of mature individuals survive in the wild. It is listed in the Red Books of the Russian Federation, Armenia, Azerbaijan and Georgia. At the European regional level the species is considered Not Applicable because only a very small proportion (much less than 1%) of the global population occurs within the region. This listing should not detract from the fact that population declines in this species are a major cause for concern.",-,"The jungle cat has a very broad range, from Southeast Asia west through India, Southwest and Central Asia, the Arabian Peninsula, and finally into Africa along the Nile River Delta.","It is a relatively common species throughout much of the range. In Europe, it is of marginal occurrence, with small populations in Cis-Caspian region and the Caucasus along the Caspian Sea. The European population has been rapidly declining since the 1960s. There have been no records of this species in Astrakhan State Reserve (Russian Federation) since the 1980s. Marked population fluctuations are characteristic of this species, probably because of absence of adaptations to cold winters. Despite these fluctuations the long-term trend in Europe is of decline in both population and area of occupancy. Data from Russia suggest that there are about 500 animals left in the wild (Prisazhnyuk and Belousova 2007). A very small population persists in Georgia (I. Macharashvili pers. comm. to K. Tsysulina 2007).","The jungle cat, despite its name, is not strongly associated with closed forest, but rather with water and dense vegetative cover, especially reed swamps, marsh, and littoral and riparian environments. It is able to satisfy these requirements in a variety of habitats, from desert to scrub woodland and dry deciduous forest, as well as cleared areas in moist forest (Nowell and Jackson 1996).","Jungle cats do well in cultivated landscapes (especially those that lead to increased numbers of rodents) and artificial wetlands. However, reclamation and destruction of natural wetlands, ongoing throughout its range but particularly in the arid areas, still pose a threat to the species, as density in natural wetlands is generally higher (Nowell and Jackson 1996). Thousands of jungle cat furs have been confiscated in illegal trade in India (Mukherjee 1998). In Europe, population and range declines since the 1960s have been attributed to illegal hunting and artificial landscape change.","Included on CITES Appendix II. Hunting is prohibited in Bangladesh, China, India, Israel, Myanmar, Pakistan, Tajikistan, Thailand and Turkey (Nowell and Jackson 1996). This species is considered threatened in a number of range states in Europe and the Caucasus, and is included in the Red Books of the Russian Federation, Armenia, Azerbaijan and Georgia. It is considered possibly extinct in Georgia.","Global assessment by IUCN SSC Cat Specialist Group, regional assessment by European Mammal Assessment team" +ANIMALIA,CHORDATA,MAMMALIA,CARNIVORA,FELIDAE,Felis silvestris,"Populations of wildcats occur on Crete, Corsica, Sardinia, and the Balearic Islands. Some authorities consider these populations to be discrete subspecies, related most closely to the lybica group, and among the most endangered populations in Europe (see Nowell and Jackson 1996 for references). Vigne (1992), Hemmer (1999) and Gippoliti and Amori (2006) on the other hand, consider them to be feral forms of domestic cats introduced centuries before by humans. The Sardinian wildcat has been assigned to the libyca group on the basis of both morphological and genetic evidence (Ragni 1981, Ragni and Randi 1986, Ragni and Possenti 1996, Randi et al. 2001); and a similar case could be made for the Corsican wildcat (Salotti 1993) and that of Crete (Ragni et al. 1999). However, the wildcat of Sicily is generally considered to be an autochthonous population of F. s. silvestris, and may warrant the status of a conservation unit, given its genetic distinctness from the mainland Italian population (Randi and Ragni 1991, Randi et al. 2001, Gippoliti and Amori 2006).",No,No,LC,,NT,,"European: Least Concern, given that there are large and stable populations in the eastern portion of the region. The category “Least Concern” can be misleading, for although the wildcat is probably the most widespread and numerous felid in the region, it is seriously threatened in some areas by genetic loss through hybridization with domestic cats. EU 25: Near Threatened (approaching A4e). It is expected that hybridization with domestic cats will cause population declines approaching 30% over 15 years (3 generations) including both the past and the future. It is unlikely that there would be a rescue effect from the eastern populations because of increasing habitat fragmentation. There is particular concern for the wildcat population north of the Alps. It is clearly adapted to the cold climate, and if conservation fails it could not be replaced by animals from the Mediterranean. The Scottish wildcat is scarce and declining, and is currently listed as Vulnerable on the IUCN Red List of Threatened Species. It may warrant uplisting to a higher category of threat.The Iberian subpopulation is suspected to be declining at a rate of >30% over 3 generations in the past or future, and should be listed as Vulnerable.Other isolated subpopulations (France/Germany, Italy, some Mediterranean island populations) face a greater level of threat than the species as a whole. These subpopulations are significant units for conservation, and thus it might be helpful to carry out separate subpopulation Red List assessments in the future; listing in a threatened category (e.g., Vulnerable, Endangered, or Critically Endangered) would be the likely outcome.",Unfavourable,"The wildcat has a very wide distribution stretching across Europe (F. silvestris, silvestris group), South West and Central Asia (F. silvestris, ornata group), and Africa (F. silvestris, lybica group) (Nowell and Jackson 1996). In Europe it was formerly very widely distributed and absent only from Fennoscandia. Severe declines and local extirpations occurred in Europe between the late 1700s and mid 1900s, resulting in a fragmented relict distribution (Stahl and Artois 1991, Nowell and Jackson 1996, Peichocki 2001). Previously considered extinct in the Netherlands (Nowell and Jackson 1996), but it may be recolonizing from populations in the Eifel or Ardennes forests (Canters et al. 2005). It was considered regionally extinct in Austria (Spitzenberger 2005), but vagrants still occur and the Italian population is spreading northwards into Austria (Lapini and Molinari 2006). It is possibly extinct in the Czech Republic (EMA Workshop 2006). Wildcats (silvestris group) occur on Sicily, and populations of cats assigned to the libyca group occur on Crete, Corsica, Sardinia, and the Balearic Islands. Feral domestic cats are also found on numerous other small Mediterranean islands. It occurs from sea level to 2,250 m in the Pyrenees (Palomo and Gisbert 2002). In some parts of the wildcat's distribution (e.g. Scotland, Stromberg in Germany) it is possible that, as a result of hybridization with the domestic cat, very few genetically pure wildcats remain (Macdonald et al. 2004, Battersby 2005, Herrmann and Vogel 2005).","One of the major barriers to the effective conservation of the wildcat in Europe is the lack of information regarding its current status and population trends (Macdonald et al. 2004). There have been no recent large-scale surveys or European regional reviews of the status of the species (Macdonald et al. 2004). During the European Mammal Assessment process, information (ranging from detailed national surveys to expert opinion) was collated for a number of European range states and is presented here, but this is by no means a comprehensive review. A review of the status of the wildcat in Europe in the 1980s and early-mid 1990s can be found in Stahl and Artois (1991) and Nowell and Jackson (1996).Scotland (UK): Recent estimates have varied between 1,000 and 4,000 (compared to 1.2 million feral cats in Britain), but as few as 400 cats with classical wildcat pelage may survive, and it is possible that very few genetically pure wildcats remain (Macdonald et al. 2004, Battersby 2005). If so, this putative subspecies would be Critically Endangered (Kitchener et al. 2005). Surveys show that 30% of populations have declined, whilst only 8% are increasing (Battersby 2005). The Scottish wildcat is currently listed as Vulnerable on the IUCN Red List of Threatened Species.Portugal: The population is suspected to be decreasing (M. Fernandes pers. comm. 2006). Considered Vulnerable at the national level, on the basis of suspected declines reaching 30% over three generations in the past or future (Cabral et al. 2005).Spain: In some places it is increasing and others decreasing (J. Herrero pers. comm. 2006). Considered Vulnerable at the national level, on the basis of suspected declines of over 30% over the last three generations (Palomo and Gisbert 2002).Belgium: Evidence from wild cats found dead on roads indicated that the species is gradually expanding its range to the north and west. There are no data on population size (Libois 2006).Germany: The population was recently estimated at 1,700-5,000 individuals (Knapp et al. 2000). The population is increasing and occupying new areas (M. Stubbe pers. comm. 2006). Switzerland: The wildcat persists in the Jura Mountains in northwestern Switzerland, adjacent to the French population. It was very rare in the 1970s, but records started to increase in the late 1980s (Doetterer andBernhart 1996) and are now reported on a low, but regular frequency over the whole of the Swiss Jura Mountains. No population estimation available. Italy: The estimated number of wildcats is between 750 and 1000 individuals (Ragni 1981, Ragni et al. 2001), which remains unchanged due to the slight range expansion in the middle and north-east, accompanied by extinction in the north-western peninsula (Ragni 2006). Slovenia: The population is estimated (on the basis of density and habitat suitability) at no more than 2,000; it is stable. Recently expanded highways possibly pose some threat in south-east part of its high density range. (B. Kryštufek pers. comm. 2006)Poland: Estimated number of wildcats in Poland is between 100 and 150 individuals, estimated density is 1-1.3 per 1000 ha (Okarma et al. 2002). The current distribution of wildcat in the Polish Carpathians, mainly along the borders with Slovakia and Ukraine, shows that the Polish population forms a continuum with Slovak and Ukrainian populations. Together they constitute the northernmost part of the larger Carpathian population of this species. The species is decreasing and is considered endangered (EN) in Red Data Book of Poland (Wolsan et al. 2001).Slovakia: The estimate of the Slovakian population in 2000 was about 1,500 individuals (unpublished data of the Slovak Environmental Agency: A. Olszanska pers. comm. 2006). Serbia: There are large populations along the southern Danube (EMA Workshop 2006).Macedonia: The species is widespread (EMA Workshop 2006).Greece: The wild cat is widespread in continental Greece with sightings in all forested areas and many wetlands. There are apparently more sightings in north and north-east Greece, where the population density seems to be higher. The population trend has not been quantified but is believed to be stable. On Crete it occurs at low densities (G. Giannatos pers. comm. 2006).Romania: The population is estimated to number c.10,000 individuals, but this is not based on quantitative data (Red Data Book of Romania). Bulgaria: There are no quantitative data, but the species is considered relatively abundant (Spassov et al. 1997).European Russia: The population size and trend have not been quantified, but there are thought to be large, relatively stable populations (EMA Workshop 2006).In Scotland, 88% of wild-living cats may be hybrids or feral domestic cats (Kitchener et al. 2005), and in Italy and Hungary the proportion of hybrids is estimated at 8% and 25-31% respectively (using genetic nethods: Pierpaoli et al. 2003, Lecis et al. 2006). On the basis of museum specimens, the proportion of hybrids in Bulgaria was estimated at 8-10% (Spassov et al. 1997), but the extent of hybridization may have increased since specimens were collected. Wild cats of mixed origin have also been found in Belgium, Portugal, Germany (only one animal) and Switzerland (Pierpaoli et al. 2003). In general the genetic distance to the domestic cat is larger in the north of the range than in the south (Pierpaoli et al. 2003). Eastern European populations are generally considered to be relatively pure (Nowell and Jackson 1996). Assessing the status of the wildcat is difficult, becuse it is a cryptic species and, moreover, because it may be difficult for some experts to distinguish between specimens of European wildcat and domestic cat (Nowell and Jackson 1996). Morphological critera established by Kitchener et al. (2005) should help to resolve these problems.","European wildcats are primarily associated with forest and are found in highest numbers in broad-leaved or mixed forests with low densities of humans. They are also found in Mediterranean maquis scrubland, riparian forest, marsh boundaries and along sea coasts. Areas of intensive cultivation are avoided (Nowell and Jackson 1996). As with other wildcats, rodents are the staple of the diet of European wildcats across much of their range (Nowell and Jackson 1996, Biro et al. 2005) However, rabbits are a major prey where they occur (Nowell and Jackson 1996, Lozano et al. 2006). Birds (both passerine and ground-dwelling) are of secondary importance (Biro et al. 2005). The composition of the diet shows only minor seasonal variations: rabbits or rodents are the major year-round food items. In Italy, historical (1968-1983) and recent (1994-2004) diets of wildcats show highly significant differences in composition, with an overwhelming occurrence of arthropods, reptiles and murines in the most recent period; the change appeared to be directly correlated to the expansion of wood vegetation and growth of atmospheric temperature over the last twenty years (Ragni 2006). Wildcats will also scavenge food and cache their kills, especially in winter (Nowell and Jackson 1996). The overlap in trophic niche between wildcats and feral domestic cats is large (Biro et al. 2005), indicating the potential for competition between these two taxa. Age at sexual maturity is 10-12 months for females and 9-10 months for males, interbirth interval is typically one year (although females may exceptionally breed twice in a year if the first litter is lost), and longevity is exceptionally up to 15 years, but more typically up to 5-6 years (Nowell and Jackson 1996, Macdonald et al. 2004).","Habitat loss and persecution by humans caused the dramatic decline of this species in Europe in the 18th to mid 20th centuries. Today, the main threats are hybridization, disease transmission, and competition with feral domestic cats. There is ongoing habitat loss, fragmentation and degradation in some areas (e.g., Mediterranean bushland); although in some other parts of Europe forest cover is increasing as a result of abandonment of extensive agricultural land. The fact that wildcats have failed to recover across much of their former European range, despite decades of strict legal protection, indicates that although persecution has largely ceased, other factors are now limiting populations of this species.European wildcats suffer from hybridization with domestic cats, which descend from African wildcats. The process of domestication began thousands of years ago in North Africa and Southwest Asia, and domestic cats are now found in large numbers throughout the world, living in peoples' homes as well as feral in the wild. Feral cats compete with wildcats for prey and space, and there is also interbreeding or hybridization, which is leading to a strong decline in genetically pure wildcats in some areas. There is also a high potential for disease transmission between domestic cats and wildcats (Nowell and Jackson 1996, Fromont et al. 1998, Daniels et al. 1999), with some infections being maintained permanently in wildcat populations by transmission from domestic cats, when otherwise the diseases would die out (Fromont et al. 1998). A further risk is presented by the selective resistance of silvestris x catus hybrids to viral disease infection (Ragni and Possenti 1991, Ragni 1993). Other threats include significant human-caused mortality, especially road kills (Nowell and Jackson 1996, Lüps et al. 2002, Schulenberg 2005). The species is still considered a pest in Scotland and is illegally persecuted. Predator control measures in a number of European countries may result in this species being killed as bycatch. In Europe at least, the species has never been commercially exploited for its fur (Palomo and Gisbert 2002). Introduced feral domestic cats cause serious harm to native species in many parts of the world, and there have been suggestions that virus-vectored immunocontraception should be developed as a control method (Courchamp and Cornell 2000). Any such development should take into account potential risks to wildcats. In recent years there have been a number of cases of people taking young wildcats from the wild in the mistaken belief that they would make good pets (8 cases in two years in two areas in Germany, and another cat that was introduced from France into the Netherlands: Canters et al. 2005, Simon et al. 2005).","Included on CITES Appendix II. The species is fully protected across most of its range in Europe and eastern areas of Central Asia, but is only protected in part of its African range (Nowell and Jackson 1996). It is listed on the EU Habitats & Species Directive (Annex IV) and the Bern Convention (Appendix II). It is classed as threatened at the national level in many European range states.","Mathias Herrmann, Andrew Kitchener, Holger Meinig, Michael Stubbe, Margarida Fernandes, Jim Conroy, Giorgos Giannatos, Juan Herrero, Andreas Kranz, Agnieszka Olszanska" +ANIMALIA,CHORDATA,MAMMALIA,CARNIVORA,FELIDAE,Lynx lynx,,No,No,LC,,NT,,"European: The species has a wide range in Europe, and remains abundant in the eastern part of the range. Although population trends in European Russia have not been quantified, they are not believed to approach the threshold for the population decline criterion of the IUCN Red List (30% over 10 years or 3 generations). Consequently the species is classed as Least Concern at the European level.EU 25: The lynx was driven extinct in much of western and central Europe over the last few centuries. However, over the past few decades, as a result of conservation action, the status of the species has improved. Reintroductions have restored it to some areas of its former range, although many of these reintroduced populations remain fragmented and extremely small. However, the lynx population within the EU remains small (below the population size threshold for Vulnerable under Criterion C, although it does not currently meet the subcriteria). If ongoing conservation action ceased, it is expected that the species would quickly start to decline again, and could meet Criterion C1 in the near future. Consequently it is assessed as Near Threatened. Continued protection is required to ensure the continuing recovery of this species.1. JuraEndangered (D). This population results from reintroductions in 1974/75. It now numbers c.80 individuals, and the range is expanding. Consequently it qualifies as Endangered under Criterion D (very small population). Although potential corridors to neighbouring lynx populations (Alps, Vosges-Palatinian and Black Forest) exist, there are barriers to dispersal. Furthermore, these neighbouring lynx populations are small and threatened, so no rescue effect can be expected; consequently the Red List category is not adjusted.2. Vosges-Palatinian.Critically Endangered (C2a(ii), D). According to the current estimations, about 30-40 lynx exist in the area of the Vosges Mts.-Palatinian Forest. Whereas the most recent tendencies indicate a slight expansion of the range in the south, it has been decreasing in the north, and an overall decline is suspected. Although there are other lynx populations in relatively close proximity, there are significant barriers to dispersal and neighbouring populations are small and threatened, so no rescue effect is anticipated. Consequently the Red List category is not adjusted.3. Alpine.Overall the Alpine population of c.120 individuals is Endangered (D). If assessed separately, the Western Alps population (80 lynx) is Endangered (D) and the Eastern Alps population is Critically Endangered (D). It is not expected that either population would experience any significant rescue effect from neighbouring populations which are fragmented and tiny. Consequently the Red List category is not adjusted. 4. Bohemian-Bavarian.Critically Endangered (C2a(i)). The current estimate is around 75 animals. Whereas the population was increasing and expanding until the mid 1990s (the population was then estimated to be 70-100), since 1999 a marked decrease has been noticed. All individuals are part of the same subpopulation. Neighbouring lynx populations are small and threatened, and there are barriers to dispersal, consequently no rescue effect from them can be expected and the Red List category is not adjusted.5. Dinaric.Endangered (D). The Dinaric lynx population bases from re-introductions in Slovenia in 1973 where the animals reproduced well and spread quickly southwards. The current size is estimated to be about 130 animals with a stable to slightly decreasing trend, however sound monitoring has only been established recently (except for Bosnia-Herzegovina), and the long-term trend is therefore difficult to assess. The population extends over a continuous area of occupancy of about 24,000 km2, but due to the small population size has to be regarded as Endangered. Although there are other lynx populations in relatively close proximity, there are significant barriers to dispersal and neighbouring populations are small and threatened, so no rescue effect is anticipated. Consequently the Red List category is not adjusted.6. Carpathian.Least Concern. The Carpathians host one of the largest continuous lynx populations in Europe (area of occupancy about 100,000 km2). The overall number is about 2,500 lynx and is stable. An range expansion towards the south (Serbia) was noticed since 2000. For these reasons the population qualifies as Least Concern.7. Scandinavian.Least Concern. In the past few years, the increase of the Scandinavian population came to a halt. This occurred because, owing to conflicts with livestock breeders, lynx were strictly controlled. The population size seems to be more or less stable, with around 2,000 indiviuals occupyng around 650,000 km2 (area of occupancy). Consequently it qualifies as Least Concern. PVA results indicate that this population has low chance of extinction. The merging of the Finish (Karelian population) and Scandinavian distribution areas is recent, but a rescue effect could potentially be expected.8. Karelian.Least Concern. In Finland, there were no animals left by 1950, before recolonisation from Russia started. Since then, the population has been increasing and expanding, especially during the past two decades. The estimation in Finland was 1050-1100 animals in 2004 with an increasing and expanding trend. The 2005 estimate for Karelia oblast was 510 and appears to be stable. Although the Karelian population is relatively small (potentially close to 1,000 mature individuals), it is in continuity with large neighbouring populations, and there would be likely to be a significant rescue effect if this population were to decline. For all these reasons, the Karelian population is assessed Least Concern.9. Baltic.Least Concern. The population consists of around 3,400 lynx, of which 1,600 are found in the Russian portion. Although there was some reduction in numbers in Estonia and Latvia during the 1990s, numbers appear to have stabilised following the adjustment of hunting quotas. The numbers in Russia appear to be stable. The highly fragmented distribution of animals throughout Lithuania, northern and western Belarus and northeastern Poland is, however, a cause for concern. This population is connected to the Karelian population and the large Asian Russian population.10. Balkan.Critically Endangered CR(C2a(i)). The total size of the population is estimated to be about 100 individuals at best, distributed over different patches, indicating a strong population fragmentation. It is impossible to assess the recent trend in population size or distribution, however local experts indicated a decrease for both 1990-1995 as well as 1996-2001.",Unfavourable,"The Eurasian lynx is one of the widest ranging of all cat species. It was once distributed throughout Russia, central Asia and Europe. It was probably absent from some of the larger islands such as Ireland and Sicily and from countries with few forests. It was also absent from the Iberian Peninsula, where the smaller Iberian lynx Lynx pardinus occurs. From this extensive distribution, lynx were exterminated from almost all of western Europe. In western and central Europe, they survived only in the Carpathian Mountains, the southern Dinaric Mountains in Macedonia and Albania, and parts of Fennoscandia and the Baltic (where populations were heavily reduced), although larger populations persisted in European Russia. Human activities reduced the lynx to its minimum numbers in the 1950s. Lynx have been released in several areas of Europe in an effort to reintroduce this elusive predator, including in Switzerland, Slovenia, Czech Republic, Austria, Germany and France. Lynx occurring in Europe can be viewed as belonging to a number of distinct populations (LCIE 2007):1. Jura.Countries: France and Switzerland. Description: This population stretches across the Jura Mountains from central-eastern France north of the Rhone to western Switzerland between Geneva and Basel.2. Vosges-Palatinian.Countries: France and Germany. Description: Distributed along the French Vosges Mountains and in the German Palatinian Forest and its surroundings.3. Alpine (comprising two segments - Western Alps and Eastern Alps).Countries: Switzerland, Slovenia, France, Italy, Austria. Description: Two main extant populations can be identified: One in the western to central Swiss Alps (mainly in the cantons of Valais, Vaud, Fribourg and Berne), stretching into the French Alps, and the western Alps in Austria (Vorarlberg); the other one in the western part of Slovenia (west of the Jesenice-Ljubljana-Triest highway), stretching into the adjacent regions of Italy (Tarvisiano) and Austria (Carinthia). Outside these two sub-populations, a more scattered distribution with no permanent lynx presence exists in France (south-east of the country, from the lake of Geneva as far south as to the department of Hautes-Alpes), eastern Italy (Friuli VG, Veneto (Bellunese), and Austria (northern Kalkalpen, Upper Carinthia, Niedere Tauern).4. Bohemian-Bavarian.Countries: Czech Republic, Germany, Austria. Description: The population stretches in the triangle of the three range countries: in the western Czech Republic (Sumava Mts., NW-part of the Cesky les Mts. = Oberpfälzerwald, the Sumava foothills, S-Novohradske Mts.; in the north more isolated, small but constant occurrence in the Brdy highlands in connection with the core population), eastern Germany (Bayerischer and Oberpfälzer Forest, Fichtelgebirge, Frankenwald), and northern Austria (Böhmerwald, Mühlviertel, Waldviertel).5. Dinaric.Countries: Slovenia, Croatia, Bosnia-Herzegovina. Description: From central-southern Slovenia (S and SE of the Jesenice-Ljubljana-Triest highway) over Croatia (Gorski Kotar and Lika) up to West Bosnia (no data available for sporadically present areas).6. Carpathian.Countries: Romania, Slovakia, Poland, Ukraine, Czech Republic, Hungary, Serbia, Bulgaria. Description: The distribution area covers at present almost the entire mountain chain of the Carpathians, and is further expanding into Serbia, and most probably south into Bulgaria.7. Scandinavian.Countries: Sweden, Norway. Description: Lynx occur from central-south to north-east Norway and almost all over Sweden. 8. Karelian.Countries: Finland, Russia. Description: The population stretches from the Republic of Karelia over to Finland where it is only permanently present in the south-east of the country. The occasional presence in northern Finland is consistent with the situation in Murmanskaya Oblast, where indications are also much more scarce compared to Karelia. 9. Baltic.Countries: Estonia, Latvia, Belarus, Poland, Lithuania, Ukraine, Russia. Description: In the north (Estonia, north-eastern Latvia, and northern Belarus) the distribution is coherent with Russia. The rest of the range (southern Latvia, Lithuania, main parts of Belarus, Poland, the Ukraine, and Kaliningrad) is highly fragmented.10. Balkan.Countries: Albania, FYR Macedonia, Serbia, Montenegro, potentially Greece. Description: Scattered distribution. Lynx occurs in the Albanian Alps and central-central east Albania, in western FYR Macedonia (mainly in the areas in and between the national parks Mavrovo, Galicica and Pelister, but most probably also in the Shar Planina Mts. bordering with Kosovo), as well as in Serbia (Kosovo and Metohija province) and Montenegro. From time to time single, unconfirmed observations in the border regions of Greece with FYR Macedonia and Albania.","Lynx in Europe were widely extirpated within the past several hundred years, reaching a nadir in the 1950s. Populations were reintroduced from the late 1970s onward, and the total number of lynx in Europe (excluding European Russia) is c.8,000. Populations in central and southern Europe remain very small and fragmented, although there are larger populations in Fennoscandia, the Baltic states, and European Russia (Breitenmoser et al. 2000). The lynx's stronghold is a broad strip of southern Siberian woodland stretching through eastern Russia from the Ural mountains to the Pacific. There is little information on population status and trends from the lynx's wide Asian range (Nowell and Jackson 1996, Cat Specialist Group 2002). For the European populations, detailed status and trend information can be found on ELOIS - the Eurasian Lynx Online Information System for Europe (http://www.kora.unibe.ch/en/proj/elois/online/index.html).","Throughout Europe and Siberia, lynx are associated primarily with forested areas which have good ungulate populations (Nowell and Jackson 1996). In Central Asia they occur in more open, thinly wooded areas. Small ungulates are the lynx's primary prey (Nowell and Jackson 1996, Cat Specialist Group 2002). In Europe, the lynx's preferred diet includes roe deer and chamois. Lynx will also take larger ungulates such as red deer, moose, or wild boar occasionally. Where ungulates are not available, birds, hares and rodents form important prey. In Norway, Sweden and Finland, lynx also kill significant numbers of semi-domesticated reindeer. Depredation on sheep is also a problem in some countries.","Lynx are vulnerable to destruction of their ungulate prey base. Hunting pressure may also play a role in lynx population declines. Habitat destruction through clear-cutting can have a negative effect on lynx abundance. There is no information beyond harvest reports on which to base an assessment of the biological impact of commercial trapping for furs, and thus its significance as a threat is difficult to judge (Nowell and Jackson 1996, Cat Specialist Group 2002). The lynx's disappearance in lowland Europe was due to human persecution, deforestation, loss of prey species, expansion of agriculture and an increase in human populations. Although the lynx is not endangered, these threats still affect it today throughout Europe. Habitat loss, loss of prey due to logging and hunting, and human population pressures have serious negative impacts. Humans still present a major threat to the lynx, particularly to small or reintroduced populations. These groups can be devastated by traffic accidents or by unsustainable hunting and poaching. In Norway in 1998, licensed hunters killed 112 lynxes out of a total population of just 400-500. This scale of hunting may be unsustainable, particularly when compounded by illegal hunting. Threats to specific European populations are detailed below:1. JuraIllegal killing, traffic accidents, limited dispersal.2. Vosges-Palatinian.Illegal killing in the Vosges Mts., in general small population size with a rather limited potential to expand.3. Alpine.Threats include illegal killing, infrastructure development (especially road constructions), vehicle and train collisions, and limited dispersal. A potential threat for the population in the Alps is the narrow genetic base: all of the relatively few founder animals came from the same region and some of them were probably closely related. First genetic analysis indicated that the Alpine population has a reduced allelic diversity compared to the Carpathian source population, and that it has today the smallest level of heterozygosity of all European lynx populations.4. Bohemian-Bavarian.Illegal killing, habitat fragmentation due to road constructions.5. Dinaric.Legal and illegal shooting, collisions with vehicles/trains, limited prey base.6. Carpathian.Potentially illegal killing and habitat fragmentation due to infrastructure developments and wood cutting.7. Scandinavian.Illegal killing, potentially legal harvest.8. Karelian.Potentially harvest.9. Baltic.Population fragmentation (in the south-west of the range), potentially illegal killing.10. Balkan.Small population number, limited prey base and habitat degradation (especially in Albania), probably illegal killing.","Included on CITES Appendix II, protected under the Bern Convention (Appendix III) and strictly protected under the EU Habitats & Species Directive (Annexes II and IV). Conservation measures in place and recommended for the European populations are as follows:1. Jura.Lynx is legally protected in both countries. Stock-raiding animals can however be removed. For this, similar criteria have been established in France and Switzerland. In practice, depredation is much more pronounced in the French than in the Swiss Jura. The Ministries of Environment are responsible for the management of the species. There is co-operation on scientific and administrative level, but no systematic common monitoring and no common management plan for the entire population. Most important conservation measures needed: Continuation and improvement of monitoring, genetic surveillance of the population, law enforcement, improve connectivity to other lynx populations or occurrences.2. Vosges-Palatinian.In France as well as in Germany, lynx is fully protected by law. Most important conservation measures needed: Improve potential corridors, mitigate the problem of illegal killings, continue monitoring and cross-border co-operation.3. Alpine. Lynx is at present protected in all Alpine countries. In Switzerland, Slovenia, and France lynx causing too much damage to livestock can be removed. With the exception of Austria, national environmental agencies have the authority for lynx management. In Austria, the owners of the hunting grounds are responsible for the management of the species, but are supervised by the states (Bundesländer), which have the legal power. With the exception of Switzerland, national management plans are lacking. Current management practices: In the early 1990s, scientists from all Alpine countries formed an expert group to survey the status of and co-ordinate actions for the Alpine lynx population. The SCALP (Status and Conservation of the Alpine Lynx Population) defined common standards to interpret the monitoring data collected, and has developed a Pan-Alpine Conservation Strategy (PACS, Molinari et al. 2003), which was adopted by the Standing Committee of the Bern Convention. Most important conservation measures needed: Promote the expansion of the area occupied, improve law enforcement, continue monitoring of demographic and genetic parameters, increase acceptance of lynx by local people. To prevent genetic problems, conservation priority should be given not only the expansion of the range (fusion of the two subpopulations), but also the genetic exchange of individuals between different populations, e.g. between all reintroduced populations and the source population.4. Bohemian-Bavarian.Lynx of the Bohemian-Bavarian population are fully protected by law. Co-operation and exchange of information amongst scientists has started some years ago, and the establishment of a discussion platform for management issues was suggested (CELTIC – Conservation of the European Lynx: Management and International Cooperation). However, there is no common management approach yet. In Germany and Austria, wildlife management is in the responsibilities of the federal states (Bundesländer), and as there are no national management strategies for lynx, it is difficult to implement international co-operation. Most important conservation measures needed: Find solutions against the widespread illegal killing, improve connectivity first within the population, but then also to neighbouring occurrences, get a clear commitment and a more strenuous involvement of the authorities.5. Dinaric.Lynx was granted legal protection in Croatia in 1998. By becoming a member state of the European Union in 2004, Slovenia has ratified the EU Habitats Directive and hence legally protected lynx. In Bosnia-Herzegovina, no proper legislation exists. National management plans are in place in Croatia (since 2005) and in preparation in Slovenia, however a coherent strategy for the entire population is missing. Most important conservation measures needed: Develop a cross-border conservation strategy (including defining the legislation in Bosnia-Herzegovina), improve and continue the monitoring of lynx and prey, increase prey base. A specific survey in southern Bosnia-Herzegovina is required to clarify whether there is a connection between the Dinaric and the Balkan population. This knowledge would be of great importance for the assessment of the Balkan lynx, which might be considered a different subspecies.6. Carpathian.In all countries but Romania, lynx is completely protected by law, though since only recently in Slovakia (2001). Until 2000, the annual legal harvest was almost 15 animals in Slovakia and considered a threat to the population. In Poland, lynx received full protection in 1995. Of the Carpathian population, Romania is therefore the only country left were lynx is legally hunted. Yet the number of lynx shot has been very modest compared to the number of lynx estimated and the potential quota set per year. It is however assumed that there is no control over the real extent of hunting, as numbers differ in the literature found. The 2003 Carpathian Workshop on Large Carnivore Conservation aimed to start the elaboration of a Carpathian Action Plan for large carnivores, a measure recommended by the Standing Committee of the Bern Convention. According to this action plan the countries are then requested to draft and implement national action plans. Most important conservation measures needed: Improve the monitoring and census systems, habitat conservation, public education, conduct field research in different parts of the Carpathians to find out more about the species' biology in this region, develop a general strategy for the lynx in the entire Carpathians.7. Scandinavian.The Nordic countries apply more or less the same census methods and management regime, namely the controlled hunting of the species in certain areas where livestock depredation is considered too high. As a matter of fact, depredation is intense: Up to 10,000 sheep and several ten thousands of reindeer have yearly been killed by lynx from 1996-2001 in the area of the Nordic population. Whereas in Norway, sheep depredation is the most extensive, reindeer is the species mainly affected in Sweden. In both countries, the state pays for domestic animals killed. Sweden has implemented a management plan in 2000, Norway a government white paper in 1997, which sets the management guidelines (a new edition is in place since 2004). The harvest numbers in each of the two countries were around 90 lynx per year in 1996-2001. Most important conservation measures needed: Change sheep husbandry in Norway, set the hunting quotas at sustainable level.8. Karelian.The lynx is protected in Finland since 1995. Complete protection can however be derogated in accordance with article 16 of the EU Habitat Directive (resulting in a kind of quota hunting). Finland maintained the same level of harvest throughout the 1990s, with no change after 1995. The level (59 lynx annually in 1996-2001) is however considered sustainable. A management plan has been implemented in Finland in 1996. In Russia, lynx is a game species. Most important conservation measures needed: Establish a monitoring system in Russia, find solutions to mitigate human-livestock-carnivore conflicts in Finland, set the annual quotas on the basis of good census data, establish co-operation between the countries.9. Baltic.Lynx is only hunted in Estonia and Latvia (reservation for including the lynx in Annex II of the EU Habitats Directive) as well as in Russia, in all other countries the species is fully protected. Legislation has in most of the countries strongly improved in the past few years due to harmonizing national laws with requirements of the European Union during the process of accession. Both Estonia and Latvia have prepared and implemented a lynx management plan. Such a plan is also planned for Lithuania. Furthermore, a cross-border network of researchers, conservationists, state officials and other stakeholder representatives from Estonia, Latvia and Lithuania was created in 2000 under the umbrella of the Large Carnivore Initiative for Europe LCIE: the Baltic Large Carnivore Initiative. A report on the status of the large carnivore conservation in the Baltic States including an action plan for the Initiative for 2001-2005 has been published. The report focuses on how the national management plans fulfil the guidelines and recommendations in the European Action Plan. There is however no such framework and strategy yet that would include all countries sharing the population. Most important conservation measures needed: Expand the population towards the south (southern half of Latvia and Lithuania), improve the connectivity within the population in the south-western part and create a broad corridor towards the occurrences in north-eastern Poland across Lithuania along the border with Belarus, improve and coordinate the monitoring of the species, develop a comprehensive conservation strategy based on a metapopulation concept and considering habitat quality and connectivity, continue with the Baltic Large Carnivore Initiative.10. Balkan.The species is fully protected by law in all range countries. No national management plans exist, however it is one of the aims of an ongoing cross-border conservation project to develop a recovery strategy for the Balkan lynx from which national actions can be derived. Most important conservation measures needed: Conduct a systematic field survey covering the whole potential distribution area, establish a standardised monitoring of lynx and prey species, research the ecology and life history of the Balkan lynx, define taxonomic status, raise public awareness, law enforcement, habitat and prey base enhancement.",Manuela von Arx (Large Carnivore Initiative for Europe / Cat Specialist Group) +ANIMALIA,CHORDATA,MAMMALIA,CARNIVORA,FELIDAE,Lynx pardinus,"Previously considered conspecific with Lynx lynx by some authorities, now accepted as a distinct species on the basis of both genetics (Johnson et al. 2006, Eizirik et al. 2008) and morphology (Werdelin 1981, Wozencraft 2005).",Yes,No,CR,C2a(i),CR,C2a(i),"The Iberian Lynx occurs only in isolated pockets of southwestern Spain, and its continued survival in Portugal is uncertain. There are only two known breeding populations in Spain, and the latest survey results suggest a minimum of 84 and a maximum of 143 adults surviving in two breeding populations (in the Coto Doñana and near Andújar-Cardeña in the eastern Sierra Morena). The Doñana population numbers 24-33 adults and the Sierra Morena is the stronghold of the species with an estimated 60-110 adults. These populations are isolated from one another making them even more vulnerable. None of the remaining potential populations in East Montes de Toledo, West Sistema Central and some areas of central and western Sierra Morena is thought to include animals that breed regularly. Current numbers are not sufficient for the survival of the species in the long term and experts agree the cat is now on the brink of extinction (IUCN 2007).With a total population of 84-143 adults, the Iberian Lynx qualifies as Critically Endangered under C2a(i). There has been a continuing decline due to severe depletion of its primary prey, the European rabbit, by disease and over-hunting, with additional threats of high rates of non-natural lynx mortality and habitat destruction and fragmentation. The effective population size of the largest subpopulation (Sierra Morena) is likely less than 50 mature breeding individuals, based on the general measure for felids (the proportion of the adult population contributing to the gene pool through successful raising and recruitment of offspring is 50%: Nowell et al. 2007).",Unfavourable,"The Iberian lynx is restricted to the Iberian peninsula, confined to scattered groups in the southwestern quadrant of the Iberian peninsula as a result of the fragmentation of their natural habitat by agricultural and industrial development. Only two or three groups in Spain are considered to have populations which could be viable in the long term. It is possibly extinct in Portugal (IUCN 2007).","The Iberian lynx occurs only in isolated pockets of Spain and possibly Portugal. The latest survey results from Spain suggest a minimum of 84 and a maximum of 143 adults surviving in two breeding populations: iin the Coto Doñana and near Andújar in the eastern Sierra Morena. The Doñana population numbers 24-33 adults and the Sierra Morena is the stronghold of the species with an estimated 60-110 adults. These populations are isolated from one another making them even more vulnerable. None of the remaining potential populations in East Montes de Toledo, West Sistema Central and some areas of central and western Sierra Morena is thought to include animals that breed regularly. Current numbers are not sufficient for the survival of the species in the long term and experts agree the cat is now on the brink of extinction. The latest population estimates represent a Spanish decline of more than 80 per cent since the last survey (1987-1988) suggested as many as 1,136 lynxes. A similar decline of 80 per cent was estimated in Spain for the period 1960-1978 (IUCN 2007). In Portugal a sign search, camera trapping and box trapping survey conducted in 2002 by the Instituto da Conservacao da Natureza failed to detect a single lynx (Sarmento et al. 2004). The most recent evidence of the presence of lynx in Portugal comes from the discovery of a scat in the Guadiana area in 2001, which was identified by molecular analysis (Pires and Fernandes 2003). During the 1990s, a national survey based on personal interviews and dead animal records suggested a population of about 40 lynxes fragmented in small subpopulations in five different areas: Algarve mountains, Sado Valley, Guadiana, S. Mamede and Malcata. However, further local field surveys indicated the absence of resident animals, pointing to a pre-extinction scenario (Pinto 2000, Fernandes et al. 2001, Sarmento et al. 2004)","The Iberian lynx occurs in Mediterranean woodland and maquis thicket. It favours a mosaic of dense scrub for shelter and open pasture for hunting rabbits (ICONA 1992). Palomares et al. (1991) examined habitat preferences of lynx in the Coto Doñana area of south-western Spain, including the national park and environs. Lynx were generally absent from cropland and exotic tree plantations (eucalyptus and pine), where rabbits were also scarce. In the park, radiotelemetry showed that more than 90% of daytime resting spots used by lynx were located in thick heather scrub (Beltrán et al. 1987). The Iberian lynx is a specialised feeder, with rabbits (Oryctolagus cuniculus) accounting for 80-100 per cent of its diet. Other species occasionally taken include rodents, hares, partridges, ducks, geese, juvenile deer, and fallow deer, but these do not form an important part of the lynx's diet. Lynx often kill other carnivore species, including those regarded as pests by humans, such as feral cats and foxes, but do not eat them. The lynx's highly specialised diet makes it a naturally vulnerable species and the rapid decline in rabbit populations since the 1950s has had a direct impact on lynx numbers (IUCN 2007).","The Iberian Lynx is a naturally vulnerable species because of its dependence on only one prey species, the rabbit, and its narrow habitat spectrum. The dramatic decline in rabbit populations, caused by habitat changes and myxomatosis since the 1950s and Rabbit Haemorrhagic Disease (RHD) since the late 1980s, has therefore had a direct impact on lynx numbers. Over-hunting of rabbits and other human activities have further compounded the problems of prey scarcity. In recent years, prey scarcity has been compounded by high rates of non-natural mortality and habitat destruction and fragmentation. Habitat destruction, deterioration and alteration have impacted negatively on the lynx for centuries. Notable examples since the middle of the 20th century include the planting of Mediterranean scrublands with pines and eucalyptus and more recently the over stocking of deer and livestock on private estates and the opening up of roads and forest tracks in previously remote areas. The lynx's preferred habitat mosaic has also suffered at the hands of afforestation and scrub clearance schemes, road building, dam construction, and the building of holiday homes. New infrastructure projects continued to fragment lynx populations and created new barriers in corridor areas between the remaining populations in the 1960s. More than forty separate lynx populations in Spain and Portugal appear to have collapsed since the early 1980s. WWF Spain/Adena has identified 53 different public works that will affect important areas for the Iberian lynx. Heavier and faster traffic is also taking an unacceptably high toll on lynx each year as juveniles venture away from their areas of birth in search of new habitats. This high mortality has been an important factor in the decline of the species, particularly in the areas surrounding Doñana National Park. The Iberian Lynx received protection against hunting in the early 1970s and since then hunting has dropped off. However, some lynxes are still shot and killed in traps and snares set for smaller predators, particularly on commercial hunting and shooting estates (IUCN 2007).","Lynx pardinus is currently listed on CITES Appendix I, and on Appendix II of the Bern Convention and Annexes II* and IV of the EU Habitats and Species Directive. It is also fully protected under national law in Spain and Portugal, and is classed as Critically Endangered on the national Red Lists of both countries (Palomo and Gisbert 2002, Cabral et al. 2005). Public awareness and education programs have helped change attitudes towards the lynx particularly among private landowners in lynx areas. Two international seminars have been held, in 2002 and 2004, to establish a coordinated strategy to save the Iberian lynx from extinction (Olszanska and Breitenmoser 2004). A captive breeding programme has been started in Spain. In Portugal, the National Action Plan foresees a re-introduction programme. The construction of facilities for breeding and reintroduction has been prepared (ICN 2003, Sarmento et al. 2004).In the short term, in situ conservation efforts must concentrate on preserving the last two breeding populations in Coto Doñana and Andújar-Cardeña. Priority must also be given to maintaining several large areas (of at least 500 km²) of suitable habitat to harbour new lynx populations. The central and western regions of Sierra Morena and the Toledo Mountains, as well as other areas in Spain and Portugal naturally rich in rabbits, will be vital for this purpose. All lynx habitat must be strictly protected from further destructive infrastructure projects. Captive breeding is of critical importance for lynx recovery. In addition to providing a vital gene bank for the survival of the species, captive lynxes will be needed to recolonise the many areas where populations have collapsed. Efforts to stimulate rabbit recovery must also be intensified. Without sufficient prey density, lynx populations will continue to decline and reintroductions will not be feasible (in spite of recent rabbit conservation measures in Doñana National Park, such as restocking, protection of burrows and vegetation management, rabbit numbers remain low). An adaptive conservation process based on careful monitoring of the last populations and the results of the measures implemented is necessary to facilitate the survival of the Iberian lynx. Recovery plans in all regions where the lynx has occurred over the past decade also need to be rapidly implemented (IUCN 2007).","von Arx, M. & Breitenmoser-Wursten, C" +ANIMALIA,CHORDATA,MAMMALIA,CARNIVORA,HERPESTIDAE,Herpestes ichneumon,,No,No,LC,,LC,,"European regional assessment: Least Concern (LC)EU 25 regional assessment: Least Concern (LC)This species is generally assumed to have been introduced to Europe, perhaps a long time ago. Although there is little evidence regarding the exact date of introduction, it is considered likely to have been before 1500. The species is widespread and common in at least part of its range. There appear to have been some range and population increases in recent years, but this may be due to better observation.",Possibly Favourable,"This species is found mainly in sub-Saharan Africa, from Senegal and Gambia to East Africa, then southwards in Angola, Zambia, Malawi and Mozambique. It is absent from much of southern Africa, but present in NE Namibia, N Botswana, N and E Zimbabwe and the extreme eastern parts of South Africa (Palomares in press). In North Africa, ranges in a narrow coastal strip from Western Sahara to Tunisia, and also from N and E Egypt southwards to Ethiopia (Palomares in press). It is also found from the Sinai Peninsula to the south of Turkey, and the Iberian Peninsula (Delibes 1999). More specifically, in Europe this species is found in southern and central Portugal (Borralho et al. 1995) and south-western Spain (Delibes 1999). At the beginning of the 20th century, it was also present in the northwestern part of the Iberian Peninsula (Delibes 1999). An individual was recently recorded near Leon (Castile and Leon, Spain) (Palomo and Gisbert 2002). It is generally considered to have been introduced to Europe, on a zoogeographical basis (Delibes 1999) and on the grounds that the species is absent from the European fossil record although late Pleistocene and Holocene fossils are known from North Africa (Dobson 1998). It has been speculated that the introduction occurred ""perhaps a long time ago"" (Delibes 1999). It has been reported to 3,000 m asl in the Ethiopian highlands (Yalden et al. 1996).","In the 19th century it regularly occurred in the north-west of the Iberian peninsula, but it subsequently became restricted to the south-west. In recent years, there have again been records from the north-west (Palomo and Gisbert 2002). “The status of its population in Europe is unknown, but numbers and probably range have increased in the last 20 years, in both Portugal and Spain (Delibes 1999).” Abundance increases from north to the south, reaching densities of 1.2 individual per square kilometer in southern Spain (Delibes 1999).","Mainly associated with habitats with understorey vegetation in coastal, lacustrine and riparian (streams, rivers, marsh, swamps) habitats (Palomares in press). This species avoids humid forests and extreme deserts (Delibes 1999, Palomares in press). In tropical Africa, the Egyptian mongoose occurs where there are termitaries, which Kingdon (1977) suggested could satisfy a need for secure shelter. In Europe, “it is found in Mediterranean maquis, with a clear preference for humid and riparian habitats (Delibes 1999).” Egyptian mongooses have home ranges of about 3 square kilometers, and are diurnal and omnivorous (Delibes 1999).","There are no major threats to this species. Incidental poisoning by rodenticides is a localized threat, and trapping with boxes is legal in Portugal (F. Palomares pers. comm. 2007). Deliberate illegal poisoning of carnivores sometimes occurs (European Mammal Assessment Workshop 2006). “It is considered a pest by hunters, because of its presumed impact on small game species"" (Delibes 1999). The range of this species in south-western Europe has experienced reductions due to increased agricultural production, yet increases in range have also occurred due to the reduction of its natural predators (Delibes 1999).","This species is present in many protected areas across its range. It is listed on Appendix III of the Bern Convention, and Annex V of the EU Habitats and Species Directive (Delibes 1999).","Juan Herrero, Paolo Cavallini, Francisco Palomares" +ANIMALIA,CHORDATA,MAMMALIA,CARNIVORA,MUSTELIDAE,Gulo gulo,,No,No,VU,A2cd,VU,D1,"European: Vulnerable (A2cd). The European population is very small (ca. 2,260 individuals), and although the Fennoscandian part of the regional range is stable, there have been sharp declines in the (much larger) Russian area over the past 30 years owing to overharvesting and decline in prey populations (reindeer). It is not anticipated that there would be a rescue effect from populations in Asian Russia, as these are suspected to be declining too.EU 25: Vulnerable (D1). Wolverine numbers in Sweden and Finland are stable, but the total population is very small. Outside the EU, the Russian wolverine population is sharply declining, and the Norwegian wolverine population is very small, so it is not expected that there would be any significant rescue effect and the Red List category is not adjusted.1. Scandinavian wolverine populationVulnerable (D1). The Scandinavian part of the geographical European range is stable, but the population is very small (750 wolverines). The Scandinavian population is only narrowly connected with the Karelian population and genetic analyses have shown that these two populations are clearly distinct, consequently it is assumed that there would not be a significant rescue effect and the Red List assessment is not adjusted.2. Karelian wolverine populationEndangered (C2a(ii)). The population in Karelia is very small (450 wolverines, of which 60 in Finland and 390 in Russia). Although the population trend in the Finnish part of the range is slowly increasing, the trend in the much larger Russian population is believed to be decreasing (although it is poorly known). The population trend in Karelia is suspected to be declining overall. All individuals are part of the same subpopulation. In Russia in general there have been sharp declines in wolverine populations over the past 30 years owing to overharvesting and decline in prey populations (reindeer). Consequently, although the Karelian population is connected to populations further east in Russia, it is not expected that there would be a significant rescue effect because the populations are declining.",Unfavourable,"In addition to their circumpolar distribution across Siberia and North America, wolverines once occurred throughout the European part of Russia, Norway, Sweden, Finland, the Baltic states, and north-east Poland. During the 19th century, wolverines disappeared from the southernmost of these areas in Europe mainly due to persecution, but also due to deforestation and other human impacts. In Europe the species is now found in Norway, Sweden, Finland and European part of Russia. Within these countries wolverines are mainly found north of 60ºN. According to the Guidelines for Population Level Management Plans for Large Carnivores (LCIE 2007) two populations are recognized in Scandinavia and Karelia:1. Scandinavian wolverine populationThis population is distributed mainly along the border of Norway and Sweden, with extensions into the southern Norwegian mountains, and the northern Norwegian county of Finnmark and adjacent areas of northwest Finland (the region of Lappland). Within this range there are three population segments, the south Norwegian, the central population segment along the Norwegian/Swedish border, and a few animals breeding in the boreal forest areas of eastern Sweden.2. Karelian wolverine populationThis population extends across southern and central Finland (all Finland excluding Lappland) and the Russian oblasts of Murmansk and Karelia. The main distribution appears to be continuous, but there is a relatively isolated population segment in western Finland.","The European population of Gulo gulo is currently estimated to be approximately 2,300 individuals. The European distribution is connected to the Asian Russian population along the Urals. The overall European population forms a more or less continuous distribution with a few geographically and genetically distinct units, and constitutes a smaller fraction of the large Eurasian population. During the last decades, there has been a increase in population numbers and distribution of wolverines in the Fennoscandian countries, but decreasing trends in Russia.1. Scandinavian wolverine populationPopulation size: 750 wolverines. Genetic surveys for the Scandinavian population have shown a low genetic variability and subdivision among populations indicating that the wolverine in Scandinavia has potentially lost variation due to a previous bottleneck event and that the current populations are the result of a recent common genetic background. The southern part of the population seems to form a sink with a few individuals emigrating from the northern continuous population. The southern Norwegian population segment was naturally re-established during the late 1970s and was a result of protective legislation. This population segment has recently increased in numbers and distribution, but seems to have stabilized at around 100 individuals. Genetic surveys have shown that the southern Norwegian population segment is genetically distinct from the northern population segments (about 220 individuals in Norway), but the geographic gap between the southern population and the main population to the north and east has decreased from 100-200 km by the early 1990s to virtually connectivity by 2006. There are an estimated 380 individuals of 1 year and older in the Swedish portion of the central population segment. Recently, during the 1990s a small and distinct reproducing population became established in the southern boreal region of the country. Population data for the past 9 years (1996-2004) suggest a fairly stable over all population trend, with a slight increase during the past 5 years.2. Karelian wolverine populationPopulation size: 450 wolverines.","Wolverines inhabit a variety of habitats in the alpine, tundra, taiga, and boreal forest zones. They are found in coniferous, mixed, and deciduous woodlands, bogs, and open mountain and tundra habitats. Sometimes known as “hyaenas of the north”, wolverines have evolved to scavenge from the kills of wild ungulates abandoned by more efficient predators such as wolves and lynx, as well as victims of accidents and disease. However, wolverines also prey on hares, rodents and occasionally animals as large as moose given certain snow conditions. They can also prey heavily on domestic sheep and semidomesticated reindeer. The wolverine has vast home-ranges (Landa et al. 1998a) and good dispersal abilities. Faecal DNA sampling has detected dispersal distances of more than 500 kilometres (Flagstad 2005, Flagstad et al. 2006).","Wolverines are scarce in Europe today. Their continued survival is threatened due to their small and fragmented distribution, and the potential for their future survival may be weakened by the likelihood of low genetic diversity. Habitat loss per se is not a substantial threat to wolverine conservation. Large areas of Norway, Sweden and Finland are still covered by forests and mountains that offer a suitable prey base and habitat for wolverines. The problem is that these are not wilderness areas, and wolverines come into conflict with a low, but crucial, number of human land uses. The fact that there are no large areas within their distribution where there is no conflict potential with sheep or semidomestic reindeer means that human tolerance for wolverines is low. This results in a difficult situation for wildlife managers who are forced to try and balance wolverine conservation with the conflicts they create with livestock. In Norway, farmers no longer use traditional sheep-herding methods that once deterred depredation, so wolverines are often controlled in an effort to protect livestock. Poaching also occurs. In Russia, overharvesting and declines in key prey species are major threats.1. Scandinavian wolverine populationHigh levels of depredation on domestic sheep in Norway, and on semi-domestic reindeer in Norway, Sweden and Finland, generate large conflicts. These lead to pressure for population reduction through both legal and illegal killing. Finding ways to reduce depredation on sheep is crucial. It is unclear if the existing levels of harvest, especially in Norway, are sustainable. With respect to depredation on semi-domestic reindeer solutions are harder to find as wolverines depend heavily on semi-domestic reindeer for food.2. Karelian wolverine populationThe Russian economic depression during the 1990s is believed to have led to widespread poaching of ungulate game species. Furthermore, there has been a reduction of the semi-domestic reindeer herding industry due to large calf/breeding losses. This is believed to have indirectly negatively affected wolverine populations in western Russia. The wolverine's main prey base (wild and domestic reindeer) became less abundant and the population has faced a decrease in numbers and distribution during the last decades.","The wolverine is listed on Appendix II of the Bern Convention and Annex II* and Annex IV of the EU Habitats and Species Directive. European range states have different monitoring and management regimes. The species is strictly protected in Finland and Sweden, but is subject to licensed harvest and control measures in Norway.1. Scandinavian wolverine populationWolverines are subject to both de facto hunting and government organised lethal control activities in Norway. The Norwegian national goal is to control the total population within the limits of 39 yearly active natal dens. Control measurements, killing of family groups in early spring and licensed harvest is used as a management tool to restrict wolverine predation on unattended sheep during summer and domestic reindeer all year around. The national goal in Sweden is to reach a minimum of 90 annual reproductions which equals approximately 550 individuals. Wolverines in Sweden are protected, although there is some limited use of lethal control following acute depredation events. The Norwegian and Swedish population is monitored through annual den inventories and there is cooperation and data exchange between the two national programmes. In Finland the species is monitored through a national fauna monitoring programme based on tracks crossing fixed 4x4+4 km triangles. 2. Karelian wolverine populationWolverines are protected in Finland and Russian Karelia.",Arild Landa (Large Carnivore Initiative for Europe) +ANIMALIA,CHORDATA,MAMMALIA,CARNIVORA,MUSTELIDAE,Lutra lutra,"Some authors considered Japanese otters as a distinct species (Lutra nippon) (see Wilson and Reeder 2005 and references therein), however they are maintained here as a distinct population of Lutra lutra.",No,No,NT,,NT,,"European regional assessment: Near Threatened (NT)EU 25 regional assessment: Near Threatened (NT)In both cases, the species is listed as Near Threatened because it has undergone historical declines but is now recovering across most of Europe (although declines are ongoing in some areas). However, if conservation actions for the species were stopped or reduced, the species would very quickly move back into a threatened category. Hence the Near Threatened listing is a precautionary one based on Criterion A3 and A4, as it is suspected that if conservation measures ceased, declines over a 12 year (=3 generation) period in the future, or including both the past and the future, might approach 30%.",Unfavourable,"The Eurasian otter has the widest distribution of all otter species. Its range covers parts of three continents: Europe, Asia and Africa. Originally the species was widespread throughout Europe, but it declined dramatically in the 1960s and 1970s, and has disappeared from parts of central and northern Europe (it is probably extinct in Liechtenstein, the Netherlands, and Switzerland: Prigioni 1999). It is not found on most of the Mediterranean islands due to the lack of appropriate habitat, although it is found on Corfu (Greece). Little is known about the original distribution in Africa and Asia. Otters have been found in brackish waters below sea level in the Netherlands, and up to 2,400 m in the Pyrenees. Outside Europe they have been recorded up to 4,120 m in Tibet (Reuther and Hilton-Taylor 2004).","Expanding throughout most of its European range following historic declines up until the 1960s, 1970s and 1980s; although in the European part of Russia there have been recent marked declines, and isolated populations in countries like Turkey, Italy, Georgia, Armenia are still declining. The UK population started to recover in the 1960s (Battersby 2005). The population in Portugal is stable and did not show much decrease historically (Cabral et al. 2005). In Norway, although the range is increasing on the south-western coast, the population appears to have declined again since the mid 1990s (T. Heggberget pers. comm. 2006).","It is known from a wide variety of aquatic habitats, including highland and lowland lakes, rivers, streams, marshes, swamp forests and coastal areas. It is very adaptable, using saltwater as well as freshwater habitats, and even sewerage systems in urban areas. In most parts of its range otter distribution is correlated with presence of riverbank vegetation. Otters in different regions may depend upon different features of the habitat, but the important component of otter habitat, for breeding purposes, is the presence of holes in the river bank, including cavities among tree roots, piles of rock, wood or debris. The Eurasian otter avoids deep water. Their distribution in coastal areas is strongly correlated with the presence of freshwater. The location of breeding holts is not confined to river banks; there is evidence to indicate that sometimes the species breeds well away from water and the pups are moved to holts on the river banks once they are a few months old (Reuther and Hilton-Taylor 2004).","The aquatic habitats of otters are extremely vulnerable to man-made changes. Canalisation of rivers, removal of bank side vegetation, dam construction, abstraction of water for irrigation, draining of wetlands, agricultural activities and associated man-made impacts on aquatic systems are all unfavourable to otter populations. Pollution is major threat to the otters in western and central Europe, the main pollutants posing a danger to otters are the organochlorines dieldrin (HEOD) and DDT/DDE, polychlorinated biphenyls (PCBs) and the heavy metal mercury. Coastal populations are particularly vulnerable to oil spills. Acidification of rivers and lakes results in the decline of fish biomass and reduces the food resources of the otters. The same effects are known to result from organic pollution by nitrate fertilisers, untreated sewage, or farm slurry. In addition, major causes of mortality from several countries are drowning, road kills, and poaching. Fyke nets set for eels and other fish as well as creels set for marine crustaceans are very attractive to otters, and many that try to enter these traps are entangled and drowned. A further potential threat is strangulation by transparent, monofilament drift net. A potential risk comes from traps designed to kill other species, especially underwater cages constructed to drown muskrats. Illegal hunting is still a problem in many parts of their distribution range. In several European countries political pressure especially by fishermen has resulted in granting of licenses for killing otters (Reuther and Hilton-Taylor 2004). Illegal killing for the trade of pelts is on the increase in Ukraine and Danube Delta, and probably in the eastern parts of its global range (European Mammal Assessment Workshop 2006).","It is strictly protected under international legislation and conventions: CITES Appendix I (Reservation by Russian Federation), Bern Convention Appendix II, EU Habitats and Species Directive Annexes II and IV, and EC 338/97 Annex A. Additionally it is protected under national law in many range states. A European Breeding Programme (EEP) for self-sustaining captive populations was started in 1985. Monitoring programmes have been established in many range states in Europe. Road barriers and tunnels under roads are required to reduce the impact of road kills (especially in countries like Germany where road kills are the main threat). Much more monitoring is required, but also better survey techniques are required. For example, the population on the Shetlands is well-surveyed, and survey results show no indications of decline, but evidence from other sources (breeding holts, changes in diet, etc.) indicate that declines are in fact happening (J. Conroy pers. comm. 2006).","Jim Conroy, Andreas Kranz, Paulo Cavallini, Margarida Fernandes, Alexei Tikhonov, Juan Herrero, Michael Stubbe, Tiit Maran" +ANIMALIA,CHORDATA,MAMMALIA,CARNIVORA,MUSTELIDAE,Martes foina,"Some of the island populations are taxonomically quite distinct, although the significance of this is not yet clear (see Krystufek 2004a, 2004b). In addition, they may be threatened, as they would meet Red List criteria on range alone (W. Duckworth in litt. 2006).",No,No,LC,,LC,,"European regional assessment: Least Concern (LC)EU 25 regional assessment: Least Concern (LC)This species is listed as Least Concern in view of its wide distribution, its large population, its occurrence in a number of protected areas, and because it is unlikely to be declining at nearly the rate required to qualify for listing in a threatened category.",Possibly Favourable,"The stone marten is widespread, occurring throughout much of Europe and central Asia. It is found from Spain and Portugal in the west, through central and southern Europe, the Middle East, and central Asia, extending as far east as the Altai and Tien Shan mountains and north-west China. In Europe, it is absent from the United Kingdom, the Scandinavian peninsula, Finland, the northern Baltic, Ireland and northern European Russia. At the end of 20th century the species extended to the north and east in European Russia, as far as the Moscow Province in the north and across the Volga River in the east (Abramov et al. 2006). The species occurs in Afghanistan, Pakistan, India, Nepal and Bhutan. It was recently found in northern Myanmar (Rabinowitz and Khaing 1998). The species was introduced to Ibiza, Balaeric Islands (Spain) but failed. It was also introduced to Wisconsin, U.S.A. (Long 1995). It is found from sea level to 3,400 m in Kazakhstan and 4,200m in Nepal.",It is common in at least parts of its range (Macdonald and Barrett 1993). Populations in western and central Europe have increased since the 1960s and 1970s. The beech marten is recolonising areas in the Netherlands from which it had disappeared.,"The stone marten prefers more open areas than other martens (Sachhi and Meriggi 1995). Its habitat preferences vary in different parts of its range. It is typically found in deciduous forest, forest edge, and open rocky hillsides (sometimes above the tree line). However, in Switzerland, Austria, north-east France, and southern Germany, it is very common in suburban and urban areas, often building its nest in house attics, outhouses, barns, garages, or even car engine spaces. In some areas they are common in towns and rare in woods. Commensal beech martens may cause damage to roofs, insulation, and electrical wiring and pipes in houses and cars (Broekhuizen 1999).",This species has no major threats. It is sometimes persecuted as a pest. The species is hunted for its fur in India and Russia; and is also hunted for food in some parts of its global range (not in Europe).,"It is listed on Appendix III of the Bern Convention. It occurs in many protected areas. The Indian population is listed in Appendix III of CITES, as Martes foina intermedia (A. Abramov pers. comm. 2006).","Alexei Tikhonov, Paulo Cavallini, Tiit Maran, Andreas Kranz, Juan Herrero, Giorgos Giannatos, Michael Stubbe, Roland Libois, Margarida Fernandes, Alexei Abramov, Chris Wozencraft" +ANIMALIA,CHORDATA,MAMMALIA,CARNIVORA,MUSTELIDAE,Martes martes,,No,No,LC,,LC,,"European regional assessment: Least Concern (LC)EU 25 regional assessment: Least Concern (LC)This species is listed as Least Concern in view of its wide distribution, large population, occurrence in a number of protected areas, tolerance to some degree of habitat modification, and because it is unlikely to be declining at nearly the rate required to qualify for listing in a threatened category. The population is stable to increasing.",Possibly Favourable,"The pine marten has a wide distribution in the Palaearctic, being found throughout most of Europe, Asia Minor, northern Iraq and Iran, the Caucasus, and in westernmost parts of Asian Russia (Western Siberia). It is widespread in continental Europe, with the exception of most of Iberia and Greece, and parts of Belgium and the Netherlands (Bright 1999, Matos and Santos-Reis 2003). It is found on the Mediterranean islands of Corsica, Sardinia, and Sicily (Bright 1999). It was introduced historically to the Balearics (S. Roy pers. comm. 2006). It was formerly widespread in the British Isles, but is now restricted to northern Britain and Ireland, where it is still locally common (Battersby 2005, S. Roy pers. comm. 2006). Altitude ranges from sea-level to the timber line (2,300 m in the Pyrenees: Palomo and Gisbert 2002).","In the more northern and eastern parts of its range it remains widespread, and it is fairly abundant owing to its large range. Population declines and range contractions occurred in many parts of its distribution, yet it was difficult to quantify these population declines because historical data were lacking for many range states. Hunting bags in Russia were 80% lower in the late 20th century than they were in the 1920s (Grakov 1993), and Russia constitutes a large part of the species' range. The pine marten has also declined in the Netherlands (Bright 1999), and has become extinct in many parts of the British Isles where it formerly occurred (Battersby 2005). In northern and central Europe, this species declined from the 1950s to the 1980s, but has since stabilized and is now regionally increasing due to implementation of hunting controls. Since 1990, in the Russian Federation the population has been increasing again in forested areas; in 1999 the number was estimated as 170,000 (A.Abramov pers. comm. 2006). In the United Kingdom, the species' range has increased in Scotland in recent years, but the population trend has not been quantified (Battersby 2005).","It inhabits deciduous, mixed, and coniferous woodlands, as well as scrub. Optimal habitat appears to be woodlands with an incomplete canopy and dense understorey vegetation. Pine martens have a predominantly carnivorous diet, consuming voles, mice, squirrels, rabbits, birds, and amphibians. Carrion is a major food source in the winter. Bee nests, mushrooms, and berries are also sometimes eaten. Solitary, but not highly territorial. The home ranges very often overlap partially or even totally. Female may mate with several males while on heat. There is delayed implantation after 165-210 days. In the eastern parts of distribution area (Ural Mts) it can hybridize with sympatrically distributed sable M. zibellina (A. Abramov pers. comm. 2006).","Threats to the pine marten include unsustainable hunting and trapping, incidental poisoning, and the loss and fragmentation of woodland habitats. The marten is still hunted and trapped for its fur in some parts of its range. Its decline in Britain was due to persecution, and the species is still subject to persecution even in some countries in which it is protected. Efforts to control other carnivore species sometimes result in pine marten deaths.","It is listed on Appendix III of the Bern Convention and Annex V of the Habitats Directive, and it occurs in a number of protected areas throughout its range. In The United Kingdom it is listed under the Wildlife and Countryside Act. Hunting controls need to be implemented and enforced across its range.","Andreas Kranz, Alexei Tikhonov, Jim Conroy, Paulo Cavallini, Juan Herrero, Michael Stubbe, Tiit Maran" +ANIMALIA,CHORDATA,MAMMALIA,CARNIVORA,MUSTELIDAE,Martes zibellina,,No,No,NA,,NE,,European regional assessment: Not Applicable (NA)EU 25 regional assessment: Not Evaluated (NE)This species is listed as Not Applicable at the European regional level because it is of marginal occurrence in the region.,-,"This species is found in ""China (Xinjiang to then northeast), Japan (Hokkaido); Mongolia, DPR Korea, Russia (Ural Mountains to Siberia, Kamchatka, Sakhalin, Kunashiri, and Etorofu)"" (Abe 2005, Wilson and Reeder 2005). This species is of marginal occurrence in Europe, where it is found only in the Ural mountains.","The species' population was fragmented due to hunting and has since recovered and is now such that the species is now fairly abundant in Siberia and the Far East (Monakhov 2001). In 1990-1999 the numbers of sable in Russia were estimated as 800-1,100 (A. Abramov pers. comm. 2006).","The species is primarily found in dense coniferous forests, but can tolerate other types of forests. It feeds on small rodents, voles, squirrels, pikas, doves and berries. For this species in the Ob region of Russia, Monakhov (2001) found that young animals tended to live near floodplains (lowland forest), while adult animals lived on watersheds (upland forest).","This species is still commercially hunted, and logging of primary dense coniferous habitat in Siberia and the Far East is a threat. The species is heavily farmed for fur (A. Abramov pers. comm. 2006). In Japan, introduced Japanese marten Martes melampus can be a competitor of the endemic subspecies Martes zibellina brachyura (T. Murakami pers. comm. 2006).","Studies are needed on the effects of hunting on this species, in order to develop methods to control its populations and use them commercially without decreasing annual population growth (Monakhov 2001).","Global assessment by Alexei Abramov, regional assessment by European Mammal Assessment team" +ANIMALIA,CHORDATA,MAMMALIA,CARNIVORA,MUSTELIDAE,Meles meles,"Previously the genus Meles was considered as monotypic. According to recent morphological and genetic studies the genus has been split into three different species: M. meles, M. leucurus and M. anakuma (Abramov 2002, 2003, Abramov and Puzachenko 2005; see also Wilson and Reeder 2005).",No,No,LC,,LC,,"European regional assessment: Least Concern (LC)EU 25 regional assessment: Least Concern (LC)This species is listed as Least Concern in view of its wide distribution, relatively large population, occurrence in a number of protected areas, and because it is unlikely to be declining at nearly the rate required to qualify for listing in a threatened category.",Possibly Favourable,"According to Wilson and Reeder (2005) this species is found in “Afghanistan, Albania, Austria, Belgium, Bosnia and Herzegovina, Bulgaria, China (Xinjiang), Crete, Croatia, Czech Republic, Denmark, Estonia, Finland, France, Germany, Great Britain, Greece, Hungary, Iran, Iraq, Ireland, Israel, Italy, Latvia, Lithuania, Luxembourg, Macedonia, Moldova, Netherlands, Norway, Poland, Portugal, Romania, Russia (eastward up to Volga River), Serbia and Montenegro, Slovakia, Slovenia, Spain, Sweden, Switzerland, and the Ukraine.” It occurs from sea level to 3,300 m in Pamir Mountains, up to 2,500m in the Caucsasus (A.V. Abramov pers. comm. 2006), and up to 2,200 m in the Alps (Spitzenberger 2002).The boundary between the distribution ranges of the European M. meles and Asian badger M. leucurus is the Volga River (up to the Middle Volga). M. meles is distributed west of the Volga River, M. leucurus is distributed from the Volga River to the east. The European badger M. meles was found in the Nizhnii Novgorod Province (on both sides of Volga River). M. meles is distributed in the west and north districts of Kirov Province, the east and south of Kirov Province are inhabited by M. leucurus. The sympatric zone between these species is the country between the Volga and Kama rivers (Abramov et al. 2003).","The species is abundant throughout its range, and populations are generally stable or increasing. Densities of this species have increased in Europe during recent decades (Holmala and Kauhala 2006). In central Europe the population is increasing due to the reduction of rabies, in western Ukraine the population has increased, and in the United Kingdom there was a 77% increase in the total population size from the 1980s to the 1990s (Battersby 2005). There are large differences in population densities across its range (Prigioni 1999). In Finland, near the northern limit of its distribution, the population density is low at about 0.2 to 0.25 individuals per km2 (Kauhala in litt. 2006), whereas in the UK densities of up to 19.7 individuals per km2 have been recorded (Prigioni 1999).","It prefers deciduous woods with clearings, or open pastureland with small patches of woodland. It is also found in mixed and coniferous woodland, scrub, suburban areas and urban parks (Prigioni 1999). It is an opportunistic forager with an omnivorous diet, including fruit, nuts, bulbs, tubers, acorns, and cereal crops. It also consumes a variety of invertebrates (especially earthworms), wasp and bee nests, birds' eggs, carrion, and live vertebrate prey such as hedgehogs, moles, and rabbits. In the northern parts of its range the species hibernates during the winter months. The home ranges of this species in Finland are very large, with a mean of about 15 km2 (Kauhala et al. 2006), and their social system is peculiar, with large overlapping home ranges without any communal den (K. Kauhala in litt. 2006). In Finland, it does not reproduce every year, and the litter size is small (Kauhala et al. 2006).","It is sometimes persecuted as a pest. In central Europe the population was formerly severely reduced by rabies, but that threat has now decreased with rabies controls. In the United Kingdom and Ireland the species is associated with bovine TB, which is used as a pretext to eradicate the species. During hunting for foxes or raccoons the badger is often killed as bycatch. In the Russian Federation the species is sometimes hunted for its meat and fat which is used as a medicine. The species is sensitive to habitat fragmentation and the size of the remaining patch is important for the continued survival of the species. In Germany, the species is hunted annually. It is possible that the introduced raccoon dog (Nyctereutes procyonoides) competes with the badger in parts of its range, and a project in Finland is looking into this possible threat (K. Kauhala in litt. 2006). Badgers are heavily hunted in Finland, the annual harvest has increased in recent years, being about 10,000 badgers now (K. Kauhala in litt. 2006). The hunting season in Finland is the whole year, with the exception of females with young being protected in May, June, and July (K. Kauhala in litt. 2006).","It is listed on Appendix III of the Bern Convention. It is protected under national legislation in a number of range states: e.g. Schedule 6 of the UK Wildlife and Countryside Act, the Protection of Badgers Act (UK), and Schedule 5 of the Irish Wildlife Acts. In Albania it is considered Endangered. The species is found in many protected areas.","Andreas Kranz, Alexei Tikhonov, Jim Conroy, Paulo Cavallini, Juan Herrero, Michael Stubbe, Tiit Maran, Margarida Fernades, Alexei Abramov, Chris Wozencraft" +ANIMALIA,CHORDATA,MAMMALIA,CARNIVORA,MUSTELIDAE,Mustela erminea,,No,No,LC,,LC,,"European regional assessment: Least Concern (LC)EU 25 regional assessment: Least Concern (LC)This is a widespread and abundant species with no significant major threats, hence it is listed as Least Concern.",Possibly Favourable,"The stoat has a very large circumboreal range, inhabiting central and northern Eurasia, northern North America and north-eastern Greenland. It has been introduced to New Zealand. In Europe, it is present as far south as 41ºN in Portugal (Santos Reis 1983), and is found on most islands with the exception of Iceland, Svalbard, and some small North Atlantic islands; it does not occur on Mediterranean islands. In Japan, it is present in central mountains (northern and central Japan Alps) to northern part of Honshu (primarily above 1,200 m) and Hokkaido (Abe et al. 2005). Its vertical range is from sea level to 3,000 m (Pulliainen 1999).","The density and structure of populations of this species are unstable, due to short life spans and high reproductive capacity; populations are greatly influenced by fluctuations in prey supply (especially small mammals) (King 1983, Pulliainen 1999). Population fluctuations of stoats and their prey tend to increase in magnitude at more northerly latitudes (Pulliainen 1999), although fluctuations have also been recorded in Spain (Blanco 1998, Palomo and Gisbert 2002). In France, it was declining, but now has stabilized as a result of full protection (EMA Workshop 2006). In Spain it has been speculated that the population may be declining as a results of declines in the southern water vole Arvicola sapidus (Palomo and Gisbert 2002), but the population trend has not been quantified in Spain or Portugal (Palomo and Gisbert 2002, Cabral et al. 2005). Despite population fluctuations, it is a widespread and abundant species.","Stoats occupy a wide range of habitats. They are often found in successional or forest-edge habitats, in scrub, alpine meadows, marshes, riparian woodlands, hedgerows, and riverbanks that have high densities of small mammals, especially Microtus and Arvicola species (King 1983). Pulliainen (1999) states that coniferous and mixed woodlands are preferred, but that many other habitats are used including tundra and the summits of fells and mountains. Dense forests and deserts are avoided (King 1983). This species is a specialist predator of small mammals, but will occasionally feed on fruit, earthworms, insects, eggs, and birds (King 1983). Its local distribution is typically related to that of small rodents and lagomorphs (King 1983, Pulliainen 1999). Estimates for home range size range from 4 to 200 hectares for males, most often falling between 10 to 40 hectares (King 1983).","In the Iberian Peninsula the species is dependent on two Arvicola species, and these are declining, so loss of prey base may be a threat (Palomo and Gisbert 2002). Habitat loss (e.g. as a result of urbanization: Pulliainen 1999) is also a problem in parts of the range. The species is commonly hunted in Russia, where there is also a limited fur trade (R. McDonald pers. comm. 2006). In western and central Europe, the stoat was frequently hunted for its white winter fur up until at least the 1930s (with c.30,000 pelts sold in Finland alone during that decade) (Pulliainen 1999). Availability of prey is the principal factor controlling population density (King 1983, Pulliainen 1999), but disease, parasites and other pressures can also contribute.","It is listed on Appendix III of the Bern Convention. It occurs in many protected areas across its range. Monitoring of exploitation is required by the Bern Convention (R. McDonald pers. comm. 2006). The species is protected under national legislation in some range states (e.g. Spain), although this is not necessarily enforced (Palomo and Gisbert 2002). However, in many parts of its global range the species is not protected and trapping is quite legal (R. McDonald pers. comm. 2006).","Margarida Fernandes, Tiit Maran, Alexei Tikhonov, Jim Conroy, Paulo Cavallini, Andreas Kranz, Juan Hererreo, Michael Stubbe, Giorgos Giannatos" +ANIMALIA,CHORDATA,MAMMALIA,CARNIVORA,MUSTELIDAE,Mustela eversmanii,,No,No,LC,,EN,C2a(i),"European: Least Concern as it has a wider distribution range, is more common and does not appear to be declining as much as in the western parts of the range. The range is more continuous eastwards.EU 25: Endangered C2a(i). The population in the European Union is very small (probably less than 1,000 mature individuals) and is undergoing continuing decline and is severely fragmented with each subpopulation containing < 250 mature individuals. There is unlikely to be a rescue effect from the eastern populations, hence the assessment is not adjusted.",Unfavourable,"The steppe polecat occurs from central and eastern Europe in the west through southern Russia, northern Georgia, Kazakhstan, Turkmenistan, Uzbekistan, Tajikistan, and Kyrgyzstan to Mongolia and northern and western China. Wilson and Reeder (2005) list the following countries of occurrence for this species: Austria, Bulgaria, China, Czech Republic, Georgia, Hungary, Kazakhstan, Kyrgyzstan, Moldova, Mongolia, Poland, Romania, Russia, Serbia and Montenegro, Slovakia, Tajikistan, Turkmenistan, Ukraine, and Uzbekistan. According to Wolsan (1999), in Europe this species is represented by two major populations that are separated by the Carpathians. The western of these two major populations (subspecies Mustela eversmanii hungarica) is found in the Czech Republic, eastern Austria, southern Slovakia, Ukraine south of the Carpathians, Hungary, northern Serbia, and western Romania; and the eastern (nominate subspecies) is restricted to northern Bulgaria, southern Romania, Moldova, Ukraine east and north of the Carpathians, southeastern Poland, southern European Russia, and Kazakhstan (Wolsan 1999). It occurs up to 800 m in Europe and to 2,600 m in central Asia.","This species is still numerous in Europe, particularly in southern European Russia. However it is unevenly distributed across its range, and especially in the western parts of its range (e.g. in the EU) it is scarce and patchily distributed. Population densities vary spatially and temporally, with fluctuations linked to the abundance of prey species. It is capable of spreading and colonizing new areas rapidly (Wolsan 1999). There has been no evidence for any decline in Europe (except in Austria and the Czech Republic). However ground squirrels are declining and this is an important prey species, so this could have an impact on the population in Europe. It is widespread and common in Central Asia and Siberia.","It inhabits a variety of relatively dry habitats including steppes, semi-deserts, pastures, and cultivated fields (Wolsan 1999). Its diet consists mainly of rodents, including sousliks, marmots, hamsters, pikas, gerbils and voles. It avoids forests, and is primarily nocturnal.",In western Europe it is seldom intentionally hunted (although it may be taken as bycatch) but is heavily impacted by persecution (EMA Workshop 2006). However in at least parts of its range (e.g. Russia) it is commonly hunted for its fur.,It is protected under Appendix II of the Bern Convention (Wolsan 1999). It occurs in many protected areas. There is a need to address the hunting and persecution issues for this species. It is listed as Vulnerable in the Red Data Book of Ukraine.,"Alexei Tikhonov, Paulo Cavallini, Tiit Maran, Andreas Kranz, Michael Stubbe, Boris Kryštufek, Alexei Abramov, Chris Wozencraft" +ANIMALIA,CHORDATA,MAMMALIA,CARNIVORA,MUSTELIDAE,Mustela lutreola,"The species occasionally hybridizes with Mustela putorius (Tumanov and Abramov 2002). Genetic studies have shown that the western populations (Spain and France) have very low genetic variability and southern populations show moderate genetic variability, whilst the eastern populations have the greatest variability (Lode 1999; Davidson et al. 2000; Michaux et al. 2004, 2005).",No,No,EN,A2ce,CR,A2ce,"European: There has been considerable reduction in the population of this species across most of its historic range. However, there is considerable uncertainty about current population size and rate of decline, which makes it difficult to determine what the true status of this species should be (given better data a Critically Endangered listing might be warranted). There has certainly been more than a 50% population reduction in the past ten years. This decline is likely to continue given the current threats, but it is hard to say if criteria A3 and A4 should be used under Endangered or even Critically Endangered.EU 25: Critically Endangered (A2ce). This assessment refers only to the isolated population in Spain and France. The French population is declining rapidly. In Spain the overall number of European mink is decreasing, and the species is disappearing from rivers in the north and centre of its range, although a concurrent slight extention of the range to the east has been observed (Palomo and Gisbert 2002). The rate of decline has not been quantified, but an 80% reduction in the past ten years seems reasonable. The species could well become extinct in France in the near future, but probably not in the next ten years.",Unfavourable,"Mustela lutreola is largely restricted to Europe. A century ago it was widespread throughout the continent, with a distribution extending from northern Spain in the west to the river Ob (just east of the Urals) in the east, and from the Archangelsk region in the north to the northern Caucasus in the south (Youngman 1990). However, over the last 150 years it has severely declined and been extirpated or greatly reduced over most of its former range (Maran 1999). The current range includes an isolated population in northern Spain and western France, which is widely disjunct from the main range in Eastern Europe (Latvia, Estonia, Belarus, Ukraine, central regions of European Russia and the Danube delta in Romania). It occurs from sea level to 1,120 m (Palazon et al. 2003).","Since the mid-19th century, this species has undergone dramatic declines throughout its range, and is now extinct in most European countries. It now occupies less than 20% of its original range, and the remaining population is small and fragmented and continues to decline (Maran 1999). Recent population estimates include 500-1,000 individuals in Spain (Palazon et al. 2003), several hundred individuals in France (Fournier and Maizeret 2003, Stephane Aulagnier and Roland Libois pers. comm. 2006), and <1,000 individuals in the Danube Delta (A. Kranz pers. comm. 2006). In Ukraine, at the beginning of the 21st century, the population was estimated at 350-400 individuals, with the majority of those found in the Danube Delta (>200 individuals) (Volokh 2004). The most viable population in western Europe is that of the Danube Delta, but even this population may be rapidly declining: in 250 trap nights (2006) only one animal was caught, compared to one in 20 nights in 2003 (A. Kranz pers. comm. 2006). Other viable populations are found in the northeastern part of European Russia.The current European mink range in Russia consists of isolated distant habitats of different size. These fragmented populations are scattered across western Russia, the Urals, and the northern Caucasus. The only parts of the range where the American mink is absent are rivers in the Archangelsk Region and Komi. Everywhere else populations of European mink are vanishing or becoming increasingly fragmented and localised, and in a greater part of historical range in Russian the European mink is not met any more. The Russian population of European mink has been estimated at c.20,000 (Tumanov 2003, 2006), but this is not based on quantitative data as no large-scale census has been done. Hunting bags suggest that the European mink is rapidly becoming less abundant by comparison with the American mink: for instance, in Vologda and Kostroma regions the proportion of European mink skins in the hunting bag of the two mink species decreased from 50-70% to 1-10% within the last 5-7 years (to 2006). For the whole of Russia, recent records refer only to the capture of single individuals or to local populations consisting of some ten of individuals (Skmatov and Saveljev 2006).","European mink have specialised habitat requirements. They are semi-aquatic, inhabiting densely vegetated banks of lakeshores, rivers, streams and marshlands, and are rarely found more than 100 meters away from fresh water. They forage at night, hunting both on land and in water for a wide range of animal prey including small mammals, birds, frogs, molluscs, crabs, fish and insects (Youngman 1990, Maran 1999, Palomo and Gisbert 2002). Females become mature at 19 months (Youngman 1990).","Habitat loss and degradation is a serious threat to the European mink. Ongoing destruction and degradation of freshwater and associated terrestrial habitats is caused by by inter alia hydroelectric developments, channelisation and water pollution. Accidental trapping is also a threat, even though the fur of the European mink is less valuable than that of the American mink Neovison vison. In France, secondary poisoning and trapping of European mink has occurred as a result of efforts to control coypu (Myocastor coypus) and small carnivores (e.g. polecat). Accidental mortality through vehicle collisions is a problem in some areas, and small remnant populations may be driven extinct by threats such as predation by feral dogs and accidental mortality in fish traps (T. Maran pers. comm. 2006). Competition and direct aggression from the American mink is a further threat to depleted remnant populations (Maran 1999). The Aleutian disease could also have an impact, but diseased animals have not yet been found. In Spain and France, hybridization with Mustela putorius may be a threat (Davidson et al. 2000).","Legally protected in all range states (Schreiber et al. 1989) including the Russian Federation (Alexei Tikhonov pers. comm 2006). At least part of the population occurs within protected areas. Studies have been undertaken to determine the mink's ecological requirements, to analyse the causes of its decline, and to assess the genetic variability of western populations. In Spain and France programmes have been started to control the American mink population. A captive breeding programme was launched in 1992 by the European Zoo Association (the Catalonian Government's captive breeding programme is part of this European initiative). Efforts are being made to reintroduce European mink to areas where they formerly occurred in Germany and the Russian Federation. An introduction programme is underway on the island of Hiiumaa (to Estonia) in the Baltic, where the American species has been excluded. In France a national action plan for the conservation of the European mink was initiated by the Ministry of Environment and has been coordinated by the SFEPM (French Mammal Society). Conservation needs vary throughout Europe, and include the following:·National and regional authorities need to increase attention and allocate sufficient resources for European mink conservation. Otherwise this species will disappear soon.·There is a need for large-scale efforts to secure the survival of the last small remaining populations in different areas inside of the historical range of the species, but also restoration and/or establishment of new populations is required. ·For remaining in situ populations, the maintenance or restoration of sufficiently large areas of suitable habitats has to be secured by designation of new protected areas and improvement of management of existing protected areas. ·The impact of the American mink on local European mink populations has to be monitored and controlled, and whenever possible and feasible the alien mink populations should be removed. Local authorities have to pay more attention to the effects of the American mink on the local fauna, including the European mink. They should support further studies and actions to mitigate the effect of alien mink to the native mink species. ·Aleutian diseases and other pathologies must be monitored in all remaining in situ populations of the European mink. ·For French and Spanish wild populations which appear to be highly inbred further research needs to be carried out to identify whether these seemingly genetically highly uniform populations suffer from inbreeding depression. The introduction of individuals from ex situ stock from genetically diverse eastern populations has to be considered as a potential conservation measure, if further research confirms the need for this. In addition to genetic studies, comparative studies on ecology and behavior of the disjunct mink populations (Spanish/French, Romanian and eastern European) should also be conducted to support the findings of genetic studies. ·The ex situ conservation breeding program has to be enhanced and promoted, as it guarantees the survival of the species in case in situ efforts fail. It also provides opportunities for the restoration of already vanished wild populations and reinforcement of existing populations whenever needed. ·There is a need for developing an all-European conservation breeding program with secured long-term funding.·Further studies are needed about the current the status of the European mink in Romania, Ukraine and elsewhere in eastern part of Europe.","Tiit Maran, Stéphane Aulagnier, Roland Libois, Andreas Kranz, Alexei Abramov, Chris Wozencraft" +ANIMALIA,CHORDATA,MAMMALIA,CARNIVORA,MUSTELIDAE,Mustela nivalis,,No,No,LC,,LC,,"European regional assessment: Least Concern (LC)EU 25 regional assessment: Least Concern (LC)The weasel is a widespread species that is locally abundant in at least parts of its range. Although declines have been observed in the UK and are suspected in other parts of Europe, it is not thought that these approach the threshold for the population decline criterion of the IUCN Red List (30% in ten years or three generations). Monitoring is required, and if new evidence emerges suggesting that declines are of a greater magnitude than is presently thought, the species should be reassessed.",Unknown,"The weasel has a very large circumboreal distribution, taking in much of Europe and North Africa, Asia and northern North America. An introduced population exists in New Zealand. It is found throughout Europe and on many islands, including the Azores, Britain (but not Ireland), and all major Mediterranean islands. The populations on the Azores and many Mediterranean islands are widely considered introduced (Dobson 1998, R. McDonald pers. comm. 2006). It occurs from sea level to at least 3,860 m. It is also found on Honshu, Hokkaido, Kunashiri, Etorofu, and Sakhalin Islands (Abe et al. 2005).","In the European part of its range, there are documented population declines in some areas (e.g. Britain: Battersby 2005), and suspected declines in others. Although it has a wide distribution, it is considered rare in North America (Sheffield and King 1994). In Eurasia, it is relatively common, but not often seen (Sheffield and King 1994). Local densities of 0.2 to 1.0 individuals per hectare can occur in favored habitats when prey are abundant (Sheffield and King 1994). However, over wider areas, the average density may be as low as 1 to 7 per 100 hectares (Goszczynski 1977). Populations fluctuate both seasonally and annually, sometimes involving large increases of up to 10-fold, concurrently or within 9 months of a population peak of small rodents, and lasting 6 to 18 months (Sheffield and King 1994).","Weasels tolerate a wide range of habitats, including forests, farmlands and cultivated fields, grassy fields and meadows, riparian woodlands, hedgerows, alpine meadows and forests, scrub, steppe and semi-deserts, prairies, and coastal dunes (Sheffield and King 1994, Pulliainen 1999). This species is a specialist predator of small mammals (especially rodents), although it will also occasionally feed on birds’ eggs, lizards, frogs, salamanders, fish, worms, and carrion (Sheffield and King 1994). Habitat selection is usually determined by local distribution of rodents. Foraging individuals avoid open spaces, where they are most vulnerable to predation by raptors (Sheffield and King 1994). They prefer dense, rank grassland where microtines (voles and lemmings) are abundant (R. McDonald pers. comm. 2006).","Threats include incidental poisoning with rodenticides (Sheffield and King 1994) and persecution. The weasel prefers open agricultural habitats, which are declining owing to changes in agricultural practices (rural abandonment) in parts of Europe, as open fields undergo succession.","This species is found in many protected areas. It is listed on Appendix III of the Bern Convention (Pulliainen 1999), and is protected under national and sub-national legislation in a number of range states (e.g. Sichuan, China: Yi-Ming et al. 2000). Monitoring is required to quantify the population trend in Europe.","Alexei Tikhonov, Paulo Cavallini, Tiit Maran, Andreas Kranz, Juan Herrero, Giorgos Giannatos, Michael Stubbe, Jim Conroy, Boris Kryštufek, Alexei Abramov, Chris Wozencraft, Robbie McDonald" +ANIMALIA,CHORDATA,MAMMALIA,CARNIVORA,MUSTELIDAE,Mustela putorius,"The origin of the Moroccan population has been debated; some authors contend that it is a feral population of M. putorius ‘furo’, although fossil remains found in 2001 and ascribed to M. putorius suggest that the species may be native to Africa (see Griffiths and Cuzin in press, and references therein).",No,No,LC,,NT,,"European: Least Concern. The species has a wide range extending to the Urals. Certainly in the northern and eastern parts of its range it appears to be common, widespread and under no major threat despite hunting pressures.EU 25: Near Threatened. There are declines in parts of the range, especially in central Europe and the situation is not clear in Portugal and Spain. There are concerns about loss of prey, persecution, loss of suitable habitat, etc. Hence the species is listed as Near Threatened as it almost qualifies under Criterion A4. The assessment is not adjusted because it is difficult to say if there would be a rescue effect or not and likewise it is unknown if the European population is a sink or not.",Unfavourable,"Mustela putorius is widespread in the western Palaearctic up to the Ural Mountains in the Russian Federation (absent from Ireland, northern Scandinavia, and much of the Balkans and eastern Adriatic coast). The species occurs only marginally in northern Greece. It is found in Morocco in the Rif Mountains from sea level to 2,400 m (Griffiths and Cuzin in press). Feral populations of the domesticated form M. putorius 'furo' (ferret) have become established in a number of areas including northern Britain, the Isle of Man (United Kingdom), Texel (Netherlands), some Mediterranean islands, the Azores, and New Zealand (Birks 1999, Clapperton 2001, W. Duckworth in litt. 2006).","The species is common in forested areas of European Russia. In western Europe, the species is scarce, typically occurring at densities of about 1 individual per 1000 hectares, and rarely exceeding 5-10 individuals per 1,000 hectares even in optimal habitat (Birks 1999). The population appears to be stable in the eastern parts of its range, but there are reports of recent declines from a number of countries in western Europe (e.g. Switzerland, Germany and Denmark: Birks 1999). In Portugal population numbers and trend have not been quantified, but a declining trend is possible related to the decrease in rabbit numbers (Cabral et al. 2005). In Morocco, Griffiths and Cuzin (in press) suggests that populations may be decreasing. In central Europe, a main prey item (the common hamster Cricetus cricetus) has declined and thus polecat numbers may also be decreasing (EMA Workshop 2006). Populations in the United Kingdom and Estonia are now increasing (Battersby 2005, Tiit Maran pers. comm. 2006). This increase in the United Kingdom follows a major persecution driven decline from the 1800s to 1920s, which nearly led to the extinction of the species there (Birks 1999, Battersby 2005).","A generalist, it is found in almost every type of lowland habitat. It is often found in lowland woods in riparian zones, and in areas close to farms and villages in the winter; but it also uses wooded steppe, sand dunes, marshes and river valleys, agricultural land, forest edge and mosaic habitats (Birks 1999, Cabral et al. 2005). Mountainous areas are avoided. It feeds on live rodents (voles, mice, hamsters) and other vertebrates, also sometimes on invertebrates and carrion. In wetland areas it often feeds on amphibians (Birks 1999).","In western and central Europe, it was formerly widely hunted for sport and fur and persecuted as a pest, although this threat has become less serious as the species is now protected in a number of range states and rates of hunting have greatly reduced (Birks 1999). Accidental mortality in car collisions and via secondary rodenticide poisoning is a problem (Birks 1999, Battersby 2005). Declines in prey species, e.g. hamsters (Nechay 2000) and rabbits in southern Iberia (Cabral et al. 2005) may contributing to declines in parts of the range. In European Russia, the species is commonly hunted (A. Abramov pers. comm. 2006). Hybridisation with the ferret is a possible threat in the United Kingdom (Battersby 2005). Possible competition with the American mink may also be a problem. In Morocco, the species may be captured in some areas for hunting.","It is listed on Appendix III of the Bern Convention and Annex V of the EU Habitats Directive. It is listed on Schedule 6 of the WildLife Countryside Act (UK). It occurs in a number of protected areas across its range. Better monitoring of the species is needed, and measures should be taken to reduce hunting pressure where this is excessive. There is also a need to control release of ferrets into the wild.","Margarida Fernandes, Tiit Maran, Alexei Tikhonov, Jim Conroy, Paulo Cavallini, Andreas Kranz, Juan Herrero, Michael Stubbe, Alexei Abramov, Chris Wozencraft" +ANIMALIA,CHORDATA,MAMMALIA,CARNIVORA,MUSTELIDAE,Mustela sibirica,,No,No,NA,,NE,,European regional assessment: Not Applicable (NA)EU 25 regional assessment: Not Evaluated (NE)This species is listed as Not Applicable at the European regional level because it is of marginal occurrence in the region.,-,"This species is found in northern Myanmar, China, Japan (Tushima, introduced to western Honshu, Kyushu, and Shikoku), North Korea, South Korea, Pakistan, Russia (from Kirov Province, Tataria and western Ural Mountains throughout Siberia to Far East), Taiwan, and northern Thailand (Wilson and Reeder 2005). There is also a historical record from Thailand (Lekagul and McNeely 1977). In Japan, it has been introduced to Honshu, Shikoku, and Kyushu Islands (Abe 2005). It is native on the islands of Sakhalin, Kamishima, and Quelpart (Abe 2005). The distribution in southeast Asia is poorly known (A. Abramov pers. comm. 2006). The species was recorded in two locations in national parks in Thailand (Kanchanasaka, pers. comm.) and in one location in Nakai-Nam Theun National Biodiversity Conservation Area in 1996 in Laos (Duckworth 1997). It occurs from sea level to over 3,000 m in Nepal and to 5,000 m in China (GMA Small Carnivore Workshop 2006). This species is of marginal occurrence in Europe, where it is found only in the Ural mountains.","The species is widespread and abundant in Siberia and China (A. Abramov pers. comm. 2006). It is also common in northern central Korea as well, where few other mammals other than rats and squirrels are easily seen (W. Duckworth in litt. 2006).","The species occurs in primary and secondary deciduous, coniferous and mixed forests, as well as open areas with small patches of forest enclaves and forest steppe. It is also found along river valleys. It feeds on small mammals, such as voles, squirrels, mice and pikas, amphibians, fish, and carrion, and occasionally on vegetative matter (e.g. pine nuts) (Global Mammal Assessment Small Carnivore Workshop 2006).",There are no major threats known to this species (Global Mammal Assessment Small Carnivore Workshop 2006). It is legally hunted in Russia for its fur (A. Abramov pers. comm. 2006).,"This species is listed on CITES Appendix III (Tibet) (Yi-ming et al. 2000). There is a large, legal harvest of pelts of this species, which is apparently sustainable (W. Duckworth pers. comm. 2006).","Global assessment by Alexei Abramov and Will Duckworth, regional assessment by European Mammal Assessment team" +ANIMALIA,CHORDATA,MAMMALIA,CARNIVORA,MUSTELIDAE,Vormela peregusna,The infra-specific taxonomy is not clear and further work on this is required (most of the work so far has been done on pelts). The nominate subspecies is found in Europe.,No,No,VU,A2c,NA,,"European: Listed as Vulnerable under criterion A2c. It seems reasonable to infer at least a 30% reduction in the population in the last ten years due to the loss of steppe habitat. This reduction may continue into the future but it is difficult to say if it would be at the same rate. The assessment was not adjusted as there is unlikely to be any rescue effect and the European population is unlikely to be a sink. EU 25: Of the EU 25 countries, it occurs only in Greece, where there are few records. Less than 1% of the global population is estimated to occur in the EU 25, so the species is classed as Not Applicable in this region as it is of marginal occurrence.",-,"The marbled polecat has a distribution extending from south-east Europe, through Asia Minor, the Middle East, the Caucasus, and Central Asia, to northern China and Mongolia. In Europe, it is found in Serbia and Montenegro, Macedonia, Greece, Romania, Bulgaria, Turkish Thrace, and parts of Ukraine (the polecat has disappeared from most of this country and is now present only in the east) and the Russian Federation and the northern Caucasus (the steppe areas, not the mountains). It is also known to be widespread throughout the Middle East, having been recorded from just across the Sinai eastern border in Gaza (Harrison 1968), in Israel/Palestine, Jordan, Lebanon, Syria, and northern Iraq and northern Saudi Arabia (Ellerman and Morrison-Scott 1951, Harrison 1968, Nader 1991). Saleh and Basuony (1998) report the first records of this species from Egypt, as it was recorded from two localities on the northern part of the Sinai Peninsula (southeast of Bir El Abd and just north of Gabal El Maghara). It occurs from sea level up to 3,000 m in the Tien Shan mountains.","It is rare throughout much of its range, and is classed as 'Rare' in the Russian Federation. Its northerly range is receding in the Balkans and Ukraine (Rozhnov 1999), and in European Russia. It has declined substantially in Europe in line with the loss of steppe habitats. Declines are also suspected in central Asia. It is less rare in central Asia than elsewhere, but not common there. The species has always been naturally rare in most areas, although it appears to be common throughout northern Sinai, and well known to the local Bedouins there (Saleh and Basuony 1998). The largest population in the Middle East is reported to be in Israel (Michael Stubbe pers. comm. 2006).","It inhabits desert, semi-desert and steppe habitats. It is a specialized predator, feeding mainly on desert and steppe rodents such as gerbils, ground squirrels, and birds. It is the most fossorial of all weasels.","The major threat to this species is the loss of natural steppe and desert habitats. Steppe habitats are declining in Europe as they are converted to cultivated farmland. Secondary poisoning by rodenticides may also be a threat, as are population declines in key prey species (a number of steppe rodent species are declining in Europe). In China, desertification is the major threat to the species.","It is strictly protected under Appendix II of the Bern Convention and Annexes II and IV of the EU Habitats Directive. Hunting for this species is prohibited in most countries across its range. It occurs in a number of protected areas across its range, but there is a need to increase the size of these. There is an urgent need to protect the remaining steppe habitat of this species. It is a flagship species for the steppe. A number of animals are in captivity, but a breeding program is not necessary. Russia's and China's Red Lists note the species as Vulnerable.","Alexei Tikhonov, Paulo Cavallini, Tiit Maran, Andreas Kranz, Juan Herrero, Giorgos Giannatos, Michael Stubbe, Jim Conroy, Boris Krystufek, Alexei Abramov, Chris Wozencraft" +ANIMALIA,CHORDATA,MAMMALIA,CARNIVORA,ODOBENIDAE,Odobenus rosmarus,"Three recognized subspecies: rosmarus: Atlantic Walrus; divergens: Pacific Walrus (Illiger, 1811); and, laptevi: Laptev Walrus (Chapskii, 1940)",No,No,NA,,NA,,"This species is a vagrant in the marine region covered by the European Mammal Assessment, consequently it is classed as Not Applicable.",-,"Walruses have a discontinuous circumpolar Arctic and sub-Arctic distribution. The Pacific subspecies is found in the Bering and Chukchi Seas to the East Siberian Sea in the west and the western Beaufort Sea in the east. The Atlantic subspecies occurs in numerous subpopulations from the Eastern Canadian Arctic to the western Kara Sea, including the Barents and White Seas, and Svalbard and Franz Josef Land. Vagrants have been reported from Iceland, and from Norway south to the Bay of Biscay. The Laptev walrus is confined to the Laptev Sea north of central Russia. All three subspecies of walruses are found in relatively shallow continental shelf areas, and rarely occur in deeper waters (Scheffer 1958, Fay 1982, Rice 1998, Kastelein 2002).","The Pacific walrus population recovered from a depleted state in 1950 to historical high levels in the 1980s (Fay et al. 1997). The population was estimated at over 230,000 in 1985 (Gilbert 1989), and 201,000 in 1990 (Gilbert et al. 1992). However, difficulties with associated with conducting these surveys greatly reduced the precision of these estimates (Gilbert 1999). The current population level is unknown (Angliss and Lodge 2004). The Atlantic walrus has been extirpated from some areas but estimates are that between 10,000 and 19,000 animals occur from the eastern Canadian Arctic to the Kara Sea (Born et al. 1995, Kastelein 2002). The Laptev population was estimated at 4,000-5,000 animals according to a report cited in Fay (1982), and the current status is unknown. The walrus is a vagrant in the marine region covered by the European Mammal Assessment.","Walruses are highly gregarious animals and are frequently found in close knit groups that regularly number in the tens to many hundreds, and aggregations of animals including many groups of these sizes can number in the low thousands. Walruses also haul out on ice floes and beaches on islands or remote stretches of mainland coastlines forming dense groups of animals lying pressed together and on top of one another. At sea, walruses can be found alone or in large aggregations.Courtship and mating occurs in the winter. It is believed that walruses are polygynous, the males forming a type of lek, or establishing small aquatic territories where they vigorously vocalize and display adjacent to females hauled-out on ice floes. Males have an unusual adaptation for producing bell-like sounds underwater. A pair of elastic pharyngeal pouches in the neck can be inflated with air to serve as resonance chambers that make this unique sound. There is also intense male-male fighting at this time. Tusks are used for interspecific aggression, defense against predators, which include polar bears and killer whales, and for aids in hauling-out on ice, but not for digging up food. Walruses are one of the largest pinnipeds. Males reach about 3.6 m and 880-1560 kg, females about 3 m and 580-1039 kg. Newborns are 1-1.4 m and weigh 33-85 kg. Although females can ovulate at four years of age, the majority do not give birth until they are 7-8 years old and usually only produce one calf every three years. Gestation lasts 15 months, including a delay of implantation time of 3-3.5 months. The period of calf dependency is long, regularly taking two years, and can extend longer if a female does not give birth every three years. Males become sexually mature between 7-10 years old, but are not physically and socially mature enough to successfully compete for breeding opportunities until they are approximately 15 years old. Longevity is approximately 40 years (Fay 1981).Walruses are primarily bottom feeders and shallow divers. Most prey taken is found in the upper few centimeters of sediment, or on or just above the bottom. A wide variety of benthic invertebrates, with several species of clams, make up the majority of food for most animals. Their diet also includes other species of mollusks, and many species of worms, snails, soft shell crabs, amphipods, shrimp, sea cucumbers, tunicates, and slow-moving fish. Some individuals regularly prey on seals, small whales, and seabirds, and occasionally scavenge marine mammal carcasses (Fay 1982).","All three walrus populations were severely depleted by episodic commercial hunting that was heaviest from the 18th through the mid-20th centuries. Native people of the Arctic have depended on walruses for food, hides, ivory, and bones since first contact, and subsistence harvests of all three subspecies continue today in most parts of their ranges. Direct conflicts with fisheries are low; however trawl fisheries can disturb important benthic feeding area (Born 2003). Human disturbance at land-based haul-out sites, low-level aircraft over-flights, and near-shore passage of vessels can have serious effects on walruses out of the water, as they are highly susceptible to disturbance, and easily panicked into stampedes. Fay and Kelly (1980) documented an instance of a mass mortality of approximately 1,000 animals from a stampede event at Saint Lawrence Island. The cause of the stampede is unknown; however this mass mortality event underscores the risks of any source of disturbance to aggregations of hauled-out walruses. Global warming and any associated reduction in the extent, timing, and characteristics of seasonal sea ice cover could negatively effect walrus populations. Declining sea ice reduces suitable strata for pupping and breeding aggregation, and limits access to offshore feeding areas (Tynan and DeMaster 1997, Moore 2005). In contrast Stirling and Derocher (1993) suggest that climatic warming could result in more favorable conditions for bearded, harp, and harbor seals and walruses if it causes sea ice to become less consolidated in winter, and the summer open water period to lengthen. Reduction in sea ice could also lead to the addition of commercial sea lanes in rarely visited portions of the walruses’ range, with increased risk of spills and discharge of pollutants, disturbance, and coastal development (Reijnders et al. 1993, Tynan and Demaster 1997, Moore 2005).","Coastal Alaska Natives have hunted walruses for subsistence purposes in the United States under an exemption from the Marine Mammal Protection Act since 1972. No quotas or limits have been established, but all animals taken are required to be harvested in a non-wasteful manner. Quotas on harvest have been imposed in Canada and in the Russian Federation. Walrus hunting in east Greenland has been banned and is regulated in other areas of Greenland. In the Laptev Sea, only natives and members of scientific expeditions are allowed to kill walruses (Reijnders et al. 1993).",European Mammal Assessment team +ANIMALIA,CHORDATA,MAMMALIA,CARNIVORA,PHOCIDAE,Cystophora cristata,,No,No,NA,,NA,,"This species is a vagrant in the marine region covered by the European Mammal Assessment, consequently it is classed as Not Applicable.",-,"Hooded seals are found in the Arctic Ocean and in high latitudes of the North Atlantic. They breed on pack ice and are associated with it for most of their lives, shifting their distribution with seasonal fluctuations in ice cover (Sergeant 1974). There are four major pupping areas: near the Magdalen Islands in the Gulf of St. Lawrence, north of Newfoundland and east of Labrador in an area known as the “Front”, the Davis Strait, and near Jan Mayen (Reeves and Ling 1981). Hooded seals wander widely, and animals have beached as far south as Portugal and the Canary Islands in Europe, and from New England south to several islands in the Caribbean, in the Americas. Since the mid 1990s large numbers of wandering vagrants have been found away from the Arctic in some years, and the numbers of these sightings are increasing for unknown reasons (Mignucci-Giannoni and Haddow 2002).","The current worldwide population of hooded seals is unknown. From the 1950s to the 1980s various estimates were published giving a population from 300,000-600,000 animals. However, the methods used to generate these past estimates are poorly documented and the estimates are considered unreliable (Kovacs and Lavigne 1986). Counts of pups born in the western Atlantic breeding areas have been used to extrapolate an estimate of approximately 400,000-450,000 animals for the Front and Gulf of Saint Lawrence herds (Waring et al. 2005). Using similar methods, the Jan Mayen stock has been estimated at 200,000 animals (Reijnders et al. 1993).","Hooded seals are markedly sexually dimorphic pinnipeds. Adult male hooded seals average 2.5 m in length and 300 kg (Kovacs and Lavigne 1986), with very large animals reaching over 400 kg (Kovacs 2002). Adult females are smaller, averaging 2.2 m and 160 kg (Kovacs and Lavigne 1986), but can reach 300 kg (Reeves and Ling 1981). Pups are born at approximately 1 m in length and 25 kg (Kovacs 2002).Hooded seals pup on pack ice in March and early April. The breeding season for this polygynous species is very short, usually lasting about two weeks, and mating takes place in the water (Boness et al. 1988). This species has the shortest lactation period for any mammal, with most pups being weaned in four days at an average weight of 42.6 kg (Bowen et al. 1985). Most animals congregate in the Denmark Strait or north of Jan Mayen for a post-breeding molt in early summer, followed by dispersal in the North Atlantic (Kovacs and Lavigne 1986). With the exception of the breeding and molting periods where they form short-lived, loose aggregations in specific areas, hooded seals live solitary lives that can last 25-30 years (Kovacs 2002).Hooded seals are capable divers and spend approximately 90% of their time at sea submerged. The majority of dives are from 100-600 m in depth and last 5-25 minutes, however, very deep dives to over 1,000 m and others lasting almost an hour have been recorded (Lavigne and Kovacs 2002). Although their diet is not well known, hooded seals have been reported to feed on a wide variety of fish and invertebrates, including species that occur throughout the water column. Examples of typical prey are Greenland halibut, cods such as polar and Atlantic cod, redfishes (Sebastes spp.), herring, capelin, squid, and shrimp (Reeves and Ling 1981, Kovacs and Lavigne 1986). Polar bears, killer whales, and Greenland sharks are known hooded seal predators (Lavigne and Kovacs 1988).","Hooded seals were subjected to episodes of intense commercial hunting in the 19th and 20th centuries. Harvests were often conducted in association with harp seal harvests and commercial fisheries for Greenland sharks. Norway, the Soviet Union, Canada, and Greenland have been principally involved in the commercial harvests. Following World War II this was primarily focused on newborns, because of their highly prized blue-back pelt, however, many adults females were taken when defending their pups. Annual harvests of hooded seals continue in Canada and Greenland (Lavigne and Kovacs 2002). In 1985 a permanent import ban on hooded seal pelts by the European Union ended most of the commercial harvesting of this species, although Canada took approximately 26,000 as recently as 1996. Hooded seals are also taken by Native People of Greenland and Canada for subsistence purposes every year (Kovacs 2002). Bycatch of hooded seals in coastal net fisheries has been reported from the United States, from trawl fisheries off Norway and Newfoundland, and salmon drift nets used off Greenland (Reeves et al. 1992, Waring et al. 2005, Woodley and Lavigne 1991). Competition for food with commercial fisheries and other predators has been suggested as a factor that may limit population growth or lead to declines (Reijnders et al. 1993).Impacts of oil spills on hooded seals have not been reported; however as an ice breeding species, they might be at risk of mortality from spills during the pupping season when newborn and newly weaned pups could be fouled (St. Aubin 1990). Hooded seals did not suffer fatalities during the mass die-off of harbour seals in European waters from phocine distemper virus in 1998 and 2002. Subsequent testing of a variety of Arctic seals revealed antibodies to the virus in 18-24% percent of the hooded seals sampled indicating exposure and transmission of the virus (Harkonen et al. 2006). The hooded seal is an Arctic pack ice species dependent on ice as a substrate for pupping, molting, and resting, and as such is vulnerable to reduction in extent or timing of pack ice formation and retreat. The productivity of the ice edge ecosystem is also dependent on the dynamics and seasonality of Arctic ice, and alteration of the cycle of formation and retreat could have negative effects on important hooded seal prey such as Arctic cod (Tynan and DeMaster 1997). Decreases in sea ice cover could also lead to more shipping and development of extraction based industries in the Arctic which in turn could negatively affect hooded seals through increased exposure to contaminants and pollution, increased disturbance, and increased risk of shipping accidents and spills (Pagnan 2000).","Numerous conservation measures, international management plans, harvest quotas, and agreements and treaties, have been developed for the conservation of hooded seals dating back to the 1870s. Molting seals in the Denmark Strait have received complete protection since 1961. Harvest quotas at Jan Mayen began in 1971, hunting was banned from the Gulf of Saint Lawrence in 1972, and quotas were placed on the rest of the Canadian harvest beginning in 1974. A European Economic Community ban on importation of all seal products in 1985 reduced the harvest of blue-back hooded seals through loss of the primary market for the furs (Reeves et al. 1992). In addition to establishing quotas, several countries place observers on commercial fishing boats, and monitor subsistence harvests.",European Mammal Assessment team +ANIMALIA,CHORDATA,MAMMALIA,CARNIVORA,PHOCIDAE,Erignathus barbatus,,No,No,NA,,NA,,"This species is a vagrant in the marine region covered by the European Mammal Assessment, consequently it is classed as Not Applicable.",-,"Bearded seals have a circumpolar distribution in the Arctic and sub-Arctic south of 85 degrees North, usually in water less than 200 m deep (Kelly 1988). A disjunct population inhabits the Sea of Okhotsk, ranging south to Hokkaido, Japan (Rice 1998). They reach the southern Bering Sea and Bristol Bay to the limit of seasonally ice covered waters (Kelly 1988). They also occupy all of Hudson Bay, and range south to Southern Labrador, and northern Iceland and Norway (Kovacs 2002).Bearded seal vagrants have been reported from many locations outside the Arctic including Portugal in the eastern North Atlantic (van Bree 2000), the Gulf of Saint Lawrence, northern Newfoundland, and Cape Cod, Massachusetts in the western North Atlantic (Gosselin and Boily 1994).The ranges of the two subspecies are divided near the central Canadian Arctic in the Western Hemisphere, and Laptev Sea in the Eastern Hemisphere, with the Atlantic subspecies barbatus occurring from the central Canadian Arctic east to the central Eurasian Arctic, and Pacific subspecies nauticus occurring from the Laptev Sea east to the central Canadian Arctic, including animals in the Sea of Okhotsk (Rice 1998).","The worldwide population of bearded seals is unknown (Kovacs 2002). Portions of the range have the following abundance estimates: 200,000-250,000 in the Sea of Okhotsk, including 60,000-75,000 off eastern Sakhalin Island for the period 1968 to 1990, and 250,000-300,000 in the Bering Sea, including 83,000-87,000 in the western Bering Sea (Fedoseev 2000). A minimum estimate for Canadian waters of 190,000 animals was suggested by Cleator (1996), based on data collected over a 35-year period. Angliss and Outlaw (2005) state that there are no current reliable population estimates for the Bering Chukchi stock of bearded seals. No estimates exist for the population in the Atlantic Ocean (Reijnders et al. 1993), or Barents to Chukchi seas area.","Bearded seals are the largest phocids in the Arctic. Adults reach lengths of 2-2.5m and weights of 250-300 kg (Andersen et al. 1999) with females typically being slightly larger than males (Kovacs 2002). In the Bering Sea, males have been recorded to reach 390 kg and females 361 kg (Kelly 1988). Sexual maturity is reached at 3-6 years in females, with 80% of females having had a pup by age 6. Males reach sexual maturity at 6-7 years (Kelly 1988). Physical maturity occurs at approximately 9-10 years (McLaren 1958), and they can live 20-25 years (Kovacs 2002). Bearded seal pups are born on the sea ice, but they swim within hours of birth (Kovacs 2002), and before they are weaned they are spending about half their time in the water. Bearded seals primarily feed on or near the bottom, and most diving is to depths of less than 100m (Kovacs 2002). Therefore they live primarily in waters overlying the continental shelf, like much of the relatively shallow Bering Sea when it is seasonally covered with ice (Burns 1981). Adults have been recorded to dive to nearly 300 m, and young pups to over 488 m (Kovacs 2002).Ice is also a determinant of habitat. Bearded seals are typically found away from shore-fast ice and unbroken heavily covered ice fields, preferring areas with moving ice where ice movement, currents, weather and land features interact to create broken ice fields, leads, polynas, and other open areas (Burns 1981). They rarely haul out more than a body length from water (Kovacs 2002). Bearded seals are typically solitary animals, but will form loose aggregations when ice availability is low (Kovacs et al. 2004). The diet of bearded seals varies by age, location, season, and possibly changes in prey availability in marine communities over long time periods (Kelly 1988). Their primary foods live on or near the bottom, but also include some infauna and schooling and demersal fish (Burns 1981). At Svalbard, bearded seals took a wide variety of prey and over half of the stomachs examined had 5 or more species. Arctic cod, found in 44% of the animals, sculpins (Cottidae spp.) in 44%, spider crab (Hyas araneus) in 59%, and the crustaceans Sabinea sptemcarinatus 59% and Sclerocrangon boreas 46%, were the most frequently found prey items (Hjelset et al. 1999).In June, following the pupping and breeding season, bearded seals undergo their annual molt. During the molt they spend much of their time hauled out, and are reluctant to enter the water (Kovacs et al. 2004). Animals can be found molting from April to August with a peak in May to June (Burns 1981). Bearded seals usually haul out on ice when it is available, but will haul out on land in the summer in the Sea of Okhotsk, along the Laptev, White, and Kara Sea coastlines (Burns 1981), and at Svalbard (Kovacs et al. 2004).Important natural predators of bearded seals include polar bears (Burns 1981), as well as killer whales, walruses, and Greenland sharks (Kovacs 2002).","Native Peoples of the Arctic have hunted bearded seals for subsistence for thousands of years, a practice that continues today (Burns 1981). Overall levels of subsistence harvest are not well known. The former Soviet Union had commercial harvests in the Sea of Okhotsk, and the Bering, Chukchi, Barents, and White Seas historically, and harvest levels were at times high. Harvest levels grew from 9,000 to 13,000 from 1957 to 1964, and were 8,000 to 10,000 per year for the Bering and Okhotsk Seas combined from 1964-1967 (Reeves et al. 1992). This commercial over-harvesting probably depleted the population (Kelly 1988). Bearded seals are now harvested more on a subsistence basis for local use in Russia, although some seals are killed as food for fur-farm animals (Kelly 1988), and are primarily taken from the Bering Sea where harvests of 1,881 and 1,418 were reported for 1988 and 1989 respectively (Reeves et al. 1992).Fisheries interactions appear to be low. Logbooks indicate 14 bearded seals killed and 31 injured in 1991 in the Bristol Bay, Alaska salmon drift net fishery. There were several incidents of incidental take, serious injury, or mortality each in the Alaskan Bering Sea/Aleutian Islands flatfish and pollock trawl fisheries respectively from 1999-2003, when annual mortality was estimated at 1.58 seals (Angliss and Outlaw 2005). Oil spills from offshore extraction and transportation could negatively affect bearded seals through direct contact with oil, and damage to foraging areas and stocks of prey, particularly benthic invertebrates, which respond poorly to oil contamination (Kelly 1988).Arctic climate change that is currently leading to reduction in the extent and duration of sea ice cover is a threat to many species of marine mammals. Patterns of Arctic primary productivity and population levels of prey species important to Arctic marine mammals may be altered as a consequence of Arctic warming and changes in sea ice. Pinnipeds, such as the bearded seal that are dependant on sea ice for pupping, molting, resting, and access to foraging areas, may be especially vulnerable to such changes (Tynan and DeMaster 1997). In contrast, Stirling and Derocher (1993) suggest that climatic warming could result in more favorable conditions for bearded, harp, and harbor seals, and walruses if it causes sea ice to become less consolidated in winter, and the summer open water period to lengthen.An increase in human-created noise in the Arctic environment could cause marine mammals, including bearded seals which are very vocal during their breeding season, to abandon areas of habitat (Tynan and DeMaster 1997). A reduction in sea ice cover would likely lead to increased human activity in the Arctic in the form of shipping and extractive industries, and an associated greater threat of marine accidents and disturbance of marine mammals (Pagnan 2000). Harp seals, hooded seals, and ringed seals from the Canadian Arctic, where they share habitat with bearded seals, were all determined to carry antibodies to phocine distemper virus (PDV), with harp seals constituting the population with the largest percentage (83%) of positive tests. Although the disease has not been identified in bearded seals, the opportunity for exposure exists (Duignan et al. 1997).","Bearded seals are protected by various laws in their range countries and by treaties internationally. Subsistence hunting by Native People of the Arctic is generally for personal use and not regulated, for example, as in Canada and the United States (Cleator 1996, Angliss and Outlaw 2005).Vessel-based commercial hunting in the former Soviet Union ended in 1975 and the harvest continues at much lower levels, more like a subsistence harvest. Prior to the end of commercial harvesting, the Soviet Union used a system of quotas to regulate the take in an attempt to manage the population (Kelly 1988). Licensed hunters can take bearded seals in Svalbard, but not in nature reserves or during the breeding season (Kovacs et al. 2004).",European Mammal Assessment team +ANIMALIA,CHORDATA,MAMMALIA,CARNIVORA,PHOCIDAE,Halichoerus grypus,,No,No,LC,,LC,,"This species is widespread and abundant, and European populations are stable or increasing. Consequently it is classed as Least Concern.",Possibly Favourable,"Grey seals have a cold temperate to sub-Arctic distribution in the North Atlantic waters over the continental shelf (Hall 2002). There are three populations isolated both geographically and by timing of reproduction (Bonner 1981). In the western Atlantic, the population is centered in northeastern North America from the Gulf of Maine to southern Labrador, including the Gulf of St. Lawrence. The eastern Atlantic population is found at Iceland, the Faroe Islands, from the Kola Peninsula south to southern Norway, around most of the United Kingdom and Ireland, and in Brittany in France. The Baltic Sea stock is entirely confined to the Baltic Sea (Bonner 1981, Hall 2002). Vagrants are known from as far south as New Jersey in the western Atlantic and Portugal in the eastern Atlantic (Rice 1998).","Grey seal numbers are increasing at some locations while declining in others. The total world population is not completely known. Canada’s Department of Fisheries and Oceans estimates its present population at 250,000 divided into in two herds, mainly in the southern Gulf of St Lawrence, and at Sable Island (Anon. 2006). Aerial surveys in 1997 provided an abundance estimate for the Gulf of Saint Lawrence and Sable Island populations at 195,000 animals. The Sable Island population is increasing by 13% per year. The Gulf of St. Lawrence population is decreasing by and unspecified amount. There are approximately 7,300 gray seals in United States waters, where its numbers are increasing (Waring et al. 2005). The population estimates for areas in the eastern North Atlantic are: Iceland, 11,600 (Hauksson 1987), Norway, a minimum of 3,100 (Wiig 1986), Ireland 2,000, the White Sea 1,000-2,000, and the United Kingdom 110,000 and increasing at 6% per year (Hall 2002). The Baltic Sea population is given as 17,640 (ICES 2005).","Grey seals are large sexually dimorphic phocids. In the United Kingdom, adult males are on average 2.07 m long and weigh an average 233 kg, with a maximum of 310 kg. Adult females are smaller, averaging 1.79 m and 155 kg. At birth, pups are 90-105 cm, with male pups averaging 15.8 kg and female pups averaging 14.8 kg in weight (Bonner 1981). Adults in the western Atlantic are larger, with males averaging 2.25 m and 300-350 kg, and females averaging 2 m and 150-200 kg (Mansfield 1988), with males reaching a maximum of over 400 kg and females over 250 kg (Hall 2002).Pupping occurs from September to March with peak dates differing significantly between populations: in the western Atlantic, January; eastern Atlantic, September-December; and in the Baltic Sea, late February to early March, which probably reproductively isolates each group (Bonner 1981). Pups are born on ice or land in the western North Atlantic, land in the eastern North Atlantic, and ice in the Baltic (Bonner 1981). Pups are born with a woolly lanugo that is molted several weeks after weaning. The pup stays on land from birth until the molt is finished, losing up to 25% of its body weight from fasting (Mansfield 1988). In the United Kingdom, pups molt before weaning; adult females molt from mid-January to mid-February, and males molt from mid-February to early April (Bonner 1981).Grey seals not known for being long-distance migrants. In one study, they spent 43% of their time within 10 km of frequently used haul-out sites, traveling to sandy areas, or gravel sea-bed sediments, the preferred habitat of sandeels, an important part of the grey seal’s diet. Short trips away averaged 2.3 days (McConnell et al. 1999). In Canada, tagging revealed that some animals travel 350-800 km, and in the United Kingdom, they took short-range trips. Occasionally, long treks of up to 2,100 km were made, crossing deep water from northern England to the Shetlands or Orkneys, and from the Faroes into the North Sea. In the Baltic Sea, grey seals make short trips, spending roughly 75% of their time within 50 km of haul-out sites (Sjoberg and Ball 2000).Grey seals' diet varies by location, though they are largely demersal or benthic feeders (Hall 2002). In some areas, the food consumed can be over 70% sandeels (Ammodytes sp.). In the United Kingdom, sandeels, cod and Dover sole accounted for 56% of the diet by weight (Prime and Hammond 1990).","Grey seals have been important in subsistence harvests throughout the history of their contact with humans. They have been hunted by peoples of the Baltic Sea coast for more than 10,000 years (Harkonen et al. 2005). Commercial harvesting has been ongoing in many areas for hundreds of year, and at times grey seals have been important to local economies (Mansfield 1988). Overharvesting in the Baltic in the early 20th century led to a large decline, from a population that once numbered an estimated 30,000 to perhaps as high as 200,000 to a low of 1,500-2,000 by the early 1980s (Kokko et al. 1999).Government culls, bounties, and licensed kills for harvest and protection of fishing gear have been put into effect in many countries, and continue to be used in some in efforts to control grey seal numbers and reduce their impact on commercially important fisheries. Grey seals feed on a number of commercial species, and by damaging nets and traps, they are in direct conflict with fisheries. Indirectly, grey seals are a vector for seal worm, also known as cod worm, a destructive parasite of Atlantic cod (Mansfield 1988, ICES 2005). Entanglement in commercial fishing nets causes bycatch mortality in most parts of the grey seals’ range (Woodley and Lavigne, 1991). Bycatch levels are approximately 300 per year in Swedish fisheries in the Baltic (ICES 2005). Of 528 deaths of tagged seals in the United Kingdom, 148 were attributable to fishing nets. However, this may overestimate the rate of entanglement-related mortality due to the high rate of tag returns from fisheries. It was also estimated that 1-2% of animals less than a year old die in fishing gear (Woodley and Lavigne 1991). Grey seals are known carriers of the morbillivirus known as phocine distemper virus (PDV), in all populations (Ross et al. 1992, Duignan et al. 1995, Harkonen et al. 2006). However, they have suffered almost no mortality from the disease. Harkonen et al. (2006) report grey seal mortality of approximately 230 (equal to 1% of the harbour seal mortality) in the 1988 epizootic in Europe, and the death of 30 gray seal pups in the Baltic were attributed to PDV. Because grey seals haul out with harbour seals in the Wadden Sea, and are known to travel more widely than the sedentary harbour seal, it is presumed that they had a role in the outbreak and spread of the 2002 epizootic of PDV in harbour seals.As a coastal species, grey seals are exposed to and ingest industrial and agricultural pollutants through the food chain. PCBs and DDT contaminant loads are extremely high in Baltic gray seals, despite the fact that tissue burdens have declined since the 1970s. Analysis of samples collected from 1996 to 1998 indicated that gray seals still have a very heavy load of contaminants when compared to other seals outside the Baltic (ICES 2005). Health effects on grey seals have been suggested to be linked to very high exposures of PCBs and DDT. Baltic grey seals have a relatively high rate of colonic ulcers, sometimes fatal, associated with hookworm infestations. This condition occurs in Baltic ringed seals as well, but essentially not found elsewhere in either species (ICES 2005). Uterine stenosis and a range of pathologies in other organs have been attributed to long-term exposure to environmental toxins, particularly in older Baltic gray seals. These are specifically linked to reproductive and population declines for this subspecies, and are conditions not seen in other populations (Bergman et al. 2001). However, no negative effects have been attributed to heavy metal contaminants in Baltic gray seals (Bergman et al. 2001, ICES 2005).Grey seals are generalist predators, and their population has increased in recent decades during periods of declines of some commercial fish stocks that are important grey seal prey. The risks of overfishing or climate-induced declines of fish stocks on grey seals are unclear at this time. One potential threat is the risk of a demand for larger culls and control of grey seal populations to help rebuild fisheries stocks that are affected by, or are presumed to be affected by, grey seals. This would be similar to the efforts to manage harp seals after the collapse of the Atlantic cod fishery, as discussed by DeMaster et al. (2001). Despite the fact that the collapse of the cod fishery is probably not attributable to seal predation, there has been ongoing pressure to cull the populations of harp seals and gray seals (Yodzis 2001).The potential effects of climate change, either warming or cooling, on gray seals are not well known. Although not a high Arctic species, some grey seals pup on ice and are seasonally associated with ice in parts of their range (Bonner 1981). It is unknown how decreases in sea-ice cover might affect gray seals, although Learmonth et al. (2006) identify the gray seal as a species that will probably undergo a decrease in range because of climate change.None of the above is thought to be a major threat to the species as a whole at present.","Numerous countries have invoked protective measures to limit grey seal harvests, culls, disturbance, and by-catch (Bonner 1981, ICES 2005). Pollutant loads in Baltic gray seals have declined in step with regulations banning of the use and/or discharge of toxic pollutants such as DDT and PCBs beginning in the 1970s, and the reproductive health of female grey seals has improved as has the population level in the Baltic (Bergman et al. 2001). Establishment of coastal marine reserves for seals in Norway have been more effective in protecting harbor seals than grey seals because the latter are more likely to travel outside the areas closed to fisheries and become entangled in nets (Bjore et al. 2002).",European Mammal Assessment team +ANIMALIA,CHORDATA,MAMMALIA,CARNIVORA,PHOCIDAE,Monachus monachus,,No,No,CR,C2a(ii),CR,C2a(ii),"The Mediterranean monk seal has a very small population (<250 mature individuals) in the European Mammal Assessment area. There is only one breeding population remaining in the region, so it is presumed that all animals belong to the same subpopulation. There are ongoing declines as a result of fisheries bycatch, persecution, human disturbance, and other threats. Consequently the species is assessed as Critically Endangered.",Unfavourable,"Mediterranean monk seals were once widely and continuously distributed in the Mediterranean, Black and adjacent seas, in North Atlantic waters off northwest Africa south to Cap Blanc, and possibly Senegal and Gambia. They also were found at the Cape Verde Islands, Canary Islands, Madeira Islands and Azores, and north as vagrants to Portugal (Ronald and Healey 1982), and Atlantic France (Israels 1992). Today the distribution is wide but extremely fragmented with three surviving small breeding populations located at opposite ends of the historic range. In the Mediterranean, the stronghold for the species is on islands in the Ionian and Aegean Seas, and along the coasts of Greece and western Turkey. The two surviving colonies in the southeastern North Atlantic are at Cabo Blanco (also known as Cap Blanc or Ras Nouadhibou) on the border of Mauritania and Western Sahara, and the small colony at the Desertas Islands in the Madeira Islands group (Gilmartin and Forcada 2002). Many locations where seals are infrequently or regularly seen, or were seen in the recent or historic past, are reported in the literature and cataloged in reviews and status updates, see Sergeant et al. (1978), Israels (1992), UNEP/MAP (2005).","The Mediterranean monk seal is the most threatened pinniped species in the world, with an estimated population of 350-450 animals. The largest remaining population is that of the eastern Mediterranean, with 250-300 individuals, of which c.100 occur in Turkish waters (Güçlüsoy 2004). Approximately 100 to 130 seals are found at Cabo Blanco in Western Sahara and Mauritania, and approximately 20-23 at Desertas Island, Madeira (Pires and Neves 2001, Gilmartin and Forcada 2002, UNEP/MAP 2005). The population at Cabo Blanco was estimated at 317 seals before the loss of an estimated 70% in a mass mortality event in 1997 (Forcada 2000). Following this event, 24 pups were born at Cabo Blanco in 1997, comparable to the rate of births in 2004 and 2005, but this number rose significantly in 2006 to 46 births (Cedenilla and de Laminoa 2006). A recent review of monk seal occurrences reported at all other locations and countries from 1999-2005 yielded a minimum of 14 additional seals, with 10 of the 14 in Algeria, plus an unspecified number of vagrants (UNEP/MAP 2005).","Mediterranean monk seals are medium-sized phocids that reach 2.3-2.8 m (Gilmartin and Forcada 2002). Adults weigh from 240-300 kg, and newborns 15-26 kg (Boulva 1979, Gilmartin and Forcada 2002), with records of a male reaching 400 kg and a pregnant female reaching 302 kg (Sergeant et al. 1978). Mediterranean monk seals once hauled out on open beaches, but this is now rare, and throughout their range they use caves with sea entrances for hauling out and pupping (Gilmartin and Forcada 2002). Sea caves used by seals often have submerged entrances or some other barrier to provide protection from waves. In a study that covered 250 km of coastline inhabited by monk seals in the Cilician Basin region of southern Turkey, 282 caves were searched. Of these, 39 showed evidence of monk seals, including 3 that were used for pupping and 16 that were actively being used. Use of these caves increased in October coincident with the autumn pupping season in Turkey (Gucu et al. 2004). The maximum number of seals from this small Turkish population found in a cave in at one time was 3 (Gucu et al. 2004). Sea caves are also used extensively at Cabo Blanco, particularly northwest of the cape. Two caves separated by 1.1 km accounted for 84% of the births in the area from 1993-1997 (Gazo et al. 1999). In contrast to the situation in Turkey, counts at one cave in the Las Cuevecillas section of the Cabo Blanco colony recorded up to 89 seals hauled out at one time, and never less than 5 animals present (Gonzalez et al. 1997).Female Mediterranean monk seals probably become sexually mature at three to four years. One female at Cabo Blanco became pregnant at 2.5 years and gave birth at 3.7 years, the youngest age known for this species (Gazo et al. 2000b). Females can give birth in successive years. The annual reproductive rate in Mediterranean monk seals is very low at 0.3-0.43 pups to each sexually mature female (Gazo et al. 1999). Pup survival is low (Gazo et al. 2000a). Mediterranean monk seals take a wide variety of prey primarily from shallow water habitats (Sergeant et al. 1978, Kenyon 1981). In the eastern Mediterranean, they have been reported to take a variety of fish, octopus and loggerhead sea turtles (Caretta caretta) (Margaritoulis et al. 1996). Examination of two seals from the Aegean Sea yielded five species of prey. By weight 94% of the contents were cephalopods including musky octopus (Eledone moschata) and globose octopus (Bathypolypus sponsalis) (Salman et al. 2001).","Mediterranean monk seals have a long history of interaction with humans that includes exploitation for subsistence needs, commercial harvest, and persecution as a competitor for fisheries resources. Once abundant, monk seals were written about and illustrated in the literature and depictions of classical antiquity. They became the target of a commercial harvest for skins and oil by the Portuguese as early as the 15th century along the coast of northwest Africa (Israels 1992).Reasons given for the recent population decline include increased human population displacing seals from their habitat, mortality due to fisheries bycatch and persecution, and the possible effects of toxics and pollutants (Boulva 1979). Exacerbating these factors are political instability and wars, the challenge of implementing effective conservation for a species in a complex multi-national environment, weak enforcement of agreements and international laws, diseases, genetic consequences of inbreeding, and other catastrophes such as oil spills and collapse of occupied pupping caves (Israels 1992).Interactions with fisheries are of great conservation concern, particularly for the population in the eastern Mediterranean, where seals are killed through net entanglement and deliberately killings by fishermen. They possibly suffer from depletion of fish stocks, anti-seal methods designed to protect aquaculture facilities, and illegal dynamite fishing (Güçlüsoy 2004). Monk seals have been entangled in a wide variety of fisheries gear including set-net, trawl net, and long-line. They seem most vulnerable to set-nets placed on the bottom, and can also become entangled in abandoned and discarded nets (Tudela 2004).The deaths of 130 seals over a 10-year period ending in 1999 highlighted the significance of deliberate killing as a source of mortality (Tudela 2004). Deliberate killing of monk seals by humans was attributed to 1/3 of all mortalities of 79 stranded animals in Greece, and is considered the single most important source of mortality (Androukaki et al. 1999).The genetic diversity of Mediterranean monk seals is amongst the lowest found in pinnipeds. Only Hawaiian monk seals and northern elephant seals have lower diversity. The consequences of mating between closely-related individuals include congenital defects leading to stillborn pups and a decreased reproductive rate, both of which have been documented in the Cabo Blanco colony. Additionally, low fitness and increased susceptibility to disease may be a problem (Pastor et al. 2004). Morbillivirus was isolated from Mediterranean monk seals after the mass mortality at Cabo Blanco in 1997. The virus most closely resembled dolphin morbillivirus (DMV) that was previously implicated in the 1991 mass mortality of striped dolphins in the Mediterranean Sea (Osterhaus et al. 1992, Van de Bildt et al. 1999). Although this virus was already circulating in monk seals prior to the mass mortality, there is doubt that it caused the deaths. Dinoflagellate-produced saxitoxins were found in tissues from animals that died during the 1997 event, and the suddenness of death of the animals and other symptoms suggest that the cause of death was from the toxins rather than an epidemic of morbillivirus. Additionally, toxic algal blooms (red tides) are favored by oceanographic conditions near Cabo Blanco, and were reported from nearby Morocco the southeastern North Atlantic during a 25-year period leading up to the mass mortality. Canine distemper virus is present in stray dog populations in Aegean Turkey at a level of approximately 9% in the population. This may be a source for future infections of wild carnivores, including monk seals through contacts in harbors and along shorelines (Gencay et al. 2004).Contaminant burdens have always been suspected to be a threat to the Mediterranean monk seal, and should be investigated and routinely monitored (Boulva 1979, Reijnders et al. 1993). Tissues collected during the 1997 mass mortality and analyzed for PCBs and DDT detected levels of pollutants comparable to those found in other marine mammals not believed to be experiencing contaminant related health or reproductive effects (UNEP 2005).Mediterranean monk seals are at an unknown but suspected high level of risk from oil tanker and other ship accidents, spills and groundings. Animals could be oiled or coated in fuels and lubricants, exposed to other toxic or environment-altering chemicals or products, and experience disturbance at haul outs or coastal feeding areas. Mauritania is planning to explore offshore oilfields which would lead to increased vessel traffic in the area, and greater chance for accidents, disturbance, and collisions near important habitat. Three accidents or spills have occurred near monk seal habitat in the recent past, including a supertanker that spilled oil off of Morocco in 1989 (Israels 1992), an oil spill in the Madeira Islands in 1994 (UNEP 2005), and the grounding of a bulk carrier near Cabo Blanco in 2003 (UNEP 2005). None of these spills or accidents had any known impacts on monk seals, but they underscore the threat of significant impacts from a major maritime accident near an important monk seal site (UNEP 2005).Human disturbance has been identified as a primary factor in the decline in numbers of monk seals through displacement of animals from habitat. Traditionally, this was the result of expanding human populations and coastal development. Since the 1970s, a new threat has emerged in the form of people seeking out monk seals to view at the few remaining locations. Tourism has grown to become one of the most significant hazards faced by monk seals, particularly in the eastern Mediterranean (Johnson and Lavigne 1999). Besides disturbance, tourist activities increase the risk of vessel accidents, spills, transmission of disease, and the discharge of pollutants and waste near the seals.","The Mediterranean monk seal is protected throughout its range. Two protected areas have been established for monk seals, the Desertas Islands in the Madeira archipelago, and the Northern Sporades Islands national marine park in Greece. There are future plans to set up nature reserves to protect more habitat for monk seals in the region.Numerous agreements, conventions, and treaties are in force to protect monk seals internationally, and many workshops and conferences have brought together scientists and managers to discuss monk seal conservation issues and problems. Israels (1992) summarizes 30 years of this conservation history, and provides details on accomplishments and failures to meet objectives. Other measures in place include Action Plans completed in 1978 and 1988 for the conservation and management of monk seals, and the 2005 plan for the recovery of the monk seal in the eastern Atlantic.Many actions have been taken on a local scale including outreach and education programs, restrictions on gear and location for fisheries, development of monitoring programs and protocols, and increasing the capability to rehabilitate sick and injured animals (Gonzalez 2004).",European Mammal Assessment team +ANIMALIA,CHORDATA,MAMMALIA,CARNIVORA,PHOCIDAE,Pagophilus groenlandicus,,No,No,NA,,NA,,"This species is a vagrant in the marine region covered by the European Mammal Assessment, consequently it is classed as Not Applicable.",-,"Harp seals are widespread in the North Atlantic and the adjacent Arctic Ocean. Their range extends from northern Hudson Bay and the Foxe Basin, Baffin Island, and the Davis Strait, and the Gulf of Saint Lawrence and Newfoundland in the western north Atlantic, east to somewhat south of Greenland, continuing east to Iceland and from there to Northern Norway, the White Sea and all of the Barents and Kara Seas. The northern limit in the eastern North Atlantic is at least to Franz Joseph Land and Svalbard and may continue to between 82-85 degrees north depending on ice conditions (Lavigne and Kovacs 1988, Rice 1998, Lavigne 2002). Harp seals often wander south outside this range and vagrants have reached the United Kingdom (Ronald and Healy 1981), the Faroe Islands, Denmark, Germany, France, and Spain (Heptner 1976, Van Bree 1997, Bloch et al. 2000).","The population level in 2000 for the animals breeding in Canadian waters of the western North Atlantic, on “the Front” off Newfoundland and Labrador and in Gulf of St. Lawrence, was estimated to be 5.2 million animals (95% CI 4.0-6.5 million). Canada’s Department of Fisheries and Oceans claims the population has recovered in the past from an estimated low of around 1.8 million in the early 1970s to more than 5 million today (Anon. 2005). The breeding group on the West Ice near Jan Mayen was estimated at 296,000 in 1994. The White Sea breeding group is made up of approximately 1.5-2.0 million animals as of 1999 (Lavigne 2002). Totaling the figures from Lavigne and each area estimate gives a world population of 5.8-8.8 million, making harp seals the most abundant pinniped in the Northern Hemisphere.","Harp seals are medium-sized phocids, with adult males averaging lengths of 1.83 m and weights of 135 kg. Females are slightly smaller at 1.79 m, weighing 120 kg. Females in the northwest Atlantic mature at about 4-5 years, compared to males at 5-8 years. The Jan Mayen and White Sea breeding groups reach maturity about a year earlier (Ronald and Healey 1981). The maximum life span of a harp seal is approximately 30 years, and it is not unusual for them to reach over 20 years of age. Both males and females are sexually active until their 20s, and females may give birth every year until they are at least 16 years old (Ronald and Healey 1981).Harp seals are migratory, and after breeding, Canadian seals follow the pack ice up the coast of Labrador, with small numbers into Hudson Bay, to Baffin Island, and both sides of the Davis Strait, to Greenland. The Jan Mayen and White Sea groups migrate and mix in the Barents Sea. The Jan Mayen group reaches the high Arctic, up to 85 degrees north.Harp seals consume a wide range of prey that varies along the migration route. Their diet, according to Lavigne (2002), consists of 67 species of fish and 70 species of invertebrates. Pups and juveniles take euphausiids (Thyanoessa spp.) and amphipods (Parathemisto spp.) (Nilssen et al. 2001), whereas adults take pelagic crustaceans and a variety of fish (Kapel 2000).","Harp seals have been harvested for thousands of years by native peoples of the Atlantic Arctic, including coastal Northern Europeans (Stora and Ericson 2004). Basque whalers began taking harp seals in the 1500s. By the mid-1600s, French settlers began the hunt in the Gulf of St. Lawrence, developing land-based netting techniques on the St. Lawrence River in the 1700s. The French Canadians exported 500 tons of oil per year by the mid-1700s, based on an estimated take of 6,000 seals per year. In Newfoundland, English settlers hunted harp seals on a larger scale that accounted for an estimated 7,000-12,800 seals per year for most of the 1700s, including 50,000 whitecoats (juvenile harp seals) killed in 1773. By the 1800s, schooner-based sealing developed, and the number of seals harvested rose dramatically; from 1803-1816 the average annual was 117,000. The peak of sealing in the northwest Atlantic occurred between 1818 and 1862, when 500,000 seals were harvested in many years, reaching a maximum of 640,000-740,000 in single years. During that time, it is estimated that 18.3 million harp seals, mostly whitecoats, were killed for oil. The records show somewhat lower figures for the northeast Atlantic. At Jan Mayen, the catch began falling in the late 1850s, attributed to overhavesting. From 1860 to 1900, an estimated 12.8 million seals were harvested there (Lavigne and Kovacs 1988). The 20th century saw the advent of steel-hulled ships, and the hunt continued, though harp seals became more valued for their pelts than their oil. 143,000 seals were taken in 1917. This number fell during the war years, then rose again in the 1950s, when it averaged 312,000 seals per year. In 1960, Canada became concerned about the large numbers of adults being killed, so it placed limits on the length of the hunting season. During the 1960s, an average of 284,000 seals were taken per year. In 1964 observers sent by humane organizations described the clubbing of whitecoats, and the subsequent public outcry led to seal protection regulations controlling the methods of the kill, and the types of vessels used. Adult females were protected on the breeding grounds, and Norway was excluded from sealing in Canadian waters. In 1971 a quota management program was set up, and from 1970 to 1987 the quotas varied, from 127,000 per year to 245,000 per year, but the actual harvest was often much lower (Lavigne and Kovacs 1988).In 1983, the European Economic Community imposed an import ban on all whitecoat (juvenile harp seal) products, and the average annual harvest in Canadian waters fell to 52,000 seals from 1983-1995. By 1987, Canada outlawed the killing of whitecoats, and the focus of the hunted switched to beaters (post-weaning to 13 months of age) (Anon. 2006a). From 1999-2003, the estimated annual mortality of harp seals in the northwest Atlantic was 453,962, broken down into an average of 232,915 taken in the commercial harvest by Canada, 83,010 taken from 1999-2002 in Greenland, and 4,881 taken in the Canadian high Arctic, plus a bycatch of 18,566 in the Newfoundland lumpfish fishery, with an average annual struck and loss rate of 119,430 from all harvests (Waring et al. 2005). Since the late 1970s large numbers of harp seals have been leaving the Barents Sea, and possibly the Greenland Sea, to forage along the coast of Norway, resulting in the deaths of thousands of seals in shore-based net fisheries. Bycatch mortality from nets was estimated to be 56,647 (perhaps up to 100,000) in 1987, and 21,474 in 1988 (Haug et al. 1991, Woodley and Lavigne 1991). Another threat to harp seals is the overharvesting of their prey, including herring and capelin. There have also been calls for an increased cull of harp seals to protect the Atlantic cod fishery, for some years in a steep decline (Lavigne 2002). Oil spills in the northwest Atlantic off the east coast of Canada remain a threat to seals. There is a concern about the impacts of tanker traffic, particularly in places like Lancaster Sound in the eastern Canadian Arctic, which is an important harp seal summering area (Reijinders et al. 1993). Additionally, harp seals have been found to carry significant loads of contaminants including heavy metals, organochlorines and PCBs (Ronald et al. 1984a,b). Phocine distemper virus (PDV) was first found in harp seals from the West Ice off Jan Mayen in 1987 and 1989. It is widespread in harp seals, but it is not known if there are significant health effects or mortality from the infection. The harp seals may have been carriers infecting harbor seals, which did experience a mass mortality in Europe in 1988 (Markussen and Have 1992).","Canada has in place sealing regulations pursuant to the 1993 Marine Mammal Regulations that require annual quotas, referred to as “Total Allowable Catches,” hunting licenses, and official observers of the commercial hunt (Anon. 2005). In the northeast Atlantic, quotas for sealing are based on recommendations made by the International Council for Exploration of the Sea (ICES) and the Northwest Atlantic Fisheries Organisation (NAFO). Russia is responsible for managing seals in the southeast part of the Barents Sea, while Norway is responsible for managing stocks in the Greenland Sea by Jan Mayen (Anon. 2006b).",European Mammal Assessment team +ANIMALIA,CHORDATA,MAMMALIA,CARNIVORA,PHOCIDAE,Phoca vitulina,,No,No,LC,,LC,,"This species is widespread and abundant. Population size well exceeds the threshold for the population size criterion of the IUCN Red List (i.e. less than 10,000 mature individuals in conjunction with appropriate decline rates and subpopulation qualifiers). Population trend has not been quantified, but it is not believed to approach the threshold for the population decline criterion of the IUCN Red List (i.e. declining more than 30% in ten years or three generations). For these reasons, the harbour seal is evaluated as Least Concern at the European level. There is concern, however, for the Baltic Sea and Svalbard populations.",Unknown,"Harbour seals are one of the most widespread of the pinnipeds. They are confined to coastal areas of the Northern Hemisphere, from temperate to polar regions. Five subspecies are recognized: P. v. vitulina occurs in the eastern Atlantic from northern Portugal to the Barents Sea in northwestern Russia, and north to Svalbard; P. v. concolor occurs in the western Atlantic from the mid-Atlantic United States to the Canadian Arctic and east to Greenland and Iceland; P. v. mellonae only lives in several lakes and rivers in Quebec, Canada that drain into Hudson and James Bays; P. v. richardii is found in the eastern Pacific from central Baja California, Mexico to the end of the Alaskan Peninsula, and possibly to the eastern Aleutian Islands, and P. v. stejnegeri ranges from either the end of the Alaskan Peninsula or the eastern Aleutians to the Commander Islands, Kamchatka, and through the Kuril Islands to Hokkaido in the western Pacific.","Combining recent estimates yield a world-wide population of 350,000 to 500,000 animals. P. v. stejnegeri of the western Pacific (approximately 7,000), and P. v. mellonae (120-600), of the seal lakes of the Ungava Peninsula, Canada, may be the subspecies most at risk due to low population numbers. Populations in Svalbard and the Baltic Sea, both in the hundreds, are also dangerously low, although they are not considered to be separate subspecies from P. v. vitulina.","Harbour seals are mainly found in the coastal waters of the continental shelf and slope, and are also commonly found in bays, rivers, estuaries, and intertidal areas. Although generally considered non-migratory species with a high degree of site fidelity to a haul out, juvenile dispersal, emigration, and establishment of new haul out sites are all possible reasons for long range movements of harbor seals (Burns 2002).Harbour seals are generalist feeders taking a wide variety of fish, cephalopods, and crustaceans obtained from surface, mid-water, and benthic habitats. Generally, a few species dominate the diet at any one location and time of year. Harbour seals also take many commercially important fish species such as Atlantic cod, many kinds of salmon, herring, and flatfishes, and this aspect of their foraging puts them into conflict with coastal fisheries. Although primarily coastal, dives to over 500 m have been recorded (Burns 2002).Male harbour seals become sexually mature when four to five years old. Longevity is typically 35 years for females and 25 years for males.","Harbour seals live in coastal areas in some of the most heavily fished waters on earth, and as a result there are significant entanglement and by-catch issues, as well as effects on the food chains they depend on for their prey. Historically there have been organized population reduction programs and bounties for taking seals in many parts of their range, and licenses, permits, and legal allowances are also available in a number of countries today to commercial fishermen to take animals that depredate nets, traps, and lines. Harbor seals may still be taken by subsistence hunters in Canada, Greenland, and the United States. Mass die-offs from viral outbreaks have claimed thousands of harbor seals. In 1988 and 1989 more than 18,000 harbor seals are estimated to have died from a phocine distemper virus (morbillivirus) epidemic in European waters. Other disease outbreaks occurred both before and after this large epidemic in both Europe and the western North Atlantic, but resulted in much smaller levels of mortality. Because many harbor seals live and feed in close proximity to large populations of humans they are exposed to and can accumulate high levels of industrial and agricultural pollutants. Immunosuppression is one effect regularly attributed to exposure to high levels of certain organochlorines, and these and other contaminants probably contribute to poor condition and overall fitness of a number of animals in some areas. Both chronic oil spills and discharges, and episodic large scale spills cause direct mortality, and have long term impacts on harbor seal health and their environment.","Hunting of subspecies P. v. vitulina is currently only permitted in Norway and Iceland, where there may be an annual catch of 5,000-7,000. In the United Kingdom, shooting licenses may be issued in order to protect fishing activities. In the United States the harbour seal is protected from all but subsistence hunting by the Marine Mammal Protection Act of 1972, which also prohibits importation of parts or products from all seals. Coastal reserves in Norway which exclude commercial fishing have been shown to reduce harbour seal mortality. Hunting is now prohibited in the Wadden Sea area (Netherlands, Germany, Denmark, and Sweden) (Reijnders et al. 1993).",European Mammal Assessment team +ANIMALIA,CHORDATA,MAMMALIA,CARNIVORA,PHOCIDAE,Pusa hispida,Five recognized subspecies: hispida; botnica; ladogensis; saimensis; and ochotensis.,No,No,LC,,LC,,"The only subspecies of ringed seal that occurs regularly in the marine area covered by the European Mammal Assessment is the Baltic ringed seal, P.h. botnica. Consequently the European regional assessment refers to this subspecies only. Although this subspecies was severely depleted by overharvesting in the past, it is now recovering. Whilst the number of mature individuals is still less than 10,000, the Bothnian Bay population, which constitutes c.75% of the total, is increasing at approximately 4.5% per year, and has done so consistently for more than ten years. As the regional population is expanding at a steady rate overall, it is classed as Least Concern, even though numbers remain low and there is serious concern for seals in some parts of the Baltic (e.g. the Gulf of Finland and the Gulf of Riga). Ongoing conservation efforts are necessary to ensure that the population continues to recover. The Saimaa ringed seal P.h. saimensis qualifies as Endangered under Criterion D as it has a very small population (<250 mature individuals) but it is not declining at present.The Ladoga ringed seal P.h. ladogensis qualifies as Vulnerable under Criterion D2 owing to its very restricted range.",Possibly Favourable,"Ringed seals have a circumpolar distribution throughout the Arctic basin including near the North Pole (Rice 1998), and range widely into adjacent seas. They are found in the Bering Sea, Canadian Arctic Archipelago, Hudson Bay and Straits, Davis Strait, and Greenland, Barents, Kara, Laptev and East Siberian seas. Separate populations occur in the Baltic Sea, Lake Ladoga in the Russian Federation, Lake Saimaa in Finland, and the Sea of Okhotsk south to northern Japan (Frost and Lowry 1981, Reeves 1998). Vagrants have been recorded south to Portugal and the Azores in Europe, southern California and New Jersey in the United States, and Zhejiang in China (Rice 1998). Ringed seals are distributed in waters of nearly any depth, and their distribution is strongly correlated with seasonally and permanently ice-covered waters, and food availability (Frost and Lowry 1981, Reeves 1998). Shore-fast ice is considered to be the most important habitat for pupping, although the importance of pack ice is not well known (Reeves 1998).","The world-wide population of ringed seals is not known. Citing many factors such as vast geographic area occupied by the species, highly variable densities found within areas that have been surveyed, the unknown relationship between the numbers of seals observed versus those not seen, and other factors, Frost and Lowry (1981) state that it is “unwise to attempt an estimate of the world population of this subspecies” (P. h. hispida). Despite numerous surveys conducted since, Reeves (1998) believes that “this conclusion remains appropriate.” Nevertheless, published world-wide population estimates exist including 6-7 million (Stirling and Calvert 1979), and 2.5 million for the most widespread subspecies, P. h. hispida (Miyazaki 2002). The population of P. h. botnica is estimated at 5,000 to 8,000 (Reeves 1998), and in excess of 6,000 (Harkonen et al. 1998). P. h. ladogensis and P. h. saimensis have been estimated to number 10,500-12,500 (Reeves 1998) and about 5,000 (Sipila and Hyvarinen 1998) for the former, and <200 (Reeves 1998) or about 200 (Sipila and Hyvarinen 1998) for the latter.","Ringed seals are usually found singly or in small groups, and when inhabiting sea ice, can be difficult to find. They swim in leads among floes, and maintain breathing holes with their claws, excavate snow lairs, and utilize naturally occurring cracks and cavities within pressure ridges when seas freeze (Smith and Stirling 1975, Frost and Lowry 1981, Kelly 1988).Sexual maturity is usually attained between 4-7 years for females and 5-7 years for males. Physical maturity is reached between 8 and 10 years old. Maximum ages of 43 years (McLaren 1958), and 46 years (Reijnders et al. 1993) have been reported.A single pup, rarely twins, is born from March to May, with most pups born in early April (Frost and Lowry 1981). Most births occur in lairs excavated under snow that accumulates upwind and downwind of ice ridges (Smith and Stirling 1975), or in cavities occurring between blocks of ice in pressure ridges (Mclaren 1958, Kelly 1988). Lairs are believed to provide protection from a variety of predators and periods of very cold air temperatures and high wind chill (Smith and Stirling 1975, Kelly 1988). Ringed seals take a wide variety of fish and invertebrate prey and show variation in diet between seasons and in different geographic areas. The most important species and groups include Arctic cod (Boreogadus saida) and saffron cod (Eleginus navaga), and a variety of crustaceans including amphipods, euphausiids, mysids, and shrimps (Lowry et al. 1980, Kelly 1988). Saimaa and Ladoga ringed seals are confined to freshwater lakes where they prey on a wide variety of fish and some invertebrates, especially smelt (Osmerus eperlanus), vendace (Coregonus albula), burbot (Lota lota), perch (Perca fluviatalis), roach (Rutilus rutilus), and whitefish (Coreogonus lavaretus) (Sipila and Hyvarinen 1998).","Ringed seals are very important to northern communities, and many thousands are taken annually in subsistence harvests. Reeves (1998) reports an annual quota for shore-based hunters in the Sea of Okhotsk of 7,500, and a combined estimate of 10,000 taken per year from the Bering, Chukchi, and Western Beaufort Sea by Russians and native Americans. Reeves et al. (1998) estimate that the annual removal of ringed seals in the Canadian Arctic is in the “high tens of thousands” at present, and that in 1980s, including animals killed and lost, the harvest was between 60,000 and 80,000, and may have exceeded 100,000 in some years. Another substantial annual harvest occurs in Greenland with nearly 100,000 taken per year in the 1970s, and approximately 70,000 taken annually in the early 1990s (Teilmann and Kapel 1998). The species is not currently harvested in the marine region covered by the European Mammal Assessment.Commercial harvests of ringed seals in the early to mid 20th century were sometimes large, and probably had significant local impacts on certain populations. Annual harvests of 72,000 from 1955 to 1965 in the Sea of Okhotsk, 20,000 in the Baltic Sea (Reeves 1998), and commercial and reduction harvests in Lakes Ladoga and Saimaa (Sipila and Hyvarinen 1998) are examples of the negative effect of localized overharvesting on ringed seal populations.Ringed seals carry loads of organochlorine and heavy metal contaminants from human industry and agriculture. Chlorinated hydrocarbons have been implicated in uterine pathology in Baltic ringed seals (Bergman and Olsson 1986), and high concentrations of mercury in Saimaa ringed seals is thought to have reduced pup production in the 1960s and 1970s (Sipila and Hyvarinen 1998).Vessel traffic and noise, and the effect of noise from offshore oil and gas exploration or construction can affect ringed seals and cause mortality, abandonment of breathing holes and lairs, and a decrease in abundance near the activity (Smith 1987, Reeves 1998). Manipulation of water levels, recreational snow machine operation, net fishing, boating, tourism, and development of cottages on the shoreline at Lake Saimaa, and industrial pollution, net fishing and poaching on Lake Ladoga have been implicated in past or present mortalities, population impacts, or disturbance to their respective ringed seal populations (Reijnders et al. 1993, Sipila and Hyvarinen 1998). Global warming may pose the greatest threat to ringed seals if it leads to large losses of stable shore-fast ice habitat used for pupping and foraging (Tynan and DeMaster 1997). Also, changes in precipitation and weather patterns could negatively effect ringed seal populations if there is insufficient snow cover to protect pups in lairs in the spring (Stirling and Derocher 1993, Ferguson et al. 2005). Climate change could be particularly acute for ringed seals living in restricted habitats such as the Ladoga and Saimaa Lake populations (Learmonth et al. 2006), and possibly in the Okhotsk and Baltic seas. An increase in human created noise in the Arctic environment could cause marine mammals, including ringed seals, to abandon areas of habitat (Tynan and DeMaster 1997). Reductions in sea ice cover would likely lead to increased human activity in the Arctic in the form of shipping and extractive industries, and an associated greater threat of marine accidents and pollution discharge (Pagnan 2000). However, Moulton et al. (2005) found no more than slight effect on ringed seals from construction, drilling, and operation of the Northstar offshore island oil production facility in the Beaufort Sea.","Ringed seals are protected by numerous laws and quotas in different parts of their range. The population in Lake Saimaa has been protected since 1955, and additional protection has resulted from establishment of two national parks at the lake, and regulation of shoreline development. Similarly, the hunting of seals in Lake Ladoga was prohibited in 1980 (Sipila and Hyvarinen 1998). In the United States ringed seals can only be harvested for subsistence purposes by Alaskan Native Subsistence Hunters, and they have been protected by the Marine Mammal Protection Act of 1972, the implementation of which reduced annual mortality by eliminating all hunting by non-native people (Angliss and Outlaw 2005). Quotas and licensing of hunting have been in place in various parts of the Russian Federation/former Soviet Union for decades and have led to protection of Sea of Okhotsk, Barents and White seas, and Lake Ladoga ringed seals (Belikov and Boltunov 1998, Reeves 1998). Baltic ringed seals were protected from all killing by the Soviet Union in 1980, by Sweden in 1986, and by Finland in 1988 (Harkonen et al. 1998). State Nature Reserves at Franz Josef Land and in the White and Kara seas protect large areas of ringed seal habitat in the western Russian Arctic (Belikov and Boltunov 1998).",European Mammal Assessment team +ANIMALIA,CHORDATA,MAMMALIA,CARNIVORA,URSIDAE,Ursus arctos,,No,No,LC,,NT,,"European regional assessment: Least Concern (LC)EU 25 regional assessment: Near Threatened (NT)The European bear population (including western Russia) is relatively large (c.55,000 individuals) and occupies a large range. Overall, the population trend is believed to be stable. Consequently it is classed as Least Concern.In the EU 25 there are fewer than 10,000 mature bears. The species was formerly widespread and abundant, but it was driven extinct in much of western and central Europe over the last few centuries. Many remnant populations are tiny and fragmented. If ongoing conservation action ceased, it is expected that the species would decline at such a rate that it would meet Criterion C1 in the near future. Consequently it is assessed as Near Threatened. Continued protection is required to ensure the continuing recovery of this species.1. CantabrianThe two Cantabrian nuclei are assessed separately as there is apparently very little or no interchange between them (there are major barriers to dispersal, and the two nuclei are genetically distict). In both cases the population may number less than 50 mature individuals. Consequently these two nuclei are assessed as Critically Endangered (D).2. PyreneesThe population in the Pyrenees is tiny and isolated. Although it has increased in number in the last decade as a result of translocations from Slovenia, it remains highly vulnerable. Classed as Critically Endangered (D).3. AlpsThe population is tiny and qualifies as Critically Endangered under Criterion D.4. Appenine MountainsThe population is tiny and qualifies as Critically Endangered under Criterion D.5. Dinara-PindosThis population is small (<2,500 mature individuals). It has a structure such that each subpopulation contains fewer than 1,000 individuals. Population trends are poorly known, and although the population seems more or less stable, it is possible that there is a slight continuing decline. Consequently it is classed as Vulnerable (C2a(i)). The assessment is not adjusted because there is little interchange with other populations, and adjacent populations are also threatened. If better information shows that the overall trend is stable or increasing, reassessment should be considered.6. CarpathianThe population is small (<10,000 mature individuals), and all individuals are part of the same subpopulation. The population has been stable in the recent past, although there are concerns that it may be declining slightly at present as a result of infrastructure developments and other threats. Classed as Vulnerable (C2a(ii)).7. BalkanThis population is very small (<1,000 mature individuals) and qualifies as Vulnerable under Criterion D1.8. ScandinaviaThis population is small (potentially less than 2,500 mature individuals). Although there is controlled harvesting, the population is nevertheless growing at a steady and relatively rapid rate. Consequently, as there is no ongoing decline, this population cannot qualify as threatened under Criterion C, even though its population size is small. It is classed as Least Concern.9. Northeastern EuropeThis population is relatively large (c.38,000 individuals) and occupies a large range. Overall, the population trend is believed to be stable. Consequently it is classed as Least Concern.",Unfavourable,"The brown bear is the most widely distributed ursid. It once ranged across a large portion of North America, including Mexico, throughout Europe, Asia, and even into several countries in north Africa. It presently ranges across parts of North America, Europe, and Asia, with the largest numbers in Russia, Alaska, and Canada. Populations in Europe are highly fragmented, and some are extremely small and isolated. Details of the European populations are given below (following LCIE 2007):1. CantabrianPresently there are two bear nuclei in the Cantabrian Mountains in Spain. They are defined as the western and eastern portions.2. PyreneesWestern Pyrenees (9 bears): The Western Pyrenean brown bear subpopulation is found in a 1,000 km2 area located on both sides of the national border between France and Spain in the western portion of the Pyrenees Mountain Range. However, only about one half of this area is used regularly.Central Pyrenees (8 bears): The Central Pyrenean brown bear subpopulation is on both sides of the national border between France and Spain in the central portion of the Pyrenees Mountain Range including Andorra.3. AlpsPresently there are three bear nuclei in the Alps. In Central Austria there is a small nucleus originated from three bears released in 1989-1993, into an area with a naturally occurring male bear. Another nucleus is located in the Central Italian Alps, centered in the province of Trento. This nucleus (20-25 individuals, all originated from the animals translocated in the 1999-2003 period) occupies an area of about 1,500 km2, of which only 240 km2 is used regularly. A third nucleus of bears is present in the Eastern Alps, and originated from individuals that arrived naturally from the Slovenian population. Vagrants from the Dinara-Pindos population are frequently present in the Alps of Slovenia along the border with Austria.4. Appenine MountainsThe population is located in Abruzzo National Park and the surrounding area in the Apennine Mountains in Italy.5. Dinara-PindosThis population consists of brown bears in the forested areas extending from the Dinara range in Slovenia in the north through Pindos Mountains in Greece in the south. The countries involved are Slovenia, Croatia, Bosnia and Herzegovina, Serbia, Montenegro, FYR Macedonia, Albania, and Greece. The forested areas in these countries are less contiguous than in the Carpathian area, separating to some degree the functional habitat into more or less isolated sub areas, although there are corridors.6. CarpathianThe Carpathian population includes the brown bears in Slovakia, Poland, Ukraine, Serbia and Romania. The Carpathian Mountains population is the second largest in Europe. The bears are widely distributed within the entire Romanian Carpathian Mountains range, starting from hilly areas and extending to sub-alpine habitats. Bears in Romania occur permanently or sporadically across a total area of 62,000 square kilometers, of which about 44,000 square kilometers are forested.7. BalkanThe Rila-Rhodope area is located in south-western Bulgaria and north-eastern Greece. It includes the three connected populations in the Bulgarian Rila Mountains and Pirin Mountains and the population in the western Rhodope Mountains on both sides of the national border. Of the total population of about 520 bears, only 25-30 are found in Greece. The connection between the bears in Greece and Bulgaria is likely to consist of dispersing males from Bulgaria, as well as of family groups seasonally dispersing from Greece into Bulgaria. The Stara Planina population is located from Kotlenska mountain in the east to Zlatitsa-Teteven in the west, along a 120 km stretch of the Stara Planina Mountains (Balkan Range). The western end extends into Serbia and a few bears are shared over the border. The Stara Planina population was believed to be isolated from the populations to the south and west but there is recent evidence of bears in the corridors to the south towards Rila-Rhodopean Mountains, including family groups.8. ScandinaviaThe population is shared between Sweden and Norway, but much more than 95% of the individuals are in Sweden. In Norway the bears are found mostly along the Swedish border and most individuals are dispersing young males from Sweden. The delineation is along the Swedish-Finnish border, and further north through Norway. Bears in Norway east of this line are in Northeastern Europe population. The area between the Scandinavian and Northeastern Europe populations is very sparsely inhabited by bears.9. Northeastern EuropeThe North-eastern European population is the largest continuous brown bear population in Europe. Its range stretches from the Ural Mountains in the east (continuous with the bears on the east side of the mountains making it the largest brown bear population in the world) to the west coast of Finland and the Baltic. It ranges from 53° N in the south to 69° N in the north. This population includes bears in north-easternmost Norway, Finland, Estonia, Latvia and Belarus.","Brown bears originally occurred throughout Europe (except from the largest islands such as Ireland, Iceland, Gotland, Corsica and Sardinia), but later disappeared from most areas as the human population grew, suitable habitat was lost due to deforestation and agriculture, and the species was persecuted by humans. Today the total number of brown bears in Europe is about 55,000 bears (c. 15,000-20,000 outside Russia) which occur within an area of more than 2.5 million km² (800,000 km² outside Russia). These bears are found in two large (>5,000), three medium (500-2,500), one small (100-500), and six very small (<100) populations. 1. Cantabrian. The two Cantabrian populations apparently have been separated since the beginning of the century and now show genetic differences. Today, they are separated by 30-50 km of mountainous terrain and interchange between the populations is thought to be unlikely, mainly due to unsuitable habitat and a high speed railway and motorway. In the Western Cantabrian Mountains the population seems to be stable or increasing in the last decade and is distributed over an area of 2,600 km2. The most recent estimate using genetic methods (García-Garitagoitia et al. 2004) calculated 85-143 bears for the western nucleus, with an average number of 107. In the Eastern Cantabrian Mountains (20 bears) the population shows less potential for recovery, unless the corridor with the western portion is reestablished. The total population for both Cantabrian nuclei may be approximately 100-150 bears; not all of these are mature individuals. 2. PyreneesThe autochthonous western population was estimated to be 3 individuals. The last documented reproductions occurred in 1995 and 1998. In 2006 the reintroduction action provided 5 (4F, 1M) bears from Slovenia mostly to central area. The autochthonous central population was gone before the last decade of 20th century. In 1996-1997 three bears were reintroduced from Slovenia. There was subsequent reproduction, including one male dispersal to Western Pyrenees. Until recently the Western and Central Pyrenees were treated as separate units. With the dispersal of one male bear from the central to the west portion the connectivity is now reastablished. The local bears have been totally isolated for over one century and had low genetic diversity. The recent reintroductions have resulted in the influx of new genes.3. AlpsThe Central Austrian subpopulation now consists of about <10 bears. After increases following reintroductions and local reproductions, in recent years numbers have declined again. No more than 4 autochthonous bears survived in north-eastern Italy until 10 were reintroduced from Slovenia in 1999-2003. With subsequent reproduction the population has exceeded 20 bears, and continues to grow; in 2006 a population of about 6-7 adults and 16-17 sub-adults and cubs was recorded. At least three individuals from the Trentino nuclei dispersed into Austria, Switzerland and Germany. None of them became established, but this demonstrated the connectivity of the habitat within the Alps and the potential for recolonization. One bear was legally shot in Germany in July 2006 because of the potential threat it posed to human safety (the bear repeatedly entered villages and broke into barns), whereas the other two bears disappeared without leaving any tracks. Occasionally individuals dispersing from the Eastern Alpine nucleus have reached the Central Italian Alps, confirming a potential connectivity among all the alpine nuclei.4. Appenine MountainsAn estimate yielded a figure of 70-80 bears in 1985. However, since then there has probably been a population decrease and 40-50 bears may be a more realistic estimate. Some expect this population to increase as poaching has been reduced in recent years, and areas surrounding Abruzzo National Park have been protected to secure suitable habitats. However, this population exists within a densely human populated area and there are potential conflicts between bear conservation and development and recreation activities.5. Dinara-PindosThe population seems to be genetically very close to the remnant bears in the Alps. The population overall has been more or less stable in recent years. However, trends vary in different areas, with steady growth in Slovenia and Croatia, a marked drop in Bosnia and Herzegovina in the 1990s due to the war, and probably stable or slightly decreasing trends in the south of the Dinarids, whereas in Pindos range it is characterized as stable (150-200) with locally positive trends and recolonization of former range. The population size estimate of 2,800 is based on weak supporting evidence. Approximately half (1,400) of these individuals are mature. The population trend data is likewise based on little quantitative data and it is possible that the trend is declining rather than stable. In countries with bear hunting there might be a political tendency for overestimation to justify higher quotas. In Slovenia in the north this population is close to that of the Alps. There is not a continuous distribution of female bears in the Alps, but there is movement of male bears. In Greece in the south the nearest bears are those of the Rila-Rhodope portion of the Balkan population along the border of Greece and Bulgaria, but there is no evidence of connection.6. CarpathianThe Carpathian Mountains population is estimated at about 8,100 bears and is the second largest in Europe. The Slovakian and Polish bear population was recently reconnected with that of Ukraine. This range expansion occurred rapidly, about 200 km in less than 20 years. Recent estimates of the Romanian population indicate that in Romania about 6,000 bears occur, the population trend being stable. The highest bear densities are found in the areas of Brasov, Harghita, Covasna, Mures, Bistrita, Arges, Vrancea and Sibiu counties (central part of the Romanian Carpathians). During the last 50 years, the Romanian bear population recovered from less than 1,000 individuals to about 6,000 individuals. This recovery process was influenced by both habitat conditions and wildlife management. However, recent developments (e.g. infrastructure developments) have had negative impacts on bears. Problems include behavioral changes (habituated bears), habitat fragmentation and reproductive isolation. Several areas (corridor between Apuseni Mountains and the main ridge of Carpathians, Prahova Valley, southern part of Carpathians - close to Danube) have started to be affected by isolation processes, but there is still connectivity within the entire Romanian Carpathian population. Some dispersers from this population have entered the Czech Republic and Hungary. The next closest population is in northern Bulgaria and north-eastern Serbia, but the migration of individual bears may be very restricted, as the Danube is a major physical barrier.7. BalkanIt consists of two segments: Rila-Rhodope Mountains (520 bears) and Stara Planina Mountains (200 bears). Little is known about genetic structure. The connections between subpopulations were recently proven, and there may be signs of recolonisation. In the early eighties Carpathian bears were released in Rhodope and Stara Planina Mountains. The numbers are not known since there is restricted access to this data. 8. ScandinaviaAfter heavy persecution in both countries, the once numerous brown bear population in Scandinavia was reduced to about 130 individuals in four areas where they have survived since 1930. The population has increased to about 2,550 in Sweden, with approximately 50 bears in Norway. Male bears may disperse between neighbouring female core areas, but when considering demographic viability they should be considered separated. This population consists of three subpopulations. In Sweden, the distribution of bears now resembles that of 1800, with bears occurring in 67% or more of the country. The population is one of the most productive in the world and is increasing at a rate of about 5.5% annually. This population is viable, both genetically and demographically, but low gene flow has been identified between the southernmost subpopulation and the other subpopulations. The population is connected with the North-eastern European population through dispersing males, but probably not by dispersing females. 9. Northeastern EuropeDensities are generally low, with the highest densities in the south-eastern part of the range and the lowest densities in the north and southwest. The total population size occurring west of 35 degrees east is estimated at c. 38,000 individuals. This population is connected with the Scandinavian one.","The original distribution of the brown bear in Europe illustrates its adaptability to different environmental conditions. With little or no human interference, brown bears occupied not only forests, but also steppes and tundra. Today, most of the bear' s former range is no longer suitable habitat due to human habitat alteration and human presence. Components of habitat can be grouped into three main categories: food, escape cover, and den sites. Bear movements and habitat use are strongly affected by availability of food. Furthermore, population density is positively associated with food availability. Areas with a high availability of preferred foods, such as berries, fruits, hard mast, colonial Hymenoptera, and ungulates, are of special importance to brown bears.1. CantabrianThe Cantabrian population inhabits the Cantabrian Mountains, which are partly covered with mixed deciduous forest.2. PyreneesMixed forests and pastures, depending on slope and elevation. 3. AlpsHabitat is predominately Alpine with steep slopes covered mostly by conifers. Human settlements and infrastructure in the valleys contribute to habitat fragmentation. 4. Appenine MountainsMountain habitat in the central Appenines; partly covered by deciduous forest (dominated by beech). 5. Dinara-PindosThe landscape is mountainous, dominated by mixed beech and spruce forest.6. CarpathianThe habitat is mainly the mixed forests in the Carpathian Mountain range. 7. BalkanMostly mountains with deciduous secondary forests.8. ScandinaviaThe habitat is dominated by intensively exploited boreal forest. 9. Northeastern EuropeThe habitat is dominated by intensively exploited boreal forest.","Bears have a low reproductive rate and are vulnerable to human-related mortality. They require large habitats that make them vulnerable to changes in land use. In Eastern Europe, land use once under centralised state administration has reverted to private ownership, often with no knowledge of wildlife management. Land use developments have tended to follow western examples with more intensive use of productive areas. The best bear habitat has already disappeared in Europe through logging and forest clearance. The planting of exotic conifers has seriously altered local ecosystems in some places. Habitat fragmentation, particularly as a result of road construction, presents serious problems for a species requiring such large areas. Mortality caused by high-speed road and rail networks through bear habitat is a major threat in some areas including Greece and Croatia. Poaching remains a threat to many, but not all populations, and takes place irrespective of population size. Females with cubs, as well as males, are liable to be killed. Poaching has probably worsened in countries such as Bulgaria, Bosnia and Herzegovina, the Yugoslav Federation, and FYR Macedonia as a result of declining economic and social conditions. Poaching in Russia, to supply the lucrative market for bear parts in Asian countries, is a particular problem. Five very small, isolated bear populations in southern and western Europe (located in France, Spain and Italy), are highly threatened by their small population size. They could easily become extinct as a result of random fluctuations.1. CantabrianThe main pressure is the loss of adult individuals due to human induced mortality. 2. PyreneesThe main pressure is the loss of adult individuals due to killing by humans. 3. AlpsDamages done by bears have the potential to reduce the public acceptance of this species, and of trouble-making individuals in particular. Intensive management of all bear related problems is under way. Despite the constant increase of the Central Italian nucleus, the limited numbers of individuals characterizing all the alpine nuclei show that all these are Critically Endangered. The loss of more than 15 bears from the central Austrian bear population and 2 dispersers from Italy suggest an unnatural high mortality rate of bears in the Alps. Unfortunately, illegal removals seems to be the most likely explanation.4. Appenine MountainsThe main pressure is the loss of adult individuals due to human induced mortality. The population is critically endangered. The bear population has been totally isolated for over a century, thus there may be genetic problems.5. Dinara-PindosPolitical instability and the lack of financial instruments represent a pressure in the central part of the range. 6. CarpathianThe socio-economic developments in Romania have an influence on bear population on medium and long term and it is considered that the Romanian bear population is vulnerable. 7. BalkanPresently in Bulgaria there is liberal (poorly functioning) system of declaring the problem individuals assigned for removal, as well as poorly controlled poaching. 8. ScandinaviaThe major pressure in Norway is related to damages on unguarded free-ranging sheep. 9. Northeastern EuropeDue to a large total size and large area the population is in favorable conservation status.","Since 1992, all brown bear populations have been listed on either Appendix I or Appendix II of CITES. In the EU, all populations are listed in Annex A of the European Union Council Regulation (EC) No. 338/97, that implements CITES in the member states (Knapp 2006). The brown bear is included on Appendix II of the Bern Convention and Annex II* (except Finnish and Swedish populations) and Annex IV of the EU Habitats & Species Directive. Most European range states have national brown bear management plans. General conservation recommendations include the following: Key bear areas and corridors need to be sufficiently managed and protected. Farmers need to be encouraged to use traditional livestock guarding techniques to reduce conflict arising from livestock depredation. Public awareness and education is also needed to inform people in bear areas about bear behaviour and ecology. International and national legislation protecting bears from poaching should be enforced. More research into population dynamics, genetics and bear habitat is also required to carry out work in bear action plans.1. CantabrianThe Cantabrian population is strictly protected but occasional losses due to poaching or other human related accidents do occur (snares set by poachers for wild boars). 2. PyreneesIt is strictly protected but occasional losses due to poaching or other human related accidents do occur.3. AlpsThe Italian and Austrian bear nuclei are under strict protection; in Slovenia a regulated harvest policy is in place. The removal of the bear in Germany caused a great public outcry and quite a controversy between different national and international GOs and NGOs. Fortunately the case also raised awareness for the need of a bear management on the population level. Initiatives to coordinate and harmonize bear management between Italy, Switzerland, Austria and Germany are underway.4. Appenine MountainsIt is strictly protected but occasional losses due to poaching or other human related accidents do occur.5. Dinara-PindosIn the largest part of this population's range (Slovenia, Croatia, Bosnia and Herzegovina, Serbia and Macedonia) the bear is a game species. In Slovenia the brown bear is hunted under protected status. In Albania and Greece it is strictly protected. Additionally in Greece it is considered as a priority species under the EU Habitat Directive 92/43.6. CarpathianWhereas in Romania and Slovakia bears are a hunted species, in other countries they are harvested under various regimes, mostly related to the damage control system. Annually, in Romania up to 250 bears are hunted (about 4% of the estimated population). In 2005 a national bear management plan was approved by the authorities, its implementation being started by the Ministry of Environment and Water Management together with the Ministry of Agriculture, Forests and Rural Development. One of the first initiated actions was related to population surveys of larger areas (geographical criteria) and setting up hunting quotas based on the analysis at the national level. Compensation for damages caused by bears is paid by the game administrators, and it is foreseen that in areas where bears are not hunted these compensations will be paid by the Ministry of Environment and Water Management (the authority for protected species).7. BalkanBears in Bulgaria are under protected status that allows the removal of problem individuals. The Greek portion is strictly protected, as well as are the few specimens in Serbia.8. ScandinaviaThere is a quota hunting regime in Sweden. The harvest rate allows the further and steady population growth. In Norway only damage causing bears are removed, but such a reduction is technically sustainable only due to influx of individuals from Sweden.9. Northeastern EuropeBears are game animals in most of this population range under various quota systems.",Djuro Huber (Large Carnivore Initiative for Europe / Bear Specialist Group) +ANIMALIA,CHORDATA,MAMMALIA,CARNIVORA,URSIDAE,Ursus maritimus,"Phipps (1774) first described the polar bear as a distinct species and named it Ursus maritimus. Other names were suggested including Thalassarctos, Thalarctos and Thalatarctos ultimately settling on Ursus (Thalarctos) maritimus Erdbrink (1953) and Thenius (1953) based on interbreeding between brown bears (U. arctos) and polar bears in zoos. Based on the fossil record and evolution Kurtén (1964) recommended the Phipps (1774) name Ursus maritimus, which was promoted by Harrington (1966), Manning (1971) and Wilson (1976) and is used today (see DeMaster and Stirling 1988, Wilson and Reeder 2005, Amstrup 2003 for review and references).",No,No,VU,A3c,NE,,"European regional assessment: Vulnerable (VU)EU 25 regional assessment: Not Evaluated (NE)The polar bear qualifies as Vulnerable at the European regional level. This assessment is based on a suspected population reduction of >30% within three generations (45 years) due to decline in area of occupancy (AOO), extent of occurrence (EOO) and habitat quality. Polar bears rely almost entirely on the marine sea ice environment for their survival so that large scale changes in their habitat will impact the population (Derocher et al. 2004). Global climate change posses a substantial threat to the habitat of polar bears. Recent modeling of the trends for sea ice extent, thickness and timing of coverage predicts dramatic reductions in sea ice coverage over the next 50-100 years (Hassol 2004). Sea ice has declined considerably over the past half century. Additional declines of roughly 10-50% of annual sea ice are predicted by 2100. The summer sea ice is projected to decrease by 50-100% during the same period. In addition the quality of the remaining ice will decline. This change may also have a negative effect on the population size (Derocher et al. 2004). The effects of sea ice change are likely to show large differences and variability by geographic location and periods of time, although the long term trends clearly reveal substantial global reductions of the extent of ice coverage in the Arctic and the annual time frames when ice is present. The winter ice over the continental shelf in the European Arctic will probably disappear completely over the next 100 years (Furevik et al. 2002).While all bear species have shown adaptability in coping with their surroundings and environment, polar bears are highly specialized for life in the Arctic marine environment. Polar bears exhibit low reproductive rates with long generational spans. These factors make facultative adaptation by polar bears to significantly reduced ice coverage scenarios unlikely. Polar Bears did adapt to warmer climate periods of the past. Due to their long generation time and the current greater speed of global warming, it seems unlikely that polar bears will be able to adapt to the current warming trend in the Arctic. If climatic trends continue polar bears may become extirpated from most of their range within 100 years. There is little doubt that polar bears in the European Arctic will have a lesser AOO, EOO and habitat quality in the future. However, no direct relation exists between these measures and the abundance of Polar Bears. While some have speculated that polar bears might become extinct within 100 years from now, which would indicate a population decrease of >50% in 45 years based on a precautionary approach due to data uncertainty. A more realistic evaluation of the risk involved in the assessment makes it fair to suspect population reduction of >30%. Other population stress factors that may also operate to impact recruitment or survival include toxic contaminants, shipping, recreational viewing, and oil and gas exploration and development.",-,"Polar bears live throughout the ice-covered waters of the circumpolar Arctic, in Canada (Manitoba, Newfoundland, Labrador, Nunavut, Northwest Territories, Quebec, Yukon Territory, Ontario), Greenland (to Denmark), Norway, Russian Federation (North European Russia, Siberia, Chukotka), and the United States (Alaska). Some vagrants occasionally reach Iceland. Their range is limited by the southern extent of sea ice. Although some occur in the permanent multi-year pack ice of the central Arctic basin, they are most common in the annual ice over the continental shelf and inter-island archipelagos that surround the polar basin. Polar bears that have continuous access to sea ice are able to hunt throughout the year. However, in those areas where the sea ice melts completely each summer, polar bears are forced to spend several months on land fasting on stored fat reserves until freeze-up. Use of land by polar bears during the ice-free season appears to be increasing in certain locations (Schliebe et al. 2006). Polar bears typically occur at low altitudes (on the sea ice and up to ca. 200 m in coastal areas), although exceptionally they may range far inland, and have been recorded at altitudes of 1,000 m above sea level in Svalbard (O. Wiig and A. Derocher pers. comm. 2006).","There are 19 hypothesized subpopulations or stocks which number in total 20,000 to 25,000 bears. Considerable overlap of putative subpopulations occurs and genetic differences among them are small (Schliebe et al. 2006). In Europe, the Barents sea subpopulation (Norway and the Russian Federation) is estimated at ca. 3,000 individuals (Aars et al. in press).","Polar bears occur at low densities throughout their range and are most abundant in shallow water areas near shore or where currents or upwellings increase biological productivity near ice areas associated with open water, polynyas or lead systems. Polar bears are not as abundant in the high central arctic over deeper waters of the polar basin. Seasonally, in the summer open water season in the Canadian arctic islands and Svalbard, and in recent years during the fall in northern Alaska and Russian Chukotka, polar bears may be found on land in higher densities. Breeding occurs in March to May, implantation is delayed until autumn, and birth is generally thought to occur from late November to mid-January. Although some cubs are born in earth dens, most births occur in snow dens that may be occupied between 5-6 months during the maternal event. In Alaska the maternal dens are located on the offshore sea ice. Only pregnant female polar bears den for this protracted period of time, during which time they rely on fat stores for energy and sustenance. The average litter size is less than two. Cubs are dependent upon mothers until after the start of their third year of life. Age of first reproduction is normally 5-6 years for females. These factors contribute to the low reproductive potential for the species (Schliebe et al. 2006).","The Intergovernmental Panel on Climate Change and the Arctic Climate Impact Assessment have both predicted that the Arctic is extremely vulnerable to projected climate change. Polar bears will likely be shifted pole-ward if the sea ice retreats. According to new scenarios presented by the Nansen Environmental and Remote Sensing Centre and others, the polar ice cap will disappear almost entirely during summer in the next 100 years. The winter ice over the continental shelf in the European Arctic will probably also disappear (Furevik et al. 2002). The increasing changes in the sea ice that affect access to prey will have a negative effect on the bears. With less food, polar bears will fail to reproduce more often and give birth to smaller young that have higher mortality rates. Polar bears may be forced on shore for extended periods and rely on fat reserves deposited the previous spring for survival. In such a situation they will be increasingly vulnerable to unregulated hunting. If these periods become excessively long, mortality will increase. Sea ice is also used for access to den areas and if ice patterns change, existing den areas may be unreachable. Warmer temperatures and higher winds may reduce ice thickness and increase ice drift. Because polar bears must walk against the moving ice (like walking the wrong way on an escalator) increased ice movements will increase energy use and reduce growth and reproduction (Schliebe et al. 2006). Polar bears are the apex predator and are exposed to high levels of pollutants that are magnified with each step higher in the food web. A key characteristic of the pollutants is that they tend to persist in the environment and resist degradation. Many of the organochlorine pollutants are lipophilic or ""fat loving"" and bond tightly to fat molecules. Polar bears are particularly vulnerable to organochlorines because they eat a fat rich diet. Ringed, bearded, and harp seals comprise the main food of polar bears and the blubber layer is preferentially eaten by the bears and subsequently, the intake of pollutants is high (Schliebe et al. 2006). Certain areas of the Arctic, such as north-east Greenland, the Barents Sea and the Kara Sea, have higher levels of pollutants. Based on studies in other species, it is reasonable to believe that the pollutant load of polar bears in some areas are negatively affecting the immune system, hormone regulation, growth patterns, reproduction, and survival rates of polar bears (Derocher et al. 2002). Recent studies have suggested that the immune system is weaker in polar bears with higher levels of PCBs. A major concern with polar bears pertains to their reproductive system. There are suggestions that species with delayed implantation are more vulnerable to the effects of pollution through endocrine (hormone) disruption. Further, female polar bears are food deprived during gestation their pollution loads increase because as they use their fat stores, where pollutants are stored, for energy. Because the cubs are nursed on fat rich milk, the cubs are exposed to very high pollution loads from their mother (Schliebe et al. 2006). Recent studies have indicated that high loads of organochlorines may cause reduction in the size of sexual organs of polar bears in certain areas, thus theoretically impairing reproduction (Sonne et al. 2006).Oil development in the Arctic poses a wide range of threats to polar bears ranging from oil spills to increased human-bear interactions (Derocher et al. 2002). It is probable that an oil spill in sea ice habitat would result in oil being concentrated in leads and between ice floes resulting in both polar bears and their main prey (ringed and bearded seals) being directly exposed to oil. Another concern is that seals covered in oil may be a major source of oil to polar bears. Other studies suggest that Polar Bears are sensitive to disturbance at maternity den sites. Disturbance could occur both when a pregnant female is selecting a den site and during the winter-spring after the cubs are born. If exploration or development occurred sufficiently close to a den, the mother may abandon the den prematurely or abandon her offspring (Schliebe et al. 2006).","Conservation actions vary by jurisdiction. The International Agreement on the Conservation of Polar Bears provides guidance, and Article II of the Agreement states that each contracting party ""shall manage polar bear populations in accordance with sound conservation practices based on the best available scientific information,"" and according to Article VII, ""The Contracting Parties shall conduct national research programs on Polar Bears"" and ""..consult with each other on the management of migrating polar bear populations"". These articles have been important for stimulating governments to support applied research to answer management questions regarding polar bears throughout their range. This work is coordinated through the IUCN SSC Polar Bear Specialist Group (PBSG). Resolutions from the PBSG are developed and directed toward ensuring that the terms and intentions of the Agreement are being met. Coordinated research is ongoing, management actions are reviewed for consistency, and legislation to effect bilateral management for internationally shared populations such as between the US-Russia is being pursued. Additional cooperative management agreements between Canada and Greenland are desirable and currently being developed (Schliebe et al. 2006). Additional details of the Global Status and Management of Polar Bears are contained in the IUCN ""Status Survey and Conservation Action Plan: Bears"" (Servheen et al. 1999) and at the PBSG website (http://pbsg.npolar.no/). The polar bear is listed on Appendix II of the Bern Convention, and Appendix II of CITES.","Wiig, Ø., Aars, J., Belikov, S.E. and Boltunov, A." +ANIMALIA,CHORDATA,MAMMALIA,CARNIVORA,VIVERRIDAE,Genetta genetta,"There is a high degree of intraspecific variation in this species, which has resulted in many described subspecies; the validity of many of these is unknown, while others may actually represent distinct species (Gaubert et al. 2004, 2005).",No,No,LC,,LC,,"European regional assessment: Least Concern (LC)EU 25 regional assessment: Least Concern (LC)The species was introduced to Europe before 1500, and thus it is considered as part of the naturalised regional fauna for the purposes of this assessment. The genet has a fairly large European range, including a number of protected areas, and the population trend is stable. Consequently it is classed as Least Concern.",Possibly Favourable,"A widespread species, occurring on the northern Saharan fringe (Morocco, Algeria, Tunisia and Libya), and then in open and dry savannah zones throughout Sub-Saharan Africa in three large blocks, corresponding roughly to West Africa, East Africa and southern Africa (Delibes and Gaubert in press). For Europe, Delibes (1999) lists this species as occurring in all of continental Portugal and Spain, and much of France (mainly south of Loire River and west of the Rhone River). It is also found on the Mediterranean islands of Majora, Ibiza, and Cabrera (Balearic Islands) (Delibes 1999). There are also scattered records from Belgium, Switzerland, Germany, and northwest Italy (Delibes 1999). This species is generally considered to have been introduced to Europe; the date of introduction is unknown, but remains have been found dating from the Middle Ages (Dobson 1998, Delibes 1999). It has been recorded to at least 3,000m asl in the Ethiopian Highlands (Admasu et al. 2004).","One of the most common small carnivores in its native range, though detailed data on density in Africa are scarce; in Serengeti, Waser (1980) estimated a density of 1.5 + 0.37 individuals per km2. In Europe, this species is moderately abundant, with increasing populations in France, and densities of 0.3 to 0.7 individuals per km2 in Spain (Delibes 1999). The genet is common in suitable habitat throughout the Iberian peninsula (Palomo and Gisbert 2002). Populations are either stable or slowly increasing (J. Herrero pers. comm. 2006). On Ibiza, habitat is declining and becoming more fragmented, thus this species is suspected to be declining.","The genet tends to prefer all types of wooded habitats (deciduous and evergreen), where it is often associated with rivers and brooks, but it is a generalist and can be found in other habitats where there is suitable prey. It avoids open habitats, but may occur even in small fragments of woodland in farmland or near villages, and usually is absent from rainforests, dense woodlands and woodland-moist savannah mosaics (e.g. miombo woodland in Angola) (Delibes and Gaubert in press). The common genet is not uncommonly found in proximity to people and human buildings (e.g. Admasu et al. 2004). It feeds mainly on small mammals, but will also take birds, other small vertebrates, insects, and fruit (Delibes and Gaubert in press).","There are no major threats. They are occasionally eaten by people in some localities, and body parts are used for medicinal purposes while skins may be used for the manufacture of karosses in southern Africa (Delibes and Gaubert in press). In Europe, the genet used to be trapped for its fur (Delibes 1999). In Portugal genets are illegally killed in predator trapping for hunting management. On Ibiza, the genet is threatened by the loss and fragmentation of habitat caused by urbanization and infrastructure and tourism development. The ability of genets to live close to humans and their domestic animals could have implications for disease transmission (Admasu et al. 2004).","It is present in many protected areas across its range. This species is listed on Appendix III of the Bern Convention, as well as EU Habitats and Species Directive, Annex V (Delibes 1999). In Ibiza, it is recommended that semi-natural habitats are protected, and that development takes place in such a way that fragmentation of remaining habitat is minimized.","Juan Herrero, Paolo Cavallini" +ANIMALIA,CHORDATA,MAMMALIA,CETARTIODACTYLA,BALAENIDAE,Balaena mysticetus,"The taxonomy is not in doubt. There are five traditionally recognised geographical populations. The species was once commonly known in the North Atlantic and adjacent Arctic as the Greenland right whale. However, the common name bowhead whale is now used almost exclusively for the species.",No,No,NA,,NA,,This species is assessed as Not Applicable as it is of marginal occurrence in the European Mammal Assessment region.,-,"Bowhead whales are found only in Arctic and subarctic regions. They spend much of their lives in and near the pack ice, migrating to the high arctic in summer, and retreating southward in winter with the advancing ice edge (Moore and Reeves 1993). The IWC recognises five stocks: Bering-Chukchi-Beaufort Sea; Hudson Bay-Fox Basin; Davis Strait-Baffin Bay; Spitsbergen; and the Okhotsk Sea (Rugh et al. 2003). The Spitsbergen stock extends from the east coast of Greenland across the Greenland Sea, the Barents Sea and the Kara Sea as far as Severnaya Zemlya, and going as far south as the ice front, exceptionally reaching Iceland and the coast of Finnmark (Norway).","Current population sizeThe range-wide abundance is not known with precision but numbers over 10,000 individuals, with 10,500 (8,200-13,500) (in 2001) in the Bering-Chukchi-Beaufort Seas (Zeh and Punt 2005), and a provisional estimate of 7,300 (3,100-16,900) for a part of the range of the Hudson Bay-Foxe Basin and Baffin Bay-Davis Strait stocks (Cosens et al. 2006). There are no reliable abundance estimates for the small Okhotsk Sea and Spitsbergen stocks.Population trendsThe Bering-Chukchi-Beaufort (BCB) population has been monitored for more than 30 years and has been increasing over this period at an estimated rate of 3.4% (1.7%-5%) per year in the presence of subsistence hunting (Zeh and Punt 2005). No quantitative estimates of trends in the other bowhead populations are available, but Inuit hunters and elders report that they are observing more bowheads in the eastern Canadian Arctic than they did in the 1960s-1970s, and that the geographic distribution of the whales has expanded in recent years. No estimates of population trend are available for the Svalbard-Barents Sea and Okhotsk Sea stocks.Pre-whaling population sizesAll bowhead populations were severely depleted by commercial whaling, which was established in the north-eastern Atlantic by 1611 (Ross 1993). Basque whalers took bowheads in the north-west Atlantic (Labrador) in the 16th century, but ambiguities over the species identity of whales taken in early commercial whaling make pre-1600 catch records difficult to interpret. Minimum pre-whaling stock sizes are estimated to have been 24,000 for the Svalbard-Barents Sea stock, 12,000 for the Hudson Bay-Foxe Basin and Baffin Bay-Davis Strait stocks, and 3,000 for the Okhotsk Sea stock (Woodby and Botkin 1993). The Spitsbergen and Okhotsk Sea stocks are at a small fraction of their pre-whaling levels.Demographic parametersA high longevity (>100 years) is suggested by biochemical methods and the finding of old-fashioned stone harpoon heads in harvested animals (George et al. 1999). If this high longevity is confirmed, it would be among the longest known for a mammal.","The seasonal distribution is strongly influenced by pack ice (Moore and Reeves 1993). During the winter they occur in areas near the ice edge, in polynyas, and in areas of unconsolidated pack ice. During the spring these whales use leads and cracks in the ice to penetrate areas that were inaccessible during the winter due to heavy ice coverage. During the summer and autumn they concentrate in areas where zooplankton production is high or where large-scale biophysical processes create local concentrations of calanoid copepods (Finley 1990, Finley et al. 1998). Small to medium-sized crustaceans, especially krill and copepods, form the bulk of the bowhead's diet (Lowry et al. 2004). They also feed on mysids and gammarid amphipods, and the diet includes at least 60 species. Bowheads skim feed at the surface and feed in the water column. It has recently been suggested that they also feed near the bottom, but probably do not directly ingest sediments as gray whales routinely do. During surface skim feeding, coordinated group patterns have been observed, including whales feeding in echelon (V-shaped) formation.","Heavy commercial hunting, beginning in the 1500s, depleted all populations of bowheads. The Bering-Chukchi-Beaufort Sea stock has recovered substantially since the end of commercial hunting in the early 20th century to around 10,000 animals, while recent provisional estimates of the Hudson Bay-Foxe Basin and Baffin Bay-Davis Strait stocks suggest that a significant recovery has probably occurred. There is no reliable evidence of recovery of the Svalbard-Barents Sea and Okhotsk Sea stocks. Limited aboriginal subsistence whaling on the BCB stock (by native peoples of Alaska and Chukotka) is permitted by the IWC on the basis of advice from its Scientific Committee (most recently under its new aboriginal subsistence whaling management procedure). These takes have not impeded the recovery of the stock. Very small takes by indigenous hunters are allowed in Canadian waters, so far too few to seriously impede recovery of the stocks, but there will be pressure to increase these takes given the recent, higher population estimates for the eastern Canadian Arctic. There has been concern since the 1970s that disturbance from oil and gas exploration and extraction activities in the Arctic region might affect bowhead whales. There is also evidence of incidental mortality and serious injury caused by entanglement in fishing gear and ship strikes (Philo et al. 1992, 1993; Finley 2000). Environmental threats, such as pollution (Bratton et al. 1993), and disturbance from tourist traffic (Finley 2000) may affect bowhead whales but the impacts have not yet been well characterized or quantified. During this century, a profound reduction in the extent of sea ice in the Arctic is expected, and possibly a complete disappearance in summer, as mean Arctic temperatures rise faster than the global average (Anonymous 2005). The implications of this for bowhead whales are unclear but warrant monitoring.",The International Whaling Commission has protected bowhead whales from commercial whaling since its inception in 1946. All range states except Canada are members of the IWC. Limited aboriginal subsistence whaling is allowed by the IWC on bowhead whales from the BCB stock on the basis of scientific advice. Indigenous hunting in Canada is co-managed by the national government and regional bodies created under land-claim agreements.,Species account by IUCN SSC Cetacean Specialist Group; regional assessment by European Mammal Assessment team +ANIMALIA,CHORDATA,MAMMALIA,CETARTIODACTYLA,BALAENIDAE,Eubalaena glacialis,"The taxonomy follows the view of the IWC Scientific Committee which now recognises right whales in the North Atlantic, North Pacific and Southern Hemisphere as three distinct species in the genus Eubalaena, namely E. glacialis (North Atlantic right whale), E. japonica (North Pacific right whale) and E. australis (southern right whale) (IWC 2004), based mainly on the findings of Rosenbaum et al. (2000).The North Atlantic right whale was included in previous Red Lists together with North Pacific right whales under the common species name E. glacialis (Baillie and Groombridge 1996).Rice (1998) classifies right whales in the North Atlantic, North Pacific and Southern Hemisphere as the single species Balaena glacialis, in the genus Balaena along with B. mysticetus, the bowhead whale. While not all cetologists accept that the three right whale taxa qualify as full species, their clear geographical separation ensures that no practical problem arises from treating them as distinct species.The species was formerly known as the black right whale to distinguish it from the Greenland right whale, Balaena mysticetus, which is now called the bowhead whale. The term “right whale” is acceptable for specimens of any of three Eubalaena species, when the species in question is implicit from the geographical context.",No,No,CR,D,CR,D,The eastern North Atlantic population is clearly extremely small (fewer than 50 mature individuals) (IWC 2001a); it is classified as Critically Endangered (CR).,Unfavourable,"The right whale in the past was common on both sides of the North Atlantic. It appears to be effectively extinct in the eastern North Atlantic, but in the past probably ranged from a calving ground in the Golfo de Cintra (23°N) off the western Sahara, through the Azores, Bay of Biscay, western British Isles, and the Norwegian Sea to the North Cape (hence the Dutch name Noordkaper). In the western North Atlantic the species migrates from a calving ground off Florida and Georgia along the eastern seaboard of North America, to summering grounds in the Gulf of Maine, Bay of Fundy, and Scotian Shelf, with some individuals reaching the Gulf of St Lawrence, the Davis and Denmark Straits and occasionally Iceland and Norway. It is unclear whether in the past the animals in the northern part of the range (off Iceland and Norway) belonged mainly to the western or eastern breeding stocks.","Northwest AtlanticHistoricIt is not clear when Basque whaling began in the northwestern North Atlantic, but it had been established by no later than 1530. An estimated 25,000-40,000 right whales were taken off Labrador and Newfoundland between 1530 and 1610 (Aguilar 1986) although recent genetic data have suggested that many of these were bowheads (Reeves 2001, Rastogi et al. 2004). Shore-based whaling along the US east coast began in the mid 17th century, with an estimated 2,000-3,800 taken during 1696-1734. Whaling continued sporadically over the next two centuries, with a few hundred taken in total until the last catch in 1935 (Reeves et al. 1999).CurrentThe current population is of about 300–350 individuals off the east coast of North America. IWC (2001a) obtained a minimum estimate of 263 in 1996 from identified animals known to be alive at that time, and indicated that the true population is probably not much higher. Kraus et al. (2001) provided a minimum estimate of 299 in 1998 based on animals presumed to be alive at that time (and not missing for more than 5 years). Preliminary analysis of more recent data have yielded estimates similar to those above. The whales are regularly surveyed in the winter calving ground off Florida and Georgia, and in spring/summer feeding grounds in Cape Cod Bay, the Great South Channel off Massachusetts, the Gulf of Maine, the Scotian Shelf, and the Bay of Fundy, but not all the whales using the wintering ground are seen in these major summering areas (IWC 2001a). There have been a few sightings in recent years in the Gulf of St Lawrence, two off Iceland in 2003, and one in the former whaling ground off Cape Farewell in 2004 (IWC 2005). A sighting off Norway in 1999 was identified as a well-known animal from the western North Atlantic population (IWC 2001a). Northeast Atlantic HistoricThe first records of Basque whaling in the Bay of Biscay are from the 11th century. At least dozens of whales were taken each year in the Bay of Biscay until a marked decline was evident by 1650; whaling continued there until the 18th century. Basque whalers arrived in Iceland as early as 1412, and participated in the right whale fishery around the British Isles and Norway from the 14th to the 18th century, but probably many more whales were taken by Dutch, Danish, British and Norwegian whalers. Quantitative estimates of catches are not available. Historic right whale catches as far north as Iceland and Norway appear to have been mainly E. glacialis, with Balaena mysticetus (bowhead) being the main species only in the far north (Greenland and Svalbard) (Aguilar 1986). Smith et al. (2006) document extensive whaling for E. glacialis in the North Cape area (northern Norway) in the 17th century. Right whaling seems to have declined from the mid-17th century and disappeared by the mid-18th century, but there was a brief period of right whale catches by modern whalers operating from shore stations in the British Isles and off Iceland, where at least 120 right whales were taken during 1881-1924 (Collett 1909, Brown 1986). The last recorded catch was a cow-calf pair off Madeira in 1967, accompanied by a third individual which escaped.CurrentIt is not clear whether there is a remnant Northeast Atlantic population or whether the animals seen here in modern times are strays from the west. There have been only eight confirmed sightings from 1960 to 1999, including the animal sighted in Norway in 1999 which was matched with the western north Atlantic population (IWC 2001a). A possible right whale was sighted in the Bay of Biscay in 1977 (Aguilar 1981) and a cow-calf pair was sighted off Cape Vincent, Portugal in 1995 (Martin and Walker 1997). A recent survey of the former Cintra Bay calving ground off the Western Sahara failed to locate any right whales (Notarbartolo di Sciara et al. 1998), although survey conditions were often poor.","Right whales are often encountered as singles or pairs, with larger groups or aggregations observed socializing, mating or feeding. They can be aerially active and generally raise their flukes before a deep dive. Right whales can be individually identified by the patterns of callosities on the head, as well as by scars (Kraus et al. 1986). The mating system appears to involve sperm competition (males competing to inseminate females, not so much by physical aggression, as by delivering large loads of sperm, thereby displacing that of other males). Young are born in winter and spring in calving areas in low temperate or subtropical latitudes.Right whales feed on calanoid copepods and other small invertebrates (smaller copepods, krill, pteropods, and larval barnacles), generally by slowly skimming through patches of concentrated prey at or below the surface. The most common prey species is the copepod Calanus finmarchicus.","Right whales in the North Atlantic are no longer hunted, and the most serious current threats are deaths and injuries from entanglements in fishing gear and collisions with ships off the eastern coast of North America (Knowlton and Kraus 2001). During 1999-2003, the recorded human-caused mortality and serious injury averaged 2.6 animals per year, of which 1.6 per year were fishery entanglements and 1.0 vessel collisions. A further 11 deaths (8 ship strikes, 1 entanglement and two of unknown cause) were reported between 2004 and the end of 2006. Based on scarring from fishing gear it is estimated that at least 72% of the right whale population had been involved in an entanglement event at some point in their lives, and that 10-30% of the population are entangled each year (Clapham 2005). Because some anthropogenic mortalities probably pass undetected, reported rates are likely minima.Hypotheses that have been advanced to explain the low reproductive rates observed for several years include: genetic factors, poor nutrition, chemical contaminants, biotoxins, disease (IWC 2001b, Reeves et al. 2001). However, reproduction in recent years has increased; whether this rate will continue is unknown.","The right whale has been protected from hunting by the IWC and its predecessor since 1935, and is also protected in Canada, a non-member of the IWC. Efforts are underway in both the US and Canada aimed at limiting deaths and injuries due to ship strikes and entanglements. In both countries, recovery plans have been developed involving collaboration between the various stakeholders. Regulations are in place in the US requiring modifications to fishing gear and restrictions on certain types of such gear in areas and times where right whales are common (Clapham 2005). A Mandatory Ship Reporting Scheme has been in place since 1999 in two areas in the right whale calving and summering grounds to enable vessels to be warned of right whales in the area. Regulations specify minimum approach distances for whale-watching and other vessels. Shipping lanes in the Bay of Fundy have been moved, with the approval of the International Maritime Organization (IMO), to take them away from the major summer concentrations of right whales. A regulatory proposal to enforce maximum transit speeds on vessels passing through right whale habitats off the US east coast was still under review in 2007.There is as yet no indication of a decrease in the rate of anthropogenic mortalities, hence it is unclear whether the measures taken to date are sufficient.",Species account by IUCN SSC Cetacean Specialist Group; regional assessment by European Mammal Assessment team +ANIMALIA,CHORDATA,MAMMALIA,CETARTIODACTYLA,BALAENOPTERIDAE,Balaenoptera acutorostrata,"Until the 1990s, only one species of minke whale was recognised, the Antarctic minke whale B. bonaerensis being regarded as conspecific with B. acutorostrata. Most of the scientific literature prior to the late 1990s uses the name B. acutorostrata for all minke whales including Antarctic minke whales. Since 2000, the International Whaling Commission (IWC) Scientific Committee (SC) recognizes Antarctic minke whales as the separate species B. bonaerensis, and provisionally groups all Northern Hemisphere minke whales and all Southern Hemisphere “dwarf” minke whales under the single species B. acutorostrata (IWC 2001). This has been followed by management agencies, such as CITES. B. acutorostrata is known as the dwarf minke whale in the Southern Hemisphere. It was described there by Best (1985) and Arnold et al. (1987) in terms of its differences from the Antarctic minke whale, which was regarded as the “ordinary” minke whale. Subsequent genetic analyses (Wada 1991, Pastene et al. 1994) revealed that the dwarf minke whale is closely related to the “ordinary” minke whale of the Northern Hemisphere, while the Antarctic minke whale is a separate species.",No,No,LC,,LC,,"The Northeast Atlantic stock is estimated to number c.80,000 individuals, well above the thresholds for a threatened category. There is no indication that the population has declined to an extent that would qualify for a threatened category. Consequently this species is assessed as Least Concern at the European regional level.",Unknown,"The common minke whale is a cosmopolitan species found in all oceans and in virtually all latitudes, from 65°S to 80°N. In parts of its range it is very abundant, in other parts much less so. Its migration patterns are poorly known. It occurs in the North Atlantic, North Pacific, and the Southern Hemisphere, but is not known in the northern Indian Ocean.North AtlanticIn summer, minke whales are common throughout the northern North Atlantic as far north as Baffin Bay, Greenland Sea, Svalbard, Franz Josef Land and Novaya Zemlya, and as far south as 40°N (New Jersey) on the US east coast (Anon. 2005), and as far south as the Hebrides (northwest British Isles) and the central North Sea in the east. In mid-Atlantic the southern limit of summer abundance is at least as far south as 50°N (Sigurjónsson et al. 1991). It is likely that at least a part of the minke whale population overwinters in the summer range, but there has been very little observation effort in winter to confirm this.Minke whales also occur south of this range in the southeastern North Atlantic, but with no obvious seasonality, and are not common, with the exception of the Canary Islands, where they appear to be frequent year-round (van Waerebeek et al. 1999). There have been occasional sightings (Aguilar et al. 1983) and strandings (van Waerebeek et al. 1999) off Spain and Portugal, Western Sahara, Mauritania and Senegal. Minke whales are rare in the Azores and not recorded from Madeira. The minke whale is considered a “visitor species” in the Mediterranean (average <1 record per year) with one vagrant recorded in the Black Sea (Reeves and Notabartolo di Sciara 2006). There are very few winter records, but a summary by Mitchell (1991) indicates that they do occur in winter near Bermuda, the Bahamas and the Antilles, and the US coast south of 40°N. Ten strandings have been recorded in the Gulf of Mexico (Jefferson and Schiro 1997) but hardly any live sightings. A Norwegian winter expedition sent to the tropical Atlantic in 1989/90 to “find the breeding grounds of the minke whale” encountered just two minke whales, at 20°N and 10°N off West Africa in December (Folklow and Blix 1991).","North AtlanticThe IWC recognizes four stocks of minke whales in the North Atlantic: Northeast Atlantic, Central North Atlantic, West Greenland, and Canadian East Coast. The latter includes the US east coast. Population estimates were last reviewed by the IWC SC in 2003 (IWC 2004), but a new estimate for West Greenland was accepted in 2006 (IWC 2007). The best/most recent available estimates for the whole North Atlantic total about 182,000, and the Northeast Atlantic stock was estimated at c.80,000 individuals.Minke whales have been exploited in the North Atlantic, mainly since the 1940s, and recorded catches total about 140,000 (IWC 2006). The largest catches have been by Norwegian “small-type” whalers who have taken about 120,000 since 1948, mainly in the Northeast Atlantic. Annual catches peaked at over 4,000 in the late 1950s, declining to about 2,000 annually in the early 1980s. Catches were phased out from 1984 to 1987. Commercial minke whaling resumed in 1993 at a lower level and continues to the present. About 4,000 minke whales were taken off Iceland during 1941-85, but recent abundance estimates imply that this would have had no discernible effect on the population. About 8,000 common minke whales have been caught by small-type whaling off West Greenland, mainly since 1960. The present catch limits (up to 175 annually for the years 2003-7) were set by the IWC in the absence of advice from its Scientific Committee. Some concerns have been expressed by the IWC Scientific Committee over the sustainability of the catch levels given the uncertainty over the size of the population available to the hunters off West Greenland (IWC 2007) although sex ratio information suggests that the population may not have been significantly impacted by the catches (Witting 2006).Generation timeNo satisfactory method of age determination has been developed for this species to date. Therefore the value of Taylor et al. (2007) was used. Unlike Antarctic minke whales, common minke whales tend not to develop ear plugs with readable layering (Lockyer 1984). A method based on layer counts in tympanic bullae (Christensen 1981) could not be reproduced by later workers. Other aging methods are being researched, but none is yet at the stage where it can be reliably applied to this species (Olsen and Øien 2002).","The common minke whale occurs in both coastal and offshore waters and exploits a variety of prey species in different areas according to availability. In the Northern Hemisphere some populations migrate to higher latitudes in summer, but it is also found year-round in some areas. With the exception of the Sea of Japan – Yellow Sea- East China Sea population, conception and birth occur in winter. Most animals occur singly, and few in groups of more than two. In the North Atlantic, studies in the Barents and Norwegian Seas show that minke whale diet varies greatly between areas and years, being dominated by krill in the northern areas, but by herring or capelin in other areas according to what is most abundant that year, with gadoids being taken when herring and capelin were scarce (Lindstrøm and Haug 2002). In the North Sea the diet consisted almost exclusively of sandeel (data from one year only). Minke whales taken off Iceland in 2003-04 contained mainly sandeel, with some capelin and gadoids (Víkingsson et al. 2006). Minke whales caught off Newfoundland during 1966-72 contained mainly capelin (Mallotus villotus) (Mitchell 1974).The overlap of the diet of this species with the targets of commercial fisheries poses difficult questions in ecosystem management. The question of whether minke whales should be culled to reduce their fish consumption is a particularly controversial issue.","Whaling on this species has been intensive in the Northeast Atlantic, and reduced the population over the period 1952-83. Catches were phased out by 1987, but whaling resumed, at a lower level, in 1993. Norway sets national catch limits based on the IWC’s Revised Management Procedure, a formula for setting safe catch limits (Hammond and Donovan in press). In presenting the RMP to the IWC for approval, the IWC SC offered three variants that it believed were acceptable and the IWC chose the most conservative option. Up until 2000, Norway used this option to set its national catch limits. It is now using the least conservative option presented by the SC. The national catch limit for 2006 was 1,052 whales, but only 521 were taken.Coastal catches averaging about 200 per year were taken off Iceland until 1985 when the IWC moratorium on commercial whaling came into effect. Small (a total of 100 expected for the period 2003-2006) experimental catches resumed in 2003. Catches off West Greenland continue, under an IWC catch limit of 175 whales annually, valid through 2007. As discussed above the IWC Scientific Committee has expressed concern at its inability to provide scientific advice on an appropriate catch limit (IWC 2007).Minke whales are subject to some level of incidental catch in fishing gear throughout much of their range, but in most areas the numbers involved are probably not significant.","Catch limits for all commercial whaling have been set at zero by the IWC since 1986. However, this moratorium does not apply to Iceland, Norway or the Russian Federation which have objected to this provision. IWC members are allowed to issue permits for whaling for scientific research. Limited aboriginal subsistence whaling is permitted by the IWC for common minke whales off Greenland. Takes of dwarf minke whales have been excluded from the Japanese scientific whaling programme in the Antarctic (JARPA) since summer 1992/93 (Nishiwaki et al. 2005). Minke whales, including B. acutorostrata, are listed on Appendix I of CITES, with the exception of the population from Greenland which is included in Appendix II. This implies prohibition of commercial international trade in its products, but that does not apply to Iceland, Norway or Japan, who hold reservations on the species. Common minke whales benefit from national protection measures implemented in several range countries.",Species account by IUCN SSC Cetacean Specialist Group; regional assessment by European Mammal Assessment team +ANIMALIA,CHORDATA,MAMMALIA,CETARTIODACTYLA,BALAENOPTERIDAE,Balaenoptera borealis,"The sei whale is a recognized species, but phylogenetically it falls within the Bryde's whale clade (Wada et al. 2003). Older catch and sightings records of sei whales, particularly prior to 1972, tended to include Bryde's whales in areas where the latter occur. Tomilin (1957) proposed two subspecies, B. b. borealis in the northern hemisphere and B. b. schlegeli (Flower 1884) in the southern hemisphere, but these are not widely recognized.",No,No,EN,D,EN,D,"Sei whales are virtually absent in the eastern North Atlantic: Norwegian surveys of northeast Atlantic waters in 1987, 1989, and annually from 1995-2005 yielded only one sei whale sighting in the Eastern stock area. Small numbers of sei whales were caught during 1957-80 off northwestern Spain, mainly in late summer/autumn (Aguilar and Sanpera 1982). It seems reasonable to assume that the total number of mature individuals in the European Mammal Assessment region is less than 250. Consequently the regional assessment is Endangered.",Unfavourable,"The sei whale is a cosmopolitan species, with a mainly offshore distribution, occurring in the North Atlantic, North Pacific and Southern Hemisphere, but probably not in the Northern Indian Ocean (Rice 1998). It is an occasional visitor to the Mediterranean (Reeves and Notabartolo di Sciara 2006). Sei whales undertake migrations between tropical and subtropical latitudes in winter to temperate and subpolar latitudes in summer, mainly in water temperatures of 8°-18°C, and tend not to penetrate to such high latitudes as other rorquals. Their winter distribution seems to be widely dispersed and is not fully mapped (Horwood 1987, 2002).In the North Atlantic the summer distribution seems to be quite variable from year to year; however, sei whales typically occur north of an arc running from south of Nova Scotia in the west, to the northwest British Isles and on to Trondheim in Norway, as far as the Davis Strait and the northern end of the Denmark Strait in the north. Occasional incursions into other areas have been noted (e.g. the Gulf of Maine, Schilling et al. 1993). Peaks of catch rates in early and late summer suggested a northward and southward migration through the former Nova Scotia whaling ground (Mitchell 1975). Sei whales have been scarce in Norwegian waters in recent years despite significant catches there in the past. Sei whales were caught in limited numbers, mainly in late summer, off northwestern Spain (Aguilar and Sanpera 1982), and have been recorded in winter as far south as the Caribbean and Cap Blanc, Mauritania (Rice 1998).","North AtlanticThe IWC recognizes three stock divisions for sei whales in the North Atlantic: Nova Scotia; Iceland-Denmark Strait; and Eastern (including the waters of Spain, Portugal, British Isles, Faeroes and Norway), but the divisions were chosen on largely arbitrary grounds (Donovan 1991). About 14,000 sei whales are recorded caught by modern whaling in the North Atlantic. In addition, an unknown proportion of the approximately 30,000 unspecified large whales caught in the North Atlantic in the late 19th and early 20th century were sei whales. Sei whales appear to have been depleted in the eastern North Atlantic, with over 7,500 recorded taken in Norwegian and British waters prior to WWII (not counting the unspecified whales), but fewer than 200 since then. The species seems to be virtually absent there now: Norwegian surveys of northeast Atlantic waters in 1987, 1989, and annually from 1995-2005 have yielded only one sei whale sighting in the Eastern stock area. Small numbers of sei whales were caught during 1957-80 off northwestern Spain, mainly in late summer/autumn (Aguilar and Sanpera 1982); the stock identity of these animals is unclear.By contrast, sei whales are still abundant in the central North Atlantic (Iceland-Denmark Strait IWC stock area), especially southwest of Iceland south to 50°N in summer. The only survey with reasonably complete coverage, designed specifically for the purpose of estimating sei whale abundance, was in 1989, and yielded a population estimate of 10,300 whales (CV 0.27) (Cattanach et al. 1993). Areas of sei whale abundance seems to shift markedly between years relative to the northern extent of the distribution, more so than for other baleen whale species (Gunnlaugsson et al. 2004).No recent abundance estimates are available for the western North Atlantic. The population size during 1966-69 was estimated at 2,078 (Mitchell and Chapman 1977) from sightings surveys, using strip transect methodology. About 1,200 sei whales were taken off Nova Scotia during 1962-72.Generation timeThe default value of 23.3 years for generation time given in Taylor et al. (2007) was considered appropriate, given an absence of any indications to the contrary from available biological information for the species.","Sei whales exhibit a greater variety in diet than, say, blue whales, but tend to feed on only one type of prey at a time. Of 21,713 stomachs examined in the North Pacific, 82.7% contained copepods only, and 12.6% contained euphausiids only; of 31,494 stomachs examined in the Southern Hemisphere, 54.3% contained euphausiids only, 30.5% contained copepods only, and 14.4% contained amphipods only (Nemoto and Kawamura 1977). Sei whale stomachs examined in the Northeast Atlantic contained copepods and euphausiids (Jonsgård and Darling 1977). Sei whale stomachs analysed in the North Pacific off California contained euphausiids and anchovies (Rice 1977). Sei whales are noted for their erratic appearance in specific feeding grounds, being plentiful in some years and absent (sometimes for years or even decades) in others (Horwood 1987).","Sei whale exploitation by modern whalers was particularly intensive in the Southern Hemisphere and the North Pacific from the late 1950s to the mid 1970s, following the depletion of the larger blue, fin and humpback whales. Sei whale stocks were seriously depleted during this period. Exploitation in the North Atlantic occurred over a longer period and was less intensive, except in the eastern North Atlantic, where the population appears not to have recovered from early modern whaling. Commercial exploitation ceased in the North Pacific in 1975, in the Southern Hemisphere in 1979 and in the North Atlantic in 1989. Catches by Japan under scientific permit resumed in the North Pacific in 2002: since 2004, the annual take has been 100 animals.Reports of other human-caused mortalities of sei whales are rare. Two fatal ship strikes (sei whales found dead on the bows of ships) have been reported on the US East Coast during 2000-2004 (Cole et al. 2006). It is hard to extrapolate from known cases to an estimated total, but sei whales appear to be at relatively low risk of human impacts, probably because of their largely offshore distribution.Rice (1961, 1974) reported a pathological condition in several North Pacific sei whales which resulted in deterioration or loss of baleen; however, the current frequency of this condition, and its impact (if any) on the population, are unknown.","Sei whales have been specifically protected from commercial whaling by the International Whaling Commission since 1975 in the North Pacific and 1979 in the Southern Hemisphere. They have also been protected by the general moratorium on commercial whaling since 1986, although this does not cover catches taken under scientific permit. No other specific conservation measures for sei whales are reported, but the species benefits from general whale protection laws in several countries.",Species account by IUCN SSC Cetacean Specialist Group; regional assessment by European Mammal Assessment team +ANIMALIA,CHORDATA,MAMMALIA,CETARTIODACTYLA,BALAENOPTERIDAE,Balaenoptera musculus,,No,No,EN,D,EN,D,"It is not possible to derive a quantitative population size or trend estimate for this species in the European Mammal Assessment region because there have been so few sightings in recent decades. However, based on the very small number of records it seems reasonable to assume that the population is smaller than 250 mature individuals. Consequently the regional assessment is Endangered. Before commercial whaling the species was much more abundant in the region.",Unfavourable,"The blue whale is a cosmopolitan species, found in all oceans except the Arctic, but absent from some regional seas such as the Mediterranean, Okhotsk and Bering seas. In the North Atlantic the summer distribution of blue whales extends in the west from the Scotian Shelf to the Davis Strait (NMFS 1998). Blue whales occur in the Denmark Strait, around Iceland and north to the ice edge, and in the northeast to Svalbard. Historically, blue whales were commonly caught along the coasts of North and West Norway, the Faeroes and the NW British Isles. They also occur in low numbers off NW Spain (Bérubé and Aguilar 1998) and in the past near the Strait of Gibraltar, but not in the Mediterranean (Reeves and Notabartolo di Sciara 2006). The winter distribution is poorly known but it appears that in the past blue whales were widely distributed in the southern half of the North Atlantic in winter (Reeves et al. 2004).","North AtlanticIn the North Atlantic, about 400 whales have been photo-identified in the Gulf of St Lawrence (Ramp et al. 2006) and Pike et al. (2004) estimate 1,000-2,000 in the central North Atlantic (Iceland, Denmark Strait, East Greenland, Jan Mayen, Faeroes and the British Isles). Sightings of blue whales are still very rare off Norway, Svalbard and the British Isles despite substantial past catches, especially in northern Norway (Christensen et al. 1992, Norwegian sighting surveys 1995-2006). Approximately 8,000 blue whales are specifically recorded caught in whaling statistics since the start of modern whaling in northern Norway in 1868, but an additional 30,000 unspecified large whales were recorded caught in the late 19th and early 20th centuries, of which perhaps as much as 25% could have been blue whales (IWC 2006). However, only about 1,600 blue whales were caught after 1917, hence the main decline occurred primarily before this time. The population is estimated to have been recovering at 5.2% p.a. (SE 1.1%) in the Iceland/Denmark Strait area during 1969-88, after catching had ceased (Sigurjónsson and Gunnlaugsson 1990). Taken together this all suggests that the North Atlantic population was very low when whaling ceased in the mid 1960s (apart from a very few pirate whaling catches up to 1978), and may now be at or above the 1911 level, but still well below the pre-whaling level.Generation time. The default value of 32 years for generation time given in Taylor et al. (2007) was considered appropriate, given an absence of any indications to the contrary from available biological information for the species.","Blue whales feed almost exclusively on euphausiids (krill), with a variety of species being taken by different blue whale populations, such as Euphausia superba in the Antarctic, Nyctiphanes australis off southern Australia (Gill 2002), Euphausia recurva off Western Australia (Bannister pers comm.) and Nyctiphanes simplex off the Galapagos (Palacios 1999). They feed both at the surface and also at depth, following the diurnal vertical migrations of their prey to at least 100m (Sears 1999). The migration patterns of blue whales are not well understood, but appear to be highly diverse. Some populations appear to be resident year-round in habitats of year-round high productivity, while others undertake long migrations to high-latitude feeding grounds (see above), but the extent of migrations and the components of the populations that undertake them are poorly known.","The main threat in the past was direct exploitation, which only became possible in the modern era using deck-mounted harpoon cannons. Blue whale hunting started in the North Atlantic in 1868 and spread to other regions around 1900 after the northeastern Atlantic populations had been severely reduced. The Antarctic and North Atlantic populations were probably depleted to the low hundreds by the time whaling ceased, but are increasing. Blue whales have been protected worldwide since 1966, although they continued to be caught illegally by USSR fleets until 1972. The last recorded deliberate catches were off Spain in 1978 (IWC, 2006). Blue whales are subject to some ship strikes and entanglements (NMFS 1998) but reported cases are few. The remote distribution of some blue whale populations probably makes them less vulnerable to human impacts than some other cetacean species, but local populations that inhabit waters with significant levels of human activity may be subject to some threat, such as disturbance from vessel traffic, including ship noise (e.g. Gulf of St Lawrence population, NMFS 1998). Globally, there appear to be no major threats to blue whales at present.","The International Whaling Commission had granted protection to blue whales by 1966. Catch limits for all commercial whaling have been set at zero by the IWC since 1986. However, this moratorium does not apply to Iceland, Norway or the Russian Federation which have objected to this provision. No blue whales have been recorded deliberately caught since 1978. They are protected by national regulations in many range states. Local measures may be required to protect the habitat of specific local populations in order to ensure their long-term viability in the face of increasing human impacts, e.g. see Hucke-Gaete et al. (2005).",Species account by IUCN SSC Cetacean Specialist Group; regional assessment by European Mammal Assessment team +ANIMALIA,CHORDATA,MAMMALIA,CETARTIODACTYLA,BALAENOPTERIDAE,Balaenoptera physalus,"The subspecific phylogeny of fin whales has not yet been fully elucidated, but some authors recognize a Northern Hemisphere subspecies B. p. physalus, and a Southern Hemisphere subspecies B. p. quoyi which has a larger body size. Clarke (2004) proposed a pygmy subspecies B. p. patachonica Burmeister 1865, but this is not widely accepted and no genetic analysis has been performed.",No,No,NT,,NT,,"European regional assessment: Near Threatened (approaching A1d). The population and range are large enough that Criteria B and D do not apply. Does not meet Criterion C (even at Near Threatened) because although the number of mature individuals is fairly low, there is no evidence of continuing decline. Generally in the North Atlantic populations are either stable or increasing, or there is no quantitative data. There are no estimates of historical or pre-exploitation abundance for the marine area covered by the European Mammal Assessment, but populations were undoubtedly depleted by commercial whaling. It is suspected that, by comparison with population levels 81 years (3 generations) ago, the population is currently 30-49% lower. This is a precautionary assessment that is not based on quantitative data, and it is strongly recommended that further surveys and modelling studies are carried out to better determine current and historic population size and trends.The Mediterranean population of the fin whale was assessed in 2006 as Data Deficient (Reeves and Notarbartolo di Sciara 2006).",Unfavourable,"Fin whales occur worldwide, mainly but not exclusively further offshore. They are rare in the tropics, except in certain cooler-water areas such as off Peru. North AtlanticIn the North Atlantic, the fin whale's range extends as far as Svalbard in the northeast (but rarely far into the Barents Sea), to the Davis Strait and Baffin Bay in the northwest (but rarely into the inner Canadian Arctic), to the Canary Islands in the southeast, and to the Antilles in the southwest (Rice 1998, Perry et al. 1999), but it is rare in the Caribbean and Gulf of Mexico (Ward et al. 2001). Their main summer range in the northwest Atlantic extends from Cape Hatteras (39°N) northward (Anon. 2005). In former times, fin whales were caught year-round near the Straits of Gibraltar. While there may be some north-south migration between summer and winter, it does not necessarily involve the entire population, and North Atlantic fin whales may occur to some extent throughout the year in all of their range, as suggested by acoustic data (Clark 1995).MediterraneanThere is a resident population in the central and western Mediterranean which is genetically distinct from that of the North Atlantic (Bérubé et al. 1998). The species also occurs, but rarely, in the eastern Mediterranean (Reeves and Notarbartolo di Sciara 2006).","North AtlanticNorth Atlantic fin whales were comprehensively assessed by the IWC Scientific Committee in 1991 (IWC 1992), and an update for the northern part of the region was undertaken in 2006 in a joint workshop with NAMMCO (IWC 2007). North Atlantic fin whale stocks had previously been assessed by the IWC Scientific Committee in 1976 (IWC 1977). Based mainly on past whaling operations, the IWC recognizes seven management areas in the North Atlantic: Nova Scotia; Newfoundland-Labrador; West Greenland; East Greenland-Iceland; North Norway; West Norway-Faeroe Islands; British Isles-Spain-Portugal. Based on genetic evidence, it is now considered more likely that there are from two to four breeding stocks, which utilize these seven management areas in different proportions (IWC 2007).The best available estimates of recent abundance accepted by the IWC Scientific Committee (IWC 2007) are: 25,800 (CV 0.125) in 2001 for the central North Atlantic (East Greenland-Iceland, Jan Mayen and the Faeroes); 4,100 (CV 0.21) in 1996-2001 for the northeastern North Atlantic (North and West Norway); and 17,355 (CV 0.27) in 1989 for the Spain-Portugal-British Isles area (Buckland et al. 1992). The only accepted estimate for West Greenland is 1,046 (CV 0.35) in 1988 (IWC 1992); a newer estimate from a 2005 survey could not be accepted due to methodological problems. There are no complete estimates for the western North Atlantic Northwest Atlantic, but partial estimates are 1,013 (95% CI 459-2,654) for Newfoundland in 2003-3 (IWC 2007), and 2,814 (CV 0.21) for the east coast of North America from the Gulf of St Lawrence southward (Anon. 2005). No significant trends were found in the total abundance for any of the above areas, but when the area west and southwest of Iceland was singled out, a significant increasing trend was found (IWC 2007).Fin whales were heavily exploited in the late 19th and early 20th centuries, starting in 1876, particularly off Norway, Iceland, the Faeroes and British Isles. Whaling then spread to Spain, Greenland and eastern Canada, and exploitation continued at a lower level until the 1980s. Catch statistics for the early years are probably incomplete, and a large number of whales were killed but lost, due to lines breaking, etc., perhaps up to one-half in the first 20-25 years and one-third in the next 15-20 years (Tønnessen 1967). The IWC Scientific Committee added 50% to recorded catches up to 1915 to allow for this (IWC 2007): recorded catches up to 1915 total 15,315 fin whales plus 29,024 unspecified whales of which about half may have been fin whales, thus the total kill may have been about 45,000 up to 1915. The total recorded catch post-1915 has been about 55,000 fin whales. The approximate figures by area are: Canada 12,000; Norway 10,000; Iceland 10,000; Faeroes 5,000; Greenland 1,000; British Isles 3,000; Spain and Portugal 11,000; and pelagic operations 3,000. The behaviour evident for the various North Atlantic fin whale populations following earlier reductions through whaling differs. It ranges from clear evidence of recovery to no firm indications of any increase. An estimated 14,000 fin whales were killed off North Norway during 1876-1904, and a further 1,500 during 1948-71, but fin whales are rare there now (although quite abundant off western Spitsbergen, where about 1,500 whales had been killed during 1904-11) (Øien 2003, 2004). An estimated 12,000 fin whales were killed off Iceland during 1890-1915, until whaling was suspended partly due to concerns about the reductions in the stocks, but the modern abundance data suggest that the there has been a recovery in the population that may still be continuing, particularly west of Iceland, despite catches during 1948-89 averaging about 220 per year (Branch and Butterworth 2006). An estimated 10,000 fin whales were taken from the Faeroes, but about 25% of these were actually caught off eastern Iceland (IWC 2007). Whaling from the Faeroes and West Norway petered out during the 1960s as whales became scarce (IWC 1977), but catches had apparently been mainly of migrating whales rather than local populations. MediterraneanCatches of about 7,000 fin whales taken near the Straits of Gibraltar in the 1920s apparently depleted the local abundance, and fin whales are still rare there today, but this did not seem to affect the abundance of fin whales off northern Spain, where catches continued until 1985. The impact of catches on the fin whale stocks in the Northwest Atlantic is unclear (Mitchell 1972). The population was estimated in 1991 from surveys covering much of the western Mediterranean at 3,583 (CV 0.27) (Forcada et al. 1996). It is likely, but not certain, that the historical catches near the Strait of Gibraltar were from the North Atlantic rather than from this population (Sanpera and Aguilar 1992). Palsbøll et al. (2004) found that Mediterranean fin whales probably have a small but non-zero genetic exchange with fin whales elsewhere in the North Atlantic.Generation time The default value of 27 years for generation time given in Taylor et al. (2007) was considered appropriate, given an absence of any indications to the contrary from available biological information for the species.","Fin whales are often portrayed in the secondary literature as eating fish including juvenile herring (e.g. NAMMCO undated). However, the available quantitative evidence suggests that the fin whale's reputation as a fish-eater is largely overstated. In Icelandic catches, 96% contained krill only, 2.5% a mixture of krill and fish, and 1.6% fish only (Sigurjónsson and Víkingsson 1997), while only one of 267 fin whales caught in the northeast Pacific off British Columbia, Canada, contained fish (Flinn et al. 2002), and over 99% of stomachs with food in the Antarctic contained krill (Kawamura 1994). On the other hand, Overholtz and Nicolas (1979) report apparent feeding of fin whales on American sand lance (sand eel) Ammodytes americanus in the northwest Atlantic, and Mitchell (1975) found that capelin comprised 80-90% of prey in fin whales caught off Newfoundland. Capelin abundance is extremely variable over time, and fin whales may feed opportunistically on capelin in high-capelin years. In summary, although the fin whale is more flexible in its diet than the blue whale (B. musculus), its consumption of fish is not necessarily a significant problem.","Prior to the advent of modern whaling in the late 19th century, fin whales were largely immune from human predation because they were too hard to catch. Fin whales were depleted worldwide by commercial whaling in the 20th century. Fin whales have been protected in the Southern Hemisphere and North Pacific since 1975, and catches ceased in the North Atlantic by 1990, except for small aboriginal subsistence catches off West Greenland. Commercial catches resumed off Iceland in 2006, with nine fin whales being taken that year. A Japanese fleet resumed experimental catches of fin whales in the Antarctic in 2005, taking 10 whales each during 2005/06 and 2006/07, with plans to take 50 per year from the 2007/08 season (IWC 2006). It seems unlikely that catching of fin whales will return to the high levels of previous years, not least due to the limited market demand for whale products.Fin whales are one of the more commonly recorded species of large whale in vessel collisions (Laist et al. 2001). Five fatal collisions are recorded off the US east coast during 2000-04 (Cole et al. 2006). Collisions with vessels appear to be a significant, but not necessarily unsustainable, source of mortality for the Mediterranean population (Weinrich et al. 2005, Reeves and Notabartolo di Sciara 2006). Fin whales are occasionally caught in fishing gear as bycatch: four deaths and serious injuries from this source are reported from the eastern US coast during 2000-04 (Cole et al. 2006); recent Japanese Progress Reports to the IWC (www.iwcoffice.org/sci_com/scprogress.htm) report about one fin whale by-caught per year on average.","The IWC set catch limits to zero for fin whales in the North Pacific and Southern Hemisphere in 1976. Catch limits for all commercial whaling have been set at zero by the IWC since 1986. However, this moratorium does not apply to Iceland, Norway or the Russian Federation which have objected to this provision. Limited aboriginal subsistence whaling is permitted by the IWC for fin whales taken off West Greenland. Fin whales are listed on Appendix I of the Convention on Trade in Endangered Species (CITES), but this does not apply to Iceland, Norway and Japan, who hold reservations. Fin whales are also listed on Appendices I and II of the Convention on Migratory Species (CMS). Under the Agreement for Conservation of Cetaceans in the Black and Mediterranean Seas (ACCOBAMS), fin whales in the Mediterranean, along with other cetaceans, are protected from deliberate killing by signatories to the agreement.",Species account by IUCN SSC Cetacean Specialist Group; regional assessment by European Mammal Assessment team +ANIMALIA,CHORDATA,MAMMALIA,CETARTIODACTYLA,BALAENOPTERIDAE,Megaptera novaeangliae,,No,No,LC,,LC,,"Reasonably good survey data are available for the two main feeding grounds that lie relatively close to the European Mammal Assessment region (Iceland and N Norway/Spitzbergen). Recent partial estimates include 13,900 individuals for Iceland (CI=3,900 – 29,000) and 889 for N Norway/Spitzbergen (CV 0.32) (IWC 2002, 2003). Not all of these are mature individuals. The global population is estimated to be increasing rapidly (3% per year), and the Iceland population may be increasing more rapidly still (surveys showed an increase of 11.4% per annum from 1986 to 2001, although immigration as well as population growth may be responsible for this) (IWC 2003). The species is rare in the European Mammal Assessment region (Reid et al. 2003). Although no quantitative estimates are available, it seems reasonable to suspect that the number of humpback whales present in the EMA area may be fewer than 1,000 mature individuals, the threshold for consideration as Vulnerable under Criterion D. However the humpback whale is highly mobile and travels large distances, and the animals in the EMA region are undoubtedly part of larger populations that extend outside the region and that are expanding rapidly in size. Consequently the category is downgraded by two steps to Least Concern.",Possibly Favourable,"The humpback whale is a cosmopolitan species found in all the major ocean basins (Clapham and Mead 1999), and all but one subpopulation (that of the Arabian Sea) migrate between mating and calving grounds in tropical waters, usually near continental coastlines or island groups, and productive colder waters in temperate and high latitudes. Humpbacks are abundant throughout the Antarctic in summer south to the ice edge, but not within the pack ice zone. In the winter, Southern Hemisphere populations are aggregated into specific nearshore breeding areas in the Atlantic, Indian Ocean and Pacific, two of which extend north of the equator, e.g. off Colombia in the eastern Pacific and in the Bight of Benin in the Atlantic. Some wintering grounds are fairly localised, for example around island groups, and some are more diffuse, for example along the western coast of Southern Africa and the southern coast of west Africa. In the North Atlantic, they range in summer from Gulf of Maine in the west and Ireland in the east, and up to but not into the pack ice in the north; the northern extent of the humpback’s range includes the Barents Sea, Greenland Sea and Davis Strait, but not the Canadian Arctic. They occur mainly in specific feeding areas. In the winter the great majority of whales migrate to wintering grounds in the West Indies, while an apparently small number of animals still utilize a historical breeding area around the Cape Verde Islands.Humpbacks rarely enter the Mediterranean and are considered vagrant there.","The humpback whale is better studied than other balaenopterid species, and migratory destinations are well known for some subpopulations. North AtlanticA comprehensive assessment of North Atlantic humpback whales was completed by the IWC Scientific Committee in 2002, from which most of the information below is drawn.Six distinct feeding aggegrations have been identified: Gulf of Maine; Gulf of St Lawrence; Newfoundland/Labrador; West Greenland; Iceland; North Norway (including Bear Island and Jan Mayen). Genetic and photo-ID data indicate that the six feeding aggregations represent relatively discrete subpopulations, fidelity to which is determined matrilineally. However, because whales from different feeding grounds all mix in a common breeding area in the West Indies, there is male-mediated nuclear gene flow between the subpopulations.Humpbacks were heavily exploited in the past by pre-modern whaling in their breeding grounds in both the West Indies and the Cape Verde islands, and by modern whaling in their feeding grounds, especially off Iceland and off Norway in the late 19th and early 20th centuries. Catches of pre-modern whaling are estimated primarily from trade records. Catches of early modern whaling also need to be estimated, because most of the catch records were not divided by species. An estimated 3,200 were taken from Iceland and 2,000 from northern Norway during 1880-1916. About 1,500 humpback whales are reported killed in the North Atlantic since 1916, from a variety of areas including the British Isles, Faeroes, Norway, Iceland, Greenland, and eastern Canada, as well as Norwegian pelagic catches.Population modelling exercises show that the recent abundance and increase rate of humpback whales in the North Atlantic are too large to represent a recovery from depletion by the estimated past kills. This suggests that either:(i) past kills have been substantially underestimated; or(ii) there has been some increase in the environmental carrying capacity for humpback whales; or(iii) whaling had a negative impact on the population, over and above the effects of the actual removals, in ways that are not understood; or(iv) some combination of the above factors.Whichever of the above hypotheses pertains, the increase rate of 3% per annum implies that humpbacks are considerably more abundant in the North Atlantic today than they were in 1940. This is consistent with anecdotal evidence of the relatively low numbers observed prior to 1960.Generation timeTaylor et al. (2007) estimate mean generation time at 22 years.","With a few exceptions, such as the Arabian Sea population, humpback whales undertake long migrations between breeding grounds in tropical coastal waters in winter to feeding grounds in middle and high latitudes, mainly in continental shelf waters. In the Southern Hemisphere, humpbacks appear to feed mainly in the Antarctic, where the diet consists almost exclusively of krill (Euphausia superba), although some feeding in the Benguela Current ecosystem on the migration route west of South Africa has been observed (suspected prey species are E. lucens and Themisto jaudichaudi). Limited data on diet in other areas is available. Humpback whales caught off Newfoundland and Labrador in the 1950s and 1960s were found to be consuming mainly capelin (Mallotus villotus). Those caught off California in the early 20th century were eating mainly euphausiids and sardines. In areas of Alaska and the North Atlantic, humpback whales have also been observed feeding co-operatively on schools of herring (Clupea harengus), sand lance (Ammodytes spp.) and (more rarely) mackerel (Scomber scombrus), by herding the school together with bubble nets, clouds or curtains.","Although commercial whaling seriously depleted all humpback populations, the species has demonstrated remarkable resilience, and most populations have increased since the end of whaling, although there are several populations which remain small and for which no increase has yet been detected, such as the populations breeding near South Pacific islands, and the western North Pacific population. Humpback whales have been protected from commercial whaling worldwide since c.1963, but illegal catches by Soviet fleets continued in the Antarctic and North Pacific until 1973. Today, small numbers only are taken by a “subsistence” whaling operation off St Vincent (1-2 animals per year); it is possible that other small unreported catches occur elsewhere. However, the government of Japan has announced plans to resume humpback whaling in the Antarctic from the 2007/08 season, starting with an experimental catch of 50 animals per year under scientific permit. The species is not currently hunted in European waters.Humpback whales are subject to entanglements, often fatal, in fishing gear. They are also vulnerable to injury by ship strikes, which an also be fatal. The documentation of such incidents is best for US waters. For the Atlantic coasts of the US during 1999-2003, there were 19 reports of mortality or serious injury caused by entanglements and 7 cases of mortality or serious injury due to ship strikes. For US Pacific waters (mainly Alaska) during 1999-2001 there were 13 reports of mortalities and serious injuries due to entanglement and three reports of mortalities due to ship strikes.","Humpbacks have been protected from commercial whaling worldwide since 1963, and there have been very few catches after 1967. Despite having been severely depleted to a world population in the low thousands at that time, humpbacks have since recovered strongly to a world population which was at least 60,000 in the mid-1990’s and has been increasing since. Humpback whales enjoy additional protective measures in some countries, such as sanctuaries.",Species account by IUCN SSC Cetacean Specialist Group; regional assessment by European Mammal Assessment team +ANIMALIA,CHORDATA,MAMMALIA,CETARTIODACTYLA,BOVIDAE,Bison bonasus,Two genetic lines are distinguished in recent populations: the Lowland line (B. b. bonasus) and the Lowland-Caucasian line (B. b. bonasus x B. b. caucasicus). There are no surviving pure-bred populations of B. b. caucasicus (Pucek et al. 2004).,No,No,VU,D1,VU,D1,"European regional assessment: Vulnerable (VU)EU 25 regional assessment: Vulnerable (VU)The global population of free-living animals was c.1,800 in 2006. However, because some of these have not reached breeding age, and because polygyny reduces the effective population size, the total number of 'mature individuals' may be less than 1,000. Almost all of these animals live in the European region (as defined by the European Mammal Assessment), and approximately 550 of them live in EU 25 countries (Poland, Lithuania, Slovakia) (EBPB 2004). Although the population declined between the early 1990s and 2000, the current population trend is increasing. Consequently the species qualifies as Vulnerable under Criterion D1 at the European regional and EU 25 levels. Bison bonasus (Lowland line): Vulnerable D1In 2000, the total population was 931, not all of these are mature individuals. Although the population declined between the early 1990s and 2000, it is currently increasing.Bison bonasus (Lowland-Caucasian line): Endangered C1+2a(i)In 2000, the total population was 714, not all of these are mature individuals. The population decreased by >20% between 1990 and 2000, and has continued to decline since 2000. All subpopulations are smaller than 250 individuals.""The fate of the European bison provides an example of the way in which a species may be brought to the brink of extinction in a very short time, and then saved only through great efforts. The saving of the bison has been an undoubted success, but further action to protect what remains a creature of relict distribution will continue to be essential"" (Krasiński 2005).",Unfavourable,"European bison Bison bonasus is the largest herbivore in Europe. Historically it was distributed throughout western, central, and south-eastern Europe and the Caucasus. By the end of the 19th century, there were only two populations of European bison left in the wild: in Białowieża Forest B. b. bonasus and in the western Caucasus mountains B. b. caucasicus. B. b. bonasus was finally driven extinct in the wild in 1919, and B. b. caucasicus had been extirpated by 1927. Subsequently, the species survived only in a few European zoological gardens (Sztolcman 1924). As a result of reintroductions and introductions, it now occurs in free-ranging and semi-free herds in Poland, Lithuania, Belarus, Russian Federation, Ukraine, and Slovakia. The introduced Kyrgyzstan subpopulation has recently gone extinct (EBPB 1996, Pucek et al. 2004). Captive populations are well distributed in 30 different countries worldwide (see Pucek et al. 2004 for details). It occurred from sea level to 2,100 m in the Caucasus (Pucek 1986), and in the Carpathians it is presently found at alitutudes of up to 800 m (K. Perzanowski pers. comm. 2006).","In historical times, the European bison was widespread and presumably abundant in its native range. However, by the end of the 19th century it was close to extinction, with only two wild populations remaining (Pucek et al. 2004). Shortly after World War I the species was extinct in the wild, and the captive population consisted of just 54 (29 males; 25 females) European bison with proved pedigrees (Raczyński 1978, Pucek 1991), originating from 12 founder animals (Slatis 1960). The captive population subsequently increased slowly until World War II, when the species again suffered a steep decline, with the population dropping from 160 animals in 1943 to 93 in 1946 (Pucek et al. 2004).As a result of captive breeding, reintroductions, benign introductions, and intensive conservation management, the total population of free-ranging bison now stands at c.1,800. A further c.1,400 individuals live in captivity (EBPB 2004). Some captive animals are not recorded in the European Bison Pedigree Book, so this is likely to be an underestimate (Pucek et al. 2004). Population structure is such that approximately 60% of individuals are sexually mature (Krasiński 1978, Krasińska and Krasiński 2004). The effective population size is smaller than the total population size, because European bison are a polygynous species, so not all males have the opportunity to breed (Krasiński and Raczyński 1967, Krasinska and Krasiński 1995, Krasińska and Krasiński 2004). The free-living population increased more or less steadily from the mid-1960s to a peak of c.2000 in the early 1990s (Pucek et al. 2004). Following a period of decline in the mid to late 1990s, the population is once again expanding (W. Olech pers. comm. 2006), although the potential for ongoing growth is limited by a number of factors (Pucek et al. 2004). Two genetic lines are distinguished in recent populations: the Lowland line (B. b. bonasus) and the Lowland-Caucasian line (B. b. bonasus x B. b. caucasicus). There are no surviving pure-bred populations of B. b. caucasicus (Pucek et al. 2004).","Optimal habitats for the European bison are deciduous and mixed forests, but the range should include about 20% of grassland habitats (meadows) (Pucek et al. 2004, K. Perzanowski pers. comm. 2006). In Białowieża Forest (Poland) they primarily forage in moist deciduous forests, and then in mixed coniferous forests (Krasińska et al. 1987, Krasiński and Krasińska 1994). Forest complexes with a mosaic-like forest type arrangement (such as Białowieża and Borecka Forests, Poland) are most favourable. In fresh deciduous forest, European bison find food throughout the vegetative season. In the Caucasus region, European bison prefer foothill forests; in summer, they feed on alpine meadows (Kazmin and Smirnov 1992, Kazmin et al. 1992). However, considerable plasticity of European bison with regard to food means they also forage in habitats where coniferous forests predominate (Krasiński et al. 1999). All European bison populations inhabit ranges that include open areas, such as mown meadows, deforested feeding glades covered with grass, clear cuts and young plantations up to 10 years old (Dzięciołowski 1991, Krasińska and Krasiński 1994, Krasiński et al. 1999). The attraction of open areas results from the fact that meadows and glades provide ungulates with much more food than the same area of the forest herb layer and food is more easily available there (Korochkina and Bunevich 1980, Kazmin et al. 1992). The species had an important role in the formation of the prehistoric European broad-leaf forest and forested steppe ecosystems (Pucek et al. 2004).","Habitat degradation and fragmentation due to agricultural activity, forest logging, and unlimited hunting and poaching were the primary reasons for the decrease and extinction of European bison populations. Pucek (1991) has summarised the history of their extinction. Among the primary reasons for the rapid decrease of the European bison population in Białowieża Primeval Forest at the beginning of 19th century was the over-population of deer species, and the drastic reduction of natural food resources for herbivores which resulted (Wróblewski 1927). During the period of World War I and the Russian Revolution of 1917, conflict and heavy poaching exacted a severe toll on remaining populations (Pucek et al. 2004). Conflict and political instability continues to be a threat to the species in the Caucasus, where reintroduced free-living herds have suffered very severe losses (leading to extinctions) in recent years (Pucek et al. 2004). Other current threats include lack of appropriate habitat, fragmentation of populations (and concomitant loss of genetic diversity), inbreeding depression, disease, hybridization, and poaching. There is little space for a large herbivore such as the European bison in Europe's contemporary ecosystems, especially in the west. The most significant limit for the enlargement of European bison populations is human population density; forestry and agricultural activity is not a limiting factor. Fragmentation and isolation of free-ranging (and captive) herds result in little or no exchange of genetic material. Small isolated populations quickly lose their genetic heterogeneity and are more vulnerable to extinction (Franklin 1980). As yet, the opportunity to reconstruct a more compact geographic range to facilitate migration of bison between herds does not exist. As a consequence of passing a dramatic bottleneck (the current population descends from just 12 founder animals), the gene pool is limited and animals are highly inbred. The average inbreeding coefficient is very high compared to other large mammals, and is equal to 44% in the Lowland line and 26% in the Lowland-Caucasian line for individuals with a full pedigree (Olech 1998). The negative effects of inbreeding, manifested in the decline in reproduction rate, are more strongly pronounced in the Lowland-Caucasian line than in the Lowland line (Olech 1987, 1989, 1998). Inbreeding exerts a harmful effect on skeleton growth, particularly in females (Kobryńczuk 1985), and possibly lowers the resistance of bison to disease and pathologies.Diseases appearing in European bison populations can bring serious threats to the whole species. It is not certain whether the species has always shown a weak resistance to disease or if immunity has declined, due to limited genetic heterogeneity. The most important disease affects the male reproductive organs and is manifested in the inflammation of the penis and prepuce, leading to diphtheroid-necrotic lesions, diagnosed as balanoposthitis. This disease was discovered at the beginning of the 1980s in Białowieża Forest (Kita et al. 1995, Piusiński et al. 1997, Jakob et al. 2000); although similar symptoms had been reported earlier (Korochkina and Kochko 1982) in Russia and Ukraine (Krasochko et al. 1997). Despite many years of study, its pathogenesis has not yet been elucidated. Other diseases that are potentially major threats to herds include foot-and-mouth disease Aphte epizooticae (to which the species is known to be sensitive) (Podgurniak 1967), and tuberculosis (Żórawski and Lipiec 1997, Welz et al. 2005) .A particular problem concerning the management of extant populations of European bison is the existence of hybrid herds, especially European × American bison hybrids living in the Caucasus. Two free-living hybrid herds have been established in the Caucasus Mountains, in close proximity to reintroduced free-living herds of the pure blood Lowland-Caucasian line. There are fears that all these animals will crossbreed, creating a mixture of various genotypes. According to Russian authors, the distances between herds are not so great, but the configuration of mountain ridges and valleys make it impossible for contact between them. There are also two small semi-free herds of European × American bison hybrids in Toksove Forest Park (St Petersburg) and the Mordovia Wildlife Reserve (Pucek et al. 2004). Finally, poaching as a result of administrative disorders and a failure to enforce nature conservancy law threatens free-living herds of European bison in many countries.","The species is listed in Appendix III (protected fauna species) of the Bern Convention, and on Annexes II* and IV of the EU Habitats & Species Directive. The European Bison Pedigree Book has been developed, which registers and publishes lists of European bison, enabling the genetic purity of the species to be maintained. A Conservation Action Plan for the species has been published (Pucek et al. 2004), and most countries in which the species occurs have national management plans. The European Endangered Species Programme (EEP) for zoos was established by the European Association of Zoos and Aquaria (EAZA) in 1996, and now a third of the captive population is participating in this programme. Conservation measures recommended in the 2004 Action Plan (Pucek et al. 2004) include the following:1. Continue captive breeding, following a coordinated programme that focuses on maintaining genetic variability. Hybridization between existing breeding lines (Lowland and Lowland-Caucasian) should be avoided, as should hybridization between European bison and American bison Bison bison.2. Establish a Gene Resource Bank (semen collection in the first phase) to serve as a safeguard against loss of important genetic diversity.3. Continue reintroductions and benign introductions, into forests and other ecosystems (including large tracts of land where human activities are abandoned, such as former farmland or military training grounds). A target of 3,000 free ranging animals of each genetic line is recommended as a management goal. It will be necessary to link isolated subpopulations (e.g. by creating habitat corridors) and restore metapopulation function to enable the population to be self-sustaining in the long term.4. Regulate bison populations by culling, when necessary, to prevent populations exceeding the carrying capacity of remaining habitat.5. Manage habitat appropriately, for example by creating watering places, and cultivated meadows or feeding glades for use by other ungulates. 6. Implement and enforce stricter regulations to control poaching.7. Continue producing the European Bison Pedigree Book, and expand its scope.8. Establish an International Bison Breeding Centre, to coordinate reintroductions, monitoring of captive and free-ranging herds, and genetic management of particular herds.9. To promote protection of the species, upgrade it to Appendix II (strictly protected fauna species) of the Bern Convention.Further details, as well as recommended research activities, can be found in Pucek et al. 2004.",Wanda Olech (Bison Specialist Group) +ANIMALIA,CHORDATA,MAMMALIA,CETARTIODACTYLA,BOVIDAE,Bos primigenius,See Gentry et al. (2004) and Wilson and Reeder (2005) for the debate about the correct name for this species.,No,No,EX,,EX,,"The species Bos primigenius is considered Extinct. It went extinct across most of Europe before 1500 A.D., but persisted in Poland until the 1600s.",-,"Bos primigenius was Extinct in the Wild, except in Jaktorowka Forest, Masovia, Poland, by the start of the 15th century. The last wild individual is reputed to have died in 1627 (Wilson and Reeder 2005). It is distributed worldwide under domestication (as Bos taurus), and feral populations have become established in Australia, New Guinea, USA, Colombia, Argentina and many islands, including Hawaiian, Galapagos, Dominican Republic/Haiti, Tristan da Cunha, New Amsterdam and Juan Fernandez Islands, and the United Kingdom (Chillingham cattle). Its native range encompassed parts of Europe, Africa and the Middle East (Wilson and Reeder 2005).",,Presumably in grasslands.,,,Alexei Tikhonov +ANIMALIA,CHORDATA,MAMMALIA,CETARTIODACTYLA,BOVIDAE,Capra hircus,"The domestic goat and the wild goat are treated here as separate species (following inter alia Shackleton 1997), named Capra hircus and Capra aegagrus respectively. These taxa are sometimes considered to be conspecific, in which case the name Capra aegagrus has generally been used to refer to the wild species and its domesticated form, although some authors use the name Capra hircus for both the wild species and its domestic descendants (see Gentry et al. 1996, BZN 2003, Gentry et al. 2004 and Wilson and Reeder 2005).""Wild goats"" and ""wild sheep"" found on Mediterranean islands are generally recognised to have been introduced by humans (Shackleton 1997, Wilson and Reeder 2005), and genetic and archaeozoological studies suggest that they are feral populations of ancient domestic stocks (e.g. Groves 1989, Vigne 1994, Hiendleder et al. 1998, Manceau et al. 1999, Kahila bar-Gal et al. 2002). Consequently, such taxa should be included in the respective domestic species (Capra hircus, Ovis aries) and not as subspecies of the wild taxa (as proposed by Gentry et al. 1996, Gentry et al. 2004, and Gippoliti and Amori 2004).",No,No,NA,,NA,,"This Red List rationale refers only to anciently introduced populations of ""wild"" goats on Majorca and certain Greek islands. As they are considered to be feral descendants of early domestic stock, they are classed as Not Applicable (NA). The total population of these animals is >20,000, and although the range is small (Area of Occupancy may be less than 2,000 km2) and there are problems in parts of the range with hybridization with domestic goats and poaching, the population trend overall is believed to be stable or increasing. However, the Cretan subpopulation (subspecies cretica) has a very restricted range (the National Park is about 50 km2 and can be considered as a single location) and is threatened by hybridization. These ancient feral form are of interest as ""living fossils"", representing the very earliest domestic stock little changed from its primitive state, and deserve protection.",-,"This Red List assessment refers to populations of Capra hircus that were introduced to Mediterranean islands in prehistoric times, known as Cretan or Majorcan ""wild"" goats, or as agrimi (Cretan populations only). These feral descendants of primitive domestic stock are clearly distinct from modern domestic and feral goats, and are of conservation interest as ""living fossils"" and repositories of important genetic diversity (Shackleton 1997). More recent feral populations are not considered here; neither are domestic Capra hircus.""Wild"" goats can be found in mountainous areas in northern and western Majorca (Spain), and on Crete (Greece) where they were formerly widespread but are now restricted to an area of approximately 72 km2 in the Lefka Mountains at the western end of the island. There is a small, semi-captive population on the small (68 ha) satellite island of Theodorou (Shackleton 1997, Palomo and Gisbert 2002). Populations on the Greek islands of Dia, Agii Pantes (Agii Apostoli), Erimomilos (Antimilos), Samothrake, Gioura and others, are all considered hybrids of ""wild"" and modern domestic or feral goats (Shackleton 1997), as are populations in the Czech Republic (Pedrotti and Lovari 1999). There are genetic and morphological differences between the Cretan and Majorcan populations (Seguí 2005). The species occurs from sea level to 1,450 m (Palomo and Gisbert 2002).","The 1985 Cretan population was estimated to be around 500 agrimi, and together with those on Theodorou island, make a total population of at least 570 to 600 agrimi in Europe at that point (Shackleton 1997). More recent population estimates vary widely, but some are as large as 2,000 individuals (G. Giannatos pers. comm. 2006). It occurs at high densities in at least parts of its range on Crete, although its total range is very small. In 1998 a census of Majorca found 20,000 individuals (Palomo and Gisbert 2002), although this included hybrids and feral domestic goats (B. Seguí pers. comm. 2007). The current (2007) estimate of the Majorcan wild goat population is 1,500-2,000 individuals, out of a total of 10,000 including hybrids and feral descendants of modern domestic goats (B. Seguí pers. comm. 2007).","Agrimi inhabit mountainous areas, where there is a mixture of rocky outcrops or scree slopes and vegetation (shrubby maquis thickets or conifer forests). They tend to be found in relatively arid habitats, and are herbivorous, feeding on grasses, herbaceous plants and shrubs (Pedrotti and Lovari 1999).","For the Cretan population, the greatest threat is hybridization with recently feral domestic goats that are common even within Samaria National Park. Other problems arise from increased road accessibility, which in turn increases tourism and poaching problems. In Majorca, hybridization with feral domestic goats is again the main threat (Palomo and Gisbert 2002).","It is listed (as Capra aegagrus) on Appendix II of the Bern Convention and Annexes II and IV of the EU Habitats and Species Directive (natural populations only). On Crete it is fully protected under national law, which is well enforced. Part of the agrimi's distribution on Crete falls within Samaria (Lefka Ori or White Mountains) National Park. There are no current management plans in operation other then an attempt to control poaching. Agrimi inhabiting Theodorou island also receive protection. Shackleton (1997) proposes the following measures for agrimi on Crete: 1) Establish a strict control program to eliminate feral goats inside Samaria National Park to remove the threat of hybridization with the agrimi. Only reducing or eliminating the herds of domestic goats from the surrounding areas will prevent their immigration into the Park. 2) Continue improving the control of poaching by regularly patrolling the Park during winter, and by allowing no further increases in access. 3) Impose greater controls on tourism developments in the Park. These should include banning the development of major tourist facilities (chair/ski lifts, hotels, restaurants, roads, etc.) in the mountain regions of the Park and its surroundings, and strictly controlling visitor use (e.g. specific hours of use enforced, no overnight use of the Park). 4) The population should be censused and the area surveyed regularly throughout the Lefka mountains, paying special attention to the degree of hybridisation and human encroachment. 5) Overall, it may be desirable to eradicate domestic x wild goat hybrids, unfortunately F1 hybrids are difficult to distinguish from agrimi in either external appearance or behaviour. (However, compared to agrimi, the hybrid' s coat appears to be slightly longer and interspersed with black hairs, the horns are curved outwards a little more and are more robust, and the resting tail is held more horizontal than downwards.) 6) Determine the degree of hybridization of the goats found on the various islands to help direct conservation management decisions. On Majorca, the wild goat has been studied since 2001 and several groups have been protected in fenced areas and captive-bred (B. Seguí pers. comm. 2007). Palomo and Gisbert (2002) recommended that selective hunting should be used to remove the hybrids from the population. Since 2006, hunting of pure-bred animals has been banned (Decret 91/2006, Balearic Government) but hunting of hybrids amd recent feral domestics goats is allowed and encouraged. Trophy hunting of Mallorcan wild goats will be allowed again once populations have reached target levels stated in Decret 91/2006. To prevent poaching, capturing alive animals for trade, and illegal hunting of hybrids for commercial purposes, the Balearic Government is collaborating with SCI and Junta Nacional de Homologación de Trofeos de Caza, MMAM, Spanish Government (B. Seguí pers. comm. 2007).","Giorgos Giannatos, Juan Herrero, Sandro Lovari" +ANIMALIA,CHORDATA,MAMMALIA,CETARTIODACTYLA,BOVIDAE,Capra ibex,,Yes,No,LC,,LC,,"This species is listed as Least Concern in view of its wide distribution, presumed large population, and because it is not declining at nearly the rate required to qualify for listing in a threatened category. The species needs conservation action to prevent future decline.",Possibly Favourable,"The Alpine ibex is endemic to Europe, where its native range is the Alps of France, Switzerland, Austria, Germany, and northern Italy (Shackleton 1997; Grubb, 2005). It has been introduced to Slovenia and Bulgaria (Pedrotti and Lovari 1999). The ibex was driven very close to extinction in the early 19th century, and with the exception of the population in the Gran Paradiso National Park (Italy), all current populations originate from re-introductions or introductions. Although the range of the ibex has increased over the last century as a result of translocations and natural colonisation, its distribution is still rather patchy in the Alps. It occurs from 500 to 3,000 m (Pedrotti and Lovari 1999).In Austria, all current populations originate from re-introductions, although not always into former or even suitable habitat. The first colony was re-established in 1924 in the Bluhnbach valley (Hagen mountains), and the second in 1936, farther east in Wildalpen, so that by 1988, ca. 740 ibex had been released (Bauer, 1991). By the 1990s, the species is now found in the Bhihnbach valley (Hagen mountains), in the Northern Limestone alps in Wildalpen, and in the Pitz and Kauner valleys of Tyrol, and in the Styria (Hochlantsch massif). In France, it is found mainly in the eastern part of the Alps. Four ibex populations had been re-established in Germany by the 1990s. The first introduction was made at Koenigsee (Berchtesgaden) in 1936 with 24 animals. The founding animals came from the Aosta valley (Italy), from Peter and Paul, and from the Berlin and Munich Zoological Gardens. The animals dispersed after a few years to the Austrian Bluebachtal. In 1951, the population was reduced considerably after an outbreak of sarcoptic mange, but since then numbers have increased slowly. The population straddles the German-Austrian border, wintering in Austria and summering in the Bavarian Alps in Germany. A second population was established at Jachenau, partly the result of immigration of one male from the Austrian colony at Baechental, supplemented by four animals from Swiss founder populations in 1967. After the addition of several more ibex, this population increased to about 100 animals by the 1990s; however, its range is very restricted and there is little potential for expansion. A small colony in Oberaudorf was the result of a re-introduction in 1963 which failed to disperse. It is now restricted to an area of about 100 ha, and foresters consider it a problem because of range over-use. Another small, restricted population became established through natural dispersal from Austria, but its size is unknown. Ibex were introduced into the Rila mountains of Bulgaria (Atlas of the Mammals of Bulgaria) in the mid-1980s. In Italy, re-introductions, combined with some spontaneous migration from adjoining countries (Peracino and Bassano, 1986; Tosi et al., 1986a), have increased areas with ibex, but its distribution is still rather discontinuous in the Alps.","After centuries of decline caused primarily by intensive hunting, at the beginning of the 19th century at most a few hundred Alpine ibex survived in the Gran Paradiso massif (Valle d’Aosta region, Italy). Current ibex populations in the Alps are generally restricted to mountain areas above the tree line and are the result of both translocations from the original core of c.100 individuals and natural colonisation (Dupré et al. 2001). These efforts, together with spontaneous migration from adjoining countries, have increased the population and the number of areas inhabited by ibex, although the distribution is still discontinuous (Stüwe and Nievergelt 1991, S. Lovari pers. comm. 2006). In the 1990s it was estimated that c.30,000 ibex lived in the Alps (Pedrotti and Lovari 1999). Populations grew steadily from the 1960s to the 1990s, showing a mean annual growth rate between 3% and 6% (Dupré et al. 2001). About 15,000 ibex were estimated in Switzerland, 9,700 in Italy, 3,200 in Austria, 3,300 in France, 250 in Slovenia and, and 220 in Germany (Shackleton 1997).","Alpine ibex typically inhabit open, rocky habitats at high altitude, above the tree line. Steep, south-facing slops with rugged topography and grassy vegetation are preferred. Below the tree line, at subalpine levels, ibex are only found in open, sunny woodland interspersed with rocky outcrops (Nievergelt and Zingg 1986, Pedrotti and Lovari 1999). Ibex feed on alpine grasses, herbaceous plants and shrubs (Pedrotti and Lovari 1999). This species is diurnal, but most active during the early morning and late afternoon. Living in montane pastures, they eat grasses and some woody plants. They migrate seasonally to different altitudes, spending the harsher winter months at medium elevations. The animals occur in maternal herds of 10-20 members, while males roam solitarily or in bachelor groups. Females gestate for about 170 days, and usually carry one kid per pregnancy. Females are sexually mature by 18 months, and males are mature at 2 years. The species lifespan is typically 10-14 years.","Although the species is not considered threatened at present, there is concern regarding genetic diversity, the founder effect and minimum viable populations (Shackleton 1997, Maudet et al. 2002). Genetic variability in ibex populations is among the lowest reported from microsatellites in mammal species, and the Alpi Marittime–Mercantour population in particular has suffered from a severe genetic bottleneck associated with its reintroduction (Maudet et al. 2002). The ibex's distribution remains fragmented and many colonies are small and thus vulnerable to epizootics and stochastic events as well as inbreeding depression. Colonies with >60 individuals are believed to be viable as long as diseases (most importantly mange) do not affect them (Shackleton 1997, EMA Workshop 2006). Hybridization can be a threat where populations are small and sympatric with high densities of domestic goats, as is the case in Italy (Randi et al. 1990, Pedrotti and Lovari 1999). High densities of domestic goats and sheep may also have a negative impact on the ibex through parasite and disease transmission and resource competition (Shackleton 1997, J. Herrero pers. comm. 2006). Appropriate habitat for the species may be decreasing, as the abandonment of traditional agriculture means that high-altitude alpine meadows are reverting to forest through natural succession (EMA Workshop 2006). Human disturbance as a result of increased tourism and recreation is suspected to be a general threat to mountain ungulates (Shackleton 1997). Alpine ibex are legally hunted in some areas (e.g. Bulgaria, Switzerland, Austria, Slovenia), although hunting is completely prohibited in several range states (Shackleton 1997). Legal hunting is not considered a threat if it is properly planned and regulated, but poaching is a potential threat (Dupré et al. 2001).","The Alpine ibex is listed on Appendix III of the Bern Convention and Annex V of the EU Habitats and Species Directive, and is protected under national legislation in most range states. It occurs in a number of protected areas (e.g. Hohe Tauern and Kalkhochalpen National Parks, Austria; Vanoise, Ecrins, and Mercantour National Parks, France; Gran Paradiso and Stelvio National Parks and Maritime Alps Natural Park, Italy), and it has been the subject of intensive conservation management in the form of reintroductions and introductions (Shackleton 1997). Reintroductions began at the end of the 19th century in the Swiss Alps, while in Italy they have been significant only since the 1970s (Dupré et al. 2001).According to Shackleton (1997) and Dupré et al. (2001), the main proposal for ibex conservation is to continue restocking populations in appropriate habitats. Reintroductions should also be carefully planned, e.g. by (1) Using environmental evaluation models for selecting areas for reintroducing ibex, in conjunction with (2) a conservation strategy that aims to make the separate colonies part of a single metapopulation; (3) Giving priority to protected areas, or to other areas capable of guaranteeing efficient surveillance against poaching and disturbance (although this does not mean that controlled hunting areas should be a priori excluded); (4) Selecting founder individuals for new colonies according to specific criteria; (5) Limiting domestic sheep and goat grazing in reintroduction areas to decrease the possibility of parasite and disease transmission, resource competition, and hybridization; and (6) Screeing reintroduction sites for suitability in relation to health and disease transmission.Other conservation recommendations include ensuring that any harvest is sustainable (through research, legislation, and international cooperation), reducing poaching (through legislation, enforcement, education and communication), reducing the impacts of human disturbance (e.g. by providing refugia in areas with intense tourism), and monitoring all populations.","Aulagnier, S., Kranz, A., Lovari, S., Jdeidi, T., Masseti, M., Nader, I., de Smet, K. & Cuzin, F." +ANIMALIA,CHORDATA,MAMMALIA,CETARTIODACTYLA,BOVIDAE,Capra pyrenaica,,Yes,Yes,LC,,LC,,This species is now abundant and its range and population are currently expanding as a result of habitat changes resulting from rural abandonment. Consequently it is assessed as Least Concern. Hunting reservations and protected areas have played a crucial role in species recovery.,Possibly Favourable,"This species historically occurred throughout the Iberian peninsula, including southwest France, Spain, Andorra, and Portugal (Grubb, 2005). It is, however, extinct in the northern part of its range (including in France and Andorra), and no longer occurs in the Pyrenees. Capra pyrenaica is now endemic to the Iberian peninsula. Of the four described subspecies, only two are extant: C. p. victoriae and C. p. hispanica. C. p. victoriae occurs in the central Spanish mountains (Sierra de Gredos), and has been re-introduced to a number of additional sites in Spain (Batuecas, La Pedriza, Riaño) and northern Portugal (Peneda-Gerês National Park) (Palomo and Gisbert 2002, Cabral et al. 2005, Moço et al. 2006, J. Herrero pers. comm. 2006). C. p. hispanica occupies the arc of mountains that run along the Mediterranean coast, from the Ebro river to the rock of Gibraltar (where it no longer occurs), as well as the Sierra Morena. C. p. lusitanica died out at the end of the 19th century, and C. p. pyrenaica went extinct in 2000 when the last known individual was found dead (Pérez et al. 2002, Cabral et al. 2005, J. M. Pérez pers. comm. 2006). It formerly occurred throughout much of the French, Spanish and Andorran Pyrenees, and persisted until recently in Ordesa and Monte Perdido National Park in the Maladeta massif. The species is found from sea level to 3,400 m (Palomo and Gisbert 2002).","The population in the whole of the Iberian peninsula was estimated at c.50,000 individuals in more than 50 subpopulations (Palomo and Gisbert 2002, Pérez et al. 2002). Subpopulations include those of the Sierra Nevada (16,000 individuals), Sierra de Gredos (8,000 individuals), Maestrazgo (7,000 individuals), Serranía de Ronda and Sierras de Grazalema (4,000 individuals), Puertos de Tortosa y Beceite Natural Park (4,000 individuals) Cazorla (2,500 individuals), Sierra Tejeda y Almijara (2,500 individuals), Sierras de Antequera (2,000 individuals), Sierra Morena (2,000 individuals) and Muela de Córtes (1,500 individuals) (Pérez et al. 2002, J. Herrero and J. M. Pérez pers. comm. 2006). Numbers have expanded dramatically since the early 1990s, when the total population was estimated at c.7,900 individuals (Shackleton 1997), and continue to increase. Its range is expanding in Spain and into Portugal (Cabral et al. 2005). In 2003 the Portuguese population consisted of a minimum of 75 individuals. (Moço et al. 2006).","It occurs in rocky habitats. Even small rocky patches in arable farmland and on the coast may be used, although cliffs and screes interspersed with scrub or pine trees are the most typical habitats. It often lives in very close proximity to humans, and is a familiar and popular species. It disperses readily and can rapidly colonise new areas if appropriate habitat is available. It is an important trophy-hunting species, with some trophy prices exceeding EUR 2,000 (J. Herrero pers. comm. 2006). Hunting can be an important source of revenue to local communities in rural areas. The species can sometimes be an agricultural pest, causing damage to almond trees (J. Herrero pers. comm. 2006).","No threats are causing population or range declines at present - indeed the species is expanding. However, alteration and fragmentation of habitats (through agriculture, forestry, fires, and infrastructure development) may impact upon certain Capra pyrenaica populations, and competition with the introduced the aoudad (Ammotragus lervia) might become a conservation problem in the near future (Cabral et al. 2005, J. M. Pérez pers. comm. 2006). The aoudad was introduced during the 1970s in southeastern Spain, and recently an important range expansion of this exotic ungulate has been reported (Cassinello et al. 2004); competition between these two ungulate species can be expected. The impact of hunting (predominantly for trophies) has not been scientifically assessed (J. M. Pérez pers. comm. 2006), but the poaching of large dominant males might alter gene flow (J. Herrero pers. comm. 2006). However, hunting levels are broadly under control. Outbreaks of mange (Sarcoptes scabiei) occur sporadically and have caused at least one major population crash (Shackleton 1997, Palomo and Gisbert 2002). Wild goats are occasionally killed by accident during wild boar hunting-drives with dogs (J. Herrero pers. comm. 2006). Previously, the population was kept low by competition with domestic livestock, which restricted wild goats to marginal habitats. The causes of C. p. pyrenaica' s demise are unknown, but there are a number of hypotheses including competition for food with chamois, inbreeding depression, parasite infections from domestic livestock, climatic conditions, poaching, and low fertility due to plant secondary compounds (Shackleton 1997). The last remaining individual, a 13-year-old female, was killed by a falling tree.","The species is protected under Appendix III of the Bern Convention and Annex V of the EU Habitats and Species Directive. It is listed as Critically Endangered in Portugal, owing to its very small population in that country (Cabral et al. 2005). C. p. victoriae occurs in Sierra de Gredos, las Batuecas and Riaño Hunting Reserves and Manzanares Natural Park. C. p. hispanica occurs in a number of protected areas, including Sierra de las Nieves, Sierra de Grazalema, Sierra Nevada, and Sierra de Tajada y Almijara, Puertos de Tortosa y Beceite, and Muela de Cortes. However, most of the range occupied by wild goats is outside protected areas. Conservation measures proposed include establishing additional populations of C. p. victoriae in other areas to strengthen its conservation status by reducing the possibility of an epizootic or some other catastrophe wiping out, or severely depleting, the present small population. When establishing new populations, founder effects should be considered, and sufficient numbers of animals should be introduced to maintain genetic diversity (J. Herrero pers. comm. 2006). Measures should be taken to reduce poaching (Cabral et al. 2005), and the impact of hunting should be scientifically assessed.","Herrero, J. & Pérez, J.M." +ANIMALIA,CHORDATA,MAMMALIA,CETARTIODACTYLA,BOVIDAE,Ovis aries,"The domestic sheep and its wild ancestor the urial are treated here as separate species (following inter alia Shackleton 1997), called Ovis aries and Ovis orientalis respectively. These taxa are sometimes considered to be conspecific, in which case the name Ovis orientalis has generally been used to refer to the wild species and its domesticated form, although some authors use the name Ovis aries for both the wild species and its domestic descendants (see Gentry et al. 1996, BZN 2003, Gentry et al. 2004 and Wilson and Reeder 2005).""Wild sheep"" and ""wild goats"" found on Mediterranean islands are generally recognised to have been introduced by humans (Shackleton 1997, Wilson and Reeder 2005), and genetic and archaeozoological studies suggest that they are feral populations of ancient domestic stocks (e.g. Groves 1989, Vigne 1994, Hiendleder et al. 1998, Manceau et al. 1999, Kahila bar-Gal et al. 2002). Consequently, such taxa should be included in the respective domestic species (Capra hircus, Ovis aries) and not as subspecies of the wild taxa (as proposed by Gentry et al. 1996, Gentry et al. 2004, and Gippoliti and Amori 2004).",No,No,NA,,NA,,"This Red List rationale refers only to anciently introduced populations of Ovis aries on Mediterranean islands. As they are considered to be feral descendants of early domestic stock, they are classed as Not Applicable (NA). These ancient feral form are of interest as “living fossils”, reperesenting the very earliest domestic stock little changed from its primitive state, and deserve protection.",-,"This Red List assessment refers to populations of Ovis aries that were introduced to Mediterranean islands in prehistoric times, known as mouflon. These feral descendants of primitive domestic stock are clearly distinct from modern domestic and feral sheep, and are of conservation interest as ""living fossils"" and repositories of important genetic diversity (Shackleton 1997). More recent feral populations, and recently-introduced populations of ancient feral forms, are not considered as part of the population for the purposes of the assessment; neither are domestic Ovis aries.The mouflon was introduced in prehistoric times to Corsica, Sardinia and Cyprus. Since the middle of the 18th Century it has been introduced to many parts of Europe and populations have become established in many countries including Spain, France, Belgium, Luxembourg, Germany, Denmark, Italy, Austria, Switzerland, Slovenia, Croatia, the Czech Republic, Slovakia, Poland, Romania, Bulgaria, Lithuania, Bosnia and Herzegovina, Macedonia, Serbia and Montenegro, Ukraine, and the Canary Islands (Röhrs 1999). These introduced mainland populations are patchily rather than continuously distributed. In Corsica it is found from sea-level to above 2,000 m, whereas in Cyprus it is found from sea level to about 500 m.","On Corsica it is known from two small isolated subpopulations (one in the north near Massif du Cinto and one in the south in the Bavella Reserve). There are only about 500 animals, and the population is probably stable (after a long decrease, during which the total population dropped below 100 individuals) (S. Aulagnier pers. comm. 2006). On Sardinia there are at least 5,000 head (C. Murgia pers. comm. to S. Lovari). In the western part of Cyprus, the population is more than 2000 animals and increasing (EMA Workshop 2006).","In Europe, the species inhabits Mediterranean maquis (shrubland), rocky areas, and open coniferous forest and green oak forest. It is absent from dense woodland (Röhrs 1999). Mouflon are hunted for trophies and meat.","Hunting is the most important threat, although competition and crossbreeding with domestic sheep are also threats (Shackleton 1997, S. Lovari pers. comm. 2006). However, these are not considered to endanger the species at present.","The mouflon is listed on Appendix III of the Bern Convention, and on Annexes II and IV of the EU Habitats & Species directive (populations on Corsica and Sardinia only). It is protected under national legislation in Sardinia, Corsica, and Cyprus. The Corsican population is being studied as part of an EU LIFE Project. As part of this project they are looking into increasing the population through captive breeding, and improving genetic vigour by mixing the two subpopulations (S. Aulagnier pers. comm. 2006).","Stéphane Aulagnier, Giorgos Giannatos, Sandro Lovari" +ANIMALIA,CHORDATA,MAMMALIA,CETARTIODACTYLA,BOVIDAE,Rupicapra pyrenaica,,Yes,Yes,LC,,LC,,"This species is currently increasing in numbers and range. It is not believed to approach the thresholds for any of the criteria for the IUCN Red List. Consequently it is assessed as Least Concern. Subspecies R. p. pyrenaica and R. p. parva are also Least Concern. However, R. p. ornata is assessed here as Vulnerable (D1+2) as it has a very small population and restricted area of occupancy. It was previously assessed in 1996 as Endangered, but as a result of strict protection and a programme of captive breeding and reintroductions, its population has increased such that it no longer meets criterion D at this level. Ongoing conservation measures are required to ensure its future survival.",Possibly Favourable,"Rupicapra pyrenaica is endemic to south-west Europe, where it occurs as three subspecies: R. p. ornata, R. p. pyrenaïca and R. p. parva (Shackleton 1997, Pedrotti and Lovari 1999). The Apennine chamois R. p. ornata now survives only in three small populations in the Abruzzo, Majella, and Gran Sasso-Monti della Laga National Parks in Italy, although earlier in the Holocene it ranged from the Sibillini mountains (Marche Region, Italy) down to the Pollino massif (Calabria Region, Italy) (Masini 1985, Masini and Lovari 1988). The isard or Pyrenean chamois R. p. pyrenaica is found in the Pyrenean mountains, along France' s border with Spain (including Andorra: C. Berducou pers. comm. 2006). The Cantabrian chamois R. p. parva occurs in the Cantabrian mountains (Spain). The altitudinal range of the species is 400-2,800 m (Palomo and Gisbert 2002).","Overall, the status of this species has greatly improved since 1990. The population and range of the Pyrenean subspecies pyrenaica increased markedly from 1989 to 2003, although there have subsequently been some declines. The 1989 estimate for the total number of R. p. pyrenaica was around 15,500 animals (Shackleton 1997), but by 2003 there were estimated to be at least 53,000 (Herrero et al. 2004). This is now (2006) likely to be an overestimate of the population, as many chamois populations have locally declined since 2004 following severe mortality caused by viral disease, and French hunting bags have reduced although hunting effort has remained steady (C. Novoa pers. comm. 2006). Densities of R. p. pyrenaica tend to be lower outside protected areas. Not all subpopulations of subspecies parva have been censused, but the population was recently estimated at c.15,000 (Palomo and Gisbert 2002). However, the Italian subspecies ornata remains very rare. Numbers of ornata have probably been low for the last few centuries, only starting to increase in the 1920s as a result of increased protection. Numbers plummeted again to just several tens of individuals in a single population in the Abruzzo National Park during World War II (Lovari 1989). As a result of conservation action, including re-introductions and the establishment of two new populations, numbers have increased and the population is currently estimated at about 1,100 individuals in three subpopulations (Mari and Lovari 2006, S. Lovari pers. comm. 2006), up from a total of c.400 individuals in the late 1980s (Lovari 1989). Not all of these are mature individuals.","The species is found in alpine meadows, rocky areas, and the forested valleys and lower slopes in mountainous regions. This species generally stays above 1,800 meters in alpine meadows during the warmer months of the year (Nowak, 1983). These animals make altitudinal migrations from the forests in the valleys to the more open alpine meadows (Pedrotti and Lovari 1999). In late fall and winter they have been known to enter lands below 1,100 meters, while usually staying on steep slopes, and rarely if ever occur in forested areas (Nowak, 1983). In recent years some populations have started to permanently inhabit forest (Mitchell-Jones et al. 1999; Herrero pers. comm. 2006).","The threats to the species vary in different parts of its range. In Italy, subspecies ornata might be vulnerable to many factors because the total number is small, there are only three subpopulations, and genetic variability is very low (Shackleton 1997, S. Lovari pers. comm. 2006). Space and food competition with livestock, especially domestic caprins, seem to be the main limiting factors for ornata . Some poaching occurs, but does not seem to impair the viability of the chamois population in Abruzzo National Park. There are currently no problems with disease for the Italian subspecies (J. Herrero pers. comm. 2006). However, in France and Spain disease is currently the most important threat. Pestivirus appeared in the Pyrenean subspecies in c. 2004, and sarcoptic mange outbreaks periodically cause local declines in the Cantabrian subspecies (J. Herrero pers. comm. 2006). In Spain and the Pyrenees, chamois coexist with domestic livestock, but there do not appear to be problems with competition; indeed in the Pyrenees the presence of domestic livestock is considered to benefit the chamois, via maintenance of young and good quality forage, which increases the carrying capacity (J. Berducou pers. comm. 2006). Most Pyrenean and Cantabrian populations are hunted (with the exception of within National Parks). Chamois is a major game species in Spain and is important socially and economically as a source of rural livelihoods. Hunting is carefully managed and revenue from hunting is returned to the local community. In Spain, regional governments set quotas, and hunting is not at an unsustainable level (J. Herrero pers. comm. 2006). In France, hunting is essentially a recreational and non-profit leisure activity, and average annual quotas are under 10% of censused populations. This is sustainable, with only a few local exceptions (C. Berducou pers. comm. 2006).","The species is listed on Appendix III of the Bern Convention and Annex V of the EU Habitats and Species Directive (as part of R. rupicapra sensu lato). In Spain, the species occurs in three national parks, at least 10 natural parks, and a number of other reserves (J. Herrero pers. comm. 2006). Spanish protected areas include Montana de Covadogna and Ordesa National Parks; Reres Natural Park; Alta Pallars-Aran, Benasque, Cadi, Cerdana, Fresser y Setcasas, Los Circos, Los Valles, Vinamala, Mampodre, Picos de Europa, Saja, Somiedo and Sueve Hunting Reserves. Spanish hunting reserves are large hunting management units with strictly controlled culling (C. Berducou pers. comm. 2006). In France, it occurs in a number of protected areas (Pyrenees-Occidentales National Park, Roc-Blanc, Moudang and Mont-Vallier Mountain Reserves, Orlu Nature Reserve and other small reserves where hunting is banned: C. Berducou pers. comm. 2006). A study of population dynamics is ongoing in France, as well as a detailed survey of the population size and distribution (C. Berducou pers. comm. 2006). In France, there is a hunting plan that is designed to correct geographic imbalances in numbers and distribution, but might be difficult to achieve. A major restoration effort was carried out in the French Pyrenees between 1981 and 2000, involving the translocation of more than 600 individuals (Herrero et al. 2004, C. Novoa and C. Berducou pers. comm. 2006). In Andorra there are a few small reserves with hunting quotas (C. Berducou pers. comm. 2006). In Italy, the autochthonous population of subspecies ornata inhabits Abruzzo National Park, and all recent and planned re-introductions and introductions are into protected areas. A group of 22 chamois was released in the Majella massif between 1991 and 1994, and more recently, 26 were re-introduced into the Gran Sasso massif in cooperation with local villagers. A captive breeding population (numbering 18 individuals in 2006: S. Lovari in litt. 2006) is kept in four large enclosures in as many national parks. No studbook has been kept, which is a major shortcoming in the captive breeding program (Shackleton 1997). The subspecies ornata is strictly protected under national and international legislation - it is listed on Appendix II of the Bern Convention, Annex II* and Annex IV of the EU Habitats and Species Directive, Appendix I of CITES, and as a “specially protected species” under Italian hunting law. A slowly increasing number of alpine meadows in the species’ range have been forbidden to livestock grazing to reduce competition. This action may generate cautious optimism about the species’ future. Proposed conservation measures include the following: 1) Consider benign introductions for a number of areas in the central and southern Apennines, once their suitability has been adequately assessed. Some national parks (e.g. Pollino, Gran Sasso-Laga, Majella and Sibillini) could in the future also host populations of the Apennine chamois. 2) When selecting individuals for transplants and captive breeding, consider Nascetti et al.'s (1985) finding of an alarming lack of genetic variability in the surviving nucleus of the Abruzzo National Park. This was most likely a result of living at low density for a long time and of population bottlenecks occurring at World Wars I and II. 3) Keep detailed breeding records, genetic profiles, and develop a studbook, for each of the captive breeding populations. 4) Avoid releasing Alpine chamois into areas of potential (re)introduction of Apennine chamois, as if such an action was carried out, it would prevent the subsequent release of the latter species (Shackleton 1997).Future priorities for the species as a whole include extending monitoring to all populations, and to increasing knowledge of demography and the impact of hunting. It is particularly important for monitoring and research to take place outside National Parks, where chamois are hunted.","Herrero, J., Lovari, S. & Berducou, C." +ANIMALIA,CHORDATA,MAMMALIA,CETARTIODACTYLA,BOVIDAE,Rupicapra rupicapra,,No,No,LC,,LC,,"European regional assessment: Least Concern (LC)EU 25 regional assessment: Least Concern (LC)The Alpine chamois is widespread and has a large population of over 440,000 individuals. Although it is declining in some parts of its European and global range, the bulk of the population is found in the Alps and is relatively secure. Consequently it is classed as Least Concern. However, several chamois subspecies qualify as globally threatened, and require urgent conservation action.",Unknown,"The Alpine chamois is native to mountainous parts of central and southern Europe and Asia Minor, where it occurs as seven subspecies: balcanica, carpatica, cartusiana, rupicapra, tatrica, asiatica and caucasica(Shackleton 1997, Pedrotti and Lovari 1999). It has been introduced to Argentina and New Zealand. Subspecies balcanica inhabits most of the mountain regions of Albania, as well as Bulgaria's four main massifs. In Greece, it is currently restricted to 11 mountains, and comprising at least six distinct and widely scattered population groups from Mount Rodopi in the northeast and the Epirus mountains in the northwest, to Mount Giona in central Greece (Shackleton 1997). Subspecies carpatica occurs in many populations throughout the Transylvania alps and the Carpathian mountains. There have been a number of successful reintroductions (Shackleton 1997). Subspecies cartusiana is endemic to France, where it is restricted to a 350 km2 area of the Chartreuse limestone massif, centred around Grenoble, at the western edge of the French Alps. Subspecies rupicapra is found in the Alps of Austria, Germany, and eastern France, and subspecies tatrica occurs in the Tatra mountains of Poland and Slovakia. In Slovakia, it has also been introduced to the Low Tatras (Shackleton 1997). R. r. asiatica occurs in Asia Minor and R. r. caucasica has a restricted range in the Caucasus. It occurs from 500 m to 3,100 m in the Alps (Spitzenberger 2002).","The Alpine chamois is widespread and generally increasing. Excluding the Caucasus population, there are an estimated 440,000 individuals in Europe, and in some protected areas densities may exceed 20 individuals per hectare (Pedrotti and Lovari 1999, S. Lovari pers. comm. 2006). However, with the exception of the Alpine subspecies R. r. rupicapra, many subspecies are rare and/or declining: R. r. asiatica: There is very little data on the status of this subspecies, but it is believed to have undergone substantial declines (EMA Workshop 2006).R. r. balcanica: The total population numbers some thousands of individuals. Numbers are believed to be declining in all subpopulations (Shackleton 1997). R. r. carpatica: In 1990, the total population was estimated to be around 9,000 animals (Shackleton 1997).R. r. cartusiana: The population was estimated at 300 to 400 individuals in the 1970s, and 150 individuals in 1986-1987, but has since increased to c.2,000 individuals (S. Lovari pers. comm. 2006).R. r. caucasica: There is very little data on the status of this subspecies, but it is declining and has virtually disappeared outside protected areas (EMA Workshop 2006).R. r. rupicapra: This subspecies is widespread and abundant in the Alps. The number of individuals culled per year in the Swiss Alps and Jura mountains has increased steadily from c.4,000 individuals in 1950 to c.17,000 individuals in 2000 (Loison et al. 2003). R. r. tatrica: The population was estimated at 220 in 1999 (Jurdíková 2000), and had dropped below 200 by 2002 (S. Lovari pers. comm. 2006). Numbers have been declining steadily since the 1960s (Jurdíková 2000).","Alpine chamois inhabit steep, rocky areas in the mountains, utilising a variety of habitats including alpine meadows, open rocky areas, mixed broadleaf woodland, and coniferous woodland (Pedrotti and Lovari 1999). They feed on grasses and herbs, and on the leaves of trees (Sägesser and Krapp 1986).","Poaching and over-hunting may be a problem for the species in parts of its range, especially where it occurs outside protected areas and private hunting reserves (Shackleton 1997, Jurdíková 2000). Many of the less numerous subspecies (e.g. R. r. balcanica, R. r. cartusiana, and R. r. tatrica) are threatened by the deliberate introduction of subspecies from other geographic areas (especially R. r. rupicapra), leading to hybridisation and genetic swamping (Shackleton 1997). Human disturbance, particularly as a result of increased tourism and leisure activities in mountain areas, may also be a problem (Shackleton 1997, Jurdíková 2000). Competition with domestic livestock and introduced species such as the mouflon Ovis aries is a threat to the more vulnerable subspecies, although it is not considered to be a major problem for R. r. rupicapra. R. r. rupicapra does, however, suffer periodic outbreaks of sarcoptic mange, causing local population declines (Shackleton 1997). In 2006 a new disease, pestivirus, was first recorded in this subspecies (J. Herrero pers. comm. 2006). In general, habitat loss is not a major threat to the species, as much of its range falls within protected areas. However, habitat loss may be a problem in some areas (e.g. for subspecies balcanica in Albania) (Shackleton 1997). Because its population is very small indeed, subspecies cartusiana is susceptible to extinction as a result of stochastic demographic or environmental events (Shackleton 1997, S. Lovari pers. comm. 2006).","The species is listed on Appendix III of the Bern Convention. Subspecies balcanica is listed on Annexes II and IV of the EU Habitats & Species Directive, and subspecies tatrica is listed on Annexes II* and IV. Chamois occur in a number of protected areas. Subspecies cartusiana has been subject to intensive conservation management, including reintroductions. Detailed conservation recommendations are given in Shackleton (1997). In general, conservation recommendations that apply to all subspecies include ensuring that any harvest is sustainable (through research, legislation, and international cooperation), reducing poaching (through legislation, enforcement, education and awareness-raising, and provision of alternative livelihoods where necessary), reducing the impacts of human disturbance (by providing refugia in areas with intense tourism), and protecting the genetic integrity of populations (by avoiding translocations of 'foreign' subspecies that could hybridise with the local population) (Shackleton 1997). Monitoring of all subspecies is required, especially those that are rare and/or declining. To protect the High Tatras subspecies, Jurdíková (2000) recommends reducing illegal hunting (by closing and guarding parts of the western Tatra mountains). R. r. rupicapra introduced into Slovakia (e.g. the Lower Tatras National Park) should be removed as they pose a threat to the wild population of R. r. tatrica (Shackleton 1997).","Stéphane Aulagnier, Giorgos Giannatos, Juan Herrero" +ANIMALIA,CHORDATA,MAMMALIA,CETARTIODACTYLA,BOVIDAE,Saiga tatarica,"Saiga tatarica is the only species in the genus Saiga. Although there is little geographical variation two subspecies are recognised: Saiga tatarica tatarica (the nominate subspecies, to which belongs the majority of the population) and Saiga tatarica mongolica (endemic to western Mongolia).",No,No,CR,A2a,NE,,"European regional assessment: Critically Endangered (CR)EU 25 regional assessment: Not Evaluated (NE)Both the global and European regional populations have shown an observed decline of over 80% during the last 10 years. The decline is continuing, and severely skewed sex ratios are leading to reproductive collapse. Consequently the saiga is assessed as Critically Endangered.",-,Saiga tatarica inhabits the steppes and semi-desert regions of southeastern Europe and Central Asia. Currently found at one location in Russia and three areas in Kazakhstan. A distinctive subspecies occurs in Mongolia.,"Historically, it was a common species in Eurasian steppes and semideserts. From information provided in recent references it appears that between 1991 and 1994, the global population of S. tatarica was relatively stable at just under one million animals, the majority of which were in Kazakhstan (approximately 810,00-825,000) (Bekenov et al. 1998, Lushchekina et al. 1999, Sokolov and Zhirnov 1998). Recent information from A.B. Bekenov and Iu. A. Grachev (in litt. to IUCN Species Survival Commission 1999) suggests that the population in Kazakhstan had fallen by spring 1998 to around 570,000 animals (a decline of ~30%). The global population is now c.50,000, down from 1,250,000 in the mid-1970s. Most are found in Kazakhstan.In European Russia (Kalmykia), the saiga population steeply declined after land reclamation of the Volga basin started, but the species remained numerous within the distribution area. In the 1970s the population recovered to c.700-800,000 as a result of hunting regulation. However, since then the population has drastically declined. In 1980 there were an estimated 380,000 individuals, in 1996 196,000, and by 2000 just 26,000 (see Milner-Gulland et al. 2001 for annual survey results for 1980-2000). At present there are no more than 18,000 animals. Sex ratio is severely skewed; the proportion of males varies from 1 to 10 % in different years.","Inhabits arid steppes and semi-deserts. Prefers clay soil open spaces covered with grass and avoids rugged terrain as well as sandy areas. A migratory species with widely separated summer (northern) and winter (southern) ranges. Lives in large herds, usually up to thousand individuals. Heat is at the beginning of winter when males defend harems of females. Gives birth in April-May to two, more seldom to one calf.","Uncontrolled illegal hunting for horns (male horns are exported for the traditional Chinese medicine trade) and meat since the break-up of the former USSR has led to the catastrophic fall in numbers. Selective hunting of young males and subsequent distortion of the sex ratio has affected reproduction: recent research shows that heavily skewed sex ratios are resulting in reproductive collapse (Milner-Gulland et al. 2003). A second significant threat is the destruction of key habitats and traditional migration routes. Agricultural abandonment is a problem in some areas; cattle grazing formerly maintained the grassy species but land abandonment allows another species (Stippa sp.) to encroach, which the saiga cannot eat. The recent increase in steppe fires is a further cause for concern. Severe winters can cause mass mortality.","Legislation protecting saiga exists at national level but increased enforcement, and especially external funding for anti-poaching measures and linked rural development are urgently needed. Some protected areas exist within saiga range but distance between summer/winter ranges of the various populations hinders full protected area coverage. Extension of already existing and new protected areas is under discussion by the Russian Federation government. Some research is being carried out on numbers, range and behaviour. Total prohibition of saiga meat and horn trade as well as temporary removal of saiga from the hunting animals list have been proposed as key conservation measures.","Global assessment by D.P. Mallon (IUCN SSC Antelope Specialist Group), regional assessment by European Mammal Assessment team." +ANIMALIA,CHORDATA,MAMMALIA,CETARTIODACTYLA,CERVIDAE,Alces alces,,No,No,LC,,LC,,European regional assessment: Least Concern (LC)EU 25 regional assessment: Least Concern (LC)Listed as Least Concern as the species is still very widespread and extremely abundant despite fairly intense hunting pressures in parts of its range. It is expanding its range in places and is tolerant of secondary habitat.,Possibly Favourable,"Alces alces has a large range extending from Norway through northern and central Europe, northern Russia, Alaska, and Canada to Newfoundland (Canada) and Maine (USA) (Corbet 1978, Bauer and Nygrén 1999, Wilson and Ruff 1999). In Europe, it has a continuous distribution extending through Norway, Sweden, Finland, Russia, the Baltic states, Belarus, Poland and northern Ukraine. There was a small population in northern Austria which is now extinct (although there may still be occasional migrants). There are three isolated subpopulations in southern Czech Republic, and the species is occasionally recorded in Germany, Croatia, Hungary and Romania. It has been extending its range southwards along the rivers into the northern Caucasus lowlands. It ranges from sea level up to at least 1,500 m in Europe (H. Henttonen pers. comm. 2006), and up to 2,500m in the Altai mountains of Central Asia (Nygrén 1986).","It is a widespread and abundant species. Numbers have increased markedy in Scandinavia in recent decades, and the range is expanding in the Caucasus (EMA Workshop 2006). The global population is in the region of 1.5 million individuals, and the European population is in the order of 0.5 million. European populations show fluctuations over a multi-year cycle (Bauer and Nygrén 1999). Population estimates for European countries include the following: Czech Republic - maximum of 50 animals, Estonia - 10,000 individuals, Finland - at least 110,000 individuals (60-80,000 shot annually), Poland - 2,800 individuals, Sweden - 340,000 individuals (EMA workshop 2006, Ruusila and Kojola in press).","Alces alces is found in a range of woodland habitats, both coniferous and broadleaved, from the tundra and taiga southwards through boreal to temperate zones. It tends to prefer damp, marshy habitats and areas in close proximity to water. It is also found in open country in the lowlands and mountains, including farmland, if there is forest nearby. It thrives in secondary growth, and its population expansion in Scandinavia has been linked to the replacement of natural taiga forest by secondary woodland after logging (Bauer and Nygrén 1999). It feeds on vegetative parts of trees, shrubs, dwarf shrubs, herbs, and aquatic plants, and is a pest of agriculture and forestry in at least parts of its range (Ruusila and Kojola in press). The species has seasonal movements in parts of its range, particularly in northern Europe.","There are no major threats to this species at present. A wasting disease has been reported, and its causes remain poorly understood (Frank 2004), but it is not considered to be a serious problem for the species. Overexploitation caused significant population declines and range contractions in the 18th and 19th centuries, but since then populations have recovered (Ruusila and Kojola in press, Bauer and Nygrén 1999). In most European range states, populations are controlled to prevent damage to forestry and arable crops (Bauer and Nygrén 1999).","It is listed on Appendix III of the Bern Convention. It occurs in a large number of protected areas across its range (Wemmer 1998, EMA Workshop 2006). The species is subject to intense management in some countries through hunting quotas (e.g. in Finland: Ruusila and Kojola in press). It is protected under national legislation in a number of countries (e.g. Germany).","Heikki Henttonen, Andreas Kranz, Michael Stubbe, Tiit Maran, Alexei Tikhonov" +ANIMALIA,CHORDATA,MAMMALIA,CETARTIODACTYLA,CERVIDAE,Capreolus capreolus,,No,No,LC,,LC,,"European regional assessment: Least Concern (LC)EU 25 regional assessment: Least Concern (LC)A widespread and common species with no major threats. It is listed as Least Concern. However, subspecies C. c. italicus is rare (<10,000 mature individuals) and faces serious threats.",Possibly Favourable,"The roe deer has a large range in the Palaearctic. It is found throughout most of Europe (with the exception of Ireland, Cyprus, Corsica, Sardinia, Sicily, and most of the smaller islands), including western Russia (Stubbe 1999). Outside Europe, it occurs in Turkey, Syria, Iraq, Iran, and the Caucasus (Wilson and Reeder 2005). It is extinct in Israel and Lebanon (Wilson and Reeder 2005). It occurs from sea level to 2,400 m in the Alps (von Lehmann and Sägesser 1986).","It is widespread and common, and is expanding in many areas. Densities in the northern and southern parts of the range tend to be lower than in the central parts of the range. The central European population is estimated to number c.15 million individuals (EMA Workshop 2006). However, the endemic Italian subspecies C. c. italicus, which is largely restricted to southern Tuscany, probably numbers no more than 10,000 individuals and is at risk from hybridisation with introduced C. c. capreolus (Lorenzini et al. 2002)","It occupies a wide variety of habitats, including deciduous, mixed or coniferous forests, moorland, pastures, arable land, and suburban areas with large gardens. It prefers landscapes with a mosaic of woodland and farmland (Stubbe 1999). Roe deer are well adapted to modern agricultural landscapes (Sempéré et al. 1996).","The main threat in Europe is the increased mixing of various genetic stocks as a result of translocations. This may be a particular threat to genetically distinct peripheral populations, such as those in northern Portugal, the southern Italian Apennines, and Greece (Randi et al. 2004, Lorenzini and Lovari 2006). Molecular studies show that roe deer in central and southern Europe are mainly admixed (Lorenzini et al. 2002, Randi et al. 2004), indicating that human manipulation has greatly affected the natural genetic structure of populations. The small remaining population of C. c. italicus is also threatened by poaching and predation by feral dogs (Lorenzini et al. 2002)","The species is listed on the Bern Convention (Appendix III), and occurs in a large number of protected areas across its range. To protect remnant populations of the Italian roe deer C. c. italicus, Lorenzini et al. (2002) recommend the following measures: (1) Conduct research to determine the genetic struture of Italian roe deer, (2) Map extant populations of Italian roe deer, with indications of their genetic purity, (3) Prohibit translocations of roe deer from northern stocks to central and southern Italy, and vice versa, (4) Facilitate the expansion of remaining populations by reducing poaching and eliminating feral dogs, and (5) Establish a reintroduction plan for southern Italy. Similar actions are recommended to protect genetically distinct peripheral populations in Portugal and Greece. In general, any translocations of roe deer should respect the genetic integrity of populations at the destination site.","Juan Herrero, Jim Conroy, Tiit Maran, Giorgos Giannatos, Michael Stubbe, Stéphane Aulagnier" +ANIMALIA,CHORDATA,MAMMALIA,CETARTIODACTYLA,CERVIDAE,Capreolus pygargus,"This taxon was formerly considered a subspecies of the European roe deer Capreolus capreolus. Currently three subspecies are recognised: C. pygargus pygargus Pallas, 1771 (main part of the distribution area), C.p. tianschanicus Satunin, 1906 (southern parts) and C.p. bedfordi Thomas, 1908 (eastern parts).",No,No,LC,,NE,,European regional assessment: Least Concern (LC)EU 25 regional assessment: Not Evaluated (NE)A widespread and common species with no major threats. Assessed as Least Concern.,-,"The Siberian roe deer has a wide distribution in the Palaearctic. It is found in southern parts of Siberia and the Urals (to the Volga River in the west), the Russian Far East, and in the mountains of Middle Asia, Mongolia, and Northern and Eastern China. It has been recorded at altitudes of up to 3,300 m.",It is generally widespread and common across the whole distribution area. The population is stable; the species is a game animal.,"Inhabits different types of deciduous and mixed forests and forest-steppes. In summer it is solitary whereas in winter it aggregates into groups of up to 20-30 individuals. During the seasonal nomadic period it forms herds of up to 500 individuals. Polygamous, but does not form harems. Heat usually occurs from mid-July to mid-September; during this period males are territorial. Young are born in May-June; females give birth to one or two calves (rarely up to four).","There are no major threats to whole population. However, poaching might be a threat to the isolated population in the Cis-Caucasus.",The main conservation measures are regulation of hunting and maintenance of suitable habitats on hunting grounds. The majority of the Cis-caucasian population inhabits protected areas.,European Mammal Assessment team +ANIMALIA,CHORDATA,MAMMALIA,CETARTIODACTYLA,CERVIDAE,Cervus elaphus,"In North America, wapiti Cervus elaphus are sometimes called elk. However, in Europe the name elk refers to Alces alces (known in North America as moose). Genetic studies suggest that populations on Sardinia and Corsica are closely related to the north African subspecies C. e. barbarus (Ludt et al. 2004, Pitra et al. 2004), and some authors have suggested that C. e. barbarus should be treated as a distinct species (Pitra et al. 2004). These island populations may have been introduced by man in Holocene times (Hmwe et al. 2006).",No,No,LC,,LC,,"European regional assessment: Least Concern (LC)EU 25 regional assessment: Least Concern (LC)This species has a wide range. Population size has not been quantified, but it is not believed to approach the thresholds for the population size criterion of the IUCN Red List (i.e. less than 10,000 mature individuals in conjunction with appropriate decline rates and subpopulation qualifiers), as the species is described as common in at least parts of its range. There have been range contractions and presumably population declines in some parts of the species' European range, but it is not believed to approach the threshold for the population decline criterion of the IUCN Red List (i.e. declining more than 30% in ten years or three generations). For these reasons, it is evaluated as Least Concern. However, genetic mixing as a result of introductions of deer from different areas is a problem that should be addressed.",Possibly Favourable,"The red deer has a large global distribution extending from Europe and North Africa through central Asia, Siberia, the Far East and North America (Corbet 1978, Koubek and Zima 1999, Wilson and Ruff 1999). It is widely but somewhat patchily distributed throughout most of continental Europe, although it is absent from northern Fennoscandia and most of European Russia. It is present on a number of islands, including the British Isles and Sardinia. It is extinct in Albania. There are several small introduced subpopulations in Russia (all introduced into nature reserves for hunting) of unknown origin. There may be a small natural subpopulation at Kaliningrad in Russia just across the Polish border (A. Tikhonov pers. comm. 2006). In Greece, the small isolated subpopulations are the result of reintroductions into areas where it previously occurred. Likewise in Portugal all populations result from reintroduction or natural expansion from transborder Spanish populations which in turn were reintroduced. It occurs from sea level to above the tree line (c.2,500 m) in the Alps. The distribution is much more patchy and fragmented than the apparent continuity suggested by the distribution map.","It is a widespread and abundant species, although there is increasing fragmentation of populations in central Europe, and the species has been lost from some areas (EMA Workshop 2006). Typical population densities range from 2 to 10 individuals per km2 (up to c.25 per km2, higher figures in the literature almost certainly refer to fed populations: S. Lovari pers. comm. 2006). It is sufficiently abundant in some areas to be considered a pest in forestry plantations. In Germany there are reports of 60,000 animals hunted per year. The most recent records indicate a population size of 150,000-180,000 in Germany (M. Stubbe pers. comm. 2006). Subspecies C. e corsicanus, endemic to the islands of Sardinia and Corsica, is relatively rare but its numbers are increasing. It was reintroduced to Corsica in the 1970s and is found in three small subpopulations, estimated in 2005 to number no fewer than 5,000 individuals (S. Lovari in litt. 2006).","It inhabits open deciduous woodland, upland moors and open mountainous areas (sometimes above the treeline), natural grasslands, pastures and meadows (Koubek and Zima 1999). In woodland, its diet consists mainly of shrub and tree shoots, but in other habitats it also consumes grasses, sedges and shrubs.","The main threat is the intermixing of the various subspecies, including subspecies from North America (wapiti) and Asia, as well as hybridisation with sika deer Cervus nippon (Koubek and Zima 1999, EMA Workshop 2006). The introduction of animals from North America has also resulted in the spread of parasites and diseases to previously unaffected subpopulations (e.g. liver worms). Overhunting and habitat loss as a result of agricultural intensification and urbanisation are other pressures (Wemmer 1998), but they are not thought to pose a major threat to the species at present (EMA Workshop 2006).","It is protected under Appendix III of the Bern Covention. Subspecies C. e. corsicanus is strictly protected under Appendix II of the Bern Convention and Annexes II* and IV of the EU Habitats and Species Directive. It occurs in numerous protected areas across its range and also in protected areas outside its range where it has been introduced. To preserve the genetic integrity of local populations, it is important that the introduction of red deer from other areas is stopped, unless there is evidence that they belong to the same taxon (subspecies).Red deer in Europe have been affected to a large extent by translocations not only between far distant populations and different subspecies within the continent, but also by imported conspecifics from Central Asia and North America, and introduced Sika deer. As a result, most of the present deer populations of Europe are either known hybrids on a subspecific or even specific level or their breeding background is insufficiently known for excluding such a possibility. Systematic investigation into the history and the genetics of all European red deer populations is therefore needed as a base for establishing a European Red Deer Managment Plan. Part of this plan should be the identification of unpolluted autochthonous populations of this species and protection of their genetic integrity, thus preserving as much as possible of what is left of its natural variation. In this respect the following populations are important and should be given a high priority for conservation and research:Swedish Red Deer (C. e. elaphus)Red deer population of Skåne, Southern SwedenSubspecies C. e. elaphus with original distribution in central Europe and southern Scandinavia has its only remaining free-living population that is free from hybridization in Skåne, Sweden (Ahlén 1965, I. Ahlén pers. comm. 2007). Genetic studies have confirmed that there is no mixing with eastern European or wapiti genes that has affected all other populations in central Europe, Denmark and other parts of Sweden. In the official Swedish Red List produced in 2005 this subspecies was classified as VU (D1) (Gärdenfors 2005). Norwegian Red Deer (C. e. atlanticus)All red deer occurring in Norway still represent pure C.e. atlanticus, with the only exception being the isolated population on the Island of Otteroy, which has experienced an inflow of genes from introduced red deer from Germany (Ahlén 1965, Trense CIC pers. comm. to W. Frey).Scottish Red Deer (C. e. scoticus)Otago Mountains Red deer population, New ZealandThe red deer population of the Otago Mountains was established in 1871 with animals from Invermark Forest, Scotland, long before these could have been polluted through introductions from other sources. Unfortunately there are deer farms now all around the periphery of the Otago Mountains, from which animals escape from time to time. Red deer from the central sections of the range land however are still pure C.e. scoticus. This has been supported by the results of genetic investigations (Banwell pers. comm. to W. Frey). Banwell recommends that some of these animals pure bred animals should be removed before it is too late, and Frey suggested that an isolated population should be established in Great Britain with animals from this source, as according to Carne (2000) there is no red deer population left in Great Britain and Ireland that reliably represents pure C.e. scoticus (W. Frey pers. comm. 2006). Central European Red Deer (C. e. hippelaphus)Western populationsVosges Red deer populationThe population of the Vosges, presently numbering c.15,000 individuals, derives from an autochthonous relict population of some 200 head. Recent contacts to the neighbouring non-autochthonous population in Germany cannot be excluded. However if gene flow between both populations has already occurred, it is believed that this should have been in one direction only: from the Vosges population to the German population (Riffel pers. comm. to W. Frey). This assumption was strongly supported by extensive genetic investigations of the Vosges population (Hartl et al. 1991, Hartl pers. comm. to W. Frey). The genetic integrity of the Vosges population however is threatened in the longer term, if a pure transplant population is not established.Eastern populationsRed deer populations of Greece, Bulgaria and the European part of TurkeyThe red deer populations of Greece and Bulgaria have remained free from admixtures of foreign genes (Trense CIC pers. comm. to W. Frey), as has the population of the Belgrad Forest in Turkey (Can pers. comm. to W. Frey) Whilst there are about 29,000 red deer in Bulgaria (Chassovnikarova et al. 2003) very little is known about the status of the species in Greece, with the exception that the total number of individuals cannot be high and is concentrated in a few isolated populations. Clutton-Brock and Gill (1989) mentioned with reference to Papageorgiou that the red deer occurring on the Sithonia peninsula is in need of better protection and may deserve examination for possible sub-specific status.Red deer of the Italian peninsulaMesola Red Deer The Gran Bosco della Mesola Natural Reserve harbours the only autochthonous unmixed population of red deer in the Italian peninsula. The population size dropped to the historically lowest level of 10 animals in 1945-1947. In spring 1998 there were 59 individuals. Considering zoogeographical factors, this indigenous red deer may represent a separate subspecies (Mattioli 1990, Hmwe et al. 2006).Sardinian Red Deer (Cervus elaphus corsicanus)It is possible that the red deer of Sardinia and Corsica is descended from deer from mainland Italy that reached the island naturally during the Pleistocene. It is also possible that it was introduced by man in Holocene times (Hmwe et al. 2006). Genetic studies suggest that populations on Sardinia and Corsica are closely related to the north African subspecies C. e. barbarus (Ludt et al. 2004, Pitra et al. 2004). Iberian Red Deer (Cervus elaphus hispanicus)Iberian subspecies C.e. hispanicus might represent a relict of the red deer populations before the last Ice Age. The Coto Doñana red deer population represents pure C.e. hispanicus (Riffel pers. comm. to W. Frey), and there are probably more unmixed populations left of this subspecies (W. Frey pers. comm. 2006). Nevertheless, it is considered to be threatened by genetic introgression from introduced animals from other parts of Europe. There have been many introductions of allochthonous red deer by private landowners seeking to ""improve"" the antlers, only some of which have been documented. (Carranza et al. 2003).","Sandro Lovari, Juan Herrero, Jim Conroy, Tiit Maran, Giorgos Giannatos, Michael Stubbe, Stéphane Aulagnier" +ANIMALIA,CHORDATA,MAMMALIA,CETARTIODACTYLA,CERVIDAE,Dama dama,"Two subspecies; Dama dama dama (original range includes Turkey and possibly parts of south-eastern Europe, widely introduced) and D. d. mesopotamica (formerly found in Jordan, Israel, Lebanon, Iran and Iraq; now restricted to Iran, possibly Iraq, and Israel where it recently has been reintroduced) (Wemmer 1998, Bar-David et al. 2005).",No,No,LC,,LC,,"European regional assessment: Least Concern (LC)EU 25 regional assessment: Least Concern (LC)As a result of introductions by the Phoenicians, Romans, and Normans, it is a widespread and abundant species in Europe. Classed as Least Concern at the regional level. However, in its non-European native range this species is under serious threat.",Unknown,"A western Palaearctic species. Its original range includes the Near and Middle East and possibly parts of south-eastern Europe. It was introduced to the western Mediterranean by the Phoenicians, and to central and northern Europe by the Romans and Normans. More recently, it has been introduced to many countries worldwide (e.g. New Zealand, where it is considered a pest) (Apollonio 1999). In Portugal most of the specimens occur within confined areas, such as parks and private hunting areas, and apart from a few scattered individuals there is no wild population (Cabral et al. 2005).","Most introduced populations in Europe are stable (Apollonio 1999). However, in its native range outside Europe, this species has suffered severe declines and has disappeared from a number of countries where it was formerly found (Wemmer 1998).",A highly adaptable species that can survive in a wide range of habitats.,"There are no major threats to this species in Europe. In the species' native range outside Europe, hunting and habitat conversion for agriculture caused massive declines in the past, and habitat degradation continues to be a serious threat (Wemmer 1998).",Listed on Appendix III of the Bern Convention. Subspecies mesopotamica is listed on CITES Appendix I (as D. mesopotamica). Occurs in a number of protected areas.,European Mammal Assessment team +ANIMALIA,CHORDATA,MAMMALIA,CETARTIODACTYLA,CERVIDAE,Rangifer tarandus,"There are three subspecies: Finnish forest reindeer (Rangifer tarandus fennicus), Mountain reindeer (R.t. tarandus) and Svalbard reindeer (R.t. platyrhynchus). Populations of Snohetta, Rondane, Knutsho and Solnketten in Southern Norway represent the original wild mountain reindeer in reasonably pure form (Bevanger and Jordhoy 2004, Bevanger pers. comm. to W. Frey) These populations have had little contact with domestic reindeer whilst mixing of both forms has occurred to a larger extend in the populations of the Hardangervidda and others. Genetic investigations did not indicate any inflow of domestic genes into the four populations in question (Roed 1997, Roed pers. comm. to W. Frey). There are also populations of free roaming reindeer in Southern Norway that have been founded with domestic individuals. Unfortunately three of these – Ottadalsomrädet, Forollhogna and Solnkletten – are adjacent to the pure populations, thus constituting a permanent danger to their genetic integrity.",No,No,LC,,LC,,"European regional assessment: Least Concern (LC)EU 25 regional assessment: Least Concern (LC)The species is Least Concern at the European level. It is still fairly widespread and abundant in Norway, although there have been marked declines in the Russian, and parts of the Finnish, portions of the range. The only EU country that the reindeer occurs in is Finland. Although the Finnish population is small (c.2,200 individuals), and although there have been recent declines in the western subpopulation, overall numbers are increasing. Consequently the species is classed as Least Concern. Wild reindeer went extinct in Finland last century, and ongoing conservation action is required to ensure continuing recovery.The Novaya Zemlya subspecies pearsoni is Endangered under C2a(ii). The population is less than 1,000 mature individuals, found on a single subpopulation on an isolated island, which is undergoing continuing decline (the reason for which is currently unknown). The Svalbard subspecies platyrhynchus is Least Concern. Although it has a small population of c.10,000, it is not declining and there are no major threats.",Unknown,"The reindeer has a circumpolar distribution in the tundra and taiga zones of northern Europe, Siberia, and North America (Corbet 1978, Hall 1981, Koubek and Zima 1999, Wilson and Ruff 1999). In Europe, wild populations have a fragmented distribution in Norway (including the island of Svalbard, where there is a separate subspecies R. t. platyrhynchus), Finland, and Russia (including the island of Novaya Zemlya, which also has an endemic subpecies R. t. pearsoni) (Herre 1986, Koubek and Zima 1999). In Finland, wild reindeer occur in two isolated subpopulations, one in the west and one in the east. Semi-domesticated reindeer are widespread in Lappland, and a feral population has historically become established on Iceland (Koubek and Zima 1999); these populations are not shown on the distribution map. It occurs from sea level to at least 2,000 m in Norway (Herre 1986).","There are approximately 30,000 wild reindeer in southern Norway and 10,000 in Svalbard (Andersen and Hustad 2004). The population trend in Norway is believed to be stable, and hunting is controlled. In Finland, forest reindeer (subspecies R. t. fennicus) were driven extinct in the early 1900s, but are now starting to recover as a result of animals moving in from Karelia in Russia and from some captive bred stock that were released (Ruusila and Kojola in press). Forest Reindeer remain very rare in Finland (about 1,200 in the eastern subpopulation and 1,000 individuals in the western subpopulation). The Finnish population trend is difficult to determine, as the population in eastern Finland has expanded rapidly from c. 40 reintroduced individuals in 1980 to c.1,200 today, whereas the western subpopulation has declined from c.1,800 to c.1,000 during 2001-2006 (although in the last few years prior to 2001 it had been increasing) (H. Henttonen pers. comm. 2006, Ruusila and Kojola in press). Overall, the current Finnish population trend is one of growth rather than decline. Numbers in European Russia are very low with presumed ongoing declines, and the reindeer is now absent from large tracts of tundra and taiga. It is not known whether the small Kola Peninsula population in Russia is derived from autochthonous wild reindeer or from semidomesticated animals (A. Tikhonov pers. comm. 2006). The Novaya Zemlya subspecies pearsoni has a small population (less than 1,000 mature individuals), which is undergoing continuing decline (A. Tikhonov pers. comm. 2006). The reindeer's status in Asia is poorly known, although it is significantly more abundant there than in Europe, with a population estimated at 400,000 in the 1950s (Koubek and Zima 1999). There are also large numbers of reindeer (locally known as caribou) in North America. The feral population in Iceland numbers c.1000, and there are approximately 0.5 million semi-domesticated reindeer in Lappland (H. Henttonen pers. comm. 2006).","It inhabits arctic and subarctic tundra, open montane habitats, and open woodland, where it feeds on lichens, mosses, grasses, and shoots and leaves of deciduous shrubs and trees (especially willow Salix spp. and birch Betula spp.). In North America it is a migratory species, making seasonal movements from the coast in summer to the interior in winter, but in Europe reindeer are more sedentary (Herre 1986).","Poaching is a major threat in the Russian Federation (A. Tikhonov pers. comm. 2006). The causes of decline of the Novaya Zemlya subspecies pearsoni are not known (A. Tikhonov pers. comm. 2006). Loss of habitat in Finland (through logging) may pose problems, and there is increased disturbance to the species in some areas due to winter sporting activities. Hybridization with semidomesticated reindeer is a potential problem for some subspecies and subpopulations (H. Henttonen pers. comm. 2006, Ruusila and Kojola in press).","It is listed on Appendix III of the Bern Convention. Subspecies R. t. fennicus is strictly protected under Annex II of the EU Habitats and Species Directive. In eastern parts of Russia there are strict anti-hunting measures in place, but there is continued poaching (A. Tikhonov pers. comm. 2006). Hunting in Norway is also strictly controlled. In Finland, a large fence has been constructed between areas occupied by semidomesticated reindeer and forest reindeer, to prevent hybridisation (Koubek and Zima 1999, H. Henttonen pers. comm. 2006). Research is urgently required to determine the causes of population decline of R. t. pearsoni on Novaya Zemlya, and to identify appropriate conservation actions.","Heikki Henttonen, Alexei Tikhonov" +ANIMALIA,CHORDATA,MAMMALIA,CETARTIODACTYLA,DELPHINIDAE,Delphinus delphis,"Until 1994, all common dolphins around the world were classified as a single species, Delphinus delphis. However, it is now known that at least two species exist within the genus: the short-beaked (D. delphis) and long-beaked (D. capensis) common dolphins (Heyning and Perrin 1994). There is also a distinct short-beaked form in the Black Sea, the taxonomic status of which has not been adequately clarified (although it is currently thought to be a subspecies, D. delphis ponticus: Amaha 1994).",No,No,DD,,DD,,"This species has a varying status in different parts of its European range. In the Mediterranean and Black seas there have been substantial population declines; the Mediterranean population was recently assessed as Endangered (A2abc), and the Black Sea subspecies D. d. ponticus was also classed as Endangered (A1d)(Reeves and Notarbartolo di Sciara 2006). However in the eastern North Atlantic there are very large populations that show no evidence of significant decline, and the species is Least Concern in this area. Overall in the European Mammal Assessment region, it is not possible to quantify the population trend because the relative size of the different subpopulations is not known. Consequently the species is assessed as Data Deficient at the European regional level.",Unknown,"The short-beaked common dolphin is an oceanic species that is widely distributed in tropical to cool temperate waters of the Atlantic and Pacific oceans (Perrin 2002), from nearshore waters to thousands of kilometers offshore. It regularly occurs in some enclosed seas, such as the Okhotsk Sea and Sea of Japan, and separate subpopulations apparently exist in the Mediterranean and Black seas. Short-beaked common dolphins may occur in parts of the Indian Ocean around southeast Africa and southern Australia, but previous records of this species in other parts of the Indian Ocean and in waters of Taiwan and are now thought to have been long-beaked common dolphins D. capensis (Jefferson and Van Waerebeek 2002).","This is a very abundant species, with many available estimates for the various areas where it occurs. In the Atlantic, abundance in European continental shelf waters was estimated at 63,400 (95%CI=27,000-149,000) in 2005 (SCANS-II project: P. Hammond pers. comm. 2007). Offshore, abundance in a block bounded by 53-57ºN and 18-29ºW has been estimated at 273,000 (95%CI=153,000-435,000) in 1995 (Cañadas et al. in press). West of the Bay of Biscay, 62,000 common dolphins were estimated in the fishing grounds of the albacore tuna driftnet fishery in 1993 (Goujon 1996). In the western North Atlantic, 121,000 (CV=0.23) were estimated (Waring et al. 2006).In the western Mediterranean, abundance has been estimated at 19,400 (95%CI=15,300-22,800) in the northern Alborán Sea between 2000 and 2004 (Cañadas 2006). Once one of the most common species in the Mediterranean Sea, the short-beaked common dolphin has experienced a generalized and major decline during the last 30-40 years (Bearzi et al. 2003). Dramatic negative trends were recorded in portions of the central Mediterranean, particularly in the northern Adriatic Sea and in the eastern Ionian Sea (Bearzi et al. 2004, 2006). Recent genetic studies indicate that population structure within the Mediterranean reflects differences in distribution pattern and habitat use by short-beaked common dolphins in the eastern (where the species is predominantly coastal) and western (where it is predominantly pelagic) portions of the basin (Natoli 2004). Genetic exchange between short-beaked common dolphins from the Mediterranean Sea and Atlantic Ocean, to the extent that it occurs, appears to involve predominantly animals from the Alborán Sea (Natoli 2004). The population size in the Black Sea is unknown. Line transect surveys have been conducted recently to estimate common dolphin abundance in a few parts of the range. The survey areas are small relative to the total range of the subspecies. Results suggest that current population size is at least several 10,000s, and possibly 100,000 or more (Birkun 2006). By the mid 1960s, the Black Sea subpopulation collapsed due to long-running overexploitation and a reduction of 70% was inferred. However, directed takes continued until 1983 when cetacean hunting finally ceased. The population has not recovered (Birkun 2006).","Short-beaked common dolphins appear to have a preference for upwelling-modified waters, areas with steep sea floor relief, and extensive shelf areas, but they are widespread in warm temperate and tropical waters (see Evans 1994). In the eastern tropical Pacific, they prefer equatorial and subtropical waters with a shallow thermocline, relatively large seasonal changes in surface temperature, and seasonal upwelling (Reilly 1990, Fiedler and Reilly 1994). Mediterranean common dolphins frequent coastal and upper slope waters (Bearzi et al. 2003). In the Black Sea, common dolphins are distributed mainly offshore and visit shallow coastal waters following seasonal aggregations and regular mass migrations of small pelagic fishes such as anchovy and sprat (Birkun 2006). Black Sea common dolphins avoid waters with low salinity, and this may explain why they do not occur in the Sea of Azov and in the Kerch Strait. Associations with other marine mammal species are common. Mixed-species groups of common dolphins, striped dolphins (Stenella coeruleoalba) and Risso's dolphins (Grampus griseus) have been observed frequently in the pelagic waters of the Gulf of Corinth, Greece (Frantzis and Herzing 2002). The prey of common dolphins consists largely of small schooling fishes and squids (Perrin 2002). Reproduction is seasonal, with the exception of the Central population in the eastern tropical Pacific, which breeds throughout the year (Danil and Chivers 2007).","The common dolphin is one of the most prominent by-catches of pelagic purse-seine and driftnet, and trawl fisheries. Incidental capture of common dolphins in European Atlantic fisheries has been well studied in recent years, and as a result of recent EU legislation, on-board observer programmes are being carried out in most of the fisheries considered to have a potentially significant bycatch of common dolphins. Northridge (2006) showed that bycatches of common dolphins in European pelagic trawl fisheries probably total around 800 animals per year in UK and French pelagic trawl fisheries for sea bass. Annual catch rates in the UK sector of this fishery have been falling in recent years (Northridge 2006) and the annual average total mortality (2000-2006) is 170 animals in this sector. Other bycatches in the same area are known to occur in gill nets, tangle nets and possibly other fisheries (Northridge 2006). The main factors thought to have contributed, singly or in synergy, to the decline of Mediterranean short-beaked common dolphins include: 1) incidental mortality in fishing gear, especially driftnets, 2) reduced availability of prey caused by overfishing and habitat degradation, 3) contamination by xenobiotic chemicals resulting in immunosuppression and reproductive impairment, and 4) environmental changes such as increased water temperatures affecting ecosystem dynamics (Bearzi et al. 2003, 2006). A recent survey focusing on the Moroccan driftnet fishing fleet estimated that about 12,000-15,000 dolphins are killed annually around the Strait of Gibraltar (Tudela et al. 2005).At least 840,000 dolphins were taken from the Black Sea from 1946 until a ban of small cetacean hunting was declared in Turkey in 1983. The take was certainly much greater because that value did not incorporate catch statistics from Romania (whole period), Turkey (before 1976 and after 1981) and Bulgaria (before 1958) (Birkun 2006). Reduced prey availability is considered to be a major ongoing threat to Black Sea common dolphins (Bushuyev 2000). Of two mass mortality events that killed an unknown but certainly large number of common dolphins in 1990 and 1994 (Krivokhizhin and Birkun 1999), the latter was recognised as the result of a morbillivirus epizootic. However, both die-offs coincided with a drastic (8 to 12 fold) decline in the abundance of the two main common dolphin prey species, anchovy and sprat. Such a reduction was caused by a combination of overfishing, eutrophication and the explosive increase of the introduced ctenophore Mnemiopsis leidyi. Correlation between large die-offs of Black Sea common dolphins and prey scarcity suggests that reduced prey availability increases susceptibility to viral infection (Birkun 2006).","The common dolphin is included in EC Directive No.92/43/EEC on the conservation of natural habitats of wild fauna and flora; D. delphis is listed on Annex IV (Animal and Plant Species of Community Interest in Need of Strict Protection).MediterraneanA large Marine Sanctuary for cetaceans in the Corso-Ligurian Basin has been declared by the Governments of Italy, France and Monaco. Other smaller marine protected areas exist or have been proposed throughout the Mediterranean Sea (Bearzi et al. 2003). While these types of designations may benefit common dolphins at least indirectly, measures to provide direct benefits, e.g., area-, season-, or fishery-specific reductions in fishing effort, curtailment of inputs of particular pollutants, etc., remain to be identified and implemented. The Agreement on the Conservation of Cetaceans in the Black Sea, Mediterranean Sea and Contiguous Atlantic Area (ACCOBAMS 2002) considers the Mediterranean common dolphin as an endangered population. It is expected that efforts to increase understanding of ongoing threats, monitor status, and provide needed protective measures on behalf of the dolphins and their habitat will be organized and implemented through ACCOBAMS. The current ban on driftnet fishing in the Mediterranean should be implemented and enforced as a matter of priority.Black SeaCommercial killing of Black Sea common dolphins, as well as other Black Sea cetaceans, was banned in 1966 in the former USSR, Bulgaria and Romania, and in 1983 in Turkey. The Strategic Action Plan for the Rehabilitation and Protection of the Black Sea (1996) envisages some special cetacean-oriented conservation and research actions, and a regional Conservation Plan for Cetaceans in the Black Sea has been drafted in accordance with the ACCOBAMS International Implementation Priorities for 2002-2006 (Notarbartolo di Sciara 2002). On a national level, Black Sea cetaceans, including common dolphins, are protected by environmental legislation and governmental decrees. Action plans for the conservation of Black Sea cetaceans were produced in Ukraine (2001) and Romania (2003) but they have no legal effect at present (Reeves and Notarbartolo di Sciara 2006).",Species account by IUCN SSC Cetacean Specialist Group; regional assessment by European Mammal Assessment team +ANIMALIA,CHORDATA,MAMMALIA,CETARTIODACTYLA,DELPHINIDAE,Globicephala melas,,No,No,DD,,DD,,"This species is widespread (thus not qualifying as threatened under criterion B) and relatively abundant (above the thresholds for criteria C and D). Population trend data for this species are unavailable. Primary threats that could cause widespread declines include entanglement in fisheries and competition with squid fisheries. The combination of potential declines driven by competition with fisheries for squid and bycatch in fisheries is believed sufficient that a 30% global reduction over three generations or in this case 60 years could not be ruled out. Therefore, the species is classed as Data Deficient. The Mediterranean population was also recently assessed as Data Deficient (Reeves and Notarbartolo di Sciara 2006).",Unknown,"Long-finned pilot whales occur in temperate and subpolar zones (Olson and Reilly 2002). They are found in oceanic waters and some coastal waters of the North Atlantic Ocean, including the Mediterranean Sea and North Sea. In the North Atlantic, the species occurs in deep offshore waters, including those inside the western Mediterranean Sea (where is thought to be the only species of pilot whale found there), North Sea, and Gulf of St. Lawrence (Abend and Smith 1999). Long-finned pilot whales tend to follow their prey (squid and mackerel) inshore and into continental shelf waters during the summer and autumn (Reeves et al. 2003). In the western North Atlantic, they occur in high densities over the continental slope in winter and spring months. In summer and autumn months, they move over the shelf. Long-finned pilot whales were previously found in the western North Pacific as well, but appear to be absent there today. The circum-antarctic subpopulation(s) in the Southern Hemisphere occur as far south as the Antarctic Convergence, sometimes to 68°S. They are apparently isolated from those of the Northern Hemisphere (Bernard and Reilly 1999).","There is little information on stocks within the species (Donovan et al. 1993). In the north-eastern Atlantic the number of pilot whales inhabiting the area between East Greenland, Iceland, Jan Mayen, Faroe Islands and off the western coasts of the British Islands and Ireland was estimated at around 778,000 (CV=30%) by Buckland et al. (1993). The removals by drive hunting at the Faroes (see below) have therefore been considered sustainable (NAMMCO 2000, Reeves et al. 2003).","Long-finned pilot whales are highly social; they are generally found in pods of about 20-100, but some groups contain over 1,000 individuals. These large pods are generally dispersed in smaller subgroups of 10-20. Based on photo-identification and genetic work, pilot whales appear to live in relatively stable, maternally-based pods like those of killer whales, and not in the fluid groups characteristic of many smaller dolphins.This is one of the species most often involved in mass strandings (Olson and Reilly 2002). Strandings are fairly frequent, for instance, on Cape Cod (Massachusetts, USA) beaches from October to January. Their tight social structure also makes pilot whales vulnerable to herding, and this has been taken advantage of by whalers in drive fisheries off Newfoundland, the Faroe Islands, and elsewhere. Primarily squid eaters, pilot whales will also take small medium-sized fish, such as mackerel, when available (Gannon et al. 1997). Other fish species taken include cod, turbot, herring hake, and dogfish. They will sometimes also ingest shrimp. Pilot whales are deep divers, most feeding appears to take place at depths of 200-500 m.","Drive fisheries for long-finned pilot whales in the Faroe Islands date back to the Norse settlement in the 9th century. Catch statistics exist from the Faroes since 1584, unbroken from 1709-today, show an annual average catch of 850 pilot whales (range: 0 - 4,480) with a cyclic variation according to the North-Atlantic climatic variations (Bloch and Lastein 1995). This level of offtake has been considered sustainable (NAMMCO 2000, Reeves et al. 2003).Incidental catches are reported from Newfoundland, the Mediterranean and the Atlantic coast of France. In British waters, long-finned pilot whales are accidentally caught in gillnets, purse seines and in trawl fisheries. A 1990 workshop to review mortality of cetaceans in passive nets and traps documented an annual kill of 50-100 G. melas off the Atlantic coast of France. Furthermore, pilot whales are also known to be taken incidentally in swordfish driftnets in the Mediterranean (Olson and Reilly 2002). Although there is considerable controversy regarding the absolute level of declines, there is good evidence of large-scale reductions in many predatory fish populations (e.g. Baum et al. 2003, 2005; Sibert et al. 2006; Polacheck 2006) and over-fishing and collapse of several important “prey” fish stocks world-wide (e.g. Jackson et al. 2001). The effects of such fish population reductions and subsequent ecosystem changes on world-wide populations of long-finned pilot whales are unknown but could result in population declines. Commercial fisheries for squids are widespread in the western North Atlantic. Target species for these fisheries are squids eaten by pilot whales, again raising the possibility of prey depletion. Long-finned pilot whales off the Faroes, France, UK and the eastern USA appear to have high levels of DDT and PCB in their tissues. Heavy metals such as cadmium and mercury also have been found in pilot whales from the Faroes. Because these contaminants accumulate in tissues over time, older animals and especially adult males tend to have the highest concentrations (Caurant and Amiard-Triquet 1995). Evidence from stranded individuals of several similar species of beaked whales indicates that they have swallowed discarded plastic items. Sometimes this may happen when animals are already ill and incapable of finding/catching normal prey (e.g. Gomercic et al. 2006), or they may be healthy and eat it by accident and it then contributes to blockage of the digestive tract and eventual death (e.g. Scott et al. 2001). Globicephala melas may also be at risk.While impacts of high levels of anthropogenic sound have been well documented for beaked whales (Simmonds and Lopez-Jurado 1991, Frantzis 1998, Balcomb and Claridge 2001, US Dept of Commerce and US Navy 2001, Jepson et al. 2003, Fernandez et al. 2005), there are examples for a number of other species of odontocetes of potential impacts. While conclusive evidence of cause and effect are often lacking, strong avoidance reactions, embayments or mass stranding events have been spatially and temporally associated with high levels of anthropogenic sound for short-finned pilot whales (Hohn et al. 2006), killer whales, melon-headed whales (Southall et al. 2006), Atlantic spotted dolphin (Balcomb and Claridge 2001), striped dolphins, dwarf sperm whales (Hohn et al. 2006), pygmy sperm whales, and Dall’s porpoise (Balcomb pers. comm.). As such, it should be recognized that high levels of anthropogenic sound have the potential to impact other deep diving odontocete species. Predicted impacts of global climate change on the marine environment may affect long-finned pilot whales, and may induce changes in the species’ range, abundance and/or migration patterns (Learmonth et al. 2006).","The North and Baltic Sea subpopulations have been listed in Appendix II of the Convention on Migratory Species. One of the areas with regular confirmed presence of long-finned pilot whales in the Mediterranean, the western section of the Ligurian Sea, is included within the marine Sanctuary dedicated to cetaceans in the Corso-Ligurian Basin, created by the Governments of Italy, France and Monaco (Pelagos Sanctuary, SPAMI). No management or conservation measures have been taken as yet specifically for the conservation of this species.A SPAMI (Specially Protected Area of Mediterranean Importance) under the Barcelona Convention has been proposed for the northern half of the Alborán Sea and Gulf of Vera in southern Spain (Cañadas et al. 2005), but it has not yet been designated or even evaluated by the Spanish administration. This proposed area includes the “hot-spots” for long-finned pilot whales in the Mediterranean.",Species account by IUCN SSC Cetacean Specialist Group; regional assessment by European Mammal Assessment team +ANIMALIA,CHORDATA,MAMMALIA,CETARTIODACTYLA,DELPHINIDAE,Grampus griseus,,No,No,DD,,DD,,"Risso’s dolphin is widely distributed in temperate and tropical waters worldwide but little is known about the species. Estimates of abundance are available for only a few regions and details of distribution are generally lacking. Population trend data for this species are unavailable. Primary threats that could cause widespread declines include entanglement in fisheries and competition with squid fisheries. The combination of potential declines driven by competition with fisheries for squid and bycatch in fisheries is believed sufficient that a 30% global reduction over three generations or in this case 60 years could not be ruled out. Therefore, the species is classed as Data Deficient. The Mediterranean population was also recently assessed as Data Deficient (Reeves and Notarbartolo di Sciara 2006).",Unknown,"This is a widely-distributed species, inhabiting primarily deep waters of the continental slope and outer shelf (especially with steep bottom topography), from the tropics through the temperate regions in both hemispheres (Kruse et al. 1999). They also occur in some oceanic areas, beyond the continental slope, such as in the eastern tropical Pacific. They are found from Newfoundland, Norway, the Kamchatka Peninsula, and Gulf of Alaska in the north to the tips of South America and South Africa, southern Australia, and southern New Zealand in the south. Their range includes many semi-enclosed bodies of water, such as the Gulf of Mexico, Gulf of California, Red Sea, Persian Gulf, Sea of Japan, and Mediterranean Sea.","There are no regional estimates of abundance for this species. Although Risso’s dolphins are regularly sighted in the western Mediterranean, they are considered scarce (Reeves and Notarbartolo di Sciara 2006). Line-transect abundance estimates for the western central Mediterranean in 2001-03 gave 493 Risso’s dolphins (95% C.I. 162-1,498) in an area of 32,270 km2 (Gómez de Segura et al. 2006).","Risso’s dolphins inhabit deep oceanic and continental slope waters, generally 400-1000 m deep (Jefferson et al. 1993, Baird 2002), mostly occurring seaward of the continental slope. They frequent subsurface seamounts and escarpments, where they are thought to feed on vertically migrant and mesopelagic cephalopods. Currents and upwelling causing local increases in marine productivity may enhance feeding opportunities, resulting in the patchy distribution and local abundance of this species worldwide (Kruse et al. 1999). Most records of this species in Britain and Ireland are within 11 km of the coast. Risso's dolphins feed on crustaceans and cephalopods, but seem to prefer squid. Squid bites may be the cause of at least some of the scars found on the bodies of these animals. In the few areas where feeding habits have been studied, they appear to feed mainly at night.","In the Mediterranean Sea, Risso’s dolphins are among the cetacean species frequently found entangled infishing nets. Bycatches in longlines and gillnets have been reported in Spain (Valeiras and Camiñas 2001) and Italy (Notarbartolo di Sciara 1990). Sound pollution is a threat to deep-diving pelagic cetaceans, including Risso’s dolphins. Evidence consistent with a syndrome related to exposure to high-intensity sonar has been described in this species in the UK (Jepson et al. 2005). Risso’s dolphins in the Mediterranean have been found to carry substantial contaminant burdens (see references in Reeves and Notarbartolo di Sciara 2006).",The North and Baltic Sea subpopulations are included in Appendix II of the Convention on Migratory Species.,Species account by IUCN SSC Cetacean Specialist Group; regional assessment by European Mammal Assessment team +ANIMALIA,CHORDATA,MAMMALIA,CETARTIODACTYLA,DELPHINIDAE,Lagenodelphis hosei,,No,No,NA,,NA,,This species is assessed as Not Applicable as it is a vagrant in the European Mammal Assessment region.,-,"The exact distribution of this species is poorly known. Fraser's dolphin has a pantropical distribution, largely between 30°N and 30°S in all three major oceans (Jefferson and Leatherwood 1994, Dolar 2002). Strandings in temperate areas may represent extralimital forays connected with temporary oceanographic anomalies such as the world-wide El Niño phenomenon in 1983-84, during which a mass stranding occurred in France (Perrin et al. 1994). Bones et al. (1998) reported on a stranding on the coast of Scotland.",This species does not appear to be particularly abundant anywhere (with the possible exception of some areas in the Philippines).,"It is an oceanic species that prefers deep offshore waters, but it can be seen near shore in some areas where deep water approaches the coast (Perrin et al. 1994). Fraser's dolphins feed on midwater fish (especially myctophids), squid, and crustaceans (Dolar et al. 2003). Physiological studies indicate that Fraser’s are capable of quite deep diving (and it is thought that they do most of their feeding deep in the water column in waters up to 600 m deep), but they have been observed to feed near the surface as well (Watkins et al. 1994).","This species very seldom occurs in European waters, and there are no known major threats in the region.",There are no conservation measures for this species in the European region.,Species account by IUCN SSC Cetacean Specialist Group; regional assessment by European Mammal Assessment team +ANIMALIA,CHORDATA,MAMMALIA,CETARTIODACTYLA,DELPHINIDAE,Lagenorhynchus acutus,,No,No,LC,,LC,,"The species is widespread and abundant and there have been no reported population declines, therefore the Atlantic white-sided dolphin is currently considered to be of Least Concern.",Possibly Favourable,"Atlantic white-sided dolphins are found in cold temperate to subpolar waters of the North Atlantic, from about 38°N (south of Cape Cod) in the west and the Brittany coast of France in the east, north to southern Greenland, Iceland, and southern Svalbard (Reeves et al. 1999, Cipriano 2002). The range includes the U.K. and the northern coasts of Scandinavia, although they rarely enter the Baltic Sea. They also sometimes move quite far up the Saint Lawrence River of eastern Canada, and they have been seen as far south as Strait of Gibraltar (Hashmi and Adloff 1991, 1992).","This species is quite abundant throughout its range.There are an estimated 51,640 (CV=38%) Atlantic white-sided dolphins off the eastern North American shoreline (Waring et al. 2006), and about 96,000 (CV=54%) off the west coast of Scotland (MacLeod 2004). There is currently little evidence for separate subpopulations (Mikkelsen and Lund 1994).","Atlantic white-sided dolphins are found primarily in waters of the continental shelf and slope, but they also occur in oceanic waters across the North Atlantic. Along the continental slope of North America, they seem to associate with high sea-bed relief along the continental shelf (Palka et al. 1997). Calves are born over an extended period around the summer season, with apparent peaks in June and July. These dolphins often associate and feed with large baleen whales (fin and humpback whales), and are known to form mixed groups with pilot whales and a number of other dolphin species (including bottlenose and white-beaked dolphins). Atlantic white-sided dolphins feed mostly on small schooling fish (such as herring, mackerel, cod, smelt, hake, and sandlance), shrimp, and squid.","Some hunting for this species occurred in the past, especially in Norway. Some dolphins are still taken in Greenland, the Faroe Islands, and eastern Canada (Jefferson et al. 1993, Reeves et al. 1999). Recent catches in Faroe Islands were 333 and 310 in 2004 and 2005, respectively (NAMMCO Annual Report 2005). Incidental mortality in fishing gear has been documented off Canada, the United States, the United Kingdom and Ireland. Gaskin (1992) judged Atlantic white-sided dolphins to be less vulnerable to capture in pelagic near-surface drift nets and fixed groundfish gill nets than are many other small cetaceans. They may, however, be especially susceptible to capture in midwater trawl nets (Addink et al. 1997). Substantial numbers have been bycaught in pelagic trawl fisheries for horse mackerel and mackerel south-west of Ireland (Reeves et al. 1999). Like other North Atlantic marine mammals, Atlantic white-sided dolphins are contaminated by organochlorines, other anthropogenic compounds and heavy metals (Reeves et al. 1999); although the effects of pollutants are not well understood in this species, they may affect reproduction or render them susceptible to other mortality factors","Existing direct takes are currently not regulated by any hunting quotas. Operational difficulties in observing bycatch and potentially significant annual fluctuation in catch rates warrant further observer studies of these and other trawl fisheries (Morizur et al. 1999, NMFS Stock Assessment Report: Atlantic and Gulf of Mexico). The impact of combined anthropogenic removals should be assessed.",Species account by IUCN SSC Cetacean Specialist Group; regional assessment by European Mammal Assessment team +ANIMALIA,CHORDATA,MAMMALIA,CETARTIODACTYLA,DELPHINIDAE,Lagenorhynchus albirostris,,No,No,LC,,LC,,The species is widespread and abundant and there have been no reported population declines or major threats identified; therefore white-beaked dolphin is currently considered to be of Least Concern.,Possibly Favourable,"This is the most northerly member of the genus Lagenorhynchus, and it has a wide distribution (Kinze 2002). White-beaked dolphins inhabit cold temperate to subpolar waters of the North Atlantic, from Cape Cod and Portugal, north to central Davis Strait, southern Greenland, Svalbard, and east to Novaya Zemlya. The range includes Iceland, Faroe Islands, the U.K., and most Scandinavian waters (but apparently does not include the Baltic Sea, although there are a few extralimital records there).","Lagenorhynchus albirostris is reasonably abundant. There are few actual estimates of abundance, but there may be a hundred thousand or more throughout their range (Øien 1996, Reeves et al. 1999).At least a few thousand white-beaked dolphins inhabit Icelandic waters and up to 100,000 are found in the northeastern Atlantic including the Barents Sea, the eastern part of the Norwegian Sea and the North Sea north of 56°N (Øien 1996). A survey of the North Sea and adjacent waters in 1994 provided an estimate of 7,856 (CV=0.30) white-beaked dolphins (Hammond et al. 2002). In 2005 there were an estimated 22,700 (CV=0.42) in the European Atlantic continental shelf waters, including 10,600 (CV=0.29) in the same area surveyed in 1994 (P. Hammond pers. comm. 2007). Kinze et al. (1997) maintained that the white-beaked dolphin is much more common in the North and Baltic Seas than its relative, the Atlantic white-sided dolphin and Northridge et al. (1997) found that white-beaked dolphins are relatively common in European waters compared with white-sided dolphins, or compared with US waters.","White-beaked dolphins inhabit continental shelf and offshore waters of the cold temperate to subpolar zones, although there is evidence suggesting that their primary habitat is in waters less than 200 m deep. The species is found widely over the continental shelf, but especially along the shelf edge. A change in habitat use has been documented in U.S. waters, where white-beaked dolphins were observed primarily on the continental shelf prior to the 1970s, but mainly occurred over slope waters during the 1970s. This shift was associated with changes in finfish abundance and a shift in the distribution of Atlantic white-sided dolphins, L. acutus (Katona et al. 1993, Kenney et al. 1996). The ecology of white-beaked dolphins has received little detailed study (Kinze 2002). Calving peaks in summer to early autumn (May to September), but not much else is known about reproduction in this species (Reeves et al. 1999). White-beaked dolphins feed on variety of small pelagic schooling fishes, but also demersal species (such as cod, haddock, poorcod, bib, hake, and whiting), squid, and crustaceans (for review, see Reeves et al. 1999). They sometimes associate, while feeding, with large whales (such as fin and humpback whales), and are known to form mixed groups with a number of other dolphin species (including bottlenose and Atlantic white-sided dolphins) (Reeves et al. 1999).","Although not a target of any large commercial fisheries, there has been a long history of small-scale hunting for white-beaked dolphins in some countries, such as Norway, the Faroe Islands, Greenland, Iceland, and Labrador, mostly for food (Reeves et al. 1999); hunting in some areas continues today (Jefferson et al. 1993), e.g. some hunting continues off the south-west coast of Greenland (Kinze 2002) and opportunistically off the coast of Canada (Lien et al. 2001). During the early 1980s an estimated 366 white-beaked dolphins were taken annually by the residents of 12 Labrador harbours (Alling and Whitehead 1987). White-beaked dolphins are known to be taken in a range of fishing gear throughout the range of the species (Dong et al. 1996, Reeves et al. 1999). In Norwegian waters where the species is abundant and fishery effort is high, bycatches of white-beaked dolphins are too rare to be detected in fishery operations monitored for marine mammal bycatches (A. Bjørge pers. comm. 2006). In the UK bycatch observer programme, no white-beaked dolphins have been recorded (S. Northridge pers. comm. 2006). Thus, recent bycatch monitoring programmes support the conclusion of Jefferson et al. (1993) that although known to be occurring, incidental catches are not thought to be high enough to represent a serious threat to this species.Like other North Atlantic marine mammals, white-beaked dolphins are contaminated by organochlorines, other anthropogenic compounds and heavy metals (Reeves et al. 1999); although the effects of pollutants are not well understood in this species, they may affect reproduction or render them susceptible to other mortality factors.","Existing direct takes are currently not regulated by any hunting quotas. Although known to occur, bycatch rates seem to be poorly documented and warrant more intensive research. The impact of combined anthropogenic removals should be assessed.",Species account by IUCN SSC Cetacean Specialist Group; regional assessment by European Mammal Assessment team +ANIMALIA,CHORDATA,MAMMALIA,CETARTIODACTYLA,DELPHINIDAE,Orcinus orca,"Killer whales are presently considered to form a single cosmopolitan species, Orcinus orca (Rice 1998). Separate species status has been suggested for different morphological forms found in the southern Ocean (Mikhalev et al. 1981, Berzin and Vladimirov 1983, Pitman and Ensor 2003). Pitman et al. (2007) describe one of these as a dwarf form of killer whale. Killer whales in the eastern North Pacific are known to consist of at least two and maybe three distinct forms, colloquially known as ‘resident’, ‘transient’ and ‘offshore’ killer whales (Ford et al. 1994). Separate species status has also been suggested for at least two of these different forms, based on color pattern, diet, and morphological traits (Baird 1994, Baird et al. 1999). Genetic differences are found among these forms, with particularly marked differences between resident and transient forms (Stevens et al. 1989, Hoelzel and Dover 1991, Hoelzel et al. 1998, Barrett-Lennard 2000). The taxonomy of this genus is clearly in need of review, and it is likely that O. orca will be split into a number of different species or at least subspecies over the next few years (Reeves et al. 2004).",No,No,DD,,DD,,"Orcinus orca is widespread and fairly abundant. Population trend data for this species are unavailable. Primary threats that could cause widespread declines include depletion of prey resources and contamination with persistent organic pollutants. Live-capture removals and direct takes are localized and do not appear to have had a high impact on the status of the species globally. Current threats for killer whales appear most serious in nearshore waters. The combination of potential declines driven by depletion of prey resources and the effects of pollutants is believed sufficient that a 30% global reduction over three generations or in this case 78 years could not be ruled out. Therefore, the species is currently considered to be Data Deficient.Additionally, regional subpopulations of killer whales can be small and highly specialized, and therefore vulnerable to over-exploitation and habitat deterioration. Several small subpopulations have already been recognized as having a high risk of extinction, including the Strait of Gibraltar subpopulation, which was provisionally assessed in 2006 as Critically Endangered (C2a(i,ii); D)(Reeves and Notarbartolo di Sciara 2006).",Unknown,"The killer whale is the most cosmopolitan of all cetaceans, and may be the second most widely-ranging mammal species on the planet, after humans. Killer whales can be seen in virtually any marine region, from the equator to polar waters. Although they are generally more common in nearshore areas and in higher productivity areas and/or higher latitudes, there appear to be no hard and fast restrictions of water temperature or depth on their range. The distribution extends to many enclosed or partially-enclosed seas, such as the Mediterranean Sea, Sea of Okhotsk, Gulf of California, Gulf of Mexico, Red Sea, and Persian Gulf. However, there are only extralimital records from the Baltic Sea and no records from the Black Sea.","Although killer whales occur worldwide, densities increase by 1-2 orders of magnitude between the tropics and the highest sampled latitudes in the Arctic and Antarctic (Forney and Wade 2006). Killer whales tend to be more common along continental margins; however, there is some variation in this general pattern that appears linked to ocean productivity. Killer whales appear to be less common in western boundary currents such as the Gulf Stream, than in more productive eastern boundary currents such as the California Current. Line-transect surveys have resulted in estimates of abundance in several regions in the North Atlantic, including an abundance estimate of 3,100 (CV=63%) killer whales in Norwegian waters (Øien 1990), and an estimate of 6,618 (CV=32%) whales in Iceland and Faroes Islands waters (Sigurjónsson et al. 1989, Gunnlaugsson and Sigurjónsson 1990).","Killer whales may occur in virtually any marine or estuarine habitat, but are most common in areas of high marine productivity, particularly at higher latitudes and near shore (Dahlheim and Heyning 1999, Forney and Wade 2006). Sightings range from the surf zone to the open sea. Although they do not migrate, movements can be extensive; for instance, some killer whales have been documented to have moved between Alaska and central California, a distance of more than 2000 km. In the Antarctic, they readily enter areas of floe ice in search of prey (Pitman and Ensor 2003). Killer whales in some areas congregate seasonally in coastal channels to forage and occasionally enter river mouths. Killer whales are known to feed on a wide array of prey types, including most marine mammal species (except river dolphins and manatees), seabirds, sea turtles, many species of fishes (including sharks and rays) and cephalopods (Dahlheim and Heyning 1999, Ford and Ellis 1999, Ford 2002). Killer whales have a diversity of foraging tactics, including intentional beaching to gain access to seals onshore. They are known to use cooperative techniques to herd fish and to attack large prey (Dahlheim and Heyning 1999, Baird 2000). Although a generalist as a species, at least some subpopulations specialize on particular types of prey (Bigg et al. 1990, Baird 2000). Studies in coastal waters of the eastern North Pacific, from California to Alaska, have described three distinct ecotypes of killer whales, referred to as residents, transients, and offshores. Although distinguished by ecological differences, there are also differences in coloration, external morphology, behavior and acoustics. The three ecotypes maintain social isolation from each other despite overlapping ranges.","Killer whales have been exploited at low levels in several regions world-wide (Jefferson et al. 1993). Norwegian whalers in the eastern North Atlantic took an average of 56 whales per year from 1938 to 1981. Fishermen in many areas see killer whales as competitors, and intentional shooting of whales is known to occur. This problem is especially serious in Alaska, where depredation of longline fisheries is extensive (Jefferson et al. 1993). Killer whales are still taken in small numbers in coastal fisheries in Japan, Greenland, Indonesia, and the Caribbean islands (Reeves et al. 2003).After 1976, Iceland has been involved in live-captures of killer whales for export. During the period 1976-1988, 59 whales were collected, of which 8 were released, 3 died and 48 (an average 3.7 per year) were exported (Reyes 1991 and ref. therein). In 1991, the lcelandic government announced that once current permits for live-capture expire, no new ones would be issued (Jefferson et al. 1993). Bycatch in trawl and driftnet fishing operations occur, but are considered rare (Dahlheim and Heyning 1999). Persistant, bioaccumulating contaminants have recently been found to present a serious potential risk to some killer whale subpopulations. Large-scale catastrophic oil spills have the potential to cause significant mortality of killer whales. Oil spills may also have an indirect effect by reducing prey abundance.Disturbance may be a matter for concern in areas inhabited by killer whales and supporting whale-watching industries (Reyes 1991). Moving boats can disrupt activities such as foraging and resting, and underwater boat noise could affect social and echolocation signals of the whales or otherwise interfere with foraging (Erbe 2002, Williams et al. 2002). For example, close approaches by whale-watching vessels have been shown to result in avoidance responses by resident killer whales in British Columbia, which may have energetic costs for whales frequently subjected to whale watching activity (Williams et al. 2002, 2006). Fast-moving boats in the proximity of killer whales also present a risk of collision or injury from propellers. Visser (1999) reported propeller scars observed on killer whales in New Zealand. There have been large-scale reductions in predatory fish populations (Myers and Worm 2003, Baum et al. 2003) and over-fishing and collapse of several important “prey” fish stocks world-wide (Jackson et al. 2001). The effects on killer whales of reductions in fish populations due to overexploitation are unknown. In some areas, populations could be vulnerable owing to dietary specialization. The depletion of the Mediterranean bluefin tuna stock is considered a source of concern for the survival of the Gibraltar killer whales (Cañadas and de Stephanis 2006).Predicted impacts of global climate change on the marine environment may affect killer whales, and may affect some subpopulations more than others through changes in prey availability.","The eastern North Atlantic subpopulation is included in Appendix II of the Convention on Migratory Species. The proposal to list all subpopulations of the killer whale in Appendix II was endorsed in 2002 by the Working Group of the CMS in Bonn (see Proceedings), as all the subpopulations were migratory and could profit from cooperative protective measures. Because killer whales are cosmopolitan in distribution, they may be present in virtually any marine protected area worldwide. Further studies on subpopulation structure, abundance and life history are needed.",Species account by IUCN SSC Cetacean Specialist Group; regional assessment by European Mammal Assessment team +ANIMALIA,CHORDATA,MAMMALIA,CETARTIODACTYLA,DELPHINIDAE,Peponocephala electra,,No,No,NA,,NA,,This species is assessed as Not Applicable as it is of marginal occurrence in the European Mammal Assessment region.,-,"Melon-headed whales have a pantropical distribution (Perryman 2002). The distribution coincides almost exactly with that of the pygmy killer whale in tropical/subtropical oceanic waters between about 40°N and 35°S (Jefferson and Barros 1997). A few high-latitude strandings are thought to be extralimital records, and are generally associated with incursions of warm water. These include specimens from Cornwall in England, Cape Province in South Africa, and Maryland, USA (Perryman et al. 1994, Rice 1998).","This species is relatively common in some areas of its range, although few abundance estimates are available.","Melon-headed whales usually occur in groups of 100-500 (with a known maximum of 2,000 individuals). Melon-headed whales are highly social. This species is sometimes involved in mass strandings, generally containing many dozens or even hundreds of animals. The largest ones known have included about 250 animals.Most sightings are from the continental shelf seaward, and around oceanic islands; they are rarely found in temperate waters. However, they do occur nearshore in some areas where deep water approaches the coast (see Watkins et al. 1997, Wang et al. 2001). In the eastern tropical Pacific, the distribution of reported sightings suggests that the oceanic habitat of this species is primarily in the upwelling modified and equatorial waters (Perryman et al. 1994).Little is known of the diet of this species, though they are known to feed on several species of squid, shrimp and small fish.","Threats include declines in prey species, incidental mortality in fishing gear, and noise pollution.","The melon-headed whale does not regularly occur in the European Mammal Assessment region, so there are no conservation measures for the species in this area.",Species account by IUCN SSC Cetacean Specialist Group; regional assessment by European Mammal Assessment team +ANIMALIA,CHORDATA,MAMMALIA,CETARTIODACTYLA,DELPHINIDAE,Pseudorca crassidens,,No,No,NA,,NA,,This species is assessed as Not Applicable as it is of marginal occurrence in the European Mammal Assessment region.,-,"False killer whales are found in tropical to warm temperate zones, generally in relatively deep, offshore waters of all three major oceans. In addition to deep, oceanic areas, they do sometimes occur over the continental shelf and appear to move into very shallow waters on occasion. They do not generally range poleward of about 50° in either hemisphere. However, some animals occasionally move into higher latitude waters. They are found in many semi-enclosed seas and bays (including the Sea of Japan, Bohai/Yellow Sea, Red Sea, and Persian Gulf), but they only occasionally occur in the Mediterranean Sea (Leatherwood et al. 1989). There are a few records for the Baltic Sea, which are considered extralimital.","There are few estimates of abundance, and none for the global population size. Abundance estimates, even for large oceanic regions such as the eastern tropical Pacific, are only in the low tens of thousands (39,800, CV=64%: Wade and Gerrodette 1993). There is no information on population trends.","As is the case for most of the tropical oceanic delphinids, this species is rather poorly-known (see Baird 2002). This species is considered to be extremely social. Groups of 10-60 are typical, though much larger groups are known. Some groups are very tight-knit, while others may be spread over a kilometer or more of ocean. This is one of the most common species involved in cetacean mass strandings, and in one case, over 800 stranded together. The false killer whale is a lively, fast-swimming cetacean, and occasionally rides bow waves of vessels. False killer whales are known to behave aggressively toward other small cetaceans, and have even been seen chasing and attacking dolphins (in particular, dolphins just released from tuna purse seines) and some large whales.False killer whales occur in tropical and temperate waters worldwide (Stacey et al. 1994, Odell and McClune 1999), generally in relatively deep, offshore waters. However, some animals may move into shallow and higher latitude waters, on occasion (including some semi-enclosed seas such as the Red Sea and the Mediterranean). It seems to prefer warmer water temperatures. Although false killer whales eat primarily fish and cephalopods, they also have been known to attack small cetaceans, humpback whales, and sperm whales. They eat some large species of fish, such as mahi-mahi (also called dorado or dolphinfish), tunas (see Alonso et al. 1999) and sailfish.","Potential threats include decline in prey base, incidental mortality in fishing gear, and noise pollution.","This is a relatively poorly-known species which, although mostly observed over deep water, is known to strand from many coasts. Abundance estimates as well as by-catch data do not exist for most areas, nor are there detailed accounts on migratory behaviour. Clearly, more research is needed.",Species account by IUCN SSC Cetacean Specialist Group; regional assessment by European Mammal Assessment team +ANIMALIA,CHORDATA,MAMMALIA,CETARTIODACTYLA,DELPHINIDAE,Sousa chinensis,"Currently, all Indo-Pacific humpback dolphins are considered to be part of a single widespread and highly-variable species, Sousa chinensis. Some biologists consider humpback dolphins in the Indo-Pacific to consist of two species: Sousa plumbea in the western Indian Ocean, from South Africa to at least the east coast of India, and Sousa chinensis from the east coast of India to China and Australia. These two geographic forms differ strongly in morphology and apparently in many ecological characters (see Jefferson and Van Waerebeek 2004 for a partial summary). Morphometric and genetic studies currently underway may resolve this controversy in the near future, but there is growing evidence that at least these two putative species, and possibly others, may be valid (see Rice 1998, Jefferson and Karczmarski 2001).",No,No,NA,,NA,,This species is assessed as Not Applicable as there is only a single record in the European Mammal Assessment region.,-,"Indo-Pacific humpback dolphins of the chinensis-type are found in shallow, coastal waters from both east and west coasts of northern Australia and southern China in the east, through the Indo-Malay Archipelago, and westward around the coastal rim of the Bay of Bengal to at least the Orissa coast of west India (Ross et al. 1994, Jefferson and Karczmarski 2001, Sutaria and Jefferson 2004). The plumbea-type is found in narrow strip of coastal waters from southwest tip of South Africa eastward around the rim of the Indian Ocean to the southeast cost of India (Jefferson and Karczmarski 2001, Ross 2002, IWC 2003). It occurs off Madagascar, Mayotte and the Comoro Islands, in the Red Sea and Persian Gulf. There is an extralimital record for Israel, in the Mediterranean Sea (an apparent stray that moved through the Suez Canal from the Red Sea: Kerem et al. 2001).",There has only been a single sighting of this species in the European Mammal Assessment area (Kerem et al. 2001).,"Humpback dolphins occurs in tropical to warm temperate coastal waters, including open coasts and bays, coastal lagoons, rocky and/or coral reefs, mangrove swamp and estuarine areas (Ross et at. 1994, Jefferson and Karczmarski 2001, Ross 2002); rarely more than a few kilometers from shore. They sometimes enter rivers, but rarely move more than a few kilometers upstream and usually within the tidal range. Their distribution appears to be limited to waters of the continental shelf, and the only places where they range far offshore are those in which the water is shallow (<100m). They appear to be opportunistic feeders, feeding on a wide variety of nearshore, estuarine, and reef fish. They also eat cephalopods in some areas, but crustaceans are rare in the diet (Jefferson and Karczmarski 2001, Ross 2002).","The majority of humpback dolphins inhabit coastal or estuarine waters of developing nations, countries with limited resources and means for environmental protection. Habitat degradation and habitat loss, and incidental mortality in fishing gear represent the greatest threats to this species (Ross et al. 1994, Jefferson and Karczmarski 2001).","Indo-Pacific humpback dolphin is a vagrant in the European Mammal Assessment region, so there are no conservation measures for the species in this area.",Species account by IUCN SSC Cetacean Specialist Group; regional assessment by European Mammal Assessment team +ANIMALIA,CHORDATA,MAMMALIA,CETARTIODACTYLA,DELPHINIDAE,Stenella coeruleoalba,"Recent genetic work suggests that the genus Stenella is paraphyletic, and it is likely that it will be restructured in coming years. This species may move to a different genus (LeDuc et al. 1999).",No,No,DD,,DD,,"This species has a varying status in different parts of its European range. In the Mediterranean there have been population declines, and the regional population was recently assessed as Vulnerable (A4de)(Reeves and Notarbartolo di Sciara 2006). However in the eastern North Atlantic there are large populations that show no evidence of significant decline, although population trends have not been quantified. Overall in the European Mammal Assessment region, it is not possible to quantify the population trend because the relative size of the different subpopulations is not known. Consequently the species is assessed as Data Deficient at the European regional level.",Unknown,"This is a widely-distributed species, found tropical and warm-temperate waters of the Atlantic, Pacific, and Indian oceans, as well as many adjacent seas, including the Mediterranean. Northern and southern range limits are about 50°N and 40°S, although there are extra-limital records from the Kamchatka Peninsula, southern Greenland, the Faroe Islands, and the Prince Edward Islands. They are uncommon in the Sea of Japan, East China Sea, off eastern Taiwan and Ryukyuan waters, and a few extra-limital records are known from the Persian Gulf and Red Sea.","Striped dolphins are the most abundant cetacean species in the Mediterranean. The population in the western Mediterranean excluding the Tyrrhenian Sea was estimated in 1991 to be 117,880 dolphins (95%CI=68,379-214,800) (Forcada et al. 1994). There is no estimate for the eastern Mediterranean Sea. Goujon (1996) conducted a sighting survey in 1993 in the fishing grounds of the albacore tuna driftnet fishery in the Bay of Biscay and estimated the abundance of striped dolphins as 74,000 individuals. Morphological and genetic studies strongly suggest that the Mediterranean and eastern North Atlantic populations are isolated from each other, with little or no gene flow across the Strait of Gibraltar (Calzada and Aguilar 1995, García-Martínez et al. 1995, Archer 1997, Gaspari 2004). Within the Mediterranean there is some evidence of population structure based on restriction in gene flow between areas and significant differences in tissue pollutant levels (Calzada and Aguilar 1995, Monaci et al. 1998, Gaspari 2004).","Striped dolphins are primarily found in warm temperate and tropical oceanic regions and are seen close to shore only where deep water approaches the coast (Van Waerebeek et al. 1999). In the Strait of Gibraltar, they are found in waters of 600 m or more depth (Hashmi 1990). In the Mediterranean, striped dolphins are associated with highly productive, oceanic waters beyond the continental shelf (Notarbartolo di Sciara et al. 1993, Forcada et al. 1994, Frantzis et al. 2003, Gannier 2005). The diet of striped dolphins consists primarily of a wide variety of small, midwater and pelagic or benthopelagic fish, especially lanternfish, cod, and squids (Wurtz and Marrale 1993, Hassani et al. 1997, Archer 2002). Striped dolphins apparently feed in pelagic to benthopelagic zones, to depths as deep as 200-700m, in continental slope or oceanic regions.","In the Mediterranean small numbers were taken in Spain, France and Italy for human consumption. They were also hunted for use as bait for shrimp traps and longlines. Despite being illegal, catches continue in southern Spain and probably in other areas (SGFEN 2001, Reeves and Notarbartolo di Sciara 2006). In the Northeast Atlantic, striped dolphins were harpooned to supply food for consumption on board or to scare them away from tuna trolling lines. It is difficult to ascertain the number of dolphins taken in this way, but it has been estimated in the thousands (Reyes 1991).Incidental catches occur throughout the range in various types of fishing gear, especially purse seines and gillnets. The high-seas drift gillnet fisheries, which operated throughout the central and western North Pacific between about 35˚N and 47˚N, increased during the 1970s, and peaked during the 1980s before a United Nations moratorium went into effect in January 1993. Bycatch estimates are only available for 1990, when about 3,000 striped dolphins were estimated killed (Hobbs and Jones 1993). During the 1970s and 1980s, the combined high-seas driftnet fisheries likely killed tens of thousands of striped dolphins, but this level would not have been high enough to cause population declines (Hobbs and Jones 1993).Incidental captures in pelagic driftnets have been a major source of mortality all over the western Mediterranean in the past. These nets are still being illegally used, e.g. by Moroccan, French, Italian and Turkish vessels, resulting in extensive dolphin mortality. The Spanish driftnet fishery in the Alborán Sea reportedly killed 145-183 striped dolphins per season in the early 1990s (Silvani et al. 1999); this fishery was halted in 1995 but the nets were transferred to Moroccan boats, which continue operating and are estimated to kill in the order of 1,555-2,092 striped dolphins per year (Tudela et al. 2005). The Italian driftnet fishery has been reported to kill 5,000-15,000 dolphins, mostly striped dolphins, per year (Di Natale 1992). The French thonaille driftnet fishery has been estimated to take about 180-472 striped dolphins per season (Imbert et al. 2001). Reports from other fishing activities are sparse and collected non-systematically, but they indicate that striped dolphin mortality in at least pelagic purse-seines, longlines and gillnets is widespread and likely significant (Di Natale and Notarbartolo di Sciara 1994). Large incidental kills in pelagic trawl and driftnet fisheries off western Europe are also a source of concern (IWC 1998, Tregenza and Collet 1998). Antoine et al. (2001) found that by-catch rates in the tuna drift-net fishery in the northeastern Atlantic were 90% composed of Delphinus delphis and Stenella coeruleoalba. Mean catch rate by trip in 1992-1993 years were 4.7 striped dolphins per km of net and per day. Such rates are similar to those estimated in other driftnet fisheries. Goujon (1996) estimated the annual additional mortality linked to driftnets in the Bay of Biscay albacore tuna fishery to 1.8% for the striped dolphin (this estimate must be increased by 30% in order to take into account the whole European albacore tuna driftnet fishery). Tissue levels of organochlorine compounds, some heavy metals and selenium in Mediterranean striped dolphins are high and exceed threshold levels above which detrimental effects commonly appear in mammals (Monaci et al. 1998, Aguilar 2000, Cardellicchio et al. 2000). Organochlorine pollutants, in particular, are found at levels that greatly exceed thresholds of reproductive impairment in bottlenose dolphins elsewhere (Aguilar 2006). Blubber concentrations of DDT (an agricultural pesticide) and PCB, the two main organochlorine pollutants, have been slowly declining in the last two decades (Aguilar and Borrell 2005) but are still high. High PCB levels have the potential to depress reproductive rates in striped dolphins (Munson et al. 1988).The 1990-92 epizootic devastated the whole Mediterranean population of striped dolphins, producing many thousands of deaths (Bortolotto et al. 1992, Aguilar and Raga 1993). Immediately after the event, the mean school size was found to be less than one third of prior levels, which may be interpreted as indicating a proportional reduction in overall population size (Forcada et al. 1994). The primary cause of the die-off was a morbillivirus infection (Domingo et al. 1990) but PCBs and other organochlorine pollutants with potential for immunosuppressive effects may have triggered the event or enhanced its spread and lethality (Aguilar and Borrell 1994). Commercially exploited fish and cephalopod species are important components of striped dolphin diet in the Mediterranean (Blanco et al. 1995). As many stocks of important striped dolphin prey (e.g. the European anchovy) are known to have been depleted, reduced prey availability resulting from conflict with commercial fisheries is considered a potentially important threat (Reyes 1991, Reeves and Notarbartolo di Sciara 2006) and may have contributed to the 1990-1992 epizootic (Aguilar 2000).","The western Mediterranean subpopulation is included in Appendix II of the Convention on Migratory Species. Further research should be focused on stock identity and abundance, the effects of direct and incidental mortality, and the effects of pollutants and other sources of habitat disturbance on dolphin subpopulations, in particular in the western Mediterranean (Reyes 1991).",Species account by IUCN SSC Cetacean Specialist Group; regional assessment by European Mammal Assessment team +ANIMALIA,CHORDATA,MAMMALIA,CETARTIODACTYLA,DELPHINIDAE,Steno bredanensis,,No,No,NA,,NA,,This species is assessed as Not Applicable as it is of marginal occurrence in the European Mammal Assessment region.,-,"The rough-toothed dolphin is a tropical to subtropical species, which generally inhabits deep, oceanic waters of all three major oceans, rarely ranging north of 40°N or south of 35°S (Jefferson 2002). However in some areas (such as off the coast of Brazil and West Africa), rough-toothed dolphins may occur in more shallow coastal waters. They are found in many semi-enclosed bodies of water (such as the Gulf of Thailand, Red Sea, Gulf of Mexico, Caribbean Sea, and Gulf of California), but they are regarded as visitors in the Mediterranean Sea (Watkins et al. 1987, Miyazaki and Perrin 1994, Reeves and Notarbartolo di Sciara 2006).","This species is of marginal occurrence in the European Mammal Assessment region. Globally, there are few estimates of abundance for this species.","Most often, Steno bredanensis is found in deep water far offshore, usually beyond the continental shelf (Maigret 1994), but may be seen close inshore in areas of steep bottom relief (Ritter 2002). Rough-toothed dolphins appear to be widespread in warm temperate and tropical waters around the world. In the eastern tropical Pacific, they tend to associate with other cetaceans (especially pilot whales and Fraser’s dolphins) (Miyazaki and Perrin 1994). Rough-toothed dolphins feed on cephalopods and fish, including large fish such as Coryphaena hippurus (Pitman and Stinchcomb 2002).","No fisheries are known to specifically target this species, but small numbers are taken in drive fisheries in parts of the global range (outside Europe). Incidental mortality in gill nets, drift nets and pelagic long-lines has been recorded.","The biology, life history, population size, and separation into subpopulations, as well as migratory behaviour are insufficiently known. Research on this species should be encouraged.",Species account by IUCN SSC Cetacean Specialist Group; regional assessment by European Mammal Assessment team +ANIMALIA,CHORDATA,MAMMALIA,CETARTIODACTYLA,DELPHINIDAE,Tursiops truncatus,"All bottlenose dolphins around the world were previously recognized as T. truncatus, but recently the genus has been split into two species: T. truncatus and T. aduncus (the smaller Indo-Pacific bottlenose dolphin: Wang et al. 1999, 2000a,b). However, the taxonomy of bottlenose dolphins is confused, due to geographical variation, and it is very possible that additional species will be recognized in the future. For example, two forms in the North Atlantic, an offshore and a coastal form, are distinguishable on the basis of morphology and ecological markers (e.g. Mead and Potter 1995), have fixed genetic differences and, therefore, eventually may be assigned to different species (Leduc and Curry 1997, Hoelzel et al. 1998, Reeves et al. 2003).Bottlenose dolphins in the Black Sea are recognized as a subspecies possessing morphological differences from Atlantic and Pacific dolphins (Barabasch-Nikiforov 1960, Geptner et al. 1976). The Black Sea subpopulation is also differentiated genetically from other bottlenose dolphins in the eastern and western Mediterranean and the northeastern Atlantic (Natoli et al. 2005), and the available evidence (Birkun 2006) supports recognition of the subspecies T. t. ponticus.",No,No,DD,,DD,,"This species has a varying status in different parts of its European range. In the Mediterranean and Black seas there have been substantial population declines; the Mediterranean population was recently assessed as Vulnerable (A2cde), and the Black Sea subspecies T. t. ponticus was classed as Endangered (A2cde)(Reeves and Notarbartolo di Sciara 2006). However, although there are no estimates of population size or trend from offshore waters of the North Atlantic, the population there is likely to be large and shows no evidence of significant decline. Overall in the European Mammal Assessment region, it is not possible to quantify the population trend because the relative size of the different subpopulations is not known. Consequently the species is assessed as Data Deficient at the European regional level.",Unknown,"Common bottlenose dolphins are distributed worldwide through tropical and temperate inshore, coastal, shelf, and oceanic waters (Leatherwood and Reeves 1990, Wells and Scott 1999, Reynolds et al. 2000). Bottlenose dolphins generally do not range pole-ward of 45° except in northern Europe (as far as the Faroe Islands 62°N 7°W: Bloch and Mikkelsen 2000). The species is rare in the Baltic Sea (it may best be considered extralimital there), and is vagrant to Norway (Wells and Scott 1999).","Abundance has been estimated for several parts of the species' range. Summing available estimates, a minimum world-wide estimate of common bottlenose dolphins is 600,000. Total abundance in the Mediterranean is unknown but thought to be in the low 10,000s based on observed densities in areas that have been surveyed (Reeves and Notarbartolo di Sciara 2006). Surveys in the northwestern Mediterranean estimated 7,654 (CV=45%) dolphins (Forcada et al. 2004). An estimated 584 (CV=28%) animals occur in the Alboran Sea (Cañadas and Hammond 2006). Mediterranean bottlenose dolphins exhibit population structure based on toxicology and diet (Borrell et al. 2005) and genetics (Natoli et al. 2005). The total population size in the Black Sea is unknown. However, there are recent abundance estimates for parts of the range suggesting that population size is at least several thousands (Reeves and Notarbartolo di Sciara 2006). Preliminary estimates from the late 1980s indicate about 1,000 dolphins occur around the Faroe Islands (Sigurjónsson et al. 1989, Bloch and Mikkelsen 2000). A wide scale survey in 2005 of western European continental shelf waters including the western Baltic, North Sea and Atlantic margin as far as southern Spain estimated that there were 12,600 bottlenose dolphins in this area (CV=27%, P. Hammond pers. comm.).Reeves and Notarbartolo di Sciara (2006) estimate generation time in the common bottlenose dolphin to be c.20 years.","Common bottlenose dolphins tend to be primarily coastal, but they can also be found in pelagic waters (Wells and Scott 1999). Where distinct ecotypes are known, the inshore form frequents estuaries, bays, lagoons and other shallow coastal regions, occasionally ranging far up into rivers. The offshore form is apparently less restricted in range and movement. Some offshore dolphins are residents around oceanic islands. In many inshore areas bottlenose dolphins maintain definable, long-term multi-generational home ranges, but in some locations near the extremes of the species range, coastal bottlenose dolphins are migratory. Black Sea bottlenose dolphins are common over the continental shelf; they sometimes occur far offshore (Reeves and Notarbartolo di Sciara 2006). Bottlenose dolphins are commonly associated with many other cetaceans, including both large whales and other dolphin species (Wells and Scott 1999). Mixed schools with Indo-Pacific bottlenose dolphins have been found, for instance off China and Taiwan (J. Wang, pers. comm.). Spring and summer, spring and fall, or single summer calving peaks are known for most areas where this has been studied (Wilson 1995, Wells and Scott 1999). In general, bottlenose dolphins consume a wide variety of prey species, mostly fish and squid (Barros and Odell 1990, Barros and Wells 1998, Santos et al. 2001). They sometimes eat shrimps and other crustaceans.","Coastal and island-centered populations are especially vulnerable to hunting, incidental catch, and habitat degradation (see Curry and Smith 1997 for a review). Acute conservation problems are known in the Mediterranean and Black seas (IWC 1992, Reeves and Notarbartolo di Sciara 2006) as well as a number of other areas in the global range (outside Europe). Dolphin catches for bait, human consumption, or to remove competition with fisheries have been reported worldwide (see reviews in Wells and Scott 1999, 2002). The only Mediterranean area with quantitative historical information is the northern Adriatic Sea, where bottlenose dolphins likely have declined by at least 50% over the past 50 years, largely as a consequence of historical killing in extermination campaigns to reduce competition for fish, followed by habitat degradation and overfishing. The extermination campaigns were conducted until the early 1960s (Bearzi et al. 2004, Reeves and Notarbartolo di Sciara 2006). For the north-western Mediterranean, the available information suggests similar trends (Reeves and Notarbartolo di Sciara 2006). Drive fisheries have been reported from the Faroe Islands and Japan. Up to 308 are taken annually in the Faroe Islands drive fishery (dating back to 1803), often with long finned pilot whales (Reyes 1991). The Black Sea subspecies has had extensive directed takes for commercial products (Kleinenberg 1956, Tomilin 1957, Buckland et al. 1992), including takes of at least 24,000-28,000 during 1946-1983 in the Black Sea off Turkey. However, the total number of dolphins killed was certainly much greater (probably by tens of thousands) as figures do not include, or only partially include, catch statistics from other Black Sea countries (Reeves and Notarbartolo di Sciara 2006).Live-capture removal of Black Sea bottlenose dolphins, including mortality during capture operations, is estimated at 1,000-2,000 since the early 1960s. Live-captures continue in the Russian Federation, with 10-20 animals taken annually from a small area in the Kerch Strait, Russia (Reeves and Notarbartolo di Sciara 2006). According to CITES statistics, at least 92 individuals were removed from the Black Sea region during 1990-1999 (Reeves et al. 2003) and Russia reportedly has exported at least 66 for travelling shows since 1997 (Fisher and Reeves 2005).Incidental catches of common bottlenose dolphins are known from throughout the species’ range, in gillnets, driftnets, purse seines, trawls, long-lines, and on hook-and-line gear used in commercial and recreational fisheries, but numbers of mortalities are often poorly documented (Wells and Scott 1999). Annual Black Sea bottlenose dolphin incidental mortality in bottom-set gillnets from 1946 through the 1980s is roughly estimated in the hundreds. The scale of this mortality almost certainly increased in the 1990s-2000s owing to the rapid expansion of illegal, unreported and unregulated fishing (Reeves and Notarbartolo di Sciara 2006). According to Öztürk (1999) at least 200-300 bottlenose dolphins per year may be taken incidentally in Turkish fisheries in a variety of fishing nets, especially bottom-set gill nets.Common bottlenose dolphins in coastal areas are exposed to a wide variety of threats in addition to direct and indirect takes. Threats that are cause for concern include: 1) the toxic effects of xenobiotic chemicals; 2) reduced prey availability caused by environmental degradation and overfishing (Pauly et al. 1998, Jackson et al. 2001); 3) direct and indirect disturbance and harassment (e.g. boat traffic and commercial dolphin watching and interactive programs); 4) marine construction and demolition and 5) other forms of habitat destruction and degradation (including anthropogenic noise). Although these and other threats are technically challenging to quantify by comparison with takes, their cumulative impact is likely to result in longitudinal population declines. Lack of historical data in many cases hampers understanding of long term trends, possibly resulting in shifting baselines. The contribution of anthropogenic factors to an increasing number of Unusual Mortality Events involving bottlenose dolphins remains to be determined (Spradlin et al. 2005).","The bottlenose dolphin has been afforded special protected status under Annex II of the EU Habitats Directive. Commercial hunting of Black Sea cetaceans including bottlenose dolphins was banned in 1966 in the former USSR, Bulgaria and Romania, and in 1983 in Turkey. Research on population structure, abundance and removals of common bottlenose dolphins is needed so that risks to regional populations can be assessed.",Species account by IUCN SSC Cetacean Specialist Group; regional assessment by European Mammal Assessment team +ANIMALIA,CHORDATA,MAMMALIA,CETARTIODACTYLA,ESCHRICHTIIDAE,Eschrichtius robustus,,No,No,RE,,RE,,The gray whale has been Regionally Extinct since the 1700s or earlier.,-,"The gray whale was once found in the North Atlantic. Sub-fossil remains, the most recent dated at around 1675, have been found on the eastern seaboard of North America from Florida to new Jersey, and on the coasts of the English Channel and the North and Baltic seas. There are historical accounts of living gray whales from Iceland in the early 1600s and possibly off New England in the early 1700s (Rice 1998). Gray whales are now only found in the North Pacific and adjacent waters.","This species is extinct in the North Atlantic. In the North Pacific, the eastern stock has recovered strongly from past over-exploitation, and the most recent population estimate is 15,000-22,000 for 2001/02. The western Pacific stock remains at a small fraction of past levels and is estimated to number about 100 individuals, of which 20-30 are mature females (Reeves et al. 2005). It is considered Critically Endangered.","Gray whales are primarily bottom feeders and are thus restricted to shallow continental shelf waters for feeding. They are largely coastal although they do feed at greater distances from shore on the shallow flats of the Bering and Chukchi seas. Gray whales feed primarily on swarming mysids, tube-dwelling amphipods, and polychaete tube worms in the northern parts of their range, but are also known to take red crabs, baitfish, and other food (crab larvae, mobile amphipods, herring eggs and larvae, cephalopods, and megalops) opportunistically or off the main feeding grounds.Most groups are small, often with no more than three individuals, but gray whales do sometimes migrate in pods of up 16, and larger aggregations are common on the feeding and breeding grounds. ‘Aerial’ behaviour such as breaching and spyhopping are common, especially during migration, and in and near the breeding lagoons of Baja California and mainland Mexico.","Gray whales have been subject to hunting since prehistoric times, due to their slow swimming speeds and coastal distribution. The North Atlantic population was extinct by the early 1700s although the causes are unclear. Overexploitation was though to have caused the extinction of the western gray whale until Soviet scientists in the 1980s reported a small remnant group summering off Sakhalin Island, Russia. The eastern North Pacific population had reached such low numbers by the end of the 19th century that commercial whaling ceased, but has now recovered to at or near carrying capacity, its abundance showing some fluctuation in response to environmental conditions. The eastern North Pacific population is subject to anthropogenic threats such as entanglements in fishing gear (Baird et al. 2002), disturbance by vessels and other noise, collisions, and possibly petroleum-related and other contaminants (Moore and Clarke 2002). However, these do not appear to be important for the demography of the population.","The gray whale is regionally extinct in European waters, so there are no conservation measures for this species in the region. Gray whales have been protected from commercial whaling by the International Whaling Commission since its establishment in the 1946. Limited aboriginal subsistence whaling is permitted by the IWC for the eastern gray whale and catch limits have been set since the 1970s on the basis of advice from its Scientific Committee.",Species account by IUCN SSC Cetacean Specialist Group; regional assessment by European Mammal Assessment team +ANIMALIA,CHORDATA,MAMMALIA,CETARTIODACTYLA,MONODONTIDAE,Delphinapterus leucas,Specimens that appear to be hybrids between narwhals and belugas have been described from nature (Heide-Jørgensen and Reeves 1993).,No,No,NA,,NA,,This species is assessed as Not Applicable as it is of marginal occurrence in the European Mammal Assessment region.,-,"Beluga whales are distributed in high latitudes of the Northern Hemisphere from the west coast of Greenland westwards to Svalbard (Stewart and Stewart 1989, O'Corry-Crowe 2002). Records from the Sea of Japan and Baltic Sea are considered extralimital but resident populations occur in cold temperate latitudes in Cook Inlet (Alaska) and the St. Lawrence River system (Canada).","The global population consists of numerous subpopulations with varying degrees of differentiation. The IWC organized information on the basis of 29 management stocks and recognized that these were provisional (IWC 2000). Some of the stock boundaries overlap spatially and seasonally, complicating assessment. Many of the sub-populations or stocks maintain distinct or contiguous geographical ranges during the summer months and mix during the spring and autumn migrations and share common wintering quarters. While good abundance estimates are available for some beluga sub-populations/stocks, the size of others is virtually unknown. Total numbers worldwide are well above 150,000 animals.","Belugas occupy estuaries, continental shelf and slope waters, and deep ocean basins in conditions of open water, loose ice, and heavy pack ice. Belugas occur seasonally (mainly in summer) in coastal waters as shallow as 1-3 m deep but also in deep offshore waters (>800 m). They typically enter estuaries and sometimes move upstream into rivers; there are records of individuals or small groups ranging hundreds of kilometers from the sea.","Direct hunting by aboriginal people for food is the biggest known threat to belugas across certain portions of their range. The most immediate concerns relate to continuing harvests from small and depleted subpopulations (IWC 2000). The strong philopatry of belugas, which causes them to return to the same estuaries year after year, makes them highly vulnerable to overexploitation. This behavioural trait is undoubtedly the most important natural factor which has led to the extirpation of belugas from some parts of their range (e.g. southwest Greenland, some river mouths in Ungava Bay, Canada) by a combination of commercial and subsistence hunting. Another threat is Arctic climate change. As recent decreases in ice coverage have been more extensive in the Arctic belugas may experience climate-induced geographic shifts or altered reproductive capacity due to persistent changes in ice extent. Changes in sea ice extent and concentration thus have the potential to alter the distribution, range and migration patterns of cetaceans associated with ice habitats, and thus indirectly affect nutritional status, reproductive success, and ultimately the abundance and stock structure of these species (Tynan and DeMaster 1997, Laidre et al. in press). Belugas are also susceptible to sassats or ice entrapments when sea ice conditions rapidly change.Other known or potential threats include a wide variety of human activities: oil and gas development, expansion of fisheries (with possible implications for bycatch and resource depletion), and industrial and urban pollution.","Local and regional management bodies exist in Canada, Greenland, and the United States (Alaska), with the expectation that they will ensure the conservation of belugas. These include the Alaska Beluga Whale Committee (United States) and JCNB/NAMMCO (Canada/Greenland) and generally set harvest limits or recommend harvest limits for beluga populations within countries of interest. Harvest levels from sub-populations range anywhere from <10 to a few hundred animals per year. Removals from some subpopulations/stocks are considered sustainable, however there is concern and evidence that removals from other subpopulations/stocks are not (e.g. Eastern Hudson Bay and West Greenland) (Alvarez and Heide-Jørgensen 2004). In the Russian Federation, there is little to no population assessment.",Species account by IUCN SSC Cetacean Specialist Group; regional assessment by European Mammal Assessment team +ANIMALIA,CHORDATA,MAMMALIA,CETARTIODACTYLA,MONODONTIDAE,Monodon monoceros,,No,No,NA,,NA,,This species is assessed as Not Applicable as it is of marginal occurrence in the European Mammal Assessment region.,-,"Narwhals primarily inhabit the Atlantic sector of the Arctic and are rare in the Pacific sector. The principal distribution is from the central Canadian Arctic (Peel Sound – Prince Regent Inlet and northern Hudson Bay), eastward to Greenland and into the eastern Russian Arctic (around 180°E). They are rarely observed in the far eastern Russian Arctic, Alaska, or the western Canadian Arctic. In summer, narwhals spend approximately two months in high Arctic ice-free shallow bays and fjords and overwinter in offshore, deep, ice-covered habitats along the continental slope (Heide-Jørgensen and Dietz 1995). These disjunct seasonal distributions are connected by extensive annual migrations (over 1,000 km) which last approximately two months (Koski and Davis 1994, Dietz et al. 2001, Heide-Jørgensen et al. 2002, Innes et al. 2002, Heide-Jørgensen et al. 2003).","The global population is probably in excess of 80,000 animals. The narwhals that summer in the Canadian High Arctic constitute the largest fraction, probably in excess of 70,000 animals (Innes et al. 2002, NAMMCO/JCNB 2005).","In all areas of their occurrence, narwhals prefer deep or offshore waters (Hay and Mansfield 1989). Narwhals from Canada and West Greenland have high site fidelity to the winter pack ice of Davis Strait and Baffin Bay in regions along the continental slope with high gradients in bottom temperatures, predictable open water (< 5%), and relatively high densities of Greenland halibut (Laidre et al. 2004). Fish, squid, and shrimp make up most of the narwhal diet (Hay and Mansfield 1989, Heide-Jørgensen 2002), especially Arctic fish species, such as Greenland halibut, Arctic cod, and polar cod (the latter of which are often associated with undersides of ice) (Laidre and Heide-Jørgensen 2005). Narwhals feed at times in deep water and possibly at or near the bottom. Dives of up to nearly 1,500 m and 25 minutes are documented (Laidre et al. 2003), and there are some seasonal differences in the depth and intensity of diving (Laidre et al. 2002, Laidre et al. 2003).","Narwhal populations may be limited or threatened by hunting, climate change, and industrial activities such as commercial fishing and oil exploration. Narwhals were never the targets of large-scale commercial hunting except for a brief period of perhaps several decades of the early 20th century in the eastern Canadian Arctic (Mitchell and Reeves 1981). They were hunted opportunistically by commercial whalers, explorers and adventurers in many areas. Narwhals have been hunted by the Inuit for human food, dog food and tusk ivory (Born et al. 1994). The mattak (skin and adhering blubber) is highly prized as food and provides a strong incentive for the hunt (Reeves 1993, Heide-Jørgensen 1994). The effects of climate change on narwhals are uncertain. Narwhals are well adapted to a life in the pack ice as indicated by the fact that there is very little open water in their winter habitat (Laidre and Heide-Jørgensen 2005). Narwhals spend much of their time in heavy ice and are vulnerable to events called ice entrapments where hundreds of whales become trapped in a small opening in the sea ice and die. This occurs when sudden changes in weather conditions (such as shifts in wind or quick drops in temperature) freeze shut leads and cracks they were using. When live entrapped whales are discovered by Inuit hunters, they normally take advantage of the event by killing the animals. A recent assessment of the sensitivity of all Arctic marine mammals to climate change ranked the narwhal as one of the three most sensitive species, primarily due to its narrow geographic distribution, specialized feeding and habitat choice, and high site fidelity (Laidre et al. in press).","The narwhal is actively hunted only in Canada and Greenland. In Canada, the quota system that had been in place since the 1970s was replaced by a community-based management system implemented in the late 1990s and early 2000s (COSEWIC 2004). The hunt is managed by local hunter and trapper organizations with harvest limits established in some communities. Compliance has been questionable (COSEWIC 2004). Under this system, removals from some summering aggregations are probably sustainable, however there is concern that removals from other summering aggregations may not be (NAMMCO/JCNB 2005). In Greenland, a quota system was introduced in 2004 by the Greenland Ministry of Fisheries and Wildlife. The quota was set at 300 narwhals (of which 294 were taken), divided among municipalities of West Greenland. Compliance has reportedly been good (NAMMCO/JCNB 2005). Narwhals are legally protected in Russia and Norway. The species is listed in Appendix II of CMS.",Species account by IUCN SSC Cetacean Specialist Group; regional assessment by European Mammal Assessment team +ANIMALIA,CHORDATA,MAMMALIA,CETARTIODACTYLA,PHOCOENIDAE,Phocoena phocoena,"Four subspecies are recognized: P. p. phocoena in the North Atlantic, P. p. vomerina in the eastern North Pacific, an un-named subspecies in the western North Pacific (Rice 1998) and P.p. relicta in the Black Sea (Reeves and Notarbartolo di Sciara 2006).Several genetic and morphometric studies have concluded that the Baltic porpoises are a separate population distinct from those living in Kattegat, Skagerrak and North Sea (Tiedeman et al. 1996, Huggenberger 1997, Huggenberger et al. 2002). A recent genetic study found no statistically significant differences that would justify a separate Baltic population (Palme et al. 2004). However, it is precautionary to consider Baltic porpoises as a distinct subpopulation.",No,No,VU,A2cde,VU,A2cde,"This species has suffered major declines in the Baltic and Black Seas, although large and apparently stable populations persist elsewhere in the European region. Overall, it is estimated that population reduction has exceeded 30% over the last 30 years (= 3 generations). This population decline is driven almost entirely by trends in the Black Sea population (a separate subspecies), which is completely isolated from the North Atlantic population. Consequently at the European regional level the species is classed as Vulnerable (A2cde).The Baltic Sea subpopulation is assessed separately as Critically Endangered (C2a(ii)). The current information on abundance provides evidence for a population size of fewer than 250 mature animals, and a continuing decline can be inferred based on the current information on bycatches. All individuals in the Baltic Sea population belong to one subpopulation.The Black Sea subspecies P. p. relicta was assessed in 2006 as Endangered (A2d+A4cde)(Reeves and Notarbartolo di Sciara 2006).The North Atlantic population of this species is large, and there is no evidence to suggest that any significant declines have occurred (although the population trend has not been quantified). This part of the European population should be considered Least Concern.",Unfavourable,"Harbor porpoises are found in cold temperate to sub-polar waters of the Northern Hemisphere (Gaskin 1992, Read 1999). They are usually found in continental shelf waters, although they occasionally travel over deeper offshore waters. In the North Pacific, they range from central California and northern Honshu to the southern Beaufort and Chukchi Seas (including the Bering and Okhotsk Seas, and Sea of Japan). In the North Atlantic, they are found from the southeastern United States to southern Baffin Island (they apparently do not enter Hudson Bay) in the west, and from Senegal to Novaya Zemlya in the east. They also occur around southeast and western Greenland, Iceland, and the Faroe Islands, and this is the only cetacean species that currently regularly occupies the Baltic Sea. The species occurs in the Black Sea, Marmara Sea, and Sea of Azov, but with the exception of the adjacent northern Aegean Sea, they do not regularly occur in the Mediterranean Sea.","In the North Atlantic Ocean (including the Black and Azov seas), fourteen population units have been proposed (Donovan and Bjørge 1995), and in the North Pacific, several population units have been identified based on genetic studies (Chivers et al. 2002). There are no synoptic surveys covering the entire range within ocean basins, but abundance has been estimated for selected portions of the species’ range. Abundance estimates have been summarised by Read 1999 (see updates in Angliss and Outlaw 2005, Carretta et al. 2006, Waring et al. 2006). In the waters of the European Atlantic, abundance in 2005 was estimated at 385,600 [CV=0.20] (SCANS-II P.S. Hammond pers. comm.), of which about 335,000 [CV=0.21] were estimated in the North Sea and adjacent waters, where abundance was estimated at 341,000 [CV=0.14] in 1994 (Hammond et al. 2002). The abundance of the Baltic Sea stock has been estimated at 599 (CV=57%; 95% confidence interval = 200-3,300) (Hiby and Lovell 1995), of which about 50% or 300 would likely be mature (Taylor et al. 2007). Using a precautionary approach (Wade 1998), a minimum abundance estimate of mature animals would be the lower 20th percentile of the abundance estimate of mature individuals, equal to 192. Line transect surveys have been conducted recently (since 2001) to estimate harbour porpoise abundance in different portions of the Black Sea suggesting that total population size in the region may be at least several thousand and perhaps as much as 10,000-12,000 (Reeves and Notarbartolo di Sciara 2006).There is evidence of decline in abundance in some areas, for example in the Black Sea (Reeves and Notarbartolo di Sciara 2006) and the Baltic Sea. Although there are no reliable estimates of pre-exploitation subpopulation size, harbour porpoises were once numerous in the Baltic proper (see citations in Kinze 1995).","Throughout its range, P. phocoena is largely limited to continental shelf waters. They frequent relatively shallow bays, estuaries, and tidal channels less than about 200 m in depth. Harbor porpoises eat a wide variety of fish and cephalopods, and the main prey items vary regionally. Although small schooling fish (e.g. herring) are important, demersal foraging is characteristic in many areas. The ecology of Black Sea harbour porpoises may be unusual reflecting the high degree of geographic isolation of their habitat.Surveys in 1994 and 2005 in the North Sea and adjacent waters have shown a major shift in distribution from northern to southern areas (Hammond et al. 2002, P.S. Hammond pers. comm. 2007), a change that is reflect by increased in shore-based sightings (Camphuysen 2004, Thomsen et al. 2006).","The harbor porpoise has been hunted in many areas of its range, including some European waters. Many of these fisheries are now closed, but hunting of harbour porpoises still occurs in Greenland. In the Black Sea, large directed takes occurred during 1976-1983 before being banned by Turkey in 1983. Within that period, the total number of harbour porpoises killed was at least 163,000-211,000. Illegal direct killing of unknown numbers continued in some parts of the Black Sea until 1991 (Reeves and Notarbartolo di Sciara 2006).Today, the most significant threat in most areas is incidental catches in fishing gear, primarily gill nets. Incidental mortality in fishing gear is likely to occur throughout the range of the species, but in European waters substantial incidental takes have been documented (summarized in Donovan and Bjørge 1995) for the North Sea (4,600/year) and the Celtic Shelf (1,500/year). More recent monitoring programmes of Danish set-net fisheries in the North Sea revealed an average of 5,591 porpoises taken annually in the period 1987-2001 (Vinther and Larsen 2002). However, most North Sea gillnet fisheries were not monitored for marine mammal bycatch (ICES 2002). In the Black Sea incidental mortality in bottom-set gillnets is estimated to have been in the thousands annually through the 1980s (e.g. Birkun 2002). Almost all (>99%) of the porpoises are caught in bottom-set gillnets. The scale of this mortality almost certainly increased in recent times owing to the rapid expansion of illegal, unreported and unregulated fishing in the Black Sea.Other types of threats include chemical pollution, vessel traffic, noise, and depletion of prey by overfishing. Due to its near shore distribution, the harbour porpoise is exposed to coastal sources of pollution throughout most of its range. Chemical pollution (PCBs) has been described as having adverse effects, especially in the Baltic. Porpoises from the Baltic Sea have up to 254% higher mean levels of PCBs than corresponding samples from the adjacent Kattegat and Skagerrak (Berggren et al. 1999, Bruhn et al. 1999), and a number of lesions and pathological changes have been reported from the Baltic Sea porpoises (Clausen and Andersen 1988).","The European Union adopted a Council Regulation 812/2004 entering into force in July 2004. This regulation is aimed at reducing the incidental catch of small cetaceans in fisheries in European Union waters. The regulation includes measures restricting Baltic Sea drift net fisheries, providing for mandatory use of acoustic deterrent devices (pingers) in some EU gillnet fisheries in the Baltic Seas, and the use of onboard observers on vessels of over 15 m in length. Immediate actions to reduce the magnitude of bycatches are necessary. A review of the progress of implementing the regulation is scheduled for 2007. Commercial hunting of Black Sea cetaceans, including harbour porpoises, was banned in 1966 in the former USSR (present Georgia, Russia and Ukraine), Bulgaria and Romania, and in 1983 in Turkey. In the North Sea incidental takes have been determined to be above the advised maximum level of removals.Under the aegis of the ASCOBANS Secretariat, a special working group composed of representatives of international conventions, government ministries, fishermen and environmental groups has developed a recovery plan for the Baltic Harbour porpoise (Jastarnia Plan), which recommends a programme for bycatch reduction, research and monitoring, marine protected area establishment and an increase of public awareness. The overall aim is to restore the Baltic population of harbour porpoises to at least 80% of the Baltic’s carrying-capacity. A change in fishing methods and a reduction of fishing effort could significantly contribute to a lower bycatch rate.",Species account by IUCN SSC Cetacean Specialist Group; regional assessment by European Mammal Assessment team +ANIMALIA,CHORDATA,MAMMALIA,CETARTIODACTYLA,PHYSETERIDAE,Kogia breviceps,,No,No,NA,,NA,,This species is assessed as Not Applicable as it is of marginal occurrence in the European Mammal Assessment region.,-,"Pygmy sperm whales are known from deep waters (outer continental shelf and beyond) in tropical to warm temperate zones of all oceans (McAlpine 2002). They appear to be especially common over and near the continental slope, although they also occur in very deep oceanic regions. This species appears to prefer somewhat more temperate waters than does the dwarf sperm whale. The range of Kogia breviceps is poorly known, though a lack of records of live animals may be more due to inconspicuous behaviour rather than rarity. Most information stems from strandings (especially females with calves), which may give an inaccurate picture of the actual distribution at sea (Culik 2004). There are very few records of this species from European waters (Reid et al. 2003)",There are no estimates of global abundance for pygmy sperm whales. The frequency with which they strand in some areas (such as Florida and South Africa) suggests that they may not always be as uncommon as sightings would suggest. Abundance is often underestimated using visual survey methods because they dive for long periods and are inconspicuous when they surface (Barlow 1999).,"Kogia breviceps has records from nearly all temperate, subtropical, and tropical seas. It is rarely seen at sea; it tends to live a long distance from shore and has inconspicuous habits. According to Caldwell and Caldwell (1989) K. breviceps lives in oceanic waters beyond the edge of the continental shelf while K. sima lives over or near the edge of the shelf. However, this separation of both species was not apparent in the study of Mullin et al. (1994) who, by aerial observation, found both species over water depths of 400-600m in the north-central Gulf of Mexico.","Although they have never been taken in large numbers and have never been hunted commercially, small numbers have been taken in coastal whaling operations off Japan, Indonesia, Taiwan, the Lesser Antilles, and Sri Lanka (Jefferson et al. 1993). Perez et al. (2001) reported occasional bycatch in fisheries in the northeast Atlantic (mostly gillnet and purse seine operations). Noise pollution may also be a problem.",This species seldom occurs in European waters and thus there are no specific conservation measures at the regional level.,Species account by IUCN SSC Cetacean Specialist Group; regional assessment by European Mammal Assessment team +ANIMALIA,CHORDATA,MAMMALIA,CETARTIODACTYLA,PHYSETERIDAE,Kogia sima,"This taxonomic unit is treated as one species even though there is genetic evidence to suggest that there may be two separate species of dwarf sperm whales, one in the Atlantic and one in the Indo-Pacific (Chivers et al. 2005). However, this remains to be confirmed with additional work.",No,No,NA,,NA,,This species is assessed as Not Applicable as it is of marginal occurrence in the European Mammal Assessment region.,-,"The dwarf sperm whale, like the pygmy sperm whale, is known mostly from strandings (Nagorsen 1985, Caldwell and Caldwell 1989, McAlpine 2002). It is generally not a commonly-seen species at sea, although this may have more to do with its cryptic appearance than actual rarity. It appears to be distributed widely in tropical to warm temperate zones, apparently largely offshore. Their distribution shows somewhat more of a preference for warmer waters than does that of the pygmy sperm whale, and this species probably does not range as far into high-latitude waters. There is no evidence of migrations. A single record exists for the Mediterranean, and this is considered extralimital.",No estimates of global abundance exist.,"There is very little known of the ecology of this species (Caldwell and Caldwell 1989, McAlpine 2002). Much of what is known comes from records of strandings. Group sizes tend to be small, most often less than about six individuals (although groups of up to 10 have been recorded). Dwarf sperm whales appear to feed primarily on deep-water cephalopods, but also take other prey types (see dos Santos and Haimovici 2001).","Primary threats that could cause widespread declines include vulnerability to high-level anthropogenic sound sources, especially military sonar and seismic surveys, and bycatch. Hunting is localized and has not had a high impact on the status of the species globally.",This species seldom occurs in European waters and thus there are no specific conservation measures at the regional level.,Species account by IUCN SSC Cetacean Specialist Group; regional assessment by European Mammal Assessment team +ANIMALIA,CHORDATA,MAMMALIA,CETARTIODACTYLA,PHYSETERIDAE,Physeter macrocephalus,"Also known as Physeter catodon Linnaeus, 1758.",No,No,VU,A1d,VU,A1d,"European regional assessment: Vulnerable. The population and range are large enough that Criteria B and D do not apply. Does not meet Criterion C because there is no evidence of continuing decline. There are no estimates of historical or pre-exploitation abundance for the marine area covered by the European Mammal Assessment, but populations were undoubtedly depleted by commercial whaling. It is suspected that, by comparison with population levels 82 years (3 generations) ago, the population is currently >50% lower. This is a precautionary assessment that is not based on quantitative data, and it is strongly recommended that further surveys and modelling studies are carried out to better determine current and historic population size and trends.The Mediterranean subpopulation, which is genetically distinct, is assessed as Endangered C2a(ii). It contains fewer than 2,500 mature individuals, there is a continuing decline, and all mature individuals are in one undivided subpopulation. The Mediterranean subpopulation is subject to a number of threats that can result in direct mortality, including bycatches in fishing gear (especially drift gillnets) and ship strikes. In addition, the subpopulation may be affected by disturbance, particularly related to intense maritime traffic (Reeves and Notarbartolo di Sciara 2006).",Unfavourable,"The sperm whale has a large geographic range (Rice 1989). Sperm whales can be seen in nearly all marine regions, from the equator to high latitudes, but they are generally found in continental slopes or deeper water. The distribution extends through many enclosed or partially enclosed seas, such as the Mediterranean Sea, Sea of Okhotsk, Gulf of California, and Gulf of Mexico.","The only recent quantitative analysis of sperm whale population trends (Whitehead 2002) suggests that a pre-whaling global population of about 1,100,000 had been reduced by about 29% by 1880 through “open-boat” whaling, and then to approximately 360,000 by the 1990s through modern whaling, although much uncertainty is associated with all these estimates. There is no direct evidence that any part of the population has increased since the end of large-scale whaling in about 1980 although, for most areas, there is also no direct evidence that they have not. In some areas there is concern that populations are continuing to decline (e.g. the Mediterranean).","The habitat of the sperm whale is the open sea. More specifically, sperm whales can be found in almost all marine waters deeper than 1,000m that are not covered by ice, except in the Black Sea and possibly the Red Sea (Rice 1989, Whitehead 2003). In some areas, particularly in the western North Atlantic, sperm whales, and especially males, can occur in shallower waters (e.g. Scott and Sadove 1997). Sperm whales are generally more numerous in areas of relatively high primary productivity (Jaquet et al. 1996), although there are some exceptions, such as the Sargasso Sea.The sperm whale is an animal of extremes, in size (up to 18m), sexual dimorphism (mature males have three times the mass of mature females), ecological imprint (sperm whales take roughly the same amount of biomass from the oceans as humans), and many other attributes (Whitehead 2003). The commercial value of the animal (a function of its size and the quality of sperm whale oil) drove two massive worldwide hunts: the technologically primitive “open-boat” hunt from 1712-c.1920 (Starbuck 1878, Best 1983), and modern whaling using engine-driven whaling ships and harpoon guns from c.1910-1988 (Tønnessen and Johnsen 1982). The complex social structure of sperm whales may have been affected by whaling, lowering potential population growth rates, which are very low anyway (Whitehead 2003). On the positive side, sperm whales are very widely distributed (see above), and their primary food, deep-water squid, are not yet major targets of fisheries. The generation time (mean age of mothers) for sperm whales can be calculated if one assumes a set of population parameters, specifically age at first birth, mortality rate of mature females, and reproductive rate of mature females. There is uncertainty about these parameters, so two calculations were made using different assumptions:a) Applying the population parameters most recently used for sperm whales by the International Whaling Commission’s Scientific Committee (International Whaling Commission 1982: age at first birth = 10 years; female reproductive rate in unexploited population = 0.20/year; female adult mortality = 0.055/yr): generation time = 27.3 years.b) The estimates of mortality used by the International Whaling Commission are particularly problematic, and sperm whales likely have age-specific survival and reproductive rates. Thus it may be more realistic (Whitehead 2002) to use the well-established mortality schedule of killer whales (Orcinus orca; Olesiuk et al. 1990) and an age-specific pregnancy rate taken from the sperm whale data presented by Best et al. (1984; pregnancy rate for mature females = 0.257-0.0038xAge in years): generation time = 27.5These estimates are consistent and suggest a generation time of 27.4yr for sperm whales.","Sperm whales have had a long history of local whaling going back at least to the 1500s (Mesnick pers. comm.), and intense whaling, beginning around 1712, and continuing to 1988. The “modern” highly mechanised phase was particularly intense around 1950, and at its peak killed around 25,000 whales per year, dramatically depleting the global population. Currently, some tens of whales are taken each year from small boats in Indonesia, and 10 are taken annually by Japan under IWC Special Permit (Clapham et al. 2003).Entanglement in fishing gear, particularly gillnets, has been a particular problem in the Mediterranean Sea (see Reeves and Notarbartolo di Sciara 2006) but sperm whales die from entanglement in nets and lines in many other areas and in a variety of fisheries as well (e.g. Haase and Félix 1994, Barlow and Cameron 2003, Caretta et al. 2005). Sperm whales sometimes take fish off fishing gear (most often demersal long-line gear), an activity known as depredation. Depredation of long-line catches appears to be a recent and increasing phenomenon, and now occurs in many regions (e.g. South East Alaska, Chile, South Georgia and several other southern ocean island areas, North Atlantic). This interaction has resulted in a few reported entanglements and deaths (e.g. Salas 1987, Hucke-Gaete et al. 2004), and has incurred hostility from some fishermen (National Marine Fisheries Service 1998, Donoghue et al. 2003), including shooting of whales (González and Olivarría 2002).Sperm whale tissues have high levels of some contaminants (O'Shea 1999, Nielsen et al. 2000), though any population-level effects on health are unknown. The effects of noise on sperm whales are also uncertain. Some evidence suggests that they are highly sensitive to noise (e.g. Watkins et al. 1985, Bowles et al. 1994) while other studies have found little or no effect (e.g. Madsen and Møhl 2000, Madsen et al. 2002). To date, all published studies of sperm whales and noise focus on short-term behavioural effects. Avoidance of sonar (Dawson pers. comm.) and seismic surveys (Mate et al. 1994; but see Madsen et al. 2002) has been observed but no mortality has been documented.Whaling on sperm whales has at various times focussed almost exclusively on one sex or the other. Removals of large numbers of males may have had lingering effects on pregnancy rates in some subpopulations (Best 1979, Clarke et al. 1980, Whitehead et al. 1997) and large males are noticeably uncommon on some breeding grounds (see Whitehead 2003). The removal of large numbers of females from social groups, and of older females in particular, may have lingering, socially disruptive effects. Further, recovery might be inhibited via temporary or permanent loss of social cohesion and of socio-ecological knowledge such as is known to occur in other large-brained, long-lived social mammals (e.g. elephants, Poole and Thomsen 1989). Maximum rates of increase for sperm whale populations are very low, possibly on the order of 1% per year (Whitehead 2002). Population recovery will be slow.The extraordinarily wide distribution of sperm whales buffers the species to some extent from competition with fisheries. However, it should be noted that in some areas, stocks of squid and fish species known to be used by sperm whales are heavily exploited.Sperm whales face other threats at a more regional level. These include collisions with ships (Laist et al. 2001), for instance off the Canary Islands (André and Potter 2000) and in the Mediterranean (Pesante et al. 2002), and ingestion of marine debris in the Mediterranean (e.g. Viale et al. 1992).","Management plans need both development and implementation. The International Whaling Commission manages sperm whale populations under the International Convention for the Regulation of Whaling, and lists sperm whale seasons, sperm whale size limits and sperm whale catch limits (0 at present), as well as sanctuaries for all species in the Indian and Southern Oceans. However, no scheme for managing sperm whale populations is in place. Moreover, many range states are not members of the International Whaling Commission.",Species account by IUCN SSC Cetacean Specialist Group; regional assessment by European Mammal Assessment team +ANIMALIA,CHORDATA,MAMMALIA,CETARTIODACTYLA,SUIDAE,Sus scrofa,,No,No,LC,,LC,,"The species is widespread, extremely abundant and facing no major threats.",Possibly Favourable,"The wild boar has a large global distribution extending from western Europe and North Africa eastwards through the Middle East and central and south-east Asia, reaching its south-eastern limit at the Greater Sunda Islands. In Europe, it is widespread in most continental areas, with the exception of northern Fennoscandia and European Russia. It disappeared from the British Isles and Scandinavia in the 17th century, although it has now been reintroduced to Sweden and escaped animals have established themselves in the wild in Britain (Spitz 1999). It is native to Corsica and Sardinia, but the population in Sicily was introduced (Spitz 1999). Animals have escaped from captivity in the UK and have established themselves in the wild. There are at least three small wild populations in England, on the Kent/East Sussex border, in Dorset, and in Hereford (Battersby 2005). In Europe it is found from sea level to 2,400 in the Pyrenees (Palomo and Gisbert 2002).","Wild boar populations in Europe increased markedly during the latter part of the 20th century (Spitz 1999), but are now thought to be stable in most areas (EMA Workshop 2006). Populations in England, southern Sweden and Finland may still be increasing (Battersby 2005, EMA Workshop 2006).","It is found in a variety of temperate and tropical habitats. It prefers broadleaved forests and especially evergreen oak forests, but may also be found in more open habitats such as steppe, mediterranean shrubland, and farmland, so long as there is water and tree cover nearby (Spitz 1999). It has an omnivorous diet, consuming vegetable matter (e.g. beech mast, acorns, green plants, tubers), carrion, and live animal prey (earthworms, insect larvae, small vertebrates) (Herre 1986, Oliver 1993).","There are no major threats to the species. It is considered a pest in parts of its range (Oliver 1993, Battersby 2005). Tuberculosis may be an issue in some areas, especially in managed populations. The disease does not kill the animals, but it is becoming increasingly prevalent (EMA Workshop 2006). Occasionally there are outbreaks of swine fever and African swine fever which cause local mortality, but populations recover rapidly (Oliver 1993). Habitat destruction, hunting (for food and sport), and persecution (often in reprisal for crop damage) may cause local declines in parts of the range (Oliver 1993).","It occurs in a large number of protected areas across its range. No specific conservation actions are recommended in Europe, except perhaps measures to control the population in certain places (EMA Workshop 2006).","Juan Herrero, Giorgos Giannatos, Andreas Kranz, Jim Conroy" +ANIMALIA,CHORDATA,MAMMALIA,CETARTIODACTYLA,ZIPHIIDAE,Hyperoodon ampullatus,,No,No,DD,,DD,,"Hyperoodon ampullatus is widespread throughout the north Atlantic region. Population trend data for this species are unavailable. A primary threat that could cause widespread declines is vulnerability to high-level anthropogenic sound sources, especially military sonar and seismic surveys. Although the current population remains depleted from whaling the decline took place more than three generation lengths ago.The combination of possible declines driven by vulnerability to high-level anthropogenic sound sources and bycatch is believed sufficient that a 30% reduction over three generations (in this case 54 years) could not be ruled out. Therefore, the species is currently considered to be Data Deficient.",Unknown,"Northern bottlenose whales are found only in the North Atlantic, from New England, USA to Baffin Island and southern Greenland in the west and from the Strait of Gibraltar to Svalbard in the east (c. 38ºN to 72ºN: Mead 1989, Gowans 2002). There are reports from the Mediterranean Sea, and some extralimital records from the Baltic Sea. Bottlenose whales are occasionally observed off the Azores (Steiner et al. 1998), and have been seen as far south as the Cape Verde Islands (15ºN: Ruud 1937). The pelagic distribution extends from the ice edges south to approximately 30°N. Historic catch distributions indicated the existence of at least six centres of abundance, each potentially representing a separate stock (Benjaminsen 1972): i) the Gully; ii) northern Labrador-Davis Strait; iii) northern Iceland; iv) and v), off Andenes and Møre, Norway, and vi) around Svalbard, Spitzbergen. Anecdotal reports from whalers suggest a north/south seasonal migration could occur in some regions but there is little strong evidence for this. They inhabit the most northerly waters of the Barents and Greenland seas in summer (May to August). The northern bottlenose whale forms an antitropical species pair with the southern bottlenose whale, Hyperoodon planifrons.","Global numbers of northern bottlenose whales are largely unknown. There are estimated to be more than 5,000 in the waters around Iceland and the Faroe Islands. An estimated 40,000 occur in the eastern North Atlantic (NAMMCO Annual Report 1995), including approximately 5,827 (CV=16%) in the high latitudes of the eastern North Atlantic (Gunnlaugsson and Sigurjónsson 1990). Estimates for Icelandic and Faroese waters are 3,142 and 287 whales respectively, although allowance was not made in the surveys for animals not observed because of their long dives (Reyes 1991). Most populations of the species are probably still depleted, due to large kills in the past; over 65,000 animals were killed in a multinations hunt that operated in the North Atlantic from c.1850 to the early 1970s (Mitchell 1977, Reeves et al. 1993). A study by Christensen and Ugland (1983) resulted in an estimated initial (pre-whaling) population size of about 90,000 whales, reduced to some 30,000 by 1914. The population size by the mid 1980s was said to be about 54,000, nearly 60% of the initial stock size.","The behavior and ecology of northern bottlenose whales have been better studied than that of any other species in the family Ziphiidae. Most groups contain at least four whales, sometimes with as many as 20, and there is some segregation by age and sex. These deep divers can remain submerged for an hour, possibly as long as two, and can reach depths of well over 1,400 m (Hooker and Baird 1999). They are known for their curiosity, often approaching and swimming around boats for some time, as well as their habit of ""standing by"" injured companions; these behaviours permitted whalers to kill large numbers of whales at the same site (Gray 1882). Although capable of travelling long distances, their movement patterns are generally quite localized (Hooker et al. 2002, Whitehead et al. 2003). These cold temperate to subarctic whales are found in deep waters, mostly seaward of the continental shelf (and generally over 500-1,000 m deep) and near submarine canyons. They sometimes travel several kilometres into broken ice fields, but are more common in open water. Few whales were caught in shallow waters over the continental shelf off Labrador and in waters less than 1000 m deep off the west coast of Norway. In the surrounding waters of Iceland, the whales were sighted in waters with surface temperature between -1.3°C and +0.9°C (Reyes 1991).Northern bottlenose whales occupy a very narrow niche; their primary food source is squid of the genus Gonatus (Hooker et al. 2001, Whitehead et al. 2003) These whales may also occasionally eat fish (such as herring and redfish), sea cucumbers, starfish, and prawns. They do much of their feeding on or near the bottom in very deep water (>800 m, and as deep as 1,400 m: Hooker and Baird 1999). Longevity is at least 37 years, possibly much longer (Christensen 1973).","This is one of only a few species of beaked whales to be hunted commercially on a large scale. Hunts occurred from the 1850s to the 1970s, and over 65,000 whales were killed (with many more struck but lost: Reeves et al. 1993). By far the major bottlenose whaling nation has been Norway, though some hunting was also done by the UK and Canada. The northern bottlenose was sought after for its oil (including a form of spermaceti oil in the head) and later for pet food. No hunting of this species has been conducted by Norway since 1973 (Jefferson et al. 1993, Reyes 1991). The species has been essentially unexploited for almost 30 years, with only a few animals taken in some years in the Faroe Islands. The aggregate population was certainly reduced by whaling, and the extent of recovery is uncertain (Reeves et al. 2003). Mitchell (1977) considered that the population was severely depleted in both the early and modern whaling periods. Very few incidental catches have been reported (Reyes 1991). Pollutant levels in this species are usually low (Reyes 1991). There are no major fisheries for squid in the Northeast Atlantic, but future developments could represent some threat for subpopulations as heavily depleted as those of the bottlenose whale (Culik 2004). This species, like other beaked whales, is likely to be vulnerable to loud anthropogenic sounds, such as those generated by navy sonar and seismic exploration (Cox et al. 2006).","The northern bottlenose whale is said to have been twice overexploited by Norwegian hunting, in the periods 1880-1920 and 1938-1973. It was included in the International Whaling Commission schedule in 1977, with recommendations that northern bottlenose whales be granted Protected Stock status with zero catch limit (Klinowska 1991). It is listed in Appendix II of the Convention on Migratory Species as well as in Appendix I of CITES. Populations or stocks are not defined; this, together with estimates of present abundance as well as present levels of catches (Faroe Islands), should be the focus of future studies (Reyes 1991, Culik 2004, Dalebout et al. 2006).",Species account by IUCN SSC Cetacean Specialist Group; regional assessment by European Mammal Assessment team +ANIMALIA,CHORDATA,MAMMALIA,CETARTIODACTYLA,ZIPHIIDAE,Mesoplodon bidens,,No,No,DD,,DD,,"The range of this species does not qualify as threatened under criterion B. It cannot be ruled out that the regional population of this species is small enough to warrant listing under criteria C-D. Population trend or abundance data for this species are unavailable. As with other beaked whales, threats that could cause widespread declines include high levels of anthropogenic sound, especially military sonar and seismic surveys, and bycatch. The relative rarity of this species implied from the existing records makes it potentially vulnerable to low-level threats.The combination of possible declines driven by vulnerability to high-level anthropogenic sound sources and bycatch is believed sufficient that a 30% reduction over three generations could not be ruled out. Therefore, the species is currently considered to be Data Deficient.",Unknown,"Sowerby's beaked whales are known almost exclusively from the colder waters of the North Atlantic, from at least Massachusetts, USA to Labrador, Canada in the west, and from Iceland to Norway in the east (Mead 1989, MacLeod et al. 2006). This is the most northerly distributed of the Atlantic species of Mesoplodon, and most records are north of 30°N. Based on unconfirmed records, the range may include (probably as a stray) the Mediterranean Sea. Records from the shallow Baltic Sea are considered extralimital. The species appears to be more common in the eastern North Atlantic than in the western. Based on strandings, the area of northern Europe appears to be the center of abundance. There is a single record from Florida in the Gulf of Mexico, but this appears to represent an extralimital wandering. As with other members of the genus, they occur almost exclusively in deep waters past the continental shelf edge.","Very little is known of the subpopulation biology of this species, other than the fact that it is not rare. It is one of the most commonly seen mesoplodonts in some parts of its range. Abundance is often underestimated using visual survey methods because they dive for long periods and are inconspicuous when they surface (Barlow 1999).","Very little is known of the natural history of this species beyond what has been learned from occasional sightings and strandings (see Pitman 2002), which have generally involved singles and pairs. However, in several sightings observed at sea off Nova Scotia, groups ranged in size from 3-10 and some were of mixed composition. Mass strandings of up to six individuals of this species have been recorded. Recorded dives lasted 12-28 minutes (Hooker and Baird 1999). These whales often bring their heads up out of the water at a 45° angle when surfacing, and often arch their backs relatively high when diving. Breaching, spy-hopping, and fluke-slapping have been observed in sightings at sea. There have also been some instances in which the animals approached vessels.Although it is one of the most commonly stranded Mesoplodon species, there have been few sightings at sea, and it is poorly known. De Buffrénil (1995) mentioned that two sightings were north of Scotland and west of the Orkney Islands, in waters several hundred metres deep. Hooker and Baird (1999) observed groups of Sowerby's beaked whales in the Gully, a submarine canyon off eastern Canada, on four occasions. Sightings were in water depths of between 550 and 1500 m. Sowerby's beaked whales feed on squid and small fish, including Atlantic cod (Gadus morhua). Ostrom et al. (1993) evaluated the diet of Sowerby's beaked whales, based on isotopic comparisons among northwestern Atlantic cetaceans.","There is little specific information on the status or threats to this species (Reeves et al. 2003). However, some are known to have been incidentally killed by whalers in Newfoundand, Iceland, and in the Barents Sea. A few entanglements in fishing gear (e.g. driftnets) have been documented. Like other beaked whales, this species is likely to be susceptible to acoustic trauma caused by loud anthropogenic sounds like those generated by navy sonar exercises (Cox et al. 2006)","The species is poorly known. However, its distribution spans most of the North Atlantic and strandings do occur on the west and east coasts of the Atlantic ocean. Range states should be encouraged to conduct more coordinated research efforts (Culik 2004).",Species account by IUCN SSC Cetacean Specialist Group; regional assessment by European Mammal Assessment team +ANIMALIA,CHORDATA,MAMMALIA,CETARTIODACTYLA,ZIPHIIDAE,Mesoplodon densirostris,,No,No,DD,,DD,,"The range of this species does not qualify as threatened under criterion B. It cannot be ruled out that the regional population of this species is small enough to warrant listing under criteria C-D. Population trend or abundance data for this species are unavailable. As with other beaked whales, threats that could cause widespread declines include high levels of anthropogenic sound, especially military sonar and seismic surveys, and bycatch. The combination of possible declines driven by vulnerability to high-level anthropogenic sound sources and bycatch is believed sufficient that a 30% reduction over three generations could not be ruled out. Therefore, the species is currently considered to be Data Deficient.",Unknown,"Blainville's beaked whales occur in temperate and tropical waters of all oceans (Mead 1989). This species has the most extensive distribution of any species of the genus Mesoplodon, and is also the most tropical of the genus (Pitman 2002, MacLeod et al. 2006). Like other beaked whales, they are found mostly offshore in deep waters, but they may sometimes occur reasonably close to shore (MacLeod and Zuur 2005). Sightings are also common around some oceanic archipelagos, like the Hawaiian (USA) and Society Islands (French Polynesia). They occur in many enclosed seas with deep water, such as the Gulf of Mexico, Caribbean Sea, and the Sea of Japan. However, there are only rare records of this species occurring in the Mediterranean, and therefore the species is considered to be a vagrant there.","Overall, the species appears to be fairly common in most tropical seas, and it is one of the most common of all the species of Mesoplodon (Reeves et al. 2003). Estimates of abundance are generally not available for most areas, but there are estimated to be 2,138 (CV=77%) in Hawaiian waters (Carretta et al. 2006). Abundance is often underestimated using visual survey methods because they dive for long periods and are inconspicuous when they surface (Barlow 1999).","There is more information available on the behavior and ecology of Blainville’s beaked whale than for any other species of Mesoplodon (Reeves et al. 2003). There is a subpopulation of this species that is being studied in detail in the Bahamas (Balcomb 1981, MacLeod and Zuur 2005). Individual whales have been identified, based on natural marks. This represents only the second case that a beaked whale subpopulation has undergone long-term behavioral and ecological study (the other case is northern bottlenose whales in the Gully). Groups of 3-7 Blainville's beaked whales have most often been recorded, although singles or pairs are most common. In the Bahamas, adults are generally grouped into what appear to be ‘harems’, with a single adult male accompanying several adult females. Subadults appear to stay in separate groups. The harems tend of occur in more productive waters over the continental shelf canyon walls, while subadults tend to occur in less productive waters inshore and offshore of these areas.Although there is not a great deal know of habitat preferences for beaked whales, there is more known for this species than for any other in the genus. A detailed analysis of habitat preferences in the Bahamas, where this species is commonly encountered, indicated that Blainville’s beaked whales were found preferentially in waters of intermediate depth gradients and depths between 200 and 1,000 m (continental slope waters). These may be areas of increased prey availability caused by interactions of currents and local topography (MacLeod and Zuur 2005). Observations around Hawaii seem to indicate that animals prefer water depths of 700 - 1000m (Baird et al. 2006). Dives of up to 1,400 m and over 54 minutes have been recorded in Hawaiian waters (Baird et al. 2006). Squid are apparently the main food items, but some deepwater fish may be taken as well. Like most other ziphiids, they are thought to be suction feeders (Heyning and Mead 1996) .","No incidental or directed catches of this species have been recorded in European waters, although they have been recorded elsewhere in the species' global range. Like other beaked whales, this species appears to be highly vulnerable to mortality associated with naval sonar exercises (Cox et al. 2006). Subadult whales, found in more offshore waters, may be more susceptible (Anonymous 2001). At least one animal died in September 2002 during a naval exercise conducted around Gran Canaria, Canary Islands (Vidal Martin pers. comm.). Another two specimens live stranded during a naval exercise off the Bahamas in March 2000 (Rowles et al. 2000). High intensity Low Frequency Active Sonar (LFAS) was used by US and NATO vessels in both these areas, respectively, which apparently led to a multi-species mass stranding in the Bahamas, including both M. densirostris and Ziphius cavirostris (Balcomb and Claridge 2001).Concerns regarding the impact of man-made debris in the marine environment are increasing. Pollution in the form of plastic debris has been recently recognised as a major threat to marine wildlife, in terms of ingestion and entanglement. On 27 February 1993, a 419 cm adult female Blainville's beaked whale was found washed ashore in an advanced state of decomposition at Mar Grosso Beach (32°07'S, 52°02'W), Sao Jose do Norte, southern Brazil (Secchi and Zarzur 1999). Stomach analysis revealed the presence of a blueish bundle of plastic threads occupying a large part of the main stomach chamber. Both stomach and intestines were completely free of parasites, as well as food remains and faeces, indicating that the whale had not fed for some time.","The species is poorly known with respect to abundance, migratory patterns, by-catch and direct catch rates. Range states should be encouraged to conduct more coordinated research efforts.",Species account by IUCN SSC Cetacean Specialist Group; regional assessment by European Mammal Assessment team +ANIMALIA,CHORDATA,MAMMALIA,CETARTIODACTYLA,ZIPHIIDAE,Mesoplodon europaeus,,No,No,DD,,DD,,"The range of this species does not qualify as threatened under criterion B. It cannot be ruled out that the regional population of this species is small enough to warrant listing under criteria C-D. Population trend or abundance data for this species are unavailable. As with other beaked whales, threats that could cause widespread declines include high levels of anthropogenic sound, especially military sonar and seismic surveys, and bycatch. The combination of possible declines driven by vulnerability to high-level anthropogenic sound sources and bycatch is believed sufficient that a 30% reduction over three generations could not be ruled out. Therefore, the species is currently considered to be Data Deficient.",Unknown,"Although sometimes depicted as a North Atlantic endemic, this species is probably continuously distributed in deep waters across the tropical and temperate Atlantic Ocean, both north and south of the equator (Mead 1989, MacLeod et al. 2006). Most records are from the east and Gulf coasts of North America, from New York to Texas, but Gervais' beaked whales are also known from several of the Caribbean islands. This is the most commonly-stranded beaked whale in the southeastern United States. In the eastern Atlantic, they are known from Ireland to Guinea-Bissau in West Africa. There is only one record of this species entering the Mediterranean, and it is considered a vagrant there (Podesta et al. 2005).","No specific estimates of abundance exist; however estimates indicate that 106 (CV=41%) mesoplodonts occur in the northern Gulf of Mexico, which are considered to be either M. densirostris or M. europaeus (Waring et al. 2006). Based on the frequency with which they strand, they are presumed to be relatively common in waters along the east coast of North America. Abundance is often underestimated using visual survey methods because they dive for long periods and are inconspicuous when they surface (Barlow 1999).","Gervais' beaked whales have only been reliably identified alive in the wild on a few occasions (Pitman 2002), mostly in the eastern Atlantic, although many Mesoplodon sightings in the Gulf of Mexico are thought to have been of this species. Around the Canary Islands, they sometimes lift their heads out of the water upon surfacing. Live-stranded individuals have been held in captivity for short periods of time.Like other members of the genus, the species prefers deep waters based on the presence of prey from such habitats in stomach contents and a lack of sightings near shore (Mead 1989). Strandings and the few possible sightings suggest that the species prefers tropical and subtropical waters (MacLeod et al. 2006).Like other members of the genus, Gervais’ beaked whales are known to feed primarily on squid, although some fish may be taken as well (Norman and Mead 2001). Growth layer group counts in the teeth of one specimen suggest they live to at least 48 years of age (Mead 1984).","Specimens of Gervais’ beaked whale have been entangled and killed in pound nets off New Jersey. Like other beaked whales, this species is highly sensitive to disturbance and mortality from loud anthropogenic sounds such as naval sonar exercises (Cox et al. 2006). Several atypical mass strandings of beaked whales, including Gervais' beaked whales, were associated with naval activities: mid to late 1980s on the Canary Islands (Waring et al. 2006), in March 2000 on the Bahamas (Rowles et al. 2000, Anonymous 2001) and again in September 2002 during a naval NATO maneuver involving low frequency sonar around the Canaries (Vidal pers. comm.).Finally, all beaked whales seem to be susceptible to the ingestion of plastic bags, which are of widespread occurrence at sea and have been linked to detrimental health effects in several cetacean species.",No specific conservation measures are known for this species.,Species account by IUCN SSC Cetacean Specialist Group; regional assessment by European Mammal Assessment team +ANIMALIA,CHORDATA,MAMMALIA,CETARTIODACTYLA,ZIPHIIDAE,Mesoplodon mirus,,No,No,DD,,DD,,"The range of this species does not qualify as threatened under criterion B. It cannot be ruled out that the regional population of this species is small enough to warrant listing under criteria C-D. Population trend or abundance data for this species are unavailable. As with other beaked whales, threats that could cause widespread declines include high levels of anthropogenic sound, especially military sonar and seismic surveys, and bycatch. The combination of possible declines driven by vulnerability to high-level anthropogenic sound sources and bycatch is believed sufficient that a 30% reduction over three generations could not be ruled out. Therefore, the species is currently considered to be Data Deficient.",Unknown,"True's beaked whales appear to have a disjunct, antitropical distribution (Mead 1989, MacLeod et al. 2006). In the Northern Hemisphere, they are known only in the North Atlantic, from records in eastern North America (Nova Scotia to Florida), Bermuda, Europe to the Canary Islands, the Bay of Biscay, and the Azores. They also occur at least in the southern Indian Ocean, from South Africa, Madagascar, southern Australia and the Atlantic coast of Brazil (MacLeod et al. 2006). The species does not generally occur within 30° north or south of the equator, which may indicate that the northern and the southern subpopulations are isolated from one another. This is supported by morphological and coloration differences (Ross 1969, Ross 1984). This peculiar disparate distribution pattern suggests that there may actually be separate species or subspecies in the Northern and Southern Hemispheres; however, this is not confirmed.","Until recent years, True’s beaked whales had been only rarely identified at sea, and there are no estimates of abundance. The species is not rare, however, at least in the North Atlantic. Abundance of beaked whales is often underestimated using visual survey methods because they dive for long periods and are inconspicuous when they surface (Barlow 1999).","Since True’s beaked whale has rarely been identified alive in the wild, and is not one of the most commonly-stranded species, there is little information available on its natural history (see Pitman 2002). Groups observed at sea have consisted of up to three individuals. They may show their beaks when surfacing. Known mainly from stranded specimens, M. mirus is probably a deep water pelagic species, like other ziphiids (Houston 1990). Like other members of the genus, stranded animals have had squid (mostly Loligo spp.) in their stomachs. They may also take fish, at least occasionally. Stable isotope analysis has found that this species feeds at a similar trophic level to other Mesoplodon species with which it is sympatric, but at lower trophic level than Cuvier’s beaked whale and the northern bottlenose whales which suggests that it feeds on smaller prey than these latter species (MacLeod 2005).","Almost no information is available on the threats and status of this species. It appears never to have been hunted. Mesoplodonts have been taken occasionally by whalers but are not presently the main targets of any hunt. Entanglement in fishing gear, especially gillnets in deep water (e.g. for billfish and tuna), is probably the most significant threat. Like other beaked whales, this species is likely to be sensitive to disturbance and mortality from loud anthropogenic sounds such as naval sonar exercises (Cox et al. 2006).As a temperate water species, True's beaked whale may be vulnerable to the effects of climate change as ocean warming may result in a shift or contraction of the species range as it tracks the occurrence of its prefered water temperatures (Learmonth et al. 2006). Finally, all beaked whales seem to be susceptible to the ingestion of plastic bags, which are of widespread occurrence at sea and have been linked to detrimental health effects in several cetacean species.",No conservation measures for this species are known.,Species account by IUCN SSC Cetacean Specialist Group; regional assessment by European Mammal Assessment team +ANIMALIA,CHORDATA,MAMMALIA,CETARTIODACTYLA,ZIPHIIDAE,Ziphius cavirostris,Recent genetic analysis confirmed that this genus is monotypic (Dalebout et al. 2005).,No,No,DD,,DD,,"The range of this species does not qualify as threatened under criterion B. It cannot be ruled out that the regional population of this species is small enough to warrant listing under criterion C. Population trend or abundance data for this species are unavailable. As with other beaked whales, threats that could cause widespread declines include high levels of anthropogenic sound, especially military sonar and seismic surveys, and bycatch. The combination of possible declines driven by vulnerability to high-level anthropogenic sound sources and bycatch is believed sufficient that a 30% reduction over three generations could not be ruled out. Therefore, the species is currently considered to be Data Deficient.",Unknown,"Cuvier's beaked whales may have the most extensive range of any beaked whale species (Heyning 1989, 2002). They are widely distributed in offshore waters of all oceans, from the topics to the polar regions in both hemispheres. Their range covers most marine waters of the world, with the exception of shallow water areas, and very high-latitude polar regions. They are found in many enclosed seas, such as the Gulf of California, Gulf of Mexico, Carribean Sea, Sea of Japan, and the Sea of Okhotsk (but not in the Baltic or Black seas). This is the only species of beaked whale regularly found in the Mediterranean Sea, where it is quite common (Podesta et al. 2006).","Global abundance has not been estimated for Cuvier’s beaked whales, but abundance has been estimated for several study areas (not in European waters). Abundance is often underestimated using visual survey methods because they dive for long periods and are often inconspicuous when they surface (Barlow et al. 2006). They are undoubtedly among the most common and abundant of all the beaked whales. However, it should be noted that there are no trend data, and the large uncertainty in abundance estimates makes the detection of population change extremely unlikely.This is the only widely-distributed beaked whale species for which a global assessment of genetic diversity has been conducted. The results of this study suggest that there is probably little movement of Cuvier’s beaked whales among different ocean basins, and that there may even be a distinct subpopulation in the Mediterranean Sea (Dalebout et al. 2005).","Due to their widespread distribution and relatively frequent stranding, Cuvier's beaked whale may be one of the most familiar of the beaked whales (Heyning 1989, 2002). They are found mostly in small groups of 2-7, but are not uncommonly seen alone. Strandings are usually of singletons or cow-calf pairs. A typical mass strandings of larger numbers of animals have been strongly linked acoustic trauma resulting from navy sonar or seismic exploration activities in the vicinity (e.g. Frantzis 1998). Their behavior tends to be rather elusive, and they can be difficult to approach. However, they have been seen breaching on a number of occasions. Dives of up to 40 minutes have been documented.Although Cuvier’s beaked whales can be found nearly anywhere in deep (>200 m) waters, they seem to prefer waters near the continental slope, especially those with a steep sea bottom. The species is known around many oceanic islands, and in some enclosed seas. It is rarely found close to mainland shores, except in submarine canyons or in areas where the continental shelf is narrow and coastal waters are deep (Heyning 1989, 2002) and is mostly a pelagic species that appears to be confined by the 10° C isotherm and the 1000 m bathymetric contour (Houston 1991, Robineau and di Natale 1995).Cuvier's beaked whales, like all beaked whales, appear to prefer deep waters for feeding. Although few stomach contents have been examined, they appear to feed mostly on deep-sea squid, but also sometimes take fish and some crustaceans (MacLeod et al. 2003). They apparently feed both near the bottom and in the water column. As with other beaked whales, suction appears to be used to draw prey items into the mouth at close range (Heyning and Mead 1996). They may sometimes incidentally ingest non-food items.","Never the main target of commercial whalers, Cuvier’s beaked whales have sometimes been taken in other direct fisheries outside Europe (Heyning 1989, Jefferson et al. 1993). Bycatch of Cuvier’s beaked whales has been reported in several fisheries, including the Italian swordfish fishery (Notarbartolo di Sciara 1990). Mignucci et al. (1999) conducted an assessment of cetacean strandings in waters off Puerto Rico, the United States and the British Virgin Islands to identify the factors associated with reported mortality events between 1867 and 1995. Cuvier's beaked whale was the second most common species. An increase in the number of strandings is evident over the past 20 years, averaging 63.1% per year. Between 1990 and 1995, the average number of cases per year increased from 2.1 to 8.2. The seasonal pattern of strandings was not found to be uniform, with a high number of strandings occurring in the winter and spring. The most common human-related cause categories observed were entanglement and accidental captures, followed by animals being shot or speared. Evidence from stranded individuals of several similar species of beaked whales indicates that they have swallowed discarded plastic items. Sometimes this may happen when animals are already ill and incapable of finding/catching normal prey (e.g. Gomercic et al. 2006), or they may be healthy and eat it by accident and it then contributes to blockage of the digestive tract and eventual death (e.g. Scott et al. 2001). Therefore Ziphuis cavirostris may also be at risk.In recent years, there has been increasing concern that loud underwater sounds, such as active sonar and seismic operations, may be harmful to beaked whales (Malakoff 2002). The use of active sonar from military vessels has been implicated in a number of mass strandings of Cuvier’s beaked whales, including in the Mediterranean Sea during 1996 (Frantzis 1998), the Bahamas during 2000 (Balcomb and Claridge 2001), the Madeira Islands in 2000 (Freitas 2004) and the Canary Islands in 2002 (Jepson et al. 2003). The mechanistic cause of the strandings is not well understood, but gas bubble formation (Fernandez et al. 2005) from a behaviorally mediated response to sound has been proposed (Cox et al. 2006).","Very little is known about this species. However, mass strandings after military sonar tests are a matter of serious concern and should be further investigated. The global effects of bycatches in fisheries cannot be evaluated. Bycatch of Cuvier’s beaked whales may have been unsustainable in the California/Oregon drift gillnet fishery in the early 1990s (Barlow et al. 1995), however, the observed bycatch of Cuvier’s and other beaked whales dropped to zero after pingers were required to reduce cetacean mortality (Barlow and Gisiner 2006). Given this success, pingers might be useful in mitigating fishery bycatch in other locations. Because they dive for such long periods and are so difficult to see at the surface, mitigation methods that depend on visually detecting them are not likely to reduce the impacts of acute sound impacts (such as military sonar or seismic surveys) (Barlow and Gisiner 2006). Areas of higher than average abundance can be identified (Ferguson et al. 2006, MacLeod and Mitchell 2006), and avoiding such areas may be a helpful mitigation method.",Species account by IUCN SSC Cetacean Specialist Group; regional assessment by European Mammal Assessment team +ANIMALIA,CHORDATA,MAMMALIA,CHIROPTERA,MOLOSSIDAE,Tadarida teniotis,,No,No,LC,,LC,,"European regional assessment: Least Concern (LC)EU 25 regional assessment: Least Concern (LC)The species is widely distributed over a large extent of occurence. lt occurs in urban areas and forages in other modified habitats. Population trends are not known, but are not believed to approach the threshold for the population decline criterion of the IUCN Red List. Consequently it is classed as Least Concern.",Unknown,"It is mainly a western Palaearctic species, although the south-eastern edge of its range extends into the Indomalayan region. It is well known in the Mediterranean basin, occuring from Portugal, Spain, Morocco, and Algeria eastwards through north Africa and southern Europe to Israel, Jordan, Saudi Arabia, Iran, Iraq, Azerbaijan, Turkmenistan, Afghanistan, Bengal (India), and possibly Yunnan (China)(Wilson and Reeder 2005). It is also found on Madeira (Portugal), the Canary Islands (Spain), and a number of Mediterranean islands (Hutson 1999, Wilson and Reeder 2005). It occurs from sea level to 3,100 m.","It is a common species in suitable habitats. Summer and winter colonies typically number 5-100 individuals, although colonies of up to 300-400 animals have been recorded. It is probably sedentary, although seasonal in some areas, e.g. Malta. It is not abundant in the Caucasus, nor is it highly gregarious - large colonies are not known in this region (K. Tsytsulina pers. comm. 2005) There are only six records for Iran, however there have not been extensive survey efforts there (M. Sharifi pers. comm. 2005).","It usually forages at 10-50 m above the ground over temperate to sub-desert habitats, although it also occurs humid habitats in some areas (e.g. Turkey: A. Altiparmak pers. comm. 2005) It feeds on aerial drifts of insects including moths and neuropterans. Summer and winter roosts: fissures and hollows in rock outcrops, quarries and cliffs. Common in some urban areas, roosts also in artificial structures, including bridges and buildings, and sometimes in the roof of high caves. The species is probably sedentary (Hutterer et al. 2005).","It is negatively affected by disturbance and loss of roosts in buildings, and by use of pesticides. It is also potentially threatened by wind farms (European Mammal Assessment workshop 2006), and deforestation affects the species in some parts of its range (Z. Amr pers. comm. 2005). However, none of these are considered to be major threats at present.","It is protected by national legislation in most range states, and receives international legal protection through the Bonn Convention (Eurobats) and Bern Convention. It is included in Annex IV of EU Habitats and Species Directive, and there is some habitat protection for the species through Natura 2000.","Tony Hutson, Friederike Spitzenberger, Javier Juste, Stéphane Aulagnier, Petr Benda" +ANIMALIA,CHORDATA,MAMMALIA,CHIROPTERA,PTEROPODIDAE,Rousettus aegyptiacus,,No,No,NA,,NA,,European regional assessment: Not Applicable (NA)EU 25 regional assessment: Not Applicable (NA)Classed as Not Applicable as it is of marginal occurrence in Europe.,-,"Found in ""Senegal and Egypt south to South Africa; Cyprus, Turkey, Jordan, Lebanon, Israel, S Syria, Yemen, Saudi Arabia, S Iraq, S. Iran, Pakistan, NW India; islands in the Gulf of Guinea (São Tomé and Príncipe); adjacent small islands"" (Wilson and Reeder 2005). Less than 1% of its global range falls within the European Mammal Assessment region.",,,,,European Mammal Assessment team +ANIMALIA,CHORDATA,MAMMALIA,CHIROPTERA,RHINOLOPHIDAE,Rhinolophus blasii,,No,No,VU,A4c,DD,,"European: This species has disappeared from a significant part of its European range during the last 50 years (generation time = 9 years). Some Mediterranean woodlands have disappeared in recent years, but the rate of habitat loss is unknown. Cave disturbance is a further threat to the species. For a closely related species, R. mehelyi, the rate of decline has been estimated as 10% in the last 10 years in Andalucia and is expected to reach 30% in a time window including 20 years in the future for entire range. Although R. blasii does not occur in the Iberian peninsula, it has very similar habitat requirements and may face the same threats. For these reasons, R. blasii is classed as Vulnerable because it is suspected that it will undergo population declines exceeding 30% over the next three generations. It is not anticipated that there would be a significant rescue effect from outside the European region, as populations are considered to be generally declining across the global range.EU 25: In the EU 25, this species is found only in Greece (and some associated islands) and Cyprus. Little information is available on the status of the species in this area. Consequently it is classed as Data Deficient.",Unknown,"Rhinolophus blasii has a large range in the Palaearctic and the Afrotropics, throughout which it is widely but patchily distributed. In Africa, it occurs from north-eastern South Africa and the Democratic Republic of Congo to Ethiopia and Somalia, and in North Africa. In Asia, it has a patchy distribution extending from Turkey in the west to Pakistan in the east, and from the Caucasus in the north to Yemen in the south (Wilson and Reeder 2005). It was confirmed in Georgia in 2006 (Z. Nagy pers. obs.). In Europe, it is extinct in northeastern Italy and has not been recorded in Slovenia during the last 50 years (Kryštufek and Dulic 2001). It is now restricted to the Balkan peninsula and to some Mediterranean islands including Crete and Cyprus. There are no recent records in Romania and northern Bulgaria despite intensive work by Christian Dietz (Z. Nagy pers. comm. 2006). Past records from this area are disputed: no specimen has been found in museums in Romania, and the presence of R. euryale in the same area might have caused confusion (Z. Nagy pers. comm. 2006). It occurs from sea level to 2,215 m in Yemen.","A rare or infrequent species, probably the rarest horseshoe bat in Europe (Kryštufek 1999). Summer colonies of ca. 20-30 are typical, although up to 300 females may be found in a single colony. In winter, it congregates in mixed-species clusters with other Rhinolophus species (up to 800 animals in Bulgaria). There are large colonies in Bulgaria and Greece. It is suspected to be declining because of loss of Mediterranean woodlands and cave disturbance, and is considered vulnerable in many range states.","In the Mediterranean region it typically forages in shrubland and woodland, although it may penetrate to desert habitat (Amr 2000). Summer roosts are situated in natural and artificial underground sites, with attics also being used in the northern part of the range. In winter, it hibernates in underground sites. This species is considered to be sedentary (Hutterer et al. 2005).","Threats to the species include loss of Mediterranean woodlands, disturbance and loss of underground habitats, and destruction of roost sites (Kryštufek 1999). In a number of range states the species is disturbed by tourist visits to caves.","It is protected by national legislation in some range states. There are international legal obligations for the protection of this species through the Bonn Convention (Eurobats) and Bern Convention. It is included in Annex II (and Annex IV) of the EU Habitats & Species Directive, and hence requires specific conservation measures, including the designation of Special Areas for Conservation. It receives some habitat protection through Natura 2000. Taxonomic research is needed to clarify the status of African populations. Monitoring and protection of caves is also required.","Tony Hutson, Friederike Spitzenberger, Stéphane Aulagnier, Zoltan Nagy" +ANIMALIA,CHORDATA,MAMMALIA,CHIROPTERA,RHINOLOPHIDAE,Rhinolophus euryale,,No,No,VU,A2c,VU,A2c,"European and EU 25: Many European range states have reported that populations have declined and colonies have disappeared over the last 27 years (=3 generations). It is inferred that regional population decline has exceeded 30% over that period, so the species is assessed as Vulnerable (A2bc). It is not expected that there would be a rescue effect from populations outside the region, as these are suspected to be declining too.",Unfavourable,"Rhinolophus euryale is a western Palaearctic species, occurring in southern Europe, north-west Africa (Morocco to Tunisia), and the Near East. It is widely distributed over its range, and is found from sea level to 1,000 m.","An infrequent species. Summer colonies number ca. 50-500 individuals (formely up to 1,500 animals). Winter clusters typically number up to 2,000 animals. It occurs in large vulnerable colonies, and is considered threatened in many range states. Large population declines have been reported in a number of European countries, including Spain (Palomo and Gisbert 2002) and Slovakia (Ibáñez 1999). In France, the population declined by ca. 70% between 1940 and 1980, although subsequently the trend appears to have stabilised (Brosset et al. 1988, S. Aulagnier pers. comm. 2006). Apart from R. blasii, which may have gone extinct in the country, R. euryale is probably the rarest rhinolophid in Italy, and anecdotal evidence suggests that a number of colonies have declined in the past few decades (D. Russo pers. comm. 2006). From 1960-2000 the species disappeared from a number of sites in Romania, but the trend over the last five years appears to be stable (Z. Nagy pers. comm. 2006). The species has a very small and declining population in Portugal (Rodrigues et al. 2003, Cabral et al. 2005).There is little information on population trends outside Europe, although it is suspected that continuing declines have also occurred in at least parts of the non-European range. For example, in Iran the species is no longer found in caves which 30 years ago held 20,000 individuals of different species (M. Sharifi pers. comm. 2005). It is considered to be declining in North Africa (GMA Africa workshop 2004).","It forages in Mediterranean and sub-Mediterranean shrubland and woodland, feeding on moths and other insects. In Italy, preferred foraging habitats are broadleaved woodland and riparian vegetation; coniferous woodland is avoided, and shrubland is rarely used (Russo et al. 2002). Summer roosts are located in natural and artificial underground sites, as well as attics in some part of the range. In winter it hibernates in underground sites (usually large caves with a constant microclimate). It is a sedentary species (the longest recorded distance travelled by an individual is 134 km) (Heymer 1964 in Hutterer et al. 2005).","Threats include loss of foraging habitat, and disturbance and loss of underground habitats. On a landscape scale, fragmentation and loss of linear elements such as hedgerows and riparian vegetation is a problem because such elements are used for commuting. The species' strong dependence upon caves for roosting makes it particularly sensitive to cave disturbance, such as that from caving or tourism. Tourist disturbance of caves affects the species in a number of range states, including Italy, Iran and Turkey (M. Sharifi and A. Karatash pers. comm. 2005, D. Russo pers. comm. 2006). The use of organochlorine pesticides is believed to have contributed to the earlier dramatic decline of the species in France (Brosset et al. 1988).","It is protected by national legislation in most range states. There are also international legal obligations for protection of this species through Bonn Convention (Eurobats) and Bern Convention. It is included in Annex II (and IV) of EU Habitats & Species Directive, and hence requires special measures for conservation including designation of Special Areas for Conservation. There is some habitat protection through Natura 2000, and some roosts are already protected by national legislation). The species is directly or indirectly benefiting from EU LIFE-funded projects in France, Spain, Italy, and Romania.","Tony Hutson, Friederike Spitzenberger, Javier Juste, Stéphane Aulagnier, Margarida Fernandes, Juan Tomas Alcaldé" +ANIMALIA,CHORDATA,MAMMALIA,CHIROPTERA,RHINOLOPHIDAE,Rhinolophus ferrumequinum,"Although Thomas (1997, unpublished thesis) found very high divergence in mitochondrial DNA sequences, Csorba et al. 2003 refrained from splitting Japanese greater horseshoe bats (“Rhinolophus nippon”) from Rh. ferrumequinum. Several subspecies are identified over the range, of which two occur in the western Palaearctic: Rh. f. creticus (Crete) and Rh. f. ferrumequinum (rest of western Palaearctic range).",No,No,NT,,NT,,"European and EU 25: Near Threatened (approaching A2bc). Although population trends vary in different parts of the range, overall the species is suspected to be declining at a rate that approaches 30% over the last three generations. It needs continued conservation action to maintain its status.",Unfavourable,"Rhinolophus ferrumequinum has a wide range in the Palaearctic encompassing north-west Africa; southern and central Europe from Portugal to Greece and north to southern England, France, Germany, Austria, Czech Republic, Slovakia, and Bulgaria; Turkey, Cyprus, Israel, Jordan and Iraq and Iran; Ukraine, Crimea, and Caucacus regions; Turkmenistan, Uzbekistan, southern Kazakhstan, Afganistan, Pakistan, northern India, Nepal, Sikkim, China (Wilson and Reeder 2005), Korea and Japan (Csorba et al. 2003). It usually occurs below 800m, but can be found up to 3,000m in the Caucasus depending on roost availability and humidity (K. Tsytsulina pers. comm. 2005).","The two most widespread Rhinolophus species in Europe, R. ferrumequinum and R. hipposideros, are of particular conservation concern and are the subject of considerable research and monitoring. R. ferrumequinum has shown marked declines in range in northwest Europe within the last 100 years (e.g. United Kingdom, Germany, Austria), and has gone extinct in some countries (e.g. Belgium, Netherlands). However there are signs of stabilisation and/or recovery in some northwest European countries (Hutson et al. 2001). For example, In the UK the species declined massively in the past but is now stable at low population level (around 5,000 individuals) (Ransome and Hutson 2000). However in Austria declines continue, with population reductions of 70% in the last 10 years (from 100 to 30 breeding individuals: Spitzenberger 2002, F. Spitzenberger pers. comm. 2006). In other parts of Europe, trends vary and are generally less well known: in Malta the species has gone extinct, in Portugal and Spain the trend is not known (although some colonies have disappeared in Spain) (Palomo and Gisbert 2002, Cabral et al. 2005), in Croatia the population is thought to be stable (N. Tvrtkovic pers. comm.), and in Romania the population has been slowly increasing since 1989 due to reduced use of pesticides and return to traditional agriculture. In Switzerland the species is very rare (3 maternity roosts with some 200 individuals), but the population trend appears stable (H. Kraettli pers. comm. 2006).It is an infrequent species in most parts of its range, although in at least parts of south-west Asia and the Caucasus it is abundant and widespread (it is the most frequently reported species in Turkey: A. Karatash pers. comm. 2005), with populations in Iran and Turkey considered to be stable (A. Karatash, M. Sharifi and K. Tsytsulina pers. comm. 2005), although it may be decreasing in Russian parts of the Caucasus (S. Kruskop pers. comm. 2005). Summer colonies of c.30-200 individuals (up to 400 animals), and winter clusters of up to 500 animals are typical.","It forages in pastures, deciduous temperate woodland, Mediterranean and sub-mediterranean shrubland and woodland. Feeds on beetles and moths at low level in pastures and in trees (by aerial hawking or perch feeding).Summer roosts are located in warm natural and artificial underground sites, and attics in the northern part of the range. Where the species occupies buildings, it requires particular features of the building itself, as well as proximity to good foraging areas and underground sites for torpor at various times of year and for winter hibernation (Hutson et al. 2001). In winter it hibernates in cold underground sites (usually large caves). A sedentary species, distances of 20-30 km between winter and summer roosts are typical (longest distance recorded 180km: de Paz et al. 1986).","The main threats are fragmentation and isolation of habitats, change of management regime of deciduous forests and agricultural areas, loss of insects due to pesticide use, and disturbance and loss of underground habitats and attics. In northwest Europe, habitat change is likely to have been amongst the major causes of declines, the conversion of woodland and small-field landscape to large-scale agricultural land being particularly damaging. While declines elsewhere, particularly in eastern Europe, may currently not be so marked, the loss of cultural landscapes in those countries as they move towards western-style economies may have significant effects in the near future. The use of pesticides has been a recognized threat to the insect food, particularly where these have been directed against the larvae of favoured food items, such as melolonthid beetles, larvae of noctuid moths or crane-flies. Favoured prey may be affected secondarily by pesticide use, such as the loss of dung fauna from the use of persistent anti-parasitic drugs (avermectins) on cattle. Populations in caves and other underground habitats have suffered from increased disturbance (e.g. by tourist visits), changes of use and the destruction of such sites. In buildings colonies may be affected by human intolerance, renovation work or the application of pesticides, such as some of those used for the remedial treatment of timbers (Hutson et al. 2001).","The greater horseshoe bat has been the subject of widespread conservation activity, especially in Europe. Until recently, this has concentrated on roosts in buildings and caves. Many buildings used as roosts have management agreements and many underground sites have been protected. Nevertheless, sites continue to be lost or damaged. More recently, attention has turned to identifying more precisely the food and foraging requirements. A European meeting (Germany, May 1995) discussed the status and conservation needs for the species on a pan-European scale. The Bern Convention has commissioned a Europe-wide Species Action Plan under the Pan-European Biological and Landscape Diversity Strategy (Ransome and Hutson 2000). It is protected by national legislation in most range states (not Russia: K. Tsytsulina pers. comm. 2005). There are international legal obligations for its protection through the Bonn Convention (Eurobats) and Bern Convention. It is included in Annex II (and IV) of the EU Habitats and Species Directive, and hence requires special measures for conservation including designation of Special Areas for Conservation. There is some habitat protection through Natura 2000 (and some roosts are already protected by national legislation).","Tony Hutson, Friederike Spitzenberger, Javier Juste, Stéphane Aulagnier, Margarida Fernandes, Juan Tomas Alcaldé" +ANIMALIA,CHORDATA,MAMMALIA,CHIROPTERA,RHINOLOPHIDAE,Rhinolophus hipposideros,,No,No,NT,,NT,,"European and EU 25: Near Threatened (approaching A2bc). The species is widespread, but there have been substantial range reductions along the northern edge of the species' distribution in Europe over the past 50 years, and declines are ongoing, albeit perhaps at a reduced rate. The species has gone extinct in the Netherlands, most of Belgium, and western Germany. It relies on continuing conservation initiatives. There is little quantitative data on population trends outside Europe, so it cannot be assumed that there would be a rescue effect from outside the region.",Unfavourable,"Rhinolophus hipposideros is widely distributed in the western and central Palaearctic. It occurs from sea level to 2,000 m.","An infrequent species in the northern part of its range. In Europe the species forms summer colonies of 10-50 individuals (up to 1,500 animals). Solitary in winter or loose aggregations up to 500 animals per roost. Since the 1950s the northern border of the range in western and central Europe has moved to the south. In the Netherlands, northern Belgium and Germany with the exception of a few colonies in Bavaria, Thüringen, Sachsen and Sachsen-Anhalt the species went extinct (Fairon et al. 1982, Schofield 1999). It disappeared from northern and western parts of Bohemia, and much of Poland where 87% of the hibernating population was lost between 1950 and 1990 (Urbanczyk 1994, Ohlendorf 1997). In Switzerland and Austria the distribution became fragmented, as colonies remained only in higher elevations (>400m) (Stutz and Haffner 1984, Spitzenberger 2002), although in Switzerland at least the population has started to slowly recover over the last 10 years (increasing from 2,200 to 2,500 adults counted in maternity roosts: H. Kraettli pers. comm. 2006). In Spain some colonies have disappeared due to the restoration of buildings, but there are no data on population trend (J. Juste and T. Alcalde pers. comm. 2006), and in France there have been some declines in the north, although large populations in the south are thought to be more stable (EMA Workshop 2006). Overall in Europe there has been a substantial decline over the last 50 years, with a slow decline continuing at present.In the southwest Asian part of the range it gathers in wintering colonies of up to 40 animals, although it is mainly solitary (K. Tsytsulina pers. comm. 2005). In Turkey it is a commonly reported species, and the population is stable (A. Karatash pers. comm. 2005). It is common in Iran although encountered less frequently than R. ferrumequinum (M. Sharifi pers. comm. 2005). It is not known how abundant this species is in Jordan and Syria but it may be more common than the collection reports indicate (Amr 2000).","Forages close to ground within and along the edges of broadleaf deciduous woodland, riparian vegetation, Mediterranean and sub-Mediterranean shrubland. Feeds mainly on midges, moths and craneflies. Summer roosts (breeding colonies): natural and artificial underground sites in the southern part of the range, attics and buildings in the northern part. Winter: hibernates in underground sites (including cellars, small caves and burrows). Sedentary, winter and summer roosts usually within 5-10km (longest distance recorded 153 km: Heymer 1964 in Hutterer et al. 2005).","Threats include disturbance and loss of underground habitats and attics (conversion of attics in human habitat), change of management regime of agricultural areas (loss of tree lines and hedgerows), and fragmentation and isolation of habitats.",Protected by national legislation in most range states (but not the Russian Federation: K. Tsytsulina pers. comm. 2005). There are international legal obligations for protection through Bonn Convention (Eurobats) and Bern Convention. Included in Annex II (and IV) of EU Habitats and Species Directive and hence requiring special measures for conservation including designation of Special Areas for Conservation. Some habitat protection through Natura 2000. Recommended conservation measures include protecting maternity roosting sites and hibernation caves and foraging habitats. One potential method is compensation schemes to give people incentives to keep colonies in their houses (this is happening in one region of Spain at the moment: J. Juste and T. Alcalde pers. comm. 2006).,"Tony Hutson, Friederike Spitzenberger, Javier Juste, Stéphane Aulagnier, Margarida Fernandes, Juan Tomas Alcaldé" +ANIMALIA,CHORDATA,MAMMALIA,CHIROPTERA,RHINOLOPHIDAE,Rhinolophus mehelyi,,No,No,VU,A4c,VU,A4c,"European regional assessment: Vulnerable (VU)EU 25 regional assessment: Vulnerable (VU)This species is declining significantly throughout its range, and is close to extinction in some areas. The rate of decline has been estimated as 10% in the last 10 years in Andalucia and is expected to reach 30% in a time window including 20 years in the future. This rate of decline is inferred to be occurring throughout its global range, so no significant rescue effect is expected. Consequently it is classed as Vulnerable.",Unfavourable,"Rhinolophus mehelyi is largely restricted to the Mediterranean. It has a discontinuous distribution from north Africa and southern Europe through Asia Minor to Transcaucasia and Iran. It is patchily distributed in some large and vulnerable colonies. It occurs up to 2,000 m in High and Saharan Atlas mountains, although it is typically found at lower altitudes in other parts of its range (e.g. in Spain it tends to occur below 700 m).","An infrequent species, which is reported to have declined in all parts of its range for which data are available. In Andalucia (Spain), the rate of decline has been estimated at 10% over the last ten years. The species is close to extinction in France (Rodrigues and Palmeirim 1999), Romania (Botnariuc and Tatole 2005), and north-east Spain (J. Juste and T. Alcalde pers. comm. 2006). In France, only one individual was recorded in 2004 (S. Aulagnier pers. comm. 2006), and in Romania the population was estimated at 5,000 in the 1950s, but now numbers approximately 100 (Dumitrescu et al. 1962-1963, Botnariuc and Tatole 2005). It is also declining in southern Spain (Franco and Rodrigues 2001), Portugal (Rodrigues et al. 2003), the Russian Federation (K. Tsytsulina pers. comm. 2005), Georgia, and Morocco (SW Asia Workshop 2005). In Iran mixed-species colonies including R. mehelyi, which in the 1970s were estimated to be over 10,000 individuals, now only number a few hundred individuals (M. Sharifi pers. obs. 2005). Summer nursery colonies typically number 30-500 individuals (although colonies of up to 3,000 individuals have been recorded, separated in smaller groups within the same cave). Winter clusters consist of up to 5,000 animals.","Forages in Mediterranean and dry sub-tropical shrubland and woodland, and in dry steppes. It feeds mainly on moths, but also preys on other insects. Summer roosts are in warm caves, often in karstic regions. Winter hibernacula are in colder underground sites (usually large caves with a constant microclimate). The species only roosts in caves and does not use artifical habitats. Sedentary (longest distance recorded 90km: Palmeirim and Rodrigues 1992).","The species is affected by disturbance and loss of underground habitats, changes in foraging habitats, and destruction of caves by tourism.","It is protected by national legislation in most range states. There are also international legal obligations for its protection through the Bonn Convention (Eurobats) and Bern Convention. It is included in Annex II (and IV) of EU Habitats and Species Directive, and hence requires special measures for conservation including designation of Special Areas for Conservation. There is some habitat protection through Natura 2000 (some roosts are already protected by national legislation). An EU-LIFE funded project aims to ensure the long-term conservation of the large populations of cave and forest-dwelling bats, including this species, in Spain.","Tony Hutson, Friederike Spitzenberger, Javier Juste, Stéphane Aulagnier, Margarida Fernandes, Juan Tomas Alcaldé" +ANIMALIA,CHORDATA,MAMMALIA,CHIROPTERA,VESPERTILIONIDAE,Barbastella barbastellus,"The genus comprises two Palaearctic species with little overlap in range. Some populations described as belonging to B. leucomelas may in fact belong to B. barbastellus (J. Juste pers. comm. 2006). The population from the Canaries is at present regarded as endemic subspecies B. barbastellus guanchae (Trujillo et al. 2002, Juste et al. 2003).",No,No,VU,A3c+4c,VU,A3c+4c,"European regional assessment: Vulnerable (VU)EU 25 regional assessment: Vulnerable (VU)Large range, rare, low density and numbers. Mainly sedentary. Population is fragmented and linked to particular kinds of old forest habitats, which are declining. Does not easily colonise new areas. Declines widely reported in most of its range with a few exceptions for recent years. Status is linked to forestry practices and the decline in the number of old trees (one colony uses up to 30 old trees with holes per season). Has specific habitat and diet requirements. Listed as Vulnerable, as it is suspected that population declines will exceed >30% over a 15 year period including both the past and the future.",Unfavourable,"Barbastella barbastellus is largely restricted to central and southern Europe, although its range extends into north Africa. It is widely but patchily distributed from England and probably Ireland, Iberia to the Caucasus and from the Mediterranean coast to southern Scandinavia, and it also found in Morocco and the Canary islands. It occurs to 1,800 m in the Alps (Spitzenberger 2002), 1,900 m in the Caucasus and 2,260 m in the Pyrenees (Urbańczyk 1999, K. Tsytsulina pers. comm. 2005).","A rare or infrequent species. Summer colonies, usually c. 30. Winter clusters usually small (often solitary), but can reach 500 and, rarely, up to 1,000 in France, Poland and over 7,000 in Slovakia (Schober 2004). Up to 10 in Caucasus (K. Tsytsulina pers. comm. 2005). Extinct in the Netherlands since 1984. Last recorded in Norway in 1949, and possibly extinct (J. van der Kooij in litt. 2006). Decreases widely reported. Considered threatened in many range states. Very small numbers in large part of the range with large temporary aggregations in areas without natural caves. Populations increasing in the last 5 years in Germany now that insecticide use has been reduced (D. Kock pers. comm. 2005). Relatively frequent in woodlands in western part of Caucasus and without reported decline; rare in Ukraine (S. Kruskop pers. comm. 2005).","Forages in mature woodland, woodland edge (and agricultural edge). Feeds on small moths. Summer roosts: usually older mature woodland with maternity sites in trees (occasionally older buildings). Depends on a large number of old trees to roost in a large part of its range, because individuals change their roosts very frequently and colonies need a large number of roost sites for this reason. Winter: Hibernation may start in trees, but later underground sites are preferred. Usually in smaller numbers (up to 50) in natural caves, but in regions where these are missing in large groups in mines and bunkers. Underground habitats may be of any type, but usually very cold sites. Recorded in old mines in winter in the Caucasus (K. Tsytsulina pers. comm. 2005). Movements up to 290 km in Austria (Kepka 1960).","Loss of old mature woodland and ancient trees with loose bark or wood crevices (reforested areas are not suitable for this species: K. Tsytsulina pers. comm. 2005); disturbance and loss of underground habitats, disturbance and loss of roost sites in older buildings. In Germany, habitat loss and fragmentation (caused by inter alia infrastructure development, forestry, and the renovation or demolition of old buildings used as roost sites), and disturbance (e.g. from cave tourism) are major threats (Schulenberg 2005); accidental mortality (roadkill) is also a problem (Rudolph et al. 2003).","It is protected by national legislation in most range states. There are also international legal obligations for its protection through the Bonn Convention (Eurobats) and Bern Convention. It is included in Annex II (as well as Annex IV) of the EU Habitats and Species Directive, and hence requires special measures for conservation including designation of Special Areas for Conservation. Some habitat protection through Natura 2000. Research is underway to establish conservation requirements for this species. Recommendations include adopting forestry practices that maintain old trees in sufficient numbers.","Tony Hutson, Friederike Spitzenberger, Stéphane Aulagnier" +ANIMALIA,CHORDATA,MAMMALIA,CHIROPTERA,VESPERTILIONIDAE,Eptesicus bottae,,No,No,NA,,NA,,European regional assessment: Not Applicable (NA)EU 25 regional assessment: Not Applicable (NA)Assessed as Not Applicable as it is of marginal occurrence in Europe.,-,"Found in ""Rhodes (Greece), Turkey, Egypt, Yemen, Israel, Jordan, Iran, Iraq, Kazakhstan, Turkmenistan, Uzbekistan, Kyrgyzstan, Tajikistan, Afghanistan, east to Mongolia, NW China, and Pakistan"" (Wilson and Reeder 2005). Less than 1% of its global range falls within the European Mammal Assessment region. Altitude: to 2,100 m.","Nothing known, but nowhere common. Seems to be more common in arid regions. Colony size probably small (e.g. to c.20).","Forges over open habitats, including disturbed (e.g. agricultural) habitats and around street lights. Roosts in crevices in buildings (including ruins) and rock faces.",Not known; apparently a species that adapts to artificial habitats.,"Protected through Eurobats (Bonn Convention) and Bern Convention, and included in Annex IV of EU Habitats and Species Directive in parts of range where these apply. No specific conservation actions known.","A.M. Hutson, S. Aulagnier, P. Benda" +ANIMALIA,CHORDATA,MAMMALIA,CHIROPTERA,VESPERTILIONIDAE,Eptesicus nilssonii,Includes Eptesicus japonensis (synonym of E. nilssonii). Could be a separate form in the southwest Asia region (K. Tsytsulina pers. comm. 2005),No,No,LC,,LC,,European regional assessment: Least Concern (LC)EU 25 regional assessment: Least Concern (LC)The species is widespread and abundant and there is no indication of significant decline at present. Consequently it is classed as Least Concern.,Unknown,"Eptesicus nilssonii is a widespread Palaearctic species that occurs from France and Norway through northern and central Europe and Asia east to the Pacific seaboard and northern Japan. In Europe, it occurs north to well above the Arctic Circle, but is absent or occasional in the west (the Low Countries, UK, western France, Iberia). It occurs from sea level to 2,300 m (van der Kooij in litt. 2006).","A widespread and common species over much of its range, indeed the most abundant bat species in the north (Rydell 1999). Summer maternity colonies usually number 10-100 females.","It forages in open areas of diverse habitats, including woodland edge (or above woodland), small-scale farmland, parks and gardens with trees (van der Kooij in litt. 2006), over lakes and rivers and at street lights. In autumn, it forages and displays in high mountains above the tree line (Spitzenberger 2002). Its diet comprises small insects such as Diptera. Summer roosts are located mainly in houses, occasionally in tree holes. It may change roost sites during summer. Winter roosts are found mainly in houses, cellars, and natural and artificial underground habitats. In winter the species roosts singly or in small groups of 2-4 individuals. Long-distance movements of up to 450 km have been recorded by Tress (1994).",The main threat is likely to be disturbance of colonies in houses (and possibly when hibernating in underground habitats). However this is not thought to be a major threat to the species.,"It is protected by national legislation in most range states. There are also international legal obligations for its protection through the Bonn Convention (Eurobats) and Bern Convention in parts of range where these apply. It is included in Annex IV of EU Habitats & Species Directive, and there is some habitat protection through Natura 2000. No specific conservation actions are known.","Tony Hutson, Friederike Spitzenberger, Stéphane Aulagnier, Ioan Coroiu" +ANIMALIA,CHORDATA,MAMMALIA,CHIROPTERA,VESPERTILIONIDAE,Eptesicus serotinus,"A recent genetic study suggests that the south Iberian population may belong to a different species, probably E. isabellinus (Ibañez et al. 2006).",No,No,LC,,LC,,"European regional assessment: Least Concern (LC)EU 25 regional assessment: Least Concern (LC)A very widespread and abundant species. Global and regional population trends are difficult to determine, as the species is decreasing in some range states (sometimes dramatically) whilst increasing in others. Overall, it is not believed to approach the threshold for the population decline criterion of the IUCN Red List (i.e. declining more than 30% in ten years or three generations). For these reasons, it is evaluated as Least Concern.",Possibly Favourable,"Eptesicus serotinus is widely distributed through the Palaearctic from the Atlantic to the Pacific seaboards. It occurs north to about 57ºN in Denmark, south-west to North Africa, and east into northern parts of the Indian subcontinent and south-east Asia. Records from the Canary Islands (Lanzarote) refer to a single vagrant that died shortly after arrival (Trujillo 1991). Its altitudinal range is from sea level to to 1,440 m in the Alps (Spitzenberger 2002).","A very widespread and abundant species, with decreases recorded in some areas and increases in others. It may be increasing in some parts of northern Europe (e.g. Denmark) and decreasing in others, slightly (e.g. UK), or severely (e.g. Austria). In Austria, a 70% decline has been recorded in the eastern part of the country (the former stronghold) over the last 15 years, and the species is now absent from lowland regions with bare arable land (F. Spitzenberger pers. comm. 2006). It is suspected to be declining in the rest of Pannonian basin. It is known from a single locality in European Turkey, and the total population in Turkey is small (A. Karatash pers. comm. 2005). In Iran it is at the edge of the its range, the species occurs in low numbers (M. Sharifi pers. comm. 2005). Summer maternity colony size is generally 10-50 females (occasionally up to 300). It winters singly or in small groups.","It forages over open woodland, woodland edge, and pasture, feeding on larger beetles, moths and Diptera.Most summer (maternity) colonies are in buildings (mainly houses) and occasionally tree holes or rock fissures.In winter it roosts singly or in small numbers in buildings and rock crevices, or often in underground habitats in north central Europe. Winter roosts are usually in fairly cold, dry sites. It is a largely sedentary species, with movements to 330 km recorded (Havekost 1960 in Hutterer et al. 2005).","In some areas it is affected by habitat loss and disturbance and destruction of colonies in houses. Population decline in Austria might be related to food reduction due to large scale mosquito control with the bacterium Bacillus thuringiensis, used in the Danube and Moravia regions (F. Spitzenberger and I. Coroiu pers. comm. 2006). The species is a host of the rabies-related virus EBLV1. There is increasing interest in the occurrence, risk to humans and epidemiology of this virus (e.g. Stantic-Pavlinic 2005), which could have an effect on the public image of this house-dependent bat.","It is protected by national legislation in most range states. There are also international legal obligations for its protection through the Bonn Convention (Eurobats) and Bern Convention in parts of range where these apply. It is included in Annex IV of EU Habitats & Species Directive, and there is some habitat protection through Natura 2000. No specific conservation actions known. Protection of maternity roosts and study of impact of B. thuringiensis on the species are needed at least in Austria (F. Spitzenberger pers. comm. 2006).","Tony Hutson, Friederike Spitzenberger, Stéphane Aulagnier, Ioan Coroiu" +ANIMALIA,CHORDATA,MAMMALIA,CHIROPTERA,VESPERTILIONIDAE,Miniopterus schreibersii,"Two papers by two different teams published in 2004 split the species in three (Appleton et al. 2004, Tian et al. 2004); only one of these taxa is present in the Western Palaeartic.",No,No,NT,,NT,,European and EU 25: Classed as Near Threatened. Significant population declines and range contractions have been recorded in a number of range states; overall the rate of population decline is likely to approach 30%.,Unfavourable,"A southern Palaearctic species; patchily distributed over its range in some huge and vulnerable colonies. It typically occurs at altitudes of up to 1,400m (commuting up to 2,600m).","In southern Europe and Asia Minor it is widely distributed and common, but it has lost the northern parts of its range since the 1960s. Summer breeding colonies typically number 500-10,000 individuals (formerly up to 80,000 animals in Bulgaria and 100,000 in India). It winters in clusters of at least a hundred individuals (exceptionally up to 33,000 animals in Spain and Romania). Population trends vary in different parts of the range: in most of south-east Europe and the Middle East it appears to be stable, whereas very significant recent declines have occurred in northern parts of the European range. In south-west Europe there have been recent mass mortality events.Extinction has occured in Germany and Ukraine. In Switzerland the species has declined since the 1960s and is now close to extinction, and in Austria the hibernating population has declined from 2,500 to 1-2 individuals and all maternity colonies have been lost. In Romania, half of the roosts have disappeared since the 1960s. However, no decline has been recorded in large colonies in Croatia and Bulgaria. In 2002 mass mortalities of this species were reported for populations in France, Spain and Portugal; there are also historical records for such mortalities in Italy and Australia and a possible incidence in Iran. A herpesvirus was found but not identified as the cause of the die offs. Hundreds of individuals were found dead in spring. Mortality up to 60% in one year (2002) was reported in France (Roué and Némoz 2002), and 40% mortality occurred in Spain during the same period including 1,000 dead individuals out of 6,000 in one colony. A number of sites were subsequently deserted. Outside Europe, it is the second most common bat species in Turkey and Iran, with large colonies of thousands of individuals (A. Karatash and M. Sharifi pers. comm. 2005). The population in Iran is probably stable (M. Sharifi pers. comm. 2005). Populations in the Caucasus are considered Near Threatened (K. Tsytsulina pers. comm. 2005).","It forages in a variety of open and semi-open natural and artificial habitats, including suburban areas. It feeds mainly on moths, and occasionally on flies and spiders. It is a colonial species that roosts almost exclusively in caves and mines, often in large mixed colonies with other cave-dwelling bat species. Large and warm caves are preferred. Solitary animals and small groups may sometimes occupy other types of shelter. In winter it hibernates in underground sites (usually large caves with a constant microclimate). Schreiber's bat is a migrant species which changes its roosts frequently, long-distance movements occur occasionally (longest recorded distance 833 km: Hutterer et al. 2005).","Disturbance and loss of underground habitats and pesticide use may threaten this species. In the Caucasus, disturbance caused by tourism in caves is a problem (K. Tsytsulina pers. comm. 2005). The cause of recent mass mortality events is unknown. A meeting was held at the 9th European Bat Conference to discuss these incidents. Veterinary investigations in Spain did not identify any disease as the cause of the die offs, and there is increasing belief that the die offs are caused by bad weather in late winter/early spring.","It is protected by national legislation in most range states. There are also international legal obligations for its protection through the Bonn Convention (Eurobats) and Bern Convention. It is included in Annex II (and IV) of the EU Habitats and Species Directive, and hence requires special measures for conservation including designation of Special Areas for Conservation. There is some habitat protection through Natura 2000, and some roosts are already protected by national legislation. There have been a number of LIFE-funded projects for this species in Spain, Italy, Romania and Germany.","Tony Hutson, Stephane Aulagnier, Petr Benda" +ANIMALIA,CHORDATA,MAMMALIA,CHIROPTERA,VESPERTILIONIDAE,Myotis alcathoe,"Formerly included in Myotis mystacinus (Kuhl, 1817); the species was differentiated (von Helversen et al. 2001) on the base of karyological, genetic and echolocation characters.",Yes,No,DD,,DD,,"The species has been recently described (2001) and is known from few localities. It is not easy to identify morphologically. More localities are being reported, but insufficient information is currently available on the extent of the range, population size and population trends. Consequently it is assessed as Data Deficient. Based on present knowledge the species is endemic to Europe.",Unknown,"This species was recently described and is poorly known (von Helversen et al. 2001), but current information suggests that it is endemic to central and southern Europe. It is known from Spain, France, Switzerland, Germany, Czech Republic, Slovakia, Hungary, Montenegro, Romania, Bulgaria, and Greece (Ruedi et al. 2002, Benda et al. 2003, Agirre-Mendi et al. 2004, von Helversen 2004, Helversen et al. 2006, P. Benda in litt. 2006). The species is possibly present for most of Serbia and areas of Montenegro (M. Paunovic pers. comm. 2007).","Its population size and trend is unknown. To date, c.15 localities are recorded in international publications (von Helversen 2001, Benda et al. 2003, von Helversen 2004). However, new localities continue to be found (EMA Workshop 2006, Mediterranean Mammals Workshop 2007).","According to present scarce knowledge, it is a tree dwelling and forest foraging species. In parts of the range at least it prefers to hunt in small valleys with deciduous trees and flowing water, which is a threatened habitat. The only breeding colony was found in a tree hollow. It may also occur in rural gardens and urban habitats. It probably occurs in underground habitats in winter.",Damage to riparian forest is believed be a threat in parts of range (von Helversen et al. 2001). Wider forest and roost tree loss (especially in wet old growth forests) may also be threats.,"It is protected by national legislation in most range states. There are also international legal obligations for the species' protection through the Bonn Convention (Eurobats) and Bern Convention. It is included in Annex IV of the EU Habitats and Species Directive, and some habitat protection may be provided through Natura 2000. Conservation recommendations include further research on distribution, population status and trends, ecology, habitat requirements, and threats. Measures to increase public awareness of this little-known species are also recommended.","Hutson, A.M., Aulagnier, S., Nagy, Z., Karataş, A., Palmeirim, J. & Paunović, M." +ANIMALIA,CHORDATA,MAMMALIA,CHIROPTERA,VESPERTILIONIDAE,Myotis aurascens,Formerly included in Myotis mystacinus; it was differentiated on the basis of morphology (Benda and Tsytsulina 2000).,No,No,LC,,LC,,"European regional assessment: Least Concern (LC)EU 25 regional assessment: Least Concern (LC)This species has a wide range. Population size has not been quantified, but it is not believed to approach the thresholds for the population size criterion of the IUCN Red List (i.e. less than 10,000 mature individuals in conjunction with appropriate decline rates and subpopulation qualifiers), as the species is described as common in at least parts of its range. Population trend has not been quantified, but it is not believed to approach the threshold for the population decline criterion of the IUCN Red List (i.e. declining more than 30% in ten years or three generations). For these reasons, it is evaluated as Least Concern.",Possibly Favourable,"Myotis aurascens is a western Palaearctic species; from present knowledge it is distributed in south-east Mediterranean and steppe Europe, and in south-west Asia (from Italy through the Balkans to southern Russia and Transcaucasia). In that area it is the most common of the M. mystacinus group and one of most common bat species (Benda 2004).","Exact details are not known, but it is a widespread and common species.","Recorded from forest and scrub (including Mediterranean-type scrub), and likely to occur in underground habitats.","Potential threats include habitat loss (as a result of infrastructure development and other causes), and disturbance of roost sites in buldings or underground habitats. However, these are not thought to be major threats to the species at present.","It is protected by national legislation in most range states. There are also international legal obligations for the protection of this species through the Bonn Convention (Eurobats) and Bern Convention. It is included in Annex IV of EU Habitats & Species Directive. Some habitat protection may be provided through Natura 2000. Further research is required on population size and trends, distribution, habitat requirements and ecology, and potential threats to this species. Measures to increase public awareness are also recommended.","Tony Hutson, Friederike Spitzenberger, Stéphane Aulagnier, Zoltan Nagy" +ANIMALIA,CHORDATA,MAMMALIA,CHIROPTERA,VESPERTILIONIDAE,Myotis bechsteinii,"Monotypic form, without taxonomic complexities (Baagøe 2001).",No,No,VU,A4c,VU,A4c,"European regional assessment: Vulnerable (VU)EU 25 regional assessment: Vulnerable (VU)A rare species that occurs at low densities and has specific habitat requirements. Its population is fragmented and its sedentary habits mean that it does not colonise new areas easily. There is very little information on population trends, but it is suspected that the species is declining as a result of the loss and degradation of specific types of old-growth woodland, compounded by other threats such as human disturbance. It is suspected that these threats may result in a population decline of >30% over a 15 year period including both the past and the future. Consequently it is assessed as Vulnerable.",Unfavourable,"A western Palaearctic species, it occurs in central and southern Europe and temperate south-western Asia (Caucasus region and Asia Minor). It is found on several islands including Bornholm, Corsica, Elba, Capri, Sicily (Baagoe 2001). It has been recorded from sea level to as high as 1,500m in central Spain (Benzal and de Paz 1991).","It is considered rare throughout its range, although in optimal habitat it may be regularly found, and it is a typical member of central European bat communities. In southern Europe and the Caucasus it is rare (K. Tsytsulina pers. comm. 2005), and there has been only one confirmed individual in Iran (Sharifi et al. 2000). There are also few records from Turkey, where it has been found in groups of up to six individuals in six localities (A. Karatash pers. comm. 2005). Breeding colonies are small, numbering up to 10-30 individuals (K. Tsytsulina, J. T. Alcalde, A. Hutson pers. comm. 2006). Populations are fragmented as a result of the loss in historic times of the majority of its forest habitat. There is very little information on recent population trends. However, one of the few colonies known from Spain has disappeared in recent years because of human disturbance (J. T. Alcalde and J. Juste pers. comm. 2006).","This species has specialised habitat requirements, and is largely dependent on mature natural forests. In the south-west Asia region it is found in broadleaf forest and sometimes mixed forest (K. Tsytsulina pers. comm. 2005). In Europe, it tends to prefer mature deciduous woodland of beech and oak with a high proportion of old trees. Densities of this species are highest in forests that are managed according to environmental (rather than strictly economic) principles. It is occasionally found in artificial habitats such as pasture, plantations (especially orchards) and rural gardens. In summer it roosts in tree-holes, or occasionally in buildings; bird and bat boxes are fairly readily accepted (Schlapp 1999). In winter it hibernates in underground habitats, and possibly also in hollow trees. It forages in woodland and along woodland edge for Lepidoptera, Diptera, Planipennia, and also non-flying insects. A sedentary species (Hutterer et al. 2005).","Threats include inappropriate management and development of woodland habitats, intensive agriculture (e.g. use of pesticides on farmland adjacent to woodland occupied by the species) and human disturbance of roost sites. The loss of old trees with hollows is a particular problem. In Germany, infrastructure developments (and associated habitat fragmentation) and forestry are the main threats (Schulenberg 2005).","It is protected by national legislation in most range states. There are also international legal obligations for its protection through the Bonn Convention (Eurobats) and Bern Convention. It is included in Annex II (and (IV) of EU Habitats and Species Directive, and hence requires special measures for conservation including designation of Special Areas for Conservation. There is some habitat protection through Natura 2000, and the species is found in protected areas all over its range. It benefits directly or indirectly from a number of LIFE funded projects in Europe, and there are current research projects focussing on the species. Appropriate habitat management involves leaving old trees in sufficient numbers, as each individual colony uses up to 30 trees in the summer. Monitoring is required to determine population trends in this species.","Tony Hutson, Friederike Spitzenberger, Javier Juste, Stéphane Aulagnier, Juan Tomas Alcaldé" +ANIMALIA,CHORDATA,MAMMALIA,CHIROPTERA,VESPERTILIONIDAE,Myotis blythii,"Based on analyses of sequence data of mitochondrial genes (Ruedi and Mayer 2001), Wilson and Reeder (2005) treated myotis, blythii, oxygnathus and punicus as separate species, an arrangement used also by Spitzenberger (2002). However, the IUCN SSC Chiroptera Specialist Group awaits further details to justify the specific separation of M. blythii and M. oxygnathus. We follow Castella et al. 2000 in treating the populations of North Africa, Corsica, Sardinia and Malta as a species: M. punicus.",No,No,NT,,NT,,"European and EU 25: Near Threatened. This species has declined in many parts of its range both inside and outside Europe. There is evidence of rapid ongoing decline in at least some areas, although in other areas the trend may be stable. It is suspected that, overall, population declines may approach 30% over the last 21 years (3 generations). Consequently, the species is assessed as Near Threatened (approaching A2b) at the European and EU 25 levels. There is not expected to be any rescue effect from populations outside the region, as these may be declining too.",Unfavourable,"A south-west Palearctic species, it occurs in southern Europe, southern parts of central Europe, and non-arid parts of southwestern Asia from Asia Minor, the Caucasus region and Palestine to Kashmir, the Altai mountains, Nepal, and parts of China. The subspecies M.b. oxygnathus occurs in Europe and western Anatolia: Portugal, Spain, France, Italy (including Sicily). Switzerland, Austria, Czech Republic, Slovakia, Romania, Moldova, Ukraine (including Krym), the Balkan Peninsula and parts of Turkey (Topál and Ruedi 2001). In the Caucasus, Turkey, Iran, the Russian Federation and Georgia it is confimed to occur no higher than 1,700m (K. Tsytsulina, M. Sharifi and A. Karatash pers. comm. 2005). However, it is found at altitudes of up to 2,100m in the winter in southern Spain (Palomo and Gisbert 2002).","A gregarious species, it congregates in nursery and/or hibernating colonies of up to 500 individuals. There have been large population reductions since the 1950s in several areas, including central Europe, Israel, and central Asia, and there is evidence of ongoing decline in some parts of the range, although in other areas populations appear stable. It remains an abundant species. In Turkey it occurs in large clusters and is the second most common bat species (A. Karatash pers. comm. 2005). In Iran there is evidence of population decline, although it remains one of the most sighted species (M. Sharifi pers. comm. 2005). The Spanish population is estimated to be smaller than 20,000 individuals, and is concentrated in the southern part of the country (Palomo and Gisbert 2002). It is declining, at a rate of one third over the last 10 years in important large colonies in Andalucia (Franco and Rodrigues de los Santos 2001). It is one of the rarest species in Portugal, where its population of c.2,000 individuals is declining (Rodrigues et al. 2003). It is uncommon in the northern part of the range (Austria) but seems stable (Spitzenberger 2002). In France, the population of over 20,000 individuals experienced declines since the 1960s, but may now be stable (S. Aulagnier pers. comm. 2006). In Romania, one well-known colony has declined by 95% as a result of disturbance by speleological tourism (Z. Nagy pers. comm. 2006). It often occurs in mixed colonies with Myotis myotis and identification is sometimes problematic.","It forages in scrub and grassland habitats, including farmland and gardens. Maternity colonies are usually found in underground habitats such as caves and mines, and sometimes in attics of buildings (particularly in central Europe).It hibernates in winter in underground sites with a relatively constant temperature of 6-12ºC. The species is an occasional migrant, with movements of up to 488 km recorded (Hutterer et al. 2005; previous reports of 600 km are erroneous).","Changes in land management, especially agricultural pollution and other agricultural activities, can affect populations of this species. Disturbance to roosts in caves and buildings may also be a problem.","It is protected by national legislation in most range states. There are also international legal obligations for its protection through the Bonn Convention (Eurobats) and Bern Convention. It is included in Annex II (and IV) of the EU Habitats and Species Directive, and hence requires special measures for conservation including designation of Special Areas for Conservation. There is some habitat protection through Natura 2000. In some countries (including Spain, Portugal, and Italy) several colonies are protected by closing entrances to caves with fences. More colonies should be protected.","Tony Hutson, Friederike Spitzenberger, Javier Juste, Stéphane Aulagnier, Juan Tomas Alcaldé, Zoltan Nagy, Ioan Coroiu" +ANIMALIA,CHORDATA,MAMMALIA,CHIROPTERA,VESPERTILIONIDAE,Myotis brandtii,"In this assessment we regard M. brandtii as a species consisisting of two forms, M. brandtii brandtii (Europe, Caucasus, Western Siberia), and M. b. gracilis (central and Eastern Siberia, Mongolia, Korea, Manchurea, Japan) (Benda and Tsytsulina 2000, Tsytsulina 2001). K. Tsytsulina has a paper in press which proposes two separate species and revises the distribution. Both the eastern and the western forms are widespread and abundant.",No,No,LC,,LC,,"European regional assessment: Least Concern (LC)EU 25 regional assessment: Least Concern (LC)The species is widespread and abundant, and there is no indication of current significant decline. Consequently it is assessed as Least Concern.",Unknown,"Myotis brandtii is a boreal Palaearctic species, distributed from Ireland, central Europe and Fennoscandia through the Russian Federation and central Asia to the northern Far East. It has a scattered distribution in south-east Europe and Anatolia. It occurs from sea level to 1,800 m.","One of the more common species within northern parts of its regular distribution area. It is decreasing in Turkey, at the southern edge of its global range (A. Karatash pers. comm. 2005).","It inhabits mixed and broadleaf forest, and sometimes coniferous forest, often in close proximity to water (K. Tsytsulina pers. comm. 2005, Gerell 1999). It is less often found near human habitation than its congener M. mystacinus. Summer roosts are sited in buildings, tree holes, and bird and bat boxes. In winter it hibernates in caves and mines. It is an occasional migrant, with movements of up to 618 km recorded (Hutterer et al. 2005).","There are no major threats known. Localized possible threats include changes in land-use practices (including woodland loss, infrastructure development and pesticide use). Human disturbance to roosts in builidings and underground habitats may also be a problem. In the eastern Black Sea area, it prefers to roost behind window shutters in older buildings, and these sites are not provided in modern buildings. Another popular roost site in this region is barrels hung in trees for honey bee farming, and when the barrels are removed to check for honey, roosting individuals are disturbed (A. Karatash pers. comm. 2005).","It is protected by national legislation in most range states. There are also international legal obligations for its protection through the Bonn Convention (Eurobats) and Bern Convention, in parts of its range where these apply. It is included in Annex IV of EU Habitats & Species Directive, and there is some habitat protection through Natura 2000.","Tony Hutson, Friederike Spitzenberger, Stéphane Aulagnier, Ioan Coroiu" +ANIMALIA,CHORDATA,MAMMALIA,CHIROPTERA,VESPERTILIONIDAE,Myotis capaccinii,Most of the recent authors consider M. capaccinii as a monotypic species (Spitzenberger and von Helversen 2001).,No,No,VU,A4bce,VU,A4bce,"The species occupies specialised habitat in Mediterranean countries (caves and associated water systems). In the eastern part of the range it congregates in winter in a few sites threatened by human disturbance. It has declined between 30 and 50% in Spain in the last 10 years, and there are indications of decline in other parts of the range. It only hunts on watercourses and is therefore threatened by water pollution and development of touristic infrastructure, which is expected to continue in the future. It is suspected that population declines are underway that will exceed 30% over 18 years (3 generations), and for that reason the species is considered Vulnerable at the European and EU 25 levels.",Unfavourable,"Myotis capaccinii is sparsely distributed from eastern Iberia through the northern Mediterranean to coastal Asia Minor and Israel, Lebanon and Jordan, and also in Mesopotamia from Turkey to Iran and in north-west Africa. It occurs from sea level to 900 m.","Locally it can be abundant. Generally, the population is fragmented, but these ""fragments"" may constitute robust parts of the overall population. Declines have been reported in many range states. In Spain, the population has declined by 30-50% in the last 10 years to fewer than 10,000 individuals. Only 30 colonies are known that comprise more than 20 individuals (Palomo and Gisbert 2002). At least six important colonies are threatened by the construction of buildings nearby and five colonies have disappeared over the last 10 years. In France the population has declined to very low numbers (an estimated 3,800 individuals). Colonies have been lost in the western part of the range in the last 15 years (S. Aulagnier pers. comm. 2006). Colonies in central Romania known from the 1960s have disappeared, and the species is now restricted to the south. The species is almost absent in winter and probably hibernates in Bulgaria (Z. Nagy pers. comm. 2006). The Bulgarian population is estimated at c.20,000. In Croatia there are still some large colonies but these are threatened by pollution of karstic water bodies (F. Spitzenberger pers. comm. 2006), and the species is listed as Endangered in the Croatian Red Book of Mammals (Tvrtković 2006). In Turkey it has a decreasing population and is considered vulnerable; it is most often encountered in small groups, very occasionally up to several hundred individuals (A. Karatash pers. comm. 2005). The species is naturally rare in Iran (M. Sharifi pers. comm. 2005) and north Africa (S. Aulagnier pers. comm. 2006). The size of colonies is smaller in the western part of the range (several hundreds of individuals in summer) than in the eastern part (up to several thousands in winter).","It forages over wetlands and waterways (including artifical waterbodies, such as canals and reservoirs), also scrub. It generally roosts in underground habitats (principally caves). Movements between summer and winter colonies are mostly within a distance of 50 km (maximum 140 km: Hutterer et al. 2005)","Threats include changes in water quality through pollution and dam building, and loss of water bodies and watercourses. Damage or disturbance to caves used as roosts may also be a problem.","It is protected by national legislation in most range states. There are also international legal obligations for its protection through the Bonn Convention (Eurobats) and Bern Convention. It is included in Annex II (and IV) of EU Habitats and Species Directive, and hence requires special measures for conservation including designation of Special Areas for Conservation. Some habitat protection through Natura 2000. In Spain, fences are in place to protect several known colonies. Measures needed include protection of colonies and improvement of water quality.","Tony Hutson, Friederike Spitzenberger, Javier Juste, Stéphane Aulagnier, Juan Tomas Alcaldé" +ANIMALIA,CHORDATA,MAMMALIA,CHIROPTERA,VESPERTILIONIDAE,Myotis dasycneme,,No,No,NT,,NT,,"The species' range is wide but it is specialised to feeding above water courses and water bodies. Loss and degradation of aquatic habitats may threaten the species. There has been a rapid decline in the past in at least parts of Europe, and although this decline may now have slowed, it is nevertheless suspected to approach 30% over the last 15 years (3 generations). Consequently the species is classed as Near Threatened (approaching A2c) at the European and EU 25 levels.",Unfavourable,"Myotis dasycneme occurs from north-west Europe (north-western France and southern Scandinavia) south to Serbia and Montenegro, Ukraine, and north Kazakhstan and east to the River Yenisey in central Russia, with few record from China. Historic or subfossil records exist from Switzerland, Austria and the former Yugoslavia. Recorded from sea level to 1,500 m.","It is rarely abundant, and ranks among the rarest bat species in Europe. Summer colonies usually less than 100, but can reach 500. In winter sites, usually roost singly or small groups of up to 10, few sites with more than 200 individuals (maximum 700). Although no quantitative data on population trends are available, the species is reported as seriously declining in much of Europe.","This species feeds principally over open calm water, particularly canals, rivers and lakes, on small emerging and emergent insects, often taken from the water surface. It prefers water lined by open rough vegetation without trees. Most of the known summer maternity roosts are in buildings, often in large attics and church steeples, in groups of 40-600. Some tree and bat box roosts are recorded. It frequently hibernates in underground habitats ranging from natural caves to cellars and bunkers. It is a partial migrant, with winter and summer roosts often separated by more than 100 km (maximum recorded: 350 km), and it may need good habitat links between summer and winter roosts.","Threatened by habitat change, including renovation and maintenance of buildings with roosts involving the use of chemicals for remedial timber treatment that are toxic to mammals. Few nursery roost sites are known and many of these have been lost, although numbers in hibernation sites have shown a slower decline in the Netherlands. Water pollution may also be a threat; the species already has a relatively restricted foraging habitat of broad, open flat water of canals, rivers and lakes with relatively open banks, with possibly some further seasonal (summer) restriction within utilised habitat. Such restrictions in summer may be opportunistic rather than enforced, and it may be that the requirements for wider dispersal in spring, and possibly autumn, is more of a conservation problem than concentration in summer in good foraging habitat close to the roost. The requirements during migration are not known and may be a constraint (Limpens et al. 2000, Hutson et al. 2001)","Protected in all European range states, and possibly in most of rest of range. In Europe it is included in Annex II of the EEC Council Directive on the Conservation of Natural Habitats and of Wild Fauna and Flora 1992 (EEC Habitat Directive) requiring full protection and designation of Special Areas of Conservation to maintain it and its habitats. Other international treaties of relevance are the Agreement on the Conservation of Bats in Europe (Bonn Convention 1994), Convention on the Conservation of European Wildlife and Natural Habitats (the Bern Convention 1982) and Bern Convention Recommendation 36 (1992, Conservation of Underground Habitats). Most European range states are party to at least one of these treaties. Numbers in underground habitats have increased following site protection. Considerable effort has been applied to the conservation of known maternity roosts, but not always with success in view of requirements for renovation and maintenance of buildings used as roosts. Particularly in the Netherlands the use of bat detectors has more clearly demonstrated the distribution of the species and hence allowed more precise definition of foraging habitat requirements and the need for an adequate network of protected flightpaths between roosts and foraging sites. Under the Agreement on the Conservation of Populations of European Bats, the species is selected for examination of its migratory behaviour.The Bern Convention has commissioned a Species Action Plan under its obligations to the Pan-European Biological and Landscape Diversity Strategy (Hutson et al. 2001). Current (2006) research in the Netherlands and Germany focuses on conservation requirements and migration.","Tony Hutson, Stéphane Aulagnier, Zoltan Nagy" +ANIMALIA,CHORDATA,MAMMALIA,CHIROPTERA,VESPERTILIONIDAE,Myotis daubentonii,"This assessment refers to M. daubentonii sensu lato, thus including M. petax from Altai and Siberia which was recently separated as species by Matveev et al. (2005).",No,No,LC,,LC,,"European regional assessment: Least Concern (LC)EU 25 regional assessment: Least Concern (LC)The species is widespread and abundant, and there are indications that its population is currently increasing. Consequently it is classed as Least Concern.",Possibly Favourable,"Myotis daubentonii is distributed from Portugal, Ireland and Norway through Europe and northern Asia to the Far East (Korea and Japan). It is absent in Central Asia from the Caspian region to the Altai mountains, and only a few records are known from Asia Minor and the western Caucasus. There are records from sea level to 1,400 m in the Alps (Spitzenberger 2002).","One of the most abundant bats in many parts of its range, and the only European bat species for which continuing population increase from the 1950s to present has been recorded. A very common species in central and eastern Europe and in northern Asia.","It forages over natural and artificial water bodies (including fjords), sometimes in woodland or scrub. Summer roosts are in trees, buildings and other artificial structures (e.g. bridges, cellars). It winters in wide range of underground habitats. Seasonal movements between winter and summer roosts are mostly within a distance of 100-150 km (Hutterer et al. 2005). The longest distance covered is 257 km (Tress et al. 2004 in Hutterer et al. 2005).","Changes in water quality may reduce food supply, and loss of or damage and disturbance to roost sites in trees, buildings, other artificial structures, and underground habitats may cause temporary localised losses. However, these are not thought to be serious threats to the survival of this abundant and expanding species.","It is protected by national legislation in most range states. There are also international legal obligations for its protection through the Bonn Convention (Eurobats) and Bern Convention in parts of its range where these apply. It is included in Annex IV of EU Habitats & Species Directive, and there is some habitat protection through Natura 2000.","Tony Hutson, Friederike Spitzenberger, Stéphane Aulagnier, Ioan Coroiu" +ANIMALIA,CHORDATA,MAMMALIA,CHIROPTERA,VESPERTILIONIDAE,Myotis emarginatus,"The population of the western part of the distributional range (NW Africa, Europe, Caucasus and Levantine regions) belongs to the nominotypic subspecies (M. emarginatus emarginatus); in the Asian part of the range two further subspecies are found (M. e. sogdianus and M. e. desertorum).",No,No,LC,,LC,,"European regional assessment: Least Concern (LC)EU 25 regional assessment: Least Concern (LC)The species experienced a significant decline from the 1960s to the 1990s, but now it is expanding in central Europe and is stable or not significantly declining elsewhere. The range is still large and the species is not restricted to a specialized habitat, although it has a very specialized diet.",Possibly Favourable,"Myotis emarginatus occurs in southern Europe and southern part of western and central Europe and non-arid parts of south-western Asia from Asia Minor, Caucasus region and Palestine to Oman, Uzbekistan and Tajikistan; also in north-west Africa. It occurs from sea level to 1,800 m, highest records in the Alps are 812 m (maternity colony) and 1,505 m (hibernaculum) (Spitzenberger 2002).","Locally it can be rare or common. The species experienced a significant decline from the 1960s to the 1990s, but more recently the numbers in several regions have increased and the species has spread into new areas. It lives in large colonies (up to 1,200 individuals in Austria in one maternity colony). It is included in the Red List of the Russian Federation as Vulnerable, on the basis of a past population decline of 30% or more inferred from a reduction in range. The species is of marginal occurrence in the Russian Federation.","It forages over scrub and grassland. Diet unique in Europe as it mainly feeds on spiders and flies. In summer, it roosts in underground habitats and, in central Europe, in buildings (in loft spaces). Sometimes roosts in summer with Rhinolophus species. It winters in underground sites. In Iran and the Caucasus, the species occurs in a variety of habitats, but in low numbers (M. Sharifi pers. comm. 2005). Mainly a sedentary species, but movements of up to 105 km have been recorded (Schunger et al. 2004 in Hutterer et al. 2005)","In Europe the species is mainly associated with agricultural landscapes, therefore all agricultural activities can affect populations of this species. Loss of and disturbance to roost sites in buildings and underground sites are also threats.","It is protected by national legislation in most range states. There are also international legal obligations for its protection through the Bonn Convention (Eurobats) and Bern Convention. It is included in Annex IV of EU Habitats & Species Directive, and there is some habitat protection through Natura 2000.","Tony Hutson, Friederike Spitzenberger, Stéphane Aulagnier, Zoltan Nagy" +ANIMALIA,CHORDATA,MAMMALIA,CHIROPTERA,VESPERTILIONIDAE,Myotis myotis,,No,No,LC,,LC,,European regional assessment: Least Concern (LC)EU 25 regional assessment: Least Concern (LC)The species experienced a significant population reduction in the past but is now stable (at lower densities) or recovering throughout the range. The range is still wide and the population large (tens of thousands of individuals in various countries). Consequently it is assessed as Least Concern.,Possibly Favourable,"Myotis myotis is a western Palaearctic species; it occurs in western, central and southern Europe (with individual records from southern England and southern Sweden) and in Asia Minor and in the Levant.","A common species in most of its distributional range, populations of several regions are fluctuating in numbers. During the 1980s and 1990s in central Europe there were increases in numbers following major declines in earlier decades. It forms large nursery colonies (tens to thousands of individuals) in caves, in central Europe also in loft spaces. In Austria the population was estimated to be 76,000 individuals in 1999 and is still increasing (Spitzenberger 2002, F. Spitzenberger pers. comm. 2006). In France 37,000 individuals were recorded in summer 1995 (Roué and Groupe Chiroptères 1997); trend data are not available. A small population went extinct in Britain in 1990 (A. Hutson pers. comm. 2006)","It forages over woodland edge, scrub, and pasture. It preys on large insects, mainly flightless beetles, gleaned from the ground. It roosts in underground sites all year in much of range, and in buildings (loft-spaces) in summer in northern parts. Occasionally it forms small colonies in trees. It is an occasional migrant; the longest recorded movement is 436 km (Simon et al. 2004).","In Europe, it is a typical species of agricultural mosaic landscapes, therefore agricultural activities (e.g. pesticide use, intensification that leads to loss of scrubby patches, hedgerows, and small woods) can affect populations of this species. Loss of or damage to roost sites in underground habitats and buildings may also be a threat. However these are not thought to be major threats to the species as a whole at present.","Protected by national legislation in most range states. Also international legal obligations for protection through Bonn Convention (Eurobats) and Bern Convention. Included in Annex II (and IV) of EU Habitats and Species Directive, and hence requiring special measures for conservation including designation of Special Areas for Conservation. Some habitat protection through Natura 2000.","Tony Hutson, Friederike Spitzenberger, Stéphane Aulagnier, Zoltan Nagy" +ANIMALIA,CHORDATA,MAMMALIA,CHIROPTERA,VESPERTILIONIDAE,Myotis mystacinus,"Includes three forms differing in morphological traits: M. mystacinus mystacinus (most of European range), M. mystacinus occidentalis (Iberia and Morocco) and M. mystacinus caucasicus (Caucasus region).",No,No,LC,,LC,,"European regional assessment: Least Concern (LC)EU 25 regional assessment: Least Concern (LC)The species is widespread and abundant, and there are no indications of current significant population decline. Consequently it is classed as Least Concern.",Unknown,"Myotis mystacinus is a western Palaearctic species, occurring in western and central Europe, southern parts of Scandinavia, the British Isles, Morocco, northern parts of eastern Europe, western parts of the Caucasus and the Urals. The occurrence in south-east Europe is questionable but likely. It has been recorded from sea level to 1,920 m (Gerell 1999).",One of the more common species within the regular distribution area.,"It inhabits forest, woodland edge and shrubland. Summer maternity roosts are typically sited in trees, buildings, and bird and bat boxes. It hibernates in small groups in underground sites (caves, mines, and cellars). It is an occasional migrant, with movements of up to 240 km recorded (Gerell 1999). Movements of up to 625 km have been described, although the longest distance covered by a bat with certain species identification is 165 km (Gaisler et al. 2003 in Hutterer et al. 2005).","Although not major threats, the species is affected by loss of woodland and other aspects of land management and development. It is also affected by loss of and damage to roost sites in trees, buildings and underground habitats.","It is protected by national legislation in most range states. There are also international legal obligations for its protection through the Bonn Convention (Eurobats) and Bern Convention. It is included in Annex IV of EU Habitats & Species Directive, and there is some habitat protection through Natura 2000.","Tony Hutson, Friederike Spitzenberger, Stéphane Aulagnier, Ioan Coroiu" +ANIMALIA,CHORDATA,MAMMALIA,CHIROPTERA,VESPERTILIONIDAE,Myotis nattereri,"Does not include Myotis schaubi (Armenia and western Iran) and Myotis bombinus (south-eastern Siberia, north-eastern China, Korea, Japan). Two subspecies of M. nattereri are recognized: M. nattereri nattereri (N Africa, Europe, SW Asia Minor, Palestine) and M. n. tschuliensis (Caucasus region, Iraq, Turkmenia). Part of the Iberian population has been described as a a new cryptic species named Myotis escalerae (Ibañez et al. 2006).",No,No,LC,,LC,,"European regional assessment: Least Concern (LC)EU 25 regional assessment: Least Concern (LC)The species is widespread and abundant, and there is no evidence of current significant population decline. Consequently it is classed as Least Concern.",Unknown,"Myotis nattereri is a western Palaearctic species. It is widespread in Europe, with the exception of northern Fennoscandia, eastern Ukraine and much of Russia. Also found in Morocco, western and south-western Asia Minor, Levant, Caucasus region (including northern Iraq), Kopetdag Mountains in Turkmenia and Iran, northern Kazakhstan. Its altitudinal range is sea level to 2,000 m.",In Europe it is widespread but everywhere rare (Topál 2001). Colonies can reach 250-300 individuals in Jordan (Z. Amr 2000).,"It forages in woodland (including Mediterranean pine and oak forest: Amr 2000), shrubland and parkland, sometimes over water, pasture, and road verges. It occurs in humid areas, and in dry areas it is dependant on water bodies. Summer roosts are in hollow trees, buildings and occasionally underground sites. It hibernates in underground habitats (caves, cellars and mines). It is a sedentary species, movements between summer, autumn and winter roosts are up to 120 km (Masing et al. 1999 in Hutterer et al. 2005).","The species is affected by loss of woodland and other changes in land management and development. Loss of or damage to roost sites in trees, buildings and underground habitats may also be a problem.","It is protected by national legislation in most range states. There are also international legal obligations for its protection through the Bonn Convention (Eurobats) and Bern Convention, in parts of its range where these apply. It is included in Annex IV of EU Habitats & Species Directive, and there is some habitat protection through Natura 2000.","Tony Hutson, Friederike Spitzenberger, Stéphane Aulagnier" +ANIMALIA,CHORDATA,MAMMALIA,CHIROPTERA,VESPERTILIONIDAE,Myotis punicus,"Originally described as a subspecies of blythii, but recently shown to lie outside a clade including blythii, myotis, and oxygnathus (Ruedi and Mayer 2001).",No,No,NT,,NT,,"European regional assessment: Near Threatened (NT)EU 25 regional assessment: Near Threatened (NT)The population size is estimated at between 6,000 and 8,000 individuals. The species is cave dwelling, only a small number of colonies are known, and those are in touristic areas subject to disturbance. Although the population trend has not been quantified in Corsica, some colonies have been lost, suggesting that declines have occurred. It is assumed that the population trend will be similar on Sardinia as the species faces the same threats there. On Malta, surveys have shown an estimated decline of 50% or more in 3 generations, although this is a small part of the overall population and the trend has now stabilised. It is therefore suspected that the species is declining faster than 10% in 3 generations (generation time for the species is 7-8 years). Because the overall decline rate is suspected rather than estimated, the species qualifies as Near Threatened (approaching C1). There is no evidence that there would be a significant rescue effect from North African populations.",Unfavourable,"Myotis punicus occurs in North Africa (Morocco, Algeria, Tunisia, and Libya) and on the Mediterranean islands of Corsica (to France), Sardinia (to Italy), and Malta.","On Corsica there are around 3,000 individuals in four colonies. The total population size on Corsica, Sardinia and Malta is estimated at between 6,000 and 8,000 individuals. Cave dwelling, therefore there are few colonies. On Malta, over 50% of the population was lost between the latter half of the 1980s and the early 1990s. Numbers appear to have stabilised at 400-450 individuals (Borg 2002, J.J. Borg unpubl. data). The population trend on Corsica is difficult to quantify as surveys before 2000 were very limited, but some colonies have been lost, indicating that there are some threats to the population (S. Aulagnier pers. comm. 2007).","This species forages in woodland and shrubland and roosts in underground sites, possibly also in buildings. Bats ringed in Malta were retrapped in Gozo, but there were no indications of longer distance movements (Hutterer et al. 2005).","Human disturbance is a major threat, as colonies are located in touristic areas, in caves that are well known and popular. Changes in land management and agricultural pollution are also threats.","It is protected by national legislation in its European range states. There are also international legal obligations for its protection through the Bonn Convention (Eurobats) and Bern Convention, in parts of its range where these apply. It is included in Annex IV of the EU Habitats & Species Directive, and there is some habitat protection may be provided through Natura 2000. There is an ongoing project for the conservation of this species. Appropriate conservation measures include fencing cave entrances and obtaining legal protection for the species.","Javier Juste, Stéphane Aulagnier, Tony Hutson" +ANIMALIA,CHORDATA,MAMMALIA,CHIROPTERA,VESPERTILIONIDAE,Nyctalus azoreum,"There is marked genetic differentiation between populations on central and eastern islands in the archipelago, indicating that they have evolved in relative isolation for a long time (Salgueiro et al. 2004).",Yes,No,EN,B1ab(iii),EN,B1ab(iii),"This species is endemic to the Azores, where it has a small population and range. It is suspected to be declining as a result of disturbance and destruction of colonies, loss and degradation of natural and semi-natural habitats and pesticide use. There is no direct information on dispersal between islands, but genetic research suggests that dispersal is restricted, and so the population is precautionarily regarded as being severely fragmented; further research would be required to confirm this. For these reasons, it is assessed as Endangered.",Unfavourable,"Nyctalus azoreum is restricted to the Azores archipelago (Portugal), where it occurs on Faial, Pico, San Jorge, Graciosa, Terceira, San Miguel and Santa Maria islands, where it occurs from sea level to 600 m (A. Rainho pers. comm. 2006). Its extent of occurrence is estimated at ca.2,200 km2.","Surveys in 2002, 2003 and 2004 found the species quite abundant on San Miguel, Faial, Terceira and San Jorge, but rare on Graciosa and extremely rare on Santa Maria. It is absent from Flores and Corvo. There is no quantitative information on population trend, but it is suspected that the species may be declining as a result of habitat degradation, destruction of or exclusion from roosts (both in trees and buildings), and human persecution. Local environmental groups report that numerous colonies have recently disappeared (A. Rainho pers. comm. 2006). The total population is estimated at 2,000-5,000 individuals, and there are probably fewer than 1,000 individuals on San Miguel, where the species is most abundant (Cabral et al. 2005, J.M. Palmeirim, A. Rainho and L. Rodrigues pers. comm. 2006).","It forages over a variety of habitats on the islands, favouring natural and semi-natural habitats. But it frequently feeds around artificial lighting (e.g. streetlamps). Most maternity colonies are probably located in buildings, trees and rock crevices.","Human persecution, and the destruction of roost sites, are likely to be the main threats (A. Rainho pers. comm. 2006). Habitat loss and degradation, use of pesticides, and the spread of exotic plant species may also have a detrimental effect on the species. It is suspected that the extreme scarcity of the species on Santa Maria is attributable to habitat loss and degradation. This species is particularly vulnerable to persecution because it flies during the day, making colonies obvious and easy to find (A. Rainho pers. comm. 2006).","There is no specific national legislation. It is protected under Bern Convention and included in Annex IV of EU Habitats and Species Directive. There are proposals for protection and monitoring of roosts, public awareness (with special reference to roosts), reduction of adverse agricultural practices, preservation and restoration of natural habitat, use of lights that attract insects (e.g. mercury), and further studies of the species' biology (Rainho et al. 2002).","Hutson, A.M., Aulagnier, S., Rainho, A. & Palmeirim, J." +ANIMALIA,CHORDATA,MAMMALIA,CHIROPTERA,VESPERTILIONIDAE,Nyctalus lasiopterus,,No,Yes,DD,,DD,,"European regional assessment: Data Deficient (DD)EU 25 regional assessment: Data Deficient (DD)This species has a wide range, but it has a patchy distribution and occurs at very low densities, making it very difficult to survey. It has specific habitat requirements (mature forest). Some cases of mortality have been recorded at wind farms, and the number of wind farms is growing. Area of Occupancy and population size are not known, but are not believed to approach the thresholds for IUCN Red List criteria. There are no data available on population trend. Consequently the species is classed as Data Deficient.",Unknown,"Nyctalus lasiopterus has a very scattered distribution through central and southern Europe and north Africa (Morocco, Libya, and possbily Algeria) through Asia Minor to the Caucasus, northern Iran and Kazakhstan. Of the Mediterranean islands, recorded on Sicily. The species is easy to detect with bat detectors, so it is known that the species' distribution in Europe is genuinely extremely patchy. Until 1999, it had been recorded in 120-130 localities in Europe (Benzal 1999). It occurs up to 1,900 m in Switzerland.","The patchy distribution and low population density in most of range suggest a relatively small global population. Breeding colonies are typically small (up to 35 females), and few are known. Only two larger-sized (50-100 females) breeding colonies are known in the world. It is rare throughout the range in the Russian Federation (K. Tsytsulina pers. comm. 2005). There is a strong population in northern Hungary. The species is difficult to survey, and difficult to capture with mist nets as it hunts 10-20 m above the ground (K. Tsytsulina in litt. 2005). The population trend is unknown.","It forages over mixed and deciduous forest and wooded river valleys (the latter especially on migration). It is highly dependent on mature forest. It is largely insectivorous, but is also reported to take small passerines in the southern part of the range during migration. In summer it roosts in hollow trees, and occasionally in buildings. Rock crevices may also be used as hibernacula in winter. It sometimes roosts with other species such as N. noctula. Nursery colonies are usually relatively small (up to 35 females). Females give birth to a single pup per litter. It is considered to be migratory in the north-east of its range, but there is very little data. Vagrants have been recorded well outside the normal range (Hutterer et al. 2005). Some areas in the western part of the range appear to be occupied exclusively by males, according to capture results. Its foraging range may be greater than 30 km in a single night.","Little is known about potential threats, but loss of mature woodland and loss of or disturbance to roost sites (in old trees and buildings) may have a negative impact on the species. Some individuals were found dead in wind farms in Spain (J.T. Alcalde pers. comm. 2006), and all pups were found dead in 2005 at one of the two known colonies in Spain (located in a city park). The cause of these deaths was not known (J.T. Alcalde pers. comm. 2006).","It is protected by national legislation in most range states. There are also international legal obligations for its protection through the Bonn Convention (Eurobats) and Bern Convention, in parts of its range where these apply. It is included in Annex IV of EU Habitats & Species Directive. No specific conservation actions are known. It occurs in a number of national parks and protected areas within its range (K. Tsytsulina pers. comm. 2005). However, in Spain the two known colonies are outside protected areas (J.T. Alcalde pers. comm. 2006). More information is needed on population size and trends, ecology, and potential threats.","Tony Hutson, Javier Juste, Juan Tomas Alcaldé" +ANIMALIA,CHORDATA,MAMMALIA,CHIROPTERA,VESPERTILIONIDAE,Nyctalus leisleri,,No,No,LC,,LC,,"European regional assessment: Least Concern (LC)EU 25 regional assessment: Least Concern (LC)The species is widespread and abundant, and there is no evidence of current significant population decline. Consequently it is classed as Least Concern.",Unknown,"Nyctalus leisleri is largely a western Palaearctic species (Europe and north-west Africa), with scattered records in west parts of the eastern Palaearctic (Pakistan, Afghanistan, the Himalayas). It is widely distributed in Europe from Portugal and the British Isles to western Russia. It is present on Madeira and the Canary islands but absent from southwestern Italy and Sicily, eastern Spain, most of Fennoscandia, the northern Baltic and northern Russia. It occurs from sea level to 2,400 m.","It is widespread although patchily distributed in Europe. Common in parts of range (e.g., Ireland), scarce in other parts (Stebbings and Griffith 1986). Local extinctions have been reported for the central part of Russian Federation (K. Tsytsulina pers. comm. 2005), although the species remains common in other parts of Russia and the Caucasus (S. Kruskop pers. comm. 2005). There is no information about trends.","It forages over woodland, pasture, and river valleys, where it feeds on flies (including mosquitos), moths and beetles. It is linked to old trees. Summer nursery roosts are located in tree holes, plus buildings and bat boxes. Nursery colonies usually number 20-50 females, occasionally up to 1,000 (e.g., in Ireland: Stebbings and Griffith 1986). In winter it hibernates mainly in tree holes, or occasionally in underground sites or buildings, often in large groups. Females migrate over distances up to 1,567 km (Ohlendorf et al. 2000).","Threats include disturbance to and destruction of roosts in trees and buildings, and loss or degradation of foraging habitat. However, these are not thought to be major threats at present.","It is protected by national legislation in most range states. There are also international legal obligations for its protection through the Bonn Convention (Eurobats) and Bern Convention, in parts of its range where these apply. It is included in Annex IV of EU Habitats & Species Directive, and there is some habitat protection through Natura 2000. It occurs in protected areas throughout its range. No specific conservation actions known, but a review of the species' status and summary of existing knowledge is currently (2006) in preparation.","Tony Hutson, Friederike Spitzenberger, Stéphane Aulagnier" +ANIMALIA,CHORDATA,MAMMALIA,CHIROPTERA,VESPERTILIONIDAE,Nyctalus noctula,Nyctalus furvus (Japan) and N. plancyi (eastern China and Taiwan) are now considered as separate species (Wilson and Reeder 2005).,No,No,LC,,LC,,"European regional assessment: Least Concern (LC)EU 25 regional assessment: Least Concern (LC)The species is widespread and abundant, and although there may have been declines in some areas, it is not believed that these approach the threshold for the population decline criterion of the IUCN Red List (30% in 10 years or 3 generations). Consequently it is classed as Least Concern.",Unknown,"Nyctalus noctula has a wide Palaearctic distribution, including Europe and southern Scandinavia to the Urals and Caucasus; Turkey to Israel and Oman; western Turkmenistan, western Kazakhstan, Uzbekistan, Kyrgyzstan, and Tajikistan to south-west Siberia and the Himalayas, south to Myanmar, Vietnam, and western Malaysia. Its occurrence in North Africa is questionable (see below), and a record from Mozambique is considered dubious. With few exceptions, maternity colonies are confined to northeastern Europe (Strelkov 1997a, 1997b). Has been found at 1,900 m in the western Alps during migration (Aellen 1962 in Gebhard and Bogdanowicz 2004).""It is possible that N. noctula occurs in Africa but this needs confirmation. A record from Algeria (two specimens collected from a hollow tree in Cheliff plain) was published by Loche (1858), but these specimens were lost with the rest of Loche's collection. According to Palmeirim (1982), it is possible that these specimens belonged to N. lasiopterus, a species which does occur in North Africa and which was considered to be conspecific with N. noctula by earlier zoologists. There are also some doubts as to the place of origin of some specimens of N. noctula in the BMNH (Palmeirim 1982) and in the RMNH (Jentink 1888). One of these was mentioned by Dobson (1878) as having been bought in Algiers. Kowalski and Rzebik-Kowalska (1991) suggest that all of them were bought from professional dealers, which means that their localities may be unreliable"" (M. Happold pers. comm. 2007).","A widespread species, relatively common throughout much of its range. Very abundant, not declining and considered least concern in the Russian Federation (K. Tsytsulina pers. comm.). Common in winter in Austria, with no sign of decline (Spitzenberger 2002 and F. Spitzenberger pers. comm. 2006). However, there have been documented local declines in the Netherlands, and there are suspected to have been substantial declines in the United Kingdom since the 1940s, although the population trend now appears to have stabilised (Bogdanowicz 1999, Battersby 2005). Within its Iranian range and based on very limited information, the species appears to be rare (M. Sharifi pers. comm. 2005).","It forages over wetland, woodland and pasture, feeding on larger moths, beetles and flies. Summer colonies are in tree holes, sometimes in buildings. Winter hibernacula are in rock crevices, caves, occasionally artificial structures. Maternity colonies number 20-50 females (occasionally up to 100), but winter groups in rock crevices, caves and artificial structures can be large, to 10,000 in one instance (Germany) (Harrje 1994, Mayer et al. 2002). Tree holes and bat boxes are also used as wintering sites. Seasonal migrations between breeding area and hibernation range which is situated in central and southwest Europe normally cover distances of less than 1,000 km. The longest recorded movement is 1,546 km (Hutterer et al. 2005).",The species is affected by loss of tree roost holes in northeastern Europe. In Romania and Hungary colonies are being lost due to renovation of buildings and human disturbance in buildings. Local declines in the Netherlands were linked to loss of wetlands (Bogdanowicz 1999). These are not thought to be major threats to the species as a whole at present.,"It is protected by national legislation in most range states. There are also international legal obligations for its protection through the Bonn Convention (Eurobats) and Bern Convention, in parts of its range where these apply. It is included in Annex IV of EU Habitats & Species Directive, and there is some habitat protection through Natura 2000. The species occurs in a number of protected areas. No specific conservation actions are known.","Tony Hutson, Friederike Spitzenberger, Stéphane Aulagnier, Zoltan Nagy" +ANIMALIA,CHORDATA,MAMMALIA,CHIROPTERA,VESPERTILIONIDAE,Pipistrellus kuhlii,"Wilson and Reeder (2005) consider African and Canary Island populations to belong to a different species, C. hesperidus. The species in Yemen requires taxonomic clarification (D. Kock pers. comm. 2005).",No,No,LC,,LC,,"European regional assessment: Least Concern (LC)EU 25 regional assessment: Least Concern (LC)The species is widespread and abundant, and there is evidence of ongoing population increase. Consequently it is classed as Least Concern.",Possibly Favourable,"Pipistrellus kuhlii has a large range extending from Iberia through southern Europe through the Near East and the Caucasus to Kazakhstan, Pakistan, and India. The northern limit of its range in Europe was formerly ca.45°N, but the species has been expanding northwards. It arrived 1994 in Vienna/Austria (48°N), and was more recently recorded to 50°N in France and 51°N in Ukraine. It has been expanding northwards in Russia for the last half century from 46°N to c.53°N, with the highest record made at almost 57°N (S. Kruskop pers. comm. 2006). It occurs from sea level to 2,000 m.","It is a relatively abundant species in the Mediterranean region and Middle East. Summer colonies typically number 30-100 individuals. In Iran and the Caucasus, the species' range is increasing and it is displacing P. pipistrellus (M. Sharifi and K. Tsytsulina pers. comm. 2005). The northern border of the species' range is also expanding.","It forages over variety of habitats, including agricultural and urban areas (including around street lights). It feeds on small insects, including Diptera, Psocoptera, and Coleoptera. Summer maternity colonies are located in crevices in buildings. Winter sites include rock crevices and cellars. Kuhl’s pipistrelle is probably a sedentary species (Hutterer et al. 2005).",No major threats are known.,"It is protected by national law in most European range states. It is also protected under international legislation in parts of its range through the Bonn Convention (Eurobats) and Bern Convention, and is included in Annex IV of EU Habitats & Species Directive. It is found in a number of protected areas. No specific conservation actions are known.","Tony Hutson, Friederike Spitzenberger, Stéphane Aulagnier, Ioan Coroiu" +ANIMALIA,CHORDATA,MAMMALIA,CHIROPTERA,VESPERTILIONIDAE,Pipistrellus maderensis,"Unidentified Pipistrellus bats found in the Azores have recently been proposed to belong to this species, but this awaits confirmation.",Yes,No,EN,"B1ab(iii,v)",EN,"B1ab(iii,v)","The species is restricted to few islands in the Canaries and the Madeira islands (and possibly the Azores). The extent of occurrence is <5,000 km2, and the population is severely fragmented. It is inferred that the population may be declining as a result of habitat loss, use of agricultural pesticides, and disturbance to roosts. Consequently it is assessed as Endangered.",Unfavourable,"This species is restricted to Madeira (Madeira, Porto Santo), and the western Canary Islands (La Palma, La Gomera, El Hierro, Tenerife). Pipistrelles found in the Azores (Santa Maria, Flores, Corvo, Graciosa, San Jorge) probably belong to this species. It is found from sea level to 2,150 m in the Canary Islands, although it prefers lowlands on Madeira (Fajardo and Benzal 1999).","On the islands of Madeira it is relatively abundant on Madeira and very rare on Porto Santo. The total population is estimated to number fewer than 1,000 individuals, and trends are unknown (Rainho et al. 2002). On the Canary Islands it is the most reported bat on all islands of occurrence, although no bat is abundant in the islands. Population size and trend have not been quantified (Palomo and Gisbert 2002), although declines are inferred as a result of threats including loss and degradation of habitats, pesticide use, and disturbance and destruction of roosts. On the Azores, Pipistrellus bats are rare or very rare on all islands of occurrence, and the total number of individuals is probably less than 300 (Rainho et al. 2002). The global population is naturally fragmented.","It forages over a wide range of habitats, including aquatic habitats, woodland and farmland (Palomo and Gisbert 2002). It feeds on flying insects, including small moths and flies. Breeding colonies have been found in crevices in sea-cliffs and underneath the roofs of houses, as well as in bird boxes (Palomo and Gisbert 2002). Roost sites include rock crevices, bird boxes, and crevices in (often disused) buildings. It is often associated with human settlements.","Loss of natural habitat may be a threat, although the species is apparently adapted to man-made habitats. The use of agricultural pesticides may be a problem, and disturbance to roosts in buildings may also be of concern.","The species is protected through Bern Convention, and included in Annex IV of EU Habitats and Species Directive. Rainho and Palmeirim (2002) proposed the following actions: identification, protection and monitoring of roosts; preservation and restoration of natural habitats, reduction of pesticide use; and, study of the species' biology, ecology, genetics, and systematics. Palomo and Gisbert (2002) additionally recommend a public awareness campaign aimed at reducing disturbance of breeding colonies in private houses.","Juste, J., Palmeirim, J. & Alcaldé, J.T." +ANIMALIA,CHORDATA,MAMMALIA,CHIROPTERA,VESPERTILIONIDAE,Pipistrellus nathusii,,No,Yes,LC,,LC,,"European regional assessment: Least Concern (LC)EU 25 regional assessment: Least Concern (LC)The species is widespread and abundant, and there is no evidence of current significant population decline. Consequently the species is classed as Least Concern.",Unknown,"Pipistrellus nathusii is a western Palaearctic migratory species. It is restricted to Europe, Asia Minor and Transcaucasia where it is found at latitudes of up to ca. 37-63°N. In Europe, it is generally widespread although absent from most of Iberia and Fennoscandia. With few exceptions, maternity colonies are confined to northeastern Europe (eastern Germany, Baltic states, Belarus, Ukraine and Russia: Vierhaus 2004). The first observation of Pipistrellus nathusii breeding in Finland was made in 2006 (H. Henttonen pers. comm. 2006) when a colony of c.10 individuals, including lactating females, was found close to the southern coast some 50-60 km east of Helsinki. The species is typically associated with lowland areas but has been recorded up to 2,200 m in the Alps (Bogdanowicz 1999).","It is abundant in northern parts of its range, and less common but increasingly recorded in southern and western parts of its range. Summer maternity colonies of up to 200 individuals have been recorded, but large winter aggregations are not known.","It forages over a range of habitats including woodland edge, wetlands, and open parkland. Summer roosts are located in tree holes, buildings, and bat boxes, mainly in woodland areas. Winter roost sites include crevices in cliffs, buildings and around the entrance of caves, often in relatively cold, dry, and exposed sites. It is a migratory species, with movements of up to 1,905 km recorded (Petersons 2004). Migrations typically follow a NE-SW route (Bogdanowicz 1999).","Although not major threats, the species is affected by habitat fragmentation on migration routes, loss of and disturbance to roosts in buildings, loss of mature trees with cavities and/or loose bark etc., and water quality changes which may affect food supply.","It is protected under national law in most range states. It is also protected under international law through the Bonn Convention (Eurobats) and Bern Convention in parts of its range where these apply, and is included in Annex IV of the EU Habitats & Species Directive. It is regarded as a species of special concern by Eurobats. Proposals for the conservation of the species in Europe (including research requirements) were made by Limpens and Schulte (2000) following a workshop in Germany in 1998. They recommended a Europe-wide census involving assessment of the species' population status and trends, identification of its mating, hibernation and maternity areas, investigation of migration routes, and identification of preferred resting areas on migration routes.","Tony Hutson, Friederike Spitzenberger, Stéphane Aulagnier, Ioan Coroiu" +ANIMALIA,CHORDATA,MAMMALIA,CHIROPTERA,VESPERTILIONIDAE,Pipistrellus pipistrellus,"The species has recently been separated into two species, P. pipistrellus and P. pygmaeus. Their respective distribution and status are not yet fully clarified (Wilson and Reeder 2005).",No,No,LC,,LC,,"European regional assessment: Least Concern (LC)EU 25 regional assessment: Least Concern (LC)The species is widespread and abundant, and there is no evidence of current significant population decline. Consequently it is assessed as Least Concern at the European and EU 25 levels.",Unknown,"Pipistrellus pipistrellus is a widespread western Palaearctic species with a range extending from the British Isles through much of Europe (with the exception of northern Fennoscandia) to the Volga and Caucasus; and through parts of north-western Africa and south-west Asia to central Asia. Its detailed distribution, as distinct from that of the recently-differentiated P. pygmaeus, is still to be established. It occurs from sea level to 2,000 m.","A widespread and abundant species, one of the most common bats in many parts of its range. Summer maternity colonies generally number 25-50 individuals, although colonies of as many as 200 have been recorded. In winter, it tends to occur singly or in small groups, although some very large groups have been recorded (e.g., up to 45,000 in caves in Romania and Slovakia) (Nagy and Szanto 2003). Significant declines have been recorded in some European countries (e.g. Britain), although in Britain at least the trend may now have stabilised (Battersby 2005).","It forages in a variety of habitats including open woodland and woodland edges, farmland, rural gardens and urban areas. It feeds on small moths and flies. Summer roosts are mainly found in buildings and trees, and individuals frequently change roost site through the maternity period. Most winter roost sites are located in crevices in buildings, although cracks in cliffs and caves and possibly holes in trees may also be used. It is not especially migratory in most of its range, but movements of up to 1,123 km have been recorded (Buresh 1941 in Hutterer et al. 2005). In at least parts of its range it seems to benefit from urbanisation (M. Sharifi pers. comm. 2005).","As a high proportion of colonies are found in buildings, the species may be particularly vulnerable to anthropogenic factors, such as disturbance, timber treatment and building renovation (Battersby 2005). However this is not thought to be a major threat to the species at present.","It is protected under national law in most range states. It is also protected under international law through the Bonn Convention (Eurobats) and Bern Convention in parts of its range where these apply, and is included in Annex IV of the EU Habitats & Species Directive. It occurs in many protected areas. No specific conservation actions are known.","Tony Hutson, Friederike Spitzenberger, Stéphane Aulagnier, Ioan Coroiu" +ANIMALIA,CHORDATA,MAMMALIA,CHIROPTERA,VESPERTILIONIDAE,Pipistrellus pygmaeus,"Includes mediterraneus, formerly regarded by some authorities as a subspecies of pipistrellus (Wilson and Reeder 2005). The genetically and morphologically distinct population of pipistrelle bats belonging to the pygmaeus genetic clade and occurring in the Cyrenaica/Libya was recently described (Benda et al. 2004) as a separate species: Pipistrellus hanaki.",No,No,LC,,LC,,"European regional assessment: Least Concern (LC)EU 25 regional assessment: Least Concern (LC)The species is widespread and abundant, and there is no evidence of current significant population decline. Consequently it is assessed as Least Concern at the European and EU 25 levels.",Unknown,"Pipistrellus pygmaeus was only recently differentiated from P. pipistrellus, and some details of its distribution are still lacking. It is also a western Palaearctic species, occurring from the British Isles through much of Europe (including the islands of Corsica and Sardinina) east to Ukraine and western Russia. Its range may extend much further east, as well as into north Africa (Wilson and Reeder 2005), although it is also possible that the species does not occur outside Europe. It occurs further north in Scandinavia than P. pipistrellus.","It generally appears to be less abundant than P. pipistrellus sensu stricto, although it is nevertheless a widespread and abundant species. Summer colonies may be larger than P. pipistrellus, numbering up to 250 (or occasionally up to 3,000) individuals. It is not known if the species congregates in winter, or what size its winter colonies are.","It forages around woodland and wetlands, and is more closely associated with water than P. pipistrellus. It feeds mainly on small Diptera (especially aquatic midges). Maternity colonies are generally located in buildings. No specific data are available on P. pygmaeus winter roost sites, but presumably they are similar to those used by P. pipistrellus.","As maternity colonies tend to be found in buildings, the species may be vulnerable to anthropogenic factors, such as disturbance, timber treatment and building renovation (Battersby 2005). However, this is not thought to be a major threat.","Although this species was only recently described, it is apparently widespread and abundant. However, further clarification of its distribution, population size and trend, habitat preferences, and ecology is required.","Tony Hutson, Friederike Spitzenberger, Stéphane Aulagnier, Ioan Coroiu" +ANIMALIA,CHORDATA,MAMMALIA,CHIROPTERA,VESPERTILIONIDAE,Pipistrellus savii,There are different lineages in south Iberian populations that may deserve recognition at subspecific level (Ibañez et al. 2006). The taxonomic status of the population of the Canary Islands needs to be revised (J. Juste pers. comm. 2006),No,No,LC,,LC,,European regional assessment: Least Concern (LC)EU 25 regional assessment: Least Concern (LC)The species is widespread and abundant and there is no evidence of population decline. Consequently it is classed as Least Concern.,Possibly Favourable,"This species has a wide range in the Palaearctic (and marginally in Indomalaya), extending from southern Europe and north Africa (France, Portugal, Spain, Italy, Switzerland, Austria, Czech Republic, Slovakia, Hungary, the Balkan countries, Morocco, Algeria, the Canary Islands and Cape Verde Islands) through the Middle East and the Caucasus to Kazakhstan, Turkmenistan, Uzbekistan, Kyrgyzstan, Tajikistan, Afghanistan, northern India and Burma (Horáček and Benda 2004, Wilson and Reeder 2005). It occurs from sea level to 2,600 m.","It generally occurs at low densities and is restricted by its habitat requirements, but it is abundant in some European areas bordering the Mediterranean. Summer maternity colonies usually number 20-70 females. Range expansion from northern Italy through Austria up to the Czech Republic and Slovakia has recently occurred.","It forages over open woodland, pasture and wetlands, and often feeds at lights in rural areas, towns and cities.It roosts in rock crevices, occasionally in fissures in buildings or under bark, rarely in underground habitats. Nothing is known about the migratory behaviour of this species (Hutterer et al. 2005).","There are probably few threats in its mainland distribution, except when roosting in buildings.",It is protected by national legislation in most range states. There are also international legal obligations for its protection through the Bonn Convention (Eurobats) and Bern Convention in parts of its range where these apply. It is included in Annex IV of EU Habitats & Species Directive.,"Tony Hutson, Friederike Spitzenberger, Stéphane Aulagnier" +ANIMALIA,CHORDATA,MAMMALIA,CHIROPTERA,VESPERTILIONIDAE,Plecotus auritus,"According to new taxonomy this species is endemic to Europe, from Ireland to the Urals (Spitzenberger et al. 2006). The Asian populations have been identified as separate species, P. ognevi and P. sacrimontis. Some Spanish populations were described as subspecies P. auritus begognae (Juste et al. 2004).",Yes,No,LC,,LC,,"This species is endemic to Europe, where it is widespread and common, with no major threats.",Unknown,"Plecotus auritus is endemic to Europe, where it is widely distributed south of 65°N and west of the Urals and north of the Caucasus. In the south it is confined to higher elevations. It occurs on the British Isles and in Sardinia. Patchy distribution in Iberia, Italy and the Balkan Peninsula. In the Alps, maternity colonies are found up to 1,920 m asl, hibernacula up to 2,350 m asl (Horácek and Dulic 2004).","A common species in central Europe, but rare in the Mediterranean. Summer colonies usually number 10-50 females, sometimes up to 100. In winter it is generally solitary, although it may occasionally be found in very small clusters (2-3 animals). Nursery colonies of up to 10 (K. Tsytsulina pers. comm.). There have been no recorded population declines throughout most of its range, but it is decreasing in Turkey (A. Karatas pers. comm.).","It forages in the vicinity of the roost in deciduous and coniferous woodlands, along hedgerows, and in isolated trees in parks and gardens. It feeds mainly on moths and flies gleaned from foliage. In summer it roosts in colonies in buildings (attics, barns, churches, drainage channels), tree holes, and bat boxes. Solitary animals also roost in underground sites. In winter it hibernates in caves, mines, buildings and occasionally trees. A sedentary species, its longest recorded movement is 88 km (Gaisler et al. 2003).","Loss of broad-leaved forest and particularly of mature trees is a threat in parts of its Mediterranean range (Balkans, Portugal, Spain and Turkey). It is affected locally by remedial timber treatment and loss of roost sites.","It is protected by national legislation in most range states. There are also international legal obligations for its protection through the Bonn Convention (Eurobats) and Bern Convention. It is included in Annex IV of EU Habitats and Species Directive, and there is some habitat protection through Natura 2000.Maintenance of natural habitat, especially forests with mature trees is required.","Hutson, A.M., Spitzenberger, F., Aulagnier, S., Coroiu, I., Karataş, A., Juste, J., Paunovic, M., Palmeirim, J. & Benda, P." +ANIMALIA,CHORDATA,MAMMALIA,CHIROPTERA,VESPERTILIONIDAE,Plecotus austriacus,According to new taxonomy it is endemic to Europe (Spitzenberger et al. 2006). The Asian and African populations belong to other species.,Yes,No,LC,,LC,,"This species has a large range, within which it is widespread and generally common. Although there is evidence of population decline in parts of the range, the overall rate of decline is not believed to approach the threshold for the population decline criterion of the IUCN Red List (i.e., declining more than 30% in ten years or three generations). For these reasons, it is evaluated as Least Concern. However, population trends should be monitored.",Unknown,"Plecotus austriacus is restricted to Europe, excluding northern countries. Widespread south of 52-53°N, from south England to Moldova and the Black Sea Coast southwards to the Mediterranean coast (Spitzenberger et al. 2006). One record in south Sweden. Found on Mediterranean and Atlantic islands: Balearic Islands, Sardinia, Corsica and Sicily and Madeira (Spitzenberger et al. 2006). Highest confirmed record in the Alps 1,390 m (hibernaculum) (Spitzenberger 2002).","It is a common species in the Mediterranean, but relatively rare in the European part of Turkey (A. Karatas pers. comm. 2007). Summer colonies usually consist of 10-30 females. Winter clusters are usually small (2-3 animals), and the species is often solitary in this season. Population declines have been documented in parts of central Europe (Horácek et al. 2004); in Austria this species is listed as Vulnerable (Spitzenberger 2005) and in Croatia it is listed as Endangered (Tvrtkovic 2006). In Portugal there is no evidence of decline. Elsewhere in the range data on population trend is lacking.","It forages in lowland valleys and open agricultural landscapes in central Europe, and in a great variety of open and semi-open habitats in southern Europe. It feeds mainly on moths. In summer it typically roosts in buildings (attics, fissures, cavities, old castles), although solitary animals may roost in underground sites. In winter it hibernates in buildings, mines, and caves. It is a sedentary species, and no individual has been recorded to move further than 62 km (Gaisler and Hanák 1969 in Hutterer et al. 2005).","Some populations are affected by remedial timber treatment (poisoning by wood preserving chemicals) and loss of roost sites. Intensification of agriculture seems to have a negative impact on the species in central Europe, and may be responsible for population declines reported in this region. Agricultural intensification may also affect the species in other parts of the range.","It is protected by national legislation in most range states. There are also international legal obligations for protection of this species through the Bonn Convention (Eurobats) and Bern Convention. It is included in Annex IV of EU Habitats and Species Directive, and there is some habitat protection through Natura 2000. Recommended actions include monitoring population trends, and improving agricultural habitats by protecting and restoring hedges and scrubby areas and reducing pesticide use.","Juste, J., Karataş, A., Palmeirim, J., Paunović, M., Spitzenberger, F. & Hutson, A.M." +ANIMALIA,CHORDATA,MAMMALIA,CHIROPTERA,VESPERTILIONIDAE,Plecotus kolombatovici,"Originally described as a subspecies of austriacus, but clearly distinct; see Mayer and von Helversen (2001) for genetics, Tvrtković et al. (2005) for morphology.",No,No,NT,,NT,,"European and EU 25: Near Threatened (close to qualifying for VU C1). The population size in Europe and the EU 25 is small and estimated as no more than 10,000 individuals, and the species is found mainly in coastal areas where it is suspected that pressure from tourism is causing population decline approaching 10% over 3 generations. It is not known whether there would be a significant rescue effect from outside Europe so the regional Red List assessment is not adjusted.",Unfavourable,"The distribution of Plecotus kolombatovici is fragmented into three main parts: southern regions of the Balkans and Asia Minor, Libya (Cyrenaika) and northwest Africa from Morocco to Tunisia; it has been found in Malta and Pantellaria (Spitzenberger et al. 2006). It occurs from sea level to higher altitudes in the Rif and Atlas mountains.","Little is known about population size and trends in this species, although it is regarded as relatively common in North Africa. In Europe, the total population is estimated at fewer than 10,000 mature individuals, and it is suspected that the population may be declining. Summer colonies usually number 10-30 females, although a breeding colony of 120 females was found in a building in Croatia (F. Spitzenberger pers. comm. 2006). Winter clusters are smaller (10 ind.), and the species is often solitary at this time of year (S. Aulagnier pers. comm. 2006). It is possible that European, African and south-west Asian populations are isolated from each other.","It forages in a variety of open and semi-closed habitats, mainly steppe but also agricultural landscapes in both lowland and mountain areas. It often forages over small water bodies. It feeds predominantly on moths, but also takes beetles and flies. Summer roosts are primarily rocky cavities, but also dark areas of old monuments, ruins, caverns and buildings. Winter roosts are located in buildings, mines, caves, wells, and trees.","Pesticides and roost disturbance have a negative impact on the species, but are not thought to be causing significant population declines at the global level. However, in Europe, where this species is largely restricted to coastal areas, disturbance of roost sites by tourists may be a major threat.","It is protected by national legislation in most range states. There are also international legal obligations for its protection through the Bonn Convention (Eurobats) and Bern Convention. It is included in Annex IV of EU Habitats & Species Directive, and there is some habitat protection through Natura 2000. Recommended actions include monitoring population trends and minimising or preventing disturbance to roost sites in Europe.","Tony Hutson, Friederike Spitzenberger, Stéphane Aulagnier" +ANIMALIA,CHORDATA,MAMMALIA,CHIROPTERA,VESPERTILIONIDAE,Plecotus macrobullaris,"Described as subspecies of P. auritus from northern Ossetia, Russia. Its specific status was first recognized for populations of the Alps, which were described as new species: Plecotus alpinus by Kiefer and Veith (2002) and Plecotus microdontus by Spitzenberger et al. (2002). Later it transpired that these names were younger synonyms of P. macrobullaris (Spitzenberger et al. 2003).",No,No,NT,,VU,B2ab(iii),"European: Near Threatened (close to qualifying for B2ab(iii)). Each colony uses around 10 km2 as foraging range. Only 15 colonies are known from the Alps, ten from Croatia, and two from the Pyrenees. This would sum to ca. 300 km2. Even if more colonies are discovered in the remaning part of the range the area of occupancy will not be much larger than 2,000 km2. Roosting habitat is declining because of tourism pressure on caves and transformation of buildings in human settlements in the Alps and Pyrenees. Genetic analysis suggests that there is little interchange between subpopulations, so it is not expected that there will be a rescue effect from outside the region.EU 25: VU B2ab(iii). Taking out Croatia, Serbia, Montenegro and Switzerland from the range, it is estimated that the species' AOO is smaller than 2,000 km2. Roosting habitat is declining because of tourism pressure on caves and transformation of buildings in human settlements in the Alps and Pyrenees. Genetic analysis suggests that there is little interchange between subpopulations, so it is not expected that there will be a rescue effect from outside the region.",Unfavourable,"Pyrenees; Alps from France to Slovenia, Dinaric Alps, Greece incl. Crete; Corsica; from Anatolia through Caucasus to south Iran; Syria (Spitzenberger et al. 2006). Altitudinal distribution from sea level to 2,800 m (Garin 2003, Pavlinić and Tvrtković 2004).","This species was only recognised in 2003, and remains quite poorly known. However, it seems to be generally uncommon, with a fragmented distribution. Individual colonies are composed of few (less that 50) individuals. Fewer than 50 colonies are known, but more are likely to be discovered in the future (Spitzenberger et al. 2003). Molecular analyses have confirmed that subpopulations from different mountain ranges are genetically isolated (Garin et al. 2003).","Is known from a wide array of habitats. In Croatia it was found in all altitudinal zones from sea level to mountain tops above the tree line. It occupies Mediterranean oak shrub as well as beech and pine forests (Pavlinić and Tvrtković 2004). The highest record is 2,800 m (Pyrenees: Garin et al. 2003). In the Eastern Alps maternity roosts are located in attics of churches, winter roosts are not known (Spitzenberger 2002), the highest record here is 1,720 m (Spitzenberger 2006).","In the European part of its range, restoration of old buildings and development of tourism infrastructure is causing habitat loss.","It is protected by national legislation in most range states. There are also international legal obligations for its protection through the Bonn Convention (Eurobats) and Bern Convention. It is included in Annex IV of EU Habitats & Species Directive, and there is some habitat protection through Natura 2000. It is present in several national parks. Recommended actions include surveys to better understand the species' distribution, molecular studies on distance between populations, and protection of roosting sites.","Tony Hutson, Friederike Spitzenberger, Javier Juste, Stéphane Aulagnier, Juan Tomas Alcaldé" +ANIMALIA,CHORDATA,MAMMALIA,CHIROPTERA,VESPERTILIONIDAE,Plecotus sardus,"Identified as a new species by genetic analyses, this species combines morphological features of both P. austriacus and P. auritus.",Yes,Yes,VU,B2ab(iii),VU,B2ab(iii),"This species is considered to be Vulnerable. It is restricted to forest fragments in Sardinia (Italy). Since this species was first identified in 2002, it has been captured in only three localities, two in the same National Park. The population is probably very small, although more localities will probably be discovered in the future. Forests in Sardinia sum up to less than 2,000 km2, and their quality is declining. Further surveys are required to obtain a more accurate understanding of the status of this species, as based just on the known information it could be listed as Endangered.",Unfavourable,Plecotus sardus is restricted to the island of Sardinia (Italy). The three known localities are situated near to the coast or at low elevations.,This species was first described in 2002 and is poorly known. It is considered to be rare (known only from five specimens).,"It occurs in the most wooded areas parts of Sardinia, and roosts in natural caves. Two of the three known localities are situated in karstic areas, one locality lies near the sea coast (Mucedda et al. 2002). Artificial habitats are not used. It is a sedentary species.",Roost disturbance (as a result of tourism) and habitat loss (caused by forestry management) are the main threats to the species.,"It is protected by national legislation in most range states. There are also international legal obligations for its protection through the Bonn Convention (Eurobats) and Bern Convention. It is included in Annex IV of EU Habitats and Species Directive. Two of the three known localities are in the National Park of Gennargentu and the Orosei Gulf. Recommended research actions include surveys and monitoring to determine distribution, status, and population trend. Protection of roosting and foraging habitat is also recommended.","Hutson, A.M., Aulagnier, S., Juste, J., Karataş, A., Palmeirim, J. & Paunović, M." +ANIMALIA,CHORDATA,MAMMALIA,CHIROPTERA,VESPERTILIONIDAE,Plecotus teneriffae,"The taxonomic status of the species has been confirmed by Spitzenberger et al. (2006). Here we refer to P. teneriffae as the population on the Canaries. Northwest African populations previously assigned to teneriffae are currently included in kolombatovici, and Balkan populations are assigned to austriacus. There are no significant genetic differences between populations on the different islands (Justeet al. 2004).",Yes,Yes,EN,B1ab(v),EN,"B1ab(iii,v)","This species has a small range (<3,000 km2) on three, and maybe four, of the Canary Islands (and it is severely fragmented). It is linked to forest habitats that are shrinking, and recent declines have been recorded in the largest known breeding colony. For these reasons, it is assessed as Endangered.",Unfavourable,"Plecotus teneriffae is endemic to the Canary Islands (Tenerife, La Palma, El Hierro and may also be on La Gomera, but presence there has not yet been confirmed although there is suitable habitat), where its extent of occurrence is less than 3,000 km2. It occurs at elevations between 100 and 2,300 m (Palomo and Gisbert 2002).","Summer colonies usually consist of 10-30 females (the maximum number recorded is 37). Winter clusters are usually small (c.10 animals), and the species often roosts solitarily at this time of year. There are only two known breeding colonies (on La Palma and Tenerife respectively). The larger of these two (the La Palma colony) has declined almost 80% in number in recent years (Palomo and Gisbert 2002; J. Juste pers. comm. 2007).The population is estimated to be between 500 and 2,000 individuals (J. Juste pers. comm. 2007, based on information in the Spanish Red Data Book).","It is highly associated with woodland habitats (coniferous and mixed), although it occasionally forages in more open and arid areas. Its diet consists primarily of moths. Recorded roost sites include volcanic tubes, caves, and crevices in abandoned buildings (Palomo and Gisbert 2002). Tree holes and bat or bird boxes are never used (Benzal and Fajardo 1999). The La Palma maternity colony is located in a natural cave. This species is considered to be sedentary (Fajardo and Benzal 2002 in Hutterer et al. 2005).","The population declined in the 1950s after aerial fumigation for pest control. Current threats include use of pesticides on agricultural land near to the forests, loss of woodland habitat, and restoration of buildings that results in the disturbance of colonies and the destruction of roost sites (Palomo and Gisbert 2002). The recent decline of the La Palma maternity colony has been attributed to disturbance, and it is known that at least one individual from this colony has been taken by private collectors (Palomo and Gisbert 2002). Shafts into the mountains to collect water are increasingly being fenced which is detrimental to the survival of the bats.",It is protected by national legislation in most range states. There are also international legal obligations for its protection through the Bonn Convention (Eurobats) and Bern Convention. It is included in Annex IV of the EU Habitats and Species Directive. A bat protection programme aimed at protecting caves used as roost sites from human disturbance was instigated in 1993 (Mitchell-Jones et al. 1999). Protection of the species' woodland foraging habitat is also recommended (Palomo and Gisbert 2002).,"Aulagnier, S., Juste, J., Palmeirim, J. & Alcaldé, J.T." +ANIMALIA,CHORDATA,MAMMALIA,CHIROPTERA,VESPERTILIONIDAE,Vespertilio murinus,,No,No,LC,,LC,,"European regional assessment: Least Concern (LC)EU 25 regional assessment: Least Concern (LC)The species is widespread and common, and there is no evidence of current significant population decline. Consequently it is classed as Least Concern.",Unknown,"Vespertilio murinus has a wide distribution in the northern Palaearctic, from France and the Netherlands in the west through central, northern, and eastern Europe and Siberia to the Pacific coast. The northern limit is above 60°N in Fennoscandia and ca. 63°N in Russia, and the southern limit of its range passes through the Balkan peninsula, northern Iran, central Asia, Afghanistan, northern Pakistan, and China. The southern records refer to wintering individuals, and the most western records refer to vagrants. Breeding is restricted to the northern part of the range in this migratory species. It occurs from sea level to over 3,000 m.","An abundant species in northern parts of its European range. Summer maternity colonies number 30-50 (exceptionally 200) females; males may also form large colonies in summer. In winter it usually occurs singly or in small groups (although clusters of up to 30 have been recorded). Populations are expanding in some parts of the range, for example Denmark (H. J. Baagøe pers. comm.) and the Netherlands (H.J.G.A. Limpens pers. comm.)","It forages in open areas over various habitat types (forest, urban, steppe, agricultural land). It feeds on moths and beetles. Summer roosts tend to be situated in houses or other buildings; also rarely hollow trees, nest boxes, or rock crevices. Winter roost sites include rock fissures, often (as substitute) crevices in tall buildings (including, or especially, in cities), occasionally tree holes or cellars. Winter roosts are usually in colder sites that are exposed to temperature changes. Migrations of up to 1,780 km have been recorded (Markovets et al. 2004), although the species is sedentary in a large part of its range.","Although not a major threat, the species is affected by loss of or disturbance to roosts in buildings.","It is protected by national legislation in most range states. There are also international legal obligations for its protection through the Bonn Convention (Eurobats) and Bern Convention, in parts of its range where these apply. It is included in Annex IV of EU Habitats & Species Directive. No specific conservation actions are known.","Tony Hutson, Friederike Spitzenberger, Stéphane Aulagnier, Ioan Coroiu, Michael Stubbe" +ANIMALIA,CHORDATA,MAMMALIA,EULIPOTYPHLA,ERINACEIDAE,Atelerix algirus,,No,No,LC,,LC,,"European regional assessment: Least Concern (LC)EU 25 regional assessment: Least Concern (LC)In Europe and the EU, the species is generally rare (although it is common on some small islands) and has a relatively small and fragmented range. There is no evidence at present of population decline, but the status of the species should be monitored, and if declines in population or range occur in the future, uplisting may be warranted.",Unknown,"Atelerix algirus is endemic to the Mediterannean region, being found across north Africa from Morocco to Libya, in Spain, and on a number of islands including the Canary Islands, Djerba, Malta, Majorca, Ibiza and Formentera. It was formerly introduced to France, but is now extinct. Its occurence in continental Europe and on many of the islands within its range may be the result of introductions by man (Lapini 1999). It typically occurs at altitudes of 0 to 400 m, although it can reach altitudes of 900 m in Morocco (Lapini 1999).","It is rare in mainland Europe, and on most of the islands within its range, although it is locally common on the Canary Islands, Malta and Formentera (Lapini 1999, Palomo and Gisbert 2002).","It is found in a range of habitats including semi-desert, dry Mediterranean scrub, grasslands, pastures, cultivated fields, and gardens, sometimes in close proximity to human habitation. It is most often found in arid areas (Lapini 1999, Palomo and Gisbert 2002). It forages at night for arthropods, small vertebrates, carrion, and fungi.",Threats include roadkill. Populations may be limited by the availability of suitable habitat (Palomo and Gisbert 2002). The species is sometimes taken from the wild to keep as a pet (Palomo and Gisbert 2002).,"It is listed on Appendix II of the Bern Convention and Annex IV of the EU Habitats and Species Directive. Surveys and monitoring are required to determine population trends in this rare species. If there is any evidence of declines, action should be taken to protect the species. Research would be required to determine appropriate conservation measures.",Giovanni Amori +ANIMALIA,CHORDATA,MAMMALIA,EULIPOTYPHLA,ERINACEIDAE,Erinaceus concolor,,No,No,NA,,NA,,European regional assessment: Not Applicable (NA)EU 25 regional assessment: Not Applicable (NA)Assessed as Not Applicable as it is of marginal occurrence in Europe.,-,"Found on Rhodes (Greece); also ""Asia Minor to Israel, Syria, Lebanon, Iraq and Iran; S Caucasus"" (Wilson and Reeder 2005). Less than 1% of its global range lies within the European Mammal Assessment region.",,,,,European Mammal Assessment team +ANIMALIA,CHORDATA,MAMMALIA,EULIPOTYPHLA,ERINACEIDAE,Erinaceus europaeus,,Yes,No,LC,,LC,,This species is common and abundant throughout its wide range. Consequently it is considered to be Least Concern.,Possibly Favourable,"Erinaceus europaeus is endemic to Europe (including European Russia), with a global distribution extending from the British Isles and the Iberian peninsula, westwards through much of western to central Europe; and from southern Fennoscandia, and the northern Baltic to north-west Russia. It was introduced recently to the Azores (Portugal); the species was recorded there in the 1990s (R. Hutterer pers. comm. 2007). In the Mediterranean, it occurs in Portugal, France (including Corsica), Spain and Italy (including Sardinia and Sicily but not present on Malta).","This generally is a relatively common and widespread species. It is rare in Sardinia (Italy), where it is hunted with dogs (R. Hutterer pers. comm. 2007). The is no evidence of any population decline in most parts of its range. Many of the island populations have been introduced there from the mainland (R. Hutterer pers. comm. 2007).","E. europaeus thrives in a variety of man-made habitats including orchards, vineyards, farmland, parks and gardens, including those in urban areas. It also occurs in deciduous woodland, woodland edge and grasslands, although it is less common in these areas (Lapini 1999). Also occurs in maquis (R. Hutterer pers. comm. 2007).","There are no major threats to this species across most of its range. In some areas, many hedgehogs are killed by collision with cars, but this is unlikely to cause serious population declines (Huijser 1999, Verkem et al. 2003). It is locally hunted and eaten in parts of its range, but this is a localised activity and is also not considered a serious threat to the species.",This species is listed on Appendix III of the Bern Convention. It occurs in a number of protected areas throughout its wide range. It is also legally protected in many countries within its range.,"Amori, G., Hutterer, R., Kryštufek, B., Yigit, N., Mitsain, G. & Palomo, L.J." +ANIMALIA,CHORDATA,MAMMALIA,EULIPOTYPHLA,ERINACEIDAE,Erinaceus roumanicus,"Formerly included in europaeus, but see Suchentrunk et al. (1998), among others. Subsequently included in concolor, but genetic and morphological data suggest that concolor and roumanicus are two distinct species with parapatric distributions.",No,No,LC,,LC,,European regional assessment: Least Concern (LC)EU 25 regional assessment: Least Concern (LC)This species is common and abundant throughout its wide range. Consequently it is considered to be Least Concern.,Possibly Favourable,"Erinaceus roumanicus has a distribution extending from central and eastern Europe, the Baltic and the Balkan peninsula eastwards through Belarus, Ukraine, and Russia, reaching as far as western Siberia. In the south, its range extends as far as the northern Caucasus and possibly north-western Anatolia (B. Kryštufek pers. comm. 2006). It is recorded from sea level to at least 1,400 m (Lapini 1999).","It is relatively rare in the colder parts of its range, but there is no evidence to suggest a population decline. It is locally common in at least some areas (Lapini 1999).","It inhabits farmland, parks and gardens in rural and urban areas, and scrubby habitats at the edge of forests. Like its congener E. europaeus, it is more abundant in artificial than in natural habitats (Lapini 1999).","Many are killed by collision with cars (Lapini 1999), but this is unlikely to cause widespread population decline.",It occurs in many protected areas throughout its wide range.,Boris Kryštufek +ANIMALIA,CHORDATA,MAMMALIA,EULIPOTYPHLA,ERINACEIDAE,Hemiechinus auritus,,No,No,LC,,NE,,"European regional assessment: Least Concern (LC)EU 25 regional assessment: Not Evaluated (NE)This species is common and abundant throughout its wide range, but some marginal populations are fragmented and slowly declining. In Ukraine the population has historically declined dramatically, and the species is considered Critically Endangered in the national Red Data Book.",-,"Widespread in the steppe zone from Northeast Africa to Central Asia. In Europe it occurs in Southeast Ukraine, the lower Don River and Volga River basin steppes (Russian Federation) and Cis-Caucasus.","It is a widespread and common species in most of the distribution area, but in marginal parts of its range populations are usually fragmented and often declining. There is a lack of detailed data on population size in the European part of the distribution area, but it is considered Critically Endangered in the Ukraine owing to its very small range and declining trend in that country (I. Zagorodnuik pers. comm. 2006). Since 1950 three fragmented populations have been recorded in Ukraine: one around the Streltsovskie Stepi Nature Reserve (last record about 50 years ago), one record from amateur source found near Lugansk city in 2001/2, and one in the Donetsk Region near shore of Azov sea. The third population is the only stable one and is largest in Ukraine. It is partly covered by the Kamennye Mogily Nature Reserve (I. Zagorodnuik pers. comm.).","Inhabits different types of dry steppes, semi-deserts and deserts. Prefers dry river valleys, gullies, forest shelter belts, abandoned irrigation ditches and shrubby areas. Often settles in oases and around human settlements. Avoids tugais and high herbage. Lives in burrows that it usually digs itself, although sometimes it occupies abandoned burrows of turtles, gerbils, foxes and otters. Active at night. In nothern parts of distribution area hibernates from late October/early November to late March/early April. Heat occurs in April after hibernation. Gestation is about 40 days, females give birth to 3 to 8 pups (5-6 on average). In the European part of the distribution area it usually gives birth once a year, in southern parts often twice.","No major threats are known for most of the distribution area. In marginal populations (e.g., Ukraine) it could suffer from habitat loss.",It occurs in a number of protected areas throughout its wide range. The species is listed as Critically Endangered in the Red Data Book of Ukraine.,Igor Zagorodniuk +ANIMALIA,CHORDATA,MAMMALIA,EULIPOTYPHLA,SORICIDAE,Crocidura canariensis,"It has been argued, on the basis of mandibular measurements, that Crocidura canariensis should be treated as a subspecies of C. sicula (Sarà 1996). However, other morphological, ecological, palaeontological and molecular evidence supports specific status (Michaux et al. 1991, Hutterer et al. 1992). Genetic distances suggest that C. canariensis and C. sicula diverged approximately five million years ago (Vogel et al. 2003).",Yes,Yes,EN,"B1ab(ii,iii)",EN,"B1ab(ii,iii)","C. canariensis has a very small extent of occurrence (5,000 km²), which is severely fragmented, and presumably declining as a result of habitat loss and degradation caused by urbanisation and desertification. Consequently it qualifies as Endangered.",Unfavourable,"The Canary shrew Crocidura canariensis is endemic to the eastern Canary Islands, where it is currently found on Lanzarote, Fuerteventura, Lobos and Mount Clara. Its extent of occurrence (EOO) is less than 5,000 km². Recent fossils indicate that it previously occurred on Graciosa and Alegranza (Hutterer 1999), but it has never been trapped on either of these islands and is presumed to have gone extinct there (Palomo and Gisbert 2002). Canary shrew remains have been found in owl pellets collected on Graciosa and Alegranza, but this is believed to result from the movement of owls between different islands (Palomo and Gisbert 2002).","Numbers and population trends are unknown. Mount Clara has a tiny population, which is unlikely to number more than a hundred individuals. The habitat of C. canariensis is severly fragmented as a result of anthropogenic habitat loss and natural barriers to dispersal (R. Hutterer pers. comm. 2006).","The Canary shrew's main habitat is the malpaís (barren lava fields), and it seems to be adapted to the hot and dry conditions of these plains (Hutterer et al. 1992, Stone 1995). It feeds on snails and insects in lava tubes, and it is cool inside its burrows even when temperatures reach 60ºC outside. The shrew is also sometimes found in gardens and abandoned arable land adjacent to lava fields, as well as in rocky gullies and sandy areas with rocks and vegetation (Palomo and Gisbert 2002). On Mount Clara, the species is restricted to a single coastal sand dune. More suitable habitat is found on other islands, however, there is a lot of urbanisation and industry.","This species has a highly restricted distribution. Rapid urbanisation and infrastructure development in and around its range are causing loss and fragmentation of suitable habitat, and desiccation may also be a problem (Hutterer 2004). Introduced cats Felis catus sometimes depredate Canary shrews (Palomo and Gisbert 2002). Other introduced species, e.g. rats and mice, are also present but are not known to have any effect on the Canary shrew. Of these threats, habitat loss is considered to be the most important (Palomo and Gisbert 2002).","C. canariensis is listed on Appendix II of the Bern Convention and Annex IV of the EU Habitats Directive, and is also protected under Spanish law. It is found within a number of National Parks in Fuerteventura. Research is needed to determine the ecological and conservation requirements of this species (Stone 1995). Recommended conservation measures include controlling feral cats and preventing further introductions of alien species to small islands such as Mount Clara (Palomo and Gisbert 2002).","Hutterer, R." +ANIMALIA,CHORDATA,MAMMALIA,EULIPOTYPHLA,SORICIDAE,Crocidura leucodon,,No,No,LC,,LC,,"European regional assessment: Least Concern (LC)EU 25 regional assessment: Least Concern (LC)This species has a large range, within which it is widespread. The population size has not been quantified, but the species is not believed to approach the thresholds for the population size criterion of the IUCN Red List (i.e. less than 10,000 mature individuals in conjunction with appropriate decline rates and subpopulation qualifiers). Although population declines or fluctuations have occurred in parts of its range, the species is not believed to approach the thresholds for the population decline criterion of the IUCN Red List (i.e. declining more than 30% in ten years or three generations). For these reasons, it is evaluated as Least Concern.",Possibly Favourable,"Crocidura leucodon occurs in Europe and western Asia, from north-west France in the west to the Caspian sea in the east, extending as far south as Israel. In Europe, it is absent from Iberia and southern France, Fennoscandia, northern Poland, the Baltic, and northern Belarus and European Russia (Krapp 1999). The only European island on which it is known to be present is Lesbos (Greece). Its distribution in the eastern part of the range is not well known because it is possible that some records from that region refer to a different species. It occurs from sea level to around 2,000 m.","At the northern and western borders of its range at least, it appears to be declining or fluctuating. In the southern part of eastern Europe this species has seriously declined during the last 50 years (50 years ago there were many records, especially from owl pellets, whereas recently there are very few records)(I. Zagorodnyuk pers. comm. 2006).","Its habitat preferences vary in different parts of its geographic range. In France, it is found in damp areas with dense vegetation, whereas in central Europe and Italy it prefers open agricultural landscapes. At the northern edge of its range it is associated with gardens and houses in suburban and urban areas, and in the Balkans and Asia Minor it can be found in moist habitats in the mountains including screes, stony areas, riverbanks and stone walls. In Asia Minor it is also found above the tree line in stony areas (Krapp 1999). In European Russia the species occurs in moist habitats within steppe and semi-desert areas. It feeds on invertebrates, including insects, insect larvae and worms.","This species often occurs in open rural country, where it may be negatively affected by agricultural intensification (accidental poisoning and loss of prey species as a result of pesticide use, and loss of cover owing to replacement of hedgerows and fallow areas with large-scale monocultures) (Krapp 1999).","It is protected under Appendix III of the Bern Convention, and it occurs within protected areas.","Vladimir Vohralík, Jan Zima, Boris Kryštufek" +ANIMALIA,CHORDATA,MAMMALIA,EULIPOTYPHLA,SORICIDAE,Crocidura pachyura,,No,No,DD,,DD,,"European regional assessment: Data Deficient (DD)EU 25 regional assessment: Data Deficient (DD)In Europe, this species is restricted to the islands of Ibiza, Sardinia and Pantelleria, where it has a small range (approaching the threshold for the geographic range criterion of the IUCN Red List, i.e less than 20,000 km²). However, there are no data on population trends. Currently there are no serious threats known, but pesticide use may be problematic. More research is needed to determine the status of this species, and reassessment is recommended if more data become available.",Unknown,"This species occurs on the islands of Ibiza (Spain), and Sardinia and Pantelleria (Italy). It also occurs in North Africa, where its range is poorly known but includes Tunisia and eastern Algeria (Wilson and Reeder 2005). The Pantelleria population may be a separate subspecies (cossyrensis). It occurs from sea level to 800-1,000 m above sea level (G. Amori pers. comm. 2006).","Little is known about population size and trends in this species, but it is not rare (G. Amori pers. comm. 2006).","It occurs in a variety of habitats including pastures, cultivated fields, low shrubland, gardens, and old agricultural terraces with dry-stone walls.","No serious threats are known at present, although accidental poisoning with pesticides may be a problem. The population on Pantelleria may be threatened because of its highly restricted range.",It is listed on Appendix III of the Bern Convention (as a subspecies of Crocidura russula). Further research is required to determine population status and trends and to investigate potential threats.,Giovanni Amori +ANIMALIA,CHORDATA,MAMMALIA,EULIPOTYPHLA,SORICIDAE,Crocidura russula,"Genetic studies indicate that the population on Gran Canaria in the Canary Islands (previously considered to be a separate species, Crocidura osorio) is conspecific with C. russula (Vogel et al. 2003), although differences in size, ecology, and behaviour (Hutterer et al. 1992) characterize it as a distinct island form. The African population is probably a composite of two species that are only sympatric in part of Algeria (R. Hutterer pers. comm.).",No,No,LC,,LC,,"European regional assessment: Least Concern (LC)EU 25 regional assessment: Least Concern (LC)A very widespread and common species within its range, with no serious threats.",Possibly Favourable,"This species is found in southern and western Europe (including some Atlantic and Mediterranean islands). It also occurs in North Africa, in Morocco, Tunisia and Algeria (Ramalhinho et al. 1999). The population on Gran Canaria in the Canary Islands (previously considered to be a separate species, Crocidura osorio) seems to have been introduced from Spain (Vogel et al. 2003). It typically occurs from sea level to 1,200 m, but has also been found as high as 2,000 m, particularly in Mediterranean landscapes (Palomo and Gisbert 2002).","Population size and trends are unknown, although the species is generally widespread and fairly common within its range. In Germany at least it is stable and expanding in some parts, although it is not known if this is natural or the result of accidental human transportation (Kraft 2000). It is probably the most common shrew in Spain, and is often the dominant prey species in the barn owl's diet in this region (Ramalhinho et al. 1999).","In the Mediterranean it occurs in a wide range of habitats including shrubland (maquis), open habitats, forest edges with abundant ground vegetation, cultivated fields, urban areas, gardens, farms, mountainous areas and land adjacent to rivers and streams (Palomo and Gisbert 2002). It particularly favours old terraces with dry stone walls. In northern Europe and at higher alititudes it is predominantly synanthropic, living in close proximity to humans in houses and gardens (Ramalhinho et al. 1999). In Morocco, it occurs in the mountains.","Due to its synanthropic habits it may suffer from the use of pesticides and other toxic chemicals (Ramalhinho et al. 1999), but this is not thought to be a serious threat to the species at present.","It receives legal protection under the Bern Convention (Appendix III), and it occurs in numerous protected areas.","Holger Meinig, Stéphane Aulagnier, Rainer Hutterer" +ANIMALIA,CHORDATA,MAMMALIA,EULIPOTYPHLA,SORICIDAE,Crocidura sicula,,Yes,Yes,LC,,LC,,"C. sicula is endemic to Italy, occurring on Sicily and surrounding islands in the Mediterranean. It is relatively widespread within its range and although population trends are not known, there do not appear to be any serious threats at present. Consequently, the species is assessed as Least Concern. It has a small extent of occurrence (approaching 20,000 km²), therefore it should be reassessed if any declines are suspected. Populations on Sicily and Gozo may deserve some special attention because they are genetically distinct.",Unknown,"Crocidura sicula is endemic to Sicily and its associated islands (to Italy) and Malta. It is currently found on Sicily, Ustica, Gozo, and the Egadi islands (Favigniana, Levanzo, Marettimo). It may be extinct on the island of Malta, where it is known only from subfossil remains (Vogel 1999). It occurs from sea level to about 1,000 m (G. Amori pers. comm. 2006).","This species is widespread on Sicily (Maddalena et al. 1990). However, trapping results indicate that it occurs at much lower densities than other Crocidura species that inhabit Mediterranean islands (Vogel 1999). Population trends are unknown. It may have gone extinct on the island of Malta, but even if so, the date of that extinction is unknown. In Ustica a melanic form occurs and shows a very restricted range (G. Amori pers. comm. 2006).A new genetic study has shown that populations of Sicily and Gozo may deserve some special attention because they are genetically distinct (R. Hutterer pers. comm. 2007).","Owl pellet analyses suggest that C. sicula inhabits suburban areas, gardens, pastures, arable land, and open scrub. In the summer, it prefers damp areas (Vogel 1999).","No serious threats are known at present, although pesticides in agricultural areas are often a problem for insectivore species. Populations on smaller islands could be adversely affected by predation from domestic cats (G. Amori pers. comm. 2006).","It is protected under Appendix III of the Bern Convention. No specific conservation actions are recommended at this time. This is one of only three ancient endemic mammal species occurring on the Mediterranean islands (Gippoliti and Amori 2006), and for this reason it is a valuable species to conserve.","Amori, G. & Hutterer, R." +ANIMALIA,CHORDATA,MAMMALIA,EULIPOTYPHLA,SORICIDAE,Crocidura suaveolens,"Populations from eastern Asia (SE Siberia, E China, Korea, Taiwan) are now considered to be a separate species, C. shantungensis.",No,No,LC,,LC,,A widespread and common species throughout its range with no major threats.,Possibly Favourable,"The lesser white-toothed shrew Crocidura suaveolens has a wide distribution in the Palaearctic, extending from the Atlantic coast of Spain and probably Portugal (where its occurrence needs further confirmation) eastwards through Europe and Asia to Siberia. The southernmost edge of its distribution passes through northern Africa (Morocco and Algeria: Corbet 1978), Asia Minor, Israel, Saudia Arabia, Iran and China. In Europe, it has a somewhat scattered distribution in north-west Iberia, south-west France, Italy, central and eastern Europe, and the Balkans. It is present on some Atlantic and Channel islands, and on most eastern Mediterranean islands, as well as Menorca, Corsica, Elba, and Capraia in the western Mediterranean. It was introduced to Crete in Minoan times (Pieper 1990), where it may threaten the endemic Cretan white-toothed shrew C. zimmermanni through competition (Nowak 1999). In eastern Europe and in Germany C. suaveolens is expanding northwards in urban landscapes. It is commonest from sea level to 1,000 m, although it occurs as high as 1,600 m (Libois et al. 1999).","It is uncommon in the western part of its range, occurring at much lower densities than its congener C. russula (Libois et al. 1999). Further east it is more common. Described as abundant and ubiquitous in at least parts of its global range (Harrison and Bates 1991). In the steppe forest zone in Ukraine it is the most abundant shrew species, both in natural and agricultural habitats (I. Zagorodnyuk pers. comm. 2006).","At higher latitudes and altitudes in Europe it is often associated with human habitation, tending to be found in parks, gardens, and even houses. It is very common in straw ricks. In western and southern Europe and it inhabits a wide range of habitats including vineyards, olive groves, terraced farmland on hillsides, dry Mediterranean shrubland, sand dunes, rocky areas in the mountains, and damp densely-vegetated patches near to water. It tends to avoid dense forests (Vlasák and Niethammer 1990, Libois et al. 1999). Small, soft-bodied insects form a major part of its diet (Vlasák and Niethammer 1990).In south-west Asia it has been collected from habitats with long dry grasses; thick vegetation along streams, river edges and vegetation channels; around houses and in forested areas (Bates and Harrison 1989, Tez 2000). Its main requirement is enough vegetation and moisture to support its insect prey, and in arid areas it tends to be more common near springs and oases; however it is more tolerant of dry conditions than many of its congeners (Qumsiyeh 1996). The gestation period is 28 days and life expectancy one year; a female may have 10-12 litters, each with one to seven young, although usually four (Qumsiyeh 1996).","It may be out-competed in some areas by C. russula. Pesticides and herbicides may have a negative impact on the species in agricultural habitats (Libois et al. 1999), but at present this does not seem to be a major threat.","It is listed on Appendix III of the Bern Convention. Subspecies C. s. caneae, endemic to Crete, is on Appendix II of the Bern Convention (as C. ariadne). It occurs in protected areas within its range. No specific conservation actions are recommended.","Vladimir Vohralík, Jan Zima, Boris Kryštufek, Boris Sheftel, Holger Meinig" +ANIMALIA,CHORDATA,MAMMALIA,EULIPOTYPHLA,SORICIDAE,Crocidura zimmermanni,,Yes,Yes,VU,"B1ab(i,ii,v)+2ab(i,ii,v)",VU,"B1ab(i,ii,v)+2ab(i,ii,v)","C. zimmermanni is endemic to Crete where it is restricted to the central areas of the island. Its extent of occurrence is less than 20,000 km² and it has been collected at only three sites, although further sites are known from owl pellet samples. It is estimated that there are fewer than 10 locations (certainly not more than 15 sites). It is suspected that population decline and range contractions are occurring as a result of out-competition by a non-native shrew, C. suaveolens. This could ultimately result in the extinction of C. zimmermanni. Assessed as Vulnerable.",Unfavourable,"Crocidura zimmermanni is endemic to the island of Crete (Greece), where it has been trapped in the central mountains at altitudes of 1,150 to 1,400 m. However, owl pellets collected at 140 to 830 m contained remains of this species, indicating that it may also occur at lower altitudes (Vogel 1999).",It is a rare and little-known species which is only recorded from a small number of localities. Analysis of owl pellets suggested that C. zimmermanni is more than ten times rarer than its congener C. suaveolens (Vogel 1999). The population trend has not been quantified but it is suspected to be decreasing.,"It has been collected in open mountainous areas that are dry in summer and snow-covered in winter (Vogel 1999). It is likely also to occur at lower altitudes, but if so its habitat preferences there are unknown.","The introduction of C. suaveolens in Minoan times (ca. 2,500 to 1,500 BC) may have forced C. zimmermanni into a restricted range as it is out-competed for habitat (Pieper 1990, Nowak 1999). C. suaveolens is abundant in coastal areas, but has also been found in the mountains at the same sites as C. zimmermanni (Vogel 1999).","It is listed on Appendix III of the Bern Convention. Research is required to determine its distribution and population trend, and to investigate potential threats (especially competition with C. suaveolens) and identify appropriate conservation measures.","Vohralík, V." +ANIMALIA,CHORDATA,MAMMALIA,EULIPOTYPHLA,SORICIDAE,Diplomesodon pulchellum,The only species of its genus.,No,No,NA,,NE,,"European regional assessment: Not Applicable (NA)EU 25 regional assessment: Not Evaluated (NE)Less than 1% of range lies within Europe, so it is considered Not Applicable.",-,"Distributed in sand deserts in Kazakhstan, Uzbekistan, Turkmenistan and Russia.","In some places is common, but it is a naturally rare species. Quantitative data on population size is lacking.","Inhabits semi-fixed and fixed sands covered by saxaul (Haloxylon sp.). Active at dusk and night. Usually uses rodent burrows. Feeds mainly on insects and their larvae, often eats ants, sometimes hunts small lizards. Breeding season is from March to October. Young animals start reproduction in the second half of summer. Litter size is 4-5.",There are no major threats to the species. In the areas of overlapping range Hemiechinus auritus and Crocidura spp. are food competitors.,There are no special conservation measures applied. A common species in most parts of the range.,"Katerina Tsytsulina, Nikolai Formozov, Boris Sheftel" +ANIMALIA,CHORDATA,MAMMALIA,EULIPOTYPHLA,SORICIDAE,Neomys anomalus,,No,No,LC,,LC,,"European regional assessment: Least Concern (LC)EU 25 regional assessment: Least Concern (LC)This species has a wide range. The population size has not been quantified, but it is not believed to approach the thresholds for the population size criterion of the IUCN Red List (i.e. less than 10,000 mature individuals in conjunction with appropriate decline rates and subpopulation qualifiers). Although the species is presumed to be declining as a result of loss and degradation of its wetland habitat, it is not believed to approach the thresholds for the population decline criterion of the IUCN Red List (i.e. declining more than 30% in ten years or three generations). For these reasons, it is evaluated as Least Concern. However, the fragmented distribution of this species makes it susceptible to local extinctions, and population trends need to be monitored.",Possibly Unfavourable,"Neomys anomalus has a patchy distribution in continental Europe and Asia Minor. It is found in parts of central and southern Europe from Spain and Portugal in the west through to the middle of the River Don (European Russia) in the east, but its range is fragmented (Corbet 1978, Spitzenberger 1999). It is recorded from sea level to 1,850 m (Spitzenberger 1999).","It is suspected to be declining in line with rates of loss of its wetland habitat (Spitzenberger 1999, Spitzenberger pers. comm. 2006). Its patchy distribution means that there are many small isolated subpopulations, making local extinctions more likely. It may be locally quite abundant in the absence of its main competitor, N. fodiens. There are areas where the two species occur in the same habitats, but using different niches.","It inhabits lush vegetation next to slow-flowing or still eutrophic waters (marshes, swamps, lakes, rivers, and streams). Its habitat choice is influenced by competition with the larger Eurasian water shrew N. fodiens, which is a stronger swimmer (Spitzenberger 1990, 1999). In general, N. anomalus is less aquatic than N. fodiens and can colonise areas away from water (Palomo and Gisbert 2002). However, in regions where N. fodiens is absent, N. anomalus may adopt its competitor's aquatic niche and increase in size (Spitzenberger 1990, 1999). N. anomalus is strictly carnivorous, feeding predominantly on soft-bodied invertebrates such as insect larvae, spiders and worms (Spitzenberger 1990, Palomo and Gisbert 2002).","The major threat to the species is habitat loss. In many parts of its range wetlands are being destroyed and fragmented as a result of water extraction, canalisation of streams, agriculture, road building, and other human activities. Water quality is often degraded by agricultural chemicals, industrial effluent and sewage. Use of pesticides may be a problem in parts of the range (Palomo and Gisbert 2002, Cabral et al. 2005).","It is listed on Appendix III of the Bern Convention, and it occurs in many protected areas. It is recommended that population trends are monitored, as the species may be vulnerable to the loss of aquatic habitats.","Holger Meinig, Sandro Bertolino, Boris Kryštufek" +ANIMALIA,CHORDATA,MAMMALIA,EULIPOTYPHLA,SORICIDAE,Neomys fodiens,,No,No,LC,,LC,,"European regional assessment: Least Concern (LC)EU 25 regional assessment: Least Concern (LC)This species has a wide range and is generally abundant, although local population declines have been recorded. Loss and degradation of wetland habitat is the main threat, although this is not a serious threat to the global population at present. The subspecies niethammeri in western Spain has a restricted range and may be threatened. It is morphologically distinct from other populations and may warrant species status. Further taxonomic investigation and population monitoring is recommended for this subspecies.",Possibly Favourable,"The water shrew has a large range extending from the British Islands eastwards to Lake Baikal, Yenisei River (Russia), Tien Shan (China), and northwest Mongolia. A disjunct range includes Sakhalin Island and adjacent Siberia, Jilin (China), and North Korea. In Europe it is generally widespread throughout, with the exception of southern Iberia. It occurs only sporadically on the Balkan peninsula, where it is largely restricted to the mountains. It occurs from sea level to over 2,500 m (Stone 1995). The distribution of the species recently expanded southwards in Italy owing to a new record in the Sila massif (Aloise et al. 2005).","It is a widespread and abundant species, although local population declines may be caused by wetland drainage, pollution, and destruction of riverbanks. Population densities fluctuate from year to year (Spitzenberger 1999). In the northern part of its range and in the steppe zone, the species has a patchy distribution.","This species is semi-aquatic with water repelling fur. It occurs in a wide variety of wetland habitats, both freshwater and coastal, including lakes, rivers, streams, marshes, bogs, damp grasslands, humid woodlands, sea shores and intertidal wetlands. It is the most aquatic of all European shrews. It hunts on land and in water for invertebrates, including crustaceans, and occasionally takes small fish and amphibia (Sokolov and Orlov 1980, Spitzenberger 1999, Smith and Xie in press). It paralyses large prey with its venomous saliva (Stone 1995, Smith and Xie in press). It is highly territorial, with males only moving out of territory during the breeding season.","Loss of wetland habitats through drainage, development, conversion to agricultural land, and destruction of natural vegetation at the water's edge may have a negative impact on this species. It may suffer from a shortage of food when prey species decline owing to acidification and pollution of water with pesticides, fertilisers, and sewage (Spitzenberger 1999).","It is listed on Appendix III of the Bern Convention, and occurs in numerous protected areas within its range. The western Spanish population is a separate subspecies (niethammeri), which has a very restricted range and may be threatened. It is morphologically distinct from other populations, and may represent a valid species (López-Fuster et al. 1990, Bühler 1996). There is a need for taxonomic research on this population, as well as surveys and monitoring to determine if it is undergoing population decline or range contractions.","Holger Meinig, Sandro Bertolino, Boris Kryštufek, Igor Zagorodnyuk, Giovanni Amori, Heikki Henttonen, Friederike Spitzenberger, Boris Sheftel, Rimvydas Juškaitis" +ANIMALIA,CHORDATA,MAMMALIA,EULIPOTYPHLA,SORICIDAE,Sorex alpinus,,Yes,No,NT,,NT,,"The species has a fairly wide but very fragmented distribution. In the core of the range the population appears to be stable but declines are occurring in some isolated populations at the edges of the range. Overall, there is a slow population decline, but not at a rate high enough to trigger a threatened category. The extent of occurrence and area of occupancy are above the thresholds for Criterion B (>20,000 km² and >2,000 km² respectively), although the area of occupancy may not be much greater than 2,000 km² and there is ongoing habitat loss and degradation. Assessed as Near Threatened as it almost qualifies as threatened under criterion B2.",Unfavourable,"The Alpine shrew is endemic to Europe, where it has a disjunct range in the Alps, the Balkans, the Carpathians, and a number of isolated mountains in Germany, Czech Republic and Poland (Spitzenberger 1999, Meinig 2004). It previously occurred in the Pyrenees, where it is thought to have gone extinct in the early 20th century, and in the Harz (Spitzenberger 1999). Its vertical range is from 200 to 2,500 m (Spitzenberger 1999).","More data are needed to be able to determine population trends. It is widespread but local in the Alps, where populations are thought to be stable. Small, isolated populations at the edge of the species' range may be declining, and there have been subpopulation extinctions (for example in the Pyrenees). In the Harz, the northernmost population in Europe, it appears to have disappeared (last record was in 1954 despite intensive studies to find the species there). It is still present in Germany. Some of the other remaining populations are considered evolutionarily significant units because of their long period of isolation (Meinig 2004).","In the mountains, it tends to be found in open habitats (meadows, rocky areas with sparse vegetation, and banks of mountain streams), where it lives in cracks and crevices under rocks and in stone walls. At lower altitudes, it prefers cool, damp, shaded areas, such as densely-vegetated ravines and holes under mossy rocks, tree-roots and logs in forests (Spitzenberger 1990, 1999). It mainly feeds on arthropods and molluscs (Spitzenberger 1990).","Loss of alpine water courses due to water abstraction and hydroelectric power is also a threat, as is loss of habitat owing to intensification of winter tourism in the Alps. Human land use is a direct threat and climate change may be a future indirect threat as a result of range shifts in other species that may be direct competitors with S. alpinus when ranges overlap.","It is listed on Appendix III of the Bern Convention. A major part of the alpine shrew's range in the Carpathians is covered by the Carpathians Reserve (about 45,000 ha) and National Park (about 70,000 ha). There is a need for monitoring, particularly of isolated subpopulations.","Hutterer, R., Amori, G., Kryštufek, B., Meinig, H., Bertolino, S., Spitzenberger, F. & Zima, J." +ANIMALIA,CHORDATA,MAMMALIA,EULIPOTYPHLA,SORICIDAE,Sorex antinorii,"Formerly known as the Valais chromosome race of the Common Shrew S. araneus (2n = 24/25, FN = 40). Given species rank, diagnosed and reviewed by Brünner et al. (2002). Sorex arunchi may be related, if not conspecific (Hutterer in Wilson and Reeder 2005).",Yes,No,DD,,DD,,"S. antinorii is a poorly known species. Although it has a wide range in Italy, its population size, trend and ecological requirements are not known. It is not abundant. More data are required to be able to assess its status.",Unknown,"The main part of of this species' range occurs in Italy, but it crosses the border into France and Switzerland. It inhabits the southern part of the Alps, the Po lowlands, and the Appenine mountains south to Calabria (Brünner et al. 2002). Further research is required to determine the distribution limits of this species. The northern boundary of its distribution is poorly defined, and in southern parts of its range it is confined to higher altitudes and its distribution is patchy; in general it is more patchily and less extensively distributed than shown on the map.It occurs from the Po plain to at least 1,300 m (Brünner et al. 2002).",There are very poor population data for this species. Population trend is not known.,Occurs in areas with dense vegetation cover.,Pesticides and habitat loss (resulting from agricultural expansion and intensification) are the main threats.,"More research is required on the range, population, threats and habitat requirements of the species.","Hutterer, R., Amori, G. & Kryštufek, B." +ANIMALIA,CHORDATA,MAMMALIA,EULIPOTYPHLA,SORICIDAE,Sorex araneus,This species has huge chromosomal variation and includes many chromosomal races. Recently one of these races has been described as a separate species (S. antinorii)(Wilson and Reeder 2005).,No,No,LC,,LC,,"European regional assessment: Least Concern (LC)EU 25 regional assessment: Least Concern (LC)S. araneus has a very wide range and is one of the commonest shrew species throughout its range. Although general habitat degradation may affect localised populations, this is not considered a serious threat to the global population.",Possibly Favourable,"The common shrew has a wide distribution in the Palaearctic, occurring from Britain through central, northern and eastern Europe and Asia as far east as Lake Baikal and as far north as the Arctic coast. It is widespread throughout, with the exception of arid steppe and desert areas. In Europe, it occurs in most continental areas, with the exception of large parts of Iberia and France, and some parts of Italy and the Balkans. There are isolated populations in the Pyrenees and the Massif Central (France). It is recorded from sea level to 2,500 m (Andĕra 1999).",It is one of the most abundant shrew species.,"It prefers cool, damp and shady habitats with dense vegetation, such as riparian forests and reed beds (Hausser et al. 1990). However, it tolerates a broad range of habitats, and it is present (albeit at lower densities) in drier areas such as woodland, scrub, road verges, hedges in farmland, and even sand dunes (Andĕra 1999). It is absent from very arid habitats. It feeds largely on invertebrates, especially arthropods, earthworms, and snails, but it also feeds on vegetative matter (Hausser et al. 1990).","Threats include general habitat degradation and an indirect threat from pesticides and pollutants (accumulation of toxins through their diet). In some countries, this is an indicator species for monitoring terrestrial pollution. However, the species is not considered seriously affected by these threats at a regional or global level.","It is listed on Appendix III of the Bern Convention, and it occurs in many protected areas. No specific conservation actions are recommended at present.","Holger Meinig, Boris Kryštufek, Boris Sheftel, Igor Zagorodnyuk, Giovanni Amori, Jan Zima, Heikki Henttonen" +ANIMALIA,CHORDATA,MAMMALIA,EULIPOTYPHLA,SORICIDAE,Sorex arunchi,"Possibly related to or conspecific with Sorex antinorii (Brünner et al. 2002), although its karyotype has not been studied yet. Genetically well distinguished from araneus, but morphological differences between both species are weak (Hutterer in Wilson and Reeder 2005). More taxonomic research is needed on this taxon.",Yes,Yes,DD,,DD,,"It is uncertain whether this is a valid species. More taxonomic investigation is required, as well as research on range, population, ecological requirements and threats. This taxon has a restricted extent of occurrence (<20,000 km2), so it may warrant listing in a threatened category when more data become available.",Unknown,"Sorex arunchi is endemic to Europe, where it is found in the Udine province of north-east Italy, and probably adjacent Slovenia (Lapini and Testone 1998).",There are no population data available for S. arunchi.,"It is a lowland taxon, and is found in forested areas.",Pesticides and habitat destruction (agriculture) are likely to be the main threats. Shrews tend to accumulate toxins from pesticides and pollutants through their invertebrate diet (Stone 1995). It may be particularly vulnerable to habitat loss because of its restricted range.,"No conservation measures are known to be in place. More research is needed, particularly taxonomic research.","Hutterer, R., Amori, G. & Kryštufek, B." +ANIMALIA,CHORDATA,MAMMALIA,EULIPOTYPHLA,SORICIDAE,Sorex caecutiens,,No,No,LC,,LC,,"European regional assessment: Least Concern (LC)EU 25 regional assessment: Least Concern (LC)Sorex caecutiens is a widespread and abundant species with a very large global range. Within the EU 25, its range is more restricted and logging activities may affect local populations. However, it is not considered threatened at present.",Possibly Favourable,"The masked shrew is found from Scandinavia in the west (including an isolated population in central Norway), through northern Europe and Asia to the Pacific coast and the islands of Sakhalin and the Kuril archipelago, as well as the Japanese island of Hokkaido (Corbet 1978, Pucek 1999, Frafjord 2002, Finch and van der Kooij 2005). It range extends to the north of the arctic circle, and the southern boundary of its distribution runs from easternmost Poland through Russia, northern Kazakhstan, northern Mongolia and north-east China to the Korean peninsula. In Europe, it is found in Norway, Sweden, Finland, Estonia, Poland, Belarus, and Russia. In northern Finland it occurs from sea level up to 1,000 m, and in central Norway it is found up to 1,600 m (J. van der Kooij in litt. 2006).","It is generally less common than its congener the common shrew, but it is nevertheless a widespread and abundant species (Sulkava 1990). Populations are thought to be stable, with interannual fluctuations that follow no particular cycle (Pucek 1999). In eastern Karelia, where population density has best been studied, tenfold fluctuations have been recorded (Sulkava 1990).","It occurs mainly in coniferous, deciduous and mixed forests in the taiga zone, although it is also found in a range of tundra habitats including birch and willow scrub in river valleys (Pucek 1999, Finch and van der Kooij 2005). In northern Fennoscandia, it tends to be found in shrub-rich mires, alpine birch forests, and open mires, and at the south-western edge of its range in Norway it occurs in alpine habitats (Finch and van der Kooij 2005). In general moist habitats are preferred, such as damp parts of forests with thick moss cover (Pucek 1999). Cultivated land is avoided (Sulkava 1990). The masked shrew feeds on a wide range of insects, spiders, and centipedes (Stone 1995). As it has a lower net food intake than larger shrews such as S. araneus, it can survive in less productive habitats (Finch and van der Kooij 2005).","Extensive logging is a general threat to habitat and may affect local populations. However, at the global scale the population is not considered under serious threat from this.",It is listed on Appendix III of the Bern Convention. It occurs in many protected areas.,"Boris Sheftel, Heikki Henttonen" +ANIMALIA,CHORDATA,MAMMALIA,EULIPOTYPHLA,SORICIDAE,Sorex coronatus,,Yes,No,LC,,LC,,A widespread and abundant species with no serious threats affecting the global population at present. Assessed as Least Concern.,Possibly Favourable,"Sorex coronatus is endemic to Europe, where it occurs from northern Spain, through France and the Low Countries, to northern Switzerland, Germany, and the westernmost corner of Austria. It is also found on the island of Jersey (United Kingdom) (Hausser 1999). Its vertical range is from 0 to 2,200 m (Palomo and Gisbert 2002).","It is generally widespread and abundant. However, at the edge of its range in Switzerland intensive agriculture and pesticide use have caused the species to decline, such that now only relict populations remain in some areas (Palomo and Gisbert 2002).","It inhabits a variety of habitats with dense vegetation at ground level, including woods, hedges, abandoned or unmown meadows, and marshes. It is scarce in intensively cultivated areas, and tends not to occur near to human habitation. It competes with Sorex araneus, and the microhabitats used are different for each species where their ranges overlap (Hausser 1990, 1999).","Threats include general habitat degradation and the indirect effects of pesticides and pollutants (accumulation of toxins through the species' diet) (Stone 1995, Palomo and Gisbert 2002). However, the species is not considered seriously affected by these threats at the global level.","It is listed on Appendix III of the Bern Convention, and occurs in protected areas within its range.","Aulagnier, S., Hutterer, R., Amori, G. & Kryštufek, B." +ANIMALIA,CHORDATA,MAMMALIA,EULIPOTYPHLA,SORICIDAE,Sorex granarius,,Yes,Yes,LC,,LC,,"Population size in this species has not been quantified, but it is not believed to approach the thresholds for the population size criterion of the IUCN Red List (i.e. less than 10,000 mature individuals in conjunction with appropriate decline rates and subpopulation qualifiers), as the species is commonly found in owl pellets in at least parts of its range. The extent of occurrence is fairly large, but the area of occupancy is not known, and it may not be safe to assume that it is much larger than 2,000 km2. In Spain the population is stable and it is likely to be stable also in Portugal. No serious threats at present. Least Concern.",Unknown,"It is endemic to the Iberian Peninsula, where it is found in northern Portugal (north of the Tagus River) and central Spain (García-Perea et al. 1997). It occurs from the coast up to 2,000 m (Palomo and Gisbert 2002).","Population size and trends have not been quantified. However, the species is quite common in the diet of nocturnal raptor species (Cabral et al. 2005). In Spain the population is stable and it is likely to be stable also in Portugal (Muñoz, L.J.P. pers. comm. 2007).","It is found in Atlantic climate areas, where it inhabits a variety of woodland and scrub habitats, including native beech, oak, and pine forests, plantations of introduced Eucalyptus and Pinus pinaster, and damp areas with dense shrubby vegetation. It is also found in cultivated fields, stream- and river-banks, scree slopes, and rocky areas near to pastures. It prefers humid locations, and is restricted to areas where the annual rainfall exceeds 600 mm (García-Perea et al. 1997, Hausser 1999, Palomo and Gisbert 2002, Cabral et al. 2005).","It is not considered threatened in Spain, although its population status is not known (Palomo and Gisbert 2002). In Portugal, it may be locally threatened by habitat destruction and pesticide use, as well as reductions in the abundance of its invertebrate prey (Cabral et al. 2005).",It is listed on Appendix III of the Bern Convention. It occurs in protected areas within its range. Research is needed to evaluate its population status and trends (Cabral et al. 2005).,"Palomo, L.J., Amori, G. & Hutterer, R." +ANIMALIA,CHORDATA,MAMMALIA,EULIPOTYPHLA,SORICIDAE,Sorex isodon,,No,No,LC,,LC,,"European regional assessment: Least Concern (LC)EU 25 regional assessment: Least Concern (LC)Globally and within Europe as a whole this species has a wide range, but it is a habitat specialist and its distribution is patchy. Habitat loss and degradation is ongoing but is not a serious threat to the species at present. In the EU 25, it is largely restricted to Finland, with some isolated populations in Sweden. The range is fragmented and habitat loss is a concern for local populations. The species needs to be monitored in western Europe at least, but is currently not believed to approach the IUCN Red List thresholds. It is consequently classed as Least Concern at both the EU 25 and European regional level.",Unknown,"The taiga shrew's range extends from Fennoscandia in the west, through northern and central Russia, north Mongolia and northern China, and northern Kazakstan, to the Pacific coast and Sakhalin island. In Europe, it is more or less continuously distributed from Finland to northern Russia and northern Belarus (Corbet 1978, Sulkava 1999). Populations in Norway and Sweden may be isolated. It is a habitat specialist, and consequently has a patchy distribution. The species was not detected in Fennoscandia until as late as 1949 (Sulkava 1999).","It is rare and local. In north-west Europe and north-western Siberia, captures of this species generally form less than 1% of all Sorex captures with snap traps and pitfall traps (Sulkava 1999). It is a patchily distibuted species and little is known about population trends.","It is a habitat specialist, preferring small brook sides with dense vegetation (e.g. ferns) within mature spruce and mixed boreal forests. It is also sometimes found in scrub and fallow fields, so long as there is damp, dense vegetation at ground level and a deep soil layer (Sulkava 1999). It feeds mainly on invertebrates, particularly earthworms and dipteran larvae, although plant material is very occasionally taken (Sulkava 1990).",Preferred habitats are being altered by forestry and drainage (Sulkava 1999). Globally this is not considered to be a serious threat at present.,"It is listed on Appendix III of the Bern Convention, and occurs in many protected areas. Population trends and habitat status require monitoring in the western European part of its range, and particular attention should be paid to isolated populations in Scandinavia.","Boris Sheftel, Heikki Henttonen" +ANIMALIA,CHORDATA,MAMMALIA,EULIPOTYPHLA,SORICIDAE,Sorex minutissimus,,No,No,LC,,LC,,"European regional assessment: Least Concern (LC)EU 25 regional assessment: Least Concern (LC)This species has a large range, within which it is widespread. It is rare and also very difficult to catch through normal trapping methods. The population size has not been quantified, but it is not believed to approach the thresholds for the population size criterion of the IUCN Red List (i.e. less than 10,000 mature individuals in conjunction with appropriate decline rates and subpopulation qualifiers). Although the population trend is not known, there are no major threats, and it is not believed to approach the thresholds for the population decline criterion of the IUCN Red List (i.e. declining more than 30% in ten years or three generations). For these reasons, it is evaluated as Least Concern.",Unknown,"The least shrew occurs from Fennoscandia through European Russia and Siberia to the Pacific coast and the islands of Hokkaido and Sakhalin (Corbet 1978, Sulkava 1999). In Europe, it occurs more or less continuously from northern Scandinavia through most of Finland to central and northern Russia. There are a small number of records from central Scandinavia (Grüner 1998, Sulkava 1999, Vaernesbranden and Larsen 2004), but this tiny and elusive shrew may be more widespread in central Scandinavia than the paucity of records would appear to suggest (Sulkava 1999). In Fennoscandia it occurs from sea level to above the tree line (0-1,600 m: J. van der Kooij in litt. 2006).","Trapping results suggest that it occurs at much lower densities than other sympatric Sorex species (although reliable population density estimates are hard to obtain because of difficulties in trapping this species)(Sulkava 1990, 1999). The long-term population trend appears to be stable (Sulkava 1999).","This is a very small species (possibly the smallest terrestrial mammal species, although the pygmy white-toothed shrew Suncus etruscus may be slightly smaller) and it is very difficult to catch, other than by pitfall traps. It occurs from the forest tundra zone in the north, through boreal coniferous forests to mixed forests and forest steppe at the southern limit of its range. Within these zones it prefers moist spruce-dominated woodland with thick moss, but it is also commonly found in bogs and mires, and even in dry pine forests and clear-felled areas (Sulkava 1990, 1999). It feeds on small insects, grubs, spiders and snails, consuming as much as 2-5 times its body weight over a 24 hour period (Sulkava 1990, Macdonald and Barrett 1993).",No major threats are known. Clear-cutting does not appear to have a negative impact on population densities (Sulkava 1999).,"It is listed on Appendix III of the Bern Convention, and occurs in a number of protected areas.","Heikki Henttonen, Boris Sheftel" +ANIMALIA,CHORDATA,MAMMALIA,EULIPOTYPHLA,SORICIDAE,Sorex minutus,,No,No,LC,,LC,,"European regional assessment: Least Concern (LC)EU 25 regional assessment: Least Concern (LC)This species is very widespread and common. Although habitat destruction is a general threat, it is not a serious threat to the species at present. Consequently, Sorex minutus qualifies as Least Concern.",Possibly Favourable,"It occurs from the British Isles and Iberia through much of continental Europe, European Russia and Siberia to Lake Baikal in the east. The northernmost limit of its range extends beyond the arctic circle. In Portugal the distribution is discontinuous in some regions north of the Tagus river (Cabral et al. 2005). It occurs from sea level to 2,000 m in the Pyrenees (Palomo and Gisbert 2002) and 2,260 m in the Alps (Spitzenberger 2002).","It is a common species in suitable habitats throughout its range, and it may even be the dominant shrew species in swampy areas (Hutterer 1999).","It tends to be found in relatively damp areas with dense vegetation at ground level, and it occurs in a wide variety of habitats including swamps, grasslands, heaths, sand dunes, woodland edge, rocky areas, shrubland, and montane forests. It feeds on invertebrates (Hutterer 1990, 1999).","It suffers from destruction of habitat, use of pesticides and declining invertebrates. However, these are not considered to be major threats to the global or European regional persistence of the species at present. The apparent geographic isolation of some Iberian populations may make local extinctions more likely (Palomo and Gisbert 2002).","It is listed on Appendix III of the Bern Convention. It occurs in a number of protected areas throughout its wide range. Studies of its ecology and distibution are required in Portugal (Cabral et al. 2005), and isolated Iberian populations should be monitored.","Holger Meinig, Boris Kryštufek, Margarida Fernandes" +ANIMALIA,CHORDATA,MAMMALIA,EULIPOTYPHLA,SORICIDAE,Sorex samniticus,"Formerly included in S. araneus, but now recognised as a distinct species (Hutterer in Wilson and Reeder 2005).",Yes,Yes,LC,,LC,,"This species has a relatively large range, within which it is widespread. Population size has not been quantified, but it is not believed to approach the thresholds for the population size criterion of the IUCN Red List (i.e. less than 10,000 mature individuals in conjunction with appropriate decline rates and subpopulation qualifiers). Population trend has not been quantified, but it is not believed to approach the threshold for the population decline criterion of the IUCN Red List (i.e. declining more than 30% in ten years or three generations), as no major threats to the species are known. For these reasons, it is evaluated as Least Concern.",Unknown,"The Appenine shrew is endemic to the Italian peninsula. It is recorded from the Appenines to Calabria, at altitudes between 300 m and 1,160 m, but its exact distribution is poorly known (Hausser 1990, 1999, Amori and Aloise 2005).","It is not abundant, but it is quite widespread (G. Amori pers. comm. 2006). There are no data on population trend.","A poorly known species. It occurs in shrubland habitat within forested areas (G. Amori pers. comm. 2006), but avoids densely forested areas (Mortelliti et al. 2007). Hausser (1990) describes it as being found near streams, in bogs, and in hedgerows and stone walls in damp areas.",Pesticides and habitat destruction (through agriculture and urbanisation) are considered to be the main threats (G. Amori pers. comm. 2006).,"It is listed on Appendix III of the Bern Convention. It occurs in protected areas in parts of the range. Research is required on its distribution, population status, and trends.","Amori, G." +ANIMALIA,CHORDATA,MAMMALIA,EULIPOTYPHLA,SORICIDAE,Sorex tundrensis,,No,No,LC,,NE,,"European regional assessment: Least Concern (LC)EU 25 regional assessment: Not Evaluated (NE)This species is widespread and abundant and abundant, with no major threats. Considered Least Concern.",-,"Distributed in tundra and forest zones from west of the Urals (Russia) to Alaska (USA); Yukon, Northwest Territories (Canada); south to the Altai Mtns (Russia), Mongolia and NE China. Also occurs along water courses in steppe zones. In Europe found along the European slope of the Ural mountains and the valley of the Ural river and along the Pechora river.",A widespread and very abundant species. The most common species of small mammal found along Siberian rivers.,"Prefers river meadows with osier, settles in fire-sites and overgrown glades. Along rivers penetrates to semi-deserts. Solitary, the size of individual space is up to 1,500 m2. Feeds mainly on beetles. Reproduction is usually in summer, gives 3-4 litters per year; litter size is about 7-10 young.",There are no major threats to the species.,No special conservation measures known or required.,"Katerina Tsytsulina, Nikolai Formozov, Boris Sheftel" +ANIMALIA,CHORDATA,MAMMALIA,EULIPOTYPHLA,SORICIDAE,Suncus etruscus,,No,No,LC,,LC,,European regional assessment: Least Concern (LC)EU 25 regional assessment: Least Concern (LC)This species is widespread within its range. No serious threats are known. Consequently it qualifies as Least Concern.,Unknown,"Suncus etruscus ocurs from southern Europe and North Africa (Morocco, Algeria, Tunisia, Libya, Egypt) through the Arabian Peninsula and Asia Minor to Iraq, Turkmenistan, Afghanistan, Pakistan, India, Nepal, Bhutan, Burma, Thailand, Laos, Vietnam and Yunnan (China). Records from southern India and Sri Lanka probably refer to another species (Libois and Fons 1999). West and East African records (Guinea, Nigeria, Ethiopia) are doubtful and need confirmation (Wilson and Reeder 2005). In Europe, it is confined to the Mediterranean climate zone, occurring on the Iberian, Italian, and Balkan peninsulas as well as on a number of Mediterannean islands. There is an established introduced population in the Canary Islands (Tenerife). It occurs from sea level to altitudes of over 1,000 m (Libois and Fons 1999, Palomo and Gisbert 2002).","It tends to be less common than other shrews living in same area, as indicated by both trapping experiments and analyses of owl pellets (Libois and Fons 1999). Trapping is not so effective for catching this species because the shrew is too small (less than 2g); it is often more commonly seen in owl pellets (V. Vohralík pers. comm. 2006).","It prefers abandoned olive groves, vinyards, and other cultivated areas overrun by mediterranean shrubs, but occurs also in gardens, low maquis, scrub, and open forest of Mediterranean oaks and pines, provided that old dry stone walls are available as shelters. It avoids sand dunes, dense forests, and intensively cultivated land (Libois and Fons 1999, Palomo and Gisbert 2002). It is more active during night than day, with a peak at dawn. It experiences daily variations of weight, hypothermy, and torpor, as regulatory mechanisms of the high energetic consumption associated with activity. Possibly the smallest terrestrial mammal, its head and body measures 35-50 mm in length (Stone 1995) .","It is sensitive to insecticides and pesticides, but these are not thought to pose a major threat to the survival of the species at present.","It is present in some protected areas (e.g. Donana and Nestos delta), and is listed on Appendix III of the Bern Convention.","Vladimir Vohralík, Boris Kryštufek" +ANIMALIA,CHORDATA,MAMMALIA,EULIPOTYPHLA,TALPIDAE,Desmana moschata,The only species of its genus.,No,No,VU,A2bc+4bc,NE,,"European regional assessment: Vulnerable (VU)EU 25 regional assessment: Not Evaluated (NE)A rare species with a fragmented distribution. Population size, area of occupancy, and habitat quality are all declining, and the species faces a number of serious threats including bycatch, habitat loss and degradation, water pollution, and competition from introduced species. Surveys in Russia indicate that the population declined from 39,000 in 1985 to 27,000 in 2000/2001, and it is suspected that rates of decline have increased since then. The desman recently went extinct in Belarus. Overall, it is suspected that declines exceed 30% over a ten-year period in the past or future, so the species is classed as Vulnerable.",-,"This species occurs in Russia, Ukraine and Kazakhstan; it has recently disappeared from Belarus. At the beginning of the 20th century the desman was common in the Dnepr, Don, Volga and Ural rivers basins. Its current range is very fragmented, and it has disappeared form many areas where it formerly occurred. At the end of the 19th century it disappeared from Ukraine, but was reintroduced in the 1950s. In the 1990s it was found again in the Desna (a tributary of the Dnepr, Ukraine).","At the beginning of the 1970s in the Soviet Union there were about 70,000 individuals, of which the majority occurred in Russia, with about 1,500 individuals in Kazahstan and single records in Ukraine and Belarus. More recent surveys in the Russian Federation indicate that the population there declined from 39,000 in 1985 to 27,000 in 2000/2001, and it is suspected that rates of decline have increased since then owing to growing threats from fisheries bycatch. The 2000/2001 survey covered around 30,000 km of the banks of rivers, lakes and artificial reservoirs, and a uniform methodology was used (see the Biodiversity Conservation Centre website http://www.biodiversity.ru/eng/programs/desman/results.html for further details). In Ukraine the desman is currently very rare and in Belarus it has recently been extirpated.","A riparian species, it is found in holes primarily along oxbow lakes, less frequently by rivers and ponds. It does not inhabit all water bodies within its range; it has quite strict habitat requirements and prefers water bodies with rich water-marsh vegetation, bushes and primary forests along the banks. Prefers lakes with 1-2 m depth with rich invertebrate fauna. Also found in small rivers with slow flow. In favourable years it is able to reproduce during the whole year, but usually has two reproduction peaks at the end of spring and autumn. Males participate in care of young. Omnivorous, recorded feeding on at least 72 species of water invertebrates and 30 plant species, as well as fish and amphibians.","The main threat to the Russian desman at present is the widespread use of fixed fishing nets. These nets, which are used by poachers, have become increasingly cheap and widely available in recent years: a recent study recorded 50 'outlets' freely selling these nets on the Moscow-Vladimir section of the Nizhny Novgorod highway alone (http://www.biodiversity.ru/eng/programs/desman/results.html). The very low price and high durability of modern nets means that poachers often leave them in the water for days or even months, checking them only occasionally and often abandoning them. A desman dies on average within 5-10 minutes when trapped in a net. The second most important threat is the use of 'electric landing nets' (or electric rods), which use an electric current to stun fish. These items of equipment, also used by poachers, have become widespread over the last 10-15 years. They are not believed to directly harm desmans, as a general rule, but they almost totally wipe out the fish and aquatic invertebrates that the desman depends upon. A third major threat is habitat loss and degradation. During the second half of the twentieth century water pollution, creation of impoundments, drainage, clearance of riparian vegetation, and uncontrolled agricultural exploitation of flood plains became widespread and contributed to the decline in the species' population. However, this process has abated somewhat in the last decade, and its influence on the decline in the Russian desman population is today secondary. Competition for breeding sites with introduced nutria (Myocastor coypus) and muskrats (Ondatra zibethicus) may also be a threat.","The desman is listed in the Russian Red Data Book (under category 2: declining in number rare relict species). It is protected in the buffer zone of Okskiy, Voronezhskiy, Kaluzhskie Zaseki Zapovednik, and Ugra National Parks and several small protected areas. This species has been the subject of re-introductions attempts. Recently, conservationists tried to reintroduce it to the Desna basin, in the area of Bryanskiy Les Zapodnenik. The Biodiversity Conservation Centre has started a public campaign against nylon nets and electro-fishing. Conservation measures recommended to stabilize and improve the condition of the Russian desman throughout its range include the following:· Banning the unrestricted sale of nets and net-making materials;· Developing a system of measures to combat electric landing nets; and· Setting up specialized hunting reserves in the desman's key areas of habitation.","Katerina Tsytsulina, Nikolai Formozov, Boris Sheftel, Igor Zagorodnyuk" +ANIMALIA,CHORDATA,MAMMALIA,EULIPOTYPHLA,TALPIDAE,Galemys pyrenaicus,,Yes,Yes,VU,A2ac+3c+4ac,NT,,"Listed as Vulnerable because the species is undergoing declines across its whole range. Declines appear to be the highest in Spain, but are lower in France (where the population marginally occurs) and Portugal. An overall decline of 30% over the last ten years is plausible, and given the ongoing threats to this species it is realistic to expect a further decline of at least 30% over the next ten years.",Unfavourable,"The Pyrenean desman is restricted to the Pyrenees mountains (Andorra, France and Spain), as well as parts of northern and central Spain and northern Portugal. In France it occurs along the Aude, Agly, Salat, Aspe, Ossau, Ariège, Ardour, Tet and Tech rivers. In Portugal it occurs along the Minho, Ancora, Lima, Neiva, Cavado, Ave, Leca, Douro, Vouga, Mondego, and Tejo rivers (Queiroz et al. 1998) In Spain it is found in the upper reaches of rivers in the Pyrenees, the Cantabrian mountains, the Sistema Central, the Picos de Europa and along the Deva River. It also occurs in the Sierra de Guarra north of Huesca and Infiesta, Oviedo, and Burguete, Navarro (J. Herrero pers. comm. 2006). It is found at altitudes between sea level and 2,500 m (Palomo and Gisbert 2002). In Spain, the river systems that the species occurs in flow to three different seas: Mediterranean, Atlantic and Cantabrian; hence the populations are all separated from each other.","The population has declined in recent years, but it is hard to obtain precise estimates of population size and decline rate for this shy and secretive species (González-Esteban et al. 2003). The desman has been radio-tracked in Portugal following successful capture of animals using underwater traps (care is required to check these traps regularly to prevent drownings: M. Fernandes pers. comm. 2006). In favourable habitats population densities may be 5-10 individuals per kilometre, but other studies indicate much lower densities (Quaresma et al. 1998, Chora 2001, Cabral et al. 2005). In Portugal it is estimated that there are less than 10,000 mature individuals divided into small and isolated subpopulations due to the existence of physical (e.g. dams) and ecological barriers (Cabral et al. 2005). In Spain the species has undergone marked declines in the central system (J. Herrero pers. comm. 2006), and the desman has disappeared from some sites where it was previously known (Palomo and Gisbert 2002). In the Spanish Pyrenees and Cantabrian regions densities range from 2.8 to 7.3 animals per km of river (Palomo and Gisbert 2002); however, in the Sistema Central population densities are lower (P. García pers. comm. 2007). In France the population is also declining (S. Aulagnier pers. comm. 2006). As well as population declines, range contractions have been observed along the western, southern, and eastern edges of the desman's range in Portugal (Cabral et al. 2005).","The desman's preferred habitat is fast flowing mountain streams, although it is occasionally found in slow moving water bodies such as canals, lakes and marshes. It favours perennial rivers where the margins offer some shelter, and it requires clean and well oxygenated water. G. pyrenaicus is specialised to an aquatic environment. It feeds nocturnally on a diverse array of crustaceans and insect larvae, including stoneflies and caddis fly larvae (Queiroz 1999, Palomo and Gisbert 2002, Cabral et al. 2005).","This species is confined to a very vulnerable habitat in a restricted area. The most potent threats are from water pollution, and habitat fragmentation caused by the construction of hydro-electric plants, water extraction, and dam and reservoir construction (Queiroz 1999, Palomo and Gisbert 2002, Cabral et al. 2005). Other threats are direct persecution from fishermen who incorrectly believe this species to be a threat to fish stocks, especially trout, or from over-eager collectors. Poison and explosives are used as fishing methods in Portugal, which would kill the desman (Cabral et al. 2005). The escape of North American mink (Neovison vison) from fur farms in northern Iberia might be negatively impacting populations in Galicia. It is predated by otters in Galicia (forming up to 5% of their diet) (Palomo and Gisbert 2002).Climate change is anticipated to be a serious threat to the desman in the near future. The species tends to occur only in areas with annual rainfall superior to 1,000 mm and, given climate change scenarios for Spain, by 2060 the species may be virtually extinct from central Spain and also in most of its important areas from northern Iberia (P. García pers. comm. 2007).","It is strictly protected under the Bern Convention (Appendix II) and the EU Habitats and Species Directive (Annexes II and IV). Part of the range falls within the Parc National des Pyrénées Occidentales and Parque Nacional de Covadona, and possibly the Parque Nacional de Aiguas y Lago de San Mauricio and the Parque Nacional de Ordesa. This species' conservation has been the topic of an international conference that has drawn up an action plan that includes priority actions. There is also an action plan for the species in Portugal. Actions proposed include appropriate management of water courses, habitat restoration, improvement of knowledge of the threatened populations, and use of the desman as a flagship species to promote river conservation (Cabral et al. 2005). In Spain the species is considered Vulnerable because populations have disappeared from the formerly known range (L.J.P. Muñoz pers. comm. 2007).","Fernandes, M., Herrero, J., Aulagnier, S. & Amori, G." +ANIMALIA,CHORDATA,MAMMALIA,EULIPOTYPHLA,TALPIDAE,Talpa caeca,,Yes,No,LC,,LC,,"The species has a relatively wide range, is common in at least some areas, and is not believed to be facing any major threat. Hence it is listed as Least Concern.",Unknown,"Talpa caeca is endemic to Europe, where it is found in the western Alps, the Apennines, and the Balkan peninsula. It is likely to occur in Albania. Records from the Carpathians (Romania) require confirmation. Small blind moles recently found in Turkish Thrace and southern Bulgaria have been ascribed to T. levantis, but the possibility that they are in fact T. caeca merits further investigation. The species occurs from sea level to 2,000 m, although it is found more often above 1,000 m (Kryštufek 1999).","Its population status is unknown across the whole range, but it is common in the mountainous areas of Italy (G. Amori pers. comm.). It is possible that it is locally common across its whole range. Its distribution is sporadic in karst limestone areas (Kryštufek 1999).","It occurs in deciduous woodland, meadows and pastures in hilly or mountainous areas. It requires deep soil that is not too dry, which explains it sporadic distribution in karstic areas. Its diet is probably similar to that of the common mole T. europea, which feeds on soil-dwelling invertebrates, especially earthworms. It tends to be competitively displaced into marginal habitats by the larger T. europea in areas such as the Balkans (Kryštufek 1999). In Italy it is similarly displaced by Talpa romana where the two species occur in sympatry (G. Amori pers. comm. 2006).",No major threats are known.,It is not protected under international legislation. It occurs in protected areas across its range. In Italy it is not protected.,"Amori, G., Hutterer, R., Bertolino, S., Mitsain, G., Yigit, N., Kryštufek, B. & Palomo, L.J." +ANIMALIA,CHORDATA,MAMMALIA,EULIPOTYPHLA,TALPIDAE,Talpa europaea,,No,No,LC,,LC,,"European regional assessment: Least Concern (LC)EU 25 regional assessment: Least Concern (LC)This species is widespread and abundant, with no serious threats at present. Consequently it is classed as Least Concern.",Possibly Favourable,"The European mole occurs from Britain and Spain eastwards through much of continental Europe to the rivers Ob and Irtysh in Asian Russia (Corbet 1978, Kryštufek 1999, Wilson and Reeder 2005). In Europe, it is generally widespread, although absent from southern Iberia, southern Italy, the southern Balkans (where it is replaced by other Talpa species); and northern Fennoscandia and European Russia. It is found on many islands in the Baltic and around the British coast, but it is not found on Ireland, Iceland, the North Sea islands, and the Mediterranean islands (with the exception of Cres in the northern Adriatic). It is found from sea level to 2,400 m (Kryštufek 1999).","It is generally common in appropriate habitats, with densities of up to 16 individuals per hectare recorded (Kryštufek 1999). It is sufficiently common to be considered a pest of farmland and lawns in many parts of its range.","It is present in most habitats where there is sufficiently deep soil to permit the construction of its extensive burrows. It prefers meadows, pastures, arable land, gardens and parks, and is rarely found in coniferous forests, or habitats with sandy, stony or permanently waterlogged soils (Kryštufek 1999). It feeds mainly on earthworms, as well as other soil invertebrates (Niethammer 1990).","It is widely persecuted as a pest, but although this may cause local population declines it is not a serious threat to the species. In the past, it was hunted in great numbers for its fur, but this no longer occurs.",It occurs in protected areas within its range. No specific conservation measures are recommended.,"Vladimir Vohralík, Jan Zima, Boris Kryštufek, Boris Sheftel, Holger Meinig, Nikolai Formozov" +ANIMALIA,CHORDATA,MAMMALIA,EULIPOTYPHLA,TALPIDAE,Talpa levantis,,No,No,LC,,NE,,"European regional assessment: Least Concern (LC)EU 25 regional assessment: Not Evaluated (NE)The species has a relatively large global range, within which it is widespread and facing no major threats. Although its Extent of Occurrence within the European region is fairly small (approaching 20,000 km2), there is no evidence of population declines or range contractions, and no serious threats are known. Consequently it is classed as Least Concern.",-,"Talpa levantis is found along the southern edge of the Black Sea, from southeastern Bulgaria through Turkey to the Caucasus region (Corbet 1978, Wilson and Reeder 2005). It is found from sea level to at least 2,000 m, possibly higher in the Caucasus (B. Kryštufek and V. Vohralík pers. comm. 2006).",No information is available.,It inhabits various biotopes from the lowland to the mountains. In its European range it is found in meadows and deciduous forests. Only a few specimens have been collected in the European part of the range through trapping. The majority of records are based on anlyses of raptor and owl pellets. In the eastern parts of its range (the Caucasus) it also occurs in alpine meadows (B. Kryštufek and V. Vohralík pers. comm. 2006).,No major threats.,It probably occurs in protected areas in the Caucasus.,"Vladimir Vohralík, Boris Kryštufek" +ANIMALIA,CHORDATA,MAMMALIA,EULIPOTYPHLA,TALPIDAE,Talpa occidentalis,,Yes,Yes,LC,,LC,,A common species in the Iberian Peninsula and under no major threats. Hence listed as Least Concern.,Possibly Favourable,"The Iberian mole is endemic to Portugal and Spain (Foy 1999). It occurs from the coast to 2,300 m (Palomo and Gisbert 2002).","It is common in suitable habitats throughout its range (Loy 1999). However, in the southern part of its range it is confined to mountainous areas (Palomo and Gisbert 2002). In Portugal it may be considered a single subpopulation or three separate subpopulations if the rivers are shown to be major barriers to dispersal (M. Fernandes pers. comm. 2006).","It is a burrowing species, and like its congener the European mole T. europaea it is found in a variety of habitats so long as there is deep soil that is not excessively stony, sandy, or waterlogged. It is often found in meadows and pastures. In southern parts of its range it is restricted to upland areas (Loy 1999, Palomo and Gisbert 2002). It feeds on invertebrates, especially earthworms (Niethammer 1990).","It is a pest species causing damage to pastures, so it is persecuted by farmers. Loss of meadows to afforestation is probably the main threat to the species, but this is not thought to be a severe threat at present (Palomo and Gisbert 2002).",It occurs in a number of protected areas. No further actions are required.,"Fernandes, M. & Herrero, J." +ANIMALIA,CHORDATA,MAMMALIA,EULIPOTYPHLA,TALPIDAE,Talpa romana,,Yes,Yes,LC,,LC,,"T. romana is widespread in central and southern Italy. The population size has not been quantified, but it is not believed to approach the thresholds for the population size criterion of the IUCN Red List (i.e. less than 10,000 mature individuals in conjunction with appropriate decline rates and subpopulation qualifiers). Although intensive arable farming may be a problem in some areas, the population trend is thought to be stable, and is not believed to approach the thresholds for the population decline criterion of the IUCN Red List (i.e. declining more than 30% in ten years or three generations). For these reasons, it is evaluated as Least Concern.",Possibly Favourable,"The Roman mole is endemic to Italy. It is now confined to the mainland, having last been recorded on Sicily in 1885 (Loy 1999). Reports of an isolated subpopulation in the Var region of southern France (Saint Girons 1973 in Niethammer 1990) have not been confirmed (Niethammer 1990, Loy 1999, Wilson and Reeder 2005). It is found from sea level to about 2,000 m (Loy 1999).",It is widespread throughout its range (Loy 1999). No information is available on abundance although it is assumed to be stable (G. Amori pers. comm. 2006).,"Its ecology is similar to that of the European mole T. europaea. It is found in a variety of habitats including arable fields, pastures, and woods, and it feeds predominantly on earthworms (Niethammer 1990, Loy 1999).","Local population declines are suspected in areas where there is intensive arable farming (Loy 1999). The mole is widely persecuted as a pest. However, these are not thought to be major threats at present.",It is not protected under national or international law. No specific conservation measures are known. Occurs in protected areas within its range.,"Amori, G." +ANIMALIA,CHORDATA,MAMMALIA,EULIPOTYPHLA,TALPIDAE,Talpa stankovici,,Yes,No,LC,,LC,,"Although this species is relatively localized and quite poorly known, no major threats are known, and it is listed as Least Concern. The population size has not been quantified, but it is not believed to approach the thresholds for the population size criterion of the IUCN Red List (i.e. less than 10,000 mature individuals in conjunction with appropriate decline rates and subpopulation qualifiers). The population trend is not known, but it is not believed to approach the thresholds for the population decline criterion of the IUCN Red List (i.e. declining more than 30% in ten years or three generations).",Unknown,"The Balkan mole is endemic to the Balkans, where it is found in southern Montenegro, western Macedonia, north-eastern Greece, and the island of Corfu. It is likely to occur in Albania. Its vertical range is from sea level to 2,300 m (Kryštufek 1999).","Its population status is not known, but it may be locally abundant (Kryštufek 1999).","It occurs in a variety of open habitats including sandy beaches, pastures and arable land (Kryštufek 1999).",No major threats.,It receives no protection under European legislation. It occurs in some protected areas in northern Greece (for example the Pelister mountains). No further actions are required at present.,"Vohralík, V. & Kryštufek, B." +ANIMALIA,CHORDATA,MAMMALIA,LAGOMORPHA,LEPORIDAE,Lepus capensis,"Lepus capensis, once thought to be conspecific with L. europaeus, is now generally treated as a separate species (Flux and Angermann 1990, Boitani et al. 1999, Kryger et al. 2004). The taxonomy of this species is unclear, and further research may result in this taxon being split into several species. A taxonomic review based on genetic studies is urgently required, otherwise it is possible that some species may go extinct before they are formally identified. A number of publications indicate that the range of L. capensis extends into China, Mongolia and Russia; however, current taxonomic classification suggests L. tibetanus and L. tolai are valid species (Wilson and Reeder 2005).",No,No,LC,,LC,,"European regional assessment: Least Concern (LC)EU 25 regional assessment: Least Concern (LC)The species is Least Concern in Europe. Although some declines in the Sardinian population have been noted, they are not thought to be of sufficient magnitude to warrant a Near Threatened listing. However, population trends should be monitored.",Possibly Unfavourable,"Lepus capensis has a large global range in Africa and the Near East, where it occurs in two separate non-forested areas; the first in the region bounded by southern Angola, Mozambique and South Africa, and the second extending across North Africa, the Sahara and the Sahel to East Africa, the Arabian peninsula, Syria and Iraq. In Europe, it is found only on the island of Sardinia (Italy), where it occurs as a distinct subspecies L. capensis mediterraneus and is found throughout the island. This population is considered to have been introduced by humans in prehistoric or early historic times (Gippoliti and Amori 2004, G. Amori pers. comm. 2006). It has been recorded from sea level to 4,000 m in Africa (Angelici 1999).","The Sardinian population is suspected to be suffering ongoing decline, even though it is considered locally common in at least parts of its range (Angelici 1999).","Globally, it occupies a variety of open habitats including desert, semi-desert, grassland and steppe. On Sardinia, it is found in almost all habitats on the island, but prefers cultivated land and maquis (Spagnesi and de Marinis 2002).","In Italy the Sardinian hare is considered a game species, and hunting and poaching may have contributed to population declines. Predation by feral dogs is also a potential threat, and anthropogenic bush fires may cause local population declines (Spagnesi and de Marinis 2002). However, these are not thought to be serious threats to the survival of this species on Sardinia.","It is listed under Appendix III of the Bern Convention. Captive breeding has been carried out in order to maintain the numbers available for shooting. Recommended measures include better regulation of hunting, and measures to control and limit the number of bush fires.",Giovanni Amori +ANIMALIA,CHORDATA,MAMMALIA,LAGOMORPHA,LEPORIDAE,Lepus castroviejoi,"Past concerns regarding taxonomic status have been resolved with recent genetic evidence that support the classification of Lepus castroviejoi as one of two endemic species of Lepus inhabiting the Iberian Peninsula (Alves et al. 2003, Melo-Ferreira et al. 2005). Recent molecular data suggest that L. castroviejoi is a sister taxa to L. corsicanus (Alves et al. 2002).There are no subspecies recognized for Lepus castroviejoi (Flux and Angermann 1990, Hoffmann and Smith 2005).",Yes,No,VU,B1ab(iii)+2ab(iii),VU,"B1ab(iii,v)","Lepus castroviejoi is restricted to a relatively small geographic range of approximately 5,000 km². (Ballesteros 2003). This species is considered fragmented, as it occupies highly specialized patches of scarce habitat (Ballesteros in press). These fragmented populations form a dispersed metapopulation within a matrix of unsuitable habitat (Ballesteros in press). Population declines have been observed along the northern portion of its range and in the marginal habitat in which it occurs (Ballesteros et al. 1996).",Unfavourable,"The distribution of L. castroviejoi is limited to the Cantabrian Mountains in the northwest of Spain (Flux and Angermann 1990). It occupies elevations of 1,000 to 1,900 m between Sierra de los Ancares and Sierra de Pena Labra (Flux and Angermann 1990, Ballesteros 2003). The total distribution is approximately 25 - 40 km from north to south, 230 km east to west (Flux and Angermann 1990). It is estimated that the extent of occurrence is 5,000 km² (Ballesteros 2003). This species is considered fragmented, as it occupies highly specialized patches of habitat that is scarce (Ballesteros, in press).","L. castroviejoi is experiencing a decline in relation to specific portions of its distribution that are disturbed by human activities and excessive hunting (Ballesteros et al. 1996). Fragmentation, resulting from the patchy distribution of suitable habitat, has produced a dispersed metapopulation of this species (Ballesteros, in press). A habitat suitability model indicated that L. castroviejoi was experiencing a decreasing population trend of 16.67% and a 4.17% increase within its metapopulation structure, with no appreciable change for 70.82% of the populations (Acevedo et al. 2007).","Little is known about the home range, population density, and food preferences, but they are likely to be similar to those of European hares in comparable habitat. No information is available on reproduction (Alves pers. comm.).L. castroviejoi occupies an elevational range of 1,300-1,900 m, descending in winter to 1,000 m to avoid snow. This habitat consists of heathland where the dominant vegetation forms are Erica, Calluna, and Vaccinium and shrub where the cover consists of Cytisus, Genista, and Juniperus (Flux and Angermann 1990, Alves and Niethammer 2003). A habitat suitability model determined that L. castroviejoi, ""selects areas characterized by a high percentage of broom and heather scrublands, high altitude and slope, and limited human accessibility (quantified as distance to roads variable) (Acevedo et al. 2007). Its habitat also includes cleared areas of mixed deciduous forest of Fagus and Quercus (Palacios 1977). L. castroviejoi also selects habitat that has been burned and areas where broom has been cleared within Somiedo Natural Park (Ballesteros et al. 1996). Nocturnal censuses with spotlights in Somiedo Natural Park determined average densities of 6.83/100 ha (Gonzalez-Quiros et al. 1992).","There has been excessive hunting at the western edge of its distribution where hares are isolated from the rest of the population during the summer (Palacios and Ramos 1979). In addition to over harvesting, this species is subject to predation, poisoning (fertilizer and pesticides) and habitat change (Ballesteros et al. 1996).","Recommended conservation actions are (Ballesteros et al. 1996):- Research to determine the effects of habitat change, predation pressure, and illegal hunting.- Develop a global hunting plan for all regional reserves and private hunting areas, accommodating specific characteristics of the situation for the species.- Avoid any restocking with other hare species within the extent of occurrence of L. castroviejoi.- Development of direct or indirect predator control, especially in conjunction with foxes and domestic dogs and cats.- Restoration of altered habitat that is no longer suitable for L. castroviejoi.The establishment of corridors among local populations should be considered to bolster interbreeding within the metapopulation (Acevedo et al. 2007).Research should also be conducted to improve knowledge of reproduction and genetic structure (Alves pers. comm.). Although L. castroviejoi is listed as endangered in Spain, it is still hunted as a game species in some regions (Cantabria and Leon) (Alves per. comm.).The ability to implement policies to manage and conserve this species should be easy, because a substantial portion of its area of occupancy lies within reserves (Ballesteros et al. 1996).","Smith, A.T. & Johnston, C.H." +ANIMALIA,CHORDATA,MAMMALIA,LAGOMORPHA,LEPORIDAE,Lepus corsicanus,"Formerly included in Lepus capensis or L. europaeus; see Ellerman and Morrison-Scott (1951) and Petter (1961); but see also Palacios et al. (1989) and Pierpaoli et al. (1999) who provided evidence of their specific distinctness (see also below).The taxonomic status of L. corsicanus has been uncertain since its first description by De Winton in 1898. Its species rank was soon rejected by Miller (1912) and others, who considered L. corsicanus a subspecies of L. europaeus. However, Palacios (1996) studied historical museum specimen and described new morphological traits that provided phenotypic support for the species rank of the Apennine Hare. Recent molecular studies confirmed that L. corsicanus is a phylogenetically distinct species, which can be identified by concordant morphological and mtDNA traits. It is reproductively isolated and apparently does not hybridize with sympatric L. europaeus. Phylogenetical analyses suggested that corsicanus and europaeus are not closely related sister taxa, but belong to distinct evolutionary lineages that dispersed in western Europe in different periods during the early Pleistocene. L. corsicanus probably differentiated in isolated refuges in southern Italy during the last glaciation. Comparative analyses of genetic variability highlighted a phylogeographical structure of the Apennine Hare. Recently, it has been hypothesized that L. corsicanus and L. castroviejoi are conspecific, based on preliminary molecular studies involving low sample size and mtDNA (Alves et al. 2003).",Yes,Yes,VU,A2bcde+3bcde,VU,A2bcde+3bcde,"Our assessment is based on field surveys (spotlight censuses, hunting bag, captures, etc) and on molecular analyses of specimens collected by a network of helpers (hunters, park rangers, etc). This species has been monitored continuously since 1997 in continental Italy and Sicily. L. corsicanus shows a variable conservation status across its distribution range. Due to the fragmentation and scarcity of L. corsicanus populations in continental Italy, mainland status is classified as endangered (following Angelici and Luiselli 2001). However, the creation of several protected areas in southern and central Italy will help the populations to recover.In Sicily, L. corsicanus is widespread and the populations are locally abundant. Furthermore since its official recognition as true species (1998), the local government has forbidden hare hunting on the island. However, hunting of this species was permitted during the 2004-2005 hunting season in Sicily. Therefore, in Sicily L. corsicanus does not appear to be threatened.Finally we have no direct information on the status of the species in Corsica. The recent discovery of three specimens in Corsica implies that there are extant populations of L. corsicanus (Scalera and Angelici 2002). However, it is presumed that population numbers are low. Further studies are needed to ascertain its true status.Globally, this species is classified as Vulnerable due to its variable conservation status across its geographic range. Utilizing information currently available regarding the historical range on continental Italy, we replicated this portion of the range using GIS to calculate the total area (Pierpaoli et al. 1999). The result showed that the historical range on continental Italy was approximately 79,700 km². Online sources gave an area of approximately 25,700 km² for Sicily. This provides a total area of 105,400 km² as the historical range for L. corsicanus. We inferred an approximate decline of 50% for the continental populations from the map provided in Pierpaoli (1999). From this we derived an overall decrease of only 37.8% for the species as a whole.",Unfavourable,"Until the 1930s, L. corsicanus was distributed in south-central Italy (the northern limit being marked by Elba Island on the Tyrrhenian coast and the province of Foggia on the Adriatic coast) and Sicily. It was also present in Corsica, where it was introduced by man in historical times (maybe between the 14th and 17th centuries). The current distribution of L. corsicanus is still poorly known. In Sicily, the distribution seems to be continuous, whereas in the Italian Peninsula, populations are known only in Tuscany (in Grosseto province), Latium, Abruzzo, Molise, Apulia (Gargano), Campania, Basilicata and Calabria. It has been recorded from sea level to 2,400 m a.s.l. on Mount Etna. Recently the presence of L. corsicanus has been rediscovered in Corsica, too (Scalera and Angelici 2002). As of 1984, L. corsicanus was thought to be possibly extinct in Corsica; however, one dead specimen was found in 2000 and two dead specimens were examined in 2001 (Scalera and Angelici 2002).","Populations of L. corsicanus in the Italian peninsula have a fragmented distribution and are sometimes in sympatry and syntopy with Lepus europaeus. Density estimates highlight low values in hunting areas (0.5 hares/km²) and higher in protected areas (11 hares/km²). In mainland Italy L. corsicanus is decreasing because of habitat degradation, hunting pressure, and probably, from competition with introduced L. europaeus. However, in Sicily, where there are not populations of L. europaeus, L. corsicanus is continuously distributed and locally abundant (protected areas: 10 hares/km²; hunting areas: 2 hares/km²). No data are actually available on abundance and distribution of L. corsicanus in Corsica (where L. europaeus is present too).","Information about the ecology of this species is still limited. However, it seems well adapted to the Mediterranean environment, although it has been recorded from sea level to 2,400 m a.s.l. on Mount Etna (Sicily). The preferred habitats are the Mediterranean maquis and the mosaic of clearings (also cultivated), bushy areas, and broad-leaved woods. Furthermore L. corsicanus inhabits also coastal dune habitat. When L. corsicanus is in sympatry with L. europaeus, the latter species tends to be more a habitat generalist, while L. corsicanus seems to inhabit almost only pastures and grasslands. In Sicily, the species inhabits a variety of natural and artificial habitats: open grassland, bushy pastures, cultivated areas, etc.In terms of elevation, L. europaeus and L. corsicanus do not differ significantly when they live allopatrically. According to Angelici and Luiselli (in press), when the two species coexist in sympatry, L. corsicanus occurs at elevations significantly higher than L. europaeus. L. europaeus inhabits significantly higher elevations when it lives allopatrically than when it lives sympatrically, and L. corsicanus inhabits significantly higher elevations when it lives sympatrically than when it lives allopatrically. However, this ecological allocation is not shared by Trocchi and Riga who always directly observed, in sympatric condition, L. europaeus occupying the mountain grassland and L. corsicanus inhabiting the lower and warmer areas with thermophilous oak woods.The diet of L. corsicanus, studied in Sicily, varies seasonally as the available vegetation changes. Monocotyledones, Cyperaceae and Juncaceae, are ingested year round, while Gramineae and Labiatae are consumed during spring and summer, respectively (De Battisti et al. 2004). Dicotyledones ingested year round by L. corsicanus are Leguminosae and Compositae (De Battisti et al. 2004).","The main threats to L. corsicanus have been identified in the following aspects: fragmentation of the range, low or absent genetic flow between populations, low population density, habitat loss, introduction of L. europaeus in central and southern Italy (with interspecific competition and disease spread - L. corsicanus is fully susceptible to EBHS), competition with the European rabbit Oryctolagus cuniculus (mainly in Sicily, where this species is widely distributed), over-hunting, poaching and predation by foxes and feral dogs (both abundant and largely distributed in southern Italy). L. corsicanus is susceptible to accidental mortality due to difficulties distinguishing it from L. europaeus by hunters (Angelici and Luiselli 2001). Potential hybridization between L. europaeus and L. corsicanus could constitute a future threat to the species (Pierpaoli et al. 2003). On the major threat list ""other"" has been checked and identified as intraspecific genetic pollution.","The main conservation actions are:-improve data of the distribution and status of the species in Italian peninsula and in Corsica-conservation and improvement of natural populations-habitat improvement-minimizing risk factors-planning specific oriented management both in protected areas and in hunting territories at a local level-carrying out a number of enclosures for captive breeding and initiating behavioral study on L. corsicanus-promote a public educational campaign to develop the awareness and understanding of L. corsicanus-prepare a training program on biology and conservation of L. corsicanus for field biologists, conservationists, game keepers, and protected areas staff-creation of a data bank on the species-improvement of scientific research -place the species on a suitable legal status for international legislationToday L. corsicanus is legally protected in continental Italy because of its conservation status (primarily low population size). However, the problematic discrimination in the field between L. corsicanus and L. europaeus (a game species) produces remarkable problems for effective protection. Since L. corsicanus was recognized as a true species (1998), hare hunting has been banned in Sicily. During the 2004-2005 hunting season, this ban was lifted allowing the hunting of hares in Sicily. In Corsica it is considered a game species, in the French hunting act, since it cannot easily be distinguished from L. europaeus.Lepus corsicanus can be found in many protected areas in Italy. The following is a partial list.Continental Italy:Parco Regionale della MaremmaParco Regionale Monti LucretiliParco Regionale dell'Appennino ""Monti Simbruini""Parco Regionale del CilentoParco Nazionale della SilaParco Nazionale del PollinoParco Nazionale dell'AspromonteSicily:Parco Regionale dell'EtnaParco Regionale dei Monti NebrodiParco Regionale delle Madonie","Angelici, F.M., Randi, E., Riga, F. & Trocchi, V." +ANIMALIA,CHORDATA,MAMMALIA,LAGOMORPHA,LEPORIDAE,Lepus europaeus,,No,Yes,LC,,LC,,"European regional assessment: Least Concern (LC)EU 25 regional assessment: Least Concern (LC)This species has a wide range. Population size has not been quantified, but it is not believed to approach the thresholds for the population size criterion of the IUCN Red List (i.e. less than 10,000 mature individuals in conjunction with appropriate decline rates and subpopulation qualifiers), as the species is described as locally common in at least parts of its range. Population trend has not been quantified, but it is not believed to approach the threshold for the population decline criterion of the IUCN Red List (i.e. declining more than 30% in ten years or three generations), although there have been some declines. For these reasons, it is evaluated as Least Concern.",Possibly Favourable,"Lepus europaeus has a large global range extending from western Europe to western Siberia (Russia) and south-western Asia (Iran). In Europe, the species is widely distributed throughout, with the exception of most of the Iberian peninsula, northern Fennoscandia and northern Russia. It occurs on a number of Mediterranean islands. The population in Ireland was introduced recently, and the population in the UK is a long-established naturalised population, that may originally have been introduced by the Romans (Battersby 2005). As a game species, the European hare has widely been introduced to countries across the globe (Flux and Angermann 1990). It is found from sea level to 2,300 m (Spitzenberger 2002).","It is considered locally common in at least parts of its range, with typical population densities ranging from 0.2 to 0.7 individuals per hectare (Homolka and Zima 1999). In western and central Europe, the species has undergone significant decline in the last 50 years (Flux and Angermann 1990, Homolka and Zima 1999, Battersby 2005, Smith et al. 2005), although there are indications that the population trend has stabilised in recent years in at least some countries (Battersby 2005, Zima pers. comm. 2006). Hunting bags suggest that populations in Finland are currently stable (H. Henttonen pers. comm. 2006). There is no information on population trends in eastern and south-eastern Europe.","A highly adaptable species, it occupies a wide variety of habitats, including grassland, steppes, open temperate woodland, arable farmland, and pastures (Flux and Angermann 1990, Homolka and Zima 1999). It tends to be particularly abundant in open, flat areas where cereal cultivation predominate. Dense old-growth forests are avoided (H. Henttonen pers. comm. 2006). Woodland, scrub, hedges and shelterbelts are used as cover when the species is resting (Homolka and Zima 1999). It feeds mainly on grasses and herbaceous plants. When available, weeds and wild grasses are preferred, but where intensive agricultural practices have reduced the availability of these food sources crop species are selected (Reichlin et al. 2006). Unlike Lepus timidus, it does not feed on shrubs.","Agricultural intensification, in particular the increased use of pesticides, fertilizers and heavy machinery in arable farming, is generally considered to be the main cause of population declines in western and central Europe (Homolka and Zima 1999). A recent study that reviewed available literature on the relationship between hare abundance, demography, habitat, and land-use practices in 12 European countries confirmed that the primary cause of hare decline was intensification of agriculture (Smith et al. 2005). It is inferred that this threat may impact on the species throughout its global range, wherever farming is practiced. Agricultural intensification in eastern and south-eastern Europe is a potential cause for concern, especially in countries that have recently acceded to the EU, or that may join in the near future. In Greece, restocking with hares from other regions has been identified as a threat to local gene pools (Mamuris et al. 2001). This issue has also been identified as a concern for the Cantabric population in Spain (Palacios et al. 2004). It is a popular game species throughout it range in Europe, but hunting is regulated and appears sustainable. Smith et al.'s (2005) review found no evidence of a link between hunting pressure and population density.","The species is listed on Appendix III of the Bern Convention. It occurs in many protected areas throughout its wide range. In Norway, Germany, Austria and Switzerland, population declines have resulted in country-specific Red Listing as ""near threatened"" or ""threatened"" (Reichlin et al. 2006).Research is needed to determine the effect that habitat change has on life history parameters with regard to declines (Smith et al. 2005). There is a lack of understanding as to why hare numbers are low in pastoral landscapes, and therefore research should be conducted within this habitat type with particular emphasis paid to demography and behavioral ecology (Smith et al. 2005). When population declines are the direct result of agricultural intensification, which results in increased application of fertilizer, landscape homogeneity and mechanization, population declines of L. europaeus can be countered by management practices that increase heterogeneity (Smith et al. 2005).In Spain, molecular phylogenetic studies have shown that the Cantabric population has unique mtDNA in relation to other European populations (Palacios et al. 2004). As an important hunting species, declining numbers have prompted the importation of non-Iberian hares (from France and elsewhere) to supplement hare densities (Palacios et al. 2004). In an effort to conserve this population's gene pool, a captive breeding program has been implemented (Palacios et al. 2004). As of 2003 this program has successfully bred leverets and in 2004 turned its focus to increasing genetic variability by introducing individuals from new localities (Palacios et al. 2004).","Giovanni Amori, Jan Zima, Heikki Henttonen, Andrew Smith, Charlotte Johnston" +ANIMALIA,CHORDATA,MAMMALIA,LAGOMORPHA,LEPORIDAE,Lepus granatensis,"Lepus granatensis was formerly included in europaeus or capensis; but see Palacios (1983, 1989), and Bonhomme et al. (1986). The population in Sardinia, to which the names mediterraneus Wagner, 1841 and typicus Hilzheimer, 1906, are applied, in the past have been assigned to this species based on Miller (1912), who regarded it as closest to granatensis, though he retained it as a ""...very distinct species"" because of its small size. If in the future mediterraneus is confirmed as a synonym of granatensis, it has priority over granatensis. The Sardinian population is included in L. capensis until its taxonomic status is resolved.Molecular phylogeny has shown that L. granatensis is indeed a full species and one of three hare species present on the Iberian Peninsula (Alves et al. 2003). Previous questions regarding taxonomic distinction of L. granatensis from L. capensis have been resolved by genetic and morphological comparisons (Mitchell-Jones et al. 1999, Alves et al. 2003).There are three subspecies: Lepus granatensis granatensis, L. g. solisi (Mallorca), L. g. gallaecius (Galicia and Astrias, Spain) (Hoffmann and Smith 2005).",Yes,No,LC,,LC,,Lepus granatensis is cited as common and locally abundant within its widespread geographic range of the Iberian Peninsula (Mitchell-Jones et al. 1999). The current population trend in general is stable (Duarte 2000).,Unknown,"The geographic range of Lepus granatensis includes Portugal and nearly the entire extent of Spain (Alves et al. 2003). It is excluded from northern regions of Spain where L. castroviejoi and europaeus exist (Alves et al. 2003). In most of the northern provinces (Navarra, Asturias, Cantabria, Aragon, Catalunya, and Basque Country), L. europaeus and L. granatensis exist in parapatry, the Iberian hare inhabits the southern region and the brown hare can be found to the north (Fernandez et al. 2004). L. granatensis is also located on the island of Mallorca of the Balearic chain (Schneider 2001). It has gone extinct on the island of Ibiza (Balearic Islands) (Mitchell-Jones et al. 1999).L. granatensis has been introduced in southern France (Perpignan) (Alves et al. 2003).","Lepus granatensis is considered locally abundant and common in the southern and central portions of its range (Mitchell-Jones et al. 1999; Farfan et al. 2004). In the autonomous communities of Galicia and Asturias, it is thought to be extremely rare or extinct (Mitchell-Jones et al. 1999). On the island of Mallorca it has become extinct in the western mountain range and is rare throughout the remainder of the island (Mitchell-Jones et al. 1999). Population trends in Navarra and Donana National Park, monitored over several years, have been increasing (Carro et al. 2004). A study of relative abundance and population trends in northeast Spain indicated that L. granatensis experienced, ""a general positive trend during the study period"" which occurred from 1992-2002 (Gortazar et al. 2007).","Lepus granatensis can persist in a variety of habitats within Spain and Portugal (Mitchell-Jones et al. 1999). It occupies arable lands of central Spain and mountainous forests of northwestern Spain (Mitchell-Jones et al. 1999). Other has been checked on the Habitat Preferences list and has been identified as dunes along the Mediterranean coast (Mitchell-Jones et al. 1999).Reproduction in L. granatensis is continuous year round, with peaks experienced between February and June (Alves et al. 2002; Farfan et al. 2004). It has been estimated that the mean number of litters per productive female per year and the mean litter size are 3.48 and 2.08, respectively (Farfan et al. 2004).",No major threats to Lepus granatensis have been cited.,Lepus granatensis is listed as an Appendix III species under the Bern Convention as part of L. capensis sensu lato (Mitchell-Jones et al. 1999).,"Smith, A.T. & Johnston, C.H." +ANIMALIA,CHORDATA,MAMMALIA,LAGOMORPHA,LEPORIDAE,Lepus timidus,,No,Yes,LC,,LC,,"European regional assessment: Least Concern (LC)EU 25 regional assessment: Least Concern (LC)This species has a large range. Population size has not been quantified, but it is not believed to approach the thresholds for the population size criterion of the IUCN Red List (i.e. less than 10,000 mature individuals in conjunction with appropriate decline rates and subpopulation qualifiers). Population trend has not been quantified, but it is not believed to approach the threshold for the population decline criterion of the IUCN Red List (i.e. declining more than 30% in ten years or three generations), although the isolated Alpine population may be declining. For these reasons, it is evaluated as Least Concern.",Possibly Favourable,"Mountain hares range from Fennoscandia, the Baltic and east Poland to the Pacific Ocean, from 75°N in the far north of Russia and Scandinavia, south to 40-50°N. There are isolated populations in the Alps from France to Slovenia, Ireland, Scotland, Switzerland, Italy, the Kurile Islands, and Hokkaido, Japan. It has been introduced into the Faeroes, England, and various Scottish Islands; some introduced on Spitzbergen later died out. It occurs at altitudes of 250 to 3,700 m (Sulkava 1999).","Long-term population trends in Europe appear generally stable, with fluctuations in population density occurring over a multi-year cycle (typically peaking every 4 or 7-8 years in Scandinavia and every 10 years in Scotland and northern Russia). Periodic population crashes occur, potentially as a result of disease (tularaemia, a bacterial infection), parasitism, predation, or starvation (Angerbjorn and Flux 1995, Sulkava 1999). Population densities of 1-10 individuals per km2 are typical in range states (e.g., Scotland and Finland). Population declines have occurred in Russia, and in the far south of Sweden the species has completely disappeared (Thulin 2003). The isolated Alpine population may be declining (Sulkava 1999).","Mountain hares occupy tundra and open forest, particularly of early successional stages. In Scotland and Ireland heather moors and bogland are favoured habitats, and in southern Russia copses in the middle of open steppe and reed belts around lakes. The diet varies with the habitat. In Scotland and Ireland much heather, Calluna, is eaten, but this is not a major food item elsewhere in Europe where willow, aspen, birch, juniper, poplar, and Vaccinium are favoured (Flux and Angermann 1990). Palatable grasses and clovers are taken when available. Mountain hares are nocturnal, but there is increased daylight activity in summer when nights are short, or in winter when food is scarce (Flux and Angermann 1990). In areas where L. timidus and L. europaeus coexist, L. timidus retreats to areas of higher elevation, presumably as a result of competitive exclusion (Thulin 2003).","It is hunted as game, but current hunting rates appear to be sustainable in most parts of its European range. L. timidus has successfully hybridized with L. europaeus in areas where the latter has been introduced (Thulin 2003). The pathogens European Brown Hare Syndrome (EHBS) and tularemia may be problematic, but research is required to determine how great an impact they have on wild populations (Thulin 2003). Competitive exclusion of the mountain hare by the European brown hare may restrict the distribution of the former (Thulin 2003), and anthropogenic climate change may affect competitive relationships between these two species. The discovery of an introduced population of L. europaeus to Ireland could pose a threat to the Irish subspecies L. t. hibernicus (N. Reid pers. comm. 2006).","The species occurs in a number of protected areas within its European range. It is listed on Appendix III of the Bern Convention, and Annex V of the Habitats and Species Directive. In areas where L. timidus is proven or suspected to be declining, research should be carried out to determine the potential causes. Monitoring is required to determine if the species is declining in the Alps. Monitoring of the endemic Irish hare (L. t. hibernicus) is already underway. Genetic investigations into the taxonomic status of this subspecies are also underway. A number of reasons for decline have been suggested: interspecific competition with L. europaeus, the impact of pathogens, and the effects of hybridization (Thulin 2003). In Ireland, the cause(s) of population change require further investigation, but agricultural intensification appears to be one of the main concerns.","Heikki Henttonen, Andrew Smith, Charlotte Johnston" +ANIMALIA,CHORDATA,MAMMALIA,LAGOMORPHA,LEPORIDAE,Oryctolagus cuniculus,"Two recognized subspecies occur on the Iberian peninsula of Europe. Oryctolagus cuniculus algirus occupies the south-western area (roughly Portugal and southern Spain). Its range overlaps somewhat with that of O. c. cuniculus, which occupies all points north and west of O. c. algirus (Biju-Duval et al. 1991). O. c. cuniculus is thought to be the descendant of early domestic rabbits released into the wild (Chapman and Flux 1990), and is the subspecies that has been introduced throughout Europe and worldwide (Angulo 2004). O. c. algirus is also found in north Africa, and on Mediterranean and Atlantic islands (Branco et al. 2000).",No,No,NT,,NT,,"European and EU 25: Populations in all parts of Europe where the rabbit has been established since before 1500 A.D. are considered for this assessment. Significant declines have been reported in many parts of the rabbit's European range, and it is inferred that declines approach 30% over the last 10 years overall. Consequently the species is assessed as Near Threatened (approaching A2b). In many countries outside Europe, the rabbit is an alien invasive species that is itself a threat to many other species; the listing of Near Threatened in Europe should not in any way deter efforts to eradicate the rabbit in areas where it is a conservation problem.",Unfavourable,"Oryctolagus cuniculus is a widespread and abundant species, which has been introduced to all continents except Antartica. It was originally restricted to Spain, Portugal, western France, and northern Africa, but it has spread over the last two millenia to almost all parts of the European region, including the British Isles, many Mediterranean islands, the Azores, and Madeira. This range expansion occurred partly because of deliberate introductions, as the rabbit was widely exploited as a food source, and partly through natural spread. It remains absent from most of Fennoscandia, and occurs only sporadically on the Balkan peninsula. Outside Europe, it was introduced to Australia, in 1788 and again in 1859, where it is now widespread (Thompson and King 1994). It was introduced to South America unsuccessfully several times since the mid-nineteenth century, and successfully in about 1936; it now maintains a limited range in Argentina and Chile (Thompson and King 1994). Found in many islands in the Pacific, off the African coast, New Zealand, and the Caribbean (Thompson and King 1994).","It is a common species throughout much of its European range. Population densities of 0.5 to 10 individuals per hectare are typical, with densities of up to 100 individuals per hectare having been recorded (Homolka and Zima 1999). However, in at least some parts of Europe the species has undergone significant decline in recent years. In Portugal, a population reduction of 24% was recorded between 1995 and 2002 (Alves and Ferreira 2002), and in Spain and Portugal as a whole it is estimated that there are now as few as 5% of the number of rabbits that existed 50 years ago (Ward 2005). Large declines since 1990 have also been noted in Austria (Spitzenberger 2005) and Germany (Eylert 2004), and in the UK the species declined significantly between 1995 and 2002 (different survey methods give a 48% decline from 1995-2002 and a 23% decline from 1997-2002: Battersby 2005). Subspecies O. c. huxleyi, which occurs on certain Atlantic and Mediterranean islands, has a restricted range and may be threatened (Homolka and Zima 1999).","The rabbit occupies a variety of habitats, including grassland, meadows, pastures, arable field-margins, sand-dunes, grassy cliffs, heathland and open woodland. In summer, it feeds on the vegetative parts of a variety of grasses and herbaceous plants, and in winter it eats grasses, bulbs and bark (Macdonald and Barrett 1993). It can be an agricultural pest in areas where it is abundant, and it has caused severe damage to native ecosystems in some areas where it has been introduced (for example Australia) (Ward 2005). Rabbits are an essential keystone element of the Mediterranean ecosystem in Spain and Portugal, being preyed on by at least 39 predator species including the Critically Endangered Iberian lynx Lynx pardinus and the vulnerable and range-restricted Iberian imperial eagle Aquila adalberti (Ward 2005, BirdLife International 2006). Rabbit declines are considered to have had a negative impact on both of these threatened species (Ward 2005, BirdLife International 2006).","Myxomatosis caused severe population declines in the 1950s, but numbers subsequently rallied as the myxoma virus become less virulent and the rabbit more immune (Macdonald and Barrett 1993, Macdonald and Tattersall 2001). Myxomatosis was deliberately introduced to Europe in 1952 in an effort to control rabbit numbers; it originates from South America (Ward 2005). Declines in recent years have been attributed to Rabbit Haemorrhagic Disease (RHD; also known as DHV), myxomatosis, and over-hunting (Ward 2005, Spitzenberger 2005). RHD is believed to have originated in Europe, where it was first detected in 1987 (Ward 2005). Habitat loss (due to agriculture, forestry, development, forest fires and land abandonment) is considered to be a contributory factor to rabbit decline in Iberia (Ward 2005). It is a popular game species, and over-hunting may be a problem in some parts of its range. Pest control measures may cause local population declines. There have been attempts in Australia to develop a genetically modified immunocontraceptive virus for rabbits, and accidental or deliberate illegal spread of such a virus could be a threat to rabbits in the future (Henzell and Cooke 2003, Trout 2003, Ward 2005).","The issue of eradication of O. cuniculus from its introduced range (e.g. Australia, New Zealand, and many islands) may have overshadowed the significance of rabbit decline in its native range. However, the importance of O. cuniculus within its natural range necessitates that it be considered for listing as threatened in spite of its global abundance. It is a keystone component of the Iberian ecosystem, as prey for specialist predators (Virgos et al. 2005) and as a landscape modeller (Delibes et al. 2000, Ward 2005). It is an important game species in Spain and Portugal (Ward 2005). Oryctolagus cuniculus occurs in some protected areas within its natural range, including Donana National Park in Spain (Ward 2005) and Serra da Malcata Nature reserve in Portugal (700km2) where the Iberian lynx is protected.Ward (2005) summarises key issues regarding the conservation of the European rabbit within its native range: ""- Establish rabbit monitoring programs to accurately describe decline directly.- Create and implement a management plan for rabbit recovery that prioritizes critical ranges and populations. Some plans have begun for local regions, including Donana National park. - Programs to limit the incidence and impact of new and existing diseases may be difficult in the wild, though some success has been observed in captive populations. Current vaccines do not confer total immunity to RHD or myxomatosis, have side effects such as increasing vulnerability to predators, and have short-lived effectiveness. A genetically modified live myxomatosis virus vaccine, LapinVac, is controversial because of the possibility of unpredictable evolution of the virus, and its potential spread to rabbit populations outside the natural O. cuniculus range where eradication, not conservation, is the objective. Increasing habitat quality may indirectly help rabbit disease resistance. Controlling disease vectors for myxomatosis has not been found to be effective. Preventing the spread of modified immunocontraceptive viruses engineered in Australia to control rabbit fertility may become an issue.- Reducing hunting impact is not guaranteed to reduce decline because disease effects often outweigh hunting as a threat, and because implementation of restrictions would likely not be realistic given the prevalence of hunting in Iberia. Revisions to existing hunting seasons have been proposed and some tested, but even moving the season to summer when rabbits are most abundant has caused concern in trials because the overall catch increases and the season coincides with a peak in death from disease. A growing recognition among hunters of the issue of rabbit decline has led to some self-restraint, and though often well intentioned, uninformed management strategies are leading to inappropriate actions. Rather than focusing on hunting restraint, many hunters exert efforts to reduce rabbit predators, which are not directly responsible for decline. As a very large demographic, hunters could represent a powerful force in maintaining sustainable hunting populations, if the awareness of the issue of decline increased within this group.- Rabbit populations affected by agriculture represent a sensitive issue, as rabbits are typically seen as a pest and an economic liability for farmers. Despite pressures from environmental groups, many farmers continue to take measures to eradicate rabbits from their land, even in areas where rabbit populations have declined dramatically. Awareness among farmers of rabbit conservation issues is low. Government policy allows farmers to control rabbits with permits, and though crop loss due to rabbit damage is economically subsidized, no requirement of those compensated is made for conservation.- Halting and reversing habitat loss and fragmentation was aided in the 1990s by the establishment of many national parks in Spain, but much optimal rabbit habitat is on private land. A shift from high-intensity farming and monoculture forestry back to mixed agro-forestry and small scale farming would help sustain rabbit populations. Natura 2000 promotion of sustainable development and EU subsidies supporting environmentally friendly agriculture are promising but underfunded and too new to demonstrate a significant impact. Eucalyptus plantation removal has demonstrated a positive effect on rabbit populations, but may compromise other environmental issues such as erosion and conditioned bird habitat, as well as economic impact.- Reintroductions have been a key focus of conservation efforts, with up to 500,000 released annually in Spain and France. The efforts so far have not increased rabbit populations, due to increased mortality from predation and inadvertent spread of disease, which may actually have a net negative impact. The flaws in reintroduction practices do not completely negate the importance of the efforts, which have been shown to help sustain predators and hunting populations. The success of introductions may be increased by fencing from predators and competitors and preventing dispersal.- Though rabbit predators have not directly caused rabbit decline, factors that have caused initial decline (e.g., disease, habitat loss) are exacerbated by some opportunistic predators (while not caused by specialist predators like the Iberian lynx and Imperial eagle). Game keeping efforts to increase rabbit populations often focus on predator reduction, sometimes counterproductively, causing decline of top predators that are already threatened. Efforts could be more productively focused on habitat protection, reduction of rabbit mortality by humans (hunting, poisoning), and reducing disease impacts.""",Andrew Smith and Anna Boyer +ANIMALIA,CHORDATA,MAMMALIA,LAGOMORPHA,PROLAGIDAE,Prolagus sardus,,Yes,Yes,EX,,EX,,"The last presumed sighting of Prolagus sardus was in 1774 (Smith 2008). This species was present in its historic distribution within the last 2,000 years (Smith 2008). It is speculated that ""habitat loss, predation, and competition with alien invasive species"" were responsible for its extinction (Smith 2008).",-,"Prolagus sardus once occupied Corsica, Sardinia, and small adjacent islands of the Mediterranean (Hoffmann and Smith 2005).",Extinct.,,,,"Smith, A.T. & Johnston, C.H." +ANIMALIA,CHORDATA,MAMMALIA,PRIMATES,CERCOPITHECIDAE,Macaca sylvanus,"Macaca sylvana is a synonym of M. sylvanus (Alvarez and Horaldo 1975, Burton 1972, Deag and Crook 1971, Hill 1966)",No,Yes,NA,,NA,,"There is no conclusive evidence that the Barbary macaque occurred in Europe before the 1700s. Consequently the Gibraltar population is regarded as a relatively recent introduction, and is classed as Not Applicable (NA) at the European and EU 25 level. The Barbary macaque is seriously threatened in its native range in North Africa.",-,"The Barbary macaque is the only surviving primate in Africa north of the Sahara desert, the only species of primate to occur in Europe (apart from Homo sapiens), and the only member of the genus Macaca that can be found outside Asia. The species was once an inhabitant of parts of Europe and all of North Africa (Delson 1980, Camperio Ciani et al. 1986) but the current distribution of the Barbary macaque is limited to relict forest areas in Algeria and Morocco (Fa 1984, Camperio Ciani 1986, Menard and Vallet 1993, Scheffran et al. 1993). A semi wild population lives in Gibraltar, which is a long established population that is almost certainly introduced (see discussion below) (Fa 1981, von Starck 1990, Hodges and Cortes 2006). In Morocco, M. sylvanus can still be found in the Rif mountains (northern Morocco) and the Middle and High Atlas mountains (central and southern Morocco). In Algeria, it is found in the Petit and Grande Kabylie mountains (northern Algeria) (Taub 1977). It occurs from sea level to 1,900 m, but in Morocco at least it is most common at altitudes above 1,600 m (E. van Lavieren pers. comm. 2006). In mainland Europe, macaques were widespread during the Pleistocene, but disappeared thereafter. However, there are no fossil or subfossil remains known from Gibraltar, suggesting that the species is not native to this promontory (Hodges and Cortes 2006). It has been speculated that macaques may have been introduced to Gibraltar in early historic times, by the Phoenicians, Romans, or Moors, who kept these animals as pets (von Starck 1990), but there is no conclusive evidence to support this (Hodges and Cortes 2006). The first definite records date from the 1700s onwards, when the island was occupied by the English (Hodges and Cortes 2006). The population was driven close to extinction by disease or persecution on a number of occasions, but each time was replenished by animals imported from North Africa (von Starck 1990). Genetic studies have confirmed that the current population are descendants of a mixture of Algerian and Moroccan stock (Modolo et al. 2005).","In 1999 the total number of remaining macaques was estimated at around 15,000 individuals (Von Segesser et al. 1999), although this estimate was based on incomplete data. The Morocco population was more recently estimated to be 6,000-10,000 individuals (Ross 2004), whereas in 1975 it was about 17,000 (Taub 1975). In Algeria, the population was estimated at 5,500 30 years ago (Taub 1977), but is currently much less, although exact numbers are unknown (Hodges and Cortes 2006). On Gibraltar, the population has been maintained at c.200 individuals in recent years (Hodges and Cortes 2006). Consequently, the global population of M. sylvanus is now estimated to number fewer than 10,000 individuals (Hodges and Cortes 2006). According to Moroccan authorities the number of macaques has increased over the last decade (van Lavieren 2006). However, a number of detailed surveys have documented marked declines in population density, along with losses of a number of sites (Von Segesser et al. 1999, Camperio Ciani et al. 2005, van Lavieren 2006). The remaining subpopulations in the Rif mountains and High Atlas mountains of Morocco are fragmented and small. The same can be said for the Algerian subpopulations (Mehlman 1989, Fa 1984, Von Segesser et al. 1999). In 1999, just seven widely separated isolated populations existed, whereas only 35 years ago they were found in at least 6 additional localities in Algeria (Von Segesser et al 1999). The remaining isolated populations are now completely separated by distances of 50-100 km, with no corridors. The only area where M. sylvanus is thought to occur in relative abundance is the cedar forest area of the central Middle Atlas (Camperio Ciani et al. 1995, van Lavieren 2006), which represents the largest refuge of the North African forest ecosystem. It was estimated that 65-75% of the world' s remaining population lived in this area (Camperio Ciani 1986). The populations in the Middle Atlas outside the central region are much lower in density (Taub 1975). The central region of the Middle Atlas thus has a crucial role in the survival of the species. In the mid-1970s, population densities in the central Middle Atlas cedar forest (the stronghold of the species) were variously estimated at 60-70 individuals per km2 (Deag 1974) or 43/km2 (Taub 1975). More recent surveys showed that the population in this region declined from 44 to 25 individuals per km2 over the last two decades of the 20th century (Camperio Ciani et al. 1999) - a decline of 43% over 20 years. The most recent surveys in the Middle Atlas show an average density of 15 to 20 individuals per km2 (van Lavieren 2006), in some areas dropping to an average density of 7-10 individuals per km2 (Camperio Ciani et al. 2005). Thus over the last 30 years a decline of 53-79% in the average population density is apparent, with declines in some areas being even greater.","In Algeria, occupied habitats include mixed cedar and oak forests, humid Portuguese oak (Quercus faginea) and cork oak (Quercus suber) mixes and gorges dominated by scrub vegetation (Taub 1977). Moroccan habitats include high cedar forests (Cedrus atlantica), cedar/holm oak (Quercus ilex) mixtures, pure holm oak forests and gorges dominated by scrub vegetation. In the High Atlas mountains the population of Barbary macaques is restricted to the Ourika valley, where only a small relict population survives (Taub 1977) in a habitat of holm oak and juniper (Juniperus phoenica) scrub on steep mountain slopes. The Rif mountains of Morocco contain a few fragmented and small populations in disjunct remnants of mixed woodland (Taub 1975, Deag 1974, Waters et al. 2007). The cedar/oak forests of the Middle Atlas region contain the largest remaining population of M. sylvanus, and are considered to be optimal habitat for the species (Camperio Ciani et al. 2001). In cedar habitats, macaques can reach densities of 25-40 individuals per km2 or greater, whereas in habitats without cedar much lower densities of 5-7 individuals per km2 are reported (Fa 1984, Mehlman 1989). All the areas occupied by the macaque are under growing pressure from human activity and the habitat availability for the M. sylvanus has severely decreased over the last decades (Camperio Ciani et al. 2005, van Lavieren 2006).M. sylvanus live in social groups of up to 30 individuals of both sexes. Life span in the wild is known to be up to 22 years of age (Lindenfors 2002). Females reach sexual maturity between 2.5 and 4 years of age and males between 4.5 and 7 years of age. Average age at first birth is 4.8 years for females (Lindenfors 2002), and the birth interval is two years (Taub 1974 in Fa 1984).","Major threats to M. sylvanus include habitat destruction and degradation (including dessication) and illegal live trade (Fa 1984; Camperio Ciani et al. 2003, 2005; van Lavieren 2004; Hodges and Cortes 2006). Severe habitat loss and degradation have been caused by domestic and industrial consumption of wood, use of fire, clearing for cultivation and overgrazing by sheep and goat herds (Taub 1977, Fa et al. 1984, Camperio Ciani et al. 1986, Menard and Vallet, 1993). Additionally, in the last ten years the drought in Morocco has prompted shepherds to settle near water sources. As shepherd tribes move into the forest region, they often enclose open water sources with cement wells so they can extract water for their herds. As a result, macaques and other wildlife have been excluded from water sources in areas where it was previously accessible to them (Camperio Ciani et al. 2003). Live trade is the second largest threat to the wild M. sylvanus population. Most of the specimens taken from the wild are for the international pet trade. In comparison with the international trade, offtake for local purposes is low. M. sylvanus seems to be rarely used for food, except for some reports in Algeria (Deag 1977). In the 1960s, a large number of macaques was captured for the use in laboratories in Casablanca, Tangier and Spain (Deag 1977), but this is no longer permitted in Morocco (A. Camperio Ciani pers. comm. 2003). M. sylvanus are kept fairly frequently as pets in Morocco (van Lavieren 2004). Reports of capture for the international pet trade date back to 1977 (Deag 1977). Since then, the trade has increased markedly (van Lavieren 2004). Sanctuaries and zoos in Europe have become overstocked with Barbary macaque infants offered to them by authorities and ex-owners, most infants coming straight from the wild (van Lavieren 2004). Infant M. sylvanus are very “cute” and are offered openly and covertly for sale on markets all over Morocco (van Lavieren 2004), resulting in frequent impulsive purchases mainly by tourists. Prices of up to 200 Euro per animal have been recorded (van Lavieren 2004). This problem has become so severe that there is only one animal sanctuary in Europe that continues to accept Barbary macaques, leading to many confiscated animals being euthanised (E. van Lavieren pers comm. 2006). It is estimated that 300 infants are taken annually from the Moroccan habitats (van Lavieren 2004). According to van Lavieren (2004) the maximum sustainable annual offtake of macaques in the Central Middle Atlas region lies between 200 and 250 individuals. If the estimate of 300 macaques taken from the wild is more or less correct (van Lavieren 2004) the offtake exceeds sustainability by up to 50% annually. Further potential threats include persecution, and predation by feral dogs (E. van Lavieren pers comm. 2006). The shooting of monkeys as a result of crop raiding and cedar bark stripping was reported by Deag (1977), but the current status of this activity is unknown.","M. sylvanus receives some protection under national and international legislation. Collection and export of M. sylvanus are regulated by a system of permits in Morocco, but enforcement of the legislation is inadequate. The National forestry department Eaux et Forets is the responsible authority (E. van Lavieren pers comm. 2006). Deag (1977) mentions a maximum quota for trade of 100 macaques annually in Morocco. The species is listed on Appendix II of CITES (EC 338/97, Annex B). In 2000, the European Community suspended imports of M. sylvanus from Algeria and Morocco under the provisions of Article 4.6b of EC Regulation 338/97 because such a trade was deemed to have a harmful effect on the conservation status of the species. These import suspensions remain in force under the most recent EC suspensions regulation (EC252/2005). Over the last few decades there have been repeated surveys of the species in the wild, mainly carried out by scientists from outside the range states. The national authorities are aware of these surveys but do not always support or agree with the outcome (E. van Lavieren pers. comm. 2006). The Moroccan authorities have planned a new survey on the Moroccan Middle Atlas population in 2007 (M. Mouna pers. comm. 2006). Most habitats of M. sylvanus in Algeria have national park status. This is not the case for all the habitats in Morocco. A part of the Rif mountains has national park status, and there are plans to make the cedar/mixed forest in the central Middle Atlas a national park, but a large part of the species' habitat in Morocco lies outside protected areas. In both Morocco and Algeria, the national forestry departments are responsible for the management and the protection of flora and fauna. There has been much debate about appropriate management of M. sylvanus. The national forestry department in Morocco believes that there are too many macaques in the region (due to the disappearance of predators such as the leopard Panthera pardus), and that they are responsible for the degradation of cedar forests through their bark stripping behaviour. There has even been talk of culling or translocating a part of the population (E. van Lavieren pers comm. 2006). However, field studies and surveys indicate that the population is declining, and that bark stripping behaviour is probably induced by water shortage (Camperio Ciani et al. 2001, 2003). The forestry department plans to start a new research project on the status of the Barbary macaque in the central Middle Atlas region, but some scientists have expressed concern that this is not necessary and may postpone the action needed to protect the species (E. van Lavieren pers comm. 2006). AAP (a Netherlands-based sanctuary for exotic animals) has initiated a major project to combat illegal trade of Barbary macaques into Europe, involving inter alia awareness raising among potential buyers, cooperation with authorities in the consuming countries and training of the customs officers in Spain. This project is carried out in collaboration with IUCN Netherlands, who are currently working to protect cedar forests in Morocco (E. van Lavieren pers comm. 2006).The Gibraltar population is intensively managed, receiving supplementary food and vetinary care (Hodges and Cortes 2006).","Thomas Butynski, John Cortes, Sian Waters, John Fa, Maria Elisa Hobbelink, Mohamed Mouna and Andrea Camperio-Ciani" +ANIMALIA,CHORDATA,MAMMALIA,RODENTIA,CASTORIDAE,Castor fiber,,No,No,LC,,LC,,"European regional assessment: Least Concern (LC)EU 25 regional assessment: Least Concern (LC)The European beaver has shown good recovery across much of its range, as a result of conservation programmes. The highest numbers are found within Europe. Conservation measures are ongoing to prevent the population declining again and as long as these continue, there is no reason to continue to assess the species as threatened or Near Threatened. Now Least Concern.",Possibly Favourable,"The Eurasian beaver Castor fiber was once widespread in Europe and Asia. However, by the beginning of the 20th century, over-hunting had drastically reduced both the numbers and range of the species. In Europe, only a few isolated sites remained: parts of the Rhone (France) and Elbe (Germany), southern Norway, the Neman River and Dnepr Basin (Belarus) and Voronezh (Russia). Reintroductions have enabled the beaver to return to much of its former range, and there are now a number of rapidly expanding populations extending from Spain and France across central and eastern Europe to European Russia, and in Scandinavia and parts of western Finland. Free-living populations of beavers are now established or establishing in most regions of their former European range, the main exceptions to date being Portugal, the south Balkans and Great Britain (Halley and Rosell 2002, Ceña et al. 2004). Detailed information on the status and distribution of the Eurasian beaver in each range state can be found in Halley and Rosell (2002), and information on the population that was translocated to Spain in 2003 can be found in Ceña et al. (2004). It is generally a lowland species, but occurs up to 850 m in Europe (D.J. Halley pers. comm. 2006).","By the beginning of the 20th century, the global population had been reduced to eight populations, totaling approximately 1,200 individuals (Halley and Rosell 2002). Protection (beginning with a hunting ban implemented in Norway in 1845), natural spread and reintroductions have resulted in a rapid recovery in numbers and range, particularly in Europe. In 1998, the global population was estimated at 430,000 (Nolet and Rosell 1998), by 2002 it had reached at least 593,000 (Halley and Rosell 2002), and in 2006 the minimum estimate was 639,000 (D.J. Halley pers. comm. 2006). This is almost certainly a considerable underestimate, as both population and range are in rapid expansion (Halley and Rosell 2002, 2003; D.J. Halley pers. comm. 2006). Considerable further expansion in range and population, especially in western Europe and the lower Danube basin, can be expected. If current trends continue, the Eurasian beaver will be a fairly common mammal in much of Europe within the next few decades. However, populations in Asia are still considered small. In Mongolia, reintroductions have been successful and the population has reached 150, and in China the population has reached 800 (Halley and Rosell 2002, EMA Workshop 2006).","Beavers are adapted for a semi-aquatic life, using a variety of freshwater systems, including rivers, streams, irrigation ditches, lakes, and swamps. They generally prefer freshwater habitats surrounded by woodland, but may occur in agricultural land or even suburban and urban areas (Tattersall 1999, Halley and Rosell 2002). In northern Scandinavia, beavers may be found right up to the limit of the willow zone in the mountains, where knee-high willow bushes are the only woody vegetation and it is iced over for 8 months of the year. This is not preferred habitat, but they can survive there. In many places, beavers live both on the valley floor, and on the mountain plateau above (where it is wooded), with a break in distribution where streams flow down the steep valley sides. In general beavers should be able to live in almost any freshwater habitat where there are trees or shrubs and the gradient is not precipitous. However, patterns of recolonisation demonstrate a clear preference for still or slow, laminar water flow if it is available (Nowak 1999, Halley and Rosell 2002, D.J. Halley pers. comm. 2006).","The beaver's historic decline was caused by over-hunting for fur, meat and castoreum (a secretion from the scent glands), combined with loss of wetland habitats. Beaver populations were severely reduced in most countries by mediæval times, but the species clung on in marshes and other inaccessible places until the advent of efficient steel traps and accurate firearms in the 17th century; and then through to the 19th century there was a rash of final extinctions for these reasons combined with drainage of many of the large marshland areas in which the species clung on (all of the European refugia where the species survived, except in Norway, are extensive marshlands). Today, beaver populations in Europe are expanding rapidly, and there are no major threats (e.g. threats of a magnitude likely to cause decline at the regional level). Competitive exclusion of the native European beaver C. fiber by its American cousin C. canadensis may be a threat in parts of Finland and north-west Russia, but it is not a major threat regionally. In Europe North American beavers are now confined entirely to Finland and north-west Russia, where populations are increasing only slowly (due to heavy harvesting). The former population at a reservoir near Paris has been removed, and populations introduced to Poland and Austria have apparently gone extinct in competition with C. fiber, the opposite of what has tended to happen in Finland and north-west Russia (it has been suggested that, due to differences in the life history of the two species, Eurasian beavers may have a competitive advantage at more southerly latitudes, whilst North American beavers may be more successful further north: D.J. Halley pers. comm. 2006). There are no serious prospects of further introductions (Halley and Rosell 2002, D.J. Halley pers. comm. 2006). The two species do not interbreed (Tattersall 1999). Roadkill is an important source of mortality for some populations (Tattersall 1999). Rapidly expanding beaver populations may come into conflict with humans in some areas, as they do some damage to forestry and crops. Such damages should be put into perspective: they tend to be less severe than those caused by other species such as deer and voles, but are noticed because beavers are a new and unfamiliar species in areas where they have been recently introduced (Halley and Rosell 2002).","A number of conservation measures have contributed to the species' recovery in Europe, including reintroductions and translocations, hunting restrictions, and habitat protection. It is listed under the Bern Convention (Appendix III) and the EU Habitats and Species Directive (Annex V for the Swedish and Finnish populations, Annex II & IV for all others). In Finland, C. canadensis populations are controlled to prevent them spreading into the west where C. fiber occurs. Halley and Rosell (2002) recommend regulated hunting as the optimal management regime in managed landscapes with healthy beaver populations. Management of beaver populations should be at the watershed scale, except where large human-made dams form significant barriers to spread. Early provision of interpretation and public viewing opportunities is also recommended, as this provides a benefit to the local economy through wildlife tourism, and helps foster positive attitudes to beavers (Halley and Rosell 2002). This has been a successful feature of several recent reintroductions. Reintroduction to Italy has been recommended in a European Union/Bern Convention Nature and Environment Series document (Nolet 1996). Considerable efforts have been made to develop a beaver reintroduction programme in Scotland, and a full public consultation showed strong support for such a scheme among the general public, including in rural areas where beavers were likely to be released (Halley and Rosell 2002).","Boris Kryštufek, Holger Meinig, Jan Zima, Heikki Henttonen, Linas Balciauskas" +ANIMALIA,CHORDATA,MAMMALIA,RODENTIA,CRICETIDAE,Allocricetulus eversmanni,,No,No,LC,,NE,,European regional assessment: Least Concern (LC)EU 25 regional assessment: Not Evaluated (NE)An abundant species with no major threats. Classed as Least Concern.,-,Distributed from eastern bank of the Volga river through the Russian Federation and Kazakhstan to Xinjiang (China).,Common and relatively abundant throughout the range. In the Ural region the species is expanding its range to the north by occupying agricultural lands.,"Inhabits dry steppe and semi-deserts, but is occasionally found in agricultural fields and the surroundings of settlements. According to Vinogradov and Gromov (1952) it is found near human settlements in Siberia further north than its original distribution. In the northern part of the range it is also found in forest-steppe (Gromov and Erbaeva 1995). In the Pleistocene it also occurred west of the Volga (Don basin, Crimea: Nechay 2000). Does not hibernate, however daily activity is lower in winter. Feeds on vegetative parts and seeds of different wild and cultivated plants. Also eats insects and molluscs on a regular basis, there are record of feeding on lizards, voles, small birds' nestlings and young ground squirrels (Gromov and Erbaeva 1995). Gives birth to 2-3 litters per year in northern parts of the range and 3-4 in southern. Litter size is 4-6 young.","There are no major threats to the species. Eversmann's hamster is a pest of cereal crops, melons and gourds.",There are no specific conservation measures applied to this species.,"Katerina Tsytsulina, Nikolai Formozov, Boris Sheftel" +ANIMALIA,CHORDATA,MAMMALIA,RODENTIA,CRICETIDAE,Arvicola amphibius,"Linnaeus' amphibius and terrestris, both proposed in 1758 on the same page, are now considered conspecific by most researchers, but which name should be properly used is still debated. Some authors split this taxon into two separate species: the aquatic A. amphibius and the fossorial A. scherman (Wilson and Reeder 2005).",No,No,LC,,LC,,"European regional assessment: Least Concern (LC)EU 25 regional assessment: Least Concern (LC)This species has a wide distribution, and both the fossorial and aquatic forms are considered pests in parts of the range. The population size has not been quantified, but it is not believed to approach the thresholds for the population size criterion of the IUCN Red List (i.e. less than 10,000 mature individuals in conjunction with appropriate decline rates and subpopulation qualifiers). Although there are ongoing declines in some range states (such as Britain, Italy, and the Netherlands), the overall population trend is believed to be stable at the regional and global level. For these reasons, it is evaluated as Least Concern.",Possibly Favourable,"Arvicola amphibius has a large range extending from Portugal and Great Britain in the west, through much of continental Europe and Russia, as far as the Lena Basin and Lake Baikal in Siberia (Russia). Its range extends north of the Arctic circle and south into Iran and the Near East (Shenbrot and Krasnov 2005). In Europe, it is widespread in central and northern parts of the continent, but it is absent from southern Iberia and southern and western France, and occurs only sporadically in the Balkans. The species occurs as two distinct ecological forms: aquatic and fossorial (burrow-dwelling). Aquatic forms are widely distributed, whereas fossorial forms are restricted to mountainous areas in southern and central Europe (Saucy 1999). In the French Alps it occurs to 2,400 m (Reichstein 1982).","Population declines in the aquatic form are evident in some European countries (e.g. Great Britain, the Netherlands and Italy) (Saucy 1999, Battersby 2005). However in many areas it is common and stable (in northern continental Europe it is considered a pest species). Even in optimal habitat, aquatic forms seldom occur at densities greater than 100 individuals per hectare (roughly equivalent to 15 individuals per 100 m of river bank), whereas fossorial forms may occur at such high densities that they become agricultural pests. Fossorial forms undergo pronounced cyclic population fluctuations every 5-8 years, with densities ranging between 0 and 1,000 individuals per hectare (Saucy 1999). In Fennoscandia and the Baltic area the aquatic form also shows population cycles in synchrony with other vole species.","Aquatic forms inhabit a variety of freshwater habitats in the lowlands and the mountains, including rivers, streams, lakes and marshes. In Fennoscandia, the aquatic form becomes fossorial during winter months. Steep riverbanks with lush grass and vegetation are preferred. Fossorial forms are restricted to the uplands, where they construct extensive underground burrows in grasslands (including pastures) or, less frequently, in woodlands. Both forms have a herbivorous diet, feeding predominantly on vegetation in the summer and on roots, bulbs and tubers in the winter (Reichstein 1982, Saucy 1999).","Declines in aquatic populations in parts of western Europe have been attributed to habitat loss, water pollution, predation by introduced American mink Neovison vison and competition by the introduced muskrat Ondatra zibethicus.",Occurs in protected areas but is frequently considered a pest species. The UK is the only part of Europe where the species is currently protected under national legislation.,"Heikki Henttonen, Boris Kryštufek, Holger Meinig" +ANIMALIA,CHORDATA,MAMMALIA,RODENTIA,CRICETIDAE,Arvicola sapidus,"There are two subspecies of the water vole: Arvicola sapidus sapidus (Miller, 1908) and Arvicola sapidus tenebricus (Miller, 1908). A. s. sapidus is present in Portugal and southern Spain, while A. s. tenebricus occurs in France and northern Spain. A. s. tenebricus is dark to reddish brown, while the coat of A. s. sapidus is generally lighter and more yellowish (Noblet 2005).",Yes,Yes,VU,A2ace+4ace,VU,A2ace+4ace,"The water vole has undergone a marked reduction in both the absolute number of individuals and its subpopulations located throughout its traditional range in France, Spain and Portugal, and that this decline is continuing as a result of ongoing habitat modification/disturbance and competition with introduced species. Furthermore, the water vole is facing all the risks associated with geographically scattered and isolated subpopulations. It is suspected that the rate of population decline exceeds 30% over a 10-year period.",Unfavourable,"The Southwestern Water Vole, Arvicola sapidus, occurs only in freshwater habitats in parts of France, Spain and Portugal, where it is found from sea level to a maximum of about 2,300 m in the Pyrenees (Le Louarn and Quéré, 2003).In France, the water vole remains relatively common in only three regions: Charente-Maritime, Brittany and southwest France (Pyrenees), though its distribution is still patchy in these areas. In the French départements of Drôme, Var, Alpes-Maritimes, Hautes-Alpes, Alpes-de-Haute-Provence, Loire, Rhône and Ain, the water vole has become rare, with a maximum of only 10 locations per département. In the Ain there is only one location, two in the Rhône and no more than 6 or 7 in the Hautes-Alpes.In Spain, the water vole is now restricted to the northern and eastern parts of the country, and has disappeared from central Spain, where it was formerly common. Locations of the water vole in Portugal are not well-documented but, as in other parts of its range, the water vole seems to be restricted to fairly isolated subpopulations in only a few parts of the country.","The water vole is declining in most parts of its range. In France it is much less common than it was 10-15 years ago (S. Aulagnier, 2006), and in the Iberian Peninsula it is considered to be declining as a result of habitat loss and degradation (Palomo and Gisbert, 2002), although it is not currently classified as threatened in Portugal (Cabral, 2005). Several studies have shown that, in optimal habitat, water vole density can reach five individuals per 100 m of river bank, but that it is unlikely to exceed this figure (Saucy 1999, Palomo and Gisbert, 2002). Population fluctuations are not known (Saucy 1999).FranceA recurring problem with accurately determining the full extent of water vole population decline is that the species has been poorly documented in the past, with older information on water vole population being anecdotal and patchy. For example, an atlas of mammals of France (1984, Société Française de l’Etude et Protection des Mammifères - SFEPM) mentioned no threat to the water vole, and reported a nation-wide distribution of the species, with the exception of Corsica, the North, North-East and the Alps. There were no national surveys on the water vole and the vole was not even mentioned in the Action Programme for wild fauna and flora, a wide-ranging survey published in 1996 by the French Ministry for the Environment. In contrast, over the last 10 years there has been increasing attention on the water vole, mainly owing to its apparent disappearance from many areas, a great cause for concern in a species with a normally high reproductive potential (3 to 4 litters per year, averaging 3.5 young per litter). These recent observations and studies all point to its rapid decline.SpainThe water vole has previously been little known and studied in Spain, yet it is probable that its numbers have suffered drastic declines in recent years, making it crucial to carry out further research and monitoring of the species (J. Román pers. comm., 2007). Experts in Spain seem to agree that the water vole is facing similar threats in the Iberian Peninsula as those in France (M. Delibes pers. comm., 2007). The water vole is not currently classified as a threatened species in any part of its range in the Iberian Peninsula, yet its subpopulations in this region exhibit a marked reduction, due to human-induced habitat degradation, destruction or modification, such as cementing over of riverbanks, canal-building, destruction of vegetation along waterways, draining of wetlands and water pollution (Álvarez, 1985; Garde, 1992).PortugalThe water vole faces a situation similar in Portugal to that confronting its subpopulations in France and Spain, though its status in this country is perhaps the least well-documented of the three. Research conducted in several locations in Portugal where the water vole is present leads to the conclusion that it is scarce and under threat principally from habitat disturbance and predation, as well as isolation of subpopulations owing to the scattered nature of suitable habitat in Portugal.","The water vole is almost always found near to water, preferring small (under 8 ha) freshwater lakes, ponds and slow-moving rivers and streams with dense riparian vegetation (Saucy 1999, Fedriani 2002). It sometimes occurs in drainage ditches and wet fields. Abundant hydrophilic vegetation and shorelines suitable for water vole burrowing activity seem to be essential characteristics of water vole habitat. Its diet consists mainly of aquatic plants, grasses, and herbs, although small animal prey are occasionally taken (insects, fish, tadpoles, freshwater shrimp). The burrows of the water vole typically have two entrances – one primary entrance above water level and one underwater entrance. The water vole is mainly active during the day, with two peaks in activity in late morning and early afternoon, as well some nocturnal activity. It is active throughout the year, with no period of hibernation.Reproduction occurs between March and October, with 3 to 4 litters of 2 to 8 young per litter, with the average reported as 3.5 to 6 young. The gestation period is 3 weeks. Sexual maturity is reached at 5 weeks old and the life span of the water vole varies from 2 to 4 years. The water vole lives in small family groups and, under optimal conditions, its density may reach 5 individuals for every 100 meters of riverbank (Saucy 1999, Palomo and Gisbert, 2002). There have never been any records of damage to human activity or agriculture by the water vole.","Since the water vole is restricted to wetland areas, it faces all the usual threats associated with this habitat. The water vole only flourishes where the banks and vegetation have not been significantly altered by human activity. Consequently, habitat loss and degradation (as a result of drainage, dredging, canal-building, infrastructure development, intensive agriculture, and so on) are major threats. Competition with the introduced Coypu and Muskrat for food and dens is also a threat. In Spain, water vole decline is attributed primarily to anthropogenic habitat modification, but competition from the Norway rat may be an additional factor threatening the water vole (Palomo and Gisbert 2002). Efforts to control invasive species by poisoning have resulted in accidental water vole deaths.In descending order of importance, the principal threats are:Secondary poisoning with anticoagulant rodenticides (Bromadiolone and Chlorophacinone) intended for the Norway Rat, Coypu and Muskrat, Competition for habitat and food sources with the Muskrat and Coypu,Predation by the American Mink, Polecat and Norway Rat, as well as domestic dogs and cats,Trapping and shooting of “vermin”,Habitat modification, including draining of suitable wetlands, dredging, canal-building, disturbance by human activity and livestock, etc.,Drastic variations in water level caused by dams or seasonal droughts,Pollution and possibly disease and parasites.","The water vole occurs in some protected areas within its range, although this does not particularly improve the status of this species (European Mammal Assessment Workshop 2006). As yet, the water vole receives no legal protection under EU legislation (Cabral et al. 2005), nor under national legislation in any of the three countries where it occurs. Further research and monitoring is urgently needed to supervise the population trend, and the aquatic habitats where the water vole occurs require protection.Nature et Humanisme and the SFEPM recommend the following methods for protecting the water vole (J.F. Noblet pers. comm.):-Prevention of the use of rodenticides in the habitats occupied by the water vole.Alternative methods of combating the proliferation of the Muskrat, Coypu and American Mink, by more selective means (live cage traps, etc.).-Forbidding the raising, import, transport or release of these three animals.-Legislative protection of the water vole, under Annexes I or II of the EU Habitats Directive, the Bern Convention, as well as in national legislation,Legislative protection of the water vole’s habitat. -Information campaigns directed at the concerned parties (local elected officials, waterway engineers, waterway management bodies, etc.).-Regulation of management techniques of water ways and their shores, such as forbidding dredging and paving of water vole habitat and destruction of riverside vegetation.-Forbidding destructive agricultural practices and associated water pollution.-International cooperation between France, Spain and Portugal in protecting the water vole and coordinating research in cross-border areas where the water vole may occur.-An ongoing research programme, in order to thoroughly map and monitor the remnant populations and their trends and to analyse the reasons for their ongoing decline.-A captive breeding programme and eventual reintroduction of the water vole in suitable protected habitat.","Rigaux, P., Vaslin, M., Noblet, J.F., Amori, G. & Palomo, L.J." +ANIMALIA,CHORDATA,MAMMALIA,RODENTIA,CRICETIDAE,Chionomys nivalis,,No,No,LC,,LC,,European regional assessment: Least Concern (LC)EU 25 regional assessment: Least Concern (LC)A common and widespread species with no major threats.,Possibly Favourable,"Chionomys nivalis has a global distribution extending from south-western Europe through south-eastern Europe to the Caucasus, Turkey, Israel, Lebanon, Syria and Iran (Shenbrot and Krasnov 2005). In Europe, it is restricted to mountainous and rocky areas, typically above 1,000 m and up to 4,700 m (Amori 1999). Its strongholds in Europe are in the Pyrenees, the Alps, the Apennines, the Carpathians and the mountains of the Balkan peninsula. Of the islands, it is found only on Euboea (Amori 1999).","It is locally common in at least parts of its range, and no declines have been recorded. Fluctuations in population density are not known to occur. Its distribution is naturally fragmented as subpopulations became isolated from each other when temperatures warmed at the end of the last ice age (Amori 1999).","It inhabits open, rocky areas, typically above the tree-line (Amori 1999). It has a herbivorous diet, feeding on grasses, shrubs, and berries (Krapp 1982).","In the northeastern part of the range the species occurs exclusively in rocky slopes. During the last two decades, these areas have been covered by enchroaching new forest as sheep grazing has declined (B. Kryštufek pers. comm. 2006). However, this is not though to be a serious threat to the species at present.","It is listed on Appendix III of the Bern Convention, and occurs within many protected areas within its range. In the Ukraine, the species is included in the Red Book of Ukraine.","Boris Kryštufek, Giovanni Amori" +ANIMALIA,CHORDATA,MAMMALIA,RODENTIA,CRICETIDAE,Cricetulus migratorius,,No,No,LC,,NA,,"European: Least Concern. The species has a large range in parts of eastern Europe and European Russia, within which it is widespread. The population size is not believed to approach the thresholds for the population size criterion of the IUCN Red List. Although there have been some range contractions within this region, presumably with concomitant population declines, these are not thought to approach the threshold for the population decline criterion of the IUCN Red List. EU 25: Not Applicable. In the EU, this species only occurs in Greece. Very little is known about the species' range and habitat requirements in this country, and there are no data on threats or population size. Only a very small proportion (less than 1%) of the grey hamster's range lies within the EU 25, thus it is classed as Not Applicable (NA) at the regional level.",-,"The present range of the grey hamster extends from eastern Europe through Russia and central Asia to Mongolia and western China. In the south, its distribution extends into Turkey, Israel, Syria, Iraq, Iran, Pakistan and Kashmir. In Europe, it is restricted to Greece, Turkish Thrace, Bulgaria, Romania, Moldova, Ukraine, and European Russia. It is recorded from sea level to 4,300 m in the Pamir mountains of central Asia (Vohralík 1999).","It is scarce and sporadic in the Balkans, although it may be more abundant elsewhere in its global range. Populations in Greece (very rare: known from less than ten collections), Bulgaria (very rare: only six records) and Turkish Thrace may be isolated (Nechay 2000). Its status is poorly known. There have been range contractions in some parts of Europe (EMA Workshop 2006).","It originally occurred in dry grasslands, steppes and semideserts. Now, it also inhabits agricultural land and gardens, sometimes even living in houses. Arid areas with relatively sparse vegetation are preferred, and forests and damp habitats are avoided (Vohralík 1999). It typically feeds on roots, shoots and seeds.","The species is rare, especially in the Balkans, and its requirements are not well known. It is not known why the species is not more widespread within Europe, given that it can use a variety of habitats.","Surveys are required to determine population status and trends, and research is needed to determine the species' requirements and investigate potential threats.","Boris Kryštufek, Igor Zagorodnyuk, Vladimir Vohralík" +ANIMALIA,CHORDATA,MAMMALIA,RODENTIA,CRICETIDAE,Cricetus cricetus,Populations west of the River Rhine are recognised as a separate subspecies (canescens) (Weinhold 1999).,No,No,LC,,LC,,"At the European and EU 25 levels the species is considered Least Concern. It has a very wide range and, although population declines are occuring in the western part of the range, it is stable elsewhere (including in a number of EU 25 countries).",Possibly Unfavourable,"Cricetus cricetus has a large global range, extending from western Europe, through central and eastern Europe, Russia, and Kazakhstan, reaching as far east as the Yenisey river (Asian Russia). In Europe, it occurs from Belgium, the Netherlands and northern France in the west to Russia in the east, and from northern Germany, Poland and Russia in the north to Bulgaria in the south (Panteleyev 1998, Weinhold 1999). It is found from sea level to 650 m (Nechay 2000).","It has undergone severe range and population declines in western and central Europe, and it now has a highly fragmented distribution in these areas. Subpopulation extinctions have occurred in a number of countries including Belgium, the Netherlands, France and Germany. Less is known about the status of the species in eastern Europe and Russia, but it is certainly more abundant there than in the west. Spring population densities of 0.5-3 individuals per hectare are reported in western Europe (Weinhold 1999), whereas densities of 3.4-37 occupied burrows per hectare have been recorded in Hungary (Nechay 2000). In Ukraine the species is considered abundant (I. Zagorodnyuk pers. comm. 2006). In areas where the species is abundant, periodic population outbreaks occur (Nechay 2000).","Its original habitat was fertile steppe and grassland, but it has successfully spread into a variety of anthropogenic habitats including meadows, croplands (especially cereals), and field edges, road verges and scrubby fallow areas on farms. In eastern parts of its range it is found quite often in gardens and orchards, in close proximity to human habitation. It is more abundant in these man-made habitats than it is in natural grassland. It prefers relatively deep, heavy soils, in which it digs extensive burrows. Its diet mainly consists of the green parts of plants and seeds, supplemented by invertebrates and, occasionally, small vertebrates. At high densities, it can be an agricultural pest (Nechay 2000).","Its decline in western Europe has been attributed to a combination of persecution and agricultural intensification. It was trapped and poisoned to prevent damage to crops, and this practice continues in some parts of the hamster's range (although not in the western part of its range). In eastern Europe it continues to be trapped for the fur trade. Agricultural intensification, specifically the loss of perennial crops and small uncultivated patches of land, the introduction of autumn-sown cereals, and the increased use of pesticides, has had a negative impact on many hamster populations. Changing agricultural practices in eastern Europe, where the hamster population has traditionally been considered stable, may pose a threat in the future.","It is listed on Appendix II of the Bern Convention and Annex IV of the EU Habitats and Species Directive. Specific conservation recommendations to improve the status of the species in western Europe are detailed in Stubbe and Stubbe (1998) and Nechay (2000). These focus on subsidising farmers to manage agricultural habitats appropriately, and minimising use of pesticides. In the last few years, reintroductions have been carried out in France, Belgium and the Netherlands. Monitoring is required in eastern range states to determine population trends.","Boris Kryštufek, Holger Meinig, Igor Zagorodnyuk, Vladimir Vohralík" +ANIMALIA,CHORDATA,MAMMALIA,RODENTIA,CRICETIDAE,Dicrostonyx torquatus,"Once believed to encompass most or all New World populations, but karyotypic and breeding evidence supports the strict application of D. torquatus for only Eurasian populations (see Wilson and Reeder 2005 and references therein).",No,No,LC,,NE,,"European regional assessment: Least Concern (LC)EU 25 regional assessment: Not Evaluated (NE)There are no major threats to the species which is common and abundant. Consequently it is classed as Least Concern. However, the collared lemming subspecies from Novaya Zemlya (Dicrostonyx torquatus ungulatus) is considered as Vulnerable under Russian nature conservation legislation (included in Red Book of Russian Federation since 1998).",-,"""Arctic and subarctic tundra and forest-tundra in the Palearctic, from White Sea, W Russia, to Chukotski Peninsula, NE Siberia, and Kamchatka; including Novaya Zemlya and New Siberian islands, Arctic Ocean"" (Wilson and Reeder 2005), but excluding Wrangel Island (Gromov and Erbaeva 1995, Pavlinov et al. 2002).",Common throughout the distributional area. Shows extreme cycles of abundance approximately every three years. Apparent population declines in the European part of the distribution area may have been the result of natural population fluctuation.,"Inhabits arctic and subarctic tundra and forest-tundra with small Salix spp. bushes. Lives in colonies with simple burrows along feeding routes; nesting and seed storage chambers used collectively. Activity is multiphase and may occur around the clock. Feeds on shoots and leaves of willows and birches, and vegetation and berries of cloudberry, great bilberry and other species. Litters 2-3 times a year with 5-6 young each time. A migratory species.","No major threats known at present, but climate change may threaten the species in the future.",The species occurs in several protected areas. The collared lemming subspecies from Novaya Zemlya (Dicrostonyx torquatus ungulatus) is considered as Vulnerable under Russian nature conservation legislation (included in Red Book of Russian Federation since 1998).,"Katerina Tsytsulina, Nikolai Formozov, Boris Sheftel" +ANIMALIA,CHORDATA,MAMMALIA,RODENTIA,CRICETIDAE,Dinaromys bogdanovi,"Molecular data suggests that this taxon might in fact consist of two (or more) species, although further research is required to confirm this (Kryštufek et al. 2007). Genetic and morphological data clearly indicate that the Balkan Snow Vole is composed of three historically isolated, independently evolving sets of populations, that can be regarded as evolutionary significant units (ESUs).",Yes,No,VU,"B2ab(i,ii,iv)",DD,,"Dinaromys bogdanovi is endemic to the Balkans area of the Mediterranean region. It is restricted to a specialised and fragmented habitat, and may be declining in parts of its range as a result of competition with the European snow vole. The area of occupancy is restricted, and is certainly less than 2,000 km² (B. Kryštufek pers. comm. 2007). Its range is severely fragmented due to the species' specialised habitat requirements and the range is shrinking. Listed as Vulnerable (VU B2ab(i,ii,iv)). Research is urgently needed to determine how serious a threat competition with the European snow vole is.Dinaromys bogdanovi consists of three historically isolated, independently evolving sets of populations, which can be regarded as evolutionary significant units (ESUs), and which are likely to constitute at least two separate species. If these were assessed separately, then it is extremely likely that one or more of them would qualify as Endangered or Critically Endangered under the IUCN Red List Criteria.",Unfavourable,"The Balkan snow vole is endemic to the Balkan states of Croatia, Bosnia and Herzegovina, Serbia, Montenegro, and western Macedonia. Its range is likely to extend into Albania and may include northern Greece, although there are no known records (Kryštufek 1999, Shenbrot and Krasnov 2005). It occurs from sea level to 2,200 m, but is typically found over 1,500 m and rarely much lower (Kryštufek 1999, B. Kryštufek pers. comm. 2006). It is the only living representative of its genus, and its range was restricted throughout prehistorical times.","Because it is restricted to karst limestone habitats, it has a naturally discontinuous distribution, and subpopulations are always small and isolated (B. Kryštufek pers. comm. 2006). The long-term population trend has not been quantified, but there is evidence to suggest that the species is declining in both population and range (Kryštufek et al. 2007). At the southernmost known site (on the Macedonia/Albania border) there have been no records of this species in the last 30 years, and the only records since then are of the European snow vole Chionomys nivalis (B. Kryštufek pers. comm. 2006). There are three distinct lineages within the population (Kryštufek et al. 2007). One of these, the north-western lineage, is of particular cause for concern: its range is excessively limited andhighly fragmented, with only 17 known localities that stretch along approximately 300 km of the Dinaric mountainrange; and its populations are invariably small and frequently highly isolated, with an extensive survey of its range often yielding only one individual in many of the sampling localities (Kryštufek et al. 2007).","It is found exclusively in rocky karst limestone areas, typically being found in stone-piles in meadows above the tree line, less often in rocky areas below the tree line. It has highly specific habitat requirements (Kryštufek et al. 2007). It eats grasses and herbs. The species' life history is slow compared to other Arvicoline rodents: longevity is up to four years, age at sexual maturity is two years, and the species has 1-2 litters per year (Petrov 1992, B. Kryštufek pers. comm. 2006).","It tends to inhabit isolated, inaccessible areas that are subject to little human disturbance. However, interspecific competition with another native rock-dwelling vole, Chionomys nivalis, may possibly pose a threat (Kryštufek 1999, Kryštufek et al. 2007). There has been no research and monitoring to determine whether this is a major threat, or whether this is occurring over a long time period - there is only anecdotal evidence from the southernmost locality (B. Kryštufek pers. comm. 2006).","The species occurs in several protected areas within its range. There is some national legislation in at least parts of its range. There is an urgent need to establish a long term monitoring program, and to determine the extent of competition with the European snow vole.","Kryštufek, B." +ANIMALIA,CHORDATA,MAMMALIA,RODENTIA,CRICETIDAE,Ellobius talpinus,"Up to four subspecies are recognized, but eastern forms need taxonomic revision (Gromov and Erbaeva 1995).",No,No,LC,,NE,,"European regional assessment: Least Concern (LC)EU 25 regional assessment: Not Evaluated (NE)This species has a wide range. Population size has not been quantified, but it is not believed to approach the thresholds for the population size criterion of the IUCN Red List (i.e. less than 10,000 mature individuals in conjunction with appropriate decline rates and subpopulation qualifiers), as the species is described as common in at least parts of its range. Although declines have been reported in some parts of the range, it is not believed to approach the threshold for the population decline criterion of the IUCN Red List (i.e. declining more than 30% in ten years or three generations). For these reasons, it is evaluated as Least Concern. However, in Ukraine this species is considered to be threatened.",-,"Steppe grassland and semi-deserts in SE Europe, Kazakhstan (except SE Kazakhstan) and Turkmenia. Sometimes found in forest-steppes.","Common throughout most of the range. In some parts it is abundant on cultivated lands, especially along forest belts, where one hectare could be inhabited by 15 family groups. In some parts in Russia and Kazakhstan it is a considerable pest. The population in Ukraine is fragmented and declining owing to cultivation of steppe areas. It has been extirpated from areas between Dnieper River and Lugansk region, and from the Dnieper to Crimea (I. Zagorodnyuk pers. comm. 2006).","A typical subterranean steppe mammal. Lives in large groups, digs complex burrows which may be inhabited by around ten animals. Colonies are very mobile. Burrow entrances usually sealed with soil. Feeds on subterranean plant parts. Nesting chambers (especially winter ones) and foraging chambers are usually about 4 meters underground. Seldom emerges above ground (usually only to clear soil from the burrow or to disperse, rarely for feeding). During dispersal could cover distances up to 800 meters. No real hibernation, but in winter as well as during summer heat and drought, activity declines significantly. During the warm period of the year gives birth to two litters with 2-3 young in each.","Cultivation of steppe habitat, fragmentation of social groups and populations.","As the species is abundant across most of the range and even sometimes a considerable agricultural pest, there have been no conservation measures in Russia and Kazakhstan. Ukrainian populations are severely fragmented and recently Ellobius talpinus was included in new edition of the Ukraine Red Data Book.",Katerina Tsytsulina and European Mammal Assessment team +ANIMALIA,CHORDATA,MAMMALIA,RODENTIA,CRICETIDAE,Lagurus lagurus,It is the only species in the genus Lagurus.,No,No,LC,,NE,,"European regional assessment: Least Concern (LC)EU 25 regional assessment: Not Evaluated (NE)This species has a wide range. Population size has not been quantified, but it is not believed to approach the thresholds for the population size criterion of the IUCN Red List (i.e. less than 10,000 mature individuals in conjunction with appropriate decline rates and subpopulation qualifiers), as the species is described as common in at least parts of its range. Although declines have been reported in some parts of the range, it is not believed to approach the threshold for the population decline criterion of the IUCN Red List (i.e. declining more than 30% in ten years or three generations). For these reasons, it is evaluated as Least Concern. However, in Ukraine this species is considered to be threatened.",-,"Distributed in plain and mountain steppes and semi-deserts in Eurasia from Dnepr River to Tuva and to Tien Shan in the south. Occurs from sea level to 2,800 m.","A typical steppe rodent. Very abundant at the beginning of the 20th century in Ukraine (Migulin 1938), but now restricted to easternmost regions. In Russia populations are fragmented, but the species remains a considerable pest of arable and pasture land. Declines in some populations may be related to climate change, specifically to increasingly moist conditions. Since the 1960s, irrigation and planting of trees to protect fields has changed the microclimate for this species.","Inhabits steppes and semi-deserts, where it forms large colonies that dig branched burrows extending over hundreds of square meters. Feeds on narrow-leaved cereals and absinths. Also consumes bulbs, tubers and sometimes insects. Breeds up to six times a year, with 5-6 young in each litter (maximum 14). Marked population fluctuations are a characteristic feature of this species; during population peaks it is nomadic.",Destruction and alteration of habitats by humans (including climate change); pesticides.,"It is an abundant species throughout most of the distribution area, but is listed as Critically Endangered in Ukraine where it partly inhabits protected areas.","Katerina Tsytsulina, Nikolai Formozov, Boris Sheftel, Igor Zagorodnyuk" +ANIMALIA,CHORDATA,MAMMALIA,RODENTIA,CRICETIDAE,Lemmus lemmus,,Yes,No,LC,,LC,,A common and widespread species with no major threats.,Possibly Favourable,"The Norway lemming is endemic to Norway, western and northern Sweden, northern Finland, and the Kola peninsula (Russia). It is found on at least some islands. During population outbreaks, it may migrate as far as the Baltic (Hansson 1999). The southern border of the range is not stable due to large migrations that occur occasionally.","It is a widespread and generally common species within much of its range, although populations undergo major fluctuations in density. The species declined in Sweden in the last decades of the 20th century, but it is thought to have remained stable in other parts of its range (Hansson 1999). It is typical for northern lemmings to have population booms every 20-30 years. In Sweden, intensive grazing was thought to be a problem for the species, but perceived population declines may have been a result of natural population fluctuation: long low phases are common for populations in Sweden, and some large populations have been found in Sweden in recent years (H. Henttonen pers. comm. 2006).","It inhabits a variety of alpine and subarctic habitats including peat bogs, dwarf shrub heaths, and sparsely-vegetated slopes and ridges. Habitat use varies seasonally: in summer it prefers very moist habitats, whereas in winter it must use other habitats as wet areas freeze. During mass outbreaks, it can be found in forests, farmland, and even on frozen lakes. Large numbers of migrating lemmings may accumulate next to rivers and lakes that bar their passage, and many drown attempting the crossing (Hansson 1999).","It has been speculated that heavy grazing by semi-domesticated reindeer may have a negative impact on the species' habitat in Sweden (Hansson 1999). Climate change may threaten the species in the future (Nowak 1999). At present, the species is not under major threat.",The species occurs in a number of protected areas. No specific conservation actions are recommended.,"Henttonen, H." +ANIMALIA,CHORDATA,MAMMALIA,RODENTIA,CRICETIDAE,Lemmus sibiricus,"This species was formerly broadly defined to encompass not only most Palearctic forms but also North American populations now considered to be a separate species, L. trimucronatus (Wilson and Reeder 2005). Now three subspecies are recognised: L. s. sibiricus Kerr, 1792 (found in most of the distribution area), L. s. novosibiricus Vinogradov, 1924 (endemic to New Siberia Island) and L. s. portenkoi Tchernyavsky, 1967 (endemic to Wrangel Island).",No,No,LC,,NE,,European regional assessment: Least Concern (LC)EU 25 regional assessment: Not Evaluated (NE)A common and widespread species with no major threats. Classed as Least Concern.,-,Distributed across the Palaearctic tundra zone from the White Sea to Kolyma (Russian Federation); also found on New Siberia Island and Wrangel Island.,A widespread and common species; has marked population cycles with periodicity of 3-4 years.,"An abundant species in tundra habitats. Populations reach maximum densities in lowland tundra with substantial moss and sedge cover. Also distributed in wetlands on shrubby tundra foothills, and in wetlands at the edge of the forest zone (Arkhangelsk, Northern Urals, Gyda peninsula, Taimyr). Lives in burrows, forming large colonies. Digs its own burrow, or occupies existing burrows of other species. In winter makes tunnels under snow cover and builds large spherical nests. Feeds on sedges, cotton-grass, green mosses and various shrubs. Reproductive peak starts in June and ends in August, however, during periods of low population density reproduction is extended and starts immediately after snowmelt. Animals that have overwintered die off by the end of the following breeding season. During summer produces 4-5 litters with 5-6 young in each. Like Lemmus lemmus, this species has large population fluctuations with a 3-4 year cycle; however, migrations are less pronounced. In summer dispersal occurs and preferred foraging habitat changes.",There are no major threats to this species known at present. Climate change may be a problem in the future.,The species occurs in several protected areas.,"Katerina Tsytsulina, Nikolai Formozov, Boris Sheftel" +ANIMALIA,CHORDATA,MAMMALIA,RODENTIA,CRICETIDAE,Mesocricetus newtoni,,Yes,No,NT,,NE,,"The species has a restricted range, but its extent of occurrence is greater than 20,000 km². The area of occupancy is not known, but is suspected to approach the 2,000 km² threshold for Vulnerable. The species is adversely affected by agricultural intensification, and is inferred to be decreasing, although there are no quantitative data on population trend. Consequently it is assessed as Near Threatened. If new information shows that the area of occupancy is below 2,000 km², uplisting to Vulnerable (criterion B2) should be considered. However, if the population trend is conclusively determined to be stable, downlisting to Least Concern may be warranted.",-,"Mesocricetus newtoni is a European endemic. It is restricted to lowlands (up to 460 m) along the right bank of the lower Danube river in northern Bulgaria and Romania, Dobrudja (Vohralík 1999). Its extent of occurrence is small (<50,000 km2), but its area of occupancy is unknown.","It is uncommon throughout its small range. Population densities fluctuate, but outbreaks are localised and infrequent. Long-term population trends have not been quantified but are believed to be declining. In Romania, the population was estimated at around 3,000 mature individuals (Murariu 1995).","It is found in relatively dry habitats including barren, rocky steppe and steppe grassland, Medicago, Taraxacum and cereal fields, vineyards, gardens, and scrubby slopes (Vohralík 1999). Its diet is probably similar to that of other hamster species.","The main threat is habitat loss and degradation as a result of intensive agriculture. The agricultural utilisation of abandoned fields and steppe-like habitat is very likely to have a negative impact on the species (V. Vohralik pers. comm. 2006), although the species does inhabit some anthropogenic habitats. In Dobrudja intensive agriculture is ongoing (I. Coroiu pers. comm. 2006), and agricultural intensification may have increased since the accession of Romania to the European Union.","It is listed on Appendix II of the Bern Convention. Monitoring is required to determine population trends in this poorly-known species; if there is evidence of declines, appropriate conservation measures should be instated (Nechay 2000). The species is included on the Red Lists of Romania and Bulgaria, and is protected by Romanian legislation.","Coroiu, I. & Vohralík, V." +ANIMALIA,CHORDATA,MAMMALIA,RODENTIA,CRICETIDAE,Microtus agrestis,Molecular evidence suggests this may be two species (Jaarola and Searle 2002).,No,No,LC,,LC,,European regional assessment: Least Concern (LC)EU 25 regional assessment: Least Concern (LC)A widespread and common species with no major threats.,Possibly Favourable,"The field vole is a widespread Palaearctic species, ranging from western Europe eastwards through Russia to Lake Baikal in south-east Siberia. In Europe, it is present in Great Britain and western, central and northern parts of the continent, but absent from Iceland, Ireland and southern Europe (Zima 1999, Shenbrot and Krasnov 2005). It occurs from sea level to 2,100 m in the Alps (Spitzenberger 2002).","It is generally common, although it may be locally rare in marginal parts of its range in western and central Europe. In some areas, population density fluctuates markedly over a cycle of approximately three to four years. In peak years it can cause damage to pastures, orchards and forestry plantations (Zima 1999).","It occurs in a wide range of habitats including grasslands, woods, upland heaths, dunes, marshes, peat-bogs and river-banks, tending to prefer damp areas. It occurs in a number of anthropogenic habitats including meadows, field-margins and young forestry plantations, but is absent from heavily grazed areas (Zima 1999). The field vole is predominantly herbivorous, feeding on grasses and herbaceous plants, and gnawing bark in the winter. Exceptionally, animal prey (e.g. dipteran larvae) are taken (Krapp and Niethammer 1982).",There appear to be no major threats to this species over much of its range.,The species is present in a large number of protected areas throughout its wide range. No specific conservation measures are required.,"Boris Kryštufek, Vladimir Vohralík, Jan Zima, Igor Zagorodnyuk" +ANIMALIA,CHORDATA,MAMMALIA,RODENTIA,CRICETIDAE,Microtus arvalis,The species consists of two allopatric chromosomal races (“arvalis” and “obscurus”: Wilson and Reeder 2005).,No,No,LC,,LC,,European regional assessment: Least Concern (LC)EU 25 regional assessment: Least Concern (LC)This is a widespread and common species with no known major threats.,Possibly Favourable,"Microtus arvalis has a large range extending from Spain across much of western, central and eastern Europe to the Middle East and central Russia (Shenbrot and Krasnov 2005). Isolated populations exist in Iberia, Guernsey and the Orkney Islands. It is absent from much of southern Europe, Fennoscandia, northern Russia, Iceland and the British Isles (with the exception of the Orkney Islands, where it was introduced prehistorically). The species occurs from sea level to 2,600 m (Spitzenberger 2002).","It is a common species throughout much of its range, with population densities of over 1,000 individuals per ha reported in peak years. Population densities may fluctuate markedly from year to year. In most areas, populations are apparently stable, although the Orkney subspecies Microtus arvalis orcadensis has declined in recent years (Macdonald and Tattersall 2001).","It is typically found in dry, open habitats such as natural alpine grassland above the timber line (Spitzenberger 2002), grazed pastures, arable land, field margins and meadows. Wet grassland and tall grasses are avoided. It feeds mainly on the green parts of grasses and herbaceous plants, and is a serious agricultural pest in some areas (Zima 1999).",The decline on Orkney has been attributed to land-use changes (Macdonald and Tattersall 2001). Elsewhere it is not under threat.,"The species is present in many protected areas. It is often considered a pest as it damages crops. On Orkney, despite recent declines the vole remains abundant, and simulation modelling suggests that the population is likely to remain viable without requiring specific conservation measures (Macdonald and Tattersall 2001).",Giovanni Amori +ANIMALIA,CHORDATA,MAMMALIA,RODENTIA,CRICETIDAE,Microtus bavaricus,"Microtus bavaricus is part of Microtus multiplex species-complex. Its formerly continuous range in the Alps was split into three parts during the last glaciation which led to the evolution of three species: Microtus liechtensteini (south of the Alps east of the river Adige and Balkan mountains), Microtus multiplex (south of the Alps west of the river Adige), and M. bavaricus (north of the Alps in a small refuge in Bavaria and Northern Tyrol) (Haring et al. 2000, Spitzenberger et al. 2000, Spitzenberger 2002, Musser and Carleton 2005, Martinkova et al. 2007).",Yes,No,CR,B1ab(iii)+2ab(iii),CR,B1ab(iii)+2ab(iii),"This species is restricted to one location, which is severely fragmented and under threat from habitat loss. There are confirmed extinctions of populations in Germany, and good certainty that the species is restricted to the one known location. There remains some doubt about the validity of this population as a distinct species, but current research indicates that it is valid.",Unfavourable,"Microtus bavaricus is endemic to the Northeastern Alps. Previously it was known from only one location in the district of Garmisch-Partenkirchen, Bavaria, Germany. The last record of the species at this site was in 1962. A population discovered in Northern Tyrol, Austria in 1976/1977 was much later (2000) assigned to Microtus bavaricus based on genetic and karyological analysis (Haring et al. 2000, Spitzenberger et al. 2000). This population was confirmed to exist there still in 2004. Genetic and karyological analyses of both captured individuals and museum specimens have confirmed that the Austrian population belongs to Microtus bavaricus (Haring et al. 2000, Spitzenberger et al. 2000, Martínkova et al. 2007). Intensive surveys in Germany have failed to find the species, and both of the former known sites have been lost (one as a result of urbanization, the other due to deforestation and the replacement of natural vegetation with fertilized pasture)(H. Meinig pers. comm. 2006). The species is now known only from Rofan Mountain, Northern Tyrol, Austria where it occurs in altitudes between 730 and 1,100 metres a.s.l. Given the extensive surveys that have been carried out, the species is unlikely to be found elsewhere (F. Spitzenberger pers. comm. 2006).",Fewer than 50 individuals have been collected (F. Spitzenberger pers. comm. 2006).,"The original site was in an area of Alpine meadows. However, the species was rediscovered in an open mixed forest dominated by spruce with abundant brooks (F. Spitzenberger pers. comm. 2006).","Habitat at the type locality was lost following the construction of a hospital. The forests in which M. bavaricus lives in Northern Tyrol were used probably since medieval times as cattle pasture. This practice stopped in 2005, when in parts of the valleys the forest was replaced by fertilized and fenced cattle pastures. Through this M. bavaricus lost large parts of its known habitat. Habitat loss is expected to go on, as the open forests will become denser through lack of cattle browsing and intensification of forestry practices (F. Spitzenberger pers. comm. 2006).","The single site at which the species is known to occur is not protected, although the species has been legally protected under the local Tyrolean provincial law since 2006. There is no current national or EU legislation, but the species is strictly protected under Appendix II of the Bern Convention. There are currently no management plans in place (F. Spitzenberger pers. comm. 2006). Recommended conservation actions include the following: conduct surveys to determine the size and distribution of the rediscovered population; continue searching similar sites in the German and Austrian Alps to look for other populations; protect habitat at the rediscovery site.","Spitzenberger, F., Zima, J., Meinig, H. & Vohralík, V." +ANIMALIA,CHORDATA,MAMMALIA,RODENTIA,CRICETIDAE,Microtus brachycercus,"The validity of this species needs to be confirmed (Wilson and Reeder 2005, G. Amori pers. comm. 2006).",Yes,Yes,LC,,LC,,"The distribution of this species is not well known, and there is continued work on its taxonomic validity. It is probably common and not declining, so there is no reason to think that with further information this species would qualify as threatened. Therefore listed as Least Concern.",Possibly Favourable,"This species is known from southern Italy, Calabrian Peninsula, Camigliatello Silano (Wilson and Reeder 2005). Genetic data also indicates that the species occurs in Abruzzo region of central Italy (Castiglia et al. 2008; G. Amori pers. comm. 2006). The distribution limits between M. savii and M. brachycercus require clarification.","Like Microtus savii, to which it it closely related (indeed perhaps conspecific), it is likely to be widespread and abundant within its range, with a stable population trend (G. Amori in litt. 2006).","It is found in the majority of terrestrial habitat types, with the exception of high mountains, dense woodlands, and some very sandy, rocky or wet areas. It occurs in many anthropogenic habitats including pastures, arable land, gardens, and urban areas.",No major threats are known.,The species is found in protected areas. Research is required to clarify the taxonomy of this species.,"Amori, G." +ANIMALIA,CHORDATA,MAMMALIA,RODENTIA,CRICETIDAE,Microtus cabrerae,Its phylogenetic position was studied by Jaarola et al. (2004).,Yes,Yes,NT,,NT,,"This species has an area of occupancy that is small and potentially in decline (Pita et al. 2007). If the area of occupancy is measured based on 2x2 km grid squares (as recommended in the Red List Guidelines), the area of occupancy is likely to exceed 2,000 km2, but potentially not by much. Assessed as Near Threatened under criterion B2.",Unfavourable,"Microtus cabrerae is endemic to the Iberian peninsula (Portugal and Spain), where it has a fragmented range (Palomo 1999, Shenbrot and Krasnov 2005). It occurs from 0 to 1,500 m, although it is most common below 1,200 m (Palomo and Gisbert 2002, R. Pita unpublished data).In Spain, populations in the south have recently disappeared (Muñoz, L.J.P. pers. comm.2007).","Many subpopulations are small, fragmented, and subject to major inter-annual fluctuations (Palomo and Gisbert 2002, Mira et al. 2005). Subfossil remains have been found outside the species' current distribution, suggesting a range contraction (Palomo 1999), and it is considered that the species occupies a relict distribution (Palomo and Gisbert 2002). Population densities are moderate by comparison with other arvicoline rodents, typically varying between 17 and 350 individuals per hectare (Palomo and Gisbert 2002). The species is often found in isolated patches inhabited by a few individuals, often an adult couple and its offspring.","It occurs in pastures, fields and open clearings in woodland, tending to prefer damper areas than the common vole. It is often found in proximity to water (Palomo 1999) and on road verges (Santos et al. 2006, Pita et al. 2006). Meadows and perennial grassland communities are the most favourable microhabitats for this species (Santos et al. 2005).","Agricultural intensification, including overgrazing, has presumably contributed to range contractions and fragmentation over the last few decades (Palomo 1999). There is increased pressure on streams and other wetland areas the species occurs in. There is suspicion that interspecific competition with Arvicola sapidus may be a problem (Pita et al. 2006).",The species occurs in protected areas in both Portugal and Spain. It is protected under the Bern Convention (Appendix II) and the EU Habitats and Species Directive (Annex II and Annex IV).,"Fernandes, M., Pita, R. & Mira, A." +ANIMALIA,CHORDATA,MAMMALIA,RODENTIA,CRICETIDAE,Microtus duodecimcostatus,,Yes,Yes,LC,,LC,,"A common species, which is considered an agricultural pest across its range.",Possibly Favourable,"Endemic to the western Mediterranean, where it occurs in the Iberian Peninsula (everywhere except the north-west) and southern France (Shenbrot and Krasnov 2005). It is found from sea level to 2,250 m (Palomo 1999).","It is widely distributed throughout its geographic range, and can reach high enough densities in some areas to be considered an agricultural pest (particularly in orchards). Population densities of 400-600 individuals per ha exceptionally have been recorded, but lower densities are more typical (le Louarn and Quéré 2003).","It occurs in open habitats with relatively deep, loose soil, where it constructs underground burrows (Palomo 1999). It occurs in a number of anthropogenic habitats, including pastures, arable land, and orchards. It is also found in shrubland (le Louarn and Quéré 2003).","Pest control can cause very significant local population declines (Palomo 1999). However, there is no evidence of global declines as a result of this.",It occurs in a number of protected areas across its range.,"Aulagnier, S. & Palomo, L.J." +ANIMALIA,CHORDATA,MAMMALIA,RODENTIA,CRICETIDAE,Microtus felteni,"Formerly considered a subspecies of Microtus savii, but now regarded as a separate species (Wilson and Reeder 2005)",Yes,Yes,DD,,DD,,"The species is endemic to the Mediterranean region and is restricted to a relatively small area. It is naturally rare, and there is some indications of shrinkage in the southern parts of its range; in Greece the species is certainly declining, perhaps by as much as 20-25% over the last ten years. However nothing is known of the status of populations in the northern parts of its range. There is a need for more information on the species' population, habitat requirements and ecology, therefore currently assessed as Data Deficient.",Unknown,"Microtus felteni occurs in southern Serbia, F. Y. R. Macedonia, Albania and northern Greece (Shenbrot and Krasnov 2005), where it has been recorded from 360-2,050 m (Kryštufek 1999). The species occurs in a relatively narrow range.",It is a little-known and rare species throughout its relatively small range. Population trends are not known. There is some evidence of range shrinkage in the south of its range indicating population declines (Greece) (C. Stamatopoulos unpublished data). The species has been rarely collected and is known from only around fifteen localities.,"It is primarily known from mountain forests, although it is very occasionally found on arable farmland at lower altitudes (Kryštufek 1999). This species is poorly known, but is likely to have a broad habitat tolerance (B. Kryštufek and V. Vohralík pers. comm. 2006).",No major threats are known. The species is not likely to be affected significantly by habitat loss (B. Kryštufek and V. Vohralík pers. comm. 2006).,"Some of the known records are from protected areas. Research on population status and trends, habitat requirements and ecology are required.","Mitsain, G. & Kryštufek, B." +ANIMALIA,CHORDATA,MAMMALIA,RODENTIA,CRICETIDAE,Microtus gerbei,"Some authors consider Microtus pyrenaicus a synonym of Microtus gerbei, although there is debate about which name is appropriate (Musser and Carleton 2005).",Yes,No,LC,,LC,,"A common species within its range, particularly in western areas. No major threats.",Possibly Favourable,"Microtus gerbei is endemic to the western Mediterranean, where it occurs in northern Spain and western and central France (Shenbrot and Krasnov 2005). It occurs from sea level up to 2,000 m in the Pyrenees (Palomo 1999).","It is locally abundant in at least parts of its range, reaching densities of up to 100 individuals per hectare (Palomo 1999). It is most abundant in western France (S. Aulagnier pers. comm. 2006).","At lower altitudes, it is found in pastures and arable land, whereas in the mountains it inhabits grassland and rocky woodland edges. Relatively cool (15º - 16º annual medium temperature) and dry areas are preferred (Palomo and Gisbert 2002). It is a fossorial species, although it burrows less in mountainous areas (Palomo 1999).",No major threats are known.,Occurs in some protected areas. No specific conservation measures required.,"Aulagnier, S. & Palomo, L.J." +ANIMALIA,CHORDATA,MAMMALIA,RODENTIA,CRICETIDAE,Microtus gregalis,"The only representative of the subgenus Stenocranius. Complex subspecies structure with 11-15 subspecies. Taking into consideration fragmented range and morphological variation, Microtus gregalis probably represents a complex of closely related species. Taxonomic revision is necessary.",No,Yes,LC,,NE,,European regional assessment: Least Concern (LC)EU 25 regional assessment: Not Evaluated (NE)A widespread and abundant species with no major threats.,-,"Distributed in several separated regions: in tundra and forest-tundra from White Sea to Kolyma River; in Alaska peninsula; in steppes of Kazakhstan, Kyrgizia, SW Siberia, Yakutia, Mongolia and Northern China. It occurs at altitudes of up to 4,000 m.",Populations undergo fluctuations in density; in mountainous areas populations are patchy and density varies.,"Inhabits tundra, plains and mountain steppes and meadows. In the forest zone (including mountain forests) and semideserts it occupies open grassy areas. It reaches maximum density in cereal and grass steppes, and alpine and water meadows. Lives in groups, during periods of high population density may form colonies. Feeds on various wild and cultivated plants, tends to prefer legumes. Reproductive period lasts throughout the warmer months of the year; in tundra zones reproduction often starts under snow cover (in Karsk tundra in February-March). Has up to 5 litters per year in southern parts of the range, and up to 4 in mountains and northern areas. Litter size is usually up to 12 young. Considerable pest of crops in Siberia and Kazakhstan and pastures in Central Asia. A natural carrier of several diseases including encephalitis, plague and rabbit fever.",There are no major threats to the species.,The species occurs in several protected areas.,"Katerina Tsytsulina, Nikolai Formozov, Boris Sheftel" +ANIMALIA,CHORDATA,MAMMALIA,RODENTIA,CRICETIDAE,Microtus guentheri,,No,No,LC,,LC,,"European regional assessment: Least Concern (LC)EU 25 regional assessment: Least Concern (LC)A widespread and common species with no major threats. It is tolerant of a range of habitat types, both natural and man-made.",Possibly Favourable,"Microtus guentheri is restricted to the south-east Balkans and Turkey and Northern Libya. Within Europe, it has a discontinuous range in southern Serbia (Serbia and Montenegro), F. Y. R. Macedonia, parts of southern and eastern Greece, southern Bulgaria, and Turkish Thrace, and has been recorded from 150 m to 500 m above sea level (Kryštufek 1999, Shenbrot and Krasnov 2005).","In Europe, it occurs in scattered subpopulations which often undergo large fluctuations with steep declines. However, local extinctions have not been recorded. The species is considered locally common in parts of the Balkans. In Asiatic Turkey, very high population densities have been recorded in peak years (Kryštufek 1999).",It inhabits dry grasslands with sparse vegetation on well drained soil. These include both natural and man-made habitats (e.g. dry meadows and pastures) (Kryštufek 1999).,No major threats.,"A lowland species, therefore across most of its range it does not occur in protected areas. In some parts, however, it does occur in protected areas (for example in Greece). No conservation measures are required - this species is considered an agricultural pest.","Boris Sheftel, Vladimir Vohralík" +ANIMALIA,CHORDATA,MAMMALIA,RODENTIA,CRICETIDAE,Microtus levis,"Synonyms include M. rossiaemeridionalis, M. subarvalis and M. epiroticus (Wilson and Reeder 2005).",No,No,LC,,LC,,"European regional assessment: Least Concern (LC)EU 25 regional assessment: Least Concern (LC)A widespread and common species, tolerant of a wide range of habitat types. No major threats are known. Consequently it is classed as Least Concern.",Possibly Favourable,"Microtus levis has a large range extending from east and south-east Europe eastwards across Russia and Asia Minor to Lake Baikal in Siberia. It has been introduced to the Svalbard (Zima 1999, Shenbrot and Krasnov 2005). In Europe, its range includes the Balkan peninsula, Ukraine, Belarus, the Baltic and southern Finland. A lowland species, it is recorded from 60 m to 1,100 m (Petrov and Ružić 1982).","It is a relatively common species. Population densities fluctuate on an annual basis, and peak densities of as high as 200,000 burrow openings per hectare have been recorded in F. Y. R. Macedonia (Zima 1999).","It occurs in a range of habitats including farmland, meadows, and open woodland. In southern parts of its range it tends to occur in damp habitats in close proximity to rivers and lakes (Zima 1999).",No major threats are known.,It occurs in protected areas throughout its range. No specific conservation actions are needed.,"Igor Zagorodnyuk, Heikki Henttonen, Boris Kryštufek" +ANIMALIA,CHORDATA,MAMMALIA,RODENTIA,CRICETIDAE,Microtus liechtensteini,"This species is closely related to Microtus multiplex, and has been previously considered synonymous (Wilson and Reeder 2005).",Yes,No,LC,,LC,,"This species is relatively widespread, with a presumed large population, no major threats, and no known declines. It is listed as Least Concern.",Unknown,"Endemic to Europe, where it occurs in Austria, eastern Italy, Slovenia, Bosnia, and Croatia. In Austria, it is found in two isolated localities and also found along the Italian and Slovenian border (Spitzenberger 2002). Its altitudinal range is from sea level to 1,700 m (B. Kryštufek pers. comm. 2006). One record for Serbia (B. Kryštufek pers. comm. 2007)","It is locally common in at least parts of its range, and there is no evidence of population decline (Kryštufek 1999).","It inhabits pastures, meadows, open woodland and woodland clearings, preferring open areas with dense herbaceous vegetation to mature forest. In the high mountains it is also found in dwarf pine Pinus mugo, and in the coastal lowlands it occurs dry meadows, vineyards, and hedgerows (Kryštufek 1999).","There are no major threats to this species. It is sometimes considered a pest, and is controlled through poisoning.",This species is found in protected areas. No specific conservation actions are recommended.,"Spitzenberger, F., Amori, G., Hutterer, R., Kryštufek, B., Yigit, N., Mitsain, G. & Palomo, L.J." +ANIMALIA,CHORDATA,MAMMALIA,RODENTIA,CRICETIDAE,Microtus lusitanicus,,Yes,No,LC,,LC,,"This species is relatively widespread, with a presumed large global population, no major threats, and no known declines. It is listed as Least Concern.",Unknown,"Microtus lusitanicus is endemic to Europe, where it occurs in central and northern Portugal, northwest Spain, and in the extreme south west of France. It has been recorded from sea level to 2,050 m (Palomo 1999, Mira and Mathias in Palomo and Gisbert 2002, Shenbrot and Krasnov 2005, S. Aulagnier pers. comm. 2006).","It is very abundant, and is considered an agricultural pest in orchards in some parts of its range. Population densities appear relatively constant, with no cyclic fluctuations. In Spain, there have been no studies on population dynamics in natural habitats, but in orchards population densities of 100-200 individuals per hectare are typical (and exceptionally densities greater than 300 individuals per hectare have been recorded) (Palomo and Gisbert 2002).","It is found in a diverse range of habitat types, including natural habitats (borders of small rivers, chestnut and oak woodland) and agricultural areas (pastures, arable land, rice fields, and orchards). It requires soft and humid soils with dense vegetal cover, where it constructs its burrows. It is often found near to small stone walls (Palomo 1999, Palomo and Gisbert 2002). There are 2.2 young per litter (le Louarn and Quéré 2003).",There are no major threats to the species. Pest control measures can cause local population declines (Palomo 1999).,It occurs in a number of protected areas within its range. No specific conservation measures are recommended.,"Aulagnier, S., Amori, G., Hutterer, R., Kryštufek, B., Yigit, N., Mitsain, G. & Palomo, L.J." +ANIMALIA,CHORDATA,MAMMALIA,RODENTIA,CRICETIDAE,Microtus middendorffii,This taxon is sometimes considered to include M. hyperboreus (Pavlinov et al. 2002).,No,Yes,NA,,NE,,"European regional assessment: Not Applicable (NA)EU 25 regional assessment: Not Evaluated (NE)A widespread and common species with no major threats. It is of marginal occurrence in Europe, and consequently is assessed as Not Applicable.",-,Arctic and subarctic waterlogged tundra from the Ural Mountains to the Kolyma lowlands (Russian Federation).,"Data on population size are lacking, but as in most rodent species populations fluctuate. Severe springs may cause population reduction; heavy rains and floods cause short-distance migrations.","Inhabits waterlogged tundra, sedge and Sphagnum marshes, waterlogged banks; avoids anthropogenic landscapes. Lives in colonies with shallow burrows in dry areas. Nest chambers are usually sited on hillocks, on the ground, or on shrub branches. The species feeds on sedges, leaves and stalks in summer and roots in winter. Reproduction occurs from May to August, in favourable years from March til October. Females that have overwintered give birth to up to 3 litters per year. In the Urals fecundity is lower than in Yakutia.",There are no major threats to this species.,This species occurs in several protected areas.,"Katerina Tsytsulina, Nikolai Formozov, Boris Sheftel" +ANIMALIA,CHORDATA,MAMMALIA,RODENTIA,CRICETIDAE,Microtus multiplex,"Eastern populations are now considered as a separate species, M. liechtensteini (Wilson and Reeder 2005).",Yes,No,LC,,LC,,"This species is relatively widespread, with a presumed large global population, no major threats, and no known declines. It is listed as Least Concern.",Possibly Favourable,"Microtus multiplex is endemic to Europe, where it occurs in the southern part of the Alps, from southeast France through Switzerland to northern Italy (Shenbrot and Krasnov 2005). It has been recorded from sea level to 2,800 m (Hausser 1995, Kryštufek 1999). Populations further east (e.g. in Austria, eastern Italy, Slovenia, Bosnia, and Croatia) are now referred to as a separate species, Microtus liechtensteini (Spitzenberger 2002, Wilson and Reeder 2005).","It is locally common in at least parts of its range, and there is no evidence of population decline. The local abundance can be high, up to 100 individuals per hectare in southern France (le Louarn and Quéré 2003).","It inhabits pastures, meadows, open woodland and woodland clearings, preferring open areas with dense herbaceous vegetation to mature forest. In the high mountains it is also found in dwarf pine Pinus mugo, and in the coastal lowlands it occurs in dry meadows, vineyards, and hedgerows (Hausser 1995). The species eats roots and bulbs, and can feed on grasses (le Louarn and Quéré 2003). The number of young averages 2.7 in Switzerland (Salvioni 1986).","There are no major threats to this species. It is sometimes considered a pest, and is controlled through poisoning (Kryštufek 1999).",This species occurs in protected areas within its range. No specific conservation measures are recommended.,"Aulagnier, S., Amori, G., Hutterer, R., Kryštufek, B., Yigit, N., Mitsain, G. & Muñoz, L.J.P." +ANIMALIA,CHORDATA,MAMMALIA,RODENTIA,CRICETIDAE,Microtus oeconomus,Small isolated subpopulations are considered separate subspecies (e.g. Netherlands and the Pannonian population).,No,No,LC,,LC,,"European regional assessment: Least Concern (LC)EU 25 regional assessment: Least Concern (LC)Globally, the species is common and widespread and is not considered threatened. In southern parts of the species' range in Europe isolated populations are declining. The species is naturally fragmented. Population decline is due to habitat degradation and loss. In central Europe decline is considered serious, however in Baltic countries the population is increasing and expanding. Overall in Europe the species is not considered threatened. However, isolated subspecies (arenicola and mehelyi) are declining at a rate that may be high enough to merit a threatened assessment.",Possibly Favourable,"Microtus oeconomus is a Holarctic species, with a wide range extending from north-west Europe in the west to Alaska in the East. In Europe, its main range extends from eastern Germany and northern Fennoscandia through Poland, Belarus, and northern and central European Russia. Isolated relict populations are found in the Netherlands, southern Scandinavia, the Finnish coast, and Austria, Slovakia and Hungary (van Apeldoorn 1999, Shenbrot and Krasnov 2005). A lowland species (occurs up to at least 1,300 m: EMA Workshop 2006).","Range and population declines are evident in parts of Europe, although the species is stable or increasing in other areas. The species' range is contracting along its south-west edge in Poland, and relict populations in Hungary, Austria, Slovakia and the Netherlands are diminishing (van Apeldoorn 1999). In other areas, populations are stable (albeit with cyclic fluctuations in Fennoscandia and central Europe), and in Lithuania the population is increasing and expanding into new areas (van Apeldoorn 1999, L. Balciauskas and R. Juškaitis pers. comm. 2006).","It typically inhabits damp, densely-vegetated areas, in close proximity to water. Wet meadows, bogs, fens, riverbanks and flooded shores are all important habitats (Tast 1982, van Apeldoorn 1999).","In the Netherlands, population declines have been attributed to a combination of habitat degradation and competitive exclusion (van Apeldoorn 1999). The population in Slovakia has shown population declines which are attributed to habitat destruction caused by the construction of the Danube River Dam (EMA Workshop 2006). Degradation of wetlands due to agricultural expansion is a further threat.","It is listed on Appendix III of the Bern Convention. Subspecies arenicola (from the Netherlands) is listed on Annex II of the EU Habitats and Species Directive, and both M. oe. arenicola and M. oe. mehelyi (the latter from Austria, Hungary and Slovakia) are listed on Annex IV. Recommended conservation measures include conducting surveys to determine the size and distribution of the isolated population, and defining management plans to maintain and improve the habitat (F. Spitzenberger pers. comm. 2006)","Rimvydas Juškaitis, Boris Sheftel, Holger Meinig, Giovanni Amori, Heikki Henttonen" +ANIMALIA,CHORDATA,MAMMALIA,RODENTIA,CRICETIDAE,Microtus savii,,Yes,No,LC,,LC,,A widespread and abundant species with no major threats. The population trend is stable. It therefore is listed as Least Concern.,Possibly Favourable,"Microtus savii is endemic to Europe, where it is found throughout northern Italy (with the exception of the extreme north-east, but including Sicily). It occurs marginally in southern Switzerland. It occurs from sea level to 2,000 m. Some southern Italian populations previously ascribed to this species have been described as a new species, Microtus brachycercus (Contoli 1999, Castiglia et al. 2008). The distribution limits between M. savii and M. brachycercus require clarification.","It is a widespread and abundant species, dominating small mammal communities within its range, and providing a key food source for many predators. Periodic population booms occur in cultivated areas, and the species is considered an agricultural pest. The long-term population trend appears to be stable (Contoli 1999).","It is found in the majority of terrestrial habitat types, with the exception of high mountains, dense woodlands, and some very sandy, rocky or wet areas. It occurs in many anthropogenic habitats including pastures, arable land, gardens, and urban areas (Contoli 1999).",No major threats.,The species is found in protected areas. The Sicilian subspecies (nebrodensis) needs more genetic investigation to determine its taxonomic status.,"Amori, G." +ANIMALIA,CHORDATA,MAMMALIA,RODENTIA,CRICETIDAE,Microtus socialis,"Six or seven subspecies are recognized, some of those have isolated ranges and their taxonomic status might need revision.",No,Yes,LC,,NE,,"European regional assessment: Least Concern (LC)EU 25 regional assessment: Not Evaluated (NE)A widespread species with no major threats. However, several isolated populations in N Ossetia, Kalmykia and Astrakhan regions, Armenia, Syria and China might need special attention.",-,"""The species is distributed in plains and low mountain dry steppes from the Dnepr River and Crimea east to Lake Balkhash and NW Xinjiang in China, south through Caucasus and E half of Turkey (Kizilirmak River may be W boundary) to NW Syria, Lebanon (restricted to Mt Lebanon), N Iraq, and NW Iran"" (Wilson and Reeder 2005). The range is fragmented. All the isolated populations are represented by separate subspecies. In the European part of the range two subspecies are present: Microtus socialis nikolajevi Ognev, 1950 from left bank of Dnepr to the Crimea and SE Rostov district; Microtus socialis parvus Satunin, 1901 in cis-Caucasia, Stavropol region, Krasnodar Territory and Dagestan.","It is a common species with relatively stable populations, with some population fluctuation from year to year. Considered as one of the main pests in agricultural landscapes. However high population densities are recorded only in long-fallow lands, winter crops and herbs, and in natural sites with dry-steppe vegetation. Population peaks tend to occur in years with humid summers and repeated warm winters (Gromov and Erbaeva 1995).","Lives in complex colonies formed by polygynic families. Burrowes are complex, but shallow, with a number of entrances and living and storage chambers. Above-ground activity is limited, especially in summer. This species mainly feeds on cereals and legumes. In autumn seeds predominate in the diet. May occasionally feed on insects and molluscs. Reproduction occurs year round, females produce up to five litters with 6-8 young in each.","Widespread and abundant in the most of the range. However, several isolated populations (e.g. M.s. gorensis and M.s. astrachanensis) are declining because of desertification and landscape degradation due to overgrazing (Shilova 1995). These changes can be reversed through steppe vegetation restoration (Kasatkin et al. 1998).","There are no special conservation measures, however the species occurs in several protected areas.","Katerina Tsytsulina, Nikolai Formozov, Boris Sheftel, Igor Zagorodnyuk" +ANIMALIA,CHORDATA,MAMMALIA,RODENTIA,CRICETIDAE,Microtus subterraneus,,No,No,LC,,LC,,"European regional assessment: Least Concern (LC)EU 25 regional assessment: Least Concern (LC)A widespread and abundant species. It occupies a wide range of habitats, and faces no known major threats. The long-term population trend is thought to be stable. For these reasons it is assessed as Least Concern.",Possibly Favourable,"Microtus subterraneus occurs primarily in Europe, where it occupies central regions from the Atlantic coast of France to European Russia, and the Balkan peninsula. Isolated populations are found in Estonia and near St Petersburg, Russia. Outside Europe, its range extends into western Asia Minor (Turkey) (Shenbrot and Krasnov 2005). There are records of this species from sea level to 2,300 m (Kryštufek 1999).","It is widespread and common throughout most of its range. Despite fluctuations, the long-term population trend appears to be stable (Kryštufek 1999).","It is found in a broad range of habitats including broadleaf and coniferous woodlands, meadows and pastures, and rocky areas in the high mountains. It tolerates both dry and damp conditions (Kryštufek 1999).",No major threats.,It occurs in protected areas throughout its range. No specific conservation measures are needed.,"Boris Kryštufek, Vladimir Vohralík, Jan Zima, Igor Zagorodnyuk" +ANIMALIA,CHORDATA,MAMMALIA,RODENTIA,CRICETIDAE,Microtus tatricus,,Yes,No,LC,,LC,,"This species has a restricted range (area of occupancy less than 2,000 km²), but there is no evidence of population or range decline and the core range is protected. Currently considered Least Concern. However, if new information suggests that population, range, or habitat quality is declining, uplisting to Near Threatened or Vulnerable should be considered.",Possibly Favourable,"The Tatra vole is a European endemic. It is restricted to the Carpathian mountains of Slovakia, Poland, Romania and Ukraine, where it is found at altitudes of 650 to 2,350 m (Martínková and Dudich 2003, Shenbrot and Krasnov 2005). Its extent of occurrence is 18,322 km², and its area of occupancy is approximately 840 km2 (Martínková and Dudich 2003).","It is a rare species that occurs in isolated subpopulations. However, there is no evidence to suggest that range or numbers are decreasing at present. The total population has been estimated to number 200,000-250,000 individuals (Martínková and Dudich 2003), and is probably stable (N. Martínková pers. comm. 2006). There is very little information on the current status of subspecies M. t. zykovi in the Eastern and Southern Carpathians. Populations are severely fragmented. This is partly natural, as the species is restricted to an intrinsically fragmented habitat type (high mountains), but fragmentation may have been exacerbated by the loss of woodland in mountain valleys through human activities in historical times.","The Tatra vole is found in two types of habitat: first, humid areas in climax upper montane forest (usually located in inverse valleys); and second, humid rocky meadows in the subalpine zone. The species is never found outside natural habitats (e.g. in agricultural land). No population fluctuations or population outbreaks are known (Jurdíková et al. 2000, Martínková et al. 2004).","There are not thought to be any major threats causing significant declines at present. The species requires old, mature forests below the timberline, hence any logging in those areas would be harmful. Its habitat in the subalpine zone, above the timberline should be safe in the near future. Much of its range in the Slovak and Polish mountains falls within protected areas, and there are not thought to be any major developments planned in this area in the near future. However, forest habitat is sometimes lost through natural events (e.g. in 2004 a big storm in the High Tatras destroyed a large 1-2 km wide belt of forest at about 1,000 m above sea level, within the range of the vole: N. Martínková pers. comm. 2006).",It is listed on Appendix II of the Bern Convention. The core range of the species' range in Slovakia and Poland falls within protected areas. Habitat and population monitoring is required to ensure that the species is stable and not declining.,"Zima, J., Vohralík, V. & Martínková, N." +ANIMALIA,CHORDATA,MAMMALIA,RODENTIA,CRICETIDAE,Microtus thomasi,"Sometimes considered as a subspecies of M. duodecimcostatus, but its specific status has been reconfirmed by analysis of karyotype, molecular genetics and molar pattern (Kryštufek 1999, Jaarola et al. 2004). A chromosomally polymorphic species; relationships are unknown (Wilson and Reeder 2005).",Yes,No,LC,,LC,,"A common species within its range, with no major threats known. Appears to be tolerant of habitat disturbance. Consequently it is assessed as Least Concern.If one of the races within this species is eventually raised to species level its restricted range may merit a threatened listing. However, more work is necessary to determine its taxonomic status.",Possibly Favourable,"Microtus thomasi is endemic to the south-eastern Balkans, including Bosnia and Herzegovina, Montenegro, mainland Greece, and the island of Euboea (Greece) (Shenbrot and Krasnov 2005). Its occurrence in Albania has now been confirmed (E. Giagia pers comm. 2007). Occurs from sea level to 2,000 m.","It is sporadic, but is considered locally common in at least parts of its range. Densities of 383 individuals per hectare have been recorded in Herzegovina (Bosnia and Herzegovina) (Kryštufek 1999). In some parts of its range it is considered a pest.","It prefers open areas with deep soil, in which it digs extensive burrows. Recorded habitats include meadows and pastures on karst limestone, and high mountain pastures. It is also found on arable farmland (Kryštufek 1999).",No major threats.,Not legally protected under international legislation. Known to occur in protected areas within Greece.,"Kryštufek, B. & Mitsain, G." +ANIMALIA,CHORDATA,MAMMALIA,RODENTIA,CRICETIDAE,Myodes glareolus,Clethrionomys is a synonym of Myodes.,No,No,LC,,LC,,European regional assessment: Least Concern (LC)EU 25 regional assessment: Least Concern (LC)A widespread and common species with no major threats.,Possibly Favourable,"The bank vole has a wide range in the Palaearctic which stretches from the British Isles through continental Europe and Russia to Lake Baikal. In the north, its range extends beyond the Arctic circle, and in the south it reaches northern Turkey and northern Kazakhstan (Shenbrot and Krasnov 2005). It is widespread in Europe, although it is absent from southern Iberia and the Mediterranean islands. It is found from sea level to 2,400 m (Spitzenberger 1999).","It is very common throughout much of its European range, with typical densities varying between approximately 6-12 individuals per hectare and 50-100 individuals per hectare (Spitzenberger 1999). Populations densities fluctuate from year to year. The long-term trend appears stable.","It inhabits all kinds of woodland, preferring densely-vegetated clearings, woodland edge, and river and stream banks in forests. It is also found in scrub, parkland, and hedges (Viro and Niethammer 1982, Spitzenberger 1999).",There are no major threats to this species at present.,It occurs in a number of protected areas throughout its wide range. No specific conservation actions are recommended.,"Giovanni Amori, Heikki Henttonen, Vladimir Vohralík, Igor Zagorodnyuk, Jan Zima, Boris Kryštufek, Rimvydas Juškaitis, Holger Meinig, Sandro Bertolino" +ANIMALIA,CHORDATA,MAMMALIA,RODENTIA,CRICETIDAE,Myodes rufocanus,Clethrionomys is a synonym of Myodes.,No,No,LC,,LC,,"European regional assessment: Least Concern (LC)EU 25 regional assessment: Least Concern (LC)Common and widespread with no major threats. Although there have been some declines in north-western parts of the range, it is not considered to approach the threshold for the population decline criterion of the IUCN Red List (30% over 10 years or 3 generations). Consequently assessed as Least Concern.",Possibly Unfavourable,"The grey-sided vole has a large range in the northern Palaearctic, extending from northern Fennoscandia through northern Russia to the Pacific coast and the islands of Sakhalin, Hokkaido and Rishiri (Sulkava 1999). It ranges as far south as northern parts of Mongolia, China and the Korean peninsula (Wilson and Reeder 2005). It occurs from the coast to at least 1,170 m in northern Fennoscandia (Henttonen and Viitala 1982).","It is a common species in northern Fennoscandia. The long-term trend is stable with cyclic fluctuations every 4-5 years (Sulkava 1999). In northern Fennoscandia (Fennoscandian taiga) and northern Russia it was previously common, but there have been declines since the mid-1980s (H. Henttonen pers. comm. 2006).","It inhabits coniferous forests and birch forests, where it tends to prefer rocky areas, and is also found in dry peat-bogs and subarctic dwarf shrub heathland. It has a herbivorous diet, feeding on vegetative parts of grasses, herbs and dwarf shrubs, and on berries (Henttonen and Viitala 1982, Sulkava 1999). The species can sometimes be found in high densities in clear-cut areas, and is often found on plains (B. Sheftel pers. comm. 2006).",There are not thought to be any major threats to this species at present. Declines in Fennoscandia may be linked to changes in forestry practices (H. Henttonen pers. comm. 2006).,"It occurs in a number of protected areas within its wide range. The population trend should be monitored, particularly in the north-western part of the range.","Boris Sheftel, Heikki Henttonen" +ANIMALIA,CHORDATA,MAMMALIA,RODENTIA,CRICETIDAE,Myodes rutilus,Clethrionomys is a synonym of Myodes,No,No,LC,,LC,,"European regional assessment: Least Concern (LC)EU 25 regional assessment: Least Concern (LC)A common and widespread species. Although there may have been declines in some parts of its European range, it is not thought that these approach the thresholds for the IUCN Red List, even at the EU 25 level. Consequently it is assessed as Least Concern.",Unknown,"Myodes rutilus has a northern Holarctic distribution. It occurs in northern Fennoscandia, European Russia, Siberia, Sakhalin and Hokkaido islands (Japan), Alaska (USA) and Canada, at latitudes of 43-73 degrees north (Shenbrot and Krasnov 2005).","It is described as common in subarctic Fennoscandian birch woods. In northern parts of its European range, the long-term population trend is stable, with fluctuations on a 4-5 year cycle. In southern parts of its European range (e.g. in central Finland and Russian Karelia) the species is suspected to be declining (Sulkava 1999).","It is found in the subarctic birch forest zone and in northern parts of the boreal forest zone. It is more abundant in productive (eutrophic or mesotrophic) forests, with a dense understorey of grasses, herbs (especially Scrophulariaceae), or moss. It prefers mature old-growth forests and, unlike other Myodes species, it is absent from clear-felled areas (Sulkava 1999). It has a herbivorous diet, feeding on the green parts of grasses and herbaceous plants. In the autumn it stores seeds, especially of Scrophulariaceae (Sulkava 1999).","Suspected declines in southern parts of its European range have been attributed to increased clear-felling of old-growth spruce forest (Sulkava 1999, H. Henttonen pers. comm. 2006).","It receives no legal protection under international legislation. Occurs in a number of protected areas in its wide global range, including some in northern Fennoscandia.","Heikki Henttonen, Boris Sheftel" +ANIMALIA,CHORDATA,MAMMALIA,RODENTIA,CRICETIDAE,Myopus schisticolor,,No,No,LC,,LC,,"European regional assessment: Least Concern (LC)EU 25 regional assessment: Least Concern (LC)This species has a wide range. The population size has not been quantified, but it is not believed to approach the thresholds for the population size criterion of the IUCN Red List (i.e. less than 10,000 mature individuals in conjunction with appropriate decline rates and subpopulation qualifiers). Although there may have been some population declines as a result of logging, it is not believed to approach the threshold for the population decline criterion of the IUCN Red List (i.e. declining more than 30% in ten years or three generations). For these reasons, it is evaluated as Least Concern.",Unknown,"Myopus schisticolor has a wide distribution in the northern Palaearctic, ranging from western Norway, through Sweden and Finland through northern and central Russia to the Pacific coast and Sakhalin island (Russia) (Shenbrot and Krasnov 2005). It occurs at altitudes from 600 to 2,450 m (Nowak 1999).","Population densities in this species are typically very low, although infrequently there may be population irruptions and local migrations. Such events occured in northern Finland in 1910, 1957-58 and 1963 (Sulkava 1999). The sex ratio is female-biased (75% females : 25% males). In Fennoscandia local population declines may have occurred as a result of logging (Sulkava 1999, H. Henttonen pers. comm. 2006).","The species's main habitat is old spruce forest, where breeding tends to occur in areas with a abundant mosses (Pleurozium, Dicranum, and Hylocomium spp.), which provide a critical winter food source. In the summer, marshy areas within forests and pine-bogs with a high dwarf shrub layer are used, and in years of high population density dry forests and even clear-cuts may be occupied (Sulkava 1999). The species is found in the taiga and not above the treeline.","There are no major threats. The species may be locally affected by logging of old-growth spruce forest, its main habitat (H. Henttonen pers. comm. 2006).",The species is found in protected areas.,Heikki Henttonen +ANIMALIA,CHORDATA,MAMMALIA,RODENTIA,DIPODIDAE,Allactaga elater,Includes a number of subspecies distributed in a quite fragmented range. The last taxonomic revision was made by Shenbrot (1991).,No,No,LC,,NE,,"European regional assessment: Least Concern (LC)EU 25 regional assessment: Not Evaluated (NE)A common species across most of the range, however in its European range (North Caspian region) the population is declining owing to transformation of semideserts into steppes. At present, it is not believed that the rate of decline approaches the threshold for Criterion A (30% over 10 years or 3 generations), and the European population and range remain large enough that Criteria B-D do not apply. However, the situation should be monitored and regional reassesment might be required in the near future.",-,"Distributed in loamy and rubbly deserts, solonetzic and desertified steppes in SE Europe, N Caucasus and Transcaucasia through Kazakhstan and Central Asia to S Siberia, to NE Xinjiang, Nei Mongol, and N Gansu, China, and western Mongolia. Southern part of the range includes SW Pakistan, Afghanistan; Iran; E Turkey (Shenbrot et al. 1995, Wilson and Reeder 2005).","A common and abundant species across most of the range. The isolated population in northern Caspian Sea region is currently declining due to rapid transformation of the species' habitats. Population fluctuations are characteristic of this species, so in favourable years the population may increase even though the overall trend is of decline in the northern Caspian Sea region. Population density may fluctuate ninefold between different years (Shenbrot et al. 1995).","Inhabits various biotopes in deserts and semideserts, depending on soil and vegetation type. The species prefers sandy, rubbly and loamy soils, and is found on solonetzic deserts, but never inhabits real deserts. It prefers areas with a mixture of vegetation including shrubs. Avoids open spaces and dense vegetation (Shenbrot et al. 1995). Feeds on different herbs, seeds and insects. Solitary, active during dusk and at night. Lives in burrows with a length up to 2 m and depth up to 70 cm. Across most of its range hibernates for about four months (from mid-November to mid-March), but in Transcaucasia does not hibernate. Reproductive period starts after hibernation (in Transcaucasia in February). There are two reproductive peaks in April and in August-September. Produces 2-3 litters per year with 2-4 young per litter.",In the European part of the range it is not abundant and the population is declining due to rapid transformation of semideserts into steppes. Also land development reduces natural habitats and causes population decline.,"Up to now no special conservation measures have been taken, although the species occurs in several protected areas. The north Caspian population might need protection in the near future as natural habitats are declining.",Katerina Tsytsulina and European Mammal Assessment team +ANIMALIA,CHORDATA,MAMMALIA,RODENTIA,DIPODIDAE,Allactaga major,According to different views includes from 3 to 6 subspecies (Shenbrot 1991).,No,No,NT,,NE,,"European regional assessment: Near Threatened (NT)EU 25 regional assessment: Not Evaluated (NE)The species is rapidly declining in northern parts of its European range, and has even recently gone extinct in some areas (e.g. Moscow district). Considered Vulnerable according to the Red Data Book of Ukraine. Overall it is suspected that population declines in the European part of the range approach (and perhaps even exceed) 30% over the last 10 years. Consequently the species is assessed as Near Threatened at the European regional level. Monitoring is required. It is not known if there would be a significant rescue effect from populations outside the region, so the regional assessment is not adjusted.",-,"Distributed from forest-steppes to northern parts of deserts from Ukraine and European Russia through Kazakhstan and N Uzbekistan to W Siberia and W Xinjiang, China (Shenbrot et al. 1995, Wilson and Reeder 2005).","Widespread across most of its range, but distributed irregularly because of fragmentation of suitable habitats and human-caused landscape change. In Ukraine west of the Dnepr the species was common until the mid 1920s (Bilsky 1929), but there are no recent records of the species there (Shenbrot et al. 1995).","One of the most ecologically plastic jerboa species. Inhabits various habitats; in the northern part of the range the main limiting factor is grass density, and the species is restricted to areas with sparse vegetation. In steppe zone often inhabits roadsides, field edges, pastures and flat slopes of ravines. In deserts and semideserts occurs in all habitats except moving sands. Prefers areas with loamy soils, with absinth and succulent vegetation. Feeds on underground and green parts of plants, also on seeds and occasionally on insect and molluscs. Has three types of burrows: permanent summer and winter, and temporary. Enters hibernation in autumn with the first frost. Exits hibernation in March-April. Reproductive period is prolonged. Pregnant females may be found from March to July. During the reproductive period females may have two litters. Litter size ranges from 1 to 8 young, usually 3-6.","Declining very rapidly in the northern part of its range. Has disappeared from Moscow, Kursk regions. The main threat is land use change. The species needs large continuous habitats and fragmentation has strong impact on populations. In the Moscow region, habitat destruction due to building of dachas has caused the species to disappear.","The species is listed in the Moscow regional Red Data Book as Extinct in the Wild, but it is not listed in the Russian national Red Data Book due to abundance elsewhere in the range. In the Red Data Book of Ukraine it is listed as category II (abundant species with rapidly declining population).","Katerina Tsytsulina, Nikolai Formozov, Boris Sheftel, Igor Zagorodnyuk" +ANIMALIA,CHORDATA,MAMMALIA,RODENTIA,DIPODIDAE,Dipus sagitta,Dipus sagitta is only species in the genus Dipus. Eight subspecies are recognized; however there is a clear geographical cline in size and colouration from north to south.,No,No,NA,,NE,,"European regional assessment: Not Applicable (NA)EU 25 regional assessment: Not Evaluated (NE)The species is common throughout most of the range and is a pioneer species that is expanding its range in the Aral Sea area. However, pervasive changes to desert habitats are a major threat in the European part of the range. Populations near the Don River are listed in the local Red Data Book because of fragmentation of habitats due to the nature of sand dunes. As the European range is less than 1% of the global range, this species as classed as Not Applicable at the European regional level.",-,"Distributed in deserts and partly in semi-deserts from Don River sands (Russian Federation) to cis-Caspian region, Turkmenistan, Uzbekistan and N Iran and through Kazakhstan to Irtysh River, Tuva, Mongolia and China (Shenbrot et al. 1995).",A common species with weakly marked population fluctuations. In favourable years population density could reach 5-6 animals per hectare (Gromov and Erbaeva 1995).,"Inhabits different types of sand, however avoids large expanses of open sand-dunes. Also found in sand-dunes covered with pine forest. Most abundant in hilly and ridge sands, including those used as pastures. Often found together with Allactaga spp. One of the pioneer species that is occupying new habitats that have emerged as the Aral Sea dries out. In northern parts of the range it hibernates, while in southern parts it remains active throughout the year with the exception of extremely cold winters. Lives in burrows with length of about 5-6 m and depths up to 3 m; can also occupy burrows of Meriones major. In spring feeds on vegetative parts of grasses and shrubs, also eats roots and bulbs. When seeds start to ripen it switches its diet to seeds. During the whole year it takes insects and larvae as a usual part of its diet. The length of the reproductive period differs in northern and southern parts of the range: from 2 to 2.5 months in north to 8-9 months in south. The number of litters per year differs correspondingly, from 1 to 4 in differents parts of the range.","The species is common throughout most of the range and is a pioneer species that occupies opening sands in the Aral Sea area. However, pervasive changes to desert habitats are a major threat in the European part of the range. It is listed as threatened in the Don River region's local Red Data Book because of the fragmentation of its preferred habitat (sand dunes).",Populations near the Don river listed in the local Red Data Book. The species occurs in several protected areas.,"Katerina Tsytsulina, Nikolai Formozov, Boris Sheftel" +ANIMALIA,CHORDATA,MAMMALIA,RODENTIA,DIPODIDAE,Pygeretmus pumilio,,No,No,LC,,NE,,"European regional assessment: Least Concern (LC)EU 25 regional assessment: Not Evaluated (NE)This species has a wide range. Population size has not been quantified, but it is not believed to approach the thresholds for the population size criterion of the IUCN Red List (i.e. less than 10,000 mature individuals in conjunction with appropriate decline rates and subpopulation qualifiers), as the species is described as relatively abundant in at least parts of its range. Although some declines have been reported, it is not believed to approach the threshold for the population decline criterion of the IUCN Red List (i.e. declining more than 30% in ten years or three generations). For these reasons, it is evaluated as Least Concern. Nevertheless, this species depends on a very specific habitat type that is under threat from human activities and global warming. Its status should be monitored.",-,"Distributed in southern part of steppe zone, semi-deserts and deserts from the Don River (Russia) through Kazakhstan to the Irtysh River, south to NE Iran; E to S Mongolia; China: W Nei Mongol, N Xinjiang Gansu, and Ningxia (Shenbrot et al. 1995, Wilson and Reeder 2005). The range is consists of two large isolated parts, western and eastern (China and Mongolia) and several small isolated populations between those two parts and along the southern border of the range.","In some parts of the range (including parts of the European range) the species is relatively abundant and population number is stable. However, the whole range is fragmented and all the isolated populations in the east and south of the range are slowly declining and potentially vulnerable owing to the species' highly specialised habitat requirements.","Pygeretmus pumilio is a stenobiont species. It inhabits clay semi-deserts with rare vegetation which includes succulents of the family Haenopodiaceae (Salsola, Suaeda, Nanopphyton, Anabasis etc.). The clay proportion in the soil and type of vegetation determine species distribution (Shenbrot et al. 1995).",Populations are quite fragmented and its habitat is shrinking in parts of the range due to land use changes and climate change.,No specific conservation measures are known for this species. In the European part of the range occurs in several protected areas.,"Katerina Tsytsulina, Nikolai Formozov, Boris Sheftel" +ANIMALIA,CHORDATA,MAMMALIA,RODENTIA,DIPODIDAE,Sicista betulina,,No,No,LC,,LC,,"European: This species has a large range. The population size has not been quantified, but it is not believed to approach the thresholds for the population size criterion of the IUCN Red List (i.e. less than 10,000 mature individuals in conjunction with appropriate decline rates and subpopulation qualifiers), even though the species is rare in parts of its range. Population trends are poorly known, but it is not believed to approach the threshold for the population decline criterion of the IUCN Red List (i.e. declining more than 30% in ten years or three generations). For these reasons, it is evaluated as Least Concern.EU 25: In the EU the species is apparently rare, but it may be more common than currently known because it is difficult to trap. In many parts of the range it is fragmented, with many isolated subpopulations. It is currently listed as Least Concern, as it is not considered to approach the thresholds for any of the IUCN Red List criteria, but population monitoring is required.",Unknown,"Sicista betulina has a large range extending from Denmark, Norway and Austria in the west to Lake Baikal (Russia) in the east, and from the Arctic Circle south to the Carpathian Mountains (Panteleyev 1998, Pucek 1999). Records from the Ussuri region of China are considered dubious (Pucek 1999). In Europe, isolated relict populations occur in the Scandinavian peninsula, Denmark and Schleswig-Holstein (Germany), the Alps (Austria and Allgäu, Germany) and the Carpathians, but the main range extends east from Baltic Countries, Poland and the Czech Republic into European Russia (Pucek 1999, Syvertsen 2003). In Austria and adjacent Czech Republic (Bavarian-Bohemian forest) there is an isolated population. It occurs from sea level to 2,200 m in the eastern Alps (Spitzenberger 2002).","In western parts of the range it is generally a rare species, although it may be locally quite frequent. In south-eastern and eastern parts of the range (e.g. Russia, Ukraine) the species is very common. In western parts of the range there are a number of very small and isolated subpopulations, some of which are considered to be evolutionarily significant units (Meinig 2004). No cyclic fluctuations have been recorded, and interannual variation in population density is less than tenfold (Pucek 1999). In Romania, the population is estimated at approximately 1,000 individuals, and Rodna National Park has a very stable population (Botnariuc and Tatole 2005). In Finland it is considerd to be increasing (H. Henttonen pers. comm. 2006). Population trends elsewhere are not known. The species may often go unrecorded, as it is cryptic and hard to trap (Pucek 1982, Spitzenberger 2002).","The range of this birch mouse covers a variety of habitats including boreal and montane forests, subalpine meadows and tundra (Pucek 1999). In Romania, the species occurs in birch forest and pine forest with dense ground vegetation (I. Coroiu pers. comm. 2006). In Germany it occurs in alpine regions and forest bogs (H. Meinig pers. comm. 2006). It has been suggested that the species spends summer months in wet meadow habitat and moves to forests in winter (Nowak 1999). It hibernates in underground burrows for at least six months each year, losing up to half its weight during this time (Nowak 1999).","Agriculture may be a problem in the northern part of the species' range in Germany. In Romania, deforestation is the main threat. Elsewhere threats are not known.","It is listed on Appendix II of the Bern Convention and Annex IV of the EU Habitats & Species directive. It is legally protected under national legislation in a number of countries (e.g. Romania), and is included in national Red Lists of many range states (e.g. Germany, Denmark, Romania, Czech Republic, Lithuania). It occurs in a number of protected areas. Monitoring of populations is needed, especially at the western edge of the species' range.","Holger Meinig, Igor Zagorodnyuk, Heikki Henttonen, Jan Zima, Ioan Coroiu" +ANIMALIA,CHORDATA,MAMMALIA,RODENTIA,DIPODIDAE,Sicista severtzovi,"Formerly considered as a subspecies of Sicista subtilis, but now recognized as a separate species primarily on the basis of karyotype (Wilson and Reeder 2005 and references therein).",Yes,No,LC,,NE,,"This species is naturally scarce and has only a moderately large range, although its extent of occurrence does not approach the threshold for the range size criterion of the IUCN Red List. The population size has not been quantified, but it is not believed to approach the thresholds for the population size criterion of the IUCN Red List (i.e. less than 10,000 mature individuals in conjunction with appropriate decline rates and subpopulation qualifiers). Population trends have not been quantified, but there is no evidence to suggest significant declines. For these reasons, it is assessed as Least Concern.",-,"This species occurs in SW Russia and Ukraine (Shenbrot et al. 1995, Wilson and Reeder 2005).","There are no data on population size. The species is naturally not abundant, but there is no evidence of population decline.","The species is poorly studied, has a scattered distribution, and is solitary and naturally scarce across the whole range. Distributed in steppe and forest-steppe zones and associated with meadows with high grasses. Feeds on seeds and insects. Reproduces once a year, after hibernation.","The most significant threat to the species is habitat destruction, as the soil in its preferred habitats tends to be very good for cultivation.","No specific conservation measures apply to this species, however, it occurs in Tsentralno-Chernozemnyi State Reserve in Russia. Severtzov's birch mouse is listed in the Ukraine Red Data Book as a subspecies of Sicista subtilis under category III (rare but not threatened species).","Tsytsulina, K., Formozov, N., Zagorodnyuk, I. & Sheftel, B." +ANIMALIA,CHORDATA,MAMMALIA,RODENTIA,DIPODIDAE,Sicista strandi,Sibling species of Sicista betulina.,No,No,LC,,NE,,European regional assessment: Least Concern (LC)EU 25 regional assessment: Not Evaluated (NE)The European population of Sicista strandi is stable and quite widespread. Classed as Least Concern.,-,"Distributed in the area between Volga and Don Rivers, from Kursk District of S Russia to northern slopes of the Caucasus ridge (Shenbrot et al. 1995, Wilson and Reeder 2005). The western limit of the range is not clear, but probably lies along the Dnepr River (Shenbrot et al. 1995, I. Zagorodnyuk pers. comm. 2006).",There are no data on population size. Widespread but not especially common.,"Inhabits floodplain meadows in the southern part of forest zone, steppes, and forest-steppes in mountain zone. Solitary, feeds on seeds, berries and insects; reproduces once a year after hibernation.",Habitat destruction and fragmentation are occurring and reducing usable habitat.,"No special conservation measures apply to the species, although it occurs in several protected areas.","Katerina Tsytsulina, Nikolai Formozov, Boris Sheftel, Igor Zagorodnyuk" +ANIMALIA,CHORDATA,MAMMALIA,RODENTIA,DIPODIDAE,Sicista subtilis,,No,No,NT,,VU,B1ab(iii),"European: This species is considered Near Threatened (approaching A2c) at the European regional level. Population declines have not been quantified, but are inferred to be taking place as a result of loss of steppe habitat, and are suspected to approach 30% over 10 years. Range contraction has been observed.EU 25: VU B1ab(iii) There are no direct data on recent population declines. However, densities are very low and the range is severely fragmented. Steppe habitat is continuing to decline, and population declines are inferred from this, but rate of decline over the last ten years is not known. There are serious concerns about the status of this very rare species within the EU countries. Extent of Occurrence (as calculated by the 50 km squares the species occurs in) is within the threshold for Vulnerable (17,500 km²). Area of Occupancy is much smaller, possibly less than 2,000 km². Populations outside the EU countries are not close enough to be able to naturally rescue the regional population, therefore the assessment remains VU B1ab(iii).",Unfavourable,"Sicista subtilis has a continuous range extending from the Ukraine and the southern parts of Russia to the north western parts of China (Panteleyev 1998, Pucek 1999). Isolated populations are found in Hungary, Romania and Bulgaria (a single locality only) and southeast Poland. It formerly occurred in Austria but is now regionally extinct (last recorded here in 1960: Spitzenberger 2002). In Serbia it is known from only one locality. Its altitude in Austria was recorded from <120 m (Spitzenberger 2002) to 1,680 m (Pucek 1982).","In Europe it tends to be rare, although it is locally common in at least parts of its global range, accounting for 25% of all rodents caught in north Kazakhstan (Pucek 1999). Little is known about population trends in this species, but its extinction in Austria suggests that in Europe at least its range may be contracting. The species has disappeared from large tracts of its former range in Hungary (F. Spitzenberger pers. comm. 2006). In Romania, the population is estimated at 2,000 individuals (Popescu and Murariu 2001, Botnariuc and Tatole 2005).","It occurs in steppe, rough grassland and pasture, open woodlands, and in field margins and shelter belts on cultivated land (Pucek 1982, 1999). It tends to prefer more open habitats than the northern birch mouse Sicistica betulina.","The species is susceptible loss of steppe habitat. In Romania, habitat loss due to agriculture and indirect mortality through pesticide use are the major threats (I. Coroiu pers. comm. 2006). In Austria, Sicista subtilis occupied a very small and relict range. It went extinct as a result of the conversion of natural meadows adjacent to the reedbeds of Lake Neusiedl into improved grassland (Spitzenberger 2002).","It is listed on the Romanian Red List, and protected by national legislation. It receives strict legal protection under the Bern Convention (Appendix II).","Boris Kryštufek, Igor Zagorodnyuk, Giovanni Amori" +ANIMALIA,CHORDATA,MAMMALIA,RODENTIA,DIPODIDAE,Stylodipus telum,"Includes five subspecies, two of which are distributed in Europe: S.t. falz-feini Brauner, 1913 (lower reaches of left bank of Dnepr River) and S.t. turovi Heptner, 1934 (NE cis-Caucasia and lower Volga region).",No,No,LC,,NE,,"European regional assessment: Least Concern (LC)EU 25 regional assessment: Not Evaluated (NE)This species has a fairly large range in Europe (well above the Extent of Occurrence threshold for Criterion B). The population size has not been quantified, but it is not believed to approach the thresholds for the population size criterion of the IUCN Red List (i.e. less than 10,000 mature individuals in conjunction with appropriate decline rates and subpopulation qualifiers), as the species is described as abundant in at least parts of its range. Although there have been some population declines since the 1960s, it is not believed to approach the threshold for the population decline criterion of the IUCN Red List (i.e. declining more than 30% in ten years or three generations). For these reasons, it is evaluated as Least Concern. However, population trends need to be monitored.Ukrainian subspecies S. t. falz-feini has a restricted range (Extent of Occurrence c.8,000 km2), and its Area of Occupancy is fragmented and declining as a result of habitat loss and degradation. Consequently it qualifies as Vulnerable B1ab(ii,iii).",-,"Distributed in steppes and desertified steppes in E Ukraine, N Caucasus, W Turkmenistan, W Uzbekistan and Kazakhstan; E to N Xinjiang, China (Shenbrot et al. 1995, Wilson and Reeder 2005). The range is fragmented: besides the major part of the range from the Caspian Sea to China there are several isolated populations. The two isolated populations in the European part of the range are represented by two different subspecies, S. t. falz-feini and S. t. turovi.","Ukrainian subspecies S. t. falz-feini is naturally rare. It has a restricted range (Extent of Occurrence c.8,000 km2), and its Area of Occupancy is fragmented and declining as a result of habitat loss and degradation. The other European subspecies S. t. turovi is relatively common, and despite population decline since the 1960s it remains abundant in some parts of the area, e.g. Tsimlyansk.","Inhabits deserts and desertified steppes. In Europe it is usually distributed in hilly sands in river valleys, and arid areas, often with trees. Active at dusk and night. Enters hibernation with first frost. Lives in complex burrows, often occupies jird burrows. Feeds on seeds and partly on insects. Reproduction is once a year with litter size of 3-6 young.","Habitat loss due to ploughing and overgrazing, pesticides.",S. t. falz-feini is listed in the Red Data Book of Ukraine under category II (abundant species with rapidly declining population). S. t. turovi is listed in the local Red Data Book in Russia (Rostov District) as Data Deficient. The species is found in several protected areas.,"Katerina Tsytsulina, Nikolai Formozov, Boris Sheftel, Igor Zagorodnyuk" +ANIMALIA,CHORDATA,MAMMALIA,RODENTIA,GLIRIDAE,Dryomys nitedula,"The western subspecies intermedius is taxonomically not well defined, but occurs in the part of the range where the species is declining.",No,No,LC,,LC,,"European regional assessment: Least Concern (LC)EU 25 regional assessment: Least Concern (LC)A widespread species with a large global population. Population trends appear stable in most parts of its range, it has a broad habitat tolerance, and is found in many protected areas. Consequently it is classed as Least Concern.",Possibly Favourable,"Dryomys nitedula is found from Switzerland in the west through eastern and southern Europe, Asia Minor and the Caucasus to central Russia and central Asia, reaching as far as 90°E. Many isolated subpopulations occur on the edge of its range, including in Israel, central Iran, Afghanistan, the Tien Shan mountains and Sinkiang (China). In Europe, it occurs from eastern Switzerland through eastern Europe and the Balkan Peninsula to Latvia in the north and Russia in the east, with an isolated subpopulation in southern Italy (Kryštufek and Vohralik 1994). Its vertical range is from sea level to 2,300 m (Kryštufek 1999).","In Europe west of Russia it is generally rare, although in some southeastern areas (e.g. Bulgaria, Turkish Thrace, Moldova) it is locally common, reaching densities of 23-25 individuals per hectare in Moldova (Kryštufek 1999). At the western border of its distribution, populations have declined due to deforestation. There is only one population remaining in Switzerland (Tester and Müller 2000), and the German population has not been surveyed in over 30 years (H. Meinig pers. comm. 2006). However, there have been no reports of declines elsewhere as yet (Kryštufek 1999, EMA Workshop 2006).","It occurs in a broad variety of habitats in Europe, including broad-leaved, mixed, and coniferous woodland (mainly at higher altitudes), dwarf pine Pinus mugo and rocky areas, evergreen Mediterranean shrubland, and wood-steppe (Kryštufek 1999). In the west, the species is found in moist areas next to streams (Austria, Switzerland, and Germany). The species is not found in human dominated habitats such as agricultural areas.",There are no major threats in most parts of its range (EMA Workshop 2006). Declines at the western edge of its range have been attributed to deforestation (H. Meinig pers. comm. 2006),It is protected by international law under the Bern Convention (Appendix III) and the EU Habitats and Species Directive (Annex IV). The species is found in protected areas.,"Boris Kryštufek, Holger Meinig, Vladimir Vohralík, Rimvydas Juškaitis" +ANIMALIA,CHORDATA,MAMMALIA,RODENTIA,GLIRIDAE,Eliomys quercinus,,Yes,No,NT,,NT,,"Populations in the east have decreased significantly over the last 20-30 years, and the species may have disappeared from as much as 50% of its former range during the last 30 years. However, there is little information on the current decline rate. Since the western populations remain stable, the overall reduction over the last 10 years is almost certainly less than 30% (the threshold for Vulnerable under criterion A). However, as the species is suffering significant ongoing decline, the cause of which is not understood, it is listed as Near Threatened. The species has declined more than almost any other rodent in Europe.",Unfavourable,"Eliomys quercinus is endemic to Europe, where it was historically widespread from Portugal in the west to the Urals (Russia) in the east. It is now largely confined to western Europe, including numerous Mediterranean islands, with eastern populations having become scattered and fragmented. The focus of the species range in the region is in the west. It is a polytypic species, and some insular populations are distinctive forms (e.g., Balearic Islands). Its altitudinal range is from sea level to 2,000 m.","Population declines, range contractions and local extinctions have occurred in central, eastern and southern Europe over the last few decades. Some island populations are declining. The species is now rare in Estonia, Latvia, Lithuania (probably extinct: Juškaitis 2003), east Germany and the Czech Republic (Andera 1994) and adjacent Austria (Spitzenberger 2002), and has disappeared completely from the Slovakian part of the Carpathians and from the Croatian mainland. The last record in Romania is over 20 years old (I. Coroiu pers. comm. 2006). In the south of Spain, where it was formerly abundant and expanding, it is now rare (Ruiz and Roman 1999, Palomo and Gisbert 2002). In Portugal a decline in population is possible, although causes and magnitude of any such reduction are unknown (Cabral et al. 2005). Many of the declines were over the last 50 years or so, with some of the declines more recently recorded. The species may have been lost from over half of the range in the last 30 years (S. Bertolino pers. comm. 2006). In parts of its range where it is more abundant, population density is usually less than 10 individuals per hectare, though exceptionally densities of 30-50 individuals per hectare have been recorded (Filippucci 1999).","Its main habitat is woodland (coniferous, deciduous, and mixed), although it is sometimes found in orchards and gardens. It is less arboreal than some other dormice, and is often found on the ground in rocky areas, cracks in stone walls, and even in houses (Le Louarn and Spitz 1974, Vaterlaus 1998, Filippucci 1999, Spitzenberger 2002, Bertolino 2006).","It has been suggested that it is threatened in some areas (especially Corsica) by direct competition with the brown rat Rattus norvegicus (Macdonald and Barrett 1993). The populations from Germany eastwards are declining (H. Meinig pers. comm. 2006), but the reasons are not well known, although thought to be related to habitat changes. In some areas of orchards, the species is considered a pest.","It is listed on Appendix III of the Bern Convention. The species is found in many protected areas. There is a need to determine why the populations in the eastern part of the range are in decline, to monitor these populations, and to identify and implement appropriate conservation measures.","Bertolino, S., Amori, G., Henttonen, H., Zagorodnyuk, I., Zima, J., Juškaitis, R., Meinig, H. & Kryštufek, B." +ANIMALIA,CHORDATA,MAMMALIA,RODENTIA,GLIRIDAE,Glis glis,Was Myoxus glis but now transferred to Glis.,No,No,LC,,LC,,"European regional assessment: Least Concern (LC)EU 25 regional assessment: Least Concern (LC)A common and widespread species. Declines are occurring in the northernmost part of the range, but in the southern part it is abundant and considered a pest species. Consequently it is classed as Least Concern.",Unknown,"Glis glis has a global distribution that extends across Europe and through northern Turkey to northern Iran and the Caucasus. In Europe, it occurs from northern Spain through central and eastern Europe, as far as Latvia in the north and Italy and the Balkan Peninsula in the south (Kryštufek 1999). It is found on a number of Mediterranean islands, but the population in the British Isles is the result of an introduction in 1902 (Kryštufek 1999, Battersby 2005). It is recorded from sea level to 2,000 m.","In northern parts of its range it is scarce and may be declining, whereas in southern parts of its range it is sufficiently abundant to be considered an agricultural pest in years of high population density. In central Europe, typical population densities may be c.5 individuals per hectare, although densities of 20-22 individuals per hectare have been recorded (Kryštufek 1999).","It is typically found in mature deciduous and mixed woodland, where it frequents the canopy, although it also occurs in maquis and shrubland on rocky areas along the Mediterranean coast. Man-made habitats such as gardens and orchards are sometimes used, and the species often enters buildings (Macdonald and Barrett 1993, Kryštufek 1999).","In parts of its range, including Slovenia, Croatia, and Italy, there is a tradition of hunting this species. In the past, it was a source of meat, fat, and skins for subsistence and trade, but today it is hunted recreationally (Kryštufek 1999). The species is protected in Italy, but is sometimes illegally hunted (G. Amori pers. comm. 2006). In northeastern Europe, cutting of oak forests is a threat (Juškaitis 2003).",It is listed on Appenix III of the Bern Convention. It occurs in protected areas throught its range.,"Boris Kryštufek, Holger Meinig, Giovanni Amori, Rimvydas Juškaitis" +ANIMALIA,CHORDATA,MAMMALIA,RODENTIA,GLIRIDAE,Muscardinus avellanarius,,No,No,LC,,LC,,"European regional assessment: Least Concern (LC)EU 25 regional assessment: Least Concern (LC)This is a relatively common and widespread species across its range. However, in parts of its northern range (e.g. UK, Netherlands, Sweden, Germany, Denmark) populations are declining and fragmented as a result of habitat loss and fragmentation. In these areas there is cause for concern.",Unknown,"The common dormouse occurs in Europe and northern Asia Minor (Turkey). In continental Europe, it is fairly widespread, although it is absent from Iberia, south-west France, and northern parts of Fennoscandia and Russia. It is also absent from eastern Ukraine and southern Russia. Island populations occur in southern Britain and on Corfu and Sicily (Morris 1999, Rossolimo et al. (2001). In the Alps it occurs up to 1,920 m (Spitzenberger 2002).","Population trends vary in different parts of the range: in some areas it is declining, in others it is considered stable. In parts of its northern range (e.g., UK, Netherlands, Sweden, Germany, Denmark) populations are declining and fragmented as a result of habitat loss and fragmentation. However in Lithuania it is a common and widespread species, and no decline has been observed (Juškaitis 2003). Population densities may reach c.10 individuals per hectare in optimal habitat, but densities are significantly lower in less favourable habitats (Morris 1999).","It inhabits deciduous woodland, favouring forest edge, secondary growth, coppices, and other wooded areas with a dense shrubby understorey. It is also found in hedgerows in farmland. It is an arboreal feeder, foraging on flowers, insects and fruit.","In north-western parts of the species' range, habitat fragmentation as a result of forestry, urbanisation and agriculture is a major threat. It was formerly a popular pet in some parts of its range, but this is now illegal in many countries (Morris 1999).",It is listed on Appendix III of the Bern Convention and Annex IV of the EU Habitats and Species Directive. In many countries this species is included on national Red Lists.,"Boris Kryštufek, Holger Meinig, Rimvydas Juškaitis" +ANIMALIA,CHORDATA,MAMMALIA,RODENTIA,GLIRIDAE,Myomimus roachi,,No,No,EN,"B1ab(ii,iii)",DD,,"European: This species is found in a restricted area, there have been no recent records from European Turkey, the vast majority of the habitat is converted to agriculture, and the remaining areas are severely fragmented and subject to ongoing decline. Consequently it is classed as Endangered at the European level. Further research may show that the species qualifies as Critically Endangered under criterion A and/or B. EU 25: The species may marginally occur easternmost Greece. As the world population of this species is small, any population in Greece might constitute a significant (>1%) proportion of the global population. The species is assessed as Data Deficient at the EU 25 level, as its occurrence in the region is uncertain, but if it is confirmed to occur in Greece it is likely to qualify as Critically Endangered under Criterion B. The population outside the EU is fragmented and declining, so no rescue effect would be expected.",Unfavourable,The mouse-tailed dormouse is found in Bulgaria and Turkey (both European and Asian Turkey). It may also occur in eastern Greece. It is mainly a lowland species.,"Little is known about this restricted-range species. In Turkish Thrace there are only definite records from a small number of sites, and none of these records are recent: despite intensive searches, the species has not been found during the last five years (Global Mammal Assessment SW Asia workshop 2005). Throughout its distribution the vast majority of suitable habitat has been converted to intensive agriculture, and the species' range is severely fragmented and subject to ongoing losses (Global Mammal Assessment SW Asia workshop 2005).","It inhabits scrub and semi-open habitats with trees or bushes such as orchards, vineyards, hedgerows in arable land, and river banks. Although it is found in some extensively managed agricultural habitats, it is absent from intensively farmed areas. It is more terrestrial than other dormice, and its diet consists for the most part of seeds.","The range of this species is in decline. In European Turkey, most of its habitat has been transformed by agriculture. In spite of intensive searches the species has not been found over the last five years. It is clear that the range is shrinking.","It is listed on Appendices II and III of the Bern Convention. Surveys are needed to determine if and where the species can still be found, and sites where the species is found should be strictly protected.",Boris Kryštufek +ANIMALIA,CHORDATA,MAMMALIA,RODENTIA,HYSTRICIDAE,Hystrix cristata,,No,No,LC,,LC,,"Globally this species is very widespread, although it is a favoured food item for humans in many parts of its range, and there should be some investigation into harvest levels in these areas (e.g. north and west Africa). In Europe, the species occurs only in Italy where it has a relatively large population and an expanding range. Consequently it is classed as Least Concern at the European and EU 25 levels.",Possibly Favourable,"The crested porcupine is found in Italy, North Africa and sub-Saharan Africa. In Europe, it is restricted to mainland Italy and the island of Sicily, where it occurs from sea level to over 1,500 m. It is sometimes asserted that the porcupine was introduced to Italy by the Romans, but fossil and subfossil remains indicate its presence in Europe in the Upper Pleistocene (Amori and Angelici 1999).","In mainland Italy, population densities are increasing, and the species is expanding its range northwards. On Sicily, the porcupine is widespread, and the long-term population trend appears to be stable (Amori and Angelici 1999). Outside Europe, there is little published information on population trends, but there have been declines in at least some areas, probably as a result of persecution and exploitation for its meat and quills (Nowak 1999). The species may have been extirpated in Egypt since 1980, and has been extinct in heavily-settled parts of Uganda since the 1970s (Nowak 1999).","It inhabits dry Mediterranean shrubland, maquis, abandoned farmland, and dry rocky areas. Its den is in a deep burrow or a cave. Its diet consists of roots and tubers (including cultivated crops), bark, and fallen fruit (Nowak 1999, S. Lovari in litt. 2006).","Despite being strictly protected under international and domestic legislation in Europe, the porcupine is still illegally hunted for meat (often with dogs). This occurs both in Europe and Africa (G. Amori pers. comm. 2006). In parts of the range it is considered a pest species and it is sometimes illegally controlled with poison baits because of the damage it may do to crops (Macdonald and Barrett 1993), a practice which continues (G. Amori pers. comm. 2006). However, at present these are not thought to be major threats to the survival of the species in Europe.","It is strictly protected under Appendix II of the Bern Convention. It is listed on Annex IV of the EU Habitats and Species Directive, and has been protected under Italian national law since 1974.","Giovanni Amori, Sandro Bertolino, Sandro Lovari" +ANIMALIA,CHORDATA,MAMMALIA,RODENTIA,MURIDAE,Acomys minous,"A poorly defined species. Likely to be part of Acomys cahirinus but currently recognized as valid (see Barome et al. 2001, and Musser and Carleton 2005 for discussion).",Yes,Yes,DD,,DD,,"Data Deficient because of taxonomic issues. This taxon is likely to be conspecific with the widespread and common species Acomys cahirinus but more research is needed to confirm this. Even if this is a valid species, it is Least Concern on Crete because it is widespread there and not under threat at present.",Unknown,"Acomys minous is endemic to the island of Crete, Greece, where it occurs from sea level to 1,000 m (P. Lymperakis unpublished data). More taxonomic research is required to clarify whether A. minous is a valid species, or whether it should be considered as part of A. cahirinus. There is no fossil or subfossil record of Acomys species on Crete (Dieterlen 1978), suggesting that this taxon is the result of a relatively recent human introduction.","Little is known about the status and population trends of this species. It may be common in suitable habitats, and there are no reports of population declines (Zima 1999).","It is found in arid areas, including scrubby hillsides and rocky slopes. It may be found in close proximity to human habitation, and sometimes enters houses, especially during the winter. Its diet is predominantly herbivorous, supplemented by some animal items (Zima 1999).",It is not believed to face any major threats at present (B. Kryštufek pers. comm. 2006).,It occurs in a number of protected areas. Research is required to clarify its taxonomic status and determine population trends.,"Amori, G., Hutterer, R., Kryštufek, B., Yigit, N., Mitsain, G. & Palomo, L.J." +ANIMALIA,CHORDATA,MAMMALIA,RODENTIA,MURIDAE,Apodemus agrarius,,No,No,LC,,LC,,European regional assessment: Least Concern (LC)EU 25 regional assessment: Least Concern (LC)A common and widespread species with no major threats.,Possibly Favourable,"The striped field mouse has an extensive but disjunct range in the Palaearctic and Indomalayan regions, which is in two separate portions (Karaseva et al. 1992, Panteleyev 1998, Gliwicz and Kryštufek 1999). The first stretches from central and eastern Europe through Russia, Poland and the Caucasus, and northern parts of Kazakhstan and Kyrghyzstan to Lake Baikal (Russia). The second encompasses southern parts of the Russian Far East, China, the Korean peninsula, and Taiwan. It is predominantly a lowland species, although it has been recorded up to 1,750 m in southern Europe (e.g. Macedonia) (Gliwicz and Kryštufek 1999). In Czech Republic, Slovakia, Ukraine and Hungary, there has been a huge expansion of the species' range (V. Vohralík and I. Zagorodnyuk pers. comm. 2006), and it reached Austria in the late 1990s (Spitzenberger 1997).","A widespread and abundant species. Population densities fluctuate, producing sporadic population outbreaks, although such an event has not been recorded in central Europe for at least 30 years (Gliwicz and Kryštufek 1999). During years of peak density it is considered an agricultural pest. Its range in western Europe is expanding (Gliwicz and Kryštufek 1999, V. Vohralík and I. Zagorodnyuk pers. comm. 2006).","It is found in a range of habitats including woodland edge, grasslands, marshes, reedbeds, cornfields, pastures, gardens in rural and suburban areas, and green spaces in urban areas (Gliwicz and Kryštufek 1999). Moist habitats are preferred.",No major threats are known.,It occurs within protected areas throughout its range. It tends to be considered an agricultural pest species.,"Boris Kryštufek, Holger Meinig, Igor Zagarodnyuk, Vladimir Vohralík" +ANIMALIA,CHORDATA,MAMMALIA,RODENTIA,MURIDAE,Apodemus alpicola,,Yes,No,LC,,LC,,Locally common within its range with no major threats.,Unknown,"The Alpine mouse is endemic to the Alps (France, Switzerland, Germany, Italy and Austria), where it occurs from 550-2,100 m (Storch 1999, Spitzenberger 2002). It probably occurs in suitable habitat throughout the Alps, although records are patchy.",It is common in suitable habitats (Storch 1999).,"It typically occurs in montane woodland, where it favours areas with rocks and patches of grass (Storch 1999).",No major threats are known.,It occurs within protected areas in its range.,"Bertolino, S., Meinig, H. & Spitzenberger, F." +ANIMALIA,CHORDATA,MAMMALIA,RODENTIA,MURIDAE,Apodemus epimelas,A. mystacinus has been split into two separate species: A. mystacinus and A. epimelas (Wilson and Reeder 2005).,Yes,No,LC,,LC,,A common and widespread species with no major threats.,Possibly Favourable,"Apodemus epimelas is endemic to the western and southern Balkans, where it is found in Croatia, west Bosnia and Herzegovina, south Serbia and Montenegro, Albania, Macedonia, west Bulgaria and Greece. It is also found on the Adriatic islands of Korčula and Mljet (Storch 1999, Wilson and Reeder 2005). It occurs at altitudes from sea level to at least 1,600 m (Storch 1999).","It is abundant in suitable habitats, and European populations are presumably stable (Storch 1999).",It inhabits rocky areas with a sparse cover of grass or shrubs (Storch 1999).,No major threats.,It occurs within protected areas within its range.,"Kryštufek, B., Vohralík, V. & Mitsain, G." +ANIMALIA,CHORDATA,MAMMALIA,RODENTIA,MURIDAE,Apodemus flavicollis,"It is very probable that Apodemus ponticus and A. flavicollis are conspecific, and that their recognition as different species arose because the Cold War prevented comparison of populations on either side of the Iron Curtain (B. Kryštufek and V. Vohralik pers. comm. 2006). A. ponticus was reported by Russian authors from the Caucasus and Transcaucasia. Authors who studied Apodemus from north-easternmost Turkey (close to the Georgian border) did not find any difference between these populations and other Turkish populations of A. flavicollis (Frynta et al. 2001, Macholan et al. 2001, B. Kryštufek unpubl. data). Individuals captured on the Turkey-Georgia border formed fertile hybrids with A. flavicollis from Austria (Steiner 1978). Thus, the range of ponticus is arbitrarily defined by political borders: populations from the extreme NE Turkey (close to Georgian border) are classified as flavicollis, those across the border as ponticus. If the Asiatic phylogroup of A. flavicollis is indeed an independent species, than arianus predates all other names, including ponticus (B. Kryštufek pers. comm. 2006).",No,No,LC,,LC,,European regional assessment: Least Concern (LC)EU 25 regional assessment: Least Concern (LC)This is a common and widespread species with no major threats affecting the population at a global or regional level.,Possibly Favourable,"The yellow-necked mouse has a large range extending from Great Britain across much of continental Europe to the Urals (Russian Federation). It also found in parts of the Near and Middle East and the Caucasus (Montgomery 1999, Wilson and Reeder 2005). In Europe, it is generally widespread, although it is absent from southern Iberia, western France, northern and central Fennoscandia and Russia, and most islands (including Ireland). It is present on some east Mediterranean islands. Occurs from sea level up to 1,850 m (Spitzenberger 2002).",It is a common species throughout much of its range. Populations appear generally stable (natural fluctuations occur). Densities of more than 100 individuals per hectare have been recorded in eastern Europe (Montgomery 1999).,"It inhabits a variety of woodland habitats. It tends to be a forest edge species, but in the Alps it lives within forests (F. Spitzenberger in litt. 2006). Its spatial distribution in large forest areas is related to the productivity and spatial distribution of forest trees with heavy seeds, mainly oak and hazel (Juškaitis 2002).","Globally there are no major threats. In the UK, the species occupied a wider distribution in historic times and has undergone a range contraction associated with the conversion of ancient woodland to agricultural land (Battersby 2005).",It occurs in protected areas across its range. No specific conservation measures are recommended.,"Sandro Bertolino, Giovanni Amori, Heikki Henttonen, Igor Zagorodnyuk, Jan Zima, Boris Kryštufek, Rimvydas Juškaitis, Holger Meinig" +ANIMALIA,CHORDATA,MAMMALIA,RODENTIA,MURIDAE,Apodemus mystacinus,A. mystacinus has been split into two separate species: A. mystacinus and A. epimelas (Wilson and Reeder 2005).,No,No,LC,,LC,,"European regional assessment: Least Concern (LC)EU 25 regional assessment: Least Concern (LC)A widespread and abundant species within its global range. Although it has a restricted Extent of Occurrence in Europe (<20,000 km2), it is common in suitable habitats, with no evidence of decline and no major threats. For these reasons, it is evaluated as Least Concern.",Possibly Favourable,"Apodemus mystacinus occurs on some Aegean and Ionian islands eastward through Turkey to Israel, Lebanon, north-west Jordan, Syria, and northern Iraq (Wilson and Reeder 2005). It occurs from sea level up to 2,700 m.",It is abundant in suitable habitats. The population trend is stable (Storch 1999).,It inhabits forest with rocky areas with a sparse cover of grass or shrubs. Rocky areas are important for this species (Storch 1999).,No major threats.,It occurs in protected areas within its range. No specific conservation actions are recommended.,"Boris Kryštufek, Vladimir Vohralík" +ANIMALIA,CHORDATA,MAMMALIA,RODENTIA,MURIDAE,Apodemus sylvaticus,,No,No,LC,,LC,,European regional assessment: Least Concern (LC)EU 25 regional assessment: Least Concern (LC)This species is widespread and abundant across its large range. There are no major threats and no suspicion of declines. Consequently it is assessed as Least Concern.,Possibly Favourable,"The wood mouse has a large range that extends throughout Europe (with the exception of Finland and northern parts of Scandinavia, the Baltic and Russia) and parts of North Africa (Panteleyev 1998, Montgomery 1999, Wilson and Reeder 2005). It is present on the majority of offshore islands including the British Isles and Iceland. It occurs from sea level to 2,000 m.","It is widespread and abundant throughout much of its range, and populations appear to be stable. Population density may fluctuate more than tenfold between years of maximum and minimum abundance, but there are no regular cycles (Montgomery 1999).","It is a very adaptable species, inhabiting a wide variety of semi-natural habitats including all types of woodland, moorland, steppe, arid Mediterranean shrubland, and sand dunes. It is also found in many man-made habitats including suburban and urban parks, gardens and wasteland, pastures and arable fields, and forestry plantations. It has an omnivorous diet including seeds and invertebrates. Although it can cause occasional damage, it is not generally considered an agricultural pest (Montgomery 1999).","There are no major threats to this species, although pollution by lead and agrochemicals may have localized negative impacts.",It occurs in protected areas within its range. No specific conservation actions are needed.,"Boris Kryštufek, Holger Meinig, Vladimir Vohralík, Rimvydas Juškaitis, Heikki Henttonen, Igor Zagorodnyuk, Linas Balciauskas" +ANIMALIA,CHORDATA,MAMMALIA,RODENTIA,MURIDAE,Apodemus uralensis,This taxon is often confused with A. sylvaticus. It may be more than one species.,No,No,LC,,LC,,European regional assessment: Least Concern (LC)EU 25 regional assessment: Least Concern (LC)A common and widespread species with no major threats.,Possibly Favourable,"Apodemus uralensis occurs from central and eastern Europe through Russia, northern Anatolia and the Caucasus to central Asia (Panteleyev 1998, Storch 1999). In Europe, it occurs from the Carpathians and the Carpathian basin through southern Poland, Ukraine, and Belarus to the Baltic countries, extending south as far as Bulgaria. In Europe it occurs from sea level to at least 1,400 m in the Carpathians (Mošansky 1962).",Little is known about the status of this species. Its distribution is patchy in at least parts of its European range (Storch 1999).,"In Europe, it is found in a variety of habitats including arable fields, dry grassland, and humid woodland. In Lithuania, it is an ""ecotonic"" species, occurring where forests adjoin open habitat (meadows overgrown with shrubs, cornfields and fallow fields), and rarely found inside forests (Juškaitis 2003). In Anatolia and the Caucasus it tends to occur along streams and brooks in woods with a dense shrub layer (Storch 1999).",No major threats.,It occurs in protected areas within its range.,"Boris Kryštufek, Vladimir Vohralík, Linas Balciauskas" +ANIMALIA,CHORDATA,MAMMALIA,RODENTIA,MURIDAE,Apodemus witherbyi,,No,No,NA,,NA,,"European regional assessment: Not Applicable (NA)EU 25 regional assessment: Not Applicable (NA)Assessed as Not Applicable as it was considered to be of marginal occurrence in the European Mammal Assessment region. The limits of its range are poorly known, especially in the south and east. It is typically widespread and abundant in appropriate habitat, and it may more appropriately be assessed as Least Concern when the EMA is next revised.",-,"Occurs on Rhodes (Greece) and in S Ukraine. Also in N and S Caucasus, Anatolian Turkish steppe, south to N Israel and NW Jordan; through C and N Iran to Kopet-Dag Mountains of SW Turkmenistan and WC Pakistan. Probably also occurs in Iraq and Afghanistan (Wilson and Reeder 2005).",,"""Plains, mountain and plateau steppes, and highland semideserts"" (Wilson and Reeder 2005).",,,European Mammal Assessment team +ANIMALIA,CHORDATA,MAMMALIA,RODENTIA,MURIDAE,Meriones meridianus,"The taxonomy of this species needs revision. Several subspecies are recognised. M. (P.) m. dahli Schidlovski, 1962 is currently listed as a subspecies, but is probably an independent species (Gromov and Erbaeva 1995).",No,No,LC,,NE,,"European regional assessment: Least Concern (LC)EU 25 regional assessment: Not Evaluated (NE)A widespread species with no major threats. Assessed as Least Concern. Taxonomic revision is needed, and if Meriones (P.) meridianus dahli Schidlovski, 1962 from Transcaucasia is recognised as a separate species, the status of this form should be reassessed.",-,"Distributed in sand deserts in the western Caspian Sea region (Russian Federation), Kazakhstan, Central Asia, Iran, northern Afganistan, northern China and Mongolia.","It is a widespread and generally common species within much of its range, although populations undergo major fluctuations in density. Depending on winter weather conditions and the availability of essential fodder crops, density could fluctuate by ten times or more. Like other gerbil species, Meriones meridianus is a natural carrier of plague and other diseases. Population size in this species is monitored by plague control agencies.","Distributed in sand deserts, including fragmented alluvial and deluvial sands. Most abundant in hilly deserts and sandy areas with shrub cover, including small sand tracts in the steppe zone in the western part of the range. In spring and summer it is nocturnal, but in autumn (while foraging for winter) it remains active all day. Burrows are usually excavated under the roots of shrubs. Congregates in large colonies with pronounced social structure. Feeds mostly on seeds, sometimes on insects. Breeding period differs in northern and southern parts of the range. In northern parts it lasts from April til September, with two peaks in spring and autumn. In southern parts the reproductive period occurs from February or March til beginning of October, and in favourable conditions it may last throughout the year. Females that are at least a year old usually give birth to three litters per year; young females give birth once, rarely twice a year. Litter size is about 6 young.",There are no major threat to this species.,This species occurs in a number of protected areas in different parts of its range.,"Katerina Tsytsulina, Nikolai Formozov, Boris Sheftel" +ANIMALIA,CHORDATA,MAMMALIA,RODENTIA,MURIDAE,Meriones tamariscinus,Includes 4-5 subspecies.,No,No,LC,,NE,,European regional assessment: Least Concern (LC)EU 25 regional assessment: Not Evaluated (NE)An abundant species with no major threats. Classed as Least Concern.,-,"Distributed from cis-Caucasia through Kazakhstan to Tajikistan, Mongolia, and N Xinjiang and Nei Mongol regions of China (Gromov and Erbaeva 1995, Wilson and Reeder 2005).","It is a common species within much of its range, although populations undergo fluctuations in density every 2-3 years. Usually does not form colonies, but in Kazakhstan density could reach 30-50 individuals per hectare. A considerable pest of grain-crops, melons and gourds. In Central Asia population density considerably increases during the time of year when cereals ripen. Like other gerbil species it is a natural carrier of plague and other diseases agents. Population size is under observation of plague control services.","Inhabits shrubby thickets in flood-plains and forest belts (in Astrakhan semidesert); also oases and shrubby semi-deserts with some grass cover. In NW parts of the range it is expanding its range and occupying new lands that have appeared as the Caspian Sea has dried out; however, in the Aral Sea region the species's range has stayed the same despite the availability of new lands. Lives in family groups, occasionally forming small colonies without social structure. Besides seeds, a considerable proportion of its diet is made up of vegetative parts of plants. Reproduction starts in February to March (western parts of the range) or March to April (eastern parts of the range) and lasts for about six months. Breeding intensity decreases during hot months. Females that have overwintered usually give birth to three litters per year; young females generally start reproduction in June. Litter size is about 4-5 young.",No major threats to this species are known.,This species occurs in some protected areas.,"Katerina Tsytsulina, Nikolai Formozov, Boris Sheftel" +ANIMALIA,CHORDATA,MAMMALIA,RODENTIA,MURIDAE,Meriones tristrami,,No,No,NA,,NA,,European regional assessment: Not Applicable (NA)EU 25 regional assessment: Not Applicable (NA)Assessed as Not Applicable as it is of marginal occurrence in Europe.,-,"Occurs on the island of Kos (Greece); also in Asia Minor, the Middle East, Transcaucasia and northwestern Iran (Mitchell-Jones et al. 1999). Less than 1% of its global range lies within the European Mammal Assessment region.",One of the most common jirds throughout much of its global range.,Prefers deserts and dry steppes.,No major threats are known.,,European Mammal Assessment team +ANIMALIA,CHORDATA,MAMMALIA,RODENTIA,MURIDAE,Micromys minutus,,No,No,LC,,LC,,"European regional assessment: Least Concern (LC)EU 25 regional assessment: Least Concern (LC)Both globally and within Europe, the species is widespread and common. Although wetland habitat destruction is occurring in many places throughout its range, the species is highly tolerant of disturbed habitats and is not considered threatened at present.",Unknown,"The harvest mouse has a large range in the Palaearctic and Indomalayan regions, where it occurs from northern Spain and Great Britain through Europe, eastern Fennoscandia, and Russia to northern Mongolia, China, northeast India, Myanmar and Vietnam (Corbet 1978, Panteleyev 1998, Spitzenberger 1999). It is present in Japan and on the border between southern Sweden and south-east Norway, where it is regarded as possibly introduced (van der Kooij et al. 2001, Wilson and Reeder 2005, van der Kooij et al. in litt. 2006). In Europe, it is largely absent from Iberia, the southern part of Italy and the Alps, and it occurs only sporadically in the Balkans. It is typically a lowland species, although it occurs at altutudes of up to 1,700 m in Europe (Spitzenberger 1999).","Population declines have been noted in many parts of Europe. However, populations of this species fluctuate drastically, and some reported declines may in fact have been part of a natural fluctuation (Trout 1978, Haberl and Kryštufek 2003). The species is hard to trap and is often not recorded even when it is present (Haberl and Kryštufek 2003). However, nests may be found quite easily by experienced observers (R. Juškaitis, pers. comm. 2006).","It is found in wetlands, reedbeds, and clearings and edges of humid forest. It has also adapted to a variety of anthropogenic habitats, including gardens and arable land (in the wetter north-western parts of its range), drainage ditches, and rice paddies (Spitzenberger 1999). It has a high tolerance of disturbed habitats (Haberl and Kryštufek 2003).","In Europe the species is common in wetlands (e.g. rice fields) and other habitats (e.g. abandoned agricultural land). There are no serious threats to the survival of the species here, although local population declines have occurred in some areas as a result of loss and degradation of wetland habitats (Spitzenberger 1999).",It occurs in protected areas within its range.,"Boris Kryštufek, Holger Meinig, Heikki Henttonen" +ANIMALIA,CHORDATA,MAMMALIA,RODENTIA,MURIDAE,Mus cypriacus,"""A new species of the genus Mus has been discovered on the island of Cyprus, namely Mus cypriacus. Molecular phylogeny of complete D-loop sequences, as well as that of a nuclear gene intron (ABP), evidence that this new taxa is not an island variant but deserves a species rank on its own, as a sister species of Mus macedonicus and Mus spicilegus, the two closest mainland relatives. Classical and geometric morphometry provide diagnostic morphological criteria separating Mus cypriacus from European species."" (Cucchi et al. 2006). Genetic and archaeological evidence suggest that the common ancestor of M. cypriacus and M. macedonicus arrived on Cyprus during the Middle Pleistocene by a founder event on natural raft (Cucchi et al. 2006). This species is one of only three surviving endemic mammal species on Mediterranean islands that originate from ancient natural colonization events (Gippoliti and Amori 2006).",Yes,No,LC,,LC,,"Little is known about the status and distribution of this recently-discovered species. However, it may be quite common in appropriate habitats, and no major threats are known. Consequently it is assessed as Least Concern. Its extent of occurrence is small (<10,000 km²), so if any evidence emerges to suggest that declines or extreme fluctuations are occurring, the species should be reassessed.",Unknown,"The Cyprus mouse Mus cypriacus is endemic to the island of Cyprus in the Mediterranean (Bonhomme et al. 2004, Cucchi et al. 2006). It may be quite widespread in upland areas, and is typically found at altitudes of 300-900 m, although there are some records from 100-150 m (Cucchi et al. 2006). Among the 15 trapping localities sampled in different biotopes on the southern part of the island, M. cypriacus was captured in eight of them (Cucchi et al. 2006). Further research is required in order to establish the range of this new species.",Population status and trends are not known.,"The species has mainly been found in abandoned cultivation terraces at moderate altitudes (300-900 m), where the vegetation consists of a mosaic of open grassy areas, shrubs and small trees, and cultivated vines (Vitis vinifera).It can also be found in forested riverine areas at 100-150 m, where it is syntopic with the house mouse (M. m. domesticus). It is apparently absent from lowland (less than 100 m) areas with strong anthropogenic pressure, such as intensive arable farmland, human dwellings and farms, and orchards (orange groves), where the house mouse is almost exclusively dominant (Cucchi 2005).","It is not yet known if there are any major threats to this recently-discovered species. It is generally found in abandoned vineyards and terraced fields at moderate altitudes. This type of habitat has increased in Cyprus in the recent past, and is probably now more or less stable, although declines may potentially occur in the future as a result of changes in agricultural policy since Cyprus joined the EU in 2004, and as a result of housing and tourism development (Panayides 2004, M. Hellicar pers. comm. 2006). The use of rodenticides as pest control may cause mortality in populations that live close to human habitation.","No conservation measures are known. Surveys are required to determine the status and range of the species, and research is required to confirm or refute the existence of any major threats. The Cyprus mouse is of conservation interest as it is one of just three surviving palaeoendemic mammal species found on Mediterranean islands (the other two being the shrew species Crocidura sicula and C. zimmermanni) (Gippoliti and Amori 2006). Most ancient endemic mammals of Mediterranean islands died out after the arrival of man (Gippoliti and Amori 2006). Mediterranean islands are also home to a number of taxa currently recognised as endemic species and subspecies that are the descendants of mainland taxa introduced by man (Gippoliti and Amori 2006).",Giovanni Amori and Eleftherios Hadjisterkotis +ANIMALIA,CHORDATA,MAMMALIA,RODENTIA,MURIDAE,Mus macedonicus,,No,No,LC,,LC,,"European regional assessment: Least Concern (LC)EU 25 regional assessment: Least Concern (LC)This species has a wide range. It is common with no major threats at present, and the population trend is believed to be stable. Consequently it is classed as Least Concern.",Possibly Favourable,"Mus macedonicus occurs in the south Balkans, Asia Minor, the Caucasus (Transcaucasia), and the Middle East south to Israel and Jordan and east to Iran (Panteleyev 1998, Macholán 1999). In Europe, it is found from sea level to 500 m (Macholán 1999).",It is common throughout its range (Macholán 1999).,"It occurs in a wide range of habitats including cultivated farmland, orchards, olive groves, road verges, sand dunes, arid Mediterranean shrubland, wadis, and densely-vegetated riverbanks. It is absent from dense forests, and avoids areas of human habitation (Macholán 1999).",No major threats.,It occurs in some protected areas within its range. No specific conservation measures are recommended.,"Boris Kryštufek, Vladimir Vohralík" +ANIMALIA,CHORDATA,MAMMALIA,RODENTIA,MURIDAE,Mus musculus,Includes domesticus as a subspecies (Wilson and Reeder 2005).,No,No,LC,,LC,,European regional assessment: Least Concern (LC)EU 25 regional assessment: Least Concern (LC)A widespread and extremely abundant species that thrives in anthropogenic habitats. Classed as Least Concern.,Possibly Favourable,"Originally a Palaearctic species; through its close association with humans it has been widely introduced and has become established in North and South America, sub-Saharan Africa, northern Australia, and many oceanic islands (Macholán 1999).",A widespread and abundant species; common except in some extreme habitats (e.g. at high altitude) (Macholán 1999).,"House mice are typically commensal, and are found in a very wide range of man-made habitats including houses, farm outbuildings, other types of buildings, and even coal mines and frozen meat stores. Sometimes it is feral in areas where it has been introduced, and in some parts of its native range it maintains wild populations in outdoor habitats such as arable land, pastures, coastal sand dunes, salt marshes, and scrubby road verges (Macholán 1999, Wilson and Reeder 2005). House mice tend not to be found in forests and deserts (Macholán 1999).",This species faces no major threats.,Not protected under international legislation; commonly regarded as a pest. Present in many protected areas. A highly successful colonist of artificial environments; no conservation measures are required.,Giovanni Amori +ANIMALIA,CHORDATA,MAMMALIA,RODENTIA,MURIDAE,Mus spicilegus,,Yes,No,LC,,LC,,"M. spicilegus is widespread in its range and can be common in suitable habitat. It is declining in some parts of its range owing to habitat loss, but not at a rate that meets the threatened criteria. Likewise in parts of the Mediterranean there are local declines; it may be in direct competition with M. musculus. Currently assessed as Least Concern, but population declines should be monitored.",Possibly Unfavourable,"Mus spicilegus is endemic to Europe, occurring from Lake Neusiedl on the Austro-Hungarian border through Slovakia, Hungary, Moldova, and Ukraine, extending eastwards to as far as Rostov in the extreme south-west of Russia. In the Mediterranean region, it occurs in Serbia and Bulgaria, with an isolated subpopulation occurring in Montenegro, Greece and Albania. This subpopulation has a fragmented range within a very narrow strip of coastal habitat, and there are only three known localities (B. Kryštufek pers. comm. 2006). It typically occurs from sea level to 200 m (Macholán 1999).","It remains common in suitable habitats, but is suspected to be undergoing population decline in some areas. Densities of 1-20 mounds per hectare are typical, but densities of up to 60-100 mounds per hectare may be reached in particularly favourable habitat. On average, each mound is inhabited by five to six individuals (Macholán 1999). In Slovakia the range appears to be expanding.","It occurs in a variety of open habitats including natural steppe grasslands, pastures and cereal fields, orchards, open woodland, woodland edges and clearings. It avoids forests and human settlements. It feeds on grain and seeds, which it hoards in the winter in a soil-covered mound built above its nest chamber; a single mound may be up to 400 cm in diameter (although 100-200 cm is more typical) and contain up to 10 kg of grain (Macdonald and Barrett 1993, Sokolov et al. 1998). Groups of 4-14 mice cooperate to build these mounds (Sokolov et al. 1998).","It is feared that loss of steppe grassland and agricultural intensification may cause population declines (Macholán 1999). However, in Romania at least, this species is considered an agricultural pest (Popescu and Murariu 2001).",It occurs in some protected area within its range. The population may be declining and this should be monitored.,"Coroiu, I., Kryštufek, B. & Vohralík, V." +ANIMALIA,CHORDATA,MAMMALIA,RODENTIA,MURIDAE,Mus spretus,,No,No,LC,,LC,,"European regional assessment: Least Concern (LC)EU 25 regional assessment: Least Concern (LC)A common and widespread species within its range, with no major threats.",Possibly Favourable,"Mus spretus is endemic to the Mediterranean region, occurring in south-west Europe and North Africa from Morocco to Libya (Panteleyev 1998, Macholán 1999). In Europe, it is found in Portugal, Spain, the Balearic islands (Spain), and southern France. Its vertical range is from sea level to 1,800 m (L.J. Palomo pers. comm. 2006).","It is common throughout its range, and populations are presumably stable. Typical densities are in the region of 3-12 individuals per hectare (Macholán 1999).","It is found in grasslands, dry shrubland, cereal fields and open woodland. It is absent from dense forest, and tends to avoid human settlements (Macholán 1999). Their limited water requirements (half that of the house mouse) allows them to inhabit drier areas than other mice (Palomo and Gisbert 2002).",No major threats.,Occurs in some protected areas within its range. No specific measures are recommended.,"Holger Meinig, Giovanni Amori" +ANIMALIA,CHORDATA,MAMMALIA,RODENTIA,MURIDAE,Rattus rattus,,No,No,LC,,LC,,"European regional assessment: Least Concern (LC)EU 25 regional assessment: Least Concern (LC)A widespread and abundant species, often regarded as a pest. Although there have been population declines in parts of the European range, these are not believed to approach the threshold for the population decline criterion of the IUCN Red List (30% over 10 years or 3 generations, whichever is longer). Classed as Least Concern.",Unknown,"Originally an Indomalayan species; widely introduced across the globe as a result of human activities. In Europe, it has been present since ancient times, and is found in most countries, with the exception of Fennoscandia (where it has gone extinct, except for one site in Denmark). It has suffered declines and now has a very restricted range in the United Kingdom, appears to be confined to one island off the east coast of Ireland, and is probably extinct in Slovakia (Amori and Cristaldi 1999).","A widespread and abundant species. It is very common in the Mediterranean. However, in some parts of its northern European range (e.g. United Kingdom, Netherlands, Austria) large population declines and range contractions have occurred since c.1970 (Amori and Cristaldi 1999, Spitzenberger 2005). It has disappeared from Fennoscandia (with the exception of one site in Denmark) (Amori and Cristaldi 1999).","Highly commensal in northern and central parts of Europe, where is is found in a variety of man-made habitats. Also lives outdoors in natural and semi-natural habitats in the Mediterranean (especially on Mediterranean islands) (Amori and Cristaldi 1999).",No major threats.,Not protected under international legislation; commonly regarded as a pest. Present in many protected areas.,Giovanni Amori +ANIMALIA,CHORDATA,MAMMALIA,RODENTIA,SCIURIDAE,Marmota bobak,"Includes three subspecies: M. b. bobak Muller, 1776 (Ukraine, European part of Russia); M. b. kozlovi Fokanov, 1966 (Volga River region, right bank around Saratov City); M. b. schaganensis Bazhanov, 1930 (the rest of the range).",No,No,LC,,NE,,"European regional assessment: Least Concern (LC)EU 25 regional assessment: Not Evaluated (NE)The population experienced severe decline in the past, but these declines ended well over 10 years (3 generations) ago. The species is now stable and abundant within its present range in Europe. Consequently it is assessed as Least Concern.",-,"At the beginning of the 20th century the species was distributed along whole steppe zone from W Ukraine through Russia and Kazakhstan to the Irtysh River. However, in the first half of the 20th century hunting and habitat loss (ploughing of steppes and conversion to arable land) significantly reduced the range of bobak marmot in the European steppes. By the 1940s the European range of the bobak marmot had become fragmented into isolated populations in unused land and protected areas. Currently the majority of the range is in the Urals and N Kazakhstan.","Formerly the species was common and abundant along the whole steppe zone from W Ukraine to the Irtysh River. By the 1940s the European population and range had declined dramatically, and the species was restricted to isolated fragments of habitat in uncultivated areas and nature reserves. In the 1960s in both Russia and Ukraine hunting was prohibited, and marmot populations in these countries subsequently increased and are now considered stable. In N Kazakhstan, by contrast, the population has not recovered and remains at low density, but in central Kazakhstan the population is increasing. The species was reintroduced to a number of locations in the early 1980s, and the species has also naturally recolonised many areas.","It inhabits a variety of steppe habitats, including lowland, mixed grass, arid, and wormwood (Artemisia) steppes. Forms colonies consisting of several families. Burrows are complex, and may be up to 4-5 m in depth. There are summer and winter burrows, both with pronounced mounds. Does not stock up for winter; instead hibernates for at least six months a year. Enters hibernation at different times in differents parts of the range, leaves hibernation in late March-April. Feeds on green parts, bulbs, flowers and shoots of grasses. Sensitive to moisture in food and in overly dry conditions enters estivation. Reproduces once a year with litter size of 4 to 7 young.",Severe population and range reductions in the early to mid 20th century were caused by excessive hunting and habitat loss (cultivation of steppe grassland). Some illegal hunting continues.,"At present, there are no special conservation measures except hunting prohibition. In the early 1980s re-introductions were carried out in a number of locations. In the European part of the range the bobak marmot occurs in protected areas, where it survived during the period of severe population decline in the early to mid 20th century.","Katerina Tsytsulina, Nikolai Formozov, Boris Sheftel, Igor Zagorodnyuk" +ANIMALIA,CHORDATA,MAMMALIA,RODENTIA,SCIURIDAE,Marmota marmota,,Yes,No,LC,,LC,,"The species is not threatened at present. Subspecies marmota is common within at least parts of its range and has no major threats. However, subspecies latirostris has a restricted range and small population, and should be monitored and protected.",Possibly Favourable,"The Alpine marmot is endemic to Europe. Its core range extends through the Alps of France, Italy, Switzerland, Germany and Austria. Isolated subpopulations are found in the Pyrenees, Massif Central, Jura, Vosges, Black Forest, Appenines, High Tatras, and Romanian Carpathians. A number of these isolated subpopulations (those in the Pyrenees, Massif Central, Jura, Vosges, Black Forest, and Appennines, and eastern Alps) are the result of introductions. The marmot has inhabited the Alps and High Tatras continuously since the end of the last Ice Age, and was reintroduced to the Romanian Carpathians (three attempts in 1973, the third attempt was successful) and Slovenia (in 1953). It occurs as two subspecies: M. m. marmota in the Alps (and most introduced subpopulations) and M. m. latirostris in the High Tatras. A hybrid population exists in the Low Tatras, the result of introductions of both subspecies. Likewise populations in the Appenines are hybrids of both subspecies. It occurs at altitudes of 600-3,200 m (Preleuthner 1999).","M. m. marmota is abundant in at least parts of its core range in the Alps, although some subpopulations may be under threat (e.g. in the Jura and in Germany). Reported population densities for M. m. marmota range from 24-36 individuals per 100 hectares (Gran Paradiso, Italy) to 40-80 individuals per 100 hectares (Tessin, Switzerland). In Romanian Carpathians, the population is estimated at 1,500 individuals. It is known from three areas in Romania: Retezat, Fagaras and Rodna. In Retezat and Fagaras the populations are stable; in Rodna the population is very small and is threatened by poaching (Popescu and Murariu 2001, Botnariuc and Tatole 2005). The population is Slovenia is expanding (B. Krystufek pers. comm. 2007). Subspecies M. m. latirostris has a restricted range (it occurs at higher elevations in a small region of the High Tatras) and is considered to be rare and threatened (Preleuthner 1999).","It inhabits alpine meadows and high-altitude pastures, typically on south-facing slopes from 1,200-3,000 m (although it is occasionally found at lower altitudes). Colonies inhabit deep burrow systems in alluvial soil or rocky areas (Preleuthner 1999). It has a herbivorous diet, primarily composed of green parts of grasses, sedges, and herbs (Krapp 1978).","Marmots were previously hunted for meat, fur, and fat (which was used for cosmetics and medicines). Hunting continues today, but is primarily a leisure activity (Preleuthner 1999). In Slovenia and Austria, hunting levels are sustainable, but in Austria at least populations living below the timberline are threatened by loss of open habitats through abandonment of high-altitude cattle grazing (Spitzenberger 2002, B. Kryštufek pers. comm. 2006). Hybridisation with introduced M. m. marmota is a potential future threat to remaining pure-bred populations of M. m. latirostris in the High Tatras.","The species occurs in a number of national parks within its range. It is listed under Appendix III of the Bern Convention, and is protected under national law in a number of range states (e.g., Slovenia). Subspecies latirostris requires strict protection in Slovakia and Poland.","Herrero, J., Zima, J. & Coroiu, I." +ANIMALIA,CHORDATA,MAMMALIA,RODENTIA,SCIURIDAE,Pteromys volans,,No,No,DD,,NT,,"European regional assessment: Data Deficient (DD)EU 25 regional assessment: Near Threatened (NT)At the European level, there are insufficient data to estimate rate of population decline. The species is susceptible to habitat loss and fragmentation through forestry practices. Within the EU, the species occurs only in Finland, Estonia and Latvia, where it continues to decline in many parts of its range. Declines of 20-58% have been recorded in small-scale local studies in Finland over the last 10-20 years. There is not expected to be any rescue effect from outside the region (e.g. from Russian Karelia) as the species is facing similar threats in that area. Consequently the species is assessed at Data Deficient at the European level, and Near Threatened (A2bc) within the EU 25.",Unfavourable,"The Siberian flying squirrel has a wide range in the northern Palaearctic, extending from Finland, Estonia and Latvia eastwards through Russia to the Pacific coast (Panteleyev 1998, Sulkava 1999). It also occurs on the Pacific islands of Sakhalin (Russia) and Hokkaido (Japan). It occurs from sea level to the tree line (H. Henttonen pers. comm. 2006).","The species continues to decline in many parts of its range owing to loss of old-growth mixed forests. In Finland, it is still locally quite common but declining everywhere, with detailed local studies showing 20-58% declines over periods of 10-20 years (Hanski et al. 2001, Hanski 2006). Declines were noted in all parts of Finland; there were no areas where the population was stable or increasing, and declines are predicted to continue in the future (Hanski 2006) A three year census ending in 2005 estimated the Finnish population at 140,000 females (95% confidence limits 134,800-151,300: Hanski 2006). It has been found at c.50 sites in Estonia (T. Maran pers. comm. 2006). In Russia, it is considered widespread but rare in Karelia, and in the Karelian isthmus its status is similar to that of the Finnish population (A. Tikhonov in litt. 2006).","It prefers mature spruce-dominated forests with a significant proportion of deciduous trees, especially aspen Populus tremula, birch Betula sp. and alder Alnus sp. (Reunanen et al. 2000, 2002). Large deciduous trees are an important source of both food and nest-sites: the flying squirrel feeds primarily on alder and birch catkins in the winter and alder leaves in the summer, and nests in old woodpecker holes or natural cavities in decaying wood.","Modern intensive forestry and logging are the major threats to this species (Hanski et al. 2001). Fragmentation of forests is a particular problem for this species, as flying squirrels are reluctant to cross open areas on the ground. Managed forests also tend to have fewer deciduous trees (which are an essential winter food source), less decaying wood and fewer tree-holes (which are needed for nest-sites). In parts of Russia, it has been estimated that up to 50% of logging is illegal (Kotlobay and Ptichnikov 2002). Illegal logging is particularly destructive, as unsustainable practices such as high-grading or 'skimming' are used, meaning that for every ten trees felled only one or two high-quality logs will be used (Kotlobay and Ptichnikov 2002).","It is listed on Appendix II of the Bern Convention, and on Annex II* and Annex IV of the EU Habitats & Species Directive. It is considered Vulnerable at the national level in Finland (Rassi et al. 2001). The Finnish Ministry of Forestry and Agriculture and Ministry of the Environment have published detailed guidelines on how to deal with flying squirrels in forestry. Specific recommendations include protecting known feeding and nesting sites (usually this means that trees surrounding nesting tree will be protected within 30 m, and ""corridors"" will be saved so that nesting sites are not isolated) (Anon. 2002, 2003, H. Henttonen pers. comm. 2006). It occurs in a number of protected areas.","Heikki Henttonen, Tiit Maran, Ilpo Hanski" +ANIMALIA,CHORDATA,MAMMALIA,RODENTIA,SCIURIDAE,Sciurus anomalus,,No,No,NA,,NA,,European regional assessment: Not Applicable (NA)EU 25 regional assessment: Not Applicable (NA)Assessed as Not Applicable as it is of marginal occurrence in Europe.,-,"In Europe it is restricted to the area around Istanbul (where it was introduced in 1964), and to the islands of Lesbos (Greece) and Gökçeada (Turkey) (Mitchell-Jones et al. 1999). Also occurs in ""Turkey, Transcaucasia (Armenia, Azerbaijan, Georgia), N and W Iran, Syria, Lebanon, Israel, Palestine, Jordan, and Iraq"" (Wilson and Reeder 2005). Less than 1% of its global range lies within the European Mammal Assessment region.",,,,,European Mammal Assessment team +ANIMALIA,CHORDATA,MAMMALIA,RODENTIA,SCIURIDAE,Sciurus vulgaris,,No,No,LC,,LC,,"European regional assessment: Least Concern (LC)EU 25 regional assessment: Least Concern (LC)This species is widespread and common throughout much of its range. In Italy and the UK there are serious declines owing to competition with the grey squirrel, Sciurus carolinensis. In the UK the species is also threatened by parapox virus transmitted from the grey squirrel. Although the grey squirrel occurs only in the UK and Italy at present, it is predicted that it will reach France and Switzerland during the next few decades. Given its current range, population, and population trends, the red squirrel is assessed as Least Concern. However, in the future its status in Europe is likely to worsen.",Possibly Favourable,"The red squirrel has a large range in the Palaearctic, extending from Ireland, Spain and Portugal in the west, through continental Europe, Russia, Mongolia, and north-east China to the Pacific coast (Panteleyev 1998, Gurnell and Wauters 1999). It is also found on the Pacific islands of Sakhalin (Russia) and Hokkaido (Japan), and it has been introduced to the Caucasus. In Europe, it is widespread in most areas, with the exception of the Iberian peninsula (where it is absent from the south-west) and Britain (where it has almost completely disappeared from the south-east). It is absent from the majority of Mediterranean islands. In Portugal the range has expanded southwards. It occurs from sea level up to 3,100 m in the Alps (Spitzenberger 2002).","Although it is described as common throughout most of its range (Gurnell and Wauters 1999), there have been well-documented population declines and range contractions in the United Kingdom, Ireland and Italy (Gurnell and Pepper 1993, Wauters et al. 1997, O'Teangana et al. 2000). Typical densities range from less than 0.1 to 1.5 individuals per hectare (Gurnell and Wauters 1999).","It is most abundant in large tracts of coniferous forest and also occurs in deciduous woods, mixed forest, parks, gardens, and small stands of conifers. Its diet is mainly vegetarian, consisting of seeds, acorns, fungus, bark, and sapwood, although it occasionally takes animal prey (young birds and eggs).","The main threats to this species are habitat loss and fragmentation and, in Britain and Italy, out-competition by the introduced grey squirrel Sciurus carolinensis (Gurnell and Pepper 1993, Wauters et al. 1997, Bertolino and Genovesi 2003). Now that the grey squirrel has become established on the continent, it can be expected that it may ultimately spread throughout much of the red squirrel's range. Grey squirrels not only out-compete the smaller red squirrels, but also carry parapox virus, which is highly pathogenic to red squirrels. Grey squirrels can carry the virus without being affected, and recent (2006) UK studies have shown that 61% of apparently healthy grey squirrels have been exposed to the virus and may be carriers (C. McInnes in litt. 2006). When the virus is present, the grey squirrel can replace the red squirrel 20 times faster than normal replacement rate (Rushton et al. 2006). The virus has not yet been recorded in Italy.","It is listed on Appendix III of the Bern Convention, and it occurs in many protected areas throughout its wide range.","Sandro Bertolino, Heikki Henttonen, Boris Kryštufek, Holger Meinig" +ANIMALIA,CHORDATA,MAMMALIA,RODENTIA,SCIURIDAE,Spermophilus citellus,"Eight subspecies have been described, but their validity was not confirmed in a comprehensive review of the species (Kryštufek 1996, 1999).",Yes,No,VU,A2bc,VU,A2bc,"Declines across the species' range are occurring, particularly in the southern and northwestern and northern areas where declines are more serious. Overall, declines are suspected to be more than 30% over the last ten years. For this reason the species is assessed as Vulnerable.",Unfavourable,"The European souslik is endemic to central and south-eastern Europe, where it occurs at altitudes of 0-2,500 m. Its range is divided in two by the Carpathian mountains. The north-western portion extends through the Czech Republic, Austria, Slovakia, Hungary, northern Serbia and Montenegro, and western Romania, whilst the south-eastern portion extends from southern Serbia, Macedonia and Greece through Bulgaria and southern Romania to Turkish Thrace, Moldova and Ukraine (Panteleyev 1998, Kryštufek 1999).","The European souslik is currently in serious decline. Its population has become fragmented, and extinctions have occurred in peripheral parts of its range in Germany (where it went extinct c.1985 because of forestry) and Poland (where the last definite autochthonous records date from the 1970s, although the species has recently been reintroduced (Kryštufek 1999, H. Meinig pers. comm. 2006, A. Gondek pers. comm. 2006). Although there are still some large and apparently stable subpopulations, there have been many reports of declines, especially in the north-western part of its range; it is also declining in the southern part of the range. In optimal habitat, densities of 18-48 individuals per hectare have been recorded, although lower figures of 5-14 individuals per hectare are also reported (Kryštufek 1999). In Romania, the population has been estimated at c.15,000 (Botnariuc and Tatole 2005). In parts of Dobrudja (Romania and Bulgaria) populations may have stabilised and started to increase since 1989, as a result of abandonment of intensive agriculture following the fall of the communist regime (I. Coroiu and D. Murariu pers. comm. 2006). In Greece, populations of two subspecies macedonicus and graolojenici) have been lost (B. Kryštufek pers. comm. 2006). In the Czech Republic there were 83 known localities in 1995, but by 2000-2001 only 26 of them still existed (Cepáková and Hulová 2002). Since 2001, there has been regular monitoring of S. citellus. Five new sites have been found, six colonies have disappeared, one was re-established due to reintroduction and one site has been naturally colonized following conservation management. Fluctuation or stagnation of abundance has been observed at eleven sites, numbers of sousliks have steadily decreased at seven sites, and only in five colonies have populations increased. In 2006 the total number of S. citellus living in the Czech Republic was estimated at 2,750 (J. Mateju unpublished data).","The European souslik has quite specific habitat requirements. It is restricted to short-grass steppe and similar artificial habitats (pastures, lawns, sports fields, golf courses) on light, well-drained soils, where it can excavate its burrows (Kryštufek 1999, Spitzenberger 2002). It avoids cultivated land, with the exception of vineyards in some parts of its range (Spitzenberger 2002). It has an omnivorous diet including seeds, roots, shoots, flowers, and arthropods (Nowak 1999, Kryštufek pers. comm. 2006).","The main threats to this species are the conversion of steppe-grassland and pasture to cultivated fields or forestry, and the abandonment of pasture and its subsequent reversion to tall-grass meadows or scrubby habitats which are not suitable for the souslik (Kryštufek 1999). In Austria it is therefore largely restricted to vineyards, airstrips, golflinks, sport- and camping grounds and other frequently mown lawns where it is completely dependent on the toleration of the owners (Spitzenberger 2002). Although not a major threat, some Gypsy communities in central and eastern Europe still catch sousliks for use as a traditional meal (J. Mateju pers. comm. 2006).","It is listed on Appendix II of the Bern Convention and Annexes II and IV of the EU Habitats and Species Directive. Research is needed to determine population status and trends, ecological requirements, potential threats, and appropriate conservation measures. In 2005, the species was reintroduced to Poland by the NGO Salamandra, and animals survived the first winter hibernation (A. Gondek pers. comm. 2006). In 2006 a project was initiated to reintroduce the species to Germany (H. Meinig pers. comm. 2006).","Coroiu, C., Kryštufek, B., Vohralík, V. & Zagorodnyuk, I." +ANIMALIA,CHORDATA,MAMMALIA,RODENTIA,SCIURIDAE,Spermophilus fulvus,Five subspecies are recognised. Spermophilus fulvus hybridizes with S. major in areas where these two species overlap.,No,No,LC,,NE,,"European regional assessment: Least Concern (LC)EU 25 regional assessment: Not Evaluated (NE)A widespread and abundant species with no major threats. Although population declines have been noted in some parts of the range, it is not believed to approach the threshold for the population decline criterion of the IUCN Red List (i.e. declining more than 30% in ten years or three generations). For these reasons, it is evaluated as Least Concern.",-,"Russia and Kazakhstan, from the Caspian Sea and the Volga River to Lake Balkash; south through Uzbekistan, W Tajikistan and Turkmenistan to NE Iran, and N Afghanistan; W Xinjiang (China). The southern part of the range is fragmented.","In some regions of Russia and Kazakhstan populations have declined as a result of commercial hunting, but the species remains common and abundant throughout most of its range.","Inhabits sand, clay and loess deserts and semi-deserts. In the forest zone it lives on black absinth and saltwort alkali soils. Usually digs a single burrows on a large territory. Sometimes burrows of the great gerbil Rhombomys opimus are used. Migrates seasonally from sites flooded with water from melted snow, or in search for fresh vegetation. Hibernation is extended; the species exits hibernation in mid-May and after 3-4 months enters hibernation again. Feeds on overground parts of cereals, absinths and saltworts.","Although it is hunted commercially, this is not considered to be a major threat to the species at present.",No special conservation measures apply to this species.,"Katerina Tsytsulina, Nikolai Formozov, Boris Sheftel" +ANIMALIA,CHORDATA,MAMMALIA,RODENTIA,SCIURIDAE,Spermophilus major,,No,No,LC,,NE,,"European regional assessment: Least Concern (LC)EU 25 regional assessment: Not Evaluated (NE)A widespread and abundant species. Although population declines have been noted in some parts of the range, it is not believed to approach the threshold for the population decline criterion of the IUCN Red List (i.e. declining more than 30% in ten years or three generations). For these reasons, it is evaluated as Least Concern.",-,"Steppe between Volga and Irtysh rivers (Russia; N Kazakhstan). Formerly, steppe between Don and Volga rivers (Russia: Gromov et al. 1965). On the western bank of Volga River found in NW part of Volga Hills (Ermakov and Titov 2000). Reported from Xinjiang (Ma et al. 1987); but probably a misidentified S. brevicauda. Its range is increasing in the south and the west (N. Formozov pers. comm. 2006). Occurs from sea level to 600 m.","Populations undergo periodical fluctuations and consequently population size varies from year to year. Periods of mass reproduction give place to population depressions, during which only single individuals could be found in colonies that had formerly been large. The main factors that determine mortality include the soil freezing through during the species' hibernation period, late arrival of spring, human disturbance (including direct killing), predators and epizootics. The species has high reproductve capacity and ecological plasticity. However, a recent study found that populations in most parts of the range were declining, and some small populations had gone extinct (Ermakov and Titov 2000). At the same time, the species has been extending its range in some areas (N. Formozov pers. comm. 2006).","Inhabits mixed grassy plains, and grain and feather-grass steppes. In the northern part of the range penetrates into forest-steppe and the southern part of forest zones. In the south it occurs in river meadows in semi-desert zones. The species is spreading as roads and development increase the number of channels containing water and long grasses. The species is able to cross the Volga due to the construction of dams in four different places. The dams contain ponds which keep ice over winter for longer, allowing the species to move. Another possible reason for observed range expansion is the release of individuals (along with marmots) by hunters. Lives in single burrows scattered over wide territories. In southern parts of the range where appropriate habitats are limited forms colonies. Adult males enter hibernation in mid-June; mass hibernation starts in August. Feeds on green parts and seeds of grasses and cereals.",The most significant threats are ploughing and direct killing by humans.,No specific conservation measures for this species are known.,"Katerina Tsytsulina, Nikolai Formozov, Boris Sheftel" +ANIMALIA,CHORDATA,MAMMALIA,RODENTIA,SCIURIDAE,Spermophilus pygmaeus,,No,No,LC,,NE,,"European regional assessment: Least Concern (LC)EU 25 regional assessment: Not Evaluated (NE)A widespread and abundant species. Although population declines have been noted in some parts of the range, it is not believed to approach the threshold for the population decline criterion of the IUCN Red List (i.e. declining more than 30% in ten years or three generations). For these reasons, it is evaluated as Least Concern.",-,"Distributed in plains or foothills steppes and semi-deserts in the Dnepr Region (Ukraine), Lower Volga Region and cis-Caucasia (Dagestan, Russia). Most of the range is in Central Asia east to the Aral Sea (Kazakhstan). The range of the species has reduced over the last 20 years as a result of climate change (more wet weather and wet years in the region). The abandonment of agricultural practices (cattle grazing and arable farming), which is changing the habitat, may also have played a role. The species occurs at low altitudes (up to 400 or 500 m).","Populations undergo periodical fluctuations. In the European part of the range over last 30 years, numbers have declined and some local populations have gone extinct.","Inhabits absinth deserts and semi-deserts in virgin and long-fallow lands. Avoids sites with dense high grasses. Lives in colonies consisting mostly of non overlapping territories of adult females. Male territories covers several female territories. Each colony includes permanent (reproduction and hibernation) burrows and temporary shelter burrows. The little ground squirrel leaves hibernation in March-April; enters estivation in second part of June-July, sometimes, especially in dry years, goes straight from estivation to hibernation.","The main factors causing decline are natural climate dessication in the southern Volga Region, with a concurrent trend towards wetter weather at mid-latitudes. Neither of these changes in climate are favourable for the little ground squirrel. Additionally, human activities including pesticide use, irrigation, overgrazing and persecution have a negative impact on populations. Abandonment of agricultural practices (cattle grazing and arable farming) may be leading to unfavourable habitat change in some areas.","Despite recorded population decline in the European part of the range, the species remains widespread and abundant. No specific conservation measures are known.","Katerina Tsytsulina, Nikolai Formozov, Boris Sheftel, Igor Zagorodnyuk" +ANIMALIA,CHORDATA,MAMMALIA,RODENTIA,SCIURIDAE,Spermophilus suslicus,There are two chromosome races of this species: S. odessanus (36 chromosome) and S. suslicus sensu stricto (34 chromosomes). These are separated by the Dnieper River. The eastern Europe race is considered a separate species by many taxonomists. S. odessanus is declining more than S. suslicus sensu stricto.,Yes,No,NT,,NA,,"Globally, the population has shown serious declines over the last 50 years. However, over the last ten years the rate of decline has slowed (perhaps to ca. 20%, but no data are currently available to support this figure). Since the population is still declining, albeit at a slower rate, and habitat loss and fragmentation is continuing, the species is assessed as Near Threatened at the global level (approaching A2bc+3bc).",-,"The spotted souslik is endemic to eastern Europe, where it is found in south-eastern Poland, small areas in Belarus, the Ukraine, Moldova, and Russia eastwards to the river Volga. In Poland, the souslik occurs on the western edge of its range and it is known from one relic enclave located between the Wieprz and Bug rivers in the region of Zamosc (Glowacinski et al. 2001, Piskorski 2005). A lowland species, it occurs up to no more than 500 m (I. Zagorodnyuk pers. comm. 2006).","The spotted souslik has suffered marked declines in both population and range. Its extent of occurrence has contracted in both Poland and southern Russia, and the number of colonies in Poland and the Ukraine (where no more than 10% of the former range described in mid-twentieth century is left) has decreased markedly (Glowacinski et al. 2001, Piskorski 2005, I. Zagorodnyuk pers. comm. 2006). Populations in the southern and eastern parts of the range are more stable. Over the last ten years some populations have shown increases in population size. However, across the global range, the total population is declining, although the rate of decline over the last ten years is likely to be less than 30% (I. Zagorodnyuk pers. comm. 2006). The Polish population of the spotted souslik has been estimated at c.20,000 individuals living in 7 compact and no more than 10 scattered colonies. The most numerous of these colonies, with 10,000-12,000 individuals, is found at Swidnik airport (near Lublin) and is the result of an unofficial introduction in the early 1980s. The present population of S. suslicus is one third of what it was in the 1960s, the number of localities has markedly decreased and the area occupied has shrunk by a half. If this trend continues the souslik will die out in Poland at the first decades of the 21th century (Glowacinski et al. 2001, Piskorski 2005, Z. Glowacinski pers. comm. 2006).","Like its congener the European souslik Spermophilus citellus, the spotted souslik prefers open areas with short grass (including steppes, pastures, and road verges). Unlike the European souslik, it can also sometimes be found on cultivated ground and can survive ploughing (Macdonald and Barrett 1993). It feeds chiefly on grasses and cereals, although arthropods and small vertebrates are also taken.","It is threatened by the loss and fragmentation of appropriate habitats. Causes of habitat loss include expansion of agriculture and forestry, urbanisation, reclamation of wasteland and industrial development (Glowacinski et al. 2001, Piskorski 2005, Z. Glowacinski pers. comm. 2006). More than 50% of the remaining Polish population is threatened by the expansion of Lublin airport (A. Gondek pers. comm. 2006). In some areas, it is persecuted as an agricultural pest. Hybridisation with S. pygmaeus and S. citellus has been recorded, but is not likely to be a major threat. Currently all populations are declining and becoming more fragmented, which makes hybridisation less of a problem.","It is legally protected under Appendix II of the Bern Convention. In Poland the souslik is strictly protected under national law, and five nature reserves have recently been created to protect the species. Development of the system of nature reserves and active protection (reintroduction and habitat management) are recommended (Glowacinski et al. 2001, Piskorski 2005, Z. Glowacinski pers. comm. 2006).","Zagorodnyuk, I., Glowacinski, Z. & Gondek, A." +ANIMALIA,CHORDATA,MAMMALIA,RODENTIA,SCIURIDAE,Tamias sibiricus,,No,No,LC,,NE,,European regional assessment: Least Concern (LC)EU 25 regional assessment: Not Evaluated (NE)A widely distributed and abundant species with no major threats. Its range is currently expanding westwards in Europe. Classed as Least Concern.,-,"Most of the range is in Asia. N European and Siberian Russia to Sakhalin; S Kurile Isls (Russia); extreme E Kazakhstan to N Mongolia, China, Korea, and Hokkaido (Japan). Introduced into Belgium, Germany, the Netherlands, Switzerland, and Italy (Amori 1999).","This species is relatively abundant alcross its range. It is expanding in Europe in the boreal forest zone, and has reached Vodlo Lake (Karelia) (H. Henttonnen pers. comm. 2006).","Typically inhabits coniferous and mixed forests with a rich undergrowth of berry-bearing shrubs. In mountains occurs up to the tree line. Climbs trees, but lives in simple shallow burrows. Summer nests are in stumps, fallen trees, sometimes in low hollows. Usually burrows consist of two big chambers, nest and larder, and small chambers used as a lavatory. Complex voice communication is characteristic to the species. Hibernates in winter. Short and long distance migrations have been registered during years with a poor harvest of Siberan pine nuts. Feeds on various seeds, mainly on Siberian pine, but diet also includes seeds of other coniferous and deciduous trees and herbs. In spring and summer consumes herb shoots; sometimes can eat insects and molluscs. From August onward stores up food for winter, storage mass usually 3-4 kg. Reproduces after leaving hibernation, in April-May.",There are no major threats to the species.,No special measures applied.,"Katerina Tsytsulina, Nikolai Formozov, Boris Sheftel" +ANIMALIA,CHORDATA,MAMMALIA,RODENTIA,SPALACIDAE,Spalax arenarius,,No,No,EN,"B1ab(ii,iii)+2ab(ii,iii)",NE,,"European regional assessment: Endangered (EN)EU 25 regional assessment: Not Evaluated (NE)This species is endemic to Ukraine, where it has a very small range. The population is stable only in Black Sea State Reserve; outside the reserve is declining due to habitat loss and degradation. The species occurs at a small number of locations (<5), and the outside the Black Sea State Reserve its range is severely fragmented. Consequently it qualifies as Endangered.",-,"Endemic species of southern Ukraine, found only on the lower Dnepr sands. Its extent of occurrence is c. 2000 km2, and its area of accupancy is about 55 km2. The main part of the population lies within the Black Sea Biosphere Reserve. Outside the reserve it occurs in fragments of poor quality habitat near the Lower Dnepr River sands. Those parts of the range are very fragmented.",The population is stable only in Black Sea State Reserve. In other areas the population is declining because of afforestation of the sands (for stabilisation of the sands and wood production).,"Stenotopic, inhbits light, moderately wet sandy soils with low subterranean waters. Never occurs in moving sands, alkali soils and in dry feather-grass steppes. Preferres absinth-grass and absinth-spurge steppes with very sparse vegetation. Ecology is poorly studied. Solitary, individual range is more than 80 m2. Feeds on most plants that are abundant in its range (Eryngium campestre, Artemisia campestris, Tragopogon ucrainicum etc.). Reproduces once a year. Copulation occurs in March, birth in April-May. Lactation period is about a month.",Habitat loss due to afforestation of the sands.,"The species occurs within a protected area, but this does not cover all of the population. It is listed in Ukraine's Red Data Book as category II (abundant species with rapidly declining population), and therefore it has legal protection at the national level.","Katerina Tsytsulina, Igor Zagorodnyuk" +ANIMALIA,CHORDATA,MAMMALIA,RODENTIA,SPALACIDAE,Spalax giganteus,,Yes,No,VU,B2ab(iii),NE,,"This species has a restricted range (extent of occurrence ca. 50,000 km2), within which its distribution is sporadic and fragmented. It is estimated that its area of occupancy is less than 2,000 km2. It is almost extinct in Chechnya as a result of civil war, and it is threatened elsewhere in its range by habitat loss due to irrigation, soil salinization, overgrazing, and ploughing. There is a continuing decline in the extent and quality of this species' habitat. Therefore it is listed as Vulnerable.",-,"It occurs in CIS-Caucasia and southernmost Kalmykia (Russia). Within the range it is distributed very patchily, as separate settlements that often occur in sandy areas.","It is declining in some parts of the range due to human impacts, although in other parts of the range populations are considered stable. Almost extinct in Chechen Republic (Russia) and parts of Dagestan (Russia). Does not undergo periodical fluctuations. Data on population size are limited and somewhat contradictory. According to data for the beginning of 1980s in Dagestan there were about 700-750 individuals (Red Data Book of Russian Federation 1983). However, a later aerial survey showed that the population was about 10,000 individuals.","Inhabits loamy and sandy semi-deserts in NE CIS-Caucasia. Prefers moderately moist areas with light soils in river valleys, lake basins and lowlands with luxuriant vegetation. Also occurs in semi-deserts with shrubs and reed, herb-grasses and herb-absinth steppes. Also found in anthropogenic landscapes such as orchards and fields, where it may be a pest. Obligatory subterranean, feeds on subterranean plant parts. Active throughout the year. Generally monogamous. Heat occurs in December-January, females give birth to 2-3 young.","Habitat loss due to irrigation and subsequent soil salinization, overgrazing, and ploughing. Low reproductive potential is a further limiting factor.",The species is listed in the Red Data Book of the Russian Federation in Category 3 (rare species). It occurs in reserves in Chechen Republic and Dagestan (Russia). Limitation of irrigation and grazing have been proposed as conservation measures.,"Tsytsulina, K., Formozov, N. & Sheftel, B." +ANIMALIA,CHORDATA,MAMMALIA,RODENTIA,SPALACIDAE,Spalax graecus,"Subspecies S. graecus istricus Mehely, 1909, is considered by some authors to be an independent species (see Wilson and Reeder 2005 for discussion).",Yes,No,NT,,NE,,"This species is assessed as Near Threatened (approaching criterion B2) at the European level, as it occurs at not many more than five locations, and agricultural intensification might be expected to impact the whole population over a short time period in the near future. The area of occupancy (AOO) is suspected to be less than 500 km², although it has not been estimated. The population is fragmented, so if an estimate of AOO was available, the species might qualify as Endangered under Criterion B2. In Romania at least, the mole rat population appears to be stable at present, although agricultural intensification may potentially become a threat in the near future. Population decline and range reduction can be presumed to have occurred in the past in Ukraine, where the species has not been recorded in the last 20-40 years and may have gone extinct. In Moldova, there is no information about population size or trend. Population monitoring is urgently required, as is research to determine the extent to which agricultural intensification is a threat, and to determine the AOO.",-,"The Balkan mole rat is a European endemic, known only from a small number of sites in Romania (Suceava, Craiova, Transylvania, and the lower Danube), south-eastern Ukraine (Cernovcy), and Moldova (Panteleyev 1998, Kryštufek 1999). Its range is very fragmented. It occurs in lowland and upland areas. In the Ukraine, the species has not been recorded over the last 20-40 years and it may be severely reduced, or already extinct there (I. Zagorodnyuk pers. comm. 2006).","It has a small and fragmented range, within which it occurs at densities of ca.1-3 individuals per hectare (although densities of up to 23 individuals per hectare have been recorded) (Nowak 1999, Kryštufek 1999). The current population trend is unknown, although declines can be assumed to have occurred in Ukraine in the relatively recent past.","It inhabits steppe grassland, pastures, small cultivated fields and orchards, often preferring northern exposures (Kryštufek 1999, B. Kryštufek pers. comm. 2006). Very arid areas are avoided (Nowak 1999). Individuals aggregate in winter but disperse in summer (Kryštufek 1999). The mole-rat is a fossorial species, digging extensive and elaborate tunnel systems with nesting chambers, storerooms and latrines (Nowak 1999). It feeds on bulbs, roots, tubers, and other underground parts of a range of plants (Nowak 1999). Mole-rats of the genus Spalax can be distinguished from all other rodents by the lack of any external openings for the eyes, although small eyes are present under the skin (Nowak 1999).","Its congener Spalax leucodon is threatened by agricultural intensification, as it cannot survive in intensively-farmed arable land. Spalax graecus may be similarly vulnerable to intensive agriculture. Subsistence agriculture continues in Transylvania, and the mole rat population appears to be stable there (I. Coroiu pers. comm. 2006), at least for the time being. However, accession of Romania to the EU might be expected to result in agricultural intensification in the near future.","It is listed on Appendix II of the Bern Convention, and on the Romanian and Ukrainian national Red Lists. A small reserve has been proposed in Transylvania to protect several species of plant and also, incidentally, Spalax (I. Coroiu pers. comm. 2006). Research is needed to determine population status and trends, ecological requirements, potential threats, and appropriate conservation measures for this little-known species.","Zagorodnyuk, I. & Coroiu, I." +ANIMALIA,CHORDATA,MAMMALIA,RODENTIA,SPALACIDAE,Spalax leucodon,Includes Nannospalax leucodon as a synonym.,No,No,LC,,LC,,"European regional assessment: Least Concern (LC)EU 25 regional assessment: Least Concern (LC)The taxonomy of this species is currently crude and in need of revision. Under its current taxonomy it is considered Least Concern, because it has a large range and although it is declining, this is not at a rate that approaches the threshold for criterion A. However, if after taxonomic revision the taxon is split into several different species, some of these may warrant listing as threatened.",Possibly Unfavourable,"The lesser mole rat occurs from Hungary and the Balkan peninsula through Moldova and the Ukraine to just east of the Dnestr river in Russia. It may also occur outside Europe in north-west Anatolia (Wilson and Reeder 2005). It is found from sea level to 2,400 m (Kryštufek 1999).","It has undergone range contractions and population declines in Europe. However, there are still areas where it is locally quite abundant. Population densities typically fall in the range of 1-13 individuals per hectare, but values of up to 23 individuals per hectare have been reported (Kryštufek 1999). Spalax leucodon is regarded as a superspecies that contains a number of forms that are well-differentiated at both a genotypic and phenotypic level, although their taxonomy remains unresolved. Some of these forms have very restricted ranges, and presumably small populations (Kryštufek 1999, B. Kryštufek pers. comm. 2006).","The mole rat inhabits steppe grassland, meadows and pastures, in areas with a deep layer of loose, freely-draining soil in which it digs its extensive burrows. It is absent from ploughed land and arable monocultures, although it may be found in agricultural lanscapes where there is a mixture of pastures, small crop-fields and orchards. It has a slow reproductive rate, raising litters of only 2-4 young (Kryštufek 1999). Mole-rats of the genus Spalax can be distinguished from all other rodents by the lack of any external openings for the eyes, although small eyes are present under the skin (Nowak 1999).","The mole-rat is threatened by habitat loss and land-use changes related to agricultural intensification and increased urbanisation and infrastructure development. It disappears when natural grasslands or pastures are ploughed up. When it was more common, it was an agricultural pest, and it is still persecuted as such in some areas (Kryštufek 1999).",It occurs within protected areas within its range. Taxonomic research is required (B. Kryštufek pers. comm. 2006).,"Boris Kryštufek, Giovanni Amori" +ANIMALIA,CHORDATA,MAMMALIA,RODENTIA,SPALACIDAE,Spalax microphthalmus,,Yes,No,LC,,NE,,"Across most of its range it is abundant and common, and there is no evidence that it is declining at a rate approaching the threshold for consideration as threatened under criterion A. However, small and isolated populations in the northern part of the range could be threatened by habitat loss through ploughing.",-,"Distributed in steppes and forest-steppes in Ukraine and S Russia between Dnepr and Volga Rivers, north to Orel-Kursk line, and south to Ciscaucasia (Gromov and Erbaeva 1995). In Crimea most probably absent since the Pleistocene. During Holocene the northern border of the range has moved significantly southward, leaving behind isolated relict populations, for example in Samarskaya Luka (Samara District, Russia).","A common species. In historical times in some parts of the range it became rare or even extinct, but elsewhere extended its extent of occurrence. In the northern part of the range and the Volga Region is occurs in small isolated populations and is considered rare. These populations are threatened by habitat loss (ploughing of major habitats). In the southern part of the range (Stavropol Region) in the 1950s, population and range declines occurred because of ploughing. Population density differs significantly in different parts of the range. Maximum densities are found in Central Black Earth Region (Russia) adjacent Ukrainian territories. Population density there is on average 3-10 individuals per hectare, however, locally it could reach up to 20. In the southern part of the range the density may be lower, as the arid climate of the steppes is less favourable. Populations are stable and do not undergone periodical fluctuations.","Obligatory subterranean species. Inhabits steppes; prefers lowlands with black earth and avoids loamy and sandy soils. Inhabits crop fields, melon plantations, gardens, orchards and forest belts. Feeds on underground parts of dandelion, cow parsnip, chicory and tree seedlings (oak, mulberry, acacia). Makes hoards for winter, sometimes up to 10-14 kg. Breeds once a year, females give birth in March to 2-5 young. During dispersal juveniles emerge above ground and often fall prey to carnivorous mammals and birds. A significant pest in southern parts of the range.",Ploughing of major habitats and use of toxic chemicals for pest control.,Locally protected in a number of State Reserves and national parks.,"Tsytsulina, K., Formozov, N., Zagorodnyuk, I. & Sheftel, B." +ANIMALIA,CHORDATA,MAMMALIA,RODENTIA,SPALACIDAE,Spalax nehringi,,No,No,NA,,NA,,European regional assessment: Not Applicable (NA)EU 25 regional assessment: Not Applicable (NA)Assessed as Not Applicable as it is of marginal occurrence in Europe.,-,"May occur on Lesbos (Greece) (Mitchell-Jones et al. 1999), also occurs on east Aegean islands of Gökçeada and Bozcaada (Turkey) (Wilson and Reeder 2005). Found throughout most of Anatolia, and in Armenia and Georgia. Less than 1% of its global range lies within the European Mammal Assessment region.",,,,,European Mammal Assessment team +ANIMALIA,CHORDATA,MAMMALIA,RODENTIA,SPALACIDAE,Spalax zemni,,Yes,No,VU,"B2ab(ii,iii)",NE,,"Although the extent of occurrence of this species is relatively large (mapped as c.150,000 km2), it has an extremely patchy and severely fragmented distribution within that area, and its area of occupancy is estimated to be less than 2,000 km2. The area of occupancy and quality of habitat is declining continually. The species does not occur in protected areas, except perhaps Podolskiy Tovtry National Park. Assessed as Vulnerable.",-,"The species occurs in Ukraine, where it is found from near the Polish border in the east to the Dnepr River in Central Ukraine and south to the Moldovan border. Populations are fragmented in Ukraine, so the area of occupancy could be much lower than the range indicated on the map..","There are no data on population size of the species. The range is highly fragmented and consists of isolated populations. Therefore although the species has relatively large extent of occurrence, the area of occupancy is low. Since the end of the 19th century the Podolsk mole rat has been considered a rare species across its whole range (Ognev 1947). Range contraction in historical time is probably due to shrinking of steppe habitats. Subfossil remains of the species were found on the left bank of Dnepr River in Kiev and Zhitomir regions. Therefore, losses of range in the south, north-west and north-east have a long history. Currently population density in optimal biotopes is about 1-8 individuals per hectare.","The major habitat of this species is virgin steppes. It also occurs in side roads, forest belts, and agricultural fields, and was recently found in former military firing ranges (I. Zagorodnyuk pers. comm. 2006). Does not avoid sandy soils. An obligate underground species. Its feeding habits are poorly studied, but according to data from southern and south-eastern part of the range it feeds on underground parts of lucerne, chicory, bindweed, mallows and tree seedlings (oak, mulberry, acacia etc.). There are no data on breeding or ecology.",Habitat degradation and loss due to cultivation and development is a major threat.,Not found in protected areas (except perhaps Podolskiy Tovtry National Park). Listed in Ukraine Red Data Book under category 3 (rare species with limited number of individuals and restricted range).,"Tsytsulina, K., Formozov, N., Zagorodnyuk, I. & Sheftel, B." diff --git a/kotlin-native/samples/csvparser/README.md b/kotlin-native/samples/csvparser/README.md new file mode 100644 index 00000000000..668b8b514aa --- /dev/null +++ b/kotlin-native/samples/csvparser/README.md @@ -0,0 +1,14 @@ +# CSV parser + +This example shows how one could implement simple comma separated values reader and parser in Kotlin. +A sample data [European Mammals Red List for 2009](https://data.europa.eu/euodp/en/data/dataset?res_format=CSV) +from EU is being used. + +To build use `../gradlew assemble`. + +To run use `../gradlew runReleaseExecutableCsvParser` or execute the program directly: + + ./build/bin/csvParser/main/release/executable/csvparser.kexe ./European_Mammals_Red_List_Nov_2009.csv --column 4 --count 100 + +It will print number of all unique entries in fifth column +(Family, zero-based index) in first 100 rows of the CSV file. diff --git a/kotlin-native/samples/csvparser/build.gradle.kts b/kotlin-native/samples/csvparser/build.gradle.kts new file mode 100644 index 00000000000..7d2da6fe2f5 --- /dev/null +++ b/kotlin-native/samples/csvparser/build.gradle.kts @@ -0,0 +1,26 @@ +plugins { + kotlin("multiplatform") +} + +kotlin { + // Determine host preset. + val hostOs = System.getProperty("os.name") + + // Create target for the host platform. + val hostTarget = when { + hostOs == "Mac OS X" -> macosX64("csvParser") + hostOs == "Linux" -> linuxX64("csvParser") + hostOs.startsWith("Windows") -> mingwX64("csvParser") + else -> throw GradleException("Host OS '$hostOs' is not supported in Kotlin/Native $project.") + } + + hostTarget.apply { + compilations["main"].enableEndorsedLibs = true + binaries { + executable { + entryPoint = "sample.csvparser.main" + runTask?.args("--column", 4, "--count", 100, "./European_Mammals_Red_List_Nov_2009.csv") + } + } + } +} diff --git a/kotlin-native/samples/csvparser/gradle.properties b/kotlin-native/samples/csvparser/gradle.properties new file mode 100644 index 00000000000..790a07d5124 --- /dev/null +++ b/kotlin-native/samples/csvparser/gradle.properties @@ -0,0 +1,2 @@ +kotlin.code.style=official +kotlin.import.noCommonSourceSets=true diff --git a/kotlin-native/samples/csvparser/src/csvParserMain/kotlin/CsvParser.kt b/kotlin-native/samples/csvparser/src/csvParserMain/kotlin/CsvParser.kt new file mode 100644 index 00000000000..72ccc2e3e57 --- /dev/null +++ b/kotlin-native/samples/csvparser/src/csvParserMain/kotlin/CsvParser.kt @@ -0,0 +1,70 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the license/LICENSE.txt file. + */ + +package sample.csvparser + +import kotlinx.cinterop.* +import platform.posix.* +import kotlinx.cli.* + +fun parseLine(line: String, separator: Char) : List { + val result = mutableListOf() + val builder = StringBuilder() + var quotes = 0 + for (ch in line) { + when { + ch == '\"' -> { + quotes++ + builder.append(ch) + } + (ch == '\n') || (ch == '\r') -> {} + (ch == separator) && (quotes % 2 == 0) -> { + result.add(builder.toString()) + builder.setLength(0) + } + else -> builder.append(ch) + } + } + return result +} + +fun main(args: Array) { + val argParser = ArgParser("csvparser") + val fileName by argParser.argument(ArgType.String, description = "CSV file") + val column by argParser.option(ArgType.Int, description = "Column to parse").required() + val count by argParser.option(ArgType.Int, description = "Count of lines to parse").required() + argParser.parse(args) + + val file = fopen(fileName, "r") + if (file == null) { + perror("cannot open input file $fileName") + return + } + + val keyValue = mutableMapOf() + + try { + memScoped { + val bufferLength = 64 * 1024 + val buffer = allocArray(bufferLength) + + for (i in 1..count) { + val nextLine = fgets(buffer, bufferLength, file)?.toKString() + if (nextLine == null || nextLine.isEmpty()) break + + val records = parseLine(nextLine, ',') + val key = records[column] + val current = keyValue[key] ?: 0 + keyValue[key] = current + 1 + } + } + } finally { + fclose(file) + } + + keyValue.forEach { + println("${it.key} -> ${it.value}") + } +} diff --git a/kotlin-native/samples/curl/README.md b/kotlin-native/samples/curl/README.md new file mode 100644 index 00000000000..d3a8624094a --- /dev/null +++ b/kotlin-native/samples/curl/README.md @@ -0,0 +1,13 @@ +# HTTP client + +This example shows how to communicate with libcurl, HTTP/HTTPS/FTP/etc client library and how to +depend on an artifact published in a maven repository. The sample depends on a library +built by [libcurl sample](../libcurl) so you need to run it first. + +To build use `../gradlew assemble`. + +To run use `../gradlew runReleaseExecutableCurl` or execute the program directly: + + ./build/bin/curl/main/release/executable/curl.kexe 'https://www.jetbrains.com/' + +It will perform HTTP get and print out the data obtained. diff --git a/kotlin-native/samples/curl/build.gradle.kts b/kotlin-native/samples/curl/build.gradle.kts new file mode 100644 index 00000000000..aeb26f73f18 --- /dev/null +++ b/kotlin-native/samples/curl/build.gradle.kts @@ -0,0 +1,71 @@ +plugins { + kotlin("multiplatform") +} + +val localRepo = rootProject.file("build/.m2-local") + +repositories { + maven("file://$localRepo") +} + +val mingwPath = File(System.getenv("MINGW64_DIR") ?: "C:/msys64/mingw64") + +kotlin { + // Determine host preset. + val hostOs = System.getProperty("os.name") + val isMingwX64 = hostOs.startsWith("Windows") + + // Create target for the host platform. + val hostTarget = when { + hostOs == "Mac OS X" -> macosX64("curl") + hostOs == "Linux" -> linuxX64("curl") + isMingwX64 -> mingwX64("curl") + else -> throw GradleException("Host OS '$hostOs' is not supported in Kotlin/Native $project.") + } + + hostTarget.apply { + binaries { + executable { + entryPoint = "sample.curl.main" + if (isMingwX64) { + // Add lib path to `libcurl` and its dependencies: + linkerOpts("-L${mingwPath.resolve("lib")}") + runTask?.environment("PATH" to mingwPath.resolve("bin")) + } + runTask?.args("https://www.jetbrains.com/") + } + } + } + + sourceSets { + val curlMain by getting { + dependencies { + implementation("org.jetbrains.kotlin.sample.native:libcurl:1.0") + } + } + } +} + +// The code snippet below is needed to make all compile tasks depend on publication of +// "libcurl" library. So that to the time of compilation the library will already be +// in Maven repo and will be successfully resolved as a dependency of this project. +tasks.withType(AbstractCompile::class) { + dependsOn(":libcurl:publish") +} + +// The following snippet is needed to give instructions for IDEA user who just imported project +// and sees "Could not resolve..." message in IDEA console. +gradle.buildFinished { + val configurationName = kotlin.targets["curl"].compilations["main"].compileDependencyConfigurationName + val configuration = project.configurations[configurationName] + if (configuration.isCanBeResolved && configuration.state == Configuration.State.RESOLVED_WITH_FAILURES) { + println( + """ + | + |IMPORTANT: + |The message about unresolved "libcurl" dependency likely means that "libcurl" has not been built and published to local Maven repo yet. + |Please run "publish" task for "libcurl" sub-project and re-import Kotlin/Native samples in IDEA. + """.trimMargin() + ) + } +} diff --git a/kotlin-native/samples/curl/gradle.properties b/kotlin-native/samples/curl/gradle.properties new file mode 100644 index 00000000000..790a07d5124 --- /dev/null +++ b/kotlin-native/samples/curl/gradle.properties @@ -0,0 +1,2 @@ +kotlin.code.style=official +kotlin.import.noCommonSourceSets=true diff --git a/kotlin-native/samples/curl/src/curlMain/kotlin/main.kt b/kotlin-native/samples/curl/src/curlMain/kotlin/main.kt new file mode 100644 index 00000000000..08fee5cc267 --- /dev/null +++ b/kotlin-native/samples/curl/src/curlMain/kotlin/main.kt @@ -0,0 +1,30 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the license/LICENSE.txt file. + */ + +package sample.curl + +import sample.libcurl.* + +fun main(args: Array) { + if (args.isEmpty()) + return help() + + val curl = CUrl(args[0]) + curl.header += { + println("[H] $it") + } + + curl.body += { + println("[B] $it") + } + + curl.fetch() + curl.close() +} + +fun help() { + println("ERROR: missing URL command line argument") +} + diff --git a/kotlin-native/samples/echoServer/README.md b/kotlin-native/samples/echoServer/README.md new file mode 100644 index 00000000000..3426bed1d7e --- /dev/null +++ b/kotlin-native/samples/echoServer/README.md @@ -0,0 +1,15 @@ +# Sockets demo + +To build use `../gradlew assemble`. + +To run use `../gradlew runReleaseExecutableEchoServer` or execute the program directly: + + ./build/bin/echoServer/main/release/executable/echoServer.kexe 3000 & + +Test the server by connecting to it, for example with telnet: + + telnet localhost 3000 + +Write something to console and watch server echoing it back. + +~~Quit telnet by pressing ctrl+] ctrl+D~~ diff --git a/kotlin-native/samples/echoServer/build.gradle.kts b/kotlin-native/samples/echoServer/build.gradle.kts new file mode 100644 index 00000000000..3b96e35c9c6 --- /dev/null +++ b/kotlin-native/samples/echoServer/build.gradle.kts @@ -0,0 +1,52 @@ +import org.jetbrains.kotlin.gradle.plugin.mpp.KotlinNativeTargetPreset + +plugins { + kotlin("multiplatform") +} + +// Add two additional presets for Raspberry Pi and Linux/ARM64. +val raspberryPiPresets: List = listOf("linuxArm32Hfp", "linuxArm64").map { + kotlin.presets[it] as KotlinNativeTargetPreset +} + +kotlin { + // Determine host preset. + val hostOs = System.getProperty("os.name") + + // Create a target for the host platform. + val hostTarget = when { + hostOs == "Mac OS X" -> macosX64("echoServer") + hostOs == "Linux" -> linuxX64("echoServer") + hostOs.startsWith("Windows") -> mingwX64("echoServer") + else -> throw GradleException("Host OS '$hostOs' is not supported in Kotlin/Native $project.") + } + + // Create cross-targets. + val raspberryPiTargets = raspberryPiPresets.map { preset -> + val targetName = "echoServer${preset.name.capitalize()}" + targetFromPreset(preset, targetName) {} + } + + // Configure executables for all targets. + configure(raspberryPiTargets + listOf(hostTarget)) { + binaries { + executable { + entryPoint = "sample.echoserver.main" + runTask?.args(3000) + } + } + } + + sourceSets { + val echoServerMain by getting + raspberryPiPresets.forEach { preset -> + val mainSourceSetName = "echoServer${preset.name.capitalize()}Main" + getByName(mainSourceSetName).dependsOn(echoServerMain) + } + } + + // Enable experimental stdlib API used by the sample. + sourceSets.all { + languageSettings.useExperimentalAnnotation("kotlin.ExperimentalStdlibApi") + } +} diff --git a/kotlin-native/samples/echoServer/gradle.properties b/kotlin-native/samples/echoServer/gradle.properties new file mode 100644 index 00000000000..790a07d5124 --- /dev/null +++ b/kotlin-native/samples/echoServer/gradle.properties @@ -0,0 +1,2 @@ +kotlin.code.style=official +kotlin.import.noCommonSourceSets=true diff --git a/kotlin-native/samples/echoServer/src/echoServerMain/kotlin/EchoServer.kt b/kotlin-native/samples/echoServer/src/echoServerMain/kotlin/EchoServer.kt new file mode 100644 index 00000000000..748c0e3eaf2 --- /dev/null +++ b/kotlin-native/samples/echoServer/src/echoServerMain/kotlin/EchoServer.kt @@ -0,0 +1,87 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the license/LICENSE.txt file. + */ + +package sample.echoserver + +import kotlinx.cinterop.* +import platform.posix.* + +fun main(args: Array) { + if (args.isEmpty()) { + println("Usage: echoserver.kexe ") + return + } + + val port = args[0].toShort() + + // Initialize sockets in platform-dependent way. + init_sockets() + + memScoped { + + val buffer = ByteArray(1024) + val prefixBuffer = "echo: ".encodeToByteArray() + val serverAddr = alloc() + + val listenFd = socket(AF_INET, SOCK_STREAM, 0) + .ensureUnixCallResult("socket") { !it.isMinusOne() } + + with(serverAddr) { + memset(this.ptr, 0, sockaddr_in.size.convert()) + sin_family = AF_INET.convert() + sin_port = posix_htons(port).convert() + } + + bind(listenFd, serverAddr.ptr.reinterpret(), sockaddr_in.size.convert()) + .ensureUnixCallResult("bind") { it == 0 } + + listen(listenFd, 10) + .ensureUnixCallResult("listen") { it == 0 } + + val commFd = accept(listenFd, null, null) + .ensureUnixCallResult("accept") { !it.isMinusOne() } + + buffer.usePinned { pinned -> + while (true) { + val length = recv(commFd, pinned.addressOf(0), buffer.size.convert(), 0).toInt() + .ensureUnixCallResult("read") { it >= 0 } + + if (length == 0) { + break + } + + send(commFd, prefixBuffer.refTo(0), prefixBuffer.size.convert(), 0) + .ensureUnixCallResult("write") { it >= 0 } + send(commFd, pinned.addressOf(0), length.convert(), 0) + .ensureUnixCallResult("write") { it >= 0 } + } + } + } +} + +inline fun Int.ensureUnixCallResult(op: String, predicate: (Int) -> Boolean): Int { + if (!predicate(this)) { + throw Error("$op: ${strerror(posix_errno())!!.toKString()}") + } + return this +} + +inline fun Long.ensureUnixCallResult(op: String, predicate: (Long) -> Boolean): Long { + if (!predicate(this)) { + throw Error("$op: ${strerror(posix_errno())!!.toKString()}") + } + return this +} + +inline fun ULong.ensureUnixCallResult(op: String, predicate: (ULong) -> Boolean): ULong { + if (!predicate(this)) { + throw Error("$op: ${strerror(posix_errno())!!.toKString()}") + } + return this +} + +private fun Int.isMinusOne() = (this == -1) +private fun Long.isMinusOne() = (this == -1L) +private fun ULong.isMinusOne() = (this == ULong.MAX_VALUE) diff --git a/kotlin-native/samples/gitchurn/README.md b/kotlin-native/samples/gitchurn/README.md new file mode 100644 index 00000000000..c17c130ecc5 --- /dev/null +++ b/kotlin-native/samples/gitchurn/README.md @@ -0,0 +1,16 @@ +# GIT frequency analyzer + +This example shows how one could perform statistics on Git repository. + +Install libgit2 development files. +For Debian-like Linux - use `apt-get install libgit2-dev`. +For Windows - `pacman -S mingw-w64-x86_64-libgit2` in MinGW64 console, if you do +not have MSYS2-MinGW64 installed - install it first as described in http://www.msys2.org + +To build use `../gradlew assemble`. + +To run use `../gradlew runReleaseExecutableGitChurn` or execute the program directly: + + ./build/bin/gitChurn/main/release/executable/gitchurn.kexe ../../ + +It will print most frequently modified (by number of commits) files in repository. diff --git a/kotlin-native/samples/gitchurn/build.gradle.kts b/kotlin-native/samples/gitchurn/build.gradle.kts new file mode 100644 index 00000000000..825991898b3 --- /dev/null +++ b/kotlin-native/samples/gitchurn/build.gradle.kts @@ -0,0 +1,41 @@ +plugins { + kotlin("multiplatform") +} + +val mingwPath = File(System.getenv("MINGW64_DIR") ?: "C:/msys64/mingw64") + +kotlin { + // Determine host preset. + val hostOs = System.getProperty("os.name") + val isMingwX64 = hostOs.startsWith("Windows") + + // Create a target for the host platform. + val hostTarget = when { + hostOs == "Mac OS X" -> macosX64("gitChurn") + hostOs == "Linux" -> linuxX64("gitChurn") + isMingwX64 -> mingwX64("gitChurn") + else -> throw GradleException("Host OS '$hostOs' is not supported in Kotlin/Native $project.") + } + + hostTarget.apply { + binaries { + executable { + entryPoint = "sample.gitchurn.main" + if (isMingwX64) { + linkerOpts("-L${mingwPath.resolve("lib")}") + runTask?.environment("PATH" to mingwPath.resolve("bin")) + } + runTask?.args(rootProject.rootDir.resolve("..")) + } + } + compilations["main"].cinterops { + val libgit2 by creating { + when (preset) { + presets["macosX64"] -> includeDirs.headerFilterOnly("/opt/local/include", "/usr/local/include") + presets["linuxX64"] -> includeDirs.headerFilterOnly("/usr/include") + presets["mingwX64"] -> includeDirs.headerFilterOnly(mingwPath.resolve("include")) + } + } + } + } +} diff --git a/kotlin-native/samples/gitchurn/gradle.properties b/kotlin-native/samples/gitchurn/gradle.properties new file mode 100644 index 00000000000..790a07d5124 --- /dev/null +++ b/kotlin-native/samples/gitchurn/gradle.properties @@ -0,0 +1,2 @@ +kotlin.code.style=official +kotlin.import.noCommonSourceSets=true diff --git a/kotlin-native/samples/gitchurn/src/gitChurnMain/kotlin/GitChurn.kt b/kotlin-native/samples/gitchurn/src/gitChurnMain/kotlin/GitChurn.kt new file mode 100644 index 00000000000..60410ba4148 --- /dev/null +++ b/kotlin-native/samples/gitchurn/src/gitChurnMain/kotlin/GitChurn.kt @@ -0,0 +1,92 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the license/LICENSE.txt file. + */ + +package sample.gitchurn + +import kotlinx.cinterop.* +import libgit2.git_time_t +import platform.posix.ctime +import platform.posix.time_tVar + +fun main(args: Array) { + if (args.isEmpty()) + return help() + + val workDir = args[0] + + val limit = if (args.size > 1) { + val limitRaw = args[1].toIntOrNull() + if (limitRaw == null || limitRaw <= 0) { + return help("Not a positive integer: $limitRaw") + } + limitRaw + } else + Int.MAX_VALUE + + try { + calculateChurn(workDir, limit) + } catch (e: GitException) { + help(e.message) + } +} + +private fun calculateChurn(workDir: String, limit: Int) { + println("Opening…") + val repository = git.repository(workDir) + val map = mutableMapOf() + var count = 0 + val commits = repository.commits() + val limited = commits.take(limit) + println("Calculating…") + limited.forEach { commit -> + if (count % 100 == 0) + println("Commit #$count [${commit.time.format()}]: ${commit.summary}") + + commit.parents.forEach { parent -> + val diff = commit.tree.diff(parent.tree) + diff.deltas().forEach { delta -> + val path = delta.newPath + val n = map[path] ?: 0 + map.put(path, n + 1) + } + diff.close() + parent.close() + } + commit.close() + count++ + } + println("Report:") + map.toList().sortedByDescending { it.second }.take(10).forEach { + println("File: ${it.first}") + println(" ${it.second}") + println() + } + + repository.close() + git.close() +} + +private fun git_time_t.format() = memScoped { + val commitTime = alloc() + commitTime.value = this@format + ctime(commitTime.ptr)!!.toKString().trim() +} + + +private fun printTree(commit: GitCommit) { + commit.tree.entries().forEach { entry -> + when (entry) { + is GitTreeEntry.File -> println(" ${entry.name}") + is GitTreeEntry.Folder -> println(" /${entry.name} (${entry.subtree.entries().size})") + } + } +} + +private fun help(errorMessage: String? = null) { + errorMessage?.let { + println("ERROR: $it") + } + println("./gitchurn.kexe []") +} diff --git a/kotlin-native/samples/gitchurn/src/gitChurnMain/kotlin/GitCommit.kt b/kotlin-native/samples/gitchurn/src/gitChurnMain/kotlin/GitCommit.kt new file mode 100644 index 00000000000..7b12183345f --- /dev/null +++ b/kotlin-native/samples/gitchurn/src/gitChurnMain/kotlin/GitCommit.kt @@ -0,0 +1,33 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the license/LICENSE.txt file. + */ + +package sample.gitchurn + +import kotlinx.cinterop.* +import libgit2.* + +class GitCommit(val repository: GitRepository, val commit: CPointer) { + fun close() = git_commit_free(commit) + + val summary: String get() = git_commit_summary(commit)!!.toKString() + val time: git_time_t get() = git_commit_time(commit) + + val tree: GitTree get() = memScoped { + val treePtr = allocPointerTo() + git_commit_tree(treePtr.ptr, commit).errorCheck() + GitTree(repository, treePtr.value!!) + } + + val parents: List get() = memScoped { + val count = git_commit_parentcount(commit).toInt() + val result = ArrayList(count) + for (index in 0..count - 1) { + val commitPtr = allocPointerTo() + git_commit_parent(commitPtr.ptr, commit, index.toUInt()).errorCheck() + result.add(GitCommit(repository, commitPtr.value!!)) + } + result + } +} \ No newline at end of file diff --git a/kotlin-native/samples/gitchurn/src/gitChurnMain/kotlin/GitDiff.kt b/kotlin-native/samples/gitchurn/src/gitChurnMain/kotlin/GitDiff.kt new file mode 100644 index 00000000000..b5d73643422 --- /dev/null +++ b/kotlin-native/samples/gitchurn/src/gitChurnMain/kotlin/GitDiff.kt @@ -0,0 +1,45 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the license/LICENSE.txt file. + */ + +package sample.gitchurn + +import kotlinx.cinterop.* +import libgit2.* + +class GitDiff(val repository: GitRepository, val handle: CPointer) { + fun deltas(): List { + val size = git_diff_num_deltas(handle).toInt() + val results = ArrayList(size) + for (index in 0..size - 1) { + val delta = git_diff_get_delta(handle, index.convert()) + results.add(GifDiffDelta(this, delta!!)) + } + return results + } + + fun close() { + git_diff_free(handle) + } + +} + +class GifDiffDelta(val diff: GitDiff, val handle: CPointer) { + + val status get() = handle.pointed.status + val newPath get() = handle.pointed.new_file.path!!.toKString() + val oldPath get() = handle.pointed.old_file.path!!.toKString() + + fun status(): String { + return when (status) { + GIT_DELTA_ADDED -> "A" + GIT_DELTA_DELETED -> "D" + GIT_DELTA_MODIFIED -> "M" + GIT_DELTA_RENAMED -> "R" + GIT_DELTA_COPIED -> "C" + else -> throw Exception("Unsupported delta status $status") + } + } + +} diff --git a/kotlin-native/samples/gitchurn/src/gitChurnMain/kotlin/GitRemote.kt b/kotlin-native/samples/gitchurn/src/gitChurnMain/kotlin/GitRemote.kt new file mode 100644 index 00000000000..18a65ee8772 --- /dev/null +++ b/kotlin-native/samples/gitchurn/src/gitChurnMain/kotlin/GitRemote.kt @@ -0,0 +1,16 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the license/LICENSE.txt file. + */ + +package sample.gitchurn + +import kotlinx.cinterop.* +import libgit2.* + +class GitRemote(val repository: GitRepository, val handle: CPointer) { + fun close() = git_remote_free(handle) + + val url: String get() = git_remote_url(handle)!!.toKString() + val name: String = git_remote_name(handle)!!.toKString() +} \ No newline at end of file diff --git a/kotlin-native/samples/gitchurn/src/gitChurnMain/kotlin/GitRepository.kt b/kotlin-native/samples/gitchurn/src/gitChurnMain/kotlin/GitRepository.kt new file mode 100644 index 00000000000..b10f23d37f6 --- /dev/null +++ b/kotlin-native/samples/gitchurn/src/gitChurnMain/kotlin/GitRepository.kt @@ -0,0 +1,63 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the license/LICENSE.txt file. + */ + +package sample.gitchurn + +import kotlinx.cinterop.* +import libgit2.* + +class GitRepository(val location: String) { + val arena = Arena() + val handle: CPointer = memScoped { + val loc = allocPointerTo() + git_repository_open(loc.ptr, location).errorCheck() + loc.value!! + } + + fun close() { + git_repository_free(handle) + arena.clear() + } + + fun remotes(): List = memScoped { + val remoteList = alloc() + git_remote_list(remoteList.ptr, handle).errorCheck() + val size = remoteList.count.toInt() + val list = ArrayList(size) + for (index in 0..size - 1) { + val array = remoteList.strings!! + val name = array[index]!!.toKString() + val remotePtr = allocPointerTo() + git_remote_lookup(remotePtr.ptr, handle, name).errorCheck() + list.add(GitRemote(this@GitRepository, remotePtr.value!!)) + } + list + } + + fun commits(): Sequence = memScoped { + val walkPtr = allocPointerTo() + git_revwalk_new(walkPtr.ptr, handle).errorCheck() + val walk = walkPtr.value + git_revwalk_sorting(walk, GIT_SORT_TOPOLOGICAL or GIT_SORT_TIME) + git_revwalk_push_head(walk).errorCheck() + generateSequence { + memScoped { + val oid = alloc() + val result = git_revwalk_next(oid.ptr, walk) + + when (result) { + 0 -> { + val commitPtr = allocPointerTo() + git_commit_lookup(commitPtr.ptr, handle, oid.ptr).errorCheck() + val commit = commitPtr.value!! + GitCommit(this@GitRepository, commit) + } + GIT_ITEROVER -> null + else -> throw Exception("Unexpected result code $result") + } + } + } + } +} \ No newline at end of file diff --git a/kotlin-native/samples/gitchurn/src/gitChurnMain/kotlin/GitTree.kt b/kotlin-native/samples/gitchurn/src/gitChurnMain/kotlin/GitTree.kt new file mode 100644 index 00000000000..03d78325939 --- /dev/null +++ b/kotlin-native/samples/gitchurn/src/gitChurnMain/kotlin/GitTree.kt @@ -0,0 +1,50 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the license/LICENSE.txt file. + */ + +package sample.gitchurn + +import kotlinx.cinterop.* +import libgit2.* + +class GitTree(val repository: GitRepository, val handle: CPointer) { + fun close() = git_tree_free(handle) + + fun entries(): List = memScoped { + val size = git_tree_entrycount(handle).toInt() + val entries = ArrayList(size) + for (index in 0..size - 1) { + val treeEntry = git_tree_entry_byindex(handle, index.convert())!! + val entryType = git_tree_entry_type(treeEntry) + val entry = when (entryType) { + GIT_OBJ_TREE -> memScoped { + val id = git_tree_entry_id(treeEntry) + val treePtr = allocPointerTo() + git_tree_lookup(treePtr.ptr, repository.handle, id) + GitTreeEntry.Folder(this@GitTree, treeEntry, treePtr.value!!) + } + GIT_OBJ_BLOB -> GitTreeEntry.File(this@GitTree, treeEntry) + else -> throw Exception("Unsupported entry type $entryType") + } + entries.add(entry) + } + entries + } + + fun diff(other: GitTree): GitDiff = memScoped { + val diffPtr = allocPointerTo() + git_diff_tree_to_tree(diffPtr.ptr, repository.handle, handle, other.handle, null).errorCheck() + GitDiff(repository, diffPtr.value!!) + } +} + +sealed class GitTreeEntry(val tree: GitTree, val handle: CPointer) { + val name: String get() = git_tree_entry_name(handle)!!.toKString() + + class Folder(tree: GitTree, handle: CPointer, val subtreeHandle: CPointer) : GitTreeEntry(tree, handle) { + val subtree = GitTree(tree.repository, subtreeHandle) + } + + class File(tree: GitTree, handle: CPointer) : GitTreeEntry(tree, handle) +} diff --git a/kotlin-native/samples/gitchurn/src/gitChurnMain/kotlin/git.kt b/kotlin-native/samples/gitchurn/src/gitChurnMain/kotlin/git.kt new file mode 100644 index 00000000000..5ecb1d6413c --- /dev/null +++ b/kotlin-native/samples/gitchurn/src/gitChurnMain/kotlin/git.kt @@ -0,0 +1,33 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the license/LICENSE.txt file. + */ + +package sample.gitchurn + +import kotlinx.cinterop.* +import libgit2.* + +object git { + init { + git_libgit2_init() + } + + fun close() { + git_libgit2_shutdown() + } + + fun repository(location: String): GitRepository { + return GitRepository(location) + } +} + +fun Int.errorCheck() { + if (this == 0) return + throw GitException() +} + +class GitException : Exception(run { + val err = giterr_last() + err!!.pointed.message!!.toKString() +}) \ No newline at end of file diff --git a/kotlin-native/samples/gitchurn/src/nativeInterop/cinterop/libgit2.def b/kotlin-native/samples/gitchurn/src/nativeInterop/cinterop/libgit2.def new file mode 100644 index 00000000000..377332016f4 --- /dev/null +++ b/kotlin-native/samples/gitchurn/src/nativeInterop/cinterop/libgit2.def @@ -0,0 +1,5 @@ +headers = git2.h +headerFilter = git2/** git2.h +linkerOpts.osx = -L/opt/local/lib -L/usr/local/lib -lgit2 +linkerOpts.linux = -L/usr/lib64 -L/usr/lib/x86_64-linux-gnu -lgit2 +linkerOpts.mingw = -lgit2 diff --git a/kotlin-native/samples/globalState/README.md b/kotlin-native/samples/globalState/README.md new file mode 100644 index 00000000000..d5e55550ebb --- /dev/null +++ b/kotlin-native/samples/globalState/README.md @@ -0,0 +1,9 @@ +# Shared global state + +This example shows how one could implement global shared state using interop mechanisms. + +To build use `../gradlew assemble`. + +To run use `../gradlew runReleaseExecutableGlobalState` or execute the program directly: + + ./build/bin/globalState/main/release/executable/globalState.kexe diff --git a/kotlin-native/samples/globalState/build.gradle.kts b/kotlin-native/samples/globalState/build.gradle.kts new file mode 100644 index 00000000000..6cb4b781a53 --- /dev/null +++ b/kotlin-native/samples/globalState/build.gradle.kts @@ -0,0 +1,27 @@ +plugins { + kotlin("multiplatform") +} + +kotlin { + // Determine host preset. + val hostOs = System.getProperty("os.name") + + // Create target for the host platform. + val hostTarget = when { + hostOs == "Mac OS X" -> macosX64("globalState") + hostOs == "Linux" -> linuxX64("globalState") + hostOs.startsWith("Windows") -> mingwX64("globalState") + else -> throw GradleException("Host OS '$hostOs' is not supported in Kotlin/Native $project.") + } + + hostTarget.apply { + binaries { + executable { + entryPoint = "sample.globalstate.main" + } + } + compilations["main"].cinterops { + val global by creating + } + } +} diff --git a/kotlin-native/samples/globalState/gradle.properties b/kotlin-native/samples/globalState/gradle.properties new file mode 100644 index 00000000000..790a07d5124 --- /dev/null +++ b/kotlin-native/samples/globalState/gradle.properties @@ -0,0 +1,2 @@ +kotlin.code.style=official +kotlin.import.noCommonSourceSets=true diff --git a/kotlin-native/samples/globalState/src/globalStateMain/kotlin/Global.kt b/kotlin-native/samples/globalState/src/globalStateMain/kotlin/Global.kt new file mode 100644 index 00000000000..4fa60b882c2 --- /dev/null +++ b/kotlin-native/samples/globalState/src/globalStateMain/kotlin/Global.kt @@ -0,0 +1,74 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the license/LICENSE.txt file. + */ + +package sample.globalstate + +import kotlin.native.concurrent.* +import kotlinx.cinterop.* +import platform.posix.* + +inline fun Int.ensureUnixCallResult(op: String, predicate: (Int) -> Boolean = { x -> x == 0} ): Int { + if (!predicate(this)) { + throw Error("$op: ${strerror(posix_errno())!!.toKString()}") + } + return this +} + +data class SharedDataMember(val double: Double) + +data class SharedData(val string: String, val int: Int, val member: SharedDataMember) + +// Here we access the same shared frozen Kotlin object from multiple threads. +val globalObject: SharedData? + get() = sharedData.frozenKotlinObject?.asStableRef()?.get() + +fun dumpShared(prefix: String) { + println(""" + $prefix: ${pthread_self()} x=${sharedData.x} f=${sharedData.f} s=${sharedData.string!!.toKString()} + """.trimIndent()) +} + +fun main() { + // Arena owning all native allocs. + val arena = Arena() + + // Assign global data. + sharedData.x = 239 + sharedData.f = 0.5f + sharedData.string = "Hello Kotlin!".cstr.getPointer(arena) + + // Here we create detached mutable object, which could be later reattached by another thread. + sharedData.kotlinObject = DetachedObjectGraph { + SharedData("A string", 42, SharedDataMember(2.39)) + }.asCPointer() + + // Here we create shared frozen object reference, + val stableRef = StableRef.create(SharedData("Shared", 239, SharedDataMember(2.71)).freeze()) + sharedData.frozenKotlinObject = stableRef.asCPointer() + dumpShared("thread1") + println("frozen is $globalObject") + + // Start a new thread, that sees the variable. + // memScoped is needed to pass thread's local address to pthread_create(). + memScoped { + val thread = alloc() + pthread_create(thread.ptr, null, staticCFunction { argC -> + initRuntimeIfNeeded() + dumpShared("thread2") + val kotlinObject = DetachedObjectGraph(sharedData.kotlinObject).attach() + val arg = DetachedObjectGraph(argC).attach() + println("thread arg is $arg Kotlin object is $kotlinObject frozen is $globalObject") + // Workaround for compiler issue. + null as COpaquePointer? + }, DetachedObjectGraph { SharedDataMember(3.14)}.asCPointer() ).ensureUnixCallResult("pthread_create") + pthread_join(thread.value, null).ensureUnixCallResult("pthread_join") + } + + // At this moment we do not need data stored in shared data, so clean up the data + // and free memory. + sharedData.string = null + stableRef.dispose() + arena.clear() +} diff --git a/kotlin-native/samples/globalState/src/nativeInterop/cinterop/global.def b/kotlin-native/samples/globalState/src/nativeInterop/cinterop/global.def new file mode 100644 index 00000000000..f4391051aa9 --- /dev/null +++ b/kotlin-native/samples/globalState/src/nativeInterop/cinterop/global.def @@ -0,0 +1,12 @@ +package = sample.globalstate + +--- +typedef struct { + int x; + float f; + char* string; + void* kotlinObject; + void* frozenKotlinObject; +} SharedDataStruct; + +SharedDataStruct sharedData; diff --git a/kotlin-native/samples/gradle.properties b/kotlin-native/samples/gradle.properties new file mode 100644 index 00000000000..3782789d9b7 --- /dev/null +++ b/kotlin-native/samples/gradle.properties @@ -0,0 +1,15 @@ +kotlin.code.style=official + +# Run parallel builds in Gradle: +org.gradle.parallel=true +org.gradle.workers.max=4 + +# Pin Kotlin version: +# CHANGE_VERSION_WITH_RELEASE +kotlin_version=1.4.10 + +# Use custom Kotlin/Native home: +kotlin.native.home=../../dist + +# Increase memory for in-process compiler execution. +org.gradle.jvmargs=-Xmx3g \ No newline at end of file diff --git a/kotlin-native/samples/gradle/wrapper/gradle-wrapper.jar b/kotlin-native/samples/gradle/wrapper/gradle-wrapper.jar new file mode 100644 index 00000000000..e708b1c023e Binary files /dev/null and b/kotlin-native/samples/gradle/wrapper/gradle-wrapper.jar differ diff --git a/kotlin-native/samples/gradle/wrapper/gradle-wrapper.properties b/kotlin-native/samples/gradle/wrapper/gradle-wrapper.properties new file mode 100644 index 00000000000..12d38de6a48 --- /dev/null +++ b/kotlin-native/samples/gradle/wrapper/gradle-wrapper.properties @@ -0,0 +1,5 @@ +distributionBase=GRADLE_USER_HOME +distributionPath=wrapper/dists +distributionUrl=https\://services.gradle.org/distributions/gradle-6.6.1-bin.zip +zipStoreBase=GRADLE_USER_HOME +zipStorePath=wrapper/dists diff --git a/kotlin-native/samples/gradlew b/kotlin-native/samples/gradlew new file mode 100755 index 00000000000..4f906e0c811 --- /dev/null +++ b/kotlin-native/samples/gradlew @@ -0,0 +1,185 @@ +#!/usr/bin/env sh + +# +# Copyright 2015 the original author or authors. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# https://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +############################################################################## +## +## Gradle start up script for UN*X +## +############################################################################## + +# Attempt to set APP_HOME +# Resolve links: $0 may be a link +PRG="$0" +# Need this for relative symlinks. +while [ -h "$PRG" ] ; do + ls=`ls -ld "$PRG"` + link=`expr "$ls" : '.*-> \(.*\)$'` + if expr "$link" : '/.*' > /dev/null; then + PRG="$link" + else + PRG=`dirname "$PRG"`"/$link" + fi +done +SAVED="`pwd`" +cd "`dirname \"$PRG\"`/" >/dev/null +APP_HOME="`pwd -P`" +cd "$SAVED" >/dev/null + +APP_NAME="Gradle" +APP_BASE_NAME=`basename "$0"` + +# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"' + +# Use the maximum available, or set MAX_FD != -1 to use that value. +MAX_FD="maximum" + +warn () { + echo "$*" +} + +die () { + echo + echo "$*" + echo + exit 1 +} + +# OS specific support (must be 'true' or 'false'). +cygwin=false +msys=false +darwin=false +nonstop=false +case "`uname`" in + CYGWIN* ) + cygwin=true + ;; + Darwin* ) + darwin=true + ;; + MINGW* ) + msys=true + ;; + NONSTOP* ) + nonstop=true + ;; +esac + +CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar + + +# Determine the Java command to use to start the JVM. +if [ -n "$JAVA_HOME" ] ; then + if [ -x "$JAVA_HOME/jre/sh/java" ] ; then + # IBM's JDK on AIX uses strange locations for the executables + JAVACMD="$JAVA_HOME/jre/sh/java" + else + JAVACMD="$JAVA_HOME/bin/java" + fi + if [ ! -x "$JAVACMD" ] ; then + die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME + +Please set the JAVA_HOME variable in your environment to match the +location of your Java installation." + fi +else + JAVACMD="java" + which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. + +Please set the JAVA_HOME variable in your environment to match the +location of your Java installation." +fi + +# Increase the maximum file descriptors if we can. +if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then + MAX_FD_LIMIT=`ulimit -H -n` + if [ $? -eq 0 ] ; then + if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then + MAX_FD="$MAX_FD_LIMIT" + fi + ulimit -n $MAX_FD + if [ $? -ne 0 ] ; then + warn "Could not set maximum file descriptor limit: $MAX_FD" + fi + else + warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT" + fi +fi + +# For Darwin, add options to specify how the application appears in the dock +if $darwin; then + GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\"" +fi + +# For Cygwin or MSYS, switch paths to Windows format before running java +if [ "$cygwin" = "true" -o "$msys" = "true" ] ; then + APP_HOME=`cygpath --path --mixed "$APP_HOME"` + CLASSPATH=`cygpath --path --mixed "$CLASSPATH"` + + JAVACMD=`cygpath --unix "$JAVACMD"` + + # We build the pattern for arguments to be converted via cygpath + ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null` + SEP="" + for dir in $ROOTDIRSRAW ; do + ROOTDIRS="$ROOTDIRS$SEP$dir" + SEP="|" + done + OURCYGPATTERN="(^($ROOTDIRS))" + # Add a user-defined pattern to the cygpath arguments + if [ "$GRADLE_CYGPATTERN" != "" ] ; then + OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)" + fi + # Now convert the arguments - kludge to limit ourselves to /bin/sh + i=0 + for arg in "$@" ; do + CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -` + CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option + + if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition + eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"` + else + eval `echo args$i`="\"$arg\"" + fi + i=`expr $i + 1` + done + case $i in + 0) set -- ;; + 1) set -- "$args0" ;; + 2) set -- "$args0" "$args1" ;; + 3) set -- "$args0" "$args1" "$args2" ;; + 4) set -- "$args0" "$args1" "$args2" "$args3" ;; + 5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;; + 6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;; + 7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;; + 8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;; + 9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;; + esac +fi + +# Escape application args +save () { + for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done + echo " " +} +APP_ARGS=`save "$@"` + +# Collect all arguments for the java command, following the shell quoting and substitution rules +eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS" + +exec "$JAVACMD" "$@" diff --git a/kotlin-native/samples/gradlew.bat b/kotlin-native/samples/gradlew.bat new file mode 100644 index 00000000000..ac1b06f9382 --- /dev/null +++ b/kotlin-native/samples/gradlew.bat @@ -0,0 +1,89 @@ +@rem +@rem Copyright 2015 the original author or authors. +@rem +@rem Licensed under the Apache License, Version 2.0 (the "License"); +@rem you may not use this file except in compliance with the License. +@rem You may obtain a copy of the License at +@rem +@rem https://www.apache.org/licenses/LICENSE-2.0 +@rem +@rem Unless required by applicable law or agreed to in writing, software +@rem distributed under the License is distributed on an "AS IS" BASIS, +@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +@rem See the License for the specific language governing permissions and +@rem limitations under the License. +@rem + +@if "%DEBUG%" == "" @echo off +@rem ########################################################################## +@rem +@rem Gradle startup script for Windows +@rem +@rem ########################################################################## + +@rem Set local scope for the variables with windows NT shell +if "%OS%"=="Windows_NT" setlocal + +set DIRNAME=%~dp0 +if "%DIRNAME%" == "" set DIRNAME=. +set APP_BASE_NAME=%~n0 +set APP_HOME=%DIRNAME% + +@rem Resolve any "." and ".." in APP_HOME to make it shorter. +for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi + +@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m" + +@rem Find java.exe +if defined JAVA_HOME goto findJavaFromJavaHome + +set JAVA_EXE=java.exe +%JAVA_EXE% -version >NUL 2>&1 +if "%ERRORLEVEL%" == "0" goto execute + +echo. +echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. +echo. +echo Please set the JAVA_HOME variable in your environment to match the +echo location of your Java installation. + +goto fail + +:findJavaFromJavaHome +set JAVA_HOME=%JAVA_HOME:"=% +set JAVA_EXE=%JAVA_HOME%/bin/java.exe + +if exist "%JAVA_EXE%" goto execute + +echo. +echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% +echo. +echo Please set the JAVA_HOME variable in your environment to match the +echo location of your Java installation. + +goto fail + +:execute +@rem Setup the command line + +set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar + + +@rem Execute Gradle +"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %* + +:end +@rem End local scope for the variables with windows NT shell +if "%ERRORLEVEL%"=="0" goto mainEnd + +:fail +rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of +rem the _cmd.exe /c_ return code! +if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 +exit /b 1 + +:mainEnd +if "%OS%"=="Windows_NT" endlocal + +:omega diff --git a/kotlin-native/samples/gtk/README.md b/kotlin-native/samples/gtk/README.md new file mode 100644 index 00000000000..cb70baa55cb --- /dev/null +++ b/kotlin-native/samples/gtk/README.md @@ -0,0 +1,39 @@ +# GTK application + +This example shows how one may use _Kotlin/Native_ to build GUI +applications with the GTK toolkit. + +To build use `../gradlew assemble`. + +Do not forget to install GTK3. See bellow. + +To run on Mac also install XQuartz X server (https://www.xquartz.org/), and then `../gradlew runReleaseExecutableGtk` or execute the program directly: + + ./build/bin/gtk/main/release/executable/gtk.kexe + +Dialog box with the button will be shown, and application will print message +and terminate on button click. + + +#### GTK3 Install + +on Mac use + + brew install gtk+3 + +or + + port install gtk3 + +on Debian flavours of Linux + + sudo apt-get install libgtk-3-dev + +on Fedora + + sudo dnf install gtk3-devel + +on Windows in MinGW64 console, if you do +not have MSYS2-MinGW64 installed - install it first as described in http://www.msys2.org + + pacman -S mingw-w64-x86_64-gtk3 diff --git a/kotlin-native/samples/gtk/build.gradle.kts b/kotlin-native/samples/gtk/build.gradle.kts new file mode 100644 index 00000000000..4f2c0aaab29 --- /dev/null +++ b/kotlin-native/samples/gtk/build.gradle.kts @@ -0,0 +1,69 @@ +plugins { + kotlin("multiplatform") +} + +val mingwPath = File(System.getenv("MINGW64_DIR") ?: "C:/msys64/mingw64") + +kotlin { + // Determine host preset. + val hostOs = System.getProperty("os.name") + val isMingwX64 = hostOs.startsWith("Windows") + + // Create a target for the host platform. + val hostTarget = when { + hostOs == "Mac OS X" -> macosX64("gtk") + hostOs == "Linux" -> linuxX64("gtk") + isMingwX64 -> mingwX64("gtk") + else -> throw GradleException("Host OS '$hostOs' is not supported in Kotlin/Native $project.") + } + + hostTarget.apply { + binaries { + executable { + entryPoint = "sample.gtk.main" + if (isMingwX64) { + linkerOpts("-L${mingwPath.resolve("lib")}") + runTask?.environment("PATH" to mingwPath.resolve("bin")) + } + } + } + compilations["main"].cinterops { + val gtk3 by creating { + when (preset) { + presets["macosX64"], presets["linuxX64"] -> { + listOf("/opt/local/include", "/usr/include", "/usr/local/include").forEach { + includeDirs( + "$it/atk-1.0", + "$it/gdk-pixbuf-2.0", + "$it/cairo", + "$it/harfbuzz", + "$it/pango-1.0", + "$it/gtk-3.0", + "$it/glib-2.0" + ) + } + + includeDirs( + "/opt/local/lib/glib-2.0/include", + "/usr/lib/x86_64-linux-gnu/glib-2.0/include", + "/usr/local/lib/glib-2.0/include" + ) + } + presets["mingwX64"] -> { + listOf( + "include/atk-1.0", + "include/gdk-pixbuf-2.0", + "include/cairo", + "include/pango-1.0", + "include/gtk-3.0", + "include/glib-2.0", + "lib/glib-2.0/include" + ).forEach { + includeDirs(mingwPath.resolve(it)) + } + } + } + } + } + } +} \ No newline at end of file diff --git a/kotlin-native/samples/gtk/gradle.properties b/kotlin-native/samples/gtk/gradle.properties new file mode 100644 index 00000000000..f833920c5d7 --- /dev/null +++ b/kotlin-native/samples/gtk/gradle.properties @@ -0,0 +1,3 @@ +kotlin.native.jvmArgs=-Xmx8g +kotlin.code.style=official +kotlin.import.noCommonSourceSets=true diff --git a/kotlin-native/samples/gtk/src/gtkMain/kotlin/Main.kt b/kotlin-native/samples/gtk/src/gtkMain/kotlin/Main.kt new file mode 100644 index 00000000000..c09de4f268a --- /dev/null +++ b/kotlin-native/samples/gtk/src/gtkMain/kotlin/Main.kt @@ -0,0 +1,56 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the license/LICENSE.txt file. + */ + +package sample.gtk + +import kotlinx.cinterop.* +import gtk3.* + +// Note that all callback parameters must be primitive types or nullable C pointers. +fun > g_signal_connect(obj: CPointer<*>, actionName: String, + action: CPointer, data: gpointer? = null, connect_flags: GConnectFlags = 0u) { + g_signal_connect_data(obj.reinterpret(), actionName, action.reinterpret(), + data = data, destroy_data = null, connect_flags = connect_flags) + +} + +fun activate(app: CPointer?, user_data: gpointer?) { + val windowWidget = gtk_application_window_new(app)!! + val window = windowWidget.reinterpret() + gtk_window_set_title(window, "Window") + gtk_window_set_default_size(window, 200, 200) + + val button_box = gtk_button_box_new( + GtkOrientation.GTK_ORIENTATION_HORIZONTAL)!! + gtk_container_add(window.reinterpret(), button_box) + + val button = gtk_button_new_with_label("Konan говорит: click me!")!! + g_signal_connect(button, "clicked", + staticCFunction { _: CPointer?, _: gpointer? -> println("Hi Kotlin") + }) + g_signal_connect(button, "clicked", + staticCFunction { widget: CPointer? -> + gtk_widget_destroy(widget) + }, + window, G_CONNECT_SWAPPED) + gtk_container_add (button_box.reinterpret(), button) + + gtk_widget_show_all(windowWidget) +} + +fun gtkMain(args: Array): Int { + val app = gtk_application_new("org.gtk.example", G_APPLICATION_FLAGS_NONE)!! + g_signal_connect(app, "activate", staticCFunction(::activate)) + val status = memScoped { + g_application_run(app.reinterpret(), + args.size, args.map { it.cstr.ptr }.toCValues()) + } + g_object_unref(app) + return status +} + +fun main(args: Array) { + gtkMain(args) +} diff --git a/kotlin-native/samples/gtk/src/nativeInterop/cinterop/gtk3.def b/kotlin-native/samples/gtk/src/nativeInterop/cinterop/gtk3.def new file mode 100644 index 00000000000..51c5e6f6d23 --- /dev/null +++ b/kotlin-native/samples/gtk/src/nativeInterop/cinterop/gtk3.def @@ -0,0 +1,9 @@ +headers = gtk/gtk.h +headerFilter = gtk/* gobject/* gio/* +compilerOpts.osx = -I/usr/local/include/gtk-3.0 -I/usr/local/include/glib-2.0 -I/usr/local/lib/glib-2.0/include \ +-I/usr/local/include/pango-1.0 -I/usr/local/include/cairo -I/usr/local/include -I/usr/local/include/gdk-pixbuf-2.0 \ +-I/usr/local/include/atk-1.0 +compilerOpts.linux = -I/usr/lib/x86_64-linux-gnu/glib-2.0/include -I/usr/local/lib/glib-2.0/include -I/usr/lib64/glib-2.0/include +linkerOpts.osx = -L/opt/local/lib -L/usr/local/lib -lglib-2.0 -lgdk-3.0 -lgtk-3 -lgio-2.0 -lgobject-2.0 +linkerOpts.linux = -L/usr/lib64 -L/usr/lib/x86_64-linux-gnu -lglib-2.0 -lgdk-3 -lgtk-3 -lgio-2.0 -lgobject-2.0 +linkerOpts.mingw = -lglib-2.0 -lgdk-3 -lgtk-3 -lgio-2.0 -lgobject-2.0 diff --git a/kotlin-native/samples/html5Canvas/README.md b/kotlin-native/samples/html5Canvas/README.md new file mode 100644 index 00000000000..24e19a4da9f --- /dev/null +++ b/kotlin-native/samples/html5Canvas/README.md @@ -0,0 +1,15 @@ +# HTML5 Canvas + +This sample shows how to use Kotlin/Native to build a WebAssembly application and how to call JavaScript functions +from a Kotlin/Native code. + +> __Note__: If you build this sample not from the Kotlin/Native repository, you need to specify a path to a +Kotlin/Native distribution. Add the following snippet in `gradle.properties`: +>``` +>kotlin.native.home= +>``` +> The default distribution path is `$HOME/.konan/kotlin-native--`. + +To build use `../gradlew assemble`. + +To run use `../gradlew runProgram`. \ No newline at end of file diff --git a/kotlin-native/samples/html5Canvas/build.gradle.kts b/kotlin-native/samples/html5Canvas/build.gradle.kts new file mode 100644 index 00000000000..1eb51b6f234 --- /dev/null +++ b/kotlin-native/samples/html5Canvas/build.gradle.kts @@ -0,0 +1,97 @@ +import org.jetbrains.kotlin.gradle.dsl.KotlinJvmCompile +import org.jetbrains.kotlin.gradle.targets.jvm.KotlinJvmTarget +import org.jetbrains.kotlin.gradle.tasks.AbstractKotlinNativeCompile + +plugins { + kotlin("multiplatform") +} + +repositories { + jcenter() + maven("https://dl.bintray.com/kotlin/ktor") +} + +val hostOs = System.getProperty("os.name") +val isWindows = hostOs.startsWith("Windows") + +val packageName = "kotlinx.interop.wasm.dom" +val jsinteropKlibFile = buildDir.resolve("klib").resolve("$packageName-jsinterop.klib") + +kotlin { + wasm32("html5Canvas") { + binaries { + executable { + entryPoint = "sample.html5canvas.main" + } + } + } + jvm("httpServer") + sourceSets { + val html5CanvasMain by getting { + dependencies { + implementation(files(jsinteropKlibFile)) + } + } + val httpServerMain by getting { + dependencies { + implementation("io.ktor:ktor-server-netty:1.2.1") + } + } + } +} + +val jsinterop by tasks.creating(Exec::class) { + workingDir = projectDir + + val ext = if (isWindows) ".bat" else "" + val distributionPath = project.properties["kotlin.native.home"] as String? + + if (distributionPath != null) { + val jsinteropCommand = file(distributionPath).resolve("bin").resolve("jsinterop$ext") + + inputs.property("jsinteropCommand", jsinteropCommand) + inputs.property("jsinteropPackageName", packageName) + outputs.file(jsinteropKlibFile) + + commandLine( + jsinteropCommand, + "-pkg", packageName, + "-o", jsinteropKlibFile, + "-target", "wasm32" + ) + } else { + doFirst { + // Abort build execution if the distribution path isn't specified. + throw GradleException( + """ + | + |Kotlin/Native distribution path must be specified to build the JavaScript interop. + |Use 'kotlin.native.home' project property to specify it. + """.trimMargin() + ) + } + } +} + +tasks.withType(AbstractKotlinNativeCompile::class).all { + dependsOn(jsinterop) +} + +val assemble by tasks.getting + +// This is to run embedded HTTP server with Ktor: +val runProgram by tasks.creating(JavaExec::class) { + dependsOn(assemble) + + val httpServer: KotlinJvmTarget by kotlin.targets + val httpServerMainCompilation = httpServer.compilations["main"] + + main = "sample.html5canvas.httpserver.HttpServer" + classpath = files(httpServerMainCompilation.output) + httpServerMainCompilation.runtimeDependencyFiles + args = listOf(projectDir.toString()) +} + +tasks.withType(KotlinJvmCompile::class).all { + runProgram.dependsOn(this) + kotlinOptions.jvmTarget = "1.8" +} diff --git a/kotlin-native/samples/html5Canvas/gradle.properties b/kotlin-native/samples/html5Canvas/gradle.properties new file mode 100644 index 00000000000..790a07d5124 --- /dev/null +++ b/kotlin-native/samples/html5Canvas/gradle.properties @@ -0,0 +1,2 @@ +kotlin.code.style=official +kotlin.import.noCommonSourceSets=true diff --git a/kotlin-native/samples/html5Canvas/index.html b/kotlin-native/samples/html5Canvas/index.html new file mode 100644 index 00000000000..a51ba19f7a6 --- /dev/null +++ b/kotlin-native/samples/html5Canvas/index.html @@ -0,0 +1,14 @@ + + + + + + + + + + +

Draw something using the mouse!

+ + + diff --git a/kotlin-native/samples/html5Canvas/src/html5CanvasMain/kotlin/main.kt b/kotlin-native/samples/html5Canvas/src/html5CanvasMain/kotlin/main.kt new file mode 100644 index 00000000000..4104fb998ca --- /dev/null +++ b/kotlin-native/samples/html5Canvas/src/html5CanvasMain/kotlin/main.kt @@ -0,0 +1,53 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the license/LICENSE.txt file. + */ + +package sample.html5canvas + +import kotlinx.interop.wasm.dom.* +import kotlinx.wasm.jsinterop.* + +fun main() { + + val canvas = document.getElementById("myCanvas").asCanvas + val ctx = canvas.getContext("2d") + val rect = canvas.getBoundingClientRect() + val rectLeft = rect.left + val rectTop = rect.top + + var mouseX: Int = 0 + var mouseY: Int = 0 + var draw: Boolean = false + + document.setter("onmousemove") { arguments: ArrayList -> + val event = MouseEvent(arguments[0]) + mouseX = event.getInt("clientX") - rectLeft + mouseY = event.getInt("clientY") - rectTop + + if (mouseX < 0) mouseX = 0 + if (mouseX > 639) mouseX = 639 + if (mouseY < 0) mouseY = 0 + if (mouseY > 479) mouseY = 479 + } + + document.setter("onmousedown") { + draw = true + } + + document.setter("onmouseup") { + draw = false + } + + setInterval(10) { + if (draw) { + ctx.strokeStyle = "#222222" + ctx.lineTo(mouseX, mouseY) + ctx.stroke() + } else { + ctx.moveTo(mouseX, mouseY) + ctx.stroke() + } + } +} + diff --git a/kotlin-native/samples/html5Canvas/src/httpServerMain/kotlin/HttpServer.kt b/kotlin-native/samples/html5Canvas/src/httpServerMain/kotlin/HttpServer.kt new file mode 100644 index 00000000000..a9e76dc20ba --- /dev/null +++ b/kotlin-native/samples/html5Canvas/src/httpServerMain/kotlin/HttpServer.kt @@ -0,0 +1,59 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the license/LICENSE.txt file. + */ + +@file:JvmName("HttpServer") + +package sample.html5canvas.httpserver + +import io.ktor.application.call +import io.ktor.http.ContentType +import io.ktor.http.content.LocalFileContent +import io.ktor.http.content.default +import io.ktor.http.content.files +import io.ktor.http.content.static +import io.ktor.response.respond +import io.ktor.routing.get +import io.ktor.routing.routing +import io.ktor.server.engine.embeddedServer +import io.ktor.server.netty.Netty +import java.io.File + +fun main(args: Array) { + + check(args.size == 1) { "Invalid number of arguments: $args.\nExpected one argument with content root." } + + val contentRoot = File(args[0]) + check(contentRoot.isDirectory) { "Invalid content root: $contentRoot." } + + println( + """ + + IMPORTANT: Please open http://localhost:8080/ in your browser! + + To stop embedded HTTP server use Ctrl+C (Cmd+C for Mac OS X). + + """.trimIndent() + ) + + val server = embeddedServer(Netty, 8080) { + routing { + val wasm = "build/bin/html5Canvas/releaseExecutable/html5Canvas.wasm" + get(wasm) { + // TODO: ktor as of now doesn't know about 'application/wasm'. + // The newer browsers (firefox and chrome at least) don't allow + // 'application/octet-stream' for wasm anymore. + // We provide the proper content type here and, + // at the same time, put it into the ktor database. + // Remove this whole get() clause when ktor fix is available. + call.respond(LocalFileContent(File(wasm), ContentType("application", "wasm"))) + } + static("/") { + files(contentRoot) + default("index.html") + } + } + } + server.start(wait = true) +} diff --git a/kotlin-native/samples/libcurl/README.md b/kotlin-native/samples/libcurl/README.md new file mode 100644 index 00000000000..4d25128baa2 --- /dev/null +++ b/kotlin-native/samples/libcurl/README.md @@ -0,0 +1,13 @@ +# Curl interop library + +This example shows how to build and publish an interop library to communicate with the libcurl, +HTTP/HTTPS/FTP/etc client library. + +Install libcurl development files. For Mac - `brew install curl`. For Debian-like Linux - use `apt-get install libcurl4-openssl-dev` or `apt-get install libcurl4-gnutls-dev`. +For Windows - `pacman -S mingw-w64-x86_64-curl` in MinGW64 console, if you do +not have MSYS2-MinGW64 installed - install it first as described in http://www.msys2.org + +To build use `../gradlew assemble`. + +To publish the library into a local repo use `../gradlew publish`. + diff --git a/kotlin-native/samples/libcurl/build.gradle.kts b/kotlin-native/samples/libcurl/build.gradle.kts new file mode 100644 index 00000000000..f6f0bfdff67 --- /dev/null +++ b/kotlin-native/samples/libcurl/build.gradle.kts @@ -0,0 +1,62 @@ +plugins { + kotlin("multiplatform") + `maven-publish` +} + +group = "org.jetbrains.kotlin.sample.native" +version = "1.0" + +val localRepo = rootProject.file("build/.m2-local") + +publishing { + repositories { + maven("file://$localRepo") + } +} + +val cleanLocalRepo by tasks.creating(Delete::class) { + delete(localRepo) +} + +val mingwPath = File(System.getenv("MINGW64_DIR") ?: "C:/msys64/mingw64") + +kotlin { + + // Determine host preset. + val hostOs = System.getProperty("os.name") + + // Create target for the host platform. + val hostTarget = when { + hostOs == "Mac OS X" -> macosX64("libcurl") + hostOs == "Linux" -> linuxX64("libcurl") + hostOs.startsWith("Windows") -> mingwX64("libcurl") + else -> throw GradleException("Host OS '$hostOs' is not supported in Kotlin/Native $project.") + } + + hostTarget.apply { + compilations["main"].cinterops { + val libcurl by creating { + when (preset) { + presets["macosX64"] -> includeDirs.headerFilterOnly("/opt/local/include", "/usr/local/include") + presets["linuxX64"] -> includeDirs.headerFilterOnly("/usr/include", "/usr/include/x86_64-linux-gnu") + presets["mingwX64"] -> includeDirs.headerFilterOnly(mingwPath.resolve("include")) + } + } + } + + mavenPublication { + pom { + withXml { + val root = asNode() + root.appendNode("name", "libcurl interop library") + root.appendNode("description", "A library providing interoperability with host libcurl") + } + } + } + } + + // Enable experimental stdlib API used by the sample. + sourceSets.all { + languageSettings.useExperimentalAnnotation("kotlin.ExperimentalStdlibApi") + } +} diff --git a/kotlin-native/samples/libcurl/gradle.properties b/kotlin-native/samples/libcurl/gradle.properties new file mode 100644 index 00000000000..790a07d5124 --- /dev/null +++ b/kotlin-native/samples/libcurl/gradle.properties @@ -0,0 +1,2 @@ +kotlin.code.style=official +kotlin.import.noCommonSourceSets=true diff --git a/kotlin-native/samples/libcurl/src/libcurlMain/kotlin/CUrl.kt b/kotlin-native/samples/libcurl/src/libcurlMain/kotlin/CUrl.kt new file mode 100644 index 00000000000..f6d7260a1c0 --- /dev/null +++ b/kotlin-native/samples/libcurl/src/libcurlMain/kotlin/CUrl.kt @@ -0,0 +1,71 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the license/LICENSE.txt file. + */ + +package sample.libcurl + +import kotlinx.cinterop.* +import platform.posix.size_t +import libcurl.* + +class CUrl(url: String) { + private val stableRef = StableRef.create(this) + + private val curl = curl_easy_init() + + init { + curl_easy_setopt(curl, CURLOPT_URL, url) + val header = staticCFunction(::header_callback) + curl_easy_setopt(curl, CURLOPT_HEADERFUNCTION, header) + curl_easy_setopt(curl, CURLOPT_HEADERDATA, stableRef.asCPointer()) + val writeData = staticCFunction(::write_callback) + curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, writeData) + curl_easy_setopt(curl, CURLOPT_WRITEDATA, stableRef.asCPointer()) + } + + val header = Event() + val body = Event() + + fun nobody(){ + curl_easy_setopt(curl, CURLOPT_NOBODY, 1L) + } + + fun fetch() { + val res = curl_easy_perform(curl) + if (res != CURLE_OK) + println("curl_easy_perform() failed: ${curl_easy_strerror(res)?.toKString()}") + } + + fun close() { + curl_easy_cleanup(curl) + stableRef.dispose() + } +} + +fun CPointer.toKString(length: Int): String { + val bytes = this.readBytes(length) + return bytes.decodeToString() +} + +fun header_callback(buffer: CPointer?, size: size_t, nitems: size_t, userdata: COpaquePointer?): size_t { + if (buffer == null) return 0u + if (userdata != null) { + val header = buffer.toKString((size * nitems).toInt()).trim() + val curl = userdata.asStableRef().get() + curl.header(header) + } + return size * nitems +} + + +fun write_callback(buffer: CPointer?, size: size_t, nitems: size_t, userdata: COpaquePointer?): size_t { + if (buffer == null) return 0u + if (userdata != null) { + val data = buffer.toKString((size * nitems).toInt()).trim() + val curl = userdata.asStableRef().get() + curl.body(data) + } + return size * nitems +} + diff --git a/kotlin-native/samples/libcurl/src/libcurlMain/kotlin/Event.kt b/kotlin-native/samples/libcurl/src/libcurlMain/kotlin/Event.kt new file mode 100644 index 00000000000..4eddfe809af --- /dev/null +++ b/kotlin-native/samples/libcurl/src/libcurlMain/kotlin/Event.kt @@ -0,0 +1,34 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the license/LICENSE.txt file. + */ + +package sample.libcurl + +typealias EventHandler = (T) -> Unit +class Event { + private var handlers = emptyList>() + + fun subscribe(handler: EventHandler) { + handlers += handler + } + + fun unsubscribe(handler: EventHandler) { + handlers -= handler + } + + operator fun plusAssign(handler: EventHandler) = subscribe(handler) + operator fun minusAssign(handler: EventHandler) = unsubscribe(handler) + + operator fun invoke(value: T) { + var exception: Throwable? = null + for (handler in handlers) { + try { + handler(value) + } catch (e: Throwable) { + exception = e + } + } + exception?.let { throw it } + } +} \ No newline at end of file diff --git a/kotlin-native/samples/libcurl/src/nativeInterop/cinterop/libcurl.def b/kotlin-native/samples/libcurl/src/nativeInterop/cinterop/libcurl.def new file mode 100644 index 00000000000..79775cad0c7 --- /dev/null +++ b/kotlin-native/samples/libcurl/src/nativeInterop/cinterop/libcurl.def @@ -0,0 +1,5 @@ +headers = curl/curl.h +headerFilter = curl/* +linkerOpts.osx = -L/opt/local/lib -L/usr/local/opt/curl/lib -lcurl +linkerOpts.linux = -L/usr/lib64 -L/usr/lib/x86_64-linux-gnu -lcurl +linkerOpts.mingw = -lcurl diff --git a/kotlin-native/samples/nonBlockingEchoServer/README.md b/kotlin-native/samples/nonBlockingEchoServer/README.md new file mode 100644 index 00000000000..c7601aad8e3 --- /dev/null +++ b/kotlin-native/samples/nonBlockingEchoServer/README.md @@ -0,0 +1,25 @@ +# Non-blocking echo server demo + +This sample shows how to implement multi-client server using coroutines. +IO operations are implemented using non-blocking OS calls, and instead coroutines +are being suspended and resumed whenever relevant. + +Thus, while server can process multiple connections concurrently, +each individual connection handler is written in simple linear manner. + +To build use `../gradlew assemble`. + +To run use `../gradlew runReleaseExecutableNonBlockingEchoServer` or execute the program directly: + + ./build/bin/nonBlockingEchoServer/main/release/executable/nonBlockingEchoServer.kexe 3000 & + +Test the server by connecting to it, for example with telnet: + + telnet localhost 3000 + +Write something to console and watch server echoing it back. +Concurrently connect from another terminal. Note that each connection gets its own +connection id prefixed to echo response. + +~~Quit telnet by pressing ctrl+] ctrl+D~~ + diff --git a/kotlin-native/samples/nonBlockingEchoServer/build.gradle.kts b/kotlin-native/samples/nonBlockingEchoServer/build.gradle.kts new file mode 100644 index 00000000000..46449d22811 --- /dev/null +++ b/kotlin-native/samples/nonBlockingEchoServer/build.gradle.kts @@ -0,0 +1,25 @@ +plugins { + kotlin("multiplatform") +} + +kotlin { + // Determine host preset. + val hostOs = System.getProperty("os.name") + + // Create target for the host platform. + val hostTarget = when { + hostOs == "Mac OS X" -> macosX64("nonBlockingEchoServer") + hostOs == "Linux" -> linuxX64("nonBlockingEchoServer") + hostOs.startsWith("Windows") -> mingwX64("nonBlockingEchoServer") + else -> throw GradleException("Host OS '$hostOs' is not supported in Kotlin/Native $project.") + } + + hostTarget.apply { + binaries { + executable { + entryPoint = "sample.nbechoserver.main" + runTask?.args(3000) + } + } + } +} \ No newline at end of file diff --git a/kotlin-native/samples/nonBlockingEchoServer/gradle.properties b/kotlin-native/samples/nonBlockingEchoServer/gradle.properties new file mode 100644 index 00000000000..790a07d5124 --- /dev/null +++ b/kotlin-native/samples/nonBlockingEchoServer/gradle.properties @@ -0,0 +1,2 @@ +kotlin.code.style=official +kotlin.import.noCommonSourceSets=true diff --git a/kotlin-native/samples/nonBlockingEchoServer/src/nonBlockingEchoServerMain/kotlin/EchoServer.kt b/kotlin-native/samples/nonBlockingEchoServer/src/nonBlockingEchoServerMain/kotlin/EchoServer.kt new file mode 100644 index 00000000000..ae31d0b31ad --- /dev/null +++ b/kotlin-native/samples/nonBlockingEchoServer/src/nonBlockingEchoServerMain/kotlin/EchoServer.kt @@ -0,0 +1,214 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the license/LICENSE.txt file. + */ + +package sample.nbechoserver + +import kotlinx.cinterop.* +import platform.posix.* +import kotlin.coroutines.* +import kotlin.coroutines.intrinsics.* + +fun main(args: Array) { + if (args.isEmpty()) { + println("Usage: nonBlockingEchoServer.kexe ") + return + } + + val port = args[0].toShort() + + memScoped { + + val serverAddr = alloc() + + val listenFd = socket(AF_INET, SOCK_STREAM, 0) + .ensureUnixCallResult { !it.isMinusOne() } + + with(serverAddr) { + memset(this.ptr, 0, sockaddr_in.size.convert()) + sin_family = AF_INET.convert() + sin_addr.s_addr = posix_htons(0).convert() + sin_port = posix_htons(port).convert() + } + + bind(listenFd, serverAddr.ptr.reinterpret(), sockaddr_in.size.toUInt()) + .ensureUnixCallResult { it == 0 } + + fcntl(listenFd, F_SETFL, O_NONBLOCK) + .ensureUnixCallResult { it == 0 } + + listen(listenFd, 10) + .ensureUnixCallResult { it == 0 } + + var connectionId = 0 + acceptClientsAndRun(listenFd) { + memScoped { + val bufferLength = 100uL + val buffer = allocArray(bufferLength.toLong()) + val connectionIdString = "#${++connectionId}: ".cstr + val connectionIdBytes = connectionIdString.ptr + + try { + while (true) { + val length = read(buffer, bufferLength) + + if (length == 0uL) + break + + write(connectionIdBytes, connectionIdString.size.toULong()) + write(buffer, length) + } + } catch (e: IOException) { + println("I/O error occured: ${e.message}") + } + } + } + } +} + +sealed class WaitingFor { + class Accept : WaitingFor() + + class Read(val data: CArrayPointer, + val length: ULong, + val continuation: Continuation) : WaitingFor() + + class Write(val data: CArrayPointer, + val length: ULong, + val continuation: Continuation) : WaitingFor() +} + +class Client(val clientFd: Int, val waitingList: MutableMap) { + suspend fun read(data: CArrayPointer, dataLength: ULong): ULong { + val length = read(clientFd, data, dataLength) + if (length >= 0) + return length.toULong() + if (posix_errno() != EWOULDBLOCK) + throw IOException(getUnixError()) + // Save continuation and suspend. + return suspendCoroutine { continuation -> + waitingList.put(clientFd, WaitingFor.Read(data, dataLength, continuation)) + } + } + + suspend fun write(data: CArrayPointer, length: ULong) { + val written = write(clientFd, data, length) + if (written >= 0) + return + if (posix_errno() != EWOULDBLOCK) + throw IOException(getUnixError()) + // Save continuation and suspend. + return suspendCoroutine { continuation -> + waitingList.put(clientFd, WaitingFor.Write(data, length, continuation)) + } + } +} + +open class EmptyContinuation(override val context: CoroutineContext = EmptyCoroutineContext) : Continuation { + companion object : EmptyContinuation() + override fun resumeWith(result: Result) { result.getOrThrow() } +} + +fun acceptClientsAndRun(serverFd: Int, block: suspend Client.() -> Unit) { + memScoped { + val waitingList = mutableMapOf(serverFd to WaitingFor.Accept()) + val readfds = alloc() + val writefds = alloc() + val errorfds = alloc() + var maxfd = serverFd + while (true) { + posix_FD_ZERO(readfds.ptr) + posix_FD_ZERO(writefds.ptr) + posix_FD_ZERO(errorfds.ptr) + for ((socketFd, watingFor) in waitingList) { + when (watingFor) { + is WaitingFor.Accept -> posix_FD_SET(socketFd, readfds.ptr) + is WaitingFor.Read -> posix_FD_SET(socketFd, readfds.ptr) + is WaitingFor.Write -> posix_FD_SET(socketFd, writefds.ptr) + } + posix_FD_SET(socketFd, errorfds.ptr) + } + pselect(maxfd + 1, readfds.ptr, writefds.ptr, errorfds.ptr, null, null) + .ensureUnixCallResult { it >= 0 } + loop@for (socketFd in 0..maxfd) { + val waitingFor = waitingList[socketFd] + val errorOccured = posix_FD_ISSET(socketFd, errorfds.ptr) != 0 + if (posix_FD_ISSET(socketFd, readfds.ptr) != 0 + || posix_FD_ISSET(socketFd, writefds.ptr) != 0 + || errorOccured) { + when (waitingFor) { + is WaitingFor.Accept -> { + if (errorOccured) + throw Error("Socket has been closed externally") + + // Accept new client. + val clientFd = accept(serverFd, null, null) + if (clientFd.isMinusOne()) { + if (posix_errno() != EWOULDBLOCK) + throw Error(getUnixError()) + break@loop + } + fcntl(clientFd, F_SETFL, O_NONBLOCK) + .ensureUnixCallResult { it == 0 } + if (maxfd < clientFd) + maxfd = clientFd + block.startCoroutine(Client(clientFd, waitingList), EmptyContinuation) + } + is WaitingFor.Read -> { + if (errorOccured) + waitingFor.continuation.resumeWithException(IOException("Connection was closed by peer")) + + // Resume reading operation. + waitingList.remove(socketFd) + val length = read(socketFd, waitingFor.data, waitingFor.length) + if (length < 0) // Read error. + waitingFor.continuation.resumeWithException(IOException(getUnixError())) + waitingFor.continuation.resume(length.toULong()) + } + is WaitingFor.Write -> { + if (errorOccured) + waitingFor.continuation.resumeWithException(IOException("Connection was closed by peer")) + + // Resume writing operation. + waitingList.remove(socketFd) + val written = write(socketFd, waitingFor.data, waitingFor.length) + if (written < 0) // Write error. + waitingFor.continuation.resumeWithException(IOException(getUnixError())) + waitingFor.continuation.resume(Unit) + } + } + } + } + } + } +} + +class IOException(message: String): RuntimeException(message) + +fun getUnixError() = strerror(posix_errno())!!.toKString() + +inline fun Int.ensureUnixCallResult(predicate: (Int) -> Boolean): Int { + if (!predicate(this)) { + throw Error(getUnixError()) + } + return this +} + +inline fun Long.ensureUnixCallResult(predicate: (Long) -> Boolean): Long { + if (!predicate(this)) { + throw Error(getUnixError()) + } + return this +} + +inline fun ULong.ensureUnixCallResult(predicate: (ULong) -> Boolean): ULong { + if (!predicate(this)) { + throw Error(getUnixError()) + } + return this +} + +private fun Int.isMinusOne() = (this == -1) +private fun Long.isMinusOne() = (this == -1L) +private fun ULong.isMinusOne() = (this == ULong.MAX_VALUE) diff --git a/kotlin-native/samples/objc/build.gradle.kts b/kotlin-native/samples/objc/build.gradle.kts new file mode 100644 index 00000000000..6fb69738b9b --- /dev/null +++ b/kotlin-native/samples/objc/build.gradle.kts @@ -0,0 +1,13 @@ +plugins { + kotlin("multiplatform") +} + +kotlin { + macosX64("objc") { + binaries { + executable { + entryPoint = "sample.objc.main" + } + } + } +} \ No newline at end of file diff --git a/kotlin-native/samples/objc/gradle.properties b/kotlin-native/samples/objc/gradle.properties new file mode 100644 index 00000000000..790a07d5124 --- /dev/null +++ b/kotlin-native/samples/objc/gradle.properties @@ -0,0 +1,2 @@ +kotlin.code.style=official +kotlin.import.noCommonSourceSets=true diff --git a/kotlin-native/samples/objc/src/objcMain/kotlin/Async.kt b/kotlin-native/samples/objc/src/objcMain/kotlin/Async.kt new file mode 100644 index 00000000000..78517f043d7 --- /dev/null +++ b/kotlin-native/samples/objc/src/objcMain/kotlin/Async.kt @@ -0,0 +1,104 @@ +package sample.objc + +import kotlinx.cinterop.staticCFunction +import platform.Foundation.NSOperationQueue +import platform.Foundation.NSThread +import platform.darwin.dispatch_async_f +import platform.darwin.dispatch_get_main_queue +import platform.darwin.dispatch_sync_f +import kotlin.native.concurrent.* +import kotlin.test.assertNotNull + +inline fun executeAsync(queue: NSOperationQueue, crossinline producerConsumer: () -> Pair Unit>) { + dispatch_async_f(queue.underlyingQueue, DetachedObjectGraph { + producerConsumer() + }.asCPointer(), staticCFunction { it -> + val result = DetachedObjectGraph Unit>>(it).attach() + result.second(result.first) + }) +} + +inline fun mainContinuation(singleShot: Boolean = true, noinline block: () -> Unit) = Continuation0( + block, staticCFunction { invokerArg -> + if (NSThread.isMainThread()) { + invokerArg!!.callContinuation0() + } else { + dispatch_sync_f(dispatch_get_main_queue(), invokerArg, staticCFunction { args -> + args!!.callContinuation0() + }) + } +}, singleShot) + +inline fun mainContinuation(singleShot: Boolean = true, noinline block: (T1) -> Unit) = Continuation1( + block, staticCFunction { invokerArg -> + if (NSThread.isMainThread()) { + invokerArg!!.callContinuation1() + } else { + dispatch_sync_f(dispatch_get_main_queue(), invokerArg, staticCFunction { args -> + args!!.callContinuation1() + }) + } +}, singleShot) + +inline fun mainContinuation(singleShot: Boolean = true, noinline block: (T1, T2) -> Unit) = Continuation2( + block, staticCFunction { invokerArg -> + if (NSThread.isMainThread()) { + invokerArg!!.callContinuation2() + } else { + dispatch_sync_f(dispatch_get_main_queue(), invokerArg, staticCFunction { args -> + args!!.callContinuation2() + }) + } +}, singleShot) + +// This object allows to create frozen Kotlin continuations suitable for execution on other threads/queues. +// It takes frozen operation and any after call, and creates lambda which could be used to run operation +// anywhere and provide result to `after` callback. +@ThreadLocal +object Continuator { + val map = mutableMapOf>() + + fun wrap(operation: () -> Unit, after: () -> Unit): () -> Unit { + assert(NSThread.isMainThread()) + assert(operation.isFrozen) + val id = Any().freeze() + map[id] = Pair(0, after) + return { + initRuntimeIfNeeded() + operation() + executeAsync(NSOperationQueue.mainQueue) { + Pair(id, { id: Any -> Continuator.execute(id) }) + } + }.freeze() + } + + fun

wrap(operation: () -> P, block: (P) -> Unit): () -> Unit { + assert(NSThread.isMainThread()) + assert(operation.isFrozen) + val id = Any().freeze() + map[id] = Pair(1, block) + return { + initRuntimeIfNeeded() + // Note, that operation here must return detachable value (for example, frozen). + executeAsync(NSOperationQueue.mainQueue) { + Pair(Pair(id, operation()), { it: Pair -> + Continuator.execute(it.first, it.second) + }) + } + }.freeze() + } + + fun execute(id: Any) { + val countAndBlock = map.remove(id) + assertNotNull(countAndBlock) + assert(countAndBlock.first == 0) + (countAndBlock.second as Function0)() + } + + fun

execute(id: Any, parameter: P) { + val countAndBlock = map.remove(id) + assertNotNull(countAndBlock) + assert(countAndBlock.first == 1) + (countAndBlock.second as Function1)(parameter) + } +} diff --git a/kotlin-native/samples/objc/src/objcMain/kotlin/Window.kt b/kotlin-native/samples/objc/src/objcMain/kotlin/Window.kt new file mode 100644 index 00000000000..29a1024fbce --- /dev/null +++ b/kotlin-native/samples/objc/src/objcMain/kotlin/Window.kt @@ -0,0 +1,208 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +package sample.objc + +import kotlinx.cinterop.* +import platform.AppKit.* +import platform.Contacts.CNContactStore +import platform.Contacts.CNEntityType +import platform.Foundation.* +import platform.darwin.* +import platform.posix.QOS_CLASS_BACKGROUND +import platform.posix.memcpy +import kotlin.native.concurrent.* +import kotlin.test.assertNotNull + +data class QueryResult(val json: Map?, val error: String?) + +private fun MutableData.asNSData() = this.withPointerLocked { it, size -> + val result = NSMutableData.create(length = size.convert())!! + memcpy(result.mutableBytes, it, size.convert()) + result +} + +private fun MutableData.asJSON(): Map? = + NSJSONSerialization.JSONObjectWithData(this.asNSData(), 0, null) as? Map + +fun main() { + autoreleasepool { + runApp() + } +} + +val appDelegate = MyAppDelegate() + +private fun runApp() { + val app = NSApplication.sharedApplication() + + app.delegate = appDelegate + app.setActivationPolicy(NSApplicationActivationPolicy.NSApplicationActivationPolicyRegular) + app.activateIgnoringOtherApps(true) + + app.run() +} + + +class Controller : NSObject() { + private var index = 1 + private val httpDelegate = HttpDelegate() + + @ObjCAction + fun onClick() { + if (!appDelegate.canClick) { + appDelegate.contentText.string = "Another load in progress..." + return + } + + // Here we call continuator service to ensure we can access mutable state from continuation. + + dispatch_async(dispatch_get_global_queue(QOS_CLASS_BACKGROUND.convert(), 0), + Continuator.wrap({ println("In queue ${dispatch_get_current_queue()}")}.freeze()) { + println("After in queue ${dispatch_get_current_queue()}: $index") + }) + + appDelegate.canClick = false + // Fetch URL in the background on the button click. + httpDelegate.fetchUrl("https://jsonplaceholder.typicode.com/todos/${index++}") + } + + @ObjCAction + fun onQuit() { + NSApplication.sharedApplication().stop(this) + } + + @ObjCAction + fun onRequest() { + val addressBookRef = CNContactStore() + addressBookRef.requestAccessForEntityType(CNEntityType.CNEntityTypeContacts, mainContinuation { + granted, error -> + appDelegate.contentText.string = if (granted) + "Access granted!" + else + "Access denied: $error" + }) + } + + class HttpDelegate: NSObject(), NSURLSessionDataDelegateProtocol { + private val asyncQueue = NSOperationQueue() + private val receivedData = MutableData() + + init { + freeze() + } + + fun fetchUrl(url: String) { + receivedData.reset() + val session = NSURLSession.sessionWithConfiguration( + NSURLSessionConfiguration.defaultSessionConfiguration(), + this, + delegateQueue = asyncQueue + ) + session.dataTaskWithURL(NSURL(string = url)).resume() + } + + override fun URLSession(session: NSURLSession, dataTask: NSURLSessionDataTask, didReceiveData: NSData) { + initRuntimeIfNeeded() + receivedData.append(didReceiveData.bytes, didReceiveData.length.convert()) + } + + override fun URLSession(session: NSURLSession, task: NSURLSessionTask, didCompleteWithError: NSError?) { + initRuntimeIfNeeded() + + executeAsync(NSOperationQueue.mainQueue) { + val response = task.response as? NSHTTPURLResponse + Pair(when { + response == null -> QueryResult(null, didCompleteWithError?.localizedDescription) + response.statusCode.toInt() != 200 -> QueryResult(null, "${response.statusCode.toInt()})") + else -> QueryResult(receivedData.asJSON(), null) + }, { result: QueryResult -> + appDelegate.contentText.string = result.json?.toString() ?: "Error: ${result.error}" + appDelegate.canClick = true + }) + } + } + } +} + +class MyAppDelegate() : NSObject(), NSApplicationDelegateProtocol { + + private val window: NSWindow + private val controller = Controller() + val contentText: NSText + var canClick = true + + init { + val mainDisplayRect = NSScreen.mainScreen()!!.frame + val windowRect = mainDisplayRect.useContents { + NSMakeRect( + origin.x + size.width * 0.25, + origin.y + size.height * 0.25, + size.width * 0.5, + size.height * 0.5 + ) + } + + val windowStyle = NSWindowStyleMaskTitled or NSWindowStyleMaskMiniaturizable or + NSWindowStyleMaskClosable or NSWindowStyleMaskResizable + + window = NSWindow(windowRect, windowStyle, NSBackingStoreBuffered, false).apply { + title = "URL async fetcher" + opaque = true + hasShadow = true + preferredBackingLocation = NSWindowBackingLocationVideoMemory + hidesOnDeactivate = false + backgroundColor = NSColor.grayColor() + releasedWhenClosed = false + + val delegateImpl = object : NSObject(), NSWindowDelegateProtocol { + override fun windowShouldClose(sender: NSWindow): Boolean { + NSApplication.sharedApplication().stop(this) + return true + } + } + + // Wrapping to autoreleasepool is a workaround for false-positive memory leak detected: + // NSWindow.delegate setter appears to put the delegate to autorelease pool. + // Since this code runs during top-level val initializer, it misses the autoreleasepool in [main], + // so the object gets released too late. + autoreleasepool { + delegate = delegateImpl + } + } + + val buttonPress = NSButton(NSMakeRect(10.0, 10.0, 100.0, 40.0)).apply { + title = "Click" + target = controller + action = NSSelectorFromString("onClick") + } + window.contentView!!.addSubview(buttonPress) + val buttonQuit = NSButton(NSMakeRect(120.0, 10.0, 100.0, 40.0)).apply { + title = "Quit" + target = controller + action = NSSelectorFromString("onQuit") + } + window.contentView!!.addSubview(buttonQuit) + + val buttonRequest = NSButton(NSMakeRect(230.0, 10.0, 100.0, 40.0)).apply { + title = "Request" + target = controller + action = NSSelectorFromString("onRequest") + } + window.contentView!!.addSubview(buttonRequest) + + contentText = NSText(NSMakeRect(10.0, 80.0, 600.0, 350.0)).apply { + string = "Press 'Click' to start fetching" + verticallyResizable = false + horizontallyResizable = false + + } + window.contentView!!.addSubview(contentText) + } + + override fun applicationWillFinishLaunching(notification: NSNotification) { + window.makeKeyAndOrderFront(this) + } +} diff --git a/kotlin-native/samples/opengl/README.md b/kotlin-native/samples/opengl/README.md new file mode 100644 index 00000000000..f4e99586b82 --- /dev/null +++ b/kotlin-native/samples/opengl/README.md @@ -0,0 +1,13 @@ +# OpenGL application + +This example shows interaction with OpenGL library, to render classical 3D test model. Linux build requires `apt-get install freeglut3-dev` or similar, +MacOS shall work as is. + +To build use `../gradlew assemble`. + +To run use `../gradlew runReleaseExecutableOpengl` or execute the program directly: + + ./build/bin/opengl/main/release/executable/opengl.kexe + +It will render 3D model of teapot. Feel free to experiment with it, the whole power of OpenGL +is at your hands. diff --git a/kotlin-native/samples/opengl/build.gradle.kts b/kotlin-native/samples/opengl/build.gradle.kts new file mode 100644 index 00000000000..fbd3012308f --- /dev/null +++ b/kotlin-native/samples/opengl/build.gradle.kts @@ -0,0 +1,13 @@ +plugins { + kotlin("multiplatform") +} + +kotlin { + macosX64("opengl") { + binaries { + executable { + entryPoint = "sample.opengl.main" + } + } + } +} \ No newline at end of file diff --git a/kotlin-native/samples/opengl/gradle.properties b/kotlin-native/samples/opengl/gradle.properties new file mode 100644 index 00000000000..790a07d5124 --- /dev/null +++ b/kotlin-native/samples/opengl/gradle.properties @@ -0,0 +1,2 @@ +kotlin.code.style=official +kotlin.import.noCommonSourceSets=true diff --git a/kotlin-native/samples/opengl/src/openglMain/kotlin/OpenGlTeapot.kt b/kotlin-native/samples/opengl/src/openglMain/kotlin/OpenGlTeapot.kt new file mode 100644 index 00000000000..c94f9cf14cb --- /dev/null +++ b/kotlin-native/samples/opengl/src/openglMain/kotlin/OpenGlTeapot.kt @@ -0,0 +1,118 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the license/LICENSE.txt file. + */ + +package sample.opengl + +import kotlinx.cinterop.* +import platform.GLUT.* +import platform.OpenGL.* +import platform.OpenGLCommon.* + +// Ported from http://openglsamples.sourceforge.net/projects/index.php/blog/index/ + +private var rotation: GLfloat = 0.0f +private val rotationSpeed: GLfloat = 0.2f + +private val windowWidth = 640 +private val windowHeight = 480 + +fun display() { + // Clear Screen and Depth Buffer + glClear((GL_COLOR_BUFFER_BIT or GL_DEPTH_BUFFER_BIT).convert()) + glLoadIdentity() + + // Define a viewing transformation + gluLookAt(4.0, 2.0, 0.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0) + + // Push and pop the current matrix stack. + // This causes that translations and rotations on this matrix wont influence others. + + glPushMatrix() + glColor3f(1.0f, 0.0f, 0.0f) + glTranslatef(0.0f, 0.0f, 0.0f) + glRotatef(rotation, 0.0f, 1.0f, 0.0f) + glRotatef(90.0f, 0.0f, 1.0f, 0.0f) + + // Draw the teapot + glutSolidTeapot(1.0) + glPopMatrix() + + + rotation += rotationSpeed + glutSwapBuffers() +} + + +fun initialize() { + // select projection matrix + glMatrixMode(GL_PROJECTION) + + // set the viewport + glViewport(0, 0, windowWidth, windowHeight) + + // set matrix mode + glMatrixMode(GL_PROJECTION) + + // reset projection matrix + glLoadIdentity() + val aspect = windowWidth.toDouble() / windowHeight + + // set up a perspective projection matrix + gluPerspective(45.0, aspect, 1.0, 500.0) + + // specify which matrix is the current matrix + glMatrixMode(GL_MODELVIEW) + glShadeModel(GL_SMOOTH) + + // specify the clear value for the depth buffer + glClearDepth(1.0) + glEnable(GL_DEPTH_TEST) + glDepthFunc(GL_LEQUAL) + + // specify implementation-specific hints + glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST) + + glLightModelfv(GL_LIGHT_MODEL_AMBIENT, cValuesOf(0.1f, 0.1f, 0.1f, 1.0f)) + glLightfv(GL_LIGHT0, GL_DIFFUSE, cValuesOf(0.6f, 0.6f, 0.6f, 1.0f)) + glLightfv(GL_LIGHT0, GL_SPECULAR, cValuesOf(0.7f, 0.7f, 0.3f, 1.0f)) + + glEnable(GL_LIGHT0) + glEnable(GL_COLOR_MATERIAL) + glShadeModel(GL_SMOOTH) + glLightModeli(GL_LIGHT_MODEL_TWO_SIDE, GL_FALSE) + glDepthFunc(GL_LEQUAL) + glEnable(GL_DEPTH_TEST) + glEnable(GL_LIGHTING) + glEnable(GL_LIGHT0) + glClearColor(0.0f, 0.0f, 0.0f, 1.0f) +} + +fun main() { + // initialize and run program + memScoped { + val argc = alloc().apply { value = 0 } + glutInit(argc.ptr, null) // TODO: pass real args + } + + // Display Mode + glutInitDisplayMode((GLUT_RGB or GLUT_DOUBLE or GLUT_DEPTH).convert()) + + // Set window size + glutInitWindowSize(windowWidth, windowHeight) + + // create Window + glutCreateWindow("The GLUT Teapot") + + // register Display Function + glutDisplayFunc(staticCFunction(::display)) + + // register Idle Function + glutIdleFunc(staticCFunction(::display)) + + initialize() + + // run GLUT mainloop + glutMainLoop() +} \ No newline at end of file diff --git a/kotlin-native/samples/python_extension/README.md b/kotlin-native/samples/python_extension/README.md new file mode 100644 index 00000000000..8ae6b7d5dc3 --- /dev/null +++ b/kotlin-native/samples/python_extension/README.md @@ -0,0 +1,114 @@ +# C to Kotlin/Native interoperability example + +This example shows how to use Kotlin/Native programs from other execution environments, such as Python. +Python has C native interface, which could be used to organize a bridge with the +Kotlin/Native application. File `kotlin_bridge.c` contains translation code between Kotlin and Python +lands. This demo works on Linux, Windows (64-bit) or macOS hosts. + +To build and run the sample do the following: + +* Install Python with development headers, i.e. on Linux + ``` + sudo apt install python-dev + ``` + +* Run `build.sh`, it will ask for superuser password to install Python extension. + Use build.bat on Windows. +* On macOS copy Kotlin binary to extension's directory and change install name with + `install_name_tool` tool, i.e. + ``` + sudo cp ./build/libserver.dylib /Library/Python/2.7/site-packages/ + sudo install_name_tool /Library/Python/2.7/site-packages/kotlin_bridge.so \ + -change libserver.dylib @loader_path/libserver.dylib + ``` +* On Linux copy Kotlin binary in some place where libraries could be loaded from, i.e. + ``` + cp ./build/libserver.so /usr/local/lib/ + ldconfig + ``` + or modify dynamic loader search path with + ``` + export LD_LIBRARY_PATH=`pwd` + ``` + +* run Python code using Kotlin functionality with + ``` + python src/main/python/main.py + ``` +* it will show you result of using several Kotlin/Native APIs, accepting and returning both objects and + primitive types + + The example works as following. Kotlin/Native API is implemented in `Server.kt`, and we run Kotlin/Native compiler + with `-produce dynamic` option. Compiler produces two artifacts: `server_api.h` which is C language API + to all public functions and classes available in the application. `libserver.dylib` or `libserver.so` or `server.dll` + shared object contains C bridge to all above APIs. + + This C bridge looks like a C struct, reflecting all scopes in program, with operations available. For example, + for class Server +```c_cpp + class Server(val prefix: String) { + fun greet(session: Session) = "$prefix: Hello from Kotlin/Native in ${session}" + fun concat(session: Session, a: String, b: String) = "$prefix: $a $b in ${session}" + fun add(session: Session, a: Int, b: Int) = a + b + session.number + } +``` + following C API is produced +```c_cpp + typedef struct { + server_KNativePtr pinned; + } server_kref_demo_Session; + typedef struct { + server_KNativePtr pinned; + } server_kref_demo_Server; + + typedef struct { + /* Service functions. */ + void (*DisposeStablePointer)(server_KNativePtr ptr); + void (*DisposeString)(const char* string); + server_KBoolean (*IsInstance)(server_KNativePtr ref, const server_KType* type); + + /* User functions. */ + struct { + struct { + struct { + server_KType* (*_type)(void); + server_kref_demo_Session (*Session)(const char* name, server_KInt number); + } Session; + struct { + server_KType* (*_type)(void); + server_kref_demo_Server (*Server)(const char* prefix); + const char* (*greet)(server_kref_demo_Server thiz, server_kref_demo_Session session); + const char* (*concat)(server_kref_demo_Server thiz, server_kref_demo_Session session, const char* a, const char* b); + server_KInt (*add)(server_kref_demo_Server thiz, server_kref_demo_Session session, server_KInt a, server_KInt b); + } Server; + } demo; + } kotlin; + } server_ExportedSymbols; + extern server_ExportedSymbols* server_symbols(void); +``` + + So every class instance is represented with a single element structure, encapsulating stable pointer to an instance. + Once no longer needed, `DisposeStablePointer()` with that stable pointer shall be called, and if value is not stored + somewhere else - it is disposed. For primitive types and `kotlin.String` smart bridges converting to C primitive types + or to C strings (which has to be manually freed with `DisposeString()`) are implemented. + + For example, running constructor of class Server taking a string will look like + + server_kref_demo_Server server = server_symbols()->kotlin.demo.Server.Server("the server"); + + And disposing no longer needed instance will look like + + server_symbols()->DisposeStablePointer(server.pinned); + + To make code easier readable, macro definitions like + + #define T_(name) server_kref_demo_ ## name + #define __ server_symbols()-> + + will transform above, overly verbose lines to more readable + + T_(Server) server = __ kotlin.demo.Server.Server("the server"); + + `_type()` function will return opaque type pointer, which could be checked with `IsInstance()` operation, like + + __ IsInstance(ref.pinned, __ kotlin.demo.Server._type()) diff --git a/kotlin-native/samples/python_extension/build.bat b/kotlin-native/samples/python_extension/build.bat new file mode 100644 index 00000000000..2fcff0aa32c --- /dev/null +++ b/kotlin-native/samples/python_extension/build.bat @@ -0,0 +1,15 @@ +setlocal +set DIR=. + +if defined KONAN_HOME ( + set "PATH=%KONAN_HOME%\bin;%PATH%" +) else ( + set "PATH=..\..\dist\bin;..\..\bin;%PATH%" +) +kotlinc-native -p dynamic src/main/kotlin/Server.kt -o server + +rem Prepare MSVC build environment, and .lib file for linking with our .dll. +SET VS90COMNTOOLS=%VS140COMNTOOLS% +\Program Files (x86)\Microsoft Visual Studio 14.0\VC\bin\lib.exe" /def:server.def /out:server.lib /machine:X64 + +python src/main/python/setup.py install diff --git a/kotlin-native/samples/python_extension/build.sh b/kotlin-native/samples/python_extension/build.sh new file mode 100755 index 00000000000..f091f2cda3d --- /dev/null +++ b/kotlin-native/samples/python_extension/build.sh @@ -0,0 +1,23 @@ +#!/usr/bin/env bash + +DIR=$(cd "$(dirname "${BASH_SOURCE[0]}" )" && pwd ) + +if [ -z "$KONAN_HOME" ]; then + PATH="$DIR/../../dist/bin:$DIR/../../bin:$PATH" +else + PATH="$KONAN_HOME/bin:$PATH" +fi + +KONAN_USER_DIR=${KONAN_DATA_DIR:-"$HOME/.konan"} +KONAN_DEPS="$KONAN_USER_DIR/dependencies" + +# python3 shall work as well. +PYTHON=python + +mkdir -p $DIR/build +cd $DIR/build + +kotlinc-native -p dynamic $DIR/src/main/kotlin/Server.kt -o server + +cd $DIR +sudo -S $PYTHON ${DIR}/src/main/python/setup.py install diff --git a/kotlin-native/samples/python_extension/src/main/c/kotlin_bridge.c b/kotlin-native/samples/python_extension/src/main/c/kotlin_bridge.c new file mode 100644 index 00000000000..d010e9ff6fd --- /dev/null +++ b/kotlin-native/samples/python_extension/src/main/c/kotlin_bridge.c @@ -0,0 +1,145 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the license/LICENSE.txt file. + */ + +#include + +#include "server_api.h" + +#define __ server_symbols()-> +#define T_(name) server_kref_demo_ ## name + +// Note, that as we cache this in the global, and Kotlin/Native object references +// are currently thread local, we make this global a TLS variable. +#ifdef _MSC_VER +#define TLSVAR __declspec(thread) +#else +#define TLSVAR __thread +#endif + +static TLSVAR server_kref_demo_Server server = { 0 }; + +static T_(Server) getServer(void) { + if (!server.pinned) { + server = __ kotlin.root.demo.Server.Server("the server"); + } + return server; +} + +static T_(Session) getSession(PyObject* args) { + T_(Session) result = { 0 }; + long long pinned; + if (PyArg_ParseTuple(args, "L", &pinned)) { + result.pinned = (void*)(uintptr_t)pinned; + } + return result; +} + +static PyObject* open_session(PyObject* self, PyObject* args) { + PyObject *result = NULL; + char* string_arg = NULL; + int int_arg = 0; + if (PyArg_ParseTuple(args, "is", &int_arg, &string_arg)) { + T_(Session) session = __ kotlin.root.demo.Session.Session(string_arg, int_arg); + result = Py_BuildValue("L", session.pinned); + } + return result; +} + +static PyObject* close_session(PyObject* self, PyObject* args) { + T_(Session) session = getSession(args); + __ DisposeStablePointer(session.pinned); + __ DisposeStablePointer(getServer().pinned); + server.pinned = 0; + return Py_BuildValue("L", 0); +} + +static PyObject* greet_server(PyObject* self, PyObject* args) { + T_(Server) server = getServer(); + T_(Session) session = getSession(args); + const char* string = __ kotlin.root.demo.Server.greet(server, session); + PyObject* result = Py_BuildValue("s", string); + __ DisposeString(string); + return result; +} + +static PyObject* concat_server(PyObject* self, PyObject* args) { + long long session_arg; + char* string_arg1 = NULL; + char* string_arg2 = NULL; + PyObject* result = NULL; + + if (PyArg_ParseTuple(args, "Lss", &session_arg, &string_arg1, &string_arg2)) { + T_(Server) server = getServer(); + T_(Session) session = { (void*)(uintptr_t)session_arg }; + const char* string = __ kotlin.root.demo.Server.concat(server, session, string_arg1, string_arg2); + result = Py_BuildValue("s", string); + __ DisposeString(string); + } else { + result = Py_BuildValue("s", NULL); + } + return result; +} + +static PyObject* add_server(PyObject* self, PyObject* args) { + long long session_arg; + int int_arg1 = 0; + int int_arg2 = 0; + PyObject* result = NULL; + + if (PyArg_ParseTuple(args, "Lii", &session_arg, &int_arg1, &int_arg2)) { + T_(Server) server = getServer(); + T_(Session) session = { (void*)(uintptr_t)session_arg }; + int sum = __ kotlin.root.demo.Server.add(server, session, int_arg1, int_arg2); + result = Py_BuildValue("i", sum); + } else { + result = Py_BuildValue("i", 0); + } + return result; +} + +static PyMethodDef kotlin_bridge_funcs[] = { + { "open_session", (PyCFunction)open_session, METH_VARARGS, "Opens a session" }, + { "close_session", (PyCFunction)close_session, METH_VARARGS, "Closes the session" }, + { "greet_server", (PyCFunction)greet_server, METH_VARARGS, "Greeting service" }, + { "concat_server", (PyCFunction)concat_server, METH_VARARGS, "Concatenation service" }, + { "add_server", (PyCFunction)add_server, METH_VARARGS, "Addition service" }, + { NULL } +}; + +#if PY_MAJOR_VERSION >= 3 + +struct module_state { + server_kref_demo_Server server; +}; + +static int kotlin_bridge_traverse(PyObject *m, visitproc visit, void *arg) { + return 0; +} + +static int kotlin_bridge_clear(PyObject *m) { + return 0; +} + +static struct PyModuleDef moduledef = { + PyModuleDef_HEAD_INIT, + "kotlin_bridge", + NULL, + sizeof(struct module_state), + kotlin_bridge_funcs, + NULL, + kotlin_bridge_traverse, + kotlin_bridge_clear, + NULL +}; + +PyMODINIT_FUNC PyInit_kotlin_bridge(void) { + PyObject *module = PyModule_Create(&moduledef); + return module; +} +#else +void initkotlin_bridge(void) { + Py_InitModule3("kotlin_bridge", kotlin_bridge_funcs, "Kotlin/Native example module"); +} +#endif diff --git a/kotlin-native/samples/python_extension/src/main/kotlin/Server.kt b/kotlin-native/samples/python_extension/src/main/kotlin/Server.kt new file mode 100644 index 00000000000..ee137f8f94b --- /dev/null +++ b/kotlin-native/samples/python_extension/src/main/kotlin/Server.kt @@ -0,0 +1,14 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the license/LICENSE.txt file. + */ + +package demo + +class Session(val name: String, val number: Int) + +class Server(val prefix: String) { + fun greet(session: Session) = "$prefix: Hello from Kotlin/Native in ${session}" + fun concat(session: Session, a: String, b: String) = "$prefix: $a $b in ${session}" + fun add(session: Session, a: Int, b: Int) = a + b + session.number +} diff --git a/kotlin-native/samples/python_extension/src/main/python/main.py b/kotlin-native/samples/python_extension/src/main/python/main.py new file mode 100644 index 00000000000..bb7111128e5 --- /dev/null +++ b/kotlin-native/samples/python_extension/src/main/python/main.py @@ -0,0 +1,22 @@ +#!/usr/bin/python +# +# Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license +# that can be found in the license/LICENSE.txt file. +# + +import kotlin_bridge + +session = kotlin_bridge.open_session(239, 'konan') + +message = kotlin_bridge.greet_server(session) +print("Greet '{}'".format(message)) + +message = kotlin_bridge.concat_server(session, "Coding", "fun") +print("Concat '{}'".format(message)) + +message = kotlin_bridge.add_server(session, 1, 60) +print("Sum '{}'".format(message)) + + +kotlin_bridge.close_session(session) + diff --git a/kotlin-native/samples/python_extension/src/main/python/setup.py b/kotlin-native/samples/python_extension/src/main/python/setup.py new file mode 100644 index 00000000000..e8030fd991b --- /dev/null +++ b/kotlin-native/samples/python_extension/src/main/python/setup.py @@ -0,0 +1,34 @@ +#!/usr/bin/python +# +# Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license +# that can be found in the license/LICENSE.txt file. +# + +from distutils.core import setup, Extension + +setup(name='kotlin_bridge', + version='1.0', + maintainer = 'JetBrains', + maintainer_email = 'info@jetbrains.com', + author = 'JetBrains', + author_email = 'info@jetbrains.com', + description = 'Kotlin/Native Python bridge', + long_description = 'Using Kotlin/Native from Python example', + + # data_files=[("/Library/Python/2.7/site-packages/", ['libserver.dylib'])], + + ext_modules=[ + Extension('kotlin_bridge', + include_dirs = ['./build'], + libraries = ['server'], + library_dirs = ['./build'], + depends = ['server_api.h'], + sources = ['src/main/c/kotlin_bridge.c'] + ) + ] +) + +# On macOS, after install you may want to copy libserver.dylib to Python's extension directory, +# and do something like +# sudo install_name_tool /Library/Python/2.7/site-packages/kotlin_bridge.so -change libserver.dylib @loader_path/libserver.dylib +# This way libserver.dylib could be loaded from extension's directory. \ No newline at end of file diff --git a/kotlin-native/samples/settings.gradle.kts b/kotlin-native/samples/settings.gradle.kts new file mode 100644 index 00000000000..0ef4bc57303 --- /dev/null +++ b/kotlin-native/samples/settings.gradle.kts @@ -0,0 +1,53 @@ +pluginManagement { + repositories { + mavenCentral() + maven("https://dl.bintray.com/kotlin/kotlin-dev") + maven("https://dl.bintray.com/kotlin/kotlin-eap") + } +} + +enableFeaturePreview("GRADLE_METADATA") + +val hostOs = System.getProperty("os.name") +val isMacos = hostOs == "Mac OS X" +val isLinux = hostOs == "Linux" +val isWindows = hostOs.startsWith("Windows") + +/* + * The following projects are only available for certain platforms. + * + * IMPORTANT: If a new sample doesn't include interop with third-party libraries, + * add it into the 'buildSamplesWithPlatfromLibs' task in the root build.gradle. + */ +if (isMacos || isLinux || isWindows) { + include(":csvparser") + include(":curl") + include(":echoServer") + include(":gitchurn") + include(":globalState") + include(":gtk") + include(":html5Canvas") + include(":libcurl") + include(":tetris") + include(":videoplayer") + include(":workers") + include(":coverage") +} + +if (isMacos || isLinux) { + include(":nonBlockingEchoServer") + include(":tensorflow") + include(":torch") +} + +if (isMacos) { + include(":objc") + include(":opengl") + include(":uikit") + include(":watchos") + include(":simd") +} + +if (isWindows) { + include(":win32") +} diff --git a/kotlin-native/samples/simd/build.gradle.kts b/kotlin-native/samples/simd/build.gradle.kts new file mode 100644 index 00000000000..ba008f6b994 --- /dev/null +++ b/kotlin-native/samples/simd/build.gradle.kts @@ -0,0 +1,11 @@ +plugins { + kotlin("multiplatform") +} + +kotlin { + macosX64 { + binaries { + executable() + } + } +} \ No newline at end of file diff --git a/kotlin-native/samples/simd/src/macosX64Main/kotlin/simd.kt b/kotlin-native/samples/simd/src/macosX64Main/kotlin/simd.kt new file mode 100644 index 00000000000..99d63bb55dd --- /dev/null +++ b/kotlin-native/samples/simd/src/macosX64Main/kotlin/simd.kt @@ -0,0 +1,54 @@ +import platform.Accelerate.* + +// Custom print +fun Vector128.toStringHex(): String { + return "0x" + (0 until 16).map { getUByteAt(it).toString(16) }.joinToString("") +} + +// Custom print +fun Vector128.toStringFloat(): String { + return "(${(0 until 4).map { getFloatAt(it).toString() }.joinToString(", ")})" +} + + +fun main() { + + // Accessors + val vf4 = vectorOf(1f, 3.162f, 10f, 31f) + println(vf4) + println(vf4.toStringFloat()) + println(vf4.toStringHex()) + println(vf4.getFloatAt(1)) + println(vf4.getIntAt(0)) + println(vf4.getByteAt(3)) + // Illegal access (out of bounds) + try { + println(vf4.getIntAt(4)) + println("FAILED") + } catch (e: IndexOutOfBoundsException) { + println("Handling $e") + } + + // Assignment and equality + var x1 = vectorOf(-1f, 0f, 0f, -7f) + val y1 = vectorOf(-1f, 0f, 0f, -7f) + var x2 = vectorOf(1f, 4f, 3f, 7f) + println("(x1 == y1) is ${(x1 == y1)}") + println("(x1.equals(y1)) is ${(x1.equals(y1))}") + println("(x1 == x2) is ${(x1 == x2)}") + x1 = x2 + println("Now (x1 == x1) is ${(x1 == x1)}") + + + // Using library function (MacOS Accelerate framework) + val sum = vS128Add(vectorOf(1,2,3,4), vectorOf(4,3,2,1)) + println(sum) + // More Accelerate framework + val q = vectorOf(1f, 9f, 25f, 49f) + val sq = vsqrtf(q) + println("vsqrtf$q = ${sq.toStringFloat()}") + val f4 = vectorOf(1f, 3.162f, 10f, 31f) + println("vlog10f($f4) = ${vlog10f(vf4).toStringFloat()}") + + +} diff --git a/kotlin-native/samples/tensorflow/README.md b/kotlin-native/samples/tensorflow/README.md new file mode 100644 index 00000000000..ae394fddf2d --- /dev/null +++ b/kotlin-native/samples/tensorflow/README.md @@ -0,0 +1,30 @@ +# TensorFlow demo + +Small Hello World calculation on the [TensorFlow](https://www.tensorflow.org/) backend, +arranging simple operations into a graph and running it on a session. +Like other [TensorFlow clients](https://www.tensorflow.org/extend/language_bindings) +(e. g. for [Python](https://github.com/tensorflow/tensorflow/tree/master/tensorflow/python/client)), +this example is built on top of the +[TensorFlow C API](https://github.com/tensorflow/tensorflow/blob/r1.1/tensorflow/c/c_api.h), +showing how a TensorFlow client in Kotlin/Native could look like. + +## Installation + + ./downloadTensorflow.sh + +will install [TensorFlow for C](https://www.tensorflow.org/versions/r1.1/install/install_c) into +`$HOME/.konan/third-party/tensorflow` (if not yet done). One may override the location of +`third-party/tensorflow` by setting the `KONAN_DATA_DIR` environment variable. + +To build use `../gradlew assemble`. + +Then run + + ../gradlew runReleaseExecutableTensorflow + +Alternatively you can run the artifact directly through + + ./build/bin/tensorflow/main/release/executable/tensorflow.kexe + +You may need to specify `LD_LIBRARY_PATH` or `DYLD_LIBRARY_PATH` to `$HOME/.konan/third-party/tensorflow/lib` +if the TensorFlow dynamic library cannot be found. diff --git a/kotlin-native/samples/tensorflow/build.gradle.kts b/kotlin-native/samples/tensorflow/build.gradle.kts new file mode 100644 index 00000000000..36e679dad28 --- /dev/null +++ b/kotlin-native/samples/tensorflow/build.gradle.kts @@ -0,0 +1,49 @@ +import org.jetbrains.kotlin.gradle.plugin.mpp.KotlinNativeTarget + +plugins { + kotlin("multiplatform") +} + +val kotlinNativeDataPath = System.getenv("KONAN_DATA_DIR")?.let { File(it) } + ?: File(System.getProperty("user.home")).resolve(".konan") + +val tensorflowHome = kotlinNativeDataPath.resolve("third-party/tensorflow") + +kotlin { + // Determine host preset. + val hostOs = System.getProperty("os.name") + + // Create target for the host platform. + val hostTarget = when { + hostOs == "Mac OS X" -> macosX64("tensorflow") + hostOs == "Linux" -> linuxX64("tensorflow") + // Windows is not supported + else -> throw GradleException("Host OS '$hostOs' is not supported in Kotlin/Native $project.") + } + + hostTarget.apply { + binaries { + executable { + entryPoint = "sample.tensorflow.main" + linkerOpts("-L${tensorflowHome.resolve("lib")}", "-ltensorflow") + runTask?.environment( + "LD_LIBRARY_PATH" to tensorflowHome.resolve("lib"), + "DYLD_LIBRARY_PATH" to tensorflowHome.resolve("lib") + ) + } + } + compilations["main"].cinterops { + val tensorflow by creating { + includeDirs(tensorflowHome.resolve("include")) + } + } + } +} + +val downloadTensorflow by tasks.creating(Exec::class) { + workingDir = projectDir + commandLine("./downloadTensorflow.sh") +} + +val tensorflow: KotlinNativeTarget by kotlin.targets +tasks[tensorflow.compilations["main"].cinterops["tensorflow"].interopProcessingTaskName].dependsOn(downloadTensorflow) diff --git a/kotlin-native/samples/tensorflow/downloadTensorflow.sh b/kotlin-native/samples/tensorflow/downloadTensorflow.sh new file mode 100755 index 00000000000..5cbda81759b --- /dev/null +++ b/kotlin-native/samples/tensorflow/downloadTensorflow.sh @@ -0,0 +1,19 @@ +#!/usr/bin/env bash + +KONAN_USER_DIR=${KONAN_DATA_DIR:-"$HOME/.konan"} +TF_TARGET_DIRECTORY="$KONAN_USER_DIR/third-party/tensorflow" +TF_TYPE="cpu" # Change to "gpu" for GPU support + +if [ x$TARGET == x ]; then +case "$OSTYPE" in + darwin*) TARGET=macbook; TF_TARGET=darwin ;; + linux*) TARGET=linux; TF_TARGET=linux ;; + *) echo "unknown: $OSTYPE" && exit 1;; +esac +fi + +if [ ! -d $TF_TARGET_DIRECTORY/include/tensorflow ]; then + echo "Installing TensorFlow into $TF_TARGET_DIRECTORY ..." + mkdir -p $TF_TARGET_DIRECTORY + curl -s -L "https://storage.googleapis.com/tensorflow/libtensorflow/libtensorflow-${TF_TYPE}-${TF_TARGET}-x86_64-1.1.0.tar.gz" | tar -C $TF_TARGET_DIRECTORY -xz +fi diff --git a/kotlin-native/samples/tensorflow/gradle.properties b/kotlin-native/samples/tensorflow/gradle.properties new file mode 100644 index 00000000000..790a07d5124 --- /dev/null +++ b/kotlin-native/samples/tensorflow/gradle.properties @@ -0,0 +1,2 @@ +kotlin.code.style=official +kotlin.import.noCommonSourceSets=true diff --git a/kotlin-native/samples/tensorflow/src/nativeInterop/cinterop/tensorflow.def b/kotlin-native/samples/tensorflow/src/nativeInterop/cinterop/tensorflow.def new file mode 100644 index 00000000000..2f0566fd401 --- /dev/null +++ b/kotlin-native/samples/tensorflow/src/nativeInterop/cinterop/tensorflow.def @@ -0,0 +1 @@ +headers = tensorflow/c/c_api.h diff --git a/kotlin-native/samples/tensorflow/src/tensorflowMain/kotlin/HelloTensorflow.kt b/kotlin-native/samples/tensorflow/src/tensorflowMain/kotlin/HelloTensorflow.kt new file mode 100644 index 00000000000..04adda9bc89 --- /dev/null +++ b/kotlin-native/samples/tensorflow/src/tensorflowMain/kotlin/HelloTensorflow.kt @@ -0,0 +1,236 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the license/LICENSE.txt file. + */ + +package sample.tensorflow + +import kotlinx.cinterop.* +import platform.posix.size_t +import tensorflow.* + +typealias Status = CPointer +typealias Operation = CPointer +typealias Tensor = CPointer + +val Status.isOk: Boolean get() = TF_GetCode(this) == TF_OK +val Status.errorMessage: String get() = TF_Message(this)!!.toKString() +fun Status.delete() = TF_DeleteStatus(this) +fun Status.validate() { + try { + if (!isOk) { + throw Error("Status is not ok: $errorMessage") + } + } finally { + delete() + } +} + +inline fun statusValidated(block: (Status) -> T): T { + val status = TF_NewStatus()!! + val result = block(status) + status.validate() + return result +} + +fun scalarTensor(value: Int): Tensor { + val data = nativeHeap.allocArray(1) + data[0] = value + + return TF_NewTensor(TF_INT32, + dims = null, num_dims = 0, + data = data, len = IntVar.size.convert(), + deallocator = staticCFunction { dataToFree, _, _ -> nativeHeap.free(dataToFree!!.reinterpret()) }, + deallocator_arg = null)!! +} + +val Tensor.scalarIntValue: Int get() { + if (TF_INT32 != TF_TensorType(this) || IntVar.size.convert() != TF_TensorByteSize(this)) { + throw Error("Tensor is not of type int.") + } + if (0 != TF_NumDims(this)) { + throw Error("Tensor is not scalar.") + } + + return TF_TensorData(this)!!.reinterpret().pointed.value +} + + +class Graph { + val tensorflowGraph = TF_NewGraph()!! + + inline fun operation(type: String, name: String, initDescription: (CPointer) -> Unit): Operation { + val description = TF_NewOperation(tensorflowGraph, type, name)!! + initDescription(description) + return statusValidated { TF_FinishOperation(description, it)!! } + } + + fun constant(value: Int, name: String = "scalarIntConstant") = operation("Const", name) { description -> + statusValidated { TF_SetAttrTensor(description, "value", scalarTensor(value), it) } + TF_SetAttrType(description, "dtype", TF_INT32) + } + + fun intInput(name: String = "input") = operation("Placeholder", name) { description -> + TF_SetAttrType(description, "dtype", TF_INT32) + } + + fun add(left: Operation, right: Operation, name: String = "add") = memScoped { + val inputs = allocArray(2) + inputs[0].apply { oper = left; index = 0 } + inputs[1].apply { oper = right; index = 0 } + + operation("AddN", name) { description -> + TF_AddInputList(description, inputs, 2) + } + } + + // TODO set unique operation names + operator fun Operation.plus(right: Operation) = add(this, right) + + inline fun withSession(block: Session.() -> T): T { + val session = Session(this) + try { + return session.block() + } finally { + session.dispose() + } + } +} + +class Session(val graph: Graph) { + private val inputs = mutableListOf() + private val inputValues = mutableListOf() + private var outputs = mutableListOf() + private val outputValues = mutableListOf() + private val targets = listOf() + + private fun createNewSession(): CPointer { + val options = TF_NewSessionOptions() + val session = statusValidated { TF_NewSession(graph.tensorflowGraph, options, it)!! } + TF_DeleteSessionOptions(options) + return session + } + + private var tensorflowSession: CPointer? = createNewSession() + + private fun clearInputValues() { + for (inputValue in inputValues) { + TF_DeleteTensor(inputValue) + } + + inputValues.clear() + } + + private fun clearOutputValues() { + for (outputValue in outputValues) { + if (outputValue != null) + TF_DeleteTensor(outputValue) + } + outputValues.clear() + } + + fun dispose() { + clearInputValues() + clearOutputValues() + clearInputs() + clearOutputs() + + if (tensorflowSession != null) { + statusValidated { TF_CloseSession(tensorflowSession, it) } + statusValidated { TF_DeleteSession(tensorflowSession, it) } + tensorflowSession = null + } + } + + private fun setInputsWithValues(inputsWithValues: List>) { + clearInputValues() + clearInputs() + for ((input, inputValue) in inputsWithValues) { + this.inputs.add(nativeHeap.alloc().apply { oper = input; index = 0 }) + inputValues.add(inputValue) + } + } + + private fun setOutputs(outputs: List) { + clearOutputValues() + clearOutputs() + this.outputs = outputs.map { nativeHeap.alloc().apply { oper = it; index = 0 } }.toMutableList() + } + + private fun clearOutputs() { + this.outputs.forEach { nativeHeap.free(it) } + this.outputs.clear() + } + + private fun clearInputs() { + this.inputs.forEach { nativeHeap.free(it) } + this.inputs.clear() + } + + operator fun invoke(outputs: List, inputsWithValues: List> = listOf()): List { + setInputsWithValues(inputsWithValues) + setOutputs(outputs) + + return invoke() + } + + operator fun invoke(output: Operation, inputsWithValues: List> = listOf()) = + invoke(listOf(output), inputsWithValues).single()!! + + operator fun invoke(): List { + if (inputs.size != inputValues.size) { + throw Error("Call SetInputs() before Run()") + } + clearOutputValues() + + val inputsCArray = if (inputs.any()) nativeHeap.allocArray(inputs.size) else null + + inputs.forEachIndexed { i, input -> + inputsCArray!![i].apply { + oper = input.oper + index = input.index + } + } + + val outputsCArray = if (outputs.any()) nativeHeap.allocArray(outputs.size) else null + + outputs.forEachIndexed { i, output -> + outputsCArray!![i].apply { + oper = output.oper + index = output.index + } + } + + memScoped { + val outputValuesCArray = allocArrayOfPointersTo(outputs.map { null }) + + statusValidated { + TF_SessionRun(tensorflowSession, null, + inputsCArray, inputValues.toCValues(), inputs.size, + outputsCArray, outputValuesCArray, outputs.size, + targets.toCValues(), targets.size, + null, it) + } + + for (index in outputs.indices) { + outputValues.add(outputValuesCArray[index]) + } + } + + clearInputValues() + + return outputValues + } +} + +fun main() { + println("Hello, TensorFlow ${TF_Version()!!.toKString()}!") + + val result = Graph().run { + val input = intInput() + + withSession { invoke(input + constant(2), inputsWithValues = listOf(input to scalarTensor(3))).scalarIntValue } + } + + println("3 + 2 is $result.") +} \ No newline at end of file diff --git a/kotlin-native/samples/tetris/README.md b/kotlin-native/samples/tetris/README.md new file mode 100644 index 00000000000..ca961c9f74e --- /dev/null +++ b/kotlin-native/samples/tetris/README.md @@ -0,0 +1,32 @@ +# Tetris game + +This example shows implementation of simple Tetris game using SDL +(Simple DirectMedia Layer) library for rendering. SDL allows easy development +of cross-platform game and multimedia applications. + +Install SDL2 development files (see https://www.libsdl.org/download-2.0.php). For Mac - +copy `SDL2.framework` to `$HOME/Library/Frameworks`. For Debian-like Linux - +use `apt-get install libsdl2-dev`. +For Windows - `pacman -S mingw-w64-x86_64-SDL2 mingw-w64-i686-SDL2` in MSYS2 console. If you do not have MSYS2 +installed - install it first as described in http://www.msys2.org + +To build Tetris application for your host platform use `../gradlew assemble`. + +Note that SDL2 must be installed on the host. + +Now you can run the game using `../gradlew runReleaseExecutableTetris` or directly with + + ./build/bin/tetris/main/release/executable/tetris.kexe + +During build process compilation script creates interoperability bindings to SDL2, using SDL C headers, +and then compiles an application with the produced bindings. + +To deploy executable to iPhone device take Info.plist, then use XCode and your own private signing identity. + +To run on Raspberry Pi one need to install SDL package with `apt-get install libsdl2-2.0.0` on the Pi. +Also GLES2 renderer is recommended (use `SDL_RENDER_DRIVER=opengles2 ./Tetris.kexe`). + +For Windows `set SDL_RENDER_DRIVER=software` may be needed on some machines. + +Note: There is a known issue with SDL2 library on Mac OS X 10.14 Mojave. Window may render black until +it is dragged. See https://bugzilla.libsdl.org/show_bug.cgi?id=4272 diff --git a/kotlin-native/samples/tetris/build.gradle.kts b/kotlin-native/samples/tetris/build.gradle.kts new file mode 100644 index 00000000000..f64040931c1 --- /dev/null +++ b/kotlin-native/samples/tetris/build.gradle.kts @@ -0,0 +1,122 @@ +import org.jetbrains.kotlin.gradle.plugin.mpp.KotlinNativeTarget + +plugins { + kotlin("multiplatform") +} + +val kotlinNativeDataPath = System.getenv("KONAN_DATA_DIR")?.let { File(it) } + ?: File(System.getProperty("user.home")).resolve(".konan") +val mingw64Path = File(System.getenv("MINGW64_DIR") ?: "C:/msys64/mingw64") +val mingw32Path = File(System.getenv("MINGW32_DIR") ?: "C:/msys64/mingw32") + +kotlin { + val hostOs = System.getProperty("os.name") + if (hostOs == "Mac OS X") { + macosX64() + } + if (hostOs == "Linux") { + linuxX64() + } + if (hostOs.startsWith("Windows")) { + mingwX64() + mingwX86() + } + linuxArm32Hfp() + + targets.withType { + sourceSets["${targetName}Main"].apply { + kotlin.srcDir("src/tetrisMain/kotlin") + } + + binaries { + executable { + entryPoint = "sample.tetris.main" + + // Compile Windows Resources + if (preset == presets["mingwX64"] || preset == presets["mingwX86"]) { + val taskName = linkTaskName.replaceFirst("link", "windres") + val inFile = File("src/tetrisMain/resources/Tetris.rc") + val outFile = buildDir.resolve("processedResources/$taskName.res") + val windresTask = tasks.register(taskName) { + val llvmDir = when (preset) { + presets["mingwX86"] -> kotlinNativeDataPath.resolve( + "dependencies/msys2-mingw-w64-i686-clang-llvm-lld-compiler_rt-8.0.1/bin") + presets["mingwX64"] -> kotlinNativeDataPath.resolve( + "dependencies/msys2-mingw-w64-x86_64-clang-llvm-lld-compiler_rt-8.0.1/bin") + else -> throw GradleException("Unsupported presets") + }.toString() + inputs.file(inFile) + outputs.file(outFile) + commandLine("$llvmDir/windres", inFile, "-O", "coff", "-o", outFile) + environment("PATH", "$llvmDir;${System.getenv("PATH")}") + dependsOn(compilation.compileKotlinTask) + } + linkTask.dependsOn(windresTask) + linkerOpts(outFile.toString()) + } + + when (preset) { + presets["macosX64"] -> linkerOpts("-L/opt/local/lib", "-L/usr/local/lib", "-lSDL2") + presets["linuxX64"] -> linkerOpts("-L/usr/lib64", "-L/usr/lib/x86_64-linux-gnu", "-lSDL2") + presets["mingwX64"] -> linkerOpts( + "-L${mingw64Path.resolve("lib")}", + "-Wl,-Bstatic", + "-lstdc++", + "-static", + "-lSDL2", + "-limm32", + "-lole32", + "-loleaut32", + "-lversion", + "-lwinmm", + "-lsetupapi", + "-mwindows" + ) + presets["mingwX86"] -> linkerOpts( + "-L${mingw32Path.resolve("lib")}", + "-Wl,-Bstatic", + "-lstdc++", + "-static", + "-lSDL2", + "-limm32", + "-lole32", + "-loleaut32", + "-lversion", + "-lwinmm", + "-lsetupapi", + "-mwindows" + ) + presets["linuxArm32Hfp"] -> linkerOpts("-lSDL2") + } + + val distTaskName = linkTaskName.replaceFirst("link", "dist") + val distTask = tasks.register(distTaskName) { + from("src/tetrisMain/resources") + into(linkTask.outputFile.get().parentFile) + exclude("*.rc") + if (!konanTarget.family.isAppleFamily) { + exclude("*.plist") + } + dependsOn(linkTask) + } + tasks["assemble"].dependsOn(distTask) + + runTask?.workingDir(project.provider { outputDirectory }) + } + } + + compilations["main"].cinterops { + val sdl by creating { + when (preset) { + presets["macosX64"] -> includeDirs("/opt/local/include/SDL2", "/usr/local/include/SDL2") + presets["linuxX64"] -> includeDirs("/usr/include/SDL2") + presets["mingwX64"] -> includeDirs(mingw64Path.resolve("include/SDL2")) + presets["mingwX86"] -> includeDirs(mingw32Path.resolve("include/SDL2")) + presets["linuxArm32Hfp"] -> includeDirs(kotlinNativeDataPath.resolve("dependencies/target-sysroot-2-raspberrypi/usr/include/SDL2")) + } + } + } + + compilations["main"].enableEndorsedLibs = true + } +} diff --git a/kotlin-native/samples/tetris/gradle.properties b/kotlin-native/samples/tetris/gradle.properties new file mode 100644 index 00000000000..790a07d5124 --- /dev/null +++ b/kotlin-native/samples/tetris/gradle.properties @@ -0,0 +1,2 @@ +kotlin.code.style=official +kotlin.import.noCommonSourceSets=true diff --git a/kotlin-native/samples/tetris/src/nativeInterop/cinterop/sdl.def b/kotlin-native/samples/tetris/src/nativeInterop/cinterop/sdl.def new file mode 100644 index 00000000000..10463bab759 --- /dev/null +++ b/kotlin-native/samples/tetris/src/nativeInterop/cinterop/sdl.def @@ -0,0 +1,9 @@ +headers = SDL.h stdlib.h time.h +entryPoint = SDL_main + +headerFilter = SDL* stdlib.h time.h + +compilerOpts = -D_POSIX_SOURCE +compilerOpts.osx = +compilerOpts.linux = -D_REENTRANT +compilerOpts.ios = diff --git a/kotlin-native/samples/tetris/src/tetrisMain/kotlin/Config.kt b/kotlin-native/samples/tetris/src/tetrisMain/kotlin/Config.kt new file mode 100644 index 00000000000..6e4f9f59ff4 --- /dev/null +++ b/kotlin-native/samples/tetris/src/tetrisMain/kotlin/Config.kt @@ -0,0 +1,42 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the license/LICENSE.txt file. + */ + +package sample.tetris + +import platform.posix.* +import kotlinx.cinterop.* + +object Config { + var width: Int = 10 + private set + var height: Int = 20 + private set + var startLevel = 0 + private set + + init { + val file = fopen("config.txt", "r") + if (file != null) { + try { + val buffer = ByteArray(2 * 1024) + while (true) { + val nextLine = fgets(buffer.refTo(0), buffer.size, file)?.toKString() + if (nextLine == null || nextLine.isEmpty()) break + val records = nextLine.split('=') + if (records.size != 2) continue + val key = records[0].trim() + val value = records[1].trim() + when (key) { + "width" -> width = value.toInt() + "height" -> height = value.toInt() + "startLevel" -> startLevel = value.toInt() + } + } + } finally { + fclose(file) + } + } + } +} \ No newline at end of file diff --git a/kotlin-native/samples/tetris/src/tetrisMain/kotlin/SDL_Visualizer.kt b/kotlin-native/samples/tetris/src/tetrisMain/kotlin/SDL_Visualizer.kt new file mode 100644 index 00000000000..8d582b531b3 --- /dev/null +++ b/kotlin-native/samples/tetris/src/tetrisMain/kotlin/SDL_Visualizer.kt @@ -0,0 +1,486 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the license/LICENSE.txt file. + */ + +package sample.tetris + +import kotlinx.cinterop.* +import platform.posix.* +import sdl.* + +fun get_SDL_Error() = SDL_GetError()!!.toKString() + +fun sleep(millis: Int) { + SDL_Delay(millis.toUInt()) +} + +class SDL_Visualizer(val width: Int, val height: Int): GameFieldVisualizer, UserInput { + private val CELL_SIZE = 20 + private val COLORS = 10 + private val CELLS_WIDTH = COLORS * CELL_SIZE + private val CELLS_HEIGHT = 3 * CELL_SIZE + private val SYMBOL_SIZE = 21 + private val INFO_MARGIN = 10 + private val MARGIN = 2 + private val BORDER_WIDTH = 18 + private val INFO_SPACE_WIDTH = SYMBOL_SIZE * (2 + 8) + private val LINES_LABEL_WIDTH = 104 + private val SCORE_LABEL_WIDTH = 107 + private val LEVEL_LABEL_WIDTH = 103 + private val NEXT_LABEL_WIDTH = 85 + private val TETRISES_LABEL_WIDTH = 162 + + private var ratio: Float + + private fun stretch(value: Int) = (value.toFloat() * ratio + 0.5).toInt() + + inner class GamePadButtons(width: Int, height: Int, gamePadHeight: Int) { + val MOVE_BUTTON_SIZE = 50 + val ROTATE_BUTTON_SIZE = 80 + val BUTTONS_MARGIN = 25 + + val arena = Arena() + val leftRect: SDL_Rect + val rightRect: SDL_Rect + val downRect: SDL_Rect + val dropRect: SDL_Rect + val rotateRect: SDL_Rect + + init { + val moveButtonsWidth = 3 * MOVE_BUTTON_SIZE + 2 * BUTTONS_MARGIN + BUTTONS_MARGIN + val x = (width - moveButtonsWidth - ROTATE_BUTTON_SIZE) / 2 - MOVE_BUTTON_SIZE + val y2 = (gamePadHeight - 2 * MOVE_BUTTON_SIZE - BUTTONS_MARGIN) / 2 + leftRect = arena.alloc() + leftRect.w = MOVE_BUTTON_SIZE + leftRect.h = MOVE_BUTTON_SIZE + leftRect.x = x + leftRect.y = height - gamePadHeight + y2 + MOVE_BUTTON_SIZE + BUTTONS_MARGIN + + downRect = arena.alloc() + downRect.w = MOVE_BUTTON_SIZE + downRect.h = MOVE_BUTTON_SIZE + downRect.x = x + MOVE_BUTTON_SIZE + BUTTONS_MARGIN + downRect.y = leftRect.y + + dropRect = arena.alloc() + dropRect.w = MOVE_BUTTON_SIZE + dropRect.h = MOVE_BUTTON_SIZE + dropRect.x = downRect.x + dropRect.y = height - gamePadHeight + y2 + + rightRect = arena.alloc() + rightRect.w = MOVE_BUTTON_SIZE + rightRect.h = MOVE_BUTTON_SIZE + rightRect.x = x + 2 * MOVE_BUTTON_SIZE + 2 * BUTTONS_MARGIN + rightRect.y = height - gamePadHeight + y2 + MOVE_BUTTON_SIZE + BUTTONS_MARGIN + + rotateRect = arena.alloc() + rotateRect.w = ROTATE_BUTTON_SIZE + rotateRect.h = ROTATE_BUTTON_SIZE + rotateRect.x = x + moveButtonsWidth + rotateRect.y = height - gamePadHeight + y2 - BUTTONS_MARGIN + } + + fun getCommandAt(x: Int, y: Int): UserCommand? { + return when { + inside(leftRect, x, y) -> UserCommand.LEFT + inside(rightRect, x, y) -> UserCommand.RIGHT + inside(downRect, x, y) -> UserCommand.DOWN + inside(dropRect, x, y) -> UserCommand.DROP + inside(rotateRect, x, y) -> UserCommand.ROTATE + else -> null + } + } + + private fun inside(rect: SDL_Rect, x: Int, y: Int): Boolean { + return x >= stretch(rect.x) && x <= stretch(rect.x + rect.w) + && y >= stretch(rect.y) && y <= stretch(rect.y + rect.h) + } + + fun destroy() { + arena.clear() + } + } + + private val field: Field = Array(height) { ByteArray(width) } + private val nextPieceField: Field = Array(4) { ByteArray(4) } + private var linesCleared: Int = 0 + private var level: Int = 0 + private var score: Int = 0 + private var tetrises: Int = 0 + + private var displayWidth: Int = 0 + private var displayHeight: Int = 0 + private val fieldWidth: Int + private val fieldHeight: Int + private var windowX: Int + private var windowY: Int + private val window: CPointer + private val renderer: CPointer + private val texture: CPointer + private val gamePadButtons: GamePadButtons? + private val platform: String + + init { + if (SDL_Init(SDL_INIT_EVERYTHING) != 0) { + throw Error("SDL_Init Error: ${get_SDL_Error()}") + } + + platform = SDL_GetPlatform()!!.toKString() + + memScoped { + val displayMode = alloc() + if (SDL_GetCurrentDisplayMode(0, displayMode.ptr.reinterpret()) != 0) { + println("SDL_GetCurrentDisplayMode Error: ${get_SDL_Error()}") + SDL_Quit() + throw Error() + } + displayWidth = displayMode.w + displayHeight = displayMode.h + } + fieldWidth = width * (CELL_SIZE + MARGIN) + MARGIN + BORDER_WIDTH * 2 + fieldHeight = height * (CELL_SIZE + MARGIN) + MARGIN + BORDER_WIDTH * 2 + var windowWidth = fieldWidth + INFO_SPACE_WIDTH + var windowHeight: Int + if (platform == "iOS") { + val gamePadHeight = (displayHeight * windowWidth - fieldHeight * displayWidth) / displayWidth + windowHeight = fieldHeight + gamePadHeight + gamePadButtons = GamePadButtons(windowWidth, windowHeight, gamePadHeight) + windowX = 0 + windowY = 0 + ratio = displayHeight.toFloat() / windowHeight + windowWidth = displayWidth + windowHeight = displayHeight + } else { + windowHeight = fieldHeight + gamePadButtons = null + windowX = (displayWidth - windowWidth) / 2 + windowY = (displayHeight - windowHeight) / 2 + ratio = 1.0f + } + val window = SDL_CreateWindow("Tetris", windowX, windowY, windowWidth, windowHeight, + SDL_WINDOW_SHOWN or SDL_WINDOW_ALLOW_HIGHDPI) + if (window == null) { + println("SDL_CreateWindow Error: ${get_SDL_Error()}") + SDL_Quit() + throw Error() + } + this.window = window + + val renderer = SDL_CreateRenderer(window, -1, SDL_RENDERER_ACCELERATED or SDL_RENDERER_PRESENTVSYNC) + if (renderer == null) { + SDL_DestroyWindow(window) + println("SDL_CreateRenderer Error: ${get_SDL_Error()}") + SDL_Quit() + throw Error() + } + this.renderer = renderer + + memScoped { + val realWidth = alloc() + val realHeight = alloc() + SDL_GetRendererOutputSize(renderer, realWidth.ptr, realHeight.ptr) + if (platform != "iOS" && windowHeight != realHeight.value) { + println("DPI differs ${realWidth.value} x ${realHeight.value} vs $windowWidth x $windowHeight") + ratio = realHeight.value.toFloat() / windowHeight + } + } + + texture = loadImage(window, renderer, findFile("tetris_all.bmp")) + } + + private fun findFile(name: String): String { + memScoped { + val dirs = listOf(".", SDL_GetBasePath()?.toKString() ?: "/") + val statBuffer = alloc() + dirs.forEach { + val candidate = "$it/$name" + if (stat(candidate, statBuffer.ptr) == 0) return candidate + } + throw Error("name not found") + } + } + + private fun loadImage(win: CPointer, ren: CPointer, imagePath: String): CPointer { + val bmp = SDL_LoadBMP_RW(SDL_RWFromFile(imagePath, "rb"), 1); + if (bmp == null) { + SDL_DestroyRenderer(ren) + SDL_DestroyWindow(win) + println("SDL_LoadBMP_RW Error: ${get_SDL_Error()}") + SDL_Quit() + throw Error() + } + + val tex = SDL_CreateTextureFromSurface(ren, bmp) + SDL_FreeSurface(bmp) + if (tex == null) { + SDL_DestroyRenderer(ren) + SDL_DestroyWindow(win) + println("SDL_CreateTextureFromSurface Error: ${get_SDL_Error()}") + SDL_Quit() + throw Error() + } + return tex + } + + override fun drawCell(x: Int, y: Int, cell: Byte) { + field[x][y] = cell + } + + override fun drawNextPieceCell(x: Int, y: Int, cell: Byte) { + nextPieceField[x][y] = cell + } + + override fun setInfo(linesCleared: Int, level: Int, score: Int, tetrises: Int) { + this.linesCleared = linesCleared + this.level = level + this.score = score + this.tetrises = tetrises + } + + override fun refresh() { + SDL_RenderClear(renderer) + drawField() + drawInfo() + drawNextPiece() + drawGamePad() + SDL_RenderPresent(renderer) + } + + private fun drawBorder(topLeftX: Int, topLeftY: Int, width: Int, height: Int) { + // Upper-left corner. + var srcX = CELLS_WIDTH + var srcY = 0 + var destX = topLeftX + var destY = topLeftY + copyRect(srcX, srcY, destX, destY, BORDER_WIDTH + MARGIN, BORDER_WIDTH) + + // Upper margin. + srcX += BORDER_WIDTH + MARGIN + destX += BORDER_WIDTH + MARGIN + for (i in 0..width - 1) { + copyRect(srcX, srcY, destX, destY, CELL_SIZE + MARGIN, BORDER_WIDTH) + destX += CELL_SIZE + MARGIN + } + + // Upper-right corner. + srcX += CELL_SIZE + MARGIN + copyRect(srcX, srcY, destX, destY, BORDER_WIDTH, BORDER_WIDTH + MARGIN) + + // Right margin. + srcY += BORDER_WIDTH + MARGIN + destY += BORDER_WIDTH + MARGIN + for (j in 0..height - 1) { + copyRect(srcX, srcY, destX, destY, BORDER_WIDTH, CELL_SIZE + MARGIN) + destY += CELL_SIZE + MARGIN + } + + // Left margin. + srcX = CELLS_WIDTH + srcY = BORDER_WIDTH + destX = topLeftX + destY = topLeftY + BORDER_WIDTH + for (j in 0..height - 1) { + copyRect(srcX, srcY, destX, destY, BORDER_WIDTH, CELL_SIZE + MARGIN) + destY += CELL_SIZE + MARGIN + } + + // Left-down corner. + srcY += CELL_SIZE + MARGIN + copyRect(srcX, srcY, destX, destY, BORDER_WIDTH, BORDER_WIDTH + MARGIN) + + // Down marign. + srcX += BORDER_WIDTH + srcY += MARGIN + destX += BORDER_WIDTH + destY += MARGIN + for (i in 0..width - 1) { + copyRect(srcX, srcY, destX, destY, CELL_SIZE + MARGIN, BORDER_WIDTH) + destX += CELL_SIZE + MARGIN + + } + // Right-down corner. + srcX += CELL_SIZE + MARGIN + copyRect(srcX, srcY, destX, destY, BORDER_WIDTH + MARGIN, BORDER_WIDTH) + } + + private fun drawField() { + drawField(field = field, + topLeftX = 0, + topLeftY = 0, + width = width, + height = height) + } + + private fun drawNextPiece() { + drawInt(labelSrcX = LEVEL_LABEL_WIDTH, + labelSrcY = CELLS_HEIGHT + SYMBOL_SIZE, + labelDestX = fieldWidth + SYMBOL_SIZE, + labelDestY = getInfoY(5), + labelWidth = NEXT_LABEL_WIDTH, + totalDigits = 0, + value = 0) + drawField(field = nextPieceField, + topLeftX = fieldWidth + SYMBOL_SIZE, + topLeftY = getInfoY(6), + width = 4, + height = 4) + } + + private fun drawField(field: Field, topLeftX: Int, topLeftY: Int, width: Int, height: Int) { + drawBorder(topLeftX = topLeftX, + topLeftY = topLeftY, + width = width, + height = height) + for (i in 0..height - 1) + for (j in 0..width - 1) { + val cell = field[i][j].toInt() + if (cell == 0) continue + copyRect(srcX = (level % COLORS) * CELL_SIZE, + srcY = (3 - cell) * CELL_SIZE, + destX = topLeftX + BORDER_WIDTH + MARGIN + j * (CELL_SIZE + MARGIN), + destY = topLeftY + BORDER_WIDTH + MARGIN + i * (CELL_SIZE + MARGIN), + width = CELL_SIZE, + height = CELL_SIZE) + } + } + + private fun drawInfo() { + drawInt(labelSrcX = LINES_LABEL_WIDTH, + labelSrcY = CELLS_HEIGHT, + labelDestX = fieldWidth + SYMBOL_SIZE, + labelDestY = getInfoY(0), + labelWidth = SCORE_LABEL_WIDTH, + totalDigits = 6, + value = score) + drawInt(labelSrcX = 0, + labelSrcY = CELLS_HEIGHT, + labelDestX = fieldWidth + SYMBOL_SIZE, + labelDestY = getInfoY(1), + labelWidth = LINES_LABEL_WIDTH, + totalDigits = 3, + value = linesCleared) + drawInt(labelSrcX = 0, + labelSrcY = CELLS_HEIGHT + SYMBOL_SIZE, + labelDestX = fieldWidth + SYMBOL_SIZE, + labelDestY = getInfoY(2), + labelWidth = LEVEL_LABEL_WIDTH, + totalDigits = 2, + value = level) + drawInt(labelSrcX = 0, + labelSrcY = CELLS_HEIGHT + SYMBOL_SIZE * 2, + labelDestX = fieldWidth + SYMBOL_SIZE, + labelDestY = getInfoY(3), + labelWidth = TETRISES_LABEL_WIDTH, + totalDigits = 2, + value = tetrises) + } + + private fun getInfoY(line: Int): Int { + return SYMBOL_SIZE * (2 * line + 1) + INFO_MARGIN * line + } + + private fun drawInt(labelSrcX: Int, labelSrcY: Int, labelDestX: Int, labelDestY: Int, + labelWidth: Int, totalDigits: Int, value: Int) { + copyRect(srcX = labelSrcX, + srcY = labelSrcY, + destX = labelDestX, + destY = labelDestY, + width = labelWidth, + height = SYMBOL_SIZE) + val digits = IntArray(totalDigits) + var x = value + for (i in 0..totalDigits - 1) { + digits[totalDigits - 1 - i] = x % 10 + x = x / 10 + } + for (i in 0..totalDigits - 1) { + copyRect(srcX = digits[i] * SYMBOL_SIZE, + srcY = CELLS_HEIGHT + 3 * SYMBOL_SIZE, + destX = labelDestX + SYMBOL_SIZE + i * SYMBOL_SIZE, + destY = labelDestY + SYMBOL_SIZE, + width = SYMBOL_SIZE, + height = SYMBOL_SIZE) + } + } + + private fun drawGamePad() { + if (gamePadButtons == null) return + SDL_SetRenderDrawColor(renderer, 127, 127, 127, SDL_ALPHA_OPAQUE.toUByte()) + fillRect(gamePadButtons.leftRect) + fillRect(gamePadButtons.downRect) + fillRect(gamePadButtons.dropRect) + fillRect(gamePadButtons.rightRect) + fillRect(gamePadButtons.rotateRect) + SDL_SetRenderDrawColor(renderer, 0, 0, 0, SDL_ALPHA_OPAQUE.toUByte()) + } + + private fun fillRect(rect: SDL_Rect) { + memScoped { + val stretchedRect = alloc() + stretchedRect.w = stretch(rect.w) + stretchedRect.h = stretch(rect.h) + stretchedRect.x = stretch(rect.x) + stretchedRect.y = stretch(rect.y) + SDL_RenderFillRect(renderer, stretchedRect.ptr.reinterpret()) + } + } + + private fun copyRect(srcX: Int, srcY: Int, destX: Int, destY: Int, width: Int, height: Int) { + memScoped { + val srcRect = alloc() + val destRect = alloc() + srcRect.w = width + srcRect.h = height + srcRect.x = srcX + srcRect.y = srcY + destRect.w = stretch(width) + destRect.h = stretch(height) + destRect.x = stretch(destX) + destRect.y = stretch(destY) + SDL_RenderCopy(renderer, texture, srcRect.ptr.reinterpret(), destRect.ptr.reinterpret()) + } + } + + override fun readCommands(): List { + val commands = mutableListOf() + memScoped { + val event = alloc() + while (SDL_PollEvent(event.ptr.reinterpret()) != 0) { + val eventType = event.type + when (eventType) { + SDL_QUIT -> commands.add(UserCommand.EXIT) + SDL_KEYDOWN -> { + val keyboardEvent = event.ptr.reinterpret().pointed + when (keyboardEvent.keysym.scancode) { + SDL_SCANCODE_LEFT -> commands.add(UserCommand.LEFT) + SDL_SCANCODE_RIGHT -> commands.add(UserCommand.RIGHT) + SDL_SCANCODE_DOWN -> commands.add(UserCommand.DOWN) + SDL_SCANCODE_Z, SDL_SCANCODE_SPACE -> commands.add(UserCommand.ROTATE) + SDL_SCANCODE_UP -> commands.add(UserCommand.DROP) + SDL_SCANCODE_ESCAPE -> commands.add(UserCommand.EXIT) + } + } + SDL_MOUSEBUTTONDOWN -> if (gamePadButtons != null) { + val mouseEvent = event.ptr.reinterpret().pointed + val x = mouseEvent.x + val y = mouseEvent.y + val command = gamePadButtons.getCommandAt(x, y) + if (command != null) + commands.add(command) + } + } + } + } + return commands + } + + fun destroy() { + SDL_DestroyTexture(texture) + SDL_DestroyRenderer(renderer) + SDL_DestroyWindow(window) + SDL_Quit() + gamePadButtons?.destroy() + } +} diff --git a/kotlin-native/samples/tetris/src/tetrisMain/kotlin/Tetris.kt b/kotlin-native/samples/tetris/src/tetrisMain/kotlin/Tetris.kt new file mode 100644 index 00000000000..0e26af76f4b --- /dev/null +++ b/kotlin-native/samples/tetris/src/tetrisMain/kotlin/Tetris.kt @@ -0,0 +1,491 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the license/LICENSE.txt file. + */ + +package sample.tetris + +import kotlinx.cinterop.* +import platform.posix.* + +typealias Field = Array + +enum class Move { + LEFT, + RIGHT, + DOWN, + ROTATE +} + +enum class PlacementResult(val linesCleared: Int = 0, val bonus: Int = 0) { + NOTHING, + GAMEOVER, + // For values of bonuses see https://tetris.wiki/Scoring + SINGLE(1, 40), + DOUBLE(2, 100), + TRIPLE(3, 300), + TETRIS(4, 1200) +} + +const val EMPTY: Byte = 0 +const val CELL1: Byte = 1 +const val CELL2: Byte = 2 +const val CELL3: Byte = 3 +const val BRICK: Byte = -1 + +class Point(var x: Int, var y: Int) + +operator fun Point.plus(other: Point): Point { + return Point(x + other.x, y + other.y) +} + +class PiecePosition(piece: Piece, private val origin: Point) { + private var p = piece.origin + val x get() = p.x + origin.x + val y get() = p.y + origin.y + + var state: Int get private set + val numberOfStates = piece.numberOfStates + + init { + state = 0 + } + + fun makeMove(move: Move) { + when (move) { + Move.LEFT -> --p.y + Move.RIGHT -> ++p.y + Move.DOWN -> ++p.x + Move.ROTATE -> state = (state + 1) % numberOfStates + } + } + + fun unMakeMove(move: Move) { + when (move) { + Move.LEFT -> ++p.y + Move.RIGHT -> --p.y + Move.DOWN -> --p.x + Move.ROTATE -> state = (state + numberOfStates - 1) % numberOfStates + } + } +} + +/* + * We use Nintendo Rotation System, right-handed version. + * See https://tetris.wiki/Nintendo_Rotation_System + */ +enum class Piece(private val origin_: Point, private vararg val states: Field) { + T(Point(-1, -2), + arrayOf( + byteArrayOf(EMPTY, EMPTY, EMPTY), + byteArrayOf(CELL1, CELL1, CELL1), + byteArrayOf(EMPTY, CELL1, EMPTY)), + arrayOf( + byteArrayOf(EMPTY, CELL1, EMPTY), + byteArrayOf(CELL1, CELL1, EMPTY), + byteArrayOf(EMPTY, CELL1, EMPTY)), + arrayOf( + byteArrayOf(EMPTY, CELL1, EMPTY), + byteArrayOf(CELL1, CELL1, CELL1), + byteArrayOf(EMPTY, EMPTY, EMPTY)), + arrayOf( + byteArrayOf(EMPTY, CELL1, EMPTY), + byteArrayOf(EMPTY, CELL1, CELL1), + byteArrayOf(EMPTY, CELL1, EMPTY)) + ), + J(Point(-1, -2), + arrayOf( + byteArrayOf(EMPTY, EMPTY, EMPTY), + byteArrayOf(CELL2, CELL2, CELL2), + byteArrayOf(EMPTY, EMPTY, CELL2)), + arrayOf( + byteArrayOf(EMPTY, CELL2, EMPTY), + byteArrayOf(EMPTY, CELL2, EMPTY), + byteArrayOf(CELL2, CELL2, EMPTY)), + arrayOf( + byteArrayOf(CELL2, EMPTY, EMPTY), + byteArrayOf(CELL2, CELL2, CELL2), + byteArrayOf(EMPTY, EMPTY, EMPTY)), + arrayOf( + byteArrayOf(EMPTY, CELL2, CELL2), + byteArrayOf(EMPTY, CELL2, EMPTY), + byteArrayOf(EMPTY, CELL2, EMPTY)) + ), + Z(Point(-1, -2), + arrayOf( + byteArrayOf(EMPTY, EMPTY, EMPTY), + byteArrayOf(CELL3, CELL3, EMPTY), + byteArrayOf(EMPTY, CELL3, CELL3)), + arrayOf( + byteArrayOf(EMPTY, EMPTY, CELL3), + byteArrayOf(EMPTY, CELL3, CELL3), + byteArrayOf(EMPTY, CELL3, EMPTY)) + ), + O(Point(0, -1), + arrayOf( + byteArrayOf(CELL1, CELL1), + byteArrayOf(CELL1, CELL1)) + ), + S(Point(-1, -2), + arrayOf( + byteArrayOf(EMPTY, EMPTY, EMPTY), + byteArrayOf(EMPTY, CELL2, CELL2), + byteArrayOf(CELL2, CELL2, EMPTY)), + arrayOf( + byteArrayOf(EMPTY, CELL2, EMPTY), + byteArrayOf(EMPTY, CELL2, CELL2), + byteArrayOf(EMPTY, EMPTY, CELL2)) + ), + L(Point(-1, -2), + arrayOf( + byteArrayOf(EMPTY, EMPTY, EMPTY), + byteArrayOf(CELL3, CELL3, CELL3), + byteArrayOf(CELL3, EMPTY, EMPTY)), + arrayOf( + byteArrayOf(CELL3, CELL3, EMPTY), + byteArrayOf(EMPTY, CELL3, EMPTY), + byteArrayOf(EMPTY, CELL3, EMPTY)), + arrayOf( + byteArrayOf(EMPTY, EMPTY, CELL3), + byteArrayOf(CELL3, CELL3, CELL3), + byteArrayOf(EMPTY, EMPTY, EMPTY)), + arrayOf( + byteArrayOf(EMPTY, CELL3, EMPTY), + byteArrayOf(EMPTY, CELL3, EMPTY), + byteArrayOf(EMPTY, CELL3, CELL3)) + ), + I(Point(-2, -2), + arrayOf( + byteArrayOf(EMPTY, EMPTY, EMPTY, EMPTY), + byteArrayOf(EMPTY, EMPTY, EMPTY, EMPTY), + byteArrayOf(CELL1, CELL1, CELL1, CELL1), + byteArrayOf(EMPTY, EMPTY, EMPTY, EMPTY)), + arrayOf( + byteArrayOf(EMPTY, EMPTY, CELL1, EMPTY), + byteArrayOf(EMPTY, EMPTY, CELL1, EMPTY), + byteArrayOf(EMPTY, EMPTY, CELL1, EMPTY), + byteArrayOf(EMPTY, EMPTY, CELL1, EMPTY)) + ); + + val origin get() = Point(origin_.x, origin_.y) + val numberOfStates: Int = states.size + + fun canBePlaced(field: Field, position: PiecePosition): Boolean { + val piece = states[position.state] + val x = position.x + val y = position.y + for (i in piece.indices) { + val pieceRow = piece[i] + val boardRow = field[x + i] + for (j in pieceRow.indices) { + if (pieceRow[j] != EMPTY && boardRow[y + j] != EMPTY) + return false + } + } + return true + } + + fun place(field: Field, position: PiecePosition) { + val piece = states[position.state] + val x = position.x + val y = position.y + for (i in piece.indices) { + val pieceRow = piece[i] + for (j in pieceRow.indices) { + if (pieceRow[j] != EMPTY) field[x + i][y + j] = pieceRow[j] + } + } + } + + fun unPlace(field: Field, position: PiecePosition) { + val piece = states[position.state] + val x = position.x + val y = position.y + for (i in piece.indices) { + val pieceRow = piece[i] + for (j in pieceRow.indices) { + if (pieceRow[j] != EMPTY) field[x + i][y + j] = EMPTY + } + } + } +} + +interface GameFieldVisualizer { + fun drawCell(x: Int, y: Int, cell: Byte) + fun drawNextPieceCell(x: Int, y: Int, cell: Byte) + fun setInfo(linesCleared: Int, level: Int, score: Int, tetrises: Int) + fun refresh() +} + +enum class UserCommand { + LEFT, + RIGHT, + DOWN, + DROP, + ROTATE, + EXIT +} + +interface UserInput { + fun readCommands(): List +} + +class GameField(val width: Int, val height: Int, val visualizer: GameFieldVisualizer) { + private val MARGIN = 4 + + private val field: Field + private val origin: Point + private val nextPieceField: Field + + init { + field = Array(height + MARGIN * 2) { ByteArray(width + MARGIN * 2) } + for (i in field.indices) { + val row = field[i] + for (j in row.indices) { + if (i >= (MARGIN + height) // Bottom (field is flipped over). + || (j < MARGIN) // Left + || (j >= MARGIN + width)) // Right + row[j] = BRICK + } + } + // Coordinates are relative to the central axis and top of the field. + origin = Point(MARGIN, MARGIN + (width + 1) / 2) + nextPieceField = Array(4) { ByteArray(4) } + } + + lateinit var currentPiece: Piece + lateinit var nextPiece: Piece + lateinit var currentPosition: PiecePosition + + fun reset() { + for (i in 0..height - 1) + for (j in 0..width - 1) + field[i + MARGIN][j + MARGIN] = 0 + srand(time(null).toUInt()) + nextPiece = getNextPiece(false) + switchCurrentPiece() + } + + private fun randInt() = (rand() and 32767) or ((rand() and 32767) shl 15) + + private fun getNextPiece(denyPrevious: Boolean): Piece { + val pieces = Piece.values() + if (!denyPrevious) + return pieces[randInt() % pieces.size] + while (true) { + val nextPiece = pieces[randInt() % pieces.size] + if (nextPiece != currentPiece) return nextPiece + } + } + + private fun switchCurrentPiece() { + currentPiece = nextPiece + nextPiece = getNextPiece(denyPrevious = true) // Forbid repeating the same piece for better distribution. + currentPosition = PiecePosition(currentPiece, origin) + } + + fun makeMove(move: Move): Boolean { + currentPosition.makeMove(move) + if (currentPiece.canBePlaced(field, currentPosition)) + return true + currentPosition.unMakeMove(move) + return false + } + + /** + * Places current piece at its current location. + */ + fun place(): PlacementResult { + currentPiece.place(field, currentPosition) + val linesCleared = clearLines() + if (isOutOfBorders()) return PlacementResult.GAMEOVER + switchCurrentPiece() + if (!currentPiece.canBePlaced(field, currentPosition)) + return PlacementResult.GAMEOVER + when (linesCleared) { + 1 -> return PlacementResult.SINGLE + 2 -> return PlacementResult.DOUBLE + 3 -> return PlacementResult.TRIPLE + 4 -> return PlacementResult.TETRIS + else -> return PlacementResult.NOTHING + } + } + + private fun clearLines(): Int { + val clearedLines = mutableListOf() + for (i in 0..height - 1) { + val row = field[i + MARGIN] + if ((0..width - 1).all { j -> row[j + MARGIN] != EMPTY }) { + clearedLines.add(i + MARGIN) + (0..width - 1).forEach { j -> row[j + MARGIN] = EMPTY } + } + } + if (clearedLines.size == 0) return 0 + draw(false) + visualizer.refresh() + sleep(500) + for (i in clearedLines) { + for (k in i - 1 downTo 1) + for (j in 0..width - 1) + field[k + 1][j + MARGIN] = field[k][j + MARGIN] + } + draw(false) + visualizer.refresh() + return clearedLines.size + } + + private fun isOutOfBorders(): Boolean { + for (i in 0..MARGIN - 1) + for (j in 0..width - 1) + if (field[i][j + MARGIN] != EMPTY) + return true + return false + } + + fun draw() { + draw(true) + drawNextPiece() + } + + private fun drawNextPiece() { + for (i in 0..3) + for (j in 0..3) + nextPieceField[i][j] = 0 + nextPiece.place(nextPieceField, PiecePosition(nextPiece, Point(1, 2))) + for (i in 0..3) + for (j in 0..3) + visualizer.drawNextPieceCell(i, j, nextPieceField[i][j]) + } + + private fun draw(drawCurrentPiece: Boolean) { + if (drawCurrentPiece) + currentPiece.place(field, currentPosition) + for (i in 0..height - 1) + for (j in 0..width - 1) + visualizer.drawCell(i, j, field[i + MARGIN][j + MARGIN]) + if (drawCurrentPiece) + currentPiece.unPlace(field, currentPosition) + } +} + +class Game(width: Int, height: Int, val visualizer: GameFieldVisualizer, val userInput: UserInput) { + private val field = GameField(width, height, visualizer) + + private var gameOver = true + private var startLevel = 0 + private var leveledUp = false + private var level = 0 + private var linesClearedAtCurrentLevel = 0 + private var linesCleared = 0 + private var tetrises = 0 + private var score = 0 + + /* + * For speed constants and level up thresholds see https://tetris.wiki/Tetris_(NES,_Nintendo) + */ + private val speeds = intArrayOf(48, 43, 38, 33, 28, 23, 18, 13, 8, 6, 5, 5, 5, 4, 4, 4, 3, 3, 3, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2) + private val levelUpThreshold + get() = + if (leveledUp) 10 + else minOf(startLevel * 10 + 10, maxOf(100, startLevel * 10 - 50)) + private val speed get() = if (level < 29) speeds[level] else 1 + + private var ticks = 0 + + fun startNewGame(level: Int) { + gameOver = false + startLevel = level + leveledUp = false + this.level = level + linesClearedAtCurrentLevel = 0 + linesCleared = 0 + tetrises = 0 + score = 0 + ticks = 0 + field.reset() + + visualizer.setInfo(linesCleared, level, score, tetrises) + field.draw() + visualizer.refresh() + + mainLoop() + } + + private fun placePiece() { + val placementResult = field.place() + ticks = 0 + when (placementResult) { + PlacementResult.NOTHING -> return + PlacementResult.GAMEOVER -> { + gameOver = true + return + } + else -> { + linesCleared += placementResult.linesCleared + linesClearedAtCurrentLevel += placementResult.linesCleared + score += placementResult.bonus * (level + 1) + if (placementResult == PlacementResult.TETRIS) + ++tetrises + val levelUpThreshold = levelUpThreshold + if (linesClearedAtCurrentLevel >= levelUpThreshold) { + ++level + linesClearedAtCurrentLevel -= levelUpThreshold + leveledUp = true + } + + visualizer.setInfo(linesCleared, level, score, tetrises) + } + } + } + + /* + * Number of additional gravity shifts before locking a piece landed on the ground. + * This is needed in order to let user to move a piece to the left/right before locking. + */ + private val LOCK_DELAY = 1 + + private fun mainLoop() { + var attemptsToLock = 0 + while (!gameOver) { + sleep(1000 / 60) // Refresh rate - 60 frames per second. + val commands = userInput.readCommands() + for (cmd in commands) { + val success: Boolean + when (cmd) { + UserCommand.EXIT -> return + UserCommand.LEFT -> success = field.makeMove(Move.LEFT) + UserCommand.RIGHT -> success = field.makeMove(Move.RIGHT) + UserCommand.ROTATE -> success = field.makeMove(Move.ROTATE) + UserCommand.DOWN -> { + success = field.makeMove(Move.DOWN) + if (!success) placePiece() + } + UserCommand.DROP -> { + while (field.makeMove(Move.DOWN)) { + } + success = true + placePiece() + } + } + if (success) { + field.draw() + visualizer.refresh() + } + } + ++ticks + if (ticks < speed) continue + if (!field.makeMove(Move.DOWN)) { + if (++attemptsToLock >= LOCK_DELAY) { + placePiece() + attemptsToLock = 0 + } + } + field.draw() + visualizer.refresh() + ticks -= speed + } + } + +} + diff --git a/kotlin-native/samples/tetris/src/tetrisMain/kotlin/main.kt b/kotlin-native/samples/tetris/src/tetrisMain/kotlin/main.kt new file mode 100644 index 00000000000..6548dcb6296 --- /dev/null +++ b/kotlin-native/samples/tetris/src/tetrisMain/kotlin/main.kt @@ -0,0 +1,21 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the license/LICENSE.txt file. + */ + +package sample.tetris + +import kotlinx.cli.* + +fun main(args: Array) { + val argParser = ArgParser("tetris", useDefaultHelpShortName = false) + val level by argParser.option(ArgType.Int, shortName = "l", description = "Game level").default(Config.startLevel) + val width by argParser.option(ArgType.Int, shortName = "w", description = "Width of the game field").default(Config.width) + val height by argParser.option(ArgType.Int, shortName = "h", description = "Height of the game field").default(Config.height) + argParser.parse(args) + val visualizer = SDL_Visualizer(width, height) + val game = Game(width, height, visualizer, visualizer) + game.startNewGame(level) + + return +} \ No newline at end of file diff --git a/kotlin-native/samples/tetris/src/tetrisMain/resources/Info.plist b/kotlin-native/samples/tetris/src/tetrisMain/resources/Info.plist new file mode 100644 index 00000000000..da637bfe644 --- /dev/null +++ b/kotlin-native/samples/tetris/src/tetrisMain/resources/Info.plist @@ -0,0 +1,77 @@ + + + + + BuildMachineOSBuild + 15G1212 + CFBundleDevelopmentRegion + en + CFBundleExecutable + tetris.kexe + CFBundleIdentifier + tetris.kexe + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + tetris.kexe + CFBundlePackageType + APPL + CFBundleShortVersionString + 1.0 + CFBundleSupportedPlatforms + + iPhoneOS + + CFBundleVersion + 1 + DTCompiler + com.apple.compilers.llvm.clang.1_0 + DTPlatformBuild + 14C89 + DTPlatformName + iphoneos + DTPlatformVersion + 10.2 + DTSDKBuild + 14C89 + DTSDKName + iphoneos10.2 + DTXcode + 0821 + DTXcodeBuild + 8C1002 + LSRequiresIPhoneOS + + MinimumOSVersion + 10.2 + UIDeviceFamily + + 1 + + UILaunchStoryboardName + LaunchScreen + UIRequiredDeviceCapabilities + + arm64 + + UIStatusBarHidden + + UISupportedInterfaceOrientations + + UIInterfaceOrientationPortrait + UIInterfaceOrientationLandscapeLeft + UIInterfaceOrientationLandscapeRight + + CFBundleIcons + + CFBundlePrimaryIcon + + CFBundleIconFiles + + Icon-60x2 + Icon-60 + + + + + diff --git a/kotlin-native/samples/tetris/src/tetrisMain/resources/Tetris.rc b/kotlin-native/samples/tetris/src/tetrisMain/resources/Tetris.rc new file mode 100644 index 00000000000..6d1bcf075d3 --- /dev/null +++ b/kotlin-native/samples/tetris/src/tetrisMain/resources/Tetris.rc @@ -0,0 +1,23 @@ +1 VERSIONINFO +FILEVERSION 1,0,0,0 +PRODUCTVERSION 1,0,0,0 +BEGIN + BLOCK "StringFileInfo" + BEGIN + BLOCK "080904E4" + BEGIN + VALUE "CompanyName", "JetBrains LLC" + VALUE "FileDescription", "Tetris Demo Game" + VALUE "FileVersion", "1.0" + VALUE "InternalName", "Tetris" + VALUE "LegalCopyright", "©JetBrains" + VALUE "OriginalFilename", "Tetris.exe" + VALUE "ProductName", "Tetris for Windows" + VALUE "ProductVersion", "1.0" + END + END + BLOCK "VarFileInfo" + BEGIN + VALUE "Translation", 0x809, 1252 + END +END diff --git a/kotlin-native/samples/tetris/src/tetrisMain/resources/config.txt b/kotlin-native/samples/tetris/src/tetrisMain/resources/config.txt new file mode 100644 index 00000000000..da8f7d7d673 --- /dev/null +++ b/kotlin-native/samples/tetris/src/tetrisMain/resources/config.txt @@ -0,0 +1,3 @@ +width = 10 +height = 30 +startLevel = 0 \ No newline at end of file diff --git a/kotlin-native/samples/tetris/src/tetrisMain/resources/tetris_all.bmp b/kotlin-native/samples/tetris/src/tetrisMain/resources/tetris_all.bmp new file mode 100644 index 00000000000..e5c57a6cc4f Binary files /dev/null and b/kotlin-native/samples/tetris/src/tetrisMain/resources/tetris_all.bmp differ diff --git a/kotlin-native/samples/torch/README.md b/kotlin-native/samples/torch/README.md new file mode 100644 index 00000000000..7c0bf73a233 --- /dev/null +++ b/kotlin-native/samples/torch/README.md @@ -0,0 +1,48 @@ +# Torch demo + +Trains a handwritten digit classifier using the [Torch](http://torch.ch) C backend. +Like other Torch clients, most prominently [PyTorch](http://pytorch.org), +this example is built on top of the +[ATen C API](https://github.com/pytorch/pytorch/tree/master/aten), +showing how a Torch client for Kotlin/Native could look like. + +## Installation + +To build [ATen (Torch for C)](https://github.com/pytorch/pytorch/tree/master/aten), +make sure you have Python 2.X and pyyaml installed: + + # macOS: if you don't have pip + sudo easy_install pip + # Linux: if you don't have pip + apt-get -y install python-pip + + # if you don't have pyyaml or typing + sudo pip install pyyaml typing + +Now + + ./downloadTorch.sh + +will install it into `$HOME/.konan/third-party/torch` (if not yet done). One may override the location of +`third-party/torch` by setting the `KONAN_DATA_DIR` environment variable. + +To build use `../gradlew assemble`. + + ./downloadMNIST.sh + +will download and unzip the [MNIST dataset](https://en.wikipedia.org/wiki/MNIST_database) of +[70000 labeled handwritten digits](http://yann.lecun.com/exdb/mnist/) for training and testing a classifier (if not yet done). + +Then run + + ../gradlew runReleaseExecutableTorch + +Alternatively you can run the artifact directly through + + ./build/bin/torch/main/release/executable/torch.kexe + +You may need to specify `LD_LIBRARY_PATH` or `DYLD_LIBRARY_PATH` environment variables +to point to `$HOME/.konan/third-party/torch/lib` if the ATen dynamic library cannot be found. + +Even on a CPU, training should only take some minutes, +and you should observe a classification accuracy of about 95% on the test dataset. diff --git a/kotlin-native/samples/torch/build.gradle.kts b/kotlin-native/samples/torch/build.gradle.kts new file mode 100644 index 00000000000..113a5e6c617 --- /dev/null +++ b/kotlin-native/samples/torch/build.gradle.kts @@ -0,0 +1,62 @@ +import org.jetbrains.kotlin.gradle.plugin.mpp.KotlinNativeTarget +import org.jetbrains.kotlin.gradle.plugin.mpp.NativeBuildType + +plugins { + kotlin("multiplatform") +} + +val kotlinNativeDataPath = System.getenv("KONAN_DATA_DIR")?.let { File(it) } + ?: File(System.getProperty("user.home")).resolve(".konan") + +val torchHome = kotlinNativeDataPath.resolve("third-party/torch") + +kotlin { + // Determine host preset. + val hostOs = System.getProperty("os.name") + + // Create target for the host platform. + val hostTarget = when { + hostOs == "Mac OS X" -> macosX64("torch") + hostOs == "Linux" -> linuxX64("torch") + // Windows is not supported + else -> throw GradleException("Host OS '$hostOs' is not supported in Kotlin/Native $project.") + } + + hostTarget.apply { + binaries { + executable { + entryPoint = "sample.torch.main" + linkerOpts("-L${torchHome.resolve("lib")}", "-lATen") + runTask?.environment( + "LD_LIBRARY_PATH" to torchHome.resolve("lib"), + "DYLD_LIBRARY_PATH" to torchHome.resolve("lib") + ) + } + } + compilations["main"].cinterops { + val torch by creating { + includeDirs( + torchHome.resolve("include"), + torchHome.resolve("include/TH") + ) + } + } + } +} + +val downloadTorch by tasks.creating(Exec::class) { + workingDir = projectDir + commandLine("./downloadTorch.sh") +} + +val torch: KotlinNativeTarget by kotlin.targets +tasks[torch.compilations["main"].cinterops["torch"].interopProcessingTaskName].dependsOn(downloadTorch) + +val downloadMNIST by tasks.creating(Exec::class) { + workingDir = projectDir + commandLine("./downloadMNIST.sh") +} + +NativeBuildType.values() + .mapNotNull { torch.binaries.getExecutable(it).runTask } + .forEach { runTask -> runTask.dependsOn(downloadMNIST) } diff --git a/kotlin-native/samples/torch/downloadMNIST.sh b/kotlin-native/samples/torch/downloadMNIST.sh new file mode 100755 index 00000000000..ea348c32340 --- /dev/null +++ b/kotlin-native/samples/torch/downloadMNIST.sh @@ -0,0 +1,17 @@ +#!/usr/bin/env bash + +# See http://yann.lecun.com/exdb/mnist/ + +MNIST_TARGET_DIRECTORY="`pwd`/build/3rd-party/MNIST" + +echo "Downloading MNIST databases into $MNIST_TARGET_DIRECTORY ..." + +mkdir -p $MNIST_TARGET_DIRECTORY +cd $MNIST_TARGET_DIRECTORY + +wget -nv -N http://yann.lecun.com/exdb/mnist/train-images-idx3-ubyte.gz +wget -nv -N http://yann.lecun.com/exdb/mnist/train-labels-idx1-ubyte.gz +wget -nv -N http://yann.lecun.com/exdb/mnist/t10k-images-idx3-ubyte.gz +wget -nv -N http://yann.lecun.com/exdb/mnist/t10k-labels-idx1-ubyte.gz + +gunzip -fk *.gz diff --git a/kotlin-native/samples/torch/downloadTorch.sh b/kotlin-native/samples/torch/downloadTorch.sh new file mode 100755 index 00000000000..4fa7c03c84a --- /dev/null +++ b/kotlin-native/samples/torch/downloadTorch.sh @@ -0,0 +1,32 @@ +#!/usr/bin/env bash + +KONAN_USER_DIR=${KONAN_DATA_DIR:-"$HOME/.konan"} +TH_TARGET_DIRECTORY="$KONAN_USER_DIR/third-party/torch" +NO_CUDA=true # set to false for GPU support + +if [ ! -d $TH_TARGET_DIRECTORY/include/THNN ]; then + echo "Installing Torch into $TH_TARGET_DIRECTORY ..." + + mkdir -p build/3rd-party + cd build/3rd-party + + git clone https://github.com/pytorch/pytorch.git + # Current pytorch master fails the build so we need to checkout a correct revision. + cd pytorch && git checkout 310c3735b9eb97f30cee743b773e5bb054989edc^ && cd ../ + + mkdir build_torch + cd build_torch + + cmake -DNO_CUDA=$NO_CUDA ../pytorch/aten + make + make DESTDIR=$TH_TARGET_DIRECTORY install + + cd $TH_TARGET_DIRECTORY + + # remove 'usr/local' prefix produced by make: + mv usr/local/* . + rm -d usr/local usr + + # hack to solve "fatal error: 'generic/THNN.h' file not found" when linking, -I$

/include/THNN did not work + cp include/THNN/generic/THNN.h include/TH/generic/THNN.h +fi diff --git a/kotlin-native/samples/torch/gradle.properties b/kotlin-native/samples/torch/gradle.properties new file mode 100644 index 00000000000..790a07d5124 --- /dev/null +++ b/kotlin-native/samples/torch/gradle.properties @@ -0,0 +1,2 @@ +kotlin.code.style=official +kotlin.import.noCommonSourceSets=true diff --git a/kotlin-native/samples/torch/src/nativeInterop/cinterop/torch.def b/kotlin-native/samples/torch/src/nativeInterop/cinterop/torch.def new file mode 100644 index 00000000000..958c948be70 --- /dev/null +++ b/kotlin-native/samples/torch/src/nativeInterop/cinterop/torch.def @@ -0,0 +1 @@ +headers = TH/TH.h THNN/THNN.h diff --git a/kotlin-native/samples/torch/src/torchMain/kotlin/ClassifierDemo.kt b/kotlin-native/samples/torch/src/torchMain/kotlin/ClassifierDemo.kt new file mode 100644 index 00000000000..719deac00b5 --- /dev/null +++ b/kotlin-native/samples/torch/src/torchMain/kotlin/ClassifierDemo.kt @@ -0,0 +1,81 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the license/LICENSE.txt file. + */ + +package sample.torch + +fun Float.toRoundedString(digits: Int = 0): String { + var factor = 1 + + for (i in 0 until digits) { + factor *= 10 + } + + return (kotlin.math.round(this * factor) / factor).toString() +} + +fun Float.toPercentageString(roundToDigits: Int = 1) = (this * 100).toRoundedString(roundToDigits) + +fun List.maxIndex() = withIndex().maxBy { it.value }!!.index + +fun accuracy(predictionBatch: FloatMatrix, labelBatch: FloatMatrix): Float { + val resultIndexes = predictionBatch.toList().map { it.maxIndex() } + val labelBatchIndexes = labelBatch.toList().map { it.maxIndex() } + return resultIndexes.zip(labelBatchIndexes). + count { (result, label) -> result == label }.toFloat() / resultIndexes.size +} + +fun Backpropagatable.trainClassifier( + dataset: Dataset, + lossByLabels: (FloatMatrix) -> Backpropagatable, + learningRateByProgress: (Float) -> Float = { 5f * kotlin.math.exp(-it * 3) }, + batchSize: Int = 64, + iterations: Int = 500) { + + for (i in 0 until iterations) { + disposeScoped { + val (inputBatch, labelBatch) = dataset.sampleBatch(batchSize) + val errorNetwork = this@trainClassifier before lossByLabels(labelBatch) + val forwardResults = use { errorNetwork.forwardPass(inputBatch) } + val accuracy = accuracy(forwardResults.hidden, labelBatch) + val progress = i.toFloat() / iterations + val learningRate = learningRateByProgress(progress) + val backpropResults = use { forwardResults.backpropagate(outputGradient = tensor(learningRate)) } + val crossEntropy = forwardResults.output[0] + backpropResults.descend() + println("Iteration ${i + 1}/$iterations: " + + "${accuracy.toPercentageString()}% training batch accuracy, " + + "cross entropy loss = ${crossEntropy.toRoundedString(4)}, " + + "learning rate = ${learningRate.toRoundedString(4)}") + } + } +} + +fun Backpropagatable.testClassifier(dataset: Dataset, batchSize: Int = 100): Float { + val testBatches = dataset.testBatches(batchSize) + return testBatches.withIndex().map { (i, batchPair) -> + val (inputBatch, outputBatch) = batchPair + val accuracy = accuracy(this.forwardPass(inputBatch).output, outputBatch) + println("Test batch ${i + 1}/${testBatches.size}: ${accuracy.toPercentageString()}% accuracy") + accuracy * inputBatch.shape[0] + }.sum() / dataset.inputs.size +} + +fun randomInit(size: Int) = random(-.01, .01, size) +fun randomInit(size0: Int, size1: Int) = random(-.1, .1, size0, size1) + +fun linear(inputSize: Int, outputSize: Int) = Linear(randomInit(outputSize, inputSize), randomInit(outputSize)) +fun twoLayerClassifier(dataset: Dataset, hiddenSize: Int = 64) = + linear(dataset.inputs[0].size, hiddenSize) before Relu before + linear(hiddenSize, dataset.labels[0].size) before Softmax + +fun main() { + val trainingDataset = MNIST.labeledTrainingImages() + val predictionNetwork = twoLayerClassifier(trainingDataset) + predictionNetwork.trainClassifier(trainingDataset, lossByLabels = { CrossEntropyLoss(labels = it) }) + + val testDataset = MNIST.labeledTestImages() + val averageAccuracy = predictionNetwork.testClassifier(testDataset) + println("Accuracy on the test set: ${averageAccuracy.toPercentageString()}") +} diff --git a/kotlin-native/samples/torch/src/torchMain/kotlin/Dataset.kt b/kotlin-native/samples/torch/src/torchMain/kotlin/Dataset.kt new file mode 100644 index 00000000000..8db12819f85 --- /dev/null +++ b/kotlin-native/samples/torch/src/torchMain/kotlin/Dataset.kt @@ -0,0 +1,104 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the license/LICENSE.txt file. + */ + +package sample.torch + +import kotlinx.cinterop.* +import platform.posix.* + +data class Dataset(val inputs: List, val labels: List) { + fun batch(indices: List): Pair { + val inputBatch = tensor(*(indices.map { inputs[it].toTypedArray() }.toTypedArray())) + val labelBatch = tensor(*(indices.map { labels[it].toTypedArray() }.toTypedArray())) + return inputBatch to labelBatch + } + + fun sampleBatch(batchSize: Int) = batch((0 until batchSize).map { randomInt(inputs.size) }) + private fun batchAt(batchIndex: Int, batchSize: Int) = + batch((0 until inputs.size).drop(batchSize + batchIndex).take(batchSize)) + + fun testBatches(batchSize: Int) = (0 until inputs.size / batchSize).map { batchAt(it, batchSize = batchSize) } +} + +/** + * Provides the MNIST labeled handwritten digit dataset, described at http://yann.lecun.com/exdb/mnist/ + */ +object MNIST { + private fun readFileData(fileName: String) = memScoped { + val path = "build/3rd-party/MNIST/$fileName" + fun fail(): Nothing = throw Error("Cannot read input file $path") + + val size = alloc().also { if (stat(path, it.ptr) != 0) fail() }.st_size.toInt() + + println("Reading $size bytes from $path...") + + val file = fopen(path, "rb") ?: fail() + try { + ByteArray(size).also { fread(it.refTo(0), 1, size.convert(), file) } + } finally { + fclose(file) + } + } + + private fun Byte.reinterpretAsUnsigned() = this.toInt().let { it + if (it < 0) 256 else 0 } + + private fun unsignedBytesToInt(bytes: List) = + bytes.withIndex().map { (i, value) -> value.reinterpretAsUnsigned().shl(8 * (3 - i)) }.sum() + + private val intSize = 4 + private fun ByteArray.getIntAt(index: Int) = + unsignedBytesToInt((index until (index + intSize)).map { this[it] }) + + private val imageLength = 28 + private val imageSize = imageLength * imageLength + + private fun ByteArray.getImageAt(index: Int) = + FloatArray(imageSize) { this[index + it].reinterpretAsUnsigned().toFloat() / 255 } + + private fun oneHot(size: Int, index: Int) = FloatArray(size) { if (it == index) 1f else 0f } + + private fun readLabels(fileName: String, totalLabels: Int = 10): List { + val data = readFileData(fileName) + val check = data.getIntAt(0) + val expectedCheck = 2049 + if (check != 2049) throw Error("File should start with int $expectedCheck, but was $check.") + + val count = data.getIntAt(4) + + val offset = 8 + + if (count + offset != data.size) throw Error("Unexpected file size: ${data.size}.") + + return (0 until count).map { oneHot(totalLabels, index = data[offset + it].reinterpretAsUnsigned()) } + } + + private fun readImages(fileName: String): List { + val data = readFileData(fileName) + val check = data.getIntAt(0) + val expectedCheck = 2051 + if (check != expectedCheck) throw Error("File should start with int $expectedCheck, but was $check.") + + val count = data.getIntAt(4) + val width = data.getIntAt(8) + val height = data.getIntAt(12) + + val offset = 16 + + if (width != imageLength) throw Error() + if (height != imageLength) throw Error() + + if (count * imageSize + offset != data.size) throw Error("Unexpected file size: ${data.size}.") + + return (0 until count).map { data.getImageAt(offset + imageSize * it) } + } + + fun labeledTrainingImages() = Dataset( + inputs = readImages("train-images-idx3-ubyte"), + labels = readLabels("train-labels-idx1-ubyte")) + + fun labeledTestImages() = Dataset( + inputs = readImages("t10k-images-idx3-ubyte"), + labels = readLabels("t10k-labels-idx1-ubyte")) +} \ No newline at end of file diff --git a/kotlin-native/samples/torch/src/torchMain/kotlin/Disposable.kt b/kotlin-native/samples/torch/src/torchMain/kotlin/Disposable.kt new file mode 100644 index 00000000000..2e94e0ed718 --- /dev/null +++ b/kotlin-native/samples/torch/src/torchMain/kotlin/Disposable.kt @@ -0,0 +1,42 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the license/LICENSE.txt file. + */ + +package sample.torch + +/** + * NOTE: resource management in this sample suffers from resource leaks + * and double-free bugs (see workaround in [FloatTensor.dispose]). + * + * This might mean that the entire approach for resource management in the sample is faulty. + * Please take this into account when considering reusing the same approach in your project. + * + * TODO: rework resource management. +*/ +interface Disposable { + fun dispose() +} + +open class DisposableContainer(private val disposables: MutableList = ArrayList()) : Disposable { + /** + * Creates the object and schedules its disposal for the end of the scope. + */ + fun use(create: () -> T) = create().also { disposables.add(it) } + + override fun dispose() { + for (disposable in disposables) { + disposable.dispose() + } + } +} + +fun disposeScoped(action: DisposableContainer.() -> T): T { + val scope = DisposableContainer() + + try { + return scope.action() + } finally { + scope.dispose() + } +} \ No newline at end of file diff --git a/kotlin-native/samples/torch/src/torchMain/kotlin/Modules.kt b/kotlin-native/samples/torch/src/torchMain/kotlin/Modules.kt new file mode 100644 index 00000000000..bc07fa2a47b --- /dev/null +++ b/kotlin-native/samples/torch/src/torchMain/kotlin/Modules.kt @@ -0,0 +1,212 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the license/LICENSE.txt file. + */ + +package sample.torch + +import kotlinx.cinterop.* +import torch.* + +// Defines network modules with the ability for backpropagation using both TH.h and THNN.h from the ATen library + +abstract class Backpropagatable { + abstract inner class ForwardResults(val input: Input) : DisposableContainer() { + init { + use { input } + } + + abstract val output: Output + abstract fun backpropagate(outputGradient: Output): BackpropagationResults + } + + abstract inner class BackpropagationResults( + val input: Input, + val output: Output, + val outputGradient: Output + ) : DisposableContainer() { + init { + use { input } + use { output } + use { outputGradient } + } + + abstract val inputGradient: Input + abstract fun descend() + } + + abstract fun forwardPass(input: Input): ForwardResults +} + +abstract class Module : Backpropagatable() { + abstract var parameters: Parameters + abstract fun parametersToList(parameters: Parameters): List + abstract fun parametersFromList(list: List): Parameters + private val parameterList get() = parametersToList(parameters) + + abstract operator fun invoke(input: Input): Output + abstract fun inputGradient(input: Input, outputGradient: Output, output: Output): Input + abstract fun parameterGradient(input: Input, outputGradient: Output, inputGradient: Input): Parameters + + override fun forwardPass(input: Input) = object : ForwardResults(input) { + override val output = use { this@Module(input) } + override fun backpropagate(outputGradient: Output) = + object : Backpropagatable.BackpropagationResults(input, output, outputGradient) { + override val inputGradient = use { this@Module.inputGradient(input, outputGradient, output) } + val parameterGradient = this@Module.parameterGradient(input, + outputGradient = outputGradient, inputGradient = inputGradient) + + override fun descend() = this@Module.descend(parameterGradient) + } + } + + open fun descend(parameterGradient: Parameters) { + parameters = parametersFromList(parameterList.zip( + parametersToList(parameterGradient)) { parameter, gradient -> parameter - gradient }) + } +} + +abstract class ParameterFreeModule : Module() { + override var parameters = Unit + override fun parametersToList(parameters: Unit) = emptyList() + override fun parametersFromList(list: List) = Unit + override fun parameterGradient(input: Input, outputGradient: Output, inputGradient: Input) = Unit + override fun descend(parameterGradient: Unit) {} +} + +class Chain( + val module1: Backpropagatable